diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/CrashReport.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/CrashReport.java.patch new file mode 100644 index 0000000000..dc7d90482e --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/CrashReport.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/CrashReport.java ++++ b/net/minecraft/CrashReport.java +@@ -33,9 +33,10 @@ + private StackTraceElement[] uncategorizedStackTrace = new StackTraceElement[0]; + private final SystemReport systemReport = new SystemReport(); + +- public CrashReport(String s, Throwable throwable) { +- this.title = s; +- this.exception = throwable; ++ public CrashReport(String title, Throwable exception) { ++ this.title = title; ++ this.exception = exception; ++ this.systemReport.setDetail("CraftBukkit Information", new org.bukkit.craftbukkit.CraftCrashReport()); // CraftBukkit + } + + public String getTitle() { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/advancements/AdvancementHolder.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/advancements/AdvancementHolder.java.patch new file mode 100644 index 0000000000..29bef626ac --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/advancements/AdvancementHolder.java.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/advancements/AdvancementHolder.java ++++ b/net/minecraft/advancements/AdvancementHolder.java +@@ -2,6 +2,10 @@ + + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.resources.ResourceLocation; ++// CraftBukkit start ++import org.bukkit.craftbukkit.advancement.CraftAdvancement; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++// CraftBukkit end + + public record AdvancementHolder(ResourceLocation id, Advancement value) { + +@@ -44,4 +45,10 @@ + public String toString() { + return this.id.toString(); + } ++ ++ // CraftBukkit start ++ public final org.bukkit.advancement.Advancement toBukkit() { ++ return new CraftAdvancement(this); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/advancements/AdvancementTree.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/advancements/AdvancementTree.java.patch new file mode 100644 index 0000000000..a09551dbaa --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/advancements/AdvancementTree.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/advancements/AdvancementTree.java ++++ b/net/minecraft/advancements/AdvancementTree.java +@@ -77,7 +77,7 @@ + } + } + +- AdvancementTree.LOGGER.info("Loaded {} advancements", this.nodes.size()); ++ // AdvancementTree.LOGGER.info("Loaded {} advancements", this.nodes.size()); // CraftBukkit - moved to AdvancementDataWorld#reload + } + + private boolean tryInsert(AdvancementHolder advancementholder) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/CommandSource.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/CommandSource.java.patch new file mode 100644 index 0000000000..8de3d6e279 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/CommandSource.java.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/commands/CommandSource.java ++++ b/net/minecraft/commands/CommandSource.java +@@ -26,6 +22,13 @@ + public boolean shouldInformAdmins() { + return false; + } ++ ++ // CraftBukkit start ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ // CraftBukkit end + }; + + void sendSystemMessage(Component component); +@@ -39,4 +42,6 @@ + default boolean alwaysAccepts() { + return false; + } ++ ++ org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper); // CraftBukkit + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/CommandSourceStack.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/CommandSourceStack.java.patch new file mode 100644 index 0000000000..6427ceeaac --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/CommandSourceStack.java.patch @@ -0,0 +1,68 @@ +--- a/net/minecraft/commands/CommandSourceStack.java ++++ b/net/minecraft/commands/CommandSourceStack.java +@@ -44,6 +43,7 @@ + import net.minecraft.world.level.dimension.DimensionType; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; ++import com.mojang.brigadier.tree.CommandNode; // CraftBukkit + + public class CommandSourceStack implements ExecutionCommandSource, SharedSuggestionProvider { + +@@ -64,6 +64,7 @@ + private final Vec2 rotation; + private final CommandSigningContext signingContext; + private final TaskChainer chatMessageChainer; ++ public volatile CommandNode currentCommand; // CraftBukkit + + public CommandSourceStack(CommandSource commandsource, Vec3 vec3, Vec2 vec2, ServerLevel serverlevel, int i, String s, Component component, MinecraftServer minecraftserver, @Nullable Entity entity) { + this(commandsource, vec3, vec2, serverlevel, i, s, component, minecraftserver, entity, false, CommandResultCallback.EMPTY, EntityAnchorArgument.Anchor.FEET, CommandSigningContext.ANONYMOUS, TaskChainer.immediate(minecraftserver)); +@@ -170,11 +170,24 @@ + } + + @Override +- @Override +- public boolean hasPermission(int i) { +- return this.permissionLevel >= i; ++ public boolean hasPermission(int level) { ++ // CraftBukkit start ++ CommandNode currentCommand = this.currentCommand; ++ if (currentCommand != null) { ++ return hasPermission(level, org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(currentCommand)); ++ } ++ // CraftBukkit end ++ ++ return this.permissionLevel >= level; + } + ++ // CraftBukkit start ++ public boolean hasPermission(int i, String bukkitPermission) { ++ // World is null when loading functions ++ return ((getLevel() == null || !getLevel().getCraftServer().ignoreVanillaPermissions) && this.permissionLevel >= i) || getBukkitSender().hasPermission(bukkitPermission); ++ } ++ // CraftBukkit end ++ + public Vec3 getPosition() { + return this.worldPosition; + } +@@ -307,8 +320,8 @@ + while (iterator.hasNext()) { + ServerPlayer serverplayer = (ServerPlayer) iterator.next(); + +- if (serverplayer != this.source && this.server.getPlayerList().isOp(serverplayer.getGameProfile())) { +- serverplayer.sendSystemMessage(mutablecomponent); ++ if (entityplayer != this.source && entityplayer.getBukkitEntity().hasPermission("minecraft.admin.command_feedback")) { // CraftBukkit ++ entityplayer.sendSystemMessage(ichatmutablecomponent); + } + } + } +@@ -413,4 +413,10 @@ + public boolean isSilent() { + return this.silent; + } ++ ++ // CraftBukkit start ++ public org.bukkit.command.CommandSender getBukkitSender() { ++ return source.getBukkitSender(this); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/Commands.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/Commands.java.patch new file mode 100644 index 0000000000..016b50a1a8 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/Commands.java.patch @@ -0,0 +1,171 @@ +--- a/net/minecraft/commands/Commands.java ++++ b/net/minecraft/commands/Commands.java +@@ -135,6 +134,14 @@ + import net.minecraft.world.level.GameRules; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.google.common.base.Joiner; ++import java.util.Collection; ++import java.util.LinkedHashSet; ++import org.bukkit.event.player.PlayerCommandSendEvent; ++import org.bukkit.event.server.ServerCommandEvent; ++// CraftBukkit end ++ + public class Commands { + + private static final ThreadLocal> CURRENT_EXECUTION_CONTEXT = new ThreadLocal(); +@@ -146,7 +153,8 @@ + public static final int LEVEL_OWNERS = 4; + private final CommandDispatcher dispatcher = new CommandDispatcher(); + +- public Commands(Commands.CommandSelection commands_commandselection, CommandBuildContext commandbuildcontext) { ++ public Commands(Commands.CommandSelection selection, CommandBuildContext context) { ++ this(); // CraftBukkit + AdvancementCommands.register(this.dispatcher); + AttributeCommand.register(this.dispatcher, commandbuildcontext); + ExecuteCommand.register(this.dispatcher, commandbuildcontext); +@@ -247,6 +255,11 @@ + PublishCommand.register(this.dispatcher); + } + ++ // CraftBukkit start ++ } ++ ++ public Commands() { ++ // CraftBukkkit end + this.dispatcher.setConsumer(ExecutionCommandSource.resultConsumer()); + } + +@@ -257,18 +270,64 @@ + return new ParseResults(commandcontextbuilder1, parseresults.getReader(), parseresults.getExceptions()); + } + +- public void performPrefixedCommand(CommandSourceStack commandsourcestack, String s) { ++ // CraftBukkit start ++ public void dispatchServerCommand(CommandSourceStack sender, String command) { ++ Joiner joiner = Joiner.on(" "); ++ if (command.startsWith("/")) { ++ command = command.substring(1); ++ } ++ ++ ServerCommandEvent event = new ServerCommandEvent(sender.getBukkitSender(), command); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ command = event.getCommand(); ++ ++ String[] args = command.split(" "); ++ ++ String cmd = args[0]; ++ if (cmd.startsWith("minecraft:")) cmd = cmd.substring("minecraft:".length()); ++ if (cmd.startsWith("bukkit:")) cmd = cmd.substring("bukkit:".length()); ++ ++ // Block disallowed commands ++ if (cmd.equalsIgnoreCase("stop") || cmd.equalsIgnoreCase("kick") || cmd.equalsIgnoreCase("op") ++ || cmd.equalsIgnoreCase("deop") || cmd.equalsIgnoreCase("ban") || cmd.equalsIgnoreCase("ban-ip") ++ || cmd.equalsIgnoreCase("pardon") || cmd.equalsIgnoreCase("pardon-ip") || cmd.equalsIgnoreCase("reload")) { ++ return; ++ } ++ ++ // Handle vanilla commands; ++ if (sender.getLevel().getCraftServer().getCommandBlockOverride(args[0])) { ++ args[0] = "minecraft:" + args[0]; ++ } ++ ++ String newCommand = joiner.join(args); ++ this.performPrefixedCommand(sender, newCommand, newCommand); ++ } ++ // CraftBukkit end ++ ++ public void performPrefixedCommand(CommandSourceStack commandlistenerwrapper, String s) { ++ // CraftBukkit start ++ this.performPrefixedCommand(commandlistenerwrapper, s, s); ++ } ++ ++ public void performPrefixedCommand(CommandSourceStack commandlistenerwrapper, String s, String label) { + s = s.startsWith("/") ? s.substring(1) : s; +- this.performCommand(this.dispatcher.parse(s, commandsourcestack), s); ++ this.performCommand(this.dispatcher.parse(s, commandlistenerwrapper), s, label); ++ // CraftBukkit end + } + + public void performCommand(ParseResults parseresults, String s) { + CommandSourceStack commandsourcestack = (CommandSourceStack) parseresults.getContext().getSource(); + +- commandsourcestack.getServer().getProfiler().push(() -> { ++ public void performCommand(ParseResults parseresults, String s, String label) { // CraftBukkit ++ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) parseresults.getContext().getSource(); ++ ++ commandlistenerwrapper.getServer().getProfiler().push(() -> { + return "/" + s; + }); +- ContextChain contextchain = finishParsing(parseresults, s, commandsourcestack); ++ ContextChain contextchain = finishParsing(parseresults, s, commandlistenerwrapper, label); // CraftBukkit + + try { + if (contextchain != null) { +@@ -302,7 +362,7 @@ + } + + @Nullable +- private static ContextChain finishParsing(ParseResults parseresults, String s, CommandSourceStack commandsourcestack) { ++ private static ContextChain finishParsing(ParseResults parseresults, String s, CommandSourceStack commandlistenerwrapper, String label) { // CraftBukkit + try { + validateParseResults(parseresults); + return (ContextChain) ContextChain.tryFlatten(parseresults.getContext().build(s)).orElseThrow(() -> { +@@ -312,8 +372,8 @@ + commandsourcestack.sendFailure(ComponentUtils.fromMessage(commandsyntaxexception.getRawMessage())); + if (commandsyntaxexception.getInput() != null && commandsyntaxexception.getCursor() >= 0) { + int i = Math.min(commandsyntaxexception.getInput().length(), commandsyntaxexception.getCursor()); +- MutableComponent mutablecomponent = Component.empty().withStyle(ChatFormatting.GRAY).withStyle((style) -> { +- return style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + s)); ++ MutableComponent ichatmutablecomponent = Component.empty().withStyle(ChatFormatting.GRAY).withStyle((chatmodifier) -> { ++ return chatmodifier.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, label)); // CraftBukkit + }); + + if (i > 10) { +@@ -371,13 +431,38 @@ + + } + +- public void sendCommands(ServerPlayer serverplayer) { +- Map, CommandNode> map = Maps.newHashMap(); ++ public void sendCommands(ServerPlayer player) { ++ // CraftBukkit start ++ // Register Vanilla commands into builtRoot as before ++ Map, CommandNode> map = Maps.newIdentityHashMap(); // Use identity to prevent aliasing issues ++ RootCommandNode vanillaRoot = new RootCommandNode(); ++ ++ RootCommandNode vanilla = player.server.vanillaCommandDispatcher.getDispatcher().getRoot(); ++ map.put(vanilla, vanillaRoot); ++ this.fillUsableCommands(vanilla, vanillaRoot, player.createCommandSourceStack(), (Map) map); ++ ++ // Now build the global commands in a second pass + RootCommandNode rootcommandnode = new RootCommandNode(); + + map.put(this.dispatcher.getRoot(), rootcommandnode); +- this.fillUsableCommands(this.dispatcher.getRoot(), rootcommandnode, serverplayer.createCommandSourceStack(), map); +- serverplayer.connection.send(new ClientboundCommandsPacket(rootcommandnode)); ++ this.fillUsableCommands(this.dispatcher.getRoot(), rootcommandnode, player.createCommandSourceStack(), map); ++ ++ Collection bukkit = new LinkedHashSet<>(); ++ for (CommandNode node : rootcommandnode.getChildren()) { ++ bukkit.add(node.getName()); ++ } ++ ++ PlayerCommandSendEvent event = new PlayerCommandSendEvent(player.getBukkitEntity(), new LinkedHashSet<>(bukkit)); ++ event.getPlayer().getServer().getPluginManager().callEvent(event); ++ ++ // Remove labels that were removed during the event ++ for (String orig : bukkit) { ++ if (!event.getCommands().contains(orig)) { ++ rootcommandnode.removeCommand(orig); ++ } ++ } ++ // CraftBukkit end ++ player.connection.send(new ClientboundCommandsPacket(rootcommandnode)); + } + + private void fillUsableCommands(CommandNode commandnode, CommandNode commandnode1, CommandSourceStack commandsourcestack, Map, CommandNode> map) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/arguments/EntityArgument.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/arguments/EntityArgument.java.patch new file mode 100644 index 0000000000..41ac851839 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/arguments/EntityArgument.java.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/commands/arguments/EntityArgument.java ++++ b/net/minecraft/commands/arguments/EntityArgument.java +@@ -93,11 +93,16 @@ + } + } + +- @Override +- public EntitySelector parse(StringReader stringreader) throws CommandSyntaxException { ++ public EntitySelector parse(StringReader reader) throws CommandSyntaxException { ++ // CraftBukkit start ++ return parse(reader, false); ++ } ++ ++ public EntitySelector parse(StringReader stringreader, boolean overridePermissions) throws CommandSyntaxException { ++ // CraftBukkit end + boolean flag = false; +- EntitySelectorParser entityselectorparser = new EntitySelectorParser(stringreader); +- EntitySelector entityselector = entityselectorparser.parse(); ++ EntitySelectorParser argumentparserselector = new EntitySelectorParser(stringreader); ++ EntitySelector entityselector = argumentparserselector.parse(overridePermissions); // CraftBukkit + + if (entityselector.getMaxResults() > 1 && this.single) { + if (this.playersOnly) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/arguments/blocks/BlockStateParser.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/arguments/blocks/BlockStateParser.java.patch new file mode 100644 index 0000000000..0f178b4599 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/arguments/blocks/BlockStateParser.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/commands/arguments/blocks/BlockStateParser.java ++++ b/net/minecraft/commands/arguments/blocks/BlockStateParser.java +@@ -68,7 +68,7 @@ + private final StringReader reader; + private final boolean forTesting; + private final boolean allowNbt; +- private final Map, Comparable> properties = Maps.newHashMap(); ++ private final Map, Comparable> properties = Maps.newLinkedHashMap(); // CraftBukkit - stable + private final Map vagueProperties = Maps.newHashMap(); + private ResourceLocation id = new ResourceLocation(""); + @Nullable diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/arguments/selector/EntitySelector.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/arguments/selector/EntitySelector.java.patch new file mode 100644 index 0000000000..be7b3eafa6 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/arguments/selector/EntitySelector.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/commands/arguments/selector/EntitySelector.java ++++ b/net/minecraft/commands/arguments/selector/EntitySelector.java +@@ -93,8 +91,8 @@ + return this.usesSelector; + } + +- private void checkPermissions(CommandSourceStack commandsourcestack) throws CommandSyntaxException { +- if (this.usesSelector && !commandsourcestack.hasPermission(2)) { ++ private void checkPermissions(CommandSourceStack source) throws CommandSyntaxException { ++ if (this.usesSelector && !source.hasPermission(2, "minecraft.command.selector")) { // CraftBukkit + throw EntityArgument.ERROR_SELECTORS_NOT_ALLOWED.create(); + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/arguments/selector/EntitySelectorParser.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/arguments/selector/EntitySelectorParser.java.patch new file mode 100644 index 0000000000..747f003169 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/commands/arguments/selector/EntitySelectorParser.java.patch @@ -0,0 +1,37 @@ +--- a/net/minecraft/commands/arguments/selector/EntitySelectorParser.java ++++ b/net/minecraft/commands/arguments/selector/EntitySelectorParser.java +@@ -204,8 +204,10 @@ + }; + } + +- protected void parseSelector() throws CommandSyntaxException { +- this.usesSelectors = true; ++ // CraftBukkit start ++ protected void parseSelector(boolean overridePermissions) throws CommandSyntaxException { ++ this.usesSelectors = !overridePermissions; ++ // CraftBukkit end + this.suggestions = this::suggestSelector; + if (!this.reader.canRead()) { + throw EntitySelectorParser.ERROR_MISSING_SELECTOR_TYPE.createWithContext(this.reader); +@@ -463,6 +465,12 @@ + } + + public EntitySelector parse() throws CommandSyntaxException { ++ // CraftBukkit start ++ return parse(false); ++ } ++ ++ public EntitySelector parse(boolean overridePermissions) throws CommandSyntaxException { ++ // CraftBukkit end + this.startPosition = this.reader.getCursor(); + this.suggestions = this::suggestNameOrSelector; + if (this.reader.canRead() && this.reader.peek() == '@') { +@@ -471,7 +479,7 @@ + } + + this.reader.skip(); +- this.parseSelector(); ++ this.parseSelector(overridePermissions); // CraftBukkit + } else { + this.parseNameOrUUID(); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/core/cauldron/CauldronInteraction.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/core/cauldron/CauldronInteraction.java.patch new file mode 100644 index 0000000000..3b9ffa86c4 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/core/cauldron/CauldronInteraction.java.patch @@ -0,0 +1,234 @@ +--- a/net/minecraft/core/cauldron/CauldronInteraction.java ++++ b/net/minecraft/core/cauldron/CauldronInteraction.java +@@ -33,6 +33,10 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.event.block.CauldronLevelChangeEvent; ++// CraftBukkit end ++ + public interface CauldronInteraction { + + Map INTERACTIONS = new Object2ObjectArrayMap(); +@@ -47,6 +53,8 @@ + CauldronInteraction SHULKER_BOX; + CauldronInteraction BANNER; + CauldronInteraction DYED_ITEM; ++ */ ++ // CraftBukkit end + + static CauldronInteraction.InteractionMap newInteractionMap(String s) { + Object2ObjectOpenHashMap object2objectopenhashmap = new Object2ObjectOpenHashMap(); +@@ -70,15 +78,20 @@ + if (PotionUtils.getPotion(itemstack) != Potions.WATER) { + return InteractionResult.PASS; + } else { +- if (!level.isClientSide) { ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.changeLevel(iblockdata, world, blockposition, Blocks.WATER_CAULDRON.defaultBlockState(), entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_EMPTY)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + Item item = itemstack.getItem(); + +- player.setItemInHand(interactionhand, ItemUtils.createFilledResult(itemstack, player, new ItemStack(Items.GLASS_BOTTLE))); +- player.awardStat(Stats.USE_CAULDRON); +- player.awardStat(Stats.ITEM_USED.get(item)); +- level.setBlockAndUpdate(blockpos, Blocks.WATER_CAULDRON.defaultBlockState()); +- level.playSound((Player) null, blockpos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockpos); ++ entityhuman.setItemInHand(enumhand, ItemUtils.createFilledResult(itemstack, entityhuman, new ItemStack(Items.GLASS_BOTTLE))); ++ entityhuman.awardStat(Stats.USE_CAULDRON); ++ entityhuman.awardStat(Stats.ITEM_USED.get(item)); ++ // world.setBlockAndUpdate(blockposition, Blocks.WATER_CAULDRON.defaultBlockState()); // CraftBukkit ++ world.playSound((Player) null, blockposition, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockposition); + } + + return InteractionResult.sidedSuccess(level.isClientSide); +@@ -92,29 +105,39 @@ + return (Integer) blockstate1.getValue(LayeredCauldronBlock.LEVEL) == 3; + }, SoundEvents.BUCKET_FILL); + }); +- map1.put(Items.GLASS_BOTTLE, (blockstate, level, blockpos, player, interactionhand, itemstack) -> { +- if (!level.isClientSide) { ++ map1.put(Items.GLASS_BOTTLE, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_FILL)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + Item item = itemstack.getItem(); + +- player.setItemInHand(interactionhand, ItemUtils.createFilledResult(itemstack, player, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER))); +- player.awardStat(Stats.USE_CAULDRON); +- player.awardStat(Stats.ITEM_USED.get(item)); +- LayeredCauldronBlock.lowerFillLevel(blockstate, level, blockpos); +- level.playSound((Player) null, blockpos, SoundEvents.BOTTLE_FILL, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockpos); ++ entityhuman.setItemInHand(enumhand, ItemUtils.createFilledResult(itemstack, entityhuman, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER))); ++ entityhuman.awardStat(Stats.USE_CAULDRON); ++ entityhuman.awardStat(Stats.ITEM_USED.get(item)); ++ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit ++ world.playSound((Player) null, blockposition, SoundEvents.BOTTLE_FILL, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockposition); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + }); +- map1.put(Items.POTION, (blockstate, level, blockpos, player, interactionhand, itemstack) -> { +- if ((Integer) blockstate.getValue(LayeredCauldronBlock.LEVEL) != 3 && PotionUtils.getPotion(itemstack) == Potions.WATER) { +- if (!level.isClientSide) { +- player.setItemInHand(interactionhand, ItemUtils.createFilledResult(itemstack, player, new ItemStack(Items.GLASS_BOTTLE))); +- player.awardStat(Stats.USE_CAULDRON); +- player.awardStat(Stats.ITEM_USED.get(itemstack.getItem())); +- level.setBlockAndUpdate(blockpos, (BlockState) blockstate.cycle(LayeredCauldronBlock.LEVEL)); +- level.playSound((Player) null, blockpos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockpos); ++ map1.put(Items.POTION, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ if ((Integer) iblockdata.getValue(LayeredCauldronBlock.LEVEL) != 3 && PotionUtils.getPotion(itemstack) == Potions.WATER) { ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.changeLevel(iblockdata, world, blockposition, iblockdata.cycle(LayeredCauldronBlock.LEVEL), entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_EMPTY)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ entityhuman.setItemInHand(enumhand, ItemUtils.createFilledResult(itemstack, entityhuman, new ItemStack(Items.GLASS_BOTTLE))); ++ entityhuman.awardStat(Stats.USE_CAULDRON); ++ entityhuman.awardStat(Stats.ITEM_USED.get(itemstack.getItem())); ++ // world.setBlockAndUpdate(blockposition, (IBlockData) iblockdata.cycle(LayeredCauldronBlock.LEVEL)); // CraftBukkit ++ world.playSound((Player) null, blockposition, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockposition); + } + + return InteractionResult.sidedSuccess(level.isClientSide); +@@ -188,14 +211,19 @@ + return InteractionResult.PASS; + } else { + if (!level.isClientSide) { +- Item item = itemstack.getItem(); ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.changeLevel(blockState, level, pos, Blocks.CAULDRON.defaultBlockState(), player, CauldronLevelChangeEvent.ChangeReason.BUCKET_FILL)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ Item item = emptyStack.getItem(); + + player.setItemInHand(interactionhand, ItemUtils.createFilledResult(itemstack, player, itemstack1)); + player.awardStat(Stats.USE_CAULDRON); + player.awardStat(Stats.ITEM_USED.get(item)); +- level.setBlockAndUpdate(blockpos, Blocks.CAULDRON.defaultBlockState()); +- level.playSound((Player) null, blockpos, soundevent, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockpos); ++ // world.setBlockAndUpdate(blockposition, Blocks.CAULDRON.defaultBlockState()); // CraftBukkit ++ level.playSound((Player) null, pos, fillSound, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, pos); + } + + return InteractionResult.sidedSuccess(level.isClientSide); +@@ -204,14 +232,19 @@ + + static InteractionResult emptyBucket(Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, ItemStack itemstack, BlockState blockstate, SoundEvent soundevent) { + if (!level.isClientSide) { +- Item item = itemstack.getItem(); ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.changeLevel(state, level, pos, state, player, CauldronLevelChangeEvent.ChangeReason.BUCKET_EMPTY)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ Item item = filledStack.getItem(); + + player.setItemInHand(interactionhand, ItemUtils.createFilledResult(itemstack, player, new ItemStack(Items.BUCKET))); + player.awardStat(Stats.FILL_CAULDRON); + player.awardStat(Stats.ITEM_USED.get(item)); +- level.setBlockAndUpdate(blockpos, blockstate); +- level.playSound((Player) null, blockpos, soundevent, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockpos); ++ // world.setBlockAndUpdate(blockposition, iblockdata); // CraftBukkit ++ level.playSound((Player) null, pos, emptySound, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.gameEvent((Entity) null, GameEvent.FLUID_PLACE, pos); + } + + return InteractionResult.sidedSuccess(level.isClientSide); +@@ -236,22 +266,28 @@ + FILL_POWDER_SNOW = (blockstate, level, blockpos, player, interactionhand, itemstack) -> { + return emptyBucket(level, blockpos, player, interactionhand, itemstack, (BlockState) Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY_POWDER_SNOW); + }; +- SHULKER_BOX = (blockstate, level, blockpos, player, interactionhand, itemstack) -> { ++ CauldronInteraction SHULKER_BOX = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ // CraftBukkit end + Block block = Block.byItem(itemstack.getItem()); + + if (!(block instanceof ShulkerBoxBlock)) { + return InteractionResult.PASS; + } else { +- if (!level.isClientSide) { ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.SHULKER_WASH)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + ItemStack itemstack1 = new ItemStack(Blocks.SHULKER_BOX); + + if (itemstack.hasTag()) { + itemstack1.setTag(itemstack.getTag().copy()); + } + +- player.setItemInHand(interactionhand, itemstack1); +- player.awardStat(Stats.CLEAN_SHULKER_BOX); +- LayeredCauldronBlock.lowerFillLevel(blockstate, level, blockpos); ++ entityhuman.setItemInHand(enumhand, itemstack1); ++ entityhuman.awardStat(Stats.CLEAN_SHULKER_BOX); ++ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit + } + + return InteractionResult.sidedSuccess(level.isClientSide); +@@ -261,7 +297,12 @@ + if (BannerBlockEntity.getPatternCount(itemstack) <= 0) { + return InteractionResult.PASS; + } else { +- if (!level.isClientSide) { ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.BANNER_WASH)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + ItemStack itemstack1 = itemstack.copyWithCount(1); + + BannerBlockEntity.removeLastPattern(itemstack1); +@@ -277,8 +318,8 @@ + player.drop(itemstack1, false); + } + +- player.awardStat(Stats.CLEAN_BANNER); +- LayeredCauldronBlock.lowerFillLevel(blockstate, level, blockpos); ++ entityhuman.awardStat(Stats.CLEAN_BANNER); ++ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit + } + + return InteractionResult.sidedSuccess(level.isClientSide); +@@ -295,10 +336,15 @@ + if (!dyeableleatheritem.hasCustomColor(itemstack)) { + return InteractionResult.PASS; + } else { +- if (!level.isClientSide) { +- dyeableleatheritem.clearColor(itemstack); +- player.awardStat(Stats.CLEAN_ARMOR); +- LayeredCauldronBlock.lowerFillLevel(blockstate, level, blockpos); ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.ARMOR_WASH)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ idyeable.clearColor(itemstack); ++ entityhuman.awardStat(Stats.CLEAN_ARMOR); ++ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit + } + + return InteractionResult.sidedSuccess(level.isClientSide); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java.patch new file mode 100644 index 0000000000..027b56ccbc --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java.patch @@ -0,0 +1,58 @@ +--- a/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java ++++ b/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java +@@ -7,6 +6,13 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.DispenserBlock; ++// CraftBukkit start ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.projectile.Projectile; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end + + public abstract class AbstractProjectileDispenseBehavior extends DefaultDispenseItemBehavior { + +@@ -20,9 +25,38 @@ + Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING); + Projectile projectile = this.getProjectile(serverlevel, position, itemstack); + +- projectile.shoot((double) direction.getStepX(), (double) ((float) direction.getStepY() + 0.1F), (double) direction.getStepZ(), this.getPower(), this.getUncertainty()); +- serverlevel.addFreshEntity(projectile); +- itemstack.shrink(1); ++ // CraftBukkit start ++ // iprojectile.shoot((double) enumdirection.getStepX(), (double) ((float) enumdirection.getStepY() + 0.1F), (double) enumdirection.getStepZ(), this.getPower(), this.getUncertainty()); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) enumdirection.getStepX(), (double) ((float) enumdirection.getStepY() + 0.1F), (double) enumdirection.getStepZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ iprojectile.shoot(event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), this.getPower(), this.getUncertainty()); ++ ((Entity) iprojectile).projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(sourceblock.blockEntity()); ++ // CraftBukkit end ++ worldserver.addFreshEntity(iprojectile); ++ // itemstack.shrink(1); // CraftBukkit - Handled during event processing + return itemstack; + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java.patch new file mode 100644 index 0000000000..a32509d4a3 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java.patch @@ -0,0 +1,61 @@ +--- a/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java ++++ b/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java +@@ -12,6 +12,11 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.DispenserBlock; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end + + public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior { + +@@ -52,13 +56,41 @@ + d4 = 0.0D; + } + +- Object object = this.isChestBoat ? new ChestBoat(serverlevel, d1, d2 + d4, d3) : new Boat(serverlevel, d1, d2 + d4, d3); ++ // Object object = this.isChestBoat ? new ChestBoat(worldserver, d1, d2 + d4, d3) : new EntityBoat(worldserver, d1, d2 + d4, d3); ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + +- EntityType.createDefaultStackConfig(serverlevel, itemstack, (Player) null).accept(object); ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d1, d2 + d4, d3)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ Boat object = this.isChestBoat ? new ChestBoat(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ()) : new Boat(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ()); ++ // CraftBukkit end ++ ++ EntityType.createDefaultStackConfig(worldserver, itemstack, (Player) null).accept(object); + ((Boat) object).setVariant(this.type); +- ((Boat) object).setYRot(direction.toYRot()); +- serverlevel.addFreshEntity((Entity) object); +- itemstack.shrink(1); ++ ((Boat) object).setYRot(enumdirection.toYRot()); ++ if (!worldserver.addFreshEntity((Entity) object)) itemstack.grow(1); // CraftBukkit ++ // itemstack.shrink(1); // CraftBukkit - handled during event processing + return itemstack; + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java.patch new file mode 100644 index 0000000000..0243bac917 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java.patch @@ -0,0 +1,113 @@ +--- a/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java ++++ b/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java +@@ -6,9 +6,23 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.DispenserBlock; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftVector; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end + + public class DefaultDispenseItemBehavior implements DispenseItemBehavior { + ++ // CraftBukkit start ++ private boolean dropper; ++ ++ public DefaultDispenseItemBehavior(boolean dropper) { ++ this.dropper = dropper; ++ } ++ // CraftBukkit end ++ + public DefaultDispenseItemBehavior() {} + + @Override +@@ -26,16 +39,27 @@ + Position position = DispenserBlock.getDispensePosition(blocksource); + ItemStack itemstack1 = itemstack.split(1); + +- spawnItem(blocksource.level(), itemstack1, 6, direction, position); ++ // CraftBukkit start ++ if (!spawnItem(sourceblock.level(), itemstack1, 6, enumdirection, sourceblock, dropper)) { ++ itemstack.grow(1); ++ } ++ // CraftBukkit end + return itemstack; + } + +- public static void spawnItem(Level level, ItemStack itemstack, int i, Direction direction, Position position) { +- double d0 = position.x(); +- double d1 = position.y(); +- double d2 = position.z(); ++ public static void spawnItem(Level level, ItemStack stack, int speed, Direction facing, IPosition position) { ++ // CraftBukkit start ++ ItemEntity entityitem = prepareItem(level, stack, speed, facing, position); ++ level.addFreshEntity(entityitem); ++ } + +- if (direction.getAxis() == Direction.Axis.Y) { ++ private static ItemEntity prepareItem(Level world, ItemStack itemstack, int i, Direction enumdirection, IPosition iposition) { ++ // CraftBukkit end ++ double d0 = iposition.x(); ++ double d1 = iposition.y(); ++ double d2 = iposition.z(); ++ ++ if (enumdirection.getAxis() == Direction.Axis.Y) { + d1 -= 0.125D; + } else { + d1 -= 0.15625D; +@@ -44,12 +68,48 @@ + ItemEntity itementity = new ItemEntity(level, d0, d1, d2, itemstack); + double d3 = level.random.nextDouble() * 0.1D + 0.2D; + +- itementity.setDeltaMovement(level.random.triangle((double) direction.getStepX() * d3, 0.0172275D * (double) i), level.random.triangle(0.2D, 0.0172275D * (double) i), level.random.triangle((double) direction.getStepZ() * d3, 0.0172275D * (double) i)); +- level.addFreshEntity(itementity); ++ entityitem.setDeltaMovement(world.random.triangle((double) enumdirection.getStepX() * d3, 0.0172275D * (double) i), world.random.triangle(0.2D, 0.0172275D * (double) i), world.random.triangle((double) enumdirection.getStepZ() * d3, 0.0172275D * (double) i)); ++ // CraftBukkit start ++ return entityitem; + } + +- protected void playSound(BlockSource blocksource) { +- blocksource.level().levelEvent(1000, blocksource.pos(), 0); ++ // CraftBukkit - void -> boolean return, IPosition -> ISourceBlock last argument, dropper ++ public static boolean spawnItem(Level world, ItemStack itemstack, int i, Direction enumdirection, SourceBlock sourceblock, boolean dropper) { ++ if (itemstack.isEmpty()) return true; ++ IPosition iposition = DispenserBlock.getDispensePosition(sourceblock); ++ ItemEntity entityitem = prepareItem(world, itemstack, i, enumdirection, iposition); ++ ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), CraftVector.toBukkit(entityitem.getDeltaMovement())); ++ if (!DispenserBlock.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ entityitem.setItem(CraftItemStack.asNMSCopy(event.getItem())); ++ entityitem.setDeltaMovement(CraftVector.toNMS(event.getVelocity())); ++ ++ if (!dropper && !event.getItem().getType().equals(craftItem.getType())) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior.getClass() != DefaultDispenseItemBehavior.class) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ } else { ++ world.addFreshEntity(entityitem); ++ } ++ return false; ++ } ++ ++ world.addFreshEntity(entityitem); ++ ++ return true; ++ // CraftBukkit end + } + + protected void playAnimation(BlockSource blocksource, Direction direction) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/core/dispenser/DispenseItemBehavior.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/core/dispenser/DispenseItemBehavior.java.patch new file mode 100644 index 0000000000..4cbfcb072a --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/core/dispenser/DispenseItemBehavior.java.patch @@ -0,0 +1,687 @@ +--- a/net/minecraft/core/dispenser/DispenseItemBehavior.java ++++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java +@@ -76,6 +79,17 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; ++import org.bukkit.Location; ++import org.bukkit.TreeType; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.craftbukkit.util.DummyGeneratorAccess; ++import org.bukkit.event.block.BlockDispenseArmorEvent; ++import org.bukkit.event.block.BlockDispenseEvent; ++import org.bukkit.event.block.BlockFertilizeEvent; ++import org.bukkit.event.world.StructureGrowEvent; ++// CraftBukkit end + + public interface DispenseItemBehavior { + +@@ -218,6 +215,33 @@ + Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING); + EntityType entitytype = ((SpawnEggItem) itemstack.getItem()).getType(itemstack.getTag()); + ++ // CraftBukkit start ++ ServerLevel worldserver = sourceblock.level(); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ + try { + entitytype.spawn(blocksource.level(), itemstack, (Player) null, blocksource.pos().relative(direction), MobSpawnType.DISPENSER, direction != Direction.UP, false); + } catch (Exception exception) { +@@ -225,8 +249,9 @@ + return ItemStack.EMPTY; + } + +- itemstack.shrink(1); +- blocksource.level().gameEvent((Entity) null, GameEvent.ENTITY_PLACE, blocksource.pos()); ++ // itemstack.shrink(1); // Handled during event processing ++ // CraftBukkit end ++ sourceblock.level().gameEvent((Entity) null, GameEvent.ENTITY_PLACE, sourceblock.pos()); + return itemstack; + } + }; +@@ -250,10 +270,42 @@ + }, serverlevel, itemstack, (Player) null); + ArmorStand armorstand = (ArmorStand) EntityType.ARMOR_STAND.spawn(serverlevel, itemstack.getTag(), consumer, blockpos, MobSpawnType.DISPENSER, false, false); + +- if (armorstand != null) { +- itemstack.shrink(1); ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); + } + ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ ++ Consumer consumer = EntityType.appendDefaultStackConfig((entityarmorstand) -> { ++ entityarmorstand.setYRot(enumdirection.toYRot()); ++ }, worldserver, itemstack, (Player) null); ++ ArmorStand entityarmorstand = (ArmorStand) EntityType.ARMOR_STAND.spawn(worldserver, itemstack.getTag(), consumer, blockposition, EnumMobSpawn.DISPENSER, false, false); ++ ++ if (entityarmorstand != null) { ++ // itemstack.shrink(1); // CraftBukkit - Handled during event processing ++ } ++ + return itemstack; + } + }); +@@ -273,8 +324,35 @@ + }); + + if (!list.isEmpty()) { ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ Level world = sourceblock.level(); ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) list.get(0).getBukkitEntity()); ++ if (!DispenserBlock.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end + ((Saddleable) list.get(0)).equipSaddle(SoundSource.BLOCKS); +- itemstack.shrink(1); ++ // itemstack.shrink(1); // CraftBukkit - handled above + this.setSuccess(true); + return itemstack; + } else { +@@ -302,7 +379,35 @@ + abstracthorse = (AbstractHorse) iterator1.next(); + } while (!abstracthorse.isArmor(itemstack) || abstracthorse.isWearingArmor() || !abstracthorse.isTamed()); + +- abstracthorse.getSlot(401).set(itemstack.split(1)); ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ Level world = sourceblock.level(); ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityhorseabstract.getBukkitEntity()); ++ if (!DispenserBlock.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ entityhorseabstract.getSlot(401).set(CraftItemStack.asNMSCopy(event.getItem())); ++ // CraftBukkit end + this.setSuccess(true); + return itemstack; + } +@@ -345,25 +449,79 @@ + return super.execute(blocksource, itemstack); + } + +- abstractchestedhorse = (AbstractChestedHorse) iterator1.next(); +- } while (!abstractchestedhorse.isTamed() || !abstractchestedhorse.getSlot(499).set(itemstack)); ++ entityhorsechestedabstract = (AbstractChestedHorse) iterator1.next(); ++ // CraftBukkit start ++ } while (!entityhorsechestedabstract.isTamed()); ++ ItemStack itemstack1 = itemstack.split(1); ++ Level world = sourceblock.level(); ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + +- itemstack.shrink(1); ++ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityhorsechestedabstract.getBukkitEntity()); ++ if (!DispenserBlock.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ entityhorsechestedabstract.getSlot(499).set(CraftItemStack.asNMSCopy(event.getItem())); ++ // CraftBukkit end ++ ++ // itemstack.shrink(1); // CraftBukkit - handled above + this.setSuccess(true); + return itemstack; + } + }); + DispenserBlock.registerBehavior(Items.FIREWORK_ROCKET, new DefaultDispenseItemBehavior() { + @Override +- @Override +- public ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING); +- Vec3 vec3 = DispenseItemBehavior.getEntityPokingOutOfBlockPos(blocksource, EntityType.FIREWORK_ROCKET, direction); +- FireworkRocketEntity fireworkrocketentity = new FireworkRocketEntity(blocksource.level(), itemstack, vec3.x(), vec3.y(), vec3.z(), true); ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ // CraftBukkit start ++ ServerLevel worldserver = sourceblock.level(); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + +- fireworkrocketentity.shoot((double) direction.getStepX(), (double) direction.getStepY(), (double) direction.getStepZ(), 0.5F, 1.0F); +- blocksource.level().addFreshEntity(fireworkrocketentity); +- itemstack.shrink(1); ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(enumdirection.getStepX(), enumdirection.getStepY(), enumdirection.getStepZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); ++ Vec3 vec3d = DispenseItemBehavior.getEntityPokingOutOfBlockPos(sourceblock, EntityType.FIREWORK_ROCKET, enumdirection); ++ FireworkRocketEntity entityfireworks = new FireworkRocketEntity(sourceblock.level(), itemstack, vec3d.x(), vec3d.y(), vec3d.z(), true); ++ ++ entityfireworks.shoot((double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ(), 0.5F, 1.0F); ++ sourceblock.level().addFreshEntity(entityfireworks); ++ // itemstack.shrink(1); // Handled during event processing ++ // CraftBukkit end + return itemstack; + } + +@@ -389,10 +544,39 @@ + double d5 = randomsource.triangle((double) direction.getStepZ(), 0.11485000000000001D); + SmallFireball smallfireball = new SmallFireball(serverlevel, d0, d1, d2, d3, d4, d5); + +- serverlevel.addFreshEntity((Entity) Util.make(smallfireball, (smallfireball1) -> { +- smallfireball1.setItem(itemstack); +- })); +- itemstack.shrink(1); ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d3, d4, d5)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ SmallFireball entitysmallfireball = new SmallFireball(worldserver, d0, d1, d2, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ()); ++ entitysmallfireball.setItem(itemstack1); ++ entitysmallfireball.projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(sourceblock.blockEntity()); ++ ++ worldserver.addFreshEntity(entitysmallfireball); ++ // itemstack.shrink(1); // Handled during event processing ++ // CraftBukkit end + return itemstack; + } + +@@ -430,9 +612,51 @@ + BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING)); + ServerLevel serverlevel = blocksource.level(); + +- if (dispensiblecontaineritem.emptyContents((Player) null, serverlevel, blockpos, (BlockHitResult) null)) { +- dispensiblecontaineritem.checkExtraContent((Player) null, serverlevel, itemstack, blockpos); +- return new ItemStack(Items.BUCKET); ++ // CraftBukkit start ++ int x = blockposition.getX(); ++ int y = blockposition.getY(); ++ int z = blockposition.getZ(); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ if (iblockdata.isAir() || iblockdata.canBeReplaced() || (dispensiblecontaineritem instanceof BucketItem && iblockdata.getBlock() instanceof LiquidBlockContainer && ((LiquidBlockContainer) iblockdata.getBlock()).canPlaceLiquid((Player) null, worldserver, blockposition, iblockdata, ((BucketItem) dispensiblecontaineritem).content))) { ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(x, y, z)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ dispensiblecontaineritem = (DispensibleContainerItem) CraftItemStack.asNMSCopy(event.getItem()).getItem(); ++ } ++ // CraftBukkit end ++ ++ if (dispensiblecontaineritem.emptyContents((Player) null, worldserver, blockposition, (BlockHitResult) null)) { ++ dispensiblecontaineritem.checkExtraContent((Player) null, worldserver, itemstack, blockposition); ++ // CraftBukkit start - Handle stacked buckets ++ Item item = Items.BUCKET; ++ itemstack.shrink(1); ++ if (itemstack.isEmpty()) { ++ itemstack.setItem(Items.BUCKET); ++ itemstack.setCount(1); ++ } else if (sourceblock.blockEntity().addItem(new ItemStack(item)) < 0) { ++ this.defaultDispenseItemBehavior.dispense(sourceblock, new ItemStack(item)); ++ } ++ return itemstack; ++ // CraftBukkit end + } else { + return this.defaultDispenseItemBehavior.dispense(blocksource, itemstack); + } +@@ -460,8 +683,8 @@ + Block block = blockstate.getBlock(); + + if (block instanceof BucketPickup) { +- BucketPickup bucketpickup = (BucketPickup) block; +- ItemStack itemstack1 = bucketpickup.pickupBlock((Player) null, serverlevel, blockpos, blockstate); ++ BucketPickup ifluidsource = (BucketPickup) block; ++ ItemStack itemstack1 = ifluidsource.pickupBlock((Player) null, DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); // CraftBukkit + + if (itemstack1.isEmpty()) { + return super.execute(blocksource, itemstack); +@@ -469,6 +692,32 @@ + serverlevel.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockpos); + Item item = itemstack1.getItem(); + ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ itemstack1 = ifluidsource.pickupBlock((Player) null, worldserver, blockposition, iblockdata); // From above ++ // CraftBukkit end ++ + itemstack.shrink(1); + if (itemstack.isEmpty()) { + return new ItemStack(item); +@@ -491,18 +739,46 @@ + protected ItemStack execute(BlockSource blocksource, ItemStack itemstack) { + ServerLevel serverlevel = blocksource.level(); + ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ + this.setSuccess(true); + Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING); + BlockPos blockpos = blocksource.pos().relative(direction); + BlockState blockstate = serverlevel.getBlockState(blockpos); + +- if (BaseFireBlock.canBePlacedAt(serverlevel, blockpos, direction)) { +- serverlevel.setBlockAndUpdate(blockpos, BaseFireBlock.getState(serverlevel, blockpos)); +- serverlevel.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockpos); +- } else if (!CampfireBlock.canLight(blockstate) && !CandleBlock.canLight(blockstate) && !CandleCakeBlock.canLight(blockstate)) { +- if (blockstate.getBlock() instanceof TntBlock) { +- TntBlock.explode(serverlevel, blockpos); +- serverlevel.removeBlock(blockpos, false); ++ if (BaseFireBlock.canBePlacedAt(worldserver, blockposition, enumdirection)) { ++ // CraftBukkit start - Ignition by dispensing flint and steel ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(worldserver, blockposition, sourceblock.pos()).isCancelled()) { ++ worldserver.setBlockAndUpdate(blockposition, BaseFireBlock.getState(worldserver, blockposition)); ++ worldserver.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockposition); ++ } ++ // CraftBukkit end ++ } else if (!CampfireBlock.canLight(iblockdata) && !CandleBlock.canLight(iblockdata) && !CandleCakeBlock.canLight(iblockdata)) { ++ if (iblockdata.getBlock() instanceof TntBlock && org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(worldserver, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.DISPENSER, null, sourceblock.pos())) { // CraftBukkit - TNTPrimeEvent ++ TntBlock.explode(worldserver, blockposition); ++ worldserver.removeBlock(blockposition, false); + } else { + this.setSuccess(false); + } +@@ -523,30 +798,108 @@ + @Override + protected ItemStack execute(BlockSource blocksource, ItemStack itemstack) { + this.setSuccess(true); +- ServerLevel serverlevel = blocksource.level(); +- BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING)); ++ ServerLevel worldserver = sourceblock.level(); ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ // CraftBukkit start ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); + +- if (!BoneMealItem.growCrop(itemstack, serverlevel, blockpos) && !BoneMealItem.growWaterPlant(itemstack, serverlevel, blockpos, (Direction) null)) { ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ worldserver.captureTreeGeneration = true; ++ // CraftBukkit end ++ ++ if (!BoneMealItem.growCrop(itemstack, worldserver, blockposition) && !BoneMealItem.growWaterPlant(itemstack, worldserver, blockposition, (Direction) null)) { + this.setSuccess(false); + } else if (!serverlevel.isClientSide) { + serverlevel.levelEvent(1505, blockpos, 0); + } ++ // CraftBukkit start ++ worldserver.captureTreeGeneration = false; ++ if (worldserver.capturedBlockStates.size() > 0) { ++ TreeType treeType = SaplingBlock.treeType; ++ SaplingBlock.treeType = null; ++ Location location = CraftLocation.toBukkit(blockposition, worldserver.getWorld()); ++ List blocks = new java.util.ArrayList<>(worldserver.capturedBlockStates.values()); ++ worldserver.capturedBlockStates.clear(); ++ StructureGrowEvent structureEvent = null; ++ if (treeType != null) { ++ structureEvent = new StructureGrowEvent(location, treeType, false, null, blocks); ++ org.bukkit.Bukkit.getPluginManager().callEvent(structureEvent); ++ } + ++ BlockFertilizeEvent fertilizeEvent = new BlockFertilizeEvent(location.getBlock(), null, blocks); ++ fertilizeEvent.setCancelled(structureEvent != null && structureEvent.isCancelled()); ++ org.bukkit.Bukkit.getPluginManager().callEvent(fertilizeEvent); ++ ++ if (!fertilizeEvent.isCancelled()) { ++ for (org.bukkit.block.BlockState blockstate : blocks) { ++ blockstate.update(true); ++ } ++ } ++ } ++ // CraftBukkit end ++ + return itemstack; + } + }); + DispenserBlock.registerBehavior(Blocks.TNT, new DefaultDispenseItemBehavior() { + @Override +- @Override +- protected ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- ServerLevel serverlevel = blocksource.level(); +- BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING)); +- PrimedTnt primedtnt = new PrimedTnt(serverlevel, (double) blockpos.getX() + 0.5D, (double) blockpos.getY(), (double) blockpos.getZ() + 0.5D, (LivingEntity) null); ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ // CraftBukkit start ++ // EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, (EntityLiving) null); + +- serverlevel.addFreshEntity(primedtnt); +- serverlevel.playSound((Player) null, primedtnt.getX(), primedtnt.getY(), primedtnt.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F); +- serverlevel.gameEvent((Entity) null, GameEvent.ENTITY_PLACE, blockpos); +- itemstack.shrink(1); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ PrimedTnt entitytntprimed = new PrimedTnt(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), (LivingEntity) null); ++ // CraftBukkit end ++ ++ worldserver.addFreshEntity(entitytntprimed); ++ worldserver.playSound((Player) null, entitytntprimed.getX(), entitytntprimed.getY(), entitytntprimed.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F); ++ worldserver.gameEvent((Entity) null, GameEvent.ENTITY_PLACE, blockposition); ++ // itemstack.shrink(1); // CraftBukkit - handled above + return itemstack; + } + }); +@@ -573,14 +924,15 @@ + Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING); + BlockPos blockpos = blocksource.pos().relative(direction); + +- if (serverlevel.isEmptyBlock(blockpos) && WitherSkullBlock.canSpawnMob(serverlevel, blockpos, itemstack)) { +- serverlevel.setBlock(blockpos, (BlockState) Blocks.WITHER_SKELETON_SKULL.defaultBlockState().setValue(SkullBlock.ROTATION, RotationSegment.convertToSegment(direction)), 3); +- serverlevel.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockpos); +- BlockEntity blockentity = serverlevel.getBlockEntity(blockpos); ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); + + if (blockentity instanceof SkullBlockEntity) { + WitherSkullBlock.checkSpawn(serverlevel, blockpos, (SkullBlockEntity) blockentity); + } ++ } ++ // CraftBukkit end + + itemstack.shrink(1); + this.setSuccess(true); +@@ -599,11 +973,29 @@ + BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING)); + CarvedPumpkinBlock carvedpumpkinblock = (CarvedPumpkinBlock) Blocks.CARVED_PUMPKIN; + +- if (serverlevel.isEmptyBlock(blockpos) && carvedpumpkinblock.canSpawnGolem(serverlevel, blockpos)) { +- if (!serverlevel.isClientSide) { +- serverlevel.setBlock(blockpos, carvedpumpkinblock.defaultBlockState(), 3); +- serverlevel.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockpos); ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; + } ++ } ++ // CraftBukkit end + + itemstack.shrink(1); + this.setSuccess(true); +@@ -649,10 +1046,34 @@ + BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING)); + BlockState blockstate = serverlevel.getBlockState(blockpos); + +- if (blockstate.is(BlockTags.BEEHIVES, (blockbehaviour_blockstatebase) -> { +- return blockbehaviour_blockstatebase.hasProperty(BeehiveBlock.HONEY_LEVEL) && blockbehaviour_blockstatebase.getBlock() instanceof BeehiveBlock; +- }) && (Integer) blockstate.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) { +- ((BeehiveBlock) blockstate.getBlock()).releaseBeesAndResetHoneyLevel(serverlevel, blockstate, blockpos, (Player) null, BeehiveBlockEntity.BeeReleaseStatus.BEE_RELEASED); ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ ++ if (iblockdata.is(BlockTags.BEEHIVES, (blockbase_blockdata) -> { ++ return blockbase_blockdata.hasProperty(BeehiveBlock.HONEY_LEVEL) && blockbase_blockdata.getBlock() instanceof BeehiveBlock; ++ }) && (Integer) iblockdata.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) { ++ ((BeehiveBlock) iblockdata.getBlock()).releaseBeesAndResetHoneyLevel(worldserver, iblockdata, blockposition, (Player) null, BeehiveBlockEntity.ReleaseStatus.BEE_RELEASED); + this.setSuccess(true); + return this.takeLiquid(blocksource, itemstack, new ItemStack(Items.HONEY_BOTTLE)); + } else if (serverlevel.getFluidState(blockpos).is(FluidTags.WATER)) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java.patch new file mode 100644 index 0000000000..d7fb8a82cc --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java.patch @@ -0,0 +1,84 @@ +--- a/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java ++++ b/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java +@@ -21,21 +21,47 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end + + public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior { + + public ShearsDispenseItemBehavior() {} + + @Override +- @Override +- protected ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- ServerLevel serverlevel = blocksource.level(); ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); + + if (!serverlevel.isClientSide()) { + BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING)); + +- this.setSuccess(tryShearBeehive(serverlevel, blockpos) || tryShearLivingEntity(serverlevel, blockpos)); +- if (this.isSuccess() && itemstack.hurt(1, serverlevel.getRandom(), (ServerPlayer) null)) { ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ ++ if (!worldserver.isClientSide()) { ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ ++ this.setSuccess(tryShearBeehive(worldserver, blockposition) || tryShearLivingEntity(worldserver, blockposition, bukkitBlock, craftItem)); // CraftBukkit ++ if (this.isSuccess() && itemstack.hurt(1, worldserver.getRandom(), (ServerPlayer) null)) { + itemstack.setCount(0); + } + } +@@ -63,8 +91,8 @@ + return false; + } + +- private static boolean tryShearLivingEntity(ServerLevel serverlevel, BlockPos blockpos) { +- List list = serverlevel.getEntitiesOfClass(LivingEntity.class, new AABB(blockpos), EntitySelector.NO_SPECTATORS); ++ private static boolean tryShearLivingEntity(ServerLevel worldserver, BlockPos blockposition, org.bukkit.block.Block bukkitBlock, CraftItemStack craftItem) { // CraftBukkit - add args ++ List list = worldserver.getEntitiesOfClass(LivingEntity.class, new AABB(blockposition), EntitySelector.NO_SPECTATORS); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +@@ -73,9 +101,14 @@ + if (livingentity instanceof Shearable) { + Shearable shearable = (Shearable) livingentity; + +- if (shearable.readyForShearing()) { +- shearable.shear(SoundSource.BLOCKS); +- serverlevel.gameEvent((Entity) null, GameEvent.SHEAR, blockpos); ++ if (ishearable.readyForShearing()) { ++ // CraftBukkit start ++ if (CraftEventFactory.callBlockShearEntityEvent(entityliving, bukkitBlock, craftItem).isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end ++ ishearable.shear(SoundSource.BLOCKS); ++ worldserver.gameEvent((Entity) null, GameEvent.SHEAR, blockposition); + return true; + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java.patch new file mode 100644 index 0000000000..6fe4c3518e --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java ++++ b/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java +@@ -10,6 +10,12 @@ + import net.minecraft.world.level.block.DispenserBlock; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end ++ + public class ShulkerBoxDispenseBehavior extends OptionalDispenseItemBehavior { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -27,6 +32,30 @@ + BlockPos blockpos = blocksource.pos().relative(direction); + Direction direction1 = blocksource.level().isEmptyBlock(blockpos.below()) ? direction : Direction.UP; + ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(sourceblock.level(), sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!DispenserBlock.eventFired) { ++ sourceblock.level().getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ + try { + this.setSuccess(((BlockItem) item).place(new DirectionalPlaceContext(blocksource.level(), blockpos, direction, itemstack, direction1)).consumesAction()); + } catch (Exception exception) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/nbt/ByteArrayTag.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/nbt/ByteArrayTag.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/nbt/ByteArrayTag.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/nbt/IntArrayTag.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/nbt/IntArrayTag.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/nbt/IntArrayTag.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/nbt/NbtIo.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/nbt/NbtIo.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/nbt/NbtIo.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/network/Connection.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/Connection.java.patch new file mode 100644 index 0000000000..b0791435a2 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/Connection.java.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/network/Connection.java ++++ b/net/minecraft/network/Connection.java +@@ -105,6 +105,7 @@ + private volatile Component delayedDisconnect; + @Nullable + BandwidthDebugMonitor bandwidthDebugMonitor; ++ public String hostname = ""; // CraftBukkit - add field + + public Connection(PacketFlow packetflow) { + this.receiving = packetflow; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/network/FriendlyByteBuf.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/FriendlyByteBuf.java.patch new file mode 100644 index 0000000000..ce4b89510c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/FriendlyByteBuf.java.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/network/FriendlyByteBuf.java ++++ b/net/minecraft/network/FriendlyByteBuf.java +@@ -81,6 +81,8 @@ + import org.joml.Quaternionf; + import org.joml.Vector3f; + ++import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit ++ + public class FriendlyByteBuf extends ByteBuf { + + public static final int DEFAULT_NBT_QUOTA = 2097152; +@@ -584,7 +586,7 @@ + try { + NbtIo.writeAnyTag((Tag) tag, new ByteBufOutputStream(this)); + return this; +- } catch (IOException ioexception) { ++ } catch (Exception ioexception) { // CraftBukkit - IOException -> Exception + throw new EncoderException(ioexception); + } + } +@@ -611,8 +613,8 @@ + } + } + +- public FriendlyByteBuf writeItem(ItemStack itemstack) { +- if (itemstack.isEmpty()) { ++ public FriendlyByteBuf writeItem(ItemStack stack) { ++ if (stack.isEmpty() || stack.getItem() == null) { // CraftBukkit - NPE fix itemstack.getItem() + this.writeBoolean(false); + } else { + this.writeBoolean(true); +@@ -641,6 +643,11 @@ + ItemStack itemstack = new ItemStack(item, b0); + + itemstack.setTag(this.readNbt()); ++ // CraftBukkit start ++ if (itemstack.getTag() != null) { ++ CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); ++ } ++ // CraftBukkit end + return itemstack; + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/network/chat/Component.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/chat/Component.java.patch new file mode 100644 index 0000000000..ca45aba148 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/chat/Component.java.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/network/chat/Component.java ++++ b/net/minecraft/network/chat/Component.java +@@ -34,9 +34,23 @@ + import net.minecraft.resources.ResourceLocation; + import net.minecraft.util.FormattedCharSequence; + import net.minecraft.world.level.ChunkPos; ++// CraftBukkit start ++import java.util.stream.Stream; ++// CraftBukkit end + +-public interface Component extends Message, FormattedText { ++public interface Component extends Message, FormattedText, Iterable { // CraftBukkit + ++ // CraftBukkit start ++ default Stream stream() { ++ return com.google.common.collect.Streams.concat(new Stream[]{Stream.of(this), this.getSiblings().stream().flatMap(Component::stream)}); ++ } ++ ++ @Override ++ default Iterator iterator() { ++ return this.stream().iterator(); ++ } ++ // CraftBukkit end ++ + Style getStyle(); + + ComponentContents getContents(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/network/chat/TextColor.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/chat/TextColor.java.patch new file mode 100644 index 0000000000..02e5b1bb3b --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/chat/TextColor.java.patch @@ -0,0 +1,32 @@ +--- a/net/minecraft/network/chat/TextColor.java ++++ b/net/minecraft/network/chat/TextColor.java +@@ -16,15 +16,18 @@ + + private static final String CUSTOM_COLOR_PREFIX = "#"; + public static final Codec CODEC = Codec.STRING.comapFlatMap(TextColor::parseColor, TextColor::serialize); +- private static final Map LEGACY_FORMAT_TO_COLOR = (Map) Stream.of(ChatFormatting.values()).filter(ChatFormatting::isColor).collect(ImmutableMap.toImmutableMap(Function.identity(), (chatformatting) -> { +- return new TextColor(chatformatting.getColor(), chatformatting.getName()); ++ private static final Map LEGACY_FORMAT_TO_COLOR = (Map) Stream.of(ChatFormatting.values()).filter(ChatFormatting::isColor).collect(ImmutableMap.toImmutableMap(Function.identity(), (enumchatformat) -> { ++ return new TextColor(enumchatformat.getColor(), enumchatformat.getName(), enumchatformat); // CraftBukkit + })); + private static final Map NAMED_COLORS = (Map) TextColor.LEGACY_FORMAT_TO_COLOR.values().stream().collect(ImmutableMap.toImmutableMap((textcolor) -> { + return textcolor.name; + }, Function.identity())); + private final int value; + @Nullable +- private final String name; ++ public final String name; ++ // CraftBukkit start ++ @Nullable ++ public final ChatFormatting format; + + private TextColor(int i, String s) { + this.value = i & 16777215; +@@ -35,6 +40,7 @@ + this.value = i & 16777215; + this.name = null; + } ++ // CraftBukkit end + + public int getValue() { + return this.value; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/PacketUtils.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/PacketUtils.java.patch new file mode 100644 index 0000000000..f2c12852ca --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/PacketUtils.java.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/network/protocol/PacketUtils.java ++++ b/net/minecraft/network/protocol/PacketUtils.java +@@ -4,8 +4,14 @@ + import net.minecraft.CrashReport; + import net.minecraft.ReportedException; + import net.minecraft.network.PacketListener; +-import net.minecraft.server.RunningOnDifferentThreadException; ++import net.minecraft.server.CancelledPacketHandleException; ++import org.slf4j.Logger; ++ ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.network.ServerCommonPacketListenerImpl; ++// CraftBukkit end + import net.minecraft.util.thread.BlockableEventLoop; + import org.slf4j.Logger; + +@@ -19,10 +24,11 @@ + ensureRunningOnSameThread(packet, t0, (BlockableEventLoop) serverlevel.getServer()); + } + +- public static void ensureRunningOnSameThread(Packet packet, T t0, BlockableEventLoop blockableeventloop) throws RunningOnDifferentThreadException { +- if (!blockableeventloop.isSameThread()) { +- blockableeventloop.executeIfPossible(() -> { +- if (t0.shouldHandleMessage(packet)) { ++ public static void ensureRunningOnSameThread(Packet packet, T processor, BlockableEventLoop executor) throws CancelledPacketHandleException { ++ if (!executor.isSameThread()) { ++ executor.executeIfPossible(() -> { ++ if (MinecraftServer.getServer().hasStopped() || (processor instanceof ServerCommonPacketListenerImpl && ((ServerCommonPacketListenerImpl) processor).processedDisconnect)) return; // CraftBukkit, MC-142590 ++ if (processor.shouldHandleMessage(packet)) { + try { + packet.handle(t0); + } catch (Exception exception) { +@@ -59,7 +65,11 @@ + } + + }); +- throw RunningOnDifferentThreadException.RUNNING_ON_DIFFERENT_THREAD; ++ throw CancelledPacketHandleException.RUNNING_ON_DIFFERENT_THREAD; ++ // CraftBukkit start - SPIGOT-5477, MC-142590 ++ } else if (MinecraftServer.getServer().hasStopped() || (processor instanceof ServerCommonPacketListenerImpl && ((ServerCommonPacketListenerImpl) processor).processedDisconnect)) { ++ throw CancelledPacketHandleException.RUNNING_ON_DIFFERENT_THREAD; ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java.patch new file mode 100644 index 0000000000..c95bd4e06e --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java.patch @@ -0,0 +1,44 @@ +--- a/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java ++++ b/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java +@@ -12,7 +12,7 @@ + public record ServerboundCustomPayloadPacket(CustomPacketPayload payload) implements Packet { + + private static final int MAX_PAYLOAD_SIZE = 32767; +- private static final Map> KNOWN_TYPES = ImmutableMap.builder().put(BrandPayload.ID, BrandPayload::new).build(); ++ private static final Map> KNOWN_TYPES = ImmutableMap.>builder().build(); // CraftBukkit - no special handling + + public ServerboundCustomPayloadPacket(FriendlyByteBuf friendlybytebuf) { + this(readPayload(friendlybytebuf.readResourceLocation(), friendlybytebuf)); +@@ -24,12 +24,13 @@ + return (CustomPacketPayload) (friendlybytebuf_reader != null ? (CustomPacketPayload) friendlybytebuf_reader.apply(friendlybytebuf) : readUnknownPayload(resourcelocation, friendlybytebuf)); + } + +- private static DiscardedPayload readUnknownPayload(ResourceLocation resourcelocation, FriendlyByteBuf friendlybytebuf) { +- int i = friendlybytebuf.readableBytes(); ++ private static UnknownPayload readUnknownPayload(ResourceLocation minecraftkey, FriendlyByteBuf packetdataserializer) { // CraftBukkit ++ int i = packetdataserializer.readableBytes(); + + if (i >= 0 && i <= 32767) { +- friendlybytebuf.skipBytes(i); +- return new DiscardedPayload(resourcelocation); ++ // CraftBukkit start ++ return new UnknownPayload(minecraftkey, packetdataserializer.readBytes(i)); ++ // CraftBukkit end + } else { + throw new IllegalArgumentException("Payload may not be larger than 32767 bytes"); + } +@@ -46,4 +45,14 @@ + public void handle(ServerCommonPacketListener servercommonpacketlistener) { + servercommonpacketlistener.handleCustomPayload(this); + } ++ ++ // CraftBukkit start ++ public record UnknownPayload(ResourceLocation id, io.netty.buffer.ByteBuf data) implements CustomPacketPayload { ++ ++ @Override ++ public void write(FriendlyByteBuf packetdataserializer) { ++ packetdataserializer.writeBytes(data); ++ } ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java.patch new file mode 100644 index 0000000000..294bfa4ffa --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java ++++ b/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java +@@ -26,15 +26,17 @@ + this.warningTime = friendlybytebuf.readVarInt(); + } + +- public ClientboundInitializeBorderPacket(WorldBorder worldborder) { +- this.newCenterX = worldborder.getCenterX(); +- this.newCenterZ = worldborder.getCenterZ(); +- this.oldSize = worldborder.getSize(); +- this.newSize = worldborder.getLerpTarget(); +- this.lerpTime = worldborder.getLerpRemainingTime(); +- this.newAbsoluteMaxSize = worldborder.getAbsoluteMaxSize(); +- this.warningBlocks = worldborder.getWarningBlocks(); +- this.warningTime = worldborder.getWarningTime(); ++ public ClientboundInitializeBorderPacket(WorldBorder worldBorder) { ++ // CraftBukkit start - multiply out nether border ++ this.newCenterX = worldBorder.getCenterX() * worldBorder.world.dimensionType().coordinateScale(); ++ this.newCenterZ = worldBorder.getCenterZ() * worldBorder.world.dimensionType().coordinateScale(); ++ // CraftBukkit end ++ this.oldSize = worldBorder.getSize(); ++ this.newSize = worldBorder.getLerpTarget(); ++ this.lerpTime = worldBorder.getLerpRemainingTime(); ++ this.newAbsoluteMaxSize = worldBorder.getAbsoluteMaxSize(); ++ this.warningBlocks = worldBorder.getWarningBlocks(); ++ this.warningTime = worldBorder.getWarningTime(); + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java.patch new file mode 100644 index 0000000000..0f91165711 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java ++++ b/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java +@@ -30,14 +30,18 @@ + short short0 = (Short) shortiterator.next(); + + this.positions[j] = short0; +- this.states[j] = levelchunksection.getBlockState(SectionPos.sectionRelativeX(short0), SectionPos.sectionRelativeY(short0), SectionPos.sectionRelativeZ(short0)); ++ this.states[j] = (section != null) ? section.getBlockState(SectionPos.sectionRelativeX(short0), SectionPos.sectionRelativeY(short0), SectionPos.sectionRelativeZ(short0)) : net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(); // CraftBukkit - SPIGOT-6076, Mojang bug when empty chunk section notified + } + + } + +- public ClientboundSectionBlocksUpdatePacket(FriendlyByteBuf friendlybytebuf) { +- this.sectionPos = SectionPos.of(friendlybytebuf.readLong()); +- int i = friendlybytebuf.readVarInt(); ++ // CraftBukkit start - Add constructor ++ public ClientboundSectionBlocksUpdatePacket(SectionPos sectionposition, ShortSet shortset, IBlockData[] states) { ++ this.sectionPos = sectionposition; ++ this.positions = shortset.toShortArray(); ++ this.states = states; ++ } ++ // CraftBukkit end + + this.positions = new short[i]; + this.states = new BlockState[i]; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java.patch new file mode 100644 index 0000000000..3439ec4759 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java.patch @@ -0,0 +1,17 @@ +--- a/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java ++++ b/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java +@@ -9,9 +9,11 @@ + private final double newCenterX; + private final double newCenterZ; + +- public ClientboundSetBorderCenterPacket(WorldBorder worldborder) { +- this.newCenterX = worldborder.getCenterX(); +- this.newCenterZ = worldborder.getCenterZ(); ++ public ClientboundSetBorderCenterPacket(WorldBorder worldBorder) { ++ // CraftBukkit start - multiply out nether border ++ this.newCenterX = worldBorder.getCenterX() * (worldBorder.world != null ? worldBorder.world.dimensionType().coordinateScale() : 1.0); ++ this.newCenterZ = worldBorder.getCenterZ() * (worldBorder.world != null ? worldBorder.world.dimensionType().coordinateScale() : 1.0); ++ // CraftBukkit end + } + + public ClientboundSetBorderCenterPacket(FriendlyByteBuf friendlybytebuf) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/game/ServerboundUseItemOnPacket.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/game/ServerboundUseItemOnPacket.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/game/ServerboundUseItemOnPacket.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/game/ServerboundUseItemPacket.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/game/ServerboundUseItemPacket.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/game/ServerboundUseItemPacket.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/network/syncher/SynchedEntityData.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/syncher/SynchedEntityData.java.patch new file mode 100644 index 0000000000..319a688f64 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/network/syncher/SynchedEntityData.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/network/syncher/SynchedEntityData.java ++++ b/net/minecraft/network/syncher/SynchedEntityData.java +@@ -146,6 +148,13 @@ + + } + ++ // CraftBukkit start - add method from above ++ public void markDirty(EntityDataAccessor datawatcherobject) { ++ this.getItem(datawatcherobject).setDirty(true); ++ this.isDirty = true; ++ } ++ // CraftBukkit end ++ + public boolean isDirty() { + return this.isDirty; + } +@@ -235,6 +244,18 @@ + return this.itemsById.isEmpty(); + } + ++ // CraftBukkit start ++ public void refresh(ServerPlayer to) { ++ if (!this.isEmpty()) { ++ List> list = this.getNonDefaultValues(); ++ ++ if (list != null) { ++ to.connection.send(new ClientboundSetEntityDataPacket(this.entity.getId(), list)); ++ } ++ } ++ } ++ // CraftBukkit end ++ + public static class DataItem { + + final EntityDataAccessor accessor; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/Bootstrap.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/Bootstrap.java.patch new file mode 100644 index 0000000000..aa93e3c2f3 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/Bootstrap.java.patch @@ -0,0 +1,96 @@ +--- a/net/minecraft/server/Bootstrap.java ++++ b/net/minecraft/server/Bootstrap.java +@@ -41,6 +44,23 @@ + + public static void bootStrap() { + if (!Bootstrap.isBootstrapped) { ++ // CraftBukkit start ++ String name = Bootstrap.class.getSimpleName(); ++ switch (name) { ++ case "DispenserRegistry": ++ break; ++ case "Bootstrap": ++ System.err.println("***************************************************************************"); ++ System.err.println("*** WARNING: This server jar may only be used for development purposes. ***"); ++ System.err.println("***************************************************************************"); ++ break; ++ default: ++ System.err.println("**********************************************************************"); ++ System.err.println("*** WARNING: This server jar is unsupported, use at your own risk. ***"); ++ System.err.println("**********************************************************************"); ++ break; ++ } ++ // CraftBukkit end + Bootstrap.isBootstrapped = true; + Instant instant = Instant.now(); + +@@ -61,6 +81,69 @@ + wrapStreams(); + Bootstrap.bootstrapDuration.set(Duration.between(instant, Instant.now()).toMillis()); + } ++ // CraftBukkit start - easier than fixing the decompile ++ BlockStateData.register(1008, "{Name:'minecraft:oak_sign',Properties:{rotation:'0'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'0'}}"); ++ BlockStateData.register(1009, "{Name:'minecraft:oak_sign',Properties:{rotation:'1'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'1'}}"); ++ BlockStateData.register(1010, "{Name:'minecraft:oak_sign',Properties:{rotation:'2'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'2'}}"); ++ BlockStateData.register(1011, "{Name:'minecraft:oak_sign',Properties:{rotation:'3'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'3'}}"); ++ BlockStateData.register(1012, "{Name:'minecraft:oak_sign',Properties:{rotation:'4'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'4'}}"); ++ BlockStateData.register(1013, "{Name:'minecraft:oak_sign',Properties:{rotation:'5'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'5'}}"); ++ BlockStateData.register(1014, "{Name:'minecraft:oak_sign',Properties:{rotation:'6'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'6'}}"); ++ BlockStateData.register(1015, "{Name:'minecraft:oak_sign',Properties:{rotation:'7'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'7'}}"); ++ BlockStateData.register(1016, "{Name:'minecraft:oak_sign',Properties:{rotation:'8'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'8'}}"); ++ BlockStateData.register(1017, "{Name:'minecraft:oak_sign',Properties:{rotation:'9'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'9'}}"); ++ BlockStateData.register(1018, "{Name:'minecraft:oak_sign',Properties:{rotation:'10'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'10'}}"); ++ BlockStateData.register(1019, "{Name:'minecraft:oak_sign',Properties:{rotation:'11'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'11'}}"); ++ BlockStateData.register(1020, "{Name:'minecraft:oak_sign',Properties:{rotation:'12'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'12'}}"); ++ BlockStateData.register(1021, "{Name:'minecraft:oak_sign',Properties:{rotation:'13'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'13'}}"); ++ BlockStateData.register(1022, "{Name:'minecraft:oak_sign',Properties:{rotation:'14'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'14'}}"); ++ BlockStateData.register(1023, "{Name:'minecraft:oak_sign',Properties:{rotation:'15'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'15'}}"); ++ ItemIdFix.ITEM_NAMES.put(323, "minecraft:oak_sign"); ++ ++ BlockStateData.register(1440, "{Name:\'minecraft:portal\',Properties:{axis:\'x\'}}", new String[]{"{Name:\'minecraft:portal\',Properties:{axis:\'x\'}}"}); ++ ++ ItemIdFix.ITEM_NAMES.put(409, "minecraft:prismarine_shard"); ++ ItemIdFix.ITEM_NAMES.put(410, "minecraft:prismarine_crystals"); ++ ItemIdFix.ITEM_NAMES.put(411, "minecraft:rabbit"); ++ ItemIdFix.ITEM_NAMES.put(412, "minecraft:cooked_rabbit"); ++ ItemIdFix.ITEM_NAMES.put(413, "minecraft:rabbit_stew"); ++ ItemIdFix.ITEM_NAMES.put(414, "minecraft:rabbit_foot"); ++ ItemIdFix.ITEM_NAMES.put(415, "minecraft:rabbit_hide"); ++ ItemIdFix.ITEM_NAMES.put(416, "minecraft:armor_stand"); ++ ++ ItemIdFix.ITEM_NAMES.put(423, "minecraft:mutton"); ++ ItemIdFix.ITEM_NAMES.put(424, "minecraft:cooked_mutton"); ++ ItemIdFix.ITEM_NAMES.put(425, "minecraft:banner"); ++ ItemIdFix.ITEM_NAMES.put(426, "minecraft:end_crystal"); ++ ItemIdFix.ITEM_NAMES.put(427, "minecraft:spruce_door"); ++ ItemIdFix.ITEM_NAMES.put(428, "minecraft:birch_door"); ++ ItemIdFix.ITEM_NAMES.put(429, "minecraft:jungle_door"); ++ ItemIdFix.ITEM_NAMES.put(430, "minecraft:acacia_door"); ++ ItemIdFix.ITEM_NAMES.put(431, "minecraft:dark_oak_door"); ++ ItemIdFix.ITEM_NAMES.put(432, "minecraft:chorus_fruit"); ++ ItemIdFix.ITEM_NAMES.put(433, "minecraft:chorus_fruit_popped"); ++ ItemIdFix.ITEM_NAMES.put(434, "minecraft:beetroot"); ++ ItemIdFix.ITEM_NAMES.put(435, "minecraft:beetroot_seeds"); ++ ItemIdFix.ITEM_NAMES.put(436, "minecraft:beetroot_soup"); ++ ItemIdFix.ITEM_NAMES.put(437, "minecraft:dragon_breath"); ++ ItemIdFix.ITEM_NAMES.put(438, "minecraft:splash_potion"); ++ ItemIdFix.ITEM_NAMES.put(439, "minecraft:spectral_arrow"); ++ ItemIdFix.ITEM_NAMES.put(440, "minecraft:tipped_arrow"); ++ ItemIdFix.ITEM_NAMES.put(441, "minecraft:lingering_potion"); ++ ItemIdFix.ITEM_NAMES.put(442, "minecraft:shield"); ++ ItemIdFix.ITEM_NAMES.put(443, "minecraft:elytra"); ++ ItemIdFix.ITEM_NAMES.put(444, "minecraft:spruce_boat"); ++ ItemIdFix.ITEM_NAMES.put(445, "minecraft:birch_boat"); ++ ItemIdFix.ITEM_NAMES.put(446, "minecraft:jungle_boat"); ++ ItemIdFix.ITEM_NAMES.put(447, "minecraft:acacia_boat"); ++ ItemIdFix.ITEM_NAMES.put(448, "minecraft:dark_oak_boat"); ++ ItemIdFix.ITEM_NAMES.put(449, "minecraft:totem_of_undying"); ++ ItemIdFix.ITEM_NAMES.put(450, "minecraft:shulker_shell"); ++ ItemIdFix.ITEM_NAMES.put(452, "minecraft:iron_nugget"); ++ ItemIdFix.ITEM_NAMES.put(453, "minecraft:knowledge_book"); ++ ++ ItemSpawnEggFix.ID_TO_ENTITY[23] = "Arrow"; ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/Main.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/Main.java.patch new file mode 100644 index 0000000000..b3319f07a7 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/Main.java.patch @@ -0,0 +1,194 @@ +--- a/net/minecraft/server/Main.java ++++ b/net/minecraft/server/Main.java +@@ -60,6 +60,14 @@ + import net.minecraft.world.level.storage.WorldData; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.google.common.base.Charsets; ++import java.io.InputStreamReader; ++import java.util.concurrent.atomic.AtomicReference; ++import net.minecraft.SharedConstants; ++import org.bukkit.configuration.file.YamlConfiguration; ++// CraftBukkit end ++ + public class Main { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -67,8 +75,9 @@ + public Main() {} + + @DontObfuscate +- public static void main(String[] astring) { ++ public static void main(final OptionSet optionset) { // CraftBukkit - replaces main(String[] astring) + SharedConstants.tryDetectVersion(); ++ /* CraftBukkit start - Replace everything + OptionParser optionparser = new OptionParser(); + OptionSpec optionspec = optionparser.accepts("nogui"); + OptionSpec optionspec1 = optionparser.accepts("initSettings", "Initializes 'server.properties' and 'eula.txt', then quits"); +@@ -93,15 +102,18 @@ + optionparser.printHelpOn(System.err); + return; + } ++ */ // CraftBukkit end + + Path path = (Path) optionset.valueOf(optionspec13); + ++ Path path = (Path) optionset.valueOf("pidFile"); // CraftBukkit ++ + if (path != null) { + writePidFile(path); + } + + CrashReport.preload(); +- if (optionset.has(optionspec12)) { ++ if (optionset.has("jfrProfile")) { // CraftBukkit + JvmProfiler.INSTANCE.start(Environment.SERVER); + } + +@@ -109,13 +121,26 @@ + Bootstrap.validate(); + Util.startTimerHackThread(); + Path path1 = Paths.get("server.properties"); +- DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(path1); ++ DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(optionset); // CraftBukkit - CLI argument support + + dedicatedserversettings.forceSave(); + Path path2 = Paths.get("eula.txt"); + Eula eula = new Eula(path2); + +- if (optionset.has(optionspec1)) { ++ if (optionset.has("initSettings")) { // CraftBukkit ++ // CraftBukkit start - SPIGOT-5761: Create bukkit.yml and commands.yml if not present ++ File configFile = (File) optionset.valueOf("bukkit-settings"); ++ YamlConfiguration configuration = YamlConfiguration.loadConfiguration(configFile); ++ configuration.options().copyDefaults(true); ++ configuration.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/bukkit.yml"), Charsets.UTF_8))); ++ configuration.save(configFile); ++ ++ File commandFile = (File) optionset.valueOf("commands-settings"); ++ YamlConfiguration commandsConfiguration = YamlConfiguration.loadConfiguration(commandFile); ++ commandsConfiguration.options().copyDefaults(true); ++ commandsConfiguration.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/commands.yml"), Charsets.UTF_8))); ++ commandsConfiguration.save(commandFile); ++ // CraftBukkit end + Main.LOGGER.info("Initialized '{}' and '{}'", path1.toAbsolutePath(), path2.toAbsolutePath()); + return; + } +@@ -125,11 +150,13 @@ + return; + } + +- File file = new File((String) optionset.valueOf(optionspec8)); ++ File file = (File) optionset.valueOf("universe"); // CraftBukkit + Services services = Services.create(new YggdrasilAuthenticationService(Proxy.NO_PROXY), file); +- String s = (String) Optional.ofNullable((String) optionset.valueOf(optionspec9)).orElse(dedicatedserversettings.getProperties().levelName); +- LevelStorageSource levelstoragesource = LevelStorageSource.createDefault(file.toPath()); +- LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess = levelstoragesource.validateAndCreateAccess(s); ++ // CraftBukkit start ++ String s = (String) Optional.ofNullable((String) optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName); ++ LevelStorageSource convertable = LevelStorageSource.createDefault(file.toPath()); ++ LevelStorageSource.LevelStorageAccess convertable_conversionsession = convertable.validateAndCreateAccess(s, LevelStem.OVERWORLD); ++ // CraftBukkit end + Dynamic dynamic; + + if (levelstoragesource_levelstorageaccess.hasWorldData()) { +@@ -170,13 +197,31 @@ + } + + Dynamic dynamic1 = dynamic; +- boolean flag = optionset.has(optionspec6); ++ boolean flag = optionset.has("safeMode"); // CraftBukkit + + if (flag) { + Main.LOGGER.warn("Safe mode active, only vanilla datapack will be loaded"); + } + +- PackRepository packrepository = ServerPacksSource.createPackRepository(levelstoragesource_levelstorageaccess); ++ PackRepository resourcepackrepository = ServerPacksSource.createPackRepository(convertable_conversionsession); ++ // CraftBukkit start ++ File bukkitDataPackFolder = new File(convertable_conversionsession.getLevelPath(LevelResource.DATAPACK_DIR).toFile(), "bukkit"); ++ if (!bukkitDataPackFolder.exists()) { ++ bukkitDataPackFolder.mkdirs(); ++ } ++ File mcMeta = new File(bukkitDataPackFolder, "pack.mcmeta"); ++ try { ++ com.google.common.io.Files.write("{\n" ++ + " \"pack\": {\n" ++ + " \"description\": \"Data pack for resources provided by Bukkit plugins\",\n" ++ + " \"pack_format\": " + SharedConstants.getCurrentVersion().getPackVersion(PackType.SERVER_DATA) + "\n" ++ + " }\n" ++ + "}\n", mcMeta, com.google.common.base.Charsets.UTF_8); ++ } catch (java.io.IOException ex) { ++ throw new RuntimeException("Could not initialize Bukkit datapack", ex); ++ } ++ AtomicReference worldLoader = new AtomicReference<>(); ++ // CraftBukkit end + + WorldStem worldstem; + +@@ -184,8 +229,9 @@ + WorldLoader.InitConfig worldloader_initconfig = loadOrCreateConfig(dedicatedserversettings.getProperties(), dynamic1, flag, packrepository); + + worldstem = (WorldStem) Util.blockUntilDone((executor) -> { +- return WorldLoader.load(worldloader_initconfig, (worldloader_dataloadcontext) -> { +- Registry registry = worldloader_dataloadcontext.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM); ++ return WorldLoader.load(worldloader_c, (worldloader_a) -> { ++ worldLoader.set(worldloader_a); // CraftBukkit ++ Registry iregistry = worldloader_a.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM); + + if (dynamic1 != null) { + LevelDataAndDimensions leveldataanddimensions = LevelStorageSource.getLevelDataAndDimensions(dynamic1, worldloader_dataloadcontext.dataConfiguration(), registry, worldloader_dataloadcontext.datapackWorldgen()); +@@ -197,16 +243,16 @@ + WorldOptions worldoptions; + WorldDimensions worlddimensions; + +- if (optionset.has(optionspec2)) { +- levelsettings = MinecraftServer.DEMO_SETTINGS; ++ if (optionset.has("demo")) { // CraftBukkit ++ worldsettings = MinecraftServer.DEMO_SETTINGS; + worldoptions = WorldOptions.DEMO_OPTIONS; + worlddimensions = WorldPresets.createNormalWorldDimensions(worldloader_dataloadcontext.datapackWorldgen()); + } else { + DedicatedServerProperties dedicatedserverproperties = dedicatedserversettings.getProperties(); + +- levelsettings = new LevelSettings(dedicatedserverproperties.levelName, dedicatedserverproperties.gamemode, dedicatedserverproperties.hardcore, dedicatedserverproperties.difficulty, false, new GameRules(), worldloader_dataloadcontext.dataConfiguration()); +- worldoptions = optionset.has(optionspec3) ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions; +- worlddimensions = dedicatedserverproperties.createDimensions(worldloader_dataloadcontext.datapackWorldgen()); ++ worldsettings = new LevelSettings(dedicatedserverproperties.levelName, dedicatedserverproperties.gamemode, dedicatedserverproperties.hardcore, dedicatedserverproperties.difficulty, false, new GameRules(), worldloader_a.dataConfiguration()); ++ worldoptions = optionset.has("bonusChest") ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions; // CraftBukkit ++ worlddimensions = dedicatedserverproperties.createDimensions(worldloader_a.datapackWorldgen()); + } + + WorldDimensions.Complete worlddimensions_complete = worlddimensions.bake(registry); +@@ -246,6 +303,7 @@ + + return dedicatedserver1; + }); ++ /* CraftBukkit start + Thread thread = new Thread("Server Shutdown Thread") { + @Override + public void run() { +@@ -255,6 +312,7 @@ + + thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(Main.LOGGER)); + Runtime.getRuntime().addShutdownHook(thread); ++ */ // CraftBukkit end + } catch (Exception exception1) { + Main.LOGGER.error(LogUtils.FATAL_MARKER, "Failed to start the minecraft server", exception1); + } +@@ -290,10 +348,10 @@ + return new WorldLoader.InitConfig(worldloader_packconfig, Commands.CommandSelection.DEDICATED, dedicatedserverproperties.functionPermissionLevel); + } + +- private static void forceUpgrade(LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess, DataFixer datafixer, boolean flag, BooleanSupplier booleansupplier, Registry registry) { +- Main.LOGGER.info("Forcing world upgrade!"); +- WorldUpgrader worldupgrader = new WorldUpgrader(levelstoragesource_levelstorageaccess, datafixer, registry, flag); +- Component component = null; ++ public static void forceUpgrade(LevelStorageSource.LevelStorageAccess levelStorage, DataFixer dataFixer, boolean eraseCache, BooleanSupplier upgradeWorld, Registry dimesions) { ++ Main.LOGGER.info("Forcing world upgrade! {}", levelStorage.getLevelId()); // CraftBukkit ++ WorldUpgrader worldupgrader = new WorldUpgrader(levelStorage, dataFixer, dimesions, eraseCache); ++ Component ichatbasecomponent = null; + + while (!worldupgrader.isFinished()) { + Component component1 = worldupgrader.getStatus(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/MinecraftServer.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/MinecraftServer.java.patch new file mode 100644 index 0000000000..3879c6d86f --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/MinecraftServer.java.patch @@ -0,0 +1,682 @@ +--- a/net/minecraft/server/MinecraftServer.java ++++ b/net/minecraft/server/MinecraftServer.java +@@ -151,6 +150,23 @@ + import net.minecraft.world.level.levelgen.WorldOptions; + import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; + import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; ++import net.minecraft.world.level.storage.WorldData; ++import net.minecraft.world.level.storage.loot.LootDataManager; ++import org.slf4j.Logger; ++ ++// CraftBukkit start ++import com.mojang.serialization.Dynamic; ++import com.mojang.serialization.Lifecycle; ++import java.util.Random; ++import jline.console.ConsoleReader; ++import joptsimple.OptionSet; ++import net.minecraft.nbt.NbtException; ++import net.minecraft.nbt.ReportedNbtException; ++import net.minecraft.server.bossevents.CustomBossEvents; ++import net.minecraft.server.dedicated.DedicatedServer; ++import net.minecraft.server.dedicated.DedicatedServerProperties; ++import net.minecraft.world.level.levelgen.WorldDimensions; ++import net.minecraft.world.level.levelgen.presets.WorldPresets; + import net.minecraft.world.level.storage.CommandStorage; + import net.minecraft.world.level.storage.DerivedLevelData; + import net.minecraft.world.level.storage.DimensionDataStorage; +@@ -163,7 +180,11 @@ + import net.minecraft.world.level.storage.loot.LootDataManager; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; +-import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.Main; ++import org.bukkit.event.server.ServerLoadEvent; ++// CraftBukkit end + + public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements ServerInfo, CommandSource, AutoCloseable { + +@@ -171,7 +192,7 @@ + public static final String VANILLA_BRAND = "vanilla"; + private static final float AVERAGE_TICK_TIME_SMOOTHING = 0.8F; + private static final int TICK_STATS_SPAN = 100; +- private static final long OVERLOADED_THRESHOLD_NANOS = 20L * TimeUtil.NANOSECONDS_PER_SECOND / 20L; ++ private static final long OVERLOADED_THRESHOLD_NANOS = 30L * TimeUtil.NANOSECONDS_PER_SECOND / 20L; // CraftBukkit + private static final int OVERLOADED_TICKS_THRESHOLD = 20; + private static final long OVERLOADED_WARNING_INTERVAL_NANOS = 10L * TimeUtil.NANOSECONDS_PER_SECOND; + private static final int OVERLOADED_TICKS_WARNING_INTERVAL = 100; +@@ -254,7 +275,20 @@ + protected final WorldData worldData; + private volatile boolean isSaving; + +- public static S spin(Function function) { ++ // CraftBukkit start ++ public final WorldLoader.a worldLoader; ++ public org.bukkit.craftbukkit.CraftServer server; ++ public OptionSet options; ++ public org.bukkit.command.ConsoleCommandSender console; ++ public ConsoleReader reader; ++ public static int currentTick = (int) (System.currentTimeMillis() / 50); ++ public java.util.Queue processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); ++ public int autosavePeriod; ++ public Commands vanillaCommandDispatcher; ++ private boolean forceTicks; ++ // CraftBukkit end ++ ++ public static S spin(Function threadFunction) { + AtomicReference atomicreference = new AtomicReference(); + Thread thread = new Thread(() -> { + ((MinecraftServer) atomicreference.get()).runServer(); +@@ -295,7 +329,7 @@ + this.customBossEvents = new CustomBossEvents(); + this.registries = worldstem.registries(); + this.worldData = worldstem.worldData(); +- if (!this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM).containsKey(LevelStem.OVERWORLD)) { ++ if (false && !this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM).containsKey(LevelStem.OVERWORLD)) { // CraftBukkit - initialised later + throw new IllegalStateException("Missing Overworld dimension data"); + } else { + this.proxy = proxy; +@@ -319,6 +353,33 @@ + this.serverThread = thread; + this.executor = Util.backgroundExecutor(); + } ++ // CraftBukkit start ++ this.options = options; ++ this.worldLoader = worldLoader; ++ this.vanillaCommandDispatcher = worldstem.dataPackResources().commands; // CraftBukkit ++ // Try to see if we're actually running in a terminal, disable jline if not ++ if (System.console() == null && System.getProperty("jline.terminal") == null) { ++ System.setProperty("jline.terminal", "jline.UnsupportedTerminal"); ++ Main.useJline = false; ++ } ++ ++ try { ++ reader = new ConsoleReader(System.in, System.out); ++ reader.setExpandEvents(false); // Avoid parsing exceptions for uncommonly used event designators ++ } catch (Throwable e) { ++ try { ++ // Try again with jline disabled for Windows users without C++ 2008 Redistributable ++ System.setProperty("jline.terminal", "jline.UnsupportedTerminal"); ++ System.setProperty("user.language", "en"); ++ Main.useJline = false; ++ reader = new ConsoleReader(System.in, System.out); ++ reader.setExpandEvents(false); ++ } catch (IOException ex) { ++ LOGGER.warn((String) null, ex); ++ } ++ } ++ Runtime.getRuntime().addShutdownHook(new org.bukkit.craftbukkit.util.ServerShutdownThread(this)); ++ // CraftBukkit end + } + + private void readScoreboard(DimensionDataStorage dimensiondatastorage) { +@@ -327,7 +388,7 @@ + + protected abstract boolean initServer() throws IOException; + +- protected void loadLevel() { ++ protected void loadLevel(String s) { // CraftBukkit + if (!JvmProfiler.INSTANCE.isRunning()) { + ; + } +@@ -335,8 +396,7 @@ + boolean flag = false; + ProfiledDuration profiledduration = JvmProfiler.INSTANCE.onWorldLoadedStarted(); + +- this.worldData.setModdedInfo(this.getServerModName(), this.getModdedStatus().shouldReportAsModified()); +- ChunkProgressListener chunkprogresslistener = this.progressListenerFactory.create(11); ++ loadWorld0(s); // CraftBukkit + + this.createLevels(chunkprogresslistener); + this.forceDifficulty(); +@@ -357,16 +414,9 @@ + + protected void forceDifficulty() {} + +- protected void createLevels(ChunkProgressListener chunkprogresslistener) { +- ServerLevelData serverleveldata = this.worldData.overworldData(); +- boolean flag = this.worldData.isDebugWorld(); +- Registry registry = this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM); +- WorldOptions worldoptions = this.worldData.worldGenOptions(); +- long i = worldoptions.seed(); +- long j = BiomeManager.obfuscateSeed(i); +- List list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(serverleveldata)); +- LevelStem levelstem = (LevelStem) registry.get(LevelStem.OVERWORLD); +- ServerLevel serverlevel = new ServerLevel(this, this.executor, this.storageSource, serverleveldata, Level.OVERWORLD, levelstem, chunkprogresslistener, flag, j, list, true, (RandomSequences) null); ++ // CraftBukkit start ++ private void loadWorld0(String s) { ++ LevelStorageSource.LevelStorageAccess worldSession = this.storageSource; + + this.levels.put(Level.OVERWORLD, serverlevel); + DimensionDataStorage dimensiondatastorage = serverlevel.getDataStorage(); +@@ -375,7 +425,207 @@ + this.commandStorage = new CommandStorage(dimensiondatastorage); + WorldBorder worldborder = serverlevel.getWorldBorder(); + +- if (!serverleveldata.isInitialized()) { ++ if (dimensionKey == LevelStem.NETHER) { ++ if (isNetherEnabled()) { ++ dimension = -1; ++ } else { ++ continue; ++ } ++ } else if (dimensionKey == LevelStem.END) { ++ if (server.getAllowEnd()) { ++ dimension = 1; ++ } else { ++ continue; ++ } ++ } else if (dimensionKey != LevelStem.OVERWORLD) { ++ dimension = -999; ++ } ++ ++ String worldType = (dimension == -999) ? dimensionKey.location().getNamespace() + "_" + dimensionKey.location().getPath() : org.bukkit.World.Environment.getEnvironment(dimension).toString().toLowerCase(); ++ String name = (dimensionKey == LevelStem.OVERWORLD) ? s : s + "_" + worldType; ++ if (dimension != 0) { ++ File newWorld = LevelStorageSource.getStorageFolder(new File(name).toPath(), dimensionKey).toFile(); ++ File oldWorld = LevelStorageSource.getStorageFolder(new File(s).toPath(), dimensionKey).toFile(); ++ File oldLevelDat = new File(new File(s), "level.dat"); // The data folders exist on first run as they are created in the PersistentCollection constructor above, but the level.dat won't ++ ++ if (!newWorld.isDirectory() && oldWorld.isDirectory() && oldLevelDat.isFile()) { ++ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder required ----"); ++ MinecraftServer.LOGGER.info("Unfortunately due to the way that Minecraft implemented multiworld support in 1.6, Bukkit requires that you move your " + worldType + " folder to a new location in order to operate correctly."); ++ MinecraftServer.LOGGER.info("We will move this folder for you, but it will mean that you need to move it back should you wish to stop using Bukkit in the future."); ++ MinecraftServer.LOGGER.info("Attempting to move " + oldWorld + " to " + newWorld + "..."); ++ ++ if (newWorld.exists()) { ++ MinecraftServer.LOGGER.warn("A file or folder already exists at " + newWorld + "!"); ++ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder failed ----"); ++ } else if (newWorld.getParentFile().mkdirs()) { ++ if (oldWorld.renameTo(newWorld)) { ++ MinecraftServer.LOGGER.info("Success! To restore " + worldType + " in the future, simply move " + newWorld + " to " + oldWorld); ++ // Migrate world data too. ++ try { ++ com.google.common.io.Files.copy(oldLevelDat, new File(new File(name), "level.dat")); ++ org.apache.commons.io.FileUtils.copyDirectory(new File(new File(s), "data"), new File(new File(name), "data")); ++ } catch (IOException exception) { ++ MinecraftServer.LOGGER.warn("Unable to migrate world data."); ++ } ++ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder complete ----"); ++ } else { ++ MinecraftServer.LOGGER.warn("Could not move folder " + oldWorld + " to " + newWorld + "!"); ++ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder failed ----"); ++ } ++ } else { ++ MinecraftServer.LOGGER.warn("Could not create path for " + newWorld + "!"); ++ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder failed ----"); ++ } ++ } ++ ++ try { ++ worldSession = LevelStorageSource.createDefault(server.getWorldContainer().toPath()).validateAndCreateAccess(name, dimensionKey); ++ } catch (IOException | ContentValidationException ex) { ++ throw new RuntimeException(ex); ++ } ++ } ++ ++ Dynamic dynamic; ++ if (worldSession.hasWorldData()) { ++ LevelSummary worldinfo; ++ ++ try { ++ dynamic = worldSession.getDataTag(); ++ worldinfo = worldSession.getSummary(dynamic); ++ } catch (NbtException | ReportedNbtException | IOException ioexception) { ++ LevelStorageSource.LevelDirectory convertable_b = worldSession.getLevelDirectory(); ++ ++ MinecraftServer.LOGGER.warn("Failed to load world data from {}", convertable_b.dataFile(), ioexception); ++ MinecraftServer.LOGGER.info("Attempting to use fallback"); ++ ++ try { ++ dynamic = worldSession.getDataTagFallback(); ++ worldinfo = worldSession.getSummary(dynamic); ++ } catch (NbtException | ReportedNbtException | IOException ioexception1) { ++ MinecraftServer.LOGGER.error("Failed to load world data from {}", convertable_b.oldDataFile(), ioexception1); ++ MinecraftServer.LOGGER.error("Failed to load world data from {} and {}. World files may be corrupted. Shutting down.", convertable_b.dataFile(), convertable_b.oldDataFile()); ++ return; ++ } ++ ++ worldSession.restoreLevelDataFromOld(); ++ } ++ ++ if (worldinfo.requiresManualConversion()) { ++ MinecraftServer.LOGGER.info("This world must be opened in an older version (like 1.6.4) to be safely converted"); ++ return; ++ } ++ ++ if (!worldinfo.isCompatible()) { ++ MinecraftServer.LOGGER.info("This world was created by an incompatible version."); ++ return; ++ } ++ } else { ++ dynamic = null; ++ } ++ ++ org.bukkit.generator.ChunkGenerator gen = this.server.getGenerator(name); ++ org.bukkit.generator.BiomeProvider biomeProvider = this.server.getBiomeProvider(name); ++ ++ PrimaryLevelData worlddata; ++ WorldLoader.a worldloader_a = this.worldLoader; ++ Registry iregistry = worldloader_a.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM); ++ if (dynamic != null) { ++ LevelDataAndDimensions leveldataanddimensions = LevelStorageSource.getLevelDataAndDimensions(dynamic, worldloader_a.dataConfiguration(), iregistry, worldloader_a.datapackWorldgen()); ++ ++ worlddata = (PrimaryLevelData) leveldataanddimensions.worldData(); ++ } else { ++ LevelSettings worldsettings; ++ WorldOptions worldoptions; ++ WorldDimensions worlddimensions; ++ ++ if (this.isDemo()) { ++ worldsettings = MinecraftServer.DEMO_SETTINGS; ++ worldoptions = WorldOptions.DEMO_OPTIONS; ++ worlddimensions = WorldPresets.createNormalWorldDimensions(worldloader_a.datapackWorldgen()); ++ } else { ++ DedicatedServerProperties dedicatedserverproperties = ((DedicatedServer) this).getProperties(); ++ ++ worldsettings = new LevelSettings(dedicatedserverproperties.levelName, dedicatedserverproperties.gamemode, dedicatedserverproperties.hardcore, dedicatedserverproperties.difficulty, false, new GameRules(), worldloader_a.dataConfiguration()); ++ worldoptions = options.has("bonusChest") ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions; ++ worlddimensions = dedicatedserverproperties.createDimensions(worldloader_a.datapackWorldgen()); ++ } ++ ++ WorldDimensions.b worlddimensions_b = worlddimensions.bake(iregistry); ++ Lifecycle lifecycle = worlddimensions_b.lifecycle().add(worldloader_a.datapackWorldgen().allRegistriesLifecycle()); ++ ++ worlddata = new PrimaryLevelData(worldsettings, worldoptions, worlddimensions_b.specialWorldProperty(), lifecycle); ++ } ++ worlddata.checkName(name); // CraftBukkit - Migration did not rewrite the level.dat; This forces 1.8 to take the last loaded world as respawn (in this case the end) ++ if (options.has("forceUpgrade")) { ++ net.minecraft.server.Main.forceUpgrade(worldSession, DataFixers.getDataFixer(), options.has("eraseCache"), () -> { ++ return true; ++ }, dimensions); ++ } ++ ++ PrimaryLevelData iworlddataserver = worlddata; ++ boolean flag = worlddata.isDebugWorld(); ++ WorldOptions worldoptions = worlddata.worldGenOptions(); ++ long i = worldoptions.seed(); ++ long j = BiomeManager.obfuscateSeed(i); ++ List list = ImmutableList.of(new MobSpawnerPhantom(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(iworlddataserver)); ++ LevelStem worlddimension = (LevelStem) dimensions.get(dimensionKey); ++ ++ org.bukkit.generator.WorldInfo worldInfo = new org.bukkit.craftbukkit.generator.CraftWorldInfo(iworlddataserver, worldSession, org.bukkit.World.Environment.getEnvironment(dimension), worlddimension.type().value()); ++ if (biomeProvider == null && gen != null) { ++ biomeProvider = gen.getDefaultBiomeProvider(worldInfo); ++ } ++ ++ ResourceKey worldKey = ResourceKey.create(Registries.DIMENSION, dimensionKey.location()); ++ ++ if (dimensionKey == LevelStem.OVERWORLD) { ++ this.worldData = worlddata; ++ this.worldData.setGameType(((DedicatedServer) this).getProperties().gamemode); // From DedicatedServer.init ++ ++ ChunkProgressListener worldloadlistener = this.progressListenerFactory.create(11); ++ ++ world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, worlddimension, worldloadlistener, flag, j, list, true, (RandomSequences) null, org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider); ++ DimensionDataStorage worldpersistentdata = world.getDataStorage(); ++ this.readScoreboard(worldpersistentdata); ++ this.server.scoreboardManager = new org.bukkit.craftbukkit.scoreboard.CraftScoreboardManager(this, world.getScoreboard()); ++ this.commandStorage = new CommandStorage(worldpersistentdata); ++ } else { ++ ChunkProgressListener worldloadlistener = this.progressListenerFactory.create(11); ++ world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, worlddimension, worldloadlistener, flag, j, ImmutableList.of(), true, this.overworld().getRandomSequences(), org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider); ++ } ++ ++ worlddata.setModdedInfo(this.getServerModName(), this.getModdedStatus().shouldReportAsModified()); ++ this.initWorld(world, worlddata, worldData, worldoptions); ++ ++ this.addLevel(world); ++ this.getPlayerList().addWorldborderListener(world); ++ ++ if (worlddata.getCustomBossEvents() != null) { ++ this.getCustomBossEvents().load(worlddata.getCustomBossEvents()); ++ } ++ } ++ this.forceDifficulty(); ++ for (ServerLevel worldserver : this.getAllLevels()) { ++ this.prepareLevels(worldserver.getChunkSource().chunkMap.progressListener, worldserver); ++ worldserver.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API ++ this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldLoadEvent(worldserver.getWorld())); ++ } ++ ++ this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.POSTWORLD); ++ this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP)); ++ this.connection.acceptConnections(); ++ } ++ ++ public void initWorld(ServerLevel worldserver, ServerLevelData iworlddataserver, WorldData saveData, WorldOptions worldoptions) { ++ boolean flag = saveData.isDebugWorld(); ++ // CraftBukkit start ++ if (worldserver.generator != null) { ++ worldserver.getWorld().getPopulators().addAll(worldserver.generator.getDefaultPopulators(worldserver.getWorld())); ++ } ++ WorldBorder worldborder = worldserver.getWorldBorder(); ++ worldborder.applySettings(iworlddataserver.getWorldBorder()); // CraftBukkit - move up so that WorldBorder is set during WorldInitEvent ++ this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldInitEvent(worldserver.getWorld())); // CraftBukkit - SPIGOT-5569: Call WorldInitEvent before any chunks are generated ++ ++ if (!iworlddataserver.isInitialized()) { + try { + setInitialSpawn(serverlevel, serverleveldata, worldoptions.generateBonusChest(), flag); + serverleveldata.setInitialized(true); +@@ -421,17 +648,30 @@ + + worldborder.applySettings(serverleveldata.getWorldBorder()); + } ++ // CraftBukkit end + + private static void setInitialSpawn(ServerLevel serverlevel, ServerLevelData serverleveldata, boolean flag, boolean flag1) { + if (flag1) { + serverleveldata.setSpawn(BlockPos.ZERO.above(80), 0.0F); + } else { +- ServerChunkCache serverchunkcache = serverlevel.getChunkSource(); +- ChunkPos chunkpos = new ChunkPos(serverchunkcache.randomState().sampler().findSpawnPosition()); +- int i = serverchunkcache.getGenerator().getSpawnHeight(serverlevel); ++ ServerChunkCache chunkproviderserver = level.getChunkSource(); ++ ChunkPos chunkcoordintpair = new ChunkPos(chunkproviderserver.randomState().sampler().findSpawnPosition()); ++ // CraftBukkit start ++ if (level.generator != null) { ++ Random rand = new Random(level.getSeed()); ++ org.bukkit.Location spawn = level.generator.getFixedSpawnLocation(level.getWorld(), rand); + +- if (i < serverlevel.getMinBuildHeight()) { +- BlockPos blockpos = chunkpos.getWorldPosition(); ++ if (spawn != null) { ++ if (spawn.getWorld() != level.getWorld()) { ++ throw new IllegalStateException("Cannot set spawn point for " + levelData.getLevelName() + " to be in another world (" + spawn.getWorld().getName() + ")"); ++ } else { ++ levelData.setSpawn(new BlockPos(spawn.getBlockX(), spawn.getBlockY(), spawn.getBlockZ()), spawn.getYaw()); ++ return; ++ } ++ } ++ } ++ // CraftBukkit end ++ int i = chunkproviderserver.getGenerator().getSpawnHeight(level); + + i = serverlevel.getHeight(Heightmap.Types.WORLD_SURFACE, blockpos.getX() + 8, blockpos.getZ() + 8); + } +@@ -487,8 +730,11 @@ + serverleveldata.setGameType(GameType.SPECTATOR); + } + +- private void prepareLevels(ChunkProgressListener chunkprogresslistener) { +- ServerLevel serverlevel = this.overworld(); ++ // CraftBukkit start ++ public void prepareLevels(ChunkProgressListener worldloadlistener, ServerLevel worldserver) { ++ // WorldServer worldserver = this.overworld(); ++ this.forceTicks = true; ++ // CraftBukkit end + + MinecraftServer.LOGGER.info("Preparing start region for dimension {}", serverlevel.dimension().location()); + BlockPos blockpos = serverlevel.getSharedSpawnPos(); +@@ -497,7 +743,9 @@ + ServerChunkCache serverchunkcache = serverlevel.getChunkSource(); + + this.nextTickTimeNanos = Util.getNanos(); +- serverchunkcache.addRegionTicket(TicketType.START, new ChunkPos(blockpos), 11, Unit.INSTANCE); ++ // CraftBukkit start ++ if (worldserver.getWorld().getKeepSpawnInMemory()) { ++ chunkproviderserver.addRegionTicket(TicketType.START, new ChunkPos(blockposition), 11, Unit.INSTANCE); + + while (serverchunkcache.getTickingGenerated() != 441) { + this.nextTickTimeNanos = Util.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; +@@ -508,9 +757,10 @@ + this.waitUntilNextTick(); + Iterator iterator = this.levels.values().iterator(); + +- while (iterator.hasNext()) { +- ServerLevel serverlevel1 = (ServerLevel) iterator.next(); +- ForcedChunksSavedData forcedchunkssaveddata = (ForcedChunksSavedData) serverlevel1.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks"); ++ if (true) { ++ ServerLevel worldserver1 = worldserver; ++ // CraftBukkit end ++ ForcedChunksSavedData forcedchunk = (ForcedChunksSavedData) worldserver1.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks"); + + if (forcedchunkssaveddata != null) { + LongIterator longiterator = forcedchunkssaveddata.getChunks().iterator(); +@@ -524,10 +774,17 @@ + } + } + +- this.nextTickTimeNanos = Util.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; +- this.waitUntilNextTick(); +- chunkprogresslistener.stop(); +- this.updateMobSpawningFlags(); ++ // CraftBukkit start ++ // this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; ++ this.executeModerately(); ++ // CraftBukkit end ++ worldloadlistener.stop(); ++ // CraftBukkit start ++ // this.updateMobSpawningFlags(); ++ worldserver.setSpawnSettings(this.isSpawningMonsters(), this.isSpawningAnimals()); ++ ++ this.forceTicks = false; ++ // CraftBukkit end + } + + public GameType getDefaultGameType() { +@@ -557,13 +814,17 @@ + serverlevel.save((ProgressListener) null, flag1, serverlevel.noSave && !flag2); + } + +- ServerLevel serverlevel1 = this.overworld(); +- ServerLevelData serverleveldata = this.worldData.overworldData(); ++ // CraftBukkit start - moved to WorldServer.save ++ /* ++ WorldServer worldserver1 = this.overworld(); ++ IWorldDataServer iworlddataserver = this.worldData.overworldData(); + + serverleveldata.setWorldBorder(serverlevel1.getWorldBorder().createSettings()); + this.worldData.setCustomBossEvents(this.getCustomBossEvents().save()); + this.storageSource.saveDataTag(this.registryAccess(), this.worldData, this.getPlayerList().getSingleplayerData()); +- if (flag1) { ++ */ ++ // CraftBukkit end ++ if (flush) { + Iterator iterator1 = this.getAllLevels().iterator(); + + while (iterator1.hasNext()) { +@@ -598,18 +858,40 @@ + this.stopServer(); + } + ++ // CraftBukkit start ++ private boolean hasStopped = false; ++ private final Object stopLock = new Object(); ++ public final boolean hasStopped() { ++ synchronized (stopLock) { ++ return hasStopped; ++ } ++ } ++ // CraftBukkit end ++ + public void stopServer() { ++ // CraftBukkit start - prevent double stopping on multiple threads ++ synchronized(stopLock) { ++ if (hasStopped) return; ++ hasStopped = true; ++ } ++ // CraftBukkit end + if (this.metricsRecorder.isRecording()) { + this.cancelRecordingMetrics(); + } + + MinecraftServer.LOGGER.info("Stopping server"); ++ // CraftBukkit start ++ if (this.server != null) { ++ this.server.disablePlugins(); ++ } ++ // CraftBukkit end + this.getConnection().stop(); + this.isSaving = true; + if (this.playerList != null) { + MinecraftServer.LOGGER.info("Saving players"); + this.playerList.saveAll(); + this.playerList.removeAll(); ++ try { Thread.sleep(100); } catch (InterruptedException ex) {} // CraftBukkit - SPIGOT-625 - give server at least a chance to send packets + } + + MinecraftServer.LOGGER.info("Saving worlds"); +@@ -714,6 +996,7 @@ + if (j > MinecraftServer.OVERLOADED_THRESHOLD_NANOS + 20L * i && this.nextTickTimeNanos - this.lastOverloadWarningNanos >= MinecraftServer.OVERLOADED_WARNING_INTERVAL_NANOS + 100L * i) { + long k = j / i; + ++ if (server.getWarnOnOverload()) // CraftBukkit + MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", j / TimeUtil.NANOSECONDS_PER_MILLISECOND, k); + this.nextTickTimeNanos += k * i; + this.lastOverloadWarningNanos = this.nextTickTimeNanos; +@@ -727,6 +1010,7 @@ + this.debugCommandProfiler = new MinecraftServer.TimeProfiler(Util.getNanos(), this.tickCount); + } + ++ MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit + this.nextTickTimeNanos += i; + this.startMetricsRecordingTick(); + this.profiler.push("tick"); +@@ -771,6 +1055,12 @@ + this.services.profileCache().clearExecutor(); + } + ++ // CraftBukkit start - Restore terminal to original settings ++ try { ++ reader.getTerminal().restore(); ++ } catch (Exception ignored) { ++ } ++ // CraftBukkit end + this.onServerExit(); + } + +@@ -804,9 +1094,16 @@ + } + + private boolean haveTime() { +- return this.runningTask() || Util.getNanos() < (this.mayHaveDelayedTasks ? this.delayedTasksMaxNextTickTimeNanos : this.nextTickTimeNanos); ++ // CraftBukkit start ++ return this.forceTicks || this.runningTask() || Util.getNanos() < (this.mayHaveDelayedTasks ? this.delayedTasksMaxNextTickTimeNanos : this.nextTickTimeNanos); + } + ++ private void executeModerately() { ++ this.runAllTasks(); ++ java.util.concurrent.locks.LockSupport.parkNanos("executing tasks", 1000L); ++ // CraftBukkit end ++ } ++ + protected void waitUntilNextTick() { + this.runAllTasks(); + this.managedBlock(() -> { +@@ -914,8 +1207,10 @@ + } + + --this.ticksUntilAutosave; +- if (this.ticksUntilAutosave <= 0) { +- this.ticksUntilAutosave = this.computeNextAutosaveInterval(); ++ // CraftBukkit start ++ if (this.autosavePeriod > 0 && this.ticksUntilAutosave <= 0) { ++ this.ticksUntilAutosave = this.autosavePeriod; ++ // CraftBukkit end + MinecraftServer.LOGGER.debug("Autosave started"); + this.profiler.push("save"); + this.saveEverything(true, false, false); +@@ -996,11 +1291,26 @@ + this.getPlayerList().getPlayers().forEach((serverplayer) -> { + serverplayer.connection.suspendFlushing(); + }); ++ this.server.getScheduler().mainThreadHeartbeat(this.tickCount); // CraftBukkit + this.profiler.push("commandFunctions"); + this.getFunctions().tick(); + this.profiler.popPush("levels"); + Iterator iterator = this.getAllLevels().iterator(); + ++ // CraftBukkit start ++ // Run tasks that are waiting on processing ++ while (!processQueue.isEmpty()) { ++ processQueue.remove().run(); ++ } ++ ++ // Send time updates to everyone, it will get the right time from the world the player is in. ++ if (this.tickCount % 20 == 0) { ++ for (int i = 0; i < this.getPlayerList().players.size(); ++i) { ++ ServerPlayer entityplayer = (ServerPlayer) this.getPlayerList().players.get(i); ++ entityplayer.connection.send(new ClientboundSetTimePacket(entityplayer.level().getGameTime(), entityplayer.getPlayerTime(), entityplayer.level().getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); // Add support for per player time ++ } ++ } ++ + while (iterator.hasNext()) { + ServerLevel serverlevel = (ServerLevel) iterator.next(); + +@@ -1012,6 +1323,7 @@ + this.synchronizeTime(serverlevel); + this.profiler.pop(); + } ++ // CraftBukkit end */ + + this.profiler.push("tick"); + +@@ -1101,6 +1413,22 @@ + return (ServerLevel) this.levels.get(resourcekey); + } + ++ // CraftBukkit start ++ public void addLevel(ServerLevel level) { ++ Map, ServerLevel> oldLevels = this.levels; ++ Map, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels); ++ newLevels.put(level.dimension(), level); ++ this.levels = Collections.unmodifiableMap(newLevels); ++ } ++ ++ public void removeLevel(ServerLevel level) { ++ Map, ServerLevel> oldLevels = this.levels; ++ Map, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels); ++ newLevels.remove(level.dimension()); ++ this.levels = Collections.unmodifiableMap(newLevels); ++ } ++ // CraftBukkit end ++ + public Set> levelKeys() { + return this.levels.keySet(); + } +@@ -1133,7 +1458,7 @@ + + @DontObfuscate + public String getServerModName() { +- return "vanilla"; ++ return server.getName(); // CraftBukkit - cb > vanilla! + } + + public SystemReport fillSystemReport(SystemReport systemreport) { +@@ -1920,6 +2237,22 @@ + + } + ++ // CraftBukkit start ++ @Override ++ public boolean isSameThread() { ++ return super.isSameThread() || this.isStopped(); // CraftBukkit - MC-142590 ++ } ++ ++ public boolean isDebugging() { ++ return false; ++ } ++ ++ @Deprecated ++ public static MinecraftServer getServer() { ++ return (Bukkit.getServer() instanceof CraftServer) ? ((CraftServer) Bukkit.getServer()).getServer() : null; ++ } ++ // CraftBukkit end ++ + private void startMetricsRecordingTick() { + if (this.willStartRecordingMetrics) { + this.metricsRecorder = ActiveMetricsRecorder.createStarted(new ServerMetricsSamplersProvider(Util.timeSource, this.isDedicatedServer()), Util.timeSource, Util.ioPool(), new MetricsPersister("server"), this.onMetricsRecordingStopped, (path) -> { +@@ -2046,6 +2379,11 @@ + + } + ++ // CraftBukkit start ++ public final java.util.concurrent.ExecutorService chatExecutor = java.util.concurrent.Executors.newCachedThreadPool( ++ new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon(true).setNameFormat("Async Chat Thread - #%d").build()); ++ // CraftBukkit end ++ + public ChatDecorator getChatDecorator() { + return ChatDecorator.PLAIN; + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/PlayerAdvancements.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/PlayerAdvancements.java.patch new file mode 100644 index 0000000000..51cacd75d0 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/PlayerAdvancements.java.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/server/PlayerAdvancements.java ++++ b/net/minecraft/server/PlayerAdvancements.java +@@ -196,7 +196,8 @@ + AdvancementHolder advancementholder = serveradvancementmanager.get(resourcelocation); + + if (advancementholder == null) { +- PlayerAdvancements.LOGGER.warn("Ignored advancement '{}' in progress file {} - it doesn't exist anymore?", resourcelocation, this.playerSavePath); ++ if (!minecraftkey.getNamespace().equals("minecraft")) return; // CraftBukkit ++ PlayerAdvancements.LOGGER.warn("Ignored advancement '{}' in progress file {} - it doesn't exist anymore?", minecraftkey, this.playerSavePath); + } else { + this.startProgress(advancementholder, advancementprogress); + this.progressChanged.add(advancementholder); +@@ -227,6 +228,7 @@ + this.progressChanged.add(advancementholder); + flag = true; + if (!flag1 && advancementprogress.isDone()) { ++ this.player.level().getCraftServer().getPluginManager().callEvent(new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancementholder.toBukkit())); // CraftBukkit + advancementholder.value().rewards().grant(this.player); + advancementholder.value().display().ifPresent((displayinfo) -> { + if (displayinfo.shouldAnnounceChat() && this.player.level().getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/ServerAdvancementManager.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/ServerAdvancementManager.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/ServerAdvancementManager.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/ServerFunctionManager.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/ServerFunctionManager.java.patch new file mode 100644 index 0000000000..f9706cc8ca --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/ServerFunctionManager.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/server/ServerFunctionManager.java ++++ b/net/minecraft/server/ServerFunctionManager.java +@@ -37,7 +36,7 @@ + } + + public CommandDispatcher getDispatcher() { +- return this.server.getCommands().getDispatcher(); ++ return this.server.vanillaCommandDispatcher.getDispatcher(); // CraftBukkit + } + + public void tick() { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/ServerScoreboard.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/ServerScoreboard.java.patch new file mode 100644 index 0000000000..73ccec84ac --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/ServerScoreboard.java.patch @@ -0,0 +1,176 @@ +--- a/net/minecraft/server/ServerScoreboard.java ++++ b/net/minecraft/server/ServerScoreboard.java +@@ -37,11 +37,10 @@ + } + + @Override +- @Override +- protected void onScoreChanged(ScoreHolder scoreholder, Objective objective, Score score) { +- super.onScoreChanged(scoreholder, objective, score); +- if (this.trackedObjectives.contains(objective)) { +- this.server.getPlayerList().broadcastAll(new ClientboundSetScorePacket(scoreholder.getScoreboardName(), objective.getName(), score.value(), score.display(), score.numberFormat())); ++ protected void onScoreChanged(ScoreHolder scoreholder, Objective scoreboardobjective, Score scoreboardscore) { ++ super.onScoreChanged(scoreholder, scoreboardobjective, scoreboardscore); ++ if (this.trackedObjectives.contains(scoreboardobjective)) { ++ this.broadcastAll(new ClientboundSetScorePacket(scoreholder.getScoreboardName(), scoreboardobjective.getName(), scoreboardscore.value(), scoreboardscore.display(), scoreboardscore.numberFormat())); // CraftBukkit + } + + this.setDirty(); +@@ -58,16 +55,15 @@ + @Override + public void onPlayerRemoved(ScoreHolder scoreholder) { + super.onPlayerRemoved(scoreholder); +- this.server.getPlayerList().broadcastAll(new ClientboundResetScorePacket(scoreholder.getScoreboardName(), (String) null)); ++ this.broadcastAll(new ClientboundResetScorePacket(scoreholder.getScoreboardName(), (String) null)); // CraftBukkit + this.setDirty(); + } + + @Override +- @Override +- public void onPlayerScoreRemoved(ScoreHolder scoreholder, Objective objective) { +- super.onPlayerScoreRemoved(scoreholder, objective); +- if (this.trackedObjectives.contains(objective)) { +- this.server.getPlayerList().broadcastAll(new ClientboundResetScorePacket(scoreholder.getScoreboardName(), objective.getName())); ++ public void onPlayerScoreRemoved(ScoreHolder scoreholder, Objective scoreboardobjective) { ++ super.onPlayerScoreRemoved(scoreholder, scoreboardobjective); ++ if (this.trackedObjectives.contains(scoreboardobjective)) { ++ this.broadcastAll(new ClientboundResetScorePacket(scoreholder.getScoreboardName(), scoreboardobjective.getName())); // CraftBukkit + } + + this.setDirty(); +@@ -78,18 +73,18 @@ + public void setDisplayObjective(DisplaySlot displayslot, @Nullable Objective objective) { + Objective objective1 = this.getDisplayObjective(displayslot); + +- super.setDisplayObjective(displayslot, objective); +- if (objective1 != objective && objective1 != null) { +- if (this.getObjectiveDisplaySlotCount(objective1) > 0) { +- this.server.getPlayerList().broadcastAll(new ClientboundSetDisplayObjectivePacket(displayslot, objective)); ++ super.setDisplayObjective(displayslot, scoreboardobjective); ++ if (scoreboardobjective1 != scoreboardobjective && scoreboardobjective1 != null) { ++ if (this.getObjectiveDisplaySlotCount(scoreboardobjective1) > 0) { ++ this.broadcastAll(new ClientboundSetDisplayObjectivePacket(displayslot, scoreboardobjective)); // CraftBukkit + } else { + this.stopTrackingObjective(objective1); + } + } + +- if (objective != null) { +- if (this.trackedObjectives.contains(objective)) { +- this.server.getPlayerList().broadcastAll(new ClientboundSetDisplayObjectivePacket(displayslot, objective)); ++ if (scoreboardobjective != null) { ++ if (this.trackedObjectives.contains(scoreboardobjective)) { ++ this.broadcastAll(new ClientboundSetDisplayObjectivePacket(displayslot, scoreboardobjective)); // CraftBukkit + } else { + this.startTrackingObjective(objective); + } +@@ -99,10 +94,9 @@ + } + + @Override +- @Override +- public boolean addPlayerToTeam(String s, PlayerTeam playerteam) { +- if (super.addPlayerToTeam(s, playerteam)) { +- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(playerteam, s, ClientboundSetPlayerTeamPacket.Action.ADD)); ++ public boolean addPlayerToTeam(String playerName, PlayerTeam team) { ++ if (super.addPlayerToTeam(playerName, team)) { ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(team, playerName, ClientboundSetPlayerTeamPacket.a.ADD)); // CraftBukkit + this.setDirty(); + return true; + } else { +@@ -111,10 +105,9 @@ + } + + @Override +- @Override +- public void removePlayerFromTeam(String s, PlayerTeam playerteam) { +- super.removePlayerFromTeam(s, playerteam); +- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(playerteam, s, ClientboundSetPlayerTeamPacket.Action.REMOVE)); ++ public void removePlayerFromTeam(String username, PlayerTeam playerTeam) { ++ super.removePlayerFromTeam(username, playerTeam); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(playerTeam, username, ClientboundSetPlayerTeamPacket.a.REMOVE)); // CraftBukkit + this.setDirty(); + } + +@@ -130,7 +121,7 @@ + public void onObjectiveChanged(Objective objective) { + super.onObjectiveChanged(objective); + if (this.trackedObjectives.contains(objective)) { +- this.server.getPlayerList().broadcastAll(new ClientboundSetObjectivePacket(objective, 2)); ++ this.broadcastAll(new ClientboundSetObjectivePacket(objective, 2)); // CraftBukkit + } + + this.setDirty(); +@@ -148,26 +138,23 @@ + } + + @Override +- @Override +- public void onTeamAdded(PlayerTeam playerteam) { +- super.onTeamAdded(playerteam); +- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerteam, true)); ++ public void onTeamAdded(PlayerTeam playerTeam) { ++ super.onTeamAdded(playerTeam); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, true)); // CraftBukkit + this.setDirty(); + } + + @Override +- @Override +- public void onTeamChanged(PlayerTeam playerteam) { +- super.onTeamChanged(playerteam); +- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerteam, false)); ++ public void onTeamChanged(PlayerTeam playerTeam) { ++ super.onTeamChanged(playerTeam); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, false)); // CraftBukkit + this.setDirty(); + } + + @Override +- @Override +- public void onTeamRemoved(PlayerTeam playerteam) { +- super.onTeamRemoved(playerteam); +- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createRemovePacket(playerteam)); ++ public void onTeamRemoved(PlayerTeam playerTeam) { ++ super.onTeamRemoved(playerTeam); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createRemovePacket(playerTeam)); // CraftBukkit + this.setDirty(); + } + +@@ -217,7 +204,8 @@ + Iterator iterator = this.server.getPlayerList().getPlayers().iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board + Iterator iterator1 = list.iterator(); + + while (iterator1.hasNext()) { +@@ -253,7 +241,8 @@ + Iterator iterator = this.server.getPlayerList().getPlayers().iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board + Iterator iterator1 = list.iterator(); + + while (iterator1.hasNext()) { +@@ -298,7 +287,15 @@ + return this.createData().load(compoundtag); + } + +- public static enum Method { ++ // CraftBukkit start - Send to players ++ private void broadcastAll(Packet packet) { ++ for (ServerPlayer entityplayer : (List) this.server.getPlayerList().players) { ++ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() == this) { ++ entityplayer.connection.send(packet); ++ } ++ } ++ } ++ // CraftBukkit end + + CHANGE, REMOVE; + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/ServerTickRateManager.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/ServerTickRateManager.java.patch new file mode 100644 index 0000000000..ba057f3e79 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/ServerTickRateManager.java.patch @@ -0,0 +1,53 @@ +--- a/net/minecraft/server/ServerTickRateManager.java ++++ b/net/minecraft/server/ServerTickRateManager.java +@@ -60,8 +59,14 @@ + } + + public boolean stopSprinting() { ++ // CraftBukkit start, add sendLog parameter ++ return stopSprinting(true); ++ } ++ ++ public boolean stopSprinting(boolean sendLog) { ++ // CraftBukkit end + if (this.remainingSprintTicks > 0L) { +- this.finishTickSprint(); ++ this.finishTickSprint(sendLog); // CraftBukkit - add sendLog parameter + return true; + } else { + return false; +@@ -79,7 +84,7 @@ + return flag; + } + +- private void finishTickSprint() { ++ private void finishTickSprint(boolean sendLog) { // CraftBukkit - add sendLog parameter + long i = this.scheduledCurrentSprintTicks - this.remainingSprintTicks; + double d0 = Math.max(1.0D, (double) this.sprintTimeSpend) / (double) TimeUtil.NANOSECONDS_PER_MILLISECOND; + int j = (int) ((double) (TimeUtil.MILLISECONDS_PER_SECOND * i) / d0); +@@ -87,9 +92,13 @@ + + this.scheduledCurrentSprintTicks = 0L; + this.sprintTimeSpend = 0L; +- this.server.createCommandSourceStack().sendSuccess(() -> { +- return Component.translatable("commands.tick.sprint.report", j, s); +- }, true); ++ // CraftBukkit start - add sendLog parameter ++ if (sendLog) { ++ this.server.createCommandSourceStack().sendSuccess(() -> { ++ return Component.translatable("commands.tick.sprint.report", j, s); ++ }, true); ++ } ++ // CraftBukkit end + this.remainingSprintTicks = 0L; + this.setFrozen(this.previousIsFrozen); + this.server.onTickRateChanged(); +@@ -103,7 +112,7 @@ + --this.remainingSprintTicks; + return true; + } else { +- this.finishTickSprint(); ++ this.finishTickSprint(true); // CraftBukkit - add sendLog parameter + return false; + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/bossevents/CustomBossEvent.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/bossevents/CustomBossEvent.java.patch new file mode 100644 index 0000000000..ef8a8c4064 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/bossevents/CustomBossEvent.java.patch @@ -0,0 +1,37 @@ +--- a/net/minecraft/server/bossevents/CustomBossEvent.java ++++ b/net/minecraft/server/bossevents/CustomBossEvent.java +@@ -17,6 +17,10 @@ + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.Mth; + import net.minecraft.world.BossEvent; ++// CraftBukkit start ++import org.bukkit.boss.KeyedBossBar; ++import org.bukkit.craftbukkit.boss.CraftKeyedBossbar; ++// CraftBukkit end + + public class CustomBossEvent extends ServerBossEvent { + +@@ -24,10 +28,20 @@ + private final Set players = Sets.newHashSet(); + private int value; + private int max = 100; ++ // CraftBukkit start ++ private KeyedBossBar bossBar; + +- public CustomBossEvent(ResourceLocation resourcelocation, Component component) { +- super(component, BossEvent.BossBarColor.WHITE, BossEvent.BossBarOverlay.PROGRESS); +- this.id = resourcelocation; ++ public KeyedBossBar getBukkitEntity() { ++ if (bossBar == null) { ++ bossBar = new CraftKeyedBossbar(this); ++ } ++ return bossBar; ++ } ++ // CraftBukkit end ++ ++ public CustomBossEvent(ResourceLocation id, Component name) { ++ super(name, BossEvent.BossBarColor.WHITE, BossEvent.BossBarOverlay.PROGRESS); ++ this.id = id; + this.setProgress(0.0F); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/DifficultyCommand.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/DifficultyCommand.java.patch new file mode 100644 index 0000000000..9781bb1783 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/DifficultyCommand.java.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/server/commands/DifficultyCommand.java ++++ b/net/minecraft/server/commands/DifficultyCommand.java +@@ -43,14 +42,15 @@ + })); + } + +- public static int setDifficulty(CommandSourceStack commandsourcestack, Difficulty difficulty) throws CommandSyntaxException { +- MinecraftServer minecraftserver = commandsourcestack.getServer(); ++ public static int setDifficulty(CommandSourceStack source, Difficulty difficulty) throws CommandSyntaxException { ++ MinecraftServer minecraftserver = source.getServer(); ++ net.minecraft.server.level.ServerLevel worldServer = source.getLevel(); // CraftBukkit + +- if (minecraftserver.getWorldData().getDifficulty() == difficulty) { ++ if (worldServer.getDifficulty() == difficulty) { // CraftBukkit + throw DifficultyCommand.ERROR_ALREADY_DIFFICULT.create(difficulty.getKey()); + } else { +- minecraftserver.setDifficulty(difficulty, true); +- commandsourcestack.sendSuccess(() -> { ++ worldServer.serverLevelData.setDifficulty(difficulty); // CraftBukkit ++ source.sendSuccess(() -> { + return Component.translatable("commands.difficulty.success", difficulty.getDisplayName()); + }, true); + return 0; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/EffectCommands.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/EffectCommands.java.patch new file mode 100644 index 0000000000..98d850e86a --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/EffectCommands.java.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/server/commands/EffectCommands.java ++++ b/net/minecraft/server/commands/EffectCommands.java +@@ -85,7 +84,7 @@ + if (entity instanceof LivingEntity) { + MobEffectInstance mobeffectinstance = new MobEffectInstance(mobeffect, k, i, false, flag); + +- if (((LivingEntity) entity).addEffect(mobeffectinstance, commandsourcestack.getEntity())) { ++ if (((LivingEntity) entity).addEffect(mobeffect, source.getEntity(), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.COMMAND)) { // CraftBukkit + ++j; + } + } +@@ -115,7 +114,7 @@ + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); + +- if (entity instanceof LivingEntity && ((LivingEntity) entity).removeAllEffects()) { ++ if (entity instanceof LivingEntity && ((LivingEntity) entity).removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.COMMAND)) { // CraftBukkit + ++i; + } + } +@@ -145,7 +144,7 @@ + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); + +- if (entity instanceof LivingEntity && ((LivingEntity) entity).removeEffect(mobeffect)) { ++ if (entity instanceof LivingEntity && ((LivingEntity) entity).removeEffect(mobeffectlist, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.COMMAND)) { // CraftBukkit + ++i; + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/GameRuleCommand.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/GameRuleCommand.java.patch new file mode 100644 index 0000000000..f87d54ce97 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/GameRuleCommand.java.patch @@ -0,0 +1,26 @@ +--- a/net/minecraft/server/commands/GameRuleCommand.java ++++ b/net/minecraft/server/commands/GameRuleCommand.java +@@ -31,9 +29,9 @@ + commanddispatcher.register(literalargumentbuilder); + } + +- static > int setRule(CommandContext commandcontext, GameRules.Key gamerules_key) { +- CommandSourceStack commandsourcestack = (CommandSourceStack) commandcontext.getSource(); +- T t0 = commandsourcestack.getServer().getGameRules().getRule(gamerules_key); ++ static > int setRule(CommandContext source, GameRules.Key gameRule) { ++ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) source.getSource(); ++ T t0 = commandlistenerwrapper.getLevel().getGameRules().getRule(gameRule); // CraftBukkit + + t0.setFromArgument(commandcontext, "value"); + commandsourcestack.sendSuccess(() -> { +@@ -42,8 +40,8 @@ + return t0.getCommandResult(); + } + +- static > int queryRule(CommandSourceStack commandsourcestack, GameRules.Key gamerules_key) { +- T t0 = commandsourcestack.getServer().getGameRules().getRule(gamerules_key); ++ static > int queryRule(CommandSourceStack source, GameRules.Key gameRule) { ++ T t0 = source.getLevel().getGameRules().getRule(gameRule); // CraftBukkit + + commandsourcestack.sendSuccess(() -> { + return Component.translatable("commands.gamerule.query", gamerules_key.getId(), t0.toString()); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/GiveCommand.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/GiveCommand.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/GiveCommand.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/ListPlayersCommand.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/ListPlayersCommand.java.patch new file mode 100644 index 0000000000..da16b8ee43 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/ListPlayersCommand.java.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/server/commands/ListPlayersCommand.java ++++ b/net/minecraft/server/commands/ListPlayersCommand.java +@@ -34,10 +33,17 @@ + }); + } + +- private static int format(CommandSourceStack commandsourcestack, Function function) { +- PlayerList playerlist = commandsourcestack.getServer().getPlayerList(); +- List list = playerlist.getPlayers(); +- Component component = ComponentUtils.formatList(list, function); ++ private static int format(CommandSourceStack source, Function nameExtractor) { ++ PlayerList playerlist = source.getServer().getPlayerList(); ++ // CraftBukkit start ++ List players = playerlist.getPlayers(); ++ if (source.getBukkitSender() instanceof org.bukkit.entity.Player) { ++ org.bukkit.entity.Player sender = (org.bukkit.entity.Player) source.getBukkitSender(); ++ players = players.stream().filter((ep) -> sender.canSee(ep.getBukkitEntity())).collect(java.util.stream.Collectors.toList()); ++ } ++ List list = players; ++ // CraftBukkit end ++ Component ichatbasecomponent = ComponentUtils.formatList(list, nameExtractor); + + commandsourcestack.sendSuccess(() -> { + return Component.translatable("commands.list.players", list.size(), playerlist.getMaxPlayers(), component); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/LootCommand.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/LootCommand.java.patch new file mode 100644 index 0000000000..0f00292435 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/LootCommand.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/server/commands/LootCommand.java ++++ b/net/minecraft/server/commands/LootCommand.java +@@ -248,8 +247,9 @@ + private static int dropInWorld(CommandSourceStack commandsourcestack, Vec3 vec3, List list, LootCommand.Callback lootcommand_callback) throws CommandSyntaxException { + ServerLevel serverlevel = commandsourcestack.getLevel(); + +- list.forEach((itemstack) -> { +- ItemEntity itementity = new ItemEntity(serverlevel, vec3.x, vec3.y, vec3.z, itemstack.copy()); ++ items.removeIf(ItemStack::isEmpty); // CraftBukkit - SPIGOT-6959 Remove empty items for avoid throw an error in new EntityItem ++ items.forEach((itemstack) -> { ++ ItemEntity entityitem = new ItemEntity(worldserver, pos.x, pos.y, pos.z, itemstack.copy()); + + itementity.setDefaultPickUpDelay(); + serverlevel.addFreshEntity(itementity); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/PlaceCommand.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/PlaceCommand.java.patch new file mode 100644 index 0000000000..7df5e5ebb8 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/PlaceCommand.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/server/commands/PlaceCommand.java ++++ b/net/minecraft/server/commands/PlaceCommand.java +@@ -131,9 +130,10 @@ + if (!structurestart.isValid()) { + throw PlaceCommand.ERROR_STRUCTURE_FAILED.create(); + } else { +- BoundingBox boundingbox = structurestart.getBoundingBox(); +- ChunkPos chunkpos = new ChunkPos(SectionPos.blockToSectionCoord(boundingbox.minX()), SectionPos.blockToSectionCoord(boundingbox.minZ())); +- ChunkPos chunkpos1 = new ChunkPos(SectionPos.blockToSectionCoord(boundingbox.maxX()), SectionPos.blockToSectionCoord(boundingbox.maxZ())); ++ structurestart.generationEventCause = org.bukkit.event.world.AsyncStructureGenerateEvent.Cause.COMMAND; // CraftBukkit - set AsyncStructureGenerateEvent.Cause.COMMAND as generation cause ++ BoundingBox structureboundingbox = structurestart.getBoundingBox(); ++ ChunkPos chunkcoordintpair = new ChunkPos(SectionPos.blockToSectionCoord(structureboundingbox.minX()), SectionPos.blockToSectionCoord(structureboundingbox.minZ())); ++ ChunkPos chunkcoordintpair1 = new ChunkPos(SectionPos.blockToSectionCoord(structureboundingbox.maxX()), SectionPos.blockToSectionCoord(structureboundingbox.maxZ())); + + checkLoaded(serverlevel, chunkpos, chunkpos1); + ChunkPos.rangeClosed(chunkpos, chunkpos1).forEach((chunkpos2) -> { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/ReloadCommand.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/ReloadCommand.java.patch new file mode 100644 index 0000000000..ebd0f16eed --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/ReloadCommand.java.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/server/commands/ReloadCommand.java ++++ b/net/minecraft/server/commands/ReloadCommand.java +@@ -45,9 +44,19 @@ + return collection1; + } + +- public static void register(CommandDispatcher commanddispatcher) { +- commanddispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) Commands.literal("reload").requires((commandsourcestack) -> { +- return commandsourcestack.hasPermission(2); ++ // CraftBukkit start ++ public static void reload(MinecraftServer minecraftserver) { ++ PackRepository resourcepackrepository = minecraftserver.getPackRepository(); ++ WorldData savedata = minecraftserver.getWorldData(); ++ Collection collection = resourcepackrepository.getSelectedIds(); ++ Collection collection1 = discoverNewPacks(resourcepackrepository, savedata, collection); ++ minecraftserver.reloadResources(collection1); ++ } ++ // CraftBukkit end ++ ++ public static void register(CommandDispatcher dispatcher) { ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("reload").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); + })).executes((commandcontext) -> { + CommandSourceStack commandsourcestack = (CommandSourceStack) commandcontext.getSource(); + MinecraftServer minecraftserver = commandsourcestack.getServer(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/ScheduleCommand.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/ScheduleCommand.java.patch new file mode 100644 index 0000000000..f34503edd1 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/ScheduleCommand.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/server/commands/ScheduleCommand.java ++++ b/net/minecraft/server/commands/ScheduleCommand.java +@@ -55,9 +53,9 @@ + if (i == 0) { + throw ScheduleCommand.ERROR_SAME_TICK.create(); + } else { +- long j = commandsourcestack.getLevel().getGameTime() + (long) i; +- ResourceLocation resourcelocation = (ResourceLocation) pair.getFirst(); +- TimerQueue timerqueue = commandsourcestack.getServer().getWorldData().overworldData().getScheduledEvents(); ++ long j = source.getLevel().getGameTime() + (long) time; ++ ResourceLocation minecraftkey = (ResourceLocation) function.getFirst(); ++ TimerQueue customfunctioncallbacktimerqueue = source.getLevel().serverLevelData.overworldData().getScheduledEvents(); // CraftBukkit - SPIGOT-6667: Use world specific function timer + + ((Either) pair.getSecond()).ifLeft((commandfunction) -> { + String s = resourcelocation.toString(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/SetSpawnCommand.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/SetSpawnCommand.java.patch new file mode 100644 index 0000000000..57fa9887c4 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/SetSpawnCommand.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/server/commands/SetSpawnCommand.java ++++ b/net/minecraft/server/commands/SetSpawnCommand.java +@@ -42,7 +41,7 @@ + while (iterator.hasNext()) { + ServerPlayer serverplayer = (ServerPlayer) iterator.next(); + +- serverplayer.setRespawnPosition(resourcekey, blockpos, f, true, false); ++ entityplayer.setRespawnPosition(resourcekey, pos, angle, true, false, org.bukkit.event.player.PlayerSpawnChangeEvent.Cause.COMMAND); // CraftBukkit + } + + String s = resourcekey.location().toString(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/SpreadPlayersCommand.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/SpreadPlayersCommand.java.patch new file mode 100644 index 0000000000..7812ce47c7 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/SpreadPlayersCommand.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/server/commands/SpreadPlayersCommand.java ++++ b/net/minecraft/server/commands/SpreadPlayersCommand.java +@@ -204,7 +203,7 @@ + spreadplayerscommand_position = aspreadplayerscommand_position[j++]; + } + +- entity.teleportTo(serverlevel, (double) Mth.floor(spreadplayerscommand_position.x) + 0.5D, (double) spreadplayerscommand_position.getSpawnY(serverlevel, i), (double) Mth.floor(spreadplayerscommand_position.z) + 0.5D, Set.of(), entity.getYRot(), entity.getXRot()); ++ entity.teleportTo(level, (double) Mth.floor(commandspreadplayers_a.x) + 0.5D, (double) commandspreadplayers_a.getSpawnY(level, maxHeight), (double) Mth.floor(commandspreadplayers_a.z) + 0.5D, Set.of(), entity.getYRot(), entity.getXRot(), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.COMMAND); // CraftBukkit - handle teleport reason + d1 = Double.MAX_VALUE; + SpreadPlayersCommand.Position[] aspreadplayerscommand_position1 = aspreadplayerscommand_position; + int k = aspreadplayerscommand_position.length; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/SummonCommand.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/SummonCommand.java.patch new file mode 100644 index 0000000000..ecd57e2c6e --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/SummonCommand.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/server/commands/SummonCommand.java ++++ b/net/minecraft/server/commands/SummonCommand.java +@@ -68,7 +67,7 @@ + ((Mob) entity).finalizeSpawn(commandsourcestack.getLevel(), commandsourcestack.getLevel().getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.COMMAND, (SpawnGroupData) null, (CompoundTag) null); + } + +- if (!serverlevel.tryAddFreshEntityWithPassengers(entity)) { ++ if (!worldserver.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.COMMAND)) { // CraftBukkit - pass a spawn reason of "COMMAND" + throw SummonCommand.ERROR_DUPLICATE_UUID.create(); + } else { + return entity; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/TeleportCommand.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/TeleportCommand.java.patch new file mode 100644 index 0000000000..193801f2b2 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/TeleportCommand.java.patch @@ -0,0 +1,53 @@ +--- a/net/minecraft/server/commands/TeleportCommand.java ++++ b/net/minecraft/server/commands/TeleportCommand.java +@@ -33,6 +32,12 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.event.entity.EntityTeleportEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++// CraftBukkit end + + public class TeleportCommand { + +@@ -156,11 +161,34 @@ + float f2 = Mth.wrapDegrees(f); + float f3 = Mth.wrapDegrees(f1); + +- if (entity.teleportTo(serverlevel, d0, d1, d2, set, f2, f3)) { +- if (teleportcommand_lookat != null) { +- teleportcommand_lookat.perform(commandsourcestack, entity); ++ // CraftBukkit start - Teleport event ++ boolean result; ++ if (entity instanceof ServerPlayer player) { ++ result = player.teleportTo(level, x, d1, y, set, f2, f3, PlayerTeleportEvent.TeleportCause.COMMAND); ++ } else { ++ Location to = new Location(level.getWorld(), x, d1, y, f2, f3); ++ EntityTeleportEvent event = new EntityTeleportEvent(entity.getBukkitEntity(), entity.getBukkitEntity().getLocation(), to); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; + } + ++ x = to.getX(); ++ d1 = to.getY(); ++ y = to.getZ(); ++ f2 = to.getYaw(); ++ f3 = to.getPitch(); ++ level = ((CraftWorld) to.getWorld()).getHandle(); ++ ++ result = entity.teleportTo(level, x, d1, y, set, f2, f3); ++ } ++ ++ if (result) { ++ // CraftBukkit end ++ if (relativeList != null) { ++ relativeList.perform(source, entity); ++ } ++ + label23: + { + if (entity instanceof LivingEntity) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/TimeCommand.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/TimeCommand.java.patch new file mode 100644 index 0000000000..ad1b09041f --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/TimeCommand.java.patch @@ -0,0 +1,59 @@ +--- a/net/minecraft/server/commands/TimeCommand.java ++++ b/net/minecraft/server/commands/TimeCommand.java +@@ -9,6 +8,10 @@ + import net.minecraft.commands.arguments.TimeArgument; + import net.minecraft.network.chat.Component; + import net.minecraft.server.level.ServerLevel; ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.event.world.TimeSkipEvent; ++// CraftBukkit end + + public class TimeCommand { + +@@ -49,13 +52,19 @@ + return i; + } + +- public static int setTime(CommandSourceStack commandsourcestack, int i) { +- Iterator iterator = commandsourcestack.getServer().getAllLevels().iterator(); ++ public static int setTime(CommandSourceStack source, int time) { ++ Iterator iterator = com.google.common.collect.Iterators.singletonIterator(source.getLevel()); // CraftBukkit - SPIGOT-6496: Only set the time for the world the command originates in + + while (iterator.hasNext()) { + ServerLevel serverlevel = (ServerLevel) iterator.next(); + +- serverlevel.setDayTime((long) i); ++ // CraftBukkit start ++ TimeSkipEvent event = new TimeSkipEvent(worldserver.getWorld(), TimeSkipEvent.SkipReason.COMMAND, time - worldserver.getDayTime()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ worldserver.setDayTime((long) worldserver.getDayTime() + event.getSkipAmount()); ++ } ++ // CraftBukkit end + } + + commandsourcestack.sendSuccess(() -> { +@@ -64,13 +73,19 @@ + return getDayTime(commandsourcestack.getLevel()); + } + +- public static int addTime(CommandSourceStack commandsourcestack, int i) { +- Iterator iterator = commandsourcestack.getServer().getAllLevels().iterator(); ++ public static int addTime(CommandSourceStack source, int amount) { ++ Iterator iterator = com.google.common.collect.Iterators.singletonIterator(source.getLevel()); // CraftBukkit - SPIGOT-6496: Only set the time for the world the command originates in + + while (iterator.hasNext()) { + ServerLevel serverlevel = (ServerLevel) iterator.next(); + +- serverlevel.setDayTime(serverlevel.getDayTime() + (long) i); ++ // CraftBukkit start ++ TimeSkipEvent event = new TimeSkipEvent(worldserver.getWorld(), TimeSkipEvent.SkipReason.COMMAND, amount); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ worldserver.setDayTime(worldserver.getDayTime() + event.getSkipAmount()); ++ } ++ // CraftBukkit end + } + + int j = getDayTime(commandsourcestack.getLevel()); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/WorldBorderCommand.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/WorldBorderCommand.java.patch new file mode 100644 index 0000000000..ff27db18c2 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/commands/WorldBorderCommand.java.patch @@ -0,0 +1,79 @@ +--- a/net/minecraft/server/commands/WorldBorderCommand.java ++++ b/net/minecraft/server/commands/WorldBorderCommand.java +@@ -57,8 +56,8 @@ + }))))); + } + +- private static int setDamageBuffer(CommandSourceStack commandsourcestack, float f) throws CommandSyntaxException { +- WorldBorder worldborder = commandsourcestack.getServer().overworld().getWorldBorder(); ++ private static int setDamageBuffer(CommandSourceStack source, float distance) throws CommandSyntaxException { ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit + + if (worldborder.getDamageSafeZone() == (double) f) { + throw WorldBorderCommand.ERROR_SAME_DAMAGE_BUFFER.create(); +@@ -71,8 +70,8 @@ + } + } + +- private static int setDamageAmount(CommandSourceStack commandsourcestack, float f) throws CommandSyntaxException { +- WorldBorder worldborder = commandsourcestack.getServer().overworld().getWorldBorder(); ++ private static int setDamageAmount(CommandSourceStack source, float damagePerBlock) throws CommandSyntaxException { ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit + + if (worldborder.getDamagePerBlock() == (double) f) { + throw WorldBorderCommand.ERROR_SAME_DAMAGE_AMOUNT.create(); +@@ -85,8 +84,8 @@ + } + } + +- private static int setWarningTime(CommandSourceStack commandsourcestack, int i) throws CommandSyntaxException { +- WorldBorder worldborder = commandsourcestack.getServer().overworld().getWorldBorder(); ++ private static int setWarningTime(CommandSourceStack source, int time) throws CommandSyntaxException { ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit + + if (worldborder.getWarningTime() == i) { + throw WorldBorderCommand.ERROR_SAME_WARNING_TIME.create(); +@@ -99,8 +98,8 @@ + } + } + +- private static int setWarningDistance(CommandSourceStack commandsourcestack, int i) throws CommandSyntaxException { +- WorldBorder worldborder = commandsourcestack.getServer().overworld().getWorldBorder(); ++ private static int setWarningDistance(CommandSourceStack source, int distance) throws CommandSyntaxException { ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit + + if (worldborder.getWarningBlocks() == i) { + throw WorldBorderCommand.ERROR_SAME_WARNING_DISTANCE.create(); +@@ -113,8 +112,8 @@ + } + } + +- private static int getSize(CommandSourceStack commandsourcestack) { +- double d0 = commandsourcestack.getServer().overworld().getWorldBorder().getSize(); ++ private static int getSize(CommandSourceStack source) { ++ double d0 = source.getLevel().getWorldBorder().getSize(); // CraftBukkit + + commandsourcestack.sendSuccess(() -> { + return Component.translatable("commands.worldborder.get", String.format(Locale.ROOT, "%.0f", d0)); +@@ -122,8 +121,8 @@ + return Mth.floor(d0 + 0.5D); + } + +- private static int setCenter(CommandSourceStack commandsourcestack, Vec2 vec2) throws CommandSyntaxException { +- WorldBorder worldborder = commandsourcestack.getServer().overworld().getWorldBorder(); ++ private static int setCenter(CommandSourceStack source, Vec2 pos) throws CommandSyntaxException { ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit + + if (worldborder.getCenterX() == (double) vec2.x && worldborder.getCenterZ() == (double) vec2.y) { + throw WorldBorderCommand.ERROR_SAME_CENTER.create(); +@@ -138,8 +137,8 @@ + } + } + +- private static int setSize(CommandSourceStack commandsourcestack, double d0, long i) throws CommandSyntaxException { +- WorldBorder worldborder = commandsourcestack.getServer().overworld().getWorldBorder(); ++ private static int setSize(CommandSourceStack source, double newSize, long i) throws CommandSyntaxException { ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit + double d1 = worldborder.getSize(); + + if (d1 == d0) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/dedicated/DedicatedServer.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/dedicated/DedicatedServer.java.patch new file mode 100644 index 0000000000..6dadb64480 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/dedicated/DedicatedServer.java.patch @@ -0,0 +1,250 @@ +--- a/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/net/minecraft/server/dedicated/DedicatedServer.java +@@ -53,6 +52,16 @@ + import net.minecraft.world.level.storage.LevelStorageSource; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.server.WorldLoader; ++import org.apache.logging.log4j.Level; ++import org.apache.logging.log4j.LogManager; ++import org.apache.logging.log4j.io.IoBuilder; ++import org.bukkit.command.CommandSender; ++import org.bukkit.event.server.ServerCommandEvent; ++import org.bukkit.event.server.RemoteServerCommandEvent; ++// CraftBukkit end ++ + public class DedicatedServer extends MinecraftServer implements ServerInterface { + + static final Logger LOGGER = LogUtils.getLogger(); +@@ -61,7 +70,7 @@ + private final List consoleInput = Collections.synchronizedList(Lists.newArrayList()); + @Nullable + private QueryThreadGs4 queryThreadGs4; +- private final RconConsoleSource rconConsoleSource; ++ // private final RemoteControlCommandListener rconConsoleSource; // CraftBukkit - remove field + @Nullable + private RconThread rconThread; + private final DedicatedServerSettings settings; +@@ -70,10 +79,12 @@ + @Nullable + private final TextFilterClient textFilterClient; + +- public DedicatedServer(Thread thread, LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess, PackRepository packrepository, WorldStem worldstem, DedicatedServerSettings dedicatedserversettings, DataFixer datafixer, Services services, ChunkProgressListenerFactory chunkprogresslistenerfactory) { +- super(thread, levelstoragesource_levelstorageaccess, packrepository, worldstem, Proxy.NO_PROXY, datafixer, services, chunkprogresslistenerfactory); ++ // CraftBukkit start - Signature changed ++ public DedicatedServer(joptsimple.OptionSet options, WorldLoader.a worldLoader, Thread thread, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PackRepository resourcepackrepository, WorldStem worldstem, DedicatedServerSettings dedicatedserversettings, DataFixer datafixer, Services services, ChunkProgressListenerFactory worldloadlistenerfactory) { ++ super(options, worldLoader, thread, convertable_conversionsession, resourcepackrepository, worldstem, Proxy.NO_PROXY, datafixer, services, worldloadlistenerfactory); ++ // CraftBukkit end + this.settings = dedicatedserversettings; +- this.rconConsoleSource = new RconConsoleSource(this); ++ // this.rconConsoleSource = new RemoteControlCommandListener(this); // CraftBukkit - remove field + this.textFilterClient = TextFilterClient.createFromConfig(dedicatedserversettings.getProperties().textFilteringConfig); + } + +@@ -83,13 +92,44 @@ + Thread thread = new Thread("Server console handler") { + @Override + public void run() { +- BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8)); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.Main.useConsole) { ++ return; ++ } ++ jline.console.ConsoleReader bufferedreader = reader; + ++ // MC-33041, SPIGOT-5538: if System.in is not valid due to javaw, then return ++ try { ++ System.in.available(); ++ } catch (IOException ex) { ++ return; ++ } ++ // CraftBukkit end ++ + String s; + + try { +- while (!DedicatedServer.this.isStopped() && DedicatedServer.this.isRunning() && (s = bufferedreader.readLine()) != null) { +- DedicatedServer.this.handleConsoleInput(s, DedicatedServer.this.createCommandSourceStack()); ++ // CraftBukkit start - JLine disabling compatibility ++ while (!DedicatedServer.this.isStopped() && DedicatedServer.this.isRunning()) { ++ if (org.bukkit.craftbukkit.Main.useJline) { ++ s = bufferedreader.readLine(">", null); ++ } else { ++ s = bufferedreader.readLine(); ++ } ++ ++ // SPIGOT-5220: Throttle if EOF (ctrl^d) or stdin is /dev/null ++ if (s == null) { ++ try { ++ Thread.sleep(50L); ++ } catch (InterruptedException ex) { ++ Thread.currentThread().interrupt(); ++ } ++ continue; ++ } ++ if (s.trim().length() > 0) { // Trim to filter lines which are just spaces ++ DedicatedServer.this.handleConsoleInput(s, DedicatedServer.this.createCommandSourceStack()); ++ } ++ // CraftBukkit end + } + } catch (IOException ioexception) { + DedicatedServer.LOGGER.error("Exception handling console input", ioexception); +@@ -98,6 +138,27 @@ + } + }; + ++ // CraftBukkit start - TODO: handle command-line logging arguments ++ java.util.logging.Logger global = java.util.logging.Logger.getLogger(""); ++ global.setUseParentHandlers(false); ++ for (java.util.logging.Handler handler : global.getHandlers()) { ++ global.removeHandler(handler); ++ } ++ global.addHandler(new org.bukkit.craftbukkit.util.ForwardLogHandler()); ++ ++ final org.apache.logging.log4j.core.Logger logger = ((org.apache.logging.log4j.core.Logger) LogManager.getRootLogger()); ++ for (org.apache.logging.log4j.core.Appender appender : logger.getAppenders().values()) { ++ if (appender instanceof org.apache.logging.log4j.core.appender.ConsoleAppender) { ++ logger.removeAppender(appender); ++ } ++ } ++ ++ new org.bukkit.craftbukkit.util.TerminalConsoleWriterThread(System.out, this.reader).start(); ++ ++ System.setOut(IoBuilder.forLogger(logger).setLevel(Level.INFO).buildPrintStream()); ++ System.setErr(IoBuilder.forLogger(logger).setLevel(Level.WARN).buildPrintStream()); ++ // CraftBukkit end ++ + thread.setDaemon(true); + thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(DedicatedServer.LOGGER)); + thread.start(); +@@ -122,7 +183,7 @@ + this.setMotd(dedicatedserverproperties.motd); + super.setPlayerIdleTimeout((Integer) dedicatedserverproperties.playerIdleTimeout.get()); + this.setEnforceWhitelist(dedicatedserverproperties.enforceWhitelist); +- this.worldData.setGameType(dedicatedserverproperties.gamemode); ++ // this.worldData.setGameType(dedicatedserverproperties.gamemode); // CraftBukkit - moved to world loading + DedicatedServer.LOGGER.info("Default game type: {}", dedicatedserverproperties.gamemode); + InetAddress inetaddress = null; + +@@ -146,6 +207,12 @@ + return false; + } + ++ // CraftBukkit start ++ this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); ++ server.loadPlugins(); ++ server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.STARTUP); ++ // CraftBukkit end ++ + if (!this.usesAuthentication()) { + DedicatedServer.LOGGER.warn("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!"); + DedicatedServer.LOGGER.warn("The server will make no attempt to authenticate usernames. Beware."); +@@ -160,13 +227,13 @@ + if (!OldUsersConverter.serverReadyAfterUserconversion(this)) { + return false; + } else { +- this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); ++ // this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); // CraftBukkit - moved up + long i = Util.getNanos(); + + SkullBlockEntity.setup(this.services, this); + GameProfileCache.setUsesAuthentication(this.usesAuthentication()); + DedicatedServer.LOGGER.info("Preparing level \"{}\"", this.getLevelIdName()); +- this.loadLevel(); ++ this.loadLevel(storageSource.getLevelId()); // CraftBukkit + long j = Util.getNanos() - i; + String s = String.format(Locale.ROOT, "%.3fs", (double) j / 1.0E9D); + +@@ -307,6 +365,7 @@ + this.queryThreadGs4.stop(); + } + ++ System.exit(0); // CraftBukkit + } + + @Override +@@ -330,7 +387,15 @@ + while (!this.consoleInput.isEmpty()) { + ConsoleInput consoleinput = (ConsoleInput) this.consoleInput.remove(0); + +- this.getCommands().performPrefixedCommand(consoleinput.source, consoleinput.msg); ++ // CraftBukkit start - ServerCommand for preprocessing ++ ServerCommandEvent event = new ServerCommandEvent(console, servercommand.msg); ++ server.getPluginManager().callEvent(event); ++ if (event.isCancelled()) continue; ++ servercommand = new ConsoleInput(event.getCommand(), servercommand.source); ++ ++ // this.getCommands().performPrefixedCommand(servercommand.source, servercommand.msg); // Called in dispatchServerCommand ++ server.dispatchServerCommand(console, servercommand); ++ // CraftBukkit end + } + + } +@@ -582,17 +622,45 @@ + @Override + @Override + public String getPluginNames() { +- return ""; ++ // CraftBukkit start - Whole method ++ StringBuilder result = new StringBuilder(); ++ org.bukkit.plugin.Plugin[] plugins = server.getPluginManager().getPlugins(); ++ ++ result.append(server.getName()); ++ result.append(" on Bukkit "); ++ result.append(server.getBukkitVersion()); ++ ++ if (plugins.length > 0 && server.getQueryPlugins()) { ++ result.append(": "); ++ ++ for (int i = 0; i < plugins.length; i++) { ++ if (i > 0) { ++ result.append("; "); ++ } ++ ++ result.append(plugins[i].getDescription().getName()); ++ result.append(" "); ++ result.append(plugins[i].getDescription().getVersion().replaceAll(";", ",")); ++ } ++ } ++ ++ return result.toString(); ++ // CraftBukkit end + } + + @Override +- @Override +- public String runCommand(String s) { +- this.rconConsoleSource.prepareForCommand(); ++ public String runCommand(String command) { ++ // CraftBukkit start - fire RemoteServerCommandEvent ++ throw new UnsupportedOperationException("Not supported - remote source required."); ++ } ++ ++ public String runCommand(RconConsoleSource rconConsoleSource, String s) { ++ rconConsoleSource.prepareForCommand(); + this.executeBlocking(() -> { + this.getCommands().performPrefixedCommand(this.rconConsoleSource.createCommandSourceStack(), s); + }); +- return this.rconConsoleSource.getCommandResponse(); ++ return rconConsoleSource.getCommandResponse(); ++ // CraftBukkit end + } + + public void storeUsingWhiteList(boolean flag) { +@@ -651,4 +718,15 @@ + public Optional getServerResourcePack() { + return this.settings.getProperties().serverResourcePackInfo; + } ++ ++ // CraftBukkit start ++ public boolean isDebugging() { ++ return this.getProperties().debug; ++ } ++ ++ @Override ++ public CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return console; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/dedicated/DedicatedServerProperties.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/dedicated/DedicatedServerProperties.java.patch new file mode 100644 index 0000000000..e4edcccb3e --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/dedicated/DedicatedServerProperties.java.patch @@ -0,0 +1,53 @@ +--- a/net/minecraft/server/dedicated/DedicatedServerProperties.java ++++ b/net/minecraft/server/dedicated/DedicatedServerProperties.java +@@ -44,11 +44,16 @@ + import net.minecraft.world.level.levelgen.presets.WorldPresets; + import org.slf4j.Logger; + ++// CraftBukkit start ++import joptsimple.OptionSet; ++// CraftBukkit end ++ + public class DedicatedServerProperties extends Settings { + + static final Logger LOGGER = LogUtils.getLogger(); + private static final Pattern SHA1 = Pattern.compile("^[a-fA-F0-9]{40}$"); + private static final Splitter COMMA_SPLITTER = Splitter.on(',').trimResults(); ++ public final boolean debug = this.get("debug", false); // CraftBukkit + public final boolean onlineMode = this.get("online-mode", true); + public final boolean preventProxyConnections = this.get("prevent-proxy-connections", false); + public final String serverIp = this.get("server-ip", ""); +@@ -103,8 +108,10 @@ + private final DedicatedServerProperties.WorldDimensionData worldDimensionData; + public final WorldOptions worldOptions; + +- public DedicatedServerProperties(Properties properties) { +- super(properties); ++ // CraftBukkit start ++ public DedicatedServerProperties(Properties properties, OptionSet optionset) { ++ super(properties, optionset); ++ // CraftBukkit end + this.difficulty = (Difficulty) this.get("difficulty", dispatchNumberOrString(Difficulty::byId, Difficulty::byName), Difficulty::getKey, Difficulty.EASY); + this.gamemode = (GameType) this.get("gamemode", dispatchNumberOrString(GameType::byId, GameType::byName), GameType::getName, GameType.SURVIVAL); + this.levelName = this.get("level-name", "world"); +@@ -161,14 +168,15 @@ + this.initialDataPackConfiguration = getDatapackConfig(this.get("initial-enabled-packs", String.join(",", WorldDataConfiguration.DEFAULT.dataPacks().getEnabled())), this.get("initial-disabled-packs", String.join(",", WorldDataConfiguration.DEFAULT.dataPacks().getDisabled()))); + } + +- public static DedicatedServerProperties fromFile(Path path) { +- return new DedicatedServerProperties(loadFromFile(path)); ++ // CraftBukkit start ++ public static DedicatedServerProperties fromFile(Path path, OptionSet optionset) { ++ return new DedicatedServerProperties(loadFromFile(path), optionset); + } + + @Override +- @Override +- protected DedicatedServerProperties reload(RegistryAccess registryaccess, Properties properties) { +- return new DedicatedServerProperties(properties); ++ protected DedicatedServerProperties reload(RegistryAccess iregistrycustom, Properties properties, OptionSet optionset) { ++ return new DedicatedServerProperties(properties, optionset); ++ // CraftBukkit end + } + + @Nullable diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/dedicated/DedicatedServerSettings.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/dedicated/DedicatedServerSettings.java.patch new file mode 100644 index 0000000000..9a52b5cc81 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/dedicated/DedicatedServerSettings.java.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/server/dedicated/DedicatedServerSettings.java ++++ b/net/minecraft/server/dedicated/DedicatedServerSettings.java +@@ -3,14 +3,21 @@ + import java.nio.file.Path; + import java.util.function.UnaryOperator; + ++// CraftBukkit start ++import java.io.File; ++import joptsimple.OptionSet; ++// CraftBukkit end ++ + public class DedicatedServerSettings { + + private final Path source; + private DedicatedServerProperties properties; + +- public DedicatedServerSettings(Path path) { +- this.source = path; +- this.properties = DedicatedServerProperties.fromFile(path); ++ // CraftBukkit start ++ public DedicatedServerSettings(OptionSet optionset) { ++ this.source = ((File) optionset.valueOf("config")).toPath(); ++ this.properties = DedicatedServerProperties.fromFile(source, optionset); ++ // CraftBukkit end + } + + public DedicatedServerProperties getProperties() { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/dedicated/Settings.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/dedicated/Settings.java.patch new file mode 100644 index 0000000000..d784dbc38c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/dedicated/Settings.java.patch @@ -0,0 +1,102 @@ +--- a/net/minecraft/server/dedicated/Settings.java ++++ b/net/minecraft/server/dedicated/Settings.java +@@ -23,17 +22,36 @@ + import net.minecraft.core.RegistryAccess; + import org.slf4j.Logger; + ++import joptsimple.OptionSet; // CraftBukkit ++import net.minecraft.core.RegistryAccess; ++ + public abstract class Settings> { + + private static final Logger LOGGER = LogUtils.getLogger(); +- protected final Properties properties; ++ public final Properties properties; ++ // CraftBukkit start ++ private OptionSet options = null; + + public Settings(Properties properties) { + this.properties = properties; + } + ++ private String getOverride(String name, String value) { ++ if ((this.options != null) && (this.options.has(name))) { ++ return String.valueOf(this.options.valueOf(name)); ++ } ++ ++ return value; ++ // CraftBukkit end ++ } ++ + public static Properties loadFromFile(Path path) { + try { ++ // CraftBukkit start - SPIGOT-7465, MC-264979: Don't load if file doesn't exist ++ if (!path.toFile().exists()) { ++ return new Properties(); ++ } ++ // CraftBukkit end + Properties properties; + Properties properties1; + +@@ -97,6 +117,11 @@ + + public void store(Path path) { + try { ++ // CraftBukkit start - Don't attempt writing to file if it's read only ++ if (path.toFile().exists() && !path.toFile().canWrite()) { ++ return; ++ } ++ // CraftBukkit end + BufferedWriter bufferedwriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8); + + try { +@@ -143,8 +168,8 @@ + } + + @Nullable +- private String getStringRaw(String s) { +- return (String) this.properties.get(s); ++ private String getStringRaw(String key) { ++ return (String) getOverride(key, this.properties.getProperty(key)); // CraftBukkit + } + + @Nullable +@@ -159,7 +184,17 @@ + } + } + +- protected V get(String s, Function function, Function function1, V v0) { ++ protected V get(String key, Function mapper, Function toString, V value) { ++ // CraftBukkit start ++ try { ++ return get0(key, mapper, toString, value); ++ } catch (Exception ex) { ++ throw new RuntimeException("Could not load invalidly configured property '" + key + "'", ex); ++ } ++ } ++ ++ private V get0(String s, Function function, Function function1, V v0) { ++ // CraftBukkit end + String s1 = this.getStringRaw(s); + V v1 = MoreObjects.firstNonNull(s1 != null ? function.apply(s1) : null, v0); + +@@ -236,7 +271,7 @@ + return properties; + } + +- protected abstract T reload(RegistryAccess registryAccess, Properties properties); ++ protected abstract T reload(RegistryAccess iregistrycustom, Properties properties, OptionSet optionset); // CraftBukkit + + public class MutableValue implements Supplier { + +@@ -258,8 +292,8 @@ + public T update(RegistryAccess registryaccess, V v0) { + Properties properties = Settings.this.cloneProperties(); + +- properties.put(this.key, this.serializer.apply(v0)); +- return Settings.this.reload(registryaccess, properties); ++ properties.put(this.key, this.serializer.apply(newValue)); ++ return Settings.this.reload(registryAccess, properties, Settings.this.options); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/gui/MinecraftServerGui.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/gui/MinecraftServerGui.java.patch new file mode 100644 index 0000000000..107e690cde --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/gui/MinecraftServerGui.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/server/gui/MinecraftServerGui.java ++++ b/net/minecraft/server/gui/MinecraftServerGui.java +@@ -168,7 +166,8 @@ + this.finalizers.forEach(Runnable::run); + } + +- public void print(JTextArea jtextarea, JScrollPane jscrollpane, String s) { ++ private static final java.util.regex.Pattern ANSI = java.util.regex.Pattern.compile("\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})*)?[m|K]"); // CraftBukkit ++ public void print(JTextArea textArea, JScrollPane scrollPane, String line) { + if (!SwingUtilities.isEventDispatchThread()) { + SwingUtilities.invokeLater(() -> { + this.print(jtextarea, jscrollpane, s); +@@ -183,7 +182,7 @@ + } + + try { +- document.insertString(document.getLength(), s, (AttributeSet) null); ++ document.insertString(document.getLength(), ANSI.matcher(line).replaceAll(""), (AttributeSet) null); // CraftBukkit + } catch (BadLocationException badlocationexception) { + ; + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ChunkHolder.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ChunkHolder.java.patch new file mode 100644 index 0000000000..3e97a8baff --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ChunkHolder.java.patch @@ -0,0 +1,122 @@ +--- a/net/minecraft/server/level/ChunkHolder.java ++++ b/net/minecraft/server/level/ChunkHolder.java +@@ -36,6 +36,10 @@ + import net.minecraft.world.level.chunk.ProtoChunk; + import net.minecraft.world.level.lighting.LevelLightEngine; + ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++// CraftBukkit end ++ + public class ChunkHolder { + + public static final Either UNLOADED_CHUNK = Either.right(ChunkHolder.ChunkLoadingFailure.UNLOADED); +@@ -90,9 +94,23 @@ + this.changedBlocksPerSection = new ShortSet[levelheightaccessor.getSectionsCount()]; + } + +- public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus chunkstatus) { +- CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(chunkstatus.getIndex()); ++ // CraftBukkit start ++ public LevelChunk getFullChunkNow() { ++ // Note: We use the oldTicketLevel for isLoaded checks. ++ if (!ChunkLevel.fullStatus(this.oldTicketLevel).isOrAfter(FullChunkStatus.FULL)) return null; ++ return this.getFullChunkNowUnchecked(); ++ } + ++ public LevelChunk getFullChunkNowUnchecked() { ++ CompletableFuture> statusFuture = this.getFutureIfPresentUnchecked(ChunkStatus.FULL); ++ Either either = (Either) statusFuture.getNow(null); ++ return (either == null) ? null : (LevelChunk) either.left().orElse(null); ++ } ++ // CraftBukkit end ++ ++ public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus chunkStatus) { ++ CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(chunkStatus.getIndex()); ++ + return completablefuture == null ? ChunkHolder.UNLOADED_CHUNK_FUTURE : completablefuture; + } + +@@ -179,6 +197,7 @@ + if (levelchunk != null) { + int i = this.levelHeightAccessor.getSectionIndex(blockpos.getY()); + ++ if (i < 0 || i >= this.changedBlocksPerSection.length) return; // CraftBukkit - SPIGOT-6086, SPIGOT-6296 + if (this.changedBlocksPerSection[i] == null) { + this.hasChangedSections = true; + this.changedBlocksPerSection[i] = new ShortOpenHashSet(); +@@ -256,9 +275,12 @@ + LevelChunkSection levelchunksection = levelchunk.getSection(i); + ClientboundSectionBlocksUpdatePacket clientboundsectionblocksupdatepacket = new ClientboundSectionBlocksUpdatePacket(sectionpos, shortset, levelchunksection); + +- this.broadcast(list, clientboundsectionblocksupdatepacket); +- clientboundsectionblocksupdatepacket.runUpdates((blockpos1, blockstate1) -> { +- this.broadcastBlockEntityIfNeeded(list, level, blockpos1, blockstate1); ++ this.broadcast(list, packetplayoutmultiblockchange); ++ // CraftBukkit start ++ List finalList = list; ++ packetplayoutmultiblockchange.runUpdates((blockposition1, iblockdata1) -> { ++ this.broadcastBlockEntityIfNeeded(finalList, world, blockposition1, iblockdata1); ++ // CraftBukkit end + }); + } + } +@@ -411,7 +433,31 @@ + boolean flag1 = ChunkLevel.isLoaded(this.ticketLevel); + FullChunkStatus fullchunkstatus = ChunkLevel.fullStatus(this.oldTicketLevel); + FullChunkStatus fullchunkstatus1 = ChunkLevel.fullStatus(this.ticketLevel); ++ // CraftBukkit start ++ // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins. ++ if (fullchunkstatus.isOrAfter(FullChunkStatus.FULL) && !fullchunkstatus1.isOrAfter(FullChunkStatus.FULL)) { ++ this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { ++ LevelChunk chunk = (LevelChunk)either.left().orElse(null); ++ if (chunk != null) { ++ chunkMap.callbackExecutor.execute(() -> { ++ // Minecraft will apply the chunks tick lists to the world once the chunk got loaded, and then store the tick ++ // lists again inside the chunk once the chunk becomes inaccessible and set the chunk's needsSaving flag. ++ // These actions may however happen deferred, so we manually set the needsSaving flag already here. ++ chunk.setUnsaved(true); ++ chunk.unloadCallback(); ++ }); ++ } ++ }).exceptionally((throwable) -> { ++ // ensure exceptions are printed, by default this is not the case ++ MinecraftServer.LOGGER.error("Failed to schedule unload callback for chunk " + ChunkHolder.this.pos, throwable); ++ return null; ++ }); + ++ // Run callback right away if the future was already done ++ chunkMap.callbackExecutor.run(); ++ } ++ // CraftBukkit end ++ + if (flag) { + Either either = Either.right(new ChunkHolder.ChunkLoadingFailure() { + @Override +@@ -482,6 +527,26 @@ + + this.onLevelChange.onLevelChange(this.pos, this::getQueueLevel, this.ticketLevel, this::setQueueLevel); + this.oldTicketLevel = this.ticketLevel; ++ // CraftBukkit start ++ // ChunkLoadEvent: Called after the chunk is loaded: isChunkLoaded returns true and chunk is ready to be modified by plugins. ++ if (!fullchunkstatus.isOrAfter(FullChunkStatus.FULL) && fullchunkstatus1.isOrAfter(FullChunkStatus.FULL)) { ++ this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { ++ LevelChunk chunk = (LevelChunk)either.left().orElse(null); ++ if (chunk != null) { ++ chunkMap.callbackExecutor.execute(() -> { ++ chunk.loadCallback(); ++ }); ++ } ++ }).exceptionally((throwable) -> { ++ // ensure exceptions are printed, by default this is not the case ++ MinecraftServer.LOGGER.error("Failed to schedule load callback for chunk " + ChunkHolder.this.pos, throwable); ++ return null; ++ }); ++ ++ // Run callback right away if the future was already done ++ chunkMap.callbackExecutor.run(); ++ } ++ // CraftBukkit end + } + + public boolean wasAccessibleSinceLastSave() { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ChunkMap.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ChunkMap.java.patch new file mode 100644 index 0000000000..720cf2486b --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ChunkMap.java.patch @@ -0,0 +1,147 @@ +--- a/net/minecraft/server/level/ChunkMap.java ++++ b/net/minecraft/server/level/ChunkMap.java +@@ -100,6 +100,9 @@ + import net.minecraft.world.phys.Vec3; + import org.apache.commons.lang3.mutable.MutableBoolean; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.generator.CustomChunkGenerator; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider { + +@@ -143,8 +146,29 @@ + private final Queue unloadQueue; + private int serverViewDistance; + +- public ChunkMap(ServerLevel serverlevel, LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess, DataFixer datafixer, StructureTemplateManager structuretemplatemanager, Executor executor, BlockableEventLoop blockableeventloop, LightChunkGetter lightchunkgetter, ChunkGenerator chunkgenerator, ChunkProgressListener chunkprogresslistener, ChunkStatusUpdateListener chunkstatusupdatelistener, Supplier supplier, int i, boolean flag) { +- super(levelstoragesource_levelstorageaccess.getDimensionPath(serverlevel.dimension()).resolve("region"), datafixer, flag); ++ // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() ++ public final CallbackExecutor callbackExecutor = new CallbackExecutor(); ++ public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable { ++ ++ private final java.util.Queue queue = new java.util.ArrayDeque<>(); ++ ++ @Override ++ public void execute(Runnable runnable) { ++ queue.add(runnable); ++ } ++ ++ @Override ++ public void run() { ++ Runnable task; ++ while ((task = queue.poll()) != null) { ++ task.run(); ++ } ++ } ++ }; ++ // CraftBukkit end ++ ++ public ChunkMap(ServerLevel level, LevelStorageSource.LevelStorageAccess levelStorageAccess, DataFixer fixerUpper, StructureTemplateManager structureManager, Executor dispatcher, BlockableEventLoop mainThreadExecutor, LightChunkGetter lightChunk, ChunkGenerator generator, ChunkProgressListener progressListener, ChunkStatusUpdateListener chunkStatusListener, Supplier overworldDataStorage, int viewDistance, boolean sync) { ++ super(levelStorageAccess.getDimensionPath(level.dimension()).resolve("region"), fixerUpper, sync); + this.visibleChunkMap = this.updatingChunkMap.clone(); + this.pendingUnloads = new Long2ObjectLinkedOpenHashMap(); + this.entitiesInLevel = new LongOpenHashSet(); +@@ -159,10 +183,15 @@ + Path path = levelstoragesource_levelstorageaccess.getDimensionPath(serverlevel.dimension()); + + this.storageName = path.getFileName().toString(); +- this.level = serverlevel; +- this.generator = chunkgenerator; +- RegistryAccess registryaccess = serverlevel.registryAccess(); +- long j = serverlevel.getSeed(); ++ this.level = level; ++ this.generator = generator; ++ // CraftBukkit start - SPIGOT-7051: It's a rigged game! Use delegate for random state creation, otherwise it is not so random. ++ if (generator instanceof CustomChunkGenerator) { ++ generator = ((CustomChunkGenerator) generator).getDelegate(); ++ } ++ // CraftBukkit end ++ RegistryAccess iregistrycustom = level.registryAccess(); ++ long j = level.getSeed(); + + if (chunkgenerator instanceof NoiseBasedChunkGenerator) { + NoiseBasedChunkGenerator noisebasedchunkgenerator = (NoiseBasedChunkGenerator) chunkgenerator; +@@ -335,8 +364,10 @@ + List list3 = Lists.newArrayList(); + final int l1 = 0; + +- for (Iterator iterator = list2.iterator(); iterator.hasNext(); ++l1) { +- final Either either = (Either) iterator.next(); ++ for (Iterator iterator = list2.iterator(); iterator.hasNext(); ++cnt) { ++ final int l1 = cnt; ++ // CraftBukkit end ++ final Either either = (Either) iterator.next(); + + if (either == null) { + throw this.debugFuturesAndCreateReportedException(new IllegalStateException("At least one of the chunk futures were null"), "n/a"); +@@ -749,9 +778,23 @@ + return chunkstatus1; + } + +- private static void postLoadProtoChunk(ServerLevel serverlevel, List list) { +- if (!list.isEmpty()) { +- serverlevel.addWorldGenChunkEntities(EntityType.loadEntitiesRecursive(list, serverlevel)); ++ private static void postLoadProtoChunk(ServerLevel level, List tags) { ++ if (!tags.isEmpty()) { ++ // CraftBukkit start - these are spawned serialized (DefinedStructure) and we don't call an add event below at the moment due to ordering complexities ++ level.addWorldGenChunkEntities(EntityType.loadEntitiesRecursive(tags, level).filter((entity) -> { ++ boolean needsRemoval = false; ++ net.minecraft.server.dedicated.DedicatedServer server = level.getCraftServer().getServer(); ++ if (!server.areNpcsEnabled() && entity instanceof net.minecraft.world.entity.npc.NPC) { ++ entity.discard(); ++ needsRemoval = true; ++ } ++ if (!server.isSpawningAnimals() && (entity instanceof net.minecraft.world.entity.animal.Animal || entity instanceof net.minecraft.world.entity.animal.WaterAnimal)) { ++ entity.discard(); ++ needsRemoval = true; ++ } ++ return !needsRemoval; ++ })); ++ // CraftBukkit end + } + + } +@@ -1047,14 +1091,16 @@ + } + } + +- private CompletableFuture> readChunk(ChunkPos chunkpos) { +- return this.read(chunkpos).thenApplyAsync((optional) -> { +- return optional.map(this::upgradeChunkTag); ++ private CompletableFuture> readChunk(ChunkPos pos) { ++ return this.read(pos).thenApplyAsync((optional) -> { ++ return optional.map((nbttagcompound) -> upgradeChunkTag(nbttagcompound, pos)); // CraftBukkit + }, Util.backgroundExecutor()); + } + +- private CompoundTag upgradeChunkTag(CompoundTag compoundtag) { +- return this.upgradeChunkTag(this.level.dimension(), this.overworldDataStorage, compoundtag, this.generator.getTypeNameForDataFixer()); ++ // CraftBukkit start ++ private CompoundTag upgradeChunkTag(CompoundTag nbttagcompound, ChunkPos chunkcoordintpair) { ++ return this.upgradeChunkTag(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, this.generator.getTypeNameForDataFixer(), chunkcoordintpair, level); ++ // CraftBukkit end + } + + boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkpos) { +@@ -1467,7 +1509,7 @@ + private final Set seenBy = Sets.newIdentityHashSet(); + + public TrackedEntity(Entity entity, int i, int j, boolean flag) { +- this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast); ++ this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, seenBy); // CraftBukkit + this.entity = entity; + this.range = i; + this.lastSectionPos = SectionPos.of((EntityAccess) entity); +@@ -1529,6 +1569,11 @@ + double d2 = d0 * d0; + boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(serverplayer) && ChunkMap.this.isChunkTracked(serverplayer, this.entity.chunkPosition().x, this.entity.chunkPosition().z); + ++ // CraftBukkit start - respect vanish API ++ if (!player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { ++ flag = false; ++ } ++ // CraftBukkit end + if (flag) { + if (this.seenBy.add(serverplayer.connection)) { + this.serverEntity.addPairing(serverplayer); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/DistanceManager.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/DistanceManager.java.patch new file mode 100644 index 0000000000..3ee42861ac --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/DistanceManager.java.patch @@ -0,0 +1,149 @@ +--- a/net/minecraft/server/level/DistanceManager.java ++++ b/net/minecraft/server/level/DistanceManager.java +@@ -122,10 +122,25 @@ + } + + if (!this.chunksToUpdateFutures.isEmpty()) { +- this.chunksToUpdateFutures.forEach((chunkholder) -> { +- chunkholder.updateFutures(chunkmap, this.mainThreadExecutor); +- }); +- this.chunksToUpdateFutures.clear(); ++ // CraftBukkit start ++ // Iterate pending chunk updates with protection against concurrent modification exceptions ++ java.util.Iterator iter = this.chunksToUpdateFutures.iterator(); ++ int expectedSize = this.chunksToUpdateFutures.size(); ++ do { ++ ChunkHolder playerchunk = iter.next(); ++ iter.remove(); ++ expectedSize--; ++ ++ playerchunk.updateFutures(chunkManager, this.mainThreadExecutor); ++ ++ // Reset iterator if set was modified using add() ++ if (this.chunksToUpdateFutures.size() != expectedSize) { ++ expectedSize = this.chunksToUpdateFutures.size(); ++ iter = this.chunksToUpdateFutures.iterator(); ++ } ++ } while (iter.hasNext()); ++ // CraftBukkit end ++ + return true; + } else { + if (!this.ticketsToRelease.isEmpty()) { +@@ -161,30 +176,33 @@ + } + } + +- void addTicket(long i, Ticket ticket) { +- SortedArraySet> sortedarrayset = this.getTickets(i); +- int j = getTicketLevelAt(sortedarrayset); +- Ticket ticket1 = (Ticket) sortedarrayset.addOrGet(ticket); ++ boolean addTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean ++ SortedArraySet> arraysetsorted = this.getTickets(i); ++ int j = getTicketLevelAt(arraysetsorted); ++ Ticket ticket1 = (Ticket) arraysetsorted.addOrGet(ticket); + + ticket1.setCreatedTick(this.ticketTickCounter); + if (ticket.getTicketLevel() < j) { + this.ticketTracker.update(i, ticket.getTicketLevel(), true); + } + ++ return ticket == ticket1; // CraftBukkit + } + +- void removeTicket(long i, Ticket ticket) { +- SortedArraySet> sortedarrayset = this.getTickets(i); ++ boolean removeTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean ++ SortedArraySet> arraysetsorted = this.getTickets(i); + +- if (sortedarrayset.remove(ticket)) { +- ; ++ boolean removed = false; // CraftBukkit ++ if (arraysetsorted.remove(ticket)) { ++ removed = true; // CraftBukkit + } + + if (sortedarrayset.isEmpty()) { + this.tickets.remove(i); + } + +- this.ticketTracker.update(i, getTicketLevelAt(sortedarrayset), false); ++ this.ticketTracker.update(i, getTicketLevelAt(arraysetsorted), false); ++ return removed; // CraftBukkit + } + + public void addTicket(TicketType tickettype, ChunkPos chunkpos, int i, T t0) { +@@ -197,20 +215,34 @@ + this.removeTicket(chunkpos.toLong(), ticket); + } + +- public void addRegionTicket(TicketType tickettype, ChunkPos chunkpos, int i, T t0) { ++ public void addRegionTicket(TicketType type, ChunkPos pos, int distance, T value) { ++ // CraftBukkit start ++ addRegionTicketAtDistance(type, pos, distance, value); ++ } ++ ++ public boolean addRegionTicketAtDistance(TicketType tickettype, ChunkPos chunkcoordintpair, int i, T t0) { ++ // CraftBukkit end + Ticket ticket = new Ticket<>(tickettype, ChunkLevel.byStatus(FullChunkStatus.FULL) - i, t0); + long j = chunkpos.toLong(); + +- this.addTicket(j, ticket); ++ boolean added = this.addTicket(j, ticket); // CraftBukkit + this.tickingTicketsTracker.addTicket(j, ticket); ++ return added; // CraftBukkit + } + +- public void removeRegionTicket(TicketType tickettype, ChunkPos chunkpos, int i, T t0) { ++ public void removeRegionTicket(TicketType type, ChunkPos pos, int distance, T value) { ++ // CraftBukkit start ++ removeRegionTicketAtDistance(type, pos, distance, value); ++ } ++ ++ public boolean removeRegionTicketAtDistance(TicketType tickettype, ChunkPos chunkcoordintpair, int i, T t0) { ++ // CraftBukkit end + Ticket ticket = new Ticket<>(tickettype, ChunkLevel.byStatus(FullChunkStatus.FULL) - i, t0); + long j = chunkpos.toLong(); + +- this.removeTicket(j, ticket); ++ boolean removed = this.removeTicket(j, ticket); // CraftBukkit + this.tickingTicketsTracker.removeTicket(j, ticket); ++ return removed; // CraftBukkit + } + + private SortedArraySet> getTickets(long i) { +@@ -249,6 +281,7 @@ + ChunkPos chunkpos = sectionpos.chunk(); + long i = chunkpos.toLong(); + ObjectSet objectset = (ObjectSet) this.playersPerChunk.get(i); ++ if (objectset == null) return; // CraftBukkit - SPIGOT-6208 + + objectset.remove(serverplayer); + if (objectset.isEmpty()) { +@@ -378,6 +411,26 @@ + return !this.tickets.isEmpty(); + } + ++ // CraftBukkit start ++ public void removeAllTicketsFor(TicketType ticketType, int ticketLevel, T ticketIdentifier) { ++ Ticket target = new Ticket<>(ticketType, ticketLevel, ticketIdentifier); ++ ++ for (java.util.Iterator>>> iterator = this.tickets.long2ObjectEntrySet().fastIterator(); iterator.hasNext();) { ++ Entry>> entry = iterator.next(); ++ SortedArraySet> tickets = entry.getValue(); ++ if (tickets.remove(target)) { ++ // copied from removeTicket ++ this.ticketTracker.update(entry.getLongKey(), getTicketLevelAt(tickets), false); ++ ++ // can't use entry after it's removed ++ if (tickets.isEmpty()) { ++ iterator.remove(); ++ } ++ } ++ } ++ } ++ // CraftBukkit end ++ + private class ChunkTicketTracker extends ChunkTracker { + + private static final int MAX_LEVEL = ChunkLevel.MAX_LEVEL + 1; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ServerChunkCache.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ServerChunkCache.java.patch new file mode 100644 index 0000000000..5e59873968 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ServerChunkCache.java.patch @@ -0,0 +1,139 @@ +--- a/net/minecraft/server/level/ServerChunkCache.java ++++ b/net/minecraft/server/level/ServerChunkCache.java +@@ -83,6 +83,16 @@ + this.clearCache(); + } + ++ // CraftBukkit start - properly implement isChunkLoaded ++ public boolean isChunkLoaded(int chunkX, int chunkZ) { ++ ChunkHolder chunk = this.chunkMap.getUpdatingChunkIfPresent(ChunkPos.asLong(chunkX, chunkZ)); ++ if (chunk == null) { ++ return false; ++ } ++ return chunk.getFullChunkNow() != null; ++ } ++ // CraftBukkit end ++ + @Override + @Override + public ThreadedLevelLightEngine getLightEngine() { +@@ -127,10 +135,10 @@ + ChunkAccess chunkaccess; + + for (int l = 0; l < 4; ++l) { +- if (k == this.lastChunkPos[l] && chunkstatus == this.lastChunkStatus[l]) { +- chunkaccess = this.lastChunk[l]; +- if (chunkaccess != null || !flag) { +- return chunkaccess; ++ if (k == this.lastChunkPos[l] && requiredStatus == this.lastChunkStatus[l]) { ++ ichunkaccess = this.lastChunk[l]; ++ if (ichunkaccess != null) { // CraftBukkit - the chunk can become accessible in the meantime TODO for non-null chunks it might also make sense to check that the chunk's state hasn't changed in the meantime ++ return ichunkaccess; + } + } + } +@@ -231,10 +238,18 @@ + int l = ChunkLevel.byStatus(chunkstatus); + ChunkHolder chunkholder = this.getVisibleChunkIfPresent(k); + +- if (flag) { +- this.distanceManager.addTicket(TicketType.UNKNOWN, chunkpos, l, chunkpos); +- if (this.chunkAbsent(chunkholder, l)) { +- ProfilerFiller profilerfiller = this.level.getProfiler(); ++ // CraftBukkit start - don't add new ticket for currently unloading chunk ++ boolean currentlyUnloading = false; ++ if (playerchunk != null) { ++ FullChunkStatus oldChunkState = ChunkLevel.fullStatus(playerchunk.oldTicketLevel); ++ FullChunkStatus currentChunkState = ChunkLevel.fullStatus(playerchunk.getTicketLevel()); ++ currentlyUnloading = (oldChunkState.isOrAfter(FullChunkStatus.FULL) && !currentChunkState.isOrAfter(FullChunkStatus.FULL)); ++ } ++ if (load && !currentlyUnloading) { ++ // CraftBukkit end ++ this.distanceManager.addTicket(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); ++ if (this.chunkAbsent(playerchunk, l)) { ++ ProfilerFiller gameprofilerfiller = this.level.getProfiler(); + + profilerfiller.push("chunkLoad"); + this.runDistanceManagerUpdates(); +@@ -249,8 +264,8 @@ + return this.chunkAbsent(chunkholder, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : chunkholder.getOrScheduleFuture(chunkstatus, this.chunkMap); + } + +- private boolean chunkAbsent(@Nullable ChunkHolder chunkholder, int i) { +- return chunkholder == null || chunkholder.getTicketLevel() > i; ++ private boolean chunkAbsent(@Nullable ChunkHolder chunkHolder, int status) { ++ return chunkHolder == null || chunkHolder.oldTicketLevel > status; // CraftBukkit using oldTicketLevel for isLoaded checks + } + + @Override +@@ -335,11 +346,31 @@ + @Override + @Override + public void close() throws IOException { +- this.save(true); ++ // CraftBukkit start ++ close(true); ++ } ++ ++ public void close(boolean save) throws IOException { ++ if (save) { ++ this.save(true); ++ } ++ // CraftBukkit end + this.lightEngine.close(); + this.chunkMap.close(); + } + ++ // CraftBukkit start - modelled on below ++ public void purgeUnload() { ++ this.level.getProfiler().push("purge"); ++ this.distanceManager.purgeStaleTickets(); ++ this.runDistanceManagerUpdates(); ++ this.level.getProfiler().popPush("unload"); ++ this.chunkMap.tick(() -> true); ++ this.level.getProfiler().pop(); ++ this.clearCache(); ++ } ++ // CraftBukkit end ++ + @Override + @Override + public void tick(BooleanSupplier booleansupplier, boolean flag) { +@@ -385,13 +415,13 @@ + int k = this.distanceManager.getNaturalSpawnChunkCount(); + NaturalSpawner.SpawnState naturalspawner_spawnstate = NaturalSpawner.createState(k, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap)); + +- this.lastSpawnState = naturalspawner_spawnstate; +- profilerfiller.popPush("spawnAndTick"); +- boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING); ++ this.lastSpawnState = spawnercreature_d; ++ gameprofilerfiller.popPush("spawnAndTick"); ++ boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit + + Util.shuffle(list, this.level.random); + int l = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); +- boolean flag1 = this.level.getLevelData().getGameTime() % 400L == 0L; ++ boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit + Iterator iterator1 = list.iterator(); + + while (iterator1.hasNext()) { +@@ -604,7 +624,9 @@ + } + + @Override +- protected boolean pollTask() { ++ // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task ++ public boolean pollTask() { ++ try { + if (ServerChunkCache.this.runDistanceManagerUpdates()) { + return true; + } else { +@@ -612,6 +636,8 @@ + return super.pollTask(); + } + } ++ // CraftBukkit end ++ } + } + + private static record ChunkAndHolder(LevelChunk chunk, ChunkHolder holder) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ServerEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ServerEntity.java.patch new file mode 100644 index 0000000000..fc4abd4089 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ServerEntity.java.patch @@ -0,0 +1,146 @@ +--- a/net/minecraft/server/level/ServerEntity.java ++++ b/net/minecraft/server/level/ServerEntity.java +@@ -42,6 +41,13 @@ + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.server.network.ServerPlayerConnection; ++import net.minecraft.util.Mth; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerVelocityEvent; ++// CraftBukkit end ++ + public class ServerEntity { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -66,8 +72,12 @@ + private boolean wasOnGround; + @Nullable + private List> trackedDataValues; ++ // CraftBukkit start ++ private final Set trackedPlayers; + +- public ServerEntity(ServerLevel serverlevel, Entity entity, int i, boolean flag, Consumer> consumer) { ++ public ServerEntity(ServerLevel worldserver, Entity entity, int i, boolean flag, Consumer> consumer, Set trackedPlayers) { ++ this.trackedPlayers = trackedPlayers; ++ // CraftBukkit end + this.ap = Vec3.ZERO; + this.lastPassengers = Collections.emptyList(); + this.level = serverlevel; +@@ -87,7 +97,7 @@ + List list = this.entity.getPassengers(); + + if (!list.equals(this.lastPassengers)) { +- this.broadcast.accept(new ClientboundSetPassengersPacket(this.entity)); ++ this.broadcastAndSend(new ClientboundSetPassengersPacket(this.entity)); // CraftBukkit + removedPassengers(list, this.lastPassengers).forEach((entity) -> { + if (entity instanceof ServerPlayer) { + ServerPlayer serverplayer = (ServerPlayer) entity; +@@ -104,18 +114,18 @@ + if (entity instanceof ItemFrame) { + ItemFrame itemframe = (ItemFrame) entity; + +- if (this.tickCount % 10 == 0) { +- ItemStack itemstack = itemframe.getItem(); ++ if (true || this.tickCount % 10 == 0) { // CraftBukkit - Moved below, should always enter this block ++ ItemStack itemstack = entityitemframe.getItem(); + +- if (itemstack.getItem() instanceof MapItem) { ++ if (this.tickCount % 10 == 0 && itemstack.getItem() instanceof MapItem) { // CraftBukkit - Moved this.tickCounter % 10 logic here so item frames do not enter the other blocks + Integer integer = MapItem.getMapId(itemstack); + MapItemSavedData mapitemsaveddata = MapItem.getSavedData(integer, this.level); + +- if (mapitemsaveddata != null) { +- Iterator iterator = this.level.players().iterator(); ++ if (worldmap != null) { ++ Iterator iterator = this.trackedPlayers.iterator(); // CraftBukkit + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = iterator.next().getPlayer(); // CraftBukkit + + mapitemsaveddata.tickCarriedBy(serverplayer, itemstack); + Packet packet = mapitemsaveddata.getUpdatePacket(integer, serverplayer); +@@ -228,7 +238,27 @@ + + ++this.tickCount; + if (this.entity.hurtMarked) { +- this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity)); ++ // CraftBukkit start - Create PlayerVelocity event ++ boolean cancelled = false; ++ ++ if (this.entity instanceof ServerPlayer) { ++ Player player = (Player) this.entity.getBukkitEntity(); ++ org.bukkit.util.Vector velocity = player.getVelocity(); ++ ++ PlayerVelocityEvent event = new PlayerVelocityEvent(player, velocity.clone()); ++ this.entity.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ cancelled = true; ++ } else if (!velocity.equals(event.getVelocity())) { ++ player.setVelocity(event.getVelocity()); ++ } ++ } ++ ++ if (!cancelled) { ++ this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity)); ++ } ++ // CraftBukkit end + this.entity.hurtMarked = false; + } + +@@ -256,7 +286,10 @@ + + public void sendPairingData(ServerPlayer serverplayer, Consumer> consumer) { + if (this.entity.isRemoved()) { +- ServerEntity.LOGGER.warn("Fetching packet for removed entity {}", this.entity); ++ // CraftBukkit start - Remove useless error spam, just return ++ // EntityTrackerEntry.LOGGER.warn("Fetching packet for removed entity {}", this.entity); ++ return; ++ // CraftBukkit end + } + + Packet packet = this.entity.getAddEntityPacket(); +@@ -272,6 +305,12 @@ + if (this.entity instanceof LivingEntity) { + Collection collection = ((LivingEntity) this.entity).getAttributes().getSyncableAttributes(); + ++ // CraftBukkit start - If sending own attributes send scaled health instead of current maximum health ++ if (this.entity.getId() == player.getId()) { ++ ((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(collection, false); ++ } ++ // CraftBukkit end ++ + if (!collection.isEmpty()) { + consumer.accept(new ClientboundUpdateAttributesPacket(this.entity.getId(), collection)); + } +@@ -303,8 +342,15 @@ + if (!list.isEmpty()) { + consumer.accept(new ClientboundSetEquipmentPacket(this.entity.getId(), list)); + } ++ ((LivingEntity) this.entity).detectEquipmentUpdatesPublic(); // CraftBukkit - SPIGOT-3789: sync again immediately after sending + } + ++ // CraftBukkit start - MC-109346: Fix for nonsensical head yaw ++ if (this.entity instanceof ServerPlayer) { ++ consumer.accept(new ClientboundRotateHeadPacket(this.entity, (byte) Mth.floor(this.entity.getYHeadRot() * 256.0F / 360.0F))); ++ } ++ // CraftBukkit end ++ + if (!this.entity.getPassengers().isEmpty()) { + consumer.accept(new ClientboundSetPassengersPacket(this.entity)); + } +@@ -338,6 +384,11 @@ + Set set = ((LivingEntity) this.entity).getAttributes().getDirtyAttributes(); + + if (!set.isEmpty()) { ++ // CraftBukkit start - Send scaled max health ++ if (this.entity instanceof ServerPlayer) { ++ ((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(set, false); ++ } ++ // CraftBukkit end + this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), set)); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ServerLevel.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ServerLevel.java.patch new file mode 100644 index 0000000000..754c0d02de --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ServerLevel.java.patch @@ -0,0 +1,657 @@ +--- a/net/minecraft/server/level/ServerLevel.java ++++ b/net/minecraft/server/level/ServerLevel.java +@@ -163,6 +164,19 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.ticks.LevelTicks; + import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.WeatherType; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.generator.CustomWorldChunkManager; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.craftbukkit.util.WorldUUID; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.server.MapInitializeEvent; ++import org.bukkit.event.weather.LightningStrikeEvent; ++import org.bukkit.event.world.GenericGameEvent; ++import org.bukkit.event.world.TimeSkipEvent; ++// CraftBukkit end + + public class ServerLevel extends Level implements WorldGenLevel { + +@@ -177,7 +191,7 @@ + final List players; + private final ServerChunkCache chunkSource; + private final MinecraftServer server; +- private final ServerLevelData serverLevelData; ++ public final PrimaryLevelData serverLevelData; // CraftBukkit - type + final EntityTickList entityTickList; + private final PersistentEntitySectionManager entityManager; + private final GameEventDispatcher gameEventDispatcher; +@@ -202,12 +216,30 @@ + private final boolean tickTime; + private final RandomSequences randomSequences; + +- public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess, ServerLevelData serverleveldata, ResourceKey resourcekey, LevelStem levelstem, ChunkProgressListener chunkprogresslistener, boolean flag, long i, List list, boolean flag1, @Nullable RandomSequences randomsequences) { +- RegistryAccess.Frozen registryaccess_frozen = minecraftserver.registryAccess(); +- Holder holder = levelstem.type(); ++ // CraftBukkit start ++ public final LevelStorageSource.LevelStorageAccess convertable; ++ public final UUID uuid; + +- Objects.requireNonNull(minecraftserver); +- super(serverleveldata, resourcekey, registryaccess_frozen, holder, minecraftserver::getProfiler, false, flag, i, minecraftserver.getMaxChainedNeighborUpdates()); ++ public LevelChunk getChunkIfLoaded(int x, int z) { ++ return this.chunkSource.getChunk(x, z, false); ++ } ++ ++ @Override ++ public ResourceKey getTypeKey() { ++ return convertable.dimensionType; ++ } ++ ++ // Add env and gen to constructor, IWorldDataServer -> WorldDataServer ++ public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List list, boolean flag1, @Nullable RandomSequences randomsequences, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) { ++ // IRegistryCustom.Dimension iregistrycustom_dimension = minecraftserver.registryAccess(); // CraftBukkit - decompile error ++ // Holder holder = worlddimension.type(); // CraftBukkit - decompile error ++ ++ // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error ++ super(iworlddataserver, resourcekey, minecraftserver.registryAccess(), worlddimension.type(), minecraftserver::getProfiler, false, flag, i, minecraftserver.getMaxChainedNeighborUpdates(), gen, biomeProvider, env); ++ this.pvpMode = minecraftserver.isPvpAllowed(); ++ convertable = convertable_conversionsession; ++ uuid = WorldUUID.getUUID(convertable_conversionsession.levelDirectory.path().toFile()); ++ // CraftBukkit end + this.players = Lists.newArrayList(); + this.entityTickList = new EntityTickList(); + this.blockTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded, this.getProfilerSupplier()); +@@ -219,8 +251,24 @@ + this.tickTime = flag1; + this.server = minecraftserver; + this.customSpawners = list; +- this.serverLevelData = serverleveldata; +- ChunkGenerator chunkgenerator = levelstem.generator(); ++ this.serverLevelData = iworlddataserver; ++ ChunkGenerator chunkgenerator = worlddimension.generator(); ++ // CraftBukkit start ++ serverLevelData.setWorld(this); ++ ++ if (biomeProvider != null) { ++ BiomeSource worldChunkManager = new CustomWorldChunkManager(getWorld(), biomeProvider, server.registryAccess().registryOrThrow(Registries.BIOME)); ++ if (chunkgenerator instanceof NoiseBasedChunkGenerator cga) { ++ chunkgenerator = new NoiseBasedChunkGenerator(worldChunkManager, cga.settings); ++ } else if (chunkgenerator instanceof FlatLevelSource cpf) { ++ chunkgenerator = new FlatLevelSource(cpf.settings(), worldChunkManager); ++ } ++ } ++ ++ if (gen != null) { ++ chunkgenerator = new org.bukkit.craftbukkit.generator.CustomChunkGenerator(this, chunkgenerator, gen); ++ } ++ // CraftBukkit end + boolean flag2 = minecraftserver.forceSynchronousWrites(); + DataFixer datafixer = minecraftserver.getFixerUpper(); + EntityPersistentStorage entitypersistentstorage = new EntityStorage(this, levelstoragesource_levelstorageaccess.getDimensionPath(resourcekey).resolve("entities"), datafixer, flag2, minecraftserver); +@@ -248,9 +296,9 @@ + long l = minecraftserver.getWorldData().worldGenOptions().seed(); + + this.structureCheck = new StructureCheck(this.chunkSource.chunkScanner(), this.registryAccess(), minecraftserver.getStructureManager(), resourcekey, chunkgenerator, this.chunkSource.randomState(), this, chunkgenerator.getBiomeSource(), l, datafixer); +- this.structureManager = new StructureManager(this, minecraftserver.getWorldData().worldGenOptions(), this.structureCheck); +- if (this.dimension() == Level.END && this.dimensionTypeRegistration().is(BuiltinDimensionTypes.END)) { +- this.dragonFight = new EndDragonFight(this, l, minecraftserver.getWorldData().endDragonFightData()); ++ this.structureManager = new StructureManager(this, this.serverLevelData.worldGenOptions(), structureCheck); // CraftBukkit ++ if ((this.dimension() == Level.END && this.dimensionTypeRegistration().is(BuiltinDimensionTypes.END)) || env == org.bukkit.World.Environment.THE_END) { // CraftBukkit - Allow to create EnderDragonBattle in default and custom END ++ this.dragonFight = new EndDragonFight(this, this.serverLevelData.worldGenOptions().seed(), this.serverLevelData.endDragonFightData()); // CraftBukkit + } else { + this.dragonFight = null; + } +@@ -260,6 +308,7 @@ + this.randomSequences = (RandomSequences) Objects.requireNonNullElseGet(randomsequences, () -> { + return (RandomSequences) this.getDataStorage().computeIfAbsent(RandomSequences.factory(l), "random_sequences"); + }); ++ this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit + } + + /** @deprecated */ +@@ -305,12 +353,18 @@ + long j; + + if (this.sleepStatus.areEnoughSleeping(i) && this.sleepStatus.areEnoughDeepSleeping(i, this.players)) { ++ // CraftBukkit start ++ j = this.levelData.getDayTime() + 24000L; ++ TimeSkipEvent event = new TimeSkipEvent(this.getWorld(), TimeSkipEvent.SkipReason.NIGHT_SKIP, (j - j % 24000L) - this.getDayTime()); + if (this.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { + j = this.levelData.getDayTime() + 24000L; + this.setDayTime(j - j % 24000L); + } + +- this.wakeUpAllPlayers(); ++ if (!event.isCancelled()) { ++ this.wakeUpAllPlayers(); ++ } ++ // CraftBukkit end + if (this.getGameRules().getBoolean(GameRules.RULE_WEATHER_CYCLE) && this.isRaining()) { + this.resetWeatherCycle(); + } +@@ -344,8 +400,8 @@ + } + + this.handlingTick = false; +- profilerfiller.pop(); +- boolean flag1 = !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); ++ gameprofilerfiller.pop(); ++ boolean flag1 = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players + + if (flag1) { + this.resetEmptyTime(); +@@ -361,7 +417,7 @@ + + this.entityTickList.forEach((entity) -> { + if (!entity.isRemoved()) { +- if (this.shouldDiscardEntity(entity)) { ++ if (false && this.shouldDiscardEntity(entity)) { // CraftBukkit - We prevent spawning in general, so this butchering is not needed + entity.discard(); + } else if (!tickratemanager.isEntityFrozen(entity)) { + profilerfiller.push("checkDespawn"); +@@ -457,20 +512,20 @@ + if (flag1) { + SkeletonHorse skeletonhorse = (SkeletonHorse) EntityType.SKELETON_HORSE.create(this); + +- if (skeletonhorse != null) { +- skeletonhorse.setTrap(true); +- skeletonhorse.setAge(0); +- skeletonhorse.setPos((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ()); +- this.addFreshEntity(skeletonhorse); ++ if (entityhorseskeleton != null) { ++ entityhorseskeleton.setTrap(true); ++ entityhorseskeleton.setAge(0); ++ entityhorseskeleton.setPos((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()); ++ this.addFreshEntity(entityhorseskeleton, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); // CraftBukkit + } + } + + LightningBolt lightningbolt = (LightningBolt) EntityType.LIGHTNING_BOLT.create(this); + +- if (lightningbolt != null) { +- lightningbolt.moveTo(Vec3.atBottomCenterOf(blockpos)); +- lightningbolt.setVisualOnly(flag1); +- this.addFreshEntity(lightningbolt); ++ if (entitylightning != null) { ++ entitylightning.moveTo(Vec3.atBottomCenterOf(blockposition)); ++ entitylightning.setVisualOnly(flag1); ++ this.strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.WEATHER); // CraftBukkit + } + } + } +@@ -525,8 +580,8 @@ + BlockPos blockpos2 = blockpos1.below(); + Biome biome = (Biome) this.getBiome(blockpos1).value(); + +- if (biome.shouldFreeze(this, blockpos2)) { +- this.setBlockAndUpdate(blockpos2, Blocks.ICE.defaultBlockState()); ++ if (biomebase.shouldFreeze(this, blockposition2)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition2, Blocks.ICE.defaultBlockState(), null); // CraftBukkit + } + + if (this.isRaining()) { +@@ -541,11 +596,11 @@ + if (j < Math.min(i, 8)) { + BlockState blockstate1 = (BlockState) blockstate.setValue(SnowLayerBlock.LAYERS, j + 1); + +- Block.pushEntitiesUp(blockstate, blockstate1, this, blockpos1); +- this.setBlockAndUpdate(blockpos1, blockstate1); ++ Block.pushEntitiesUp(iblockdata, iblockdata1, this, blockposition1); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, iblockdata1, null); // CraftBukkit + } + } else { +- this.setBlockAndUpdate(blockpos1, Blocks.SNOW.defaultBlockState()); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, Blocks.SNOW.defaultBlockState(), null); // CraftBukkit + } + } + +@@ -707,6 +761,7 @@ + this.rainLevel = Mth.clamp(this.rainLevel, 0.0F, 1.0F); + } + ++ /* CraftBukkit start + if (this.oRainLevel != this.rainLevel) { + this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, this.rainLevel), this.dimension()); + } +@@ -726,14 +787,41 @@ + this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, this.thunderLevel)); + } + ++ if (flag != this.isRaining()) { ++ // Only send weather packets to those affected ++ for (int idx = 0; idx < this.players.size(); ++idx) { ++ if (((ServerPlayer) this.players.get(idx)).level() == this) { ++ ((ServerPlayer) this.players.get(idx)).setPlayerWeather((!flag ? WeatherType.DOWNFALL : WeatherType.CLEAR), false); ++ } ++ } ++ } ++ for (int idx = 0; idx < this.players.size(); ++idx) { ++ if (((ServerPlayer) this.players.get(idx)).level() == this) { ++ ((ServerPlayer) this.players.get(idx)).updateWeather(this.oRainLevel, this.rainLevel, this.oThunderLevel, this.thunderLevel); ++ } ++ } ++ // CraftBukkit end ++ + } + + @VisibleForTesting + public void resetWeatherCycle() { +- this.serverLevelData.setRainTime(0); ++ // CraftBukkit start + this.serverLevelData.setRaining(false); +- this.serverLevelData.setThunderTime(0); ++ // If we stop due to everyone sleeping we should reset the weather duration to some other random value. ++ // Not that everyone ever manages to get the whole server to sleep at the same time.... ++ if (!this.serverLevelData.isRaining()) { ++ this.serverLevelData.setRainTime(0); ++ } ++ // CraftBukkit end + this.serverLevelData.setThundering(false); ++ // CraftBukkit start ++ // If we stop due to everyone sleeping we should reset the weather duration to some other random value. ++ // Not that everyone ever manages to get the whole server to sleep at the same time.... ++ if (!this.serverLevelData.isThundering()) { ++ this.serverLevelData.setThunderTime(0); ++ } ++ // CraftBukkit end + } + + public void resetEmptyTime() { +@@ -768,6 +856,7 @@ + }); + profilerfiller.incrementCounter("tickNonPassenger"); + entity.tick(); ++ entity.postTick(); // CraftBukkit + this.getProfiler().pop(); + Iterator iterator = entity.getPassengers().iterator(); + +@@ -789,10 +878,11 @@ + profilerfiller.push(() -> { + return BuiltInRegistries.ENTITY_TYPE.getKey(entity1.getType()).toString(); + }); +- profilerfiller.incrementCounter("tickPassenger"); +- entity1.rideTick(); +- profilerfiller.pop(); +- Iterator iterator = entity1.getPassengers().iterator(); ++ gameprofilerfiller.incrementCounter("tickPassenger"); ++ passengerEntity.rideTick(); ++ passengerEntity.postTick(); // CraftBukkit ++ gameprofilerfiller.pop(); ++ Iterator iterator = passengerEntity.getPassengers().iterator(); + + while (iterator.hasNext()) { + Entity entity2 = (Entity) iterator.next(); +@@ -815,9 +904,10 @@ + public void save(@Nullable ProgressListener progresslistener, boolean flag, boolean flag1) { + ServerChunkCache serverchunkcache = this.getChunkSource(); + +- if (!flag1) { +- if (progresslistener != null) { +- progresslistener.progressStartNoAbort(Component.translatable("menu.savingLevel")); ++ if (!skipSave) { ++ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit ++ if (progress != null) { ++ progress.progressStartNoAbort(Component.translatable("menu.savingLevel")); + } + + this.saveLevelData(); +@@ -833,11 +923,19 @@ + } + + } ++ ++ // CraftBukkit start - moved from MinecraftServer.saveChunks ++ ServerLevel worldserver1 = this; ++ ++ serverLevelData.setWorldBorder(worldserver1.getWorldBorder().createSettings()); ++ serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save()); ++ convertable.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData()); ++ // CraftBukkit end + } + + private void saveLevelData() { + if (this.dragonFight != null) { +- this.server.getWorldData().setEndDragonFightData(this.dragonFight.saveData()); ++ this.serverLevelData.setEndDragonFightData(this.dragonFight.saveData()); // CraftBukkit + } + + this.getChunkSource().getDataStorage().save(); +@@ -903,19 +1000,37 @@ + @Override + @Override + public boolean addFreshEntity(Entity entity) { +- return this.addEntity(entity); ++ // CraftBukkit start ++ return this.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.DEFAULT); + } + ++ @Override ++ public boolean addFreshEntity(Entity entity, CreatureSpawnEvent.SpawnReason reason) { ++ return this.addEntity(entity, reason); ++ // CraftBukkit end ++ } ++ + public boolean addWithUUID(Entity entity) { +- return this.addEntity(entity); ++ // CraftBukkit start ++ return this.addWithUUID(entity, CreatureSpawnEvent.SpawnReason.DEFAULT); + } + ++ public boolean addWithUUID(Entity entity, CreatureSpawnEvent.SpawnReason reason) { ++ return this.addEntity(entity, reason); ++ // CraftBukkit end ++ } ++ + public void addDuringTeleport(Entity entity) { +- this.addEntity(entity); ++ // CraftBukkit start ++ // SPIGOT-6415: Don't call spawn event for entities which travel trough worlds, ++ // since it is only an implementation detail, that a new entity is created when ++ // they are traveling between worlds. ++ this.addDuringTeleport(entity, null); + } + +- public void addDuringCommandTeleport(ServerPlayer serverplayer) { +- this.addPlayer(serverplayer); ++ public void addDuringTeleport(Entity entity, CreatureSpawnEvent.SpawnReason reason) { ++ this.addEntity(entity, reason); ++ // CraftBukkit end + } + + public void addDuringPortalTeleport(ServerPlayer serverplayer) { +@@ -942,24 +1061,37 @@ + this.entityManager.addNewEntity(serverplayer); + } + +- private boolean addEntity(Entity entity) { ++ // CraftBukkit start ++ private boolean addEntity(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { + if (entity.isRemoved()) { +- ServerLevel.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityType.getKey(entity.getType())); ++ // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getKey(entity.getType())); // CraftBukkit + return false; + } else { ++ // SPIGOT-6415: Don't call spawn event when reason is null. For example when an entity teleports to a new world. ++ if (spawnReason != null && !CraftEventFactory.doEntityAddEventCalling(this, entity, spawnReason)) { ++ return false; ++ } ++ // CraftBukkit end ++ + return this.entityManager.addNewEntity(entity); + } + } + + public boolean tryAddFreshEntityWithPassengers(Entity entity) { +- Stream stream = entity.getSelfAndPassengers().map(Entity::getUUID); ++ // CraftBukkit start ++ return this.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ public boolean tryAddFreshEntityWithPassengers(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ // CraftBukkit end ++ Stream stream = entity.getSelfAndPassengers().map(Entity::getUUID); // CraftBukkit - decompile error + PersistentEntitySectionManager persistententitysectionmanager = this.entityManager; + + Objects.requireNonNull(this.entityManager); + if (stream.anyMatch(persistententitysectionmanager::isLoaded)) { + return false; + } else { +- this.addFreshEntityWithPassengers(entity); ++ this.addFreshEntityWithPassengers(entity, reason); // CraftBukkit + return true; + } + } +@@ -973,11 +1105,33 @@ + serverplayer.remove(entity_removalreason); + } + ++ // CraftBukkit start ++ public boolean strikeLightning(Entity entitylightning) { ++ return this.strikeLightning(entitylightning, LightningStrikeEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean strikeLightning(Entity entitylightning, LightningStrikeEvent.Cause cause) { ++ LightningStrikeEvent lightning = CraftEventFactory.callLightningStrikeEvent((org.bukkit.entity.LightningStrike) entitylightning.getBukkitEntity(), cause); ++ ++ if (lightning.isCancelled()) { ++ return false; ++ } ++ ++ return this.addFreshEntity(entitylightning); ++ } ++ // CraftBukkit end ++ + @Override + @Override + public void destroyBlockProgress(int i, BlockPos blockpos, int j) { + Iterator iterator = this.server.getPlayerList().getPlayers().iterator(); + ++ // CraftBukkit start ++ Player entityhuman = null; ++ Entity entity = this.getEntity(breakerId); ++ if (entity instanceof Player) entityhuman = (Player) entity; ++ // CraftBukkit end ++ + while (iterator.hasNext()) { + ServerPlayer serverplayer = (ServerPlayer) iterator.next(); + +@@ -986,6 +1139,12 @@ + double d1 = (double) blockpos.getY() - serverplayer.getY(); + double d2 = (double) blockpos.getZ() - serverplayer.getZ(); + ++ // CraftBukkit start ++ if (entityhuman != null && !entityplayer.getBukkitEntity().canSee(entityhuman.getBukkitEntity())) { ++ continue; ++ } ++ // CraftBukkit end ++ + if (d0 * d0 + d1 * d1 + d2 * d2 < 1024.0D) { + serverplayer.connection.send(new ClientboundBlockDestructionPacket(i, blockpos, j)); + } +@@ -1051,8 +1204,19 @@ + Iterator iterator = this.navigatingMobs.iterator(); + + while (iterator.hasNext()) { +- Mob mob = (Mob) iterator.next(); +- PathNavigation pathnavigation = mob.getNavigation(); ++ // CraftBukkit start - fix SPIGOT-6362 ++ Mob entityinsentient; ++ try { ++ entityinsentient = (Mob) iterator.next(); ++ } catch (java.util.ConcurrentModificationException ex) { ++ // This can happen because the pathfinder update below may trigger a chunk load, which in turn may cause more navigators to register ++ // In this case we just run the update again across all the iterators as the chunk will then be loaded ++ // As this is a relative edge case it is much faster than copying navigators (on either read or write) ++ sendBlockUpdated(pos, oldState, newState, flags); ++ return; ++ } ++ // CraftBukkit end ++ PathNavigation navigationabstract = entityinsentient.getNavigation(); + + if (pathnavigation.shouldRecomputePath(blockpos)) { + list.add(pathnavigation); +@@ -1118,9 +1275,13 @@ + } + + @Override +- @Override +- public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.ExplosionInteraction level_explosioninteraction, ParticleOptions particleoptions, ParticleOptions particleoptions1, SoundEvent soundevent) { +- Explosion explosion = this.explode(entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, level_explosioninteraction, false, particleoptions, particleoptions1, soundevent); ++ public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.a world_a, ParticleOptions particleparam, ParticleOptions particleparam1, SoundEvent soundeffect) { ++ Explosion explosion = this.explode(entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, world_a, false, particleparam, particleparam1, soundeffect); ++ // CraftBukkit start ++ if (explosion.wasCanceled) { ++ return explosion; ++ } ++ // CraftBukkit end + + if (!explosion.interactsWithBlocks()) { + explosion.clearToBlow(); +@@ -1196,14 +1353,21 @@ + return this.server.getStructureManager(); + } + +- public int sendParticles(T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6) { +- ClientboundLevelParticlesPacket clientboundlevelparticlespacket = new ClientboundLevelParticlesPacket(t0, false, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i); ++ public int sendParticles(T type, double posX, double d1, double posY, int i, double posZ, double d4, double particleCount, double xOffset) { ++ // CraftBukkit - visibility api support ++ return sendParticles(null, type, posX, d1, posY, i, posZ, d4, particleCount, xOffset, false); ++ } ++ ++ public int sendParticles(ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { ++ ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(t0, force, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i); ++ // CraftBukkit end + int j = 0; + + for (int k = 0; k < this.players.size(); ++k) { +- ServerPlayer serverplayer = (ServerPlayer) this.players.get(k); ++ ServerPlayer entityplayer = (ServerPlayer) this.players.get(k); ++ if (sender != null && !entityplayer.getBukkitEntity().canSee(sender.getBukkitEntity())) continue; // CraftBukkit + +- if (this.sendParticles(serverplayer, false, d0, d1, d2, clientboundlevelparticlespacket)) { ++ if (this.sendParticles(entityplayer, force, d0, d1, d2, packetplayoutworldparticles)) { // CraftBukkit + ++j; + } + } +@@ -1254,8 +1417,8 @@ + } + + @Nullable +- public BlockPos findNearestMapStructure(TagKey tagkey, BlockPos blockpos, int i, boolean flag) { +- if (!this.server.getWorldData().worldGenOptions().generateStructures()) { ++ public BlockPos findNearestMapStructure(TagKey structureTag, BlockPos pos, int radius, boolean skipExistingChunks) { ++ if (!this.serverLevelData.worldGenOptions().generateStructures()) { // CraftBukkit + return null; + } else { + Optional> optional = this.registryAccess().registryOrThrow(Registries.STRUCTURE).getTag(tagkey); +@@ -1299,15 +1459,24 @@ + + @Nullable + @Override +- @Override +- public MapItemSavedData getMapData(String s) { +- return (MapItemSavedData) this.getServer().overworld().getDataStorage().get(MapItemSavedData.factory(), s); ++ public MapItemSavedData getMapData(String mapName) { ++ // CraftBukkit start ++ MapItemSavedData worldmap = (MapItemSavedData) this.getServer().overworld().getDataStorage().get(MapItemSavedData.factory(), mapName); ++ if (worldmap != null) { ++ worldmap.id = mapName; ++ } ++ return worldmap; ++ // CraftBukkit end + } + + @Override +- @Override +- public void setMapData(String s, MapItemSavedData mapitemsaveddata) { +- this.getServer().overworld().getDataStorage().set(s, mapitemsaveddata); ++ public void setMapData(String mapName, MapItemSavedData data) { ++ // CraftBukkit start ++ data.id = mapName; ++ MapInitializeEvent event = new MapInitializeEvent(data.mapView); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ // CraftBukkit end ++ this.getServer().overworld().getDataStorage().set(mapName, data); + } + + @Override +@@ -1608,7 +1773,12 @@ + @Override + public void blockUpdated(BlockPos blockpos, Block block) { + if (!this.isDebug()) { +- this.updateNeighborsAt(blockpos, block); ++ // CraftBukkit start ++ if (populating) { ++ return; ++ } ++ // CraftBukkit end ++ this.updateNeighborsAt(pos, block); + } + + } +@@ -1629,13 +1797,13 @@ + } + + public boolean isFlat() { +- return this.server.getWorldData().isFlatWorld(); ++ return this.serverLevelData.isFlatWorld(); // CraftBukkit + } + + @Override + @Override + public long getSeed() { +- return this.server.getWorldData().worldGenOptions().seed(); ++ return this.serverLevelData.worldGenOptions().seed(); // CraftBukkit + } + + @Nullable +@@ -1678,18 +1844,34 @@ + } + } + +- public static void makeObsidianPlatform(ServerLevel serverlevel) { +- BlockPos blockpos = ServerLevel.END_SPAWN_POINT; +- int i = blockpos.getX(); +- int j = blockpos.getY() - 2; +- int k = blockpos.getZ(); ++ public static void makeObsidianPlatform(ServerLevel serverLevel) { ++ // CraftBukkit start ++ ServerLevel.makeObsidianPlatform(serverLevel, null); ++ } + +- BlockPos.betweenClosed(i - 2, j + 1, k - 2, i + 2, j + 3, k + 2).forEach((blockpos1) -> { +- serverlevel.setBlockAndUpdate(blockpos1, Blocks.AIR.defaultBlockState()); ++ public static void makeObsidianPlatform(ServerLevel worldserver, Entity entity) { ++ // CraftBukkit end ++ BlockPos blockposition = ServerLevel.END_SPAWN_POINT; ++ int i = blockposition.getX(); ++ int j = blockposition.getY() - 2; ++ int k = blockposition.getZ(); ++ ++ // CraftBukkit start ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(worldserver); ++ BlockPos.betweenClosed(i - 2, j + 1, k - 2, i + 2, j + 3, k + 2).forEach((blockposition1) -> { ++ blockList.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3); + }); + BlockPos.betweenClosed(i - 2, j, k - 2, i + 2, j, k + 2).forEach((blockpos1) -> { + serverlevel.setBlockAndUpdate(blockpos1, Blocks.OBSIDIAN.defaultBlockState()); + }); ++ org.bukkit.World bworld = worldserver.getWorld(); ++ org.bukkit.event.world.PortalCreateEvent portalEvent = new org.bukkit.event.world.PortalCreateEvent((List) (List) blockList.getList(), bworld, (entity == null) ? null : entity.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM); ++ ++ worldserver.getCraftServer().getPluginManager().callEvent(portalEvent); ++ if (!portalEvent.isCancelled()) { ++ blockList.updateList(); ++ } ++ // CraftBukkit end + } + + @Override +@@ -1833,6 +2005,8 @@ + } + + entity.updateDynamicGameEventListener(DynamicGameEventListener::add); ++ entity.inWorld = true; // CraftBukkit - Mark entity as in world ++ entity.valid = true; // CraftBukkit + } + + @Override +@@ -1870,6 +2043,14 @@ + } + + entity.updateDynamicGameEventListener(DynamicGameEventListener::remove); ++ // CraftBukkit start ++ entity.valid = false; ++ if (!(entity instanceof ServerPlayer)) { ++ for (ServerPlayer player : players) { ++ player.getBukkitEntity().onEntityRemove(entity); ++ } ++ } ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ServerPlayer.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ServerPlayer.java.patch new file mode 100644 index 0000000000..eb83e16f4a --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ServerPlayer.java.patch @@ -0,0 +1,1159 @@ +--- a/net/minecraft/server/level/ServerPlayer.java ++++ b/net/minecraft/server/level/ServerPlayer.java +@@ -155,7 +162,29 @@ + import net.minecraft.world.scores.ScoreHolder; + import net.minecraft.world.scores.Team; + import net.minecraft.world.scores.criteria.ObjectiveCriteria; +-import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.WeatherType; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.CraftWorldBorder; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.event.CraftPortalEvent; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftDimensionUtil; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.entity.EntityExhaustionEvent; ++import org.bukkit.event.player.PlayerBedLeaveEvent; ++import org.bukkit.event.player.PlayerChangedMainHandEvent; ++import org.bukkit.event.player.PlayerChangedWorldEvent; ++import org.bukkit.event.player.PlayerLocaleChangeEvent; ++import org.bukkit.event.player.PlayerPortalEvent; ++import org.bukkit.event.player.PlayerSpawnChangeEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; ++import org.bukkit.event.player.PlayerToggleSneakEvent; ++import org.bukkit.inventory.MainHand; ++// CraftBukkit end + + public class ServerPlayer extends Player { + +@@ -192,7 +221,7 @@ + private int levitationStartTime; + private boolean disconnected; + private int requestedViewDistance; +- private String language; ++ public String language = "en_us"; // CraftBukkit - default + @Nullable + private Vec3 startingToFallPosition; + @Nullable +@@ -217,8 +246,22 @@ + private int containerCounter; + public boolean wonGame; + +- public ServerPlayer(MinecraftServer minecraftserver, ServerLevel serverlevel, GameProfile gameprofile, ClientInformation clientinformation) { +- super(serverlevel, serverlevel.getSharedSpawnPos(), serverlevel.getSharedSpawnAngle(), gameprofile); ++ // CraftBukkit start ++ public String displayName; ++ public Component listName; ++ public org.bukkit.Location compassTarget; ++ public int newExp = 0; ++ public int newLevel = 0; ++ public int newTotalExp = 0; ++ public boolean keepLevel = false; ++ public double maxHealthCache; ++ public boolean joining = true; ++ public boolean sentListPacket = false; ++ public String kickLeaveMessage = null; // SPIGOT-3034: Forward leave message to PlayerQuitEvent ++ // CraftBukkit end ++ ++ public ServerPlayer(MinecraftServer minecraftserver, ServerLevel worldserver, GameProfile gameprofile, ClientInformation clientinformation) { ++ super(worldserver, worldserver.getSharedSpawnPos(), worldserver.getSharedSpawnAngle(), gameprofile); + this.chatVisibility = ChatVisiblity.FULL; + this.canChatColor = true; + this.lastActionTime = Util.getMillis(); +@@ -289,6 +326,11 @@ + this.setMaxUpStep(1.0F); + this.fudgeSpawnLocation(serverlevel); + this.updateOptions(clientinformation); ++ ++ // CraftBukkit start ++ this.displayName = this.getScoreboardName(); ++ this.bukkitPickUpLoot = true; ++ this.maxHealthCache = this.getMaxHealth(); + } + + private void fudgeSpawnLocation(ServerLevel serverlevel) { +@@ -318,9 +362,46 @@ + int k2 = i2 / (i * 2 + 1); + BlockPos blockpos1 = PlayerRespawnLogic.getOverworldRespawnPos(serverlevel, blockpos.getX() + j2 - i, blockpos.getZ() + k2 - i); + +- if (blockpos1 != null) { +- this.moveTo(blockpos1, 0.0F, 0.0F); +- if (serverlevel.noCollision((Entity) this)) { ++ if (blockposition1 != null) { ++ return blockposition1; ++ } ++ } ++ } ++ ++ return blockposition; ++ } ++ // CraftBukkit end ++ ++ private void fudgeSpawnLocation(ServerLevel level) { ++ BlockPos blockposition = level.getSharedSpawnPos(); ++ ++ if (level.dimensionType().hasSkyLight() && level.serverLevelData.getGameType() != GameType.ADVENTURE) { // CraftBukkit ++ int i = Math.max(0, this.server.getSpawnRadius(level)); ++ int j = Mth.floor(level.getWorldBorder().getDistanceToBorder((double) blockposition.getX(), (double) blockposition.getZ())); ++ ++ if (j < i) { ++ i = j; ++ } ++ ++ if (j <= 1) { ++ i = 1; ++ } ++ ++ long k = (long) (i * 2 + 1); ++ long l = k * k; ++ int i1 = l > 2147483647L ? Integer.MAX_VALUE : (int) l; ++ int j1 = this.getCoprime(i1); ++ int k1 = RandomSource.create().nextInt(i1); ++ ++ for (int l1 = 0; l1 < i1; ++l1) { ++ int i2 = (k1 + j1 * l1) % i1; ++ int j2 = i2 % (i * 2 + 1); ++ int k2 = i2 / (i * 2 + 1); ++ BlockPos blockposition1 = PlayerRespawnLogic.getOverworldRespawnPos(level, blockposition.getX() + j2 - i, blockposition.getZ() + k2 - i); ++ ++ if (blockposition1 != null) { ++ this.moveTo(blockposition1, 0.0F, 0.0F); ++ if (level.noCollision((Entity) this)) { + break; + } + } +@@ -363,17 +443,26 @@ + if (compoundtag.contains("recipeBook", 10)) { + this.recipeBook.fromNbt(compoundtag.getCompound("recipeBook"), this.server.getRecipeManager()); + } ++ this.getBukkitEntity().readExtraData(compound); // CraftBukkit + + if (this.isSleeping()) { + this.stopSleeping(); + } + +- if (compoundtag.contains("SpawnX", 99) && compoundtag.contains("SpawnY", 99) && compoundtag.contains("SpawnZ", 99)) { +- this.respawnPosition = new BlockPos(compoundtag.getInt("SpawnX"), compoundtag.getInt("SpawnY"), compoundtag.getInt("SpawnZ")); +- this.respawnForced = compoundtag.getBoolean("SpawnForced"); +- this.respawnAngle = compoundtag.getFloat("SpawnAngle"); +- if (compoundtag.contains("SpawnDimension")) { +- DataResult dataresult1 = Level.RESOURCE_KEY_CODEC.parse(NbtOps.INSTANCE, compoundtag.get("SpawnDimension")); ++ // CraftBukkit start ++ String spawnWorld = compound.getString("SpawnWorld"); ++ CraftWorld oldWorld = (CraftWorld) Bukkit.getWorld(spawnWorld); ++ if (oldWorld != null) { ++ this.respawnDimension = oldWorld.getHandle().dimension(); ++ } ++ // CraftBukkit end ++ ++ if (compound.contains("SpawnX", 99) && compound.contains("SpawnY", 99) && compound.contains("SpawnZ", 99)) { ++ this.respawnPosition = new BlockPos(compound.getInt("SpawnX"), compound.getInt("SpawnY"), compound.getInt("SpawnZ")); ++ this.respawnForced = compound.getBoolean("SpawnForced"); ++ this.respawnAngle = compound.getFloat("SpawnAngle"); ++ if (compound.contains("SpawnDimension")) { ++ DataResult> dataresult1 = Level.RESOURCE_KEY_CODEC.parse(NbtOps.INSTANCE, compound.get("SpawnDimension")); // CraftBukkit - decompile error + Logger logger1 = ServerPlayer.LOGGER; + + Objects.requireNonNull(logger1); +@@ -408,14 +496,27 @@ + Entity entity = this.getRootVehicle(); + Entity entity1 = this.getVehicle(); + +- if (entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger()) { +- CompoundTag compoundtag2 = new CompoundTag(); +- CompoundTag compoundtag3 = new CompoundTag(); ++ // CraftBukkit start - handle non-persistent vehicles ++ boolean persistVehicle = true; ++ if (entity1 != null) { ++ Entity vehicle; ++ for (vehicle = entity1; vehicle != null; vehicle = vehicle.getVehicle()) { ++ if (!vehicle.persist) { ++ persistVehicle = false; ++ break; ++ } ++ } ++ } + +- entity.save(compoundtag3); +- compoundtag2.putUUID("Attach", entity1.getUUID()); +- compoundtag2.put("Entity", compoundtag3); +- compoundtag.put("RootVehicle", compoundtag2); ++ if (persistVehicle && entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger()) { ++ // CraftBukkit end ++ CompoundTag nbttagcompound2 = new CompoundTag(); ++ CompoundTag nbttagcompound3 = new CompoundTag(); ++ ++ entity.save(nbttagcompound3); ++ nbttagcompound2.putUUID("Attach", entity1.getUUID()); ++ nbttagcompound2.put("Entity", nbttagcompound3); ++ compound.put("RootVehicle", nbttagcompound2); + } + + compoundtag.put("recipeBook", this.recipeBook.toNbt()); +@@ -433,10 +534,34 @@ + compoundtag.put("SpawnDimension", tag); + }); + } ++ this.getBukkitEntity().setExtraData(compound); // CraftBukkit + + } + +- public void setExperiencePoints(int i) { ++ // CraftBukkit start - World fallback code, either respawn location or global spawn ++ public void spawnIn(Level world) { ++ this.setLevel(world); ++ if (world == null) { ++ this.unsetRemoved(); ++ Vec3 position = null; ++ if (this.respawnDimension != null) { ++ world = this.server.getLevel(this.respawnDimension); ++ if (world != null && this.getRespawnPosition() != null) { ++ position = Player.findRespawnPositionAndUseSpawnBlock((ServerLevel) world, this.getRespawnPosition(), this.getRespawnAngle(), false, false).orElse(null); ++ } ++ } ++ if (world == null || position == null) { ++ world = ((CraftWorld) Bukkit.getServer().getWorlds().get(0)).getHandle(); ++ position = Vec3.atCenterOf(world.getSharedSpawnPos()); ++ } ++ this.setLevel(world); ++ this.setPos(position); ++ } ++ this.gameMode.setLevel((ServerLevel) world); ++ } ++ // CraftBukkit end ++ ++ public void setExperiencePoints(int experiencePoints) { + float f = (float) this.getXpNeededForNextLevel(); + float f1 = (f - 1.0F) / f; + +@@ -501,6 +619,11 @@ + @Override + @Override + public void tick() { ++ // CraftBukkit start ++ if (this.joining) { ++ this.joining = false; ++ } ++ // CraftBukkit end + this.gameMode.tick(); + this.wardenSpawnTracker.tick(); + --this.spawnInvulnerableTime; +@@ -557,7 +680,7 @@ + } + + if (this.getHealth() != this.lastSentHealth || this.lastSentFood != this.foodData.getFoodLevel() || this.foodData.getSaturationLevel() == 0.0F != this.lastFoodSaturationZero) { +- this.connection.send(new ClientboundSetHealthPacket(this.getHealth(), this.foodData.getFoodLevel(), this.foodData.getSaturationLevel())); ++ this.connection.send(new ClientboundSetHealthPacket(this.getBukkitEntity().getScaledHealth(), this.foodData.getFoodLevel(), this.foodData.getSaturationLevel())); // CraftBukkit + this.lastSentHealth = this.getHealth(); + this.lastSentFood = this.foodData.getFoodLevel(); + this.lastFoodSaturationZero = this.foodData.getSaturationLevel() == 0.0F; +@@ -588,6 +711,12 @@ + this.updateScoreForCriteria(ObjectiveCriteria.EXPERIENCE, Mth.ceil((float) this.lastRecordedExperience)); + } + ++ // CraftBukkit start - Force max health updates ++ if (this.maxHealthCache != this.getMaxHealth()) { ++ this.getBukkitEntity().updateScaledHealth(); ++ } ++ // CraftBukkit end ++ + if (this.experienceLevel != this.lastRecordedLevel) { + this.lastRecordedLevel = this.experienceLevel; + this.updateScoreForCriteria(ObjectiveCriteria.LEVEL, Mth.ceil((float) this.lastRecordedLevel)); +@@ -602,6 +731,20 @@ + CriteriaTriggers.LOCATION.trigger(this); + } + ++ // CraftBukkit start - initialize oldLevel, fire PlayerLevelChangeEvent, and tick client-sided world border ++ if (this.oldLevel == -1) { ++ this.oldLevel = this.experienceLevel; ++ } ++ ++ if (this.oldLevel != this.experienceLevel) { ++ CraftEventFactory.callPlayerLevelChangeEvent(this.getBukkitEntity(), this.oldLevel, this.experienceLevel); ++ this.oldLevel = this.experienceLevel; ++ } ++ ++ if (this.getBukkitEntity().hasClientWorldBorder()) { ++ ((CraftWorldBorder) this.getBukkitEntity().getWorldBorder()).getHandle().tick(); ++ } ++ // CraftBukkit end + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking player"); + CrashReportCategory crashreportcategory = crashreport.addCategory("Player being ticked"); +@@ -644,9 +786,10 @@ + + } + +- private void updateScoreForCriteria(ObjectiveCriteria objectivecriteria, int i) { +- this.getScoreboard().forAllObjectives(objectivecriteria, this, (scoreaccess) -> { +- scoreaccess.set(i); ++ private void updateScoreForCriteria(ObjectiveCriteria criteria, int points) { ++ // CraftBukkit - Use our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(criteria, this, (scoreaccess) -> { ++ scoreaccess.set(points); + }); + } + +@@ -655,6 +797,12 @@ + public void die(DamageSource damagesource) { + this.gameEvent(GameEvent.ENTITY_DIE); + boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); ++ // CraftBukkit start - fire PlayerDeathEvent ++ if (this.isRemoved()) { ++ return; ++ } ++ java.util.List loot = new java.util.ArrayList(this.getInventory().getContainerSize()); ++ boolean keepInventory = this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || this.isSpectator(); + + if (flag) { + Component component = this.getCombatTracker().getDeathMessage(); +@@ -693,13 +875,17 @@ + this.dropAllDeathLoot(damagesource); + } + +- this.getScoreboard().forAllObjectives(ObjectiveCriteria.DEATH_COUNT, this, ScoreAccess::increment); +- LivingEntity livingentity = this.getKillCredit(); ++ this.setCamera(this); // Remove spectated target ++ // CraftBukkit end + +- if (livingentity != null) { +- this.awardStat(Stats.ENTITY_KILLED_BY.get(livingentity.getType())); +- livingentity.awardKillScore(this, this.deathScore, damagesource); +- this.createWitherRose(livingentity); ++ // CraftBukkit - Get our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(ObjectiveCriteria.DEATH_COUNT, this, ScoreAccess::increment); ++ LivingEntity entityliving = this.getKillCredit(); ++ ++ if (entityliving != null) { ++ this.awardStat(Stats.ENTITY_KILLED_BY.get(entityliving.getType())); ++ entityliving.awardKillScore(this, this.deathScore, cause); ++ this.createWitherRose(entityliving); + } + + this.level().broadcastEntityEvent(this, (byte) 3); +@@ -724,15 +910,16 @@ + } + + @Override +- @Override +- public void awardKillScore(Entity entity, int i, DamageSource damagesource) { +- if (entity != this) { +- super.awardKillScore(entity, i, damagesource); +- this.increaseScore(i); +- this.getScoreboard().forAllObjectives(ObjectiveCriteria.KILL_COUNT_ALL, this, ScoreAccess::increment); +- if (entity instanceof Player) { ++ public void awardKillScore(Entity killed, int scoreValue, DamageSource damageSource) { ++ if (killed != this) { ++ super.awardKillScore(killed, scoreValue, damageSource); ++ this.increaseScore(scoreValue); ++ // CraftBukkit - Get our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(ObjectiveCriteria.KILL_COUNT_ALL, this, ScoreAccess::increment); ++ if (killed instanceof Player) { + this.awardStat(Stats.PLAYER_KILLS); +- this.getScoreboard().forAllObjectives(ObjectiveCriteria.KILL_COUNT_PLAYERS, this, ScoreAccess::increment); ++ // CraftBukkit - Get our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(ObjectiveCriteria.KILL_COUNT_PLAYERS, this, ScoreAccess::increment); + } else { + this.awardStat(Stats.MOB_KILLS); + } +@@ -749,8 +936,9 @@ + if (playerteam != null) { + int i = playerteam.getColor().getId(); + +- if (i >= 0 && i < aobjectivecriteria.length) { +- this.getScoreboard().forAllObjectives(aobjectivecriteria[i], scoreholder, ScoreAccess::increment); ++ if (i >= 0 && i < aiscoreboardcriteria.length) { ++ // CraftBukkit - Get our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(aiscoreboardcriteria[i], scoreholder, ScoreAccess::increment); + } + } + +@@ -802,19 +988,20 @@ + } + + private boolean isPvpAllowed() { +- return this.server.isPvpAllowed(); ++ // CraftBukkit - this.server.isPvpAllowed() -> this.world.pvpMode ++ return this.level().pvpMode; + } + + @Nullable + @Override +- @Override +- protected PortalInfo findDimensionEntryPoint(ServerLevel serverlevel) { +- PortalInfo portalinfo = super.findDimensionEntryPoint(serverlevel); ++ protected PortalInfo findDimensionEntryPoint(ServerLevel destination) { ++ PortalInfo shapedetectorshape = super.findDimensionEntryPoint(destination); ++ destination = (shapedetectorshape == null) ? destination : shapedetectorshape.world; // CraftBukkit + +- if (portalinfo != null && this.level().dimension() == Level.OVERWORLD && serverlevel.dimension() == Level.END) { +- Vec3 vec3 = portalinfo.pos.add(0.0D, -1.0D, 0.0D); ++ if (shapedetectorshape != null && this.level().getTypeKey() == LevelStem.OVERWORLD && destination != null && destination.getTypeKey() == LevelStem.END) { // CraftBukkit ++ Vec3 vec3d = shapedetectorshape.pos.add(0.0D, -1.0D, 0.0D); + +- return new PortalInfo(vec3, Vec3.ZERO, 90.0F, 0.0F); ++ return new PortalInfo(vec3d, Vec3.ZERO, 90.0F, 0.0F, destination, shapedetectorshape.portalEventInfo); // CraftBukkit + } else { + return portalinfo; + } +@@ -822,13 +1009,21 @@ + + @Nullable + @Override +- @Override +- public Entity changeDimension(ServerLevel serverlevel) { +- this.isChangingDimension = true; +- ServerLevel serverlevel1 = this.serverLevel(); +- ResourceKey resourcekey = serverlevel1.dimension(); ++ public Entity changeDimension(ServerLevel server) { ++ // CraftBukkit start ++ return changeDimension(server, TeleportCause.UNKNOWN); ++ } + +- if (resourcekey == Level.END && serverlevel.dimension() == Level.OVERWORLD) { ++ @Nullable ++ public Entity changeDimension(ServerLevel worldserver, PlayerTeleportEvent.TeleportCause cause) { ++ // CraftBukkit end ++ if (this.isSleeping()) return this; // CraftBukkit - SPIGOT-3154 ++ // this.isChangingDimension = true; // CraftBukkit - Moved down and into PlayerList#changeDimension ++ ServerLevel worldserver1 = this.serverLevel(); ++ ResourceKey resourcekey = worldserver1.getTypeKey(); // CraftBukkit ++ ++ if (resourcekey == LevelStem.END && worldserver != null && worldserver.getTypeKey() == LevelStem.OVERWORLD) { // CraftBukkit ++ this.isChangingDimension = true; // CraftBukkit - Moved down from above + this.unRide(); + this.serverLevel().removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); + if (!this.wonGame) { +@@ -839,7 +1034,9 @@ + + return this; + } else { +- LevelData leveldata = serverlevel.getLevelData(); ++ // CraftBukkit start ++ /* ++ WorldData worlddata = worldserver.getLevelData(); + + this.connection.send(new ClientboundRespawnPacket(this.createCommonSpawnInfo(serverlevel), (byte) 3)); + this.connection.send(new ClientboundChangeDifficultyPacket(leveldata.getDifficulty(), leveldata.isDifficultyLocked())); +@@ -848,20 +1045,50 @@ + playerlist.sendPlayerPermissionLevel(this); + serverlevel1.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); + this.unsetRemoved(); +- PortalInfo portalinfo = this.findDimensionEntryPoint(serverlevel); ++ */ ++ // CraftBukkit end ++ PortalInfo shapedetectorshape = this.findDimensionEntryPoint(worldserver); + +- if (portalinfo != null) { +- serverlevel1.getProfiler().push("moving"); +- if (resourcekey == Level.OVERWORLD && serverlevel.dimension() == Level.NETHER) { ++ if (shapedetectorshape != null) { ++ worldserver1.getProfiler().push("moving"); ++ worldserver = shapedetectorshape.world; // CraftBukkit ++ if (worldserver == null) { } else // CraftBukkit - empty to fall through to null to event ++ if (resourcekey == LevelStem.OVERWORLD && worldserver.getTypeKey() == LevelStem.NETHER) { // CraftBukkit + this.enteredNetherPosition = this.position(); +- } else if (serverlevel.dimension() == Level.END) { +- this.createEndPlatform(serverlevel, BlockPos.containing(portalinfo.pos)); ++ } else if (worldserver.getTypeKey() == LevelStem.END && shapedetectorshape.portalEventInfo != null && shapedetectorshape.portalEventInfo.getCanCreatePortal()) { // CraftBukkit ++ this.createEndPlatform(worldserver, BlockPos.containing(shapedetectorshape.pos)); + } ++ // CraftBukkit start ++ } else { ++ return null; ++ } ++ Location enter = this.getBukkitEntity().getLocation(); ++ Location exit = (worldserver == null) ? null : CraftLocation.toBukkit(shapedetectorshape.pos, worldserver.getWorld(), shapedetectorshape.yRot, shapedetectorshape.xRot); ++ PlayerTeleportEvent tpEvent = new PlayerTeleportEvent(this.getBukkitEntity(), enter, exit, cause); ++ Bukkit.getServer().getPluginManager().callEvent(tpEvent); ++ if (tpEvent.isCancelled() || tpEvent.getTo() == null) { ++ return null; ++ } ++ exit = tpEvent.getTo(); ++ worldserver = ((CraftWorld) exit.getWorld()).getHandle(); ++ // CraftBukkit end + +- serverlevel1.getProfiler().pop(); +- serverlevel1.getProfiler().push("placing"); +- this.setServerLevel(serverlevel); +- this.connection.teleport(portalinfo.pos.x, portalinfo.pos.y, portalinfo.pos.z, portalinfo.yRot, portalinfo.xRot); ++ worldserver1.getProfiler().pop(); ++ worldserver1.getProfiler().push("placing"); ++ if (true) { // CraftBukkit ++ this.isChangingDimension = true; // CraftBukkit - Set teleport invulnerability only if player changing worlds ++ ++ this.connection.send(new ClientboundRespawnPacket(this.createCommonSpawnInfo(worldserver), (byte) 3)); ++ this.connection.send(new ClientboundChangeDifficultyPacket(this.level().getDifficulty(), this.level().getLevelData().isDifficultyLocked())); ++ PlayerList playerlist = this.server.getPlayerList(); ++ ++ playerlist.sendPlayerPermissionLevel(this); ++ worldserver1.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); ++ this.unsetRemoved(); ++ ++ // CraftBukkit end ++ this.setServerLevel(worldserver); ++ this.connection.teleport(exit); // CraftBukkit - use internal teleport without event + this.connection.resetPosition(); + serverlevel.addDuringPortalTeleport(this); + serverlevel1.getProfiler().pop(); +@@ -881,40 +1108,66 @@ + this.lastSentExp = -1; + this.lastSentHealth = -1.0F; + this.lastSentFood = -1; ++ ++ // CraftBukkit start ++ PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.getBukkitEntity(), worldserver1.getWorld()); ++ this.level().getCraftServer().getPluginManager().callEvent(changeEvent); ++ // CraftBukkit end + } + + return this; + } + } + +- private void createEndPlatform(ServerLevel serverlevel, BlockPos blockpos) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = blockpos.mutable(); ++ // CraftBukkit start ++ @Override ++ protected CraftPortalEvent callPortalEvent(Entity entity, ServerLevel exitWorldServer, Vec3 exitPosition, TeleportCause cause, int searchRadius, int creationRadius) { ++ Location enter = this.getBukkitEntity().getLocation(); ++ Location exit = CraftLocation.toBukkit(exitPosition, exitWorldServer.getWorld(), getYRot(), getXRot()); ++ PlayerPortalEvent event = new PlayerPortalEvent(this.getBukkitEntity(), enter, exit, cause, searchRadius, true, creationRadius); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null) { ++ return null; ++ } ++ return new CraftPortalEvent(event); ++ } ++ // CraftBukkit end + ++ private void createEndPlatform(ServerLevel level, BlockPos pos) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(level); // CraftBukkit ++ + for (int i = -2; i <= 2; ++i) { + for (int j = -2; j <= 2; ++j) { + for (int k = -1; k < 3; ++k) { + BlockState blockstate = k == -1 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); + +- serverlevel.setBlockAndUpdate(blockpos_mutableblockpos.set(blockpos).move(j, k, i), blockstate); ++ blockList.setBlock(blockposition_mutableblockposition.set(pos).move(j, k, i), iblockdata, 3); // CraftBukkit + } + } + } ++ // CraftBukkit start - call portal event ++ org.bukkit.event.world.PortalCreateEvent portalEvent = new org.bukkit.event.world.PortalCreateEvent((List) (List) blockList.getList(), level.getWorld(), this.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM); ++ level.getCraftServer().getPluginManager().callEvent(portalEvent); ++ if (!portalEvent.isCancelled()) { ++ blockList.updateList(); ++ } ++ // CraftBukkit end + + } + + @Override +- @Override +- protected Optional getExitPortal(ServerLevel serverlevel, BlockPos blockpos, boolean flag, WorldBorder worldborder) { +- Optional optional = super.getExitPortal(serverlevel, blockpos, flag, worldborder); ++ protected Optional getExitPortal(ServerLevel worldserver, BlockPos blockposition, boolean flag, WorldBorder worldborder, int searchRadius, boolean canCreatePortal, int createRadius) { // CraftBukkit ++ Optional optional = super.getExitPortal(worldserver, blockposition, flag, worldborder, searchRadius, canCreatePortal, createRadius); // CraftBukkit + +- if (optional.isPresent()) { ++ if (optional.isPresent() || !canCreatePortal) { // CraftBukkit + return optional; + } else { +- Direction.Axis direction_axis = (Direction.Axis) this.level().getBlockState(this.portalEntrancePos).getOptionalValue(NetherPortalBlock.AXIS).orElse(Direction.Axis.X); +- Optional optional1 = serverlevel.getPortalForcer().createPortal(blockpos, direction_axis); ++ Direction.Axis enumdirection_enumaxis = (Direction.Axis) this.level().getBlockState(this.portalEntrancePos).getOptionalValue(NetherPortalBlock.AXIS).orElse(Direction.Axis.X); ++ Optional optional1 = worldserver.getPortalForcer().createPortal(blockposition, enumdirection_enumaxis, this, createRadius); // CraftBukkit + + if (optional1.isEmpty()) { +- ServerPlayer.LOGGER.error("Unable to create a portal, likely target out of worldborder"); ++ // EntityPlayer.LOGGER.error("Unable to create a portal, likely target out of worldborder"); // CraftBukkit + } + + return optional1; +@@ -924,13 +1177,21 @@ + private void triggerDimensionChangeTriggers(ServerLevel serverlevel) { + ResourceKey resourcekey = serverlevel.dimension(); + ResourceKey resourcekey1 = this.level().dimension(); ++ // CraftBukkit start ++ ResourceKey maindimensionkey = CraftDimensionUtil.getMainDimensionKey(level); ++ ResourceKey maindimensionkey1 = CraftDimensionUtil.getMainDimensionKey(this.level()); + +- CriteriaTriggers.CHANGED_DIMENSION.trigger(this, resourcekey, resourcekey1); +- if (resourcekey == Level.NETHER && resourcekey1 == Level.OVERWORLD && this.enteredNetherPosition != null) { ++ CriteriaTriggers.CHANGED_DIMENSION.trigger(this, maindimensionkey, maindimensionkey1); ++ if (maindimensionkey != resourcekey || maindimensionkey1 != resourcekey1) { ++ CriteriaTriggers.CHANGED_DIMENSION.trigger(this, resourcekey, resourcekey1); ++ } ++ ++ if (maindimensionkey == Level.NETHER && maindimensionkey1 == Level.OVERWORLD && this.enteredNetherPosition != null) { ++ // CraftBukkit end + CriteriaTriggers.NETHER_TRAVEL.trigger(this, this.enteredNetherPosition); + } + +- if (resourcekey1 != Level.NETHER) { ++ if (maindimensionkey1 != Level.NETHER) { // CraftBukkit + this.enteredNetherPosition = null; + } + +@@ -949,11 +1208,8 @@ + this.containerMenu.broadcastChanges(); + } + +- @Override +- @Override +- public Either startSleepInBed(BlockPos blockpos) { +- Direction direction = (Direction) this.level().getBlockState(blockpos).getValue(HorizontalDirectionalBlock.FACING); +- ++ // CraftBukkit start - moved bed result checks from below into separate method ++ private Either getBedResult(BlockPos blockposition, Direction enumdirection) { + if (!this.isSleeping() && this.isAlive()) { + if (!this.level().dimensionType().natural()) { + return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_HERE); +@@ -962,7 +1218,7 @@ + } else if (this.bedBlocked(blockpos, direction)) { + return Either.left(Player.BedSleepingProblem.OBSTRUCTED); + } else { +- this.setRespawnPosition(this.level().dimension(), blockpos, this.getYRot(), false, true); ++ this.setRespawnPosition(this.level().dimension(), blockposition, this.getYRot(), false, true, PlayerSpawnChangeEvent.Cause.BED); // CraftBukkit + if (this.level().isDay()) { + return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_NOW); + } else { +@@ -995,6 +1278,7 @@ + } else { + return Either.left(Player.BedSleepingProblem.OTHER_PROBLEM); + } ++ // CraftBukkit end + } + + @Override +@@ -1021,15 +1304,32 @@ + } + + @Override +- @Override +- public void stopSleepInBed(boolean flag, boolean flag1) { ++ public void stopSleepInBed(boolean wakeImmediately, boolean updateLevelForSleepingPlayers) { ++ if (!this.isSleeping()) return; // CraftBukkit - Can't leave bed if not in one! ++ // CraftBukkit start - fire PlayerBedLeaveEvent ++ CraftPlayer player = this.getBukkitEntity(); ++ BlockPos bedPosition = this.getSleepingPos().orElse(null); ++ ++ org.bukkit.block.Block bed; ++ if (bedPosition != null) { ++ bed = this.level().getWorld().getBlockAt(bedPosition.getX(), bedPosition.getY(), bedPosition.getZ()); ++ } else { ++ bed = this.level().getWorld().getBlockAt(player.getLocation()); ++ } ++ ++ PlayerBedLeaveEvent event = new PlayerBedLeaveEvent(player, bed, true); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + if (this.isSleeping()) { + this.serverLevel().getChunkSource().broadcastAndSend(this, new ClientboundAnimatePacket(this, 2)); + } + + super.stopSleepInBed(flag, flag1); + if (this.connection != null) { +- this.connection.teleport(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); ++ this.connection.teleport(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot(), TeleportCause.EXIT_BED); // CraftBukkit + } + + } +@@ -1085,8 +1379,9 @@ + this.connection.send(new ClientboundOpenSignEditorPacket(signblockentity.getBlockPos(), flag)); + } + +- private void nextContainerCounter() { ++ public int nextContainerCounter() { // CraftBukkit - void -> int + this.containerCounter = this.containerCounter % 100 + 1; ++ return containerCounter; // CraftBukkit + } + + @Override +@@ -1095,23 +1389,47 @@ + if (menuprovider == null) { + return OptionalInt.empty(); + } else { ++ // CraftBukkit start - SPIGOT-6552: Handle inventory closing in CraftEventFactory#callInventoryOpenEvent(...) ++ /* + if (this.containerMenu != this.inventoryMenu) { + this.closeContainer(); + } ++ */ ++ // CraftBukkit end + + this.nextContainerCounter(); + AbstractContainerMenu abstractcontainermenu = menuprovider.createMenu(this.containerCounter, this.getInventory(), this); + +- if (abstractcontainermenu == null) { ++ // CraftBukkit start - Inventory open hook ++ if (container != null) { ++ container.setTitle(menu.getDisplayName()); ++ ++ boolean cancelled = false; ++ container = CraftEventFactory.callInventoryOpenEvent(this, container, cancelled); ++ if (container == null && !cancelled) { // Let pre-cancelled events fall through ++ // SPIGOT-5263 - close chest if cancelled ++ if (menu instanceof Container) { ++ ((Container) menu).stopOpen(this); ++ } else if (menu instanceof ChestBlock.DoubleInventory) { ++ // SPIGOT-5355 - double chests too :( ++ ((ChestBlock.DoubleInventory) menu).inventorylargechest.stopOpen(this); ++ } ++ return OptionalInt.empty(); ++ } ++ } ++ // CraftBukkit end ++ if (container == null) { + if (this.isSpectator()) { + this.displayClientMessage(Component.translatable("container.spectatorCantOpen").withStyle(ChatFormatting.RED), true); + } + + return OptionalInt.empty(); + } else { +- this.connection.send(new ClientboundOpenScreenPacket(abstractcontainermenu.containerId, abstractcontainermenu.getType(), menuprovider.getDisplayName())); +- this.initMenu(abstractcontainermenu); +- this.containerMenu = abstractcontainermenu; ++ // CraftBukkit start ++ this.containerMenu = container; ++ this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); ++ // CraftBukkit end ++ this.initMenu(container); + return OptionalInt.of(this.containerCounter); + } + } +@@ -1124,15 +1441,25 @@ + } + + @Override +- @Override +- public void openHorseInventory(AbstractHorse abstracthorse, Container container) { ++ public void openHorseInventory(AbstractHorse horse, Container inventory) { ++ // CraftBukkit start - Inventory open hook ++ this.nextContainerCounter(); ++ AbstractContainerMenu container = new HorseInventoryMenu(this.containerCounter, this.getInventory(), inventory, horse); ++ container.setTitle(horse.getDisplayName()); ++ container = CraftEventFactory.callInventoryOpenEvent(this, container); ++ ++ if (container == null) { ++ inventory.stopOpen(this); ++ return; ++ } ++ // CraftBukkit end + if (this.containerMenu != this.inventoryMenu) { + this.closeContainer(); + } + +- this.nextContainerCounter(); +- this.connection.send(new ClientboundHorseScreenOpenPacket(this.containerCounter, container.getContainerSize(), abstracthorse.getId())); +- this.containerMenu = new HorseInventoryMenu(this.containerCounter, this.getInventory(), container, abstracthorse); ++ // this.nextContainerCounter(); // CraftBukkit - moved up ++ this.connection.send(new ClientboundHorseScreenOpenPacket(this.containerCounter, inventory.getContainerSize(), horse.getId())); ++ this.containerMenu = container; // CraftBukkit + this.initMenu(this.containerMenu); + } + +@@ -1158,6 +1482,7 @@ + @Override + @Override + public void closeContainer() { ++ CraftEventFactory.handleInventoryCloseEvent(this); // CraftBukkit + this.connection.send(new ClientboundContainerClosePacket(this.containerMenu.containerId)); + this.doCloseContainer(); + } +@@ -1180,8 +1504,18 @@ + this.zza = f1; + } + +- this.jumping = flag; +- this.setShiftKeyDown(flag1); ++ this.jumping = jumping; ++ // CraftBukkit start ++ if (sneaking != this.isShiftKeyDown()) { ++ PlayerToggleSneakEvent event = new PlayerToggleSneakEvent(this.getBukkitEntity(), sneaking); ++ this.server.server.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ this.setShiftKeyDown(sneaking); + } + + } +@@ -1216,19 +1548,19 @@ + i = Math.round((float) Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2) * 100.0F); + if (i > 0) { + this.awardStat(Stats.SWIM_ONE_CM, i); +- this.causeFoodExhaustion(0.01F * (float) i * 0.01F); ++ this.causeFoodExhaustion(0.01F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.SWIM); // CraftBukkit - EntityExhaustionEvent + } + } else if (this.isEyeInFluid(FluidTags.WATER)) { + i = Math.round((float) Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2) * 100.0F); + if (i > 0) { + this.awardStat(Stats.WALK_UNDER_WATER_ONE_CM, i); +- this.causeFoodExhaustion(0.01F * (float) i * 0.01F); ++ this.causeFoodExhaustion(0.01F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.WALK_UNDERWATER); // CraftBukkit - EntityExhaustionEvent + } + } else if (this.isInWater()) { + i = Math.round((float) Math.sqrt(d0 * d0 + d2 * d2) * 100.0F); + if (i > 0) { + this.awardStat(Stats.WALK_ON_WATER_ONE_CM, i); +- this.causeFoodExhaustion(0.01F * (float) i * 0.01F); ++ this.causeFoodExhaustion(0.01F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.WALK_ON_WATER); // CraftBukkit - EntityExhaustionEvent + } + } else if (this.onClimbable()) { + if (d1 > 0.0D) { +@@ -1239,13 +1571,13 @@ + if (i > 0) { + if (this.isSprinting()) { + this.awardStat(Stats.SPRINT_ONE_CM, i); +- this.causeFoodExhaustion(0.1F * (float) i * 0.01F); ++ this.causeFoodExhaustion(0.1F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.SPRINT); // CraftBukkit - EntityExhaustionEvent + } else if (this.isCrouching()) { + this.awardStat(Stats.CROUCH_ONE_CM, i); +- this.causeFoodExhaustion(0.0F * (float) i * 0.01F); ++ this.causeFoodExhaustion(0.0F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.CROUCH); // CraftBukkit - EntityExhaustionEvent + } else { + this.awardStat(Stats.WALK_ONE_CM, i); +- this.causeFoodExhaustion(0.0F * (float) i * 0.01F); ++ this.causeFoodExhaustion(0.0F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.WALK); // CraftBukkit - EntityExhaustionEvent + } + } + } else if (this.isFallFlying()) { +@@ -1298,7 +1628,7 @@ + @Override + public void resetStat(Stat stat) { + this.stats.setValue(this, stat, 0); +- this.getScoreboard().forAllObjectives(stat, this, ScoreAccess::reset); ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(stat, this, ScoreAccess::reset); // CraftBukkit - Get our scores instead + } + + @Override +@@ -1351,6 +1676,7 @@ + + public void resetSentInfo() { + this.lastSentHealth = -1.0E8F; ++ this.lastSentExp = -1; // CraftBukkit - Added to reset + } + + @Override +@@ -1411,13 +1734,13 @@ + this.lastSentExp = -1; + this.lastSentHealth = -1.0F; + this.lastSentFood = -1; +- this.recipeBook.copyOverData(serverplayer.recipeBook); +- this.seenCredits = serverplayer.seenCredits; +- this.enteredNetherPosition = serverplayer.enteredNetherPosition; +- this.chunkTrackingView = serverplayer.chunkTrackingView; +- this.setShoulderEntityLeft(serverplayer.getShoulderEntityLeft()); +- this.setShoulderEntityRight(serverplayer.getShoulderEntityRight()); +- this.setLastDeathLocation(serverplayer.getLastDeathLocation()); ++ // this.recipeBook.copyOverData(entityplayer.recipeBook); // CraftBukkit ++ this.seenCredits = that.seenCredits; ++ this.enteredNetherPosition = that.enteredNetherPosition; ++ this.chunkTrackingView = that.chunkTrackingView; ++ this.setShoulderEntityLeft(that.getShoulderEntityLeft()); ++ this.setShoulderEntityRight(that.getShoulderEntityRight()); ++ this.setLastDeathLocation(that.getLastDeathLocation()); + } + + @Override +@@ -1466,20 +1784,25 @@ + } + + @Override +- @Override +- public boolean teleportTo(ServerLevel serverlevel, double d0, double d1, double d2, Set set, float f, float f1) { +- ChunkPos chunkpos = new ChunkPos(BlockPos.containing(d0, d1, d2)); ++ public boolean teleportTo(ServerLevel level, double x, double d1, double y, Set set, float z, float f1) { ++ // CraftBukkit start ++ return teleportTo(level, x, d1, y, set, z, f1, TeleportCause.UNKNOWN); ++ } + +- serverlevel.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, chunkpos, 1, this.getId()); ++ public boolean teleportTo(ServerLevel worldserver, double d0, double d1, double d2, Set set, float f, float f1, TeleportCause cause) { ++ // CraftBukkit end ++ ChunkPos chunkcoordintpair = new ChunkPos(BlockPos.containing(d0, d1, d2)); ++ ++ worldserver.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, chunkcoordintpair, 1, this.getId()); + this.stopRiding(); + if (this.isSleeping()) { + this.stopSleepInBed(true, true); + } + +- if (serverlevel == this.level()) { +- this.connection.teleport(d0, d1, d2, f, f1, set); ++ if (worldserver == this.level()) { ++ this.connection.teleport(d0, d1, d2, f, f1, set, cause); // CraftBukkit + } else { +- this.teleportTo(serverlevel, d0, d1, d2, f, f1); ++ this.teleportTo(worldserver, d0, d1, d2, f, f1, cause); // CraftBukkit + } + + this.setYHeadRot(f); +@@ -1590,6 +1906,16 @@ + } + + public void updateOptions(ClientInformation clientinformation) { ++ // CraftBukkit start ++ if (getMainArm() != clientinformation.mainHand()) { ++ PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(getBukkitEntity(), getMainArm() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT); ++ this.server.server.getPluginManager().callEvent(event); ++ } ++ if (!this.language.equals(clientinformation.language())) { ++ PlayerLocaleChangeEvent event = new PlayerLocaleChangeEvent(getBukkitEntity(), clientinformation.language()); ++ this.server.server.getPluginManager().callEvent(event); ++ } ++ // CraftBukkit end + this.language = clientinformation.language(); + this.requestedViewDistance = clientinformation.viewDistance(); + this.chatVisibility = clientinformation.chatVisibility(); +@@ -1675,7 +1999,7 @@ + if (level instanceof ServerLevel) { + ServerLevel serverlevel = (ServerLevel) level; + +- this.teleportTo(serverlevel, this.camera.getX(), this.camera.getY(), this.camera.getZ(), Set.of(), this.getYRot(), this.getXRot()); ++ this.teleportTo(worldserver, this.camera.getX(), this.camera.getY(), this.camera.getZ(), Set.of(), this.getYRot(), this.getXRot(), TeleportCause.SPECTATE); // CraftBukkit + } + + if (entity != null) { +@@ -1714,7 +2036,7 @@ + + @Nullable + public Component getTabListDisplayName() { +- return null; ++ return listName; // CraftBukkit + } + + @Override +@@ -1736,10 +2057,17 @@ + return this.advancements; + } + +- public void teleportTo(ServerLevel serverlevel, double d0, double d1, double d2, float f, float f1) { ++ // CraftBukkit start ++ public void teleportTo(ServerLevel newLevel, double x, double d1, double y, float f, float z) { ++ this.teleportTo(newLevel, x, d1, y, f, z, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.UNKNOWN); ++ } ++ ++ public void teleportTo(ServerLevel worldserver, double d0, double d1, double d2, float f, float f1, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { ++ // CraftBukkit end + this.setCamera(this); + this.stopRiding(); +- if (serverlevel == this.level()) { ++ /* CraftBukkit start - replace with bukkit handling for multi-world ++ if (worldserver == this.level()) { + this.connection.teleport(d0, d1, d2, f, f1); + } else { + ServerLevel serverlevel1 = this.serverLevel(); +@@ -1758,6 +2086,9 @@ + this.server.getPlayerList().sendLevelInfo(this, serverlevel); + this.server.getPlayerList().sendAllPlayerInfo(this); + } ++ */ ++ this.getBukkitEntity().teleport(new Location(worldserver.getWorld(), d0, d1, d2, f, f1), cause); ++ // CraftBukkit end + + } + +@@ -1778,10 +2109,36 @@ + return this.respawnForced; + } + +- public void setRespawnPosition(ResourceKey resourcekey, @Nullable BlockPos blockpos, float f, boolean flag, boolean flag1) { +- if (blockpos != null) { +- boolean flag2 = blockpos.equals(this.respawnPosition) && resourcekey.equals(this.respawnDimension); ++ public void setRespawnPosition(ResourceKey dimension, @Nullable BlockPos position, float angle, boolean forced, boolean sendMessage) { ++ // CraftBukkit start ++ this.setRespawnPosition(dimension, position, angle, forced, sendMessage, PlayerSpawnChangeEvent.Cause.UNKNOWN); ++ } + ++ public void setRespawnPosition(ResourceKey resourcekey, @Nullable BlockPos blockposition, float f, boolean flag, boolean flag1, PlayerSpawnChangeEvent.Cause cause) { ++ ServerLevel newWorld = this.server.getLevel(resourcekey); ++ Location newSpawn = (blockposition != null) ? CraftLocation.toBukkit(blockposition, newWorld.getWorld(), f, 0) : null; ++ ++ PlayerSpawnChangeEvent event = new PlayerSpawnChangeEvent(this.getBukkitEntity(), newSpawn, flag, cause); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ newSpawn = event.getNewSpawn(); ++ flag = event.isForced(); ++ ++ if (newSpawn != null) { ++ resourcekey = ((CraftWorld) newSpawn.getWorld()).getHandle().dimension(); ++ blockposition = BlockPos.containing(newSpawn.getX(), newSpawn.getY(), newSpawn.getZ()); ++ f = newSpawn.getYaw(); ++ } else { ++ resourcekey = Level.OVERWORLD; ++ blockposition = null; ++ f = 0.0F; ++ } ++ // CraftBukkit end ++ if (blockposition != null) { ++ boolean flag2 = blockposition.equals(this.respawnPosition) && resourcekey.equals(this.respawnDimension); ++ + if (flag1 && !flag2) { + this.sendSystemMessage(Component.translatable("block.minecraft.set_spawn")); + } +@@ -1994,4 +2341,146 @@ + public CommonPlayerSpawnInfo createCommonSpawnInfo(ServerLevel serverlevel) { + return new CommonPlayerSpawnInfo(serverlevel.dimensionTypeId(), serverlevel.dimension(), BiomeManager.obfuscateSeed(serverlevel.getSeed()), this.gameMode.getGameModeForPlayer(), this.gameMode.getPreviousGameModeForPlayer(), serverlevel.isDebug(), serverlevel.isFlat(), this.getLastDeathLocation(), this.getPortalCooldown()); + } ++ ++ // CraftBukkit start - Add per-player time and weather. ++ public long timeOffset = 0; ++ public boolean relativeTime = true; ++ ++ public long getPlayerTime() { ++ if (this.relativeTime) { ++ // Adds timeOffset to the current server time. ++ return this.level().getDayTime() + this.timeOffset; ++ } else { ++ // Adds timeOffset to the beginning of this day. ++ return this.level().getDayTime() - (this.level().getDayTime() % 24000) + this.timeOffset; ++ } ++ } ++ ++ public WeatherType weather = null; ++ ++ public WeatherType getPlayerWeather() { ++ return this.weather; ++ } ++ ++ public void setPlayerWeather(WeatherType type, boolean plugin) { ++ if (!plugin && this.weather != null) { ++ return; ++ } ++ ++ if (plugin) { ++ this.weather = type; ++ } ++ ++ if (type == WeatherType.DOWNFALL) { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.STOP_RAINING, 0)); ++ } else { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.START_RAINING, 0)); ++ } ++ } ++ ++ private float pluginRainPosition; ++ private float pluginRainPositionPrevious; ++ ++ public void updateWeather(float oldRain, float newRain, float oldThunder, float newThunder) { ++ if (this.weather == null) { ++ // Vanilla ++ if (oldRain != newRain) { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, newRain)); ++ } ++ } else { ++ // Plugin ++ if (pluginRainPositionPrevious != pluginRainPosition) { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, pluginRainPosition)); ++ } ++ } ++ ++ if (oldThunder != newThunder) { ++ if (weather == WeatherType.DOWNFALL || weather == null) { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, newThunder)); ++ } else { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, 0)); ++ } ++ } ++ } ++ ++ public void tickWeather() { ++ if (this.weather == null) return; ++ ++ pluginRainPositionPrevious = pluginRainPosition; ++ if (weather == WeatherType.DOWNFALL) { ++ pluginRainPosition += 0.01; ++ } else { ++ pluginRainPosition -= 0.01; ++ } ++ ++ pluginRainPosition = Mth.clamp(pluginRainPosition, 0.0F, 1.0F); ++ } ++ ++ public void resetPlayerWeather() { ++ this.weather = null; ++ this.setPlayerWeather(this.level().getLevelData().isRaining() ? WeatherType.DOWNFALL : WeatherType.CLEAR, false); ++ } ++ ++ @Override ++ public String toString() { ++ return super.toString() + "(" + this.getScoreboardName() + " at " + this.getX() + "," + this.getY() + "," + this.getZ() + ")"; ++ } ++ ++ // SPIGOT-1903, MC-98153 ++ public void forceSetPositionRotation(double x, double y, double z, float yaw, float pitch) { ++ this.moveTo(x, y, z, yaw, pitch); ++ this.connection.resetPosition(); ++ } ++ ++ @Override ++ public boolean isImmobile() { ++ return super.isImmobile() || !getBukkitEntity().isOnline(); ++ } ++ ++ @Override ++ public Scoreboard getScoreboard() { ++ return getBukkitEntity().getScoreboard().getHandle(); ++ } ++ ++ public void reset() { ++ float exp = 0; ++ boolean keepInventory = this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY); ++ ++ if (this.keepLevel) { // CraftBukkit - SPIGOT-6687: Only use keepLevel (was pre-set with RULE_KEEPINVENTORY value in PlayerDeathEvent) ++ exp = this.experienceProgress; ++ this.newTotalExp = this.totalExperience; ++ this.newLevel = this.experienceLevel; ++ } ++ ++ this.setHealth(this.getMaxHealth()); ++ this.stopUsingItem(); // CraftBukkit - SPIGOT-6682: Clear active item on reset ++ this.setRemainingFireTicks(0); ++ this.fallDistance = 0; ++ this.foodData = new FoodData(this); ++ this.experienceLevel = this.newLevel; ++ this.totalExperience = this.newTotalExp; ++ this.experienceProgress = 0; ++ this.deathTime = 0; ++ this.setArrowCount(0, true); // CraftBukkit - ArrowBodyCountChangeEvent ++ this.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.DEATH); ++ this.effectsDirty = true; ++ this.containerMenu = this.inventoryMenu; ++ this.lastHurtByPlayer = null; ++ this.lastHurtByMob = null; ++ this.combatTracker = new CombatTracker(this); ++ this.lastSentExp = -1; ++ if (this.keepLevel) { // CraftBukkit - SPIGOT-6687: Only use keepLevel (was pre-set with RULE_KEEPINVENTORY value in PlayerDeathEvent) ++ this.experienceProgress = exp; ++ } else { ++ this.giveExperiencePoints(this.newExp); ++ } ++ this.keepLevel = false; ++ this.setDeltaMovement(0, 0, 0); // CraftBukkit - SPIGOT-6948: Reset velocity on death ++ } ++ ++ @Override ++ public CraftPlayer getBukkitEntity() { ++ return (CraftPlayer) super.getBukkitEntity(); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ServerPlayerGameMode.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ServerPlayerGameMode.java.patch new file mode 100644 index 0000000000..bf951d1eea --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/ServerPlayerGameMode.java.patch @@ -0,0 +1,334 @@ +--- a/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -21,10 +23,28 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.GameMasterBlock; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; ++import org.slf4j.Logger; ++ ++// CraftBukkit start ++import java.util.ArrayList; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.network.ServerGamePacketListenerImpl; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.CakeBlock; ++import net.minecraft.world.level.block.DoorBlock; ++import net.minecraft.world.level.block.state.properties.BlockPropertyDoubleBlockHalf; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; +-import org.slf4j.Logger; ++import org.bukkit.GameMode; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockBreakEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.Event; ++import org.bukkit.event.block.Action; ++import org.bukkit.event.player.PlayerGameModeChangeEvent; ++import org.bukkit.event.player.PlayerInteractEvent; ++// CraftBukkit end + + public class ServerPlayerGameMode { + +@@ -56,9 +76,16 @@ + if (gametype == this.gameModeForPlayer) { + return false; + } else { +- this.setGameModeForPlayer(gametype, this.previousGameModeForPlayer); ++ // CraftBukkit start ++ PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(player.getBukkitEntity(), GameMode.getByValue(gameModeForPlayer.getId())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ this.setGameModeForPlayer(gameModeForPlayer, this.previousGameModeForPlayer); + this.player.onUpdateAbilities(); +- this.player.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player)); ++ this.player.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player), this.player); // CraftBukkit + this.level.updateSleepingPlayerList(); + return true; + } +@@ -88,8 +115,8 @@ + } + + public void tick() { +- ++this.gameTicks; +- BlockState blockstate; ++ this.gameTicks = MinecraftServer.currentTick; // CraftBukkit; ++ IBlockData iblockdata; + + if (this.hasDelayedDestroy) { + blockstate = this.level.getBlockState(this.delayedDestroyPos); +@@ -140,13 +167,35 @@ + } else { + BlockState blockstate; + +- if (serverboundplayeractionpacket_action == ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK) { +- if (!this.level.mayInteract(this.player, blockpos)) { +- this.player.connection.send(new ClientboundBlockUpdatePacket(blockpos, this.level.getBlockState(blockpos))); +- this.debugLogging(blockpos, false, j, "may not interact"); ++ if (action == ServerboundPlayerActionPacket.EnumPlayerDigType.START_DESTROY_BLOCK) { ++ if (!this.level.mayInteract(this.player, pos)) { ++ // CraftBukkit start - fire PlayerInteractEvent ++ CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, pos, face, this.player.getInventory().getSelected(), EnumHand.MAIN_HAND); ++ this.player.connection.send(new ClientboundBlockUpdatePacket(pos, this.level.getBlockState(pos))); ++ this.debugLogging(pos, false, sequence, "may not interact"); ++ // Update any tile entity data for this block ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ if (tileentity != null) { ++ this.player.connection.send(tileentity.getUpdatePacket()); ++ } ++ // CraftBukkit end + return; + } + ++ // CraftBukkit start ++ PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, pos, face, this.player.getInventory().getSelected(), EnumHand.MAIN_HAND); ++ if (event.isCancelled()) { ++ // Let the client know the block still exists ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ // Update any tile entity data for this block ++ BlockEntity tileentity = this.level.getBlockEntity(pos); ++ if (tileentity != null) { ++ this.player.connection.send(tileentity.getUpdatePacket()); ++ } ++ return; ++ } ++ // CraftBukkit end ++ + if (this.isCreative()) { + this.destroyAndAck(blockpos, j, "creative destroy"); + return; +@@ -161,14 +210,46 @@ + this.destroyProgressStart = this.gameTicks; + float f = 1.0F; + +- blockstate = this.level.getBlockState(blockpos); +- if (!blockstate.isAir()) { +- blockstate.attack(this.level, blockpos, this.player); +- f = blockstate.getDestroyProgress(this.player, this.player.level(), blockpos); ++ iblockdata = this.level.getBlockState(pos); ++ // CraftBukkit start - Swings at air do *NOT* exist. ++ if (event.useInteractedBlock() == Event.Result.DENY) { ++ // If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door. ++ IBlockData data = this.level.getBlockState(pos); ++ if (data.getBlock() instanceof DoorBlock) { ++ // For some reason *BOTH* the bottom/top part have to be marked updated. ++ boolean bottom = data.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER; ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, bottom ? pos.above() : pos.below())); ++ } else if (data.getBlock() instanceof TrapDoorBlock) { ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ } ++ } else if (!iblockdata.isAir()) { ++ iblockdata.attack(this.level, pos, this.player); ++ f = iblockdata.getDestroyProgress(this.player, this.player.level(), pos); + } + +- if (!blockstate.isAir() && f >= 1.0F) { +- this.destroyAndAck(blockpos, j, "insta mine"); ++ if (event.useItemInHand() == Event.Result.DENY) { ++ // If we 'insta destroyed' then the client needs to be informed. ++ if (f > 1.0f) { ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ } ++ return; ++ } ++ org.bukkit.event.block.BlockDamageEvent blockEvent = CraftEventFactory.callBlockDamageEvent(this.player, pos, this.player.getInventory().getSelected(), f >= 1.0f); ++ ++ if (blockEvent.isCancelled()) { ++ // Let the client know the block still exists ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ return; ++ } ++ ++ if (blockEvent.getInstaBreak()) { ++ f = 2.0f; ++ } ++ // CraftBukkit end ++ ++ if (!iblockdata.isAir() && f >= 1.0F) { ++ this.destroyAndAck(pos, sequence, "insta mine"); + } else { + if (this.isDestroyingBlock) { + this.player.connection.send(new ClientboundBlockUpdatePacket(this.destroyPos, this.level.getBlockState(this.destroyPos))); +@@ -210,14 +291,16 @@ + this.debugLogging(blockpos, true, j, "stopped destroying"); + } else if (serverboundplayeractionpacket_action == ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK) { + this.isDestroyingBlock = false; +- if (!Objects.equals(this.destroyPos, blockpos)) { +- ServerPlayerGameMode.LOGGER.warn("Mismatch in destroy block pos: {} {}", this.destroyPos, blockpos); ++ if (!Objects.equals(this.destroyPos, pos)) { ++ ServerPlayerGameMode.LOGGER.debug("Mismatch in destroy block pos: {} {}", this.destroyPos, pos); // CraftBukkit - SPIGOT-5457 sent by client when interact event cancelled + this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); + this.debugLogging(blockpos, true, j, "aborted mismatched destroying"); + } + +- this.level.destroyBlockProgress(this.player.getId(), blockpos, -1); +- this.debugLogging(blockpos, true, j, "aborted destroying"); ++ this.level.destroyBlockProgress(this.player.getId(), pos, -1); ++ this.debugLogging(pos, true, sequence, "aborted destroying"); ++ ++ CraftEventFactory.callBlockDamageAbortEvent(this.player, pos, this.player.getInventory().getSelected()); // CraftBukkit + } + + } +@@ -233,14 +316,69 @@ + + } + +- public boolean destroyBlock(BlockPos blockpos) { +- BlockState blockstate = this.level.getBlockState(blockpos); ++ public boolean destroyBlock(BlockPos pos) { ++ IBlockData iblockdata = this.level.getBlockState(pos); ++ // CraftBukkit start - fire BlockBreakEvent ++ org.bukkit.block.Block bblock = CraftBlock.at(level, pos); ++ BlockBreakEvent event = null; + +- if (!this.player.getMainHandItem().getItem().canAttackBlock(blockstate, this.level, blockpos, this.player)) { ++ if (this.player instanceof ServerPlayer) { ++ // Sword + Creative mode pre-cancel ++ boolean isSwordNoBreak = !this.player.getMainHandItem().getItem().canAttackBlock(iblockdata, this.level, pos, this.player); ++ ++ // Tell client the block is gone immediately then process events ++ // Don't tell the client if its a creative sword break because its not broken! ++ if (level.getBlockEntity(pos) == null && !isSwordNoBreak) { ++ ClientboundBlockUpdatePacket packet = new ClientboundBlockUpdatePacket(pos, Blocks.AIR.defaultBlockState()); ++ this.player.connection.send(packet); ++ } ++ ++ event = new BlockBreakEvent(bblock, this.player.getBukkitEntity()); ++ ++ // Sword + Creative mode pre-cancel ++ event.setCancelled(isSwordNoBreak); ++ ++ // Calculate default block experience ++ IBlockData nmsData = this.level.getBlockState(pos); ++ Block nmsBlock = nmsData.getBlock(); ++ ++ ItemStack itemstack = this.player.getItemBySlot(EquipmentSlot.MAINHAND); ++ ++ if (nmsBlock != null && !event.isCancelled() && !this.isCreative() && this.player.hasCorrectToolForDrops(nmsBlock.defaultBlockState())) { ++ event.setExpToDrop(nmsBlock.getExpDrop(nmsData, this.level, pos, itemstack, true)); ++ } ++ ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ if (isSwordNoBreak) { ++ return false; ++ } ++ // Let the client know the block still exists ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ ++ // Brute force all possible updates ++ for (Direction dir : Direction.values()) { ++ this.player.connection.send(new ClientboundBlockUpdatePacket(level, pos.relative(dir))); ++ } ++ ++ // Update any tile entity data for this block ++ BlockEntity tileentity = this.level.getBlockEntity(pos); ++ if (tileentity != null) { ++ this.player.connection.send(tileentity.getUpdatePacket()); ++ } ++ return false; ++ } ++ } ++ // CraftBukkit end ++ ++ if (false && !this.player.getMainHandItem().getItem().canAttackBlock(iblockdata, this.level, pos, this.player)) { // CraftBukkit - false + return false; + } else { +- BlockEntity blockentity = this.level.getBlockEntity(blockpos); +- Block block = blockstate.getBlock(); ++ iblockdata = this.level.getBlockState(pos); // CraftBukkit - update state from plugins ++ if (iblockdata.isAir()) return false; // CraftBukkit - A plugin set block to air without cancelling ++ BlockEntity tileentity = this.level.getBlockEntity(pos); ++ Block block = iblockdata.getBlock(); + + if (block instanceof GameMasterBlock && !this.player.canUseGameMasterBlocks()) { + this.level.sendBlockUpdated(blockpos, blockstate, blockstate, 3); +@@ -248,27 +386,44 @@ + } else if (this.player.blockActionRestricted(this.level, blockpos, this.gameModeForPlayer)) { + return false; + } else { +- BlockState blockstate1 = block.playerWillDestroy(this.level, blockpos, blockstate, this.player); +- boolean flag = this.level.removeBlock(blockpos, false); ++ // CraftBukkit start ++ org.bukkit.block.BlockState state = bblock.getState(); ++ level.captureDrops = new ArrayList<>(); ++ // CraftBukkit end ++ IBlockData iblockdata1 = block.playerWillDestroy(this.level, pos, iblockdata, this.player); ++ boolean flag = this.level.removeBlock(pos, false); + + if (flag) { + block.destroy(this.level, blockpos, blockstate1); + } + + if (this.isCreative()) { +- return true; ++ // return true; // CraftBukkit + } else { + ItemStack itemstack = this.player.getMainHandItem(); + ItemStack itemstack1 = itemstack.copy(); + boolean flag1 = this.player.hasCorrectToolForDrops(blockstate1); + +- itemstack.mineBlock(this.level, blockstate1, blockpos, this.player); +- if (flag && flag1) { +- block.playerDestroy(this.level, this.player, blockpos, blockstate1, blockentity, itemstack1); ++ itemstack.mineBlock(this.level, iblockdata1, pos, this.player); ++ if (flag && flag1 && event.isDropItems()) { // CraftBukkit - Check if block should drop items ++ block.playerDestroy(this.level, this.player, pos, iblockdata1, tileentity, itemstack1); + } + +- return true; ++ // return true; // CraftBukkit + } ++ // CraftBukkit start ++ if (event.isDropItems()) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, level.captureDrops); ++ } ++ level.captureDrops = null; ++ ++ // Drop event experience ++ if (flag && event != null) { ++ iblockdata.getBlock().popExperience(this.level, pos, event.getExpToDrop()); ++ } ++ ++ return true; ++ // CraftBukkit end + } + } + } +@@ -313,9 +468,17 @@ + } + } + +- public InteractionResult useItemOn(ServerPlayer serverplayer, Level level, ItemStack itemstack, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- BlockPos blockpos = blockhitresult.getBlockPos(); +- BlockState blockstate = level.getBlockState(blockpos); ++ // CraftBukkit start - whole method ++ public boolean interactResult = false; ++ public boolean firedInteract = false; ++ public BlockPos interactPosition; ++ public EnumHand interactHand; ++ public ItemStack interactItemStack; ++ public InteractionResult useItemOn(ServerPlayer player, Level level, ItemStack stack, EnumHand hand, BlockHitResult hitResult) { ++ BlockPos blockposition = hitResult.getBlockPos(); ++ IBlockData iblockdata = level.getBlockState(blockposition); ++ InteractionResult enuminteractionresult = InteractionResult.PASS; ++ boolean cancelledBlock = false; + + if (!blockstate.getBlock().isEnabled(level.enabledFeatures())) { + return InteractionResult.FAIL; +@@ -364,6 +557,8 @@ + return InteractionResult.PASS; + } + } ++ return enuminteractionresult; ++ // CraftBukkit end + } + + public void setLevel(ServerLevel serverlevel) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/TicketType.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/TicketType.java.patch new file mode 100644 index 0000000000..cd45c85c43 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/TicketType.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/server/level/TicketType.java ++++ b/net/minecraft/server/level/TicketType.java +@@ -23,6 +23,8 @@ + public static final TicketType PORTAL = create("portal", Vec3i::compareTo, 300); + public static final TicketType POST_TELEPORT = create("post_teleport", Integer::compareTo, 5); + public static final TicketType UNKNOWN = create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1); ++ public static final TicketType PLUGIN = create("plugin", (a, b) -> 0); // CraftBukkit ++ public static final TicketType PLUGIN_TICKET = create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit + + public static TicketType create(String s, Comparator comparator) { + return new TicketType<>(s, comparator, 0L); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/WorldGenRegion.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/WorldGenRegion.java.patch new file mode 100644 index 0000000000..e5539e27fd --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/level/WorldGenRegion.java.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/server/level/WorldGenRegion.java ++++ b/net/minecraft/server/level/WorldGenRegion.java +@@ -221,8 +208,8 @@ + if (blockstate.isAir()) { + return false; + } else { +- if (flag) { +- BlockEntity blockentity = blockstate.hasBlockEntity() ? this.getBlockEntity(blockpos) : null; ++ if (false) { // CraftBukkit - SPIGOT-6833: Do not drop during world generation ++ BlockEntity tileentity = iblockdata.hasBlockEntity() ? this.getBlockEntity(pos) : null; + + Block.dropResources(blockstate, this.level, blockpos, blockentity, entity, ItemStack.EMPTY); + } +@@ -344,6 +327,13 @@ + @Override + @Override + public boolean addFreshEntity(Entity entity) { ++ // CraftBukkit start ++ return addFreshEntity(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ @Override ++ public boolean addFreshEntity(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ // CraftBukkit end + int i = SectionPos.blockToSectionCoord(entity.getBlockX()); + int j = SectionPos.blockToSectionCoord(entity.getBlockZ()); + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/LegacyQueryHandler.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/LegacyQueryHandler.java.patch new file mode 100644 index 0000000000..da24fc74b6 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/LegacyQueryHandler.java.patch @@ -0,0 +1,45 @@ +--- a/net/minecraft/server/network/LegacyQueryHandler.java ++++ b/net/minecraft/server/network/LegacyQueryHandler.java +@@ -36,10 +35,11 @@ + SocketAddress socketaddress = channelhandlercontext.channel().remoteAddress(); + int i = bytebuf.readableBytes(); + String s; ++ org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(socketaddress, server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); // CraftBukkit + + if (i == 0) { + LegacyQueryHandler.LOGGER.debug("Ping: (<1.3.x) from {}", socketaddress); +- s = createVersion0Response(this.server); ++ s = createVersion0Response(this.server, event); // CraftBukkit + sendFlushAndClose(channelhandlercontext, createLegacyDisconnectPacket(channelhandlercontext.alloc(), s)); + } else { + if (bytebuf.readUnsignedByte() != 1) { +@@ -56,7 +56,7 @@ + LegacyQueryHandler.LOGGER.debug("Ping: (1.4-1.5.x) from {}", socketaddress); + } + +- s = createVersion1Response(this.server); ++ s = createVersion1Response(this.server, event); // CraftBukkit + sendFlushAndClose(channelhandlercontext, createLegacyDisconnectPacket(channelhandlercontext.alloc(), s)); + } + +@@ -107,12 +107,16 @@ + } + } + +- private static String createVersion0Response(ServerInfo serverinfo) { +- return String.format(Locale.ROOT, "%s\u00a7%d\u00a7%d", serverinfo.getMotd(), serverinfo.getPlayerCount(), serverinfo.getMaxPlayers()); ++ // CraftBukkit start ++ private static String createVersion0Response(ServerInfo serverinfo, org.bukkit.event.server.ServerListPingEvent event) { ++ return String.format(Locale.ROOT, "%s\u00a7%d\u00a7%d", event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); ++ // CraftBukkit end + } + +- private static String createVersion1Response(ServerInfo serverinfo) { +- return String.format(Locale.ROOT, "\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, serverinfo.getServerVersion(), serverinfo.getMotd(), serverinfo.getPlayerCount(), serverinfo.getMaxPlayers()); ++ // CraftBukkit start ++ private static String createVersion1Response(ServerInfo serverinfo, org.bukkit.event.server.ServerListPingEvent event) { ++ return String.format(Locale.ROOT, "\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, serverinfo.getServerVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); ++ // CraftBukkit end + } + + private static void sendFlushAndClose(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerCommonPacketListenerImpl.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerCommonPacketListenerImpl.java.patch new file mode 100644 index 0000000000..3db848b5ec --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerCommonPacketListenerImpl.java.patch @@ -0,0 +1,208 @@ +--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java +@@ -26,6 +30,17 @@ + import net.minecraft.util.thread.BlockableEventLoop; + import org.slf4j.Logger; + ++// CraftBukkit start ++import io.netty.buffer.ByteBuf; ++import java.util.concurrent.ExecutionException; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.bukkit.event.player.PlayerKickEvent; ++import org.bukkit.event.player.PlayerResourcePackStatusEvent; ++// CraftBukkit end ++ + public abstract class ServerCommonPacketListenerImpl implements ServerCommonPacketListener { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -39,13 +54,21 @@ + private int latency; + private volatile boolean suspendFlushingOnServerThread = false; + +- public ServerCommonPacketListenerImpl(MinecraftServer minecraftserver, Connection connection, CommonListenerCookie commonlistenercookie) { ++ public ServerCommonPacketListenerImpl(MinecraftServer minecraftserver, Connection networkmanager, CommonListenerCookie commonlistenercookie, ServerPlayer player) { // CraftBukkit + this.server = minecraftserver; + this.connection = connection; + this.keepAliveTime = Util.getMillis(); + this.latency = commonlistenercookie.latency(); ++ // CraftBukkit start - add fields and methods ++ this.player = player; ++ this.cserver = minecraftserver.server; + } + ++ public CraftPlayer getCraftPlayer() { ++ return (this.player == null) ? null : (CraftPlayer) this.player.getBukkitEntity(); ++ // CraftBukkit end ++ } ++ + @Override + @Override + public void onDisconnect(Component component) { +@@ -59,6 +83,7 @@ + @Override + @Override + public void handleKeepAlive(ServerboundKeepAlivePacket serverboundkeepalivepacket) { ++ PacketUtils.ensureRunningOnSameThread(serverboundkeepalivepacket, this, this.player.serverLevel()); // CraftBukkit + if (this.keepAlivePending && serverboundkeepalivepacket.getId() == this.keepAliveChallenge) { + int i = (int) (Util.getMillis() - this.keepAliveTime); + +@@ -74,10 +98,52 @@ + @Override + public void handlePong(ServerboundPongPacket serverboundpongpacket) {} + ++ // CraftBukkit start ++ private static final ResourceLocation CUSTOM_REGISTER = new ResourceLocation("register"); ++ private static final ResourceLocation CUSTOM_UNREGISTER = new ResourceLocation("unregister"); ++ + @Override + @Override + public void handleCustomPayload(ServerboundCustomPayloadPacket serverboundcustompayloadpacket) {} + ++ if (identifier.equals(CUSTOM_REGISTER)) { ++ try { ++ String channels = payload.toString(com.google.common.base.Charsets.UTF_8); ++ for (String channel : channels.split("\0")) { ++ getCraftPlayer().addChannel(channel); ++ } ++ } catch (Exception ex) { ++ ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t register custom payload", ex); ++ this.disconnect("Invalid payload REGISTER!"); ++ } ++ } else if (identifier.equals(CUSTOM_UNREGISTER)) { ++ try { ++ String channels = payload.toString(com.google.common.base.Charsets.UTF_8); ++ for (String channel : channels.split("\0")) { ++ getCraftPlayer().removeChannel(channel); ++ } ++ } catch (Exception ex) { ++ ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t unregister custom payload", ex); ++ this.disconnect("Invalid payload UNREGISTER!"); ++ } ++ } else { ++ try { ++ byte[] data = new byte[payload.readableBytes()]; ++ payload.readBytes(data); ++ cserver.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), identifier.toString(), data); ++ } catch (Exception ex) { ++ ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t dispatch custom payload", ex); ++ this.disconnect("Invalid custom payload!"); ++ } ++ } ++ ++ } ++ ++ public final boolean isDisconnected() { ++ return !this.player.joining && !this.connection.isConnected(); ++ } ++ // CraftBukkit end ++ + @Override + @Override + public void handleResourcePackResponse(ServerboundResourcePackPacket serverboundresourcepackpacket) { +@@ -86,6 +156,7 @@ + ServerCommonPacketListenerImpl.LOGGER.info("Disconnecting {} due to resource pack {} rejection", this.playerProfile().getName(), serverboundresourcepackpacket.id()); + this.disconnect(Component.translatable("multiplayer.requiredTexturePrompt.disconnect")); + } ++ this.cserver.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getCraftPlayer(), serverboundresourcepackpacket.id(), PlayerResourcePackStatusEvent.Status.values()[serverboundresourcepackpacket.action().ordinal()])); // CraftBukkit + + } + +@@ -93,7 +164,7 @@ + this.server.getProfiler().push("keepAlive"); + long i = Util.getMillis(); + +- if (i - this.keepAliveTime >= 15000L) { ++ if (i - this.keepAliveTime >= 25000L) { // CraftBukkit + if (this.keepAlivePending) { + this.disconnect(ServerCommonPacketListenerImpl.TIMEOUT_DISCONNECTION_MESSAGE); + } else { +@@ -121,6 +192,14 @@ + } + + public void send(Packet packet, @Nullable PacketSendListener packetsendlistener) { ++ // CraftBukkit start ++ if (packet == null) { ++ return; ++ } else if (packet instanceof ClientboundSetDefaultSpawnPositionPacket) { ++ ClientboundSetDefaultSpawnPositionPacket packet6 = (ClientboundSetDefaultSpawnPositionPacket) packet; ++ this.player.compassTarget = CraftLocation.toBukkit(packet6.pos, this.getCraftPlayer().getWorld()); ++ } ++ // CraftBukkit end + boolean flag = !this.suspendFlushingOnServerThread || !this.server.isSameThread(); + + try { +@@ -136,16 +215,67 @@ + } + } + +- public void disconnect(Component component) { +- this.connection.send(new ClientboundDisconnectPacket(component), PacketSendListener.thenRun(() -> { +- this.connection.disconnect(component); ++ // CraftBukkit start ++ @Deprecated ++ public void disconnect(Component ichatbasecomponent) { ++ disconnect(CraftChatMessage.fromComponent(ichatbasecomponent)); ++ } ++ // CraftBukkit end ++ ++ public void disconnect(String s) { ++ // CraftBukkit start - fire PlayerKickEvent ++ if (this.processedDisconnect) { ++ return; ++ } ++ if (!this.cserver.isPrimaryThread()) { ++ Waitable waitable = new Waitable() { ++ @Override ++ protected Object evaluate() { ++ ServerCommonPacketListenerImpl.this.disconnect(s); ++ return null; ++ } ++ }; ++ ++ this.server.processQueue.add(waitable); ++ ++ try { ++ waitable.get(); ++ } catch (InterruptedException e) { ++ Thread.currentThread().interrupt(); ++ } catch (ExecutionException e) { ++ throw new RuntimeException(e); ++ } ++ return; ++ } ++ ++ String leaveMessage = ChatFormatting.YELLOW + this.player.getScoreboardName() + " left the game."; ++ ++ PlayerKickEvent event = new PlayerKickEvent(this.player.getBukkitEntity(), s, leaveMessage); ++ ++ if (this.cserver.getServer().isRunning()) { ++ this.cserver.getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ // Do not kick the player ++ return; ++ } ++ this.player.kickLeaveMessage = event.getLeaveMessage(); // CraftBukkit - SPIGOT-3034: Forward leave message to PlayerQuitEvent ++ // Send the possibly modified leave message ++ final Component ichatbasecomponent = CraftChatMessage.fromString(event.getReason(), true)[0]; ++ // CraftBukkit end ++ ++ this.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), PacketSendListener.thenRun(() -> { ++ this.connection.disconnect(ichatbasecomponent); + })); ++ this.onDisconnect(ichatbasecomponent); // CraftBukkit - fire quit instantly + this.connection.setReadOnly(); + MinecraftServer minecraftserver = this.server; + Connection connection = this.connection; + + Objects.requireNonNull(this.connection); +- minecraftserver.executeBlocking(connection::handleDisconnection); ++ // CraftBukkit - Don't wait ++ minecraftserver.wrapRunnable(networkmanager::handleDisconnection); + } + + protected boolean isSingleplayerOwner() { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java.patch new file mode 100644 index 0000000000..fa1a085dbb --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java +@@ -44,8 +44,8 @@ + private ConfigurationTask currentTask; + private ClientInformation clientInformation; + +- public ServerConfigurationPacketListenerImpl(MinecraftServer minecraftserver, Connection connection, CommonListenerCookie commonlistenercookie) { +- super(minecraftserver, connection, commonlistenercookie); ++ public ServerConfigurationPacketListenerImpl(MinecraftServer minecraftserver, Connection networkmanager, CommonListenerCookie commonlistenercookie, ServerPlayer player) { // CraftBukkit ++ super(minecraftserver, networkmanager, commonlistenercookie, player); // CraftBukkit + this.gameProfile = commonlistenercookie.gameProfile(); + this.clientInformation = commonlistenercookie.clientInformation(); + } +@@ -123,14 +117,14 @@ + return; + } + +- Component component = playerlist.canPlayerLogin(this.connection.getRemoteAddress(), this.gameProfile); ++ Component ichatbasecomponent = null; // CraftBukkit - login checks already completed + + if (component != null) { + this.disconnect(component); + return; + } + +- ServerPlayer serverplayer = playerlist.getPlayerForLogin(this.gameProfile, this.clientInformation); ++ ServerPlayer entityplayer = playerlist.getPlayerForLogin(this.gameProfile, this.clientInformation, this.player); // CraftBukkit + + playerlist.placeNewPlayer(this.connection, serverplayer, this.createCookie(this.clientInformation)); + this.connection.resumeInboundAfterProtocolChange(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerConnectionListener.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerConnectionListener.java.patch new file mode 100644 index 0000000000..ee30186f96 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerConnectionListener.java.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/server/network/ServerConnectionListener.java ++++ b/net/minecraft/server/network/ServerConnectionListener.java +@@ -105,10 +104,20 @@ + ((Connection) object).configurePacketHandler(channelpipeline); + ((Connection) object).setListenerForServerboundHandshake(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object)); + } +- }).group(eventloopgroup).localAddress(inetaddress, i)).bind().syncUninterruptibly()); ++ }).group(eventloopgroup).localAddress(address, port)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit + } + } + ++ // CraftBukkit start ++ public void acceptConnections() { ++ synchronized (this.channels) { ++ for (ChannelFuture future : this.channels) { ++ future.channel().config().setAutoRead(true); ++ } ++ } ++ } ++ // CraftBukkit end ++ + public SocketAddress startMemoryChannel() { + List list = this.channels; + ChannelFuture channelfuture; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch new file mode 100644 index 0000000000..89935a450c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch @@ -0,0 +1,1682 @@ +--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -184,6 +185,62 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.mojang.datafixers.util.Pair; ++import java.util.Arrays; ++import java.util.concurrent.ExecutionException; ++import java.util.concurrent.atomic.AtomicInteger; ++import java.util.function.Function; ++import net.minecraft.network.chat.OutgoingChatMessage; ++import net.minecraft.world.entity.animal.Bucketable; ++import net.minecraft.world.entity.animal.allay.Allay; ++import net.minecraft.world.entity.item.ItemEntity; ++import net.minecraft.world.inventory.InventoryClickType; ++import net.minecraft.world.inventory.MerchantMenu; ++import net.minecraft.world.inventory.RecipeBookMenu; ++import net.minecraft.world.inventory.Slot; ++import net.minecraft.world.item.crafting.RecipeHolder; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftEntity; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.craftbukkit.util.LazyPlayerSet; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Event; ++import org.bukkit.event.block.Action; ++import org.bukkit.event.inventory.ClickType; ++import org.bukkit.event.inventory.CraftItemEvent; ++import org.bukkit.event.inventory.InventoryAction; ++import org.bukkit.event.inventory.InventoryClickEvent; ++import org.bukkit.event.inventory.InventoryCreativeEvent; ++import org.bukkit.event.inventory.InventoryType.SlotType; ++import org.bukkit.event.inventory.SmithItemEvent; ++import org.bukkit.event.player.AsyncPlayerChatEvent; ++import org.bukkit.event.player.PlayerAnimationEvent; ++import org.bukkit.event.player.PlayerAnimationType; ++import org.bukkit.event.player.PlayerChatEvent; ++import org.bukkit.event.player.PlayerCommandPreprocessEvent; ++import org.bukkit.event.player.PlayerInteractAtEntityEvent; ++import org.bukkit.event.player.PlayerInteractEntityEvent; ++import org.bukkit.event.player.PlayerItemHeldEvent; ++import org.bukkit.event.player.PlayerMoveEvent; ++import org.bukkit.event.player.PlayerRespawnEvent.RespawnReason; ++import org.bukkit.event.player.PlayerSwapHandItemsEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++import org.bukkit.event.player.PlayerToggleFlightEvent; ++import org.bukkit.event.player.PlayerToggleSneakEvent; ++import org.bukkit.event.player.PlayerToggleSprintEvent; ++import org.bukkit.inventory.CraftingInventory; ++import org.bukkit.inventory.EquipmentSlot; ++import org.bukkit.inventory.InventoryView; ++import org.bukkit.inventory.SmithingInventory; ++// CraftBukkit end ++ + public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl implements ServerGamePacketListener, ServerPlayerConnection, TickablePacketListener { + + static final Logger LOGGER = LogUtils.getLogger(); +@@ -195,7 +252,9 @@ + public final PlayerChunkSender chunkSender; + private int tickCount; + private int ackBlockChangesUpTo = -1; +- private int chatSpamTickCount; ++ // CraftBukkit start - multithreaded fields ++ private final AtomicInteger chatSpamTickCount = new AtomicInteger(); ++ // CraftBukkit end + private int dropSpamTickCount; + private double firstGoodX; + private double firstGoodY; +@@ -229,20 +288,36 @@ + private final FutureChain chatMessageChain; + private boolean waitingForSwitchToConfig; + +- public ServerGamePacketListenerImpl(MinecraftServer minecraftserver, Connection connection, ServerPlayer serverplayer, CommonListenerCookie commonlistenercookie) { +- super(minecraftserver, connection, commonlistenercookie); +- this.chunkSender = new PlayerChunkSender(connection.isMemoryConnection()); +- connection.setListener(this); +- this.player = serverplayer; +- serverplayer.connection = this; +- serverplayer.getTextFilter().join(); +- UUID uuid = serverplayer.getUUID(); ++ public ServerGamePacketListenerImpl(MinecraftServer minecraftserver, Connection networkmanager, ServerPlayer entityplayer, CommonListenerCookie commonlistenercookie) { ++ super(minecraftserver, networkmanager, commonlistenercookie, entityplayer); // CraftBukkit ++ this.chunkSender = new PlayerChunkSender(networkmanager.isMemoryConnection()); ++ networkmanager.setListener(this); ++ this.player = entityplayer; ++ entityplayer.connection = this; ++ entityplayer.getTextFilter().join(); ++ UUID uuid = entityplayer.getUUID(); + + Objects.requireNonNull(minecraftserver); + this.signedMessageDecoder = SignedMessageChain.Decoder.unsigned(uuid, minecraftserver::enforceSecureProfile); +- this.chatMessageChain = new FutureChain(minecraftserver); ++ this.chatMessageChain = new FutureChain(minecraftserver.chatExecutor); // CraftBukkit - async chat + } + ++ // CraftBukkit start - add fields ++ private int lastTick = MinecraftServer.currentTick; ++ private int allowedPlayerTicks = 1; ++ private int lastDropTick = MinecraftServer.currentTick; ++ private int lastBookTick = MinecraftServer.currentTick; ++ private int dropCount = 0; ++ ++ // Get position of last block hit for BlockDamageLevel.STOPPED ++ private double lastPosX = Double.MAX_VALUE; ++ private double lastPosY = Double.MAX_VALUE; ++ private double lastPosZ = Double.MAX_VALUE; ++ private float lastPitch = Float.MAX_VALUE; ++ private float lastYaw = Float.MAX_VALUE; ++ private boolean justTeleported = false; ++ // CraftBukkit end ++ + @Override + @Override + public void tick() { +@@ -295,15 +369,21 @@ + } + + this.keepConnectionAlive(); ++ // CraftBukkit start ++ for (int spam; (spam = this.chatSpamTickCount.get()) > 0 && !chatSpamTickCount.compareAndSet(spam, spam - 1); ) ; ++ /* Use thread-safe field access instead + if (this.chatSpamTickCount > 0) { + --this.chatSpamTickCount; + } ++ */ ++ // CraftBukkit end + + if (this.dropSpamTickCount > 0) { + --this.dropSpamTickCount; + } + + if (this.player.getLastActionTime() > 0L && this.server.getPlayerIdleTimeout() > 0 && Util.getMillis() - this.player.getLastActionTime() > (long) this.server.getPlayerIdleTimeout() * 1000L * 60L) { ++ this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 + this.disconnect(Component.translatable("multiplayer.disconnect.idling")); + } + +@@ -399,7 +474,34 @@ + double d9 = entity.getDeltaMovement().lengthSqr(); + double d10 = d6 * d6 + d7 * d7 + d8 * d8; + +- if (d10 - d9 > 100.0D && !this.isSingleplayerOwner()) { ++ ++ // CraftBukkit start - handle custom speeds and skipped ticks ++ this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick; ++ this.allowedPlayerTicks = Math.max(this.allowedPlayerTicks, 1); ++ this.lastTick = (int) (System.currentTimeMillis() / 50); ++ ++ ++this.receivedMovePacketCount; ++ int i = this.receivedMovePacketCount - this.knownMovePacketCount; ++ if (i > Math.max(this.allowedPlayerTicks, 5)) { ++ ServerGamePacketListenerImpl.LOGGER.debug(this.player.getScoreboardName() + " is sending move packets too frequently (" + i + " packets since last tick)"); ++ i = 1; ++ } ++ ++ if (d10 > 0) { ++ allowedPlayerTicks -= 1; ++ } else { ++ allowedPlayerTicks = 20; ++ } ++ double speed; ++ if (player.getAbilities().flying) { ++ speed = player.getAbilities().flyingSpeed * 20f; ++ } else { ++ speed = player.getAbilities().walkingSpeed * 10f; ++ } ++ speed *= 2f; // TODO: Get the speed of the vehicle instead of the player ++ ++ if (d10 - d9 > Math.max(100.0D, Math.pow((double) (10.0F * (float) i * speed), 2)) && !this.isSingleplayerOwner()) { ++ // CraftBukkit end + ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", new Object[]{entity.getName().getString(), this.player.getName().getString(), d6, d7, d8}); + this.send(new ClientboundMoveVehiclePacket(entity)); + return; +@@ -439,14 +541,72 @@ + } + + entity.absMoveTo(d3, d4, d5, f, f1); +- boolean flag3 = serverlevel.noCollision(entity, entity.getBoundingBox().deflate(0.0625D)); ++ player.absMoveTo(d3, d4, d5, this.player.getYRot(), this.player.getXRot()); // CraftBukkit ++ boolean flag3 = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D)); + + if (flag && (flag2 || !flag3)) { + entity.absMoveTo(d0, d1, d2, f, f1); ++ player.absMoveTo(d0, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit + this.send(new ClientboundMoveVehiclePacket(entity)); + return; + } + ++ // CraftBukkit start - fire PlayerMoveEvent ++ Player player = this.getCraftPlayer(); ++ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. ++ Location to = player.getLocation().clone(); // Start off the To location as the Players current location. ++ ++ // If the packet contains movement information then we update the To location with the correct XYZ. ++ to.setX(packet.getX()); ++ to.setY(packet.getY()); ++ to.setZ(packet.getZ()); ++ ++ ++ // If the packet contains look information then we update the To location with the correct Yaw & Pitch. ++ to.setYaw(packet.getYRot()); ++ to.setPitch(packet.getXRot()); ++ ++ // Prevent 40 event-calls for less than a single pixel of movement >.> ++ double delta = Math.pow(this.lastPosX - to.getX(), 2) + Math.pow(this.lastPosY - to.getY(), 2) + Math.pow(this.lastPosZ - to.getZ(), 2); ++ float deltaAngle = Math.abs(this.lastYaw - to.getYaw()) + Math.abs(this.lastPitch - to.getPitch()); ++ ++ if ((delta > 1f / 256 || deltaAngle > 10f) && !this.player.isImmobile()) { ++ this.lastPosX = to.getX(); ++ this.lastPosY = to.getY(); ++ this.lastPosZ = to.getZ(); ++ this.lastYaw = to.getYaw(); ++ this.lastPitch = to.getPitch(); ++ ++ // Skip the first time we do this ++ if (from.getX() != Double.MAX_VALUE) { ++ Location oldTo = to.clone(); ++ PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ // If the event is cancelled we move the player back to their old location. ++ if (event.isCancelled()) { ++ teleport(from); ++ return; ++ } ++ ++ // If a Plugin has changed the To destination then we teleport the Player ++ // there to avoid any 'Moved wrongly' or 'Moved too quickly' errors. ++ // We only do this if the Event was not cancelled. ++ if (!oldTo.equals(event.getTo()) && !event.isCancelled()) { ++ this.player.getBukkitEntity().teleport(event.getTo(), PlayerTeleportEvent.TeleportCause.PLUGIN); ++ return; ++ } ++ ++ // Check to see if the Players Location has some how changed during the call of the event. ++ // This can happen due to a plugin teleporting the player instead of using .setTo() ++ if (!from.equals(this.getCraftPlayer().getLocation()) && this.justTeleported) { ++ this.justTeleported = false; ++ return; ++ } ++ } ++ } ++ // CraftBukkit end ++ + this.player.serverLevel().getChunkSource().move(this.player); + this.player.checkMovementStatistics(this.player.getX() - d0, this.player.getY() - d1, this.player.getZ() - d2); + this.clientVehicleIsFloating = d11 >= -0.03125D && !flag1 && !this.server.isFlightAllowed() && !entity.isNoGravity() && this.noBlocksAround(entity); +@@ -481,6 +640,7 @@ + } + + this.awaitingPositionFromClient = null; ++ this.player.serverLevel().getChunkSource().move(this.player); // CraftBukkit + } + + } +@@ -497,10 +656,10 @@ + } + + @Override +- @Override +- public void handleRecipeBookChangeSettingsPacket(ServerboundRecipeBookChangeSettingsPacket serverboundrecipebookchangesettingspacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundrecipebookchangesettingspacket, this, this.player.serverLevel()); +- this.player.getRecipeBook().setBookSetting(serverboundrecipebookchangesettingspacket.getBookType(), serverboundrecipebookchangesettingspacket.isOpen(), serverboundrecipebookchangesettingspacket.isFiltering()); ++ public void handleRecipeBookChangeSettingsPacket(ServerboundRecipeBookChangeSettingsPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ CraftEventFactory.callRecipeBookSettingsEvent(this.player, packet.getBookType(), packet.isOpen(), packet.isFiltering()); // CraftBukkit ++ this.player.getRecipeBook().setBookSetting(packet.getBookType(), packet.isOpen(), packet.isFiltering()); + } + + @Override +@@ -519,10 +677,15 @@ + } + + @Override +- @Override +- public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket serverboundcommandsuggestionpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundcommandsuggestionpacket, this, this.player.serverLevel()); +- StringReader stringreader = new StringReader(serverboundcommandsuggestionpacket.getCommand()); ++ public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ // CraftBukkit start ++ if (chatSpamTickCount.addAndGet(1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { ++ this.disconnect(Component.translatable("disconnect.spam")); ++ return; ++ } ++ // CraftBukkit end ++ StringReader stringreader = new StringReader(packet.getCommand()); + + if (stringreader.canRead() && stringreader.peek() == '/') { + stringreader.skip(); +@@ -531,7 +694,8 @@ + ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); + + this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { +- this.send(new ClientboundCommandSuggestionsPacket(serverboundcommandsuggestionpacket.getId(), suggestions)); ++ if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer ++ this.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions)); + }); + } + +@@ -785,8 +940,15 @@ + int i = serverboundselecttradepacket.getItem(); + AbstractContainerMenu abstractcontainermenu = this.player.containerMenu; + +- if (abstractcontainermenu instanceof MerchantMenu) { +- MerchantMenu merchantmenu = (MerchantMenu) abstractcontainermenu; ++ if (container instanceof MerchantMenu) { ++ MerchantMenu containermerchant = (MerchantMenu) container; ++ // CraftBukkit start ++ final org.bukkit.event.inventory.TradeSelectEvent tradeSelectEvent = CraftEventFactory.callTradeSelectEvent(this.player, i, containermerchant); ++ if (tradeSelectEvent.isCancelled()) { ++ this.player.getBukkitEntity().updateInventory(); ++ return; ++ } ++ // CraftBukkit end + + if (!merchantmenu.stillValid(this.player)) { + ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, merchantmenu); +@@ -800,9 +962,15 @@ + } + + @Override +- @Override +- public void handleEditBook(ServerboundEditBookPacket serverboundeditbookpacket) { +- int i = serverboundeditbookpacket.getSlot(); ++ public void handleEditBook(ServerboundEditBookPacket packet) { ++ // CraftBukkit start ++ if (this.lastBookTick + 20 > MinecraftServer.currentTick) { ++ this.disconnect("Book edited too quickly!"); ++ return; ++ } ++ this.lastBookTick = MinecraftServer.currentTick; ++ // CraftBukkit end ++ int i = packet.getSlot(); + + if (Inventory.isHotbarSlot(i) || i == 40) { + List list = Lists.newArrayList(); +@@ -828,7 +996,7 @@ + ItemStack itemstack = this.player.getInventory().getItem(i); + + if (itemstack.is(Items.WRITABLE_BOOK)) { +- this.updateBookPages(list, UnaryOperator.identity(), itemstack); ++ this.updateBookPages(pages, UnaryOperator.identity(), itemstack.copy(), index, itemstack); // CraftBukkit + } + } + +@@ -853,13 +1021,13 @@ + + this.updateBookPages(list, (s) -> { + return Component.Serializer.toJson(Component.literal(s)); +- }, itemstack1); +- this.player.getInventory().setItem(i, itemstack1); ++ }, itemstack1, index, itemstack); // CraftBukkit ++ this.player.getInventory().setItem(index, itemstack); // CraftBukkit - event factory updates the hand book + } + } + +- private void updateBookPages(List list, UnaryOperator unaryoperator, ItemStack itemstack) { +- ListTag listtag = new ListTag(); ++ private void updateBookPages(List list, UnaryOperator unaryoperator, ItemStack itemstack, int slot, ItemStack handItem) { // CraftBukkit ++ ListTag nbttaglist = new ListTag(); + + if (this.player.isTextFilteringEnabled()) { + Stream stream = list.stream().map((filteredtext) -> { +@@ -887,7 +1055,8 @@ + } + } + +- itemstack.addTagElement("pages", listtag); ++ itemstack.addTagElement("pages", nbttaglist); ++ CraftEventFactory.handleEditBookEvent(player, slot, handItem, itemstack); // CraftBukkit + } + + @Override +@@ -948,7 +1113,7 @@ + } else { + ServerLevel serverlevel = this.player.serverLevel(); + +- if (!this.player.wonGame) { ++ if (!this.player.wonGame && !this.player.isImmobile()) { // CraftBukkit + if (this.tickCount == 0) { + this.resetPosition(); + } +@@ -958,7 +1123,7 @@ + this.awaitingTeleportTime = this.tickCount; + this.teleport(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); + } +- ++ this.allowedPlayerTicks = 20; // CraftBukkit + } else { + this.awaitingTeleportTime = this.tickCount; + double d0 = clampHorizontal(serverboundmoveplayerpacket.getX(this.player.getX())); +@@ -970,7 +1135,15 @@ + if (this.player.isPassenger()) { + this.player.absMoveTo(this.player.getX(), this.player.getY(), this.player.getZ(), f, f1); + this.player.serverLevel().getChunkSource().move(this.player); ++ this.allowedPlayerTicks = 20; // CraftBukkit + } else { ++ // CraftBukkit - Make sure the move is valid but then reset it for plugins to modify ++ double prevX = player.getX(); ++ double prevY = player.getY(); ++ double prevZ = player.getZ(); ++ float prevYaw = player.getYRot(); ++ float prevPitch = player.getXRot(); ++ // CraftBukkit end + double d3 = this.player.getX(); + double d4 = this.player.getY(); + double d5 = this.player.getZ(); +@@ -990,7 +1163,12 @@ + ++this.receivedMovePacketCount; + int i = this.receivedMovePacketCount - this.knownMovePacketCount; + +- if (i > 5) { ++ // CraftBukkit start - handle custom speeds and skipped ticks ++ this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick; ++ this.allowedPlayerTicks = Math.max(this.allowedPlayerTicks, 1); ++ this.lastTick = (int) (System.currentTimeMillis() / 50); ++ ++ if (i > Math.max(this.allowedPlayerTicks, 5)) { + ServerGamePacketListenerImpl.LOGGER.debug("{} is sending move packets too frequently ({} packets since last tick)", this.player.getName().getString(), i); + i = 1; + } +@@ -998,7 +1188,8 @@ + if (!this.player.isChangingDimension() && (!this.player.level().getGameRules().getBoolean(GameRules.RULE_DISABLE_ELYTRA_MOVEMENT_CHECK) || !this.player.isFallFlying())) { + float f2 = this.player.isFallFlying() ? 300.0F : 100.0F; + +- if (d10 - d9 > (double) (f2 * (float) i) && !this.isSingleplayerOwner()) { ++ if (d10 - d9 > Math.max(f2, Math.pow((double) (10.0F * (float) i * speed), 2)) && !this.isSingleplayerOwner()) { ++ // CraftBukkit end + ServerGamePacketListenerImpl.LOGGER.warn("{} moved too quickly! {},{},{}", new Object[]{this.player.getName().getString(), d6, d7, d8}); + this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot()); + return; +@@ -1019,7 +1210,8 @@ + + boolean flag1 = this.player.verticalCollisionBelow; + +- this.player.move(MoverType.PLAYER, new Vec3(d6, d7, d8)); ++ this.player.move(EnumMoveType.PLAYER, new Vec3(d6, d7, d8)); ++ this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move + double d11 = d7; + + d6 = d0 - this.player.getX(); +@@ -1037,10 +1229,71 @@ + ServerGamePacketListenerImpl.LOGGER.warn("{} moved wrongly!", this.player.getName().getString()); + } + +- if (!this.player.noPhysics && !this.player.isSleeping() && (flag2 && serverlevel.noCollision(this.player, aabb) || this.isPlayerCollidingWithAnythingNew(serverlevel, aabb, d0, d1, d2))) { +- this.teleport(d3, d4, d5, f, f1); +- this.player.doCheckFallDamage(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5, serverboundmoveplayerpacket.isOnGround()); ++ if (!this.player.noPhysics && !this.player.isSleeping() && (flag2 && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb, d0, d1, d2))) { ++ this.internalTeleport(d3, d4, d5, f, f1, Collections.emptySet()); // CraftBukkit - SPIGOT-1807: Don't call teleport event, when the client thinks the player is falling, because the chunks are not loaded on the client yet. ++ this.player.doCheckFallDamage(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5, packet.isOnGround()); + } else { ++ // CraftBukkit start - fire PlayerMoveEvent ++ // Reset to old location first ++ this.player.absMoveTo(prevX, prevY, prevZ, prevYaw, prevPitch); ++ ++ Player player = this.getCraftPlayer(); ++ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. ++ Location to = player.getLocation().clone(); // Start off the To location as the Players current location. ++ ++ // If the packet contains movement information then we update the To location with the correct XYZ. ++ if (packet.hasPos) { ++ to.setX(packet.x); ++ to.setY(packet.y); ++ to.setZ(packet.z); ++ } ++ ++ // If the packet contains look information then we update the To location with the correct Yaw & Pitch. ++ if (packet.hasRot) { ++ to.setYaw(packet.yRot); ++ to.setPitch(packet.xRot); ++ } ++ ++ // Prevent 40 event-calls for less than a single pixel of movement >.> ++ double delta = Math.pow(this.lastPosX - to.getX(), 2) + Math.pow(this.lastPosY - to.getY(), 2) + Math.pow(this.lastPosZ - to.getZ(), 2); ++ float deltaAngle = Math.abs(this.lastYaw - to.getYaw()) + Math.abs(this.lastPitch - to.getPitch()); ++ ++ if ((delta > 1f / 256 || deltaAngle > 10f) && !this.player.isImmobile()) { ++ this.lastPosX = to.getX(); ++ this.lastPosY = to.getY(); ++ this.lastPosZ = to.getZ(); ++ this.lastYaw = to.getYaw(); ++ this.lastPitch = to.getPitch(); ++ ++ // Skip the first time we do this ++ if (from.getX() != Double.MAX_VALUE) { ++ Location oldTo = to.clone(); ++ PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ // If the event is cancelled we move the player back to their old location. ++ if (event.isCancelled()) { ++ teleport(from); ++ return; ++ } ++ ++ // If a Plugin has changed the To destination then we teleport the Player ++ // there to avoid any 'Moved wrongly' or 'Moved too quickly' errors. ++ // We only do this if the Event was not cancelled. ++ if (!oldTo.equals(event.getTo()) && !event.isCancelled()) { ++ this.player.getBukkitEntity().teleport(event.getTo(), PlayerTeleportEvent.TeleportCause.PLUGIN); ++ return; ++ } ++ ++ // Check to see if the Players Location has some how changed during the call of the event. ++ // This can happen due to a plugin teleporting the player instead of using .setTo() ++ if (!from.equals(this.getCraftPlayer().getLocation()) && this.justTeleported) { ++ this.justTeleported = false; ++ return; ++ } ++ } ++ } ++ // CraftBukkit end + this.player.absMoveTo(d0, d1, d2, f, f1); + this.clientIsFloating = d11 >= -0.03125D && !flag1 && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR && !this.server.isFlightAllowed() && !this.player.getAbilities().mayfly && !this.player.hasEffect(MobEffects.LEVITATION) && !this.player.isFallFlying() && !this.player.isAutoSpinAttack() && this.noBlocksAround(this.player); + this.player.serverLevel().getChunkSource().move(this.player); +@@ -1081,11 +1334,68 @@ + return true; + } + +- public void teleport(double d0, double d1, double d2, float f, float f1) { +- this.teleport(d0, d1, d2, f, f1, Collections.emptySet()); ++ // CraftBukkit start - Delegate to teleport(Location) ++ public void teleport(double x, double d1, double y, float f, float z) { ++ this.teleport(x, d1, y, f, z, PlayerTeleportEvent.TeleportCause.UNKNOWN); + } + +- public void teleport(double d0, double d1, double d2, float f, float f1, Set set) { ++ public void teleport(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { ++ this.teleport(d0, d1, d2, f, f1, Collections.emptySet(), cause); ++ } ++ ++ public void teleport(double x, double d1, double y, float f, float z, Set set) { ++ this.teleport(x, d1, y, f, z, set, PlayerTeleportEvent.TeleportCause.UNKNOWN); ++ } ++ ++ public boolean teleport(double d0, double d1, double d2, float f, float f1, Set set, PlayerTeleportEvent.TeleportCause cause) { // CraftBukkit - Return event status ++ Player player = this.getCraftPlayer(); ++ Location from = player.getLocation(); ++ ++ double x = d0; ++ double y = d1; ++ double z = d2; ++ float yaw = f; ++ float pitch = f1; ++ ++ Location to = new Location(this.getCraftPlayer().getWorld(), x, y, z, yaw, pitch); ++ // SPIGOT-5171: Triggered on join ++ if (from.equals(to)) { ++ this.internalTeleport(d0, d1, d2, f, f1, set); ++ return false; // CraftBukkit - Return event status ++ } ++ ++ PlayerTeleportEvent event = new PlayerTeleportEvent(player, from.clone(), to.clone(), cause); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled() || !to.equals(event.getTo())) { ++ set.clear(); // Can't relative teleport ++ to = event.isCancelled() ? event.getFrom() : event.getTo(); ++ d0 = to.getX(); ++ d1 = to.getY(); ++ d2 = to.getZ(); ++ f = to.getYaw(); ++ f1 = to.getPitch(); ++ } ++ ++ this.internalTeleport(d0, d1, d2, f, f1, set); ++ return event.isCancelled(); // CraftBukkit - Return event status ++ } ++ ++ public void teleport(Location dest) { ++ internalTeleport(dest.getX(), dest.getY(), dest.getZ(), dest.getYaw(), dest.getPitch(), Collections.emptySet()); ++ } ++ ++ private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set set) { ++ // CraftBukkit start ++ if (Float.isNaN(f)) { ++ f = 0; ++ } ++ if (Float.isNaN(f1)) { ++ f1 = 0; ++ } ++ ++ this.justTeleported = true; ++ // CraftBukkit end + double d3 = set.contains(RelativeMovement.X) ? this.player.getX() : 0.0D; + double d4 = set.contains(RelativeMovement.Y) ? this.player.getY() : 0.0D; + double d5 = set.contains(RelativeMovement.Z) ? this.player.getZ() : 0.0D; +@@ -1097,16 +1407,24 @@ + this.awaitingTeleport = 0; + } + ++ // CraftBukkit start - update last location ++ this.lastPosX = this.awaitingPositionFromClient.x; ++ this.lastPosY = this.awaitingPositionFromClient.y; ++ this.lastPosZ = this.awaitingPositionFromClient.z; ++ this.lastYaw = f; ++ this.lastPitch = f1; ++ // CraftBukkit end ++ + this.awaitingTeleportTime = this.tickCount; + this.player.absMoveTo(d0, d1, d2, f, f1); + this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport)); + } + + @Override +- @Override +- public void handlePlayerAction(ServerboundPlayerActionPacket serverboundplayeractionpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundplayeractionpacket, this, this.player.serverLevel()); +- BlockPos blockpos = serverboundplayeractionpacket.getPos(); ++ public void handlePlayerAction(ServerboundPlayerActionPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit ++ BlockPos blockposition = packet.getPos(); + + this.player.resetLastActionTime(); + ServerboundPlayerActionPacket.Action serverboundplayeractionpacket_action = serverboundplayeractionpacket.getAction(); +@@ -1116,14 +1434,46 @@ + if (!this.player.isSpectator()) { + ItemStack itemstack = this.player.getItemInHand(InteractionHand.OFF_HAND); + +- this.player.setItemInHand(InteractionHand.OFF_HAND, this.player.getItemInHand(InteractionHand.MAIN_HAND)); +- this.player.setItemInHand(InteractionHand.MAIN_HAND, itemstack); ++ // CraftBukkit start - inspiration taken from DispenserRegistry (See SpigotCraft#394) ++ CraftItemStack mainHand = CraftItemStack.asCraftMirror(itemstack); ++ CraftItemStack offHand = CraftItemStack.asCraftMirror(this.player.getItemInHand(EnumHand.MAIN_HAND)); ++ PlayerSwapHandItemsEvent swapItemsEvent = new PlayerSwapHandItemsEvent(getCraftPlayer(), mainHand.clone(), offHand.clone()); ++ this.cserver.getPluginManager().callEvent(swapItemsEvent); ++ if (swapItemsEvent.isCancelled()) { ++ return; ++ } ++ if (swapItemsEvent.getOffHandItem().equals(offHand)) { ++ this.player.setItemInHand(EnumHand.OFF_HAND, this.player.getItemInHand(EnumHand.MAIN_HAND)); ++ } else { ++ this.player.setItemInHand(EnumHand.OFF_HAND, CraftItemStack.asNMSCopy(swapItemsEvent.getOffHandItem())); ++ } ++ if (swapItemsEvent.getMainHandItem().equals(mainHand)) { ++ this.player.setItemInHand(EnumHand.MAIN_HAND, itemstack); ++ } else { ++ this.player.setItemInHand(EnumHand.MAIN_HAND, CraftItemStack.asNMSCopy(swapItemsEvent.getMainHandItem())); ++ } ++ // CraftBukkit end + this.player.stopUsingItem(); + } + + return; + case DROP_ITEM: + if (!this.player.isSpectator()) { ++ // limit how quickly items can be dropped ++ // If the ticks aren't the same then the count starts from 0 and we update the lastDropTick. ++ if (this.lastDropTick != MinecraftServer.currentTick) { ++ this.dropCount = 0; ++ this.lastDropTick = MinecraftServer.currentTick; ++ } else { ++ // Else we increment the drop count and check the amount. ++ this.dropCount++; ++ if (this.dropCount >= 20) { ++ LOGGER.warn(this.player.getScoreboardName() + " dropped their items too quickly!"); ++ this.disconnect("You dropped your items too quickly (Hacking?)"); ++ return; ++ } ++ } ++ // CraftBukkit end + this.player.drop(false); + } + +@@ -1159,13 +1509,13 @@ + } + + @Override +- @Override +- public void handleUseItemOn(ServerboundUseItemOnPacket serverbounduseitemonpacket) { +- PacketUtils.ensureRunningOnSameThread(serverbounduseitemonpacket, this, this.player.serverLevel()); +- this.player.connection.ackBlockChangesUpTo(serverbounduseitemonpacket.getSequence()); +- ServerLevel serverlevel = this.player.serverLevel(); +- InteractionHand interactionhand = serverbounduseitemonpacket.getHand(); +- ItemStack itemstack = this.player.getItemInHand(interactionhand); ++ public void handleUseItemOn(ServerboundUseItemOnPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit ++ this.player.connection.ackBlockChangesUpTo(packet.getSequence()); ++ ServerLevel worldserver = this.player.serverLevel(); ++ EnumHand enumhand = packet.getHand(); ++ ItemStack itemstack = this.player.getItemInHand(enumhand); + + if (itemstack.isItemEnabled(serverlevel.enabledFeatures())) { + BlockHitResult blockhitresult = serverbounduseitemonpacket.getHitResult(); +@@ -1183,9 +1533,10 @@ + this.player.resetLastActionTime(); + int i = this.player.level().getMaxBuildHeight(); + +- if (blockpos.getY() < i) { +- if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D) < 64.0D && serverlevel.mayInteract(this.player, blockpos)) { +- InteractionResult interactionresult = this.player.gameMode.useItemOn(this.player, serverlevel, itemstack, interactionhand, blockhitresult); ++ if (blockposition.getY() < i) { ++ if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.mayInteract(this.player, blockposition)) { ++ this.player.stopUsingItem(); // CraftBukkit - SPIGOT-4706 ++ InteractionResult enuminteractionresult = this.player.gameMode.useItemOn(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock); + + if (direction == Direction.UP && !interactionresult.consumesAction() && blockpos.getY() >= i - 1 && wasBlockPlacementAttempt(this.player, itemstack)) { + MutableComponent mutablecomponent = Component.translatable("build.tooHigh", i - 1).withStyle(ChatFormatting.RED); +@@ -1211,22 +1562,44 @@ + } + + @Override +- @Override +- public void handleUseItem(ServerboundUseItemPacket serverbounduseitempacket) { +- PacketUtils.ensureRunningOnSameThread(serverbounduseitempacket, this, this.player.serverLevel()); +- this.ackBlockChangesUpTo(serverbounduseitempacket.getSequence()); +- ServerLevel serverlevel = this.player.serverLevel(); +- InteractionHand interactionhand = serverbounduseitempacket.getHand(); +- ItemStack itemstack = this.player.getItemInHand(interactionhand); ++ public void handleUseItem(ServerboundUseItemPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit ++ this.ackBlockChangesUpTo(packet.getSequence()); ++ ServerLevel worldserver = this.player.serverLevel(); ++ EnumHand enumhand = packet.getHand(); ++ ItemStack itemstack = this.player.getItemInHand(enumhand); + + this.player.resetLastActionTime(); +- if (!itemstack.isEmpty() && itemstack.isItemEnabled(serverlevel.enabledFeatures())) { +- InteractionResult interactionresult = this.player.gameMode.useItem(this.player, serverlevel, itemstack, interactionhand); ++ if (!itemstack.isEmpty() && itemstack.isItemEnabled(worldserver.enabledFeatures())) { ++ // CraftBukkit start ++ // Raytrace to look for 'rogue armswings' ++ float f1 = this.player.getXRot(); ++ float f2 = this.player.getYRot(); ++ double d0 = this.player.getX(); ++ double d1 = this.player.getY() + (double) this.player.getEyeHeight(); ++ double d2 = this.player.getZ(); ++ Vec3 vec3d = new Vec3(d0, d1, d2); + + if (interactionresult.shouldSwing()) { + this.player.swing(interactionhand, true); + } + ++ if (cancelled) { ++ this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524 ++ return; ++ } ++ itemstack = this.player.getItemInHand(enumhand); // Update in case it was changed in the event ++ if (itemstack.isEmpty()) { ++ return; ++ } ++ // CraftBukkit end ++ InteractionResult enuminteractionresult = this.player.gameMode.useItem(this.player, worldserver, itemstack, enumhand); ++ ++ if (enuminteractionresult.shouldSwing()) { ++ this.player.swing(enumhand, true); ++ } ++ + } + } + +@@ -1242,7 +1635,7 @@ + Entity entity = serverboundteleporttoentitypacket.getEntity(serverlevel); + + if (entity != null) { +- this.player.teleportTo(serverlevel, entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot()); ++ this.player.teleportTo(worldserver, entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot(), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.SPECTATE); // CraftBukkit + return; + } + } +@@ -1265,19 +1657,31 @@ + } + + @Override +- @Override +- public void onDisconnect(Component component) { +- ServerGamePacketListenerImpl.LOGGER.info("{} lost connection: {}", this.player.getName().getString(), component.getString()); ++ public void onDisconnect(Component reason) { ++ // CraftBukkit start - Rarely it would send a disconnect line twice ++ if (this.processedDisconnect) { ++ return; ++ } else { ++ this.processedDisconnect = true; ++ } ++ // CraftBukkit end ++ ServerGamePacketListenerImpl.LOGGER.info("{} lost connection: {}", this.player.getName().getString(), reason.getString()); + this.removePlayerFromWorld(); + super.onDisconnect(component); + } + + private void removePlayerFromWorld() { + this.chatMessageChain.close(); ++ // CraftBukkit start - Replace vanilla quit message handling with our own. ++ /* + this.server.invalidateStatus(); + this.server.getPlayerList().broadcastSystemMessage(Component.translatable("multiplayer.player.left", this.player.getDisplayName()).withStyle(ChatFormatting.YELLOW), false); + this.player.disconnect(); +- this.server.getPlayerList().remove(this.player); ++ String quitMessage = this.server.getPlayerList().remove(this.player); ++ if ((quitMessage != null) && (quitMessage.length() > 0)) { ++ this.server.getPlayerList().broadcastMessage(CraftChatMessage.fromString(quitMessage)); ++ } ++ // CraftBukkit end + this.player.getTextFilter().leave(); + } + +@@ -1290,11 +1696,19 @@ + } + + @Override +- @Override +- public void handleSetCarriedItem(ServerboundSetCarriedItemPacket serverboundsetcarrieditempacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundsetcarrieditempacket, this, this.player.serverLevel()); +- if (serverboundsetcarrieditempacket.getSlot() >= 0 && serverboundsetcarrieditempacket.getSlot() < Inventory.getSelectionSize()) { +- if (this.player.getInventory().selected != serverboundsetcarrieditempacket.getSlot() && this.player.getUsedItemHand() == InteractionHand.MAIN_HAND) { ++ public void handleSetCarriedItem(ServerboundSetCarriedItemPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit ++ if (packet.getSlot() >= 0 && packet.getSlot() < Inventory.getSelectionSize()) { ++ PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getCraftPlayer(), this.player.getInventory().selected, packet.getSlot()); ++ this.cserver.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ this.send(new ClientboundSetCarriedItemPacket(this.player.getInventory().selected)); ++ this.player.resetLastActionTime(); ++ return; ++ } ++ // CraftBukkit end ++ if (this.player.getInventory().selected != packet.getSlot() && this.player.getUsedItemHand() == EnumHand.MAIN_HAND) { + this.player.stopUsingItem(); + } + +@@ -1302,19 +1716,25 @@ + this.player.resetLastActionTime(); + } else { + ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); ++ this.disconnect("Invalid hotbar selection (Hacking?)"); // CraftBukkit + } + } + + @Override +- @Override +- public void handleChat(ServerboundChatPacket serverboundchatpacket) { +- if (isChatMessageIllegal(serverboundchatpacket.message())) { ++ public void handleChat(ServerboundChatPacket packet) { ++ // CraftBukkit start - async chat ++ // SPIGOT-3638 ++ if (this.server.isStopped()) { ++ return; ++ } ++ // CraftBukkit end ++ if (isChatMessageIllegal(packet.message())) { + this.disconnect(Component.translatable("multiplayer.disconnect.illegal_characters")); + } else { + Optional optional = this.tryHandleChat(serverboundchatpacket.lastSeenMessages()); + + if (optional.isPresent()) { +- this.server.submit(() -> { ++ // this.server.submit(() -> { // CraftBukkit - async chat + PlayerChatMessage playerchatmessage; + + try { +@@ -1324,15 +1744,15 @@ + return; + } + +- CompletableFuture completablefuture = this.filterTextPacket(playerchatmessage.signedContent()); +- Component component = this.server.getChatDecorator().decorate(this.player, playerchatmessage.decoratedContent()); ++ CompletableFuture completablefuture = this.filterTextPacket(playerchatmessage.signedContent()).thenApplyAsync(Function.identity(), this.server.chatExecutor); // CraftBukkit - async chat ++ Component ichatbasecomponent = this.server.getChatDecorator().decorate(this.player, playerchatmessage.decoratedContent()); + + this.chatMessageChain.append(completablefuture, (filteredtext) -> { + PlayerChatMessage playerchatmessage1 = playerchatmessage.withUnsignedContent(component).filter(filteredtext.mask()); + + this.broadcastChatMessage(playerchatmessage1); + }); +- }); ++ // }); // CraftBukkit - async chat + } + + } +@@ -1348,7 +1767,13 @@ + + if (optional.isPresent()) { + this.server.submit(() -> { +- this.performChatCommand(serverboundchatcommandpacket, (LastSeenMessages) optional.get()); ++ // CraftBukkit start - SPIGOT-7346: Prevent disconnected players from executing commands ++ if (player.hasDisconnected()) { ++ return; ++ } ++ // CraftBukkit end ++ ++ this.performChatCommand(packet, (LastSeenMessages) optional.get()); + this.detectRateSpam(); + }); + } +@@ -1356,15 +1781,28 @@ + } + } + +- private void performChatCommand(ServerboundChatCommandPacket serverboundchatcommandpacket, LastSeenMessages lastseenmessages) { +- ParseResults parseresults = this.parseCommand(serverboundchatcommandpacket.command()); ++ private void performChatCommand(ServerboundChatCommandPacket packet, LastSeenMessages lastSeenMessages) { ++ // CraftBukkit start ++ String command = "/" + packet.command(); ++ ServerGamePacketListenerImpl.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + command); + ++ PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(getCraftPlayer(), command, new LazyPlayerSet(server)); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ command = event.getMessage().substring(1); ++ ++ ParseResults parseresults = this.parseCommand(command); ++ // CraftBukkit end ++ + Map map; + + try { +- map = this.collectSignedArguments(serverboundchatcommandpacket, SignableCommand.of(parseresults), lastseenmessages); +- } catch (SignedMessageChain.DecodeException signedmessagechain_decodeexception) { +- this.handleMessageDecodeFailure(signedmessagechain_decodeexception); ++ map = (packet.command().equals(command)) ? this.collectSignedArguments(packet, SignableCommand.of(parseresults), lastSeenMessages) : Collections.emptyMap(); // CraftBukkit ++ } catch (SignedMessageChain.DecodeException signedmessagechain_a) { ++ this.handleMessageDecodeFailure(signedmessagechain_a); + return; + } + +@@ -1373,7 +1811,7 @@ + parseresults = Commands.mapSource(parseresults, (commandsourcestack) -> { + return commandsourcestack.withSigningContext(commandsigningcontext_signedarguments, this.chatMessageChain); + }); +- this.server.getCommands().performCommand(parseresults, serverboundchatcommandpacket.command()); ++ this.server.getCommands().performCommand(parseresults, command); // CraftBukkit + } + + private void handleMessageDecodeFailure(SignedMessageChain.DecodeException signedmessagechain_decodeexception) { +@@ -1410,7 +1848,7 @@ + private Optional tryHandleChat(LastSeenMessages.Update lastseenmessages_update) { + Optional optional = this.unpackAndApplyLastSeen(lastseenmessages_update); + +- if (this.player.getChatVisibility() == ChatVisiblity.HIDDEN) { ++ if (this.player.isRemoved() || this.player.getChatVisibility() == ChatVisiblity.HIDDEN) { // CraftBukkit - dead men tell no tales + this.send(new ClientboundSystemChatPacket(Component.translatable("chat.disabled.options").withStyle(ChatFormatting.RED), false)); + return Optional.empty(); + } else { +@@ -1444,20 +1882,74 @@ + return false; + } + +- private PlayerChatMessage getSignedMessage(ServerboundChatPacket serverboundchatpacket, LastSeenMessages lastseenmessages) throws SignedMessageChain.DecodeException { +- SignedMessageBody signedmessagebody = new SignedMessageBody(serverboundchatpacket.message(), serverboundchatpacket.timeStamp(), serverboundchatpacket.salt(), lastseenmessages); ++ // CraftBukkit start - add method ++ public void chat(String s, PlayerChatMessage original, boolean async) { ++ if (s.isEmpty() || this.player.getChatVisibility() == ChatVisiblity.HIDDEN) { ++ return; ++ } ++ OutgoingChatMessage outgoing = OutgoingChatMessage.create(original); + + return this.signedMessageDecoder.unpack(serverboundchatpacket.signature(), signedmessagebody); + } + +- private void broadcastChatMessage(PlayerChatMessage playerchatmessage) { +- this.server.getPlayerList().broadcastChatMessage(playerchatmessage, this.player, ChatType.bind(ChatType.CHAT, (Entity) this.player)); ++ private void handleCommand(String s) { ++ this.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + s); ++ ++ CraftPlayer player = this.getCraftPlayer(); ++ ++ PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(player, s, new LazyPlayerSet(server)); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ try { ++ if (this.cserver.dispatchCommand(event.getPlayer(), event.getMessage().substring(1))) { ++ return; ++ } ++ } catch (org.bukkit.command.CommandException ex) { ++ player.sendMessage(org.bukkit.ChatColor.RED + "An internal error occurred while attempting to perform this command"); ++ java.util.logging.Logger.getLogger(ServerGamePacketListenerImpl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); ++ return; ++ } ++ } ++ // CraftBukkit end ++ ++ private PlayerChatMessage getSignedMessage(ServerboundChatPacket packet, LastSeenMessages lastSeenMessages) throws SignedMessageChain.DecodeException { ++ SignedMessageBody signedmessagebody = new SignedMessageBody(packet.message(), packet.timeStamp(), packet.salt(), lastSeenMessages); ++ ++ return this.signedMessageDecoder.unpack(packet.signature(), signedmessagebody); ++ } ++ ++ private void broadcastChatMessage(PlayerChatMessage message) { ++ // CraftBukkit start ++ String s = message.signedContent(); ++ if (s.isEmpty()) { ++ LOGGER.warn(this.player.getScoreboardName() + " tried to send an empty message"); ++ } else if (getCraftPlayer().isConversing()) { ++ final String conversationInput = s; ++ this.server.processQueue.add(new Runnable() { ++ @Override ++ public void run() { ++ getCraftPlayer().acceptConversationInput(conversationInput); ++ } ++ }); ++ } else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { // Re-add "Command Only" flag check ++ this.send(new ClientboundSystemChatPacket(Component.translatable("chat.cannotSend").withStyle(ChatFormatting.RED), false)); ++ } else { ++ this.chat(s, message, true); ++ } ++ // this.server.getPlayerList().broadcastChatMessage(playerchatmessage, this.player, ChatMessageType.bind(ChatMessageType.CHAT, (Entity) this.player)); ++ // CraftBukkit end + this.detectRateSpam(); + } + + private void detectRateSpam() { +- this.chatSpamTickCount += 20; +- if (this.chatSpamTickCount > 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { ++ // CraftBukkit start - replaced with thread safe throttle ++ // this.chatSpamTickCount += 20; ++ if (this.chatSpamTickCount.addAndGet(20) > 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { ++ // CraftBukkit end + this.disconnect(Component.translatable("disconnect.spam")); + } + +@@ -1478,17 +2045,64 @@ + } + + @Override +- @Override +- public void handleAnimate(ServerboundSwingPacket serverboundswingpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundswingpacket, this, this.player.serverLevel()); ++ public void handleAnimate(ServerboundSwingPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.resetLastActionTime(); +- this.player.swing(serverboundswingpacket.getHand()); ++ // CraftBukkit start - Raytrace to look for 'rogue armswings' ++ float f1 = this.player.getXRot(); ++ float f2 = this.player.getYRot(); ++ double d0 = this.player.getX(); ++ double d1 = this.player.getY() + (double) this.player.getEyeHeight(); ++ double d2 = this.player.getZ(); ++ Location origin = new Location(this.player.level().getWorld(), d0, d1, d2, f2, f1); ++ ++ double d3 = player.gameMode.getGameModeForPlayer() == GameType.CREATIVE ? 5.0D : 4.5D; ++ // SPIGOT-5607: Only call interact event if no block or entity is being clicked. Use bukkit ray trace method, because it handles blocks and entities at the same time ++ // SPIGOT-7429: Make sure to call PlayerInteractEvent for spectators and non-pickable entities ++ org.bukkit.util.RayTraceResult result = this.player.level().getWorld().rayTrace(origin, origin.getDirection(), d3, org.bukkit.FluidCollisionMode.NEVER, false, 0.1, entity -> { ++ Entity handle = ((CraftEntity) entity).getHandle(); ++ return entity != this.player.getBukkitEntity() && this.player.getBukkitEntity().canSee(entity) && !handle.isSpectator() && handle.isPickable() && !handle.isPassengerOfSameVehicle(player); ++ }); ++ if (result == null) { ++ CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_AIR, this.player.getInventory().getSelected(), EnumHand.MAIN_HAND); ++ } ++ ++ // Arm swing animation ++ PlayerAnimationEvent event = new PlayerAnimationEvent(this.getCraftPlayer(), (packet.getHand() == EnumHand.MAIN_HAND) ? PlayerAnimationType.ARM_SWING : PlayerAnimationType.OFF_ARM_SWING); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) return; ++ // CraftBukkit end ++ this.player.swing(packet.getHand()); + } + + @Override +- @Override +- public void handlePlayerCommand(ServerboundPlayerCommandPacket serverboundplayercommandpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundplayercommandpacket, this, this.player.serverLevel()); ++ public void handlePlayerCommand(ServerboundPlayerCommandPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ // CraftBukkit start ++ if (this.player.isRemoved()) return; ++ switch (packet.getAction()) { ++ case PRESS_SHIFT_KEY: ++ case RELEASE_SHIFT_KEY: ++ PlayerToggleSneakEvent event = new PlayerToggleSneakEvent(this.getCraftPlayer(), packet.getAction() == ServerboundPlayerCommandPacket.EnumPlayerAction.PRESS_SHIFT_KEY); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ break; ++ case START_SPRINTING: ++ case STOP_SPRINTING: ++ PlayerToggleSprintEvent e2 = new PlayerToggleSprintEvent(this.getCraftPlayer(), packet.getAction() == ServerboundPlayerCommandPacket.EnumPlayerAction.START_SPRINTING); ++ this.cserver.getPluginManager().callEvent(e2); ++ ++ if (e2.isCancelled()) { ++ return; ++ } ++ break; ++ } ++ // CraftBukkit end + this.player.resetLastActionTime(); + Entity entity; + PlayerRideableJumping playerrideablejumping; +@@ -1569,9 +2183,15 @@ + } + } + +- public void sendPlayerChatMessage(PlayerChatMessage playerchatmessage, ChatType.Bound chattype_bound) { +- this.send(new ClientboundPlayerChatPacket(playerchatmessage.link().sender(), playerchatmessage.link().index(), playerchatmessage.signature(), playerchatmessage.signedBody().pack(this.messageSignatureCache), playerchatmessage.unsignedContent(), playerchatmessage.filterMask(), chattype_bound.toNetwork(this.player.level().registryAccess()))); +- this.addPendingMessage(playerchatmessage); ++ public void sendPlayerChatMessage(PlayerChatMessage chatMessage, ChatType.Bound boundType) { ++ // CraftBukkit start - SPIGOT-7262: if hidden we have to send as disguised message. Query whether we should send at all (but changing this may not be expected). ++ if (!getCraftPlayer().canSee(chatMessage.link().sender())) { ++ sendDisguisedChatMessage(chatMessage.decoratedContent(), boundType); ++ return; ++ } ++ // CraftBukkit end ++ this.send(new ClientboundPlayerChatPacket(chatMessage.link().sender(), chatMessage.link().index(), chatMessage.signature(), chatMessage.signedBody().pack(this.messageSignatureCache), chatMessage.unsignedContent(), chatMessage.filterMask(), boundType.toNetwork(this.player.level().registryAccess()))); ++ this.addPendingMessage(chatMessage); + } + + public void sendDisguisedChatMessage(Component component, ChatType.Bound chattype_bound) { +@@ -1595,11 +2214,11 @@ + } + + @Override +- @Override +- public void handleInteract(ServerboundInteractPacket serverboundinteractpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundinteractpacket, this, this.player.serverLevel()); +- final ServerLevel serverlevel = this.player.serverLevel(); +- final Entity entity = serverboundinteractpacket.getTarget(serverlevel); ++ public void handleInteract(ServerboundInteractPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit ++ final ServerLevel worldserver = this.player.serverLevel(); ++ final Entity entity = packet.getTarget(worldserver); + + this.player.resetLastActionTime(); + this.player.setShiftKeyDown(serverboundinteractpacket.isUsingSecondaryAction()); +@@ -1610,16 +2229,54 @@ + + AABB aabb = entity.getBoundingBox(); + +- if (aabb.distanceToSqr(this.player.getEyePosition()) < ServerGamePacketListenerImpl.MAX_INTERACTION_DISTANCE) { +- serverboundinteractpacket.dispatch(new ServerboundInteractPacket.Handler() { +- private void performInteraction(InteractionHand interactionhand, ServerGamePacketListenerImpl.EntityInteraction servergamepacketlistenerimpl_entityinteraction) { +- ItemStack itemstack = ServerGamePacketListenerImpl.this.player.getItemInHand(interactionhand); ++ if (axisalignedbb.distanceToSqr(this.player.getEyePosition()) < ServerGamePacketListenerImpl.MAX_INTERACTION_DISTANCE) { ++ packet.dispatch(new ServerboundInteractPacket.Handler() { ++ private void performInteraction(EnumHand enumhand, ServerGamePacketListenerImpl.EntityInteraction playerconnection_a, PlayerInteractEntityEvent event) { // CraftBukkit ++ ItemStack itemstack = ServerGamePacketListenerImpl.this.player.getItemInHand(enumhand); + + if (itemstack.isItemEnabled(serverlevel.enabledFeatures())) { + ItemStack itemstack1 = itemstack.copy(); +- InteractionResult interactionresult = servergamepacketlistenerimpl_entityinteraction.run(ServerGamePacketListenerImpl.this.player, entity, interactionhand); ++ // CraftBukkit start ++ ItemStack itemInHand = ServerGamePacketListenerImpl.this.player.getItemInHand(enumhand); ++ boolean triggerLeashUpdate = itemInHand != null && itemInHand.getItem() == Items.LEAD && entity instanceof Mob; ++ Item origItem = player.getInventory().getSelected() == null ? null : player.getInventory().getSelected().getItem(); + +- if (interactionresult.consumesAction()) { ++ cserver.getPluginManager().callEvent(event); ++ ++ // Entity in bucket - SPIGOT-4048 and SPIGOT-6859a ++ if ((entity instanceof Bucketable && entity instanceof LivingEntity && origItem != null && origItem.asItem() == Items.WATER_BUCKET) && (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem)) { ++ send(new ClientboundAddEntityPacket(entity)); ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ ++ if (triggerLeashUpdate && (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem)) { ++ // Refresh the current leash state ++ send(new ClientboundSetEntityLinkPacket(entity, ((Mob) entity).getLeashHolder())); ++ } ++ ++ if (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem) { ++ // Refresh the current entity metadata ++ entity.getEntityData().refresh(player); ++ // SPIGOT-7136 - Allays ++ if (entity instanceof Allay) { ++ send(new ClientboundSetEquipmentPacket(entity.getId(), Arrays.stream(net.minecraft.world.entity.EquipmentSlot.values()).map((slot) -> Pair.of(slot, ((LivingEntity) entity).getItemBySlot(slot).copy())).collect(Collectors.toList()))); ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ } ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ InteractionResult enuminteractionresult = playerconnection_a.run(ServerGamePacketListenerImpl.this.player, entity, enumhand); ++ ++ // CraftBukkit start ++ if (!itemInHand.isEmpty() && itemInHand.getCount() <= -1) { ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ // CraftBukkit end ++ ++ if (enuminteractionresult.consumesAction()) { + CriteriaTriggers.PLAYER_INTERACTED_WITH_ENTITY.trigger(ServerGamePacketListenerImpl.this.player, itemstack1, entity); + if (interactionresult.shouldSwing()) { + ServerGamePacketListenerImpl.this.player.swing(interactionhand, true); +@@ -1630,27 +2287,31 @@ + } + + @Override +- @Override +- public void onInteraction(InteractionHand interactionhand) { +- this.performInteraction(interactionhand, Player::interactOn); ++ public void onInteraction(EnumHand hand) { ++ this.performInteraction(hand, net.minecraft.world.entity.player.Player::interactOn, new PlayerInteractEntityEvent(getCraftPlayer(), entity.getBukkitEntity(), (hand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); // CraftBukkit + } + + @Override +- @Override +- public void onInteraction(InteractionHand interactionhand, Vec3 vec3) { +- this.performInteraction(interactionhand, (serverplayer, entity1, interactionhand1) -> { +- return entity1.interactAt(serverplayer, vec3, interactionhand1); +- }); ++ public void onInteraction(EnumHand hand, Vec3 interactionLocation) { ++ this.performInteraction(hand, (entityplayer, entity1, enumhand1) -> { ++ return entity1.interactAt(entityplayer, interactionLocation, enumhand1); ++ }, new PlayerInteractAtEntityEvent(getCraftPlayer(), entity.getBukkitEntity(), new org.bukkit.util.Vector(interactionLocation.x, interactionLocation.y, interactionLocation.z), (hand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); // CraftBukkit + } + + @Override + @Override + public void onAttack() { +- if (!(entity instanceof ItemEntity) && !(entity instanceof ExperienceOrb) && !(entity instanceof AbstractArrow) && entity != ServerGamePacketListenerImpl.this.player) { +- ItemStack itemstack = ServerGamePacketListenerImpl.this.player.getItemInHand(InteractionHand.MAIN_HAND); ++ // CraftBukkit ++ if (!(entity instanceof ItemEntity) && !(entity instanceof ExperienceOrb) && !(entity instanceof AbstractArrow) && (entity != ServerGamePacketListenerImpl.this.player || player.isSpectator())) { ++ ItemStack itemstack = ServerGamePacketListenerImpl.this.player.getItemInHand(EnumHand.MAIN_HAND); + + if (itemstack.isItemEnabled(serverlevel.enabledFeatures())) { + ServerGamePacketListenerImpl.this.player.attack(entity); ++ // CraftBukkit start ++ if (!itemstack.isEmpty() && itemstack.getCount() <= -1) { ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ // CraftBukkit end + } + } else { + ServerGamePacketListenerImpl.this.disconnect(Component.translatable("multiplayer.disconnect.invalid_entity_attacked")); +@@ -1695,19 +2354,23 @@ + } + + @Override +- @Override +- public void handleContainerClose(ServerboundContainerClosePacket serverboundcontainerclosepacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundcontainerclosepacket, this, this.player.serverLevel()); ++ public void handleContainerClose(ServerboundContainerClosePacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ ++ if (this.player.isImmobile()) return; // CraftBukkit ++ CraftEventFactory.handleInventoryCloseEvent(this.player); // CraftBukkit ++ + this.player.doCloseContainer(); + } + + @Override +- @Override +- public void handleContainerClick(ServerboundContainerClickPacket serverboundcontainerclickpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundcontainerclickpacket, this, this.player.serverLevel()); ++ public void handleContainerClick(ServerboundContainerClickPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.resetLastActionTime(); +- if (this.player.containerMenu.containerId == serverboundcontainerclickpacket.getContainerId()) { +- if (this.player.isSpectator()) { ++ if (this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu.stillValid(this.player)) { // CraftBukkit ++ boolean cancelled = this.player.isSpectator(); // CraftBukkit - see below if ++ if (false/*this.player.isSpectator()*/) { // CraftBukkit + this.player.containerMenu.sendAllDataToRemote(); + } else if (!this.player.containerMenu.stillValid(this.player)) { + ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu); +@@ -1720,9 +2383,286 @@ + boolean flag = serverboundcontainerclickpacket.getStateId() != this.player.containerMenu.getStateId(); + + this.player.containerMenu.suppressRemoteUpdates(); +- this.player.containerMenu.clicked(i, serverboundcontainerclickpacket.getButtonNum(), serverboundcontainerclickpacket.getClickType(), this.player); +- ObjectIterator objectiterator = Int2ObjectMaps.fastIterable(serverboundcontainerclickpacket.getChangedSlots()).iterator(); ++ // CraftBukkit start - Call InventoryClickEvent ++ if (packet.getSlotNum() < -1 && packet.getSlotNum() != -999) { ++ return; ++ } + ++ InventoryView inventory = this.player.containerMenu.getBukkitView(); ++ SlotType type = inventory.getSlotType(packet.getSlotNum()); ++ ++ InventoryClickEvent event; ++ ClickType click = ClickType.UNKNOWN; ++ InventoryAction action = InventoryAction.UNKNOWN; ++ ++ ItemStack itemstack = ItemStack.EMPTY; ++ ++ switch (packet.getClickType()) { ++ case PICKUP: ++ if (packet.getButtonNum() == 0) { ++ click = ClickType.LEFT; ++ } else if (packet.getButtonNum() == 1) { ++ click = ClickType.RIGHT; ++ } ++ if (packet.getButtonNum() == 0 || packet.getButtonNum() == 1) { ++ action = InventoryAction.NOTHING; // Don't want to repeat ourselves ++ if (packet.getSlotNum() == -999) { ++ if (!player.containerMenu.getCarried().isEmpty()) { ++ action = packet.getButtonNum() == 0 ? InventoryAction.DROP_ALL_CURSOR : InventoryAction.DROP_ONE_CURSOR; ++ } ++ } else if (packet.getSlotNum() < 0) { ++ action = InventoryAction.NOTHING; ++ } else { ++ Slot slot = this.player.containerMenu.getSlot(packet.getSlotNum()); ++ if (slot != null) { ++ ItemStack clickedItem = slot.getItem(); ++ ItemStack cursor = player.containerMenu.getCarried(); ++ if (clickedItem.isEmpty()) { ++ if (!cursor.isEmpty()) { ++ action = packet.getButtonNum() == 0 ? InventoryAction.PLACE_ALL : InventoryAction.PLACE_ONE; ++ } ++ } else if (slot.mayPickup(player)) { ++ if (cursor.isEmpty()) { ++ action = packet.getButtonNum() == 0 ? InventoryAction.PICKUP_ALL : InventoryAction.PICKUP_HALF; ++ } else if (slot.mayPlace(cursor)) { ++ if (ItemStack.isSameItemSameTags(clickedItem, cursor)) { ++ int toPlace = packet.getButtonNum() == 0 ? cursor.getCount() : 1; ++ toPlace = Math.min(toPlace, clickedItem.getMaxStackSize() - clickedItem.getCount()); ++ toPlace = Math.min(toPlace, slot.container.getMaxStackSize() - clickedItem.getCount()); ++ if (toPlace == 1) { ++ action = InventoryAction.PLACE_ONE; ++ } else if (toPlace == cursor.getCount()) { ++ action = InventoryAction.PLACE_ALL; ++ } else if (toPlace < 0) { ++ action = toPlace != -1 ? InventoryAction.PICKUP_SOME : InventoryAction.PICKUP_ONE; // this happens with oversized stacks ++ } else if (toPlace != 0) { ++ action = InventoryAction.PLACE_SOME; ++ } ++ } else if (cursor.getCount() <= slot.getMaxStackSize()) { ++ action = InventoryAction.SWAP_WITH_CURSOR; ++ } ++ } else if (ItemStack.isSameItemSameTags(cursor, clickedItem)) { ++ if (clickedItem.getCount() >= 0) { ++ if (clickedItem.getCount() + cursor.getCount() <= cursor.getMaxStackSize()) { ++ // As of 1.5, this is result slots only ++ action = InventoryAction.PICKUP_ALL; ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ break; ++ // TODO check on updates ++ case QUICK_MOVE: ++ if (packet.getButtonNum() == 0) { ++ click = ClickType.SHIFT_LEFT; ++ } else if (packet.getButtonNum() == 1) { ++ click = ClickType.SHIFT_RIGHT; ++ } ++ if (packet.getButtonNum() == 0 || packet.getButtonNum() == 1) { ++ if (packet.getSlotNum() < 0) { ++ action = InventoryAction.NOTHING; ++ } else { ++ Slot slot = this.player.containerMenu.getSlot(packet.getSlotNum()); ++ if (slot != null && slot.mayPickup(this.player) && slot.hasItem()) { ++ action = InventoryAction.MOVE_TO_OTHER_INVENTORY; ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } ++ } ++ break; ++ case SWAP: ++ if ((packet.getButtonNum() >= 0 && packet.getButtonNum() < 9) || packet.getButtonNum() == 40) { ++ click = (packet.getButtonNum() == 40) ? ClickType.SWAP_OFFHAND : ClickType.NUMBER_KEY; ++ Slot clickedSlot = this.player.containerMenu.getSlot(packet.getSlotNum()); ++ if (clickedSlot.mayPickup(player)) { ++ ItemStack hotbar = this.player.getInventory().getItem(packet.getButtonNum()); ++ boolean canCleanSwap = hotbar.isEmpty() || (clickedSlot.container == player.getInventory() && clickedSlot.mayPlace(hotbar)); // the slot will accept the hotbar item ++ if (clickedSlot.hasItem()) { ++ if (canCleanSwap) { ++ action = InventoryAction.HOTBAR_SWAP; ++ } else { ++ action = InventoryAction.HOTBAR_MOVE_AND_READD; ++ } ++ } else if (!clickedSlot.hasItem() && !hotbar.isEmpty() && clickedSlot.mayPlace(hotbar)) { ++ action = InventoryAction.HOTBAR_SWAP; ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } ++ break; ++ case CLONE: ++ if (packet.getButtonNum() == 2) { ++ click = ClickType.MIDDLE; ++ if (packet.getSlotNum() < 0) { ++ action = InventoryAction.NOTHING; ++ } else { ++ Slot slot = this.player.containerMenu.getSlot(packet.getSlotNum()); ++ if (slot != null && slot.hasItem() && player.getAbilities().instabuild && player.containerMenu.getCarried().isEmpty()) { ++ action = InventoryAction.CLONE_STACK; ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } ++ } else { ++ click = ClickType.UNKNOWN; ++ action = InventoryAction.UNKNOWN; ++ } ++ break; ++ case THROW: ++ if (packet.getSlotNum() >= 0) { ++ if (packet.getButtonNum() == 0) { ++ click = ClickType.DROP; ++ Slot slot = this.player.containerMenu.getSlot(packet.getSlotNum()); ++ if (slot != null && slot.hasItem() && slot.mayPickup(player) && !slot.getItem().isEmpty() && slot.getItem().getItem() != Item.byBlock(Blocks.AIR)) { ++ action = InventoryAction.DROP_ONE_SLOT; ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } else if (packet.getButtonNum() == 1) { ++ click = ClickType.CONTROL_DROP; ++ Slot slot = this.player.containerMenu.getSlot(packet.getSlotNum()); ++ if (slot != null && slot.hasItem() && slot.mayPickup(player) && !slot.getItem().isEmpty() && slot.getItem().getItem() != Item.byBlock(Blocks.AIR)) { ++ action = InventoryAction.DROP_ALL_SLOT; ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } ++ } else { ++ // Sane default (because this happens when they are holding nothing. Don't ask why.) ++ click = ClickType.LEFT; ++ if (packet.getButtonNum() == 1) { ++ click = ClickType.RIGHT; ++ } ++ action = InventoryAction.NOTHING; ++ } ++ break; ++ case QUICK_CRAFT: ++ this.player.containerMenu.clicked(packet.getSlotNum(), packet.getButtonNum(), packet.getClickType(), this.player); ++ break; ++ case PICKUP_ALL: ++ click = ClickType.DOUBLE_CLICK; ++ action = InventoryAction.NOTHING; ++ if (packet.getSlotNum() >= 0 && !this.player.containerMenu.getCarried().isEmpty()) { ++ ItemStack cursor = this.player.containerMenu.getCarried(); ++ action = InventoryAction.NOTHING; ++ // Quick check for if we have any of the item ++ if (inventory.getTopInventory().contains(CraftMagicNumbers.getMaterial(cursor.getItem())) || inventory.getBottomInventory().contains(CraftMagicNumbers.getMaterial(cursor.getItem()))) { ++ action = InventoryAction.COLLECT_TO_CURSOR; ++ } ++ } ++ break; ++ default: ++ break; ++ } ++ ++ if (packet.getClickType() != InventoryClickType.QUICK_CRAFT) { ++ if (click == ClickType.NUMBER_KEY) { ++ event = new InventoryClickEvent(inventory, type, packet.getSlotNum(), click, action, packet.getButtonNum()); ++ } else { ++ event = new InventoryClickEvent(inventory, type, packet.getSlotNum(), click, action); ++ } ++ ++ org.bukkit.inventory.Inventory top = inventory.getTopInventory(); ++ if (packet.getSlotNum() == 0 && top instanceof CraftingInventory) { ++ org.bukkit.inventory.Recipe recipe = ((CraftingInventory) top).getRecipe(); ++ if (recipe != null) { ++ if (click == ClickType.NUMBER_KEY) { ++ event = new CraftItemEvent(recipe, inventory, type, packet.getSlotNum(), click, action, packet.getButtonNum()); ++ } else { ++ event = new CraftItemEvent(recipe, inventory, type, packet.getSlotNum(), click, action); ++ } ++ } ++ } ++ ++ if (packet.getSlotNum() == 3 && top instanceof SmithingInventory) { ++ org.bukkit.inventory.ItemStack result = ((SmithingInventory) top).getResult(); ++ if (result != null) { ++ if (click == ClickType.NUMBER_KEY) { ++ event = new SmithItemEvent(inventory, type, packet.getSlotNum(), click, action, packet.getButtonNum()); ++ } else { ++ event = new SmithItemEvent(inventory, type, packet.getSlotNum(), click, action); ++ } ++ } ++ } ++ ++ event.setCancelled(cancelled); ++ AbstractContainerMenu oldContainer = this.player.containerMenu; // SPIGOT-1224 ++ cserver.getPluginManager().callEvent(event); ++ if (this.player.containerMenu != oldContainer) { ++ return; ++ } ++ ++ switch (event.getResult()) { ++ case ALLOW: ++ case DEFAULT: ++ this.player.containerMenu.clicked(i, packet.getButtonNum(), packet.getClickType(), this.player); ++ break; ++ case DENY: ++ /* Needs enum constructor in InventoryAction ++ if (action.modifiesOtherSlots()) { ++ ++ } else { ++ if (action.modifiesCursor()) { ++ this.player.playerConnection.sendPacket(new Packet103SetSlot(-1, -1, this.player.inventory.getCarried())); ++ } ++ if (action.modifiesClicked()) { ++ this.player.playerConnection.sendPacket(new Packet103SetSlot(this.player.activeContainer.windowId, packet102windowclick.slot, this.player.activeContainer.getSlot(packet102windowclick.slot).getItem())); ++ } ++ }*/ ++ switch (action) { ++ // Modified other slots ++ case PICKUP_ALL: ++ case MOVE_TO_OTHER_INVENTORY: ++ case HOTBAR_MOVE_AND_READD: ++ case HOTBAR_SWAP: ++ case COLLECT_TO_CURSOR: ++ case UNKNOWN: ++ this.player.containerMenu.sendAllDataToRemote(); ++ break; ++ // Modified cursor and clicked ++ case PICKUP_SOME: ++ case PICKUP_HALF: ++ case PICKUP_ONE: ++ case PLACE_ALL: ++ case PLACE_SOME: ++ case PLACE_ONE: ++ case SWAP_WITH_CURSOR: ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(-1, -1, this.player.inventoryMenu.incrementStateId(), this.player.containerMenu.getCarried())); ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(this.player.containerMenu.containerId, this.player.inventoryMenu.incrementStateId(), packet.getSlotNum(), this.player.containerMenu.getSlot(packet.getSlotNum()).getItem())); ++ break; ++ // Modified clicked only ++ case DROP_ALL_SLOT: ++ case DROP_ONE_SLOT: ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(this.player.containerMenu.containerId, this.player.inventoryMenu.incrementStateId(), packet.getSlotNum(), this.player.containerMenu.getSlot(packet.getSlotNum()).getItem())); ++ break; ++ // Modified cursor only ++ case DROP_ALL_CURSOR: ++ case DROP_ONE_CURSOR: ++ case CLONE_STACK: ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(-1, -1, this.player.inventoryMenu.incrementStateId(), this.player.containerMenu.getCarried())); ++ break; ++ // Nothing ++ case NOTHING: ++ break; ++ } ++ } ++ ++ if (event instanceof CraftItemEvent || event instanceof SmithItemEvent) { ++ // Need to update the inventory on crafting to ++ // correctly support custom recipes ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ } ++ // CraftBukkit end ++ ObjectIterator objectiterator = Int2ObjectMaps.fastIterable(packet.getChangedSlots()).iterator(); ++ + while (objectiterator.hasNext()) { + Entry entry = (Entry) objectiterator.next(); + +@@ -1751,17 +2690,26 @@ + if (!this.player.containerMenu.stillValid(this.player)) { + ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu); + } else { +- this.server.getRecipeManager().byKey(serverboundplacerecipepacket.getRecipe()).ifPresent((recipeholder) -> { +- ((RecipeBookMenu) this.player.containerMenu).handlePlacement(serverboundplacerecipepacket.isShiftDown(), recipeholder, this.player); ++ // CraftBukkit start - implement PlayerRecipeBookClickEvent ++ org.bukkit.inventory.Recipe recipe = this.cserver.getRecipe(CraftNamespacedKey.fromMinecraft(packet.getRecipe())); ++ if (recipe == null) { ++ return; ++ } ++ org.bukkit.event.player.PlayerRecipeBookClickEvent event = CraftEventFactory.callRecipeBookClickEvent(this.player, recipe, packet.isShiftDown()); ++ ++ // Cast to keyed should be safe as the recipe will never be a MerchantRecipe. ++ this.server.getRecipeManager().byKey(CraftNamespacedKey.toMinecraft(((org.bukkit.Keyed) event.getRecipe()).getKey())).ifPresent((recipeholder) -> { ++ ((RecipeBookMenu) this.player.containerMenu).handlePlacement(event.isShiftClick(), recipeholder, this.player); + }); ++ // CraftBukkit end + } + } + } + + @Override +- @Override +- public void handleContainerButtonClick(ServerboundContainerButtonClickPacket serverboundcontainerbuttonclickpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundcontainerbuttonclickpacket, this, this.player.serverLevel()); ++ public void handleContainerButtonClick(ServerboundContainerButtonClickPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.resetLastActionTime(); + if (this.player.containerMenu.containerId == serverboundcontainerbuttonclickpacket.getContainerId() && !this.player.isSpectator()) { + if (!this.player.containerMenu.stillValid(this.player)) { +@@ -1805,7 +2752,44 @@ + + boolean flag1 = serverboundsetcreativemodeslotpacket.getSlotNum() >= 1 && serverboundsetcreativemodeslotpacket.getSlotNum() <= 45; + boolean flag2 = itemstack.isEmpty() || itemstack.getDamageValue() >= 0 && itemstack.getCount() <= 64 && !itemstack.isEmpty(); ++ if (flag || (flag1 && !ItemStack.matches(this.player.inventoryMenu.getSlot(packet.getSlotNum()).getItem(), packet.getItem()))) { // Insist on valid slot ++ // CraftBukkit start - Call click event ++ InventoryView inventory = this.player.inventoryMenu.getBukkitView(); ++ org.bukkit.inventory.ItemStack item = CraftItemStack.asBukkitCopy(packet.getItem()); + ++ SlotType type = SlotType.QUICKBAR; ++ if (flag) { ++ type = SlotType.OUTSIDE; ++ } else if (packet.getSlotNum() < 36) { ++ if (packet.getSlotNum() >= 5 && packet.getSlotNum() < 9) { ++ type = SlotType.ARMOR; ++ } else { ++ type = SlotType.CONTAINER; ++ } ++ } ++ InventoryCreativeEvent event = new InventoryCreativeEvent(inventory, type, flag ? -999 : packet.getSlotNum(), item); ++ cserver.getPluginManager().callEvent(event); ++ ++ itemstack = CraftItemStack.asNMSCopy(event.getCursor()); ++ ++ switch (event.getResult()) { ++ case ALLOW: ++ // Plugin cleared the id / stacksize checks ++ flag2 = true; ++ break; ++ case DEFAULT: ++ break; ++ case DENY: ++ // Reset the slot ++ if (packet.getSlotNum() >= 0) { ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(this.player.inventoryMenu.containerId, this.player.inventoryMenu.incrementStateId(), packet.getSlotNum(), this.player.inventoryMenu.getSlot(packet.getSlotNum()).getItem())); ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(-1, this.player.inventoryMenu.incrementStateId(), -1, ItemStack.EMPTY)); ++ } ++ return; ++ } ++ } ++ // CraftBukkit end ++ + if (flag1 && flag2) { + this.player.inventoryMenu.getSlot(serverboundsetcreativemodeslotpacket.getSlotNum()).setByPlayer(itemstack); + this.player.inventoryMenu.broadcastChanges(); +@@ -1827,7 +2810,8 @@ + }, this.server); + } + +- private void updateSignText(ServerboundSignUpdatePacket serverboundsignupdatepacket, List list) { ++ private void updateSignText(ServerboundSignUpdatePacket packet, List filteredText) { ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.resetLastActionTime(); + ServerLevel serverlevel = this.player.serverLevel(); + BlockPos blockpos = serverboundsignupdatepacket.getPos(); +@@ -1847,10 +2831,19 @@ + } + + @Override +- @Override +- public void handlePlayerAbilities(ServerboundPlayerAbilitiesPacket serverboundplayerabilitiespacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundplayerabilitiespacket, this, this.player.serverLevel()); +- this.player.getAbilities().flying = serverboundplayerabilitiespacket.isFlying() && this.player.getAbilities().mayfly; ++ public void handlePlayerAbilities(ServerboundPlayerAbilitiesPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ // CraftBukkit start ++ if (this.player.getAbilities().mayfly && this.player.getAbilities().flying != packet.isFlying()) { ++ PlayerToggleFlightEvent event = new PlayerToggleFlightEvent(this.player.getBukkitEntity(), packet.isFlying()); ++ this.cserver.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ this.player.getAbilities().flying = packet.isFlying(); // Actually set the player's flying status ++ } else { ++ this.player.onUpdateAbilities(); // Tell the player their ability was reverted ++ } ++ } ++ // CraftBukkit end + } + + @Override +@@ -1914,7 +2902,7 @@ + if (!this.waitingForSwitchToConfig) { + throw new IllegalStateException("Client acknowledged config, but none was requested"); + } else { +- this.connection.setListener(new ServerConfigurationPacketListenerImpl(this.server, this.connection, this.createCookie(this.player.clientInformation()))); ++ this.connection.setListener(new ServerConfigurationPacketListenerImpl(this.server, this.connection, this.createCookie(this.player.clientInformation()), this.player)); // CraftBukkit + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java.patch new file mode 100644 index 0000000000..d65ceccd51 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java.patch @@ -0,0 +1,78 @@ +--- a/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +@@ -11,8 +11,17 @@ + import net.minecraft.network.protocol.status.ServerStatus; + import net.minecraft.server.MinecraftServer; + ++// CraftBukkit start ++import java.net.InetAddress; ++import java.util.HashMap; ++// CraftBukkit end ++ + public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketListener { + ++ // CraftBukkit start - add fields ++ private static final HashMap throttleTracker = new HashMap(); ++ private static int throttleCounter = 0; ++ // CraftBukkit end + private static final Component IGNORE_STATUS_REASON = Component.translatable("disconnect.ignoring_status_request"); + private final MinecraftServer server; + private final Connection connection; +@@ -23,16 +32,50 @@ + } + + @Override +- @Override +- public void handleIntention(ClientIntentionPacket clientintentionpacket) { +- switch (clientintentionpacket.intention()) { ++ public void handleIntention(ClientIntentionPacket packet) { ++ this.connection.hostname = packet.hostName() + ":" + packet.port(); // CraftBukkit - set hostname ++ switch (packet.intention()) { + case LOGIN: + this.connection.setClientboundProtocolAfterHandshake(ClientIntent.LOGIN); +- if (clientintentionpacket.protocolVersion() != SharedConstants.getCurrentVersion().getProtocolVersion()) { +- MutableComponent mutablecomponent; ++ // CraftBukkit start - Connection throttle ++ try { ++ long currentTime = System.currentTimeMillis(); ++ long connectionThrottle = this.server.server.getConnectionThrottle(); ++ InetAddress address = ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getAddress(); + +- if (clientintentionpacket.protocolVersion() < 754) { +- mutablecomponent = Component.translatable("multiplayer.disconnect.outdated_client", SharedConstants.getCurrentVersion().getName()); ++ synchronized (throttleTracker) { ++ if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { ++ throttleTracker.put(address, currentTime); ++ MutableComponent chatmessage = Component.literal("Connection throttled! Please wait before reconnecting."); ++ this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); ++ this.connection.disconnect(chatmessage); ++ return; ++ } ++ ++ throttleTracker.put(address, currentTime); ++ throttleCounter++; ++ if (throttleCounter > 200) { ++ throttleCounter = 0; ++ ++ // Cleanup stale entries ++ java.util.Iterator iter = throttleTracker.entrySet().iterator(); ++ while (iter.hasNext()) { ++ java.util.Map.Entry entry = (java.util.Map.Entry) iter.next(); ++ if (entry.getValue() > connectionThrottle) { ++ iter.remove(); ++ } ++ } ++ } ++ } ++ } catch (Throwable t) { ++ org.apache.logging.log4j.LogManager.getLogger().debug("Failed to check connection throttle", t); ++ } ++ // CraftBukkit end ++ if (packet.protocolVersion() != SharedConstants.getCurrentVersion().getProtocolVersion()) { ++ MutableComponent ichatmutablecomponent; ++ ++ if (packet.protocolVersion() < 754) { ++ ichatmutablecomponent = Component.translatable("multiplayer.disconnect.outdated_client", SharedConstants.getCurrentVersion().getName()); + } else { + mutablecomponent = Component.translatable("multiplayer.disconnect.incompatible", SharedConstants.getCurrentVersion().getName()); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerLoginPacketListenerImpl.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerLoginPacketListenerImpl.java.patch new file mode 100644 index 0000000000..3a317236ad --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerLoginPacketListenerImpl.java.patch @@ -0,0 +1,125 @@ +--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -39,6 +40,10 @@ + import net.minecraft.world.entity.player.Player; + import org.apache.commons.lang3.Validate; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.bukkit.event.player.AsyncPlayerPreLoginEvent; ++import org.bukkit.event.player.PlayerPreLoginEvent; ++// CraftBukkit end + + public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, TickablePacketListener { + +@@ -56,6 +61,7 @@ + @Nullable + private GameProfile authenticatedProfile; + private final String serverId; ++ private ServerPlayer player; // CraftBukkit + + public ServerLoginPacketListenerImpl(MinecraftServer minecraftserver, Connection connection) { + this.state = ServerLoginPacketListenerImpl.State.HELLO; +@@ -82,6 +87,13 @@ + + } + ++ // CraftBukkit start ++ @Deprecated ++ public void disconnect(String s) { ++ disconnect(Component.literal(s)); ++ } ++ // CraftBukkit end ++ + @Override + @Override + public boolean isAcceptingMessages() { +@@ -143,10 +152,12 @@ + + private void verifyLoginAndFinishConnectionSetup(GameProfile gameprofile) { + PlayerList playerlist = this.server.getPlayerList(); +- Component component = playerlist.canPlayerLogin(this.connection.getRemoteAddress(), gameprofile); ++ // CraftBukkit start - fire PlayerLoginEvent ++ this.player = playerlist.canPlayerLogin(this, gameprofile); // CraftBukkit + +- if (component != null) { +- this.disconnect(component); ++ if (this.player == null) { ++ // this.disconnect(ichatbasecomponent); ++ // CraftBukkit end + } else { + if (this.server.getCompressionThreshold() >= 0 && !this.connection.isMemoryConnection()) { + this.connection.send(new ClientboundLoginCompressionPacket(this.server.getCompressionThreshold()), PacketSendListener.thenRun(() -> { +@@ -154,7 +165,7 @@ + })); + } + +- boolean flag = playerlist.disconnectAllPlayersWithProfile(gameprofile); ++ boolean flag = playerlist.disconnectAllPlayersWithProfile(gameprofile, this.player); // CraftBukkit - add player reference + + if (flag) { + this.state = ServerLoginPacketListenerImpl.State.WAITING_FOR_DUPE_DISCONNECT; +@@ -206,6 +215,43 @@ + if (profileresult != null) { + GameProfile gameprofile = profileresult.profile(); + ++ // CraftBukkit start - fire PlayerPreLoginEvent ++ if (!connection.isConnected()) { ++ return; ++ } ++ ++ String playerName = gameprofile.getName(); ++ java.net.InetAddress address = ((java.net.InetSocketAddress) connection.getRemoteAddress()).getAddress(); ++ java.util.UUID uniqueId = gameprofile.getId(); ++ final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server; ++ ++ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId); ++ server.getPluginManager().callEvent(asyncEvent); ++ ++ if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { ++ final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); ++ if (asyncEvent.getResult() != PlayerPreLoginEvent.Result.ALLOWED) { ++ event.disallow(asyncEvent.getResult(), asyncEvent.getKickMessage()); ++ } ++ Waitable waitable = new Waitable() { ++ @Override ++ protected PlayerPreLoginEvent.Result evaluate() { ++ server.getPluginManager().callEvent(event); ++ return event.getResult(); ++ }}; ++ ++ ServerLoginPacketListenerImpl.this.server.processQueue.add(waitable); ++ if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) { ++ disconnect(event.getKickMessage()); ++ return; ++ } ++ } else { ++ if (asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { ++ disconnect(asyncEvent.getKickMessage()); ++ return; ++ } ++ } ++ // CraftBukkit end + ServerLoginPacketListenerImpl.LOGGER.info("UUID of player {} is {}", gameprofile.getName(), gameprofile.getId()); + ServerLoginPacketListenerImpl.this.startClientVerification(gameprofile); + } else if (ServerLoginPacketListenerImpl.this.server.isSingleplayer()) { +@@ -223,6 +269,11 @@ + ServerLoginPacketListenerImpl.this.disconnect(Component.translatable("multiplayer.disconnect.authservers_down")); + ServerLoginPacketListenerImpl.LOGGER.error("Couldn't verify username because servers are unavailable"); + } ++ // CraftBukkit start - catch all exceptions ++ } catch (Exception exception) { ++ disconnect("Failed to verify username!"); ++ server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + s1, exception); ++ // CraftBukkit end + } + + } +@@ -250,7 +299,7 @@ + public void handleLoginAcknowledgement(ServerboundLoginAcknowledgedPacket serverboundloginacknowledgedpacket) { + Validate.validState(this.state == ServerLoginPacketListenerImpl.State.PROTOCOL_SWITCHING, "Unexpected login acknowledgement packet", new Object[0]); + CommonListenerCookie commonlistenercookie = CommonListenerCookie.createInitial((GameProfile) Objects.requireNonNull(this.authenticatedProfile)); +- ServerConfigurationPacketListenerImpl serverconfigurationpacketlistenerimpl = new ServerConfigurationPacketListenerImpl(this.server, this.connection, commonlistenercookie); ++ ServerConfigurationPacketListenerImpl serverconfigurationpacketlistenerimpl = new ServerConfigurationPacketListenerImpl(this.server, this.connection, commonlistenercookie, this.player); // CraftBukkit + + this.connection.setListener(serverconfigurationpacketlistenerimpl); + serverconfigurationpacketlistenerimpl.startConfiguration(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerStatusPacketListenerImpl.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerStatusPacketListenerImpl.java.patch new file mode 100644 index 0000000000..921c4d81ca --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/network/ServerStatusPacketListenerImpl.java.patch @@ -0,0 +1,131 @@ +--- a/net/minecraft/server/network/ServerStatusPacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerStatusPacketListenerImpl.java +@@ -1,5 +1,12 @@ + package net.minecraft.server.network; + ++// CraftBukkit start ++import com.mojang.authlib.GameProfile; ++import java.net.InetSocketAddress; ++import java.util.Collections; ++import java.util.Iterator; ++import java.util.Optional; ++import net.minecraft.SharedConstants; + import net.minecraft.network.Connection; + import net.minecraft.network.chat.Component; + import net.minecraft.network.protocol.status.ClientboundPongResponsePacket; +@@ -8,6 +15,12 @@ + import net.minecraft.network.protocol.status.ServerStatusPacketListener; + import net.minecraft.network.protocol.status.ServerboundPingRequestPacket; + import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerPlayer; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.craftbukkit.util.CraftIconCache; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class ServerStatusPacketListenerImpl implements ServerStatusPacketListener { + +@@ -38,7 +48,101 @@ + this.connection.disconnect(ServerStatusPacketListenerImpl.DISCONNECT_REASON); + } else { + this.hasRequestedStatus = true; +- this.connection.send(new ClientboundStatusResponsePacket(this.status)); ++ // CraftBukkit start ++ // this.connection.send(new PacketStatusOutServerInfo(this.status)); ++ MinecraftServer server = MinecraftServer.getServer(); ++ final Object[] players = server.getPlayerList().players.toArray(); ++ class ServerListPingEvent extends org.bukkit.event.server.ServerListPingEvent { ++ ++ CraftIconCache icon = server.server.getServerIcon(); ++ ++ ServerListPingEvent() { ++ super(connection.hostname, ((InetSocketAddress) connection.getRemoteAddress()).getAddress(), server.getMotd(), server.getPlayerList().getMaxPlayers()); ++ } ++ ++ @Override ++ public void setServerIcon(org.bukkit.util.CachedServerIcon icon) { ++ if (!(icon instanceof CraftIconCache)) { ++ throw new IllegalArgumentException(icon + " was not created by " + org.bukkit.craftbukkit.CraftServer.class); ++ } ++ this.icon = (CraftIconCache) icon; ++ } ++ ++ @Override ++ public Iterator iterator() throws UnsupportedOperationException { ++ return new Iterator() { ++ int i; ++ int ret = Integer.MIN_VALUE; ++ ServerPlayer player; ++ ++ @Override ++ public boolean hasNext() { ++ if (player != null) { ++ return true; ++ } ++ final Object[] currentPlayers = players; ++ for (int length = currentPlayers.length, i = this.i; i < length; i++) { ++ final ServerPlayer player = (ServerPlayer) currentPlayers[i]; ++ if (player != null) { ++ this.i = i + 1; ++ this.player = player; ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ @Override ++ public Player next() { ++ if (!hasNext()) { ++ throw new java.util.NoSuchElementException(); ++ } ++ final ServerPlayer player = this.player; ++ this.player = null; ++ this.ret = this.i - 1; ++ return player.getBukkitEntity(); ++ } ++ ++ @Override ++ public void remove() { ++ final Object[] currentPlayers = players; ++ final int i = this.ret; ++ if (i < 0 || currentPlayers[i] == null) { ++ throw new IllegalStateException(); ++ } ++ currentPlayers[i] = null; ++ } ++ }; ++ } ++ } ++ ++ ServerListPingEvent event = new ServerListPingEvent(); ++ server.server.getPluginManager().callEvent(event); ++ ++ java.util.List profiles = new java.util.ArrayList(players.length); ++ for (Object player : players) { ++ if (player != null) { ++ ServerPlayer entityPlayer = ((ServerPlayer) player); ++ if (entityPlayer.allowsListing()) { ++ profiles.add(entityPlayer.getGameProfile()); ++ } else { ++ profiles.add(MinecraftServer.ANONYMOUS_PLAYER_PROFILE); ++ } ++ } ++ } ++ ++ ServerStatus.ServerPingPlayerSample playerSample = new ServerStatus.ServerPingPlayerSample(event.getMaxPlayers(), profiles.size(), (server.hidesOnlinePlayers()) ? Collections.emptyList() : profiles); ++ ++ ServerStatus ping = new ServerStatus( ++ CraftChatMessage.fromString(event.getMotd(), true)[0], ++ Optional.of(playerSample), ++ Optional.of(new ServerStatus.Version(server.getServerModName() + " " + server.getServerVersion(), SharedConstants.getCurrentVersion().getProtocolVersion())), ++ (event.icon.value != null) ? Optional.of(new ServerStatus.a(event.icon.value)) : Optional.empty(), ++ server.enforceSecureProfile() ++ ); ++ ++ this.connection.send(new ClientboundStatusResponsePacket(ping)); ++ // CraftBukkit end + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/BanListEntry.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/BanListEntry.java.patch new file mode 100644 index 0000000000..68f43cd7f0 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/BanListEntry.java.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/server/players/BanListEntry.java ++++ b/net/minecraft/server/players/BanListEntry.java +@@ -26,8 +26,8 @@ + this.reason = s1 == null ? "Banned by an operator." : s1; + } + +- protected BanListEntry(@Nullable T t0, JsonObject jsonobject) { +- super(t0); ++ protected BanListEntry(@Nullable T user, JsonObject entryData) { ++ super(checkExpiry(user, entryData)); // CraftBukkit + + Date date; + +@@ -85,4 +83,22 @@ + jsonobject.addProperty("expires", this.expires == null ? "forever" : BanListEntry.DATE_FORMAT.format(this.expires)); + jsonobject.addProperty("reason", this.reason); + } ++ ++ // CraftBukkit start ++ private static T checkExpiry(T object, JsonObject jsonobject) { ++ Date expires = null; ++ ++ try { ++ expires = jsonobject.has("expires") ? DATE_FORMAT.parse(jsonobject.get("expires").getAsString()) : null; ++ } catch (ParseException ex) { ++ // Guess we don't have a date ++ } ++ ++ if (expires == null || expires.after(new Date())) { ++ return object; ++ } else { ++ return null; ++ } ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/GameProfileCache.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/GameProfileCache.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/GameProfileCache.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/OldUsersConverter.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/OldUsersConverter.java.patch new file mode 100644 index 0000000000..b4efbb4805 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/OldUsersConverter.java.patch @@ -0,0 +1,71 @@ +--- a/net/minecraft/server/players/OldUsersConverter.java ++++ b/net/minecraft/server/players/OldUsersConverter.java +@@ -85,7 +88,7 @@ + try { + userbanlist.load(); + } catch (IOException ioexception) { +- OldUsersConverter.LOGGER.warn("Could not load existing file {}", userbanlist.getFile().getName(), ioexception); ++ OldUsersConverter.LOGGER.warn("Could not load existing file {}", gameprofilebanlist.getFile().getName()); // CraftBukkit - don't print stacktrace + } + } + +@@ -145,7 +146,7 @@ + try { + ipbanlist.load(); + } catch (IOException ioexception) { +- OldUsersConverter.LOGGER.warn("Could not load existing file {}", ipbanlist.getFile().getName(), ioexception); ++ OldUsersConverter.LOGGER.warn("Could not load existing file {}", ipbanlist.getFile().getName()); // CraftBukkit - don't print stacktrace + } + } + +@@ -186,7 +187,7 @@ + try { + serveroplist.load(); + } catch (IOException ioexception) { +- OldUsersConverter.LOGGER.warn("Could not load existing file {}", serveroplist.getFile().getName(), ioexception); ++ OldUsersConverter.LOGGER.warn("Could not load existing file {}", oplist.getFile().getName()); // CraftBukkit - don't print stacktrace + } + } + +@@ -232,7 +231,7 @@ + try { + userwhitelist.load(); + } catch (IOException ioexception) { +- OldUsersConverter.LOGGER.warn("Could not load existing file {}", userwhitelist.getFile().getName(), ioexception); ++ OldUsersConverter.LOGGER.warn("Could not load existing file {}", whitelist.getFile().getName()); // CraftBukkit - don't print stacktrace + } + } + +@@ -357,7 +350,31 @@ + File file5 = new File(file, s2 + ".dat"); + File file6 = new File(file4, s3 + ".dat"); + +- OldUsersConverter.ensureDirectoryExists(file4); ++ // CraftBukkit start - Use old file name to seed lastKnownName ++ CompoundTag root = null; ++ ++ try { ++ root = NbtIo.readCompressed(new java.io.FileInputStream(file5), NbtAccounter.unlimitedHeap()); ++ } catch (Exception exception) { ++ exception.printStackTrace(); ++ } ++ ++ if (root != null) { ++ if (!root.contains("bukkit")) { ++ root.put("bukkit", new CompoundTag()); ++ } ++ CompoundTag data = root.getCompound("bukkit"); ++ data.putString("lastKnownName", oldFileName); ++ ++ try { ++ NbtIo.writeCompressed(root, new java.io.FileOutputStream(file2)); ++ } catch (Exception exception) { ++ exception.printStackTrace(); ++ } ++ } ++ // CraftBukkit end ++ ++ OldUsersConverter.ensureDirectoryExists(file); + if (!file5.renameTo(file6)) { + throw new OldUsersConverter.ConversionError("Could not convert file for " + s2); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/PlayerList.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/PlayerList.java.patch new file mode 100644 index 0000000000..a902891a3c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/PlayerList.java.patch @@ -0,0 +1,856 @@ +--- a/net/minecraft/server/players/PlayerList.java ++++ b/net/minecraft/server/players/PlayerList.java +@@ -101,6 +101,25 @@ + import net.minecraft.world.scores.PlayerTeam; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.stream.Collectors; ++import net.minecraft.server.dedicated.DedicatedServer; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerChangedWorldEvent; ++import org.bukkit.event.player.PlayerJoinEvent; ++import org.bukkit.event.player.PlayerLoginEvent; ++import org.bukkit.event.player.PlayerQuitEvent; ++import org.bukkit.event.player.PlayerRespawnEvent; ++import org.bukkit.event.player.PlayerRespawnEvent.RespawnReason; ++import org.bukkit.event.player.PlayerSpawnChangeEvent; ++// CraftBukkit end ++ + public abstract class PlayerList { + + public static final File USERBANLIST_FILE = new File("banned-players.json"); +@@ -113,15 +132,17 @@ + private static final int SEND_PLAYER_INFO_INTERVAL = 600; + private static final SimpleDateFormat BAN_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z"); + private final MinecraftServer server; +- private final List players = Lists.newArrayList(); ++ public final List players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety + private final Map playersByUUID = Maps.newHashMap(); + private final UserBanList bans; + private final IpBanList ipBans; + private final ServerOpList ops; + private final UserWhiteList whitelist; +- private final Map stats; +- private final Map advancements; +- private final PlayerDataStorage playerIo; ++ // CraftBukkit start ++ // private final Map stats; ++ // private final Map advancements; ++ // CraftBukkit end ++ public final PlayerDataStorage playerIo; + private boolean doWhiteList; + private final LayeredRegistryAccess registries; + protected final int maxPlayers; +@@ -131,17 +152,27 @@ + private static final boolean ALLOW_LOGOUTIVATOR = false; + private int sendAllPlayerInfoIn; + +- public PlayerList(MinecraftServer minecraftserver, LayeredRegistryAccess layeredregistryaccess, PlayerDataStorage playerdatastorage, int i) { ++ // CraftBukkit start ++ private CraftServer cserver; ++ ++ public PlayerList(MinecraftServer server, LayeredRegistryAccess registries, PlayerDataStorage playerIo, int maxPlayers) { ++ this.cserver = server.server = new CraftServer((DedicatedServer) server, this); ++ server.console = org.bukkit.craftbukkit.command.ColouredConsoleSender.getInstance(); ++ server.reader.addCompleter(new org.bukkit.craftbukkit.command.ConsoleCommandCompleter(server.server)); ++ // CraftBukkit end ++ + this.bans = new UserBanList(PlayerList.USERBANLIST_FILE); + this.ipBans = new IpBanList(PlayerList.IPBANLIST_FILE); + this.ops = new ServerOpList(PlayerList.OPLIST_FILE); + this.whitelist = new UserWhiteList(PlayerList.WHITELIST_FILE); +- this.stats = Maps.newHashMap(); +- this.advancements = Maps.newHashMap(); +- this.server = minecraftserver; +- this.registries = layeredregistryaccess; +- this.maxPlayers = i; +- this.playerIo = playerdatastorage; ++ // CraftBukkit start ++ // this.stats = Maps.newHashMap(); ++ // this.advancements = Maps.newHashMap(); ++ // CraftBukkit end ++ this.server = server; ++ this.registries = registries; ++ this.maxPlayers = maxPlayers; ++ this.playerIo = playerIo; + } + + public void placeNewPlayer(Connection connection, ServerPlayer serverplayer, CommonListenerCookie commonlistenercookie) { +@@ -160,15 +191,21 @@ + + CompoundTag compoundtag = this.load(serverplayer); + ResourceKey resourcekey; ++ // CraftBukkit start - Better rename detection ++ if (nbttagcompound != null && nbttagcompound.contains("bukkit")) { ++ CompoundTag bukkit = nbttagcompound.getCompound("bukkit"); ++ s = bukkit.contains("lastKnownName", 8) ? bukkit.getString("lastKnownName") : s; ++ } ++ // CraftBukkit end + + if (compoundtag != null) { + DataResult dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, compoundtag.get("Dimension"))); + Logger logger = PlayerList.LOGGER; + + Objects.requireNonNull(logger); +- resourcekey = (ResourceKey) dataresult.resultOrPartial(logger::error).orElse(Level.OVERWORLD); ++ resourcekey = (ResourceKey) dataresult.resultOrPartial(logger::error).orElse(entityplayer.serverLevel().dimension()); // CraftBukkit - SPIGOT-7507: If no dimension, fall back to existing dimension loaded from "WorldUUID", which in turn defaults to World.OVERWORLD + } else { +- resourcekey = Level.OVERWORLD; ++ resourcekey = entityplayer.serverLevel().dimension(); // CraftBukkit - SPIGOT-7507: If no dimension, fall back to existing dimension loaded from "WorldUUID", which in turn defaults to World.OVERWORLD + } + + ResourceKey resourcekey1 = resourcekey; +@@ -185,8 +222,9 @@ + serverplayer.setServerLevel(serverlevel1); + String s1 = connection.getLoggableAddress(this.server.logIPs()); + +- PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ({}, {}, {})", new Object[]{serverplayer.getName().getString(), s1, serverplayer.getId(), serverplayer.getX(), serverplayer.getY(), serverplayer.getZ()}); +- LevelData leveldata = serverlevel1.getLevelData(); ++ // CraftBukkit - Moved message to after join ++ // PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ({}, {}, {})", new Object[]{entityplayer.getName().getString(), s1, entityplayer.getId(), entityplayer.getX(), entityplayer.getY(), entityplayer.getZ()}); ++ LevelData worlddata = worldserver1.getLevelData(); + + serverplayer.loadGameTypes(compoundtag); + ServerGamePacketListenerImpl servergamepacketlistenerimpl = new ServerGamePacketListenerImpl(this.server, connection, serverplayer, commonlistenercookie); +@@ -195,15 +233,16 @@ + boolean flag1 = gamerules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO); + boolean flag2 = gamerules.getBoolean(GameRules.RULE_LIMITED_CRAFTING); + +- servergamepacketlistenerimpl.send(new ClientboundLoginPacket(serverplayer.getId(), leveldata.isHardcore(), this.server.levelKeys(), this.getMaxPlayers(), this.viewDistance, this.simulationDistance, flag1, !flag, flag2, serverplayer.createCommonSpawnInfo(serverlevel1))); +- servergamepacketlistenerimpl.send(new ClientboundChangeDifficultyPacket(leveldata.getDifficulty(), leveldata.isDifficultyLocked())); +- servergamepacketlistenerimpl.send(new ClientboundPlayerAbilitiesPacket(serverplayer.getAbilities())); +- servergamepacketlistenerimpl.send(new ClientboundSetCarriedItemPacket(serverplayer.getInventory().selected)); +- servergamepacketlistenerimpl.send(new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes())); +- this.sendPlayerPermissionLevel(serverplayer); +- serverplayer.getStats().markAllDirty(); +- serverplayer.getRecipeBook().sendInitialRecipeBook(serverplayer); +- this.updateEntireScoreboard(serverlevel1.getScoreboard(), serverplayer); ++ playerconnection.send(new ClientboundLoginPacket(entityplayer.getId(), worlddata.isHardcore(), this.server.levelKeys(), this.getMaxPlayers(), this.viewDistance, this.simulationDistance, flag1, !flag, flag2, entityplayer.createCommonSpawnInfo(worldserver1))); ++ entityplayer.getBukkitEntity().sendSupportedChannels(); // CraftBukkit ++ playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); ++ playerconnection.send(new ClientboundPlayerAbilitiesPacket(entityplayer.getAbilities())); ++ playerconnection.send(new ClientboundSetCarriedItemPacket(entityplayer.getInventory().selected)); ++ playerconnection.send(new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes())); ++ this.sendPlayerPermissionLevel(entityplayer); ++ entityplayer.getStats().markAllDirty(); ++ entityplayer.getRecipeBook().sendInitialRecipeBook(entityplayer); ++ this.updateEntireScoreboard(worldserver1.getScoreboard(), entityplayer); + this.server.invalidateStatus(); + MutableComponent mutablecomponent; + +@@ -212,6 +251,9 @@ + } else { + mutablecomponent = Component.translatable("multiplayer.player.joined.renamed", serverplayer.getDisplayName(), s); + } ++ // CraftBukkit start ++ ichatmutablecomponent.withStyle(ChatFormatting.YELLOW); ++ String joinMessage = CraftChatMessage.fromComponent(ichatmutablecomponent); + + this.broadcastSystemMessage(mutablecomponent.withStyle(ChatFormatting.YELLOW), false); + servergamepacketlistenerimpl.teleport(serverplayer.getX(), serverplayer.getY(), serverplayer.getZ(), serverplayer.getYRot(), serverplayer.getXRot()); +@@ -221,25 +262,79 @@ + serverplayer.sendServerStatus(serverstatus); + } + +- serverplayer.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); +- this.players.add(serverplayer); +- this.playersByUUID.put(serverplayer.getUUID(), serverplayer); +- this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(serverplayer))); +- this.sendLevelInfo(serverplayer, serverlevel1); +- serverlevel1.addNewPlayer(serverplayer); +- this.server.getCustomBossEvents().onPlayerConnect(serverplayer); +- Iterator iterator = serverplayer.getActiveEffects().iterator(); ++ // entityplayer.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below ++ this.players.add(entityplayer); ++ this.playersByUUID.put(entityplayer.getUUID(), entityplayer); ++ // this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer))); // CraftBukkit - replaced with loop below + ++ // CraftBukkit start ++ CraftPlayer bukkitPlayer = entityplayer.getBukkitEntity(); ++ ++ // Ensure that player inventory is populated with its viewer ++ entityplayer.containerMenu.transferTo(entityplayer.containerMenu, bukkitPlayer); ++ ++ PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(bukkitPlayer, joinMessage); ++ cserver.getPluginManager().callEvent(playerJoinEvent); ++ ++ if (!entityplayer.connection.isAcceptingMessages()) { ++ return; ++ } ++ ++ joinMessage = playerJoinEvent.getJoinMessage(); ++ ++ if (joinMessage != null && joinMessage.length() > 0) { ++ for (Component line : org.bukkit.craftbukkit.util.CraftChatMessage.fromString(joinMessage)) { ++ server.getPlayerList().broadcastSystemMessage(line, false); ++ } ++ } ++ // CraftBukkit end ++ ++ // CraftBukkit start - sendAll above replaced with this loop ++ ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer)); ++ ++ for (int i = 0; i < this.players.size(); ++i) { ++ ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i); ++ ++ if (entityplayer1.getBukkitEntity().canSee(bukkitPlayer)) { ++ entityplayer1.connection.send(packet); ++ } ++ ++ if (!bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { ++ continue; ++ } ++ ++ entityplayer.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer1))); ++ } ++ entityplayer.sentListPacket = true; ++ // CraftBukkit end ++ ++ entityplayer.getEntityData().refresh(entityplayer); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn ++ ++ this.sendLevelInfo(entityplayer, worldserver1); ++ ++ // CraftBukkit start - Only add if the player wasn't moved in the event ++ if (entityplayer.level() == worldserver1 && !worldserver1.players().contains(entityplayer)) { ++ worldserver1.addNewPlayer(entityplayer); ++ this.server.getCustomBossEvents().onPlayerConnect(entityplayer); ++ } ++ ++ worldserver1 = entityplayer.serverLevel(); // CraftBukkit - Update in case join event changed it ++ // CraftBukkit end ++ Iterator iterator = entityplayer.getActiveEffects().iterator(); ++ + while (iterator.hasNext()) { + MobEffectInstance mobeffectinstance = (MobEffectInstance) iterator.next(); + + servergamepacketlistenerimpl.send(new ClientboundUpdateMobEffectPacket(serverplayer.getId(), mobeffectinstance)); + } + +- if (compoundtag != null && compoundtag.contains("RootVehicle", 10)) { +- CompoundTag compoundtag1 = compoundtag.getCompound("RootVehicle"); +- Entity entity = EntityType.loadEntityRecursive(compoundtag1.getCompound("Entity"), serverlevel1, (entity1) -> { +- return !serverlevel1.addWithUUID(entity1) ? null : entity1; ++ if (nbttagcompound != null && nbttagcompound.contains("RootVehicle", 10)) { ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("RootVehicle"); ++ // CraftBukkit start ++ ServerLevel finalWorldServer = worldserver1; ++ Entity entity = EntityType.loadEntityRecursive(nbttagcompound1.getCompound("Entity"), finalWorldServer, (entity1) -> { ++ return !finalWorldServer.addWithUUID(entity1) ? null : entity1; ++ // CraftBukkit end + }); + + if (entity != null) { +@@ -281,7 +376,9 @@ + } + } + +- serverplayer.initInventoryMenu(); ++ entityplayer.initInventoryMenu(); ++ // CraftBukkit - Moved from above, added world ++ PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", entityplayer.getName().getString(), s1, entityplayer.getId(), worldserver1.serverLevelData.getLevelName(), entityplayer.getX(), entityplayer.getY(), entityplayer.getZ()); + } + + protected void updateEntireScoreboard(ServerScoreboard serverscoreboard, ServerPlayer serverplayer) { +@@ -317,36 +414,32 @@ + + } + +- public void addWorldborderListener(ServerLevel serverlevel) { +- serverlevel.getWorldBorder().addListener(new BorderChangeListener() { ++ public void addWorldborderListener(ServerLevel level) { ++ if (playerIo != null) return; // CraftBukkit ++ level.getWorldBorder().addListener(new BorderChangeListener() { + @Override +- @Override +- public void onBorderSizeSet(WorldBorder worldborder, double d0) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderSizePacket(worldborder)); ++ public void onBorderSizeSet(WorldBorder border, double size) { ++ PlayerList.this.broadcastAll(new ClientboundSetBorderSizePacket(border), border.world); // CraftBukkit + } + + @Override +- @Override +- public void onBorderSizeLerping(WorldBorder worldborder, double d0, double d1, long i) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderLerpSizePacket(worldborder)); ++ public void onBorderSizeLerping(WorldBorder border, double oldSize, double d1, long newSize) { ++ PlayerList.this.broadcastAll(new ClientboundSetBorderLerpSizePacket(border), border.world); // CraftBukkit + } + + @Override +- @Override +- public void onBorderCenterSet(WorldBorder worldborder, double d0, double d1) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderCenterPacket(worldborder)); ++ public void onBorderCenterSet(WorldBorder border, double x, double d1) { ++ PlayerList.this.broadcastAll(new ClientboundSetBorderCenterPacket(border), border.world); // CraftBukkit + } + + @Override +- @Override +- public void onBorderSetWarningTime(WorldBorder worldborder, int i) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDelayPacket(worldborder)); ++ public void onBorderSetWarningTime(WorldBorder border, int warningTime) { ++ PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDelayPacket(border), border.world); // CraftBukkit + } + + @Override +- @Override +- public void onBorderSetWarningBlocks(WorldBorder worldborder, int i) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDistancePacket(worldborder)); ++ public void onBorderSetWarningBlocks(WorldBorder border, int warningBlocks) { ++ PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDistancePacket(border), border.world); // CraftBukkit + } + + @Override +@@ -375,15 +466,16 @@ + return compoundtag1; + } + +- protected void save(ServerPlayer serverplayer) { +- this.playerIo.save(serverplayer); +- ServerStatsCounter serverstatscounter = (ServerStatsCounter) this.stats.get(serverplayer.getUUID()); ++ protected void save(ServerPlayer player) { ++ if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit ++ this.playerIo.save(player); ++ ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit + + if (serverstatscounter != null) { + serverstatscounter.save(); + } + +- PlayerAdvancements playeradvancements = (PlayerAdvancements) this.advancements.get(serverplayer.getUUID()); ++ PlayerAdvancements advancementdataplayer = (PlayerAdvancements) player.getAdvancements(); // CraftBukkit + + if (playeradvancements != null) { + playeradvancements.save(); +@@ -391,14 +483,31 @@ + + } + +- public void remove(ServerPlayer serverplayer) { +- ServerLevel serverlevel = serverplayer.serverLevel(); ++ public String remove(ServerPlayer entityplayer) { // CraftBukkit - return string ++ ServerLevel worldserver = entityplayer.serverLevel(); + + serverplayer.awardStat(Stats.LEAVE_GAME); + this.save(serverplayer); + if (serverplayer.isPassenger()) { + Entity entity = serverplayer.getRootVehicle(); + ++ // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it ++ // See SPIGOT-5799, SPIGOT-6145 ++ if (entityplayer.containerMenu != entityplayer.inventoryMenu) { ++ entityplayer.closeContainer(); ++ } ++ ++ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(entityplayer.getBukkitEntity(), entityplayer.kickLeaveMessage != null ? entityplayer.kickLeaveMessage : "\u00A7e" + entityplayer.getScoreboardName() + " left the game"); ++ cserver.getPluginManager().callEvent(playerQuitEvent); ++ entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); ++ ++ entityplayer.doTick(); // SPIGOT-924 ++ // CraftBukkit end ++ ++ this.save(entityplayer); ++ if (entityplayer.isPassenger()) { ++ Entity entity = entityplayer.getRootVehicle(); ++ + if (entity.hasExactlyOnePlayerPassenger()) { + PlayerList.LOGGER.debug("Removing player mount"); + serverplayer.stopRiding(); +@@ -418,16 +524,34 @@ + + if (serverplayer1 == serverplayer) { + this.playersByUUID.remove(uuid); +- this.stats.remove(uuid); +- this.advancements.remove(uuid); ++ // CraftBukkit start ++ // this.stats.remove(uuid); ++ // this.advancements.remove(uuid); ++ // CraftBukkit end + } + +- this.broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(serverplayer.getUUID()))); ++ // CraftBukkit start ++ // this.broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID()))); ++ ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID())); ++ for (int i = 0; i < players.size(); i++) { ++ ServerPlayer entityplayer2 = (ServerPlayer) this.players.get(i); ++ ++ if (entityplayer2.getBukkitEntity().canSee(entityplayer.getBukkitEntity())) { ++ entityplayer2.connection.send(packet); ++ } else { ++ entityplayer2.getBukkitEntity().onEntityRemove(entityplayer); ++ } ++ } ++ // This removes the scoreboard (and player reference) for the specific player in the manager ++ cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); ++ // CraftBukkit end ++ ++ return playerQuitEvent.getQuitMessage(); // CraftBukkit + } + +- @Nullable +- public Component canPlayerLogin(SocketAddress socketaddress, GameProfile gameprofile) { +- MutableComponent mutablecomponent; ++ // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer ++ public ServerPlayer canPlayerLogin(ServerLoginPacketListenerImpl loginlistener, GameProfile gameprofile) { ++ MutableComponent ichatmutablecomponent; + + if (this.bans.isBanned(gameprofile)) { + UserBanListEntry userbanlistentry = (UserBanListEntry) this.bans.get(gameprofile); +@@ -437,7 +566,33 @@ + mutablecomponent.append((Component) Component.translatable("multiplayer.disconnect.banned.expiration", PlayerList.BAN_DATE_FORMAT.format(userbanlistentry.getExpires()))); + } + +- return mutablecomponent; ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ entityplayer = (ServerPlayer) iterator.next(); ++ save(entityplayer); // CraftBukkit - Force the player's inventory to be saved ++ entityplayer.connection.disconnect(Component.translatable("multiplayer.disconnect.duplicate_login")); ++ } ++ ++ // Instead of kicking then returning, we need to store the kick reason ++ // in the event, check with plugins to see if it's ok, and THEN kick ++ // depending on the outcome. ++ SocketAddress socketaddress = loginlistener.connection.getRemoteAddress(); ++ ++ ServerPlayer entity = new ServerPlayer(this.server, this.server.getLevel(Level.OVERWORLD), gameprofile, ClientInformation.createDefault()); ++ Player player = entity.getBukkitEntity(); ++ PlayerLoginEvent event = new PlayerLoginEvent(player, loginlistener.connection.hostname, ((java.net.InetSocketAddress) socketaddress).getAddress()); ++ ++ if (getBans().isBanned(gameprofile) && !getBans().get(gameprofile).hasExpired()) { ++ UserBanListEntry gameprofilebanentry = (UserBanListEntry) this.bans.get(gameprofile); ++ ++ ichatmutablecomponent = Component.translatable("multiplayer.disconnect.banned.reason", gameprofilebanentry.getReason()); ++ if (gameprofilebanentry.getExpires() != null) { ++ ichatmutablecomponent.append((Component) Component.translatable("multiplayer.disconnect.banned.expiration", PlayerList.BAN_DATE_FORMAT.format(gameprofilebanentry.getExpires()))); ++ } ++ ++ // return chatmessage; ++ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(ichatmutablecomponent)); + } else if (!this.isWhiteListed(gameprofile)) { + return Component.translatable("multiplayer.disconnect.not_whitelisted"); + } else if (this.ipBans.isBanned(socketaddress)) { +@@ -454,11 +621,15 @@ + } + } + +- public ServerPlayer getPlayerForLogin(GameProfile gameprofile, ClientInformation clientinformation) { +- return new ServerPlayer(this.server, this.server.overworld(), gameprofile, clientinformation); ++ // CraftBukkit start - added EntityPlayer ++ public ServerPlayer getPlayerForLogin(GameProfile gameprofile, ClientInformation clientinformation, ServerPlayer player) { ++ player.updateOptions(clientinformation); ++ return player; ++ // CraftBukkit end + } + +- public boolean disconnectAllPlayersWithProfile(GameProfile gameprofile) { ++ public boolean disconnectAllPlayersWithProfile(GameProfile gameprofile, ServerPlayer player) { // CraftBukkit - added EntityPlayer ++ /* CraftBukkit startMoved up + UUID uuid = gameprofile.getId(); + Set set = Sets.newIdentityHashSet(); + Iterator iterator = this.players.iterator(); +@@ -486,15 +657,25 @@ + } + + return !set.isEmpty(); ++ */ ++ return player == null; ++ // CraftBukkit end + } + +- public ServerPlayer respawn(ServerPlayer serverplayer, boolean flag) { +- this.players.remove(serverplayer); +- serverplayer.serverLevel().removePlayerImmediately(serverplayer, Entity.RemovalReason.DISCARDED); +- BlockPos blockpos = serverplayer.getRespawnPosition(); +- float f = serverplayer.getRespawnAngle(); +- boolean flag1 = serverplayer.isRespawnForced(); +- ServerLevel serverlevel = this.server.getLevel(serverplayer.getRespawnDimension()); ++ // CraftBukkit start ++ public ServerPlayer respawn(ServerPlayer entityplayer, boolean flag, RespawnReason reason) { ++ return this.respawn(entityplayer, this.server.getLevel(entityplayer.getRespawnDimension()), flag, null, true, reason); ++ } ++ ++ public ServerPlayer respawn(ServerPlayer entityplayer, ServerLevel worldserver, boolean flag, Location location, boolean avoidSuffocation, RespawnReason reason) { ++ entityplayer.stopRiding(); // CraftBukkit ++ this.players.remove(entityplayer); ++ entityplayer.serverLevel().removePlayerImmediately(entityplayer, Entity.RemovalReason.DISCARDED); ++ BlockPos blockposition = entityplayer.getRespawnPosition(); ++ float f = entityplayer.getRespawnAngle(); ++ boolean flag1 = entityplayer.isRespawnForced(); ++ /* CraftBukkit start ++ WorldServer worldserver = this.server.getLevel(entityplayer.getRespawnDimension()); + Optional optional; + + if (serverlevel != null && blockpos != null) { +@@ -503,8 +684,13 @@ + optional = Optional.empty(); + } + +- ServerLevel serverlevel1 = serverlevel != null && optional.isPresent() ? serverlevel : this.server.overworld(); +- ServerPlayer serverplayer1 = new ServerPlayer(this.server, serverlevel1, serverplayer.getGameProfile(), serverplayer.clientInformation()); ++ WorldServer worldserver1 = worldserver != null && optional.isPresent() ? worldserver : this.server.overworld(); ++ EntityPlayer entityplayer1 = new EntityPlayer(this.server, worldserver1, entityplayer.getGameProfile(), entityplayer.clientInformation()); ++ // */ ++ ServerPlayer entityplayer1 = entityplayer; ++ org.bukkit.World fromWorld = entityplayer.getBukkitEntity().getWorld(); ++ entityplayer.wonGame = false; ++ // CraftBukkit end + + serverplayer1.connection = serverplayer.connection; + serverplayer1.restoreFrom(serverplayer, flag); +@@ -520,18 +706,40 @@ + + boolean flag2 = false; + +- if (optional.isPresent()) { +- BlockState blockstate = serverlevel1.getBlockState(blockpos); +- boolean flag3 = blockstate.is(Blocks.RESPAWN_ANCHOR); +- Vec3 vec3 = (Vec3) optional.get(); +- float f1; ++ // CraftBukkit start - fire PlayerRespawnEvent ++ if (location == null) { ++ boolean isBedSpawn = false; ++ ServerLevel worldserver1 = this.server.getLevel(entityplayer.getRespawnDimension()); ++ if (worldserver1 != null) { ++ Optional optional; + + if (!blockstate.is(BlockTags.BEDS) && !flag3) { + f1 = f; + } else { + Vec3 vec31 = Vec3.atBottomCenterOf(blockpos).subtract(vec3).normalize(); + +- f1 = (float) Mth.wrapDegrees(Mth.atan2(vec31.z, vec31.x) * 57.2957763671875D - 90.0D); ++ if (optional.isPresent()) { ++ IBlockData iblockdata = worldserver1.getBlockState(blockposition); ++ boolean flag3 = iblockdata.is(Blocks.RESPAWN_ANCHOR); ++ Vec3 vec3d = (Vec3) optional.get(); ++ float f1; ++ ++ if (!iblockdata.is(BlockTags.BEDS) && !flag3) { ++ f1 = f; ++ } else { ++ Vec3 vec3d1 = Vec3.atBottomCenterOf(blockposition).subtract(vec3d).normalize(); ++ ++ f1 = (float) Mth.wrapDegrees(Mth.atan2(vec3d1.z, vec3d1.x) * 57.2957763671875D - 90.0D); ++ } ++ ++ // entityplayer1.setRespawnPosition(worldserver1.dimension(), blockposition, f, flag1, false); // CraftBukkit - not required, just copies old location into reused entity ++ flag2 = !flag && flag3; ++ isBedSpawn = true; ++ location = CraftLocation.toBukkit(vec3d, worldserver1.getWorld(), f1, 0.0F); ++ } else if (blockposition != null) { ++ entityplayer1.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F)); ++ entityplayer1.setRespawnPosition(null, null, 0f, false, false, PlayerSpawnChangeEvent.Cause.RESET); // CraftBukkit - SPIGOT-5988: Clear respawn location when obstructed ++ } + } + + serverplayer1.moveTo(vec3.x, vec3.y, vec3.z, f1, 0.0F); +@@ -541,31 +764,48 @@ + serverplayer1.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F)); + } + +- while (!serverlevel1.noCollision((Entity) serverplayer1) && serverplayer1.getY() < (double) serverlevel1.getMaxBuildHeight()) { +- serverplayer1.setPos(serverplayer1.getX(), serverplayer1.getY() + 1.0D, serverplayer1.getZ()); ++ while (avoidSuffocation && !worldserver1.noCollision((Entity) entityplayer1) && entityplayer1.getY() < (double) worldserver1.getMaxBuildHeight()) { ++ // CraftBukkit end ++ entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); + } + + int i = flag ? 1 : 0; + ServerLevel serverlevel2 = serverplayer1.serverLevel(); + LevelData leveldata = serverlevel2.getLevelData(); + +- serverplayer1.connection.send(new ClientboundRespawnPacket(serverplayer1.createCommonSpawnInfo(serverlevel2), (byte) i)); +- serverplayer1.connection.teleport(serverplayer1.getX(), serverplayer1.getY(), serverplayer1.getZ(), serverplayer1.getYRot(), serverplayer1.getXRot()); +- serverplayer1.connection.send(new ClientboundSetDefaultSpawnPositionPacket(serverlevel1.getSharedSpawnPos(), serverlevel1.getSharedSpawnAngle())); +- serverplayer1.connection.send(new ClientboundChangeDifficultyPacket(leveldata.getDifficulty(), leveldata.isDifficultyLocked())); +- serverplayer1.connection.send(new ClientboundSetExperiencePacket(serverplayer1.experienceProgress, serverplayer1.totalExperience, serverplayer1.experienceLevel)); +- this.sendLevelInfo(serverplayer1, serverlevel1); +- this.sendPlayerPermissionLevel(serverplayer1); +- serverlevel1.addRespawnedPlayer(serverplayer1); +- this.players.add(serverplayer1); +- this.playersByUUID.put(serverplayer1.getUUID(), serverplayer1); +- serverplayer1.initInventoryMenu(); +- serverplayer1.setHealth(serverplayer1.getHealth()); ++ entityplayer1.connection.send(new ClientboundRespawnPacket(entityplayer1.createCommonSpawnInfo(worldserver2), (byte) i)); ++ entityplayer1.connection.teleport(CraftLocation.toBukkit(entityplayer1.position(), worldserver2.getWorld(), entityplayer1.getYRot(), entityplayer1.getXRot())); // CraftBukkit ++ entityplayer1.connection.send(new ClientboundSetDefaultSpawnPositionPacket(worldserver1.getSharedSpawnPos(), worldserver1.getSharedSpawnAngle())); ++ entityplayer1.connection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); ++ entityplayer1.connection.send(new ClientboundSetExperiencePacket(entityplayer1.experienceProgress, entityplayer1.totalExperience, entityplayer1.experienceLevel)); ++ this.sendLevelInfo(entityplayer1, worldserver1); ++ this.sendPlayerPermissionLevel(entityplayer1); ++ if (!entityplayer.connection.isDisconnected()) { ++ worldserver1.addRespawnedPlayer(entityplayer1); ++ this.players.add(entityplayer1); ++ this.playersByUUID.put(entityplayer1.getUUID(), entityplayer1); ++ } ++ // entityplayer1.initInventoryMenu(); ++ entityplayer1.setHealth(entityplayer1.getHealth()); + if (flag2) { + serverplayer1.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, (double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), 1.0F, 1.0F, serverlevel1.getRandom().nextLong())); + } + +- return serverplayer1; ++ // Fire advancement trigger ++ entityplayer.triggerDimensionChangeTriggers(((CraftWorld) fromWorld).getHandle()); ++ ++ // Don't fire on respawn ++ if (fromWorld != location.getWorld()) { ++ PlayerChangedWorldEvent event = new PlayerChangedWorldEvent(entityplayer.getBukkitEntity(), fromWorld); ++ server.server.getPluginManager().callEvent(event); ++ } ++ ++ // Save player file again if they were disconnected ++ if (entityplayer.connection.isDisconnected()) { ++ this.save(entityplayer); ++ } ++ // CraftBukkit end ++ return entityplayer1; + } + + public void sendPlayerPermissionLevel(ServerPlayer serverplayer) { +@@ -577,7 +823,18 @@ + + public void tick() { + if (++this.sendAllPlayerInfoIn > 600) { +- this.broadcastAll(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY), this.players)); ++ // CraftBukkit start ++ for (int i = 0; i < this.players.size(); ++i) { ++ final ServerPlayer target = (ServerPlayer) this.players.get(i); ++ ++ target.connection.send(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY), this.players.stream().filter(new Predicate() { ++ @Override ++ public boolean test(ServerPlayer input) { ++ return target.getBukkitEntity().canSee(input.getBukkitEntity()); ++ } ++ }).collect(Collectors.toList()))); ++ } ++ // CraftBukkit end + this.sendAllPlayerInfoIn = 0; + } + +@@ -594,7 +851,26 @@ + + } + +- public void broadcastAll(Packet packet, ResourceKey resourcekey) { ++ // CraftBukkit start - add a world/entity limited version ++ public void broadcastAll(Packet packet, net.minecraft.world.entity.player.Player entityhuman) { ++ for (int i = 0; i < this.players.size(); ++i) { ++ ServerPlayer entityplayer = this.players.get(i); ++ if (entityhuman != null && !entityplayer.getBukkitEntity().canSee(entityhuman.getBukkitEntity())) { ++ continue; ++ } ++ ((ServerPlayer) this.players.get(i)).connection.send(packet); ++ } ++ } ++ ++ public void broadcastAll(Packet packet, Level world) { ++ for (int i = 0; i < world.players().size(); ++i) { ++ ((ServerPlayer) world.players().get(i)).connection.send(packet); ++ } ++ ++ } ++ // CraftBukkit end ++ ++ public void broadcastAll(Packet packet, ResourceKey dimension) { + Iterator iterator = this.players.iterator(); + + while (iterator.hasNext()) { +@@ -696,7 +972,8 @@ + serverplayer.connection.send(new ClientboundEntityEventPacket(serverplayer, b0)); + } + +- this.server.getCommands().sendCommands(serverplayer); ++ player.getBukkitEntity().recalculatePermissions(); // CraftBukkit ++ this.server.getCommands().sendCommands(player); + } + + public boolean isWhiteListed(GameProfile gameprofile) { +@@ -726,10 +1003,11 @@ + for (int i = 0; i < this.players.size(); ++i) { + ServerPlayer serverplayer = (ServerPlayer) this.players.get(i); + +- if (serverplayer != player && serverplayer.level().dimension() == resourcekey) { +- double d4 = d0 - serverplayer.getX(); +- double d5 = d1 - serverplayer.getY(); +- double d6 = d2 - serverplayer.getZ(); ++ // CraftBukkit start - Test if player receiving packet can see the source of the packet ++ if (except != null && !entityplayer.getBukkitEntity().canSee(except.getBukkitEntity())) { ++ continue; ++ } ++ // CraftBukkit end + + if (d4 * d4 + d5 * d5 + d6 * d6 < d3 * d3) { + serverplayer.connection.send(packet); +@@ -764,26 +1047,38 @@ + + public void reloadWhiteList() {} + +- public void sendLevelInfo(ServerPlayer serverplayer, ServerLevel serverlevel) { +- WorldBorder worldborder = this.server.overworld().getWorldBorder(); ++ public void sendLevelInfo(ServerPlayer player, ServerLevel level) { ++ WorldBorder worldborder = player.level().getWorldBorder(); // CraftBukkit + +- serverplayer.connection.send(new ClientboundInitializeBorderPacket(worldborder)); +- serverplayer.connection.send(new ClientboundSetTimePacket(serverlevel.getGameTime(), serverlevel.getDayTime(), serverlevel.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); +- serverplayer.connection.send(new ClientboundSetDefaultSpawnPositionPacket(serverlevel.getSharedSpawnPos(), serverlevel.getSharedSpawnAngle())); +- if (serverlevel.isRaining()) { +- serverplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.START_RAINING, 0.0F)); +- serverplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, serverlevel.getRainLevel(1.0F))); +- serverplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, serverlevel.getThunderLevel(1.0F))); ++ player.connection.send(new ClientboundInitializeBorderPacket(worldborder)); ++ player.connection.send(new ClientboundSetTimePacket(level.getGameTime(), level.getDayTime(), level.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); ++ player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(level.getSharedSpawnPos(), level.getSharedSpawnAngle())); ++ if (level.isRaining()) { ++ // CraftBukkit start - handle player weather ++ // entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.START_RAINING, 0.0F)); ++ // entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.RAIN_LEVEL_CHANGE, worldserver.getRainLevel(1.0F))); ++ // entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, worldserver.getThunderLevel(1.0F))); ++ player.setPlayerWeather(org.bukkit.WeatherType.DOWNFALL, false); ++ player.updateWeather(-level.rainLevel, level.rainLevel, -level.thunderLevel, level.thunderLevel); ++ // CraftBukkit end + } + + serverplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LEVEL_CHUNKS_LOAD_START, 0.0F)); + this.server.tickRateManager().updateJoiningPlayer(serverplayer); + } + +- public void sendAllPlayerInfo(ServerPlayer serverplayer) { +- serverplayer.inventoryMenu.sendAllDataToRemote(); +- serverplayer.resetSentInfo(); +- serverplayer.connection.send(new ClientboundSetCarriedItemPacket(serverplayer.getInventory().selected)); ++ public void sendAllPlayerInfo(ServerPlayer player) { ++ player.inventoryMenu.sendAllDataToRemote(); ++ // entityplayer.resetSentInfo(); ++ player.getBukkitEntity().updateScaledHealth(); // CraftBukkit - Update scaled health on respawn and worldchange ++ player.getEntityData().refresh(player); // CraftBukkkit - SPIGOT-7218: sync metadata ++ player.connection.send(new ClientboundSetCarriedItemPacket(player.getInventory().selected)); ++ // CraftBukkit start - from GameRules ++ int i = player.level().getGameRules().getBoolean(GameRules.RULE_REDUCEDDEBUGINFO) ? 22 : 23; ++ player.connection.send(new ClientboundEntityEventPacket(player, (byte) i)); ++ float immediateRespawn = player.level().getGameRules().getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN) ? 1.0F: 0.0F; ++ player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.IMMEDIATE_RESPAWN, immediateRespawn)); ++ // CraftBukkit end + } + + public int getPlayerCount() { +@@ -839,17 +1134,21 @@ + } + + public void removeAll() { +- for (int i = 0; i < this.players.size(); ++i) { +- ((ServerPlayer) this.players.get(i)).connection.disconnect(Component.translatable("multiplayer.disconnect.server_shutdown")); ++ // CraftBukkit start - disconnect safely ++ for (ServerPlayer player : this.players) { ++ player.connection.disconnect(this.server.server.getShutdownMessage()); // CraftBukkit - add custom shutdown message + } ++ // CraftBukkit end + + } + +- public void broadcastSystemMessage(Component component, boolean flag) { +- this.broadcastSystemMessage(component, (serverplayer) -> { +- return component; +- }, flag); ++ // CraftBukkit start ++ public void broadcastMessage(Component[] iChatBaseComponents) { ++ for (Component component : iChatBaseComponents) { ++ broadcastSystemMessage(component, false); ++ } + } ++ // CraftBukkit end + + public void broadcastSystemMessage(Component component, Function function, boolean flag) { + this.server.sendSystemMessage(component); +@@ -902,16 +1207,23 @@ + return playerchatmessage.hasSignature() && !playerchatmessage.hasExpiredServer(Instant.now()); + } + +- public ServerStatsCounter getPlayerStats(Player player) { +- UUID uuid = player.getUUID(); +- ServerStatsCounter serverstatscounter = (ServerStatsCounter) this.stats.get(uuid); ++ // CraftBukkit start ++ public ServerStatsCounter getPlayerStats(ServerPlayer entityhuman) { ++ ServerStatsCounter serverstatisticmanager = entityhuman.getStats(); ++ return serverstatisticmanager == null ? getPlayerStats(entityhuman.getUUID(), entityhuman.getDisplayName().getString()) : serverstatisticmanager; ++ } + +- if (serverstatscounter == null) { ++ public ServerStatsCounter getPlayerStats(UUID uuid, String displayName) { ++ ServerPlayer entityhuman = this.getPlayer(uuid); ++ ServerStatsCounter serverstatisticmanager = entityhuman == null ? null : (ServerStatsCounter) entityhuman.getStats(); ++ // CraftBukkit end ++ ++ if (serverstatisticmanager == null) { + File file = this.server.getWorldPath(LevelResource.PLAYER_STATS_DIR).toFile(); + File file1 = new File(file, uuid + ".json"); + + if (!file1.exists()) { +- File file2 = new File(file, player.getName().getString() + ".json"); ++ File file2 = new File(file, displayName + ".json"); // CraftBukkit + Path path = file2.toPath(); + + if (FileUtil.isPathNormalized(path) && FileUtil.isPathPortable(path) && path.startsWith(file.getPath()) && file2.isFile()) { +@@ -919,22 +1231,22 @@ + } + } + +- serverstatscounter = new ServerStatsCounter(this.server, file1); +- this.stats.put(uuid, serverstatscounter); ++ serverstatisticmanager = new ServerStatsCounter(this.server, file1); ++ // this.stats.put(uuid, serverstatisticmanager); // CraftBukkit + } + + return serverstatscounter; + } + +- public PlayerAdvancements getPlayerAdvancements(ServerPlayer serverplayer) { +- UUID uuid = serverplayer.getUUID(); +- PlayerAdvancements playeradvancements = (PlayerAdvancements) this.advancements.get(uuid); ++ public PlayerAdvancements getPlayerAdvancements(ServerPlayer player) { ++ UUID uuid = player.getUUID(); ++ PlayerAdvancements advancementdataplayer = (PlayerAdvancements) player.getAdvancements(); // CraftBukkit + + if (playeradvancements == null) { + Path path = this.server.getWorldPath(LevelResource.PLAYER_ADVANCEMENTS_DIR).resolve(uuid + ".json"); + +- playeradvancements = new PlayerAdvancements(this.server.getFixerUpper(), this, this.server.getAdvancements(), path, serverplayer); +- this.advancements.put(uuid, playeradvancements); ++ advancementdataplayer = new PlayerAdvancements(this.server.getFixerUpper(), this, this.server.getAdvancements(), path, player); ++ // this.advancements.put(uuid, advancementdataplayer); // CraftBukkit + } + + playeradvancements.setPlayer(serverplayer); +@@ -985,13 +1297,20 @@ + } + + public void reloadResources() { +- Iterator iterator = this.advancements.values().iterator(); ++ // CraftBukkit start ++ /*Iterator iterator = this.advancements.values().iterator(); + + while (iterator.hasNext()) { + PlayerAdvancements playeradvancements = (PlayerAdvancements) iterator.next(); + +- playeradvancements.reload(this.server.getAdvancements()); ++ advancementdataplayer.reload(this.server.getAdvancements()); ++ }*/ ++ ++ for (ServerPlayer player : players) { ++ player.getAdvancements().reload(this.server.getAdvancements()); ++ player.getAdvancements().flushDirty(player); // CraftBukkit - trigger immediate flush of advancements + } ++ // CraftBukkit end + + this.broadcastAll(new ClientboundUpdateTagsPacket(TagNetworkSerialization.serializeTagsToNetwork(this.registries))); + ClientboundUpdateRecipesPacket clientboundupdaterecipespacket = new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes()); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/SleepStatus.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/SleepStatus.java.patch new file mode 100644 index 0000000000..580cdaf078 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/SleepStatus.java.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/server/players/SleepStatus.java ++++ b/net/minecraft/server/players/SleepStatus.java +@@ -17,10 +17,13 @@ + return this.sleepingPlayers >= this.sleepersNeeded(i); + } + +- public boolean areEnoughDeepSleeping(int i, List list) { +- int j = (int) list.stream().filter(Player::isSleepingLongEnough).count(); ++ public boolean areEnoughDeepSleeping(int requiredSleepPercentage, List sleepingPlayers) { ++ // CraftBukkit start ++ int j = (int) sleepingPlayers.stream().filter((eh) -> { return eh.isSleepingLongEnough() || eh.fauxSleeping; }).count(); ++ boolean anyDeepSleep = sleepingPlayers.stream().anyMatch(Player::isSleepingLongEnough); + +- return j >= this.sleepersNeeded(i); ++ return anyDeepSleep && j >= this.sleepersNeeded(requiredSleepPercentage); ++ // CraftBukkit end + } + + public int sleepersNeeded(int i) { +@@ -41,19 +44,25 @@ + + this.activePlayers = 0; + this.sleepingPlayers = 0; +- Iterator iterator = list.iterator(); ++ Iterator iterator = players.iterator(); ++ boolean anySleep = false; // CraftBukkit + + while (iterator.hasNext()) { + ServerPlayer serverplayer = (ServerPlayer) iterator.next(); + + if (!serverplayer.isSpectator()) { + ++this.activePlayers; +- if (serverplayer.isSleeping()) { ++ if (entityplayer.isSleeping() || entityplayer.fauxSleeping) { // CraftBukkit + ++this.sleepingPlayers; + } ++ // CraftBukkit start ++ if (entityplayer.isSleeping()) { ++ anySleep = true; ++ } ++ // CraftBukkit end + } + } + +- return (j > 0 || this.sleepingPlayers > 0) && (i != this.activePlayers || j != this.sleepingPlayers); ++ return anySleep && (j > 0 || this.sleepingPlayers > 0) && (i != this.activePlayers || j != this.sleepingPlayers); // CraftBukkit + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/StoredUserList.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/StoredUserList.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/StoredUserList.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/UserBanListEntry.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/UserBanListEntry.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/players/UserBanListEntry.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/rcon/RconConsoleSource.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/rcon/RconConsoleSource.java.patch new file mode 100644 index 0000000000..489801bb83 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/rcon/RconConsoleSource.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/server/rcon/RconConsoleSource.java ++++ b/net/minecraft/server/rcon/RconConsoleSource.java +@@ -8,15 +8,23 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; +- ++// CraftBukkit start ++import java.net.SocketAddress; ++import org.bukkit.craftbukkit.command.CraftRemoteConsoleCommandSender; ++// CraftBukkit end + public class RconConsoleSource implements CommandSource { + + private static final String RCON = "Rcon"; + private static final Component RCON_COMPONENT = Component.literal("Rcon"); + private final StringBuffer buffer = new StringBuffer(); + private final MinecraftServer server; ++ // CraftBukkit start ++ public final SocketAddress socketAddress; ++ private final CraftRemoteConsoleCommandSender remoteConsole = new CraftRemoteConsoleCommandSender(this); + +- public RconConsoleSource(MinecraftServer minecraftserver) { ++ public RconConsoleSource(MinecraftServer minecraftserver, SocketAddress socketAddress) { ++ this.socketAddress = socketAddress; ++ // CraftBukkit end + this.server = minecraftserver; + } + +@@ -34,7 +42,17 @@ + return new CommandSourceStack(this, Vec3.atLowerCornerOf(serverlevel.getSharedSpawnPos()), Vec2.ZERO, serverlevel, 4, "Rcon", RconConsoleSource.RCON_COMPONENT, this.server, (Entity) null); + } + ++ // CraftBukkit start - Send a String ++ public void sendMessage(String message) { ++ this.buffer.append(message); ++ } ++ + @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return this.remoteConsole; ++ } ++ // CraftBukkit end ++ + @Override + public void sendSystemMessage(Component component) { + this.buffer.append(component.getString()); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/server/rcon/thread/RconClient.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/rcon/thread/RconClient.java.patch new file mode 100644 index 0000000000..8ee4fae33b --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/server/rcon/thread/RconClient.java.patch @@ -0,0 +1,74 @@ +--- a/net/minecraft/server/rcon/thread/RconClient.java ++++ b/net/minecraft/server/rcon/thread/RconClient.java +@@ -9,6 +10,8 @@ + import java.nio.charset.StandardCharsets; + import java.util.Locale; + import net.minecraft.server.ServerInterface; ++// CraftBukkit start ++import net.minecraft.server.dedicated.DedicatedServer; + import net.minecraft.server.rcon.PktUtils; + import org.slf4j.Logger; + +@@ -24,12 +27,15 @@ + private final Socket client; + private final byte[] buf = new byte[1460]; + private final String rconPassword; +- private final ServerInterface serverInterface; ++ // CraftBukkit start ++ private final DedicatedServer serverInterface; ++ private final RconConsoleSource rconConsoleSource; ++ // CraftBukkit end + +- RconClient(ServerInterface serverinterface, String s, Socket socket) { +- super("RCON Client " + socket.getInetAddress()); +- this.serverInterface = serverinterface; +- this.client = socket; ++ RconClient(ServerInterface serverInterface, String rconPassword, Socket client) { ++ super("RCON Client " + client.getInetAddress()); ++ this.serverInterface = (DedicatedServer) serverInterface; // CraftBukkit ++ this.client = client; + + try { + this.client.setSoTimeout(0); +@@ -37,13 +43,16 @@ + this.running = false; + } + +- this.rconPassword = s; ++ this.rconPassword = rconPassword; ++ this.rconConsoleSource = new net.minecraft.server.rcon.RconConsoleSource(this.serverInterface, client.getRemoteSocketAddress()); // CraftBukkit + } + + @Override + public void run() { +- while (true) { +- try { ++ // CraftBukkit start - decompile error: switch try / while statement ++ try { ++ while (true) { ++ // CraftBukkit end + if (!this.running) { + return; + } +@@ -72,7 +80,7 @@ + String s = PktUtils.stringFromByteArray(this.buf, k, i); + + try { +- this.sendCmdResponse(l, this.serverInterface.runCommand(s)); ++ this.sendCmdResponse(l, this.serverInterface.runCommand(this.rconConsoleSource, s)); // CraftBukkit + } catch (Exception exception) { + this.sendCmdResponse(l, "Error executing: " + s + " (" + exception.getMessage() + ")"); + } +@@ -110,8 +119,10 @@ + this.running = false; + } + +- return; +- } ++ // CraftBukkit start - decompile error: switch try / while statement ++ // return; ++ // } ++ // CraftBukkit end + } + + private void send(int i, int j, String s) throws IOException { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/stats/ServerRecipeBook.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/stats/ServerRecipeBook.java.patch new file mode 100644 index 0000000000..8ffb0784be --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/stats/ServerRecipeBook.java.patch @@ -0,0 +1,28 @@ +--- a/net/minecraft/stats/ServerRecipeBook.java ++++ b/net/minecraft/stats/ServerRecipeBook.java +@@ -20,6 +20,8 @@ + import net.minecraft.world.item.crafting.RecipeManager; + import org.slf4j.Logger; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public class ServerRecipeBook extends RecipeBook { + + public static final String RECIPE_BOOK_TAG = "recipeBook"; +@@ -36,11 +38,11 @@ + RecipeHolder recipeholder = (RecipeHolder) iterator.next(); + ResourceLocation resourcelocation = recipeholder.id(); + +- if (!this.known.contains(resourcelocation) && !recipeholder.value().isSpecial()) { +- this.add(resourcelocation); +- this.addHighlight(resourcelocation); +- list.add(resourcelocation); +- CriteriaTriggers.RECIPE_UNLOCKED.trigger(serverplayer, recipeholder); ++ if (!this.known.contains(minecraftkey) && !recipeholder.value().isSpecial() && CraftEventFactory.handlePlayerRecipeListUpdateEvent(player, minecraftkey)) { // CraftBukkit ++ this.add(minecraftkey); ++ this.addHighlight(minecraftkey); ++ list.add(minecraftkey); ++ CriteriaTriggers.RECIPE_UNLOCKED.trigger(player, recipeholder); + ++i; + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/stats/ServerStatsCounter.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/stats/ServerStatsCounter.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/stats/ServerStatsCounter.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/stats/StatsCounter.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/stats/StatsCounter.java.patch new file mode 100644 index 0000000000..8c5216bd18 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/stats/StatsCounter.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/stats/StatsCounter.java ++++ b/net/minecraft/stats/StatsCounter.java +@@ -16,6 +16,12 @@ + public void increment(Player player, Stat stat, int i) { + int j = (int) Math.min((long) this.getValue(stat) + (long) i, 2147483647L); + ++ // CraftBukkit start - fire Statistic events ++ org.bukkit.event.Cancellable cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.handleStatisticsIncrease(player, stat, this.getValue(stat), j); ++ if (cancellable != null && cancellable.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.setValue(player, stat, j); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/util/SpawnUtil.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/util/SpawnUtil.java.patch new file mode 100644 index 0000000000..3eb9602d45 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/util/SpawnUtil.java.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/util/SpawnUtil.java ++++ b/net/minecraft/util/SpawnUtil.java +@@ -20,9 +20,15 @@ + + public SpawnUtil() {} + +- public static Optional trySpawnMob(EntityType entitytype, MobSpawnType mobspawntype, ServerLevel serverlevel, BlockPos blockpos, int i, int j, int k, SpawnUtil.Strategy spawnutil_strategy) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = blockpos.mutable(); ++ public static Optional trySpawnMob(EntityType entityType, EnumMobSpawn spawnType, ServerLevel level, BlockPos pos, int attempts, int j, int yOffset, SpawnUtil.Strategy strategy) { ++ // CraftBukkit start ++ return trySpawnMob(entityType, spawnType, level, pos, attempts, j, yOffset, strategy, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } + ++ public static Optional trySpawnMob(EntityType entitytypes, EnumMobSpawn enummobspawn, ServerLevel worldserver, BlockPos blockposition, int i, int j, int k, SpawnUtil.Strategy spawnutil_a, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ // CraftBukkit end ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = blockposition.mutable(); ++ + for (int l = 0; l < i; ++l) { + int i1 = Mth.randomBetweenInclusive(serverlevel.random, -j, j); + int j1 = Mth.randomBetweenInclusive(serverlevel.random, -j, j); +@@ -32,8 +38,8 @@ + T t0 = (Mob) entitytype.create(serverlevel, (CompoundTag) null, (Consumer) null, blockpos_mutableblockpos, mobspawntype, false, false); + + if (t0 != null) { +- if (t0.checkSpawnRules(serverlevel, mobspawntype) && t0.checkSpawnObstruction(serverlevel)) { +- serverlevel.addFreshEntityWithPassengers(t0); ++ if (t0.checkSpawnRules(worldserver, enummobspawn) && t0.checkSpawnObstruction(worldserver)) { ++ worldserver.addFreshEntityWithPassengers(t0, reason); // CraftBukkit + return Optional.of(t0); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/util/datafix/DataFixers.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/util/datafix/DataFixers.java.patch new file mode 100644 index 0000000000..a30ad435a0 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/util/datafix/DataFixers.java.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/util/datafix/DataFixers.java ++++ b/net/minecraft/util/datafix/DataFixers.java +@@ -455,10 +279,22 @@ + datafixerbuilder.addFixer(new EntityItemFrameDirectionFix(schema44, false)); + Schema schema45 = datafixerbuilder.addSchema(1458, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new EntityCustomNameToComponentFix(schema45, false)); +- datafixerbuilder.addFixer(new ItemCustomNameToComponentFix(schema45, false)); +- datafixerbuilder.addFixer(new BlockEntityCustomNameToComponentFix(schema45, false)); +- Schema schema46 = datafixerbuilder.addSchema(1460, V1460::new); ++ // CraftBukkit start ++ builder.addFixer(new com.mojang.datafixers.DataFix(schema45, false) { ++ @Override ++ protected com.mojang.datafixers.TypeRewriteRule makeRule() { ++ return this.fixTypeEverywhereTyped("Player CustomName", this.getInputSchema().getType(DataConverterTypes.PLAYER), (typed) -> { ++ return typed.update(DSL.remainderFinder(), (dynamic) -> { ++ return EntityCustomNameToComponentFix.fixTagCustomName(dynamic); ++ }); ++ }); ++ } ++ }); ++ // CraftBukkit end ++ builder.addFixer(new EntityCustomNameToComponentFix(schema45, false)); ++ builder.addFixer(new ItemCustomNameToComponentFix(schema45, false)); ++ builder.addFixer(new BlockEntityCustomNameToComponentFix(schema45, false)); ++ Schema schema46 = builder.addSchema(1460, V1460::new); + + datafixerbuilder.addFixer(new EntityPaintingMotiveFix(schema46, false)); + Schema schema47 = datafixerbuilder.addSchema(1466, V1466::new); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java.patch new file mode 100644 index 0000000000..e5e5128702 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java ++++ b/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java +@@ -33,7 +32,7 @@ + Typed typed1 = typed.getOrCreateTyped(opticfinder1); + Dynamic dynamic1 = (Dynamic) typed1.get(DSL.remainderFinder()); + +- dynamic1 = dynamic1.set("map", dynamic1.createInt(dynamic.get("Damage").asInt(0))); ++ if (!dynamic1.getElement("map").result().isPresent()) dynamic1 = dynamic1.set("map", dynamic1.createInt(dynamic.get("Damage").asInt(0))); // CraftBukkit + return typed.set(opticfinder1, typed1.set(DSL.remainderFinder(), dynamic1)); + } else { + return typed; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java.patch new file mode 100644 index 0000000000..2153992c7f --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java ++++ b/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java +@@ -377,7 +376,7 @@ + Typed typed2 = typed.getOrCreateTyped(opticfinder1); + Dynamic dynamic1 = (Dynamic) typed2.get(DSL.remainderFinder()); + +- dynamic1 = dynamic1.set("Damage", dynamic1.createInt(i)); ++ if (i != 0) dynamic1 = dynamic1.set("Damage", dynamic1.createInt(i)); // CraftBukkit + typed1 = typed1.set(opticfinder1, typed2.set(DSL.remainderFinder(), dynamic1)); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/util/worldupdate/WorldUpgrader.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/util/worldupdate/WorldUpgrader.java.patch new file mode 100644 index 0000000000..14d66bba93 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/util/worldupdate/WorldUpgrader.java.patch @@ -0,0 +1,37 @@ +--- a/net/minecraft/util/worldupdate/WorldUpgrader.java ++++ b/net/minecraft/util/worldupdate/WorldUpgrader.java +@@ -64,13 +64,13 @@ + private static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$"); + private final DimensionDataStorage overworldDataStorage; + +- public WorldUpgrader(LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess, DataFixer datafixer, Registry registry, boolean flag) { +- this.dimensions = registry; +- this.levels = (Set) registry.registryKeySet().stream().map(Registries::levelStemToLevel).collect(Collectors.toUnmodifiableSet()); +- this.eraseCache = flag; +- this.dataFixer = datafixer; +- this.levelStorage = levelstoragesource_levelstorageaccess; +- this.overworldDataStorage = new DimensionDataStorage(this.levelStorage.getDimensionPath(Level.OVERWORLD).resolve("data").toFile(), datafixer); ++ public WorldUpgrader(LevelStorageSource.LevelStorageAccess levelStoarge, DataFixer dataFixer, Registry dimensions, boolean eraseCache) { ++ this.dimensions = dimensions; ++ this.levels = (Set) java.util.stream.Stream.of(levelStoarge.dimensionType).map(Registries::levelStemToLevel).collect(Collectors.toUnmodifiableSet()); // CraftBukkit ++ this.eraseCache = eraseCache; ++ this.dataFixer = dataFixer; ++ this.levelStorage = levelStoarge; ++ this.overworldDataStorage = new DimensionDataStorage(this.levelStorage.getDimensionPath(Level.OVERWORLD).resolve("data").toFile(), dataFixer); + this.thread = WorldUpgrader.THREAD_FACTORY.newThread(this::work); + this.thread.setUncaughtExceptionHandler((thread, throwable) -> { + WorldUpgrader.LOGGER.error("Error upgrading world", throwable); +@@ -145,10 +145,10 @@ + if (compoundtag != null) { + int j = ChunkStorage.getVersion(compoundtag); + ChunkGenerator chunkgenerator = ((LevelStem) this.dimensions.getOrThrow(Registries.levelToLevelStem(resourcekey2))).generator(); +- CompoundTag compoundtag1 = chunkstorage.upgradeChunkTag(resourcekey2, () -> { ++ CompoundTag nbttagcompound1 = ichunkloader.upgradeChunkTag(Registries.levelToLevelStem(resourcekey2), () -> { // CraftBukkit + return this.overworldDataStorage; +- }, compoundtag, chunkgenerator.getTypeNameForDataFixer()); +- ChunkPos chunkpos1 = new ChunkPos(compoundtag1.getInt("xPos"), compoundtag1.getInt("zPos")); ++ }, nbttagcompound, chunkgenerator.getTypeNameForDataFixer(), chunkcoordintpair, null); // CraftBukkit ++ ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); + + if (!chunkpos1.equals(chunkpos)) { + WorldUpgrader.LOGGER.warn("Chunk {} has invalid position {}", chunkpos, chunkpos1); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/CompoundContainer.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/CompoundContainer.java.patch new file mode 100644 index 0000000000..0d3f513d34 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/CompoundContainer.java.patch @@ -0,0 +1,57 @@ +--- a/net/minecraft/world/CompoundContainer.java ++++ b/net/minecraft/world/CompoundContainer.java +@@ -3,17 +3,42 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import org.bukkit.Location; ++ ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class CompoundContainer implements Container { + + private final Container container1; + private final Container container2; + +- public CompoundContainer(Container container, Container container1) { +- this.container1 = container; +- this.container2 = container1; ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ ++ public List getContents() { ++ List result = new ArrayList(this.getContainerSize()); ++ for (int i = 0; i < this.getContainerSize(); i++) { ++ result.add(this.getItem(i)); ++ } ++ return result; + } + + @Override ++ public Location getLocation() { ++ return container1.getLocation(); // TODO: right? ++ } ++ // CraftBukkit end ++ ++ public CompoundContainer(Container container1, Container container2) { ++ this.container1 = container1; ++ this.container2 = container2; ++ } ++ + @Override + public int getContainerSize() { + return this.container1.getContainerSize() + this.container2.getContainerSize(); +@@ -61,7 +105,7 @@ + @Override + @Override + public int getMaxStackSize() { +- return this.container1.getMaxStackSize(); ++ return Math.min(this.container1.getMaxStackSize(), this.container2.getMaxStackSize()); // CraftBukkit - check both sides + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/Container.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/Container.java.patch new file mode 100644 index 0000000000..7222f92079 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/Container.java.patch @@ -0,0 +1,56 @@ +--- a/net/minecraft/world/Container.java ++++ b/net/minecraft/world/Container.java +@@ -6,8 +6,12 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; ++// CraftBukkit start ++import net.minecraft.world.item.crafting.RecipeHolder; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.BlockEntity; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++// CraftBukkit end + + public interface Container extends Clearable { + +@@ -26,9 +30,7 @@ + + void setItem(int slot, ItemStack stack); + +- default int getMaxStackSize() { +- return 64; +- } ++ int getMaxStackSize(); // CraftBukkit + + void setChanged(); + +@@ -88,4 +90,29 @@ + + return level == null ? false : (level.getBlockEntity(blockpos) != blockentity ? false : player.distanceToSqr((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D) <= (double) (i * i)); + } ++ ++ // CraftBukkit start ++ java.util.List getContents(); ++ ++ void onOpen(CraftHumanEntity who); ++ ++ void onClose(CraftHumanEntity who); ++ ++ java.util.List getViewers(); ++ ++ org.bukkit.inventory.InventoryHolder getOwner(); ++ ++ void setMaxStackSize(int size); ++ ++ org.bukkit.Location getLocation(); ++ ++ default RecipeHolder getCurrentRecipe() { ++ return null; ++ } ++ ++ default void setCurrentRecipe(RecipeHolder recipe) { ++ } ++ ++ int MAX_STACK = 64; ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/LockCode.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/LockCode.java.patch new file mode 100644 index 0000000000..8787dc2f00 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/LockCode.java.patch @@ -0,0 +1,37 @@ +--- a/net/minecraft/world/LockCode.java ++++ b/net/minecraft/world/LockCode.java +@@ -4,6 +4,11 @@ + import net.minecraft.nbt.CompoundTag; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.ChatColor; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++// CraftBukkit end ++ + @Immutable + public class LockCode { + +@@ -15,8 +20,20 @@ + this.key = s; + } + +- public boolean unlocksWith(ItemStack itemstack) { +- return this.key.isEmpty() || !itemstack.isEmpty() && itemstack.hasCustomHoverName() && this.key.equals(itemstack.getHoverName().getString()); ++ public boolean unlocksWith(ItemStack stack) { ++ // CraftBukkit start - SPIGOT-6307: Check for color codes if the lock contains color codes ++ if (this.key.isEmpty()) return true; ++ if (!stack.isEmpty() && stack.hasCustomHoverName()) { ++ if (this.key.indexOf(ChatColor.COLOR_CHAR) == -1) { ++ // The lock key contains no color codes, so let's ignore colors in the item display name (vanilla Minecraft behavior): ++ return this.key.equals(stack.getHoverName().getString()); ++ } else { ++ // The lock key contains color codes, so let's take them into account: ++ return this.key.equals(CraftChatMessage.fromComponent(stack.getHoverName())); ++ } ++ } ++ return false; ++ // CraftBukkit end + } + + public void addToTag(CompoundTag compoundtag) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/SimpleContainer.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/SimpleContainer.java.patch new file mode 100644 index 0000000000..700beac642 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/SimpleContainer.java.patch @@ -0,0 +1,76 @@ +--- a/net/minecraft/world/SimpleContainer.java ++++ b/net/minecraft/world/SimpleContainer.java +@@ -14,6 +14,12 @@ + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class SimpleContainer implements Container, StackedContentsCompatible { + + private final int size; +@@ -21,7 +27,59 @@ + @Nullable + private List listeners; + +- public SimpleContainer(int i) { ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ protected org.bukkit.inventory.InventoryHolder bukkitOwner; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return bukkitOwner; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return null; ++ } ++ ++ public SimpleContainer(SimpleContainer original) { ++ this(original.size); ++ for (int slot = 0; slot < original.size; slot++) { ++ this.items.set(slot, original.items.get(slot).copy()); ++ } ++ } ++ ++ public SimpleContainer(int size) { ++ this(size, null); ++ } ++ ++ public SimpleContainer(int i, org.bukkit.inventory.InventoryHolder owner) { ++ this.bukkitOwner = owner; ++ // CraftBukkit end + this.size = i; + this.items = NonNullList.withSize(i, ItemStack.EMPTY); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/damagesource/DamageSource.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/damagesource/DamageSource.java.patch new file mode 100644 index 0000000000..94ba17f3b7 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/damagesource/DamageSource.java.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/world/damagesource/DamageSource.java ++++ b/net/minecraft/world/damagesource/DamageSource.java +@@ -20,8 +20,39 @@ + private final Entity directEntity; + @Nullable + private final Vec3 damageSourcePosition; ++ // CraftBukkit start ++ private boolean sweep; ++ private boolean melting; ++ private boolean poison; + +- @Override ++ public boolean isSweep() { ++ return sweep; ++ } ++ ++ public DamageSource sweep() { ++ this.sweep = true; ++ return this; ++ } ++ ++ public boolean isMelting() { ++ return melting; ++ } ++ ++ public DamageSource melting() { ++ this.melting = true; ++ return this; ++ } ++ ++ public boolean isPoison() { ++ return poison; ++ } ++ ++ public DamageSource poison() { ++ this.poison = true; ++ return this; ++ } ++ // CraftBukkit end ++ + public String toString() { + return "DamageSource (" + this.type().msgId() + ")"; + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/damagesource/DamageSources.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/damagesource/DamageSources.java.patch new file mode 100644 index 0000000000..233f5cc911 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/damagesource/DamageSources.java.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/damagesource/DamageSources.java ++++ b/net/minecraft/world/damagesource/DamageSources.java +@@ -41,9 +41,15 @@ + private final DamageSource stalagmite; + private final DamageSource outsideBorder; + private final DamageSource genericKill; ++ // CraftBukkit start ++ public final DamageSource melting; ++ public final DamageSource poison; + +- public DamageSources(RegistryAccess registryaccess) { +- this.damageTypes = registryaccess.registryOrThrow(Registries.DAMAGE_TYPE); ++ public DamageSources(RegistryAccess registry) { ++ this.damageTypes = registry.registryOrThrow(Registries.DAMAGE_TYPE); ++ this.melting = this.source(DamageTypes.ON_FIRE).melting(); ++ this.poison = this.source(DamageTypes.MAGIC).poison(); ++ // CraftBukkit end + this.inFire = this.source(DamageTypes.IN_FIRE); + this.lightningBolt = this.source(DamageTypes.LIGHTNING_BOLT); + this.onFire = this.source(DamageTypes.ON_FIRE); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/effect/HealOrHarmMobEffect.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/effect/HealOrHarmMobEffect.java.patch new file mode 100644 index 0000000000..8433a065ed --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/effect/HealOrHarmMobEffect.java.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/effect/HealOrHarmMobEffect.java ++++ b/net/minecraft/world/effect/HealOrHarmMobEffect.java +@@ -14,11 +14,10 @@ + } + + @Override +- @Override +- public void applyEffectTick(LivingEntity livingentity, int i) { +- super.applyEffectTick(livingentity, i); +- if (this.isHarm == livingentity.isInvertedHealAndHarm()) { +- livingentity.heal((float) Math.max(4 << i, 0)); ++ public void applyEffectTick(LivingEntity livingEntity, int amplifier) { ++ super.applyEffectTick(livingEntity, amplifier); ++ if (this.isHarm == livingEntity.isInvertedHealAndHarm()) { ++ livingEntity.heal((float) Math.max(4 << amplifier, 0), org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.MAGIC); // CraftBukkit + } else { + livingentity.hurt(livingentity.damageSources().magic(), (float) (6 << i)); + } +@@ -30,9 +28,9 @@ + public void applyInstantenousEffect(@Nullable Entity entity, @Nullable Entity entity1, LivingEntity livingentity, int i, double d0) { + int j; + +- if (this.isHarm == livingentity.isInvertedHealAndHarm()) { +- j = (int) (d0 * (double) (4 << i) + 0.5D); +- livingentity.heal((float) j); ++ if (this.isHarm == livingEntity.isInvertedHealAndHarm()) { ++ j = (int) (health * (double) (4 << amplifier) + 0.5D); ++ livingEntity.heal((float) j, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.MAGIC); // CraftBukkit + } else { + j = (int) (d0 * (double) (6 << i) + 0.5D); + if (entity == null) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/effect/HungerMobEffect.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/effect/HungerMobEffect.java.patch new file mode 100644 index 0000000000..811fd56fa9 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/effect/HungerMobEffect.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/effect/HungerMobEffect.java ++++ b/net/minecraft/world/effect/HungerMobEffect.java +@@ -16,7 +15,7 @@ + if (livingentity instanceof Player) { + Player player = (Player) livingentity; + +- player.causeFoodExhaustion(0.005F * (float) (i + 1)); ++ entityhuman.causeFoodExhaustion(0.005F * (float) (amplifier + 1), org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.HUNGER_EFFECT); // CraftBukkit - EntityExhaustionEvent + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/effect/MobEffectUtil.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/effect/MobEffectUtil.java.patch new file mode 100644 index 0000000000..c566068ab2 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/effect/MobEffectUtil.java.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/world/effect/MobEffectUtil.java ++++ b/net/minecraft/world/effect/MobEffectUtil.java +@@ -48,14 +48,20 @@ + return livingentity.hasEffect(MobEffects.WATER_BREATHING) || livingentity.hasEffect(MobEffects.CONDUIT_POWER); + } + +- public static List addEffectToPlayersAround(ServerLevel serverlevel, @Nullable Entity entity, Vec3 vec3, double d0, MobEffectInstance mobeffectinstance, int i) { +- MobEffect mobeffect = mobeffectinstance.getEffect(); +- List list = serverlevel.getPlayers((serverplayer) -> { +- return serverplayer.gameMode.isSurvival() && (entity == null || !entity.isAlliedTo((Entity) serverplayer)) && vec3.closerThan(serverplayer.position(), d0) && (!serverplayer.hasEffect(mobeffect) || serverplayer.getEffect(mobeffect).getAmplifier() < mobeffectinstance.getAmplifier() || serverplayer.getEffect(mobeffect).endsWithin(i - 1)); ++ public static List addEffectToPlayersAround(ServerLevel level, @Nullable Entity source, Vec3 pos, double radius, MobEffectInstance mobeffect, int effect) { ++ // CraftBukkit start ++ return addEffectToPlayersAround(level, source, pos, radius, mobeffect, effect, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public static List addEffectToPlayersAround(ServerLevel worldserver, @Nullable Entity entity, Vec3 vec3d, double d0, MobEffectInstance mobeffect, int i, org.bukkit.event.entity.EntityPotionEffectEvent.Cause cause) { ++ // CraftBukkit end ++ MobEffect mobeffectlist = mobeffect.getEffect(); ++ List list = worldserver.getPlayers((entityplayer) -> { ++ return entityplayer.gameMode.isSurvival() && (entity == null || !entity.isAlliedTo((Entity) entityplayer)) && vec3d.closerThan(entityplayer.position(), d0) && (!entityplayer.hasEffect(mobeffectlist) || entityplayer.getEffect(mobeffectlist).getAmplifier() < mobeffect.getAmplifier() || entityplayer.getEffect(mobeffectlist).endsWithin(i - 1)); + }); + +- list.forEach((serverplayer) -> { +- serverplayer.addEffect(new MobEffectInstance(mobeffectinstance), entity); ++ list.forEach((entityplayer) -> { ++ entityplayer.addEffect(new MobEffectInstance(mobeffect), entity, cause); // CraftBukkit + }); + return list; + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/effect/PoisonMobEffect.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/effect/PoisonMobEffect.java.patch new file mode 100644 index 0000000000..6b728cb252 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/effect/PoisonMobEffect.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/effect/PoisonMobEffect.java ++++ b/net/minecraft/world/effect/PoisonMobEffect.java +@@ -9,11 +9,10 @@ + } + + @Override +- @Override +- public void applyEffectTick(LivingEntity livingentity, int i) { +- super.applyEffectTick(livingentity, i); +- if (livingentity.getHealth() > 1.0F) { +- livingentity.hurt(livingentity.damageSources().magic(), 1.0F); ++ public void applyEffectTick(LivingEntity livingEntity, int amplifier) { ++ super.applyEffectTick(livingEntity, amplifier); ++ if (livingEntity.getHealth() > 1.0F) { ++ livingEntity.hurt(livingEntity.damageSources().poison, 1.0F); // CraftBukkit - DamageSource.MAGIC -> CraftEventFactory.POISON + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/effect/RegenerationMobEffect.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/effect/RegenerationMobEffect.java.patch new file mode 100644 index 0000000000..e521009cff --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/effect/RegenerationMobEffect.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/effect/RegenerationMobEffect.java ++++ b/net/minecraft/world/effect/RegenerationMobEffect.java +@@ -9,11 +9,10 @@ + } + + @Override +- @Override +- public void applyEffectTick(LivingEntity livingentity, int i) { +- super.applyEffectTick(livingentity, i); +- if (livingentity.getHealth() < livingentity.getMaxHealth()) { +- livingentity.heal(1.0F); ++ public void applyEffectTick(LivingEntity livingEntity, int amplifier) { ++ super.applyEffectTick(livingEntity, amplifier); ++ if (livingEntity.getHealth() < livingEntity.getMaxHealth()) { ++ livingEntity.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.MAGIC_REGEN); // CraftBukkit + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/effect/SaturationMobEffect.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/effect/SaturationMobEffect.java.patch new file mode 100644 index 0000000000..6c674df037 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/effect/SaturationMobEffect.java.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/effect/SaturationMobEffect.java ++++ b/net/minecraft/world/effect/SaturationMobEffect.java +@@ -2,6 +2,10 @@ + + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.player.Player; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + class SaturationMobEffect extends InstantenousMobEffect { + +@@ -16,7 +19,15 @@ + if (!livingentity.level().isClientSide && livingentity instanceof Player) { + Player player = (Player) livingentity; + +- player.getFoodData().eat(i + 1, 1.0F); ++ // CraftBukkit start ++ int oldFoodLevel = entityhuman.getFoodData().foodLevel; ++ org.bukkit.event.entity.FoodLevelChangeEvent event = CraftEventFactory.callFoodLevelChangeEvent(entityhuman, amplifier + 1 + oldFoodLevel); ++ if (!event.isCancelled()) { ++ entityhuman.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, 1.0F); ++ } ++ ++ ((CraftPlayer) entityhuman.getBukkitEntity()).sendHealthUpdate(); ++ // CraftBukkit end + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/AgeableMob.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/AgeableMob.java.patch new file mode 100644 index 0000000000..a615763ef4 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/AgeableMob.java.patch @@ -0,0 +1,49 @@ +--- a/net/minecraft/world/entity/AgeableMob.java ++++ b/net/minecraft/world/entity/AgeableMob.java +@@ -20,6 +20,7 @@ + protected int age; + protected int forcedAge; + protected int forcedAgeTimer; ++ public boolean ageLocked; // CraftBukkit + + protected AgeableMob(EntityType entitytype, Level level) { + super(entitytype, level); +@@ -101,19 +100,19 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("Age", this.getAge()); +- compoundtag.putInt("ForcedAge", this.forcedAge); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("Age", this.getAge()); ++ compound.putInt("ForcedAge", this.forcedAge); ++ compound.putBoolean("AgeLocked", this.ageLocked); // CraftBukkit + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setAge(compoundtag.getInt("Age")); +- this.forcedAge = compoundtag.getInt("ForcedAge"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setAge(compound.getInt("Age")); ++ this.forcedAge = compound.getInt("ForcedAge"); ++ this.ageLocked = compound.getBoolean("AgeLocked"); // CraftBukkit + } + + @Override +@@ -130,7 +127,7 @@ + @Override + public void aiStep() { + super.aiStep(); +- if (this.level().isClientSide) { ++ if (this.level().isClientSide || ageLocked) { // CraftBukkit + if (this.forcedAgeTimer > 0) { + if (this.forcedAgeTimer % 4 == 0) { + this.level().addParticle(ParticleTypes.HAPPY_VILLAGER, this.getRandomX(1.0D), this.getRandomY() + 0.5D, this.getRandomZ(1.0D), 0.0D, 0.0D, 0.0D); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/AreaEffectCloud.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/AreaEffectCloud.java.patch new file mode 100644 index 0000000000..183916f556 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/AreaEffectCloud.java.patch @@ -0,0 +1,49 @@ +--- a/net/minecraft/world/entity/AreaEffectCloud.java ++++ b/net/minecraft/world/entity/AreaEffectCloud.java +@@ -30,6 +30,9 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.material.PushReaction; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.entity.LivingEntity; ++// CraftBukkit end + + public class AreaEffectCloud extends Entity implements TraceableEntity { + +@@ -267,6 +267,7 @@ + if (!list1.isEmpty()) { + Iterator iterator1 = list1.iterator(); + ++ List entities = new java.util.ArrayList(); // CraftBukkit + while (iterator1.hasNext()) { + LivingEntity livingentity = (LivingEntity) iterator1.next(); + +@@ -276,7 +277,18 @@ + double d8 = d6 * d6 + d7 * d7; + + if (d8 <= (double) (f * f)) { +- this.victims.put(livingentity, this.tickCount + this.reapplicationDelay); ++ // CraftBukkit start ++ entities.add((LivingEntity) entityliving.getBukkitEntity()); ++ } ++ } ++ } ++ org.bukkit.event.entity.AreaEffectCloudApplyEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callAreaEffectCloudApplyEvent(this, entities); ++ if (!event.isCancelled()) { ++ for (LivingEntity entity : event.getAffectedEntities()) { ++ if (entity instanceof CraftLivingEntity) { ++ net.minecraft.world.entity.LivingEntity entityliving = ((CraftLivingEntity) entity).getHandle(); ++ // CraftBukkit end ++ this.victims.put(entityliving, this.tickCount + this.reapplicationDelay); + Iterator iterator2 = list.iterator(); + + while (iterator2.hasNext()) { +@@ -285,7 +297,7 @@ + if (mobeffectinstance1.getEffect().isInstantenous()) { + mobeffectinstance1.getEffect().applyInstantenousEffect(this, this.getOwner(), livingentity, mobeffectinstance1.getAmplifier(), 0.5D); + } else { +- livingentity.addEffect(new MobEffectInstance(mobeffectinstance1), this); ++ entityliving.addEffect(new MobEffectInstance(mobeffect1), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AREA_EFFECT_CLOUD); // CraftBukkit + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/Entity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/Entity.java.patch new file mode 100644 index 0000000000..952a26da6e --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/Entity.java.patch @@ -0,0 +1,1002 @@ +--- a/net/minecraft/world/entity/Entity.java ++++ b/net/minecraft/world/entity/Entity.java +@@ -125,9 +126,63 @@ + import net.minecraft.world.scores.Team; + import org.joml.Vector3f; + import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.Server; ++import org.bukkit.block.BlockFace; ++import org.bukkit.command.CommandSender; ++import org.bukkit.craftbukkit.event.CraftPortalEvent; ++import org.bukkit.entity.Hanging; ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.entity.Vehicle; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.hanging.HangingBreakByEntityEvent; ++import org.bukkit.event.vehicle.VehicleBlockCollisionEvent; ++import org.bukkit.event.vehicle.VehicleEnterEvent; ++import org.bukkit.event.vehicle.VehicleExitEvent; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.entity.CraftEntity; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.Pose; ++import org.bukkit.event.entity.EntityAirChangeEvent; ++import org.bukkit.event.entity.EntityCombustEvent; ++import org.bukkit.event.entity.EntityDropItemEvent; ++import org.bukkit.event.entity.EntityPortalEvent; ++import org.bukkit.event.entity.EntityPoseChangeEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++import org.bukkit.plugin.PluginManager; ++// CraftBukkit end + + public abstract class Entity implements Nameable, EntityAccess, CommandSource, ScoreHolder { + ++ // CraftBukkit start ++ private static final int CURRENT_LEVEL = 2; ++ static boolean isLevelAtLeast(CompoundTag tag, int level) { ++ return tag.contains("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; ++ } ++ ++ private CraftEntity bukkitEntity; ++ ++ public CraftEntity getBukkitEntity() { ++ if (bukkitEntity == null) { ++ bukkitEntity = CraftEntity.getEntity(level.getCraftServer(), this); ++ } ++ return bukkitEntity; ++ } ++ ++ @Override ++ public CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return getBukkitEntity(); ++ } ++ ++ // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ public int getDefaultMaxAirSupply() { ++ return TOTAL_AIR_SUPPLY; ++ } ++ // CraftBukkit end ++ + private static final Logger LOGGER = LogUtils.getLogger(); + public static final String ID_TAG = "id"; + public static final String PASSENGERS_TAG = "Passengers"; +@@ -241,9 +296,32 @@ + private int lastCrystalSoundPlayTick; + private boolean hasVisualFire; + @Nullable +- private BlockState feetBlockState; ++ private IBlockData feetBlockState; ++ // CraftBukkit start ++ public boolean persist = true; ++ public boolean visibleByDefault = true; ++ public boolean valid; ++ public boolean inWorld = false; ++ public boolean generation; ++ public int maxAirTicks = getDefaultMaxAirSupply(); // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only ++ public boolean lastDamageCancelled; // SPIGOT-5339, SPIGOT-6252, SPIGOT-6777: Keep track if the event was canceled ++ public boolean persistentInvisibility = false; ++ public BlockPos lastLavaContact; ++ // Marks an entity, that it was removed by a plugin via Entity#remove ++ // Main use case currently is for SPIGOT-7487, preventing dropping of leash when leash is removed ++ public boolean pluginRemoved = false; + +- public Entity(EntityType entitytype, Level level) { ++ public float getBukkitYaw() { ++ return this.yRot; ++ } ++ ++ public boolean isChunkLoaded() { ++ return level.hasChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); ++ } ++ // CraftBukkit end ++ ++ public Entity(EntityType entityType, Level level) { + this.id = Entity.ENTITY_COUNTER.incrementAndGet(); + this.passengers = ImmutableList.of(); + this.deltaMovement = Vec3.ZERO; +@@ -377,7 +452,13 @@ + + public void onClientRemoval() {} + +- public void setPose(Pose pose) { ++ public void setPose(EntityPose pose) { ++ // CraftBukkit start ++ if (pose == this.getPose()) { ++ return; ++ } ++ this.level.getCraftServer().getPluginManager().callEvent(new EntityPoseChangeEvent(this.getBukkitEntity(), Pose.values()[pose.ordinal()])); ++ // CraftBukkit end + this.entityData.set(Entity.DATA_POSE, pose); + } + +@@ -401,9 +482,36 @@ + return Mth.lengthSquared(d2, d4) < Mth.square(d0) && Mth.square(d3) < Mth.square(d1); + } + +- protected void setRot(float f, float f1) { +- this.setYRot(f % 360.0F); +- this.setXRot(f1 % 360.0F); ++ protected void setRot(float yRot, float xRot) { ++ // CraftBukkit start - yaw was sometimes set to NaN, so we need to set it back to 0 ++ if (Float.isNaN(yRot)) { ++ yRot = 0; ++ } ++ ++ if (yRot == Float.POSITIVE_INFINITY || yRot == Float.NEGATIVE_INFINITY) { ++ if (this instanceof ServerPlayer) { ++ this.level.getCraftServer().getLogger().warning(this.getScoreboardName() + " was caught trying to crash the server with an invalid yaw"); ++ ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Infinite yaw (Hacking?)"); ++ } ++ yRot = 0; ++ } ++ ++ // pitch was sometimes set to NaN, so we need to set it back to 0 ++ if (Float.isNaN(xRot)) { ++ xRot = 0; ++ } ++ ++ if (xRot == Float.POSITIVE_INFINITY || xRot == Float.NEGATIVE_INFINITY) { ++ if (this instanceof ServerPlayer) { ++ this.level.getCraftServer().getLogger().warning(this.getScoreboardName() + " was caught trying to crash the server with an invalid pitch"); ++ ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Infinite pitch (Hacking?)"); ++ } ++ xRot = 0; ++ } ++ // CraftBukkit end ++ ++ this.setYRot(yRot % 360.0F); ++ this.setXRot(xRot % 360.0F); + } + + public final void setPos(Vec3 vec3) { +@@ -443,6 +551,15 @@ + this.baseTick(); + } + ++ // CraftBukkit start ++ public void postTick() { ++ // No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle ++ if (!(this instanceof ServerPlayer)) { ++ this.handleNetherPortal(); ++ } ++ } ++ // CraftBukkit end ++ + public void baseTick() { + this.level().getProfiler().push("entityBaseTick"); + this.feetBlockState = null; +@@ -457,7 +574,7 @@ + this.walkDistO = this.walkDist; + this.xRotO = this.getXRot(); + this.yRotO = this.getYRot(); +- this.handleNetherPortal(); ++ if (this instanceof ServerPlayer) this.handleNetherPortal(); // CraftBukkit - // Moved up to postTick + if (this.canSpawnSprintParticle()) { + this.spawnSprintParticle(); + } +@@ -492,6 +609,10 @@ + if (this.isInLava()) { + this.lavaHurt(); + this.fallDistance *= 0.5F; ++ // CraftBukkit start ++ } else { ++ this.lastLavaContact = null; ++ // CraftBukkit end + } + + this.checkBelowWorld(); +@@ -543,15 +664,48 @@ + + public void lavaHurt() { + if (!this.fireImmune()) { +- this.setSecondsOnFire(15); ++ // CraftBukkit start - Fallen in lava TODO: this event spams! ++ if (this instanceof net.minecraft.world.entity.LivingEntity && remainingFireTicks <= 0) { ++ // not on fire yet ++ org.bukkit.block.Block damager = (lastLavaContact == null) ? null : org.bukkit.craftbukkit.block.CraftBlock.at(level, lastLavaContact); ++ org.bukkit.entity.Entity damagee = this.getBukkitEntity(); ++ EntityCombustEvent combustEvent = new org.bukkit.event.entity.EntityCombustByBlockEvent(damager, damagee, 15); ++ this.level.getCraftServer().getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ this.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ } else { ++ // This will be called every single tick the entity is in lava, so don't throw an event ++ this.setSecondsOnFire(15, false); ++ } ++ CraftEventFactory.blockDamage = (lastLavaContact) == null ? null : org.bukkit.craftbukkit.block.CraftBlock.at(level, lastLavaContact); + if (this.hurt(this.damageSources().lava(), 4.0F)) { + this.playSound(SoundEvents.GENERIC_BURN, 0.4F, 2.0F + this.random.nextFloat() * 0.4F); + } ++ CraftEventFactory.blockDamage = null; ++ // CraftBukkit end - we also don't throw an event unless the object in lava is living, to save on some event calls + + } + } + +- public void setSecondsOnFire(int i) { ++ public void setSecondsOnFire(int seconds) { ++ // CraftBukkit start ++ this.setSecondsOnFire(seconds, true); ++ } ++ ++ public void setSecondsOnFire(int i, boolean callEvent) { ++ if (callEvent) { ++ EntityCombustEvent event = new EntityCombustEvent(this.getBukkitEntity(), i); ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ i = event.getDuration(); ++ } ++ // CraftBukkit end + int j = i * 20; + + if (this instanceof LivingEntity) { +@@ -702,6 +856,28 @@ + block.updateEntityAfterFallOn(this.level(), this); + } + ++ // CraftBukkit start ++ if (horizontalCollision && getBukkitEntity() instanceof Vehicle) { ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ org.bukkit.block.Block bl = this.level.getWorld().getBlockAt(Mth.floor(this.getX()), Mth.floor(this.getY()), Mth.floor(this.getZ())); ++ ++ if (pos.x > vec3d1.x) { ++ bl = bl.getRelative(BlockFace.EAST); ++ } else if (pos.x < vec3d1.x) { ++ bl = bl.getRelative(BlockFace.WEST); ++ } else if (pos.z > vec3d1.z) { ++ bl = bl.getRelative(BlockFace.SOUTH); ++ } else if (pos.z < vec3d1.z) { ++ bl = bl.getRelative(BlockFace.NORTH); ++ } ++ ++ if (!bl.getType().isAir()) { ++ VehicleBlockCollisionEvent event = new VehicleBlockCollisionEvent(vehicle, bl); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ } ++ } ++ // CraftBukkit end ++ + if (this.onGround()) { + block.stepOn(this.level(), blockpos, blockstate, this); + } +@@ -1029,6 +1205,20 @@ + return SoundEvents.GENERIC_SPLASH; + } + ++ // CraftBukkit start - Add delegate methods ++ public SoundEvent getSwimSound0() { ++ return getSwimSound(); ++ } ++ ++ public SoundEvent getSwimSplashSound0() { ++ return getSwimSplashSound(); ++ } ++ ++ public SoundEvent getSwimHighSpeedSplashSound0() { ++ return getSwimHighSpeedSplashSound(); ++ } ++ // CraftBukkit end ++ + protected void checkInsideBlocks() { + AABB aabb = this.getBoundingBox(); + BlockPos blockpos = BlockPos.containing(aabb.minX + 1.0E-7D, aabb.minY + 1.0E-7D, aabb.minZ + 1.0E-7D); +@@ -1443,6 +1633,7 @@ + this.yo = d1; + this.zo = d4; + this.setPos(d3, d1, d4); ++ if (valid) level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit + } + + public void moveTo(Vec3 vec3) { +@@ -1637,9 +1828,15 @@ + return false; + } + +- public void awardKillScore(Entity entity, int i, DamageSource damagesource) { +- if (entity instanceof ServerPlayer) { +- CriteriaTriggers.ENTITY_KILLED_PLAYER.trigger((ServerPlayer) entity, this, damagesource); ++ // CraftBukkit start - collidable API ++ public boolean canCollideWithBukkit(Entity entity) { ++ return isPushable(); ++ } ++ // CraftBukkit end ++ ++ public void awardKillScore(Entity killed, int scoreValue, DamageSource source) { ++ if (killed instanceof ServerPlayer) { ++ CriteriaTriggers.ENTITY_KILLED_PLAYER.trigger((ServerPlayer) killed, this, source); + } + + } +@@ -1664,17 +1861,23 @@ + return d0 < d1 * d1; + } + +- public boolean saveAsPassenger(CompoundTag compoundtag) { ++ public boolean saveAsPassenger(CompoundTag compound) { ++ // CraftBukkit start - allow excluding certain data when saving ++ return saveAsPassenger(compound, true); ++ } ++ ++ public boolean saveAsPassenger(CompoundTag nbttagcompound, boolean includeAll) { ++ // CraftBukkit end + if (this.removalReason != null && !this.removalReason.shouldSave()) { + return false; + } else { + String s = this.getEncodeId(); + +- if (s == null) { ++ if (!this.persist || s == null) { // CraftBukkit - persist flag + return false; + } else { +- compoundtag.putString("id", s); +- this.saveWithoutId(compoundtag); ++ nbttagcompound.putString("id", s); ++ this.saveWithoutId(nbttagcompound, includeAll); // CraftBukkit - pass on includeAll + return true; + } + } +@@ -1684,13 +1887,23 @@ + return this.isPassenger() ? false : this.saveAsPassenger(compoundtag); + } + +- public CompoundTag saveWithoutId(CompoundTag compoundtag) { ++ public CompoundTag saveWithoutId(CompoundTag compound) { ++ // CraftBukkit start - allow excluding certain data when saving ++ return saveWithoutId(compound, true); ++ } ++ ++ public CompoundTag saveWithoutId(CompoundTag nbttagcompound, boolean includeAll) { ++ // CraftBukkit end + try { +- if (this.vehicle != null) { +- compoundtag.put("Pos", this.newDoubleList(this.vehicle.getX(), this.getY(), this.vehicle.getZ())); +- } else { +- compoundtag.put("Pos", this.newDoubleList(this.getX(), this.getY(), this.getZ())); ++ // CraftBukkit start - selectively save position ++ if (includeAll) { ++ if (this.vehicle != null) { ++ nbttagcompound.put("Pos", this.newDoubleList(this.vehicle.getX(), this.getY(), this.vehicle.getZ())); ++ } else { ++ nbttagcompound.put("Pos", this.newDoubleList(this.getX(), this.getY(), this.getZ())); ++ } + } ++ // CraftBukkit end + + Vec3 vec3 = this.getDeltaMovement(); + +@@ -1705,10 +1909,52 @@ + compoundtag.putUUID("UUID", this.getUUID()); + Component component = this.getCustomName(); + +- if (component != null) { +- compoundtag.putString("CustomName", Component.Serializer.toJson(component)); ++ // CraftBukkit start - Checking for NaN pitch/yaw and resetting to zero ++ // TODO: make sure this is the best way to address this. ++ if (Float.isNaN(this.yRot)) { ++ this.yRot = 0; + } + ++ if (Float.isNaN(this.xRot)) { ++ this.xRot = 0; ++ } ++ // CraftBukkit end ++ ++ nbttagcompound.put("Rotation", this.newFloatList(this.getYRot(), this.getXRot())); ++ nbttagcompound.putFloat("FallDistance", this.fallDistance); ++ nbttagcompound.putShort("Fire", (short) this.remainingFireTicks); ++ nbttagcompound.putShort("Air", (short) this.getAirSupply()); ++ nbttagcompound.putBoolean("OnGround", this.onGround()); ++ nbttagcompound.putBoolean("Invulnerable", this.invulnerable); ++ nbttagcompound.putInt("PortalCooldown", this.portalCooldown); ++ // CraftBukkit start - selectively save uuid and world ++ if (includeAll) { ++ nbttagcompound.putUUID("UUID", this.getUUID()); ++ // PAIL: Check above UUID reads 1.8 properly, ie: UUIDMost / UUIDLeast ++ nbttagcompound.putLong("WorldUUIDLeast", ((ServerLevel) this.level).getWorld().getUID().getLeastSignificantBits()); ++ nbttagcompound.putLong("WorldUUIDMost", ((ServerLevel) this.level).getWorld().getUID().getMostSignificantBits()); ++ } ++ nbttagcompound.putInt("Bukkit.updateLevel", CURRENT_LEVEL); ++ if (!this.persist) { ++ nbttagcompound.putBoolean("Bukkit.persist", this.persist); ++ } ++ if (!this.visibleByDefault) { ++ nbttagcompound.putBoolean("Bukkit.visibleByDefault", this.visibleByDefault); ++ } ++ if (this.persistentInvisibility) { ++ nbttagcompound.putBoolean("Bukkit.invisible", this.persistentInvisibility); ++ } ++ // SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ if (maxAirTicks != getDefaultMaxAirSupply()) { ++ nbttagcompound.putInt("Bukkit.MaxAirSupply", getMaxAirSupply()); ++ } ++ // CraftBukkit end ++ Component ichatbasecomponent = this.getCustomName(); ++ ++ if (ichatbasecomponent != null) { ++ nbttagcompound.putString("CustomName", Component.Serializer.toJson(ichatbasecomponent)); ++ } ++ + if (this.isCustomNameVisible()) { + compoundtag.putBoolean("CustomNameVisible", this.isCustomNameVisible()); + } +@@ -1751,7 +1997,7 @@ + compoundtag.put("Tags", listtag); + } + +- this.addAdditionalSaveData(compoundtag); ++ this.addAdditionalSaveData(nbttagcompound, includeAll); // CraftBukkit - pass on includeAll + if (this.isVehicle()) { + listtag = new ListTag(); + iterator = this.getPassengers().iterator(); +@@ -1760,8 +2006,8 @@ + Entity entity = (Entity) iterator.next(); + CompoundTag compoundtag1 = new CompoundTag(); + +- if (entity.saveAsPassenger(compoundtag1)) { +- listtag.add(compoundtag1); ++ if (entity.saveAsPassenger(nbttagcompound1, includeAll)) { // CraftBukkit - pass on includeAll ++ nbttaglist.add(nbttagcompound1); + } + } + +@@ -1770,7 +2016,12 @@ + } + } + +- return compoundtag; ++ // CraftBukkit start - stores eventually existing bukkit values ++ if (this.bukkitEntity != null) { ++ this.bukkitEntity.storeBukkitValues(nbttagcompound); ++ } ++ // CraftBukkit end ++ return nbttagcompound; + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT"); + CrashReportCategory crashreportcategory = crashreport.addCategory("Entity being saved"); +@@ -1853,6 +2104,45 @@ + } else { + throw new IllegalStateException("Entity has invalid position"); + } ++ ++ // CraftBukkit start ++ this.persist = !compound.contains("Bukkit.persist") || compound.getBoolean("Bukkit.persist"); ++ this.visibleByDefault = !compound.contains("Bukkit.visibleByDefault") || compound.getBoolean("Bukkit.visibleByDefault"); ++ // SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ if (compound.contains("Bukkit.MaxAirSupply")) { ++ maxAirTicks = compound.getInt("Bukkit.MaxAirSupply"); ++ } ++ // CraftBukkit end ++ ++ // CraftBukkit start - Reset world ++ if (this instanceof ServerPlayer) { ++ Server server = Bukkit.getServer(); ++ org.bukkit.World bworld = null; ++ ++ // TODO: Remove World related checks, replaced with WorldUID ++ String worldName = compound.getString("world"); ++ ++ if (compound.contains("WorldUUIDMost") && compound.contains("WorldUUIDLeast")) { ++ UUID uid = new UUID(compound.getLong("WorldUUIDMost"), compound.getLong("WorldUUIDLeast")); ++ bworld = server.getWorld(uid); ++ } else { ++ bworld = server.getWorld(worldName); ++ } ++ ++ if (bworld == null) { ++ bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getLevel(Level.OVERWORLD).getWorld(); ++ } ++ ++ ((ServerPlayer) this).setLevel(bworld == null ? null : ((CraftWorld) bworld).getHandle()); ++ } ++ this.getBukkitEntity().readBukkitValues(compound); ++ if (compound.contains("Bukkit.invisible")) { ++ boolean bukkitInvisible = compound.getBoolean("Bukkit.invisible"); ++ this.setInvisible(bukkitInvisible); ++ this.persistentInvisibility = bukkitInvisible; ++ } ++ // CraftBukkit end ++ + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT"); + CrashReportCategory crashreportcategory = crashreport.addCategory("Entity being loaded"); +@@ -1874,6 +2164,12 @@ + return entitytype.canSerialize() && resourcelocation != null ? resourcelocation.toString() : null; + } + ++ // CraftBukkit start - allow excluding certain data when saving ++ protected void addAdditionalSaveData(CompoundTag nbttagcompound, boolean includeAll) { ++ addAdditionalSaveData(nbttagcompound); ++ } ++ // CraftBukkit end ++ + protected abstract void readAdditionalSaveData(CompoundTag compound); + + protected abstract void addAdditionalSaveData(CompoundTag compound); +@@ -1928,11 +2224,24 @@ + } else if (this.level().isClientSide) { + return null; + } else { +- ItemEntity itementity = new ItemEntity(this.level(), this.getX(), this.getY() + (double) f, this.getZ(), itemstack); ++ // CraftBukkit start - Capture drops for death event ++ if (this instanceof net.minecraft.world.entity.LivingEntity && !((net.minecraft.world.entity.LivingEntity) this).forceDrops) { ++ ((net.minecraft.world.entity.LivingEntity) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(stack)); ++ return null; ++ } ++ // CraftBukkit end ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY() + (double) offsetY, this.getZ(), stack); + +- itementity.setDefaultPickUpDelay(); +- this.level().addFreshEntity(itementity); +- return itementity; ++ entityitem.setDefaultPickUpDelay(); ++ // CraftBukkit start ++ EntityDropItemEvent event = new EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return null; ++ } ++ // CraftBukkit end ++ this.level().addFreshEntity(entityitem); ++ return entityitem; + } + } + +@@ -2028,6 +2337,18 @@ + if (!flag && (!this.canRide(entity) || !entity.canAddPassenger(this))) { + return false; + } else { ++ // CraftBukkit start ++ if (vehicle.getBukkitEntity() instanceof Vehicle && this.getBukkitEntity() instanceof LivingEntity) { ++ VehicleEnterEvent event = new VehicleEnterEvent((Vehicle) vehicle.getBukkitEntity(), this.getBukkitEntity()); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ if (event.isCancelled()) { ++ return false; ++ } ++ } ++ // CraftBukkit end + if (this.isPassenger()) { + this.stopRiding(); + } +@@ -2061,7 +2382,7 @@ + Entity entity = this.vehicle; + + this.vehicle = null; +- entity.removePassenger(this); ++ if (!entity.removePassenger(this)) this.vehicle = entity; // CraftBukkit + } + + } +@@ -2092,10 +2413,29 @@ + } + } + +- protected void removePassenger(Entity entity) { ++ protected boolean removePassenger(Entity entity) { // CraftBukkit + if (entity.getVehicle() == this) { + throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); + } else { ++ // CraftBukkit start ++ CraftEntity craft = (CraftEntity) entity.getBukkitEntity().getVehicle(); ++ Entity orig = craft == null ? null : craft.getHandle(); ++ if (getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { ++ VehicleExitEvent event = new VehicleExitEvent( ++ (Vehicle) getBukkitEntity(), ++ (LivingEntity) entity.getBukkitEntity() ++ ); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ CraftEntity craftn = (CraftEntity) entity.getBukkitEntity().getVehicle(); ++ Entity n = craftn == null ? null : craftn.getHandle(); ++ if (event.isCancelled() || n != orig) { ++ return false; ++ } ++ } ++ // CraftBukkit end + if (this.passengers.size() == 1 && this.passengers.get(0) == entity) { + this.passengers = ImmutableList.of(); + } else { +@@ -2107,6 +2447,7 @@ + entity.boardingCooldown = 60; + this.gameEvent(GameEvent.ENTITY_DISMOUNT, entity); + } ++ return true; // CraftBukkit + } + + protected boolean canAddPassenger(Entity entity) { +@@ -2192,15 +2533,21 @@ + ServerLevel serverlevel = (ServerLevel) this.level(); + + if (this.isInsidePortal) { +- MinecraftServer minecraftserver = serverlevel.getServer(); +- ResourceKey resourcekey = this.level().dimension() == Level.NETHER ? Level.OVERWORLD : Level.NETHER; +- ServerLevel serverlevel1 = minecraftserver.getLevel(resourcekey); ++ MinecraftServer minecraftserver = worldserver.getServer(); ++ ResourceKey resourcekey = this.level().getTypeKey() == LevelStem.NETHER ? Level.OVERWORLD : Level.NETHER; // CraftBukkit ++ ServerLevel worldserver1 = minecraftserver.getLevel(resourcekey); + +- if (serverlevel1 != null && minecraftserver.isNetherEnabled() && !this.isPassenger() && this.portalTime++ >= i) { ++ if (true && !this.isPassenger() && this.portalTime++ >= i) { // CraftBukkit + this.level().getProfiler().push("portal"); + this.portalTime = i; + this.setPortalCooldown(); +- this.changeDimension(serverlevel1); ++ // CraftBukkit start ++ if (this instanceof ServerPlayer) { ++ ((ServerPlayer) this).changeDimension(worldserver1, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL); ++ } else { ++ this.changeDimension(worldserver1); ++ } ++ // CraftBukkit end + this.level().getProfiler().pop(); + } + +@@ -2323,8 +2670,15 @@ + return this.isVisuallySwimming() && !this.isInWater(); + } + +- public void setSwimming(boolean flag) { +- this.setSharedFlag(4, flag); ++ public void setSwimming(boolean swimming) { ++ // CraftBukkit start ++ if (valid && this.isSwimming() != swimming && this instanceof net.minecraft.world.entity.LivingEntity) { ++ if (CraftEventFactory.callToggleSwimEvent((net.minecraft.world.entity.LivingEntity) this, swimming).isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ this.setSharedFlag(4, swimming); + } + + public final boolean hasGlowingTag() { +@@ -2373,8 +2727,12 @@ + return this.getTeam() != null ? this.getTeam().isAlliedTo(team) : false; + } + +- public void setInvisible(boolean flag) { +- this.setSharedFlag(5, flag); ++ // CraftBukkit - start ++ public void setInvisible(boolean invisible) { ++ if (!this.persistentInvisibility) { // Prevent Minecraft from removing our invisibility flag ++ this.setSharedFlag(5, invisible); ++ } ++ // CraftBukkit - end + } + + protected boolean getSharedFlag(int i) { +@@ -2393,15 +2751,26 @@ + } + + public int getMaxAirSupply() { +- return 300; ++ return maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() + } + + public int getAirSupply() { + return (Integer) this.entityData.get(Entity.DATA_AIR_SUPPLY_ID); + } + +- public void setAirSupply(int i) { +- this.entityData.set(Entity.DATA_AIR_SUPPLY_ID, i); ++ public void setAirSupply(int air) { ++ // CraftBukkit start ++ EntityAirChangeEvent event = new EntityAirChangeEvent(this.getBukkitEntity(), air); ++ // Suppress during worldgen ++ if (this.valid) { ++ event.getEntity().getServer().getPluginManager().callEvent(event); ++ } ++ if (event.isCancelled() && this.getAirSupply() != air) { ++ this.entityData.markDirty(Entity.DATA_AIR_SUPPLY_ID); ++ return; ++ } ++ this.entityData.set(Entity.DATA_AIR_SUPPLY_ID, event.getAmount()); ++ // CraftBukkit end + } + + public int getTicksFrozen() { +@@ -2428,11 +2797,41 @@ + + public void thunderHit(ServerLevel serverlevel, LightningBolt lightningbolt) { + this.setRemainingFireTicks(this.remainingFireTicks + 1); ++ // CraftBukkit start ++ final org.bukkit.entity.Entity thisBukkitEntity = this.getBukkitEntity(); ++ final org.bukkit.entity.Entity stormBukkitEntity = lightning.getBukkitEntity(); ++ final PluginManager pluginManager = Bukkit.getPluginManager(); ++ // CraftBukkit end ++ + if (this.remainingFireTicks == 0) { +- this.setSecondsOnFire(8); ++ // CraftBukkit start - Call a combust event when lightning strikes ++ EntityCombustByEntityEvent entityCombustEvent = new EntityCombustByEntityEvent(stormBukkitEntity, thisBukkitEntity, 8); ++ pluginManager.callEvent(entityCombustEvent); ++ if (!entityCombustEvent.isCancelled()) { ++ this.setSecondsOnFire(entityCombustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + +- this.hurt(this.damageSources().lightningBolt(), 5.0F); ++ // CraftBukkit start ++ if (thisBukkitEntity instanceof Hanging) { ++ HangingBreakByEntityEvent hangingEvent = new HangingBreakByEntityEvent((Hanging) thisBukkitEntity, stormBukkitEntity); ++ pluginManager.callEvent(hangingEvent); ++ ++ if (hangingEvent.isCancelled()) { ++ return; ++ } ++ } ++ ++ if (this.fireImmune()) { ++ return; ++ } ++ CraftEventFactory.entityDamage = lightning; ++ if (!this.hurt(this.damageSources().lightningBolt(), 5.0F)) { ++ CraftEventFactory.entityDamage = null; ++ return; ++ } ++ // CraftBukkit end + } + + public void onAboveBubbleCol(boolean flag) { +@@ -2598,27 +2995,62 @@ + } + + @Nullable +- public Entity changeDimension(ServerLevel serverlevel) { ++ public Entity changeDimension(ServerLevel destination) { ++ // CraftBukkit start ++ return teleportTo(destination, null); ++ } ++ ++ @Nullable ++ public Entity teleportTo(ServerLevel worldserver, Vec3 location) { ++ // CraftBukkit end + if (this.level() instanceof ServerLevel && !this.isRemoved()) { + this.level().getProfiler().push("changeDimension"); +- this.unRide(); ++ // CraftBukkit start ++ // this.unRide(); ++ if (worldserver == null) { ++ return null; ++ } ++ // CraftBukkit end + this.level().getProfiler().push("reposition"); +- PortalInfo portalinfo = this.findDimensionEntryPoint(serverlevel); ++ PortalInfo shapedetectorshape = (location == null) ? this.findDimensionEntryPoint(worldserver) : new PortalInfo(new Vec3(location.x(), location.y(), location.z()), Vec3.ZERO, this.yRot, this.xRot, worldserver, null); // CraftBukkit + + if (portalinfo == null) { + return null; + } else { ++ // CraftBukkit start ++ worldserver = shapedetectorshape.world; ++ if (worldserver == level) { ++ // SPIGOT-6782: Just move the entity if a plugin changed the world to the one the entity is already in ++ moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, shapedetectorshape.xRot); ++ setDeltaMovement(shapedetectorshape.speed); ++ return this; ++ } ++ this.unRide(); ++ // CraftBukkit end ++ + this.level().getProfiler().popPush("reloading"); + Entity entity = this.getType().create(serverlevel); + + if (entity != null) { + entity.restoreFrom(this); +- entity.moveTo(portalinfo.pos.x, portalinfo.pos.y, portalinfo.pos.z, portalinfo.yRot, entity.getXRot()); +- entity.setDeltaMovement(portalinfo.speed); +- serverlevel.addDuringTeleport(entity); +- if (serverlevel.dimension() == Level.END) { +- ServerLevel.makeObsidianPlatform(serverlevel); ++ entity.moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, entity.getXRot()); ++ entity.setDeltaMovement(shapedetectorshape.speed); ++ // CraftBukkit start - Don't spawn the new entity if the current entity isn't spawned ++ if (this.inWorld) { ++ worldserver.addDuringTeleport(entity); ++ if (worldserver.getTypeKey() == LevelStem.END) { // CraftBukkit ++ ServerLevel.makeObsidianPlatform(worldserver, this); // CraftBukkit ++ } + } ++ // CraftBukkit end ++ // CraftBukkit start - Forward the CraftEntity to the new entity ++ this.getBukkitEntity().setHandle(entity); ++ entity.bukkitEntity = this.getBukkitEntity(); ++ ++ if (this instanceof Mob) { ++ ((Mob) this).dropLeash(true, false); // Unleash to prevent duping of leads. ++ } ++ // CraftBukkit end + } + + this.removeAfterChangingDimensions(); +@@ -2638,24 +3070,38 @@ + } + + @Nullable +- protected PortalInfo findDimensionEntryPoint(ServerLevel serverlevel) { +- boolean flag = this.level().dimension() == Level.END && serverlevel.dimension() == Level.OVERWORLD; +- boolean flag1 = serverlevel.dimension() == Level.END; ++ protected PortalInfo findDimensionEntryPoint(ServerLevel destination) { ++ // CraftBukkit start ++ if (destination == null) { ++ return null; ++ } ++ boolean flag = this.level().getTypeKey() == LevelStem.END && destination.getTypeKey() == LevelStem.OVERWORLD; // fromEndToOverworld ++ boolean flag1 = destination.getTypeKey() == LevelStem.END; // targetIsEnd ++ // CraftBukkit end + + if (!flag && !flag1) { +- boolean flag2 = serverlevel.dimension() == Level.NETHER; ++ boolean flag2 = destination.getTypeKey() == LevelStem.NETHER; // CraftBukkit + +- if (this.level().dimension() != Level.NETHER && !flag2) { ++ if (this.level().getTypeKey() != LevelStem.NETHER && !flag2) { // CraftBukkit + return null; + } else { +- WorldBorder worldborder = serverlevel.getWorldBorder(); +- double d0 = DimensionType.getTeleportationScale(this.level().dimensionType(), serverlevel.dimensionType()); +- BlockPos blockpos = worldborder.clampToBounds(this.getX() * d0, this.getY(), this.getZ() * d0); ++ WorldBorder worldborder = destination.getWorldBorder(); ++ double d0 = DimensionType.getTeleportationScale(this.level().dimensionType(), destination.dimensionType()); ++ BlockPos blockposition = worldborder.clampToBounds(this.getX() * d0, this.getY(), this.getZ() * d0); ++ // CraftBukkit start ++ CraftPortalEvent event = callPortalEvent(this, destination, new Vec3(blockposition.getX(), blockposition.getY(), blockposition.getZ()), PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, flag2 ? 16 : 128, 16); ++ if (event == null) { ++ return null; ++ } ++ final ServerLevel worldserverFinal = destination = ((CraftWorld) event.getTo().getWorld()).getHandle(); ++ worldborder = worldserverFinal.getWorldBorder(); ++ blockposition = worldborder.clampToBounds(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); + +- return (PortalInfo) this.getExitPortal(serverlevel, blockpos, flag2, worldborder).map((blockutil_foundrectangle) -> { +- BlockState blockstate = this.level().getBlockState(this.portalEntrancePos); +- Direction.Axis direction_axis; +- Vec3 vec3; ++ return (PortalInfo) this.getExitPortal(destination, blockposition, flag2, worldborder, event.getSearchRadius(), event.getCanCreatePortal(), event.getCreationRadius()).map((blockutil_rectangle) -> { ++ // CraftBukkit end ++ IBlockData iblockdata = this.level().getBlockState(this.portalEntrancePos); ++ Direction.Axis enumdirection_enumaxis; ++ Vec3 vec3d; + + if (blockstate.hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) { + direction_axis = (Direction.Axis) blockstate.getValue(BlockStateProperties.HORIZONTAL_AXIS); +@@ -2669,8 +3115,8 @@ + vec3 = new Vec3(0.5D, 0.0D, 0.0D); + } + +- return PortalShape.createPortalInfo(serverlevel, blockutil_foundrectangle, direction_axis, vec3, this, this.getDeltaMovement(), this.getYRot(), this.getXRot()); +- }).orElse((Object) null); ++ return PortalShape.createPortalInfo(worldserverFinal, blockutil_rectangle, enumdirection_enumaxis, vec3d, this, this.getDeltaMovement(), this.getYRot(), this.getXRot(), event); // CraftBukkit ++ }).orElse(null); // CraftBukkit - decompile error + } + } else { + BlockPos blockpos1; +@@ -2680,8 +3126,14 @@ + } else { + blockpos1 = serverlevel.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, serverlevel.getSharedSpawnPos()); + } ++ // CraftBukkit start ++ CraftPortalEvent event = callPortalEvent(this, destination, new Vec3(blockposition1.getX() + 0.5D, blockposition1.getY(), blockposition1.getZ() + 0.5D), PlayerTeleportEvent.TeleportCause.END_PORTAL, 0, 0); ++ if (event == null) { ++ return null; ++ } + +- return new PortalInfo(new Vec3((double) blockpos1.getX() + 0.5D, (double) blockpos1.getY(), (double) blockpos1.getZ() + 0.5D), this.getDeltaMovement(), this.getYRot(), this.getXRot()); ++ return new PortalInfo(new Vec3(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()), this.getDeltaMovement(), this.getYRot(), this.getXRot(), ((CraftWorld) event.getTo().getWorld()).getHandle(), event); ++ // CraftBukkit end + } + } + +@@ -2689,10 +3141,25 @@ + return PortalShape.getRelativePosition(blockutil_foundrectangle, direction_axis, this.position(), this.getDimensions(this.getPose())); + } + +- protected Optional getExitPortal(ServerLevel serverlevel, BlockPos blockpos, boolean flag, WorldBorder worldborder) { +- return serverlevel.getPortalForcer().findPortalAround(blockpos, flag, worldborder); ++ // CraftBukkit start ++ protected CraftPortalEvent callPortalEvent(Entity entity, ServerLevel exitWorldServer, Vec3 exitPosition, PlayerTeleportEvent.TeleportCause cause, int searchRadius, int creationRadius) { ++ org.bukkit.entity.Entity bukkitEntity = entity.getBukkitEntity(); ++ Location enter = bukkitEntity.getLocation(); ++ Location exit = CraftLocation.toBukkit(exitPosition, exitWorldServer.getWorld()); ++ ++ EntityPortalEvent event = new EntityPortalEvent(bukkitEntity, enter, exit, searchRadius); ++ event.getEntity().getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null || !entity.isAlive()) { ++ return null; ++ } ++ return new CraftPortalEvent(event); + } + ++ protected Optional getExitPortal(ServerLevel worldserver, BlockPos blockposition, boolean flag, WorldBorder worldborder, int searchRadius, boolean canCreatePortal, int createRadius) { ++ return worldserver.getPortalForcer().findPortalAround(blockposition, worldborder, searchRadius); ++ // CraftBukkit end ++ } ++ + public boolean canChangeDimensions() { + return !this.isPassenger() && !this.isVehicle(); + } +@@ -2816,7 +3278,13 @@ + } + } + +- public boolean teleportTo(ServerLevel serverlevel, double d0, double d1, double d2, Set set, float f, float f1) { ++ // CraftBukkit start ++ public boolean teleportTo(ServerLevel worldserver, double d0, double d1, double d2, Set set, float f, float f1, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { ++ return this.teleportTo(worldserver, d0, d1, d2, set, f, f1); ++ } ++ // CraftBukkit end ++ ++ public boolean teleportTo(ServerLevel level, double x, double d1, double y, Set set, float z, float f1) { + float f2 = Mth.clamp(f1, -90.0F, 90.0F); + + if (serverlevel == this.level()) { +@@ -2835,7 +3303,11 @@ + entity.moveTo(d0, d1, d2, f, f2); + entity.setYHeadRot(f); + this.setRemoved(Entity.RemovalReason.CHANGED_DIMENSION); +- serverlevel.addDuringTeleport(entity); ++ // CraftBukkit start - Don't spawn the new entity if the current entity isn't spawned ++ if (inWorld) { ++ level.addDuringTeleport(entity); ++ } ++ // CraftBukkit end + } + + return true; +@@ -2941,8 +3412,27 @@ + return this.getBoundingBox(); + } + +- public final void setBoundingBox(AABB aabb) { +- this.bb = aabb; ++ public final void setBoundingBox(AABB bb) { ++ // CraftBukkit start - block invalid bounding boxes ++ double minX = bb.minX, ++ minY = bb.minY, ++ minZ = bb.minZ, ++ maxX = bb.maxX, ++ maxY = bb.maxY, ++ maxZ = bb.maxZ; ++ double len = bb.maxX - bb.minX; ++ if (len < 0) maxX = minX; ++ if (len > 64) maxX = minX + 64.0; ++ ++ len = bb.maxY - bb.minY; ++ if (len < 0) maxY = minY; ++ if (len > 64) maxY = minY + 64.0; ++ ++ len = bb.maxZ - bb.minZ; ++ if (len < 0) maxZ = minZ; ++ if (len > 64) maxZ = minZ + 64.0; ++ this.bb = new AABB(minX, minY, minZ, maxX, maxY, maxZ); ++ // CraftBukkit end + } + + protected float getEyeHeight(Pose pose, EntityDimensions entitydimensions) { +@@ -3263,6 +3747,11 @@ + vec3 = vec3.add(vec31); + ++k1; + } ++ // CraftBukkit start - store last lava contact location ++ if (fluidTag == FluidTags.LAVA) { ++ this.lastLavaContact = blockposition_mutableblockposition.immutable(); ++ } ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/EntitySelector.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/EntitySelector.java.patch new file mode 100644 index 0000000000..59a9208de6 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/EntitySelector.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/entity/EntitySelector.java ++++ b/net/minecraft/world/entity/EntitySelector.java +@@ -43,8 +43,8 @@ + PlayerTeam playerteam = entity.getTeam(); + Team.CollisionRule team_collisionrule = playerteam == null ? Team.CollisionRule.ALWAYS : playerteam.getCollisionRule(); + +- return (Predicate) (team_collisionrule == Team.CollisionRule.NEVER ? Predicates.alwaysFalse() : EntitySelector.NO_SPECTATORS.and((entity1) -> { +- if (!entity1.isPushable()) { ++ return (Predicate) (scoreboardteambase_enumteampush == Team.CollisionRule.NEVER ? Predicates.alwaysFalse() : EntitySelector.NO_SPECTATORS.and((entity1) -> { ++ if (!entity1.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(entity1)) { // CraftBukkit - collidable API + return false; + } else if (entity.level().isClientSide && (!(entity1 instanceof Player) || !((Player) entity1).isLocalPlayer())) { + return false; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/EntityType.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/EntityType.java.patch new file mode 100644 index 0000000000..6762ded21c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/EntityType.java.patch @@ -0,0 +1,87 @@ +--- a/net/minecraft/world/entity/EntityType.java ++++ b/net/minecraft/world/entity/EntityType.java +@@ -170,7 +171,7 @@ + private static final float MAGIC_HORSE_WIDTH = 1.3964844F; + private static final int DISPLAY_TRACKING_RANGE = 10; + public static final EntityType ALLAY = register("allay", EntityType.Builder.of(Allay::new, MobCategory.CREATURE).sized(0.35F, 0.6F).clientTrackingRange(8).updateInterval(2)); +- public static final EntityType AREA_EFFECT_CLOUD = register("area_effect_cloud", EntityType.Builder.of(AreaEffectCloud::new, MobCategory.MISC).fireImmune().sized(6.0F, 0.5F).clientTrackingRange(10).updateInterval(Integer.MAX_VALUE)); ++ public static final EntityType AREA_EFFECT_CLOUD = register("area_effect_cloud", EntityType.Builder.of(AreaEffectCloud::new, MobCategory.MISC).fireImmune().sized(6.0F, 0.5F).clientTrackingRange(10).updateInterval(10)); // CraftBukkit - SPIGOT-3729: track area effect clouds + public static final EntityType ARMOR_STAND = register("armor_stand", EntityType.Builder.of(ArmorStand::new, MobCategory.MISC).sized(0.5F, 1.975F).clientTrackingRange(10)); + public static final EntityType ARROW = register("arrow", EntityType.Builder.of(Arrow::new, MobCategory.MISC).sized(0.5F, 0.5F).clientTrackingRange(4).updateInterval(20)); + public static final EntityType AXOLOTL = register("axolotl", EntityType.Builder.of(Axolotl::new, MobCategory.AXOLOTLS).sized(0.75F, 0.42F).clientTrackingRange(10)); +@@ -341,10 +342,17 @@ + } + + @Nullable +- public T spawn(ServerLevel serverlevel, @Nullable ItemStack itemstack, @Nullable Player player, BlockPos blockpos, MobSpawnType mobspawntype, boolean flag, boolean flag1) { +- CompoundTag compoundtag; +- Consumer consumer; ++ public T spawn(ServerLevel serverLevel, @Nullable ItemStack stack, @Nullable Player player, BlockPos pos, EnumMobSpawn spawnType, boolean shouldOffsetY, boolean shouldOffsetYMore) { ++ // CraftBukkit start ++ return this.spawn(serverLevel, stack, player, pos, spawnType, shouldOffsetY, shouldOffsetYMore, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG); ++ } + ++ @Nullable ++ public T spawn(ServerLevel worldserver, @Nullable ItemStack itemstack, @Nullable Player entityhuman, BlockPos blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end ++ CompoundTag nbttagcompound; ++ Consumer consumer; // CraftBukkit - decompile error ++ + if (itemstack != null) { + compoundtag = itemstack.getTag(); + consumer = createDefaultStackConfig(serverlevel, itemstack, player); +@@ -354,7 +362,7 @@ + compoundtag = null; + } + +- return this.spawn(serverlevel, compoundtag, consumer, blockpos, mobspawntype, flag, flag1); ++ return this.spawn(worldserver, nbttagcompound, consumer, blockposition, enummobspawn, flag, flag1, spawnReason); // CraftBukkit + } + + public static Consumer createDefaultStackConfig(ServerLevel serverlevel, ItemStack itemstack, @Nullable Player player) { +@@ -375,22 +383,38 @@ + public static Consumer appendCustomEntityStackConfig(Consumer consumer, ServerLevel serverlevel, ItemStack itemstack, @Nullable Player player) { + CompoundTag compoundtag = itemstack.getTag(); + +- return compoundtag != null ? consumer.andThen((entity) -> { +- updateCustomEntityTag(serverlevel, player, entity, compoundtag); ++ return nbttagcompound != null ? consumer.andThen((entity) -> { ++ try { updateCustomEntityTag(level, player, entity, nbttagcompound); } catch (Throwable t) { LOGGER.warn("Error loading spawn egg NBT", t); } // CraftBukkit - SPIGOT-5665 + }) : consumer; + } + + @Nullable +- public T spawn(ServerLevel serverlevel, BlockPos blockpos, MobSpawnType mobspawntype) { +- return this.spawn(serverlevel, (CompoundTag) null, (Consumer) null, blockpos, mobspawntype, false, false); ++ public T spawn(ServerLevel level, BlockPos pos, EnumMobSpawn spawnType) { ++ // CraftBukkit start ++ return this.spawn(level, pos, spawnType, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); + } + + @Nullable +- public T spawn(ServerLevel serverlevel, @Nullable CompoundTag compoundtag, @Nullable Consumer consumer, BlockPos blockpos, MobSpawnType mobspawntype, boolean flag, boolean flag1) { +- T t0 = this.create(serverlevel, compoundtag, consumer, blockpos, mobspawntype, flag, flag1); ++ public T spawn(ServerLevel worldserver, BlockPos blockposition, EnumMobSpawn enummobspawn, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ return this.spawn(worldserver, (CompoundTag) null, null, blockposition, enummobspawn, false, false, spawnReason); // CraftBukkit - decompile error ++ // CraftBukkit end ++ } + ++ @Nullable ++ public T spawn(ServerLevel level, @Nullable CompoundTag compound, @Nullable Consumer consumer, BlockPos pos, EnumMobSpawn spawnType, boolean shouldOffsetY, boolean shouldOffsetYMore) { ++ // CraftBukkit start ++ return this.spawn(level, compound, consumer, pos, spawnType, shouldOffsetY, shouldOffsetYMore, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ @Nullable ++ public T spawn(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Consumer consumer, BlockPos blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end ++ T t0 = this.create(worldserver, nbttagcompound, consumer, blockposition, enummobspawn, flag, flag1); ++ + if (t0 != null) { +- serverlevel.addFreshEntityWithPassengers(t0); ++ worldserver.addFreshEntityWithPassengers(t0, spawnReason); ++ return !t0.isRemoved() ? t0 : null; // Don't return an entity when CreatureSpawnEvent is canceled ++ // CraftBukkit end + } + + return t0; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ExperienceOrb.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ExperienceOrb.java.patch new file mode 100644 index 0000000000..7d59276054 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ExperienceOrb.java.patch @@ -0,0 +1,121 @@ +--- a/net/minecraft/world/entity/ExperienceOrb.java ++++ b/net/minecraft/world/entity/ExperienceOrb.java +@@ -20,6 +20,12 @@ + import net.minecraft.world.level.entity.EntityTypeTest; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.player.PlayerExpCooldownChangeEvent; ++// CraftBukkit end + + public class ExperienceOrb extends Entity { + +@@ -62,6 +65,7 @@ + @Override + public void tick() { + super.tick(); ++ Player prevTarget = this.followingPlayer;// CraftBukkit - store old target + this.xo = this.getX(); + this.yo = this.getY(); + this.zo = this.getZ(); +@@ -87,10 +91,25 @@ + this.followingPlayer = null; + } + +- if (this.followingPlayer != null) { +- Vec3 vec3 = new Vec3(this.followingPlayer.getX() - this.getX(), this.followingPlayer.getY() + (double) this.followingPlayer.getEyeHeight() / 2.0D - this.getY(), this.followingPlayer.getZ() - this.getZ()); +- double d0 = vec3.lengthSqr(); ++ // CraftBukkit start ++ boolean cancelled = false; ++ if (this.followingPlayer != prevTarget) { ++ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(this, followingPlayer, (followingPlayer != null) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.FORGOT_TARGET); ++ LivingEntity target = (event.getTarget() == null) ? null : ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getTarget()).getHandle(); ++ cancelled = event.isCancelled(); + ++ if (cancelled) { ++ followingPlayer = prevTarget; ++ } else { ++ followingPlayer = (target instanceof Player) ? (Player) target : null; ++ } ++ } ++ ++ if (this.followingPlayer != null && !cancelled) { ++ // CraftBukkit end ++ Vec3 vec3d = new Vec3(this.followingPlayer.getX() - this.getX(), this.followingPlayer.getY() + (double) this.followingPlayer.getEyeHeight() / 2.0D - this.getY(), this.followingPlayer.getZ() - this.getZ()); ++ double d0 = vec3d.lengthSqr(); ++ + if (d0 < 64.0D) { + double d1 = 1.0D - Math.sqrt(d0) / 8.0D; + +@@ -235,13 +248,13 @@ + @Override + public void playerTouch(Player player) { + if (!this.level().isClientSide) { +- if (player.takeXpDelay == 0) { +- player.takeXpDelay = 2; +- player.take(this, 1); +- int i = this.repairPlayerItems(player, this.value); ++ if (entity.takeXpDelay == 0) { ++ entity.takeXpDelay = CraftEventFactory.callPlayerXpCooldownEvent(entity, 2, PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2; ++ entity.take(this, 1); ++ int i = this.repairPlayerItems(entity, this.value); + + if (i > 0) { +- player.giveExperiencePoints(i); ++ entity.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(entity, i).getAmount()); // CraftBukkit - this.value -> event.getAmount() + } + + --this.count; +@@ -258,10 +271,18 @@ + + if (entry != null) { + ItemStack itemstack = (ItemStack) entry.getValue(); +- int j = Math.min(this.xpToDurability(i), itemstack.getDamageValue()); ++ int j = Math.min(this.xpToDurability(repairAmount), itemstack.getDamageValue()); ++ // CraftBukkit start ++ org.bukkit.event.player.PlayerItemMendEvent event = CraftEventFactory.callPlayerItemMendEvent(player, this, itemstack, entry.getKey(), j); ++ j = event.getRepairAmount(); ++ if (event.isCancelled()) { ++ return repairAmount; ++ } ++ // CraftBukkit end + + itemstack.setDamageValue(itemstack.getDamageValue() - j); +- int k = i - this.durabilityToXp(j); ++ int k = repairAmount - this.durabilityToXp(j); ++ this.value = k; // CraftBukkit - update exp value of orb for PlayerItemMendEvent calls + + return k > 0 ? this.repairPlayerItems(player, k) : 0; + } else { +@@ -285,8 +306,26 @@ + return this.value >= 2477 ? 10 : (this.value >= 1237 ? 9 : (this.value >= 617 ? 8 : (this.value >= 307 ? 7 : (this.value >= 149 ? 6 : (this.value >= 73 ? 5 : (this.value >= 37 ? 4 : (this.value >= 17 ? 3 : (this.value >= 7 ? 2 : (this.value >= 3 ? 1 : 0))))))))); + } + +- public static int getExperienceValue(int i) { +- return i >= 2477 ? 2477 : (i >= 1237 ? 1237 : (i >= 617 ? 617 : (i >= 307 ? 307 : (i >= 149 ? 149 : (i >= 73 ? 73 : (i >= 37 ? 37 : (i >= 17 ? 17 : (i >= 7 ? 7 : (i >= 3 ? 3 : 1))))))))); ++ public static int getExperienceValue(int expValue) { ++ // CraftBukkit start ++ if (expValue > 162670129) return expValue - 100000; ++ if (expValue > 81335063) return 81335063; ++ if (expValue > 40667527) return 40667527; ++ if (expValue > 20333759) return 20333759; ++ if (expValue > 10166857) return 10166857; ++ if (expValue > 5083423) return 5083423; ++ if (expValue > 2541701) return 2541701; ++ if (expValue > 1270849) return 1270849; ++ if (expValue > 635413) return 635413; ++ if (expValue > 317701) return 317701; ++ if (expValue > 158849) return 158849; ++ if (expValue > 79423) return 79423; ++ if (expValue > 39709) return 39709; ++ if (expValue > 19853) return 19853; ++ if (expValue > 9923) return 9923; ++ if (expValue > 4957) return 4957; ++ // CraftBukkit end ++ return expValue >= 2477 ? 2477 : (expValue >= 1237 ? 1237 : (expValue >= 617 ? 617 : (expValue >= 307 ? 307 : (expValue >= 149 ? 149 : (expValue >= 73 ? 73 : (expValue >= 37 ? 37 : (expValue >= 17 ? 17 : (expValue >= 7 ? 7 : (expValue >= 3 ? 3 : 1))))))))); + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/Interaction.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/Interaction.java.patch new file mode 100644 index 0000000000..e78b361c1c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/Interaction.java.patch @@ -0,0 +1,39 @@ +--- a/net/minecraft/world/entity/Interaction.java ++++ b/net/minecraft/world/entity/Interaction.java +@@ -24,6 +23,13 @@ + import net.minecraft.world.phys.AABB; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.world.damagesource.DamageSource; ++import net.minecraft.world.entity.player.Player; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityDamageEvent; ++// CraftBukkit end ++ + public class Interaction extends Entity implements Attackable, Targeting { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -151,13 +148,20 @@ + @Override + public boolean skipAttackInteraction(Entity entity) { + if (entity instanceof Player) { +- Player player = (Player) entity; ++ Player entityhuman = (Player) entity; ++ // CraftBukkit start ++ DamageSource source = entityhuman.damageSources().playerAttack(entityhuman); ++ EntityDamageEvent event = CraftEventFactory.callNonLivingEntityDamageEvent(this, source, 1.0F, false); ++ if (event.isCancelled()) { ++ return true; ++ } ++ // CraftBukkit end + + this.attack = new Interaction.PlayerAction(player.getUUID(), this.level().getGameTime()); + if (player instanceof ServerPlayer) { + ServerPlayer serverplayer = (ServerPlayer) player; + +- CriteriaTriggers.PLAYER_HURT_ENTITY.trigger(serverplayer, this, player.damageSources().generic(), 1.0F, 1.0F, false); ++ CriteriaTriggers.PLAYER_HURT_ENTITY.trigger(entityplayer, this, source, (float) event.getFinalDamage(), 1.0F, false); // CraftBukkit + } + + return !this.getResponse(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ItemBasedSteering.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ItemBasedSteering.java.patch new file mode 100644 index 0000000000..60e69f4544 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ItemBasedSteering.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/entity/ItemBasedSteering.java ++++ b/net/minecraft/world/entity/ItemBasedSteering.java +@@ -53,9 +53,13 @@ + return (Integer) this.entityData.get(this.boostTimeAccessor); + } + +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- compoundtag.putBoolean("Saddle", this.hasSaddle()); ++ // CraftBukkit add setBoostTicks(int) ++ public void setBoostTicks(int ticks) { ++ this.boosting = true; ++ this.boostTime = 0; ++ this.entityData.set(this.boostTimeAccessor, ticks); + } ++ // CraftBukkit end + + public void readAdditionalSaveData(CompoundTag compoundtag) { + this.setSaddle(compoundtag.getBoolean("Saddle")); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/LightningBolt.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/LightningBolt.java.patch new file mode 100644 index 0000000000..fc67c814a7 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/LightningBolt.java.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/entity/LightningBolt.java ++++ b/net/minecraft/world/entity/LightningBolt.java +@@ -28,6 +28,9 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class LightningBolt extends Entity { + +@@ -131,7 +132,7 @@ + } + } + +- if (this.life >= 0) { ++ if (this.life >= 0 && !this.visualOnly) { // CraftBukkit - add !this.visualOnly + if (!(this.level() instanceof ServerLevel)) { + this.level().setSkyFlashTime(2); + } else if (!this.visualOnly) { +@@ -164,18 +165,26 @@ + BlockPos blockpos = this.blockPosition(); + BlockState blockstate = BaseFireBlock.getState(this.level(), blockpos); + +- if (this.level().getBlockState(blockpos).isAir() && blockstate.canSurvive(this.level(), blockpos)) { +- this.level().setBlockAndUpdate(blockpos, blockstate); +- ++this.blocksSetOnFire; ++ if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) { ++ // CraftBukkit start - add "!visualOnly" ++ if (!visualOnly && !CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition, this).isCancelled()) { ++ this.level().setBlockAndUpdate(blockposition, iblockdata); ++ ++this.blocksSetOnFire; ++ } ++ // CraftBukkit end + } + + for (int j = 0; j < i; ++j) { + BlockPos blockpos1 = blockpos.offset(this.random.nextInt(3) - 1, this.random.nextInt(3) - 1, this.random.nextInt(3) - 1); + +- blockstate = BaseFireBlock.getState(this.level(), blockpos1); +- if (this.level().getBlockState(blockpos1).isAir() && blockstate.canSurvive(this.level(), blockpos1)) { +- this.level().setBlockAndUpdate(blockpos1, blockstate); +- ++this.blocksSetOnFire; ++ iblockdata = BaseFireBlock.getState(this.level(), blockposition1); ++ if (this.level().getBlockState(blockposition1).isAir() && iblockdata.canSurvive(this.level(), blockposition1)) { ++ // CraftBukkit start - add "!visualOnly" ++ if (!visualOnly && !CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition1, this).isCancelled()) { ++ this.level().setBlockAndUpdate(blockposition1, iblockdata); ++ ++this.blocksSetOnFire; ++ } ++ // CraftBukkit end + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/LivingEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/LivingEntity.java.patch new file mode 100644 index 0000000000..55799925f7 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/LivingEntity.java.patch @@ -0,0 +1,921 @@ +--- a/net/minecraft/world/entity/LivingEntity.java ++++ b/net/minecraft/world/entity/LivingEntity.java +@@ -119,6 +120,26 @@ + import net.minecraft.world.scores.PlayerTeam; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.HashSet; ++import java.util.Set; ++import com.google.common.base.Function; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.attribute.CraftAttributeMap; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.Player; ++import org.bukkit.event.entity.ArrowBodyCountChangeEvent; ++import org.bukkit.event.entity.EntityDamageEvent; ++import org.bukkit.event.entity.EntityDamageEvent.DamageModifier; ++import org.bukkit.event.entity.EntityPotionEffectEvent; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++import org.bukkit.event.entity.EntityResurrectEvent; ++import org.bukkit.event.entity.EntityTeleportEvent; ++import org.bukkit.event.player.PlayerItemConsumeEvent; ++// CraftBukkit end ++ + public abstract class LivingEntity extends Entity implements Attackable { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -226,9 +247,23 @@ + private float swimAmountO; + protected Brain brain; + private boolean skipDropExperience; ++ // CraftBukkit start ++ public int expToDrop; ++ public boolean forceDrops; ++ public ArrayList drops = new ArrayList(); ++ public final org.bukkit.craftbukkit.attribute.CraftAttributeMap craftAttributes; ++ public boolean collides = true; ++ public Set collidableExemptions = new HashSet<>(); ++ public boolean bukkitPickUpLoot; + +- protected LivingEntity(EntityType entitytype, Level level) { +- super(entitytype, level); ++ @Override ++ public float getBukkitYaw() { ++ return getYHeadRot(); ++ } ++ // CraftBukkit end ++ ++ protected LivingEntity(EntityType entityType, Level level) { ++ super(entityType, level); + this.lastHandItemStacks = NonNullList.withSize(2, ItemStack.EMPTY); + this.lastArmorItemStacks = NonNullList.withSize(4, ItemStack.EMPTY); + this.discardFriction = false; +@@ -237,8 +272,10 @@ + this.effectsDirty = true; + this.useItem = ItemStack.EMPTY; + this.lastClimbablePos = Optional.empty(); +- this.attributes = new AttributeMap(DefaultAttributes.getSupplier(entitytype)); +- this.setHealth(this.getMaxHealth()); ++ this.attributes = new AttributeMap(DefaultAttributes.getSupplier(entityType)); ++ this.craftAttributes = new CraftAttributeMap(attributes); // CraftBukkit ++ // CraftBukkit - setHealth(getMaxHealth()) inlined and simplified to skip the instanceof check for EntityPlayer, as getBukkitEntity() is not initialized in constructor ++ this.entityData.set(LivingEntity.DATA_HEALTH_ID, (float) this.getAttribute(Attributes.MAX_HEALTH).getValue()); + this.blocksBuilding = true; + this.rotA = (float) ((Math.random() + 1.0D) * 0.009999999776482582D); + this.reapplyPosition(); +@@ -320,7 +354,13 @@ + double d7 = Math.min((double) (0.2F + f / 15.0F), 2.5D); + int i = (int) (150.0D * d7); + +- ((ServerLevel) this.level()).sendParticles(new BlockParticleOption(ParticleTypes.BLOCK, blockstate), d1, d2, d3, i, 0.0D, 0.0D, 0.0D, 0.15000000596046448D); ++ // CraftBukkit start - visiblity api ++ if (this instanceof ServerPlayer) { ++ ((ServerLevel) this.level()).sendParticles((ServerPlayer) this, new BlockParticleOption(ParticleTypes.BLOCK, onGround), this.getX(), this.getY(), this.getZ(), i, 0.0D, 0.0D, 0.0D, 0.15000000596046448D, false); ++ } else { ++ ((ServerLevel) this.level()).sendParticles(new BlockParticleOption(ParticleTypes.BLOCK, onGround), d1, d2, d3, i, 0.0D, 0.0D, 0.0D, 0.15000000596046448D); ++ } ++ // CraftBukkit end + } + + super.checkFallDamage(d0, flag, blockstate, blockpos); +@@ -677,15 +714,21 @@ + return true; + } + +- public void onEquipItem(EquipmentSlot equipmentslot, ItemStack itemstack, ItemStack itemstack1) { ++ public void onEquipItem(EquipmentSlot slot, ItemStack oldItem, ItemStack newItem) { ++ // CraftBukkit start ++ onEquipItem(slot, oldItem, newItem, false); ++ } ++ ++ public void onEquipItem(EquipmentSlot enumitemslot, ItemStack itemstack, ItemStack itemstack1, boolean silent) { ++ // CraftBukkit end + boolean flag = itemstack1.isEmpty() && itemstack.isEmpty(); + + if (!flag && !ItemStack.isSameItemSameTags(itemstack, itemstack1) && !this.firstTick) { + Equipable equipable = Equipable.get(itemstack1); + + if (!this.level().isClientSide() && !this.isSpectator()) { +- if (!this.isSilent() && equipable != null && equipable.getEquipmentSlot() == equipmentslot) { +- this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), equipable.getEquipSound(), this.getSoundSource(), 1.0F, 1.0F); ++ if (!this.isSilent() && equipable != null && equipable.getEquipmentSlot() == enumitemslot && !silent) { // CraftBukkit ++ this.level().playSound((net.minecraft.world.entity.player.Player) null, this.getX(), this.getY(), this.getZ(), equipable.getEquipSound(), this.getSoundSource(), 1.0F, 1.0F); + } + + if (this.doesEmitEquipEvent(equipmentslot)) { +@@ -761,9 +801,16 @@ + } + } + +- if (compoundtag.contains("Health", 99)) { +- this.setHealth(compoundtag.getFloat("Health")); ++ // CraftBukkit start ++ if (compound.contains("Bukkit.MaxHealth")) { ++ Tag nbtbase = compound.get("Bukkit.MaxHealth"); ++ if (nbtbase.getId() == 5) { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(((FloatTag) nbtbase).getAsDouble()); ++ } else if (nbtbase.getId() == 3) { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(((IntTag) nbtbase).getAsDouble()); ++ } + } ++ // CraftBukkit end + + this.hurtTime = compoundtag.getShort("HurtTime"); + this.deathTime = compoundtag.getShort("DeathTime"); +@@ -798,9 +849,32 @@ + + } + ++ // CraftBukkit start ++ private boolean isTickingEffects = false; ++ private List effectsToProcess = Lists.newArrayList(); ++ ++ private static class ProcessableEffect { ++ ++ private MobEffect type; ++ private MobEffectInstance effect; ++ private final EntityPotionEffectEvent.Cause cause; ++ ++ private ProcessableEffect(MobEffectInstance effect, EntityPotionEffectEvent.Cause cause) { ++ this.effect = effect; ++ this.cause = cause; ++ } ++ ++ private ProcessableEffect(MobEffect type, EntityPotionEffectEvent.Cause cause) { ++ this.type = type; ++ this.cause = cause; ++ } ++ } ++ // CraftBukkit end ++ + protected void tickEffects() { + Iterator iterator = this.activeEffects.keySet().iterator(); + ++ isTickingEffects = true; // CraftBukkit + try { + while (iterator.hasNext()) { + MobEffect mobeffect = (MobEffect) iterator.next(); +@@ -810,6 +884,12 @@ + this.onEffectUpdated(mobeffectinstance, true, (Entity) null); + })) { + if (!this.level().isClientSide) { ++ // CraftBukkit start ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, mobeffect, null, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.EXPIRATION); ++ if (event.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end + iterator.remove(); + this.onEffectRemoved(mobeffectinstance); + } +@@ -820,6 +900,17 @@ + } catch (ConcurrentModificationException concurrentmodificationexception) { + ; + } ++ // CraftBukkit start ++ isTickingEffects = false; ++ for (ProcessableEffect e : effectsToProcess) { ++ if (e.effect != null) { ++ addEffect(e.effect, e.cause); ++ } else { ++ removeEffect(e.type, e.cause); ++ } ++ } ++ effectsToProcess.clear(); ++ // CraftBukkit end + + if (this.effectsDirty) { + if (!this.level().isClientSide) { +@@ -946,7 +1037,13 @@ + this.entityData.set(LivingEntity.DATA_EFFECT_COLOR_ID, 0); + } + ++ // CraftBukkit start + public boolean removeAllEffects() { ++ return removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean removeAllEffects(EntityPotionEffectEvent.Cause cause) { ++ // CraftBukkit end + if (this.level().isClientSide) { + return false; + } else { +@@ -955,7 +1052,14 @@ + boolean flag; + + for (flag = false; iterator.hasNext(); flag = true) { +- this.onEffectRemoved((MobEffectInstance) iterator.next()); ++ // CraftBukkit start ++ MobEffectInstance effect = (MobEffectInstance) iterator.next(); ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, effect, null, cause, EntityPotionEffectEvent.Action.CLEARED); ++ if (event.isCancelled()) { ++ continue; ++ } ++ this.onEffectRemoved(effect); ++ // CraftBukkit end + iterator.remove(); + } + +@@ -984,19 +1088,49 @@ + return this.addEffect(mobeffectinstance, (Entity) null); + } + +- public boolean addEffect(MobEffectInstance mobeffectinstance, @Nullable Entity entity) { +- if (!this.canBeAffected(mobeffectinstance)) { ++ // CraftBukkit start ++ public boolean addEffect(MobEffectInstance mobeffect, EntityPotionEffectEvent.Cause cause) { ++ return this.addEffect(mobeffect, (Entity) null, cause); ++ } ++ ++ public boolean addEffect(MobEffectInstance effectInstance, @Nullable Entity entity) { ++ return this.addEffect(effectInstance, entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean addEffect(MobEffectInstance mobeffect, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause) { ++ if (isTickingEffects) { ++ effectsToProcess.add(new ProcessableEffect(mobeffect, cause)); ++ return true; ++ } ++ // CraftBukkit end ++ ++ if (!this.canBeAffected(mobeffect)) { + return false; + } else { + MobEffectInstance mobeffectinstance1 = (MobEffectInstance) this.activeEffects.get(mobeffectinstance.getEffect()); + boolean flag = false; + +- if (mobeffectinstance1 == null) { +- this.activeEffects.put(mobeffectinstance.getEffect(), mobeffectinstance); +- this.onEffectAdded(mobeffectinstance, entity); ++ // CraftBukkit start ++ boolean override = false; ++ if (mobeffect1 != null) { ++ override = new MobEffectInstance(mobeffect1).update(mobeffect); ++ } ++ ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, mobeffect1, mobeffect, cause, override); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ ++ if (mobeffect1 == null) { ++ this.activeEffects.put(mobeffect.getEffect(), mobeffect); ++ this.onEffectAdded(mobeffect, entity); + flag = true; +- } else if (mobeffectinstance1.update(mobeffectinstance)) { +- this.onEffectUpdated(mobeffectinstance1, true, entity); ++ // CraftBukkit start ++ } else if (event.isOverride()) { ++ mobeffect1.update(mobeffect); ++ this.onEffectUpdated(mobeffect1, true, entity); ++ // CraftBukkit end + flag = true; + } + +@@ -1034,6 +1168,7 @@ + return this.getMobType() == MobType.UNDEAD; + } + ++ // CraftBukkit start + @Nullable + public MobEffectInstance removeEffectNoUpdate(@Nullable MobEffect mobeffect) { + return (MobEffectInstance) this.activeEffects.remove(mobeffect); +@@ -1042,8 +1181,29 @@ + public boolean removeEffect(MobEffect mobeffect) { + MobEffectInstance mobeffectinstance = this.removeEffectNoUpdate(mobeffect); + +- if (mobeffectinstance != null) { +- this.onEffectRemoved(mobeffectinstance); ++ MobEffectInstance effect = this.activeEffects.get(mobeffectlist); ++ if (effect == null) { ++ return null; ++ } ++ ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, effect, null, cause); ++ if (event.isCancelled()) { ++ return null; ++ } ++ ++ return (MobEffectInstance) this.activeEffects.remove(mobeffectlist); ++ } ++ ++ public boolean removeEffect(MobEffect effect) { ++ return removeEffect(effect, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean removeEffect(MobEffect mobeffectlist, EntityPotionEffectEvent.Cause cause) { ++ MobEffectInstance mobeffect = this.c(mobeffectlist, cause); ++ // CraftBukkit end ++ ++ if (mobeffect != null) { ++ this.onEffectRemoved(mobeffect); + return true; + } else { + return false; +@@ -1138,21 +1298,56 @@ + + } + +- public void heal(float f) { ++ // CraftBukkit start - Delegate so we can handle providing a reason for health being regained ++ public void heal(float healAmount) { ++ heal(healAmount, EntityRegainHealthEvent.RegainReason.CUSTOM); ++ } ++ ++ public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason) { + float f1 = this.getHealth(); + + if (f1 > 0.0F) { +- this.setHealth(f1 + f); ++ EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason); ++ // Suppress during worldgen ++ if (this.valid) { ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (!event.isCancelled()) { ++ this.setHealth((float) (this.getHealth() + event.getAmount())); ++ } ++ // CraftBukkit end + } + + } + + public float getHealth() { ++ // CraftBukkit start - Use unscaled health ++ if (this instanceof ServerPlayer) { ++ return (float) ((ServerPlayer) this).getBukkitEntity().getHealth(); ++ } ++ // CraftBukkit end + return (Float) this.entityData.get(LivingEntity.DATA_HEALTH_ID); + } + +- public void setHealth(float f) { +- this.entityData.set(LivingEntity.DATA_HEALTH_ID, Mth.clamp(f, 0.0F, this.getMaxHealth())); ++ public void setHealth(float health) { ++ // CraftBukkit start - Handle scaled health ++ if (this instanceof ServerPlayer) { ++ org.bukkit.craftbukkit.entity.CraftPlayer player = ((ServerPlayer) this).getBukkitEntity(); ++ // Squeeze ++ if (health < 0.0F) { ++ player.setRealHealth(0.0D); ++ } else if (health > player.getMaxHealth()) { ++ player.setRealHealth(player.getMaxHealth()); ++ } else { ++ player.setRealHealth(health); ++ } ++ ++ player.updateScaledHealth(false); ++ return; ++ } ++ // CraftBukkit end ++ this.entityData.set(LivingEntity.DATA_HEALTH_ID, Mth.clamp(health, 0.0F, this.getMaxHealth())); + } + + public boolean isDeadOrDying() { +@@ -1166,7 +1360,7 @@ + return false; + } else if (this.level().isClientSide) { + return false; +- } else if (this.isDeadOrDying()) { ++ } else if (this.isRemoved() || this.dead || this.getHealth() <= 0.0F) { // CraftBukkit - Don't allow entities that got set to dead/killed elsewhere to get damaged and die + return false; + } else if (damagesource.is(DamageTypeTags.IS_FIRE) && this.hasEffect(MobEffects.FIRE_RESISTANCE)) { + return false; +@@ -1180,12 +1374,13 @@ + boolean flag = false; + float f2 = 0.0F; + +- if (f > 0.0F && this.isDamageSourceBlocked(damagesource)) { +- this.hurtCurrentlyUsedShield(f); +- f2 = f; +- f = 0.0F; +- if (!damagesource.is(DamageTypeTags.IS_PROJECTILE)) { +- Entity entity = damagesource.getDirectEntity(); ++ // CraftBukkit - Moved into damageEntity0(DamageSource, float) ++ if (false && amount > 0.0F && this.isDamageSourceBlocked(source)) { ++ this.hurtCurrentlyUsedShield(amount); ++ f2 = amount; ++ amount = 0.0F; ++ if (!source.is(DamageTypeTags.IS_PROJECTILE)) { ++ Entity entity = source.getDirectEntity(); + + if (entity instanceof LivingEntity) { + LivingEntity livingentity = (LivingEntity) entity; +@@ -1204,25 +1399,35 @@ + this.walkAnimation.setSpeed(1.5F); + boolean flag1 = true; + +- if ((float) this.invulnerableTime > 10.0F && !damagesource.is(DamageTypeTags.BYPASSES_COOLDOWN)) { +- if (f <= this.lastHurt) { ++ if ((float) this.invulnerableTime > (float) this.invulnerableDuration / 2.0F && !source.is(DamageTypeTags.BYPASSES_COOLDOWN)) { // CraftBukkit - restore use of maxNoDamageTicks ++ if (amount <= this.lastHurt) { + return false; + } + +- this.actuallyHurt(damagesource, f - this.lastHurt); +- this.lastHurt = f; ++ // CraftBukkit start ++ if (!this.damageEntity0(source, amount - this.lastHurt)) { ++ return false; ++ } ++ // CraftBukkit end ++ this.lastHurt = amount; + flag1 = false; + } else { +- this.lastHurt = f; +- this.invulnerableTime = 20; +- this.actuallyHurt(damagesource, f); ++ // CraftBukkit start ++ if (!this.damageEntity0(source, amount)) { ++ return false; ++ } ++ this.lastHurt = amount; ++ this.invulnerableTime = this.invulnerableDuration; // CraftBukkit - restore use of maxNoDamageTicks ++ // this.damageEntity0(damagesource, f); ++ // CraftBukkit end + this.hurtDuration = 10; + this.hurtTime = this.hurtDuration; + } + +- if (damagesource.is(DamageTypeTags.DAMAGES_HELMET) && !this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { +- this.hurtHelmet(damagesource, f); +- f *= 0.75F; ++ // CraftBukkit - Moved into damageEntity0(DamageSource, float) ++ if (false && source.is(DamageTypeTags.DAMAGES_HELMET) && !this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { ++ this.hurtHelmet(source, amount); ++ amount *= 0.75F; + } + + Entity entity1 = damagesource.getEntity(); +@@ -1338,13 +1543,17 @@ + InteractionHand[] ainteractionhand = InteractionHand.values(); + int i = ainteractionhand.length; + ++ // CraftBukkit start ++ EnumHand hand = null; ++ ItemStack itemstack1 = ItemStack.EMPTY; + for (int j = 0; j < i; ++j) { + InteractionHand interactionhand = ainteractionhand[j]; + ItemStack itemstack1 = this.getItemInHand(interactionhand); + + if (itemstack1.is(Items.TOTEM_OF_UNDYING)) { ++ hand = enumhand; // CraftBukkit + itemstack = itemstack1.copy(); +- itemstack1.shrink(1); ++ // itemstack1.subtract(1); // CraftBukkit + break; + } + } +@@ -1353,16 +1563,26 @@ + if (this instanceof ServerPlayer) { + ServerPlayer serverplayer = (ServerPlayer) this; + +- serverplayer.awardStat(Stats.ITEM_USED.get(Items.TOTEM_OF_UNDYING)); +- CriteriaTriggers.USED_TOTEM.trigger(serverplayer, itemstack); ++ if (!event.isCancelled()) { ++ if (!itemstack1.isEmpty()) { ++ itemstack1.shrink(1); ++ } ++ if (itemstack != null && this instanceof ServerPlayer) { ++ // CraftBukkit end ++ ServerPlayer entityplayer = (ServerPlayer) this; ++ ++ entityplayer.awardStat(Stats.ITEM_USED.get(Items.TOTEM_OF_UNDYING)); ++ CriteriaTriggers.USED_TOTEM.trigger(entityplayer, itemstack); + this.gameEvent(GameEvent.ITEM_INTERACT_FINISH); + } + + this.setHealth(1.0F); +- this.removeAllEffects(); +- this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 900, 1)); +- this.addEffect(new MobEffectInstance(MobEffects.ABSORPTION, 100, 1)); +- this.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 800, 0)); ++ // CraftBukkit start ++ this.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 900, 1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ this.addEffect(new MobEffectInstance(MobEffects.ABSORPTION, 100, 1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ this.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 800, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ // CraftBukkit end + this.level().broadcastEntityEvent(this, (byte) 35); + } + +@@ -1472,16 +1692,24 @@ + BlockPos blockpos = this.blockPosition(); + BlockState blockstate = Blocks.WITHER_ROSE.defaultBlockState(); + +- if (this.level().getBlockState(blockpos).isAir() && blockstate.canSurvive(this.level(), blockpos)) { +- this.level().setBlock(blockpos, blockstate, 3); +- flag = true; ++ if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) { ++ // CraftBukkit start - call EntityBlockFormEvent for Wither Rose ++ flag = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this.level(), blockposition, iblockdata, 3, this); ++ // CraftBukkit end + } + } + + if (!flag) { + ItemEntity itementity = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), new ItemStack(Items.WITHER_ROSE)); + +- this.level().addFreshEntity(itementity); ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ CraftEventFactory.callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ this.level().addFreshEntity(entityitem); + } + } + +@@ -1500,22 +1728,38 @@ + + boolean flag = this.lastHurtByPlayerTime > 0; + ++ this.dropEquipment(); // CraftBukkit - from below + if (this.shouldDropLoot() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { + this.dropFromLootTable(damagesource, flag); + this.dropCustomDeathLoot(damagesource, i, flag); + } ++ // CraftBukkit start - Call death event ++ CraftEventFactory.callEntityDeathEvent(this, this.drops); ++ this.drops = new ArrayList<>(); ++ // CraftBukkit end + +- this.dropEquipment(); ++ // this.dropInventory();// CraftBukkit - moved up + this.dropExperience(); + } + + protected void dropEquipment() {} + +- protected void dropExperience() { ++ // CraftBukkit start ++ public int getExpReward() { + if (this.level() instanceof ServerLevel && !this.wasExperienceConsumed() && (this.isAlwaysExperienceDropper() || this.lastHurtByPlayerTime > 0 && this.shouldDropExperience() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT))) { + ExperienceOrb.award((ServerLevel) this.level(), this.position(), this.getExperienceReward()); + } ++ } ++ // CraftBukkit end + ++ protected void dropExperience() { ++ // CraftBukkit start - Update getExpReward() above if the removed if() changes! ++ if (true && !(this instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon)) { // CraftBukkit - SPIGOT-2420: Special case ender dragon will drop the xp over time ++ ExperienceOrb.award((ServerLevel) this.level(), this.position(), this.expToDrop); ++ this.expToDrop = 0; ++ } ++ // CraftBukkit end ++ + } + + protected void dropCustomDeathLoot(DamageSource damagesource, int i, boolean flag) {} +@@ -1606,6 +1853,28 @@ + return itemstack.getEatingSound(); + } + ++ // CraftBukkit start - Add delegate methods ++ public SoundEvent getHurtSound0(DamageSource damagesource) { ++ return getHurtSound(damagesource); ++ } ++ ++ public SoundEvent getDeathSound0() { ++ return getDeathSound(); ++ } ++ ++ public SoundEvent getFallDamageSound0(int fallHeight) { ++ return getFallDamageSound(fallHeight); ++ } ++ ++ public SoundEvent getDrinkingSound0(ItemStack itemstack) { ++ return getDrinkingSound(itemstack); ++ } ++ ++ public SoundEvent getEatingSound0(ItemStack itemstack) { ++ return getEatingSound(itemstack); ++ } ++ // CraftBukkit end ++ + public Optional getLastClimbablePos() { + return this.lastClimbablePos; + } +@@ -1654,9 +1921,14 @@ + int i = this.calculateFallDamage(f, f1); + + if (i > 0) { ++ // CraftBukkit start ++ if (!this.hurt(source, (float) i)) { ++ return true; ++ } ++ // CraftBukkit end + this.playSound(this.getFallDamageSound(i), 1.0F, 1.0F); + this.playBlockFallSound(); +- this.hurt(damagesource, (float) i); ++ // this.damageEntity(damagesource, (float) i); // CraftBukkit - moved up + return true; + } else { + return flag; +@@ -1707,10 +1978,10 @@ + + protected void hurtCurrentlyUsedShield(float f) {} + +- protected float getDamageAfterArmorAbsorb(DamageSource damagesource, float f) { +- if (!damagesource.is(DamageTypeTags.BYPASSES_ARMOR)) { +- this.hurtArmor(damagesource, f); +- f = CombatRules.getDamageAfterAbsorb(f, (float) this.getArmorValue(), (float) this.getAttributeValue(Attributes.ARMOR_TOUGHNESS)); ++ protected float getDamageAfterArmorAbsorb(DamageSource damageSource, float damageAmount) { ++ if (!damageSource.is(DamageTypeTags.BYPASSES_ARMOR)) { ++ // this.hurtArmor(damagesource, f); // CraftBukkit - Moved into damageEntity0(DamageSource, float) ++ damageAmount = CombatRules.getDamageAfterAbsorb(damageAmount, (float) this.getArmorValue(), (float) this.getAttributeValue(Attributes.ARMOR_TOUGHNESS)); + } + + return f; +@@ -1722,7 +1993,8 @@ + } else { + int i; + +- if (this.hasEffect(MobEffects.DAMAGE_RESISTANCE) && !damagesource.is(DamageTypeTags.BYPASSES_RESISTANCE)) { ++ // CraftBukkit - Moved to damageEntity0(DamageSource, float) ++ if (false && this.hasEffect(MobEffects.DAMAGE_RESISTANCE) && !damageSource.is(DamageTypeTags.BYPASSES_RESISTANCE)) { + i = (this.getEffect(MobEffects.DAMAGE_RESISTANCE).getAmplifier() + 1) * 5; + int j = 25 - i; + float f1 = f * (float) j; +@@ -1755,11 +2027,16 @@ + } + } + +- protected void actuallyHurt(DamageSource damagesource, float f) { +- if (!this.isInvulnerableTo(damagesource)) { +- f = this.getDamageAfterArmorAbsorb(damagesource, f); +- f = this.getDamageAfterMagicAbsorb(damagesource, f); +- float f1 = f; ++ // CraftBukkit start ++ protected boolean damageEntity0(final DamageSource damagesource, float f) { // void -> boolean, add final ++ if (!this.isInvulnerableTo(damagesource)) { ++ final boolean human = this instanceof net.minecraft.world.entity.player.Player; ++ float originalDamage = f; ++ Function hardHat = new Function() { ++ @Override ++ public Double apply(Double f) { ++ if (damagesource.is(DamageTypeTags.DAMAGES_HELMET) && !LivingEntity.this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { ++ return -(f - (f * 0.75F)); + + f = Math.max(f - this.getAbsorptionAmount(), 0.0F); + this.setAbsorptionAmount(this.getAbsorptionAmount() - (f1 - f)); +@@ -1775,13 +2156,47 @@ + } + } + +- if (f != 0.0F) { ++ if (f > 0 || !human) { ++ if (human) { ++ // PAIL: Be sure to drag all this code from the EntityHuman subclass each update. ++ ((net.minecraft.world.entity.player.Player) this).causeFoodExhaustion(damagesource.getFoodExhaustion(), org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.DAMAGED); // CraftBukkit - EntityExhaustionEvent ++ if (f < 3.4028235E37F) { ++ ((net.minecraft.world.entity.player.Player) this).awardStat(Stats.DAMAGE_TAKEN, Math.round(f * 10.0F)); ++ } ++ } ++ // CraftBukkit end + this.getCombatTracker().recordDamage(damagesource, f); + this.setHealth(this.getHealth() - f); +- this.setAbsorptionAmount(this.getAbsorptionAmount() - f); ++ // CraftBukkit start ++ if (!human) { ++ this.setAbsorptionAmount(this.getAbsorptionAmount() - f); ++ } + this.gameEvent(GameEvent.ENTITY_DAMAGE); ++ ++ return true; ++ } else { ++ // Duplicate triggers if blocking ++ if (event.getDamage(DamageModifier.BLOCKING) < 0) { ++ if (this instanceof ServerPlayer) { ++ CriteriaTriggers.ENTITY_HURT_PLAYER.trigger((ServerPlayer) this, damagesource, f, originalDamage, true); ++ f2 = (float) -event.getDamage(DamageModifier.BLOCKING); ++ if (f2 > 0.0F && f2 < 3.4028235E37F) { ++ ((ServerPlayer) this).awardStat(Stats.DAMAGE_BLOCKED_BY_SHIELD, Math.round(originalDamage * 10.0F)); ++ } ++ } ++ ++ if (damagesource.getEntity() instanceof ServerPlayer) { ++ CriteriaTriggers.PLAYER_HURT_ENTITY.trigger((ServerPlayer) damagesource.getEntity(), this, damagesource, f, originalDamage, true); ++ } ++ ++ return false; ++ } else { ++ return originalDamage > 0; ++ } ++ // CraftBukkit end + } + } ++ return false; // CraftBukkit + } + + public CombatTracker getCombatTracker() { +@@ -1805,10 +2220,20 @@ + return (Integer) this.entityData.get(LivingEntity.DATA_ARROW_COUNT_ID); + } + +- public final void setArrowCount(int i) { +- this.entityData.set(LivingEntity.DATA_ARROW_COUNT_ID, i); ++ public final void setArrowCount(int count) { ++ // CraftBukkit start ++ setArrowCount(count, false); + } + ++ public final void setArrowCount(int i, boolean flag) { ++ ArrowBodyCountChangeEvent event = CraftEventFactory.callArrowBodyCountChangeEvent(this, getArrowCount(), i, flag); ++ if (event.isCancelled()) { ++ return; ++ } ++ this.entityData.set(LivingEntity.DATA_ARROW_COUNT_ID, event.getNewAmount()); ++ } ++ // CraftBukkit end ++ + public final int getStingerCount() { + return (Integer) this.entityData.get(LivingEntity.DATA_STINGER_COUNT_ID); + } +@@ -2053,6 +2474,12 @@ + + public abstract ItemStack getItemBySlot(EquipmentSlot slot); + ++ // CraftBukkit start ++ public void setItemSlot(EquipmentSlot enumitemslot, ItemStack itemstack, boolean silent) { ++ this.setItemSlot(enumitemslot, itemstack); ++ } ++ // CraftBukkit end ++ + @Override + @Override + public abstract void setItemSlot(EquipmentSlot slot, ItemStack stack); +@@ -2291,6 +2714,7 @@ + } + + if (this.onGround() && !this.level().isClientSide) { ++ if (getSharedFlag(7) && !CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) // CraftBukkit + this.setSharedFlag(7, false); + } + } else { +@@ -2462,7 +2885,7 @@ + } + } + +- this.detectEquipmentUpdates(); ++ this.detectEquipmentUpdatesPublic(); // CraftBukkit + if (this.tickCount % 20 == 0) { + this.getCombatTracker().recheckStatus(); + } +@@ -2559,7 +2982,7 @@ + this.refreshDirtyAttributes(); + } + +- private void detectEquipmentUpdates() { ++ public void detectEquipmentUpdatesPublic() { // CraftBukkit + Map map = this.collectEquipmentChanges(); + + if (map != null) { +@@ -2861,6 +3284,7 @@ + } + + if (!this.level().isClientSide) { ++ if (flag != this.getSharedFlag(7) && !CraftEventFactory.callToggleGlideEvent(this, flag).isCancelled()) // CraftBukkit + this.setSharedFlag(7, flag); + } + +@@ -3062,16 +3475,22 @@ + @Override + @Override + public boolean isPickable() { +- return !this.isRemoved(); ++ return !this.isRemoved() && this.collides; // CraftBukkit + } + + @Override + @Override + public boolean isPushable() { +- return this.isAlive() && !this.isSpectator() && !this.onClimbable(); ++ return this.isAlive() && !this.isSpectator() && !this.onClimbable() && this.collides; // CraftBukkit + } + ++ // CraftBukkit start - collidable API + @Override ++ public boolean canCollideWithBukkit(Entity entity) { ++ return isPushable() && this.collides != this.collidableExemptions.contains(entity.getUUID()); ++ } ++ // CraftBukkit end ++ + @Override + public float getYHeadRot() { + return this.yHeadRot; +@@ -3271,8 +3684,27 @@ + } else { + if (!this.useItem.isEmpty() && this.isUsingItem()) { + this.triggerItemUseEffects(this.useItem, 16); +- ItemStack itemstack = this.useItem.finishUsingItem(this.level(), this); ++ // CraftBukkit start - fire PlayerItemConsumeEvent ++ ItemStack itemstack; ++ if (this instanceof ServerPlayer) { ++ org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(this.useItem); ++ org.bukkit.inventory.EquipmentSlot hand = org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(enumhand); ++ PlayerItemConsumeEvent event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem, hand); ++ this.level().getCraftServer().getPluginManager().callEvent(event); + ++ if (event.isCancelled()) { ++ // Update client ++ ((ServerPlayer) this).getBukkitEntity().updateInventory(); ++ ((ServerPlayer) this).getBukkitEntity().updateScaledHealth(); ++ return; ++ } ++ ++ itemstack = (craftItem.equals(event.getItem())) ? this.useItem.finishUsingItem(this.level(), this) : CraftItemStack.asNMSCopy(event.getItem()).finishUsingItem(this.level(), this); ++ } else { ++ itemstack = this.useItem.finishUsingItem(this.level(), this); ++ } ++ // CraftBukkit end ++ + if (itemstack != this.useItem) { + this.setItemInHand(interactionhand, itemstack); + } +@@ -3349,7 +3780,13 @@ + return this.fallFlyTicks; + } + +- public boolean randomTeleport(double d0, double d1, double d2, boolean flag) { ++ public boolean randomTeleport(double x, double d1, double y, boolean flag) { ++ // CraftBukkit start ++ return randomTeleport(x, d1, y, flag, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.UNKNOWN).orElse(false); ++ } ++ ++ public Optional randomTeleport(double d0, double d1, double d2, boolean flag, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { ++ // CraftBukkit end + double d3 = this.getX(); + double d4 = this.getY(); + double d5 = this.getZ(); +@@ -3374,16 +3811,41 @@ + } + + if (flag2) { +- this.teleportTo(d0, d6, d2); +- if (level.noCollision((Entity) this) && !level.containsAnyLiquid(this.getBoundingBox())) { ++ // CraftBukkit start - Teleport event ++ // this.teleportTo(d0, d6, d2); ++ ++ // first set position, to check if the place to teleport is valid ++ this.setPos(d0, d6, d2); ++ if (world.noCollision((Entity) this) && !world.containsAnyLiquid(this.getBoundingBox())) { + flag1 = true; + } ++ // now revert and call event if the teleport place is valid ++ this.setPos(d3, d4, d5); ++ ++ if (flag1) { ++ if (!(this instanceof ServerPlayer)) { ++ EntityTeleportEvent teleport = new EntityTeleportEvent(this.getBukkitEntity(), new Location(this.level().getWorld(), d3, d4, d5), new Location(this.level().getWorld(), d0, d6, d2)); ++ this.level().getCraftServer().getPluginManager().callEvent(teleport); ++ if (!teleport.isCancelled()) { ++ Location to = teleport.getTo(); ++ this.teleportTo(to.getX(), to.getY(), to.getZ()); ++ } else { ++ return Optional.empty(); ++ } ++ } else { ++ // player teleport event is called in the underlining code ++ if (((ServerPlayer) this).connection.teleport(d0, d6, d2, this.getYRot(), this.getXRot(), java.util.Collections.emptySet(), cause)) { ++ return Optional.empty(); ++ } ++ } ++ } ++ // CraftBukkit end + } + } + + if (!flag1) { +- this.teleportTo(d3, d4, d5); +- return false; ++ // this.enderTeleportTo(d3, d4, d5); // CraftBukkit - already set the location back ++ return Optional.of(false); // CraftBukkit + } else { + if (flag) { + level.broadcastEntityEvent(this, (byte) 46); +@@ -3395,7 +3857,7 @@ + pathfindermob.getNavigation().stop(); + } + +- return true; ++ return Optional.of(true); // CraftBukkit + } + } + +@@ -3570,7 +4028,7 @@ + Pair pair = (Pair) iterator.next(); + + if (!level.isClientSide && pair.getFirst() != null && level.random.nextFloat() < (Float) pair.getSecond()) { +- livingentity.addEffect(new MobEffectInstance((MobEffectInstance) pair.getFirst())); ++ livingEntity.addEffect(new MobEffectInstance((MobEffectInstance) pair.getFirst()), EntityPotionEffectEvent.Cause.FOOD); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/Mob.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/Mob.java.patch new file mode 100644 index 0000000000..e998b34007 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/Mob.java.patch @@ -0,0 +1,349 @@ +--- a/net/minecraft/world/entity/Mob.java ++++ b/net/minecraft/world/entity/Mob.java +@@ -75,6 +76,16 @@ + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.AABB; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++import org.bukkit.event.entity.EntityUnleashEvent; ++import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; ++// CraftBukkit end + + public abstract class Mob extends LivingEntity implements Targeting { + +@@ -123,8 +134,10 @@ + private BlockPos restrictCenter; + private float restrictRadius; + +- protected Mob(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public boolean aware = true; // CraftBukkit ++ ++ protected Mob(EntityType entityType, Level level) { ++ super(entityType, level); + this.handItems = NonNullList.withSize(2, ItemStack.EMPTY); + this.handDropChances = new float[2]; + this.armorItems = NonNullList.withSize(4, ItemStack.EMPTY); +@@ -148,6 +161,12 @@ + + } + ++ // CraftBukkit start ++ public void setPersistenceRequired(boolean persistenceRequired) { ++ this.persistenceRequired = persistenceRequired; ++ } ++ // CraftBukkit end ++ + protected void registerGoals() {} + + public static AttributeSupplier.Builder createMobAttributes() { +@@ -260,10 +277,41 @@ + return this.target; + } + +- public void setTarget(@Nullable LivingEntity livingentity) { +- this.target = livingentity; ++ public void setTarget(@Nullable LivingEntity target) { ++ // CraftBukkit start - fire event ++ setTarget(target, EntityTargetEvent.TargetReason.UNKNOWN, true); + } + ++ public boolean setTarget(LivingEntity entityliving, EntityTargetEvent.TargetReason reason, boolean fireEvent) { ++ if (getTarget() == entityliving) return false; ++ if (fireEvent) { ++ if (reason == EntityTargetEvent.TargetReason.UNKNOWN && getTarget() != null && entityliving == null) { ++ reason = getTarget().isAlive() ? EntityTargetEvent.TargetReason.FORGOT_TARGET : EntityTargetEvent.TargetReason.TARGET_DIED; ++ } ++ if (reason == EntityTargetEvent.TargetReason.UNKNOWN) { ++ this.level().getCraftServer().getLogger().log(java.util.logging.Level.WARNING, "Unknown target reason, please report on the issue tracker", new Exception()); ++ } ++ CraftLivingEntity ctarget = null; ++ if (entityliving != null) { ++ ctarget = (CraftLivingEntity) entityliving.getBukkitEntity(); ++ } ++ EntityTargetLivingEntityEvent event = new EntityTargetLivingEntityEvent(this.getBukkitEntity(), ctarget, reason); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ if (event.getTarget() != null) { ++ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ } else { ++ entityliving = null; ++ } ++ } ++ this.target = entityliving; ++ return true; ++ // CraftBukkit end ++ } ++ + @Override + @Override + public boolean canAttackType(EntityType entitytype) { +@@ -409,6 +449,12 @@ + return null; + } + ++ // CraftBukkit start - Add delegate method ++ public SoundEvent getAmbientSound0() { ++ return getAmbientSound(); ++ } ++ // CraftBukkit end ++ + @Override + @Override + public void addAdditionalSaveData(CompoundTag compoundtag) { +@@ -467,9 +512,9 @@ + listtag3.add(FloatTag.valueOf(f1)); + } + +- compoundtag.put("HandDropChances", listtag3); +- if (this.leashHolder != null) { +- compoundtag2 = new CompoundTag(); ++ compound.put("HandDropChances", nbttaglist3); ++ if (this.leashHolder != null && !this.leashHolder.pluginRemoved) { // CraftBukkit - SPIGOT-7487: Don't save (and possible drop) leash, when the holder was removed by a plugin ++ nbttagcompound2 = new CompoundTag(); + if (this.leashHolder instanceof LivingEntity) { + UUID uuid = this.leashHolder.getUUID(); + +@@ -499,18 +544,27 @@ + compoundtag.putBoolean("NoAI", this.isNoAi()); + } + ++ compound.putBoolean("Bukkit.Aware", this.aware); // CraftBukkit + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("CanPickUpLoot", 1)) { +- this.setCanPickUpLoot(compoundtag.getBoolean("CanPickUpLoot")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ ++ // CraftBukkit start - If looting or persistence is false only use it if it was set after we started using it ++ if (compound.contains("CanPickUpLoot", 1)) { ++ boolean data = compound.getBoolean("CanPickUpLoot"); ++ if (isLevelAtLeast(compound, 1) || data) { ++ this.setCanPickUpLoot(data); ++ } + } + +- this.persistenceRequired = compoundtag.getBoolean("PersistenceRequired"); +- ListTag listtag; ++ boolean data = compound.getBoolean("PersistenceRequired"); ++ if (isLevelAtLeast(compound, 1) || data) { ++ this.persistenceRequired = data; ++ } ++ // CraftBukkit end ++ ListTag nbttaglist; + int i; + + if (compoundtag.contains("ArmorItems", 9)) { +@@ -555,7 +609,12 @@ + this.lootTableSeed = compoundtag.getLong("DeathLootTableSeed"); + } + +- this.setNoAi(compoundtag.getBoolean("NoAI")); ++ this.setNoAi(compound.getBoolean("NoAI")); ++ // CraftBukkit start ++ if (compound.contains("Bukkit.Aware")) { ++ this.aware = compound.getBoolean("Bukkit.Aware"); ++ } ++ // CraftBukkit end + } + + @Override +@@ -626,9 +680,9 @@ + return Mob.ITEM_PICKUP_REACH; + } + +- protected void pickUpItem(ItemEntity itementity) { +- ItemStack itemstack = itementity.getItem(); +- ItemStack itemstack1 = this.equipItemIfPossible(itemstack.copy()); ++ protected void pickUpItem(ItemEntity itemEntity) { ++ ItemStack itemstack = itemEntity.getItem(); ++ ItemStack itemstack1 = this.equipItemIfPossible(itemstack.copy(), itemEntity); // CraftBukkit - add item + + if (!itemstack1.isEmpty()) { + this.onItemPickup(itementity); +@@ -641,9 +695,15 @@ + + } + +- public ItemStack equipItemIfPossible(ItemStack itemstack) { +- EquipmentSlot equipmentslot = getEquipmentSlotForItem(itemstack); +- ItemStack itemstack1 = this.getItemBySlot(equipmentslot); ++ public ItemStack equipItemIfPossible(ItemStack stack) { ++ // CraftBukkit start - add item ++ return this.equipItemIfPossible(stack, null); ++ } ++ ++ public ItemStack equipItemIfPossible(ItemStack itemstack, ItemEntity entityitem) { ++ // CraftBukkit end ++ EquipmentSlot enumitemslot = getEquipmentSlotForItem(itemstack); ++ ItemStack itemstack1 = this.getItemBySlot(enumitemslot); + boolean flag = this.canReplaceCurrentItem(itemstack, itemstack1); + + if (equipmentslot.isArmor() && !flag) { +@@ -652,11 +712,19 @@ + flag = itemstack1.isEmpty(); + } + +- if (flag && this.canHoldItem(itemstack)) { +- double d0 = (double) this.getEquipmentDropChance(equipmentslot); ++ // CraftBukkit start ++ boolean canPickup = flag && this.canHoldItem(itemstack); ++ if (entityitem != null) { ++ canPickup = !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, entityitem, 0, !canPickup).isCancelled(); ++ } ++ if (canPickup) { ++ // CraftBukkit end ++ double d0 = (double) this.getEquipmentDropChance(enumitemslot); + + if (!itemstack1.isEmpty() && (double) Math.max(this.random.nextFloat() - 0.1F, 0.0F) < d0) { ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation(itemstack1); ++ this.forceDrops = false; // CraftBukkit + } + + if (equipmentslot.isArmor() && itemstack.getCount() > 1) { +@@ -810,6 +876,7 @@ + @Override + protected final void serverAiStep() { + ++this.noActionTime; ++ if (!this.aware) return; // CraftBukkit + this.level().getProfiler().push("sensing"); + this.sensing.tick(); + this.level().getProfiler().pop(); +@@ -1211,6 +1270,12 @@ + if (!this.isAlive()) { + return InteractionResult.PASS; + } else if (this.getLeashHolder() == player) { ++ // CraftBukkit start - fire PlayerUnleashEntityEvent ++ if (CraftEventFactory.callPlayerUnleashEntityEvent(this, player, hand).isCancelled()) { ++ ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, this.getLeashHolder())); ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.dropLeash(true, !player.getAbilities().instabuild); + this.gameEvent(GameEvent.ENTITY_INTERACT, player); + return InteractionResult.sidedSuccess(this.level().isClientSide); +@@ -1236,6 +1301,12 @@ + ItemStack itemstack = player.getItemInHand(interactionhand); + + if (itemstack.is(Items.LEAD) && this.canBeLeashed(player)) { ++ // CraftBukkit start - fire PlayerLeashEntityEvent ++ if (CraftEventFactory.callPlayerLeashEntityEvent(this, player, player, hand).isCancelled()) { ++ ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, this.getLeashHolder())); ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.setLeashedTo(player, true); + itemstack.shrink(1); + return InteractionResult.sidedSuccess(this.level().isClientSide); +@@ -1301,8 +1372,15 @@ + return this.restrictRadius != -1.0F; + } + ++ // CraftBukkit start + @Nullable +- public T convertTo(EntityType entitytype, boolean flag) { ++ public T convertTo(EntityType entityType, boolean transferInventory) { ++ return this.convertTo(entityType, transferInventory, EntityTransformEvent.TransformReason.UNKNOWN, CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ @Nullable ++ public T convertTo(EntityType entitytypes, boolean flag, EntityTransformEvent.TransformReason transformReason, CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end + if (this.isRemoved()) { + return null; + } else { +@@ -1340,7 +1418,12 @@ + } + } + +- this.level().addFreshEntity(t0); ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, t0, transformReason).isCancelled()) { ++ return null; ++ } ++ this.level().addFreshEntity(t0, spawnReason); ++ // CraftBukkit end + if (this.isPassenger()) { + Entity entity = this.getVehicle(); + +@@ -1361,7 +1444,8 @@ + + if (this.leashHolder != null) { + if (!this.isAlive() || !this.leashHolder.isAlive()) { +- this.dropLeash(true, true); ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE)); // CraftBukkit ++ this.dropLeash(true, !this.leashHolder.pluginRemoved);// CraftBukkit - SPIGOT-7487: Don't drop leash, when the holder was removed by a plugin + } + + } +@@ -1371,8 +1455,10 @@ + if (this.leashHolder != null) { + this.leashHolder = null; + this.leashInfoTag = null; +- if (!this.level().isClientSide && flag1) { +- this.spawnAtLocation((ItemLike) Items.LEAD); ++ if (!this.level().isClientSide && dropLeash) { ++ this.forceDrops = true; // CraftBukkit ++ this.spawnAtLocation((IMaterial) Items.LEAD); ++ this.forceDrops = false; // CraftBukkit + } + + if (!this.level().isClientSide && flag && this.level() instanceof ServerLevel) { +@@ -1423,6 +1508,7 @@ + boolean flag1 = super.startRiding(entity, flag); + + if (flag1 && this.isLeashed()) { ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit + this.dropLeash(true, true); + } + +@@ -1447,7 +1533,9 @@ + } + + if (this.tickCount > 100) { +- this.spawnAtLocation((ItemLike) Items.LEAD); ++ this.forceDrops = true; // CraftBukkit ++ this.spawnAtLocation((IMaterial) Items.LEAD); ++ this.forceDrops = false; // CraftBukkit + this.leashInfoTag = null; + } + } +@@ -1532,7 +1617,14 @@ + int i = EnchantmentHelper.getFireAspect(this); + + if (i > 0) { +- entity.setSecondsOnFire(i * 4); ++ // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), i * 4); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ entity.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + + boolean flag = entity.hurt(this.damageSources().mobAttack(this), f); +@@ -1609,6 +1699,7 @@ + @Override + protected void removeAfterChangingDimensions() { + super.removeAfterChangingDimensions(); ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit + this.dropLeash(true, false); + this.getAllSlots().forEach((itemstack) -> { + if (!itemstack.isEmpty()) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/NeutralMob.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/NeutralMob.java.patch new file mode 100644 index 0000000000..d997e5441b --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/NeutralMob.java.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/entity/NeutralMob.java ++++ b/net/minecraft/world/entity/NeutralMob.java +@@ -108,7 +108,7 @@ + default void stopBeingAngry() { + this.setLastHurtByMob((LivingEntity) null); + this.setPersistentAngerTarget((UUID) null); +- this.setTarget((LivingEntity) null); ++ this.setTarget((LivingEntity) null, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET, true); // CraftBukkit + this.setRemainingPersistentAngerTime(0); + } + +@@ -121,6 +121,8 @@ + + void setTarget(@Nullable LivingEntity livingEntity); + ++ boolean setTarget(@Nullable LivingEntity entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent); // CraftBukkit ++ + boolean canAttack(LivingEntity entity); + + @Nullable diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/PathfinderMob.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/PathfinderMob.java.patch new file mode 100644 index 0000000000..1b7ee9be1f --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/PathfinderMob.java.patch @@ -0,0 +1,28 @@ +--- a/net/minecraft/world/entity/PathfinderMob.java ++++ b/net/minecraft/world/entity/PathfinderMob.java +@@ -8,6 +8,9 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.event.entity.EntityUnleashEvent; ++// CraftBukkit end + + public abstract class PathfinderMob extends Mob { + +@@ -53,6 +54,7 @@ + + if (this instanceof TamableAnimal && ((TamableAnimal) this).isInSittingPose()) { + if (f > 10.0F) { ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit + this.dropLeash(true, true); + } + +@@ -61,6 +63,7 @@ + + this.onLeashDistance(f); + if (f > 10.0F) { ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit + this.dropLeash(true, true); + this.goalSelector.disableControlFlag(Goal.Flag.MOVE); + } else if (f > 6.0F) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/attributes/Attributes.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/attributes/Attributes.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/attributes/Attributes.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java.patch new file mode 100644 index 0000000000..293e20b291 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java ++++ b/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java +@@ -9,6 +9,12 @@ + import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.entity.npc.VillagerProfession; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftVillager; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.VillagerCareerChangeEvent; ++// CraftBukkit end ++ + public class AssignProfessionFromJobSite { + + public AssignProfessionFromJobSite() {} +@@ -37,8 +43,15 @@ + return villagerprofession.heldJobSite().test(holder); + }).findFirst(); + }).ifPresent((villagerprofession) -> { +- villager.setVillagerData(villager.getVillagerData().setProfession(villagerprofession)); +- villager.refreshBrain(serverlevel); ++ // CraftBukkit start - Fire VillagerCareerChangeEvent where Villager gets employed ++ VillagerCareerChangeEvent event = CraftEventFactory.callVillagerCareerChangeEvent(entityvillager, CraftVillager.CraftProfession.minecraftToBukkit(villagerprofession), VillagerCareerChangeEvent.ChangeReason.EMPLOYED); ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ entityvillager.setVillagerData(entityvillager.getVillagerData().setProfession(CraftVillager.CraftProfession.bukkitToMinecraft(event.getProfession()))); ++ // CraftBukkit end ++ entityvillager.refreshBrain(worldserver); + }); + return true; + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java.patch new file mode 100644 index 0000000000..d036d0e4d1 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java ++++ b/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java +@@ -7,6 +7,12 @@ + import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + import net.minecraft.world.entity.ai.memory.WalkTarget; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++// CraftBukkit end + + public class BabyFollowAdult { + +@@ -25,10 +31,21 @@ + if (!ageablemob.isBaby()) { + return false; + } else { +- AgeableMob ageablemob1 = (AgeableMob) behaviorbuilder_instance.get(memoryaccessor); ++ LivingEntity entityageable1 = (AgeableMob) behaviorbuilder_b.get(memoryaccessor); // CraftBukkit - type + +- if (ageablemob.closerThan(ageablemob1, (double) (uniformint.getMaxValue() + 1)) && !ageablemob.closerThan(ageablemob1, (double) uniformint.getMinValue())) { +- WalkTarget walktarget = new WalkTarget(new EntityTracker(ageablemob1, false), (Float) function.apply(ageablemob), uniformint.getMinValue() - 1); ++ if (entityageable.closerThan(entityageable1, (double) (followRange.getMaxValue() + 1)) && !entityageable.closerThan(entityageable1, (double) followRange.getMinValue())) { ++ // CraftBukkit start ++ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(entityageable, entityageable1, EntityTargetEvent.TargetReason.FOLLOW_LEADER); ++ if (event.isCancelled()) { ++ return false; ++ } ++ if (event.getTarget() == null) { ++ memoryaccessor.erase(); ++ return true; ++ } ++ entityageable1 = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ // CraftBukkit end ++ WalkTarget memorytarget = new WalkTarget(new EntityTracker(entityageable1, false), (Float) speedModifier.apply(entityageable), followRange.getMinValue() - 1); + + memoryaccessor1.set(new EntityTracker(ageablemob1, true)); + memoryaccessor2.set(walktarget); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java.patch new file mode 100644 index 0000000000..4e842e3a81 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java ++++ b/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java +@@ -91,17 +91,25 @@ + throwItem(livingentity, itemstack, vec3, vec31, 0.3F); + } + +- public static void throwItem(LivingEntity livingentity, ItemStack itemstack, Vec3 vec3, Vec3 vec31, float f) { +- double d0 = livingentity.getEyeY() - (double) f; +- ItemEntity itementity = new ItemEntity(livingentity.level(), livingentity.getX(), d0, livingentity.getZ(), itemstack); ++ public static void throwItem(LivingEntity entity, ItemStack stack, Vec3 offset, Vec3 speedMultiplier, float yOffset) { ++ if (stack.isEmpty()) return; // CraftBukkit - SPIGOT-4940: no empty loot ++ double d0 = entity.getEyeY() - (double) yOffset; ++ ItemEntity entityitem = new ItemEntity(entity.level(), entity.getX(), d0, entity.getZ(), stack); + + itementity.setThrower(livingentity); + Vec3 vec32 = vec3.subtract(livingentity.position()); + +- vec32 = vec32.normalize().multiply(vec31.x, vec31.y, vec31.z); +- itementity.setDeltaMovement(vec32); +- itementity.setDefaultPickUpDelay(); +- livingentity.level().addFreshEntity(itementity); ++ vec3d2 = vec3d2.normalize().multiply(speedMultiplier.x, speedMultiplier.y, speedMultiplier.z); ++ entityitem.setDeltaMovement(vec3d2); ++ entityitem.setDefaultPickUpDelay(); ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(entity.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ entityitem.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ entity.level().addFreshEntity(entityitem); + } + + public static SectionPos findSectionClosestToVillage(ServerLevel serverlevel, SectionPos sectionpos, int i) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java.patch new file mode 100644 index 0000000000..916a7f852c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java.patch @@ -0,0 +1,32 @@ +--- a/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java ++++ b/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java +@@ -27,11 +27,25 @@ + return (serverlevel, livingentity, j) -> { + ItemEntity itementity = (ItemEntity) behaviorbuilder_instance.get(memoryaccessor2); + +- if (behaviorbuilder_instance.tryGet(memoryaccessor3).isEmpty() && predicate.test(livingentity) && itementity.closerThan(livingentity, (double) i) && livingentity.level().getWorldBorder().isWithinBounds(itementity.blockPosition())) { +- WalkTarget walktarget = new WalkTarget(new EntityTracker(itementity, false), f, 0); ++ if (behaviorbuilder_b.tryGet(memoryaccessor3).isEmpty() && canWalkToItem.test(entityliving) && entityitem.closerThan(entityliving, (double) maxDistToWalk) && entityliving.level().getWorldBorder().isWithinBounds(entityitem.blockPosition())) { ++ // CraftBukkit start ++ if (entityliving instanceof net.minecraft.world.entity.animal.allay.Allay) { ++ org.bukkit.event.entity.EntityTargetEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTargetEvent(entityliving, entityitem, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_ENTITY); + +- memoryaccessor.set(new EntityTracker(itementity, true)); +- memoryaccessor1.set(walktarget); ++ if (event.isCancelled()) { ++ return false; ++ } ++ if (!(event.getTarget() instanceof ItemEntity)) { ++ memoryaccessor2.erase(); ++ } ++ ++ entityitem = (ItemEntity) ((org.bukkit.craftbukkit.entity.CraftEntity) event.getTarget()).getHandle(); ++ } ++ // CraftBukkit end ++ WalkTarget memorytarget = new WalkTarget(new EntityTracker(entityitem, false), speedModifier, 0); ++ ++ memoryaccessor.set(new EntityTracker(entityitem, true)); ++ memoryaccessor1.set(memorytarget); + return true; + } else { + return false; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java.patch new file mode 100644 index 0000000000..9a8b798fe4 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java ++++ b/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java +@@ -21,10 +21,15 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.gameevent.GameEvent; ++ ++// CraftBukkit start ++import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.CropBlock; + import net.minecraft.world.level.block.FarmBlock; +-import net.minecraft.world.level.block.state.BlockState; +-import net.minecraft.world.level.gameevent.GameEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class HarvestFarmland extends Behavior { + +@@ -105,8 +106,10 @@ + Block block = blockstate.getBlock(); + Block block1 = serverlevel.getBlockState(this.aboveFarmlandPos.below()).getBlock(); + +- if (block instanceof CropBlock && ((CropBlock) block).isMaxAge(blockstate)) { +- serverlevel.destroyBlock(this.aboveFarmlandPos, true, villager); ++ if (block instanceof CropBlock && ((CropBlock) block).isMaxAge(iblockdata)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(owner, this.aboveFarmlandPos, Blocks.AIR.defaultBlockState())) { // CraftBukkit ++ level.destroyBlock(this.aboveFarmlandPos, true, owner); ++ } // CraftBukkit + } + + if (blockstate.isAir() && block1 instanceof FarmBlock && villager.hasFarmSeeds()) { +@@ -123,9 +126,11 @@ + BlockItem blockitem = (BlockItem) item; + BlockState blockstate1 = blockitem.getBlock().defaultBlockState(); + +- serverlevel.setBlockAndUpdate(this.aboveFarmlandPos, blockstate1); +- serverlevel.gameEvent(GameEvent.BLOCK_PLACE, this.aboveFarmlandPos, GameEvent.Context.of(villager, blockstate1)); ++ if (CraftEventFactory.callEntityChangeBlockEvent(owner, this.aboveFarmlandPos, iblockdata1)) { // CraftBukkit ++ level.setBlockAndUpdate(this.aboveFarmlandPos, iblockdata1); ++ level.gameEvent(GameEvent.BLOCK_PLACE, this.aboveFarmlandPos, GameEvent.Context.of(owner, iblockdata1)); + flag = true; ++ } // CraftBukkit + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java.patch new file mode 100644 index 0000000000..5929a6db5d --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java ++++ b/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java +@@ -60,8 +60,15 @@ + })) { + DoorBlock doorblock = (DoorBlock) blockstate.getBlock(); + +- if (!doorblock.isOpen(blockstate)) { +- doorblock.setOpen(livingentity, serverlevel, blockstate, blockpos, true); ++ if (!blockdoor.isOpen(iblockdata)) { ++ // CraftBukkit start - entities opening doors ++ org.bukkit.event.entity.EntityInteractEvent event = new org.bukkit.event.entity.EntityInteractEvent(entityliving.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(entityliving.level(), blockposition)); ++ entityliving.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ blockdoor.setOpen(entityliving, worldserver, iblockdata, blockposition, true); + } + + optional = rememberDoorToClose(memoryaccessor1, optional, serverlevel, blockpos); +@@ -75,9 +82,16 @@ + })) { + DoorBlock doorblock1 = (DoorBlock) blockstate1.getBlock(); + +- if (!doorblock1.isOpen(blockstate1)) { +- doorblock1.setOpen(livingentity, serverlevel, blockstate1, blockpos1, true); +- optional = rememberDoorToClose(memoryaccessor1, optional, serverlevel, blockpos1); ++ if (!blockdoor1.isOpen(iblockdata1)) { ++ // CraftBukkit start - entities opening doors ++ org.bukkit.event.entity.EntityInteractEvent event = new org.bukkit.event.entity.EntityInteractEvent(entityliving.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(entityliving.level(), blockposition1)); ++ entityliving.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ blockdoor1.setOpen(entityliving, worldserver, iblockdata1, blockposition1, true); ++ optional = rememberDoorToClose(memoryaccessor1, optional, worldserver, blockposition1); + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java.patch new file mode 100644 index 0000000000..84e29804b4 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java ++++ b/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java +@@ -29,6 +30,10 @@ + import net.minecraft.world.level.pathfinder.Path; + import net.minecraft.world.level.pathfinder.WalkNodeEvaluator; + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end + + public class PrepareRamNearestTarget extends Behavior { + +@@ -62,8 +66,15 @@ + return nearestvisiblelivingentities.findClosest((livingentity) -> { + return this.ramTargeting.test(pathfindermob, livingentity); + }); +- }).ifPresent((livingentity) -> { +- this.chooseRamPosition(pathfindermob, livingentity); ++ }).ifPresent((entityliving) -> { ++ // CraftBukkit start ++ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entity, entityliving, (entityliving instanceof ServerPlayer) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.CLOSEST_ENTITY); ++ if (event.isCancelled() || event.getTarget() == null) { ++ return; ++ } ++ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ // CraftBukkit end ++ this.chooseRamPosition(entity, entityliving); + }); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/ResetProfession.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/ResetProfession.java.patch new file mode 100644 index 0000000000..1bc8e58c47 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/ResetProfession.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/entity/ai/behavior/ResetProfession.java ++++ b/net/minecraft/world/entity/ai/behavior/ResetProfession.java +@@ -6,6 +6,12 @@ + import net.minecraft.world.entity.npc.VillagerData; + import net.minecraft.world.entity.npc.VillagerProfession; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftVillager; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.VillagerCareerChangeEvent; ++// CraftBukkit end ++ + public class ResetProfession { + + public ResetProfession() {} +@@ -16,9 +22,16 @@ + return (serverlevel, villager, i) -> { + VillagerData villagerdata = villager.getVillagerData(); + +- if (villagerdata.getProfession() != VillagerProfession.NONE && villagerdata.getProfession() != VillagerProfession.NITWIT && villager.getVillagerXp() == 0 && villagerdata.getLevel() <= 1) { +- villager.setVillagerData(villager.getVillagerData().setProfession(VillagerProfession.NONE)); +- villager.refreshBrain(serverlevel); ++ if (villagerdata.getProfession() != VillagerProfession.NONE && villagerdata.getProfession() != VillagerProfession.NITWIT && entityvillager.getVillagerXp() == 0 && villagerdata.getLevel() <= 1) { ++ // CraftBukkit start ++ VillagerCareerChangeEvent event = CraftEventFactory.callVillagerCareerChangeEvent(entityvillager, CraftVillager.CraftProfession.minecraftToBukkit(VillagerProfession.NONE), VillagerCareerChangeEvent.ChangeReason.LOSING_JOB); ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ entityvillager.setVillagerData(entityvillager.getVillagerData().setProfession(CraftVillager.CraftProfession.bukkitToMinecraft(event.getProfession()))); ++ // CraftBukkit end ++ entityvillager.refreshBrain(worldserver); + return true; + } else { + return false; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/StartAttacking.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/StartAttacking.java.patch new file mode 100644 index 0000000000..d06873d925 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/StartAttacking.java.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/world/entity/ai/behavior/StartAttacking.java ++++ b/net/minecraft/world/entity/ai/behavior/StartAttacking.java +@@ -7,6 +8,10 @@ + import net.minecraft.world.entity.Mob; + import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end + + public class StartAttacking { + +@@ -35,7 +40,18 @@ + if (!mob.canAttack(livingentity)) { + return false; + } else { +- memoryaccessor.set(livingentity); ++ // CraftBukkit start ++ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entityinsentient, entityliving, (entityliving instanceof ServerPlayer) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.CLOSEST_ENTITY); ++ if (event.isCancelled()) { ++ return false; ++ } ++ if (event.getTarget() == null) { ++ memoryaccessor.erase(); ++ return true; ++ } ++ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ // CraftBukkit end ++ memoryaccessor.set(entityliving); + memoryaccessor1.erase(); + return true; + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java.patch new file mode 100644 index 0000000000..5d5b0c7ab5 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java ++++ b/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java +@@ -8,6 +8,12 @@ + import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end ++ + public class StopAttackingIfTargetInvalid { + + private static final int TIMEOUT_TO_GET_WITHIN_ATTACK_RANGE = 200; +@@ -41,7 +47,19 @@ + if (mob.canAttack(livingentity) && (!flag || !isTiredOfTryingToReachTarget(mob, behaviorbuilder_instance.tryGet(memoryaccessor1))) && livingentity.isAlive() && livingentity.level() == mob.level() && !predicate.test(livingentity)) { + return true; + } else { +- biconsumer.accept(mob, livingentity); ++ // CraftBukkit start ++ LivingEntity old = entityinsentient.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); ++ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entityinsentient, null, (old != null && !old.isAlive()) ? EntityTargetEvent.TargetReason.TARGET_DIED : EntityTargetEvent.TargetReason.FORGOT_TARGET); ++ if (event.isCancelled()) { ++ return false; ++ } ++ if (event.getTarget() == null) { ++ memoryaccessor.erase(); ++ return true; ++ } ++ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ // CraftBukkit end ++ onStopAttacking.accept(entityinsentient, entityliving); + memoryaccessor.erase(); + return true; + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java.patch new file mode 100644 index 0000000000..020f4f13a9 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java ++++ b/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java +@@ -17,6 +17,10 @@ + import net.minecraft.world.entity.ai.village.poi.PoiTypes; + import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.level.pathfinder.Path; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++// CraftBukkit end + + public class VillagerMakeLove extends Behavior { + +@@ -121,13 +120,19 @@ + if (villager2 == null) { + return Optional.empty(); + } else { +- villager.setAge(6000); +- villager1.setAge(6000); +- villager2.setAge(-24000); +- villager2.moveTo(villager.getX(), villager.getY(), villager.getZ(), 0.0F, 0.0F); +- serverlevel.addFreshEntityWithPassengers(villager2); +- serverlevel.broadcastEntityEvent(villager2, (byte) 12); +- return Optional.of(villager2); ++ entityvillager2.setAge(-24000); ++ entityvillager2.moveTo(parent.getX(), parent.getY(), parent.getZ(), 0.0F, 0.0F); ++ // CraftBukkit start - call EntityBreedEvent ++ if (CraftEventFactory.callEntityBreedEvent(entityvillager2, parent, partner, null, null, 0).isCancelled()) { ++ return Optional.empty(); ++ } ++ // Move age setting down ++ parent.setAge(6000); ++ partner.setAge(6000); ++ level.addFreshEntityWithPassengers(entityvillager2, CreatureSpawnEvent.SpawnReason.BREEDING); ++ // CraftBukkit end ++ level.broadcastEntityEvent(entityvillager2, (byte) 12); ++ return Optional.of(entityvillager2); + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java.patch new file mode 100644 index 0000000000..a4cc73ca81 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java ++++ b/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java +@@ -76,6 +71,12 @@ + } + + if (this.breakTime == this.getDoorBreakTime() && this.isValidDifficulty(this.mob.level().getDifficulty())) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreakDoorEvent(this.mob, this.doorPos).isCancelled()) { ++ this.start(); ++ return; ++ } ++ // CraftBukkit end + this.mob.level().removeBlock(this.doorPos, false); + this.mob.level().levelEvent(1021, this.doorPos, 0); + this.mob.level().levelEvent(2001, this.doorPos, Block.getId(this.mob.level().getBlockState(this.doorPos))); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/EatBlockGoal.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/EatBlockGoal.java.patch new file mode 100644 index 0000000000..03ac06a116 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/EatBlockGoal.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/entity/ai/goal/EatBlockGoal.java ++++ b/net/minecraft/world/entity/ai/goal/EatBlockGoal.java +@@ -11,6 +11,10 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.block.state.predicate.BlockStatePredicate; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class EatBlockGoal extends Goal { + + private static final int EAT_ANIMATION_TICKS = 40; +@@ -68,19 +67,19 @@ + if (this.eatAnimationTick == this.adjustedTickDelay(4)) { + BlockPos blockpos = this.mob.blockPosition(); + +- if (EatBlockGoal.IS_TALL_GRASS.test(this.level.getBlockState(blockpos))) { +- if (this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- this.level.destroyBlock(blockpos, false); ++ if (EatBlockGoal.IS_TALL_GRASS.test(this.level.getBlockState(blockposition))) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition, Blocks.AIR.defaultBlockState(), !this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit ++ this.level.destroyBlock(blockposition, false); + } + + this.mob.ate(); + } else { + BlockPos blockpos1 = blockpos.below(); + +- if (this.level.getBlockState(blockpos1).is(Blocks.GRASS_BLOCK)) { +- if (this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- this.level.levelEvent(2001, blockpos1, Block.getId(Blocks.GRASS_BLOCK.defaultBlockState())); +- this.level.setBlock(blockpos1, Blocks.DIRT.defaultBlockState(), 2); ++ if (this.level.getBlockState(blockposition1).is(Blocks.GRASS_BLOCK)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition1, Blocks.AIR.defaultBlockState(), !this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit ++ this.level.levelEvent(2001, blockposition1, Block.getId(Blocks.GRASS_BLOCK.defaultBlockState())); ++ this.level.setBlock(blockposition1, Blocks.DIRT.defaultBlockState(), 2); + } + + this.mob.ate(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java.patch new file mode 100644 index 0000000000..d686adb2a5 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java ++++ b/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java +@@ -13,6 +13,11 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.level.pathfinder.WalkNodeEvaluator; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTeleportEvent; ++// CraftBukkit end + + public class FollowOwnerGoal extends Goal { + +@@ -127,7 +127,14 @@ + } else if (!this.canTeleportTo(new BlockPos(i, j, k))) { + return false; + } else { +- this.tamable.moveTo((double) i + 0.5D, (double) j, (double) k + 0.5D, this.tamable.getYRot(), this.tamable.getXRot()); ++ // CraftBukkit start ++ EntityTeleportEvent event = CraftEventFactory.callEntityTeleportEvent(this.tamable, (double) x + 0.5D, (double) y, (double) z + 0.5D); ++ if (event.isCancelled()) { ++ return false; ++ } ++ Location to = event.getTo(); ++ this.tamable.moveTo(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch()); ++ // CraftBukkit end + this.navigation.stop(); + return true; + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java.patch new file mode 100644 index 0000000000..93948419de --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java ++++ b/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java +@@ -20,6 +20,10 @@ + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class RemoveBlockGoal extends MoveToBlockGoal { + +@@ -100,8 +100,13 @@ + } + + if (this.ticksSinceReachedGoal > 60) { +- level.removeBlock(blockpos1, false); +- if (!level.isClientSide) { ++ // CraftBukkit start - Step on eggs ++ if (!CraftEventFactory.callEntityInteractEvent(this.removerMob, CraftBlock.at(world, blockposition1))) { ++ return; ++ } ++ // CraftBukkit end ++ world.removeBlock(blockposition1, false); ++ if (!world.isClientSide) { + for (int i = 0; i < 20; ++i) { + d0 = randomsource.nextGaussian() * 0.02D; + double d1 = randomsource.nextGaussian() * 0.02D; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java.patch new file mode 100644 index 0000000000..ec6c6ee0ba --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java ++++ b/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java +@@ -6,6 +6,10 @@ + import net.minecraft.world.entity.animal.horse.AbstractHorse; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class RunAroundLikeCrazyGoal extends Goal { + +@@ -67,8 +67,8 @@ + int i = this.horse.getTemper(); + int j = this.horse.getMaxTemper(); + +- if (j > 0 && this.horse.getRandom().nextInt(j) < i) { +- this.horse.tameWithName(player); ++ if (j > 0 && this.horse.getRandom().nextInt(j) < i && !CraftEventFactory.callEntityTameEvent(this.horse, ((CraftHumanEntity) this.horse.getBukkitEntity().getPassenger()).getHandle()).isCancelled()) { // CraftBukkit - fire EntityTameEvent ++ this.horse.tameWithName(entityhuman); + return; + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java.patch new file mode 100644 index 0000000000..c9bfae21ad --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java ++++ b/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java +@@ -24,7 +22,7 @@ + @Override + public boolean canUse() { + if (!this.mob.isTame()) { +- return false; ++ return this.mob.isOrderedToSit() && this.mob.getTarget() == null; // CraftBukkit - Allow sitting for wild animals + } else if (this.mob.isInWaterOrBubble()) { + return false; + } else if (!this.mob.onGround()) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/TemptGoal.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/TemptGoal.java.patch new file mode 100644 index 0000000000..7fd5e8a4ff --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/goal/TemptGoal.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/entity/ai/goal/TemptGoal.java ++++ b/net/minecraft/world/entity/ai/goal/TemptGoal.java +@@ -8,6 +7,12 @@ + import net.minecraft.world.entity.ai.targeting.TargetingConditions; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.crafting.Ingredient; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++// CraftBukkit end + + public class TemptGoal extends Goal { + +@@ -21,7 +26,7 @@ + private double pRotX; + private double pRotY; + @Nullable +- protected Player player; ++ protected LivingEntity player; // CraftBukkit + private int calmDown; + private boolean isRunning; + private final Ingredient items; +@@ -44,6 +48,15 @@ + return false; + } else { + this.player = this.mob.level().getNearestPlayer(this.targetingConditions, this.mob); ++ // CraftBukkit start ++ if (this.player != null) { ++ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(this.mob, this.player, EntityTargetEvent.TargetReason.TEMPT); ++ if (event.isCancelled()) { ++ return false; ++ } ++ this.player = (event.getTarget() == null) ? null : ((CraftLivingEntity) event.getTarget()).getHandle(); ++ } ++ // CraftBukkit end + return this.player != null; + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/sensing/TemptingSensor.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/sensing/TemptingSensor.java.patch new file mode 100644 index 0000000000..26a9813353 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/sensing/TemptingSensor.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/entity/ai/sensing/TemptingSensor.java ++++ b/net/minecraft/world/entity/ai/sensing/TemptingSensor.java +@@ -17,6 +17,13 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.crafting.Ingredient; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++// CraftBukkit end + + public class TemptingSensor extends Sensor { + +@@ -45,7 +51,17 @@ + if (!list.isEmpty()) { + Player player = (Player) list.get(0); + +- brain.setMemory(MemoryModuleType.TEMPTING_PLAYER, (Object) player); ++ // CraftBukkit start ++ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(entity, entityhuman, EntityTargetEvent.TargetReason.TEMPT); ++ if (event.isCancelled()) { ++ return; ++ } ++ if (event.getTarget() instanceof HumanEntity) { ++ behaviorcontroller.setMemory(MemoryModuleType.TEMPTING_PLAYER, ((CraftHumanEntity) event.getTarget()).getHandle()); ++ } else { ++ behaviorcontroller.eraseMemory(MemoryModuleType.TEMPTING_PLAYER); ++ } ++ // CraftBukkit end + } else { + brain.eraseMemory(MemoryModuleType.TEMPTING_PLAYER); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/village/VillageSiege.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/village/VillageSiege.java.patch new file mode 100644 index 0000000000..95afc35501 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ai/village/VillageSiege.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/entity/ai/village/VillageSiege.java ++++ b/net/minecraft/world/entity/ai/village/VillageSiege.java +@@ -122,8 +121,8 @@ + return; + } + +- zombie.moveTo(vec3.x, vec3.y, vec3.z, serverlevel.random.nextFloat() * 360.0F, 0.0F); +- serverlevel.addFreshEntityWithPassengers(zombie); ++ entityzombie.moveTo(vec3d.x, vec3d.y, vec3d.z, level.random.nextFloat() * 360.0F, 0.0F); ++ level.addFreshEntityWithPassengers(entityzombie, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_INVASION); // CraftBukkit + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ambient/Bat.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ambient/Bat.java.patch new file mode 100644 index 0000000000..7419cd3d85 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/ambient/Bat.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/world/entity/ambient/Bat.java ++++ b/net/minecraft/world/entity/ambient/Bat.java +@@ -28,6 +28,9 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class Bat extends AmbientCreature { + +@@ -155,13 +146,13 @@ + this.yHeadRot = (float) this.random.nextInt(360); + } + +- if (this.level().getNearestPlayer(Bat.BAT_RESTING_TARGETING, this) != null) { ++ if (this.level().getNearestPlayer(Bat.BAT_RESTING_TARGETING, this) != null && CraftEventFactory.handleBatToggleSleepEvent(this, true)) { // CraftBukkit - Call BatToggleSleepEvent + this.setResting(false); + if (!flag) { + this.level().levelEvent((Player) null, 1025, blockpos, 0); + } + } +- } else { ++ } else if (CraftEventFactory.handleBatToggleSleepEvent(this, true)) { // CraftBukkit - Call BatToggleSleepEvent + this.setResting(false); + if (!flag) { + this.level().levelEvent((Player) null, 1025, blockpos, 0); +@@ -188,7 +179,7 @@ + + this.zza = 0.5F; + this.setYRot(this.getYRot() + f1); +- if (this.random.nextInt(100) == 0 && this.level().getBlockState(blockpos1).isRedstoneConductor(this.level(), blockpos1)) { ++ if (this.random.nextInt(100) == 0 && this.level().getBlockState(blockposition1).isRedstoneConductor(this.level(), blockposition1) && CraftEventFactory.handleBatToggleSleepEvent(this, false)) { // CraftBukkit - Call BatToggleSleepEvent + this.setResting(true); + } + } +@@ -217,7 +204,7 @@ + if (this.isInvulnerableTo(damagesource)) { + return false; + } else { +- if (!this.level().isClientSide && this.isResting()) { ++ if (!this.level().isClientSide && this.isResting() && CraftEventFactory.handleBatToggleSleepEvent(this, true)) { // CraftBukkit - Call BatToggleSleepEvent + this.setResting(false); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Animal.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Animal.java.patch new file mode 100644 index 0000000000..d7c2f54549 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Animal.java.patch @@ -0,0 +1,115 @@ +--- a/net/minecraft/world/entity/animal/Animal.java ++++ b/net/minecraft/world/entity/animal/Animal.java +@@ -29,13 +29,19 @@ + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.pathfinder.BlockPathTypes; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityBreedEvent; ++import org.bukkit.event.entity.EntityEnterLoveModeEvent; ++// CraftBukkit end + + public abstract class Animal extends AgeableMob { + + protected static final int PARENT_AGE_AFTER_BREEDING = 6000; + private int inLove; + @Nullable +- private UUID loveCause; ++ public UUID loveCause; ++ public ItemStack breedItem; // CraftBukkit - Add breedItem variable + + protected Animal(EntityType entitytype, Level level) { + super(entitytype, level); +@@ -80,8 +83,13 @@ + if (this.isInvulnerableTo(damagesource)) { + return false; + } else { ++ // CraftBukkit start ++ boolean result = super.hurt(source, amount); ++ if (result) { + this.inLove = 0; +- return super.hurt(damagesource, f); ++ } ++ return result; ++ // CraftBukkit end + } + } + +@@ -182,10 +183,17 @@ + } + + public void setInLove(@Nullable Player player) { +- this.inLove = 600; ++ // CraftBukkit start ++ EntityEnterLoveModeEvent entityEnterLoveModeEvent = CraftEventFactory.callEntityEnterLoveModeEvent(player, this, 600); ++ if (entityEnterLoveModeEvent.isCancelled()) { ++ return; ++ } ++ this.inLove = entityEnterLoveModeEvent.getTicksInLove(); ++ // CraftBukkit end + if (player != null) { + this.loveCause = player.getUUID(); + } ++ this.breedItem = player.getInventory().getSelected(); // CraftBukkit + + this.level().broadcastEntityEvent(this, (byte) 18); + } +@@ -224,15 +232,32 @@ + public void spawnChildFromBreeding(ServerLevel serverlevel, Animal animal) { + AgeableMob ageablemob = this.getBreedOffspring(serverlevel, animal); + +- if (ageablemob != null) { +- ageablemob.setBaby(true); +- ageablemob.moveTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F); +- this.finalizeSpawnChildFromBreeding(serverlevel, animal, ageablemob); +- serverlevel.addFreshEntityWithPassengers(ageablemob); ++ if (entityageable != null) { ++ entityageable.setBaby(true); ++ entityageable.moveTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F); ++ // CraftBukkit start - call EntityBreedEvent ++ ServerPlayer breeder = Optional.ofNullable(this.getLoveCause()).or(() -> { ++ return Optional.ofNullable(mate.getLoveCause()); ++ }).orElse(null); ++ int experience = this.getRandom().nextInt(7) + 1; ++ EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(entityageable, this, mate, breeder, this.breedItem, experience); ++ if (entityBreedEvent.isCancelled()) { ++ return; ++ } ++ experience = entityBreedEvent.getExperience(); ++ this.finalizeSpawnChildFromBreeding(level, mate, entityageable, experience); ++ level.addFreshEntityWithPassengers(entityageable, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); ++ // CraftBukkit end + } + } + +- public void finalizeSpawnChildFromBreeding(ServerLevel serverlevel, Animal animal, @Nullable AgeableMob ageablemob) { ++ public void finalizeSpawnChildFromBreeding(ServerLevel level, Animal animal, @Nullable AgeableMob baby) { ++ // CraftBukkit start ++ this.finalizeSpawnChildFromBreeding(level, animal, baby, this.getRandom().nextInt(7) + 1); ++ } ++ ++ public void finalizeSpawnChildFromBreeding(ServerLevel worldserver, Animal entityanimal, @Nullable AgeableMob entityageable, int experience) { ++ // CraftBukkit end + Optional.ofNullable(this.getLoveCause()).or(() -> { + return Optional.ofNullable(animal.getLoveCause()); + }).ifPresent((serverplayer) -> { +@@ -242,10 +267,14 @@ + this.setAge(6000); + animal.setAge(6000); + this.resetLove(); +- animal.resetLove(); +- serverlevel.broadcastEntityEvent(this, (byte) 18); +- if (serverlevel.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +- serverlevel.addFreshEntity(new ExperienceOrb(serverlevel, this.getX(), this.getY(), this.getZ(), this.getRandom().nextInt(7) + 1)); ++ entityanimal.resetLove(); ++ worldserver.broadcastEntityEvent(this, (byte) 18); ++ if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { ++ // CraftBukkit start - use event experience ++ if (experience > 0) { ++ worldserver.addFreshEntity(new ExperienceOrb(worldserver, this.getX(), this.getY(), this.getZ(), experience)); ++ } ++ // CraftBukkit end + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Bee.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Bee.java.patch new file mode 100644 index 0000000000..3b5f28a11a --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Bee.java.patch @@ -0,0 +1,115 @@ +--- a/net/minecraft/world/entity/animal/Bee.java ++++ b/net/minecraft/world/entity/animal/Bee.java +@@ -89,6 +89,11 @@ + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.level.pathfinder.Path; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityPotionEffectEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end + + public class Bee extends Animal implements NeutralMob, FlyingAnimal { + +@@ -189,15 +191,21 @@ + } + + @Override ++ public void addAdditionalSaveData(CompoundTag compound) { ++ // CraftBukkit start - selectively save data ++ addAdditionalSaveData(compound, true); ++ } ++ + @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- if (this.hasHive()) { +- compoundtag.put("HivePos", NbtUtils.writeBlockPos(this.getHivePos())); ++ public void addAdditionalSaveData(CompoundTag nbttagcompound, boolean includeAll) { ++ // CraftBukkit end ++ super.addAdditionalSaveData(nbttagcompound); ++ if (includeAll && this.hasHive()) { // CraftBukkit - selectively save hive ++ nbttagcompound.put("HivePos", NbtUtils.writeBlockPos(this.getHivePos())); + } + +- if (this.hasSavedFlowerPos()) { +- compoundtag.put("FlowerPos", NbtUtils.writeBlockPos(this.getSavedFlowerPos())); ++ if (includeAll && this.hasSavedFlowerPos()) { // CraftBukkit - selectively save flower ++ nbttagcompound.put("FlowerPos", NbtUtils.writeBlockPos(this.getSavedFlowerPos())); + } + + compoundtag.putBoolean("HasNectar", this.hasNectar()); +@@ -248,7 +254,7 @@ + } + + if (b0 > 0) { +- ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.POISON, b0 * 20, 0), this); ++ ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.POISON, b0 * 20, 0), this, EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + +@@ -670,11 +652,14 @@ + if (this.isInvulnerableTo(damagesource)) { + return false; + } else { +- if (!this.level().isClientSide) { ++ // CraftBukkit start - Only stop pollinating if entity was damaged ++ boolean result = super.hurt(source, amount); ++ if (result && !this.level().isClientSide) { ++ // CraftBukkit end + this.beePollinateGoal.stopPollinating(); + } + +- return super.hurt(damagesource, f); ++ return result; // CraftBukkit + } + } + +@@ -1048,7 +1014,7 @@ + + BeeGoToHiveGoal() { + super(); +- this.travellingTicks = Bee.this.level().random.nextInt(10); ++ this.travellingTicks = Bee.this.random.nextInt(10); // CraftBukkit - SPIGOT-7495: Give Bees another chance and let them use their own random, avoid concurrency issues + this.blacklistedTargets = Lists.newArrayList(); + this.setFlags(EnumSet.of(Goal.Flag.MOVE)); + } +@@ -1170,8 +1131,8 @@ + + BeeGoToKnownFlowerGoal() { + super(); +- this.travellingTicks = Bee.this.level().random.nextInt(10); +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ this.travellingTicks = Bee.this.random.nextInt(10); // CraftBukkit - SPIGOT-7495: Give Bees another chance and let them use their own random, avoid concurrency issues ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +@@ -1278,9 +1231,9 @@ + } + } + +- if (blockstate1 != null) { +- Bee.this.level().levelEvent(2005, blockpos, 0); +- Bee.this.level().setBlockAndUpdate(blockpos, blockstate1); ++ if (iblockdata1 != null && CraftEventFactory.callEntityChangeBlockEvent(Bee.this, blockposition, iblockdata1)) { // CraftBukkit ++ Bee.this.level().levelEvent(2005, blockposition, 0); ++ Bee.this.level().setBlockAndUpdate(blockposition, iblockdata1); + Bee.this.incrementNumCropsGrownSincePollination(); + } + } +@@ -1353,10 +1302,9 @@ + } + + @Override +- @Override +- protected void alertOther(Mob mob, LivingEntity livingentity) { +- if (mob instanceof Bee && this.mob.hasLineOfSight(livingentity)) { +- mob.setTarget(livingentity); ++ protected void alertOther(Mob mob, LivingEntity target) { ++ if (mob instanceof Bee && this.mob.hasLineOfSight(target)) { ++ mob.setTarget(target, EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY, true); // CraftBukkit - reason + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Bucketable.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Bucketable.java.patch new file mode 100644 index 0000000000..7a07f25b49 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Bucketable.java.patch @@ -0,0 +1,41 @@ +--- a/net/minecraft/world/entity/animal/Bucketable.java ++++ b/net/minecraft/world/entity/animal/Bucketable.java +@@ -14,6 +15,10 @@ + import net.minecraft.world.item.ItemUtils; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerBucketEntityEvent; ++// CraftBukkit end + + public interface Bucketable { + +@@ -93,11 +98,23 @@ + static Optional bucketMobPickup(Player player, InteractionHand interactionhand, T t0) { + ItemStack itemstack = player.getItemInHand(interactionhand); + +- if (itemstack.getItem() == Items.WATER_BUCKET && t0.isAlive()) { +- t0.playSound(((Bucketable) t0).getPickupSound(), 1.0F, 1.0F); +- ItemStack itemstack1 = ((Bucketable) t0).getBucketItemStack(); ++ if (itemstack.getItem() == Items.WATER_BUCKET && entity.isAlive()) { ++ // CraftBukkit start ++ // t0.playSound(((Bucketable) t0).getPickupSound(), 1.0F, 1.0F); // CraftBukkit - moved down ++ ItemStack itemstack1 = ((Bucketable) entity).getBucketItemStack(); + +- ((Bucketable) t0).saveToBucketTag(itemstack1); ++ ((Bucketable) entity).saveToBucketTag(itemstack1); ++ ++ PlayerBucketEntityEvent playerBucketFishEvent = CraftEventFactory.callPlayerFishBucketEvent(entity, player, itemstack, itemstack1, hand); ++ itemstack1 = CraftItemStack.asNMSCopy(playerBucketFishEvent.getEntityBucket()); ++ if (playerBucketFishEvent.isCancelled()) { ++ ((ServerPlayer) player).containerMenu.sendAllDataToRemote(); // We need to update inventory to resync client's bucket ++ ((ServerPlayer) player).connection.send(new ClientboundAddEntityPacket(entity)); // We need to play out these packets as the client assumes the fish is gone ++ entity.getEntityData().refresh((ServerPlayer) player); // Need to send data such as the display name to client ++ return Optional.of(InteractionResult.FAIL); ++ } ++ entity.playSound(((Bucketable) entity).getPickupSound(), 1.0F, 1.0F); ++ // CraftBukkit end + ItemStack itemstack2 = ItemUtils.createFilledResult(itemstack, player, itemstack1, false); + + player.setItemInHand(interactionhand, itemstack2); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Cat.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Cat.java.patch new file mode 100644 index 0000000000..b0c0ac3937 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Cat.java.patch @@ -0,0 +1,39 @@ +--- a/net/minecraft/world/entity/animal/Cat.java ++++ b/net/minecraft/world/entity/animal/Cat.java +@@ -430,8 +412,8 @@ + } + } + } else if (this.isFood(itemstack)) { +- this.usePlayerItem(player, interactionhand, itemstack); +- if (this.random.nextInt(3) == 0) { ++ this.usePlayerItem(player, hand, itemstack); ++ if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit + this.tame(player); + this.setOrderedToSit(true); + this.level().broadcastEntityEvent(this, (byte) 7); +@@ -499,7 +475,7 @@ + private static class CatTemptGoal extends TemptGoal { + + @Nullable +- private Player selectedPlayer; ++ private LivingEntity selectedPlayer; // CraftBukkit + private final Cat cat; + + public CatTemptGoal(Cat cat, double d0, Ingredient ingredient, boolean flag) { +@@ -647,7 +616,15 @@ + while (iterator.hasNext()) { + ItemStack itemstack = (ItemStack) iterator.next(); + +- this.cat.level().addFreshEntity(new ItemEntity(this.cat.level(), (double) blockpos_mutableblockpos.getX() - (double) Mth.sin(this.cat.yBodyRot * 0.017453292F), (double) blockpos_mutableblockpos.getY(), (double) blockpos_mutableblockpos.getZ() + (double) Mth.cos(this.cat.yBodyRot * 0.017453292F), itemstack)); ++ // CraftBukkit start ++ ItemEntity entityitem = new ItemEntity(this.cat.level(), (double) blockposition_mutableblockposition.getX() - (double) Mth.sin(this.cat.yBodyRot * 0.017453292F), (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + (double) Mth.cos(this.cat.yBodyRot * 0.017453292F), itemstack); ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.cat.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ entityitem.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ continue; ++ } ++ this.cat.level().addFreshEntity(entityitem); ++ // CraftBukkit end + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Chicken.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Chicken.java.patch new file mode 100644 index 0000000000..fbe787042f --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Chicken.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/entity/animal/Chicken.java ++++ b/net/minecraft/world/entity/animal/Chicken.java +@@ -100,7 +97,9 @@ + this.flap += this.flapping * 2.0F; + if (!this.level().isClientSide && this.isAlive() && !this.isBaby() && !this.isChickenJockey() && --this.eggTime <= 0) { + this.playSound(SoundEvents.CHICKEN_EGG, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); +- this.spawnAtLocation((ItemLike) Items.EGG); ++ this.forceDrops = true; // CraftBukkit ++ this.spawnAtLocation((IMaterial) Items.EGG); ++ this.forceDrops = false; // CraftBukkit + this.gameEvent(GameEvent.ENTITY_PLACE); + this.eggTime = this.random.nextInt(6000) + 6000; + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Cow.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Cow.java.patch new file mode 100644 index 0000000000..135f6878b5 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Cow.java.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/world/entity/animal/Cow.java ++++ b/net/minecraft/world/entity/animal/Cow.java +@@ -33,6 +33,12 @@ + import net.minecraft.world.level.block.state.BlockState; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerBucketFillEvent; ++// CraftBukkit end ++ + public class Cow extends Animal { + + public Cow(EntityType entitytype, Level level) { +@@ -92,8 +91,16 @@ + ItemStack itemstack = player.getItemInHand(interactionhand); + + if (itemstack.is(Items.BUCKET) && !this.isBaby()) { ++ // CraftBukkit start - Got milk? ++ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level(), player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand); ++ ++ if (event.isCancelled()) { ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end ++ + player.playSound(SoundEvents.COW_MILK, 1.0F, 1.0F); +- ItemStack itemstack1 = ItemUtils.createFilledResult(itemstack, player, Items.MILK_BUCKET.getDefaultInstance()); ++ ItemStack itemstack1 = ItemUtils.createFilledResult(itemstack, player, CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit + + player.setItemInHand(interactionhand, itemstack1); + return InteractionResult.sidedSuccess(this.level().isClientSide); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Dolphin.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Dolphin.java.patch new file mode 100644 index 0000000000..c2a7096092 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Dolphin.java.patch @@ -0,0 +1,64 @@ +--- a/net/minecraft/world/entity/animal/Dolphin.java ++++ b/net/minecraft/world/entity/animal/Dolphin.java +@@ -60,9 +60,19 @@ + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityPotionEffectEvent; ++// CraftBukkit end + + public class Dolphin extends WaterAnimal { + ++ // CraftBukkit start - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ @Override ++ public int getDefaultMaxAirSupply() { ++ return TOTAL_AIR_SUPPLY; ++ } ++ // CraftBukkit end + private static final EntityDataAccessor TREASURE_POS = SynchedEntityData.defineId(Dolphin.class, EntityDataSerializers.BLOCK_POS); + private static final EntityDataAccessor GOT_FISH = SynchedEntityData.defineId(Dolphin.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor MOISTNESS_LEVEL = SynchedEntityData.defineId(Dolphin.class, EntityDataSerializers.INT); +@@ -194,7 +195,7 @@ + @Override + @Override + public int getMaxAirSupply() { +- return 4800; ++ return maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() + } + + @Override +@@ -242,7 +236,13 @@ + ItemStack itemstack = itementity.getItem(); + + if (this.canHoldItem(itemstack)) { +- this.onItemPickup(itementity); ++ // CraftBukkit start - call EntityPickupItemEvent ++ if (CraftEventFactory.callEntityPickupItemEvent(this, itemEntity, 0, false).isCancelled()) { ++ return; ++ } ++ itemstack = itemEntity.getItem(); // CraftBukkit- update ItemStack from event ++ // CraftBukkit start ++ this.onItemPickup(itemEntity); + this.setItemSlot(EquipmentSlot.MAINHAND, itemstack); + this.setGuaranteedDrop(EquipmentSlot.MAINHAND); + this.take(itementity, itemstack.getCount()); +@@ -519,7 +500,7 @@ + @Override + @Override + public void start() { +- this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin); ++ this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin, EntityPotionEffectEvent.Cause.DOLPHIN); // CraftBukkit + } + + @Override +@@ -540,7 +519,7 @@ + } + + if (this.player.isSwimming() && this.player.level().random.nextInt(6) == 0) { +- this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin); ++ this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin, EntityPotionEffectEvent.Cause.DOLPHIN); // CraftBukkit + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Fox.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Fox.java.patch new file mode 100644 index 0000000000..5d38bfb8b9 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Fox.java.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/entity/animal/Fox.java ++++ b/net/minecraft/world/entity/animal/Fox.java +@@ -542,7 +523,8 @@ + protected void pickUpItem(ItemEntity itementity) { + ItemStack itemstack = itementity.getItem(); + +- if (this.canHoldItem(itemstack)) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, itemEntity, itemstack.getCount() - 1, !this.canHoldItem(itemstack)).isCancelled()) { // CraftBukkit - call EntityPickupItemEvent ++ itemstack = itemEntity.getItem(); // CraftBukkit - update ItemStack from event + int i = itemstack.getCount(); + + if (i > 1) { +@@ -928,6 +884,16 @@ + if (serverplayer1 != null && serverplayer != serverplayer1) { + fox.addTrustedUUID(serverplayer1.getUUID()); + } ++ // CraftBukkit start - call EntityBreedEvent ++ entityfox.setAge(-24000); ++ entityfox.moveTo(this.animal.getX(), this.animal.getY(), this.animal.getZ(), 0.0F, 0.0F); ++ int experience = this.animal.getRandom().nextInt(7) + 1; ++ org.bukkit.event.entity.EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(entityfox, animal, partner, entityplayer, this.animal.breedItem, experience); ++ if (entityBreedEvent.isCancelled()) { ++ return; ++ } ++ experience = entityBreedEvent.getExperience(); ++ // CraftBukkit end + + if (serverplayer2 != null) { + serverplayer2.awardStat(Stats.ANIMALS_BRED); +@@ -938,12 +904,14 @@ + this.partner.setAge(6000); + this.animal.resetLove(); + this.partner.resetLove(); +- fox.setAge(-24000); +- fox.moveTo(this.animal.getX(), this.animal.getY(), this.animal.getZ(), 0.0F, 0.0F); +- serverlevel.addFreshEntityWithPassengers(fox); ++ worldserver.addFreshEntityWithPassengers(entityfox, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - added SpawnReason + this.level.broadcastEntityEvent(this.animal, (byte) 18); + if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), this.animal.getRandom().nextInt(7) + 1)); ++ // CraftBukkit start - use event experience ++ if (experience > 0) { ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience)); ++ } ++ // CraftBukkit end + } + + } +@@ -1367,7 +1306,12 @@ + private void pickSweetBerries(BlockState blockstate) { + int i = (Integer) blockstate.getValue(SweetBerryBushBlock.AGE); + +- blockstate.setValue(SweetBerryBushBlock.AGE, 1); ++ state.setValue(SweetBerryBushBlock.AGE, 1); ++ // CraftBukkit start - call EntityChangeBlockEvent ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(Fox.this, this.blockPos, state.setValue(SweetBerryBushBlock.AGE, 1))) { ++ return; ++ } ++ // CraftBukkit end + int j = 1 + Fox.this.level().random.nextInt(2) + (i == 3 ? 1 : 0); + ItemStack itemstack = Fox.this.getItemBySlot(EquipmentSlot.MAINHAND); + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/IronGolem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/IronGolem.java.patch new file mode 100644 index 0000000000..d6de83afda --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/IronGolem.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/entity/animal/IronGolem.java ++++ b/net/minecraft/world/entity/animal/IronGolem.java +@@ -105,8 +101,8 @@ + @Override + @Override + protected void doPush(Entity entity) { +- if (entity instanceof Enemy && !(entity instanceof Creeper) && this.getRandom().nextInt(20) == 0) { +- this.setTarget((LivingEntity) entity); ++ if (entity instanceof IMonster && !(entity instanceof Creeper) && this.getRandom().nextInt(20) == 0) { ++ this.setTarget((LivingEntity) entity, org.bukkit.event.entity.EntityTargetLivingEntityEvent.TargetReason.COLLISION, true); // CraftBukkit - set reason + } + + super.doPush(entity); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/MushroomCow.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/MushroomCow.java.patch new file mode 100644 index 0000000000..25a849b38f --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/MushroomCow.java.patch @@ -0,0 +1,73 @@ +--- a/net/minecraft/world/entity/animal/MushroomCow.java ++++ b/net/minecraft/world/entity/animal/MushroomCow.java +@@ -42,6 +42,13 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityDropItemEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++// CraftBukkit end ++ + public class MushroomCow extends Cow implements Shearable, VariantHolder { + + private static final EntityDataAccessor DATA_TYPE = SynchedEntityData.defineId(MushroomCow.class, EntityDataSerializers.STRING); +@@ -118,6 +121,11 @@ + this.playSound(soundevent, 1.0F, 1.0F); + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else if (itemstack.is(Items.SHEARS) && this.readyForShearing()) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) { ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.shear(SoundSource.PLAYERS); + this.gameEvent(GameEvent.SHEAR, player); + if (!this.level().isClientSide) { +@@ -166,10 +173,10 @@ + + if (cow != null) { + ((ServerLevel) this.level()).sendParticles(ParticleTypes.EXPLOSION, this.getX(), this.getY(0.5D), this.getZ(), 1, 0.0D, 0.0D, 0.0D, 0.0D); +- this.discard(); +- cow.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); +- cow.setHealth(this.getHealth()); +- cow.yBodyRot = this.yBodyRot; ++ // this.discard(); // CraftBukkit - moved down ++ entitycow.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); ++ entitycow.setHealth(this.getHealth()); ++ entitycow.yBodyRot = this.yBodyRot; + if (this.hasCustomName()) { + cow.setCustomName(this.getCustomName()); + cow.setCustomNameVisible(this.isCustomNameVisible()); +@@ -179,11 +186,26 @@ + cow.setPersistenceRequired(); + } + +- cow.setInvulnerable(this.isInvulnerable()); +- this.level().addFreshEntity(cow); ++ entitycow.setInvulnerable(this.isInvulnerable()); ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, entitycow, EntityTransformEvent.TransformReason.SHEARED).isCancelled()) { ++ return; ++ } ++ this.level().addFreshEntity(entitycow, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SHEARED); + ++ this.discard(); // CraftBukkit - from above ++ // CraftBukkit end ++ + for (int i = 0; i < 5; ++i) { +- this.level().addFreshEntity(new ItemEntity(this.level(), this.getX(), this.getY(1.0D), this.getZ(), new ItemStack(this.getVariant().blockState.getBlock()))); ++ // CraftBukkit start ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY(1.0D), this.getZ(), new ItemStack(this.getVariant().blockState.getBlock())); ++ EntityDropItemEvent event = new EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ continue; ++ } ++ this.level().addFreshEntity(entityitem); ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Ocelot.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Ocelot.java.patch new file mode 100644 index 0000000000..8a95a5861a --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Ocelot.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/animal/Ocelot.java ++++ b/net/minecraft/world/entity/animal/Ocelot.java +@@ -191,7 +179,7 @@ + if ((this.temptGoal == null || this.temptGoal.isRunning()) && !this.isTrusting() && this.isFood(itemstack) && player.distanceToSqr((Entity) this) < 9.0D) { + this.usePlayerItem(player, interactionhand, itemstack); + if (!this.level().isClientSide) { +- if (this.random.nextInt(3) == 0) { ++ if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit - added event call and isCancelled check + this.setTrusting(true); + this.spawnTrustingParticles(true); + this.level().broadcastEntityEvent(this, (byte) 41); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Panda.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Panda.java.patch new file mode 100644 index 0000000000..5d027ce3c7 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Panda.java.patch @@ -0,0 +1,39 @@ +--- a/net/minecraft/world/entity/animal/Panda.java ++++ b/net/minecraft/world/entity/animal/Panda.java +@@ -67,6 +67,11 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end ++ + public class Panda extends Animal { + + private static final EntityDataAccessor UNHAPPY_COUNTER = SynchedEntityData.defineId(Panda.class, EntityDataSerializers.INT); +@@ -543,11 +538,10 @@ + } + + @Override +- @Override +- protected void pickUpItem(ItemEntity itementity) { +- if (this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty() && Panda.PANDA_ITEMS.test(itementity)) { +- this.onItemPickup(itementity); +- ItemStack itemstack = itementity.getItem(); ++ protected void pickUpItem(ItemEntity itemEntity) { ++ if (!CraftEventFactory.callEntityPickupItemEvent(this, itemEntity, 0, !(this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty() && Panda.PANDA_ITEMS.test(itemEntity))).isCancelled()) { // CraftBukkit ++ this.onItemPickup(itemEntity); ++ ItemStack itemstack = itemEntity.getItem(); + + this.setItemSlot(EquipmentSlot.MAINHAND, itemstack); + this.setGuaranteedDrop(EquipmentSlot.MAINHAND); +@@ -1160,7 +1117,7 @@ + @Override + protected void alertOther(Mob mob, LivingEntity livingentity) { + if (mob instanceof Panda && mob.isAggressive()) { +- mob.setTarget(livingentity); ++ mob.setTarget(target, EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY, true); // CraftBukkit + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Parrot.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Parrot.java.patch new file mode 100644 index 0000000000..b0d4b5f8a0 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Parrot.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/world/entity/animal/Parrot.java ++++ b/net/minecraft/world/entity/animal/Parrot.java +@@ -272,7 +263,7 @@ + } + + if (!this.level().isClientSide) { +- if (this.random.nextInt(10) == 0) { ++ if (this.random.nextInt(10) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit + this.tame(player); + this.level().broadcastEntityEvent(this, (byte) 7); + } else { +@@ -286,7 +277,7 @@ + itemstack.shrink(1); + } + +- this.addEffect(new MobEffectInstance(MobEffects.POISON, 900)); ++ this.addEffect(new MobEffectInstance(MobEffects.POISON, 900), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.FOOD); // CraftBukkit + if (player.isCreative() || !this.isInvulnerable()) { + this.hurt(this.damageSources().playerAttack(player), Float.MAX_VALUE); + } +@@ -407,7 +384,7 @@ + @Override + @Override + public boolean isPushable() { +- return true; ++ return super.isPushable(); // CraftBukkit - collidable API + } + + @Override +@@ -424,11 +399,14 @@ + if (this.isInvulnerableTo(damagesource)) { + return false; + } else { +- if (!this.level().isClientSide) { ++ // CraftBukkit start ++ boolean result = super.hurt(source, amount); ++ if (!this.level().isClientSide && result) { ++ // CraftBukkit end + this.setOrderedToSit(false); + } + +- return super.hurt(damagesource, f); ++ return result; // CraftBukkit + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Pig.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Pig.java.patch new file mode 100644 index 0000000000..b9d1eaf983 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Pig.java.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/entity/animal/Pig.java ++++ b/net/minecraft/world/entity/animal/Pig.java +@@ -51,7 +51,9 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Pig extends Animal implements ItemSteerable, Saddleable { ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + private static final EntityDataAccessor DATA_SADDLE_ID = SynchedEntityData.defineId(Pig.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_BOOST_TIME = SynchedEntityData.defineId(Pig.class, EntityDataSerializers.INT); +@@ -268,8 +255,14 @@ + zombifiedpiglin.setCustomNameVisible(this.isCustomNameVisible()); + } + +- zombifiedpiglin.setPersistenceRequired(); +- serverlevel.addFreshEntity(zombifiedpiglin); ++ entitypigzombie.setPersistenceRequired(); ++ // CraftBukkit start ++ if (CraftEventFactory.callPigZapEvent(this, lightning, entitypigzombie).isCancelled()) { ++ return; ++ } ++ // CraftBukkit - added a reason for spawning this creature ++ level.addFreshEntity(entitypigzombie, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); ++ // CraftBukkit end + this.discard(); + } else { + super.thunderHit(serverlevel, lightningbolt); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Pufferfish.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Pufferfish.java.patch new file mode 100644 index 0000000000..3f402b8d8c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Pufferfish.java.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/entity/animal/Pufferfish.java ++++ b/net/minecraft/world/entity/animal/Pufferfish.java +@@ -152,7 +144,7 @@ + int i = this.getPuffState(); + + if (mob.hurt(this.damageSources().mobAttack(this), (float) (1 + i))) { +- mob.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * i, 0), this); ++ mob.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * i, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + this.playSound(SoundEvents.PUFFER_FISH_STING, 1.0F, 1.0F); + } + +@@ -168,7 +159,7 @@ + ((ServerPlayer) player).connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.PUFFER_FISH_STING, 0.0F)); + } + +- player.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * i, 0), this); ++ entity.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * i, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Rabbit.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Rabbit.java.patch new file mode 100644 index 0000000000..0bdf9432a9 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Rabbit.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/entity/animal/Rabbit.java ++++ b/net/minecraft/world/entity/animal/Rabbit.java +@@ -66,6 +66,9 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.pathfinder.Path; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class Rabbit extends Animal implements VariantHolder { + +@@ -607,12 +579,22 @@ + int i = (Integer) blockstate.getValue(CarrotBlock.AGE); + + if (i == 0) { +- level.setBlock(blockpos, Blocks.AIR.defaultBlockState(), 2); +- level.destroyBlock(blockpos, true, this.rabbit); ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.rabbit, blockposition, Blocks.AIR.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end ++ world.setBlock(blockposition, Blocks.AIR.defaultBlockState(), 2); ++ world.destroyBlock(blockposition, true, this.rabbit); + } else { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(CarrotBlock.AGE, i - 1), 2); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of((Entity) this.rabbit)); +- level.levelEvent(2001, blockpos, Block.getId(blockstate)); ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.rabbit, blockposition, iblockdata.setValue(CarrotBlock.AGE, i - 1))) { ++ return; ++ } ++ // CraftBukkit end ++ world.setBlock(blockposition, (IBlockData) iblockdata.setValue(CarrotBlock.AGE, i - 1), 2); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of((Entity) this.rabbit)); ++ world.levelEvent(2001, blockposition, Block.getId(iblockdata)); + } + + this.rabbit.moreCarrotTicks = 40; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Sheep.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Sheep.java.patch new file mode 100644 index 0000000000..9669ced77d --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Sheep.java.patch @@ -0,0 +1,73 @@ +--- a/net/minecraft/world/entity/animal/Sheep.java ++++ b/net/minecraft/world/entity/animal/Sheep.java +@@ -65,6 +64,13 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.storage.loot.BuiltInLootTables; + import org.joml.Vector3f; ++import net.minecraft.world.item.DyeColor; ++import net.minecraft.world.item.DyeItem; ++import net.minecraft.world.item.Item; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.SheepRegrowWoolEvent; ++import org.bukkit.inventory.InventoryView; ++// CraftBukkit end + + public class Sheep extends Animal implements Shearable { + +@@ -253,6 +252,11 @@ + + if (itemstack.is(Items.SHEARS)) { + if (!this.level().isClientSide && this.readyForShearing()) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) { ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.shear(SoundSource.PLAYERS); + this.gameEvent(GameEvent.SHEAR, player); + itemstack.hurtAndBreak(1, player, (player1) -> { +@@ -275,7 +278,9 @@ + int i = 1 + this.random.nextInt(3); + + for (int j = 0; j < i; ++j) { +- ItemEntity itementity = this.spawnAtLocation((ItemLike) Sheep.ITEM_BY_DYE.get(this.getColor()), 1); ++ this.forceDrops = true; // CraftBukkit ++ ItemEntity entityitem = this.spawnAtLocation((IMaterial) Sheep.ITEM_BY_DYE.get(this.getColor()), 1); ++ this.forceDrops = false; // CraftBukkit + + if (itementity != null) { + itementity.setDeltaMovement(itementity.getDeltaMovement().add((double) ((this.random.nextFloat() - this.random.nextFloat()) * 0.1F), (double) (this.random.nextFloat() * 0.05F), (double) ((this.random.nextFloat() - this.random.nextFloat()) * 0.1F))); +@@ -377,6 +373,12 @@ + @Override + @Override + public void ate() { ++ // CraftBukkit start ++ SheepRegrowWoolEvent event = new SheepRegrowWoolEvent((org.bukkit.entity.Sheep) this.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) return; ++ // CraftBukkit end + super.ate(); + this.setSheared(false); + if (this.isBaby()) { +@@ -422,10 +421,18 @@ + public boolean stillValid(Player player) { + return false; + } ++ ++ // CraftBukkit start ++ @Override ++ public InventoryView getBukkitView() { ++ return null; // TODO: O.O ++ } ++ // CraftBukkit end + }, 2, 1); + +- transientcraftingcontainer.setItem(0, new ItemStack(DyeItem.byColor(dyecolor))); +- transientcraftingcontainer.setItem(1, new ItemStack(DyeItem.byColor(dyecolor1))); ++ transientcraftingcontainer.setItem(0, new ItemStack(DyeItem.byColor(fatherColor))); ++ transientcraftingcontainer.setItem(1, new ItemStack(DyeItem.byColor(motherColor))); ++ transientcraftingcontainer.resultInventory = new ResultContainer(); // CraftBukkit - add result slot for event + return transientcraftingcontainer; + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/SnowGolem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/SnowGolem.java.patch new file mode 100644 index 0000000000..344040376e --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/SnowGolem.java.patch @@ -0,0 +1,60 @@ +--- a/net/minecraft/world/entity/animal/SnowGolem.java ++++ b/net/minecraft/world/entity/animal/SnowGolem.java +@@ -40,6 +40,9 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackMob { + +@@ -103,7 +100,7 @@ + super.aiStep(); + if (!this.level().isClientSide) { + if (this.level().getBiome(this.blockPosition()).is(BiomeTags.SNOW_GOLEM_MELTS)) { +- this.hurt(this.damageSources().onFire(), 1.0F); ++ this.hurt(this.damageSources().melting, 1.0F); // CraftBukkit - DamageSource.BURN -> CraftEventFactory.MELTING + } + + if (!this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +@@ -118,9 +115,13 @@ + int l = Mth.floor(this.getZ() + (double) ((float) (i / 2 % 2 * 2 - 1) * 0.25F)); + BlockPos blockpos = new BlockPos(j, k, l); + +- if (this.level().getBlockState(blockpos).isAir() && blockstate.canSurvive(this.level(), blockpos)) { +- this.level().setBlockAndUpdate(blockpos, blockstate); +- this.level().gameEvent(GameEvent.BLOCK_PLACE, blockpos, GameEvent.Context.of(this, blockstate)); ++ if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handleBlockFormEvent(this.level(), blockposition, iblockdata, this)) { ++ continue; ++ } ++ // CraftBukkit end ++ this.level().gameEvent(GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(this, iblockdata)); + } + } + } +@@ -154,6 +152,11 @@ + ItemStack itemstack = player.getItemInHand(interactionhand); + + if (itemstack.is(Items.SHEARS) && this.readyForShearing()) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) { ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.shear(SoundSource.PLAYERS); + this.gameEvent(GameEvent.SHEAR, player); + if (!this.level().isClientSide) { +@@ -174,7 +176,9 @@ + this.level().playSound((Player) null, (Entity) this, SoundEvents.SNOW_GOLEM_SHEAR, soundsource, 1.0F, 1.0F); + if (!this.level().isClientSide()) { + this.setPumpkin(false); ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation(new ItemStack(Items.CARVED_PUMPKIN), 1.7F); ++ this.forceDrops = false; // CraftBukkit + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Turtle.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Turtle.java.patch new file mode 100644 index 0000000000..2bcafa973e --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Turtle.java.patch @@ -0,0 +1,45 @@ +--- a/net/minecraft/world/entity/animal/Turtle.java ++++ b/net/minecraft/world/entity/animal/Turtle.java +@@ -330,7 +307,9 @@ + protected void ageBoundaryReached() { + super.ageBoundaryReached(); + if (!this.isBaby() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation(Items.SCUTE, 1); ++ this.forceDrops = false; // CraftBukkit + } + + } +@@ -358,9 +335,10 @@ + } + + @Override +- @Override +- public void thunderHit(ServerLevel serverlevel, LightningBolt lightningbolt) { ++ public void thunderHit(ServerLevel level, LightningBolt lightning) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = lightning; // CraftBukkit + this.hurt(this.damageSources().lightningBolt(), Float.MAX_VALUE); ++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = null; // CraftBukkit + } + + @Override +@@ -525,12 +495,14 @@ + } else if (this.turtle.layEggCounter > this.adjustedTickDelay(200)) { + Level level = this.turtle.level(); + +- level.playSound((Player) null, blockpos, SoundEvents.TURTLE_LAY_EGG, SoundSource.BLOCKS, 0.3F, 0.9F + level.random.nextFloat() * 0.2F); +- BlockPos blockpos1 = this.blockPos.above(); +- BlockState blockstate = (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1); ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.turtle, this.blockPos.above(), (IBlockData) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1))) { // CraftBukkit ++ world.playSound((Player) null, blockposition, SoundEvents.TURTLE_LAY_EGG, SoundSource.BLOCKS, 0.3F, 0.9F + world.random.nextFloat() * 0.2F); ++ BlockPos blockposition1 = this.blockPos.above(); ++ IBlockData iblockdata = (IBlockData) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1); + +- level.setBlock(blockpos1, blockstate, 3); +- level.gameEvent(GameEvent.BLOCK_PLACE, blockpos1, GameEvent.Context.of(this.turtle, blockstate)); ++ world.setBlock(blockposition1, iblockdata, 3); ++ world.gameEvent(GameEvent.BLOCK_PLACE, blockposition1, GameEvent.Context.of(this.turtle, iblockdata)); ++ } // CraftBukkit + this.turtle.setHasEgg(false); + this.turtle.setLayingEgg(false); + this.turtle.setInLoveTime(600); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Wolf.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Wolf.java.patch new file mode 100644 index 0000000000..659203726a --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/Wolf.java.patch @@ -0,0 +1,76 @@ +--- a/net/minecraft/world/entity/animal/Wolf.java ++++ b/net/minecraft/world/entity/animal/Wolf.java +@@ -70,6 +70,12 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class Wolf extends TamableAnimal implements NeutralMob { + + private static final EntityDataAccessor DATA_INTERESTED_ID = SynchedEntityData.defineId(Wolf.class, EntityDataSerializers.BOOLEAN); +@@ -313,15 +304,19 @@ + } else { + Entity entity = damagesource.getEntity(); + +- if (!this.level().isClientSide) { +- this.setOrderedToSit(false); +- } ++ // CraftBukkit - move diff down + + if (entity != null && !(entity instanceof Player) && !(entity instanceof AbstractArrow)) { + f = (f + 1.0F) / 2.0F; + } + +- return super.hurt(damagesource, f); ++ // CraftBukkit start ++ boolean result = super.hurt(source, amount); ++ if (!this.level().isClientSide && result) { ++ this.setOrderedToSit(false); ++ } ++ return result; ++ // CraftBukkit end + } + } + +@@ -343,7 +336,7 @@ + super.setTame(flag); + if (flag) { + this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(20.0D); +- this.setHealth(20.0F); ++ this.setHealth(this.getMaxHealth()); // CraftBukkit - 20.0 -> getMaxHealth() + } else { + this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(8.0D); + } +@@ -367,7 +359,7 @@ + itemstack.shrink(1); + } + +- this.heal((float) item.getFoodProperties().getNutrition()); ++ this.heal((float) item.getFoodProperties().getNutrition(), EntityRegainHealthEvent.RegainReason.EATING); // CraftBukkit + return InteractionResult.SUCCESS; + } else { + if (item instanceof DyeItem) { +@@ -395,7 +387,7 @@ + this.setOrderedToSit(!this.isOrderedToSit()); + this.jumping = false; + this.navigation.stop(); +- this.setTarget((LivingEntity) null); ++ this.setTarget((LivingEntity) null, EntityTargetEvent.TargetReason.FORGOT_TARGET, true); // CraftBukkit - reason + return InteractionResult.SUCCESS; + } else { + return interactionresult; +@@ -406,7 +398,8 @@ + itemstack.shrink(1); + } + +- if (this.random.nextInt(3) == 0) { ++ // CraftBukkit - added event call and isCancelled check. ++ if (this.random.nextInt(3) == 0 && !CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { + this.tame(player); + this.navigation.stop(); + this.setTarget((LivingEntity) null); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/allay/Allay.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/allay/Allay.java.patch new file mode 100644 index 0000000000..a7a166d05c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/allay/Allay.java.patch @@ -0,0 +1,75 @@ +--- a/net/minecraft/world/entity/animal/allay/Allay.java ++++ b/net/minecraft/world/entity/animal/allay/Allay.java +@@ -99,6 +99,7 @@ + private float dancingAnimationTicks; + private float spinningAnimationTicks; + private float spinningAnimationTicks0; ++ public boolean forceDancing = false; // CraftBukkit + + public Allay(EntityType entitytype, Level level) { + super(entitytype, level); +@@ -110,6 +111,12 @@ + this.dynamicJukeboxListener = new DynamicGameEventListener<>(new Allay.JukeboxListener(this.vibrationUser.getPositionSource(), GameEvent.JUKEBOX_PLAY.getNotificationRadius())); + } + ++ // CraftBukkit start ++ public void setCanDuplicate(boolean canDuplicate) { ++ this.entityData.set(Allay.DATA_CAN_DUPLICATE, canDuplicate); ++ } ++ // CraftBukkit end ++ + @Override + @Override + protected Brain.Provider brainProvider() { +@@ -245,7 +236,7 @@ + public void aiStep() { + super.aiStep(); + if (!this.level().isClientSide && this.isAlive() && this.tickCount % 10 == 0) { +- this.heal(1.0F); ++ this.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit + } + + if (this.isDancing() && this.shouldStopDancing() && this.tickCount % 20 == 0) { +@@ -319,7 +306,12 @@ + ItemStack itemstack1 = this.getItemInHand(InteractionHand.MAIN_HAND); + + if (this.isDancing() && this.isDuplicationItem(itemstack) && this.canDuplicate()) { +- this.duplicateAllay(); ++ // CraftBukkit start - handle cancel duplication ++ Allay allay = this.duplicateAllay(); ++ if (allay == null) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + this.level().broadcastEntityEvent(this, (byte) 18); + this.level().playSound(player, (Entity) this, SoundEvents.AMETHYST_BLOCK_CHIME, SoundSource.NEUTRAL, 2.0F, 1.0F); + this.removeInteractionItem(player, itemstack); +@@ -454,6 +439,7 @@ + } + + private boolean shouldStopDancing() { ++ if (this.forceDancing) {return false;} // CraftBukkit + return this.jukeboxPos == null || !this.jukeboxPos.closerToCenterThan(this.position(), (double) GameEvent.JUKEBOX_PLAY.getNotificationRadius()) || !this.level().getBlockState(this.jukeboxPos).is(Blocks.JUKEBOX); + } + +@@ -553,7 +533,7 @@ + return Allay.DUPLICATION_ITEM.test(itemstack); + } + +- private void duplicateAllay() { ++ public Allay duplicateAllay() { // CraftBukkit - return allay + Allay allay = (Allay) EntityType.ALLAY.create(this.level()); + + if (allay != null) { +@@ -561,9 +541,9 @@ + allay.setPersistenceRequired(); + allay.resetDuplicationCooldown(); + this.resetDuplicationCooldown(); +- this.level().addFreshEntity(allay); ++ this.level().addFreshEntity(allay, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DUPLICATION); // CraftBukkit - reason for duplicated allay + } +- ++ return allay; // CraftBukkit + } + + private void resetDuplicationCooldown() { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/axolotl/Axolotl.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/axolotl/Axolotl.java.patch new file mode 100644 index 0000000000..3621a730df --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/axolotl/Axolotl.java.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/world/entity/animal/axolotl/Axolotl.java ++++ b/net/minecraft/world/entity/animal/axolotl/Axolotl.java +@@ -68,6 +68,12 @@ + + public class Axolotl extends Animal implements LerpingModel, VariantHolder, Bucketable { + ++ // CraftBukkit start - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ @Override ++ public int getDefaultMaxAirSupply() { ++ return AXOLOTL_TOTAL_AIR_SUPPLY; ++ } ++ // CraftBukkit end + public static final int TOTAL_PLAYDEAD_TIME = 200; + protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_ADULT, SensorType.HURT_BY, SensorType.AXOLOTL_ATTACKABLES, SensorType.AXOLOTL_TEMPTATIONS); + protected static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.BREED_TARGET, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.LOOK_TARGET, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.PATH, MemoryModuleType.ATTACK_TARGET, MemoryModuleType.ATTACK_COOLING_DOWN, MemoryModuleType.NEAREST_VISIBLE_ADULT, new MemoryModuleType[]{MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.PLAY_DEAD_TICKS, MemoryModuleType.NEAREST_ATTACKABLE, MemoryModuleType.TEMPTING_PLAYER, MemoryModuleType.TEMPTATION_COOLDOWN_TICKS, MemoryModuleType.IS_TEMPTED, MemoryModuleType.HAS_HUNTING_COOLDOWN, MemoryModuleType.IS_PANICKING}); +@@ -197,7 +195,7 @@ + @Override + @Override + public int getMaxAirSupply() { +- return 6000; ++ return maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() + } + + @Override +@@ -441,7 +416,7 @@ + int i = mobeffectinstance != null ? mobeffectinstance.getDuration() : 0; + int j = Math.min(2400, 100 + i); + +- player.addEffect(new MobEffectInstance(MobEffects.REGENERATION, j, 0), this); ++ player.addEffect(new MobEffectInstance(MobEffects.REGENERATION, j, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AXOLOTL); // CraftBukkit + } + + player.removeEffect(MobEffects.DIG_SLOWDOWN); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/frog/Tadpole.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/frog/Tadpole.java.patch new file mode 100644 index 0000000000..68454adde5 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/frog/Tadpole.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/entity/animal/frog/Tadpole.java ++++ b/net/minecraft/world/entity/animal/frog/Tadpole.java +@@ -253,8 +233,14 @@ + } + + frog.setPersistenceRequired(); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTransformEvent(this, frog, org.bukkit.event.entity.EntityTransformEvent.TransformReason.METAMORPHOSIS).isCancelled()) { ++ this.setAge(0); // Sets the age to 0 for avoid a loop if the event is canceled ++ return; ++ } ++ // CraftBukkit end + this.playSound(SoundEvents.TADPOLE_GROW_UP, 0.15F, 1.0F); +- serverlevel.addFreshEntityWithPassengers(frog); ++ worldserver.addFreshEntityWithPassengers(frog, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.METAMORPHOSIS); // CraftBukkit - add SpawnReason + this.discard(); + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/goat/Goat.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/goat/Goat.java.patch new file mode 100644 index 0000000000..d3e0177a47 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/goat/Goat.java.patch @@ -0,0 +1,32 @@ +--- a/net/minecraft/world/entity/animal/goat/Goat.java ++++ b/net/minecraft/world/entity/animal/goat/Goat.java +@@ -55,6 +55,12 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerBucketFillEvent; ++// CraftBukkit end ++ + public class Goat extends Animal { + + public static final EntityDimensions LONG_JUMPING_DIMENSIONS = EntityDimensions.scalable(0.9F, 1.3F).scale(0.7F); +@@ -235,8 +226,15 @@ + ItemStack itemstack = player.getItemInHand(interactionhand); + + if (itemstack.is(Items.BUCKET) && !this.isBaby()) { ++ // CraftBukkit start - Got milk? ++ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level(), player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand); ++ ++ if (event.isCancelled()) { ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + player.playSound(this.getMilkingSound(), 1.0F, 1.0F); +- ItemStack itemstack1 = ItemUtils.createFilledResult(itemstack, player, Items.MILK_BUCKET.getDefaultInstance()); ++ ItemStack itemstack1 = ItemUtils.createFilledResult(itemstack, player, CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit + + player.setItemInHand(interactionhand, itemstack1); + return InteractionResult.sidedSuccess(this.level().isClientSide); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/horse/AbstractHorse.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/horse/AbstractHorse.java.patch new file mode 100644 index 0000000000..18aa0c920f --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/horse/AbstractHorse.java.patch @@ -0,0 +1,105 @@ +--- a/net/minecraft/world/entity/animal/horse/AbstractHorse.java ++++ b/net/minecraft/world/entity/animal/horse/AbstractHorse.java +@@ -79,6 +79,11 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++// CraftBukkit end ++ + public abstract class AbstractHorse extends Animal implements ContainerListener, HasCustomInventoryScreen, OwnableEntity, PlayerRideableJumping, Saddleable { + + public static final int EQUIPMENT_SLOT_OFFSET = 400; +@@ -140,6 +145,7 @@ + protected int gallopSoundCounter; + @Nullable + private UUID owner; ++ public int maxDomestication = 100; // CraftBukkit - store max domestication value + + protected AbstractHorse(EntityType entitytype, Level level) { + super(entitytype, level); +@@ -345,10 +341,10 @@ + protected void createInventory() { + SimpleContainer simplecontainer = this.inventory; + +- this.inventory = new SimpleContainer(this.getInventorySize()); +- if (simplecontainer != null) { +- simplecontainer.removeListener(this); +- int i = Math.min(simplecontainer.getContainerSize(), this.inventory.getContainerSize()); ++ this.inventory = new SimpleContainer(this.getInventorySize(), (org.bukkit.entity.AbstractHorse) this.getBukkitEntity()); // CraftBukkit ++ if (inventorysubcontainer != null) { ++ inventorysubcontainer.removeListener(this); ++ int i = Math.min(inventorysubcontainer.getContainerSize(), this.inventory.getContainerSize()); + + for (int j = 0; j < i; ++j) { + ItemStack itemstack = simplecontainer.getItem(j); +@@ -457,7 +449,7 @@ + } + + public int getMaxTemper() { +- return 100; ++ return this.maxDomestication; // CraftBukkit - return stored max domestication instead of 100 + } + + @Override +@@ -531,7 +520,7 @@ + } + + if (this.getHealth() < this.getMaxHealth() && f > 0.0F) { +- this.heal(f); ++ this.heal(f, EntityRegainHealthEvent.RegainReason.EATING); // CraftBukkit + flag = true; + } + +@@ -609,7 +594,7 @@ + super.aiStep(); + if (!this.level().isClientSide && this.isAlive()) { + if (this.random.nextInt(900) == 0 && this.deathTime == 0) { +- this.heal(1.0F); ++ this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit + } + + if (this.canEatGrass()) { +@@ -882,6 +861,7 @@ + if (this.getOwnerUUID() != null) { + compoundtag.putUUID("Owner", this.getOwnerUUID()); + } ++ compound.putInt("Bukkit.MaxDomestication", this.maxDomestication); // CraftBukkit + + if (!this.inventory.getItem(0).isEmpty()) { + compoundtag.put("SaddleItem", this.inventory.getItem(0).save(new CompoundTag())); +@@ -910,6 +889,11 @@ + if (uuid != null) { + this.setOwnerUUID(uuid); + } ++ // CraftBukkit start ++ if (compound.contains("Bukkit.MaxDomestication")) { ++ this.maxDomestication = compound.getInt("Bukkit.MaxDomestication"); ++ } ++ // CraftBukkit end + + if (compoundtag.contains("SaddleItem", 10)) { + ItemStack itemstack = ItemStack.of(compoundtag.getCompound("SaddleItem")); +@@ -1015,8 +995,18 @@ + } + + @Override +- @Override +- public void handleStartJump(int i) { ++ public void handleStartJump(int jumpPower) { ++ // CraftBukkit start ++ float power; ++ if (jumpPower >= 90) { ++ power = 1.0F; ++ } else { ++ power = 0.4F + 0.4F * (float) jumpPower / 90.0F; ++ } ++ if (!CraftEventFactory.callHorseJumpEvent(this, power)) { ++ return; ++ } ++ // CraftBukkit end + this.allowStandSliding = true; + this.standIfPossible(); + this.playJumpSound(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/horse/Llama.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/horse/Llama.java.patch new file mode 100644 index 0000000000..14597356bb --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/horse/Llama.java.patch @@ -0,0 +1,19 @@ +--- a/net/minecraft/world/entity/animal/horse/Llama.java ++++ b/net/minecraft/world/entity/animal/horse/Llama.java +@@ -84,9 +84,14 @@ + return false; + } + +- private void setStrength(int i) { +- this.entityData.set(Llama.DATA_STRENGTH_ID, Math.max(1, Math.min(5, i))); ++ // CraftBukkit start ++ public void setStrengthPublic(int i) { ++ this.setStrength(i); + } ++ // CraftBukkit end ++ private void setStrength(int strength) { ++ this.entityData.set(Llama.DATA_STRENGTH_ID, Math.max(1, Math.min(5, strength))); ++ } + + private void setRandomStrength(RandomSource randomsource) { + int i = randomsource.nextFloat() < 0.04F ? 5 : 3; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java.patch new file mode 100644 index 0000000000..fd45a9e6d2 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java.patch @@ -0,0 +1,41 @@ +--- a/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java ++++ b/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java +@@ -40,15 +38,15 @@ + this.horse.setAge(0); + LightningBolt lightningbolt = (LightningBolt) EntityType.LIGHTNING_BOLT.create(serverlevel); + +- if (lightningbolt != null) { +- lightningbolt.moveTo(this.horse.getX(), this.horse.getY(), this.horse.getZ()); +- lightningbolt.setVisualOnly(true); +- serverlevel.addFreshEntity(lightningbolt); +- Skeleton skeleton = this.createSkeleton(difficultyinstance, this.horse); ++ if (entitylightning != null) { ++ entitylightning.moveTo(this.horse.getX(), this.horse.getY(), this.horse.getZ()); ++ entitylightning.setVisualOnly(true); ++ worldserver.strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.TRAP); // CraftBukkit ++ Skeleton entityskeleton = this.createSkeleton(difficultydamagescaler, this.horse); + +- if (skeleton != null) { +- skeleton.startRiding(this.horse); +- serverlevel.addFreshEntityWithPassengers(skeleton); ++ if (entityskeleton != null) { ++ entityskeleton.startRiding(this.horse); ++ worldserver.addFreshEntityWithPassengers(entityskeleton, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.TRAP); // CraftBukkit + + for (int i = 0; i < 3; ++i) { + AbstractHorse abstracthorse = this.createHorse(difficultyinstance); +@@ -56,10 +54,10 @@ + if (abstracthorse != null) { + Skeleton skeleton1 = this.createSkeleton(difficultyinstance, abstracthorse); + +- if (skeleton1 != null) { +- skeleton1.startRiding(abstracthorse); +- abstracthorse.push(this.horse.getRandom().triangle(0.0D, 1.1485D), 0.0D, this.horse.getRandom().triangle(0.0D, 1.1485D)); +- serverlevel.addFreshEntityWithPassengers(abstracthorse); ++ if (entityskeleton1 != null) { ++ entityskeleton1.startRiding(entityhorseabstract); ++ entityhorseabstract.push(this.horse.getRandom().triangle(0.0D, 1.1485D), 0.0D, this.horse.getRandom().triangle(0.0D, 1.1485D)); ++ worldserver.addFreshEntityWithPassengers(entityhorseabstract, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.JOCKEY); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/horse/TraderLlama.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/horse/TraderLlama.java.patch new file mode 100644 index 0000000000..45a098f4b5 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/horse/TraderLlama.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/animal/horse/TraderLlama.java ++++ b/net/minecraft/world/entity/animal/horse/TraderLlama.java +@@ -163,7 +153,7 @@ + @Override + @Override + public void start() { +- this.mob.setTarget(this.ownerLastHurtBy); ++ this.mob.setTarget(this.ownerLastHurtBy, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_OWNER, true); // CraftBukkit + Entity entity = this.llama.getLeashHolder(); + + if (entity instanceof WanderingTrader) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/sniffer/Sniffer.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/sniffer/Sniffer.java.patch new file mode 100644 index 0000000000..3d68a6c97f --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/animal/sniffer/Sniffer.java.patch @@ -0,0 +1,50 @@ +--- a/net/minecraft/world/entity/animal/sniffer/Sniffer.java ++++ b/net/minecraft/world/entity/animal/sniffer/Sniffer.java +@@ -81,17 +81,25 @@ + return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.10000000149011612D).add(Attributes.MAX_HEALTH, 14.0D); + } + +- public Sniffer(EntityType entitytype, Level level) { +- super(entitytype, level); +- this.entityData.define(Sniffer.DATA_STATE, Sniffer.State.IDLING); +- this.entityData.define(Sniffer.DATA_DROP_SEED_AT_TICK, 0); ++ public Sniffer(EntityType entityType, Level level) { ++ super(entityType, level); ++ // this.entityData.define(Sniffer.DATA_STATE, Sniffer.State.IDLING); // CraftBukkit - moved down to appropriate location ++ // this.entityData.define(Sniffer.DATA_DROP_SEED_AT_TICK, 0); // CraftBukkit - moved down to appropriate location + this.getNavigation().setCanFloat(true); + this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); + this.setPathfindingMalus(BlockPathTypes.DANGER_POWDER_SNOW, -1.0F); + this.setPathfindingMalus(BlockPathTypes.DAMAGE_CAUTIOUS, -1.0F); + } + ++ // CraftBukkit start - SPIGOT-7295: moved from constructor to appropriate location + @Override ++ protected void defineSynchedData() { ++ super.defineSynchedData(); ++ this.entityData.define(Sniffer.DATA_STATE, Sniffer.State.IDLING); ++ this.entityData.define(Sniffer.DATA_DROP_SEED_AT_TICK, 0); ++ } ++ // CraftBukkit end ++ + @Override + protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { + return this.getDimensions(pose).height * 0.6F; +@@ -272,8 +276,15 @@ + ItemStack itemstack = (ItemStack) iterator.next(); + ItemEntity itementity = new ItemEntity(serverlevel, (double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), itemstack); + +- itementity.setDefaultPickUpDelay(); +- serverlevel.addFreshEntity(itementity); ++ // CraftBukkit start - handle EntityDropItemEvent ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end ++ entityitem.setDefaultPickUpDelay(); ++ worldserver.addFreshEntity(entityitem); + } + + this.playSound(SoundEvents.SNIFFER_DROP_SEED, 1.0F, 1.0F); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java.patch new file mode 100644 index 0000000000..45151e7e26 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java.patch @@ -0,0 +1,53 @@ +--- a/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java ++++ b/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java +@@ -19,6 +19,10 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.BaseFireBlock; + import net.minecraft.world.level.dimension.end.EndDragonFight; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end + + public class EndCrystal extends Entity { + +@@ -57,8 +58,12 @@ + if (this.level() instanceof ServerLevel) { + BlockPos blockpos = this.blockPosition(); + +- if (((ServerLevel) this.level()).getDragonFight() != null && this.level().getBlockState(blockpos).isAir()) { +- this.level().setBlockAndUpdate(blockpos, BaseFireBlock.getState(this.level(), blockpos)); ++ if (((ServerLevel) this.level()).getDragonFight() != null && this.level().getBlockState(blockposition).isAir()) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition, this).isCancelled()) { ++ this.level().setBlockAndUpdate(blockposition, BaseFireBlock.getState(this.level(), blockposition)); ++ } ++ // CraftBukkit end + } + } + +@@ -102,11 +103,23 @@ + return false; + } else { + if (!this.isRemoved() && !this.level().isClientSide) { ++ // CraftBukkit start - All non-living entities need this ++ if (CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, false)) { ++ return false; ++ } ++ // CraftBukkit end + this.remove(Entity.RemovalReason.KILLED); + if (!damagesource.is(DamageTypeTags.IS_EXPLOSION)) { + DamageSource damagesource1 = damagesource.getEntity() != null ? this.damageSources().explosion(this, damagesource.getEntity()) : null; + +- this.level().explode(this, damagesource1, (ExplosionDamageCalculator) null, this.getX(), this.getY(), this.getZ(), 6.0F, false, Level.ExplosionInteraction.BLOCK); ++ // CraftBukkit start ++ ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent(this, 6.0F, false); ++ if (event.isCancelled()) { ++ this.unsetRemoved(); ++ return false; ++ } ++ this.level().explode(this, damagesource1, (ExplosionDamageCalculator) null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.BLOCK); ++ // CraftBukkit end + } + + this.onDestroyedBy(damagesource); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java.patch new file mode 100644 index 0000000000..9c402d8c12 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java.patch @@ -0,0 +1,231 @@ +--- a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java ++++ b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +@@ -53,7 +51,19 @@ + import org.joml.Vector3f; + import org.slf4j.Logger; + +-public class EnderDragon extends Mob implements Enemy { ++// CraftBukkit start ++import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.level.Explosion; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.entity.BlockEntity; ++import net.minecraft.world.level.storage.loot.LootParams; ++import net.minecraft.world.level.storage.loot.parameters.LootContextParams; ++import net.minecraft.world.phys.AABB; ++import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.entity.EntityExplodeEvent; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++// CraftBukkit end + + private static final Logger LOGGER = LogUtils.getLogger(); + public static final EntityDataAccessor DATA_PHASE = SynchedEntityData.defineId(EnderDragon.class, EntityDataSerializers.INT); +@@ -90,6 +102,7 @@ + private final Node[] nodes; + private final int[] nodeAdjacency; + private final BinaryHeap openSet; ++ private final Explosion explosionSource; // CraftBukkit - reusable source for CraftTNTPrimed.getSource() + + public EnderDragon(EntityType entitytype, Level level) { + super(EntityType.ENDER_DRAGON, level); +@@ -111,6 +124,7 @@ + this.noPhysics = true; + this.noCulling = true; + this.phaseManager = new EnderDragonPhaseManager(this); ++ this.explosionSource = new Explosion(level, this, null, null, Double.NaN, Double.NaN, Double.NaN, Float.NaN, true, Explosion.Effect.DESTROY, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); // CraftBukkit + } + + public void setDragonFight(EndDragonFight enddragonfight) { +@@ -262,10 +272,10 @@ + + Vec3 vec31 = dragonphaseinstance.getFlyTargetLocation(); + +- if (vec31 != null) { +- double d0 = vec31.x - this.getX(); +- double d1 = vec31.y - this.getY(); +- double d2 = vec31.z - this.getZ(); ++ if (vec3d1 != null && idragoncontroller.getPhase() != EnderDragonPhase.HOVERING) { // CraftBukkit - Don't move when hovering ++ double d0 = vec3d1.x - this.getX(); ++ double d1 = vec3d1.y - this.getY(); ++ double d2 = vec3d1.z - this.getZ(); + double d3 = d0 * d0 + d1 * d1 + d2 * d2; + float f6 = dragonphaseinstance.getFlySpeed(); + double d4 = Math.sqrt(d0 * d0 + d2 * d2); +@@ -403,7 +413,14 @@ + if (this.nearestCrystal.isRemoved()) { + this.nearestCrystal = null; + } else if (this.tickCount % 10 == 0 && this.getHealth() < this.getMaxHealth()) { +- this.setHealth(this.getHealth() + 1.0F); ++ // CraftBukkit start ++ EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), 1.0F, EntityRegainHealthEvent.RegainReason.ENDER_CRYSTAL); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ this.setHealth((float) (this.getHealth() + event.getAmount())); ++ } ++ // CraftBukkit end + } + } + +@@ -478,6 +495,9 @@ + int j1 = Mth.floor(aabb.maxZ); + boolean flag = false; + boolean flag1 = false; ++ // CraftBukkit start - Create a list to hold all the destroyed blocks ++ List destroyedBlocks = new java.util.ArrayList(); ++ // CraftBukkit end + + for (int k1 = i; k1 <= l; ++k1) { + for (int l1 = j; l1 <= i1; ++l1) { +@@ -485,9 +505,13 @@ + BlockPos blockpos = new BlockPos(k1, l1, i2); + BlockState blockstate = this.level().getBlockState(blockpos); + +- if (!blockstate.isAir() && !blockstate.is(BlockTags.DRAGON_TRANSPARENT)) { +- if (this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && !blockstate.is(BlockTags.DRAGON_IMMUNE)) { +- flag1 = this.level().removeBlock(blockpos, false) || flag1; ++ if (!iblockdata.isAir() && !iblockdata.is(BlockTags.DRAGON_TRANSPARENT)) { ++ if (this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && !iblockdata.is(BlockTags.DRAGON_IMMUNE)) { ++ // CraftBukkit start - Add blocks to list rather than destroying them ++ // flag1 = this.level().removeBlock(blockposition, false) || flag1; ++ flag1 = true; ++ destroyedBlocks.add(CraftBlock.at(this.level(), blockposition)); ++ // CraftBukkit end + } else { + flag = true; + } +@@ -496,6 +520,51 @@ + } + } + ++ // CraftBukkit start - Set off an EntityExplodeEvent for the dragon exploding all these blocks ++ // SPIGOT-4882: don't fire event if nothing hit ++ if (!flag1) { ++ return flag; ++ } ++ ++ org.bukkit.entity.Entity bukkitEntity = this.getBukkitEntity(); ++ EntityExplodeEvent event = new EntityExplodeEvent(bukkitEntity, bukkitEntity.getLocation(), destroyedBlocks, 0F); ++ bukkitEntity.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ // This flag literally means 'Dragon hit something hard' (Obsidian, White Stone or Bedrock) and will cause the dragon to slow down. ++ // We should consider adding an event extension for it, or perhaps returning true if the event is cancelled. ++ return flag; ++ } else if (event.getYield() == 0F) { ++ // Yield zero ==> no drops ++ for (org.bukkit.block.Block block : event.blockList()) { ++ this.level().removeBlock(new BlockPos(block.getX(), block.getY(), block.getZ()), false); ++ } ++ } else { ++ for (org.bukkit.block.Block block : event.blockList()) { ++ org.bukkit.Material blockId = block.getType(); ++ if (blockId.isAir()) { ++ continue; ++ } ++ ++ CraftBlock craftBlock = ((CraftBlock) block); ++ BlockPos blockposition = craftBlock.getPosition(); ++ ++ Block nmsBlock = craftBlock.getNMS().getBlock(); ++ if (nmsBlock.dropFromExplosion(explosionSource)) { ++ BlockEntity tileentity = craftBlock.getNMS().hasBlockEntity() ? this.level().getBlockEntity(blockposition) : null; ++ LootParams.Builder loottableinfo_builder = (new LootParams.Builder((ServerLevel) this.level())).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockposition)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withParameter(LootContextParams.EXPLOSION_RADIUS, 1.0F / event.getYield()).withOptionalParameter(LootContextParams.BLOCK_ENTITY, tileentity); ++ ++ craftBlock.getNMS().getDrops(loottableinfo_builder).forEach((itemstack) -> { ++ Block.popResource(this.level(), blockposition, itemstack); ++ }); ++ craftBlock.getNMS().spawnAfterBreak((ServerLevel) this.level(), blockposition, ItemStack.EMPTY, false); ++ } ++ nmsBlock.wasExploded(this.level(), blockposition, explosionSource); ++ ++ this.level().removeBlock(blockposition, false); ++ } ++ } ++ // CraftBukkit end ++ + if (flag1) { + BlockPos blockpos1 = new BlockPos(i + this.random.nextInt(l - i + 1), j + this.random.nextInt(i1 - j + 1), k + this.random.nextInt(j1 - k + 1)); + +@@ -562,7 +629,21 @@ + + } + ++ // CraftBukkit start - SPIGOT-2420: Special case, the ender dragon drops 12000 xp for the first kill and 500 xp for every other kill and this over time. + @Override ++ public int getExpReward() { ++ // CraftBukkit - Moved from #tickDeath method ++ boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT); ++ short short0 = 500; ++ ++ if (this.dragonFight != null && !this.dragonFight.hasPreviouslyKilledDragon()) { ++ short0 = 12000; ++ } ++ ++ return flag ? short0 : 0; ++ } ++ // CraftBukkit end ++ + @Override + protected void tickDeath() { + if (this.dragonFight != null) { +@@ -578,15 +659,20 @@ + this.level().addParticle(ParticleTypes.EXPLOSION_EMITTER, this.getX() + (double) f, this.getY() + 2.0D + (double) f1, this.getZ() + (double) f2, 0.0D, 0.0D, 0.0D); + } + ++ // CraftBukkit start - SPIGOT-2420: Moved up to #getExpReward method ++ /* + boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT); + short short0 = 500; + + if (this.dragonFight != null && !this.dragonFight.hasPreviouslyKilledDragon()) { + short0 = 12000; + } ++ */ ++ int short0 = expToDrop; ++ // CraftBukkit end + + if (this.level() instanceof ServerLevel) { +- if (this.dragonDeathTime > 150 && this.dragonDeathTime % 5 == 0 && flag) { ++ if (this.dragonDeathTime > 150 && this.dragonDeathTime % 5 == 0 && true) { // CraftBukkit - SPIGOT-2420: Already checked for the game rule when calculating the xp + ExperienceOrb.award((ServerLevel) this.level(), this.position(), Mth.floor((float) short0 * 0.08F)); + } + +@@ -597,7 +683,7 @@ + + this.move(MoverType.SELF, new Vec3(0.0D, 0.10000000149011612D, 0.0D)); + if (this.dragonDeathTime == 200 && this.level() instanceof ServerLevel) { +- if (flag) { ++ if (true) { // CraftBukkit - SPIGOT-2420: Already checked for the game rule when calculating the xp + ExperienceOrb.award((ServerLevel) this.level(), this.position(), Mth.floor((float) short0 * 0.2F)); + } + +@@ -814,11 +900,11 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("DragonPhase", this.phaseManager.getCurrentPhase().getPhase().getId()); +- compoundtag.putInt("DragonDeathTime", this.dragonDeathTime); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("DragonPhase", this.phaseManager.getCurrentPhase().getPhase().getId()); ++ compound.putInt("DragonDeathTime", this.dragonDeathTime); ++ compound.putInt("Bukkit.expToDrop", expToDrop); // CraftBukkit - SPIGOT-2420: The ender dragon drops xp over time which can also happen between server starts + } + + @Override +@@ -833,6 +918,11 @@ + this.dragonDeathTime = compoundtag.getInt("DragonDeathTime"); + } + ++ // CraftBukkit start - SPIGOT-2420: The ender dragon drops xp over time which can also happen between server starts ++ if (compound.contains("Bukkit.expToDrop")) { ++ this.expToDrop = compound.getInt("Bukkit.expToDrop"); ++ } ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhaseManager.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhaseManager.java.patch new file mode 100644 index 0000000000..ec9afdecce --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhaseManager.java.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhaseManager.java ++++ b/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhaseManager.java +@@ -5,6 +5,11 @@ + import net.minecraft.world.entity.boss.enderdragon.EnderDragon; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftEnderDragon; ++import org.bukkit.event.entity.EnderDragonChangePhaseEvent; ++// CraftBukkit end ++ + public class EnderDragonPhaseManager { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -24,7 +29,20 @@ + this.currentPhase.end(); + } + +- this.currentPhase = this.getPhase(enderdragonphase); ++ // CraftBukkit start - Call EnderDragonChangePhaseEvent ++ EnderDragonChangePhaseEvent event = new EnderDragonChangePhaseEvent( ++ (CraftEnderDragon) this.dragon.getBukkitEntity(), ++ (this.currentPhase == null) ? null : CraftEnderDragon.getBukkitPhase(this.currentPhase.getPhase()), ++ CraftEnderDragon.getBukkitPhase(phase) ++ ); ++ this.dragon.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ phase = CraftEnderDragon.getMinecraftPhase(event.getNewPhase()); ++ // CraftBukkit end ++ ++ this.currentPhase = this.getPhase(phase); + if (!this.dragon.level().isClientSide) { + this.dragon.getEntityData().set(EnderDragon.DATA_PHASE, enderdragonphase.getId()); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/boss/wither/WitherBoss.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/boss/wither/WitherBoss.java.patch new file mode 100644 index 0000000000..ed242f6462 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/boss/wither/WitherBoss.java.patch @@ -0,0 +1,108 @@ +--- a/net/minecraft/world/entity/boss/wither/WitherBoss.java ++++ b/net/minecraft/world/entity/boss/wither/WitherBoss.java +@@ -54,6 +43,26 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.Vec3; ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.particles.ParticleTypes; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.network.chat.Component; ++import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; ++import net.minecraft.network.syncher.EntityDataAccessor; ++import net.minecraft.network.syncher.EntityDataSerializers; ++import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerBossEvent; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundEvents; ++import net.minecraft.world.level.block.Blocks; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end + + public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob { + +@@ -259,15 +257,40 @@ + i = this.getInvulnerableTicks() - 1; + this.bossEvent.setProgress(1.0F - (float) i / 220.0F); + if (i <= 0) { +- this.level().explode(this, this.getX(), this.getEyeY(), this.getZ(), 7.0F, false, Level.ExplosionInteraction.MOB); ++ // CraftBukkit start ++ // this.level().explode(this, this.getX(), this.getEyeY(), this.getZ(), 7.0F, false, World.a.MOB); ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), 7.0F, false); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ this.level().explode(this, this.getX(), this.getEyeY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.MOB); ++ } ++ // CraftBukkit end ++ + if (!this.isSilent()) { +- this.level().globalLevelEvent(1023, this.blockPosition(), 0); ++ // CraftBukkit start - Use relative location for far away sounds ++ // this.level().globalLevelEvent(1023, new BlockPosition(this), 0); ++ int viewDistance = ((ServerLevel) this.level()).getCraftServer().getViewDistance() * 16; ++ for (ServerPlayer player : (List) MinecraftServer.getServer().getPlayerList().players) { ++ double deltaX = this.getX() - player.getX(); ++ double deltaZ = this.getZ() - player.getZ(); ++ double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; ++ if (distanceSquared > viewDistance * viewDistance) { ++ double deltaLength = Math.sqrt(distanceSquared); ++ double relativeX = player.getX() + (deltaX / deltaLength) * viewDistance; ++ double relativeZ = player.getZ() + (deltaZ / deltaLength) * viewDistance; ++ player.connection.send(new ClientboundLevelEventPacket(1023, new BlockPos((int) relativeX, (int) this.getY(), (int) relativeZ), 0, true)); ++ } else { ++ player.connection.send(new ClientboundLevelEventPacket(1023, this.blockPosition(), 0, true)); ++ } ++ } ++ // CraftBukkit end + } + } + + this.setInvulnerableTicks(i); + if (this.tickCount % 10 == 0) { +- this.heal(10.0F); ++ this.heal(10.0F, EntityRegainHealthEvent.RegainReason.WITHER_SPAWN); // CraftBukkit + } + + } else { +@@ -312,7 +335,8 @@ + if (!list.isEmpty()) { + LivingEntity livingentity1 = (LivingEntity) list.get(this.random.nextInt(list.size())); + +- this.setAlternativeTarget(i, livingentity1.getId()); ++ if (CraftEventFactory.callEntityTargetLivingEvent(this, entityliving1, EntityTargetEvent.TargetReason.CLOSEST_ENTITY).isCancelled()) continue; // CraftBukkit ++ this.setAlternativeTarget(i, entityliving1.getId()); + } + } + } +@@ -341,8 +365,13 @@ + BlockPos blockpos = new BlockPos(i2, j2, k2); + BlockState blockstate = this.level().getBlockState(blockpos); + +- if (canDestroy(blockstate)) { +- flag = this.level().destroyBlock(blockpos, true, this) || flag; ++ if (canDestroy(iblockdata)) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState())) { ++ continue; ++ } ++ // CraftBukkit end ++ flag = this.level().destroyBlock(blockposition, true, this) || flag; + } + } + } +@@ -355,7 +384,7 @@ + } + + if (this.tickCount % 20 == 0) { +- this.heal(1.0F); ++ this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit + } + + this.bossEvent.setProgress(this.getHealth() / this.getMaxHealth()); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/decoration/ArmorStand.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/decoration/ArmorStand.java.patch new file mode 100644 index 0000000000..8cb4d0c164 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/decoration/ArmorStand.java.patch @@ -0,0 +1,183 @@ +--- a/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -43,6 +41,13 @@ + import net.minecraft.world.level.material.PushReaction; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.inventory.EquipmentSlot; ++import org.bukkit.craftbukkit.CraftEquipmentSlot; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerArmorStandManipulateEvent; ++// CraftBukkit end + + public class ArmorStand extends LivingEntity { + +@@ -106,7 +111,13 @@ + this.setPos(d0, d1, d2); + } + ++ // CraftBukkit start - SPIGOT-3607, SPIGOT-3637 + @Override ++ public float getBukkitYaw() { ++ return this.getYRot(); ++ } ++ // CraftBukkit end ++ + @Override + public void refreshDimensions() { + double d0 = this.getX(); +@@ -166,15 +172,21 @@ + } + + @Override ++ public void setItemSlot(net.minecraft.world.entity.EquipmentSlot slot, ItemStack stack) { ++ // CraftBukkit start ++ this.setItemSlot(slot, stack, false); ++ } ++ + @Override +- public void setItemSlot(EquipmentSlot equipmentslot, ItemStack itemstack) { ++ public void setItemSlot(net.minecraft.world.entity.EquipmentSlot enumitemslot, ItemStack itemstack, boolean silent) { ++ // CraftBukkit end + this.verifyEquippedItem(itemstack); + switch (equipmentslot.getType()) { + case HAND: +- this.onEquipItem(equipmentslot, (ItemStack) this.handItems.set(equipmentslot.getIndex(), itemstack), itemstack); ++ this.onEquipItem(enumitemslot, (ItemStack) this.handItems.set(enumitemslot.getIndex(), itemstack), itemstack, silent); // CraftBukkit + break; + case ARMOR: +- this.onEquipItem(equipmentslot, (ItemStack) this.armorItems.set(equipmentslot.getIndex(), itemstack), itemstack); ++ this.onEquipItem(enumitemslot, (ItemStack) this.armorItems.set(enumitemslot.getIndex(), itemstack), itemstack, silent); // CraftBukkit + } + + } +@@ -416,8 +421,26 @@ + return false; + } else if (itemstack1.isEmpty() && (this.disabledSlots & 1 << equipmentslot.getFilterFlag() + 16) != 0) { + return false; +- } else if (player.getAbilities().instabuild && itemstack1.isEmpty() && !itemstack.isEmpty()) { +- this.setItemSlot(equipmentslot, itemstack.copyWithCount(1)); ++ // CraftBukkit start ++ } else { ++ org.bukkit.inventory.ItemStack armorStandItem = CraftItemStack.asCraftMirror(itemstack1); ++ org.bukkit.inventory.ItemStack playerHeldItem = CraftItemStack.asCraftMirror(stack); ++ ++ Player player1 = (Player) player.getBukkitEntity(); ++ org.bukkit.entity.ArmorStand self = (org.bukkit.entity.ArmorStand) this.getBukkitEntity(); ++ ++ EquipmentSlot slot1 = CraftEquipmentSlot.getSlot(slot); ++ EquipmentSlot hand = CraftEquipmentSlot.getHand(hand); ++ PlayerArmorStandManipulateEvent armorStandManipulateEvent = new PlayerArmorStandManipulateEvent(player1, self, playerHeldItem, armorStandItem, slot1, hand); ++ this.level().getCraftServer().getPluginManager().callEvent(armorStandManipulateEvent); ++ ++ if (armorStandManipulateEvent.isCancelled()) { ++ return true; ++ } ++ ++ if (player.getAbilities().instabuild && itemstack1.isEmpty() && !stack.isEmpty()) { ++ // CraftBukkit end ++ this.setItemSlot(slot, stack.copyWithCount(1)); + return true; + } else if (!itemstack.isEmpty() && itemstack.getCount() > 1) { + if (!itemstack1.isEmpty()) { +@@ -431,18 +454,29 @@ + player.setItemInHand(interactionhand, itemstack1); + return true; + } ++ } // CraftBukkit + } + + @Override + @Override + public boolean hurt(DamageSource damagesource, float f) { + if (!this.level().isClientSide && !this.isRemoved()) { +- if (damagesource.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { ++ if (source.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount)) { ++ return false; ++ } ++ // CraftBukkit end + this.kill(); + return false; +- } else if (!this.isInvulnerableTo(damagesource) && !this.invisible && !this.isMarker()) { +- if (damagesource.is(DamageTypeTags.IS_EXPLOSION)) { +- this.brokenByAnything(damagesource); ++ } else if (!this.isInvulnerableTo(source) && (true || !this.invisible) && !this.isMarker()) { // CraftBukkit ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, true, this.invisible)) { ++ return false; ++ } ++ // CraftBukkit end ++ if (source.is(DamageTypeTags.IS_EXPLOSION)) { ++ this.brokenByAnything(source); + this.kill(); + return false; + } else if (damagesource.is(DamageTypeTags.IGNITES_ARMOR_STANDS)) { +@@ -488,7 +521,7 @@ + } else { + this.brokenByPlayer(damagesource); + this.showBreakingParticles(); +- this.kill(); ++ this.discard(); // CraftBukkit - SPIGOT-4890: remain as this.discard() since above damagesource method will call death event + } + + return true; +@@ -558,13 +589,13 @@ + itemstack.setHoverName(this.getCustomName()); + } + +- Block.popResource(this.level(), this.blockPosition(), itemstack); +- this.brokenByAnything(damagesource); ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops ++ this.brokenByAnything(damageSource); + } + + private void brokenByAnything(DamageSource damagesource) { + this.playBrokenSound(); +- this.dropAllDeathLoot(damagesource); ++ // this.dropAllDeathLoot(damagesource); // CraftBukkit - moved down + + ItemStack itemstack; + int i; +@@ -572,7 +603,7 @@ + for (i = 0; i < this.handItems.size(); ++i) { + itemstack = (ItemStack) this.handItems.get(i); + if (!itemstack.isEmpty()) { +- Block.popResource(this.level(), this.blockPosition().above(), itemstack); ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops + this.handItems.set(i, ItemStack.EMPTY); + } + } +@@ -580,10 +611,11 @@ + for (i = 0; i < this.armorItems.size(); ++i) { + itemstack = (ItemStack) this.armorItems.get(i); + if (!itemstack.isEmpty()) { +- Block.popResource(this.level(), this.blockPosition().above(), itemstack); ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops + this.armorItems.set(i, ItemStack.EMPTY); + } + } ++ this.dropAllDeathLoot(damageSource); // CraftBukkit - moved from above + + } + +@@ -688,9 +711,16 @@ + return this.isSmall(); + } + ++ // CraftBukkit start + @Override ++ public boolean shouldDropExperience() { ++ return true; // MC-157395, SPIGOT-5193 even baby (small) armor stands should drop ++ } ++ // CraftBukkit end ++ + @Override + public void kill() { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event + this.remove(Entity.RemovalReason.KILLED); + this.gameEvent(GameEvent.ENTITY_DIE); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/decoration/HangingEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/decoration/HangingEntity.java.patch new file mode 100644 index 0000000000..fae392e24a --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/decoration/HangingEntity.java.patch @@ -0,0 +1,152 @@ +--- a/net/minecraft/world/entity/decoration/HangingEntity.java ++++ b/net/minecraft/world/entity/decoration/HangingEntity.java +@@ -25,6 +20,17 @@ + import net.minecraft.world.phys.Vec3; + import org.apache.commons.lang3.Validate; + import org.slf4j.Logger; ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.Direction; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.server.level.ServerLevel; ++// CraftBukkit start ++import net.minecraft.tags.DamageTypeTags; ++import net.minecraft.util.Mth; ++import org.bukkit.entity.Hanging; ++import org.bukkit.event.hanging.HangingBreakByEntityEvent; ++import org.bukkit.event.hanging.HangingBreakEvent; ++// CraftBukkit end + + public abstract class HangingEntity extends Entity { + +@@ -61,9 +66,18 @@ + + protected void recalculateBoundingBox() { + if (this.direction != null) { +- double d0 = (double) this.pos.getX() + 0.5D; +- double d1 = (double) this.pos.getY() + 0.5D; +- double d2 = (double) this.pos.getZ() + 0.5D; ++ // CraftBukkit start code moved in to calculateBoundingBox ++ this.setBoundingBox(calculateBoundingBox(this, this.pos, this.direction, this.getWidth(), this.getHeight())); ++ // CraftBukkit end ++ } ++ } ++ ++ // CraftBukkit start - break out BB calc into own method ++ public static AABB calculateBoundingBox(@Nullable Entity entity, BlockPos blockPosition, Direction direction, int width, int height) { ++ { ++ double d0 = (double) blockPosition.getX() + 0.5D; ++ double d1 = (double) blockPosition.getY() + 0.5D; ++ double d2 = (double) blockPosition.getZ() + 0.5D; + double d3 = 0.46875D; + double d4 = this.offs(this.getWidth()); + double d5 = this.offs(this.getHeight()); +@@ -92,8 +108,9 @@ + this.setBoundingBox(new AABB(d0 - d6, d1 - d7, d2 - d8, d0 + d6, d1 + d7, d2 + d8)); + } + } ++ // CraftBukkit end + +- private double offs(int i) { ++ private static double offs(int i) { // CraftBukkit - static + return i % 32 == 0 ? 0.5D : 0.0D; + } + +@@ -105,6 +121,24 @@ + if (this.checkInterval++ == 100) { + this.checkInterval = 0; + if (!this.isRemoved() && !this.survives()) { ++ // CraftBukkit start - fire break events ++ IBlockData material = this.level().getBlockState(this.blockPosition()); ++ HangingBreakEvent.RemoveCause cause; ++ ++ if (!material.isAir()) { ++ // TODO: This feels insufficient to catch 100% of suffocation cases ++ cause = HangingBreakEvent.RemoveCause.OBSTRUCTION; ++ } else { ++ cause = HangingBreakEvent.RemoveCause.PHYSICS; ++ } ++ ++ HangingBreakEvent event = new HangingBreakEvent((Hanging) this.getBukkitEntity(), cause); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (this.isRemoved() || event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.discard(); + this.dropItem((Entity) null); + } +@@ -172,6 +202,22 @@ + return false; + } else { + if (!this.isRemoved() && !this.level().isClientSide) { ++ // CraftBukkit start - fire break events ++ Entity damager = (source.isIndirect()) ? source.getEntity() : source.getDirectEntity(); ++ HangingBreakEvent event; ++ if (damager != null) { ++ event = new HangingBreakByEntityEvent((Hanging) this.getBukkitEntity(), damager.getBukkitEntity(), source.is(DamageTypeTags.IS_EXPLOSION) ? HangingBreakEvent.RemoveCause.EXPLOSION : HangingBreakEvent.RemoveCause.ENTITY); ++ } else { ++ event = new HangingBreakEvent((Hanging) this.getBukkitEntity(), source.is(DamageTypeTags.IS_EXPLOSION) ? HangingBreakEvent.RemoveCause.EXPLOSION : HangingBreakEvent.RemoveCause.DEFAULT); ++ } ++ ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (this.isRemoved() || event.isCancelled()) { ++ return true; ++ } ++ // CraftBukkit end ++ + this.kill(); + this.markHurt(); + this.dropItem(damagesource.getEntity()); +@@ -182,9 +228,20 @@ + } + + @Override +- @Override +- public void move(MoverType movertype, Vec3 vec3) { +- if (!this.level().isClientSide && !this.isRemoved() && vec3.lengthSqr() > 0.0D) { ++ public void move(EnumMoveType type, Vec3 pos) { ++ if (!this.level().isClientSide && !this.isRemoved() && pos.lengthSqr() > 0.0D) { ++ if (this.isRemoved()) return; // CraftBukkit ++ ++ // CraftBukkit start - fire break events ++ // TODO - Does this need its own cause? Seems to only be triggered by pistons ++ HangingBreakEvent event = new HangingBreakEvent((Hanging) this.getBukkitEntity(), HangingBreakEvent.RemoveCause.PHYSICS); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (this.isRemoved() || event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ + this.kill(); + this.dropItem((Entity) null); + } +@@ -192,16 +249,23 @@ + } + + @Override +- @Override +- public void push(double d0, double d1, double d2) { +- if (!this.level().isClientSide && !this.isRemoved() && d0 * d0 + d1 * d1 + d2 * d2 > 0.0D) { ++ public void push(double x, double d1, double y) { ++ if (false && !this.level().isClientSide && !this.isRemoved() && x * x + d1 * d1 + y * y > 0.0D) { // CraftBukkit - not needed + this.kill(); + this.dropItem((Entity) null); + } + + } + ++ // CraftBukkit start - selectively save tile position + @Override ++ public void addAdditionalSaveData(CompoundTag nbttagcompound, boolean includeAll) { ++ if (includeAll) { ++ addAdditionalSaveData(nbttagcompound); ++ } ++ } ++ // CraftBukkit end ++ + @Override + public void addAdditionalSaveData(CompoundTag compoundtag) { + BlockPos blockpos = this.getPos(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/decoration/ItemFrame.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/decoration/ItemFrame.java.patch new file mode 100644 index 0000000000..1097eada2c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/decoration/ItemFrame.java.patch @@ -0,0 +1,65 @@ +--- a/net/minecraft/world/entity/decoration/ItemFrame.java ++++ b/net/minecraft/world/entity/decoration/ItemFrame.java +@@ -100,6 +96,15 @@ + @Override + protected void recalculateBoundingBox() { + if (this.direction != null) { ++ // CraftBukkit start code moved in to calculateBoundingBox ++ this.setBoundingBox(calculateBoundingBox(this, this.pos, this.direction, this.getWidth(), this.getHeight())); ++ // CraftBukkit end ++ } ++ } ++ ++ // CraftBukkit start - break out BB calc into own method ++ public static AABB calculateBoundingBox(@Nullable Entity entity, BlockPos blockPosition, Direction direction, int width, int height) { ++ { + double d0 = 0.46875D; + double d1 = (double) this.pos.getX() + 0.5D - (double) this.direction.getStepX() * 0.46875D; + double d2 = (double) this.pos.getY() + 0.5D - (double) this.direction.getStepY() * 0.46875D; +@@ -128,6 +135,7 @@ + this.setBoundingBox(new AABB(d1 - d4, d2 - d5, d3 - d6, d1 + d4, d2 + d5, d3 + d6)); + } + } ++ // CraftBukkit end + + @Override + @Override +@@ -177,8 +180,13 @@ + return false; + } else if (!damagesource.is(DamageTypeTags.IS_EXPLOSION) && !this.getItem().isEmpty()) { + if (!this.level().isClientSide) { +- this.dropItem(damagesource.getEntity(), false); +- this.gameEvent(GameEvent.BLOCK_CHANGE, damagesource.getEntity()); ++ // CraftBukkit start - fire EntityDamageEvent ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, false) || this.isRemoved()) { ++ return true; ++ } ++ // CraftBukkit end ++ this.dropItem(source.getEntity(), false); ++ this.gameEvent(GameEvent.BLOCK_CHANGE, source.getEntity()); + this.playSound(this.getRemoveItemSound(), 1.0F, 1.0F); + } + +@@ -310,14 +313,20 @@ + this.setItem(itemstack, true); + } + +- public void setItem(ItemStack itemstack, boolean flag) { ++ public void setItem(ItemStack stack, boolean updateNeighbours) { ++ // CraftBukkit start ++ this.setItem(stack, updateNeighbours, true); ++ } ++ ++ public void setItem(ItemStack itemstack, boolean flag, boolean playSound) { ++ // CraftBukkit end + if (!itemstack.isEmpty()) { + itemstack = itemstack.copyWithCount(1); + } + + this.onItemChanged(itemstack); + this.getEntityData().set(ItemFrame.DATA_ITEM, itemstack); +- if (!itemstack.isEmpty()) { ++ if (!itemstack.isEmpty() && playSound) { // CraftBukkit + this.playSound(this.getAddItemSound(), 1.0F, 1.0F); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java.patch new file mode 100644 index 0000000000..12bf5ad58a --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java.patch @@ -0,0 +1,65 @@ +--- a/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java ++++ b/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java +@@ -25,6 +27,8 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class LeashFenceKnotEntity extends HangingEntity { + +@@ -105,8 +99,14 @@ + while (iterator.hasNext()) { + Mob mob = (Mob) iterator.next(); + +- if (mob.getLeashHolder() == player) { +- mob.setLeashedTo(this, true); ++ if (entityinsentient.getLeashHolder() == player) { ++ // CraftBukkit start ++ if (CraftEventFactory.callPlayerLeashEntityEvent(entityinsentient, this, player, hand).isCancelled()) { ++ ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(entityinsentient, entityinsentient.getLeashHolder())); ++ continue; ++ } ++ // CraftBukkit end ++ entityinsentient.setLeashedTo(this, true); + flag = true; + } + } +@@ -114,18 +114,32 @@ + boolean flag1 = false; + + if (!flag) { +- this.discard(); +- if (player.getAbilities().instabuild) { ++ // CraftBukkit start - Move below ++ // this.discard(); ++ boolean die = true; ++ // CraftBukkit end ++ if (true || player.getAbilities().instabuild) { // CraftBukkit - Process for non-creative as well + Iterator iterator1 = list.iterator(); + + while (iterator1.hasNext()) { + Mob mob1 = (Mob) iterator1.next(); + +- if (mob1.isLeashed() && mob1.getLeashHolder() == this) { +- mob1.dropLeash(true, false); ++ if (entityinsentient1.isLeashed() && entityinsentient1.getLeashHolder() == this) { ++ // CraftBukkit start ++ if (CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient1, player, hand).isCancelled()) { ++ die = false; ++ continue; ++ } ++ entityinsentient1.dropLeash(true, !player.getAbilities().instabuild); // false -> survival mode boolean ++ // CraftBukkit end + flag1 = true; + } + } ++ // CraftBukkit start ++ if (die) { ++ this.discard(); ++ } ++ // CraftBukkit end + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/item/FallingBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/item/FallingBlockEntity.java.patch new file mode 100644 index 0000000000..2a0c5ba3a4 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/item/FallingBlockEntity.java.patch @@ -0,0 +1,65 @@ +--- a/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -49,6 +49,10 @@ + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class FallingBlockEntity extends Entity { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -82,12 +86,19 @@ + this.setStartPos(this.blockPosition()); + } + +- public static FallingBlockEntity fall(Level level, BlockPos blockpos, BlockState blockstate) { +- FallingBlockEntity fallingblockentity = new FallingBlockEntity(level, (double) blockpos.getX() + 0.5D, (double) blockpos.getY(), (double) blockpos.getZ() + 0.5D, blockstate.hasProperty(BlockStateProperties.WATERLOGGED) ? (BlockState) blockstate.setValue(BlockStateProperties.WATERLOGGED, false) : blockstate); ++ public static FallingBlockEntity fall(Level level, BlockPos pos, IBlockData blockState) { ++ // CraftBukkit start ++ return fall(level, pos, blockState, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } + +- level.setBlock(blockpos, blockstate.getFluidState().createLegacyBlock(), 3); +- level.addFreshEntity(fallingblockentity); +- return fallingblockentity; ++ public static FallingBlockEntity fall(Level world, BlockPos blockposition, IBlockData iblockdata, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end ++ FallingBlockEntity entityfallingblock = new FallingBlockEntity(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, iblockdata.hasProperty(BlockStateProperties.WATERLOGGED) ? (IBlockData) iblockdata.setValue(BlockStateProperties.WATERLOGGED, false) : iblockdata); ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entityfallingblock, blockposition, iblockdata.getFluidState().createLegacyBlock())) return entityfallingblock; // CraftBukkit ++ ++ world.setBlock(blockposition, iblockdata.getFluidState().createLegacyBlock(), 3); ++ world.addFreshEntity(entityfallingblock, spawnReason); // CraftBukkit ++ return entityfallingblock; + } + + @Override +@@ -174,8 +180,14 @@ + this.blockState = (BlockState) this.blockState.setValue(BlockStateProperties.WATERLOGGED, true); + } + +- if (this.level().setBlock(blockpos, this.blockState, 3)) { +- ((ServerLevel) this.level()).getChunkSource().chunkMap.broadcast(this, new ClientboundBlockUpdatePacket(blockpos, this.level().getBlockState(blockpos))); ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, this.blockState)) { ++ this.discard(); // SPIGOT-6586 called before the event in previous versions ++ return; ++ } ++ // CraftBukkit end ++ if (this.level().setBlock(blockposition, this.blockState, 3)) { ++ ((ServerLevel) this.level()).getChunkSource().chunkMap.broadcast(this, new ClientboundBlockUpdatePacket(blockposition, this.level().getBlockState(blockposition))); + this.discard(); + if (block instanceof Fallable) { + ((Fallable) block).onLand(this.level(), blockpos, this.blockState, blockstate, this); +@@ -261,7 +272,9 @@ + float f2 = (float) Math.min(Mth.floor((float) i * this.fallDamagePerDistance), this.fallDamageMax); + + this.level().getEntities((Entity) this, this.getBoundingBox(), predicate).forEach((entity) -> { ++ CraftEventFactory.entityDamage = this; // CraftBukkit + entity.hurt(damagesource2, f2); ++ CraftEventFactory.entityDamage = null; // CraftBukkit + }); + boolean flag = this.blockState.is(BlockTags.ANVIL); + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/item/ItemEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/item/ItemEntity.java.patch new file mode 100644 index 0000000000..e36cc3a090 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/item/ItemEntity.java.patch @@ -0,0 +1,162 @@ +--- a/net/minecraft/world/entity/item/ItemEntity.java ++++ b/net/minecraft/world/entity/item/ItemEntity.java +@@ -30,6 +20,22 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3; ++import net.minecraft.core.BlockPos; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.network.chat.Component; ++import net.minecraft.network.syncher.EntityDataAccessor; ++import net.minecraft.network.syncher.EntityDataSerializers; ++import net.minecraft.network.syncher.SynchedEntityData; ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.sounds.SoundSource; ++import net.minecraft.stats.Stats; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.entity.Player; ++import org.bukkit.event.entity.EntityPickupItemEvent; ++import org.bukkit.event.player.PlayerPickupItemEvent; ++// CraftBukkit end + + public class ItemEntity extends Entity implements TraceableEntity { + +@@ -47,6 +53,7 @@ + @Nullable + private UUID target; + public final float bobOffs; ++ private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit + + public ItemEntity(EntityType entitytype, Level level) { + super(entitytype, level); +@@ -134,9 +135,12 @@ + this.discard(); + } else { + super.tick(); +- if (this.pickupDelay > 0 && this.pickupDelay != 32767) { +- --this.pickupDelay; +- } ++ // CraftBukkit start - Use wall time for pickup and despawn timers ++ int elapsedTicks = MinecraftServer.currentTick - this.lastTick; ++ if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; ++ if (this.age != -32768) this.age += elapsedTicks; ++ this.lastTick = MinecraftServer.currentTick; ++ // CraftBukkit end + + this.xo = this.getX(); + this.yo = this.getY(); +@@ -186,9 +190,11 @@ + this.mergeWithNeighbours(); + } + ++ /* CraftBukkit start - moved up + if (this.age != -32768) { + ++this.age; + } ++ // CraftBukkit end */ + + this.hasImpulse |= this.updateInWaterStateAndDoFluidPushing(); + if (!this.level().isClientSide) { +@@ -200,6 +206,12 @@ + } + + if (!this.level().isClientSide && this.age >= 6000) { ++ // CraftBukkit start - fire ItemDespawnEvent ++ if (CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { ++ this.age = 0; ++ return; ++ } ++ // CraftBukkit end + this.discard(); + } + +@@ -283,13 +294,18 @@ + itementity.setItem(itemstack2); + } + +- private static void merge(ItemEntity itementity, ItemStack itemstack, ItemEntity itementity1, ItemStack itemstack1) { +- merge(itementity, itemstack, itemstack1); +- itementity.pickupDelay = Math.max(itementity.pickupDelay, itementity1.pickupDelay); +- itementity.age = Math.min(itementity.age, itementity1.age); +- if (itemstack1.isEmpty()) { +- itementity1.discard(); ++ private static void merge(ItemEntity destinationEntity, ItemStack destinationStack, ItemEntity originEntity, ItemStack originStack) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callItemMergeEvent(originEntity, destinationEntity)) { ++ return; + } ++ // CraftBukkit end ++ merge(destinationEntity, destinationStack, originStack); ++ destinationEntity.pickupDelay = Math.max(destinationEntity.pickupDelay, originEntity.pickupDelay); ++ destinationEntity.age = Math.min(destinationEntity.age, originEntity.age); ++ if (originStack.isEmpty()) { ++ originEntity.discard(); ++ } + + } + +@@ -311,6 +325,11 @@ + } else if (this.level().isClientSide) { + return true; + } else { ++ // CraftBukkit start ++ if (CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount)) { ++ return false; ++ } ++ // CraftBukkit end + this.markHurt(); + this.health = (int) ((float) this.health - f); + this.gameEvent(GameEvent.ENTITY_DAMAGE, damagesource.getEntity()); +@@ -378,8 +394,48 @@ + Item item = itemstack.getItem(); + int i = itemstack.getCount(); + +- if (this.pickupDelay == 0 && (this.target == null || this.target.equals(player.getUUID())) && player.getInventory().add(itemstack)) { +- player.take(this, i); ++ // CraftBukkit start - fire PlayerPickupItemEvent ++ int canHold = entity.getInventory().canHold(itemstack); ++ int remaining = i - canHold; ++ ++ if (this.pickupDelay <= 0 && canHold > 0) { ++ itemstack.setCount(canHold); ++ // Call legacy event ++ PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent((Player) entity.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); ++ playerEvent.setCancelled(!playerEvent.getPlayer().getCanPickupItems()); ++ this.level().getCraftServer().getPluginManager().callEvent(playerEvent); ++ if (playerEvent.isCancelled()) { ++ itemstack.setCount(i); // SPIGOT-5294 - restore count ++ return; ++ } ++ ++ // Call newer event afterwards ++ EntityPickupItemEvent entityEvent = new EntityPickupItemEvent((Player) entity.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); ++ entityEvent.setCancelled(!entityEvent.getEntity().getCanPickupItems()); ++ this.level().getCraftServer().getPluginManager().callEvent(entityEvent); ++ if (entityEvent.isCancelled()) { ++ itemstack.setCount(i); // SPIGOT-5294 - restore count ++ return; ++ } ++ ++ // Update the ItemStack if it was changed in the event ++ ItemStack current = this.getItem(); ++ if (!itemstack.equals(current)) { ++ itemstack = current; ++ } else { ++ itemstack.setCount(canHold + remaining); // = i ++ } ++ ++ // Possibly < 0; fix here so we do not have to modify code below ++ this.pickupDelay = 0; ++ } else if (this.pickupDelay == 0) { ++ // ensure that the code below isn't triggered if canHold says we can't pick the items up ++ this.pickupDelay = -1; ++ } ++ // CraftBukkit end ++ ++ if (this.pickupDelay == 0 && (this.target == null || this.target.equals(entity.getUUID())) && entity.getInventory().add(itemstack)) { ++ entity.take(this, i); + if (itemstack.isEmpty()) { + this.discard(); + itemstack.setCount(i); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/item/PrimedTnt.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/item/PrimedTnt.java.patch new file mode 100644 index 0000000000..ece1ce8332 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/item/PrimedTnt.java.patch @@ -0,0 +1,57 @@ +--- a/net/minecraft/world/entity/item/PrimedTnt.java ++++ b/net/minecraft/world/entity/item/PrimedTnt.java +@@ -19,6 +19,11 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end ++ + public class PrimedTnt extends Entity implements TraceableEntity { + + private static final EntityDataAccessor DATA_FUSE_ID = SynchedEntityData.defineId(PrimedTnt.class, EntityDataSerializers.INT); +@@ -27,7 +32,9 @@ + private static final String TAG_BLOCK_STATE = "block_state"; + public static final String TAG_FUSE = "fuse"; + @Nullable +- private LivingEntity owner; ++ public LivingEntity owner; ++ public float yield = 4; // CraftBukkit - add field ++ public boolean isIncendiary = false; // CraftBukkit - add field + + public PrimedTnt(EntityType entitytype, Level level) { + super(entitytype, level); +@@ -83,10 +86,13 @@ + + this.setFuse(i); + if (i <= 0) { +- this.discard(); ++ // CraftBukkit start - Need to reverse the order of the explosion and the entity death so we have a location for the event ++ // this.discard(); + if (!this.level().isClientSide) { + this.explode(); + } ++ this.discard(); ++ // CraftBukkit end + } else { + this.updateInWaterStateAndDoFluidPushing(); + if (this.level().isClientSide) { +@@ -97,9 +103,14 @@ + } + + private void explode() { +- float f = 4.0F; ++ // CraftBukkit start ++ // float f = 4.0F; ++ ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent((org.bukkit.entity.Explosive)this.getBukkitEntity()); + +- this.level().explode(this, this.getX(), this.getY(0.0625D), this.getZ(), 4.0F, Level.ExplosionInteraction.TNT); ++ if (!event.isCancelled()) { ++ this.level().explode(this, this.getX(), this.getY(0.0625D), this.getZ(), event.getRadius(), event.getFire(), Level.a.TNT); ++ } ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/AbstractSkeleton.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/AbstractSkeleton.java.patch new file mode 100644 index 0000000000..88a4ace98b --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/AbstractSkeleton.java.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/world/entity/monster/AbstractSkeleton.java ++++ b/net/minecraft/world/entity/monster/AbstractSkeleton.java +@@ -209,9 +199,20 @@ + double d2 = livingentity.getZ() - this.getZ(); + double d3 = Math.sqrt(d0 * d0 + d2 * d2); + +- abstractarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level().getDifficulty().getId() * 4)); ++ entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level().getDifficulty().getId() * 4)); ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), null, entityarrow, net.minecraft.world.EnumHand.MAIN_HAND, 0.8F, true); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ ++ if (event.getProjectile() == entityarrow.getBukkitEntity()) { ++ this.level().addFreshEntity(entityarrow); ++ } ++ // CraftBukkit end + this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); +- this.level().addFreshEntity(abstractarrow); ++ // this.level().addFreshEntity(entityarrow); // CraftBukkit - moved up + } + + protected AbstractArrow getArrow(ItemStack itemstack, float f) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/CaveSpider.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/CaveSpider.java.patch new file mode 100644 index 0000000000..5af24b6b00 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/CaveSpider.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/monster/CaveSpider.java ++++ b/net/minecraft/world/entity/monster/CaveSpider.java +@@ -43,7 +42,7 @@ + } + + if (b0 > 0) { +- ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.POISON, b0 * 20, 0), this); ++ ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.POISON, b0 * 20, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Creeper.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Creeper.java.patch new file mode 100644 index 0000000000..36a4a02c69 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Creeper.java.patch @@ -0,0 +1,98 @@ +--- a/net/minecraft/world/entity/monster/Creeper.java ++++ b/net/minecraft/world/entity/monster/Creeper.java +@@ -43,6 +43,12 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end ++ + public class Creeper extends Monster implements PowerableMob { + + private static final EntityDataAccessor DATA_SWELL_DIR = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.INT); +@@ -229,12 +222,22 @@ + } + + @Override +- @Override +- public void thunderHit(ServerLevel serverlevel, LightningBolt lightningbolt) { +- super.thunderHit(serverlevel, lightningbolt); ++ public void thunderHit(ServerLevel level, LightningBolt lightning) { ++ super.thunderHit(level, lightning); ++ // CraftBukkit start ++ if (CraftEventFactory.callCreeperPowerEvent(this, lightning, org.bukkit.event.entity.CreeperPowerEvent.PowerCause.LIGHTNING).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.entityData.set(Creeper.DATA_IS_POWERED, true); + } + ++ // CraftBukkit start ++ public void setPowered(boolean powered) { ++ this.entityData.set(Creeper.DATA_IS_POWERED, powered); ++ } ++ // CraftBukkit end ++ + @Override + @Override + protected InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +@@ -246,7 +248,7 @@ + this.level().playSound(player, this.getX(), this.getY(), this.getZ(), soundevent, this.getSoundSource(), 1.0F, this.random.nextFloat() * 0.4F + 0.8F); + if (!this.level().isClientSide) { + this.ignite(); +- if (!itemstack.isDamageableItem()) { ++ if (itemstack.getItem().getMaxDamage() == 0) { // CraftBukkit - fix MC-264285: unbreakable flint and steels are completely consumed when igniting a creeper + itemstack.shrink(1); + } else { + itemstack.hurtAndBreak(1, player, (player1) -> { +@@ -265,10 +267,19 @@ + if (!this.level().isClientSide) { + float f = this.isPowered() ? 2.0F : 1.0F; + ++ // CraftBukkit start ++ ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent(this, this.explosionRadius * f, false); ++ if (!event.isCancelled()) { ++ // CraftBukkit end + this.dead = true; +- this.level().explode(this, this.getX(), this.getY(), this.getZ(), (float) this.explosionRadius * f, Level.ExplosionInteraction.MOB); ++ this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.MOB); // CraftBukkit + this.discard(); + this.spawnLingeringCloud(); ++ // CraftBukkit start ++ } else { ++ swell = 0; ++ } ++ // CraftBukkit end + } + + } +@@ -279,11 +290,12 @@ + if (!collection.isEmpty()) { + AreaEffectCloud areaeffectcloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); + +- areaeffectcloud.setRadius(2.5F); +- areaeffectcloud.setRadiusOnUse(-0.5F); +- areaeffectcloud.setWaitTime(10); +- areaeffectcloud.setDuration(areaeffectcloud.getDuration() / 2); +- areaeffectcloud.setRadiusPerTick(-areaeffectcloud.getRadius() / (float) areaeffectcloud.getDuration()); ++ entityareaeffectcloud.setOwner(this); // CraftBukkit ++ entityareaeffectcloud.setRadius(2.5F); ++ entityareaeffectcloud.setRadiusOnUse(-0.5F); ++ entityareaeffectcloud.setWaitTime(10); ++ entityareaeffectcloud.setDuration(entityareaeffectcloud.getDuration() / 2); ++ entityareaeffectcloud.setRadiusPerTick(-entityareaeffectcloud.getRadius() / (float) entityareaeffectcloud.getDuration()); + Iterator iterator = collection.iterator(); + + while (iterator.hasNext()) { +@@ -292,7 +304,7 @@ + areaeffectcloud.addEffect(new MobEffectInstance(mobeffectinstance)); + } + +- this.level().addFreshEntity(areaeffectcloud); ++ this.level().addFreshEntity(entityareaeffectcloud, CreatureSpawnEvent.SpawnReason.EXPLOSION); // CraftBukkit + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Drowned.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Drowned.java.patch new file mode 100644 index 0000000000..67ee44fa5b --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Drowned.java.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/entity/monster/Drowned.java ++++ b/net/minecraft/world/entity/monster/Drowned.java +@@ -260,12 +243,11 @@ + } + + @Override +- @Override +- public void performRangedAttack(LivingEntity livingentity, float f) { +- ThrownTrident throwntrident = new ThrownTrident(this.level(), this, new ItemStack(Items.TRIDENT)); +- double d0 = livingentity.getX() - this.getX(); +- double d1 = livingentity.getY(0.3333333333333333D) - throwntrident.getY(); +- double d2 = livingentity.getZ() - this.getZ(); ++ public void performRangedAttack(LivingEntity target, float distanceFactor) { ++ ThrownTrident entitythrowntrident = new ThrownTrident(this.level(), this, this.getItemInHand(net.minecraft.world.entity.projectile.ProjectileUtil.getWeaponHoldingHand(this, Items.TRIDENT))); // CraftBukkit - Use Trident in hand like skeletons (SPIGOT-7025) ++ double d0 = target.getX() - this.getX(); ++ double d1 = target.getY(0.3333333333333333D) - entitythrowntrident.getY(); ++ double d2 = target.getZ() - this.getZ(); + double d3 = Math.sqrt(d0 * d0 + d2 * d2); + + throwntrident.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level().getDifficulty().getId() * 4)); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/ElderGuardian.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/ElderGuardian.java.patch new file mode 100644 index 0000000000..c15872accd --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/ElderGuardian.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/entity/monster/ElderGuardian.java ++++ b/net/minecraft/world/entity/monster/ElderGuardian.java +@@ -75,8 +69,8 @@ + protected void customServerAiStep() { + super.customServerAiStep(); + if ((this.tickCount + this.getId()) % 1200 == 0) { +- MobEffectInstance mobeffectinstance = new MobEffectInstance(MobEffects.DIG_SLOWDOWN, 6000, 2); +- List list = MobEffectUtil.addEffectToPlayersAround((ServerLevel) this.level(), this, this.position(), 50.0D, mobeffectinstance, 1200); ++ MobEffectInstance mobeffect = new MobEffectInstance(MobEffects.DIG_SLOWDOWN, 6000, 2); ++ List list = MobEffectUtil.addEffectToPlayersAround((ServerLevel) this.level(), this, this.position(), 50.0D, mobeffect, 1200, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + + list.forEach((serverplayer) -> { + serverplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, this.isSilent() ? 0.0F : 1.0F)); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/EnderMan.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/EnderMan.java.patch new file mode 100644 index 0000000000..93aa700933 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/EnderMan.java.patch @@ -0,0 +1,75 @@ +--- a/net/minecraft/world/entity/monster/EnderMan.java ++++ b/net/minecraft/world/entity/monster/EnderMan.java +@@ -71,6 +71,11 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end ++ + public class EnderMan extends Monster implements NeutralMob { + + private static final UUID SPEED_MODIFIER_ATTACKING_UUID = UUID.fromString("020E0DFB-87AE-4653-9556-831010E291A0"); +@@ -115,10 +119,19 @@ + } + + @Override ++ public void setTarget(@Nullable LivingEntity livingEntity) { ++ // CraftBukkit start - fire event ++ setTarget(livingEntity, EntityTargetEvent.TargetReason.UNKNOWN, true); ++ } ++ + @Override +- public void setTarget(@Nullable LivingEntity livingentity) { +- super.setTarget(livingentity); +- AttributeInstance attributeinstance = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ public boolean setTarget(LivingEntity entityliving, EntityTargetEvent.TargetReason reason, boolean fireEvent) { ++ if (!super.setTarget(entityliving, reason, fireEvent)) { ++ return false; ++ } ++ entityliving = getTarget(); ++ // CraftBukkit end ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); + + if (livingentity == null) { + this.targetChangeTime = 0; +@@ -517,12 +506,14 @@ + BlockState blockstate1 = level.getBlockState(blockpos1); + BlockState blockstate2 = this.enderman.getCarriedBlock(); + +- if (blockstate2 != null) { +- blockstate2 = Block.updateFromNeighbourShapes(blockstate2, this.enderman.level(), blockpos); +- if (this.canPlaceBlock(level, blockpos, blockstate2, blockstate, blockstate1, blockpos1)) { +- level.setBlock(blockpos, blockstate2, 3); +- level.gameEvent(GameEvent.BLOCK_PLACE, blockpos, GameEvent.Context.of(this.enderman, blockstate2)); +- this.enderman.setCarriedBlock((BlockState) null); ++ if (iblockdata2 != null) { ++ iblockdata2 = Block.updateFromNeighbourShapes(iblockdata2, this.enderman.level(), blockposition); ++ if (this.canPlaceBlock(world, blockposition, iblockdata2, iblockdata, iblockdata1, blockposition1)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockposition, iblockdata2)) { // CraftBukkit - Place event ++ world.setBlock(blockposition, iblockdata2, 3); ++ world.gameEvent(GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(this.enderman, iblockdata2)); ++ this.enderman.setCarriedBlock((IBlockData) null); ++ } // CraftBukkit + } + + } +@@ -562,10 +551,12 @@ + BlockHitResult blockhitresult = level.clip(new ClipContext(vec3, vec31, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.enderman)); + boolean flag = blockhitresult.getBlockPos().equals(blockpos); + +- if (blockstate.is(BlockTags.ENDERMAN_HOLDABLE) && flag) { +- level.removeBlock(blockpos, false); +- level.gameEvent(GameEvent.BLOCK_DESTROY, blockpos, GameEvent.Context.of(this.enderman, blockstate)); +- this.enderman.setCarriedBlock(blockstate.getBlock().defaultBlockState()); ++ if (iblockdata.is(BlockTags.ENDERMAN_HOLDABLE) && flag) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockposition, Blocks.AIR.defaultBlockState())) { // CraftBukkit - Place event ++ world.removeBlock(blockposition, false); ++ world.gameEvent(GameEvent.BLOCK_DESTROY, blockposition, GameEvent.Context.of(this.enderman, iblockdata)); ++ this.enderman.setCarriedBlock(iblockdata.getBlock().defaultBlockState()); ++ } // CraftBukkit + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Evoker.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Evoker.java.patch new file mode 100644 index 0000000000..9eafb5e220 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Evoker.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/entity/monster/Evoker.java ++++ b/net/minecraft/world/entity/monster/Evoker.java +@@ -217,8 +200,8 @@ + serverlevel.getScoreboard().addPlayerToTeam(vex.getScoreboardName(), playerteam); + } + +- serverlevel.addFreshEntityWithPassengers(vex); +- serverlevel.gameEvent(GameEvent.ENTITY_PLACE, blockpos, GameEvent.Context.of((Entity) Evoker.this)); ++ worldserver.addFreshEntityWithPassengers(entityvex, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPELL); // CraftBukkit - Add SpawnReason ++ worldserver.gameEvent(GameEvent.ENTITY_PLACE, blockposition, GameEvent.Context.of((Entity) Evoker.this)); + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Ghast.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Ghast.java.patch new file mode 100644 index 0000000000..d4f69001e5 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Ghast.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/entity/monster/Ghast.java ++++ b/net/minecraft/world/entity/monster/Ghast.java +@@ -376,8 +348,10 @@ + + LargeFireball largefireball = new LargeFireball(level, this.ghast, d2, d3, d4, this.ghast.getExplosionPower()); + +- largefireball.setPos(this.ghast.getX() + vec3.x * 4.0D, this.ghast.getY(0.5D) + 0.5D, largefireball.getZ() + vec3.z * 4.0D); +- level.addFreshEntity(largefireball); ++ // CraftBukkit - set bukkitYield when setting explosionpower ++ entitylargefireball.bukkitYield = entitylargefireball.explosionPower = this.ghast.getExplosionPower(); ++ entitylargefireball.setPos(this.ghast.getX() + vec3d.x * 4.0D, this.ghast.getY(0.5D) + 0.5D, entitylargefireball.getZ() + vec3d.z * 4.0D); ++ world.addFreshEntity(entitylargefireball); + this.chargeTime = -40; + } + } else if (this.chargeTime > 0) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Guardian.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Guardian.java.patch new file mode 100644 index 0000000000..f5f9f6ea39 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Guardian.java.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/world/entity/monster/Guardian.java ++++ b/net/minecraft/world/entity/monster/Guardian.java +@@ -62,7 +62,8 @@ + private int clientSideAttackTime; + private boolean clientSideTouchedGround; + @Nullable +- protected RandomStrollGoal randomStrollGoal; ++ public RandomStrollGoal randomStrollGoal; ++ public Guardian.GuardianAttackGoal guardianAttackGoal; // CraftBukkit - add field + + public Guardian(EntityType entitytype, Level level) { + super(entitytype, level); +@@ -79,8 +79,8 @@ + MoveTowardsRestrictionGoal movetowardsrestrictiongoal = new MoveTowardsRestrictionGoal(this, 1.0D); + + this.randomStrollGoal = new RandomStrollGoal(this, 1.0D, 80); +- this.goalSelector.addGoal(4, new Guardian.GuardianAttackGoal(this)); +- this.goalSelector.addGoal(5, movetowardsrestrictiongoal); ++ this.goalSelector.addGoal(4, guardianAttackGoal = new Guardian.GuardianAttackGoal(this)); // CraftBukkit - assign field ++ this.goalSelector.addGoal(5, pathfindergoalmovetowardsrestriction); + this.goalSelector.addGoal(7, this.randomStrollGoal); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Guardian.class, 12.0F, 0.01F)); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Husk.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Husk.java.patch new file mode 100644 index 0000000000..a4d25b959c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Husk.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/monster/Husk.java ++++ b/net/minecraft/world/entity/monster/Husk.java +@@ -66,7 +60,7 @@ + if (flag && this.getMainHandItem().isEmpty() && entity instanceof LivingEntity) { + float f = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty(); + +- ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.HUNGER, 140 * (int) f), this); ++ ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.HUNGER, 140 * (int) f), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + + return flag; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Illusioner.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Illusioner.java.patch new file mode 100644 index 0000000000..61b1f950ce --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Illusioner.java.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/entity/monster/Illusioner.java ++++ b/net/minecraft/world/entity/monster/Illusioner.java +@@ -246,7 +228,7 @@ + @Override + @Override + protected void performSpellCasting() { +- Illusioner.this.addEffect(new MobEffectInstance(MobEffects.INVISIBILITY, 1200)); ++ Illusioner.this.addEffect(new MobEffectInstance(MobEffects.INVISIBILITY, 1200), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ILLUSION); // CraftBukkit + } + + @Nullable +@@ -304,7 +279,7 @@ + @Override + @Override + protected void performSpellCasting() { +- Illusioner.this.getTarget().addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 400), Illusioner.this); ++ Illusioner.this.getTarget().addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 400), Illusioner.this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Phantom.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Phantom.java.patch new file mode 100644 index 0000000000..c80803c72b --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Phantom.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/entity/monster/Phantom.java ++++ b/net/minecraft/world/entity/monster/Phantom.java +@@ -589,8 +549,8 @@ + while (iterator.hasNext()) { + Player player = (Player) iterator.next(); + +- if (Phantom.this.canAttack(player, TargetingConditions.DEFAULT)) { +- Phantom.this.setTarget(player); ++ if (Phantom.this.canAttack(entityhuman, TargetingConditions.DEFAULT)) { ++ Phantom.this.setTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit - reason + return true; + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Ravager.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Ravager.java.patch new file mode 100644 index 0000000000..ed04ec54ac --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Ravager.java.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/world/entity/monster/Ravager.java ++++ b/net/minecraft/world/entity/monster/Ravager.java +@@ -43,6 +43,10 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class Ravager extends Raider { + + private static final Predicate NO_RAVAGER_AND_ALIVE = (entity) -> { +@@ -161,7 +157,12 @@ + Block block = blockstate.getBlock(); + + if (block instanceof LeavesBlock) { +- flag = this.level().destroyBlock(blockpos, true, this) || flag; ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState())) { ++ continue; ++ } ++ // CraftBukkit end ++ flag = this.level().destroyBlock(blockposition, true, this) || flag; + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Shulker.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Shulker.java.patch new file mode 100644 index 0000000000..2e8b3aa748 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Shulker.java.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/world/entity/monster/Shulker.java ++++ b/net/minecraft/world/entity/monster/Shulker.java +@@ -59,7 +59,11 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Shulker extends AbstractGolem implements VariantHolder>, Enemy { ++// CraftBukkit start ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.entity.EntityTeleportEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + private static final UUID COVERED_ARMOR_MODIFIER_UUID = UUID.fromString("7E0292F2-9434-48D5-A29F-9583AF7DF27F"); + private static final AttributeModifier COVERED_ARMOR_MODIFIER = new AttributeModifier(Shulker.COVERED_ARMOR_MODIFIER_UUID, "Covered armor bonus", 20.0D, AttributeModifier.Operation.ADDITION); +@@ -419,7 +405,15 @@ + if (blockpos1.getY() > this.level().getMinBuildHeight() && this.level().isEmptyBlock(blockpos1) && this.level().getWorldBorder().isWithinBounds(blockpos1) && this.level().noCollision(this, (new AABB(blockpos1)).deflate(1.0E-6D))) { + Direction direction = this.findAttachableSurface(blockpos1); + +- if (direction != null) { ++ if (enumdirection != null) { ++ // CraftBukkit start ++ EntityTeleportEvent teleportEvent = CraftEventFactory.callEntityTeleportEvent(this, blockposition1.getX(), blockposition1.getY(), blockposition1.getZ()); ++ if (teleportEvent.isCancelled()) { ++ return false; ++ } else { ++ blockposition1 = CraftLocation.toBlockPosition(teleportEvent.getTo()); ++ } ++ // CraftBukkit end + this.unRide(); + this.setAttachFace(direction); + this.playSound(SoundEvents.SHULKER_TELEPORT, 1.0F, 1.0F); +@@ -489,10 +481,10 @@ + if (this.level().random.nextFloat() >= f) { + Shulker shulker = (Shulker) EntityType.SHULKER.create(this.level()); + +- if (shulker != null) { +- shulker.setVariant(this.getVariant()); +- shulker.moveTo(vec3); +- this.level().addFreshEntity(shulker); ++ if (entityshulker != null) { ++ entityshulker.setVariant(this.getVariant()); ++ entityshulker.moveTo(vec3d); ++ this.level().addFreshEntity(entityshulker, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - the mysteries of life + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Silverfish.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Silverfish.java.patch new file mode 100644 index 0000000000..78592dad43 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Silverfish.java.patch @@ -0,0 +1,45 @@ +--- a/net/minecraft/world/entity/monster/Silverfish.java ++++ b/net/minecraft/world/entity/monster/Silverfish.java +@@ -34,6 +34,10 @@ + import net.minecraft.world.level.block.state.BlockState; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class Silverfish extends Monster { + + @Nullable +@@ -191,8 +180,13 @@ + Block block = blockstate.getBlock(); + + if (block instanceof InfestedBlock) { +- if (level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- level.destroyBlock(blockpos1, true, this.silverfish); ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.silverfish, blockposition1, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState())) { ++ continue; ++ } ++ // CraftBukkit end ++ if (world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ world.destroyBlock(blockposition1, true, this.silverfish); + } else { + level.setBlock(blockpos1, ((InfestedBlock) block).hostStateByInfested(level.getBlockState(blockpos1)), 3); + } +@@ -262,8 +253,13 @@ + BlockPos blockpos = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5D, this.mob.getZ()).relative(this.selectedDirection); + BlockState blockstate = level.getBlockState(blockpos); + +- if (InfestedBlock.isCompatibleHostBlock(blockstate)) { +- level.setBlock(blockpos, InfestedBlock.infestedStateByHost(blockstate), 3); ++ if (InfestedBlock.isCompatibleHostBlock(iblockdata)) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition, InfestedBlock.infestedStateByHost(iblockdata))) { ++ return; ++ } ++ // CraftBukkit end ++ world.setBlock(blockposition, InfestedBlock.infestedStateByHost(iblockdata), 3); + this.mob.spawnAnim(); + this.mob.discard(); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Skeleton.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Skeleton.java.patch new file mode 100644 index 0000000000..c9a8225075 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Skeleton.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/monster/Skeleton.java ++++ b/net/minecraft/world/entity/monster/Skeleton.java +@@ -95,7 +90,7 @@ + } + + protected void doFreezeConversion() { +- this.convertTo(EntityType.STRAY, true); ++ this.convertTo(EntityType.STRAY, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.FROZEN, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.FROZEN); // CraftBukkit - add spawn and transform reasons + if (!this.isSilent()) { + this.level().levelEvent((Player) null, 1048, this.blockPosition(), 0); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Slime.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Slime.java.patch new file mode 100644 index 0000000000..ffdbc9be15 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Slime.java.patch @@ -0,0 +1,67 @@ +--- a/net/minecraft/world/entity/monster/Slime.java ++++ b/net/minecraft/world/entity/monster/Slime.java +@@ -44,7 +44,13 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Slime extends Mob implements Enemy { ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTransformEvent; ++import org.bukkit.event.entity.SlimeSplitEvent; ++// CraftBukkit end + + private static final EntityDataAccessor ID_SIZE = SynchedEntityData.defineId(Slime.class, EntityDataSerializers.INT); + public static final int MIN_SIZE = 1; +@@ -217,6 +214,19 @@ + int j = i / 2; + int k = 2 + this.random.nextInt(3); + ++ // CraftBukkit start ++ SlimeSplitEvent event = new SlimeSplitEvent((org.bukkit.entity.Slime) this.getBukkitEntity(), k); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled() && event.getCount() > 0) { ++ k = event.getCount(); ++ } else { ++ super.remove(reason); ++ return; ++ } ++ List slimes = new ArrayList<>(j); ++ // CraftBukkit end ++ + for (int l = 0; l < k; ++l) { + float f1 = ((float) (l % 2) - 0.5F) * f; + float f2 = ((float) (l / 2) - 0.5F) * f; +@@ -227,14 +237,23 @@ + slime.setPersistenceRequired(); + } + +- slime.setCustomName(component); +- slime.setNoAi(flag); +- slime.setInvulnerable(this.isInvulnerable()); +- slime.setSize(j, true); +- slime.moveTo(this.getX() + (double) f1, this.getY() + 0.5D, this.getZ() + (double) f2, this.random.nextFloat() * 360.0F, 0.0F); +- this.level().addFreshEntity(slime); ++ entityslime.setCustomName(ichatbasecomponent); ++ entityslime.setNoAi(flag); ++ entityslime.setInvulnerable(this.isInvulnerable()); ++ entityslime.setSize(j, true); ++ entityslime.moveTo(this.getX() + (double) f1, this.getY() + 0.5D, this.getZ() + (double) f2, this.random.nextFloat() * 360.0F, 0.0F); ++ slimes.add(entityslime); // CraftBukkit + } + } ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, slimes, EntityTransformEvent.TransformReason.SPLIT).isCancelled()) { ++ super.remove(reason); ++ return; ++ } ++ for (LivingEntity living : slimes) { ++ this.level().addFreshEntity(living, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SLIME_SPLIT); // CraftBukkit - SpawnReason ++ } ++ // CraftBukkit end + } + + super.remove(entity_removalreason); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/SpellcasterIllager.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/SpellcasterIllager.java.patch new file mode 100644 index 0000000000..f1eae8779a --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/SpellcasterIllager.java.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/world/entity/monster/SpellcasterIllager.java ++++ b/net/minecraft/world/entity/monster/SpellcasterIllager.java +@@ -15,6 +15,9 @@ + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.ai.goal.Goal; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public abstract class SpellcasterIllager extends AbstractIllager { + +@@ -165,6 +158,11 @@ + public void tick() { + --this.attackWarmupDelay; + if (this.attackWarmupDelay == 0) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handleEntitySpellCastEvent(SpellcasterIllager.this, this.getSpell())) { ++ return; ++ } ++ // CraftBukkit end + this.performSpellCasting(); + SpellcasterIllager.this.playSound(SpellcasterIllager.this.getCastingSoundEvent(), 1.0F, 1.0F); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Spider.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Spider.java.patch new file mode 100644 index 0000000000..b3af84dbd5 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Spider.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/entity/monster/Spider.java ++++ b/net/minecraft/world/entity/monster/Spider.java +@@ -195,8 +181,8 @@ + Spider.SpiderEffectsGroupData spider_spidereffectsgroupdata = (Spider.SpiderEffectsGroupData) object; + MobEffect mobeffect = spider_spidereffectsgroupdata.effect; + +- if (mobeffect != null) { +- this.addEffect(new MobEffectInstance(mobeffect, -1)); ++ if (mobeffectlist != null) { ++ this.addEffect(new MobEffectInstance(mobeffectlist, -1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.SPIDER_SPAWN); // CraftBukkit + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Strider.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Strider.java.patch new file mode 100644 index 0000000000..fb4fab2cf1 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Strider.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/entity/monster/Strider.java ++++ b/net/minecraft/world/entity/monster/Strider.java +@@ -372,7 +351,14 @@ + + boolean flag2 = flag1; + +- this.setSuffocating(!flag || flag2); ++ // CraftBukkit start ++ boolean suffocating = !flag || flag2; ++ if (suffocating ^ this.isSuffocating()) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callStriderTemperatureChangeEvent(this, suffocating)) { ++ this.setSuffocating(suffocating); ++ } ++ } ++ // CraftBukkit end + } + + super.tick(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Vex.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Vex.java.patch new file mode 100644 index 0000000000..b2dc532475 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Vex.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/monster/Vex.java ++++ b/net/minecraft/world/entity/monster/Vex.java +@@ -434,7 +404,7 @@ + @Override + @Override + public void start() { +- Vex.this.setTarget(Vex.this.owner.getTarget()); ++ Vex.this.setTarget(Vex.this.owner.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.OWNER_ATTACKED_TARGET, true); // CraftBukkit + super.start(); + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Witch.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Witch.java.patch new file mode 100644 index 0000000000..433ba0519b --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Witch.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/monster/Witch.java ++++ b/net/minecraft/world/entity/monster/Witch.java +@@ -140,7 +134,7 @@ + while (iterator.hasNext()) { + MobEffectInstance mobeffectinstance = (MobEffectInstance) iterator.next(); + +- this.addEffect(new MobEffectInstance(mobeffectinstance)); ++ this.addEffect(new MobEffectInstance(mobeffect), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/WitherSkeleton.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/WitherSkeleton.java.patch new file mode 100644 index 0000000000..96a88f3467 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/WitherSkeleton.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/monster/WitherSkeleton.java ++++ b/net/minecraft/world/entity/monster/WitherSkeleton.java +@@ -123,7 +111,7 @@ + return false; + } else { + if (entity instanceof LivingEntity) { +- ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.WITHER, 200), this); ++ ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.WITHER, 200), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + + return true; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Zombie.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Zombie.java.patch new file mode 100644 index 0000000000..e6851623ef --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/Zombie.java.patch @@ -0,0 +1,186 @@ +--- a/net/minecraft/world/entity/monster/Zombie.java ++++ b/net/minecraft/world/entity/monster/Zombie.java +@@ -66,6 +54,25 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; + import org.joml.Vector3f; ++import net.minecraft.core.BlockPos; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.Tag; ++import net.minecraft.network.syncher.EntityDataAccessor; ++import net.minecraft.network.syncher.EntityDataSerializers; ++import net.minecraft.network.syncher.SynchedEntityData; ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundEvents; ++import net.minecraft.sounds.SoundSource; ++import net.minecraft.tags.FluidTags; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++// CraftBukkit end + + public class Zombie extends Monster { + +@@ -86,7 +93,8 @@ + private final BreakDoorGoal breakDoorGoal; + private boolean canBreakDoors; + private int inWaterTime; +- private int conversionTime; ++ public int conversionTime; ++ private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field + + public Zombie(EntityType entitytype, Level level) { + super(entitytype, level); +@@ -210,7 +211,10 @@ + public void tick() { + if (!this.level().isClientSide && this.isAlive() && !this.isNoAi()) { + if (this.isUnderWaterConverting()) { +- --this.conversionTime; ++ // CraftBukkit start - Use wall time instead of ticks for conversion ++ int elapsedTicks = MinecraftServer.currentTick - this.lastTick; ++ this.conversionTime -= elapsedTicks; ++ // CraftBukkit end + if (this.conversionTime < 0) { + this.doUnderWaterConversion(); + } +@@ -227,6 +231,7 @@ + } + + super.tick(); ++ this.lastTick = MinecraftServer.currentTick; // CraftBukkit + } + + @Override +@@ -259,8 +263,9 @@ + super.aiStep(); + } + +- private void startUnderWaterConversion(int i) { +- this.conversionTime = i; ++ public void startUnderWaterConversion(int conversionTime) { ++ this.lastTick = MinecraftServer.currentTick; // CraftBukkit ++ this.conversionTime = conversionTime; + this.getEntityData().set(Zombie.DATA_DROWNED_CONVERSION_ID, true); + } + +@@ -275,9 +280,13 @@ + protected void convertToZombieType(EntityType entitytype) { + Zombie zombie = (Zombie) this.convertTo(entitytype, true); + +- if (zombie != null) { +- zombie.handleAttributes(zombie.level().getCurrentDifficultyAt(zombie.blockPosition()).getSpecialMultiplier()); +- zombie.setCanBreakDoors(zombie.supportsBreakDoorGoal() && this.canBreakDoors()); ++ if (entityzombie != null) { ++ entityzombie.handleAttributes(entityzombie.level().getCurrentDifficultyAt(entityzombie.blockPosition()).getSpecialMultiplier()); ++ entityzombie.setCanBreakDoors(entityzombie.supportsBreakDoorGoal() && this.canBreakDoors()); ++ // CraftBukkit start - SPIGOT-5208: End conversion to stop event spam ++ } else { ++ ((org.bukkit.entity.Zombie) getBukkitEntity()).setConversionTime(-1); ++ // CraftBukkit end + } + + } +@@ -315,12 +323,12 @@ + EntityType entitytype = zombie.getType(); + SpawnPlacements.Type spawnplacements_type = SpawnPlacements.getPlacementType(entitytype); + +- if (NaturalSpawner.isSpawnPositionOk(spawnplacements_type, this.level(), blockpos, entitytype) && SpawnPlacements.checkSpawnRules(entitytype, serverlevel, MobSpawnType.REINFORCEMENT, blockpos, this.level().random)) { +- zombie.setPos((double) i1, (double) j1, (double) k1); +- if (!this.level().hasNearbyAlivePlayer((double) i1, (double) j1, (double) k1, 7.0D) && this.level().isUnobstructed(zombie) && this.level().noCollision((Entity) zombie) && !this.level().containsAnyLiquid(zombie.getBoundingBox())) { +- zombie.setTarget(livingentity); +- zombie.finalizeSpawn(serverlevel, this.level().getCurrentDifficultyAt(zombie.blockPosition()), MobSpawnType.REINFORCEMENT, (SpawnGroupData) null, (CompoundTag) null); +- serverlevel.addFreshEntityWithPassengers(zombie); ++ if (NaturalSpawner.isSpawnPositionOk(entitypositiontypes_surface, this.level(), blockposition, entitytypes) && SpawnPlacements.checkSpawnRules(entitytypes, worldserver, EnumMobSpawn.REINFORCEMENT, blockposition, this.level().random)) { ++ entityzombie.setPos((double) i1, (double) j1, (double) k1); ++ if (!this.level().hasNearbyAlivePlayer((double) i1, (double) j1, (double) k1, 7.0D) && this.level().isUnobstructed(entityzombie) && this.level().noCollision((Entity) entityzombie) && !this.level().containsAnyLiquid(entityzombie.getBoundingBox())) { ++ entityzombie.setTarget(entityliving, EntityTargetEvent.TargetReason.REINFORCEMENT_TARGET, true); // CraftBukkit ++ entityzombie.finalizeSpawn(worldserver, this.level().getCurrentDifficultyAt(entityzombie.blockPosition()), EnumMobSpawn.REINFORCEMENT, (GroupDataEntity) null, (CompoundTag) null); ++ worldserver.addFreshEntityWithPassengers(entityzombie, CreatureSpawnEvent.SpawnReason.REINFORCEMENTS); // CraftBukkit + this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).addPermanentModifier(new AttributeModifier("Zombie reinforcement caller charge", -0.05000000074505806D, AttributeModifier.Operation.ADDITION)); + zombie.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).addPermanentModifier(new AttributeModifier("Zombie reinforcement callee charge", -0.05000000074505806D, AttributeModifier.Operation.ADDITION)); + break; +@@ -342,7 +349,14 @@ + float f = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty(); + + if (this.getMainHandItem().isEmpty() && this.isOnFire() && this.random.nextFloat() < f * 0.3F) { +- entity.setSecondsOnFire(2 * (int) f); ++ // CraftBukkit start ++ EntityCombustByEntityEvent event = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), 2 * (int) f); // PAIL: fixme ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ entity.setSecondsOnFire(event.getDuration(), false); ++ } ++ // CraftBukkit end + } + } + +@@ -433,24 +438,35 @@ + if (serverlevel.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { + return flag; + } ++ // CraftBukkit start ++ flag = zombifyVillager(level, entityvillager, this.blockPosition(), this.isSilent(), CreatureSpawnEvent.SpawnReason.INFECTION) == null; ++ } + + ZombieVillager zombievillager = (ZombieVillager) villager.convertTo(EntityType.ZOMBIE_VILLAGER, false); + +- if (zombievillager != null) { +- zombievillager.finalizeSpawn(serverlevel, serverlevel.getCurrentDifficultyAt(zombievillager.blockPosition()), MobSpawnType.CONVERSION, new Zombie.ZombieGroupData(false, true), (CompoundTag) null); +- zombievillager.setVillagerData(villager.getVillagerData()); +- zombievillager.setGossips((Tag) villager.getGossips().store(NbtOps.INSTANCE)); +- zombievillager.setTradeOffers(villager.getOffers().createTag()); +- zombievillager.setVillagerXp(villager.getVillagerXp()); +- if (!this.isSilent()) { +- serverlevel.levelEvent((Player) null, 1026, this.blockPosition(), 0); ++ public static ZombieVillager zombifyVillager(ServerLevel worldserver, Villager entityvillager, net.minecraft.core.BlockPos blockPosition, boolean silent, CreatureSpawnEvent.SpawnReason spawnReason) { ++ { ++ ZombieVillager entityzombievillager = (ZombieVillager) entityvillager.convertTo(EntityType.ZOMBIE_VILLAGER, false, EntityTransformEvent.TransformReason.INFECTION, spawnReason); ++ // CraftBukkit end ++ ++ if (entityzombievillager != null) { ++ entityzombievillager.finalizeSpawn(worldserver, worldserver.getCurrentDifficultyAt(entityzombievillager.blockPosition()), EnumMobSpawn.CONVERSION, new Zombie.ZombieGroupData(false, true), (CompoundTag) null); ++ entityzombievillager.setVillagerData(entityvillager.getVillagerData()); ++ entityzombievillager.setGossips((Tag) entityvillager.getGossips().store(NbtOps.INSTANCE)); ++ entityzombievillager.setTradeOffers(entityvillager.getOffers().createTag()); ++ entityzombievillager.setVillagerXp(entityvillager.getVillagerXp()); ++ // CraftBukkit start ++ if (!silent) { ++ worldserver.levelEvent((Player) null, 1026, blockPosition, 0); + } + + flag = false; + } + } + +- return flag; ++ return entityzombievillager; ++ } ++ // CraftBukkit end + } + + @Override +@@ -502,12 +514,12 @@ + } else if ((double) randomsource.nextFloat() < 0.05D) { + Chicken chicken1 = (Chicken) EntityType.CHICKEN.create(this.level()); + +- if (chicken1 != null) { +- chicken1.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); +- chicken1.finalizeSpawn(serverlevelaccessor, difficultyinstance, MobSpawnType.JOCKEY, (SpawnGroupData) null, (CompoundTag) null); +- chicken1.setChickenJockey(true); +- this.startRiding(chicken1); +- serverlevelaccessor.addFreshEntity(chicken1); ++ if (entitychicken1 != null) { ++ entitychicken1.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); ++ entitychicken1.finalizeSpawn(level, difficulty, EnumMobSpawn.JOCKEY, (GroupDataEntity) null, (CompoundTag) null); ++ entitychicken1.setChickenJockey(true); ++ this.startRiding(entitychicken1); ++ level.addFreshEntity(entitychicken1, CreatureSpawnEvent.SpawnReason.MOUNT); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/ZombieVillager.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/ZombieVillager.java.patch new file mode 100644 index 0000000000..41eb20eaef --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/ZombieVillager.java.patch @@ -0,0 +1,99 @@ +--- a/net/minecraft/world/entity/monster/ZombieVillager.java ++++ b/net/minecraft/world/entity/monster/ZombieVillager.java +@@ -50,6 +46,16 @@ + import org.joml.Vector3f; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundEvents; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++// CraftBukkit end ++ + public class ZombieVillager extends Zombie implements VillagerDataHolder { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -67,6 +73,7 @@ + @Nullable + private CompoundTag tradeOffers; + private int villagerXp; ++ private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field + + public ZombieVillager(EntityType entitytype, Level level) { + super(entitytype, level); +@@ -145,6 +148,10 @@ + public void tick() { + if (!this.level().isClientSide && this.isAlive() && this.isConverting()) { + int i = this.getConversionProgress(); ++ // CraftBukkit start - Use wall time instead of ticks for villager conversion ++ int elapsedTicks = MinecraftServer.currentTick - this.lastTick; ++ i *= elapsedTicks; ++ // CraftBukkit end + + this.villagerConversionTime -= i; + if (this.villagerConversionTime <= 0) { +@@ -153,6 +160,7 @@ + } + + super.tick(); ++ this.lastTick = MinecraftServer.currentTick; // CraftBukkit + } + + @Override +@@ -199,8 +204,10 @@ + this.conversionStarter = uuid; + this.villagerConversionTime = i; + this.getEntityData().set(ZombieVillager.DATA_CONVERTING_ID, true); +- this.removeEffect(MobEffects.WEAKNESS); +- this.addEffect(new MobEffectInstance(MobEffects.DAMAGE_BOOST, i, Math.min(this.level().getDifficulty().getId() - 1, 0))); ++ // CraftBukkit start ++ this.removeEffect(MobEffects.WEAKNESS, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); ++ this.addEffect(new MobEffectInstance(MobEffects.DAMAGE_BOOST, villagerConversionTime, Math.min(this.level().getDifficulty().getId() - 1, 0)), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); ++ // CraftBukkit end + this.level().broadcastEntityEvent(this, (byte) 16); + } + +@@ -217,10 +223,16 @@ + } + } + +- private void finishConversion(ServerLevel serverlevel) { +- Villager villager = (Villager) this.convertTo(EntityType.VILLAGER, false); +- EquipmentSlot[] aequipmentslot = EquipmentSlot.values(); +- int i = aequipmentslot.length; ++ private void finishConversion(ServerLevel serverLevel) { ++ // CraftBukkit start ++ Villager entityvillager = (Villager) this.convertTo(EntityType.VILLAGER, false, EntityTransformEvent.TransformReason.CURED, CreatureSpawnEvent.SpawnReason.CURED); ++ if (entityvillager == null) { ++ ((org.bukkit.entity.ZombieVillager) getBukkitEntity()).setConversionTime(-1); // SPIGOT-5208: End conversion to stop event spam ++ return; ++ } ++ // CraftBukkit end ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ int i = aenumitemslot.length; + + for (int j = 0; j < i; ++j) { + EquipmentSlot equipmentslot = aequipmentslot[j]; +@@ -233,7 +245,9 @@ + double d0 = (double) this.getEquipmentDropChance(equipmentslot); + + if (d0 > 1.0D) { ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation(itemstack); ++ this.forceDrops = false; // CraftBukkit + } + } + } +@@ -260,7 +274,7 @@ + } + } + +- villager.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0)); ++ entityvillager.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); // CraftBukkit + if (!this.isSilent()) { + serverlevel.levelEvent((Player) null, 1027, this.blockPosition(), 0); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/ZombifiedPiglin.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/ZombifiedPiglin.java.patch new file mode 100644 index 0000000000..92f5c3d734 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/ZombifiedPiglin.java.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/entity/monster/ZombifiedPiglin.java ++++ b/net/minecraft/world/entity/monster/ZombifiedPiglin.java +@@ -148,14 +143,14 @@ + double d0 = this.getAttributeValue(Attributes.FOLLOW_RANGE); + AABB aabb = AABB.unitCubeFromLowerCorner(this.position()).inflate(d0, 10.0D, d0); + +- this.level().getEntitiesOfClass(ZombifiedPiglin.class, aabb, EntitySelector.NO_SPECTATORS).stream().filter((zombifiedpiglin) -> { +- return zombifiedpiglin != this; +- }).filter((zombifiedpiglin) -> { +- return zombifiedpiglin.getTarget() == null; +- }).filter((zombifiedpiglin) -> { +- return !zombifiedpiglin.isAlliedTo((Entity) this.getTarget()); +- }).forEach((zombifiedpiglin) -> { +- zombifiedpiglin.setTarget(this.getTarget()); ++ this.level().getEntitiesOfClass(ZombifiedPiglin.class, axisalignedbb, EntitySelector.NO_SPECTATORS).stream().filter((entitypigzombie) -> { ++ return entitypigzombie != this; ++ }).filter((entitypigzombie) -> { ++ return entitypigzombie.getTarget() == null; ++ }).filter((entitypigzombie) -> { ++ return !entitypigzombie.isAlliedTo((Entity) this.getTarget()); ++ }).forEach((entitypigzombie) -> { ++ entitypigzombie.setTarget(this.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_NEARBY_ENTITY, true); // CraftBukkit + }); + } + +@@ -164,9 +159,8 @@ + } + + @Override +- @Override +- public void setTarget(@Nullable LivingEntity livingentity) { +- if (this.getTarget() == null && livingentity != null) { ++ public boolean setTarget(@Nullable LivingEntity entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) { // CraftBukkit - signature ++ if (this.getTarget() == null && entityliving != null) { + this.playFirstAngerSoundIn = ZombifiedPiglin.FIRST_ANGER_SOUND_DELAY.sample(this.random); + this.ticksUntilNextAlert = ZombifiedPiglin.ALERT_INTERVAL.sample(this.random); + } +@@ -175,13 +169,22 @@ + this.setLastHurtByPlayer((Player) livingentity); + } + +- super.setTarget(livingentity); ++ return super.setTarget(entityliving, reason, fireEvent); // CraftBukkit + } + + @Override + @Override + public void startPersistentAngerTimer() { +- this.setRemainingPersistentAngerTime(ZombifiedPiglin.PERSISTENT_ANGER_TIME.sample(this.random)); ++ // CraftBukkit start ++ Entity entity = ((ServerLevel) this.level()).getEntity(getPersistentAngerTarget()); ++ org.bukkit.event.entity.PigZombieAngerEvent event = new org.bukkit.event.entity.PigZombieAngerEvent((org.bukkit.entity.PigZombie) this.getBukkitEntity(), (entity == null) ? null : entity.getBukkitEntity(), ZombifiedPiglin.PERSISTENT_ANGER_TIME.sample(this.random)); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ this.setPersistentAngerTarget(null); ++ return; ++ } ++ this.setRemainingPersistentAngerTime(event.getNewAnger()); ++ // CraftBukkit end + } + + public static boolean checkZombifiedPiglinSpawnRules(EntityType entitytype, LevelAccessor levelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java.patch new file mode 100644 index 0000000000..6642497f69 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java ++++ b/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java +@@ -121,8 +114,8 @@ + return !this.level().dimensionType().piglinSafe() && !this.isImmuneToZombification() && !this.isNoAi(); + } + +- protected void finishConversion(ServerLevel serverlevel) { +- ZombifiedPiglin zombifiedpiglin = (ZombifiedPiglin) this.convertTo(EntityType.ZOMBIFIED_PIGLIN, true); ++ protected void finishConversion(ServerLevel serverLevel) { ++ ZombifiedPiglin entitypigzombie = (ZombifiedPiglin) this.convertTo(EntityType.ZOMBIFIED_PIGLIN, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.PIGLIN_ZOMBIFIED, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.PIGLIN_ZOMBIFIED); // CraftBukkit - add spawn and transform reasons + + if (zombifiedpiglin != null) { + zombifiedpiglin.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0)); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/piglin/Piglin.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/piglin/Piglin.java.patch new file mode 100644 index 0000000000..012d5e6e7d --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/piglin/Piglin.java.patch @@ -0,0 +1,117 @@ +--- a/net/minecraft/world/entity/monster/piglin/Piglin.java ++++ b/net/minecraft/world/entity/monster/piglin/Piglin.java +@@ -55,6 +47,26 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; + ++// CraftBukkit start ++import java.util.stream.Collectors; ++import java.util.HashSet; ++import java.util.Set; ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.registries.BuiltInRegistries; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; ++import net.minecraft.nbt.StringTag; ++import net.minecraft.nbt.Tag; ++import net.minecraft.network.syncher.EntityDataAccessor; ++import net.minecraft.network.syncher.EntityDataSerializers; ++import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundEvents; ++import net.minecraft.world.item.Item; ++// CraftBukkit end ++ + public class Piglin extends AbstractPiglin implements CrossbowAttackMob, InventoryCarrier { + + private static final EntityDataAccessor DATA_BABY_ID = SynchedEntityData.defineId(Piglin.class, EntityDataSerializers.BOOLEAN); +@@ -75,6 +87,10 @@ + private boolean cannotHunt; + protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.NEAREST_ITEMS, SensorType.HURT_BY, SensorType.PIGLIN_SPECIFIC_SENSOR); + protected static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.LOOK_TARGET, MemoryModuleType.DOORS_TO_CLOSE, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ADULT_PIGLINS, MemoryModuleType.NEARBY_ADULT_PIGLINS, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, new MemoryModuleType[]{MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.ATTACK_TARGET, MemoryModuleType.ATTACK_COOLING_DOWN, MemoryModuleType.INTERACTION_TARGET, MemoryModuleType.PATH, MemoryModuleType.ANGRY_AT, MemoryModuleType.UNIVERSAL_ANGER, MemoryModuleType.AVOID_TARGET, MemoryModuleType.ADMIRING_ITEM, MemoryModuleType.TIME_TRYING_TO_REACH_ADMIRE_ITEM, MemoryModuleType.ADMIRING_DISABLED, MemoryModuleType.DISABLE_WALK_TO_ADMIRE_ITEM, MemoryModuleType.CELEBRATE_LOCATION, MemoryModuleType.DANCING, MemoryModuleType.HUNTED_RECENTLY, MemoryModuleType.NEAREST_VISIBLE_BABY_HOGLIN, MemoryModuleType.NEAREST_VISIBLE_NEMESIS, MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED, MemoryModuleType.RIDE_TARGET, MemoryModuleType.VISIBLE_ADULT_PIGLIN_COUNT, MemoryModuleType.VISIBLE_ADULT_HOGLIN_COUNT, MemoryModuleType.NEAREST_VISIBLE_HUNTABLE_HOGLIN, MemoryModuleType.NEAREST_TARGETABLE_PLAYER_NOT_WEARING_GOLD, MemoryModuleType.NEAREST_PLAYER_HOLDING_WANTED_ITEM, MemoryModuleType.ATE_RECENTLY, MemoryModuleType.NEAREST_REPELLENT}); ++ // CraftBukkit start - Custom bartering and interest list ++ public Set allowedBarterItems = new HashSet<>(); ++ public Set interestItems = new HashSet<>(); ++ // CraftBukkit end + + public Piglin(EntityType entitytype, Level level) { + super(entitytype, level); +@@ -93,16 +108,27 @@ + compoundtag.putBoolean("CannotHunt", true); + } + +- this.writeInventoryToTag(compoundtag); ++ this.writeInventoryToTag(compound); ++ // CraftBukkit start ++ ListTag barterList = new ListTag(); ++ allowedBarterItems.stream().map(BuiltInRegistries.ITEM::getKey).map(ResourceLocation::toString).map(StringTag::valueOf).forEach(barterList::add); ++ compound.put("Bukkit.BarterList", barterList); ++ ListTag interestList = new ListTag(); ++ interestItems.stream().map(BuiltInRegistries.ITEM::getKey).map(ResourceLocation::toString).map(StringTag::valueOf).forEach(interestList::add); ++ compound.put("Bukkit.InterestList", interestList); ++ // CraftBukkit end + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setBaby(compoundtag.getBoolean("IsBaby")); +- this.setCannotHunt(compoundtag.getBoolean("CannotHunt")); +- this.readInventoryFromTag(compoundtag); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setBaby(compound.getBoolean("IsBaby")); ++ this.setCannotHunt(compound.getBoolean("CannotHunt")); ++ this.readInventoryFromTag(compound); ++ // CraftBukkit start ++ this.allowedBarterItems = compound.getList("Bukkit.BarterList", 8).stream().map(Tag::getAsString).map(ResourceLocation::tryParse).map(BuiltInRegistries.ITEM::get).collect(Collectors.toCollection(HashSet::new)); ++ this.interestItems = compound.getList("Bukkit.InterestList", 8).stream().map(Tag::getAsString).map(ResourceLocation::tryParse).map(BuiltInRegistries.ITEM::get).collect(Collectors.toCollection(HashSet::new)); ++ // CraftBukkit end + } + + @VisibleForDebug +@@ -233,7 +248,7 @@ + @Override + @Override + public Brain getBrain() { +- return super.getBrain(); ++ return (Brain) super.getBrain(); // CraftBukkit - Decompile error + } + + @Override +@@ -387,9 +387,9 @@ + this.setItemSlotAndDropWhenKilled(EquipmentSlot.MAINHAND, itemstack); + } + +- protected void holdInOffHand(ItemStack itemstack) { +- if (itemstack.is(PiglinAi.BARTERING_ITEM)) { +- this.setItemSlot(EquipmentSlot.OFFHAND, itemstack); ++ protected void holdInOffHand(ItemStack stack) { ++ if (stack.is(PiglinAi.BARTERING_ITEM) || allowedBarterItems.contains(stack.getItem())) { // CraftBukkit - Changes to accept custom payment items ++ this.setItemSlot(EquipmentSlot.OFFHAND, stack); + this.setGuaranteedDrop(EquipmentSlot.OFFHAND); + } else { + this.setItemSlotAndDropWhenKilled(EquipmentSlot.OFFHAND, itemstack); +@@ -416,8 +414,8 @@ + if (EnchantmentHelper.hasBindingCurse(itemstack1)) { + return false; + } else { +- boolean flag = PiglinAi.isLovedItem(itemstack) || itemstack.is(Items.CROSSBOW); +- boolean flag1 = PiglinAi.isLovedItem(itemstack1) || itemstack1.is(Items.CROSSBOW); ++ boolean flag = PiglinAi.isLovedItem(candidate, this) || candidate.is(Items.CROSSBOW); // CraftBukkit ++ boolean flag1 = PiglinAi.isLovedItem(existing, this) || existing.is(Items.CROSSBOW); // CraftBukkit + + return flag && !flag1 ? true : (!flag && flag1 ? false : (this.isAdult() && !itemstack.is(Items.CROSSBOW) && itemstack1.is(Items.CROSSBOW) ? false : super.canReplaceCurrentItem(itemstack, itemstack1))); + } +@@ -449,7 +444,7 @@ + @Override + @Override + protected SoundEvent getAmbientSound() { +- return this.level().isClientSide ? null : (SoundEvent) PiglinAi.getSoundForCurrentActivity(this).orElse((Object) null); ++ return this.level().isClientSide ? null : (SoundEvent) PiglinAi.getSoundForCurrentActivity(this).orElse(null); // CraftBukkit - Decompile error + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/piglin/PiglinAi.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/piglin/PiglinAi.java.patch new file mode 100644 index 0000000000..8fb400c5fa --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/piglin/PiglinAi.java.patch @@ -0,0 +1,134 @@ +--- a/net/minecraft/world/entity/monster/piglin/PiglinAi.java ++++ b/net/minecraft/world/entity/monster/piglin/PiglinAi.java +@@ -73,6 +73,12 @@ + import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; + import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import java.util.stream.Collectors; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.entity.PiglinBarterEvent; ++// CraftBukkit end + + public class PiglinAi { + +@@ -233,23 +240,28 @@ + stopWalking(piglin); + ItemStack itemstack; + +- if (itementity.getItem().is(Items.GOLD_NUGGET)) { +- piglin.take(itementity, itementity.getItem().getCount()); +- itemstack = itementity.getItem(); +- itementity.discard(); ++ // CraftBukkit start ++ if (itemEntity.getItem().is(Items.GOLD_NUGGET) && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(piglin, itemEntity, 0, false).isCancelled()) { ++ piglin.take(itemEntity, itemEntity.getItem().getCount()); ++ itemstack = itemEntity.getItem(); ++ itemEntity.discard(); ++ } else if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(piglin, itemEntity, itemEntity.getItem().getCount() - 1, false).isCancelled()) { ++ piglin.take(itemEntity, 1); ++ itemstack = removeOneItemFromItemEntity(itemEntity); + } else { + piglin.take(itementity, 1); + itemstack = removeOneItemFromItemEntity(itementity); + } ++ // CraftBukkit end + +- if (isLovedItem(itemstack)) { ++ if (isLovedItem(itemstack, piglin)) { // CraftBukkit - Changes to allow for custom payment in bartering + piglin.getBrain().eraseMemory(MemoryModuleType.TIME_TRYING_TO_REACH_ADMIRE_ITEM); + holdInOffhand(piglin, itemstack); + admireGoldItem(piglin); + } else if (isFood(itemstack) && !hasEatenRecently(piglin)) { + eat(piglin); + } else { +- boolean flag = !piglin.equipItemIfPossible(itemstack).equals(ItemStack.EMPTY); ++ boolean flag = !piglin.equipItemIfPossible(itemstack, itemEntity).equals(ItemStack.EMPTY); // CraftBukkit + + if (!flag) { + putInInventory(piglin, itemstack); +@@ -285,9 +296,14 @@ + boolean flag1; + + if (piglin.isAdult()) { +- flag1 = isBarterCurrency(itemstack); +- if (flag && flag1) { +- throwItems(piglin, getBarterResponseItems(piglin)); ++ flag1 = isBarterCurrency(itemstack, piglin); // CraftBukkit - Changes to allow custom payment for bartering ++ if (shouldBarter && flag1) { ++ // CraftBukkit start ++ PiglinBarterEvent event = CraftEventFactory.callPiglinBarterEvent(piglin, getBarterResponseItems(piglin), itemstack); ++ if (!event.isCancelled()) { ++ throwItems(piglin, event.getOutcome().stream().map(CraftItemStack::asNMSCopy).collect(Collectors.toList())); ++ } ++ // CraftBukkit end + } else if (!flag1) { + boolean flag2 = !piglin.equipItemIfPossible(itemstack).isEmpty(); + +@@ -300,7 +316,7 @@ + if (!flag1) { + ItemStack itemstack1 = piglin.getMainHandItem(); + +- if (isLovedItem(itemstack1)) { ++ if (isLovedItem(itemstack1, piglin)) { // CraftBukkit - Changes to allow for custom payment in bartering + putInInventory(piglin, itemstack1); + } else { + throwItems(piglin, Collections.singletonList(itemstack1)); +@@ -377,7 +393,7 @@ + return false; + } else if (isAdmiringDisabled(piglin) && piglin.getBrain().hasMemoryValue(MemoryModuleType.ATTACK_TARGET)) { + return false; +- } else if (isBarterCurrency(itemstack)) { ++ } else if (isBarterCurrency(stack, piglin)) { // CraftBukkit + return isNotHoldingLovedItemInOffHand(piglin); + } else { + boolean flag = piglin.canAddToInventory(itemstack); +@@ -386,9 +402,11 @@ + } + } + +- protected static boolean isLovedItem(ItemStack itemstack) { +- return itemstack.is(ItemTags.PIGLIN_LOVED); ++ // CraftBukkit start - Added method to allow checking for custom payment items ++ protected static boolean isLovedItem(ItemStack itemstack, Piglin piglin) { ++ return isLovedItem(itemstack) || (piglin.interestItems.contains(itemstack.getItem()) || piglin.allowedBarterItems.contains(itemstack.getItem())); + } ++ // CraftBukkit end + + private static boolean wantsToStopRiding(Piglin piglin, Entity entity) { + if (!(entity instanceof Mob)) { +@@ -480,8 +502,8 @@ + } + } + +- protected static boolean canAdmire(Piglin piglin, ItemStack itemstack) { +- return !isAdmiringDisabled(piglin) && !isAdmiringItem(piglin) && piglin.isAdult() && isBarterCurrency(itemstack); ++ protected static boolean canAdmire(Piglin piglin, ItemStack stack) { ++ return !isAdmiringDisabled(piglin) && !isAdmiringItem(piglin) && piglin.isAdult() && isBarterCurrency(stack, piglin); // CraftBukkit + } + + protected static void wasHurtBy(Piglin piglin, LivingEntity livingentity) { +@@ -738,9 +760,11 @@ + return piglin.getBrain().hasMemoryValue(MemoryModuleType.ADMIRING_ITEM); + } + +- private static boolean isBarterCurrency(ItemStack itemstack) { +- return itemstack.is(PiglinAi.BARTERING_ITEM); ++ // CraftBukkit start - Changes to allow custom payment for bartering ++ private static boolean isBarterCurrency(ItemStack itemstack, Piglin piglin) { ++ return isBarterCurrency(itemstack) || piglin.allowedBarterItems.contains(itemstack.getItem()); + } ++ // CraftBukkit end + + private static boolean isFood(ItemStack itemstack) { + return itemstack.is(ItemTags.PIGLIN_FOOD); +@@ -775,7 +803,7 @@ + } + + private static boolean isNotHoldingLovedItemInOffHand(Piglin piglin) { +- return piglin.getOffhandItem().isEmpty() || !isLovedItem(piglin.getOffhandItem()); ++ return piglin.getOffhandItem().isEmpty() || !isLovedItem(piglin.getOffhandItem(), piglin); // CraftBukkit - Changes to allow custom payment for bartering + } + + public static boolean isZombified(EntityType entitytype) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/warden/Warden.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/warden/Warden.java.patch new file mode 100644 index 0000000000..d1278d065d --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/monster/warden/Warden.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/monster/warden/Warden.java ++++ b/net/minecraft/world/entity/monster/warden/Warden.java +@@ -439,7 +414,7 @@ + public static void applyDarknessAround(ServerLevel serverlevel, Vec3 vec3, @Nullable Entity entity, int i) { + MobEffectInstance mobeffectinstance = new MobEffectInstance(MobEffects.DARKNESS, 260, 0, false, false); + +- MobEffectUtil.addEffectToPlayersAround(serverlevel, entity, vec3, (double) i, mobeffectinstance, 200); ++ MobEffectUtil.addEffectToPlayersAround(level, source, pos, radius, mobeffect, 200, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.WARDEN); // CraftBukkit - Add EntityPotionEffectEvent.Cause + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/npc/AbstractVillager.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/npc/AbstractVillager.java.patch new file mode 100644 index 0000000000..cef3364ec8 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/npc/AbstractVillager.java.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/entity/npc/AbstractVillager.java ++++ b/net/minecraft/world/entity/npc/AbstractVillager.java +@@ -34,9 +34,23 @@ + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.inventory.CraftMerchant; ++import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; ++import org.bukkit.event.entity.VillagerAcquireTradeEvent; ++// CraftBukkit end + + public abstract class AbstractVillager extends AgeableMob implements InventoryCarrier, Npc, Merchant { + ++ // CraftBukkit start ++ private CraftMerchant craftMerchant; ++ ++ @Override ++ public CraftMerchant getCraftMerchant() { ++ return (craftMerchant == null) ? craftMerchant = new CraftMerchant(this) : craftMerchant; ++ } ++ // CraftBukkit end + private static final EntityDataAccessor DATA_UNHAPPY_COUNTER = SynchedEntityData.defineId(AbstractVillager.class, EntityDataSerializers.INT); + public static final int VILLAGER_SLOT_OFFSET = 300; + private static final int VILLAGER_INVENTORY_SIZE = 8; +@@ -44,7 +58,7 @@ + private Player tradingPlayer; + @Nullable + protected MerchantOffers offers; +- private final SimpleContainer inventory = new SimpleContainer(8); ++ private final SimpleContainer inventory = new SimpleContainer(8, (org.bukkit.craftbukkit.entity.CraftAbstractVillager) this.getBukkitEntity()); // CraftBukkit add argument + + public AbstractVillager(EntityType entitytype, Level level) { + super(entitytype, level); +@@ -252,8 +246,17 @@ + while (j < i && !arraylist.isEmpty()) { + MerchantOffer merchantoffer = ((VillagerTrades.ItemListing) arraylist.remove(this.random.nextInt(arraylist.size()))).getOffer(this, this.random); + +- if (merchantoffer != null) { +- merchantoffers.add(merchantoffer); ++ if (merchantrecipe != null) { ++ // CraftBukkit start ++ VillagerAcquireTradeEvent event = new VillagerAcquireTradeEvent((org.bukkit.entity.AbstractVillager) getBukkitEntity(), merchantrecipe.asBukkit()); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ if (!event.isCancelled()) { ++ givenMerchantOffers.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); ++ } ++ // CraftBukkit end + ++j; + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/npc/InventoryCarrier.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/npc/InventoryCarrier.java.patch new file mode 100644 index 0000000000..d3c77db624 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/npc/InventoryCarrier.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/entity/npc/InventoryCarrier.java ++++ b/net/minecraft/world/entity/npc/InventoryCarrier.java +@@ -23,7 +23,14 @@ + return; + } + +- mob.onItemPickup(itementity); ++ // CraftBukkit start ++ ItemStack remaining = new SimpleContainer(inventorysubcontainer).addItem(itemstack); ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(mob, itemEntity, remaining.getCount(), false).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ ++ mob.onItemPickup(itemEntity); + int i = itemstack.getCount(); + ItemStack itemstack1 = simplecontainer.addItem(itemstack); + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/npc/Villager.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/npc/Villager.java.patch new file mode 100644 index 0000000000..b583c81780 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/npc/Villager.java.patch @@ -0,0 +1,80 @@ +--- a/net/minecraft/world/entity/npc/Villager.java ++++ b/net/minecraft/world/entity/npc/Villager.java +@@ -92,6 +92,13 @@ + import net.minecraft.world.phys.AABB; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTransformEvent; ++import org.bukkit.event.entity.VillagerReplenishTradeEvent; ++// CraftBukkit end ++ + public class Villager extends AbstractVillager implements ReputationEventHandler, VillagerDataHolder { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -238,7 +240,7 @@ + this.increaseProfessionLevelOnUpdate = false; + } + +- this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 200, 0)); ++ this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 200, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.VILLAGER_TRADE); // CraftBukkit + } + } + +@@ -372,7 +368,13 @@ + while (iterator.hasNext()) { + MerchantOffer merchantoffer = (MerchantOffer) iterator.next(); + +- merchantoffer.resetUses(); ++ // CraftBukkit start ++ VillagerReplenishTradeEvent event = new VillagerReplenishTradeEvent((org.bukkit.entity.Villager) this.getBukkitEntity(), merchantrecipe.asBukkit()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ merchantrecipe.resetUses(); ++ } ++ // CraftBukkit end + } + + this.resendOffersToTradingPlayer(); +@@ -441,7 +443,13 @@ + while (iterator.hasNext()) { + MerchantOffer merchantoffer = (MerchantOffer) iterator.next(); + +- merchantoffer.resetUses(); ++ // CraftBukkit start ++ VillagerReplenishTradeEvent event = new VillagerReplenishTradeEvent((org.bukkit.entity.Villager) this.getBukkitEntity(), merchantrecipe.asBukkit()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ merchantrecipe.resetUses(); ++ } ++ // CraftBukkit end + } + } + +@@ -862,8 +852,13 @@ + witch.setCustomNameVisible(this.isCustomNameVisible()); + } + +- witch.setPersistenceRequired(); +- serverlevel.addFreshEntityWithPassengers(witch); ++ entitywitch.setPersistenceRequired(); ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, entitywitch, EntityTransformEvent.TransformReason.LIGHTNING).isCancelled()) { ++ return; ++ } ++ level.addFreshEntityWithPassengers(entitywitch, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); ++ // CraftBukkit end + this.releaseAllPois(); + this.discard(); + } else { +@@ -965,7 +957,7 @@ + }).limit(5L).collect(Collectors.toList()); + + if (list1.size() >= j) { +- if (!SpawnUtil.trySpawnMob(EntityType.IRON_GOLEM, MobSpawnType.MOB_SUMMONED, serverlevel, this.blockPosition(), 10, 8, 6, SpawnUtil.Strategy.LEGACY_IRON_GOLEM).isEmpty()) { ++ if (!SpawnUtil.trySpawnMob(EntityType.IRON_GOLEM, EnumMobSpawn.MOB_SUMMONED, serverLevel, this.blockPosition(), 10, 8, 6, SpawnUtil.Strategy.LEGACY_IRON_GOLEM, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE).isEmpty()) { // CraftBukkit + list.forEach(GolemSensor::golemDetected); + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/npc/WanderingTrader.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/npc/WanderingTrader.java.patch new file mode 100644 index 0000000000..48dd4579db --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/npc/WanderingTrader.java.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/world/entity/npc/WanderingTrader.java ++++ b/net/minecraft/world/entity/npc/WanderingTrader.java +@@ -47,15 +47,21 @@ + import net.minecraft.world.phys.Vec3; + import org.apache.commons.lang3.tuple.Pair; + +-public class WanderingTrader extends AbstractVillager { ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; ++import org.bukkit.entity.AbstractVillager; ++import org.bukkit.event.entity.VillagerAcquireTradeEvent; ++// CraftBukkit end + + private static final int NUMBER_OF_TRADE_OFFERS = 5; + @Nullable + private BlockPos wanderTarget; + private int despawnDelay; + +- public WanderingTrader(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public WanderingTrader(EntityType entityType, Level level) { ++ super(entityType, level); ++ this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader + } + + @Override +@@ -140,8 +143,17 @@ + VillagerTrades.ItemListing villagertrades_itemlisting = avillagertrades_itemlisting1[i]; + MerchantOffer merchantoffer = villagertrades_itemlisting.getOffer(this, this.random); + +- if (merchantoffer != null) { +- merchantoffers.add(merchantoffer); ++ if (merchantrecipe != null) { ++ // CraftBukkit start ++ VillagerAcquireTradeEvent event = new VillagerAcquireTradeEvent((AbstractVillager) getBukkitEntity(), merchantrecipe.asBukkit()); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ if (!event.isCancelled()) { ++ merchantrecipelist.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); ++ } ++ // CraftBukkit end + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/npc/WanderingTraderSpawner.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/npc/WanderingTraderSpawner.java.patch new file mode 100644 index 0000000000..d3b5420fdb --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/npc/WanderingTraderSpawner.java.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/world/entity/npc/WanderingTraderSpawner.java ++++ b/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +@@ -111,17 +110,17 @@ + return false; + } + +- WanderingTrader wanderingtrader = (WanderingTrader) EntityType.WANDERING_TRADER.spawn(serverlevel, blockpos2, MobSpawnType.EVENT); ++ WanderingTrader entityvillagertrader = (WanderingTrader) EntityType.WANDERING_TRADER.spawn(serverLevel, blockposition2, EnumMobSpawn.EVENT, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit + + if (wanderingtrader != null) { + for (int i = 0; i < 2; ++i) { + this.tryToSpawnLlamaFor(serverlevel, wanderingtrader, 4); + } + +- this.serverLevelData.setWanderingTraderId(wanderingtrader.getUUID()); +- wanderingtrader.setDespawnDelay(48000); +- wanderingtrader.setWanderTarget(blockpos1); +- wanderingtrader.restrictTo(blockpos1, 16); ++ this.serverLevelData.setWanderingTraderId(entityvillagertrader.getUUID()); ++ // entityvillagertrader.setDespawnDelay(48000); // CraftBukkit - moved to EntityVillagerTrader constructor. This lets the value be modified by plugins on CreatureSpawnEvent ++ entityvillagertrader.setWanderTarget(blockposition1); ++ entityvillagertrader.restrictTo(blockposition1, 16); + return true; + } + } +@@ -133,8 +132,8 @@ + private void tryToSpawnLlamaFor(ServerLevel serverlevel, WanderingTrader wanderingtrader, int i) { + BlockPos blockpos = this.findSpawnPositionNear(serverlevel, wanderingtrader.blockPosition(), i); + +- if (blockpos != null) { +- TraderLlama traderllama = (TraderLlama) EntityType.TRADER_LLAMA.spawn(serverlevel, blockpos, MobSpawnType.EVENT); ++ if (blockposition != null) { ++ TraderLlama entityllamatrader = (TraderLlama) EntityType.TRADER_LLAMA.spawn(serverLevel, blockposition, EnumMobSpawn.EVENT, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit + + if (traderllama != null) { + traderllama.setLeashedTo(wanderingtrader, true); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/player/Inventory.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/player/Inventory.java.patch new file mode 100644 index 0000000000..c8952ba42c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/player/Inventory.java.patch @@ -0,0 +1,100 @@ +--- a/net/minecraft/world/entity/player/Inventory.java ++++ b/net/minecraft/world/entity/player/Inventory.java +@@ -26,7 +26,12 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.state.BlockState; + +-public class Inventory implements Container, Nameable { ++// CraftBukkit start ++import java.util.ArrayList; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end + + public static final int POP_TIME_DURATION = 5; + public static final int INVENTORY_SIZE = 36; +@@ -43,6 +50,54 @@ + public final Player player; + private int timesChanged; + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ List combined = new ArrayList(items.size() + armor.size() + offhand.size()); ++ for (List sub : this.compartments) { ++ combined.addAll(sub); ++ } ++ ++ return combined; ++ } ++ ++ public List getArmorContents() { ++ return this.armor; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return this.player.getBukkitEntity(); ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return player.getBukkitEntity().getLocation(); ++ } ++ // CraftBukkit end ++ + public Inventory(Player player) { + this.items = NonNullList.withSize(36, ItemStack.EMPTY); + this.armor = NonNullList.withSize(4, ItemStack.EMPTY); +@@ -63,6 +118,28 @@ + return !itemstack.isEmpty() && ItemStack.isSameItemSameTags(itemstack, itemstack1) && itemstack.isStackable() && itemstack.getCount() < itemstack.getMaxStackSize() && itemstack.getCount() < this.getMaxStackSize(); + } + ++ // CraftBukkit start - Watch method above! :D ++ public int canHold(ItemStack itemstack) { ++ int remains = itemstack.getCount(); ++ for (int i = 0; i < this.items.size(); ++i) { ++ ItemStack itemstack1 = this.getItem(i); ++ if (itemstack1.isEmpty()) return itemstack.getCount(); ++ ++ if (this.hasRemainingSpaceForItem(itemstack1, itemstack)) { ++ remains -= (itemstack1.getMaxStackSize() < this.getMaxStackSize() ? itemstack1.getMaxStackSize() : this.getMaxStackSize()) - itemstack1.getCount(); ++ } ++ if (remains <= 0) return itemstack.getCount(); ++ } ++ ItemStack offhandItemStack = this.getItem(this.items.size() + this.armor.size()); ++ if (this.hasRemainingSpaceForItem(offhandItemStack, itemstack)) { ++ remains -= (offhandItemStack.getMaxStackSize() < this.getMaxStackSize() ? offhandItemStack.getMaxStackSize() : this.getMaxStackSize()) - offhandItemStack.getCount(); ++ } ++ if (remains <= 0) return itemstack.getCount(); ++ ++ return itemstack.getCount() - remains; ++ } ++ // CraftBukkit end ++ + public int getFreeSlot() { + for (int i = 0; i < this.items.size(); ++i) { + if (((ItemStack) this.items.get(i)).isEmpty()) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/player/Player.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/player/Player.java.patch new file mode 100644 index 0000000000..8eb24b7af0 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/player/Player.java.patch @@ -0,0 +1,519 @@ +--- a/net/minecraft/world/entity/player/Player.java ++++ b/net/minecraft/world/entity/player/Player.java +@@ -111,6 +112,16 @@ + import net.minecraft.world.scores.PlayerTeam; + import net.minecraft.world.scores.Scoreboard; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.util.CraftVector; ++import org.bukkit.entity.Item; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.entity.EntityExhaustionEvent; ++import org.bukkit.event.player.PlayerDropItemEvent; ++import org.bukkit.event.player.PlayerVelocityEvent; ++// CraftBukkit end + + public abstract class Player extends LivingEntity { + +@@ -136,10 +148,10 @@ + protected static final EntityDataAccessor DATA_SHOULDER_RIGHT = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG); + private long timeEntitySatOnShoulder; + private final Inventory inventory = new Inventory(this); +- protected PlayerEnderChestContainer enderChestInventory = new PlayerEnderChestContainer(); ++ protected PlayerEnderChestContainer enderChestInventory = new PlayerEnderChestContainer(this); // CraftBukkit - add "this" to constructor + public final InventoryMenu inventoryMenu; + public AbstractContainerMenu containerMenu; +- protected FoodData foodData = new FoodData(); ++ protected FoodData foodData = new FoodData(this); // CraftBukkit - add "this" to constructor + protected int jumpTriggerTime; + public float oBob; + public float bob; +@@ -168,7 +180,17 @@ + public FishingHook fishing; + protected float hurtDir; + +- public Player(Level level, BlockPos blockpos, float f, GameProfile gameprofile) { ++ // CraftBukkit start ++ public boolean fauxSleeping; ++ public int oldLevel = -1; ++ ++ @Override ++ public CraftHumanEntity getBukkitEntity() { ++ return (CraftHumanEntity) super.getBukkitEntity(); ++ } ++ // CraftBukkit end ++ ++ public Player(Level level, BlockPos pos, float yRot, GameProfile gameProfile) { + super(EntityType.PLAYER, level); + this.lastItemInMainHand = ItemStack.EMPTY; + this.cooldowns = this.createItemCooldowns(); +@@ -315,7 +334,7 @@ + ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); + + if (itemstack.is(Items.TURTLE_HELMET) && !this.isEyeInFluid(FluidTags.WATER)) { +- this.addEffect(new MobEffectInstance(MobEffects.WATER_BREATHING, 200, 0, false, false, true)); ++ this.addEffect(new MobEffectInstance(MobEffects.WATER_BREATHING, 200, 0, false, false, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TURTLE_HELMET); // CraftBukkit + } + + } +@@ -495,8 +504,14 @@ + public void rideTick() { + if (!this.level().isClientSide && this.wantsToStopRiding() && this.isPassenger()) { + this.stopRiding(); +- this.setShiftKeyDown(false); +- } else { ++ // CraftBukkit start - SPIGOT-7316: no longer passenger, dismount and return ++ if (!this.isPassenger()) { ++ this.setShiftKeyDown(false); ++ return; ++ } ++ } ++ { ++ // CraftBukkit end + super.rideTick(); + this.oBob = this.bob; + this.bob = 0.0F; +@@ -520,7 +533,8 @@ + + if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.level().getGameRules().getBoolean(GameRules.RULE_NATURAL_REGENERATION)) { + if (this.getHealth() < this.getMaxHealth() && this.tickCount % 20 == 0) { +- this.heal(1.0F); ++ // CraftBukkit - added regain reason of "REGEN" for filtering purposes. ++ this.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.REGEN); + } + + if (this.foodData.needsFood() && this.tickCount % 10 == 0) { +@@ -683,7 +693,14 @@ + } + + @Nullable +- public ItemEntity drop(ItemStack itemstack, boolean flag, boolean flag1) { ++ public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean includeThrowerName) { ++ // CraftBukkit start - SPIGOT-2942: Add boolean to call event ++ return drop(droppedItem, dropAround, includeThrowerName, true); ++ } ++ ++ @Nullable ++ public ItemEntity drop(ItemStack itemstack, boolean flag, boolean flag1, boolean callEvent) { ++ // CraftBukkit end + if (itemstack.isEmpty()) { + return null; + } else { +@@ -718,7 +735,34 @@ + itementity.setDeltaMovement((double) (-f3 * f2 * 0.3F) + Math.cos((double) f5) * (double) f6, (double) (-f1 * 0.3F + 0.1F + (this.random.nextFloat() - this.random.nextFloat()) * 0.1F), (double) (f4 * f2 * 0.3F) + Math.sin((double) f5) * (double) f6); + } + +- return itementity; ++ // CraftBukkit start - fire PlayerDropItemEvent ++ if (!callEvent) { // SPIGOT-2942: Add boolean to call event ++ return entityitem; ++ } ++ org.bukkit.entity.Player player = (org.bukkit.entity.Player) this.getBukkitEntity(); ++ Item drop = (Item) entityitem.getBukkitEntity(); ++ ++ PlayerDropItemEvent event = new PlayerDropItemEvent(player, drop); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ org.bukkit.inventory.ItemStack cur = player.getInventory().getItemInHand(); ++ if (flag1 && (cur == null || cur.getAmount() == 0)) { ++ // The complete stack was dropped ++ player.getInventory().setItemInHand(drop.getItemStack()); ++ } else if (flag1 && cur.isSimilar(drop.getItemStack()) && cur.getAmount() < cur.getMaxStackSize() && drop.getItemStack().getAmount() == 1) { ++ // Only one item is dropped ++ cur.setAmount(cur.getAmount() + 1); ++ player.getInventory().setItemInHand(cur); ++ } else { ++ // Fallback ++ player.getInventory().addItem(drop.getItemStack()); ++ } ++ return null; ++ } ++ // CraftBukkit end ++ ++ return entityitem; + } + } + +@@ -872,12 +912,12 @@ + return false; + } else { + if (!this.level().isClientSide) { +- this.removeEntitiesOnShoulder(); ++ // this.removeEntitiesOnShoulder(); // CraftBukkit - moved down + } + + if (damagesource.scalesWithDifficulty()) { + if (this.level().getDifficulty() == Difficulty.PEACEFUL) { +- f = 0.0F; ++ return false; // CraftBukkit - f = 0.0f -> return false + } + + if (this.level().getDifficulty() == Difficulty.EASY) { +@@ -889,7 +929,13 @@ + } + } + +- return f == 0.0F ? false : super.hurt(damagesource, f); ++ // CraftBukkit start - Don't filter out 0 damage ++ boolean damaged = super.hurt(source, amount); ++ if (damaged) { ++ this.removeEntitiesOnShoulder(); ++ } ++ return damaged; ++ // CraftBukkit end + } + } + } +@@ -910,11 +954,30 @@ + return !this.getAbilities().invulnerable && super.canBeSeenAsEnemy(); + } + +- public boolean canHarmPlayer(Player player) { +- PlayerTeam playerteam = this.getTeam(); +- PlayerTeam playerteam1 = player.getTeam(); ++ public boolean canHarmPlayer(Player other) { ++ // CraftBukkit start - Change to check OTHER player's scoreboard team according to API ++ // To summarize this method's logic, it's "Can parameter hurt this" ++ org.bukkit.scoreboard.Team team; ++ if (other instanceof ServerPlayer) { ++ ServerPlayer thatPlayer = (ServerPlayer) other; ++ team = thatPlayer.getBukkitEntity().getScoreboard().getPlayerTeam(thatPlayer.getBukkitEntity()); ++ if (team == null || team.allowFriendlyFire()) { ++ return true; ++ } ++ } else { ++ // This should never be called, but is implemented anyway ++ org.bukkit.OfflinePlayer thisPlayer = other.level().getCraftServer().getOfflinePlayer(other.getScoreboardName()); ++ team = other.level().getCraftServer().getScoreboardManager().getMainScoreboard().getPlayerTeam(thisPlayer); ++ if (team == null || team.allowFriendlyFire()) { ++ return true; ++ } ++ } + +- return playerteam == null ? true : (!playerteam.isAlliedTo(playerteam1) ? true : playerteam.isAllowFriendlyFire()); ++ if (this instanceof ServerPlayer) { ++ return !team.hasPlayer(((ServerPlayer) this).getBukkitEntity()); ++ } ++ return !team.hasPlayer(this.level().getCraftServer().getOfflinePlayer(this.getScoreboardName())); ++ // CraftBukkit end + } + + @Override +@@ -959,9 +1019,13 @@ + } + } + ++ // CraftBukkit start + @Override +- @Override +- protected void actuallyHurt(DamageSource damagesource, float f) { ++ protected boolean damageEntity0(DamageSource damagesource, float f) { // void -> boolean ++ if (true) { ++ return super.damageEntity0(damagesource, f); ++ } ++ // CraftBukkit end + if (!this.isInvulnerableTo(damagesource)) { + f = this.getDamageAfterArmorAbsorb(damagesource, f); + f = this.getDamageAfterMagicAbsorb(damagesource, f); +@@ -976,7 +1040,7 @@ + } + + if (f != 0.0F) { +- this.causeFoodExhaustion(damagesource.getFoodExhaustion()); ++ this.causeFoodExhaustion(damagesource.getFoodExhaustion(), EntityExhaustionEvent.ExhaustionReason.DAMAGED); // CraftBukkit - EntityExhaustionEvent + this.getCombatTracker().recordDamage(damagesource, f); + this.setHealth(this.getHealth() - f); + if (f < 3.4028235E37F) { +@@ -986,6 +1050,7 @@ + this.gameEvent(GameEvent.ENTITY_DAMAGE); + } + } ++ return false; // CraftBukkit + } + + @Override +@@ -1156,7 +1215,7 @@ + + f *= 0.2F + f2 * f2 * 0.8F; + f1 *= f2; +- this.resetAttackStrengthTicker(); ++ // this.resetAttackCooldown(); // CraftBukkit - Moved to EntityLiving to reset the cooldown after the damage is dealt + if (f > 0.0F || f1 > 0.0F) { + boolean flag = f2 > 0.9F; + boolean flag1 = false; +@@ -1192,11 +1251,18 @@ + boolean flag4 = false; + int j = EnchantmentHelper.getFireAspect(this); + +- if (entity instanceof LivingEntity) { +- f3 = ((LivingEntity) entity).getHealth(); +- if (j > 0 && !entity.isOnFire()) { +- flag4 = true; +- entity.setSecondsOnFire(1); ++ if (target instanceof LivingEntity) { ++ f3 = ((LivingEntity) target).getHealth(); ++ if (j > 0 && !target.isOnFire()) { ++ // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), target.getBukkitEntity(), 1); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ flag4 = true; ++ target.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + } + +@@ -1223,9 +1289,12 @@ + while (iterator.hasNext()) { + LivingEntity livingentity = (LivingEntity) iterator.next(); + +- if (livingentity != this && livingentity != entity && !this.isAlliedTo((Entity) livingentity) && (!(livingentity instanceof ArmorStand) || !((ArmorStand) livingentity).isMarker()) && this.distanceToSqr((Entity) livingentity) < 9.0D) { +- livingentity.knockback(0.4000000059604645D, (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F))); +- livingentity.hurt(this.damageSources().playerAttack(this), f4); ++ if (entityliving != this && entityliving != target && !this.isAlliedTo((Entity) entityliving) && (!(entityliving instanceof ArmorStand) || !((ArmorStand) entityliving).isMarker()) && this.distanceToSqr((Entity) entityliving) < 9.0D) { ++ // CraftBukkit start - Only apply knockback if the damage hits ++ if (entityliving.hurt(this.damageSources().playerAttack(this).sweep(), f4)) { ++ entityliving.knockback(0.4000000059604645D, (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F))); ++ } ++ // CraftBukkit end + } + } + +@@ -1233,10 +1302,27 @@ + this.sweepAttack(); + } + +- if (entity instanceof ServerPlayer && entity.hurtMarked) { +- ((ServerPlayer) entity).connection.send(new ClientboundSetEntityMotionPacket(entity)); +- entity.hurtMarked = false; +- entity.setDeltaMovement(vec3); ++ if (target instanceof ServerPlayer && target.hurtMarked) { ++ // CraftBukkit start - Add Velocity Event ++ boolean cancelled = false; ++ org.bukkit.entity.Player player = (org.bukkit.entity.Player) target.getBukkitEntity(); ++ org.bukkit.util.Vector velocity = CraftVector.toBukkit(vec3d); ++ ++ PlayerVelocityEvent event = new PlayerVelocityEvent(player, velocity.clone()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ cancelled = true; ++ } else if (!velocity.equals(event.getVelocity())) { ++ player.setVelocity(event.getVelocity()); ++ } ++ ++ if (!cancelled) { ++ ((ServerPlayer) target).connection.send(new ClientboundSetEntityMotionPacket(target)); ++ target.hurtMarked = false; ++ target.setDeltaMovement(vec3d); ++ } ++ // CraftBukkit end + } + + if (flag2) { +@@ -1281,7 +1367,14 @@ + + this.awardStat(Stats.DAMAGE_DEALT, Math.round(f5 * 10.0F)); + if (j > 0) { +- entity.setSecondsOnFire(j * 4); ++ // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), target.getBukkitEntity(), j * 4); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ target.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + + if (this.level() instanceof ServerLevel && f5 > 2.0F) { +@@ -1291,12 +1384,17 @@ + } + } + +- this.causeFoodExhaustion(0.1F); ++ this.causeFoodExhaustion(0.1F, EntityExhaustionEvent.ExhaustionReason.ATTACK); // CraftBukkit - EntityExhaustionEvent + } else { + this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F); + if (flag4) { + entity.clearFire(); + } ++ // CraftBukkit start - resync on cancelled event ++ if (this instanceof ServerPlayer) { ++ ((ServerPlayer) this).getBukkitEntity().updateInventory(); ++ } ++ // CraftBukkit end + } + } + +@@ -1374,8 +1470,14 @@ + return this.containerMenu != this.inventoryMenu; + } + +- public Either startSleepInBed(BlockPos blockpos) { +- this.startSleeping(blockpos); ++ public Either startSleepInBed(BlockPos bedPos) { ++ // CraftBukkit start ++ return this.startSleepInBed(bedPos, false); ++ } ++ ++ public Either startSleepInBed(BlockPos blockposition, boolean force) { ++ // CraftBukkit end ++ this.startSleeping(blockposition); + this.sleepCounter = 0; + return Either.right(Unit.INSTANCE); + } +@@ -1464,9 +1564,9 @@ + super.jumpFromGround(); + this.awardStat(Stats.JUMP); + if (this.isSprinting()) { +- this.causeFoodExhaustion(0.2F); ++ this.causeFoodExhaustion(0.2F, EntityExhaustionEvent.ExhaustionReason.JUMP_SPRINT); // CraftBukkit - EntityExhaustionEvent + } else { +- this.causeFoodExhaustion(0.05F); ++ this.causeFoodExhaustion(0.05F, EntityExhaustionEvent.ExhaustionReason.JUMP); // CraftBukkit - EntityExhaustionEvent + } + + } +@@ -1494,7 +1593,11 @@ + + this.setDeltaMovement(vec32.x, d0 * 0.6D, vec32.z); + this.resetFallDistance(); +- this.setSharedFlag(7, false); ++ // CraftBukkit start ++ if (getSharedFlag(7) && !org.bukkit.craftbukkit.event.CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) { ++ this.setSharedFlag(7, false); ++ } ++ // CraftBukkit end + } else { + super.travel(vec3); + } +@@ -1550,12 +1650,24 @@ + } + + public void startFallFlying() { +- this.setSharedFlag(7, true); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callToggleGlideEvent(this, true).isCancelled()) { ++ this.setSharedFlag(7, true); ++ } else { ++ // SPIGOT-5542: must toggle like below ++ this.setSharedFlag(7, true); ++ this.setSharedFlag(7, false); ++ } ++ // CraftBukkit end + } + + public void stopFallFlying() { ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) { + this.setSharedFlag(7, true); + this.setSharedFlag(7, false); ++ } ++ // CraftBukkit end + } + + @Override +@@ -1674,10 +1781,21 @@ + return this.experienceLevel >= 30 ? 112 + (this.experienceLevel - 30) * 9 : (this.experienceLevel >= 15 ? 37 + (this.experienceLevel - 15) * 5 : 7 + this.experienceLevel * 2); + } + +- public void causeFoodExhaustion(float f) { ++ // CraftBukkit start ++ public void causeFoodExhaustion(float exhaustion) { ++ this.causeFoodExhaustion(exhaustion, EntityExhaustionEvent.ExhaustionReason.UNKNOWN); ++ } ++ ++ public void causeFoodExhaustion(float f, EntityExhaustionEvent.ExhaustionReason reason) { ++ // CraftBukkit end + if (!this.abilities.invulnerable) { + if (!this.level().isClientSide) { +- this.foodData.addExhaustion(f); ++ // CraftBukkit start ++ EntityExhaustionEvent event = CraftEventFactory.callPlayerExhaustionEvent(this, reason, f); ++ if (!event.isCancelled()) { ++ this.foodData.addExhaustion(event.getExhaustion()); ++ } ++ // CraftBukkit end + } + + } +@@ -1763,21 +1880,21 @@ + } + + @Override +- @Override +- protected boolean doesEmitEquipEvent(EquipmentSlot equipmentslot) { +- return equipmentslot.getType() == EquipmentSlot.Type.ARMOR; ++ public void setItemSlot(EquipmentSlot slot, ItemStack stack) { ++ // CraftBukkit start ++ setItemSlot(slot, stack, false); + } + + @Override +- @Override +- public void setItemSlot(EquipmentSlot equipmentslot, ItemStack itemstack) { ++ public void setItemSlot(EquipmentSlot enumitemslot, ItemStack itemstack, boolean silent) { ++ // CraftBukkit end + this.verifyEquippedItem(itemstack); +- if (equipmentslot == EquipmentSlot.MAINHAND) { +- this.onEquipItem(equipmentslot, (ItemStack) this.inventory.items.set(this.inventory.selected, itemstack), itemstack); +- } else if (equipmentslot == EquipmentSlot.OFFHAND) { +- this.onEquipItem(equipmentslot, (ItemStack) this.inventory.offhand.set(0, itemstack), itemstack); +- } else if (equipmentslot.getType() == EquipmentSlot.Type.ARMOR) { +- this.onEquipItem(equipmentslot, (ItemStack) this.inventory.armor.set(equipmentslot.getIndex(), itemstack), itemstack); ++ if (enumitemslot == EquipmentSlot.MAINHAND) { ++ this.onEquipItem(enumitemslot, (ItemStack) this.inventory.items.set(this.inventory.selected, itemstack), itemstack, silent); // CraftBukkit ++ } else if (enumitemslot == EquipmentSlot.OFFHAND) { ++ this.onEquipItem(enumitemslot, (ItemStack) this.inventory.offhand.set(0, itemstack), itemstack, silent); // CraftBukkit ++ } else if (enumitemslot.getType() == EquipmentSlot.Function.ARMOR) { ++ this.onEquipItem(enumitemslot, (ItemStack) this.inventory.armor.set(enumitemslot.getIndex(), itemstack), itemstack, silent); // CraftBukkit + } + + } +@@ -1818,26 +1933,31 @@ + + protected void removeEntitiesOnShoulder() { + if (this.timeEntitySatOnShoulder + 20L < this.level().getGameTime()) { +- this.respawnEntityOnShoulder(this.getShoulderEntityLeft()); +- this.setShoulderEntityLeft(new CompoundTag()); +- this.respawnEntityOnShoulder(this.getShoulderEntityRight()); +- this.setShoulderEntityRight(new CompoundTag()); ++ // CraftBukkit start ++ if (this.respawnEntityOnShoulder(this.getShoulderEntityLeft())) { ++ this.setShoulderEntityLeft(new CompoundTag()); ++ } ++ if (this.respawnEntityOnShoulder(this.getShoulderEntityRight())) { ++ this.setShoulderEntityRight(new CompoundTag()); ++ } ++ // CraftBukkit end + } + + } + +- private void respawnEntityOnShoulder(CompoundTag compoundtag) { +- if (!this.level().isClientSide && !compoundtag.isEmpty()) { +- EntityType.create(compoundtag, this.level()).ifPresent((entity) -> { ++ private boolean respawnEntityOnShoulder(CompoundTag nbttagcompound) { // CraftBukkit void->boolean ++ if (!this.level().isClientSide && !nbttagcompound.isEmpty()) { ++ return EntityType.create(nbttagcompound, this.level()).map((entity) -> { // CraftBukkit + if (entity instanceof TamableAnimal) { + ((TamableAnimal) entity).setOwnerUUID(this.uuid); + } + + entity.setPos(this.getX(), this.getY() + 0.699999988079071D, this.getZ()); +- ((ServerLevel) this.level()).addWithUUID(entity); +- }); ++ return ((ServerLevel) this.level()).addWithUUID(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit ++ }).orElse(true); // CraftBukkit + } + ++ return true; // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/AbstractArrow.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/AbstractArrow.java.patch new file mode 100644 index 0000000000..59d167b863 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/AbstractArrow.java.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/entity/projectile/AbstractArrow.java ++++ b/net/minecraft/world/entity/projectile/AbstractArrow.java +@@ -46,6 +47,9 @@ + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.player.PlayerPickupArrowEvent; ++// CraftBukkit end + + public abstract class AbstractArrow extends Projectile { + +@@ -225,7 +223,7 @@ + } + + if (object != null && !flag) { +- this.onHit((HitResult) object); ++ this.preOnHit((HitResult) object); // CraftBukkit - projectile hit event + this.hasImpulse = true; + } + +@@ -375,7 +371,13 @@ + boolean flag1 = entity.getType().is(EntityTypeTags.DEFLECTS_ARROWS); + + if (this.isOnFire() && !flag && !flag1) { +- entity.setSecondsOnFire(5); ++ // CraftBukkit start ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), 5); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ if (!combustEvent.isCancelled()) { ++ entity.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + + if (entity.hurt(damagesource, (float) i)) { +@@ -559,8 +555,23 @@ + @Override + public void playerTouch(Player player) { + if (!this.level().isClientSide && (this.inGround || this.isNoPhysics()) && this.shakeTime <= 0) { +- if (this.tryPickup(player)) { +- player.take(this, 1); ++ // CraftBukkit start ++ ItemStack itemstack = this.getPickupItem(); ++ if (this.pickup == Pickup.ALLOWED && !itemstack.isEmpty() && entity.getInventory().canHold(itemstack) > 0) { ++ ItemEntity item = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), itemstack); ++ PlayerPickupArrowEvent event = new PlayerPickupArrowEvent((org.bukkit.entity.Player) entity.getBukkitEntity(), new org.bukkit.craftbukkit.entity.CraftItem(this.level().getCraftServer(), item), (org.bukkit.entity.AbstractArrow) this.getBukkitEntity()); ++ // event.setCancelled(!entityhuman.canPickUpLoot); TODO ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ itemstack = item.getItem(); ++ } ++ ++ if ((this.pickup == AbstractArrow.Pickup.ALLOWED && entity.getInventory().add(itemstack)) || (this.pickup == AbstractArrow.Pickup.CREATIVE_ONLY && entity.getAbilities().instabuild)) { ++ // CraftBukkit end ++ entity.take(this, 1); + this.discard(); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java.patch new file mode 100644 index 0000000000..837230eaf2 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java ++++ b/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java +@@ -16,12 +16,15 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public abstract class AbstractHurtingProjectile extends Projectile { + + public double xPower; + public double yPower; + public double zPower; ++ public float bukkitYield = 1; // CraftBukkit ++ public boolean isIncendiary = true; // CraftBukkit + + protected AbstractHurtingProjectile(EntityType entitytype, Level level) { + super(entitytype, level); +@@ -36,6 +39,12 @@ + this(entitytype, level); + this.moveTo(d0, d1, d2, this.getYRot(), this.getXRot()); + this.reapplyPosition(); ++ // CraftBukkit start - Added setDirection method ++ this.setDirection(d3, z, d5); ++ } ++ ++ public void setDirection(double d3, double d4, double d5) { ++ // CraftBukkit end + double d6 = Math.sqrt(d3 * d3 + d4 * d4 + d5 * d5); + + if (d6 != 0.0D) { +@@ -88,8 +94,14 @@ + + HitResult hitresult = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity, this.getClipType()); + +- if (hitresult.getType() != HitResult.Type.MISS) { +- this.onHit(hitresult); ++ if (movingobjectposition.getType() != HitResult.EnumMovingObjectType.MISS) { ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event ++ ++ // CraftBukkit start - Fire ProjectileHitEvent ++ if (this.isRemoved()) { ++ CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); ++ } ++ // CraftBukkit end + } + + this.checkInsideBlocks(); +@@ -193,7 +199,12 @@ + + if (entity != null) { + if (!this.level().isClientSide) { +- Vec3 vec3 = entity.getLookAngle(); ++ // CraftBukkit start ++ if (CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, false)) { ++ return false; ++ } ++ // CraftBukkit end ++ Vec3 vec3d = entity.getLookAngle(); + + this.setDeltaMovement(vec3); + this.xPower = vec3.x * 0.1D; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/Arrow.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/Arrow.java.patch new file mode 100644 index 0000000000..19236dddac --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/Arrow.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/entity/projectile/Arrow.java ++++ b/net/minecraft/world/entity/projectile/Arrow.java +@@ -218,15 +213,15 @@ + mobeffectinstance = (MobEffectInstance) iterator.next(); + livingentity.addEffect(new MobEffectInstance(mobeffectinstance.getEffect(), Math.max(mobeffectinstance.mapDuration((i) -> { + return i / 8; +- }), 1), mobeffectinstance.getAmplifier(), mobeffectinstance.isAmbient(), mobeffectinstance.isVisible()), entity); ++ }), 1), mobeffect.getAmplifier(), mobeffect.isAmbient(), mobeffect.isVisible()), entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ARROW); // CraftBukkit + } + + if (!this.effects.isEmpty()) { + iterator = this.effects.iterator(); + + while (iterator.hasNext()) { +- mobeffectinstance = (MobEffectInstance) iterator.next(); +- livingentity.addEffect(mobeffectinstance, entity); ++ mobeffect = (MobEffectInstance) iterator.next(); ++ living.addEffect(mobeffect, entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ARROW); // CraftBukkit + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/EvokerFangs.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/EvokerFangs.java.patch new file mode 100644 index 0000000000..e5712ae16e --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/EvokerFangs.java.patch @@ -0,0 +1,17 @@ +--- a/net/minecraft/world/entity/projectile/EvokerFangs.java ++++ b/net/minecraft/world/entity/projectile/EvokerFangs.java +@@ -132,9 +127,11 @@ + private void dealDamageTo(LivingEntity livingentity) { + LivingEntity livingentity1 = this.getOwner(); + +- if (livingentity.isAlive() && !livingentity.isInvulnerable() && livingentity != livingentity1) { +- if (livingentity1 == null) { +- livingentity.hurt(this.damageSources().magic(), 6.0F); ++ if (target.isAlive() && !target.isInvulnerable() && target != entityliving1) { ++ if (entityliving1 == null) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = this; // CraftBukkit ++ target.hurt(this.damageSources().magic(), 6.0F); ++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = null; // CraftBukkit + } else { + if (livingentity1.isAlliedTo((Entity) livingentity)) { + return; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/EyeOfEnder.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/EyeOfEnder.java.patch new file mode 100644 index 0000000000..f10ba9607b --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/EyeOfEnder.java.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/world/entity/projectile/EyeOfEnder.java ++++ b/net/minecraft/world/entity/projectile/EyeOfEnder.java +@@ -34,9 +34,9 @@ + this.setPos(d0, d1, d2); + } + +- public void setItem(ItemStack itemstack) { +- if (!itemstack.is(Items.ENDER_EYE) || itemstack.hasTag()) { +- this.getEntityData().set(EyeOfEnder.DATA_ITEM_STACK, itemstack.copyWithCount(1)); ++ public void setItem(ItemStack stack) { ++ if (true || !stack.is(Items.ENDER_EYE) || stack.hasTag()) { // CraftBukkit - always allow item changing ++ this.getEntityData().set(EyeOfEnder.DATA_ITEM_STACK, stack.copyWithCount(1)); + } + + } +@@ -184,7 +177,7 @@ + public void readAdditionalSaveData(CompoundTag compoundtag) { + ItemStack itemstack = ItemStack.of(compoundtag.getCompound("Item")); + +- this.setItem(itemstack); ++ if (!itemstack.isEmpty()) this.setItem(itemstack); // CraftBukkit - SPIGOT-6103 summon, see also SPIGOT-5474 + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/Fireball.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/Fireball.java.patch new file mode 100644 index 0000000000..418d8315b3 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/Fireball.java.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/world/entity/projectile/Fireball.java ++++ b/net/minecraft/world/entity/projectile/Fireball.java +@@ -69,6 +65,6 @@ + super.readAdditionalSaveData(compoundtag); + ItemStack itemstack = ItemStack.of(compoundtag.getCompound("Item")); + +- this.setItem(itemstack); ++ if (!itemstack.isEmpty()) this.setItem(itemstack); // CraftBukkit - SPIGOT-5474 probably came from bugged earlier versions + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/FireworkRocketEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/FireworkRocketEntity.java.patch new file mode 100644 index 0000000000..4a7a183754 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/FireworkRocketEntity.java.patch @@ -0,0 +1,80 @@ +--- a/net/minecraft/world/entity/projectile/FireworkRocketEntity.java ++++ b/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +@@ -27,6 +27,7 @@ + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class FireworkRocketEntity extends Projectile implements ItemSupplier { + +@@ -147,7 +144,7 @@ + HitResult hitresult = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); + + if (!this.noPhysics) { +- this.onHit(hitresult); ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + this.hasImpulse = true; + } + +@@ -162,7 +159,11 @@ + } + + if (!this.level().isClientSide && this.life > this.lifetime) { +- this.explode(); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) { ++ this.explode(); ++ } ++ // CraftBukkit end + } + + } +@@ -179,7 +179,11 @@ + protected void onHitEntity(EntityHitResult entityhitresult) { + super.onHitEntity(entityhitresult); + if (!this.level().isClientSide) { +- this.explode(); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) { ++ this.explode(); ++ } ++ // CraftBukkit end + } + } + +@@ -190,7 +193,11 @@ + + this.level().getBlockState(blockpos).entityInside(this.level(), blockpos, this); + if (!this.level().isClientSide() && this.hasExplosion()) { +- this.explode(); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) { ++ this.explode(); ++ } ++ // CraftBukkit end + } + + super.onHitBlock(blockhitresult); +@@ -216,7 +223,9 @@ + + if (f > 0.0F) { + if (this.attachedToEntity != null) { +- this.attachedToEntity.hurt(this.damageSources().fireworks(this, this.getOwner()), 5.0F + (float) (listtag.size() * 2)); ++ CraftEventFactory.entityDamage = this; // CraftBukkit ++ this.attachedToEntity.hurt(this.damageSources().fireworks(this, this.getOwner()), 5.0F + (float) (nbttaglist.size() * 2)); ++ CraftEventFactory.entityDamage = null; // CraftBukkit + } + + double d0 = 5.0D; +@@ -243,7 +252,9 @@ + if (flag) { + float f1 = f * (float) Math.sqrt((5.0D - (double) this.distanceTo(livingentity)) / 5.0D); + +- livingentity.hurt(this.damageSources().fireworks(this, this.getOwner()), f1); ++ CraftEventFactory.entityDamage = this; // CraftBukkit ++ entityliving.hurt(this.damageSources().fireworks(this, this.getOwner()), f1); ++ CraftEventFactory.entityDamage = null; // CraftBukkit + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/FishingHook.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/FishingHook.java.patch new file mode 100644 index 0000000000..b595ce9ab1 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/FishingHook.java.patch @@ -0,0 +1,184 @@ +--- a/net/minecraft/world/entity/projectile/FishingHook.java ++++ b/net/minecraft/world/entity/projectile/FishingHook.java +@@ -46,6 +45,12 @@ + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.entity.Player; ++import org.bukkit.entity.FishHook; ++import org.bukkit.event.player.PlayerFishEvent; ++// CraftBukkit end ++ + public class FishingHook extends Projectile { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -67,8 +72,20 @@ + private final int luck; + private final int lureSpeed; + +- private FishingHook(EntityType entitytype, Level level, int i, int j) { +- super(entitytype, level); ++ // CraftBukkit start - Extra variables to enable modification of fishing wait time, values are minecraft defaults ++ public int minWaitTime = 100; ++ public int maxWaitTime = 600; ++ public int minLureTime = 20; ++ public int maxLureTime = 80; ++ public float minLureAngle = 0.0F; ++ public float maxLureAngle = 360.0F; ++ public boolean applyLure = true; ++ public boolean rainInfluenced = true; ++ public boolean skyInfluenced = true; ++ // CraftBukkit end ++ ++ private FishingHook(EntityType entityType, Level level, int luck, int lureSpeed) { ++ super(entityType, level); + this.syncronizedRandom = RandomSource.create(); + this.openWater = true; + this.currentState = FishingHook.FishHookState.FLYING; +@@ -266,7 +278,7 @@ + private void checkCollision() { + HitResult hitresult = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); + +- this.onHit(hitresult); ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + } + + @Override +@@ -302,11 +311,11 @@ + int i = 1; + BlockPos blockpos1 = blockpos.above(); + +- if (this.random.nextFloat() < 0.25F && this.level().isRainingAt(blockpos1)) { ++ if (this.rainInfluenced && this.random.nextFloat() < 0.25F && this.level().isRainingAt(blockposition1)) { // CraftBukkit + ++i; + } + +- if (this.random.nextFloat() < 0.5F && !this.level().canSeeSky(blockpos1)) { ++ if (this.skyInfluenced && this.random.nextFloat() < 0.5F && !this.level().canSeeSky(blockposition1)) { // CraftBukkit + --i; + } + +@@ -316,6 +325,10 @@ + this.timeUntilLured = 0; + this.timeUntilHooked = 0; + this.getEntityData().set(FishingHook.DATA_BITING, false); ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) this.getPlayerOwner().getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.FAILED_ATTEMPT); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ // CraftBukkit end + } + } else { + float f; +@@ -349,6 +362,13 @@ + serverlevel.sendParticles(ParticleTypes.FISHING, d0, d1, d2, 0, (double) (-f4), 0.01D, (double) f3, 1.0D); + } + } else { ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) this.getPlayerOwner().getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.BITE); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ if (playerFishEvent.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.playSound(SoundEvents.FISHING_BOBBER_SPLASH, 0.25F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); + double d3 = this.getY() + 0.5D; + +@@ -381,12 +401,16 @@ + } + + if (this.timeUntilLured <= 0) { +- this.fishAngle = Mth.nextFloat(this.random, 0.0F, 360.0F); +- this.timeUntilHooked = Mth.nextInt(this.random, 20, 80); ++ // CraftBukkit start - logic to modify fishing wait time, lure time, and lure angle ++ this.fishAngle = Mth.nextFloat(this.random, this.minLureAngle, this.maxLureAngle); ++ this.timeUntilHooked = Mth.nextInt(this.random, this.minLureTime, this.maxLureTime); ++ // CraftBukkit end + } + } else { +- this.timeUntilLured = Mth.nextInt(this.random, 100, 600); +- this.timeUntilLured -= this.lureSpeed * 20 * 5; ++ // CraftBukkit start - logic to modify fishing wait time ++ this.timeUntilLured = Mth.nextInt(this.random, this.minWaitTime, this.maxWaitTime); ++ this.timeUntilLured -= (this.applyLure) ? this.lureSpeed * 20 * 5 : 0; ++ // CraftBukkit end + } + } + +@@ -455,6 +477,14 @@ + int i = 0; + + if (this.hookedIn != null) { ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), this.hookedIn.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_ENTITY); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ return 0; ++ } ++ // CraftBukkit end + this.pullEntity(this.hookedIn); + CriteriaTriggers.FISHING_ROD_HOOKED.trigger((ServerPlayer) player, itemstack, this, Collections.emptyList()); + this.level().broadcastEntityEvent(this, (byte) 31); +@@ -469,15 +499,28 @@ + + while (iterator.hasNext()) { + ItemStack itemstack1 = (ItemStack) iterator.next(); +- ItemEntity itementity = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), itemstack1); +- double d0 = player.getX() - this.getX(); +- double d1 = player.getY() - this.getY(); +- double d2 = player.getZ() - this.getZ(); ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), itemstack1); ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); ++ playerFishEvent.setExpToDrop(this.random.nextInt(6) + 1); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ return 0; ++ } ++ // CraftBukkit end ++ double d0 = entityhuman.getX() - this.getX(); ++ double d1 = entityhuman.getY() - this.getY(); ++ double d2 = entityhuman.getZ() - this.getZ(); + double d3 = 0.1D; + +- itementity.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); +- this.level().addFreshEntity(itementity); +- player.level().addFreshEntity(new ExperienceOrb(player.level(), player.getX(), player.getY() + 0.5D, player.getZ() + 0.5D, this.random.nextInt(6) + 1)); ++ entityitem.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); ++ this.level().addFreshEntity(entityitem); ++ // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() ++ if (playerFishEvent.getExpToDrop() > 0) { ++ entityhuman.level().addFreshEntity(new ExperienceOrb(entityhuman.level(), entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop())); ++ } ++ // CraftBukkit end + if (itemstack1.is(ItemTags.FISHES)) { + player.awardStat(Stats.FISH_CAUGHT, 1); + } +@@ -487,8 +530,25 @@ + } + + if (this.onGround()) { ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.IN_GROUND); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ return 0; ++ } ++ // CraftBukkit end + i = 2; + } ++ // CraftBukkit start ++ if (i == 0) { ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.REEL_IN); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ if (playerFishEvent.isCancelled()) { ++ return 0; ++ } ++ } ++ // CraftBukkit end + + this.discard(); + return i; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/LargeFireball.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/LargeFireball.java.patch new file mode 100644 index 0000000000..99a6249186 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/LargeFireball.java.patch @@ -0,0 +1,60 @@ +--- a/net/minecraft/world/entity/projectile/LargeFireball.java ++++ b/net/minecraft/world/entity/projectile/LargeFireball.java +@@ -8,18 +8,21 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++import org.bukkit.event.entity.ExplosionPrimeEvent; // CraftBukkit + + public class LargeFireball extends Fireball { + + private int explosionPower = 1; + +- public LargeFireball(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public LargeFireball(EntityType entityType, Level level) { ++ super(entityType, level); ++ isIncendiary = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // CraftBukkit + } + + public LargeFireball(Level level, LivingEntity livingentity, double d0, double d1, double d2, int i) { + super(EntityType.FIREBALL, livingentity, d0, d1, d2, level); + this.explosionPower = i; ++ isIncendiary = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // CraftBukkit + } + + @Override +@@ -29,7 +31,15 @@ + if (!this.level().isClientSide) { + boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); + +- this.level().explode(this, this.getX(), this.getY(), this.getZ(), (float) this.explosionPower, flag, Level.ExplosionInteraction.MOB); ++ // CraftBukkit start - fire ExplosionPrimeEvent ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent((org.bukkit.entity.Explosive) this.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ // give 'this' instead of (Entity) null so we know what causes the damage ++ this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.MOB); ++ } ++ // CraftBukkit end + this.discard(); + } + +@@ -59,11 +67,11 @@ + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("ExplosionPower", 99)) { +- this.explosionPower = compoundtag.getByte("ExplosionPower"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("ExplosionPower", 99)) { ++ // CraftBukkit - set bukkitYield when setting explosionpower ++ bukkitYield = this.explosionPower = compound.getByte("ExplosionPower"); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/LlamaSpit.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/LlamaSpit.java.patch new file mode 100644 index 0000000000..3a0f211e17 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/LlamaSpit.java.patch @@ -0,0 +1,17 @@ +--- a/net/minecraft/world/entity/projectile/LlamaSpit.java ++++ b/net/minecraft/world/entity/projectile/LlamaSpit.java +@@ -33,10 +32,10 @@ + Vec3 vec3 = this.getDeltaMovement(); + HitResult hitresult = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); + +- this.onHit(hitresult); +- double d0 = this.getX() + vec3.x; +- double d1 = this.getY() + vec3.y; +- double d2 = this.getZ() + vec3.z; ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event ++ double d0 = this.getX() + vec3d.x; ++ double d1 = this.getY() + vec3d.y; ++ double d2 = this.getZ() + vec3d.z; + + this.updateRotation(); + float f = 0.99F; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/Projectile.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/Projectile.java.patch new file mode 100644 index 0000000000..7389e32773 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/Projectile.java.patch @@ -0,0 +1,69 @@ +--- a/net/minecraft/world/entity/projectile/Projectile.java ++++ b/net/minecraft/world/entity/projectile/Projectile.java +@@ -24,6 +24,9 @@ + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.projectiles.ProjectileSource; ++// CraftBukkit end + + public abstract class Projectile extends Entity implements TraceableEntity { + +@@ -34,8 +37,12 @@ + private boolean leftOwner; + private boolean hasBeenShot; + +- Projectile(EntityType entitytype, Level level) { +- super(entitytype, level); ++ // CraftBukkit start ++ private boolean hitCancelled = false; ++ // CraftBukkit end ++ ++ Projectile(EntityType entityType, Level level) { ++ super(entityType, level); + } + + public void setOwner(@Nullable Entity entity) { +@@ -43,6 +50,7 @@ + this.ownerUUID = entity.getUUID(); + this.cachedOwner = entity; + } ++ this.projectileSource = (owner != null && owner.getBukkitEntity() instanceof ProjectileSource) ? (ProjectileSource) owner.getBukkitEntity() : null; // CraftBukkit + + } + +@@ -172,8 +175,15 @@ + this.setDeltaMovement(this.getDeltaMovement().add(vec3.x, entity.onGround() ? 0.0D : vec3.y, vec3.z)); + } + +- protected void onHit(HitResult hitresult) { +- HitResult.Type hitresult_type = hitresult.getType(); ++ // CraftBukkit start - call projectile hit event ++ protected void preOnHit(HitResult movingobjectposition) { ++ org.bukkit.event.entity.ProjectileHitEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); ++ this.hitCancelled = event != null && event.isCancelled(); ++ if (movingobjectposition.getType() == HitResult.EnumMovingObjectType.BLOCK || !this.hitCancelled) { ++ this.onHit(movingobjectposition); ++ } ++ } ++ // CraftBukkit end + + if (hitresult_type == HitResult.Type.ENTITY) { + this.onHitEntity((EntityHitResult) hitresult); +@@ -191,8 +204,13 @@ + + protected void onHitEntity(EntityHitResult entityhitresult) {} + +- protected void onHitBlock(BlockHitResult blockhitresult) { +- BlockState blockstate = this.level().getBlockState(blockhitresult.getBlockPos()); ++ protected void onHitBlock(BlockHitResult result) { ++ // CraftBukkit start - cancellable hit event ++ if (hitCancelled) { ++ return; ++ } ++ // CraftBukkit end ++ IBlockData iblockdata = this.level().getBlockState(result.getBlockPos()); + + blockstate.onProjectileHit(this.level(), blockstate, blockhitresult, this); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ShulkerBullet.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ShulkerBullet.java.patch new file mode 100644 index 0000000000..4512f7190d --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ShulkerBullet.java.patch @@ -0,0 +1,61 @@ +--- a/net/minecraft/world/entity/projectile/ShulkerBullet.java ++++ b/net/minecraft/world/entity/projectile/ShulkerBullet.java +@@ -59,9 +59,22 @@ + this.moveTo(d0, d1, d2, this.getYRot(), this.getXRot()); + this.finalTarget = entity; + this.currentMoveDirection = Direction.UP; +- this.selectNextMoveDirection(direction_axis); ++ this.selectNextMoveDirection(axis); ++ projectileSource = (org.bukkit.entity.LivingEntity) shooter.getBukkitEntity(); // CraftBukkit + } + ++ // CraftBukkit start ++ public Entity getTarget() { ++ return this.finalTarget; ++ } ++ ++ public void setTarget(Entity e) { ++ this.finalTarget = e; ++ this.currentMoveDirection = Direction.UP; ++ this.selectNextMoveDirection(Direction.Axis.X); ++ } ++ // CraftBukkit end ++ + @Override + @Override + public SoundSource getSoundSource() { +@@ -230,8 +237,8 @@ + + HitResult hitresult = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); + +- if (hitresult.getType() != HitResult.Type.MISS) { +- this.onHit(hitresult); ++ if (movingobjectposition.getType() != HitResult.EnumMovingObjectType.MISS) { ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + } + } + +@@ -305,7 +307,7 @@ + if (entity instanceof LivingEntity) { + LivingEntity livingentity1 = (LivingEntity) entity; + +- livingentity1.addEffect(new MobEffectInstance(MobEffects.LEVITATION, 200), (Entity) MoreObjects.firstNonNull(entity1, this)); ++ entityliving1.addEffect(new MobEffectInstance(MobEffects.LEVITATION, 200), (Entity) MoreObjects.firstNonNull(entity1, this), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + +@@ -338,8 +337,12 @@ + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { ++ public boolean hurt(DamageSource source, float amount) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, false)) { ++ return false; ++ } ++ // CraftBukkit end + if (!this.level().isClientSide) { + this.playSound(SoundEvents.SHULKER_BULLET_HURT, 1.0F, 1.0F); + ((ServerLevel) this.level()).sendParticles(ParticleTypes.CRIT, this.getX(), this.getY(), this.getZ(), 15, 0.2D, 0.2D, 0.2D, 0.0D); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/SmallFireball.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/SmallFireball.java.patch new file mode 100644 index 0000000000..9ce39e4476 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/SmallFireball.java.patch @@ -0,0 +1,58 @@ +--- a/net/minecraft/world/entity/projectile/SmallFireball.java ++++ b/net/minecraft/world/entity/projectile/SmallFireball.java +@@ -12,6 +12,7 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; // CraftBukkit + + public class SmallFireball extends Fireball { + +@@ -19,8 +20,13 @@ + super(entitytype, level); + } + +- public SmallFireball(Level level, LivingEntity livingentity, double d0, double d1, double d2) { +- super(EntityType.SMALL_FIREBALL, livingentity, d0, d1, d2, level); ++ public SmallFireball(Level level, LivingEntity shooter, double offsetX, double d1, double offsetY) { ++ super(EntityType.SMALL_FIREBALL, shooter, offsetX, d1, offsetY, level); ++ // CraftBukkit start ++ if (this.getOwner() != null && this.getOwner() instanceof Mob) { ++ isIncendiary = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); ++ } ++ // CraftBukkit end + } + + public SmallFireball(Level level, double d0, double d1, double d2, double d3, double d4, double d5) { +@@ -36,7 +41,14 @@ + Entity entity1 = this.getOwner(); + int i = entity.getRemainingFireTicks(); + +- entity.setSecondsOnFire(5); ++ // CraftBukkit start - Entity damage by entity event + combust event ++ EntityCombustByEntityEvent event = new EntityCombustByEntityEvent((org.bukkit.entity.Projectile) this.getBukkitEntity(), entity.getBukkitEntity(), 5); ++ entity.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ entity.setSecondsOnFire(event.getDuration(), false); ++ } ++ // CraftBukkit end + if (!entity.hurt(this.damageSources().fireball(this, entity1), 5.0F)) { + entity.setRemainingFireTicks(i); + } else if (entity1 instanceof LivingEntity) { +@@ -53,11 +64,11 @@ + if (!this.level().isClientSide) { + Entity entity = this.getOwner(); + +- if (!(entity instanceof Mob) || this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- BlockPos blockpos = blockhitresult.getBlockPos().relative(blockhitresult.getDirection()); ++ if (isIncendiary) { // CraftBukkit ++ BlockPos blockposition = result.getBlockPos().relative(result.getDirection()); + +- if (this.level().isEmptyBlock(blockpos)) { +- this.level().setBlockAndUpdate(blockpos, BaseFireBlock.getState(this.level(), blockpos)); ++ if (this.level().isEmptyBlock(blockposition) && !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition, this).isCancelled()) { // CraftBukkit ++ this.level().setBlockAndUpdate(blockposition, BaseFireBlock.getState(this.level(), blockposition)); + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/SpectralArrow.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/SpectralArrow.java.patch new file mode 100644 index 0000000000..7797849d52 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/SpectralArrow.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/projectile/SpectralArrow.java ++++ b/net/minecraft/world/entity/projectile/SpectralArrow.java +@@ -43,7 +41,7 @@ + super.doPostHurtEffects(livingentity); + MobEffectInstance mobeffectinstance = new MobEffectInstance(MobEffects.GLOWING, this.duration, 0); + +- livingentity.addEffect(mobeffectinstance, this.getEffectSource()); ++ living.addEffect(mobeffect, this.getEffectSource(), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ARROW); // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrowableItemProjectile.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrowableItemProjectile.java.patch new file mode 100644 index 0000000000..34ac2052d7 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrowableItemProjectile.java.patch @@ -0,0 +1,17 @@ +--- a/net/minecraft/world/entity/projectile/ThrowableItemProjectile.java ++++ b/net/minecraft/world/entity/projectile/ThrowableItemProjectile.java +@@ -35,7 +35,13 @@ + + protected abstract Item getDefaultItem(); + +- protected ItemStack getItemRaw() { ++ // CraftBukkit start ++ public Item getDefaultItemPublic() { ++ return getDefaultItem(); ++ } ++ // CraftBukkit end ++ ++ public ItemStack getItemRaw() { + return (ItemStack) this.getEntityData().get(ThrowableItemProjectile.DATA_ITEM_STACK); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrowableProjectile.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrowableProjectile.java.patch new file mode 100644 index 0000000000..1b03fbb817 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrowableProjectile.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/entity/projectile/ThrowableProjectile.java ++++ b/net/minecraft/world/entity/projectile/ThrowableProjectile.java +@@ -67,8 +65,8 @@ + } + } + +- if (hitresult.getType() != HitResult.Type.MISS && !flag) { +- this.onHit(hitresult); ++ if (movingobjectposition.getType() != HitResult.EnumMovingObjectType.MISS && !flag) { ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + } + + this.checkInsideBlocks(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrownEgg.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrownEgg.java.patch new file mode 100644 index 0000000000..e6eaff52bb --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrownEgg.java.patch @@ -0,0 +1,73 @@ +--- a/net/minecraft/world/entity/projectile/ThrownEgg.java ++++ b/net/minecraft/world/entity/projectile/ThrownEgg.java +@@ -10,6 +5,16 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++import net.minecraft.core.particles.ItemParticleOption; ++import net.minecraft.core.particles.ParticleTypes; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.LivingEntity; ++import org.bukkit.entity.Ageable; ++import org.bukkit.entity.EntityType; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerEggThrowEvent; ++// CraftBukkit end + + public class ThrownEgg extends ThrowableItemProjectile { + +@@ -50,20 +52,47 @@ + protected void onHit(HitResult hitresult) { + super.onHit(hitresult); + if (!this.level().isClientSide) { +- if (this.random.nextInt(8) == 0) { ++ // CraftBukkit start ++ boolean hatching = this.random.nextInt(8) == 0; ++ if (true) { ++ // CraftBukkit end + byte b0 = 1; + + if (this.random.nextInt(32) == 0) { + b0 = 4; + } + ++ // CraftBukkit start ++ EntityType hatchingType = EntityType.CHICKEN; ++ ++ Entity shooter = this.getOwner(); ++ if (!hatching) { ++ b0 = 0; ++ } ++ if (shooter instanceof ServerPlayer) { ++ PlayerEggThrowEvent event = new PlayerEggThrowEvent((Player) shooter.getBukkitEntity(), (org.bukkit.entity.Egg) this.getBukkitEntity(), hatching, b0, hatchingType); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ b0 = event.getNumHatches(); ++ hatching = event.isHatching(); ++ hatchingType = event.getHatchingType(); ++ // If hatching is set to false, ensure child count is 0 ++ if (!hatching) { ++ b0 = 0; ++ } ++ } ++ // CraftBukkit end ++ + for (int i = 0; i < b0; ++i) { +- Chicken chicken = (Chicken) EntityType.CHICKEN.create(this.level()); ++ Entity entitychicken = this.level().getWorld().makeEntity(new org.bukkit.Location(this.level().getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F), hatchingType.getEntityClass()); // CraftBukkit + +- if (chicken != null) { +- chicken.setAge(-24000); +- chicken.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); +- this.level().addFreshEntity(chicken); ++ if (entitychicken != null) { ++ // CraftBukkit start ++ if (entitychicken.getBukkitEntity() instanceof Ageable) { ++ ((Ageable) entitychicken.getBukkitEntity()).setBaby(); ++ } ++ this.level().addFreshEntity(entitychicken, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrownEnderpearl.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrownEnderpearl.java.patch new file mode 100644 index 0000000000..5bf2ed6971 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrownEnderpearl.java.patch @@ -0,0 +1,56 @@ +--- a/net/minecraft/world/entity/projectile/ThrownEnderpearl.java ++++ b/net/minecraft/world/entity/projectile/ThrownEnderpearl.java +@@ -17,6 +17,12 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++// CraftBukkit end + + public class ThrownEnderpearl extends ThrowableItemProjectile { + +@@ -56,9 +59,12 @@ + if (entity instanceof ServerPlayer) { + ServerPlayer serverplayer = (ServerPlayer) entity; + +- if (serverplayer.connection.isAcceptingMessages() && serverplayer.level() == this.level() && !serverplayer.isSleeping()) { +- if (this.random.nextFloat() < 0.05F && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { +- Endermite endermite = (Endermite) EntityType.ENDERMITE.create(this.level()); ++ if (entityplayer.connection.isAcceptingMessages() && entityplayer.level() == this.level() && !entityplayer.isSleeping()) { ++ // CraftBukkit start - Fire PlayerTeleportEvent ++ org.bukkit.craftbukkit.entity.CraftPlayer player = entityplayer.getBukkitEntity(); ++ org.bukkit.Location location = getBukkitEntity().getLocation(); ++ location.setPitch(player.getLocation().getPitch()); ++ location.setYaw(player.getLocation().getYaw()); + + if (endermite != null) { + endermite.moveTo(entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot()); +@@ -72,8 +83,13 @@ + entity.teleportTo(this.getX(), this.getY(), this.getZ()); + } + +- entity.resetFallDistance(); +- entity.hurt(this.damageSources().fall(), 5.0F); ++ entityplayer.connection.teleport(teleEvent.getTo()); ++ entity.resetFallDistance(); ++ CraftEventFactory.entityDamage = this; ++ entity.hurt(this.damageSources().fall(), 5.0F); ++ CraftEventFactory.entityDamage = null; ++ } ++ // CraftBukkit end + this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_TELEPORT, SoundSource.PLAYERS); + } + } else if (entity != null) { +@@ -105,7 +119,7 @@ + public Entity changeDimension(ServerLevel serverlevel) { + Entity entity = this.getOwner(); + +- if (entity != null && entity.level().dimension() != serverlevel.dimension()) { ++ if (entity != null && server != null && entity.level().dimension() != server.dimension()) { // CraftBukkit - SPIGOT-6113 + this.setOwner((Entity) null); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java.patch new file mode 100644 index 0000000000..8ba925a0b9 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java ++++ b/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java +@@ -42,9 +39,18 @@ + protected void onHit(HitResult hitresult) { + super.onHit(hitresult); + if (this.level() instanceof ServerLevel) { +- this.level().levelEvent(2002, this.blockPosition(), PotionUtils.getColor(Potions.WATER)); ++ // CraftBukkit - moved to after event ++ // this.level().levelEvent(2002, this.blockPosition(), PotionUtil.getColor(Potions.WATER)); + int i = 3 + this.level().random.nextInt(5) + this.level().random.nextInt(5); + ++ // CraftBukkit start ++ org.bukkit.event.entity.ExpBottleEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExpBottleEvent(this, result, i); ++ i = event.getExperience(); ++ if (event.getShowEffect()) { ++ this.level().levelEvent(2002, this.blockPosition(), PotionUtils.getColor(Potions.WATER)); ++ } ++ // CraftBukkit end ++ + ExperienceOrb.award((ServerLevel) this.level(), this.position(), i); + this.discard(); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrownPotion.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrownPotion.java.patch new file mode 100644 index 0000000000..290501b436 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrownPotion.java.patch @@ -0,0 +1,169 @@ +--- a/net/minecraft/world/entity/projectile/ThrownPotion.java ++++ b/net/minecraft/world/entity/projectile/ThrownPotion.java +@@ -30,6 +29,16 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++// CraftBukkit start ++import java.util.HashMap; ++import java.util.Map; ++import net.minecraft.world.effect.MobEffects; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.CampfireBlock; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.entity.LivingEntity; ++// CraftBukkit end + + public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplier { + +@@ -103,11 +108,11 @@ + + if (flag) { + this.applyWater(); +- } else if (!list.isEmpty()) { ++ } else if (true || !list.isEmpty()) { // CraftBukkit - Call event even if no effects to apply + if (this.isLingering()) { +- this.makeAreaOfEffectCloud(itemstack, potion); ++ this.makeAreaOfEffectCloud(itemstack, potionregistry, result); // CraftBukkit - Pass MovingObjectPosition + } else { +- this.applySplash(list, hitresult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitresult).getEntity() : null); ++ this.applySplash(list, result.getType() == HitResult.EnumMovingObjectType.ENTITY ? ((EntityHitResult) result).getEntity() : null, result); // CraftBukkit - Pass MovingObjectPosition + } + } + +@@ -149,9 +154,10 @@ + + } + +- private void applySplash(List list, @Nullable Entity entity) { +- AABB aabb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D); +- List list1 = this.level().getEntitiesOfClass(LivingEntity.class, aabb); ++ private void applySplash(List list, @Nullable Entity entity, HitResult position) { // CraftBukkit - Pass MovingObjectPosition ++ AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D); ++ List list1 = this.level().getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb); ++ Map affected = new HashMap(); // CraftBukkit + + if (!list1.isEmpty()) { + Entity entity1 = this.getEffectSource(); +@@ -172,34 +178,55 @@ + d1 = 1.0D - Math.sqrt(d0) / 4.0D; + } + +- Iterator iterator1 = list.iterator(); ++ // CraftBukkit start ++ affected.put((LivingEntity) entityliving.getBukkitEntity(), d1); ++ } ++ } ++ } ++ } + + while (iterator1.hasNext()) { + MobEffectInstance mobeffectinstance = (MobEffectInstance) iterator1.next(); + MobEffect mobeffect = mobeffectinstance.getEffect(); + +- if (mobeffect.isInstantenous()) { +- mobeffect.applyInstantenousEffect(this, this.getOwner(), livingentity, mobeffectinstance.getAmplifier(), d1); +- } else { +- int i = mobeffectinstance.mapDuration((j) -> { +- return (int) (d1 * (double) j + 0.5D); +- }); +- MobEffectInstance mobeffectinstance1 = new MobEffectInstance(mobeffect, i, mobeffectinstance.getAmplifier(), mobeffectinstance.isAmbient(), mobeffectinstance.isVisible()); ++ net.minecraft.world.entity.LivingEntity entityliving = ((CraftLivingEntity) victim).getHandle(); ++ double d1 = event.getIntensity(victim); ++ // CraftBukkit end + +- if (!mobeffectinstance1.endsWithin(20)) { +- livingentity.addEffect(mobeffectinstance1, entity1); +- } +- } ++ Iterator iterator1 = list.iterator(); ++ ++ while (iterator1.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator1.next(); ++ MobEffect mobeffectlist = mobeffect.getEffect(); ++ // CraftBukkit start - Abide by PVP settings - for players only! ++ if (!this.level().pvpMode && this.getOwner() instanceof ServerPlayer && entityliving instanceof ServerPlayer && entityliving != this.getOwner()) { ++ if (mobeffectlist == MobEffects.MOVEMENT_SLOWDOWN || mobeffectlist == MobEffects.DIG_SLOWDOWN || mobeffectlist == MobEffects.HARM || mobeffectlist == MobEffects.BLINDNESS ++ || mobeffectlist == MobEffects.HUNGER || mobeffectlist == MobEffects.WEAKNESS || mobeffectlist == MobEffects.POISON) { ++ continue; + } + } ++ // CraftBukkit end ++ ++ if (mobeffectlist.isInstantenous()) { ++ mobeffectlist.applyInstantenousEffect(this, this.getOwner(), entityliving, mobeffect.getAmplifier(), d1); ++ } else { ++ int i = mobeffect.mapDuration((j) -> { ++ return (int) (d1 * (double) j + 0.5D); ++ }); ++ MobEffectInstance mobeffect1 = new MobEffectInstance(mobeffectlist, i, mobeffect.getAmplifier(), mobeffect.isAmbient(), mobeffect.isVisible()); ++ ++ if (!mobeffect1.endsWithin(20)) { ++ entityliving.addEffect(mobeffect1, entity1, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_SPLASH); // CraftBukkit ++ } ++ } + } + } + } + + } + +- private void makeAreaOfEffectCloud(ItemStack itemstack, Potion potion) { +- AreaEffectCloud areaeffectcloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); ++ private void makeAreaOfEffectCloud(ItemStack itemstack, Potion potionregistry, HitResult position) { // CraftBukkit - Pass MovingObjectPosition ++ AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); + Entity entity = this.getOwner(); + + if (entity instanceof LivingEntity) { +@@ -225,7 +256,14 @@ + areaeffectcloud.setFixedColor(compoundtag.getInt("CustomPotionColor")); + } + +- this.level().addFreshEntity(areaeffectcloud); ++ // CraftBukkit start ++ org.bukkit.event.entity.LingeringPotionSplashEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callLingeringPotionSplashEvent(this, position, entityareaeffectcloud); ++ if (!(event.isCancelled() || entityareaeffectcloud.isRemoved())) { ++ this.level().addFreshEntity(entityareaeffectcloud); ++ } else { ++ entityareaeffectcloud.discard(); ++ } ++ // CraftBukkit end + } + + private boolean isLingering() { +@@ -235,14 +273,26 @@ + private void dowseFire(BlockPos blockpos) { + BlockState blockstate = this.level().getBlockState(blockpos); + +- if (blockstate.is(BlockTags.FIRE)) { +- this.level().destroyBlock(blockpos, false, this); +- } else if (AbstractCandleBlock.isLit(blockstate)) { +- AbstractCandleBlock.extinguish((Player) null, blockstate, this.level(), blockpos); +- } else if (CampfireBlock.isLitCampfire(blockstate)) { +- this.level().levelEvent((Player) null, 1009, blockpos, 0); +- CampfireBlock.dowse(this.getOwner(), this.level(), blockpos, blockstate); +- this.level().setBlockAndUpdate(blockpos, (BlockState) blockstate.setValue(CampfireBlock.LIT, false)); ++ if (iblockdata.is(BlockTags.FIRE)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityChangeBlockEvent(this, pos, Blocks.AIR.defaultBlockState())) { ++ this.level().destroyBlock(pos, false, this); ++ } ++ // CraftBukkit end ++ } else if (AbstractCandleBlock.isLit(iblockdata)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityChangeBlockEvent(this, pos, iblockdata.setValue(AbstractCandleBlock.LIT, false))) { ++ AbstractCandleBlock.extinguish((Player) null, iblockdata, this.level(), pos); ++ } ++ // CraftBukkit end ++ } else if (CampfireBlock.isLitCampfire(iblockdata)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityChangeBlockEvent(this, pos, iblockdata.setValue(CampfireBlock.LIT, false))) { ++ this.level().levelEvent((Player) null, 1009, pos, 0); ++ CampfireBlock.dowse(this.getOwner(), this.level(), pos, iblockdata); ++ this.level().setBlockAndUpdate(pos, (IBlockData) iblockdata.setValue(CampfireBlock.LIT, false)); ++ } ++ // CraftBukkit end + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrownTrident.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrownTrident.java.patch new file mode 100644 index 0000000000..e222409598 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/ThrownTrident.java.patch @@ -0,0 +1,19 @@ +--- a/net/minecraft/world/entity/projectile/ThrownTrident.java ++++ b/net/minecraft/world/entity/projectile/ThrownTrident.java +@@ -154,11 +150,11 @@ + if (this.level().canSeeSky(blockpos)) { + LightningBolt lightningbolt = (LightningBolt) EntityType.LIGHTNING_BOLT.create(this.level()); + +- if (lightningbolt != null) { +- lightningbolt.moveTo(Vec3.atBottomCenterOf(blockpos)); +- lightningbolt.setCause(entity1 instanceof ServerPlayer ? (ServerPlayer) entity1 : null); +- this.level().addFreshEntity(lightningbolt); +- soundevent = SoundEvents.TRIDENT_THUNDER; ++ if (entitylightning != null) { ++ entitylightning.moveTo(Vec3.atBottomCenterOf(blockposition)); ++ entitylightning.setCause(entity1 instanceof ServerPlayer ? (ServerPlayer) entity1 : null); ++ ((ServerLevel) this.level()).strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.TRIDENT); // CraftBukkit ++ soundeffect = SoundEvents.TRIDENT_THUNDER; + f1 = 5.0F; + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/WindCharge.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/WindCharge.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/WindCharge.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/WitherSkull.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/WitherSkull.java.patch new file mode 100644 index 0000000000..9fad777d0e --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/projectile/WitherSkull.java.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/world/entity/projectile/WitherSkull.java ++++ b/net/minecraft/world/entity/projectile/WitherSkull.java +@@ -20,6 +20,9 @@ + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++// CraftBukkit start ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end + + public class WitherSkull extends AbstractHurtingProjectile { + +@@ -68,7 +67,7 @@ + if (entity.isAlive()) { + this.doEnchantDamageEffects(livingentity, entity); + } else { +- livingentity.heal(5.0F); ++ entityliving.heal(5.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.WITHER); // CraftBukkit + } + } + } else { +@@ -86,7 +85,7 @@ + } + + if (b0 > 0) { +- livingentity.addEffect(new MobEffectInstance(MobEffects.WITHER, 20 * b0, 1), this.getEffectSource()); ++ entityliving.addEffect(new MobEffectInstance(MobEffects.WITHER, 20 * b0, 1), this.getEffectSource(), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + +@@ -98,7 +96,15 @@ + protected void onHit(HitResult hitresult) { + super.onHit(hitresult); + if (!this.level().isClientSide) { +- this.level().explode(this, this.getX(), this.getY(), this.getZ(), 1.0F, false, Level.ExplosionInteraction.MOB); ++ // CraftBukkit start ++ // this.level().explode(this, this.getX(), this.getY(), this.getZ(), 1.0F, false, World.a.MOB); ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), 1.0F, false); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.MOB); ++ } ++ // CraftBukkit end + this.discard(); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/raid/Raid.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/raid/Raid.java.patch new file mode 100644 index 0000000000..8db1d9c988 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/raid/Raid.java.patch @@ -0,0 +1,155 @@ +--- a/net/minecraft/world/entity/raid/Raid.java ++++ b/net/minecraft/world/entity/raid/Raid.java +@@ -176,6 +176,12 @@ + return this.status == Raid.RaidStatus.LOSS; + } + ++ // CraftBukkit start ++ public boolean isInProgress() { ++ return this.status == RaidStatus.ONGOING; ++ } ++ // CraftBukkit end ++ + public float getTotalHealth() { + return this.totalHealth; + } +@@ -272,6 +278,7 @@ + + this.active = this.level.hasChunkAt(this.center); + if (this.level.getDifficulty() == Difficulty.PEACEFUL) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.PEACE); // CraftBukkit + this.stop(); + return; + } +@@ -291,13 +298,16 @@ + if (!this.level.isVillage(this.center)) { + if (this.groupsSpawned > 0) { + this.status = Raid.RaidStatus.LOSS; ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidFinishEvent(this, new java.util.ArrayList<>()); // CraftBukkit + } else { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.NOT_IN_VILLAGE); // CraftBukkit + this.stop(); + } + } + + ++this.ticksActive; + if (this.ticksActive >= 48000L) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.TIMEOUT); // CraftBukkit + this.stop(); + return; + } +@@ -371,6 +381,7 @@ + } + + if (j > 3) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.UNSPAWNABLE); // CraftBukkit + this.stop(); + break; + } +@@ -383,6 +394,7 @@ + this.status = Raid.RaidStatus.VICTORY; + Iterator iterator = this.heroesOfTheVillage.iterator(); + ++ List winners = new java.util.ArrayList<>(); // CraftBukkit + while (iterator.hasNext()) { + UUID uuid = (UUID) iterator.next(); + Entity entity = this.level.getEntity(uuid); +@@ -395,12 +407,14 @@ + if (livingentity instanceof ServerPlayer) { + ServerPlayer serverplayer = (ServerPlayer) livingentity; + +- serverplayer.awardStat(Stats.RAID_WIN); +- CriteriaTriggers.RAID_WIN.trigger(serverplayer); ++ entityplayer.awardStat(Stats.RAID_WIN); ++ CriteriaTriggers.RAID_WIN.trigger(entityplayer); ++ winners.add(entityplayer.getBukkitEntity()); // CraftBukkit + } + } + } + } ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidFinishEvent(this, winners); // CraftBukkit + } + } + +@@ -408,6 +422,7 @@ + } else if (this.isOver()) { + ++this.celebrationTicks; + if (this.celebrationTicks >= 600) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.FINISHED); // CraftBukkit + this.stop(); + return; + } +@@ -544,6 +559,10 @@ + int j = araid_raidertype.length; + int k = 0; + ++ // CraftBukkit start ++ Raider leader = null; ++ List raiders = new java.util.ArrayList<>(); ++ // CraftBukkit end + while (k < j) { + Raid.RaiderType raid_raidertype = araid_raidertype[k]; + int l = this.getDefaultNumSpawns(raid_raidertype, i, flag1) + this.getPotentialBonusSpawns(raid_raidertype, this.random, i, difficultyinstance, flag1); +@@ -559,11 +578,13 @@ + raider.setPatrolLeader(true); + this.setLeader(i, raider); + flag = true; ++ leader = entityraider; // CraftBukkit + } + +- this.joinRaid(i, raider, blockpos, false); +- if (raid_raidertype.entityType == EntityType.RAVAGER) { +- Raider raider1 = null; ++ this.joinRaid(i, entityraider, pos, false); ++ raiders.add(entityraider); // CraftBukkit ++ if (raid_wave.entityType == EntityType.RAVAGER) { ++ Raider entityraider1 = null; + + if (i == this.getNumGroups(Difficulty.NORMAL)) { + raider1 = (Raider) EntityType.PILLAGER.create(this.level); +@@ -576,10 +597,11 @@ + } + + ++i1; +- if (raider1 != null) { +- this.joinRaid(i, raider1, blockpos, false); +- raider1.moveTo(blockpos, 0.0F, 0.0F); +- raider1.startRiding(raider); ++ if (entityraider1 != null) { ++ this.joinRaid(i, entityraider1, pos, false); ++ entityraider1.moveTo(pos, 0.0F, 0.0F); ++ entityraider1.startRiding(entityraider); ++ raiders.add(entityraider); // CraftBukkit + } + } + +@@ -597,6 +619,7 @@ + ++this.groupsSpawned; + this.updateBossbar(); + this.setDirty(); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidSpawnWaveEvent(this, leader, raiders); // CraftBukkit + } + + public void joinRaid(int i, Raider raider, @Nullable BlockPos blockpos, boolean flag) { +@@ -612,7 +635,7 @@ + raider.finalizeSpawn(this.level, this.level.getCurrentDifficultyAt(blockpos), MobSpawnType.EVENT, (SpawnGroupData) null, (CompoundTag) null); + raider.applyRaidBuffs(i, false); + raider.setOnGround(true); +- this.level.addFreshEntityWithPassengers(raider); ++ this.level.addFreshEntityWithPassengers(raider, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.RAID); // CraftBukkit + } + } + +@@ -862,6 +885,12 @@ + this.heroesOfTheVillage.add(entity.getUUID()); + } + ++ // CraftBukkit start - a method to get all raiders ++ public java.util.Collection getRaiders() { ++ return this.groupRaiderMap.values().stream().flatMap(Set::stream).collect(java.util.stream.Collectors.toSet()); ++ } ++ // CraftBukkit end ++ + private static enum RaidStatus { + + ONGOING, VICTORY, LOSS, STOPPED; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/raid/Raider.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/raid/Raider.java.patch new file mode 100644 index 0000000000..17f7705f6e --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/raid/Raider.java.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/entity/raid/Raider.java ++++ b/net/minecraft/world/entity/raid/Raider.java +@@ -170,7 +165,7 @@ + MobEffectInstance mobeffectinstance1 = new MobEffectInstance(MobEffects.BAD_OMEN, 120000, i, false, false, true); + + if (!this.level().getGameRules().getBoolean(GameRules.RULE_DISABLE_RAIDS)) { +- player.addEffect(mobeffectinstance1); ++ entityhuman.addEffect(mobeffect1, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN); // CraftBukkit + } + } + } +@@ -547,7 +521,7 @@ + while (iterator.hasNext()) { + Raider raider = (Raider) iterator.next(); + +- raider.setTarget(this.mob.getTarget()); ++ entityraider.setTarget(this.mob.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.FOLLOW_LEADER, true); // CraftBukkit + } + + } +@@ -565,8 +538,8 @@ + while (iterator.hasNext()) { + Raider raider = (Raider) iterator.next(); + +- raider.setTarget(livingentity); +- raider.setAggressive(true); ++ entityraider.setTarget(this.mob.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.FOLLOW_LEADER, true); // CraftBukkit ++ entityraider.setAggressive(true); + } + + this.mob.setAggressive(true); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/raid/Raids.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/raid/Raids.java.patch new file mode 100644 index 0000000000..e1975b1818 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/raid/Raids.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/entity/raid/Raids.java ++++ b/net/minecraft/world/entity/raid/Raids.java +@@ -121,21 +121,34 @@ + boolean flag = false; + + if (!raid.isStarted()) { ++ /* CraftBukkit - moved down + if (!this.raidMap.containsKey(raid.getId())) { + this.raidMap.put(raid.getId(), raid); + } + + flag = true; +- } else if (raid.getBadOmenLevel() < raid.getMaxBadOmenLevel()) { ++ // CraftBukkit start - fixed a bug with raid: players could add up Bad Omen level even when the raid had finished ++ } else if (raid.isInProgress() && raid.getBadOmenLevel() < raid.getMaxBadOmenLevel()) { + flag = true; ++ // CraftBukkit end + } else { + serverplayer.removeEffect(MobEffects.BAD_OMEN); + serverplayer.connection.send(new ClientboundEntityEventPacket(serverplayer, (byte) 43)); + } + + if (flag) { +- raid.absorbBadOmen(serverplayer); +- serverplayer.connection.send(new ClientboundEntityEventPacket(serverplayer, (byte) 43)); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callRaidTriggerEvent(raid, serverPlayer)) { ++ serverPlayer.removeEffect(MobEffects.BAD_OMEN); ++ return null; ++ } ++ ++ if (!this.raidMap.containsKey(raid.getId())) { ++ this.raidMap.put(raid.getId(), raid); ++ } ++ // CraftBukkit end ++ raid.absorbBadOmen(serverPlayer); ++ serverPlayer.connection.send(new ClientboundEntityEventPacket(serverPlayer, (byte) 43)); + if (!raid.hasFirstWaveSpawned()) { + serverplayer.awardStat(Stats.RAID_TRIGGER); + CriteriaTriggers.BAD_OMEN.trigger(serverplayer); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/AbstractMinecart.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/AbstractMinecart.java.patch new file mode 100644 index 0000000000..89898296d1 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/AbstractMinecart.java.patch @@ -0,0 +1,207 @@ +--- a/net/minecraft/world/entity/vehicle/AbstractMinecart.java ++++ b/net/minecraft/world/entity/vehicle/AbstractMinecart.java +@@ -48,6 +48,14 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.Vehicle; ++import org.bukkit.event.vehicle.VehicleEntityCollisionEvent; ++import org.bukkit.util.Vector; ++// CraftBukkit end ++ + public abstract class AbstractMinecart extends VehicleEntity { + + private static final float LOWERED_PASSENGER_ATTACHMENT_Y = 0.0F; +@@ -88,8 +96,19 @@ + enummap.put(RailShape.NORTH_EAST, Pair.of(vec3i2, vec3i1)); + }); + +- protected AbstractMinecart(EntityType entitytype, Level level) { +- super(entitytype, level); ++ // CraftBukkit start ++ public boolean slowWhenEmpty = true; ++ private double derailedX = 0.5; ++ private double derailedY = 0.5; ++ private double derailedZ = 0.5; ++ private double flyingX = 0.95; ++ private double flyingY = 0.95; ++ private double flyingZ = 0.95; ++ public double maxSpeed = 0.4D; ++ // CraftBukkit end ++ ++ protected AbstractMinecart(EntityType entityType, Level level) { ++ super(entityType, level); + this.targetDeltaMovement = Vec3.ZERO; + this.blocksBuilding = true; + } +@@ -279,6 +286,14 @@ + @Override + @Override + public void tick() { ++ // CraftBukkit start ++ double prevX = this.getX(); ++ double prevY = this.getY(); ++ double prevZ = this.getZ(); ++ float prevYaw = this.getYRot(); ++ float prevPitch = this.getXRot(); ++ // CraftBukkit end ++ + if (this.getHurtTime() > 0) { + this.setHurtTime(this.getHurtTime() - 1); + } +@@ -288,7 +303,7 @@ + } + + this.checkBelowWorld(); +- this.handleNetherPortal(); ++ // this.handleNetherPortal(); // CraftBukkit - handled in postTick + if (this.level().isClientSide) { + if (this.lerpSteps > 0) { + this.lerpPositionAndRotationStep(this.lerpSteps, this.lerpX, this.lerpY, this.lerpZ, this.lerpYRot, this.lerpXRot); +@@ -346,7 +361,19 @@ + } + + this.setRot(this.getYRot(), this.getXRot()); +- if (this.getMinecartType() == AbstractMinecart.Type.RIDEABLE && this.getDeltaMovement().horizontalDistanceSqr() > 0.01D) { ++ // CraftBukkit start ++ org.bukkit.World bworld = this.level().getWorld(); ++ Location from = new Location(bworld, prevX, prevY, prevZ, prevYaw, prevPitch); ++ Location to = CraftLocation.toBukkit(this.position(), bworld, this.getYRot(), this.getXRot()); ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ ++ this.level().getCraftServer().getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleUpdateEvent(vehicle)); ++ ++ if (!from.equals(to)) { ++ this.level().getCraftServer().getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleMoveEvent(vehicle, from, to)); ++ } ++ // CraftBukkit end ++ if (this.getMinecartType() == AbstractMinecart.EnumMinecartType.RIDEABLE && this.getDeltaMovement().horizontalDistanceSqr() > 0.01D) { + List list = this.level().getEntities((Entity) this, this.getBoundingBox().inflate(0.20000000298023224D, 0.0D, 0.20000000298023224D), EntitySelector.pushableBy(this)); + + if (!list.isEmpty()) { +@@ -356,8 +383,26 @@ + Entity entity = (Entity) iterator.next(); + + if (!(entity instanceof Player) && !(entity instanceof IronGolem) && !(entity instanceof AbstractMinecart) && !this.isVehicle() && !entity.isPassenger()) { ++ // CraftBukkit start ++ VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(collisionEvent); ++ ++ if (collisionEvent.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end + entity.startRiding(this); + } else { ++ // CraftBukkit start ++ if (!this.isPassengerOfSameVehicle(entity)) { ++ VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(collisionEvent); ++ ++ if (collisionEvent.isCancelled()) { ++ continue; ++ } ++ } ++ // CraftBukkit end + entity.push(this); + } + } +@@ -369,6 +414,14 @@ + Entity entity1 = (Entity) iterator1.next(); + + if (!this.hasPassenger(entity1) && entity1.isPushable() && entity1 instanceof AbstractMinecart) { ++ // CraftBukkit start ++ VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, entity1.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(collisionEvent); ++ ++ if (collisionEvent.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end + entity1.push(this); + } + } +@@ -385,7 +438,7 @@ + } + + protected double getMaxSpeed() { +- return (this.isInWater() ? 4.0D : 8.0D) / 20.0D; ++ return (this.isInWater() ? this.maxSpeed / 2.0D: this.maxSpeed); // CraftBukkit + } + + public void activateMinecart(int i, int j, int k, boolean flag) {} +@@ -396,12 +449,16 @@ + + this.setDeltaMovement(Mth.clamp(vec3.x, -d0, d0), vec3.y, Mth.clamp(vec3.z, -d0, d0)); + if (this.onGround()) { +- this.setDeltaMovement(this.getDeltaMovement().scale(0.5D)); ++ // CraftBukkit start - replace magic numbers with our variables ++ this.setDeltaMovement(new Vec3(this.getDeltaMovement().x * this.derailedX, this.getDeltaMovement().y * this.derailedY, this.getDeltaMovement().z * this.derailedZ)); ++ // CraftBukkit end + } + + this.move(MoverType.SELF, this.getDeltaMovement()); + if (!this.onGround()) { +- this.setDeltaMovement(this.getDeltaMovement().scale(0.95D)); ++ // CraftBukkit start - replace magic numbers with our variables ++ this.setDeltaMovement(new Vec3(this.getDeltaMovement().x * this.flyingX, this.getDeltaMovement().y * this.flyingY, this.getDeltaMovement().z * this.flyingZ)); ++ // CraftBukkit end + } + + } +@@ -598,8 +654,8 @@ + } + + protected void applyNaturalSlowdown() { +- double d0 = this.isVehicle() ? 0.997D : 0.96D; +- Vec3 vec3 = this.getDeltaMovement(); ++ double d0 = this.isVehicle() || !this.slowWhenEmpty ? 0.997D : 0.96D; // CraftBukkit - add !this.slowWhenEmpty ++ Vec3 vec3d = this.getDeltaMovement(); + + vec3 = vec3.multiply(d0, 0.0D, d0); + if (this.isInWater()) { +@@ -741,6 +793,14 @@ + if (!this.level().isClientSide) { + if (!entity.noPhysics && !this.noPhysics) { + if (!this.hasPassenger(entity)) { ++ // CraftBukkit start ++ VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(collisionEvent); ++ ++ if (collisionEvent.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + double d0 = entity.getX() - this.getX(); + double d1 = entity.getZ() - this.getZ(); + double d2 = d0 * d0 + d1 * d1; +@@ -923,4 +975,26 @@ + + private Type() {} + } ++ ++ // CraftBukkit start - Methods for getting and setting flying and derailed velocity modifiers ++ public Vector getFlyingVelocityMod() { ++ return new Vector(flyingX, flyingY, flyingZ); ++ } ++ ++ public void setFlyingVelocityMod(Vector flying) { ++ flyingX = flying.getX(); ++ flyingY = flying.getY(); ++ flyingZ = flying.getZ(); ++ } ++ ++ public Vector getDerailedVelocityMod() { ++ return new Vector(derailedX, derailedY, derailedZ); ++ } ++ ++ public void setDerailedVelocityMod(Vector derailed) { ++ derailedX = derailed.getX(); ++ derailedY = derailed.getY(); ++ derailedZ = derailed.getZ(); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java.patch new file mode 100644 index 0000000000..513d659d35 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java.patch @@ -0,0 +1,51 @@ +--- a/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java ++++ b/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java +@@ -17,6 +17,13 @@ + import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end + + public abstract class AbstractMinecartContainer extends AbstractMinecart implements ContainerEntity { + +@@ -25,9 +32,12 @@ + private ResourceLocation lootTable; + private long lootTableSeed; + +- protected AbstractMinecartContainer(EntityType entitytype, Level level) { +- super(entitytype, level); +- this.itemStacks = NonNullList.withSize(36, ItemStack.EMPTY); ++ // CraftBukkit start ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.itemStacks; + } + + protected AbstractMinecartContainer(EntityType entitytype, double d0, double d1, double d2, Level level) { +@@ -41,7 +71,18 @@ + super.destroy(damagesource); + this.chestVehicleDestroyed(damagesource, this.level(), this); + } ++ // CraftBukkit end + ++ protected AbstractMinecartContainer(EntityType entityType, Level level) { ++ super(entityType, level); ++ this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); // CraftBukkit - SPIGOT-3513 ++ } ++ ++ protected AbstractMinecartContainer(EntityType entityType, double x, double d1, double y, Level world) { ++ super(entityType, world, x, d1, y); ++ this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); // CraftBukkit - SPIGOT-3513 ++ } ++ + @Override + @Override + public ItemStack getItem(int i) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/Boat.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/Boat.java.patch new file mode 100644 index 0000000000..341637cd7d --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/Boat.java.patch @@ -0,0 +1,118 @@ +--- a/net/minecraft/world/entity/vehicle/Boat.java ++++ b/net/minecraft/world/entity/vehicle/Boat.java +@@ -55,6 +55,15 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.Vehicle; ++import org.bukkit.event.vehicle.VehicleDestroyEvent; ++import org.bukkit.event.vehicle.VehicleEntityCollisionEvent; ++import org.bukkit.event.vehicle.VehicleMoveEvent; ++// CraftBukkit end ++ + public class Boat extends VehicleEntity implements VariantHolder { + + private static final EntityDataAccessor DATA_ID_TYPE = SynchedEntityData.defineId(Boat.class, EntityDataSerializers.INT); +@@ -92,8 +101,16 @@ + private float bubbleAngle; + private float bubbleAngleO; + +- public Boat(EntityType entitytype, Level level) { +- super(entitytype, level); ++ // CraftBukkit start ++ // PAIL: Some of these haven't worked since a few updates, and since 1.9 they are less and less applicable. ++ public double maxSpeed = 0.4D; ++ public double occupiedDeceleration = 0.2D; ++ public double unoccupiedDeceleration = -1; ++ public boolean landBoats = false; ++ // CraftBukkit end ++ ++ public Boat(EntityType entityType, Level level) { ++ super(entityType, level); + this.paddlePositions = new float[2]; + this.blocksBuilding = true; + } +@@ -202,9 +209,29 @@ + public void push(Entity entity) { + if (entity instanceof Boat) { + if (entity.getBoundingBox().minY < this.getBoundingBox().maxY) { ++ // CraftBukkit start ++ if (!this.isPassengerOfSameVehicle(entity)) { ++ VehicleEntityCollisionEvent event = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + super.push(entity); + } + } else if (entity.getBoundingBox().minY <= this.getBoundingBox().minY) { ++ // CraftBukkit start ++ if (!this.isPassengerOfSameVehicle(entity)) { ++ VehicleEntityCollisionEvent event = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + super.push(entity); + } + +@@ -308,6 +325,7 @@ + return this.getDirection().getClockWise(); + } + ++ private Location lastLocation; // CraftBukkit + @Override + @Override + public void tick() { +@@ -349,6 +366,22 @@ + this.setDeltaMovement(Vec3.ZERO); + } + ++ // CraftBukkit start ++ org.bukkit.Server server = this.level().getCraftServer(); ++ org.bukkit.World bworld = this.level().getWorld(); ++ ++ Location to = CraftLocation.toBukkit(this.position(), bworld, this.getYRot(), this.getXRot()); ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ ++ server.getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleUpdateEvent(vehicle)); ++ ++ if (lastLocation != null && !lastLocation.equals(to)) { ++ VehicleMoveEvent event = new VehicleMoveEvent(vehicle, lastLocation, to); ++ server.getPluginManager().callEvent(event); ++ } ++ lastLocation = vehicle.getLocation(); ++ // CraftBukkit end ++ + this.tickBubbleColumn(); + + for (int i = 0; i <= 1; ++i) { +@@ -841,6 +867,11 @@ + + this.causeFallDamage(this.fallDistance, 1.0F, this.damageSources().fall()); + if (!this.level().isClientSide && !this.isRemoved()) { ++ // CraftBukkit start ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, null); ++ this.level().getCraftServer().getPluginManager().callEvent(destroyEvent); ++ if (!destroyEvent.isCancelled()) { + this.kill(); + if (this.level().getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { + int i; +@@ -854,6 +885,7 @@ + } + } + } ++ } // CraftBukkit end + } + + this.resetFallDistance(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/ChestBoat.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/ChestBoat.java.patch new file mode 100644 index 0000000000..f287bad03c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/ChestBoat.java.patch @@ -0,0 +1,68 @@ +--- a/net/minecraft/world/entity/vehicle/ChestBoat.java ++++ b/net/minecraft/world/entity/vehicle/ChestBoat.java +@@ -23,6 +23,13 @@ + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end + + public class ChestBoat extends Boat implements HasCustomInventoryScreen, ContainerEntity { + +@@ -264,4 +245,51 @@ + public void stopOpen(Player player) { + this.level().gameEvent(GameEvent.CONTAINER_CLOSE, this.position(), GameEvent.Context.of((Entity) player)); + } ++ ++ // CraftBukkit start ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ @Override ++ public List getContents() { ++ return this.itemStacks; ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public InventoryHolder getOwner() { ++ org.bukkit.entity.Entity entity = getBukkitEntity(); ++ if (entity instanceof InventoryHolder) return (InventoryHolder) entity; ++ return null; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ @Override ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return getBukkitEntity().getLocation(); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java.patch new file mode 100644 index 0000000000..6027706fe1 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java ++++ b/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java +@@ -158,5 +143,12 @@ + public boolean isValid() { + return !MinecartCommandBlock.this.isRemoved(); + } ++ ++ // CraftBukkit start ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return (org.bukkit.craftbukkit.entity.CraftMinecartCommand) MinecartCommandBlock.this.getBukkitEntity(); ++ } ++ // CraftBukkit end + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/MinecartTNT.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/MinecartTNT.java.patch new file mode 100644 index 0000000000..1ad988dd1c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/MinecartTNT.java.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/world/entity/vehicle/MinecartTNT.java ++++ b/net/minecraft/world/entity/vehicle/MinecartTNT.java +@@ -22,6 +22,9 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.material.FluidState; ++// CraftBukkit start ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end + + public class MinecartTNT extends AbstractMinecart { + +@@ -121,7 +118,15 @@ + d1 = 5.0D; + } + +- this.level().explode(this, damagesource, (ExplosionDamageCalculator) null, this.getX(), this.getY(), this.getZ(), (float) (4.0D + this.random.nextDouble() * 1.5D * d1), false, Level.ExplosionInteraction.TNT); ++ // CraftBukkit start ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), (float) (4.0D + this.random.nextDouble() * 1.5D * d1), false); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ fuse = -1; ++ return; ++ } ++ this.level().explode(this, damageSource, (ExplosionDamageCalculator) null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.TNT); ++ // CraftBukkit end + this.discard(); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/VehicleEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/VehicleEntity.java.patch new file mode 100644 index 0000000000..36804ea421 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/vehicle/VehicleEntity.java.patch @@ -0,0 +1,64 @@ +--- a/net/minecraft/world/entity/vehicle/VehicleEntity.java ++++ b/net/minecraft/world/entity/vehicle/VehicleEntity.java +@@ -13,6 +13,12 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.entity.Vehicle; ++import org.bukkit.event.vehicle.VehicleDamageEvent; ++import org.bukkit.event.vehicle.VehicleDestroyEvent; ++// CraftBukkit end ++ + public abstract class VehicleEntity extends Entity { + + protected static final EntityDataAccessor DATA_ID_HURT = SynchedEntityData.defineId(VehicleEntity.class, EntityDataSerializers.INT); +@@ -30,6 +35,18 @@ + if (this.isInvulnerableTo(damagesource)) { + return false; + } else { ++ // CraftBukkit start ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ org.bukkit.entity.Entity attacker = (source.getEntity() == null) ? null : source.getEntity().getBukkitEntity(); ++ ++ VehicleDamageEvent event = new VehicleDamageEvent(vehicle, attacker, (double) amount); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ amount = (float) event.getDamage(); ++ // CraftBukkit end + this.setHurtDir(-this.getHurtDir()); + this.setHurtTime(10); + this.markHurt(); +@@ -39,10 +56,28 @@ + + if ((flag || this.getDamage() <= 40.0F) && !this.shouldSourceDestroy(damagesource)) { + if (flag) { ++ // CraftBukkit start ++ VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, attacker); ++ this.level().getCraftServer().getPluginManager().callEvent(destroyEvent); ++ ++ if (destroyEvent.isCancelled()) { ++ this.setDamage(40.0F); // Maximize damage so this doesn't get triggered again right away ++ return true; ++ } ++ // CraftBukkit end + this.discard(); + } + } else { +- this.destroy(damagesource); ++ // CraftBukkit start ++ VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, attacker); ++ this.level().getCraftServer().getPluginManager().callEvent(destroyEvent); ++ ++ if (destroyEvent.isCancelled()) { ++ this.setDamage(40.0F); // Maximize damage so this doesn't get triggered again right away ++ return true; ++ } ++ // CraftBukkit end ++ this.destroy(source); + } + + return true; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/food/FoodData.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/food/FoodData.java.patch new file mode 100644 index 0000000000..601d6a3963 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/food/FoodData.java.patch @@ -0,0 +1,100 @@ +--- a/net/minecraft/world/food/FoodData.java ++++ b/net/minecraft/world/food/FoodData.java +@@ -13,20 +15,37 @@ + private float saturationLevel = 5.0F; + private float exhaustionLevel; + private int tickTimer; ++ // CraftBukkit start ++ private Player entityhuman; ++ public int saturatedRegenRate = 10; ++ public int unsaturatedRegenRate = 80; ++ public int starvationRate = 80; ++ // CraftBukkit end + private int lastFoodLevel = 20; + +- public FoodData() {} ++ public FoodData() { throw new AssertionError("Whoopsie, we missed the bukkit."); } // CraftBukkit start - throw an error + +- public void eat(int i, float f) { +- this.foodLevel = Math.min(i + this.foodLevel, 20); +- this.saturationLevel = Math.min(this.saturationLevel + (float) i * f * 2.0F, (float) this.foodLevel); ++ // CraftBukkit start - added EntityHuman constructor ++ public FoodData(Player entityhuman) { ++ org.apache.commons.lang.Validate.notNull(entityhuman); ++ this.entityhuman = entityhuman; + } ++ // CraftBukkit end + + public void eat(Item item, ItemStack itemstack) { + if (item.isEdible()) { +- FoodProperties foodproperties = item.getFoodProperties(); ++ FoodProperties foodinfo = item.getFoodProperties(); ++ // CraftBukkit start ++ int oldFoodLevel = foodLevel; + +- this.eat(foodproperties.getNutrition(), foodproperties.getSaturationModifier()); ++ org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(entityhuman, foodinfo.getNutrition() + oldFoodLevel, stack); ++ ++ if (!event.isCancelled()) { ++ this.eat(event.getFoodLevel() - oldFoodLevel, foodinfo.getSaturationModifier()); ++ } ++ ++ ((ServerPlayer) entityhuman).getBukkitEntity().sendHealthUpdate(); ++ // CraftBukkit end + } + + } +@@ -39,8 +63,16 @@ + this.exhaustionLevel -= 4.0F; + if (this.saturationLevel > 0.0F) { + this.saturationLevel = Math.max(this.saturationLevel - 1.0F, 0.0F); +- } else if (difficulty != Difficulty.PEACEFUL) { +- this.foodLevel = Math.max(this.foodLevel - 1, 0); ++ } else if (enumdifficulty != Difficulty.PEACEFUL) { ++ // CraftBukkit start ++ org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(player, Math.max(this.foodLevel - 1, 0)); ++ ++ if (!event.isCancelled()) { ++ this.foodLevel = event.getFoodLevel(); ++ } ++ ++ ((ServerPlayer) player).connection.send(new ClientboundSetHealthPacket(((ServerPlayer) player).getBukkitEntity().getScaledHealth(), this.foodLevel, this.saturationLevel)); ++ // CraftBukkit end + } + } + +@@ -48,24 +80,26 @@ + + if (flag && this.saturationLevel > 0.0F && player.isHurt() && this.foodLevel >= 20) { + ++this.tickTimer; +- if (this.tickTimer >= 10) { ++ if (this.tickTimer >= this.saturatedRegenRate) { // CraftBukkit + float f = Math.min(this.saturationLevel, 6.0F); + +- player.heal(f / 6.0F); +- this.addExhaustion(f); ++ player.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED); // CraftBukkit - added RegainReason ++ // this.addExhaustion(f); CraftBukkit - EntityExhaustionEvent ++ player.causeFoodExhaustion(f, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.REGEN); // CraftBukkit - EntityExhaustionEvent + this.tickTimer = 0; + } + } else if (flag && this.foodLevel >= 18 && player.isHurt()) { + ++this.tickTimer; +- if (this.tickTimer >= 80) { +- player.heal(1.0F); +- this.addExhaustion(6.0F); ++ if (this.tickTimer >= this.unsaturatedRegenRate) { // CraftBukkit - add regen rate manipulation ++ player.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED); // CraftBukkit - added RegainReason ++ // this.a(6.0F); CraftBukkit - EntityExhaustionEvent ++ player.causeFoodExhaustion(6.0f, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.REGEN); // CraftBukkit - EntityExhaustionEvent + this.tickTimer = 0; + } + } else if (this.foodLevel <= 0) { + ++this.tickTimer; +- if (this.tickTimer >= 80) { +- if (player.getHealth() > 10.0F || difficulty == Difficulty.HARD || player.getHealth() > 1.0F && difficulty == Difficulty.NORMAL) { ++ if (this.tickTimer >= this.starvationRate) { // CraftBukkit - add regen rate manipulation ++ if (player.getHealth() > 10.0F || enumdifficulty == Difficulty.HARD || player.getHealth() > 1.0F && enumdifficulty == Difficulty.NORMAL) { + player.hurt(player.damageSources().starve(), 1.0F); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/AbstractContainerMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/AbstractContainerMenu.java.patch new file mode 100644 index 0000000000..45f274d0b5 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/AbstractContainerMenu.java.patch @@ -0,0 +1,194 @@ +--- a/net/minecraft/world/inventory/AbstractContainerMenu.java ++++ b/net/minecraft/world/inventory/AbstractContainerMenu.java +@@ -33,6 +35,18 @@ + import net.minecraft.world.level.block.entity.BlockEntity; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.google.common.base.Preconditions; ++import java.util.HashMap; ++import java.util.Map; ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.Event.Result; ++import org.bukkit.event.inventory.InventoryDragEvent; ++import org.bukkit.event.inventory.InventoryType; ++import org.bukkit.inventory.InventoryView; ++// CraftBukkit end ++ + public abstract class AbstractContainerMenu { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -63,7 +77,28 @@ + private ContainerSynchronizer synchronizer; + private boolean suppressRemoteUpdates; + +- protected AbstractContainerMenu(@Nullable MenuType menutype, int i) { ++ // CraftBukkit start ++ public boolean checkReachable = true; ++ public abstract InventoryView getBukkitView(); ++ public void transferTo(AbstractContainerMenu other, org.bukkit.craftbukkit.entity.CraftHumanEntity player) { ++ InventoryView source = this.getBukkitView(), destination = other.getBukkitView(); ++ ((CraftInventory) source.getTopInventory()).getInventory().onClose(player); ++ ((CraftInventory) source.getBottomInventory()).getInventory().onClose(player); ++ ((CraftInventory) destination.getTopInventory()).getInventory().onOpen(player); ++ ((CraftInventory) destination.getBottomInventory()).getInventory().onOpen(player); ++ } ++ private Component title; ++ public final Component getTitle() { ++ Preconditions.checkState(this.title != null, "Title not set"); ++ return this.title; ++ } ++ public final void setTitle(Component title) { ++ Preconditions.checkState(this.title == null, "Title already set"); ++ this.title = title; ++ } ++ // CraftBukkit end ++ ++ protected AbstractContainerMenu(@Nullable MenuType menuType, int containerId) { + this.carried = ItemStack.EMPTY; + this.remoteSlots = NonNullList.create(); + this.remoteDataSlots = new IntArrayList(); +@@ -164,9 +199,14 @@ + + } + +- public void removeSlotListener(ContainerListener containerlistener) { +- this.containerListeners.remove(containerlistener); ++ // CraftBukkit start ++ public void broadcastCarriedItem() { ++ this.remoteCarried = this.getCarried().copy(); ++ if (this.synchronizer != null) { ++ this.synchronizer.sendCarriedChange(this, this.remoteCarried); ++ } + } ++ // CraftBukkit end + + public NonNullList getItems() { + NonNullList nonnulllist = NonNullList.create(); +@@ -380,7 +424,7 @@ + } + } else if (this.quickcraftStatus == 2) { + if (!this.quickcraftSlots.isEmpty()) { +- if (this.quickcraftSlots.size() == 1) { ++ if (false && this.quickcraftSlots.size() == 1) { // CraftBukkit - treat everything as a drag since we are unable to easily call InventoryClickEvent instead + k = ((Slot) this.quickcraftSlots.iterator().next()).index; + this.resetQuickCraft(); + this.doClick(k, this.quickcraftType, ClickType.PICKUP, player); +@@ -396,6 +440,7 @@ + l = this.getCarried().getCount(); + Iterator iterator = this.quickcraftSlots.iterator(); + ++ Map draggedSlots = new HashMap(); // CraftBukkit - Store slots from drag in map (raw slot id -> new stack) + while (iterator.hasNext()) { + Slot slot1 = (Slot) iterator.next(); + ItemStack itemstack2 = this.getCarried(); +@@ -406,12 +451,48 @@ + int l1 = Math.min(getQuickCraftPlaceCount(this.quickcraftSlots, this.quickcraftType, itemstack1) + j1, k1); + + l -= l1 - j1; +- slot1.setByPlayer(itemstack1.copyWithCount(l1)); ++ // slot1.setByPlayer(itemstack1.copyWithCount(l1)); ++ draggedSlots.put(slot1.index, itemstack1.copyWithCount(l1)); // CraftBukkit - Put in map instead of setting + } + } + +- itemstack1.setCount(l); +- this.setCarried(itemstack1); ++ // CraftBukkit start - InventoryDragEvent ++ InventoryView view = getBukkitView(); ++ org.bukkit.inventory.ItemStack newcursor = CraftItemStack.asCraftMirror(itemstack1); ++ newcursor.setAmount(l); ++ Map eventmap = new HashMap(); ++ for (Map.Entry ditem : draggedSlots.entrySet()) { ++ eventmap.put(ditem.getKey(), CraftItemStack.asBukkitCopy(ditem.getValue())); ++ } ++ ++ // It's essential that we set the cursor to the new value here to prevent item duplication if a plugin closes the inventory. ++ ItemStack oldCursor = this.getCarried(); ++ this.setCarried(CraftItemStack.asNMSCopy(newcursor)); ++ ++ InventoryDragEvent event = new InventoryDragEvent(view, (newcursor.getType() != org.bukkit.Material.AIR ? newcursor : null), CraftItemStack.asBukkitCopy(oldCursor), this.quickcraftType == 1, eventmap); ++ player.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ // Whether or not a change was made to the inventory that requires an update. ++ boolean needsUpdate = event.getResult() != Result.DEFAULT; ++ ++ if (event.getResult() != Result.DENY) { ++ for (Map.Entry dslot : draggedSlots.entrySet()) { ++ view.setItem(dslot.getKey(), CraftItemStack.asBukkitCopy(dslot.getValue())); ++ } ++ // The only time the carried item will be set to null is if the inventory is closed by the server. ++ // If the inventory is closed by the server, then the cursor items are dropped. This is why we change the cursor early. ++ if (this.getCarried() != null) { ++ this.setCarried(CraftItemStack.asNMSCopy(event.getCursor())); ++ needsUpdate = true; ++ } ++ } else { ++ this.setCarried(oldCursor); ++ } ++ ++ if (needsUpdate && player instanceof ServerPlayer) { ++ this.sendAllDataToRemote(); ++ } ++ // CraftBukkit end + } + + this.resetQuickCraft(); +@@ -429,8 +510,11 @@ + if (i == -999) { + if (!this.getCarried().isEmpty()) { + if (clickaction == ClickAction.PRIMARY) { +- player.drop(this.getCarried(), true); ++ // CraftBukkit start ++ ItemStack carried = this.getCarried(); + this.setCarried(ItemStack.EMPTY); ++ player.drop(carried, true); ++ // CraftBukkit start + } else { + player.drop(this.getCarried().split(1), true); + } +@@ -493,6 +577,15 @@ + } + + slot.setChanged(); ++ // CraftBukkit start - Make sure the client has the right slot contents ++ if (player instanceof ServerPlayer && slot.getMaxStackSize() != 64) { ++ ((ServerPlayer) player).connection.send(new ClientboundContainerSetSlotPacket(this.containerId, this.incrementStateId(), slot.index, slot.getItem())); ++ // Updating a crafting inventory makes the client reset the result slot, have to send it again ++ if (this.getBukkitView().getType() == InventoryType.WORKBENCH || this.getBukkitView().getType() == InventoryType.CRAFTING) { ++ ((ServerPlayer) player).connection.send(new ClientboundContainerSetSlotPacket(this.containerId, this.incrementStateId(), 0, this.getSlot(0).getItem())); ++ } ++ } ++ // CraftBukkit end + } + } else { + int j2; +@@ -611,13 +702,14 @@ + ItemStack itemstack = this.getCarried(); + + if (!itemstack.isEmpty()) { ++ this.setCarried(ItemStack.EMPTY); // CraftBukkit - SPIGOT-4556 - from below + if (player.isAlive() && !((ServerPlayer) player).hasDisconnected()) { + player.getInventory().placeItemBackInInventory(itemstack); + } else { + player.drop(itemstack, false); + } + +- this.setCarried(ItemStack.EMPTY); ++ // this.setCarried(ItemStack.EMPTY); // CraftBukkit - moved up + } + } + +@@ -834,6 +926,11 @@ + } + + public ItemStack getCarried() { ++ // CraftBukkit start ++ if (this.carried.isEmpty()) { ++ this.setCarried(ItemStack.EMPTY); ++ } ++ // CraftBukkit end + return this.carried; + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/AbstractFurnaceMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/AbstractFurnaceMenu.java.patch new file mode 100644 index 0000000000..aaf5b6de89 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/AbstractFurnaceMenu.java.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/inventory/AbstractFurnaceMenu.java ++++ b/net/minecraft/world/inventory/AbstractFurnaceMenu.java +@@ -13,6 +13,10 @@ + import net.minecraft.world.item.crafting.RecipeType; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryFurnace; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + + public abstract class AbstractFurnaceMenu extends RecipeBookMenu { + +@@ -31,9 +35,21 @@ + private final RecipeType recipeType; + private final RecipeBookType recipeBookType; + +- protected AbstractFurnaceMenu(MenuType menutype, RecipeType recipetype, RecipeBookType recipebooktype, int i, Inventory inventory) { +- this(menutype, recipetype, recipebooktype, i, inventory, new SimpleContainer(3), new SimpleContainerData(4)); ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryFurnace inventory = new CraftInventoryFurnace((AbstractFurnaceBlockEntity) this.container); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; + } ++ // CraftBukkit end + + protected AbstractFurnaceMenu(MenuType menutype, RecipeType recipetype, RecipeBookType recipebooktype, int i, Inventory inventory, Container container, ContainerData containerdata) { + super(menutype, i); +@@ -46,7 +66,8 @@ + this.level = inventory.player.level(); + this.addSlot(new Slot(container, 0, 56, 17)); + this.addSlot(new FurnaceFuelSlot(this, container, 1, 56, 53)); +- this.addSlot(new FurnaceResultSlot(inventory.player, container, 2, 116, 35)); ++ this.addSlot(new FurnaceResultSlot(playerInventory.player, container, 2, 116, 35)); ++ this.player = playerInventory; // CraftBukkit - save player + + int j; + +@@ -112,6 +125,7 @@ + @Override + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(player); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/AnvilMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/AnvilMenu.java.patch new file mode 100644 index 0000000000..421c6d7e48 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/AnvilMenu.java.patch @@ -0,0 +1,138 @@ +--- a/net/minecraft/world/inventory/AnvilMenu.java ++++ b/net/minecraft/world/inventory/AnvilMenu.java +@@ -19,6 +19,10 @@ + import net.minecraft.world.level.block.state.BlockState; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class AnvilMenu extends ItemCombinerMenu { + + public static final int INPUT_SLOT = 0; +@@ -42,6 +46,11 @@ + private static final int ADDITIONAL_SLOT_X_PLACEMENT = 76; + private static final int RESULT_SLOT_X_PLACEMENT = 134; + private static final int SLOT_Y_PLACEMENT = 47; ++ // CraftBukkit start ++ public static final int DEFAULT_DENIED_COST = -1; ++ public int maximumRepairCost = 40; ++ private CraftInventoryView bukkitEntity; ++ // CraftBukkit end + + public AnvilMenu(int i, Inventory inventory) { + this(i, inventory, ContainerLevelAccess.NULL); +@@ -70,9 +77,8 @@ + } + + @Override +- @Override +- protected boolean mayPickup(Player player, boolean flag) { +- return (player.getAbilities().instabuild || player.experienceLevel >= this.cost.get()) && this.cost.get() > 0; ++ protected boolean mayPickup(Player player, boolean hasStack) { ++ return (player.getAbilities().instabuild || player.experienceLevel >= this.cost.get()) && this.cost.get() > AnvilMenu.DEFAULT_DENIED_COST && hasStack; // CraftBukkit - allow cost 0 like a free item + } + + @Override +@@ -96,9 +101,9 @@ + this.inputSlots.setItem(1, ItemStack.EMPTY); + } + +- this.cost.set(0); +- this.access.execute((level, blockpos) -> { +- BlockState blockstate = level.getBlockState(blockpos); ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item ++ this.access.execute((world, blockposition) -> { ++ IBlockData iblockdata = world.getBlockState(blockposition); + + if (!player.getAbilities().instabuild && blockstate.is(BlockTags.ANVIL) && player.getRandom().nextFloat() < 0.12F) { + BlockState blockstate1 = AnvilBlock.damage(blockstate); +@@ -128,8 +132,8 @@ + byte b1 = 0; + + if (itemstack.isEmpty()) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- this.cost.set(0); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + } else { + ItemStack itemstack1 = itemstack.copy(); + ItemStack itemstack2 = this.inputSlots.getItem(1); +@@ -146,8 +150,8 @@ + if (itemstack1.isDamageableItem() && itemstack1.getItem().isValidRepairItem(itemstack, itemstack2)) { + k = Math.min(itemstack1.getDamageValue(), itemstack1.getMaxDamage() / 4); + if (k <= 0) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- this.cost.set(0); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + return; + } + +@@ -161,8 +165,8 @@ + this.repairItemCountCost = i1; + } else { + if (!flag && (!itemstack1.is(itemstack2.getItem()) || !itemstack1.isDamageableItem())) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- this.cost.set(0); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + return; + } + +@@ -251,8 +255,8 @@ + } + + if (flag2 && !flag1) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- this.cost.set(0); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + return; + } + } +@@ -275,11 +279,11 @@ + itemstack1 = ItemStack.EMPTY; + } + +- if (b1 == i && b1 > 0 && this.cost.get() >= 40) { +- this.cost.set(39); ++ if (b1 == i && b1 > 0 && this.cost.get() >= maximumRepairCost) { // CraftBukkit ++ this.cost.set(maximumRepairCost - 1); // CraftBukkit + } + +- if (this.cost.get() >= 40 && !this.player.getAbilities().instabuild) { ++ if (this.cost.get() >= maximumRepairCost && !this.player.getAbilities().instabuild) { // CraftBukkit + itemstack1 = ItemStack.EMPTY; + } + +@@ -298,7 +302,8 @@ + EnchantmentHelper.setEnchantments(map, itemstack1); + } + +- this.resultSlots.setItem(0, itemstack1); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), itemstack1); // CraftBukkit ++ sendAllDataToRemote(); // CraftBukkit - SPIGOT-6686: Always send completed inventory to stay in sync with client + this.broadcastChanges(); + } + } +@@ -339,4 +344,18 @@ + public int getCost() { + return this.cost.get(); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventory inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryAnvil( ++ access.getLocation(), this.inputSlots, this.resultSlots, this); ++ bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/BeaconMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/BeaconMenu.java.patch new file mode 100644 index 0000000000..8e5ec5d3c2 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/BeaconMenu.java.patch @@ -0,0 +1,58 @@ +--- a/net/minecraft/world/inventory/BeaconMenu.java ++++ b/net/minecraft/world/inventory/BeaconMenu.java +@@ -11,6 +12,8 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + + public class BeaconMenu extends AbstractContainerMenu { + +@@ -26,13 +29,18 @@ + private final BeaconMenu.PaymentSlot paymentSlot; + private final ContainerLevelAccess access; + private final ContainerData beaconData; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ // CraftBukkit end + + public BeaconMenu(int i, Container container) { + this(i, container, new SimpleContainerData(3), ContainerLevelAccess.NULL); + } + +- public BeaconMenu(int i, Container container, ContainerData containerdata, ContainerLevelAccess containerlevelaccess) { +- super(MenuType.BEACON, i); ++ public BeaconMenu(int containerId, Container container, ContainerData beaconData, ContainerLevelAccess access) { ++ super(MenuType.BEACON, containerId); ++ player = (Inventory) container; // CraftBukkit - TODO: check this + this.beacon = new SimpleContainer(1) { + @Override + @Override +@@ -86,6 +90,7 @@ + @Override + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.BEACON); + } + +@@ -199,4 +200,17 @@ + return 1; + } + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventory inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryBeacon(this.beacon); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/BrewingStandMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/BrewingStandMenu.java.patch new file mode 100644 index 0000000000..4e23e36b65 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/BrewingStandMenu.java.patch @@ -0,0 +1,82 @@ +--- a/net/minecraft/world/inventory/BrewingStandMenu.java ++++ b/net/minecraft/world/inventory/BrewingStandMenu.java +@@ -12,6 +12,10 @@ + import net.minecraft.world.item.alchemy.Potion; + import net.minecraft.world.item.alchemy.PotionBrewing; + import net.minecraft.world.item.alchemy.PotionUtils; ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryBrewer; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + + public class BrewingStandMenu extends AbstractContainerMenu { + +@@ -29,22 +33,28 @@ + private final ContainerData brewingStandData; + private final Slot ingredientSlot; + +- public BrewingStandMenu(int i, Inventory inventory) { +- this(i, inventory, new SimpleContainer(5), new SimpleContainerData(2)); ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ // CraftBukkit end ++ ++ public BrewingStandMenu(int containerId, Inventory playerInventory) { ++ this(containerId, playerInventory, new SimpleContainer(5), new SimpleContainerData(2)); + } + +- public BrewingStandMenu(int i, Inventory inventory, Container container, ContainerData containerdata) { +- super(MenuType.BREWING_STAND, i); +- checkContainerSize(container, 5); +- checkContainerDataCount(containerdata, 2); +- this.brewingStand = container; +- this.brewingStandData = containerdata; +- this.addSlot(new BrewingStandMenu.PotionSlot(container, 0, 56, 51)); +- this.addSlot(new BrewingStandMenu.PotionSlot(container, 1, 79, 58)); +- this.addSlot(new BrewingStandMenu.PotionSlot(container, 2, 102, 51)); +- this.ingredientSlot = this.addSlot(new BrewingStandMenu.IngredientsSlot(container, 3, 79, 17)); +- this.addSlot(new BrewingStandMenu.FuelSlot(container, 4, 17, 17)); +- this.addDataSlots(containerdata); ++ public BrewingStandMenu(int containerId, Inventory playerInventory, Container brewingStandContainer, ContainerData brewingStandData) { ++ super(MenuType.BREWING_STAND, containerId); ++ player = playerInventory; // CraftBukkit ++ checkContainerSize(brewingStandContainer, 5); ++ checkContainerDataCount(brewingStandData, 2); ++ this.brewingStand = brewingStandContainer; ++ this.brewingStandData = brewingStandData; ++ this.addSlot(new BrewingStandMenu.PotionSlot(brewingStandContainer, 0, 56, 51)); ++ this.addSlot(new BrewingStandMenu.PotionSlot(brewingStandContainer, 1, 79, 58)); ++ this.addSlot(new BrewingStandMenu.PotionSlot(brewingStandContainer, 2, 102, 51)); ++ this.ingredientSlot = this.addSlot(new BrewingStandMenu.IngredientsSlot(brewingStandContainer, 3, 79, 17)); ++ this.addSlot(new BrewingStandMenu.FuelSlot(brewingStandContainer, 4, 17, 17)); ++ this.addDataSlots(brewingStandData); + + int j; + +@@ -63,6 +72,7 @@ + @Override + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.brewingStand.stillValid(player); + } + +@@ -208,4 +210,17 @@ + return 64; + } + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryBrewer inventory = new CraftInventoryBrewer(this.brewingStand); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/CartographyTableMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/CartographyTableMenu.java.patch new file mode 100644 index 0000000000..13a6e37f71 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/CartographyTableMenu.java.patch @@ -0,0 +1,76 @@ +--- a/net/minecraft/world/inventory/CartographyTableMenu.java ++++ b/net/minecraft/world/inventory/CartographyTableMenu.java +@@ -11,9 +10,30 @@ + import net.minecraft.world.item.MapItem; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.saveddata.maps.MapItemSavedData; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.inventory.CraftInventoryCartography; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class CartographyTableMenu extends AbstractContainerMenu { + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryCartography inventory = new CraftInventoryCartography(this.container, this.resultContainer); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + public static final int MAP_SLOT = 0; + public static final int ADDITIONAL_SLOT = 1; + public static final int RESULT_SLOT = 2; +@@ -39,6 +58,13 @@ + CartographyTableMenu.this.slotsChanged(this); + super.setChanged(); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end + }; + this.resultContainer = new ResultContainer() { + @Override +@@ -47,6 +72,13 @@ + CartographyTableMenu.this.slotsChanged(this); + super.setChanged(); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end + }; + this.access = containerlevelaccess; + this.addSlot(new Slot(this.container, 0, 15, 15) { +@@ -101,11 +129,12 @@ + this.addSlot(new Slot(inventory, j, 8 + j * 18, 142)); + } + ++ player = (Player) playerInventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override +- @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.CARTOGRAPHY_TABLE); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/ChestMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/ChestMenu.java.patch new file mode 100644 index 0000000000..edc63ba678 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/ChestMenu.java.patch @@ -0,0 +1,45 @@ +--- a/net/minecraft/world/inventory/ChestMenu.java ++++ b/net/minecraft/world/inventory/ChestMenu.java +@@ -5,16 +6,23 @@ + import net.minecraft.world.entity.player.Inventory; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + + public class ChestMenu extends AbstractContainerMenu { + + private static final int SLOTS_PER_ROW = 9; + private final Container container; + private final int containerRows; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; + + private ChestMenu(MenuType menutype, int i, Inventory inventory, int j) { + this(menutype, i, inventory, new SimpleContainer(9 * j), j); + } ++ // CraftBukkit end + + public static ChestMenu oneRow(int i, Inventory inventory) { + return new ChestMenu(MenuType.GENERIC_9x1, i, inventory, 1); +@@ -56,6 +83,10 @@ + container.startOpen(inventory.player); + int k = (this.containerRows - 4) * 18; + ++ // CraftBukkit start - Save player ++ this.player = playerInventory; ++ // CraftBukkit end ++ + int l; + int i1; + +@@ -80,6 +110,7 @@ + @Override + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(player); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/ContainerLevelAccess.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/ContainerLevelAccess.java.patch new file mode 100644 index 0000000000..9842d48860 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/ContainerLevelAccess.java.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/world/inventory/ContainerLevelAccess.java ++++ b/net/minecraft/world/inventory/ContainerLevelAccess.java +@@ -8,6 +8,20 @@ + + public interface ContainerLevelAccess { + ++ // CraftBukkit start ++ default Level getWorld() { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ ++ default BlockPos getPosition() { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ ++ default org.bukkit.Location getLocation() { ++ return new org.bukkit.Location(getWorld().getWorld(), getPosition().getX(), getPosition().getY(), getPosition().getZ()); ++ } ++ // CraftBukkit end ++ + ContainerLevelAccess NULL = new ContainerLevelAccess() { + @Override + @Override +@@ -18,11 +31,18 @@ + + static ContainerLevelAccess create(final Level level, final BlockPos blockpos) { + return new ContainerLevelAccess() { ++ // CraftBukkit start + @Override + @Override + public Optional evaluate(BiFunction bifunction) { + return Optional.of(bifunction.apply(level, blockpos)); + } ++ // CraftBukkit end ++ ++ @Override ++ public Optional evaluate(BiFunction levelPosConsumer) { ++ return Optional.of(levelPosConsumer.apply(level, pos)); ++ } + }; + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/CrafterMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/CrafterMenu.java.patch new file mode 100644 index 0000000000..84de94f9c8 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/CrafterMenu.java.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/world/inventory/CrafterMenu.java ++++ b/net/minecraft/world/inventory/CrafterMenu.java +@@ -8,8 +8,27 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.CrafterBlock; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryCrafter; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class CrafterMenu extends AbstractContainerMenu implements ContainerListener { + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryCrafter inventory = new CraftInventoryCrafter(this.container, this.resultContainer); ++ bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + protected static final int SLOT_COUNT = 9; + private static final int INV_SLOT_START = 9; + private static final int INV_SLOT_END = 36; +@@ -118,6 +135,7 @@ + @Override + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(player); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/CraftingMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/CraftingMenu.java.patch new file mode 100644 index 0000000000..becbef811b --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/CraftingMenu.java.patch @@ -0,0 +1,81 @@ +--- a/net/minecraft/world/inventory/CraftingMenu.java ++++ b/net/minecraft/world/inventory/CraftingMenu.java +@@ -14,6 +15,9 @@ + import net.minecraft.world.item.crafting.RecipeType; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; ++import org.bukkit.craftbukkit.inventory.CraftInventoryCrafting; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + + public class CraftingMenu extends RecipeBookMenu { + +@@ -24,22 +28,28 @@ + private static final int INV_SLOT_END = 37; + private static final int USE_ROW_SLOT_START = 37; + private static final int USE_ROW_SLOT_END = 46; +- private final CraftingContainer craftSlots; +- private final ResultContainer resultSlots; +- private final ContainerLevelAccess access; ++ public final TransientCraftingContainer craftSlots; // CraftBukkit ++ public final ResultContainer resultSlots; ++ public final ContainerLevelAccess access; + private final Player player; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ // CraftBukkit end + + public CraftingMenu(int i, Inventory inventory) { + this(i, inventory, ContainerLevelAccess.NULL); + } + +- public CraftingMenu(int i, Inventory inventory, ContainerLevelAccess containerlevelaccess) { +- super(MenuType.CRAFTING, i); +- this.craftSlots = new TransientCraftingContainer(this, 3, 3); ++ public CraftingMenu(int containerId, Inventory playerInventory, ContainerLevelAccess access) { ++ super(MenuType.CRAFTING, containerId); ++ // CraftBukkit start - Switched order of IInventory construction and stored player + this.resultSlots = new ResultContainer(); +- this.access = containerlevelaccess; +- this.player = inventory.player; +- this.addSlot(new ResultSlot(inventory.player, this.craftSlots, this.resultSlots, 0, 124, 35)); ++ this.craftSlots = new TransientCraftingContainer(this, 3, 3, playerInventory.player); // CraftBukkit - pass player ++ this.craftSlots.resultInventory = this.resultSlots; ++ // CraftBukkit end ++ this.access = access; ++ this.player = playerInventory.player; ++ this.addSlot(new ResultSlot(playerInventory.player, this.craftSlots, this.resultSlots, 0, 124, 35)); + + int j; + int k; +@@ -80,6 +90,7 @@ + } + } + } ++ itemstack = org.bukkit.craftbukkit.event.CraftEventFactory.callPreCraftEvent(container, result, itemstack, menu.getBukkitView(), optional.map(RecipeHolder::toBukkitRecipe).orElse(null) instanceof RepairItemRecipe); // CraftBukkit + + resultcontainer.setItem(0, itemstack); + abstractcontainermenu.setRemoteSlot(0, itemstack); +@@ -126,6 +131,7 @@ + @Override + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.CRAFTING_TABLE); + } + +@@ -218,8 +217,14 @@ + } + + @Override ++ public boolean shouldMoveToInventory(int slotIndex) { ++ return slotIndex != this.getResultSlotIndex(); ++ } ++ ++ // CraftBukkit start + @Override + public boolean shouldMoveToInventory(int i) { + return i != this.getResultSlotIndex(); + } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/DispenserMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/DispenserMenu.java.patch new file mode 100644 index 0000000000..725f337033 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/DispenserMenu.java.patch @@ -0,0 +1,66 @@ +--- a/net/minecraft/world/inventory/DispenserMenu.java ++++ b/net/minecraft/world/inventory/DispenserMenu.java +@@ -6,6 +6,11 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class DispenserMenu extends AbstractContainerMenu { + + private static final int SLOT_COUNT = 9; +@@ -13,14 +18,22 @@ + private static final int INV_SLOT_END = 36; + private static final int USE_ROW_SLOT_START = 36; + private static final int USE_ROW_SLOT_END = 45; +- private final Container dispenser; ++ public final Container dispenser; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ // CraftBukkit end + + public DispenserMenu(int i, Inventory inventory) { + this(i, inventory, new SimpleContainer(9)); + } + +- public DispenserMenu(int i, Inventory inventory, Container container) { +- super(MenuType.GENERIC_3x3, i); ++ public DispenserMenu(int containerId, Inventory playerInventory, Container container) { ++ super(MenuType.GENERIC_3x3, containerId); ++ // CraftBukkit start - Save player ++ this.player = playerInventory; ++ // CraftBukkit end ++ + checkContainerSize(container, 9); + this.dispenser = container; + container.startOpen(inventory.player); +@@ -49,6 +61,7 @@ + @Override + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.dispenser.stillValid(player); + } + +@@ -92,4 +103,17 @@ + super.removed(player); + this.dispenser.stopOpen(player); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventory inventory = new CraftInventory(this.dispenser); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/EnchantmentMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/EnchantmentMenu.java.patch new file mode 100644 index 0000000000..8e5dc408ee --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/EnchantmentMenu.java.patch @@ -0,0 +1,198 @@ +--- a/net/minecraft/world/inventory/EnchantmentMenu.java ++++ b/net/minecraft/world/inventory/EnchantmentMenu.java +@@ -26,6 +23,22 @@ + import net.minecraft.world.item.enchantment.EnchantmentInstance; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.EnchantmentTableBlock; ++// CraftBukkit start ++import java.util.Map; ++import net.minecraft.world.item.enchantment.Enchantment; ++import net.minecraft.world.item.enchantment.EnchantmentHelper; ++import net.minecraft.world.item.enchantment.EnchantmentInstance; ++import org.bukkit.Location; ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftInventoryEnchanting; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.enchantments.EnchantmentOffer; ++import org.bukkit.event.enchantment.EnchantItemEvent; ++import org.bukkit.event.enchantment.PrepareItemEnchantEvent; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class EnchantmentMenu extends AbstractContainerMenu { + +@@ -37,6 +50,10 @@ + public final int[] costs; + public final int[] enchantClue; + public final int[] levelClue; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ // CraftBukkit end + + public EnchantmentMenu(int i, Inventory inventory) { + this(i, inventory, ContainerLevelAccess.NULL); +@@ -51,6 +67,13 @@ + super.setChanged(); + EnchantmentMenu.this.slotsChanged(this); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end + }; + this.random = RandomSource.create(); + this.enchantmentSeed = DataSlot.standalone(); +@@ -101,6 +121,9 @@ + this.addDataSlot(DataSlot.shared(this.levelClue, 0)); + this.addDataSlot(DataSlot.shared(this.levelClue, 1)); + this.addDataSlot(DataSlot.shared(this.levelClue, 2)); ++ // CraftBukkit start ++ player = (Player) playerInventory.player.getBukkitEntity(); ++ // CraftBukkit end + } + + @Override +@@ -109,8 +131,8 @@ + if (container == this.enchantSlots) { + ItemStack itemstack = container.getItem(0); + +- if (!itemstack.isEmpty() && itemstack.isEnchantable()) { +- this.access.execute((level, blockpos) -> { ++ if (!itemstack.isEmpty()) { // CraftBukkit - relax condition ++ this.access.execute((world, blockposition) -> { + int i = 0; + Iterator iterator = EnchantmentTableBlock.BOOKSHELF_OFFSETS.iterator(); + +@@ -148,6 +170,41 @@ + } + } + ++ // CraftBukkit start ++ CraftItemStack item = CraftItemStack.asCraftMirror(itemstack); ++ org.bukkit.enchantments.EnchantmentOffer[] offers = new EnchantmentOffer[3]; ++ for (j = 0; j < 3; ++j) { ++ org.bukkit.enchantments.Enchantment enchantment = (this.enchantClue[j] >= 0) ? org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(BuiltInRegistries.ENCHANTMENT.byId(this.enchantClue[j])))) : null; ++ offers[j] = (enchantment != null) ? new EnchantmentOffer(enchantment, this.levelClue[j], this.costs[j]) : null; ++ } ++ ++ PrepareItemEnchantEvent event = new PrepareItemEnchantEvent(player, this.getBukkitView(), access.getLocation().getBlock(), item, offers, i); ++ event.setCancelled(!itemstack.isEnchantable()); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ for (j = 0; j < 3; ++j) { ++ this.costs[j] = 0; ++ this.enchantClue[j] = -1; ++ this.levelClue[j] = -1; ++ } ++ return; ++ } ++ ++ for (j = 0; j < 3; j++) { ++ EnchantmentOffer offer = event.getOffers()[j]; ++ if (offer != null) { ++ this.costs[j] = offer.getCost(); ++ this.enchantClue[j] = BuiltInRegistries.ENCHANTMENT.getId(BuiltInRegistries.ENCHANTMENT.get(CraftNamespacedKey.toMinecraft(offer.getEnchantment().getKey()))); ++ this.levelClue[j] = offer.getEnchantmentLevel(); ++ } else { ++ this.costs[j] = 0; ++ this.enchantClue[j] = -1; ++ this.levelClue[j] = -1; ++ } ++ } ++ // CraftBukkit end ++ + this.broadcastChanges(); + }); + } else { +@@ -176,8 +232,25 @@ + ItemStack itemstack2 = itemstack; + List list = this.getEnchantmentList(itemstack, i, this.costs[i]); + +- if (!list.isEmpty()) { +- player.onEnchantmentPerformed(itemstack, j); ++ // CraftBukkit start ++ if (true || !list.isEmpty()) { ++ // entityhuman.onEnchantmentPerformed(itemstack, j); // Moved down ++ Map enchants = new java.util.HashMap(); ++ for (EnchantmentInstance instance : list) { ++ enchants.put(org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(instance.enchantment))), instance.level); ++ } ++ CraftItemStack item = CraftItemStack.asCraftMirror(itemstack2); ++ ++ org.bukkit.enchantments.Enchantment hintedEnchantment = org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(Enchantment.byId(enchantClue[id])))); ++ int hintedEnchantmentLevel = levelClue[id]; ++ EnchantItemEvent event = new EnchantItemEvent((Player) player.getBukkitEntity(), this.getBukkitView(), access.getLocation().getBlock(), item, this.costs[id], enchants, hintedEnchantment, hintedEnchantmentLevel, id); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ int level = event.getExpLevelCost(); ++ if (event.isCancelled() || (level > player.experienceLevel && !player.getAbilities().instabuild) || event.getEnchantsToAdd().isEmpty()) { ++ return; ++ } ++ // CraftBukkit end + boolean flag = itemstack.is(Items.BOOK); + + if (flag) { +@@ -191,7 +264,15 @@ + this.enchantSlots.setItem(0, itemstack2); + } + +- Iterator iterator = list.iterator(); ++ // CraftBukkit start ++ for (Map.Entry entry : event.getEnchantsToAdd().entrySet()) { ++ try { ++ if (flag) { ++ NamespacedKey enchantId = entry.getKey().getKey(); ++ Enchantment nms = BuiltInRegistries.ENCHANTMENT.get(CraftNamespacedKey.toMinecraft(enchantId)); ++ if (nms == null) { ++ continue; ++ } + + while (iterator.hasNext()) { + EnchantmentInstance enchantmentinstance = (EnchantmentInstance) iterator.next(); +@@ -203,6 +284,10 @@ + } + } + ++ player.onEnchantmentPerformed(itemstack, j); ++ // CraftBukkit end ++ ++ // CraftBukkit - TODO: let plugins change this + if (!player.getAbilities().instabuild) { + itemstack1.shrink(j); + if (itemstack1.isEmpty()) { +@@ -265,8 +349,8 @@ + } + + @Override +- @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.ENCHANTING_TABLE); + } + +@@ -318,4 +401,17 @@ + + return itemstack; + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryEnchanting inventory = new CraftInventoryEnchanting(this.enchantSlots); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/FurnaceResultSlot.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/FurnaceResultSlot.java.patch new file mode 100644 index 0000000000..92ab3e6165 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/FurnaceResultSlot.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/inventory/FurnaceResultSlot.java ++++ b/net/minecraft/world/inventory/FurnaceResultSlot.java +@@ -59,7 +54,7 @@ + if (container instanceof AbstractFurnaceBlockEntity) { + AbstractFurnaceBlockEntity abstractfurnaceblockentity = (AbstractFurnaceBlockEntity) container; + +- abstractfurnaceblockentity.awardUsedRecipesAndPopExperience(serverplayer); ++ tileentityfurnace.awardUsedRecipesAndPopExperience(entityplayer, stack, this.removeCount); // CraftBukkit + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/GrindstoneMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/GrindstoneMenu.java.patch new file mode 100644 index 0000000000..9729875c6d --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/GrindstoneMenu.java.patch @@ -0,0 +1,109 @@ +--- a/net/minecraft/world/inventory/GrindstoneMenu.java ++++ b/net/minecraft/world/inventory/GrindstoneMenu.java +@@ -18,9 +17,30 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.inventory.CraftInventoryGrindstone; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class GrindstoneMenu extends AbstractContainerMenu { + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryGrindstone inventory = new CraftInventoryGrindstone(this.repairSlots, this.resultSlots); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + public static final int MAX_NAME_LENGTH = 35; + public static final int INPUT_SLOT = 0; + public static final int ADDITIONAL_SLOT = 1; +@@ -47,6 +66,13 @@ + super.setChanged(); + GrindstoneMenu.this.slotsChanged(this); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end + }; + this.access = containerlevelaccess; + this.addSlot(new Slot(this.repairSlots, 0, 49, 19) { +@@ -129,6 +151,7 @@ + this.addSlot(new Slot(inventory, j, 8 + j * 18, 142)); + } + ++ player = (Player) playerInventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override +@@ -151,7 +173,7 @@ + boolean flag2 = !itemstack.isEmpty() && !itemstack.is(Items.ENCHANTED_BOOK) && !itemstack.isEnchanted() || !itemstack1.isEmpty() && !itemstack1.is(Items.ENCHANTED_BOOK) && !itemstack1.isEnchanted(); + + if (itemstack.getCount() > 1 || itemstack1.getCount() > 1 || !flag1 && flag2) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + this.broadcastChanges(); + return; + } +@@ -162,7 +184,7 @@ + + if (flag1) { + if (!itemstack.is(itemstack1.getItem())) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + this.broadcastChanges(); + return; + } +@@ -176,7 +198,7 @@ + itemstack2 = this.mergeEnchants(itemstack, itemstack1); + if (!itemstack2.isDamageableItem()) { + if (!ItemStack.matches(itemstack, itemstack1)) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + this.broadcastChanges(); + return; + } +@@ -189,12 +211,12 @@ + i = flag3 ? itemstack.getDamageValue() : itemstack1.getDamageValue(); + itemstack2 = flag3 ? itemstack : itemstack1; + } +- +- this.resultSlots.setItem(0, this.removeNonCurses(itemstack2, i, b0)); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), this.removeNonCurses(itemstack2, i, b0)); // CraftBukkit + } else { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + } + ++ sendAllDataToRemote(); // CraftBukkit - SPIGOT-6686: Always send completed inventory to stay in sync with client + this.broadcastChanges(); + } + +@@ -256,8 +277,8 @@ + } + + @Override +- @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.GRINDSTONE); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/HopperMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/HopperMenu.java.patch new file mode 100644 index 0000000000..dd741c4d56 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/HopperMenu.java.patch @@ -0,0 +1,49 @@ +--- a/net/minecraft/world/inventory/HopperMenu.java ++++ b/net/minecraft/world/inventory/HopperMenu.java +@@ -6,18 +6,36 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class HopperMenu extends AbstractContainerMenu { + + public static final int CONTAINER_SIZE = 5; + private final Container hopper; + +- public HopperMenu(int i, Inventory inventory) { +- this(i, inventory, new SimpleContainer(5)); ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventory inventory = new CraftInventory(this.hopper); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; + } ++ // CraftBukkit end + + public HopperMenu(int i, Inventory inventory, Container container) { + super(MenuType.HOPPER, i); + this.hopper = container; ++ this.player = playerInventory; // CraftBukkit - save player + checkContainerSize(container, 5); + container.startOpen(inventory.player); + boolean flag = true; +@@ -43,6 +64,7 @@ + @Override + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.hopper.stillValid(player); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/HorseInventoryMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/HorseInventoryMenu.java.patch new file mode 100644 index 0000000000..a8cda8a126 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/HorseInventoryMenu.java.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/world/inventory/HorseInventoryMenu.java ++++ b/net/minecraft/world/inventory/HorseInventoryMenu.java +@@ -8,13 +8,33 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.inventory.InventoryView; ++// CraftBukkit end ++ + public class HorseInventoryMenu extends AbstractContainerMenu { + + private final Container horseContainer; + private final AbstractHorse horse; + +- public HorseInventoryMenu(int i, Inventory inventory, Container container, final AbstractHorse abstracthorse) { +- super((MenuType) null, i); ++ // CraftBukkit start ++ org.bukkit.craftbukkit.inventory.CraftInventoryView bukkitEntity; ++ Inventory player; ++ ++ @Override ++ public InventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ return bukkitEntity = new CraftInventoryView(player.player.getBukkitEntity(), horseContainer.getOwner().getInventory(), this); ++ } ++ ++ public HorseInventoryMenu(int containerId, Inventory playerInventory, Container container, final AbstractHorse horse) { ++ super((MenuType) null, containerId); ++ player = playerInventory; ++ // CraftBukkit end + this.horseContainer = container; + this.horse = abstracthorse; + boolean flag = true; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/InventoryMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/InventoryMenu.java.patch new file mode 100644 index 0000000000..519b631f4c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/InventoryMenu.java.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/inventory/InventoryMenu.java ++++ b/net/minecraft/world/inventory/InventoryMenu.java +@@ -12,6 +13,9 @@ + import net.minecraft.world.item.crafting.Recipe; + import net.minecraft.world.item.crafting.RecipeHolder; + import net.minecraft.world.item.enchantment.EnchantmentHelper; ++import org.bukkit.craftbukkit.inventory.CraftInventoryCrafting; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + + public class InventoryMenu extends RecipeBookMenu { + +@@ -34,16 +38,29 @@ + public static final ResourceLocation EMPTY_ARMOR_SLOT_SHIELD = new ResourceLocation("item/empty_armor_slot_shield"); + static final ResourceLocation[] TEXTURE_EMPTY_SLOTS = new ResourceLocation[]{InventoryMenu.EMPTY_ARMOR_SLOT_BOOTS, InventoryMenu.EMPTY_ARMOR_SLOT_LEGGINGS, InventoryMenu.EMPTY_ARMOR_SLOT_CHESTPLATE, InventoryMenu.EMPTY_ARMOR_SLOT_HELMET}; + private static final EquipmentSlot[] SLOT_IDS = new EquipmentSlot[]{EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET}; +- private final CraftingContainer craftSlots = new TransientCraftingContainer(this, 2, 2); +- private final ResultContainer resultSlots = new ResultContainer(); ++ // CraftBukkit start ++ private final TransientCraftingContainer craftSlots; ++ private final ResultContainer resultSlots; ++ // CraftBukkit end + public final boolean active; + private final Player owner; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ // CraftBukkit end + + public InventoryMenu(Inventory inventory, boolean flag, final Player player) { + super((MenuType) null, 0); +- this.active = flag; +- this.owner = player; +- this.addSlot(new ResultSlot(inventory.player, this.craftSlots, this.resultSlots, 0, 154, 28)); ++ this.active = active; ++ this.owner = owner; ++ // CraftBukkit start ++ this.resultSlots = new ResultContainer(); // CraftBukkit - moved to before InventoryCrafting construction ++ this.craftSlots = new TransientCraftingContainer(this, 2, 2, playerInventory.player); // CraftBukkit - pass player ++ this.craftSlots.resultInventory = this.resultSlots; // CraftBukkit - let InventoryCrafting know about its result slot ++ this.player = playerInventory; // CraftBukkit - save player ++ setTitle(Component.translatable("container.crafting")); // SPIGOT-4722: Allocate title for player inventory ++ // CraftBukkit end ++ this.addSlot(new ResultSlot(playerInventory.player, this.craftSlots, this.resultSlots, 0, 154, 28)); + + int i; + int j; +@@ -276,8 +273,14 @@ + } + + @Override ++ public boolean shouldMoveToInventory(int slotIndex) { ++ return slotIndex != this.getResultSlotIndex(); ++ } ++ ++ // CraftBukkit start + @Override + public boolean shouldMoveToInventory(int i) { + return i != this.getResultSlotIndex(); + } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/ItemCombinerMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/ItemCombinerMenu.java.patch new file mode 100644 index 0000000000..80316c4c94 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/ItemCombinerMenu.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/inventory/ItemCombinerMenu.java ++++ b/net/minecraft/world/inventory/ItemCombinerMenu.java +@@ -132,8 +124,9 @@ + @Override + @Override + public boolean stillValid(Player player) { +- return (Boolean) this.access.evaluate((level, blockpos) -> { +- return !this.isValidBlock(level.getBlockState(blockpos)) ? false : player.distanceToSqr((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D) <= 64.0D; ++ if (!this.checkReachable) return true; // CraftBukkit ++ return (Boolean) this.access.evaluate((world, blockposition) -> { ++ return !this.isValidBlock(world.getBlockState(blockposition)) ? false : player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) <= 64.0D; + }, true); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/LecternMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/LecternMenu.java.patch new file mode 100644 index 0000000000..fbce988295 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/LecternMenu.java.patch @@ -0,0 +1,87 @@ +--- a/net/minecraft/world/inventory/LecternMenu.java ++++ b/net/minecraft/world/inventory/LecternMenu.java +@@ -4,9 +4,31 @@ + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.level.block.entity.LecternBlockEntity.LecternInventory; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.inventory.CraftInventoryLectern; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerTakeLecternBookEvent; ++// CraftBukkit end + + public class LecternMenu extends AbstractContainerMenu { + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryLectern inventory = new CraftInventoryLectern(this.lectern); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + private static final int DATA_COUNT = 1; + private static final int SLOT_COUNT = 1; + public static final int BUTTON_PREV_PAGE = 1; +@@ -16,11 +38,13 @@ + private final Container lectern; + private final ContainerData lecternData; + +- public LecternMenu(int i) { +- this(i, new SimpleContainer(1), new SimpleContainerData(1)); ++ // CraftBukkit start - add player ++ public LecternMenu(int i, Inventory playerinventory) { ++ this(i, new SimpleContainer(1), new SimpleContainerData(1), playerinventory); + } + +- public LecternMenu(int i, Container container, ContainerData containerdata) { ++ public LecternMenu(int i, Container iinventory, ContainerData icontainerproperties, Inventory playerinventory) { ++ // CraftBukkit end + super(MenuType.LECTERN, i); + checkContainerSize(container, 1); + checkContainerDataCount(containerdata, 1); +@@ -34,7 +57,8 @@ + LecternMenu.this.slotsChanged(this.container); + } + }); +- this.addDataSlots(containerdata); ++ this.addDataSlots(icontainerproperties); ++ player = (Player) playerinventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override +@@ -61,6 +84,13 @@ + return false; + } + ++ // CraftBukkit start - Event for taking the book ++ PlayerTakeLecternBookEvent event = new PlayerTakeLecternBookEvent(player, ((CraftInventoryLectern) getBukkitView().getTopInventory()).getHolder()); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end + ItemStack itemstack = this.lectern.removeItemNoUpdate(0); + + this.lectern.setChanged(); +@@ -89,8 +117,9 @@ + } + + @Override +- @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (lectern instanceof LecternInventory && !((LecternInventory) lectern).getLectern().hasBook()) return false; // CraftBukkit ++ if (!this.checkReachable) return true; // CraftBukkit + return this.lectern.stillValid(player); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/LoomMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/LoomMenu.java.patch new file mode 100644 index 0000000000..d748ed1303 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/LoomMenu.java.patch @@ -0,0 +1,92 @@ +--- a/net/minecraft/world/inventory/LoomMenu.java ++++ b/net/minecraft/world/inventory/LoomMenu.java +@@ -23,9 +22,30 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.BannerPattern; + import net.minecraft.world.level.block.entity.BlockEntityType; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.inventory.CraftInventoryLoom; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class LoomMenu extends AbstractContainerMenu { + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryLoom inventory = new CraftInventoryLoom(this.inputContainer, this.outputContainer); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + private static final int PATTERN_NOT_SET = -1; + private static final int INV_SLOT_START = 4; + private static final int INV_SLOT_END = 31; +@@ -61,6 +80,13 @@ + LoomMenu.this.slotsChanged(this); + LoomMenu.this.slotUpdateListener.run(); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end + }; + this.outputContainer = new SimpleContainer(1) { + @Override +@@ -69,6 +94,13 @@ + super.setChanged(); + LoomMenu.this.slotUpdateListener.run(); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end + }; + this.access = containerlevelaccess; + this.bannerSlot = this.addSlot(new Slot(this.inputContainer, 0, 13, 26) { +@@ -134,11 +161,12 @@ + } + + this.addDataSlot(this.selectedBannerPatternIndex); ++ player = (Player) playerInventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override +- @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.LOOM); + } + +@@ -318,8 +342,13 @@ + CompoundTag compoundtag = BlockItem.getBlockEntityData(itemstack2); + ListTag listtag; + +- if (compoundtag != null && compoundtag.contains("Patterns", 9)) { +- listtag = compoundtag.getList("Patterns", 10); ++ if (nbttagcompound != null && nbttagcompound.contains("Patterns", 9)) { ++ nbttaglist = nbttagcompound.getList("Patterns", 10); ++ // CraftBukkit start ++ while (nbttaglist.size() > 20) { ++ nbttaglist.remove(20); ++ } ++ // CraftBukkit end + } else { + listtag = new ListTag(); + if (compoundtag == null) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/MenuType.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/MenuType.java.patch new file mode 100644 index 0000000000..70d67be914 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/MenuType.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/inventory/MenuType.java ++++ b/net/minecraft/world/inventory/MenuType.java +@@ -27,8 +27,8 @@ + public static final MenuType FURNACE = register("furnace", FurnaceMenu::new); + public static final MenuType GRINDSTONE = register("grindstone", GrindstoneMenu::new); + public static final MenuType HOPPER = register("hopper", HopperMenu::new); +- public static final MenuType LECTERN = register("lectern", (i, inventory) -> { +- return new LecternMenu(i); ++ public static final MenuType LECTERN = register("lectern", (i, playerinventory) -> { ++ return new LecternMenu(i, playerinventory); // CraftBukkit + }); + public static final MenuType LOOM = register("loom", LoomMenu::new); + public static final MenuType MERCHANT = register("merchant", MerchantMenu::new); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/MerchantContainer.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/MerchantContainer.java.patch new file mode 100644 index 0000000000..b7fc503096 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/MerchantContainer.java.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/world/inventory/MerchantContainer.java ++++ b/net/minecraft/world/inventory/MerchantContainer.java +@@ -10,6 +12,13 @@ + import net.minecraft.world.item.trading.Merchant; + import net.minecraft.world.item.trading.MerchantOffer; + import net.minecraft.world.item.trading.MerchantOffers; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.entity.CraftAbstractVillager; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end + + public class MerchantContainer implements Container { + +@@ -20,6 +29,46 @@ + private int selectionHint; + private int futureXp; + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.itemStacks; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ merchant.setTradingPlayer((Player) null); // SPIGOT-4860 ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return (merchant instanceof AbstractVillager) ? (CraftAbstractVillager) ((AbstractVillager) this.merchant).getBukkitEntity() : null; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return (merchant instanceof Villager) ? ((Villager) this.merchant).getBukkitEntity().getLocation() : null; ++ } ++ // CraftBukkit end ++ + public MerchantContainer(Merchant merchant) { + this.itemStacks = NonNullList.withSize(3, ItemStack.EMPTY); + this.merchant = merchant; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/MerchantMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/MerchantMenu.java.patch new file mode 100644 index 0000000000..25c8a20f81 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/MerchantMenu.java.patch @@ -0,0 +1,50 @@ +--- a/net/minecraft/world/inventory/MerchantMenu.java ++++ b/net/minecraft/world/inventory/MerchantMenu.java +@@ -11,6 +11,7 @@ + import net.minecraft.world.item.trading.Merchant; + import net.minecraft.world.item.trading.MerchantOffer; + import net.minecraft.world.item.trading.MerchantOffers; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; // CraftBukkit + + public class MerchantMenu extends AbstractContainerMenu { + +@@ -31,9 +32,18 @@ + private boolean showProgressBar; + private boolean canRestock; + +- public MerchantMenu(int i, Inventory inventory) { +- this(i, inventory, new ClientSideMerchant(inventory.player)); ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity == null) { ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), new org.bukkit.craftbukkit.inventory.CraftInventoryMerchant(trader, tradeContainer), this); ++ } ++ return bukkitEntity; + } ++ // CraftBukkit end + + public MerchantMenu(int i, Inventory inventory, Merchant merchant) { + super(MenuType.MERCHANT, i); +@@ -41,7 +55,8 @@ + this.tradeContainer = new MerchantContainer(merchant); + this.addSlot(new Slot(this.tradeContainer, 0, 136, 37)); + this.addSlot(new Slot(this.tradeContainer, 1, 162, 37)); +- this.addSlot(new MerchantResultSlot(inventory.player, merchant, this.tradeContainer, 2, 220, 37)); ++ this.addSlot(new MerchantResultSlot(playerInventory.player, trader, this.tradeContainer, 2, 220, 37)); ++ this.player = playerInventory; // CraftBukkit - save player + + int j; + +@@ -158,7 +169,7 @@ + } + + private void playTradeSound() { +- if (!this.trader.isClientSide()) { ++ if (!this.trader.isClientSide() && this.trader instanceof Entity) { // CraftBukkit - SPIGOT-5035 + Entity entity = (Entity) this.trader; + + entity.level().playLocalSound(entity.getX(), entity.getY(), entity.getZ(), this.trader.getNotifyTradeSound(), SoundSource.NEUTRAL, 1.0F, 1.0F, false); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/PlayerEnderChestContainer.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/PlayerEnderChestContainer.java.patch new file mode 100644 index 0000000000..5705f524dd --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/PlayerEnderChestContainer.java.patch @@ -0,0 +1,26 @@ +--- a/net/minecraft/world/inventory/PlayerEnderChestContainer.java ++++ b/net/minecraft/world/inventory/PlayerEnderChestContainer.java +@@ -7,14 +7,23 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.entity.EnderChestBlockEntity; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end + + public class PlayerEnderChestContainer extends SimpleContainer { + + @Nullable + private EnderChestBlockEntity activeChest; ++ // CraftBukkit start ++ private final Player owner; + + public PlayerEnderChestContainer() { + super(27); ++ this.owner = owner; ++ // CraftBukkit end + } + + public void setActiveChest(EnderChestBlockEntity enderchestblockentity) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/ResultContainer.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/ResultContainer.java.patch new file mode 100644 index 0000000000..76f0416155 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/ResultContainer.java.patch @@ -0,0 +1,54 @@ +--- a/net/minecraft/world/inventory/ResultContainer.java ++++ b/net/minecraft/world/inventory/ResultContainer.java +@@ -9,12 +9,51 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.crafting.RecipeHolder; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class ResultContainer implements Container, RecipeCraftingHolder { + + private final NonNullList itemStacks; + @Nullable + private RecipeHolder recipeUsed; + ++ // CraftBukkit start ++ private int maxStack = MAX_STACK; ++ ++ public java.util.List getContents() { ++ return this.itemStacks; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return null; // Result slots don't get an owner ++ } ++ ++ // Don't need a transaction; the InventoryCrafting keeps track of it for us ++ public void onOpen(CraftHumanEntity who) {} ++ public void onClose(CraftHumanEntity who) {} ++ public java.util.List getViewers() { ++ return new java.util.ArrayList(); ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return null; ++ } ++ // CraftBukkit end ++ + public ResultContainer() { + this.itemStacks = NonNullList.withSize(1, ItemStack.EMPTY); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/ShulkerBoxMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/ShulkerBoxMenu.java.patch new file mode 100644 index 0000000000..6f85526956 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/ShulkerBoxMenu.java.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/world/inventory/ShulkerBoxMenu.java ++++ b/net/minecraft/world/inventory/ShulkerBoxMenu.java +@@ -6,20 +6,30 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class ShulkerBoxMenu extends AbstractContainerMenu { + + private static final int CONTAINER_SIZE = 27; + private final Container container; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity; ++ private Inventory player; + + public ShulkerBoxMenu(int i, Inventory inventory) { + this(i, inventory, new SimpleContainer(27)); + } ++ // CraftBukkit end + + public ShulkerBoxMenu(int i, Inventory inventory, Container container) { + super(MenuType.SHULKER_BOX, i); + checkContainerSize(container, 27); + this.container = container; +- container.startOpen(inventory.player); ++ this.player = playerInventory; // CraftBukkit - save player ++ container.startOpen(playerInventory.player); + boolean flag = true; + boolean flag1 = true; + +@@ -47,6 +66,7 @@ + @Override + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(player); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/SmithingMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/SmithingMenu.java.patch new file mode 100644 index 0000000000..cb8ee7ea9a --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/SmithingMenu.java.patch @@ -0,0 +1,60 @@ +--- a/net/minecraft/world/inventory/SmithingMenu.java ++++ b/net/minecraft/world/inventory/SmithingMenu.java +@@ -13,6 +13,8 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; + ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; // CraftBukkit ++ + public class SmithingMenu extends ItemCombinerMenu { + + public static final int TEMPLATE_SLOT = 0; +@@ -28,6 +30,9 @@ + @Nullable + private RecipeHolder selectedRecipe; + private final List> recipes; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity; ++ // CraftBukkit end + + public SmithingMenu(int i, Inventory inventory) { + this(i, inventory, ContainerLevelAccess.NULL); +@@ -102,7 +102,7 @@ + List> list = this.level.getRecipeManager().getRecipesFor(RecipeType.SMITHING, this.inputSlots, this.level); + + if (list.isEmpty()) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareSmithingEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + } else { + RecipeHolder recipeholder = (RecipeHolder) list.get(0); + ItemStack itemstack = ((SmithingRecipe) recipeholder.value()).assemble(this.inputSlots, this.level.registryAccess()); +@@ -110,7 +110,9 @@ + if (itemstack.isItemEnabled(this.level.enabledFeatures())) { + this.selectedRecipe = recipeholder; + this.resultSlots.setRecipeUsed(recipeholder); +- this.resultSlots.setItem(0, itemstack); ++ // CraftBukkit start ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareSmithingEvent(getBukkitView(), itemstack); ++ // CraftBukkit end + } + } + +@@ -145,4 +144,18 @@ + return !this.getSlot(i).hasItem(); + }).findFirst(); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventory inventory = new org.bukkit.craftbukkit.inventory.CraftInventorySmithing( ++ access.getLocation(), this.inputSlots, this.resultSlots); ++ bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/StonecutterMenu.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/StonecutterMenu.java.patch new file mode 100644 index 0000000000..6d483e63b5 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/StonecutterMenu.java.patch @@ -0,0 +1,64 @@ +--- a/net/minecraft/world/inventory/StonecutterMenu.java ++++ b/net/minecraft/world/inventory/StonecutterMenu.java +@@ -16,6 +15,13 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.inventory.CraftInventoryStonecutter; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++// CraftBukkit end ++ + public class StonecutterMenu extends AbstractContainerMenu { + + public static final int INPUT_SLOT = 0; +@@ -35,10 +41,14 @@ + Runnable slotUpdateListener; + public final Container container; + final ResultContainer resultContainer; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; + + public StonecutterMenu(int i, Inventory inventory) { + this(i, inventory, ContainerLevelAccess.NULL); + } ++ // CraftBukkit end + + public StonecutterMenu(int i, Inventory inventory, final ContainerLevelAccess containerlevelaccess) { + super(MenuType.STONECUTTER, i); +@@ -55,6 +75,13 @@ + StonecutterMenu.this.slotsChanged(this); + StonecutterMenu.this.slotUpdateListener.run(); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end + }; + this.resultContainer = new ResultContainer(); + this.access = containerlevelaccess; +@@ -108,6 +133,7 @@ + } + + this.addDataSlot(this.selectedRecipeIndex); ++ player = (Player) playerInventory.player.getBukkitEntity(); // CraftBukkit + } + + public int getSelectedRecipeIndex() { +@@ -127,8 +153,8 @@ + } + + @Override +- @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.STONECUTTER); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/TransientCraftingContainer.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/TransientCraftingContainer.java.patch new file mode 100644 index 0000000000..b665ab63fe --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/inventory/TransientCraftingContainer.java.patch @@ -0,0 +1,74 @@ +--- a/net/minecraft/world/inventory/TransientCraftingContainer.java ++++ b/net/minecraft/world/inventory/TransientCraftingContainer.java +@@ -8,15 +9,29 @@ + import net.minecraft.world.entity.player.StackedContents; + import net.minecraft.world.item.ItemStack; + +-public class TransientCraftingContainer implements CraftingContainer { ++// CraftBukkit start ++import java.util.List; ++import net.minecraft.world.item.crafting.RecipeHolder; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.event.inventory.InventoryType; ++// CraftBukkit end + + private final NonNullList items; + private final int width; + private final int height; + private final AbstractContainerMenu menu; + +- public TransientCraftingContainer(AbstractContainerMenu abstractcontainermenu, int i, int j) { +- this(abstractcontainermenu, i, j, NonNullList.withSize(i * j, ItemStack.EMPTY)); ++ // CraftBukkit start - add fields ++ public List transaction = new java.util.ArrayList(); ++ private RecipeHolder currentRecipe; ++ public Container resultInventory; ++ private Player owner; ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.items; + } + + public TransientCraftingContainer(AbstractContainerMenu abstractcontainermenu, int i, int j, NonNullList nonnulllist) { +@@ -28,6 +67,38 @@ + + @Override + @Override ++ public Location getLocation() { ++ return menu instanceof CraftingMenu ? ((CraftingMenu) menu).access.getLocation() : owner.getBukkitEntity().getLocation(); ++ } ++ ++ @Override ++ public RecipeHolder getCurrentRecipe() { ++ return currentRecipe; ++ } ++ ++ @Override ++ public void setCurrentRecipe(RecipeHolder currentRecipe) { ++ this.currentRecipe = currentRecipe; ++ } ++ ++ public TransientCraftingContainer(AbstractContainerMenu container, int i, int j, Player player) { ++ this(container, i, j); ++ this.owner = player; ++ } ++ // CraftBukkit end ++ ++ public TransientCraftingContainer(AbstractContainerMenu menu, int width, int height) { ++ this(menu, width, height, NonNullList.withSize(width * height, ItemStack.EMPTY)); ++ } ++ ++ public TransientCraftingContainer(AbstractContainerMenu menu, int width, int height, NonNullList items) { ++ this.items = items; ++ this.menu = menu; ++ this.width = width; ++ this.height = height; ++ } ++ ++ @Override + public int getContainerSize() { + return this.items.size(); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/ArmorItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/ArmorItem.java.patch new file mode 100644 index 0000000000..3d4e9cf80c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/ArmorItem.java.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/item/ArmorItem.java ++++ b/net/minecraft/world/item/ArmorItem.java +@@ -26,6 +26,11 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.DispenserBlock; + import net.minecraft.world.phys.AABB; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseArmorEvent; ++// CraftBukkit end + + public class ArmorItem extends Item implements Equipable { + +@@ -59,6 +63,10 @@ + LivingEntity livingentity = (LivingEntity) list.get(0); + EquipmentSlot equipmentslot = Mob.getEquipmentSlotForItem(itemstack); + ItemStack itemstack1 = itemstack.split(1); ++ // CraftBukkit start ++ Level world = sourceblock.level(); ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + + livingentity.setItemSlot(equipmentslot, itemstack1); + if (livingentity instanceof Mob) { +@@ -66,6 +73,29 @@ + ((Mob) livingentity).setPersistenceRequired(); + } + ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return false; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return true; ++ } ++ } ++ ++ entityliving.setItemSlot(enumitemslot, CraftItemStack.asNMSCopy(event.getItem())); ++ // CraftBukkit end ++ if (entityliving instanceof Mob) { ++ ((Mob) entityliving).setDropChance(enumitemslot, 2.0F); ++ ((Mob) entityliving).setPersistenceRequired(); ++ } ++ + return true; + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/ArmorStandItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/ArmorStandItem.java.patch new file mode 100644 index 0000000000..e5d15f07cd --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/ArmorStandItem.java.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/item/ArmorStandItem.java ++++ b/net/minecraft/world/item/ArmorStandItem.java +@@ -53,10 +52,15 @@ + + float f = (float) Mth.floor((Mth.wrapDegrees(useoncontext.getRotation() - 180.0F) + 22.5F) / 45.0F) * 45.0F; + +- armorstand.moveTo(armorstand.getX(), armorstand.getY(), armorstand.getZ(), f, 0.0F); +- serverlevel.addFreshEntityWithPassengers(armorstand); +- level.playSound((Player) null, armorstand.getX(), armorstand.getY(), armorstand.getZ(), SoundEvents.ARMOR_STAND_PLACE, SoundSource.BLOCKS, 0.75F, 0.8F); +- armorstand.gameEvent(GameEvent.ENTITY_PLACE, useoncontext.getPlayer()); ++ entityarmorstand.moveTo(entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), f, 0.0F); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(context, entityarmorstand).isCancelled()) { ++ return InteractionResult.FAIL; ++ } ++ // CraftBukkit end ++ worldserver.addFreshEntityWithPassengers(entityarmorstand); ++ world.playSound((Player) null, entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), SoundEvents.ARMOR_STAND_PLACE, SoundSource.BLOCKS, 0.75F, 0.8F); ++ entityarmorstand.gameEvent(GameEvent.ENTITY_PLACE, context.getPlayer()); + } + + itemstack.shrink(1); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/BlockItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/BlockItem.java.patch new file mode 100644 index 0000000000..b415a4a867 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/BlockItem.java.patch @@ -0,0 +1,125 @@ +--- a/net/minecraft/world/item/BlockItem.java ++++ b/net/minecraft/world/item/BlockItem.java +@@ -32,6 +32,10 @@ + import net.minecraft.world.level.block.state.properties.Property; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.CollisionContext; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.event.block.BlockCanBuildEvent; ++// CraftBukkit end + + public class BlockItem extends Item { + +@@ -71,7 +74,13 @@ + if (blockplacecontext1 == null) { + return InteractionResult.FAIL; + } else { +- BlockState blockstate = this.getPlacementState(blockplacecontext1); ++ IBlockData iblockdata = this.getPlacementState(blockactioncontext1); ++ // CraftBukkit start - special case for handling block placement with water lilies and snow buckets ++ org.bukkit.block.BlockState blockstate = null; ++ if (this instanceof PlaceOnWaterBlockItem || this instanceof SolidBucketItem) { ++ blockstate = org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockactioncontext1.getLevel(), blockactioncontext1.getClickedPos()); ++ } ++ // CraftBukkit end + + if (blockstate == null) { + return InteractionResult.FAIL; +@@ -84,20 +93,33 @@ + ItemStack itemstack = blockplacecontext1.getItemInHand(); + BlockState blockstate1 = level.getBlockState(blockpos); + +- if (blockstate1.is(blockstate.getBlock())) { +- blockstate1 = this.updateBlockStateFromTag(blockpos, level, itemstack, blockstate1); +- this.updateCustomBlockEntityTag(blockpos, level, player, itemstack, blockstate1); +- blockstate1.getBlock().setPlacedBy(level, blockpos, blockstate1, player, itemstack); +- if (player instanceof ServerPlayer) { +- CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) player, blockpos, itemstack); ++ if (iblockdata1.is(iblockdata.getBlock())) { ++ iblockdata1 = this.updateBlockStateFromTag(blockposition, world, itemstack, iblockdata1); ++ this.updateCustomBlockEntityTag(blockposition, world, entityhuman, itemstack, iblockdata1); ++ iblockdata1.getBlock().setPlacedBy(world, blockposition, iblockdata1, entityhuman, itemstack); ++ // CraftBukkit start ++ if (blockstate != null) { ++ org.bukkit.event.block.BlockPlaceEvent placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEvent((ServerLevel) world, entityhuman, blockactioncontext1.getHand(), blockstate, blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild())) { ++ blockstate.update(true, false); ++ ++ if (this instanceof SolidBucketItem) { ++ ((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 ++ } ++ return InteractionResult.FAIL; ++ } + } ++ // CraftBukkit end ++ if (entityhuman instanceof ServerPlayer) { ++ CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) entityhuman, blockposition, itemstack); ++ } + } + + SoundType soundtype = blockstate1.getSoundType(); + +- level.playSound(player, blockpos, this.getPlaceSound(blockstate1), SoundSource.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F); +- level.gameEvent(GameEvent.BLOCK_PLACE, blockpos, GameEvent.Context.of(player, blockstate1)); +- if (player == null || !player.getAbilities().instabuild) { ++ // world.playSound(entityhuman, blockposition, this.getPlaceSound(iblockdata1), SoundCategory.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F); ++ world.gameEvent(GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(entityhuman, iblockdata1)); ++ if ((entityhuman == null || !entityhuman.getAbilities().instabuild) && itemstack != ItemStack.EMPTY) { // CraftBukkit + itemstack.shrink(1); + } + +@@ -131,11 +153,26 @@ + BlockState blockstate1 = blockstate; + CompoundTag compoundtag = itemstack.getTag(); + +- if (compoundtag != null) { +- CompoundTag compoundtag1 = compoundtag.getCompound("BlockStateTag"); +- StateDefinition statedefinition = blockstate.getBlock().getStateDefinition(); +- Iterator iterator = compoundtag1.getAllKeys().iterator(); ++ if (nbttagcompound != null) { ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("BlockStateTag"); ++ // CraftBukkit start ++ iblockdata1 = getBlockState(iblockdata1, nbttagcompound1); ++ } + ++ if (iblockdata1 != state) { ++ level.setBlock(pos, iblockdata1, 2); ++ } ++ ++ return iblockdata1; ++ } ++ ++ public static IBlockData getBlockState(IBlockData iblockdata, CompoundTag nbttagcompound1) { ++ IBlockData iblockdata1 = iblockdata; ++ { ++ // CraftBukkit end ++ StateDefinition blockstatelist = iblockdata.getBlock().getStateDefinition(); ++ Iterator iterator = nbttagcompound1.getAllKeys().iterator(); ++ + while (iterator.hasNext()) { + String s = (String) iterator.next(); + Property property = statedefinition.getProperty(s); +@@ -161,11 +193,18 @@ + }).orElse(blockstate); + } + +- protected boolean canPlace(BlockPlaceContext blockplacecontext, BlockState blockstate) { +- Player player = blockplacecontext.getPlayer(); +- CollisionContext collisioncontext = player == null ? CollisionContext.empty() : CollisionContext.of(player); ++ protected boolean canPlace(BlockPlaceContext context, IBlockData state) { ++ Player entityhuman = context.getPlayer(); ++ CollisionContext voxelshapecollision = entityhuman == null ? CollisionContext.empty() : CollisionContext.of(entityhuman); ++ // CraftBukkit start - store default return ++ boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && context.getLevel().isUnobstructed(state, context.getClickedPos(), voxelshapecollision); ++ org.bukkit.entity.Player player = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null; + +- return (!this.mustSurvive() || blockstate.canSurvive(blockplacecontext.getLevel(), blockplacecontext.getClickedPos())) && blockplacecontext.getLevel().isUnobstructed(blockstate, blockplacecontext.getClickedPos(), collisioncontext); ++ BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(context.getLevel(), context.getClickedPos()), player, CraftBlockData.fromData(state), defaultReturn); ++ context.getLevel().getCraftServer().getPluginManager().callEvent(event); ++ ++ return event.isBuildable(); ++ // CraftBukkit end + } + + protected boolean mustSurvive() { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/BoatItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/BoatItem.java.patch new file mode 100644 index 0000000000..454abde943 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/BoatItem.java.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/world/item/BoatItem.java ++++ b/net/minecraft/world/item/BoatItem.java +@@ -60,17 +59,32 @@ + } + } + +- if (blockhitresult.getType() == HitResult.Type.BLOCK) { +- Boat boat = this.getBoat(level, blockhitresult, itemstack, player); ++ if (movingobjectpositionblock.getType() == HitResult.EnumMovingObjectType.BLOCK) { ++ // CraftBukkit start - Boat placement ++ org.bukkit.event.player.PlayerInteractEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(player, org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), itemstack, false, hand, movingobjectpositionblock.getLocation()); + +- boat.setVariant(this.type); +- boat.setYRot(player.getYRot()); +- if (!level.noCollision(boat, boat.getBoundingBox())) { ++ if (event.isCancelled()) { ++ return InteractionResultHolder.pass(itemstack); ++ } ++ // CraftBukkit end ++ Boat entityboat = this.getBoat(level, movingobjectpositionblock, itemstack, player); ++ ++ entityboat.setVariant(this.type); ++ entityboat.setYRot(player.getYRot()); ++ if (!level.noCollision(entityboat, entityboat.getBoundingBox())) { + return InteractionResultHolder.fail(itemstack); + } else { + if (!level.isClientSide) { +- level.addFreshEntity(boat); +- level.gameEvent((Entity) player, GameEvent.ENTITY_PLACE, blockhitresult.getLocation()); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(level, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), player, entityboat, hand).isCancelled()) { ++ return InteractionResultHolder.fail(itemstack); ++ } ++ ++ if (!level.addFreshEntity(entityboat)) { ++ return InteractionResultHolder.pass(itemstack); ++ } ++ // CraftBukkit end ++ level.gameEvent((Entity) player, GameEvent.ENTITY_PLACE, movingobjectpositionblock.getLocation()); + if (!player.getAbilities().instabuild) { + itemstack.shrink(1); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/BoneMealItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/BoneMealItem.java.patch new file mode 100644 index 0000000000..881e489080 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/BoneMealItem.java.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/world/item/BoneMealItem.java ++++ b/net/minecraft/world/item/BoneMealItem.java +@@ -33,16 +33,21 @@ + } + + @Override +- @Override +- public InteractionResult useOn(UseOnContext useoncontext) { +- Level level = useoncontext.getLevel(); +- BlockPos blockpos = useoncontext.getClickedPos(); +- BlockPos blockpos1 = blockpos.relative(useoncontext.getClickedFace()); ++ public InteractionResult useOn(UseOnContext context) { ++ // CraftBukkit start - extract bonemeal application logic to separate, static method ++ return applyBonemeal(context); ++ } + +- if (growCrop(useoncontext.getItemInHand(), level, blockpos)) { +- if (!level.isClientSide) { +- useoncontext.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); +- level.levelEvent(1505, blockpos, 0); ++ public static InteractionResult applyBonemeal(UseOnContext itemactioncontext) { ++ // CraftBukkit end ++ Level world = itemactioncontext.getLevel(); ++ BlockPos blockposition = itemactioncontext.getClickedPos(); ++ BlockPos blockposition1 = blockposition.relative(itemactioncontext.getClickedFace()); ++ ++ if (growCrop(itemactioncontext.getItemInHand(), world, blockposition)) { ++ if (!world.isClientSide) { ++ if (itemactioncontext.getPlayer() != null) itemactioncontext.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); // CraftBukkit - SPIGOT-7518 ++ world.levelEvent(1505, blockposition, 0); + } + + return InteractionResult.sidedSuccess(level.isClientSide); +@@ -50,10 +55,10 @@ + BlockState blockstate = level.getBlockState(blockpos); + boolean flag = blockstate.isFaceSturdy(level, blockpos, useoncontext.getClickedFace()); + +- if (flag && growWaterPlant(useoncontext.getItemInHand(), level, blockpos1, useoncontext.getClickedFace())) { +- if (!level.isClientSide) { +- useoncontext.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); +- level.levelEvent(1505, blockpos1, 0); ++ if (flag && growWaterPlant(itemactioncontext.getItemInHand(), world, blockposition1, itemactioncontext.getClickedFace())) { ++ if (!world.isClientSide) { ++ if (itemactioncontext.getPlayer() != null) itemactioncontext.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); // CraftBukkit - SPIGOT-7518 ++ world.levelEvent(1505, blockposition1, 0); + } + + return InteractionResult.sidedSuccess(level.isClientSide); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/BowItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/BowItem.java.patch new file mode 100644 index 0000000000..1f61431d98 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/BowItem.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/item/BowItem.java ++++ b/net/minecraft/world/item/BowItem.java +@@ -65,6 +64,14 @@ + if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.FLAMING_ARROWS, itemstack) > 0) { + abstractarrow.setSecondsOnFire(100); + } ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(entityhuman, stack, itemstack1, entityarrow, entityhuman.getUsedItemHand(), f, !flag1); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ flag1 = !event.shouldConsumeItem(); ++ // CraftBukkit end + + itemstack.hurtAndBreak(1, player, (player1) -> { + player1.broadcastBreakEvent(player.getUsedItemHand()); +@@ -73,7 +80,16 @@ + abstractarrow.pickup = AbstractArrow.Pickup.CREATIVE_ONLY; + } + +- level.addFreshEntity(abstractarrow); ++ // CraftBukkit start ++ if (event.getProjectile() == entityarrow.getBukkitEntity()) { ++ if (!level.addFreshEntity(entityarrow)) { ++ if (entityhuman instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } ++ return; ++ } ++ } ++ // CraftBukkit end + } + + level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.ARROW_SHOOT, SoundSource.PLAYERS, 1.0F, 1.0F / (level.getRandom().nextFloat() * 0.4F + 1.2F) + f * 0.5F); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/BucketItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/BucketItem.java.patch new file mode 100644 index 0000000000..9738ca0790 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/BucketItem.java.patch @@ -0,0 +1,107 @@ +--- a/net/minecraft/world/item/BucketItem.java ++++ b/net/minecraft/world/item/BucketItem.java +@@ -28,6 +30,12 @@ + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.HitResult; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.DummyGeneratorAccess; ++import org.bukkit.event.player.PlayerBucketEmptyEvent; ++import org.bukkit.event.player.PlayerBucketFillEvent; ++// CraftBukkit end + + public class BucketItem extends Item implements DispensibleContainerItem { + +@@ -61,16 +68,27 @@ + Block block = blockstate.getBlock(); + + if (block instanceof BucketPickup) { +- BucketPickup bucketpickup = (BucketPickup) block; +- ItemStack itemstack1 = bucketpickup.pickupBlock(player, level, blockpos, blockstate); ++ BucketPickup ifluidsource = (BucketPickup) block; ++ // CraftBukkit start ++ ItemStack dummyFluid = ifluidsource.pickupBlock(player, DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); ++ if (dummyFluid.isEmpty()) return InteractionResultHolder.fail(itemstack); // Don't fire event if the bucket won't be filled. ++ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) level, player, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.getItem(), hand); + ++ if (event.isCancelled()) { ++ ((ServerPlayer) player).connection.send(new ClientboundBlockUpdatePacket(level, blockposition)); // SPIGOT-5163 (see PlayerInteractManager) ++ ((ServerPlayer) player).getBukkitEntity().updateInventory(); // SPIGOT-4541 ++ return InteractionResultHolder.fail(itemstack); ++ } ++ // CraftBukkit end ++ ItemStack itemstack1 = ifluidsource.pickupBlock(player, level, blockposition, iblockdata); ++ + if (!itemstack1.isEmpty()) { + player.awardStat(Stats.ITEM_USED.get(this)); + bucketpickup.getPickupSound().ifPresent((soundevent) -> { + player.playSound(soundevent, 1.0F, 1.0F); + }); +- level.gameEvent((Entity) player, GameEvent.FLUID_PICKUP, blockpos); +- ItemStack itemstack2 = ItemUtils.createFilledResult(itemstack, player, itemstack1); ++ level.gameEvent((Entity) player, GameEvent.FLUID_PICKUP, blockposition); ++ ItemStack itemstack2 = ItemUtils.createFilledResult(itemstack, player, CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit + + if (!level.isClientSide) { + CriteriaTriggers.FILLED_BUCKET.trigger((ServerPlayer) player, itemstack1); +@@ -85,8 +103,8 @@ + blockstate = level.getBlockState(blockpos); + BlockPos blockpos2 = blockstate.getBlock() instanceof LiquidBlockContainer && this.content == Fluids.WATER ? blockpos : blockpos1; + +- if (this.emptyContents(player, level, blockpos2, blockhitresult)) { +- this.checkExtraContent(player, level, itemstack, blockpos2); ++ if (this.emptyContents(player, level, blockposition2, movingobjectpositionblock, movingobjectpositionblock.getDirection(), blockposition, itemstack, hand)) { // CraftBukkit ++ this.checkExtraContent(player, level, itemstack, blockposition2); + if (player instanceof ServerPlayer) { + CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) player, blockpos2, itemstack); + } +@@ -112,11 +129,16 @@ + public void checkExtraContent(@Nullable Player player, Level level, ItemStack itemstack, BlockPos blockpos) {} + + @Override +- @Override +- public boolean emptyContents(@Nullable Player player, Level level, BlockPos blockpos, @Nullable BlockHitResult blockhitresult) { +- Fluid fluid = this.content; ++ public boolean emptyContents(@Nullable Player player, Level level, BlockPos pos, @Nullable BlockHitResult result) { ++ // CraftBukkit start ++ return emptyContents(player, level, pos, result, null, null, null, EnumHand.MAIN_HAND); ++ } + +- if (!(fluid instanceof FlowingFluid)) { ++ public boolean emptyContents(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack, EnumHand enumhand) { ++ // CraftBukkit end ++ Fluid fluidtype = this.content; ++ ++ if (!(fluidtype instanceof FlowingFluid)) { + return false; + } else { + FlowingFluid flowingfluid; +@@ -151,12 +173,22 @@ + + boolean flag2 = flag1; + ++ // CraftBukkit start ++ if (flag2 && entityhuman != null) { ++ PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((ServerLevel) world, entityhuman, blockposition, clicked, enumdirection, itemstack, enumhand); ++ if (event.isCancelled()) { ++ ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-4238: needed when looking through entity ++ ((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 ++ return false; ++ } ++ } ++ // CraftBukkit end + if (!flag2) { +- return blockhitresult != null && this.emptyContents(player, level, blockhitresult.getBlockPos().relative(blockhitresult.getDirection()), (BlockHitResult) null); +- } else if (level.dimensionType().ultraWarm() && this.content.is(FluidTags.WATER)) { +- int i = blockpos.getX(); +- int j = blockpos.getY(); +- int k = blockpos.getZ(); ++ return movingobjectpositionblock != null && this.emptyContents(entityhuman, world, movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()), (BlockHitResult) null, enumdirection, clicked, itemstack, enumhand); // CraftBukkit ++ } else if (world.dimensionType().ultraWarm() && this.content.is(FluidTags.WATER)) { ++ int i = blockposition.getX(); ++ int j = blockposition.getY(); ++ int k = blockposition.getZ(); + + level.playSound(player, blockpos, SoundEvents.FIRE_EXTINGUISH, SoundSource.BLOCKS, 0.5F, 2.6F + (level.random.nextFloat() - level.random.nextFloat()) * 0.8F); + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/ChorusFruitItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/ChorusFruitItem.java.patch new file mode 100644 index 0000000000..7732cbb121 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/ChorusFruitItem.java.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/world/item/ChorusFruitItem.java ++++ b/net/minecraft/world/item/ChorusFruitItem.java +@@ -36,14 +35,23 @@ + + Vec3 vec3 = livingentity.position(); + +- if (livingentity.randomTeleport(d0, d1, d2, true)) { +- level.gameEvent(GameEvent.TELEPORT, vec3, GameEvent.Context.of((Entity) livingentity)); +- SoundEvent soundevent; +- SoundSource soundsource; ++ // CraftBukkit start - handle canceled status of teleport event ++ java.util.Optional status = entityLiving.randomTeleport(d0, d1, d2, true, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.CHORUS_FRUIT); + +- if (livingentity instanceof Fox) { +- soundevent = SoundEvents.FOX_TELEPORT; +- soundsource = SoundSource.NEUTRAL; ++ if (!status.isPresent()) { ++ // teleport event was canceled, no more tries ++ break; ++ } ++ ++ if (status.get()) { ++ // CraftBukkit end ++ level.gameEvent(GameEvent.TELEPORT, vec3d, GameEvent.Context.of((Entity) entityLiving)); ++ SoundEvent soundeffect; ++ SoundSource soundcategory; ++ ++ if (entityLiving instanceof Fox) { ++ soundeffect = SoundEvents.FOX_TELEPORT; ++ soundcategory = SoundSource.NEUTRAL; + } else { + soundevent = SoundEvents.CHORUS_FRUIT_TELEPORT; + soundsource = SoundSource.PLAYERS; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/CrossbowItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/CrossbowItem.java.patch new file mode 100644 index 0000000000..f4dee8fd60 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/CrossbowItem.java.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/world/item/CrossbowItem.java ++++ b/net/minecraft/world/item/CrossbowItem.java +@@ -240,12 +236,28 @@ + + ((Projectile) object).shoot((double) vector3f.x(), (double) vector3f.y(), (double) vector3f.z(), f1, f2); + } ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(shooter, crossbowStack, ammoStack, (Entity) object, shooter.getUsedItemHand(), soundPitch, true); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ // CraftBukkit end + + itemstack.hurtAndBreak(flag1 ? 3 : 1, livingentity, (livingentity1) -> { + livingentity1.broadcastBreakEvent(interactionhand); + }); +- level.addFreshEntity((Entity) object); +- level.playSound((Player) null, livingentity.getX(), livingentity.getY(), livingentity.getZ(), SoundEvents.CROSSBOW_SHOOT, SoundSource.PLAYERS, 1.0F, f); ++ // CraftBukkit start ++ if (event.getProjectile() == ((Entity) object).getBukkitEntity()) { ++ if (!level.addFreshEntity((Entity) object)) { ++ if (shooter instanceof ServerPlayer) { ++ ((ServerPlayer) shooter).getBukkitEntity().updateInventory(); ++ } ++ return; ++ } ++ } ++ // CraftBukkit end ++ level.playSound((Player) null, shooter.getX(), shooter.getY(), shooter.getZ(), SoundEvents.CROSSBOW_SHOOT, SoundSource.PLAYERS, 1.0F, soundPitch); + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/DebugStickItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/DebugStickItem.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/DebugStickItem.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/DyeItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/DyeItem.java.patch new file mode 100644 index 0000000000..74656d485b --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/DyeItem.java.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/item/DyeItem.java ++++ b/net/minecraft/world/item/DyeItem.java +@@ -12,6 +12,7 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.SignBlockEntity; ++import org.bukkit.event.entity.SheepDyeWoolEvent; // CraftBukkit + + public class DyeItem extends Item implements SignApplicator { + +@@ -33,8 +33,18 @@ + if (sheep.isAlive() && !sheep.isSheared() && sheep.getColor() != this.dyeColor) { + sheep.level().playSound(player, (Entity) sheep, SoundEvents.DYE_USE, SoundSource.PLAYERS, 1.0F, 1.0F); + if (!player.level().isClientSide) { +- sheep.setColor(this.dyeColor); +- itemstack.shrink(1); ++ // CraftBukkit start ++ byte bColor = (byte) this.dyeColor.getId(); ++ SheepDyeWoolEvent event = new SheepDyeWoolEvent((org.bukkit.entity.Sheep) entitysheep.getBukkitEntity(), org.bukkit.DyeColor.getByWoolData(bColor), (org.bukkit.entity.Player) player.getBukkitEntity()); ++ entitysheep.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return InteractionResult.PASS; ++ } ++ ++ entitysheep.setColor(DyeColor.byId((byte) event.getColor().getWoolData())); ++ // CraftBukkit end ++ stack.shrink(1); + } + + return InteractionResult.sidedSuccess(player.level().isClientSide); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/EggItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/EggItem.java.patch new file mode 100644 index 0000000000..c13da4b071 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/EggItem.java.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/world/item/EggItem.java ++++ b/net/minecraft/world/item/EggItem.java +@@ -20,13 +19,20 @@ + public InteractionResultHolder use(Level level, Player player, InteractionHand interactionhand) { + ItemStack itemstack = player.getItemInHand(interactionhand); + +- level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.EGG_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); ++ // world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); // CraftBukkit - moved down + if (!level.isClientSide) { + ThrownEgg thrownegg = new ThrownEgg(level, player); + +- thrownegg.setItem(itemstack); +- thrownegg.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 1.5F, 1.0F); +- level.addFreshEntity(thrownegg); ++ entityegg.setItem(itemstack); ++ entityegg.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 1.5F, 1.0F); ++ // CraftBukkit start ++ if (!level.addFreshEntity(entityegg)) { ++ if (player instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().updateInventory(); ++ } ++ return InteractionResultHolder.fail(itemstack); ++ } ++ // CraftBukkit end + } + + player.awardStat(Stats.ITEM_USED.get(this)); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/EndCrystalItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/EndCrystalItem.java.patch new file mode 100644 index 0000000000..706c3edb1e --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/EndCrystalItem.java.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/item/EndCrystalItem.java ++++ b/net/minecraft/world/item/EndCrystalItem.java +@@ -46,10 +45,15 @@ + if (level instanceof ServerLevel) { + EndCrystal endcrystal = new EndCrystal(level, d0 + 0.5D, d1, d2 + 0.5D); + +- endcrystal.setShowBottom(false); +- level.addFreshEntity(endcrystal); +- level.gameEvent((Entity) useoncontext.getPlayer(), GameEvent.ENTITY_PLACE, blockpos1); +- EndDragonFight enddragonfight = ((ServerLevel) level).getDragonFight(); ++ entityendercrystal.setShowBottom(false); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(context, entityendercrystal).isCancelled()) { ++ return InteractionResult.FAIL; ++ } ++ // CraftBukkit end ++ world.addFreshEntity(entityendercrystal); ++ world.gameEvent((Entity) context.getPlayer(), GameEvent.ENTITY_PLACE, blockposition1); ++ EndDragonFight enderdragonbattle = ((ServerLevel) world).getDragonFight(); + + if (enddragonfight != null) { + enddragonfight.tryRespawn(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/EnderEyeItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/EnderEyeItem.java.patch new file mode 100644 index 0000000000..bdbf4103f3 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/EnderEyeItem.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/item/EnderEyeItem.java ++++ b/net/minecraft/world/item/EnderEyeItem.java +@@ -88,10 +86,14 @@ + if (blockpos != null) { + EyeOfEnder eyeofender = new EyeOfEnder(level, player.getX(), player.getY(0.5D), player.getZ()); + +- eyeofender.setItem(itemstack); +- eyeofender.signalTo(blockpos); +- level.gameEvent(GameEvent.PROJECTILE_SHOOT, eyeofender.position(), GameEvent.Context.of((Entity) player)); +- level.addFreshEntity(eyeofender); ++ entityendersignal.setItem(itemstack); ++ entityendersignal.signalTo(blockposition); ++ level.gameEvent(GameEvent.PROJECTILE_SHOOT, entityendersignal.position(), GameEvent.Context.of((Entity) player)); ++ // CraftBukkit start ++ if (!level.addFreshEntity(entityendersignal)) { ++ return new InteractionResultHolder(InteractionResult.FAIL, itemstack); ++ } ++ // CraftBukkit end + if (player instanceof ServerPlayer) { + CriteriaTriggers.USED_ENDER_EYE.trigger((ServerPlayer) player, blockpos); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/EnderpearlItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/EnderpearlItem.java.patch new file mode 100644 index 0000000000..3dec247baf --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/EnderpearlItem.java.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/world/item/EnderpearlItem.java ++++ b/net/minecraft/world/item/EnderpearlItem.java +@@ -20,8 +19,7 @@ + public InteractionResultHolder use(Level level, Player player, InteractionHand interactionhand) { + ItemStack itemstack = player.getItemInHand(interactionhand); + +- level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); +- player.getCooldowns().addCooldown(this, 20); ++ // CraftBukkit start - change order + if (!level.isClientSide) { + ThrownEnderpearl thrownenderpearl = new ThrownEnderpearl(level, player); + +@@ -30,6 +33,10 @@ + level.addFreshEntity(thrownenderpearl); + } + ++ level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); ++ player.getCooldowns().addCooldown(this, 20); ++ // CraftBukkit end ++ + player.awardStat(Stats.ITEM_USED.get(this)); + if (!player.getAbilities().instabuild) { + itemstack.shrink(1); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/FireChargeItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/FireChargeItem.java.patch new file mode 100644 index 0000000000..4865beeaa3 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/FireChargeItem.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/world/item/FireChargeItem.java ++++ b/net/minecraft/world/item/FireChargeItem.java +@@ -31,18 +30,34 @@ + BlockState blockstate = level.getBlockState(blockpos); + boolean flag = false; + +- if (!CampfireBlock.canLight(blockstate) && !CandleBlock.canLight(blockstate) && !CandleCakeBlock.canLight(blockstate)) { +- blockpos = blockpos.relative(useoncontext.getClickedFace()); +- if (BaseFireBlock.canBePlacedAt(level, blockpos, useoncontext.getHorizontalDirection())) { +- this.playSound(level, blockpos); +- level.setBlockAndUpdate(blockpos, BaseFireBlock.getState(level, blockpos)); +- level.gameEvent((Entity) useoncontext.getPlayer(), GameEvent.BLOCK_PLACE, blockpos); ++ if (!CampfireBlock.canLight(iblockdata) && !CandleBlock.canLight(iblockdata) && !CandleCakeBlock.canLight(iblockdata)) { ++ blockposition = blockposition.relative(context.getClickedFace()); ++ if (BaseFireBlock.canBePlacedAt(world, blockposition, context.getHorizontalDirection())) { ++ // CraftBukkit start - fire BlockIgniteEvent ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FIREBALL, context.getPlayer()).isCancelled()) { ++ if (!context.getPlayer().getAbilities().instabuild) { ++ context.getItemInHand().shrink(1); ++ } ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end ++ this.playSound(world, blockposition); ++ world.setBlockAndUpdate(blockposition, BaseFireBlock.getState(world, blockposition)); ++ world.gameEvent((Entity) context.getPlayer(), GameEvent.BLOCK_PLACE, blockposition); + flag = true; + } + } else { +- this.playSound(level, blockpos); +- level.setBlockAndUpdate(blockpos, (BlockState) blockstate.setValue(BlockStateProperties.LIT, true)); +- level.gameEvent((Entity) useoncontext.getPlayer(), GameEvent.BLOCK_CHANGE, blockpos); ++ // CraftBukkit start - fire BlockIgniteEvent ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FIREBALL, context.getPlayer()).isCancelled()) { ++ if (!context.getPlayer().getAbilities().instabuild) { ++ context.getItemInHand().shrink(1); ++ } ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end ++ this.playSound(world, blockposition); ++ world.setBlockAndUpdate(blockposition, (IBlockData) iblockdata.setValue(BlockStateProperties.LIT, true)); ++ world.gameEvent((Entity) context.getPlayer(), GameEvent.BLOCK_CHANGE, blockposition); + flag = true; + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/FishingRodItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/FishingRodItem.java.patch new file mode 100644 index 0000000000..e7042e73eb --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/FishingRodItem.java.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/item/FishingRodItem.java ++++ b/net/minecraft/world/item/FishingRodItem.java +@@ -11,7 +11,10 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + +-public class FishingRodItem extends Item implements Vanishable { ++// CraftBukkit start ++import org.bukkit.event.player.PlayerFishEvent; ++import org.bukkit.craftbukkit.CraftEquipmentSlot; ++// CraftBukkit end + + public FishingRodItem(Item.Properties item_properties) { + super(item_properties); +@@ -39,7 +43,18 @@ + i = EnchantmentHelper.getFishingSpeedBonus(itemstack); + int j = EnchantmentHelper.getFishingLuckBonus(itemstack); + +- level.addFreshEntity(new FishingHook(player, level, j, i)); ++ // CraftBukkit start ++ FishingHook entityfishinghook = new FishingHook(player, level, j, i); ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((org.bukkit.entity.Player) player.getBukkitEntity(), null, (org.bukkit.entity.FishHook) entityfishinghook.getBukkitEntity(), CraftEquipmentSlot.getHand(hand), PlayerFishEvent.State.FISHING); ++ level.getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ player.fishing = null; ++ return InteractionResultHolder.pass(itemstack); ++ } ++ level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.FISHING_BOBBER_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); ++ level.addFreshEntity(entityfishinghook); ++ // CraftBukkit end + } + + player.awardStat(Stats.ITEM_USED.get(this)); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/FlintAndSteelItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/FlintAndSteelItem.java.patch new file mode 100644 index 0000000000..46e3e7dd6b --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/FlintAndSteelItem.java.patch @@ -0,0 +1,51 @@ +--- a/net/minecraft/world/item/FlintAndSteelItem.java ++++ b/net/minecraft/world/item/FlintAndSteelItem.java +@@ -35,9 +34,17 @@ + if (!CampfireBlock.canLight(blockstate) && !CandleBlock.canLight(blockstate) && !CandleCakeBlock.canLight(blockstate)) { + BlockPos blockpos1 = blockpos.relative(useoncontext.getClickedFace()); + +- if (BaseFireBlock.canBePlacedAt(level, blockpos1, useoncontext.getHorizontalDirection())) { +- level.playSound(player, blockpos1, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.4F + 0.8F); +- BlockState blockstate1 = BaseFireBlock.getState(level, blockpos1); ++ if (BaseFireBlock.canBePlacedAt(world, blockposition1, context.getHorizontalDirection())) { ++ // CraftBukkit start - Store the clicked block ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition1, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL, entityhuman).isCancelled()) { ++ context.getItemInHand().hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(context.getHand()); ++ }); ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end ++ world.playSound(entityhuman, blockposition1, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, world.getRandom().nextFloat() * 0.4F + 0.8F); ++ IBlockData iblockdata1 = BaseFireBlock.getState(world, blockposition1); + + level.setBlock(blockpos1, blockstate1, 11); + level.gameEvent((Entity) player, GameEvent.BLOCK_PLACE, blockpos); +@@ -55,14 +62,21 @@ + return InteractionResult.FAIL; + } + } else { +- level.playSound(player, blockpos, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.4F + 0.8F); +- level.setBlock(blockpos, (BlockState) blockstate.setValue(BlockStateProperties.LIT, true), 11); +- level.gameEvent((Entity) player, GameEvent.BLOCK_CHANGE, blockpos); +- if (player != null) { +- useoncontext.getItemInHand().hurtAndBreak(1, player, (player1) -> { +- player1.broadcastBreakEvent(useoncontext.getHand()); ++ // CraftBukkit start - Store the clicked block ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL, entityhuman).isCancelled()) { ++ context.getItemInHand().hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(context.getHand()); + }); + } ++ // CraftBukkit end ++ world.playSound(entityhuman, blockposition, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, world.getRandom().nextFloat() * 0.4F + 0.8F); ++ world.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockStateProperties.LIT, true), 11); ++ world.gameEvent((Entity) entityhuman, GameEvent.BLOCK_CHANGE, blockposition); ++ if (entityhuman != null) { ++ context.getItemInHand().hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(context.getHand()); ++ }); ++ } + + return InteractionResult.sidedSuccess(level.isClientSide()); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/HangingEntityItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/HangingEntityItem.java.patch new file mode 100644 index 0000000000..5cfdae7aa5 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/HangingEntityItem.java.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/world/item/HangingEntityItem.java ++++ b/net/minecraft/world/item/HangingEntityItem.java +@@ -22,6 +21,11 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.entity.Player; ++import org.bukkit.event.hanging.HangingPlaceEvent; ++// CraftBukkit end ++ + public class HangingEntityItem extends Item { + + private static final Component TOOLTIP_RANDOM_VARIANT = Component.translatable("painting.random").withStyle(ChatFormatting.GRAY); +@@ -72,7 +75,20 @@ + } + + if (((HangingEntity) object).survives()) { +- if (!level.isClientSide) { ++ if (!world.isClientSide) { ++ // CraftBukkit start - fire HangingPlaceEvent ++ Player who = (context.getPlayer() == null) ? null : (Player) context.getPlayer().getBukkitEntity(); ++ org.bukkit.block.Block blockClicked = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(enumdirection); ++ org.bukkit.inventory.EquipmentSlot hand = org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand()); ++ ++ HangingPlaceEvent event = new HangingPlaceEvent((org.bukkit.entity.Hanging) ((HangingEntity) object).getBukkitEntity(), who, blockClicked, blockFace, hand, org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return InteractionResult.FAIL; ++ } ++ // CraftBukkit end + ((HangingEntity) object).playPlacementSound(); + level.gameEvent((Entity) player, GameEvent.ENTITY_PLACE, ((HangingEntity) object).position()); + level.addFreshEntity((Entity) object); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/ItemStack.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/ItemStack.java.patch new file mode 100644 index 0000000000..505db2a2b4 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/ItemStack.java.patch @@ -0,0 +1,324 @@ +--- a/net/minecraft/world/item/ItemStack.java ++++ b/net/minecraft/world/item/ItemStack.java +@@ -81,6 +82,41 @@ + import net.minecraft.world.level.block.state.pattern.BlockInWorld; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.mojang.serialization.Dynamic; ++import java.util.Map; ++import java.util.Objects; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundSource; ++import net.minecraft.stats.Stats; ++import net.minecraft.util.datafix.fixes.DataConverterTypes; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.SaplingBlock; ++import net.minecraft.world.level.block.SignBlock; ++import net.minecraft.world.level.block.SoundType; ++import net.minecraft.world.level.block.WitherSkullBlock; ++import net.minecraft.world.level.block.entity.BlockEntity; ++import net.minecraft.world.level.block.entity.JukeboxBlockEntity; ++import net.minecraft.world.level.block.entity.SignBlockEntity; ++import net.minecraft.world.level.block.entity.SkullBlockEntity; ++import net.minecraft.world.level.gameevent.GameEvent; ++import org.bukkit.Location; ++import org.bukkit.TreeType; ++import org.bukkit.block.BlockState; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.entity.Player; ++import org.bukkit.event.block.BlockFertilizeEvent; ++import org.bukkit.event.player.PlayerItemDamageEvent; ++import org.bukkit.event.world.StructureGrowEvent; ++// CraftBukkit end ++ + public final class ItemStack { + + public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { +@@ -175,11 +211,22 @@ + this.item = null; + } + +- private ItemStack(CompoundTag compoundtag) { +- this.item = (Item) BuiltInRegistries.ITEM.get(new ResourceLocation(compoundtag.getString("id"))); +- this.count = compoundtag.getByte("Count"); +- if (compoundtag.contains("tag", 10)) { +- this.tag = compoundtag.getCompound("tag").copy(); ++ // Called to run this stack through the data converter to handle older storage methods and serialized items ++ public void convertStack(int version) { ++ if (0 < version && version < CraftMagicNumbers.INSTANCE.getDataVersion()) { ++ CompoundTag savedStack = new CompoundTag(); ++ this.save(savedStack); ++ savedStack = (CompoundTag) MinecraftServer.getServer().fixerUpper.update(DataConverterTypes.ITEM_STACK, new Dynamic(NbtOps.INSTANCE, savedStack), version, CraftMagicNumbers.INSTANCE.getDataVersion()).getValue(); ++ this.load(savedStack); ++ } ++ } ++ ++ // CraftBukkit - break into own method ++ private void load(CompoundTag nbttagcompound) { ++ this.item = (Item) BuiltInRegistries.ITEM.get(new ResourceLocation(nbttagcompound.getString("id"))); ++ this.count = nbttagcompound.getByte("Count"); ++ if (nbttagcompound.contains("tag", 10)) { ++ this.tag = nbttagcompound.getCompound("tag").copy(); + this.getItem().verifyTagAfterLoad(this.tag); + } + +@@ -189,7 +236,12 @@ + + } + +- public static ItemStack of(CompoundTag compoundtag) { ++ private ItemStack(CompoundTag compoundTag) { ++ this.load(compoundTag); ++ // CraftBukkit end ++ } ++ ++ public static ItemStack of(CompoundTag compoundTag) { + try { + return new ItemStack(compoundtag); + } catch (RuntimeException runtimeexception) { +@@ -266,13 +318,165 @@ + return InteractionResult.PASS; + } else { + Item item = this.getItem(); +- InteractionResult interactionresult = item.useOn(useoncontext); ++ // CraftBukkit start - handle all block place event logic here ++ CompoundTag oldData = this.getTagClone(); ++ int oldCount = this.getCount(); ++ ServerLevel world = (ServerLevel) context.getLevel(); + + if (player != null && interactionresult.shouldAwardStats()) { + player.awardStat(Stats.ITEM_USED.get(item)); + } + +- return interactionresult; ++ BlockFertilizeEvent fertilizeEvent = new BlockFertilizeEvent(CraftBlock.at(world, blockposition), (Player) entityhuman.getBukkitEntity(), (List< BlockState>) (List) blocks); ++ fertilizeEvent.setCancelled(structureEvent != null && structureEvent.isCancelled()); ++ org.bukkit.Bukkit.getPluginManager().callEvent(fertilizeEvent); ++ ++ if (!fertilizeEvent.isCancelled()) { ++ // Change the stack to its new contents if it hasn't been tampered with. ++ if (this.getCount() == oldCount && Objects.equals(this.tag, oldData)) { ++ this.setTag(newData); ++ this.setCount(newCount); ++ } ++ for (CraftBlockState blockstate : blocks) { ++ world.setBlock(blockstate.getPosition(),blockstate.getHandle(), blockstate.getFlag()); // SPIGOT-7248 - manual update to avoid physics where appropriate ++ } ++ entityhuman.awardStat(Stats.ITEM_USED.get(item)); // SPIGOT-7236 - award stat ++ } ++ ++ SignItem.openSign = null; // SPIGOT-6758 - Reset on early return ++ return enuminteractionresult; ++ } ++ world.captureTreeGeneration = false; ++ ++ if (entityhuman != null && enuminteractionresult.shouldAwardStats()) { ++ EnumHand enumhand = context.getHand(); ++ org.bukkit.event.block.BlockPlaceEvent placeEvent = null; ++ List blocks = new java.util.ArrayList<>(world.capturedBlockStates.values()); ++ world.capturedBlockStates.clear(); ++ if (blocks.size() > 1) { ++ placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockMultiPlaceEvent(world, entityhuman, enumhand, blocks, blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ } else if (blocks.size() == 1) { ++ placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEvent(world, entityhuman, enumhand, blocks.get(0), blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ } ++ ++ if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild())) { ++ enuminteractionresult = InteractionResult.FAIL; // cancel placement ++ // PAIL: Remove this when MC-99075 fixed ++ placeEvent.getPlayer().updateInventory(); ++ // revert back all captured blocks ++ world.preventPoiUpdated = true; // CraftBukkit - SPIGOT-5710 ++ for (BlockState blockstate : blocks) { ++ blockstate.update(true, false); ++ } ++ world.preventPoiUpdated = false; ++ ++ // Brute force all possible updates ++ BlockPos placedPos = ((CraftBlock) placeEvent.getBlock()).getPosition(); ++ for (Direction dir : Direction.values()) { ++ ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, placedPos.relative(dir))); ++ } ++ SignItem.openSign = null; // SPIGOT-6758 - Reset on early return ++ } else { ++ // Change the stack to its new contents if it hasn't been tampered with. ++ if (this.getCount() == oldCount && Objects.equals(this.tag, oldData)) { ++ this.setTag(newData); ++ this.setCount(newCount); ++ } ++ ++ for (Map.Entry e : world.capturedTileEntities.entrySet()) { ++ world.setBlockEntity(e.getValue()); ++ } ++ ++ for (BlockState blockstate : blocks) { ++ int updateFlag = ((CraftBlockState) blockstate).getFlag(); ++ IBlockData oldBlock = ((CraftBlockState) blockstate).getHandle(); ++ BlockPos newblockposition = ((CraftBlockState) blockstate).getPosition(); ++ IBlockData block = world.getBlockState(newblockposition); ++ ++ if (!(block.getBlock() instanceof BaseEntityBlock)) { // Containers get placed automatically ++ block.getBlock().onPlace(block, world, newblockposition, oldBlock, true); ++ } ++ ++ world.notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, world.getBlockState(newblockposition), updateFlag, 512); // send null chunk as chunk.k() returns false by this point ++ } ++ ++ // Special case juke boxes as they update their tile entity. Copied from ItemRecord. ++ // PAIL: checkme on updates. ++ if (this.item instanceof RecordItem) { ++ BlockEntity tileentity = world.getBlockEntity(blockposition); ++ ++ if (tileentity instanceof JukeboxBlockEntity) { ++ JukeboxBlockEntity tileentityjukebox = (JukeboxBlockEntity) tileentity; ++ ++ // There can only be one ++ ItemStack record = this.copy(); ++ if (!record.isEmpty()) { ++ record.setCount(1); ++ } ++ ++ tileentityjukebox.setTheItem(record); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entityhuman, world.getBlockState(blockposition))); ++ } ++ ++ this.shrink(1); ++ entityhuman.awardStat(Stats.PLAY_RECORD); ++ } ++ ++ if (this.item == Items.WITHER_SKELETON_SKULL) { // Special case skulls to allow wither spawns to be cancelled ++ BlockPos bp = blockposition; ++ if (!world.getBlockState(blockposition).canBeReplaced()) { ++ if (!world.getBlockState(blockposition).isSolid()) { ++ bp = null; ++ } else { ++ bp = bp.relative(context.getClickedFace()); ++ } ++ } ++ if (bp != null) { ++ BlockEntity te = world.getBlockEntity(bp); ++ if (te instanceof SkullBlockEntity) { ++ WitherSkullBlock.checkSpawn(world, bp, (SkullBlockEntity) te); ++ } ++ } ++ } ++ ++ // SPIGOT-4678 ++ if (this.item instanceof SignItem && SignItem.openSign != null) { ++ try { ++ if (world.getBlockEntity(SignItem.openSign) instanceof SignBlockEntity tileentitysign) { ++ if (world.getBlockState(SignItem.openSign).getBlock() instanceof SignBlock blocksign) { ++ blocksign.openTextEdit(entityhuman, tileentitysign, true, org.bukkit.event.player.PlayerSignOpenEvent.Cause.PLACE); // Craftbukkit ++ } ++ } ++ } finally { ++ SignItem.openSign = null; ++ } ++ } ++ ++ // SPIGOT-7315: Moved from BlockBed#setPlacedBy ++ if (placeEvent != null && this.item instanceof BedItem) { ++ BlockPos position = ((CraftBlock) placeEvent.getBlock()).getPosition(); ++ IBlockData blockData = world.getBlockState(position); ++ ++ if (blockData.getBlock() instanceof BedBlock) { ++ world.blockUpdated(position, Blocks.AIR); ++ blockData.updateNeighbourShapes(world, position, 3); ++ } ++ } ++ ++ // SPIGOT-1288 - play sound stripped from ItemBlock ++ if (this.item instanceof BlockItem) { ++ SoundType soundeffecttype = ((BlockItem) this.item).getBlock().defaultBlockState().getSoundType(); // TODO: not strictly correct, however currently only affects decorated pots ++ world.playSound(entityhuman, blockposition, soundeffecttype.getPlaceSound(), SoundSource.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F); ++ } ++ ++ entityhuman.awardStat(Stats.ITEM_USED.get(item)); ++ } ++ } ++ world.capturedTileEntities.clear(); ++ world.capturedBlockStates.clear(); ++ // CraftBukkit end ++ ++ return enuminteractionresult; + } + } + +@@ -350,8 +581,23 @@ + } + } + +- i -= k; +- if (i <= 0) { ++ amount -= k; ++ // CraftBukkit start ++ if (user != null) { ++ PlayerItemDamageEvent event = new PlayerItemDamageEvent(user.getBukkitEntity(), CraftItemStack.asCraftMirror(this), amount); ++ event.getPlayer().getServer().getPluginManager().callEvent(event); ++ ++ if (amount != event.getDamage() || event.isCancelled()) { ++ event.getPlayer().updateInventory(); ++ } ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ amount = event.getDamage(); ++ } ++ // CraftBukkit end ++ if (amount <= 0) { + return false; + } + } +@@ -372,6 +618,11 @@ + if (this.hurt(i, t0.getRandom(), t0 instanceof ServerPlayer ? (ServerPlayer) t0 : null)) { + consumer.accept(t0); + Item item = this.getItem(); ++ // CraftBukkit start - Check for item breaking ++ if (this.count == 1 && entity instanceof net.minecraft.world.entity.player.Player) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemBreakEvent((net.minecraft.world.entity.player.Player) entity, this); ++ } ++ // CraftBukkit end + + this.shrink(1); + if (t0 instanceof Player) { +@@ -525,6 +775,17 @@ + return this.tag; + } + ++ // CraftBukkit start ++ @Nullable ++ private CompoundTag getTagClone() { ++ return this.tag == null ? null : this.tag.copy(); ++ } ++ ++ private void setTagClone(@Nullable CompoundTag nbtttagcompound) { ++ this.setTag(nbtttagcompound == null ? null : nbtttagcompound.copy()); ++ } ++ // CraftBukkit end ++ + public CompoundTag getOrCreateTag() { + if (this.tag == null) { + this.setTag(new CompoundTag()); +@@ -949,6 +1210,13 @@ + listtag.add(compoundtag); + } + ++ // CraftBukkit start ++ @Deprecated ++ public void setItem(Item item) { ++ this.item = item; ++ } ++ // CraftBukkit end ++ + public Component getDisplayName() { + MutableComponent mutablecomponent = Component.empty().append(this.getHoverName()); + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/LeadItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/LeadItem.java.patch new file mode 100644 index 0000000000..875c3ae2e9 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/LeadItem.java.patch @@ -0,0 +1,82 @@ +--- a/net/minecraft/world/item/LeadItem.java ++++ b/net/minecraft/world/item/LeadItem.java +@@ -14,6 +14,10 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; ++// CraftBukkit start ++import org.bukkit.craftbukkit.CraftEquipmentSlot; ++import org.bukkit.event.hanging.HangingPlaceEvent; ++// CraftBukkit end + + public class LeadItem extends Item { + +@@ -31,8 +34,8 @@ + if (blockstate.is(BlockTags.FENCES)) { + Player player = useoncontext.getPlayer(); + +- if (!level.isClientSide && player != null) { +- bindPlayerMobs(player, level, blockpos); ++ if (!world.isClientSide && entityhuman != null) { ++ bindPlayerMobs(entityhuman, world, blockposition, context.getHand()); // CraftBukkit - Pass hand + } + + return InteractionResult.sidedSuccess(level.isClientSide); +@@ -41,8 +44,8 @@ + } + } + +- public static InteractionResult bindPlayerMobs(Player player, Level level, BlockPos blockpos) { +- LeashFenceKnotEntity leashfenceknotentity = null; ++ public static InteractionResult bindPlayerMobs(Player entityhuman, Level world, BlockPos blockposition, net.minecraft.world.EnumHand enumhand) { // CraftBukkit - Add EnumHand ++ LeashFenceKnotEntity entityleash = null; + boolean flag = false; + double d0 = 7.0D; + int i = blockpos.getX(); +@@ -54,13 +57,30 @@ + while (iterator.hasNext()) { + Mob mob = (Mob) iterator.next(); + +- if (mob.getLeashHolder() == player) { +- if (leashfenceknotentity == null) { +- leashfenceknotentity = LeashFenceKnotEntity.getOrCreateKnot(level, blockpos); +- leashfenceknotentity.playPlacementSound(); ++ if (entityinsentient.getLeashHolder() == entityhuman) { ++ if (entityleash == null) { ++ entityleash = LeashFenceKnotEntity.getOrCreateKnot(world, blockposition); ++ ++ // CraftBukkit start - fire HangingPlaceEvent ++ org.bukkit.inventory.EquipmentSlot hand = CraftEquipmentSlot.getHand(enumhand); ++ HangingPlaceEvent event = new HangingPlaceEvent((org.bukkit.entity.Hanging) entityleash.getBukkitEntity(), entityhuman != null ? (org.bukkit.entity.Player) entityhuman.getBukkitEntity() : null, world.getWorld().getBlockAt(i, j, k), org.bukkit.block.BlockFace.SELF, hand); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ entityleash.discard(); ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end ++ entityleash.playPlacementSound(); + } + +- mob.setLeashedTo(leashfenceknotentity, true); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerLeashEntityEvent(entityinsentient, entityleash, entityhuman, enumhand).isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end ++ ++ entityinsentient.setLeashedTo(entityleash, true); + flag = true; + } + } +@@ -71,4 +91,10 @@ + + return flag ? InteractionResult.SUCCESS : InteractionResult.PASS; + } ++ ++ // CraftBukkit start ++ public static InteractionResult bindPlayerMobs(Player player, Level level, BlockPos pos) { ++ return bindPlayerMobs(player, level, pos, net.minecraft.world.EnumHand.MAIN_HAND); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/MapItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/MapItem.java.patch new file mode 100644 index 0000000000..547eacc615 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/MapItem.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/item/MapItem.java ++++ b/net/minecraft/world/item/MapItem.java +@@ -69,7 +69,7 @@ + public static Integer getMapId(ItemStack itemstack) { + CompoundTag compoundtag = itemstack.getTag(); + +- return compoundtag != null && compoundtag.contains("map", 99) ? compoundtag.getInt("map") : null; ++ return nbttagcompound != null && nbttagcompound.contains("map", 99) ? nbttagcompound.getInt("map") : -1; // CraftBukkit - make new maps for no tag + } + + private static int createNewSavedData(Level level, int i, int j, int k, boolean flag, boolean flag1, ResourceKey resourcekey) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/MilkBucketItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/MilkBucketItem.java.patch new file mode 100644 index 0000000000..9319057302 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/MilkBucketItem.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/item/MilkBucketItem.java ++++ b/net/minecraft/world/item/MilkBucketItem.java +@@ -32,7 +31,7 @@ + } + + if (!level.isClientSide) { +- livingentity.removeAllEffects(); ++ entityLiving.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.MILK); // CraftBukkit + } + + return itemstack.isEmpty() ? new ItemStack(Items.BUCKET) : itemstack; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/MinecartItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/MinecartItem.java.patch new file mode 100644 index 0000000000..9f82c85999 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/MinecartItem.java.patch @@ -0,0 +1,73 @@ +--- a/net/minecraft/world/item/MinecartItem.java ++++ b/net/minecraft/world/item/MinecartItem.java +@@ -18,6 +18,11 @@ + import net.minecraft.world.level.block.state.properties.RailShape; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end + + public class MinecartItem extends Item { + +@@ -59,10 +63,39 @@ + } + } + +- AbstractMinecart abstractminecart = AbstractMinecart.createMinecart(serverlevel, d0, d1 + d3, d2, ((MinecartItem) itemstack.getItem()).type, itemstack, (Player) null); ++ // CraftBukkit start ++ // EntityMinecartAbstract entityminecartabstract = EntityMinecartAbstract.createMinecart(worldserver, d0, d1 + d3, d2, ((ItemMinecart) itemstack.getItem()).type); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block2 = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + +- serverlevel.addFreshEntity(abstractminecart); +- itemstack.shrink(1); ++ BlockDispenseEvent event = new BlockDispenseEvent(block2, craftItem.clone(), new org.bukkit.util.Vector(d0, d1 + d3, d2)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); ++ AbstractMinecart entityminecartabstract = AbstractMinecart.createMinecart(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), ((MinecartItem) itemstack1.getItem()).type, itemstack1, (Player) null); ++ ++ if (!worldserver.addFreshEntity(entityminecartabstract)) itemstack.grow(1); ++ // itemstack.shrink(1); // CraftBukkit - handled during event processing ++ // CraftBukkit end + return itemstack; + } + +@@ -103,8 +134,13 @@ + + AbstractMinecart abstractminecart = AbstractMinecart.createMinecart(serverlevel, (double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.0625D + d0, (double) blockpos.getZ() + 0.5D, this.type, itemstack, useoncontext.getPlayer()); + +- serverlevel.addFreshEntity(abstractminecart); +- serverlevel.gameEvent(GameEvent.ENTITY_PLACE, blockpos, GameEvent.Context.of(useoncontext.getPlayer(), serverlevel.getBlockState(blockpos.below()))); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(context, entityminecartabstract).isCancelled()) { ++ return InteractionResult.FAIL; ++ } ++ // CraftBukkit end ++ if (!worldserver.addFreshEntity(entityminecartabstract)) return InteractionResult.PASS; // CraftBukkit ++ worldserver.gameEvent(GameEvent.ENTITY_PLACE, blockposition, GameEvent.Context.of(context.getPlayer(), worldserver.getBlockState(blockposition.below()))); + } + + itemstack.shrink(1); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/PotionItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/PotionItem.java.patch new file mode 100644 index 0000000000..efd70f391c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/PotionItem.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/item/PotionItem.java ++++ b/net/minecraft/world/item/PotionItem.java +@@ -62,7 +60,7 @@ + if (mobeffectinstance.getEffect().isInstantenous()) { + mobeffectinstance.getEffect().applyInstantenousEffect(player, player, livingentity, mobeffectinstance.getAmplifier(), 1.0D); + } else { +- livingentity.addEffect(new MobEffectInstance(mobeffectinstance)); ++ entityLiving.addEffect(new MobEffectInstance(mobeffect), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_DRINK); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/RecordItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/RecordItem.java.patch new file mode 100644 index 0000000000..7e377a438b --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/RecordItem.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/item/RecordItem.java ++++ b/net/minecraft/world/item/RecordItem.java +@@ -46,9 +45,10 @@ + if (blockstate.is(Blocks.JUKEBOX) && !(Boolean) blockstate.getValue(JukeboxBlock.HAS_RECORD)) { + ItemStack itemstack = useoncontext.getItemInHand(); + +- if (!level.isClientSide) { +- Player player = useoncontext.getPlayer(); +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ if (!world.isClientSide) { ++ if (true) return InteractionResult.SUCCESS; // CraftBukkit - handled in ItemStack ++ Player entityhuman = context.getPlayer(); ++ BlockEntity tileentity = world.getBlockEntity(blockposition); + + if (blockentity instanceof JukeboxBlockEntity) { + JukeboxBlockEntity jukeboxblockentity = (JukeboxBlockEntity) blockentity; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/SignItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/SignItem.java.patch new file mode 100644 index 0000000000..51e2e94845 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/SignItem.java.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/world/item/SignItem.java ++++ b/net/minecraft/world/item/SignItem.java +@@ -13,8 +13,10 @@ + + public class SignItem extends StandingAndWallBlockItem { + +- public SignItem(Item.Properties item_properties, Block block, Block block1) { +- super(block, block1, item_properties, Direction.DOWN); ++ public static BlockPos openSign; // CraftBukkit ++ ++ public SignItem(Item.Properties properties, Block standingBlock, Block wallBlock) { ++ super(standingBlock, wallBlock, properties, Direction.DOWN); + } + + public SignItem(Item.Properties item_properties, Block block, Block block1, Direction direction) { +@@ -36,7 +37,10 @@ + if (block instanceof SignBlock) { + SignBlock signblock = (SignBlock) block; + +- signblock.openTextEdit(player, signblockentity, true); ++ // CraftBukkit start - SPIGOT-4678 ++ // blocksign.openTextEdit(entityhuman, tileentitysign, true); ++ SignItem.openSign = pos; ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/SnowballItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/SnowballItem.java.patch new file mode 100644 index 0000000000..9a0cd1a7ee --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/SnowballItem.java.patch @@ -0,0 +1,26 @@ +--- a/net/minecraft/world/item/SnowballItem.java ++++ b/net/minecraft/world/item/SnowballItem.java +@@ -20,7 +19,8 @@ + public InteractionResultHolder use(Level level, Player player, InteractionHand interactionhand) { + ItemStack itemstack = player.getItemInHand(interactionhand); + +- level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.SNOWBALL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); ++ // CraftBukkit - moved down ++ // world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.SNOWBALL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); + if (!level.isClientSide) { + Snowball snowball = new Snowball(level, player); + +@@ -28,9 +36,12 @@ + snowball.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 1.5F, 1.0F); + level.addFreshEntity(snowball); + } ++ // CraftBukkit end + + player.awardStat(Stats.ITEM_USED.get(this)); +- if (!player.getAbilities().instabuild) { ++ // CraftBukkit start - moved up ++ /* ++ if (!entityhuman.getAbilities().instabuild) { + itemstack.shrink(1); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/SpawnEggItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/SpawnEggItem.java.patch new file mode 100644 index 0000000000..87e1849bfc --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/SpawnEggItem.java.patch @@ -0,0 +1,17 @@ +--- a/net/minecraft/world/item/SpawnEggItem.java ++++ b/net/minecraft/world/item/SpawnEggItem.java +@@ -182,10 +179,10 @@ + if (!((Mob) object).isBaby()) { + return Optional.empty(); + } else { +- ((Mob) object).moveTo(vec3.x(), vec3.y(), vec3.z(), 0.0F, 0.0F); +- serverlevel.addFreshEntityWithPassengers((Entity) object); +- if (itemstack.hasCustomHoverName()) { +- ((Mob) object).setCustomName(itemstack.getHoverName()); ++ ((Mob) object).moveTo(pos.x(), pos.y(), pos.z(), 0.0F, 0.0F); ++ serverLevel.addFreshEntityWithPassengers((Entity) object, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG); // CraftBukkit ++ if (stack.hasCustomHoverName()) { ++ ((Mob) object).setCustomName(stack.getHoverName()); + } + + if (!player.getAbilities().instabuild) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/StandingAndWallBlockItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/StandingAndWallBlockItem.java.patch new file mode 100644 index 0000000000..930370c442 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/StandingAndWallBlockItem.java.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/item/StandingAndWallBlockItem.java ++++ b/net/minecraft/world/item/StandingAndWallBlockItem.java +@@ -10,6 +11,10 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.shapes.CollisionContext; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.event.block.BlockCanBuildEvent; ++// CraftBukkit end + + public class StandingAndWallBlockItem extends BlockItem { + +@@ -50,7 +54,19 @@ + } + } + +- return blockstate1 != null && level.isUnobstructed(blockstate1, blockpos, CollisionContext.empty()) ? blockstate1 : null; ++ // CraftBukkit start ++ if (iblockdata1 != null) { ++ boolean defaultReturn = world.isUnobstructed(iblockdata1, blockposition, CollisionContext.empty()); ++ org.bukkit.entity.Player player = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null; ++ ++ BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(world, blockposition), player, CraftBlockData.fromData(iblockdata1), defaultReturn); ++ context.getLevel().getCraftServer().getPluginManager().callEvent(event); ++ ++ return (event.isBuildable()) ? iblockdata1 : null; ++ } else { ++ return null; ++ } ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/TridentItem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/TridentItem.java.patch new file mode 100644 index 0000000000..8a451c85af --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/TridentItem.java.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/world/item/TridentItem.java ++++ b/net/minecraft/world/item/TridentItem.java +@@ -72,8 +68,10 @@ + + if (k <= 0 || player.isInWaterOrRain()) { + if (!level.isClientSide) { +- itemstack.hurtAndBreak(1, player, (player1) -> { +- player1.broadcastBreakEvent(livingentity.getUsedItemHand()); ++ // CraftBukkit - moved down ++ /* ++ itemstack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(entityliving.getUsedItemHand()); + }); + if (k == 0) { + ThrownTrident throwntrident = new ThrownTrident(level, player, itemstack); +@@ -83,18 +82,41 @@ + throwntrident.pickup = AbstractArrow.Pickup.CREATIVE_ONLY; + } + +- level.addFreshEntity(throwntrident); +- level.playSound((Player) null, (Entity) throwntrident, SoundEvents.TRIDENT_THROW, SoundSource.PLAYERS, 1.0F, 1.0F); +- if (!player.getAbilities().instabuild) { +- player.getInventory().removeItem(itemstack); ++ // CraftBukkit start ++ if (!level.addFreshEntity(entitythrowntrident)) { ++ if (entityhuman instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } ++ return; + } ++ ++ stack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(entityLiving.getUsedItemHand()); ++ }); ++ entitythrowntrident.pickupItemStack = stack.copy(); // SPIGOT-4511 update since damage call moved ++ // CraftBukkit end ++ ++ level.playSound((Player) null, (Entity) entitythrowntrident, SoundEvents.TRIDENT_THROW, SoundSource.PLAYERS, 1.0F, 1.0F); ++ if (!entityhuman.getAbilities().instabuild) { ++ entityhuman.getInventory().removeItem(stack); ++ } ++ // CraftBukkit start - SPIGOT-5458 also need in this branch :( ++ } else { ++ stack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(entityLiving.getUsedItemHand()); ++ }); ++ // CraftBukkkit end + } + } + + player.awardStat(Stats.ITEM_USED.get(this)); + if (k > 0) { +- float f = player.getYRot(); +- float f1 = player.getXRot(); ++ // CraftBukkit start ++ org.bukkit.event.player.PlayerRiptideEvent event = new org.bukkit.event.player.PlayerRiptideEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack)); ++ event.getPlayer().getServer().getPluginManager().callEvent(event); ++ // CraftBukkit end ++ float f = entityhuman.getYRot(); ++ float f1 = entityhuman.getXRot(); + float f2 = -Mth.sin(f * 0.017453292F) * Mth.cos(f1 * 0.017453292F); + float f3 = -Mth.sin(f1 * 0.017453292F); + float f4 = Mth.cos(f * 0.017453292F) * Mth.cos(f1 * 0.017453292F); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/BlastingRecipe.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/BlastingRecipe.java.patch new file mode 100644 index 0000000000..c9f9c5f2be --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/BlastingRecipe.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/item/crafting/BlastingRecipe.java ++++ b/net/minecraft/world/item/crafting/BlastingRecipe.java +@@ -3,6 +3,14 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftBlastingRecipe; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class BlastingRecipe extends AbstractCookingRecipe { + + public BlastingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient ingredient, ItemStack itemstack, float f, int i) { +@@ -20,4 +26,17 @@ + public RecipeSerializer getSerializer() { + return RecipeSerializer.BLASTING_RECIPE; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftBlastingRecipe recipe = new CraftBlastingRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/CampfireCookingRecipe.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/CampfireCookingRecipe.java.patch new file mode 100644 index 0000000000..fb81e72c5b --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/CampfireCookingRecipe.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/item/crafting/CampfireCookingRecipe.java ++++ b/net/minecraft/world/item/crafting/CampfireCookingRecipe.java +@@ -3,6 +3,14 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftCampfireRecipe; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class CampfireCookingRecipe extends AbstractCookingRecipe { + + public CampfireCookingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient ingredient, ItemStack itemstack, float f, int i) { +@@ -20,4 +26,17 @@ + public RecipeSerializer getSerializer() { + return RecipeSerializer.CAMPFIRE_COOKING_RECIPE; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftCampfireRecipe recipe = new CraftCampfireRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/CustomRecipe.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/CustomRecipe.java.patch new file mode 100644 index 0000000000..e48edf6f3c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/CustomRecipe.java.patch @@ -0,0 +1,26 @@ +--- a/net/minecraft/world/item/crafting/CustomRecipe.java ++++ b/net/minecraft/world/item/crafting/CustomRecipe.java +@@ -3,7 +3,10 @@ + import net.minecraft.core.RegistryAccess; + import net.minecraft.world.item.ItemStack; + +-public abstract class CustomRecipe implements CraftingRecipe { ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end + + private final CraftingBookCategory category; + +@@ -28,4 +30,11 @@ + public CraftingBookCategory category() { + return this.category; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ return new org.bukkit.craftbukkit.inventory.CraftComplexRecipe(id, this); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/Ingredient.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/Ingredient.java.patch new file mode 100644 index 0000000000..169cb8b3c7 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/Ingredient.java.patch @@ -0,0 +1,28 @@ +--- a/net/minecraft/world/item/crafting/Ingredient.java ++++ b/net/minecraft/world/item/crafting/Ingredient.java +@@ -35,6 +35,7 @@ + private ItemStack[] itemStacks; + @Nullable + private IntList stackingIds; ++ public boolean exact; // CraftBukkit + public static final Codec CODEC = codec(true); + public static final Codec CODEC_NONEMPTY = codec(false); + +@@ -73,7 +73,16 @@ + for (int j = 0; j < i; ++j) { + ItemStack itemstack1 = aitemstack[j]; + +- if (itemstack1.is(itemstack.getItem())) { ++ // CraftBukkit start ++ if (exact) { ++ if (itemstack1.getItem() == stack.getItem() && ItemStack.isSameItemSameTags(stack, itemstack1)) { ++ return true; ++ } ++ ++ continue; ++ } ++ // CraftBukkit end ++ if (itemstack1.is(stack.getItem())) { + return true; + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/Recipe.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/Recipe.java.patch new file mode 100644 index 0000000000..d7cfffbac3 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/Recipe.java.patch @@ -0,0 +1,9 @@ +--- a/net/minecraft/world/item/crafting/Recipe.java ++++ b/net/minecraft/world/item/crafting/Recipe.java +@@ -67,4 +67,6 @@ + return ingredient.getItems().length == 0; + }); + } ++ ++ org.bukkit.inventory.Recipe toBukkitRecipe(org.bukkit.NamespacedKey id); // CraftBukkit + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/RecipeHolder.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/RecipeHolder.java.patch new file mode 100644 index 0000000000..35a86ff378 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/RecipeHolder.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/item/crafting/RecipeHolder.java ++++ b/net/minecraft/world/item/crafting/RecipeHolder.java +@@ -1,10 +1,17 @@ + package net.minecraft.world.item.crafting; + + import net.minecraft.resources.ResourceLocation; ++// CraftBukkit start ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.inventory.Recipe; + + public record RecipeHolder> (ResourceLocation id, T value) { + +- @Override ++ public final Recipe toBukkitRecipe() { ++ return this.value.toBukkitRecipe(CraftNamespacedKey.fromMinecraft(this.id)); ++ } ++ // CraftBukkit end ++ + public boolean equals(Object object) { + if (this == object) { + return true; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/RecipeManager.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/RecipeManager.java.patch new file mode 100644 index 0000000000..764085dcde --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/RecipeManager.java.patch @@ -0,0 +1,161 @@ +--- a/net/minecraft/world/item/crafting/RecipeManager.java ++++ b/net/minecraft/world/item/crafting/RecipeManager.java +@@ -24,6 +24,15 @@ + import javax.annotation.Nullable; + import net.minecraft.Util; + import net.minecraft.core.NonNullList; ++import net.minecraft.world.Container; ++import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.level.Level; ++import org.slf4j.Logger; ++ ++// CraftBukkit start ++import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; ++import net.minecraft.core.registries.BuiltInRegistries; ++// CraftBukkit end + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.packs.resources.ResourceManager; + import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; +@@ -38,7 +43,7 @@ + + private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().disableHtmlEscaping().create(); + private static final Logger LOGGER = LogUtils.getLogger(); +- private Map, Map>> recipes = ImmutableMap.of(); ++ public Map, Object2ObjectLinkedOpenHashMap>> recipes = ImmutableMap.of(); // CraftBukkit + private Map> byName = ImmutableMap.of(); + private boolean hasErrors; + +@@ -49,7 +53,12 @@ + @Override + protected void apply(Map map, ResourceManager resourcemanager, ProfilerFiller profilerfiller) { + this.hasErrors = false; +- Map, Builder>> map1 = Maps.newHashMap(); ++ // CraftBukkit start - SPIGOT-5667 make sure all types are populated and mutable ++ Map, Object2ObjectLinkedOpenHashMap>> map1 = Maps.newHashMap(); ++ for (RecipeType recipeType : BuiltInRegistries.RECIPE_TYPE) { ++ map1.put(recipeType, new Object2ObjectLinkedOpenHashMap<>()); ++ } ++ // CraftBukkit end + Builder> builder = ImmutableMap.builder(); + Iterator iterator = map.entrySet().iterator(); + +@@ -60,30 +69,49 @@ + try { + RecipeHolder recipeholder = fromJson(resourcelocation, GsonHelper.convertToJsonObject((JsonElement) entry.getValue(), "top element")); + +- ((Builder) map1.computeIfAbsent(recipeholder.value().getType(), (recipetype) -> { +- return ImmutableMap.builder(); +- })).put(resourcelocation, recipeholder); +- builder.put(resourcelocation, recipeholder); ++ // CraftBukkit start ++ (map1.computeIfAbsent(recipeholder.value().getType(), (recipes) -> { ++ return new Object2ObjectLinkedOpenHashMap<>(); ++ // CraftBukkit end ++ })).put(minecraftkey, recipeholder); ++ builder.put(minecraftkey, recipeholder); + } catch (IllegalArgumentException | JsonParseException jsonparseexception) { + RecipeManager.LOGGER.error("Parsing error loading recipe {}", resourcelocation, jsonparseexception); + } + } + + this.recipes = (Map) map1.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry1) -> { +- return ((Builder) entry1.getValue()).build(); ++ return (entry1.getValue()); // CraftBukkit + })); +- this.byName = builder.build(); ++ this.byName = Maps.newHashMap(builder.build()); // CraftBukkit + RecipeManager.LOGGER.info("Loaded {} recipes", map1.size()); + } + ++ // CraftBukkit start ++ public void addRecipe(RecipeHolder irecipe) { ++ Object2ObjectLinkedOpenHashMap> map = this.recipes.get(irecipe.value().getType()); // CraftBukkit ++ ++ if (byName.containsKey(irecipe.id()) || map.containsKey(irecipe.id())) { ++ throw new IllegalStateException("Duplicate recipe ignored with ID " + irecipe.id()); ++ } else { ++ map.putAndMoveToFirst(irecipe.id(), irecipe); // CraftBukkit - SPIGOT-4638: last recipe gets priority ++ byName.put(irecipe.id(), irecipe); ++ } ++ } ++ // CraftBukkit end ++ + public boolean hadErrorsLoading() { + return this.hasErrors; + } + +- public > Optional> getRecipeFor(RecipeType recipetype, C c0, Level level) { +- return this.byType(recipetype).values().stream().filter((recipeholder) -> { +- return recipeholder.value().matches(c0, level); ++ public > Optional> getRecipeFor(RecipeType recipeType, C inventory, Level level) { ++ // CraftBukkit start ++ Optional> recipe = this.byType(recipeType).values().stream().filter((recipeholder) -> { ++ return recipeholder.value().matches(inventory, level); + }).findFirst(); ++ inventory.setCurrentRecipe(recipe.orElse(null)); // CraftBukkit - Clear recipe when no recipe is found ++ return recipe; ++ // CraftBukkit end + } + + public > Optional>> getRecipeFor(RecipeType recipetype, C c0, Level level, @Nullable ResourceLocation resourcelocation) { +@@ -116,8 +144,8 @@ + })).collect(Collectors.toList()); + } + +- private > Map> byType(RecipeType recipetype) { +- return (Map) this.recipes.getOrDefault(recipetype, Collections.emptyMap()); ++ private > Map> byType(RecipeType recipeType) { ++ return (Map) this.recipes.getOrDefault(recipeType, new Object2ObjectLinkedOpenHashMap<>()); // CraftBukkit + } + + public > NonNullList getRemainingItemsFor(RecipeType recipetype, C c0, Level level) { +@@ -160,12 +188,12 @@ + + public void replaceRecipes(Iterable> iterable) { + this.hasErrors = false; +- Map, Map>> map = Maps.newHashMap(); ++ Map, Object2ObjectLinkedOpenHashMap>> map = Maps.newHashMap(); // CraftBukkit + Builder> builder = ImmutableMap.builder(); + +- iterable.forEach((recipeholder) -> { +- Map> map1 = (Map) map.computeIfAbsent(recipeholder.value().getType(), (recipetype) -> { +- return Maps.newHashMap(); ++ recipes.forEach((recipeholder) -> { ++ Map> map1 = (Map) map.computeIfAbsent(recipeholder.value().getType(), (recipes) -> { ++ return new Object2ObjectLinkedOpenHashMap<>(); // CraftBukkit + }); + ResourceLocation resourcelocation = recipeholder.id(); + RecipeHolder recipeholder1 = (RecipeHolder) map1.put(resourcelocation, recipeholder); +@@ -176,10 +204,30 @@ + } + }); + this.recipes = ImmutableMap.copyOf(map); +- this.byName = builder.build(); ++ this.byName = Maps.newHashMap(builder.build()); // CraftBukkit + } + +- public static > RecipeManager.CachedCheck createCheck(final RecipeType recipetype) { ++ // CraftBukkit start ++ public boolean removeRecipe(ResourceLocation mcKey) { ++ for (Object2ObjectLinkedOpenHashMap> recipes : recipes.values()) { ++ recipes.remove(mcKey); ++ } ++ ++ return byName.remove(mcKey) != null; ++ } ++ ++ public void clearRecipes() { ++ this.recipes = Maps.newHashMap(); ++ ++ for (RecipeType recipeType : BuiltInRegistries.RECIPE_TYPE) { ++ this.recipes.put(recipeType, new Object2ObjectLinkedOpenHashMap<>()); ++ } ++ ++ this.byName = Maps.newHashMap(); ++ } ++ // CraftBukkit end ++ ++ public static > RecipeManager.CachedCheck createCheck(final RecipeType recipeType) { + return new RecipeManager.CachedCheck() { + @Nullable + private ResourceLocation lastRecipe; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/ShapedRecipe.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/ShapedRecipe.java.patch new file mode 100644 index 0000000000..e52d917b29 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/ShapedRecipe.java.patch @@ -0,0 +1,85 @@ +--- a/net/minecraft/world/item/crafting/ShapedRecipe.java ++++ b/net/minecraft/world/item/crafting/ShapedRecipe.java +@@ -9,6 +9,13 @@ + import net.minecraft.world.inventory.CraftingContainer; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftShapedRecipe; ++import org.bukkit.inventory.RecipeChoice; ++// CraftBukkit end + + public class ShapedRecipe implements CraftingRecipe { + +@@ -30,7 +37,68 @@ + this(s, craftingbookcategory, shapedrecipepattern, itemstack, true); + } + ++ // CraftBukkit start + @Override ++ public org.bukkit.inventory.ShapedRecipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ CraftShapedRecipe recipe = new CraftShapedRecipe(id, result, this); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ switch (this.pattern.height()) { ++ case 1: ++ switch (this.pattern.width()) { ++ case 1: ++ recipe.shape("a"); ++ break; ++ case 2: ++ recipe.shape("ab"); ++ break; ++ case 3: ++ recipe.shape("abc"); ++ break; ++ } ++ break; ++ case 2: ++ switch (this.pattern.width()) { ++ case 1: ++ recipe.shape("a","b"); ++ break; ++ case 2: ++ recipe.shape("ab","cd"); ++ break; ++ case 3: ++ recipe.shape("abc","def"); ++ break; ++ } ++ break; ++ case 3: ++ switch (this.pattern.width()) { ++ case 1: ++ recipe.shape("a","b","c"); ++ break; ++ case 2: ++ recipe.shape("ab","cd","ef"); ++ break; ++ case 3: ++ recipe.shape("abc","def","ghi"); ++ break; ++ } ++ break; ++ } ++ char c = 'a'; ++ for (Ingredient list : this.pattern.ingredients()) { ++ RecipeChoice choice = CraftRecipe.toBukkit(list); ++ if (choice != null) { ++ recipe.setIngredient(c, choice); ++ } ++ ++ c++; ++ } ++ return recipe; ++ } ++ // CraftBukkit end ++ + @Override + public RecipeSerializer getSerializer() { + return RecipeSerializer.SHAPED_RECIPE; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/ShapelessRecipe.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/ShapelessRecipe.java.patch new file mode 100644 index 0000000000..299d6f7c27 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/ShapelessRecipe.java.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/world/item/crafting/ShapelessRecipe.java ++++ b/net/minecraft/world/item/crafting/ShapelessRecipe.java +@@ -13,6 +13,12 @@ + import net.minecraft.world.inventory.CraftingContainer; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftShapelessRecipe; ++// CraftBukkit end + + public class ShapelessRecipe implements CraftingRecipe { + +@@ -28,7 +34,22 @@ + this.ingredients = nonnulllist; + } + ++ // CraftBukkit start ++ @SuppressWarnings("unchecked") + @Override ++ public org.bukkit.inventory.ShapelessRecipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ CraftShapelessRecipe recipe = new CraftShapelessRecipe(id, result, this); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ for (Ingredient list : this.ingredients) { ++ recipe.addIngredient(CraftRecipe.toBukkit(list)); ++ } ++ return recipe; ++ } ++ // CraftBukkit end ++ + @Override + public RecipeSerializer getSerializer() { + return RecipeSerializer.SHAPELESS_RECIPE; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/SmeltingRecipe.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/SmeltingRecipe.java.patch new file mode 100644 index 0000000000..13a11d2982 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/SmeltingRecipe.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/item/crafting/SmeltingRecipe.java ++++ b/net/minecraft/world/item/crafting/SmeltingRecipe.java +@@ -3,6 +3,14 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftFurnaceRecipe; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class SmeltingRecipe extends AbstractCookingRecipe { + + public SmeltingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient ingredient, ItemStack itemstack, float f, int i) { +@@ -20,4 +26,17 @@ + public RecipeSerializer getSerializer() { + return RecipeSerializer.SMELTING_RECIPE; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftFurnaceRecipe recipe = new CraftFurnaceRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/SmithingTransformRecipe.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/SmithingTransformRecipe.java.patch new file mode 100644 index 0000000000..e4042bea81 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/SmithingTransformRecipe.java.patch @@ -0,0 +1,37 @@ +--- a/net/minecraft/world/item/crafting/SmithingTransformRecipe.java ++++ b/net/minecraft/world/item/crafting/SmithingTransformRecipe.java +@@ -9,6 +9,13 @@ + import net.minecraft.world.Container; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftSmithingTransformRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end + + public class SmithingTransformRecipe implements SmithingRecipe { + +@@ -79,8 +78,19 @@ + return Stream.of(this.template, this.base, this.addition).anyMatch(Ingredient::isEmpty); + } + +- public static class Serializer implements RecipeSerializer { ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); + ++ CraftSmithingTransformRecipe recipe = new CraftSmithingTransformRecipe(id, result, CraftRecipe.toBukkit(this.template), CraftRecipe.toBukkit(this.base), CraftRecipe.toBukkit(this.addition)); ++ ++ return recipe; ++ } ++ // CraftBukkit end ++ ++ public static class a implements RecipeSerializer { ++ + private static final Codec CODEC = RecordCodecBuilder.create((instance) -> { + return instance.group(Ingredient.CODEC.fieldOf("template").forGetter((smithingtransformrecipe) -> { + return smithingtransformrecipe.template; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/SmithingTrimRecipe.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/SmithingTrimRecipe.java.patch new file mode 100644 index 0000000000..fda66586fc --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/SmithingTrimRecipe.java.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/world/item/crafting/SmithingTrimRecipe.java ++++ b/net/minecraft/world/item/crafting/SmithingTrimRecipe.java +@@ -17,6 +17,12 @@ + import net.minecraft.world.item.armortrim.TrimPattern; + import net.minecraft.world.item.armortrim.TrimPatterns; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftSmithingTrimRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end + + public class SmithingTrimRecipe implements SmithingRecipe { + +@@ -115,7 +113,12 @@ + return Stream.of(this.template, this.base, this.addition).anyMatch(Ingredient::isEmpty); + } + +- public static class Serializer implements RecipeSerializer { ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ return new CraftSmithingTrimRecipe(id, CraftRecipe.toBukkit(this.template), CraftRecipe.toBukkit(this.base), CraftRecipe.toBukkit(this.addition)); ++ } ++ // CraftBukkit end + + private static final Codec CODEC = RecordCodecBuilder.create((instance) -> { + return instance.group(Ingredient.CODEC.fieldOf("template").forGetter((smithingtrimrecipe) -> { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/SmokingRecipe.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/SmokingRecipe.java.patch new file mode 100644 index 0000000000..c09a16b9e8 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/SmokingRecipe.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/item/crafting/SmokingRecipe.java ++++ b/net/minecraft/world/item/crafting/SmokingRecipe.java +@@ -3,6 +3,14 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftSmokingRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class SmokingRecipe extends AbstractCookingRecipe { + + public SmokingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient ingredient, ItemStack itemstack, float f, int i) { +@@ -20,4 +26,17 @@ + public RecipeSerializer getSerializer() { + return RecipeSerializer.SMOKING_RECIPE; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftSmokingRecipe recipe = new CraftSmokingRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/StonecutterRecipe.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/StonecutterRecipe.java.patch new file mode 100644 index 0000000000..5a8da8ebc4 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/crafting/StonecutterRecipe.java.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/item/crafting/StonecutterRecipe.java ++++ b/net/minecraft/world/item/crafting/StonecutterRecipe.java +@@ -5,6 +5,14 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftStonecuttingRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class StonecutterRecipe extends SingleItemRecipe { + + public StonecutterRecipe(String s, Ingredient ingredient, ItemStack itemstack) { +@@ -22,4 +28,16 @@ + public ItemStack getToastSymbol() { + return new ItemStack(Blocks.STONECUTTER); + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftStonecuttingRecipe recipe = new CraftStonecuttingRecipe(id, result, CraftRecipe.toBukkit(this.ingredient)); ++ recipe.setGroup(this.group); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/enchantment/DamageEnchantment.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/enchantment/DamageEnchantment.java.patch new file mode 100644 index 0000000000..48596baafd --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/enchantment/DamageEnchantment.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/item/enchantment/DamageEnchantment.java ++++ b/net/minecraft/world/item/enchantment/DamageEnchantment.java +@@ -70,7 +63,7 @@ + if (this.type == 2 && i > 0 && livingentity1.getMobType() == MobType.ARTHROPOD) { + int j = 20 + livingentity.getRandom().nextInt(10 * i); + +- livingentity1.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, j, 3)); ++ entityliving1.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, j, 3), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/enchantment/FrostWalkerEnchantment.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/enchantment/FrostWalkerEnchantment.java.patch new file mode 100644 index 0000000000..76b89e3376 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/enchantment/FrostWalkerEnchantment.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/item/enchantment/FrostWalkerEnchantment.java ++++ b/net/minecraft/world/item/enchantment/FrostWalkerEnchantment.java +@@ -58,9 +54,12 @@ + if (blockstate1.isAir()) { + BlockState blockstate2 = level.getBlockState(blockpos1); + +- if (blockstate2 == FrostedIceBlock.meltsInto() && blockstate.canSurvive(level, blockpos1) && level.isUnobstructed(blockstate, blockpos1, CollisionContext.empty())) { +- level.setBlockAndUpdate(blockpos1, blockstate); +- level.scheduleTick(blockpos1, Blocks.FROSTED_ICE, Mth.nextInt(livingentity.getRandom(), 60, 120)); ++ if (iblockdata2 == FrostedIceBlock.meltsInto() && iblockdata.canSurvive(level, blockposition1) && level.isUnobstructed(iblockdata, blockposition1, CollisionContext.empty())) { ++ // CraftBukkit Start - Call EntityBlockFormEvent for Frost Walker ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, blockposition1, iblockdata, living)) { ++ level.scheduleTick(blockposition1, Blocks.FROSTED_ICE, Mth.nextInt(living.getRandom(), 60, 120)); ++ } ++ // CraftBukkit End + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/trading/Merchant.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/trading/Merchant.java.patch new file mode 100644 index 0000000000..592a148801 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/trading/Merchant.java.patch @@ -0,0 +1,9 @@ +--- a/net/minecraft/world/item/trading/Merchant.java ++++ b/net/minecraft/world/item/trading/Merchant.java +@@ -52,4 +52,6 @@ + } + + boolean isClientSide(); ++ ++ org.bukkit.craftbukkit.inventory.CraftMerchant getCraftMerchant(); // CraftBukkit + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/trading/MerchantOffer.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/trading/MerchantOffer.java.patch new file mode 100644 index 0000000000..497a5ecc84 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/item/trading/MerchantOffer.java.patch @@ -0,0 +1,73 @@ +--- a/net/minecraft/world/item/trading/MerchantOffer.java ++++ b/net/minecraft/world/item/trading/MerchantOffer.java +@@ -5,20 +5,38 @@ + import net.minecraft.util.Mth; + import net.minecraft.world.item.ItemStack; + ++import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; // CraftBukkit ++ + public class MerchantOffer { + +- private final ItemStack baseCostA; +- private final ItemStack costB; +- private final ItemStack result; +- private int uses; +- private final int maxUses; +- private boolean rewardExp; +- private int specialPriceDiff; +- private int demand; +- private float priceMultiplier; +- private int xp; ++ public ItemStack baseCostA; ++ public ItemStack costB; ++ public final ItemStack result; ++ public int uses; ++ public int maxUses; ++ public boolean rewardExp; ++ public int specialPriceDiff; ++ public int demand; ++ public float priceMultiplier; ++ public int xp; ++ // CraftBukkit start ++ private CraftMerchantRecipe bukkitHandle; + +- public MerchantOffer(CompoundTag compoundtag) { ++ public CraftMerchantRecipe asBukkit() { ++ return (bukkitHandle == null) ? bukkitHandle = new CraftMerchantRecipe(this) : bukkitHandle; ++ } ++ ++ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, CraftMerchantRecipe bukkit) { ++ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, 0, bukkit); ++ } ++ ++ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, int demand, CraftMerchantRecipe bukkit) { ++ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, demand); ++ this.bukkitHandle = bukkit; ++ } ++ // CraftBukkit end ++ ++ public MerchantOffer(CompoundTag compoundTag) { + this.rewardExp = true; + this.xp = 1; + this.baseCostA = ItemStack.of(compoundtag.getCompound("buy")); +@@ -96,6 +114,7 @@ + return ItemStack.EMPTY; + } else { + int i = this.baseCostA.getCount(); ++ if (i <= 0) return ItemStack.EMPTY; // CraftBukkit - SPIGOT-5476 + int j = Math.max(0, Mth.floor((float) (i * this.demand) * this.priceMultiplier)); + + return this.baseCostA.copyWithCount(Mth.clamp(i + j + this.specialPriceDiff, 1, this.baseCostA.getItem().getMaxStackSize())); +@@ -216,7 +235,11 @@ + if (!this.satisfiedBy(itemstack, itemstack1)) { + return false; + } else { +- itemstack.shrink(this.getCostA().getCount()); ++ // CraftBukkit start ++ if (!this.getCostA().isEmpty()) { ++ playerOfferA.shrink(this.getCostA().getCount()); ++ } ++ // CraftBukkit end + if (!this.getCostB().isEmpty()) { + itemstack1.shrink(this.getCostB().getCount()); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/BaseCommandBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/BaseCommandBlock.java.patch new file mode 100644 index 0000000000..c3f913c304 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/BaseCommandBlock.java.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/level/BaseCommandBlock.java ++++ b/net/minecraft/world/level/BaseCommandBlock.java +@@ -30,6 +30,10 @@ + private Component lastOutput; + private String command = ""; + private Component name; ++ // CraftBukkit start ++ @Override ++ public abstract org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper); ++ // CraftBukkit end + + public BaseCommandBlock() { + this.name = BaseCommandBlock.DEFAULT_NAME; +@@ -126,7 +130,7 @@ + + }); + +- minecraftserver.getCommands().performPrefixedCommand(commandsourcestack, this.command); ++ minecraftserver.getCommands().dispatchServerCommand(commandlistenerwrapper, this.command); // CraftBukkit + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Executing command block"); + CrashReportCategory crashreportcategory = crashreport.addCategory("Command to be executed"); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/BaseSpawner.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/BaseSpawner.java.patch new file mode 100644 index 0000000000..d597c8cea9 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/BaseSpawner.java.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/level/BaseSpawner.java ++++ b/net/minecraft/world/level/BaseSpawner.java +@@ -50,8 +50,9 @@ + + public BaseSpawner() {} + +- public void setEntityId(EntityType entitytype, @Nullable Level level, RandomSource randomsource, BlockPos blockpos) { +- this.getOrCreateNextSpawnData(level, randomsource, blockpos).getEntityToSpawn().putString("id", BuiltInRegistries.ENTITY_TYPE.getKey(entitytype).toString()); ++ public void setEntityId(EntityType type, @Nullable Level level, RandomSource random, BlockPos pos) { ++ this.getOrCreateNextSpawnData(level, random, pos).getEntityToSpawn().putString("id", BuiltInRegistries.ENTITY_TYPE.getKey(type).toString()); ++ this.spawnPotentials = SimpleWeightedRandomList.empty(); // CraftBukkit - SPIGOT-3496, MC-92282 + } + + private boolean isNearPlayer(Level level, BlockPos blockpos) { +@@ -154,8 +155,13 @@ + } + } + +- if (!serverlevel.tryAddFreshEntityWithPassengers(entity)) { +- this.delay(serverlevel, blockpos); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) { ++ continue; ++ } ++ if (!serverLevel.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER)) { ++ // CraftBukkit end ++ this.delay(serverLevel, pos); + return; + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/BlockGetter.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/BlockGetter.java.patch new file mode 100644 index 0000000000..b36a28adfd --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/BlockGetter.java.patch @@ -0,0 +1,49 @@ +--- a/net/minecraft/world/level/BlockGetter.java ++++ b/net/minecraft/world/level/BlockGetter.java +@@ -58,24 +58,30 @@ + }); + } + +- default BlockHitResult clip(ClipContext clipcontext) { +- return (BlockHitResult) traverseBlocks(clipcontext.getFrom(), clipcontext.getTo(), clipcontext, (clipcontext1, blockpos) -> { +- BlockState blockstate = this.getBlockState(blockpos); +- FluidState fluidstate = this.getFluidState(blockpos); +- Vec3 vec3 = clipcontext1.getFrom(); +- Vec3 vec31 = clipcontext1.getTo(); +- VoxelShape voxelshape = clipcontext1.getBlockShape(blockstate, this, blockpos); +- BlockHitResult blockhitresult = this.clipWithInteractionOverride(vec3, vec31, blockpos, voxelshape, blockstate); +- VoxelShape voxelshape1 = clipcontext1.getFluidShape(fluidstate, this, blockpos); +- BlockHitResult blockhitresult1 = voxelshape1.clip(vec3, vec31, blockpos); +- double d0 = blockhitresult == null ? Double.MAX_VALUE : clipcontext1.getFrom().distanceToSqr(blockhitresult.getLocation()); +- double d1 = blockhitresult1 == null ? Double.MAX_VALUE : clipcontext1.getFrom().distanceToSqr(blockhitresult1.getLocation()); ++ // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace ++ default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition) { ++ IBlockData iblockdata = this.getBlockState(blockposition); ++ FluidState fluid = this.getFluidState(blockposition); ++ Vec3 vec3d = raytrace1.getFrom(); ++ Vec3 vec3d1 = raytrace1.getTo(); ++ VoxelShape voxelshape = raytrace1.getBlockShape(iblockdata, this, blockposition); ++ BlockHitResult movingobjectpositionblock = this.clipWithInteractionOverride(vec3d, vec3d1, blockposition, voxelshape, iblockdata); ++ VoxelShape voxelshape1 = raytrace1.getFluidShape(fluid, this, blockposition); ++ BlockHitResult movingobjectpositionblock1 = voxelshape1.clip(vec3d, vec3d1, blockposition); ++ double d0 = movingobjectpositionblock == null ? Double.MAX_VALUE : raytrace1.getFrom().distanceToSqr(movingobjectpositionblock.getLocation()); ++ double d1 = movingobjectpositionblock1 == null ? Double.MAX_VALUE : raytrace1.getFrom().distanceToSqr(movingobjectpositionblock1.getLocation()); + +- return d0 <= d1 ? blockhitresult : blockhitresult1; +- }, (clipcontext1) -> { +- Vec3 vec3 = clipcontext1.getFrom().subtract(clipcontext1.getTo()); ++ return d0 <= d1 ? movingobjectpositionblock : movingobjectpositionblock1; ++ } ++ // CraftBukkit end + +- return BlockHitResult.miss(clipcontext1.getTo(), Direction.getNearest(vec3.x, vec3.y, vec3.z), BlockPos.containing(clipcontext1.getTo())); ++ default BlockHitResult clip(ClipContext context) { ++ return (BlockHitResult) traverseBlocks(context.getFrom(), context.getTo(), context, (raytrace1, blockposition) -> { ++ return this.clip(raytrace1, blockposition); // CraftBukkit - moved into separate method ++ }, (raytrace1) -> { ++ Vec3 vec3d = raytrace1.getFrom().subtract(raytrace1.getTo()); ++ ++ return BlockHitResult.miss(raytrace1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(raytrace1.getTo())); + }); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/ClipContext.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/ClipContext.java.patch new file mode 100644 index 0000000000..8f1992fa07 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/ClipContext.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/level/ClipContext.java ++++ b/net/minecraft/world/level/ClipContext.java +@@ -21,8 +21,8 @@ + private final ClipContext.Fluid fluid; + private final CollisionContext collisionContext; + +- public ClipContext(Vec3 vec3, Vec3 vec31, ClipContext.Block clipcontext_block, ClipContext.Fluid clipcontext_fluid, Entity entity) { +- this(vec3, vec31, clipcontext_block, clipcontext_fluid, CollisionContext.of(entity)); ++ public ClipContext(Vec3 from, Vec3 to, ClipContext.Block block, ClipContext.Fluid fluid, Entity entity) { ++ this(from, to, block, fluid, (entity == null) ? CollisionContext.empty() : CollisionContext.of(entity)); // CraftBukkit + } + + public ClipContext(Vec3 vec3, Vec3 vec31, ClipContext.Block clipcontext_block, ClipContext.Fluid clipcontext_fluid, CollisionContext collisioncontext) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/Explosion.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/Explosion.java.patch new file mode 100644 index 0000000000..9c6b59259b --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/Explosion.java.patch @@ -0,0 +1,189 @@ +--- a/net/minecraft/world/level/Explosion.java ++++ b/net/minecraft/world/level/Explosion.java +@@ -38,6 +40,12 @@ + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++import net.minecraft.world.level.block.Blocks; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityExplodeEvent; ++import org.bukkit.Location; ++import org.bukkit.event.block.BlockExplodeEvent; ++// CraftBukkit end + + public class Explosion { + +@@ -60,6 +68,10 @@ + private final SoundEvent explosionSound; + private final ObjectArrayList toBlow; + private final Map hitPlayers; ++ // CraftBukkit - add field ++ public boolean wasCanceled = false; ++ public float yield; ++ // CraftBukkit end + + public static DamageSource getDefaultDamageSource(Level level, @Nullable Entity entity) { + return level.damageSources().explosion(entity, getIndirectSourceEntityInternal(entity)); +@@ -85,7 +97,7 @@ + this.hitPlayers = Maps.newHashMap(); + this.level = level; + this.source = entity; +- this.radius = f; ++ this.radius = (float) Math.max(f, 0.0); // CraftBukkit - clamp bad values + this.x = d0; + this.y = d1; + this.z = d2; +@@ -93,9 +105,10 @@ + this.blockInteraction = explosion_blockinteraction; + this.damageSource = damagesource == null ? level.damageSources().explosion(this) : damagesource; + this.damageCalculator = explosiondamagecalculator == null ? this.makeDamageCalculator(entity) : explosiondamagecalculator; +- this.smallExplosionParticles = particleoptions; +- this.largeExplosionParticles = particleoptions1; +- this.explosionSound = soundevent; ++ this.smallExplosionParticles = particleparam; ++ this.largeExplosionParticles = particleparam1; ++ this.explosionSound = soundeffect; ++ this.yield = this.blockInteraction == Explosion.Effect.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F; // CraftBukkit + } + + private ExplosionDamageCalculator makeDamageCalculator(@Nullable Entity entity) { +@@ -146,6 +159,11 @@ + } + + public void explode() { ++ // CraftBukkit start ++ if (this.radius < 0.1F) { ++ return; ++ } ++ // CraftBukkit end + this.level.gameEvent(this.source, GameEvent.EXPLODE, new Vec3(this.x, this.y, this.z)); + Set set = Sets.newHashSet(); + boolean flag = true; +@@ -228,7 +246,37 @@ + d9 /= d11; + d10 /= d11; + if (this.damageCalculator.shouldDamageEntity(this, entity)) { +- entity.hurt(this.damageSource, this.damageCalculator.getEntityDamageAmount(this, entity)); ++ // CraftBukkit start ++ ++ // Special case ender dragon only give knockback if no damage is cancelled ++ // Thinks to note: ++ // - Setting a velocity to a ComplexEntityPart is ignored (and therefore not needed) ++ // - Damaging ComplexEntityPart while forward the damage to EntityEnderDragon ++ // - Damaging EntityEnderDragon does nothing ++ // - EntityEnderDragon hitbock always covers the other parts and is therefore always present ++ if (entity instanceof EnderDragonPart) { ++ continue; ++ } ++ ++ CraftEventFactory.entityDamage = source; ++ entity.lastDamageCancelled = false; ++ ++ if (entity instanceof EnderDragon) { ++ for (EnderDragonPart entityComplexPart : ((EnderDragon) entity).subEntities) { ++ // Calculate damage separately for each EntityComplexPart ++ if (list.contains(entityComplexPart)) { ++ entityComplexPart.hurt(this.damageSource, this.damageCalculator.getEntityDamageAmount(this, entity)); ++ } ++ } ++ } else { ++ entity.hurt(this.damageSource, this.damageCalculator.getEntityDamageAmount(this, entity)); ++ } ++ ++ CraftEventFactory.entityDamage = null; ++ if (entity.lastDamageCancelled) { // SPIGOT-5339, SPIGOT-6252, SPIGOT-6777: Skip entity if damage event was cancelled ++ continue; ++ } ++ // CraftBukkit end + } + + double d12 = (1.0D - d7) * (double) getSeenPercent(vec3, entity); +@@ -287,9 +335,63 @@ + + Util.shuffle(this.toBlow, this.level.random); + ObjectListIterator objectlistiterator = this.toBlow.iterator(); ++ // CraftBukkit start ++ org.bukkit.World bworld = this.level.getWorld(); ++ org.bukkit.entity.Entity explode = this.source == null ? null : this.source.getBukkitEntity(); ++ Location location = new Location(bworld, this.x, this.y, this.z); + ++ List blockList = new ObjectArrayList<>(); ++ for (int i1 = this.toBlow.size() - 1; i1 >= 0; i1--) { ++ BlockPos cpos = this.toBlow.get(i1); ++ org.bukkit.block.Block bblock = bworld.getBlockAt(cpos.getX(), cpos.getY(), cpos.getZ()); ++ if (!bblock.getType().isAir()) { ++ blockList.add(bblock); ++ } ++ } ++ ++ List bukkitBlocks; ++ ++ if (explode != null) { ++ EntityExplodeEvent event = new EntityExplodeEvent(explode, location, blockList, this.yield); ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ this.wasCanceled = event.isCancelled(); ++ bukkitBlocks = event.blockList(); ++ this.yield = event.getYield(); ++ } else { ++ BlockExplodeEvent event = new BlockExplodeEvent(location.getBlock(), blockList, this.yield); ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ this.wasCanceled = event.isCancelled(); ++ bukkitBlocks = event.blockList(); ++ this.yield = event.getYield(); ++ } ++ ++ this.toBlow.clear(); ++ ++ for (org.bukkit.block.Block bblock : bukkitBlocks) { ++ BlockPos coords = new BlockPos(bblock.getX(), bblock.getY(), bblock.getZ()); ++ toBlow.add(coords); ++ } ++ ++ if (this.wasCanceled) { ++ return; ++ } ++ // CraftBukkit end ++ objectlistiterator = this.toBlow.iterator(); ++ + while (objectlistiterator.hasNext()) { +- BlockPos blockpos = (BlockPos) objectlistiterator.next(); ++ BlockPos blockposition = (BlockPos) objectlistiterator.next(); ++ // CraftBukkit start - TNTPrimeEvent ++ IBlockData iblockdata = this.level.getBlockState(blockposition); ++ Block block = iblockdata.getBlock(); ++ if (block instanceof net.minecraft.world.level.block.TntBlock) { ++ Entity sourceEntity = source == null ? null : source; ++ BlockPos sourceBlock = sourceEntity == null ? BlockPos.containing(this.x, this.y, this.z) : null; ++ if (!CraftEventFactory.callTNTPrimeEvent(this.level, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.EXPLOSION, sourceEntity, sourceBlock)) { ++ this.level.sendBlockUpdated(blockposition, Blocks.AIR.defaultBlockState(), iblockdata, 3); // Update the block on the client ++ continue; ++ } ++ } ++ // CraftBukkit end + + this.level.getBlockState(blockpos).onExplosionHit(this.level, blockpos, this, (itemstack, blockpos1) -> { + addOrAppendStack(list, itemstack, blockpos1); +@@ -313,15 +415,20 @@ + while (objectlistiterator1.hasNext()) { + BlockPos blockpos1 = (BlockPos) objectlistiterator1.next(); + +- if (this.random.nextInt(3) == 0 && this.level.getBlockState(blockpos1).isAir() && this.level.getBlockState(blockpos1.below()).isSolidRender(this.level, blockpos1.below())) { +- this.level.setBlockAndUpdate(blockpos1, BaseFireBlock.getState(this.level, blockpos1)); ++ if (this.random.nextInt(3) == 0 && this.level.getBlockState(blockposition1).isAir() && this.level.getBlockState(blockposition1.below()).isSolidRender(this.level, blockposition1.below())) { ++ // CraftBukkit start - Ignition by explosion ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(this.level, blockposition1, this).isCancelled()) { ++ this.level.setBlockAndUpdate(blockposition1, BaseFireBlock.getState(this.level, blockposition1)); ++ } ++ // CraftBukkit end + } + } + } + + } + +- private static void addOrAppendStack(List> list, ItemStack itemstack, BlockPos blockpos) { ++ private static void addOrAppendStack(List> list, ItemStack itemstack, BlockPos blockposition) { ++ if (itemstack.isEmpty()) return; // CraftBukkit - SPIGOT-5425 + for (int i = 0; i < list.size(); ++i) { + Pair pair = (Pair) list.get(i); + ItemStack itemstack1 = (ItemStack) pair.getFirst(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/GameRules.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/GameRules.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/GameRules.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/Level.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/Level.java.patch new file mode 100644 index 0000000000..2e0b34452c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/Level.java.patch @@ -0,0 +1,316 @@ +--- a/net/minecraft/world/level/Level.java ++++ b/net/minecraft/world/level/Level.java +@@ -75,6 +79,27 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.scores.Scoreboard; + ++// CraftBukkit start ++import java.util.HashMap; ++import java.util.Map; ++import net.minecraft.network.protocol.game.ClientboundSetBorderCenterPacket; ++import net.minecraft.network.protocol.game.ClientboundSetBorderLerpSizePacket; ++import net.minecraft.network.protocol.game.ClientboundSetBorderSizePacket; ++import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDelayPacket; ++import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDistancePacket; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.block.CapturedBlockState; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.craftbukkit.util.CraftSpawnCategory; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.entity.SpawnCategory; ++import org.bukkit.event.block.BlockPhysicsEvent; ++import org.bukkit.event.world.GenericGameEvent; ++// CraftBukkit end ++ + public abstract class Level implements LevelAccessor, AutoCloseable { + + public static final Codec> RESOURCE_KEY_CODEC = ResourceKey.codec(Registries.DIMENSION); +@@ -117,7 +142,43 @@ + private final DamageSources damageSources; + private long subTickCount; + +- protected Level(WritableLevelData writableleveldata, ResourceKey resourcekey, RegistryAccess registryaccess, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j) { ++ // CraftBukkit start Added the following ++ private final CraftWorld world; ++ public boolean pvpMode; ++ public boolean keepSpawnInMemory = true; ++ public org.bukkit.generator.ChunkGenerator generator; ++ ++ public boolean preventPoiUpdated = false; // CraftBukkit - SPIGOT-5710 ++ public boolean captureBlockStates = false; ++ public boolean captureTreeGeneration = false; ++ public Map capturedBlockStates = new java.util.LinkedHashMap<>(); ++ public Map capturedTileEntities = new HashMap<>(); ++ public List captureDrops; ++ public final it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap ticksPerSpawnCategory = new it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<>(); ++ public boolean populating; ++ ++ public CraftWorld getWorld() { ++ return this.world; ++ } ++ ++ public CraftServer getCraftServer() { ++ return (CraftServer) Bukkit.getServer(); ++ } ++ ++ public abstract ResourceKey getTypeKey(); ++ ++ protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env) { ++ this.generator = gen; ++ this.world = new CraftWorld((ServerLevel) this, gen, biomeProvider, env); ++ ++ // CraftBukkit Ticks things ++ for (SpawnCategory spawnCategory : SpawnCategory.values()) { ++ if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { ++ this.ticksPerSpawnCategory.put(spawnCategory, (long) this.getCraftServer().getTicksPerSpawns(spawnCategory)); ++ } ++ } ++ ++ // CraftBukkit end + this.profiler = supplier; + this.levelData = writableleveldata; + this.dimensionTypeRegistration = holder; +@@ -133,13 +193,13 @@ + @Override + @Override + public double getCenterX() { +- return super.getCenterX() / dimensiontype.coordinateScale(); ++ return super.getCenterX(); // CraftBukkit + } + + @Override + @Override + public double getCenterZ() { +- return super.getCenterZ() / dimensiontype.coordinateScale(); ++ return super.getCenterZ(); // CraftBukkit + } + }; + } else { +@@ -150,8 +209,44 @@ + this.biomeManager = new BiomeManager(this, i); + this.isDebug = flag1; + this.neighborUpdater = new CollectingNeighborUpdater(this, j); +- this.registryAccess = registryaccess; +- this.damageSources = new DamageSources(registryaccess); ++ this.registryAccess = iregistrycustom; ++ this.damageSources = new DamageSources(iregistrycustom); ++ // CraftBukkit start ++ getWorldBorder().world = (ServerLevel) this; ++ // From PlayerList.setPlayerFileData ++ getWorldBorder().addListener(new BorderChangeListener() { ++ @Override ++ public void onBorderSizeSet(WorldBorder border, double size) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderSizePacket(border), border.world); ++ } ++ ++ @Override ++ public void onBorderSizeLerping(WorldBorder border, double oldSize, double d1, long newSize) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderLerpSizePacket(border), border.world); ++ } ++ ++ @Override ++ public void onBorderCenterSet(WorldBorder border, double x, double d1) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderCenterPacket(border), border.world); ++ } ++ ++ @Override ++ public void onBorderSetWarningTime(WorldBorder border, int warningTime) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderWarningDelayPacket(border), border.world); ++ } ++ ++ @Override ++ public void onBorderSetWarningBlocks(WorldBorder border, int warningBlocks) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderWarningDistancePacket(border), border.world); ++ } ++ ++ @Override ++ public void onBorderSetDamagePerBlock(WorldBorder border, double damagePerBlock) {} ++ ++ @Override ++ public void onBorderSetDamageSafeZOne(WorldBorder border, double damageSafeZone) {} ++ }); ++ // CraftBukkit end + } + + @Override +@@ -213,9 +303,19 @@ + } + + @Override +- @Override +- public boolean setBlock(BlockPos blockpos, BlockState blockstate, int i, int j) { +- if (this.isOutsideBuildHeight(blockpos)) { ++ public boolean setBlock(BlockPos pos, IBlockData state, int flags, int recursionLeft) { ++ // CraftBukkit start - tree generation ++ if (this.captureTreeGeneration) { ++ CapturedBlockState blockstate = capturedBlockStates.get(pos); ++ if (blockstate == null) { ++ blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags); ++ this.capturedBlockStates.put(pos.immutable(), blockstate); ++ } ++ blockstate.setData(state); ++ return true; ++ } ++ // CraftBukkit end ++ if (this.isOutsideBuildHeight(pos)) { + return false; + } else if (!this.isClientSide && this.isDebug()) { + return false; +@@ -224,7 +323,23 @@ + Block block = blockstate.getBlock(); + BlockState blockstate1 = levelchunk.setBlockState(blockpos, blockstate, (i & 64) != 0); + +- if (blockstate1 == null) { ++ // CraftBukkit start - capture blockstates ++ boolean captured = false; ++ if (this.captureBlockStates && !this.capturedBlockStates.containsKey(pos)) { ++ CapturedBlockState blockstate = CapturedBlockState.getBlockState(this, pos, flags); ++ this.capturedBlockStates.put(pos.immutable(), blockstate); ++ captured = true; ++ } ++ // CraftBukkit end ++ ++ IBlockData iblockdata1 = chunk.setBlockState(pos, state, (flags & 64) != 0, (flags & 1024) == 0); // CraftBukkit custom NO_PLACE flag ++ ++ if (iblockdata1 == null) { ++ // CraftBukkit start - remove blockstate if failed (or the same) ++ if (this.captureBlockStates && captured) { ++ this.capturedBlockStates.remove(pos); ++ } ++ // CraftBukkit end + return false; + } else { + BlockState blockstate2 = this.getBlockState(blockpos); +@@ -256,13 +373,69 @@ + this.onBlockStateChange(blockpos, blockstate1, blockstate2); + } + ++ // CraftBukkit start ++ if (!this.captureBlockStates) { // Don't notify clients or update physics while capturing blockstates ++ // Modularize client and physic updates ++ notifyAndUpdatePhysics(pos, chunk, iblockdata1, state, iblockdata2, flags, recursionLeft); ++ } ++ // CraftBukkit end ++ + return true; + } + } + } + +- public void onBlockStateChange(BlockPos blockpos, BlockState blockstate, BlockState blockstate1) {} ++ // CraftBukkit start - Split off from above in order to directly send client and physic updates ++ public void notifyAndUpdatePhysics(BlockPos blockposition, LevelChunk chunk, IBlockData oldBlock, IBlockData newBlock, IBlockData actualBlock, int i, int j) { ++ IBlockData iblockdata = newBlock; ++ IBlockData iblockdata1 = oldBlock; ++ IBlockData iblockdata2 = actualBlock; ++ if (iblockdata2 == iblockdata) { ++ if (iblockdata1 != iblockdata2) { ++ this.setBlocksDirty(blockposition, iblockdata1, iblockdata2); ++ } + ++ if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getFullStatus() != null && chunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement ++ this.sendBlockUpdated(blockposition, iblockdata1, iblockdata, i); ++ } ++ ++ if ((i & 1) != 0) { ++ this.blockUpdated(blockposition, iblockdata1.getBlock()); ++ if (!this.isClientSide && iblockdata.hasAnalogOutputSignal()) { ++ this.updateNeighbourForOutputSignal(blockposition, newBlock.getBlock()); ++ } ++ } ++ ++ if ((i & 16) == 0 && j > 0) { ++ int k = i & -34; ++ ++ // CraftBukkit start ++ iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam ++ CraftWorld world = ((ServerLevel) this).getWorld(); ++ if (world != null) { ++ BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata)); ++ this.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ iblockdata.updateNeighbourShapes(this, blockposition, k, j - 1); ++ iblockdata.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); ++ } ++ ++ // CraftBukkit start - SPIGOT-5710 ++ if (!preventPoiUpdated) { ++ this.onBlockStateChange(blockposition, iblockdata1, iblockdata2); ++ } ++ // CraftBukkit end ++ } ++ } ++ // CraftBukkit end ++ ++ public void onBlockStateChange(BlockPos pos, IBlockData blockState, IBlockData newState) {} ++ + @Override + @Override + public boolean removeBlock(BlockPos blockpos, boolean flag) { +@@ -350,9 +518,16 @@ + } + + @Override +- @Override +- public BlockState getBlockState(BlockPos blockpos) { +- if (this.isOutsideBuildHeight(blockpos)) { ++ public IBlockData getBlockState(BlockPos pos) { ++ // CraftBukkit start - tree generation ++ if (captureTreeGeneration) { ++ CapturedBlockState previous = capturedBlockStates.get(pos); ++ if (previous != null) { ++ return previous.getHandle(); ++ } ++ } ++ // CraftBukkit end ++ if (this.isOutsideBuildHeight(pos)) { + return Blocks.VOID_AIR.defaultBlockState(); + } else { + LevelChunk levelchunk = this.getChunk(SectionPos.blockToSectionCoord(blockpos.getX()), SectionPos.blockToSectionCoord(blockpos.getZ())); +@@ -559,16 +731,31 @@ + + @Nullable + @Override +- @Override +- public BlockEntity getBlockEntity(BlockPos blockpos) { +- return this.isOutsideBuildHeight(blockpos) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(blockpos).getBlockEntity(blockpos, LevelChunk.EntityCreationType.IMMEDIATE)); ++ public BlockEntity getBlockEntity(BlockPos pos) { ++ // CraftBukkit start ++ return getBlockEntity(pos, true); + } + +- public void setBlockEntity(BlockEntity blockentity) { +- BlockPos blockpos = blockentity.getBlockPos(); ++ @Nullable ++ public BlockEntity getBlockEntity(BlockPos blockposition, boolean validate) { ++ if (capturedTileEntities.containsKey(blockposition)) { ++ return capturedTileEntities.get(blockposition); ++ } ++ // CraftBukkit end ++ return this.isOutsideBuildHeight(blockposition) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(blockposition).getBlockEntity(blockposition, LevelChunk.EnumTileEntityState.IMMEDIATE)); ++ } + +- if (!this.isOutsideBuildHeight(blockpos)) { +- this.getChunkAt(blockpos).addAndRegisterBlockEntity(blockentity); ++ public void setBlockEntity(BlockEntity blockEntity) { ++ BlockPos blockposition = blockEntity.getBlockPos(); ++ ++ if (!this.isOutsideBuildHeight(blockposition)) { ++ // CraftBukkit start ++ if (captureBlockStates) { ++ capturedTileEntities.put(blockposition.immutable(), blockEntity); ++ return; ++ } ++ // CraftBukkit end ++ this.getChunkAt(blockposition).addAndRegisterBlockEntity(blockEntity); + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/LevelAccessor.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/LevelAccessor.java.patch new file mode 100644 index 0000000000..39ce92c7b6 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/LevelAccessor.java.patch @@ -0,0 +1,9 @@ +--- a/net/minecraft/world/level/LevelAccessor.java ++++ b/net/minecraft/world/level/LevelAccessor.java +@@ -116,4 +114,6 @@ + default void gameEvent(GameEvent gameevent, BlockPos blockpos, GameEvent.Context gameevent_context) { + this.gameEvent(gameevent, Vec3.atCenterOf(blockpos), gameevent_context); + } ++ ++ net.minecraft.server.level.ServerLevel getMinecraftWorld(); // CraftBukkit + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/LevelWriter.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/LevelWriter.java.patch new file mode 100644 index 0000000000..3008822ea1 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/LevelWriter.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/level/LevelWriter.java ++++ b/net/minecraft/world/level/LevelWriter.java +@@ -28,4 +28,10 @@ + default boolean addFreshEntity(Entity entity) { + return false; + } ++ ++ // CraftBukkit start ++ default boolean addFreshEntity(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ return false; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/NaturalSpawner.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/NaturalSpawner.java.patch new file mode 100644 index 0000000000..068638be02 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/NaturalSpawner.java.patch @@ -0,0 +1,101 @@ +--- a/net/minecraft/world/level/NaturalSpawner.java ++++ b/net/minecraft/world/level/NaturalSpawner.java +@@ -48,6 +49,10 @@ + import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.util.CraftSpawnCategory; ++import org.bukkit.entity.SpawnCategory; ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; ++// CraftBukkit end + + public final class NaturalSpawner { + +@@ -113,15 +118,30 @@ + MobCategory[] amobcategory = NaturalSpawner.SPAWNING_CATEGORIES; + int i = amobcategory.length; + ++ LevelData worlddata = level.getLevelData(); // CraftBukkit - Other mob type spawn tick rate ++ + for (int j = 0; j < i; ++j) { +- MobCategory mobcategory = amobcategory[j]; ++ MobCategory enumcreaturetype = aenumcreaturetype[j]; ++ // CraftBukkit start - Use per-world spawn limits ++ boolean spawnThisTick = true; ++ int limit = enumcreaturetype.getMaxInstancesPerChunk(); ++ SpawnCategory spawnCategory = CraftSpawnCategory.toBukkit(enumcreaturetype); ++ if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { ++ spawnThisTick = level.ticksPerSpawnCategory.getLong(spawnCategory) != 0 && worlddata.getGameTime() % level.ticksPerSpawnCategory.getLong(spawnCategory) == 0; ++ limit = level.getWorld().getSpawnLimit(spawnCategory); ++ } + + if ((flag || !mobcategory.isFriendly()) && (flag1 || mobcategory.isFriendly()) && (flag2 || !mobcategory.isPersistent()) && naturalspawner_spawnstate.canSpawnForCategory(mobcategory, levelchunk.getPos())) { + Objects.requireNonNull(naturalspawner_spawnstate); + NaturalSpawner.SpawnPredicate naturalspawner_spawnpredicate = naturalspawner_spawnstate::canSpawn; + +- Objects.requireNonNull(naturalspawner_spawnstate); +- spawnCategoryForChunk(mobcategory, serverlevel, levelchunk, naturalspawner_spawnpredicate, naturalspawner_spawnstate::afterSpawn); ++ if ((spawnFriendlies || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (forcedDespawn || !enumcreaturetype.isPersistent()) && spawnState.canSpawnForCategory(enumcreaturetype, chunk.getPos(), limit)) { ++ // CraftBukkit end ++ Objects.requireNonNull(spawnState); ++ NaturalSpawner.SpawnPredicate spawnercreature_c = spawnState::canSpawn; ++ ++ Objects.requireNonNull(spawnState); ++ spawnCategoryForChunk(enumcreaturetype, level, chunk, spawnercreature_c, spawnState::afterSpawn); + } + } + +@@ -198,14 +218,19 @@ + return; + } + +- mob.moveTo(d0, (double) i, d1, serverlevel.random.nextFloat() * 360.0F, 0.0F); +- if (isValidPositionForMob(serverlevel, mob, d2)) { +- spawngroupdata = mob.finalizeSpawn(serverlevel, serverlevel.getCurrentDifficultyAt(mob.blockPosition()), MobSpawnType.NATURAL, spawngroupdata, (CompoundTag) null); +- ++j; +- ++k1; +- serverlevel.addFreshEntityWithPassengers(mob); +- naturalspawner_afterspawncallback.run(mob, chunkaccess); +- if (j >= mob.getMaxSpawnClusterSize()) { ++ entityinsentient.moveTo(d0, (double) i, d1, level.random.nextFloat() * 360.0F, 0.0F); ++ if (isValidPositionForMob(level, entityinsentient, d2)) { ++ groupdataentity = entityinsentient.finalizeSpawn(level, level.getCurrentDifficultyAt(entityinsentient.blockPosition()), EnumMobSpawn.NATURAL, groupdataentity, (CompoundTag) null); ++ // CraftBukkit start ++ // SPIGOT-7045: Give ocelot babies back their special spawn reason. Note: This is the only modification required as ocelots count as monsters which means they only spawn during normal chunk ticking and do not spawn during chunk generation as starter mobs. ++ level.addFreshEntityWithPassengers(entityinsentient, (entityinsentient instanceof net.minecraft.world.entity.animal.Ocelot && !((org.bukkit.entity.Ageable) entityinsentient.getBukkitEntity()).isAdult()) ? SpawnReason.OCELOT_BABY : SpawnReason.NATURAL); ++ if (!entityinsentient.isRemoved()) { ++ ++j; ++ ++k1; ++ callback.run(entityinsentient, chunk); ++ } ++ // CraftBukkit end ++ if (j >= entityinsentient.getMaxSpawnClusterSize()) { + return; + } + +@@ -388,9 +413,9 @@ + if (entity instanceof Mob) { + Mob mob = (Mob) entity; + +- if (mob.checkSpawnRules(serverlevelaccessor, MobSpawnType.CHUNK_GENERATION) && mob.checkSpawnObstruction(serverlevelaccessor)) { +- spawngroupdata = mob.finalizeSpawn(serverlevelaccessor, serverlevelaccessor.getCurrentDifficultyAt(mob.blockPosition()), MobSpawnType.CHUNK_GENERATION, spawngroupdata, (CompoundTag) null); +- serverlevelaccessor.addFreshEntityWithPassengers(mob); ++ if (entityinsentient.checkSpawnRules(levelAccessor, EnumMobSpawn.CHUNK_GENERATION) && entityinsentient.checkSpawnObstruction(levelAccessor)) { ++ groupdataentity = entityinsentient.finalizeSpawn(levelAccessor, levelAccessor.getCurrentDifficultyAt(entityinsentient.blockPosition()), EnumMobSpawn.CHUNK_GENERATION, groupdataentity, (CompoundTag) null); ++ levelAccessor.addFreshEntityWithPassengers(entityinsentient, SpawnReason.CHUNK_GEN); // CraftBukkit + flag = true; + } + } +@@ -511,8 +536,10 @@ + return this.unmodifiableMobCategoryCounts; + } + +- boolean canSpawnForCategory(MobCategory mobcategory, ChunkPos chunkpos) { +- int i = mobcategory.getMaxInstancesPerChunk() * this.spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER; ++ // CraftBukkit start ++ boolean canSpawnForCategory(MobCategory enumcreaturetype, ChunkPos chunkcoordintpair, int limit) { ++ int i = limit * this.spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER; ++ // CraftBukkit end + + return this.mobCategoryCounts.getInt(mobcategory) >= i ? false : this.localMobCapCalculator.canSpawn(mobcategory, chunkpos); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/ServerLevelAccessor.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/ServerLevelAccessor.java.patch new file mode 100644 index 0000000000..5318edb2bd --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/ServerLevelAccessor.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/level/ServerLevelAccessor.java ++++ b/net/minecraft/world/level/ServerLevelAccessor.java +@@ -8,6 +8,17 @@ + ServerLevel getLevel(); + + default void addFreshEntityWithPassengers(Entity entity) { +- entity.getSelfAndPassengers().forEach(this::addFreshEntity); ++ // CraftBukkit start ++ this.addFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); + } ++ ++ default void addFreshEntityWithPassengers(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ entity.getSelfAndPassengers().forEach((e) -> this.addFreshEntity(e, reason)); ++ } ++ ++ @Override ++ default ServerLevel getMinecraftWorld() { ++ return getLevel(); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/AbstractCandleBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/AbstractCandleBlock.java.patch new file mode 100644 index 0000000000..43a86bef96 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/AbstractCandleBlock.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/level/block/AbstractCandleBlock.java ++++ b/net/minecraft/world/level/block/AbstractCandleBlock.java +@@ -44,10 +43,14 @@ + } + + @Override +- @Override +- public void onProjectileHit(Level level, BlockState blockstate, BlockHitResult blockhitresult, Projectile projectile) { +- if (!level.isClientSide && projectile.isOnFire() && this.canBeLit(blockstate)) { +- setLit(level, blockstate, blockhitresult.getBlockPos(), true); ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { ++ if (!level.isClientSide && projectile.isOnFire() && this.canBeLit(state)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, hit.getBlockPos(), projectile).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ setLit(level, state, hit.getBlockPos(), true); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BambooSaplingBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BambooSaplingBlock.java.patch new file mode 100644 index 0000000000..1fe629ace2 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BambooSaplingBlock.java.patch @@ -0,0 +1,12 @@ +--- a/net/minecraft/world/level/block/BambooSaplingBlock.java ++++ b/net/minecraft/world/level/block/BambooSaplingBlock.java +@@ -104,7 +94,7 @@ + return player.getMainHandItem().getItem() instanceof SwordItem ? 1.0F : super.getDestroyProgress(blockstate, player, blockgetter, blockpos); + } + +- protected void growBamboo(Level level, BlockPos blockpos) { +- level.setBlock(blockpos.above(), (BlockState) Blocks.BAMBOO.defaultBlockState().setValue(BambooStalkBlock.LEAVES, BambooLeaves.SMALL), 3); ++ protected void growBamboo(Level level, BlockPos state) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, state, state.above(), (IBlockData) Blocks.BAMBOO.defaultBlockState().setValue(BambooStalkBlock.LEAVES, BambooLeaves.SMALL), 3); // CraftBukkit - BlockSpreadEvent + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BambooStalkBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BambooStalkBlock.java.patch new file mode 100644 index 0000000000..4dcaa89ffe --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BambooStalkBlock.java.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/world/level/block/BambooStalkBlock.java ++++ b/net/minecraft/world/level/block/BambooStalkBlock.java +@@ -203,7 +187,7 @@ + BlockPos blockpos1 = blockpos.above(i); + BlockState blockstate1 = serverlevel.getBlockState(blockpos1); + +- if (k >= 16 || (Integer) blockstate1.getValue(BambooStalkBlock.STAGE) == 1 || !serverlevel.isEmptyBlock(blockpos1.above())) { ++ if (k >= 16 || !iblockdata1.is(Blocks.BAMBOO) || (Integer) iblockdata1.getValue(BambooStalkBlock.STAGE) == 1 || !level.isEmptyBlock(blockposition1.above())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here + return; + } + +@@ -220,19 +203,23 @@ + return player.getMainHandItem().getItem() instanceof SwordItem ? 1.0F : super.getDestroyProgress(blockstate, player, blockgetter, blockpos); + } + +- protected void growBamboo(BlockState blockstate, Level level, BlockPos blockpos, RandomSource randomsource, int i) { +- BlockState blockstate1 = level.getBlockState(blockpos.below()); +- BlockPos blockpos1 = blockpos.below(2); +- BlockState blockstate2 = level.getBlockState(blockpos1); +- BambooLeaves bambooleaves = BambooLeaves.NONE; ++ protected void growBamboo(IBlockData state, Level level, BlockPos pos, RandomSource random, int age) { ++ IBlockData iblockdata1 = level.getBlockState(pos.below()); ++ BlockPos blockposition1 = pos.below(2); ++ IBlockData iblockdata2 = level.getBlockState(blockposition1); ++ BambooLeaves blockpropertybamboosize = BambooLeaves.NONE; ++ boolean shouldUpdateOthers = false; // CraftBukkit + +- if (i >= 1) { +- if (blockstate1.is(Blocks.BAMBOO) && blockstate1.getValue(BambooStalkBlock.LEAVES) != BambooLeaves.NONE) { +- if (blockstate1.is(Blocks.BAMBOO) && blockstate1.getValue(BambooStalkBlock.LEAVES) != BambooLeaves.NONE) { +- bambooleaves = BambooLeaves.LARGE; +- if (blockstate2.is(Blocks.BAMBOO)) { +- level.setBlock(blockpos.below(), (BlockState) blockstate1.setValue(BambooStalkBlock.LEAVES, BambooLeaves.SMALL), 3); +- level.setBlock(blockpos1, (BlockState) blockstate2.setValue(BambooStalkBlock.LEAVES, BambooLeaves.NONE), 3); ++ if (age >= 1) { ++ if (iblockdata1.is(Blocks.BAMBOO) && iblockdata1.getValue(BambooStalkBlock.LEAVES) != BambooLeaves.NONE) { ++ if (iblockdata1.is(Blocks.BAMBOO) && iblockdata1.getValue(BambooStalkBlock.LEAVES) != BambooLeaves.NONE) { ++ blockpropertybamboosize = BambooLeaves.LARGE; ++ if (iblockdata2.is(Blocks.BAMBOO)) { ++ // CraftBukkit start - moved down ++ // world.setBlock(blockposition.below(), (IBlockData) iblockdata1.setValue(BlockBamboo.LEAVES, BlockPropertyBambooSize.SMALL), 3); ++ // world.setBlock(blockposition1, (IBlockData) iblockdata2.setValue(BlockBamboo.LEAVES, BlockPropertyBambooSize.NONE), 3); ++ shouldUpdateOthers = true; ++ // CraftBukkit end + } + } + } else { +@@ -243,7 +230,14 @@ + int j = (Integer) blockstate.getValue(BambooStalkBlock.AGE) != 1 && !blockstate2.is(Blocks.BAMBOO) ? 0 : 1; + int k = (i < 11 || randomsource.nextFloat() >= 0.25F) && i != 15 ? 0 : 1; + +- level.setBlock(blockpos.above(), (BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(BambooStalkBlock.AGE, j)).setValue(BambooStalkBlock.LEAVES, bambooleaves)).setValue(BambooStalkBlock.STAGE, k), 3); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, pos.above(), (IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(BambooStalkBlock.AGE, j)).setValue(BambooStalkBlock.LEAVES, blockpropertybamboosize)).setValue(BambooStalkBlock.STAGE, k), 3)) { ++ if (shouldUpdateOthers) { ++ level.setBlock(pos.below(), (IBlockData) iblockdata1.setValue(BambooStalkBlock.LEAVES, BambooLeaves.SMALL), 3); ++ level.setBlock(blockposition1, (IBlockData) iblockdata2.setValue(BambooStalkBlock.LEAVES, BambooLeaves.NONE), 3); ++ } ++ } ++ // CraftBukkit end + } + + protected int getHeightAboveUpToMax(BlockGetter blockgetter, BlockPos blockpos) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BaseFireBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BaseFireBlock.java.patch new file mode 100644 index 0000000000..58464d61d0 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BaseFireBlock.java.patch @@ -0,0 +1,50 @@ +--- a/net/minecraft/world/level/block/BaseFireBlock.java ++++ b/net/minecraft/world/level/block/BaseFireBlock.java +@@ -132,7 +127,14 @@ + if (!entity.fireImmune()) { + entity.setRemainingFireTicks(entity.getRemainingFireTicks() + 1); + if (entity.getRemainingFireTicks() == 0) { +- entity.setSecondsOnFire(8); ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityCombustEvent event = new org.bukkit.event.entity.EntityCombustByBlockEvent(org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), entity.getBukkitEntity(), 8); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ entity.setSecondsOnFire(event.getDuration(), false); ++ } ++ // CraftBukkit end + } + } + +@@ -153,15 +154,15 @@ + } + } + +- if (!blockstate.canSurvive(level, blockpos)) { +- level.removeBlock(blockpos, false); ++ if (!state.canSurvive(level, pos)) { ++ fireExtinguished(level, pos); // CraftBukkit - fuel block broke + } + + } + } + + private static boolean inPortalDimension(Level level) { +- return level.dimension() == Level.OVERWORLD || level.dimension() == Level.NETHER; ++ return level.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.OVERWORLD || level.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.NETHER; // CraftBukkit - getTypeKey() + } + + @Override +@@ -211,4 +210,12 @@ + } + } + } ++ ++ // CraftBukkit start ++ protected void fireExtinguished(net.minecraft.world.level.LevelAccessor world, BlockPos position) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, position, Blocks.AIR.defaultBlockState()).isCancelled()) { ++ world.removeBlock(position, false); ++ } ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BasePressurePlateBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BasePressurePlateBlock.java.patch new file mode 100644 index 0000000000..18de1cf8fe --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BasePressurePlateBlock.java.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/world/level/block/BasePressurePlateBlock.java ++++ b/net/minecraft/world/level/block/BasePressurePlateBlock.java +@@ -21,6 +21,7 @@ + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public abstract class BasePressurePlateBlock extends Block { + +@@ -97,13 +91,15 @@ + boolean flag = i > 0; + boolean flag1 = j > 0; + +- if (i != j) { +- BlockState blockstate1 = this.setSignalForState(blockstate, j); ++ // CraftBukkit start - Interact Pressure Plate ++ org.bukkit.World bworld = level.getWorld(); ++ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager(); + + level.setBlock(blockpos, blockstate1, 2); + this.updateNeighbours(level, blockpos); + level.setBlocksDirty(blockpos, blockstate, blockstate1); + } ++ // CraftBukkit end + + if (!flag1 && flag) { + level.playSound((Player) null, blockpos, this.type.pressurePlateClickOff(), SoundSource.BLOCKS); +@@ -154,10 +157,16 @@ + return true; + } + +- protected static int getEntityCount(Level level, AABB aabb, Class oclass) { +- return level.getEntitiesOfClass(oclass, aabb, EntitySelector.NO_SPECTATORS.and((entity) -> { ++ protected static int getEntityCount(Level level, AABB box, Class entityClass) { ++ // CraftBukkit start ++ return getEntities(level, box, entityClass).size(); ++ } ++ ++ protected static java.util.List getEntities(Level world, AABB axisalignedbb, Class oclass) { ++ // CraftBukkit end ++ return world.getEntitiesOfClass(oclass, axisalignedbb, EntitySelector.NO_SPECTATORS.and((entity) -> { + return !entity.isIgnoringBlockTriggers(); +- })).size(); ++ })); // CraftBukkit + } + + protected abstract int getSignalStrength(Level level, BlockPos pos); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BedBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BedBlock.java.patch new file mode 100644 index 0000000000..ec6b4b8138 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BedBlock.java.patch @@ -0,0 +1,87 @@ +--- a/net/minecraft/world/level/block/BedBlock.java ++++ b/net/minecraft/world/level/block/BedBlock.java +@@ -96,9 +94,10 @@ + } + } + +- if (!canSetSpawn(level)) { +- level.removeBlock(blockpos, false); +- BlockPos blockpos1 = blockpos.relative(((Direction) blockstate.getValue(BedBlock.FACING)).getOpposite()); ++ // CraftBukkit - moved world and biome check into EntityHuman ++ if (false && !canSetSpawn(level)) { ++ level.removeBlock(pos, false); ++ BlockPos blockposition1 = pos.relative(((Direction) state.getValue(BedBlock.FACING)).getOpposite()); + + if (level.getBlockState(blockpos1).is((Block) this)) { + level.removeBlock(blockpos1, false); +@@ -115,9 +114,18 @@ + + return InteractionResult.SUCCESS; + } else { +- player.startSleepInBed(blockpos).ifLeft((player_bedsleepingproblem) -> { +- if (player_bedsleepingproblem.getMessage() != null) { +- player.displayClientMessage(player_bedsleepingproblem.getMessage(), true); ++ // CraftBukkit start ++ IBlockData finaliblockdata = state; ++ BlockPos finalblockposition = pos; ++ // CraftBukkit end ++ player.startSleepInBed(pos).ifLeft((entityhuman_enumbedresult) -> { ++ // CraftBukkit start - handling bed explosion from below here ++ if (!level.dimensionType().bedWorks()) { ++ this.explodeBed(finaliblockdata, level, finalblockposition); ++ } else ++ // CraftBukkit end ++ if (entityhuman_enumbedresult.getMessage() != null) { ++ player.displayClientMessage(entityhuman_enumbedresult.getMessage(), true); + } + + }); +@@ -126,8 +134,29 @@ + } + } + ++ // CraftBukkit start ++ private InteractionResult explodeBed(IBlockData iblockdata, Level world, BlockPos blockposition) { ++ { ++ { ++ world.removeBlock(blockposition, false); ++ BlockPos blockposition1 = blockposition.relative(((Direction) iblockdata.getValue(BedBlock.FACING)).getOpposite()); ++ ++ if (world.getBlockState(blockposition1).getBlock() == this) { ++ world.removeBlock(blockposition1, false); ++ } ++ ++ Vec3 vec3d = blockposition.getCenter(); ++ ++ world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.a.BLOCK); ++ return InteractionResult.SUCCESS; ++ } ++ } ++ } ++ // CraftBukkit end ++ + public static boolean canSetSpawn(Level level) { +- return level.dimensionType().bedWorks(); ++ // CraftBukkit - moved world and biome check into EntityHuman ++ return true || level.dimensionType().bedWorks(); + } + + private boolean kickVillagerOutOfBed(Level level, BlockPos blockpos) { +@@ -335,9 +354,14 @@ + if (!level.isClientSide) { + BlockPos blockpos1 = blockpos.relative((Direction) blockstate.getValue(BedBlock.FACING)); + +- level.setBlock(blockpos1, (BlockState) blockstate.setValue(BedBlock.PART, BedPart.HEAD), 3); +- level.blockUpdated(blockpos, Blocks.AIR); +- blockstate.updateNeighbourShapes(level, blockpos, 3); ++ level.setBlock(blockposition1, (IBlockData) state.setValue(BedBlock.PART, BedPart.HEAD), 3); ++ // CraftBukkit start - SPIGOT-7315: Don't updated if we capture block states ++ if (level.captureBlockStates) { ++ return; ++ } ++ // CraftBukkit end ++ level.blockUpdated(pos, Blocks.AIR); ++ state.updateNeighbourShapes(level, pos, 3); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BeehiveBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BeehiveBlock.java.patch new file mode 100644 index 0000000000..14ce6be3f8 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BeehiveBlock.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/level/block/BeehiveBlock.java ++++ b/net/minecraft/world/level/block/BeehiveBlock.java +@@ -123,7 +119,7 @@ + if (bee.getTarget() == null) { + Player player = (Player) Util.getRandom(list1, level.random); + +- bee.setTarget(player); ++ entitybee.setTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BellBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BellBlock.java.patch new file mode 100644 index 0000000000..c8af995332 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BellBlock.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/block/BellBlock.java ++++ b/net/minecraft/world/level/block/BellBlock.java +@@ -150,6 +146,11 @@ + if (direction == null) { + direction = (Direction) level.getBlockState(blockpos).getValue(BellBlock.FACING); + } ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBellRingEvent(level, pos, direction, entity)) { ++ return false; ++ } ++ // CraftBukkit end + + ((BellBlockEntity) blockentity).onHit(direction); + level.playSound((Player) null, blockpos, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2.0F, 1.0F); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BigDripleafBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BigDripleafBlock.java.patch new file mode 100644 index 0000000000..885aef8a5f --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BigDripleafBlock.java.patch @@ -0,0 +1,115 @@ +--- a/net/minecraft/world/level/block/BigDripleafBlock.java ++++ b/net/minecraft/world/level/block/BigDripleafBlock.java +@@ -41,6 +41,10 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end + + public class BigDripleafBlock extends HorizontalDirectionalBlock implements BonemealableBlock, SimpleWaterloggedBlock { + +@@ -116,9 +119,8 @@ + } + + @Override +- @Override +- public void onProjectileHit(Level level, BlockState blockstate, BlockHitResult blockhitresult, Projectile projectile) { +- this.setTiltAndScheduleTick(blockstate, level, blockhitresult.getBlockPos(), Tilt.FULL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN); ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { ++ this.setTiltAndScheduleTick(state, level, hit.getBlockPos(), Tilt.FULL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN, projectile); // CraftBukkit + } + + @Override +@@ -183,8 +178,21 @@ + @Override + public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { + if (!level.isClientSide) { +- if (blockstate.getValue(BigDripleafBlock.TILT) == Tilt.NONE && canEntityTilt(blockpos, entity) && !level.hasNeighborSignal(blockpos)) { +- this.setTiltAndScheduleTick(blockstate, level, blockpos, Tilt.UNSTABLE, (SoundEvent) null); ++ if (state.getValue(BigDripleafBlock.TILT) == Tilt.NONE && canEntityTilt(pos, entity) && !level.hasNeighborSignal(pos)) { ++ // CraftBukkit start - tilt dripleaf ++ org.bukkit.event.Cancellable cancellable; ++ if (entity instanceof Player) { ++ cancellable = CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ if (cancellable.isCancelled()) { ++ return; ++ } ++ this.setTiltAndScheduleTick(state, level, pos, Tilt.UNSTABLE, (SoundEvent) null, entity); ++ // CraftBukkit end + } + + } +@@ -199,9 +206,9 @@ + Tilt tilt = (Tilt) blockstate.getValue(BigDripleafBlock.TILT); + + if (tilt == Tilt.UNSTABLE) { +- this.setTiltAndScheduleTick(blockstate, serverlevel, blockpos, Tilt.PARTIAL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN); ++ this.setTiltAndScheduleTick(state, level, pos, Tilt.PARTIAL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN, null); // CraftBukkit + } else if (tilt == Tilt.PARTIAL) { +- this.setTiltAndScheduleTick(blockstate, serverlevel, blockpos, Tilt.FULL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN); ++ this.setTiltAndScheduleTick(state, level, pos, Tilt.FULL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN, null); // CraftBukkit + } else if (tilt == Tilt.FULL) { + resetTilt(blockstate, serverlevel, blockpos); + } +@@ -228,10 +234,12 @@ + return entity.onGround() && entity.position().y > (double) ((float) blockpos.getY() + 0.6875F); + } + +- private void setTiltAndScheduleTick(BlockState blockstate, Level level, BlockPos blockpos, Tilt tilt, @Nullable SoundEvent soundevent) { +- setTilt(blockstate, level, blockpos, tilt); +- if (soundevent != null) { +- playTiltSound(level, blockpos, soundevent); ++ // CraftBukkit start ++ private void setTiltAndScheduleTick(IBlockData iblockdata, Level world, BlockPos blockposition, Tilt tilt, @Nullable SoundEvent soundeffect, @Nullable Entity entity) { ++ if (!setTilt(iblockdata, world, blockposition, tilt, entity)) return; ++ // CraftBukkit end ++ if (soundeffect != null) { ++ playTiltSound(world, blockposition, soundeffect); + } + + int i = BigDripleafBlock.DELAY_UNTIL_NEXT_TILT_STATE.getInt(tilt); +@@ -242,22 +250,30 @@ + + } + +- private static void resetTilt(BlockState blockstate, Level level, BlockPos blockpos) { +- setTilt(blockstate, level, blockpos, Tilt.NONE); +- if (blockstate.getValue(BigDripleafBlock.TILT) != Tilt.NONE) { +- playTiltSound(level, blockpos, SoundEvents.BIG_DRIPLEAF_TILT_UP); ++ private static void resetTilt(IBlockData state, Level level, BlockPos pos) { ++ setTilt(state, level, pos, Tilt.NONE, null); // CraftBukkit ++ if (state.getValue(BigDripleafBlock.TILT) != Tilt.NONE) { ++ playTiltSound(level, pos, SoundEvents.BIG_DRIPLEAF_TILT_UP); + } + + } + +- private static void setTilt(BlockState blockstate, Level level, BlockPos blockpos, Tilt tilt) { +- Tilt tilt1 = (Tilt) blockstate.getValue(BigDripleafBlock.TILT); ++ // CraftBukkit start ++ private static boolean setTilt(IBlockData iblockdata, Level world, BlockPos blockposition, Tilt tilt, @Nullable Entity entity) { ++ if (entity != null) { ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, iblockdata.setValue(BigDripleafBlock.TILT, tilt))) { ++ return false; ++ } ++ } ++ // CraftBukkit end ++ Tilt tilt1 = (Tilt) iblockdata.getValue(BigDripleafBlock.TILT); + + level.setBlock(blockpos, (BlockState) blockstate.setValue(BigDripleafBlock.TILT, tilt), 2); + if (tilt.causesVibration() && tilt != tilt1) { + level.gameEvent((Entity) null, GameEvent.BLOCK_CHANGE, blockpos); + } + ++ return true; // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/Block.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/Block.java.patch new file mode 100644 index 0000000000..9f70065941 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/Block.java.patch @@ -0,0 +1,52 @@ +--- a/net/minecraft/world/level/block/Block.java ++++ b/net/minecraft/world/level/block/Block.java +@@ -351,8 +348,14 @@ + if (!level.isClientSide && !itemstack.isEmpty() && level.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { + ItemEntity itementity = (ItemEntity) supplier.get(); + +- itementity.setDefaultPickUpDelay(); +- level.addFreshEntity(itementity); ++ entityitem.setDefaultPickUpDelay(); ++ // CraftBukkit start ++ if (level.captureDrops != null) { ++ level.captureDrops.add(entityitem); ++ } else { ++ level.addFreshEntity(entityitem); ++ } ++ // CraftBukkit end + } + } + +@@ -378,8 +381,8 @@ + + public void playerDestroy(Level level, Player player, BlockPos blockpos, BlockState blockstate, @Nullable BlockEntity blockentity, ItemStack itemstack) { + player.awardStat(Stats.BLOCK_MINED.get(this)); +- player.causeFoodExhaustion(0.005F); +- dropResources(blockstate, level, blockpos, blockentity, player, itemstack); ++ player.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED); // CraftBukkit - EntityExhaustionEvent ++ dropResources(state, level, pos, blockEntity, player, tool); + } + + public void setPlacedBy(Level level, BlockPos blockpos, BlockState blockstate, @Nullable LivingEntity livingentity, ItemStack itemstack) {} +@@ -518,7 +518,8 @@ + return this.builtInRegistryHolder; + } + +- protected void tryDropExperience(ServerLevel serverlevel, BlockPos blockpos, ItemStack itemstack, IntProvider intprovider) { ++ // CraftBukkit start ++ protected int tryDropExperience(ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, IntProvider intprovider) { + if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, itemstack) == 0) { + int i = intprovider.sample(serverlevel.random); + +@@ -529,6 +532,11 @@ + + } + ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { ++ return 0; ++ } ++ // CraftBukkit end ++ + public static final class BlockStatePairKey { + + private final BlockState first; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BuddingAmethystBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BuddingAmethystBlock.java.patch new file mode 100644 index 0000000000..3f4fa951dd --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BuddingAmethystBlock.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/level/block/BuddingAmethystBlock.java ++++ b/net/minecraft/world/level/block/BuddingAmethystBlock.java +@@ -47,7 +45,7 @@ + if (block != null) { + BlockState blockstate2 = (BlockState) ((BlockState) block.defaultBlockState().setValue(AmethystClusterBlock.FACING, direction)).setValue(AmethystClusterBlock.WATERLOGGED, blockstate1.getFluidState().getType() == Fluids.WATER); + +- serverlevel.setBlockAndUpdate(blockpos1, blockstate2); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition1, iblockdata2); // CraftBukkit + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BushBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BushBlock.java.patch new file mode 100644 index 0000000000..eb1a377017 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/BushBlock.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/level/block/BushBlock.java ++++ b/net/minecraft/world/level/block/BushBlock.java +@@ -26,9 +25,15 @@ + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- return !blockstate.canSurvive(levelaccessor, blockpos) ? Blocks.AIR.defaultBlockState() : super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ // CraftBukkit start ++ if (!state.canSurvive(level, currentPos)) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(level, currentPos).isCancelled()) { ++ return Blocks.AIR.defaultBlockState(); ++ } ++ } ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ButtonBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ButtonBlock.java.patch new file mode 100644 index 0000000000..8fe77b2e7d --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ButtonBlock.java.patch @@ -0,0 +1,80 @@ +--- a/net/minecraft/world/level/block/ButtonBlock.java ++++ b/net/minecraft/world/level/block/ButtonBlock.java +@@ -32,6 +32,10 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.event.block.BlockRedstoneEvent; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end + + public class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock { + +@@ -127,9 +128,22 @@ + if ((Boolean) blockstate.getValue(ButtonBlock.POWERED)) { + return InteractionResult.CONSUME; + } else { +- this.press(blockstate, level, blockpos); +- this.playSound(player, level, blockpos, true); +- level.gameEvent((Entity) player, GameEvent.BLOCK_ACTIVATE, blockpos); ++ // CraftBukkit start ++ boolean powered = ((Boolean) state.getValue(POWERED)); ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ int old = (powered) ? 15 : 0; ++ int current = (!powered) ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if ((eventRedstone.getNewCurrent() > 0) != (!powered)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ this.press(state, level, pos); ++ this.playSound(player, level, pos, true); ++ level.gameEvent((Entity) player, GameEvent.BLOCK_ACTIVATE, pos); + return InteractionResult.sidedSuccess(level.isClientSide); + } + } +@@ -209,11 +216,36 @@ + boolean flag = abstractarrow != null; + boolean flag1 = (Boolean) blockstate.getValue(ButtonBlock.POWERED); + ++ // CraftBukkit start - Call interact event when arrows turn on wooden buttons ++ if (flag1 != flag && flag) { ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ EntityInteractEvent event = new EntityInteractEvent(entityarrow.getBukkitEntity(), block); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ + if (flag != flag1) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(ButtonBlock.POWERED, flag), 3); +- this.updateNeighbours(blockstate, level, blockpos); +- this.playSound((Player) null, level, blockpos, flag); +- level.gameEvent((Entity) abstractarrow, flag ? GameEvent.BLOCK_ACTIVATE : GameEvent.BLOCK_DEACTIVATE, blockpos); ++ // CraftBukkit start ++ boolean powered = flag1; ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ int old = (powered) ? 15 : 0; ++ int current = (!powered) ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if ((flag && eventRedstone.getNewCurrent() <= 0) || (!flag && eventRedstone.getNewCurrent() > 0)) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(ButtonBlock.POWERED, flag), 3); ++ this.updateNeighbours(state, level, pos); ++ this.playSound((Player) null, level, pos, flag); ++ level.gameEvent((Entity) entityarrow, flag ? GameEvent.BLOCK_ACTIVATE : GameEvent.BLOCK_DEACTIVATE, pos); + } + + if (flag) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CactusBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CactusBlock.java.patch new file mode 100644 index 0000000000..584e14001b --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CactusBlock.java.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/level/block/CactusBlock.java ++++ b/net/minecraft/world/level/block/CactusBlock.java +@@ -21,6 +21,7 @@ + import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class CactusBlock extends Block { + +@@ -67,8 +65,8 @@ + int j = (Integer) blockstate.getValue(CactusBlock.AGE); + + if (j == 15) { +- serverlevel.setBlockAndUpdate(blockpos1, this.defaultBlockState()); +- BlockState blockstate1 = (BlockState) blockstate.setValue(CactusBlock.AGE, 0); ++ CraftEventFactory.handleBlockGrowEvent(level, blockposition1, this.defaultBlockState()); // CraftBukkit ++ IBlockData iblockdata1 = (IBlockData) state.setValue(CactusBlock.AGE, 0); + + serverlevel.setBlock(blockpos, blockstate1, 4); + serverlevel.neighborChanged(blockstate1, blockpos1, this, blockpos, false); +@@ -125,9 +119,10 @@ + } + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ CraftEventFactory.blockDamage = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); // CraftBukkit + entity.hurt(level.damageSources().cactus(), 1.0F); ++ CraftEventFactory.blockDamage = null; // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CakeBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CakeBlock.java.patch new file mode 100644 index 0000000000..8da72b433f --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CakeBlock.java.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/world/level/block/CakeBlock.java ++++ b/net/minecraft/world/level/block/CakeBlock.java +@@ -95,10 +92,21 @@ + return InteractionResult.PASS; + } else { + player.awardStat(Stats.EAT_CAKE_SLICE); +- player.getFoodData().eat(2, 0.1F); +- int i = (Integer) blockstate.getValue(CakeBlock.BITES); ++ // CraftBukkit start ++ // entityhuman.getFoodData().eat(2, 0.1F); ++ int oldFoodLevel = player.getFoodData().foodLevel; + +- levelaccessor.gameEvent((Entity) player, GameEvent.EAT, blockpos); ++ org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(player, 2 + oldFoodLevel); ++ ++ if (!event.isCancelled()) { ++ player.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, 0.1F); ++ } ++ ++ ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().sendHealthUpdate(); ++ // CraftBukkit end ++ int i = (Integer) state.getValue(CakeBlock.BITES); ++ ++ level.gameEvent((Entity) player, GameEvent.EAT, pos); + if (i < 6) { + levelaccessor.setBlock(blockpos, (BlockState) blockstate.setValue(CakeBlock.BITES, i + 1), 3); + } else { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CampfireBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CampfireBlock.java.patch new file mode 100644 index 0000000000..1fc979024f --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CampfireBlock.java.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/world/level/block/CampfireBlock.java ++++ b/net/minecraft/world/level/block/CampfireBlock.java +@@ -49,6 +49,9 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++// CraftBukkit end + + public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedBlock { + +@@ -106,10 +107,11 @@ + } + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { +- if ((Boolean) blockstate.getValue(CampfireBlock.LIT) && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity) entity)) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ if ((Boolean) state.getValue(CampfireBlock.LIT) && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity) entity)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = CraftBlock.at(level, pos); // CraftBukkit + entity.hurt(level.damageSources().inFire(), (float) this.fireDamage); ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = null; // CraftBukkit + } + + super.entityInside(blockstate, level, blockpos, entity); +@@ -226,8 +220,13 @@ + public void onProjectileHit(Level level, BlockState blockstate, BlockHitResult blockhitresult, Projectile projectile) { + BlockPos blockpos = blockhitresult.getBlockPos(); + +- if (!level.isClientSide && projectile.isOnFire() && projectile.mayInteract(level, blockpos) && !(Boolean) blockstate.getValue(CampfireBlock.LIT) && !(Boolean) blockstate.getValue(CampfireBlock.WATERLOGGED)) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(BlockStateProperties.LIT, true), 11); ++ if (!level.isClientSide && projectile.isOnFire() && projectile.mayInteract(level, blockposition) && !(Boolean) state.getValue(CampfireBlock.LIT) && !(Boolean) state.getValue(CampfireBlock.WATERLOGGED)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, blockposition, projectile).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(blockposition, (IBlockData) state.setValue(BlockStateProperties.LIT, true), 11); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CarvedPumpkinBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CarvedPumpkinBlock.java.patch new file mode 100644 index 0000000000..5da2390b07 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CarvedPumpkinBlock.java.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/level/block/CarvedPumpkinBlock.java ++++ b/net/minecraft/world/level/block/CarvedPumpkinBlock.java +@@ -23,6 +23,9 @@ + import net.minecraft.world.level.block.state.pattern.BlockPatternBuilder; + import net.minecraft.world.level.block.state.predicate.BlockStatePredicate; + import net.minecraft.world.level.block.state.properties.DirectionProperty; ++// CraftBukkit start ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; ++// CraftBukkit end + + public class CarvedPumpkinBlock extends HorizontalDirectionalBlock { + +@@ -87,11 +88,16 @@ + + } + +- private static void spawnGolemInWorld(Level level, BlockPattern.BlockPatternMatch blockpattern_blockpatternmatch, Entity entity, BlockPos blockpos) { +- clearPatternBlocks(level, blockpattern_blockpatternmatch); +- entity.moveTo((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.05D, (double) blockpos.getZ() + 0.5D, 0.0F, 0.0F); +- level.addFreshEntity(entity); +- Iterator iterator = level.getEntitiesOfClass(ServerPlayer.class, entity.getBoundingBox().inflate(5.0D)).iterator(); ++ private static void spawnGolemInWorld(Level level, BlockPattern.BlockPatternMatch patternMatch, Entity golem, BlockPos pos) { ++ // clearPatternBlocks(world, shapedetector_shapedetectorcollection); // CraftBukkit - moved down ++ golem.moveTo((double) pos.getX() + 0.5D, (double) pos.getY() + 0.05D, (double) pos.getZ() + 0.5D, 0.0F, 0.0F); ++ // CraftBukkit start ++ if (!level.addFreshEntity(golem, SpawnReason.BUILD_IRONGOLEM)) { ++ return; ++ } ++ clearPatternBlocks(level, patternMatch); // CraftBukkit - from above ++ // CraftBukkit end ++ Iterator iterator = level.getEntitiesOfClass(ServerPlayer.class, golem.getBoundingBox().inflate(5.0D)).iterator(); + + while (iterator.hasNext()) { + ServerPlayer serverplayer = (ServerPlayer) iterator.next(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CauldronBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CauldronBlock.java.patch new file mode 100644 index 0000000000..a8eb7d75f0 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CauldronBlock.java.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/level/block/CauldronBlock.java ++++ b/net/minecraft/world/level/block/CauldronBlock.java +@@ -11,6 +11,9 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; ++// CraftBukkit start ++import org.bukkit.event.block.CauldronLevelChangeEvent; ++// CraftBukkit end + + public class CauldronBlock extends AbstractCauldronBlock { + +@@ -65,15 +63,13 @@ + BlockState blockstate1; + + if (fluid == Fluids.WATER) { +- blockstate1 = Blocks.WATER_CAULDRON.defaultBlockState(); +- level.setBlockAndUpdate(blockpos, blockstate1); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(blockstate1)); +- level.levelEvent(1047, blockpos, 0); ++ iblockdata1 = Blocks.WATER_CAULDRON.defaultBlockState(); ++ LayeredCauldronBlock.changeLevel(state, level, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL); // CraftBukkit ++ level.levelEvent(1047, pos, 0); + } else if (fluid == Fluids.LAVA) { +- blockstate1 = Blocks.LAVA_CAULDRON.defaultBlockState(); +- level.setBlockAndUpdate(blockpos, blockstate1); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(blockstate1)); +- level.levelEvent(1046, blockpos, 0); ++ iblockdata1 = Blocks.LAVA_CAULDRON.defaultBlockState(); ++ LayeredCauldronBlock.changeLevel(state, level, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL); // CraftBukkit ++ level.levelEvent(1046, pos, 0); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CaveVines.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CaveVines.java.patch new file mode 100644 index 0000000000..8557f597ed --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CaveVines.java.patch @@ -0,0 +1,44 @@ +--- a/net/minecraft/world/level/block/CaveVines.java ++++ b/net/minecraft/world/level/block/CaveVines.java +@@ -18,14 +18,38 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.VoxelShape; + ++// CraftBukkit start ++import java.util.Collections; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerHarvestBlockEvent; ++// CraftBukkit end ++ + public interface CaveVines { + + VoxelShape SHAPE = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 16.0D, 15.0D); + BooleanProperty BERRIES = BlockStateProperties.BERRIES; + +- static InteractionResult use(@Nullable Entity entity, BlockState blockstate, Level level, BlockPos blockpos) { +- if ((Boolean) blockstate.getValue(CaveVines.BERRIES)) { +- Block.popResource(level, blockpos, new ItemStack(Items.GLOW_BERRIES, 1)); ++ static InteractionResult use(@Nullable Entity entity, IBlockData state, Level level, BlockPos pos) { ++ if ((Boolean) state.getValue(CaveVines.BERRIES)) { ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, (IBlockData) state.setValue(CaveVines.BERRIES, false))) { ++ return InteractionResult.SUCCESS; ++ } ++ ++ if (entity instanceof Player) { ++ PlayerHarvestBlockEvent event = CraftEventFactory.callPlayerHarvestBlockEvent(level, pos, (Player) entity, net.minecraft.world.EnumHand.MAIN_HAND, Collections.singletonList(new ItemStack(Items.GLOW_BERRIES, 1))); ++ if (event.isCancelled()) { ++ return InteractionResult.SUCCESS; // We need to return a success either way, because making it PASS or FAIL will result in a bug where cancelling while harvesting w/ block in hand places block ++ } ++ for (org.bukkit.inventory.ItemStack itemStack : event.getItemsHarvested()) { ++ Block.popResource(level, pos, CraftItemStack.asNMSCopy(itemStack)); ++ } ++ } else { ++ Block.popResource(level, pos, new ItemStack(Items.GLOW_BERRIES, 1)); ++ } ++ // CraftBukkit end ++ + float f = Mth.randomBetween(level.random, 0.8F, 1.2F); + + level.playSound((Player) null, blockpos, SoundEvents.CAVE_VINES_PICK_BERRIES, SoundSource.BLOCKS, 1.0F, f); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CeilingHangingSignBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CeilingHangingSignBlock.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CeilingHangingSignBlock.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ChangeOverTimeBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ChangeOverTimeBlock.java.patch new file mode 100644 index 0000000000..bfb8e06f44 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ChangeOverTimeBlock.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/level/block/ChangeOverTimeBlock.java ++++ b/net/minecraft/world/level/block/ChangeOverTimeBlock.java +@@ -19,8 +19,8 @@ + float f = 0.05688889F; + + if (randomsource.nextFloat() < 0.05688889F) { +- this.getNextState(blockstate, serverlevel, blockpos, randomsource).ifPresent((blockstate1) -> { +- serverlevel.setBlockAndUpdate(blockpos, blockstate1); ++ this.getNextState(iblockdata, worldserver, blockposition, randomsource).ifPresent((iblockdata1) -> { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(worldserver, blockposition, iblockdata1); // CraftBukkit + }); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ChestBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ChestBlock.java.patch new file mode 100644 index 0000000000..7682147213 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ChestBlock.java.patch @@ -0,0 +1,71 @@ +--- a/net/minecraft/world/level/block/ChestBlock.java ++++ b/net/minecraft/world/level/block/ChestBlock.java +@@ -92,24 +89,23 @@ + return Optional.empty(); + } + }; +- private static final DoubleBlockCombiner.Combiner> MENU_PROVIDER_COMBINER = new DoubleBlockCombiner.Combiner>() { ++ private static final DoubleBlockCombiner.Combiner> MENU_PROVIDER_COMBINER = new DoubleBlockCombiner.Combiner>() { ++ public Optional acceptDouble(final ChestBlockEntity tileentitychest, final ChestBlockEntity tileentitychest1) { ++ final CompoundContainer inventorylargechest = new CompoundContainer(tileentitychest, tileentitychest1); ++ ++ return Optional.of(new DoubleInventory(tileentitychest, tileentitychest1, inventorylargechest)); // CraftBukkit ++ } ++ ++ public Optional acceptSingle(ChestBlockEntity tileentitychest) { ++ return Optional.of(tileentitychest); ++ } ++ + @Override + public Optional acceptDouble(final ChestBlockEntity chestblockentity, final ChestBlockEntity chestblockentity1) { + final CompoundContainer compoundcontainer = new CompoundContainer(chestblockentity, chestblockentity1); + +- return Optional.of(new MenuProvider() { +- @Nullable +- @Override +- @Override +- public AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) { +- if (chestblockentity.canOpen(player) && chestblockentity1.canOpen(player)) { +- chestblockentity.unpackLootTable(inventory.player); +- chestblockentity1.unpackLootTable(inventory.player); +- return ChestMenu.sixRows(i, inventory, compoundcontainer); +- } else { +- return null; +- } +- } ++ // CraftBukkit start ++ public static class DoubleInventory implements ITileInventory { + + @Override + @Override +@@ -130,6 +136,7 @@ + return Optional.empty(); + } + }; ++ // CraftBukkit end + + @Override + @Override +@@ -311,12 +308,18 @@ + + @Nullable + @Override +- @Override +- public MenuProvider getMenuProvider(BlockState blockstate, Level level, BlockPos blockpos) { +- return (MenuProvider) ((Optional) this.combine(blockstate, level, blockpos, false).apply(ChestBlock.MENU_PROVIDER_COMBINER)).orElse((Object) null); ++ public ITileInventory getMenuProvider(IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ return getMenuProvider(state, level, pos, false); + } + +- public static DoubleBlockCombiner.Combiner opennessCombiner(final LidBlockEntity lidblockentity) { ++ @Nullable ++ public ITileInventory getMenuProvider(IBlockData iblockdata, Level world, BlockPos blockposition, boolean ignoreObstructions) { ++ return (ITileInventory) ((Optional) this.combine(iblockdata, world, blockposition, ignoreObstructions).apply(ChestBlock.MENU_PROVIDER_COMBINER)).orElse((Object) null); ++ // CraftBukkit end ++ } ++ ++ public static DoubleBlockCombiner.Combiner opennessCombiner(final LidBlockEntity lid) { + return new DoubleBlockCombiner.Combiner() { + @Override + public Float2FloatFunction acceptDouble(ChestBlockEntity chestblockentity, ChestBlockEntity chestblockentity1) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ChorusFlowerBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ChorusFlowerBlock.java.patch new file mode 100644 index 0000000000..7b2eb2ebfa --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ChorusFlowerBlock.java.patch @@ -0,0 +1,81 @@ +--- a/net/minecraft/world/level/block/ChorusFlowerBlock.java ++++ b/net/minecraft/world/level/block/ChorusFlowerBlock.java +@@ -22,6 +22,8 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.VoxelShape; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public class ChorusFlowerBlock extends Block { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +@@ -106,9 +103,13 @@ + flag = true; + } + +- if (flag && allNeighborsEmpty(serverlevel, blockpos1, (Direction) null) && serverlevel.isEmptyBlock(blockpos.above(2))) { +- serverlevel.setBlock(blockpos, ChorusPlantBlock.getStateWithConnections(serverlevel, blockpos, this.plant.defaultBlockState()), 2); +- this.placeGrownFlower(serverlevel, blockpos1, i); ++ if (flag && allNeighborsEmpty(level, blockposition1, (Direction) null) && level.isEmptyBlock(pos.above(2))) { ++ // CraftBukkit start - add event ++ if (CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition1, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(i)), 2)) { ++ level.setBlock(pos, ChorusPlantBlock.getStateWithConnections(level, pos, this.plant.defaultBlockState()), 2); ++ this.placeGrownFlower(level, blockposition1, i); ++ } ++ // CraftBukkit end + } else if (i < 4) { + j = randomsource.nextInt(4); + if (flag1) { +@@ -121,19 +122,31 @@ + Direction direction = Direction.Plane.HORIZONTAL.getRandomDirection(randomsource); + BlockPos blockpos2 = blockpos.relative(direction); + +- if (serverlevel.isEmptyBlock(blockpos2) && serverlevel.isEmptyBlock(blockpos2.below()) && allNeighborsEmpty(serverlevel, blockpos2, direction.getOpposite())) { +- this.placeGrownFlower(serverlevel, blockpos2, i + 1); +- flag2 = true; ++ if (level.isEmptyBlock(blockposition2) && level.isEmptyBlock(blockposition2.below()) && allNeighborsEmpty(level, blockposition2, enumdirection.getOpposite())) { ++ // CraftBukkit start - add event ++ if (CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition2, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(i + 1)), 2)) { ++ this.placeGrownFlower(level, blockposition2, i + 1); ++ flag2 = true; ++ } ++ // CraftBukkit end + } + } + + if (flag2) { + serverlevel.setBlock(blockpos, ChorusPlantBlock.getStateWithConnections(serverlevel, blockpos, this.plant.defaultBlockState()), 2); + } else { +- this.placeDeadFlower(serverlevel, blockpos); ++ // CraftBukkit start - add event ++ if (CraftEventFactory.handleBlockGrowEvent(level, pos, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(5)), 2)) { ++ this.placeDeadFlower(level, pos); ++ } ++ // CraftBukkit end + } + } else { +- this.placeDeadFlower(serverlevel, blockpos); ++ // CraftBukkit start - add event ++ if (CraftEventFactory.handleBlockGrowEvent(level, pos, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(5)), 2)) { ++ this.placeDeadFlower(level, pos); ++ } ++ // CraftBukkit end + } + + } +@@ -273,8 +282,13 @@ + public void onProjectileHit(Level level, BlockState blockstate, BlockHitResult blockhitresult, Projectile projectile) { + BlockPos blockpos = blockhitresult.getBlockPos(); + +- if (!level.isClientSide && projectile.mayInteract(level, blockpos) && projectile.mayBreak(level)) { +- level.destroyBlock(blockpos, true, projectile); ++ if (!level.isClientSide && projectile.mayInteract(level, blockposition) && projectile.mayBreak(level)) { ++ // CraftBukkit ++ if (!CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, Blocks.AIR.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end ++ level.destroyBlock(blockposition, true, projectile); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CocoaBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CocoaBlock.java.patch new file mode 100644 index 0000000000..bb5d756304 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CocoaBlock.java.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/level/block/CocoaBlock.java ++++ b/net/minecraft/world/level/block/CocoaBlock.java +@@ -20,6 +20,7 @@ + import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class CocoaBlock extends HorizontalDirectionalBlock implements BonemealableBlock { + +@@ -139,9 +131,8 @@ + } + + @Override +- @Override +- public void performBonemeal(ServerLevel serverlevel, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(CocoaBlock.AGE, (Integer) blockstate.getValue(CocoaBlock.AGE) + 1), 2); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ CraftEventFactory.handleBlockGrowEvent(level, pos, (IBlockData) state.setValue(CocoaBlock.AGE, (Integer) state.getValue(CocoaBlock.AGE) + 1), 2); // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CommandBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CommandBlock.java.patch new file mode 100644 index 0000000000..93f0237c6f --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CommandBlock.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/level/block/CommandBlock.java ++++ b/net/minecraft/world/level/block/CommandBlock.java +@@ -30,6 +30,8 @@ + import net.minecraft.world.phys.BlockHitResult; + import org.slf4j.Logger; + ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit ++ + public class CommandBlock extends BaseEntityBlock implements GameMasterBlock { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +@@ -69,13 +68,22 @@ + if (!level.isClientSide) { + BlockEntity blockentity = level.getBlockEntity(blockpos); + +- if (blockentity instanceof CommandBlockEntity) { +- CommandBlockEntity commandblockentity = (CommandBlockEntity) blockentity; +- boolean flag1 = level.hasNeighborSignal(blockpos); +- boolean flag2 = commandblockentity.isPowered(); ++ if (tileentity instanceof CommandBlockEntity) { ++ CommandBlockEntity tileentitycommand = (CommandBlockEntity) tileentity; ++ boolean flag1 = level.hasNeighborSignal(pos); ++ boolean flag2 = tileentitycommand.isPowered(); ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ int old = flag2 ? 15 : 0; ++ int current = flag1 ? 15 : 0; + +- commandblockentity.setPowered(flag1); +- if (!flag2 && !commandblockentity.isAutomatic() && commandblockentity.getMode() != CommandBlockEntity.Mode.SEQUENCE) { ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bukkitBlock, old, current); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ flag1 = eventRedstone.getNewCurrent() > 0; ++ // CraftBukkit end ++ ++ tileentitycommand.setPowered(flag1); ++ if (!flag2 && !tileentitycommand.isAutomatic() && tileentitycommand.getMode() != CommandBlockEntity.Type.SEQUENCE) { + if (flag1) { + commandblockentity.markConditionMet(); + level.scheduleTick(blockpos, (Block) this, 1); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ComparatorBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ComparatorBlock.java.patch new file mode 100644 index 0000000000..9be8474075 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ComparatorBlock.java.patch @@ -0,0 +1,32 @@ +--- a/net/minecraft/world/level/block/ComparatorBlock.java ++++ b/net/minecraft/world/level/block/ComparatorBlock.java +@@ -27,6 +27,7 @@ + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.ticks.TickPriority; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class ComparatorBlock extends DiodeBlock implements EntityBlock { + +@@ -173,9 +167,19 @@ + boolean flag1 = (Boolean) blockstate.getValue(ComparatorBlock.POWERED); + + if (flag1 && !flag) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(ComparatorBlock.POWERED, false), 2); ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 15, 0).getNewCurrent() != 0) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(ComparatorBlock.POWERED, false), 2); + } else if (!flag1 && flag) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(ComparatorBlock.POWERED, true), 2); ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 0, 15).getNewCurrent() != 15) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(ComparatorBlock.POWERED, true), 2); + } + + this.updateNeighborsInFront(level, blockpos, blockstate); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ComposterBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ComposterBlock.java.patch new file mode 100644 index 0000000000..5b5ee06ef8 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ComposterBlock.java.patch @@ -0,0 +1,134 @@ +--- a/net/minecraft/world/level/block/ComposterBlock.java ++++ b/net/minecraft/world/level/block/ComposterBlock.java +@@ -40,6 +40,10 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftBlockInventoryHolder; ++import org.bukkit.craftbukkit.util.DummyGeneratorAccess; ++// CraftBukkit end + + public class ComposterBlock extends Block implements WorldlyContainerHolder { + +@@ -260,8 +258,15 @@ + public static BlockState insertItem(Entity entity, BlockState blockstate, ServerLevel serverlevel, ItemStack itemstack, BlockPos blockpos) { + int i = (Integer) blockstate.getValue(ComposterBlock.LEVEL); + +- if (i < 7 && ComposterBlock.COMPOSTABLES.containsKey(itemstack.getItem())) { +- BlockState blockstate1 = addItem(entity, blockstate, serverlevel, blockpos, itemstack); ++ if (i < 7 && ComposterBlock.COMPOSTABLES.containsKey(stack.getItem())) { ++ // CraftBukkit start ++ double rand = level.getRandom().nextDouble(); ++ IBlockData iblockdata1 = addItem(entity, state, DummyGeneratorAccess.INSTANCE, pos, stack, rand); ++ if (state == iblockdata1 || !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, iblockdata1)) { ++ return state; ++ } ++ iblockdata1 = addItem(entity, state, level, pos, stack, rand); ++ // CraftBukkit end + + itemstack.shrink(1); + return blockstate1; +@@ -270,7 +275,15 @@ + } + } + +- public static BlockState extractProduce(Entity entity, BlockState blockstate, Level level, BlockPos blockpos) { ++ public static IBlockData extractProduce(Entity entity, IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ if (entity != null && !(entity instanceof Player)) { ++ IBlockData iblockdata1 = empty(entity, state, DummyGeneratorAccess.INSTANCE, pos); ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, iblockdata1)) { ++ return state; ++ } ++ } ++ // CraftBukkit end + if (!level.isClientSide) { + Vec3 vec3 = Vec3.atLowerCornerWithOffset(blockpos, 0.5D, 1.01D, 0.5D).offsetRandom(level.random, 0.7F); + ItemEntity itementity = new ItemEntity(level, vec3.x(), vec3.y(), vec3.z(), new ItemStack(Items.BONE_MEAL)); +@@ -293,8 +306,14 @@ + return blockstate1; + } + +- static BlockState addItem(@Nullable Entity entity, BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos, ItemStack itemstack) { +- int i = (Integer) blockstate.getValue(ComposterBlock.LEVEL); ++ static IBlockData addItem(@Nullable Entity entity, IBlockData state, LevelAccessor level, BlockPos pos, ItemStack stack) { ++ // CraftBukkit start ++ return addItem(entity, state, level, pos, stack, level.getRandom().nextDouble()); ++ } ++ ++ static IBlockData addItem(@Nullable Entity entity, IBlockData iblockdata, LevelAccessor generatoraccess, BlockPos blockposition, ItemStack itemstack, double rand) { ++ // CraftBukkit end ++ int i = (Integer) iblockdata.getValue(ComposterBlock.LEVEL); + float f = ComposterBlock.COMPOSTABLES.getFloat(itemstack.getItem()); + + if ((i != 0 || f <= 0.0F) && levelaccessor.getRandom().nextDouble() >= (double) f) { +@@ -352,7 +365,8 @@ + public WorldlyContainer getContainer(BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos) { + int i = (Integer) blockstate.getValue(ComposterBlock.LEVEL); + +- return (WorldlyContainer) (i == 8 ? new ComposterBlock.OutputContainer(blockstate, levelaccessor, blockpos, new ItemStack(Items.BONE_MEAL)) : (i < 7 ? new ComposterBlock.InputContainer(blockstate, levelaccessor, blockpos) : new ComposterBlock.EmptyContainer())); ++ // CraftBukkit - empty generatoraccess, blockposition ++ return (WorldlyContainer) (i == 8 ? new ComposterBlock.OutputContainer(state, level, pos, new ItemStack(Items.BONE_MEAL)) : (i < 7 ? new ComposterBlock.InputContainer(state, level, pos) : new ComposterBlock.EmptyContainer(level, pos))); + } + + private static class OutputContainer extends SimpleContainer implements WorldlyContainer { +@@ -362,11 +376,12 @@ + private final BlockPos pos; + private boolean changed; + +- public OutputContainer(BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos, ItemStack itemstack) { +- super(itemstack); +- this.state = blockstate; +- this.level = levelaccessor; +- this.pos = blockpos; ++ public OutputContainer(IBlockData state, LevelAccessor level, BlockPos pos, ItemStack stack) { ++ super(stack); ++ this.state = state; ++ this.level = level; ++ this.pos = pos; ++ this.bukkitOwner = new CraftBlockInventoryHolder(level, pos, this); // CraftBukkit + } + + @Override +@@ -396,8 +406,15 @@ + @Override + @Override + public void setChanged() { ++ // CraftBukkit start - allow putting items back (eg cancelled InventoryMoveItemEvent) ++ if (this.isEmpty()) { + ComposterBlock.empty((Entity) null, this.state, this.level, this.pos); + this.changed = true; ++ } else { ++ this.level.setBlock(this.pos, this.state, 3); ++ this.changed = false; ++ } ++ // CraftBukkit end + } + } + +@@ -410,9 +427,10 @@ + + public InputContainer(BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos) { + super(1); +- this.state = blockstate; +- this.level = levelaccessor; +- this.pos = blockpos; ++ this.bukkitOwner = new CraftBlockInventoryHolder(level, pos, this); // CraftBukkit ++ this.state = state; ++ this.level = level; ++ this.pos = pos; + } + + @Override +@@ -457,8 +470,9 @@ + + private static class EmptyContainer extends SimpleContainer implements WorldlyContainer { + +- public EmptyContainer() { ++ public EmptyContainer(LevelAccessor generatoraccess, BlockPos blockposition) { // CraftBukkit + super(0); ++ this.bukkitOwner = new CraftBlockInventoryHolder(generatoraccess, blockposition, this); // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ConcretePowderBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ConcretePowderBlock.java.patch new file mode 100644 index 0000000000..755f032236 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ConcretePowderBlock.java.patch @@ -0,0 +1,85 @@ +--- a/net/minecraft/world/level/block/ConcretePowderBlock.java ++++ b/net/minecraft/world/level/block/ConcretePowderBlock.java +@@ -14,6 +14,12 @@ + import net.minecraft.world.level.block.state.BlockBehaviour; + import net.minecraft.world.level.block.state.BlockState; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.block.CraftBlockStates; ++import org.bukkit.event.block.BlockFormEvent; ++// CraftBukkit end ++ + public class ConcretePowderBlock extends FallingBlock { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +@@ -35,10 +40,9 @@ + } + + @Override +- @Override +- public void onLand(Level level, BlockPos blockpos, BlockState blockstate, BlockState blockstate1, FallingBlockEntity fallingblockentity) { +- if (shouldSolidify(level, blockpos, blockstate1)) { +- level.setBlock(blockpos, this.concrete.defaultBlockState(), 3); ++ public void onLand(Level level, BlockPos pos, IBlockData state, IBlockData replaceableState, FallingBlockEntity fallingBlock) { ++ if (shouldSolidify(level, pos, replaceableState)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, this.concrete.defaultBlockState(), 3); // CraftBukkit + } + + } +@@ -50,7 +53,24 @@ + BlockPos blockpos = blockplacecontext.getClickedPos(); + BlockState blockstate = level.getBlockState(blockpos); + +- return shouldSolidify(level, blockpos, blockstate) ? this.concrete.defaultBlockState() : super.getStateForPlacement(blockplacecontext); ++ // CraftBukkit start ++ if (!shouldSolidify(world, blockposition, iblockdata)) { ++ return super.getStateForPlacement(context); ++ } ++ ++ // TODO: An event factory call for methods like this ++ CraftBlockState blockState = CraftBlockStates.getBlockState(world, blockposition); ++ blockState.setData(this.concrete.defaultBlockState()); ++ ++ BlockFormEvent event = new BlockFormEvent(blockState.getBlock(), blockState); ++ world.getServer().server.getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ return blockState.getHandle(); ++ } ++ ++ return super.getStateForPlacement(context); ++ // CraftBukkit end + } + + private static boolean shouldSolidify(BlockGetter blockgetter, BlockPos blockpos, BlockState blockstate) { +@@ -85,9 +105,26 @@ + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- return touchesLiquid(levelaccessor, blockpos) ? this.concrete.defaultBlockState() : super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ // CraftBukkit start ++ if (touchesLiquid(level, currentPos)) { ++ // Suppress during worldgen ++ if (!(level instanceof Level)) { ++ return this.concrete.defaultBlockState(); ++ } ++ CraftBlockState blockState = CraftBlockStates.getBlockState(level, currentPos); ++ blockState.setData(this.concrete.defaultBlockState()); ++ ++ BlockFormEvent event = new BlockFormEvent(blockState.getBlock(), blockState); ++ ((Level) level).getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ return blockState.getHandle(); ++ } ++ } ++ ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CoralBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CoralBlock.java.patch new file mode 100644 index 0000000000..fcfdef93a4 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CoralBlock.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/level/block/CoralBlock.java ++++ b/net/minecraft/world/level/block/CoralBlock.java +@@ -38,10 +37,14 @@ + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (!this.scanForWater(serverlevel, blockpos)) { +- serverlevel.setBlock(blockpos, this.deadBlock.defaultBlockState(), 2); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (!this.scanForWater(level, pos)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, this.deadBlock.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, this.deadBlock.defaultBlockState(), 2); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CoralFanBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CoralFanBlock.java.patch new file mode 100644 index 0000000000..bf2ed0b28c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CoralFanBlock.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/level/block/CoralFanBlock.java ++++ b/net/minecraft/world/level/block/CoralFanBlock.java +@@ -40,10 +38,14 @@ + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (!scanForWater(blockstate, serverlevel, blockpos)) { +- serverlevel.setBlock(blockpos, (BlockState) this.deadBlock.defaultBlockState().setValue(CoralFanBlock.WATERLOGGED, false), 2); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (!scanForWater(state, level, pos)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, this.deadBlock.defaultBlockState().setValue(CoralFanBlock.WATERLOGGED, false)).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) this.deadBlock.defaultBlockState().setValue(CoralFanBlock.WATERLOGGED, false), 2); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CoralPlantBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CoralPlantBlock.java.patch new file mode 100644 index 0000000000..f686b4752c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CoralPlantBlock.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/level/block/CoralPlantBlock.java ++++ b/net/minecraft/world/level/block/CoralPlantBlock.java +@@ -45,10 +43,14 @@ + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (!scanForWater(blockstate, serverlevel, blockpos)) { +- serverlevel.setBlock(blockpos, (BlockState) this.deadBlock.defaultBlockState().setValue(CoralPlantBlock.WATERLOGGED, false), 2); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (!scanForWater(state, level, pos)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, this.deadBlock.defaultBlockState().setValue(CoralPlantBlock.WATERLOGGED, false)).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) this.deadBlock.defaultBlockState().setValue(CoralPlantBlock.WATERLOGGED, false), 2); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CoralWallFanBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CoralWallFanBlock.java.patch new file mode 100644 index 0000000000..f422c2075e --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CoralWallFanBlock.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/level/block/CoralWallFanBlock.java ++++ b/net/minecraft/world/level/block/CoralWallFanBlock.java +@@ -40,10 +38,14 @@ + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (!scanForWater(blockstate, serverlevel, blockpos)) { +- serverlevel.setBlock(blockpos, (BlockState) ((BlockState) this.deadBlock.defaultBlockState().setValue(CoralWallFanBlock.WATERLOGGED, false)).setValue(CoralWallFanBlock.FACING, (Direction) blockstate.getValue(CoralWallFanBlock.FACING)), 2); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (!scanForWater(state, level, pos)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, this.deadBlock.defaultBlockState().setValue(CoralWallFanBlock.WATERLOGGED, false).setValue(CoralWallFanBlock.FACING, state.getValue(CoralWallFanBlock.FACING))).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) ((IBlockData) this.deadBlock.defaultBlockState().setValue(CoralWallFanBlock.WATERLOGGED, false)).setValue(CoralWallFanBlock.FACING, (Direction) state.getValue(CoralWallFanBlock.FACING)), 2); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CropBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CropBlock.java.patch new file mode 100644 index 0000000000..3514aeeca0 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/CropBlock.java.patch @@ -0,0 +1,44 @@ +--- a/net/minecraft/world/level/block/CropBlock.java ++++ b/net/minecraft/world/level/block/CropBlock.java +@@ -21,6 +21,7 @@ + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class CropBlock extends BushBlock implements BonemealableBlock { + +@@ -87,8 +83,8 @@ + if (i < this.getMaxAge()) { + float f = getGrowthSpeed(this, serverlevel, blockpos); + +- if (randomsource.nextInt((int) (25.0F / f) + 1) == 0) { +- serverlevel.setBlock(blockpos, this.getStateForAge(i + 1), 2); ++ if (random.nextInt((int) (25.0F / f) + 1) == 0) { ++ CraftEventFactory.handleBlockGrowEvent(level, pos, this.getStateForAge(i + 1), 2); // CraftBukkit + } + } + } +@@ -103,7 +99,7 @@ + i = j; + } + +- level.setBlock(blockpos, this.getStateForAge(i), 2); ++ CraftEventFactory.handleBlockGrowEvent(level, pos, this.getStateForAge(i), 2); // CraftBukkit + } + + protected int getBonemealAgeIncrease(Level level) { +@@ -165,10 +160,9 @@ + } + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { +- if (entity instanceof Ravager && level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- level.destroyBlock(blockpos, true, entity); ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ if (entity instanceof Ravager && CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit ++ level.destroyBlock(pos, true, entity); + } + + super.entityInside(blockstate, level, blockpos, entity); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DaylightDetectorBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DaylightDetectorBlock.java.patch new file mode 100644 index 0000000000..8e990550cb --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DaylightDetectorBlock.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/block/DaylightDetectorBlock.java ++++ b/net/minecraft/world/level/block/DaylightDetectorBlock.java +@@ -77,8 +73,9 @@ + } + + i = Mth.clamp(i, 0, 15); +- if ((Integer) blockstate.getValue(DaylightDetectorBlock.POWER) != i) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(DaylightDetectorBlock.POWER, i), 3); ++ if ((Integer) state.getValue(DaylightDetectorBlock.POWER) != i) { ++ i = org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(level, pos, ((Integer) state.getValue(POWER)), i).getNewCurrent(); // CraftBukkit - Call BlockRedstoneEvent ++ level.setBlock(pos, (IBlockData) state.setValue(DaylightDetectorBlock.POWER, i), 3); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DetectorRailBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DetectorRailBlock.java.patch new file mode 100644 index 0000000000..f28eaa5935 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DetectorRailBlock.java.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/level/block/DetectorRailBlock.java ++++ b/net/minecraft/world/level/block/DetectorRailBlock.java +@@ -25,6 +25,7 @@ + import net.minecraft.world.level.block.state.properties.Property; + import net.minecraft.world.level.block.state.properties.RailShape; + import net.minecraft.world.phys.AABB; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class DetectorRailBlock extends BaseRailBlock { + +@@ -92,8 +87,18 @@ + flag1 = true; + } + +- BlockState blockstate1; ++ IBlockData iblockdata1; ++ // CraftBukkit start ++ if (flag != flag1) { ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); + ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, flag ? 15 : 0, flag1 ? 15 : 0); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ flag1 = eventRedstone.getNewCurrent() > 0; ++ } ++ // CraftBukkit end ++ + if (flag1 && !flag) { + blockstate1 = (BlockState) blockstate.setValue(DetectorRailBlock.POWERED, true); + level.setBlock(blockpos, blockstate1, 3); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DiodeBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DiodeBlock.java.patch new file mode 100644 index 0000000000..6a6f9087df --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DiodeBlock.java.patch @@ -0,0 +1,32 @@ +--- a/net/minecraft/world/level/block/DiodeBlock.java ++++ b/net/minecraft/world/level/block/DiodeBlock.java +@@ -20,6 +20,7 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.ticks.TickPriority; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public abstract class DiodeBlock extends HorizontalDirectionalBlock { + +@@ -60,9 +57,19 @@ + boolean flag1 = this.shouldTurnOn(serverlevel, blockpos, blockstate); + + if (flag && !flag1) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(DiodeBlock.POWERED, false), 2); ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 15, 0).getNewCurrent() != 0) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(DiodeBlock.POWERED, false), 2); + } else if (!flag) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(DiodeBlock.POWERED, true), 2); ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 0, 15).getNewCurrent() != 15) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(DiodeBlock.POWERED, true), 2); + if (!flag1) { + serverlevel.scheduleTick(blockpos, (Block) this, this.getDelay(blockstate), TickPriority.VERY_HIGH); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DispenserBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DispenserBlock.java.patch new file mode 100644 index 0000000000..1386fa28c8 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DispenserBlock.java.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/level/block/DispenserBlock.java ++++ b/net/minecraft/world/level/block/DispenserBlock.java +@@ -49,6 +49,7 @@ + object2objectopenhashmap.defaultReturnValue(new DefaultDispenseItemBehavior()); + }); + private static final int TRIGGER_DURATION = 4; ++ public static boolean eventFired = false; // CraftBukkit + + @Override + @Override +@@ -102,8 +101,9 @@ + ItemStack itemstack = dispenserblockentity.getItem(i); + DispenseItemBehavior dispenseitembehavior = this.getDispenseMethod(itemstack); + +- if (dispenseitembehavior != DispenseItemBehavior.NOOP) { +- dispenserblockentity.setItem(i, dispenseitembehavior.dispense(blocksource, itemstack)); ++ if (idispensebehavior != DispenseItemBehavior.NOOP) { ++ eventFired = false; // CraftBukkit - reset event status ++ tileentitydispenser.setItem(i, idispensebehavior.dispense(sourceblock, itemstack)); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DoorBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DoorBlock.java.patch new file mode 100644 index 0000000000..642d1c57c5 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DoorBlock.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/world/level/block/DoorBlock.java ++++ b/net/minecraft/world/level/block/DoorBlock.java +@@ -36,6 +36,7 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class DoorBlock extends Block { + +@@ -228,14 +220,28 @@ + } + + @Override +- @Override +- public void neighborChanged(BlockState blockstate, Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { +- boolean flag1 = level.hasNeighborSignal(blockpos) || level.hasNeighborSignal(blockpos.relative(blockstate.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER ? Direction.UP : Direction.DOWN)); ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ // CraftBukkit start ++ BlockPos otherHalf = pos.relative(state.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER ? Direction.UP : Direction.DOWN); + +- if (!this.defaultBlockState().is(block) && flag1 != (Boolean) blockstate.getValue(DoorBlock.POWERED)) { +- if (flag1 != (Boolean) blockstate.getValue(DoorBlock.OPEN)) { +- this.playSound((Entity) null, level, blockpos, flag1); +- level.gameEvent((Entity) null, flag1 ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, blockpos); ++ org.bukkit.World bworld = level.getWorld(); ++ org.bukkit.block.Block bukkitBlock = bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ org.bukkit.block.Block blockTop = bworld.getBlockAt(otherHalf.getX(), otherHalf.getY(), otherHalf.getZ()); ++ ++ int power = bukkitBlock.getBlockPower(); ++ int powerTop = blockTop.getBlockPower(); ++ if (powerTop > power) power = powerTop; ++ int oldPower = (Boolean) state.getValue(DoorBlock.POWERED) ? 15 : 0; ++ ++ if (oldPower == 0 ^ power == 0) { ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bukkitBlock, oldPower, power); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ boolean flag1 = eventRedstone.getNewCurrent() > 0; ++ // CraftBukkit end ++ if (flag1 != (Boolean) state.getValue(DoorBlock.OPEN)) { ++ this.playSound((Entity) null, level, pos, flag1); ++ level.gameEvent((Entity) null, flag1 ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); + } + + level.setBlock(blockpos, (BlockState) ((BlockState) blockstate.setValue(DoorBlock.POWERED, flag1)).setValue(DoorBlock.OPEN, flag1), 2); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DoublePlantBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DoublePlantBlock.java.patch new file mode 100644 index 0000000000..1f0897e3b3 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DoublePlantBlock.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/level/block/DoublePlantBlock.java ++++ b/net/minecraft/world/level/block/DoublePlantBlock.java +@@ -107,8 +100,13 @@ + super.playerDestroy(level, player, blockpos, Blocks.AIR.defaultBlockState(), blockentity, itemstack); + } + +- protected static void preventDropFromBottomPart(Level level, BlockPos blockpos, BlockState blockstate, Player player) { +- DoubleBlockHalf doubleblockhalf = (DoubleBlockHalf) blockstate.getValue(DoublePlantBlock.HALF); ++ protected static void preventDropFromBottomPart(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, blockposition).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ BlockPropertyDoubleBlockHalf blockpropertydoubleblockhalf = (BlockPropertyDoubleBlockHalf) iblockdata.getValue(DoublePlantBlock.HALF); + + if (doubleblockhalf == DoubleBlockHalf.UPPER) { + BlockPos blockpos1 = blockpos.below(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DragonEggBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DragonEggBlock.java.patch new file mode 100644 index 0000000000..ba8684303f --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DragonEggBlock.java.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/level/block/DragonEggBlock.java ++++ b/net/minecraft/world/level/block/DragonEggBlock.java +@@ -16,6 +16,7 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockFromToEvent; // CraftBukkit + + public class DragonEggBlock extends FallingBlock { + +@@ -57,7 +54,19 @@ + for (int i = 0; i < 1000; ++i) { + BlockPos blockpos1 = blockpos.offset(level.random.nextInt(16) - level.random.nextInt(16), level.random.nextInt(8) - level.random.nextInt(8), level.random.nextInt(16) - level.random.nextInt(16)); + +- if (level.getBlockState(blockpos1).isAir() && worldborder.isWithinBounds(blockpos1)) { ++ if (level.getBlockState(blockposition1).isAir() && worldborder.isWithinBounds(blockposition1)) { ++ // CraftBukkit start ++ org.bukkit.block.Block from = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ org.bukkit.block.Block to = level.getWorld().getBlockAt(blockposition1.getX(), blockposition1.getY(), blockposition1.getZ()); ++ BlockFromToEvent event = new BlockFromToEvent(from, to); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ blockposition1 = new BlockPos(event.getToBlock().getX(), event.getToBlock().getY(), event.getToBlock().getZ()); ++ // CraftBukkit end + if (level.isClientSide) { + for (int j = 0; j < 128; ++j) { + double d0 = level.random.nextDouble(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DropExperienceBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DropExperienceBlock.java.patch new file mode 100644 index 0000000000..24d445e184 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DropExperienceBlock.java.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/level/block/DropExperienceBlock.java ++++ b/net/minecraft/world/level/block/DropExperienceBlock.java +@@ -30,6 +29,11 @@ + } + + @Override ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ super.spawnAfterBreak(state, level, pos, stack, dropExperience); ++ // CraftBukkit start - Delegate to getExpDrop ++ } ++ + @Override + public void spawnAfterBreak(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, ItemStack itemstack, boolean flag) { + super.spawnAfterBreak(blockstate, serverlevel, blockpos, itemstack, flag); +@@ -37,5 +40,7 @@ + this.tryDropExperience(serverlevel, blockpos, itemstack, this.xpRange); + } + ++ return 0; ++ // CraftBukkit end + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DropperBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DropperBlock.java.patch new file mode 100644 index 0000000000..537883288f --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/DropperBlock.java.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/world/level/block/DropperBlock.java ++++ b/net/minecraft/world/level/block/DropperBlock.java +@@ -18,12 +19,15 @@ + import net.minecraft.world.level.block.state.BlockBehaviour; + import net.minecraft.world.level.block.state.BlockState; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.inventory.InventoryMoveItemEvent; ++// CraftBukkit end + + public class DropperBlock extends DispenserBlock { + + private static final Logger LOGGER = LogUtils.getLogger(); + public static final MapCodec CODEC = simpleCodec(DropperBlock::new); +- private static final DispenseItemBehavior DISPENSE_BEHAVIOUR = new DefaultDispenseItemBehavior(); ++ private static final DispenseItemBehavior DISPENSE_BEHAVIOUR = new DefaultDispenseItemBehavior(true); // CraftBukkit + + @Override + @Override +@@ -71,8 +71,25 @@ + if (container == null) { + itemstack1 = DropperBlock.DISPENSE_BEHAVIOUR.dispense(blocksource, itemstack); + } else { +- itemstack1 = HopperBlockEntity.addItem(dispenserblockentity, container, itemstack.copy().split(1), direction.getOpposite()); +- if (itemstack1.isEmpty()) { ++ // CraftBukkit start - Fire event when pushing items into other inventories ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(itemstack.copy().split(1)); ++ ++ org.bukkit.inventory.Inventory destinationInventory; ++ // Have to special case large chests as they work oddly ++ if (iinventory instanceof CompoundContainer) { ++ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory); ++ } else { ++ destinationInventory = iinventory.getOwner().getInventory(); ++ } ++ ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(tileentitydispenser.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true); ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ itemstack1 = HopperBlockEntity.addItem(tileentitydispenser, iinventory, CraftItemStack.asNMSCopy(event.getItem()), enumdirection.getOpposite()); ++ if (event.getItem().equals(oitemstack) && itemstack1.isEmpty()) { ++ // CraftBukkit end + itemstack1 = itemstack.copy(); + itemstack1.shrink(1); + } else { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/EndPortalBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/EndPortalBlock.java.patch new file mode 100644 index 0000000000..5d28ce54a3 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/EndPortalBlock.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/world/level/block/EndPortalBlock.java ++++ b/net/minecraft/world/level/block/EndPortalBlock.java +@@ -20,6 +22,9 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.entity.EntityPortalEnterEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++// CraftBukkit end + + public class EndPortalBlock extends BaseEntityBlock { + +@@ -49,17 +51,25 @@ + } + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { +- if (level instanceof ServerLevel && entity.canChangeDimensions() && Shapes.joinIsNotEmpty(Shapes.create(entity.getBoundingBox().move((double) (-blockpos.getX()), (double) (-blockpos.getY()), (double) (-blockpos.getZ()))), blockstate.getShape(level, blockpos), BooleanOp.AND)) { +- ResourceKey resourcekey = level.dimension() == Level.END ? Level.OVERWORLD : Level.END; +- ServerLevel serverlevel = ((ServerLevel) level).getServer().getLevel(resourcekey); ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ if (level instanceof ServerLevel && entity.canChangeDimensions() && Shapes.joinIsNotEmpty(Shapes.create(entity.getBoundingBox().move((double) (-pos.getX()), (double) (-pos.getY()), (double) (-pos.getZ()))), state.getShape(level, pos), BooleanOp.AND)) { ++ ResourceKey resourcekey = level.getTypeKey() == LevelStem.END ? Level.OVERWORLD : Level.END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends ++ ServerLevel worldserver = ((ServerLevel) level).getServer().getLevel(resourcekey); + +- if (serverlevel == null) { +- return; ++ if (worldserver == null) { ++ // return; // CraftBukkit - always fire event in case plugins wish to change it + } + +- entity.changeDimension(serverlevel); ++ // CraftBukkit start - Entity in portal ++ EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(level.getWorld(), pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (entity instanceof ServerPlayer) { ++ ((ServerPlayer) entity).changeDimension(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); ++ return; ++ } ++ // CraftBukkit end ++ entity.changeDimension(worldserver); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/FarmBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/FarmBlock.java.patch new file mode 100644 index 0000000000..08770f993f --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/FarmBlock.java.patch @@ -0,0 +1,75 @@ +--- a/net/minecraft/world/level/block/FarmBlock.java ++++ b/net/minecraft/world/level/block/FarmBlock.java +@@ -28,6 +28,10 @@ + import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.event.entity.EntityInteractEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class FarmBlock extends Block { + +@@ -99,28 +95,50 @@ + + if (!isNearWater(serverlevel, blockpos) && !serverlevel.isRainingAt(blockpos.above())) { + if (i > 0) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(FarmBlock.MOISTURE, i - 1), 2); +- } else if (!shouldMaintainFarmland(serverlevel, blockpos)) { +- turnToDirt((Entity) null, blockstate, serverlevel, blockpos); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleMoistureChangeEvent(level, pos, (IBlockData) state.setValue(FarmBlock.MOISTURE, i - 1), 2); // CraftBukkit ++ } else if (!shouldMaintainFarmland(level, pos)) { ++ turnToDirt((Entity) null, state, level, pos); + } + } else if (i < 7) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(FarmBlock.MOISTURE, 7), 2); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleMoistureChangeEvent(level, pos, (IBlockData) state.setValue(FarmBlock.MOISTURE, 7), 2); // CraftBukkit + } + + } + + @Override +- @Override +- public void fallOn(Level level, BlockState blockstate, BlockPos blockpos, Entity entity, float f) { +- if (!level.isClientSide && level.random.nextFloat() < f - 0.5F && entity instanceof LivingEntity && (entity instanceof Player || level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && entity.getBbWidth() * entity.getBbWidth() * entity.getBbHeight() > 0.512F) { +- turnToDirt(entity, blockstate, level, blockpos); ++ public void fallOn(Level level, IBlockData state, BlockPos pos, Entity entity, float fallDistance) { ++ super.fallOn(level, state, pos, entity, fallDistance); // CraftBukkit - moved here as game rules / events shouldn't affect fall damage. ++ if (!level.isClientSide && level.random.nextFloat() < fallDistance - 0.5F && entity instanceof LivingEntity && (entity instanceof Player || level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && entity.getBbWidth() * entity.getBbWidth() * entity.getBbHeight() > 0.512F) { ++ // CraftBukkit start - Interact soil ++ org.bukkit.event.Cancellable cancellable; ++ if (entity instanceof Player) { ++ cancellable = CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ if (cancellable.isCancelled()) { ++ return; ++ } ++ ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.DIRT.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end ++ turnToDirt(entity, state, level, pos); + } + +- super.fallOn(level, blockstate, blockpos, entity, f); ++ // super.fallOn(world, iblockdata, blockposition, entity, f); // CraftBukkit - moved up + } + +- public static void turnToDirt(@Nullable Entity entity, BlockState blockstate, Level level, BlockPos blockpos) { +- BlockState blockstate1 = pushEntitiesUp(blockstate, Blocks.DIRT.defaultBlockState(), level, blockpos); ++ public static void turnToDirt(@Nullable Entity entity, IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ if (CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ IBlockData iblockdata1 = pushEntitiesUp(state, Blocks.DIRT.defaultBlockState(), level, pos); + + level.setBlockAndUpdate(blockpos, blockstate1); + level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(entity, blockstate1)); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/FenceGateBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/FenceGateBlock.java.patch new file mode 100644 index 0000000000..09f55ee7bd --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/FenceGateBlock.java.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/level/block/FenceGateBlock.java ++++ b/net/minecraft/world/level/block/FenceGateBlock.java +@@ -178,7 +167,18 @@ + @Override + public void neighborChanged(BlockState blockstate, Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { + if (!level.isClientSide) { +- boolean flag1 = level.hasNeighborSignal(blockpos); ++ boolean flag1 = level.hasNeighborSignal(pos); ++ // CraftBukkit start ++ boolean oldPowered = state.getValue(FenceGateBlock.POWERED); ++ if (oldPowered != flag1) { ++ int newPower = flag1 ? 15 : 0; ++ int oldPower = oldPowered ? 15 : 0; ++ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos); ++ org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(bukkitBlock, oldPower, newPower); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ flag1 = eventRedstone.getNewCurrent() > 0; ++ } ++ // CraftBukkit end + + if ((Boolean) blockstate.getValue(FenceGateBlock.POWERED) != flag1) { + level.setBlock(blockpos, (BlockState) ((BlockState) blockstate.setValue(FenceGateBlock.POWERED, flag1)).setValue(FenceGateBlock.OPEN, flag1), 2); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/FireBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/FireBlock.java.patch new file mode 100644 index 0000000000..02a611b44e --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/FireBlock.java.patch @@ -0,0 +1,166 @@ +--- a/net/minecraft/world/level/block/FireBlock.java ++++ b/net/minecraft/world/level/block/FireBlock.java +@@ -28,6 +28,13 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.block.CraftBlockStates; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.block.BlockBurnEvent; ++import org.bukkit.event.block.BlockFadeEvent; ++// CraftBukkit end + + public class FireBlock extends BaseFireBlock { + +@@ -100,9 +106,25 @@ + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- return this.canSurvive(blockstate, levelaccessor, blockpos) ? this.getStateWithAge(levelaccessor, blockpos, (Integer) blockstate.getValue(FireBlock.AGE)) : Blocks.AIR.defaultBlockState(); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ // CraftBukkit start ++ if (!this.canSurvive(state, level, currentPos)) { ++ // Suppress during worldgen ++ if (!(level instanceof Level)) { ++ return Blocks.AIR.defaultBlockState(); ++ } ++ CraftBlockState blockState = CraftBlockStates.getBlockState(level, currentPos); ++ blockState.setData(Blocks.AIR.defaultBlockState()); ++ ++ BlockFadeEvent event = new BlockFadeEvent(blockState.getBlock(), blockState); ++ ((Level) level).getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ return blockState.getHandle(); ++ } ++ } ++ return this.getStateWithAge(level, currentPos, (Integer) state.getValue(FireBlock.AGE)); ++ // CraftBukkit end + } + + @Override +@@ -150,20 +169,19 @@ + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- serverlevel.scheduleTick(blockpos, (Block) this, getFireTickDelay(serverlevel.random)); +- if (serverlevel.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) { +- if (!blockstate.canSurvive(serverlevel, blockpos)) { +- serverlevel.removeBlock(blockpos, false); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ level.scheduleTick(pos, (Block) this, getFireTickDelay(level.random)); ++ if (level.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) { ++ if (!state.canSurvive(level, pos)) { ++ fireExtinguished(level, pos); // CraftBukkit - invalid place location + } + + BlockState blockstate1 = serverlevel.getBlockState(blockpos.below()); + boolean flag = blockstate1.is(serverlevel.dimensionType().infiniburn()); + int i = (Integer) blockstate.getValue(FireBlock.AGE); + +- if (!flag && serverlevel.isRaining() && this.isNearRain(serverlevel, blockpos) && randomsource.nextFloat() < 0.2F + (float) i * 0.03F) { +- serverlevel.removeBlock(blockpos, false); ++ if (!flag && level.isRaining() && this.isNearRain(level, pos) && random.nextFloat() < 0.2F + (float) i * 0.03F) { ++ fireExtinguished(level, pos); // CraftBukkit - extinguished by rain + } else { + int j = Math.min(15, i + randomsource.nextInt(3) / 2); + +@@ -176,15 +194,15 @@ + if (!this.isValidFireLocation(serverlevel, blockpos)) { + BlockPos blockpos1 = blockpos.below(); + +- if (!serverlevel.getBlockState(blockpos1).isFaceSturdy(serverlevel, blockpos1, Direction.UP) || i > 3) { +- serverlevel.removeBlock(blockpos, false); ++ if (!level.getBlockState(blockposition1).isFaceSturdy(level, blockposition1, Direction.UP) || i > 3) { ++ fireExtinguished(level, pos); // CraftBukkit + } + + return; + } + +- if (i == 15 && randomsource.nextInt(4) == 0 && !this.canBurn(serverlevel.getBlockState(blockpos.below()))) { +- serverlevel.removeBlock(blockpos, false); ++ if (i == 15 && random.nextInt(4) == 0 && !this.canBurn(level.getBlockState(pos.below()))) { ++ fireExtinguished(level, pos); // CraftBukkit + return; + } + } +@@ -192,13 +210,15 @@ + boolean flag1 = serverlevel.getBiome(blockpos).is(BiomeTags.INCREASED_FIRE_BURNOUT); + int k = flag1 ? -50 : 0; + +- this.checkBurnOut(serverlevel, blockpos.east(), 300 + k, randomsource, i); +- this.checkBurnOut(serverlevel, blockpos.west(), 300 + k, randomsource, i); +- this.checkBurnOut(serverlevel, blockpos.below(), 250 + k, randomsource, i); +- this.checkBurnOut(serverlevel, blockpos.above(), 250 + k, randomsource, i); +- this.checkBurnOut(serverlevel, blockpos.north(), 300 + k, randomsource, i); +- this.checkBurnOut(serverlevel, blockpos.south(), 300 + k, randomsource, i); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ // CraftBukkit start - add source blockposition to burn calls ++ this.trySpread(level, pos.east(), 300 + k, random, i, pos); ++ this.trySpread(level, pos.west(), 300 + k, random, i, pos); ++ this.trySpread(level, pos.below(), 250 + k, random, i, pos); ++ this.trySpread(level, pos.above(), 250 + k, random, i, pos); ++ this.trySpread(level, pos.north(), 300 + k, random, i, pos); ++ this.trySpread(level, pos.south(), 300 + k, random, i, pos); ++ // CraftBukkit end ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + + for (int l = -1; l <= 1; ++l) { + for (int i1 = -1; i1 <= 1; ++i1) { +@@ -223,7 +243,15 @@ + if (i2 > 0 && randomsource.nextInt(k1) <= i2 && (!serverlevel.isRaining() || !this.isNearRain(serverlevel, blockpos_mutableblockpos))) { + int j2 = Math.min(15, i + randomsource.nextInt(5) / 4); + +- serverlevel.setBlock(blockpos_mutableblockpos, this.getStateWithAge(serverlevel, blockpos_mutableblockpos, j2), 3); ++ // CraftBukkit start - Call to stop spread of fire ++ if (level.getBlockState(blockposition_mutableblockposition).getBlock() != Blocks.FIRE) { ++ if (CraftEventFactory.callBlockIgniteEvent(level, blockposition_mutableblockposition, pos).isCancelled()) { ++ continue; ++ } ++ ++ CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition_mutableblockposition, this.getStateWithAge(level, blockposition_mutableblockposition, j2), 3); // CraftBukkit ++ } ++ // CraftBukkit end + } + } + } +@@ -247,13 +275,29 @@ + return blockstate.hasProperty(BlockStateProperties.WATERLOGGED) && (Boolean) blockstate.getValue(BlockStateProperties.WATERLOGGED) ? 0 : this.igniteOdds.getInt(blockstate.getBlock()); + } + +- private void checkBurnOut(Level level, BlockPos blockpos, int i, RandomSource randomsource, int j) { +- int k = this.getBurnOdds(level.getBlockState(blockpos)); ++ private void trySpread(Level world, BlockPos blockposition, int i, RandomSource randomsource, int j, BlockPos sourceposition) { // CraftBukkit add sourceposition ++ int k = this.getBurnOdds(world.getBlockState(blockposition)); + + if (randomsource.nextInt(i) < k) { + BlockState blockstate = level.getBlockState(blockpos); + +- if (randomsource.nextInt(j + 10) < 5 && !level.isRainingAt(blockpos)) { ++ // CraftBukkit start ++ org.bukkit.block.Block theBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ org.bukkit.block.Block sourceBlock = world.getWorld().getBlockAt(sourceposition.getX(), sourceposition.getY(), sourceposition.getZ()); ++ ++ BlockBurnEvent event = new BlockBurnEvent(theBlock, sourceBlock); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ if (iblockdata.getBlock() instanceof TntBlock && !CraftEventFactory.callTNTPrimeEvent(world, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.FIRE, null, sourceposition)) { ++ return; ++ } ++ // CraftBukkit end ++ ++ if (randomsource.nextInt(j + 10) < 5 && !world.isRainingAt(blockposition)) { + int l = Math.min(j + randomsource.nextInt(5) / 4, 15); + + level.setBlock(blockpos, this.getStateWithAge(level, blockpos, l), 3); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/FungusBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/FungusBlock.java.patch new file mode 100644 index 0000000000..d0ae076543 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/FungusBlock.java.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/world/level/block/FungusBlock.java ++++ b/net/minecraft/world/level/block/FungusBlock.java +@@ -77,10 +72,16 @@ + } + + @Override +- @Override +- public void performBonemeal(ServerLevel serverlevel, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { +- this.getFeature(serverlevel).ifPresent((holder) -> { +- ((ConfiguredFeature) holder.value()).place(serverlevel, serverlevel.getChunkSource().getGenerator(), randomsource, blockpos); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ this.getFeature(level).ifPresent((holder) -> { ++ // CraftBukkit start ++ if (this == Blocks.WARPED_FUNGUS) { ++ SaplingBlock.treeType = org.bukkit.TreeType.WARPED_FUNGUS; ++ } else if (this == Blocks.CRIMSON_FUNGUS) { ++ SaplingBlock.treeType = org.bukkit.TreeType.CRIMSON_FUNGUS; ++ } ++ // CraftBukkit end ++ ((ConfiguredFeature) holder.value()).place(level, level.getChunkSource().getGenerator(), random, pos); + }); + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/GrowingPlantHeadBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/GrowingPlantHeadBlock.java.patch new file mode 100644 index 0000000000..4fe796fa43 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/GrowingPlantHeadBlock.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/level/block/GrowingPlantHeadBlock.java ++++ b/net/minecraft/world/level/block/GrowingPlantHeadBlock.java +@@ -51,8 +47,8 @@ + if ((Integer) blockstate.getValue(GrowingPlantHeadBlock.AGE) < 25 && randomsource.nextDouble() < this.growPerTickProbability) { + BlockPos blockpos1 = blockpos.relative(this.growthDirection); + +- if (this.canGrowInto(serverlevel.getBlockState(blockpos1))) { +- serverlevel.setBlockAndUpdate(blockpos1, this.getGrowIntoState(blockstate, serverlevel.random)); ++ if (this.canGrowInto(level.getBlockState(blockposition1))) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition1, this.getGrowIntoState(state, level.random)); // CraftBukkit + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/IceBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/IceBlock.java.patch new file mode 100644 index 0000000000..67c1c37c89 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/IceBlock.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/level/block/IceBlock.java ++++ b/net/minecraft/world/level/block/IceBlock.java +@@ -61,7 +58,12 @@ + + } + +- protected void melt(BlockState blockstate, Level level, BlockPos blockpos) { ++ protected void melt(IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, level.dimensionType().ultraWarm() ? Blocks.AIR.defaultBlockState() : Blocks.WATER.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + if (level.dimensionType().ultraWarm()) { + level.removeBlock(blockpos, false); + } else { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/InfestedBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/InfestedBlock.java.patch new file mode 100644 index 0000000000..9e735c66d2 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/InfestedBlock.java.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/world/level/block/InfestedBlock.java ++++ b/net/minecraft/world/level/block/InfestedBlock.java +@@ -18,6 +18,7 @@ + import net.minecraft.world.level.block.state.BlockBehaviour; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.block.state.properties.Property; ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; // CraftBukkit + + public class InfestedBlock extends Block { + +@@ -52,10 +52,10 @@ + private void spawnInfestation(ServerLevel serverlevel, BlockPos blockpos) { + Silverfish silverfish = (Silverfish) EntityType.SILVERFISH.create(serverlevel); + +- if (silverfish != null) { +- silverfish.moveTo((double) blockpos.getX() + 0.5D, (double) blockpos.getY(), (double) blockpos.getZ() + 0.5D, 0.0F, 0.0F); +- serverlevel.addFreshEntity(silverfish); +- silverfish.spawnAnim(); ++ if (entitysilverfish != null) { ++ entitysilverfish.moveTo((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, 0.0F, 0.0F); ++ level.addFreshEntity(entitysilverfish, SpawnReason.SILVERFISH_BLOCK); // CraftBukkit - add SpawnReason ++ entitysilverfish.spawnAnim(); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/LayeredCauldronBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/LayeredCauldronBlock.java.patch new file mode 100644 index 0000000000..62f7ac2b1c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/LayeredCauldronBlock.java.patch @@ -0,0 +1,100 @@ +--- a/net/minecraft/world/level/block/LayeredCauldronBlock.java ++++ b/net/minecraft/world/level/block/LayeredCauldronBlock.java +@@ -15,6 +15,11 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.block.CraftBlockStates; ++import org.bukkit.event.block.CauldronLevelChangeEvent; ++// CraftBukkit end + + public class LayeredCauldronBlock extends AbstractCauldronBlock { + +@@ -63,13 +64,16 @@ + } + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { +- if (!level.isClientSide && entity.isOnFire() && this.isEntityInsideContent(blockstate, blockpos, entity)) { +- entity.clearFire(); +- if (entity.mayInteract(level, blockpos)) { +- this.handleEntityOnFireInside(blockstate, level, blockpos); ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ if (!level.isClientSide && entity.isOnFire() && this.isEntityInsideContent(state, pos, entity)) { ++ // CraftBukkit start ++ if (entity.mayInteract(level, pos)) { ++ if (!lowerFillLevel(state, level, pos, entity, CauldronLevelChangeEvent.ChangeReason.EXTINGUISH)) { ++ return; ++ } + } ++ entity.clearFire(); ++ // CraftBukkit end + } + + } +@@ -83,22 +87,41 @@ + + } + +- public static void lowerFillLevel(BlockState blockstate, Level level, BlockPos blockpos) { +- int i = (Integer) blockstate.getValue(LayeredCauldronBlock.LEVEL) - 1; +- BlockState blockstate1 = i == 0 ? Blocks.CAULDRON.defaultBlockState() : (BlockState) blockstate.setValue(LayeredCauldronBlock.LEVEL, i); ++ public static void lowerFillLevel(IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ lowerFillLevel(state, level, pos, null, CauldronLevelChangeEvent.ChangeReason.UNKNOWN); ++ } + + level.setBlockAndUpdate(blockpos, blockstate1); + level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(blockstate1)); + } + ++ // CraftBukkit start ++ public static boolean changeLevel(IBlockData iblockdata, Level world, BlockPos blockposition, IBlockData newBlock, Entity entity, CauldronLevelChangeEvent.ChangeReason reason) { ++ CraftBlockState newState = CraftBlockStates.getBlockState(world, blockposition); ++ newState.setData(newBlock); ++ ++ CauldronLevelChangeEvent event = new CauldronLevelChangeEvent( ++ world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), ++ (entity == null) ? null : entity.getBukkitEntity(), reason, newState ++ ); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ newState.update(true); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(newBlock)); ++ return true; ++ } ++ // CraftBukkit end ++ + @Override + @Override + public void handlePrecipitation(BlockState blockstate, Level level, BlockPos blockpos, Biome.Precipitation biome_precipitation) { + if (CauldronBlock.shouldHandlePrecipitation(level, biome_precipitation) && (Integer) blockstate.getValue(LayeredCauldronBlock.LEVEL) != 3 && biome_precipitation == this.precipitationType) { + BlockState blockstate1 = (BlockState) blockstate.cycle(LayeredCauldronBlock.LEVEL); + +- level.setBlockAndUpdate(blockpos, blockstate1); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(blockstate1)); ++ changeLevel(state, level, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL); // CraftBukkit + } + } + +@@ -120,9 +142,12 @@ + if (!this.isFull(blockstate)) { + BlockState blockstate1 = (BlockState) blockstate.setValue(LayeredCauldronBlock.LEVEL, (Integer) blockstate.getValue(LayeredCauldronBlock.LEVEL) + 1); + +- level.setBlockAndUpdate(blockpos, blockstate1); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(blockstate1)); +- level.levelEvent(1047, blockpos, 0); ++ // CraftBukkit start ++ if (!changeLevel(state, level, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL)) { ++ return; ++ } ++ // CraftBukkit end ++ level.levelEvent(1047, pos, 0); + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/LeavesBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/LeavesBlock.java.patch new file mode 100644 index 0000000000..84f1ba0a95 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/LeavesBlock.java.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/level/block/LeavesBlock.java ++++ b/net/minecraft/world/level/block/LeavesBlock.java +@@ -24,6 +24,7 @@ + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.LeavesDecayEvent; // CraftBukkit + + public class LeavesBlock extends Block implements SimpleWaterloggedBlock { + +@@ -58,11 +56,18 @@ + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (this.decaying(blockstate)) { +- dropResources(blockstate, serverlevel, blockpos); +- serverlevel.removeBlock(blockpos, false); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (this.decaying(state)) { ++ // CraftBukkit start ++ LeavesDecayEvent event = new LeavesDecayEvent(level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled() || level.getBlockState(pos).getBlock() != this) { ++ return; ++ } ++ // CraftBukkit end ++ dropResources(state, level, pos); ++ level.removeBlock(pos, false); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/LecternBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/LecternBlock.java.patch new file mode 100644 index 0000000000..8c4d06e92f --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/LecternBlock.java.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/world/level/block/LecternBlock.java ++++ b/net/minecraft/world/level/block/LecternBlock.java +@@ -219,16 +206,17 @@ + } + } + +- private void popBook(BlockState blockstate, Level level, BlockPos blockpos) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ private void popBook(IBlockData state, Level level, BlockPos pos) { ++ BlockEntity tileentity = level.getBlockEntity(pos, false); // CraftBukkit - don't validate, type may be changed already + +- if (blockentity instanceof LecternBlockEntity) { +- LecternBlockEntity lecternblockentity = (LecternBlockEntity) blockentity; +- Direction direction = (Direction) blockstate.getValue(LecternBlock.FACING); +- ItemStack itemstack = lecternblockentity.getBook().copy(); +- float f = 0.25F * (float) direction.getStepX(); +- float f1 = 0.25F * (float) direction.getStepZ(); +- ItemEntity itementity = new ItemEntity(level, (double) blockpos.getX() + 0.5D + (double) f, (double) (blockpos.getY() + 1), (double) blockpos.getZ() + 0.5D + (double) f1, itemstack); ++ if (tileentity instanceof LecternBlockEntity) { ++ LecternBlockEntity tileentitylectern = (LecternBlockEntity) tileentity; ++ Direction enumdirection = (Direction) state.getValue(LecternBlock.FACING); ++ ItemStack itemstack = tileentitylectern.getBook().copy(); ++ if (itemstack.isEmpty()) return; // CraftBukkit - SPIGOT-5500 ++ float f = 0.25F * (float) enumdirection.getStepX(); ++ float f1 = 0.25F * (float) enumdirection.getStepZ(); ++ ItemEntity entityitem = new ItemEntity(level, (double) pos.getX() + 0.5D + (double) f, (double) (pos.getY() + 1), (double) pos.getZ() + 0.5D + (double) f1, itemstack); + + itementity.setDefaultPickUpDelay(); + level.addFreshEntity(itementity); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/LeverBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/LeverBlock.java.patch new file mode 100644 index 0000000000..fe17dcb9ed --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/LeverBlock.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/level/block/LeverBlock.java ++++ b/net/minecraft/world/level/block/LeverBlock.java +@@ -27,6 +27,7 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class LeverBlock extends FaceAttachedHorizontalDirectionalBlock { + +@@ -104,11 +102,25 @@ + + return InteractionResult.SUCCESS; + } else { +- blockstate1 = this.pull(blockstate, level, blockpos); +- float f = (Boolean) blockstate1.getValue(LeverBlock.POWERED) ? 0.6F : 0.5F; ++ // CraftBukkit start - Interact Lever ++ boolean powered = state.getValue(LeverBlock.POWERED); // Old powered state ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ int old = (powered) ? 15 : 0; ++ int current = (!powered) ? 15 : 0; + +- level.playSound((Player) null, blockpos, SoundEvents.LEVER_CLICK, SoundSource.BLOCKS, 0.3F, f); +- level.gameEvent((Entity) player, (Boolean) blockstate1.getValue(LeverBlock.POWERED) ? GameEvent.BLOCK_ACTIVATE : GameEvent.BLOCK_DEACTIVATE, blockpos); ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if ((eventRedstone.getNewCurrent() > 0) != (!powered)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ ++ iblockdata1 = this.pull(state, level, pos); ++ float f = (Boolean) iblockdata1.getValue(LeverBlock.POWERED) ? 0.6F : 0.5F; ++ ++ level.playSound((Player) null, pos, SoundEvents.LEVER_CLICK, SoundSource.BLOCKS, 0.3F, f); ++ level.gameEvent((Entity) player, (Boolean) iblockdata1.getValue(LeverBlock.POWERED) ? GameEvent.BLOCK_ACTIVATE : GameEvent.BLOCK_DEACTIVATE, pos); + return InteractionResult.CONSUME; + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/LightningRodBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/LightningRodBlock.java.patch new file mode 100644 index 0000000000..41efe02dd4 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/LightningRodBlock.java.patch @@ -0,0 +1,53 @@ +--- a/net/minecraft/world/level/block/LightningRodBlock.java ++++ b/net/minecraft/world/level/block/LightningRodBlock.java +@@ -32,6 +32,10 @@ + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockRedstoneEvent; ++// CraftBukkit end + + public class LightningRodBlock extends RodBlock implements SimpleWaterloggedBlock { + +@@ -90,11 +88,23 @@ + return (Boolean) blockstate.getValue(LightningRodBlock.POWERED) && blockstate.getValue(LightningRodBlock.FACING) == direction ? 15 : 0; + } + +- public void onLightningStrike(BlockState blockstate, Level level, BlockPos blockpos) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(LightningRodBlock.POWERED, true), 3); +- this.updateNeighbours(blockstate, level, blockpos); +- level.scheduleTick(blockpos, (Block) this, 8); +- level.levelEvent(3002, blockpos, ((Direction) blockstate.getValue(LightningRodBlock.FACING)).getAxis().ordinal()); ++ public void onLightningStrike(IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ boolean powered = state.getValue(LightningRodBlock.POWERED); ++ int old = (powered) ? 15 : 0; ++ int current = (!powered) ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(level, pos), old, current); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if (eventRedstone.getNewCurrent() <= 0) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(LightningRodBlock.POWERED, true), 3); ++ this.updateNeighbours(state, level, pos); ++ level.scheduleTick(pos, (Block) this, 8); ++ level.levelEvent(3002, pos, ((Direction) state.getValue(LightningRodBlock.FACING)).getAxis().ordinal()); + } + + private void updateNeighbours(BlockState blockstate, Level level, BlockPos blockpos) { +@@ -152,8 +157,8 @@ + lightningbolt.moveTo(Vec3.atBottomCenterOf(blockpos.above())); + Entity entity = projectile.getOwner(); + +- lightningbolt.setCause(entity instanceof ServerPlayer ? (ServerPlayer) entity : null); +- level.addFreshEntity(lightningbolt); ++ entitylightning.setCause(entity instanceof ServerPlayer ? (ServerPlayer) entity : null); ++ ((ServerLevel) level).strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.TRIDENT); // CraftBukkit + } + + level.playSound((Player) null, blockpos, SoundEvents.TRIDENT_THUNDER, SoundSource.WEATHER, 5.0F, 1.0F); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/LiquidBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/LiquidBlock.java.patch new file mode 100644 index 0000000000..bf57f95334 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/LiquidBlock.java.patch @@ -0,0 +1,28 @@ +--- a/net/minecraft/world/level/block/LiquidBlock.java ++++ b/net/minecraft/world/level/block/LiquidBlock.java +@@ -188,14 +174,20 @@ + if (level.getFluidState(blockpos1).is(FluidTags.WATER)) { + Block block = level.getFluidState(blockpos).isSource() ? Blocks.OBSIDIAN : Blocks.COBBLESTONE; + +- level.setBlockAndUpdate(blockpos, block.defaultBlockState()); +- this.fizz(level, blockpos); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, block.defaultBlockState())) { ++ this.fizz(level, pos); ++ } ++ // CraftBukkit end + return false; + } + +- if (flag && level.getBlockState(blockpos1).is(Blocks.BLUE_ICE)) { +- level.setBlockAndUpdate(blockpos, Blocks.BASALT.defaultBlockState()); +- this.fizz(level, blockpos); ++ if (flag && level.getBlockState(blockposition1).is(Blocks.BLUE_ICE)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, Blocks.BASALT.defaultBlockState())) { ++ this.fizz(level, pos); ++ } ++ // CraftBukkit end + return false; + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/MagmaBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/MagmaBlock.java.patch new file mode 100644 index 0000000000..95f3de5de8 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/MagmaBlock.java.patch @@ -0,0 +1,12 @@ +--- a/net/minecraft/world/level/block/MagmaBlock.java ++++ b/net/minecraft/world/level/block/MagmaBlock.java +@@ -32,7 +30,9 @@ + @Override + public void stepOn(Level level, BlockPos blockpos, BlockState blockstate, Entity entity) { + if (!entity.isSteppingCarefully() && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity) entity)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); // CraftBukkit + entity.hurt(level.damageSources().hotFloor(), 1.0F); ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = null; // CraftBukkit + } + + super.stepOn(level, blockpos, blockstate, entity); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/MultifaceSpreader.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/MultifaceSpreader.java.patch new file mode 100644 index 0000000000..0582fb0d0e --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/MultifaceSpreader.java.patch @@ -0,0 +1,50 @@ +--- a/net/minecraft/world/level/block/MultifaceSpreader.java ++++ b/net/minecraft/world/level/block/MultifaceSpreader.java +@@ -158,7 +156,7 @@ + levelaccessor.getChunk(multifacespreader_spreadpos.pos()).markPosForPostprocessing(multifacespreader_spreadpos.pos()); + } + +- return levelaccessor.setBlock(multifacespreader_spreadpos.pos(), blockstate1, 2); ++ return org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos.source(), pos.pos(), iblockdata1, 2); // CraftBukkit + } else { + return false; + } +@@ -175,23 +173,20 @@ + + SAME_POSITION { + @Override +- @Override +- public MultifaceSpreader.SpreadPos getSpreadPos(BlockPos blockpos, Direction direction, Direction direction1) { +- return new MultifaceSpreader.SpreadPos(blockpos, direction); ++ public MultifaceSpreader.c getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection) { ++ return new MultifaceSpreader.c(pos, face, pos); // CraftBukkit + } + }, + SAME_PLANE { + @Override +- @Override +- public MultifaceSpreader.SpreadPos getSpreadPos(BlockPos blockpos, Direction direction, Direction direction1) { +- return new MultifaceSpreader.SpreadPos(blockpos.relative(direction), direction1); ++ public MultifaceSpreader.c getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection) { ++ return new MultifaceSpreader.c(pos.relative(face), spreadDirection, pos); // CraftBukkit + } + }, + WRAP_AROUND { + @Override +- @Override +- public MultifaceSpreader.SpreadPos getSpreadPos(BlockPos blockpos, Direction direction, Direction direction1) { +- return new MultifaceSpreader.SpreadPos(blockpos.relative(direction).relative(direction1), direction.getOpposite()); ++ public MultifaceSpreader.c getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection) { ++ return new MultifaceSpreader.c(pos.relative(face).relative(spreadDirection), face.getOpposite(), pos); // CraftBukkit + } + }; + +@@ -200,7 +195,7 @@ + public abstract MultifaceSpreader.SpreadPos getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection); + } + +- public static record SpreadPos(BlockPos pos, Direction face) { ++ public static record c(BlockPos pos, Direction face, BlockPos source) { // CraftBukkit + + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/MushroomBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/MushroomBlock.java.patch new file mode 100644 index 0000000000..1898945308 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/MushroomBlock.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/level/block/MushroomBlock.java ++++ b/net/minecraft/world/level/block/MushroomBlock.java +@@ -19,6 +19,9 @@ + import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.TreeType; ++// CraftBukkit end + + public class MushroomBlock extends BushBlock implements BonemealableBlock { + +@@ -77,8 +77,8 @@ + blockpos2 = blockpos.offset(randomsource.nextInt(3) - 1, randomsource.nextInt(2) - randomsource.nextInt(2), randomsource.nextInt(3) - 1); + } + +- if (serverlevel.isEmptyBlock(blockpos2) && blockstate.canSurvive(serverlevel, blockpos2)) { +- serverlevel.setBlock(blockpos2, blockstate, 2); ++ if (level.isEmptyBlock(blockposition2) && state.canSurvive(level, blockposition2)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition2, state, 2); // CraftBukkit + } + } + +@@ -105,8 +103,9 @@ + if (optional.isEmpty()) { + return false; + } else { +- serverlevel.removeBlock(blockpos, false); +- if (((ConfiguredFeature) ((Holder) optional.get()).value()).place(serverlevel, serverlevel.getChunkSource().getGenerator(), randomsource, blockpos)) { ++ level.removeBlock(pos, false); ++ SaplingBlock.treeType = (this == Blocks.BROWN_MUSHROOM) ? TreeType.BROWN_MUSHROOM : TreeType.BROWN_MUSHROOM; // CraftBukkit ++ if (((ConfiguredFeature) ((Holder) optional.get()).value()).place(level, level.getChunkSource().getGenerator(), random, pos)) { + return true; + } else { + serverlevel.setBlock(blockpos, blockstate, 3); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/NetherPortalBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/NetherPortalBlock.java.patch new file mode 100644 index 0000000000..c3a45fdb2b --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/NetherPortalBlock.java.patch @@ -0,0 +1,37 @@ +--- a/net/minecraft/world/level/block/NetherPortalBlock.java ++++ b/net/minecraft/world/level/block/NetherPortalBlock.java +@@ -25,6 +25,9 @@ + import net.minecraft.world.level.portal.PortalShape; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.event.entity.EntityPortalEnterEvent; ++// CraftBukkit end + + public class NetherPortalBlock extends Block { + +@@ -65,8 +65,9 @@ + blockpos = blockpos.below(); + } + +- if (serverlevel.getBlockState(blockpos).isValidSpawn(serverlevel, blockpos, EntityType.ZOMBIFIED_PIGLIN)) { +- Entity entity = EntityType.ZOMBIFIED_PIGLIN.spawn(serverlevel, blockpos.above(), MobSpawnType.STRUCTURE); ++ if (level.getBlockState(pos).isValidSpawn(level, pos, EntityType.ZOMBIFIED_PIGLIN)) { ++ // CraftBukkit - set spawn reason to NETHER_PORTAL ++ Entity entity = EntityType.ZOMBIFIED_PIGLIN.spawn(level, pos.above(), EnumMobSpawn.STRUCTURE, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NETHER_PORTAL); + + if (entity != null) { + entity.setPortalCooldown(); +@@ -90,7 +89,11 @@ + @Override + public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { + if (entity.canChangeDimensions()) { +- entity.handleInsidePortal(blockpos); ++ // CraftBukkit start - Entity in portal ++ EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(level.getWorld(), pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ // CraftBukkit end ++ entity.handleInsidePortal(pos); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/NetherWartBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/NetherWartBlock.java.patch new file mode 100644 index 0000000000..07d93631f7 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/NetherWartBlock.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/level/block/NetherWartBlock.java ++++ b/net/minecraft/world/level/block/NetherWartBlock.java +@@ -57,9 +52,9 @@ + public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { + int i = (Integer) blockstate.getValue(NetherWartBlock.AGE); + +- if (i < 3 && randomsource.nextInt(10) == 0) { +- blockstate = (BlockState) blockstate.setValue(NetherWartBlock.AGE, i + 1); +- serverlevel.setBlock(blockpos, blockstate, 2); ++ if (i < 3 && random.nextInt(10) == 0) { ++ state = (IBlockData) state.setValue(NetherWartBlock.AGE, i + 1); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, state, 2); // CraftBukkit + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/NoteBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/NoteBlock.java.patch new file mode 100644 index 0000000000..cee86bd747 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/NoteBlock.java.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/world/level/block/NoteBlock.java ++++ b/net/minecraft/world/level/block/NoteBlock.java +@@ -85,7 +81,8 @@ + + if (flag1 != (Boolean) blockstate.getValue(NoteBlock.POWERED)) { + if (flag1) { +- this.playNote((Entity) null, blockstate, level, blockpos); ++ this.playNote((Entity) null, state, level, pos); ++ state = level.getBlockState(pos); // CraftBukkit - SPIGOT-5617: update in case changed in event + } + + level.setBlock(blockpos, (BlockState) blockstate.setValue(NoteBlock.POWERED, flag1), 3); +@@ -93,10 +90,16 @@ + + } + +- private void playNote(@Nullable Entity entity, BlockState blockstate, Level level, BlockPos blockpos) { +- if (((NoteBlockInstrument) blockstate.getValue(NoteBlock.INSTRUMENT)).worksAboveNoteBlock() || level.getBlockState(blockpos.above()).isAir()) { +- level.blockEvent(blockpos, this, 0, 0); +- level.gameEvent(entity, GameEvent.NOTE_BLOCK_PLAY, blockpos); ++ private void playNote(@Nullable Entity entity, IBlockData state, Level level, BlockPos pos) { ++ if (((NoteBlockInstrument) state.getValue(NoteBlock.INSTRUMENT)).worksAboveNoteBlock() || level.getBlockState(pos.above()).isAir()) { ++ // CraftBukkit start ++ org.bukkit.event.block.NotePlayEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callNotePlayEvent(level, pos, state.getValue(NoteBlock.INSTRUMENT), state.getValue(NoteBlock.NOTE)); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.blockEvent(pos, this, 0, 0); ++ level.gameEvent(entity, GameEvent.NOTE_BLOCK_PLAY, pos); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/NyliumBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/NyliumBlock.java.patch new file mode 100644 index 0000000000..8d555c9360 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/NyliumBlock.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/level/block/NyliumBlock.java ++++ b/net/minecraft/world/level/block/NyliumBlock.java +@@ -40,10 +39,14 @@ + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (!canBeNylium(blockstate, serverlevel, blockpos)) { +- serverlevel.setBlockAndUpdate(blockpos, Blocks.NETHERRACK.defaultBlockState()); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (!canBeNylium(state, level, pos)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.NETHERRACK.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlockAndUpdate(pos, Blocks.NETHERRACK.defaultBlockState()); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ObserverBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ObserverBlock.java.patch new file mode 100644 index 0000000000..6d4737b916 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ObserverBlock.java.patch @@ -0,0 +1,39 @@ +--- a/net/minecraft/world/level/block/ObserverBlock.java ++++ b/net/minecraft/world/level/block/ObserverBlock.java +@@ -14,6 +14,7 @@ + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class ObserverBlock extends DirectionalBlock { + +@@ -50,13 +47,22 @@ + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if ((Boolean) blockstate.getValue(ObserverBlock.POWERED)) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(ObserverBlock.POWERED, false), 2); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(ObserverBlock.POWERED)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 15, 0).getNewCurrent() != 0) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(ObserverBlock.POWERED, false), 2); + } else { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(ObserverBlock.POWERED, true), 2); +- serverlevel.scheduleTick(blockpos, (Block) this, 2); ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 0, 15).getNewCurrent() != 15) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(ObserverBlock.POWERED, true), 2); ++ level.scheduleTick(pos, (Block) this, 2); + } + + this.updateNeighborsInFront(serverlevel, blockpos, blockstate); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/PointedDripstoneBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/PointedDripstoneBlock.java.patch new file mode 100644 index 0000000000..5a04d1bb18 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/PointedDripstoneBlock.java.patch @@ -0,0 +1,81 @@ +--- a/net/minecraft/world/level/block/PointedDripstoneBlock.java ++++ b/net/minecraft/world/level/block/PointedDripstoneBlock.java +@@ -42,6 +42,10 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class PointedDripstoneBlock extends Block implements Fallable, SimpleWaterloggedBlock { + +@@ -136,18 +135,24 @@ + if (!level.isClientSide) { + BlockPos blockpos = blockhitresult.getBlockPos(); + +- if (projectile.mayInteract(level, blockpos) && projectile.mayBreak(level) && projectile instanceof ThrownTrident && projectile.getDeltaMovement().length() > 0.6D) { +- level.destroyBlock(blockpos, true); ++ if (projectile.mayInteract(level, blockposition) && projectile.mayBreak(level) && projectile instanceof ThrownTrident && projectile.getDeltaMovement().length() > 0.6D) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, Blocks.AIR.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end ++ level.destroyBlock(blockposition, true); + } + + } + } + + @Override +- @Override +- public void fallOn(Level level, BlockState blockstate, BlockPos blockpos, Entity entity, float f) { +- if (blockstate.getValue(PointedDripstoneBlock.TIP_DIRECTION) == Direction.UP && blockstate.getValue(PointedDripstoneBlock.THICKNESS) == DripstoneThickness.TIP) { +- entity.causeFallDamage(f + 2.0F, 2.0F, level.damageSources().stalagmite()); ++ public void fallOn(Level level, IBlockData state, BlockPos pos, Entity entity, float fallDistance) { ++ if (state.getValue(PointedDripstoneBlock.TIP_DIRECTION) == Direction.UP && state.getValue(PointedDripstoneBlock.THICKNESS) == DripstoneThickness.TIP) { ++ CraftEventFactory.blockDamage = CraftBlock.at(level, pos); // CraftBukkit ++ entity.causeFallDamage(fallDistance + 2.0F, 2.0F, level.damageSources().stalagmite()); ++ CraftEventFactory.blockDamage = null; // CraftBukkit + } else { + super.fallOn(level, blockstate, blockpos, entity, f); + } +@@ -400,18 +394,18 @@ + BlockPos blockpos1 = blockpos.relative(direction); + BlockState blockstate = serverlevel.getBlockState(blockpos1); + +- if (isUnmergedTipWithDirection(blockstate, direction.getOpposite())) { +- createMergedTips(blockstate, serverlevel, blockpos1); +- } else if (blockstate.isAir() || blockstate.is(Blocks.WATER)) { +- createDripstone(serverlevel, blockpos1, direction, DripstoneThickness.TIP); ++ if (isUnmergedTipWithDirection(iblockdata, direction.getOpposite())) { ++ createMergedTips(iblockdata, server, blockposition1); ++ } else if (iblockdata.isAir() || iblockdata.is(Blocks.WATER)) { ++ createDripstone(server, blockposition1, direction, DripstoneThickness.TIP, pos); // CraftBukkit + } + + } + +- private static void createDripstone(LevelAccessor levelaccessor, BlockPos blockpos, Direction direction, DripstoneThickness dripstonethickness) { +- BlockState blockstate = (BlockState) ((BlockState) ((BlockState) Blocks.POINTED_DRIPSTONE.defaultBlockState().setValue(PointedDripstoneBlock.TIP_DIRECTION, direction)).setValue(PointedDripstoneBlock.THICKNESS, dripstonethickness)).setValue(PointedDripstoneBlock.WATERLOGGED, levelaccessor.getFluidState(blockpos).getType() == Fluids.WATER); ++ private static void createDripstone(LevelAccessor generatoraccess, BlockPos blockposition, Direction enumdirection, DripstoneThickness dripstonethickness, BlockPos source) { // CraftBukkit ++ IBlockData iblockdata = (IBlockData) ((IBlockData) ((IBlockData) Blocks.POINTED_DRIPSTONE.defaultBlockState().setValue(PointedDripstoneBlock.TIP_DIRECTION, enumdirection)).setValue(PointedDripstoneBlock.THICKNESS, dripstonethickness)).setValue(PointedDripstoneBlock.WATERLOGGED, generatoraccess.getFluidState(blockposition).getType() == Fluids.WATER); + +- levelaccessor.setBlock(blockpos, blockstate, 3); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(generatoraccess, source, blockposition, iblockdata, 3); // CraftBukkit + } + + private static void createMergedTips(BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos) { +@@ -426,8 +420,8 @@ + blockpos1 = blockpos.below(); + } + +- createDripstone(levelaccessor, blockpos2, Direction.DOWN, DripstoneThickness.TIP_MERGE); +- createDripstone(levelaccessor, blockpos1, Direction.UP, DripstoneThickness.TIP_MERGE); ++ createDripstone(level, blockposition2, Direction.DOWN, DripstoneThickness.TIP_MERGE, pos); // CraftBukkit ++ createDripstone(level, blockposition1, Direction.UP, DripstoneThickness.TIP_MERGE, pos); // CraftBukkit + } + + public static void spawnDripParticle(Level level, BlockPos blockpos, BlockState blockstate) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/PowderSnowBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/PowderSnowBlock.java.patch new file mode 100644 index 0000000000..25407902e0 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/PowderSnowBlock.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/level/block/PowderSnowBlock.java ++++ b/net/minecraft/world/level/block/PowderSnowBlock.java +@@ -81,8 +77,13 @@ + + entity.setIsInPowderSnow(true); + if (!level.isClientSide) { +- if (entity.isOnFire() && (level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity instanceof Player) && entity.mayInteract(level, blockpos)) { +- level.destroyBlock(blockpos, false); ++ // CraftBukkit start ++ if (entity.isOnFire() && entity.mayInteract(level, pos)) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !(level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity instanceof Player))) { ++ return; ++ } ++ // CraftBukkit end ++ level.destroyBlock(pos, false); + } + + entity.setSharedFlagOnFire(false); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/PoweredRailBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/PoweredRailBlock.java.patch new file mode 100644 index 0000000000..3649b9bccc --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/PoweredRailBlock.java.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/world/level/block/PoweredRailBlock.java ++++ b/net/minecraft/world/level/block/PoweredRailBlock.java +@@ -11,6 +11,7 @@ + import net.minecraft.world.level.block.state.properties.EnumProperty; + import net.minecraft.world.level.block.state.properties.Property; + import net.minecraft.world.level.block.state.properties.RailShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class PoweredRailBlock extends BaseRailBlock { + +@@ -122,11 +121,18 @@ + boolean flag1 = level.hasNeighborSignal(blockpos) || this.findPoweredRailSignal(level, blockpos, blockstate, true, 0) || this.findPoweredRailSignal(level, blockpos, blockstate, false, 0); + + if (flag1 != flag) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(PoweredRailBlock.POWERED, flag1), 3); +- level.updateNeighborsAt(blockpos.below(), this); +- if (((RailShape) blockstate.getValue(PoweredRailBlock.SHAPE)).isAscending()) { +- level.updateNeighborsAt(blockpos.above(), this); ++ // CraftBukkit start ++ int power = flag ? 15 : 0; ++ int newPower = CraftEventFactory.callRedstoneChange(level, pos, power, 15 - power).getNewCurrent(); ++ if (newPower == power) { ++ return; + } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(PoweredRailBlock.POWERED, flag1), 3); ++ level.updateNeighborsAt(pos.below(), this); ++ if (((RailShape) state.getValue(PoweredRailBlock.SHAPE)).isAscending()) { ++ level.updateNeighborsAt(pos.above(), this); ++ } + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/PressurePlateBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/PressurePlateBlock.java.patch new file mode 100644 index 0000000000..6af2035dc2 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/PressurePlateBlock.java.patch @@ -0,0 +1,56 @@ +--- a/net/minecraft/world/level/block/PressurePlateBlock.java ++++ b/net/minecraft/world/level/block/PressurePlateBlock.java +@@ -12,6 +13,8 @@ + import net.minecraft.world.level.block.state.properties.BlockSetType; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end + + public class PressurePlateBlock extends BasePressurePlateBlock { + +@@ -46,9 +46,8 @@ + } + + @Override +- @Override +- protected int getSignalStrength(Level level, BlockPos blockpos) { +- Class oclass; ++ protected int getSignalStrength(Level level, BlockPos pos) { ++ Class oclass; // CraftBukkit + + switch (this.type.pressurePlateSensitivity()) { + case EVERYTHING: +@@ -63,7 +62,31 @@ + + Class oclass1 = oclass; + +- return getEntityCount(level, PressurePlateBlock.TOUCH_AABB.move(blockpos), oclass1) > 0 ? 15 : 0; ++ // CraftBukkit start - Call interact event when turning on a pressure plate ++ for (Entity entity : getEntities(level, PressurePlateBlock.TOUCH_AABB.move(pos), oclass)) { ++ if (this.getSignalForState(level.getBlockState(pos)) == 0) { ++ org.bukkit.World bworld = level.getWorld(); ++ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager(); ++ org.bukkit.event.Cancellable cancellable; ++ ++ if (entity instanceof Player) { ++ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ manager.callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ // We only want to block turning the plate on if all events are cancelled ++ if (cancellable.isCancelled()) { ++ continue; ++ } ++ } ++ ++ return 15; ++ } ++ ++ return 0; ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/RedStoneOreBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/RedStoneOreBlock.java.patch new file mode 100644 index 0000000000..c648573fe2 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/RedStoneOreBlock.java.patch @@ -0,0 +1,115 @@ +--- a/net/minecraft/world/level/block/RedStoneOreBlock.java ++++ b/net/minecraft/world/level/block/RedStoneOreBlock.java +@@ -21,6 +21,10 @@ + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.phys.BlockHitResult; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end + + public class RedStoneOreBlock extends Block { + +@@ -39,17 +42,29 @@ + } + + @Override +- @Override +- public void attack(BlockState blockstate, Level level, BlockPos blockpos, Player player) { +- interact(blockstate, level, blockpos); +- super.attack(blockstate, level, blockpos, player); ++ public void attack(IBlockData state, Level level, BlockPos pos, Player player) { ++ interact(state, level, pos, player); // CraftBukkit - add entityhuman ++ super.attack(state, level, pos, player); + } + + @Override + @Override + public void stepOn(Level level, BlockPos blockpos, BlockState blockstate, Entity entity) { + if (!entity.isSteppingCarefully()) { +- interact(blockstate, level, blockpos); ++ // CraftBukkit start ++ if (entity instanceof Player) { ++ org.bukkit.event.player.PlayerInteractEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ if (!event.isCancelled()) { ++ interact(level.getBlockState(pos), level, pos, entity); // add entity ++ } ++ } else { ++ EntityInteractEvent event = new EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ interact(level.getBlockState(pos), level, pos, entity); // add entity ++ } ++ } ++ // CraftBukkit end + } + + super.stepOn(level, blockpos, blockstate, entity); +@@ -61,7 +74,7 @@ + if (level.isClientSide) { + spawnParticles(level, blockpos); + } else { +- interact(blockstate, level, blockpos); ++ interact(state, level, pos, player); // CraftBukkit - add entityhuman + } + + ItemStack itemstack = player.getItemInHand(interactionhand); +@@ -69,10 +82,15 @@ + return itemstack.getItem() instanceof BlockItem && (new BlockPlaceContext(player, interactionhand, itemstack, blockhitresult)).canPlace() ? InteractionResult.PASS : InteractionResult.SUCCESS; + } + +- private static void interact(BlockState blockstate, Level level, BlockPos blockpos) { +- spawnParticles(level, blockpos); +- if (!(Boolean) blockstate.getValue(RedStoneOreBlock.LIT)) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(RedStoneOreBlock.LIT, true), 3); ++ private static void interact(IBlockData iblockdata, Level world, BlockPos blockposition, Entity entity) { // CraftBukkit - add Entity ++ spawnParticles(world, blockposition); ++ if (!(Boolean) iblockdata.getValue(RedStoneOreBlock.LIT)) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, iblockdata.setValue(RedStoneOreBlock.LIT, true))) { ++ return; ++ } ++ // CraftBukkit end ++ world.setBlock(blockposition, (IBlockData) iblockdata.setValue(RedStoneOreBlock.LIT, true), 3); + } + + } +@@ -84,15 +101,24 @@ + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if ((Boolean) blockstate.getValue(RedStoneOreBlock.LIT)) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(RedStoneOreBlock.LIT, false), 3); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(RedStoneOreBlock.LIT)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callBlockFadeEvent(level, pos, state.setValue(RedStoneOreBlock.LIT, false)).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(RedStoneOreBlock.LIT, false), 3); + } + + } + + @Override ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ super.spawnAfterBreak(state, level, pos, stack, dropExperience); ++ // CraftBukkit start - Delegated to getExpDrop ++ } ++ + @Override + public void spawnAfterBreak(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, ItemStack itemstack, boolean flag) { + super.spawnAfterBreak(blockstate, serverlevel, blockpos, itemstack, flag); +@@ -102,6 +128,8 @@ + this.popExperience(serverlevel, blockpos, i); + } + ++ return 0; ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/RedStoneWireBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/RedStoneWireBlock.java.patch new file mode 100644 index 0000000000..19688d2738 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/RedStoneWireBlock.java.patch @@ -0,0 +1,32 @@ +--- a/net/minecraft/world/level/block/RedStoneWireBlock.java ++++ b/net/minecraft/world/level/block/RedStoneWireBlock.java +@@ -36,6 +36,7 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class RedStoneWireBlock extends Block { + +@@ -267,9 +262,18 @@ + private void updatePowerStrength(Level level, BlockPos blockpos, BlockState blockstate) { + int i = this.calculateTargetStrength(level, blockpos); + +- if ((Integer) blockstate.getValue(RedStoneWireBlock.POWER) != i) { +- if (level.getBlockState(blockpos) == blockstate) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(RedStoneWireBlock.POWER, i), 2); ++ // CraftBukkit start ++ int oldPower = (Integer) state.getValue(RedStoneWireBlock.POWER); ++ if (oldPower != i) { ++ BlockRedstoneEvent event = new BlockRedstoneEvent(level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()), oldPower, i); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ i = event.getNewCurrent(); ++ } ++ if (oldPower != i) { ++ // CraftBukkit end ++ if (level.getBlockState(pos) == state) { ++ level.setBlock(pos, (IBlockData) state.setValue(RedStoneWireBlock.POWER, i), 2); + } + + Set set = Sets.newHashSet(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/RedstoneLampBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/RedstoneLampBlock.java.patch new file mode 100644 index 0000000000..0e78eed83b --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/RedstoneLampBlock.java.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/world/level/block/RedstoneLampBlock.java ++++ b/net/minecraft/world/level/block/RedstoneLampBlock.java +@@ -11,6 +11,7 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BooleanProperty; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class RedstoneLampBlock extends Block { + +@@ -45,7 +43,12 @@ + if (flag1) { + level.scheduleTick(blockpos, (Block) this, 4); + } else { +- level.setBlock(blockpos, (BlockState) blockstate.cycle(RedstoneLampBlock.LIT), 2); ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 0, 15).getNewCurrent() != 15) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.cycle(RedstoneLampBlock.LIT), 2); + } + } + +@@ -53,10 +56,14 @@ + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if ((Boolean) blockstate.getValue(RedstoneLampBlock.LIT) && !serverlevel.hasNeighborSignal(blockpos)) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.cycle(RedstoneLampBlock.LIT), 2); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(RedstoneLampBlock.LIT) && !level.hasNeighborSignal(pos)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 15, 0).getNewCurrent() != 0) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.cycle(RedstoneLampBlock.LIT), 2); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/RedstoneTorchBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/RedstoneTorchBlock.java.patch new file mode 100644 index 0000000000..4aac8d3e1b --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/RedstoneTorchBlock.java.patch @@ -0,0 +1,59 @@ +--- a/net/minecraft/world/level/block/RedstoneTorchBlock.java ++++ b/net/minecraft/world/level/block/RedstoneTorchBlock.java +@@ -18,6 +18,7 @@ + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class RedstoneTorchBlock extends BaseTorchBlock { + +@@ -90,16 +86,41 @@ + list.remove(0); + } + +- if ((Boolean) blockstate.getValue(RedstoneTorchBlock.LIT)) { ++ // CraftBukkit start ++ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager(); ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ int oldCurrent = ((Boolean) state.getValue(RedstoneTorchBlock.LIT)).booleanValue() ? 15 : 0; ++ ++ BlockRedstoneEvent event = new BlockRedstoneEvent(block, oldCurrent, oldCurrent); ++ // CraftBukkit end ++ if ((Boolean) state.getValue(RedstoneTorchBlock.LIT)) { + if (flag) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(RedstoneTorchBlock.LIT, false), 3); +- if (isToggledTooFrequently(serverlevel, blockpos, true)) { +- serverlevel.levelEvent(1502, blockpos, 0); +- serverlevel.scheduleTick(blockpos, serverlevel.getBlockState(blockpos).getBlock(), 160); ++ // CraftBukkit start ++ if (oldCurrent != 0) { ++ event.setNewCurrent(0); ++ manager.callEvent(event); ++ if (event.getNewCurrent() != 0) { ++ return; ++ } + } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(RedstoneTorchBlock.LIT, false), 3); ++ if (isToggledTooFrequently(level, pos, true)) { ++ level.levelEvent(1502, pos, 0); ++ level.scheduleTick(pos, level.getBlockState(pos).getBlock(), 160); ++ } + } +- } else if (!flag && !isToggledTooFrequently(serverlevel, blockpos, false)) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(RedstoneTorchBlock.LIT, true), 3); ++ } else if (!flag && !isToggledTooFrequently(level, pos, false)) { ++ // CraftBukkit start ++ if (oldCurrent != 15) { ++ event.setNewCurrent(15); ++ manager.callEvent(event); ++ if (event.getNewCurrent() != 15) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(RedstoneTorchBlock.LIT, true), 3); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/RespawnAnchorBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/RespawnAnchorBlock.java.patch new file mode 100644 index 0000000000..8f81326b5e --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/RespawnAnchorBlock.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/level/block/RespawnAnchorBlock.java ++++ b/net/minecraft/world/level/block/RespawnAnchorBlock.java +@@ -88,9 +86,9 @@ + if (!level.isClientSide) { + ServerPlayer serverplayer = (ServerPlayer) player; + +- if (serverplayer.getRespawnDimension() != level.dimension() || !blockpos.equals(serverplayer.getRespawnPosition())) { +- serverplayer.setRespawnPosition(level.dimension(), blockpos, 0.0F, false, true); +- level.playSound((Player) null, (double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D, SoundEvents.RESPAWN_ANCHOR_SET_SPAWN, SoundSource.BLOCKS, 1.0F, 1.0F); ++ if (entityplayer.getRespawnDimension() != level.dimension() || !pos.equals(entityplayer.getRespawnPosition())) { ++ entityplayer.setRespawnPosition(level.dimension(), pos, 0.0F, false, true, org.bukkit.event.player.PlayerSpawnChangeEvent.Cause.RESPAWN_ANCHOR); // CraftBukkit ++ level.playSound((Player) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.RESPAWN_ANCHOR_SET_SPAWN, SoundSource.BLOCKS, 1.0F, 1.0F); + return InteractionResult.SUCCESS; + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/RootedDirtBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/RootedDirtBlock.java.patch new file mode 100644 index 0000000000..e573a620c7 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/RootedDirtBlock.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/level/block/RootedDirtBlock.java ++++ b/net/minecraft/world/level/block/RootedDirtBlock.java +@@ -36,8 +33,7 @@ + } + + @Override +- @Override +- public void performBonemeal(ServerLevel serverlevel, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { +- serverlevel.setBlockAndUpdate(blockpos.below(), Blocks.HANGING_ROOTS.defaultBlockState()); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, pos.below(), Blocks.HANGING_ROOTS.defaultBlockState()); // CraftBukkit + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SaplingBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SaplingBlock.java.patch new file mode 100644 index 0000000000..d472f07842 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SaplingBlock.java.patch @@ -0,0 +1,60 @@ +--- a/net/minecraft/world/level/block/SaplingBlock.java ++++ b/net/minecraft/world/level/block/SaplingBlock.java +@@ -16,6 +16,13 @@ + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.TreeType; ++import org.bukkit.block.BlockState; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.world.StructureGrowEvent; ++// CraftBukkit end + + public class SaplingBlock extends BushBlock implements BonemealableBlock { + +@@ -27,7 +34,8 @@ + public static final IntegerProperty STAGE = BlockStateProperties.STAGE; + protected static final float AABB_OFFSET = 6.0F; + protected static final VoxelShape SHAPE = Block.box(2.0D, 0.0D, 2.0D, 14.0D, 12.0D, 14.0D); +- protected final TreeGrower treeGrower; ++ protected final WorldGenTreeProvider treeGrower; ++ public static TreeType treeType; // CraftBukkit + + @Override + @Override +@@ -60,7 +65,32 @@ + if ((Integer) blockstate.getValue(SaplingBlock.STAGE) == 0) { + serverlevel.setBlock(blockpos, (BlockState) blockstate.cycle(SaplingBlock.STAGE), 4); + } else { +- this.treeGrower.growTree(serverlevel, serverlevel.getChunkSource().getGenerator(), blockpos, blockstate, randomsource); ++ // CraftBukkit start ++ if (level.captureTreeGeneration) { ++ this.treeGrower.growTree(level, level.getChunkSource().getGenerator(), pos, state, random); ++ } else { ++ level.captureTreeGeneration = true; ++ this.treeGrower.growTree(level, level.getChunkSource().getGenerator(), pos, state, random); ++ level.captureTreeGeneration = false; ++ if (level.capturedBlockStates.size() > 0) { ++ TreeType treeType = SaplingBlock.treeType; ++ SaplingBlock.treeType = null; ++ Location location = CraftLocation.toBukkit(pos, level.getWorld()); ++ java.util.List blocks = new java.util.ArrayList<>(level.capturedBlockStates.values()); ++ level.capturedBlockStates.clear(); ++ StructureGrowEvent event = null; ++ if (treeType != null) { ++ event = new StructureGrowEvent(location, treeType, false, null, blocks); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ } ++ if (event == null || !event.isCancelled()) { ++ for (BlockState blockstate : blocks) { ++ blockstate.update(true); ++ } ++ } ++ } ++ } ++ // CraftBukkit end + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ScaffoldingBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ScaffoldingBlock.java.patch new file mode 100644 index 0000000000..ce8ef9088c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/ScaffoldingBlock.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/level/block/ScaffoldingBlock.java ++++ b/net/minecraft/world/level/block/ScaffoldingBlock.java +@@ -112,9 +103,9 @@ + int i = getDistance(serverlevel, blockpos); + BlockState blockstate1 = (BlockState) ((BlockState) blockstate.setValue(ScaffoldingBlock.DISTANCE, i)).setValue(ScaffoldingBlock.BOTTOM, this.isBottom(serverlevel, blockpos, i)); + +- if ((Integer) blockstate1.getValue(ScaffoldingBlock.DISTANCE) == 7) { +- if ((Integer) blockstate.getValue(ScaffoldingBlock.DISTANCE) == 7) { +- FallingBlockEntity.fall(serverlevel, blockpos, blockstate1); ++ if ((Integer) iblockdata1.getValue(ScaffoldingBlock.DISTANCE) == 7 && !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.AIR.defaultBlockState()).isCancelled()) { // CraftBukkit - BlockFadeEvent ++ if ((Integer) state.getValue(ScaffoldingBlock.DISTANCE) == 7) { ++ FallingBlockEntity.fall(level, pos, iblockdata1); + } else { + serverlevel.destroyBlock(blockpos, true); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SculkBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SculkBlock.java.patch new file mode 100644 index 0000000000..28e71ab626 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SculkBlock.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/level/block/SculkBlock.java ++++ b/net/minecraft/world/level/block/SculkBlock.java +@@ -45,8 +43,11 @@ + BlockPos blockpos2 = blockpos1.above(); + BlockState blockstate = this.getRandomGrowthState(levelaccessor, blockpos2, randomsource, sculkspreader.isWorldGeneration()); + +- levelaccessor.setBlock(blockpos2, blockstate, 3); +- levelaccessor.playSound((Player) null, blockpos1, blockstate.getSoundType().getPlaceSound(), SoundSource.BLOCKS, 1.0F, 1.0F); ++ // CraftBukkit start - Call BlockSpreadEvent ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition2, iblockdata, 3)) { ++ level.playSound((Player) null, blockposition1, iblockdata.getSoundType().getPlaceSound(), SoundSource.BLOCKS, 1.0F, 1.0F); ++ } ++ // CraftBukkit end + } + + return Math.max(0, i - j); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SculkCatalystBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SculkCatalystBlock.java.patch new file mode 100644 index 0000000000..3726fe60b2 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SculkCatalystBlock.java.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/world/level/block/SculkCatalystBlock.java ++++ b/net/minecraft/world/level/block/SculkCatalystBlock.java +@@ -66,9 +66,9 @@ + } + + @Override +- @Override +- public RenderShape getRenderShape(BlockState blockstate) { +- return RenderShape.MODEL; ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ super.spawnAfterBreak(state, level, pos, stack, dropExperience); ++ // CraftBukkit start - Delegate to getExpDrop + } + + @Override +@@ -79,5 +77,7 @@ + this.tryDropExperience(serverlevel, blockpos, itemstack, this.xpRange); + } + ++ return 0; ++ // CraftBukkit end + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SculkSensorBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SculkSensorBlock.java.patch new file mode 100644 index 0000000000..11dbdd5930 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SculkSensorBlock.java.patch @@ -0,0 +1,116 @@ +--- a/net/minecraft/world/level/block/SculkSensorBlock.java ++++ b/net/minecraft/world/level/block/SculkSensorBlock.java +@@ -41,6 +41,10 @@ + import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockRedstoneEvent; ++// CraftBukkit end + + public class SculkSensorBlock extends BaseEntityBlock implements SimpleWaterloggedBlock { + +@@ -104,10 +104,21 @@ + } + + @Override +- @Override +- public void stepOn(Level level, BlockPos blockpos, BlockState blockstate, Entity entity) { +- if (!level.isClientSide() && canActivate(blockstate) && entity.getType() != EntityType.WARDEN) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ public void stepOn(Level level, BlockPos pos, IBlockData state, Entity entity) { ++ if (!level.isClientSide() && canActivate(state) && entity.getType() != EntityType.WARDEN) { ++ // CraftBukkit start ++ org.bukkit.event.Cancellable cancellable; ++ if (entity instanceof Player) { ++ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new org.bukkit.event.entity.EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent((org.bukkit.event.entity.EntityInteractEvent) cancellable); ++ } ++ if (cancellable.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ BlockEntity tileentity = level.getBlockEntity(pos); + + if (blockentity instanceof SculkSensorBlockEntity) { + SculkSensorBlockEntity sculksensorblockentity = (SculkSensorBlockEntity) blockentity; +@@ -219,10 +220,19 @@ + return getPhase(blockstate) == SculkSensorPhase.INACTIVE; + } + +- public static void deactivate(Level level, BlockPos blockpos, BlockState blockstate) { +- level.setBlock(blockpos, (BlockState) ((BlockState) blockstate.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.COOLDOWN)).setValue(SculkSensorBlock.POWER, 0), 3); +- level.scheduleTick(blockpos, blockstate.getBlock(), 10); +- updateNeighbours(level, blockpos, blockstate); ++ public static void deactivate(Level level, BlockPos pos, IBlockData state) { ++ // CraftBukkit start ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(level, pos), state.getValue(SculkSensorBlock.POWER), 0); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if (eventRedstone.getNewCurrent() > 0) { ++ level.setBlock(pos, state.setValue(SculkSensorBlock.POWER, eventRedstone.getNewCurrent()), 3); ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) ((IBlockData) state.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.COOLDOWN)).setValue(SculkSensorBlock.POWER, 0), 3); ++ level.scheduleTick(pos, state.getBlock(), 10); ++ updateNeighbours(level, pos, state); + } + + @VisibleForTesting +@@ -230,15 +240,24 @@ + return 30; + } + +- public void activate(@Nullable Entity entity, Level level, BlockPos blockpos, BlockState blockstate, int i, int j) { +- level.setBlock(blockpos, (BlockState) ((BlockState) blockstate.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.ACTIVE)).setValue(SculkSensorBlock.POWER, i), 3); +- level.scheduleTick(blockpos, blockstate.getBlock(), this.getActiveTicks()); +- updateNeighbours(level, blockpos, blockstate); +- tryResonateVibration(entity, level, blockpos, j); +- level.gameEvent(entity, GameEvent.SCULK_SENSOR_TENDRILS_CLICKING, blockpos); +- if (!(Boolean) blockstate.getValue(SculkSensorBlock.WATERLOGGED)) { +- level.playSound((Player) null, (double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D, SoundEvents.SCULK_CLICKING, SoundSource.BLOCKS, 1.0F, level.random.nextFloat() * 0.2F + 0.8F); ++ public void activate(@Nullable Entity entity, Level level, BlockPos pos, IBlockData state, int power, int frequency) { ++ // CraftBukkit start ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(level, pos), state.getValue(SculkSensorBlock.POWER), power); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if (eventRedstone.getNewCurrent() <= 0) { ++ return; + } ++ power = eventRedstone.getNewCurrent(); ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) ((IBlockData) state.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.ACTIVE)).setValue(SculkSensorBlock.POWER, power), 3); ++ level.scheduleTick(pos, state.getBlock(), this.getActiveTicks()); ++ updateNeighbours(level, pos, state); ++ tryResonateVibration(entity, level, pos, frequency); ++ level.gameEvent(entity, GameEvent.SCULK_SENSOR_TENDRILS_CLICKING, pos); ++ if (!(Boolean) state.getValue(SculkSensorBlock.WATERLOGGED)) { ++ level.playSound((Player) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.SCULK_CLICKING, SoundSource.BLOCKS, 1.0F, level.random.nextFloat() * 0.2F + 0.8F); ++ } + + } + +@@ -317,6 +330,11 @@ + } + + @Override ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ super.spawnAfterBreak(state, level, pos, stack, dropExperience); ++ // CraftBukkit start - Delegate to getExpDrop ++ } ++ + @Override + public void spawnAfterBreak(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, ItemStack itemstack, boolean flag) { + super.spawnAfterBreak(blockstate, serverlevel, blockpos, itemstack, flag); +@@ -324,5 +341,7 @@ + this.tryDropExperience(serverlevel, blockpos, itemstack, ConstantInt.of(5)); + } + ++ return 0; ++ // CraftBukkit end + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SculkShriekerBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SculkShriekerBlock.java.patch new file mode 100644 index 0000000000..d73f7a4bfa --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SculkShriekerBlock.java.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/world/level/block/SculkShriekerBlock.java ++++ b/net/minecraft/world/level/block/SculkShriekerBlock.java +@@ -65,9 +62,10 @@ + ServerLevel serverlevel = (ServerLevel) level; + ServerPlayer serverplayer = SculkShriekerBlockEntity.tryGetPlayer(entity); + +- if (serverplayer != null) { +- serverlevel.getBlockEntity(blockpos, BlockEntityType.SCULK_SHRIEKER).ifPresent((sculkshriekerblockentity) -> { +- sculkshriekerblockentity.tryShriek(serverlevel, serverplayer); ++ if (entityplayer != null) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(entityplayer, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null).isCancelled()) return; // CraftBukkit ++ worldserver.getBlockEntity(pos, BlockEntityType.SCULK_SHRIEKER).ifPresent((sculkshriekerblockentity) -> { ++ sculkshriekerblockentity.tryShriek(worldserver, entityplayer); + }); + } + } +@@ -152,9 +146,9 @@ + } + + @Override +- @Override +- public FluidState getFluidState(BlockState blockstate) { +- return (Boolean) blockstate.getValue(SculkShriekerBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(blockstate); ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ super.spawnAfterBreak(state, level, pos, stack, dropExperience); ++ // CraftBukkit start - Delegate to getExpDrop + } + + @Override +@@ -165,6 +157,8 @@ + this.tryDropExperience(serverlevel, blockpos, itemstack, ConstantInt.of(5)); + } + ++ return 0; ++ // CraftBukkit end + } + + @Nullable diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SculkSpreader.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SculkSpreader.java.patch new file mode 100644 index 0000000000..422c2e4ea0 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SculkSpreader.java.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/world/level/block/SculkSpreader.java ++++ b/net/minecraft/world/level/block/SculkSpreader.java +@@ -40,6 +42,10 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockState; + import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.SculkBloomEvent; ++// CraftBukkit end + + public class SculkSpreader { + +@@ -56,6 +62,7 @@ + private final int additionalDecayRate; + private List cursors = new ArrayList(); + private static final Logger LOGGER = LogUtils.getLogger(); ++ public Level level; // CraftBukkit + + public SculkSpreader(boolean flag, TagKey tagkey, int i, int j, int k, int l) { + this.isWorldGeneration = flag; +@@ -146,7 +153,20 @@ + + private void addCursor(SculkSpreader.ChargeCursor sculkspreader_chargecursor) { + if (this.cursors.size() < 32) { +- this.cursors.add(sculkspreader_chargecursor); ++ // CraftBukkit start ++ if (!isWorldGeneration()) { // CraftBukkit - SPIGOT-7475: Don't call event during world generation ++ CraftBlock bukkitBlock = CraftBlock.at(level, cursor.pos); ++ SculkBloomEvent event = new SculkBloomEvent(bukkitBlock, cursor.getCharge()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ cursor.charge = event.getCharge(); ++ } ++ // CraftBukkit end ++ ++ this.cursors.add(cursor); + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SculkVeinBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SculkVeinBlock.java.patch new file mode 100644 index 0000000000..65795265b7 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SculkVeinBlock.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/world/level/block/SculkVeinBlock.java ++++ b/net/minecraft/world/level/block/SculkVeinBlock.java +@@ -110,13 +107,13 @@ + } + + @Override +- @Override +- public int attemptUseCharge(SculkSpreader.ChargeCursor sculkspreader_chargecursor, LevelAccessor levelaccessor, BlockPos blockpos, RandomSource randomsource, SculkSpreader sculkspreader, boolean flag) { +- return flag && this.attemptPlaceSculk(sculkspreader, levelaccessor, sculkspreader_chargecursor.getPos(), randomsource) ? sculkspreader_chargecursor.getCharge() - 1 : (randomsource.nextInt(sculkspreader.chargeDecayRate()) == 0 ? Mth.floor((float) sculkspreader_chargecursor.getCharge() * 0.5F) : sculkspreader_chargecursor.getCharge()); ++ public int attemptUseCharge(SculkSpreader.ChargeCursor cursor, LevelAccessor level, BlockPos pos, RandomSource random, SculkSpreader spreader, boolean shouldConvertBlocks) { ++ // CraftBukkit - add source block ++ return shouldConvertBlocks && this.attemptPlaceSculk(spreader, level, cursor.getPos(), random, pos) ? cursor.getCharge() - 1 : (random.nextInt(spreader.chargeDecayRate()) == 0 ? Mth.floor((float) cursor.getCharge() * 0.5F) : cursor.getCharge()); + } + +- private boolean attemptPlaceSculk(SculkSpreader sculkspreader, LevelAccessor levelaccessor, BlockPos blockpos, RandomSource randomsource) { +- BlockState blockstate = levelaccessor.getBlockState(blockpos); ++ private boolean attemptPlaceSculk(SculkSpreader sculkspreader, LevelAccessor generatoraccess, BlockPos blockposition, RandomSource randomsource, BlockPos sourceBlock) { // CraftBukkit ++ IBlockData iblockdata = generatoraccess.getBlockState(blockposition); + TagKey tagkey = sculkspreader.replaceableBlocks(); + Iterator iterator = Direction.allShuffled(randomsource).iterator(); + +@@ -130,13 +127,17 @@ + if (blockstate1.is(tagkey)) { + BlockState blockstate2 = Blocks.SCULK.defaultBlockState(); + +- levelaccessor.setBlock(blockpos1, blockstate2, 3); +- Block.pushEntitiesUp(blockstate1, blockstate2, levelaccessor, blockpos1); +- levelaccessor.playSound((Player) null, blockpos1, SoundEvents.SCULK_BLOCK_SPREAD, SoundSource.BLOCKS, 1.0F, 1.0F); +- this.veinSpreader.spreadAll(blockstate2, levelaccessor, blockpos1, sculkspreader.isWorldGeneration()); +- Direction direction1 = direction.getOpposite(); +- Direction[] adirection = SculkVeinBlock.DIRECTIONS; +- int i = adirection.length; ++ // CraftBukkit start - Call BlockSpreadEvent ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(generatoraccess, sourceBlock, blockposition1, iblockdata2, 3)) { ++ return false; ++ } ++ // CraftBukkit end ++ Block.pushEntitiesUp(iblockdata1, iblockdata2, generatoraccess, blockposition1); ++ generatoraccess.playSound((Player) null, blockposition1, SoundEvents.SCULK_BLOCK_SPREAD, SoundSource.BLOCKS, 1.0F, 1.0F); ++ this.veinSpreader.spreadAll(iblockdata2, generatoraccess, blockposition1, sculkspreader.isWorldGeneration()); ++ Direction enumdirection1 = enumdirection.getOpposite(); ++ Direction[] aenumdirection = SculkVeinBlock.DIRECTIONS; ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { + Direction direction2 = adirection[j]; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SignBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SignBlock.java.patch new file mode 100644 index 0000000000..6093dba163 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SignBlock.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/level/block/SignBlock.java ++++ b/net/minecraft/world/level/block/SignBlock.java +@@ -123,8 +117,8 @@ + return InteractionResult.SUCCESS; + } else if (flag2) { + return InteractionResult.SUCCESS; +- } else if (!this.otherPlayerIsEditingSign(player, signblockentity) && player.mayBuild() && this.hasEditableText(player, signblockentity, flag1)) { +- this.openTextEdit(player, signblockentity, flag1); ++ } else if (!this.otherPlayerIsEditingSign(player, tileentitysign) && player.mayBuild() && this.hasEditableText(player, tileentitysign, flag1)) { ++ this.openTextEdit(player, tileentitysign, flag1, org.bukkit.event.player.PlayerSignOpenEvent.Cause.INTERACT); // CraftBukkit + return this.getInteractionResult(flag); + } else { + return InteractionResult.PASS; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SnowLayerBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SnowLayerBlock.java.patch new file mode 100644 index 0000000000..5aeff46aa6 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SnowLayerBlock.java.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/world/level/block/SnowLayerBlock.java ++++ b/net/minecraft/world/level/block/SnowLayerBlock.java +@@ -107,11 +97,15 @@ + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (serverlevel.getBrightness(LightLayer.BLOCK, blockpos) > 11) { +- dropResources(blockstate, serverlevel, blockpos); +- serverlevel.removeBlock(blockpos, false); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (level.getBrightness(EnumSkyBlock.BLOCK, pos) > 11) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.AIR.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ dropResources(state, level, pos); ++ level.removeBlock(pos, false); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SpawnerBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SpawnerBlock.java.patch new file mode 100644 index 0000000000..94bcf33ce2 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SpawnerBlock.java.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/world/level/block/SpawnerBlock.java ++++ b/net/minecraft/world/level/block/SpawnerBlock.java +@@ -41,8 +43,9 @@ + @Nullable + @Override + @Override +- public BlockEntityTicker getTicker(Level level, BlockState blockstate, BlockEntityType blockentitytype) { +- return createTickerHelper(blockentitytype, BlockEntityType.MOB_SPAWNER, level.isClientSide ? SpawnerBlockEntity::clientTick : SpawnerBlockEntity::serverTick); ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ super.spawnAfterBreak(state, level, pos, stack, dropExperience); ++ // CraftBukkit start - Delegate to getExpDrop + } + + @Override +@@ -55,6 +57,8 @@ + this.popExperience(serverlevel, blockpos, i); + } + ++ return 0; ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SpongeBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SpongeBlock.java.patch new file mode 100644 index 0000000000..589241706e --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SpongeBlock.java.patch @@ -0,0 +1,116 @@ +--- a/net/minecraft/world/level/block/SpongeBlock.java ++++ b/net/minecraft/world/level/block/SpongeBlock.java +@@ -12,6 +12,12 @@ + import net.minecraft.world.level.block.state.BlockBehaviour; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.material.FluidState; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.util.BlockStateListPopulator; ++import org.bukkit.event.block.SpongeAbsorbEvent; ++// CraftBukkit end + + public class SpongeBlock extends Block { + +@@ -53,10 +56,11 @@ + + } + +- private boolean removeWaterBreadthFirstSearch(Level level, BlockPos blockpos) { +- return BlockPos.breadthFirstTraversal(blockpos, 6, 65, (blockpos1, consumer) -> { +- Direction[] adirection = SpongeBlock.ALL_DIRECTIONS; +- int i = adirection.length; ++ private boolean removeWaterBreadthFirstSearch(Level level, BlockPos pos) { ++ BlockStateListPopulator blockList = new BlockStateListPopulator(level); // CraftBukkit - Use BlockStateListPopulator ++ BlockPos.breadthFirstTraversal(pos, 6, 65, (blockposition1, consumer) -> { ++ Direction[] aenumdirection = SpongeBlock.ALL_DIRECTIONS; ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { + Direction direction = adirection[j]; +@@ -68,8 +72,10 @@ + if (blockpos1.equals(blockpos)) { + return true; + } else { +- BlockState blockstate = level.getBlockState(blockpos1); +- FluidState fluidstate = level.getFluidState(blockpos1); ++ // CraftBukkit start ++ IBlockData iblockdata = blockList.getBlockState(blockposition1); ++ FluidState fluid = blockList.getFluidState(blockposition1); ++ // CraftBukkit end + + if (!fluidstate.is(FluidTags.WATER)) { + return false; +@@ -79,27 +85,64 @@ + if (block instanceof BucketPickup) { + BucketPickup bucketpickup = (BucketPickup) block; + +- if (!bucketpickup.pickupBlock((Player) null, level, blockpos1, blockstate).isEmpty()) { ++ if (!ifluidsource.pickupBlock((Player) null, blockList, blockposition1, iblockdata).isEmpty()) { // CraftBukkit + return true; + } + } + +- if (blockstate.getBlock() instanceof LiquidBlock) { +- level.setBlock(blockpos1, Blocks.AIR.defaultBlockState(), 3); ++ if (iblockdata.getBlock() instanceof LiquidBlock) { ++ blockList.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3); // CraftBukkit + } else { + if (!blockstate.is(Blocks.KELP) && !blockstate.is(Blocks.KELP_PLANT) && !blockstate.is(Blocks.SEAGRASS) && !blockstate.is(Blocks.TALL_SEAGRASS)) { + return false; + } + +- BlockEntity blockentity = blockstate.hasBlockEntity() ? level.getBlockEntity(blockpos1) : null; ++ // CraftBukkit start ++ // TileEntity tileentity = iblockdata.hasBlockEntity() ? world.getBlockEntity(blockposition1) : null; + +- dropResources(blockstate, level, blockpos1, blockentity); +- level.setBlock(blockpos1, Blocks.AIR.defaultBlockState(), 3); ++ // dropResources(iblockdata, world, blockposition1, tileentity); ++ blockList.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3); ++ // CraftBukkit end + } + + return true; + } + } +- }) > 1; ++ }); ++ // CraftBukkit start ++ List blocks = blockList.getList(); // Is a clone ++ if (!blocks.isEmpty()) { ++ final org.bukkit.block.Block bblock = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ ++ SpongeAbsorbEvent event = new SpongeAbsorbEvent(bblock, (List) (List) blocks); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ for (CraftBlockState block : blocks) { ++ BlockPos blockposition1 = block.getPosition(); ++ IBlockData iblockdata = level.getBlockState(blockposition1); ++ FluidState fluid = level.getFluidState(blockposition1); ++ ++ if (fluid.is(FluidTags.WATER)) { ++ if (iblockdata.getBlock() instanceof BucketPickup && !((BucketPickup) iblockdata.getBlock()).pickupBlock((Player) null, blockList, blockposition1, iblockdata).isEmpty()) { ++ // NOP ++ } else if (iblockdata.getBlock() instanceof LiquidBlock) { ++ // NOP ++ } else if (iblockdata.is(Blocks.KELP) || iblockdata.is(Blocks.KELP_PLANT) || iblockdata.is(Blocks.SEAGRASS) || iblockdata.is(Blocks.TALL_SEAGRASS)) { ++ BlockEntity tileentity = iblockdata.hasBlockEntity() ? level.getBlockEntity(blockposition1) : null; ++ ++ dropResources(iblockdata, level, blockposition1, tileentity); ++ } ++ } ++ level.setBlock(blockposition1, block.getHandle(), block.getFlag()); ++ } ++ ++ return true; ++ } ++ return false; ++ // CraftBukkit end + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java.patch new file mode 100644 index 0000000000..797b68dd95 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java.patch @@ -0,0 +1,32 @@ +--- a/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java ++++ b/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java +@@ -43,10 +42,14 @@ + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (!canBeGrass(blockstate, serverlevel, blockpos)) { +- serverlevel.setBlockAndUpdate(blockpos, Blocks.DIRT.defaultBlockState()); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (!canBeGrass(state, level, pos)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlockAndUpdate(pos, Blocks.DIRT.defaultBlockState()); + } else { + if (serverlevel.getMaxLocalRawBrightness(blockpos.above()) >= 9) { + BlockState blockstate1 = this.defaultBlockState(); +@@ -54,8 +57,8 @@ + for (int i = 0; i < 4; ++i) { + BlockPos blockpos1 = blockpos.offset(randomsource.nextInt(3) - 1, randomsource.nextInt(5) - 3, randomsource.nextInt(3) - 1); + +- if (serverlevel.getBlockState(blockpos1).is(Blocks.DIRT) && canPropagate(blockstate1, serverlevel, blockpos1)) { +- serverlevel.setBlockAndUpdate(blockpos1, (BlockState) blockstate1.setValue(SpreadingSnowyDirtBlock.SNOWY, serverlevel.getBlockState(blockpos1.above()).is(Blocks.SNOW))); ++ if (level.getBlockState(blockposition1).is(Blocks.DIRT) && canPropagate(iblockdata1, level, blockposition1)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition1, (IBlockData) iblockdata1.setValue(SpreadingSnowyDirtBlock.SNOWY, level.getBlockState(blockposition1.above()).is(Blocks.SNOW))); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/StemBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/StemBlock.java.patch new file mode 100644 index 0000000000..675d69cf74 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/StemBlock.java.patch @@ -0,0 +1,45 @@ +--- a/net/minecraft/world/level/block/StemBlock.java ++++ b/net/minecraft/world/level/block/StemBlock.java +@@ -26,6 +26,7 @@ + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class StemBlock extends BushBlock implements BonemealableBlock { + +@@ -82,8 +79,8 @@ + int i = (Integer) blockstate.getValue(StemBlock.AGE); + + if (i < 7) { +- blockstate = (BlockState) blockstate.setValue(StemBlock.AGE, i + 1); +- serverlevel.setBlock(blockpos, blockstate, 2); ++ state = (IBlockData) state.setValue(StemBlock.AGE, i + 1); ++ CraftEventFactory.handleBlockGrowEvent(level, pos, state, 2); // CraftBukkit + } else { + Direction direction = Direction.Plane.HORIZONTAL.getRandomDirection(randomsource); + BlockPos blockpos1 = blockpos.relative(direction); +@@ -95,8 +92,12 @@ + Optional optional1 = registry.getOptional(this.attachedStem); + + if (optional.isPresent() && optional1.isPresent()) { +- serverlevel.setBlockAndUpdate(blockpos1, ((Block) optional.get()).defaultBlockState()); +- serverlevel.setBlockAndUpdate(blockpos, (BlockState) ((Block) optional1.get()).defaultBlockState().setValue(HorizontalDirectionalBlock.FACING, direction)); ++ // CraftBukkit start ++ if (!CraftEventFactory.handleBlockGrowEvent(level, blockposition1, ((Block) optional.get()).defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlockAndUpdate(pos, (IBlockData) ((Block) optional1.get()).defaultBlockState().setValue(HorizontalDirectionalBlock.FACING, enumdirection)); + } + } + } +@@ -129,7 +126,7 @@ + int i = Math.min(7, (Integer) blockstate.getValue(StemBlock.AGE) + Mth.nextInt(serverlevel.random, 2, 5)); + BlockState blockstate1 = (BlockState) blockstate.setValue(StemBlock.AGE, i); + +- serverlevel.setBlock(blockpos, blockstate1, 2); ++ CraftEventFactory.handleBlockGrowEvent(level, pos, iblockdata1, 2); // CraftBukkit + if (i == 7) { + blockstate1.randomTick(serverlevel, blockpos, serverlevel.random); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SugarCaneBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SugarCaneBlock.java.patch new file mode 100644 index 0000000000..eb1ae72ea2 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SugarCaneBlock.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/level/block/SugarCaneBlock.java ++++ b/net/minecraft/world/level/block/SugarCaneBlock.java +@@ -67,8 +63,8 @@ + int j = (Integer) blockstate.getValue(SugarCaneBlock.AGE); + + if (j == 15) { +- serverlevel.setBlockAndUpdate(blockpos.above(), this.defaultBlockState()); +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(SugarCaneBlock.AGE, 0), 4); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos.above(), this.defaultBlockState()); // CraftBukkit ++ level.setBlock(pos, (IBlockData) state.setValue(SugarCaneBlock.AGE, 0), 4); + } else { + serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(SugarCaneBlock.AGE, j + 1), 4); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SweetBerryBushBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SweetBerryBushBlock.java.patch new file mode 100644 index 0000000000..d260cf1c58 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/SweetBerryBushBlock.java.patch @@ -0,0 +1,58 @@ +--- a/net/minecraft/world/level/block/SweetBerryBushBlock.java ++++ b/net/minecraft/world/level/block/SweetBerryBushBlock.java +@@ -27,6 +27,13 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import java.util.Collections; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerHarvestBlockEvent; ++// CraftBukkit end + + public class SweetBerryBushBlock extends BushBlock implements BonemealableBlock { + +@@ -74,8 +76,8 @@ + if (i < 3 && randomsource.nextInt(5) == 0 && serverlevel.getRawBrightness(blockpos.above(), 0) >= 9) { + BlockState blockstate1 = (BlockState) blockstate.setValue(SweetBerryBushBlock.AGE, i + 1); + +- serverlevel.setBlock(blockpos, blockstate1, 2); +- serverlevel.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(blockstate1)); ++ if (!CraftEventFactory.handleBlockGrowEvent(level, pos, iblockdata1, 2)) return; // CraftBukkit ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(iblockdata1)); + } + + } +@@ -90,7 +91,9 @@ + double d1 = Math.abs(entity.getZ() - entity.zOld); + + if (d0 >= 0.003000000026077032D || d1 >= 0.003000000026077032D) { ++ CraftEventFactory.blockDamage = CraftBlock.at(level, pos); // CraftBukkit + entity.hurt(level.damageSources().sweetBerryBush(), 1.0F); ++ CraftEventFactory.blockDamage = null; // CraftBukkit + } + } + +@@ -108,9 +110,17 @@ + } else if (i > 1) { + int j = 1 + level.random.nextInt(2); + +- popResource(level, blockpos, new ItemStack(Items.SWEET_BERRIES, j + (flag ? 1 : 0))); +- level.playSound((Player) null, blockpos, SoundEvents.SWEET_BERRY_BUSH_PICK_BERRIES, SoundSource.BLOCKS, 1.0F, 0.8F + level.random.nextFloat() * 0.4F); +- BlockState blockstate1 = (BlockState) blockstate.setValue(SweetBerryBushBlock.AGE, 1); ++ // CraftBukkit start ++ PlayerHarvestBlockEvent event = CraftEventFactory.callPlayerHarvestBlockEvent(level, pos, player, hand, Collections.singletonList(new ItemStack(Items.SWEET_BERRIES, j + (flag ? 1 : 0)))); ++ if (event.isCancelled()) { ++ return InteractionResult.SUCCESS; // We need to return a success either way, because making it PASS or FAIL will result in a bug where cancelling while harvesting w/ block in hand places block ++ } ++ for (org.bukkit.inventory.ItemStack itemStack : event.getItemsHarvested()) { ++ popResource(level, pos, CraftItemStack.asNMSCopy(itemStack)); ++ } ++ // CraftBukkit end ++ level.playSound((Player) null, pos, SoundEvents.SWEET_BERRY_BUSH_PICK_BERRIES, SoundSource.BLOCKS, 1.0F, 0.8F + level.random.nextFloat() * 0.4F); ++ IBlockData iblockdata1 = (IBlockData) state.setValue(SweetBerryBushBlock.AGE, 1); + + level.setBlock(blockpos, blockstate1, 2); + level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(player, blockstate1)); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/TntBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/TntBlock.java.patch new file mode 100644 index 0000000000..e7df5b1fff --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/TntBlock.java.patch @@ -0,0 +1,92 @@ +--- a/net/minecraft/world/level/block/TntBlock.java ++++ b/net/minecraft/world/level/block/TntBlock.java +@@ -25,6 +25,10 @@ + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.BlockHitResult; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.block.TNTPrimeEvent.PrimeCause; ++// CraftBukkit end + + public class TntBlock extends Block { + +@@ -43,32 +46,29 @@ + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!blockstate1.is(blockstate.getBlock())) { +- if (level.hasNeighborSignal(blockpos)) { +- explode(level, blockpos); +- level.removeBlock(blockpos, false); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ if (!oldState.is(state.getBlock())) { ++ if (level.hasNeighborSignal(pos) && CraftEventFactory.callTNTPrimeEvent(level, pos, PrimeCause.REDSTONE, null, null)) { // CraftBukkit - TNTPrimeEvent ++ explode(level, pos); ++ level.removeBlock(pos, false); + } + + } + } + + @Override +- @Override +- public void neighborChanged(BlockState blockstate, Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { +- if (level.hasNeighborSignal(blockpos)) { +- explode(level, blockpos); +- level.removeBlock(blockpos, false); ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ if (level.hasNeighborSignal(pos) && CraftEventFactory.callTNTPrimeEvent(level, pos, PrimeCause.REDSTONE, null, fromPos)) { // CraftBukkit - TNTPrimeEvent ++ explode(level, pos); ++ level.removeBlock(pos, false); + } + + } + + @Override +- @Override +- public BlockState playerWillDestroy(Level level, BlockPos blockpos, BlockState blockstate, Player player) { +- if (!level.isClientSide() && !player.isCreative() && (Boolean) blockstate.getValue(TntBlock.UNSTABLE)) { +- explode(level, blockpos); ++ public IBlockData playerWillDestroy(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ if (!world.isClientSide() && !entityhuman.isCreative() && (Boolean) iblockdata.getValue(TntBlock.UNSTABLE) && CraftEventFactory.callTNTPrimeEvent(world, blockposition, PrimeCause.BLOCK_BREAK, entityhuman, null)) { // CraftBukkit - TNTPrimeEvent ++ explode(world, blockposition); + } + + return super.playerWillDestroy(level, blockpos, blockstate, player); +@@ -108,8 +106,13 @@ + if (!itemstack.is(Items.FLINT_AND_STEEL) && !itemstack.is(Items.FIRE_CHARGE)) { + return super.use(blockstate, level, blockpos, player, interactionhand, blockhitresult); + } else { +- explode(level, blockpos, player); +- level.setBlock(blockpos, Blocks.AIR.defaultBlockState(), 11); ++ // CraftBukkit start - TNTPrimeEvent ++ if (!CraftEventFactory.callTNTPrimeEvent(level, pos, PrimeCause.PLAYER, player, null)) { ++ return InteractionResult.CONSUME; ++ } ++ // CraftBukkit end ++ explode(level, pos, player); ++ level.setBlock(pos, Blocks.AIR.defaultBlockState(), 11); + Item item = itemstack.getItem(); + + if (!player.isCreative()) { +@@ -134,9 +136,14 @@ + BlockPos blockpos = blockhitresult.getBlockPos(); + Entity entity = projectile.getOwner(); + +- if (projectile.isOnFire() && projectile.mayInteract(level, blockpos)) { +- explode(level, blockpos, entity instanceof LivingEntity ? (LivingEntity) entity : null); +- level.removeBlock(blockpos, false); ++ if (projectile.isOnFire() && projectile.mayInteract(level, blockposition)) { ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, Blocks.AIR.defaultBlockState()) || !CraftEventFactory.callTNTPrimeEvent(level, blockposition, PrimeCause.PROJECTILE, projectile, null)) { ++ return; ++ } ++ // CraftBukkit end ++ explode(level, blockposition, entity instanceof LivingEntity ? (LivingEntity) entity : null); ++ level.removeBlock(blockposition, false); + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/TrapDoorBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/TrapDoorBlock.java.patch new file mode 100644 index 0000000000..4a84297494 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/TrapDoorBlock.java.patch @@ -0,0 +1,39 @@ +--- a/net/minecraft/world/level/block/TrapDoorBlock.java ++++ b/net/minecraft/world/level/block/TrapDoorBlock.java +@@ -33,6 +33,7 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class TrapDoorBlock extends HorizontalDirectionalBlock implements SimpleWaterloggedBlock { + +@@ -144,11 +139,24 @@ + if (!level.isClientSide) { + boolean flag1 = level.hasNeighborSignal(blockpos); + +- if (flag1 != (Boolean) blockstate.getValue(TrapDoorBlock.POWERED)) { +- if ((Boolean) blockstate.getValue(TrapDoorBlock.OPEN) != flag1) { +- blockstate = (BlockState) blockstate.setValue(TrapDoorBlock.OPEN, flag1); +- this.playSound((Player) null, level, blockpos, flag1); ++ if (flag1 != (Boolean) state.getValue(TrapDoorBlock.POWERED)) { ++ // CraftBukkit start ++ org.bukkit.World bworld = level.getWorld(); ++ org.bukkit.block.Block bblock = bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ ++ int power = bblock.getBlockPower(); ++ int oldPower = (Boolean) state.getValue(OPEN) ? 15 : 0; ++ ++ if (oldPower == 0 ^ power == 0 || block.defaultBlockState().isSignalSource()) { ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bblock, oldPower, power); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ flag1 = eventRedstone.getNewCurrent() > 0; + } ++ // CraftBukkit end ++ if ((Boolean) state.getValue(TrapDoorBlock.OPEN) != flag1) { ++ state = (IBlockData) state.setValue(TrapDoorBlock.OPEN, flag1); ++ this.playSound((Player) null, level, pos, flag1); ++ } + + level.setBlock(blockpos, (BlockState) blockstate.setValue(TrapDoorBlock.POWERED, flag1), 2); + if ((Boolean) blockstate.getValue(TrapDoorBlock.WATERLOGGED)) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/TripWireBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/TripWireBlock.java.patch new file mode 100644 index 0000000000..3872e5202c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/TripWireBlock.java.patch @@ -0,0 +1,51 @@ +--- a/net/minecraft/world/level/block/TripWireBlock.java ++++ b/net/minecraft/world/level/block/TripWireBlock.java +@@ -26,6 +26,7 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.entity.EntityInteractEvent; // CraftBukkit + + public class TripWireBlock extends Block { + +@@ -175,6 +167,40 @@ + } + } + ++ // CraftBukkit start - Call interact even when triggering connected tripwire ++ if (flag != flag1 && flag1 && (Boolean)iblockdata.getValue(ATTACHED)) { ++ org.bukkit.World bworld = level.getWorld(); ++ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager(); ++ org.bukkit.block.Block block = bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ boolean allowed = false; ++ ++ // If all of the events are cancelled block the tripwire trigger, else allow ++ for (Object object : list) { ++ if (object != null) { ++ org.bukkit.event.Cancellable cancellable; ++ ++ if (object instanceof Player) { ++ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) object, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else if (object instanceof Entity) { ++ cancellable = new EntityInteractEvent(((Entity) object).getBukkitEntity(), block); ++ manager.callEvent((EntityInteractEvent) cancellable); ++ } else { ++ continue; ++ } ++ ++ if (!cancellable.isCancelled()) { ++ allowed = true; ++ break; ++ } ++ } ++ } ++ ++ if (!allowed) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ + if (flag1 != flag) { + blockstate = (BlockState) blockstate.setValue(TripWireBlock.POWERED, flag1); + level.setBlock(blockpos, blockstate, 3); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/TripWireHookBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/TripWireHookBlock.java.patch new file mode 100644 index 0000000000..788243b667 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/TripWireHookBlock.java.patch @@ -0,0 +1,39 @@ +--- a/net/minecraft/world/level/block/TripWireHookBlock.java ++++ b/net/minecraft/world/level/block/TripWireHookBlock.java +@@ -28,6 +28,10 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockRedstoneEvent; ++// CraftBukkit end + + public class TripWireHookBlock extends Block { + +@@ -179,11 +177,20 @@ + emitState(level, blockpos1, flag4, flag5, flag2, flag3); + } + +- emitState(level, blockpos, flag4, flag5, flag2, flag3); +- if (!flag) { +- level.setBlock(blockpos, (BlockState) blockstate3.setValue(TripWireHookBlock.FACING, direction), 3); +- if (flag1) { +- notifyNeighbors(block, level, blockpos, direction); ++ // CraftBukkit start ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(world, level), 15, 0); ++ world.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if (eventRedstone.getNewCurrent() > 0) { ++ return; ++ } ++ // CraftBukkit end ++ ++ emitState(world, level, flag4, flag5, flag2, flag3); ++ if (!hookState) { ++ world.setBlock(level, (IBlockData) iblockdata3.setValue(TripWireHookBlock.FACING, enumdirection), 3); ++ if (attaching) { ++ notifyNeighbors(block, world, level, enumdirection); + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/TurtleEggBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/TurtleEggBlock.java.patch new file mode 100644 index 0000000000..3e7b7d98f4 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/TurtleEggBlock.java.patch @@ -0,0 +1,83 @@ +--- a/net/minecraft/world/level/block/TurtleEggBlock.java ++++ b/net/minecraft/world/level/block/TurtleEggBlock.java +@@ -29,6 +29,11 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.event.entity.EntityInteractEvent; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class TurtleEggBlock extends Block { + +@@ -74,8 +76,21 @@ + + private void destroyEgg(Level level, BlockState blockstate, BlockPos blockpos, Entity entity, int i) { + if (this.canDestroyEgg(level, entity)) { +- if (!level.isClientSide && level.random.nextInt(i) == 0 && blockstate.is(Blocks.TURTLE_EGG)) { +- this.decreaseEggs(level, blockpos, blockstate); ++ if (!level.isClientSide && level.random.nextInt(chance) == 0 && state.is(Blocks.TURTLE_EGG)) { ++ // CraftBukkit start - Step on eggs ++ org.bukkit.event.Cancellable cancellable; ++ if (entity instanceof Player) { ++ cancellable = CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), CraftBlock.at(level, pos)); ++ level.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ if (cancellable.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ this.decreaseEggs(level, pos, state); + } + + } +@@ -102,23 +116,33 @@ + int i = (Integer) blockstate.getValue(TurtleEggBlock.HATCH); + + if (i < 2) { +- serverlevel.playSound((Player) null, blockpos, SoundEvents.TURTLE_EGG_CRACK, SoundSource.BLOCKS, 0.7F, 0.9F + randomsource.nextFloat() * 0.2F); +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(TurtleEggBlock.HATCH, i + 1), 2); +- serverlevel.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(blockstate)); ++ // CraftBukkit start - Call BlockGrowEvent ++ if (!CraftEventFactory.handleBlockGrowEvent(level, pos, state.setValue(TurtleEggBlock.HATCH, i + 1), 2)) { ++ return; ++ } ++ // CraftBukkit end ++ level.playSound((Player) null, pos, SoundEvents.TURTLE_EGG_CRACK, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F); ++ // worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockTurtleEgg.HATCH, i + 1), 2); // CraftBukkit - handled above ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(state)); + } else { +- serverlevel.playSound((Player) null, blockpos, SoundEvents.TURTLE_EGG_HATCH, SoundSource.BLOCKS, 0.7F, 0.9F + randomsource.nextFloat() * 0.2F); +- serverlevel.removeBlock(blockpos, false); +- serverlevel.gameEvent(GameEvent.BLOCK_DESTROY, blockpos, GameEvent.Context.of(blockstate)); ++ // CraftBukkit start - Call BlockFadeEvent ++ if (CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.AIR.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.playSound((Player) null, pos, SoundEvents.TURTLE_EGG_HATCH, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F); ++ level.removeBlock(pos, false); ++ level.gameEvent(GameEvent.BLOCK_DESTROY, pos, GameEvent.Context.of(state)); + + for (int j = 0; j < (Integer) blockstate.getValue(TurtleEggBlock.EGGS); ++j) { + serverlevel.levelEvent(2001, blockpos, Block.getId(blockstate)); + Turtle turtle = (Turtle) EntityType.TURTLE.create(serverlevel); + +- if (turtle != null) { +- turtle.setAge(-24000); +- turtle.setHomePos(blockpos); +- turtle.moveTo((double) blockpos.getX() + 0.3D + (double) j * 0.2D, (double) blockpos.getY(), (double) blockpos.getZ() + 0.3D, 0.0F, 0.0F); +- serverlevel.addFreshEntity(turtle); ++ if (entityturtle != null) { ++ entityturtle.setAge(-24000); ++ entityturtle.setHomePos(pos); ++ entityturtle.moveTo((double) pos.getX() + 0.3D + (double) j * 0.2D, (double) pos.getY(), (double) pos.getZ() + 0.3D, 0.0F, 0.0F); ++ level.addFreshEntity(entityturtle, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/VineBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/VineBlock.java.patch new file mode 100644 index 0000000000..f01a593599 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/VineBlock.java.patch @@ -0,0 +1,73 @@ +--- a/net/minecraft/world/level/block/VineBlock.java ++++ b/net/minecraft/world/level/block/VineBlock.java +@@ -24,6 +24,7 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class VineBlock extends Block { + +@@ -209,10 +204,13 @@ + BlockPos blockpos3 = blockpos2.relative(direction1); + BlockPos blockpos4 = blockpos2.relative(direction2); + +- if (flag && isAcceptableNeighbour(serverlevel, blockpos3, direction1)) { +- serverlevel.setBlock(blockpos2, (BlockState) this.defaultBlockState().setValue(getPropertyForFace(direction1), true), 2); +- } else if (flag1 && isAcceptableNeighbour(serverlevel, blockpos4, direction2)) { +- serverlevel.setBlock(blockpos2, (BlockState) this.defaultBlockState().setValue(getPropertyForFace(direction2), true), 2); ++ // CraftBukkit start - Call BlockSpreadEvent ++ BlockPos source = pos; ++ ++ if (flag && isAcceptableNeighbour(level, blockposition3, enumdirection1)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, source, blockposition2, (IBlockData) this.defaultBlockState().setValue(getPropertyForFace(enumdirection1), true), 2); ++ } else if (flag1 && isAcceptableNeighbour(level, blockposition4, enumdirection2)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, source, blockposition2, (IBlockData) this.defaultBlockState().setValue(getPropertyForFace(enumdirection2), true), 2); + } else { + Direction direction3 = direction.getOpposite(); + +@@ -223,16 +221,17 @@ + } else if ((double) randomsource.nextFloat() < 0.05D && isAcceptableNeighbour(serverlevel, blockpos2.above(), Direction.UP)) { + serverlevel.setBlock(blockpos2, (BlockState) this.defaultBlockState().setValue(VineBlock.UP, true), 2); + } ++ // CraftBukkit end + } +- } else if (isAcceptableNeighbour(serverlevel, blockpos2, direction)) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(getPropertyForFace(direction), true), 2); ++ } else if (isAcceptableNeighbour(level, blockposition2, enumdirection)) { ++ CraftEventFactory.handleBlockGrowEvent(level, pos, (IBlockData) state.setValue(getPropertyForFace(enumdirection), true), 2); // CraftBukkit + } + + } + } else { +- if (direction == Direction.UP && blockpos.getY() < serverlevel.getMaxBuildHeight() - 1) { +- if (this.canSupportAtFace(serverlevel, blockpos, direction)) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(VineBlock.UP, true), 2); ++ if (enumdirection == Direction.UP && pos.getY() < level.getMaxBuildHeight() - 1) { ++ if (this.canSupportAtFace(level, pos, enumdirection)) { ++ CraftEventFactory.handleBlockGrowEvent(level, pos, (IBlockData) state.setValue(VineBlock.UP, true), 2); // CraftBukkit + return; + } + +@@ -251,8 +250,8 @@ + } + } + +- if (this.hasHorizontalConnection(blockstate2)) { +- serverlevel.setBlock(blockpos1, blockstate2, 2); ++ if (this.hasHorizontalConnection(iblockdata2)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition1, iblockdata2, 2); // CraftBukkit + } + + return; +@@ -266,8 +265,8 @@ + BlockState blockstate3 = blockstate1.isAir() ? this.defaultBlockState() : blockstate1; + BlockState blockstate4 = this.copyRandomFaces(blockstate, blockstate3, randomsource); + +- if (blockstate3 != blockstate4 && this.hasHorizontalConnection(blockstate4)) { +- serverlevel.setBlock(blockpos2, blockstate4, 2); ++ if (iblockdata3 != iblockdata4 && this.hasHorizontalConnection(iblockdata4)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition2, iblockdata4, 2); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/WallHangingSignBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/WallHangingSignBlock.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/WallHangingSignBlock.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/WaterlilyBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/WaterlilyBlock.java.patch new file mode 100644 index 0000000000..bd171643af --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/WaterlilyBlock.java.patch @@ -0,0 +1,26 @@ +--- a/net/minecraft/world/level/block/WaterlilyBlock.java ++++ b/net/minecraft/world/level/block/WaterlilyBlock.java +@@ -13,6 +13,9 @@ + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class WaterlilyBlock extends BushBlock { + +@@ -34,7 +35,12 @@ + public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { + super.entityInside(blockstate, level, blockpos, entity); + if (level instanceof ServerLevel && entity instanceof Boat) { +- level.destroyBlock(new BlockPos(blockpos), true, entity); ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end ++ level.destroyBlock(new BlockPos(pos), true, entity); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/WeightedPressurePlateBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/WeightedPressurePlateBlock.java.patch new file mode 100644 index 0000000000..6988256183 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/WeightedPressurePlateBlock.java.patch @@ -0,0 +1,44 @@ +--- a/net/minecraft/world/level/block/WeightedPressurePlateBlock.java ++++ b/net/minecraft/world/level/block/WeightedPressurePlateBlock.java +@@ -13,6 +14,8 @@ + import net.minecraft.world.level.block.state.properties.BlockSetType; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end + + public class WeightedPressurePlateBlock extends BasePressurePlateBlock { + +@@ -39,10 +41,29 @@ + } + + @Override +- @Override +- protected int getSignalStrength(Level level, BlockPos blockpos) { +- int i = Math.min(getEntityCount(level, WeightedPressurePlateBlock.TOUCH_AABB.move(blockpos), Entity.class), this.maxWeight); ++ protected int getSignalStrength(Level level, BlockPos pos) { ++ // CraftBukkit start ++ // int i = Math.min(getEntityCount(world, BlockPressurePlateWeighted.TOUCH_AABB.move(blockposition), Entity.class), this.maxWeight); ++ int i = 0; ++ for (Entity entity : getEntities(level, WeightedPressurePlateBlock.TOUCH_AABB.move(pos), Entity.class)) { ++ org.bukkit.event.Cancellable cancellable; + ++ if (entity instanceof Player) { ++ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ // We only want to block turning the plate on if all events are cancelled ++ if (!cancellable.isCancelled()) { ++ i++; ++ } ++ } ++ ++ i = Math.min(i, this.maxWeight); ++ // CraftBukkit end ++ + if (i > 0) { + float f = (float) Math.min(this.maxWeight, i) / (float) this.maxWeight; + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/WitherRoseBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/WitherRoseBlock.java.patch new file mode 100644 index 0000000000..894b9d58f3 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/WitherRoseBlock.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/level/block/WitherRoseBlock.java ++++ b/net/minecraft/world/level/block/WitherRoseBlock.java +@@ -69,8 +65,8 @@ + if (entity instanceof LivingEntity) { + LivingEntity livingentity = (LivingEntity) entity; + +- if (!livingentity.isInvulnerableTo(level.damageSources().wither())) { +- livingentity.addEffect(new MobEffectInstance(MobEffects.WITHER, 40)); ++ if (!entityliving.isInvulnerableTo(level.damageSources().wither())) { ++ entityliving.addEffect(new MobEffectInstance(MobEffects.WITHER, 40), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.WITHER_ROSE); // CraftBukkit + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/WitherSkullBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/WitherSkullBlock.java.patch new file mode 100644 index 0000000000..f646cfcc54 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/WitherSkullBlock.java.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/level/block/WitherSkullBlock.java ++++ b/net/minecraft/world/level/block/WitherSkullBlock.java +@@ -25,6 +25,10 @@ + import net.minecraft.world.level.block.state.pattern.BlockPatternBuilder; + import net.minecraft.world.level.block.state.predicate.BlockStatePredicate; + ++// CraftBukkit start ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; ++// CraftBukkit end ++ + public class WitherSkullBlock extends SkullBlock { + + public static final MapCodec CODEC = simpleCodec(WitherSkullBlock::new); +@@ -55,7 +57,8 @@ + + } + +- public static void checkSpawn(Level level, BlockPos blockpos, SkullBlockEntity skullblockentity) { ++ public static void checkSpawn(Level level, BlockPos pos, SkullBlockEntity blockEntity) { ++ if (level.captureBlockStates) return; // CraftBukkit + if (!level.isClientSide) { + BlockState blockstate = skullblockentity.getBlockState(); + boolean flag = blockstate.is(Blocks.WITHER_SKELETON_SKULL) || blockstate.is(Blocks.WITHER_SKELETON_WALL_SKULL); +@@ -66,14 +69,20 @@ + if (blockpattern_blockpatternmatch != null) { + WitherBoss witherboss = (WitherBoss) EntityType.WITHER.create(level); + +- if (witherboss != null) { +- CarvedPumpkinBlock.clearPatternBlocks(level, blockpattern_blockpatternmatch); +- BlockPos blockpos1 = blockpattern_blockpatternmatch.getBlock(1, 2, 0).getPos(); ++ if (entitywither != null) { ++ // BlockPumpkinCarved.clearPatternBlocks(world, shapedetector_shapedetectorcollection); // CraftBukkit - move down ++ BlockPos blockposition1 = shapedetector_shapedetectorcollection.getBlock(1, 2, 0).getPos(); + +- witherboss.moveTo((double) blockpos1.getX() + 0.5D, (double) blockpos1.getY() + 0.55D, (double) blockpos1.getZ() + 0.5D, blockpattern_blockpatternmatch.getForwards().getAxis() == Direction.Axis.X ? 0.0F : 90.0F, 0.0F); +- witherboss.yBodyRot = blockpattern_blockpatternmatch.getForwards().getAxis() == Direction.Axis.X ? 0.0F : 90.0F; +- witherboss.makeInvulnerable(); +- Iterator iterator = level.getEntitiesOfClass(ServerPlayer.class, witherboss.getBoundingBox().inflate(50.0D)).iterator(); ++ entitywither.moveTo((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.55D, (double) blockposition1.getZ() + 0.5D, shapedetector_shapedetectorcollection.getForwards().getAxis() == Direction.Axis.X ? 0.0F : 90.0F, 0.0F); ++ entitywither.yBodyRot = shapedetector_shapedetectorcollection.getForwards().getAxis() == Direction.Axis.X ? 0.0F : 90.0F; ++ entitywither.makeInvulnerable(); ++ // CraftBukkit start ++ if (!level.addFreshEntity(entitywither, SpawnReason.BUILD_WITHER)) { ++ return; ++ } ++ CarvedPumpkinBlock.clearPatternBlocks(level, shapedetector_shapedetectorcollection); // CraftBukkit - from above ++ // CraftBukkit end ++ Iterator iterator = level.getEntitiesOfClass(ServerPlayer.class, entitywither.getBoundingBox().inflate(50.0D)).iterator(); + + while (iterator.hasNext()) { + ServerPlayer serverplayer = (ServerPlayer) iterator.next(); +@@ -81,8 +90,8 @@ + CriteriaTriggers.SUMMONED_ENTITY.trigger(serverplayer, (Entity) witherboss); + } + +- level.addFreshEntity(witherboss); +- CarvedPumpkinBlock.updatePatternBlocks(level, blockpattern_blockpatternmatch); ++ // world.addFreshEntity(entitywither); // CraftBukkit - moved up ++ CarvedPumpkinBlock.updatePatternBlocks(level, shapedetector_shapedetectorcollection); + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java.patch new file mode 100644 index 0000000000..50074c84ea --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java.patch @@ -0,0 +1,244 @@ +--- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -46,6 +45,19 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.block.BlockExpEvent; ++import org.bukkit.event.inventory.FurnaceBurnEvent; ++import org.bukkit.event.inventory.FurnaceExtractEvent; ++import org.bukkit.event.inventory.FurnaceSmeltEvent; ++import org.bukkit.event.inventory.FurnaceStartSmeltEvent; ++import org.bukkit.inventory.CookingRecipe; ++// CraftBukkit end + + public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntity implements WorldlyContainer, RecipeCraftingHolder, StackedContentsCompatible { + +@@ -186,6 +195,40 @@ + return map; + } + ++ // CraftBukkit start - add fields and methods ++ private int maxStack = MAX_STACK; ++ public List transaction = new java.util.ArrayList(); ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ public Object2IntOpenHashMap getRecipesUsed() { ++ return this.recipesUsed; // PAIL private -> public ++ } ++ // CraftBukkit end ++ + private static boolean isNeverAFurnaceFuel(Item item) { + return item.builtInRegistryHolder().is(ItemTags.NON_FLAMMABLE_WOOD); + } +@@ -283,10 +324,21 @@ + + int i = abstractfurnaceblockentity.getMaxStackSize(); + +- if (!abstractfurnaceblockentity.isLit() && canBurn(level.registryAccess(), recipeholder, abstractfurnaceblockentity.items, i)) { +- abstractfurnaceblockentity.litTime = abstractfurnaceblockentity.getBurnDuration(itemstack); +- abstractfurnaceblockentity.litDuration = abstractfurnaceblockentity.litTime; +- if (abstractfurnaceblockentity.isLit()) { ++ if (!blockEntity.isLit() && canBurn(level.registryAccess(), recipeholder, blockEntity.items, i)) { ++ // CraftBukkit start ++ CraftItemStack fuel = CraftItemStack.asCraftMirror(itemstack); ++ ++ FurnaceBurnEvent furnaceBurnEvent = new FurnaceBurnEvent(CraftBlock.at(level, pos), fuel, blockEntity.getBurnDuration(itemstack)); ++ level.getCraftServer().getPluginManager().callEvent(furnaceBurnEvent); ++ ++ if (furnaceBurnEvent.isCancelled()) { ++ return; ++ } ++ ++ blockEntity.litTime = furnaceBurnEvent.getBurnTime(); ++ blockEntity.litDuration = blockEntity.litTime; ++ if (blockEntity.isLit() && furnaceBurnEvent.isBurning()) { ++ // CraftBukkit end + flag1 = true; + if (flag3) { + Item item = itemstack.getItem(); +@@ -301,13 +353,25 @@ + } + } + +- if (abstractfurnaceblockentity.isLit() && canBurn(level.registryAccess(), recipeholder, abstractfurnaceblockentity.items, i)) { +- ++abstractfurnaceblockentity.cookingProgress; +- if (abstractfurnaceblockentity.cookingProgress == abstractfurnaceblockentity.cookingTotalTime) { +- abstractfurnaceblockentity.cookingProgress = 0; +- abstractfurnaceblockentity.cookingTotalTime = getTotalCookTime(level, abstractfurnaceblockentity); +- if (burn(level.registryAccess(), recipeholder, abstractfurnaceblockentity.items, i)) { +- abstractfurnaceblockentity.setRecipeUsed(recipeholder); ++ if (blockEntity.isLit() && canBurn(level.registryAccess(), recipeholder, blockEntity.items, i)) { ++ // CraftBukkit start ++ if (recipeholder != null && blockEntity.cookingProgress == 0) { ++ CraftItemStack source = CraftItemStack.asCraftMirror(blockEntity.items.get(0)); ++ CookingRecipe recipe = (CookingRecipe) recipeholder.toBukkitRecipe(); ++ ++ FurnaceStartSmeltEvent event = new FurnaceStartSmeltEvent(CraftBlock.at(level, pos), source, recipe); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ blockEntity.cookingTotalTime = event.getTotalCookTime(); ++ } ++ // CraftBukkit end ++ ++ ++blockEntity.cookingProgress; ++ if (blockEntity.cookingProgress == blockEntity.cookingTotalTime) { ++ blockEntity.cookingProgress = 0; ++ blockEntity.cookingTotalTime = getTotalCookTime(level, blockEntity); ++ if (burn(blockEntity.level, blockEntity.worldPosition, level.registryAccess(), recipeholder, blockEntity.items, i)) { // CraftBukkit ++ blockEntity.setRecipeUsed(recipeholder); + } + + flag1 = true; +@@ -345,17 +409,44 @@ + } + } + +- private static boolean burn(RegistryAccess registryaccess, @Nullable RecipeHolder recipeholder, NonNullList nonnulllist, int i) { +- if (recipeholder != null && canBurn(registryaccess, recipeholder, nonnulllist, i)) { ++ private static boolean burn(Level world, BlockPos blockposition, RegistryAccess iregistrycustom, @Nullable RecipeHolder recipeholder, NonNullList nonnulllist, int i) { // CraftBukkit ++ if (recipeholder != null && canBurn(iregistrycustom, recipeholder, nonnulllist, i)) { + ItemStack itemstack = (ItemStack) nonnulllist.get(0); + ItemStack itemstack1 = recipeholder.value().getResultItem(registryaccess); + ItemStack itemstack2 = (ItemStack) nonnulllist.get(2); + ++ // CraftBukkit start - fire FurnaceSmeltEvent ++ CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); ++ org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); ++ ++ FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(CraftBlock.at(world, blockposition), source, result); ++ world.getCraftServer().getPluginManager().callEvent(furnaceSmeltEvent); ++ ++ if (furnaceSmeltEvent.isCancelled()) { ++ return false; ++ } ++ ++ result = furnaceSmeltEvent.getResult(); ++ itemstack1 = CraftItemStack.asNMSCopy(result); ++ ++ if (!itemstack1.isEmpty()) { ++ if (itemstack2.isEmpty()) { ++ nonnulllist.set(2, itemstack1.copy()); ++ } else if (CraftItemStack.asCraftMirror(itemstack2).isSimilar(result)) { ++ itemstack2.grow(itemstack1.getCount()); ++ } else { ++ return false; ++ } ++ } ++ ++ /* + if (itemstack2.isEmpty()) { + nonnulllist.set(2, itemstack1.copy()); + } else if (itemstack2.is(itemstack1.getItem())) { + itemstack2.grow(1); + } ++ */ ++ // CraftBukkit end + + if (itemstack.is(Blocks.WET_SPONGE.asItem()) && !((ItemStack) nonnulllist.get(1)).isEmpty() && ((ItemStack) nonnulllist.get(1)).is(Items.BUCKET)) { + nonnulllist.set(1, new ItemStack(Items.WATER_BUCKET)); +@@ -378,8 +469,9 @@ + } + } + +- private static int getTotalCookTime(Level level, AbstractFurnaceBlockEntity abstractfurnaceblockentity) { +- return (Integer) abstractfurnaceblockentity.quickCheck.getRecipeFor(abstractfurnaceblockentity, level).map((recipeholder) -> { ++ private static int getTotalCookTime(Level level, AbstractFurnaceBlockEntity blockEntity) { ++ if (level == null) return 200; // CraftBukkit - SPIGOT-4302 ++ return (Integer) blockEntity.quickCheck.getRecipeFor(blockEntity, level).map((recipeholder) -> { + return ((AbstractCookingRecipe) recipeholder.value()).getCookingTime(); + }).orElse(200); + } +@@ -515,8 +592,8 @@ + @Override + public void awardUsedRecipes(Player player, List list) {} + +- public void awardUsedRecipesAndPopExperience(ServerPlayer serverplayer) { +- List> list = this.getRecipesToAwardAndPopExperience(serverplayer.serverLevel(), serverplayer.position()); ++ public void awardUsedRecipesAndPopExperience(ServerPlayer entityplayer, ItemStack itemstack, int amount) { // CraftBukkit ++ List> list = this.getRecipesToAwardAndPopExperience(entityplayer.serverLevel(), entityplayer.position(), this.worldPosition, entityplayer, itemstack, amount); // CraftBukkit + + serverplayer.awardRecipes(list); + Iterator iterator = list.iterator(); +@@ -532,7 +609,13 @@ + this.recipesUsed.clear(); + } + +- public List> getRecipesToAwardAndPopExperience(ServerLevel serverlevel, Vec3 vec3) { ++ public List> getRecipesToAwardAndPopExperience(ServerLevel level, Vec3 popVec) { ++ // CraftBukkit start ++ return this.getRecipesToAwardAndPopExperience(level, popVec, this.worldPosition, null, null, 0); ++ } ++ ++ public List> getRecipesToAwardAndPopExperience(ServerLevel worldserver, Vec3 vec3d, BlockPos blockposition, ServerPlayer entityplayer, ItemStack itemstack, int amount) { ++ // CraftBukkit end + List> list = Lists.newArrayList(); + ObjectIterator objectiterator = this.recipesUsed.object2IntEntrySet().iterator(); + +@@ -541,14 +624,14 @@ + + serverlevel.getRecipeManager().byKey((ResourceLocation) entry.getKey()).ifPresent((recipeholder) -> { + list.add(recipeholder); +- createExperience(serverlevel, vec3, entry.getIntValue(), ((AbstractCookingRecipe) recipeholder.value()).getExperience()); ++ createExperience(worldserver, vec3d, entry.getIntValue(), ((AbstractCookingRecipe) recipeholder.value()).getExperience(), blockposition, entityplayer, itemstack, amount); // CraftBukkit + }); + } + + return list; + } + +- private static void createExperience(ServerLevel serverlevel, Vec3 vec3, int i, float f) { ++ private static void createExperience(ServerLevel worldserver, Vec3 vec3d, int i, float f, BlockPos blockposition, net.minecraft.world.entity.player.Player entityhuman, ItemStack itemstack, int amount) { // CraftBukkit + int j = Mth.floor((float) i * f); + float f1 = Mth.frac((float) i * f); + +@@ -556,7 +639,18 @@ + ++j; + } + +- ExperienceOrb.award(serverlevel, vec3, j); ++ // CraftBukkit start - fire FurnaceExtractEvent / BlockExpEvent ++ BlockExpEvent event; ++ if (amount != 0) { ++ event = new FurnaceExtractEvent((Player) entityhuman.getBukkitEntity(), CraftBlock.at(worldserver, blockposition), org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(itemstack.getItem()), amount, j); ++ } else { ++ event = new BlockExpEvent(CraftBlock.at(worldserver, blockposition), j); ++ } ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ j = event.getExpToDrop(); ++ // CraftBukkit end ++ ++ ExperienceOrb.award(worldserver, vec3d, j); + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BannerBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BannerBlockEntity.java.patch new file mode 100644 index 0000000000..64cfabdde0 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BannerBlockEntity.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/level/block/entity/BannerBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BannerBlockEntity.java +@@ -105,7 +101,12 @@ + this.name = Component.Serializer.fromJson(compoundtag.getString("CustomName")); + } + +- this.itemPatterns = compoundtag.getList("Patterns", 10); ++ this.itemPatterns = tag.getList("Patterns", 10); ++ // CraftBukkit start ++ while (this.itemPatterns.size() > 20) { ++ this.itemPatterns.remove(20); ++ } ++ // CraftBukkit end + this.patterns = null; + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BarrelBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BarrelBlockEntity.java.patch new file mode 100644 index 0000000000..e17aee50b9 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BarrelBlockEntity.java.patch @@ -0,0 +1,52 @@ +--- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java +@@ -20,8 +20,49 @@ + import net.minecraft.world.level.block.BarrelBlock; + import net.minecraft.world.level.block.state.BlockState; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class BarrelBlockEntity extends RandomizableContainerBlockEntity { + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new ArrayList<>(); ++ private int maxStack = MAX_STACK; ++ ++ @Override ++ public List getContents() { ++ return this.items; ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ @Override ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ // CraftBukkit end + private NonNullList items; + private final ContainerOpenersCounter openersCounter; + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java.patch new file mode 100644 index 0000000000..fc78cc82b4 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java +@@ -95,4 +89,12 @@ + } + + protected abstract AbstractContainerMenu createMenu(int containerId, Inventory inventory); ++ ++ // CraftBukkit start ++ @Override ++ public org.bukkit.Location getLocation() { ++ if (level == null) return null; ++ return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BeaconBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BeaconBlockEntity.java.patch new file mode 100644 index 0000000000..81e9f2bf96 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BeaconBlockEntity.java.patch @@ -0,0 +1,80 @@ +--- a/net/minecraft/world/level/block/entity/BeaconBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +@@ -39,6 +39,10 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.levelgen.Heightmap; + import net.minecraft.world.phys.AABB; ++// CraftBukkit start ++import org.bukkit.craftbukkit.potion.CraftPotionUtil; ++import org.bukkit.potion.PotionEffect; ++// CraftBukkit end + + public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Nameable { + +@@ -65,7 +69,16 @@ + private Component name; + private LockCode lockKey; + private final ContainerData dataAccess; ++ // CraftBukkit start - add fields and methods ++ public PotionEffect getPrimaryEffect() { ++ return (this.primaryPower != null) ? CraftPotionUtil.toBukkit(new MobEffectInstance(this.primaryPower, getLevel(this.levels), getAmplification(levels, primaryPower, secondaryPower), true, true)) : null; ++ } + ++ public PotionEffect getSecondaryEffect() { ++ return (hasSecondaryEffect(levels, primaryPower, secondaryPower)) ? CraftPotionUtil.toBukkit(new MobEffectInstance(this.secondaryPower, getLevel(this.levels), getAmplification(levels, primaryPower, secondaryPower), true, true)) : null; ++ } ++ // CraftBukkit end ++ + @Nullable + static MobEffect filterEffect(@Nullable MobEffect mobeffect) { + return BeaconBlockEntity.VALID_EFFECTS.contains(mobeffect) ? mobeffect : null; +@@ -249,9 +258,9 @@ + super.setRemoved(); + } + +- private static void applyEffects(Level level, BlockPos blockpos, int i, @Nullable MobEffect mobeffect, @Nullable MobEffect mobeffect1) { +- if (!level.isClientSide && mobeffect != null) { +- double d0 = (double) (i * 10 + 10); ++ // CraftBukkit start - split into components ++ private static byte getAmplification(int i, @Nullable MobEffect mobeffectlist, @Nullable MobEffect mobeffectlist1) { ++ { + byte b0 = 0; + + if (i >= 4 && mobeffect == mobeffect1) { +@@ -285,6 +328,7 @@ + public static void playSound(Level level, BlockPos blockpos, SoundEvent soundevent) { + level.playSound((Player) null, blockpos, soundevent, SoundSource.BLOCKS, 1.0F, 1.0F); + } ++ // CraftBukkit end + + public List getBeamSections() { + return (List) (this.levels == 0 ? ImmutableList.of() : this.beamSections); +@@ -318,20 +364,20 @@ + if (compoundtag.contains(s, 8)) { + ResourceLocation resourcelocation = ResourceLocation.tryParse(compoundtag.getString(s)); + +- return filterEffect((MobEffect) BuiltInRegistries.MOB_EFFECT.get(resourcelocation)); ++ return (MobEffect) BuiltInRegistries.MOB_EFFECT.get(minecraftkey); // CraftBukkit - persist manually set non-default beacon effects (SPIGOT-3598) + } else { + return null; + } + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); +- this.primaryPower = loadEffect(compoundtag, "primary_effect"); +- this.secondaryPower = loadEffect(compoundtag, "secondary_effect"); +- if (compoundtag.contains("CustomName", 8)) { +- this.name = Component.Serializer.fromJson(compoundtag.getString("CustomName")); ++ public void load(CompoundTag tag) { ++ super.load(tag); ++ this.primaryPower = loadEffect(tag, "primary_effect"); ++ this.secondaryPower = loadEffect(tag, "secondary_effect"); ++ this.levels = tag.getInt("Levels"); // CraftBukkit - SPIGOT-5053, use where available ++ if (tag.contains("CustomName", 8)) { ++ this.name = Component.Serializer.fromJson(tag.getString("CustomName")); + } + + this.lockKey = LockCode.fromTag(compoundtag); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java.patch new file mode 100644 index 0000000000..754d608776 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java.patch @@ -0,0 +1,174 @@ +--- a/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java +@@ -42,7 +42,8 @@ + public static final int MIN_OCCUPATION_TICKS_NECTARLESS = 600; + private final List stored = Lists.newArrayList(); + @Nullable +- private BlockPos savedFlowerPos; ++ public BlockPos savedFlowerPos; ++ public int maxBees = 3; // CraftBukkit - allow setting max amount of bees a hive can hold + + public BeehiveBlockEntity(BlockPos blockpos, BlockState blockstate) { + super(BlockEntityType.BEEHIVE, blockpos, blockstate); +@@ -83,7 +83,7 @@ + } + + public boolean isFull() { +- return this.stored.size() == 3; ++ return this.stored.size() == this.maxBees; // CraftBukkit + } + + public void emptyAllLivingFromHive(@Nullable Player player, BlockState blockstate, BeehiveBlockEntity.BeeReleaseStatus beehiveblockentity_beereleasestatus) { +@@ -100,7 +100,7 @@ + + if (player.position().distanceToSqr(entity.position()) <= 16.0D) { + if (!this.isSedated()) { +- bee.setTarget(player); ++ entitybee.setTarget(player, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit + } else { + bee.setStayOutOfHiveCountdown(400); + } +@@ -111,11 +111,17 @@ + + } + +- private List releaseAllOccupants(BlockState blockstate, BeehiveBlockEntity.BeeReleaseStatus beehiveblockentity_beereleasestatus) { ++ private List releaseAllOccupants(IBlockData state, BeehiveBlockEntity.ReleaseStatus releaseStatus) { ++ // CraftBukkit start - This allows us to bypass the night/rain/emergency check ++ return releaseBees(state, releaseStatus, false); ++ } ++ ++ public List releaseBees(IBlockData iblockdata, BeehiveBlockEntity.ReleaseStatus tileentitybeehive_releasestatus, boolean force) { + List list = Lists.newArrayList(); + +- this.stored.removeIf((beehiveblockentity_beedata) -> { +- return releaseOccupant(this.level, this.worldPosition, blockstate, beehiveblockentity_beedata, list, beehiveblockentity_beereleasestatus, this.savedFlowerPos); ++ this.stored.removeIf((tileentitybeehive_hivebee) -> { ++ return releaseBee(this.level, this.worldPosition, iblockdata, tileentitybeehive_hivebee, list, tileentitybeehive_releasestatus, this.savedFlowerPos, force); ++ // CraftBukkit end + }); + if (!list.isEmpty()) { + super.setChanged(); +@@ -142,11 +148,23 @@ + return CampfireBlock.isSmokeyPos(this.level, this.getBlockPos()); + } + +- public void addOccupantWithPresetTicks(Entity entity, boolean flag, int i) { +- if (this.stored.size() < 3) { +- entity.stopRiding(); +- entity.ejectPassengers(); +- CompoundTag compoundtag = new CompoundTag(); ++ public void addOccupantWithPresetTicks(Entity occupant, boolean hasNectar, int ticksInHive) { ++ if (this.stored.size() < this.maxBees) { // CraftBukkit ++ // CraftBukkit start ++ if (this.level != null) { ++ org.bukkit.event.entity.EntityEnterBlockEvent event = new org.bukkit.event.entity.EntityEnterBlockEvent(occupant.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, getBlockPos())); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ if (occupant instanceof Bee) { ++ ((Bee) occupant).setStayOutOfHiveCountdown(400); ++ } ++ return; ++ } ++ } ++ // CraftBukkit end ++ occupant.stopRiding(); ++ occupant.ejectPassengers(); ++ CompoundTag nbttagcompound = new CompoundTag(); + + entity.save(compoundtag); + this.storeBee(compoundtag, i, flag); +@@ -174,8 +192,14 @@ + this.stored.add(new BeehiveBlockEntity.BeeData(compoundtag, i, flag ? 2400 : 600)); + } + +- private static boolean releaseOccupant(Level level, BlockPos blockpos, BlockState blockstate, BeehiveBlockEntity.BeeData beehiveblockentity_beedata, @Nullable List list, BeehiveBlockEntity.BeeReleaseStatus beehiveblockentity_beereleasestatus, @Nullable BlockPos blockpos1) { +- if ((level.isNight() || level.isRaining()) && beehiveblockentity_beereleasestatus != BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY) { ++ private static boolean releaseOccupant(Level level, BlockPos pos, IBlockData state, BeehiveBlockEntity.BeeData data, @Nullable List storedInHives, BeehiveBlockEntity.ReleaseStatus releaseStatus, @Nullable BlockPos savedFlowerPos) { ++ // CraftBukkit start - This allows us to bypass the night/rain/emergency check ++ return releaseBee(level, pos, state, data, storedInHives, releaseStatus, savedFlowerPos, false); ++ } ++ ++ private static boolean releaseBee(Level world, BlockPos blockposition, IBlockData iblockdata, BeehiveBlockEntity.BeeData tileentitybeehive_hivebee, @Nullable List list, BeehiveBlockEntity.ReleaseStatus tileentitybeehive_releasestatus, @Nullable BlockPos blockposition1, boolean force) { ++ if (!force && (world.isNight() || world.isRaining()) && tileentitybeehive_releasestatus != BeehiveBlockEntity.ReleaseStatus.EMERGENCY) { ++ // CraftBukkit end + return false; + } else { + CompoundTag compoundtag = beehiveblockentity_beedata.entityData.copy(); +@@ -198,11 +222,19 @@ + if (!entity.getType().is(EntityTypeTags.BEEHIVE_INHABITORS)) { + return false; + } else { ++ // CraftBukkit start + if (entity instanceof Bee) { + Bee bee = (Bee) entity; + +- if (blockpos1 != null && !bee.hasSavedFlowerPos() && level.random.nextFloat() < 0.9F) { +- bee.setSavedFlowerPos(blockpos1); ++ entity.moveTo(d1, d2, d3, entity.getYRot(), entity.getXRot()); ++ } ++ if (!world.addFreshEntity(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BEEHIVE)) return false; // CraftBukkit - SpawnReason, moved from below ++ // CraftBukkit end ++ if (entity instanceof Bee) { ++ Bee entitybee = (Bee) entity; ++ ++ if (blockposition1 != null && !entitybee.hasSavedFlowerPos() && world.random.nextFloat() < 0.9F) { ++ entitybee.setSavedFlowerPos(blockposition1); + } + + if (beehiveblockentity_beereleasestatus == BeehiveBlockEntity.BeeReleaseStatus.HONEY_DELIVERED) { +@@ -229,6 +265,7 @@ + list.add(bee); + } + ++ /* // CraftBukkit start + float f = entity.getBbWidth(); + double d0 = flag ? 0.0D : 0.55D + (double) (f / 2.0F); + double d1 = (double) blockpos.getX() + 0.5D + d0 * (double) direction.getStepX(); +@@ -236,11 +273,12 @@ + double d3 = (double) blockpos.getZ() + 0.5D + d0 * (double) direction.getStepZ(); + + entity.moveTo(d1, d2, d3, entity.getYRot(), entity.getXRot()); ++ */ // CraftBukkit end + } + +- level.playSound((Player) null, blockpos, SoundEvents.BEEHIVE_EXIT, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(entity, level.getBlockState(blockpos))); +- return level.addFreshEntity(entity); ++ world.playSound((Player) null, blockposition, SoundEvents.BEEHIVE_EXIT, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entity, world.getBlockState(blockposition))); ++ return true; // return this.world.addFreshEntity(entity); // CraftBukkit - moved up + } + } else { + return false; +@@ -289,6 +327,10 @@ + if (releaseOccupant(level, blockpos, blockstate, beehiveblockentity_beedata, (List) null, beehiveblockentity_beereleasestatus, blockpos1)) { + flag = true; + iterator.remove(); ++ // CraftBukkit start ++ } else { ++ tileentitybeehive_hivebee.ticksInHive = tileentitybeehive_hivebee.minOccupationTicks / 2; // Not strictly Vanilla behaviour in cases where bees cannot spawn but still reasonable ++ // CraftBukkit end + } + } + } +@@ -331,6 +372,11 @@ + this.savedFlowerPos = NbtUtils.readBlockPos(compoundtag.getCompound("FlowerPos")); + } + ++ // CraftBukkit start ++ if (tag.contains("Bukkit.MaxEntities")) { ++ this.maxBees = tag.getInt("Bukkit.MaxEntities"); ++ } ++ // CraftBukkit end + } + + @Override +@@ -341,6 +386,7 @@ + if (this.hasSavedFlowerPos()) { + compoundtag.put("FlowerPos", NbtUtils.writeBlockPos(this.savedFlowerPos)); + } ++ tag.putInt("Bukkit.MaxEntities", this.maxBees); // CraftBukkit + + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BellBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BellBlockEntity.java.patch new file mode 100644 index 0000000000..953b49e27d --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BellBlockEntity.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/level/block/entity/BellBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BellBlockEntity.java +@@ -144,10 +143,14 @@ + return true; + } + +- private static void makeRaidersGlow(Level level, BlockPos blockpos, List list) { +- list.stream().filter((livingentity) -> { +- return isRaiderWithinRange(blockpos, livingentity); +- }).forEach(BellBlockEntity::glow); ++ private static void makeRaidersGlow(Level level, BlockPos pos, List raiders) { ++ List entities = // CraftBukkit ++ raiders.stream().filter((entityliving) -> { ++ return isRaiderWithinRange(pos, entityliving); ++ }).map((entity) -> (org.bukkit.entity.LivingEntity) entity.getBukkitEntity()).collect(java.util.stream.Collectors.toCollection(java.util.ArrayList::new)); // CraftBukkit ++ ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBellResonateEvent(level, pos, entities).forEach(BellBlockEntity::glow); ++ // CraftBukkit end + } + + private static void showBellParticles(Level level, BlockPos blockpos, List list) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BlockEntity.java.patch new file mode 100644 index 0000000000..b3db9595fd --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BlockEntity.java.patch @@ -0,0 +1,70 @@ +--- a/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -15,8 +15,18 @@ + import net.minecraft.world.level.block.state.BlockState; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer; ++import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end ++ + public abstract class BlockEntity { + ++ // CraftBukkit start - data containers ++ private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); ++ public CraftPersistentDataContainer persistentDataContainer; ++ // CraftBukkit end + private static final Logger LOGGER = LogUtils.getLogger(); + private final BlockEntityType type; + @Nullable +@@ -48,9 +58,16 @@ + return this.level != null; + } + +- public void load(CompoundTag compoundtag) {} ++ // CraftBukkit start - read container ++ public void load(CompoundTag tag) { ++ this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); + +- protected void saveAdditional(CompoundTag compoundtag) {} ++ net.minecraft.nbt.Tag persistentDataTag = tag.get("PublicBukkitValues"); ++ if (persistentDataTag instanceof CompoundTag) { ++ this.persistentDataContainer.putAll((CompoundTag) persistentDataTag); ++ } ++ } ++ // CraftBukkit end + + public final CompoundTag saveWithFullMetadata() { + CompoundTag compoundtag = this.saveWithoutMetadata(); +@@ -69,8 +88,13 @@ + public final CompoundTag saveWithoutMetadata() { + CompoundTag compoundtag = new CompoundTag(); + +- this.saveAdditional(compoundtag); +- return compoundtag; ++ this.saveAdditional(nbttagcompound); ++ // CraftBukkit start - store container ++ if (this.persistentDataContainer != null && !this.persistentDataContainer.isEmpty()) { ++ nbttagcompound.put("PublicBukkitValues", this.persistentDataContainer.toTagCompound()); ++ } ++ // CraftBukkit end ++ return nbttagcompound; + } + + private void saveId(CompoundTag compoundtag) { +@@ -202,4 +226,13 @@ + public void setBlockState(BlockState blockstate) { + this.blockState = blockstate; + } ++ ++ // CraftBukkit start - add method ++ public InventoryHolder getOwner() { ++ if (level == null) return null; ++ org.bukkit.block.BlockState state = level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()).getState(); ++ if (state instanceof InventoryHolder) return (InventoryHolder) state; ++ return null; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java.patch new file mode 100644 index 0000000000..62cf910147 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java.patch @@ -0,0 +1,169 @@ +--- a/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java +@@ -25,6 +25,20 @@ + import net.minecraft.world.level.block.BrewingStandBlock; + import net.minecraft.world.level.block.state.BlockState; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.event.block.BrewingStartEvent; ++import org.bukkit.event.inventory.BrewEvent; ++import org.bukkit.event.inventory.BrewingStandFuelEvent; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end ++ + public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements WorldlyContainer { + + private static final int INGREDIENT_SLOT = 3; +@@ -42,9 +56,39 @@ + private Item ingredient; + int fuel; + protected final ContainerData dataAccess; ++ // CraftBukkit start - add fields and methods ++ private int lastTick = MinecraftServer.currentTick; ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = 64; + +- public BrewingStandBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.BREWING_STAND, blockpos, blockstate); ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ ++ public BrewingStandBlockEntity(BlockPos pos, IBlockData state) { ++ super(BlockEntityType.BREWING_STAND, pos, state); + this.items = NonNullList.withSize(5, ItemStack.EMPTY); + this.dataAccess = new ContainerData() { + @Override +@@ -114,32 +152,52 @@ + public static void serverTick(Level level, BlockPos blockpos, BlockState blockstate, BrewingStandBlockEntity brewingstandblockentity) { + ItemStack itemstack = (ItemStack) brewingstandblockentity.items.get(4); + +- if (brewingstandblockentity.fuel <= 0 && itemstack.is(Items.BLAZE_POWDER)) { +- brewingstandblockentity.fuel = 20; +- itemstack.shrink(1); +- setChanged(level, blockpos, blockstate); ++ if (blockEntity.fuel <= 0 && itemstack.is(Items.BLAZE_POWDER)) { ++ // CraftBukkit start ++ BrewingStandFuelEvent event = new BrewingStandFuelEvent(CraftBlock.at(level, pos), CraftItemStack.asCraftMirror(itemstack), 20); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ blockEntity.fuel = event.getFuelPower(); ++ if (blockEntity.fuel > 0 && event.isConsuming()) { ++ itemstack.shrink(1); ++ } ++ // CraftBukkit end ++ setChanged(level, pos, state); + } + + boolean flag = isBrewable(brewingstandblockentity.items); + boolean flag1 = brewingstandblockentity.brewTime > 0; + ItemStack itemstack1 = (ItemStack) brewingstandblockentity.items.get(3); + ++ // CraftBukkit start - Use wall time instead of ticks for brewing ++ int elapsedTicks = MinecraftServer.currentTick - blockEntity.lastTick; ++ blockEntity.lastTick = MinecraftServer.currentTick; ++ + if (flag1) { +- --brewingstandblockentity.brewTime; +- boolean flag2 = brewingstandblockentity.brewTime == 0; ++ blockEntity.brewTime -= elapsedTicks; ++ boolean flag2 = blockEntity.brewTime <= 0; // == -> <= ++ // CraftBukkit end + + if (flag2 && flag) { +- doBrew(level, blockpos, brewingstandblockentity.items); +- setChanged(level, blockpos, blockstate); +- } else if (!flag || !itemstack1.is(brewingstandblockentity.ingredient)) { +- brewingstandblockentity.brewTime = 0; +- setChanged(level, blockpos, blockstate); ++ doBrew(level, pos, blockEntity.items, blockEntity); // CraftBukkit ++ setChanged(level, pos, state); ++ } else if (!flag || !itemstack1.is(blockEntity.ingredient)) { ++ blockEntity.brewTime = 0; ++ setChanged(level, pos, state); + } +- } else if (flag && brewingstandblockentity.fuel > 0) { +- --brewingstandblockentity.fuel; +- brewingstandblockentity.brewTime = 400; +- brewingstandblockentity.ingredient = itemstack1.getItem(); +- setChanged(level, blockpos, blockstate); ++ } else if (flag && blockEntity.fuel > 0) { ++ --blockEntity.fuel; ++ // CraftBukkit start ++ BrewingStartEvent event = new BrewingStartEvent(CraftBlock.at(level, pos), CraftItemStack.asCraftMirror(itemstack1), 400); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ blockEntity.brewTime = event.getTotalBrewTime(); // 400 -> event.getTotalBrewTime() ++ // CraftBukkit end ++ blockEntity.ingredient = itemstack1.getItem(); ++ setChanged(level, pos, state); + } + + boolean[] aboolean = brewingstandblockentity.getPotionBits(); +@@ -193,13 +251,33 @@ + } + } + +- private static void doBrew(Level level, BlockPos blockpos, NonNullList nonnulllist) { ++ // CraftBukkit start ++ private static void doBrew(Level world, BlockPos blockposition, NonNullList nonnulllist, BrewingStandBlockEntity tileentitybrewingstand) { + ItemStack itemstack = (ItemStack) nonnulllist.get(3); + + for (int i = 0; i < 3; ++i) { + nonnulllist.set(i, PotionBrewing.mix(itemstack, (ItemStack) nonnulllist.get(i))); + } + ++ if (owner != null) { ++ BrewEvent event = new BrewEvent(CraftBlock.at(world, blockposition), (org.bukkit.inventory.BrewerInventory) owner.getInventory(), brewResults, tileentitybrewingstand.fuel); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ ++ for (int i = 0; i < 3; ++i) { ++ // CraftBukkit start - validate index in case it is cleared by plugins ++ if (i < brewResults.size()) { ++ nonnulllist.set(i, CraftItemStack.asNMSCopy(brewResults.get(i))); ++ } else { ++ nonnulllist.set(i, ItemStack.EMPTY); ++ } ++ // CraftBukkit end ++ } ++ + itemstack.shrink(1); + if (itemstack.getItem().hasCraftingRemainingItem()) { + ItemStack itemstack1 = new ItemStack(itemstack.getItem().getCraftingRemainingItem()); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BrushableBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BrushableBlockEntity.java.patch new file mode 100644 index 0000000000..a644f202b9 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/BrushableBlockEntity.java.patch @@ -0,0 +1,44 @@ +--- a/net/minecraft/world/level/block/entity/BrushableBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BrushableBlockEntity.java +@@ -28,6 +28,12 @@ + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.Arrays; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class BrushableBlockEntity extends BlockEntity { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -152,8 +158,11 @@ + double d5 = (double) blockpos.getZ() + 0.5D * d1 + d2; + ItemEntity itementity = new ItemEntity(this.level, d3, d4, d5, this.item.split(this.level.random.nextInt(21) + 10)); + +- itementity.setDeltaMovement(Vec3.ZERO); +- this.level.addFreshEntity(itementity); ++ entityitem.setDeltaMovement(Vec3.ZERO); ++ // CraftBukkit start ++ org.bukkit.block.Block bblock = CraftBlock.at(this.level, this.worldPosition); ++ CraftEventFactory.handleBlockDropItemEvent(bblock, bblock.getState(), (ServerPlayer) player, Arrays.asList(entityitem)); ++ // CraftBukkit end + this.item = ItemStack.EMPTY; + } + +@@ -231,10 +238,10 @@ + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- if (!this.tryLoadLootTable(compoundtag) && compoundtag.contains("item")) { +- this.item = ItemStack.of(compoundtag.getCompound("item")); ++ public void load(CompoundTag tag) { ++ super.load(tag); // CraftBukkit - SPIGOT-7393: Load super Bukkit data ++ if (!this.tryLoadLootTable(tag) && tag.contains("item")) { ++ this.item = ItemStack.of(tag.getCompound("item")); + } + + if (compoundtag.contains("hit_direction")) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/CampfireBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/CampfireBlockEntity.java.patch new file mode 100644 index 0000000000..e9805e979c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/CampfireBlockEntity.java.patch @@ -0,0 +1,59 @@ +--- a/net/minecraft/world/level/block/entity/CampfireBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/CampfireBlockEntity.java +@@ -26,6 +26,14 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockCookEvent; ++import org.bukkit.event.block.CampfireStartEvent; ++import org.bukkit.inventory.CampfireRecipe; ++// CraftBukkit end ++ + public class CampfireBlockEntity extends BlockEntity implements Clearable { + + private static final int BURN_COOL_SPEED = 2; +@@ -60,10 +68,24 @@ + }).orElse(itemstack); + + if (itemstack1.isItemEnabled(level.enabledFeatures())) { +- Containers.dropItemStack(level, (double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), itemstack1); +- campfireblockentity.items.set(i, ItemStack.EMPTY); +- level.sendBlockUpdated(blockpos, blockstate, blockstate, 3); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(blockstate)); ++ // CraftBukkit start - fire BlockCookEvent ++ CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); ++ org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); ++ ++ BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(level, pos), source, result); ++ level.getCraftServer().getPluginManager().callEvent(blockCookEvent); ++ ++ if (blockCookEvent.isCancelled()) { ++ return; ++ } ++ ++ result = blockCookEvent.getResult(); ++ itemstack1 = CraftItemStack.asNMSCopy(result); ++ // CraftBukkit end ++ Containers.dropItemStack(level, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), itemstack1); ++ blockEntity.items.set(i, ItemStack.EMPTY); ++ level.sendBlockUpdated(pos, state, state, 3); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(state)); + } + } + } +@@ -176,7 +194,11 @@ + ItemStack itemstack1 = (ItemStack) this.items.get(j); + + if (itemstack1.isEmpty()) { +- this.cookingTime[j] = i; ++ // CraftBukkit start ++ CampfireStartEvent event = new CampfireStartEvent(CraftBlock.at(this.level,this.worldPosition), CraftItemStack.asCraftMirror(stack), (CampfireRecipe) getCookableRecipe(stack).get().toBukkitRecipe()); ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ this.cookingTime[j] = event.getTotalCookTime(); // i -> event.getTotalCookTime() ++ // CraftBukkit end + this.cookingProgress[j] = 0; + this.items.set(j, itemstack.split(1)); + this.level.gameEvent(GameEvent.BLOCK_CHANGE, this.getBlockPos(), GameEvent.Context.of(entity, this.getBlockState())); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/ChestBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/ChestBlockEntity.java.patch new file mode 100644 index 0000000000..d46de1b7ad --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/ChestBlockEntity.java.patch @@ -0,0 +1,67 @@ +--- a/net/minecraft/world/level/block/entity/ChestBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/ChestBlockEntity.java +@@ -22,6 +22,11 @@ + import net.minecraft.world.level.block.ChestBlock; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.block.state.properties.ChestType; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end + + public class ChestBlockEntity extends RandomizableContainerBlockEntity implements LidBlockEntity { + +@@ -30,8 +35,38 @@ + private final ContainerOpenersCounter openersCounter; + private final ChestLidController chestLidController; + +- protected ChestBlockEntity(BlockEntityType blockentitytype, BlockPos blockpos, BlockState blockstate) { +- super(blockentitytype, blockpos, blockstate); ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ ++ protected ChestBlockEntity(BlockEntityType type, BlockPos pos, IBlockData blockState) { ++ super(type, pos, blockState); + this.items = NonNullList.withSize(27, ItemStack.EMPTY); + this.openersCounter = new ContainerOpenersCounter() { + @Override +@@ -213,4 +233,11 @@ + + level.blockEvent(blockpos, block, 1, j); + } ++ ++ // CraftBukkit start ++ @Override ++ public boolean onlyOpCanSetNbt() { ++ return true; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java.patch new file mode 100644 index 0000000000..7478505f4f --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java.patch @@ -0,0 +1,112 @@ +--- a/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java +@@ -18,15 +18,57 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class ChiseledBookShelfBlockEntity extends BlockEntity implements Container { + + public static final int MAX_BOOKS_IN_STORAGE = 6; + private static final Logger LOGGER = LogUtils.getLogger(); + private final NonNullList items; +- private int lastInteractedSlot; ++ public int lastInteractedSlot; ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList<>(); ++ private int maxStack = 1; + +- public ChiseledBookShelfBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.CHISELED_BOOKSHELF, blockpos, blockstate); ++ @Override ++ public List getContents() { ++ return this.items; ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ } ++ // CraftBukkit end ++ ++ public ChiseledBookShelfBlockEntity(BlockPos pos, IBlockData state) { ++ super(BlockEntityType.CHISELED_BOOKSHELF, pos, state); + this.items = NonNullList.withSize(6, ItemStack.EMPTY); + this.lastInteractedSlot = -1; + } +@@ -51,8 +93,8 @@ + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { ++ public void load(CompoundTag tag) { ++ super.load(tag); // CraftBukkit - SPIGOT-7393: Load super Bukkit data + this.items.clear(); + ContainerHelper.loadAllItems(compoundtag, this.items); + this.lastInteractedSlot = compoundtag.getInt("last_interacted_slot"); +@@ -100,7 +136,7 @@ + + this.items.set(i, ItemStack.EMPTY); + if (!itemstack.isEmpty()) { +- this.updateState(i); ++ if (level != null) this.updateState(slot); // CraftBukkit - SPIGOT-7381: check for null world + } + + return itemstack; +@@ -113,13 +148,12 @@ + } + + @Override +- @Override +- public void setItem(int i, ItemStack itemstack) { +- if (itemstack.is(ItemTags.BOOKSHELF_BOOKS)) { +- this.items.set(i, itemstack); +- this.updateState(i); +- } else if (itemstack.isEmpty()) { +- this.removeItem(i, 1); ++ public void setItem(int slot, ItemStack stack) { ++ if (stack.is(ItemTags.BOOKSHELF_BOOKS)) { ++ this.items.set(slot, stack); ++ if (level != null) this.updateState(slot); // CraftBukkit - SPIGOT-7381: check for null world ++ } else if (stack.isEmpty()) { ++ this.removeItem(slot, 1); + } + + } +@@ -135,7 +167,7 @@ + @Override + @Override + public int getMaxStackSize() { +- return 1; ++ return maxStack; // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/CommandBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/CommandBlockEntity.java.patch new file mode 100644 index 0000000000..0995672902 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/CommandBlockEntity.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/level/block/entity/CommandBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/CommandBlockEntity.java +@@ -20,7 +20,13 @@ + private boolean auto; + private boolean conditionMet; + private final BaseCommandBlock commandBlock = new BaseCommandBlock() { ++ // CraftBukkit start + @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return new org.bukkit.craftbukkit.command.CraftBlockCommandSender(wrapper, CommandBlockEntity.this); ++ } ++ // CraftBukkit end ++ + @Override + public void setCommand(String s) { + super.setCommand(s); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/ConduitBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/ConduitBlockEntity.java.patch new file mode 100644 index 0000000000..5d79703bb1 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/ConduitBlockEntity.java.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/world/level/block/entity/ConduitBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/ConduitBlockEntity.java +@@ -26,6 +26,10 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class ConduitBlockEntity extends BlockEntity { + +@@ -204,8 +204,8 @@ + while (iterator.hasNext()) { + Player player = (Player) iterator.next(); + +- if (blockpos.closerThan(player.blockPosition(), (double) j) && player.isInWaterOrRain()) { +- player.addEffect(new MobEffectInstance(MobEffects.CONDUIT_POWER, 260, 0, true, true)); ++ if (pos.closerThan(entityhuman.blockPosition(), (double) j) && entityhuman.isInWaterOrRain()) { ++ entityhuman.addEffect(new MobEffectInstance(MobEffects.CONDUIT_POWER, 260, 0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONDUIT); // CraftBukkit + } + } + +@@ -233,9 +233,14 @@ + conduitblockentity.destroyTarget = null; + } + +- if (conduitblockentity.destroyTarget != null) { +- level.playSound((Player) null, conduitblockentity.destroyTarget.getX(), conduitblockentity.destroyTarget.getY(), conduitblockentity.destroyTarget.getZ(), SoundEvents.CONDUIT_ATTACK_TARGET, SoundSource.BLOCKS, 1.0F, 1.0F); +- conduitblockentity.destroyTarget.hurt(level.damageSources().magic(), 4.0F); ++ if (blockEntity.destroyTarget != null) { ++ // CraftBukkit start ++ CraftEventFactory.blockDamage = CraftBlock.at(level, pos); ++ if (blockEntity.destroyTarget.hurt(level.damageSources().magic(), 4.0F)) { ++ level.playSound((Player) null, blockEntity.destroyTarget.getX(), blockEntity.destroyTarget.getY(), blockEntity.destroyTarget.getZ(), SoundEvents.CONDUIT_ATTACK_TARGET, SoundSource.BLOCKS, 1.0F, 1.0F); ++ } ++ CraftEventFactory.blockDamage = null; ++ // CraftBukkit end + } + + if (livingentity != conduitblockentity.destroyTarget) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java.patch new file mode 100644 index 0000000000..7c5c00e021 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java.patch @@ -0,0 +1,82 @@ +--- a/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java ++++ b/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java +@@ -13,6 +13,7 @@ + + private static final int CHECK_TICK_DELAY = 5; + private int openCount; ++ public boolean opened; // CraftBukkit + + public ContainerOpenersCounter() {} + +@@ -22,11 +23,36 @@ + + protected abstract void openerCountChanged(Level level, BlockPos pos, BlockState state, int count, int openCount); + ++ // CraftBukkit start ++ public void onAPIOpen(Level world, BlockPos blockposition, IBlockData iblockdata) { ++ onOpen(world, blockposition, iblockdata); ++ } ++ ++ public void onAPIClose(Level world, BlockPos blockposition, IBlockData iblockdata) { ++ onClose(world, blockposition, iblockdata); ++ } ++ ++ public void openerAPICountChanged(Level world, BlockPos blockposition, IBlockData iblockdata, int i, int j) { ++ openerCountChanged(world, blockposition, iblockdata, i, j); ++ } ++ // CraftBukkit end ++ + protected abstract boolean isOwnContainer(Player player); + +- public void incrementOpeners(Player player, Level level, BlockPos blockpos, BlockState blockstate) { ++ public void incrementOpeners(Player player, Level level, BlockPos pos, IBlockData state) { ++ int oldPower = Math.max(0, Math.min(15, this.openCount)); // CraftBukkit - Get power before new viewer is added + int i = this.openCount++; + ++ // CraftBukkit start - Call redstone event ++ if (level.getBlockState(pos).is(net.minecraft.world.level.block.Blocks.TRAPPED_CHEST)) { ++ int newPower = Math.max(0, Math.min(15, this.openCount)); ++ ++ if (oldPower != newPower) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(level, pos, oldPower, newPower); ++ } ++ } ++ // CraftBukkit end ++ + if (i == 0) { + this.onOpen(level, blockpos, blockstate); + level.gameEvent((Entity) player, GameEvent.CONTAINER_OPEN, blockpos); +@@ -36,9 +62,20 @@ + this.openerCountChanged(level, blockpos, blockstate, i, this.openCount); + } + +- public void decrementOpeners(Player player, Level level, BlockPos blockpos, BlockState blockstate) { ++ public void decrementOpeners(Player player, Level level, BlockPos pos, IBlockData state) { ++ int oldPower = Math.max(0, Math.min(15, this.openCount)); // CraftBukkit - Get power before new viewer is added + int i = this.openCount--; + ++ // CraftBukkit start - Call redstone event ++ if (level.getBlockState(pos).is(net.minecraft.world.level.block.Blocks.TRAPPED_CHEST)) { ++ int newPower = Math.max(0, Math.min(15, this.openCount)); ++ ++ if (oldPower != newPower) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(level, pos, oldPower, newPower); ++ } ++ } ++ // CraftBukkit end ++ + if (this.openCount == 0) { + this.onClose(level, blockpos, blockstate); + level.gameEvent((Entity) player, GameEvent.CONTAINER_CLOSE, blockpos); +@@ -57,8 +94,9 @@ + return level.getEntities(EntityTypeTest.forClass(Player.class), aabb, this::isOwnContainer).size(); + } + +- public void recheckOpeners(Level level, BlockPos blockpos, BlockState blockstate) { +- int i = this.getOpenCount(level, blockpos); ++ public void recheckOpeners(Level level, BlockPos pos, IBlockData state) { ++ int i = this.getOpenCount(level, pos); ++ if (opened) i++; // CraftBukkit - add dummy count from API + int j = this.openCount; + + if (j != i) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/CrafterBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/CrafterBlockEntity.java.patch new file mode 100644 index 0000000000..1a7e685c3a --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/CrafterBlockEntity.java.patch @@ -0,0 +1,67 @@ +--- a/net/minecraft/world/level/block/entity/CrafterBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/CrafterBlockEntity.java +@@ -21,7 +21,11 @@ + import net.minecraft.world.level.block.CrafterBlock; + import net.minecraft.world.level.block.state.BlockState; + +-public class CrafterBlockEntity extends RandomizableContainerBlockEntity implements CraftingContainer { ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end + + public static final int CONTAINER_WIDTH = 3; + public static final int CONTAINER_HEIGHT = 3; +@@ -33,9 +39,49 @@ + private NonNullList items; + private int craftingTicksRemaining; + protected final ContainerData containerData; ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList<>(); ++ private int maxStack = 1; + +- public CrafterBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.CRAFTER, blockpos, blockstate); ++ @Override ++ public List getContents() { ++ return this.items; ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ @Override ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ } ++ // CraftBukkit end ++ ++ public CrafterBlockEntity(BlockPos blockposition, IBlockData iblockdata) { ++ super(BlockEntityType.CRAFTER, blockposition, iblockdata); + this.items = NonNullList.withSize(9, ItemStack.EMPTY); + this.craftingTicksRemaining = 0; + this.containerData = new ContainerData() { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java.patch new file mode 100644 index 0000000000..2668c3cd48 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java +@@ -21,8 +21,59 @@ + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.ticks.ContainerSingleItem; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class DecoratedPotBlockEntity extends BlockEntity implements RandomizableContainer, ContainerSingleItem { + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new ArrayList<>(); ++ private int maxStack = MAX_STACK; ++ ++ @Override ++ public List getContents() { ++ return Arrays.asList(this.item); ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ @Override ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return CraftLocation.toBukkit(worldPosition, level.getWorld()); ++ } ++ // CraftBukkit end ++ + public static final String TAG_SHERDS = "sherds"; + public static final String TAG_ITEM = "item"; + public static final int EVENT_POT_WOBBLES = 1; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/DispenserBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/DispenserBlockEntity.java.patch new file mode 100644 index 0000000000..56c3c6798f --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/DispenserBlockEntity.java.patch @@ -0,0 +1,54 @@ +--- a/net/minecraft/world/level/block/entity/DispenserBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/DispenserBlockEntity.java +@@ -13,13 +13,49 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.state.BlockState; + ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class DispenserBlockEntity extends RandomizableContainerBlockEntity { + + public static final int CONTAINER_SIZE = 9; + private NonNullList items; + +- protected DispenserBlockEntity(BlockEntityType blockentitytype, BlockPos blockpos, BlockState blockstate) { +- super(blockentitytype, blockpos, blockstate); ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ ++ protected DispenserBlockEntity(BlockEntityType type, BlockPos pos, IBlockData blockState) { ++ super(type, pos, blockState); + this.items = NonNullList.withSize(9, ItemStack.EMPTY); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/HopperBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/HopperBlockEntity.java.patch new file mode 100644 index 0000000000..b143c488e7 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/HopperBlockEntity.java.patch @@ -0,0 +1,211 @@ +--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java +@@ -31,6 +31,17 @@ + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.Shapes; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.event.inventory.HopperInventorySearchEvent; ++import org.bukkit.event.inventory.InventoryMoveItemEvent; ++import org.bukkit.event.inventory.InventoryPickupItemEvent; ++import org.bukkit.inventory.Inventory; ++// CraftBukkit end + + public class HopperBlockEntity extends RandomizableContainerBlockEntity implements Hopper { + +@@ -40,8 +51,38 @@ + private int cooldownTime; + private long tickedGameTime; + +- public HopperBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.HOPPER, blockpos, blockstate); ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ ++ public HopperBlockEntity(BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.HOPPER, pos, blockState); + this.items = NonNullList.withSize(5, ItemStack.EMPTY); + this.cooldownTime = -1; + } +@@ -118,8 +153,8 @@ + if (!hopperblockentity.isOnCooldown() && (Boolean) blockstate.getValue(HopperBlock.ENABLED)) { + boolean flag = false; + +- if (!hopperblockentity.isEmpty()) { +- flag = ejectItems(level, blockpos, blockstate, hopperblockentity); ++ if (!blockEntity.isEmpty()) { ++ flag = ejectItems(level, pos, state, (Container) blockEntity, blockEntity); // CraftBukkit + } + + if (!hopperblockentity.inventoryFull()) { +@@ -153,8 +188,8 @@ + return false; + } + +- private static boolean ejectItems(Level level, BlockPos blockpos, BlockState blockstate, Container container) { +- Container container1 = getAttachedContainer(level, blockpos, blockstate); ++ private static boolean ejectItems(Level world, BlockPos blockposition, IBlockData iblockdata, Container iinventory, HopperBlockEntity hopper) { // CraftBukkit ++ Container iinventory1 = getAttachedContainer(world, blockposition, iblockdata); + + if (container1 == null) { + return false; +@@ -169,6 +204,29 @@ + ItemStack itemstack = container.getItem(i).copy(); + ItemStack itemstack1 = addItem(container, container1, container.removeItem(i, 1), direction); + ++ // CraftBukkit start - Call event when pushing items into other inventories ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.removeItem(i, 1)); ++ ++ Inventory destinationInventory; ++ // Have to special case large chests as they work oddly ++ if (iinventory1 instanceof CompoundContainer) { ++ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory1); ++ } else if (iinventory1.getOwner() != null) { ++ destinationInventory = iinventory1.getOwner().getInventory(); ++ } else { ++ destinationInventory = new CraftInventory(iinventory); ++ } ++ ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(iinventory.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ hopper.setItem(i, itemstack); ++ hopper.setCooldown(8); // Delay hopper checks ++ return false; ++ } ++ ItemStack itemstack1 = addItem(iinventory, iinventory1, CraftItemStack.asNMSCopy(event.getItem()), enumdirection); ++ // CraftBukkit end ++ + if (itemstack1.isEmpty()) { + container1.setChanged(); + return true; +@@ -232,8 +290,35 @@ + + if (!itemstack.isEmpty() && canTakeItemFromContainer(hopper, container, itemstack, i, direction)) { + ItemStack itemstack1 = itemstack.copy(); +- ItemStack itemstack2 = addItem(container, hopper, container.removeItem(i, 1), (Direction) null); ++ // ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.removeItem(i, 1), (EnumDirection) null); ++ // CraftBukkit start - Call event on collection of items from inventories into the hopper ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(container.removeItem(slot, 1)); + ++ Inventory sourceInventory; ++ // Have to special case large chests as they work oddly ++ if (container instanceof CompoundContainer) { ++ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) container); ++ } else if (container.getOwner() != null) { ++ sourceInventory = container.getOwner().getInventory(); ++ } else { ++ sourceInventory = new CraftInventory(container); ++ } ++ ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack.clone(), hopper.getOwner().getInventory(), false); ++ ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ container.setItem(slot, itemstack1); ++ ++ if (hopper instanceof HopperBlockEntity) { ++ ((HopperBlockEntity) hopper).setCooldown(8); // Delay hopper checks ++ } ++ ++ return false; ++ } ++ ItemStack itemstack2 = addItem(container, hopper, CraftItemStack.asNMSCopy(event.getItem()), null); ++ // CraftBukkit end ++ + if (itemstack2.isEmpty()) { + container.setChanged(); + return true; +@@ -247,7 +332,14 @@ + + public static boolean addItem(Container container, ItemEntity itementity) { + boolean flag = false; +- ItemStack itemstack = itementity.getItem().copy(); ++ // CraftBukkit start ++ InventoryPickupItemEvent event = new InventoryPickupItemEvent(container.getOwner().getInventory(), (org.bukkit.entity.Item) item.getBukkitEntity()); ++ item.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ ItemStack itemstack = item.getItem().copy(); + ItemStack itemstack1 = addItem((Container) null, container, itemstack, (Direction) null); + + if (itemstack1.isEmpty()) { +@@ -373,16 +465,40 @@ + return itemstack; + } + ++ // CraftBukkit start + @Nullable +- private static Container getAttachedContainer(Level level, BlockPos blockpos, BlockState blockstate) { +- Direction direction = (Direction) blockstate.getValue(HopperBlock.FACING); ++ private static Container runHopperInventorySearchEvent(Container inventory, CraftBlock hopper, CraftBlock searchLocation, HopperInventorySearchEvent.ContainerType containerType) { ++ HopperInventorySearchEvent event = new HopperInventorySearchEvent((inventory != null) ? new CraftInventory(inventory) : null, containerType, hopper, searchLocation); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ CraftInventory craftInventory = (CraftInventory) event.getInventory(); ++ return (craftInventory != null) ? craftInventory.getInventory() : null; ++ } ++ // CraftBukkit end + +- return getContainerAt(level, blockpos.relative(direction)); ++ @Nullable ++ private static Container getAttachedContainer(Level level, BlockPos pos, IBlockData state) { ++ Direction enumdirection = (Direction) state.getValue(HopperBlock.FACING); ++ ++ // CraftBukkit start ++ BlockPos searchPosition = pos.relative(enumdirection); ++ Container inventory = getContainerAt(level, pos.relative(enumdirection)); ++ ++ CraftBlock hopper = CraftBlock.at(level, pos); ++ CraftBlock searchBlock = CraftBlock.at(level, searchPosition); ++ return runHopperInventorySearchEvent(inventory, hopper, searchBlock, HopperInventorySearchEvent.ContainerType.DESTINATION); ++ // CraftBukkit end + } + + @Nullable + private static Container getSourceContainer(Level level, Hopper hopper) { +- return getContainerAt(level, hopper.getLevelX(), hopper.getLevelY() + 1.0D, hopper.getLevelZ()); ++ // CraftBukkit start ++ Container inventory = getContainerAt(level, hopper.getLevelX(), hopper.getLevelY() + 1.0D, hopper.getLevelZ()); ++ ++ BlockPos blockPosition = BlockPos.containing(hopper.getLevelX(), hopper.getLevelY(), hopper.getLevelZ()); ++ CraftBlock hopper1 = CraftBlock.at(level, blockPosition); ++ CraftBlock container = CraftBlock.at(level, blockPosition.above()); ++ return runHopperInventorySearchEvent(inventory, hopper1, container, HopperInventorySearchEvent.ContainerType.SOURCE); ++ // CraftBukkit end + } + + public static List getItemsAtAndAbove(Level level, Hopper hopper) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java.patch new file mode 100644 index 0000000000..c146dc3218 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java.patch @@ -0,0 +1,93 @@ +--- a/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java +@@ -22,14 +22,26 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.ticks.ContainerSingleItem; + ++// CraftBukkit start ++import java.util.Collections; ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class JukeboxBlockEntity extends BlockEntity implements Clearable, ContainerSingleItem { + + private static final int SONG_END_PADDING = 20; + private ItemStack item; + private int ticksSinceLastEvent; +- private long tickCount; +- private long recordStartedTick; +- private boolean isPlaying; ++ public long tickCount; ++ public long recordStartedTick; ++ public boolean isPlaying; ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ public boolean opened; + + public JukeboxBlockEntity(BlockPos blockpos, BlockState blockstate) { + super(BlockEntityType.JUKEBOX, blockpos, blockstate); +@@ -51,8 +69,32 @@ + + @Override + @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); ++ public Location getLocation() { ++ if (level == null) return null; ++ return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ } ++ // CraftBukkit end ++ ++ public JukeboxBlockEntity(BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.JUKEBOX, pos, blockState); ++ this.item = ItemStack.EMPTY; ++ } ++ ++ @Override ++ public void load(CompoundTag tag) { ++ super.load(tag); ++ if (tag.contains("RecordItem", 10)) { ++ this.item = ItemStack.of(tag.getCompound("RecordItem")); ++ } ++ ++ this.isPlaying = tag.getBoolean("IsPlaying"); ++ this.recordStartedTick = tag.getLong("RecordStartTick"); ++ this.tickCount = tag.getLong("TickCount"); ++ } ++ ++ @Override ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); + if (!this.getTheItem().isEmpty()) { + compoundtag.put("RecordItem", this.getTheItem().save(new CompoundTag())); + } +@@ -156,7 +194,7 @@ + @Override + @Override + public int getMaxStackSize() { +- return 1; ++ return maxStack; // CraftBukkit + } + + @Override +@@ -210,9 +245,13 @@ + } + + @VisibleForTesting +- public void setRecordWithoutPlaying(ItemStack itemstack) { +- this.item = itemstack; +- this.level.updateNeighborsAt(this.getBlockPos(), this.getBlockState().getBlock()); ++ public void setRecordWithoutPlaying(ItemStack stack) { ++ this.item = stack; ++ // CraftBukkit start - add null check for level ++ if (level != null) { ++ this.level.updateNeighborsAt(this.getBlockPos(), this.getBlockState().getBlock()); ++ } ++ // CraftBukkit end + this.setChanged(); + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/LecternBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/LecternBlockEntity.java.patch new file mode 100644 index 0000000000..41faf78303 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/LecternBlockEntity.java.patch @@ -0,0 +1,163 @@ +--- a/net/minecraft/world/level/block/entity/LecternBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/LecternBlockEntity.java +@@ -24,16 +24,69 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.block.Lectern; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end + +-public class LecternBlockEntity extends BlockEntity implements Clearable, MenuProvider { ++public class LecternBlockEntity extends BlockEntity implements Clearable, ITileInventory, CommandSource { // CraftBukkit - ICommandListener + + public static final int DATA_PAGE = 0; + public static final int NUM_DATA = 1; + public static final int SLOT_BOOK = 0; + public static final int NUM_SLOTS = 1; +- private final Container bookAccess = new Container() { ++ // CraftBukkit start - add fields and methods ++ public final Container bookAccess = new LecternInventory(); ++ public class LecternInventory implements Container { ++ ++ public List transaction = new ArrayList<>(); ++ private int maxStack = 1; ++ + @Override + @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return CraftLocation.toBukkit(worldPosition, level.getWorld()); ++ } ++ ++ @Override ++ public InventoryHolder getOwner() { ++ return (Lectern) LecternBlockEntity.this.getOwner(); ++ } ++ ++ public LecternBlockEntity getLectern() { ++ return LecternBlockEntity.this; ++ } ++ // CraftBukkit end ++ ++ @Override + public int getContainerSize() { + return 1; + } +@@ -81,13 +134,21 @@ + } + + @Override +- @Override +- public void setItem(int i, ItemStack itemstack) {} ++ // CraftBukkit start ++ public void setItem(int slot, ItemStack stack) { ++ if (slot == 0) { ++ LecternBlockEntity.this.setBook(stack); ++ if (LecternBlockEntity.this.getLevel() != null) { ++ LecternBlock.resetBookState(null, LecternBlockEntity.this.getLevel(), LecternBlockEntity.this.getBlockPos(), LecternBlockEntity.this.getBlockState(), LecternBlockEntity.this.hasBook()); ++ } ++ } ++ } ++ // CraftBukkit end + + @Override + @Override + public int getMaxStackSize() { +- return 1; ++ return maxStack; // CraftBukkit + } + + @Override +@@ -174,7 +227,7 @@ + if (j != this.page) { + this.page = j; + this.setChanged(); +- LecternBlock.signalPageChange(this.getLevel(), this.getBlockPos(), this.getBlockState()); ++ if (this.level != null) LecternBlock.signalPageChange(this.getLevel(), this.getBlockPos(), this.getBlockState()); // CraftBukkit + } + + } +@@ -197,6 +250,32 @@ + return itemstack; + } + ++ // CraftBukkit start ++ @Override ++ public void sendSystemMessage(Component component) { ++ } ++ ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return wrapper.getEntity() != null ? wrapper.getEntity().getBukkitSender(wrapper) : new org.bukkit.craftbukkit.command.CraftBlockCommandSender(wrapper, this); ++ } ++ ++ @Override ++ public boolean acceptsSuccess() { ++ return false; ++ } ++ ++ @Override ++ public boolean acceptsFailure() { ++ return false; ++ } ++ ++ @Override ++ public boolean shouldInformAdmins() { ++ return false; ++ } ++ ++ // CraftBukkit end + private CommandSourceStack createCommandSourceStack(@Nullable Player player) { + String s; + Object object; +@@ -211,7 +290,8 @@ + + Vec3 vec3 = Vec3.atCenterOf(this.worldPosition); + +- return new CommandSourceStack(CommandSource.NULL, vec3, Vec2.ZERO, (ServerLevel) this.level, 2, s, (Component) object, this.level.getServer(), player); ++ // CraftBukkit - this ++ return new CommandSourceStack(this, vec3d, Vec2.ZERO, (ServerLevel) this.level, 2, s, (Component) object, this.level.getServer(), player); + } + + @Override +@@ -252,9 +328,8 @@ + } + + @Override +- @Override +- public AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) { +- return new LecternMenu(i, this.bookAccess, this.dataAccess); ++ public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { ++ return new LecternMenu(containerId, this.bookAccess, this.dataAccess, playerInventory); // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java.patch new file mode 100644 index 0000000000..d6171b3c6b --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java +@@ -29,19 +29,22 @@ + + private final SculkCatalystBlockEntity.CatalystListener catalystListener; + +- public SculkCatalystBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.SCULK_CATALYST, blockpos, blockstate); +- this.catalystListener = new SculkCatalystBlockEntity.CatalystListener(blockstate, new BlockPositionSource(blockpos)); ++ public SculkCatalystBlockEntity(BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.SCULK_CATALYST, pos, blockState); ++ this.catalystListener = new SculkCatalystBlockEntity.CatalystListener(blockState, new BlockPositionSource(pos)); ++ catalystListener.level = level; // CraftBukkit + } + +- public static void serverTick(Level level, BlockPos blockpos, BlockState blockstate, SculkCatalystBlockEntity sculkcatalystblockentity) { +- sculkcatalystblockentity.catalystListener.getSculkSpreader().updateCursors(level, blockpos, level.getRandom(), true); ++ public static void serverTick(Level level, BlockPos pos, IBlockData state, SculkCatalystBlockEntity sculkCatalyst) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = sculkCatalyst.getBlockPos(); // CraftBukkit - SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep. ++ sculkCatalyst.catalystListener.getSculkSpreader().updateCursors(level, pos, level.getRandom(), true); ++ org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = null; // CraftBukkit + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- this.catalystListener.sculkSpreader.load(compoundtag); ++ public void load(CompoundTag tag) { ++ super.load(tag); // CraftBukkit - SPIGOT-7393: Load super Bukkit data ++ this.catalystListener.sculkSpreader.load(tag); + } + + @Override +@@ -63,11 +64,13 @@ + final SculkSpreader sculkSpreader; + private final BlockState blockState; + private final PositionSource positionSource; ++ private Level level; // CraftBukkit + + public CatalystListener(BlockState blockstate, PositionSource positionsource) { + this.blockState = blockstate; + this.positionSource = positionsource; + this.sculkSpreader = SculkSpreader.createLevelSpreader(); ++ this.sculkSpreader.level = level; // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java.patch new file mode 100644 index 0000000000..2182780559 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java.patch @@ -0,0 +1,71 @@ +--- a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java +@@ -31,6 +31,10 @@ + import net.minecraft.world.level.material.PushReaction; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end + + public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity implements WorldlyContainer { + +@@ -51,8 +55,39 @@ + @Nullable + private final DyeColor color; + +- public ShulkerBoxBlockEntity(@Nullable DyeColor dyecolor, BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.SHULKER_BOX, blockpos, blockstate); ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ public boolean opened; ++ ++ public List getContents() { ++ return this.itemStacks; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ ++ public ShulkerBoxBlockEntity(@Nullable DyeColor color, BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.SHULKER_BOX, pos, blockState); + this.itemStacks = NonNullList.withSize(27, ItemStack.EMPTY); + this.animationStatus = ShulkerBoxBlockEntity.AnimationStatus.CLOSED; + this.color = dyecolor; +@@ -175,6 +207,7 @@ + } + + ++this.openCount; ++ if (opened) return; // CraftBukkit - only animate if the ShulkerBox hasn't been forced open already by an API call. + this.level.blockEvent(this.worldPosition, this.getBlockState().getBlock(), 1, this.openCount); + if (this.openCount == 1) { + this.level.gameEvent((Entity) player, GameEvent.CONTAINER_OPEN, this.worldPosition); +@@ -189,6 +221,7 @@ + public void stopOpen(Player player) { + if (!this.remove && !player.isSpectator()) { + --this.openCount; ++ if (opened) return; // CraftBukkit - only animate if the ShulkerBox hasn't been forced open already by an API call. + this.level.blockEvent(this.worldPosition, this.getBlockState().getBlock(), 1, this.openCount); + if (this.openCount <= 0) { + this.level.gameEvent((Entity) player, GameEvent.CONTAINER_CLOSE, this.worldPosition); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/SignBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/SignBlockEntity.java.patch new file mode 100644 index 0000000000..3b5dbd1f4d --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/SignBlockEntity.java.patch @@ -0,0 +1,131 @@ +--- a/net/minecraft/world/level/block/entity/SignBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/SignBlockEntity.java +@@ -32,8 +33,14 @@ + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; ++import org.bukkit.block.sign.Side; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.entity.Player; ++import org.bukkit.event.block.SignChangeEvent; ++// CraftBukkit end + +-public class SignBlockEntity extends BlockEntity { ++public class SignBlockEntity extends BlockEntity implements CommandSource { // CraftBukkit - implements + + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int MAX_TEXT_LINE_WIDTH = 90; +@@ -173,12 +178,13 @@ + public void updateSignText(Player player, boolean flag, List list) { + if (!this.isWaxed() && player.getUUID().equals(this.getPlayerWhoMayEdit()) && this.level != null) { + this.updateText((signtext) -> { +- return this.setMessages(player, list, signtext); +- }, flag); ++ return this.setMessages(player, filteredText, signtext, isFrontText); // CraftBukkit ++ }, isFrontText); + this.setAllowedPlayerEditor((UUID) null); + this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3); + } else { + SignBlockEntity.LOGGER.warn("Player {} just tried to change non-editable sign", player.getName().getString()); ++ ((ServerPlayer) player).connection.send(this.getUpdatePacket()); // CraftBukkit + } + } + +@@ -188,7 +194,8 @@ + return this.setText((SignText) unaryoperator.apply(signtext), flag); + } + +- private SignText setMessages(Player player, List list, SignText signtext) { ++ private SignText setMessages(net.minecraft.world.entity.player.Player entityhuman, List list, SignText signtext, boolean front) { // CraftBukkit ++ SignText originalText = signtext; // CraftBukkit + for (int i = 0; i < list.size(); ++i) { + FilteredText filteredtext = (FilteredText) list.get(i); + Style style = signtext.getMessage(i, player.isTextFilteringEnabled()).getStyle(); +@@ -200,6 +207,29 @@ + } + } + ++ // CraftBukkit start ++ Player player = ((ServerPlayer) entityhuman).getBukkitEntity(); ++ String[] lines = new String[4]; ++ ++ for (int i = 0; i < list.size(); ++i) { ++ lines[i] = CraftChatMessage.fromComponent(signtext.getMessage(i, entityhuman.isTextFilteringEnabled())); ++ } ++ ++ SignChangeEvent event = new SignChangeEvent(CraftBlock.at(this.level, this.worldPosition), player, lines.clone(), (front) ? Side.FRONT : Side.BACK); ++ entityhuman.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return originalText; ++ } ++ ++ Component[] components = org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()); ++ for (int i = 0; i < components.length; i++) { ++ if (!Objects.equals(lines[i], event.getLine(i))) { ++ signtext = signtext.setMessage(i, components[i]); ++ } ++ } ++ // CraftBukkit end ++ + return signtext; + } + +@@ -250,15 +280,34 @@ + return flag1; + } + +- private static CommandSourceStack createCommandSourceStack(@Nullable Player player, Level level, BlockPos blockpos) { +- String s = player == null ? "Sign" : player.getName().getString(); +- Object object = player == null ? Component.literal("Sign") : player.getDisplayName(); ++ // CraftBukkit start ++ @Override ++ public void sendSystemMessage(Component component) {} + + return new CommandSourceStack(CommandSource.NULL, Vec3.atCenterOf(blockpos), Vec2.ZERO, (ServerLevel) level, 2, s, (Component) object, level.getServer(), player); + } + + @Override + @Override ++ public boolean acceptsFailure() { ++ return false; ++ } ++ ++ @Override ++ public boolean shouldInformAdmins() { ++ return false; ++ } ++ ++ private CommandSourceStack createCommandSourceStack(@Nullable net.minecraft.world.entity.player.Player level, Level pos, BlockPos blockposition) { ++ // CraftBukkit end ++ String s = level == null ? "Sign" : level.getName().getString(); ++ Object object = level == null ? Component.literal("Sign") : level.getDisplayName(); ++ ++ // CraftBukkit - this ++ return new CommandSourceStack(this, Vec3.atCenterOf(blockposition), Vec2.ZERO, (ServerLevel) pos, 2, s, (Component) object, pos.getServer(), level); ++ } ++ ++ @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } +@@ -281,12 +334,17 @@ + + @Nullable + public UUID getPlayerWhoMayEdit() { ++ // CraftBukkit start - unnecessary sign ticking removed, so do this lazily ++ if (this.level != null && this.playerWhoMayEdit != null) { ++ clearInvalidPlayerWhoMayEdit(this, this.level, this.playerWhoMayEdit); ++ } ++ // CraftBukkit end + return this.playerWhoMayEdit; + } + + private void markUpdated() { + this.setChanged(); +- this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3); ++ if (this.level != null) this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3); // CraftBukkit - skip notify if world is null (SPIGOT-5122) + } + + public boolean isWaxed() { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/SkullBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/SkullBlockEntity.java.patch new file mode 100644 index 0000000000..8044466def --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/SkullBlockEntity.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/level/block/entity/SkullBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/SkullBlockEntity.java +@@ -198,7 +193,17 @@ + String s = compoundtag.getString("SkullOwner"); + + if (!Util.isBlank(s)) { +- resolveGameProfile(compoundtag, s); ++ resolveGameProfile(nbttagcompound, s); ++ // CraftBukkit start ++ } else { ++ net.minecraft.nbt.ListTag textures = nbttagcompound.getCompound("SkullOwner").getCompound("Properties").getList("textures", 10); // Safe due to method contracts ++ for (int i = 0; i < textures.size(); i++) { ++ if (textures.get(i) instanceof CompoundTag && !((CompoundTag) textures.get(i)).contains("Signature", 8) && ((CompoundTag) textures.get(i)).getString("Value").trim().isEmpty()) { ++ nbttagcompound.remove("SkullOwner"); ++ break; ++ } ++ } ++ // CraftBukkit end + } + + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java.patch new file mode 100644 index 0000000000..86289c3ead --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java.patch @@ -0,0 +1,69 @@ +--- a/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +@@ -32,6 +33,11 @@ + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.player.PlayerTeleportEvent; ++// CraftBukkit end + + public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { + +@@ -174,12 +175,12 @@ + theendgatewayblockentity.teleportCooldown = 100; + BlockPos blockpos1; + +- if (theendgatewayblockentity.exitPortal == null && level.dimension() == Level.END) { +- blockpos1 = findOrCreateValidTeleportPos(serverlevel, blockpos); +- blockpos1 = blockpos1.above(10); +- TheEndGatewayBlockEntity.LOGGER.debug("Creating portal at {}", blockpos1); +- spawnGatewayPortal(serverlevel, blockpos1, EndGatewayConfiguration.knownExit(blockpos, false)); +- theendgatewayblockentity.exitPortal = blockpos1; ++ if (blockEntity.exitPortal == null && level.getTypeKey() == LevelStem.END) { // CraftBukkit - work in alternate worlds ++ blockposition1 = findOrCreateValidTeleportPos(worldserver, pos); ++ blockposition1 = blockposition1.above(10); ++ TheEndGatewayBlockEntity.LOGGER.debug("Creating portal at {}", blockposition1); ++ spawnGatewayPortal(worldserver, blockposition1, EndGatewayConfiguration.knownExit(pos, false)); ++ blockEntity.exitPortal = blockposition1; + } + + if (theendgatewayblockentity.exitPortal != null) { +@@ -203,8 +204,34 @@ + entity1 = entity.getRootVehicle(); + } + ++ // CraftBukkit start - Fire PlayerTeleportEvent/EntityTeleportEvent ++ if (entity1 instanceof ServerPlayer) { ++ org.bukkit.craftbukkit.entity.CraftPlayer player = (CraftPlayer) entity1.getBukkitEntity(); ++ org.bukkit.Location location = CraftLocation.toBukkit(blockposition1, level.getWorld()).add(0.5D, 0.5D, 0.5D); ++ location.setPitch(player.getLocation().getPitch()); ++ location.setYaw(player.getLocation().getYaw()); ++ ++ PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.END_GATEWAY); ++ Bukkit.getPluginManager().callEvent(teleEvent); ++ if (teleEvent.isCancelled()) { ++ return; ++ } ++ ++ entity1.setPortalCooldown(); ++ ((ServerPlayer) entity1).connection.teleport(teleEvent.getTo()); ++ triggerCooldown(level, pos, state, blockEntity); // CraftBukkit - call at end of method ++ return; ++ ++ } ++ ++ org.bukkit.event.entity.EntityTeleportEvent teleEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTeleportEvent(entity1, blockposition1.getX() + 0.5, blockposition1.getY() + 0.5, blockposition1.getZ() + 0.5); ++ if (teleEvent.isCancelled()) { ++ return; ++ } ++ + entity1.setPortalCooldown(); +- entity1.teleportToWithTicket((double) blockpos1.getX() + 0.5D, (double) blockpos1.getY(), (double) blockpos1.getZ() + 0.5D); ++ entity1.teleportToWithTicket(teleEvent.getTo().getX(), teleEvent.getTo().getY(), teleEvent.getTo().getZ()); ++ // CraftBukkit end + } + + triggerCooldown(level, blockpos, blockstate, theendgatewayblockentity); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/piston/PistonBaseBlock.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/piston/PistonBaseBlock.java.patch new file mode 100644 index 0000000000..cf6b0a02ef --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/piston/PistonBaseBlock.java.patch @@ -0,0 +1,89 @@ +--- a/net/minecraft/world/level/block/piston/PistonBaseBlock.java ++++ b/net/minecraft/world/level/block/piston/PistonBaseBlock.java +@@ -40,6 +40,13 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import com.google.common.collect.ImmutableList; ++import java.util.AbstractList; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockPistonRetractEvent; ++import org.bukkit.event.block.BlockPistonExtendEvent; ++// CraftBukkit end + + public class PistonBaseBlock extends DirectionalBlock { + +@@ -157,7 +158,19 @@ + } + } + +- level.blockEvent(blockpos, this, b0, direction.get3DDataValue()); ++ // CraftBukkit start ++ if (!this.isSticky) { ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ BlockPistonRetractEvent event = new BlockPistonRetractEvent(block, ImmutableList.of(), CraftBlock.notchToBlockFace(enumdirection)); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // PAIL: checkME - what happened to setTypeAndData? ++ // CraftBukkit end ++ level.blockEvent(pos, this, b0, enumdirection.get3DDataValue()); + } + + } +@@ -338,8 +350,50 @@ + BlockState[] ablockstate = new BlockState[list.size() + list2.size()]; + Direction direction1 = flag ? direction : direction.getOpposite(); + int i = 0; ++ // CraftBukkit start ++ final org.bukkit.block.Block bblock = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); + +- BlockPos blockpos3; ++ final List moved = pistonextendschecker.getToPush(); ++ final List broken = pistonextendschecker.getToDestroy(); ++ ++ List blocks = new AbstractList() { ++ ++ @Override ++ public int size() { ++ return moved.size() + broken.size(); ++ } ++ ++ @Override ++ public org.bukkit.block.Block get(int index) { ++ if (index >= size() || index < 0) { ++ throw new ArrayIndexOutOfBoundsException(index); ++ } ++ BlockPos pos = (BlockPos) (index < moved.size() ? moved.get(index) : broken.get(index - moved.size())); ++ return bblock.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ } ++ }; ++ org.bukkit.event.block.BlockPistonEvent event; ++ if (extending) { ++ event = new BlockPistonExtendEvent(bblock, blocks, CraftBlock.notchToBlockFace(enumdirection1)); ++ } else { ++ event = new BlockPistonRetractEvent(bblock, blocks, CraftBlock.notchToBlockFace(enumdirection1)); ++ } ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ for (BlockPos b : broken) { ++ level.sendBlockUpdated(b, Blocks.AIR.defaultBlockState(), level.getBlockState(b), 3); ++ } ++ for (BlockPos b : moved) { ++ level.sendBlockUpdated(b, Blocks.AIR.defaultBlockState(), level.getBlockState(b), 3); ++ b = b.relative(enumdirection1); ++ level.sendBlockUpdated(b, Blocks.AIR.defaultBlockState(), level.getBlockState(b), 3); ++ } ++ return false; ++ } ++ // CraftBukkit end ++ ++ BlockPos blockposition3; + int j; + BlockState blockstate1; + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/state/BlockBehaviour.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/state/BlockBehaviour.java.patch new file mode 100644 index 0000000000..70419eb747 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/block/state/BlockBehaviour.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -188,8 +188,10 @@ + BlockEntity blockentity = blockstate.hasBlockEntity() ? level.getBlockEntity(blockpos) : null; + LootParams.Builder lootparams_builder = (new LootParams.Builder(serverlevel)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockpos)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withOptionalParameter(LootContextParams.BLOCK_ENTITY, blockentity).withOptionalParameter(LootContextParams.THIS_ENTITY, explosion.getDirectSourceEntity()); + +- if (explosion.getBlockInteraction() == Explosion.BlockInteraction.DESTROY_WITH_DECAY) { +- lootparams_builder.withParameter(LootContextParams.EXPLOSION_RADIUS, explosion.radius()); ++ // CraftBukkit start - add yield ++ if (explosion.yield < 1.0F) { ++ lootparams_a.withParameter(LootContextParams.EXPLOSION_RADIUS, 1.0F / explosion.yield); ++ // CraftBukkit end + } + + blockstate.spawnAfterBreak(serverlevel, blockpos, ItemStack.EMPTY, flag); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/border/WorldBorder.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/border/WorldBorder.java.patch new file mode 100644 index 0000000000..45f0b0b718 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/border/WorldBorder.java.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/level/border/WorldBorder.java ++++ b/net/minecraft/world/level/border/WorldBorder.java +@@ -29,6 +29,7 @@ + int absoluteMaxSize = 29999984; + private WorldBorder.BorderExtent extent = new WorldBorder.StaticBorderExtent(5.9999968E7D); + public static final WorldBorder.Settings DEFAULT_SETTINGS = new WorldBorder.Settings(0.0D, 0.0D, 0.2D, 5.0D, 5, 15, 5.9999968E7D, 0L, 0.0D); ++ public net.minecraft.server.level.ServerLevel world; // CraftBukkit + + public WorldBorder() {} + +@@ -163,8 +164,9 @@ + return Lists.newArrayList(this.listeners); + } + +- public void addListener(BorderChangeListener borderchangelistener) { +- this.listeners.add(borderchangelistener); ++ public void addListener(BorderChangeListener listener) { ++ if (listeners.contains(listener)) return; // CraftBukkit ++ this.listeners.add(listener); + } + + public void removeListener(BorderChangeListener borderchangelistener) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/ChunkAccess.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/ChunkAccess.java.patch new file mode 100644 index 0000000000..ecc6a59334 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/ChunkAccess.java.patch @@ -0,0 +1,102 @@ +--- a/net/minecraft/world/level/chunk/ChunkAccess.java ++++ b/net/minecraft/world/level/chunk/ChunkAccess.java +@@ -82,25 +82,34 @@ + protected final LevelHeightAccessor levelHeightAccessor; + protected final LevelChunkSection[] sections; + +- public ChunkAccess(ChunkPos chunkpos, UpgradeData upgradedata, LevelHeightAccessor levelheightaccessor, Registry registry, long i, @Nullable LevelChunkSection[] alevelchunksection, @Nullable BlendingData blendingdata) { +- this.chunkPos = chunkpos; +- this.upgradeData = upgradedata; +- this.levelHeightAccessor = levelheightaccessor; +- this.sections = new LevelChunkSection[levelheightaccessor.getSectionsCount()]; +- this.inhabitedTime = i; +- this.postProcessing = new ShortList[levelheightaccessor.getSectionsCount()]; +- this.blendingData = blendingdata; +- this.skyLightSources = new ChunkSkyLightSources(levelheightaccessor); +- if (alevelchunksection != null) { +- if (this.sections.length == alevelchunksection.length) { +- System.arraycopy(alevelchunksection, 0, this.sections, 0, this.sections.length); ++ // CraftBukkit start - SPIGOT-6814: move to IChunkAccess to account for 1.17 to 1.18 chunk upgrading. ++ private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry(); ++ public org.bukkit.craftbukkit.persistence.DirtyCraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.DirtyCraftPersistentDataContainer(DATA_TYPE_REGISTRY); ++ // CraftBukkit end ++ ++ public ChunkAccess(ChunkPos chunkPos, UpgradeData upgradeData, LevelHeightAccessor levelHeightAccessor, Registry biomeRegistry, long inhabitedTime, @Nullable LevelChunkSection[] achunksection, @Nullable BlendingData sections) { ++ this.chunkPos = chunkPos; ++ this.upgradeData = upgradeData; ++ this.levelHeightAccessor = levelHeightAccessor; ++ this.sections = new LevelChunkSection[levelHeightAccessor.getSectionsCount()]; ++ this.inhabitedTime = inhabitedTime; ++ this.postProcessing = new ShortList[levelHeightAccessor.getSectionsCount()]; ++ this.blendingData = sections; ++ this.skyLightSources = new ChunkSkyLightSources(levelHeightAccessor); ++ if (achunksection != null) { ++ if (this.sections.length == achunksection.length) { ++ System.arraycopy(achunksection, 0, this.sections, 0, this.sections.length); + } else { + ChunkAccess.LOGGER.warn("Could not set level chunk sections, array length is {} instead of {}", alevelchunksection.length, this.sections.length); + } + } + +- replaceMissingSections(registry, this.sections); ++ replaceMissingSections(biomeRegistry, this.sections); ++ // CraftBukkit start ++ this.biomeRegistry = biomeRegistry; + } ++ public final Registry biomeRegistry; ++ // CraftBukkit end + + private static void replaceMissingSections(Registry registry, LevelChunkSection[] alevelchunksection) { + for (int i = 0; i < alevelchunksection.length; ++i) { +@@ -267,12 +270,13 @@ + return true; + } + +- public void setUnsaved(boolean flag) { +- this.unsaved = flag; ++ public void setUnsaved(boolean unsaved) { ++ this.unsaved = unsaved; ++ if (!unsaved) this.persistentDataContainer.dirty(false); // CraftBukkit - SPIGOT-6814: chunk was saved, pdc is no longer dirty + } + + public boolean isUnsaved() { +- return this.unsaved; ++ return this.unsaved || this.persistentDataContainer.dirty(); // CraftBukkit - SPIGOT-6814: chunk is unsaved if pdc was mutated + } + + public abstract ChunkStatus getStatus(); +@@ -445,12 +445,33 @@ + CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting biome"); + CrashReportCategory crashreportcategory = crashreport.addCategory("Biome being got"); + +- crashreportcategory.setDetail("Location", () -> { ++ crashreportsystemdetails.setDetail("Location", () -> { ++ return CrashReportCategory.formatLocation(this, x, y, z); ++ }); ++ throw new ReportedException(crashreport); ++ } ++ } ++ ++ // CraftBukkit start ++ public void setBiome(int i, int j, int k, Holder biome) { ++ try { ++ int l = QuartPos.fromBlock(this.getMinBuildHeight()); ++ int i1 = l + QuartPos.fromBlock(this.getHeight()) - 1; ++ int j1 = Mth.clamp(j, l, i1); ++ int k1 = this.getSectionIndex(QuartPos.toBlock(j1)); ++ ++ this.sections[k1].setBiome(i & 3, j1 & 3, k & 3, biome); ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Setting biome"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Biome being set"); ++ ++ crashreportsystemdetails.setDetail("Location", () -> { + return CrashReportCategory.formatLocation(this, i, j, k); + }); + throw new ReportedException(crashreport); + } + } ++ // CraftBukkit end + + public void fillBiomesFromNoise(BiomeResolver biomeresolver, Climate.Sampler climate_sampler) { + ChunkPos chunkpos = this.getPos(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/ChunkGenerator.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/ChunkGenerator.java.patch new file mode 100644 index 0000000000..5e896beacf --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/ChunkGenerator.java.patch @@ -0,0 +1,74 @@ +--- a/net/minecraft/world/level/chunk/ChunkGenerator.java ++++ b/net/minecraft/world/level/chunk/ChunkGenerator.java +@@ -307,8 +306,8 @@ + } + } + +- public void applyBiomeDecoration(WorldGenLevel worldgenlevel, ChunkAccess chunkaccess, StructureManager structuremanager) { +- ChunkPos chunkpos = chunkaccess.getPos(); ++ public void addVanillaDecorations(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager) { // CraftBukkit ++ ChunkPos chunkcoordintpair = ichunkaccess.getPos(); + + if (!SharedConstants.debugVoidTerrain(chunkpos)) { + SectionPos sectionpos = SectionPos.of(chunkpos, worldgenlevel.getMinSection()); +@@ -440,11 +439,38 @@ + } + } + +- private static BoundingBox getWritableArea(ChunkAccess chunkaccess) { +- ChunkPos chunkpos = chunkaccess.getPos(); +- int i = chunkpos.getMinBlockX(); +- int j = chunkpos.getMinBlockZ(); +- LevelHeightAccessor levelheightaccessor = chunkaccess.getHeightAccessorForGeneration(); ++ // CraftBukkit start ++ public void applyBiomeDecoration(WorldGenLevel level, ChunkAccess chunk, StructureManager structureManager) { ++ applyBiomeDecoration(level, chunk, structureManager, true); ++ } ++ ++ public void applyBiomeDecoration(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager, boolean vanilla) { ++ if (vanilla) { ++ addVanillaDecorations(generatoraccessseed, ichunkaccess, structuremanager); ++ } ++ ++ org.bukkit.World world = generatoraccessseed.getMinecraftWorld().getWorld(); ++ // only call when a populator is present (prevents unnecessary entity conversion) ++ if (!world.getPopulators().isEmpty()) { ++ org.bukkit.craftbukkit.generator.CraftLimitedRegion limitedRegion = new org.bukkit.craftbukkit.generator.CraftLimitedRegion(generatoraccessseed, ichunkaccess.getPos()); ++ int x = ichunkaccess.getPos().x; ++ int z = ichunkaccess.getPos().z; ++ for (org.bukkit.generator.BlockPopulator populator : world.getPopulators()) { ++ WorldgenRandom seededrandom = new WorldgenRandom(new net.minecraft.world.level.levelgen.LegacyRandomSource(generatoraccessseed.getSeed())); ++ seededrandom.setDecorationSeed(generatoraccessseed.getSeed(), x, z); ++ populator.populate(world, new org.bukkit.craftbukkit.util.RandomSourceWrapper.RandomWrapper(seededrandom), x, z, limitedRegion); ++ } ++ limitedRegion.saveEntities(); ++ limitedRegion.breakLink(); ++ } ++ } ++ // CraftBukkit end ++ ++ private static BoundingBox getWritableArea(ChunkAccess chunk) { ++ ChunkPos chunkcoordintpair = chunk.getPos(); ++ int i = chunkcoordintpair.getMinBlockX(); ++ int j = chunkcoordintpair.getMinBlockZ(); ++ LevelHeightAccessor levelheightaccessor = chunk.getHeightAccessorForGeneration(); + int k = levelheightaccessor.getMinBuildHeight() + 1; + int l = levelheightaccessor.getMaxBuildHeight() - 1; + +@@ -577,7 +603,15 @@ + StructureStart structurestart = structure.generate(registryaccess, this, this.biomeSource, randomstate, structuretemplatemanager, i, chunkpos, j, chunkaccess, predicate); + + if (structurestart.isValid()) { +- structuremanager.setStartForStructure(sectionpos, structure, structurestart, chunkaccess); ++ // CraftBukkit start ++ BoundingBox box = structurestart.getBoundingBox(); ++ org.bukkit.event.world.AsyncStructureSpawnEvent event = new org.bukkit.event.world.AsyncStructureSpawnEvent(structureManager.level.getMinecraftWorld().getWorld(), org.bukkit.craftbukkit.generator.structure.CraftStructure.minecraftToBukkit(structure, registryAccess), new org.bukkit.util.BoundingBox(box.minX(), box.minY(), box.minZ(), box.maxX(), box.maxY(), box.maxZ()), chunk.x, chunk.z); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return true; ++ } ++ // CraftBukkit end ++ structureManager.setStartForStructure(chunkPos, structure, structurestart, ichunkaccess); + return true; + } else { + return false; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/ChunkStatus.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/ChunkStatus.java.patch new file mode 100644 index 0000000000..2e317e64ea --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/ChunkStatus.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/level/chunk/ChunkStatus.java ++++ b/net/minecraft/world/level/chunk/ChunkStatus.java +@@ -38,9 +38,9 @@ + }; + public static final ChunkStatus EMPTY = registerSimple("empty", (ChunkStatus) null, -1, ChunkStatus.PRE_FEATURES, ChunkStatus.ChunkType.PROTOCHUNK, (chunkstatus, serverlevel, chunkgenerator, list, chunkaccess) -> { + }); +- public static final ChunkStatus STRUCTURE_STARTS = register("structure_starts", ChunkStatus.EMPTY, 0, false, ChunkStatus.PRE_FEATURES, ChunkStatus.ChunkType.PROTOCHUNK, (chunkstatus, executor, serverlevel, chunkgenerator, structuretemplatemanager, threadedlevellightengine, function, list, chunkaccess) -> { +- if (serverlevel.getServer().getWorldData().worldGenOptions().generateStructures()) { +- chunkgenerator.createStructures(serverlevel.registryAccess(), serverlevel.getChunkSource().getGeneratorState(), serverlevel.structureManager(), chunkaccess, structuretemplatemanager); ++ public static final ChunkStatus STRUCTURE_STARTS = register("structure_starts", ChunkStatus.EMPTY, 0, false, ChunkStatus.PRE_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, executor, worldserver, chunkgenerator, structuretemplatemanager, lightenginethreaded, function, list, ichunkaccess) -> { ++ if (worldserver.serverLevelData.worldGenOptions().generateStructures()) { // CraftBukkit ++ chunkgenerator.createStructures(worldserver.registryAccess(), worldserver.getChunkSource().getGeneratorState(), worldserver.structureManager(), ichunkaccess, structuretemplatemanager); + } + + serverlevel.onStructureStartsAvailable(chunkaccess); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/DataLayer.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/DataLayer.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/DataLayer.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/LevelChunk.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/LevelChunk.java.patch new file mode 100644 index 0000000000..dc92d39044 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/LevelChunk.java.patch @@ -0,0 +1,185 @@ +--- a/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/net/minecraft/world/level/chunk/LevelChunk.java +@@ -78,8 +74,8 @@ + } + }; + private final Map tickersInLevel; +- private boolean loaded; +- final Level level; ++ public boolean loaded; ++ public final ServerLevel level; // CraftBukkit - type + @Nullable + private Supplier fullStatus; + @Nullable +@@ -95,7 +91,7 @@ + public LevelChunk(Level level, ChunkPos chunkpos, UpgradeData upgradedata, LevelChunkTicks levelchunkticks, LevelChunkTicks levelchunkticks1, long i, @Nullable LevelChunkSection[] alevelchunksection, @Nullable LevelChunk.PostLoadProcessor levelchunk_postloadprocessor, @Nullable BlendingData blendingdata) { + super(chunkpos, upgradedata, level, level.registryAccess().registryOrThrow(Registries.BIOME), i, alevelchunksection, blendingdata); + this.tickersInLevel = Maps.newHashMap(); +- this.level = level; ++ this.level = (ServerLevel) level; // CraftBukkit - type + this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap(); + Heightmap.Types[] aheightmap_types = Heightmap.Types.values(); + int j = aheightmap_types.length; +@@ -113,9 +109,10 @@ + this.fluidTicks = levelchunkticks1; + } + +- public LevelChunk(ServerLevel serverlevel, ProtoChunk protochunk, @Nullable LevelChunk.PostLoadProcessor levelchunk_postloadprocessor) { +- this(serverlevel, protochunk.getPos(), protochunk.getUpgradeData(), protochunk.unpackBlockTicks(), protochunk.unpackFluidTicks(), protochunk.getInhabitedTime(), protochunk.getSections(), levelchunk_postloadprocessor, protochunk.getBlendingData()); +- Iterator iterator = protochunk.getBlockEntities().values().iterator(); ++ // CraftBukkit start ++ public boolean mustNotSave; ++ public boolean needsDecoration; ++ // CraftBukkit end + + while (iterator.hasNext()) { + BlockEntity blockentity = (BlockEntity) iterator.next(); +@@ -144,6 +145,10 @@ + this.skyLightSources = protochunk.skyLightSources; + this.setLightCorrect(protochunk.isLightCorrect()); + this.unsaved = true; ++ this.needsDecoration = true; // CraftBukkit ++ // CraftBukkit start ++ this.persistentDataContainer = chunk.persistentDataContainer; // SPIGOT-6814: copy PDC to account for 1.17 to 1.18 chunk upgrading. ++ // CraftBukkit end + } + + @Override +@@ -254,6 +253,7 @@ + } + } + ++ // CraftBukkit start + @Nullable + @Override + @Override +@@ -262,7 +260,14 @@ + LevelChunkSection levelchunksection = this.getSection(this.getSectionIndex(i)); + boolean flag1 = levelchunksection.hasOnlyAir(); + +- if (flag1 && blockstate.isAir()) { ++ @Nullable ++ public IBlockData setBlockState(BlockPos blockposition, IBlockData iblockdata, boolean flag, boolean doPlace) { ++ // CraftBukkit end ++ int i = blockposition.getY(); ++ LevelChunkSection chunksection = this.getSection(this.getSectionIndex(i)); ++ boolean flag1 = chunksection.hasOnlyAir(); ++ ++ if (flag1 && iblockdata.isAir()) { + return null; + } else { + int j = blockpos.getX() & 15; +@@ -306,8 +311,9 @@ + if (!levelchunksection.getBlockState(j, k, l).is(block)) { + return null; + } else { +- if (!this.level.isClientSide) { +- blockstate.onPlace(this.level, blockpos, blockstate1, flag); ++ // CraftBukkit - Don't place while processing the BlockPlaceEvent, unless it's a BlockContainer. Prevents blocks such as TNT from activating when cancelled. ++ if (!this.level.isClientSide && doPlace && (!this.level.captureBlockStates || block instanceof net.minecraft.world.level.block.BaseEntityBlock)) { ++ iblockdata.onPlace(this.level, blockposition, iblockdata1, flag); + } + + if (blockstate.hasBlockEntity()) { +@@ -352,8 +356,13 @@ + } + + @Nullable +- public BlockEntity getBlockEntity(BlockPos blockpos, LevelChunk.EntityCreationType levelchunk_entitycreationtype) { +- BlockEntity blockentity = (BlockEntity) this.blockEntities.get(blockpos); ++ public BlockEntity getBlockEntity(BlockPos pos, LevelChunk.EnumTileEntityState creationType) { ++ // CraftBukkit start ++ BlockEntity tileentity = level.capturedTileEntities.get(pos); ++ if (tileentity == null) { ++ tileentity = (BlockEntity) this.blockEntities.get(pos); ++ } ++ // CraftBukkit end + + if (blockentity == null) { + CompoundTag compoundtag = (CompoundTag) this.pendingBlockEntities.remove(blockpos); +@@ -432,6 +440,13 @@ + blockentity1.setRemoved(); + } + ++ // CraftBukkit start ++ } else { ++ System.out.println("Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() ++ + " (" + getBlockState(blockposition) + ") where there was no entity tile!"); ++ System.out.println("Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); ++ new Exception().printStackTrace(); ++ // CraftBukkit end + } + } + +@@ -463,8 +476,11 @@ + if (this.isInLevel()) { + BlockEntity blockentity = (BlockEntity) this.blockEntities.remove(blockpos); + +- if (blockentity != null) { +- Level level = this.level; ++ // CraftBukkit start - SPIGOT-5561: Also remove from pending map ++ if (!pendingBlockEntities.isEmpty()) { ++ pendingBlockEntities.remove(pos); ++ } ++ // CraftBukkit end + + if (level instanceof ServerLevel) { + ServerLevel serverlevel = (ServerLevel) level; +@@ -516,6 +535,57 @@ + + } + ++ // CraftBukkit start ++ public void loadCallback() { ++ org.bukkit.Server server = this.level.getCraftServer(); ++ if (server != null) { ++ /* ++ * If it's a new world, the first few chunks are generated inside ++ * the World constructor. We can't reliably alter that, so we have ++ * no way of creating a CraftWorld/CraftServer at that point. ++ */ ++ org.bukkit.Chunk bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this); ++ server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(bukkitChunk, this.needsDecoration)); ++ ++ if (this.needsDecoration) { ++ this.needsDecoration = false; ++ java.util.Random random = new java.util.Random(); ++ random.setSeed(level.getSeed()); ++ long xRand = random.nextLong() / 2L * 2L + 1L; ++ long zRand = random.nextLong() / 2L * 2L + 1L; ++ random.setSeed((long) this.chunkPos.x * xRand + (long) this.chunkPos.z * zRand ^ level.getSeed()); ++ ++ org.bukkit.World world = this.level.getWorld(); ++ if (world != null) { ++ this.level.populating = true; ++ try { ++ for (org.bukkit.generator.BlockPopulator populator : world.getPopulators()) { ++ populator.populate(world, random, bukkitChunk); ++ } ++ } finally { ++ this.level.populating = false; ++ } ++ } ++ server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk)); ++ } ++ } ++ } ++ ++ public void unloadCallback() { ++ org.bukkit.Server server = this.level.getCraftServer(); ++ org.bukkit.Chunk bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this); ++ org.bukkit.event.world.ChunkUnloadEvent unloadEvent = new org.bukkit.event.world.ChunkUnloadEvent(bukkitChunk, this.isUnsaved()); ++ server.getPluginManager().callEvent(unloadEvent); ++ // note: saving can be prevented, but not forced if no saving is actually required ++ this.mustNotSave = !unloadEvent.isSaveChunk(); ++ } ++ ++ @Override ++ public boolean isUnsaved() { ++ return super.isUnsaved() && !this.mustNotSave; ++ } ++ // CraftBukkit end ++ + public boolean isEmpty() { + return false; + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/LevelChunkSection.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/LevelChunkSection.java.patch new file mode 100644 index 0000000000..87bf8fcc9d --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/LevelChunkSection.java.patch @@ -0,0 +1,37 @@ +--- a/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -22,11 +22,13 @@ + private short nonEmptyBlockCount; + private short tickingBlockCount; + private short tickingFluidCount; +- private final PalettedContainer states; +- private PalettedContainerRO> biomes; ++ private final PalettedContainer states; ++ // CraftBukkit start - read/write ++ private PalettedContainer> biomes; + +- public LevelChunkSection(PalettedContainer palettedcontainer, PalettedContainerRO> palettedcontainerro) { +- this.states = palettedcontainer; ++ public LevelChunkSection(PalettedContainer datapaletteblock, PalettedContainer> palettedcontainerro) { ++ // CraftBukkit end ++ this.states = datapaletteblock; + this.biomes = palettedcontainerro; + this.recalcBlockCounts(); + } +@@ -189,8 +190,14 @@ + return (Holder) this.biomes.get(i, j, k); + } + +- public void fillBiomesFromNoise(BiomeResolver biomeresolver, Climate.Sampler climate_sampler, int i, int j, int k) { +- PalettedContainer> palettedcontainer = this.biomes.recreate(); ++ // CraftBukkit start ++ public void setBiome(int i, int j, int k, Holder biome) { ++ this.biomes.set(i, j, k, biome); ++ } ++ // CraftBukkit end ++ ++ public void fillBiomesFromNoise(BiomeResolver biomeResolver, Climate.Sampler climateSampler, int x, int y, int z) { ++ PalettedContainer> datapaletteblock = this.biomes.recreate(); + boolean flag = true; + + for (int l = 0; l < 4; ++l) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/storage/ChunkSerializer.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/storage/ChunkSerializer.java.patch new file mode 100644 index 0000000000..1f6ebd7010 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/storage/ChunkSerializer.java.patch @@ -0,0 +1,94 @@ +--- a/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -93,16 +93,16 @@ + ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", new Object[]{chunkpos, chunkpos, chunkpos1}); + } + +- UpgradeData upgradedata = compoundtag.contains("UpgradeData", 10) ? new UpgradeData(compoundtag.getCompound("UpgradeData"), serverlevel) : UpgradeData.EMPTY; +- boolean flag = compoundtag.getBoolean("isLightOn"); +- ListTag listtag = compoundtag.getList("sections", 10); +- int i = serverlevel.getSectionsCount(); +- LevelChunkSection[] alevelchunksection = new LevelChunkSection[i]; +- boolean flag1 = serverlevel.dimensionType().hasSkyLight(); +- ServerChunkCache serverchunkcache = serverlevel.getChunkSource(); +- LevelLightEngine levellightengine = serverchunkcache.getLightEngine(); +- Registry registry = serverlevel.registryAccess().registryOrThrow(Registries.BIOME); +- Codec>> codec = makeBiomeCodec(registry); ++ UpgradeData chunkconverter = tag.contains("UpgradeData", 10) ? new UpgradeData(tag.getCompound("UpgradeData"), level) : UpgradeData.EMPTY; ++ boolean flag = tag.getBoolean("isLightOn"); ++ ListTag nbttaglist = tag.getList("sections", 10); ++ int i = level.getSectionsCount(); ++ LevelChunkSection[] achunksection = new LevelChunkSection[i]; ++ boolean flag1 = level.dimensionType().hasSkyLight(); ++ ServerChunkCache chunkproviderserver = level.getChunkSource(); ++ LevelLightEngine levellightengine = chunkproviderserver.getLightEngine(); ++ Registry iregistry = level.registryAccess().registryOrThrow(Registries.BIOME); ++ Codec>> codec = makeBiomeCodecRW(iregistry); // CraftBukkit - read/write + boolean flag2 = false; + + DataResult dataresult; +@@ -127,7 +127,7 @@ + palettedcontainer = new PalettedContainer<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES); + } + +- Object object; ++ PalettedContainer object; // CraftBukkit - read/write + + if (compoundtag1.contains("biomes", 10)) { + dataresult = codec.parse(NbtOps.INSTANCE, compoundtag1.getCompound("biomes")).promotePartial((s) -> { +@@ -140,7 +140,7 @@ + object = new PalettedContainer<>(registry.asHolderIdMap(), registry.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES); + } + +- LevelChunkSection levelchunksection = new LevelChunkSection(palettedcontainer, (PalettedContainerRO) object); ++ LevelChunkSection chunksection = new LevelChunkSection(datapaletteblock, (PalettedContainer) object); // CraftBukkit - read/write + + alevelchunksection[k] = levelchunksection; + SectionPos sectionpos = SectionPos.of(chunkpos, b0); +@@ -221,6 +221,13 @@ + } + } + ++ // CraftBukkit start - load chunk persistent data from nbt - SPIGOT-6814: Already load PDC here to account for 1.17 to 1.18 chunk upgrading. ++ net.minecraft.nbt.Tag persistentBase = tag.get("ChunkBukkitValues"); ++ if (persistentBase instanceof CompoundTag) { ++ ((ChunkAccess) object1).persistentDataContainer.putAll((CompoundTag) persistentBase); ++ } ++ // CraftBukkit end ++ + ((ChunkAccess) object1).setLightCorrect(flag); + CompoundTag compoundtag2 = compoundtag.getCompound("Heightmaps"); + EnumSet enumset = EnumSet.noneOf(Heightmap.Types.class); +@@ -300,9 +307,11 @@ + return PalettedContainer.codecRO(registry.asHolderIdMap(), registry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, registry.getHolderOrThrow(Biomes.PLAINS)); + } + +- public static CompoundTag write(ServerLevel serverlevel, ChunkAccess chunkaccess) { +- ChunkPos chunkpos = chunkaccess.getPos(); +- CompoundTag compoundtag = NbtUtils.addCurrentDataVersion(new CompoundTag()); ++ // CraftBukkit start - read/write ++ private static Codec>> makeBiomeCodecRW(Registry iregistry) { ++ return PalettedContainer.codecRW(iregistry.asHolderIdMap(), iregistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, iregistry.getHolderOrThrow(Biomes.PLAINS)); ++ } ++ // CraftBukkit end + + compoundtag.putInt("xPos", chunkpos.x); + compoundtag.putInt("yPos", chunkaccess.getMinSection()); +@@ -439,9 +452,14 @@ + } + } + +- compoundtag.put("Heightmaps", compoundtag3); +- compoundtag.put("structures", packStructureData(StructurePieceSerializationContext.fromLevel(serverlevel), chunkpos, chunkaccess.getAllStarts(), chunkaccess.getAllReferences())); +- return compoundtag; ++ nbttagcompound.put("Heightmaps", nbttagcompound3); ++ nbttagcompound.put("structures", packStructureData(StructurePieceSerializationContext.fromLevel(level), chunkcoordintpair, chunk.getAllStarts(), chunk.getAllReferences())); ++ // CraftBukkit start - store chunk persistent data in nbt ++ if (!chunk.persistentDataContainer.isEmpty()) { // SPIGOT-6814: Always save PDC to account for 1.17 to 1.18 chunk upgrading. ++ nbttagcompound.put("ChunkBukkitValues", chunk.persistentDataContainer.toTagCompound()); ++ } ++ // CraftBukkit end ++ return nbttagcompound; + } + + private static void saveTicks(ServerLevel serverlevel, CompoundTag compoundtag, ChunkAccess.TicksToSave chunkaccess_tickstosave) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/storage/ChunkStorage.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/storage/ChunkStorage.java.patch new file mode 100644 index 0000000000..b8f6e2e997 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/storage/ChunkStorage.java.patch @@ -0,0 +1,91 @@ +--- a/net/minecraft/world/level/chunk/storage/ChunkStorage.java ++++ b/net/minecraft/world/level/chunk/storage/ChunkStorage.java +@@ -16,6 +18,10 @@ + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.chunk.ChunkGenerator; ++// CraftBukkit start ++import java.util.concurrent.ExecutionException; ++import net.minecraft.world.level.chunk.ChunkStatus; ++import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.levelgen.structure.LegacyStructureDataHandler; + import net.minecraft.world.level.storage.DimensionDataStorage; + +@@ -36,9 +42,53 @@ + return this.worker.isOldChunkAround(chunkpos, i); + } + +- public CompoundTag upgradeChunkTag(ResourceKey resourcekey, Supplier supplier, CompoundTag compoundtag, Optional>> optional) { +- int i = getVersion(compoundtag); ++ // CraftBukkit start ++ private boolean check(ServerChunkCache cps, int x, int z) { ++ ChunkPos pos = new ChunkPos(x, z); ++ if (cps != null) { ++ com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); ++ if (cps.hasChunk(x, z)) { ++ return true; ++ } ++ } + ++ CompoundTag nbt; ++ try { ++ nbt = read(pos).get().orElse(null); ++ } catch (InterruptedException | ExecutionException ex) { ++ throw new RuntimeException(ex); ++ } ++ if (nbt != null) { ++ CompoundTag level = nbt.getCompound("Level"); ++ if (level.getBoolean("TerrainPopulated")) { ++ return true; ++ } ++ ++ ChunkStatus status = ChunkStatus.byName(level.getString("Status")); ++ if (status != null && status.isOrAfter(ChunkStatus.FEATURES)) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ public CompoundTag upgradeChunkTag(ResourceKey resourcekey, Supplier supplier, CompoundTag nbttagcompound, Optional>> optional, ChunkPos pos, @Nullable LevelAccessor generatoraccess) { ++ // CraftBukkit end ++ int i = getVersion(nbttagcompound); ++ ++ // CraftBukkit start ++ if (i < 1466) { ++ CompoundTag level = nbttagcompound.getCompound("Level"); ++ if (level.getBoolean("TerrainPopulated") && !level.getBoolean("LightPopulated")) { ++ ServerChunkCache cps = (generatoraccess == null) ? null : ((ServerLevel) generatoraccess).getChunkSource(); ++ if (check(cps, pos.x - 1, pos.z) && check(cps, pos.x - 1, pos.z - 1) && check(cps, pos.x, pos.z - 1)) { ++ level.putBoolean("LightPopulated", true); ++ } ++ } ++ } ++ // CraftBukkit end ++ + if (i < 1493) { + compoundtag = DataFixTypes.CHUNK.update(this.fixerUpper, compoundtag, i, 1493); + if (compoundtag.getCompound("Level").getBoolean("hasLegacyStructureData")) { +@@ -58,8 +108,8 @@ + return compoundtag; + } + +- private LegacyStructureDataHandler getLegacyStructureHandler(ResourceKey resourcekey, Supplier supplier) { +- LegacyStructureDataHandler legacystructuredatahandler = this.legacyStructureHandler; ++ private LegacyStructureDataHandler getLegacyStructureHandler(ResourceKey level, Supplier storage) { // CraftBukkit ++ LegacyStructureDataHandler persistentstructurelegacy = this.legacyStructureHandler; + + if (legacystructuredatahandler == null) { + synchronized (this) { +@@ -73,8 +123,8 @@ + return legacystructuredatahandler; + } + +- public static void injectDatafixingContext(CompoundTag compoundtag, ResourceKey resourcekey, Optional>> optional) { +- CompoundTag compoundtag1 = new CompoundTag(); ++ public static void injectDatafixingContext(CompoundTag chunkData, ResourceKey levelKey, Optional>> chunkGeneratorKey) { // CraftBukkit ++ CompoundTag nbttagcompound1 = new CompoundTag(); + + compoundtag1.putString("dimension", resourcekey.location().toString()); + optional.ifPresent((resourcekey1) -> { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/storage/RegionFile.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/storage/RegionFile.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/storage/RegionFile.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch new file mode 100644 index 0000000000..ce9acb3765 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch @@ -0,0 +1,72 @@ +--- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -30,8 +30,8 @@ + this.sync = flag; + } + +- private RegionFile getRegionFile(ChunkPos chunkpos) throws IOException { +- long i = ChunkPos.asLong(chunkpos.getRegionX(), chunkpos.getRegionZ()); ++ private RegionFile getRegionFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit ++ long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); + RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i); + + if (regionfile != null) { +@@ -43,8 +43,9 @@ + + FileUtil.createDirectoriesSafe(this.folder); + Path path = this.folder; +- int j = chunkpos.getRegionX(); +- Path path1 = path.resolve("r." + j + "." + chunkpos.getRegionZ() + ".mca"); ++ int j = chunkcoordintpair.getRegionX(); ++ Path path1 = path.resolve("r." + j + "." + chunkcoordintpair.getRegionZ() + ".mca"); ++ if (existingOnly && !java.nio.file.Files.exists(path1)) return null; // CraftBukkit + RegionFile regionfile1 = new RegionFile(path1, this.folder, this.sync); + + this.regionCache.putAndMoveToFirst(i, regionfile1); +@@ -53,9 +54,14 @@ + } + + @Nullable +- public CompoundTag read(ChunkPos chunkpos) throws IOException { +- RegionFile regionfile = this.getRegionFile(chunkpos); +- DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkpos); ++ public CompoundTag read(ChunkPos chunkPos) throws IOException { ++ // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing ++ RegionFile regionfile = this.getRegionFile(chunkPos, true); ++ if (regionfile == null) { ++ return null; ++ } ++ // CraftBukkit end ++ DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkPos); + + CompoundTag compoundtag; + label43: +@@ -93,9 +99,14 @@ + return compoundtag; + } + +- public void scanChunk(ChunkPos chunkpos, StreamTagVisitor streamtagvisitor) throws IOException { +- RegionFile regionfile = this.getRegionFile(chunkpos); +- DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkpos); ++ public void scanChunk(ChunkPos chunkPos, StreamTagVisitor visitor) throws IOException { ++ // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing ++ RegionFile regionfile = this.getRegionFile(chunkPos, true); ++ if (regionfile == null) { ++ return; ++ } ++ // CraftBukkit end ++ DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkPos); + + try { + if (datainputstream != null) { +@@ -119,8 +130,8 @@ + + } + +- protected void write(ChunkPos chunkpos, @Nullable CompoundTag compoundtag) throws IOException { +- RegionFile regionfile = this.getRegionFile(chunkpos); ++ protected void write(ChunkPos chunkPos, @Nullable CompoundTag chunkData) throws IOException { ++ RegionFile regionfile = this.getRegionFile(chunkPos, false); // CraftBukkit + + if (compoundtag == null) { + regionfile.clear(chunkpos); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/dimension/end/EndDragonFight.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/dimension/end/EndDragonFight.java.patch new file mode 100644 index 0000000000..53b66c693e --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/dimension/end/EndDragonFight.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -510,7 +510,7 @@ + return this.previouslyKilled; + } + +- public void tryRespawn() { ++ public boolean tryRespawn() { // CraftBukkit - return boolean + if (this.dragonKilled && this.respawnStage == null) { + BlockPos blockpos = this.portalLocation; + +@@ -537,19 +537,19 @@ + List list1 = this.level.getEntitiesOfClass(EndCrystal.class, new AABB(blockpos1.relative(direction, 2))); + + if (list1.isEmpty()) { +- return; ++ return false; // CraftBukkit - return value + } + + list.addAll(list1); + } + + EndDragonFight.LOGGER.debug("Found all crystals, respawning dragon."); +- this.respawnDragon(list); ++ return this.respawnDragon(list); // CraftBukkit - return value + } +- ++ return false; // CraftBukkit - return value + } + +- private void respawnDragon(List list) { ++ public boolean respawnDragon(List list) { // CraftBukkit - return boolean + if (this.dragonKilled && this.respawnStage == null) { + for (BlockPattern.BlockPatternMatch blockpattern_blockpatternmatch = this.findExitPortal(); blockpattern_blockpatternmatch != null; blockpattern_blockpatternmatch = this.findExitPortal()) { + for (int i = 0; i < this.exitPortalPattern.getWidth(); ++i) { +@@ -569,8 +569,9 @@ + this.respawnTime = 0; + this.spawnExitPortal(false); + this.respawnCrystals = list; ++ return true; // CraftBukkit - return value + } +- ++ return false; // CraftBukkit - return value + } + + public void resetSpikeCrystals() { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/entity/PersistentEntitySectionManager.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/entity/PersistentEntitySectionManager.java.patch new file mode 100644 index 0000000000..b7bfb6b1e1 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/entity/PersistentEntitySectionManager.java.patch @@ -0,0 +1,110 @@ +--- a/net/minecraft/world/level/entity/PersistentEntitySectionManager.java ++++ b/net/minecraft/world/level/entity/PersistentEntitySectionManager.java +@@ -31,6 +30,11 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.ChunkPos; + import org.slf4j.Logger; ++import net.minecraft.world.level.ChunkPos; ++// CraftBukkit start ++import net.minecraft.world.level.chunk.storage.EntityStorage; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class PersistentEntitySectionManager implements AutoCloseable { + +@@ -55,7 +59,17 @@ + this.entityGetter = new LevelEntityGetterAdapter<>(this.visibleEntityStorage, this.sectionStorage); + } + +- void removeSectionIfEmpty(long i, EntitySection entitysection) { ++ // CraftBukkit start - add method to get all entities in chunk ++ public List getEntities(ChunkPos chunkCoordIntPair) { ++ return sectionStorage.getExistingSectionsInChunk(chunkCoordIntPair.toLong()).flatMap(EntitySection::getEntities).map(entity -> (Entity) entity).collect(Collectors.toList()); ++ } ++ ++ public boolean isPending(long pair) { ++ return chunkLoadStatuses.get(pair) == b.PENDING; ++ } ++ // CraftBukkit end ++ ++ void removeSectionIfEmpty(long sectionKey, EntitySection entitysection) { + if (entitysection.isEmpty()) { + this.sectionStorage.remove(i); + } +@@ -195,10 +209,16 @@ + + } + +- private boolean storeChunkSections(long i, Consumer consumer) { +- PersistentEntitySectionManager.ChunkLoadStatus persistententitysectionmanager_chunkloadstatus = (PersistentEntitySectionManager.ChunkLoadStatus) this.chunkLoadStatuses.get(i); ++ private boolean storeChunkSections(long chunkPosValue, Consumer consumer) { ++ // CraftBukkit start - add boolean for event call ++ return storeChunkSections(chunkPosValue, consumer, false); ++ } + +- if (persistententitysectionmanager_chunkloadstatus == PersistentEntitySectionManager.ChunkLoadStatus.PENDING) { ++ private boolean storeChunkSections(long i, Consumer consumer, boolean callEvent) { ++ // CraftBukkit end ++ PersistentEntitySectionManager.b persistententitysectionmanager_b = (PersistentEntitySectionManager.b) this.chunkLoadStatuses.get(i); ++ ++ if (persistententitysectionmanager_b == PersistentEntitySectionManager.b.PENDING) { + return false; + } else { + List list = (List) this.sectionStorage.getExistingSectionsInChunk(i).flatMap((entitysection) -> { +@@ -206,7 +226,8 @@ + }).collect(Collectors.toList()); + + if (list.isEmpty()) { +- if (persistententitysectionmanager_chunkloadstatus == PersistentEntitySectionManager.ChunkLoadStatus.LOADED) { ++ if (persistententitysectionmanager_b == PersistentEntitySectionManager.b.LOADED) { ++ if (callEvent) CraftEventFactory.callEntitiesUnloadEvent(((EntityStorage) permanentStorage).level, new ChunkPos(i), ImmutableList.of()); // CraftBukkit + this.permanentStorage.storeEntities(new ChunkEntities<>(new ChunkPos(i), ImmutableList.of())); + } + +@@ -215,6 +236,7 @@ + this.requestChunkLoad(i); + return false; + } else { ++ if (callEvent) CraftEventFactory.callEntitiesUnloadEvent(((EntityStorage) permanentStorage).level, new ChunkPos(i), list.stream().map(entity -> (Entity) entity).collect(Collectors.toList())); // CraftBukkit + this.permanentStorage.storeEntities(new ChunkEntities<>(new ChunkPos(i), list)); + list.forEach(consumer); + return true; +@@ -238,7 +260,7 @@ + private boolean processChunkUnload(long i) { + boolean flag = this.storeChunkSections(i, (entityaccess) -> { + entityaccess.getPassengersAndSelf().forEach(this::unloadEntity); +- }); ++ }, true); // CraftBukkit - add boolean for event call + + if (!flag) { + return false; +@@ -266,7 +288,11 @@ + chunkentities.getEntities().forEach((entityaccess) -> { + this.addEntity(entityaccess, true); + }); +- this.chunkLoadStatuses.put(chunkentities.getPos().toLong(), PersistentEntitySectionManager.ChunkLoadStatus.LOADED); ++ this.chunkLoadStatuses.put(chunkentities.getPos().toLong(), PersistentEntitySectionManager.b.LOADED); ++ // CraftBukkit start - call entity load event ++ List entities = getEntities(chunkentities.getPos()); ++ CraftEventFactory.callEntitiesLoadEvent(((EntityStorage) permanentStorage).level, chunkentities.getPos(), entities); ++ // CraftBukkit end + } + + } +@@ -324,7 +349,15 @@ + + @Override + public void close() throws IOException { +- this.saveAll(); ++ // CraftBukkit start - add save boolean ++ close(true); ++ } ++ ++ public void close(boolean save) throws IOException { ++ if (save) { ++ this.saveAll(); ++ } ++ // CraftBukkit end + this.permanentStorage.close(); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/gameevent/GameEventDispatcher.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/gameevent/GameEventDispatcher.java.patch new file mode 100644 index 0000000000..65e8eb295c --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/gameevent/GameEventDispatcher.java.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/world/level/gameevent/GameEventDispatcher.java ++++ b/net/minecraft/world/level/gameevent/GameEventDispatcher.java +@@ -10,6 +10,12 @@ + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.CraftGameEvent; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.world.GenericGameEvent; ++// CraftBukkit end + + public class GameEventDispatcher { + +@@ -19,15 +25,23 @@ + this.level = serverlevel; + } + +- public void post(GameEvent gameevent, Vec3 vec3, GameEvent.Context gameevent_context) { +- int i = gameevent.getNotificationRadius(); +- BlockPos blockpos = BlockPos.containing(vec3); +- int j = SectionPos.blockToSectionCoord(blockpos.getX() - i); +- int k = SectionPos.blockToSectionCoord(blockpos.getY() - i); +- int l = SectionPos.blockToSectionCoord(blockpos.getZ() - i); +- int i1 = SectionPos.blockToSectionCoord(blockpos.getX() + i); +- int j1 = SectionPos.blockToSectionCoord(blockpos.getY() + i); +- int k1 = SectionPos.blockToSectionCoord(blockpos.getZ() + i); ++ public void post(GameEvent event, Vec3 pos, GameEvent.Context context) { ++ int i = event.getNotificationRadius(); ++ BlockPos blockposition = BlockPos.containing(pos); ++ // CraftBukkit start ++ GenericGameEvent event1 = new GenericGameEvent(CraftGameEvent.minecraftToBukkit(event), CraftLocation.toBukkit(blockposition, level.getWorld()), (context.sourceEntity() == null) ? null : context.sourceEntity().getBukkitEntity(), i, !Bukkit.isPrimaryThread()); ++ level.getCraftServer().getPluginManager().callEvent(event1); ++ if (event1.isCancelled()) { ++ return; ++ } ++ i = event1.getRadius(); ++ // CraftBukkit end ++ int j = SectionPos.blockToSectionCoord(blockposition.getX() - i); ++ int k = SectionPos.blockToSectionCoord(blockposition.getY() - i); ++ int l = SectionPos.blockToSectionCoord(blockposition.getZ() - i); ++ int i1 = SectionPos.blockToSectionCoord(blockposition.getX() + i); ++ int j1 = SectionPos.blockToSectionCoord(blockposition.getY() + i); ++ int k1 = SectionPos.blockToSectionCoord(blockposition.getZ() + i); + List list = new ArrayList(); + GameEventListenerRegistry.ListenerVisitor gameeventlistenerregistry_listenervisitor = (gameeventlistener, vec31) -> { + if (gameeventlistener.getDeliveryMode() == GameEventListener.DeliveryMode.BY_DISTANCE) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java.patch new file mode 100644 index 0000000000..a5aa9c1f84 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java ++++ b/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java +@@ -27,6 +27,11 @@ + import net.minecraft.world.level.gameevent.PositionSource; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.CraftGameEvent; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockReceiveGameEvent; ++// CraftBukkit end + + public interface VibrationSystem { + +@@ -284,9 +287,15 @@ + if (optional.isEmpty()) { + return false; + } else { +- Vec3 vec31 = (Vec3) optional.get(); +- +- if (!vibrationsystem_user.canReceiveVibration(serverlevel, BlockPos.containing(vec3), gameevent, gameevent_context)) { ++ Vec3 vec3d1 = (Vec3) optional.get(); ++ // CraftBukkit start ++ boolean defaultCancel = !vibrationsystem_d.canReceiveVibration(level, BlockPos.containing(pos), gameEvent, context); ++ Entity entity = context.sourceEntity(); ++ BlockReceiveGameEvent event = new BlockReceiveGameEvent(CraftGameEvent.minecraftToBukkit(gameEvent), CraftBlock.at(level, BlockPos.containing(vec3d1)), (entity == null) ? null : entity.getBukkitEntity()); ++ event.setCancelled(defaultCancel); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ // CraftBukkit end + return false; + } else if (isOccluded(serverlevel, vec3, vec31)) { + return false; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/FlatLevelSource.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/FlatLevelSource.java.patch new file mode 100644 index 0000000000..966130e6fd --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/FlatLevelSource.java.patch @@ -0,0 +1,26 @@ +--- a/net/minecraft/world/level/levelgen/FlatLevelSource.java ++++ b/net/minecraft/world/level/levelgen/FlatLevelSource.java +@@ -34,14 +34,21 @@ + }); + private final FlatLevelGeneratorSettings settings; + +- public FlatLevelSource(FlatLevelGeneratorSettings flatlevelgeneratorsettings) { +- FixedBiomeSource fixedbiomesource = new FixedBiomeSource(flatlevelgeneratorsettings.getBiome()); ++ public FlatLevelSource(FlatLevelGeneratorSettings settings) { ++ // CraftBukkit start ++ // WorldChunkManagerHell worldchunkmanagerhell = new WorldChunkManagerHell(generatorsettingsflat.getBiome()); + + Objects.requireNonNull(flatlevelgeneratorsettings); + super(fixedbiomesource, Util.memoize(flatlevelgeneratorsettings::adjustGenerationSettings)); + this.settings = flatlevelgeneratorsettings; + } + ++ public FlatLevelSource(FlatLevelGeneratorSettings generatorsettingsflat, net.minecraft.world.level.biome.BiomeSource worldchunkmanager) { ++ super(worldchunkmanager, Util.memoize(generatorsettingsflat::adjustGenerationSettings)); ++ // CraftBukkit end ++ this.settings = generatorsettingsflat; ++ } ++ + @Override + @Override + public ChunkGeneratorStructureState createState(HolderLookup holderlookup, RandomState randomstate, long i) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/PatrolSpawner.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/PatrolSpawner.java.patch new file mode 100644 index 0000000000..a83bcc06ec --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/PatrolSpawner.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/level/levelgen/PatrolSpawner.java ++++ b/net/minecraft/world/level/levelgen/PatrolSpawner.java +@@ -116,9 +115,9 @@ + patrollingmonster.findPatrolTarget(); + } + +- patrollingmonster.setPos((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ()); +- patrollingmonster.finalizeSpawn(serverlevel, serverlevel.getCurrentDifficultyAt(blockpos), MobSpawnType.PATROL, (SpawnGroupData) null, (CompoundTag) null); +- serverlevel.addFreshEntityWithPassengers(patrollingmonster); ++ entitymonsterpatrolling.setPos((double) pos.getX(), (double) pos.getY(), (double) pos.getZ()); ++ entitymonsterpatrolling.finalizeSpawn(level, level.getCurrentDifficultyAt(pos), EnumMobSpawn.PATROL, (GroupDataEntity) null, (CompoundTag) null); ++ level.addFreshEntityWithPassengers(entitymonsterpatrolling, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.PATROL); // CraftBukkit + return true; + } else { + return false; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java.patch new file mode 100644 index 0000000000..ea4c28cdd1 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java ++++ b/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java +@@ -236,16 +236,16 @@ + } + } + +- public static LegacyStructureDataHandler getLegacyStructureHandler(ResourceKey resourcekey, @Nullable DimensionDataStorage dimensiondatastorage) { +- if (resourcekey == Level.OVERWORLD) { +- return new LegacyStructureDataHandler(dimensiondatastorage, ImmutableList.of("Monument", "Stronghold", "Village", "Mineshaft", "Temple", "Mansion"), ImmutableList.of("Village", "Mineshaft", "Mansion", "Igloo", "Desert_Pyramid", "Jungle_Pyramid", "Swamp_Hut", "Stronghold", "Monument")); ++ public static LegacyStructureDataHandler getLegacyStructureHandler(ResourceKey level, @Nullable DimensionDataStorage storage) { // CraftBukkit ++ if (level == LevelStem.OVERWORLD) { // CraftBukkit ++ return new LegacyStructureDataHandler(storage, ImmutableList.of("Monument", "Stronghold", "Village", "Mineshaft", "Temple", "Mansion"), ImmutableList.of("Village", "Mineshaft", "Mansion", "Igloo", "Desert_Pyramid", "Jungle_Pyramid", "Swamp_Hut", "Stronghold", "Monument")); + } else { + ImmutableList immutablelist; + +- if (resourcekey == Level.NETHER) { ++ if (level == LevelStem.NETHER) { // CraftBukkit + immutablelist = ImmutableList.of("Fortress"); +- return new LegacyStructureDataHandler(dimensiondatastorage, immutablelist, immutablelist); +- } else if (resourcekey == Level.END) { ++ return new LegacyStructureDataHandler(storage, immutablelist, immutablelist); ++ } else if (level == LevelStem.END) { // CraftBukkit + immutablelist = ImmutableList.of("EndCity"); + return new LegacyStructureDataHandler(dimensiondatastorage, immutablelist, immutablelist); + } else { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/StructurePiece.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/StructurePiece.java.patch new file mode 100644 index 0000000000..f7502c633a --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/StructurePiece.java.patch @@ -0,0 +1,128 @@ +--- a/net/minecraft/world/level/levelgen/structure/StructurePiece.java ++++ b/net/minecraft/world/level/levelgen/structure/StructurePiece.java +@@ -67,7 +61,8 @@ + this(structurepiecetype, i, (BoundingBox) dataresult.resultOrPartial(logger::error).orElseThrow(() -> { + return new IllegalArgumentException("Invalid boundingbox"); + })); +- int j = compoundtag.getInt("O"); ++ // CraftBukkit end ++ int j = tag.getInt("O"); + + this.setOrientation(j == -1 ? null : Direction.from2DDataValue(j)); + } +@@ -91,7 +83,8 @@ + dataresult.resultOrPartial(logger::error).ifPresent((tag) -> { + compoundtag.put("BB", tag); + }); +- Direction direction = this.getOrientation(); ++ // CraftBukkit end ++ Direction enumdirection = this.getOrientation(); + + compoundtag.putInt("O", direction == null ? -1 : direction.get2DDataValue()); + compoundtag.putInt("GD", this.genDepth); +@@ -189,8 +182,13 @@ + blockstate = blockstate.rotate(this.rotation); + } + +- worldgenlevel.setBlock(blockpos_mutableblockpos, blockstate, 2); +- FluidState fluidstate = worldgenlevel.getFluidState(blockpos_mutableblockpos); ++ level.setBlock(blockposition_mutableblockposition, blockstate, 2); ++ // CraftBukkit start - fluid handling is already done if we have a transformer generator access ++ if (level instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess) { ++ return; ++ } ++ // CraftBukkit end ++ FluidState fluid = level.getFluidState(blockposition_mutableblockposition); + + if (!fluidstate.isEmpty()) { + worldgenlevel.scheduleTick(blockpos_mutableblockpos, fluidstate.getType(), 0); +@@ -204,7 +202,39 @@ + } + } + +- protected boolean canBeReplaced(LevelReader levelreader, int i, int j, int k, BoundingBox boundingbox) { ++ // CraftBukkit start ++ protected boolean placeCraftBlockEntity(ServerLevelAccessor worldAccess, BlockPos position, org.bukkit.craftbukkit.block.CraftBlockEntityState craftBlockEntityState, int i) { ++ if (worldAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ return transformerAccess.setCraftBlock(position, craftBlockEntityState, i); ++ } ++ boolean result = worldAccess.setBlock(position, craftBlockEntityState.getHandle(), i); ++ BlockEntity tileEntity = worldAccess.getBlockEntity(position); ++ if (tileEntity != null) { ++ tileEntity.load(craftBlockEntityState.getSnapshotNBT()); ++ } ++ return result; ++ } ++ ++ protected void placeCraftSpawner(ServerLevelAccessor worldAccess, BlockPos position, org.bukkit.entity.EntityType entityType, int i) { ++ // This method is used in structures that are generated by code and place spawners as they set the entity after the block was placed making it impossible for plugins to access that information ++ org.bukkit.craftbukkit.block.CraftCreatureSpawner spawner = (org.bukkit.craftbukkit.block.CraftCreatureSpawner) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(position, Blocks.SPAWNER.defaultBlockState(), null); ++ spawner.setSpawnedType(entityType); ++ placeCraftBlockEntity(worldAccess, position, spawner, i); ++ } ++ ++ protected void setCraftLootTable(ServerLevelAccessor worldAccess, BlockPos position, RandomSource randomSource, net.minecraft.resources.ResourceLocation loottableKey) { ++ // This method is used in structures that use data markers to a loot table to loot containers as otherwise plugins won't have access to that information. ++ net.minecraft.world.level.block.entity.BlockEntity tileEntity = worldAccess.getBlockEntity(position); ++ if (tileEntity instanceof net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity tileEntityLootable) { ++ tileEntityLootable.setLootTable(loottableKey, randomSource.nextLong()); ++ if (worldAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ transformerAccess.setCraftBlock(position, (org.bukkit.craftbukkit.block.CraftBlockState) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(position, tileEntity.getBlockState(), tileEntityLootable.saveWithFullMetadata()), 3); ++ } ++ } ++ } ++ // CraftBukkit end ++ ++ protected boolean canBeReplaced(LevelReader level, int x, int y, int z, BoundingBox box) { + return true; + } + +@@ -397,12 +427,20 @@ + blockstate = reorient(serverlevelaccessor, blockpos, Blocks.CHEST.defaultBlockState()); + } + +- serverlevelaccessor.setBlock(blockpos, blockstate, 2); +- BlockEntity blockentity = serverlevelaccessor.getBlockEntity(blockpos); ++ // CraftBukkit start ++ /* ++ worldaccess.setBlock(blockposition, iblockdata, 2); ++ TileEntity tileentity = worldaccess.getBlockEntity(blockposition); + + if (blockentity instanceof ChestBlockEntity) { + ((ChestBlockEntity) blockentity).setLootTable(resourcelocation, randomsource.nextLong()); + } ++ */ ++ org.bukkit.craftbukkit.block.CraftChest chestState = (org.bukkit.craftbukkit.block.CraftChest) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(pos, state, null); ++ chestState.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(lootTable))); ++ chestState.setSeed(random.nextLong()); ++ placeCraftBlockEntity(level, pos, chestState, 2); ++ // CraftBukkit end + + return true; + } else { +@@ -413,14 +451,22 @@ + protected boolean createDispenser(WorldGenLevel worldgenlevel, BoundingBox boundingbox, RandomSource randomsource, int i, int j, int k, Direction direction, ResourceLocation resourcelocation) { + BlockPos.MutableBlockPos blockpos_mutableblockpos = this.getWorldPos(i, j, k); + +- if (boundingbox.isInside(blockpos_mutableblockpos) && !worldgenlevel.getBlockState(blockpos_mutableblockpos).is(Blocks.DISPENSER)) { +- this.placeBlock(worldgenlevel, (BlockState) Blocks.DISPENSER.defaultBlockState().setValue(DispenserBlock.FACING, direction), i, j, k, boundingbox); +- BlockEntity blockentity = worldgenlevel.getBlockEntity(blockpos_mutableblockpos); ++ if (box.isInside(blockposition_mutableblockposition) && !level.getBlockState(blockposition_mutableblockposition).is(Blocks.DISPENSER)) { ++ // CraftBukkit start ++ /* ++ this.placeBlock(generatoraccessseed, (IBlockData) Blocks.DISPENSER.defaultBlockState().setValue(BlockDispenser.FACING, enumdirection), i, j, k, structureboundingbox); ++ TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); + + if (blockentity instanceof DispenserBlockEntity) { + ((DispenserBlockEntity) blockentity).setLootTable(resourcelocation, randomsource.nextLong()); + } + ++ org.bukkit.craftbukkit.block.CraftDispenser dispenserState = (org.bukkit.craftbukkit.block.CraftDispenser) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockposition_mutableblockposition, iblockdata, null); ++ dispenserState.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(lootTable))); ++ dispenserState.setSeed(random.nextLong()); ++ placeCraftBlockEntity(level, blockposition_mutableblockposition, dispenserState, 2); ++ // CraftBukkit end ++ + return true; + } else { + return false; diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/StructureStart.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/StructureStart.java.patch new file mode 100644 index 0000000000..4b625628e7 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/StructureStart.java.patch @@ -0,0 +1,44 @@ +--- a/net/minecraft/world/level/levelgen/structure/StructureStart.java ++++ b/net/minecraft/world/level/levelgen/structure/StructureStart.java +@@ -31,6 +31,7 @@ + private int references; + @Nullable + private volatile BoundingBox cachedBoundingBox; ++ public org.bukkit.event.world.AsyncStructureGenerateEvent.Cause generationEventCause = org.bukkit.event.world.AsyncStructureGenerateEvent.Cause.WORLD_GENERATION; // CraftBukkit + + public StructureStart(Structure structure, ChunkPos chunkpos, int i, PiecesContainer piecescontainer) { + this.structure = structure; +@@ -88,9 +89,11 @@ + List list = this.pieceContainer.pieces(); + + if (!list.isEmpty()) { +- BoundingBox boundingbox1 = ((StructurePiece) list.get(0)).boundingBox; +- BlockPos blockpos = boundingbox1.getCenter(); +- BlockPos blockpos1 = new BlockPos(blockpos.getX(), boundingbox1.minY(), blockpos.getZ()); ++ BoundingBox structureboundingbox1 = ((StructurePiece) list.get(0)).boundingBox; ++ BlockPos blockposition = structureboundingbox1.getCenter(); ++ BlockPos blockposition1 = new BlockPos(blockposition.getX(), structureboundingbox1.minY(), blockposition.getZ()); ++ // CraftBukkit start ++ /* + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +@@ -100,6 +103,18 @@ + structurepiece.postProcess(worldgenlevel, structuremanager, chunkgenerator, randomsource, boundingbox, chunkpos, blockpos1); + } + } ++ */ ++ List pieces = list.stream().filter(piece -> piece.getBoundingBox().intersects(box)).toList(); ++ if (!pieces.isEmpty()) { ++ org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess = new org.bukkit.craftbukkit.util.TransformerGeneratorAccess(); ++ transformerAccess.setHandle(level); ++ transformerAccess.setStructureTransformer(new org.bukkit.craftbukkit.util.CraftStructureTransformer(generationEventCause, level, structureManager, structure, box, chunkPos)); ++ for (StructurePiece piece : pieces) { ++ piece.postProcess(transformerAccess, structureManager, generator, random, box, chunkPos, blockposition1); ++ } ++ transformerAccess.getStructureTransformer().discard(); ++ } ++ // CraftBukkit end + + this.structure.afterPlace(worldgenlevel, structuremanager, chunkgenerator, randomsource, boundingbox, chunkpos, this.pieceContainer); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java.patch new file mode 100644 index 0000000000..c20ca612c5 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java.patch @@ -0,0 +1,28 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java +@@ -69,11 +68,20 @@ + + } + +- private static void placeSuspiciousSand(BoundingBox boundingbox, WorldGenLevel worldgenlevel, BlockPos blockpos) { +- if (boundingbox.isInside(blockpos)) { +- worldgenlevel.setBlock(blockpos, Blocks.SUSPICIOUS_SAND.defaultBlockState(), 2); +- worldgenlevel.getBlockEntity(blockpos, BlockEntityType.BRUSHABLE_BLOCK).ifPresent((brushableblockentity) -> { +- brushableblockentity.setLootTable(BuiltInLootTables.DESERT_PYRAMID_ARCHAEOLOGY, blockpos.asLong()); ++ private static void placeSuspiciousSand(BoundingBox boundingBox, WorldGenLevel worldGenLevel, BlockPos pos) { ++ if (boundingBox.isInside(pos)) { ++ // CraftBukkit start ++ if (worldGenLevel instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ org.bukkit.craftbukkit.block.CraftBrushableBlock brushableState = (org.bukkit.craftbukkit.block.CraftBrushableBlock) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(pos, Blocks.SUSPICIOUS_SAND.defaultBlockState(), null); ++ brushableState.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(BuiltInLootTables.DESERT_PYRAMID_ARCHAEOLOGY))); ++ brushableState.setSeed(pos.asLong()); ++ transformerAccess.setCraftBlock(pos, brushableState, 2); ++ return; ++ } ++ // CraftBukkit end ++ worldGenLevel.setBlock(pos, Blocks.SUSPICIOUS_SAND.defaultBlockState(), 2); ++ worldGenLevel.getBlockEntity(pos, BlockEntityType.BRUSHABLE_BLOCK).ifPresent((brushableblockentity) -> { ++ brushableblockentity.setLootTable(BuiltInLootTables.DESERT_PYRAMID_ARCHAEOLOGY, pos.asLong()); + }); + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java.patch new file mode 100644 index 0000000000..ebf61ce987 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java +@@ -294,8 +283,13 @@ + if (s.startsWith("Chest")) { + BlockPos blockpos1 = blockpos.below(); + +- if (boundingbox.isInside(blockpos1)) { +- RandomizableContainer.setBlockEntityLootTable(serverlevelaccessor, randomsource, blockpos1, BuiltInLootTables.END_CITY_TREASURE); ++ if (box.isInside(blockposition1)) { ++ // CraftBukkit start - ensure block transformation ++ /* ++ RandomizableContainer.setBlockEntityLootTable(worldaccess, randomsource, blockposition1, LootTables.END_CITY_TREASURE); ++ */ ++ setCraftLootTable(level, blockposition1, random, BuiltInLootTables.END_CITY_TREASURE); ++ // CraftBukkit end + } + } else if (boundingbox.isInside(blockpos) && Level.isInSpawnableBounds(blockpos)) { + if (s.startsWith("Sentry")) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java.patch new file mode 100644 index 0000000000..5eed6bf146 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java +@@ -83,15 +80,19 @@ + } + + @Override +- @Override +- protected void handleDataMarker(String s, BlockPos blockpos, ServerLevelAccessor serverlevelaccessor, RandomSource randomsource, BoundingBox boundingbox) { +- if ("chest".equals(s)) { +- serverlevelaccessor.setBlock(blockpos, Blocks.AIR.defaultBlockState(), 3); +- BlockEntity blockentity = serverlevelaccessor.getBlockEntity(blockpos.below()); ++ protected void handleDataMarker(String name, BlockPos pos, ServerLevelAccessor level, RandomSource random, BoundingBox box) { ++ if ("chest".equals(name)) { ++ level.setBlock(pos, Blocks.AIR.defaultBlockState(), 3); ++ // CraftBukkit start - ensure block transformation ++ /* ++ TileEntity tileentity = worldaccess.getBlockEntity(blockposition.below()); + + if (blockentity instanceof ChestBlockEntity) { + ((ChestBlockEntity) blockentity).setLootTable(BuiltInLootTables.IGLOO_CHEST, randomsource.nextLong()); + } ++ */ ++ setCraftLootTable(level, pos.below(), random, BuiltInLootTables.IGLOO_CHEST); ++ // CraftBukkit end + + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java.patch new file mode 100644 index 0000000000..01a9c37ee1 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java +@@ -523,14 +512,19 @@ + + if (boundingbox.isInside(blockpos_mutableblockpos) && this.isInterior(worldgenlevel, 1, 0, l, boundingbox)) { + this.hasPlacedSpider = true; +- worldgenlevel.setBlock(blockpos_mutableblockpos, Blocks.SPAWNER.defaultBlockState(), 2); +- BlockEntity blockentity = worldgenlevel.getBlockEntity(blockpos_mutableblockpos); ++ // CraftBukkit start ++ /* ++ generatoraccessseed.setBlock(blockposition_mutableblockposition, Blocks.SPAWNER.defaultBlockState(), 2); ++ TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); + + if (blockentity instanceof SpawnerBlockEntity) { + SpawnerBlockEntity spawnerblockentity = (SpawnerBlockEntity) blockentity; + + spawnerblockentity.setEntityId(EntityType.CAVE_SPIDER, randomsource); + } ++ */ ++ placeCraftSpawner(level, blockposition_mutableblockposition, org.bukkit.entity.EntityType.CAVE_SPIDER, 2); ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java.patch new file mode 100644 index 0000000000..6fdb04621d --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java +@@ -438,14 +425,19 @@ + + if (boundingbox.isInside(blockpos_mutableblockpos)) { + this.hasPlacedSpawner = true; +- worldgenlevel.setBlock(blockpos_mutableblockpos, Blocks.SPAWNER.defaultBlockState(), 2); +- BlockEntity blockentity = worldgenlevel.getBlockEntity(blockpos_mutableblockpos); ++ // CraftBukkit start ++ /* ++ generatoraccessseed.setBlock(blockposition_mutableblockposition, Blocks.SPAWNER.defaultBlockState(), 2); ++ TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); + + if (blockentity instanceof SpawnerBlockEntity) { + SpawnerBlockEntity spawnerblockentity = (SpawnerBlockEntity) blockentity; + + spawnerblockentity.setEntityId(EntityType.BLAZE, randomsource); + } ++ */ ++ placeCraftSpawner(level, blockposition_mutableblockposition, org.bukkit.entity.EntityType.BLAZE, 2); ++ // CraftBukkit end + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java.patch new file mode 100644 index 0000000000..26ca09acac --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java +@@ -197,17 +194,24 @@ + } + + @Override +- @Override +- protected void handleDataMarker(String s, BlockPos blockpos, ServerLevelAccessor serverlevelaccessor, RandomSource randomsource, BoundingBox boundingbox) { +- if ("chest".equals(s)) { +- serverlevelaccessor.setBlock(blockpos, (BlockState) Blocks.CHEST.defaultBlockState().setValue(ChestBlock.WATERLOGGED, serverlevelaccessor.getFluidState(blockpos).is(FluidTags.WATER)), 2); +- BlockEntity blockentity = serverlevelaccessor.getBlockEntity(blockpos); ++ protected void handleDataMarker(String name, BlockPos pos, ServerLevelAccessor level, RandomSource random, BoundingBox box) { ++ if ("chest".equals(name)) { ++ // CraftBukkit start - transform block to ensure loot table is accessible ++ /* ++ worldaccess.setBlock(blockposition, (IBlockData) Blocks.CHEST.defaultBlockState().setValue(BlockChest.WATERLOGGED, worldaccess.getFluidState(blockposition).is(TagsFluid.WATER)), 2); ++ TileEntity tileentity = worldaccess.getBlockEntity(blockposition); + + if (blockentity instanceof ChestBlockEntity) { + ((ChestBlockEntity) blockentity).setLootTable(this.isLarge ? BuiltInLootTables.UNDERWATER_RUIN_BIG : BuiltInLootTables.UNDERWATER_RUIN_SMALL, randomsource.nextLong()); + } +- } else if ("drowned".equals(s)) { +- Drowned drowned = (Drowned) EntityType.DROWNED.create(serverlevelaccessor.getLevel()); ++ */ ++ org.bukkit.craftbukkit.block.CraftChest craftChest = (org.bukkit.craftbukkit.block.CraftChest) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(pos, Blocks.CHEST.defaultBlockState().setValue(ChestBlock.WATERLOGGED, level.getFluidState(pos).is(FluidTags.WATER)), null); ++ craftChest.setSeed(random.nextLong()); ++ craftChest.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.isLarge ? BuiltInLootTables.UNDERWATER_RUIN_BIG : BuiltInLootTables.UNDERWATER_RUIN_SMALL))); ++ placeCraftBlockEntity(level, pos, craftChest, 2); ++ // CraftBukkit end ++ } else if ("drowned".equals(name)) { ++ Drowned entitydrowned = (Drowned) EntityType.DROWNED.create(level.getLevel()); + + if (drowned != null) { + drowned.setPersistenceRequired(); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java.patch new file mode 100644 index 0000000000..118134ef2a --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java +@@ -55,7 +50,7 @@ + public boolean doPlace(int i) { + return super.doPlace(i) && i > 5; + } +- }}; ++ } }; // CraftBukkit - fix decompile styling + private static List currentPieces; + static Class imposedPiece; + private static int totalWeight; +@@ -1166,14 +1133,19 @@ + + if (boundingbox.isInside(blockpos_mutableblockpos)) { + this.hasPlacedSpawner = true; +- worldgenlevel.setBlock(blockpos_mutableblockpos, Blocks.SPAWNER.defaultBlockState(), 2); +- BlockEntity blockentity = worldgenlevel.getBlockEntity(blockpos_mutableblockpos); ++ // CraftBukkit start ++ /* ++ generatoraccessseed.setBlock(blockposition_mutableblockposition, Blocks.SPAWNER.defaultBlockState(), 2); ++ TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); + + if (blockentity instanceof SpawnerBlockEntity) { + SpawnerBlockEntity spawnerblockentity = (SpawnerBlockEntity) blockentity; + + spawnerblockentity.setEntityId(EntityType.SILVERFISH, randomsource); + } ++ */ ++ placeCraftSpawner(level, blockposition_mutableblockposition, org.bukkit.entity.EntityType.SILVERFISH, 2); ++ // CraftBukkit end + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java.patch new file mode 100644 index 0000000000..b2b2723fc8 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java +@@ -98,11 +96,11 @@ + this.spawnedWitch = true; + Witch witch = (Witch) EntityType.WITCH.create(worldgenlevel.getLevel()); + +- if (witch != null) { +- witch.setPersistenceRequired(); +- witch.moveTo((double) blockpos_mutableblockpos.getX() + 0.5D, (double) blockpos_mutableblockpos.getY(), (double) blockpos_mutableblockpos.getZ() + 0.5D, 0.0F, 0.0F); +- witch.finalizeSpawn(worldgenlevel, worldgenlevel.getCurrentDifficultyAt(blockpos_mutableblockpos), MobSpawnType.STRUCTURE, (SpawnGroupData) null, (CompoundTag) null); +- worldgenlevel.addFreshEntityWithPassengers(witch); ++ if (entitywitch != null) { ++ entitywitch.setPersistenceRequired(); ++ entitywitch.moveTo((double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + 0.5D, 0.0F, 0.0F); ++ entitywitch.finalizeSpawn(level, level.getCurrentDifficultyAt(blockposition_mutableblockposition), EnumMobSpawn.STRUCTURE, (GroupDataEntity) null, (CompoundTag) null); ++ level.addFreshEntityWithPassengers(entitywitch, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN); // CraftBukkit - add SpawnReason + } + } + } +@@ -119,11 +117,11 @@ + this.spawnedCat = true; + Cat cat = (Cat) EntityType.CAT.create(serverlevelaccessor.getLevel()); + +- if (cat != null) { +- cat.setPersistenceRequired(); +- cat.moveTo((double) blockpos_mutableblockpos.getX() + 0.5D, (double) blockpos_mutableblockpos.getY(), (double) blockpos_mutableblockpos.getZ() + 0.5D, 0.0F, 0.0F); +- cat.finalizeSpawn(serverlevelaccessor, serverlevelaccessor.getCurrentDifficultyAt(blockpos_mutableblockpos), MobSpawnType.STRUCTURE, (SpawnGroupData) null, (CompoundTag) null); +- serverlevelaccessor.addFreshEntityWithPassengers(cat); ++ if (entitycat != null) { ++ entitycat.setPersistenceRequired(); ++ entitycat.moveTo((double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + 0.5D, 0.0F, 0.0F); ++ entitycat.finalizeSpawn(level, level.getCurrentDifficultyAt(blockposition_mutableblockposition), EnumMobSpawn.STRUCTURE, (GroupDataEntity) null, (CompoundTag) null); ++ level.addFreshEntityWithPassengers(entitycat, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN); // CraftBukkit - add SpawnReason + } + } + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings.java.patch new file mode 100644 index 0000000000..33369a7692 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings.java.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings.java ++++ b/net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings.java +@@ -22,7 +22,7 @@ + private boolean keepLiquids; + @Nullable + private RandomSource random; +- private int palette; ++ public int palette = -1; // CraftBukkit - Set initial value so we know if the palette has been set forcefully + private final List processors; + private boolean knownShape; + private boolean finalizeEntities; +@@ -149,6 +149,13 @@ + + if (i == 0) { + throw new IllegalStateException("No palettes"); ++ // CraftBukkit start ++ } else if (this.palette > 0) { ++ if (this.palette >= i) { ++ throw new IllegalArgumentException("Palette index out of bounds. Got " + this.palette + " where there are only " + i + " palettes available."); ++ } ++ return palettes.get(this.palette); ++ // CraftBukkit end + } else { + return (StructureTemplate.Palette) list.get(this.getRandom(blockpos).nextInt(i)); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java.patch new file mode 100644 index 0000000000..9d43b91b36 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java.patch @@ -0,0 +1,157 @@ +--- a/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java ++++ b/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java +@@ -51,6 +52,9 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.BitSetDiscreteVoxelShape; + import net.minecraft.world.phys.shapes.DiscreteVoxelShape; ++import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer; ++import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry; ++// CraftBukkit end + + public class StructureTemplate { + +@@ -70,6 +74,11 @@ + private Vec3i size; + private String author; + ++ // CraftBukkit start - data containers ++ private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); ++ public CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); ++ // CraftBukkit end ++ + public StructureTemplate() { + this.size = Vec3i.ZERO; + this.author = "?"; +@@ -229,7 +238,20 @@ + if (this.palettes.isEmpty()) { + return false; + } else { +- List list = structureplacesettings.getRandomPalette(this.palettes, blockpos).blocks(); ++ // CraftBukkit start ++ // We only want the TransformerGeneratorAccess at certain locations because in here are many "block update" calls that shouldn't be transformed ++ ServerLevelAccessor wrappedAccess = serverLevel; ++ org.bukkit.craftbukkit.util.CraftStructureTransformer structureTransformer = null; ++ if (wrappedAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ serverLevel = transformerAccess.getHandle(); ++ structureTransformer = transformerAccess.getStructureTransformer(); ++ // The structureTransformer is not needed if we can not transform blocks therefore we can save a little bit of performance doing this ++ if (structureTransformer != null && !structureTransformer.canTransformBlocks()) { ++ structureTransformer = null; ++ } ++ } ++ // CraftBukkit end ++ List list = settings.getRandomPalette(this.palettes, offset).blocks(); + + if ((!list.isEmpty() || !structureplacesettings.isIgnoreEntities() && !this.entityInfoList.isEmpty()) && this.size.getX() >= 1 && this.size.getY() >= 1 && this.size.getZ() >= 1) { + BoundingBox boundingbox = structureplacesettings.getBoundingBox(); +@@ -260,20 +282,34 @@ + Clearable.tryClear(blockentity); + serverlevelaccessor.setBlock(blockpos2, Blocks.BARRIER.defaultBlockState(), 20); + } ++ // CraftBukkit start ++ if (structureTransformer != null) { ++ org.bukkit.craftbukkit.block.CraftBlockState craftBlockState = (org.bukkit.craftbukkit.block.CraftBlockState) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockposition2, iblockdata, null); ++ if (definedstructure_blockinfo.nbt != null && craftBlockState instanceof org.bukkit.craftbukkit.block.CraftBlockEntityState entityState) { ++ entityState.loadData(definedstructure_blockinfo.nbt); ++ if (craftBlockState instanceof org.bukkit.craftbukkit.block.CraftLootable craftLootable) { ++ craftLootable.setSeed(random.nextLong()); ++ } ++ } ++ craftBlockState = structureTransformer.transformCraftState(craftBlockState); ++ iblockdata = craftBlockState.getHandle(); ++ definedstructure_blockinfo = new StructureTemplate.StructureBlockInfo(blockposition2, iblockdata, (craftBlockState instanceof org.bukkit.craftbukkit.block.CraftBlockEntityState craftBlockEntityState ? craftBlockEntityState.getSnapshotNBT() : null)); ++ } ++ // CraftBukkit end + +- if (serverlevelaccessor.setBlock(blockpos2, blockstate, i)) { +- j = Math.min(j, blockpos2.getX()); +- k = Math.min(k, blockpos2.getY()); +- l = Math.min(l, blockpos2.getZ()); +- i1 = Math.max(i1, blockpos2.getX()); +- j1 = Math.max(j1, blockpos2.getY()); +- k1 = Math.max(k1, blockpos2.getZ()); +- list3.add(Pair.of(blockpos2, structuretemplate_structureblockinfo.nbt)); +- if (structuretemplate_structureblockinfo.nbt != null) { +- blockentity = serverlevelaccessor.getBlockEntity(blockpos2); +- if (blockentity != null) { +- if (blockentity instanceof RandomizableContainer) { +- structuretemplate_structureblockinfo.nbt.putLong("LootTableSeed", randomsource.nextLong()); ++ if (serverLevel.setBlock(blockposition2, iblockdata, flags)) { ++ j = Math.min(j, blockposition2.getX()); ++ k = Math.min(k, blockposition2.getY()); ++ l = Math.min(l, blockposition2.getZ()); ++ i1 = Math.max(i1, blockposition2.getX()); ++ j1 = Math.max(j1, blockposition2.getY()); ++ k1 = Math.max(k1, blockposition2.getZ()); ++ list3.add(Pair.of(blockposition2, definedstructure_blockinfo.nbt)); ++ if (definedstructure_blockinfo.nbt != null) { ++ tileentity = serverLevel.getBlockEntity(blockposition2); ++ if (tileentity != null) { ++ if (structureTransformer == null && tileentity instanceof RandomizableContainer) { // CraftBukkit - only process if don't have a transformer access (Was already set above) - SPIGOT-7520: Use structureTransformer as check, so that it is the same as above ++ definedstructure_blockinfo.nbt.putLong("LootTableSeed", random.nextLong()); + } + + blockentity.load(structuretemplate_structureblockinfo.nbt); +@@ -376,8 +412,8 @@ + } + } + +- if (!structureplacesettings.isIgnoreEntities()) { +- this.placeEntities(serverlevelaccessor, blockpos, structureplacesettings.getMirror(), structureplacesettings.getRotation(), structureplacesettings.getRotationPivot(), boundingbox, structureplacesettings.shouldFinalizeEntities()); ++ if (!settings.isIgnoreEntities()) { ++ this.placeEntities(wrappedAccess, offset, settings.getMirror(), settings.getRotation(), settings.getRotationPivot(), structureboundingbox, settings.shouldFinalizeEntities()); // CraftBukkit + } + + return true; +@@ -471,12 +507,14 @@ + + } + +- private static Optional createEntityIgnoreException(ServerLevelAccessor serverlevelaccessor, CompoundTag compoundtag) { +- try { +- return EntityType.create(compoundtag, serverlevelaccessor.getLevel()); +- } catch (Exception exception) { +- return Optional.empty(); +- } ++ private static Optional createEntityIgnoreException(ServerLevelAccessor level, CompoundTag tag) { ++ // CraftBukkit start ++ // try { ++ return EntityType.create(tag, level.getLevel()); ++ // } catch (Exception exception) { ++ // return Optional.empty(); ++ // } ++ // CraftBukkit end + } + + public Vec3i getSize(Rotation rotation) { +@@ -688,9 +726,14 @@ + } + } + +- compoundtag.put("entities", listtag3); +- compoundtag.put("size", this.newIntegerList(this.size.getX(), this.size.getY(), this.size.getZ())); +- return NbtUtils.addCurrentDataVersion(compoundtag); ++ tag.put("entities", nbttaglist3); ++ tag.put("size", this.newIntegerList(this.size.getX(), this.size.getY(), this.size.getZ())); ++ // CraftBukkit start - PDC ++ if (!this.persistentDataContainer.isEmpty()) { ++ tag.put("BukkitValues", this.persistentDataContainer.toTagCompound()); ++ } ++ // CraftBukkit end ++ return NbtUtils.addCurrentDataVersion(tag); + } + + public void load(HolderGetter holdergetter, CompoundTag compoundtag) { +@@ -729,6 +772,12 @@ + } + } + ++ // CraftBukkit start - PDC ++ Tag base = tag.get("BukkitValues"); ++ if (base instanceof CompoundTag) { ++ this.persistentDataContainer.putAll((CompoundTag) base); ++ } ++ // CraftBukkit end + } + + private void loadPalette(HolderGetter holdergetter, ListTag listtag, ListTag listtag1) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/material/FlowingFluid.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/material/FlowingFluid.java.patch new file mode 100644 index 0000000000..2ad5f6d0ef --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/material/FlowingFluid.java.patch @@ -0,0 +1,104 @@ +--- a/net/minecraft/world/level/material/FlowingFluid.java ++++ b/net/minecraft/world/level/material/FlowingFluid.java +@@ -31,6 +31,14 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.block.BlockFace; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.block.BlockFromToEvent; ++import org.bukkit.event.block.FluidLevelChangeEvent; ++// CraftBukkit end + + public abstract class FlowingFluid extends Fluid { + +@@ -134,13 +139,22 @@ + BlockState blockstate1 = level.getBlockState(blockpos1); + FluidState fluidstate1 = this.getNewLiquid(level, blockpos1, blockstate1); + +- if (this.canSpreadTo(level, blockpos, blockstate, Direction.DOWN, blockpos1, blockstate1, level.getFluidState(blockpos1), fluidstate1.getType())) { +- this.spreadTo(level, blockpos1, blockstate1, Direction.DOWN, fluidstate1); +- if (this.sourceNeighborCount(level, blockpos) >= 3) { +- this.spreadToSides(level, blockpos, fluidstate, blockstate); ++ if (this.canSpreadTo(level, pos, iblockdata, Direction.DOWN, blockposition1, iblockdata1, level.getFluidState(blockposition1), fluid1.getType())) { ++ // CraftBukkit start ++ org.bukkit.block.Block source = CraftBlock.at(level, pos); ++ BlockFromToEvent event = new BlockFromToEvent(source, BlockFace.DOWN); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; + } +- } else if (fluidstate.isSource() || !this.isWaterHole(level, fluidstate1.getType(), blockpos, blockstate, blockpos1, blockstate1)) { +- this.spreadToSides(level, blockpos, fluidstate, blockstate); ++ // CraftBukkit end ++ this.spreadTo(level, blockposition1, iblockdata1, Direction.DOWN, fluid1); ++ if (this.sourceNeighborCount(level, pos) >= 3) { ++ this.spreadToSides(level, pos, state, iblockdata); ++ } ++ } else if (state.isSource() || !this.isWaterHole(level, fluid1.getType(), pos, iblockdata, blockposition1, iblockdata1)) { ++ this.spreadToSides(level, pos, state, iblockdata); + } + + } +@@ -164,8 +178,17 @@ + BlockPos blockpos1 = blockpos.relative(direction); + BlockState blockstate1 = level.getBlockState(blockpos1); + +- if (this.canSpreadTo(level, blockpos, blockstate, direction, blockpos1, blockstate1, level.getFluidState(blockpos1), fluidstate1.getType())) { +- this.spreadTo(level, blockpos1, blockstate1, direction, fluidstate1); ++ if (this.canSpreadTo(level, pos, blockState, enumdirection, blockposition1, iblockdata1, level.getFluidState(blockposition1), fluid1.getType())) { ++ // CraftBukkit start ++ org.bukkit.block.Block source = CraftBlock.at(level, pos); ++ BlockFromToEvent event = new BlockFromToEvent(source, org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(enumdirection)); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end ++ this.spreadTo(level, blockposition1, iblockdata1, enumdirection, fluid1); + } + } + +@@ -440,16 +462,27 @@ + FluidState fluidstate1 = this.getNewLiquid(level, blockpos, level.getBlockState(blockpos)); + int i = this.getSpreadDelay(level, blockpos, fluidstate, fluidstate1); + +- if (fluidstate1.isEmpty()) { +- fluidstate = fluidstate1; +- level.setBlock(blockpos, Blocks.AIR.defaultBlockState(), 3); +- } else if (!fluidstate1.equals(fluidstate)) { +- fluidstate = fluidstate1; +- BlockState blockstate = fluidstate1.createLegacyBlock(); +- +- level.setBlock(blockpos, blockstate, 2); +- level.scheduleTick(blockpos, fluidstate1.getType(), i); +- level.updateNeighborsAt(blockpos, blockstate.getBlock()); ++ if (fluid1.isEmpty()) { ++ state = fluid1; ++ // CraftBukkit start ++ FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(level, pos, Blocks.AIR.defaultBlockState()); ++ if (event.isCancelled()) { ++ return; ++ } ++ level.setBlock(pos, ((CraftBlockData) event.getNewData()).getState(), 3); ++ // CraftBukkit end ++ } else if (!fluid1.equals(state)) { ++ state = fluid1; ++ IBlockData iblockdata = fluid1.createLegacyBlock(); ++ // CraftBukkit start ++ FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(level, pos, iblockdata); ++ if (event.isCancelled()) { ++ return; ++ } ++ level.setBlock(pos, ((CraftBlockData) event.getNewData()).getState(), 2); ++ // CraftBukkit end ++ level.scheduleTick(pos, fluid1.getType(), i); ++ level.updateNeighborsAt(pos, iblockdata.getBlock()); + } + } + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/material/LavaFluid.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/material/LavaFluid.java.patch new file mode 100644 index 0000000000..236f8f0879 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/material/LavaFluid.java.patch @@ -0,0 +1,58 @@ +--- a/net/minecraft/world/level/material/LavaFluid.java ++++ b/net/minecraft/world/level/material/LavaFluid.java +@@ -87,9 +82,16 @@ + + BlockState blockstate = level.getBlockState(blockpos1); + +- if (blockstate.isAir()) { +- if (this.hasFlammableNeighbours(level, blockpos1)) { +- level.setBlockAndUpdate(blockpos1, BaseFireBlock.getState(level, blockpos1)); ++ if (iblockdata.isAir()) { ++ if (this.hasFlammableNeighbours(level, blockposition1)) { ++ // CraftBukkit start - Prevent lava putting something on fire ++ if (level.getBlockState(blockposition1).getBlock() != Blocks.FIRE) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, blockposition1, pos).isCancelled()) { ++ continue; ++ } ++ } ++ // CraftBukkit end ++ level.setBlockAndUpdate(blockposition1, BaseFireBlock.getState(level, blockposition1)); + return; + } + } else if (blockstate.blocksMotion()) { +@@ -104,8 +106,16 @@ + return; + } + +- if (level.isEmptyBlock(blockpos2.above()) && this.isFlammable(level, blockpos2)) { +- level.setBlockAndUpdate(blockpos2.above(), BaseFireBlock.getState(level, blockpos2)); ++ if (level.isEmptyBlock(blockposition2.above()) && this.isFlammable(level, blockposition2)) { ++ // CraftBukkit start - Prevent lava putting something on fire ++ BlockPos up = blockposition2.above(); ++ if (level.getBlockState(up).getBlock() != Blocks.FIRE) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, up, pos).isCancelled()) { ++ continue; ++ } ++ } ++ // CraftBukkit end ++ level.setBlockAndUpdate(blockposition2.above(), BaseFireBlock.getState(level, blockposition2)); + } + } + } +@@ -209,9 +208,13 @@ + if (direction == Direction.DOWN) { + FluidState fluidstate1 = levelaccessor.getFluidState(blockpos); + +- if (this.is(FluidTags.LAVA) && fluidstate1.is(FluidTags.WATER)) { +- if (blockstate.getBlock() instanceof LiquidBlock) { +- levelaccessor.setBlock(blockpos, Blocks.STONE.defaultBlockState(), 3); ++ if (this.is(FluidTags.LAVA) && fluid1.is(FluidTags.WATER)) { ++ if (blockState.getBlock() instanceof LiquidBlock) { ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level.getMinecraftWorld(), pos, Blocks.STONE.defaultBlockState(), 3)) { ++ return; ++ } ++ // CraftBukkit end + } + + this.fizz(levelaccessor, blockpos); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/portal/PortalForcer.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/portal/PortalForcer.java.patch new file mode 100644 index 0000000000..8ccc7232cb --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/portal/PortalForcer.java.patch @@ -0,0 +1,109 @@ +--- a/net/minecraft/world/level/portal/PortalForcer.java ++++ b/net/minecraft/world/level/portal/PortalForcer.java +@@ -41,12 +41,18 @@ + this.level = serverlevel; + } + +- public Optional findPortalAround(BlockPos blockpos, boolean flag, WorldBorder worldborder) { +- PoiManager poimanager = this.level.getPoiManager(); +- int i = flag ? 16 : 128; ++ public Optional findPortalAround(BlockPos pos, boolean isNether, WorldBorder worldBorder) { ++ // CraftBukkit start ++ return findPortalAround(pos, worldBorder, isNether ? 16 : 128); // Search Radius ++ } + +- poimanager.ensureLoadedAndValid(this.level, blockpos, i); +- Optional optional = poimanager.getInSquare((holder) -> { ++ public Optional findPortalAround(BlockPos blockposition, WorldBorder worldborder, int i) { ++ PoiManager villageplace = this.level.getPoiManager(); ++ // int i = flag ? 16 : 128; ++ // CraftBukkit end ++ ++ villageplace.ensureLoadedAndValid(this.level, blockposition, i); ++ Optional optional = villageplace.getInSquare((holder) -> { + return holder.is(PoiTypes.NETHER_PORTAL); + }, blockpos, i, PoiManager.Occupancy.ANY).filter((poirecord) -> { + return worldborder.isWithinBounds(poirecord.getPos()); +@@ -70,16 +76,22 @@ + }); + } + +- public Optional createPortal(BlockPos blockpos, Direction.Axis direction_axis) { +- Direction direction = Direction.get(Direction.AxisDirection.POSITIVE, direction_axis); ++ public Optional createPortal(BlockPos pos, Direction.Axis axis) { ++ // CraftBukkit start ++ return this.createPortal(pos, axis, null, 16); ++ } ++ ++ public Optional createPortal(BlockPos blockposition, Direction.Axis enumdirection_enumaxis, net.minecraft.world.entity.Entity entity, int createRadius) { ++ // CraftBukkit end ++ Direction enumdirection = Direction.get(Direction.AxisDirection.POSITIVE, enumdirection_enumaxis); + double d0 = -1.0D; + BlockPos blockpos1 = null; + double d1 = -1.0D; + BlockPos blockpos2 = null; + WorldBorder worldborder = this.level.getWorldBorder(); + int i = Math.min(this.level.getMaxBuildHeight(), this.level.getMinBuildHeight() + this.level.getLogicalHeight()) - 1; +- BlockPos.MutableBlockPos blockpos_mutableblockpos = blockpos.mutable(); +- Iterator iterator = BlockPos.spiralAround(blockpos, 16, Direction.EAST, Direction.SOUTH).iterator(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = blockposition.mutable(); ++ Iterator iterator = BlockPos.spiralAround(blockposition, createRadius, Direction.EAST, Direction.SOUTH).iterator(); // CraftBukkit + + int j; + int k; +@@ -134,6 +146,7 @@ + int j1; + int k1; + ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(this.level); // CraftBukkit - Use BlockStateListPopulator + if (d0 == -1.0D) { + j1 = Math.max(this.level.getMinBuildHeight() - -1, 70); + k1 = i - 9; +@@ -153,8 +166,8 @@ + for (l = -1; l < 3; ++l) { + BlockState blockstate = l < 0 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); + +- blockpos_mutableblockpos.setWithOffset(blockpos1, k * direction.getStepX() + l1 * direction1.getStepX(), l, k * direction.getStepZ() + l1 * direction1.getStepZ()); +- this.level.setBlockAndUpdate(blockpos_mutableblockpos, blockstate); ++ blockposition_mutableblockposition.setWithOffset(blockposition1, k * enumdirection.getStepX() + l1 * enumdirection1.getStepX(), l, k * enumdirection.getStepZ() + l1 * enumdirection1.getStepZ()); ++ blockList.setBlock(blockposition_mutableblockposition, iblockdata, 3); // CraftBukkit + } + } + } +@@ -163,8 +176,8 @@ + for (j1 = -1; j1 < 3; ++j1) { + for (k1 = -1; k1 < 4; ++k1) { + if (j1 == -1 || j1 == 2 || k1 == -1 || k1 == 3) { +- blockpos_mutableblockpos.setWithOffset(blockpos1, j1 * direction.getStepX(), k1, j1 * direction.getStepZ()); +- this.level.setBlock(blockpos_mutableblockpos, Blocks.OBSIDIAN.defaultBlockState(), 3); ++ blockposition_mutableblockposition.setWithOffset(blockposition1, j1 * enumdirection.getStepX(), k1, j1 * enumdirection.getStepZ()); ++ blockList.setBlock(blockposition_mutableblockposition, Blocks.OBSIDIAN.defaultBlockState(), 3); // CraftBukkit + } + } + } +@@ -173,12 +186,22 @@ + + for (k1 = 0; k1 < 2; ++k1) { + for (j = 0; j < 3; ++j) { +- blockpos_mutableblockpos.setWithOffset(blockpos1, k1 * direction.getStepX(), j, k1 * direction.getStepZ()); +- this.level.setBlock(blockpos_mutableblockpos, blockstate1, 18); ++ blockposition_mutableblockposition.setWithOffset(blockposition1, k1 * enumdirection.getStepX(), j, k1 * enumdirection.getStepZ()); ++ blockList.setBlock(blockposition_mutableblockposition, iblockdata1, 18); // CraftBukkit + } + } + +- return Optional.of(new BlockUtil.FoundRectangle(blockpos1.immutable(), 2, 3)); ++ // CraftBukkit start ++ org.bukkit.World bworld = this.level.getWorld(); ++ org.bukkit.event.world.PortalCreateEvent event = new org.bukkit.event.world.PortalCreateEvent((java.util.List) (java.util.List) blockList.getList(), bworld, (entity == null) ? null : entity.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.NETHER_PAIR); ++ ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return Optional.empty(); ++ } ++ blockList.updateList(); ++ // CraftBukkit end ++ return Optional.of(new BlockUtil.FoundRectangle(blockposition1.immutable(), 2, 3)); + } + + private boolean canPortalReplaceBlock(BlockPos.MutableBlockPos blockpos_mutableblockpos) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/portal/PortalInfo.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/portal/PortalInfo.java.patch new file mode 100644 index 0000000000..5e814d3846 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/portal/PortalInfo.java.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/level/portal/PortalInfo.java ++++ b/net/minecraft/world/level/portal/PortalInfo.java +@@ -1,6 +2,8 @@ + package net.minecraft.world.level.portal; + + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.event.CraftPortalEvent; ++// CraftBukkit end + + public class PortalInfo { + +@@ -8,10 +11,16 @@ + public final Vec3 speed; + public final float yRot; + public final float xRot; ++ // CraftBukkit start ++ public final ServerLevel world; ++ public final CraftPortalEvent portalEventInfo; + +- public PortalInfo(Vec3 vec3, Vec3 vec31, float f, float f1) { +- this.pos = vec3; +- this.speed = vec31; ++ public PortalInfo(Vec3 vec3d, Vec3 vec3d1, float f, float f1, ServerLevel world, CraftPortalEvent portalEventInfo) { ++ this.world = world; ++ this.portalEventInfo = portalEventInfo; ++ // CraftBukkit end ++ this.pos = vec3d; ++ this.speed = vec3d1; + this.yRot = f; + this.xRot = f1; + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/portal/PortalShape.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/portal/PortalShape.java.patch new file mode 100644 index 0000000000..6693622549 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/portal/PortalShape.java.patch @@ -0,0 +1,146 @@ +--- a/net/minecraft/world/level/portal/PortalShape.java ++++ b/net/minecraft/world/level/portal/PortalShape.java +@@ -21,6 +21,10 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftPortalEvent; ++import org.bukkit.event.world.PortalCreateEvent; ++// CraftBukkit end + + public class PortalShape { + +@@ -41,6 +45,7 @@ + private BlockPos bottomLeft; + private int height; + private final int width; ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blocks; // CraftBukkit - add field + + public static Optional findEmptyPortalShape(LevelAccessor levelaccessor, BlockPos blockpos, Direction.Axis direction_axis) { + return findPortalShape(levelaccessor, blockpos, (portalshape) -> { +@@ -60,11 +65,12 @@ + } + } + +- public PortalShape(LevelAccessor levelaccessor, BlockPos blockpos, Direction.Axis direction_axis) { +- this.level = levelaccessor; +- this.axis = direction_axis; +- this.rightDir = direction_axis == Direction.Axis.X ? Direction.WEST : Direction.SOUTH; +- this.bottomLeft = this.calculateBottomLeft(blockpos); ++ public PortalShape(LevelAccessor level, BlockPos bottomLeft, Direction.Axis axis) { ++ blocks = new org.bukkit.craftbukkit.util.BlockStateListPopulator(level.getMinecraftWorld()); // CraftBukkit ++ this.level = level; ++ this.axis = axis; ++ this.rightDir = axis == Direction.Axis.X ? Direction.WEST : Direction.SOUTH; ++ this.bottomLeft = this.calculateBottomLeft(bottomLeft); + if (this.bottomLeft == null) { + this.bottomLeft = blockpos; + this.width = 1; +@@ -103,8 +109,9 @@ + blockpos_mutableblockpos.set(blockpos).move(direction, i); + BlockState blockstate = this.level.getBlockState(blockpos_mutableblockpos); + +- if (!isEmpty(blockstate)) { +- if (PortalShape.FRAME.test(blockstate, this.level, blockpos_mutableblockpos)) { ++ if (!isEmpty(iblockdata)) { ++ if (PortalShape.FRAME.test(iblockdata, this.level, blockposition_mutableblockposition)) { ++ blocks.setBlock(blockposition_mutableblockposition, iblockdata, 18); // CraftBukkit - lower left / right + return i; + } + break; +@@ -115,6 +122,7 @@ + if (!PortalShape.FRAME.test(blockstate1, this.level, blockpos_mutableblockpos)) { + break; + } ++ blocks.setBlock(blockposition_mutableblockposition, iblockdata1, 18); // CraftBukkit - bottom row + } + + return 0; +@@ -134,6 +142,7 @@ + if (!PortalShape.FRAME.test(this.level.getBlockState(blockpos_mutableblockpos1), this.level, blockpos_mutableblockpos1)) { + return false; + } ++ blocks.setBlock(blockposition_mutableblockposition1, this.level.getBlockState(blockposition_mutableblockposition1), 18); // CraftBukkit - upper row + } + + return true; +@@ -163,6 +172,10 @@ + ++this.numPortalBlocks; + } + } ++ // CraftBukkit start - left and right ++ blocks.setBlock(pos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, -1), this.level.getBlockState(pos), 18); ++ blocks.setBlock(pos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, this.width), this.level.getBlockState(pos), 18); ++ // CraftBukkit end + } + + return 21; +@@ -176,12 +189,25 @@ + return this.bottomLeft != null && this.width >= 2 && this.width <= 21 && this.height >= 3 && this.height <= 21; + } + +- public void createPortalBlocks() { +- BlockState blockstate = (BlockState) Blocks.NETHER_PORTAL.defaultBlockState().setValue(NetherPortalBlock.AXIS, this.axis); ++ // CraftBukkit start - return boolean ++ public boolean createPortalBlocks() { ++ org.bukkit.World bworld = this.level.getMinecraftWorld().getWorld(); + + BlockPos.betweenClosed(this.bottomLeft, this.bottomLeft.relative(Direction.UP, this.height - 1).relative(this.rightDir, this.width - 1)).forEach((blockpos) -> { + this.level.setBlock(blockpos, blockstate, 18); + }); ++ ++ PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) blocks.getList(), bworld, null, PortalCreateEvent.CreateReason.FIRE); ++ this.level.getMinecraftWorld().getServer().server.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ BlockPos.betweenClosed(this.bottomLeft, this.bottomLeft.relative(Direction.UP, this.height - 1).relative(this.rightDir, this.width - 1)).forEach((blockposition) -> { ++ this.level.setBlock(blockposition, iblockdata, 18); ++ }); ++ return true; // CraftBukkit + } + + public boolean isComplete() { +@@ -217,23 +246,23 @@ + return new Vec3(d3, d2, d4); + } + +- public static PortalInfo createPortalInfo(ServerLevel serverlevel, BlockUtil.FoundRectangle blockutil_foundrectangle, Direction.Axis direction_axis, Vec3 vec3, Entity entity, Vec3 vec31, float f, float f1) { +- BlockPos blockpos = blockutil_foundrectangle.minCorner; +- BlockState blockstate = serverlevel.getBlockState(blockpos); +- Direction.Axis direction_axis1 = (Direction.Axis) blockstate.getOptionalValue(BlockStateProperties.HORIZONTAL_AXIS).orElse(Direction.Axis.X); +- double d0 = (double) blockutil_foundrectangle.axis1Size; +- double d1 = (double) blockutil_foundrectangle.axis2Size; +- EntityDimensions entitydimensions = entity.getDimensions(entity.getPose()); +- int i = direction_axis == direction_axis1 ? 0 : 90; +- Vec3 vec32 = direction_axis == direction_axis1 ? vec31 : new Vec3(vec31.z, vec31.y, -vec31.x); +- double d2 = (double) entitydimensions.width / 2.0D + (d0 - (double) entitydimensions.width) * vec3.x(); +- double d3 = (d1 - (double) entitydimensions.height) * vec3.y(); +- double d4 = 0.5D + vec3.z(); +- boolean flag = direction_axis1 == Direction.Axis.X; +- Vec3 vec33 = new Vec3((double) blockpos.getX() + (flag ? d2 : d4), (double) blockpos.getY() + d3, (double) blockpos.getZ() + (flag ? d4 : d2)); +- Vec3 vec34 = findCollisionFreePosition(vec33, serverlevel, entity, entitydimensions); ++ public static PortalInfo createPortalInfo(ServerLevel worldserver, BlockUtil.FoundRectangle blockutil_rectangle, Direction.Axis enumdirection_enumaxis, Vec3 vec3d, Entity entity, Vec3 vec3d1, float f, float f1, CraftPortalEvent portalEventInfo) { // CraftBukkit ++ BlockPos blockposition = blockutil_rectangle.minCorner; ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ Direction.Axis enumdirection_enumaxis1 = (Direction.Axis) iblockdata.getOptionalValue(BlockStateProperties.HORIZONTAL_AXIS).orElse(Direction.Axis.X); ++ double d0 = (double) blockutil_rectangle.axis1Size; ++ double d1 = (double) blockutil_rectangle.axis2Size; ++ EntityDimensions entitysize = entity.getDimensions(entity.getPose()); ++ int i = enumdirection_enumaxis == enumdirection_enumaxis1 ? 0 : 90; ++ Vec3 vec3d2 = enumdirection_enumaxis == enumdirection_enumaxis1 ? vec3d1 : new Vec3(vec3d1.z, vec3d1.y, -vec3d1.x); ++ double d2 = (double) entitysize.width / 2.0D + (d0 - (double) entitysize.width) * vec3d.x(); ++ double d3 = (d1 - (double) entitysize.height) * vec3d.y(); ++ double d4 = 0.5D + vec3d.z(); ++ boolean flag = enumdirection_enumaxis1 == Direction.Axis.X; ++ Vec3 vec3d3 = new Vec3((double) blockposition.getX() + (flag ? d2 : d4), (double) blockposition.getY() + d3, (double) blockposition.getZ() + (flag ? d4 : d2)); ++ Vec3 vec3d4 = findCollisionFreePosition(vec3d3, worldserver, entity, entitysize); + +- return new PortalInfo(vec34, vec32, f + (float) i, f1); ++ return new PortalInfo(vec3d4, vec3d2, f + (float) i, f1, worldserver, portalEventInfo); // CraftBukkit + } + + private static Vec3 findCollisionFreePosition(Vec3 vec3, ServerLevel serverlevel, Entity entity, EntityDimensions entitydimensions) { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/redstone/NeighborUpdater.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/redstone/NeighborUpdater.java.patch new file mode 100644 index 0000000000..b753d72f9d --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/redstone/NeighborUpdater.java.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/world/level/redstone/NeighborUpdater.java ++++ b/net/minecraft/world/level/redstone/NeighborUpdater.java +@@ -11,7 +12,12 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.Block; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.event.block.BlockPhysicsEvent; ++// CraftBukkit end + + public interface NeighborUpdater { + +@@ -46,7 +52,18 @@ + + static void executeUpdate(Level level, BlockState blockstate, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { + try { +- blockstate.neighborChanged(level, blockpos, block, blockpos1, flag); ++ // CraftBukkit start ++ CraftWorld cworld = ((ServerLevel) level).getWorld(); ++ if (cworld != null) { ++ BlockPhysicsEvent event = new BlockPhysicsEvent(CraftBlock.at(level, pos), CraftBlockData.fromData(state), CraftBlock.at(level, neighborPos)); ++ ((ServerLevel) level).getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ state.neighborChanged(level, pos, neighborBlock, neighborPos, movedByPiston); + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception while updating neighbours"); + CrashReportCategory crashreportcategory = crashreport.addCategory("Block being updated"); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java.patch new file mode 100644 index 0000000000..2680282bad --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java.patch @@ -0,0 +1,173 @@ +--- a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java ++++ b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +@@ -32,6 +33,15 @@ + import net.minecraft.world.level.saveddata.SavedData; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.UUID; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.map.CraftMapView; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++// CraftBukkit end ++ + public class MapItemSavedData extends SavedData { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -54,8 +64,15 @@ + private final Map frameMarkers = Maps.newHashMap(); + private int trackedDecorationCount; + +- public static SavedData.Factory factory() { +- return new SavedData.Factory<>(() -> { ++ // CraftBukkit start ++ public final CraftMapView mapView; ++ private CraftServer server; ++ public UUID uniqueId = null; ++ public String id; ++ // CraftBukkit end ++ ++ public static SavedData.a factory() { ++ return new SavedData.a<>(() -> { + throw new IllegalStateException("Should never create an empty map saved data"); + }, MapItemSavedData::load, DataFixTypes.SAVED_DATA_MAP_DATA); + } +@@ -69,6 +86,10 @@ + this.unlimitedTracking = flag1; + this.locked = flag2; + this.setDirty(); ++ // CraftBukkit start ++ mapView = new CraftMapView(this); ++ server = (CraftServer) org.bukkit.Bukkit.getServer(); ++ // CraftBukkit end + } + + public static MapItemSavedData createFresh(double d0, double d1, byte b0, boolean flag, boolean flag1, ResourceKey resourcekey) { +@@ -90,8 +111,26 @@ + Logger logger = MapItemSavedData.LOGGER; + + Objects.requireNonNull(logger); +- ResourceKey resourcekey = (ResourceKey) dataresult.resultOrPartial(logger::error).orElseThrow(() -> { +- return new IllegalArgumentException("Invalid map dimension: " + compoundtag.get("dimension")); ++ // CraftBukkit start ++ ResourceKey resourcekey = dataresult.resultOrPartial(logger::error).orElseGet(() -> { ++ long least = compoundTag.getLong("UUIDLeast"); ++ long most = compoundTag.getLong("UUIDMost"); ++ ++ if (least != 0L && most != 0L) { ++ UUID uniqueId = new UUID(most, least); ++ ++ CraftWorld world = (CraftWorld) Bukkit.getWorld(uniqueId); ++ // Check if the stored world details are correct. ++ if (world == null) { ++ /* All Maps which do not have their valid world loaded are set to a dimension which hopefully won't be reached. ++ This is to prevent them being corrupted with the wrong map data. */ ++ // PAIL: Use Vanilla exception handling for now ++ } else { ++ return world.getHandle().dimension(); ++ } ++ } ++ throw new IllegalArgumentException("Invalid map dimension: " + compoundTag.get("dimension")); ++ // CraftBukkit end + }); + int i = compoundtag.getInt("xCenter"); + int j = compoundtag.getInt("zCenter"); +@@ -137,14 +175,33 @@ + dataresult.resultOrPartial(logger::error).ifPresent((tag) -> { + compoundtag.put("dimension", tag); + }); +- compoundtag.putInt("xCenter", this.centerX); +- compoundtag.putInt("zCenter", this.centerZ); +- compoundtag.putByte("scale", this.scale); +- compoundtag.putByteArray("colors", this.colors); +- compoundtag.putBoolean("trackingPosition", this.trackingPosition); +- compoundtag.putBoolean("unlimitedTracking", this.unlimitedTracking); +- compoundtag.putBoolean("locked", this.locked); +- ListTag listtag = new ListTag(); ++ // CraftBukkit start ++ if (true) { ++ if (this.uniqueId == null) { ++ for (org.bukkit.World world : server.getWorlds()) { ++ CraftWorld cWorld = (CraftWorld) world; ++ if (cWorld.getHandle().dimension() == this.dimension) { ++ this.uniqueId = cWorld.getUID(); ++ break; ++ } ++ } ++ } ++ /* Perform a second check to see if a matching world was found, this is a necessary ++ change incase Maps are forcefully unlinked from a World and lack a UID.*/ ++ if (this.uniqueId != null) { ++ compound.putLong("UUIDLeast", this.uniqueId.getLeastSignificantBits()); ++ compound.putLong("UUIDMost", this.uniqueId.getMostSignificantBits()); ++ } ++ } ++ // CraftBukkit end ++ compound.putInt("xCenter", this.centerX); ++ compound.putInt("zCenter", this.centerZ); ++ compound.putByte("scale", this.scale); ++ compound.putByteArray("colors", this.colors); ++ compound.putBoolean("trackingPosition", this.trackingPosition); ++ compound.putBoolean("unlimitedTracking", this.unlimitedTracking); ++ compound.putBoolean("locked", this.locked); ++ ListTag nbttaglist = new ListTag(); + Iterator iterator = this.bannerMarkers.values().iterator(); + + while (iterator.hasNext()) { +@@ -511,7 +568,7 @@ + this.player = player; + } + +- private MapItemSavedData.MapPatch createPatch() { ++ private MapItemSavedData.MapPatch createPatch(byte[] buffer) { // CraftBukkit + int i = this.minDirtyX; + int j = this.minDirtyY; + int k = this.maxDirtyX + 1 - this.minDirtyX; +@@ -520,7 +577,7 @@ + + for (int i1 = 0; i1 < k; ++i1) { + for (int j1 = 0; j1 < l; ++j1) { +- abyte[i1 + j1 * k] = MapItemSavedData.this.colors[i + i1 + (j + j1) * 128]; ++ abyte[i1 + j1 * k] = buffer[i + i1 + (j + j1) * 128]; // CraftBukkit + } + } + +@@ -528,21 +585,31 @@ + } + + @Nullable +- Packet nextUpdatePacket(int i) { +- MapItemSavedData.MapPatch mapitemsaveddata_mappatch; ++ Packet nextUpdatePacket(int mapId) { ++ MapItemSavedData.MapPatch worldmap_b; ++ org.bukkit.craftbukkit.map.RenderData render = MapItemSavedData.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()); // CraftBukkit + + if (this.dirtyData) { + this.dirtyData = false; +- mapitemsaveddata_mappatch = this.createPatch(); ++ worldmap_b = this.createPatch(render.buffer); // CraftBukkit + } else { + mapitemsaveddata_mappatch = null; + } + + Collection collection; + +- if (this.dirtyDecorations && this.tick++ % 5 == 0) { ++ if ((true || this.dirtyDecorations) && this.tick++ % 5 == 0) { // CraftBukkit - custom maps don't update this yet + this.dirtyDecorations = false; +- collection = MapItemSavedData.this.decorations.values(); ++ // CraftBukkit start ++ java.util.Collection icons = new java.util.ArrayList(); ++ ++ for (org.bukkit.map.MapCursor cursor : render.cursors) { ++ if (cursor.isVisible()) { ++ icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption()))); ++ } ++ } ++ collection = icons; ++ // CraftBukkit end + } else { + collection = null; + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/LevelStorageSource.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/LevelStorageSource.java.patch new file mode 100644 index 0000000000..2cbea754a8 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/LevelStorageSource.java.patch @@ -0,0 +1,91 @@ +--- a/net/minecraft/world/level/storage/LevelStorageSource.java ++++ b/net/minecraft/world/level/storage/LevelStorageSource.java +@@ -169,11 +168,12 @@ + Logger logger = LevelStorageSource.LOGGER; + + Objects.requireNonNull(logger); +- WorldGenSettings worldgensettings = (WorldGenSettings) dataresult.getOrThrow(false, Util.prefix("WorldGenSettings: ", logger::error)); +- LevelSettings levelsettings = LevelSettings.parse(dynamic1, worlddataconfiguration); +- WorldDimensions.Complete worlddimensions_complete = worldgensettings.dimensions().bake(registry); +- Lifecycle lifecycle = worlddimensions_complete.lifecycle().add(registryaccess_frozen.allRegistriesLifecycle()); +- PrimaryLevelData primaryleveldata = PrimaryLevelData.parse(dynamic1, levelsettings, worlddimensions_complete.specialWorldProperty(), worldgensettings.options(), lifecycle); ++ WorldGenSettings generatorsettings = (WorldGenSettings) dataresult.getOrThrow(false, Util.prefix("WorldGenSettings: ", logger::error)); ++ LevelSettings worldsettings = LevelSettings.parse(dynamic1, worlddataconfiguration); ++ WorldDimensions.b worlddimensions_b = generatorsettings.dimensions().bake(iregistry); ++ Lifecycle lifecycle = worlddimensions_b.lifecycle().add(iregistrycustom_dimension.allRegistriesLifecycle()); ++ PrimaryLevelData worlddataserver = PrimaryLevelData.parse(dynamic1, worldsettings, worlddimensions_b.specialWorldProperty(), generatorsettings.options(), lifecycle); ++ worlddataserver.pdc = ((Dynamic) dynamic1).getElement("BukkitValues", null); // CraftBukkit - Add PDC to world + + return new LevelDataAndDimensions(primaryleveldata, worlddimensions_complete); + } +@@ -423,28 +423,40 @@ + return this.backupDir; + } + +- public LevelStorageSource.LevelStorageAccess validateAndCreateAccess(String s) throws IOException, ContentValidationException { ++ public LevelStorageSource.LevelStorageAccess validateAndCreateAccess(String s, ResourceKey dimensionType) throws IOException, ContentValidationException { // CraftBukkit + Path path = this.getLevelPath(s); + List list = this.worldDirValidator.validateDirectory(path, true); + + if (!list.isEmpty()) { + throw new ContentValidationException(path, list); + } else { +- return new LevelStorageSource.LevelStorageAccess(s, path); ++ return new LevelStorageSource.LevelStorageAccess(s, path, dimensionType); // CraftBukkit + } + } + +- public LevelStorageSource.LevelStorageAccess createAccess(String s) throws IOException { ++ public LevelStorageSource.LevelStorageAccess createAccess(String s, ResourceKey dimensionType) throws IOException { // CraftBukkit + Path path = this.getLevelPath(s); + +- return new LevelStorageSource.LevelStorageAccess(s, path); ++ return new LevelStorageSource.LevelStorageAccess(s, path, dimensionType); // CraftBukkit + } + + public DirectoryValidator getWorldDirValidator() { + return this.worldDirValidator; + } + +- public static record LevelCandidates(List levels) implements Iterable { ++ // CraftBukkit start ++ public static Path getStorageFolder(Path path, ResourceKey dimensionType) { ++ if (dimensionType == LevelStem.OVERWORLD) { ++ return path; ++ } else if (dimensionType == LevelStem.NETHER) { ++ return path.resolve("DIM-1"); ++ } else if (dimensionType == LevelStem.END) { ++ return path.resolve("DIM1"); ++ } else { ++ return path.resolve("dimensions").resolve(dimensionType.location().getNamespace()).resolve(dimensionType.location().getPath()); ++ } ++ } ++ // CraftBukkit end + + public boolean isEmpty() { + return this.levels.isEmpty(); +@@ -503,8 +516,12 @@ + final LevelStorageSource.LevelDirectory levelDirectory; + private final String levelId; + private final Map resources = Maps.newHashMap(); ++ // CraftBukkit start ++ public final ResourceKey dimensionType; + +- LevelStorageAccess(String s, Path path) throws IOException { ++ LevelStorageAccess(String s, Path path, ResourceKey dimensionType) throws IOException { ++ this.dimensionType = dimensionType; ++ // CraftBukkit end + this.levelId = s; + this.levelDirectory = new LevelStorageSource.LevelDirectory(path); + this.lock = DirectoryLock.create(path); +@@ -539,8 +556,8 @@ + return (Path) map.computeIfAbsent(levelresource, levelstoragesource_leveldirectory::resourcePath); + } + +- public Path getDimensionPath(ResourceKey resourcekey) { +- return DimensionType.getStorageFolder(resourcekey, this.levelDirectory.path()); ++ public Path getDimensionPath(ResourceKey dimensionPath) { ++ return getStorageFolder(this.levelDirectory.path(), this.dimensionType); // CraftBukkit + } + + private void checkLock() { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/PlayerDataStorage.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/PlayerDataStorage.java.patch new file mode 100644 index 0000000000..411a4d76e9 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/PlayerDataStorage.java.patch @@ -0,0 +1,70 @@ +--- a/net/minecraft/world/level/storage/PlayerDataStorage.java ++++ b/net/minecraft/world/level/storage/PlayerDataStorage.java +@@ -15,6 +16,12 @@ + import net.minecraft.world.entity.player.Player; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.io.FileInputStream; ++import java.io.InputStream; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++// CraftBukkit end ++ + public class PlayerDataStorage { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -58,8 +65,18 @@ + PlayerDataStorage.LOGGER.warn("Failed to load player data for {}", player.getName().getString()); + } + +- if (compoundtag != null) { +- int i = NbtUtils.getDataVersion(compoundtag, -1); ++ if (nbttagcompound != null) { ++ // CraftBukkit start ++ if (player instanceof ServerPlayer) { ++ CraftPlayer player = (CraftPlayer) player.getBukkitEntity(); ++ // Only update first played if it is older than the one we have ++ long modified = new File(this.playerDir, player.getUUID().toString() + ".dat").lastModified(); ++ if (modified < player.getFirstPlayed()) { ++ player.setFirstPlayed(modified); ++ } ++ } ++ // CraftBukkit end ++ int i = NbtUtils.getDataVersion(nbttagcompound, -1); + + compoundtag = DataFixTypes.PLAYER.updateToCurrentVersion(this.fixerUpper, compoundtag, i); + player.load(compoundtag); +@@ -68,6 +85,22 @@ + return compoundtag; + } + ++ // CraftBukkit start ++ public CompoundTag getPlayerData(String s) { ++ try { ++ File file1 = new File(this.playerDir, s + ".dat"); ++ ++ if (file1.exists()) { ++ return NbtIo.readCompressed(file1.toPath(), NbtAccounter.unlimitedHeap()); ++ } ++ } catch (Exception exception) { ++ LOGGER.warn("Failed to load player data for " + s); ++ } ++ ++ return null; ++ } ++ // CraftBukkit end ++ + public String[] getSeenPlayers() { + String[] astring = this.playerDir.list(); + +@@ -83,4 +116,10 @@ + + return astring; + } ++ ++ // CraftBukkit start ++ public File getPlayerDir() { ++ return playerDir; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/PrimaryLevelData.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/PrimaryLevelData.java.patch new file mode 100644 index 0000000000..7ef05b7e32 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/PrimaryLevelData.java.patch @@ -0,0 +1,159 @@ +--- a/net/minecraft/world/level/storage/PrimaryLevelData.java ++++ b/net/minecraft/world/level/storage/PrimaryLevelData.java +@@ -42,6 +39,20 @@ + import net.minecraft.world.level.timers.TimerCallbacks; + import net.minecraft.world.level.timers.TimerQueue; + import org.slf4j.Logger; ++import net.minecraft.core.registries.Registries; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; ++import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.NbtUtils; ++import net.minecraft.nbt.StringTag; ++import net.minecraft.nbt.Tag; ++import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; ++import net.minecraft.world.level.levelgen.WorldDimensions; ++import net.minecraft.world.level.levelgen.WorldGenSettings; ++import org.bukkit.Bukkit; ++import org.bukkit.event.weather.ThunderChangeEvent; ++import org.bukkit.event.weather.WeatherChangeEvent; ++// CraftBukkit end + + public class PrimaryLevelData implements ServerLevelData, WorldData { + +@@ -81,8 +92,22 @@ + private boolean wasModded; + private final Set removedFeatureFlags; + private final TimerQueue scheduledEvents; ++ // CraftBukkit start - Add world and pdc ++ public Registry customDimensions; ++ private ServerLevel world; ++ protected Tag pdc; + +- private PrimaryLevelData(@Nullable CompoundTag compoundtag, boolean flag, int i, int j, int k, float f, long l, long i1, int j1, int k1, int l1, boolean flag1, int i2, boolean flag2, boolean flag3, boolean flag4, WorldBorder.Settings worldborder_settings, int j2, int k2, @Nullable UUID uuid, Set set, Set set1, TimerQueue timerqueue, @Nullable CompoundTag compoundtag1, EndDragonFight.Data enddragonfight_data, LevelSettings levelsettings, WorldOptions worldoptions, PrimaryLevelData.SpecialWorldProperty primaryleveldata_specialworldproperty, Lifecycle lifecycle) { ++ public void setWorld(ServerLevel world) { ++ if (this.world != null) { ++ return; ++ } ++ this.world = world; ++ world.getWorld().readBukkitValues(pdc); ++ pdc = null; ++ } ++ // CraftBukkit end ++ ++ private PrimaryLevelData(@Nullable CompoundTag nbttagcompound, boolean flag, int i, int j, int k, float f, long l, long i1, int j1, int k1, int l1, boolean flag1, int i2, boolean flag2, boolean flag3, boolean flag4, WorldBorder.Settings worldborder_c, int j2, int k2, @Nullable UUID uuid, Set set, Set set1, TimerQueue customfunctioncallbacktimerqueue, @Nullable CompoundTag nbttagcompound1, EndDragonFight.Data enderdragonbattle_a, LevelSettings worldsettings, WorldOptions worldoptions, PrimaryLevelData.a worlddataserver_a, Lifecycle lifecycle) { + this.wasModded = flag; + this.xSpawn = i; + this.ySpawn = j; +@@ -176,14 +200,14 @@ + + CompoundTag compoundtag2 = new CompoundTag(); + +- compoundtag2.putString("Name", SharedConstants.getCurrentVersion().getName()); +- compoundtag2.putInt("Id", SharedConstants.getCurrentVersion().getDataVersion().getVersion()); +- compoundtag2.putBoolean("Snapshot", !SharedConstants.getCurrentVersion().isStable()); +- compoundtag2.putString("Series", SharedConstants.getCurrentVersion().getDataVersion().getSeries()); +- compoundtag.put("Version", compoundtag2); +- NbtUtils.addCurrentDataVersion(compoundtag); +- DynamicOps dynamicops = RegistryOps.create(NbtOps.INSTANCE, (HolderLookup.Provider) registryaccess); +- DataResult dataresult = WorldGenSettings.encode(dynamicops, this.worldOptions, registryaccess); ++ nbttagcompound2.putString("Name", SharedConstants.getCurrentVersion().getName()); ++ nbttagcompound2.putInt("Id", SharedConstants.getCurrentVersion().getDataVersion().getVersion()); ++ nbttagcompound2.putBoolean("Snapshot", !SharedConstants.getCurrentVersion().isStable()); ++ nbttagcompound2.putString("Series", SharedConstants.getCurrentVersion().getDataVersion().getSeries()); ++ nbt.put("Version", nbttagcompound2); ++ NbtUtils.addCurrentDataVersion(nbt); ++ DynamicOps dynamicops = RegistryOps.create(NbtOps.INSTANCE, (HolderLookup.Provider) registry); ++ DataResult dataresult = WorldGenSettings.encode(dynamicops, this.worldOptions, new WorldDimensions(this.customDimensions != null ? this.customDimensions : registry.registryOrThrow(Registries.LEVEL_STEM))); // CraftBukkit + Logger logger = PrimaryLevelData.LOGGER; + + Objects.requireNonNull(logger); +@@ -235,6 +259,8 @@ + compoundtag.putUUID("WanderingTraderId", this.wanderingTraderId); + } + ++ nbt.putString("Bukkit.Version", Bukkit.getName() + "/" + Bukkit.getVersion() + "/" + Bukkit.getBukkitVersion()); // CraftBukkit ++ world.getWorld().storeBukkitValues(nbt); // CraftBukkit - add pdc + } + + private static ListTag stringCollectionToTag(Set set) { +@@ -365,9 +372,22 @@ + } + + @Override +- @Override +- public void setThundering(boolean flag) { +- this.thundering = flag; ++ public void setThundering(boolean thundering) { ++ // CraftBukkit start ++ if (this.thundering == thundering) { ++ return; ++ } ++ ++ org.bukkit.World world = Bukkit.getWorld(getLevelName()); ++ if (world != null) { ++ ThunderChangeEvent thunder = new ThunderChangeEvent(world, thundering); ++ Bukkit.getServer().getPluginManager().callEvent(thunder); ++ if (thunder.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ this.thundering = thundering; + } + + @Override +@@ -389,9 +406,22 @@ + } + + @Override +- @Override +- public void setRaining(boolean flag) { +- this.raining = flag; ++ public void setRaining(boolean isRaining) { ++ // CraftBukkit start ++ if (this.raining == isRaining) { ++ return; ++ } ++ ++ org.bukkit.World world = Bukkit.getWorld(getLevelName()); ++ if (world != null) { ++ WeatherChangeEvent weather = new WeatherChangeEvent(world, isRaining); ++ Bukkit.getServer().getPluginManager().callEvent(weather); ++ if (weather.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ this.raining = isRaining; + } + + @Override +@@ -470,6 +487,12 @@ + @Override + public void setDifficulty(Difficulty difficulty) { + this.settings = this.settings.withDifficulty(difficulty); ++ // CraftBukkit start ++ ClientboundChangeDifficultyPacket packet = new ClientboundChangeDifficultyPacket(this.getDifficulty(), this.isDifficultyLocked()); ++ for (ServerPlayer player : (java.util.List) (java.util.List) world.players()) { ++ player.connection.send(packet); ++ } ++ // CraftBukkit end + } + + @Override +@@ -632,6 +629,14 @@ + return this.settings.copy(); + } + ++ // CraftBukkit start - Check if the name stored in NBT is the correct one ++ public void checkName(String name) { ++ if (!this.settings.levelName.equals(name)) { ++ this.settings.levelName = name; ++ } ++ } ++ // CraftBukkit end ++ + /** @deprecated */ + @Deprecated + public static enum SpecialWorldProperty { diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/loot/LootDataManager.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/loot/LootDataManager.java.patch new file mode 100644 index 0000000000..094a4a7cf4 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/loot/LootDataManager.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/level/storage/loot/LootDataManager.java ++++ b/net/minecraft/world/level/storage/loot/LootDataManager.java +@@ -101,6 +101,13 @@ + problemreporter_collector.get().forEach((s, s1) -> { + LootDataManager.LOGGER.warn("Found loot table element validation problem in {}: {}", s, s1); + }); ++ // CraftBukkit start ++ map1.forEach((key, lootTable) -> { ++ if (object instanceof LootTable table) { ++ table.craftLootTable = new CraftLootTable(CraftNamespacedKey.fromMinecraft(key.location()), table); ++ } ++ }); ++ // CraftBukkit end + this.elements = map1; + this.typeKeys = com_google_common_collect_immutablemultimap_builder.build(); + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/loot/LootTable.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/loot/LootTable.java.patch new file mode 100644 index 0000000000..4cdf24f83f --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/loot/LootTable.java.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/level/storage/loot/LootTable.java ++++ b/net/minecraft/world/level/storage/loot/LootTable.java +@@ -28,6 +29,13 @@ + import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.CraftLootTable; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.world.LootGenerateEvent; ++// CraftBukkit end ++ + public class LootTable { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -49,6 +57,7 @@ + private final List pools; + private final List functions; + private final BiFunction compositeFunction; ++ public CraftLootTable craftLootTable; // CraftBukkit + + LootTable(LootContextParamSet lootcontextparamset, Optional optional, List list, List list1) { + this.paramSet = lootcontextparamset; +@@ -147,12 +156,25 @@ + + } + +- public void fill(Container container, LootParams lootparams, long i) { +- LootContext lootcontext = (new LootContext.Builder(lootparams)).withOptionalRandomSeed(i).create(this.randomSequence); +- ObjectArrayList objectarraylist = this.getRandomItems(lootcontext); +- RandomSource randomsource = lootcontext.getRandom(); +- List list = this.getAvailableSlots(container, randomsource); ++ public void fill(Container container, LootParams params, long seed) { ++ // CraftBukkit start ++ this.fillInventory(container, params, seed, false); ++ } + ++ public void fillInventory(Container iinventory, LootParams lootparams, long i, boolean plugin) { ++ // CraftBukkit end ++ LootContext loottableinfo = (new LootContext.Builder(lootparams)).withOptionalRandomSeed(i).create(this.randomSequence); ++ ObjectArrayList objectarraylist = this.getRandomItems(loottableinfo); ++ RandomSource randomsource = loottableinfo.getRandom(); ++ // CraftBukkit start ++ LootGenerateEvent event = CraftEventFactory.callLootGenerateEvent(iinventory, this, loottableinfo, objectarraylist, plugin); ++ if (event.isCancelled()) { ++ return; ++ } ++ objectarraylist = event.getLoot().stream().map(CraftItemStack::asNMSCopy).collect(ObjectArrayList.toList()); ++ // CraftBukkit end ++ List list = this.getAvailableSlots(iinventory, randomsource); ++ + this.shuffleAndSplitItems(objectarraylist, list.size(), randomsource); + ObjectListIterator objectlistiterator = objectarraylist.iterator(); + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java.patch new file mode 100644 index 0000000000..fc87dc8f58 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java.patch @@ -0,0 +1,19 @@ +--- a/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java ++++ b/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java +@@ -60,9 +57,14 @@ + + if (entity instanceof LivingEntity) { + int i = EnchantmentHelper.getMobLooting((LivingEntity) entity); ++ // CraftBukkit start - use lootingModifier if set by plugin ++ if (context.hasParam(LootContextParams.LOOTING_MOD)) { ++ i = context.getParamOrNull(LootContextParams.LOOTING_MOD); ++ } ++ // CraftBukkit end + +- if (i == 0) { +- return itemstack; ++ if (i <= 0) { // CraftBukkit - account for possible negative looting values from Bukkit ++ return stack; + } + + float f = (float) i * this.value.getFloat(lootcontext); diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/loot/parameters/LootContextParams.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/loot/parameters/LootContextParams.java.patch new file mode 100644 index 0000000000..06bff1eca5 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/loot/parameters/LootContextParams.java.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/world/level/storage/loot/parameters/LootContextParams.java ++++ b/net/minecraft/world/level/storage/loot/parameters/LootContextParams.java +@@ -21,6 +21,7 @@ + public static final LootContextParam BLOCK_ENTITY = create("block_entity"); + public static final LootContextParam TOOL = create("tool"); + public static final LootContextParam EXPLOSION_RADIUS = create("explosion_radius"); ++ public static final LootContextParam LOOTING_MOD = new LootContextParam<>(new ResourceLocation("bukkit:looting_mod")); // CraftBukkit + + public LootContextParams() {} + diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/loot/predicates/ExplosionCondition.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/loot/predicates/ExplosionCondition.java.patch new file mode 100644 index 0000000000..e1866659bd --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/loot/predicates/ExplosionCondition.java.patch @@ -0,0 +1,12 @@ +--- a/net/minecraft/world/level/storage/loot/predicates/ExplosionCondition.java ++++ b/net/minecraft/world/level/storage/loot/predicates/ExplosionCondition.java +@@ -35,7 +32,8 @@ + RandomSource randomsource = lootcontext.getRandom(); + float f = 1.0F / ofloat; + +- return randomsource.nextFloat() <= f; ++ // CraftBukkit - <= to < to allow for plugins to completely disable block drops from explosions ++ return randomsource.nextFloat() < f; + } else { + return true; + } diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/loot/predicates/LootItemRandomChanceWithLootingCondition.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/loot/predicates/LootItemRandomChanceWithLootingCondition.java.patch new file mode 100644 index 0000000000..fd32980e86 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/level/storage/loot/predicates/LootItemRandomChanceWithLootingCondition.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/storage/loot/predicates/LootItemRandomChanceWithLootingCondition.java ++++ b/net/minecraft/world/level/storage/loot/predicates/LootItemRandomChanceWithLootingCondition.java +@@ -37,6 +34,11 @@ + if (entity instanceof LivingEntity) { + i = EnchantmentHelper.getMobLooting((LivingEntity) entity); + } ++ // CraftBukkit start - only use lootingModifier if set by Bukkit ++ if (context.hasParam(LootContextParams.LOOTING_MOD)) { ++ i = context.getParamOrNull(LootContextParams.LOOTING_MOD); ++ } ++ // CraftBukkit end + + return lootcontext.getRandom().nextFloat() < this.percent + (float) i * this.lootingMultiplier; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/CrashReport.java.patch b/patch-remap/mache-spigotflower/net/minecraft/CrashReport.java.patch new file mode 100644 index 0000000000..4470f18054 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/CrashReport.java.patch @@ -0,0 +1,167 @@ +--- a/net/minecraft/CrashReport.java ++++ b/net/minecraft/CrashReport.java +@@ -33,9 +33,10 @@ + private StackTraceElement[] uncategorizedStackTrace = new StackTraceElement[0]; + private final SystemReport systemReport = new SystemReport(); + +- public CrashReport(String s, Throwable throwable) { +- this.title = s; +- this.exception = throwable; ++ public CrashReport(String title, Throwable exception) { ++ this.title = title; ++ this.exception = exception; ++ this.systemReport.setDetail("CraftBukkit Information", new org.bukkit.craftbukkit.CraftCrashReport()); // CraftBukkit + } + + public String getTitle() { +@@ -53,38 +54,38 @@ + return stringbuilder.toString(); + } + +- public void getDetails(StringBuilder stringbuilder) { ++ public void getDetails(StringBuilder builder) { + if ((this.uncategorizedStackTrace == null || this.uncategorizedStackTrace.length <= 0) && !this.details.isEmpty()) { + this.uncategorizedStackTrace = (StackTraceElement[]) ArrayUtils.subarray(((CrashReportCategory) this.details.get(0)).getStacktrace(), 0, 1); + } + + if (this.uncategorizedStackTrace != null && this.uncategorizedStackTrace.length > 0) { +- stringbuilder.append("-- Head --\n"); +- stringbuilder.append("Thread: ").append(Thread.currentThread().getName()).append("\n"); +- stringbuilder.append("Stacktrace:\n"); ++ builder.append("-- Head --\n"); ++ builder.append("Thread: ").append(Thread.currentThread().getName()).append("\n"); ++ builder.append("Stacktrace:\n"); + StackTraceElement[] astacktraceelement = this.uncategorizedStackTrace; + int i = astacktraceelement.length; + + for (int j = 0; j < i; ++j) { + StackTraceElement stacktraceelement = astacktraceelement[j]; + +- stringbuilder.append("\t").append("at ").append(stacktraceelement); +- stringbuilder.append("\n"); ++ builder.append("\t").append("at ").append(stacktraceelement); ++ builder.append("\n"); + } + +- stringbuilder.append("\n"); ++ builder.append("\n"); + } + + Iterator iterator = this.details.iterator(); + + while (iterator.hasNext()) { +- CrashReportCategory crashreportcategory = (CrashReportCategory) iterator.next(); ++ CrashReportCategory crashreportsystemdetails = (CrashReportCategory) iterator.next(); + +- crashreportcategory.getDetails(stringbuilder); +- stringbuilder.append("\n\n"); ++ crashreportsystemdetails.getDetails(builder); ++ builder.append("\n\n"); + } + +- this.systemReport.appendToCrashReportString(stringbuilder); ++ this.systemReport.appendToCrashReportString(builder); + } + + public String getExceptionMessage() { +@@ -149,12 +150,12 @@ + return this.saveFile; + } + +- public boolean saveToFile(File file) { ++ public boolean saveToFile(File toFile) { + if (this.saveFile != null) { + return false; + } else { +- if (file.getParentFile() != null) { +- file.getParentFile().mkdirs(); ++ if (toFile.getParentFile() != null) { ++ toFile.getParentFile().mkdirs(); + } + + OutputStreamWriter outputstreamwriter = null; +@@ -162,14 +163,14 @@ + boolean flag; + + try { +- outputstreamwriter = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8); ++ outputstreamwriter = new OutputStreamWriter(new FileOutputStream(toFile), StandardCharsets.UTF_8); + outputstreamwriter.write(this.getFriendlyReport()); +- this.saveFile = file; ++ this.saveFile = toFile; + boolean flag1 = true; + + return flag1; + } catch (Throwable throwable) { +- CrashReport.LOGGER.error("Could not save crash report to {}", file, throwable); ++ CrashReport.LOGGER.error("Could not save crash report to {}", toFile, throwable); + flag = false; + } finally { + IOUtils.closeQuietly(outputstreamwriter); +@@ -183,15 +184,15 @@ + return this.systemReport; + } + +- public CrashReportCategory addCategory(String s) { +- return this.addCategory(s, 1); ++ public CrashReportCategory addCategory(String name) { ++ return this.addCategory(name, 1); + } + +- public CrashReportCategory addCategory(String s, int i) { +- CrashReportCategory crashreportcategory = new CrashReportCategory(s); ++ public CrashReportCategory addCategory(String categoryName, int stacktraceLength) { ++ CrashReportCategory crashreportsystemdetails = new CrashReportCategory(categoryName); + + if (this.trackingStackTrace) { +- int j = crashreportcategory.fillInStackTrace(i); ++ int j = crashreportsystemdetails.fillInStackTrace(stacktraceLength); + StackTraceElement[] astacktraceelement = this.exception.getStackTrace(); + StackTraceElement stacktraceelement = null; + StackTraceElement stacktraceelement1 = null; +@@ -208,7 +209,7 @@ + } + } + +- this.trackingStackTrace = crashreportcategory.validateStackTrace(stacktraceelement, stacktraceelement1); ++ this.trackingStackTrace = crashreportsystemdetails.validateStackTrace(stacktraceelement, stacktraceelement1); + if (astacktraceelement != null && astacktraceelement.length >= j && 0 <= k && k < astacktraceelement.length) { + this.uncategorizedStackTrace = new StackTraceElement[k]; + System.arraycopy(astacktraceelement, 0, this.uncategorizedStackTrace, 0, this.uncategorizedStackTrace.length); +@@ -217,8 +218,8 @@ + } + } + +- this.details.add(crashreportcategory); +- return crashreportcategory; ++ this.details.add(crashreportsystemdetails); ++ return crashreportsystemdetails; + } + + private static String getErrorComment() { +@@ -231,19 +232,19 @@ + } + } + +- public static CrashReport forThrowable(Throwable throwable, String s) { +- while (throwable instanceof CompletionException && throwable.getCause() != null) { +- throwable = throwable.getCause(); ++ public static CrashReport forThrowable(Throwable cause, String description) { ++ while (cause instanceof CompletionException && cause.getCause() != null) { ++ cause = cause.getCause(); + } + + CrashReport crashreport; + +- if (throwable instanceof ReportedException) { +- ReportedException reportedexception = (ReportedException) throwable; ++ if (cause instanceof ReportedException) { ++ ReportedException reportedexception = (ReportedException) cause; + + crashreport = reportedexception.getReport(); + } else { +- crashreport = new CrashReport(s, throwable); ++ crashreport = new CrashReport(description, cause); + } + + return crashreport; diff --git a/patch-remap/mache-spigotflower/net/minecraft/advancements/AdvancementHolder.java.patch b/patch-remap/mache-spigotflower/net/minecraft/advancements/AdvancementHolder.java.patch new file mode 100644 index 0000000000..d743aa95ea --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/advancements/AdvancementHolder.java.patch @@ -0,0 +1,51 @@ +--- a/net/minecraft/advancements/AdvancementHolder.java ++++ b/net/minecraft/advancements/AdvancementHolder.java +@@ -2,19 +2,22 @@ + + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.resources.ResourceLocation; ++// CraftBukkit start ++import org.bukkit.craftbukkit.advancement.CraftAdvancement; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++// CraftBukkit end + + public record AdvancementHolder(ResourceLocation id, Advancement value) { + +- public void write(FriendlyByteBuf friendlybytebuf) { +- friendlybytebuf.writeResourceLocation(this.id); +- this.value.write(friendlybytebuf); ++ public void write(FriendlyByteBuf packetdataserializer) { ++ packetdataserializer.writeResourceLocation(this.id); ++ this.value.write(packetdataserializer); + } + +- public static AdvancementHolder read(FriendlyByteBuf friendlybytebuf) { +- return new AdvancementHolder(friendlybytebuf.readResourceLocation(), Advancement.read(friendlybytebuf)); ++ public static AdvancementHolder read(FriendlyByteBuf packetdataserializer) { ++ return new AdvancementHolder(packetdataserializer.readResourceLocation(), Advancement.read(packetdataserializer)); + } + +- @Override + public boolean equals(Object object) { + if (this == object) { + return true; +@@ -35,13 +38,17 @@ + } + } + +- @Override + public int hashCode() { + return this.id.hashCode(); + } + +- @Override + public String toString() { + return this.id.toString(); + } ++ ++ // CraftBukkit start ++ public final org.bukkit.advancement.Advancement toBukkit() { ++ return new CraftAdvancement(this); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/advancements/AdvancementTree.java.patch b/patch-remap/mache-spigotflower/net/minecraft/advancements/AdvancementTree.java.patch new file mode 100644 index 0000000000..b56ce287c1 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/advancements/AdvancementTree.java.patch @@ -0,0 +1,103 @@ +--- a/net/minecraft/advancements/AdvancementTree.java ++++ b/net/minecraft/advancements/AdvancementTree.java +@@ -22,7 +22,7 @@ + private final Set roots = new ObjectLinkedOpenHashSet(); + private final Set tasks = new ObjectLinkedOpenHashSet(); + @Nullable +- private AdvancementTree.Listener listener; ++ private AdvancementTree.a listener; + + public AdvancementTree() {} + +@@ -55,11 +55,11 @@ + Iterator iterator = set.iterator(); + + while (iterator.hasNext()) { +- ResourceLocation resourcelocation = (ResourceLocation) iterator.next(); +- AdvancementNode advancementnode = (AdvancementNode) this.nodes.get(resourcelocation); ++ ResourceLocation minecraftkey = (ResourceLocation) iterator.next(); ++ AdvancementNode advancementnode = (AdvancementNode) this.nodes.get(minecraftkey); + + if (advancementnode == null) { +- AdvancementTree.LOGGER.warn("Told to remove advancement {} but I don't know what that is", resourcelocation); ++ AdvancementTree.LOGGER.warn("Told to remove advancement {} but I don't know what that is", minecraftkey); + } else { + this.remove(advancementnode); + } +@@ -68,7 +68,7 @@ + } + + public void addAll(Collection collection) { +- ArrayList arraylist = new ArrayList(collection); ++ ArrayList arraylist = new ArrayList(collection); // CraftBukkit - decompile error + + while (!arraylist.isEmpty()) { + if (!arraylist.removeIf(this::tryInsert)) { +@@ -77,7 +77,7 @@ + } + } + +- AdvancementTree.LOGGER.info("Loaded {} advancements", this.nodes.size()); ++ // AdvancementTree.LOGGER.info("Loaded {} advancements", this.nodes.size()); // CraftBukkit - moved to AdvancementDataWorld#reload + } + + private boolean tryInsert(AdvancementHolder advancementholder) { +@@ -132,8 +132,8 @@ + } + + @Nullable +- public AdvancementNode get(ResourceLocation resourcelocation) { +- return (AdvancementNode) this.nodes.get(resourcelocation); ++ public AdvancementNode get(ResourceLocation minecraftkey) { ++ return (AdvancementNode) this.nodes.get(minecraftkey); + } + + @Nullable +@@ -141,37 +141,37 @@ + return (AdvancementNode) this.nodes.get(advancementholder.id()); + } + +- public void setListener(@Nullable AdvancementTree.Listener advancementtree_listener) { +- this.listener = advancementtree_listener; +- if (advancementtree_listener != null) { ++ public void setListener(@Nullable AdvancementTree.a advancementtree_a) { ++ this.listener = advancementtree_a; ++ if (advancementtree_a != null) { + Iterator iterator = this.roots.iterator(); + + AdvancementNode advancementnode; + + while (iterator.hasNext()) { + advancementnode = (AdvancementNode) iterator.next(); +- advancementtree_listener.onAddAdvancementRoot(advancementnode); ++ advancementtree_a.onAddAdvancementRoot(advancementnode); + } + + iterator = this.tasks.iterator(); + + while (iterator.hasNext()) { + advancementnode = (AdvancementNode) iterator.next(); +- advancementtree_listener.onAddAdvancementTask(advancementnode); ++ advancementtree_a.onAddAdvancementTask(advancementnode); + } + } + + } + +- public interface Listener { ++ public interface a { + +- void onAddAdvancementRoot(AdvancementNode advancementNode); ++ void onAddAdvancementRoot(AdvancementNode advancementnode); + +- void onRemoveAdvancementRoot(AdvancementNode advancementNode); ++ void onRemoveAdvancementRoot(AdvancementNode advancementnode); + +- void onAddAdvancementTask(AdvancementNode advancementNode); ++ void onAddAdvancementTask(AdvancementNode advancementnode); + +- void onRemoveAdvancementTask(AdvancementNode advancementNode); ++ void onRemoveAdvancementTask(AdvancementNode advancementnode); + + void onAdvancementsCleared(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/commands/CommandSource.java.patch b/patch-remap/mache-spigotflower/net/minecraft/commands/CommandSource.java.patch new file mode 100644 index 0000000000..332ddf77d7 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/commands/CommandSource.java.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/commands/CommandSource.java ++++ b/net/minecraft/commands/CommandSource.java +@@ -6,26 +6,29 @@ + + CommandSource NULL = new CommandSource() { + @Override +- @Override + public void sendSystemMessage(Component component) {} + + @Override +- @Override + public boolean acceptsSuccess() { + return false; + } + + @Override +- @Override + public boolean acceptsFailure() { + return false; + } + + @Override +- @Override + public boolean shouldInformAdmins() { + return false; + } ++ ++ // CraftBukkit start ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ // CraftBukkit end + }; + + void sendSystemMessage(Component component); +@@ -39,4 +42,6 @@ + default boolean alwaysAccepts() { + return false; + } ++ ++ org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper); // CraftBukkit + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/commands/CommandSourceStack.java.patch b/patch-remap/mache-spigotflower/net/minecraft/commands/CommandSourceStack.java.patch new file mode 100644 index 0000000000..16f4f7d9a5 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/commands/CommandSourceStack.java.patch @@ -0,0 +1,411 @@ +--- a/net/minecraft/commands/CommandSourceStack.java ++++ b/net/minecraft/commands/CommandSourceStack.java +@@ -1,7 +1,6 @@ + package net.minecraft.commands; + + import com.google.common.collect.Lists; +-import com.mojang.brigadier.CommandDispatcher; + import com.mojang.brigadier.Message; + import com.mojang.brigadier.context.CommandContext; + import com.mojang.brigadier.exceptions.CommandExceptionType; +@@ -44,12 +43,13 @@ + import net.minecraft.world.level.dimension.DimensionType; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; ++import com.mojang.brigadier.tree.CommandNode; // CraftBukkit + + public class CommandSourceStack implements ExecutionCommandSource, SharedSuggestionProvider { + + public static final SimpleCommandExceptionType ERROR_NOT_PLAYER = new SimpleCommandExceptionType(Component.translatable("permissions.requires.player")); + public static final SimpleCommandExceptionType ERROR_NOT_ENTITY = new SimpleCommandExceptionType(Component.translatable("permissions.requires.entity")); +- private final CommandSource source; ++ public final CommandSource source; + private final Vec3 worldPosition; + private final ServerLevel level; + private final int permissionLevel; +@@ -64,46 +64,46 @@ + private final Vec2 rotation; + private final CommandSigningContext signingContext; + private final TaskChainer chatMessageChainer; ++ public volatile CommandNode currentCommand; // CraftBukkit + +- public CommandSourceStack(CommandSource commandsource, Vec3 vec3, Vec2 vec2, ServerLevel serverlevel, int i, String s, Component component, MinecraftServer minecraftserver, @Nullable Entity entity) { +- this(commandsource, vec3, vec2, serverlevel, i, s, component, minecraftserver, entity, false, CommandResultCallback.EMPTY, EntityAnchorArgument.Anchor.FEET, CommandSigningContext.ANONYMOUS, TaskChainer.immediate(minecraftserver)); ++ public CommandSourceStack(CommandSource source, Vec3 worldPosition, Vec2 rotation, ServerLevel level, int permissionLevel, String textName, Component displayName, MinecraftServer server, @Nullable Entity entity) { ++ this(source, worldPosition, rotation, level, permissionLevel, textName, displayName, server, entity, false, CommandResultCallback.EMPTY, EntityAnchorArgument.Anchor.FEET, CommandSigningContext.ANONYMOUS, TaskChainer.immediate(server)); + } + +- protected CommandSourceStack(CommandSource commandsource, Vec3 vec3, Vec2 vec2, ServerLevel serverlevel, int i, String s, Component component, MinecraftServer minecraftserver, @Nullable Entity entity, boolean flag, CommandResultCallback commandresultcallback, EntityAnchorArgument.Anchor entityanchorargument_anchor, CommandSigningContext commandsigningcontext, TaskChainer taskchainer) { +- this.source = commandsource; +- this.worldPosition = vec3; +- this.level = serverlevel; ++ protected CommandSourceStack(CommandSource icommandlistener, Vec3 vec3d, Vec2 vec2f, ServerLevel worldserver, int i, String s, Component ichatbasecomponent, MinecraftServer minecraftserver, @Nullable Entity entity, boolean flag, CommandResultCallback commandresultcallback, EntityAnchorArgument.Anchor argumentanchor_anchor, CommandSigningContext commandsigningcontext, TaskChainer taskchainer) { ++ this.source = icommandlistener; ++ this.worldPosition = vec3d; ++ this.level = worldserver; + this.silent = flag; + this.entity = entity; + this.permissionLevel = i; + this.textName = s; +- this.displayName = component; ++ this.displayName = ichatbasecomponent; + this.server = minecraftserver; + this.resultCallback = commandresultcallback; +- this.anchor = entityanchorargument_anchor; +- this.rotation = vec2; ++ this.anchor = argumentanchor_anchor; ++ this.rotation = vec2f; + this.signingContext = commandsigningcontext; + this.chatMessageChainer = taskchainer; + } + +- public CommandSourceStack withSource(CommandSource commandsource) { +- return this.source == commandsource ? this : new CommandSourceStack(commandsource, this.worldPosition, this.rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); ++ public CommandSourceStack withSource(CommandSource source) { ++ return this.source == source ? this : new CommandSourceStack(source, this.worldPosition, this.rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); + } + + public CommandSourceStack withEntity(Entity entity) { + return this.entity == entity ? this : new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, this.permissionLevel, entity.getName().getString(), entity.getDisplayName(), this.server, entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); + } + +- public CommandSourceStack withPosition(Vec3 vec3) { +- return this.worldPosition.equals(vec3) ? this : new CommandSourceStack(this.source, vec3, this.rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); ++ public CommandSourceStack withPosition(Vec3 pos) { ++ return this.worldPosition.equals(pos) ? this : new CommandSourceStack(this.source, pos, this.rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); + } + +- public CommandSourceStack withRotation(Vec2 vec2) { +- return this.rotation.equals(vec2) ? this : new CommandSourceStack(this.source, this.worldPosition, vec2, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); ++ public CommandSourceStack withRotation(Vec2 rotation) { ++ return this.rotation.equals(rotation) ? this : new CommandSourceStack(this.source, this.worldPosition, rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); + } + + @Override +- @Override + public CommandSourceStack withCallback(CommandResultCallback commandresultcallback) { + return Objects.equals(this.resultCallback, commandresultcallback) ? this : new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, commandresultcallback, this.anchor, this.signingContext, this.chatMessageChainer); + } +@@ -118,38 +118,38 @@ + return !this.silent && !this.source.alwaysAccepts() ? new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, true, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer) : this; + } + +- public CommandSourceStack withPermission(int i) { +- return i == this.permissionLevel ? this : new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, i, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); ++ public CommandSourceStack withPermission(int permissionLevel) { ++ return permissionLevel == this.permissionLevel ? this : new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); + } + +- public CommandSourceStack withMaximumPermission(int i) { +- return i <= this.permissionLevel ? this : new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, i, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); ++ public CommandSourceStack withMaximumPermission(int permissionLevel) { ++ return permissionLevel <= this.permissionLevel ? this : new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); + } + +- public CommandSourceStack withAnchor(EntityAnchorArgument.Anchor entityanchorargument_anchor) { +- return entityanchorargument_anchor == this.anchor ? this : new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, entityanchorargument_anchor, this.signingContext, this.chatMessageChainer); ++ public CommandSourceStack withAnchor(EntityAnchorArgument.Anchor anchor) { ++ return anchor == this.anchor ? this : new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, anchor, this.signingContext, this.chatMessageChainer); + } + +- public CommandSourceStack withLevel(ServerLevel serverlevel) { +- if (serverlevel == this.level) { ++ public CommandSourceStack withLevel(ServerLevel level) { ++ if (level == this.level) { + return this; + } else { +- double d0 = DimensionType.getTeleportationScale(this.level.dimensionType(), serverlevel.dimensionType()); +- Vec3 vec3 = new Vec3(this.worldPosition.x * d0, this.worldPosition.y, this.worldPosition.z * d0); ++ double d0 = DimensionType.getTeleportationScale(this.level.dimensionType(), level.dimensionType()); ++ Vec3 vec3d = new Vec3(this.worldPosition.x * d0, this.worldPosition.y, this.worldPosition.z * d0); + +- return new CommandSourceStack(this.source, vec3, this.rotation, serverlevel, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); ++ return new CommandSourceStack(this.source, vec3d, this.rotation, level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); + } + } + +- public CommandSourceStack facing(Entity entity, EntityAnchorArgument.Anchor entityanchorargument_anchor) { +- return this.facing(entityanchorargument_anchor.apply(entity)); ++ public CommandSourceStack facing(Entity entity, EntityAnchorArgument.Anchor anchor) { ++ return this.facing(anchor.apply(entity)); + } + +- public CommandSourceStack facing(Vec3 vec3) { +- Vec3 vec31 = this.anchor.apply(this); +- double d0 = vec3.x - vec31.x; +- double d1 = vec3.y - vec31.y; +- double d2 = vec3.z - vec31.z; ++ public CommandSourceStack facing(Vec3 lookPos) { ++ Vec3 vec3d1 = this.anchor.apply(this); ++ double d0 = lookPos.x - vec3d1.x; ++ double d1 = lookPos.y - vec3d1.y; ++ double d2 = lookPos.z - vec3d1.z; + double d3 = Math.sqrt(d0 * d0 + d2 * d2); + float f = Mth.wrapDegrees((float) (-(Mth.atan2(d1, d3) * 57.2957763671875D))); + float f1 = Mth.wrapDegrees((float) (Mth.atan2(d2, d0) * 57.2957763671875D) - 90.0F); +@@ -170,11 +170,24 @@ + } + + @Override +- @Override +- public boolean hasPermission(int i) { +- return this.permissionLevel >= i; ++ public boolean hasPermission(int level) { ++ // CraftBukkit start ++ CommandNode currentCommand = this.currentCommand; ++ if (currentCommand != null) { ++ return hasPermission(level, org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(currentCommand)); ++ } ++ // CraftBukkit end ++ ++ return this.permissionLevel >= level; + } + ++ // CraftBukkit start ++ public boolean hasPermission(int i, String bukkitPermission) { ++ // World is null when loading functions ++ return ((getLevel() == null || !getLevel().getCraftServer().ignoreVanillaPermissions) && this.permissionLevel >= i) || getBukkitSender().hasPermission(bukkitPermission); ++ } ++ // CraftBukkit end ++ + public Vec3 getPosition() { + return this.worldPosition; + } +@@ -200,9 +213,9 @@ + Entity entity = this.entity; + + if (entity instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) entity; ++ ServerPlayer entityplayer = (ServerPlayer) entity; + +- return serverplayer; ++ return entityplayer; + } else { + throw CommandSourceStack.ERROR_NOT_PLAYER.create(); + } +@@ -211,17 +224,17 @@ + @Nullable + public ServerPlayer getPlayer() { + Entity entity = this.entity; +- ServerPlayer serverplayer; ++ ServerPlayer entityplayer; + + if (entity instanceof ServerPlayer) { +- ServerPlayer serverplayer1 = (ServerPlayer) entity; ++ ServerPlayer entityplayer1 = (ServerPlayer) entity; + +- serverplayer = serverplayer1; ++ entityplayer = entityplayer1; + } else { +- serverplayer = null; ++ entityplayer = null; + } + +- return serverplayer; ++ return entityplayer; + } + + public boolean isPlayer() { +@@ -248,155 +261,143 @@ + return this.chatMessageChainer; + } + +- public boolean shouldFilterMessageTo(ServerPlayer serverplayer) { +- ServerPlayer serverplayer1 = this.getPlayer(); ++ public boolean shouldFilterMessageTo(ServerPlayer receiver) { ++ ServerPlayer entityplayer1 = this.getPlayer(); + +- return serverplayer == serverplayer1 ? false : serverplayer1 != null && serverplayer1.isTextFilteringEnabled() || serverplayer.isTextFilteringEnabled(); ++ return receiver == entityplayer1 ? false : entityplayer1 != null && entityplayer1.isTextFilteringEnabled() || receiver.isTextFilteringEnabled(); + } + +- public void sendChatMessage(OutgoingChatMessage outgoingchatmessage, boolean flag, ChatType.Bound chattype_bound) { ++ public void sendChatMessage(OutgoingChatMessage message, boolean shouldFilter, ChatType.Bound boundChatType) { + if (!this.silent) { +- ServerPlayer serverplayer = this.getPlayer(); ++ ServerPlayer entityplayer = this.getPlayer(); + +- if (serverplayer != null) { +- serverplayer.sendChatMessage(outgoingchatmessage, flag, chattype_bound); ++ if (entityplayer != null) { ++ entityplayer.sendChatMessage(message, shouldFilter, boundChatType); + } else { +- this.source.sendSystemMessage(chattype_bound.decorate(outgoingchatmessage.content())); ++ this.source.sendSystemMessage(boundChatType.decorate(message.content())); + } + + } + } + +- public void sendSystemMessage(Component component) { ++ public void sendSystemMessage(Component message) { + if (!this.silent) { +- ServerPlayer serverplayer = this.getPlayer(); ++ ServerPlayer entityplayer = this.getPlayer(); + +- if (serverplayer != null) { +- serverplayer.sendSystemMessage(component); ++ if (entityplayer != null) { ++ entityplayer.sendSystemMessage(message); + } else { +- this.source.sendSystemMessage(component); ++ this.source.sendSystemMessage(message); + } + + } + } + +- public void sendSuccess(Supplier supplier, boolean flag) { ++ public void sendSuccess(Supplier messageSupplier, boolean allowLogging) { + boolean flag1 = this.source.acceptsSuccess() && !this.silent; +- boolean flag2 = flag && this.source.shouldInformAdmins() && !this.silent; ++ boolean flag2 = allowLogging && this.source.shouldInformAdmins() && !this.silent; + + if (flag1 || flag2) { +- Component component = (Component) supplier.get(); ++ Component ichatbasecomponent = (Component) messageSupplier.get(); + + if (flag1) { +- this.source.sendSystemMessage(component); ++ this.source.sendSystemMessage(ichatbasecomponent); + } + + if (flag2) { +- this.broadcastToAdmins(component); ++ this.broadcastToAdmins(ichatbasecomponent); + } + + } + } + +- private void broadcastToAdmins(Component component) { +- MutableComponent mutablecomponent = Component.translatable("chat.type.admin", this.getDisplayName(), component).withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC); ++ private void broadcastToAdmins(Component message) { ++ MutableComponent ichatmutablecomponent = Component.translatable("chat.type.admin", this.getDisplayName(), message).withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC); + + if (this.server.getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK)) { + Iterator iterator = this.server.getPlayerList().getPlayers().iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- if (serverplayer != this.source && this.server.getPlayerList().isOp(serverplayer.getGameProfile())) { +- serverplayer.sendSystemMessage(mutablecomponent); ++ if (entityplayer != this.source && entityplayer.getBukkitEntity().hasPermission("minecraft.admin.command_feedback")) { // CraftBukkit ++ entityplayer.sendSystemMessage(ichatmutablecomponent); + } + } + } + + if (this.source != this.server && this.server.getGameRules().getBoolean(GameRules.RULE_LOGADMINCOMMANDS)) { +- this.server.sendSystemMessage(mutablecomponent); ++ this.server.sendSystemMessage(ichatmutablecomponent); + } + + } + +- public void sendFailure(Component component) { ++ public void sendFailure(Component message) { + if (this.source.acceptsFailure() && !this.silent) { +- this.source.sendSystemMessage(Component.empty().append(component).withStyle(ChatFormatting.RED)); ++ this.source.sendSystemMessage(Component.empty().append(message).withStyle(ChatFormatting.RED)); + } + + } + + @Override +- @Override + public CommandResultCallback callback() { + return this.resultCallback; + } + + @Override +- @Override + public Collection getOnlinePlayerNames() { + return Lists.newArrayList(this.server.getPlayerNames()); + } + + @Override +- @Override + public Collection getAllTeams() { + return this.server.getScoreboard().getTeamNames(); + } + + @Override +- @Override + public Stream getAvailableSounds() { + return BuiltInRegistries.SOUND_EVENT.stream().map(SoundEvent::getLocation); + } + + @Override +- @Override + public Stream getRecipeNames() { + return this.server.getRecipeManager().getRecipeIds(); + } + + @Override +- @Override +- public CompletableFuture customSuggestion(CommandContext commandcontext) { ++ public CompletableFuture customSuggestion(CommandContext context) { + return Suggestions.empty(); + } + + @Override +- @Override +- public CompletableFuture suggestRegistryElements(ResourceKey> resourcekey, SharedSuggestionProvider.ElementSuggestionType sharedsuggestionprovider_elementsuggestiontype, SuggestionsBuilder suggestionsbuilder, CommandContext commandcontext) { +- return (CompletableFuture) this.registryAccess().registry(resourcekey).map((registry) -> { +- this.suggestRegistryElements(registry, sharedsuggestionprovider_elementsuggestiontype, suggestionsbuilder); +- return suggestionsbuilder.buildFuture(); ++ public CompletableFuture suggestRegistryElements(ResourceKey> resourceKey, SharedSuggestionProvider.a registryKey, SuggestionsBuilder builder, CommandContext context) { ++ return (CompletableFuture) this.registryAccess().registry(resourceKey).map((iregistry) -> { ++ this.suggestRegistryElements(iregistry, registryKey, builder); ++ return builder.buildFuture(); + }).orElseGet(Suggestions::empty); + } + + @Override +- @Override + public Set> levels() { + return this.server.levelKeys(); + } + + @Override +- @Override + public RegistryAccess registryAccess() { + return this.server.registryAccess(); + } + + @Override +- @Override + public FeatureFlagSet enabledFeatures() { + return this.level.enabledFeatures(); + } + + @Override +- @Override +- public CommandDispatcher dispatcher() { ++ public com.mojang.brigadier.CommandDispatcher dispatcher() { + return this.getServer().getFunctions().getDispatcher(); + } + + @Override +- @Override + public void handleError(CommandExceptionType commandexceptiontype, Message message, boolean flag, @Nullable TraceCallbacks tracecallbacks) { + if (tracecallbacks != null) { + tracecallbacks.onError(message.getString()); +@@ -409,8 +410,13 @@ + } + + @Override +- @Override + public boolean isSilent() { + return this.silent; + } ++ ++ // CraftBukkit start ++ public org.bukkit.command.CommandSender getBukkitSender() { ++ return source.getBukkitSender(this); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/commands/Commands.java.patch b/patch-remap/mache-spigotflower/net/minecraft/commands/Commands.java.patch new file mode 100644 index 0000000000..1a4e576de0 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/commands/Commands.java.patch @@ -0,0 +1,482 @@ +--- a/net/minecraft/commands/Commands.java ++++ b/net/minecraft/commands/Commands.java +@@ -1,7 +1,6 @@ + package net.minecraft.commands; + + import com.google.common.collect.Maps; +-import com.mojang.brigadier.CommandDispatcher; + import com.mojang.brigadier.ParseResults; + import com.mojang.brigadier.StringReader; + import com.mojang.brigadier.arguments.ArgumentType; +@@ -135,6 +134,14 @@ + import net.minecraft.world.level.GameRules; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.google.common.base.Joiner; ++import java.util.Collection; ++import java.util.LinkedHashSet; ++import org.bukkit.event.player.PlayerCommandSendEvent; ++import org.bukkit.event.server.ServerCommandEvent; ++// CraftBukkit end ++ + public class Commands { + + private static final ThreadLocal> CURRENT_EXECUTION_CONTEXT = new ThreadLocal(); +@@ -144,41 +151,42 @@ + public static final int LEVEL_GAMEMASTERS = 2; + public static final int LEVEL_ADMINS = 3; + public static final int LEVEL_OWNERS = 4; +- private final CommandDispatcher dispatcher = new CommandDispatcher(); ++ private final com.mojang.brigadier.CommandDispatcher dispatcher = new com.mojang.brigadier.CommandDispatcher(); + +- public Commands(Commands.CommandSelection commands_commandselection, CommandBuildContext commandbuildcontext) { ++ public Commands(Commands.CommandSelection selection, CommandBuildContext context) { ++ this(); // CraftBukkit + AdvancementCommands.register(this.dispatcher); +- AttributeCommand.register(this.dispatcher, commandbuildcontext); +- ExecuteCommand.register(this.dispatcher, commandbuildcontext); ++ AttributeCommand.register(this.dispatcher, context); ++ ExecuteCommand.register(this.dispatcher, context); + BossBarCommands.register(this.dispatcher); +- ClearInventoryCommands.register(this.dispatcher, commandbuildcontext); +- CloneCommands.register(this.dispatcher, commandbuildcontext); +- DamageCommand.register(this.dispatcher, commandbuildcontext); ++ ClearInventoryCommands.register(this.dispatcher, context); ++ CloneCommands.register(this.dispatcher, context); ++ DamageCommand.register(this.dispatcher, context); + DataCommands.register(this.dispatcher); + DataPackCommand.register(this.dispatcher); + DebugCommand.register(this.dispatcher); + DefaultGameModeCommands.register(this.dispatcher); + DifficultyCommand.register(this.dispatcher); +- EffectCommands.register(this.dispatcher, commandbuildcontext); ++ EffectCommands.register(this.dispatcher, context); + EmoteCommands.register(this.dispatcher); +- EnchantCommand.register(this.dispatcher, commandbuildcontext); ++ EnchantCommand.register(this.dispatcher, context); + ExperienceCommand.register(this.dispatcher); +- FillCommand.register(this.dispatcher, commandbuildcontext); +- FillBiomeCommand.register(this.dispatcher, commandbuildcontext); ++ FillCommand.register(this.dispatcher, context); ++ FillBiomeCommand.register(this.dispatcher, context); + ForceLoadCommand.register(this.dispatcher); + FunctionCommand.register(this.dispatcher); + GameModeCommand.register(this.dispatcher); + GameRuleCommand.register(this.dispatcher); +- GiveCommand.register(this.dispatcher, commandbuildcontext); ++ GiveCommand.register(this.dispatcher, context); + HelpCommand.register(this.dispatcher); +- ItemCommands.register(this.dispatcher, commandbuildcontext); ++ ItemCommands.register(this.dispatcher, context); + KickCommand.register(this.dispatcher); + KillCommand.register(this.dispatcher); + ListPlayersCommand.register(this.dispatcher); +- LocateCommand.register(this.dispatcher, commandbuildcontext); +- LootCommand.register(this.dispatcher, commandbuildcontext); ++ LocateCommand.register(this.dispatcher, context); ++ LootCommand.register(this.dispatcher, context); + MsgCommand.register(this.dispatcher); +- ParticleCommand.register(this.dispatcher, commandbuildcontext); ++ ParticleCommand.register(this.dispatcher, context); + PlaceCommand.register(this.dispatcher); + PlaySoundCommand.register(this.dispatcher); + RandomCommand.register(this.dispatcher); +@@ -189,14 +197,14 @@ + SayCommand.register(this.dispatcher); + ScheduleCommand.register(this.dispatcher); + ScoreboardCommand.register(this.dispatcher); +- SeedCommand.register(this.dispatcher, commands_commandselection != Commands.CommandSelection.INTEGRATED); +- SetBlockCommand.register(this.dispatcher, commandbuildcontext); ++ SeedCommand.register(this.dispatcher, selection != Commands.CommandSelection.INTEGRATED); ++ SetBlockCommand.register(this.dispatcher, context); + SetSpawnCommand.register(this.dispatcher); + SetWorldSpawnCommand.register(this.dispatcher); + SpectateCommand.register(this.dispatcher); + SpreadPlayersCommand.register(this.dispatcher); + StopSoundCommand.register(this.dispatcher); +- SummonCommand.register(this.dispatcher, commandbuildcontext); ++ SummonCommand.register(this.dispatcher, context); + TagCommand.register(this.dispatcher); + TeamCommand.register(this.dispatcher); + TeamMsgCommand.register(this.dispatcher); +@@ -221,12 +229,12 @@ + WardenSpawnTrackerCommand.register(this.dispatcher); + SpawnArmorTrimsCommand.register(this.dispatcher); + ServerPackCommand.register(this.dispatcher); +- if (commands_commandselection.includeDedicated) { ++ if (selection.includeDedicated) { + DebugConfigCommand.register(this.dispatcher); + } + } + +- if (commands_commandselection.includeDedicated) { ++ if (selection.includeDedicated) { + BanIpCommands.register(this.dispatcher); + BanListCommands.register(this.dispatcher); + BanPlayerCommands.register(this.dispatcher); +@@ -243,100 +251,152 @@ + WhitelistCommand.register(this.dispatcher); + } + +- if (commands_commandselection.includeIntegrated) { ++ if (selection.includeIntegrated) { + PublishCommand.register(this.dispatcher); + } + ++ // CraftBukkit start ++ } ++ ++ public Commands() { ++ // CraftBukkkit end + this.dispatcher.setConsumer(ExecutionCommandSource.resultConsumer()); + } + +- public static ParseResults mapSource(ParseResults parseresults, UnaryOperator unaryoperator) { +- CommandContextBuilder commandcontextbuilder = parseresults.getContext(); +- CommandContextBuilder commandcontextbuilder1 = commandcontextbuilder.withSource(unaryoperator.apply(commandcontextbuilder.getSource())); ++ public static ParseResults mapSource(ParseResults parseResults, UnaryOperator mapper) { ++ CommandContextBuilder commandcontextbuilder = parseResults.getContext(); ++ CommandContextBuilder commandcontextbuilder1 = commandcontextbuilder.withSource(mapper.apply(commandcontextbuilder.getSource())); + +- return new ParseResults(commandcontextbuilder1, parseresults.getReader(), parseresults.getExceptions()); ++ return new ParseResults(commandcontextbuilder1, parseResults.getReader(), parseResults.getExceptions()); + } + +- public void performPrefixedCommand(CommandSourceStack commandsourcestack, String s) { ++ // CraftBukkit start ++ public void dispatchServerCommand(CommandSourceStack sender, String command) { ++ Joiner joiner = Joiner.on(" "); ++ if (command.startsWith("/")) { ++ command = command.substring(1); ++ } ++ ++ ServerCommandEvent event = new ServerCommandEvent(sender.getBukkitSender(), command); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ command = event.getCommand(); ++ ++ String[] args = command.split(" "); ++ ++ String cmd = args[0]; ++ if (cmd.startsWith("minecraft:")) cmd = cmd.substring("minecraft:".length()); ++ if (cmd.startsWith("bukkit:")) cmd = cmd.substring("bukkit:".length()); ++ ++ // Block disallowed commands ++ if (cmd.equalsIgnoreCase("stop") || cmd.equalsIgnoreCase("kick") || cmd.equalsIgnoreCase("op") ++ || cmd.equalsIgnoreCase("deop") || cmd.equalsIgnoreCase("ban") || cmd.equalsIgnoreCase("ban-ip") ++ || cmd.equalsIgnoreCase("pardon") || cmd.equalsIgnoreCase("pardon-ip") || cmd.equalsIgnoreCase("reload")) { ++ return; ++ } ++ ++ // Handle vanilla commands; ++ if (sender.getLevel().getCraftServer().getCommandBlockOverride(args[0])) { ++ args[0] = "minecraft:" + args[0]; ++ } ++ ++ String newCommand = joiner.join(args); ++ this.performPrefixedCommand(sender, newCommand, newCommand); ++ } ++ // CraftBukkit end ++ ++ public void performPrefixedCommand(CommandSourceStack commandlistenerwrapper, String s) { ++ // CraftBukkit start ++ this.performPrefixedCommand(commandlistenerwrapper, s, s); ++ } ++ ++ public void performPrefixedCommand(CommandSourceStack commandlistenerwrapper, String s, String label) { + s = s.startsWith("/") ? s.substring(1) : s; +- this.performCommand(this.dispatcher.parse(s, commandsourcestack), s); ++ this.performCommand(this.dispatcher.parse(s, commandlistenerwrapper), s, label); ++ // CraftBukkit end + } + + public void performCommand(ParseResults parseresults, String s) { +- CommandSourceStack commandsourcestack = (CommandSourceStack) parseresults.getContext().getSource(); ++ this.performCommand(parseresults, s, s); ++ } + +- commandsourcestack.getServer().getProfiler().push(() -> { ++ public void performCommand(ParseResults parseresults, String s, String label) { // CraftBukkit ++ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) parseresults.getContext().getSource(); ++ ++ commandlistenerwrapper.getServer().getProfiler().push(() -> { + return "/" + s; + }); +- ContextChain contextchain = finishParsing(parseresults, s, commandsourcestack); ++ ContextChain contextchain = finishParsing(parseresults, s, commandlistenerwrapper, label); // CraftBukkit + + try { + if (contextchain != null) { +- executeCommandInContext(commandsourcestack, (executioncontext) -> { +- ExecutionContext.queueInitialCommandExecution(executioncontext, s, contextchain, commandsourcestack, CommandResultCallback.EMPTY); ++ executeCommandInContext(commandlistenerwrapper, (executioncontext) -> { ++ ExecutionContext.queueInitialCommandExecution(executioncontext, s, contextchain, commandlistenerwrapper, CommandResultCallback.EMPTY); + }); + } + } catch (Exception exception) { +- MutableComponent mutablecomponent = Component.literal(exception.getMessage() == null ? exception.getClass().getName() : exception.getMessage()); ++ MutableComponent ichatmutablecomponent = Component.literal(exception.getMessage() == null ? exception.getClass().getName() : exception.getMessage()); + + if (Commands.LOGGER.isDebugEnabled()) { + Commands.LOGGER.error("Command exception: /{}", s, exception); + StackTraceElement[] astacktraceelement = exception.getStackTrace(); + + for (int i = 0; i < Math.min(astacktraceelement.length, 3); ++i) { +- mutablecomponent.append("\n\n").append(astacktraceelement[i].getMethodName()).append("\n ").append(astacktraceelement[i].getFileName()).append(":").append(String.valueOf(astacktraceelement[i].getLineNumber())); ++ ichatmutablecomponent.append("\n\n").append(astacktraceelement[i].getMethodName()).append("\n ").append(astacktraceelement[i].getFileName()).append(":").append(String.valueOf(astacktraceelement[i].getLineNumber())); + } + } + +- commandsourcestack.sendFailure(Component.translatable("command.failed").withStyle((style) -> { +- return style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, mutablecomponent)); ++ commandlistenerwrapper.sendFailure(Component.translatable("command.failed").withStyle((chatmodifier) -> { ++ return chatmodifier.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, ichatmutablecomponent)); + })); + if (SharedConstants.IS_RUNNING_IN_IDE) { +- commandsourcestack.sendFailure(Component.literal(Util.describeError(exception))); ++ commandlistenerwrapper.sendFailure(Component.literal(Util.describeError(exception))); + Commands.LOGGER.error("'/{}' threw an exception", s, exception); + } + } finally { +- commandsourcestack.getServer().getProfiler().pop(); ++ commandlistenerwrapper.getServer().getProfiler().pop(); + } + + } + + @Nullable +- private static ContextChain finishParsing(ParseResults parseresults, String s, CommandSourceStack commandsourcestack) { ++ private static ContextChain finishParsing(ParseResults parseresults, String s, CommandSourceStack commandlistenerwrapper, String label) { // CraftBukkit + try { + validateParseResults(parseresults); + return (ContextChain) ContextChain.tryFlatten(parseresults.getContext().build(s)).orElseThrow(() -> { + return CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand().createWithContext(parseresults.getReader()); + }); + } catch (CommandSyntaxException commandsyntaxexception) { +- commandsourcestack.sendFailure(ComponentUtils.fromMessage(commandsyntaxexception.getRawMessage())); ++ commandlistenerwrapper.sendFailure(ComponentUtils.fromMessage(commandsyntaxexception.getRawMessage())); + if (commandsyntaxexception.getInput() != null && commandsyntaxexception.getCursor() >= 0) { + int i = Math.min(commandsyntaxexception.getInput().length(), commandsyntaxexception.getCursor()); +- MutableComponent mutablecomponent = Component.empty().withStyle(ChatFormatting.GRAY).withStyle((style) -> { +- return style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + s)); ++ MutableComponent ichatmutablecomponent = Component.empty().withStyle(ChatFormatting.GRAY).withStyle((chatmodifier) -> { ++ return chatmodifier.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, label)); // CraftBukkit + }); + + if (i > 10) { +- mutablecomponent.append(CommonComponents.ELLIPSIS); ++ ichatmutablecomponent.append(CommonComponents.ELLIPSIS); + } + +- mutablecomponent.append(commandsyntaxexception.getInput().substring(Math.max(0, i - 10), i)); ++ ichatmutablecomponent.append(commandsyntaxexception.getInput().substring(Math.max(0, i - 10), i)); + if (i < commandsyntaxexception.getInput().length()) { +- MutableComponent mutablecomponent1 = Component.literal(commandsyntaxexception.getInput().substring(i)).withStyle(ChatFormatting.RED, ChatFormatting.UNDERLINE); ++ MutableComponent ichatmutablecomponent1 = Component.literal(commandsyntaxexception.getInput().substring(i)).withStyle(ChatFormatting.RED, ChatFormatting.UNDERLINE); + +- mutablecomponent.append((Component) mutablecomponent1); ++ ichatmutablecomponent.append((Component) ichatmutablecomponent1); + } + +- mutablecomponent.append((Component) Component.translatable("command.context.here").withStyle(ChatFormatting.RED, ChatFormatting.ITALIC)); +- commandsourcestack.sendFailure(mutablecomponent); ++ ichatmutablecomponent.append((Component) Component.translatable("command.context.here").withStyle(ChatFormatting.RED, ChatFormatting.ITALIC)); ++ commandlistenerwrapper.sendFailure(ichatmutablecomponent); + } + + return null; + } + } + +- public static void executeCommandInContext(CommandSourceStack commandsourcestack, Consumer> consumer) { +- MinecraftServer minecraftserver = commandsourcestack.getServer(); ++ public static void executeCommandInContext(CommandSourceStack commandlistenerwrapper, Consumer> consumer) { ++ MinecraftServer minecraftserver = commandlistenerwrapper.getServer(); + ExecutionContext executioncontext = (ExecutionContext) Commands.CURRENT_EXECUTION_CONTEXT.get(); + boolean flag = executioncontext == null; + +@@ -363,7 +423,7 @@ + + executioncontext1.close(); + } finally { +- Commands.CURRENT_EXECUTION_CONTEXT.set((Object) null); ++ Commands.CURRENT_EXECUTION_CONTEXT.set(null); // CraftBukkit - decompile error + } + } else { + consumer.accept(executioncontext); +@@ -371,25 +431,50 @@ + + } + +- public void sendCommands(ServerPlayer serverplayer) { +- Map, CommandNode> map = Maps.newHashMap(); ++ public void sendCommands(ServerPlayer player) { ++ // CraftBukkit start ++ // Register Vanilla commands into builtRoot as before ++ Map, CommandNode> map = Maps.newIdentityHashMap(); // Use identity to prevent aliasing issues ++ RootCommandNode vanillaRoot = new RootCommandNode(); ++ ++ RootCommandNode vanilla = player.server.vanillaCommandDispatcher.getDispatcher().getRoot(); ++ map.put(vanilla, vanillaRoot); ++ this.fillUsableCommands(vanilla, vanillaRoot, player.createCommandSourceStack(), (Map) map); ++ ++ // Now build the global commands in a second pass + RootCommandNode rootcommandnode = new RootCommandNode(); + + map.put(this.dispatcher.getRoot(), rootcommandnode); +- this.fillUsableCommands(this.dispatcher.getRoot(), rootcommandnode, serverplayer.createCommandSourceStack(), map); +- serverplayer.connection.send(new ClientboundCommandsPacket(rootcommandnode)); ++ this.fillUsableCommands(this.dispatcher.getRoot(), rootcommandnode, player.createCommandSourceStack(), map); ++ ++ Collection bukkit = new LinkedHashSet<>(); ++ for (CommandNode node : rootcommandnode.getChildren()) { ++ bukkit.add(node.getName()); ++ } ++ ++ PlayerCommandSendEvent event = new PlayerCommandSendEvent(player.getBukkitEntity(), new LinkedHashSet<>(bukkit)); ++ event.getPlayer().getServer().getPluginManager().callEvent(event); ++ ++ // Remove labels that were removed during the event ++ for (String orig : bukkit) { ++ if (!event.getCommands().contains(orig)) { ++ rootcommandnode.removeCommand(orig); ++ } ++ } ++ // CraftBukkit end ++ player.connection.send(new ClientboundCommandsPacket(rootcommandnode)); + } + +- private void fillUsableCommands(CommandNode commandnode, CommandNode commandnode1, CommandSourceStack commandsourcestack, Map, CommandNode> map) { +- Iterator iterator = commandnode.getChildren().iterator(); ++ private void fillUsableCommands(CommandNode rootCommandSource, CommandNode rootSuggestion, CommandSourceStack source, Map, CommandNode> commandNodeToSuggestionNode) { ++ Iterator iterator = rootCommandSource.getChildren().iterator(); + + while (iterator.hasNext()) { + CommandNode commandnode2 = (CommandNode) iterator.next(); + +- if (commandnode2.canUse(commandsourcestack)) { +- ArgumentBuilder argumentbuilder = commandnode2.createBuilder(); ++ if (commandnode2.canUse(source)) { ++ ArgumentBuilder argumentbuilder = commandnode2.createBuilder(); // CraftBukkit - decompile error + +- argumentbuilder.requires((sharedsuggestionprovider) -> { ++ argumentbuilder.requires((icompletionprovider) -> { + return true; + }); + if (argumentbuilder.getCommand() != null) { +@@ -407,33 +492,33 @@ + } + + if (argumentbuilder.getRedirect() != null) { +- argumentbuilder.redirect((CommandNode) map.get(argumentbuilder.getRedirect())); ++ argumentbuilder.redirect((CommandNode) commandNodeToSuggestionNode.get(argumentbuilder.getRedirect())); + } + +- CommandNode commandnode3 = argumentbuilder.build(); ++ CommandNode commandnode3 = argumentbuilder.build(); // CraftBukkit - decompile error + +- map.put(commandnode2, commandnode3); +- commandnode1.addChild(commandnode3); ++ commandNodeToSuggestionNode.put(commandnode2, commandnode3); ++ rootSuggestion.addChild(commandnode3); + if (!commandnode2.getChildren().isEmpty()) { +- this.fillUsableCommands(commandnode2, commandnode3, commandsourcestack, map); ++ this.fillUsableCommands(commandnode2, commandnode3, source, commandNodeToSuggestionNode); + } + } + } + + } + +- public static LiteralArgumentBuilder literal(String s) { +- return LiteralArgumentBuilder.literal(s); ++ public static LiteralArgumentBuilder literal(String name) { ++ return LiteralArgumentBuilder.literal(name); + } + +- public static RequiredArgumentBuilder argument(String s, ArgumentType argumenttype) { +- return RequiredArgumentBuilder.argument(s, argumenttype); ++ public static RequiredArgumentBuilder argument(String name, ArgumentType type) { ++ return RequiredArgumentBuilder.argument(name, type); + } + +- public static Predicate createValidator(Commands.ParseFunction commands_parsefunction) { ++ public static Predicate createValidator(Commands.ParseFunction parser) { + return (s) -> { + try { +- commands_parsefunction.parse(new StringReader(s)); ++ parser.parse(new StringReader(s)); + return true; + } catch (CommandSyntaxException commandsyntaxexception) { + return false; +@@ -441,7 +526,7 @@ + }; + } + +- public CommandDispatcher getDispatcher() { ++ public com.mojang.brigadier.CommandDispatcher getDispatcher() { + return this.dispatcher; + } + +@@ -454,31 +539,28 @@ + } + + @Nullable +- public static CommandSyntaxException getParseException(ParseResults parseresults) { +- return !parseresults.getReader().canRead() ? null : (parseresults.getExceptions().size() == 1 ? (CommandSyntaxException) parseresults.getExceptions().values().iterator().next() : (parseresults.getContext().getRange().isEmpty() ? CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand().createWithContext(parseresults.getReader()) : CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().createWithContext(parseresults.getReader()))); ++ public static CommandSyntaxException getParseException(ParseResults result) { ++ return !result.getReader().canRead() ? null : (result.getExceptions().size() == 1 ? (CommandSyntaxException) result.getExceptions().values().iterator().next() : (result.getContext().getRange().isEmpty() ? CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand().createWithContext(result.getReader()) : CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().createWithContext(result.getReader()))); + } + +- public static CommandBuildContext createValidationContext(final HolderLookup.Provider holderlookup_provider) { ++ public static CommandBuildContext createValidationContext(final HolderLookup.Provider provider) { + return new CommandBuildContext() { + @Override +- @Override +- public HolderLookup holderLookup(ResourceKey> resourcekey) { +- final HolderLookup.RegistryLookup holderlookup_registrylookup = holderlookup_provider.lookupOrThrow(resourcekey); ++ public HolderLookup holderLookup(ResourceKey> registryResourceKey) { ++ final HolderLookup.RegistryLookup holderlookup_c = provider.lookupOrThrow(registryResourceKey); + +- return new HolderLookup.Delegate(holderlookup_registrylookup) { ++ return new HolderLookup.Delegate(holderlookup_c) { + @Override +- @Override +- public Optional> get(TagKey tagkey) { +- return Optional.of(this.getOrThrow(tagkey)); ++ public Optional> get(TagKey tagKey) { ++ return Optional.of(this.getOrThrow(tagKey)); + } + + @Override +- @Override +- public HolderSet.Named getOrThrow(TagKey tagkey) { +- Optional> optional = holderlookup_registrylookup.get(tagkey); ++ public HolderSet.Named getOrThrow(TagKey tagKey) { ++ Optional> optional = holderlookup_c.get(tagKey); + + return (HolderSet.Named) optional.orElseGet(() -> { +- return HolderSet.emptyNamed(holderlookup_registrylookup, tagkey); ++ return HolderSet.emptyNamed(holderlookup_c, tagKey); + }); + } + }; +@@ -488,11 +570,11 @@ + + public static void validate() { + CommandBuildContext commandbuildcontext = createValidationContext(VanillaRegistries.createLookup()); +- CommandDispatcher commanddispatcher = (new Commands(Commands.CommandSelection.ALL, commandbuildcontext)).getDispatcher(); +- RootCommandNode rootcommandnode = commanddispatcher.getRoot(); ++ com.mojang.brigadier.CommandDispatcher com_mojang_brigadier_commanddispatcher = (new Commands(Commands.CommandSelection.ALL, commandbuildcontext)).getDispatcher(); ++ RootCommandNode rootcommandnode = com_mojang_brigadier_commanddispatcher.getRoot(); + +- commanddispatcher.findAmbiguities((commandnode, commandnode1, commandnode2, collection) -> { +- Commands.LOGGER.warn("Ambiguity between arguments {} and {} with inputs: {}", new Object[]{commanddispatcher.getPath(commandnode1), commanddispatcher.getPath(commandnode2), collection}); ++ com_mojang_brigadier_commanddispatcher.findAmbiguities((commandnode, commandnode1, commandnode2, collection) -> { ++ Commands.LOGGER.warn("Ambiguity between arguments {} and {} with inputs: {}", new Object[]{com_mojang_brigadier_commanddispatcher.getPath(commandnode1), com_mojang_brigadier_commanddispatcher.getPath(commandnode2), collection}); + }); + Set> set = ArgumentUtils.findUsedArgumentTypes(rootcommandnode); + Set> set1 = (Set) set.stream().filter((argumenttype) -> { diff --git a/patch-remap/mache-spigotflower/net/minecraft/commands/arguments/EntityArgument.java.patch b/patch-remap/mache-spigotflower/net/minecraft/commands/arguments/EntityArgument.java.patch new file mode 100644 index 0000000000..362597edc4 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/commands/arguments/EntityArgument.java.patch @@ -0,0 +1,199 @@ +--- a/net/minecraft/commands/arguments/EntityArgument.java ++++ b/net/minecraft/commands/arguments/EntityArgument.java +@@ -36,25 +36,25 @@ + final boolean single; + final boolean playersOnly; + +- protected EntityArgument(boolean flag, boolean flag1) { +- this.single = flag; +- this.playersOnly = flag1; ++ protected EntityArgument(boolean single, boolean playersOnly) { ++ this.single = single; ++ this.playersOnly = playersOnly; + } + + public static EntityArgument entity() { + return new EntityArgument(true, false); + } + +- public static Entity getEntity(CommandContext commandcontext, String s) throws CommandSyntaxException { +- return ((EntitySelector) commandcontext.getArgument(s, EntitySelector.class)).findSingleEntity((CommandSourceStack) commandcontext.getSource()); ++ public static Entity getEntity(CommandContext context, String name) throws CommandSyntaxException { ++ return ((EntitySelector) context.getArgument(name, EntitySelector.class)).findSingleEntity((CommandSourceStack) context.getSource()); + } + + public static EntityArgument entities() { + return new EntityArgument(false, false); + } + +- public static Collection getEntities(CommandContext commandcontext, String s) throws CommandSyntaxException { +- Collection collection = getOptionalEntities(commandcontext, s); ++ public static Collection getEntities(CommandContext context, String name) throws CommandSyntaxException { ++ Collection collection = getOptionalEntities(context, name); + + if (collection.isEmpty()) { + throw EntityArgument.NO_ENTITIES_FOUND.create(); +@@ -63,28 +63,28 @@ + } + } + +- public static Collection getOptionalEntities(CommandContext commandcontext, String s) throws CommandSyntaxException { +- return ((EntitySelector) commandcontext.getArgument(s, EntitySelector.class)).findEntities((CommandSourceStack) commandcontext.getSource()); ++ public static Collection getOptionalEntities(CommandContext context, String name) throws CommandSyntaxException { ++ return ((EntitySelector) context.getArgument(name, EntitySelector.class)).findEntities((CommandSourceStack) context.getSource()); + } + +- public static Collection getOptionalPlayers(CommandContext commandcontext, String s) throws CommandSyntaxException { +- return ((EntitySelector) commandcontext.getArgument(s, EntitySelector.class)).findPlayers((CommandSourceStack) commandcontext.getSource()); ++ public static Collection getOptionalPlayers(CommandContext context, String name) throws CommandSyntaxException { ++ return ((EntitySelector) context.getArgument(name, EntitySelector.class)).findPlayers((CommandSourceStack) context.getSource()); + } + + public static EntityArgument player() { + return new EntityArgument(true, true); + } + +- public static ServerPlayer getPlayer(CommandContext commandcontext, String s) throws CommandSyntaxException { +- return ((EntitySelector) commandcontext.getArgument(s, EntitySelector.class)).findSinglePlayer((CommandSourceStack) commandcontext.getSource()); ++ public static ServerPlayer getPlayer(CommandContext context, String name) throws CommandSyntaxException { ++ return ((EntitySelector) context.getArgument(name, EntitySelector.class)).findSinglePlayer((CommandSourceStack) context.getSource()); + } + + public static EntityArgument players() { + return new EntityArgument(false, true); + } + +- public static Collection getPlayers(CommandContext commandcontext, String s) throws CommandSyntaxException { +- List list = ((EntitySelector) commandcontext.getArgument(s, EntitySelector.class)).findPlayers((CommandSourceStack) commandcontext.getSource()); ++ public static Collection getPlayers(CommandContext context, String name) throws CommandSyntaxException { ++ List list = ((EntitySelector) context.getArgument(name, EntitySelector.class)).findPlayers((CommandSourceStack) context.getSource()); + + if (list.isEmpty()) { + throw EntityArgument.NO_PLAYERS_FOUND.create(); +@@ -93,11 +93,16 @@ + } + } + +- @Override +- public EntitySelector parse(StringReader stringreader) throws CommandSyntaxException { ++ public EntitySelector parse(StringReader reader) throws CommandSyntaxException { ++ // CraftBukkit start ++ return parse(reader, false); ++ } ++ ++ public EntitySelector parse(StringReader stringreader, boolean overridePermissions) throws CommandSyntaxException { ++ // CraftBukkit end + boolean flag = false; +- EntitySelectorParser entityselectorparser = new EntitySelectorParser(stringreader); +- EntitySelector entityselector = entityselectorparser.parse(); ++ EntitySelectorParser argumentparserselector = new EntitySelectorParser(stringreader); ++ EntitySelector entityselector = argumentparserselector.parse(overridePermissions); // CraftBukkit + + if (entityselector.getMaxResults() > 1 && this.single) { + if (this.playersOnly) { +@@ -115,26 +120,25 @@ + } + } + +- @Override + public CompletableFuture listSuggestions(CommandContext commandcontext, SuggestionsBuilder suggestionsbuilder) { + Object object = commandcontext.getSource(); + + if (object instanceof SharedSuggestionProvider) { +- SharedSuggestionProvider sharedsuggestionprovider = (SharedSuggestionProvider) object; ++ SharedSuggestionProvider icompletionprovider = (SharedSuggestionProvider) object; + StringReader stringreader = new StringReader(suggestionsbuilder.getInput()); + + stringreader.setCursor(suggestionsbuilder.getStart()); +- EntitySelectorParser entityselectorparser = new EntitySelectorParser(stringreader, sharedsuggestionprovider.hasPermission(2)); ++ EntitySelectorParser argumentparserselector = new EntitySelectorParser(stringreader, icompletionprovider.hasPermission(2)); + + try { +- entityselectorparser.parse(); ++ argumentparserselector.parse(); + } catch (CommandSyntaxException commandsyntaxexception) { + ; + } + +- return entityselectorparser.fillSuggestions(suggestionsbuilder, (suggestionsbuilder1) -> { +- Collection collection = sharedsuggestionprovider.getOnlinePlayerNames(); +- Iterable iterable = this.playersOnly ? collection : Iterables.concat(collection, sharedsuggestionprovider.getSelectedEntities()); ++ return argumentparserselector.fillSuggestions(suggestionsbuilder, (suggestionsbuilder1) -> { ++ Collection collection = icompletionprovider.getOnlinePlayerNames(); ++ Iterable iterable = this.playersOnly ? collection : Iterables.concat(collection, icompletionprovider.getSelectedEntities()); + + SharedSuggestionProvider.suggest((Iterable) iterable, suggestionsbuilder1); + }); +@@ -143,7 +147,6 @@ + } + } + +- @Override + public Collection getExamples() { + return EntityArgument.EXAMPLES; + } +@@ -155,38 +158,34 @@ + + public Info() {} + +- @Override +- public void serializeToNetwork(EntityArgument.Info.Template entityargument_info_template, FriendlyByteBuf friendlybytebuf) { ++ public void serializeToNetwork(EntityArgument.Info.Template template, FriendlyByteBuf buffer) { + int i = 0; + +- if (entityargument_info_template.single) { ++ if (template.single) { + i |= 1; + } + +- if (entityargument_info_template.playersOnly) { ++ if (template.playersOnly) { + i |= 2; + } + +- friendlybytebuf.writeByte(i); ++ buffer.writeByte(i); + } + + @Override +- @Override +- public EntityArgument.Info.Template deserializeFromNetwork(FriendlyByteBuf friendlybytebuf) { +- byte b0 = friendlybytebuf.readByte(); ++ public EntityArgument.Info.Template deserializeFromNetwork(FriendlyByteBuf buffer) { ++ byte b0 = buffer.readByte(); + + return new EntityArgument.Info.Template((b0 & 1) != 0, (b0 & 2) != 0); + } + +- @Override +- public void serializeToJson(EntityArgument.Info.Template entityargument_info_template, JsonObject jsonobject) { +- jsonobject.addProperty("amount", entityargument_info_template.single ? "single" : "multiple"); +- jsonobject.addProperty("type", entityargument_info_template.playersOnly ? "players" : "entities"); ++ public void serializeToJson(EntityArgument.Info.Template template, JsonObject json) { ++ json.addProperty("amount", template.single ? "single" : "multiple"); ++ json.addProperty("type", template.playersOnly ? "players" : "entities"); + } + +- @Override +- public EntityArgument.Info.Template unpack(EntityArgument entityargument) { +- return new EntityArgument.Info.Template(entityargument.single, entityargument.playersOnly); ++ public EntityArgument.Info.Template unpack(EntityArgument argument) { ++ return new EntityArgument.Info.Template(argument.single, argument.playersOnly); + } + + public final class Template implements ArgumentTypeInfo.Template { +@@ -200,13 +199,11 @@ + } + + @Override +- @Override +- public EntityArgument instantiate(CommandBuildContext commandbuildcontext) { ++ public EntityArgument instantiate(CommandBuildContext context) { + return new EntityArgument(this.single, this.playersOnly); + } + + @Override +- @Override + public ArgumentTypeInfo type() { + return Info.this; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/commands/arguments/blocks/BlockStateParser.java.patch b/patch-remap/mache-spigotflower/net/minecraft/commands/arguments/blocks/BlockStateParser.java.patch new file mode 100644 index 0000000000..974d7a862c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/commands/arguments/blocks/BlockStateParser.java.patch @@ -0,0 +1,484 @@ +--- a/net/minecraft/commands/arguments/blocks/BlockStateParser.java ++++ b/net/minecraft/commands/arguments/blocks/BlockStateParser.java +@@ -31,7 +31,7 @@ + import net.minecraft.resources.ResourceLocation; + import net.minecraft.tags.TagKey; + import net.minecraft.world.level.block.Block; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.Property; + +@@ -68,76 +68,76 @@ + private final StringReader reader; + private final boolean forTesting; + private final boolean allowNbt; +- private final Map, Comparable> properties = Maps.newHashMap(); ++ private final Map, Comparable> properties = Maps.newLinkedHashMap(); // CraftBukkit - stable + private final Map vagueProperties = Maps.newHashMap(); + private ResourceLocation id = new ResourceLocation(""); + @Nullable +- private StateDefinition definition; ++ private StateDefinition definition; + @Nullable +- private BlockState state; ++ private IBlockData state; + @Nullable + private CompoundTag nbt; + @Nullable + private HolderSet tag; + private Function> suggestions; + +- private BlockStateParser(HolderLookup holderlookup, StringReader stringreader, boolean flag, boolean flag1) { ++ private BlockStateParser(HolderLookup blocks, StringReader reader, boolean forTesting, boolean allowNbt) { + this.suggestions = BlockStateParser.SUGGEST_NOTHING; +- this.blocks = holderlookup; +- this.reader = stringreader; +- this.forTesting = flag; +- this.allowNbt = flag1; ++ this.blocks = blocks; ++ this.reader = reader; ++ this.forTesting = forTesting; ++ this.allowNbt = allowNbt; + } + +- public static BlockStateParser.BlockResult parseForBlock(HolderLookup holderlookup, String s, boolean flag) throws CommandSyntaxException { +- return parseForBlock(holderlookup, new StringReader(s), flag); ++ public static BlockStateParser.a parseForBlock(HolderLookup lookup, String input, boolean allowNbt) throws CommandSyntaxException { ++ return parseForBlock(lookup, new StringReader(input), allowNbt); + } + +- public static BlockStateParser.BlockResult parseForBlock(HolderLookup holderlookup, StringReader stringreader, boolean flag) throws CommandSyntaxException { +- int i = stringreader.getCursor(); ++ public static BlockStateParser.a parseForBlock(HolderLookup lookup, StringReader reader, boolean allowNbt) throws CommandSyntaxException { ++ int i = reader.getCursor(); + + try { +- BlockStateParser blockstateparser = new BlockStateParser(holderlookup, stringreader, false, flag); ++ BlockStateParser argumentblock = new BlockStateParser(lookup, reader, false, allowNbt); + +- blockstateparser.parse(); +- return new BlockStateParser.BlockResult(blockstateparser.state, blockstateparser.properties, blockstateparser.nbt); ++ argumentblock.parse(); ++ return new BlockStateParser.a(argumentblock.state, argumentblock.properties, argumentblock.nbt); + } catch (CommandSyntaxException commandsyntaxexception) { +- stringreader.setCursor(i); ++ reader.setCursor(i); + throw commandsyntaxexception; + } + } + +- public static Either parseForTesting(HolderLookup holderlookup, String s, boolean flag) throws CommandSyntaxException { +- return parseForTesting(holderlookup, new StringReader(s), flag); ++ public static Either parseForTesting(HolderLookup lookup, String input, boolean allowNbt) throws CommandSyntaxException { ++ return parseForTesting(lookup, new StringReader(input), allowNbt); + } + +- public static Either parseForTesting(HolderLookup holderlookup, StringReader stringreader, boolean flag) throws CommandSyntaxException { +- int i = stringreader.getCursor(); ++ public static Either parseForTesting(HolderLookup lookup, StringReader reader, boolean allowNbt) throws CommandSyntaxException { ++ int i = reader.getCursor(); + + try { +- BlockStateParser blockstateparser = new BlockStateParser(holderlookup, stringreader, true, flag); ++ BlockStateParser argumentblock = new BlockStateParser(lookup, reader, true, allowNbt); + +- blockstateparser.parse(); +- return blockstateparser.tag != null ? Either.right(new BlockStateParser.TagResult(blockstateparser.tag, blockstateparser.vagueProperties, blockstateparser.nbt)) : Either.left(new BlockStateParser.BlockResult(blockstateparser.state, blockstateparser.properties, blockstateparser.nbt)); ++ argumentblock.parse(); ++ return argumentblock.tag != null ? Either.right(new BlockStateParser.b(argumentblock.tag, argumentblock.vagueProperties, argumentblock.nbt)) : Either.left(new BlockStateParser.a(argumentblock.state, argumentblock.properties, argumentblock.nbt)); + } catch (CommandSyntaxException commandsyntaxexception) { +- stringreader.setCursor(i); ++ reader.setCursor(i); + throw commandsyntaxexception; + } + } + +- public static CompletableFuture fillSuggestions(HolderLookup holderlookup, SuggestionsBuilder suggestionsbuilder, boolean flag, boolean flag1) { +- StringReader stringreader = new StringReader(suggestionsbuilder.getInput()); ++ public static CompletableFuture fillSuggestions(HolderLookup lookup, SuggestionsBuilder builder, boolean forTesting, boolean allowNbt) { ++ StringReader stringreader = new StringReader(builder.getInput()); + +- stringreader.setCursor(suggestionsbuilder.getStart()); +- BlockStateParser blockstateparser = new BlockStateParser(holderlookup, stringreader, flag, flag1); ++ stringreader.setCursor(builder.getStart()); ++ BlockStateParser argumentblock = new BlockStateParser(lookup, stringreader, forTesting, allowNbt); + + try { +- blockstateparser.parse(); ++ argumentblock.parse(); + } catch (CommandSyntaxException commandsyntaxexception) { + ; + } + +- return (CompletableFuture) blockstateparser.suggestions.apply(suggestionsbuilder.createOffset(stringreader.getCursor())); ++ return (CompletableFuture) argumentblock.suggestions.apply(builder.createOffset(stringreader.getCursor())); + } + + private void parse() throws CommandSyntaxException { +@@ -170,39 +170,39 @@ + + } + +- private CompletableFuture suggestPropertyNameOrEnd(SuggestionsBuilder suggestionsbuilder) { +- if (suggestionsbuilder.getRemaining().isEmpty()) { +- suggestionsbuilder.suggest(String.valueOf(']')); ++ private CompletableFuture suggestPropertyNameOrEnd(SuggestionsBuilder builder) { ++ if (builder.getRemaining().isEmpty()) { ++ builder.suggest(String.valueOf(']')); + } + +- return this.suggestPropertyName(suggestionsbuilder); ++ return this.suggestPropertyName(builder); + } + +- private CompletableFuture suggestVaguePropertyNameOrEnd(SuggestionsBuilder suggestionsbuilder) { +- if (suggestionsbuilder.getRemaining().isEmpty()) { +- suggestionsbuilder.suggest(String.valueOf(']')); ++ private CompletableFuture suggestVaguePropertyNameOrEnd(SuggestionsBuilder builder) { ++ if (builder.getRemaining().isEmpty()) { ++ builder.suggest(String.valueOf(']')); + } + +- return this.suggestVaguePropertyName(suggestionsbuilder); ++ return this.suggestVaguePropertyName(builder); + } + +- private CompletableFuture suggestPropertyName(SuggestionsBuilder suggestionsbuilder) { +- String s = suggestionsbuilder.getRemaining().toLowerCase(Locale.ROOT); ++ private CompletableFuture suggestPropertyName(SuggestionsBuilder builder) { ++ String s = builder.getRemaining().toLowerCase(Locale.ROOT); + Iterator iterator = this.state.getProperties().iterator(); + + while (iterator.hasNext()) { +- Property property = (Property) iterator.next(); ++ Property iblockstate = (Property) iterator.next(); + +- if (!this.properties.containsKey(property) && property.getName().startsWith(s)) { +- suggestionsbuilder.suggest(property.getName() + "="); ++ if (!this.properties.containsKey(iblockstate) && iblockstate.getName().startsWith(s)) { ++ builder.suggest(iblockstate.getName() + "="); + } + } + +- return suggestionsbuilder.buildFuture(); ++ return builder.buildFuture(); + } + +- private CompletableFuture suggestVaguePropertyName(SuggestionsBuilder suggestionsbuilder) { +- String s = suggestionsbuilder.getRemaining().toLowerCase(Locale.ROOT); ++ private CompletableFuture suggestVaguePropertyName(SuggestionsBuilder builder) { ++ String s = builder.getRemaining().toLowerCase(Locale.ROOT); + + if (this.tag != null) { + Iterator iterator = this.tag.iterator(); +@@ -212,24 +212,24 @@ + Iterator iterator1 = ((Block) holder.value()).getStateDefinition().getProperties().iterator(); + + while (iterator1.hasNext()) { +- Property property = (Property) iterator1.next(); ++ Property iblockstate = (Property) iterator1.next(); + +- if (!this.vagueProperties.containsKey(property.getName()) && property.getName().startsWith(s)) { +- suggestionsbuilder.suggest(property.getName() + "="); ++ if (!this.vagueProperties.containsKey(iblockstate.getName()) && iblockstate.getName().startsWith(s)) { ++ builder.suggest(iblockstate.getName() + "="); + } + } + } + } + +- return suggestionsbuilder.buildFuture(); ++ return builder.buildFuture(); + } + +- private CompletableFuture suggestOpenNbt(SuggestionsBuilder suggestionsbuilder) { +- if (suggestionsbuilder.getRemaining().isEmpty() && this.hasBlockEntity()) { +- suggestionsbuilder.suggest(String.valueOf('{')); ++ private CompletableFuture suggestOpenNbt(SuggestionsBuilder builder) { ++ if (builder.getRemaining().isEmpty() && this.hasBlockEntity()) { ++ builder.suggest(String.valueOf('{')); + } + +- return suggestionsbuilder.buildFuture(); ++ return builder.buildFuture(); + } + + private boolean hasBlockEntity() { +@@ -252,45 +252,45 @@ + } + } + +- private CompletableFuture suggestEquals(SuggestionsBuilder suggestionsbuilder) { +- if (suggestionsbuilder.getRemaining().isEmpty()) { +- suggestionsbuilder.suggest(String.valueOf('=')); ++ private CompletableFuture suggestEquals(SuggestionsBuilder builder) { ++ if (builder.getRemaining().isEmpty()) { ++ builder.suggest(String.valueOf('=')); + } + +- return suggestionsbuilder.buildFuture(); ++ return builder.buildFuture(); + } + +- private CompletableFuture suggestNextPropertyOrEnd(SuggestionsBuilder suggestionsbuilder) { +- if (suggestionsbuilder.getRemaining().isEmpty()) { +- suggestionsbuilder.suggest(String.valueOf(']')); ++ private CompletableFuture suggestNextPropertyOrEnd(SuggestionsBuilder builder) { ++ if (builder.getRemaining().isEmpty()) { ++ builder.suggest(String.valueOf(']')); + } + +- if (suggestionsbuilder.getRemaining().isEmpty() && this.properties.size() < this.state.getProperties().size()) { +- suggestionsbuilder.suggest(String.valueOf(',')); ++ if (builder.getRemaining().isEmpty() && this.properties.size() < this.state.getProperties().size()) { ++ builder.suggest(String.valueOf(',')); + } + +- return suggestionsbuilder.buildFuture(); ++ return builder.buildFuture(); + } + +- private static > SuggestionsBuilder addSuggestions(SuggestionsBuilder suggestionsbuilder, Property property) { ++ private static > SuggestionsBuilder addSuggestions(SuggestionsBuilder builder, Property property) { + Iterator iterator = property.getPossibleValues().iterator(); + + while (iterator.hasNext()) { +- T t0 = (Comparable) iterator.next(); ++ T t0 = (T) iterator.next(); // CraftBukkit - decompile error + + if (t0 instanceof Integer) { + Integer integer = (Integer) t0; + +- suggestionsbuilder.suggest(integer); ++ builder.suggest(integer); + } else { +- suggestionsbuilder.suggest(property.getName(t0)); ++ builder.suggest(property.getName(t0)); + } + } + +- return suggestionsbuilder; ++ return builder; + } + +- private CompletableFuture suggestVaguePropertyValue(SuggestionsBuilder suggestionsbuilder, String s) { ++ private CompletableFuture suggestVaguePropertyValue(SuggestionsBuilder builder, String propertyName) { + boolean flag = false; + + if (this.tag != null) { +@@ -299,19 +299,19 @@ + while (iterator.hasNext()) { + Holder holder = (Holder) iterator.next(); + Block block = (Block) holder.value(); +- Property property = block.getStateDefinition().getProperty(s); ++ Property iblockstate = block.getStateDefinition().getProperty(propertyName); + +- if (property != null) { +- addSuggestions(suggestionsbuilder, property); ++ if (iblockstate != null) { ++ addSuggestions(builder, iblockstate); + } + + if (!flag) { + Iterator iterator1 = block.getStateDefinition().getProperties().iterator(); + + while (iterator1.hasNext()) { +- Property property1 = (Property) iterator1.next(); ++ Property iblockstate1 = (Property) iterator1.next(); + +- if (!this.vagueProperties.containsKey(property1.getName())) { ++ if (!this.vagueProperties.containsKey(iblockstate1.getName())) { + flag = true; + break; + } +@@ -321,15 +321,15 @@ + } + + if (flag) { +- suggestionsbuilder.suggest(String.valueOf(',')); ++ builder.suggest(String.valueOf(',')); + } + +- suggestionsbuilder.suggest(String.valueOf(']')); +- return suggestionsbuilder.buildFuture(); ++ builder.suggest(String.valueOf(']')); ++ return builder.buildFuture(); + } + +- private CompletableFuture suggestOpenVaguePropertiesOrNbt(SuggestionsBuilder suggestionsbuilder) { +- if (suggestionsbuilder.getRemaining().isEmpty() && this.tag != null) { ++ private CompletableFuture suggestOpenVaguePropertiesOrNbt(SuggestionsBuilder builder) { ++ if (builder.getRemaining().isEmpty() && this.tag != null) { + boolean flag = false; + boolean flag1 = false; + Iterator iterator = this.tag.iterator(); +@@ -346,43 +346,43 @@ + } + + if (flag) { +- suggestionsbuilder.suggest(String.valueOf('[')); ++ builder.suggest(String.valueOf('[')); + } + + if (flag1) { +- suggestionsbuilder.suggest(String.valueOf('{')); ++ builder.suggest(String.valueOf('{')); + } + } + +- return suggestionsbuilder.buildFuture(); ++ return builder.buildFuture(); + } + +- private CompletableFuture suggestOpenPropertiesOrNbt(SuggestionsBuilder suggestionsbuilder) { +- if (suggestionsbuilder.getRemaining().isEmpty()) { ++ private CompletableFuture suggestOpenPropertiesOrNbt(SuggestionsBuilder builder) { ++ if (builder.getRemaining().isEmpty()) { + if (!this.definition.getProperties().isEmpty()) { +- suggestionsbuilder.suggest(String.valueOf('[')); ++ builder.suggest(String.valueOf('[')); + } + + if (this.state.hasBlockEntity()) { +- suggestionsbuilder.suggest(String.valueOf('{')); ++ builder.suggest(String.valueOf('{')); + } + } + +- return suggestionsbuilder.buildFuture(); ++ return builder.buildFuture(); + } + +- private CompletableFuture suggestTag(SuggestionsBuilder suggestionsbuilder) { +- return SharedSuggestionProvider.suggestResource(this.blocks.listTagIds().map(TagKey::location), suggestionsbuilder, String.valueOf('#')); ++ private CompletableFuture suggestTag(SuggestionsBuilder builder) { ++ return SharedSuggestionProvider.suggestResource(this.blocks.listTagIds().map(TagKey::location), builder, String.valueOf('#')); + } + +- private CompletableFuture suggestItem(SuggestionsBuilder suggestionsbuilder) { +- return SharedSuggestionProvider.suggestResource(this.blocks.listElementIds().map(ResourceKey::location), suggestionsbuilder); ++ private CompletableFuture suggestItem(SuggestionsBuilder builder) { ++ return SharedSuggestionProvider.suggestResource(this.blocks.listElementIds().map(ResourceKey::location), builder); + } + +- private CompletableFuture suggestBlockIdOrTag(SuggestionsBuilder suggestionsbuilder) { +- this.suggestTag(suggestionsbuilder); +- this.suggestItem(suggestionsbuilder); +- return suggestionsbuilder.buildFuture(); ++ private CompletableFuture suggestBlockIdOrTag(SuggestionsBuilder builder) { ++ this.suggestTag(builder); ++ this.suggestItem(builder); ++ return builder.buildFuture(); + } + + private void readBlock() throws CommandSyntaxException { +@@ -406,11 +406,11 @@ + + this.reader.expect('#'); + this.suggestions = this::suggestTag; +- ResourceLocation resourcelocation = ResourceLocation.read(this.reader); ++ ResourceLocation minecraftkey = ResourceLocation.read(this.reader); + +- this.tag = (HolderSet) this.blocks.get(TagKey.create(Registries.BLOCK, resourcelocation)).orElseThrow(() -> { ++ this.tag = (HolderSet) this.blocks.get(TagKey.create(Registries.BLOCK, minecraftkey)).orElseThrow(() -> { + this.reader.setCursor(i); +- return BlockStateParser.ERROR_UNKNOWN_TAG.createWithContext(this.reader, resourcelocation.toString()); ++ return BlockStateParser.ERROR_UNKNOWN_TAG.createWithContext(this.reader, minecraftkey.toString()); + }); + } + } +@@ -425,14 +425,14 @@ + this.reader.skipWhitespace(); + int i = this.reader.getCursor(); + String s = this.reader.readString(); +- Property property = this.definition.getProperty(s); ++ Property iblockstate = this.definition.getProperty(s); + +- if (property == null) { ++ if (iblockstate == null) { + this.reader.setCursor(i); + throw BlockStateParser.ERROR_UNKNOWN_PROPERTY.createWithContext(this.reader, this.id.toString(), s); + } + +- if (this.properties.containsKey(property)) { ++ if (this.properties.containsKey(iblockstate)) { + this.reader.setCursor(i); + throw BlockStateParser.ERROR_DUPLICATE_PROPERTY.createWithContext(this.reader, this.id.toString(), s); + } +@@ -446,11 +446,11 @@ + this.reader.skip(); + this.reader.skipWhitespace(); + this.suggestions = (suggestionsbuilder) -> { +- return addSuggestions(suggestionsbuilder, property).buildFuture(); ++ return addSuggestions(suggestionsbuilder, iblockstate).buildFuture(); + }; + int j = this.reader.getCursor(); + +- this.setValue(property, this.reader.readString(), j); ++ this.setValue(iblockstate, this.reader.readString(), j); + this.suggestions = this::suggestNextPropertyOrEnd; + this.reader.skipWhitespace(); + if (!this.reader.canRead()) { +@@ -544,28 +544,28 @@ + this.nbt = (new TagParser(this.reader)).readStruct(); + } + +- private > void setValue(Property property, String s, int i) throws CommandSyntaxException { +- Optional optional = property.getValue(s); ++ private > void setValue(Property property, String value, int valuePosition) throws CommandSyntaxException { ++ Optional optional = property.getValue(value); + + if (optional.isPresent()) { +- this.state = (BlockState) this.state.setValue(property, (Comparable) optional.get()); ++ this.state = (IBlockData) this.state.setValue(property, (T) optional.get()); // CraftBukkit - decompile error + this.properties.put(property, (Comparable) optional.get()); + } else { +- this.reader.setCursor(i); +- throw BlockStateParser.ERROR_INVALID_VALUE.createWithContext(this.reader, this.id.toString(), property.getName(), s); ++ this.reader.setCursor(valuePosition); ++ throw BlockStateParser.ERROR_INVALID_VALUE.createWithContext(this.reader, this.id.toString(), property.getName(), value); + } + } + +- public static String serialize(BlockState blockstate) { +- StringBuilder stringbuilder = new StringBuilder((String) blockstate.getBlockHolder().unwrapKey().map((resourcekey) -> { ++ public static String serialize(IBlockData state) { ++ StringBuilder stringbuilder = new StringBuilder((String) state.getBlockHolder().unwrapKey().map((resourcekey) -> { + return resourcekey.location().toString(); + }).orElse("air")); + +- if (!blockstate.getProperties().isEmpty()) { ++ if (!state.getProperties().isEmpty()) { + stringbuilder.append('['); + boolean flag = false; + +- for (UnmodifiableIterator unmodifiableiterator = blockstate.getValues().entrySet().iterator(); unmodifiableiterator.hasNext(); flag = true) { ++ for (UnmodifiableIterator unmodifiableiterator = state.getValues().entrySet().iterator(); unmodifiableiterator.hasNext(); flag = true) { + Entry, Comparable> entry = (Entry) unmodifiableiterator.next(); + + if (flag) { +@@ -581,17 +581,17 @@ + return stringbuilder.toString(); + } + +- private static > void appendProperty(StringBuilder stringbuilder, Property property, Comparable comparable) { +- stringbuilder.append(property.getName()); +- stringbuilder.append('='); +- stringbuilder.append(property.getName(comparable)); ++ private static > void appendProperty(StringBuilder builder, Property property, Comparable value) { ++ builder.append(property.getName()); ++ builder.append('='); ++ builder.append(property.getName((T) value)); // CraftBukkit - decompile error + } + +- public static record BlockResult(BlockState blockState, Map, Comparable> properties, @Nullable CompoundTag nbt) { ++ public static record a(IBlockData blockState, Map, Comparable> properties, @Nullable CompoundTag nbt) { + + } + +- public static record TagResult(HolderSet tag, Map vagueProperties, @Nullable CompoundTag nbt) { ++ public static record b(HolderSet tag, Map vagueProperties, @Nullable CompoundTag nbt) { + + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/commands/arguments/selector/EntitySelector.java.patch b/patch-remap/mache-spigotflower/net/minecraft/commands/arguments/selector/EntitySelector.java.patch new file mode 100644 index 0000000000..3217274cc0 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/commands/arguments/selector/EntitySelector.java.patch @@ -0,0 +1,296 @@ +--- a/net/minecraft/commands/arguments/selector/EntitySelector.java ++++ b/net/minecraft/commands/arguments/selector/EntitySelector.java +@@ -26,16 +26,14 @@ + public class EntitySelector { + + public static final int INFINITE = Integer.MAX_VALUE; +- public static final BiConsumer> ORDER_ARBITRARY = (vec3, list) -> { ++ public static final BiConsumer> ORDER_ARBITRARY = (vec3d, list) -> { + }; + private static final EntityTypeTest ANY_TYPE = new EntityTypeTest() { +- @Override + public Entity tryCast(Entity entity) { + return entity; + } + + @Override +- @Override + public Class getBaseClass() { + return Entity.class; + } +@@ -57,20 +55,20 @@ + private final EntityTypeTest type; + private final boolean usesSelector; + +- public EntitySelector(int i, boolean flag, boolean flag1, Predicate predicate, MinMaxBounds.Doubles minmaxbounds_doubles, Function function, @Nullable AABB aabb, BiConsumer> biconsumer, boolean flag2, @Nullable String s, @Nullable UUID uuid, @Nullable EntityType entitytype, boolean flag3) { +- this.maxResults = i; +- this.includesEntities = flag; +- this.worldLimited = flag1; ++ public EntitySelector(int maxResults, boolean includeEntities, boolean worldLimited, Predicate predicate, MinMaxBounds.Doubles range, Function positions, @Nullable AABB aabb, BiConsumer> order, boolean currentEntity, @Nullable String playerName, @Nullable UUID entityUUID, @Nullable EntityType type, boolean usesSelector) { ++ this.maxResults = maxResults; ++ this.includesEntities = includeEntities; ++ this.worldLimited = worldLimited; + this.predicate = predicate; +- this.range = minmaxbounds_doubles; +- this.position = function; ++ this.range = range; ++ this.position = positions; + this.aabb = aabb; +- this.order = biconsumer; +- this.currentEntity = flag2; +- this.playerName = s; +- this.entityUUID = uuid; +- this.type = (EntityTypeTest) (entitytype == null ? EntitySelector.ANY_TYPE : entitytype); +- this.usesSelector = flag3; ++ this.order = order; ++ this.currentEntity = currentEntity; ++ this.playerName = playerName; ++ this.entityUUID = entityUUID; ++ this.type = (EntityTypeTest) (type == null ? EntitySelector.ANY_TYPE : type); ++ this.usesSelector = usesSelector; + } + + public int getMaxResults() { +@@ -93,15 +91,15 @@ + return this.usesSelector; + } + +- private void checkPermissions(CommandSourceStack commandsourcestack) throws CommandSyntaxException { +- if (this.usesSelector && !commandsourcestack.hasPermission(2)) { ++ private void checkPermissions(CommandSourceStack source) throws CommandSyntaxException { ++ if (this.usesSelector && !source.hasPermission(2, "minecraft.command.selector")) { // CraftBukkit + throw EntityArgument.ERROR_SELECTORS_NOT_ALLOWED.create(); + } + } + +- public Entity findSingleEntity(CommandSourceStack commandsourcestack) throws CommandSyntaxException { +- this.checkPermissions(commandsourcestack); +- List list = this.findEntities(commandsourcestack); ++ public Entity findSingleEntity(CommandSourceStack source) throws CommandSyntaxException { ++ this.checkPermissions(source); ++ List list = this.findEntities(source); + + if (list.isEmpty()) { + throw EntityArgument.NO_ENTITIES_FOUND.create(); +@@ -112,22 +110,22 @@ + } + } + +- public List findEntities(CommandSourceStack commandsourcestack) throws CommandSyntaxException { +- return this.findEntitiesRaw(commandsourcestack).stream().filter((entity) -> { +- return entity.getType().isEnabled(commandsourcestack.enabledFeatures()); ++ public List findEntities(CommandSourceStack source) throws CommandSyntaxException { ++ return this.findEntitiesRaw(source).stream().filter((entity) -> { ++ return entity.getType().isEnabled(source.enabledFeatures()); + }).toList(); + } + +- private List findEntitiesRaw(CommandSourceStack commandsourcestack) throws CommandSyntaxException { +- this.checkPermissions(commandsourcestack); ++ private List findEntitiesRaw(CommandSourceStack source) throws CommandSyntaxException { ++ this.checkPermissions(source); + if (!this.includesEntities) { +- return this.findPlayers(commandsourcestack); ++ return this.findPlayers(source); + } else if (this.playerName != null) { +- ServerPlayer serverplayer = commandsourcestack.getServer().getPlayerList().getPlayerByName(this.playerName); ++ ServerPlayer entityplayer = source.getServer().getPlayerList().getPlayerByName(this.playerName); + +- return (List) (serverplayer == null ? Collections.emptyList() : Lists.newArrayList(new ServerPlayer[]{serverplayer})); ++ return (List) (entityplayer == null ? Collections.emptyList() : Lists.newArrayList(new ServerPlayer[]{entityplayer})); + } else if (this.entityUUID != null) { +- Iterator iterator = commandsourcestack.getServer().getAllLevels().iterator(); ++ Iterator iterator = source.getServer().getAllLevels().iterator(); + + Entity entity; + +@@ -136,46 +134,46 @@ + return Collections.emptyList(); + } + +- ServerLevel serverlevel = (ServerLevel) iterator.next(); ++ ServerLevel worldserver = (ServerLevel) iterator.next(); + +- entity = serverlevel.getEntity(this.entityUUID); ++ entity = worldserver.getEntity(this.entityUUID); + } while (entity == null); + + return Lists.newArrayList(new Entity[]{entity}); + } else { +- Vec3 vec3 = (Vec3) this.position.apply(commandsourcestack.getPosition()); +- Predicate predicate = this.getPredicate(vec3); ++ Vec3 vec3d = (Vec3) this.position.apply(source.getPosition()); ++ Predicate predicate = this.getPredicate(vec3d); + + if (this.currentEntity) { +- return (List) (commandsourcestack.getEntity() != null && predicate.test(commandsourcestack.getEntity()) ? Lists.newArrayList(new Entity[]{commandsourcestack.getEntity()}) : Collections.emptyList()); ++ return (List) (source.getEntity() != null && predicate.test(source.getEntity()) ? Lists.newArrayList(new Entity[]{source.getEntity()}) : Collections.emptyList()); + } else { + List list = Lists.newArrayList(); + + if (this.isWorldLimited()) { +- this.addEntities(list, commandsourcestack.getLevel(), vec3, predicate); ++ this.addEntities(list, source.getLevel(), vec3d, predicate); + } else { +- Iterator iterator1 = commandsourcestack.getServer().getAllLevels().iterator(); ++ Iterator iterator1 = source.getServer().getAllLevels().iterator(); + + while (iterator1.hasNext()) { +- ServerLevel serverlevel1 = (ServerLevel) iterator1.next(); ++ ServerLevel worldserver1 = (ServerLevel) iterator1.next(); + +- this.addEntities(list, serverlevel1, vec3, predicate); ++ this.addEntities(list, worldserver1, vec3d, predicate); + } + } + +- return this.sortAndLimit(vec3, list); ++ return this.sortAndLimit(vec3d, list); + } + } + } + +- private void addEntities(List list, ServerLevel serverlevel, Vec3 vec3, Predicate predicate) { ++ private void addEntities(List result, ServerLevel level, Vec3 pos, Predicate predicate) { + int i = this.getResultLimit(); + +- if (list.size() < i) { ++ if (result.size() < i) { + if (this.aabb != null) { +- serverlevel.getEntities(this.type, this.aabb.move(vec3), predicate, list, i); ++ level.getEntities(this.type, this.aabb.move(pos), predicate, result, i); + } else { +- serverlevel.getEntities(this.type, predicate, list, i); ++ level.getEntities(this.type, predicate, result, i); + } + + } +@@ -185,9 +183,9 @@ + return this.order == EntitySelector.ORDER_ARBITRARY ? this.maxResults : Integer.MAX_VALUE; + } + +- public ServerPlayer findSinglePlayer(CommandSourceStack commandsourcestack) throws CommandSyntaxException { +- this.checkPermissions(commandsourcestack); +- List list = this.findPlayers(commandsourcestack); ++ public ServerPlayer findSinglePlayer(CommandSourceStack source) throws CommandSyntaxException { ++ this.checkPermissions(source); ++ List list = this.findPlayers(source); + + if (list.size() != 1) { + throw EntityArgument.NO_PLAYERS_FOUND.create(); +@@ -196,28 +194,28 @@ + } + } + +- public List findPlayers(CommandSourceStack commandsourcestack) throws CommandSyntaxException { +- this.checkPermissions(commandsourcestack); +- ServerPlayer serverplayer; ++ public List findPlayers(CommandSourceStack source) throws CommandSyntaxException { ++ this.checkPermissions(source); ++ ServerPlayer entityplayer; + + if (this.playerName != null) { +- serverplayer = commandsourcestack.getServer().getPlayerList().getPlayerByName(this.playerName); +- return (List) (serverplayer == null ? Collections.emptyList() : Lists.newArrayList(new ServerPlayer[]{serverplayer})); ++ entityplayer = source.getServer().getPlayerList().getPlayerByName(this.playerName); ++ return (List) (entityplayer == null ? Collections.emptyList() : Lists.newArrayList(new ServerPlayer[]{entityplayer})); + } else if (this.entityUUID != null) { +- serverplayer = commandsourcestack.getServer().getPlayerList().getPlayer(this.entityUUID); +- return (List) (serverplayer == null ? Collections.emptyList() : Lists.newArrayList(new ServerPlayer[]{serverplayer})); ++ entityplayer = source.getServer().getPlayerList().getPlayer(this.entityUUID); ++ return (List) (entityplayer == null ? Collections.emptyList() : Lists.newArrayList(new ServerPlayer[]{entityplayer})); + } else { +- Vec3 vec3 = (Vec3) this.position.apply(commandsourcestack.getPosition()); +- Predicate predicate = this.getPredicate(vec3); ++ Vec3 vec3d = (Vec3) this.position.apply(source.getPosition()); ++ Predicate predicate = this.getPredicate(vec3d); + + if (this.currentEntity) { +- Entity entity = commandsourcestack.getEntity(); ++ Entity entity = source.getEntity(); + + if (entity instanceof ServerPlayer) { +- ServerPlayer serverplayer1 = (ServerPlayer) entity; ++ ServerPlayer entityplayer1 = (ServerPlayer) entity; + +- if (predicate.test(serverplayer1)) { +- return Lists.newArrayList(new ServerPlayer[]{serverplayer1}); ++ if (predicate.test(entityplayer1)) { ++ return Lists.newArrayList(new ServerPlayer[]{entityplayer1}); + } + } + +@@ -227,16 +225,16 @@ + Object object; + + if (this.isWorldLimited()) { +- object = commandsourcestack.getLevel().getPlayers(predicate, i); ++ object = source.getLevel().getPlayers(predicate, i); + } else { + object = Lists.newArrayList(); +- Iterator iterator = commandsourcestack.getServer().getPlayerList().getPlayers().iterator(); ++ Iterator iterator = source.getServer().getPlayerList().getPlayers().iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer2 = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer2 = (ServerPlayer) iterator.next(); + +- if (predicate.test(serverplayer2)) { +- ((List) object).add(serverplayer2); ++ if (predicate.test(entityplayer2)) { ++ ((List) object).add(entityplayer2); + if (((List) object).size() >= i) { + return (List) object; + } +@@ -244,40 +242,40 @@ + } + } + +- return this.sortAndLimit(vec3, (List) object); ++ return this.sortAndLimit(vec3d, (List) object); + } + } + } + +- private Predicate getPredicate(Vec3 vec3) { ++ private Predicate getPredicate(Vec3 pos) { + Predicate predicate = this.predicate; + + if (this.aabb != null) { +- AABB aabb = this.aabb.move(vec3); ++ AABB axisalignedbb = this.aabb.move(pos); + + predicate = predicate.and((entity) -> { +- return aabb.intersects(entity.getBoundingBox()); ++ return axisalignedbb.intersects(entity.getBoundingBox()); + }); + } + + if (!this.range.isAny()) { + predicate = predicate.and((entity) -> { +- return this.range.matchesSqr(entity.distanceToSqr(vec3)); ++ return this.range.matchesSqr(entity.distanceToSqr(pos)); + }); + } + + return predicate; + } + +- private List sortAndLimit(Vec3 vec3, List list) { +- if (list.size() > 1) { +- this.order.accept(vec3, list); ++ private List sortAndLimit(Vec3 pos, List entities) { ++ if (entities.size() > 1) { ++ this.order.accept(pos, entities); + } + +- return list.subList(0, Math.min(this.maxResults, list.size())); ++ return entities.subList(0, Math.min(this.maxResults, entities.size())); + } + +- public static Component joinNames(List list) { +- return ComponentUtils.formatList(list, Entity::getDisplayName); ++ public static Component joinNames(List names) { ++ return ComponentUtils.formatList(names, Entity::getDisplayName); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/commands/arguments/selector/EntitySelectorParser.java.patch b/patch-remap/mache-spigotflower/net/minecraft/commands/arguments/selector/EntitySelectorParser.java.patch new file mode 100644 index 0000000000..588de4c68a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/commands/arguments/selector/EntitySelectorParser.java.patch @@ -0,0 +1,503 @@ +--- a/net/minecraft/commands/arguments/selector/EntitySelectorParser.java ++++ b/net/minecraft/commands/arguments/selector/EntitySelectorParser.java +@@ -53,17 +53,17 @@ + public static final DynamicCommandExceptionType ERROR_EXPECTED_OPTION_VALUE = new DynamicCommandExceptionType((object) -> { + return Component.translatableEscape("argument.entity.options.valueless", object); + }); +- public static final BiConsumer> ORDER_NEAREST = (vec3, list) -> { ++ public static final BiConsumer> ORDER_NEAREST = (vec3d, list) -> { + list.sort((entity, entity1) -> { +- return Doubles.compare(entity.distanceToSqr(vec3), entity1.distanceToSqr(vec3)); ++ return Doubles.compare(entity.distanceToSqr(vec3d), entity1.distanceToSqr(vec3d)); + }); + }; +- public static final BiConsumer> ORDER_FURTHEST = (vec3, list) -> { ++ public static final BiConsumer> ORDER_FURTHEST = (vec3d, list) -> { + list.sort((entity, entity1) -> { +- return Doubles.compare(entity1.distanceToSqr(vec3), entity.distanceToSqr(vec3)); ++ return Doubles.compare(entity1.distanceToSqr(vec3d), entity.distanceToSqr(vec3d)); + }); + }; +- public static final BiConsumer> ORDER_RANDOM = (vec3, list) -> { ++ public static final BiConsumer> ORDER_RANDOM = (vec3d, list) -> { + Collections.shuffle(list); + }; + public static final BiFunction, CompletableFuture> SUGGEST_NOTHING = (suggestionsbuilder, consumer) -> { +@@ -114,11 +114,11 @@ + private boolean hasAdvancements; + private boolean usesSelectors; + +- public EntitySelectorParser(StringReader stringreader) { +- this(stringreader, true); ++ public EntitySelectorParser(StringReader reader) { ++ this(reader, true); + } + +- public EntitySelectorParser(StringReader stringreader, boolean flag) { ++ public EntitySelectorParser(StringReader reader, boolean allowSelectors) { + this.distance = MinMaxBounds.Doubles.ANY; + this.level = MinMaxBounds.Ints.ANY; + this.rotX = WrappedMinMaxBounds.ANY; +@@ -128,50 +128,50 @@ + }; + this.order = EntitySelector.ORDER_ARBITRARY; + this.suggestions = EntitySelectorParser.SUGGEST_NOTHING; +- this.reader = stringreader; +- this.allowSelectors = flag; ++ this.reader = reader; ++ this.allowSelectors = allowSelectors; + } + + public EntitySelector getSelector() { +- AABB aabb; ++ AABB axisalignedbb; + + if (this.deltaX == null && this.deltaY == null && this.deltaZ == null) { + if (this.distance.max().isPresent()) { + double d0 = (Double) this.distance.max().get(); + +- aabb = new AABB(-d0, -d0, -d0, d0 + 1.0D, d0 + 1.0D, d0 + 1.0D); ++ axisalignedbb = new AABB(-d0, -d0, -d0, d0 + 1.0D, d0 + 1.0D, d0 + 1.0D); + } else { +- aabb = null; ++ axisalignedbb = null; + } + } else { +- aabb = this.createAabb(this.deltaX == null ? 0.0D : this.deltaX, this.deltaY == null ? 0.0D : this.deltaY, this.deltaZ == null ? 0.0D : this.deltaZ); ++ axisalignedbb = this.createAabb(this.deltaX == null ? 0.0D : this.deltaX, this.deltaY == null ? 0.0D : this.deltaY, this.deltaZ == null ? 0.0D : this.deltaZ); + } + +- Function function; ++ Function function; // CraftBukkit - decompile error + + if (this.x == null && this.y == null && this.z == null) { +- function = (vec3) -> { +- return vec3; ++ function = (vec3d) -> { ++ return vec3d; + }; + } else { +- function = (vec3) -> { +- return new Vec3(this.x == null ? vec3.x : this.x, this.y == null ? vec3.y : this.y, this.z == null ? vec3.z : this.z); ++ function = (vec3d) -> { ++ return new Vec3(this.x == null ? vec3d.x : this.x, this.y == null ? vec3d.y : this.y, this.z == null ? vec3d.z : this.z); + }; + } + +- return new EntitySelector(this.maxResults, this.includesEntities, this.worldLimited, this.predicate, this.distance, function, aabb, this.order, this.currentEntity, this.playerName, this.entityUUID, this.type, this.usesSelectors); ++ return new EntitySelector(this.maxResults, this.includesEntities, this.worldLimited, this.predicate, this.distance, function, axisalignedbb, this.order, this.currentEntity, this.playerName, this.entityUUID, this.type, this.usesSelectors); + } + +- private AABB createAabb(double d0, double d1, double d2) { +- boolean flag = d0 < 0.0D; ++ private AABB createAabb(double sizeX, double d1, double sizeY) { ++ boolean flag = sizeX < 0.0D; + boolean flag1 = d1 < 0.0D; +- boolean flag2 = d2 < 0.0D; +- double d3 = flag ? d0 : 0.0D; ++ boolean flag2 = sizeY < 0.0D; ++ double d3 = flag ? sizeX : 0.0D; + double d4 = flag1 ? d1 : 0.0D; +- double d5 = flag2 ? d2 : 0.0D; +- double d6 = (flag ? 0.0D : d0) + 1.0D; ++ double d5 = flag2 ? sizeY : 0.0D; ++ double d6 = (flag ? 0.0D : sizeX) + 1.0D; + double d7 = (flag1 ? 0.0D : d1) + 1.0D; +- double d8 = (flag2 ? 0.0D : d2) + 1.0D; ++ double d8 = (flag2 ? 0.0D : sizeY) + 1.0D; + + return new AABB(d3, d4, d5, d6, d7, d8); + } +@@ -193,19 +193,21 @@ + + } + +- private Predicate createRotationPredicate(WrappedMinMaxBounds wrappedminmaxbounds, ToDoubleFunction todoublefunction) { +- double d0 = (double) Mth.wrapDegrees(wrappedminmaxbounds.min() == null ? 0.0F : wrappedminmaxbounds.min()); +- double d1 = (double) Mth.wrapDegrees(wrappedminmaxbounds.max() == null ? 359.0F : wrappedminmaxbounds.max()); ++ private Predicate createRotationPredicate(WrappedMinMaxBounds angleBounds, ToDoubleFunction angleFunction) { ++ double d0 = (double) Mth.wrapDegrees(angleBounds.min() == null ? 0.0F : angleBounds.min()); ++ double d1 = (double) Mth.wrapDegrees(angleBounds.max() == null ? 359.0F : angleBounds.max()); + + return (entity) -> { +- double d2 = Mth.wrapDegrees(todoublefunction.applyAsDouble(entity)); ++ double d2 = Mth.wrapDegrees(angleFunction.applyAsDouble(entity)); + + return d0 > d1 ? d2 >= d0 || d2 <= d1 : d2 >= d0 && d2 <= d1; + }; + } + +- protected void parseSelector() throws CommandSyntaxException { +- this.usesSelectors = true; ++ // CraftBukkit start ++ protected void parseSelector(boolean overridePermissions) throws CommandSyntaxException { ++ this.usesSelectors = !overridePermissions; ++ // CraftBukkit end + this.suggestions = this::suggestSelector; + if (!this.reader.canRead()) { + throw EntitySelectorParser.ERROR_MISSING_SELECTOR_TYPE.createWithContext(this.reader); +@@ -287,7 +289,7 @@ + this.reader.skipWhitespace(); + int i = this.reader.getCursor(); + String s = this.reader.readString(); +- EntitySelectorOptions.Modifier entityselectoroptions_modifier = EntitySelectorOptions.get(this, s, i); ++ EntitySelectorOptions.Modifier playerselector_a = EntitySelectorOptions.get(this, s, i); + + this.reader.skipWhitespace(); + if (!this.reader.canRead() || this.reader.peek() != '=') { +@@ -298,7 +300,7 @@ + this.reader.skip(); + this.reader.skipWhitespace(); + this.suggestions = EntitySelectorParser.SUGGEST_NOTHING; +- entityselectoroptions_modifier.handle(this); ++ playerselector_a.handle(this); + this.reader.skipWhitespace(); + this.suggestions = this::suggestOptionsNextOrClose; + if (!this.reader.canRead()) { +@@ -364,32 +366,32 @@ + return this.distance; + } + +- public void setDistance(MinMaxBounds.Doubles minmaxbounds_doubles) { +- this.distance = minmaxbounds_doubles; ++ public void setDistance(MinMaxBounds.Doubles distance) { ++ this.distance = distance; + } + + public MinMaxBounds.Ints getLevel() { + return this.level; + } + +- public void setLevel(MinMaxBounds.Ints minmaxbounds_ints) { +- this.level = minmaxbounds_ints; ++ public void setLevel(MinMaxBounds.Ints level) { ++ this.level = level; + } + + public WrappedMinMaxBounds getRotX() { + return this.rotX; + } + +- public void setRotX(WrappedMinMaxBounds wrappedminmaxbounds) { +- this.rotX = wrappedminmaxbounds; ++ public void setRotX(WrappedMinMaxBounds rotX) { ++ this.rotX = rotX; + } + + public WrappedMinMaxBounds getRotY() { + return this.rotY; + } + +- public void setRotY(WrappedMinMaxBounds wrappedminmaxbounds) { +- this.rotY = wrappedminmaxbounds; ++ public void setRotY(WrappedMinMaxBounds rotY) { ++ this.rotY = rotY; + } + + @Nullable +@@ -407,28 +409,28 @@ + return this.z; + } + +- public void setX(double d0) { +- this.x = d0; ++ public void setX(double x) { ++ this.x = x; + } + +- public void setY(double d0) { +- this.y = d0; ++ public void setY(double y) { ++ this.y = y; + } + +- public void setZ(double d0) { +- this.z = d0; ++ public void setZ(double z) { ++ this.z = z; + } + +- public void setDeltaX(double d0) { +- this.deltaX = d0; ++ public void setDeltaX(double deltaX) { ++ this.deltaX = deltaX; + } + +- public void setDeltaY(double d0) { +- this.deltaY = d0; ++ public void setDeltaY(double deltaY) { ++ this.deltaY = deltaY; + } + +- public void setDeltaZ(double d0) { +- this.deltaZ = d0; ++ public void setDeltaZ(double deltaZ) { ++ this.deltaZ = deltaZ; + } + + @Nullable +@@ -446,23 +448,29 @@ + return this.deltaZ; + } + +- public void setMaxResults(int i) { +- this.maxResults = i; ++ public void setMaxResults(int maxResults) { ++ this.maxResults = maxResults; + } + +- public void setIncludesEntities(boolean flag) { +- this.includesEntities = flag; ++ public void setIncludesEntities(boolean includesEntities) { ++ this.includesEntities = includesEntities; + } + + public BiConsumer> getOrder() { + return this.order; + } + +- public void setOrder(BiConsumer> biconsumer) { +- this.order = biconsumer; ++ public void setOrder(BiConsumer> order) { ++ this.order = order; + } + + public EntitySelector parse() throws CommandSyntaxException { ++ // CraftBukkit start ++ return parse(false); ++ } ++ ++ public EntitySelector parse(boolean overridePermissions) throws CommandSyntaxException { ++ // CraftBukkit end + this.startPosition = this.reader.getCursor(); + this.suggestions = this::suggestNameOrSelector; + if (this.reader.canRead() && this.reader.peek() == '@') { +@@ -471,7 +479,7 @@ + } + + this.reader.skip(); +- this.parseSelector(); ++ this.parseSelector(overridePermissions); // CraftBukkit + } else { + this.parseNameOrUUID(); + } +@@ -480,143 +488,143 @@ + return this.getSelector(); + } + +- private static void fillSelectorSuggestions(SuggestionsBuilder suggestionsbuilder) { +- suggestionsbuilder.suggest("@p", Component.translatable("argument.entity.selector.nearestPlayer")); +- suggestionsbuilder.suggest("@a", Component.translatable("argument.entity.selector.allPlayers")); +- suggestionsbuilder.suggest("@r", Component.translatable("argument.entity.selector.randomPlayer")); +- suggestionsbuilder.suggest("@s", Component.translatable("argument.entity.selector.self")); +- suggestionsbuilder.suggest("@e", Component.translatable("argument.entity.selector.allEntities")); ++ private static void fillSelectorSuggestions(SuggestionsBuilder builder) { ++ builder.suggest("@p", Component.translatable("argument.entity.selector.nearestPlayer")); ++ builder.suggest("@a", Component.translatable("argument.entity.selector.allPlayers")); ++ builder.suggest("@r", Component.translatable("argument.entity.selector.randomPlayer")); ++ builder.suggest("@s", Component.translatable("argument.entity.selector.self")); ++ builder.suggest("@e", Component.translatable("argument.entity.selector.allEntities")); + } + +- private CompletableFuture suggestNameOrSelector(SuggestionsBuilder suggestionsbuilder, Consumer consumer) { +- consumer.accept(suggestionsbuilder); ++ private CompletableFuture suggestNameOrSelector(SuggestionsBuilder builder, Consumer consumer) { ++ consumer.accept(builder); + if (this.allowSelectors) { +- fillSelectorSuggestions(suggestionsbuilder); ++ fillSelectorSuggestions(builder); + } + +- return suggestionsbuilder.buildFuture(); ++ return builder.buildFuture(); + } + +- private CompletableFuture suggestName(SuggestionsBuilder suggestionsbuilder, Consumer consumer) { +- SuggestionsBuilder suggestionsbuilder1 = suggestionsbuilder.createOffset(this.startPosition); ++ private CompletableFuture suggestName(SuggestionsBuilder builder, Consumer consumer) { ++ SuggestionsBuilder suggestionsbuilder1 = builder.createOffset(this.startPosition); + + consumer.accept(suggestionsbuilder1); +- return suggestionsbuilder.add(suggestionsbuilder1).buildFuture(); ++ return builder.add(suggestionsbuilder1).buildFuture(); + } + +- private CompletableFuture suggestSelector(SuggestionsBuilder suggestionsbuilder, Consumer consumer) { +- SuggestionsBuilder suggestionsbuilder1 = suggestionsbuilder.createOffset(suggestionsbuilder.getStart() - 1); ++ private CompletableFuture suggestSelector(SuggestionsBuilder builder, Consumer consumer) { ++ SuggestionsBuilder suggestionsbuilder1 = builder.createOffset(builder.getStart() - 1); + + fillSelectorSuggestions(suggestionsbuilder1); +- suggestionsbuilder.add(suggestionsbuilder1); +- return suggestionsbuilder.buildFuture(); ++ builder.add(suggestionsbuilder1); ++ return builder.buildFuture(); + } + +- private CompletableFuture suggestOpenOptions(SuggestionsBuilder suggestionsbuilder, Consumer consumer) { +- suggestionsbuilder.suggest(String.valueOf('[')); +- return suggestionsbuilder.buildFuture(); ++ private CompletableFuture suggestOpenOptions(SuggestionsBuilder builder, Consumer consumer) { ++ builder.suggest(String.valueOf('[')); ++ return builder.buildFuture(); + } + +- private CompletableFuture suggestOptionsKeyOrClose(SuggestionsBuilder suggestionsbuilder, Consumer consumer) { +- suggestionsbuilder.suggest(String.valueOf(']')); +- EntitySelectorOptions.suggestNames(this, suggestionsbuilder); +- return suggestionsbuilder.buildFuture(); ++ private CompletableFuture suggestOptionsKeyOrClose(SuggestionsBuilder builder, Consumer consumer) { ++ builder.suggest(String.valueOf(']')); ++ EntitySelectorOptions.suggestNames(this, builder); ++ return builder.buildFuture(); + } + +- private CompletableFuture suggestOptionsKey(SuggestionsBuilder suggestionsbuilder, Consumer consumer) { +- EntitySelectorOptions.suggestNames(this, suggestionsbuilder); +- return suggestionsbuilder.buildFuture(); ++ private CompletableFuture suggestOptionsKey(SuggestionsBuilder builder, Consumer consumer) { ++ EntitySelectorOptions.suggestNames(this, builder); ++ return builder.buildFuture(); + } + +- private CompletableFuture suggestOptionsNextOrClose(SuggestionsBuilder suggestionsbuilder, Consumer consumer) { +- suggestionsbuilder.suggest(String.valueOf(',')); +- suggestionsbuilder.suggest(String.valueOf(']')); +- return suggestionsbuilder.buildFuture(); ++ private CompletableFuture suggestOptionsNextOrClose(SuggestionsBuilder builder, Consumer consumer) { ++ builder.suggest(String.valueOf(',')); ++ builder.suggest(String.valueOf(']')); ++ return builder.buildFuture(); + } + +- private CompletableFuture suggestEquals(SuggestionsBuilder suggestionsbuilder, Consumer consumer) { +- suggestionsbuilder.suggest(String.valueOf('=')); +- return suggestionsbuilder.buildFuture(); ++ private CompletableFuture suggestEquals(SuggestionsBuilder builder, Consumer consumer) { ++ builder.suggest(String.valueOf('=')); ++ return builder.buildFuture(); + } + + public boolean isCurrentEntity() { + return this.currentEntity; + } + +- public void setSuggestions(BiFunction, CompletableFuture> bifunction) { +- this.suggestions = bifunction; ++ public void setSuggestions(BiFunction, CompletableFuture> suggestionHandler) { ++ this.suggestions = suggestionHandler; + } + +- public CompletableFuture fillSuggestions(SuggestionsBuilder suggestionsbuilder, Consumer consumer) { +- return (CompletableFuture) this.suggestions.apply(suggestionsbuilder.createOffset(this.reader.getCursor()), consumer); ++ public CompletableFuture fillSuggestions(SuggestionsBuilder builder, Consumer consumer) { ++ return (CompletableFuture) this.suggestions.apply(builder.createOffset(this.reader.getCursor()), consumer); + } + + public boolean hasNameEquals() { + return this.hasNameEquals; + } + +- public void setHasNameEquals(boolean flag) { +- this.hasNameEquals = flag; ++ public void setHasNameEquals(boolean hasNameEquals) { ++ this.hasNameEquals = hasNameEquals; + } + + public boolean hasNameNotEquals() { + return this.hasNameNotEquals; + } + +- public void setHasNameNotEquals(boolean flag) { +- this.hasNameNotEquals = flag; ++ public void setHasNameNotEquals(boolean hasNameNotEquals) { ++ this.hasNameNotEquals = hasNameNotEquals; + } + + public boolean isLimited() { + return this.isLimited; + } + +- public void setLimited(boolean flag) { +- this.isLimited = flag; ++ public void setLimited(boolean isLimited) { ++ this.isLimited = isLimited; + } + + public boolean isSorted() { + return this.isSorted; + } + +- public void setSorted(boolean flag) { +- this.isSorted = flag; ++ public void setSorted(boolean isSorted) { ++ this.isSorted = isSorted; + } + + public boolean hasGamemodeEquals() { + return this.hasGamemodeEquals; + } + +- public void setHasGamemodeEquals(boolean flag) { +- this.hasGamemodeEquals = flag; ++ public void setHasGamemodeEquals(boolean hasGamemodeEquals) { ++ this.hasGamemodeEquals = hasGamemodeEquals; + } + + public boolean hasGamemodeNotEquals() { + return this.hasGamemodeNotEquals; + } + +- public void setHasGamemodeNotEquals(boolean flag) { +- this.hasGamemodeNotEquals = flag; ++ public void setHasGamemodeNotEquals(boolean hasGamemodeNotEquals) { ++ this.hasGamemodeNotEquals = hasGamemodeNotEquals; + } + + public boolean hasTeamEquals() { + return this.hasTeamEquals; + } + +- public void setHasTeamEquals(boolean flag) { +- this.hasTeamEquals = flag; ++ public void setHasTeamEquals(boolean hasTeamEquals) { ++ this.hasTeamEquals = hasTeamEquals; + } + + public boolean hasTeamNotEquals() { + return this.hasTeamNotEquals; + } + +- public void setHasTeamNotEquals(boolean flag) { +- this.hasTeamNotEquals = flag; ++ public void setHasTeamNotEquals(boolean hasTeamNotEquals) { ++ this.hasTeamNotEquals = hasTeamNotEquals; + } + +- public void limitToType(EntityType entitytype) { +- this.type = entitytype; ++ public void limitToType(EntityType type) { ++ this.type = type; + } + + public void setTypeLimitedInversely() { +@@ -635,15 +643,15 @@ + return this.hasScores; + } + +- public void setHasScores(boolean flag) { +- this.hasScores = flag; ++ public void setHasScores(boolean hasScores) { ++ this.hasScores = hasScores; + } + + public boolean hasAdvancements() { + return this.hasAdvancements; + } + +- public void setHasAdvancements(boolean flag) { +- this.hasAdvancements = flag; ++ public void setHasAdvancements(boolean hasAdvancements) { ++ this.hasAdvancements = hasAdvancements; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/core/cauldron/CauldronInteraction.java.patch b/patch-remap/mache-spigotflower/net/minecraft/core/cauldron/CauldronInteraction.java.patch new file mode 100644 index 0000000000..3ce6880c7b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/core/cauldron/CauldronInteraction.java.patch @@ -0,0 +1,414 @@ +--- a/net/minecraft/core/cauldron/CauldronInteraction.java ++++ b/net/minecraft/core/cauldron/CauldronInteraction.java +@@ -13,7 +13,7 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; + import net.minecraft.util.ExtraCodecs; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; +@@ -30,94 +30,117 @@ + import net.minecraft.world.level.block.LayeredCauldronBlock; + import net.minecraft.world.level.block.ShulkerBoxBlock; + import net.minecraft.world.level.block.entity.BannerBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.event.block.CauldronLevelChangeEvent; ++// CraftBukkit end ++ + public interface CauldronInteraction { + +- Map INTERACTIONS = new Object2ObjectArrayMap(); +- Codec CODEC; +- CauldronInteraction.InteractionMap EMPTY; +- CauldronInteraction.InteractionMap WATER; +- CauldronInteraction.InteractionMap LAVA; +- CauldronInteraction.InteractionMap POWDER_SNOW; ++ Map INTERACTIONS = new Object2ObjectArrayMap(); ++ // CraftBukkit start - decompile error ++ /* ++ Codec CODEC; ++ CauldronInteraction.a EMPTY; ++ CauldronInteraction.a WATER; ++ CauldronInteraction.a LAVA; ++ CauldronInteraction.a POWDER_SNOW; + CauldronInteraction FILL_WATER; + CauldronInteraction FILL_LAVA; + CauldronInteraction FILL_POWDER_SNOW; + CauldronInteraction SHULKER_BOX; + CauldronInteraction BANNER; + CauldronInteraction DYED_ITEM; ++ */ ++ // CraftBukkit end + +- static CauldronInteraction.InteractionMap newInteractionMap(String s) { ++ static CauldronInteraction.a newInteractionMap(String s) { + Object2ObjectOpenHashMap object2objectopenhashmap = new Object2ObjectOpenHashMap(); + +- object2objectopenhashmap.defaultReturnValue((blockstate, level, blockpos, player, interactionhand, itemstack) -> { ++ object2objectopenhashmap.defaultReturnValue((iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { + return InteractionResult.PASS; + }); +- CauldronInteraction.InteractionMap cauldroninteraction_interactionmap = new CauldronInteraction.InteractionMap(s, object2objectopenhashmap); ++ CauldronInteraction.a cauldroninteraction_a = new CauldronInteraction.a(s, object2objectopenhashmap); + +- CauldronInteraction.INTERACTIONS.put(s, cauldroninteraction_interactionmap); +- return cauldroninteraction_interactionmap; ++ CauldronInteraction.INTERACTIONS.put(s, cauldroninteraction_a); ++ return cauldroninteraction_a; + } + +- InteractionResult interact(BlockState blockState, Level level, BlockPos blockPos, Player player, InteractionHand hand, ItemStack stack); ++ InteractionResult interact(IBlockData blockState, Level level, BlockPos blockPos, Player player, EnumHand hand, ItemStack stack); + + static void bootStrap() { + Map map = CauldronInteraction.EMPTY.map(); + + addDefaultInteractions(map); +- map.put(Items.POTION, (blockstate, level, blockpos, player, interactionhand, itemstack) -> { ++ map.put(Items.POTION, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { + if (PotionUtils.getPotion(itemstack) != Potions.WATER) { + return InteractionResult.PASS; + } else { +- if (!level.isClientSide) { ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.changeLevel(iblockdata, world, blockposition, Blocks.WATER_CAULDRON.defaultBlockState(), entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_EMPTY)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + Item item = itemstack.getItem(); + +- player.setItemInHand(interactionhand, ItemUtils.createFilledResult(itemstack, player, new ItemStack(Items.GLASS_BOTTLE))); +- player.awardStat(Stats.USE_CAULDRON); +- player.awardStat(Stats.ITEM_USED.get(item)); +- level.setBlockAndUpdate(blockpos, Blocks.WATER_CAULDRON.defaultBlockState()); +- level.playSound((Player) null, blockpos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockpos); ++ entityhuman.setItemInHand(enumhand, ItemUtils.createFilledResult(itemstack, entityhuman, new ItemStack(Items.GLASS_BOTTLE))); ++ entityhuman.awardStat(Stats.USE_CAULDRON); ++ entityhuman.awardStat(Stats.ITEM_USED.get(item)); ++ // world.setBlockAndUpdate(blockposition, Blocks.WATER_CAULDRON.defaultBlockState()); // CraftBukkit ++ world.playSound((Player) null, blockposition, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockposition); + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } + }); + Map map1 = CauldronInteraction.WATER.map(); + + addDefaultInteractions(map1); +- map1.put(Items.BUCKET, (blockstate, level, blockpos, player, interactionhand, itemstack) -> { +- return fillBucket(blockstate, level, blockpos, player, interactionhand, itemstack, new ItemStack(Items.WATER_BUCKET), (blockstate1) -> { +- return (Integer) blockstate1.getValue(LayeredCauldronBlock.LEVEL) == 3; ++ map1.put(Items.BUCKET, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ return fillBucket(iblockdata, world, blockposition, entityhuman, enumhand, itemstack, new ItemStack(Items.WATER_BUCKET), (iblockdata1) -> { ++ return (Integer) iblockdata1.getValue(LayeredCauldronBlock.LEVEL) == 3; + }, SoundEvents.BUCKET_FILL); + }); +- map1.put(Items.GLASS_BOTTLE, (blockstate, level, blockpos, player, interactionhand, itemstack) -> { +- if (!level.isClientSide) { ++ map1.put(Items.GLASS_BOTTLE, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_FILL)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + Item item = itemstack.getItem(); + +- player.setItemInHand(interactionhand, ItemUtils.createFilledResult(itemstack, player, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER))); +- player.awardStat(Stats.USE_CAULDRON); +- player.awardStat(Stats.ITEM_USED.get(item)); +- LayeredCauldronBlock.lowerFillLevel(blockstate, level, blockpos); +- level.playSound((Player) null, blockpos, SoundEvents.BOTTLE_FILL, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockpos); ++ entityhuman.setItemInHand(enumhand, ItemUtils.createFilledResult(itemstack, entityhuman, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER))); ++ entityhuman.awardStat(Stats.USE_CAULDRON); ++ entityhuman.awardStat(Stats.ITEM_USED.get(item)); ++ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit ++ world.playSound((Player) null, blockposition, SoundEvents.BOTTLE_FILL, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockposition); + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + }); +- map1.put(Items.POTION, (blockstate, level, blockpos, player, interactionhand, itemstack) -> { +- if ((Integer) blockstate.getValue(LayeredCauldronBlock.LEVEL) != 3 && PotionUtils.getPotion(itemstack) == Potions.WATER) { +- if (!level.isClientSide) { +- player.setItemInHand(interactionhand, ItemUtils.createFilledResult(itemstack, player, new ItemStack(Items.GLASS_BOTTLE))); +- player.awardStat(Stats.USE_CAULDRON); +- player.awardStat(Stats.ITEM_USED.get(itemstack.getItem())); +- level.setBlockAndUpdate(blockpos, (BlockState) blockstate.cycle(LayeredCauldronBlock.LEVEL)); +- level.playSound((Player) null, blockpos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockpos); ++ map1.put(Items.POTION, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ if ((Integer) iblockdata.getValue(LayeredCauldronBlock.LEVEL) != 3 && PotionUtils.getPotion(itemstack) == Potions.WATER) { ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.changeLevel(iblockdata, world, blockposition, iblockdata.cycle(LayeredCauldronBlock.LEVEL), entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_EMPTY)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ entityhuman.setItemInHand(enumhand, ItemUtils.createFilledResult(itemstack, entityhuman, new ItemStack(Items.GLASS_BOTTLE))); ++ entityhuman.awardStat(Stats.USE_CAULDRON); ++ entityhuman.awardStat(Stats.ITEM_USED.get(itemstack.getItem())); ++ // world.setBlockAndUpdate(blockposition, (IBlockData) iblockdata.cycle(LayeredCauldronBlock.LEVEL)); // CraftBukkit ++ world.playSound((Player) null, blockposition, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockposition); + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } else { + return InteractionResult.PASS; + } +@@ -161,153 +184,176 @@ + map1.put(Items.YELLOW_SHULKER_BOX, CauldronInteraction.SHULKER_BOX); + Map map2 = CauldronInteraction.LAVA.map(); + +- map2.put(Items.BUCKET, (blockstate, level, blockpos, player, interactionhand, itemstack) -> { +- return fillBucket(blockstate, level, blockpos, player, interactionhand, itemstack, new ItemStack(Items.LAVA_BUCKET), (blockstate1) -> { ++ map2.put(Items.BUCKET, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ return fillBucket(iblockdata, world, blockposition, entityhuman, enumhand, itemstack, new ItemStack(Items.LAVA_BUCKET), (iblockdata1) -> { + return true; + }, SoundEvents.BUCKET_FILL_LAVA); + }); + addDefaultInteractions(map2); + Map map3 = CauldronInteraction.POWDER_SNOW.map(); + +- map3.put(Items.BUCKET, (blockstate, level, blockpos, player, interactionhand, itemstack) -> { +- return fillBucket(blockstate, level, blockpos, player, interactionhand, itemstack, new ItemStack(Items.POWDER_SNOW_BUCKET), (blockstate1) -> { +- return (Integer) blockstate1.getValue(LayeredCauldronBlock.LEVEL) == 3; ++ map3.put(Items.BUCKET, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ return fillBucket(iblockdata, world, blockposition, entityhuman, enumhand, itemstack, new ItemStack(Items.POWDER_SNOW_BUCKET), (iblockdata1) -> { ++ return (Integer) iblockdata1.getValue(LayeredCauldronBlock.LEVEL) == 3; + }, SoundEvents.BUCKET_FILL_POWDER_SNOW); + }); + addDefaultInteractions(map3); + } + +- static void addDefaultInteractions(Map map) { +- map.put(Items.LAVA_BUCKET, CauldronInteraction.FILL_LAVA); +- map.put(Items.WATER_BUCKET, CauldronInteraction.FILL_WATER); +- map.put(Items.POWDER_SNOW_BUCKET, CauldronInteraction.FILL_POWDER_SNOW); ++ static void addDefaultInteractions(Map interactionsMap) { ++ interactionsMap.put(Items.LAVA_BUCKET, CauldronInteraction.FILL_LAVA); ++ interactionsMap.put(Items.WATER_BUCKET, CauldronInteraction.FILL_WATER); ++ interactionsMap.put(Items.POWDER_SNOW_BUCKET, CauldronInteraction.FILL_POWDER_SNOW); + } + +- static InteractionResult fillBucket(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, ItemStack itemstack, ItemStack itemstack1, Predicate predicate, SoundEvent soundevent) { +- if (!predicate.test(blockstate)) { ++ static InteractionResult fillBucket(IBlockData blockState, Level level, BlockPos pos, Player player, EnumHand hand, ItemStack emptyStack, ItemStack filledStack, Predicate statePredicate, SoundEvent fillSound) { ++ if (!statePredicate.test(blockState)) { + return InteractionResult.PASS; + } else { + if (!level.isClientSide) { +- Item item = itemstack.getItem(); ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.changeLevel(blockState, level, pos, Blocks.CAULDRON.defaultBlockState(), player, CauldronLevelChangeEvent.ChangeReason.BUCKET_FILL)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ Item item = emptyStack.getItem(); + +- player.setItemInHand(interactionhand, ItemUtils.createFilledResult(itemstack, player, itemstack1)); ++ player.setItemInHand(hand, ItemUtils.createFilledResult(emptyStack, player, filledStack)); + player.awardStat(Stats.USE_CAULDRON); + player.awardStat(Stats.ITEM_USED.get(item)); +- level.setBlockAndUpdate(blockpos, Blocks.CAULDRON.defaultBlockState()); +- level.playSound((Player) null, blockpos, soundevent, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockpos); ++ // world.setBlockAndUpdate(blockposition, Blocks.CAULDRON.defaultBlockState()); // CraftBukkit ++ level.playSound((Player) null, pos, fillSound, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, pos); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + } + } + +- static InteractionResult emptyBucket(Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, ItemStack itemstack, BlockState blockstate, SoundEvent soundevent) { ++ static InteractionResult emptyBucket(Level level, BlockPos pos, Player player, EnumHand hand, ItemStack filledStack, IBlockData state, SoundEvent emptySound) { + if (!level.isClientSide) { +- Item item = itemstack.getItem(); ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.changeLevel(state, level, pos, state, player, CauldronLevelChangeEvent.ChangeReason.BUCKET_EMPTY)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ Item item = filledStack.getItem(); + +- player.setItemInHand(interactionhand, ItemUtils.createFilledResult(itemstack, player, new ItemStack(Items.BUCKET))); ++ player.setItemInHand(hand, ItemUtils.createFilledResult(filledStack, player, new ItemStack(Items.BUCKET))); + player.awardStat(Stats.FILL_CAULDRON); + player.awardStat(Stats.ITEM_USED.get(item)); +- level.setBlockAndUpdate(blockpos, blockstate); +- level.playSound((Player) null, blockpos, soundevent, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockpos); ++ // world.setBlockAndUpdate(blockposition, iblockdata); // CraftBukkit ++ level.playSound((Player) null, pos, emptySound, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.gameEvent((Entity) null, GameEvent.FLUID_PLACE, pos); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + } + +- static { +- Function function = CauldronInteraction.InteractionMap::name; +- Map map = CauldronInteraction.INTERACTIONS; +- +- Objects.requireNonNull(map); +- CODEC = ExtraCodecs.stringResolverCodec(function, map::get); +- EMPTY = newInteractionMap("empty"); +- WATER = newInteractionMap("water"); +- LAVA = newInteractionMap("lava"); +- POWDER_SNOW = newInteractionMap("powder_snow"); +- FILL_WATER = (blockstate, level, blockpos, player, interactionhand, itemstack) -> { +- return emptyBucket(level, blockpos, player, interactionhand, itemstack, (BlockState) Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY); ++ // CraftBukkit start - decompile errors ++ // static { ++ Codec CODEC = ExtraCodecs.stringResolverCodec(CauldronInteraction.a::name, CauldronInteraction.INTERACTIONS::get); ++ CauldronInteraction.a EMPTY = newInteractionMap("empty"); ++ CauldronInteraction.a WATER = newInteractionMap("water"); ++ CauldronInteraction.a LAVA = newInteractionMap("lava"); ++ CauldronInteraction.a POWDER_SNOW = newInteractionMap("powder_snow"); ++ CauldronInteraction FILL_WATER = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ return emptyBucket(world, blockposition, entityhuman, enumhand, itemstack, (IBlockData) Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY); + }; +- FILL_LAVA = (blockstate, level, blockpos, player, interactionhand, itemstack) -> { +- return emptyBucket(level, blockpos, player, interactionhand, itemstack, Blocks.LAVA_CAULDRON.defaultBlockState(), SoundEvents.BUCKET_EMPTY_LAVA); ++ CauldronInteraction FILL_LAVA = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ return emptyBucket(world, blockposition, entityhuman, enumhand, itemstack, Blocks.LAVA_CAULDRON.defaultBlockState(), SoundEvents.BUCKET_EMPTY_LAVA); + }; +- FILL_POWDER_SNOW = (blockstate, level, blockpos, player, interactionhand, itemstack) -> { +- return emptyBucket(level, blockpos, player, interactionhand, itemstack, (BlockState) Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY_POWDER_SNOW); ++ CauldronInteraction FILL_POWDER_SNOW = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ return emptyBucket(world, blockposition, entityhuman, enumhand, itemstack, (IBlockData) Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY_POWDER_SNOW); + }; +- SHULKER_BOX = (blockstate, level, blockpos, player, interactionhand, itemstack) -> { ++ CauldronInteraction SHULKER_BOX = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ // CraftBukkit end + Block block = Block.byItem(itemstack.getItem()); + + if (!(block instanceof ShulkerBoxBlock)) { + return InteractionResult.PASS; + } else { +- if (!level.isClientSide) { ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.SHULKER_WASH)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + ItemStack itemstack1 = new ItemStack(Blocks.SHULKER_BOX); + + if (itemstack.hasTag()) { + itemstack1.setTag(itemstack.getTag().copy()); + } + +- player.setItemInHand(interactionhand, itemstack1); +- player.awardStat(Stats.CLEAN_SHULKER_BOX); +- LayeredCauldronBlock.lowerFillLevel(blockstate, level, blockpos); ++ entityhuman.setItemInHand(enumhand, itemstack1); ++ entityhuman.awardStat(Stats.CLEAN_SHULKER_BOX); ++ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } + }; +- BANNER = (blockstate, level, blockpos, player, interactionhand, itemstack) -> { ++ CauldronInteraction BANNER = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { // CraftBukkit - decompile error + if (BannerBlockEntity.getPatternCount(itemstack) <= 0) { + return InteractionResult.PASS; + } else { +- if (!level.isClientSide) { ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.BANNER_WASH)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + ItemStack itemstack1 = itemstack.copyWithCount(1); + + BannerBlockEntity.removeLastPattern(itemstack1); +- if (!player.getAbilities().instabuild) { ++ if (!entityhuman.getAbilities().instabuild) { + itemstack.shrink(1); + } + + if (itemstack.isEmpty()) { +- player.setItemInHand(interactionhand, itemstack1); +- } else if (player.getInventory().add(itemstack1)) { +- player.inventoryMenu.sendAllDataToRemote(); ++ entityhuman.setItemInHand(enumhand, itemstack1); ++ } else if (entityhuman.getInventory().add(itemstack1)) { ++ entityhuman.inventoryMenu.sendAllDataToRemote(); + } else { +- player.drop(itemstack1, false); ++ entityhuman.drop(itemstack1, false); + } + +- player.awardStat(Stats.CLEAN_BANNER); +- LayeredCauldronBlock.lowerFillLevel(blockstate, level, blockpos); ++ entityhuman.awardStat(Stats.CLEAN_BANNER); ++ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } + }; +- DYED_ITEM = (blockstate, level, blockpos, player, interactionhand, itemstack) -> { ++ CauldronInteraction DYED_ITEM = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { // CraftBukkit - decompile error + Item item = itemstack.getItem(); + + if (!(item instanceof DyeableLeatherItem)) { + return InteractionResult.PASS; + } else { +- DyeableLeatherItem dyeableleatheritem = (DyeableLeatherItem) item; ++ DyeableLeatherItem idyeable = (DyeableLeatherItem) item; + +- if (!dyeableleatheritem.hasCustomColor(itemstack)) { ++ if (!idyeable.hasCustomColor(itemstack)) { + return InteractionResult.PASS; + } else { +- if (!level.isClientSide) { +- dyeableleatheritem.clearColor(itemstack); +- player.awardStat(Stats.CLEAN_ARMOR); +- LayeredCauldronBlock.lowerFillLevel(blockstate, level, blockpos); ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.ARMOR_WASH)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ idyeable.clearColor(itemstack); ++ entityhuman.awardStat(Stats.CLEAN_ARMOR); ++ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } + } + }; +- } ++ // } // CraftBukkit - decompile error + +- public static record InteractionMap(String name, Map map) { ++ public static record a(String name, Map map) { + + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java.patch b/patch-remap/mache-spigotflower/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java.patch new file mode 100644 index 0000000000..b900cf8f30 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java.patch @@ -0,0 +1,89 @@ +--- a/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java ++++ b/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java +@@ -1,38 +1,71 @@ + package net.minecraft.core.dispenser; + + import net.minecraft.core.Direction; +-import net.minecraft.core.Position; ++import net.minecraft.core.IPosition; + import net.minecraft.server.level.ServerLevel; +-import net.minecraft.world.entity.projectile.Projectile; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.DispenserBlock; ++// CraftBukkit start ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.projectile.Projectile; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end + + public abstract class AbstractProjectileDispenseBehavior extends DefaultDispenseItemBehavior { + + public AbstractProjectileDispenseBehavior() {} + + @Override +- @Override +- public ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- ServerLevel serverlevel = blocksource.level(); +- Position position = DispenserBlock.getDispensePosition(blocksource); +- Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING); +- Projectile projectile = this.getProjectile(serverlevel, position, itemstack); ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ IPosition iposition = DispenserBlock.getDispensePosition(sourceblock); ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ Projectile iprojectile = this.getProjectile(worldserver, iposition, itemstack); + +- projectile.shoot((double) direction.getStepX(), (double) ((float) direction.getStepY() + 0.1F), (double) direction.getStepZ(), this.getPower(), this.getUncertainty()); +- serverlevel.addFreshEntity(projectile); +- itemstack.shrink(1); ++ // CraftBukkit start ++ // iprojectile.shoot((double) enumdirection.getStepX(), (double) ((float) enumdirection.getStepY() + 0.1F), (double) enumdirection.getStepZ(), this.getPower(), this.getUncertainty()); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) enumdirection.getStepX(), (double) ((float) enumdirection.getStepY() + 0.1F), (double) enumdirection.getStepZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ iprojectile.shoot(event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), this.getPower(), this.getUncertainty()); ++ ((Entity) iprojectile).projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(sourceblock.blockEntity()); ++ // CraftBukkit end ++ worldserver.addFreshEntity(iprojectile); ++ // itemstack.shrink(1); // CraftBukkit - Handled during event processing + return itemstack; + } + + @Override +- @Override +- protected void playSound(BlockSource blocksource) { +- blocksource.level().levelEvent(1002, blocksource.pos(), 0); ++ protected void playSound(SourceBlock sourceblock) { ++ sourceblock.level().levelEvent(1002, sourceblock.pos(), 0); + } + +- protected abstract Projectile getProjectile(Level level, Position position, ItemStack stack); ++ protected abstract Projectile getProjectile(Level level, IPosition position, ItemStack stack); + + protected float getUncertainty() { + return 6.0F; diff --git a/patch-remap/mache-spigotflower/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java.patch b/patch-remap/mache-spigotflower/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java.patch new file mode 100644 index 0000000000..55ea95de87 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java.patch @@ -0,0 +1,118 @@ +--- a/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java ++++ b/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java +@@ -12,6 +12,11 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.DispenserBlock; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end + + public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior { + +@@ -19,52 +24,78 @@ + private final Boat.Type type; + private final boolean isChestBoat; + +- public BoatDispenseItemBehavior(Boat.Type boat_type) { +- this(boat_type, false); ++ public BoatDispenseItemBehavior(Boat.Type type) { ++ this(type, false); + } + +- public BoatDispenseItemBehavior(Boat.Type boat_type, boolean flag) { ++ public BoatDispenseItemBehavior(Boat.Type type, boolean isChestBoat) { + this.defaultDispenseItemBehavior = new DefaultDispenseItemBehavior(); +- this.type = boat_type; +- this.isChestBoat = flag; ++ this.type = type; ++ this.isChestBoat = isChestBoat; + } + + @Override +- @Override +- public ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING); +- ServerLevel serverlevel = blocksource.level(); +- Vec3 vec3 = blocksource.center(); ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ ServerLevel worldserver = sourceblock.level(); ++ Vec3 vec3d = sourceblock.center(); + double d0 = 0.5625D + (double) EntityType.BOAT.getWidth() / 2.0D; +- double d1 = vec3.x() + (double) direction.getStepX() * d0; +- double d2 = vec3.y() + (double) ((float) direction.getStepY() * 1.125F); +- double d3 = vec3.z() + (double) direction.getStepZ() * d0; +- BlockPos blockpos = blocksource.pos().relative(direction); ++ double d1 = vec3d.x() + (double) enumdirection.getStepX() * d0; ++ double d2 = vec3d.y() + (double) ((float) enumdirection.getStepY() * 1.125F); ++ double d3 = vec3d.z() + (double) enumdirection.getStepZ() * d0; ++ BlockPos blockposition = sourceblock.pos().relative(enumdirection); + double d4; + +- if (serverlevel.getFluidState(blockpos).is(FluidTags.WATER)) { ++ if (worldserver.getFluidState(blockposition).is(FluidTags.WATER)) { + d4 = 1.0D; + } else { +- if (!serverlevel.getBlockState(blockpos).isAir() || !serverlevel.getFluidState(blockpos.below()).is(FluidTags.WATER)) { +- return this.defaultDispenseItemBehavior.dispense(blocksource, itemstack); ++ if (!worldserver.getBlockState(blockposition).isAir() || !worldserver.getFluidState(blockposition.below()).is(FluidTags.WATER)) { ++ return this.defaultDispenseItemBehavior.dispense(sourceblock, itemstack); + } + + d4 = 0.0D; + } + +- Object object = this.isChestBoat ? new ChestBoat(serverlevel, d1, d2 + d4, d3) : new Boat(serverlevel, d1, d2 + d4, d3); ++ // Object object = this.isChestBoat ? new ChestBoat(worldserver, d1, d2 + d4, d3) : new EntityBoat(worldserver, d1, d2 + d4, d3); ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + +- EntityType.createDefaultStackConfig(serverlevel, itemstack, (Player) null).accept(object); ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d1, d2 + d4, d3)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ Boat object = this.isChestBoat ? new ChestBoat(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ()) : new Boat(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ()); ++ // CraftBukkit end ++ ++ EntityType.createDefaultStackConfig(worldserver, itemstack, (Player) null).accept(object); + ((Boat) object).setVariant(this.type); +- ((Boat) object).setYRot(direction.toYRot()); +- serverlevel.addFreshEntity((Entity) object); +- itemstack.shrink(1); ++ ((Boat) object).setYRot(enumdirection.toYRot()); ++ if (!worldserver.addFreshEntity((Entity) object)) itemstack.grow(1); // CraftBukkit ++ // itemstack.shrink(1); // CraftBukkit - handled during event processing + return itemstack; + } + + @Override +- @Override +- protected void playSound(BlockSource blocksource) { +- blocksource.level().levelEvent(1000, blocksource.pos(), 0); ++ protected void playSound(SourceBlock sourceblock) { ++ sourceblock.level().levelEvent(1000, sourceblock.pos(), 0); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java.patch b/patch-remap/mache-spigotflower/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java.patch new file mode 100644 index 0000000000..d812ee6a01 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java.patch @@ -0,0 +1,148 @@ +--- a/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java ++++ b/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java +@@ -1,58 +1,122 @@ + package net.minecraft.core.dispenser; + + import net.minecraft.core.Direction; +-import net.minecraft.core.Position; ++import net.minecraft.core.IPosition; + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.DispenserBlock; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftVector; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end + + public class DefaultDispenseItemBehavior implements DispenseItemBehavior { + ++ // CraftBukkit start ++ private boolean dropper; ++ ++ public DefaultDispenseItemBehavior(boolean dropper) { ++ this.dropper = dropper; ++ } ++ // CraftBukkit end ++ + public DefaultDispenseItemBehavior() {} + + @Override +- @Override +- public final ItemStack dispense(BlockSource blocksource, ItemStack itemstack) { +- ItemStack itemstack1 = this.execute(blocksource, itemstack); ++ public final ItemStack dispense(SourceBlock sourceblock, ItemStack itemstack) { ++ ItemStack itemstack1 = this.execute(sourceblock, itemstack); + +- this.playSound(blocksource); +- this.playAnimation(blocksource, (Direction) blocksource.state().getValue(DispenserBlock.FACING)); ++ this.playSound(sourceblock); ++ this.playAnimation(sourceblock, (Direction) sourceblock.state().getValue(DispenserBlock.FACING)); + return itemstack1; + } + +- protected ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING); +- Position position = DispenserBlock.getDispensePosition(blocksource); ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ IPosition iposition = DispenserBlock.getDispensePosition(sourceblock); + ItemStack itemstack1 = itemstack.split(1); + +- spawnItem(blocksource.level(), itemstack1, 6, direction, position); ++ // CraftBukkit start ++ if (!spawnItem(sourceblock.level(), itemstack1, 6, enumdirection, sourceblock, dropper)) { ++ itemstack.grow(1); ++ } ++ // CraftBukkit end + return itemstack; + } + +- public static void spawnItem(Level level, ItemStack itemstack, int i, Direction direction, Position position) { +- double d0 = position.x(); +- double d1 = position.y(); +- double d2 = position.z(); ++ public static void spawnItem(Level level, ItemStack stack, int speed, Direction facing, IPosition position) { ++ // CraftBukkit start ++ ItemEntity entityitem = prepareItem(level, stack, speed, facing, position); ++ level.addFreshEntity(entityitem); ++ } + +- if (direction.getAxis() == Direction.Axis.Y) { ++ private static ItemEntity prepareItem(Level world, ItemStack itemstack, int i, Direction enumdirection, IPosition iposition) { ++ // CraftBukkit end ++ double d0 = iposition.x(); ++ double d1 = iposition.y(); ++ double d2 = iposition.z(); ++ ++ if (enumdirection.getAxis() == Direction.Axis.Y) { + d1 -= 0.125D; + } else { + d1 -= 0.15625D; + } + +- ItemEntity itementity = new ItemEntity(level, d0, d1, d2, itemstack); +- double d3 = level.random.nextDouble() * 0.1D + 0.2D; ++ ItemEntity entityitem = new ItemEntity(world, d0, d1, d2, itemstack); ++ double d3 = world.random.nextDouble() * 0.1D + 0.2D; + +- itementity.setDeltaMovement(level.random.triangle((double) direction.getStepX() * d3, 0.0172275D * (double) i), level.random.triangle(0.2D, 0.0172275D * (double) i), level.random.triangle((double) direction.getStepZ() * d3, 0.0172275D * (double) i)); +- level.addFreshEntity(itementity); ++ entityitem.setDeltaMovement(world.random.triangle((double) enumdirection.getStepX() * d3, 0.0172275D * (double) i), world.random.triangle(0.2D, 0.0172275D * (double) i), world.random.triangle((double) enumdirection.getStepZ() * d3, 0.0172275D * (double) i)); ++ // CraftBukkit start ++ return entityitem; + } + +- protected void playSound(BlockSource blocksource) { +- blocksource.level().levelEvent(1000, blocksource.pos(), 0); ++ // CraftBukkit - void -> boolean return, IPosition -> ISourceBlock last argument, dropper ++ public static boolean spawnItem(Level world, ItemStack itemstack, int i, Direction enumdirection, SourceBlock sourceblock, boolean dropper) { ++ if (itemstack.isEmpty()) return true; ++ IPosition iposition = DispenserBlock.getDispensePosition(sourceblock); ++ ItemEntity entityitem = prepareItem(world, itemstack, i, enumdirection, iposition); ++ ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), CraftVector.toBukkit(entityitem.getDeltaMovement())); ++ if (!DispenserBlock.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ entityitem.setItem(CraftItemStack.asNMSCopy(event.getItem())); ++ entityitem.setDeltaMovement(CraftVector.toNMS(event.getVelocity())); ++ ++ if (!dropper && !event.getItem().getType().equals(craftItem.getType())) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior.getClass() != DefaultDispenseItemBehavior.class) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ } else { ++ world.addFreshEntity(entityitem); ++ } ++ return false; ++ } ++ ++ world.addFreshEntity(entityitem); ++ ++ return true; ++ // CraftBukkit end + } + +- protected void playAnimation(BlockSource blocksource, Direction direction) { +- blocksource.level().levelEvent(2000, blocksource.pos(), direction.get3DDataValue()); ++ protected void playSound(SourceBlock sourceblock) { ++ sourceblock.level().levelEvent(1000, sourceblock.pos(), 0); + } ++ ++ protected void playAnimation(SourceBlock sourceblock, Direction enumdirection) { ++ sourceblock.level().levelEvent(2000, sourceblock.pos(), enumdirection.get3DDataValue()); ++ } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/core/dispenser/DispenseItemBehavior.java.patch b/patch-remap/mache-spigotflower/net/minecraft/core/dispenser/DispenseItemBehavior.java.patch new file mode 100644 index 0000000000..3958739a5e --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/core/dispenser/DispenseItemBehavior.java.patch @@ -0,0 +1,1424 @@ +--- a/net/minecraft/core/dispenser/DispenseItemBehavior.java ++++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java +@@ -8,7 +8,7 @@ + import net.minecraft.Util; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.Position; ++import net.minecraft.core.IPosition; + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; +@@ -19,8 +19,8 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.Saddleable; + import net.minecraft.world.entity.animal.horse.AbstractChestedHorse; + import net.minecraft.world.entity.animal.horse.AbstractHorse; +@@ -40,6 +40,7 @@ + import net.minecraft.world.entity.vehicle.Boat; + import net.minecraft.world.item.ArmorItem; + import net.minecraft.world.item.BoneMealItem; ++import net.minecraft.world.item.BucketItem; + import net.minecraft.world.item.DispensibleContainerItem; + import net.minecraft.world.item.DyeColor; + import net.minecraft.world.item.HoneycombItem; +@@ -60,7 +61,9 @@ + import net.minecraft.world.level.block.CandleCakeBlock; + import net.minecraft.world.level.block.CarvedPumpkinBlock; + import net.minecraft.world.level.block.DispenserBlock; ++import net.minecraft.world.level.block.LiquidBlockContainer; + import net.minecraft.world.level.block.RespawnAnchorBlock; ++import net.minecraft.world.level.block.SaplingBlock; + import net.minecraft.world.level.block.ShulkerBoxBlock; + import net.minecraft.world.level.block.SkullBlock; + import net.minecraft.world.level.block.TntBlock; +@@ -68,7 +71,7 @@ + import net.minecraft.world.level.block.entity.BeehiveBlockEntity; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.SkullBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.RotationSegment; + import net.minecraft.world.level.gameevent.GameEvent; +@@ -76,330 +79,510 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; ++import org.bukkit.Location; ++import org.bukkit.TreeType; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.craftbukkit.util.DummyGeneratorAccess; ++import org.bukkit.event.block.BlockDispenseArmorEvent; ++import org.bukkit.event.block.BlockDispenseEvent; ++import org.bukkit.event.block.BlockFertilizeEvent; ++import org.bukkit.event.world.StructureGrowEvent; ++// CraftBukkit end + + public interface DispenseItemBehavior { + + Logger LOGGER = LogUtils.getLogger(); +- DispenseItemBehavior NOOP = (blocksource, itemstack) -> { ++ DispenseItemBehavior NOOP = (sourceblock, itemstack) -> { + return itemstack; + }; + +- ItemStack dispense(BlockSource blockSource, ItemStack itemStack); ++ ItemStack dispense(SourceBlock sourceblock, ItemStack itemstack); + + static void bootStrap() { + DispenserBlock.registerBehavior(Items.ARROW, new AbstractProjectileDispenseBehavior() { + @Override +- @Override +- protected Projectile getProjectile(Level level, Position position, ItemStack itemstack) { +- Arrow arrow = new Arrow(level, position.x(), position.y(), position.z(), itemstack.copyWithCount(1)); ++ protected Projectile getProjectile(Level level, IPosition position, ItemStack stack) { ++ Arrow entitytippedarrow = new Arrow(level, position.x(), position.y(), position.z(), stack.copyWithCount(1)); + +- arrow.pickup = AbstractArrow.Pickup.ALLOWED; +- return arrow; ++ entitytippedarrow.pickup = AbstractArrow.Pickup.ALLOWED; ++ return entitytippedarrow; + } + }); + DispenserBlock.registerBehavior(Items.TIPPED_ARROW, new AbstractProjectileDispenseBehavior() { + @Override +- @Override +- protected Projectile getProjectile(Level level, Position position, ItemStack itemstack) { +- Arrow arrow = new Arrow(level, position.x(), position.y(), position.z(), itemstack.copyWithCount(1)); ++ protected Projectile getProjectile(Level level, IPosition position, ItemStack stack) { ++ Arrow entitytippedarrow = new Arrow(level, position.x(), position.y(), position.z(), stack.copyWithCount(1)); + +- arrow.setEffectsFromItem(itemstack); +- arrow.pickup = AbstractArrow.Pickup.ALLOWED; +- return arrow; ++ entitytippedarrow.setEffectsFromItem(stack); ++ entitytippedarrow.pickup = AbstractArrow.Pickup.ALLOWED; ++ return entitytippedarrow; + } + }); + DispenserBlock.registerBehavior(Items.SPECTRAL_ARROW, new AbstractProjectileDispenseBehavior() { + @Override +- @Override +- protected Projectile getProjectile(Level level, Position position, ItemStack itemstack) { +- SpectralArrow spectralarrow = new SpectralArrow(level, position.x(), position.y(), position.z(), itemstack.copyWithCount(1)); ++ protected Projectile getProjectile(Level level, IPosition position, ItemStack stack) { ++ SpectralArrow entityspectralarrow = new SpectralArrow(level, position.x(), position.y(), position.z(), stack.copyWithCount(1)); + +- spectralarrow.pickup = AbstractArrow.Pickup.ALLOWED; +- return spectralarrow; ++ entityspectralarrow.pickup = AbstractArrow.Pickup.ALLOWED; ++ return entityspectralarrow; + } + }); + DispenserBlock.registerBehavior(Items.EGG, new AbstractProjectileDispenseBehavior() { + @Override +- @Override +- protected Projectile getProjectile(Level level, Position position, ItemStack itemstack) { +- return (Projectile) Util.make(new ThrownEgg(level, position.x(), position.y(), position.z()), (thrownegg) -> { +- thrownegg.setItem(itemstack); ++ protected Projectile getProjectile(Level level, IPosition position, ItemStack stack) { ++ return (Projectile) Util.make(new ThrownEgg(level, position.x(), position.y(), position.z()), (entityegg) -> { ++ entityegg.setItem(stack); + }); + } + }); + DispenserBlock.registerBehavior(Items.SNOWBALL, new AbstractProjectileDispenseBehavior() { + @Override +- @Override +- protected Projectile getProjectile(Level level, Position position, ItemStack itemstack) { +- return (Projectile) Util.make(new Snowball(level, position.x(), position.y(), position.z()), (snowball) -> { +- snowball.setItem(itemstack); ++ protected Projectile getProjectile(Level level, IPosition position, ItemStack stack) { ++ return (Projectile) Util.make(new Snowball(level, position.x(), position.y(), position.z()), (entitysnowball) -> { ++ entitysnowball.setItem(stack); + }); + } + }); + DispenserBlock.registerBehavior(Items.EXPERIENCE_BOTTLE, new AbstractProjectileDispenseBehavior() { + @Override +- @Override +- protected Projectile getProjectile(Level level, Position position, ItemStack itemstack) { +- return (Projectile) Util.make(new ThrownExperienceBottle(level, position.x(), position.y(), position.z()), (thrownexperiencebottle) -> { +- thrownexperiencebottle.setItem(itemstack); ++ protected Projectile getProjectile(Level level, IPosition position, ItemStack stack) { ++ return (Projectile) Util.make(new ThrownExperienceBottle(level, position.x(), position.y(), position.z()), (entitythrownexpbottle) -> { ++ entitythrownexpbottle.setItem(stack); + }); + } + + @Override +- @Override + protected float getUncertainty() { + return super.getUncertainty() * 0.5F; + } + + @Override +- @Override + protected float getPower() { + return super.getPower() * 1.25F; + } + }); + DispenserBlock.registerBehavior(Items.SPLASH_POTION, new DispenseItemBehavior() { + @Override +- @Override +- public ItemStack dispense(BlockSource blocksource, ItemStack itemstack) { ++ public ItemStack dispense(SourceBlock sourceblock, ItemStack itemstack) { + return (new AbstractProjectileDispenseBehavior() { + @Override +- @Override +- protected Projectile getProjectile(Level level, Position position, ItemStack itemstack1) { +- return (Projectile) Util.make(new ThrownPotion(level, position.x(), position.y(), position.z()), (thrownpotion) -> { +- thrownpotion.setItem(itemstack1); ++ protected Projectile getProjectile(Level level, IPosition position, ItemStack stack) { ++ return (Projectile) Util.make(new ThrownPotion(level, position.x(), position.y(), position.z()), (entitypotion) -> { ++ entitypotion.setItem(stack); + }); + } + + @Override +- @Override + protected float getUncertainty() { + return super.getUncertainty() * 0.5F; + } + + @Override +- @Override + protected float getPower() { + return super.getPower() * 1.25F; + } +- }).dispense(blocksource, itemstack); ++ }).dispense(sourceblock, itemstack); + } + }); + DispenserBlock.registerBehavior(Items.LINGERING_POTION, new DispenseItemBehavior() { + @Override +- @Override +- public ItemStack dispense(BlockSource blocksource, ItemStack itemstack) { ++ public ItemStack dispense(SourceBlock sourceblock, ItemStack itemstack) { + return (new AbstractProjectileDispenseBehavior() { + @Override +- @Override +- protected Projectile getProjectile(Level level, Position position, ItemStack itemstack1) { +- return (Projectile) Util.make(new ThrownPotion(level, position.x(), position.y(), position.z()), (thrownpotion) -> { +- thrownpotion.setItem(itemstack1); ++ protected Projectile getProjectile(Level level, IPosition position, ItemStack stack) { ++ return (Projectile) Util.make(new ThrownPotion(level, position.x(), position.y(), position.z()), (entitypotion) -> { ++ entitypotion.setItem(stack); + }); + } + + @Override +- @Override + protected float getUncertainty() { + return super.getUncertainty() * 0.5F; + } + + @Override +- @Override + protected float getPower() { + return super.getPower() * 1.25F; + } +- }).dispense(blocksource, itemstack); ++ }).dispense(sourceblock, itemstack); + } + }); +- DefaultDispenseItemBehavior defaultdispenseitembehavior = new DefaultDispenseItemBehavior() { ++ DefaultDispenseItemBehavior dispensebehavioritem = new DefaultDispenseItemBehavior() { + @Override +- @Override +- public ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING); +- EntityType entitytype = ((SpawnEggItem) itemstack.getItem()).getType(itemstack.getTag()); ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ EntityType entitytypes = ((SpawnEggItem) itemstack.getItem()).getType(itemstack.getTag()); + ++ // CraftBukkit start ++ ServerLevel worldserver = sourceblock.level(); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ + try { +- entitytype.spawn(blocksource.level(), itemstack, (Player) null, blocksource.pos().relative(direction), MobSpawnType.DISPENSER, direction != Direction.UP, false); ++ entitytypes.spawn(sourceblock.level(), itemstack, (Player) null, sourceblock.pos().relative(enumdirection), EnumMobSpawn.DISPENSER, enumdirection != Direction.UP, false); + } catch (Exception exception) { +- null.LOGGER.error("Error while dispensing spawn egg from dispenser at {}", blocksource.pos(), exception); ++ LOGGER.error("Error while dispensing spawn egg from dispenser at {}", sourceblock.pos(), exception); // CraftBukkit - decompile error + return ItemStack.EMPTY; + } + +- itemstack.shrink(1); +- blocksource.level().gameEvent((Entity) null, GameEvent.ENTITY_PLACE, blocksource.pos()); ++ // itemstack.shrink(1); // Handled during event processing ++ // CraftBukkit end ++ sourceblock.level().gameEvent((Entity) null, GameEvent.ENTITY_PLACE, sourceblock.pos()); + return itemstack; + } + }; + Iterator iterator = SpawnEggItem.eggs().iterator(); + + while (iterator.hasNext()) { +- SpawnEggItem spawneggitem = (SpawnEggItem) iterator.next(); ++ SpawnEggItem itemmonsteregg = (SpawnEggItem) iterator.next(); + +- DispenserBlock.registerBehavior(spawneggitem, defaultdispenseitembehavior); ++ DispenserBlock.registerBehavior(itemmonsteregg, dispensebehavioritem); + } + + DispenserBlock.registerBehavior(Items.ARMOR_STAND, new DefaultDispenseItemBehavior() { + @Override +- @Override +- public ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING); +- BlockPos blockpos = blocksource.pos().relative(direction); +- ServerLevel serverlevel = blocksource.level(); +- Consumer consumer = EntityType.appendDefaultStackConfig((armorstand) -> { +- armorstand.setYRot(direction.toYRot()); +- }, serverlevel, itemstack, (Player) null); +- ArmorStand armorstand = (ArmorStand) EntityType.ARMOR_STAND.spawn(serverlevel, itemstack.getTag(), consumer, blockpos, MobSpawnType.DISPENSER, false, false); ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ BlockPos blockposition = sourceblock.pos().relative(enumdirection); ++ ServerLevel worldserver = sourceblock.level(); + +- if (armorstand != null) { +- itemstack.shrink(1); ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); + } + ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ ++ Consumer consumer = EntityType.appendDefaultStackConfig((entityarmorstand) -> { ++ entityarmorstand.setYRot(enumdirection.toYRot()); ++ }, worldserver, itemstack, (Player) null); ++ ArmorStand entityarmorstand = (ArmorStand) EntityType.ARMOR_STAND.spawn(worldserver, itemstack.getTag(), consumer, blockposition, EnumMobSpawn.DISPENSER, false, false); ++ ++ if (entityarmorstand != null) { ++ // itemstack.shrink(1); // CraftBukkit - Handled during event processing ++ } ++ + return itemstack; + } + }); + DispenserBlock.registerBehavior(Items.SADDLE, new OptionalDispenseItemBehavior() { + @Override +- @Override +- public ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING)); +- List list = blocksource.level().getEntitiesOfClass(LivingEntity.class, new AABB(blockpos), (livingentity) -> { +- if (!(livingentity instanceof Saddleable)) { ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ List list = sourceblock.level().getEntitiesOfClass(LivingEntity.class, new AABB(blockposition), (entityliving) -> { ++ if (!(entityliving instanceof Saddleable)) { + return false; + } else { +- Saddleable saddleable = (Saddleable) livingentity; ++ Saddleable isaddleable = (Saddleable) entityliving; + +- return !saddleable.isSaddled() && saddleable.isSaddleable(); ++ return !isaddleable.isSaddled() && isaddleable.isSaddleable(); + } + }); + + if (!list.isEmpty()) { ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ Level world = sourceblock.level(); ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) list.get(0).getBukkitEntity()); ++ if (!DispenserBlock.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end + ((Saddleable) list.get(0)).equipSaddle(SoundSource.BLOCKS); +- itemstack.shrink(1); ++ // itemstack.shrink(1); // CraftBukkit - handled above + this.setSuccess(true); + return itemstack; + } else { +- return super.execute(blocksource, itemstack); ++ return super.execute(sourceblock, itemstack); + } + } + }); +- OptionalDispenseItemBehavior optionaldispenseitembehavior = new OptionalDispenseItemBehavior() { ++ OptionalDispenseItemBehavior dispensebehaviormaybe = new OptionalDispenseItemBehavior() { + @Override +- @Override +- protected ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING)); +- List list = blocksource.level().getEntitiesOfClass(AbstractHorse.class, new AABB(blockpos), (abstracthorse) -> { +- return abstracthorse.isAlive() && abstracthorse.canWearArmor(); ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ List list = sourceblock.level().getEntitiesOfClass(AbstractHorse.class, new AABB(blockposition), (entityhorseabstract) -> { ++ return entityhorseabstract.isAlive() && entityhorseabstract.canWearArmor(); + }); + Iterator iterator1 = list.iterator(); + +- AbstractHorse abstracthorse; ++ AbstractHorse entityhorseabstract; + + do { + if (!iterator1.hasNext()) { +- return super.execute(blocksource, itemstack); ++ return super.execute(sourceblock, itemstack); + } + +- abstracthorse = (AbstractHorse) iterator1.next(); +- } while (!abstracthorse.isArmor(itemstack) || abstracthorse.isWearingArmor() || !abstracthorse.isTamed()); ++ entityhorseabstract = (AbstractHorse) iterator1.next(); ++ } while (!entityhorseabstract.isArmor(itemstack) || entityhorseabstract.isWearingArmor() || !entityhorseabstract.isTamed()); + +- abstracthorse.getSlot(401).set(itemstack.split(1)); ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ Level world = sourceblock.level(); ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityhorseabstract.getBukkitEntity()); ++ if (!DispenserBlock.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ entityhorseabstract.getSlot(401).set(CraftItemStack.asNMSCopy(event.getItem())); ++ // CraftBukkit end + this.setSuccess(true); + return itemstack; + } + }; + +- DispenserBlock.registerBehavior(Items.LEATHER_HORSE_ARMOR, optionaldispenseitembehavior); +- DispenserBlock.registerBehavior(Items.IRON_HORSE_ARMOR, optionaldispenseitembehavior); +- DispenserBlock.registerBehavior(Items.GOLDEN_HORSE_ARMOR, optionaldispenseitembehavior); +- DispenserBlock.registerBehavior(Items.DIAMOND_HORSE_ARMOR, optionaldispenseitembehavior); +- DispenserBlock.registerBehavior(Items.WHITE_CARPET, optionaldispenseitembehavior); +- DispenserBlock.registerBehavior(Items.ORANGE_CARPET, optionaldispenseitembehavior); +- DispenserBlock.registerBehavior(Items.CYAN_CARPET, optionaldispenseitembehavior); +- DispenserBlock.registerBehavior(Items.BLUE_CARPET, optionaldispenseitembehavior); +- DispenserBlock.registerBehavior(Items.BROWN_CARPET, optionaldispenseitembehavior); +- DispenserBlock.registerBehavior(Items.BLACK_CARPET, optionaldispenseitembehavior); +- DispenserBlock.registerBehavior(Items.GRAY_CARPET, optionaldispenseitembehavior); +- DispenserBlock.registerBehavior(Items.GREEN_CARPET, optionaldispenseitembehavior); +- DispenserBlock.registerBehavior(Items.LIGHT_BLUE_CARPET, optionaldispenseitembehavior); +- DispenserBlock.registerBehavior(Items.LIGHT_GRAY_CARPET, optionaldispenseitembehavior); +- DispenserBlock.registerBehavior(Items.LIME_CARPET, optionaldispenseitembehavior); +- DispenserBlock.registerBehavior(Items.MAGENTA_CARPET, optionaldispenseitembehavior); +- DispenserBlock.registerBehavior(Items.PINK_CARPET, optionaldispenseitembehavior); +- DispenserBlock.registerBehavior(Items.PURPLE_CARPET, optionaldispenseitembehavior); +- DispenserBlock.registerBehavior(Items.RED_CARPET, optionaldispenseitembehavior); +- DispenserBlock.registerBehavior(Items.YELLOW_CARPET, optionaldispenseitembehavior); ++ DispenserBlock.registerBehavior(Items.LEATHER_HORSE_ARMOR, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.IRON_HORSE_ARMOR, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.GOLDEN_HORSE_ARMOR, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.DIAMOND_HORSE_ARMOR, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.WHITE_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.ORANGE_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.CYAN_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.BLUE_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.BROWN_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.BLACK_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.GRAY_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.GREEN_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.LIGHT_BLUE_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.LIGHT_GRAY_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.LIME_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.MAGENTA_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.PINK_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.PURPLE_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.RED_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.YELLOW_CARPET, dispensebehaviormaybe); + DispenserBlock.registerBehavior(Items.CHEST, new OptionalDispenseItemBehavior() { + @Override +- @Override +- public ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING)); +- List list = blocksource.level().getEntitiesOfClass(AbstractChestedHorse.class, new AABB(blockpos), (abstractchestedhorse) -> { +- return abstractchestedhorse.isAlive() && !abstractchestedhorse.hasChest(); ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ List list = sourceblock.level().getEntitiesOfClass(AbstractChestedHorse.class, new AABB(blockposition), (entityhorsechestedabstract) -> { ++ return entityhorsechestedabstract.isAlive() && !entityhorsechestedabstract.hasChest(); + }); + Iterator iterator1 = list.iterator(); + +- AbstractChestedHorse abstractchestedhorse; ++ AbstractChestedHorse entityhorsechestedabstract; + + do { + if (!iterator1.hasNext()) { +- return super.execute(blocksource, itemstack); ++ return super.execute(sourceblock, itemstack); + } + +- abstractchestedhorse = (AbstractChestedHorse) iterator1.next(); +- } while (!abstractchestedhorse.isTamed() || !abstractchestedhorse.getSlot(499).set(itemstack)); ++ entityhorsechestedabstract = (AbstractChestedHorse) iterator1.next(); ++ // CraftBukkit start ++ } while (!entityhorsechestedabstract.isTamed()); ++ ItemStack itemstack1 = itemstack.split(1); ++ Level world = sourceblock.level(); ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + +- itemstack.shrink(1); ++ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityhorsechestedabstract.getBukkitEntity()); ++ if (!DispenserBlock.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ entityhorsechestedabstract.getSlot(499).set(CraftItemStack.asNMSCopy(event.getItem())); ++ // CraftBukkit end ++ ++ // itemstack.shrink(1); // CraftBukkit - handled above + this.setSuccess(true); + return itemstack; + } + }); + DispenserBlock.registerBehavior(Items.FIREWORK_ROCKET, new DefaultDispenseItemBehavior() { + @Override +- @Override +- public ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING); +- Vec3 vec3 = DispenseItemBehavior.getEntityPokingOutOfBlockPos(blocksource, EntityType.FIREWORK_ROCKET, direction); +- FireworkRocketEntity fireworkrocketentity = new FireworkRocketEntity(blocksource.level(), itemstack, vec3.x(), vec3.y(), vec3.z(), true); ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ // CraftBukkit start ++ ServerLevel worldserver = sourceblock.level(); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + +- fireworkrocketentity.shoot((double) direction.getStepX(), (double) direction.getStepY(), (double) direction.getStepZ(), 0.5F, 1.0F); +- blocksource.level().addFreshEntity(fireworkrocketentity); +- itemstack.shrink(1); ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(enumdirection.getStepX(), enumdirection.getStepY(), enumdirection.getStepZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); ++ Vec3 vec3d = DispenseItemBehavior.getEntityPokingOutOfBlockPos(sourceblock, EntityType.FIREWORK_ROCKET, enumdirection); ++ FireworkRocketEntity entityfireworks = new FireworkRocketEntity(sourceblock.level(), itemstack, vec3d.x(), vec3d.y(), vec3d.z(), true); ++ ++ entityfireworks.shoot((double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ(), 0.5F, 1.0F); ++ sourceblock.level().addFreshEntity(entityfireworks); ++ // itemstack.shrink(1); // Handled during event processing ++ // CraftBukkit end + return itemstack; + } + + @Override +- @Override +- protected void playSound(BlockSource blocksource) { +- blocksource.level().levelEvent(1004, blocksource.pos(), 0); ++ protected void playSound(SourceBlock sourceblock) { ++ sourceblock.level().levelEvent(1004, sourceblock.pos(), 0); + } + }); + DispenserBlock.registerBehavior(Items.FIRE_CHARGE, new DefaultDispenseItemBehavior() { + @Override +- @Override +- public ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING); +- Position position = DispenserBlock.getDispensePosition(blocksource); +- double d0 = position.x() + (double) ((float) direction.getStepX() * 0.3F); +- double d1 = position.y() + (double) ((float) direction.getStepY() * 0.3F); +- double d2 = position.z() + (double) ((float) direction.getStepZ() * 0.3F); +- ServerLevel serverlevel = blocksource.level(); +- RandomSource randomsource = serverlevel.random; +- double d3 = randomsource.triangle((double) direction.getStepX(), 0.11485000000000001D); +- double d4 = randomsource.triangle((double) direction.getStepY(), 0.11485000000000001D); +- double d5 = randomsource.triangle((double) direction.getStepZ(), 0.11485000000000001D); +- SmallFireball smallfireball = new SmallFireball(serverlevel, d0, d1, d2, d3, d4, d5); ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ IPosition iposition = DispenserBlock.getDispensePosition(sourceblock); ++ double d0 = iposition.x() + (double) ((float) enumdirection.getStepX() * 0.3F); ++ double d1 = iposition.y() + (double) ((float) enumdirection.getStepY() * 0.3F); ++ double d2 = iposition.z() + (double) ((float) enumdirection.getStepZ() * 0.3F); ++ ServerLevel worldserver = sourceblock.level(); ++ RandomSource randomsource = worldserver.random; ++ double d3 = randomsource.triangle((double) enumdirection.getStepX(), 0.11485000000000001D); ++ double d4 = randomsource.triangle((double) enumdirection.getStepY(), 0.11485000000000001D); ++ double d5 = randomsource.triangle((double) enumdirection.getStepZ(), 0.11485000000000001D); + +- serverlevel.addFreshEntity((Entity) Util.make(smallfireball, (smallfireball1) -> { +- smallfireball1.setItem(itemstack); +- })); +- itemstack.shrink(1); ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d3, d4, d5)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ SmallFireball entitysmallfireball = new SmallFireball(worldserver, d0, d1, d2, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ()); ++ entitysmallfireball.setItem(itemstack1); ++ entitysmallfireball.projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(sourceblock.blockEntity()); ++ ++ worldserver.addFreshEntity(entitysmallfireball); ++ // itemstack.shrink(1); // Handled during event processing ++ // CraftBukkit end + return itemstack; + } + + @Override +- @Override +- protected void playSound(BlockSource blocksource) { +- blocksource.level().levelEvent(1018, blocksource.pos(), 0); ++ protected void playSound(SourceBlock sourceblock) { ++ sourceblock.level().levelEvent(1018, sourceblock.pos(), 0); + } + }); + DispenserBlock.registerBehavior(Items.OAK_BOAT, new BoatDispenseItemBehavior(Boat.Type.OAK)); +@@ -420,98 +603,191 @@ + DispenserBlock.registerBehavior(Items.CHERRY_CHEST_BOAT, new BoatDispenseItemBehavior(Boat.Type.CHERRY, true)); + DispenserBlock.registerBehavior(Items.MANGROVE_CHEST_BOAT, new BoatDispenseItemBehavior(Boat.Type.MANGROVE, true)); + DispenserBlock.registerBehavior(Items.BAMBOO_CHEST_RAFT, new BoatDispenseItemBehavior(Boat.Type.BAMBOO, true)); +- DefaultDispenseItemBehavior defaultdispenseitembehavior1 = new DefaultDispenseItemBehavior() { ++ DefaultDispenseItemBehavior dispensebehavioritem1 = new DefaultDispenseItemBehavior() { + private final DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior(); + + @Override +- @Override +- public ItemStack execute(BlockSource blocksource, ItemStack itemstack) { ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { + DispensibleContainerItem dispensiblecontaineritem = (DispensibleContainerItem) itemstack.getItem(); +- BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING)); +- ServerLevel serverlevel = blocksource.level(); ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ ServerLevel worldserver = sourceblock.level(); + +- if (dispensiblecontaineritem.emptyContents((Player) null, serverlevel, blockpos, (BlockHitResult) null)) { +- dispensiblecontaineritem.checkExtraContent((Player) null, serverlevel, itemstack, blockpos); +- return new ItemStack(Items.BUCKET); ++ // CraftBukkit start ++ int x = blockposition.getX(); ++ int y = blockposition.getY(); ++ int z = blockposition.getZ(); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ if (iblockdata.isAir() || iblockdata.canBeReplaced() || (dispensiblecontaineritem instanceof BucketItem && iblockdata.getBlock() instanceof LiquidBlockContainer && ((LiquidBlockContainer) iblockdata.getBlock()).canPlaceLiquid((Player) null, worldserver, blockposition, iblockdata, ((BucketItem) dispensiblecontaineritem).content))) { ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(x, y, z)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ dispensiblecontaineritem = (DispensibleContainerItem) CraftItemStack.asNMSCopy(event.getItem()).getItem(); ++ } ++ // CraftBukkit end ++ ++ if (dispensiblecontaineritem.emptyContents((Player) null, worldserver, blockposition, (BlockHitResult) null)) { ++ dispensiblecontaineritem.checkExtraContent((Player) null, worldserver, itemstack, blockposition); ++ // CraftBukkit start - Handle stacked buckets ++ Item item = Items.BUCKET; ++ itemstack.shrink(1); ++ if (itemstack.isEmpty()) { ++ itemstack.setItem(Items.BUCKET); ++ itemstack.setCount(1); ++ } else if (sourceblock.blockEntity().addItem(new ItemStack(item)) < 0) { ++ this.defaultDispenseItemBehavior.dispense(sourceblock, new ItemStack(item)); ++ } ++ return itemstack; ++ // CraftBukkit end + } else { +- return this.defaultDispenseItemBehavior.dispense(blocksource, itemstack); ++ return this.defaultDispenseItemBehavior.dispense(sourceblock, itemstack); + } + } + }; + +- DispenserBlock.registerBehavior(Items.LAVA_BUCKET, defaultdispenseitembehavior1); +- DispenserBlock.registerBehavior(Items.WATER_BUCKET, defaultdispenseitembehavior1); +- DispenserBlock.registerBehavior(Items.POWDER_SNOW_BUCKET, defaultdispenseitembehavior1); +- DispenserBlock.registerBehavior(Items.SALMON_BUCKET, defaultdispenseitembehavior1); +- DispenserBlock.registerBehavior(Items.COD_BUCKET, defaultdispenseitembehavior1); +- DispenserBlock.registerBehavior(Items.PUFFERFISH_BUCKET, defaultdispenseitembehavior1); +- DispenserBlock.registerBehavior(Items.TROPICAL_FISH_BUCKET, defaultdispenseitembehavior1); +- DispenserBlock.registerBehavior(Items.AXOLOTL_BUCKET, defaultdispenseitembehavior1); +- DispenserBlock.registerBehavior(Items.TADPOLE_BUCKET, defaultdispenseitembehavior1); ++ DispenserBlock.registerBehavior(Items.LAVA_BUCKET, dispensebehavioritem1); ++ DispenserBlock.registerBehavior(Items.WATER_BUCKET, dispensebehavioritem1); ++ DispenserBlock.registerBehavior(Items.POWDER_SNOW_BUCKET, dispensebehavioritem1); ++ DispenserBlock.registerBehavior(Items.SALMON_BUCKET, dispensebehavioritem1); ++ DispenserBlock.registerBehavior(Items.COD_BUCKET, dispensebehavioritem1); ++ DispenserBlock.registerBehavior(Items.PUFFERFISH_BUCKET, dispensebehavioritem1); ++ DispenserBlock.registerBehavior(Items.TROPICAL_FISH_BUCKET, dispensebehavioritem1); ++ DispenserBlock.registerBehavior(Items.AXOLOTL_BUCKET, dispensebehavioritem1); ++ DispenserBlock.registerBehavior(Items.TADPOLE_BUCKET, dispensebehavioritem1); + DispenserBlock.registerBehavior(Items.BUCKET, new DefaultDispenseItemBehavior() { + private final DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior(); + + @Override +- @Override +- public ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- ServerLevel serverlevel = blocksource.level(); +- BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING)); +- BlockState blockstate = serverlevel.getBlockState(blockpos); +- Block block = blockstate.getBlock(); ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ Block block = iblockdata.getBlock(); + + if (block instanceof BucketPickup) { +- BucketPickup bucketpickup = (BucketPickup) block; +- ItemStack itemstack1 = bucketpickup.pickupBlock((Player) null, serverlevel, blockpos, blockstate); ++ BucketPickup ifluidsource = (BucketPickup) block; ++ ItemStack itemstack1 = ifluidsource.pickupBlock((Player) null, DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); // CraftBukkit + + if (itemstack1.isEmpty()) { +- return super.execute(blocksource, itemstack); ++ return super.execute(sourceblock, itemstack); + } else { +- serverlevel.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockpos); ++ worldserver.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockposition); + Item item = itemstack1.getItem(); + ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ itemstack1 = ifluidsource.pickupBlock((Player) null, worldserver, blockposition, iblockdata); // From above ++ // CraftBukkit end ++ + itemstack.shrink(1); + if (itemstack.isEmpty()) { + return new ItemStack(item); + } else { +- if (blocksource.blockEntity().addItem(new ItemStack(item)) < 0) { +- this.defaultDispenseItemBehavior.dispense(blocksource, new ItemStack(item)); ++ if (sourceblock.blockEntity().addItem(new ItemStack(item)) < 0) { ++ this.defaultDispenseItemBehavior.dispense(sourceblock, new ItemStack(item)); + } + + return itemstack; + } + } + } else { +- return super.execute(blocksource, itemstack); ++ return super.execute(sourceblock, itemstack); + } + } + }); + DispenserBlock.registerBehavior(Items.FLINT_AND_STEEL, new OptionalDispenseItemBehavior() { + @Override +- @Override +- protected ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- ServerLevel serverlevel = blocksource.level(); ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); + ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ + this.setSuccess(true); +- Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING); +- BlockPos blockpos = blocksource.pos().relative(direction); +- BlockState blockstate = serverlevel.getBlockState(blockpos); ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ BlockPos blockposition = sourceblock.pos().relative(enumdirection); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); + +- if (BaseFireBlock.canBePlacedAt(serverlevel, blockpos, direction)) { +- serverlevel.setBlockAndUpdate(blockpos, BaseFireBlock.getState(serverlevel, blockpos)); +- serverlevel.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockpos); +- } else if (!CampfireBlock.canLight(blockstate) && !CandleBlock.canLight(blockstate) && !CandleCakeBlock.canLight(blockstate)) { +- if (blockstate.getBlock() instanceof TntBlock) { +- TntBlock.explode(serverlevel, blockpos); +- serverlevel.removeBlock(blockpos, false); ++ if (BaseFireBlock.canBePlacedAt(worldserver, blockposition, enumdirection)) { ++ // CraftBukkit start - Ignition by dispensing flint and steel ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(worldserver, blockposition, sourceblock.pos()).isCancelled()) { ++ worldserver.setBlockAndUpdate(blockposition, BaseFireBlock.getState(worldserver, blockposition)); ++ worldserver.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockposition); ++ } ++ // CraftBukkit end ++ } else if (!CampfireBlock.canLight(iblockdata) && !CandleBlock.canLight(iblockdata) && !CandleCakeBlock.canLight(iblockdata)) { ++ if (iblockdata.getBlock() instanceof TntBlock && org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(worldserver, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.DISPENSER, null, sourceblock.pos())) { // CraftBukkit - TNTPrimeEvent ++ TntBlock.explode(worldserver, blockposition); ++ worldserver.removeBlock(blockposition, false); + } else { + this.setSuccess(false); + } + } else { +- serverlevel.setBlockAndUpdate(blockpos, (BlockState) blockstate.setValue(BlockStateProperties.LIT, true)); +- serverlevel.gameEvent((Entity) null, GameEvent.BLOCK_CHANGE, blockpos); ++ worldserver.setBlockAndUpdate(blockposition, (IBlockData) iblockdata.setValue(BlockStateProperties.LIT, true)); ++ worldserver.gameEvent((Entity) null, GameEvent.BLOCK_CHANGE, blockposition); + } + +- if (this.isSuccess() && itemstack.hurt(1, serverlevel.random, (ServerPlayer) null)) { ++ if (this.isSuccess() && itemstack.hurt(1, worldserver.random, (ServerPlayer) null)) { + itemstack.setCount(0); + } + +@@ -520,72 +796,171 @@ + }); + DispenserBlock.registerBehavior(Items.BONE_MEAL, new OptionalDispenseItemBehavior() { + @Override +- @Override +- protected ItemStack execute(BlockSource blocksource, ItemStack itemstack) { ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { + this.setSuccess(true); +- ServerLevel serverlevel = blocksource.level(); +- BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING)); ++ ServerLevel worldserver = sourceblock.level(); ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ // CraftBukkit start ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); + +- if (!BoneMealItem.growCrop(itemstack, serverlevel, blockpos) && !BoneMealItem.growWaterPlant(itemstack, serverlevel, blockpos, (Direction) null)) { ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ worldserver.captureTreeGeneration = true; ++ // CraftBukkit end ++ ++ if (!BoneMealItem.growCrop(itemstack, worldserver, blockposition) && !BoneMealItem.growWaterPlant(itemstack, worldserver, blockposition, (Direction) null)) { + this.setSuccess(false); +- } else if (!serverlevel.isClientSide) { +- serverlevel.levelEvent(1505, blockpos, 0); ++ } else if (!worldserver.isClientSide) { ++ worldserver.levelEvent(1505, blockposition, 0); + } ++ // CraftBukkit start ++ worldserver.captureTreeGeneration = false; ++ if (worldserver.capturedBlockStates.size() > 0) { ++ TreeType treeType = SaplingBlock.treeType; ++ SaplingBlock.treeType = null; ++ Location location = CraftLocation.toBukkit(blockposition, worldserver.getWorld()); ++ List blocks = new java.util.ArrayList<>(worldserver.capturedBlockStates.values()); ++ worldserver.capturedBlockStates.clear(); ++ StructureGrowEvent structureEvent = null; ++ if (treeType != null) { ++ structureEvent = new StructureGrowEvent(location, treeType, false, null, blocks); ++ org.bukkit.Bukkit.getPluginManager().callEvent(structureEvent); ++ } + ++ BlockFertilizeEvent fertilizeEvent = new BlockFertilizeEvent(location.getBlock(), null, blocks); ++ fertilizeEvent.setCancelled(structureEvent != null && structureEvent.isCancelled()); ++ org.bukkit.Bukkit.getPluginManager().callEvent(fertilizeEvent); ++ ++ if (!fertilizeEvent.isCancelled()) { ++ for (org.bukkit.block.BlockState blockstate : blocks) { ++ blockstate.update(true); ++ } ++ } ++ } ++ // CraftBukkit end ++ + return itemstack; + } + }); + DispenserBlock.registerBehavior(Blocks.TNT, new DefaultDispenseItemBehavior() { + @Override +- @Override +- protected ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- ServerLevel serverlevel = blocksource.level(); +- BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING)); +- PrimedTnt primedtnt = new PrimedTnt(serverlevel, (double) blockpos.getX() + 0.5D, (double) blockpos.getY(), (double) blockpos.getZ() + 0.5D, (LivingEntity) null); ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ // CraftBukkit start ++ // EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, (EntityLiving) null); + +- serverlevel.addFreshEntity(primedtnt); +- serverlevel.playSound((Player) null, primedtnt.getX(), primedtnt.getY(), primedtnt.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F); +- serverlevel.gameEvent((Entity) null, GameEvent.ENTITY_PLACE, blockpos); +- itemstack.shrink(1); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ PrimedTnt entitytntprimed = new PrimedTnt(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), (LivingEntity) null); ++ // CraftBukkit end ++ ++ worldserver.addFreshEntity(entitytntprimed); ++ worldserver.playSound((Player) null, entitytntprimed.getX(), entitytntprimed.getY(), entitytntprimed.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F); ++ worldserver.gameEvent((Entity) null, GameEvent.ENTITY_PLACE, blockposition); ++ // itemstack.shrink(1); // CraftBukkit - handled above + return itemstack; + } + }); +- OptionalDispenseItemBehavior optionaldispenseitembehavior1 = new OptionalDispenseItemBehavior() { ++ OptionalDispenseItemBehavior dispensebehaviormaybe1 = new OptionalDispenseItemBehavior() { + @Override +- @Override +- protected ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- this.setSuccess(ArmorItem.dispenseArmor(blocksource, itemstack)); ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ this.setSuccess(ArmorItem.dispenseArmor(sourceblock, itemstack)); + return itemstack; + } + }; + +- DispenserBlock.registerBehavior(Items.CREEPER_HEAD, optionaldispenseitembehavior1); +- DispenserBlock.registerBehavior(Items.ZOMBIE_HEAD, optionaldispenseitembehavior1); +- DispenserBlock.registerBehavior(Items.DRAGON_HEAD, optionaldispenseitembehavior1); +- DispenserBlock.registerBehavior(Items.SKELETON_SKULL, optionaldispenseitembehavior1); +- DispenserBlock.registerBehavior(Items.PIGLIN_HEAD, optionaldispenseitembehavior1); +- DispenserBlock.registerBehavior(Items.PLAYER_HEAD, optionaldispenseitembehavior1); ++ DispenserBlock.registerBehavior(Items.CREEPER_HEAD, dispensebehaviormaybe1); ++ DispenserBlock.registerBehavior(Items.ZOMBIE_HEAD, dispensebehaviormaybe1); ++ DispenserBlock.registerBehavior(Items.DRAGON_HEAD, dispensebehaviormaybe1); ++ DispenserBlock.registerBehavior(Items.SKELETON_SKULL, dispensebehaviormaybe1); ++ DispenserBlock.registerBehavior(Items.PIGLIN_HEAD, dispensebehaviormaybe1); ++ DispenserBlock.registerBehavior(Items.PLAYER_HEAD, dispensebehaviormaybe1); + DispenserBlock.registerBehavior(Items.WITHER_SKELETON_SKULL, new OptionalDispenseItemBehavior() { + @Override +- @Override +- protected ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- ServerLevel serverlevel = blocksource.level(); +- Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING); +- BlockPos blockpos = blocksource.pos().relative(direction); ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ BlockPos blockposition = sourceblock.pos().relative(enumdirection); + +- if (serverlevel.isEmptyBlock(blockpos) && WitherSkullBlock.canSpawnMob(serverlevel, blockpos, itemstack)) { +- serverlevel.setBlock(blockpos, (BlockState) Blocks.WITHER_SKELETON_SKULL.defaultBlockState().setValue(SkullBlock.ROTATION, RotationSegment.convertToSegment(direction)), 3); +- serverlevel.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockpos); +- BlockEntity blockentity = serverlevel.getBlockEntity(blockpos); ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); + +- if (blockentity instanceof SkullBlockEntity) { +- WitherSkullBlock.checkSpawn(serverlevel, blockpos, (SkullBlockEntity) blockentity); ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; + } ++ } ++ // CraftBukkit end + ++ if (worldserver.isEmptyBlock(blockposition) && WitherSkullBlock.canSpawnMob(worldserver, blockposition, itemstack)) { ++ worldserver.setBlock(blockposition, (IBlockData) Blocks.WITHER_SKELETON_SKULL.defaultBlockState().setValue(SkullBlock.ROTATION, RotationSegment.convertToSegment(enumdirection)), 3); ++ worldserver.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockposition); ++ BlockEntity tileentity = worldserver.getBlockEntity(blockposition); ++ ++ if (tileentity instanceof SkullBlockEntity) { ++ WitherSkullBlock.checkSpawn(worldserver, blockposition, (SkullBlockEntity) tileentity); ++ } ++ + itemstack.shrink(1); + this.setSuccess(true); + } else { +- this.setSuccess(ArmorItem.dispenseArmor(blocksource, itemstack)); ++ this.setSuccess(ArmorItem.dispenseArmor(sourceblock, itemstack)); + } + + return itemstack; +@@ -593,48 +968,71 @@ + }); + DispenserBlock.registerBehavior(Blocks.CARVED_PUMPKIN, new OptionalDispenseItemBehavior() { + @Override +- @Override +- protected ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- ServerLevel serverlevel = blocksource.level(); +- BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING)); +- CarvedPumpkinBlock carvedpumpkinblock = (CarvedPumpkinBlock) Blocks.CARVED_PUMPKIN; ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ CarvedPumpkinBlock blockpumpkincarved = (CarvedPumpkinBlock) Blocks.CARVED_PUMPKIN; + +- if (serverlevel.isEmptyBlock(blockpos) && carvedpumpkinblock.canSpawnGolem(serverlevel, blockpos)) { +- if (!serverlevel.isClientSide) { +- serverlevel.setBlock(blockpos, carvedpumpkinblock.defaultBlockState(), 3); +- serverlevel.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockpos); ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; + } ++ } ++ // CraftBukkit end + ++ if (worldserver.isEmptyBlock(blockposition) && blockpumpkincarved.canSpawnGolem(worldserver, blockposition)) { ++ if (!worldserver.isClientSide) { ++ worldserver.setBlock(blockposition, blockpumpkincarved.defaultBlockState(), 3); ++ worldserver.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockposition); ++ } ++ + itemstack.shrink(1); + this.setSuccess(true); + } else { +- this.setSuccess(ArmorItem.dispenseArmor(blocksource, itemstack)); ++ this.setSuccess(ArmorItem.dispenseArmor(sourceblock, itemstack)); + } + + return itemstack; + } + }); + DispenserBlock.registerBehavior(Blocks.SHULKER_BOX.asItem(), new ShulkerBoxDispenseBehavior()); +- DyeColor[] adyecolor = DyeColor.values(); +- int i = adyecolor.length; ++ DyeColor[] aenumcolor = DyeColor.values(); ++ int i = aenumcolor.length; + + for (int j = 0; j < i; ++j) { +- DyeColor dyecolor = adyecolor[j]; ++ DyeColor enumcolor = aenumcolor[j]; + +- DispenserBlock.registerBehavior(ShulkerBoxBlock.getBlockByColor(dyecolor).asItem(), new ShulkerBoxDispenseBehavior()); ++ DispenserBlock.registerBehavior(ShulkerBoxBlock.getBlockByColor(enumcolor).asItem(), new ShulkerBoxDispenseBehavior()); + } + + DispenserBlock.registerBehavior(Items.GLASS_BOTTLE.asItem(), new OptionalDispenseItemBehavior() { + private final DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior(); + +- private ItemStack takeLiquid(BlockSource blocksource, ItemStack itemstack, ItemStack itemstack1) { ++ private ItemStack takeLiquid(SourceBlock sourceblock, ItemStack itemstack, ItemStack itemstack1) { + itemstack.shrink(1); + if (itemstack.isEmpty()) { +- blocksource.level().gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blocksource.pos()); ++ sourceblock.level().gameEvent((Entity) null, GameEvent.FLUID_PICKUP, sourceblock.pos()); + return itemstack1.copy(); + } else { +- if (blocksource.blockEntity().addItem(itemstack1.copy()) < 0) { +- this.defaultDispenseItemBehavior.dispense(blocksource, itemstack1.copy()); ++ if (sourceblock.blockEntity().addItem(itemstack1.copy()) < 0) { ++ this.defaultDispenseItemBehavior.dispense(sourceblock, itemstack1.copy()); + } + + return itemstack; +@@ -642,40 +1040,62 @@ + } + + @Override +- @Override +- public ItemStack execute(BlockSource blocksource, ItemStack itemstack) { ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { + this.setSuccess(false); +- ServerLevel serverlevel = blocksource.level(); +- BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING)); +- BlockState blockstate = serverlevel.getBlockState(blockpos); ++ ServerLevel worldserver = sourceblock.level(); ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); + +- if (blockstate.is(BlockTags.BEEHIVES, (blockbehaviour_blockstatebase) -> { +- return blockbehaviour_blockstatebase.hasProperty(BeehiveBlock.HONEY_LEVEL) && blockbehaviour_blockstatebase.getBlock() instanceof BeehiveBlock; +- }) && (Integer) blockstate.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) { +- ((BeehiveBlock) blockstate.getBlock()).releaseBeesAndResetHoneyLevel(serverlevel, blockstate, blockpos, (Player) null, BeehiveBlockEntity.BeeReleaseStatus.BEE_RELEASED); ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ ++ if (iblockdata.is(BlockTags.BEEHIVES, (blockbase_blockdata) -> { ++ return blockbase_blockdata.hasProperty(BeehiveBlock.HONEY_LEVEL) && blockbase_blockdata.getBlock() instanceof BeehiveBlock; ++ }) && (Integer) iblockdata.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) { ++ ((BeehiveBlock) iblockdata.getBlock()).releaseBeesAndResetHoneyLevel(worldserver, iblockdata, blockposition, (Player) null, BeehiveBlockEntity.ReleaseStatus.BEE_RELEASED); + this.setSuccess(true); +- return this.takeLiquid(blocksource, itemstack, new ItemStack(Items.HONEY_BOTTLE)); +- } else if (serverlevel.getFluidState(blockpos).is(FluidTags.WATER)) { ++ return this.takeLiquid(sourceblock, itemstack, new ItemStack(Items.HONEY_BOTTLE)); ++ } else if (worldserver.getFluidState(blockposition).is(FluidTags.WATER)) { + this.setSuccess(true); +- return this.takeLiquid(blocksource, itemstack, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER)); ++ return this.takeLiquid(sourceblock, itemstack, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER)); + } else { +- return super.execute(blocksource, itemstack); ++ return super.execute(sourceblock, itemstack); + } + } + }); + DispenserBlock.registerBehavior(Items.GLOWSTONE, new OptionalDispenseItemBehavior() { + @Override +- @Override +- public ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING); +- BlockPos blockpos = blocksource.pos().relative(direction); +- ServerLevel serverlevel = blocksource.level(); +- BlockState blockstate = serverlevel.getBlockState(blockpos); ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ BlockPos blockposition = sourceblock.pos().relative(enumdirection); ++ ServerLevel worldserver = sourceblock.level(); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); + + this.setSuccess(true); +- if (blockstate.is(Blocks.RESPAWN_ANCHOR)) { +- if ((Integer) blockstate.getValue(RespawnAnchorBlock.CHARGE) != 4) { +- RespawnAnchorBlock.charge((Entity) null, serverlevel, blockpos, blockstate); ++ if (iblockdata.is(Blocks.RESPAWN_ANCHOR)) { ++ if ((Integer) iblockdata.getValue(RespawnAnchorBlock.CHARGE) != 4) { ++ RespawnAnchorBlock.charge((Entity) null, worldserver, blockposition, iblockdata); + itemstack.shrink(1); + } else { + this.setSuccess(false); +@@ -683,28 +1103,27 @@ + + return itemstack; + } else { +- return super.execute(blocksource, itemstack); ++ return super.execute(sourceblock, itemstack); + } + } + }); + DispenserBlock.registerBehavior(Items.SHEARS.asItem(), new ShearsDispenseItemBehavior()); + DispenserBlock.registerBehavior(Items.HONEYCOMB, new OptionalDispenseItemBehavior() { + @Override +- @Override +- public ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING)); +- ServerLevel serverlevel = blocksource.level(); +- BlockState blockstate = serverlevel.getBlockState(blockpos); +- Optional optional = HoneycombItem.getWaxed(blockstate); ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ ServerLevel worldserver = sourceblock.level(); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ Optional optional = HoneycombItem.getWaxed(iblockdata); + + if (optional.isPresent()) { +- serverlevel.setBlockAndUpdate(blockpos, (BlockState) optional.get()); +- serverlevel.levelEvent(3003, blockpos, 0); ++ worldserver.setBlockAndUpdate(blockposition, (IBlockData) optional.get()); ++ worldserver.levelEvent(3003, blockposition, 0); + itemstack.shrink(1); + this.setSuccess(true); + return itemstack; + } else { +- return super.execute(blocksource, itemstack); ++ return super.execute(sourceblock, itemstack); + } + } + }); +@@ -712,27 +1131,26 @@ + private final DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior(); + + @Override +- @Override +- public ItemStack execute(BlockSource blocksource, ItemStack itemstack) { ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { + if (PotionUtils.getPotion(itemstack) != Potions.WATER) { +- return this.defaultDispenseItemBehavior.dispense(blocksource, itemstack); ++ return this.defaultDispenseItemBehavior.dispense(sourceblock, itemstack); + } else { +- ServerLevel serverlevel = blocksource.level(); +- BlockPos blockpos = blocksource.pos(); +- BlockPos blockpos1 = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING)); ++ ServerLevel worldserver = sourceblock.level(); ++ BlockPos blockposition = sourceblock.pos(); ++ BlockPos blockposition1 = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); + +- if (!serverlevel.getBlockState(blockpos1).is(BlockTags.CONVERTABLE_TO_MUD)) { +- return this.defaultDispenseItemBehavior.dispense(blocksource, itemstack); ++ if (!worldserver.getBlockState(blockposition1).is(BlockTags.CONVERTABLE_TO_MUD)) { ++ return this.defaultDispenseItemBehavior.dispense(sourceblock, itemstack); + } else { +- if (!serverlevel.isClientSide) { ++ if (!worldserver.isClientSide) { + for (int k = 0; k < 5; ++k) { +- serverlevel.sendParticles(ParticleTypes.SPLASH, (double) blockpos.getX() + serverlevel.random.nextDouble(), (double) (blockpos.getY() + 1), (double) blockpos.getZ() + serverlevel.random.nextDouble(), 1, 0.0D, 0.0D, 0.0D, 1.0D); ++ worldserver.sendParticles(ParticleTypes.SPLASH, (double) blockposition.getX() + worldserver.random.nextDouble(), (double) (blockposition.getY() + 1), (double) blockposition.getZ() + worldserver.random.nextDouble(), 1, 0.0D, 0.0D, 0.0D, 1.0D); + } + } + +- serverlevel.playSound((Player) null, blockpos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); +- serverlevel.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockpos); +- serverlevel.setBlockAndUpdate(blockpos1, Blocks.MUD.defaultBlockState()); ++ worldserver.playSound((Player) null, blockposition, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); ++ worldserver.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockposition); ++ worldserver.setBlockAndUpdate(blockposition1, Blocks.MUD.defaultBlockState()); + return new ItemStack(Items.GLASS_BOTTLE); + } + } +@@ -740,7 +1158,7 @@ + }); + } + +- static Vec3 getEntityPokingOutOfBlockPos(BlockSource blocksource, EntityType entitytype, Direction direction) { +- return blocksource.center().add((double) direction.getStepX() * (0.5000099999997474D - (double) entitytype.getWidth() / 2.0D), (double) direction.getStepY() * (0.5000099999997474D - (double) entitytype.getHeight() / 2.0D) - (double) entitytype.getHeight() / 2.0D, (double) direction.getStepZ() * (0.5000099999997474D - (double) entitytype.getWidth() / 2.0D)); ++ static Vec3 getEntityPokingOutOfBlockPos(SourceBlock sourceblock, EntityType entitytypes, Direction enumdirection) { ++ return sourceblock.center().add((double) enumdirection.getStepX() * (0.5000099999997474D - (double) entitytypes.getWidth() / 2.0D), (double) enumdirection.getStepY() * (0.5000099999997474D - (double) entitytypes.getHeight() / 2.0D) - (double) entitytypes.getHeight() / 2.0D, (double) enumdirection.getStepZ() * (0.5000099999997474D - (double) entitytypes.getWidth() / 2.0D)); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java.patch b/patch-remap/mache-spigotflower/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java.patch new file mode 100644 index 0000000000..6cc037d13b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java.patch @@ -0,0 +1,125 @@ +--- a/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java ++++ b/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java +@@ -18,24 +18,52 @@ + import net.minecraft.world.level.block.BeehiveBlock; + import net.minecraft.world.level.block.DispenserBlock; + import net.minecraft.world.level.block.entity.BeehiveBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end + + public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior { + + public ShearsDispenseItemBehavior() {} + + @Override +- @Override +- protected ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- ServerLevel serverlevel = blocksource.level(); ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); + +- if (!serverlevel.isClientSide()) { +- BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING)); ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } + +- this.setSuccess(tryShearBeehive(serverlevel, blockpos) || tryShearLivingEntity(serverlevel, blockpos)); +- if (this.isSuccess() && itemstack.hurt(1, serverlevel.getRandom(), (ServerPlayer) null)) { ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ ++ if (!worldserver.isClientSide()) { ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ ++ this.setSuccess(tryShearBeehive(worldserver, blockposition) || tryShearLivingEntity(worldserver, blockposition, bukkitBlock, craftItem)); // CraftBukkit ++ if (this.isSuccess() && itemstack.hurt(1, worldserver.getRandom(), (ServerPlayer) null)) { + itemstack.setCount(0); + } + } +@@ -43,19 +71,19 @@ + return itemstack; + } + +- private static boolean tryShearBeehive(ServerLevel serverlevel, BlockPos blockpos) { +- BlockState blockstate = serverlevel.getBlockState(blockpos); ++ private static boolean tryShearBeehive(ServerLevel level, BlockPos pos) { ++ IBlockData iblockdata = level.getBlockState(pos); + +- if (blockstate.is(BlockTags.BEEHIVES, (blockbehaviour_blockstatebase) -> { +- return blockbehaviour_blockstatebase.hasProperty(BeehiveBlock.HONEY_LEVEL) && blockbehaviour_blockstatebase.getBlock() instanceof BeehiveBlock; ++ if (iblockdata.is(BlockTags.BEEHIVES, (blockbase_blockdata) -> { ++ return blockbase_blockdata.hasProperty(BeehiveBlock.HONEY_LEVEL) && blockbase_blockdata.getBlock() instanceof BeehiveBlock; + })) { +- int i = (Integer) blockstate.getValue(BeehiveBlock.HONEY_LEVEL); ++ int i = (Integer) iblockdata.getValue(BeehiveBlock.HONEY_LEVEL); + + if (i >= 5) { +- serverlevel.playSound((Player) null, blockpos, SoundEvents.BEEHIVE_SHEAR, SoundSource.BLOCKS, 1.0F, 1.0F); +- BeehiveBlock.dropHoneycomb(serverlevel, blockpos); +- ((BeehiveBlock) blockstate.getBlock()).releaseBeesAndResetHoneyLevel(serverlevel, blockstate, blockpos, (Player) null, BeehiveBlockEntity.BeeReleaseStatus.BEE_RELEASED); +- serverlevel.gameEvent((Entity) null, GameEvent.SHEAR, blockpos); ++ level.playSound((Player) null, pos, SoundEvents.BEEHIVE_SHEAR, SoundSource.BLOCKS, 1.0F, 1.0F); ++ BeehiveBlock.dropHoneycomb(level, pos); ++ ((BeehiveBlock) iblockdata.getBlock()).releaseBeesAndResetHoneyLevel(level, iblockdata, pos, (Player) null, BeehiveBlockEntity.ReleaseStatus.BEE_RELEASED); ++ level.gameEvent((Entity) null, GameEvent.SHEAR, pos); + return true; + } + } +@@ -63,19 +91,24 @@ + return false; + } + +- private static boolean tryShearLivingEntity(ServerLevel serverlevel, BlockPos blockpos) { +- List list = serverlevel.getEntitiesOfClass(LivingEntity.class, new AABB(blockpos), EntitySelector.NO_SPECTATORS); ++ private static boolean tryShearLivingEntity(ServerLevel worldserver, BlockPos blockposition, org.bukkit.block.Block bukkitBlock, CraftItemStack craftItem) { // CraftBukkit - add args ++ List list = worldserver.getEntitiesOfClass(LivingEntity.class, new AABB(blockposition), EntitySelector.NO_SPECTATORS); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- LivingEntity livingentity = (LivingEntity) iterator.next(); ++ LivingEntity entityliving = (LivingEntity) iterator.next(); + +- if (livingentity instanceof Shearable) { +- Shearable shearable = (Shearable) livingentity; ++ if (entityliving instanceof Shearable) { ++ Shearable ishearable = (Shearable) entityliving; + +- if (shearable.readyForShearing()) { +- shearable.shear(SoundSource.BLOCKS); +- serverlevel.gameEvent((Entity) null, GameEvent.SHEAR, blockpos); ++ if (ishearable.readyForShearing()) { ++ // CraftBukkit start ++ if (CraftEventFactory.callBlockShearEntityEvent(entityliving, bukkitBlock, craftItem).isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end ++ ishearable.shear(SoundSource.BLOCKS); ++ worldserver.gameEvent((Entity) null, GameEvent.SHEAR, blockposition); + return true; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java.patch b/patch-remap/mache-spigotflower/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java.patch new file mode 100644 index 0000000000..0ceec22a3c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java.patch @@ -0,0 +1,66 @@ +--- a/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java ++++ b/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java +@@ -10,6 +10,12 @@ + import net.minecraft.world.level.block.DispenserBlock; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end ++ + public class ShulkerBoxDispenseBehavior extends OptionalDispenseItemBehavior { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -17,20 +23,43 @@ + public ShulkerBoxDispenseBehavior() {} + + @Override +- @Override +- protected ItemStack execute(BlockSource blocksource, ItemStack itemstack) { ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { + this.setSuccess(false); + Item item = itemstack.getItem(); + + if (item instanceof BlockItem) { +- Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING); +- BlockPos blockpos = blocksource.pos().relative(direction); +- Direction direction1 = blocksource.level().isEmptyBlock(blockpos.below()) ? direction : Direction.UP; ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ BlockPos blockposition = sourceblock.pos().relative(enumdirection); ++ Direction enumdirection1 = sourceblock.level().isEmptyBlock(blockposition.below()) ? enumdirection : Direction.UP; + ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(sourceblock.level(), sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!DispenserBlock.eventFired) { ++ sourceblock.level().getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ + try { +- this.setSuccess(((BlockItem) item).place(new DirectionalPlaceContext(blocksource.level(), blockpos, direction, itemstack, direction1)).consumesAction()); ++ this.setSuccess(((BlockItem) item).place(new DirectionalPlaceContext(sourceblock.level(), blockposition, enumdirection, itemstack, enumdirection1)).consumesAction()); + } catch (Exception exception) { +- ShulkerBoxDispenseBehavior.LOGGER.error("Error trying to place shulker box at {}", blockpos, exception); ++ ShulkerBoxDispenseBehavior.LOGGER.error("Error trying to place shulker box at {}", blockposition, exception); + } + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/nbt/ByteArrayTag.java.patch b/patch-remap/mache-spigotflower/net/minecraft/nbt/ByteArrayTag.java.patch new file mode 100644 index 0000000000..e4704b8164 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/nbt/ByteArrayTag.java.patch @@ -0,0 +1,238 @@ +--- a/net/minecraft/nbt/ByteArrayTag.java ++++ b/net/minecraft/nbt/ByteArrayTag.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.nbt; + + import java.io.DataInput; +@@ -10,24 +11,22 @@ + public class ByteArrayTag extends CollectionTag { + + private static final int SELF_SIZE_IN_BYTES = 24; +- public static final TagType TYPE = new TagType.VariableSize() { ++ public static final TagType TYPE = new TagType.b() { + @Override +- @Override +- public ByteArrayTag load(DataInput datainput, NbtAccounter nbtaccounter) throws IOException { +- return new ByteArrayTag(readAccounted(datainput, nbtaccounter)); ++ public ByteArrayTag load(DataInput datainput, NbtAccounter nbtreadlimiter) throws IOException { ++ return new ByteArrayTag(readAccounted(datainput, nbtreadlimiter)); + } + + @Override +- @Override +- public StreamTagVisitor.ValueResult parse(DataInput datainput, StreamTagVisitor streamtagvisitor, NbtAccounter nbtaccounter) throws IOException { +- return streamtagvisitor.visit(readAccounted(datainput, nbtaccounter)); ++ public StreamTagVisitor.b parse(DataInput datainput, StreamTagVisitor streamtagvisitor, NbtAccounter nbtreadlimiter) throws IOException { ++ return streamtagvisitor.visit(readAccounted(datainput, nbtreadlimiter)); + } + +- private static byte[] readAccounted(DataInput datainput, NbtAccounter nbtaccounter) throws IOException { +- nbtaccounter.accountBytes(24L); ++ private static byte[] readAccounted(DataInput datainput, NbtAccounter nbtreadlimiter) throws IOException { ++ nbtreadlimiter.accountBytes(24L); + int i = datainput.readInt(); + +- nbtaccounter.accountBytes(1L, (long) i); ++ nbtreadlimiter.accountBytes(1L, (long) i); + byte[] abyte = new byte[i]; + + datainput.readFully(abyte); +@@ -35,38 +34,35 @@ + } + + @Override +- @Override +- public void skip(DataInput datainput, NbtAccounter nbtaccounter) throws IOException { ++ public void skip(DataInput datainput, NbtAccounter nbtreadlimiter) throws IOException { + datainput.skipBytes(datainput.readInt() * 1); + } + + @Override +- @Override + public String getName() { + return "BYTE[]"; + } + + @Override +- @Override + public String getPrettyName() { + return "TAG_Byte_Array"; + } + }; + private byte[] data; + +- public ByteArrayTag(byte[] abyte) { +- this.data = abyte; ++ public ByteArrayTag(byte[] data) { ++ this.data = data; + } + +- public ByteArrayTag(List list) { +- this(toArray(list)); ++ public ByteArrayTag(List dataList) { ++ this(toArray(dataList)); + } + +- private static byte[] toArray(List list) { +- byte[] abyte = new byte[list.size()]; ++ private static byte[] toArray(List dataList) { ++ byte[] abyte = new byte[dataList.size()]; + +- for (int i = 0; i < list.size(); ++i) { +- Byte obyte = (Byte) list.get(i); ++ for (int i = 0; i < dataList.size(); ++i) { ++ Byte obyte = (Byte) dataList.get(i); + + abyte[i] = obyte == null ? 0 : obyte; + } +@@ -75,38 +71,32 @@ + } + + @Override +- @Override +- public void write(DataOutput dataoutput) throws IOException { +- dataoutput.writeInt(this.data.length); +- dataoutput.write(this.data); ++ public void write(DataOutput output) throws IOException { ++ output.writeInt(this.data.length); ++ output.write(this.data); + } + + @Override +- @Override + public int sizeInBytes() { + return 24 + 1 * this.data.length; + } + + @Override +- @Override + public byte getId() { + return 7; + } + + @Override +- @Override + public TagType getType() { + return ByteArrayTag.TYPE; + } + + @Override +- @Override + public String toString() { + return this.getAsString(); + } + + @Override +- @Override + public Tag copy() { + byte[] abyte = new byte[this.data.length]; + +@@ -114,54 +104,46 @@ + return new ByteArrayTag(abyte); + } + +- @Override + public boolean equals(Object object) { + return this == object ? true : object instanceof ByteArrayTag && Arrays.equals(this.data, ((ByteArrayTag) object).data); + } + +- @Override + public int hashCode() { + return Arrays.hashCode(this.data); + } + + @Override +- @Override +- public void accept(TagVisitor tagvisitor) { +- tagvisitor.visitByteArray(this); ++ public void accept(TagVisitor visitor) { ++ visitor.visitByteArray(this); + } + + public byte[] getAsByteArray() { + return this.data; + } + +- @Override + public int size() { + return this.data.length; + } + +- @Override + public ByteTag get(int i) { + return ByteTag.valueOf(this.data[i]); + } + +- @Override +- public ByteTag set(int i, ByteTag bytetag) { ++ public ByteTag set(int i, ByteTag nbttagbyte) { + byte b0 = this.data[i]; + +- this.data[i] = bytetag.getAsByte(); ++ this.data[i] = nbttagbyte.getAsByte(); + return ByteTag.valueOf(b0); + } + +- @Override +- public void add(int i, ByteTag bytetag) { +- this.data = ArrayUtils.add(this.data, i, bytetag.getAsByte()); ++ public void add(int i, ByteTag nbttagbyte) { ++ this.data = ArrayUtils.add(this.data, i, nbttagbyte.getAsByte()); + } + + @Override +- @Override +- public boolean setTag(int i, Tag tag) { +- if (tag instanceof NumericTag) { +- this.data[i] = ((NumericTag) tag).getAsByte(); ++ public boolean setTag(int index, Tag nbt) { ++ if (nbt instanceof NBTNumber) { ++ this.data[index] = ((NBTNumber) nbt).getAsByte(); + return true; + } else { + return false; +@@ -169,10 +151,9 @@ + } + + @Override +- @Override +- public boolean addTag(int i, Tag tag) { +- if (tag instanceof NumericTag) { +- this.data = ArrayUtils.add(this.data, i, ((NumericTag) tag).getAsByte()); ++ public boolean addTag(int index, Tag nbt) { ++ if (nbt instanceof NBTNumber) { ++ this.data = ArrayUtils.add(this.data, index, ((NBTNumber) nbt).getAsByte()); + return true; + } else { + return false; +@@ -180,7 +161,6 @@ + } + + @Override +- @Override + public ByteTag remove(int i) { + byte b0 = this.data[i]; + +@@ -189,19 +169,16 @@ + } + + @Override +- @Override + public byte getElementType() { + return 1; + } + +- @Override + public void clear() { + this.data = new byte[0]; + } + + @Override +- @Override +- public StreamTagVisitor.ValueResult accept(StreamTagVisitor streamtagvisitor) { +- return streamtagvisitor.visit(this.data); ++ public StreamTagVisitor.b accept(StreamTagVisitor visitor) { ++ return visitor.visit(this.data); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/nbt/IntArrayTag.java.patch b/patch-remap/mache-spigotflower/net/minecraft/nbt/IntArrayTag.java.patch new file mode 100644 index 0000000000..c613bd510f --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/nbt/IntArrayTag.java.patch @@ -0,0 +1,244 @@ +--- a/net/minecraft/nbt/IntArrayTag.java ++++ b/net/minecraft/nbt/IntArrayTag.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.nbt; + + import java.io.DataInput; +@@ -10,24 +11,22 @@ + public class IntArrayTag extends CollectionTag { + + private static final int SELF_SIZE_IN_BYTES = 24; +- public static final TagType TYPE = new TagType.VariableSize() { ++ public static final TagType TYPE = new TagType.b() { + @Override +- @Override +- public IntArrayTag load(DataInput datainput, NbtAccounter nbtaccounter) throws IOException { +- return new IntArrayTag(readAccounted(datainput, nbtaccounter)); ++ public IntArrayTag load(DataInput datainput, NbtAccounter nbtreadlimiter) throws IOException { ++ return new IntArrayTag(readAccounted(datainput, nbtreadlimiter)); + } + + @Override +- @Override +- public StreamTagVisitor.ValueResult parse(DataInput datainput, StreamTagVisitor streamtagvisitor, NbtAccounter nbtaccounter) throws IOException { +- return streamtagvisitor.visit(readAccounted(datainput, nbtaccounter)); ++ public StreamTagVisitor.b parse(DataInput datainput, StreamTagVisitor streamtagvisitor, NbtAccounter nbtreadlimiter) throws IOException { ++ return streamtagvisitor.visit(readAccounted(datainput, nbtreadlimiter)); + } + +- private static int[] readAccounted(DataInput datainput, NbtAccounter nbtaccounter) throws IOException { +- nbtaccounter.accountBytes(24L); ++ private static int[] readAccounted(DataInput datainput, NbtAccounter nbtreadlimiter) throws IOException { ++ nbtreadlimiter.accountBytes(24L); + int i = datainput.readInt(); + +- nbtaccounter.accountBytes(4L, (long) i); ++ nbtreadlimiter.accountBytes(4L, (long) i); + int[] aint = new int[i]; + + for (int j = 0; j < i; ++j) { +@@ -38,38 +37,35 @@ + } + + @Override +- @Override +- public void skip(DataInput datainput, NbtAccounter nbtaccounter) throws IOException { ++ public void skip(DataInput datainput, NbtAccounter nbtreadlimiter) throws IOException { + datainput.skipBytes(datainput.readInt() * 4); + } + + @Override +- @Override + public String getName() { + return "INT[]"; + } + + @Override +- @Override + public String getPrettyName() { + return "TAG_Int_Array"; + } + }; + private int[] data; + +- public IntArrayTag(int[] aint) { +- this.data = aint; ++ public IntArrayTag(int[] data) { ++ this.data = data; + } + +- public IntArrayTag(List list) { +- this(toArray(list)); ++ public IntArrayTag(List dataList) { ++ this(toArray(dataList)); + } + +- private static int[] toArray(List list) { +- int[] aint = new int[list.size()]; ++ private static int[] toArray(List dataList) { ++ int[] aint = new int[dataList.size()]; + +- for (int i = 0; i < list.size(); ++i) { +- Integer integer = (Integer) list.get(i); ++ for (int i = 0; i < dataList.size(); ++i) { ++ Integer integer = (Integer) dataList.get(i); + + aint[i] = integer == null ? 0 : integer; + } +@@ -78,46 +74,40 @@ + } + + @Override +- @Override +- public void write(DataOutput dataoutput) throws IOException { +- dataoutput.writeInt(this.data.length); ++ public void write(DataOutput output) throws IOException { ++ output.writeInt(this.data.length); + int[] aint = this.data; + int i = aint.length; + + for (int j = 0; j < i; ++j) { + int k = aint[j]; + +- dataoutput.writeInt(k); ++ output.writeInt(k); + } + + } + + @Override +- @Override + public int sizeInBytes() { + return 24 + 4 * this.data.length; + } + + @Override +- @Override + public byte getId() { + return 11; + } + + @Override +- @Override + public TagType getType() { + return IntArrayTag.TYPE; + } + + @Override +- @Override + public String toString() { + return this.getAsString(); + } + + @Override +- @Override + public IntArrayTag copy() { + int[] aint = new int[this.data.length]; + +@@ -125,12 +115,10 @@ + return new IntArrayTag(aint); + } + +- @Override + public boolean equals(Object object) { + return this == object ? true : object instanceof IntArrayTag && Arrays.equals(this.data, ((IntArrayTag) object).data); + } + +- @Override + public int hashCode() { + return Arrays.hashCode(this.data); + } +@@ -140,39 +128,33 @@ + } + + @Override +- @Override +- public void accept(TagVisitor tagvisitor) { +- tagvisitor.visitIntArray(this); ++ public void accept(TagVisitor visitor) { ++ visitor.visitIntArray(this); + } + +- @Override + public int size() { + return this.data.length; + } + +- @Override + public IntTag get(int i) { + return IntTag.valueOf(this.data[i]); + } + +- @Override +- public IntTag set(int i, IntTag inttag) { ++ public IntTag set(int i, IntTag nbttagint) { + int j = this.data[i]; + +- this.data[i] = inttag.getAsInt(); ++ this.data[i] = nbttagint.getAsInt(); + return IntTag.valueOf(j); + } + +- @Override +- public void add(int i, IntTag inttag) { +- this.data = ArrayUtils.add(this.data, i, inttag.getAsInt()); ++ public void add(int i, IntTag nbttagint) { ++ this.data = ArrayUtils.add(this.data, i, nbttagint.getAsInt()); + } + + @Override +- @Override +- public boolean setTag(int i, Tag tag) { +- if (tag instanceof NumericTag) { +- this.data[i] = ((NumericTag) tag).getAsInt(); ++ public boolean setTag(int index, Tag nbt) { ++ if (nbt instanceof NBTNumber) { ++ this.data[index] = ((NBTNumber) nbt).getAsInt(); + return true; + } else { + return false; +@@ -180,10 +162,9 @@ + } + + @Override +- @Override +- public boolean addTag(int i, Tag tag) { +- if (tag instanceof NumericTag) { +- this.data = ArrayUtils.add(this.data, i, ((NumericTag) tag).getAsInt()); ++ public boolean addTag(int index, Tag nbt) { ++ if (nbt instanceof NBTNumber) { ++ this.data = ArrayUtils.add(this.data, index, ((NBTNumber) nbt).getAsInt()); + return true; + } else { + return false; +@@ -191,7 +172,6 @@ + } + + @Override +- @Override + public IntTag remove(int i) { + int j = this.data[i]; + +@@ -200,19 +180,16 @@ + } + + @Override +- @Override + public byte getElementType() { + return 3; + } + +- @Override + public void clear() { + this.data = new int[0]; + } + + @Override +- @Override +- public StreamTagVisitor.ValueResult accept(StreamTagVisitor streamtagvisitor) { +- return streamtagvisitor.visit(this.data); ++ public StreamTagVisitor.b accept(StreamTagVisitor visitor) { ++ return visitor.visit(this.data); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/nbt/NbtIo.java.patch b/patch-remap/mache-spigotflower/net/minecraft/nbt/NbtIo.java.patch new file mode 100644 index 0000000000..7cd362d049 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/nbt/NbtIo.java.patch @@ -0,0 +1,299 @@ +--- a/net/minecraft/nbt/NbtIo.java ++++ b/net/minecraft/nbt/NbtIo.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.nbt; + + import java.io.BufferedOutputStream; +@@ -29,13 +30,13 @@ + + public NbtIo() {} + +- public static CompoundTag readCompressed(Path path, NbtAccounter nbtaccounter) throws IOException { ++ public static CompoundTag readCompressed(Path path, NbtAccounter nbtreadlimiter) throws IOException { + InputStream inputstream = Files.newInputStream(path); + +- CompoundTag compoundtag; ++ CompoundTag nbttagcompound; + + try { +- compoundtag = readCompressed(inputstream, nbtaccounter); ++ nbttagcompound = readCompressed(inputstream, nbtreadlimiter); + } catch (Throwable throwable) { + if (inputstream != null) { + try { +@@ -52,24 +53,24 @@ + inputstream.close(); + } + +- return compoundtag; ++ return nbttagcompound; + } + +- private static DataInputStream createDecompressorStream(InputStream inputstream) throws IOException { +- return new DataInputStream(new FastBufferedInputStream(new GZIPInputStream(inputstream))); ++ private static DataInputStream createDecompressorStream(InputStream zippedStream) throws IOException { ++ return new DataInputStream(new FastBufferedInputStream(new GZIPInputStream(zippedStream))); + } + + private static DataOutputStream createCompressorStream(OutputStream outputstream) throws IOException { + return new DataOutputStream(new BufferedOutputStream(new GZIPOutputStream(outputstream))); + } + +- public static CompoundTag readCompressed(InputStream inputstream, NbtAccounter nbtaccounter) throws IOException { ++ public static CompoundTag readCompressed(InputStream inputstream, NbtAccounter nbtreadlimiter) throws IOException { + DataInputStream datainputstream = createDecompressorStream(inputstream); + +- CompoundTag compoundtag; ++ CompoundTag nbttagcompound; + + try { +- compoundtag = read(datainputstream, nbtaccounter); ++ nbttagcompound = read(datainputstream, nbtreadlimiter); + } catch (Throwable throwable) { + if (datainputstream != null) { + try { +@@ -86,14 +87,14 @@ + datainputstream.close(); + } + +- return compoundtag; ++ return nbttagcompound; + } + +- public static void parseCompressed(Path path, StreamTagVisitor streamtagvisitor, NbtAccounter nbtaccounter) throws IOException { ++ public static void parseCompressed(Path path, StreamTagVisitor streamtagvisitor, NbtAccounter nbtreadlimiter) throws IOException { + InputStream inputstream = Files.newInputStream(path); + + try { +- parseCompressed(inputstream, streamtagvisitor, nbtaccounter); ++ parseCompressed(inputstream, streamtagvisitor, nbtreadlimiter); + } catch (Throwable throwable) { + if (inputstream != null) { + try { +@@ -112,11 +113,11 @@ + + } + +- public static void parseCompressed(InputStream inputstream, StreamTagVisitor streamtagvisitor, NbtAccounter nbtaccounter) throws IOException { ++ public static void parseCompressed(InputStream inputstream, StreamTagVisitor streamtagvisitor, NbtAccounter nbtreadlimiter) throws IOException { + DataInputStream datainputstream = createDecompressorStream(inputstream); + + try { +- parse(datainputstream, streamtagvisitor, nbtaccounter); ++ parse(datainputstream, streamtagvisitor, nbtreadlimiter); + } catch (Throwable throwable) { + if (datainputstream != null) { + try { +@@ -135,14 +136,14 @@ + + } + +- public static void writeCompressed(CompoundTag compoundtag, Path path) throws IOException { ++ public static void writeCompressed(CompoundTag nbttagcompound, Path path) throws IOException { + OutputStream outputstream = Files.newOutputStream(path, NbtIo.SYNC_OUTPUT_OPTIONS); + + try { + BufferedOutputStream bufferedoutputstream = new BufferedOutputStream(outputstream); + + try { +- writeCompressed(compoundtag, (OutputStream) bufferedoutputstream); ++ writeCompressed(nbttagcompound, (OutputStream) bufferedoutputstream); + } catch (Throwable throwable) { + try { + bufferedoutputstream.close(); +@@ -172,11 +173,11 @@ + + } + +- public static void writeCompressed(CompoundTag compoundtag, OutputStream outputstream) throws IOException { +- DataOutputStream dataoutputstream = createCompressorStream(outputstream); ++ public static void writeCompressed(CompoundTag compoundTag, OutputStream outputStream) throws IOException { ++ DataOutputStream dataoutputstream = createCompressorStream(outputStream); + + try { +- write(compoundtag, (DataOutput) dataoutputstream); ++ write(compoundTag, (DataOutput) dataoutputstream); + } catch (Throwable throwable) { + if (dataoutputstream != null) { + try { +@@ -195,7 +196,7 @@ + + } + +- public static void write(CompoundTag compoundtag, Path path) throws IOException { ++ public static void write(CompoundTag nbttagcompound, Path path) throws IOException { + OutputStream outputstream = Files.newOutputStream(path, NbtIo.SYNC_OUTPUT_OPTIONS); + + try { +@@ -205,7 +206,7 @@ + DataOutputStream dataoutputstream = new DataOutputStream(bufferedoutputstream); + + try { +- write(compoundtag, (DataOutput) dataoutputstream); ++ write(nbttagcompound, (DataOutput) dataoutputstream); + } catch (Throwable throwable) { + try { + dataoutputstream.close(); +@@ -253,13 +254,13 @@ + } else { + InputStream inputstream = Files.newInputStream(path); + +- CompoundTag compoundtag; ++ CompoundTag nbttagcompound; + + try { + DataInputStream datainputstream = new DataInputStream(inputstream); + + try { +- compoundtag = read(datainputstream, NbtAccounter.unlimitedHeap()); ++ nbttagcompound = read(datainputstream, NbtAccounter.unlimitedHeap()); + } catch (Throwable throwable) { + try { + datainputstream.close(); +@@ -287,109 +288,108 @@ + inputstream.close(); + } + +- return compoundtag; ++ return nbttagcompound; + } + } + +- public static CompoundTag read(DataInput datainput) throws IOException { +- return read(datainput, NbtAccounter.unlimitedHeap()); ++ public static CompoundTag read(DataInput input) throws IOException { ++ return read(input, NbtAccounter.unlimitedHeap()); + } + +- public static CompoundTag read(DataInput datainput, NbtAccounter nbtaccounter) throws IOException { +- Tag tag = readUnnamedTag(datainput, nbtaccounter); ++ public static CompoundTag read(DataInput input, NbtAccounter accounter) throws IOException { ++ Tag nbtbase = readUnnamedTag(input, accounter); + +- if (tag instanceof CompoundTag) { +- return (CompoundTag) tag; ++ if (nbtbase instanceof CompoundTag) { ++ return (CompoundTag) nbtbase; + } else { + throw new IOException("Root tag must be a named compound tag"); + } + } + +- public static void write(CompoundTag compoundtag, DataOutput dataoutput) throws IOException { +- writeUnnamedTagWithFallback(compoundtag, dataoutput); ++ public static void write(CompoundTag compoundTag, DataOutput output) throws IOException { ++ writeUnnamedTagWithFallback(compoundTag, output); + } + +- public static void parse(DataInput datainput, StreamTagVisitor streamtagvisitor, NbtAccounter nbtaccounter) throws IOException { +- TagType tagtype = TagTypes.getType(datainput.readByte()); ++ public static void parse(DataInput datainput, StreamTagVisitor streamtagvisitor, NbtAccounter nbtreadlimiter) throws IOException { ++ TagType nbttagtype = TagTypes.getType(datainput.readByte()); + +- if (tagtype == EndTag.TYPE) { +- if (streamtagvisitor.visitRootEntry(EndTag.TYPE) == StreamTagVisitor.ValueResult.CONTINUE) { ++ if (nbttagtype == EndTag.TYPE) { ++ if (streamtagvisitor.visitRootEntry(EndTag.TYPE) == StreamTagVisitor.b.CONTINUE) { + streamtagvisitor.visitEnd(); + } + + } else { +- switch (streamtagvisitor.visitRootEntry(tagtype)) { ++ switch (streamtagvisitor.visitRootEntry(nbttagtype)) { + case HALT: + default: + break; + case BREAK: + StringTag.skipString(datainput); +- tagtype.skip(datainput, nbtaccounter); ++ nbttagtype.skip(datainput, nbtreadlimiter); + break; + case CONTINUE: + StringTag.skipString(datainput); +- tagtype.parse(datainput, streamtagvisitor, nbtaccounter); ++ nbttagtype.parse(datainput, streamtagvisitor, nbtreadlimiter); + } + + } + } + +- public static Tag readAnyTag(DataInput datainput, NbtAccounter nbtaccounter) throws IOException { ++ public static Tag readAnyTag(DataInput datainput, NbtAccounter nbtreadlimiter) throws IOException { + byte b0 = datainput.readByte(); + +- return (Tag) (b0 == 0 ? EndTag.INSTANCE : readTagSafe(datainput, nbtaccounter, b0)); ++ return (Tag) (b0 == 0 ? EndTag.INSTANCE : readTagSafe(datainput, nbtreadlimiter, b0)); + } + +- public static void writeAnyTag(Tag tag, DataOutput dataoutput) throws IOException { +- dataoutput.writeByte(tag.getId()); +- if (tag.getId() != 0) { +- tag.write(dataoutput); ++ public static void writeAnyTag(Tag nbtbase, DataOutput dataoutput) throws IOException { ++ dataoutput.writeByte(nbtbase.getId()); ++ if (nbtbase.getId() != 0) { ++ nbtbase.write(dataoutput); + } + } + +- public static void writeUnnamedTag(Tag tag, DataOutput dataoutput) throws IOException { +- dataoutput.writeByte(tag.getId()); ++ public static void writeUnnamedTag(Tag tag, DataOutput output) throws IOException { ++ output.writeByte(tag.getId()); + if (tag.getId() != 0) { +- dataoutput.writeUTF(""); +- tag.write(dataoutput); ++ output.writeUTF(""); ++ tag.write(output); + } + } + +- public static void writeUnnamedTagWithFallback(Tag tag, DataOutput dataoutput) throws IOException { +- writeUnnamedTag(tag, new NbtIo.StringFallbackDataOutput(dataoutput)); ++ public static void writeUnnamedTagWithFallback(Tag nbtbase, DataOutput dataoutput) throws IOException { ++ writeUnnamedTag(nbtbase, new NbtIo.a(dataoutput)); + } + +- private static Tag readUnnamedTag(DataInput datainput, NbtAccounter nbtaccounter) throws IOException { ++ private static Tag readUnnamedTag(DataInput datainput, NbtAccounter nbtreadlimiter) throws IOException { + byte b0 = datainput.readByte(); + + if (b0 == 0) { + return EndTag.INSTANCE; + } else { + StringTag.skipString(datainput); +- return readTagSafe(datainput, nbtaccounter, b0); ++ return readTagSafe(datainput, nbtreadlimiter, b0); + } + } + +- private static Tag readTagSafe(DataInput datainput, NbtAccounter nbtaccounter, byte b0) { ++ private static Tag readTagSafe(DataInput datainput, NbtAccounter nbtreadlimiter, byte b0) { + try { +- return TagTypes.getType(b0).load(datainput, nbtaccounter); ++ return TagTypes.getType(b0).load(datainput, nbtreadlimiter); + } catch (IOException ioexception) { + CrashReport crashreport = CrashReport.forThrowable(ioexception, "Loading NBT data"); +- CrashReportCategory crashreportcategory = crashreport.addCategory("NBT Tag"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("NBT Tag"); + +- crashreportcategory.setDetail("Tag type", (Object) b0); ++ crashreportsystemdetails.setDetail("Tag type", (Object) b0); + throw new ReportedNbtException(crashreport); + } + } + +- public static class StringFallbackDataOutput extends DelegateDataOutput { ++ public static class a extends DelegateDataOutput { + +- public StringFallbackDataOutput(DataOutput dataoutput) { ++ public a(DataOutput dataoutput) { + super(dataoutput); + } + + @Override +- @Override + public void writeUTF(String s) throws IOException { + try { + super.writeUTF(s); diff --git a/patch-remap/mache-spigotflower/net/minecraft/network/Connection.java.patch b/patch-remap/mache-spigotflower/net/minecraft/network/Connection.java.patch new file mode 100644 index 0000000000..e15b114d99 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/network/Connection.java.patch @@ -0,0 +1,386 @@ +--- a/net/minecraft/network/Connection.java ++++ b/net/minecraft/network/Connection.java +@@ -50,7 +50,7 @@ + import net.minecraft.network.protocol.login.ClientLoginPacketListener; + import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket; + import net.minecraft.network.protocol.status.ClientStatusPacketListener; +-import net.minecraft.server.RunningOnDifferentThreadException; ++import net.minecraft.server.CancelledPacketHandleException; + import net.minecraft.util.Mth; + import net.minecraft.util.SampleLogger; + import org.apache.commons.lang3.Validate; +@@ -72,8 +72,8 @@ + public static final Marker PACKET_SENT_MARKER = (Marker) Util.make(MarkerFactory.getMarker("PACKET_SENT"), (marker) -> { + marker.add(Connection.PACKET_MARKER); + }); +- public static final AttributeKey> ATTRIBUTE_SERVERBOUND_PROTOCOL = AttributeKey.valueOf("serverbound_protocol"); +- public static final AttributeKey> ATTRIBUTE_CLIENTBOUND_PROTOCOL = AttributeKey.valueOf("clientbound_protocol"); ++ public static final AttributeKey> ATTRIBUTE_SERVERBOUND_PROTOCOL = AttributeKey.valueOf("serverbound_protocol"); ++ public static final AttributeKey> ATTRIBUTE_CLIENTBOUND_PROTOCOL = AttributeKey.valueOf("clientbound_protocol"); + public static final Supplier NETWORK_WORKER_GROUP = Suppliers.memoize(() -> { + return new NioEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Client IO #%d").setDaemon(true).build()); + }); +@@ -85,8 +85,8 @@ + }); + private final PacketFlow receiving; + private final Queue> pendingActions = Queues.newConcurrentLinkedQueue(); +- private Channel channel; +- private SocketAddress address; ++ public Channel channel; ++ public SocketAddress address; + @Nullable + private volatile PacketListener disconnectListener; + @Nullable +@@ -105,12 +105,12 @@ + private volatile Component delayedDisconnect; + @Nullable + BandwidthDebugMonitor bandwidthDebugMonitor; ++ public String hostname = ""; // CraftBukkit - add field + +- public Connection(PacketFlow packetflow) { +- this.receiving = packetflow; ++ public Connection(PacketFlow receiving) { ++ this.receiving = receiving; + } + +- @Override + public void channelActive(ChannelHandlerContext channelhandlercontext) throws Exception { + super.channelActive(channelhandlercontext); + this.channel = channelhandlercontext.channel(); +@@ -126,12 +126,10 @@ + channel.attr(Connection.ATTRIBUTE_CLIENTBOUND_PROTOCOL).set(ConnectionProtocol.HANDSHAKING.codec(PacketFlow.CLIENTBOUND)); + } + +- @Override + public void channelInactive(ChannelHandlerContext channelhandlercontext) { + this.disconnect(Component.translatable("disconnect.endOfStream")); + } + +- @Override + public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) { + if (throwable instanceof SkipPacketException) { + Connection.LOGGER.debug("Skipping packet due to errors", throwable.getCause()); +@@ -144,25 +142,25 @@ + Connection.LOGGER.debug("Timeout", throwable); + this.disconnect(Component.translatable("disconnect.timeout")); + } else { +- MutableComponent mutablecomponent = Component.translatable("disconnect.genericReason", "Internal Exception: " + throwable); ++ MutableComponent ichatmutablecomponent = Component.translatable("disconnect.genericReason", "Internal Exception: " + throwable); + + if (flag) { + Connection.LOGGER.debug("Failed to sent packet", throwable); + if (this.getSending() == PacketFlow.CLIENTBOUND) { +- ConnectionProtocol connectionprotocol = ((ConnectionProtocol.CodecData) this.channel.attr(Connection.ATTRIBUTE_CLIENTBOUND_PROTOCOL).get()).protocol(); +- Packet packet = connectionprotocol == ConnectionProtocol.LOGIN ? new ClientboundLoginDisconnectPacket(mutablecomponent) : new ClientboundDisconnectPacket(mutablecomponent); ++ ConnectionProtocol enumprotocol = ((ConnectionProtocol.a) this.channel.attr(Connection.ATTRIBUTE_CLIENTBOUND_PROTOCOL).get()).protocol(); ++ Packet packet = enumprotocol == ConnectionProtocol.LOGIN ? new ClientboundLoginDisconnectPacket(ichatmutablecomponent) : new ClientboundDisconnectPacket(ichatmutablecomponent); + + this.send((Packet) packet, PacketSendListener.thenRun(() -> { +- this.disconnect(mutablecomponent); ++ this.disconnect(ichatmutablecomponent); + })); + } else { +- this.disconnect(mutablecomponent); ++ this.disconnect(ichatmutablecomponent); + } + + this.setReadOnly(); + } else { + Connection.LOGGER.debug("Double fault", throwable); +- this.disconnect(mutablecomponent); ++ this.disconnect(ichatmutablecomponent); + } + } + +@@ -170,8 +168,7 @@ + } + } + +- @Override +- protected void channelRead0(ChannelHandlerContext channelhandlercontext, Packet packet) { ++ protected void channelRead0(ChannelHandlerContext context, Packet packet) { + if (this.channel.isOpen()) { + PacketListener packetlistener = this.packetListener; + +@@ -181,7 +178,7 @@ + if (packetlistener.shouldHandleMessage(packet)) { + try { + genericsFtw(packet, packetlistener); +- } catch (RunningOnDifferentThreadException runningondifferentthreadexception) { ++ } catch (CancelledPacketHandleException cancelledpackethandleexception) { + ; + } catch (RejectedExecutionException rejectedexecutionexception) { + this.disconnect(Component.translatable("multiplayer.disconnect.server_shutdown")); +@@ -197,8 +194,8 @@ + } + } + +- private static void genericsFtw(Packet packet, PacketListener packetlistener) { +- packet.handle(packetlistener); ++ private static void genericsFtw(Packet packet, PacketListener listener) { ++ packet.handle((T) listener); // CraftBukkit - decompile error + } + + public void suspendInboundAfterProtocolChange() { +@@ -209,20 +206,20 @@ + this.channel.config().setAutoRead(true); + } + +- public void setListener(PacketListener packetlistener) { +- Validate.notNull(packetlistener, "packetListener", new Object[0]); +- PacketFlow packetflow = packetlistener.flow(); ++ public void setListener(PacketListener handler) { ++ Validate.notNull(handler, "packetListener", new Object[0]); ++ PacketFlow enumprotocoldirection = handler.flow(); + +- if (packetflow != this.receiving) { +- throw new IllegalStateException("Trying to set listener for wrong side: connection is " + this.receiving + ", but listener is " + packetflow); ++ if (enumprotocoldirection != this.receiving) { ++ throw new IllegalStateException("Trying to set listener for wrong side: connection is " + this.receiving + ", but listener is " + enumprotocoldirection); + } else { +- ConnectionProtocol connectionprotocol = packetlistener.protocol(); +- ConnectionProtocol connectionprotocol1 = ((ConnectionProtocol.CodecData) this.channel.attr(getProtocolKey(packetflow)).get()).protocol(); ++ ConnectionProtocol enumprotocol = handler.protocol(); ++ ConnectionProtocol enumprotocol1 = ((ConnectionProtocol.a) this.channel.attr(getProtocolKey(enumprotocoldirection)).get()).protocol(); + +- if (connectionprotocol1 != connectionprotocol) { +- throw new IllegalStateException("Trying to set listener for protocol " + connectionprotocol.id() + ", but current " + packetflow + " protocol is " + connectionprotocol1.id()); ++ if (enumprotocol1 != enumprotocol) { ++ throw new IllegalStateException("Trying to set listener for protocol " + enumprotocol.id() + ", but current " + enumprotocoldirection + " protocol is " + enumprotocol1.id()); + } else { +- this.packetListener = packetlistener; ++ this.packetListener = handler; + this.disconnectListener = null; + } + } +@@ -238,20 +235,20 @@ + } + } + +- public void initiateServerboundStatusConnection(String s, int i, ClientStatusPacketListener clientstatuspacketlistener) { +- this.initiateServerboundConnection(s, i, clientstatuspacketlistener, ClientIntent.STATUS); ++ public void initiateServerboundStatusConnection(String s, int i, ClientStatusPacketListener packetstatusoutlistener) { ++ this.initiateServerboundConnection(s, i, packetstatusoutlistener, ClientIntent.STATUS); + } + +- public void initiateServerboundPlayConnection(String s, int i, ClientLoginPacketListener clientloginpacketlistener) { +- this.initiateServerboundConnection(s, i, clientloginpacketlistener, ClientIntent.LOGIN); ++ public void initiateServerboundPlayConnection(String s, int i, ClientLoginPacketListener packetloginoutlistener) { ++ this.initiateServerboundConnection(s, i, packetloginoutlistener, ClientIntent.LOGIN); + } + + private void initiateServerboundConnection(String s, int i, PacketListener packetlistener, ClientIntent clientintent) { + this.disconnectListener = packetlistener; +- this.runOnceConnected((connection) -> { +- connection.setClientboundProtocolAfterHandshake(clientintent); ++ this.runOnceConnected((networkmanager) -> { ++ networkmanager.setClientboundProtocolAfterHandshake(clientintent); + this.setListener(packetlistener); +- connection.sendPacket(new ClientIntentionPacket(SharedConstants.getCurrentVersion().getProtocolVersion(), s, i, clientintent), (PacketSendListener) null, true); ++ networkmanager.sendPacket(new ClientIntentionPacket(SharedConstants.getCurrentVersion().getProtocolVersion(), s, i, clientintent), (PacketSendListener) null, true); + }); + } + +@@ -263,8 +260,8 @@ + this.send(packet, (PacketSendListener) null); + } + +- public void send(Packet packet, @Nullable PacketSendListener packetsendlistener) { +- this.send(packet, packetsendlistener, true); ++ public void send(Packet packet, @Nullable PacketSendListener sendListener) { ++ this.send(packet, sendListener, true); + } + + public void send(Packet packet, @Nullable PacketSendListener packetsendlistener, boolean flag) { +@@ -272,8 +269,8 @@ + this.flushQueue(); + this.sendPacket(packet, packetsendlistener, flag); + } else { +- this.pendingActions.add((connection) -> { +- connection.sendPacket(packet, packetsendlistener, flag); ++ this.pendingActions.add((networkmanager) -> { ++ networkmanager.sendPacket(packet, packetsendlistener, flag); + }); + } + +@@ -344,10 +341,10 @@ + + } + +- private static AttributeKey> getProtocolKey(PacketFlow packetflow) { ++ private static AttributeKey> getProtocolKey(PacketFlow enumprotocoldirection) { + AttributeKey attributekey; + +- switch (packetflow) { ++ switch (enumprotocoldirection) { + case CLIENTBOUND: + attributekey = Connection.ATTRIBUTE_CLIENTBOUND_PROTOCOL; + break; +@@ -419,14 +416,14 @@ + return this.address == null ? "local" : (flag ? this.address.toString() : "IP hidden"); + } + +- public void disconnect(Component component) { ++ public void disconnect(Component message) { + if (this.channel == null) { +- this.delayedDisconnect = component; ++ this.delayedDisconnect = message; + } + + if (this.isConnected()) { +- this.channel.close().awaitUninterruptibly(); +- this.disconnectedReason = component; ++ this.channel.close(); // We can't wait as this may be called from an event loop. ++ this.disconnectedReason = message; + } + + } +@@ -444,23 +441,23 @@ + } + + public static Connection connectToServer(InetSocketAddress inetsocketaddress, boolean flag, @Nullable SampleLogger samplelogger) { +- Connection connection = new Connection(PacketFlow.CLIENTBOUND); ++ Connection networkmanager = new Connection(PacketFlow.CLIENTBOUND); + + if (samplelogger != null) { +- connection.setBandwidthLogger(samplelogger); ++ networkmanager.setBandwidthLogger(samplelogger); + } + +- ChannelFuture channelfuture = connect(inetsocketaddress, flag, connection); ++ ChannelFuture channelfuture = connect(inetsocketaddress, flag, networkmanager); + + channelfuture.syncUninterruptibly(); +- return connection; ++ return networkmanager; + } + +- public static ChannelFuture connect(InetSocketAddress inetsocketaddress, boolean flag, final Connection connection) { ++ public static ChannelFuture connect(InetSocketAddress address, boolean useEpollIfAvailable, final Connection connection) { + Class oclass; + EventLoopGroup eventloopgroup; + +- if (Epoll.isAvailable() && flag) { ++ if (Epoll.isAvailable() && useEpollIfAvailable) { + oclass = EpollSocketChannel.class; + eventloopgroup = (EventLoopGroup) Connection.NETWORK_EPOLL_WORKER_GROUP.get(); + } else { +@@ -469,7 +466,6 @@ + } + + return ((Bootstrap) ((Bootstrap) ((Bootstrap) (new Bootstrap()).group(eventloopgroup)).handler(new ChannelInitializer() { +- @Override + protected void initChannel(Channel channel) { + Connection.setInitialProtocolAttributes(channel); + +@@ -484,13 +480,13 @@ + Connection.configureSerialization(channelpipeline, PacketFlow.CLIENTBOUND, connection.bandwidthDebugMonitor); + connection.configurePacketHandler(channelpipeline); + } +- })).channel(oclass)).connect(inetsocketaddress.getAddress(), inetsocketaddress.getPort()); ++ })).channel(oclass)).connect(address.getAddress(), address.getPort()); + } + +- public static void configureSerialization(ChannelPipeline channelpipeline, PacketFlow packetflow, @Nullable BandwidthDebugMonitor bandwidthdebugmonitor) { +- PacketFlow packetflow1 = packetflow.getOpposite(); +- AttributeKey> attributekey = getProtocolKey(packetflow); +- AttributeKey> attributekey1 = getProtocolKey(packetflow1); ++ public static void configureSerialization(ChannelPipeline channelpipeline, PacketFlow enumprotocoldirection, @Nullable BandwidthDebugMonitor bandwidthdebugmonitor) { ++ PacketFlow enumprotocoldirection1 = enumprotocoldirection.getOpposite(); ++ AttributeKey> attributekey = getProtocolKey(enumprotocoldirection); ++ AttributeKey> attributekey1 = getProtocolKey(enumprotocoldirection1); + + channelpipeline.addLast("splitter", new Varint21FrameDecoder(bandwidthdebugmonitor)).addLast("decoder", new PacketDecoder(attributekey)).addLast("prepender", new Varint21LengthFieldPrepender()).addLast("encoder", new PacketEncoder(attributekey1)).addLast("unbundler", new PacketBundleUnpacker(attributekey1)).addLast("bundler", new PacketBundlePacker(attributekey)); + } +@@ -499,38 +495,37 @@ + channelpipeline.addLast(new ChannelHandler[]{new FlowControlHandler()}).addLast("packet_handler", this); + } + +- private static void configureInMemoryPacketValidation(ChannelPipeline channelpipeline, PacketFlow packetflow) { +- PacketFlow packetflow1 = packetflow.getOpposite(); +- AttributeKey> attributekey = getProtocolKey(packetflow); +- AttributeKey> attributekey1 = getProtocolKey(packetflow1); ++ private static void configureInMemoryPacketValidation(ChannelPipeline channelpipeline, PacketFlow enumprotocoldirection) { ++ PacketFlow enumprotocoldirection1 = enumprotocoldirection.getOpposite(); ++ AttributeKey> attributekey = getProtocolKey(enumprotocoldirection); ++ AttributeKey> attributekey1 = getProtocolKey(enumprotocoldirection1); + + channelpipeline.addLast("validator", new PacketFlowValidator(attributekey, attributekey1)); + } + +- public static void configureInMemoryPipeline(ChannelPipeline channelpipeline, PacketFlow packetflow) { +- configureInMemoryPacketValidation(channelpipeline, packetflow); ++ public static void configureInMemoryPipeline(ChannelPipeline channelpipeline, PacketFlow enumprotocoldirection) { ++ configureInMemoryPacketValidation(channelpipeline, enumprotocoldirection); + } + +- public static Connection connectToLocalServer(SocketAddress socketaddress) { +- final Connection connection = new Connection(PacketFlow.CLIENTBOUND); ++ public static Connection connectToLocalServer(SocketAddress address) { ++ final Connection networkmanager = new Connection(PacketFlow.CLIENTBOUND); + + ((Bootstrap) ((Bootstrap) ((Bootstrap) (new Bootstrap()).group((EventLoopGroup) Connection.LOCAL_WORKER_GROUP.get())).handler(new ChannelInitializer() { +- @Override + protected void initChannel(Channel channel) { + Connection.setInitialProtocolAttributes(channel); + ChannelPipeline channelpipeline = channel.pipeline(); + + Connection.configureInMemoryPipeline(channelpipeline, PacketFlow.CLIENTBOUND); +- connection.configurePacketHandler(channelpipeline); ++ networkmanager.configurePacketHandler(channelpipeline); + } +- })).channel(LocalChannel.class)).connect(socketaddress).syncUninterruptibly(); +- return connection; ++ })).channel(LocalChannel.class)).connect(address).syncUninterruptibly(); ++ return networkmanager; + } + +- public void setEncryptionKey(Cipher cipher, Cipher cipher1) { ++ public void setEncryptionKey(Cipher decryptingCipher, Cipher encryptingCipher) { + this.encrypted = true; +- this.channel.pipeline().addBefore("splitter", "decrypt", new CipherDecoder(cipher)); +- this.channel.pipeline().addBefore("prepender", "encrypt", new CipherEncoder(cipher1)); ++ this.channel.pipeline().addBefore("splitter", "decrypt", new CipherDecoder(decryptingCipher)); ++ this.channel.pipeline().addBefore("prepender", "encrypt", new CipherEncoder(encryptingCipher)); + } + + public boolean isEncrypted() { +@@ -562,18 +557,18 @@ + + } + +- public void setupCompression(int i, boolean flag) { +- if (i >= 0) { ++ public void setupCompression(int threshold, boolean validateDecompressed) { ++ if (threshold >= 0) { + if (this.channel.pipeline().get("decompress") instanceof CompressionDecoder) { +- ((CompressionDecoder) this.channel.pipeline().get("decompress")).setThreshold(i, flag); ++ ((CompressionDecoder) this.channel.pipeline().get("decompress")).setThreshold(threshold, validateDecompressed); + } else { +- this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(i, flag)); ++ this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(threshold, validateDecompressed)); + } + + if (this.channel.pipeline().get("compress") instanceof CompressionEncoder) { +- ((CompressionEncoder) this.channel.pipeline().get("compress")).setThreshold(i); ++ ((CompressionEncoder) this.channel.pipeline().get("compress")).setThreshold(threshold); + } else { +- this.channel.pipeline().addBefore("encoder", "compress", new CompressionEncoder(i)); ++ this.channel.pipeline().addBefore("encoder", "compress", new CompressionEncoder(threshold)); + } + } else { + if (this.channel.pipeline().get("decompress") instanceof CompressionDecoder) { +@@ -597,11 +592,11 @@ + PacketListener packetlistener1 = packetlistener != null ? packetlistener : this.disconnectListener; + + if (packetlistener1 != null) { +- Component component = (Component) Objects.requireNonNullElseGet(this.getDisconnectedReason(), () -> { ++ Component ichatbasecomponent = (Component) Objects.requireNonNullElseGet(this.getDisconnectedReason(), () -> { + return Component.translatable("multiplayer.disconnect.generic"); + }); + +- packetlistener1.onDisconnect(component); ++ packetlistener1.onDisconnect(ichatbasecomponent); + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/network/FriendlyByteBuf.java.patch b/patch-remap/mache-spigotflower/net/minecraft/network/FriendlyByteBuf.java.patch new file mode 100644 index 0000000000..b2743abcda --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/network/FriendlyByteBuf.java.patch @@ -0,0 +1,1851 @@ +--- a/net/minecraft/network/FriendlyByteBuf.java ++++ b/net/minecraft/network/FriendlyByteBuf.java +@@ -81,6 +81,8 @@ + import org.joml.Quaternionf; + import org.joml.Vector3f; + ++import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit ++ + public class FriendlyByteBuf extends ByteBuf { + + public static final int DEFAULT_NBT_QUOTA = 2097152; +@@ -92,8 +94,8 @@ + private static final int MAX_PUBLIC_KEY_LENGTH = 512; + private static final Gson GSON = new Gson(); + +- public FriendlyByteBuf(ByteBuf bytebuf) { +- this.source = bytebuf; ++ public FriendlyByteBuf(ByteBuf source) { ++ this.source = source; + } + + /** @deprecated */ +@@ -104,22 +106,22 @@ + + /** @deprecated */ + @Deprecated +- public T readWithCodec(DynamicOps dynamicops, Codec codec, NbtAccounter nbtaccounter) { +- Tag tag = this.readNbt(nbtaccounter); ++ public T readWithCodec(DynamicOps dynamicops, Codec codec, NbtAccounter nbtreadlimiter) { ++ Tag nbtbase = this.readNbt(nbtreadlimiter); + +- return Util.getOrThrow(codec.parse(dynamicops, tag), (s) -> { +- return new DecoderException("Failed to decode: " + s + " " + tag); ++ return Util.getOrThrow(codec.parse(dynamicops, nbtbase), (s) -> { ++ return new DecoderException("Failed to decode: " + s + " " + nbtbase); + }); + } + + /** @deprecated */ + @Deprecated + public FriendlyByteBuf writeWithCodec(DynamicOps dynamicops, Codec codec, T t0) { +- Tag tag = (Tag) Util.getOrThrow(codec.encodeStart(dynamicops, t0), (s) -> { ++ Tag nbtbase = (Tag) Util.getOrThrow(codec.encodeStart(dynamicops, t0), (s) -> { + return new EncoderException("Failed to encode: " + s + " " + t0); + }); + +- this.writeNbt(tag); ++ this.writeNbt(nbtbase); + return this; + } + +@@ -132,58 +134,58 @@ + }); + } + +- public void writeJsonWithCodec(Codec codec, T t0) { +- DataResult dataresult = codec.encodeStart(JsonOps.INSTANCE, t0); ++ public void writeJsonWithCodec(Codec codec, T value) { ++ DataResult dataresult = codec.encodeStart(JsonOps.INSTANCE, value); + + this.writeUtf(FriendlyByteBuf.GSON.toJson((JsonElement) Util.getOrThrow(dataresult, (s) -> { +- return new EncoderException("Failed to encode: " + s + " " + t0); ++ return new EncoderException("Failed to encode: " + s + " " + value); + }))); + } + +- public void writeId(IdMap idmap, T t0) { +- int i = idmap.getId(t0); ++ public void writeId(IdMap idMap, T value) { ++ int i = idMap.getId(value); + + if (i == -1) { +- throw new IllegalArgumentException("Can't find id for '" + t0 + "' in map " + idmap); ++ throw new IllegalArgumentException("Can't find id for '" + value + "' in map " + idMap); + } else { + this.writeVarInt(i); + } + } + +- public void writeId(IdMap> idmap, Holder holder, FriendlyByteBuf.Writer friendlybytebuf_writer) { +- switch (holder.kind()) { ++ public void writeId(IdMap> idMap, Holder value, FriendlyByteBuf.b writer) { ++ switch (value.kind()) { + case REFERENCE: +- int i = idmap.getId(holder); ++ int i = idMap.getId(value); + + if (i == -1) { +- Object object = holder.value(); ++ Object object = value.value(); + +- throw new IllegalArgumentException("Can't find id for '" + object + "' in map " + idmap); ++ throw new IllegalArgumentException("Can't find id for '" + object + "' in map " + idMap); + } + + this.writeVarInt(i + 1); + break; + case DIRECT: + this.writeVarInt(0); +- friendlybytebuf_writer.accept(this, holder.value()); ++ writer.accept(this, value.value()); + } + + } + + @Nullable +- public T readById(IdMap idmap) { ++ public T readById(IdMap idMap) { + int i = this.readVarInt(); + +- return idmap.byId(i); ++ return idMap.byId(i); + } + +- public Holder readById(IdMap> idmap, FriendlyByteBuf.Reader friendlybytebuf_reader) { ++ public Holder readById(IdMap> idMap, FriendlyByteBuf.a reader) { + int i = this.readVarInt(); + + if (i == 0) { +- return Holder.direct(friendlybytebuf_reader.apply(this)); ++ return Holder.direct(reader.apply(this)); + } else { +- Holder holder = (Holder) idmap.byId(i - 1); ++ Holder holder = (Holder) idMap.byId(i - 1); + + if (holder == null) { + throw new IllegalArgumentException("Can't find element with id " + i); +@@ -193,41 +195,41 @@ + } + } + +- public static IntFunction limitValue(IntFunction intfunction, int i) { ++ public static IntFunction limitValue(IntFunction function, int limit) { + return (j) -> { +- if (j > i) { +- throw new DecoderException("Value " + j + " is larger than limit " + i); ++ if (j > limit) { ++ throw new DecoderException("Value " + j + " is larger than limit " + limit); + } else { +- return intfunction.apply(j); ++ return function.apply(j); + } + }; + } + +- public > C readCollection(IntFunction intfunction, FriendlyByteBuf.Reader friendlybytebuf_reader) { ++ public > C readCollection(IntFunction collectionFactory, FriendlyByteBuf.a elementReader) { + int i = this.readVarInt(); +- C c0 = (Collection) intfunction.apply(i); ++ C c0 = collectionFactory.apply(i); // CraftBukkit - decompile error + + for (int j = 0; j < i; ++j) { +- c0.add(friendlybytebuf_reader.apply(this)); ++ c0.add(elementReader.apply(this)); + } + + return c0; + } + +- public void writeCollection(Collection collection, FriendlyByteBuf.Writer friendlybytebuf_writer) { ++ public void writeCollection(Collection collection, FriendlyByteBuf.b elementWriter) { + this.writeVarInt(collection.size()); +- Iterator iterator = collection.iterator(); ++ Iterator iterator = collection.iterator(); // CraftBukkit - decompile error + + while (iterator.hasNext()) { + T t0 = iterator.next(); + +- friendlybytebuf_writer.accept(this, t0); ++ elementWriter.accept(this, t0); + } + + } + +- public List readList(FriendlyByteBuf.Reader friendlybytebuf_reader) { +- return (List) this.readCollection(Lists::newArrayListWithCapacity, friendlybytebuf_reader); ++ public List readList(FriendlyByteBuf.a elementReader) { ++ return (List) this.readCollection(Lists::newArrayListWithCapacity, elementReader); + } + + public IntList readIntIdList() { +@@ -241,18 +243,18 @@ + return intarraylist; + } + +- public void writeIntIdList(IntList intlist) { +- this.writeVarInt(intlist.size()); +- intlist.forEach(this::writeVarInt); ++ public void writeIntIdList(IntList itIdList) { ++ this.writeVarInt(itIdList.size()); ++ itIdList.forEach((java.util.function.IntConsumer) this::writeVarInt); // CraftBukkit - decompile error + } + +- public > M readMap(IntFunction intfunction, FriendlyByteBuf.Reader friendlybytebuf_reader, FriendlyByteBuf.Reader friendlybytebuf_reader1) { ++ public > M readMap(IntFunction mapFactory, FriendlyByteBuf.a keyReader, FriendlyByteBuf.a valueReader) { + int i = this.readVarInt(); +- M m0 = (Map) intfunction.apply(i); ++ M m0 = mapFactory.apply(i); // CraftBukkit - decompile error + + for (int j = 0; j < i; ++j) { +- K k0 = friendlybytebuf_reader.apply(this); +- V v0 = friendlybytebuf_reader1.apply(this); ++ K k0 = keyReader.apply(this); ++ V v0 = valueReader.apply(this); + + m0.put(k0, v0); + } +@@ -260,42 +262,42 @@ + return m0; + } + +- public Map readMap(FriendlyByteBuf.Reader friendlybytebuf_reader, FriendlyByteBuf.Reader friendlybytebuf_reader1) { +- return this.readMap(Maps::newHashMapWithExpectedSize, friendlybytebuf_reader, friendlybytebuf_reader1); ++ public Map readMap(FriendlyByteBuf.a keyReader, FriendlyByteBuf.a valueReader) { ++ return this.readMap(Maps::newHashMapWithExpectedSize, keyReader, valueReader); + } + +- public void writeMap(Map map, FriendlyByteBuf.Writer friendlybytebuf_writer, FriendlyByteBuf.Writer friendlybytebuf_writer1) { ++ public void writeMap(Map map, FriendlyByteBuf.b keyWriter, FriendlyByteBuf.b valueWriter) { + this.writeVarInt(map.size()); + map.forEach((object, object1) -> { +- friendlybytebuf_writer.accept(this, object); +- friendlybytebuf_writer1.accept(this, object1); ++ keyWriter.accept(this, object); ++ valueWriter.accept(this, object1); + }); + } + +- public void readWithCount(Consumer consumer) { ++ public void readWithCount(Consumer reader) { + int i = this.readVarInt(); + + for (int j = 0; j < i; ++j) { +- consumer.accept(this); ++ reader.accept(this); + } + + } + +- public > void writeEnumSet(EnumSet enumset, Class oclass) { +- E[] ae = (Enum[]) oclass.getEnumConstants(); ++ public > void writeEnumSet(EnumSet enumSet, Class enumClass) { ++ E[] ae = enumClass.getEnumConstants(); // CraftBukkit - decompile error + BitSet bitset = new BitSet(ae.length); + + for (int i = 0; i < ae.length; ++i) { +- bitset.set(i, enumset.contains(ae[i])); ++ bitset.set(i, enumSet.contains(ae[i])); + } + + this.writeFixedBitSet(bitset, ae.length); + } + +- public > EnumSet readEnumSet(Class oclass) { +- E[] ae = (Enum[]) oclass.getEnumConstants(); ++ public > EnumSet readEnumSet(Class enumClass) { ++ E[] ae = enumClass.getEnumConstants(); // CraftBukkit - decompile error + BitSet bitset = this.readFixedBitSet(ae.length); +- EnumSet enumset = EnumSet.noneOf(oclass); ++ EnumSet enumset = EnumSet.noneOf(enumClass); + + for (int i = 0; i < ae.length; ++i) { + if (bitset.get(i)) { +@@ -306,64 +308,64 @@ + return enumset; + } + +- public void writeOptional(Optional optional, FriendlyByteBuf.Writer friendlybytebuf_writer) { ++ public void writeOptional(Optional optional, FriendlyByteBuf.b writer) { + if (optional.isPresent()) { + this.writeBoolean(true); +- friendlybytebuf_writer.accept(this, optional.get()); ++ writer.accept(this, optional.get()); + } else { + this.writeBoolean(false); + } + + } + +- public Optional readOptional(FriendlyByteBuf.Reader friendlybytebuf_reader) { +- return this.readBoolean() ? Optional.of(friendlybytebuf_reader.apply(this)) : Optional.empty(); ++ public Optional readOptional(FriendlyByteBuf.a reader) { ++ return this.readBoolean() ? Optional.of(reader.apply(this)) : Optional.empty(); + } + + @Nullable +- public T readNullable(FriendlyByteBuf.Reader friendlybytebuf_reader) { +- return this.readBoolean() ? friendlybytebuf_reader.apply(this) : null; ++ public T readNullable(FriendlyByteBuf.a reader) { ++ return this.readBoolean() ? reader.apply(this) : null; + } + +- public void writeNullable(@Nullable T t0, FriendlyByteBuf.Writer friendlybytebuf_writer) { +- if (t0 != null) { ++ public void writeNullable(@Nullable T value, FriendlyByteBuf.b writer) { ++ if (value != null) { + this.writeBoolean(true); +- friendlybytebuf_writer.accept(this, t0); ++ writer.accept(this, value); + } else { + this.writeBoolean(false); + } + + } + +- public void writeEither(Either either, FriendlyByteBuf.Writer friendlybytebuf_writer, FriendlyByteBuf.Writer friendlybytebuf_writer1) { +- either.ifLeft((object) -> { ++ public void writeEither(Either value, FriendlyByteBuf.b leftWriter, FriendlyByteBuf.b rightWriter) { ++ value.ifLeft((object) -> { + this.writeBoolean(true); +- friendlybytebuf_writer.accept(this, object); ++ leftWriter.accept(this, object); + }).ifRight((object) -> { + this.writeBoolean(false); +- friendlybytebuf_writer1.accept(this, object); ++ rightWriter.accept(this, object); + }); + } + +- public Either readEither(FriendlyByteBuf.Reader friendlybytebuf_reader, FriendlyByteBuf.Reader friendlybytebuf_reader1) { +- return this.readBoolean() ? Either.left(friendlybytebuf_reader.apply(this)) : Either.right(friendlybytebuf_reader1.apply(this)); ++ public Either readEither(FriendlyByteBuf.a leftReader, FriendlyByteBuf.a rightReader) { ++ return this.readBoolean() ? Either.left(leftReader.apply(this)) : Either.right(rightReader.apply(this)); + } + + public byte[] readByteArray() { + return this.readByteArray(this.readableBytes()); + } + +- public FriendlyByteBuf writeByteArray(byte[] abyte) { +- this.writeVarInt(abyte.length); +- this.writeBytes(abyte); ++ public FriendlyByteBuf writeByteArray(byte[] array) { ++ this.writeVarInt(array.length); ++ this.writeBytes(array); + return this; + } + +- public byte[] readByteArray(int i) { ++ public byte[] readByteArray(int maxLength) { + int j = this.readVarInt(); + +- if (j > i) { +- throw new DecoderException("ByteArray with size " + j + " is bigger than allowed " + i); ++ if (j > maxLength) { ++ throw new DecoderException("ByteArray with size " + j + " is bigger than allowed " + maxLength); + } else { + byte[] abyte = new byte[j]; + +@@ -372,10 +374,10 @@ + } + } + +- public FriendlyByteBuf writeVarIntArray(int[] aint) { +- this.writeVarInt(aint.length); +- int[] aint1 = aint; +- int i = aint.length; ++ public FriendlyByteBuf writeVarIntArray(int[] array) { ++ this.writeVarInt(array.length); ++ int[] aint1 = array; ++ int i = array.length; + + for (int j = 0; j < i; ++j) { + int k = aint1[j]; +@@ -390,11 +392,11 @@ + return this.readVarIntArray(this.readableBytes()); + } + +- public int[] readVarIntArray(int i) { ++ public int[] readVarIntArray(int maxLength) { + int j = this.readVarInt(); + +- if (j > i) { +- throw new DecoderException("VarIntArray with size " + j + " is bigger than allowed " + i); ++ if (j > maxLength) { ++ throw new DecoderException("VarIntArray with size " + j + " is bigger than allowed " + maxLength); + } else { + int[] aint = new int[j]; + +@@ -406,10 +408,10 @@ + } + } + +- public FriendlyByteBuf writeLongArray(long[] along) { +- this.writeVarInt(along.length); +- long[] along1 = along; +- int i = along.length; ++ public FriendlyByteBuf writeLongArray(long[] array) { ++ this.writeVarInt(array.length); ++ long[] along1 = array; ++ int i = array.length; + + for (int j = 0; j < i; ++j) { + long k = along1[j]; +@@ -424,34 +426,34 @@ + return this.readLongArray((long[]) null); + } + +- public long[] readLongArray(@Nullable long[] along) { +- return this.readLongArray(along, this.readableBytes() / 8); ++ public long[] readLongArray(@Nullable long[] array) { ++ return this.readLongArray(array, this.readableBytes() / 8); + } + +- public long[] readLongArray(@Nullable long[] along, int i) { ++ public long[] readLongArray(@Nullable long[] array, int maxLength) { + int j = this.readVarInt(); + +- if (along == null || along.length != j) { +- if (j > i) { +- throw new DecoderException("LongArray with size " + j + " is bigger than allowed " + i); ++ if (array == null || array.length != j) { ++ if (j > maxLength) { ++ throw new DecoderException("LongArray with size " + j + " is bigger than allowed " + maxLength); + } + +- along = new long[j]; ++ array = new long[j]; + } + +- for (int k = 0; k < along.length; ++k) { +- along[k] = this.readLong(); ++ for (int k = 0; k < array.length; ++k) { ++ array[k] = this.readLong(); + } + +- return along; ++ return array; + } + + public BlockPos readBlockPos() { + return BlockPos.of(this.readLong()); + } + +- public FriendlyByteBuf writeBlockPos(BlockPos blockpos) { +- this.writeLong(blockpos.asLong()); ++ public FriendlyByteBuf writeBlockPos(BlockPos pos) { ++ this.writeLong(pos.asLong()); + return this; + } + +@@ -459,8 +461,8 @@ + return new ChunkPos(this.readLong()); + } + +- public FriendlyByteBuf writeChunkPos(ChunkPos chunkpos) { +- this.writeLong(chunkpos.toLong()); ++ public FriendlyByteBuf writeChunkPos(ChunkPos chunkPos) { ++ this.writeLong(chunkPos.toLong()); + return this; + } + +@@ -468,21 +470,21 @@ + return SectionPos.of(this.readLong()); + } + +- public FriendlyByteBuf writeSectionPos(SectionPos sectionpos) { +- this.writeLong(sectionpos.asLong()); ++ public FriendlyByteBuf writeSectionPos(SectionPos sectionPos) { ++ this.writeLong(sectionPos.asLong()); + return this; + } + + public GlobalPos readGlobalPos() { + ResourceKey resourcekey = this.readResourceKey(Registries.DIMENSION); +- BlockPos blockpos = this.readBlockPos(); ++ BlockPos blockposition = this.readBlockPos(); + +- return GlobalPos.of(resourcekey, blockpos); ++ return GlobalPos.of(resourcekey, blockposition); + } + +- public void writeGlobalPos(GlobalPos globalpos) { +- this.writeResourceKey(globalpos.dimension()); +- this.writeBlockPos(globalpos.pos()); ++ public void writeGlobalPos(GlobalPos pos) { ++ this.writeResourceKey(pos.dimension()); ++ this.writeBlockPos(pos.pos()); + } + + public Vector3f readVector3f() { +@@ -499,21 +501,21 @@ + return new Quaternionf(this.readFloat(), this.readFloat(), this.readFloat(), this.readFloat()); + } + +- public void writeQuaternion(Quaternionf quaternionf) { +- this.writeFloat(quaternionf.x); +- this.writeFloat(quaternionf.y); +- this.writeFloat(quaternionf.z); +- this.writeFloat(quaternionf.w); ++ public void writeQuaternion(Quaternionf quaternion) { ++ this.writeFloat(quaternion.x); ++ this.writeFloat(quaternion.y); ++ this.writeFloat(quaternion.z); ++ this.writeFloat(quaternion.w); + } + + public Vec3 readVec3() { + return new Vec3(this.readDouble(), this.readDouble(), this.readDouble()); + } + +- public void writeVec3(Vec3 vec3) { +- this.writeDouble(vec3.x()); +- this.writeDouble(vec3.y()); +- this.writeDouble(vec3.z()); ++ public void writeVec3(Vec3 vec3d) { ++ this.writeDouble(vec3d.x()); ++ this.writeDouble(vec3d.y()); ++ this.writeDouble(vec3d.z()); + } + + public Component readComponent() { +@@ -528,12 +530,12 @@ + return this.writeWithCodec(NbtOps.INSTANCE, ComponentSerialization.CODEC, component); + } + +- public > T readEnum(Class oclass) { +- return ((Enum[]) oclass.getEnumConstants())[this.readVarInt()]; ++ public > T readEnum(Class enumClass) { ++ return ((T[]) enumClass.getEnumConstants())[this.readVarInt()]; // CraftBukkit - fix decompile error + } + +- public FriendlyByteBuf writeEnum(Enum oenum) { +- return this.writeVarInt(oenum.ordinal()); ++ public FriendlyByteBuf writeEnum(Enum value) { ++ return this.writeVarInt(value.ordinal()); + } + + public T readById(IntFunction intfunction) { +@@ -566,67 +568,67 @@ + return new UUID(this.readLong(), this.readLong()); + } + +- public FriendlyByteBuf writeVarInt(int i) { +- VarInt.write(this.source, i); ++ public FriendlyByteBuf writeVarInt(int input) { ++ VarInt.write(this.source, input); + return this; + } + +- public FriendlyByteBuf writeVarLong(long i) { +- VarLong.write(this.source, i); ++ public FriendlyByteBuf writeVarLong(long value) { ++ VarLong.write(this.source, value); + return this; + } + +- public FriendlyByteBuf writeNbt(@Nullable Tag tag) { +- if (tag == null) { +- tag = EndTag.INSTANCE; ++ public FriendlyByteBuf writeNbt(@Nullable Tag nbtbase) { ++ if (nbtbase == null) { ++ nbtbase = EndTag.INSTANCE; + } + + try { +- NbtIo.writeAnyTag((Tag) tag, new ByteBufOutputStream(this)); ++ NbtIo.writeAnyTag((Tag) nbtbase, new ByteBufOutputStream(this)); + return this; +- } catch (IOException ioexception) { ++ } catch (Exception ioexception) { // CraftBukkit - IOException -> Exception + throw new EncoderException(ioexception); + } + } + + @Nullable + public CompoundTag readNbt() { +- Tag tag = this.readNbt(NbtAccounter.create(2097152L)); ++ Tag nbtbase = this.readNbt(NbtAccounter.create(2097152L)); + +- if (tag != null && !(tag instanceof CompoundTag)) { +- throw new DecoderException("Not a compound tag: " + tag); ++ if (nbtbase != null && !(nbtbase instanceof CompoundTag)) { ++ throw new DecoderException("Not a compound tag: " + nbtbase); + } else { +- return (CompoundTag) tag; ++ return (CompoundTag) nbtbase; + } + } + + @Nullable +- public Tag readNbt(NbtAccounter nbtaccounter) { ++ public Tag readNbt(NbtAccounter nbtreadlimiter) { + try { +- Tag tag = NbtIo.readAnyTag(new ByteBufInputStream(this), nbtaccounter); ++ Tag nbtbase = NbtIo.readAnyTag(new ByteBufInputStream(this), nbtreadlimiter); + +- return tag.getId() == 0 ? null : tag; ++ return nbtbase.getId() == 0 ? null : nbtbase; + } catch (IOException ioexception) { + throw new EncoderException(ioexception); + } + } + +- public FriendlyByteBuf writeItem(ItemStack itemstack) { +- if (itemstack.isEmpty()) { ++ public FriendlyByteBuf writeItem(ItemStack stack) { ++ if (stack.isEmpty() || stack.getItem() == null) { // CraftBukkit - NPE fix itemstack.getItem() + this.writeBoolean(false); + } else { + this.writeBoolean(true); +- Item item = itemstack.getItem(); ++ Item item = stack.getItem(); + + this.writeId(BuiltInRegistries.ITEM, item); +- this.writeByte(itemstack.getCount()); +- CompoundTag compoundtag = null; ++ this.writeByte(stack.getCount()); ++ CompoundTag nbttagcompound = null; + + if (item.canBeDepleted() || item.shouldOverrideMultiplayerNbt()) { +- compoundtag = itemstack.getTag(); ++ nbttagcompound = stack.getTag(); + } + +- this.writeNbt(compoundtag); ++ this.writeNbt(nbttagcompound); + } + + return this; +@@ -641,6 +643,11 @@ + ItemStack itemstack = new ItemStack(item, b0); + + itemstack.setTag(this.readNbt()); ++ // CraftBukkit start ++ if (itemstack.getTag() != null) { ++ CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); ++ } ++ // CraftBukkit end + return itemstack; + } + } +@@ -649,16 +656,16 @@ + return this.readUtf(32767); + } + +- public String readUtf(int i) { +- return Utf8String.read(this.source, i); ++ public String readUtf(int maxLength) { ++ return Utf8String.read(this.source, maxLength); + } + +- public FriendlyByteBuf writeUtf(String s) { +- return this.writeUtf(s, 32767); ++ public FriendlyByteBuf writeUtf(String string) { ++ return this.writeUtf(string, 32767); + } + +- public FriendlyByteBuf writeUtf(String s, int i) { +- Utf8String.write(this.source, s, i); ++ public FriendlyByteBuf writeUtf(String string, int maxLength) { ++ Utf8String.write(this.source, string, maxLength); + return this; + } + +@@ -666,33 +673,33 @@ + return new ResourceLocation(this.readUtf(32767)); + } + +- public FriendlyByteBuf writeResourceLocation(ResourceLocation resourcelocation) { +- this.writeUtf(resourcelocation.toString()); ++ public FriendlyByteBuf writeResourceLocation(ResourceLocation resourceLocation) { ++ this.writeUtf(resourceLocation.toString()); + return this; + } + +- public ResourceKey readResourceKey(ResourceKey> resourcekey) { +- ResourceLocation resourcelocation = this.readResourceLocation(); ++ public ResourceKey readResourceKey(ResourceKey> registryKey) { ++ ResourceLocation minecraftkey = this.readResourceLocation(); + +- return ResourceKey.create(resourcekey, resourcelocation); ++ return ResourceKey.create(registryKey, minecraftkey); + } + +- public void writeResourceKey(ResourceKey resourcekey) { +- this.writeResourceLocation(resourcekey.location()); ++ public void writeResourceKey(ResourceKey resourceKey) { ++ this.writeResourceLocation(resourceKey.location()); + } + + public ResourceKey> readRegistryKey() { +- ResourceLocation resourcelocation = this.readResourceLocation(); ++ ResourceLocation minecraftkey = this.readResourceLocation(); + +- return ResourceKey.createRegistryKey(resourcelocation); ++ return ResourceKey.createRegistryKey(minecraftkey); + } + + public Date readDate() { + return new Date(this.readLong()); + } + +- public FriendlyByteBuf writeDate(Date date) { +- this.writeLong(date.getTime()); ++ public FriendlyByteBuf writeDate(Date time) { ++ this.writeLong(time.getTime()); + return this; + } + +@@ -707,64 +714,64 @@ + public PublicKey readPublicKey() { + try { + return Crypt.byteToPublicKey(this.readByteArray(512)); +- } catch (CryptException cryptexception) { +- throw new DecoderException("Malformed public key bytes", cryptexception); ++ } catch (CryptException cryptographyexception) { ++ throw new DecoderException("Malformed public key bytes", cryptographyexception); + } + } + +- public FriendlyByteBuf writePublicKey(PublicKey publickey) { +- this.writeByteArray(publickey.getEncoded()); ++ public FriendlyByteBuf writePublicKey(PublicKey publicKey) { ++ this.writeByteArray(publicKey.getEncoded()); + return this; + } + + public BlockHitResult readBlockHitResult() { +- BlockPos blockpos = this.readBlockPos(); +- Direction direction = (Direction) this.readEnum(Direction.class); ++ BlockPos blockposition = this.readBlockPos(); ++ Direction enumdirection = (Direction) this.readEnum(Direction.class); + float f = this.readFloat(); + float f1 = this.readFloat(); + float f2 = this.readFloat(); + boolean flag = this.readBoolean(); + +- return new BlockHitResult(new Vec3((double) blockpos.getX() + (double) f, (double) blockpos.getY() + (double) f1, (double) blockpos.getZ() + (double) f2), direction, blockpos, flag); ++ return new BlockHitResult(new Vec3((double) blockposition.getX() + (double) f, (double) blockposition.getY() + (double) f1, (double) blockposition.getZ() + (double) f2), enumdirection, blockposition, flag); + } + +- public void writeBlockHitResult(BlockHitResult blockhitresult) { +- BlockPos blockpos = blockhitresult.getBlockPos(); ++ public void writeBlockHitResult(BlockHitResult result) { ++ BlockPos blockposition = result.getBlockPos(); + +- this.writeBlockPos(blockpos); +- this.writeEnum(blockhitresult.getDirection()); +- Vec3 vec3 = blockhitresult.getLocation(); ++ this.writeBlockPos(blockposition); ++ this.writeEnum(result.getDirection()); ++ Vec3 vec3d = result.getLocation(); + +- this.writeFloat((float) (vec3.x - (double) blockpos.getX())); +- this.writeFloat((float) (vec3.y - (double) blockpos.getY())); +- this.writeFloat((float) (vec3.z - (double) blockpos.getZ())); +- this.writeBoolean(blockhitresult.isInside()); ++ this.writeFloat((float) (vec3d.x - (double) blockposition.getX())); ++ this.writeFloat((float) (vec3d.y - (double) blockposition.getY())); ++ this.writeFloat((float) (vec3d.z - (double) blockposition.getZ())); ++ this.writeBoolean(result.isInside()); + } + + public BitSet readBitSet() { + return BitSet.valueOf(this.readLongArray()); + } + +- public void writeBitSet(BitSet bitset) { +- this.writeLongArray(bitset.toLongArray()); ++ public void writeBitSet(BitSet bitSet) { ++ this.writeLongArray(bitSet.toLongArray()); + } + +- public BitSet readFixedBitSet(int i) { +- byte[] abyte = new byte[Mth.positiveCeilDiv(i, 8)]; ++ public BitSet readFixedBitSet(int size) { ++ byte[] abyte = new byte[Mth.positiveCeilDiv(size, 8)]; + + this.readBytes(abyte); + return BitSet.valueOf(abyte); + } + +- public void writeFixedBitSet(BitSet bitset, int i) { +- if (bitset.length() > i) { +- int j = bitset.length(); ++ public void writeFixedBitSet(BitSet bitSet, int size) { ++ if (bitSet.length() > size) { ++ int j = bitSet.length(); + +- throw new EncoderException("BitSet is larger than expected size (" + j + ">" + i + ")"); ++ throw new EncoderException("BitSet is larger than expected size (" + j + ">" + size + ")"); + } else { +- byte[] abyte = bitset.toByteArray(); ++ byte[] abyte = bitSet.toByteArray(); + +- this.writeBytes(Arrays.copyOf(abyte, Mth.positiveCeilDiv(i, 8))); ++ this.writeBytes(Arrays.copyOf(abyte, Mth.positiveCeilDiv(size, 8))); + } + } + +@@ -777,16 +784,16 @@ + return gameprofile; + } + +- public void writeGameProfile(GameProfile gameprofile) { +- this.writeUUID(gameprofile.getId()); +- this.writeUtf(gameprofile.getName()); +- this.writeGameProfileProperties(gameprofile.getProperties()); ++ public void writeGameProfile(GameProfile gameProfile) { ++ this.writeUUID(gameProfile.getId()); ++ this.writeUtf(gameProfile.getName()); ++ this.writeGameProfileProperties(gameProfile.getProperties()); + } + + public PropertyMap readGameProfileProperties() { + PropertyMap propertymap = new PropertyMap(); + +- this.readWithCount((friendlybytebuf) -> { ++ this.readWithCount((packetdataserializer) -> { + Property property = this.readProperty(); + + propertymap.put(property.name(), property); +@@ -794,8 +801,8 @@ + return propertymap; + } + +- public void writeGameProfileProperties(PropertyMap propertymap) { +- this.writeCollection(propertymap.values(), FriendlyByteBuf::writeProperty); ++ public void writeGameProfileProperties(PropertyMap gameProfileProperties) { ++ this.writeCollection(gameProfileProperties.values(), FriendlyByteBuf::writeProperty); + } + + public Property readProperty() { +@@ -812,1018 +819,833 @@ + this.writeNullable(property.signature(), FriendlyByteBuf::writeUtf); + } + +- @Override + public boolean isContiguous() { + return this.source.isContiguous(); + } + +- @Override + public int maxFastWritableBytes() { + return this.source.maxFastWritableBytes(); + } + +- @Override + public int capacity() { + return this.source.capacity(); + } + +- @Override + public FriendlyByteBuf capacity(int i) { + this.source.capacity(i); + return this; + } + +- @Override + public int maxCapacity() { + return this.source.maxCapacity(); + } + +- @Override + public ByteBufAllocator alloc() { + return this.source.alloc(); + } + +- @Override + public ByteOrder order() { + return this.source.order(); + } + +- @Override + public ByteBuf order(ByteOrder byteorder) { + return this.source.order(byteorder); + } + +- @Override + public ByteBuf unwrap() { + return this.source; + } + +- @Override + public boolean isDirect() { + return this.source.isDirect(); + } + +- @Override + public boolean isReadOnly() { + return this.source.isReadOnly(); + } + +- @Override + public ByteBuf asReadOnly() { + return this.source.asReadOnly(); + } + +- @Override + public int readerIndex() { + return this.source.readerIndex(); + } + +- @Override + public FriendlyByteBuf readerIndex(int i) { + this.source.readerIndex(i); + return this; + } + +- @Override + public int writerIndex() { + return this.source.writerIndex(); + } + +- @Override + public FriendlyByteBuf writerIndex(int i) { + this.source.writerIndex(i); + return this; + } + +- @Override + public FriendlyByteBuf setIndex(int i, int j) { + this.source.setIndex(i, j); + return this; + } + +- @Override + public int readableBytes() { + return this.source.readableBytes(); + } + +- @Override + public int writableBytes() { + return this.source.writableBytes(); + } + +- @Override + public int maxWritableBytes() { + return this.source.maxWritableBytes(); + } + +- @Override + public boolean isReadable() { + return this.source.isReadable(); + } + +- @Override + public boolean isReadable(int i) { + return this.source.isReadable(i); + } + +- @Override + public boolean isWritable() { + return this.source.isWritable(); + } + +- @Override + public boolean isWritable(int i) { + return this.source.isWritable(i); + } + +- @Override + public FriendlyByteBuf clear() { + this.source.clear(); + return this; + } + +- @Override + public FriendlyByteBuf markReaderIndex() { + this.source.markReaderIndex(); + return this; + } + +- @Override + public FriendlyByteBuf resetReaderIndex() { + this.source.resetReaderIndex(); + return this; + } + +- @Override + public FriendlyByteBuf markWriterIndex() { + this.source.markWriterIndex(); + return this; + } + +- @Override + public FriendlyByteBuf resetWriterIndex() { + this.source.resetWriterIndex(); + return this; + } + +- @Override + public FriendlyByteBuf discardReadBytes() { + this.source.discardReadBytes(); + return this; + } + +- @Override + public FriendlyByteBuf discardSomeReadBytes() { + this.source.discardSomeReadBytes(); + return this; + } + +- @Override + public FriendlyByteBuf ensureWritable(int i) { + this.source.ensureWritable(i); + return this; + } + +- @Override + public int ensureWritable(int i, boolean flag) { + return this.source.ensureWritable(i, flag); + } + +- @Override + public boolean getBoolean(int i) { + return this.source.getBoolean(i); + } + +- @Override + public byte getByte(int i) { + return this.source.getByte(i); + } + +- @Override + public short getUnsignedByte(int i) { + return this.source.getUnsignedByte(i); + } + +- @Override + public short getShort(int i) { + return this.source.getShort(i); + } + +- @Override + public short getShortLE(int i) { + return this.source.getShortLE(i); + } + +- @Override + public int getUnsignedShort(int i) { + return this.source.getUnsignedShort(i); + } + +- @Override + public int getUnsignedShortLE(int i) { + return this.source.getUnsignedShortLE(i); + } + +- @Override + public int getMedium(int i) { + return this.source.getMedium(i); + } + +- @Override + public int getMediumLE(int i) { + return this.source.getMediumLE(i); + } + +- @Override + public int getUnsignedMedium(int i) { + return this.source.getUnsignedMedium(i); + } + +- @Override + public int getUnsignedMediumLE(int i) { + return this.source.getUnsignedMediumLE(i); + } + +- @Override + public int getInt(int i) { + return this.source.getInt(i); + } + +- @Override + public int getIntLE(int i) { + return this.source.getIntLE(i); + } + +- @Override + public long getUnsignedInt(int i) { + return this.source.getUnsignedInt(i); + } + +- @Override + public long getUnsignedIntLE(int i) { + return this.source.getUnsignedIntLE(i); + } + +- @Override + public long getLong(int i) { + return this.source.getLong(i); + } + +- @Override + public long getLongLE(int i) { + return this.source.getLongLE(i); + } + +- @Override + public char getChar(int i) { + return this.source.getChar(i); + } + +- @Override + public float getFloat(int i) { + return this.source.getFloat(i); + } + +- @Override + public double getDouble(int i) { + return this.source.getDouble(i); + } + +- @Override + public FriendlyByteBuf getBytes(int i, ByteBuf bytebuf) { + this.source.getBytes(i, bytebuf); + return this; + } + +- @Override + public FriendlyByteBuf getBytes(int i, ByteBuf bytebuf, int j) { + this.source.getBytes(i, bytebuf, j); + return this; + } + +- @Override + public FriendlyByteBuf getBytes(int i, ByteBuf bytebuf, int j, int k) { + this.source.getBytes(i, bytebuf, j, k); + return this; + } + +- @Override + public FriendlyByteBuf getBytes(int i, byte[] abyte) { + this.source.getBytes(i, abyte); + return this; + } + +- @Override + public FriendlyByteBuf getBytes(int i, byte[] abyte, int j, int k) { + this.source.getBytes(i, abyte, j, k); + return this; + } + +- @Override + public FriendlyByteBuf getBytes(int i, ByteBuffer bytebuffer) { + this.source.getBytes(i, bytebuffer); + return this; + } + +- @Override + public FriendlyByteBuf getBytes(int i, OutputStream outputstream, int j) throws IOException { + this.source.getBytes(i, outputstream, j); + return this; + } + +- @Override + public int getBytes(int i, GatheringByteChannel gatheringbytechannel, int j) throws IOException { + return this.source.getBytes(i, gatheringbytechannel, j); + } + +- @Override + public int getBytes(int i, FileChannel filechannel, long j, int k) throws IOException { + return this.source.getBytes(i, filechannel, j, k); + } + +- @Override + public CharSequence getCharSequence(int i, int j, Charset charset) { + return this.source.getCharSequence(i, j, charset); + } + +- @Override + public FriendlyByteBuf setBoolean(int i, boolean flag) { + this.source.setBoolean(i, flag); + return this; + } + +- @Override + public FriendlyByteBuf setByte(int i, int j) { + this.source.setByte(i, j); + return this; + } + +- @Override + public FriendlyByteBuf setShort(int i, int j) { + this.source.setShort(i, j); + return this; + } + +- @Override + public FriendlyByteBuf setShortLE(int i, int j) { + this.source.setShortLE(i, j); + return this; + } + +- @Override + public FriendlyByteBuf setMedium(int i, int j) { + this.source.setMedium(i, j); + return this; + } + +- @Override + public FriendlyByteBuf setMediumLE(int i, int j) { + this.source.setMediumLE(i, j); + return this; + } + +- @Override + public FriendlyByteBuf setInt(int i, int j) { + this.source.setInt(i, j); + return this; + } + +- @Override + public FriendlyByteBuf setIntLE(int i, int j) { + this.source.setIntLE(i, j); + return this; + } + +- @Override + public FriendlyByteBuf setLong(int i, long j) { + this.source.setLong(i, j); + return this; + } + +- @Override + public FriendlyByteBuf setLongLE(int i, long j) { + this.source.setLongLE(i, j); + return this; + } + +- @Override + public FriendlyByteBuf setChar(int i, int j) { + this.source.setChar(i, j); + return this; + } + +- @Override + public FriendlyByteBuf setFloat(int i, float f) { + this.source.setFloat(i, f); + return this; + } + +- @Override + public FriendlyByteBuf setDouble(int i, double d0) { + this.source.setDouble(i, d0); + return this; + } + +- @Override + public FriendlyByteBuf setBytes(int i, ByteBuf bytebuf) { + this.source.setBytes(i, bytebuf); + return this; + } + +- @Override + public FriendlyByteBuf setBytes(int i, ByteBuf bytebuf, int j) { + this.source.setBytes(i, bytebuf, j); + return this; + } + +- @Override + public FriendlyByteBuf setBytes(int i, ByteBuf bytebuf, int j, int k) { + this.source.setBytes(i, bytebuf, j, k); + return this; + } + +- @Override + public FriendlyByteBuf setBytes(int i, byte[] abyte) { + this.source.setBytes(i, abyte); + return this; + } + +- @Override + public FriendlyByteBuf setBytes(int i, byte[] abyte, int j, int k) { + this.source.setBytes(i, abyte, j, k); + return this; + } + +- @Override + public FriendlyByteBuf setBytes(int i, ByteBuffer bytebuffer) { + this.source.setBytes(i, bytebuffer); + return this; + } + +- @Override + public int setBytes(int i, InputStream inputstream, int j) throws IOException { + return this.source.setBytes(i, inputstream, j); + } + +- @Override + public int setBytes(int i, ScatteringByteChannel scatteringbytechannel, int j) throws IOException { + return this.source.setBytes(i, scatteringbytechannel, j); + } + +- @Override + public int setBytes(int i, FileChannel filechannel, long j, int k) throws IOException { + return this.source.setBytes(i, filechannel, j, k); + } + +- @Override + public FriendlyByteBuf setZero(int i, int j) { + this.source.setZero(i, j); + return this; + } + +- @Override + public int setCharSequence(int i, CharSequence charsequence, Charset charset) { + return this.source.setCharSequence(i, charsequence, charset); + } + +- @Override + public boolean readBoolean() { + return this.source.readBoolean(); + } + +- @Override + public byte readByte() { + return this.source.readByte(); + } + +- @Override + public short readUnsignedByte() { + return this.source.readUnsignedByte(); + } + +- @Override + public short readShort() { + return this.source.readShort(); + } + +- @Override + public short readShortLE() { + return this.source.readShortLE(); + } + +- @Override + public int readUnsignedShort() { + return this.source.readUnsignedShort(); + } + +- @Override + public int readUnsignedShortLE() { + return this.source.readUnsignedShortLE(); + } + +- @Override + public int readMedium() { + return this.source.readMedium(); + } + +- @Override + public int readMediumLE() { + return this.source.readMediumLE(); + } + +- @Override + public int readUnsignedMedium() { + return this.source.readUnsignedMedium(); + } + +- @Override + public int readUnsignedMediumLE() { + return this.source.readUnsignedMediumLE(); + } + +- @Override + public int readInt() { + return this.source.readInt(); + } + +- @Override + public int readIntLE() { + return this.source.readIntLE(); + } + +- @Override + public long readUnsignedInt() { + return this.source.readUnsignedInt(); + } + +- @Override + public long readUnsignedIntLE() { + return this.source.readUnsignedIntLE(); + } + +- @Override + public long readLong() { + return this.source.readLong(); + } + +- @Override + public long readLongLE() { + return this.source.readLongLE(); + } + +- @Override + public char readChar() { + return this.source.readChar(); + } + +- @Override + public float readFloat() { + return this.source.readFloat(); + } + +- @Override + public double readDouble() { + return this.source.readDouble(); + } + +- @Override + public ByteBuf readBytes(int i) { + return this.source.readBytes(i); + } + +- @Override + public ByteBuf readSlice(int i) { + return this.source.readSlice(i); + } + +- @Override + public ByteBuf readRetainedSlice(int i) { + return this.source.readRetainedSlice(i); + } + +- @Override + public FriendlyByteBuf readBytes(ByteBuf bytebuf) { + this.source.readBytes(bytebuf); + return this; + } + +- @Override + public FriendlyByteBuf readBytes(ByteBuf bytebuf, int i) { + this.source.readBytes(bytebuf, i); + return this; + } + +- @Override + public FriendlyByteBuf readBytes(ByteBuf bytebuf, int i, int j) { + this.source.readBytes(bytebuf, i, j); + return this; + } + +- @Override + public FriendlyByteBuf readBytes(byte[] abyte) { + this.source.readBytes(abyte); + return this; + } + +- @Override + public FriendlyByteBuf readBytes(byte[] abyte, int i, int j) { + this.source.readBytes(abyte, i, j); + return this; + } + +- @Override + public FriendlyByteBuf readBytes(ByteBuffer bytebuffer) { + this.source.readBytes(bytebuffer); + return this; + } + +- @Override + public FriendlyByteBuf readBytes(OutputStream outputstream, int i) throws IOException { + this.source.readBytes(outputstream, i); + return this; + } + +- @Override + public int readBytes(GatheringByteChannel gatheringbytechannel, int i) throws IOException { + return this.source.readBytes(gatheringbytechannel, i); + } + +- @Override + public CharSequence readCharSequence(int i, Charset charset) { + return this.source.readCharSequence(i, charset); + } + +- @Override + public int readBytes(FileChannel filechannel, long i, int j) throws IOException { + return this.source.readBytes(filechannel, i, j); + } + +- @Override + public FriendlyByteBuf skipBytes(int i) { + this.source.skipBytes(i); + return this; + } + +- @Override + public FriendlyByteBuf writeBoolean(boolean flag) { + this.source.writeBoolean(flag); + return this; + } + +- @Override + public FriendlyByteBuf writeByte(int i) { + this.source.writeByte(i); + return this; + } + +- @Override + public FriendlyByteBuf writeShort(int i) { + this.source.writeShort(i); + return this; + } + +- @Override + public FriendlyByteBuf writeShortLE(int i) { + this.source.writeShortLE(i); + return this; + } + +- @Override + public FriendlyByteBuf writeMedium(int i) { + this.source.writeMedium(i); + return this; + } + +- @Override + public FriendlyByteBuf writeMediumLE(int i) { + this.source.writeMediumLE(i); + return this; + } + +- @Override + public FriendlyByteBuf writeInt(int i) { + this.source.writeInt(i); + return this; + } + +- @Override + public FriendlyByteBuf writeIntLE(int i) { + this.source.writeIntLE(i); + return this; + } + +- @Override + public FriendlyByteBuf writeLong(long i) { + this.source.writeLong(i); + return this; + } + +- @Override + public FriendlyByteBuf writeLongLE(long i) { + this.source.writeLongLE(i); + return this; + } + +- @Override + public FriendlyByteBuf writeChar(int i) { + this.source.writeChar(i); + return this; + } + +- @Override + public FriendlyByteBuf writeFloat(float f) { + this.source.writeFloat(f); + return this; + } + +- @Override + public FriendlyByteBuf writeDouble(double d0) { + this.source.writeDouble(d0); + return this; + } + +- @Override + public FriendlyByteBuf writeBytes(ByteBuf bytebuf) { + this.source.writeBytes(bytebuf); + return this; + } + +- @Override + public FriendlyByteBuf writeBytes(ByteBuf bytebuf, int i) { + this.source.writeBytes(bytebuf, i); + return this; + } + +- @Override + public FriendlyByteBuf writeBytes(ByteBuf bytebuf, int i, int j) { + this.source.writeBytes(bytebuf, i, j); + return this; + } + +- @Override + public FriendlyByteBuf writeBytes(byte[] abyte) { + this.source.writeBytes(abyte); + return this; + } + +- @Override + public FriendlyByteBuf writeBytes(byte[] abyte, int i, int j) { + this.source.writeBytes(abyte, i, j); + return this; + } + +- @Override + public FriendlyByteBuf writeBytes(ByteBuffer bytebuffer) { + this.source.writeBytes(bytebuffer); + return this; + } + +- @Override + public int writeBytes(InputStream inputstream, int i) throws IOException { + return this.source.writeBytes(inputstream, i); + } + +- @Override + public int writeBytes(ScatteringByteChannel scatteringbytechannel, int i) throws IOException { + return this.source.writeBytes(scatteringbytechannel, i); + } + +- @Override + public int writeBytes(FileChannel filechannel, long i, int j) throws IOException { + return this.source.writeBytes(filechannel, i, j); + } + +- @Override + public FriendlyByteBuf writeZero(int i) { + this.source.writeZero(i); + return this; + } + +- @Override + public int writeCharSequence(CharSequence charsequence, Charset charset) { + return this.source.writeCharSequence(charsequence, charset); + } + +- @Override + public int indexOf(int i, int j, byte b0) { + return this.source.indexOf(i, j, b0); + } + +- @Override + public int bytesBefore(byte b0) { + return this.source.bytesBefore(b0); + } + +- @Override + public int bytesBefore(int i, byte b0) { + return this.source.bytesBefore(i, b0); + } + +- @Override + public int bytesBefore(int i, int j, byte b0) { + return this.source.bytesBefore(i, j, b0); + } + +- @Override + public int forEachByte(ByteProcessor byteprocessor) { + return this.source.forEachByte(byteprocessor); + } + +- @Override + public int forEachByte(int i, int j, ByteProcessor byteprocessor) { + return this.source.forEachByte(i, j, byteprocessor); + } + +- @Override + public int forEachByteDesc(ByteProcessor byteprocessor) { + return this.source.forEachByteDesc(byteprocessor); + } + +- @Override + public int forEachByteDesc(int i, int j, ByteProcessor byteprocessor) { + return this.source.forEachByteDesc(i, j, byteprocessor); + } + +- @Override + public ByteBuf copy() { + return this.source.copy(); + } + +- @Override + public ByteBuf copy(int i, int j) { + return this.source.copy(i, j); + } + +- @Override + public ByteBuf slice() { + return this.source.slice(); + } + +- @Override + public ByteBuf retainedSlice() { + return this.source.retainedSlice(); + } + +- @Override + public ByteBuf slice(int i, int j) { + return this.source.slice(i, j); + } + +- @Override + public ByteBuf retainedSlice(int i, int j) { + return this.source.retainedSlice(i, j); + } + +- @Override + public ByteBuf duplicate() { + return this.source.duplicate(); + } + +- @Override + public ByteBuf retainedDuplicate() { + return this.source.retainedDuplicate(); + } + +- @Override + public int nioBufferCount() { + return this.source.nioBufferCount(); + } + +- @Override + public ByteBuffer nioBuffer() { + return this.source.nioBuffer(); + } + +- @Override + public ByteBuffer nioBuffer(int i, int j) { + return this.source.nioBuffer(i, j); + } + +- @Override + public ByteBuffer internalNioBuffer(int i, int j) { + return this.source.internalNioBuffer(i, j); + } + +- @Override + public ByteBuffer[] nioBuffers() { + return this.source.nioBuffers(); + } + +- @Override + public ByteBuffer[] nioBuffers(int i, int j) { + return this.source.nioBuffers(i, j); + } + +- @Override + public boolean hasArray() { + return this.source.hasArray(); + } + +- @Override + public byte[] array() { + return this.source.array(); + } + +- @Override + public int arrayOffset() { + return this.source.arrayOffset(); + } + +- @Override + public boolean hasMemoryAddress() { + return this.source.hasMemoryAddress(); + } + +- @Override + public long memoryAddress() { + return this.source.memoryAddress(); + } + +- @Override + public String toString(Charset charset) { + return this.source.toString(charset); + } + +- @Override + public String toString(int i, int j, Charset charset) { + return this.source.toString(i, j, charset); + } + +- @Override + public int hashCode() { + return this.source.hashCode(); + } + +- @Override + public boolean equals(Object object) { + return this.source.equals(object); + } + +- @Override + public int compareTo(ByteBuf bytebuf) { + return this.source.compareTo(bytebuf); + } + +- @Override + public String toString() { + return this.source.toString(); + } + +- @Override + public FriendlyByteBuf retain(int i) { + this.source.retain(i); + return this; + } + +- @Override + public FriendlyByteBuf retain() { + this.source.retain(); + return this; + } + +- @Override + public FriendlyByteBuf touch() { + this.source.touch(); + return this; + } + +- @Override + public FriendlyByteBuf touch(Object object) { + this.source.touch(object); + return this; + } + +- @Override + public int refCnt() { + return this.source.refCnt(); + } + +- @Override + public boolean release() { + return this.source.release(); + } + +- @Override + public boolean release(int i) { + return this.source.release(i); + } + + @FunctionalInterface +- public interface Writer extends BiConsumer { ++ public interface b extends BiConsumer { + +- default FriendlyByteBuf.Writer> asOptional() { +- return (friendlybytebuf, optional) -> { +- friendlybytebuf.writeOptional(optional, this); ++ default FriendlyByteBuf.b> asOptional() { ++ return (packetdataserializer, optional) -> { ++ packetdataserializer.writeOptional(optional, this); + }; + } + } + + @FunctionalInterface +- public interface Reader extends Function { ++ public interface a extends Function { + +- default FriendlyByteBuf.Reader> asOptional() { +- return (friendlybytebuf) -> { +- return friendlybytebuf.readOptional(this); ++ default FriendlyByteBuf.a> asOptional() { ++ return (packetdataserializer) -> { ++ return packetdataserializer.readOptional(this); + }; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/network/chat/Component.java.patch b/patch-remap/mache-spigotflower/net/minecraft/network/chat/Component.java.patch new file mode 100644 index 0000000000..41ce78732e --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/network/chat/Component.java.patch @@ -0,0 +1,304 @@ +--- a/net/minecraft/network/chat/Component.java ++++ b/net/minecraft/network/chat/Component.java +@@ -26,32 +26,45 @@ + import net.minecraft.Util; + import net.minecraft.network.chat.contents.DataSource; + import net.minecraft.network.chat.contents.KeybindContents; ++import net.minecraft.network.chat.contents.LiteralContents; + import net.minecraft.network.chat.contents.NbtContents; +-import net.minecraft.network.chat.contents.PlainTextContents; + import net.minecraft.network.chat.contents.ScoreContents; + import net.minecraft.network.chat.contents.SelectorContents; + import net.minecraft.network.chat.contents.TranslatableContents; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.util.FormattedCharSequence; + import net.minecraft.world.level.ChunkPos; ++// CraftBukkit start ++import java.util.stream.Stream; ++// CraftBukkit end + +-public interface Component extends Message, FormattedText { ++public interface Component extends Message, FormattedText, Iterable { // CraftBukkit + ++ // CraftBukkit start ++ default Stream stream() { ++ return com.google.common.collect.Streams.concat(new Stream[]{Stream.of(this), this.getSiblings().stream().flatMap(Component::stream)}); ++ } ++ ++ @Override ++ default Iterator iterator() { ++ return this.stream().iterator(); ++ } ++ // CraftBukkit end ++ + Style getStyle(); + + ComponentContents getContents(); + + @Override +- @Override + default String getString() { + return FormattedText.super.getString(); + } + +- default String getString(int i) { ++ default String getString(int maxLength) { + StringBuilder stringbuilder = new StringBuilder(); + + this.visit((s) -> { +- int j = i - stringbuilder.length(); ++ int j = maxLength - stringbuilder.length(); + + if (j <= 0) { + return Component.STOP_ITERATION; +@@ -69,11 +82,11 @@ + default String tryCollapseToString() { + ComponentContents componentcontents = this.getContents(); + +- if (componentcontents instanceof PlainTextContents) { +- PlainTextContents plaintextcontents = (PlainTextContents) componentcontents; ++ if (componentcontents instanceof LiteralContents) { ++ LiteralContents literalcontents = (LiteralContents) componentcontents; + + if (this.getSiblings().isEmpty() && this.getStyle().isEmpty()) { +- return plaintextcontents.text(); ++ return literalcontents.text(); + } + } + +@@ -91,10 +104,9 @@ + FormattedCharSequence getVisualOrderText(); + + @Override +- @Override +- default Optional visit(FormattedText.StyledContentConsumer formattedtext_styledcontentconsumer, Style style) { +- Style style1 = this.getStyle().applyTo(style); +- Optional optional = this.getContents().visit(formattedtext_styledcontentconsumer, style1); ++ default Optional visit(FormattedText.StyledContentConsumer acceptor, Style style) { ++ Style chatmodifier1 = this.getStyle().applyTo(style); ++ Optional optional = this.getContents().visit(acceptor, chatmodifier1); + + if (optional.isPresent()) { + return optional; +@@ -108,9 +120,9 @@ + return Optional.empty(); + } + +- Component component = (Component) iterator.next(); ++ Component ichatbasecomponent = (Component) iterator.next(); + +- optional1 = component.visit(formattedtext_styledcontentconsumer, style1); ++ optional1 = ichatbasecomponent.visit(acceptor, chatmodifier1); + } while (!optional1.isPresent()); + + return optional1; +@@ -118,9 +130,8 @@ + } + + @Override +- @Override +- default Optional visit(FormattedText.ContentConsumer formattedtext_contentconsumer) { +- Optional optional = this.getContents().visit(formattedtext_contentconsumer); ++ default Optional visit(FormattedText.ContentConsumer acceptor) { ++ Optional optional = this.getContents().visit(acceptor); + + if (optional.isPresent()) { + return optional; +@@ -134,9 +145,9 @@ + return Optional.empty(); + } + +- Component component = (Component) iterator.next(); ++ Component ichatbasecomponent = (Component) iterator.next(); + +- optional1 = component.visit(formattedtext_contentconsumer); ++ optional1 = ichatbasecomponent.visit(acceptor); + } while (!optional1.isPresent()); + + return optional1; +@@ -150,9 +161,9 @@ + default List toFlatList(Style style) { + List list = Lists.newArrayList(); + +- this.visit((style1, s) -> { ++ this.visit((chatmodifier1, s) -> { + if (!s.isEmpty()) { +- list.add(literal(s).withStyle(style1)); ++ list.add(literal(s).withStyle(chatmodifier1)); + } + + return Optional.empty(); +@@ -160,31 +171,31 @@ + return list; + } + +- default boolean contains(Component component) { +- if (this.equals(component)) { ++ default boolean contains(Component other) { ++ if (this.equals(other)) { + return true; + } else { + List list = this.toFlatList(); +- List list1 = component.toFlatList(this.getStyle()); ++ List list1 = other.toFlatList(this.getStyle()); + + return Collections.indexOfSubList(list, list1) != -1; + } + } + +- static Component nullToEmpty(@Nullable String s) { +- return (Component) (s != null ? literal(s) : CommonComponents.EMPTY); ++ static Component nullToEmpty(@Nullable String text) { ++ return (Component) (text != null ? literal(text) : CommonComponents.EMPTY); + } + +- static MutableComponent literal(String s) { +- return MutableComponent.create(PlainTextContents.create(s)); ++ static MutableComponent literal(String text) { ++ return MutableComponent.create(LiteralContents.create(text)); + } + +- static MutableComponent translatable(String s) { +- return MutableComponent.create(new TranslatableContents(s, (String) null, TranslatableContents.NO_ARGS)); ++ static MutableComponent translatable(String key) { ++ return MutableComponent.create(new TranslatableContents(key, (String) null, TranslatableContents.NO_ARGS)); + } + +- static MutableComponent translatable(String s, Object... aobject) { +- return MutableComponent.create(new TranslatableContents(s, (String) null, aobject)); ++ static MutableComponent translatable(String key, Object... args) { ++ return MutableComponent.create(new TranslatableContents(key, (String) null, args)); + } + + static MutableComponent translatableEscape(String s, Object... aobject) { +@@ -199,32 +210,32 @@ + return translatable(s, aobject); + } + +- static MutableComponent translatableWithFallback(String s, @Nullable String s1) { +- return MutableComponent.create(new TranslatableContents(s, s1, TranslatableContents.NO_ARGS)); ++ static MutableComponent translatableWithFallback(String key, @Nullable String fallback) { ++ return MutableComponent.create(new TranslatableContents(key, fallback, TranslatableContents.NO_ARGS)); + } + +- static MutableComponent translatableWithFallback(String s, @Nullable String s1, Object... aobject) { +- return MutableComponent.create(new TranslatableContents(s, s1, aobject)); ++ static MutableComponent translatableWithFallback(String key, @Nullable String fallback, Object... args) { ++ return MutableComponent.create(new TranslatableContents(key, fallback, args)); + } + + static MutableComponent empty() { +- return MutableComponent.create(PlainTextContents.EMPTY); ++ return MutableComponent.create(LiteralContents.EMPTY); + } + +- static MutableComponent keybind(String s) { +- return MutableComponent.create(new KeybindContents(s)); ++ static MutableComponent keybind(String name) { ++ return MutableComponent.create(new KeybindContents(name)); + } + +- static MutableComponent nbt(String s, boolean flag, Optional optional, DataSource datasource) { +- return MutableComponent.create(new NbtContents(s, flag, optional, datasource)); ++ static MutableComponent nbt(String nbtPathPattern, boolean interpreting, Optional separator, DataSource dataSource) { ++ return MutableComponent.create(new NbtContents(nbtPathPattern, interpreting, separator, dataSource)); + } + +- static MutableComponent score(String s, String s1) { +- return MutableComponent.create(new ScoreContents(s, s1)); ++ static MutableComponent score(String name, String objective) { ++ return MutableComponent.create(new ScoreContents(name, objective)); + } + +- static MutableComponent selector(String s, Optional optional) { +- return MutableComponent.create(new SelectorContents(s, optional)); ++ static MutableComponent selector(String pattern, Optional separator) { ++ return MutableComponent.create(new SelectorContents(pattern, separator)); + } + + static Component translationArg(Date date) { +@@ -235,9 +246,9 @@ + Object object; + + if (message instanceof Component) { +- Component component = (Component) message; ++ Component ichatbasecomponent = (Component) message; + +- object = component; ++ object = ichatbasecomponent; + } else { + object = literal(message.getString()); + } +@@ -249,26 +260,24 @@ + return literal(uuid.toString()); + } + +- static Component translationArg(ResourceLocation resourcelocation) { +- return literal(resourcelocation.toString()); ++ static Component translationArg(ResourceLocation minecraftkey) { ++ return literal(minecraftkey.toString()); + } + +- static Component translationArg(ChunkPos chunkpos) { +- return literal(chunkpos.toString()); ++ static Component translationArg(ChunkPos chunkcoordintpair) { ++ return literal(chunkcoordintpair.toString()); + } + +- public static class SerializerAdapter implements JsonDeserializer, JsonSerializer { ++ public static class b implements JsonDeserializer, JsonSerializer { + +- public SerializerAdapter() {} ++ public b() {} + +- @Override + public MutableComponent deserialize(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException { + return Component.Serializer.deserialize(jsonelement); + } + +- @Override +- public JsonElement serialize(Component component, Type type, JsonSerializationContext jsonserializationcontext) { +- return Component.Serializer.serialize(component); ++ public JsonElement serialize(Component ichatbasecomponent, Type type, JsonSerializationContext jsonserializationcontext) { ++ return Component.Serializer.serialize(ichatbasecomponent); + } + } + +@@ -282,8 +291,8 @@ + return (MutableComponent) Util.getOrThrow(ComponentSerialization.CODEC.parse(JsonOps.INSTANCE, jsonelement), JsonParseException::new); + } + +- static JsonElement serialize(Component component) { +- return (JsonElement) Util.getOrThrow(ComponentSerialization.CODEC.encodeStart(JsonOps.INSTANCE, component), JsonParseException::new); ++ static JsonElement serialize(Component ichatbasecomponent) { ++ return (JsonElement) Util.getOrThrow(ComponentSerialization.CODEC.encodeStart(JsonOps.INSTANCE, ichatbasecomponent), JsonParseException::new); + } + + public static String toJson(Component component) { +@@ -295,20 +304,20 @@ + } + + @Nullable +- public static MutableComponent fromJson(String s) { +- JsonElement jsonelement = JsonParser.parseString(s); ++ public static MutableComponent fromJson(String json) { ++ JsonElement jsonelement = JsonParser.parseString(json); + + return jsonelement == null ? null : deserialize(jsonelement); + } + + @Nullable +- public static MutableComponent fromJson(@Nullable JsonElement jsonelement) { +- return jsonelement == null ? null : deserialize(jsonelement); ++ public static MutableComponent fromJson(@Nullable JsonElement json) { ++ return json == null ? null : deserialize(json); + } + + @Nullable +- public static MutableComponent fromJsonLenient(String s) { +- JsonReader jsonreader = new JsonReader(new StringReader(s)); ++ public static MutableComponent fromJsonLenient(String json) { ++ JsonReader jsonreader = new JsonReader(new StringReader(json)); + + jsonreader.setLenient(true); + JsonElement jsonelement = JsonParser.parseReader(jsonreader); diff --git a/patch-remap/mache-spigotflower/net/minecraft/network/chat/TextColor.java.patch b/patch-remap/mache-spigotflower/net/minecraft/network/chat/TextColor.java.patch new file mode 100644 index 0000000000..643fcab5a1 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/network/chat/TextColor.java.patch @@ -0,0 +1,100 @@ +--- a/net/minecraft/network/chat/TextColor.java ++++ b/net/minecraft/network/chat/TextColor.java +@@ -16,25 +16,31 @@ + + private static final String CUSTOM_COLOR_PREFIX = "#"; + public static final Codec CODEC = Codec.STRING.comapFlatMap(TextColor::parseColor, TextColor::serialize); +- private static final Map LEGACY_FORMAT_TO_COLOR = (Map) Stream.of(ChatFormatting.values()).filter(ChatFormatting::isColor).collect(ImmutableMap.toImmutableMap(Function.identity(), (chatformatting) -> { +- return new TextColor(chatformatting.getColor(), chatformatting.getName()); ++ private static final Map LEGACY_FORMAT_TO_COLOR = (Map) Stream.of(ChatFormatting.values()).filter(ChatFormatting::isColor).collect(ImmutableMap.toImmutableMap(Function.identity(), (enumchatformat) -> { ++ return new TextColor(enumchatformat.getColor(), enumchatformat.getName(), enumchatformat); // CraftBukkit + })); +- private static final Map NAMED_COLORS = (Map) TextColor.LEGACY_FORMAT_TO_COLOR.values().stream().collect(ImmutableMap.toImmutableMap((textcolor) -> { +- return textcolor.name; ++ private static final Map NAMED_COLORS = (Map) TextColor.LEGACY_FORMAT_TO_COLOR.values().stream().collect(ImmutableMap.toImmutableMap((chathexcolor) -> { ++ return chathexcolor.name; + }, Function.identity())); + private final int value; + @Nullable +- private final String name; ++ public final String name; ++ // CraftBukkit start ++ @Nullable ++ public final ChatFormatting format; + +- private TextColor(int i, String s) { ++ private TextColor(int i, String s, ChatFormatting format) { + this.value = i & 16777215; + this.name = s; ++ this.format = format; + } + +- private TextColor(int i) { +- this.value = i & 16777215; ++ private TextColor(int value) { ++ this.value = value & 16777215; + this.name = null; ++ this.format = null; + } ++ // CraftBukkit end + + public int getValue() { + return this.value; +@@ -48,36 +54,33 @@ + return String.format(Locale.ROOT, "#%06X", this.value); + } + +- @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } else if (object != null && this.getClass() == object.getClass()) { +- TextColor textcolor = (TextColor) object; ++ TextColor chathexcolor = (TextColor) object; + +- return this.value == textcolor.value; ++ return this.value == chathexcolor.value; + } else { + return false; + } + } + +- @Override + public int hashCode() { + return Objects.hash(new Object[]{this.value, this.name}); + } + +- @Override + public String toString() { + return this.serialize(); + } + + @Nullable +- public static TextColor fromLegacyFormat(ChatFormatting chatformatting) { +- return (TextColor) TextColor.LEGACY_FORMAT_TO_COLOR.get(chatformatting); ++ public static TextColor fromLegacyFormat(ChatFormatting formatting) { ++ return (TextColor) TextColor.LEGACY_FORMAT_TO_COLOR.get(formatting); + } + +- public static TextColor fromRgb(int i) { +- return new TextColor(i); ++ public static TextColor fromRgb(int color) { ++ return new TextColor(color); + } + + public static DataResult parseColor(String s) { +@@ -94,11 +97,11 @@ + }); + } + } else { +- TextColor textcolor = (TextColor) TextColor.NAMED_COLORS.get(s); ++ TextColor chathexcolor = (TextColor) TextColor.NAMED_COLORS.get(s); + +- return textcolor == null ? DataResult.error(() -> { ++ return chathexcolor == null ? DataResult.error(() -> { + return "Invalid color name: " + s; +- }) : DataResult.success(textcolor, Lifecycle.stable()); ++ }) : DataResult.success(chathexcolor, Lifecycle.stable()); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/network/protocol/PacketUtils.java.patch b/patch-remap/mache-spigotflower/net/minecraft/network/protocol/PacketUtils.java.patch new file mode 100644 index 0000000000..eae575f793 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/network/protocol/PacketUtils.java.patch @@ -0,0 +1,83 @@ +--- a/net/minecraft/network/protocol/PacketUtils.java ++++ b/net/minecraft/network/protocol/PacketUtils.java +@@ -4,10 +4,15 @@ + import net.minecraft.CrashReport; + import net.minecraft.ReportedException; + import net.minecraft.network.PacketListener; +-import net.minecraft.server.RunningOnDifferentThreadException; ++import net.minecraft.server.CancelledPacketHandleException; ++import org.slf4j.Logger; ++ ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.network.ServerCommonPacketListenerImpl; ++// CraftBukkit end + import net.minecraft.util.thread.BlockableEventLoop; +-import org.slf4j.Logger; + + public class PacketUtils { + +@@ -15,16 +20,17 @@ + + public PacketUtils() {} + +- public static void ensureRunningOnSameThread(Packet packet, T t0, ServerLevel serverlevel) throws RunningOnDifferentThreadException { +- ensureRunningOnSameThread(packet, t0, (BlockableEventLoop) serverlevel.getServer()); ++ public static void ensureRunningOnSameThread(Packet packet, T processor, ServerLevel level) throws CancelledPacketHandleException { ++ ensureRunningOnSameThread(packet, processor, (BlockableEventLoop) level.getServer()); + } + +- public static void ensureRunningOnSameThread(Packet packet, T t0, BlockableEventLoop blockableeventloop) throws RunningOnDifferentThreadException { +- if (!blockableeventloop.isSameThread()) { +- blockableeventloop.executeIfPossible(() -> { +- if (t0.shouldHandleMessage(packet)) { ++ public static void ensureRunningOnSameThread(Packet packet, T processor, BlockableEventLoop executor) throws CancelledPacketHandleException { ++ if (!executor.isSameThread()) { ++ executor.executeIfPossible(() -> { ++ if (MinecraftServer.getServer().hasStopped() || (processor instanceof ServerCommonPacketListenerImpl && ((ServerCommonPacketListenerImpl) processor).processedDisconnect)) return; // CraftBukkit, MC-142590 ++ if (processor.shouldHandleMessage(packet)) { + try { +- packet.handle(t0); ++ packet.handle(processor); + } catch (Exception exception) { + label25: + { +@@ -36,7 +42,7 @@ + } + } + +- if (!t0.shouldPropagateHandlingExceptions()) { ++ if (!processor.shouldPropagateHandlingExceptions()) { + PacketUtils.LOGGER.error("Failed to handle packet {}, suppressing error", packet, exception); + return; + } +@@ -45,13 +51,13 @@ + if (exception instanceof ReportedException) { + ReportedException reportedexception1 = (ReportedException) exception; + +- t0.fillCrashReport(reportedexception1.getReport()); ++ processor.fillCrashReport(reportedexception1.getReport()); + throw exception; + } + + CrashReport crashreport = CrashReport.forThrowable(exception, "Main thread packet handler"); + +- t0.fillCrashReport(crashreport); ++ processor.fillCrashReport(crashreport); + throw new ReportedException(crashreport); + } + } else { +@@ -59,7 +65,11 @@ + } + + }); +- throw RunningOnDifferentThreadException.RUNNING_ON_DIFFERENT_THREAD; ++ throw CancelledPacketHandleException.RUNNING_ON_DIFFERENT_THREAD; ++ // CraftBukkit start - SPIGOT-5477, MC-142590 ++ } else if (MinecraftServer.getServer().hasStopped() || (processor instanceof ServerCommonPacketListenerImpl && ((ServerCommonPacketListenerImpl) processor).processedDisconnect)) { ++ throw CancelledPacketHandleException.RUNNING_ON_DIFFERENT_THREAD; ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java.patch b/patch-remap/mache-spigotflower/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java.patch new file mode 100644 index 0000000000..7209c3be34 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java.patch @@ -0,0 +1,67 @@ +--- a/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java ++++ b/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java +@@ -12,38 +12,47 @@ + public record ServerboundCustomPayloadPacket(CustomPacketPayload payload) implements Packet { + + private static final int MAX_PAYLOAD_SIZE = 32767; +- private static final Map> KNOWN_TYPES = ImmutableMap.builder().put(BrandPayload.ID, BrandPayload::new).build(); ++ private static final Map> KNOWN_TYPES = ImmutableMap.>builder().build(); // CraftBukkit - no special handling + +- public ServerboundCustomPayloadPacket(FriendlyByteBuf friendlybytebuf) { +- this(readPayload(friendlybytebuf.readResourceLocation(), friendlybytebuf)); ++ public ServerboundCustomPayloadPacket(FriendlyByteBuf packetdataserializer) { ++ this(readPayload(packetdataserializer.readResourceLocation(), packetdataserializer)); + } + +- private static CustomPacketPayload readPayload(ResourceLocation resourcelocation, FriendlyByteBuf friendlybytebuf) { +- FriendlyByteBuf.Reader friendlybytebuf_reader = (FriendlyByteBuf.Reader) ServerboundCustomPayloadPacket.KNOWN_TYPES.get(resourcelocation); ++ private static CustomPacketPayload readPayload(ResourceLocation minecraftkey, FriendlyByteBuf packetdataserializer) { ++ FriendlyByteBuf.a packetdataserializer_a = (FriendlyByteBuf.a) ServerboundCustomPayloadPacket.KNOWN_TYPES.get(minecraftkey); + +- return (CustomPacketPayload) (friendlybytebuf_reader != null ? (CustomPacketPayload) friendlybytebuf_reader.apply(friendlybytebuf) : readUnknownPayload(resourcelocation, friendlybytebuf)); ++ return (CustomPacketPayload) (packetdataserializer_a != null ? (CustomPacketPayload) packetdataserializer_a.apply(packetdataserializer) : readUnknownPayload(minecraftkey, packetdataserializer)); + } + +- private static DiscardedPayload readUnknownPayload(ResourceLocation resourcelocation, FriendlyByteBuf friendlybytebuf) { +- int i = friendlybytebuf.readableBytes(); ++ private static UnknownPayload readUnknownPayload(ResourceLocation minecraftkey, FriendlyByteBuf packetdataserializer) { // CraftBukkit ++ int i = packetdataserializer.readableBytes(); + + if (i >= 0 && i <= 32767) { +- friendlybytebuf.skipBytes(i); +- return new DiscardedPayload(resourcelocation); ++ // CraftBukkit start ++ return new UnknownPayload(minecraftkey, packetdataserializer.readBytes(i)); ++ // CraftBukkit end + } else { + throw new IllegalArgumentException("Payload may not be larger than 32767 bytes"); + } + } + + @Override +- @Override +- public void write(FriendlyByteBuf friendlybytebuf) { +- friendlybytebuf.writeResourceLocation(this.payload.id()); +- this.payload.write(friendlybytebuf); ++ public void write(FriendlyByteBuf buffer) { ++ buffer.writeResourceLocation(this.payload.id()); ++ this.payload.write(buffer); + } + +- @Override +- public void handle(ServerCommonPacketListener servercommonpacketlistener) { +- servercommonpacketlistener.handleCustomPayload(this); ++ public void handle(ServerCommonPacketListener handler) { ++ handler.handleCustomPayload(this); + } ++ ++ // CraftBukkit start ++ public record UnknownPayload(ResourceLocation id, io.netty.buffer.ByteBuf data) implements CustomPacketPayload { ++ ++ @Override ++ public void write(FriendlyByteBuf packetdataserializer) { ++ packetdataserializer.writeBytes(data); ++ } ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java.patch b/patch-remap/mache-spigotflower/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java.patch new file mode 100644 index 0000000000..abca0f1fb1 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java.patch @@ -0,0 +1,78 @@ +--- a/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java ++++ b/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java +@@ -15,44 +15,44 @@ + private final int warningBlocks; + private final int warningTime; + +- public ClientboundInitializeBorderPacket(FriendlyByteBuf friendlybytebuf) { +- this.newCenterX = friendlybytebuf.readDouble(); +- this.newCenterZ = friendlybytebuf.readDouble(); +- this.oldSize = friendlybytebuf.readDouble(); +- this.newSize = friendlybytebuf.readDouble(); +- this.lerpTime = friendlybytebuf.readVarLong(); +- this.newAbsoluteMaxSize = friendlybytebuf.readVarInt(); +- this.warningBlocks = friendlybytebuf.readVarInt(); +- this.warningTime = friendlybytebuf.readVarInt(); ++ public ClientboundInitializeBorderPacket(FriendlyByteBuf buffer) { ++ this.newCenterX = buffer.readDouble(); ++ this.newCenterZ = buffer.readDouble(); ++ this.oldSize = buffer.readDouble(); ++ this.newSize = buffer.readDouble(); ++ this.lerpTime = buffer.readVarLong(); ++ this.newAbsoluteMaxSize = buffer.readVarInt(); ++ this.warningBlocks = buffer.readVarInt(); ++ this.warningTime = buffer.readVarInt(); + } + +- public ClientboundInitializeBorderPacket(WorldBorder worldborder) { +- this.newCenterX = worldborder.getCenterX(); +- this.newCenterZ = worldborder.getCenterZ(); +- this.oldSize = worldborder.getSize(); +- this.newSize = worldborder.getLerpTarget(); +- this.lerpTime = worldborder.getLerpRemainingTime(); +- this.newAbsoluteMaxSize = worldborder.getAbsoluteMaxSize(); +- this.warningBlocks = worldborder.getWarningBlocks(); +- this.warningTime = worldborder.getWarningTime(); ++ public ClientboundInitializeBorderPacket(WorldBorder worldBorder) { ++ // CraftBukkit start - multiply out nether border ++ this.newCenterX = worldBorder.getCenterX() * worldBorder.world.dimensionType().coordinateScale(); ++ this.newCenterZ = worldBorder.getCenterZ() * worldBorder.world.dimensionType().coordinateScale(); ++ // CraftBukkit end ++ this.oldSize = worldBorder.getSize(); ++ this.newSize = worldBorder.getLerpTarget(); ++ this.lerpTime = worldBorder.getLerpRemainingTime(); ++ this.newAbsoluteMaxSize = worldBorder.getAbsoluteMaxSize(); ++ this.warningBlocks = worldBorder.getWarningBlocks(); ++ this.warningTime = worldBorder.getWarningTime(); + } + + @Override +- @Override +- public void write(FriendlyByteBuf friendlybytebuf) { +- friendlybytebuf.writeDouble(this.newCenterX); +- friendlybytebuf.writeDouble(this.newCenterZ); +- friendlybytebuf.writeDouble(this.oldSize); +- friendlybytebuf.writeDouble(this.newSize); +- friendlybytebuf.writeVarLong(this.lerpTime); +- friendlybytebuf.writeVarInt(this.newAbsoluteMaxSize); +- friendlybytebuf.writeVarInt(this.warningBlocks); +- friendlybytebuf.writeVarInt(this.warningTime); ++ public void write(FriendlyByteBuf buffer) { ++ buffer.writeDouble(this.newCenterX); ++ buffer.writeDouble(this.newCenterZ); ++ buffer.writeDouble(this.oldSize); ++ buffer.writeDouble(this.newSize); ++ buffer.writeVarLong(this.lerpTime); ++ buffer.writeVarInt(this.newAbsoluteMaxSize); ++ buffer.writeVarInt(this.warningBlocks); ++ buffer.writeVarInt(this.warningTime); + } + +- @Override +- public void handle(ClientGamePacketListener clientgamepacketlistener) { +- clientgamepacketlistener.handleInitializeBorder(this); ++ public void handle(ClientGamePacketListener handler) { ++ handler.handleInitializeBorder(this); + } + + public double getNewCenterX() { diff --git a/patch-remap/mache-spigotflower/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java.patch b/patch-remap/mache-spigotflower/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java.patch new file mode 100644 index 0000000000..35b491f95b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java.patch @@ -0,0 +1,109 @@ +--- a/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java ++++ b/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java +@@ -8,7 +8,7 @@ + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.protocol.Packet; + import net.minecraft.world.level.block.Block; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.LevelChunkSection; + + public class ClientboundSectionBlocksUpdatePacket implements Packet { +@@ -16,66 +16,72 @@ + private static final int POS_IN_SECTION_BITS = 12; + private final SectionPos sectionPos; + private final short[] positions; +- private final BlockState[] states; ++ private final IBlockData[] states; + +- public ClientboundSectionBlocksUpdatePacket(SectionPos sectionpos, ShortSet shortset, LevelChunkSection levelchunksection) { +- this.sectionPos = sectionpos; +- int i = shortset.size(); ++ public ClientboundSectionBlocksUpdatePacket(SectionPos sectionPos, ShortSet positions, LevelChunkSection section) { ++ this.sectionPos = sectionPos; ++ int i = positions.size(); + + this.positions = new short[i]; +- this.states = new BlockState[i]; ++ this.states = new IBlockData[i]; + int j = 0; + +- for (ShortIterator shortiterator = shortset.iterator(); shortiterator.hasNext(); ++j) { ++ for (ShortIterator shortiterator = positions.iterator(); shortiterator.hasNext(); ++j) { + short short0 = (Short) shortiterator.next(); + + this.positions[j] = short0; +- this.states[j] = levelchunksection.getBlockState(SectionPos.sectionRelativeX(short0), SectionPos.sectionRelativeY(short0), SectionPos.sectionRelativeZ(short0)); ++ this.states[j] = (section != null) ? section.getBlockState(SectionPos.sectionRelativeX(short0), SectionPos.sectionRelativeY(short0), SectionPos.sectionRelativeZ(short0)) : net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(); // CraftBukkit - SPIGOT-6076, Mojang bug when empty chunk section notified + } + + } + +- public ClientboundSectionBlocksUpdatePacket(FriendlyByteBuf friendlybytebuf) { +- this.sectionPos = SectionPos.of(friendlybytebuf.readLong()); +- int i = friendlybytebuf.readVarInt(); ++ // CraftBukkit start - Add constructor ++ public ClientboundSectionBlocksUpdatePacket(SectionPos sectionposition, ShortSet shortset, IBlockData[] states) { ++ this.sectionPos = sectionposition; ++ this.positions = shortset.toShortArray(); ++ this.states = states; ++ } ++ // CraftBukkit end + ++ public ClientboundSectionBlocksUpdatePacket(FriendlyByteBuf buffer) { ++ this.sectionPos = SectionPos.of(buffer.readLong()); ++ int i = buffer.readVarInt(); ++ + this.positions = new short[i]; +- this.states = new BlockState[i]; ++ this.states = new IBlockData[i]; + + for (int j = 0; j < i; ++j) { +- long k = friendlybytebuf.readVarLong(); ++ long k = buffer.readVarLong(); + + this.positions[j] = (short) ((int) (k & 4095L)); +- this.states[j] = (BlockState) Block.BLOCK_STATE_REGISTRY.byId((int) (k >>> 12)); ++ this.states[j] = (IBlockData) Block.BLOCK_STATE_REGISTRY.byId((int) (k >>> 12)); + } + + } + + @Override +- @Override +- public void write(FriendlyByteBuf friendlybytebuf) { +- friendlybytebuf.writeLong(this.sectionPos.asLong()); +- friendlybytebuf.writeVarInt(this.positions.length); ++ public void write(FriendlyByteBuf buffer) { ++ buffer.writeLong(this.sectionPos.asLong()); ++ buffer.writeVarInt(this.positions.length); + + for (int i = 0; i < this.positions.length; ++i) { +- friendlybytebuf.writeVarLong((long) Block.getId(this.states[i]) << 12 | (long) this.positions[i]); ++ buffer.writeVarLong((long) Block.getId(this.states[i]) << 12 | (long) this.positions[i]); + } + + } + +- @Override +- public void handle(ClientGamePacketListener clientgamepacketlistener) { +- clientgamepacketlistener.handleChunkBlocksUpdate(this); ++ public void handle(ClientGamePacketListener handler) { ++ handler.handleChunkBlocksUpdate(this); + } + +- public void runUpdates(BiConsumer biconsumer) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ public void runUpdates(BiConsumer consumer) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + + for (int i = 0; i < this.positions.length; ++i) { + short short0 = this.positions[i]; + +- blockpos_mutableblockpos.set(this.sectionPos.relativeToBlockX(short0), this.sectionPos.relativeToBlockY(short0), this.sectionPos.relativeToBlockZ(short0)); +- biconsumer.accept(blockpos_mutableblockpos, this.states[i]); ++ blockposition_mutableblockposition.set(this.sectionPos.relativeToBlockX(short0), this.sectionPos.relativeToBlockY(short0), this.sectionPos.relativeToBlockZ(short0)); ++ consumer.accept(blockposition_mutableblockposition, this.states[i]); + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java.patch b/patch-remap/mache-spigotflower/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java.patch new file mode 100644 index 0000000000..5ac38655e0 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java ++++ b/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java +@@ -9,26 +9,26 @@ + private final double newCenterX; + private final double newCenterZ; + +- public ClientboundSetBorderCenterPacket(WorldBorder worldborder) { +- this.newCenterX = worldborder.getCenterX(); +- this.newCenterZ = worldborder.getCenterZ(); ++ public ClientboundSetBorderCenterPacket(WorldBorder worldBorder) { ++ // CraftBukkit start - multiply out nether border ++ this.newCenterX = worldBorder.getCenterX() * (worldBorder.world != null ? worldBorder.world.dimensionType().coordinateScale() : 1.0); ++ this.newCenterZ = worldBorder.getCenterZ() * (worldBorder.world != null ? worldBorder.world.dimensionType().coordinateScale() : 1.0); ++ // CraftBukkit end + } + +- public ClientboundSetBorderCenterPacket(FriendlyByteBuf friendlybytebuf) { +- this.newCenterX = friendlybytebuf.readDouble(); +- this.newCenterZ = friendlybytebuf.readDouble(); ++ public ClientboundSetBorderCenterPacket(FriendlyByteBuf buffer) { ++ this.newCenterX = buffer.readDouble(); ++ this.newCenterZ = buffer.readDouble(); + } + + @Override +- @Override +- public void write(FriendlyByteBuf friendlybytebuf) { +- friendlybytebuf.writeDouble(this.newCenterX); +- friendlybytebuf.writeDouble(this.newCenterZ); ++ public void write(FriendlyByteBuf buffer) { ++ buffer.writeDouble(this.newCenterX); ++ buffer.writeDouble(this.newCenterZ); + } + +- @Override +- public void handle(ClientGamePacketListener clientgamepacketlistener) { +- clientgamepacketlistener.handleSetBorderCenter(this); ++ public void handle(ClientGamePacketListener handler) { ++ handler.handleSetBorderCenter(this); + } + + public double getNewCenterZ() { diff --git a/patch-remap/mache-spigotflower/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.java.patch b/patch-remap/mache-spigotflower/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.java.patch new file mode 100644 index 0000000000..0cdd79b9c8 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.java.patch @@ -0,0 +1,39 @@ +--- a/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.java ++++ b/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.network.protocol.game; + + import net.minecraft.network.FriendlyByteBuf; +@@ -6,24 +7,21 @@ + + public record ClientboundSystemChatPacket(Component content, boolean overlay) implements Packet { + +- public ClientboundSystemChatPacket(FriendlyByteBuf friendlybytebuf) { +- this(friendlybytebuf.readComponentTrusted(), friendlybytebuf.readBoolean()); ++ public ClientboundSystemChatPacket(FriendlyByteBuf buffer) { ++ this(buffer.readComponentTrusted(), buffer.readBoolean()); + } + + @Override +- @Override +- public void write(FriendlyByteBuf friendlybytebuf) { +- friendlybytebuf.writeComponent(this.content); +- friendlybytebuf.writeBoolean(this.overlay); ++ public void write(FriendlyByteBuf buffer) { ++ buffer.writeComponent(this.content); ++ buffer.writeBoolean(this.overlay); + } + +- @Override +- public void handle(ClientGamePacketListener clientgamepacketlistener) { +- clientgamepacketlistener.handleSystemChat(this); ++ public void handle(ClientGamePacketListener handler) { ++ handler.handleSystemChat(this); + } + + @Override +- @Override + public boolean isSkippable() { + return true; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/network/protocol/game/ServerboundUseItemOnPacket.java.patch b/patch-remap/mache-spigotflower/net/minecraft/network/protocol/game/ServerboundUseItemOnPacket.java.patch new file mode 100644 index 0000000000..b1f7aa6e0c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/network/protocol/game/ServerboundUseItemOnPacket.java.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/network/protocol/game/ServerboundUseItemOnPacket.java ++++ b/net/minecraft/network/protocol/game/ServerboundUseItemOnPacket.java +@@ -1,42 +1,41 @@ ++// mc-dev import + package net.minecraft.network.protocol.game; + + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.protocol.Packet; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.phys.BlockHitResult; + + public class ServerboundUseItemOnPacket implements Packet { + + private final BlockHitResult blockHit; +- private final InteractionHand hand; ++ private final EnumHand hand; + private final int sequence; + +- public ServerboundUseItemOnPacket(InteractionHand interactionhand, BlockHitResult blockhitresult, int i) { +- this.hand = interactionhand; +- this.blockHit = blockhitresult; +- this.sequence = i; ++ public ServerboundUseItemOnPacket(EnumHand hand, BlockHitResult blockHit, int sequence) { ++ this.hand = hand; ++ this.blockHit = blockHit; ++ this.sequence = sequence; + } + +- public ServerboundUseItemOnPacket(FriendlyByteBuf friendlybytebuf) { +- this.hand = (InteractionHand) friendlybytebuf.readEnum(InteractionHand.class); +- this.blockHit = friendlybytebuf.readBlockHitResult(); +- this.sequence = friendlybytebuf.readVarInt(); ++ public ServerboundUseItemOnPacket(FriendlyByteBuf buffer) { ++ this.hand = (EnumHand) buffer.readEnum(EnumHand.class); ++ this.blockHit = buffer.readBlockHitResult(); ++ this.sequence = buffer.readVarInt(); + } + + @Override +- @Override +- public void write(FriendlyByteBuf friendlybytebuf) { +- friendlybytebuf.writeEnum(this.hand); +- friendlybytebuf.writeBlockHitResult(this.blockHit); +- friendlybytebuf.writeVarInt(this.sequence); ++ public void write(FriendlyByteBuf buffer) { ++ buffer.writeEnum(this.hand); ++ buffer.writeBlockHitResult(this.blockHit); ++ buffer.writeVarInt(this.sequence); + } + +- @Override +- public void handle(ServerGamePacketListener servergamepacketlistener) { +- servergamepacketlistener.handleUseItemOn(this); ++ public void handle(ServerGamePacketListener handler) { ++ handler.handleUseItemOn(this); + } + +- public InteractionHand getHand() { ++ public EnumHand getHand() { + return this.hand; + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/network/protocol/game/ServerboundUseItemPacket.java.patch b/patch-remap/mache-spigotflower/net/minecraft/network/protocol/game/ServerboundUseItemPacket.java.patch new file mode 100644 index 0000000000..09f410f55b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/network/protocol/game/ServerboundUseItemPacket.java.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/network/protocol/game/ServerboundUseItemPacket.java ++++ b/net/minecraft/network/protocol/game/ServerboundUseItemPacket.java +@@ -1,37 +1,36 @@ ++// mc-dev import + package net.minecraft.network.protocol.game; + + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.protocol.Packet; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + + public class ServerboundUseItemPacket implements Packet { + +- private final InteractionHand hand; ++ private final EnumHand hand; + private final int sequence; + +- public ServerboundUseItemPacket(InteractionHand interactionhand, int i) { +- this.hand = interactionhand; +- this.sequence = i; ++ public ServerboundUseItemPacket(EnumHand hand, int sequence) { ++ this.hand = hand; ++ this.sequence = sequence; + } + +- public ServerboundUseItemPacket(FriendlyByteBuf friendlybytebuf) { +- this.hand = (InteractionHand) friendlybytebuf.readEnum(InteractionHand.class); +- this.sequence = friendlybytebuf.readVarInt(); ++ public ServerboundUseItemPacket(FriendlyByteBuf buffer) { ++ this.hand = (EnumHand) buffer.readEnum(EnumHand.class); ++ this.sequence = buffer.readVarInt(); + } + + @Override +- @Override +- public void write(FriendlyByteBuf friendlybytebuf) { +- friendlybytebuf.writeEnum(this.hand); +- friendlybytebuf.writeVarInt(this.sequence); ++ public void write(FriendlyByteBuf buffer) { ++ buffer.writeEnum(this.hand); ++ buffer.writeVarInt(this.sequence); + } + +- @Override +- public void handle(ServerGamePacketListener servergamepacketlistener) { +- servergamepacketlistener.handleUseItem(this); ++ public void handle(ServerGamePacketListener handler) { ++ handler.handleUseItem(this); + } + +- public InteractionHand getHand() { ++ public EnumHand getHand() { + return this.hand; + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java.patch b/patch-remap/mache-spigotflower/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java.patch new file mode 100644 index 0000000000..5567cc06aa --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java ++++ b/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.network.protocol.handshake; + + import net.minecraft.network.ConnectionProtocol; +@@ -8,26 +9,23 @@ + + private static final int MAX_HOST_LENGTH = 255; + +- public ClientIntentionPacket(FriendlyByteBuf friendlybytebuf) { +- this(friendlybytebuf.readVarInt(), friendlybytebuf.readUtf(255), friendlybytebuf.readUnsignedShort(), ClientIntent.byId(friendlybytebuf.readVarInt())); ++ public ClientIntentionPacket(FriendlyByteBuf buffer) { ++ this(buffer.readVarInt(), buffer.readUtf(255), buffer.readUnsignedShort(), ClientIntent.byId(buffer.readVarInt())); + } + + @Override +- @Override +- public void write(FriendlyByteBuf friendlybytebuf) { +- friendlybytebuf.writeVarInt(this.protocolVersion); +- friendlybytebuf.writeUtf(this.hostName); +- friendlybytebuf.writeShort(this.port); +- friendlybytebuf.writeVarInt(this.intention.id()); ++ public void write(FriendlyByteBuf buffer) { ++ buffer.writeVarInt(this.protocolVersion); ++ buffer.writeUtf(this.hostName); ++ buffer.writeShort(this.port); ++ buffer.writeVarInt(this.intention.id()); + } + +- @Override +- public void handle(ServerHandshakePacketListener serverhandshakepacketlistener) { +- serverhandshakepacketlistener.handleIntention(this); ++ public void handle(ServerHandshakePacketListener handler) { ++ handler.handleIntention(this); + } + + @Override +- @Override + public ConnectionProtocol nextProtocol() { + return this.intention.protocol(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/network/syncher/SynchedEntityData.java.patch b/patch-remap/mache-spigotflower/net/minecraft/network/syncher/SynchedEntityData.java.patch new file mode 100644 index 0000000000..b688b36479 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/network/syncher/SynchedEntityData.java.patch @@ -0,0 +1,353 @@ +--- a/net/minecraft/network/syncher/SynchedEntityData.java ++++ b/net/minecraft/network/syncher/SynchedEntityData.java +@@ -20,6 +20,8 @@ + import net.minecraft.CrashReportCategory; + import net.minecraft.ReportedException; + import net.minecraft.network.FriendlyByteBuf; ++import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.entity.Entity; + import org.apache.commons.lang3.ObjectUtils; + import org.slf4j.Logger; +@@ -38,13 +40,13 @@ + this.entity = entity; + } + +- public static EntityDataAccessor defineId(Class oclass, EntityDataSerializer entitydataserializer) { ++ public static EntityDataAccessor defineId(Class clazz, EntityDataSerializer serializer) { + if (SynchedEntityData.LOGGER.isDebugEnabled()) { + try { + Class oclass1 = Class.forName(Thread.currentThread().getStackTrace()[2].getClassName()); + +- if (!oclass1.equals(oclass)) { +- SynchedEntityData.LOGGER.debug("defineId called for: {} from {}", new Object[]{oclass, oclass1, new RuntimeException()}); ++ if (!oclass1.equals(clazz)) { ++ SynchedEntityData.LOGGER.debug("defineId called for: {} from {}", new Object[]{clazz, oclass1, new RuntimeException()}); + } + } catch (ClassNotFoundException classnotfoundexception) { + ; +@@ -53,11 +55,11 @@ + + int i; + +- if (SynchedEntityData.ENTITY_ID_POOL.containsKey(oclass)) { +- i = SynchedEntityData.ENTITY_ID_POOL.getInt(oclass) + 1; ++ if (SynchedEntityData.ENTITY_ID_POOL.containsKey(clazz)) { ++ i = SynchedEntityData.ENTITY_ID_POOL.getInt(clazz) + 1; + } else { + int j = 0; +- Class oclass2 = oclass; ++ Class oclass2 = clazz; + + while (oclass2 != Entity.class) { + oclass2 = oclass2.getSuperclass(); +@@ -73,79 +75,86 @@ + if (i > 254) { + throw new IllegalArgumentException("Data value id is too big with " + i + "! (Max is 254)"); + } else { +- SynchedEntityData.ENTITY_ID_POOL.put(oclass, i); +- return entitydataserializer.createAccessor(i); ++ SynchedEntityData.ENTITY_ID_POOL.put(clazz, i); ++ return serializer.createAccessor(i); + } + } + +- public void define(EntityDataAccessor entitydataaccessor, T t0) { +- int i = entitydataaccessor.getId(); ++ public void define(EntityDataAccessor key, T value) { ++ int i = key.getId(); + + if (i > 254) { + throw new IllegalArgumentException("Data value id is too big with " + i + "! (Max is 254)"); + } else if (this.itemsById.containsKey(i)) { + throw new IllegalArgumentException("Duplicate id value for " + i + "!"); +- } else if (EntityDataSerializers.getSerializedId(entitydataaccessor.getSerializer()) < 0) { +- EntityDataSerializer entitydataserializer = entitydataaccessor.getSerializer(); ++ } else if (EntityDataSerializers.getSerializedId(key.getSerializer()) < 0) { ++ EntityDataSerializer datawatcherserializer = key.getSerializer(); + +- throw new IllegalArgumentException("Unregistered serializer " + entitydataserializer + " for " + i + "!"); ++ throw new IllegalArgumentException("Unregistered serializer " + datawatcherserializer + " for " + i + "!"); + } else { +- this.createDataItem(entitydataaccessor, t0); ++ this.createDataItem(key, value); + } + } + +- private void createDataItem(EntityDataAccessor entitydataaccessor, T t0) { +- SynchedEntityData.DataItem synchedentitydata_dataitem = new SynchedEntityData.DataItem<>(entitydataaccessor, t0); ++ private void createDataItem(EntityDataAccessor key, T value) { ++ SynchedEntityData.DataItem datawatcher_item = new SynchedEntityData.DataItem<>(key, value); + + this.lock.writeLock().lock(); +- this.itemsById.put(entitydataaccessor.getId(), synchedentitydata_dataitem); ++ this.itemsById.put(key.getId(), datawatcher_item); + this.lock.writeLock().unlock(); + } + +- public boolean hasItem(EntityDataAccessor entitydataaccessor) { +- return this.itemsById.containsKey(entitydataaccessor.getId()); ++ public boolean hasItem(EntityDataAccessor key) { ++ return this.itemsById.containsKey(key.getId()); + } + +- private SynchedEntityData.DataItem getItem(EntityDataAccessor entitydataaccessor) { ++ private SynchedEntityData.DataItem getItem(EntityDataAccessor key) { + this.lock.readLock().lock(); + +- SynchedEntityData.DataItem synchedentitydata_dataitem; ++ SynchedEntityData.DataItem datawatcher_item; + + try { +- synchedentitydata_dataitem = (SynchedEntityData.DataItem) this.itemsById.get(entitydataaccessor.getId()); ++ datawatcher_item = (SynchedEntityData.DataItem) this.itemsById.get(key.getId()); + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting synched entity data"); +- CrashReportCategory crashreportcategory = crashreport.addCategory("Synched entity data"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Synched entity data"); + +- crashreportcategory.setDetail("Data ID", (Object) entitydataaccessor); ++ crashreportsystemdetails.setDetail("Data ID", (Object) key); + throw new ReportedException(crashreport); + } finally { + this.lock.readLock().unlock(); + } + +- return synchedentitydata_dataitem; ++ return datawatcher_item; + } + +- public T get(EntityDataAccessor entitydataaccessor) { +- return this.getItem(entitydataaccessor).getValue(); ++ public T get(EntityDataAccessor key) { ++ return this.getItem(key).getValue(); + } + +- public void set(EntityDataAccessor entitydataaccessor, T t0) { +- this.set(entitydataaccessor, t0, false); ++ public void set(EntityDataAccessor key, T value) { ++ this.set(key, value, false); + } + +- public void set(EntityDataAccessor entitydataaccessor, T t0, boolean flag) { +- SynchedEntityData.DataItem synchedentitydata_dataitem = this.getItem(entitydataaccessor); ++ public void set(EntityDataAccessor key, T value, boolean force) { ++ SynchedEntityData.DataItem datawatcher_item = this.getItem(key); + +- if (flag || ObjectUtils.notEqual(t0, synchedentitydata_dataitem.getValue())) { +- synchedentitydata_dataitem.setValue(t0); +- this.entity.onSyncedDataUpdated(entitydataaccessor); +- synchedentitydata_dataitem.setDirty(true); ++ if (force || ObjectUtils.notEqual(value, datawatcher_item.getValue())) { ++ datawatcher_item.setValue(value); ++ this.entity.onSyncedDataUpdated(key); ++ datawatcher_item.setDirty(true); + this.isDirty = true; + } + + } + ++ // CraftBukkit start - add method from above ++ public void markDirty(EntityDataAccessor datawatcherobject) { ++ this.getItem(datawatcherobject).setDirty(true); ++ this.isDirty = true; ++ } ++ // CraftBukkit end ++ + public boolean isDirty() { + return this.isDirty; + } +@@ -159,15 +168,15 @@ + ObjectIterator objectiterator = this.itemsById.values().iterator(); + + while (objectiterator.hasNext()) { +- SynchedEntityData.DataItem synchedentitydata_dataitem = (SynchedEntityData.DataItem) objectiterator.next(); ++ SynchedEntityData.DataItem datawatcher_item = (SynchedEntityData.DataItem) objectiterator.next(); + +- if (synchedentitydata_dataitem.isDirty()) { +- synchedentitydata_dataitem.setDirty(false); ++ if (datawatcher_item.isDirty()) { ++ datawatcher_item.setDirty(false); + if (list == null) { + list = new ArrayList(); + } + +- list.add(synchedentitydata_dataitem.value()); ++ list.add(datawatcher_item.value()); + } + } + +@@ -186,14 +195,14 @@ + ObjectIterator objectiterator = this.itemsById.values().iterator(); + + while (objectiterator.hasNext()) { +- SynchedEntityData.DataItem synchedentitydata_dataitem = (SynchedEntityData.DataItem) objectiterator.next(); ++ SynchedEntityData.DataItem datawatcher_item = (SynchedEntityData.DataItem) objectiterator.next(); + +- if (!synchedentitydata_dataitem.isSetToDefault()) { ++ if (!datawatcher_item.isSetToDefault()) { + if (list == null) { + list = new ArrayList(); + } + +- list.add(synchedentitydata_dataitem.value()); ++ list.add(datawatcher_item.value()); + } + } + +@@ -201,33 +210,33 @@ + return list; + } + +- public void assignValues(List> list) { ++ public void assignValues(List> entries) { + this.lock.writeLock().lock(); + + try { +- Iterator iterator = list.iterator(); ++ Iterator iterator = entries.iterator(); + + while (iterator.hasNext()) { +- SynchedEntityData.DataValue synchedentitydata_datavalue = (SynchedEntityData.DataValue) iterator.next(); +- SynchedEntityData.DataItem synchedentitydata_dataitem = (SynchedEntityData.DataItem) this.itemsById.get(synchedentitydata_datavalue.id); ++ SynchedEntityData.DataValue datawatcher_b = (SynchedEntityData.DataValue) iterator.next(); ++ SynchedEntityData.DataItem datawatcher_item = (SynchedEntityData.DataItem) this.itemsById.get(datawatcher_b.id); + +- if (synchedentitydata_dataitem != null) { +- this.assignValue(synchedentitydata_dataitem, synchedentitydata_datavalue); +- this.entity.onSyncedDataUpdated(synchedentitydata_dataitem.getAccessor()); ++ if (datawatcher_item != null) { ++ this.assignValue(datawatcher_item, datawatcher_b); ++ this.entity.onSyncedDataUpdated(datawatcher_item.getAccessor()); + } + } + } finally { + this.lock.writeLock().unlock(); + } + +- this.entity.onSyncedDataUpdated(list); ++ this.entity.onSyncedDataUpdated(entries); + } + +- private void assignValue(SynchedEntityData.DataItem synchedentitydata_dataitem, SynchedEntityData.DataValue synchedentitydata_datavalue) { +- if (!Objects.equals(synchedentitydata_datavalue.serializer(), synchedentitydata_dataitem.accessor.getSerializer())) { +- throw new IllegalStateException(String.format(Locale.ROOT, "Invalid entity data item type for field %d on entity %s: old=%s(%s), new=%s(%s)", synchedentitydata_dataitem.accessor.getId(), this.entity, synchedentitydata_dataitem.value, synchedentitydata_dataitem.value.getClass(), synchedentitydata_datavalue.value, synchedentitydata_datavalue.value.getClass())); ++ private void assignValue(SynchedEntityData.DataItem target, SynchedEntityData.DataValue entry) { ++ if (!Objects.equals(entry.serializer(), target.accessor.getSerializer())) { ++ throw new IllegalStateException(String.format(Locale.ROOT, "Invalid entity data item type for field %d on entity %s: old=%s(%s), new=%s(%s)", target.accessor.getId(), this.entity, target.value, target.value.getClass(), entry.value, entry.value.getClass())); + } else { +- synchedentitydata_dataitem.setValue(synchedentitydata_datavalue.value); ++ target.setValue((T) entry.value); // CraftBukkit - decompile error + } + } + +@@ -235,6 +244,18 @@ + return this.itemsById.isEmpty(); + } + ++ // CraftBukkit start ++ public void refresh(ServerPlayer to) { ++ if (!this.isEmpty()) { ++ List> list = this.getNonDefaultValues(); ++ ++ if (list != null) { ++ to.connection.send(new ClientboundSetEntityDataPacket(this.entity.getId(), list)); ++ } ++ } ++ } ++ // CraftBukkit end ++ + public static class DataItem { + + final EntityDataAccessor accessor; +@@ -242,18 +263,18 @@ + private final T initialValue; + private boolean dirty; + +- public DataItem(EntityDataAccessor entitydataaccessor, T t0) { +- this.accessor = entitydataaccessor; +- this.initialValue = t0; +- this.value = t0; ++ public DataItem(EntityDataAccessor accessor, T value) { ++ this.accessor = accessor; ++ this.initialValue = value; ++ this.value = value; + } + + public EntityDataAccessor getAccessor() { + return this.accessor; + } + +- public void setValue(T t0) { +- this.value = t0; ++ public void setValue(T value) { ++ this.value = value; + } + + public T getValue() { +@@ -264,8 +285,8 @@ + return this.dirty; + } + +- public void setDirty(boolean flag) { +- this.dirty = flag; ++ public void setDirty(boolean dirty) { ++ this.dirty = dirty; + } + + public boolean isSetToDefault() { +@@ -277,39 +298,39 @@ + } + } + +- public static record DataValue (int id, EntityDataSerializer serializer, T value) { ++ public static record DataValue(int id, EntityDataSerializer serializer, T value) { // CraftBukkit - decompile error + +- public static SynchedEntityData.DataValue create(EntityDataAccessor entitydataaccessor, T t0) { +- EntityDataSerializer entitydataserializer = entitydataaccessor.getSerializer(); ++ public static SynchedEntityData.DataValue create(EntityDataAccessor dataAccessor, T value) { ++ EntityDataSerializer datawatcherserializer = dataAccessor.getSerializer(); + +- return new SynchedEntityData.DataValue<>(entitydataaccessor.getId(), entitydataserializer, entitydataserializer.copy(t0)); ++ return new SynchedEntityData.DataValue<>(dataAccessor.getId(), datawatcherserializer, datawatcherserializer.copy(value)); + } + +- public void write(FriendlyByteBuf friendlybytebuf) { ++ public void write(FriendlyByteBuf buffer) { + int i = EntityDataSerializers.getSerializedId(this.serializer); + + if (i < 0) { + throw new EncoderException("Unknown serializer type " + this.serializer); + } else { +- friendlybytebuf.writeByte(this.id); +- friendlybytebuf.writeVarInt(i); +- this.serializer.write(friendlybytebuf, this.value); ++ buffer.writeByte(this.id); ++ buffer.writeVarInt(i); ++ this.serializer.write(buffer, this.value); + } + } + +- public static SynchedEntityData.DataValue read(FriendlyByteBuf friendlybytebuf, int i) { +- int j = friendlybytebuf.readVarInt(); +- EntityDataSerializer entitydataserializer = EntityDataSerializers.getSerializer(j); ++ public static SynchedEntityData.DataValue read(FriendlyByteBuf buffer, int id) { ++ int j = buffer.readVarInt(); ++ EntityDataSerializer datawatcherserializer = EntityDataSerializers.getSerializer(j); + +- if (entitydataserializer == null) { ++ if (datawatcherserializer == null) { + throw new DecoderException("Unknown serializer type " + j); + } else { +- return read(friendlybytebuf, i, entitydataserializer); ++ return read(buffer, id, datawatcherserializer); + } + } + +- private static SynchedEntityData.DataValue read(FriendlyByteBuf friendlybytebuf, int i, EntityDataSerializer entitydataserializer) { +- return new SynchedEntityData.DataValue<>(i, entitydataserializer, entitydataserializer.read(friendlybytebuf)); ++ private static SynchedEntityData.DataValue read(FriendlyByteBuf buffer, int id, EntityDataSerializer serializer) { ++ return new SynchedEntityData.DataValue<>(id, serializer, serializer.read(buffer)); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/Bootstrap.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/Bootstrap.java.patch new file mode 100644 index 0000000000..7c4118df8d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/Bootstrap.java.patch @@ -0,0 +1,184 @@ +--- a/net/minecraft/server/Bootstrap.java ++++ b/net/minecraft/server/Bootstrap.java +@@ -16,6 +16,9 @@ + import net.minecraft.core.dispenser.DispenseItemBehavior; + import net.minecraft.core.registries.BuiltInRegistries; + import net.minecraft.locale.Language; ++import net.minecraft.util.datafix.fixes.BlockStateData; ++import net.minecraft.util.datafix.fixes.ItemIdFix; ++import net.minecraft.util.datafix.fixes.ItemSpawnEggFix; + import net.minecraft.world.effect.MobEffect; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.ai.attributes.Attribute; +@@ -41,6 +44,23 @@ + + public static void bootStrap() { + if (!Bootstrap.isBootstrapped) { ++ // CraftBukkit start ++ String name = Bootstrap.class.getSimpleName(); ++ switch (name) { ++ case "DispenserRegistry": ++ break; ++ case "Bootstrap": ++ System.err.println("***************************************************************************"); ++ System.err.println("*** WARNING: This server jar may only be used for development purposes. ***"); ++ System.err.println("***************************************************************************"); ++ break; ++ default: ++ System.err.println("**********************************************************************"); ++ System.err.println("*** WARNING: This server jar is unsupported, use at your own risk. ***"); ++ System.err.println("**********************************************************************"); ++ break; ++ } ++ // CraftBukkit end + Bootstrap.isBootstrapped = true; + Instant instant = Instant.now(); + +@@ -61,32 +81,94 @@ + wrapStreams(); + Bootstrap.bootstrapDuration.set(Duration.between(instant, Instant.now()).toMillis()); + } ++ // CraftBukkit start - easier than fixing the decompile ++ BlockStateData.register(1008, "{Name:'minecraft:oak_sign',Properties:{rotation:'0'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'0'}}"); ++ BlockStateData.register(1009, "{Name:'minecraft:oak_sign',Properties:{rotation:'1'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'1'}}"); ++ BlockStateData.register(1010, "{Name:'minecraft:oak_sign',Properties:{rotation:'2'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'2'}}"); ++ BlockStateData.register(1011, "{Name:'minecraft:oak_sign',Properties:{rotation:'3'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'3'}}"); ++ BlockStateData.register(1012, "{Name:'minecraft:oak_sign',Properties:{rotation:'4'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'4'}}"); ++ BlockStateData.register(1013, "{Name:'minecraft:oak_sign',Properties:{rotation:'5'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'5'}}"); ++ BlockStateData.register(1014, "{Name:'minecraft:oak_sign',Properties:{rotation:'6'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'6'}}"); ++ BlockStateData.register(1015, "{Name:'minecraft:oak_sign',Properties:{rotation:'7'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'7'}}"); ++ BlockStateData.register(1016, "{Name:'minecraft:oak_sign',Properties:{rotation:'8'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'8'}}"); ++ BlockStateData.register(1017, "{Name:'minecraft:oak_sign',Properties:{rotation:'9'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'9'}}"); ++ BlockStateData.register(1018, "{Name:'minecraft:oak_sign',Properties:{rotation:'10'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'10'}}"); ++ BlockStateData.register(1019, "{Name:'minecraft:oak_sign',Properties:{rotation:'11'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'11'}}"); ++ BlockStateData.register(1020, "{Name:'minecraft:oak_sign',Properties:{rotation:'12'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'12'}}"); ++ BlockStateData.register(1021, "{Name:'minecraft:oak_sign',Properties:{rotation:'13'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'13'}}"); ++ BlockStateData.register(1022, "{Name:'minecraft:oak_sign',Properties:{rotation:'14'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'14'}}"); ++ BlockStateData.register(1023, "{Name:'minecraft:oak_sign',Properties:{rotation:'15'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'15'}}"); ++ ItemIdFix.ITEM_NAMES.put(323, "minecraft:oak_sign"); ++ ++ BlockStateData.register(1440, "{Name:\'minecraft:portal\',Properties:{axis:\'x\'}}", new String[]{"{Name:\'minecraft:portal\',Properties:{axis:\'x\'}}"}); ++ ++ ItemIdFix.ITEM_NAMES.put(409, "minecraft:prismarine_shard"); ++ ItemIdFix.ITEM_NAMES.put(410, "minecraft:prismarine_crystals"); ++ ItemIdFix.ITEM_NAMES.put(411, "minecraft:rabbit"); ++ ItemIdFix.ITEM_NAMES.put(412, "minecraft:cooked_rabbit"); ++ ItemIdFix.ITEM_NAMES.put(413, "minecraft:rabbit_stew"); ++ ItemIdFix.ITEM_NAMES.put(414, "minecraft:rabbit_foot"); ++ ItemIdFix.ITEM_NAMES.put(415, "minecraft:rabbit_hide"); ++ ItemIdFix.ITEM_NAMES.put(416, "minecraft:armor_stand"); ++ ++ ItemIdFix.ITEM_NAMES.put(423, "minecraft:mutton"); ++ ItemIdFix.ITEM_NAMES.put(424, "minecraft:cooked_mutton"); ++ ItemIdFix.ITEM_NAMES.put(425, "minecraft:banner"); ++ ItemIdFix.ITEM_NAMES.put(426, "minecraft:end_crystal"); ++ ItemIdFix.ITEM_NAMES.put(427, "minecraft:spruce_door"); ++ ItemIdFix.ITEM_NAMES.put(428, "minecraft:birch_door"); ++ ItemIdFix.ITEM_NAMES.put(429, "minecraft:jungle_door"); ++ ItemIdFix.ITEM_NAMES.put(430, "minecraft:acacia_door"); ++ ItemIdFix.ITEM_NAMES.put(431, "minecraft:dark_oak_door"); ++ ItemIdFix.ITEM_NAMES.put(432, "minecraft:chorus_fruit"); ++ ItemIdFix.ITEM_NAMES.put(433, "minecraft:chorus_fruit_popped"); ++ ItemIdFix.ITEM_NAMES.put(434, "minecraft:beetroot"); ++ ItemIdFix.ITEM_NAMES.put(435, "minecraft:beetroot_seeds"); ++ ItemIdFix.ITEM_NAMES.put(436, "minecraft:beetroot_soup"); ++ ItemIdFix.ITEM_NAMES.put(437, "minecraft:dragon_breath"); ++ ItemIdFix.ITEM_NAMES.put(438, "minecraft:splash_potion"); ++ ItemIdFix.ITEM_NAMES.put(439, "minecraft:spectral_arrow"); ++ ItemIdFix.ITEM_NAMES.put(440, "minecraft:tipped_arrow"); ++ ItemIdFix.ITEM_NAMES.put(441, "minecraft:lingering_potion"); ++ ItemIdFix.ITEM_NAMES.put(442, "minecraft:shield"); ++ ItemIdFix.ITEM_NAMES.put(443, "minecraft:elytra"); ++ ItemIdFix.ITEM_NAMES.put(444, "minecraft:spruce_boat"); ++ ItemIdFix.ITEM_NAMES.put(445, "minecraft:birch_boat"); ++ ItemIdFix.ITEM_NAMES.put(446, "minecraft:jungle_boat"); ++ ItemIdFix.ITEM_NAMES.put(447, "minecraft:acacia_boat"); ++ ItemIdFix.ITEM_NAMES.put(448, "minecraft:dark_oak_boat"); ++ ItemIdFix.ITEM_NAMES.put(449, "minecraft:totem_of_undying"); ++ ItemIdFix.ITEM_NAMES.put(450, "minecraft:shulker_shell"); ++ ItemIdFix.ITEM_NAMES.put(452, "minecraft:iron_nugget"); ++ ItemIdFix.ITEM_NAMES.put(453, "minecraft:knowledge_book"); ++ ++ ItemSpawnEggFix.ID_TO_ENTITY[23] = "Arrow"; ++ // CraftBukkit end + } + } + } + +- private static void checkTranslations(Iterable iterable, Function function, Set set) { +- Language language = Language.getInstance(); ++ private static void checkTranslations(Iterable objects, Function objectToKeyFunction, Set translationSet) { ++ Language localelanguage = Language.getInstance(); + +- iterable.forEach((object) -> { +- String s = (String) function.apply(object); ++ objects.forEach((object) -> { ++ String s = (String) objectToKeyFunction.apply(object); + +- if (!language.has(s)) { +- set.add(s); ++ if (!localelanguage.has(s)) { ++ translationSet.add(s); + } + + }); + } + +- private static void checkGameruleTranslations(final Set set) { +- final Language language = Language.getInstance(); ++ private static void checkGameruleTranslations(final Set translations) { ++ final Language localelanguage = Language.getInstance(); + + GameRules.visitGameRuleTypes(new GameRules.GameRuleTypeVisitor() { + @Override +- @Override +- public > void visit(GameRules.Key gamerules_key, GameRules.Type gamerules_type) { +- if (!language.has(gamerules_key.getDescriptionId())) { +- set.add(gamerules_key.getId()); ++ public > void visit(GameRules.Key key, GameRules.Type type) { ++ if (!localelanguage.has(key.getDescriptionId())) { ++ translations.add(key.getId()); + } + + } +@@ -102,8 +184,8 @@ + checkTranslations(BuiltInRegistries.ITEM, Item::getDescriptionId, set); + checkTranslations(BuiltInRegistries.ENCHANTMENT, Enchantment::getDescriptionId, set); + checkTranslations(BuiltInRegistries.BLOCK, Block::getDescriptionId, set); +- checkTranslations(BuiltInRegistries.CUSTOM_STAT, (resourcelocation) -> { +- String s = resourcelocation.toString(); ++ checkTranslations(BuiltInRegistries.CUSTOM_STAT, (minecraftkey) -> { ++ String s = minecraftkey.toString(); + + return "stat." + s.replace(':', '.'); + }, set); +@@ -111,15 +193,15 @@ + return set; + } + +- public static void checkBootstrapCalled(Supplier supplier) { ++ public static void checkBootstrapCalled(Supplier callSite) { + if (!Bootstrap.isBootstrapped) { +- throw createBootstrapException(supplier); ++ throw createBootstrapException(callSite); + } + } + +- private static RuntimeException createBootstrapException(Supplier supplier) { ++ private static RuntimeException createBootstrapException(Supplier callSite) { + try { +- String s = (String) supplier.get(); ++ String s = (String) callSite.get(); + + return new IllegalArgumentException("Not bootstrapped (called from " + s + ")"); + } catch (Exception exception) { +@@ -155,7 +237,7 @@ + + } + +- public static void realStdoutPrintln(String s) { +- Bootstrap.STDOUT.println(s); ++ public static void realStdoutPrintln(String message) { ++ Bootstrap.STDOUT.println(message); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/Main.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/Main.java.patch new file mode 100644 index 0000000000..13a68e4aee --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/Main.java.patch @@ -0,0 +1,360 @@ +--- a/net/minecraft/server/Main.java ++++ b/net/minecraft/server/Main.java +@@ -28,7 +28,6 @@ + import net.minecraft.Util; + import net.minecraft.commands.Commands; + import net.minecraft.core.Registry; +-import net.minecraft.core.RegistryAccess; + import net.minecraft.core.registries.Registries; + import net.minecraft.nbt.NbtException; + import net.minecraft.nbt.ReportedNbtException; +@@ -38,6 +37,7 @@ + import net.minecraft.server.dedicated.DedicatedServerProperties; + import net.minecraft.server.dedicated.DedicatedServerSettings; + import net.minecraft.server.level.progress.LoggerChunkProgressListener; ++import net.minecraft.server.packs.PackType; + import net.minecraft.server.packs.repository.PackRepository; + import net.minecraft.server.packs.repository.ServerPacksSource; + import net.minecraft.util.Mth; +@@ -54,12 +54,20 @@ + import net.minecraft.world.level.levelgen.WorldOptions; + import net.minecraft.world.level.levelgen.presets.WorldPresets; + import net.minecraft.world.level.storage.LevelDataAndDimensions; ++import net.minecraft.world.level.storage.LevelResource; + import net.minecraft.world.level.storage.LevelStorageSource; + import net.minecraft.world.level.storage.LevelSummary; + import net.minecraft.world.level.storage.PrimaryLevelData; +-import net.minecraft.world.level.storage.WorldData; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.google.common.base.Charsets; ++import java.io.InputStreamReader; ++import java.util.concurrent.atomic.AtomicReference; ++import net.minecraft.SharedConstants; ++import org.bukkit.configuration.file.YamlConfiguration; ++// CraftBukkit end ++ + public class Main { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -67,8 +75,9 @@ + public Main() {} + + @DontObfuscate +- public static void main(String[] astring) { ++ public static void main(final OptionSet optionset) { // CraftBukkit - replaces main(String[] astring) + SharedConstants.tryDetectVersion(); ++ /* CraftBukkit start - Replace everything + OptionParser optionparser = new OptionParser(); + OptionSpec optionspec = optionparser.accepts("nogui"); + OptionSpec optionspec1 = optionparser.accepts("initSettings", "Initializes 'server.properties' and 'eula.txt', then quits"); +@@ -93,15 +102,18 @@ + optionparser.printHelpOn(System.err); + return; + } ++ */ // CraftBukkit end + +- Path path = (Path) optionset.valueOf(optionspec13); ++ try { + ++ Path path = (Path) optionset.valueOf("pidFile"); // CraftBukkit ++ + if (path != null) { + writePidFile(path); + } + + CrashReport.preload(); +- if (optionset.has(optionspec12)) { ++ if (optionset.has("jfrProfile")) { // CraftBukkit + JvmProfiler.INSTANCE.start(Environment.SERVER); + } + +@@ -109,13 +121,26 @@ + Bootstrap.validate(); + Util.startTimerHackThread(); + Path path1 = Paths.get("server.properties"); +- DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(path1); ++ DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(optionset); // CraftBukkit - CLI argument support + + dedicatedserversettings.forceSave(); + Path path2 = Paths.get("eula.txt"); + Eula eula = new Eula(path2); + +- if (optionset.has(optionspec1)) { ++ if (optionset.has("initSettings")) { // CraftBukkit ++ // CraftBukkit start - SPIGOT-5761: Create bukkit.yml and commands.yml if not present ++ File configFile = (File) optionset.valueOf("bukkit-settings"); ++ YamlConfiguration configuration = YamlConfiguration.loadConfiguration(configFile); ++ configuration.options().copyDefaults(true); ++ configuration.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/bukkit.yml"), Charsets.UTF_8))); ++ configuration.save(configFile); ++ ++ File commandFile = (File) optionset.valueOf("commands-settings"); ++ YamlConfiguration commandsConfiguration = YamlConfiguration.loadConfiguration(commandFile); ++ commandsConfiguration.options().copyDefaults(true); ++ commandsConfiguration.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/commands.yml"), Charsets.UTF_8))); ++ commandsConfiguration.save(commandFile); ++ // CraftBukkit end + Main.LOGGER.info("Initialized '{}' and '{}'", path1.toAbsolutePath(), path2.toAbsolutePath()); + return; + } +@@ -125,43 +150,45 @@ + return; + } + +- File file = new File((String) optionset.valueOf(optionspec8)); ++ File file = (File) optionset.valueOf("universe"); // CraftBukkit + Services services = Services.create(new YggdrasilAuthenticationService(Proxy.NO_PROXY), file); +- String s = (String) Optional.ofNullable((String) optionset.valueOf(optionspec9)).orElse(dedicatedserversettings.getProperties().levelName); +- LevelStorageSource levelstoragesource = LevelStorageSource.createDefault(file.toPath()); +- LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess = levelstoragesource.validateAndCreateAccess(s); ++ // CraftBukkit start ++ String s = (String) Optional.ofNullable((String) optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName); ++ LevelStorageSource convertable = LevelStorageSource.createDefault(file.toPath()); ++ LevelStorageSource.LevelStorageAccess convertable_conversionsession = convertable.validateAndCreateAccess(s, LevelStem.OVERWORLD); ++ // CraftBukkit end + Dynamic dynamic; + +- if (levelstoragesource_levelstorageaccess.hasWorldData()) { +- LevelSummary levelsummary; ++ if (convertable_conversionsession.hasWorldData()) { ++ LevelSummary worldinfo; + + try { +- dynamic = levelstoragesource_levelstorageaccess.getDataTag(); +- levelsummary = levelstoragesource_levelstorageaccess.getSummary(dynamic); ++ dynamic = convertable_conversionsession.getDataTag(); ++ worldinfo = convertable_conversionsession.getSummary(dynamic); + } catch (NbtException | ReportedNbtException | IOException ioexception) { +- LevelStorageSource.LevelDirectory levelstoragesource_leveldirectory = levelstoragesource_levelstorageaccess.getLevelDirectory(); ++ LevelStorageSource.LevelDirectory convertable_b = convertable_conversionsession.getLevelDirectory(); + +- Main.LOGGER.warn("Failed to load world data from {}", levelstoragesource_leveldirectory.dataFile(), ioexception); ++ Main.LOGGER.warn("Failed to load world data from {}", convertable_b.dataFile(), ioexception); + Main.LOGGER.info("Attempting to use fallback"); + + try { +- dynamic = levelstoragesource_levelstorageaccess.getDataTagFallback(); +- levelsummary = levelstoragesource_levelstorageaccess.getSummary(dynamic); ++ dynamic = convertable_conversionsession.getDataTagFallback(); ++ worldinfo = convertable_conversionsession.getSummary(dynamic); + } catch (NbtException | ReportedNbtException | IOException ioexception1) { +- Main.LOGGER.error("Failed to load world data from {}", levelstoragesource_leveldirectory.oldDataFile(), ioexception1); +- Main.LOGGER.error("Failed to load world data from {} and {}. World files may be corrupted. Shutting down.", levelstoragesource_leveldirectory.dataFile(), levelstoragesource_leveldirectory.oldDataFile()); ++ Main.LOGGER.error("Failed to load world data from {}", convertable_b.oldDataFile(), ioexception1); ++ Main.LOGGER.error("Failed to load world data from {} and {}. World files may be corrupted. Shutting down.", convertable_b.dataFile(), convertable_b.oldDataFile()); + return; + } + +- levelstoragesource_levelstorageaccess.restoreLevelDataFromOld(); ++ convertable_conversionsession.restoreLevelDataFromOld(); + } + +- if (levelsummary.requiresManualConversion()) { ++ if (worldinfo.requiresManualConversion()) { + Main.LOGGER.info("This world must be opened in an older version (like 1.6.4) to be safely converted"); + return; + } + +- if (!levelsummary.isCompatible()) { ++ if (!worldinfo.isCompatible()) { + Main.LOGGER.info("This world was created by an incompatible version."); + return; + } +@@ -170,49 +197,68 @@ + } + + Dynamic dynamic1 = dynamic; +- boolean flag = optionset.has(optionspec6); ++ boolean flag = optionset.has("safeMode"); // CraftBukkit + + if (flag) { + Main.LOGGER.warn("Safe mode active, only vanilla datapack will be loaded"); + } + +- PackRepository packrepository = ServerPacksSource.createPackRepository(levelstoragesource_levelstorageaccess); ++ PackRepository resourcepackrepository = ServerPacksSource.createPackRepository(convertable_conversionsession); ++ // CraftBukkit start ++ File bukkitDataPackFolder = new File(convertable_conversionsession.getLevelPath(LevelResource.DATAPACK_DIR).toFile(), "bukkit"); ++ if (!bukkitDataPackFolder.exists()) { ++ bukkitDataPackFolder.mkdirs(); ++ } ++ File mcMeta = new File(bukkitDataPackFolder, "pack.mcmeta"); ++ try { ++ com.google.common.io.Files.write("{\n" ++ + " \"pack\": {\n" ++ + " \"description\": \"Data pack for resources provided by Bukkit plugins\",\n" ++ + " \"pack_format\": " + SharedConstants.getCurrentVersion().getPackVersion(PackType.SERVER_DATA) + "\n" ++ + " }\n" ++ + "}\n", mcMeta, com.google.common.base.Charsets.UTF_8); ++ } catch (java.io.IOException ex) { ++ throw new RuntimeException("Could not initialize Bukkit datapack", ex); ++ } ++ AtomicReference worldLoader = new AtomicReference<>(); ++ // CraftBukkit end + + WorldStem worldstem; + + try { +- WorldLoader.InitConfig worldloader_initconfig = loadOrCreateConfig(dedicatedserversettings.getProperties(), dynamic1, flag, packrepository); ++ WorldLoader.c worldloader_c = loadOrCreateConfig(dedicatedserversettings.getProperties(), dynamic1, flag, resourcepackrepository); + + worldstem = (WorldStem) Util.blockUntilDone((executor) -> { +- return WorldLoader.load(worldloader_initconfig, (worldloader_dataloadcontext) -> { +- Registry registry = worldloader_dataloadcontext.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM); ++ return WorldLoader.load(worldloader_c, (worldloader_a) -> { ++ worldLoader.set(worldloader_a); // CraftBukkit ++ Registry iregistry = worldloader_a.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM); + + if (dynamic1 != null) { +- LevelDataAndDimensions leveldataanddimensions = LevelStorageSource.getLevelDataAndDimensions(dynamic1, worldloader_dataloadcontext.dataConfiguration(), registry, worldloader_dataloadcontext.datapackWorldgen()); ++ LevelDataAndDimensions leveldataanddimensions = LevelStorageSource.getLevelDataAndDimensions(dynamic1, worldloader_a.dataConfiguration(), iregistry, worldloader_a.datapackWorldgen()); + +- return new WorldLoader.DataLoadOutput<>(leveldataanddimensions.worldData(), leveldataanddimensions.dimensions().dimensionsRegistryAccess()); ++ return new WorldLoader.b<>(leveldataanddimensions.worldData(), leveldataanddimensions.dimensions().dimensionsRegistryAccess()); + } else { + Main.LOGGER.info("No existing world data, creating new world"); +- LevelSettings levelsettings; ++ LevelSettings worldsettings; + WorldOptions worldoptions; + WorldDimensions worlddimensions; + +- if (optionset.has(optionspec2)) { +- levelsettings = MinecraftServer.DEMO_SETTINGS; ++ if (optionset.has("demo")) { // CraftBukkit ++ worldsettings = MinecraftServer.DEMO_SETTINGS; + worldoptions = WorldOptions.DEMO_OPTIONS; +- worlddimensions = WorldPresets.createNormalWorldDimensions(worldloader_dataloadcontext.datapackWorldgen()); ++ worlddimensions = WorldPresets.createNormalWorldDimensions(worldloader_a.datapackWorldgen()); + } else { + DedicatedServerProperties dedicatedserverproperties = dedicatedserversettings.getProperties(); + +- levelsettings = new LevelSettings(dedicatedserverproperties.levelName, dedicatedserverproperties.gamemode, dedicatedserverproperties.hardcore, dedicatedserverproperties.difficulty, false, new GameRules(), worldloader_dataloadcontext.dataConfiguration()); +- worldoptions = optionset.has(optionspec3) ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions; +- worlddimensions = dedicatedserverproperties.createDimensions(worldloader_dataloadcontext.datapackWorldgen()); ++ worldsettings = new LevelSettings(dedicatedserverproperties.levelName, dedicatedserverproperties.gamemode, dedicatedserverproperties.hardcore, dedicatedserverproperties.difficulty, false, new GameRules(), worldloader_a.dataConfiguration()); ++ worldoptions = optionset.has("bonusChest") ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions; // CraftBukkit ++ worlddimensions = dedicatedserverproperties.createDimensions(worldloader_a.datapackWorldgen()); + } + +- WorldDimensions.Complete worlddimensions_complete = worlddimensions.bake(registry); +- Lifecycle lifecycle = worlddimensions_complete.lifecycle().add(worldloader_dataloadcontext.datapackWorldgen().allRegistriesLifecycle()); ++ WorldDimensions.b worlddimensions_b = worlddimensions.bake(iregistry); ++ Lifecycle lifecycle = worlddimensions_b.lifecycle().add(worldloader_a.datapackWorldgen().allRegistriesLifecycle()); + +- return new WorldLoader.DataLoadOutput<>(new PrimaryLevelData(levelsettings, worldoptions, worlddimensions_complete.specialWorldProperty(), lifecycle), worlddimensions_complete.dimensionsRegistryAccess()); ++ return new WorldLoader.b<>(new PrimaryLevelData(worldsettings, worldoptions, worlddimensions_b.specialWorldProperty(), lifecycle), worlddimensions_b.dimensionsRegistryAccess()); + } + }, WorldStem::new, Util.backgroundExecutor(), executor); + }).get(); +@@ -221,33 +267,44 @@ + return; + } + +- RegistryAccess.Frozen registryaccess_frozen = worldstem.registries().compositeAccess(); ++ /* ++ IRegistryCustom.Dimension iregistrycustom_dimension = worldstem.registries().compositeAccess(); + + if (optionset.has(optionspec4)) { +- forceUpgrade(levelstoragesource_levelstorageaccess, DataFixers.getDataFixer(), optionset.has(optionspec5), () -> { ++ forceUpgrade(convertable_conversionsession, DataConverterRegistry.getDataFixer(), optionset.has(optionspec5), () -> { + return true; +- }, registryaccess_frozen.registryOrThrow(Registries.LEVEL_STEM)); ++ }, iregistrycustom_dimension.registryOrThrow(Registries.LEVEL_STEM)); + } + +- WorldData worlddata = worldstem.worldData(); ++ SaveData savedata = worldstem.worldData(); + +- levelstoragesource_levelstorageaccess.saveDataTag(registryaccess_frozen, worlddata); ++ convertable_conversionsession.saveDataTag(iregistrycustom_dimension, savedata); ++ */ + final DedicatedServer dedicatedserver = (DedicatedServer) MinecraftServer.spin((thread) -> { +- DedicatedServer dedicatedserver1 = new DedicatedServer(thread, levelstoragesource_levelstorageaccess, packrepository, worldstem, dedicatedserversettings, DataFixers.getDataFixer(), services, LoggerChunkProgressListener::new); ++ DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, worldLoader.get(), thread, convertable_conversionsession, resourcepackrepository, worldstem, dedicatedserversettings, DataFixers.getDataFixer(), services, LoggerChunkProgressListener::new); + ++ /* + dedicatedserver1.setPort((Integer) optionset.valueOf(optionspec10)); + dedicatedserver1.setDemo(optionset.has(optionspec2)); + dedicatedserver1.setId((String) optionset.valueOf(optionspec11)); +- boolean flag1 = !optionset.has(optionspec) && !optionset.valuesOf(nonoptionargumentspec).contains("nogui"); ++ */ ++ boolean flag1 = !optionset.has("nogui") && !optionset.nonOptionArguments().contains("nogui"); + + if (flag1 && !GraphicsEnvironment.isHeadless()) { + dedicatedserver1.showGui(); + } + ++ if (optionset.has("port")) { ++ int port = (Integer) optionset.valueOf("port"); ++ if (port > 0) { ++ dedicatedserver1.setPort(port); ++ } ++ } ++ + return dedicatedserver1; + }); ++ /* CraftBukkit start + Thread thread = new Thread("Server Shutdown Thread") { +- @Override + public void run() { + dedicatedserver.halt(true); + } +@@ -255,6 +312,7 @@ + + thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(Main.LOGGER)); + Runtime.getRuntime().addShutdownHook(thread); ++ */ // CraftBukkit end + } catch (Exception exception1) { + Main.LOGGER.error(LogUtils.FATAL_MARKER, "Failed to start the minecraft server", exception1); + } +@@ -271,7 +329,7 @@ + } + } + +- private static WorldLoader.InitConfig loadOrCreateConfig(DedicatedServerProperties dedicatedserverproperties, @Nullable Dynamic dynamic, boolean flag, PackRepository packrepository) { ++ private static WorldLoader.c loadOrCreateConfig(DedicatedServerProperties dedicatedserverproperties, @Nullable Dynamic dynamic, boolean flag, PackRepository resourcepackrepository) { + boolean flag1; + WorldDataConfiguration worlddataconfiguration; + +@@ -285,21 +343,21 @@ + worlddataconfiguration = new WorldDataConfiguration(dedicatedserverproperties.initialDataPackConfiguration, FeatureFlags.DEFAULT_FLAGS); + } + +- WorldLoader.PackConfig worldloader_packconfig = new WorldLoader.PackConfig(packrepository, worlddataconfiguration, flag, flag1); ++ WorldLoader.d worldloader_d = new WorldLoader.d(resourcepackrepository, worlddataconfiguration, flag, flag1); + +- return new WorldLoader.InitConfig(worldloader_packconfig, Commands.CommandSelection.DEDICATED, dedicatedserverproperties.functionPermissionLevel); ++ return new WorldLoader.c(worldloader_d, Commands.CommandSelection.DEDICATED, dedicatedserverproperties.functionPermissionLevel); + } + +- private static void forceUpgrade(LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess, DataFixer datafixer, boolean flag, BooleanSupplier booleansupplier, Registry registry) { +- Main.LOGGER.info("Forcing world upgrade!"); +- WorldUpgrader worldupgrader = new WorldUpgrader(levelstoragesource_levelstorageaccess, datafixer, registry, flag); +- Component component = null; ++ public static void forceUpgrade(LevelStorageSource.LevelStorageAccess levelStorage, DataFixer dataFixer, boolean eraseCache, BooleanSupplier upgradeWorld, Registry dimesions) { ++ Main.LOGGER.info("Forcing world upgrade! {}", levelStorage.getLevelId()); // CraftBukkit ++ WorldUpgrader worldupgrader = new WorldUpgrader(levelStorage, dataFixer, dimesions, eraseCache); ++ Component ichatbasecomponent = null; + + while (!worldupgrader.isFinished()) { +- Component component1 = worldupgrader.getStatus(); ++ Component ichatbasecomponent1 = worldupgrader.getStatus(); + +- if (component != component1) { +- component = component1; ++ if (ichatbasecomponent != ichatbasecomponent1) { ++ ichatbasecomponent = ichatbasecomponent1; + Main.LOGGER.info(worldupgrader.getStatus().getString()); + } + +@@ -311,7 +369,7 @@ + Main.LOGGER.info("{}% completed ({} / {} chunks)...", new Object[]{Mth.floor((float) j / (float) i * 100.0F), j, i}); + } + +- if (!booleansupplier.getAsBoolean()) { ++ if (!upgradeWorld.getAsBoolean()) { + worldupgrader.cancel(); + } else { + try { diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/MinecraftServer.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/MinecraftServer.java.patch new file mode 100644 index 0000000000..76e6ef94a3 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/MinecraftServer.java.patch @@ -0,0 +1,2048 @@ +--- a/net/minecraft/server/MinecraftServer.java ++++ b/net/minecraft/server/MinecraftServer.java +@@ -76,7 +76,6 @@ + import net.minecraft.obfuscate.DontObfuscate; + import net.minecraft.resources.ResourceKey; + import net.minecraft.resources.ResourceLocation; +-import net.minecraft.server.bossevents.CustomBossEvents; + import net.minecraft.server.level.DemoMode; + import net.minecraft.server.level.PlayerRespawnLogic; + import net.minecraft.server.level.ServerChunkCache; +@@ -91,7 +90,7 @@ + import net.minecraft.server.packs.PackType; + import net.minecraft.server.packs.repository.Pack; + import net.minecraft.server.packs.repository.PackRepository; +-import net.minecraft.server.packs.resources.CloseableResourceManager; ++import net.minecraft.server.packs.resources.IReloadableResourceManager; + import net.minecraft.server.packs.resources.MultiPackResourceManager; + import net.minecraft.server.packs.resources.ResourceManager; + import net.minecraft.server.players.GameProfileCache; +@@ -108,6 +107,7 @@ + import net.minecraft.util.SignatureValidator; + import net.minecraft.util.TimeUtil; + import net.minecraft.util.Unit; ++import net.minecraft.util.datafix.DataFixers; + import net.minecraft.util.profiling.EmptyProfileResults; + import net.minecraft.util.profiling.ProfileResults; + import net.minecraft.util.profiling.ProfilerFiller; +@@ -142,36 +142,57 @@ + import net.minecraft.world.level.WorldDataConfiguration; + import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.block.Block; +-import net.minecraft.world.level.border.BorderChangeListener; + import net.minecraft.world.level.border.WorldBorder; + import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.levelgen.Heightmap; ++import net.minecraft.world.level.levelgen.MobSpawnerPhantom; + import net.minecraft.world.level.levelgen.PatrolSpawner; +-import net.minecraft.world.level.levelgen.PhantomSpawner; + import net.minecraft.world.level.levelgen.WorldOptions; + import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; + import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; ++import net.minecraft.world.level.storage.WorldData; ++import net.minecraft.world.level.storage.loot.LootDataManager; ++import org.slf4j.Logger; ++ ++// CraftBukkit start ++import com.mojang.serialization.Dynamic; ++import com.mojang.serialization.Lifecycle; ++import java.util.Random; ++import jline.console.ConsoleReader; ++import joptsimple.OptionSet; ++import net.minecraft.nbt.NbtException; ++import net.minecraft.nbt.ReportedNbtException; ++import net.minecraft.server.bossevents.CustomBossEvents; ++import net.minecraft.server.dedicated.DedicatedServer; ++import net.minecraft.server.dedicated.DedicatedServerProperties; ++import net.minecraft.world.level.levelgen.WorldDimensions; ++import net.minecraft.world.level.levelgen.presets.WorldPresets; + import net.minecraft.world.level.storage.CommandStorage; +-import net.minecraft.world.level.storage.DerivedLevelData; + import net.minecraft.world.level.storage.DimensionDataStorage; + import net.minecraft.world.level.storage.LevelData; ++import net.minecraft.world.level.storage.LevelDataAndDimensions; + import net.minecraft.world.level.storage.LevelResource; + import net.minecraft.world.level.storage.LevelStorageSource; ++import net.minecraft.world.level.storage.LevelSummary; + import net.minecraft.world.level.storage.PlayerDataStorage; ++import net.minecraft.world.level.storage.PrimaryLevelData; + import net.minecraft.world.level.storage.ServerLevelData; +-import net.minecraft.world.level.storage.WorldData; +-import net.minecraft.world.level.storage.loot.LootDataManager; ++import net.minecraft.world.level.validation.ContentValidationException; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; +-import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.Main; ++import org.bukkit.event.server.ServerLoadEvent; ++// CraftBukkit end + + public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements ServerInfo, CommandSource, AutoCloseable { + +- private static final Logger LOGGER = LogUtils.getLogger(); ++ public static final Logger LOGGER = LogUtils.getLogger(); + public static final String VANILLA_BRAND = "vanilla"; + private static final float AVERAGE_TICK_TIME_SMOOTHING = 0.8F; + private static final int TICK_STATS_SPAN = 100; +- private static final long OVERLOADED_THRESHOLD_NANOS = 20L * TimeUtil.NANOSECONDS_PER_SECOND / 20L; ++ private static final long OVERLOADED_THRESHOLD_NANOS = 30L * TimeUtil.NANOSECONDS_PER_SECOND / 20L; // CraftBukkit + private static final int OVERLOADED_TICKS_THRESHOLD = 20; + private static final long OVERLOADED_WARNING_INTERVAL_NANOS = 10L * TimeUtil.NANOSECONDS_PER_SECOND; + private static final int OVERLOADED_TICKS_WARNING_INTERVAL = 100; +@@ -186,8 +207,8 @@ + public static final int ABSOLUTE_MAX_WORLD_SIZE = 29999984; + public static final LevelSettings DEMO_SETTINGS = new LevelSettings("Demo World", GameType.SURVIVAL, false, Difficulty.NORMAL, false, new GameRules(), WorldDataConfiguration.DEFAULT); + public static final GameProfile ANONYMOUS_PLAYER_PROFILE = new GameProfile(Util.NIL_UUID, "Anonymous Player"); +- protected final LevelStorageSource.LevelStorageAccess storageSource; +- protected final PlayerDataStorage playerDataStorage; ++ public LevelStorageSource.LevelStorageAccess storageSource; ++ public final PlayerDataStorage playerDataStorage; + private final List tickables = Lists.newArrayList(); + private MetricsRecorder metricsRecorder; + private ProfilerFiller profiler; +@@ -197,18 +218,18 @@ + @Nullable + private MinecraftServer.TimeProfiler debugCommandProfiler; + private boolean debugCommandProfilerDelayStart; +- private final ServerConnectionListener connection; +- private final ChunkProgressListenerFactory progressListenerFactory; ++ private ServerConnectionListener connection; ++ public final ChunkProgressListenerFactory progressListenerFactory; + @Nullable + private ServerStatus status; + @Nullable +- private ServerStatus.Favicon statusIcon; ++ private ServerStatus.a statusIcon; + private final RandomSource random; +- private final DataFixer fixerUpper; ++ public final DataFixer fixerUpper; + private String localIp; + private int port; + private final LayeredRegistryAccess registries; +- private final Map, ServerLevel> levels; ++ private Map, ServerLevel> levels; + private PlayerList playerList; + private volatile boolean running; + private boolean stopped; +@@ -233,7 +254,7 @@ + private long lastOverloadWarningNanos; + protected final Services services; + private long lastServerStatus; +- private final Thread serverThread; ++ public final Thread serverThread; + private long nextTickTimeNanos; + private long delayedTasksMaxNextTickTimeNanos; + private boolean mayHaveDelayedTasks; +@@ -245,16 +266,29 @@ + private final ServerFunctionManager functionManager; + private boolean enforceWhitelist; + private float smoothedTickTimeMillis; +- private final Executor executor; ++ public final Executor executor; + @Nullable + private String serverId; +- private MinecraftServer.ReloadableResources resources; ++ public MinecraftServer.ReloadableResources resources; + private final StructureTemplateManager structureTemplateManager; + private final ServerTickRateManager tickRateManager; +- protected final WorldData worldData; ++ protected WorldData worldData; + private volatile boolean isSaving; + +- public static S spin(Function function) { ++ // CraftBukkit start ++ public final WorldLoader.a worldLoader; ++ public org.bukkit.craftbukkit.CraftServer server; ++ public OptionSet options; ++ public org.bukkit.command.ConsoleCommandSender console; ++ public ConsoleReader reader; ++ public static int currentTick = (int) (System.currentTimeMillis() / 50); ++ public java.util.Queue processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); ++ public int autosavePeriod; ++ public Commands vanillaCommandDispatcher; ++ private boolean forceTicks; ++ // CraftBukkit end ++ ++ public static S spin(Function threadFunction) { + AtomicReference atomicreference = new AtomicReference(); + Thread thread = new Thread(() -> { + ((MinecraftServer) atomicreference.get()).runServer(); +@@ -267,18 +301,18 @@ + thread.setPriority(8); + } + +- S s0 = (MinecraftServer) function.apply(thread); ++ S s0 = threadFunction.apply(thread); // CraftBukkit - decompile error + + atomicreference.set(s0); + thread.start(); + return s0; + } + +- public MinecraftServer(Thread thread, LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess, PackRepository packrepository, WorldStem worldstem, Proxy proxy, DataFixer datafixer, Services services, ChunkProgressListenerFactory chunkprogresslistenerfactory) { ++ public MinecraftServer(OptionSet options, WorldLoader.a worldLoader, Thread thread, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PackRepository resourcepackrepository, WorldStem worldstem, Proxy proxy, DataFixer datafixer, Services services, ChunkProgressListenerFactory worldloadlistenerfactory) { + super("Server"); + this.metricsRecorder = InactiveMetricsRecorder.INSTANCE; + this.profiler = this.metricsRecorder.getProfiler(); +- this.onMetricsRecordingStopped = (profileresults) -> { ++ this.onMetricsRecordingStopped = (methodprofilerresults) -> { + this.stopRecordingMetrics(); + }; + this.onMetricsRecordingFinished = (path) -> { +@@ -295,11 +329,11 @@ + this.customBossEvents = new CustomBossEvents(); + this.registries = worldstem.registries(); + this.worldData = worldstem.worldData(); +- if (!this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM).containsKey(LevelStem.OVERWORLD)) { ++ if (false && !this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM).containsKey(LevelStem.OVERWORLD)) { // CraftBukkit - initialised later + throw new IllegalStateException("Missing Overworld dimension data"); + } else { + this.proxy = proxy; +- this.packRepository = packrepository; ++ this.packRepository = resourcepackrepository; + this.resources = new MinecraftServer.ReloadableResources(worldstem.resourceManager(), worldstem.dataPackResources()); + this.services = services; + if (services.profileCache() != null) { +@@ -308,26 +342,53 @@ + + this.connection = new ServerConnectionListener(this); + this.tickRateManager = new ServerTickRateManager(this); +- this.progressListenerFactory = chunkprogresslistenerfactory; +- this.storageSource = levelstoragesource_levelstorageaccess; +- this.playerDataStorage = levelstoragesource_levelstorageaccess.createPlayerStorage(); ++ this.progressListenerFactory = worldloadlistenerfactory; ++ this.storageSource = convertable_conversionsession; ++ this.playerDataStorage = convertable_conversionsession.createPlayerStorage(); + this.fixerUpper = datafixer; + this.functionManager = new ServerFunctionManager(this, this.resources.managers.getFunctionLibrary()); + HolderGetter holdergetter = this.registries.compositeAccess().registryOrThrow(Registries.BLOCK).asLookup().filterFeatures(this.worldData.enabledFeatures()); + +- this.structureTemplateManager = new StructureTemplateManager(worldstem.resourceManager(), levelstoragesource_levelstorageaccess, datafixer, holdergetter); ++ this.structureTemplateManager = new StructureTemplateManager(worldstem.resourceManager(), convertable_conversionsession, datafixer, holdergetter); + this.serverThread = thread; + this.executor = Util.backgroundExecutor(); + } ++ // CraftBukkit start ++ this.options = options; ++ this.worldLoader = worldLoader; ++ this.vanillaCommandDispatcher = worldstem.dataPackResources().commands; // CraftBukkit ++ // Try to see if we're actually running in a terminal, disable jline if not ++ if (System.console() == null && System.getProperty("jline.terminal") == null) { ++ System.setProperty("jline.terminal", "jline.UnsupportedTerminal"); ++ Main.useJline = false; ++ } ++ ++ try { ++ reader = new ConsoleReader(System.in, System.out); ++ reader.setExpandEvents(false); // Avoid parsing exceptions for uncommonly used event designators ++ } catch (Throwable e) { ++ try { ++ // Try again with jline disabled for Windows users without C++ 2008 Redistributable ++ System.setProperty("jline.terminal", "jline.UnsupportedTerminal"); ++ System.setProperty("user.language", "en"); ++ Main.useJline = false; ++ reader = new ConsoleReader(System.in, System.out); ++ reader.setExpandEvents(false); ++ } catch (IOException ex) { ++ LOGGER.warn((String) null, ex); ++ } ++ } ++ Runtime.getRuntime().addShutdownHook(new org.bukkit.craftbukkit.util.ServerShutdownThread(this)); ++ // CraftBukkit end + } + +- private void readScoreboard(DimensionDataStorage dimensiondatastorage) { +- dimensiondatastorage.computeIfAbsent(this.getScoreboard().dataFactory(), "scoreboard"); ++ private void readScoreboard(DimensionDataStorage dataStorage) { ++ dataStorage.computeIfAbsent(this.getScoreboard().dataFactory(), "scoreboard"); + } + + protected abstract boolean initServer() throws IOException; + +- protected void loadLevel() { ++ protected void loadLevel(String s) { // CraftBukkit + if (!JvmProfiler.INSTANCE.isRunning()) { + ; + } +@@ -335,12 +396,8 @@ + boolean flag = false; + ProfiledDuration profiledduration = JvmProfiler.INSTANCE.onWorldLoadedStarted(); + +- this.worldData.setModdedInfo(this.getServerModName(), this.getModdedStatus().shouldReportAsModified()); +- ChunkProgressListener chunkprogresslistener = this.progressListenerFactory.create(11); ++ loadWorld0(s); // CraftBukkit + +- this.createLevels(chunkprogresslistener); +- this.forceDifficulty(); +- this.prepareLevels(chunkprogresslistener); + if (profiledduration != null) { + profiledduration.finish(); + } +@@ -357,28 +414,221 @@ + + protected void forceDifficulty() {} + +- protected void createLevels(ChunkProgressListener chunkprogresslistener) { +- ServerLevelData serverleveldata = this.worldData.overworldData(); +- boolean flag = this.worldData.isDebugWorld(); +- Registry registry = this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM); +- WorldOptions worldoptions = this.worldData.worldGenOptions(); +- long i = worldoptions.seed(); +- long j = BiomeManager.obfuscateSeed(i); +- List list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(serverleveldata)); +- LevelStem levelstem = (LevelStem) registry.get(LevelStem.OVERWORLD); +- ServerLevel serverlevel = new ServerLevel(this, this.executor, this.storageSource, serverleveldata, Level.OVERWORLD, levelstem, chunkprogresslistener, flag, j, list, true, (RandomSequences) null); ++ // CraftBukkit start ++ private void loadWorld0(String s) { ++ LevelStorageSource.LevelStorageAccess worldSession = this.storageSource; + +- this.levels.put(Level.OVERWORLD, serverlevel); +- DimensionDataStorage dimensiondatastorage = serverlevel.getDataStorage(); ++ Registry dimensions = this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM); ++ for (LevelStem worldDimension : dimensions) { ++ ResourceKey dimensionKey = dimensions.getResourceKey(worldDimension).get(); + +- this.readScoreboard(dimensiondatastorage); +- this.commandStorage = new CommandStorage(dimensiondatastorage); +- WorldBorder worldborder = serverlevel.getWorldBorder(); ++ ServerLevel world; ++ int dimension = 0; + +- if (!serverleveldata.isInitialized()) { ++ if (dimensionKey == LevelStem.NETHER) { ++ if (isNetherEnabled()) { ++ dimension = -1; ++ } else { ++ continue; ++ } ++ } else if (dimensionKey == LevelStem.END) { ++ if (server.getAllowEnd()) { ++ dimension = 1; ++ } else { ++ continue; ++ } ++ } else if (dimensionKey != LevelStem.OVERWORLD) { ++ dimension = -999; ++ } ++ ++ String worldType = (dimension == -999) ? dimensionKey.location().getNamespace() + "_" + dimensionKey.location().getPath() : org.bukkit.World.Environment.getEnvironment(dimension).toString().toLowerCase(); ++ String name = (dimensionKey == LevelStem.OVERWORLD) ? s : s + "_" + worldType; ++ if (dimension != 0) { ++ File newWorld = LevelStorageSource.getStorageFolder(new File(name).toPath(), dimensionKey).toFile(); ++ File oldWorld = LevelStorageSource.getStorageFolder(new File(s).toPath(), dimensionKey).toFile(); ++ File oldLevelDat = new File(new File(s), "level.dat"); // The data folders exist on first run as they are created in the PersistentCollection constructor above, but the level.dat won't ++ ++ if (!newWorld.isDirectory() && oldWorld.isDirectory() && oldLevelDat.isFile()) { ++ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder required ----"); ++ MinecraftServer.LOGGER.info("Unfortunately due to the way that Minecraft implemented multiworld support in 1.6, Bukkit requires that you move your " + worldType + " folder to a new location in order to operate correctly."); ++ MinecraftServer.LOGGER.info("We will move this folder for you, but it will mean that you need to move it back should you wish to stop using Bukkit in the future."); ++ MinecraftServer.LOGGER.info("Attempting to move " + oldWorld + " to " + newWorld + "..."); ++ ++ if (newWorld.exists()) { ++ MinecraftServer.LOGGER.warn("A file or folder already exists at " + newWorld + "!"); ++ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder failed ----"); ++ } else if (newWorld.getParentFile().mkdirs()) { ++ if (oldWorld.renameTo(newWorld)) { ++ MinecraftServer.LOGGER.info("Success! To restore " + worldType + " in the future, simply move " + newWorld + " to " + oldWorld); ++ // Migrate world data too. ++ try { ++ com.google.common.io.Files.copy(oldLevelDat, new File(new File(name), "level.dat")); ++ org.apache.commons.io.FileUtils.copyDirectory(new File(new File(s), "data"), new File(new File(name), "data")); ++ } catch (IOException exception) { ++ MinecraftServer.LOGGER.warn("Unable to migrate world data."); ++ } ++ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder complete ----"); ++ } else { ++ MinecraftServer.LOGGER.warn("Could not move folder " + oldWorld + " to " + newWorld + "!"); ++ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder failed ----"); ++ } ++ } else { ++ MinecraftServer.LOGGER.warn("Could not create path for " + newWorld + "!"); ++ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder failed ----"); ++ } ++ } ++ ++ try { ++ worldSession = LevelStorageSource.createDefault(server.getWorldContainer().toPath()).validateAndCreateAccess(name, dimensionKey); ++ } catch (IOException | ContentValidationException ex) { ++ throw new RuntimeException(ex); ++ } ++ } ++ ++ Dynamic dynamic; ++ if (worldSession.hasWorldData()) { ++ LevelSummary worldinfo; ++ ++ try { ++ dynamic = worldSession.getDataTag(); ++ worldinfo = worldSession.getSummary(dynamic); ++ } catch (NbtException | ReportedNbtException | IOException ioexception) { ++ LevelStorageSource.LevelDirectory convertable_b = worldSession.getLevelDirectory(); ++ ++ MinecraftServer.LOGGER.warn("Failed to load world data from {}", convertable_b.dataFile(), ioexception); ++ MinecraftServer.LOGGER.info("Attempting to use fallback"); ++ ++ try { ++ dynamic = worldSession.getDataTagFallback(); ++ worldinfo = worldSession.getSummary(dynamic); ++ } catch (NbtException | ReportedNbtException | IOException ioexception1) { ++ MinecraftServer.LOGGER.error("Failed to load world data from {}", convertable_b.oldDataFile(), ioexception1); ++ MinecraftServer.LOGGER.error("Failed to load world data from {} and {}. World files may be corrupted. Shutting down.", convertable_b.dataFile(), convertable_b.oldDataFile()); ++ return; ++ } ++ ++ worldSession.restoreLevelDataFromOld(); ++ } ++ ++ if (worldinfo.requiresManualConversion()) { ++ MinecraftServer.LOGGER.info("This world must be opened in an older version (like 1.6.4) to be safely converted"); ++ return; ++ } ++ ++ if (!worldinfo.isCompatible()) { ++ MinecraftServer.LOGGER.info("This world was created by an incompatible version."); ++ return; ++ } ++ } else { ++ dynamic = null; ++ } ++ ++ org.bukkit.generator.ChunkGenerator gen = this.server.getGenerator(name); ++ org.bukkit.generator.BiomeProvider biomeProvider = this.server.getBiomeProvider(name); ++ ++ PrimaryLevelData worlddata; ++ WorldLoader.a worldloader_a = this.worldLoader; ++ Registry iregistry = worldloader_a.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM); ++ if (dynamic != null) { ++ LevelDataAndDimensions leveldataanddimensions = LevelStorageSource.getLevelDataAndDimensions(dynamic, worldloader_a.dataConfiguration(), iregistry, worldloader_a.datapackWorldgen()); ++ ++ worlddata = (PrimaryLevelData) leveldataanddimensions.worldData(); ++ } else { ++ LevelSettings worldsettings; ++ WorldOptions worldoptions; ++ WorldDimensions worlddimensions; ++ ++ if (this.isDemo()) { ++ worldsettings = MinecraftServer.DEMO_SETTINGS; ++ worldoptions = WorldOptions.DEMO_OPTIONS; ++ worlddimensions = WorldPresets.createNormalWorldDimensions(worldloader_a.datapackWorldgen()); ++ } else { ++ DedicatedServerProperties dedicatedserverproperties = ((DedicatedServer) this).getProperties(); ++ ++ worldsettings = new LevelSettings(dedicatedserverproperties.levelName, dedicatedserverproperties.gamemode, dedicatedserverproperties.hardcore, dedicatedserverproperties.difficulty, false, new GameRules(), worldloader_a.dataConfiguration()); ++ worldoptions = options.has("bonusChest") ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions; ++ worlddimensions = dedicatedserverproperties.createDimensions(worldloader_a.datapackWorldgen()); ++ } ++ ++ WorldDimensions.b worlddimensions_b = worlddimensions.bake(iregistry); ++ Lifecycle lifecycle = worlddimensions_b.lifecycle().add(worldloader_a.datapackWorldgen().allRegistriesLifecycle()); ++ ++ worlddata = new PrimaryLevelData(worldsettings, worldoptions, worlddimensions_b.specialWorldProperty(), lifecycle); ++ } ++ worlddata.checkName(name); // CraftBukkit - Migration did not rewrite the level.dat; This forces 1.8 to take the last loaded world as respawn (in this case the end) ++ if (options.has("forceUpgrade")) { ++ net.minecraft.server.Main.forceUpgrade(worldSession, DataFixers.getDataFixer(), options.has("eraseCache"), () -> { ++ return true; ++ }, dimensions); ++ } ++ ++ PrimaryLevelData iworlddataserver = worlddata; ++ boolean flag = worlddata.isDebugWorld(); ++ WorldOptions worldoptions = worlddata.worldGenOptions(); ++ long i = worldoptions.seed(); ++ long j = BiomeManager.obfuscateSeed(i); ++ List list = ImmutableList.of(new MobSpawnerPhantom(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(iworlddataserver)); ++ LevelStem worlddimension = (LevelStem) dimensions.get(dimensionKey); ++ ++ org.bukkit.generator.WorldInfo worldInfo = new org.bukkit.craftbukkit.generator.CraftWorldInfo(iworlddataserver, worldSession, org.bukkit.World.Environment.getEnvironment(dimension), worlddimension.type().value()); ++ if (biomeProvider == null && gen != null) { ++ biomeProvider = gen.getDefaultBiomeProvider(worldInfo); ++ } ++ ++ ResourceKey worldKey = ResourceKey.create(Registries.DIMENSION, dimensionKey.location()); ++ ++ if (dimensionKey == LevelStem.OVERWORLD) { ++ this.worldData = worlddata; ++ this.worldData.setGameType(((DedicatedServer) this).getProperties().gamemode); // From DedicatedServer.init ++ ++ ChunkProgressListener worldloadlistener = this.progressListenerFactory.create(11); ++ ++ world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, worlddimension, worldloadlistener, flag, j, list, true, (RandomSequences) null, org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider); ++ DimensionDataStorage worldpersistentdata = world.getDataStorage(); ++ this.readScoreboard(worldpersistentdata); ++ this.server.scoreboardManager = new org.bukkit.craftbukkit.scoreboard.CraftScoreboardManager(this, world.getScoreboard()); ++ this.commandStorage = new CommandStorage(worldpersistentdata); ++ } else { ++ ChunkProgressListener worldloadlistener = this.progressListenerFactory.create(11); ++ world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, worlddimension, worldloadlistener, flag, j, ImmutableList.of(), true, this.overworld().getRandomSequences(), org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider); ++ } ++ ++ worlddata.setModdedInfo(this.getServerModName(), this.getModdedStatus().shouldReportAsModified()); ++ this.initWorld(world, worlddata, worldData, worldoptions); ++ ++ this.addLevel(world); ++ this.getPlayerList().addWorldborderListener(world); ++ ++ if (worlddata.getCustomBossEvents() != null) { ++ this.getCustomBossEvents().load(worlddata.getCustomBossEvents()); ++ } ++ } ++ this.forceDifficulty(); ++ for (ServerLevel worldserver : this.getAllLevels()) { ++ this.prepareLevels(worldserver.getChunkSource().chunkMap.progressListener, worldserver); ++ worldserver.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API ++ this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldLoadEvent(worldserver.getWorld())); ++ } ++ ++ this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.POSTWORLD); ++ this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP)); ++ this.connection.acceptConnections(); ++ } ++ ++ public void initWorld(ServerLevel worldserver, ServerLevelData iworlddataserver, WorldData saveData, WorldOptions worldoptions) { ++ boolean flag = saveData.isDebugWorld(); ++ // CraftBukkit start ++ if (worldserver.generator != null) { ++ worldserver.getWorld().getPopulators().addAll(worldserver.generator.getDefaultPopulators(worldserver.getWorld())); ++ } ++ WorldBorder worldborder = worldserver.getWorldBorder(); ++ worldborder.applySettings(iworlddataserver.getWorldBorder()); // CraftBukkit - move up so that WorldBorder is set during WorldInitEvent ++ this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldInitEvent(worldserver.getWorld())); // CraftBukkit - SPIGOT-5569: Call WorldInitEvent before any chunks are generated ++ ++ if (!iworlddataserver.isInitialized()) { + try { +- setInitialSpawn(serverlevel, serverleveldata, worldoptions.generateBonusChest(), flag); +- serverleveldata.setInitialized(true); ++ setInitialSpawn(worldserver, iworlddataserver, worldoptions.generateBonusChest(), flag); ++ iworlddataserver.setInitialized(true); + if (flag) { + this.setupDebugLevel(this.worldData); + } +@@ -386,7 +636,7 @@ + CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception initializing level"); + + try { +- serverlevel.fillReportDetails(crashreport); ++ worldserver.fillReportDetails(crashreport); + } catch (Throwable throwable1) { + ; + } +@@ -394,49 +644,42 @@ + throw new ReportedException(crashreport); + } + +- serverleveldata.setInitialized(true); ++ iworlddataserver.setInitialized(true); + } + +- this.getPlayerList().addWorldborderListener(serverlevel); +- if (this.worldData.getCustomBossEvents() != null) { +- this.getCustomBossEvents().load(this.worldData.getCustomBossEvents()); +- } +- +- RandomSequences randomsequences = serverlevel.getRandomSequences(); +- Iterator iterator = registry.entrySet().iterator(); +- +- while (iterator.hasNext()) { +- Entry, LevelStem> entry = (Entry) iterator.next(); +- ResourceKey resourcekey = (ResourceKey) entry.getKey(); +- +- if (resourcekey != LevelStem.OVERWORLD) { +- ResourceKey resourcekey1 = ResourceKey.create(Registries.DIMENSION, resourcekey.location()); +- DerivedLevelData derivedleveldata = new DerivedLevelData(this.worldData, serverleveldata); +- ServerLevel serverlevel1 = new ServerLevel(this, this.executor, this.storageSource, derivedleveldata, resourcekey1, (LevelStem) entry.getValue(), chunkprogresslistener, flag, j, ImmutableList.of(), false, randomsequences); +- +- worldborder.addListener(new BorderChangeListener.DelegateBorderChangeListener(serverlevel1.getWorldBorder())); +- this.levels.put(resourcekey1, serverlevel1); +- } +- } +- +- worldborder.applySettings(serverleveldata.getWorldBorder()); + } ++ // CraftBukkit end + +- private static void setInitialSpawn(ServerLevel serverlevel, ServerLevelData serverleveldata, boolean flag, boolean flag1) { +- if (flag1) { +- serverleveldata.setSpawn(BlockPos.ZERO.above(80), 0.0F); ++ private static void setInitialSpawn(ServerLevel level, ServerLevelData levelData, boolean generateBonusChest, boolean debug) { ++ if (debug) { ++ levelData.setSpawn(BlockPos.ZERO.above(80), 0.0F); + } else { +- ServerChunkCache serverchunkcache = serverlevel.getChunkSource(); +- ChunkPos chunkpos = new ChunkPos(serverchunkcache.randomState().sampler().findSpawnPosition()); +- int i = serverchunkcache.getGenerator().getSpawnHeight(serverlevel); ++ ServerChunkCache chunkproviderserver = level.getChunkSource(); ++ ChunkPos chunkcoordintpair = new ChunkPos(chunkproviderserver.randomState().sampler().findSpawnPosition()); ++ // CraftBukkit start ++ if (level.generator != null) { ++ Random rand = new Random(level.getSeed()); ++ org.bukkit.Location spawn = level.generator.getFixedSpawnLocation(level.getWorld(), rand); + +- if (i < serverlevel.getMinBuildHeight()) { +- BlockPos blockpos = chunkpos.getWorldPosition(); ++ if (spawn != null) { ++ if (spawn.getWorld() != level.getWorld()) { ++ throw new IllegalStateException("Cannot set spawn point for " + levelData.getLevelName() + " to be in another world (" + spawn.getWorld().getName() + ")"); ++ } else { ++ levelData.setSpawn(new BlockPos(spawn.getBlockX(), spawn.getBlockY(), spawn.getBlockZ()), spawn.getYaw()); ++ return; ++ } ++ } ++ } ++ // CraftBukkit end ++ int i = chunkproviderserver.getGenerator().getSpawnHeight(level); + +- i = serverlevel.getHeight(Heightmap.Types.WORLD_SURFACE, blockpos.getX() + 8, blockpos.getZ() + 8); ++ if (i < level.getMinBuildHeight()) { ++ BlockPos blockposition = chunkcoordintpair.getWorldPosition(); ++ ++ i = level.getHeight(Heightmap.Types.WORLD_SURFACE, blockposition.getX() + 8, blockposition.getZ() + 8); + } + +- serverleveldata.setSpawn(chunkpos.getWorldPosition().offset(8, i, 8), 0.0F); ++ levelData.setSpawn(chunkcoordintpair.getWorldPosition().offset(8, i, 8), 0.0F); + int j = 0; + int k = 0; + int l = 0; +@@ -445,10 +688,10 @@ + + for (int j1 = 0; j1 < Mth.square(11); ++j1) { + if (j >= -5 && j <= 5 && k >= -5 && k <= 5) { +- BlockPos blockpos1 = PlayerRespawnLogic.getSpawnPosInChunk(serverlevel, new ChunkPos(chunkpos.x + j, chunkpos.z + k)); ++ BlockPos blockposition1 = PlayerRespawnLogic.getSpawnPosInChunk(level, new ChunkPos(chunkcoordintpair.x + j, chunkcoordintpair.z + k)); + +- if (blockpos1 != null) { +- serverleveldata.setSpawn(blockpos1, 0.0F); ++ if (blockposition1 != null) { ++ levelData.setSpawn(blockposition1, 0.0F); + break; + } + } +@@ -464,70 +707,84 @@ + k += i1; + } + +- if (flag) { +- serverlevel.registryAccess().registry(Registries.CONFIGURED_FEATURE).flatMap((registry) -> { +- return registry.getHolder(MiscOverworldFeatures.BONUS_CHEST); +- }).ifPresent((holder_reference) -> { +- ((ConfiguredFeature) holder_reference.value()).place(serverlevel, serverchunkcache.getGenerator(), serverlevel.random, new BlockPos(serverleveldata.getXSpawn(), serverleveldata.getYSpawn(), serverleveldata.getZSpawn())); ++ if (generateBonusChest) { ++ level.registryAccess().registry(Registries.CONFIGURED_FEATURE).flatMap((iregistry) -> { ++ return iregistry.getHolder(MiscOverworldFeatures.BONUS_CHEST); ++ }).ifPresent((holder_c) -> { ++ ((ConfiguredFeature) holder_c.value()).place(level, chunkproviderserver.getGenerator(), level.random, new BlockPos(levelData.getXSpawn(), levelData.getYSpawn(), levelData.getZSpawn())); + }); + } + + } + } + +- private void setupDebugLevel(WorldData worlddata) { +- worlddata.setDifficulty(Difficulty.PEACEFUL); +- worlddata.setDifficultyLocked(true); +- ServerLevelData serverleveldata = worlddata.overworldData(); ++ private void setupDebugLevel(WorldData worldData) { ++ worldData.setDifficulty(Difficulty.PEACEFUL); ++ worldData.setDifficultyLocked(true); ++ ServerLevelData iworlddataserver = worldData.overworldData(); + +- serverleveldata.setRaining(false); +- serverleveldata.setThundering(false); +- serverleveldata.setClearWeatherTime(1000000000); +- serverleveldata.setDayTime(6000L); +- serverleveldata.setGameType(GameType.SPECTATOR); ++ iworlddataserver.setRaining(false); ++ iworlddataserver.setThundering(false); ++ iworlddataserver.setClearWeatherTime(1000000000); ++ iworlddataserver.setDayTime(6000L); ++ iworlddataserver.setGameType(GameType.SPECTATOR); + } + +- private void prepareLevels(ChunkProgressListener chunkprogresslistener) { +- ServerLevel serverlevel = this.overworld(); ++ // CraftBukkit start ++ public void prepareLevels(ChunkProgressListener worldloadlistener, ServerLevel worldserver) { ++ // WorldServer worldserver = this.overworld(); ++ this.forceTicks = true; ++ // CraftBukkit end + +- MinecraftServer.LOGGER.info("Preparing start region for dimension {}", serverlevel.dimension().location()); +- BlockPos blockpos = serverlevel.getSharedSpawnPos(); ++ MinecraftServer.LOGGER.info("Preparing start region for dimension {}", worldserver.dimension().location()); ++ BlockPos blockposition = worldserver.getSharedSpawnPos(); + +- chunkprogresslistener.updateSpawnPos(new ChunkPos(blockpos)); +- ServerChunkCache serverchunkcache = serverlevel.getChunkSource(); ++ worldloadlistener.updateSpawnPos(new ChunkPos(blockposition)); ++ ServerChunkCache chunkproviderserver = worldserver.getChunkSource(); + + this.nextTickTimeNanos = Util.getNanos(); +- serverchunkcache.addRegionTicket(TicketType.START, new ChunkPos(blockpos), 11, Unit.INSTANCE); ++ // CraftBukkit start ++ if (worldserver.getWorld().getKeepSpawnInMemory()) { ++ chunkproviderserver.addRegionTicket(TicketType.START, new ChunkPos(blockposition), 11, Unit.INSTANCE); + +- while (serverchunkcache.getTickingGenerated() != 441) { +- this.nextTickTimeNanos = Util.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; +- this.waitUntilNextTick(); ++ while (chunkproviderserver.getTickingGenerated() != 441) { ++ // this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; ++ this.executeModerately(); ++ } + } + +- this.nextTickTimeNanos = Util.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; +- this.waitUntilNextTick(); +- Iterator iterator = this.levels.values().iterator(); ++ // this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; ++ this.executeModerately(); ++ // Iterator iterator = this.levels.values().iterator(); + +- while (iterator.hasNext()) { +- ServerLevel serverlevel1 = (ServerLevel) iterator.next(); +- ForcedChunksSavedData forcedchunkssaveddata = (ForcedChunksSavedData) serverlevel1.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks"); ++ if (true) { ++ ServerLevel worldserver1 = worldserver; ++ // CraftBukkit end ++ ForcedChunksSavedData forcedchunk = (ForcedChunksSavedData) worldserver1.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks"); + +- if (forcedchunkssaveddata != null) { +- LongIterator longiterator = forcedchunkssaveddata.getChunks().iterator(); ++ if (forcedchunk != null) { ++ LongIterator longiterator = forcedchunk.getChunks().iterator(); + + while (longiterator.hasNext()) { + long i = longiterator.nextLong(); +- ChunkPos chunkpos = new ChunkPos(i); ++ ChunkPos chunkcoordintpair = new ChunkPos(i); + +- serverlevel1.getChunkSource().updateChunkForced(chunkpos, true); ++ worldserver1.getChunkSource().updateChunkForced(chunkcoordintpair, true); + } + } + } + +- this.nextTickTimeNanos = Util.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; +- this.waitUntilNextTick(); +- chunkprogresslistener.stop(); +- this.updateMobSpawningFlags(); ++ // CraftBukkit start ++ // this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; ++ this.executeModerately(); ++ // CraftBukkit end ++ worldloadlistener.stop(); ++ // CraftBukkit start ++ // this.updateMobSpawningFlags(); ++ worldserver.setSpawnSettings(this.isSpawningMonsters(), this.isSpawningAnimals()); ++ ++ this.forceTicks = false; ++ // CraftBukkit end + } + + public GameType getDefaultGameType() { +@@ -544,32 +801,36 @@ + + public abstract boolean shouldRconBroadcast(); + +- public boolean saveAllChunks(boolean flag, boolean flag1, boolean flag2) { ++ public boolean saveAllChunks(boolean suppressLog, boolean flush, boolean forced) { + boolean flag3 = false; + + for (Iterator iterator = this.getAllLevels().iterator(); iterator.hasNext(); flag3 = true) { +- ServerLevel serverlevel = (ServerLevel) iterator.next(); ++ ServerLevel worldserver = (ServerLevel) iterator.next(); + +- if (!flag) { +- MinecraftServer.LOGGER.info("Saving chunks for level '{}'/{}", serverlevel, serverlevel.dimension().location()); ++ if (!suppressLog) { ++ MinecraftServer.LOGGER.info("Saving chunks for level '{}'/{}", worldserver, worldserver.dimension().location()); + } + +- serverlevel.save((ProgressListener) null, flag1, serverlevel.noSave && !flag2); ++ worldserver.save((ProgressListener) null, flush, worldserver.noSave && !forced); + } + +- ServerLevel serverlevel1 = this.overworld(); +- ServerLevelData serverleveldata = this.worldData.overworldData(); ++ // CraftBukkit start - moved to WorldServer.save ++ /* ++ WorldServer worldserver1 = this.overworld(); ++ IWorldDataServer iworlddataserver = this.worldData.overworldData(); + +- serverleveldata.setWorldBorder(serverlevel1.getWorldBorder().createSettings()); ++ iworlddataserver.setWorldBorder(worldserver1.getWorldBorder().createSettings()); + this.worldData.setCustomBossEvents(this.getCustomBossEvents().save()); + this.storageSource.saveDataTag(this.registryAccess(), this.worldData, this.getPlayerList().getSingleplayerData()); +- if (flag1) { ++ */ ++ // CraftBukkit end ++ if (flush) { + Iterator iterator1 = this.getAllLevels().iterator(); + + while (iterator1.hasNext()) { +- ServerLevel serverlevel2 = (ServerLevel) iterator1.next(); ++ ServerLevel worldserver2 = (ServerLevel) iterator1.next(); + +- MinecraftServer.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", serverlevel2.getChunkSource().chunkMap.getStorageName()); ++ MinecraftServer.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", worldserver2.getChunkSource().chunkMap.getStorageName()); + } + + MinecraftServer.LOGGER.info("ThreadedAnvilChunkStorage: All dimensions are saved"); +@@ -578,13 +839,13 @@ + return flag3; + } + +- public boolean saveEverything(boolean flag, boolean flag1, boolean flag2) { ++ public boolean saveEverything(boolean suppressLog, boolean flush, boolean forced) { + boolean flag3; + + try { + this.isSaving = true; + this.getPlayerList().saveAll(); +- flag3 = this.saveAllChunks(flag, flag1, flag2); ++ flag3 = this.saveAllChunks(suppressLog, flush, forced); + } finally { + this.isSaving = false; + } +@@ -593,47 +854,68 @@ + } + + @Override +- @Override + public void close() { + this.stopServer(); + } + ++ // CraftBukkit start ++ private boolean hasStopped = false; ++ private final Object stopLock = new Object(); ++ public final boolean hasStopped() { ++ synchronized (stopLock) { ++ return hasStopped; ++ } ++ } ++ // CraftBukkit end ++ + public void stopServer() { ++ // CraftBukkit start - prevent double stopping on multiple threads ++ synchronized(stopLock) { ++ if (hasStopped) return; ++ hasStopped = true; ++ } ++ // CraftBukkit end + if (this.metricsRecorder.isRecording()) { + this.cancelRecordingMetrics(); + } + + MinecraftServer.LOGGER.info("Stopping server"); ++ // CraftBukkit start ++ if (this.server != null) { ++ this.server.disablePlugins(); ++ } ++ // CraftBukkit end + this.getConnection().stop(); + this.isSaving = true; + if (this.playerList != null) { + MinecraftServer.LOGGER.info("Saving players"); + this.playerList.saveAll(); + this.playerList.removeAll(); ++ try { Thread.sleep(100); } catch (InterruptedException ex) {} // CraftBukkit - SPIGOT-625 - give server at least a chance to send packets + } + + MinecraftServer.LOGGER.info("Saving worlds"); + Iterator iterator = this.getAllLevels().iterator(); + +- ServerLevel serverlevel; ++ ServerLevel worldserver; + + while (iterator.hasNext()) { +- serverlevel = (ServerLevel) iterator.next(); +- if (serverlevel != null) { +- serverlevel.noSave = false; ++ worldserver = (ServerLevel) iterator.next(); ++ if (worldserver != null) { ++ worldserver.noSave = false; + } + } + +- while (this.levels.values().stream().anyMatch((serverlevel1) -> { +- return serverlevel1.getChunkSource().chunkMap.hasWork(); ++ while (this.levels.values().stream().anyMatch((worldserver1) -> { ++ return worldserver1.getChunkSource().chunkMap.hasWork(); + })) { + this.nextTickTimeNanos = Util.getNanos() + TimeUtil.NANOSECONDS_PER_MILLISECOND; + iterator = this.getAllLevels().iterator(); + + while (iterator.hasNext()) { +- serverlevel = (ServerLevel) iterator.next(); +- serverlevel.getChunkSource().removeTicketsOnClosing(); +- serverlevel.getChunkSource().tick(() -> { ++ worldserver = (ServerLevel) iterator.next(); ++ worldserver.getChunkSource().removeTicketsOnClosing(); ++ worldserver.getChunkSource().tick(() -> { + return true; + }, false); + } +@@ -645,10 +927,10 @@ + iterator = this.getAllLevels().iterator(); + + while (iterator.hasNext()) { +- serverlevel = (ServerLevel) iterator.next(); +- if (serverlevel != null) { ++ worldserver = (ServerLevel) iterator.next(); ++ if (worldserver != null) { + try { +- serverlevel.close(); ++ worldserver.close(); + } catch (IOException ioexception) { + MinecraftServer.LOGGER.error("Exception closing the level", ioexception); + } +@@ -670,17 +952,17 @@ + return this.localIp; + } + +- public void setLocalIp(String s) { +- this.localIp = s; ++ public void setLocalIp(String host) { ++ this.localIp = host; + } + + public boolean isRunning() { + return this.running; + } + +- public void halt(boolean flag) { ++ public void halt(boolean waitForServer) { + this.running = false; +- if (flag) { ++ if (waitForServer) { + try { + this.serverThread.join(); + } catch (InterruptedException interruptedexception) { +@@ -697,7 +979,7 @@ + } + + this.nextTickTimeNanos = Util.getNanos(); +- this.statusIcon = (ServerStatus.Favicon) this.loadStatusIcon().orElse((Object) null); ++ this.statusIcon = (ServerStatus.a) this.loadStatusIcon().orElse(null); // CraftBukkit - decompile error + this.status = this.buildServerStatus(); + + while (this.running) { +@@ -714,6 +996,7 @@ + if (j > MinecraftServer.OVERLOADED_THRESHOLD_NANOS + 20L * i && this.nextTickTimeNanos - this.lastOverloadWarningNanos >= MinecraftServer.OVERLOADED_WARNING_INTERVAL_NANOS + 100L * i) { + long k = j / i; + ++ if (server.getWarnOnOverload()) // CraftBukkit + MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", j / TimeUtil.NANOSECONDS_PER_MILLISECOND, k); + this.nextTickTimeNanos += k * i; + this.lastOverloadWarningNanos = this.nextTickTimeNanos; +@@ -727,6 +1010,7 @@ + this.debugCommandProfiler = new MinecraftServer.TimeProfiler(Util.getNanos(), this.tickCount); + } + ++ MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit + this.nextTickTimeNanos += i; + this.startMetricsRecordingTick(); + this.profiler.push("tick"); +@@ -771,6 +1055,12 @@ + this.services.profileCache().clearExecutor(); + } + ++ // CraftBukkit start - Restore terminal to original settings ++ try { ++ reader.getTerminal().restore(); ++ } catch (Exception ignored) { ++ } ++ // CraftBukkit end + this.onServerExit(); + } + +@@ -778,10 +1068,10 @@ + + } + +- private static CrashReport constructOrExtractCrashReport(Throwable throwable) { ++ private static CrashReport constructOrExtractCrashReport(Throwable cause) { + ReportedException reportedexception = null; + +- for (Throwable throwable1 = throwable; throwable1 != null; throwable1 = throwable1.getCause()) { ++ for (Throwable throwable1 = cause; throwable1 != null; throwable1 = throwable1.getCause()) { + if (throwable1 instanceof ReportedException) { + ReportedException reportedexception1 = (ReportedException) throwable1; + +@@ -793,20 +1083,27 @@ + + if (reportedexception != null) { + crashreport = reportedexception.getReport(); +- if (reportedexception != throwable) { +- crashreport.addCategory("Wrapped in").setDetailError("Wrapping exception", throwable); ++ if (reportedexception != cause) { ++ crashreport.addCategory("Wrapped in").setDetailError("Wrapping exception", cause); + } + } else { +- crashreport = new CrashReport("Exception in server tick loop", throwable); ++ crashreport = new CrashReport("Exception in server tick loop", cause); + } + + return crashreport; + } + + private boolean haveTime() { +- return this.runningTask() || Util.getNanos() < (this.mayHaveDelayedTasks ? this.delayedTasksMaxNextTickTimeNanos : this.nextTickTimeNanos); ++ // CraftBukkit start ++ return this.forceTicks || this.runningTask() || Util.getNanos() < (this.mayHaveDelayedTasks ? this.delayedTasksMaxNextTickTimeNanos : this.nextTickTimeNanos); + } + ++ private void executeModerately() { ++ this.runAllTasks(); ++ java.util.concurrent.locks.LockSupport.parkNanos("executing tasks", 1000L); ++ // CraftBukkit end ++ } ++ + protected void waitUntilNextTick() { + this.runAllTasks(); + this.managedBlock(() -> { +@@ -815,18 +1112,15 @@ + } + + @Override +- @Override +- protected TickTask wrapRunnable(Runnable runnable) { ++ public TickTask wrapRunnable(Runnable runnable) { + return new TickTask(this.tickCount, runnable); + } + +- @Override + protected boolean shouldRun(TickTask ticktask) { + return ticktask.getTick() + 3 < this.tickCount || this.haveTime(); + } + + @Override +- @Override + public boolean pollTask() { + boolean flag = this.pollTaskInternal(); + +@@ -842,9 +1136,9 @@ + Iterator iterator = this.getAllLevels().iterator(); + + while (iterator.hasNext()) { +- ServerLevel serverlevel = (ServerLevel) iterator.next(); ++ ServerLevel worldserver = (ServerLevel) iterator.next(); + +- if (serverlevel.getChunkSource().pollTask()) { ++ if (worldserver.getChunkSource().pollTask()) { + return true; + } + } +@@ -854,13 +1148,12 @@ + } + } + +- @Override +- protected void doRunTask(TickTask ticktask) { ++ public void doRunTask(TickTask ticktask) { // CraftBukkit - decompile error + this.getProfiler().incrementCounter("runTask"); + super.doRunTask(ticktask); + } + +- private Optional loadStatusIcon() { ++ private Optional loadStatusIcon() { + Optional optional = Optional.of(this.getFile("server-icon.png").toPath()).filter((path) -> { + return Files.isRegularFile(path, new LinkOption[0]); + }).or(() -> { +@@ -878,7 +1171,7 @@ + ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(); + + ImageIO.write(bufferedimage, "PNG", bytearrayoutputstream); +- return Optional.of(new ServerStatus.Favicon(bytearrayoutputstream.toByteArray())); ++ return Optional.of(new ServerStatus.a(bytearrayoutputstream.toByteArray())); + } catch (Exception exception) { + MinecraftServer.LOGGER.error("Couldn't load server icon", exception); + return Optional.empty(); +@@ -894,7 +1187,7 @@ + return new File("."); + } + +- public void onServerCrash(CrashReport crashreport) {} ++ public void onServerCrash(CrashReport report) {} + + public void onServerExit() {} + +@@ -902,20 +1195,22 @@ + return false; + } + +- public void tickServer(BooleanSupplier booleansupplier) { ++ public void tickServer(BooleanSupplier hasTimeLeft) { + long i = Util.getNanos(); + + ++this.tickCount; + this.tickRateManager.tick(); +- this.tickChildren(booleansupplier); ++ this.tickChildren(hasTimeLeft); + if (i - this.lastServerStatus >= MinecraftServer.STATUS_EXPIRE_TIME_NANOS) { + this.lastServerStatus = i; + this.status = this.buildServerStatus(); + } + + --this.ticksUntilAutosave; +- if (this.ticksUntilAutosave <= 0) { +- this.ticksUntilAutosave = this.computeNextAutosaveInterval(); ++ // CraftBukkit start ++ if (this.autosavePeriod > 0 && this.ticksUntilAutosave <= 0) { ++ this.ticksUntilAutosave = this.autosavePeriod; ++ // CraftBukkit end + MinecraftServer.LOGGER.debug("Autosave started"); + this.profiler.push("save"); + this.saveEverything(true, false, false); +@@ -965,62 +1260,79 @@ + protected void logTickTime(long i) {} + + private ServerStatus buildServerStatus() { +- ServerStatus.Players serverstatus_players = this.buildPlayerStatus(); ++ ServerStatus.ServerPingPlayerSample serverping_serverpingplayersample = this.buildPlayerStatus(); + +- return new ServerStatus(Component.nullToEmpty(this.motd), Optional.of(serverstatus_players), Optional.of(ServerStatus.Version.current()), Optional.ofNullable(this.statusIcon), this.enforceSecureProfile()); ++ return new ServerStatus(Component.nullToEmpty(this.motd), Optional.of(serverping_serverpingplayersample), Optional.of(ServerStatus.Version.current()), Optional.ofNullable(this.statusIcon), this.enforceSecureProfile()); + } + +- private ServerStatus.Players buildPlayerStatus() { ++ private ServerStatus.ServerPingPlayerSample buildPlayerStatus() { + List list = this.playerList.getPlayers(); + int i = this.getMaxPlayers(); + + if (this.hidesOnlinePlayers()) { +- return new ServerStatus.Players(i, list.size(), List.of()); ++ return new ServerStatus.ServerPingPlayerSample(i, list.size(), List.of()); + } else { + int j = Math.min(list.size(), 12); + ObjectArrayList objectarraylist = new ObjectArrayList(j); + int k = Mth.nextInt(this.random, 0, list.size() - j); + + for (int l = 0; l < j; ++l) { +- ServerPlayer serverplayer = (ServerPlayer) list.get(k + l); ++ ServerPlayer entityplayer = (ServerPlayer) list.get(k + l); + +- objectarraylist.add(serverplayer.allowsListing() ? serverplayer.getGameProfile() : MinecraftServer.ANONYMOUS_PLAYER_PROFILE); ++ objectarraylist.add(entityplayer.allowsListing() ? entityplayer.getGameProfile() : MinecraftServer.ANONYMOUS_PLAYER_PROFILE); + } + + Util.shuffle(objectarraylist, this.random); +- return new ServerStatus.Players(i, list.size(), objectarraylist); ++ return new ServerStatus.ServerPingPlayerSample(i, list.size(), objectarraylist); + } + } + +- public void tickChildren(BooleanSupplier booleansupplier) { +- this.getPlayerList().getPlayers().forEach((serverplayer) -> { +- serverplayer.connection.suspendFlushing(); ++ public void tickChildren(BooleanSupplier hasTimeLeft) { ++ this.getPlayerList().getPlayers().forEach((entityplayer) -> { ++ entityplayer.connection.suspendFlushing(); + }); ++ this.server.getScheduler().mainThreadHeartbeat(this.tickCount); // CraftBukkit + this.profiler.push("commandFunctions"); + this.getFunctions().tick(); + this.profiler.popPush("levels"); + Iterator iterator = this.getAllLevels().iterator(); + ++ // CraftBukkit start ++ // Run tasks that are waiting on processing ++ while (!processQueue.isEmpty()) { ++ processQueue.remove().run(); ++ } ++ ++ // Send time updates to everyone, it will get the right time from the world the player is in. ++ if (this.tickCount % 20 == 0) { ++ for (int i = 0; i < this.getPlayerList().players.size(); ++i) { ++ ServerPlayer entityplayer = (ServerPlayer) this.getPlayerList().players.get(i); ++ entityplayer.connection.send(new ClientboundSetTimePacket(entityplayer.level().getGameTime(), entityplayer.getPlayerTime(), entityplayer.level().getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); // Add support for per player time ++ } ++ } ++ + while (iterator.hasNext()) { +- ServerLevel serverlevel = (ServerLevel) iterator.next(); ++ ServerLevel worldserver = (ServerLevel) iterator.next(); + + this.profiler.push(() -> { +- return serverlevel + " " + serverlevel.dimension().location(); ++ return worldserver + " " + worldserver.dimension().location(); + }); ++ /* Drop global time updates + if (this.tickCount % 20 == 0) { + this.profiler.push("timeSync"); +- this.synchronizeTime(serverlevel); ++ this.synchronizeTime(worldserver); + this.profiler.pop(); + } ++ // CraftBukkit end */ + + this.profiler.push("tick"); + + try { +- serverlevel.tick(booleansupplier); ++ worldserver.tick(hasTimeLeft); + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception ticking world"); + +- serverlevel.fillReportDetails(crashreport); ++ worldserver.fillReportDetails(crashreport); + throw new ReportedException(crashreport); + } + +@@ -1046,17 +1358,17 @@ + iterator = this.playerList.getPlayers().iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- serverplayer.connection.chunkSender.sendNextChunks(serverplayer); +- serverplayer.connection.resumeFlushing(); ++ entityplayer.connection.chunkSender.sendNextChunks(entityplayer); ++ entityplayer.connection.resumeFlushing(); + } + + this.profiler.pop(); + } + +- private void synchronizeTime(ServerLevel serverlevel) { +- this.playerList.broadcastAll(new ClientboundSetTimePacket(serverlevel.getGameTime(), serverlevel.getDayTime(), serverlevel.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)), serverlevel.dimension()); ++ private void synchronizeTime(ServerLevel level) { ++ this.playerList.broadcastAll(new ClientboundSetTimePacket(level.getGameTime(), level.getDayTime(), level.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)), level.dimension()); + } + + public void forceTimeSynchronization() { +@@ -1064,9 +1376,9 @@ + Iterator iterator = this.getAllLevels().iterator(); + + while (iterator.hasNext()) { +- ServerLevel serverlevel = (ServerLevel) iterator.next(); ++ ServerLevel worldserver = (ServerLevel) iterator.next(); + +- this.synchronizeTime(serverlevel); ++ this.synchronizeTime(worldserver); + } + + this.profiler.pop(); +@@ -1076,20 +1388,20 @@ + return true; + } + +- public void addTickable(Runnable runnable) { +- this.tickables.add(runnable); ++ public void addTickable(Runnable tickable) { ++ this.tickables.add(tickable); + } + +- protected void setId(String s) { +- this.serverId = s; ++ protected void setId(String serverId) { ++ this.serverId = serverId; + } + + public boolean isShutdown() { + return !this.serverThread.isAlive(); + } + +- public File getFile(String s) { +- return new File(this.getServerDirectory(), s); ++ public File getFile(String fileName) { ++ return new File(this.getServerDirectory(), fileName); + } + + public final ServerLevel overworld() { +@@ -1097,10 +1409,26 @@ + } + + @Nullable +- public ServerLevel getLevel(ResourceKey resourcekey) { +- return (ServerLevel) this.levels.get(resourcekey); ++ public ServerLevel getLevel(ResourceKey dimension) { ++ return (ServerLevel) this.levels.get(dimension); + } + ++ // CraftBukkit start ++ public void addLevel(ServerLevel level) { ++ Map, ServerLevel> oldLevels = this.levels; ++ Map, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels); ++ newLevels.put(level.dimension(), level); ++ this.levels = Collections.unmodifiableMap(newLevels); ++ } ++ ++ public void removeLevel(ServerLevel level) { ++ Map, ServerLevel> oldLevels = this.levels; ++ Map, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels); ++ newLevels.remove(level.dimension()); ++ this.levels = Collections.unmodifiableMap(newLevels); ++ } ++ // CraftBukkit end ++ + public Set> levelKeys() { + return this.levels.keySet(); + } +@@ -1110,19 +1438,16 @@ + } + + @Override +- @Override + public String getServerVersion() { + return SharedConstants.getCurrentVersion().getName(); + } + + @Override +- @Override + public int getPlayerCount() { + return this.playerList.getPlayerCount(); + } + + @Override +- @Override + public int getMaxPlayers() { + return this.playerList.getMaxPlayers(); + } +@@ -1133,41 +1458,41 @@ + + @DontObfuscate + public String getServerModName() { +- return "vanilla"; ++ return server.getName(); // CraftBukkit - cb > vanilla! + } + +- public SystemReport fillSystemReport(SystemReport systemreport) { +- systemreport.setDetail("Server Running", () -> { ++ public SystemReport fillSystemReport(SystemReport systemReport) { ++ systemReport.setDetail("Server Running", () -> { + return Boolean.toString(this.running); + }); + if (this.playerList != null) { +- systemreport.setDetail("Player Count", () -> { ++ systemReport.setDetail("Player Count", () -> { + int i = this.playerList.getPlayerCount(); + + return i + " / " + this.playerList.getMaxPlayers() + "; " + this.playerList.getPlayers(); + }); + } + +- systemreport.setDetail("Data Packs", () -> { +- return (String) this.packRepository.getSelectedPacks().stream().map((pack) -> { +- String s = pack.getId(); ++ systemReport.setDetail("Data Packs", () -> { ++ return (String) this.packRepository.getSelectedPacks().stream().map((resourcepackloader) -> { ++ String s = resourcepackloader.getId(); + +- return s + (pack.getCompatibility().isCompatible() ? "" : " (incompatible)"); ++ return s + (resourcepackloader.getCompatibility().isCompatible() ? "" : " (incompatible)"); + }).collect(Collectors.joining(", ")); + }); +- systemreport.setDetail("Enabled Feature Flags", () -> { ++ systemReport.setDetail("Enabled Feature Flags", () -> { + return (String) FeatureFlags.REGISTRY.toNames(this.worldData.enabledFeatures()).stream().map(ResourceLocation::toString).collect(Collectors.joining(", ")); + }); +- systemreport.setDetail("World Generation", () -> { ++ systemReport.setDetail("World Generation", () -> { + return this.worldData.worldGenSettingsLifecycle().toString(); + }); + if (this.serverId != null) { +- systemreport.setDetail("Server Id", () -> { ++ systemReport.setDetail("Server Id", () -> { + return this.serverId; + }); + } + +- return this.fillServerSystemReport(systemreport); ++ return this.fillServerSystemReport(systemReport); + } + + public abstract SystemReport fillServerSystemReport(SystemReport report); +@@ -1177,7 +1502,6 @@ + } + + @Override +- @Override + public void sendSystemMessage(Component component) { + MinecraftServer.LOGGER.info(component.getString()); + } +@@ -1190,8 +1514,8 @@ + return this.port; + } + +- public void setPort(int i) { +- this.port = i; ++ public void setPort(int port) { ++ this.port = port; + } + + @Nullable +@@ -1199,8 +1523,8 @@ + return this.singleplayerProfile; + } + +- public void setSingleplayerProfile(@Nullable GameProfile gameprofile) { +- this.singleplayerProfile = gameprofile; ++ public void setSingleplayerProfile(@Nullable GameProfile singleplayerProfile) { ++ this.singleplayerProfile = singleplayerProfile; + } + + public boolean isSingleplayer() { +@@ -1212,43 +1536,43 @@ + + try { + this.keyPair = Crypt.generateKeyPair(); +- } catch (CryptException cryptexception) { +- throw new IllegalStateException("Failed to generate key pair", cryptexception); ++ } catch (CryptException cryptographyexception) { ++ throw new IllegalStateException("Failed to generate key pair", cryptographyexception); + } + } + +- public void setDifficulty(Difficulty difficulty, boolean flag) { +- if (flag || !this.worldData.isDifficultyLocked()) { ++ public void setDifficulty(Difficulty difficulty, boolean forced) { ++ if (forced || !this.worldData.isDifficultyLocked()) { + this.worldData.setDifficulty(this.worldData.isHardcore() ? Difficulty.HARD : difficulty); + this.updateMobSpawningFlags(); + this.getPlayerList().getPlayers().forEach(this::sendDifficultyUpdate); + } + } + +- public int getScaledTrackingDistance(int i) { +- return i; ++ public int getScaledTrackingDistance(int trackingDistance) { ++ return trackingDistance; + } + + private void updateMobSpawningFlags() { + Iterator iterator = this.getAllLevels().iterator(); + + while (iterator.hasNext()) { +- ServerLevel serverlevel = (ServerLevel) iterator.next(); ++ ServerLevel worldserver = (ServerLevel) iterator.next(); + +- serverlevel.setSpawnSettings(this.isSpawningMonsters(), this.isSpawningAnimals()); ++ worldserver.setSpawnSettings(this.isSpawningMonsters(), this.isSpawningAnimals()); + } + + } + +- public void setDifficultyLocked(boolean flag) { +- this.worldData.setDifficultyLocked(flag); ++ public void setDifficultyLocked(boolean locked) { ++ this.worldData.setDifficultyLocked(locked); + this.getPlayerList().getPlayers().forEach(this::sendDifficultyUpdate); + } + +- private void sendDifficultyUpdate(ServerPlayer serverplayer) { +- LevelData leveldata = serverplayer.level().getLevelData(); ++ private void sendDifficultyUpdate(ServerPlayer player) { ++ LevelData worlddata = player.level().getLevelData(); + +- serverplayer.connection.send(new ClientboundChangeDifficultyPacket(leveldata.getDifficulty(), leveldata.isDifficultyLocked())); ++ player.connection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); + } + + public boolean isSpawningMonsters() { +@@ -1259,8 +1583,8 @@ + return this.isDemo; + } + +- public void setDemo(boolean flag) { +- this.isDemo = flag; ++ public void setDemo(boolean demo) { ++ this.isDemo = demo; + } + + public Optional getServerResourcePack() { +@@ -1279,16 +1603,16 @@ + return this.onlineMode; + } + +- public void setUsesAuthentication(boolean flag) { +- this.onlineMode = flag; ++ public void setUsesAuthentication(boolean online) { ++ this.onlineMode = online; + } + + public boolean getPreventProxyConnections() { + return this.preventProxyConnections; + } + +- public void setPreventProxyConnections(boolean flag) { +- this.preventProxyConnections = flag; ++ public void setPreventProxyConnections(boolean preventProxyConnections) { ++ this.preventProxyConnections = preventProxyConnections; + } + + public boolean isSpawningAnimals() { +@@ -1305,28 +1629,27 @@ + return this.pvp; + } + +- public void setPvpAllowed(boolean flag) { +- this.pvp = flag; ++ public void setPvpAllowed(boolean allowPvp) { ++ this.pvp = allowPvp; + } + + public boolean isFlightAllowed() { + return this.allowFlight; + } + +- public void setFlightAllowed(boolean flag) { +- this.allowFlight = flag; ++ public void setFlightAllowed(boolean allow) { ++ this.allowFlight = allow; + } + + public abstract boolean isCommandBlockEnabled(); + + @Override +- @Override + public String getMotd() { + return this.motd; + } + +- public void setMotd(String s) { +- this.motd = s; ++ public void setMotd(String motd) { ++ this.motd = motd; + } + + public boolean isStopped() { +@@ -1337,14 +1660,14 @@ + return this.playerList; + } + +- public void setPlayerList(PlayerList playerlist) { +- this.playerList = playerlist; ++ public void setPlayerList(PlayerList list) { ++ this.playerList = list; + } + + public abstract boolean isPublished(); + +- public void setDefaultGameType(GameType gametype) { +- this.worldData.setGameType(gametype); ++ public void setDefaultGameType(GameType gameMode) { ++ this.worldData.setGameType(gameMode); + } + + public ServerConnectionListener getConnection() { +@@ -1359,7 +1682,7 @@ + return false; + } + +- public boolean publishServer(@Nullable GameType gametype, boolean flag, int i) { ++ public boolean publishServer(@Nullable GameType gameMode, boolean cheats, int port) { + return false; + } + +@@ -1371,7 +1694,7 @@ + return 16; + } + +- public boolean isUnderSpawnProtection(ServerLevel serverlevel, BlockPos blockpos, Player player) { ++ public boolean isUnderSpawnProtection(ServerLevel level, BlockPos pos, Player player) { + return false; + } + +@@ -1391,8 +1714,8 @@ + return this.playerIdleTimeout; + } + +- public void setPlayerIdleTimeout(int i) { +- this.playerIdleTimeout = i; ++ public void setPlayerIdleTimeout(int idleTimeout) { ++ this.playerIdleTimeout = idleTimeout; + } + + public MinecraftSessionService getSessionService() { +@@ -1427,23 +1750,20 @@ + } + + @Override +- @Override + public boolean scheduleExecutables() { + return super.scheduleExecutables() && !this.isStopped(); + } + + @Override +- @Override +- public void executeIfPossible(Runnable runnable) { ++ public void executeIfPossible(Runnable task) { + if (this.isStopped()) { + throw new RejectedExecutionException("Server already shutting down"); + } else { +- super.executeIfPossible(runnable); ++ super.executeIfPossible(task); + } + } + + @Override +- @Override + public Thread getRunningThread() { + return this.serverThread; + } +@@ -1464,8 +1784,8 @@ + return this.fixerUpper; + } + +- public int getSpawnRadius(@Nullable ServerLevel serverlevel) { +- return serverlevel != null ? serverlevel.getGameRules().getInt(GameRules.RULE_SPAWN_RADIUS) : 10; ++ public int getSpawnRadius(@Nullable ServerLevel level) { ++ return level != null ? level.getGameRules().getInt(GameRules.RULE_SPAWN_RADIUS) : 10; + } + + public ServerAdvancementManager getAdvancements() { +@@ -1476,29 +1796,30 @@ + return this.functionManager; + } + +- public CompletableFuture reloadResources(Collection collection) { +- RegistryAccess.Frozen registryaccess_frozen = this.registries.getAccessForLoading(RegistryLayer.RELOADABLE); ++ public CompletableFuture reloadResources(Collection selectedIds) { ++ RegistryAccess.Dimension iregistrycustom_dimension = this.registries.getAccessForLoading(RegistryLayer.RELOADABLE); + CompletableFuture completablefuture = CompletableFuture.supplyAsync(() -> { +- Stream stream = collection.stream(); +- PackRepository packrepository = this.packRepository; ++ Stream stream = selectedIds.stream(); // CraftBukkit - decompile error ++ PackRepository resourcepackrepository = this.packRepository; + + Objects.requireNonNull(this.packRepository); +- return (ImmutableList) stream.map(packrepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()); ++ return stream.map(resourcepackrepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()); // CraftBukkit - decompile error + }, this).thenCompose((immutablelist) -> { +- MultiPackResourceManager multipackresourcemanager = new MultiPackResourceManager(PackType.SERVER_DATA, immutablelist); ++ MultiPackResourceManager resourcemanager = new MultiPackResourceManager(PackType.SERVER_DATA, immutablelist); + +- return ReloadableServerResources.loadResources(multipackresourcemanager, registryaccess_frozen, this.worldData.enabledFeatures(), this.isDedicatedServer() ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED, this.getFunctionCompilationLevel(), this.executor, this).whenComplete((reloadableserverresources, throwable) -> { ++ return ReloadableServerResources.loadResources(resourcemanager, iregistrycustom_dimension, this.worldData.enabledFeatures(), this.isDedicatedServer() ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED, this.getFunctionCompilationLevel(), this.executor, this).whenComplete((datapackresources, throwable) -> { + if (throwable != null) { +- multipackresourcemanager.close(); ++ resourcemanager.close(); + } + +- }).thenApply((reloadableserverresources) -> { +- return new MinecraftServer.ReloadableResources(multipackresourcemanager, reloadableserverresources); ++ }).thenApply((datapackresources) -> { ++ return new MinecraftServer.ReloadableResources(resourcemanager, datapackresources); + }); + }).thenAcceptAsync((minecraftserver_reloadableresources) -> { + this.resources.close(); + this.resources = minecraftserver_reloadableresources; +- this.packRepository.setSelected(collection); ++ this.server.syncCommands(); // SPIGOT-5884: Lost on reload ++ this.packRepository.setSelected(selectedIds); + WorldDataConfiguration worlddataconfiguration = new WorldDataConfiguration(getSelectedPacks(this.packRepository), this.worldData.enabledFeatures()); + + this.worldData.setDataConfiguration(worlddataconfiguration); +@@ -1517,46 +1838,46 @@ + return completablefuture; + } + +- public static WorldDataConfiguration configurePackRepository(PackRepository packrepository, DataPackConfig datapackconfig, boolean flag, FeatureFlagSet featureflagset) { +- packrepository.reload(); +- if (flag) { +- packrepository.setSelected(Collections.singleton("vanilla")); ++ public static WorldDataConfiguration configurePackRepository(PackRepository packRepository, DataPackConfig dataPackConfig, boolean safeMode, FeatureFlagSet enabledFeatures) { ++ packRepository.reload(); ++ if (safeMode) { ++ packRepository.setSelected(Collections.singleton("vanilla")); + return WorldDataConfiguration.DEFAULT; + } else { + Set set = Sets.newLinkedHashSet(); +- Iterator iterator = datapackconfig.getEnabled().iterator(); ++ Iterator iterator = dataPackConfig.getEnabled().iterator(); + + while (iterator.hasNext()) { + String s = (String) iterator.next(); + +- if (packrepository.isAvailable(s)) { ++ if (packRepository.isAvailable(s)) { + set.add(s); + } else { + MinecraftServer.LOGGER.warn("Missing data pack {}", s); + } + } + +- iterator = packrepository.getAvailablePacks().iterator(); ++ iterator = packRepository.getAvailablePacks().iterator(); + + while (iterator.hasNext()) { +- Pack pack = (Pack) iterator.next(); +- String s1 = pack.getId(); ++ Pack resourcepackloader = (Pack) iterator.next(); ++ String s1 = resourcepackloader.getId(); + +- if (!datapackconfig.getDisabled().contains(s1)) { +- FeatureFlagSet featureflagset1 = pack.getRequestedFeatures(); ++ if (!dataPackConfig.getDisabled().contains(s1)) { ++ FeatureFlagSet featureflagset1 = resourcepackloader.getRequestedFeatures(); + boolean flag1 = set.contains(s1); + +- if (!flag1 && pack.getPackSource().shouldAddAutomatically()) { +- if (featureflagset1.isSubsetOf(featureflagset)) { ++ if (!flag1 && resourcepackloader.getPackSource().shouldAddAutomatically()) { ++ if (featureflagset1.isSubsetOf(enabledFeatures)) { + MinecraftServer.LOGGER.info("Found new data pack {}, loading it automatically", s1); + set.add(s1); + } else { +- MinecraftServer.LOGGER.info("Found new data pack {}, but can't load it due to missing features {}", s1, FeatureFlags.printMissingFlags(featureflagset, featureflagset1)); ++ MinecraftServer.LOGGER.info("Found new data pack {}, but can't load it due to missing features {}", s1, FeatureFlags.printMissingFlags(enabledFeatures, featureflagset1)); + } + } + +- if (flag1 && !featureflagset1.isSubsetOf(featureflagset)) { +- MinecraftServer.LOGGER.warn("Pack {} requires features {} that are not enabled for this world, disabling pack.", s1, FeatureFlags.printMissingFlags(featureflagset, featureflagset1)); ++ if (flag1 && !featureflagset1.isSubsetOf(enabledFeatures)) { ++ MinecraftServer.LOGGER.warn("Pack {} requires features {} that are not enabled for this world, disabling pack.", s1, FeatureFlags.printMissingFlags(enabledFeatures, featureflagset1)); + set.remove(s1); + } + } +@@ -1567,36 +1888,36 @@ + set.add("vanilla"); + } + +- packrepository.setSelected(set); +- DataPackConfig datapackconfig1 = getSelectedPacks(packrepository); +- FeatureFlagSet featureflagset2 = packrepository.getRequestedFeatureFlags(); ++ packRepository.setSelected(set); ++ DataPackConfig datapackconfiguration1 = getSelectedPacks(packRepository); ++ FeatureFlagSet featureflagset2 = packRepository.getRequestedFeatureFlags(); + +- return new WorldDataConfiguration(datapackconfig1, featureflagset2); ++ return new WorldDataConfiguration(datapackconfiguration1, featureflagset2); + } + } + +- private static DataPackConfig getSelectedPacks(PackRepository packrepository) { +- Collection collection = packrepository.getSelectedIds(); ++ private static DataPackConfig getSelectedPacks(PackRepository packRepository) { ++ Collection collection = packRepository.getSelectedIds(); + List list = ImmutableList.copyOf(collection); +- List list1 = (List) packrepository.getAvailableIds().stream().filter((s) -> { ++ List list1 = (List) packRepository.getAvailableIds().stream().filter((s) -> { + return !collection.contains(s); + }).collect(ImmutableList.toImmutableList()); + + return new DataPackConfig(list, list1); + } + +- public void kickUnlistedPlayers(CommandSourceStack commandsourcestack) { ++ public void kickUnlistedPlayers(CommandSourceStack commandSource) { + if (this.isEnforceWhitelist()) { +- PlayerList playerlist = commandsourcestack.getServer().getPlayerList(); +- UserWhiteList userwhitelist = playerlist.getWhiteList(); ++ PlayerList playerlist = commandSource.getServer().getPlayerList(); ++ UserWhiteList whitelist = playerlist.getWhiteList(); + List list = Lists.newArrayList(playerlist.getPlayers()); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- if (!userwhitelist.isWhiteListed(serverplayer.getGameProfile())) { +- serverplayer.connection.disconnect(Component.translatable("multiplayer.disconnect.not_whitelisted")); ++ if (!whitelist.isWhiteListed(entityplayer.getGameProfile())) { ++ entityplayer.connection.disconnect(Component.translatable("multiplayer.disconnect.not_whitelisted")); + } + } + +@@ -1612,25 +1933,22 @@ + } + + public CommandSourceStack createCommandSourceStack() { +- ServerLevel serverlevel = this.overworld(); ++ ServerLevel worldserver = this.overworld(); + +- return new CommandSourceStack(this, serverlevel == null ? Vec3.ZERO : Vec3.atLowerCornerOf(serverlevel.getSharedSpawnPos()), Vec2.ZERO, serverlevel, 4, "Server", Component.literal("Server"), this, (Entity) null); ++ return new CommandSourceStack(this, worldserver == null ? Vec3.ZERO : Vec3.atLowerCornerOf(worldserver.getSharedSpawnPos()), Vec2.ZERO, worldserver, 4, "Server", Component.literal("Server"), this, (Entity) null); + } + + @Override +- @Override + public boolean acceptsSuccess() { + return true; + } + + @Override +- @Override + public boolean acceptsFailure() { + return true; + } + + @Override +- @Override + public abstract boolean shouldInformAdmins(); + + public RecipeManager getRecipeManager() { +@@ -1665,8 +1983,8 @@ + return this.enforceWhitelist; + } + +- public void setEnforceWhitelist(boolean flag) { +- this.enforceWhitelist = flag; ++ public void setEnforceWhitelist(boolean whitelistEnabled) { ++ this.enforceWhitelist = whitelistEnabled; + } + + public float getCurrentSmoothedTickTime() { +@@ -1685,11 +2003,11 @@ + return this.tickTimesNanos; + } + +- public int getProfilePermissions(GameProfile gameprofile) { +- if (this.getPlayerList().isOp(gameprofile)) { +- ServerOpListEntry serveroplistentry = (ServerOpListEntry) this.getPlayerList().getOps().get(gameprofile); ++ public int getProfilePermissions(GameProfile profile) { ++ if (this.getPlayerList().isOp(profile)) { ++ ServerOpListEntry oplistentry = (ServerOpListEntry) this.getPlayerList().getOps().get(profile); + +- return serveroplistentry != null ? serveroplistentry.getLevel() : (this.isSingleplayerOwner(gameprofile) ? 4 : (this.isSingleplayer() ? (this.getPlayerList().isAllowCheatsForAllPlayers() ? 4 : 0) : this.getOperatorUserPermissionLevel())); ++ return oplistentry != null ? oplistentry.getLevel() : (this.isSingleplayerOwner(profile) ? 4 : (this.isSingleplayer() ? (this.getPlayerList().isAllowCheatsForAllPlayers() ? 4 : 0) : this.getOperatorUserPermissionLevel())); + } else { + return 0; + } +@@ -1711,8 +2029,8 @@ + + while (iterator.hasNext()) { + Entry, ServerLevel> entry = (Entry) iterator.next(); +- ResourceLocation resourcelocation = ((ResourceKey) entry.getKey()).location(); +- Path path2 = path1.resolve(resourcelocation.getNamespace()).resolve(resourcelocation.getPath()); ++ ResourceLocation minecraftkey = ((ResourceKey) entry.getKey()).location(); ++ Path path2 = path1.resolve(minecraftkey.getNamespace()).resolve(minecraftkey.getPath()); + + Files.createDirectories(path2); + ((ServerLevel) entry.getValue()).saveDebugReport(path2); +@@ -1765,9 +2083,8 @@ + + GameRules.visitGameRuleTypes(new GameRules.GameRuleTypeVisitor() { + @Override +- @Override +- public > void visit(GameRules.Key gamerules_key, GameRules.Type gamerules_type) { +- list.add(String.format(Locale.ROOT, "%s=%s\n", gamerules_key.getId(), gamerules.getRule(gamerules_key))); ++ public > void visit(GameRules.Key key, GameRules.Type type) { ++ list.add(String.format(Locale.ROOT, "%s=%s\n", key.getId(), gamerules.getRule(key))); + } + }); + Iterator iterator = list.iterator(); +@@ -1870,7 +2187,7 @@ + try { + label51: + { +- ArrayList arraylist; ++ ArrayList arraylist; // CraftBukkit - decompile error + + try { + arraylist = Lists.newArrayList(NativeModuleLister.listModules()); +@@ -1879,8 +2196,8 @@ + break label51; + } + +- arraylist.sort(Comparator.comparing((nativemodulelister_nativemoduleinfo) -> { +- return nativemodulelister_nativemoduleinfo.name; ++ arraylist.sort(Comparator.comparing((nativemodulelister_a) -> { ++ return nativemodulelister_a.name; + })); + Iterator iterator = arraylist.iterator(); + +@@ -1889,9 +2206,9 @@ + break label50; + } + +- NativeModuleLister.NativeModuleInfo nativemodulelister_nativemoduleinfo = (NativeModuleLister.NativeModuleInfo) iterator.next(); ++ NativeModuleLister.NativeModuleInfo nativemodulelister_a = (NativeModuleLister.NativeModuleInfo) iterator.next(); + +- bufferedwriter.write(nativemodulelister_nativemoduleinfo.toString()); ++ bufferedwriter.write(nativemodulelister_a.toString()); + bufferedwriter.write(10); + } + } +@@ -1920,6 +2237,22 @@ + + } + ++ // CraftBukkit start ++ @Override ++ public boolean isSameThread() { ++ return super.isSameThread() || this.isStopped(); // CraftBukkit - MC-142590 ++ } ++ ++ public boolean isDebugging() { ++ return false; ++ } ++ ++ @Deprecated ++ public static MinecraftServer getServer() { ++ return (Bukkit.getServer() instanceof CraftServer) ? ((CraftServer) Bukkit.getServer()).getServer() : null; ++ } ++ // CraftBukkit end ++ + private void startMetricsRecordingTick() { + if (this.willStartRecordingMetrics) { + this.metricsRecorder = ActiveMetricsRecorder.createStarted(new ServerMetricsSamplersProvider(Util.timeSource, this.isDedicatedServer()), Util.timeSource, Util.ioPool(), new MetricsPersister("server"), this.onMetricsRecordingStopped, (path) -> { +@@ -1945,12 +2278,12 @@ + return this.metricsRecorder.isRecording(); + } + +- public void startRecordingMetrics(Consumer consumer, Consumer consumer1) { +- this.onMetricsRecordingStopped = (profileresults) -> { ++ public void startRecordingMetrics(Consumer output, Consumer onMetricsRecordingFinished) { ++ this.onMetricsRecordingStopped = (methodprofilerresults) -> { + this.stopRecordingMetrics(); +- consumer.accept(profileresults); ++ output.accept(methodprofilerresults); + }; +- this.onMetricsRecordingFinished = consumer1; ++ this.onMetricsRecordingFinished = onMetricsRecordingFinished; + this.willStartRecordingMetrics = true; + } + +@@ -1967,8 +2300,8 @@ + this.profiler = this.metricsRecorder.getProfiler(); + } + +- public Path getWorldPath(LevelResource levelresource) { +- return this.storageSource.getLevelPath(levelresource); ++ public Path getWorldPath(LevelResource levelResource) { ++ return this.storageSource.getLevelPath(levelResource); + } + + public boolean forceSynchronousWrites() { +@@ -1983,7 +2316,7 @@ + return this.worldData; + } + +- public RegistryAccess.Frozen registryAccess() { ++ public RegistryAccess.Dimension registryAccess() { + return this.registries.compositeAccess(); + } + +@@ -1991,12 +2324,12 @@ + return this.registries; + } + +- public TextFilter createTextFilterForPlayer(ServerPlayer serverplayer) { ++ public TextFilter createTextFilterForPlayer(ServerPlayer player) { + return TextFilter.DUMMY; + } + +- public ServerPlayerGameMode createGameModeForPlayer(ServerPlayer serverplayer) { +- return (ServerPlayerGameMode) (this.isDemo() ? new DemoMode(serverplayer) : new ServerPlayerGameMode(serverplayer)); ++ public ServerPlayerGameMode createGameModeForPlayer(ServerPlayer player) { ++ return (ServerPlayerGameMode) (this.isDemo() ? new DemoMode(player) : new ServerPlayerGameMode(player)); + } + + @Nullable +@@ -2024,10 +2357,10 @@ + if (this.debugCommandProfiler == null) { + return EmptyProfileResults.EMPTY; + } else { +- ProfileResults profileresults = this.debugCommandProfiler.stop(Util.getNanos(), this.tickCount); ++ ProfileResults methodprofilerresults = this.debugCommandProfiler.stop(Util.getNanos(), this.tickCount); + + this.debugCommandProfiler = null; +- return profileresults; ++ return methodprofilerresults; + } + } + +@@ -2035,17 +2368,22 @@ + return 1000000; + } + +- public void logChatMessage(Component component, ChatType.Bound chattype_bound, @Nullable String s) { +- String s1 = chattype_bound.decorate(component).getString(); ++ public void logChatMessage(Component content, ChatType.Bound boundChatType, @Nullable String header) { ++ String s1 = boundChatType.decorate(content).getString(); + +- if (s != null) { +- MinecraftServer.LOGGER.info("[{}] {}", s, s1); ++ if (header != null) { ++ MinecraftServer.LOGGER.info("[{}] {}", header, s1); + } else { + MinecraftServer.LOGGER.info("{}", s1); + } + + } + ++ // CraftBukkit start ++ public final java.util.concurrent.ExecutorService chatExecutor = java.util.concurrent.Executors.newCachedThreadPool( ++ new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon(true).setNameFormat("Async Chat Thread - #%d").build()); ++ // CraftBukkit end ++ + public ChatDecorator getChatDecorator() { + return ChatDecorator.PLAIN; + } +@@ -2054,9 +2392,8 @@ + return true; + } + +- private static record ReloadableResources(CloseableResourceManager resourceManager, ReloadableServerResources managers) implements AutoCloseable { ++ public static record ReloadableResources(IReloadableResourceManager resourceManager, ReloadableServerResources managers) implements AutoCloseable { + +- @Override + public void close() { + this.resourceManager.close(); + } +@@ -2067,51 +2404,44 @@ + final long startNanos; + final int startTick; + +- TimeProfiler(long i, int j) { +- this.startNanos = i; ++ TimeProfiler(long startNanos, int j) { ++ this.startNanos = startNanos; + this.startTick = j; + } + +- ProfileResults stop(final long i, final int j) { ++ ProfileResults stop(final long endTimeNano, final int j) { + return new ProfileResults() { + @Override +- @Override +- public List getTimes(String s) { ++ public List getTimes(String sectionPath) { + return Collections.emptyList(); + } + + @Override +- @Override + public boolean saveResults(Path path) { + return false; + } + + @Override +- @Override + public long getStartTimeNano() { + return TimeProfiler.this.startNanos; + } + + @Override +- @Override + public int getStartTimeTicks() { + return TimeProfiler.this.startTick; + } + + @Override +- @Override + public long getEndTimeNano() { +- return i; ++ return endTimeNano; + } + + @Override +- @Override + public int getEndTimeTicks() { + return j; + } + + @Override +- @Override + public String getProfilerResults() { + return ""; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/PlayerAdvancements.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/PlayerAdvancements.java.patch new file mode 100644 index 0000000000..c5f25216e9 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/PlayerAdvancements.java.patch @@ -0,0 +1,184 @@ +--- a/net/minecraft/server/PlayerAdvancements.java ++++ b/net/minecraft/server/PlayerAdvancements.java +@@ -62,21 +62,21 @@ + @Nullable + private AdvancementHolder lastSelectedTab; + private boolean isFirstPacket = true; +- private final Codec codec; ++ private final Codec codec; + +- public PlayerAdvancements(DataFixer datafixer, PlayerList playerlist, ServerAdvancementManager serveradvancementmanager, Path path, ServerPlayer serverplayer) { +- this.playerList = playerlist; +- this.playerSavePath = path; +- this.player = serverplayer; +- this.tree = serveradvancementmanager.tree(); ++ public PlayerAdvancements(DataFixer dataFixer, PlayerList playerList, ServerAdvancementManager manager, Path playerSavePath, ServerPlayer player) { ++ this.playerList = playerList; ++ this.playerSavePath = playerSavePath; ++ this.player = player; ++ this.tree = manager.tree(); + boolean flag = true; + +- this.codec = DataFixTypes.ADVANCEMENTS.wrapCodec(PlayerAdvancements.Data.CODEC, datafixer, 1343); +- this.load(serveradvancementmanager); ++ this.codec = DataFixTypes.ADVANCEMENTS.wrapCodec(PlayerAdvancements.a.CODEC, dataFixer, 1343); ++ this.load(manager); + } + +- public void setPlayer(ServerPlayer serverplayer) { +- this.player = serverplayer; ++ public void setPlayer(ServerPlayer player) { ++ this.player = player; + } + + public void stopListening() { +@@ -90,7 +90,7 @@ + + } + +- public void reload(ServerAdvancementManager serveradvancementmanager) { ++ public void reload(ServerAdvancementManager manager) { + this.stopListening(); + this.progress.clear(); + this.visible.clear(); +@@ -98,12 +98,12 @@ + this.progressChanged.clear(); + this.isFirstPacket = true; + this.lastSelectedTab = null; +- this.tree = serveradvancementmanager.tree(); +- this.load(serveradvancementmanager); ++ this.tree = manager.tree(); ++ this.load(manager); + } + +- private void registerListeners(ServerAdvancementManager serveradvancementmanager) { +- Iterator iterator = serveradvancementmanager.getAllAdvancements().iterator(); ++ private void registerListeners(ServerAdvancementManager manager) { ++ Iterator iterator = manager.getAllAdvancements().iterator(); + + while (iterator.hasNext()) { + AdvancementHolder advancementholder = (AdvancementHolder) iterator.next(); +@@ -113,8 +113,8 @@ + + } + +- private void checkForAutomaticTriggers(ServerAdvancementManager serveradvancementmanager) { +- Iterator iterator = serveradvancementmanager.getAllAdvancements().iterator(); ++ private void checkForAutomaticTriggers(ServerAdvancementManager manager) { ++ Iterator iterator = manager.getAllAdvancements().iterator(); + + while (iterator.hasNext()) { + AdvancementHolder advancementholder = (AdvancementHolder) iterator.next(); +@@ -128,7 +128,7 @@ + + } + +- private void load(ServerAdvancementManager serveradvancementmanager) { ++ private void load(ServerAdvancementManager manager) { + if (Files.isRegularFile(this.playerSavePath, new LinkOption[0])) { + try { + JsonReader jsonreader = new JsonReader(Files.newBufferedReader(this.playerSavePath, StandardCharsets.UTF_8)); +@@ -136,9 +136,9 @@ + try { + jsonreader.setLenient(false); + JsonElement jsonelement = Streams.parse(jsonreader); +- PlayerAdvancements.Data playeradvancements_data = (PlayerAdvancements.Data) Util.getOrThrow(this.codec.parse(JsonOps.INSTANCE, jsonelement), JsonParseException::new); ++ PlayerAdvancements.a advancementdataplayer_a = (PlayerAdvancements.a) Util.getOrThrow(this.codec.parse(JsonOps.INSTANCE, jsonelement), JsonParseException::new); + +- this.applyFrom(serveradvancementmanager, playeradvancements_data); ++ this.applyFrom(manager, advancementdataplayer_a); + } catch (Throwable throwable) { + try { + jsonreader.close(); +@@ -157,8 +157,8 @@ + } + } + +- this.checkForAutomaticTriggers(serveradvancementmanager); +- this.registerListeners(serveradvancementmanager); ++ this.checkForAutomaticTriggers(manager); ++ this.registerListeners(manager); + } + + public void save() { +@@ -191,12 +191,13 @@ + + } + +- private void applyFrom(ServerAdvancementManager serveradvancementmanager, PlayerAdvancements.Data playeradvancements_data) { +- playeradvancements_data.forEach((resourcelocation, advancementprogress) -> { +- AdvancementHolder advancementholder = serveradvancementmanager.get(resourcelocation); ++ private void applyFrom(ServerAdvancementManager advancementdataworld, PlayerAdvancements.a advancementdataplayer_a) { ++ advancementdataplayer_a.forEach((minecraftkey, advancementprogress) -> { ++ AdvancementHolder advancementholder = advancementdataworld.get(minecraftkey); + + if (advancementholder == null) { +- PlayerAdvancements.LOGGER.warn("Ignored advancement '{}' in progress file {} - it doesn't exist anymore?", resourcelocation, this.playerSavePath); ++ if (!minecraftkey.getNamespace().equals("minecraft")) return; // CraftBukkit ++ PlayerAdvancements.LOGGER.warn("Ignored advancement '{}' in progress file {} - it doesn't exist anymore?", minecraftkey, this.playerSavePath); + } else { + this.startProgress(advancementholder, advancementprogress); + this.progressChanged.add(advancementholder); +@@ -205,7 +206,7 @@ + }); + } + +- private PlayerAdvancements.Data asData() { ++ private PlayerAdvancements.a asData() { + Map map = new LinkedHashMap(); + + this.progress.forEach((advancementholder, advancementprogress) -> { +@@ -214,7 +215,7 @@ + } + + }); +- return new PlayerAdvancements.Data(map); ++ return new PlayerAdvancements.a(map); + } + + public boolean award(AdvancementHolder advancementholder, String s) { +@@ -227,10 +228,11 @@ + this.progressChanged.add(advancementholder); + flag = true; + if (!flag1 && advancementprogress.isDone()) { ++ this.player.level().getCraftServer().getPluginManager().callEvent(new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancementholder.toBukkit())); // CraftBukkit + advancementholder.value().rewards().grant(this.player); +- advancementholder.value().display().ifPresent((displayinfo) -> { +- if (displayinfo.shouldAnnounceChat() && this.player.level().getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { +- this.playerList.broadcastSystemMessage(displayinfo.getType().createAnnouncement(advancementholder, this.player), false); ++ advancementholder.value().display().ifPresent((advancementdisplay) -> { ++ if (advancementdisplay.shouldAnnounceChat() && this.player.level().getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { ++ this.playerList.broadcastSystemMessage(advancementdisplay.getType().createAnnouncement(advancementholder, this.player), false); + } + + }); +@@ -312,7 +314,7 @@ + criterion.trigger().removePlayerListener(this, new CriterionTrigger.Listener<>(criterion.triggerInstance(), advancementholder, s)); + } + +- public void flushDirty(ServerPlayer serverplayer) { ++ public void flushDirty(ServerPlayer serverPlayer) { + if (this.isFirstPacket || !this.rootsToUpdate.isEmpty() || !this.progressChanged.isEmpty()) { + Map map = new HashMap(); + Set set = new HashSet(); +@@ -338,7 +340,7 @@ + + this.progressChanged.clear(); + if (!map.isEmpty() || !set.isEmpty() || !set1.isEmpty()) { +- serverplayer.connection.send(new ClientboundUpdateAdvancementsPacket(this.isFirstPacket, set, set1, map)); ++ serverPlayer.connection.send(new ClientboundUpdateAdvancementsPacket(this.isFirstPacket, set, set1, map)); + } + } + +@@ -396,9 +398,9 @@ + }); + } + +- private static record Data(Map map) { ++ private static record a(Map map) { + +- public static final Codec CODEC = Codec.unboundedMap(ResourceLocation.CODEC, AdvancementProgress.CODEC).xmap(PlayerAdvancements.Data::new, PlayerAdvancements.Data::map); ++ public static final Codec CODEC = Codec.unboundedMap(ResourceLocation.CODEC, AdvancementProgress.CODEC).xmap(PlayerAdvancements.a::new, PlayerAdvancements.a::map); + + public void forEach(BiConsumer biconsumer) { + this.map.entrySet().stream().sorted(Entry.comparingByValue()).forEach((entry) -> { diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/ServerAdvancementManager.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/ServerAdvancementManager.java.patch new file mode 100644 index 0000000000..0110285a8d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/ServerAdvancementManager.java.patch @@ -0,0 +1,79 @@ +--- a/net/minecraft/server/ServerAdvancementManager.java ++++ b/net/minecraft/server/ServerAdvancementManager.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.server; + + import com.google.common.collect.ImmutableMap; +@@ -31,28 +32,27 @@ + public class ServerAdvancementManager extends SimpleJsonResourceReloadListener { + + private static final Logger LOGGER = LogUtils.getLogger(); +- private static final Gson GSON = (new GsonBuilder()).create(); +- private Map advancements = Map.of(); ++ public static final Gson GSON = (new GsonBuilder()).create(); ++ public Map advancements = Map.of(); + private AdvancementTree tree = new AdvancementTree(); + private final LootDataManager lootData; + +- public ServerAdvancementManager(LootDataManager lootdatamanager) { ++ public ServerAdvancementManager(LootDataManager lootData) { + super(ServerAdvancementManager.GSON, "advancements"); +- this.lootData = lootdatamanager; ++ this.lootData = lootData; + } + +- @Override +- protected void apply(Map map, ResourceManager resourcemanager, ProfilerFiller profilerfiller) { ++ protected void apply(Map object, ResourceManager resourceManager, ProfilerFiller profiler) { + Builder builder = ImmutableMap.builder(); + +- map.forEach((resourcelocation, jsonelement) -> { ++ object.forEach((minecraftkey, jsonelement) -> { + try { + Advancement advancement = (Advancement) Util.getOrThrow(Advancement.CODEC.parse(JsonOps.INSTANCE, jsonelement), JsonParseException::new); + +- this.validate(resourcelocation, advancement); +- builder.put(resourcelocation, new AdvancementHolder(resourcelocation, advancement)); ++ this.validate(minecraftkey, advancement); ++ builder.put(minecraftkey, new AdvancementHolder(minecraftkey, advancement)); + } catch (Exception exception) { +- ServerAdvancementManager.LOGGER.error("Parsing error loading custom advancement {}: {}", resourcelocation, exception.getMessage()); ++ ServerAdvancementManager.LOGGER.error("Parsing error loading custom advancement {}: {}", minecraftkey, exception.getMessage()); + } + + }); +@@ -73,11 +73,11 @@ + this.tree = advancementtree; + } + +- private void validate(ResourceLocation resourcelocation, Advancement advancement) { +- ProblemReporter.Collector problemreporter_collector = new ProblemReporter.Collector(); ++ private void validate(ResourceLocation minecraftkey, Advancement advancement) { ++ ProblemReporter.a problemreporter_a = new ProblemReporter.a(); + +- advancement.validate(problemreporter_collector, this.lootData); +- Multimap multimap = problemreporter_collector.get(); ++ advancement.validate(problemreporter_a, this.lootData); ++ Multimap multimap = problemreporter_a.get(); + + if (!multimap.isEmpty()) { + String s = (String) multimap.asMap().entrySet().stream().map((entry) -> { +@@ -86,14 +86,14 @@ + return " at " + s1 + ": " + String.join("; ", (Iterable) entry.getValue()); + }).collect(Collectors.joining("\n")); + +- ServerAdvancementManager.LOGGER.warn("Found validation problems in advancement {}: \n{}", resourcelocation, s); ++ ServerAdvancementManager.LOGGER.warn("Found validation problems in advancement {}: \n{}", minecraftkey, s); + } + + } + + @Nullable +- public AdvancementHolder get(ResourceLocation resourcelocation) { +- return (AdvancementHolder) this.advancements.get(resourcelocation); ++ public AdvancementHolder get(ResourceLocation minecraftkey) { ++ return (AdvancementHolder) this.advancements.get(minecraftkey); + } + + public AdvancementTree tree() { diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/ServerFunctionManager.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/ServerFunctionManager.java.patch new file mode 100644 index 0000000000..bddeddbcd8 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/ServerFunctionManager.java.patch @@ -0,0 +1,114 @@ +--- a/net/minecraft/server/ServerFunctionManager.java ++++ b/net/minecraft/server/ServerFunctionManager.java +@@ -10,7 +10,6 @@ + import java.util.Optional; + import net.minecraft.commands.CommandResultCallback; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.FunctionInstantiationException; + import net.minecraft.commands.execution.ExecutionContext; + import net.minecraft.commands.functions.CommandFunction; +@@ -30,14 +29,14 @@ + private boolean postReload; + private ServerFunctionLibrary library; + +- public ServerFunctionManager(MinecraftServer minecraftserver, ServerFunctionLibrary serverfunctionlibrary) { +- this.server = minecraftserver; +- this.library = serverfunctionlibrary; +- this.postReload(serverfunctionlibrary); ++ public ServerFunctionManager(MinecraftServer server, ServerFunctionLibrary library) { ++ this.server = server; ++ this.library = library; ++ this.postReload(library); + } + + public CommandDispatcher getDispatcher() { +- return this.server.getCommands().getDispatcher(); ++ return this.server.vanillaCommandDispatcher.getDispatcher(); // CraftBukkit + } + + public void tick() { +@@ -53,12 +52,12 @@ + } + } + +- private void executeTagFunctions(Collection> collection, ResourceLocation resourcelocation) { +- ProfilerFiller profilerfiller = this.server.getProfiler(); ++ private void executeTagFunctions(Collection> functionObjects, ResourceLocation identifier) { ++ ProfilerFiller gameprofilerfiller = this.server.getProfiler(); + +- Objects.requireNonNull(resourcelocation); +- profilerfiller.push(resourcelocation::toString); +- Iterator iterator = collection.iterator(); ++ Objects.requireNonNull(identifier); ++ gameprofilerfiller.push(identifier::toString); ++ Iterator iterator = functionObjects.iterator(); + + while (iterator.hasNext()) { + CommandFunction commandfunction = (CommandFunction) iterator.next(); +@@ -69,36 +68,36 @@ + this.server.getProfiler().pop(); + } + +- public void execute(CommandFunction commandfunction, CommandSourceStack commandsourcestack) { +- ProfilerFiller profilerfiller = this.server.getProfiler(); ++ public void execute(CommandFunction commandfunction, CommandSourceStack commandlistenerwrapper) { ++ ProfilerFiller gameprofilerfiller = this.server.getProfiler(); + +- profilerfiller.push(() -> { ++ gameprofilerfiller.push(() -> { + return "function " + commandfunction.id(); + }); + + try { +- InstantiatedFunction instantiatedfunction = commandfunction.instantiate((CompoundTag) null, this.getDispatcher(), commandsourcestack); ++ InstantiatedFunction instantiatedfunction = commandfunction.instantiate((CompoundTag) null, this.getDispatcher(), commandlistenerwrapper); + +- Commands.executeCommandInContext(commandsourcestack, (executioncontext) -> { +- ExecutionContext.queueInitialFunctionCall(executioncontext, instantiatedfunction, commandsourcestack, CommandResultCallback.EMPTY); ++ net.minecraft.commands.Commands.executeCommandInContext(commandlistenerwrapper, (executioncontext) -> { ++ ExecutionContext.queueInitialFunctionCall(executioncontext, instantiatedfunction, commandlistenerwrapper, CommandResultCallback.EMPTY); + }); + } catch (FunctionInstantiationException functioninstantiationexception) { + ; + } catch (Exception exception) { + ServerFunctionManager.LOGGER.warn("Failed to execute function {}", commandfunction.id(), exception); + } finally { +- profilerfiller.pop(); ++ gameprofilerfiller.pop(); + } + + } + +- public void replaceLibrary(ServerFunctionLibrary serverfunctionlibrary) { +- this.library = serverfunctionlibrary; +- this.postReload(serverfunctionlibrary); ++ public void replaceLibrary(ServerFunctionLibrary reloader) { ++ this.library = reloader; ++ this.postReload(reloader); + } + +- private void postReload(ServerFunctionLibrary serverfunctionlibrary) { +- this.ticking = ImmutableList.copyOf(serverfunctionlibrary.getTag(ServerFunctionManager.TICK_FUNCTION_TAG)); ++ private void postReload(ServerFunctionLibrary reloader) { ++ this.ticking = ImmutableList.copyOf(reloader.getTag(ServerFunctionManager.TICK_FUNCTION_TAG)); + this.postReload = true; + } + +@@ -106,12 +105,12 @@ + return this.server.createCommandSourceStack().withPermission(2).withSuppressedOutput(); + } + +- public Optional> get(ResourceLocation resourcelocation) { +- return this.library.getFunction(resourcelocation); ++ public Optional> get(ResourceLocation functionIdentifier) { ++ return this.library.getFunction(functionIdentifier); + } + +- public Collection> getTag(ResourceLocation resourcelocation) { +- return this.library.getTag(resourcelocation); ++ public Collection> getTag(ResourceLocation functionTagIdentifier) { ++ return this.library.getTag(functionTagIdentifier); + } + + public Iterable getFunctionNames() { diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/ServerScoreboard.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/ServerScoreboard.java.patch new file mode 100644 index 0000000000..a45a693ffe --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/ServerScoreboard.java.patch @@ -0,0 +1,262 @@ +--- a/net/minecraft/server/ServerScoreboard.java ++++ b/net/minecraft/server/ServerScoreboard.java +@@ -32,66 +32,61 @@ + private final Set trackedObjectives = Sets.newHashSet(); + private final List dirtyListeners = Lists.newArrayList(); + +- public ServerScoreboard(MinecraftServer minecraftserver) { +- this.server = minecraftserver; ++ public ServerScoreboard(MinecraftServer server) { ++ this.server = server; + } + + @Override +- @Override +- protected void onScoreChanged(ScoreHolder scoreholder, Objective objective, Score score) { +- super.onScoreChanged(scoreholder, objective, score); +- if (this.trackedObjectives.contains(objective)) { +- this.server.getPlayerList().broadcastAll(new ClientboundSetScorePacket(scoreholder.getScoreboardName(), objective.getName(), score.value(), score.display(), score.numberFormat())); ++ protected void onScoreChanged(ScoreHolder scoreholder, Objective scoreboardobjective, Score scoreboardscore) { ++ super.onScoreChanged(scoreholder, scoreboardobjective, scoreboardscore); ++ if (this.trackedObjectives.contains(scoreboardobjective)) { ++ this.broadcastAll(new ClientboundSetScorePacket(scoreholder.getScoreboardName(), scoreboardobjective.getName(), scoreboardscore.value(), scoreboardscore.display(), scoreboardscore.numberFormat())); // CraftBukkit + } + + this.setDirty(); + } + + @Override +- @Override +- protected void onScoreLockChanged(ScoreHolder scoreholder, Objective objective) { +- super.onScoreLockChanged(scoreholder, objective); ++ protected void onScoreLockChanged(ScoreHolder scoreholder, Objective scoreboardobjective) { ++ super.onScoreLockChanged(scoreholder, scoreboardobjective); + this.setDirty(); + } + + @Override +- @Override + public void onPlayerRemoved(ScoreHolder scoreholder) { + super.onPlayerRemoved(scoreholder); +- this.server.getPlayerList().broadcastAll(new ClientboundResetScorePacket(scoreholder.getScoreboardName(), (String) null)); ++ this.broadcastAll(new ClientboundResetScorePacket(scoreholder.getScoreboardName(), (String) null)); // CraftBukkit + this.setDirty(); + } + + @Override +- @Override +- public void onPlayerScoreRemoved(ScoreHolder scoreholder, Objective objective) { +- super.onPlayerScoreRemoved(scoreholder, objective); +- if (this.trackedObjectives.contains(objective)) { +- this.server.getPlayerList().broadcastAll(new ClientboundResetScorePacket(scoreholder.getScoreboardName(), objective.getName())); ++ public void onPlayerScoreRemoved(ScoreHolder scoreholder, Objective scoreboardobjective) { ++ super.onPlayerScoreRemoved(scoreholder, scoreboardobjective); ++ if (this.trackedObjectives.contains(scoreboardobjective)) { ++ this.broadcastAll(new ClientboundResetScorePacket(scoreholder.getScoreboardName(), scoreboardobjective.getName())); // CraftBukkit + } + + this.setDirty(); + } + + @Override +- @Override +- public void setDisplayObjective(DisplaySlot displayslot, @Nullable Objective objective) { +- Objective objective1 = this.getDisplayObjective(displayslot); ++ public void setDisplayObjective(DisplaySlot displayslot, @Nullable Objective scoreboardobjective) { ++ Objective scoreboardobjective1 = this.getDisplayObjective(displayslot); + +- super.setDisplayObjective(displayslot, objective); +- if (objective1 != objective && objective1 != null) { +- if (this.getObjectiveDisplaySlotCount(objective1) > 0) { +- this.server.getPlayerList().broadcastAll(new ClientboundSetDisplayObjectivePacket(displayslot, objective)); ++ super.setDisplayObjective(displayslot, scoreboardobjective); ++ if (scoreboardobjective1 != scoreboardobjective && scoreboardobjective1 != null) { ++ if (this.getObjectiveDisplaySlotCount(scoreboardobjective1) > 0) { ++ this.broadcastAll(new ClientboundSetDisplayObjectivePacket(displayslot, scoreboardobjective)); // CraftBukkit + } else { +- this.stopTrackingObjective(objective1); ++ this.stopTrackingObjective(scoreboardobjective1); + } + } + +- if (objective != null) { +- if (this.trackedObjectives.contains(objective)) { +- this.server.getPlayerList().broadcastAll(new ClientboundSetDisplayObjectivePacket(displayslot, objective)); ++ if (scoreboardobjective != null) { ++ if (this.trackedObjectives.contains(scoreboardobjective)) { ++ this.broadcastAll(new ClientboundSetDisplayObjectivePacket(displayslot, scoreboardobjective)); // CraftBukkit + } else { +- this.startTrackingObjective(objective); ++ this.startTrackingObjective(scoreboardobjective); + } + } + +@@ -99,10 +94,9 @@ + } + + @Override +- @Override +- public boolean addPlayerToTeam(String s, PlayerTeam playerteam) { +- if (super.addPlayerToTeam(s, playerteam)) { +- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(playerteam, s, ClientboundSetPlayerTeamPacket.Action.ADD)); ++ public boolean addPlayerToTeam(String playerName, PlayerTeam team) { ++ if (super.addPlayerToTeam(playerName, team)) { ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(team, playerName, ClientboundSetPlayerTeamPacket.a.ADD)); // CraftBukkit + this.setDirty(); + return true; + } else { +@@ -111,33 +105,29 @@ + } + + @Override +- @Override +- public void removePlayerFromTeam(String s, PlayerTeam playerteam) { +- super.removePlayerFromTeam(s, playerteam); +- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(playerteam, s, ClientboundSetPlayerTeamPacket.Action.REMOVE)); ++ public void removePlayerFromTeam(String username, PlayerTeam playerTeam) { ++ super.removePlayerFromTeam(username, playerTeam); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(playerTeam, username, ClientboundSetPlayerTeamPacket.a.REMOVE)); // CraftBukkit + this.setDirty(); + } + + @Override +- @Override + public void onObjectiveAdded(Objective objective) { + super.onObjectiveAdded(objective); + this.setDirty(); + } + + @Override +- @Override + public void onObjectiveChanged(Objective objective) { + super.onObjectiveChanged(objective); + if (this.trackedObjectives.contains(objective)) { +- this.server.getPlayerList().broadcastAll(new ClientboundSetObjectivePacket(objective, 2)); ++ this.broadcastAll(new ClientboundSetObjectivePacket(objective, 2)); // CraftBukkit + } + + this.setDirty(); + } + + @Override +- @Override + public void onObjectiveRemoved(Objective objective) { + super.onObjectiveRemoved(objective); + if (this.trackedObjectives.contains(objective)) { +@@ -148,26 +138,23 @@ + } + + @Override +- @Override +- public void onTeamAdded(PlayerTeam playerteam) { +- super.onTeamAdded(playerteam); +- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerteam, true)); ++ public void onTeamAdded(PlayerTeam playerTeam) { ++ super.onTeamAdded(playerTeam); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, true)); // CraftBukkit + this.setDirty(); + } + + @Override +- @Override +- public void onTeamChanged(PlayerTeam playerteam) { +- super.onTeamChanged(playerteam); +- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerteam, false)); ++ public void onTeamChanged(PlayerTeam playerTeam) { ++ super.onTeamChanged(playerTeam); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, false)); // CraftBukkit + this.setDirty(); + } + + @Override +- @Override +- public void onTeamRemoved(PlayerTeam playerteam) { +- super.onTeamRemoved(playerteam); +- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createRemovePacket(playerteam)); ++ public void onTeamRemoved(PlayerTeam playerTeam) { ++ super.onTeamRemoved(playerTeam); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createRemovePacket(playerTeam)); // CraftBukkit + this.setDirty(); + } + +@@ -217,13 +204,14 @@ + Iterator iterator = this.server.getPlayerList().getPlayers().iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board + Iterator iterator1 = list.iterator(); + + while (iterator1.hasNext()) { + Packet packet = (Packet) iterator1.next(); + +- serverplayer.connection.send(packet); ++ entityplayer.connection.send(packet); + } + } + +@@ -253,13 +241,14 @@ + Iterator iterator = this.server.getPlayerList().getPlayers().iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board + Iterator iterator1 = list.iterator(); + + while (iterator1.hasNext()) { + Packet packet = (Packet) iterator1.next(); + +- serverplayer.connection.send(packet); ++ entityplayer.connection.send(packet); + } + } + +@@ -282,26 +271,36 @@ + return i; + } + +- public SavedData.Factory dataFactory() { +- return new SavedData.Factory<>(this::createData, this::createData, DataFixTypes.SAVED_DATA_SCOREBOARD); ++ public SavedData.a dataFactory() { ++ return new SavedData.a<>(this::createData, this::createData, DataFixTypes.SAVED_DATA_SCOREBOARD); + } + + private ScoreboardSaveData createData() { +- ScoreboardSaveData scoreboardsavedata = new ScoreboardSaveData(this); ++ ScoreboardSaveData persistentscoreboard = new ScoreboardSaveData(this); + +- Objects.requireNonNull(scoreboardsavedata); +- this.addDirtyListener(scoreboardsavedata::setDirty); +- return scoreboardsavedata; ++ Objects.requireNonNull(persistentscoreboard); ++ this.addDirtyListener(persistentscoreboard::setDirty); ++ return persistentscoreboard; + } + +- private ScoreboardSaveData createData(CompoundTag compoundtag) { +- return this.createData().load(compoundtag); ++ private ScoreboardSaveData createData(CompoundTag tag) { ++ return this.createData().load(tag); + } + +- public static enum Method { ++ // CraftBukkit start - Send to players ++ private void broadcastAll(Packet packet) { ++ for (ServerPlayer entityplayer : (List) this.server.getPlayerList().players) { ++ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() == this) { ++ entityplayer.connection.send(packet); ++ } ++ } ++ } ++ // CraftBukkit end + ++ public static enum Action { ++ + CHANGE, REMOVE; + +- private Method() {} ++ private Action() {} + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/ServerTickRateManager.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/ServerTickRateManager.java.patch new file mode 100644 index 0000000000..fbc3470f36 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/ServerTickRateManager.java.patch @@ -0,0 +1,80 @@ +--- a/net/minecraft/server/ServerTickRateManager.java ++++ b/net/minecraft/server/ServerTickRateManager.java +@@ -25,7 +25,6 @@ + } + + @Override +- @Override + public void setFrozen(boolean flag) { + super.setFrozen(flag); + this.updateStateToClients(); +@@ -60,8 +59,14 @@ + } + + public boolean stopSprinting() { ++ // CraftBukkit start, add sendLog parameter ++ return stopSprinting(true); ++ } ++ ++ public boolean stopSprinting(boolean sendLog) { ++ // CraftBukkit end + if (this.remainingSprintTicks > 0L) { +- this.finishTickSprint(); ++ this.finishTickSprint(sendLog); // CraftBukkit - add sendLog parameter + return true; + } else { + return false; +@@ -79,7 +84,7 @@ + return flag; + } + +- private void finishTickSprint() { ++ private void finishTickSprint(boolean sendLog) { // CraftBukkit - add sendLog parameter + long i = this.scheduledCurrentSprintTicks - this.remainingSprintTicks; + double d0 = Math.max(1.0D, (double) this.sprintTimeSpend) / (double) TimeUtil.NANOSECONDS_PER_MILLISECOND; + int j = (int) ((double) (TimeUtil.MILLISECONDS_PER_SECOND * i) / d0); +@@ -87,9 +92,13 @@ + + this.scheduledCurrentSprintTicks = 0L; + this.sprintTimeSpend = 0L; +- this.server.createCommandSourceStack().sendSuccess(() -> { +- return Component.translatable("commands.tick.sprint.report", j, s); +- }, true); ++ // CraftBukkit start - add sendLog parameter ++ if (sendLog) { ++ this.server.createCommandSourceStack().sendSuccess(() -> { ++ return Component.translatable("commands.tick.sprint.report", j, s); ++ }, true); ++ } ++ // CraftBukkit end + this.remainingSprintTicks = 0L; + this.setFrozen(this.previousIsFrozen); + this.server.onTickRateChanged(); +@@ -103,7 +112,7 @@ + --this.remainingSprintTicks; + return true; + } else { +- this.finishTickSprint(); ++ this.finishTickSprint(true); // CraftBukkit - add sendLog parameter + return false; + } + } +@@ -113,15 +122,14 @@ + } + + @Override +- @Override + public void setTickRate(float f) { + super.setTickRate(f); + this.server.onTickRateChanged(); + this.updateStateToClients(); + } + +- public void updateJoiningPlayer(ServerPlayer serverplayer) { +- serverplayer.connection.send(ClientboundTickingStatePacket.from(this)); +- serverplayer.connection.send(ClientboundTickingStepPacket.from(this)); ++ public void updateJoiningPlayer(ServerPlayer entityplayer) { ++ entityplayer.connection.send(ClientboundTickingStatePacket.from(this)); ++ entityplayer.connection.send(ClientboundTickingStepPacket.from(this)); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/bossevents/CustomBossEvent.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/bossevents/CustomBossEvent.java.patch new file mode 100644 index 0000000000..5b80bb621b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/bossevents/CustomBossEvent.java.patch @@ -0,0 +1,278 @@ +--- a/net/minecraft/server/bossevents/CustomBossEvent.java ++++ b/net/minecraft/server/bossevents/CustomBossEvent.java +@@ -17,6 +17,10 @@ + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.Mth; + import net.minecraft.world.BossEvent; ++// CraftBukkit start ++import org.bukkit.boss.KeyedBossBar; ++import org.bukkit.craftbukkit.boss.CraftKeyedBossbar; ++// CraftBukkit end + + public class CustomBossEvent extends ServerBossEvent { + +@@ -24,10 +28,20 @@ + private final Set players = Sets.newHashSet(); + private int value; + private int max = 100; ++ // CraftBukkit start ++ private KeyedBossBar bossBar; + +- public CustomBossEvent(ResourceLocation resourcelocation, Component component) { +- super(component, BossEvent.BossBarColor.WHITE, BossEvent.BossBarOverlay.PROGRESS); +- this.id = resourcelocation; ++ public KeyedBossBar getBukkitEntity() { ++ if (bossBar == null) { ++ bossBar = new CraftKeyedBossbar(this); ++ } ++ return bossBar; ++ } ++ // CraftBukkit end ++ ++ public CustomBossEvent(ResourceLocation id, Component name) { ++ super(name, BossEvent.BossBarColor.WHITE, BossEvent.BossBarOverlay.PROGRESS); ++ this.id = id; + this.setProgress(0.0F); + } + +@@ -36,25 +50,22 @@ + } + + @Override +- @Override +- public void addPlayer(ServerPlayer serverplayer) { +- super.addPlayer(serverplayer); +- this.players.add(serverplayer.getUUID()); ++ public void addPlayer(ServerPlayer player) { ++ super.addPlayer(player); ++ this.players.add(player.getUUID()); + } + +- public void addOfflinePlayer(UUID uuid) { +- this.players.add(uuid); ++ public void addOfflinePlayer(UUID player) { ++ this.players.add(player); + } + + @Override +- @Override +- public void removePlayer(ServerPlayer serverplayer) { +- super.removePlayer(serverplayer); +- this.players.remove(serverplayer.getUUID()); ++ public void removePlayer(ServerPlayer player) { ++ super.removePlayer(player); ++ this.players.remove(player.getUUID()); + } + + @Override +- @Override + public void removeAllPlayers() { + super.removeAllPlayers(); + this.players.clear(); +@@ -68,23 +79,23 @@ + return this.max; + } + +- public void setValue(int i) { +- this.value = i; +- this.setProgress(Mth.clamp((float) i / (float) this.max, 0.0F, 1.0F)); ++ public void setValue(int value) { ++ this.value = value; ++ this.setProgress(Mth.clamp((float) value / (float) this.max, 0.0F, 1.0F)); + } + +- public void setMax(int i) { +- this.max = i; +- this.setProgress(Mth.clamp((float) this.value / (float) i, 0.0F, 1.0F)); ++ public void setMax(int max) { ++ this.max = max; ++ this.setProgress(Mth.clamp((float) this.value / (float) max, 0.0F, 1.0F)); + } + + public final Component getDisplayName() { +- return ComponentUtils.wrapInSquareBrackets(this.getName()).withStyle((style) -> { +- return style.withColor(this.getColor().getFormatting()).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.literal(this.getTextId().toString()))).withInsertion(this.getTextId().toString()); ++ return ComponentUtils.wrapInSquareBrackets(this.getName()).withStyle((chatmodifier) -> { ++ return chatmodifier.withColor(this.getColor().getFormatting()).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.literal(this.getTextId().toString()))).withInsertion(this.getTextId().toString()); + }); + } + +- public boolean setPlayers(Collection collection) { ++ public boolean setPlayers(Collection serverPlayerList) { + Set set = Sets.newHashSet(); + Set set1 = Sets.newHashSet(); + Iterator iterator = this.players.iterator(); +@@ -96,13 +107,13 @@ + while (iterator.hasNext()) { + uuid = (UUID) iterator.next(); + flag = false; +- iterator1 = collection.iterator(); ++ iterator1 = serverPlayerList.iterator(); + + while (true) { + if (iterator1.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator1.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator1.next(); + +- if (!serverplayer.getUUID().equals(uuid)) { ++ if (!entityplayer.getUUID().equals(uuid)) { + continue; + } + +@@ -116,12 +127,12 @@ + } + } + +- iterator = collection.iterator(); ++ iterator = serverPlayerList.iterator(); + +- ServerPlayer serverplayer1; ++ ServerPlayer entityplayer1; + + while (iterator.hasNext()) { +- serverplayer1 = (ServerPlayer) iterator.next(); ++ entityplayer1 = (ServerPlayer) iterator.next(); + flag = false; + iterator1 = this.players.iterator(); + +@@ -129,7 +140,7 @@ + if (iterator1.hasNext()) { + UUID uuid1 = (UUID) iterator1.next(); + +- if (!serverplayer1.getUUID().equals(uuid1)) { ++ if (!entityplayer1.getUUID().equals(uuid1)) { + continue; + } + +@@ -137,7 +148,7 @@ + } + + if (!flag) { +- set1.add(serverplayer1); ++ set1.add(entityplayer1); + } + break; + } +@@ -151,13 +162,13 @@ + + while (true) { + if (iterator2.hasNext()) { +- ServerPlayer serverplayer2 = (ServerPlayer) iterator2.next(); ++ ServerPlayer entityplayer2 = (ServerPlayer) iterator2.next(); + +- if (!serverplayer2.getUUID().equals(uuid)) { ++ if (!entityplayer2.getUUID().equals(uuid)) { + continue; + } + +- this.removePlayer(serverplayer2); ++ this.removePlayer(entityplayer2); + } + + this.players.remove(uuid); +@@ -168,69 +179,69 @@ + iterator = set1.iterator(); + + while (iterator.hasNext()) { +- serverplayer1 = (ServerPlayer) iterator.next(); +- this.addPlayer(serverplayer1); ++ entityplayer1 = (ServerPlayer) iterator.next(); ++ this.addPlayer(entityplayer1); + } + + return !set.isEmpty() || !set1.isEmpty(); + } + + public CompoundTag save() { +- CompoundTag compoundtag = new CompoundTag(); ++ CompoundTag nbttagcompound = new CompoundTag(); + +- compoundtag.putString("Name", Component.Serializer.toJson(this.name)); +- compoundtag.putBoolean("Visible", this.isVisible()); +- compoundtag.putInt("Value", this.value); +- compoundtag.putInt("Max", this.max); +- compoundtag.putString("Color", this.getColor().getName()); +- compoundtag.putString("Overlay", this.getOverlay().getName()); +- compoundtag.putBoolean("DarkenScreen", this.shouldDarkenScreen()); +- compoundtag.putBoolean("PlayBossMusic", this.shouldPlayBossMusic()); +- compoundtag.putBoolean("CreateWorldFog", this.shouldCreateWorldFog()); +- ListTag listtag = new ListTag(); ++ nbttagcompound.putString("Name", Component.Serializer.toJson(this.name)); ++ nbttagcompound.putBoolean("Visible", this.isVisible()); ++ nbttagcompound.putInt("Value", this.value); ++ nbttagcompound.putInt("Max", this.max); ++ nbttagcompound.putString("Color", this.getColor().getName()); ++ nbttagcompound.putString("Overlay", this.getOverlay().getName()); ++ nbttagcompound.putBoolean("DarkenScreen", this.shouldDarkenScreen()); ++ nbttagcompound.putBoolean("PlayBossMusic", this.shouldPlayBossMusic()); ++ nbttagcompound.putBoolean("CreateWorldFog", this.shouldCreateWorldFog()); ++ ListTag nbttaglist = new ListTag(); + Iterator iterator = this.players.iterator(); + + while (iterator.hasNext()) { + UUID uuid = (UUID) iterator.next(); + +- listtag.add(NbtUtils.createUUID(uuid)); ++ nbttaglist.add(NbtUtils.createUUID(uuid)); + } + +- compoundtag.put("Players", listtag); +- return compoundtag; ++ nbttagcompound.put("Players", nbttaglist); ++ return nbttagcompound; + } + +- public static CustomBossEvent load(CompoundTag compoundtag, ResourceLocation resourcelocation) { +- CustomBossEvent custombossevent = new CustomBossEvent(resourcelocation, Component.Serializer.fromJson(compoundtag.getString("Name"))); ++ public static CustomBossEvent load(CompoundTag nbt, ResourceLocation id) { ++ CustomBossEvent bossbattlecustom = new CustomBossEvent(id, Component.Serializer.fromJson(nbt.getString("Name"))); + +- custombossevent.setVisible(compoundtag.getBoolean("Visible")); +- custombossevent.setValue(compoundtag.getInt("Value")); +- custombossevent.setMax(compoundtag.getInt("Max")); +- custombossevent.setColor(BossEvent.BossBarColor.byName(compoundtag.getString("Color"))); +- custombossevent.setOverlay(BossEvent.BossBarOverlay.byName(compoundtag.getString("Overlay"))); +- custombossevent.setDarkenScreen(compoundtag.getBoolean("DarkenScreen")); +- custombossevent.setPlayBossMusic(compoundtag.getBoolean("PlayBossMusic")); +- custombossevent.setCreateWorldFog(compoundtag.getBoolean("CreateWorldFog")); +- ListTag listtag = compoundtag.getList("Players", 11); +- Iterator iterator = listtag.iterator(); ++ bossbattlecustom.setVisible(nbt.getBoolean("Visible")); ++ bossbattlecustom.setValue(nbt.getInt("Value")); ++ bossbattlecustom.setMax(nbt.getInt("Max")); ++ bossbattlecustom.setColor(BossEvent.BossBarColor.byName(nbt.getString("Color"))); ++ bossbattlecustom.setOverlay(BossEvent.BossBarOverlay.byName(nbt.getString("Overlay"))); ++ bossbattlecustom.setDarkenScreen(nbt.getBoolean("DarkenScreen")); ++ bossbattlecustom.setPlayBossMusic(nbt.getBoolean("PlayBossMusic")); ++ bossbattlecustom.setCreateWorldFog(nbt.getBoolean("CreateWorldFog")); ++ ListTag nbttaglist = nbt.getList("Players", 11); ++ Iterator iterator = nbttaglist.iterator(); + + while (iterator.hasNext()) { +- Tag tag = (Tag) iterator.next(); ++ Tag nbtbase = (Tag) iterator.next(); + +- custombossevent.addOfflinePlayer(NbtUtils.loadUUID(tag)); ++ bossbattlecustom.addOfflinePlayer(NbtUtils.loadUUID(nbtbase)); + } + +- return custombossevent; ++ return bossbattlecustom; + } + +- public void onPlayerConnect(ServerPlayer serverplayer) { +- if (this.players.contains(serverplayer.getUUID())) { +- this.addPlayer(serverplayer); ++ public void onPlayerConnect(ServerPlayer player) { ++ if (this.players.contains(player.getUUID())) { ++ this.addPlayer(player); + } + + } + +- public void onPlayerDisconnect(ServerPlayer serverplayer) { +- super.removePlayer(serverplayer); ++ public void onPlayerDisconnect(ServerPlayer player) { ++ super.removePlayer(player); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/commands/DifficultyCommand.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/commands/DifficultyCommand.java.patch new file mode 100644 index 0000000000..2378c01fbe --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/commands/DifficultyCommand.java.patch @@ -0,0 +1,68 @@ +--- a/net/minecraft/server/commands/DifficultyCommand.java ++++ b/net/minecraft/server/commands/DifficultyCommand.java +@@ -5,7 +5,6 @@ + import com.mojang.brigadier.exceptions.CommandSyntaxException; + import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.network.chat.Component; + import net.minecraft.server.MinecraftServer; + import net.minecraft.world.Difficulty; +@@ -18,39 +17,40 @@ + + public DifficultyCommand() {} + +- public static void register(CommandDispatcher commanddispatcher) { +- LiteralArgumentBuilder literalargumentbuilder = Commands.literal("difficulty"); +- Difficulty[] adifficulty = Difficulty.values(); +- int i = adifficulty.length; ++ public static void register(CommandDispatcher dispatcher) { ++ LiteralArgumentBuilder literalargumentbuilder = net.minecraft.commands.Commands.literal("difficulty"); ++ Difficulty[] aenumdifficulty = Difficulty.values(); ++ int i = aenumdifficulty.length; + + for (int j = 0; j < i; ++j) { +- Difficulty difficulty = adifficulty[j]; ++ Difficulty enumdifficulty = aenumdifficulty[j]; + +- literalargumentbuilder.then(Commands.literal(difficulty.getKey()).executes((commandcontext) -> { +- return setDifficulty((CommandSourceStack) commandcontext.getSource(), difficulty); ++ literalargumentbuilder.then(net.minecraft.commands.Commands.literal(enumdifficulty.getKey()).executes((commandcontext) -> { ++ return setDifficulty((CommandSourceStack) commandcontext.getSource(), enumdifficulty); + })); + } + +- commanddispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) literalargumentbuilder.requires((commandsourcestack) -> { +- return commandsourcestack.hasPermission(2); ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) literalargumentbuilder.requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); + })).executes((commandcontext) -> { +- Difficulty difficulty1 = ((CommandSourceStack) commandcontext.getSource()).getLevel().getDifficulty(); ++ Difficulty enumdifficulty1 = ((CommandSourceStack) commandcontext.getSource()).getLevel().getDifficulty(); + + ((CommandSourceStack) commandcontext.getSource()).sendSuccess(() -> { +- return Component.translatable("commands.difficulty.query", difficulty1.getDisplayName()); ++ return Component.translatable("commands.difficulty.query", enumdifficulty1.getDisplayName()); + }, false); +- return difficulty1.getId(); ++ return enumdifficulty1.getId(); + })); + } + +- public static int setDifficulty(CommandSourceStack commandsourcestack, Difficulty difficulty) throws CommandSyntaxException { +- MinecraftServer minecraftserver = commandsourcestack.getServer(); ++ public static int setDifficulty(CommandSourceStack source, Difficulty difficulty) throws CommandSyntaxException { ++ MinecraftServer minecraftserver = source.getServer(); ++ net.minecraft.server.level.ServerLevel worldServer = source.getLevel(); // CraftBukkit + +- if (minecraftserver.getWorldData().getDifficulty() == difficulty) { ++ if (worldServer.getDifficulty() == difficulty) { // CraftBukkit + throw DifficultyCommand.ERROR_ALREADY_DIFFICULT.create(difficulty.getKey()); + } else { +- minecraftserver.setDifficulty(difficulty, true); +- commandsourcestack.sendSuccess(() -> { ++ worldServer.serverLevelData.setDifficulty(difficulty); // CraftBukkit ++ source.sendSuccess(() -> { + return Component.translatable("commands.difficulty.success", difficulty.getDisplayName()); + }, true); + return 0; diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/commands/EffectCommands.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/commands/EffectCommands.java.patch new file mode 100644 index 0000000000..1af9a53d4d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/commands/EffectCommands.java.patch @@ -0,0 +1,190 @@ +--- a/net/minecraft/server/commands/EffectCommands.java ++++ b/net/minecraft/server/commands/EffectCommands.java +@@ -13,7 +13,6 @@ + import javax.annotation.Nullable; + import net.minecraft.commands.CommandBuildContext; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.arguments.EntityArgument; + import net.minecraft.commands.arguments.ResourceArgument; + import net.minecraft.core.Holder; +@@ -32,60 +31,60 @@ + + public EffectCommands() {} + +- public static void register(CommandDispatcher commanddispatcher, CommandBuildContext commandbuildcontext) { +- commanddispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) Commands.literal("effect").requires((commandsourcestack) -> { +- return commandsourcestack.hasPermission(2); +- })).then(((LiteralArgumentBuilder) Commands.literal("clear").executes((commandcontext) -> { ++ public static void register(CommandDispatcher dispatcher, CommandBuildContext context) { ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("effect").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).then(((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("clear").executes((commandcontext) -> { + return clearEffects((CommandSourceStack) commandcontext.getSource(), ImmutableList.of(((CommandSourceStack) commandcontext.getSource()).getEntityOrException())); +- })).then(((RequiredArgumentBuilder) Commands.argument("targets", EntityArgument.entities()).executes((commandcontext) -> { ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("targets", EntityArgument.entities()).executes((commandcontext) -> { + return clearEffects((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets")); +- })).then(Commands.argument("effect", ResourceArgument.resource(commandbuildcontext, Registries.MOB_EFFECT)).executes((commandcontext) -> { ++ })).then(net.minecraft.commands.Commands.argument("effect", ResourceArgument.resource(context, Registries.MOB_EFFECT)).executes((commandcontext) -> { + return clearEffect((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ResourceArgument.getMobEffect(commandcontext, "effect")); +- }))))).then(Commands.literal("give").then(Commands.argument("targets", EntityArgument.entities()).then(((RequiredArgumentBuilder) ((RequiredArgumentBuilder) Commands.argument("effect", ResourceArgument.resource(commandbuildcontext, Registries.MOB_EFFECT)).executes((commandcontext) -> { ++ }))))).then(net.minecraft.commands.Commands.literal("give").then(net.minecraft.commands.Commands.argument("targets", EntityArgument.entities()).then(((RequiredArgumentBuilder) ((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("effect", ResourceArgument.resource(context, Registries.MOB_EFFECT)).executes((commandcontext) -> { + return giveEffect((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ResourceArgument.getMobEffect(commandcontext, "effect"), (Integer) null, 0, true); +- })).then(((RequiredArgumentBuilder) Commands.argument("seconds", IntegerArgumentType.integer(1, 1000000)).executes((commandcontext) -> { ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("seconds", IntegerArgumentType.integer(1, 1000000)).executes((commandcontext) -> { + return giveEffect((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ResourceArgument.getMobEffect(commandcontext, "effect"), IntegerArgumentType.getInteger(commandcontext, "seconds"), 0, true); +- })).then(((RequiredArgumentBuilder) Commands.argument("amplifier", IntegerArgumentType.integer(0, 255)).executes((commandcontext) -> { ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("amplifier", IntegerArgumentType.integer(0, 255)).executes((commandcontext) -> { + return giveEffect((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ResourceArgument.getMobEffect(commandcontext, "effect"), IntegerArgumentType.getInteger(commandcontext, "seconds"), IntegerArgumentType.getInteger(commandcontext, "amplifier"), true); +- })).then(Commands.argument("hideParticles", BoolArgumentType.bool()).executes((commandcontext) -> { ++ })).then(net.minecraft.commands.Commands.argument("hideParticles", BoolArgumentType.bool()).executes((commandcontext) -> { + return giveEffect((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ResourceArgument.getMobEffect(commandcontext, "effect"), IntegerArgumentType.getInteger(commandcontext, "seconds"), IntegerArgumentType.getInteger(commandcontext, "amplifier"), !BoolArgumentType.getBool(commandcontext, "hideParticles")); +- }))))).then(((LiteralArgumentBuilder) Commands.literal("infinite").executes((commandcontext) -> { ++ }))))).then(((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("infinite").executes((commandcontext) -> { + return giveEffect((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ResourceArgument.getMobEffect(commandcontext, "effect"), -1, 0, true); +- })).then(((RequiredArgumentBuilder) Commands.argument("amplifier", IntegerArgumentType.integer(0, 255)).executes((commandcontext) -> { ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("amplifier", IntegerArgumentType.integer(0, 255)).executes((commandcontext) -> { + return giveEffect((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ResourceArgument.getMobEffect(commandcontext, "effect"), -1, IntegerArgumentType.getInteger(commandcontext, "amplifier"), true); +- })).then(Commands.argument("hideParticles", BoolArgumentType.bool()).executes((commandcontext) -> { ++ })).then(net.minecraft.commands.Commands.argument("hideParticles", BoolArgumentType.bool()).executes((commandcontext) -> { + return giveEffect((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ResourceArgument.getMobEffect(commandcontext, "effect"), -1, IntegerArgumentType.getInteger(commandcontext, "amplifier"), !BoolArgumentType.getBool(commandcontext, "hideParticles")); + })))))))); + } + +- private static int giveEffect(CommandSourceStack commandsourcestack, Collection collection, Holder holder, @Nullable Integer integer, int i, boolean flag) throws CommandSyntaxException { +- MobEffect mobeffect = (MobEffect) holder.value(); ++ private static int giveEffect(CommandSourceStack source, Collection targets, Holder effect, @Nullable Integer seconds, int amplifier, boolean showParticles) throws CommandSyntaxException { ++ MobEffect mobeffectlist = (MobEffect) effect.value(); + int j = 0; + int k; + +- if (integer != null) { +- if (mobeffect.isInstantenous()) { +- k = integer; +- } else if (integer == -1) { ++ if (seconds != null) { ++ if (mobeffectlist.isInstantenous()) { ++ k = seconds; ++ } else if (seconds == -1) { + k = -1; + } else { +- k = integer * 20; ++ k = seconds * 20; + } +- } else if (mobeffect.isInstantenous()) { ++ } else if (mobeffectlist.isInstantenous()) { + k = 1; + } else { + k = 600; + } + +- Iterator iterator = collection.iterator(); ++ Iterator iterator = targets.iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); + + if (entity instanceof LivingEntity) { +- MobEffectInstance mobeffectinstance = new MobEffectInstance(mobeffect, k, i, false, flag); ++ MobEffectInstance mobeffect = new MobEffectInstance(mobeffectlist, k, amplifier, false, showParticles); + +- if (((LivingEntity) entity).addEffect(mobeffectinstance, commandsourcestack.getEntity())) { ++ if (((LivingEntity) entity).addEffect(mobeffect, source.getEntity(), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.COMMAND)) { // CraftBukkit + ++j; + } + } +@@ -94,13 +93,13 @@ + if (j == 0) { + throw EffectCommands.ERROR_GIVE_FAILED.create(); + } else { +- if (collection.size() == 1) { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.effect.give.success.single", mobeffect.getDisplayName(), ((Entity) collection.iterator().next()).getDisplayName(), k / 20); ++ if (targets.size() == 1) { ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.effect.give.success.single", mobeffectlist.getDisplayName(), ((Entity) targets.iterator().next()).getDisplayName(), k / 20); + }, true); + } else { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.effect.give.success.multiple", mobeffect.getDisplayName(), collection.size(), k / 20); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.effect.give.success.multiple", mobeffectlist.getDisplayName(), targets.size(), k / 20); + }, true); + } + +@@ -108,14 +107,14 @@ + } + } + +- private static int clearEffects(CommandSourceStack commandsourcestack, Collection collection) throws CommandSyntaxException { ++ private static int clearEffects(CommandSourceStack source, Collection targets) throws CommandSyntaxException { + int i = 0; +- Iterator iterator = collection.iterator(); ++ Iterator iterator = targets.iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); + +- if (entity instanceof LivingEntity && ((LivingEntity) entity).removeAllEffects()) { ++ if (entity instanceof LivingEntity && ((LivingEntity) entity).removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.COMMAND)) { // CraftBukkit + ++i; + } + } +@@ -123,13 +122,13 @@ + if (i == 0) { + throw EffectCommands.ERROR_CLEAR_EVERYTHING_FAILED.create(); + } else { +- if (collection.size() == 1) { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.effect.clear.everything.success.single", ((Entity) collection.iterator().next()).getDisplayName()); ++ if (targets.size() == 1) { ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.effect.clear.everything.success.single", ((Entity) targets.iterator().next()).getDisplayName()); + }, true); + } else { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.effect.clear.everything.success.multiple", collection.size()); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.effect.clear.everything.success.multiple", targets.size()); + }, true); + } + +@@ -137,15 +136,15 @@ + } + } + +- private static int clearEffect(CommandSourceStack commandsourcestack, Collection collection, Holder holder) throws CommandSyntaxException { +- MobEffect mobeffect = (MobEffect) holder.value(); ++ private static int clearEffect(CommandSourceStack source, Collection targets, Holder effect) throws CommandSyntaxException { ++ MobEffect mobeffectlist = (MobEffect) effect.value(); + int i = 0; +- Iterator iterator = collection.iterator(); ++ Iterator iterator = targets.iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); + +- if (entity instanceof LivingEntity && ((LivingEntity) entity).removeEffect(mobeffect)) { ++ if (entity instanceof LivingEntity && ((LivingEntity) entity).removeEffect(mobeffectlist, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.COMMAND)) { // CraftBukkit + ++i; + } + } +@@ -153,13 +152,13 @@ + if (i == 0) { + throw EffectCommands.ERROR_CLEAR_SPECIFIC_FAILED.create(); + } else { +- if (collection.size() == 1) { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.effect.clear.specific.success.single", mobeffect.getDisplayName(), ((Entity) collection.iterator().next()).getDisplayName()); ++ if (targets.size() == 1) { ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.effect.clear.specific.success.single", mobeffectlist.getDisplayName(), ((Entity) targets.iterator().next()).getDisplayName()); + }, true); + } else { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.effect.clear.specific.success.multiple", mobeffect.getDisplayName(), collection.size()); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.effect.clear.specific.success.multiple", mobeffectlist.getDisplayName(), targets.size()); + }, true); + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/commands/GameRuleCommand.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/commands/GameRuleCommand.java.patch new file mode 100644 index 0000000000..c19f6d9203 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/commands/GameRuleCommand.java.patch @@ -0,0 +1,71 @@ +--- a/net/minecraft/server/commands/GameRuleCommand.java ++++ b/net/minecraft/server/commands/GameRuleCommand.java +@@ -4,7 +4,6 @@ + import com.mojang.brigadier.builder.LiteralArgumentBuilder; + import com.mojang.brigadier.context.CommandContext; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.network.chat.Component; + import net.minecraft.world.level.GameRules; + +@@ -12,41 +11,40 @@ + + public GameRuleCommand() {} + +- public static void register(CommandDispatcher commanddispatcher) { +- final LiteralArgumentBuilder literalargumentbuilder = (LiteralArgumentBuilder) Commands.literal("gamerule").requires((commandsourcestack) -> { +- return commandsourcestack.hasPermission(2); ++ public static void register(CommandDispatcher dispatcher) { ++ final LiteralArgumentBuilder literalargumentbuilder = (LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("gamerule").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); + }); + + GameRules.visitGameRuleTypes(new GameRules.GameRuleTypeVisitor() { + @Override +- @Override +- public > void visit(GameRules.Key gamerules_key, GameRules.Type gamerules_type) { +- literalargumentbuilder.then(((LiteralArgumentBuilder) Commands.literal(gamerules_key.getId()).executes((commandcontext) -> { +- return GameRuleCommand.queryRule((CommandSourceStack) commandcontext.getSource(), gamerules_key); +- })).then(gamerules_type.createArgument("value").executes((commandcontext) -> { +- return GameRuleCommand.setRule(commandcontext, gamerules_key); ++ public > void visit(GameRules.Key key, GameRules.Type type) { ++ literalargumentbuilder.then(((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal(key.getId()).executes((commandcontext) -> { ++ return GameRuleCommand.queryRule((CommandSourceStack) commandcontext.getSource(), key); ++ })).then(type.createArgument("value").executes((commandcontext) -> { ++ return GameRuleCommand.setRule(commandcontext, key); + }))); + } + }); +- commanddispatcher.register(literalargumentbuilder); ++ dispatcher.register(literalargumentbuilder); + } + +- static > int setRule(CommandContext commandcontext, GameRules.Key gamerules_key) { +- CommandSourceStack commandsourcestack = (CommandSourceStack) commandcontext.getSource(); +- T t0 = commandsourcestack.getServer().getGameRules().getRule(gamerules_key); ++ static > int setRule(CommandContext source, GameRules.Key gameRule) { ++ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) source.getSource(); ++ T t0 = commandlistenerwrapper.getLevel().getGameRules().getRule(gameRule); // CraftBukkit + +- t0.setFromArgument(commandcontext, "value"); +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.gamerule.set", gamerules_key.getId(), t0.toString()); ++ t0.setFromArgument(source, "value"); ++ commandlistenerwrapper.sendSuccess(() -> { ++ return Component.translatable("commands.gamerule.set", gameRule.getId(), t0.toString()); + }, true); + return t0.getCommandResult(); + } + +- static > int queryRule(CommandSourceStack commandsourcestack, GameRules.Key gamerules_key) { +- T t0 = commandsourcestack.getServer().getGameRules().getRule(gamerules_key); ++ static > int queryRule(CommandSourceStack source, GameRules.Key gameRule) { ++ T t0 = source.getLevel().getGameRules().getRule(gameRule); // CraftBukkit + +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.gamerule.query", gamerules_key.getId(), t0.toString()); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.gamerule.query", gameRule.getId(), t0.toString()); + }, false); + return t0.getCommandResult(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/commands/GiveCommand.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/commands/GiveCommand.java.patch new file mode 100644 index 0000000000..bee7346024 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/commands/GiveCommand.java.patch @@ -0,0 +1,111 @@ +--- a/net/minecraft/server/commands/GiveCommand.java ++++ b/net/minecraft/server/commands/GiveCommand.java +@@ -9,7 +9,6 @@ + import java.util.Iterator; + import net.minecraft.commands.CommandBuildContext; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.arguments.EntityArgument; + import net.minecraft.commands.arguments.item.ItemArgument; + import net.minecraft.commands.arguments.item.ItemInput; +@@ -27,69 +26,69 @@ + + public GiveCommand() {} + +- public static void register(CommandDispatcher commanddispatcher, CommandBuildContext commandbuildcontext) { +- commanddispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) Commands.literal("give").requires((commandsourcestack) -> { +- return commandsourcestack.hasPermission(2); +- })).then(Commands.argument("targets", EntityArgument.players()).then(((RequiredArgumentBuilder) Commands.argument("item", ItemArgument.item(commandbuildcontext)).executes((commandcontext) -> { ++ public static void register(CommandDispatcher dispatcher, CommandBuildContext context) { ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("give").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).then(net.minecraft.commands.Commands.argument("targets", EntityArgument.players()).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("item", ItemArgument.item(context)).executes((commandcontext) -> { + return giveItem((CommandSourceStack) commandcontext.getSource(), ItemArgument.getItem(commandcontext, "item"), EntityArgument.getPlayers(commandcontext, "targets"), 1); +- })).then(Commands.argument("count", IntegerArgumentType.integer(1)).executes((commandcontext) -> { ++ })).then(net.minecraft.commands.Commands.argument("count", IntegerArgumentType.integer(1)).executes((commandcontext) -> { + return giveItem((CommandSourceStack) commandcontext.getSource(), ItemArgument.getItem(commandcontext, "item"), EntityArgument.getPlayers(commandcontext, "targets"), IntegerArgumentType.getInteger(commandcontext, "count")); + }))))); + } + +- private static int giveItem(CommandSourceStack commandsourcestack, ItemInput iteminput, Collection collection, int i) throws CommandSyntaxException { +- int j = iteminput.getItem().getMaxStackSize(); ++ private static int giveItem(CommandSourceStack source, ItemInput item, Collection targets, int count) throws CommandSyntaxException { ++ int j = item.getItem().getMaxStackSize(); + int k = j * 100; +- ItemStack itemstack = iteminput.createItemStack(i, false); ++ ItemStack itemstack = item.createItemStack(count, false); + +- if (i > k) { +- commandsourcestack.sendFailure(Component.translatable("commands.give.failed.toomanyitems", k, itemstack.getDisplayName())); ++ if (count > k) { ++ source.sendFailure(Component.translatable("commands.give.failed.toomanyitems", k, itemstack.getDisplayName())); + return 0; + } else { +- Iterator iterator = collection.iterator(); ++ Iterator iterator = targets.iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); +- int l = i; ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ int l = count; + + while (l > 0) { + int i1 = Math.min(j, l); + + l -= i1; +- ItemStack itemstack1 = iteminput.createItemStack(i1, false); +- boolean flag = serverplayer.getInventory().add(itemstack1); +- ItemEntity itementity; ++ ItemStack itemstack1 = item.createItemStack(i1, false); ++ boolean flag = entityplayer.getInventory().add(itemstack1); ++ ItemEntity entityitem; + + if (flag && itemstack1.isEmpty()) { + itemstack1.setCount(1); +- itementity = serverplayer.drop(itemstack1, false); +- if (itementity != null) { +- itementity.makeFakeItem(); ++ entityitem = entityplayer.drop(itemstack1, false, false, false); // SPIGOT-2942: Add boolean to call event ++ if (entityitem != null) { ++ entityitem.makeFakeItem(); + } + +- serverplayer.level().playSound((Player) null, serverplayer.getX(), serverplayer.getY(), serverplayer.getZ(), SoundEvents.ITEM_PICKUP, SoundSource.PLAYERS, 0.2F, ((serverplayer.getRandom().nextFloat() - serverplayer.getRandom().nextFloat()) * 0.7F + 1.0F) * 2.0F); +- serverplayer.containerMenu.broadcastChanges(); ++ entityplayer.level().playSound((Player) null, entityplayer.getX(), entityplayer.getY(), entityplayer.getZ(), SoundEvents.ITEM_PICKUP, SoundSource.PLAYERS, 0.2F, ((entityplayer.getRandom().nextFloat() - entityplayer.getRandom().nextFloat()) * 0.7F + 1.0F) * 2.0F); ++ entityplayer.containerMenu.broadcastChanges(); + } else { +- itementity = serverplayer.drop(itemstack1, false); +- if (itementity != null) { +- itementity.setNoPickUpDelay(); +- itementity.setTarget(serverplayer.getUUID()); ++ entityitem = entityplayer.drop(itemstack1, false); ++ if (entityitem != null) { ++ entityitem.setNoPickUpDelay(); ++ entityitem.setTarget(entityplayer.getUUID()); + } + } + } + } + +- if (collection.size() == 1) { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.give.success.single", i, itemstack.getDisplayName(), ((ServerPlayer) collection.iterator().next()).getDisplayName()); ++ if (targets.size() == 1) { ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.give.success.single", count, itemstack.getDisplayName(), ((ServerPlayer) targets.iterator().next()).getDisplayName()); + }, true); + } else { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.give.success.single", i, itemstack.getDisplayName(), collection.size()); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.give.success.single", count, itemstack.getDisplayName(), targets.size()); + }, true); + } + +- return collection.size(); ++ return targets.size(); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/commands/ListPlayersCommand.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/commands/ListPlayersCommand.java.patch new file mode 100644 index 0000000000..685919c97a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/commands/ListPlayersCommand.java.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/server/commands/ListPlayersCommand.java ++++ b/net/minecraft/server/commands/ListPlayersCommand.java +@@ -5,7 +5,6 @@ + import java.util.List; + import java.util.function.Function; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.ComponentUtils; + import net.minecraft.server.level.ServerPlayer; +@@ -16,31 +15,38 @@ + + public ListPlayersCommand() {} + +- public static void register(CommandDispatcher commanddispatcher) { +- commanddispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) Commands.literal("list").executes((commandcontext) -> { ++ public static void register(CommandDispatcher dispatcher) { ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("list").executes((commandcontext) -> { + return listPlayers((CommandSourceStack) commandcontext.getSource()); +- })).then(Commands.literal("uuids").executes((commandcontext) -> { ++ })).then(net.minecraft.commands.Commands.literal("uuids").executes((commandcontext) -> { + return listPlayersWithUuids((CommandSourceStack) commandcontext.getSource()); + }))); + } + +- private static int listPlayers(CommandSourceStack commandsourcestack) { +- return format(commandsourcestack, Player::getDisplayName); ++ private static int listPlayers(CommandSourceStack source) { ++ return format(source, Player::getDisplayName); + } + +- private static int listPlayersWithUuids(CommandSourceStack commandsourcestack) { +- return format(commandsourcestack, (serverplayer) -> { +- return Component.translatable("commands.list.nameAndId", serverplayer.getName(), Component.translationArg(serverplayer.getGameProfile().getId())); ++ private static int listPlayersWithUuids(CommandSourceStack source) { ++ return format(source, (entityplayer) -> { ++ return Component.translatable("commands.list.nameAndId", entityplayer.getName(), Component.translationArg(entityplayer.getGameProfile().getId())); + }); + } + +- private static int format(CommandSourceStack commandsourcestack, Function function) { +- PlayerList playerlist = commandsourcestack.getServer().getPlayerList(); +- List list = playerlist.getPlayers(); +- Component component = ComponentUtils.formatList(list, function); ++ private static int format(CommandSourceStack source, Function nameExtractor) { ++ PlayerList playerlist = source.getServer().getPlayerList(); ++ // CraftBukkit start ++ List players = playerlist.getPlayers(); ++ if (source.getBukkitSender() instanceof org.bukkit.entity.Player) { ++ org.bukkit.entity.Player sender = (org.bukkit.entity.Player) source.getBukkitSender(); ++ players = players.stream().filter((ep) -> sender.canSee(ep.getBukkitEntity())).collect(java.util.stream.Collectors.toList()); ++ } ++ List list = players; ++ // CraftBukkit end ++ Component ichatbasecomponent = ComponentUtils.formatList(list, nameExtractor); + +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.list.players", list.size(), playerlist.getMaxPlayers(), component); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.list.players", list.size(), playerlist.getMaxPlayers(), ichatbasecomponent); + }, false); + return list.size(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/commands/LootCommand.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/commands/LootCommand.java.patch new file mode 100644 index 0000000000..a3fd16e3b3 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/commands/LootCommand.java.patch @@ -0,0 +1,481 @@ +--- a/net/minecraft/server/commands/LootCommand.java ++++ b/net/minecraft/server/commands/LootCommand.java +@@ -15,7 +15,6 @@ + import java.util.List; + import net.minecraft.commands.CommandBuildContext; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.SharedSuggestionProvider; + import net.minecraft.commands.arguments.EntityArgument; + import net.minecraft.commands.arguments.ResourceLocationArgument; +@@ -37,7 +36,7 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.storage.loot.LootDataManager; + import net.minecraft.world.level.storage.loot.LootDataType; + import net.minecraft.world.level.storage.loot.LootParams; +@@ -62,98 +61,98 @@ + + public LootCommand() {} + +- public static void register(CommandDispatcher commanddispatcher, CommandBuildContext commandbuildcontext) { +- commanddispatcher.register((LiteralArgumentBuilder) addTargets((LiteralArgumentBuilder) Commands.literal("loot").requires((commandsourcestack) -> { +- return commandsourcestack.hasPermission(2); +- }), (argumentbuilder, lootcommand_dropconsumer) -> { +- return argumentbuilder.then(Commands.literal("fish").then(Commands.argument("loot_table", ResourceLocationArgument.id()).suggests(LootCommand.SUGGEST_LOOT_TABLE).then(((RequiredArgumentBuilder) ((RequiredArgumentBuilder) ((RequiredArgumentBuilder) Commands.argument("pos", BlockPosArgument.blockPos()).executes((commandcontext) -> { +- return dropFishingLoot(commandcontext, ResourceLocationArgument.getId(commandcontext, "loot_table"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), ItemStack.EMPTY, lootcommand_dropconsumer); +- })).then(Commands.argument("tool", ItemArgument.item(commandbuildcontext)).executes((commandcontext) -> { +- return dropFishingLoot(commandcontext, ResourceLocationArgument.getId(commandcontext, "loot_table"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), ItemArgument.getItem(commandcontext, "tool").createItemStack(1, false), lootcommand_dropconsumer); +- }))).then(Commands.literal("mainhand").executes((commandcontext) -> { +- return dropFishingLoot(commandcontext, ResourceLocationArgument.getId(commandcontext, "loot_table"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), getSourceHandItem((CommandSourceStack) commandcontext.getSource(), EquipmentSlot.MAINHAND), lootcommand_dropconsumer); +- }))).then(Commands.literal("offhand").executes((commandcontext) -> { +- return dropFishingLoot(commandcontext, ResourceLocationArgument.getId(commandcontext, "loot_table"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), getSourceHandItem((CommandSourceStack) commandcontext.getSource(), EquipmentSlot.OFFHAND), lootcommand_dropconsumer); +- }))))).then(Commands.literal("loot").then(Commands.argument("loot_table", ResourceLocationArgument.id()).suggests(LootCommand.SUGGEST_LOOT_TABLE).executes((commandcontext) -> { +- return dropChestLoot(commandcontext, ResourceLocationArgument.getId(commandcontext, "loot_table"), lootcommand_dropconsumer); +- }))).then(Commands.literal("kill").then(Commands.argument("target", EntityArgument.entity()).executes((commandcontext) -> { +- return dropKillLoot(commandcontext, EntityArgument.getEntity(commandcontext, "target"), lootcommand_dropconsumer); +- }))).then(Commands.literal("mine").then(((RequiredArgumentBuilder) ((RequiredArgumentBuilder) ((RequiredArgumentBuilder) Commands.argument("pos", BlockPosArgument.blockPos()).executes((commandcontext) -> { +- return dropBlockLoot(commandcontext, BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), ItemStack.EMPTY, lootcommand_dropconsumer); +- })).then(Commands.argument("tool", ItemArgument.item(commandbuildcontext)).executes((commandcontext) -> { +- return dropBlockLoot(commandcontext, BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), ItemArgument.getItem(commandcontext, "tool").createItemStack(1, false), lootcommand_dropconsumer); +- }))).then(Commands.literal("mainhand").executes((commandcontext) -> { +- return dropBlockLoot(commandcontext, BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), getSourceHandItem((CommandSourceStack) commandcontext.getSource(), EquipmentSlot.MAINHAND), lootcommand_dropconsumer); +- }))).then(Commands.literal("offhand").executes((commandcontext) -> { +- return dropBlockLoot(commandcontext, BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), getSourceHandItem((CommandSourceStack) commandcontext.getSource(), EquipmentSlot.OFFHAND), lootcommand_dropconsumer); ++ public static void register(CommandDispatcher dispatcher, CommandBuildContext context) { ++ dispatcher.register((LiteralArgumentBuilder) addTargets((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("loot").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ }), (argumentbuilder, commandloot_b) -> { ++ return argumentbuilder.then(net.minecraft.commands.Commands.literal("fish").then(net.minecraft.commands.Commands.argument("loot_table", ResourceLocationArgument.id()).suggests(LootCommand.SUGGEST_LOOT_TABLE).then(((RequiredArgumentBuilder) ((RequiredArgumentBuilder) ((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("pos", BlockPosArgument.blockPos()).executes((commandcontext) -> { ++ return dropFishingLoot(commandcontext, ResourceLocationArgument.getId(commandcontext, "loot_table"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), ItemStack.EMPTY, commandloot_b); ++ })).then(net.minecraft.commands.Commands.argument("tool", ItemArgument.item(context)).executes((commandcontext) -> { ++ return dropFishingLoot(commandcontext, ResourceLocationArgument.getId(commandcontext, "loot_table"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), ItemArgument.getItem(commandcontext, "tool").createItemStack(1, false), commandloot_b); ++ }))).then(net.minecraft.commands.Commands.literal("mainhand").executes((commandcontext) -> { ++ return dropFishingLoot(commandcontext, ResourceLocationArgument.getId(commandcontext, "loot_table"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), getSourceHandItem((CommandSourceStack) commandcontext.getSource(), EquipmentSlot.MAINHAND), commandloot_b); ++ }))).then(net.minecraft.commands.Commands.literal("offhand").executes((commandcontext) -> { ++ return dropFishingLoot(commandcontext, ResourceLocationArgument.getId(commandcontext, "loot_table"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), getSourceHandItem((CommandSourceStack) commandcontext.getSource(), EquipmentSlot.OFFHAND), commandloot_b); ++ }))))).then(net.minecraft.commands.Commands.literal("loot").then(net.minecraft.commands.Commands.argument("loot_table", ResourceLocationArgument.id()).suggests(LootCommand.SUGGEST_LOOT_TABLE).executes((commandcontext) -> { ++ return dropChestLoot(commandcontext, ResourceLocationArgument.getId(commandcontext, "loot_table"), commandloot_b); ++ }))).then(net.minecraft.commands.Commands.literal("kill").then(net.minecraft.commands.Commands.argument("target", EntityArgument.entity()).executes((commandcontext) -> { ++ return dropKillLoot(commandcontext, EntityArgument.getEntity(commandcontext, "target"), commandloot_b); ++ }))).then(net.minecraft.commands.Commands.literal("mine").then(((RequiredArgumentBuilder) ((RequiredArgumentBuilder) ((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("pos", BlockPosArgument.blockPos()).executes((commandcontext) -> { ++ return dropBlockLoot(commandcontext, BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), ItemStack.EMPTY, commandloot_b); ++ })).then(net.minecraft.commands.Commands.argument("tool", ItemArgument.item(context)).executes((commandcontext) -> { ++ return dropBlockLoot(commandcontext, BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), ItemArgument.getItem(commandcontext, "tool").createItemStack(1, false), commandloot_b); ++ }))).then(net.minecraft.commands.Commands.literal("mainhand").executes((commandcontext) -> { ++ return dropBlockLoot(commandcontext, BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), getSourceHandItem((CommandSourceStack) commandcontext.getSource(), EquipmentSlot.MAINHAND), commandloot_b); ++ }))).then(net.minecraft.commands.Commands.literal("offhand").executes((commandcontext) -> { ++ return dropBlockLoot(commandcontext, BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), getSourceHandItem((CommandSourceStack) commandcontext.getSource(), EquipmentSlot.OFFHAND), commandloot_b); + })))); + })); + } + +- private static > T addTargets(T t0, LootCommand.TailProvider lootcommand_tailprovider) { +- return t0.then(((LiteralArgumentBuilder) Commands.literal("replace").then(Commands.literal("entity").then(Commands.argument("entities", EntityArgument.entities()).then(lootcommand_tailprovider.construct(Commands.argument("slot", SlotArgument.slot()), (commandcontext, list, lootcommand_callback) -> { +- return entityReplace(EntityArgument.getEntities(commandcontext, "entities"), SlotArgument.getSlot(commandcontext, "slot"), list.size(), list, lootcommand_callback); +- }).then(lootcommand_tailprovider.construct(Commands.argument("count", IntegerArgumentType.integer(0)), (commandcontext, list, lootcommand_callback) -> { +- return entityReplace(EntityArgument.getEntities(commandcontext, "entities"), SlotArgument.getSlot(commandcontext, "slot"), IntegerArgumentType.getInteger(commandcontext, "count"), list, lootcommand_callback); +- })))))).then(Commands.literal("block").then(Commands.argument("targetPos", BlockPosArgument.blockPos()).then(lootcommand_tailprovider.construct(Commands.argument("slot", SlotArgument.slot()), (commandcontext, list, lootcommand_callback) -> { +- return blockReplace((CommandSourceStack) commandcontext.getSource(), BlockPosArgument.getLoadedBlockPos(commandcontext, "targetPos"), SlotArgument.getSlot(commandcontext, "slot"), list.size(), list, lootcommand_callback); +- }).then(lootcommand_tailprovider.construct(Commands.argument("count", IntegerArgumentType.integer(0)), (commandcontext, list, lootcommand_callback) -> { +- return blockReplace((CommandSourceStack) commandcontext.getSource(), BlockPosArgument.getLoadedBlockPos(commandcontext, "targetPos"), IntegerArgumentType.getInteger(commandcontext, "slot"), IntegerArgumentType.getInteger(commandcontext, "count"), list, lootcommand_callback); +- })))))).then(Commands.literal("insert").then(lootcommand_tailprovider.construct(Commands.argument("targetPos", BlockPosArgument.blockPos()), (commandcontext, list, lootcommand_callback) -> { +- return blockDistribute((CommandSourceStack) commandcontext.getSource(), BlockPosArgument.getLoadedBlockPos(commandcontext, "targetPos"), list, lootcommand_callback); +- }))).then(Commands.literal("give").then(lootcommand_tailprovider.construct(Commands.argument("players", EntityArgument.players()), (commandcontext, list, lootcommand_callback) -> { +- return playerGive(EntityArgument.getPlayers(commandcontext, "players"), list, lootcommand_callback); +- }))).then(Commands.literal("spawn").then(lootcommand_tailprovider.construct(Commands.argument("targetPos", Vec3Argument.vec3()), (commandcontext, list, lootcommand_callback) -> { +- return dropInWorld((CommandSourceStack) commandcontext.getSource(), Vec3Argument.getVec3(commandcontext, "targetPos"), list, lootcommand_callback); ++ private static > T addTargets(T builder, LootCommand.TailProvider tailProvider) { ++ return (T) builder.then(((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("replace").then(net.minecraft.commands.Commands.literal("entity").then(net.minecraft.commands.Commands.argument("entities", EntityArgument.entities()).then(tailProvider.construct(net.minecraft.commands.Commands.argument("slot", SlotArgument.slot()), (commandcontext, list, commandloot_a) -> { // CraftBukkit - decompile error ++ return entityReplace(EntityArgument.getEntities(commandcontext, "entities"), SlotArgument.getSlot(commandcontext, "slot"), list.size(), list, commandloot_a); ++ }).then(tailProvider.construct(net.minecraft.commands.Commands.argument("count", IntegerArgumentType.integer(0)), (commandcontext, list, commandloot_a) -> { ++ return entityReplace(EntityArgument.getEntities(commandcontext, "entities"), SlotArgument.getSlot(commandcontext, "slot"), IntegerArgumentType.getInteger(commandcontext, "count"), list, commandloot_a); ++ })))))).then(net.minecraft.commands.Commands.literal("block").then(net.minecraft.commands.Commands.argument("targetPos", BlockPosArgument.blockPos()).then(tailProvider.construct(net.minecraft.commands.Commands.argument("slot", SlotArgument.slot()), (commandcontext, list, commandloot_a) -> { ++ return blockReplace((CommandSourceStack) commandcontext.getSource(), BlockPosArgument.getLoadedBlockPos(commandcontext, "targetPos"), SlotArgument.getSlot(commandcontext, "slot"), list.size(), list, commandloot_a); ++ }).then(tailProvider.construct(net.minecraft.commands.Commands.argument("count", IntegerArgumentType.integer(0)), (commandcontext, list, commandloot_a) -> { ++ return blockReplace((CommandSourceStack) commandcontext.getSource(), BlockPosArgument.getLoadedBlockPos(commandcontext, "targetPos"), IntegerArgumentType.getInteger(commandcontext, "slot"), IntegerArgumentType.getInteger(commandcontext, "count"), list, commandloot_a); ++ })))))).then(net.minecraft.commands.Commands.literal("insert").then(tailProvider.construct(net.minecraft.commands.Commands.argument("targetPos", BlockPosArgument.blockPos()), (commandcontext, list, commandloot_a) -> { ++ return blockDistribute((CommandSourceStack) commandcontext.getSource(), BlockPosArgument.getLoadedBlockPos(commandcontext, "targetPos"), list, commandloot_a); ++ }))).then(net.minecraft.commands.Commands.literal("give").then(tailProvider.construct(net.minecraft.commands.Commands.argument("players", EntityArgument.players()), (commandcontext, list, commandloot_a) -> { ++ return playerGive(EntityArgument.getPlayers(commandcontext, "players"), list, commandloot_a); ++ }))).then(net.minecraft.commands.Commands.literal("spawn").then(tailProvider.construct(net.minecraft.commands.Commands.argument("targetPos", Vec3Argument.vec3()), (commandcontext, list, commandloot_a) -> { ++ return dropInWorld((CommandSourceStack) commandcontext.getSource(), Vec3Argument.getVec3(commandcontext, "targetPos"), list, commandloot_a); + }))); + } + +- private static Container getContainer(CommandSourceStack commandsourcestack, BlockPos blockpos) throws CommandSyntaxException { +- BlockEntity blockentity = commandsourcestack.getLevel().getBlockEntity(blockpos); ++ private static Container getContainer(CommandSourceStack source, BlockPos pos) throws CommandSyntaxException { ++ BlockEntity tileentity = source.getLevel().getBlockEntity(pos); + +- if (!(blockentity instanceof Container)) { +- throw ItemCommands.ERROR_TARGET_NOT_A_CONTAINER.create(blockpos.getX(), blockpos.getY(), blockpos.getZ()); ++ if (!(tileentity instanceof Container)) { ++ throw ItemCommands.ERROR_TARGET_NOT_A_CONTAINER.create(pos.getX(), pos.getY(), pos.getZ()); + } else { +- return (Container) blockentity; ++ return (Container) tileentity; + } + } + +- private static int blockDistribute(CommandSourceStack commandsourcestack, BlockPos blockpos, List list, LootCommand.Callback lootcommand_callback) throws CommandSyntaxException { +- Container container = getContainer(commandsourcestack, blockpos); +- List list1 = Lists.newArrayListWithCapacity(list.size()); +- Iterator iterator = list.iterator(); ++ private static int blockDistribute(CommandSourceStack source, BlockPos pos, List items, LootCommand.Callback callback) throws CommandSyntaxException { ++ Container iinventory = getContainer(source, pos); ++ List list1 = Lists.newArrayListWithCapacity(items.size()); ++ Iterator iterator = items.iterator(); + + while (iterator.hasNext()) { + ItemStack itemstack = (ItemStack) iterator.next(); + +- if (distributeToContainer(container, itemstack.copy())) { +- container.setChanged(); ++ if (distributeToContainer(iinventory, itemstack.copy())) { ++ iinventory.setChanged(); + list1.add(itemstack); + } + } + +- lootcommand_callback.accept(list1); ++ callback.accept(list1); + return list1.size(); + } + +- private static boolean distributeToContainer(Container container, ItemStack itemstack) { ++ private static boolean distributeToContainer(Container container, ItemStack item) { + boolean flag = false; + +- for (int i = 0; i < container.getContainerSize() && !itemstack.isEmpty(); ++i) { ++ for (int i = 0; i < container.getContainerSize() && !item.isEmpty(); ++i) { + ItemStack itemstack1 = container.getItem(i); + +- if (container.canPlaceItem(i, itemstack)) { ++ if (container.canPlaceItem(i, item)) { + if (itemstack1.isEmpty()) { +- container.setItem(i, itemstack); ++ container.setItem(i, item); + flag = true; + break; + } + +- if (canMergeItems(itemstack1, itemstack)) { +- int j = itemstack.getMaxStackSize() - itemstack1.getCount(); +- int k = Math.min(itemstack.getCount(), j); ++ if (canMergeItems(itemstack1, item)) { ++ int j = item.getMaxStackSize() - itemstack1.getCount(); ++ int k = Math.min(item.getCount(), j); + +- itemstack.shrink(k); ++ item.shrink(k); + itemstack1.grow(k); + flag = true; + } +@@ -163,205 +162,206 @@ + return flag; + } + +- private static int blockReplace(CommandSourceStack commandsourcestack, BlockPos blockpos, int i, int j, List list, LootCommand.Callback lootcommand_callback) throws CommandSyntaxException { +- Container container = getContainer(commandsourcestack, blockpos); +- int k = container.getContainerSize(); ++ private static int blockReplace(CommandSourceStack source, BlockPos pos, int slot, int numSlots, List items, LootCommand.Callback callback) throws CommandSyntaxException { ++ Container iinventory = getContainer(source, pos); ++ int k = iinventory.getContainerSize(); + +- if (i >= 0 && i < k) { +- List list1 = Lists.newArrayListWithCapacity(list.size()); ++ if (slot >= 0 && slot < k) { ++ List list1 = Lists.newArrayListWithCapacity(items.size()); + +- for (int l = 0; l < j; ++l) { +- int i1 = i + l; +- ItemStack itemstack = l < list.size() ? (ItemStack) list.get(l) : ItemStack.EMPTY; ++ for (int l = 0; l < numSlots; ++l) { ++ int i1 = slot + l; ++ ItemStack itemstack = l < items.size() ? (ItemStack) items.get(l) : ItemStack.EMPTY; + +- if (container.canPlaceItem(i1, itemstack)) { +- container.setItem(i1, itemstack); ++ if (iinventory.canPlaceItem(i1, itemstack)) { ++ iinventory.setItem(i1, itemstack); + list1.add(itemstack); + } + } + +- lootcommand_callback.accept(list1); ++ callback.accept(list1); + return list1.size(); + } else { +- throw ItemCommands.ERROR_TARGET_INAPPLICABLE_SLOT.create(i); ++ throw ItemCommands.ERROR_TARGET_INAPPLICABLE_SLOT.create(slot); + } + } + +- private static boolean canMergeItems(ItemStack itemstack, ItemStack itemstack1) { +- return itemstack.getCount() <= itemstack.getMaxStackSize() && ItemStack.isSameItemSameTags(itemstack, itemstack1); ++ private static boolean canMergeItems(ItemStack first, ItemStack second) { ++ return first.getCount() <= first.getMaxStackSize() && ItemStack.isSameItemSameTags(first, second); + } + +- private static int playerGive(Collection collection, List list, LootCommand.Callback lootcommand_callback) throws CommandSyntaxException { +- List list1 = Lists.newArrayListWithCapacity(list.size()); +- Iterator iterator = list.iterator(); ++ private static int playerGive(Collection targets, List items, LootCommand.Callback callback) throws CommandSyntaxException { ++ List list1 = Lists.newArrayListWithCapacity(items.size()); ++ Iterator iterator = items.iterator(); + + while (iterator.hasNext()) { + ItemStack itemstack = (ItemStack) iterator.next(); +- Iterator iterator1 = collection.iterator(); ++ Iterator iterator1 = targets.iterator(); + + while (iterator1.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator1.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator1.next(); + +- if (serverplayer.getInventory().add(itemstack.copy())) { ++ if (entityplayer.getInventory().add(itemstack.copy())) { + list1.add(itemstack); + } + } + } + +- lootcommand_callback.accept(list1); ++ callback.accept(list1); + return list1.size(); + } + +- private static void setSlots(Entity entity, List list, int i, int j, List list1) { +- for (int k = 0; k < j; ++k) { +- ItemStack itemstack = k < list.size() ? (ItemStack) list.get(k) : ItemStack.EMPTY; +- SlotAccess slotaccess = entity.getSlot(i + k); ++ private static void setSlots(Entity target, List items, int startSlot, int numSlots, List setItems) { ++ for (int k = 0; k < numSlots; ++k) { ++ ItemStack itemstack = k < items.size() ? (ItemStack) items.get(k) : ItemStack.EMPTY; ++ SlotAccess slotaccess = target.getSlot(startSlot + k); + + if (slotaccess != SlotAccess.NULL && slotaccess.set(itemstack.copy())) { +- list1.add(itemstack); ++ setItems.add(itemstack); + } + } + + } + +- private static int entityReplace(Collection collection, int i, int j, List list, LootCommand.Callback lootcommand_callback) throws CommandSyntaxException { +- List list1 = Lists.newArrayListWithCapacity(list.size()); +- Iterator iterator = collection.iterator(); ++ private static int entityReplace(Collection targets, int startSlot, int numSlots, List items, LootCommand.Callback callback) throws CommandSyntaxException { ++ List list1 = Lists.newArrayListWithCapacity(items.size()); ++ Iterator iterator = targets.iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); + + if (entity instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) entity; ++ ServerPlayer entityplayer = (ServerPlayer) entity; + +- setSlots(entity, list, i, j, list1); +- serverplayer.containerMenu.broadcastChanges(); ++ setSlots(entity, items, startSlot, numSlots, list1); ++ entityplayer.containerMenu.broadcastChanges(); + } else { +- setSlots(entity, list, i, j, list1); ++ setSlots(entity, items, startSlot, numSlots, list1); + } + } + +- lootcommand_callback.accept(list1); ++ callback.accept(list1); + return list1.size(); + } + +- private static int dropInWorld(CommandSourceStack commandsourcestack, Vec3 vec3, List list, LootCommand.Callback lootcommand_callback) throws CommandSyntaxException { +- ServerLevel serverlevel = commandsourcestack.getLevel(); ++ private static int dropInWorld(CommandSourceStack source, Vec3 pos, List items, LootCommand.Callback callback) throws CommandSyntaxException { ++ ServerLevel worldserver = source.getLevel(); + +- list.forEach((itemstack) -> { +- ItemEntity itementity = new ItemEntity(serverlevel, vec3.x, vec3.y, vec3.z, itemstack.copy()); ++ items.removeIf(ItemStack::isEmpty); // CraftBukkit - SPIGOT-6959 Remove empty items for avoid throw an error in new EntityItem ++ items.forEach((itemstack) -> { ++ ItemEntity entityitem = new ItemEntity(worldserver, pos.x, pos.y, pos.z, itemstack.copy()); + +- itementity.setDefaultPickUpDelay(); +- serverlevel.addFreshEntity(itementity); ++ entityitem.setDefaultPickUpDelay(); ++ worldserver.addFreshEntity(entityitem); + }); +- lootcommand_callback.accept(list); +- return list.size(); ++ callback.accept(items); ++ return items.size(); + } + +- private static void callback(CommandSourceStack commandsourcestack, List list) { +- if (list.size() == 1) { +- ItemStack itemstack = (ItemStack) list.get(0); ++ private static void callback(CommandSourceStack source, List items) { ++ if (items.size() == 1) { ++ ItemStack itemstack = (ItemStack) items.get(0); + +- commandsourcestack.sendSuccess(() -> { ++ source.sendSuccess(() -> { + return Component.translatable("commands.drop.success.single", itemstack.getCount(), itemstack.getDisplayName()); + }, false); + } else { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.drop.success.multiple", list.size()); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.drop.success.multiple", items.size()); + }, false); + } + + } + +- private static void callback(CommandSourceStack commandsourcestack, List list, ResourceLocation resourcelocation) { +- if (list.size() == 1) { +- ItemStack itemstack = (ItemStack) list.get(0); ++ private static void callback(CommandSourceStack source, List items, ResourceLocation lootTable) { ++ if (items.size() == 1) { ++ ItemStack itemstack = (ItemStack) items.get(0); + +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.drop.success.single_with_table", itemstack.getCount(), itemstack.getDisplayName(), Component.translationArg(resourcelocation)); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.drop.success.single_with_table", itemstack.getCount(), itemstack.getDisplayName(), Component.translationArg(lootTable)); + }, false); + } else { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.drop.success.multiple_with_table", list.size(), Component.translationArg(resourcelocation)); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.drop.success.multiple_with_table", items.size(), Component.translationArg(lootTable)); + }, false); + } + + } + +- private static ItemStack getSourceHandItem(CommandSourceStack commandsourcestack, EquipmentSlot equipmentslot) throws CommandSyntaxException { +- Entity entity = commandsourcestack.getEntityOrException(); ++ private static ItemStack getSourceHandItem(CommandSourceStack source, EquipmentSlot slot) throws CommandSyntaxException { ++ Entity entity = source.getEntityOrException(); + + if (entity instanceof LivingEntity) { +- return ((LivingEntity) entity).getItemBySlot(equipmentslot); ++ return ((LivingEntity) entity).getItemBySlot(slot); + } else { + throw LootCommand.ERROR_NO_HELD_ITEMS.create(entity.getDisplayName()); + } + } + +- private static int dropBlockLoot(CommandContext commandcontext, BlockPos blockpos, ItemStack itemstack, LootCommand.DropConsumer lootcommand_dropconsumer) throws CommandSyntaxException { +- CommandSourceStack commandsourcestack = (CommandSourceStack) commandcontext.getSource(); +- ServerLevel serverlevel = commandsourcestack.getLevel(); +- BlockState blockstate = serverlevel.getBlockState(blockpos); +- BlockEntity blockentity = serverlevel.getBlockEntity(blockpos); +- LootParams.Builder lootparams_builder = (new LootParams.Builder(serverlevel)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockpos)).withParameter(LootContextParams.BLOCK_STATE, blockstate).withOptionalParameter(LootContextParams.BLOCK_ENTITY, blockentity).withOptionalParameter(LootContextParams.THIS_ENTITY, commandsourcestack.getEntity()).withParameter(LootContextParams.TOOL, itemstack); +- List list = blockstate.getDrops(lootparams_builder); ++ private static int dropBlockLoot(CommandContext context, BlockPos pos, ItemStack tool, LootCommand.DropConsumer dropConsumer) throws CommandSyntaxException { ++ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) context.getSource(); ++ ServerLevel worldserver = commandlistenerwrapper.getLevel(); ++ IBlockData iblockdata = worldserver.getBlockState(pos); ++ BlockEntity tileentity = worldserver.getBlockEntity(pos); ++ LootParams.Builder lootparams_a = (new LootParams.Builder(worldserver)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos)).withParameter(LootContextParams.BLOCK_STATE, iblockdata).withOptionalParameter(LootContextParams.BLOCK_ENTITY, tileentity).withOptionalParameter(LootContextParams.THIS_ENTITY, commandlistenerwrapper.getEntity()).withParameter(LootContextParams.TOOL, tool); ++ List list = iblockdata.getDrops(lootparams_a); + +- return lootcommand_dropconsumer.accept(commandcontext, list, (list1) -> { +- callback(commandsourcestack, list1, blockstate.getBlock().getLootTable()); ++ return dropConsumer.accept(context, list, (list1) -> { ++ callback(commandlistenerwrapper, list1, iblockdata.getBlock().getLootTable()); + }); + } + +- private static int dropKillLoot(CommandContext commandcontext, Entity entity, LootCommand.DropConsumer lootcommand_dropconsumer) throws CommandSyntaxException { ++ private static int dropKillLoot(CommandContext context, Entity entity, LootCommand.DropConsumer dropConsumer) throws CommandSyntaxException { + if (!(entity instanceof LivingEntity)) { + throw LootCommand.ERROR_NO_LOOT_TABLE.create(entity.getDisplayName()); + } else { +- ResourceLocation resourcelocation = ((LivingEntity) entity).getLootTable(); +- CommandSourceStack commandsourcestack = (CommandSourceStack) commandcontext.getSource(); +- LootParams.Builder lootparams_builder = new LootParams.Builder(commandsourcestack.getLevel()); +- Entity entity1 = commandsourcestack.getEntity(); ++ ResourceLocation minecraftkey = ((LivingEntity) entity).getLootTable(); ++ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) context.getSource(); ++ LootParams.Builder lootparams_a = new LootParams.Builder(commandlistenerwrapper.getLevel()); ++ Entity entity1 = commandlistenerwrapper.getEntity(); + + if (entity1 instanceof Player) { +- Player player = (Player) entity1; ++ Player entityhuman = (Player) entity1; + +- lootparams_builder.withParameter(LootContextParams.LAST_DAMAGE_PLAYER, player); ++ lootparams_a.withParameter(LootContextParams.LAST_DAMAGE_PLAYER, entityhuman); + } + +- lootparams_builder.withParameter(LootContextParams.DAMAGE_SOURCE, entity.damageSources().magic()); +- lootparams_builder.withOptionalParameter(LootContextParams.DIRECT_KILLER_ENTITY, entity1); +- lootparams_builder.withOptionalParameter(LootContextParams.KILLER_ENTITY, entity1); +- lootparams_builder.withParameter(LootContextParams.THIS_ENTITY, entity); +- lootparams_builder.withParameter(LootContextParams.ORIGIN, commandsourcestack.getPosition()); +- LootParams lootparams = lootparams_builder.create(LootContextParamSets.ENTITY); +- LootTable loottable = commandsourcestack.getServer().getLootData().getLootTable(resourcelocation); ++ lootparams_a.withParameter(LootContextParams.DAMAGE_SOURCE, entity.damageSources().magic()); ++ lootparams_a.withOptionalParameter(LootContextParams.DIRECT_KILLER_ENTITY, entity1); ++ lootparams_a.withOptionalParameter(LootContextParams.KILLER_ENTITY, entity1); ++ lootparams_a.withParameter(LootContextParams.THIS_ENTITY, entity); ++ lootparams_a.withParameter(LootContextParams.ORIGIN, commandlistenerwrapper.getPosition()); ++ LootParams lootparams = lootparams_a.create(LootContextParamSets.ENTITY); ++ LootTable loottable = commandlistenerwrapper.getServer().getLootData().getLootTable(minecraftkey); + List list = loottable.getRandomItems(lootparams); + +- return lootcommand_dropconsumer.accept(commandcontext, list, (list1) -> { +- callback(commandsourcestack, list1, resourcelocation); ++ return dropConsumer.accept(context, list, (list1) -> { ++ callback(commandlistenerwrapper, list1, minecraftkey); + }); + } + } + +- private static int dropChestLoot(CommandContext commandcontext, ResourceLocation resourcelocation, LootCommand.DropConsumer lootcommand_dropconsumer) throws CommandSyntaxException { +- CommandSourceStack commandsourcestack = (CommandSourceStack) commandcontext.getSource(); +- LootParams lootparams = (new LootParams.Builder(commandsourcestack.getLevel())).withOptionalParameter(LootContextParams.THIS_ENTITY, commandsourcestack.getEntity()).withParameter(LootContextParams.ORIGIN, commandsourcestack.getPosition()).create(LootContextParamSets.CHEST); ++ private static int dropChestLoot(CommandContext context, ResourceLocation lootTable, LootCommand.DropConsumer dropConsumer) throws CommandSyntaxException { ++ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) context.getSource(); ++ LootParams lootparams = (new LootParams.Builder(commandlistenerwrapper.getLevel())).withOptionalParameter(LootContextParams.THIS_ENTITY, commandlistenerwrapper.getEntity()).withParameter(LootContextParams.ORIGIN, commandlistenerwrapper.getPosition()).create(LootContextParamSets.CHEST); + +- return drop(commandcontext, resourcelocation, lootparams, lootcommand_dropconsumer); ++ return drop(context, lootTable, lootparams, dropConsumer); + } + +- private static int dropFishingLoot(CommandContext commandcontext, ResourceLocation resourcelocation, BlockPos blockpos, ItemStack itemstack, LootCommand.DropConsumer lootcommand_dropconsumer) throws CommandSyntaxException { +- CommandSourceStack commandsourcestack = (CommandSourceStack) commandcontext.getSource(); +- LootParams lootparams = (new LootParams.Builder(commandsourcestack.getLevel())).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockpos)).withParameter(LootContextParams.TOOL, itemstack).withOptionalParameter(LootContextParams.THIS_ENTITY, commandsourcestack.getEntity()).create(LootContextParamSets.FISHING); ++ private static int dropFishingLoot(CommandContext context, ResourceLocation lootTable, BlockPos pos, ItemStack tool, LootCommand.DropConsumer dropConsumer) throws CommandSyntaxException { ++ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) context.getSource(); ++ LootParams lootparams = (new LootParams.Builder(commandlistenerwrapper.getLevel())).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos)).withParameter(LootContextParams.TOOL, tool).withOptionalParameter(LootContextParams.THIS_ENTITY, commandlistenerwrapper.getEntity()).create(LootContextParamSets.FISHING); + +- return drop(commandcontext, resourcelocation, lootparams, lootcommand_dropconsumer); ++ return drop(context, lootTable, lootparams, dropConsumer); + } + +- private static int drop(CommandContext commandcontext, ResourceLocation resourcelocation, LootParams lootparams, LootCommand.DropConsumer lootcommand_dropconsumer) throws CommandSyntaxException { +- CommandSourceStack commandsourcestack = (CommandSourceStack) commandcontext.getSource(); +- LootTable loottable = commandsourcestack.getServer().getLootData().getLootTable(resourcelocation); +- List list = loottable.getRandomItems(lootparams); ++ private static int drop(CommandContext context, ResourceLocation lootTable, LootParams params, LootCommand.DropConsumer dropConsumer) throws CommandSyntaxException { ++ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) context.getSource(); ++ LootTable loottable = commandlistenerwrapper.getServer().getLootData().getLootTable(lootTable); ++ List list = loottable.getRandomItems(params); + +- return lootcommand_dropconsumer.accept(commandcontext, list, (list1) -> { +- callback(commandsourcestack, list1); ++ return dropConsumer.accept(context, list, (list1) -> { ++ callback(commandlistenerwrapper, list1); + }); + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/commands/PlaceCommand.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/commands/PlaceCommand.java.patch new file mode 100644 index 0000000000..6a92ffd458 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/commands/PlaceCommand.java.patch @@ -0,0 +1,208 @@ +--- a/net/minecraft/server/commands/PlaceCommand.java ++++ b/net/minecraft/server/commands/PlaceCommand.java +@@ -12,7 +12,6 @@ + import java.util.Optional; + import net.minecraft.ResourceLocationException; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.SharedSuggestionProvider; + import net.minecraft.commands.arguments.ResourceKeyArgument; + import net.minecraft.commands.arguments.ResourceLocationArgument; +@@ -59,135 +58,136 @@ + + public PlaceCommand() {} + +- public static void register(CommandDispatcher commanddispatcher) { +- commanddispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) Commands.literal("place").requires((commandsourcestack) -> { +- return commandsourcestack.hasPermission(2); +- })).then(Commands.literal("feature").then(((RequiredArgumentBuilder) Commands.argument("feature", ResourceKeyArgument.key(Registries.CONFIGURED_FEATURE)).executes((commandcontext) -> { ++ public static void register(CommandDispatcher dispatcher) { ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("place").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).then(net.minecraft.commands.Commands.literal("feature").then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("feature", ResourceKeyArgument.key(Registries.CONFIGURED_FEATURE)).executes((commandcontext) -> { + return placeFeature((CommandSourceStack) commandcontext.getSource(), ResourceKeyArgument.getConfiguredFeature(commandcontext, "feature"), BlockPos.containing(((CommandSourceStack) commandcontext.getSource()).getPosition())); +- })).then(Commands.argument("pos", BlockPosArgument.blockPos()).executes((commandcontext) -> { ++ })).then(net.minecraft.commands.Commands.argument("pos", BlockPosArgument.blockPos()).executes((commandcontext) -> { + return placeFeature((CommandSourceStack) commandcontext.getSource(), ResourceKeyArgument.getConfiguredFeature(commandcontext, "feature"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos")); +- }))))).then(Commands.literal("jigsaw").then(Commands.argument("pool", ResourceKeyArgument.key(Registries.TEMPLATE_POOL)).then(Commands.argument("target", ResourceLocationArgument.id()).then(((RequiredArgumentBuilder) Commands.argument("max_depth", IntegerArgumentType.integer(1, 7)).executes((commandcontext) -> { ++ }))))).then(net.minecraft.commands.Commands.literal("jigsaw").then(net.minecraft.commands.Commands.argument("pool", ResourceKeyArgument.key(Registries.TEMPLATE_POOL)).then(net.minecraft.commands.Commands.argument("target", ResourceLocationArgument.id()).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("max_depth", IntegerArgumentType.integer(1, 7)).executes((commandcontext) -> { + return placeJigsaw((CommandSourceStack) commandcontext.getSource(), ResourceKeyArgument.getStructureTemplatePool(commandcontext, "pool"), ResourceLocationArgument.getId(commandcontext, "target"), IntegerArgumentType.getInteger(commandcontext, "max_depth"), BlockPos.containing(((CommandSourceStack) commandcontext.getSource()).getPosition())); +- })).then(Commands.argument("position", BlockPosArgument.blockPos()).executes((commandcontext) -> { ++ })).then(net.minecraft.commands.Commands.argument("position", BlockPosArgument.blockPos()).executes((commandcontext) -> { + return placeJigsaw((CommandSourceStack) commandcontext.getSource(), ResourceKeyArgument.getStructureTemplatePool(commandcontext, "pool"), ResourceLocationArgument.getId(commandcontext, "target"), IntegerArgumentType.getInteger(commandcontext, "max_depth"), BlockPosArgument.getLoadedBlockPos(commandcontext, "position")); +- }))))))).then(Commands.literal("structure").then(((RequiredArgumentBuilder) Commands.argument("structure", ResourceKeyArgument.key(Registries.STRUCTURE)).executes((commandcontext) -> { ++ }))))))).then(net.minecraft.commands.Commands.literal("structure").then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("structure", ResourceKeyArgument.key(Registries.STRUCTURE)).executes((commandcontext) -> { + return placeStructure((CommandSourceStack) commandcontext.getSource(), ResourceKeyArgument.getStructure(commandcontext, "structure"), BlockPos.containing(((CommandSourceStack) commandcontext.getSource()).getPosition())); +- })).then(Commands.argument("pos", BlockPosArgument.blockPos()).executes((commandcontext) -> { ++ })).then(net.minecraft.commands.Commands.argument("pos", BlockPosArgument.blockPos()).executes((commandcontext) -> { + return placeStructure((CommandSourceStack) commandcontext.getSource(), ResourceKeyArgument.getStructure(commandcontext, "structure"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos")); +- }))))).then(Commands.literal("template").then(((RequiredArgumentBuilder) Commands.argument("template", ResourceLocationArgument.id()).suggests(PlaceCommand.SUGGEST_TEMPLATES).executes((commandcontext) -> { ++ }))))).then(net.minecraft.commands.Commands.literal("template").then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("template", ResourceLocationArgument.id()).suggests(PlaceCommand.SUGGEST_TEMPLATES).executes((commandcontext) -> { + return placeTemplate((CommandSourceStack) commandcontext.getSource(), ResourceLocationArgument.getId(commandcontext, "template"), BlockPos.containing(((CommandSourceStack) commandcontext.getSource()).getPosition()), Rotation.NONE, Mirror.NONE, 1.0F, 0); +- })).then(((RequiredArgumentBuilder) Commands.argument("pos", BlockPosArgument.blockPos()).executes((commandcontext) -> { ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("pos", BlockPosArgument.blockPos()).executes((commandcontext) -> { + return placeTemplate((CommandSourceStack) commandcontext.getSource(), ResourceLocationArgument.getId(commandcontext, "template"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), Rotation.NONE, Mirror.NONE, 1.0F, 0); +- })).then(((RequiredArgumentBuilder) Commands.argument("rotation", TemplateRotationArgument.templateRotation()).executes((commandcontext) -> { ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("rotation", TemplateRotationArgument.templateRotation()).executes((commandcontext) -> { + return placeTemplate((CommandSourceStack) commandcontext.getSource(), ResourceLocationArgument.getId(commandcontext, "template"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), TemplateRotationArgument.getRotation(commandcontext, "rotation"), Mirror.NONE, 1.0F, 0); +- })).then(((RequiredArgumentBuilder) Commands.argument("mirror", TemplateMirrorArgument.templateMirror()).executes((commandcontext) -> { ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("mirror", TemplateMirrorArgument.templateMirror()).executes((commandcontext) -> { + return placeTemplate((CommandSourceStack) commandcontext.getSource(), ResourceLocationArgument.getId(commandcontext, "template"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), TemplateRotationArgument.getRotation(commandcontext, "rotation"), TemplateMirrorArgument.getMirror(commandcontext, "mirror"), 1.0F, 0); +- })).then(((RequiredArgumentBuilder) Commands.argument("integrity", FloatArgumentType.floatArg(0.0F, 1.0F)).executes((commandcontext) -> { ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("integrity", FloatArgumentType.floatArg(0.0F, 1.0F)).executes((commandcontext) -> { + return placeTemplate((CommandSourceStack) commandcontext.getSource(), ResourceLocationArgument.getId(commandcontext, "template"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), TemplateRotationArgument.getRotation(commandcontext, "rotation"), TemplateMirrorArgument.getMirror(commandcontext, "mirror"), FloatArgumentType.getFloat(commandcontext, "integrity"), 0); +- })).then(Commands.argument("seed", IntegerArgumentType.integer()).executes((commandcontext) -> { ++ })).then(net.minecraft.commands.Commands.argument("seed", IntegerArgumentType.integer()).executes((commandcontext) -> { + return placeTemplate((CommandSourceStack) commandcontext.getSource(), ResourceLocationArgument.getId(commandcontext, "template"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), TemplateRotationArgument.getRotation(commandcontext, "rotation"), TemplateMirrorArgument.getMirror(commandcontext, "mirror"), FloatArgumentType.getFloat(commandcontext, "integrity"), IntegerArgumentType.getInteger(commandcontext, "seed")); + }))))))))); + } + +- public static int placeFeature(CommandSourceStack commandsourcestack, Holder.Reference> holder_reference, BlockPos blockpos) throws CommandSyntaxException { +- ServerLevel serverlevel = commandsourcestack.getLevel(); +- ConfiguredFeature configuredfeature = (ConfiguredFeature) holder_reference.value(); +- ChunkPos chunkpos = new ChunkPos(blockpos); ++ public static int placeFeature(CommandSourceStack source, Holder.Reference> feature, BlockPos pos) throws CommandSyntaxException { ++ ServerLevel worldserver = source.getLevel(); ++ ConfiguredFeature worldgenfeatureconfigured = (ConfiguredFeature) feature.value(); ++ ChunkPos chunkcoordintpair = new ChunkPos(pos); + +- checkLoaded(serverlevel, new ChunkPos(chunkpos.x - 1, chunkpos.z - 1), new ChunkPos(chunkpos.x + 1, chunkpos.z + 1)); +- if (!configuredfeature.place(serverlevel, serverlevel.getChunkSource().getGenerator(), serverlevel.getRandom(), blockpos)) { ++ checkLoaded(worldserver, new ChunkPos(chunkcoordintpair.x - 1, chunkcoordintpair.z - 1), new ChunkPos(chunkcoordintpair.x + 1, chunkcoordintpair.z + 1)); ++ if (!worldgenfeatureconfigured.place(worldserver, worldserver.getChunkSource().getGenerator(), worldserver.getRandom(), pos)) { + throw PlaceCommand.ERROR_FEATURE_FAILED.create(); + } else { +- String s = holder_reference.key().location().toString(); ++ String s = feature.key().location().toString(); + +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.place.feature.success", s, blockpos.getX(), blockpos.getY(), blockpos.getZ()); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.place.feature.success", s, pos.getX(), pos.getY(), pos.getZ()); + }, true); + return 1; + } + } + +- public static int placeJigsaw(CommandSourceStack commandsourcestack, Holder holder, ResourceLocation resourcelocation, int i, BlockPos blockpos) throws CommandSyntaxException { +- ServerLevel serverlevel = commandsourcestack.getLevel(); ++ public static int placeJigsaw(CommandSourceStack source, Holder templatePool, ResourceLocation target, int maxDepth, BlockPos pos) throws CommandSyntaxException { ++ ServerLevel worldserver = source.getLevel(); + +- if (!JigsawPlacement.generateJigsaw(serverlevel, holder, resourcelocation, i, blockpos, false)) { ++ if (!JigsawPlacement.generateJigsaw(worldserver, templatePool, target, maxDepth, pos, false)) { + throw PlaceCommand.ERROR_JIGSAW_FAILED.create(); + } else { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.place.jigsaw.success", blockpos.getX(), blockpos.getY(), blockpos.getZ()); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.place.jigsaw.success", pos.getX(), pos.getY(), pos.getZ()); + }, true); + return 1; + } + } + +- public static int placeStructure(CommandSourceStack commandsourcestack, Holder.Reference holder_reference, BlockPos blockpos) throws CommandSyntaxException { +- ServerLevel serverlevel = commandsourcestack.getLevel(); +- Structure structure = (Structure) holder_reference.value(); +- ChunkGenerator chunkgenerator = serverlevel.getChunkSource().getGenerator(); +- StructureStart structurestart = structure.generate(commandsourcestack.registryAccess(), chunkgenerator, chunkgenerator.getBiomeSource(), serverlevel.getChunkSource().randomState(), serverlevel.getStructureManager(), serverlevel.getSeed(), new ChunkPos(blockpos), 0, serverlevel, (holder) -> { ++ public static int placeStructure(CommandSourceStack source, Holder.Reference structure, BlockPos pos) throws CommandSyntaxException { ++ ServerLevel worldserver = source.getLevel(); ++ Structure structure1 = (Structure) structure.value(); ++ ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator(); ++ StructureStart structurestart = structure1.generate(source.registryAccess(), chunkgenerator, chunkgenerator.getBiomeSource(), worldserver.getChunkSource().randomState(), worldserver.getStructureManager(), worldserver.getSeed(), new ChunkPos(pos), 0, worldserver, (holder) -> { + return true; + }); + + if (!structurestart.isValid()) { + throw PlaceCommand.ERROR_STRUCTURE_FAILED.create(); + } else { +- BoundingBox boundingbox = structurestart.getBoundingBox(); +- ChunkPos chunkpos = new ChunkPos(SectionPos.blockToSectionCoord(boundingbox.minX()), SectionPos.blockToSectionCoord(boundingbox.minZ())); +- ChunkPos chunkpos1 = new ChunkPos(SectionPos.blockToSectionCoord(boundingbox.maxX()), SectionPos.blockToSectionCoord(boundingbox.maxZ())); ++ structurestart.generationEventCause = org.bukkit.event.world.AsyncStructureGenerateEvent.Cause.COMMAND; // CraftBukkit - set AsyncStructureGenerateEvent.Cause.COMMAND as generation cause ++ BoundingBox structureboundingbox = structurestart.getBoundingBox(); ++ ChunkPos chunkcoordintpair = new ChunkPos(SectionPos.blockToSectionCoord(structureboundingbox.minX()), SectionPos.blockToSectionCoord(structureboundingbox.minZ())); ++ ChunkPos chunkcoordintpair1 = new ChunkPos(SectionPos.blockToSectionCoord(structureboundingbox.maxX()), SectionPos.blockToSectionCoord(structureboundingbox.maxZ())); + +- checkLoaded(serverlevel, chunkpos, chunkpos1); +- ChunkPos.rangeClosed(chunkpos, chunkpos1).forEach((chunkpos2) -> { +- structurestart.placeInChunk(serverlevel, serverlevel.structureManager(), chunkgenerator, serverlevel.getRandom(), new BoundingBox(chunkpos2.getMinBlockX(), serverlevel.getMinBuildHeight(), chunkpos2.getMinBlockZ(), chunkpos2.getMaxBlockX(), serverlevel.getMaxBuildHeight(), chunkpos2.getMaxBlockZ()), chunkpos2); ++ checkLoaded(worldserver, chunkcoordintpair, chunkcoordintpair1); ++ ChunkPos.rangeClosed(chunkcoordintpair, chunkcoordintpair1).forEach((chunkcoordintpair2) -> { ++ structurestart.placeInChunk(worldserver, worldserver.structureManager(), chunkgenerator, worldserver.getRandom(), new BoundingBox(chunkcoordintpair2.getMinBlockX(), worldserver.getMinBuildHeight(), chunkcoordintpair2.getMinBlockZ(), chunkcoordintpair2.getMaxBlockX(), worldserver.getMaxBuildHeight(), chunkcoordintpair2.getMaxBlockZ()), chunkcoordintpair2); + }); +- String s = holder_reference.key().location().toString(); ++ String s = structure.key().location().toString(); + +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.place.structure.success", s, blockpos.getX(), blockpos.getY(), blockpos.getZ()); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.place.structure.success", s, pos.getX(), pos.getY(), pos.getZ()); + }, true); + return 1; + } + } + +- public static int placeTemplate(CommandSourceStack commandsourcestack, ResourceLocation resourcelocation, BlockPos blockpos, Rotation rotation, Mirror mirror, float f, int i) throws CommandSyntaxException { +- ServerLevel serverlevel = commandsourcestack.getLevel(); +- StructureTemplateManager structuretemplatemanager = serverlevel.getStructureManager(); ++ public static int placeTemplate(CommandSourceStack source, ResourceLocation template, BlockPos pos, Rotation rotation, Mirror mirror, float integrity, int seed) throws CommandSyntaxException { ++ ServerLevel worldserver = source.getLevel(); ++ StructureTemplateManager structuretemplatemanager = worldserver.getStructureManager(); + + Optional optional; + + try { +- optional = structuretemplatemanager.get(resourcelocation); +- } catch (ResourceLocationException resourcelocationexception) { +- throw PlaceCommand.ERROR_TEMPLATE_INVALID.create(resourcelocation); ++ optional = structuretemplatemanager.get(template); ++ } catch (ResourceLocationException resourcekeyinvalidexception) { ++ throw PlaceCommand.ERROR_TEMPLATE_INVALID.create(template); + } + + if (optional.isEmpty()) { +- throw PlaceCommand.ERROR_TEMPLATE_INVALID.create(resourcelocation); ++ throw PlaceCommand.ERROR_TEMPLATE_INVALID.create(template); + } else { +- StructureTemplate structuretemplate = (StructureTemplate) optional.get(); ++ StructureTemplate definedstructure = (StructureTemplate) optional.get(); + +- checkLoaded(serverlevel, new ChunkPos(blockpos), new ChunkPos(blockpos.offset(structuretemplate.getSize()))); +- StructurePlaceSettings structureplacesettings = (new StructurePlaceSettings()).setMirror(mirror).setRotation(rotation); ++ checkLoaded(worldserver, new ChunkPos(pos), new ChunkPos(pos.offset(definedstructure.getSize()))); ++ StructurePlaceSettings definedstructureinfo = (new StructurePlaceSettings()).setMirror(mirror).setRotation(rotation); + +- if (f < 1.0F) { +- structureplacesettings.clearProcessors().addProcessor(new BlockRotProcessor(f)).setRandom(StructureBlockEntity.createRandom((long) i)); ++ if (integrity < 1.0F) { ++ definedstructureinfo.clearProcessors().addProcessor(new BlockRotProcessor(integrity)).setRandom(StructureBlockEntity.createRandom((long) seed)); + } + +- boolean flag = structuretemplate.placeInWorld(serverlevel, blockpos, blockpos, structureplacesettings, StructureBlockEntity.createRandom((long) i), 2); ++ boolean flag = definedstructure.placeInWorld(worldserver, pos, pos, definedstructureinfo, StructureBlockEntity.createRandom((long) seed), 2); + + if (!flag) { + throw PlaceCommand.ERROR_TEMPLATE_FAILED.create(); + } else { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.place.template.success", Component.translationArg(resourcelocation), blockpos.getX(), blockpos.getY(), blockpos.getZ()); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.place.template.success", Component.translationArg(template), pos.getX(), pos.getY(), pos.getZ()); + }, true); + return 1; + } + } + } + +- private static void checkLoaded(ServerLevel serverlevel, ChunkPos chunkpos, ChunkPos chunkpos1) throws CommandSyntaxException { +- if (ChunkPos.rangeClosed(chunkpos, chunkpos1).filter((chunkpos2) -> { +- return !serverlevel.isLoaded(chunkpos2.getWorldPosition()); ++ private static void checkLoaded(ServerLevel level, ChunkPos start, ChunkPos end) throws CommandSyntaxException { ++ if (ChunkPos.rangeClosed(start, end).filter((chunkcoordintpair2) -> { ++ return !level.isLoaded(chunkcoordintpair2.getWorldPosition()); + }).findAny().isPresent()) { + throw BlockPosArgument.ERROR_NOT_LOADED.create(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/commands/ReloadCommand.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/commands/ReloadCommand.java.patch new file mode 100644 index 0000000000..22bbb2b63b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/commands/ReloadCommand.java.patch @@ -0,0 +1,81 @@ +--- a/net/minecraft/server/commands/ReloadCommand.java ++++ b/net/minecraft/server/commands/ReloadCommand.java +@@ -7,7 +7,6 @@ + import java.util.Collection; + import java.util.Iterator; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.network.chat.Component; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.packs.repository.PackRepository; +@@ -20,19 +19,19 @@ + + public ReloadCommand() {} + +- public static void reloadPacks(Collection collection, CommandSourceStack commandsourcestack) { +- commandsourcestack.getServer().reloadResources(collection).exceptionally((throwable) -> { ++ public static void reloadPacks(Collection selectedIds, CommandSourceStack source) { ++ source.getServer().reloadResources(selectedIds).exceptionally((throwable) -> { + ReloadCommand.LOGGER.warn("Failed to execute reload", throwable); +- commandsourcestack.sendFailure(Component.translatable("commands.reload.failure")); ++ source.sendFailure(Component.translatable("commands.reload.failure")); + return null; + }); + } + +- private static Collection discoverNewPacks(PackRepository packrepository, WorldData worlddata, Collection collection) { +- packrepository.reload(); +- Collection collection1 = Lists.newArrayList(collection); +- Collection collection2 = worlddata.getDataConfiguration().dataPacks().getDisabled(); +- Iterator iterator = packrepository.getAvailableIds().iterator(); ++ private static Collection discoverNewPacks(PackRepository packRepository, WorldData worldData, Collection selectedIds) { ++ packRepository.reload(); ++ Collection collection1 = Lists.newArrayList(selectedIds); ++ Collection collection2 = worldData.getDataConfiguration().dataPacks().getDisabled(); ++ Iterator iterator = packRepository.getAvailableIds().iterator(); + + while (iterator.hasNext()) { + String s = (String) iterator.next(); +@@ -45,21 +44,31 @@ + return collection1; + } + +- public static void register(CommandDispatcher commanddispatcher) { +- commanddispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) Commands.literal("reload").requires((commandsourcestack) -> { +- return commandsourcestack.hasPermission(2); ++ // CraftBukkit start ++ public static void reload(MinecraftServer minecraftserver) { ++ PackRepository resourcepackrepository = minecraftserver.getPackRepository(); ++ WorldData savedata = minecraftserver.getWorldData(); ++ Collection collection = resourcepackrepository.getSelectedIds(); ++ Collection collection1 = discoverNewPacks(resourcepackrepository, savedata, collection); ++ minecraftserver.reloadResources(collection1); ++ } ++ // CraftBukkit end ++ ++ public static void register(CommandDispatcher dispatcher) { ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("reload").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); + })).executes((commandcontext) -> { +- CommandSourceStack commandsourcestack = (CommandSourceStack) commandcontext.getSource(); +- MinecraftServer minecraftserver = commandsourcestack.getServer(); +- PackRepository packrepository = minecraftserver.getPackRepository(); +- WorldData worlddata = minecraftserver.getWorldData(); +- Collection collection = packrepository.getSelectedIds(); +- Collection collection1 = discoverNewPacks(packrepository, worlddata, collection); ++ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) commandcontext.getSource(); ++ MinecraftServer minecraftserver = commandlistenerwrapper.getServer(); ++ PackRepository resourcepackrepository = minecraftserver.getPackRepository(); ++ WorldData savedata = minecraftserver.getWorldData(); ++ Collection collection = resourcepackrepository.getSelectedIds(); ++ Collection collection1 = discoverNewPacks(resourcepackrepository, savedata, collection); + +- commandsourcestack.sendSuccess(() -> { ++ commandlistenerwrapper.sendSuccess(() -> { + return Component.translatable("commands.reload.success"); + }, true); +- reloadPacks(collection1, commandsourcestack); ++ reloadPacks(collection1, commandlistenerwrapper); + return 0; + })); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/commands/ScheduleCommand.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/commands/ScheduleCommand.java.patch new file mode 100644 index 0000000000..e215303389 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/commands/ScheduleCommand.java.patch @@ -0,0 +1,108 @@ +--- a/net/minecraft/server/commands/ScheduleCommand.java ++++ b/net/minecraft/server/commands/ScheduleCommand.java +@@ -13,11 +13,9 @@ + import com.mojang.datafixers.util.Pair; + import java.util.Collection; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.SharedSuggestionProvider; + import net.minecraft.commands.arguments.TimeArgument; + import net.minecraft.commands.arguments.item.FunctionArgument; +-import net.minecraft.commands.functions.CommandFunction; + import net.minecraft.network.chat.Component; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MinecraftServer; +@@ -37,63 +35,63 @@ + + public ScheduleCommand() {} + +- public static void register(CommandDispatcher commanddispatcher) { +- commanddispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) Commands.literal("schedule").requires((commandsourcestack) -> { +- return commandsourcestack.hasPermission(2); +- })).then(Commands.literal("function").then(Commands.argument("function", FunctionArgument.functions()).suggests(FunctionCommand.SUGGEST_FUNCTION).then(((RequiredArgumentBuilder) ((RequiredArgumentBuilder) Commands.argument("time", TimeArgument.time()).executes((commandcontext) -> { ++ public static void register(CommandDispatcher dispatcher) { ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("schedule").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).then(net.minecraft.commands.Commands.literal("function").then(net.minecraft.commands.Commands.argument("function", FunctionArgument.functions()).suggests(FunctionCommand.SUGGEST_FUNCTION).then(((RequiredArgumentBuilder) ((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("time", TimeArgument.time()).executes((commandcontext) -> { + return schedule((CommandSourceStack) commandcontext.getSource(), FunctionArgument.getFunctionOrTag(commandcontext, "function"), IntegerArgumentType.getInteger(commandcontext, "time"), true); +- })).then(Commands.literal("append").executes((commandcontext) -> { ++ })).then(net.minecraft.commands.Commands.literal("append").executes((commandcontext) -> { + return schedule((CommandSourceStack) commandcontext.getSource(), FunctionArgument.getFunctionOrTag(commandcontext, "function"), IntegerArgumentType.getInteger(commandcontext, "time"), false); +- }))).then(Commands.literal("replace").executes((commandcontext) -> { ++ }))).then(net.minecraft.commands.Commands.literal("replace").executes((commandcontext) -> { + return schedule((CommandSourceStack) commandcontext.getSource(), FunctionArgument.getFunctionOrTag(commandcontext, "function"), IntegerArgumentType.getInteger(commandcontext, "time"), true); +- })))))).then(Commands.literal("clear").then(Commands.argument("function", StringArgumentType.greedyString()).suggests(ScheduleCommand.SUGGEST_SCHEDULE).executes((commandcontext) -> { ++ })))))).then(net.minecraft.commands.Commands.literal("clear").then(net.minecraft.commands.Commands.argument("function", StringArgumentType.greedyString()).suggests(ScheduleCommand.SUGGEST_SCHEDULE).executes((commandcontext) -> { + return remove((CommandSourceStack) commandcontext.getSource(), StringArgumentType.getString(commandcontext, "function")); + })))); + } + +- private static int schedule(CommandSourceStack commandsourcestack, Pair, Collection>>> pair, int i, boolean flag) throws CommandSyntaxException { +- if (i == 0) { ++ private static int schedule(CommandSourceStack source, Pair, Collection>>> function, int time, boolean append) throws CommandSyntaxException { ++ if (time == 0) { + throw ScheduleCommand.ERROR_SAME_TICK.create(); + } else { +- long j = commandsourcestack.getLevel().getGameTime() + (long) i; +- ResourceLocation resourcelocation = (ResourceLocation) pair.getFirst(); +- TimerQueue timerqueue = commandsourcestack.getServer().getWorldData().overworldData().getScheduledEvents(); ++ long j = source.getLevel().getGameTime() + (long) time; ++ ResourceLocation minecraftkey = (ResourceLocation) function.getFirst(); ++ TimerQueue customfunctioncallbacktimerqueue = source.getLevel().serverLevelData.overworldData().getScheduledEvents(); // CraftBukkit - SPIGOT-6667: Use world specific function timer + +- ((Either) pair.getSecond()).ifLeft((commandfunction) -> { +- String s = resourcelocation.toString(); ++ ((Either) function.getSecond()).ifLeft((net_minecraft_commands_functions_commandfunction) -> { ++ String s = minecraftkey.toString(); + +- if (flag) { +- timerqueue.remove(s); ++ if (append) { ++ customfunctioncallbacktimerqueue.remove(s); + } + +- timerqueue.schedule(s, j, new FunctionCallback(resourcelocation)); +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.schedule.created.function", Component.translationArg(resourcelocation), i, j); ++ customfunctioncallbacktimerqueue.schedule(s, j, new FunctionCallback(minecraftkey)); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.schedule.created.function", Component.translationArg(minecraftkey), time, j); + }, true); + }).ifRight((collection) -> { +- String s = "#" + resourcelocation; ++ String s = "#" + minecraftkey; + +- if (flag) { +- timerqueue.remove(s); ++ if (append) { ++ customfunctioncallbacktimerqueue.remove(s); + } + +- timerqueue.schedule(s, j, new FunctionTagCallback(resourcelocation)); +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.schedule.created.tag", Component.translationArg(resourcelocation), i, j); ++ customfunctioncallbacktimerqueue.schedule(s, j, new FunctionTagCallback(minecraftkey)); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.schedule.created.tag", Component.translationArg(minecraftkey), time, j); + }, true); + }); + return Math.floorMod(j, Integer.MAX_VALUE); + } + } + +- private static int remove(CommandSourceStack commandsourcestack, String s) throws CommandSyntaxException { +- int i = commandsourcestack.getServer().getWorldData().overworldData().getScheduledEvents().remove(s); ++ private static int remove(CommandSourceStack source, String function) throws CommandSyntaxException { ++ int i = source.getServer().getWorldData().overworldData().getScheduledEvents().remove(function); + + if (i == 0) { +- throw ScheduleCommand.ERROR_CANT_REMOVE.create(s); ++ throw ScheduleCommand.ERROR_CANT_REMOVE.create(function); + } else { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.schedule.cleared.success", i, s); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.schedule.cleared.success", i, function); + }, true); + return i; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/commands/SetSpawnCommand.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/commands/SetSpawnCommand.java.patch new file mode 100644 index 0000000000..da58e30d0a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/commands/SetSpawnCommand.java.patch @@ -0,0 +1,70 @@ +--- a/net/minecraft/server/commands/SetSpawnCommand.java ++++ b/net/minecraft/server/commands/SetSpawnCommand.java +@@ -7,7 +7,6 @@ + import java.util.Collections; + import java.util.Iterator; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.arguments.AngleArgument; + import net.minecraft.commands.arguments.EntityArgument; + import net.minecraft.commands.arguments.coordinates.BlockPosArgument; +@@ -21,42 +20,42 @@ + + public SetSpawnCommand() {} + +- public static void register(CommandDispatcher commanddispatcher) { +- commanddispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) Commands.literal("spawnpoint").requires((commandsourcestack) -> { +- return commandsourcestack.hasPermission(2); ++ public static void register(CommandDispatcher dispatcher) { ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("spawnpoint").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); + })).executes((commandcontext) -> { + return setSpawn((CommandSourceStack) commandcontext.getSource(), Collections.singleton(((CommandSourceStack) commandcontext.getSource()).getPlayerOrException()), BlockPos.containing(((CommandSourceStack) commandcontext.getSource()).getPosition()), 0.0F); +- })).then(((RequiredArgumentBuilder) Commands.argument("targets", EntityArgument.players()).executes((commandcontext) -> { ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("targets", EntityArgument.players()).executes((commandcontext) -> { + return setSpawn((CommandSourceStack) commandcontext.getSource(), EntityArgument.getPlayers(commandcontext, "targets"), BlockPos.containing(((CommandSourceStack) commandcontext.getSource()).getPosition()), 0.0F); +- })).then(((RequiredArgumentBuilder) Commands.argument("pos", BlockPosArgument.blockPos()).executes((commandcontext) -> { ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("pos", BlockPosArgument.blockPos()).executes((commandcontext) -> { + return setSpawn((CommandSourceStack) commandcontext.getSource(), EntityArgument.getPlayers(commandcontext, "targets"), BlockPosArgument.getSpawnablePos(commandcontext, "pos"), 0.0F); +- })).then(Commands.argument("angle", AngleArgument.angle()).executes((commandcontext) -> { ++ })).then(net.minecraft.commands.Commands.argument("angle", AngleArgument.angle()).executes((commandcontext) -> { + return setSpawn((CommandSourceStack) commandcontext.getSource(), EntityArgument.getPlayers(commandcontext, "targets"), BlockPosArgument.getSpawnablePos(commandcontext, "pos"), AngleArgument.getAngle(commandcontext, "angle")); + }))))); + } + +- private static int setSpawn(CommandSourceStack commandsourcestack, Collection collection, BlockPos blockpos, float f) { +- ResourceKey resourcekey = commandsourcestack.getLevel().dimension(); +- Iterator iterator = collection.iterator(); ++ private static int setSpawn(CommandSourceStack source, Collection targets, BlockPos pos, float angle) { ++ ResourceKey resourcekey = source.getLevel().dimension(); ++ Iterator iterator = targets.iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- serverplayer.setRespawnPosition(resourcekey, blockpos, f, true, false); ++ entityplayer.setRespawnPosition(resourcekey, pos, angle, true, false, org.bukkit.event.player.PlayerSpawnChangeEvent.Cause.COMMAND); // CraftBukkit + } + + String s = resourcekey.location().toString(); + +- if (collection.size() == 1) { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.spawnpoint.success.single", blockpos.getX(), blockpos.getY(), blockpos.getZ(), f, s, ((ServerPlayer) collection.iterator().next()).getDisplayName()); ++ if (targets.size() == 1) { ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.spawnpoint.success.single", pos.getX(), pos.getY(), pos.getZ(), angle, s, ((ServerPlayer) targets.iterator().next()).getDisplayName()); + }, true); + } else { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.spawnpoint.success.multiple", blockpos.getX(), blockpos.getY(), blockpos.getZ(), f, s, collection.size()); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.spawnpoint.success.multiple", pos.getX(), pos.getY(), pos.getZ(), angle, s, targets.size()); + }, true); + } + +- return collection.size(); ++ return targets.size(); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/commands/SpreadPlayersCommand.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/commands/SpreadPlayersCommand.java.patch new file mode 100644 index 0000000000..7e9fbb2e3f --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/commands/SpreadPlayersCommand.java.patch @@ -0,0 +1,374 @@ +--- a/net/minecraft/server/commands/SpreadPlayersCommand.java ++++ b/net/minecraft/server/commands/SpreadPlayersCommand.java +@@ -17,7 +17,6 @@ + import java.util.Map; + import java.util.Set; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.arguments.EntityArgument; + import net.minecraft.commands.arguments.coordinates.Vec2Argument; + import net.minecraft.core.BlockPos; +@@ -30,7 +29,7 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.BlockGetter; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.scores.PlayerTeam; + import net.minecraft.world.scores.Team; +@@ -50,43 +49,43 @@ + + public SpreadPlayersCommand() {} + +- public static void register(CommandDispatcher commanddispatcher) { +- commanddispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) Commands.literal("spreadplayers").requires((commandsourcestack) -> { +- return commandsourcestack.hasPermission(2); +- })).then(Commands.argument("center", Vec2Argument.vec2()).then(Commands.argument("spreadDistance", FloatArgumentType.floatArg(0.0F)).then(((RequiredArgumentBuilder) Commands.argument("maxRange", FloatArgumentType.floatArg(1.0F)).then(Commands.argument("respectTeams", BoolArgumentType.bool()).then(Commands.argument("targets", EntityArgument.entities()).executes((commandcontext) -> { ++ public static void register(CommandDispatcher dispatcher) { ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("spreadplayers").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).then(net.minecraft.commands.Commands.argument("center", Vec2Argument.vec2()).then(net.minecraft.commands.Commands.argument("spreadDistance", FloatArgumentType.floatArg(0.0F)).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("maxRange", FloatArgumentType.floatArg(1.0F)).then(net.minecraft.commands.Commands.argument("respectTeams", BoolArgumentType.bool()).then(net.minecraft.commands.Commands.argument("targets", EntityArgument.entities()).executes((commandcontext) -> { + return spreadPlayers((CommandSourceStack) commandcontext.getSource(), Vec2Argument.getVec2(commandcontext, "center"), FloatArgumentType.getFloat(commandcontext, "spreadDistance"), FloatArgumentType.getFloat(commandcontext, "maxRange"), ((CommandSourceStack) commandcontext.getSource()).getLevel().getMaxBuildHeight(), BoolArgumentType.getBool(commandcontext, "respectTeams"), EntityArgument.getEntities(commandcontext, "targets")); +- })))).then(Commands.literal("under").then(Commands.argument("maxHeight", IntegerArgumentType.integer()).then(Commands.argument("respectTeams", BoolArgumentType.bool()).then(Commands.argument("targets", EntityArgument.entities()).executes((commandcontext) -> { ++ })))).then(net.minecraft.commands.Commands.literal("under").then(net.minecraft.commands.Commands.argument("maxHeight", IntegerArgumentType.integer()).then(net.minecraft.commands.Commands.argument("respectTeams", BoolArgumentType.bool()).then(net.minecraft.commands.Commands.argument("targets", EntityArgument.entities()).executes((commandcontext) -> { + return spreadPlayers((CommandSourceStack) commandcontext.getSource(), Vec2Argument.getVec2(commandcontext, "center"), FloatArgumentType.getFloat(commandcontext, "spreadDistance"), FloatArgumentType.getFloat(commandcontext, "maxRange"), IntegerArgumentType.getInteger(commandcontext, "maxHeight"), BoolArgumentType.getBool(commandcontext, "respectTeams"), EntityArgument.getEntities(commandcontext, "targets")); + }))))))))); + } + +- private static int spreadPlayers(CommandSourceStack commandsourcestack, Vec2 vec2, float f, float f1, int i, boolean flag, Collection collection) throws CommandSyntaxException { +- ServerLevel serverlevel = commandsourcestack.getLevel(); +- int j = serverlevel.getMinBuildHeight(); ++ private static int spreadPlayers(CommandSourceStack source, Vec2 center, float spreadDistance, float maxRange, int maxHeight, boolean respectTeams, Collection targets) throws CommandSyntaxException { ++ ServerLevel worldserver = source.getLevel(); ++ int j = worldserver.getMinBuildHeight(); + +- if (i < j) { +- throw SpreadPlayersCommand.ERROR_INVALID_MAX_HEIGHT.create(i, j); ++ if (maxHeight < j) { ++ throw SpreadPlayersCommand.ERROR_INVALID_MAX_HEIGHT.create(maxHeight, j); + } else { + RandomSource randomsource = RandomSource.create(); +- double d0 = (double) (vec2.x - f1); +- double d1 = (double) (vec2.y - f1); +- double d2 = (double) (vec2.x + f1); +- double d3 = (double) (vec2.y + f1); +- SpreadPlayersCommand.Position[] aspreadplayerscommand_position = createInitialPositions(randomsource, flag ? getNumberOfTeams(collection) : collection.size(), d0, d1, d2, d3); ++ double d0 = (double) (center.x - maxRange); ++ double d1 = (double) (center.y - maxRange); ++ double d2 = (double) (center.x + maxRange); ++ double d3 = (double) (center.y + maxRange); ++ SpreadPlayersCommand.Position[] acommandspreadplayers_a = createInitialPositions(randomsource, respectTeams ? getNumberOfTeams(targets) : targets.size(), d0, d1, d2, d3); + +- spreadPositions(vec2, (double) f, serverlevel, randomsource, d0, d1, d2, d3, i, aspreadplayerscommand_position, flag); +- double d4 = setPlayerPositions(collection, serverlevel, aspreadplayerscommand_position, i, flag); ++ spreadPositions(center, (double) spreadDistance, worldserver, randomsource, d0, d1, d2, d3, maxHeight, acommandspreadplayers_a, respectTeams); ++ double d4 = setPlayerPositions(targets, worldserver, acommandspreadplayers_a, maxHeight, respectTeams); + +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.spreadplayers.success." + (flag ? "teams" : "entities"), aspreadplayerscommand_position.length, vec2.x, vec2.y, String.format(Locale.ROOT, "%.2f", d4)); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.spreadplayers.success." + (respectTeams ? "teams" : "entities"), acommandspreadplayers_a.length, center.x, center.y, String.format(Locale.ROOT, "%.2f", d4)); + }, true); +- return aspreadplayerscommand_position.length; ++ return acommandspreadplayers_a.length; + } + } + +- private static int getNumberOfTeams(Collection collection) { ++ private static int getNumberOfTeams(Collection entities) { + Set set = Sets.newHashSet(); +- Iterator iterator = collection.iterator(); ++ Iterator iterator = entities.iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); +@@ -94,14 +93,14 @@ + if (entity instanceof Player) { + set.add(entity.getTeam()); + } else { +- set.add((Object) null); ++ set.add((Team) null); // CraftBukkit - decompile error + } + } + + return set.size(); + } + +- private static void spreadPositions(Vec2 vec2, double d0, ServerLevel serverlevel, RandomSource randomsource, double d1, double d2, double d3, double d4, int i, SpreadPlayersCommand.Position[] aspreadplayerscommand_position, boolean flag) throws CommandSyntaxException { ++ private static void spreadPositions(Vec2 center, double spreadDistance, ServerLevel worldserver, RandomSource level, double random, double minX, double d3, double minZ, int i, SpreadPlayersCommand.Position[] maxX, boolean flag) throws CommandSyntaxException { + boolean flag1 = true; + double d5 = 3.4028234663852886E38D; + +@@ -112,56 +111,56 @@ + d5 = 3.4028234663852886E38D; + + int k; +- SpreadPlayersCommand.Position spreadplayerscommand_position; ++ SpreadPlayersCommand.Position commandspreadplayers_a; + +- for (int l = 0; l < aspreadplayerscommand_position.length; ++l) { +- SpreadPlayersCommand.Position spreadplayerscommand_position1 = aspreadplayerscommand_position[l]; ++ for (int l = 0; l < maxX.length; ++l) { ++ SpreadPlayersCommand.Position commandspreadplayers_a1 = maxX[l]; + + k = 0; +- spreadplayerscommand_position = new SpreadPlayersCommand.Position(); ++ commandspreadplayers_a = new SpreadPlayersCommand.Position(); + +- for (int i1 = 0; i1 < aspreadplayerscommand_position.length; ++i1) { ++ for (int i1 = 0; i1 < maxX.length; ++i1) { + if (l != i1) { +- SpreadPlayersCommand.Position spreadplayerscommand_position2 = aspreadplayerscommand_position[i1]; +- double d6 = spreadplayerscommand_position1.dist(spreadplayerscommand_position2); ++ SpreadPlayersCommand.Position commandspreadplayers_a2 = maxX[i1]; ++ double d6 = commandspreadplayers_a1.dist(commandspreadplayers_a2); + + d5 = Math.min(d6, d5); +- if (d6 < d0) { ++ if (d6 < spreadDistance) { + ++k; +- spreadplayerscommand_position.x += spreadplayerscommand_position2.x - spreadplayerscommand_position1.x; +- spreadplayerscommand_position.z += spreadplayerscommand_position2.z - spreadplayerscommand_position1.z; ++ commandspreadplayers_a.x += commandspreadplayers_a2.x - commandspreadplayers_a1.x; ++ commandspreadplayers_a.z += commandspreadplayers_a2.z - commandspreadplayers_a1.z; + } + } + } + + if (k > 0) { +- spreadplayerscommand_position.x /= (double) k; +- spreadplayerscommand_position.z /= (double) k; +- double d7 = spreadplayerscommand_position.getLength(); ++ commandspreadplayers_a.x /= (double) k; ++ commandspreadplayers_a.z /= (double) k; ++ double d7 = commandspreadplayers_a.getLength(); + + if (d7 > 0.0D) { +- spreadplayerscommand_position.normalize(); +- spreadplayerscommand_position1.moveAway(spreadplayerscommand_position); ++ commandspreadplayers_a.normalize(); ++ commandspreadplayers_a1.moveAway(commandspreadplayers_a); + } else { +- spreadplayerscommand_position1.randomize(randomsource, d1, d2, d3, d4); ++ commandspreadplayers_a1.randomize(level, random, minX, d3, minZ); + } + + flag1 = true; + } + +- if (spreadplayerscommand_position1.clamp(d1, d2, d3, d4)) { ++ if (commandspreadplayers_a1.clamp(random, minX, d3, minZ)) { + flag1 = true; + } + } + + if (!flag1) { +- SpreadPlayersCommand.Position[] aspreadplayerscommand_position1 = aspreadplayerscommand_position; +- int j1 = aspreadplayerscommand_position.length; ++ SpreadPlayersCommand.Position[] acommandspreadplayers_a1 = maxX; ++ int j1 = maxX.length; + + for (k = 0; k < j1; ++k) { +- spreadplayerscommand_position = aspreadplayerscommand_position1[k]; +- if (!spreadplayerscommand_position.isSafe(serverlevel, i)) { +- spreadplayerscommand_position.randomize(randomsource, d1, d2, d3, d4); ++ commandspreadplayers_a = acommandspreadplayers_a1[k]; ++ if (!commandspreadplayers_a.isSafe(worldserver, i)) { ++ commandspreadplayers_a.randomize(level, random, minX, d3, minZ); + flag1 = true; + } + } +@@ -174,71 +173,71 @@ + + if (j >= 10000) { + if (flag) { +- throw SpreadPlayersCommand.ERROR_FAILED_TO_SPREAD_TEAMS.create(aspreadplayerscommand_position.length, vec2.x, vec2.y, String.format(Locale.ROOT, "%.2f", d5)); ++ throw SpreadPlayersCommand.ERROR_FAILED_TO_SPREAD_TEAMS.create(maxX.length, center.x, center.y, String.format(Locale.ROOT, "%.2f", d5)); + } else { +- throw SpreadPlayersCommand.ERROR_FAILED_TO_SPREAD_ENTITIES.create(aspreadplayerscommand_position.length, vec2.x, vec2.y, String.format(Locale.ROOT, "%.2f", d5)); ++ throw SpreadPlayersCommand.ERROR_FAILED_TO_SPREAD_ENTITIES.create(maxX.length, center.x, center.y, String.format(Locale.ROOT, "%.2f", d5)); + } + } + } + +- private static double setPlayerPositions(Collection collection, ServerLevel serverlevel, SpreadPlayersCommand.Position[] aspreadplayerscommand_position, int i, boolean flag) { ++ private static double setPlayerPositions(Collection targets, ServerLevel level, SpreadPlayersCommand.Position[] positions, int maxHeight, boolean respectTeams) { + double d0 = 0.0D; + int j = 0; + Map map = Maps.newHashMap(); + + double d1; + +- for (Iterator iterator = collection.iterator(); iterator.hasNext(); d0 += d1) { ++ for (Iterator iterator = targets.iterator(); iterator.hasNext(); d0 += d1) { + Entity entity = (Entity) iterator.next(); +- SpreadPlayersCommand.Position spreadplayerscommand_position; ++ SpreadPlayersCommand.Position commandspreadplayers_a; + +- if (flag) { +- PlayerTeam playerteam = entity instanceof Player ? entity.getTeam() : null; ++ if (respectTeams) { ++ PlayerTeam scoreboardteam = entity instanceof Player ? entity.getTeam() : null; + +- if (!map.containsKey(playerteam)) { +- map.put(playerteam, aspreadplayerscommand_position[j++]); ++ if (!map.containsKey(scoreboardteam)) { ++ map.put(scoreboardteam, positions[j++]); + } + +- spreadplayerscommand_position = (SpreadPlayersCommand.Position) map.get(playerteam); ++ commandspreadplayers_a = (SpreadPlayersCommand.Position) map.get(scoreboardteam); + } else { +- spreadplayerscommand_position = aspreadplayerscommand_position[j++]; ++ commandspreadplayers_a = positions[j++]; + } + +- entity.teleportTo(serverlevel, (double) Mth.floor(spreadplayerscommand_position.x) + 0.5D, (double) spreadplayerscommand_position.getSpawnY(serverlevel, i), (double) Mth.floor(spreadplayerscommand_position.z) + 0.5D, Set.of(), entity.getYRot(), entity.getXRot()); ++ entity.teleportTo(level, (double) Mth.floor(commandspreadplayers_a.x) + 0.5D, (double) commandspreadplayers_a.getSpawnY(level, maxHeight), (double) Mth.floor(commandspreadplayers_a.z) + 0.5D, Set.of(), entity.getYRot(), entity.getXRot(), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.COMMAND); // CraftBukkit - handle teleport reason + d1 = Double.MAX_VALUE; +- SpreadPlayersCommand.Position[] aspreadplayerscommand_position1 = aspreadplayerscommand_position; +- int k = aspreadplayerscommand_position.length; ++ SpreadPlayersCommand.Position[] acommandspreadplayers_a1 = positions; ++ int k = positions.length; + + for (int l = 0; l < k; ++l) { +- SpreadPlayersCommand.Position spreadplayerscommand_position1 = aspreadplayerscommand_position1[l]; ++ SpreadPlayersCommand.Position commandspreadplayers_a1 = acommandspreadplayers_a1[l]; + +- if (spreadplayerscommand_position != spreadplayerscommand_position1) { +- double d2 = spreadplayerscommand_position.dist(spreadplayerscommand_position1); ++ if (commandspreadplayers_a != commandspreadplayers_a1) { ++ double d2 = commandspreadplayers_a.dist(commandspreadplayers_a1); + + d1 = Math.min(d2, d1); + } + } + } + +- if (collection.size() < 2) { ++ if (targets.size() < 2) { + return 0.0D; + } else { +- d0 /= (double) collection.size(); ++ d0 /= (double) targets.size(); + return d0; + } + } + +- private static SpreadPlayersCommand.Position[] createInitialPositions(RandomSource randomsource, int i, double d0, double d1, double d2, double d3) { +- SpreadPlayersCommand.Position[] aspreadplayerscommand_position = new SpreadPlayersCommand.Position[i]; ++ private static SpreadPlayersCommand.Position[] createInitialPositions(RandomSource random, int count, double minX, double d1, double minZ, double d3) { ++ SpreadPlayersCommand.Position[] acommandspreadplayers_a = new SpreadPlayersCommand.Position[count]; + +- for (int j = 0; j < aspreadplayerscommand_position.length; ++j) { +- SpreadPlayersCommand.Position spreadplayerscommand_position = new SpreadPlayersCommand.Position(); ++ for (int j = 0; j < acommandspreadplayers_a.length; ++j) { ++ SpreadPlayersCommand.Position commandspreadplayers_a = new SpreadPlayersCommand.Position(); + +- spreadplayerscommand_position.randomize(randomsource, d0, d1, d2, d3); +- aspreadplayerscommand_position[j] = spreadplayerscommand_position; ++ commandspreadplayers_a.randomize(random, minX, d1, minZ, d3); ++ acommandspreadplayers_a[j] = commandspreadplayers_a; + } + +- return aspreadplayerscommand_position; ++ return acommandspreadplayers_a; + } + + private static class Position { +@@ -248,9 +247,9 @@ + + Position() {} + +- double dist(SpreadPlayersCommand.Position spreadplayerscommand_position) { +- double d0 = this.x - spreadplayerscommand_position.x; +- double d1 = this.z - spreadplayerscommand_position.z; ++ double dist(SpreadPlayersCommand.Position other) { ++ double d0 = this.x - other.x; ++ double d1 = this.z - other.z; + + return Math.sqrt(d0 * d0 + d1 * d1); + } +@@ -266,19 +265,19 @@ + return Math.sqrt(this.x * this.x + this.z * this.z); + } + +- public void moveAway(SpreadPlayersCommand.Position spreadplayerscommand_position) { +- this.x -= spreadplayerscommand_position.x; +- this.z -= spreadplayerscommand_position.z; ++ public void moveAway(SpreadPlayersCommand.Position other) { ++ this.x -= other.x; ++ this.z -= other.z; + } + +- public boolean clamp(double d0, double d1, double d2, double d3) { ++ public boolean clamp(double minX, double d1, double minZ, double d3) { + boolean flag = false; + +- if (this.x < d0) { +- this.x = d0; ++ if (this.x < minX) { ++ this.x = minX; + flag = true; +- } else if (this.x > d2) { +- this.x = d2; ++ } else if (this.x > minZ) { ++ this.x = minZ; + flag = true; + } + +@@ -293,37 +292,37 @@ + return flag; + } + +- public int getSpawnY(BlockGetter blockgetter, int i) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(this.x, (double) (i + 1), this.z); +- boolean flag = blockgetter.getBlockState(blockpos_mutableblockpos).isAir(); ++ public int getSpawnY(BlockGetter level, int y) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(this.x, (double) (y + 1), this.z); ++ boolean flag = level.getBlockState(blockposition_mutableblockposition).isAir(); + +- blockpos_mutableblockpos.move(Direction.DOWN); ++ blockposition_mutableblockposition.move(Direction.DOWN); + + boolean flag1; + +- for (boolean flag2 = blockgetter.getBlockState(blockpos_mutableblockpos).isAir(); blockpos_mutableblockpos.getY() > blockgetter.getMinBuildHeight(); flag2 = flag1) { +- blockpos_mutableblockpos.move(Direction.DOWN); +- flag1 = blockgetter.getBlockState(blockpos_mutableblockpos).isAir(); ++ for (boolean flag2 = level.getBlockState(blockposition_mutableblockposition).isAir(); blockposition_mutableblockposition.getY() > level.getMinBuildHeight(); flag2 = flag1) { ++ blockposition_mutableblockposition.move(Direction.DOWN); ++ flag1 = level.getBlockState(blockposition_mutableblockposition).isAir(); + if (!flag1 && flag2 && flag) { +- return blockpos_mutableblockpos.getY() + 1; ++ return blockposition_mutableblockposition.getY() + 1; + } + + flag = flag2; + } + +- return i + 1; ++ return y + 1; + } + +- public boolean isSafe(BlockGetter blockgetter, int i) { +- BlockPos blockpos = BlockPos.containing(this.x, (double) (this.getSpawnY(blockgetter, i) - 1), this.z); +- BlockState blockstate = blockgetter.getBlockState(blockpos); ++ public boolean isSafe(BlockGetter level, int y) { ++ BlockPos blockposition = BlockPos.containing(this.x, (double) (this.getSpawnY(level, y) - 1), this.z); ++ IBlockData iblockdata = level.getBlockState(blockposition); + +- return blockpos.getY() < i && !blockstate.liquid() && !blockstate.is(BlockTags.FIRE); ++ return blockposition.getY() < y && !iblockdata.liquid() && !iblockdata.is(BlockTags.FIRE); + } + +- public void randomize(RandomSource randomsource, double d0, double d1, double d2, double d3) { +- this.x = Mth.nextDouble(randomsource, d0, d2); +- this.z = Mth.nextDouble(randomsource, d1, d3); ++ public void randomize(RandomSource random, double minX, double d1, double minZ, double d3) { ++ this.x = Mth.nextDouble(random, minX, minZ); ++ this.z = Mth.nextDouble(random, d1, d3); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/commands/SummonCommand.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/commands/SummonCommand.java.patch new file mode 100644 index 0000000000..e25ba0fd60 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/commands/SummonCommand.java.patch @@ -0,0 +1,95 @@ +--- a/net/minecraft/server/commands/SummonCommand.java ++++ b/net/minecraft/server/commands/SummonCommand.java +@@ -7,7 +7,6 @@ + import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; + import net.minecraft.commands.CommandBuildContext; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.arguments.CompoundTagArgument; + import net.minecraft.commands.arguments.ResourceArgument; + import net.minecraft.commands.arguments.coordinates.Vec3Argument; +@@ -20,9 +19,9 @@ + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.Vec3; + +@@ -34,41 +33,41 @@ + + public SummonCommand() {} + +- public static void register(CommandDispatcher commanddispatcher, CommandBuildContext commandbuildcontext) { +- commanddispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) Commands.literal("summon").requires((commandsourcestack) -> { +- return commandsourcestack.hasPermission(2); +- })).then(((RequiredArgumentBuilder) Commands.argument("entity", ResourceArgument.resource(commandbuildcontext, Registries.ENTITY_TYPE)).suggests(SuggestionProviders.SUMMONABLE_ENTITIES).executes((commandcontext) -> { ++ public static void register(CommandDispatcher dispatcher, CommandBuildContext context) { ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("summon").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("entity", ResourceArgument.resource(context, Registries.ENTITY_TYPE)).suggests(SuggestionProviders.SUMMONABLE_ENTITIES).executes((commandcontext) -> { + return spawnEntity((CommandSourceStack) commandcontext.getSource(), ResourceArgument.getSummonableEntityType(commandcontext, "entity"), ((CommandSourceStack) commandcontext.getSource()).getPosition(), new CompoundTag(), true); +- })).then(((RequiredArgumentBuilder) Commands.argument("pos", Vec3Argument.vec3()).executes((commandcontext) -> { ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("pos", Vec3Argument.vec3()).executes((commandcontext) -> { + return spawnEntity((CommandSourceStack) commandcontext.getSource(), ResourceArgument.getSummonableEntityType(commandcontext, "entity"), Vec3Argument.getVec3(commandcontext, "pos"), new CompoundTag(), true); +- })).then(Commands.argument("nbt", CompoundTagArgument.compoundTag()).executes((commandcontext) -> { ++ })).then(net.minecraft.commands.Commands.argument("nbt", CompoundTagArgument.compoundTag()).executes((commandcontext) -> { + return spawnEntity((CommandSourceStack) commandcontext.getSource(), ResourceArgument.getSummonableEntityType(commandcontext, "entity"), Vec3Argument.getVec3(commandcontext, "pos"), CompoundTagArgument.getCompoundTag(commandcontext, "nbt"), false); + }))))); + } + +- public static Entity createEntity(CommandSourceStack commandsourcestack, Holder.Reference> holder_reference, Vec3 vec3, CompoundTag compoundtag, boolean flag) throws CommandSyntaxException { +- BlockPos blockpos = BlockPos.containing(vec3); ++ public static Entity createEntity(CommandSourceStack source, Holder.Reference> type, Vec3 pos, CompoundTag tag, boolean randomizeProperties) throws CommandSyntaxException { ++ BlockPos blockposition = BlockPos.containing(pos); + +- if (!Level.isInSpawnableBounds(blockpos)) { ++ if (!Level.isInSpawnableBounds(blockposition)) { + throw SummonCommand.INVALID_POSITION.create(); + } else { +- CompoundTag compoundtag1 = compoundtag.copy(); ++ CompoundTag nbttagcompound1 = tag.copy(); + +- compoundtag1.putString("id", holder_reference.key().location().toString()); +- ServerLevel serverlevel = commandsourcestack.getLevel(); +- Entity entity = EntityType.loadEntityRecursive(compoundtag1, serverlevel, (entity1) -> { +- entity1.moveTo(vec3.x, vec3.y, vec3.z, entity1.getYRot(), entity1.getXRot()); ++ nbttagcompound1.putString("id", type.key().location().toString()); ++ ServerLevel worldserver = source.getLevel(); ++ Entity entity = EntityType.loadEntityRecursive(nbttagcompound1, worldserver, (entity1) -> { ++ entity1.moveTo(pos.x, pos.y, pos.z, entity1.getYRot(), entity1.getXRot()); + return entity1; + }); + + if (entity == null) { + throw SummonCommand.ERROR_FAILED.create(); + } else { +- if (flag && entity instanceof Mob) { +- ((Mob) entity).finalizeSpawn(commandsourcestack.getLevel(), commandsourcestack.getLevel().getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.COMMAND, (SpawnGroupData) null, (CompoundTag) null); ++ if (randomizeProperties && entity instanceof Mob) { ++ ((Mob) entity).finalizeSpawn(source.getLevel(), source.getLevel().getCurrentDifficultyAt(entity.blockPosition()), EnumMobSpawn.COMMAND, (GroupDataEntity) null, (CompoundTag) null); + } + +- if (!serverlevel.tryAddFreshEntityWithPassengers(entity)) { ++ if (!worldserver.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.COMMAND)) { // CraftBukkit - pass a spawn reason of "COMMAND" + throw SummonCommand.ERROR_DUPLICATE_UUID.create(); + } else { + return entity; +@@ -77,10 +76,10 @@ + } + } + +- private static int spawnEntity(CommandSourceStack commandsourcestack, Holder.Reference> holder_reference, Vec3 vec3, CompoundTag compoundtag, boolean flag) throws CommandSyntaxException { +- Entity entity = createEntity(commandsourcestack, holder_reference, vec3, compoundtag, flag); ++ private static int spawnEntity(CommandSourceStack source, Holder.Reference> type, Vec3 pos, CompoundTag tag, boolean randomizeProperties) throws CommandSyntaxException { ++ Entity entity = createEntity(source, type, pos, tag, randomizeProperties); + +- commandsourcestack.sendSuccess(() -> { ++ source.sendSuccess(() -> { + return Component.translatable("commands.summon.success", entity.getDisplayName()); + }, true); + return 1; diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/commands/TeleportCommand.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/commands/TeleportCommand.java.patch new file mode 100644 index 0000000000..e183608f33 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/commands/TeleportCommand.java.patch @@ -0,0 +1,281 @@ +--- a/net/minecraft/server/commands/TeleportCommand.java ++++ b/net/minecraft/server/commands/TeleportCommand.java +@@ -14,7 +14,6 @@ + import java.util.Set; + import javax.annotation.Nullable; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.arguments.EntityAnchorArgument; + import net.minecraft.commands.arguments.EntityArgument; + import net.minecraft.commands.arguments.coordinates.Coordinates; +@@ -33,6 +32,12 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.event.entity.EntityTeleportEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++// CraftBukkit end + + public class TeleportCommand { + +@@ -40,133 +45,156 @@ + + public TeleportCommand() {} + +- public static void register(CommandDispatcher commanddispatcher) { +- LiteralCommandNode literalcommandnode = commanddispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) Commands.literal("teleport").requires((commandsourcestack) -> { +- return commandsourcestack.hasPermission(2); +- })).then(Commands.argument("location", Vec3Argument.vec3()).executes((commandcontext) -> { ++ public static void register(CommandDispatcher dispatcher) { ++ LiteralCommandNode literalcommandnode = dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("teleport").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).then(net.minecraft.commands.Commands.argument("location", Vec3Argument.vec3()).executes((commandcontext) -> { + return teleportToPos((CommandSourceStack) commandcontext.getSource(), Collections.singleton(((CommandSourceStack) commandcontext.getSource()).getEntityOrException()), ((CommandSourceStack) commandcontext.getSource()).getLevel(), Vec3Argument.getCoordinates(commandcontext, "location"), WorldCoordinates.current(), (TeleportCommand.LookAt) null); +- }))).then(Commands.argument("destination", EntityArgument.entity()).executes((commandcontext) -> { ++ }))).then(net.minecraft.commands.Commands.argument("destination", EntityArgument.entity()).executes((commandcontext) -> { + return teleportToEntity((CommandSourceStack) commandcontext.getSource(), Collections.singleton(((CommandSourceStack) commandcontext.getSource()).getEntityOrException()), EntityArgument.getEntity(commandcontext, "destination")); +- }))).then(((RequiredArgumentBuilder) Commands.argument("targets", EntityArgument.entities()).then(((RequiredArgumentBuilder) ((RequiredArgumentBuilder) Commands.argument("location", Vec3Argument.vec3()).executes((commandcontext) -> { ++ }))).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("targets", EntityArgument.entities()).then(((RequiredArgumentBuilder) ((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("location", Vec3Argument.vec3()).executes((commandcontext) -> { + return teleportToPos((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ((CommandSourceStack) commandcontext.getSource()).getLevel(), Vec3Argument.getCoordinates(commandcontext, "location"), (Coordinates) null, (TeleportCommand.LookAt) null); +- })).then(Commands.argument("rotation", RotationArgument.rotation()).executes((commandcontext) -> { ++ })).then(net.minecraft.commands.Commands.argument("rotation", RotationArgument.rotation()).executes((commandcontext) -> { + return teleportToPos((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ((CommandSourceStack) commandcontext.getSource()).getLevel(), Vec3Argument.getCoordinates(commandcontext, "location"), RotationArgument.getRotation(commandcontext, "rotation"), (TeleportCommand.LookAt) null); +- }))).then(((LiteralArgumentBuilder) Commands.literal("facing").then(Commands.literal("entity").then(((RequiredArgumentBuilder) Commands.argument("facingEntity", EntityArgument.entity()).executes((commandcontext) -> { ++ }))).then(((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("facing").then(net.minecraft.commands.Commands.literal("entity").then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("facingEntity", EntityArgument.entity()).executes((commandcontext) -> { + return teleportToPos((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ((CommandSourceStack) commandcontext.getSource()).getLevel(), Vec3Argument.getCoordinates(commandcontext, "location"), (Coordinates) null, new TeleportCommand.LookAt(EntityArgument.getEntity(commandcontext, "facingEntity"), EntityAnchorArgument.Anchor.FEET)); +- })).then(Commands.argument("facingAnchor", EntityAnchorArgument.anchor()).executes((commandcontext) -> { ++ })).then(net.minecraft.commands.Commands.argument("facingAnchor", EntityAnchorArgument.anchor()).executes((commandcontext) -> { + return teleportToPos((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ((CommandSourceStack) commandcontext.getSource()).getLevel(), Vec3Argument.getCoordinates(commandcontext, "location"), (Coordinates) null, new TeleportCommand.LookAt(EntityArgument.getEntity(commandcontext, "facingEntity"), EntityAnchorArgument.getAnchor(commandcontext, "facingAnchor"))); +- }))))).then(Commands.argument("facingLocation", Vec3Argument.vec3()).executes((commandcontext) -> { ++ }))))).then(net.minecraft.commands.Commands.argument("facingLocation", Vec3Argument.vec3()).executes((commandcontext) -> { + return teleportToPos((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ((CommandSourceStack) commandcontext.getSource()).getLevel(), Vec3Argument.getCoordinates(commandcontext, "location"), (Coordinates) null, new TeleportCommand.LookAt(Vec3Argument.getVec3(commandcontext, "facingLocation"))); +- }))))).then(Commands.argument("destination", EntityArgument.entity()).executes((commandcontext) -> { ++ }))))).then(net.minecraft.commands.Commands.argument("destination", EntityArgument.entity()).executes((commandcontext) -> { + return teleportToEntity((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), EntityArgument.getEntity(commandcontext, "destination")); + })))); + +- commanddispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) Commands.literal("tp").requires((commandsourcestack) -> { +- return commandsourcestack.hasPermission(2); ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("tp").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); + })).redirect(literalcommandnode)); + } + +- private static int teleportToEntity(CommandSourceStack commandsourcestack, Collection collection, Entity entity) throws CommandSyntaxException { +- Iterator iterator = collection.iterator(); ++ private static int teleportToEntity(CommandSourceStack source, Collection targets, Entity destination) throws CommandSyntaxException { ++ Iterator iterator = targets.iterator(); + + while (iterator.hasNext()) { + Entity entity1 = (Entity) iterator.next(); + +- performTeleport(commandsourcestack, entity1, (ServerLevel) entity.level(), entity.getX(), entity.getY(), entity.getZ(), EnumSet.noneOf(RelativeMovement.class), entity.getYRot(), entity.getXRot(), (TeleportCommand.LookAt) null); ++ performTeleport(source, entity1, (ServerLevel) destination.level(), destination.getX(), destination.getY(), destination.getZ(), EnumSet.noneOf(RelativeMovement.class), destination.getYRot(), destination.getXRot(), (TeleportCommand.LookAt) null); + } + +- if (collection.size() == 1) { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.teleport.success.entity.single", ((Entity) collection.iterator().next()).getDisplayName(), entity.getDisplayName()); ++ if (targets.size() == 1) { ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.teleport.success.entity.single", ((Entity) targets.iterator().next()).getDisplayName(), destination.getDisplayName()); + }, true); + } else { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.teleport.success.entity.multiple", collection.size(), entity.getDisplayName()); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.teleport.success.entity.multiple", targets.size(), destination.getDisplayName()); + }, true); + } + +- return collection.size(); ++ return targets.size(); + } + +- private static int teleportToPos(CommandSourceStack commandsourcestack, Collection collection, ServerLevel serverlevel, Coordinates coordinates, @Nullable Coordinates coordinates1, @Nullable TeleportCommand.LookAt teleportcommand_lookat) throws CommandSyntaxException { +- Vec3 vec3 = coordinates.getPosition(commandsourcestack); +- Vec2 vec2 = coordinates1 == null ? null : coordinates1.getRotation(commandsourcestack); ++ private static int teleportToPos(CommandSourceStack source, Collection targets, ServerLevel level, Coordinates position, @Nullable Coordinates rotation, @Nullable TeleportCommand.LookAt facing) throws CommandSyntaxException { ++ Vec3 vec3d = position.getPosition(source); ++ Vec2 vec2f = rotation == null ? null : rotation.getRotation(source); + Set set = EnumSet.noneOf(RelativeMovement.class); + +- if (coordinates.isXRelative()) { ++ if (position.isXRelative()) { + set.add(RelativeMovement.X); + } + +- if (coordinates.isYRelative()) { ++ if (position.isYRelative()) { + set.add(RelativeMovement.Y); + } + +- if (coordinates.isZRelative()) { ++ if (position.isZRelative()) { + set.add(RelativeMovement.Z); + } + +- if (coordinates1 == null) { ++ if (rotation == null) { + set.add(RelativeMovement.X_ROT); + set.add(RelativeMovement.Y_ROT); + } else { +- if (coordinates1.isXRelative()) { ++ if (rotation.isXRelative()) { + set.add(RelativeMovement.X_ROT); + } + +- if (coordinates1.isYRelative()) { ++ if (rotation.isYRelative()) { + set.add(RelativeMovement.Y_ROT); + } + } + +- Iterator iterator = collection.iterator(); ++ Iterator iterator = targets.iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); + +- if (coordinates1 == null) { +- performTeleport(commandsourcestack, entity, serverlevel, vec3.x, vec3.y, vec3.z, set, entity.getYRot(), entity.getXRot(), teleportcommand_lookat); ++ if (rotation == null) { ++ performTeleport(source, entity, level, vec3d.x, vec3d.y, vec3d.z, set, entity.getYRot(), entity.getXRot(), facing); + } else { +- performTeleport(commandsourcestack, entity, serverlevel, vec3.x, vec3.y, vec3.z, set, vec2.y, vec2.x, teleportcommand_lookat); ++ performTeleport(source, entity, level, vec3d.x, vec3d.y, vec3d.z, set, vec2f.y, vec2f.x, facing); + } + } + +- if (collection.size() == 1) { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.teleport.success.location.single", ((Entity) collection.iterator().next()).getDisplayName(), formatDouble(vec3.x), formatDouble(vec3.y), formatDouble(vec3.z)); ++ if (targets.size() == 1) { ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.teleport.success.location.single", ((Entity) targets.iterator().next()).getDisplayName(), formatDouble(vec3d.x), formatDouble(vec3d.y), formatDouble(vec3d.z)); + }, true); + } else { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.teleport.success.location.multiple", collection.size(), formatDouble(vec3.x), formatDouble(vec3.y), formatDouble(vec3.z)); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.teleport.success.location.multiple", targets.size(), formatDouble(vec3d.x), formatDouble(vec3d.y), formatDouble(vec3d.z)); + }, true); + } + +- return collection.size(); ++ return targets.size(); + } + +- private static String formatDouble(double d0) { +- return String.format(Locale.ROOT, "%f", d0); ++ private static String formatDouble(double value) { ++ return String.format(Locale.ROOT, "%f", value); + } + +- private static void performTeleport(CommandSourceStack commandsourcestack, Entity entity, ServerLevel serverlevel, double d0, double d1, double d2, Set set, float f, float f1, @Nullable TeleportCommand.LookAt teleportcommand_lookat) throws CommandSyntaxException { +- BlockPos blockpos = BlockPos.containing(d0, d1, d2); ++ private static void performTeleport(CommandSourceStack source, Entity entity, ServerLevel level, double x, double d1, double y, Set set, float z, float f1, @Nullable TeleportCommand.LookAt relativeList) throws CommandSyntaxException { ++ BlockPos blockposition = BlockPos.containing(x, d1, y); + +- if (!Level.isInSpawnableBounds(blockpos)) { ++ if (!Level.isInSpawnableBounds(blockposition)) { + throw TeleportCommand.INVALID_POSITION.create(); + } else { +- float f2 = Mth.wrapDegrees(f); ++ float f2 = Mth.wrapDegrees(z); + float f3 = Mth.wrapDegrees(f1); + +- if (entity.teleportTo(serverlevel, d0, d1, d2, set, f2, f3)) { +- if (teleportcommand_lookat != null) { +- teleportcommand_lookat.perform(commandsourcestack, entity); ++ // CraftBukkit start - Teleport event ++ boolean result; ++ if (entity instanceof ServerPlayer player) { ++ result = player.teleportTo(level, x, d1, y, set, f2, f3, PlayerTeleportEvent.TeleportCause.COMMAND); ++ } else { ++ Location to = new Location(level.getWorld(), x, d1, y, f2, f3); ++ EntityTeleportEvent event = new EntityTeleportEvent(entity.getBukkitEntity(), entity.getBukkitEntity().getLocation(), to); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; + } + ++ x = to.getX(); ++ d1 = to.getY(); ++ y = to.getZ(); ++ f2 = to.getYaw(); ++ f3 = to.getPitch(); ++ level = ((CraftWorld) to.getWorld()).getHandle(); ++ ++ result = entity.teleportTo(level, x, d1, y, set, f2, f3); ++ } ++ ++ if (result) { ++ // CraftBukkit end ++ if (relativeList != null) { ++ relativeList.perform(source, entity); ++ } ++ + label23: + { + if (entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; ++ LivingEntity entityliving = (LivingEntity) entity; + +- if (livingentity.isFallFlying()) { ++ if (entityliving.isFallFlying()) { + break label23; + } + } +@@ -176,9 +204,9 @@ + } + + if (entity instanceof PathfinderMob) { +- PathfinderMob pathfindermob = (PathfinderMob) entity; ++ PathfinderMob entitycreature = (PathfinderMob) entity; + +- pathfindermob.getNavigation().stop(); ++ entitycreature.getNavigation().stop(); + } + + } +@@ -191,27 +219,27 @@ + private final Entity entity; + private final EntityAnchorArgument.Anchor anchor; + +- public LookAt(Entity entity, EntityAnchorArgument.Anchor entityanchorargument_anchor) { ++ public LookAt(Entity entity, EntityAnchorArgument.Anchor anchor) { + this.entity = entity; +- this.anchor = entityanchorargument_anchor; +- this.position = entityanchorargument_anchor.apply(entity); ++ this.anchor = anchor; ++ this.position = anchor.apply(entity); + } + +- public LookAt(Vec3 vec3) { ++ public LookAt(Vec3 position) { + this.entity = null; +- this.position = vec3; ++ this.position = position; + this.anchor = null; + } + +- public void perform(CommandSourceStack commandsourcestack, Entity entity) { ++ public void perform(CommandSourceStack source, Entity entity) { + if (this.entity != null) { + if (entity instanceof ServerPlayer) { +- ((ServerPlayer) entity).lookAt(commandsourcestack.getAnchor(), this.entity, this.anchor); ++ ((ServerPlayer) entity).lookAt(source.getAnchor(), this.entity, this.anchor); + } else { +- entity.lookAt(commandsourcestack.getAnchor(), this.position); ++ entity.lookAt(source.getAnchor(), this.position); + } + } else { +- entity.lookAt(commandsourcestack.getAnchor(), this.position); ++ entity.lookAt(source.getAnchor(), this.position); + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/commands/TimeCommand.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/commands/TimeCommand.java.patch new file mode 100644 index 0000000000..b1383ee771 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/commands/TimeCommand.java.patch @@ -0,0 +1,127 @@ +--- a/net/minecraft/server/commands/TimeCommand.java ++++ b/net/minecraft/server/commands/TimeCommand.java +@@ -5,77 +5,92 @@ + import com.mojang.brigadier.builder.LiteralArgumentBuilder; + import java.util.Iterator; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.arguments.TimeArgument; + import net.minecraft.network.chat.Component; + import net.minecraft.server.level.ServerLevel; ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.event.world.TimeSkipEvent; ++// CraftBukkit end + + public class TimeCommand { + + public TimeCommand() {} + +- public static void register(CommandDispatcher commanddispatcher) { +- commanddispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) Commands.literal("time").requires((commandsourcestack) -> { +- return commandsourcestack.hasPermission(2); +- })).then(((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) Commands.literal("set").then(Commands.literal("day").executes((commandcontext) -> { ++ public static void register(CommandDispatcher dispatcher) { ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("time").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).then(((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("set").then(net.minecraft.commands.Commands.literal("day").executes((commandcontext) -> { + return setTime((CommandSourceStack) commandcontext.getSource(), 1000); +- }))).then(Commands.literal("noon").executes((commandcontext) -> { ++ }))).then(net.minecraft.commands.Commands.literal("noon").executes((commandcontext) -> { + return setTime((CommandSourceStack) commandcontext.getSource(), 6000); +- }))).then(Commands.literal("night").executes((commandcontext) -> { ++ }))).then(net.minecraft.commands.Commands.literal("night").executes((commandcontext) -> { + return setTime((CommandSourceStack) commandcontext.getSource(), 13000); +- }))).then(Commands.literal("midnight").executes((commandcontext) -> { ++ }))).then(net.minecraft.commands.Commands.literal("midnight").executes((commandcontext) -> { + return setTime((CommandSourceStack) commandcontext.getSource(), 18000); +- }))).then(Commands.argument("time", TimeArgument.time()).executes((commandcontext) -> { ++ }))).then(net.minecraft.commands.Commands.argument("time", TimeArgument.time()).executes((commandcontext) -> { + return setTime((CommandSourceStack) commandcontext.getSource(), IntegerArgumentType.getInteger(commandcontext, "time")); +- })))).then(Commands.literal("add").then(Commands.argument("time", TimeArgument.time()).executes((commandcontext) -> { ++ })))).then(net.minecraft.commands.Commands.literal("add").then(net.minecraft.commands.Commands.argument("time", TimeArgument.time()).executes((commandcontext) -> { + return addTime((CommandSourceStack) commandcontext.getSource(), IntegerArgumentType.getInteger(commandcontext, "time")); +- })))).then(((LiteralArgumentBuilder) ((LiteralArgumentBuilder) Commands.literal("query").then(Commands.literal("daytime").executes((commandcontext) -> { ++ })))).then(((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("query").then(net.minecraft.commands.Commands.literal("daytime").executes((commandcontext) -> { + return queryTime((CommandSourceStack) commandcontext.getSource(), getDayTime(((CommandSourceStack) commandcontext.getSource()).getLevel())); +- }))).then(Commands.literal("gametime").executes((commandcontext) -> { ++ }))).then(net.minecraft.commands.Commands.literal("gametime").executes((commandcontext) -> { + return queryTime((CommandSourceStack) commandcontext.getSource(), (int) (((CommandSourceStack) commandcontext.getSource()).getLevel().getGameTime() % 2147483647L)); +- }))).then(Commands.literal("day").executes((commandcontext) -> { ++ }))).then(net.minecraft.commands.Commands.literal("day").executes((commandcontext) -> { + return queryTime((CommandSourceStack) commandcontext.getSource(), (int) (((CommandSourceStack) commandcontext.getSource()).getLevel().getDayTime() / 24000L % 2147483647L)); + })))); + } + +- private static int getDayTime(ServerLevel serverlevel) { +- return (int) (serverlevel.getDayTime() % 24000L); ++ private static int getDayTime(ServerLevel level) { ++ return (int) (level.getDayTime() % 24000L); + } + +- private static int queryTime(CommandSourceStack commandsourcestack, int i) { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.time.query", i); ++ private static int queryTime(CommandSourceStack source, int time) { ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.time.query", time); + }, false); +- return i; ++ return time; + } + +- public static int setTime(CommandSourceStack commandsourcestack, int i) { +- Iterator iterator = commandsourcestack.getServer().getAllLevels().iterator(); ++ public static int setTime(CommandSourceStack source, int time) { ++ Iterator iterator = com.google.common.collect.Iterators.singletonIterator(source.getLevel()); // CraftBukkit - SPIGOT-6496: Only set the time for the world the command originates in + + while (iterator.hasNext()) { +- ServerLevel serverlevel = (ServerLevel) iterator.next(); ++ ServerLevel worldserver = (ServerLevel) iterator.next(); + +- serverlevel.setDayTime((long) i); ++ // CraftBukkit start ++ TimeSkipEvent event = new TimeSkipEvent(worldserver.getWorld(), TimeSkipEvent.SkipReason.COMMAND, time - worldserver.getDayTime()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ worldserver.setDayTime((long) worldserver.getDayTime() + event.getSkipAmount()); ++ } ++ // CraftBukkit end + } + +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.time.set", i); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.time.set", time); + }, true); +- return getDayTime(commandsourcestack.getLevel()); ++ return getDayTime(source.getLevel()); + } + +- public static int addTime(CommandSourceStack commandsourcestack, int i) { +- Iterator iterator = commandsourcestack.getServer().getAllLevels().iterator(); ++ public static int addTime(CommandSourceStack source, int amount) { ++ Iterator iterator = com.google.common.collect.Iterators.singletonIterator(source.getLevel()); // CraftBukkit - SPIGOT-6496: Only set the time for the world the command originates in + + while (iterator.hasNext()) { +- ServerLevel serverlevel = (ServerLevel) iterator.next(); ++ ServerLevel worldserver = (ServerLevel) iterator.next(); + +- serverlevel.setDayTime(serverlevel.getDayTime() + (long) i); ++ // CraftBukkit start ++ TimeSkipEvent event = new TimeSkipEvent(worldserver.getWorld(), TimeSkipEvent.SkipReason.COMMAND, amount); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ worldserver.setDayTime(worldserver.getDayTime() + event.getSkipAmount()); ++ } ++ // CraftBukkit end + } + +- int j = getDayTime(commandsourcestack.getLevel()); ++ int j = getDayTime(source.getLevel()); + +- commandsourcestack.sendSuccess(() -> { ++ source.sendSuccess(() -> { + return Component.translatable("commands.time.set", j); + }, true); + return j; diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/commands/WorldBorderCommand.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/commands/WorldBorderCommand.java.patch new file mode 100644 index 0000000000..4224aaf266 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/commands/WorldBorderCommand.java.patch @@ -0,0 +1,220 @@ +--- a/net/minecraft/server/commands/WorldBorderCommand.java ++++ b/net/minecraft/server/commands/WorldBorderCommand.java +@@ -10,7 +10,6 @@ + import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; + import java.util.Locale; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.arguments.coordinates.Vec2Argument; + import net.minecraft.network.chat.Component; + import net.minecraft.util.Mth; +@@ -31,106 +30,106 @@ + + public WorldBorderCommand() {} + +- public static void register(CommandDispatcher commanddispatcher) { +- commanddispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) Commands.literal("worldborder").requires((commandsourcestack) -> { +- return commandsourcestack.hasPermission(2); +- })).then(Commands.literal("add").then(((RequiredArgumentBuilder) Commands.argument("distance", DoubleArgumentType.doubleArg(-5.9999968E7D, 5.9999968E7D)).executes((commandcontext) -> { ++ public static void register(CommandDispatcher dispatcher) { ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("worldborder").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).then(net.minecraft.commands.Commands.literal("add").then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("distance", DoubleArgumentType.doubleArg(-5.9999968E7D, 5.9999968E7D)).executes((commandcontext) -> { + return setSize((CommandSourceStack) commandcontext.getSource(), ((CommandSourceStack) commandcontext.getSource()).getLevel().getWorldBorder().getSize() + DoubleArgumentType.getDouble(commandcontext, "distance"), 0L); +- })).then(Commands.argument("time", IntegerArgumentType.integer(0)).executes((commandcontext) -> { ++ })).then(net.minecraft.commands.Commands.argument("time", IntegerArgumentType.integer(0)).executes((commandcontext) -> { + return setSize((CommandSourceStack) commandcontext.getSource(), ((CommandSourceStack) commandcontext.getSource()).getLevel().getWorldBorder().getSize() + DoubleArgumentType.getDouble(commandcontext, "distance"), ((CommandSourceStack) commandcontext.getSource()).getLevel().getWorldBorder().getLerpRemainingTime() + (long) IntegerArgumentType.getInteger(commandcontext, "time") * 1000L); +- }))))).then(Commands.literal("set").then(((RequiredArgumentBuilder) Commands.argument("distance", DoubleArgumentType.doubleArg(-5.9999968E7D, 5.9999968E7D)).executes((commandcontext) -> { ++ }))))).then(net.minecraft.commands.Commands.literal("set").then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("distance", DoubleArgumentType.doubleArg(-5.9999968E7D, 5.9999968E7D)).executes((commandcontext) -> { + return setSize((CommandSourceStack) commandcontext.getSource(), DoubleArgumentType.getDouble(commandcontext, "distance"), 0L); +- })).then(Commands.argument("time", IntegerArgumentType.integer(0)).executes((commandcontext) -> { ++ })).then(net.minecraft.commands.Commands.argument("time", IntegerArgumentType.integer(0)).executes((commandcontext) -> { + return setSize((CommandSourceStack) commandcontext.getSource(), DoubleArgumentType.getDouble(commandcontext, "distance"), (long) IntegerArgumentType.getInteger(commandcontext, "time") * 1000L); +- }))))).then(Commands.literal("center").then(Commands.argument("pos", Vec2Argument.vec2()).executes((commandcontext) -> { ++ }))))).then(net.minecraft.commands.Commands.literal("center").then(net.minecraft.commands.Commands.argument("pos", Vec2Argument.vec2()).executes((commandcontext) -> { + return setCenter((CommandSourceStack) commandcontext.getSource(), Vec2Argument.getVec2(commandcontext, "pos")); +- })))).then(((LiteralArgumentBuilder) Commands.literal("damage").then(Commands.literal("amount").then(Commands.argument("damagePerBlock", FloatArgumentType.floatArg(0.0F)).executes((commandcontext) -> { ++ })))).then(((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("damage").then(net.minecraft.commands.Commands.literal("amount").then(net.minecraft.commands.Commands.argument("damagePerBlock", FloatArgumentType.floatArg(0.0F)).executes((commandcontext) -> { + return setDamageAmount((CommandSourceStack) commandcontext.getSource(), FloatArgumentType.getFloat(commandcontext, "damagePerBlock")); +- })))).then(Commands.literal("buffer").then(Commands.argument("distance", FloatArgumentType.floatArg(0.0F)).executes((commandcontext) -> { ++ })))).then(net.minecraft.commands.Commands.literal("buffer").then(net.minecraft.commands.Commands.argument("distance", FloatArgumentType.floatArg(0.0F)).executes((commandcontext) -> { + return setDamageBuffer((CommandSourceStack) commandcontext.getSource(), FloatArgumentType.getFloat(commandcontext, "distance")); +- }))))).then(Commands.literal("get").executes((commandcontext) -> { ++ }))))).then(net.minecraft.commands.Commands.literal("get").executes((commandcontext) -> { + return getSize((CommandSourceStack) commandcontext.getSource()); +- }))).then(((LiteralArgumentBuilder) Commands.literal("warning").then(Commands.literal("distance").then(Commands.argument("distance", IntegerArgumentType.integer(0)).executes((commandcontext) -> { ++ }))).then(((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("warning").then(net.minecraft.commands.Commands.literal("distance").then(net.minecraft.commands.Commands.argument("distance", IntegerArgumentType.integer(0)).executes((commandcontext) -> { + return setWarningDistance((CommandSourceStack) commandcontext.getSource(), IntegerArgumentType.getInteger(commandcontext, "distance")); +- })))).then(Commands.literal("time").then(Commands.argument("time", IntegerArgumentType.integer(0)).executes((commandcontext) -> { ++ })))).then(net.minecraft.commands.Commands.literal("time").then(net.minecraft.commands.Commands.argument("time", IntegerArgumentType.integer(0)).executes((commandcontext) -> { + return setWarningTime((CommandSourceStack) commandcontext.getSource(), IntegerArgumentType.getInteger(commandcontext, "time")); + }))))); + } + +- private static int setDamageBuffer(CommandSourceStack commandsourcestack, float f) throws CommandSyntaxException { +- WorldBorder worldborder = commandsourcestack.getServer().overworld().getWorldBorder(); ++ private static int setDamageBuffer(CommandSourceStack source, float distance) throws CommandSyntaxException { ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit + +- if (worldborder.getDamageSafeZone() == (double) f) { ++ if (worldborder.getDamageSafeZone() == (double) distance) { + throw WorldBorderCommand.ERROR_SAME_DAMAGE_BUFFER.create(); + } else { +- worldborder.setDamageSafeZone((double) f); +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.worldborder.damage.buffer.success", String.format(Locale.ROOT, "%.2f", f)); ++ worldborder.setDamageSafeZone((double) distance); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.worldborder.damage.buffer.success", String.format(Locale.ROOT, "%.2f", distance)); + }, true); +- return (int) f; ++ return (int) distance; + } + } + +- private static int setDamageAmount(CommandSourceStack commandsourcestack, float f) throws CommandSyntaxException { +- WorldBorder worldborder = commandsourcestack.getServer().overworld().getWorldBorder(); ++ private static int setDamageAmount(CommandSourceStack source, float damagePerBlock) throws CommandSyntaxException { ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit + +- if (worldborder.getDamagePerBlock() == (double) f) { ++ if (worldborder.getDamagePerBlock() == (double) damagePerBlock) { + throw WorldBorderCommand.ERROR_SAME_DAMAGE_AMOUNT.create(); + } else { +- worldborder.setDamagePerBlock((double) f); +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.worldborder.damage.amount.success", String.format(Locale.ROOT, "%.2f", f)); ++ worldborder.setDamagePerBlock((double) damagePerBlock); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.worldborder.damage.amount.success", String.format(Locale.ROOT, "%.2f", damagePerBlock)); + }, true); +- return (int) f; ++ return (int) damagePerBlock; + } + } + +- private static int setWarningTime(CommandSourceStack commandsourcestack, int i) throws CommandSyntaxException { +- WorldBorder worldborder = commandsourcestack.getServer().overworld().getWorldBorder(); ++ private static int setWarningTime(CommandSourceStack source, int time) throws CommandSyntaxException { ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit + +- if (worldborder.getWarningTime() == i) { ++ if (worldborder.getWarningTime() == time) { + throw WorldBorderCommand.ERROR_SAME_WARNING_TIME.create(); + } else { +- worldborder.setWarningTime(i); +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.worldborder.warning.time.success", i); ++ worldborder.setWarningTime(time); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.worldborder.warning.time.success", time); + }, true); +- return i; ++ return time; + } + } + +- private static int setWarningDistance(CommandSourceStack commandsourcestack, int i) throws CommandSyntaxException { +- WorldBorder worldborder = commandsourcestack.getServer().overworld().getWorldBorder(); ++ private static int setWarningDistance(CommandSourceStack source, int distance) throws CommandSyntaxException { ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit + +- if (worldborder.getWarningBlocks() == i) { ++ if (worldborder.getWarningBlocks() == distance) { + throw WorldBorderCommand.ERROR_SAME_WARNING_DISTANCE.create(); + } else { +- worldborder.setWarningBlocks(i); +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.worldborder.warning.distance.success", i); ++ worldborder.setWarningBlocks(distance); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.worldborder.warning.distance.success", distance); + }, true); +- return i; ++ return distance; + } + } + +- private static int getSize(CommandSourceStack commandsourcestack) { +- double d0 = commandsourcestack.getServer().overworld().getWorldBorder().getSize(); ++ private static int getSize(CommandSourceStack source) { ++ double d0 = source.getLevel().getWorldBorder().getSize(); // CraftBukkit + +- commandsourcestack.sendSuccess(() -> { ++ source.sendSuccess(() -> { + return Component.translatable("commands.worldborder.get", String.format(Locale.ROOT, "%.0f", d0)); + }, false); + return Mth.floor(d0 + 0.5D); + } + +- private static int setCenter(CommandSourceStack commandsourcestack, Vec2 vec2) throws CommandSyntaxException { +- WorldBorder worldborder = commandsourcestack.getServer().overworld().getWorldBorder(); ++ private static int setCenter(CommandSourceStack source, Vec2 pos) throws CommandSyntaxException { ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit + +- if (worldborder.getCenterX() == (double) vec2.x && worldborder.getCenterZ() == (double) vec2.y) { ++ if (worldborder.getCenterX() == (double) pos.x && worldborder.getCenterZ() == (double) pos.y) { + throw WorldBorderCommand.ERROR_SAME_CENTER.create(); +- } else if ((double) Math.abs(vec2.x) <= 2.9999984E7D && (double) Math.abs(vec2.y) <= 2.9999984E7D) { +- worldborder.setCenter((double) vec2.x, (double) vec2.y); +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.worldborder.center.success", String.format(Locale.ROOT, "%.2f", vec2.x), String.format(Locale.ROOT, "%.2f", vec2.y)); ++ } else if ((double) Math.abs(pos.x) <= 2.9999984E7D && (double) Math.abs(pos.y) <= 2.9999984E7D) { ++ worldborder.setCenter((double) pos.x, (double) pos.y); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.worldborder.center.success", String.format(Locale.ROOT, "%.2f", pos.x), String.format(Locale.ROOT, "%.2f", pos.y)); + }, true); + return 0; + } else { +@@ -138,36 +137,36 @@ + } + } + +- private static int setSize(CommandSourceStack commandsourcestack, double d0, long i) throws CommandSyntaxException { +- WorldBorder worldborder = commandsourcestack.getServer().overworld().getWorldBorder(); ++ private static int setSize(CommandSourceStack source, double newSize, long i) throws CommandSyntaxException { ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit + double d1 = worldborder.getSize(); + +- if (d1 == d0) { ++ if (d1 == newSize) { + throw WorldBorderCommand.ERROR_SAME_SIZE.create(); +- } else if (d0 < 1.0D) { ++ } else if (newSize < 1.0D) { + throw WorldBorderCommand.ERROR_TOO_SMALL.create(); +- } else if (d0 > 5.9999968E7D) { ++ } else if (newSize > 5.9999968E7D) { + throw WorldBorderCommand.ERROR_TOO_BIG.create(); + } else { + if (i > 0L) { +- worldborder.lerpSizeBetween(d1, d0, i); +- if (d0 > d1) { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.worldborder.set.grow", String.format(Locale.ROOT, "%.1f", d0), Long.toString(i / 1000L)); ++ worldborder.lerpSizeBetween(d1, newSize, i); ++ if (newSize > d1) { ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.worldborder.set.grow", String.format(Locale.ROOT, "%.1f", newSize), Long.toString(i / 1000L)); + }, true); + } else { +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.worldborder.set.shrink", String.format(Locale.ROOT, "%.1f", d0), Long.toString(i / 1000L)); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.worldborder.set.shrink", String.format(Locale.ROOT, "%.1f", newSize), Long.toString(i / 1000L)); + }, true); + } + } else { +- worldborder.setSize(d0); +- commandsourcestack.sendSuccess(() -> { +- return Component.translatable("commands.worldborder.set.immediate", String.format(Locale.ROOT, "%.1f", d0)); ++ worldborder.setSize(newSize); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.worldborder.set.immediate", String.format(Locale.ROOT, "%.1f", newSize)); + }, true); + } + +- return (int) (d0 - d1); ++ return (int) (newSize - d1); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/dedicated/DedicatedServer.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/dedicated/DedicatedServer.java.patch new file mode 100644 index 0000000000..fdca32af12 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/dedicated/DedicatedServer.java.patch @@ -0,0 +1,589 @@ +--- a/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/net/minecraft/server/dedicated/DedicatedServer.java +@@ -48,11 +48,20 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.GameType; +-import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.SkullBlockEntity; + import net.minecraft.world.level.storage.LevelStorageSource; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.server.WorldLoader; ++import org.apache.logging.log4j.Level; ++import org.apache.logging.log4j.LogManager; ++import org.apache.logging.log4j.io.IoBuilder; ++import org.bukkit.command.CommandSender; ++import org.bukkit.event.server.ServerCommandEvent; ++import org.bukkit.event.server.RemoteServerCommandEvent; ++// CraftBukkit end ++ + public class DedicatedServer extends MinecraftServer implements ServerInterface { + + static final Logger LOGGER = LogUtils.getLogger(); +@@ -61,35 +70,66 @@ + private final List consoleInput = Collections.synchronizedList(Lists.newArrayList()); + @Nullable + private QueryThreadGs4 queryThreadGs4; +- private final RconConsoleSource rconConsoleSource; ++ // private final RemoteControlCommandListener rconConsoleSource; // CraftBukkit - remove field + @Nullable + private RconThread rconThread; +- private final DedicatedServerSettings settings; ++ public DedicatedServerSettings settings; + @Nullable + private MinecraftServerGui gui; + @Nullable + private final TextFilterClient textFilterClient; + +- public DedicatedServer(Thread thread, LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess, PackRepository packrepository, WorldStem worldstem, DedicatedServerSettings dedicatedserversettings, DataFixer datafixer, Services services, ChunkProgressListenerFactory chunkprogresslistenerfactory) { +- super(thread, levelstoragesource_levelstorageaccess, packrepository, worldstem, Proxy.NO_PROXY, datafixer, services, chunkprogresslistenerfactory); ++ // CraftBukkit start - Signature changed ++ public DedicatedServer(joptsimple.OptionSet options, WorldLoader.a worldLoader, Thread thread, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PackRepository resourcepackrepository, WorldStem worldstem, DedicatedServerSettings dedicatedserversettings, DataFixer datafixer, Services services, ChunkProgressListenerFactory worldloadlistenerfactory) { ++ super(options, worldLoader, thread, convertable_conversionsession, resourcepackrepository, worldstem, Proxy.NO_PROXY, datafixer, services, worldloadlistenerfactory); ++ // CraftBukkit end + this.settings = dedicatedserversettings; +- this.rconConsoleSource = new RconConsoleSource(this); ++ // this.rconConsoleSource = new RemoteControlCommandListener(this); // CraftBukkit - remove field + this.textFilterClient = TextFilterClient.createFromConfig(dedicatedserversettings.getProperties().textFilteringConfig); + } + + @Override +- @Override + public boolean initServer() throws IOException { + Thread thread = new Thread("Server console handler") { +- @Override + public void run() { +- BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8)); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.Main.useConsole) { ++ return; ++ } ++ jline.console.ConsoleReader bufferedreader = reader; + ++ // MC-33041, SPIGOT-5538: if System.in is not valid due to javaw, then return ++ try { ++ System.in.available(); ++ } catch (IOException ex) { ++ return; ++ } ++ // CraftBukkit end ++ + String s; + + try { +- while (!DedicatedServer.this.isStopped() && DedicatedServer.this.isRunning() && (s = bufferedreader.readLine()) != null) { +- DedicatedServer.this.handleConsoleInput(s, DedicatedServer.this.createCommandSourceStack()); ++ // CraftBukkit start - JLine disabling compatibility ++ while (!DedicatedServer.this.isStopped() && DedicatedServer.this.isRunning()) { ++ if (org.bukkit.craftbukkit.Main.useJline) { ++ s = bufferedreader.readLine(">", null); ++ } else { ++ s = bufferedreader.readLine(); ++ } ++ ++ // SPIGOT-5220: Throttle if EOF (ctrl^d) or stdin is /dev/null ++ if (s == null) { ++ try { ++ Thread.sleep(50L); ++ } catch (InterruptedException ex) { ++ Thread.currentThread().interrupt(); ++ } ++ continue; ++ } ++ if (s.trim().length() > 0) { // Trim to filter lines which are just spaces ++ DedicatedServer.this.handleConsoleInput(s, DedicatedServer.this.createCommandSourceStack()); ++ } ++ // CraftBukkit end + } + } catch (IOException ioexception) { + DedicatedServer.LOGGER.error("Exception handling console input", ioexception); +@@ -98,6 +138,27 @@ + } + }; + ++ // CraftBukkit start - TODO: handle command-line logging arguments ++ java.util.logging.Logger global = java.util.logging.Logger.getLogger(""); ++ global.setUseParentHandlers(false); ++ for (java.util.logging.Handler handler : global.getHandlers()) { ++ global.removeHandler(handler); ++ } ++ global.addHandler(new org.bukkit.craftbukkit.util.ForwardLogHandler()); ++ ++ final org.apache.logging.log4j.core.Logger logger = ((org.apache.logging.log4j.core.Logger) LogManager.getRootLogger()); ++ for (org.apache.logging.log4j.core.Appender appender : logger.getAppenders().values()) { ++ if (appender instanceof org.apache.logging.log4j.core.appender.ConsoleAppender) { ++ logger.removeAppender(appender); ++ } ++ } ++ ++ new org.bukkit.craftbukkit.util.TerminalConsoleWriterThread(System.out, this.reader).start(); ++ ++ System.setOut(IoBuilder.forLogger(logger).setLevel(Level.INFO).buildPrintStream()); ++ System.setErr(IoBuilder.forLogger(logger).setLevel(Level.WARN).buildPrintStream()); ++ // CraftBukkit end ++ + thread.setDaemon(true); + thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(DedicatedServer.LOGGER)); + thread.start(); +@@ -122,7 +183,7 @@ + this.setMotd(dedicatedserverproperties.motd); + super.setPlayerIdleTimeout((Integer) dedicatedserverproperties.playerIdleTimeout.get()); + this.setEnforceWhitelist(dedicatedserverproperties.enforceWhitelist); +- this.worldData.setGameType(dedicatedserverproperties.gamemode); ++ // this.worldData.setGameType(dedicatedserverproperties.gamemode); // CraftBukkit - moved to world loading + DedicatedServer.LOGGER.info("Default game type: {}", dedicatedserverproperties.gamemode); + InetAddress inetaddress = null; + +@@ -146,6 +207,12 @@ + return false; + } + ++ // CraftBukkit start ++ this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); ++ server.loadPlugins(); ++ server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.STARTUP); ++ // CraftBukkit end ++ + if (!this.usesAuthentication()) { + DedicatedServer.LOGGER.warn("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!"); + DedicatedServer.LOGGER.warn("The server will make no attempt to authenticate usernames. Beware."); +@@ -160,13 +227,13 @@ + if (!OldUsersConverter.serverReadyAfterUserconversion(this)) { + return false; + } else { +- this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); ++ // this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); // CraftBukkit - moved up + long i = Util.getNanos(); + + SkullBlockEntity.setup(this.services, this); + GameProfileCache.setUsesAuthentication(this.usesAuthentication()); + DedicatedServer.LOGGER.info("Preparing level \"{}\"", this.getLevelIdName()); +- this.loadLevel(); ++ this.loadLevel(storageSource.getLevelId()); // CraftBukkit + long j = Util.getNanos() - i; + String s = String.format(Locale.ROOT, "%.3fs", (double) j / 1.0E9D); + +@@ -204,55 +271,47 @@ + } + + @Override +- @Override + public boolean isSpawningAnimals() { + return this.getProperties().spawnAnimals && super.isSpawningAnimals(); + } + + @Override +- @Override + public boolean isSpawningMonsters() { + return this.settings.getProperties().spawnMonsters && super.isSpawningMonsters(); + } + + @Override +- @Override + public boolean areNpcsEnabled() { + return this.settings.getProperties().spawnNpcs && super.areNpcsEnabled(); + } + + @Override +- @Override + public DedicatedServerProperties getProperties() { + return this.settings.getProperties(); + } + + @Override +- @Override + public void forceDifficulty() { + this.setDifficulty(this.getProperties().difficulty, true); + } + + @Override +- @Override + public boolean isHardcore() { + return this.getProperties().hardcore; + } + + @Override +- @Override +- public SystemReport fillServerSystemReport(SystemReport systemreport) { +- systemreport.setDetail("Is Modded", () -> { ++ public SystemReport fillServerSystemReport(SystemReport report) { ++ report.setDetail("Is Modded", () -> { + return this.getModdedStatus().fullDescription(); + }); +- systemreport.setDetail("Type", () -> { ++ report.setDetail("Type", () -> { + return "Dedicated Server (map_server.txt)"; + }); +- return systemreport; ++ return report; + } + + @Override +- @Override + public void dumpServerProperties(Path path) throws IOException { + DedicatedServerProperties dedicatedserverproperties = this.getProperties(); + BufferedWriter bufferedwriter = Files.newBufferedWriter(path); +@@ -289,7 +348,6 @@ + } + + @Override +- @Override + public void onServerExit() { + if (this.textFilterClient != null) { + this.textFilterClient.close(); +@@ -307,78 +365,77 @@ + this.queryThreadGs4.stop(); + } + ++ System.exit(0); // CraftBukkit + } + + @Override +- @Override +- public void tickChildren(BooleanSupplier booleansupplier) { +- super.tickChildren(booleansupplier); ++ public void tickChildren(BooleanSupplier hasTimeLeft) { ++ super.tickChildren(hasTimeLeft); + this.handleConsoleInputs(); + } + + @Override +- @Override + public boolean isNetherEnabled() { + return this.getProperties().allowNether; + } + +- public void handleConsoleInput(String s, CommandSourceStack commandsourcestack) { +- this.consoleInput.add(new ConsoleInput(s, commandsourcestack)); ++ public void handleConsoleInput(String msg, CommandSourceStack source) { ++ this.consoleInput.add(new ConsoleInput(msg, source)); + } + + public void handleConsoleInputs() { + while (!this.consoleInput.isEmpty()) { +- ConsoleInput consoleinput = (ConsoleInput) this.consoleInput.remove(0); ++ ConsoleInput servercommand = (ConsoleInput) this.consoleInput.remove(0); + +- this.getCommands().performPrefixedCommand(consoleinput.source, consoleinput.msg); ++ // CraftBukkit start - ServerCommand for preprocessing ++ ServerCommandEvent event = new ServerCommandEvent(console, servercommand.msg); ++ server.getPluginManager().callEvent(event); ++ if (event.isCancelled()) continue; ++ servercommand = new ConsoleInput(event.getCommand(), servercommand.source); ++ ++ // this.getCommands().performPrefixedCommand(servercommand.source, servercommand.msg); // Called in dispatchServerCommand ++ server.dispatchServerCommand(console, servercommand); ++ // CraftBukkit end + } + + } + + @Override +- @Override + public boolean isDedicatedServer() { + return true; + } + + @Override +- @Override + public int getRateLimitPacketsPerSecond() { + return this.getProperties().rateLimitPacketsPerSecond; + } + + @Override +- @Override + public boolean isEpollEnabled() { + return this.getProperties().useNativeTransport; + } + + @Override +- @Override + public DedicatedPlayerList getPlayerList() { + return (DedicatedPlayerList) super.getPlayerList(); + } + + @Override +- @Override + public boolean isPublished() { + return true; + } + + @Override +- @Override + public String getServerIp() { + return this.getLocalIp(); + } + + @Override +- @Override + public int getServerPort() { + return this.getPort(); + } + + @Override +- @Override + public String getServerName() { + return this.getMotd(); + } +@@ -391,27 +448,23 @@ + } + + @Override +- @Override + public boolean hasGui() { + return this.gui != null; + } + + @Override +- @Override + public boolean isCommandBlockEnabled() { + return this.getProperties().enableCommandBlock; + } + + @Override +- @Override + public int getSpawnProtectionRadius() { + return this.getProperties().spawnProtection; + } + + @Override +- @Override +- public boolean isUnderSpawnProtection(ServerLevel serverlevel, BlockPos blockpos, Player player) { +- if (serverlevel.dimension() != Level.OVERWORLD) { ++ public boolean isUnderSpawnProtection(ServerLevel level, BlockPos pos, Player player) { ++ if (level.dimension() != net.minecraft.world.level.Level.OVERWORLD) { + return false; + } else if (this.getPlayerList().getOps().isEmpty()) { + return false; +@@ -420,9 +473,9 @@ + } else if (this.getSpawnProtectionRadius() <= 0) { + return false; + } else { +- BlockPos blockpos1 = serverlevel.getSharedSpawnPos(); +- int i = Mth.abs(blockpos.getX() - blockpos1.getX()); +- int j = Mth.abs(blockpos.getZ() - blockpos1.getZ()); ++ BlockPos blockposition1 = level.getSharedSpawnPos(); ++ int i = Mth.abs(pos.getX() - blockposition1.getX()); ++ int j = Mth.abs(pos.getZ() - blockposition1.getZ()); + int k = Math.max(i, j); + + return k <= this.getSpawnProtectionRadius(); +@@ -430,64 +483,54 @@ + } + + @Override +- @Override + public boolean repliesToStatus() { + return this.getProperties().enableStatus; + } + + @Override +- @Override + public boolean hidesOnlinePlayers() { + return this.getProperties().hideOnlinePlayers; + } + + @Override +- @Override + public int getOperatorUserPermissionLevel() { + return this.getProperties().opPermissionLevel; + } + + @Override +- @Override + public int getFunctionCompilationLevel() { + return this.getProperties().functionPermissionLevel; + } + + @Override +- @Override +- public void setPlayerIdleTimeout(int i) { +- super.setPlayerIdleTimeout(i); ++ public void setPlayerIdleTimeout(int idleTimeout) { ++ super.setPlayerIdleTimeout(idleTimeout); + this.settings.update((dedicatedserverproperties) -> { +- return (DedicatedServerProperties) dedicatedserverproperties.playerIdleTimeout.update(this.registryAccess(), i); ++ return (DedicatedServerProperties) dedicatedserverproperties.playerIdleTimeout.update(this.registryAccess(), idleTimeout); + }); + } + + @Override +- @Override + public boolean shouldRconBroadcast() { + return this.getProperties().broadcastRconToOps; + } + + @Override +- @Override + public boolean shouldInformAdmins() { + return this.getProperties().broadcastConsoleToOps; + } + + @Override +- @Override + public int getAbsoluteMaxWorldSize() { + return this.getProperties().maxWorldSize; + } + + @Override +- @Override + public int getCompressionThreshold() { + return this.getProperties().networkCompressionThreshold; + } + + @Override +- @Override + public boolean enforceSecureProfile() { + DedicatedServerProperties dedicatedserverproperties = this.getProperties(); + +@@ -495,7 +538,6 @@ + } + + @Override +- @Override + public boolean logIPs() { + return this.getProperties().logIPs; + } +@@ -574,35 +616,67 @@ + } + + @Override +- @Override + public int getMaxChainedNeighborUpdates() { + return this.getProperties().maxChainedNeighborUpdates; + } + + @Override +- @Override + public String getPluginNames() { +- return ""; ++ // CraftBukkit start - Whole method ++ StringBuilder result = new StringBuilder(); ++ org.bukkit.plugin.Plugin[] plugins = server.getPluginManager().getPlugins(); ++ ++ result.append(server.getName()); ++ result.append(" on Bukkit "); ++ result.append(server.getBukkitVersion()); ++ ++ if (plugins.length > 0 && server.getQueryPlugins()) { ++ result.append(": "); ++ ++ for (int i = 0; i < plugins.length; i++) { ++ if (i > 0) { ++ result.append("; "); ++ } ++ ++ result.append(plugins[i].getDescription().getName()); ++ result.append(" "); ++ result.append(plugins[i].getDescription().getVersion().replaceAll(";", ",")); ++ } ++ } ++ ++ return result.toString(); ++ // CraftBukkit end + } + + @Override +- @Override +- public String runCommand(String s) { +- this.rconConsoleSource.prepareForCommand(); ++ public String runCommand(String command) { ++ // CraftBukkit start - fire RemoteServerCommandEvent ++ throw new UnsupportedOperationException("Not supported - remote source required."); ++ } ++ ++ public String runCommand(RconConsoleSource rconConsoleSource, String s) { ++ rconConsoleSource.prepareForCommand(); + this.executeBlocking(() -> { +- this.getCommands().performPrefixedCommand(this.rconConsoleSource.createCommandSourceStack(), s); ++ CommandSourceStack wrapper = rconConsoleSource.createCommandSourceStack(); ++ RemoteServerCommandEvent event = new RemoteServerCommandEvent(rconConsoleSource.getBukkitSender(wrapper), s); ++ server.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ ConsoleInput serverCommand = new ConsoleInput(event.getCommand(), wrapper); ++ server.dispatchServerCommand(event.getSender(), serverCommand); + }); +- return this.rconConsoleSource.getCommandResponse(); ++ return rconConsoleSource.getCommandResponse(); ++ // CraftBukkit end + } + +- public void storeUsingWhiteList(boolean flag) { ++ public void storeUsingWhiteList(boolean isStoreUsingWhiteList) { + this.settings.update((dedicatedserverproperties) -> { +- return (DedicatedServerProperties) dedicatedserverproperties.whiteList.update(this.registryAccess(), flag); ++ return (DedicatedServerProperties) dedicatedserverproperties.whiteList.update(this.registryAccess(), isStoreUsingWhiteList); + }); + } + + @Override +- @Override + public void stopServer() { + super.stopServer(); + Util.shutdownExecutors(); +@@ -610,45 +684,49 @@ + } + + @Override +- @Override +- public boolean isSingleplayerOwner(GameProfile gameprofile) { ++ public boolean isSingleplayerOwner(GameProfile profile) { + return false; + } + + @Override +- @Override +- public int getScaledTrackingDistance(int i) { +- return this.getProperties().entityBroadcastRangePercentage * i / 100; ++ public int getScaledTrackingDistance(int trackingDistance) { ++ return this.getProperties().entityBroadcastRangePercentage * trackingDistance / 100; + } + + @Override +- @Override + public String getLevelIdName() { + return this.storageSource.getLevelId(); + } + + @Override +- @Override + public boolean forceSynchronousWrites() { + return this.settings.getProperties().syncChunkWrites; + } + + @Override +- @Override +- public TextFilter createTextFilterForPlayer(ServerPlayer serverplayer) { +- return this.textFilterClient != null ? this.textFilterClient.createContext(serverplayer.getGameProfile()) : TextFilter.DUMMY; ++ public TextFilter createTextFilterForPlayer(ServerPlayer player) { ++ return this.textFilterClient != null ? this.textFilterClient.createContext(player.getGameProfile()) : TextFilter.DUMMY; + } + + @Nullable + @Override +- @Override + public GameType getForcedGameType() { + return this.settings.getProperties().forceGameMode ? this.worldData.getGameType() : null; + } + + @Override +- @Override + public Optional getServerResourcePack() { + return this.settings.getProperties().serverResourcePackInfo; + } ++ ++ // CraftBukkit start ++ public boolean isDebugging() { ++ return this.getProperties().debug; ++ } ++ ++ @Override ++ public CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return console; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/dedicated/DedicatedServerProperties.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/dedicated/DedicatedServerProperties.java.patch new file mode 100644 index 0000000000..dc1a182995 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/dedicated/DedicatedServerProperties.java.patch @@ -0,0 +1,152 @@ +--- a/net/minecraft/server/dedicated/DedicatedServerProperties.java ++++ b/net/minecraft/server/dedicated/DedicatedServerProperties.java +@@ -44,11 +44,16 @@ + import net.minecraft.world.level.levelgen.presets.WorldPresets; + import org.slf4j.Logger; + ++// CraftBukkit start ++import joptsimple.OptionSet; ++// CraftBukkit end ++ + public class DedicatedServerProperties extends Settings { + + static final Logger LOGGER = LogUtils.getLogger(); + private static final Pattern SHA1 = Pattern.compile("^[a-fA-F0-9]{40}$"); + private static final Splitter COMMA_SPLITTER = Splitter.on(',').trimResults(); ++ public final boolean debug = this.get("debug", false); // CraftBukkit + public final boolean onlineMode = this.get("online-mode", true); + public final boolean preventProxyConnections = this.get("prevent-proxy-connections", false); + public final String serverIp = this.get("server-ip", ""); +@@ -103,8 +108,10 @@ + private final DedicatedServerProperties.WorldDimensionData worldDimensionData; + public final WorldOptions worldOptions; + +- public DedicatedServerProperties(Properties properties) { +- super(properties); ++ // CraftBukkit start ++ public DedicatedServerProperties(Properties properties, OptionSet optionset) { ++ super(properties, optionset); ++ // CraftBukkit end + this.difficulty = (Difficulty) this.get("difficulty", dispatchNumberOrString(Difficulty::byId, Difficulty::byName), Difficulty::getKey, Difficulty.EASY); + this.gamemode = (GameType) this.get("gamemode", dispatchNumberOrString(GameType::byId, GameType::byName), GameType::getName, GameType.SURVIVAL); + this.levelName = this.get("level-name", "world"); +@@ -161,23 +168,24 @@ + this.initialDataPackConfiguration = getDatapackConfig(this.get("initial-enabled-packs", String.join(",", WorldDataConfiguration.DEFAULT.dataPacks().getEnabled())), this.get("initial-disabled-packs", String.join(",", WorldDataConfiguration.DEFAULT.dataPacks().getDisabled()))); + } + +- public static DedicatedServerProperties fromFile(Path path) { +- return new DedicatedServerProperties(loadFromFile(path)); ++ // CraftBukkit start ++ public static DedicatedServerProperties fromFile(Path path, OptionSet optionset) { ++ return new DedicatedServerProperties(loadFromFile(path), optionset); + } + + @Override +- @Override +- protected DedicatedServerProperties reload(RegistryAccess registryaccess, Properties properties) { +- return new DedicatedServerProperties(properties); ++ protected DedicatedServerProperties reload(RegistryAccess iregistrycustom, Properties properties, OptionSet optionset) { ++ return new DedicatedServerProperties(properties, optionset); ++ // CraftBukkit end + } + + @Nullable +- private static Component parseResourcePackPrompt(String s) { +- if (!Strings.isNullOrEmpty(s)) { ++ private static Component parseResourcePackPrompt(String json) { ++ if (!Strings.isNullOrEmpty(json)) { + try { +- return Component.Serializer.fromJson(s); ++ return Component.Serializer.fromJson(json); + } catch (Exception exception) { +- DedicatedServerProperties.LOGGER.warn("Failed to parse resource pack prompt '{}'", s, exception); ++ DedicatedServerProperties.LOGGER.warn("Failed to parse resource pack prompt '{}'", json, exception); + } + } + +@@ -208,7 +216,7 @@ + DedicatedServerProperties.LOGGER.warn("Invalid sha1 for resource-pack-sha1"); + } + +- Component component = parseResourcePackPrompt(s4); ++ Component ichatbasecomponent = parseResourcePackPrompt(s4); + UUID uuid; + + if (s.isEmpty()) { +@@ -223,55 +231,55 @@ + } + } + +- return Optional.of(new MinecraftServer.ServerResourcePackInfo(uuid, s1, s5, flag, component)); ++ return Optional.of(new MinecraftServer.ServerResourcePackInfo(uuid, s1, s5, flag, ichatbasecomponent)); + } + } + +- private static DataPackConfig getDatapackConfig(String s, String s1) { +- List list = DedicatedServerProperties.COMMA_SPLITTER.splitToList(s); +- List list1 = DedicatedServerProperties.COMMA_SPLITTER.splitToList(s1); ++ private static DataPackConfig getDatapackConfig(String initalEnabledPacks, String initialDisabledPacks) { ++ List list = DedicatedServerProperties.COMMA_SPLITTER.splitToList(initalEnabledPacks); ++ List list1 = DedicatedServerProperties.COMMA_SPLITTER.splitToList(initialDisabledPacks); + + return new DataPackConfig(list, list1); + } + +- public WorldDimensions createDimensions(RegistryAccess registryaccess) { +- return this.worldDimensionData.create(registryaccess); ++ public WorldDimensions createDimensions(RegistryAccess registryAccess) { ++ return this.worldDimensionData.create(registryAccess); + } + +- private static record WorldDimensionData(JsonObject generatorSettings, String levelType) { ++ public static record WorldDimensionData(JsonObject generatorSettings, String levelType) { + + private static final Map> LEGACY_PRESET_NAMES = Map.of("default", WorldPresets.NORMAL, "largebiomes", WorldPresets.LARGE_BIOMES); + +- public WorldDimensions create(RegistryAccess registryaccess) { +- Registry registry = registryaccess.registryOrThrow(Registries.WORLD_PRESET); +- Holder.Reference holder_reference = (Holder.Reference) registry.getHolder(WorldPresets.NORMAL).or(() -> { +- return registry.holders().findAny(); ++ public WorldDimensions create(RegistryAccess registryAccess) { ++ Registry iregistry = registryAccess.registryOrThrow(Registries.WORLD_PRESET); ++ Holder.Reference holder_c = (Holder.Reference) iregistry.getHolder(WorldPresets.NORMAL).or(() -> { ++ return iregistry.holders().findAny(); + }).orElseThrow(() -> { + return new IllegalStateException("Invalid datapack contents: can't find default preset"); + }); +- Optional optional = Optional.ofNullable(ResourceLocation.tryParse(this.levelType)).map((resourcelocation) -> { +- return ResourceKey.create(Registries.WORLD_PRESET, resourcelocation); ++ Optional> optional = Optional.ofNullable(ResourceLocation.tryParse(this.levelType)).map((minecraftkey) -> { // CraftBukkit - decompile error ++ return ResourceKey.create(Registries.WORLD_PRESET, minecraftkey); + }).or(() -> { +- return Optional.ofNullable((ResourceKey) DedicatedServerProperties.WorldDimensionData.LEGACY_PRESET_NAMES.get(this.levelType)); ++ return Optional.ofNullable(DedicatedServerProperties.WorldDimensionData.LEGACY_PRESET_NAMES.get(this.levelType)); // CraftBukkit - decompile error + }); + +- Objects.requireNonNull(registry); +- Holder holder = (Holder) optional.flatMap(registry::getHolder).orElseGet(() -> { +- DedicatedServerProperties.LOGGER.warn("Failed to parse level-type {}, defaulting to {}", this.levelType, holder_reference.key().location()); +- return holder_reference; ++ Objects.requireNonNull(iregistry); ++ Holder holder = (Holder) optional.flatMap(iregistry::getHolder).orElseGet(() -> { ++ DedicatedServerProperties.LOGGER.warn("Failed to parse level-type {}, defaulting to {}", this.levelType, holder_c.key().location()); ++ return holder_c; + }); + WorldDimensions worlddimensions = ((WorldPreset) holder.value()).createWorldDimensions(); + + if (holder.is(WorldPresets.FLAT)) { +- RegistryOps registryops = RegistryOps.create(JsonOps.INSTANCE, (HolderLookup.Provider) registryaccess); +- DataResult dataresult = FlatLevelGeneratorSettings.CODEC.parse(new Dynamic(registryops, this.generatorSettings())); ++ RegistryOps registryops = RegistryOps.create(JsonOps.INSTANCE, (HolderLookup.Provider) registryAccess); ++ DataResult dataresult = FlatLevelGeneratorSettings.CODEC.parse(new Dynamic(registryops, this.generatorSettings())); // CraftBukkit - decompile error + Logger logger = DedicatedServerProperties.LOGGER; + + Objects.requireNonNull(logger); + Optional optional1 = dataresult.resultOrPartial(logger::error); + + if (optional1.isPresent()) { +- return worlddimensions.replaceOverworldGenerator(registryaccess, new FlatLevelSource((FlatLevelGeneratorSettings) optional1.get())); ++ return worlddimensions.replaceOverworldGenerator(registryAccess, new FlatLevelSource((FlatLevelGeneratorSettings) optional1.get())); + } + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/dedicated/DedicatedServerSettings.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/dedicated/DedicatedServerSettings.java.patch new file mode 100644 index 0000000000..28aed34995 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/dedicated/DedicatedServerSettings.java.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/server/dedicated/DedicatedServerSettings.java ++++ b/net/minecraft/server/dedicated/DedicatedServerSettings.java +@@ -3,14 +3,21 @@ + import java.nio.file.Path; + import java.util.function.UnaryOperator; + ++// CraftBukkit start ++import java.io.File; ++import joptsimple.OptionSet; ++// CraftBukkit end ++ + public class DedicatedServerSettings { + + private final Path source; + private DedicatedServerProperties properties; + +- public DedicatedServerSettings(Path path) { +- this.source = path; +- this.properties = DedicatedServerProperties.fromFile(path); ++ // CraftBukkit start ++ public DedicatedServerSettings(OptionSet optionset) { ++ this.source = ((File) optionset.valueOf("config")).toPath(); ++ this.properties = DedicatedServerProperties.fromFile(source, optionset); ++ // CraftBukkit end + } + + public DedicatedServerProperties getProperties() { +@@ -21,8 +28,8 @@ + this.properties.store(this.source); + } + +- public DedicatedServerSettings update(UnaryOperator unaryoperator) { +- (this.properties = (DedicatedServerProperties) unaryoperator.apply(this.properties)).store(this.source); ++ public DedicatedServerSettings update(UnaryOperator propertiesOperator) { ++ (this.properties = (DedicatedServerProperties) propertiesOperator.apply(this.properties)).store(this.source); + return this; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/dedicated/Settings.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/dedicated/Settings.java.patch new file mode 100644 index 0000000000..5d53c1de5f --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/dedicated/Settings.java.patch @@ -0,0 +1,260 @@ +--- a/net/minecraft/server/dedicated/Settings.java ++++ b/net/minecraft/server/dedicated/Settings.java +@@ -20,20 +20,40 @@ + import java.util.function.Supplier; + import java.util.function.UnaryOperator; + import javax.annotation.Nullable; +-import net.minecraft.core.RegistryAccess; + import org.slf4j.Logger; + ++import joptsimple.OptionSet; // CraftBukkit ++import net.minecraft.core.RegistryAccess; ++ + public abstract class Settings> { + + private static final Logger LOGGER = LogUtils.getLogger(); +- protected final Properties properties; ++ public final Properties properties; ++ // CraftBukkit start ++ private OptionSet options = null; + +- public Settings(Properties properties) { ++ public Settings(Properties properties, final OptionSet options) { + this.properties = properties; ++ ++ this.options = options; + } + ++ private String getOverride(String name, String value) { ++ if ((this.options != null) && (this.options.has(name))) { ++ return String.valueOf(this.options.valueOf(name)); ++ } ++ ++ return value; ++ // CraftBukkit end ++ } ++ + public static Properties loadFromFile(Path path) { + try { ++ // CraftBukkit start - SPIGOT-7465, MC-264979: Don't load if file doesn't exist ++ if (!path.toFile().exists()) { ++ return new Properties(); ++ } ++ // CraftBukkit end + Properties properties; + Properties properties1; + +@@ -97,6 +117,11 @@ + + public void store(Path path) { + try { ++ // CraftBukkit start - Don't attempt writing to file if it's read only ++ if (path.toFile().exists() && !path.toFile().canWrite()) { ++ return; ++ } ++ // CraftBukkit end + BufferedWriter bufferedwriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8); + + try { +@@ -122,44 +147,54 @@ + + } + +- private static Function wrapNumberDeserializer(Function function) { ++ private static Function wrapNumberDeserializer(Function parseFunc) { + return (s) -> { + try { +- return (Number) function.apply(s); ++ return (V) parseFunc.apply(s); // CraftBukkit - decompile error + } catch (NumberFormatException numberformatexception) { + return null; + } + }; + } + +- protected static Function dispatchNumberOrString(IntFunction intfunction, Function function) { ++ protected static Function dispatchNumberOrString(IntFunction byId, Function byName) { + return (s) -> { + try { +- return intfunction.apply(Integer.parseInt(s)); ++ return byId.apply(Integer.parseInt(s)); + } catch (NumberFormatException numberformatexception) { +- return function.apply(s); ++ return byName.apply(s); + } + }; + } + + @Nullable +- private String getStringRaw(String s) { +- return (String) this.properties.get(s); ++ private String getStringRaw(String key) { ++ return (String) getOverride(key, this.properties.getProperty(key)); // CraftBukkit + } + + @Nullable +- protected V getLegacy(String s, Function function) { +- String s1 = this.getStringRaw(s); ++ protected V getLegacy(String key, Function mapper) { ++ String s1 = this.getStringRaw(key); + + if (s1 == null) { + return null; + } else { +- this.properties.remove(s); +- return function.apply(s1); ++ this.properties.remove(key); ++ return mapper.apply(s1); + } + } + +- protected V get(String s, Function function, Function function1, V v0) { ++ protected V get(String key, Function mapper, Function toString, V value) { ++ // CraftBukkit start ++ try { ++ return get0(key, mapper, toString, value); ++ } catch (Exception ex) { ++ throw new RuntimeException("Could not load invalidly configured property '" + key + "'", ex); ++ } ++ } ++ ++ private V get0(String s, Function function, Function function1, V v0) { ++ // CraftBukkit end + String s1 = this.getStringRaw(s); + V v1 = MoreObjects.firstNonNull(s1 != null ? function.apply(s1) : null, v0); + +@@ -167,66 +202,66 @@ + return v1; + } + +- protected Settings.MutableValue getMutable(String s, Function function, Function function1, V v0) { +- String s1 = this.getStringRaw(s); +- V v1 = MoreObjects.firstNonNull(s1 != null ? function.apply(s1) : null, v0); ++ protected Settings.MutableValue getMutable(String key, Function mapper, Function toString, V value) { ++ String s1 = this.getStringRaw(key); ++ V v1 = MoreObjects.firstNonNull(s1 != null ? mapper.apply(s1) : null, value); + +- this.properties.put(s, function1.apply(v1)); +- return new Settings.MutableValue<>(s, v1, function1); ++ this.properties.put(key, toString.apply(v1)); ++ return new Settings.MutableValue(key, v1, toString); // CraftBukkit - decompile error + } + +- protected V get(String s, Function function, UnaryOperator unaryoperator, Function function1, V v0) { +- return this.get(s, (s1) -> { +- V v1 = function.apply(s1); ++ protected V get(String key, Function mapper, UnaryOperator unaryoperator, Function toString, V value) { ++ return this.get(key, (s1) -> { ++ V v1 = mapper.apply(s1); + + return v1 != null ? unaryoperator.apply(v1) : null; +- }, function1, v0); ++ }, toString, value); + } + +- protected V get(String s, Function function, V v0) { +- return this.get(s, function, Objects::toString, v0); ++ protected V get(String key, Function mapper, V value) { ++ return this.get(key, mapper, Objects::toString, value); + } + +- protected Settings.MutableValue getMutable(String s, Function function, V v0) { +- return this.getMutable(s, function, Objects::toString, v0); ++ protected Settings.MutableValue getMutable(String key, Function mapper, V value) { ++ return this.getMutable(key, mapper, Objects::toString, value); + } + +- protected String get(String s, String s1) { +- return (String) this.get(s, Function.identity(), Function.identity(), s1); ++ protected String get(String key, String value) { ++ return (String) this.get(key, Function.identity(), Function.identity(), value); + } + + @Nullable +- protected String getLegacyString(String s) { +- return (String) this.getLegacy(s, Function.identity()); ++ protected String getLegacyString(String key) { ++ return (String) this.getLegacy(key, Function.identity()); + } + +- protected int get(String s, int i) { +- return (Integer) this.get(s, wrapNumberDeserializer(Integer::parseInt), i); ++ protected int get(String key, int value) { ++ return (Integer) this.get(key, wrapNumberDeserializer(Integer::parseInt), value); + } + +- protected Settings.MutableValue getMutable(String s, int i) { +- return this.getMutable(s, wrapNumberDeserializer(Integer::parseInt), i); ++ protected Settings.MutableValue getMutable(String key, int value) { ++ return this.getMutable(key, wrapNumberDeserializer(Integer::parseInt), value); + } + +- protected int get(String s, UnaryOperator unaryoperator, int i) { +- return (Integer) this.get(s, wrapNumberDeserializer(Integer::parseInt), unaryoperator, Objects::toString, i); ++ protected int get(String key, UnaryOperator unaryoperator, int value) { ++ return (Integer) this.get(key, wrapNumberDeserializer(Integer::parseInt), unaryoperator, Objects::toString, value); + } + +- protected long get(String s, long i) { +- return (Long) this.get(s, wrapNumberDeserializer(Long::parseLong), i); ++ protected long get(String key, long value) { ++ return (Long) this.get(key, wrapNumberDeserializer(Long::parseLong), value); + } + +- protected boolean get(String s, boolean flag) { +- return (Boolean) this.get(s, Boolean::valueOf, flag); ++ protected boolean get(String key, boolean value) { ++ return (Boolean) this.get(key, Boolean::valueOf, value); + } + +- protected Settings.MutableValue getMutable(String s, boolean flag) { +- return this.getMutable(s, Boolean::valueOf, flag); ++ protected Settings.MutableValue getMutable(String key, boolean value) { ++ return this.getMutable(key, Boolean::valueOf, value); + } + + @Nullable +- protected Boolean getLegacyBoolean(String s) { +- return (Boolean) this.getLegacy(s, Boolean::valueOf); ++ protected Boolean getLegacyBoolean(String key) { ++ return (Boolean) this.getLegacy(key, Boolean::valueOf); + } + + protected Properties cloneProperties() { +@@ -236,7 +271,7 @@ + return properties; + } + +- protected abstract T reload(RegistryAccess registryAccess, Properties properties); ++ protected abstract T reload(RegistryAccess iregistrycustom, Properties properties, OptionSet optionset); // CraftBukkit + + public class MutableValue implements Supplier { + +@@ -244,22 +279,21 @@ + private final V value; + private final Function serializer; + +- MutableValue(String s, V v0, Function function) { ++ MutableValue(String s, V object, Function function) { // CraftBukkit - decompile error + this.key = s; +- this.value = v0; ++ this.value = object; + this.serializer = function; + } + +- @Override + public V get() { + return this.value; + } + +- public T update(RegistryAccess registryaccess, V v0) { ++ public T update(RegistryAccess registryAccess, V newValue) { + Properties properties = Settings.this.cloneProperties(); + +- properties.put(this.key, this.serializer.apply(v0)); +- return Settings.this.reload(registryaccess, properties); ++ properties.put(this.key, this.serializer.apply(newValue)); ++ return Settings.this.reload(registryAccess, properties, Settings.this.options); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/gui/MinecraftServerGui.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/gui/MinecraftServerGui.java.patch new file mode 100644 index 0000000000..d8691c8b4d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/gui/MinecraftServerGui.java.patch @@ -0,0 +1,118 @@ +--- a/net/minecraft/server/gui/MinecraftServerGui.java ++++ b/net/minecraft/server/gui/MinecraftServerGui.java +@@ -44,7 +44,7 @@ + private final Collection finalizers = Lists.newArrayList(); + final AtomicBoolean isClosing = new AtomicBoolean(); + +- public static MinecraftServerGui showFrameFor(final DedicatedServer dedicatedserver) { ++ public static MinecraftServerGui showFrameFor(final DedicatedServer server) { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception exception) { +@@ -52,32 +52,31 @@ + } + + final JFrame jframe = new JFrame("Minecraft server"); +- final MinecraftServerGui minecraftservergui = new MinecraftServerGui(dedicatedserver); ++ final MinecraftServerGui servergui = new MinecraftServerGui(server); + + jframe.setDefaultCloseOperation(2); +- jframe.add(minecraftservergui); ++ jframe.add(servergui); + jframe.pack(); + jframe.setLocationRelativeTo((Component) null); + jframe.setVisible(true); + jframe.addWindowListener(new WindowAdapter() { +- @Override + public void windowClosing(WindowEvent windowevent) { +- if (!minecraftservergui.isClosing.getAndSet(true)) { ++ if (!servergui.isClosing.getAndSet(true)) { + jframe.setTitle("Minecraft server - shutting down!"); +- dedicatedserver.halt(true); +- minecraftservergui.runFinalizers(); ++ server.halt(true); ++ servergui.runFinalizers(); + } + + } + }); + Objects.requireNonNull(jframe); +- minecraftservergui.addFinalizer(jframe::dispose); +- minecraftservergui.start(); +- return minecraftservergui; ++ servergui.addFinalizer(jframe::dispose); ++ servergui.start(); ++ return servergui; + } + +- private MinecraftServerGui(DedicatedServer dedicatedserver) { +- this.server = dedicatedserver; ++ private MinecraftServerGui(DedicatedServer server) { ++ this.server = server; + this.setPreferredSize(new Dimension(854, 480)); + this.setLayout(new BorderLayout()); + +@@ -90,18 +89,18 @@ + + } + +- public void addFinalizer(Runnable runnable) { +- this.finalizers.add(runnable); ++ public void addFinalizer(Runnable finalizer) { ++ this.finalizers.add(finalizer); + } + + private JComponent buildInfoPanel() { + JPanel jpanel = new JPanel(new BorderLayout()); +- StatsComponent statscomponent = new StatsComponent(this.server); +- Collection collection = this.finalizers; ++ StatsComponent guistatscomponent = new StatsComponent(this.server); ++ Collection collection = this.finalizers; // CraftBukkit - decompile error + +- Objects.requireNonNull(statscomponent); +- collection.add(statscomponent::close); +- jpanel.add(statscomponent, "North"); ++ Objects.requireNonNull(guistatscomponent); ++ collection.add(guistatscomponent::close); ++ jpanel.add(guistatscomponent, "North"); + jpanel.add(this.buildPlayerPanel(), "Center"); + jpanel.setBorder(new TitledBorder(new EtchedBorder(), "Stats")); + return jpanel; +@@ -134,7 +133,6 @@ + jtextfield.setText(""); + }); + jtextarea.addFocusListener(new FocusAdapter() { +- @Override + public void focusGained(FocusEvent focusevent) {} + }); + jpanel.add(jscrollpane, "Center"); +@@ -168,22 +166,23 @@ + this.finalizers.forEach(Runnable::run); + } + +- public void print(JTextArea jtextarea, JScrollPane jscrollpane, String s) { ++ private static final java.util.regex.Pattern ANSI = java.util.regex.Pattern.compile("\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})*)?[m|K]"); // CraftBukkit ++ public void print(JTextArea textArea, JScrollPane scrollPane, String line) { + if (!SwingUtilities.isEventDispatchThread()) { + SwingUtilities.invokeLater(() -> { +- this.print(jtextarea, jscrollpane, s); ++ this.print(textArea, scrollPane, line); + }); + } else { +- Document document = jtextarea.getDocument(); +- JScrollBar jscrollbar = jscrollpane.getVerticalScrollBar(); ++ Document document = textArea.getDocument(); ++ JScrollBar jscrollbar = scrollPane.getVerticalScrollBar(); + boolean flag = false; + +- if (jscrollpane.getViewport().getView() == jtextarea) { ++ if (scrollPane.getViewport().getView() == textArea) { + flag = (double) jscrollbar.getValue() + jscrollbar.getSize().getHeight() + (double) (MinecraftServerGui.MONOSPACED.getSize() * 4) > (double) jscrollbar.getMaximum(); + } + + try { +- document.insertString(document.getLength(), s, (AttributeSet) null); ++ document.insertString(document.getLength(), ANSI.matcher(line).replaceAll(""), (AttributeSet) null); // CraftBukkit + } catch (BadLocationException badlocationexception) { + ; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/level/ChunkHolder.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/level/ChunkHolder.java.patch new file mode 100644 index 0000000000..f589430b82 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/level/ChunkHolder.java.patch @@ -0,0 +1,630 @@ +--- a/net/minecraft/server/level/ChunkHolder.java ++++ b/net/minecraft/server/level/ChunkHolder.java +@@ -23,11 +23,11 @@ + import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket; + import net.minecraft.util.DebugBuffer; + import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.EnumSkyBlock; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelHeightAccessor; +-import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.level.chunk.ImposterProtoChunk; +@@ -36,23 +36,27 @@ + import net.minecraft.world.level.chunk.ProtoChunk; + import net.minecraft.world.level.lighting.LevelLightEngine; + ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++// CraftBukkit end ++ + public class ChunkHolder { + +- public static final Either UNLOADED_CHUNK = Either.right(ChunkHolder.ChunkLoadingFailure.UNLOADED); +- public static final CompletableFuture> UNLOADED_CHUNK_FUTURE = CompletableFuture.completedFuture(ChunkHolder.UNLOADED_CHUNK); +- public static final Either UNLOADED_LEVEL_CHUNK = Either.right(ChunkHolder.ChunkLoadingFailure.UNLOADED); +- private static final Either NOT_DONE_YET = Either.right(ChunkHolder.ChunkLoadingFailure.UNLOADED); +- private static final CompletableFuture> UNLOADED_LEVEL_CHUNK_FUTURE = CompletableFuture.completedFuture(ChunkHolder.UNLOADED_LEVEL_CHUNK); ++ public static final Either UNLOADED_CHUNK = Either.right(ChunkHolder.Failure.UNLOADED); ++ public static final CompletableFuture> UNLOADED_CHUNK_FUTURE = CompletableFuture.completedFuture(ChunkHolder.UNLOADED_CHUNK); ++ public static final Either UNLOADED_LEVEL_CHUNK = Either.right(ChunkHolder.Failure.UNLOADED); ++ private static final Either NOT_DONE_YET = Either.right(ChunkHolder.Failure.UNLOADED); ++ private static final CompletableFuture> UNLOADED_LEVEL_CHUNK_FUTURE = CompletableFuture.completedFuture(ChunkHolder.UNLOADED_LEVEL_CHUNK); + private static final List CHUNK_STATUSES = ChunkStatus.getStatusList(); +- private final AtomicReferenceArray>> futures; ++ private final AtomicReferenceArray>> futures; + private final LevelHeightAccessor levelHeightAccessor; +- private volatile CompletableFuture> fullChunkFuture; +- private volatile CompletableFuture> tickingChunkFuture; +- private volatile CompletableFuture> entityTickingChunkFuture; ++ private volatile CompletableFuture> fullChunkFuture; ++ private volatile CompletableFuture> tickingChunkFuture; ++ private volatile CompletableFuture> entityTickingChunkFuture; + private CompletableFuture chunkToSave; + @Nullable + private final DebugBuffer chunkToSaveHistory; +- private int oldTicketLevel; ++ public int oldTicketLevel; + private int ticketLevel; + private int queueLevel; + final ChunkPos pos; +@@ -62,62 +66,76 @@ + private final BitSet skyChangedLightSectionFilter; + private final LevelLightEngine lightEngine; + private final ChunkHolder.LevelChangeListener onLevelChange; +- private final ChunkHolder.PlayerProvider playerProvider; ++ public final ChunkHolder.PlayerProvider playerProvider; + private boolean wasAccessibleSinceLastSave; + private CompletableFuture pendingFullStateConfirmation; + private CompletableFuture sendSync; + +- public ChunkHolder(ChunkPos chunkpos, int i, LevelHeightAccessor levelheightaccessor, LevelLightEngine levellightengine, ChunkHolder.LevelChangeListener chunkholder_levelchangelistener, ChunkHolder.PlayerProvider chunkholder_playerprovider) { ++ public ChunkHolder(ChunkPos pos, int ticketLevel, LevelHeightAccessor levelHeightAccessor, LevelLightEngine lightEngine, ChunkHolder.LevelChangeListener onLevelChange, ChunkHolder.PlayerProvider playerProvider) { + this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); + this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; + this.tickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; + this.entityTickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; +- this.chunkToSave = CompletableFuture.completedFuture((Object) null); ++ this.chunkToSave = CompletableFuture.completedFuture(null); // CraftBukkit - decompile error + this.chunkToSaveHistory = null; + this.blockChangedLightSectionFilter = new BitSet(); + this.skyChangedLightSectionFilter = new BitSet(); +- this.pendingFullStateConfirmation = CompletableFuture.completedFuture((Object) null); +- this.sendSync = CompletableFuture.completedFuture((Object) null); +- this.pos = chunkpos; +- this.levelHeightAccessor = levelheightaccessor; +- this.lightEngine = levellightengine; +- this.onLevelChange = chunkholder_levelchangelistener; +- this.playerProvider = chunkholder_playerprovider; ++ this.pendingFullStateConfirmation = CompletableFuture.completedFuture(null); // CraftBukkit - decompile error ++ this.sendSync = CompletableFuture.completedFuture(null); // CraftBukkit - decompile error ++ this.pos = pos; ++ this.levelHeightAccessor = levelHeightAccessor; ++ this.lightEngine = lightEngine; ++ this.onLevelChange = onLevelChange; ++ this.playerProvider = playerProvider; + this.oldTicketLevel = ChunkLevel.MAX_LEVEL + 1; + this.ticketLevel = this.oldTicketLevel; + this.queueLevel = this.oldTicketLevel; +- this.setTicketLevel(i); +- this.changedBlocksPerSection = new ShortSet[levelheightaccessor.getSectionsCount()]; ++ this.setTicketLevel(ticketLevel); ++ this.changedBlocksPerSection = new ShortSet[levelHeightAccessor.getSectionsCount()]; + } + +- public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus chunkstatus) { +- CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(chunkstatus.getIndex()); ++ // CraftBukkit start ++ public LevelChunk getFullChunkNow() { ++ // Note: We use the oldTicketLevel for isLoaded checks. ++ if (!ChunkLevel.fullStatus(this.oldTicketLevel).isOrAfter(FullChunkStatus.FULL)) return null; ++ return this.getFullChunkNowUnchecked(); ++ } + ++ public LevelChunk getFullChunkNowUnchecked() { ++ CompletableFuture> statusFuture = this.getFutureIfPresentUnchecked(ChunkStatus.FULL); ++ Either either = (Either) statusFuture.getNow(null); ++ return (either == null) ? null : (LevelChunk) either.left().orElse(null); ++ } ++ // CraftBukkit end ++ ++ public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus chunkStatus) { ++ CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(chunkStatus.getIndex()); ++ + return completablefuture == null ? ChunkHolder.UNLOADED_CHUNK_FUTURE : completablefuture; + } + +- public CompletableFuture> getFutureIfPresent(ChunkStatus chunkstatus) { +- return ChunkLevel.generationStatus(this.ticketLevel).isOrAfter(chunkstatus) ? this.getFutureIfPresentUnchecked(chunkstatus) : ChunkHolder.UNLOADED_CHUNK_FUTURE; ++ public CompletableFuture> getFutureIfPresent(ChunkStatus chunkStatus) { ++ return ChunkLevel.generationStatus(this.ticketLevel).isOrAfter(chunkStatus) ? this.getFutureIfPresentUnchecked(chunkStatus) : ChunkHolder.UNLOADED_CHUNK_FUTURE; + } + +- public CompletableFuture> getTickingChunkFuture() { ++ public CompletableFuture> getTickingChunkFuture() { + return this.tickingChunkFuture; + } + +- public CompletableFuture> getEntityTickingChunkFuture() { ++ public CompletableFuture> getEntityTickingChunkFuture() { + return this.entityTickingChunkFuture; + } + +- public CompletableFuture> getFullChunkFuture() { ++ public CompletableFuture> getFullChunkFuture() { + return this.fullChunkFuture; + } + + @Nullable + public LevelChunk getTickingChunk() { +- CompletableFuture> completablefuture = this.getTickingChunkFuture(); +- Either either = (Either) completablefuture.getNow((Object) null); ++ CompletableFuture> completablefuture = this.getTickingChunkFuture(); ++ Either either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error + +- return either == null ? null : (LevelChunk) either.left().orElse((Object) null); ++ return either == null ? null : (LevelChunk) either.left().orElse(null); // CraftBukkit - decompile error + } + + public CompletableFuture getChunkSendSyncFuture() { +@@ -131,17 +149,17 @@ + + @Nullable + public LevelChunk getFullChunk() { +- CompletableFuture> completablefuture = this.getFullChunkFuture(); +- Either either = (Either) completablefuture.getNow((Object) null); ++ CompletableFuture> completablefuture = this.getFullChunkFuture(); ++ Either either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error + +- return either == null ? null : (LevelChunk) either.left().orElse((Object) null); ++ return either == null ? null : (LevelChunk) either.left().orElse(null); // CraftBukkit - decompile error + } + + @Nullable + public ChunkStatus getLastAvailableStatus() { + for (int i = ChunkHolder.CHUNK_STATUSES.size() - 1; i >= 0; --i) { + ChunkStatus chunkstatus = (ChunkStatus) ChunkHolder.CHUNK_STATUSES.get(i); +- CompletableFuture> completablefuture = this.getFutureIfPresentUnchecked(chunkstatus); ++ CompletableFuture> completablefuture = this.getFutureIfPresentUnchecked(chunkstatus); + + if (((Either) completablefuture.getNow(ChunkHolder.UNLOADED_CHUNK)).left().isPresent()) { + return chunkstatus; +@@ -155,7 +173,7 @@ + public ChunkAccess getLastAvailable() { + for (int i = ChunkHolder.CHUNK_STATUSES.size() - 1; i >= 0; --i) { + ChunkStatus chunkstatus = (ChunkStatus) ChunkHolder.CHUNK_STATUSES.get(i); +- CompletableFuture> completablefuture = this.getFutureIfPresentUnchecked(chunkstatus); ++ CompletableFuture> completablefuture = this.getFutureIfPresentUnchecked(chunkstatus); + + if (!completablefuture.isCompletedExceptionally()) { + Optional optional = ((Either) completablefuture.getNow(ChunkHolder.UNLOADED_CHUNK)).left(); +@@ -173,39 +191,40 @@ + return this.chunkToSave; + } + +- public void blockChanged(BlockPos blockpos) { +- LevelChunk levelchunk = this.getTickingChunk(); ++ public void blockChanged(BlockPos pos) { ++ LevelChunk chunk = this.getTickingChunk(); + +- if (levelchunk != null) { +- int i = this.levelHeightAccessor.getSectionIndex(blockpos.getY()); ++ if (chunk != null) { ++ int i = this.levelHeightAccessor.getSectionIndex(pos.getY()); + ++ if (i < 0 || i >= this.changedBlocksPerSection.length) return; // CraftBukkit - SPIGOT-6086, SPIGOT-6296 + if (this.changedBlocksPerSection[i] == null) { + this.hasChangedSections = true; + this.changedBlocksPerSection[i] = new ShortOpenHashSet(); + } + +- this.changedBlocksPerSection[i].add(SectionPos.sectionRelativePos(blockpos)); ++ this.changedBlocksPerSection[i].add(SectionPos.sectionRelativePos(pos)); + } + } + +- public void sectionLightChanged(LightLayer lightlayer, int i) { +- Either either = (Either) this.getFutureIfPresent(ChunkStatus.INITIALIZE_LIGHT).getNow((Object) null); ++ public void sectionLightChanged(EnumSkyBlock type, int sectionY) { ++ Either either = (Either) this.getFutureIfPresent(ChunkStatus.INITIALIZE_LIGHT).getNow(null); // CraftBukkit - decompile error + + if (either != null) { +- ChunkAccess chunkaccess = (ChunkAccess) either.left().orElse((Object) null); ++ ChunkAccess ichunkaccess = (ChunkAccess) either.left().orElse(null); // CraftBukkit - decompile error + +- if (chunkaccess != null) { +- chunkaccess.setUnsaved(true); +- LevelChunk levelchunk = this.getTickingChunk(); ++ if (ichunkaccess != null) { ++ ichunkaccess.setUnsaved(true); ++ LevelChunk chunk = this.getTickingChunk(); + +- if (levelchunk != null) { ++ if (chunk != null) { + int j = this.lightEngine.getMinLightSection(); + int k = this.lightEngine.getMaxLightSection(); + +- if (i >= j && i <= k) { +- int l = i - j; ++ if (sectionY >= j && sectionY <= k) { ++ int l = sectionY - j; + +- if (lightlayer == LightLayer.SKY) { ++ if (type == EnumSkyBlock.SKY) { + this.skyChangedLightSectionFilter.set(l); + } else { + this.blockChangedLightSectionFilter.set(l); +@@ -217,17 +236,17 @@ + } + } + +- public void broadcastChanges(LevelChunk levelchunk) { ++ public void broadcastChanges(LevelChunk chunk) { + if (this.hasChangedSections || !this.skyChangedLightSectionFilter.isEmpty() || !this.blockChangedLightSectionFilter.isEmpty()) { +- Level level = levelchunk.getLevel(); ++ Level world = chunk.getLevel(); + List list; + + if (!this.skyChangedLightSectionFilter.isEmpty() || !this.blockChangedLightSectionFilter.isEmpty()) { + list = this.playerProvider.getPlayers(this.pos, true); + if (!list.isEmpty()) { +- ClientboundLightUpdatePacket clientboundlightupdatepacket = new ClientboundLightUpdatePacket(levelchunk.getPos(), this.lightEngine, this.skyChangedLightSectionFilter, this.blockChangedLightSectionFilter); ++ ClientboundLightUpdatePacket packetplayoutlightupdate = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, this.skyChangedLightSectionFilter, this.blockChangedLightSectionFilter); + +- this.broadcast(list, clientboundlightupdatepacket); ++ this.broadcast(list, packetplayoutlightupdate); + } + + this.skyChangedLightSectionFilter.clear(); +@@ -244,21 +263,24 @@ + this.changedBlocksPerSection[i] = null; + if (!list.isEmpty()) { + int j = this.levelHeightAccessor.getSectionYFromSectionIndex(i); +- SectionPos sectionpos = SectionPos.of(levelchunk.getPos(), j); ++ SectionPos sectionposition = SectionPos.of(chunk.getPos(), j); + + if (shortset.size() == 1) { +- BlockPos blockpos = sectionpos.relativeToBlockPos(shortset.iterator().nextShort()); +- BlockState blockstate = level.getBlockState(blockpos); ++ BlockPos blockposition = sectionposition.relativeToBlockPos(shortset.iterator().nextShort()); ++ IBlockData iblockdata = world.getBlockState(blockposition); + +- this.broadcast(list, new ClientboundBlockUpdatePacket(blockpos, blockstate)); +- this.broadcastBlockEntityIfNeeded(list, level, blockpos, blockstate); ++ this.broadcast(list, new ClientboundBlockUpdatePacket(blockposition, iblockdata)); ++ this.broadcastBlockEntityIfNeeded(list, world, blockposition, iblockdata); + } else { +- LevelChunkSection levelchunksection = levelchunk.getSection(i); +- ClientboundSectionBlocksUpdatePacket clientboundsectionblocksupdatepacket = new ClientboundSectionBlocksUpdatePacket(sectionpos, shortset, levelchunksection); ++ LevelChunkSection chunksection = chunk.getSection(i); ++ ClientboundSectionBlocksUpdatePacket packetplayoutmultiblockchange = new ClientboundSectionBlocksUpdatePacket(sectionposition, shortset, chunksection); + +- this.broadcast(list, clientboundsectionblocksupdatepacket); +- clientboundsectionblocksupdatepacket.runUpdates((blockpos1, blockstate1) -> { +- this.broadcastBlockEntityIfNeeded(list, level, blockpos1, blockstate1); ++ this.broadcast(list, packetplayoutmultiblockchange); ++ // CraftBukkit start ++ List finalList = list; ++ packetplayoutmultiblockchange.runUpdates((blockposition1, iblockdata1) -> { ++ this.broadcastBlockEntityIfNeeded(finalList, world, blockposition1, iblockdata1); ++ // CraftBukkit end + }); + } + } +@@ -270,43 +292,43 @@ + } + } + +- private void broadcastBlockEntityIfNeeded(List list, Level level, BlockPos blockpos, BlockState blockstate) { +- if (blockstate.hasBlockEntity()) { +- this.broadcastBlockEntity(list, level, blockpos); ++ private void broadcastBlockEntityIfNeeded(List players, Level level, BlockPos pos, IBlockData state) { ++ if (state.hasBlockEntity()) { ++ this.broadcastBlockEntity(players, level, pos); + } + + } + +- private void broadcastBlockEntity(List list, Level level, BlockPos blockpos) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ private void broadcastBlockEntity(List players, Level level, BlockPos pox) { ++ BlockEntity tileentity = level.getBlockEntity(pox); + +- if (blockentity != null) { +- Packet packet = blockentity.getUpdatePacket(); ++ if (tileentity != null) { ++ Packet packet = tileentity.getUpdatePacket(); + + if (packet != null) { +- this.broadcast(list, packet); ++ this.broadcast(players, packet); + } + } + + } + +- private void broadcast(List list, Packet packet) { +- list.forEach((serverplayer) -> { +- serverplayer.connection.send(packet); ++ private void broadcast(List players, Packet packet) { ++ players.forEach((entityplayer) -> { ++ entityplayer.connection.send(packet); + }); + } + +- public CompletableFuture> getOrScheduleFuture(ChunkStatus chunkstatus, ChunkMap chunkmap) { +- int i = chunkstatus.getIndex(); +- CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(i); ++ public CompletableFuture> getOrScheduleFuture(ChunkStatus status, ChunkMap map) { ++ int i = status.getIndex(); ++ CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(i); + + if (completablefuture != null) { +- Either either = (Either) completablefuture.getNow(ChunkHolder.NOT_DONE_YET); ++ Either either = (Either) completablefuture.getNow(ChunkHolder.NOT_DONE_YET); + + if (either == null) { +- String s = "value in future for status: " + chunkstatus + " was incorrectly set to null at chunk: " + this.pos; ++ String s = "value in future for status: " + status + " was incorrectly set to null at chunk: " + this.pos; + +- throw chunkmap.debugFuturesAndCreateReportedException(new IllegalStateException("null value previously set for chunk status"), s); ++ throw map.debugFuturesAndCreateReportedException(new IllegalStateException("null value previously set for chunk status"), s); + } + + if (either == ChunkHolder.NOT_DONE_YET || either.right().isEmpty()) { +@@ -314,10 +336,10 @@ + } + } + +- if (ChunkLevel.generationStatus(this.ticketLevel).isOrAfter(chunkstatus)) { +- CompletableFuture> completablefuture1 = chunkmap.schedule(this, chunkstatus); ++ if (ChunkLevel.generationStatus(this.ticketLevel).isOrAfter(status)) { ++ CompletableFuture> completablefuture1 = map.schedule(this, status); + +- this.updateChunkToSave(completablefuture1, "schedule " + chunkstatus); ++ this.updateChunkToSave(completablefuture1, "schedule " + status); + this.futures.set(i, completablefuture1); + return completablefuture1; + } else { +@@ -325,26 +347,26 @@ + } + } + +- protected void addSaveDependency(String s, CompletableFuture completablefuture) { ++ protected void addSaveDependency(String source, CompletableFuture future) { + if (this.chunkToSaveHistory != null) { +- this.chunkToSaveHistory.push(new ChunkHolder.ChunkSaveDebug(Thread.currentThread(), completablefuture, s)); ++ this.chunkToSaveHistory.push(new ChunkHolder.ChunkSaveDebug(Thread.currentThread(), future, source)); + } + +- this.chunkToSave = this.chunkToSave.thenCombine(completablefuture, (chunkaccess, object) -> { +- return chunkaccess; ++ this.chunkToSave = this.chunkToSave.thenCombine(future, (ichunkaccess, object) -> { ++ return ichunkaccess; + }); + } + +- private void updateChunkToSave(CompletableFuture> completablefuture, String s) { ++ private void updateChunkToSave(CompletableFuture> feature, String source) { + if (this.chunkToSaveHistory != null) { +- this.chunkToSaveHistory.push(new ChunkHolder.ChunkSaveDebug(Thread.currentThread(), completablefuture, s)); ++ this.chunkToSaveHistory.push(new ChunkHolder.ChunkSaveDebug(Thread.currentThread(), feature, source)); + } + +- this.chunkToSave = this.chunkToSave.thenCombine(completablefuture, (chunkaccess, either) -> { +- return (ChunkAccess) either.map((chunkaccess1) -> { +- return chunkaccess1; +- }, (chunkholder_chunkloadingfailure) -> { +- return chunkaccess; ++ this.chunkToSave = this.chunkToSave.thenCombine(feature, (ichunkaccess, either) -> { ++ return (ChunkAccess) either.map((ichunkaccess1) -> { ++ return ichunkaccess1; ++ }, (playerchunk_failure) -> { ++ return ichunkaccess; + }); + }); + } +@@ -376,52 +398,75 @@ + return this.queueLevel; + } + +- private void setQueueLevel(int i) { +- this.queueLevel = i; ++ private void setQueueLevel(int queueLevel) { ++ this.queueLevel = queueLevel; + } + +- public void setTicketLevel(int i) { +- this.ticketLevel = i; ++ public void setTicketLevel(int level) { ++ this.ticketLevel = level; + } + +- private void scheduleFullChunkPromotion(ChunkMap chunkmap, CompletableFuture> completablefuture, Executor executor, FullChunkStatus fullchunkstatus) { ++ private void scheduleFullChunkPromotion(ChunkMap chunkMap, CompletableFuture> future, Executor executor, FullChunkStatus fullChunkStatus) { + this.pendingFullStateConfirmation.cancel(false); + CompletableFuture completablefuture1 = new CompletableFuture(); + + completablefuture1.thenRunAsync(() -> { +- chunkmap.onFullChunkStatusChange(this.pos, fullchunkstatus); ++ chunkMap.onFullChunkStatusChange(this.pos, fullChunkStatus); + }, executor); + this.pendingFullStateConfirmation = completablefuture1; +- completablefuture.thenAccept((either) -> { +- either.ifLeft((levelchunk) -> { +- completablefuture1.complete((Object) null); ++ future.thenAccept((either) -> { ++ either.ifLeft((chunk) -> { ++ completablefuture1.complete(null); // CraftBukkit - decompile error + }); + }); + } + +- private void demoteFullChunk(ChunkMap chunkmap, FullChunkStatus fullchunkstatus) { ++ private void demoteFullChunk(ChunkMap chunkMap, FullChunkStatus fullChunkStatus) { + this.pendingFullStateConfirmation.cancel(false); +- chunkmap.onFullChunkStatusChange(this.pos, fullchunkstatus); ++ chunkMap.onFullChunkStatusChange(this.pos, fullChunkStatus); + } + +- protected void updateFutures(ChunkMap chunkmap, Executor executor) { ++ protected void updateFutures(ChunkMap chunkMap, Executor executor) { + ChunkStatus chunkstatus = ChunkLevel.generationStatus(this.oldTicketLevel); + ChunkStatus chunkstatus1 = ChunkLevel.generationStatus(this.ticketLevel); + boolean flag = ChunkLevel.isLoaded(this.oldTicketLevel); + boolean flag1 = ChunkLevel.isLoaded(this.ticketLevel); + FullChunkStatus fullchunkstatus = ChunkLevel.fullStatus(this.oldTicketLevel); + FullChunkStatus fullchunkstatus1 = ChunkLevel.fullStatus(this.ticketLevel); ++ // CraftBukkit start ++ // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins. ++ if (fullchunkstatus.isOrAfter(FullChunkStatus.FULL) && !fullchunkstatus1.isOrAfter(FullChunkStatus.FULL)) { ++ this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { ++ LevelChunk chunk = (LevelChunk)either.left().orElse(null); ++ if (chunk != null) { ++ chunkMap.callbackExecutor.execute(() -> { ++ // Minecraft will apply the chunks tick lists to the world once the chunk got loaded, and then store the tick ++ // lists again inside the chunk once the chunk becomes inaccessible and set the chunk's needsSaving flag. ++ // These actions may however happen deferred, so we manually set the needsSaving flag already here. ++ chunk.setUnsaved(true); ++ chunk.unloadCallback(); ++ }); ++ } ++ }).exceptionally((throwable) -> { ++ // ensure exceptions are printed, by default this is not the case ++ MinecraftServer.LOGGER.error("Failed to schedule unload callback for chunk " + ChunkHolder.this.pos, throwable); ++ return null; ++ }); + ++ // Run callback right away if the future was already done ++ chunkMap.callbackExecutor.run(); ++ } ++ // CraftBukkit end ++ + if (flag) { +- Either either = Either.right(new ChunkHolder.ChunkLoadingFailure() { +- @Override ++ Either either = Either.right(new ChunkHolder.Failure() { + public String toString() { + return "Unloaded ticket level " + ChunkHolder.this.pos; + } + }); + + for (int i = flag1 ? chunkstatus1.getIndex() + 1 : 0; i <= chunkstatus.getIndex(); ++i) { +- CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(i); ++ CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(i); + + if (completablefuture == null) { + this.futures.set(i, CompletableFuture.completedFuture(either)); +@@ -434,8 +479,8 @@ + + this.wasAccessibleSinceLastSave |= flag3; + if (!flag2 && flag3) { +- this.fullChunkFuture = chunkmap.prepareAccessibleChunk(this); +- this.scheduleFullChunkPromotion(chunkmap, this.fullChunkFuture, executor, FullChunkStatus.FULL); ++ this.fullChunkFuture = chunkMap.prepareAccessibleChunk(this); ++ this.scheduleFullChunkPromotion(chunkMap, this.fullChunkFuture, executor, FullChunkStatus.FULL); + this.updateChunkToSave(this.fullChunkFuture, "full"); + } + +@@ -448,8 +493,8 @@ + boolean flag5 = fullchunkstatus1.isOrAfter(FullChunkStatus.BLOCK_TICKING); + + if (!flag4 && flag5) { +- this.tickingChunkFuture = chunkmap.prepareTickingChunk(this); +- this.scheduleFullChunkPromotion(chunkmap, this.tickingChunkFuture, executor, FullChunkStatus.BLOCK_TICKING); ++ this.tickingChunkFuture = chunkMap.prepareTickingChunk(this); ++ this.scheduleFullChunkPromotion(chunkMap, this.tickingChunkFuture, executor, FullChunkStatus.BLOCK_TICKING); + this.updateChunkToSave(this.tickingChunkFuture, "ticking"); + } + +@@ -466,8 +511,8 @@ + throw (IllegalStateException) Util.pauseInIde(new IllegalStateException()); + } + +- this.entityTickingChunkFuture = chunkmap.prepareEntityTickingChunk(this); +- this.scheduleFullChunkPromotion(chunkmap, this.entityTickingChunkFuture, executor, FullChunkStatus.ENTITY_TICKING); ++ this.entityTickingChunkFuture = chunkMap.prepareEntityTickingChunk(this); ++ this.scheduleFullChunkPromotion(chunkMap, this.entityTickingChunkFuture, executor, FullChunkStatus.ENTITY_TICKING); + this.updateChunkToSave(this.entityTickingChunkFuture, "entity ticking"); + } + +@@ -477,11 +522,31 @@ + } + + if (!fullchunkstatus1.isOrAfter(fullchunkstatus)) { +- this.demoteFullChunk(chunkmap, fullchunkstatus1); ++ this.demoteFullChunk(chunkMap, fullchunkstatus1); + } + + this.onLevelChange.onLevelChange(this.pos, this::getQueueLevel, this.ticketLevel, this::setQueueLevel); + this.oldTicketLevel = this.ticketLevel; ++ // CraftBukkit start ++ // ChunkLoadEvent: Called after the chunk is loaded: isChunkLoaded returns true and chunk is ready to be modified by plugins. ++ if (!fullchunkstatus.isOrAfter(FullChunkStatus.FULL) && fullchunkstatus1.isOrAfter(FullChunkStatus.FULL)) { ++ this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { ++ LevelChunk chunk = (LevelChunk)either.left().orElse(null); ++ if (chunk != null) { ++ chunkMap.callbackExecutor.execute(() -> { ++ chunk.loadCallback(); ++ }); ++ } ++ }).exceptionally((throwable) -> { ++ // ensure exceptions are printed, by default this is not the case ++ MinecraftServer.LOGGER.error("Failed to schedule load callback for chunk " + ChunkHolder.this.pos, throwable); ++ return null; ++ }); ++ ++ // Run callback right away if the future was already done ++ chunkMap.callbackExecutor.run(); ++ } ++ // CraftBukkit end + } + + public boolean wasAccessibleSinceLastSave() { +@@ -492,24 +557,24 @@ + this.wasAccessibleSinceLastSave = ChunkLevel.fullStatus(this.ticketLevel).isOrAfter(FullChunkStatus.FULL); + } + +- public void replaceProtoChunk(ImposterProtoChunk imposterprotochunk) { ++ public void replaceProtoChunk(ImposterProtoChunk imposter) { + for (int i = 0; i < this.futures.length(); ++i) { +- CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(i); ++ CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(i); + + if (completablefuture != null) { + Optional optional = ((Either) completablefuture.getNow(ChunkHolder.UNLOADED_CHUNK)).left(); + + if (!optional.isEmpty() && optional.get() instanceof ProtoChunk) { +- this.futures.set(i, CompletableFuture.completedFuture(Either.left(imposterprotochunk))); ++ this.futures.set(i, CompletableFuture.completedFuture(Either.left(imposter))); + } + } + } + +- this.updateChunkToSave(CompletableFuture.completedFuture(Either.left(imposterprotochunk.getWrapped())), "replaceProto"); ++ this.updateChunkToSave(CompletableFuture.completedFuture(Either.left(imposter.getWrapped())), "replaceProto"); + } + +- public List>>> getAllFutures() { +- List>>> list = new ArrayList(); ++ public List>>> getAllFutures() { ++ List>>> list = new ArrayList(); + + for (int i = 0; i < ChunkHolder.CHUNK_STATUSES.size(); ++i) { + list.add(Pair.of((ChunkStatus) ChunkHolder.CHUNK_STATUSES.get(i), (CompletableFuture) this.futures.get(i))); +@@ -521,7 +586,7 @@ + @FunctionalInterface + public interface LevelChangeListener { + +- void onLevelChange(ChunkPos chunkPos, IntSupplier intSupplier, int i, IntConsumer intConsumer); ++ void onLevelChange(ChunkPos chunkPos, IntSupplier intsupplier, int i, IntConsumer intconsumer); + } + + public interface PlayerProvider { +@@ -535,17 +600,16 @@ + private final CompletableFuture future; + private final String source; + +- ChunkSaveDebug(Thread thread, CompletableFuture completablefuture, String s) { ++ ChunkSaveDebug(Thread thread, CompletableFuture future, String source) { + this.thread = thread; +- this.future = completablefuture; +- this.source = s; ++ this.future = future; ++ this.source = source; + } + } + +- public interface ChunkLoadingFailure { ++ public interface Failure { + +- ChunkHolder.ChunkLoadingFailure UNLOADED = new ChunkHolder.ChunkLoadingFailure() { +- @Override ++ ChunkHolder.Failure UNLOADED = new ChunkHolder.Failure() { + public String toString() { + return "UNLOADED"; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/level/ChunkMap.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/level/ChunkMap.java.patch new file mode 100644 index 0000000000..0eb9c2a4f2 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/level/ChunkMap.java.patch @@ -0,0 +1,1896 @@ +--- a/net/minecraft/server/level/ChunkMap.java ++++ b/net/minecraft/server/level/ChunkMap.java +@@ -100,6 +100,9 @@ + import net.minecraft.world.phys.Vec3; + import org.apache.commons.lang3.mutable.MutableBoolean; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.generator.CustomChunkGenerator; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider { + +@@ -113,38 +116,59 @@ + public static final int MIN_VIEW_DISTANCE = 2; + public static final int MAX_VIEW_DISTANCE = 32; + public static final int FORCED_TICKET_LEVEL = ChunkLevel.byStatus(FullChunkStatus.ENTITY_TICKING); +- private final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); +- private volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; ++ public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); ++ public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; + private final Long2ObjectLinkedOpenHashMap pendingUnloads; + private final LongSet entitiesInLevel; +- final ServerLevel level; ++ public final ServerLevel level; + private final ThreadedLevelLightEngine lightEngine; + private final BlockableEventLoop mainThreadExecutor; +- private ChunkGenerator generator; ++ public ChunkGenerator generator; + private final RandomState randomState; + private final ChunkGeneratorStructureState chunkGeneratorState; + private final Supplier overworldDataStorage; + private final PoiManager poiManager; +- final LongSet toDrop; ++ public final LongSet toDrop; + private boolean modified; + private final ChunkTaskPriorityQueueSorter queueSorter; + private final ProcessorHandle> worldgenMailbox; + private final ProcessorHandle> mainThreadMailbox; +- private final ChunkProgressListener progressListener; ++ public final ChunkProgressListener progressListener; + private final ChunkStatusUpdateListener chunkStatusListener; +- private final ChunkMap.DistanceManager distanceManager; ++ public final ChunkMap.DistanceManager distanceManager; + private final AtomicInteger tickingGenerated; + private final StructureTemplateManager structureTemplateManager; + private final String storageName; + private final PlayerMap playerMap; +- private final Int2ObjectMap entityMap; ++ public final Int2ObjectMap entityMap; + private final Long2ByteMap chunkTypeCache; + private final Long2LongMap chunkSaveCooldowns; + private final Queue unloadQueue; + private int serverViewDistance; + +- public ChunkMap(ServerLevel serverlevel, LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess, DataFixer datafixer, StructureTemplateManager structuretemplatemanager, Executor executor, BlockableEventLoop blockableeventloop, LightChunkGetter lightchunkgetter, ChunkGenerator chunkgenerator, ChunkProgressListener chunkprogresslistener, ChunkStatusUpdateListener chunkstatusupdatelistener, Supplier supplier, int i, boolean flag) { +- super(levelstoragesource_levelstorageaccess.getDimensionPath(serverlevel.dimension()).resolve("region"), datafixer, flag); ++ // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() ++ public final CallbackExecutor callbackExecutor = new CallbackExecutor(); ++ public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable { ++ ++ private final java.util.Queue queue = new java.util.ArrayDeque<>(); ++ ++ @Override ++ public void execute(Runnable runnable) { ++ queue.add(runnable); ++ } ++ ++ @Override ++ public void run() { ++ Runnable task; ++ while ((task = queue.poll()) != null) { ++ task.run(); ++ } ++ } ++ }; ++ // CraftBukkit end ++ ++ public ChunkMap(ServerLevel level, LevelStorageSource.LevelStorageAccess levelStorageAccess, DataFixer fixerUpper, StructureTemplateManager structureManager, Executor dispatcher, BlockableEventLoop mainThreadExecutor, LightChunkGetter lightChunk, ChunkGenerator generator, ChunkProgressListener progressListener, ChunkStatusUpdateListener chunkStatusListener, Supplier overworldDataStorage, int viewDistance, boolean sync) { ++ super(levelStorageAccess.getDimensionPath(level.dimension()).resolve("region"), fixerUpper, sync); + this.visibleChunkMap = this.updatingChunkMap.clone(); + this.pendingUnloads = new Long2ObjectLinkedOpenHashMap(); + this.entitiesInLevel = new LongOpenHashSet(); +@@ -155,42 +179,47 @@ + this.chunkTypeCache = new Long2ByteOpenHashMap(); + this.chunkSaveCooldowns = new Long2LongOpenHashMap(); + this.unloadQueue = Queues.newConcurrentLinkedQueue(); +- this.structureTemplateManager = structuretemplatemanager; +- Path path = levelstoragesource_levelstorageaccess.getDimensionPath(serverlevel.dimension()); ++ this.structureTemplateManager = structureManager; ++ Path path = levelStorageAccess.getDimensionPath(level.dimension()); + + this.storageName = path.getFileName().toString(); +- this.level = serverlevel; +- this.generator = chunkgenerator; +- RegistryAccess registryaccess = serverlevel.registryAccess(); +- long j = serverlevel.getSeed(); ++ this.level = level; ++ this.generator = generator; ++ // CraftBukkit start - SPIGOT-7051: It's a rigged game! Use delegate for random state creation, otherwise it is not so random. ++ if (generator instanceof CustomChunkGenerator) { ++ generator = ((CustomChunkGenerator) generator).getDelegate(); ++ } ++ // CraftBukkit end ++ RegistryAccess iregistrycustom = level.registryAccess(); ++ long j = level.getSeed(); + +- if (chunkgenerator instanceof NoiseBasedChunkGenerator) { +- NoiseBasedChunkGenerator noisebasedchunkgenerator = (NoiseBasedChunkGenerator) chunkgenerator; ++ if (generator instanceof NoiseBasedChunkGenerator) { ++ NoiseBasedChunkGenerator chunkgeneratorabstract = (NoiseBasedChunkGenerator) generator; + +- this.randomState = RandomState.create((NoiseGeneratorSettings) noisebasedchunkgenerator.generatorSettings().value(), (HolderGetter) registryaccess.lookupOrThrow(Registries.NOISE), j); ++ this.randomState = RandomState.create((NoiseGeneratorSettings) chunkgeneratorabstract.generatorSettings().value(), (HolderGetter) iregistrycustom.lookupOrThrow(Registries.NOISE), j); + } else { +- this.randomState = RandomState.create(NoiseGeneratorSettings.dummy(), (HolderGetter) registryaccess.lookupOrThrow(Registries.NOISE), j); ++ this.randomState = RandomState.create(NoiseGeneratorSettings.dummy(), (HolderGetter) iregistrycustom.lookupOrThrow(Registries.NOISE), j); + } + +- this.chunkGeneratorState = chunkgenerator.createState(registryaccess.lookupOrThrow(Registries.STRUCTURE_SET), this.randomState, j); +- this.mainThreadExecutor = blockableeventloop; +- ProcessorMailbox processormailbox = ProcessorMailbox.create(executor, "worldgen"); ++ this.chunkGeneratorState = generator.createState(iregistrycustom.lookupOrThrow(Registries.STRUCTURE_SET), this.randomState, j); ++ this.mainThreadExecutor = mainThreadExecutor; ++ ProcessorMailbox threadedmailbox = ProcessorMailbox.create(dispatcher, "worldgen"); + +- Objects.requireNonNull(blockableeventloop); +- ProcessorHandle processorhandle = ProcessorHandle.of("main", blockableeventloop::tell); ++ Objects.requireNonNull(mainThreadExecutor); ++ ProcessorHandle mailbox = ProcessorHandle.of("main", mainThreadExecutor::tell); + +- this.progressListener = chunkprogresslistener; +- this.chunkStatusListener = chunkstatusupdatelistener; +- ProcessorMailbox processormailbox1 = ProcessorMailbox.create(executor, "light"); ++ this.progressListener = progressListener; ++ this.chunkStatusListener = chunkStatusListener; ++ ProcessorMailbox threadedmailbox1 = ProcessorMailbox.create(dispatcher, "light"); + +- this.queueSorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(processormailbox, processorhandle, processormailbox1), executor, Integer.MAX_VALUE); +- this.worldgenMailbox = this.queueSorter.getProcessor(processormailbox, false); +- this.mainThreadMailbox = this.queueSorter.getProcessor(processorhandle, false); +- this.lightEngine = new ThreadedLevelLightEngine(lightchunkgetter, this, this.level.dimensionType().hasSkyLight(), processormailbox1, this.queueSorter.getProcessor(processormailbox1, false)); +- this.distanceManager = new ChunkMap.DistanceManager(executor, blockableeventloop); +- this.overworldDataStorage = supplier; +- this.poiManager = new PoiManager(path.resolve("poi"), datafixer, flag, registryaccess, serverlevel); +- this.setServerViewDistance(i); ++ this.queueSorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), dispatcher, Integer.MAX_VALUE); ++ this.worldgenMailbox = this.queueSorter.getProcessor(threadedmailbox, false); ++ this.mainThreadMailbox = this.queueSorter.getProcessor(mailbox, false); ++ this.lightEngine = new ThreadedLevelLightEngine(lightChunk, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false)); ++ this.distanceManager = new ChunkMap.DistanceManager(dispatcher, mainThreadExecutor); ++ this.overworldDataStorage = overworldDataStorage; ++ this.poiManager = new PoiManager(path.resolve("poi"), fixerUpper, sync, iregistrycustom, level); ++ this.setServerViewDistance(viewDistance); + } + + protected ChunkGenerator generator() { +@@ -216,26 +245,26 @@ + }); + } + +- private static double euclideanDistanceSquared(ChunkPos chunkpos, Entity entity) { +- double d0 = (double) SectionPos.sectionToBlockCoord(chunkpos.x, 8); +- double d1 = (double) SectionPos.sectionToBlockCoord(chunkpos.z, 8); ++ private static double euclideanDistanceSquared(ChunkPos chunkPos, Entity entity) { ++ double d0 = (double) SectionPos.sectionToBlockCoord(chunkPos.x, 8); ++ double d1 = (double) SectionPos.sectionToBlockCoord(chunkPos.z, 8); + double d2 = d0 - entity.getX(); + double d3 = d1 - entity.getZ(); + + return d2 * d2 + d3 * d3; + } + +- boolean isChunkTracked(ServerPlayer serverplayer, int i, int j) { +- return serverplayer.getChunkTrackingView().contains(i, j) && !serverplayer.connection.chunkSender.isPending(ChunkPos.asLong(i, j)); ++ boolean isChunkTracked(ServerPlayer entityplayer, int i, int j) { ++ return entityplayer.getChunkTrackingView().contains(i, j) && !entityplayer.connection.chunkSender.isPending(ChunkPos.asLong(i, j)); + } + +- private boolean isChunkOnTrackedBorder(ServerPlayer serverplayer, int i, int j) { +- if (!this.isChunkTracked(serverplayer, i, j)) { ++ private boolean isChunkOnTrackedBorder(ServerPlayer entityplayer, int i, int j) { ++ if (!this.isChunkTracked(entityplayer, i, j)) { + return false; + } else { + for (int k = -1; k <= 1; ++k) { + for (int l = -1; l <= 1; ++l) { +- if ((k != 0 || l != 0) && !this.isChunkTracked(serverplayer, i + k, j + l)) { ++ if ((k != 0 || l != 0) && !this.isChunkTracked(entityplayer, i + k, j + l)) { + return true; + } + } +@@ -250,93 +279,95 @@ + } + + @Nullable +- protected ChunkHolder getUpdatingChunkIfPresent(long i) { +- return (ChunkHolder) this.updatingChunkMap.get(i); ++ protected ChunkHolder getUpdatingChunkIfPresent(long chunkPos) { ++ return (ChunkHolder) this.updatingChunkMap.get(chunkPos); + } + + @Nullable +- protected ChunkHolder getVisibleChunkIfPresent(long i) { +- return (ChunkHolder) this.visibleChunkMap.get(i); ++ protected ChunkHolder getVisibleChunkIfPresent(long chunkPos) { ++ return (ChunkHolder) this.visibleChunkMap.get(chunkPos); + } + +- protected IntSupplier getChunkQueueLevel(long i) { ++ protected IntSupplier getChunkQueueLevel(long chunkPos) { + return () -> { +- ChunkHolder chunkholder = this.getVisibleChunkIfPresent(i); ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(chunkPos); + +- return chunkholder == null ? ChunkTaskPriorityQueue.PRIORITY_LEVEL_COUNT - 1 : Math.min(chunkholder.getQueueLevel(), ChunkTaskPriorityQueue.PRIORITY_LEVEL_COUNT - 1); ++ return playerchunk == null ? ChunkTaskPriorityQueue.PRIORITY_LEVEL_COUNT - 1 : Math.min(playerchunk.getQueueLevel(), ChunkTaskPriorityQueue.PRIORITY_LEVEL_COUNT - 1); + }; + } + +- public String getChunkDebugData(ChunkPos chunkpos) { +- ChunkHolder chunkholder = this.getVisibleChunkIfPresent(chunkpos.toLong()); ++ public String getChunkDebugData(ChunkPos pos) { ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos.toLong()); + +- if (chunkholder == null) { ++ if (playerchunk == null) { + return "null"; + } else { +- String s = chunkholder.getTicketLevel() + "\n"; +- ChunkStatus chunkstatus = chunkholder.getLastAvailableStatus(); +- ChunkAccess chunkaccess = chunkholder.getLastAvailable(); ++ String s = playerchunk.getTicketLevel() + "\n"; ++ ChunkStatus chunkstatus = playerchunk.getLastAvailableStatus(); ++ ChunkAccess ichunkaccess = playerchunk.getLastAvailable(); + + if (chunkstatus != null) { + s = s + "St: \u00a7" + chunkstatus.getIndex() + chunkstatus + "\u00a7r\n"; + } + +- if (chunkaccess != null) { +- s = s + "Ch: \u00a7" + chunkaccess.getStatus().getIndex() + chunkaccess.getStatus() + "\u00a7r\n"; ++ if (ichunkaccess != null) { ++ s = s + "Ch: \u00a7" + ichunkaccess.getStatus().getIndex() + ichunkaccess.getStatus() + "\u00a7r\n"; + } + +- FullChunkStatus fullchunkstatus = chunkholder.getFullStatus(); ++ FullChunkStatus fullchunkstatus = playerchunk.getFullStatus(); + + s = s + String.valueOf('\u00a7') + fullchunkstatus.ordinal() + fullchunkstatus; + return s + "\u00a7r"; + } + } + +- private CompletableFuture, ChunkHolder.ChunkLoadingFailure>> getChunkRangeFuture(ChunkHolder chunkholder, int i, IntFunction intfunction) { +- if (i == 0) { +- ChunkStatus chunkstatus = (ChunkStatus) intfunction.apply(0); ++ private CompletableFuture, ChunkHolder.Failure>> getChunkRangeFuture(ChunkHolder chunkHolder, int range, IntFunction statusGetter) { ++ if (range == 0) { ++ ChunkStatus chunkstatus = (ChunkStatus) statusGetter.apply(0); + +- return chunkholder.getOrScheduleFuture(chunkstatus, this).thenApply((either) -> { ++ return chunkHolder.getOrScheduleFuture(chunkstatus, this).thenApply((either) -> { + return either.mapLeft(List::of); + }); + } else { +- List>> list = new ArrayList(); ++ List>> list = new ArrayList(); + List list1 = new ArrayList(); +- ChunkPos chunkpos = chunkholder.getPos(); +- int j = chunkpos.x; +- int k = chunkpos.z; ++ ChunkPos chunkcoordintpair = chunkHolder.getPos(); ++ int j = chunkcoordintpair.x; ++ int k = chunkcoordintpair.z; + +- for (int l = -i; l <= i; ++l) { +- for (int i1 = -i; i1 <= i; ++i1) { ++ for (int l = -range; l <= range; ++l) { ++ for (int i1 = -range; i1 <= range; ++i1) { + int j1 = Math.max(Math.abs(i1), Math.abs(l)); +- final ChunkPos chunkpos1 = new ChunkPos(j + i1, k + l); +- long k1 = chunkpos1.toLong(); +- ChunkHolder chunkholder1 = this.getUpdatingChunkIfPresent(k1); ++ final ChunkPos chunkcoordintpair1 = new ChunkPos(j + i1, k + l); ++ long k1 = chunkcoordintpair1.toLong(); ++ ChunkHolder playerchunk1 = this.getUpdatingChunkIfPresent(k1); + +- if (chunkholder1 == null) { +- return CompletableFuture.completedFuture(Either.right(new ChunkHolder.ChunkLoadingFailure() { +- @Override ++ if (playerchunk1 == null) { ++ return CompletableFuture.completedFuture(Either.right(new ChunkHolder.Failure() { + public String toString() { +- return "Unloaded " + chunkpos1; ++ return "Unloaded " + chunkcoordintpair1; + } + })); + } + +- ChunkStatus chunkstatus1 = (ChunkStatus) intfunction.apply(j1); +- CompletableFuture> completablefuture = chunkholder1.getOrScheduleFuture(chunkstatus1, this); ++ ChunkStatus chunkstatus1 = (ChunkStatus) statusGetter.apply(j1); ++ CompletableFuture> completablefuture = playerchunk1.getOrScheduleFuture(chunkstatus1, this); + +- list1.add(chunkholder1); ++ list1.add(playerchunk1); + list.add(completablefuture); + } + } + +- CompletableFuture>> completablefuture1 = Util.sequence(list); +- CompletableFuture, ChunkHolder.ChunkLoadingFailure>> completablefuture2 = completablefuture1.thenApply((list2) -> { ++ CompletableFuture>> completablefuture1 = Util.sequence(list); ++ CompletableFuture, ChunkHolder.Failure>> completablefuture2 = completablefuture1.thenApply((list2) -> { + List list3 = Lists.newArrayList(); +- final int l1 = 0; ++ // CraftBukkit start - decompile error ++ int cnt = 0; + +- for (Iterator iterator = list2.iterator(); iterator.hasNext(); ++l1) { +- final Either either = (Either) iterator.next(); ++ for (Iterator iterator = list2.iterator(); iterator.hasNext(); ++cnt) { ++ final int l1 = cnt; ++ // CraftBukkit end ++ final Either either = (Either) iterator.next(); + + if (either == null) { + throw this.debugFuturesAndCreateReportedException(new IllegalStateException("At least one of the chunk futures were null"), "n/a"); +@@ -345,12 +376,11 @@ + Optional optional = either.left(); + + if (optional.isEmpty()) { +- return Either.right(new ChunkHolder.ChunkLoadingFailure() { +- @Override ++ return Either.right(new ChunkHolder.Failure() { + public String toString() { +- ChunkPos chunkpos2 = new ChunkPos(j + l1 % (i * 2 + 1), k + l1 / (i * 2 + 1)); ++ ChunkPos chunkcoordintpair2 = new ChunkPos(j + l1 % (range * 2 + 1), k + l1 / (range * 2 + 1)); + +- return "Unloaded " + chunkpos2 + " " + either.right().get(); ++ return "Unloaded " + chunkcoordintpair2 + " " + either.right().get(); + } + }); + } +@@ -363,24 +393,24 @@ + Iterator iterator = list1.iterator(); + + while (iterator.hasNext()) { +- ChunkHolder chunkholder2 = (ChunkHolder) iterator.next(); ++ ChunkHolder playerchunk2 = (ChunkHolder) iterator.next(); + +- chunkholder2.addSaveDependency("getChunkRangeFuture " + chunkpos + " " + i, completablefuture2); ++ playerchunk2.addSaveDependency("getChunkRangeFuture " + chunkcoordintpair + " " + range, completablefuture2); + } + + return completablefuture2; + } + } + +- public ReportedException debugFuturesAndCreateReportedException(IllegalStateException illegalstateexception, String s) { ++ public ReportedException debugFuturesAndCreateReportedException(IllegalStateException exception, String details) { + StringBuilder stringbuilder = new StringBuilder(); +- Consumer consumer = (chunkholder) -> { +- chunkholder.getAllFutures().forEach((pair) -> { ++ Consumer consumer = (playerchunk) -> { ++ playerchunk.getAllFutures().forEach((pair) -> { + ChunkStatus chunkstatus = (ChunkStatus) pair.getFirst(); +- CompletableFuture> completablefuture = (CompletableFuture) pair.getSecond(); ++ CompletableFuture> completablefuture = (CompletableFuture) pair.getSecond(); + + if (completablefuture != null && completablefuture.isDone() && completablefuture.join() == null) { +- stringbuilder.append(chunkholder.getPos()).append(" - status: ").append(chunkstatus).append(" future: ").append(completablefuture).append(System.lineSeparator()); ++ stringbuilder.append(playerchunk.getPos()).append(" - status: ").append(chunkstatus).append(" future: ").append(completablefuture).append(System.lineSeparator()); + } + + }); +@@ -390,16 +420,16 @@ + this.updatingChunkMap.values().forEach(consumer); + stringbuilder.append("Visible:").append(System.lineSeparator()); + this.visibleChunkMap.values().forEach(consumer); +- CrashReport crashreport = CrashReport.forThrowable(illegalstateexception, "Chunk loading"); +- CrashReportCategory crashreportcategory = crashreport.addCategory("Chunk loading"); ++ CrashReport crashreport = CrashReport.forThrowable(exception, "Chunk loading"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Chunk loading"); + +- crashreportcategory.setDetail("Details", (Object) s); +- crashreportcategory.setDetail("Futures", (Object) stringbuilder); ++ crashreportsystemdetails.setDetail("Details", (Object) details); ++ crashreportsystemdetails.setDetail("Futures", (Object) stringbuilder); + return new ReportedException(crashreport); + } + +- public CompletableFuture> prepareEntityTickingChunk(ChunkHolder chunkholder) { +- return this.getChunkRangeFuture(chunkholder, 2, (i) -> { ++ public CompletableFuture> prepareEntityTickingChunk(ChunkHolder chunk) { ++ return this.getChunkRangeFuture(chunk, 2, (i) -> { + return ChunkStatus.FULL; + }).thenApplyAsync((either) -> { + return either.mapLeft((list) -> { +@@ -409,40 +439,39 @@ + } + + @Nullable +- ChunkHolder updateChunkScheduling(long i, int j, @Nullable ChunkHolder chunkholder, int k) { +- if (!ChunkLevel.isLoaded(k) && !ChunkLevel.isLoaded(j)) { +- return chunkholder; ++ ChunkHolder updateChunkScheduling(long chunkPos, int j, @Nullable ChunkHolder newLevel, int holder) { ++ if (!ChunkLevel.isLoaded(holder) && !ChunkLevel.isLoaded(j)) { ++ return newLevel; + } else { +- if (chunkholder != null) { +- chunkholder.setTicketLevel(j); ++ if (newLevel != null) { ++ newLevel.setTicketLevel(j); + } + +- if (chunkholder != null) { ++ if (newLevel != null) { + if (!ChunkLevel.isLoaded(j)) { +- this.toDrop.add(i); ++ this.toDrop.add(chunkPos); + } else { +- this.toDrop.remove(i); ++ this.toDrop.remove(chunkPos); + } + } + +- if (ChunkLevel.isLoaded(j) && chunkholder == null) { +- chunkholder = (ChunkHolder) this.pendingUnloads.remove(i); +- if (chunkholder != null) { +- chunkholder.setTicketLevel(j); ++ if (ChunkLevel.isLoaded(j) && newLevel == null) { ++ newLevel = (ChunkHolder) this.pendingUnloads.remove(chunkPos); ++ if (newLevel != null) { ++ newLevel.setTicketLevel(j); + } else { +- chunkholder = new ChunkHolder(new ChunkPos(i), j, this.level, this.lightEngine, this.queueSorter, this); ++ newLevel = new ChunkHolder(new ChunkPos(chunkPos), j, this.level, this.lightEngine, this.queueSorter, this); + } + +- this.updatingChunkMap.put(i, chunkholder); ++ this.updatingChunkMap.put(chunkPos, newLevel); + this.modified = true; + } + +- return chunkholder; ++ return newLevel; + } + } + + @Override +- @Override + public void close() throws IOException { + try { + this.queueSorter.close(); +@@ -453,28 +482,28 @@ + + } + +- protected void saveAllChunks(boolean flag) { +- if (flag) { ++ protected void saveAllChunks(boolean flush) { ++ if (flush) { + List list = this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).toList(); + MutableBoolean mutableboolean = new MutableBoolean(); + + do { + mutableboolean.setFalse(); +- list.stream().map((chunkholder) -> { ++ list.stream().map((playerchunk) -> { + CompletableFuture completablefuture; + + do { +- completablefuture = chunkholder.getChunkToSave(); +- BlockableEventLoop blockableeventloop = this.mainThreadExecutor; ++ completablefuture = playerchunk.getChunkToSave(); ++ BlockableEventLoop iasynctaskhandler = this.mainThreadExecutor; + + Objects.requireNonNull(completablefuture); +- blockableeventloop.managedBlock(completablefuture::isDone); +- } while (completablefuture != chunkholder.getChunkToSave()); ++ iasynctaskhandler.managedBlock(completablefuture::isDone); ++ } while (completablefuture != playerchunk.getChunkToSave()); + + return (ChunkAccess) completablefuture.join(); +- }).filter((chunkaccess) -> { +- return chunkaccess instanceof ImposterProtoChunk || chunkaccess instanceof LevelChunk; +- }).filter(this::save).forEach((chunkaccess) -> { ++ }).filter((ichunkaccess) -> { ++ return ichunkaccess instanceof ImposterProtoChunk || ichunkaccess instanceof LevelChunk; ++ }).filter(this::save).forEach((ichunkaccess) -> { + mutableboolean.setTrue(); + }); + } while (mutableboolean.isTrue()); +@@ -489,35 +518,35 @@ + + } + +- protected void tick(BooleanSupplier booleansupplier) { +- ProfilerFiller profilerfiller = this.level.getProfiler(); ++ protected void tick(BooleanSupplier hasMoreTime) { ++ ProfilerFiller gameprofilerfiller = this.level.getProfiler(); + +- profilerfiller.push("poi"); +- this.poiManager.tick(booleansupplier); +- profilerfiller.popPush("chunk_unload"); ++ gameprofilerfiller.push("poi"); ++ this.poiManager.tick(hasMoreTime); ++ gameprofilerfiller.popPush("chunk_unload"); + if (!this.level.noSave()) { +- this.processUnloads(booleansupplier); ++ this.processUnloads(hasMoreTime); + } + +- profilerfiller.pop(); ++ gameprofilerfiller.pop(); + } + + public boolean hasWork() { + return this.lightEngine.hasLightWork() || !this.pendingUnloads.isEmpty() || !this.updatingChunkMap.isEmpty() || this.poiManager.hasWork() || !this.toDrop.isEmpty() || !this.unloadQueue.isEmpty() || this.queueSorter.hasWork() || this.distanceManager.hasTickets(); + } + +- private void processUnloads(BooleanSupplier booleansupplier) { ++ private void processUnloads(BooleanSupplier hasMoreTime) { + LongIterator longiterator = this.toDrop.iterator(); + +- for (int i = 0; longiterator.hasNext() && (booleansupplier.getAsBoolean() || i < 200 || this.toDrop.size() > 2000); longiterator.remove()) { ++ for (int i = 0; longiterator.hasNext() && (hasMoreTime.getAsBoolean() || i < 200 || this.toDrop.size() > 2000); longiterator.remove()) { + long j = longiterator.nextLong(); +- ChunkHolder chunkholder = (ChunkHolder) this.updatingChunkMap.remove(j); ++ ChunkHolder playerchunk = (ChunkHolder) this.updatingChunkMap.remove(j); + +- if (chunkholder != null) { +- this.pendingUnloads.put(j, chunkholder); ++ if (playerchunk != null) { ++ this.pendingUnloads.put(j, playerchunk); + this.modified = true; + ++i; +- this.scheduleUnload(j, chunkholder); ++ this.scheduleUnload(j, playerchunk); + } + } + +@@ -525,7 +554,7 @@ + + Runnable runnable; + +- while ((booleansupplier.getAsBoolean() || k > 0) && (runnable = (Runnable) this.unloadQueue.poll()) != null) { ++ while ((hasMoreTime.getAsBoolean() || k > 0) && (runnable = (Runnable) this.unloadQueue.poll()) != null) { + --k; + runnable.run(); + } +@@ -533,7 +562,7 @@ + int l = 0; + ObjectIterator objectiterator = this.visibleChunkMap.values().iterator(); + +- while (l < 20 && booleansupplier.getAsBoolean() && objectiterator.hasNext()) { ++ while (l < 20 && hasMoreTime.getAsBoolean() && objectiterator.hasNext()) { + if (this.saveChunkIfNeeded((ChunkHolder) objectiterator.next())) { + ++l; + } +@@ -541,30 +570,30 @@ + + } + +- private void scheduleUnload(long i, ChunkHolder chunkholder) { +- CompletableFuture completablefuture = chunkholder.getChunkToSave(); +- Consumer consumer = (chunkaccess) -> { +- CompletableFuture completablefuture1 = chunkholder.getChunkToSave(); ++ private void scheduleUnload(long chunkPos, ChunkHolder playerchunk) { ++ CompletableFuture completablefuture = playerchunk.getChunkToSave(); ++ Consumer consumer = (ichunkaccess) -> { // CraftBukkit - decompile error ++ CompletableFuture completablefuture1 = playerchunk.getChunkToSave(); + + if (completablefuture1 != completablefuture) { +- this.scheduleUnload(i, chunkholder); ++ this.scheduleUnload(chunkPos, playerchunk); + } else { +- if (this.pendingUnloads.remove(i, chunkholder) && chunkaccess != null) { +- if (chunkaccess instanceof LevelChunk) { +- ((LevelChunk) chunkaccess).setLoaded(false); ++ if (this.pendingUnloads.remove(chunkPos, playerchunk) && ichunkaccess != null) { ++ if (ichunkaccess instanceof LevelChunk) { ++ ((LevelChunk) ichunkaccess).setLoaded(false); + } + +- this.save(chunkaccess); +- if (this.entitiesInLevel.remove(i) && chunkaccess instanceof LevelChunk) { +- LevelChunk levelchunk = (LevelChunk) chunkaccess; ++ this.save(ichunkaccess); ++ if (this.entitiesInLevel.remove(chunkPos) && ichunkaccess instanceof LevelChunk) { ++ LevelChunk chunk = (LevelChunk) ichunkaccess; + +- this.level.unload(levelchunk); ++ this.level.unload(chunk); + } + +- this.lightEngine.updateChunkStatus(chunkaccess.getPos()); ++ this.lightEngine.updateChunkStatus(ichunkaccess.getPos()); + this.lightEngine.tryScheduleUpdate(); +- this.progressListener.onStatusChange(chunkaccess.getPos(), (ChunkStatus) null); +- this.chunkSaveCooldowns.remove(chunkaccess.getPos().toLong()); ++ this.progressListener.onStatusChange(ichunkaccess.getPos(), (ChunkStatus) null); ++ this.chunkSaveCooldowns.remove(ichunkaccess.getPos().toLong()); + } + + } +@@ -574,7 +603,7 @@ + Objects.requireNonNull(this.unloadQueue); + completablefuture.thenAcceptAsync(consumer, queue::add).whenComplete((ovoid, throwable) -> { + if (throwable != null) { +- ChunkMap.LOGGER.error("Failed to save chunk {}", chunkholder.getPos(), throwable); ++ ChunkMap.LOGGER.error("Failed to save chunk {}", playerchunk.getPos(), throwable); + } + + }); +@@ -590,40 +619,40 @@ + } + } + +- public CompletableFuture> schedule(ChunkHolder chunkholder, ChunkStatus chunkstatus) { +- ChunkPos chunkpos = chunkholder.getPos(); ++ public CompletableFuture> schedule(ChunkHolder holder, ChunkStatus status) { ++ ChunkPos chunkcoordintpair = holder.getPos(); + +- if (chunkstatus == ChunkStatus.EMPTY) { +- return this.scheduleChunkLoad(chunkpos); ++ if (status == ChunkStatus.EMPTY) { ++ return this.scheduleChunkLoad(chunkcoordintpair); + } else { +- if (chunkstatus == ChunkStatus.LIGHT) { +- this.distanceManager.addTicket(TicketType.LIGHT, chunkpos, ChunkLevel.byStatus(ChunkStatus.LIGHT), chunkpos); ++ if (status == ChunkStatus.LIGHT) { ++ this.distanceManager.addTicket(TicketType.LIGHT, chunkcoordintpair, ChunkLevel.byStatus(ChunkStatus.LIGHT), chunkcoordintpair); + } + +- if (!chunkstatus.hasLoadDependencies()) { +- Optional optional = ((Either) chunkholder.getOrScheduleFuture(chunkstatus.getParent(), this).getNow(ChunkHolder.UNLOADED_CHUNK)).left(); ++ if (!status.hasLoadDependencies()) { ++ Optional optional = ((Either) holder.getOrScheduleFuture(status.getParent(), this).getNow(ChunkHolder.UNLOADED_CHUNK)).left(); + +- if (optional.isPresent() && ((ChunkAccess) optional.get()).getStatus().isOrAfter(chunkstatus)) { +- CompletableFuture> completablefuture = chunkstatus.load(this.level, this.structureTemplateManager, this.lightEngine, (chunkaccess) -> { +- return this.protoChunkToFullChunk(chunkholder); ++ if (optional.isPresent() && ((ChunkAccess) optional.get()).getStatus().isOrAfter(status)) { ++ CompletableFuture> completablefuture = status.load(this.level, this.structureTemplateManager, this.lightEngine, (ichunkaccess) -> { ++ return this.protoChunkToFullChunk(holder); + }, (ChunkAccess) optional.get()); + +- this.progressListener.onStatusChange(chunkpos, chunkstatus); ++ this.progressListener.onStatusChange(chunkcoordintpair, status); + return completablefuture; + } + } + +- return this.scheduleChunkGeneration(chunkholder, chunkstatus); ++ return this.scheduleChunkGeneration(holder, status); + } + } + +- private CompletableFuture> scheduleChunkLoad(ChunkPos chunkpos) { +- return this.readChunk(chunkpos).thenApply((optional) -> { +- return optional.filter((compoundtag) -> { +- boolean flag = isChunkDataValid(compoundtag); ++ private CompletableFuture> scheduleChunkLoad(ChunkPos chunkPos) { ++ return this.readChunk(chunkPos).thenApply((optional) -> { ++ return optional.filter((nbttagcompound) -> { ++ boolean flag = isChunkDataValid(nbttagcompound); + + if (!flag) { +- ChunkMap.LOGGER.error("Chunk file at {} is missing level data, skipping", chunkpos); ++ ChunkMap.LOGGER.error("Chunk file at {} is missing level data, skipping", chunkPos); + } + + return flag; +@@ -631,193 +660,207 @@ + }).thenApplyAsync((optional) -> { + this.level.getProfiler().incrementCounter("chunkLoad"); + if (optional.isPresent()) { +- ProtoChunk protochunk = ChunkSerializer.read(this.level, this.poiManager, chunkpos, (CompoundTag) optional.get()); ++ ProtoChunk protochunk = ChunkSerializer.read(this.level, this.poiManager, chunkPos, (CompoundTag) optional.get()); + +- this.markPosition(chunkpos, protochunk.getStatus().getChunkType()); +- return Either.left(protochunk); ++ this.markPosition(chunkPos, protochunk.getStatus().getChunkType()); ++ return Either.left(protochunk); // CraftBukkit - decompile error + } else { +- return Either.left(this.createEmptyChunk(chunkpos)); ++ return Either.left(this.createEmptyChunk(chunkPos)); // CraftBukkit - decompile error + } + }, this.mainThreadExecutor).exceptionallyAsync((throwable) -> { +- return this.handleChunkLoadFailure(throwable, chunkpos); ++ return this.handleChunkLoadFailure(throwable, chunkPos); + }, this.mainThreadExecutor); + } + +- private static boolean isChunkDataValid(CompoundTag compoundtag) { +- return compoundtag.contains("Status", 8); ++ private static boolean isChunkDataValid(CompoundTag tag) { ++ return tag.contains("Status", 8); + } + +- private Either handleChunkLoadFailure(Throwable throwable, ChunkPos chunkpos) { +- if (throwable instanceof ReportedException) { +- ReportedException reportedexception = (ReportedException) throwable; ++ private Either handleChunkLoadFailure(Throwable exception, ChunkPos chunkPos) { ++ if (exception instanceof ReportedException) { ++ ReportedException reportedexception = (ReportedException) exception; + Throwable throwable1 = reportedexception.getCause(); + + if (!(throwable1 instanceof IOException)) { +- this.markPositionReplaceable(chunkpos); ++ this.markPositionReplaceable(chunkPos); + throw reportedexception; + } + +- ChunkMap.LOGGER.error("Couldn't load chunk {}", chunkpos, throwable1); +- } else if (throwable instanceof IOException) { +- ChunkMap.LOGGER.error("Couldn't load chunk {}", chunkpos, throwable); ++ ChunkMap.LOGGER.error("Couldn't load chunk {}", chunkPos, throwable1); ++ } else if (exception instanceof IOException) { ++ ChunkMap.LOGGER.error("Couldn't load chunk {}", chunkPos, exception); + } + +- return Either.left(this.createEmptyChunk(chunkpos)); ++ return Either.left(this.createEmptyChunk(chunkPos)); + } + +- private ChunkAccess createEmptyChunk(ChunkPos chunkpos) { +- this.markPositionReplaceable(chunkpos); +- return new ProtoChunk(chunkpos, UpgradeData.EMPTY, this.level, this.level.registryAccess().registryOrThrow(Registries.BIOME), (BlendingData) null); ++ private ChunkAccess createEmptyChunk(ChunkPos chunkPos) { ++ this.markPositionReplaceable(chunkPos); ++ return new ProtoChunk(chunkPos, UpgradeData.EMPTY, this.level, this.level.registryAccess().registryOrThrow(Registries.BIOME), (BlendingData) null); + } + +- private void markPositionReplaceable(ChunkPos chunkpos) { +- this.chunkTypeCache.put(chunkpos.toLong(), (byte) -1); ++ private void markPositionReplaceable(ChunkPos chunkPos) { ++ this.chunkTypeCache.put(chunkPos.toLong(), (byte) -1); + } + +- private byte markPosition(ChunkPos chunkpos, ChunkStatus.ChunkType chunkstatus_chunktype) { +- return this.chunkTypeCache.put(chunkpos.toLong(), (byte) (chunkstatus_chunktype == ChunkStatus.ChunkType.PROTOCHUNK ? -1 : 1)); ++ private byte markPosition(ChunkPos chunkPos, ChunkStatus.Type chunkType) { ++ return this.chunkTypeCache.put(chunkPos.toLong(), (byte) (chunkType == ChunkStatus.Type.PROTOCHUNK ? -1 : 1)); + } + +- private CompletableFuture> scheduleChunkGeneration(ChunkHolder chunkholder, ChunkStatus chunkstatus) { +- ChunkPos chunkpos = chunkholder.getPos(); +- CompletableFuture, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getChunkRangeFuture(chunkholder, chunkstatus.getRange(), (i) -> { +- return this.getDependencyStatus(chunkstatus, i); ++ private CompletableFuture> scheduleChunkGeneration(ChunkHolder chunkHolder, ChunkStatus chunkStatus) { ++ ChunkPos chunkcoordintpair = chunkHolder.getPos(); ++ CompletableFuture, ChunkHolder.Failure>> completablefuture = this.getChunkRangeFuture(chunkHolder, chunkStatus.getRange(), (i) -> { ++ return this.getDependencyStatus(chunkStatus, i); + }); + + this.level.getProfiler().incrementCounter(() -> { +- return "chunkGenerate " + chunkstatus; ++ return "chunkGenerate " + chunkStatus; + }); + Executor executor = (runnable) -> { +- this.worldgenMailbox.tell(ChunkTaskPriorityQueueSorter.message(chunkholder, runnable)); ++ this.worldgenMailbox.tell(ChunkTaskPriorityQueueSorter.message(chunkHolder, runnable)); + }; + + return completablefuture.thenComposeAsync((either) -> { + return (CompletionStage) either.map((list) -> { + try { +- ChunkAccess chunkaccess = (ChunkAccess) list.get(list.size() / 2); ++ ChunkAccess ichunkaccess = (ChunkAccess) list.get(list.size() / 2); + CompletableFuture completablefuture1; + +- if (chunkaccess.getStatus().isOrAfter(chunkstatus)) { +- completablefuture1 = chunkstatus.load(this.level, this.structureTemplateManager, this.lightEngine, (chunkaccess1) -> { +- return this.protoChunkToFullChunk(chunkholder); +- }, chunkaccess); ++ if (ichunkaccess.getStatus().isOrAfter(chunkStatus)) { ++ completablefuture1 = chunkStatus.load(this.level, this.structureTemplateManager, this.lightEngine, (ichunkaccess1) -> { ++ return this.protoChunkToFullChunk(chunkHolder); ++ }, ichunkaccess); + } else { +- completablefuture1 = chunkstatus.generate(executor, this.level, this.generator, this.structureTemplateManager, this.lightEngine, (chunkaccess1) -> { +- return this.protoChunkToFullChunk(chunkholder); ++ completablefuture1 = chunkStatus.generate(executor, this.level, this.generator, this.structureTemplateManager, this.lightEngine, (ichunkaccess1) -> { ++ return this.protoChunkToFullChunk(chunkHolder); + }, list); + } + +- this.progressListener.onStatusChange(chunkpos, chunkstatus); ++ this.progressListener.onStatusChange(chunkcoordintpair, chunkStatus); + return completablefuture1; + } catch (Exception exception) { + exception.getStackTrace(); + CrashReport crashreport = CrashReport.forThrowable(exception, "Exception generating new chunk"); +- CrashReportCategory crashreportcategory = crashreport.addCategory("Chunk to be generated"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Chunk to be generated"); + +- crashreportcategory.setDetail("Location", (Object) String.format(Locale.ROOT, "%d,%d", chunkpos.x, chunkpos.z)); +- crashreportcategory.setDetail("Position hash", (Object) ChunkPos.asLong(chunkpos.x, chunkpos.z)); +- crashreportcategory.setDetail("Generator", (Object) this.generator); ++ crashreportsystemdetails.setDetail("Location", (Object) String.format(Locale.ROOT, "%d,%d", chunkcoordintpair.x, chunkcoordintpair.z)); ++ crashreportsystemdetails.setDetail("Position hash", (Object) ChunkPos.asLong(chunkcoordintpair.x, chunkcoordintpair.z)); ++ crashreportsystemdetails.setDetail("Generator", (Object) this.generator); + this.mainThreadExecutor.execute(() -> { + throw new ReportedException(crashreport); + }); + throw new ReportedException(crashreport); + } +- }, (chunkholder_chunkloadingfailure) -> { +- this.releaseLightTicket(chunkpos); +- return CompletableFuture.completedFuture(Either.right(chunkholder_chunkloadingfailure)); ++ }, (playerchunk_failure) -> { ++ this.releaseLightTicket(chunkcoordintpair); ++ return CompletableFuture.completedFuture(Either.right(playerchunk_failure)); + }); + }, executor); + } + +- protected void releaseLightTicket(ChunkPos chunkpos) { ++ protected void releaseLightTicket(ChunkPos chunkPos) { + this.mainThreadExecutor.tell(Util.name(() -> { +- this.distanceManager.removeTicket(TicketType.LIGHT, chunkpos, ChunkLevel.byStatus(ChunkStatus.LIGHT), chunkpos); ++ this.distanceManager.removeTicket(TicketType.LIGHT, chunkPos, ChunkLevel.byStatus(ChunkStatus.LIGHT), chunkPos); + }, () -> { +- return "release light ticket " + chunkpos; ++ return "release light ticket " + chunkPos; + })); + } + +- private ChunkStatus getDependencyStatus(ChunkStatus chunkstatus, int i) { ++ private ChunkStatus getDependencyStatus(ChunkStatus chunkStatus, int i) { + ChunkStatus chunkstatus1; + + if (i == 0) { +- chunkstatus1 = chunkstatus.getParent(); ++ chunkstatus1 = chunkStatus.getParent(); + } else { +- chunkstatus1 = ChunkStatus.getStatusAroundFullChunk(ChunkStatus.getDistance(chunkstatus) + i); ++ chunkstatus1 = ChunkStatus.getStatusAroundFullChunk(ChunkStatus.getDistance(chunkStatus) + i); + } + + return chunkstatus1; + } + +- private static void postLoadProtoChunk(ServerLevel serverlevel, List list) { +- if (!list.isEmpty()) { +- serverlevel.addWorldGenChunkEntities(EntityType.loadEntitiesRecursive(list, serverlevel)); ++ private static void postLoadProtoChunk(ServerLevel level, List tags) { ++ if (!tags.isEmpty()) { ++ // CraftBukkit start - these are spawned serialized (DefinedStructure) and we don't call an add event below at the moment due to ordering complexities ++ level.addWorldGenChunkEntities(EntityType.loadEntitiesRecursive(tags, level).filter((entity) -> { ++ boolean needsRemoval = false; ++ net.minecraft.server.dedicated.DedicatedServer server = level.getCraftServer().getServer(); ++ if (!server.areNpcsEnabled() && entity instanceof net.minecraft.world.entity.npc.NPC) { ++ entity.discard(); ++ needsRemoval = true; ++ } ++ if (!server.isSpawningAnimals() && (entity instanceof net.minecraft.world.entity.animal.Animal || entity instanceof net.minecraft.world.entity.animal.WaterAnimal)) { ++ entity.discard(); ++ needsRemoval = true; ++ } ++ return !needsRemoval; ++ })); ++ // CraftBukkit end + } + + } + +- private CompletableFuture> protoChunkToFullChunk(ChunkHolder chunkholder) { +- CompletableFuture> completablefuture = chunkholder.getFutureIfPresentUnchecked(ChunkStatus.FULL.getParent()); ++ private CompletableFuture> protoChunkToFullChunk(ChunkHolder holder) { ++ CompletableFuture> completablefuture = holder.getFutureIfPresentUnchecked(ChunkStatus.FULL.getParent()); + + return completablefuture.thenApplyAsync((either) -> { +- ChunkStatus chunkstatus = ChunkLevel.generationStatus(chunkholder.getTicketLevel()); ++ ChunkStatus chunkstatus = ChunkLevel.generationStatus(holder.getTicketLevel()); + +- return !chunkstatus.isOrAfter(ChunkStatus.FULL) ? ChunkHolder.UNLOADED_CHUNK : either.mapLeft((chunkaccess) -> { +- ChunkPos chunkpos = chunkholder.getPos(); +- ProtoChunk protochunk = (ProtoChunk) chunkaccess; +- LevelChunk levelchunk; ++ return !chunkstatus.isOrAfter(ChunkStatus.FULL) ? ChunkHolder.UNLOADED_CHUNK : either.mapLeft((ichunkaccess) -> { ++ ChunkPos chunkcoordintpair = holder.getPos(); ++ ProtoChunk protochunk = (ProtoChunk) ichunkaccess; ++ LevelChunk chunk; + + if (protochunk instanceof ImposterProtoChunk) { +- levelchunk = ((ImposterProtoChunk) protochunk).getWrapped(); ++ chunk = ((ImposterProtoChunk) protochunk).getWrapped(); + } else { +- levelchunk = new LevelChunk(this.level, protochunk, (levelchunk1) -> { ++ chunk = new LevelChunk(this.level, protochunk, (chunk1) -> { + postLoadProtoChunk(this.level, protochunk.getEntities()); + }); +- chunkholder.replaceProtoChunk(new ImposterProtoChunk(levelchunk, false)); ++ holder.replaceProtoChunk(new ImposterProtoChunk(chunk, false)); + } + +- levelchunk.setFullStatus(() -> { +- return ChunkLevel.fullStatus(chunkholder.getTicketLevel()); ++ chunk.setFullStatus(() -> { ++ return ChunkLevel.fullStatus(holder.getTicketLevel()); + }); +- levelchunk.runPostLoad(); +- if (this.entitiesInLevel.add(chunkpos.toLong())) { +- levelchunk.setLoaded(true); +- levelchunk.registerAllBlockEntitiesAfterLevelLoad(); +- levelchunk.registerTickContainerInLevel(this.level); ++ chunk.runPostLoad(); ++ if (this.entitiesInLevel.add(chunkcoordintpair.toLong())) { ++ chunk.setLoaded(true); ++ chunk.registerAllBlockEntitiesAfterLevelLoad(); ++ chunk.registerTickContainerInLevel(this.level); + } + +- return levelchunk; ++ return chunk; + }); + }, (runnable) -> { +- ProcessorHandle processorhandle = this.mainThreadMailbox; +- long i = chunkholder.getPos().toLong(); ++ ProcessorHandle mailbox = this.mainThreadMailbox; ++ long i = holder.getPos().toLong(); + +- Objects.requireNonNull(chunkholder); +- processorhandle.tell(ChunkTaskPriorityQueueSorter.message(runnable, i, chunkholder::getTicketLevel)); ++ Objects.requireNonNull(holder); ++ mailbox.tell(ChunkTaskPriorityQueueSorter.message(runnable, i, holder::getTicketLevel)); + }); + } + +- public CompletableFuture> prepareTickingChunk(ChunkHolder chunkholder) { +- CompletableFuture, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getChunkRangeFuture(chunkholder, 1, (i) -> { ++ public CompletableFuture> prepareTickingChunk(ChunkHolder holder) { ++ CompletableFuture, ChunkHolder.Failure>> completablefuture = this.getChunkRangeFuture(holder, 1, (i) -> { + return ChunkStatus.FULL; + }); +- CompletableFuture> completablefuture1 = completablefuture.thenApplyAsync((either) -> { ++ CompletableFuture> completablefuture1 = completablefuture.thenApplyAsync((either) -> { + return either.mapLeft((list) -> { + return (LevelChunk) list.get(list.size() / 2); + }); + }, (runnable) -> { +- this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(chunkholder, runnable)); ++ this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); + }).thenApplyAsync((either) -> { +- return either.ifLeft((levelchunk) -> { +- levelchunk.postProcessGeneration(); +- this.level.startTickingChunk(levelchunk); +- CompletableFuture completablefuture2 = chunkholder.getChunkSendSyncFuture(); ++ return either.ifLeft((chunk) -> { ++ chunk.postProcessGeneration(); ++ this.level.startTickingChunk(chunk); ++ CompletableFuture completablefuture2 = holder.getChunkSendSyncFuture(); + + if (completablefuture2.isDone()) { +- this.onChunkReadyToSend(levelchunk); ++ this.onChunkReadyToSend(chunk); + } else { + completablefuture2.thenAcceptAsync((object) -> { +- this.onChunkReadyToSend(levelchunk); ++ this.onChunkReadyToSend(chunk); + }, this.mainThreadExecutor); + } + +@@ -831,27 +874,27 @@ + return completablefuture1; + } + +- private void onChunkReadyToSend(LevelChunk levelchunk) { +- ChunkPos chunkpos = levelchunk.getPos(); ++ private void onChunkReadyToSend(LevelChunk chunk) { ++ ChunkPos chunkcoordintpair = chunk.getPos(); + Iterator iterator = this.playerMap.getAllPlayers().iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- if (serverplayer.getChunkTrackingView().contains(chunkpos)) { +- markChunkPendingToSend(serverplayer, levelchunk); ++ if (entityplayer.getChunkTrackingView().contains(chunkcoordintpair)) { ++ markChunkPendingToSend(entityplayer, chunk); + } + } + + } + +- public CompletableFuture> prepareAccessibleChunk(ChunkHolder chunkholder) { +- return this.getChunkRangeFuture(chunkholder, 1, ChunkStatus::getStatusAroundFullChunk).thenApplyAsync((either) -> { ++ public CompletableFuture> prepareAccessibleChunk(ChunkHolder holder) { ++ return this.getChunkRangeFuture(holder, 1, ChunkStatus::getStatusAroundFullChunk).thenApplyAsync((either) -> { + return either.mapLeft((list) -> { + return (LevelChunk) list.get(list.size() / 2); + }); + }, (runnable) -> { +- this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(chunkholder, runnable)); ++ this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); + }); + } + +@@ -859,25 +902,25 @@ + return this.tickingGenerated.get(); + } + +- private boolean saveChunkIfNeeded(ChunkHolder chunkholder) { +- if (!chunkholder.wasAccessibleSinceLastSave()) { ++ private boolean saveChunkIfNeeded(ChunkHolder holder) { ++ if (!holder.wasAccessibleSinceLastSave()) { + return false; + } else { +- ChunkAccess chunkaccess = (ChunkAccess) chunkholder.getChunkToSave().getNow((Object) null); ++ ChunkAccess ichunkaccess = (ChunkAccess) holder.getChunkToSave().getNow(null); // CraftBukkit - decompile error + +- if (!(chunkaccess instanceof ImposterProtoChunk) && !(chunkaccess instanceof LevelChunk)) { ++ if (!(ichunkaccess instanceof ImposterProtoChunk) && !(ichunkaccess instanceof LevelChunk)) { + return false; + } else { +- long i = chunkaccess.getPos().toLong(); ++ long i = ichunkaccess.getPos().toLong(); + long j = this.chunkSaveCooldowns.getOrDefault(i, -1L); + long k = System.currentTimeMillis(); + + if (k < j) { + return false; + } else { +- boolean flag = this.save(chunkaccess); ++ boolean flag = this.save(ichunkaccess); + +- chunkholder.refreshAccessibility(); ++ holder.refreshAccessibility(); + if (flag) { + this.chunkSaveCooldowns.put(i, k + 10000L); + } +@@ -888,63 +931,63 @@ + } + } + +- private boolean save(ChunkAccess chunkaccess) { +- this.poiManager.flush(chunkaccess.getPos()); +- if (!chunkaccess.isUnsaved()) { ++ public boolean save(ChunkAccess chunk) { ++ this.poiManager.flush(chunk.getPos()); ++ if (!chunk.isUnsaved()) { + return false; + } else { +- chunkaccess.setUnsaved(false); +- ChunkPos chunkpos = chunkaccess.getPos(); ++ chunk.setUnsaved(false); ++ ChunkPos chunkcoordintpair = chunk.getPos(); + + try { +- ChunkStatus chunkstatus = chunkaccess.getStatus(); ++ ChunkStatus chunkstatus = chunk.getStatus(); + +- if (chunkstatus.getChunkType() != ChunkStatus.ChunkType.LEVELCHUNK) { +- if (this.isExistingChunkFull(chunkpos)) { ++ if (chunkstatus.getChunkType() != ChunkStatus.Type.LEVELCHUNK) { ++ if (this.isExistingChunkFull(chunkcoordintpair)) { + return false; + } + +- if (chunkstatus == ChunkStatus.EMPTY && chunkaccess.getAllStarts().values().stream().noneMatch(StructureStart::isValid)) { ++ if (chunkstatus == ChunkStatus.EMPTY && chunk.getAllStarts().values().stream().noneMatch(StructureStart::isValid)) { + return false; + } + } + + this.level.getProfiler().incrementCounter("chunkSave"); +- CompoundTag compoundtag = ChunkSerializer.write(this.level, chunkaccess); ++ CompoundTag nbttagcompound = ChunkSerializer.write(this.level, chunk); + +- this.write(chunkpos, compoundtag); +- this.markPosition(chunkpos, chunkstatus.getChunkType()); ++ this.write(chunkcoordintpair, nbttagcompound); ++ this.markPosition(chunkcoordintpair, chunkstatus.getChunkType()); + return true; + } catch (Exception exception) { +- ChunkMap.LOGGER.error("Failed to save chunk {},{}", new Object[]{chunkpos.x, chunkpos.z, exception}); ++ ChunkMap.LOGGER.error("Failed to save chunk {},{}", new Object[]{chunkcoordintpair.x, chunkcoordintpair.z, exception}); + return false; + } + } + } + +- private boolean isExistingChunkFull(ChunkPos chunkpos) { +- byte b0 = this.chunkTypeCache.get(chunkpos.toLong()); ++ private boolean isExistingChunkFull(ChunkPos chunkPos) { ++ byte b0 = this.chunkTypeCache.get(chunkPos.toLong()); + + if (b0 != 0) { + return b0 == 1; + } else { +- CompoundTag compoundtag; ++ CompoundTag nbttagcompound; + + try { +- compoundtag = (CompoundTag) ((Optional) this.readChunk(chunkpos).join()).orElse((Object) null); +- if (compoundtag == null) { +- this.markPositionReplaceable(chunkpos); ++ nbttagcompound = (CompoundTag) ((Optional) this.readChunk(chunkPos).join()).orElse((Object) null); ++ if (nbttagcompound == null) { ++ this.markPositionReplaceable(chunkPos); + return false; + } + } catch (Exception exception) { +- ChunkMap.LOGGER.error("Failed to read chunk {}", chunkpos, exception); +- this.markPositionReplaceable(chunkpos); ++ ChunkMap.LOGGER.error("Failed to read chunk {}", chunkPos, exception); ++ this.markPositionReplaceable(chunkPos); + return false; + } + +- ChunkStatus.ChunkType chunkstatus_chunktype = ChunkSerializer.getChunkTypeFromTag(compoundtag); ++ ChunkStatus.Type chunkstatus_type = ChunkSerializer.getChunkTypeFromTag(nbttagcompound); + +- return this.markPosition(chunkpos, chunkstatus_chunktype) == 1; ++ return this.markPosition(chunkPos, chunkstatus_type) == 1; + } + } + +@@ -957,47 +1000,47 @@ + Iterator iterator = this.playerMap.getAllPlayers().iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- this.updateChunkTracking(serverplayer); ++ this.updateChunkTracking(entityplayer); + } + } + + } + +- int getPlayerViewDistance(ServerPlayer serverplayer) { +- return Mth.clamp(serverplayer.requestedViewDistance(), 2, this.serverViewDistance); ++ int getPlayerViewDistance(ServerPlayer entityplayer) { ++ return Mth.clamp(entityplayer.requestedViewDistance(), 2, this.serverViewDistance); + } + +- private void markChunkPendingToSend(ServerPlayer serverplayer, ChunkPos chunkpos) { +- LevelChunk levelchunk = this.getChunkToSend(chunkpos.toLong()); ++ private void markChunkPendingToSend(ServerPlayer entityplayer, ChunkPos chunkcoordintpair) { ++ LevelChunk chunk = this.getChunkToSend(chunkcoordintpair.toLong()); + +- if (levelchunk != null) { +- markChunkPendingToSend(serverplayer, levelchunk); ++ if (chunk != null) { ++ markChunkPendingToSend(entityplayer, chunk); + } + + } + +- private static void markChunkPendingToSend(ServerPlayer serverplayer, LevelChunk levelchunk) { +- serverplayer.connection.chunkSender.markChunkPendingToSend(levelchunk); ++ private static void markChunkPendingToSend(ServerPlayer entityplayer, LevelChunk chunk) { ++ entityplayer.connection.chunkSender.markChunkPendingToSend(chunk); + } + +- private static void dropChunk(ServerPlayer serverplayer, ChunkPos chunkpos) { +- serverplayer.connection.chunkSender.dropChunk(serverplayer, chunkpos); ++ private static void dropChunk(ServerPlayer entityplayer, ChunkPos chunkcoordintpair) { ++ entityplayer.connection.chunkSender.dropChunk(entityplayer, chunkcoordintpair); + } + + @Nullable + public LevelChunk getChunkToSend(long i) { +- ChunkHolder chunkholder = this.getVisibleChunkIfPresent(i); ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(i); + +- return chunkholder == null ? null : chunkholder.getChunkToSend(); ++ return playerchunk == null ? null : playerchunk.getChunkToSend(); + } + + public int size() { + return this.visibleChunkMap.size(); + } + +- public net.minecraft.server.level.DistanceManager getDistanceManager() { ++ public DistanceManager getDistanceManager() { + return this.distanceManager; + } + +@@ -1006,38 +1049,39 @@ + } + + void dumpChunks(Writer writer) throws IOException { +- CsvOutput csvoutput = CsvOutput.builder().addColumn("x").addColumn("z").addColumn("level").addColumn("in_memory").addColumn("status").addColumn("full_status").addColumn("accessible_ready").addColumn("ticking_ready").addColumn("entity_ticking_ready").addColumn("ticket").addColumn("spawning").addColumn("block_entity_count").addColumn("ticking_ticket").addColumn("ticking_level").addColumn("block_ticks").addColumn("fluid_ticks").build(writer); ++ CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("z").addColumn("level").addColumn("in_memory").addColumn("status").addColumn("full_status").addColumn("accessible_ready").addColumn("ticking_ready").addColumn("entity_ticking_ready").addColumn("ticket").addColumn("spawning").addColumn("block_entity_count").addColumn("ticking_ticket").addColumn("ticking_level").addColumn("block_ticks").addColumn("fluid_ticks").build(writer); + TickingTracker tickingtracker = this.distanceManager.tickingTracker(); + ObjectBidirectionalIterator objectbidirectionaliterator = this.visibleChunkMap.long2ObjectEntrySet().iterator(); + + while (objectbidirectionaliterator.hasNext()) { + Entry entry = (Entry) objectbidirectionaliterator.next(); + long i = entry.getLongKey(); +- ChunkPos chunkpos = new ChunkPos(i); +- ChunkHolder chunkholder = (ChunkHolder) entry.getValue(); +- Optional optional = Optional.ofNullable(chunkholder.getLastAvailable()); +- Optional optional1 = optional.flatMap((chunkaccess) -> { +- return chunkaccess instanceof LevelChunk ? Optional.of((LevelChunk) chunkaccess) : Optional.empty(); ++ ChunkPos chunkcoordintpair = new ChunkPos(i); ++ ChunkHolder playerchunk = (ChunkHolder) entry.getValue(); ++ Optional optional = Optional.ofNullable(playerchunk.getLastAvailable()); ++ Optional optional1 = optional.flatMap((ichunkaccess) -> { ++ return ichunkaccess instanceof LevelChunk ? Optional.of((LevelChunk) ichunkaccess) : Optional.empty(); + }); + +- csvoutput.writeRow(chunkpos.x, chunkpos.z, chunkholder.getTicketLevel(), optional.isPresent(), optional.map(ChunkAccess::getStatus).orElse((Object) null), optional1.map(LevelChunk::getFullStatus).orElse((Object) null), printFuture(chunkholder.getFullChunkFuture()), printFuture(chunkholder.getTickingChunkFuture()), printFuture(chunkholder.getEntityTickingChunkFuture()), this.distanceManager.getTicketDebugString(i), this.anyPlayerCloseEnoughForSpawning(chunkpos), optional1.map((levelchunk) -> { +- return levelchunk.getBlockEntities().size(); +- }).orElse(0), tickingtracker.getTicketDebugString(i), tickingtracker.getLevel(i), optional1.map((levelchunk) -> { +- return levelchunk.getBlockTicks().count(); +- }).orElse(0), optional1.map((levelchunk) -> { +- return levelchunk.getFluidTicks().count(); ++ // CraftBukkit - decompile error ++ csvwriter.writeRow(chunkcoordintpair.x, chunkcoordintpair.z, playerchunk.getTicketLevel(), optional.isPresent(), optional.map(ChunkAccess::getStatus).orElse(null), optional1.map(LevelChunk::getFullStatus).orElse(null), printFuture(playerchunk.getFullChunkFuture()), printFuture(playerchunk.getTickingChunkFuture()), printFuture(playerchunk.getEntityTickingChunkFuture()), this.distanceManager.getTicketDebugString(i), this.anyPlayerCloseEnoughForSpawning(chunkcoordintpair), optional1.map((chunk) -> { ++ return chunk.getBlockEntities().size(); ++ }).orElse(0), tickingtracker.getTicketDebugString(i), tickingtracker.getLevel(i), optional1.map((chunk) -> { ++ return chunk.getBlockTicks().count(); ++ }).orElse(0), optional1.map((chunk) -> { ++ return chunk.getFluidTicks().count(); + }).orElse(0)); + } + + } + +- private static String printFuture(CompletableFuture> completablefuture) { ++ private static String printFuture(CompletableFuture> future) { + try { +- Either either = (Either) completablefuture.getNow((Object) null); ++ Either either = (Either) future.getNow(null); // CraftBukkit - decompile error + +- return either != null ? (String) either.map((levelchunk) -> { ++ return either != null ? (String) either.map((chunk) -> { + return "done"; +- }, (chunkholder_chunkloadingfailure) -> { ++ }, (playerchunk_failure) -> { + return "unloaded"; + }) : "not completed"; + } catch (CompletionException completionexception) { +@@ -1047,38 +1091,40 @@ + } + } + +- private CompletableFuture> readChunk(ChunkPos chunkpos) { +- return this.read(chunkpos).thenApplyAsync((optional) -> { +- return optional.map(this::upgradeChunkTag); ++ private CompletableFuture> readChunk(ChunkPos pos) { ++ return this.read(pos).thenApplyAsync((optional) -> { ++ return optional.map((nbttagcompound) -> upgradeChunkTag(nbttagcompound, pos)); // CraftBukkit + }, Util.backgroundExecutor()); + } + +- private CompoundTag upgradeChunkTag(CompoundTag compoundtag) { +- return this.upgradeChunkTag(this.level.dimension(), this.overworldDataStorage, compoundtag, this.generator.getTypeNameForDataFixer()); ++ // CraftBukkit start ++ private CompoundTag upgradeChunkTag(CompoundTag nbttagcompound, ChunkPos chunkcoordintpair) { ++ return this.upgradeChunkTag(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, this.generator.getTypeNameForDataFixer(), chunkcoordintpair, level); ++ // CraftBukkit end + } + +- boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkpos) { +- if (!this.distanceManager.hasPlayersNearby(chunkpos.toLong())) { ++ boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkPos) { ++ if (!this.distanceManager.hasPlayersNearby(chunkPos.toLong())) { + return false; + } else { + Iterator iterator = this.playerMap.getAllPlayers().iterator(); + +- ServerPlayer serverplayer; ++ ServerPlayer entityplayer; + + do { + if (!iterator.hasNext()) { + return false; + } + +- serverplayer = (ServerPlayer) iterator.next(); +- } while (!this.playerIsCloseEnoughForSpawning(serverplayer, chunkpos)); ++ entityplayer = (ServerPlayer) iterator.next(); ++ } while (!this.playerIsCloseEnoughForSpawning(entityplayer, chunkPos)); + + return true; + } + } + +- public List getPlayersCloseForSpawning(ChunkPos chunkpos) { +- long i = chunkpos.toLong(); ++ public List getPlayersCloseForSpawning(ChunkPos chunkPos) { ++ long i = chunkPos.toLong(); + + if (!this.distanceManager.hasPlayersNearby(i)) { + return List.of(); +@@ -1087,10 +1133,10 @@ + Iterator iterator = this.playerMap.getAllPlayers().iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- if (this.playerIsCloseEnoughForSpawning(serverplayer, chunkpos)) { +- builder.add(serverplayer); ++ if (this.playerIsCloseEnoughForSpawning(entityplayer, chunkPos)) { ++ builder.add(entityplayer); + } + } + +@@ -1098,152 +1144,151 @@ + } + } + +- private boolean playerIsCloseEnoughForSpawning(ServerPlayer serverplayer, ChunkPos chunkpos) { +- if (serverplayer.isSpectator()) { ++ private boolean playerIsCloseEnoughForSpawning(ServerPlayer player, ChunkPos chunkPos) { ++ if (player.isSpectator()) { + return false; + } else { +- double d0 = euclideanDistanceSquared(chunkpos, serverplayer); ++ double d0 = euclideanDistanceSquared(chunkPos, player); + + return d0 < 16384.0D; + } + } + +- private boolean skipPlayer(ServerPlayer serverplayer) { +- return serverplayer.isSpectator() && !this.level.getGameRules().getBoolean(GameRules.RULE_SPECTATORSGENERATECHUNKS); ++ private boolean skipPlayer(ServerPlayer player) { ++ return player.isSpectator() && !this.level.getGameRules().getBoolean(GameRules.RULE_SPECTATORSGENERATECHUNKS); + } + +- void updatePlayerStatus(ServerPlayer serverplayer, boolean flag) { +- boolean flag1 = this.skipPlayer(serverplayer); +- boolean flag2 = this.playerMap.ignoredOrUnknown(serverplayer); ++ void updatePlayerStatus(ServerPlayer player, boolean track) { ++ boolean flag1 = this.skipPlayer(player); ++ boolean flag2 = this.playerMap.ignoredOrUnknown(player); + +- if (flag) { +- this.playerMap.addPlayer(serverplayer, flag1); +- this.updatePlayerPos(serverplayer); ++ if (track) { ++ this.playerMap.addPlayer(player, flag1); ++ this.updatePlayerPos(player); + if (!flag1) { +- this.distanceManager.addPlayer(SectionPos.of((EntityAccess) serverplayer), serverplayer); ++ this.distanceManager.addPlayer(SectionPos.of((EntityAccess) player), player); + } + +- serverplayer.setChunkTrackingView(ChunkTrackingView.EMPTY); +- this.updateChunkTracking(serverplayer); ++ player.setChunkTrackingView(ChunkTrackingView.EMPTY); ++ this.updateChunkTracking(player); + } else { +- SectionPos sectionpos = serverplayer.getLastSectionPos(); ++ SectionPos sectionposition = player.getLastSectionPos(); + +- this.playerMap.removePlayer(serverplayer); ++ this.playerMap.removePlayer(player); + if (!flag2) { +- this.distanceManager.removePlayer(sectionpos, serverplayer); ++ this.distanceManager.removePlayer(sectionposition, player); + } + +- this.applyChunkTrackingView(serverplayer, ChunkTrackingView.EMPTY); ++ this.applyChunkTrackingView(player, ChunkTrackingView.EMPTY); + } + + } + +- private void updatePlayerPos(ServerPlayer serverplayer) { +- SectionPos sectionpos = SectionPos.of((EntityAccess) serverplayer); ++ private void updatePlayerPos(ServerPlayer entityplayer) { ++ SectionPos sectionposition = SectionPos.of((EntityAccess) entityplayer); + +- serverplayer.setLastSectionPos(sectionpos); ++ entityplayer.setLastSectionPos(sectionposition); + } + +- public void move(ServerPlayer serverplayer) { ++ public void move(ServerPlayer player) { + ObjectIterator objectiterator = this.entityMap.values().iterator(); + + while (objectiterator.hasNext()) { +- ChunkMap.TrackedEntity chunkmap_trackedentity = (ChunkMap.TrackedEntity) objectiterator.next(); ++ ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); + +- if (chunkmap_trackedentity.entity == serverplayer) { +- chunkmap_trackedentity.updatePlayers(this.level.players()); ++ if (playerchunkmap_entitytracker.entity == player) { ++ playerchunkmap_entitytracker.updatePlayers(this.level.players()); + } else { +- chunkmap_trackedentity.updatePlayer(serverplayer); ++ playerchunkmap_entitytracker.updatePlayer(player); + } + } + +- SectionPos sectionpos = serverplayer.getLastSectionPos(); +- SectionPos sectionpos1 = SectionPos.of((EntityAccess) serverplayer); +- boolean flag = this.playerMap.ignored(serverplayer); +- boolean flag1 = this.skipPlayer(serverplayer); +- boolean flag2 = sectionpos.asLong() != sectionpos1.asLong(); ++ SectionPos sectionposition = player.getLastSectionPos(); ++ SectionPos sectionposition1 = SectionPos.of((EntityAccess) player); ++ boolean flag = this.playerMap.ignored(player); ++ boolean flag1 = this.skipPlayer(player); ++ boolean flag2 = sectionposition.asLong() != sectionposition1.asLong(); + + if (flag2 || flag != flag1) { +- this.updatePlayerPos(serverplayer); ++ this.updatePlayerPos(player); + if (!flag) { +- this.distanceManager.removePlayer(sectionpos, serverplayer); ++ this.distanceManager.removePlayer(sectionposition, player); + } + + if (!flag1) { +- this.distanceManager.addPlayer(sectionpos1, serverplayer); ++ this.distanceManager.addPlayer(sectionposition1, player); + } + + if (!flag && flag1) { +- this.playerMap.ignorePlayer(serverplayer); ++ this.playerMap.ignorePlayer(player); + } + + if (flag && !flag1) { +- this.playerMap.unIgnorePlayer(serverplayer); ++ this.playerMap.unIgnorePlayer(player); + } + +- this.updateChunkTracking(serverplayer); ++ this.updateChunkTracking(player); + } + + } + +- private void updateChunkTracking(ServerPlayer serverplayer) { +- ChunkPos chunkpos = serverplayer.chunkPosition(); +- int i = this.getPlayerViewDistance(serverplayer); +- ChunkTrackingView chunktrackingview = serverplayer.getChunkTrackingView(); ++ private void updateChunkTracking(ServerPlayer entityplayer) { ++ ChunkPos chunkcoordintpair = entityplayer.chunkPosition(); ++ int i = this.getPlayerViewDistance(entityplayer); ++ ChunkTrackingView chunktrackingview = entityplayer.getChunkTrackingView(); + +- if (chunktrackingview instanceof ChunkTrackingView.Positioned) { +- ChunkTrackingView.Positioned chunktrackingview_positioned = (ChunkTrackingView.Positioned) chunktrackingview; ++ if (chunktrackingview instanceof ChunkTrackingView.a) { ++ ChunkTrackingView.a chunktrackingview_a = (ChunkTrackingView.a) chunktrackingview; + +- if (chunktrackingview_positioned.center().equals(chunkpos) && chunktrackingview_positioned.viewDistance() == i) { ++ if (chunktrackingview_a.center().equals(chunkcoordintpair) && chunktrackingview_a.viewDistance() == i) { + return; + } + } + +- this.applyChunkTrackingView(serverplayer, ChunkTrackingView.of(chunkpos, i)); ++ this.applyChunkTrackingView(entityplayer, ChunkTrackingView.of(chunkcoordintpair, i)); + } + +- private void applyChunkTrackingView(ServerPlayer serverplayer, ChunkTrackingView chunktrackingview) { +- if (serverplayer.level() == this.level) { +- ChunkTrackingView chunktrackingview1 = serverplayer.getChunkTrackingView(); ++ private void applyChunkTrackingView(ServerPlayer entityplayer, ChunkTrackingView chunktrackingview) { ++ if (entityplayer.level() == this.level) { ++ ChunkTrackingView chunktrackingview1 = entityplayer.getChunkTrackingView(); + +- if (chunktrackingview instanceof ChunkTrackingView.Positioned) { ++ if (chunktrackingview instanceof ChunkTrackingView.a) { + label15: + { +- ChunkTrackingView.Positioned chunktrackingview_positioned = (ChunkTrackingView.Positioned) chunktrackingview; ++ ChunkTrackingView.a chunktrackingview_a = (ChunkTrackingView.a) chunktrackingview; + +- if (chunktrackingview1 instanceof ChunkTrackingView.Positioned) { +- ChunkTrackingView.Positioned chunktrackingview_positioned1 = (ChunkTrackingView.Positioned) chunktrackingview1; ++ if (chunktrackingview1 instanceof ChunkTrackingView.a) { ++ ChunkTrackingView.a chunktrackingview_a1 = (ChunkTrackingView.a) chunktrackingview1; + +- if (chunktrackingview_positioned1.center().equals(chunktrackingview_positioned.center())) { ++ if (chunktrackingview_a1.center().equals(chunktrackingview_a.center())) { + break label15; + } + } + +- serverplayer.connection.send(new ClientboundSetChunkCacheCenterPacket(chunktrackingview_positioned.center().x, chunktrackingview_positioned.center().z)); ++ entityplayer.connection.send(new ClientboundSetChunkCacheCenterPacket(chunktrackingview_a.center().x, chunktrackingview_a.center().z)); + } + } + +- ChunkTrackingView.difference(chunktrackingview1, chunktrackingview, (chunkpos) -> { +- this.markChunkPendingToSend(serverplayer, chunkpos); +- }, (chunkpos) -> { +- dropChunk(serverplayer, chunkpos); ++ ChunkTrackingView.difference(chunktrackingview1, chunktrackingview, (chunkcoordintpair) -> { ++ this.markChunkPendingToSend(entityplayer, chunkcoordintpair); ++ }, (chunkcoordintpair) -> { ++ dropChunk(entityplayer, chunkcoordintpair); + }); +- serverplayer.setChunkTrackingView(chunktrackingview); ++ entityplayer.setChunkTrackingView(chunktrackingview); + } + } + + @Override +- @Override +- public List getPlayers(ChunkPos chunkpos, boolean flag) { ++ public List getPlayers(ChunkPos pos, boolean boundaryOnly) { + Set set = this.playerMap.getAllPlayers(); + Builder builder = ImmutableList.builder(); + Iterator iterator = set.iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- if (flag && this.isChunkOnTrackedBorder(serverplayer, chunkpos.x, chunkpos.z) || !flag && this.isChunkTracked(serverplayer, chunkpos.x, chunkpos.z)) { +- builder.add(serverplayer); ++ if (boundaryOnly && this.isChunkOnTrackedBorder(entityplayer, pos.x, pos.z) || !boundaryOnly && this.isChunkTracked(entityplayer, pos.x, pos.z)) { ++ builder.add(entityplayer); + } + } + +@@ -1252,30 +1297,30 @@ + + protected void addEntity(Entity entity) { + if (!(entity instanceof EnderDragonPart)) { +- EntityType entitytype = entity.getType(); +- int i = entitytype.clientTrackingRange() * 16; ++ EntityType entitytypes = entity.getType(); ++ int i = entitytypes.clientTrackingRange() * 16; + + if (i != 0) { +- int j = entitytype.updateInterval(); ++ int j = entitytypes.updateInterval(); + + if (this.entityMap.containsKey(entity.getId())) { + throw (IllegalStateException) Util.pauseInIde(new IllegalStateException("Entity is already tracked!")); + } else { +- ChunkMap.TrackedEntity chunkmap_trackedentity = new ChunkMap.TrackedEntity(entity, i, j, entitytype.trackDeltas()); ++ ChunkMap.TrackedEntity playerchunkmap_entitytracker = new ChunkMap.TrackedEntity(entity, i, j, entitytypes.trackDeltas()); + +- this.entityMap.put(entity.getId(), chunkmap_trackedentity); +- chunkmap_trackedentity.updatePlayers(this.level.players()); ++ this.entityMap.put(entity.getId(), playerchunkmap_entitytracker); ++ playerchunkmap_entitytracker.updatePlayers(this.level.players()); + if (entity instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) entity; ++ ServerPlayer entityplayer = (ServerPlayer) entity; + +- this.updatePlayerStatus(serverplayer, true); ++ this.updatePlayerStatus(entityplayer, true); + ObjectIterator objectiterator = this.entityMap.values().iterator(); + + while (objectiterator.hasNext()) { +- ChunkMap.TrackedEntity chunkmap_trackedentity1 = (ChunkMap.TrackedEntity) objectiterator.next(); ++ ChunkMap.TrackedEntity playerchunkmap_entitytracker1 = (ChunkMap.TrackedEntity) objectiterator.next(); + +- if (chunkmap_trackedentity1.entity != serverplayer) { +- chunkmap_trackedentity1.updatePlayer(serverplayer); ++ if (playerchunkmap_entitytracker1.entity != entityplayer) { ++ playerchunkmap_entitytracker1.updatePlayer(entityplayer); + } + } + } +@@ -1287,22 +1332,22 @@ + + protected void removeEntity(Entity entity) { + if (entity instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) entity; ++ ServerPlayer entityplayer = (ServerPlayer) entity; + +- this.updatePlayerStatus(serverplayer, false); ++ this.updatePlayerStatus(entityplayer, false); + ObjectIterator objectiterator = this.entityMap.values().iterator(); + + while (objectiterator.hasNext()) { +- ChunkMap.TrackedEntity chunkmap_trackedentity = (ChunkMap.TrackedEntity) objectiterator.next(); ++ ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); + +- chunkmap_trackedentity.removePlayer(serverplayer); ++ playerchunkmap_entitytracker.removePlayer(entityplayer); + } + } + +- ChunkMap.TrackedEntity chunkmap_trackedentity1 = (ChunkMap.TrackedEntity) this.entityMap.remove(entity.getId()); ++ ChunkMap.TrackedEntity playerchunkmap_entitytracker1 = (ChunkMap.TrackedEntity) this.entityMap.remove(entity.getId()); + +- if (chunkmap_trackedentity1 != null) { +- chunkmap_trackedentity1.broadcastRemoved(); ++ if (playerchunkmap_entitytracker1 != null) { ++ playerchunkmap_entitytracker1.broadcastRemoved(); + } + + } +@@ -1311,36 +1356,36 @@ + Iterator iterator = this.playerMap.getAllPlayers().iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- this.updateChunkTracking(serverplayer); ++ this.updateChunkTracking(entityplayer); + } + + List list = Lists.newArrayList(); + List list1 = this.level.players(); + ObjectIterator objectiterator = this.entityMap.values().iterator(); + +- ChunkMap.TrackedEntity chunkmap_trackedentity; ++ ChunkMap.TrackedEntity playerchunkmap_entitytracker; + + while (objectiterator.hasNext()) { +- chunkmap_trackedentity = (ChunkMap.TrackedEntity) objectiterator.next(); +- SectionPos sectionpos = chunkmap_trackedentity.lastSectionPos; +- SectionPos sectionpos1 = SectionPos.of((EntityAccess) chunkmap_trackedentity.entity); +- boolean flag = !Objects.equals(sectionpos, sectionpos1); ++ playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); ++ SectionPos sectionposition = playerchunkmap_entitytracker.lastSectionPos; ++ SectionPos sectionposition1 = SectionPos.of((EntityAccess) playerchunkmap_entitytracker.entity); ++ boolean flag = !Objects.equals(sectionposition, sectionposition1); + + if (flag) { +- chunkmap_trackedentity.updatePlayers(list1); +- Entity entity = chunkmap_trackedentity.entity; ++ playerchunkmap_entitytracker.updatePlayers(list1); ++ Entity entity = playerchunkmap_entitytracker.entity; + + if (entity instanceof ServerPlayer) { + list.add((ServerPlayer) entity); + } + +- chunkmap_trackedentity.lastSectionPos = sectionpos1; ++ playerchunkmap_entitytracker.lastSectionPos = sectionposition1; + } + +- if (flag || this.distanceManager.inEntityTickingRange(sectionpos1.chunk().toLong())) { +- chunkmap_trackedentity.serverEntity.sendChanges(); ++ if (flag || this.distanceManager.inEntityTickingRange(sectionposition1.chunk().toLong())) { ++ playerchunkmap_entitytracker.serverEntity.sendChanges(); + } + } + +@@ -1348,61 +1393,61 @@ + objectiterator = this.entityMap.values().iterator(); + + while (objectiterator.hasNext()) { +- chunkmap_trackedentity = (ChunkMap.TrackedEntity) objectiterator.next(); +- chunkmap_trackedentity.updatePlayers(list); ++ playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); ++ playerchunkmap_entitytracker.updatePlayers(list); + } + } + + } + + public void broadcast(Entity entity, Packet packet) { +- ChunkMap.TrackedEntity chunkmap_trackedentity = (ChunkMap.TrackedEntity) this.entityMap.get(entity.getId()); ++ ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) this.entityMap.get(entity.getId()); + +- if (chunkmap_trackedentity != null) { +- chunkmap_trackedentity.broadcast(packet); ++ if (playerchunkmap_entitytracker != null) { ++ playerchunkmap_entitytracker.broadcast(packet); + } + + } + + protected void broadcastAndSend(Entity entity, Packet packet) { +- ChunkMap.TrackedEntity chunkmap_trackedentity = (ChunkMap.TrackedEntity) this.entityMap.get(entity.getId()); ++ ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) this.entityMap.get(entity.getId()); + +- if (chunkmap_trackedentity != null) { +- chunkmap_trackedentity.broadcastAndSend(packet); ++ if (playerchunkmap_entitytracker != null) { ++ playerchunkmap_entitytracker.broadcastAndSend(packet); + } + + } + +- public void resendBiomesForChunks(List list) { ++ public void resendBiomesForChunks(List chunks) { + Map> map = new HashMap(); +- Iterator iterator = list.iterator(); ++ Iterator iterator = chunks.iterator(); + + while (iterator.hasNext()) { +- ChunkAccess chunkaccess = (ChunkAccess) iterator.next(); +- ChunkPos chunkpos = chunkaccess.getPos(); +- LevelChunk levelchunk; ++ ChunkAccess ichunkaccess = (ChunkAccess) iterator.next(); ++ ChunkPos chunkcoordintpair = ichunkaccess.getPos(); ++ LevelChunk chunk; + +- if (chunkaccess instanceof LevelChunk) { +- LevelChunk levelchunk1 = (LevelChunk) chunkaccess; ++ if (ichunkaccess instanceof LevelChunk) { ++ LevelChunk chunk1 = (LevelChunk) ichunkaccess; + +- levelchunk = levelchunk1; ++ chunk = chunk1; + } else { +- levelchunk = this.level.getChunk(chunkpos.x, chunkpos.z); ++ chunk = this.level.getChunk(chunkcoordintpair.x, chunkcoordintpair.z); + } + +- Iterator iterator1 = this.getPlayers(chunkpos, false).iterator(); ++ Iterator iterator1 = this.getPlayers(chunkcoordintpair, false).iterator(); + + while (iterator1.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator1.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator1.next(); + +- ((List) map.computeIfAbsent(serverplayer, (serverplayer1) -> { ++ ((List) map.computeIfAbsent(entityplayer, (entityplayer1) -> { + return new ArrayList(); +- })).add(levelchunk); ++ })).add(chunk); + } + } + +- map.forEach((serverplayer1, list1) -> { +- serverplayer1.connection.send(ClientboundChunksBiomesPacket.forChunks(list1)); ++ map.forEach((entityplayer1, list1) -> { ++ entityplayer1.connection.send(ClientboundChunksBiomesPacket.forChunks(list1)); + }); + } + +@@ -1414,71 +1459,66 @@ + return this.storageName; + } + +- void onFullChunkStatusChange(ChunkPos chunkpos, FullChunkStatus fullchunkstatus) { +- this.chunkStatusListener.onChunkStatusChange(chunkpos, fullchunkstatus); ++ void onFullChunkStatusChange(ChunkPos chunkPos, FullChunkStatus fullChunkStatus) { ++ this.chunkStatusListener.onChunkStatusChange(chunkPos, fullChunkStatus); + } + +- public void waitForLightBeforeSending(ChunkPos chunkpos, int i) { ++ public void waitForLightBeforeSending(ChunkPos chunkcoordintpair, int i) { + int j = i + 1; + +- ChunkPos.rangeClosed(chunkpos, j).forEach((chunkpos1) -> { +- ChunkHolder chunkholder = this.getVisibleChunkIfPresent(chunkpos1.toLong()); ++ ChunkPos.rangeClosed(chunkcoordintpair, j).forEach((chunkcoordintpair1) -> { ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(chunkcoordintpair1.toLong()); + +- if (chunkholder != null) { +- chunkholder.addSendDependency(this.lightEngine.waitForPendingTasks(chunkpos1.x, chunkpos1.z)); ++ if (playerchunk != null) { ++ playerchunk.addSendDependency(this.lightEngine.waitForPendingTasks(chunkcoordintpair1.x, chunkcoordintpair1.z)); + } + + }); + } + +- private class DistanceManager extends net.minecraft.server.level.DistanceManager { ++ private class DistanceManager extends DistanceManager { + +- protected DistanceManager(Executor executor, Executor executor1) { +- super(executor, executor1); ++ protected DistanceManager(Executor dispatcher, Executor mainThreadExecutor) { ++ super(dispatcher, mainThreadExecutor); + } + + @Override +- @Override +- protected boolean isChunkToRemove(long i) { +- return ChunkMap.this.toDrop.contains(i); ++ protected boolean isChunkToRemove(long chunkPos) { ++ return ChunkMap.this.toDrop.contains(chunkPos); + } + + @Nullable + @Override +- @Override +- protected ChunkHolder getChunk(long i) { +- return ChunkMap.this.getUpdatingChunkIfPresent(i); ++ protected ChunkHolder getChunk(long chunkPos) { ++ return ChunkMap.this.getUpdatingChunkIfPresent(chunkPos); + } + + @Nullable + @Override +- @Override +- protected ChunkHolder updateChunkScheduling(long i, int j, @Nullable ChunkHolder chunkholder, int k) { +- return ChunkMap.this.updateChunkScheduling(i, j, chunkholder, k); ++ protected ChunkHolder updateChunkScheduling(long chunkPos, int j, @Nullable ChunkHolder newLevel, int holder) { ++ return ChunkMap.this.updateChunkScheduling(chunkPos, j, newLevel, holder); + } + } + +- private class TrackedEntity { ++ public class TrackedEntity { + + final ServerEntity serverEntity; + final Entity entity; + private final int range; + SectionPos lastSectionPos; +- private final Set seenBy = Sets.newIdentityHashSet(); ++ public final Set seenBy = Sets.newIdentityHashSet(); + + public TrackedEntity(Entity entity, int i, int j, boolean flag) { +- this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast); ++ this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, seenBy); // CraftBukkit + this.entity = entity; + this.range = i; + this.lastSectionPos = SectionPos.of((EntityAccess) entity); + } + +- @Override + public boolean equals(Object object) { + return object instanceof ChunkMap.TrackedEntity ? ((ChunkMap.TrackedEntity) object).entity.getId() == this.entity.getId() : false; + } + +- @Override + public int hashCode() { + return this.entity.getId(); + } +@@ -1513,35 +1553,40 @@ + + } + +- public void removePlayer(ServerPlayer serverplayer) { +- if (this.seenBy.remove(serverplayer.connection)) { +- this.serverEntity.removePairing(serverplayer); ++ public void removePlayer(ServerPlayer player) { ++ if (this.seenBy.remove(player.connection)) { ++ this.serverEntity.removePairing(player); + } + + } + +- public void updatePlayer(ServerPlayer serverplayer) { +- if (serverplayer != this.entity) { +- Vec3 vec3 = serverplayer.position().subtract(this.entity.position()); +- int i = ChunkMap.this.getPlayerViewDistance(serverplayer); ++ public void updatePlayer(ServerPlayer player) { ++ if (player != this.entity) { ++ Vec3 vec3d = player.position().subtract(this.entity.position()); ++ int i = ChunkMap.this.getPlayerViewDistance(player); + double d0 = (double) Math.min(this.getEffectiveRange(), i * 16); +- double d1 = vec3.x * vec3.x + vec3.z * vec3.z; ++ double d1 = vec3d.x * vec3d.x + vec3d.z * vec3d.z; + double d2 = d0 * d0; +- boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(serverplayer) && ChunkMap.this.isChunkTracked(serverplayer, this.entity.chunkPosition().x, this.entity.chunkPosition().z); ++ boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(player) && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z); + ++ // CraftBukkit start - respect vanish API ++ if (!player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { ++ flag = false; ++ } ++ // CraftBukkit end + if (flag) { +- if (this.seenBy.add(serverplayer.connection)) { +- this.serverEntity.addPairing(serverplayer); ++ if (this.seenBy.add(player.connection)) { ++ this.serverEntity.addPairing(player); + } +- } else if (this.seenBy.remove(serverplayer.connection)) { +- this.serverEntity.removePairing(serverplayer); ++ } else if (this.seenBy.remove(player.connection)) { ++ this.serverEntity.removePairing(player); + } + + } + } + +- private int scaledRange(int i) { +- return ChunkMap.this.level.getServer().getScaledTrackingDistance(i); ++ private int scaledRange(int trackingDistance) { ++ return ChunkMap.this.level.getServer().getScaledTrackingDistance(trackingDistance); + } + + private int getEffectiveRange() { +@@ -1560,13 +1605,13 @@ + return this.scaledRange(i); + } + +- public void updatePlayers(List list) { +- Iterator iterator = list.iterator(); ++ public void updatePlayers(List playersList) { ++ Iterator iterator = playersList.iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- this.updatePlayer(serverplayer); ++ this.updatePlayer(entityplayer); + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/level/DistanceManager.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/level/DistanceManager.java.patch new file mode 100644 index 0000000000..ade6cf5c6c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/level/DistanceManager.java.patch @@ -0,0 +1,598 @@ +--- a/net/minecraft/server/level/DistanceManager.java ++++ b/net/minecraft/server/level/DistanceManager.java +@@ -43,7 +43,7 @@ + static final int PLAYER_TICKET_LEVEL = ChunkLevel.byStatus(FullChunkStatus.ENTITY_TICKING); + private static final int INITIAL_TICKET_LIST_CAPACITY = 4; + final Long2ObjectMap> playersPerChunk = new Long2ObjectOpenHashMap(); +- final Long2ObjectOpenHashMap>> tickets = new Long2ObjectOpenHashMap(); ++ public final Long2ObjectOpenHashMap>> tickets = new Long2ObjectOpenHashMap(); + private final DistanceManager.ChunkTicketTracker ticketTracker = new DistanceManager.ChunkTicketTracker(); + private final DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter = new DistanceManager.FixedPlayerDistanceChunkTracker(8); + private final TickingTracker tickingTicketsTracker = new TickingTracker(); +@@ -57,15 +57,15 @@ + private long ticketTickCounter; + private int simulationDistance = 10; + +- protected DistanceManager(Executor executor, Executor executor1) { +- Objects.requireNonNull(executor1); +- ProcessorHandle processorhandle = ProcessorHandle.of("player ticket throttler", executor1::execute); +- ChunkTaskPriorityQueueSorter chunktaskpriorityqueuesorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(processorhandle), executor, 4); ++ protected DistanceManager(Executor dispatcher, Executor mainThreadExecutor) { ++ Objects.requireNonNull(mainThreadExecutor); ++ ProcessorHandle mailbox = ProcessorHandle.of("player ticket throttler", mainThreadExecutor::execute); ++ ChunkTaskPriorityQueueSorter chunktaskqueuesorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(mailbox), dispatcher, 4); + +- this.ticketThrottler = chunktaskpriorityqueuesorter; +- this.ticketThrottlerInput = chunktaskpriorityqueuesorter.getProcessor(processorhandle, true); +- this.ticketThrottlerReleaser = chunktaskpriorityqueuesorter.getReleaseProcessor(processorhandle); +- this.mainThreadExecutor = executor1; ++ this.ticketThrottler = chunktaskqueuesorter; ++ this.ticketThrottlerInput = chunktaskqueuesorter.getProcessor(mailbox, true); ++ this.ticketThrottlerReleaser = chunktaskqueuesorter.getReleaseProcessor(mailbox); ++ this.mainThreadExecutor = mainThreadExecutor; + } + + protected void purgeStaleTickets() { +@@ -98,8 +98,8 @@ + + } + +- private static int getTicketLevelAt(SortedArraySet> sortedarrayset) { +- return !sortedarrayset.isEmpty() ? ((Ticket) sortedarrayset.first()).getTicketLevel() : ChunkLevel.MAX_LEVEL + 1; ++ private static int getTicketLevelAt(SortedArraySet> tickets) { ++ return !tickets.isEmpty() ? ((Ticket) tickets.first()).getTicketLevel() : ChunkLevel.MAX_LEVEL + 1; + } + + protected abstract boolean isChunkToRemove(long chunkPos); +@@ -108,9 +108,9 @@ + protected abstract ChunkHolder getChunk(long chunkPos); + + @Nullable +- protected abstract ChunkHolder updateChunkScheduling(long chunkPos, int i, @Nullable ChunkHolder newLevel, int holder); ++ protected abstract ChunkHolder updateChunkScheduling(long chunkPos, int j, @Nullable ChunkHolder newLevel, int holder); + +- public boolean runAllUpdates(ChunkMap chunkmap) { ++ public boolean runAllUpdates(ChunkMap chunkManager) { + this.naturalSpawnChunkCounter.runAllUpdates(); + this.tickingTicketsTracker.runAllUpdates(); + this.playerTicketManager.runAllUpdates(); +@@ -122,10 +122,25 @@ + } + + if (!this.chunksToUpdateFutures.isEmpty()) { +- this.chunksToUpdateFutures.forEach((chunkholder) -> { +- chunkholder.updateFutures(chunkmap, this.mainThreadExecutor); +- }); +- this.chunksToUpdateFutures.clear(); ++ // CraftBukkit start ++ // Iterate pending chunk updates with protection against concurrent modification exceptions ++ java.util.Iterator iter = this.chunksToUpdateFutures.iterator(); ++ int expectedSize = this.chunksToUpdateFutures.size(); ++ do { ++ ChunkHolder playerchunk = iter.next(); ++ iter.remove(); ++ expectedSize--; ++ ++ playerchunk.updateFutures(chunkManager, this.mainThreadExecutor); ++ ++ // Reset iterator if set was modified using add() ++ if (this.chunksToUpdateFutures.size() != expectedSize) { ++ expectedSize = this.chunksToUpdateFutures.size(); ++ iter = this.chunksToUpdateFutures.iterator(); ++ } ++ } while (iter.hasNext()); ++ // CraftBukkit end ++ + return true; + } else { + if (!this.ticketsToRelease.isEmpty()) { +@@ -137,13 +152,13 @@ + if (this.getTickets(j).stream().anyMatch((ticket) -> { + return ticket.getType() == TicketType.PLAYER; + })) { +- ChunkHolder chunkholder = chunkmap.getUpdatingChunkIfPresent(j); ++ ChunkHolder playerchunk = chunkManager.getUpdatingChunkIfPresent(j); + +- if (chunkholder == null) { ++ if (playerchunk == null) { + throw new IllegalStateException(); + } + +- CompletableFuture> completablefuture = chunkholder.getEntityTickingChunkFuture(); ++ CompletableFuture> completablefuture = playerchunk.getEntityTickingChunkFuture(); + + completablefuture.thenAccept((either) -> { + this.mainThreadExecutor.execute(() -> { +@@ -161,69 +176,86 @@ + } + } + +- void addTicket(long i, Ticket ticket) { +- SortedArraySet> sortedarrayset = this.getTickets(i); +- int j = getTicketLevelAt(sortedarrayset); +- Ticket ticket1 = (Ticket) sortedarrayset.addOrGet(ticket); ++ boolean addTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean ++ SortedArraySet> arraysetsorted = this.getTickets(i); ++ int j = getTicketLevelAt(arraysetsorted); ++ Ticket ticket1 = (Ticket) arraysetsorted.addOrGet(ticket); + + ticket1.setCreatedTick(this.ticketTickCounter); + if (ticket.getTicketLevel() < j) { + this.ticketTracker.update(i, ticket.getTicketLevel(), true); + } + ++ return ticket == ticket1; // CraftBukkit + } + +- void removeTicket(long i, Ticket ticket) { +- SortedArraySet> sortedarrayset = this.getTickets(i); ++ boolean removeTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean ++ SortedArraySet> arraysetsorted = this.getTickets(i); + +- if (sortedarrayset.remove(ticket)) { +- ; ++ boolean removed = false; // CraftBukkit ++ if (arraysetsorted.remove(ticket)) { ++ removed = true; // CraftBukkit + } + +- if (sortedarrayset.isEmpty()) { ++ if (arraysetsorted.isEmpty()) { + this.tickets.remove(i); + } + +- this.ticketTracker.update(i, getTicketLevelAt(sortedarrayset), false); ++ this.ticketTracker.update(i, getTicketLevelAt(arraysetsorted), false); ++ return removed; // CraftBukkit + } + +- public void addTicket(TicketType tickettype, ChunkPos chunkpos, int i, T t0) { +- this.addTicket(chunkpos.toLong(), new Ticket<>(tickettype, i, t0)); ++ public void addTicket(TicketType type, ChunkPos pos, int level, T value) { ++ this.addTicket(pos.toLong(), new Ticket<>(type, level, value)); + } + +- public void removeTicket(TicketType tickettype, ChunkPos chunkpos, int i, T t0) { +- Ticket ticket = new Ticket<>(tickettype, i, t0); ++ public void removeTicket(TicketType type, ChunkPos pos, int level, T value) { ++ Ticket ticket = new Ticket<>(type, level, value); + +- this.removeTicket(chunkpos.toLong(), ticket); ++ this.removeTicket(pos.toLong(), ticket); + } + +- public void addRegionTicket(TicketType tickettype, ChunkPos chunkpos, int i, T t0) { ++ public void addRegionTicket(TicketType type, ChunkPos pos, int distance, T value) { ++ // CraftBukkit start ++ addRegionTicketAtDistance(type, pos, distance, value); ++ } ++ ++ public boolean addRegionTicketAtDistance(TicketType tickettype, ChunkPos chunkcoordintpair, int i, T t0) { ++ // CraftBukkit end + Ticket ticket = new Ticket<>(tickettype, ChunkLevel.byStatus(FullChunkStatus.FULL) - i, t0); +- long j = chunkpos.toLong(); ++ long j = chunkcoordintpair.toLong(); + +- this.addTicket(j, ticket); ++ boolean added = this.addTicket(j, ticket); // CraftBukkit + this.tickingTicketsTracker.addTicket(j, ticket); ++ return added; // CraftBukkit + } + +- public void removeRegionTicket(TicketType tickettype, ChunkPos chunkpos, int i, T t0) { ++ public void removeRegionTicket(TicketType type, ChunkPos pos, int distance, T value) { ++ // CraftBukkit start ++ removeRegionTicketAtDistance(type, pos, distance, value); ++ } ++ ++ public boolean removeRegionTicketAtDistance(TicketType tickettype, ChunkPos chunkcoordintpair, int i, T t0) { ++ // CraftBukkit end + Ticket ticket = new Ticket<>(tickettype, ChunkLevel.byStatus(FullChunkStatus.FULL) - i, t0); +- long j = chunkpos.toLong(); ++ long j = chunkcoordintpair.toLong(); + +- this.removeTicket(j, ticket); ++ boolean removed = this.removeTicket(j, ticket); // CraftBukkit + this.tickingTicketsTracker.removeTicket(j, ticket); ++ return removed; // CraftBukkit + } + +- private SortedArraySet> getTickets(long i) { +- return (SortedArraySet) this.tickets.computeIfAbsent(i, (j) -> { ++ private SortedArraySet> getTickets(long chunkPos) { ++ return (SortedArraySet) this.tickets.computeIfAbsent(chunkPos, (j) -> { + return SortedArraySet.create(4); + }); + } + +- protected void updateChunkForced(ChunkPos chunkpos, boolean flag) { +- Ticket ticket = new Ticket<>(TicketType.FORCED, ChunkMap.FORCED_TICKET_LEVEL, chunkpos); +- long i = chunkpos.toLong(); ++ protected void updateChunkForced(ChunkPos pos, boolean add) { ++ Ticket ticket = new Ticket<>(TicketType.FORCED, ChunkMap.FORCED_TICKET_LEVEL, pos); ++ long i = pos.toLong(); + +- if (flag) { ++ if (add) { + this.addTicket(i, ticket); + this.tickingTicketsTracker.addTicket(i, ticket); + } else { +@@ -233,29 +265,30 @@ + + } + +- public void addPlayer(SectionPos sectionpos, ServerPlayer serverplayer) { +- ChunkPos chunkpos = sectionpos.chunk(); +- long i = chunkpos.toLong(); ++ public void addPlayer(SectionPos sectionPos, ServerPlayer player) { ++ ChunkPos chunkcoordintpair = sectionPos.chunk(); ++ long i = chunkcoordintpair.toLong(); + + ((ObjectSet) this.playersPerChunk.computeIfAbsent(i, (j) -> { + return new ObjectOpenHashSet(); +- })).add(serverplayer); ++ })).add(player); + this.naturalSpawnChunkCounter.update(i, 0, true); + this.playerTicketManager.update(i, 0, true); +- this.tickingTicketsTracker.addTicket(TicketType.PLAYER, chunkpos, this.getPlayerTicketLevel(), chunkpos); ++ this.tickingTicketsTracker.addTicket(TicketType.PLAYER, chunkcoordintpair, this.getPlayerTicketLevel(), chunkcoordintpair); + } + +- public void removePlayer(SectionPos sectionpos, ServerPlayer serverplayer) { +- ChunkPos chunkpos = sectionpos.chunk(); +- long i = chunkpos.toLong(); ++ public void removePlayer(SectionPos sectionPos, ServerPlayer player) { ++ ChunkPos chunkcoordintpair = sectionPos.chunk(); ++ long i = chunkcoordintpair.toLong(); + ObjectSet objectset = (ObjectSet) this.playersPerChunk.get(i); ++ if (objectset == null) return; // CraftBukkit - SPIGOT-6208 + +- objectset.remove(serverplayer); ++ objectset.remove(player); + if (objectset.isEmpty()) { + this.playersPerChunk.remove(i); + this.naturalSpawnChunkCounter.update(i, Integer.MAX_VALUE, false); + this.playerTicketManager.update(i, Integer.MAX_VALUE, false); +- this.tickingTicketsTracker.removeTicket(TicketType.PLAYER, chunkpos, this.getPlayerTicketLevel(), chunkpos); ++ this.tickingTicketsTracker.removeTicket(TicketType.PLAYER, chunkcoordintpair, this.getPlayerTicketLevel(), chunkcoordintpair); + } + + } +@@ -264,27 +297,27 @@ + return Math.max(0, ChunkLevel.byStatus(FullChunkStatus.ENTITY_TICKING) - this.simulationDistance); + } + +- public boolean inEntityTickingRange(long i) { +- return ChunkLevel.isEntityTicking(this.tickingTicketsTracker.getLevel(i)); ++ public boolean inEntityTickingRange(long chunkPos) { ++ return ChunkLevel.isEntityTicking(this.tickingTicketsTracker.getLevel(chunkPos)); + } + +- public boolean inBlockTickingRange(long i) { +- return ChunkLevel.isBlockTicking(this.tickingTicketsTracker.getLevel(i)); ++ public boolean inBlockTickingRange(long chunkPos) { ++ return ChunkLevel.isBlockTicking(this.tickingTicketsTracker.getLevel(chunkPos)); + } + +- protected String getTicketDebugString(long i) { +- SortedArraySet> sortedarrayset = (SortedArraySet) this.tickets.get(i); ++ protected String getTicketDebugString(long chunkPos) { ++ SortedArraySet> arraysetsorted = (SortedArraySet) this.tickets.get(chunkPos); + +- return sortedarrayset != null && !sortedarrayset.isEmpty() ? ((Ticket) sortedarrayset.first()).toString() : "no_ticket"; ++ return arraysetsorted != null && !arraysetsorted.isEmpty() ? ((Ticket) arraysetsorted.first()).toString() : "no_ticket"; + } + +- protected void updatePlayerTickets(int i) { +- this.playerTicketManager.updateViewDistance(i); ++ protected void updatePlayerTickets(int viewDistance) { ++ this.playerTicketManager.updateViewDistance(viewDistance); + } + +- public void updateSimulationDistance(int i) { +- if (i != this.simulationDistance) { +- this.simulationDistance = i; ++ public void updateSimulationDistance(int simulationDistance) { ++ if (simulationDistance != this.simulationDistance) { ++ this.simulationDistance = simulationDistance; + this.tickingTicketsTracker.replacePlayerTicketsLevel(this.getPlayerTicketLevel()); + } + +@@ -295,31 +328,31 @@ + return this.naturalSpawnChunkCounter.chunks.size(); + } + +- public boolean hasPlayersNearby(long i) { ++ public boolean hasPlayersNearby(long chunkPos) { + this.naturalSpawnChunkCounter.runAllUpdates(); +- return this.naturalSpawnChunkCounter.chunks.containsKey(i); ++ return this.naturalSpawnChunkCounter.chunks.containsKey(chunkPos); + } + + public String getDebugStatus() { + return this.ticketThrottler.getDebugStatus(); + } + +- private void dumpTickets(String s) { ++ private void dumpTickets(String filename) { + try { +- FileOutputStream fileoutputstream = new FileOutputStream(new File(s)); ++ FileOutputStream fileoutputstream = new FileOutputStream(new File(filename)); + + try { + ObjectIterator objectiterator = this.tickets.long2ObjectEntrySet().iterator(); + + while (objectiterator.hasNext()) { + Entry>> entry = (Entry) objectiterator.next(); +- ChunkPos chunkpos = new ChunkPos(entry.getLongKey()); ++ ChunkPos chunkcoordintpair = new ChunkPos(entry.getLongKey()); + Iterator iterator = ((SortedArraySet) entry.getValue()).iterator(); + + while (iterator.hasNext()) { + Ticket ticket = (Ticket) iterator.next(); + +- fileoutputstream.write((chunkpos.x + "\t" + chunkpos.z + "\t" + ticket.getType() + "\t" + ticket.getTicketLevel() + "\t\n").getBytes(StandardCharsets.UTF_8)); ++ fileoutputstream.write((chunkcoordintpair.x + "\t" + chunkcoordintpair.z + "\t" + ticket.getType() + "\t" + ticket.getTicketLevel() + "\t\n").getBytes(StandardCharsets.UTF_8)); + } + } + } catch (Throwable throwable) { +@@ -334,7 +367,7 @@ + + fileoutputstream.close(); + } catch (IOException ioexception) { +- DistanceManager.LOGGER.error("Failed to dump tickets to {}", s, ioexception); ++ DistanceManager.LOGGER.error("Failed to dump tickets to {}", filename, ioexception); + } + + } +@@ -378,6 +411,26 @@ + return !this.tickets.isEmpty(); + } + ++ // CraftBukkit start ++ public void removeAllTicketsFor(TicketType ticketType, int ticketLevel, T ticketIdentifier) { ++ Ticket target = new Ticket<>(ticketType, ticketLevel, ticketIdentifier); ++ ++ for (java.util.Iterator>>> iterator = this.tickets.long2ObjectEntrySet().fastIterator(); iterator.hasNext();) { ++ Entry>> entry = iterator.next(); ++ SortedArraySet> tickets = entry.getValue(); ++ if (tickets.remove(target)) { ++ // copied from removeTicket ++ this.ticketTracker.update(entry.getLongKey(), getTicketLevelAt(tickets), false); ++ ++ // can't use entry after it's removed ++ if (tickets.isEmpty()) { ++ iterator.remove(); ++ } ++ } ++ } ++ } ++ // CraftBukkit end ++ + private class ChunkTicketTracker extends ChunkTracker { + + private static final int MAX_LEVEL = ChunkLevel.MAX_LEVEL + 1; +@@ -387,21 +440,19 @@ + } + + @Override +- @Override +- protected int getLevelFromSource(long i) { +- SortedArraySet> sortedarrayset = (SortedArraySet) DistanceManager.this.tickets.get(i); ++ protected int getLevelFromSource(long pos) { ++ SortedArraySet> arraysetsorted = (SortedArraySet) DistanceManager.this.tickets.get(pos); + +- return sortedarrayset == null ? Integer.MAX_VALUE : (sortedarrayset.isEmpty() ? Integer.MAX_VALUE : ((Ticket) sortedarrayset.first()).getTicketLevel()); ++ return arraysetsorted == null ? Integer.MAX_VALUE : (arraysetsorted.isEmpty() ? Integer.MAX_VALUE : ((Ticket) arraysetsorted.first()).getTicketLevel()); + } + + @Override +- @Override +- protected int getLevel(long i) { +- if (!DistanceManager.this.isChunkToRemove(i)) { +- ChunkHolder chunkholder = DistanceManager.this.getChunk(i); ++ protected int getLevel(long sectionPos) { ++ if (!DistanceManager.this.isChunkToRemove(sectionPos)) { ++ ChunkHolder playerchunk = DistanceManager.this.getChunk(sectionPos); + +- if (chunkholder != null) { +- return chunkholder.getTicketLevel(); ++ if (playerchunk != null) { ++ return playerchunk.getTicketLevel(); + } + } + +@@ -409,22 +460,21 @@ + } + + @Override +- @Override +- protected void setLevel(long i, int j) { +- ChunkHolder chunkholder = DistanceManager.this.getChunk(i); +- int k = chunkholder == null ? DistanceManager.ChunkTicketTracker.MAX_LEVEL : chunkholder.getTicketLevel(); ++ protected void setLevel(long sectionPos, int j) { ++ ChunkHolder playerchunk = DistanceManager.this.getChunk(sectionPos); ++ int k = playerchunk == null ? DistanceManager.ChunkTicketTracker.MAX_LEVEL : playerchunk.getTicketLevel(); + + if (k != j) { +- chunkholder = DistanceManager.this.updateChunkScheduling(i, j, chunkholder, k); +- if (chunkholder != null) { +- DistanceManager.this.chunksToUpdateFutures.add(chunkholder); ++ playerchunk = DistanceManager.this.updateChunkScheduling(sectionPos, j, playerchunk, k); ++ if (playerchunk != null) { ++ DistanceManager.this.chunksToUpdateFutures.add(playerchunk); + } + + } + } + +- public int runDistanceUpdates(int i) { +- return this.runUpdates(i); ++ public int runDistanceUpdates(int toUpdateCount) { ++ return this.runUpdates(toUpdateCount); + } + } + +@@ -440,35 +490,32 @@ + } + + @Override +- @Override +- protected int getLevel(long i) { +- return this.chunks.get(i); ++ protected int getLevel(long sectionPos) { ++ return this.chunks.get(sectionPos); + } + + @Override +- @Override +- protected void setLevel(long i, int j) { ++ protected void setLevel(long sectionPos, int j) { + byte b0; + + if (j > this.maxDistance) { +- b0 = this.chunks.remove(i); ++ b0 = this.chunks.remove(sectionPos); + } else { +- b0 = this.chunks.put(i, (byte) j); ++ b0 = this.chunks.put(sectionPos, (byte) j); + } + +- this.onLevelChange(i, b0, j); ++ this.onLevelChange(sectionPos, b0, j); + } + +- protected void onLevelChange(long i, int j, int k) {} ++ protected void onLevelChange(long chunkPos, int j, int oldLevel) {} + + @Override +- @Override +- protected int getLevelFromSource(long i) { +- return this.havePlayer(i) ? 0 : Integer.MAX_VALUE; ++ protected int getLevelFromSource(long pos) { ++ return this.havePlayer(pos) ? 0 : Integer.MAX_VALUE; + } + +- private boolean havePlayer(long i) { +- ObjectSet objectset = (ObjectSet) DistanceManager.this.playersPerChunk.get(i); ++ private boolean havePlayer(long chunkPos) { ++ ObjectSet objectset = (ObjectSet) DistanceManager.this.playersPerChunk.get(chunkPos); + + return objectset != null && !objectset.isEmpty(); + } +@@ -477,19 +524,19 @@ + this.runUpdates(Integer.MAX_VALUE); + } + +- private void dumpChunks(String s) { ++ private void dumpChunks(String filename) { + try { +- FileOutputStream fileoutputstream = new FileOutputStream(new File(s)); ++ FileOutputStream fileoutputstream = new FileOutputStream(new File(filename)); + + try { + ObjectIterator objectiterator = this.chunks.long2ByteEntrySet().iterator(); + + while (objectiterator.hasNext()) { + it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry) objectiterator.next(); +- ChunkPos chunkpos = new ChunkPos(it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey()); ++ ChunkPos chunkcoordintpair = new ChunkPos(it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey()); + String s1 = Byte.toString(it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue()); + +- fileoutputstream.write((chunkpos.x + "\t" + chunkpos.z + "\t" + s1 + "\n").getBytes(StandardCharsets.UTF_8)); ++ fileoutputstream.write((chunkcoordintpair.x + "\t" + chunkcoordintpair.z + "\t" + s1 + "\n").getBytes(StandardCharsets.UTF_8)); + } + } catch (Throwable throwable) { + try { +@@ -503,7 +550,7 @@ + + fileoutputstream.close(); + } catch (IOException ioexception) { +- DistanceManager.LOGGER.error("Failed to dump chunks to {}", s, ioexception); ++ DistanceManager.LOGGER.error("Failed to dump chunks to {}", filename, ioexception); + } + + } +@@ -521,12 +568,11 @@ + } + + @Override +- @Override +- protected void onLevelChange(long i, int j, int k) { +- this.toUpdate.add(i); ++ protected void onLevelChange(long chunkPos, int j, int oldLevel) { ++ this.toUpdate.add(chunkPos); + } + +- public void updateViewDistance(int i) { ++ public void updateViewDistance(int viewDistance) { + ObjectIterator objectiterator = this.chunks.long2ByteEntrySet().iterator(); + + while (objectiterator.hasNext()) { +@@ -534,44 +580,43 @@ + byte b0 = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue(); + long j = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey(); + +- this.onLevelChange(j, b0, this.haveTicketFor(b0), b0 <= i); ++ this.onLevelChange(j, b0, this.haveTicketFor(b0), b0 <= viewDistance); + } + +- this.viewDistance = i; ++ this.viewDistance = viewDistance; + } + +- private void onLevelChange(long i, int j, boolean flag, boolean flag1) { ++ private void onLevelChange(long chunkPos, int j, boolean flag, boolean flag1) { + if (flag != flag1) { +- Ticket ticket = new Ticket<>(TicketType.PLAYER, DistanceManager.PLAYER_TICKET_LEVEL, new ChunkPos(i)); ++ Ticket ticket = new Ticket<>(TicketType.PLAYER, DistanceManager.PLAYER_TICKET_LEVEL, new ChunkPos(chunkPos)); + + if (flag1) { + DistanceManager.this.ticketThrottlerInput.tell(ChunkTaskPriorityQueueSorter.message(() -> { + DistanceManager.this.mainThreadExecutor.execute(() -> { +- if (this.haveTicketFor(this.getLevel(i))) { +- DistanceManager.this.addTicket(i, ticket); +- DistanceManager.this.ticketsToRelease.add(i); ++ if (this.haveTicketFor(this.getLevel(chunkPos))) { ++ DistanceManager.this.addTicket(chunkPos, ticket); ++ DistanceManager.this.ticketsToRelease.add(chunkPos); + } else { + DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { +- }, i, false)); ++ }, chunkPos, false)); + } + + }); +- }, i, () -> { ++ }, chunkPos, () -> { + return j; + })); + } else { + DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { + DistanceManager.this.mainThreadExecutor.execute(() -> { +- DistanceManager.this.removeTicket(i, ticket); ++ DistanceManager.this.removeTicket(chunkPos, ticket); + }); +- }, i, true)); ++ }, chunkPos, true)); + } + } + + } + + @Override +- @Override + public void runAllUpdates() { + super.runAllUpdates(); + if (!this.toUpdate.isEmpty()) { +@@ -602,8 +647,8 @@ + + } + +- private boolean haveTicketFor(int i) { +- return i <= this.viewDistance; ++ private boolean haveTicketFor(int level) { ++ return level <= this.viewDistance; + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/level/ServerChunkCache.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/level/ServerChunkCache.java.patch new file mode 100644 index 0000000000..6668fd6616 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/level/ServerChunkCache.java.patch @@ -0,0 +1,695 @@ +--- a/net/minecraft/server/level/ServerChunkCache.java ++++ b/net/minecraft/server/level/ServerChunkCache.java +@@ -28,9 +28,9 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.ai.village.poi.PoiManager; + import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.EnumSkyBlock; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.LocalMobCapCalculator; + import net.minecraft.world.level.NaturalSpawner; + import net.minecraft.world.level.chunk.ChunkAccess; +@@ -58,8 +58,8 @@ + public final ChunkMap chunkMap; + private final DimensionDataStorage dataStorage; + private long lastInhabitedUpdate; +- private boolean spawnEnemies = true; +- private boolean spawnFriendlies = true; ++ public boolean spawnEnemies = true; ++ public boolean spawnFriendlies = true; + private static final int CACHE_SIZE = 4; + private final long[] lastChunkPos = new long[4]; + private final ChunkStatus[] lastChunkStatus = new ChunkStatus[4]; +@@ -68,127 +68,134 @@ + @VisibleForDebug + private NaturalSpawner.SpawnState lastSpawnState; + +- public ServerChunkCache(ServerLevel serverlevel, LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess, DataFixer datafixer, StructureTemplateManager structuretemplatemanager, Executor executor, ChunkGenerator chunkgenerator, int i, int j, boolean flag, ChunkProgressListener chunkprogresslistener, ChunkStatusUpdateListener chunkstatusupdatelistener, Supplier supplier) { +- this.level = serverlevel; +- this.mainThreadProcessor = new ServerChunkCache.MainThreadExecutor(serverlevel); ++ public ServerChunkCache(ServerLevel level, LevelStorageSource.LevelStorageAccess levelStorageAccess, DataFixer fixerUpper, StructureTemplateManager structureManager, Executor dispatcher, ChunkGenerator generator, int viewDistance, int simulationDistance, boolean sync, ChunkProgressListener progressListener, ChunkStatusUpdateListener chunkStatusListener, Supplier overworldDataStorage) { ++ this.level = level; ++ this.mainThreadProcessor = new ServerChunkCache.MainThreadExecutor(level); + this.mainThread = Thread.currentThread(); +- File file = levelstoragesource_levelstorageaccess.getDimensionPath(serverlevel.dimension()).resolve("data").toFile(); ++ File file = levelStorageAccess.getDimensionPath(level.dimension()).resolve("data").toFile(); + + file.mkdirs(); +- this.dataStorage = new DimensionDataStorage(file, datafixer); +- this.chunkMap = new ChunkMap(serverlevel, levelstoragesource_levelstorageaccess, datafixer, structuretemplatemanager, executor, this.mainThreadProcessor, this, chunkgenerator, chunkprogresslistener, chunkstatusupdatelistener, supplier, i, flag); ++ this.dataStorage = new DimensionDataStorage(file, fixerUpper); ++ this.chunkMap = new ChunkMap(level, levelStorageAccess, fixerUpper, structureManager, dispatcher, this.mainThreadProcessor, this, generator, progressListener, chunkStatusListener, overworldDataStorage, viewDistance, sync); + this.lightEngine = this.chunkMap.getLightEngine(); + this.distanceManager = this.chunkMap.getDistanceManager(); +- this.distanceManager.updateSimulationDistance(j); ++ this.distanceManager.updateSimulationDistance(simulationDistance); + this.clearCache(); + } + ++ // CraftBukkit start - properly implement isChunkLoaded ++ public boolean isChunkLoaded(int chunkX, int chunkZ) { ++ ChunkHolder chunk = this.chunkMap.getUpdatingChunkIfPresent(ChunkPos.asLong(chunkX, chunkZ)); ++ if (chunk == null) { ++ return false; ++ } ++ return chunk.getFullChunkNow() != null; ++ } ++ // CraftBukkit end ++ + @Override +- @Override + public ThreadedLevelLightEngine getLightEngine() { + return this.lightEngine; + } + + @Nullable +- private ChunkHolder getVisibleChunkIfPresent(long i) { +- return this.chunkMap.getVisibleChunkIfPresent(i); ++ private ChunkHolder getVisibleChunkIfPresent(long chunkPos) { ++ return this.chunkMap.getVisibleChunkIfPresent(chunkPos); + } + + public int getTickingGenerated() { + return this.chunkMap.getTickingGenerated(); + } + +- private void storeInCache(long i, ChunkAccess chunkaccess, ChunkStatus chunkstatus) { ++ private void storeInCache(long chunkPos, ChunkAccess ichunkaccess, ChunkStatus chunk) { + for (int j = 3; j > 0; --j) { + this.lastChunkPos[j] = this.lastChunkPos[j - 1]; + this.lastChunkStatus[j] = this.lastChunkStatus[j - 1]; + this.lastChunk[j] = this.lastChunk[j - 1]; + } + +- this.lastChunkPos[0] = i; +- this.lastChunkStatus[0] = chunkstatus; +- this.lastChunk[0] = chunkaccess; ++ this.lastChunkPos[0] = chunkPos; ++ this.lastChunkStatus[0] = chunk; ++ this.lastChunk[0] = ichunkaccess; + } + + @Nullable + @Override +- @Override +- public ChunkAccess getChunk(int i, int j, ChunkStatus chunkstatus, boolean flag) { ++ public ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus requiredStatus, boolean load) { + if (Thread.currentThread() != this.mainThread) { + return (ChunkAccess) CompletableFuture.supplyAsync(() -> { +- return this.getChunk(i, j, chunkstatus, flag); ++ return this.getChunk(chunkX, chunkZ, requiredStatus, load); + }, this.mainThreadProcessor).join(); + } else { +- ProfilerFiller profilerfiller = this.level.getProfiler(); ++ ProfilerFiller gameprofilerfiller = this.level.getProfiler(); + +- profilerfiller.incrementCounter("getChunk"); +- long k = ChunkPos.asLong(i, j); ++ gameprofilerfiller.incrementCounter("getChunk"); ++ long k = ChunkPos.asLong(chunkX, chunkZ); + +- ChunkAccess chunkaccess; ++ ChunkAccess ichunkaccess; + + for (int l = 0; l < 4; ++l) { +- if (k == this.lastChunkPos[l] && chunkstatus == this.lastChunkStatus[l]) { +- chunkaccess = this.lastChunk[l]; +- if (chunkaccess != null || !flag) { +- return chunkaccess; ++ if (k == this.lastChunkPos[l] && requiredStatus == this.lastChunkStatus[l]) { ++ ichunkaccess = this.lastChunk[l]; ++ if (ichunkaccess != null) { // CraftBukkit - the chunk can become accessible in the meantime TODO for non-null chunks it might also make sense to check that the chunk's state hasn't changed in the meantime ++ return ichunkaccess; + } + } + } + +- profilerfiller.incrementCounter("getChunkCacheMiss"); +- CompletableFuture> completablefuture = this.getChunkFutureMainThread(i, j, chunkstatus, flag); +- ServerChunkCache.MainThreadExecutor serverchunkcache_mainthreadexecutor = this.mainThreadProcessor; ++ gameprofilerfiller.incrementCounter("getChunkCacheMiss"); ++ CompletableFuture> completablefuture = this.getChunkFutureMainThread(chunkX, chunkZ, requiredStatus, load); ++ ServerChunkCache.MainThreadExecutor chunkproviderserver_b = this.mainThreadProcessor; + + Objects.requireNonNull(completablefuture); +- serverchunkcache_mainthreadexecutor.managedBlock(completablefuture::isDone); +- chunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((chunkaccess1) -> { +- return chunkaccess1; +- }, (chunkholder_chunkloadingfailure) -> { +- if (flag) { +- throw (IllegalStateException) Util.pauseInIde(new IllegalStateException("Chunk not there when requested: " + chunkholder_chunkloadingfailure)); ++ chunkproviderserver_b.managedBlock(completablefuture::isDone); ++ ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { ++ return ichunkaccess1; ++ }, (playerchunk_failure) -> { ++ if (load) { ++ throw (IllegalStateException) Util.pauseInIde(new IllegalStateException("Chunk not there when requested: " + playerchunk_failure)); + } else { + return null; + } + }); +- this.storeInCache(k, chunkaccess, chunkstatus); +- return chunkaccess; ++ this.storeInCache(k, ichunkaccess, requiredStatus); ++ return ichunkaccess; + } + } + + @Nullable + @Override +- @Override +- public LevelChunk getChunkNow(int i, int j) { ++ public LevelChunk getChunkNow(int chunkX, int chunkZ) { + if (Thread.currentThread() != this.mainThread) { + return null; + } else { + this.level.getProfiler().incrementCounter("getChunkNow"); +- long k = ChunkPos.asLong(i, j); ++ long k = ChunkPos.asLong(chunkX, chunkZ); + + for (int l = 0; l < 4; ++l) { + if (k == this.lastChunkPos[l] && this.lastChunkStatus[l] == ChunkStatus.FULL) { +- ChunkAccess chunkaccess = this.lastChunk[l]; ++ ChunkAccess ichunkaccess = this.lastChunk[l]; + +- return chunkaccess instanceof LevelChunk ? (LevelChunk) chunkaccess : null; ++ return ichunkaccess instanceof LevelChunk ? (LevelChunk) ichunkaccess : null; + } + } + +- ChunkHolder chunkholder = this.getVisibleChunkIfPresent(k); ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(k); + +- if (chunkholder == null) { ++ if (playerchunk == null) { + return null; + } else { +- Either either = (Either) chunkholder.getFutureIfPresent(ChunkStatus.FULL).getNow((Object) null); ++ Either either = (Either) playerchunk.getFutureIfPresent(ChunkStatus.FULL).getNow(null); // CraftBukkit - decompile error + + if (either == null) { + return null; + } else { +- ChunkAccess chunkaccess1 = (ChunkAccess) either.left().orElse((Object) null); ++ ChunkAccess ichunkaccess1 = (ChunkAccess) either.left().orElse(null); // CraftBukkit - decompile error + +- if (chunkaccess1 != null) { +- this.storeInCache(k, chunkaccess1, ChunkStatus.FULL); +- if (chunkaccess1 instanceof LevelChunk) { +- return (LevelChunk) chunkaccess1; ++ if (ichunkaccess1 != null) { ++ this.storeInCache(k, ichunkaccess1, ChunkStatus.FULL); ++ if (ichunkaccess1 instanceof LevelChunk) { ++ return (LevelChunk) ichunkaccess1; + } + } + +@@ -204,19 +211,19 @@ + Arrays.fill(this.lastChunk, (Object) null); + } + +- public CompletableFuture> getChunkFuture(int i, int j, ChunkStatus chunkstatus, boolean flag) { ++ public CompletableFuture> getChunkFuture(int x, int y, ChunkStatus chunkStatus, boolean load) { + boolean flag1 = Thread.currentThread() == this.mainThread; + CompletableFuture completablefuture; + + if (flag1) { +- completablefuture = this.getChunkFutureMainThread(i, j, chunkstatus, flag); +- ServerChunkCache.MainThreadExecutor serverchunkcache_mainthreadexecutor = this.mainThreadProcessor; ++ completablefuture = this.getChunkFutureMainThread(x, y, chunkStatus, load); ++ ServerChunkCache.MainThreadExecutor chunkproviderserver_b = this.mainThreadProcessor; + + Objects.requireNonNull(completablefuture); +- serverchunkcache_mainthreadexecutor.managedBlock(completablefuture::isDone); ++ chunkproviderserver_b.managedBlock(completablefuture::isDone); + } else { + completablefuture = CompletableFuture.supplyAsync(() -> { +- return this.getChunkFutureMainThread(i, j, chunkstatus, flag); ++ return this.getChunkFutureMainThread(x, y, chunkStatus, load); + }, this.mainThreadProcessor).thenCompose((completablefuture1) -> { + return completablefuture1; + }); +@@ -225,58 +232,64 @@ + return completablefuture; + } + +- private CompletableFuture> getChunkFutureMainThread(int i, int j, ChunkStatus chunkstatus, boolean flag) { +- ChunkPos chunkpos = new ChunkPos(i, j); +- long k = chunkpos.toLong(); +- int l = ChunkLevel.byStatus(chunkstatus); +- ChunkHolder chunkholder = this.getVisibleChunkIfPresent(k); ++ private CompletableFuture> getChunkFutureMainThread(int x, int y, ChunkStatus chunkStatus, boolean load) { ++ ChunkPos chunkcoordintpair = new ChunkPos(x, y); ++ long k = chunkcoordintpair.toLong(); ++ int l = ChunkLevel.byStatus(chunkStatus); ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(k); + +- if (flag) { +- this.distanceManager.addTicket(TicketType.UNKNOWN, chunkpos, l, chunkpos); +- if (this.chunkAbsent(chunkholder, l)) { +- ProfilerFiller profilerfiller = this.level.getProfiler(); ++ // CraftBukkit start - don't add new ticket for currently unloading chunk ++ boolean currentlyUnloading = false; ++ if (playerchunk != null) { ++ FullChunkStatus oldChunkState = ChunkLevel.fullStatus(playerchunk.oldTicketLevel); ++ FullChunkStatus currentChunkState = ChunkLevel.fullStatus(playerchunk.getTicketLevel()); ++ currentlyUnloading = (oldChunkState.isOrAfter(FullChunkStatus.FULL) && !currentChunkState.isOrAfter(FullChunkStatus.FULL)); ++ } ++ if (load && !currentlyUnloading) { ++ // CraftBukkit end ++ this.distanceManager.addTicket(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); ++ if (this.chunkAbsent(playerchunk, l)) { ++ ProfilerFiller gameprofilerfiller = this.level.getProfiler(); + +- profilerfiller.push("chunkLoad"); ++ gameprofilerfiller.push("chunkLoad"); + this.runDistanceManagerUpdates(); +- chunkholder = this.getVisibleChunkIfPresent(k); +- profilerfiller.pop(); +- if (this.chunkAbsent(chunkholder, l)) { ++ playerchunk = this.getVisibleChunkIfPresent(k); ++ gameprofilerfiller.pop(); ++ if (this.chunkAbsent(playerchunk, l)) { + throw (IllegalStateException) Util.pauseInIde(new IllegalStateException("No chunk holder after ticket has been added")); + } + } + } + +- return this.chunkAbsent(chunkholder, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : chunkholder.getOrScheduleFuture(chunkstatus, this.chunkMap); ++ return this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(chunkStatus, this.chunkMap); + } + +- private boolean chunkAbsent(@Nullable ChunkHolder chunkholder, int i) { +- return chunkholder == null || chunkholder.getTicketLevel() > i; ++ private boolean chunkAbsent(@Nullable ChunkHolder chunkHolder, int status) { ++ return chunkHolder == null || chunkHolder.oldTicketLevel > status; // CraftBukkit using oldTicketLevel for isLoaded checks + } + + @Override +- @Override +- public boolean hasChunk(int i, int j) { +- ChunkHolder chunkholder = this.getVisibleChunkIfPresent((new ChunkPos(i, j)).toLong()); ++ public boolean hasChunk(int x, int z) { ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent((new ChunkPos(x, z)).toLong()); + int k = ChunkLevel.byStatus(ChunkStatus.FULL); + +- return !this.chunkAbsent(chunkholder, k); ++ return !this.chunkAbsent(playerchunk, k); + } + + @Nullable + @Override +- @Override +- public LightChunk getChunkForLighting(int i, int j) { +- long k = ChunkPos.asLong(i, j); +- ChunkHolder chunkholder = this.getVisibleChunkIfPresent(k); ++ public LightChunk getChunkForLighting(int chunkX, int chunkZ) { ++ long k = ChunkPos.asLong(chunkX, chunkZ); ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(k); + +- if (chunkholder == null) { ++ if (playerchunk == null) { + return null; + } else { + int l = ServerChunkCache.CHUNK_STATUSES.size() - 1; + + while (true) { + ChunkStatus chunkstatus = (ChunkStatus) ServerChunkCache.CHUNK_STATUSES.get(l); +- Optional optional = ((Either) chunkholder.getFutureIfPresentUnchecked(chunkstatus).getNow(ChunkHolder.UNLOADED_CHUNK)).left(); ++ Optional optional = ((Either) playerchunk.getFutureIfPresentUnchecked(chunkstatus).getNow(ChunkHolder.UNLOADED_CHUNK)).left(); + + if (optional.isPresent()) { + return (LightChunk) optional.get(); +@@ -292,7 +305,6 @@ + } + + @Override +- @Override + public Level getLevel() { + return this.level; + } +@@ -313,47 +325,65 @@ + } + } + +- public boolean isPositionTicking(long i) { +- ChunkHolder chunkholder = this.getVisibleChunkIfPresent(i); ++ public boolean isPositionTicking(long chunkPos) { ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(chunkPos); + +- if (chunkholder == null) { ++ if (playerchunk == null) { + return false; +- } else if (!this.level.shouldTickBlocksAt(i)) { ++ } else if (!this.level.shouldTickBlocksAt(chunkPos)) { + return false; + } else { +- Either either = (Either) chunkholder.getTickingChunkFuture().getNow((Object) null); ++ Either either = (Either) playerchunk.getTickingChunkFuture().getNow(null); // CraftBukkit - decompile error + + return either != null && either.left().isPresent(); + } + } + +- public void save(boolean flag) { ++ public void save(boolean flush) { + this.runDistanceManagerUpdates(); +- this.chunkMap.saveAllChunks(flag); ++ this.chunkMap.saveAllChunks(flush); + } + + @Override +- @Override + public void close() throws IOException { +- this.save(true); ++ // CraftBukkit start ++ close(true); ++ } ++ ++ public void close(boolean save) throws IOException { ++ if (save) { ++ this.save(true); ++ } ++ // CraftBukkit end + this.lightEngine.close(); + this.chunkMap.close(); + } + ++ // CraftBukkit start - modelled on below ++ public void purgeUnload() { ++ this.level.getProfiler().push("purge"); ++ this.distanceManager.purgeStaleTickets(); ++ this.runDistanceManagerUpdates(); ++ this.level.getProfiler().popPush("unload"); ++ this.chunkMap.tick(() -> true); ++ this.level.getProfiler().pop(); ++ this.clearCache(); ++ } ++ // CraftBukkit end ++ + @Override +- @Override +- public void tick(BooleanSupplier booleansupplier, boolean flag) { ++ public void tick(BooleanSupplier hasTimeLeft, boolean tickChunks) { + this.level.getProfiler().push("purge"); + this.distanceManager.purgeStaleTickets(); + this.runDistanceManagerUpdates(); + this.level.getProfiler().popPush("chunks"); +- if (flag) { ++ if (tickChunks) { + this.tickChunks(); + this.chunkMap.tick(); + } + + this.level.getProfiler().popPush("unload"); +- this.chunkMap.tick(booleansupplier); ++ this.chunkMap.tick(hasTimeLeft); + this.level.getProfiler().pop(); + this.clearCache(); + } +@@ -364,79 +394,78 @@ + + this.lastInhabitedUpdate = i; + if (!this.level.isDebug()) { +- ProfilerFiller profilerfiller = this.level.getProfiler(); ++ ProfilerFiller gameprofilerfiller = this.level.getProfiler(); + +- profilerfiller.push("pollingChunks"); +- profilerfiller.push("filteringLoadedChunks"); +- List list = Lists.newArrayListWithCapacity(this.chunkMap.size()); ++ gameprofilerfiller.push("pollingChunks"); ++ gameprofilerfiller.push("filteringLoadedChunks"); ++ List list = Lists.newArrayListWithCapacity(this.chunkMap.size()); + Iterator iterator = this.chunkMap.getChunks().iterator(); + + while (iterator.hasNext()) { +- ChunkHolder chunkholder = (ChunkHolder) iterator.next(); +- LevelChunk levelchunk = chunkholder.getTickingChunk(); ++ ChunkHolder playerchunk = (ChunkHolder) iterator.next(); ++ LevelChunk chunk = playerchunk.getTickingChunk(); + +- if (levelchunk != null) { +- list.add(new ServerChunkCache.ChunkAndHolder(levelchunk, chunkholder)); ++ if (chunk != null) { ++ list.add(new ServerChunkCache.a(chunk, playerchunk)); + } + } + + if (this.level.getServer().tickRateManager().runsNormally()) { +- profilerfiller.popPush("naturalSpawnCount"); ++ gameprofilerfiller.popPush("naturalSpawnCount"); + int k = this.distanceManager.getNaturalSpawnChunkCount(); +- NaturalSpawner.SpawnState naturalspawner_spawnstate = NaturalSpawner.createState(k, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap)); ++ NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(k, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap)); + +- this.lastSpawnState = naturalspawner_spawnstate; +- profilerfiller.popPush("spawnAndTick"); +- boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING); ++ this.lastSpawnState = spawnercreature_d; ++ gameprofilerfiller.popPush("spawnAndTick"); ++ boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit + + Util.shuffle(list, this.level.random); + int l = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); +- boolean flag1 = this.level.getLevelData().getGameTime() % 400L == 0L; ++ boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit + Iterator iterator1 = list.iterator(); + + while (iterator1.hasNext()) { +- ServerChunkCache.ChunkAndHolder serverchunkcache_chunkandholder = (ServerChunkCache.ChunkAndHolder) iterator1.next(); +- LevelChunk levelchunk1 = serverchunkcache_chunkandholder.chunk; +- ChunkPos chunkpos = levelchunk1.getPos(); ++ ServerChunkCache.a chunkproviderserver_a = (ServerChunkCache.a) iterator1.next(); ++ LevelChunk chunk1 = chunkproviderserver_a.chunk; ++ ChunkPos chunkcoordintpair = chunk1.getPos(); + +- if (this.level.isNaturalSpawningAllowed(chunkpos) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkpos)) { +- levelchunk1.incrementInhabitedTime(j); +- if (flag && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkpos)) { +- NaturalSpawner.spawnForChunk(this.level, levelchunk1, naturalspawner_spawnstate, this.spawnFriendlies, this.spawnEnemies, flag1); ++ if (this.level.isNaturalSpawningAllowed(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair)) { ++ chunk1.incrementInhabitedTime(j); ++ if (flag && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair)) { ++ NaturalSpawner.spawnForChunk(this.level, chunk1, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1); + } + +- if (this.level.shouldTickBlocksAt(chunkpos.toLong())) { +- this.level.tickChunk(levelchunk1, l); ++ if (this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) { ++ this.level.tickChunk(chunk1, l); + } + } + } + +- profilerfiller.popPush("customSpawners"); ++ gameprofilerfiller.popPush("customSpawners"); + if (flag) { + this.level.tickCustomSpawners(this.spawnEnemies, this.spawnFriendlies); + } + } + +- profilerfiller.popPush("broadcast"); +- list.forEach((serverchunkcache_chunkandholder1) -> { +- serverchunkcache_chunkandholder1.holder.broadcastChanges(serverchunkcache_chunkandholder1.chunk); ++ gameprofilerfiller.popPush("broadcast"); ++ list.forEach((chunkproviderserver_a1) -> { ++ chunkproviderserver_a1.holder.broadcastChanges(chunkproviderserver_a1.chunk); + }); +- profilerfiller.pop(); +- profilerfiller.pop(); ++ gameprofilerfiller.pop(); ++ gameprofilerfiller.pop(); + } + } + +- private void getFullChunk(long i, Consumer consumer) { +- ChunkHolder chunkholder = this.getVisibleChunkIfPresent(i); ++ private void getFullChunk(long chunkPos, Consumer consumer) { ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(chunkPos); + +- if (chunkholder != null) { +- ((Either) chunkholder.getFullChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left().ifPresent(consumer); ++ if (playerchunk != null) { ++ ((Either) playerchunk.getFullChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left().ifPresent(consumer); + } + + } + + @Override +- @Override + public String gatherStats() { + return Integer.toString(this.getLoadedChunksCount()); + } +@@ -459,52 +488,49 @@ + } + + @Override +- @Override + public int getLoadedChunksCount() { + return this.chunkMap.size(); + } + +- public void blockChanged(BlockPos blockpos) { +- int i = SectionPos.blockToSectionCoord(blockpos.getX()); +- int j = SectionPos.blockToSectionCoord(blockpos.getZ()); +- ChunkHolder chunkholder = this.getVisibleChunkIfPresent(ChunkPos.asLong(i, j)); ++ public void blockChanged(BlockPos pos) { ++ int i = SectionPos.blockToSectionCoord(pos.getX()); ++ int j = SectionPos.blockToSectionCoord(pos.getZ()); ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(ChunkPos.asLong(i, j)); + +- if (chunkholder != null) { +- chunkholder.blockChanged(blockpos); ++ if (playerchunk != null) { ++ playerchunk.blockChanged(pos); + } + + } + + @Override +- @Override +- public void onLightUpdate(LightLayer lightlayer, SectionPos sectionpos) { ++ public void onLightUpdate(EnumSkyBlock type, SectionPos pos) { + this.mainThreadProcessor.execute(() -> { +- ChunkHolder chunkholder = this.getVisibleChunkIfPresent(sectionpos.chunk().toLong()); ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos.chunk().toLong()); + +- if (chunkholder != null) { +- chunkholder.sectionLightChanged(lightlayer, sectionpos.y()); ++ if (playerchunk != null) { ++ playerchunk.sectionLightChanged(type, pos.y()); + } + + }); + } + +- public void addRegionTicket(TicketType tickettype, ChunkPos chunkpos, int i, T t0) { +- this.distanceManager.addRegionTicket(tickettype, chunkpos, i, t0); ++ public void addRegionTicket(TicketType type, ChunkPos pos, int distance, T value) { ++ this.distanceManager.addRegionTicket(type, pos, distance, value); + } + +- public void removeRegionTicket(TicketType tickettype, ChunkPos chunkpos, int i, T t0) { +- this.distanceManager.removeRegionTicket(tickettype, chunkpos, i, t0); ++ public void removeRegionTicket(TicketType type, ChunkPos pos, int distance, T value) { ++ this.distanceManager.removeRegionTicket(type, pos, distance, value); + } + + @Override +- @Override +- public void updateChunkForced(ChunkPos chunkpos, boolean flag) { +- this.distanceManager.updateChunkForced(chunkpos, flag); ++ public void updateChunkForced(ChunkPos pos, boolean add) { ++ this.distanceManager.updateChunkForced(pos, add); + } + +- public void move(ServerPlayer serverplayer) { +- if (!serverplayer.isRemoved()) { +- this.chunkMap.move(serverplayer); ++ public void move(ServerPlayer player) { ++ if (!player.isRemoved()) { ++ this.chunkMap.move(player); + } + + } +@@ -525,23 +551,22 @@ + this.chunkMap.broadcast(entity, packet); + } + +- public void setViewDistance(int i) { +- this.chunkMap.setServerViewDistance(i); ++ public void setViewDistance(int viewDistance) { ++ this.chunkMap.setServerViewDistance(viewDistance); + } + +- public void setSimulationDistance(int i) { +- this.distanceManager.updateSimulationDistance(i); ++ public void setSimulationDistance(int simulationDistance) { ++ this.distanceManager.updateSimulationDistance(simulationDistance); + } + + @Override +- @Override +- public void setSpawnSettings(boolean flag, boolean flag1) { +- this.spawnEnemies = flag; +- this.spawnFriendlies = flag1; ++ public void setSpawnSettings(boolean hostile, boolean peaceful) { ++ this.spawnEnemies = hostile; ++ this.spawnFriendlies = peaceful; + } + +- public String getChunkDebugData(ChunkPos chunkpos) { +- return this.chunkMap.getChunkDebugData(chunkpos); ++ public String getChunkDebugData(ChunkPos chunkPos) { ++ return this.chunkMap.getChunkDebugData(chunkPos); + } + + public DimensionDataStorage getDataStorage() { +@@ -568,53 +593,54 @@ + + private final class MainThreadExecutor extends BlockableEventLoop { + +- MainThreadExecutor(Level level) { +- super("Chunk source main thread executor for " + level.dimension().location()); ++ MainThreadExecutor(Level world) { ++ super("Chunk source main thread executor for " + world.dimension().location()); + } + + @Override +- @Override + protected Runnable wrapRunnable(Runnable runnable) { + return runnable; + } + + @Override +- @Override + protected boolean shouldRun(Runnable runnable) { + return true; + } + + @Override +- @Override + protected boolean scheduleExecutables() { + return true; + } + + @Override +- @Override + protected Thread getRunningThread() { + return ServerChunkCache.this.mainThread; + } + + @Override +- @Override +- protected void doRunTask(Runnable runnable) { ++ protected void doRunTask(Runnable task) { + ServerChunkCache.this.level.getProfiler().incrementCounter("runTask"); +- super.doRunTask(runnable); ++ super.doRunTask(task); + } + + @Override +- protected boolean pollTask() { ++ // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task ++ public boolean pollTask() { ++ try { + if (ServerChunkCache.this.runDistanceManagerUpdates()) { + return true; + } else { + ServerChunkCache.this.lightEngine.tryScheduleUpdate(); + return super.pollTask(); + } ++ } finally { ++ chunkMap.callbackExecutor.run(); + } ++ // CraftBukkit end ++ } + } + +- private static record ChunkAndHolder(LevelChunk chunk, ChunkHolder holder) { ++ private static record a(LevelChunk chunk, ChunkHolder holder) { + + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/level/ServerEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/level/ServerEntity.java.patch new file mode 100644 index 0000000000..7af7213a79 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/level/ServerEntity.java.patch @@ -0,0 +1,306 @@ +--- a/net/minecraft/server/level/ServerEntity.java ++++ b/net/minecraft/server/level/ServerEntity.java +@@ -28,7 +28,6 @@ + import net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket; + import net.minecraft.network.protocol.game.VecDeltaCodec; + import net.minecraft.network.syncher.SynchedEntityData; +-import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.LivingEntity; +@@ -42,6 +41,13 @@ + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.server.network.ServerPlayerConnection; ++import net.minecraft.util.Mth; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerVelocityEvent; ++// CraftBukkit end ++ + public class ServerEntity { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -66,11 +72,15 @@ + private boolean wasOnGround; + @Nullable + private List> trackedDataValues; ++ // CraftBukkit start ++ private final Set trackedPlayers; + +- public ServerEntity(ServerLevel serverlevel, Entity entity, int i, boolean flag, Consumer> consumer) { ++ public ServerEntity(ServerLevel worldserver, Entity entity, int i, boolean flag, Consumer> consumer, Set trackedPlayers) { ++ this.trackedPlayers = trackedPlayers; ++ // CraftBukkit end + this.ap = Vec3.ZERO; + this.lastPassengers = Collections.emptyList(); +- this.level = serverlevel; ++ this.level = worldserver; + this.broadcast = consumer; + this.entity = entity; + this.updateInterval = i; +@@ -87,12 +97,12 @@ + List list = this.entity.getPassengers(); + + if (!list.equals(this.lastPassengers)) { +- this.broadcast.accept(new ClientboundSetPassengersPacket(this.entity)); ++ this.broadcastAndSend(new ClientboundSetPassengersPacket(this.entity)); // CraftBukkit + removedPassengers(list, this.lastPassengers).forEach((entity) -> { + if (entity instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) entity; ++ ServerPlayer entityplayer = (ServerPlayer) entity; + +- serverplayer.connection.teleport(serverplayer.getX(), serverplayer.getY(), serverplayer.getZ(), serverplayer.getYRot(), serverplayer.getXRot()); ++ entityplayer.connection.teleport(entityplayer.getX(), entityplayer.getY(), entityplayer.getZ(), entityplayer.getYRot(), entityplayer.getXRot()); + } + + }); +@@ -102,26 +112,26 @@ + Entity entity = this.entity; + + if (entity instanceof ItemFrame) { +- ItemFrame itemframe = (ItemFrame) entity; ++ ItemFrame entityitemframe = (ItemFrame) entity; + +- if (this.tickCount % 10 == 0) { +- ItemStack itemstack = itemframe.getItem(); ++ if (true || this.tickCount % 10 == 0) { // CraftBukkit - Moved below, should always enter this block ++ ItemStack itemstack = entityitemframe.getItem(); + +- if (itemstack.getItem() instanceof MapItem) { ++ if (this.tickCount % 10 == 0 && itemstack.getItem() instanceof MapItem) { // CraftBukkit - Moved this.tickCounter % 10 logic here so item frames do not enter the other blocks + Integer integer = MapItem.getMapId(itemstack); +- MapItemSavedData mapitemsaveddata = MapItem.getSavedData(integer, this.level); ++ MapItemSavedData worldmap = MapItem.getSavedData(integer, this.level); + +- if (mapitemsaveddata != null) { +- Iterator iterator = this.level.players().iterator(); ++ if (worldmap != null) { ++ Iterator iterator = this.trackedPlayers.iterator(); // CraftBukkit + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = iterator.next().getPlayer(); // CraftBukkit + +- mapitemsaveddata.tickCarriedBy(serverplayer, itemstack); +- Packet packet = mapitemsaveddata.getUpdatePacket(integer, serverplayer); ++ worldmap.tickCarriedBy(entityplayer, itemstack); ++ Packet packet = worldmap.getUpdatePacket(integer, entityplayer); + + if (packet != null) { +- serverplayer.connection.send(packet); ++ entityplayer.connection.send(packet); + } + } + } +@@ -153,8 +163,8 @@ + ++this.teleportDelay; + i = Mth.floor(this.entity.getYRot() * 256.0F / 360.0F); + j = Mth.floor(this.entity.getXRot() * 256.0F / 360.0F); +- Vec3 vec3 = this.entity.trackingPosition(); +- boolean flag1 = this.positionCodec.delta(vec3).lengthSqr() >= 7.62939453125E-6D; ++ Vec3 vec3d = this.entity.trackingPosition(); ++ boolean flag1 = this.positionCodec.delta(vec3d).lengthSqr() >= 7.62939453125E-6D; + Packet packet1 = null; + boolean flag2 = flag1 || this.tickCount % 60 == 0; + boolean flag3 = Math.abs(i - this.yRotp) >= 1 || Math.abs(j - this.xRotp) >= 1; +@@ -162,9 +172,9 @@ + boolean flag5 = false; + + if (this.tickCount > 0 || this.entity instanceof AbstractArrow) { +- long k = this.positionCodec.encodeX(vec3); +- long l = this.positionCodec.encodeY(vec3); +- long i1 = this.positionCodec.encodeZ(vec3); ++ long k = this.positionCodec.encodeX(vec3d); ++ long l = this.positionCodec.encodeY(vec3d); ++ long i1 = this.positionCodec.encodeZ(vec3d); + boolean flag6 = k < -32768L || k > 32767L || l < -32768L || l > 32767L || i1 < -32768L || i1 > 32767L; + + if (!flag6 && this.teleportDelay <= 400 && !this.wasRiding && this.wasOnGround == this.entity.onGround()) { +@@ -191,11 +201,11 @@ + } + + if ((this.trackDelta || this.entity.hasImpulse || this.entity instanceof LivingEntity && ((LivingEntity) this.entity).isFallFlying()) && this.tickCount > 0) { +- Vec3 vec31 = this.entity.getDeltaMovement(); +- double d0 = vec31.distanceToSqr(this.ap); ++ Vec3 vec3d1 = this.entity.getDeltaMovement(); ++ double d0 = vec3d1.distanceToSqr(this.ap); + +- if (d0 > 1.0E-7D || d0 > 0.0D && vec31.lengthSqr() == 0.0D) { +- this.ap = vec31; ++ if (d0 > 1.0E-7D || d0 > 0.0D && vec3d1.lengthSqr() == 0.0D) { ++ this.ap = vec3d1; + this.broadcast.accept(new ClientboundSetEntityMotionPacket(this.entity.getId(), this.ap)); + } + } +@@ -206,7 +216,7 @@ + + this.sendDirtyEntityData(); + if (flag4) { +- this.positionCodec.setBase(vec3); ++ this.positionCodec.setBase(vec3d); + } + + if (flag5) { +@@ -228,35 +238,58 @@ + + ++this.tickCount; + if (this.entity.hurtMarked) { +- this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity)); ++ // CraftBukkit start - Create PlayerVelocity event ++ boolean cancelled = false; ++ ++ if (this.entity instanceof ServerPlayer) { ++ Player player = (Player) this.entity.getBukkitEntity(); ++ org.bukkit.util.Vector velocity = player.getVelocity(); ++ ++ PlayerVelocityEvent event = new PlayerVelocityEvent(player, velocity.clone()); ++ this.entity.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ cancelled = true; ++ } else if (!velocity.equals(event.getVelocity())) { ++ player.setVelocity(event.getVelocity()); ++ } ++ } ++ ++ if (!cancelled) { ++ this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity)); ++ } ++ // CraftBukkit end + this.entity.hurtMarked = false; + } + + } + +- private static Stream removedPassengers(List list, List list1) { +- return list1.stream().filter((entity) -> { +- return !list.contains(entity); ++ private static Stream removedPassengers(List initialPassengers, List currentPassengers) { ++ return currentPassengers.stream().filter((entity) -> { ++ return !initialPassengers.contains(entity); + }); + } + +- public void removePairing(ServerPlayer serverplayer) { +- this.entity.stopSeenByPlayer(serverplayer); +- serverplayer.connection.send(new ClientboundRemoveEntitiesPacket(new int[]{this.entity.getId()})); ++ public void removePairing(ServerPlayer player) { ++ this.entity.stopSeenByPlayer(player); ++ player.connection.send(new ClientboundRemoveEntitiesPacket(new int[]{this.entity.getId()})); + } + +- public void addPairing(ServerPlayer serverplayer) { ++ public void addPairing(ServerPlayer player) { + List> list = new ArrayList(); + + Objects.requireNonNull(list); +- this.sendPairingData(serverplayer, list::add); +- serverplayer.connection.send(new ClientboundBundlePacket(list)); +- this.entity.startSeenByPlayer(serverplayer); ++ this.sendPairingData(player, list::add); ++ player.connection.send(new ClientboundBundlePacket(list)); ++ this.entity.startSeenByPlayer(player); + } + +- public void sendPairingData(ServerPlayer serverplayer, Consumer> consumer) { ++ public void sendPairingData(ServerPlayer player, Consumer> consumer) { + if (this.entity.isRemoved()) { +- ServerEntity.LOGGER.warn("Fetching packet for removed entity {}", this.entity); ++ // CraftBukkit start - Remove useless error spam, just return ++ // EntityTrackerEntry.LOGGER.warn("Fetching packet for removed entity {}", this.entity); ++ return; ++ // CraftBukkit end + } + + Packet packet = this.entity.getAddEntityPacket(); +@@ -272,6 +305,12 @@ + if (this.entity instanceof LivingEntity) { + Collection collection = ((LivingEntity) this.entity).getAttributes().getSyncableAttributes(); + ++ // CraftBukkit start - If sending own attributes send scaled health instead of current maximum health ++ if (this.entity.getId() == player.getId()) { ++ ((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(collection, false); ++ } ++ // CraftBukkit end ++ + if (!collection.isEmpty()) { + consumer.accept(new ClientboundUpdateAttributesPacket(this.entity.getId(), collection)); + } +@@ -288,23 +327,30 @@ + + if (this.entity instanceof LivingEntity) { + List> list = Lists.newArrayList(); +- EquipmentSlot[] aequipmentslot = EquipmentSlot.values(); +- int i = aequipmentslot.length; ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ int i = aenumitemslot.length; + + for (int j = 0; j < i; ++j) { +- EquipmentSlot equipmentslot = aequipmentslot[j]; +- ItemStack itemstack = ((LivingEntity) this.entity).getItemBySlot(equipmentslot); ++ EquipmentSlot enumitemslot = aenumitemslot[j]; ++ ItemStack itemstack = ((LivingEntity) this.entity).getItemBySlot(enumitemslot); + + if (!itemstack.isEmpty()) { +- list.add(Pair.of(equipmentslot, itemstack.copy())); ++ list.add(Pair.of(enumitemslot, itemstack.copy())); + } + } + + if (!list.isEmpty()) { + consumer.accept(new ClientboundSetEquipmentPacket(this.entity.getId(), list)); + } ++ ((LivingEntity) this.entity).detectEquipmentUpdatesPublic(); // CraftBukkit - SPIGOT-3789: sync again immediately after sending + } + ++ // CraftBukkit start - MC-109346: Fix for nonsensical head yaw ++ if (this.entity instanceof ServerPlayer) { ++ consumer.accept(new ClientboundRotateHeadPacket(this.entity, (byte) Mth.floor(this.entity.getYHeadRot() * 256.0F / 360.0F))); ++ } ++ // CraftBukkit end ++ + if (!this.entity.getPassengers().isEmpty()) { + consumer.accept(new ClientboundSetPassengersPacket(this.entity)); + } +@@ -316,21 +362,21 @@ + Entity entity = this.entity; + + if (entity instanceof Mob) { +- Mob mob = (Mob) entity; ++ Mob entityinsentient = (Mob) entity; + +- if (mob.isLeashed()) { +- consumer.accept(new ClientboundSetEntityLinkPacket(mob, mob.getLeashHolder())); ++ if (entityinsentient.isLeashed()) { ++ consumer.accept(new ClientboundSetEntityLinkPacket(entityinsentient, entityinsentient.getLeashHolder())); + } + } + + } + + private void sendDirtyEntityData() { +- SynchedEntityData synchedentitydata = this.entity.getEntityData(); +- List> list = synchedentitydata.packDirty(); ++ SynchedEntityData datawatcher = this.entity.getEntityData(); ++ List> list = datawatcher.packDirty(); + + if (list != null) { +- this.trackedDataValues = synchedentitydata.getNonDefaultValues(); ++ this.trackedDataValues = datawatcher.getNonDefaultValues(); + this.broadcastAndSend(new ClientboundSetEntityDataPacket(this.entity.getId(), list)); + } + +@@ -338,6 +384,11 @@ + Set set = ((LivingEntity) this.entity).getAttributes().getDirtyAttributes(); + + if (!set.isEmpty()) { ++ // CraftBukkit start - Send scaled max health ++ if (this.entity instanceof ServerPlayer) { ++ ((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(set, false); ++ } ++ // CraftBukkit end + this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), set)); + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/level/ServerLevel.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/level/ServerLevel.java.patch new file mode 100644 index 0000000000..dc29b1cb79 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/level/ServerLevel.java.patch @@ -0,0 +1,2159 @@ +--- a/net/minecraft/server/level/ServerLevel.java ++++ b/net/minecraft/server/level/ServerLevel.java +@@ -44,7 +44,6 @@ + import net.minecraft.core.Direction; + import net.minecraft.core.Holder; + import net.minecraft.core.HolderSet; +-import net.minecraft.core.RegistryAccess; + import net.minecraft.core.SectionPos; + import net.minecraft.core.particles.ParticleOptions; + import net.minecraft.core.registries.BuiltInRegistries; +@@ -57,7 +56,6 @@ + import net.minecraft.network.protocol.game.ClientboundDamageEventPacket; + import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; + import net.minecraft.network.protocol.game.ClientboundExplodePacket; +-import net.minecraft.network.protocol.game.ClientboundGameEventPacket; + import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; + import net.minecraft.network.protocol.game.ClientboundLevelParticlesPacket; + import net.minecraft.network.protocol.game.ClientboundSetDefaultSpawnPositionPacket; +@@ -103,7 +101,7 @@ + import net.minecraft.world.entity.animal.horse.SkeletonHorse; + import net.minecraft.world.entity.boss.EnderDragonPart; + import net.minecraft.world.entity.boss.enderdragon.EnderDragon; +-import net.minecraft.world.entity.npc.Npc; ++import net.minecraft.world.entity.npc.NPC; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.raid.Raid; + import net.minecraft.world.entity.raid.Raids; +@@ -121,11 +119,12 @@ + import net.minecraft.world.level.StructureManager; + import net.minecraft.world.level.WorldGenLevel; + import net.minecraft.world.level.biome.Biome; ++import net.minecraft.world.level.biome.BiomeSource; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.SnowLayerBlock; + import net.minecraft.world.level.block.entity.TickingBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.chunk.LevelChunk; +@@ -143,7 +142,9 @@ + import net.minecraft.world.level.gameevent.DynamicGameEventListener; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.gameevent.GameEventDispatcher; ++import net.minecraft.world.level.levelgen.FlatLevelSource; + import net.minecraft.world.level.levelgen.Heightmap; ++import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; + import net.minecraft.world.level.levelgen.structure.BoundingBox; + import net.minecraft.world.level.levelgen.structure.Structure; + import net.minecraft.world.level.levelgen.structure.StructureCheck; +@@ -155,7 +156,7 @@ + import net.minecraft.world.level.saveddata.maps.MapItemSavedData; + import net.minecraft.world.level.storage.DimensionDataStorage; + import net.minecraft.world.level.storage.LevelStorageSource; +-import net.minecraft.world.level.storage.ServerLevelData; ++import net.minecraft.world.level.storage.PrimaryLevelData; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.BooleanOp; +@@ -163,6 +164,19 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.ticks.LevelTicks; + import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.WeatherType; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.generator.CustomWorldChunkManager; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.craftbukkit.util.WorldUUID; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.server.MapInitializeEvent; ++import org.bukkit.event.weather.LightningStrikeEvent; ++import org.bukkit.event.world.GenericGameEvent; ++import org.bukkit.event.world.TimeSkipEvent; ++// CraftBukkit end + + public class ServerLevel extends Level implements WorldGenLevel { + +@@ -177,9 +191,9 @@ + final List players; + private final ServerChunkCache chunkSource; + private final MinecraftServer server; +- private final ServerLevelData serverLevelData; ++ public final PrimaryLevelData serverLevelData; // CraftBukkit - type + final EntityTickList entityTickList; +- private final PersistentEntitySectionManager entityManager; ++ public final PersistentEntitySectionManager entityManager; + private final GameEventDispatcher gameEventDispatcher; + public boolean noSave; + private final SleepStatus sleepStatus; +@@ -202,12 +216,30 @@ + private final boolean tickTime; + private final RandomSequences randomSequences; + +- public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess, ServerLevelData serverleveldata, ResourceKey resourcekey, LevelStem levelstem, ChunkProgressListener chunkprogresslistener, boolean flag, long i, List list, boolean flag1, @Nullable RandomSequences randomsequences) { +- RegistryAccess.Frozen registryaccess_frozen = minecraftserver.registryAccess(); +- Holder holder = levelstem.type(); ++ // CraftBukkit start ++ public final LevelStorageSource.LevelStorageAccess convertable; ++ public final UUID uuid; + +- Objects.requireNonNull(minecraftserver); +- super(serverleveldata, resourcekey, registryaccess_frozen, holder, minecraftserver::getProfiler, false, flag, i, minecraftserver.getMaxChainedNeighborUpdates()); ++ public LevelChunk getChunkIfLoaded(int x, int z) { ++ return this.chunkSource.getChunk(x, z, false); ++ } ++ ++ @Override ++ public ResourceKey getTypeKey() { ++ return convertable.dimensionType; ++ } ++ ++ // Add env and gen to constructor, IWorldDataServer -> WorldDataServer ++ public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List list, boolean flag1, @Nullable RandomSequences randomsequences, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) { ++ // IRegistryCustom.Dimension iregistrycustom_dimension = minecraftserver.registryAccess(); // CraftBukkit - decompile error ++ // Holder holder = worlddimension.type(); // CraftBukkit - decompile error ++ ++ // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error ++ super(iworlddataserver, resourcekey, minecraftserver.registryAccess(), worlddimension.type(), minecraftserver::getProfiler, false, flag, i, minecraftserver.getMaxChainedNeighborUpdates(), gen, biomeProvider, env); ++ this.pvpMode = minecraftserver.isPvpAllowed(); ++ convertable = convertable_conversionsession; ++ uuid = WorldUUID.getUUID(convertable_conversionsession.levelDirectory.path().toFile()); ++ // CraftBukkit end + this.players = Lists.newArrayList(); + this.entityTickList = new EntityTickList(); + this.blockTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded, this.getProfilerSupplier()); +@@ -219,20 +251,36 @@ + this.tickTime = flag1; + this.server = minecraftserver; + this.customSpawners = list; +- this.serverLevelData = serverleveldata; +- ChunkGenerator chunkgenerator = levelstem.generator(); ++ this.serverLevelData = iworlddataserver; ++ ChunkGenerator chunkgenerator = worlddimension.generator(); ++ // CraftBukkit start ++ serverLevelData.setWorld(this); ++ ++ if (biomeProvider != null) { ++ BiomeSource worldChunkManager = new CustomWorldChunkManager(getWorld(), biomeProvider, server.registryAccess().registryOrThrow(Registries.BIOME)); ++ if (chunkgenerator instanceof NoiseBasedChunkGenerator cga) { ++ chunkgenerator = new NoiseBasedChunkGenerator(worldChunkManager, cga.settings); ++ } else if (chunkgenerator instanceof FlatLevelSource cpf) { ++ chunkgenerator = new FlatLevelSource(cpf.settings(), worldChunkManager); ++ } ++ } ++ ++ if (gen != null) { ++ chunkgenerator = new org.bukkit.craftbukkit.generator.CustomChunkGenerator(this, chunkgenerator, gen); ++ } ++ // CraftBukkit end + boolean flag2 = minecraftserver.forceSynchronousWrites(); + DataFixer datafixer = minecraftserver.getFixerUpper(); +- EntityPersistentStorage entitypersistentstorage = new EntityStorage(this, levelstoragesource_levelstorageaccess.getDimensionPath(resourcekey).resolve("entities"), datafixer, flag2, minecraftserver); ++ EntityPersistentStorage entitypersistentstorage = new EntityStorage(this, convertable_conversionsession.getDimensionPath(resourcekey).resolve("entities"), datafixer, flag2, minecraftserver); + +- this.entityManager = new PersistentEntitySectionManager<>(Entity.class, new ServerLevel.EntityCallbacks(), entitypersistentstorage); ++ this.entityManager = new PersistentEntitySectionManager<>(Entity.class, new ServerLevel.a(), entitypersistentstorage); + StructureTemplateManager structuretemplatemanager = minecraftserver.getStructureManager(); + int j = minecraftserver.getPlayerList().getViewDistance(); + int k = minecraftserver.getPlayerList().getSimulationDistance(); + PersistentEntitySectionManager persistententitysectionmanager = this.entityManager; + + Objects.requireNonNull(this.entityManager); +- this.chunkSource = new ServerChunkCache(this, levelstoragesource_levelstorageaccess, datafixer, structuretemplatemanager, executor, chunkgenerator, j, k, flag2, chunkprogresslistener, persistententitysectionmanager::updateChunkStatus, () -> { ++ this.chunkSource = new ServerChunkCache(this, convertable_conversionsession, datafixer, structuretemplatemanager, executor, chunkgenerator, j, k, flag2, worldloadlistener, persistententitysectionmanager::updateChunkStatus, () -> { + return minecraftserver.overworld().getDataStorage(); + }); + this.chunkSource.getGeneratorState().ensureStructuresGenerated(); +@@ -242,15 +290,15 @@ + this.getWorldBorder().setAbsoluteMaxSize(minecraftserver.getAbsoluteMaxWorldSize()); + this.raids = (Raids) this.getDataStorage().computeIfAbsent(Raids.factory(this), Raids.getFileId(this.dimensionTypeRegistration())); + if (!minecraftserver.isSingleplayer()) { +- serverleveldata.setGameType(minecraftserver.getDefaultGameType()); ++ iworlddataserver.setGameType(minecraftserver.getDefaultGameType()); + } + + long l = minecraftserver.getWorldData().worldGenOptions().seed(); + + this.structureCheck = new StructureCheck(this.chunkSource.chunkScanner(), this.registryAccess(), minecraftserver.getStructureManager(), resourcekey, chunkgenerator, this.chunkSource.randomState(), this, chunkgenerator.getBiomeSource(), l, datafixer); +- this.structureManager = new StructureManager(this, minecraftserver.getWorldData().worldGenOptions(), this.structureCheck); +- if (this.dimension() == Level.END && this.dimensionTypeRegistration().is(BuiltinDimensionTypes.END)) { +- this.dragonFight = new EndDragonFight(this, l, minecraftserver.getWorldData().endDragonFightData()); ++ this.structureManager = new StructureManager(this, this.serverLevelData.worldGenOptions(), structureCheck); // CraftBukkit ++ if ((this.dimension() == Level.END && this.dimensionTypeRegistration().is(BuiltinDimensionTypes.END)) || env == org.bukkit.World.Environment.THE_END) { // CraftBukkit - Allow to create EnderDragonBattle in default and custom END ++ this.dragonFight = new EndDragonFight(this, this.serverLevelData.worldGenOptions().seed(), this.serverLevelData.endDragonFightData()); // CraftBukkit + } else { + this.dragonFight = null; + } +@@ -260,44 +308,44 @@ + this.randomSequences = (RandomSequences) Objects.requireNonNullElseGet(randomsequences, () -> { + return (RandomSequences) this.getDataStorage().computeIfAbsent(RandomSequences.factory(l), "random_sequences"); + }); ++ this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit + } + + /** @deprecated */ + @Deprecated + @VisibleForTesting +- public void setDragonFight(@Nullable EndDragonFight enddragonfight) { +- this.dragonFight = enddragonfight; ++ public void setDragonFight(@Nullable EndDragonFight dragonFight) { ++ this.dragonFight = dragonFight; + } + +- public void setWeatherParameters(int i, int j, boolean flag, boolean flag1) { +- this.serverLevelData.setClearWeatherTime(i); +- this.serverLevelData.setRainTime(j); +- this.serverLevelData.setThunderTime(j); +- this.serverLevelData.setRaining(flag); +- this.serverLevelData.setThundering(flag1); ++ public void setWeatherParameters(int clearTime, int weatherTime, boolean isRaining, boolean isThundering) { ++ this.serverLevelData.setClearWeatherTime(clearTime); ++ this.serverLevelData.setRainTime(weatherTime); ++ this.serverLevelData.setThunderTime(weatherTime); ++ this.serverLevelData.setRaining(isRaining); ++ this.serverLevelData.setThundering(isThundering); + } + + @Override +- @Override +- public Holder getUncachedNoiseBiome(int i, int j, int k) { +- return this.getChunkSource().getGenerator().getBiomeSource().getNoiseBiome(i, j, k, this.getChunkSource().randomState().sampler()); ++ public Holder getUncachedNoiseBiome(int x, int y, int z) { ++ return this.getChunkSource().getGenerator().getBiomeSource().getNoiseBiome(x, y, z, this.getChunkSource().randomState().sampler()); + } + + public StructureManager structureManager() { + return this.structureManager; + } + +- public void tick(BooleanSupplier booleansupplier) { +- ProfilerFiller profilerfiller = this.getProfiler(); ++ public void tick(BooleanSupplier hasTimeLeft) { ++ ProfilerFiller gameprofilerfiller = this.getProfiler(); + + this.handlingTick = true; + TickRateManager tickratemanager = this.tickRateManager(); + boolean flag = tickratemanager.runsNormally(); + + if (flag) { +- profilerfiller.push("world border"); ++ gameprofilerfiller.push("world border"); + this.getWorldBorder().tick(); +- profilerfiller.popPush("weather"); ++ gameprofilerfiller.popPush("weather"); + this.advanceWeatherCycle(); + } + +@@ -305,12 +353,20 @@ + long j; + + if (this.sleepStatus.areEnoughSleeping(i) && this.sleepStatus.areEnoughDeepSleeping(i, this.players)) { ++ // CraftBukkit start ++ j = this.levelData.getDayTime() + 24000L; ++ TimeSkipEvent event = new TimeSkipEvent(this.getWorld(), TimeSkipEvent.SkipReason.NIGHT_SKIP, (j - j % 24000L) - this.getDayTime()); + if (this.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { +- j = this.levelData.getDayTime() + 24000L; +- this.setDayTime(j - j % 24000L); ++ getCraftServer().getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ this.setDayTime(this.getDayTime() + event.getSkipAmount()); ++ } + } + +- this.wakeUpAllPlayers(); ++ if (!event.isCancelled()) { ++ this.wakeUpAllPlayers(); ++ } ++ // CraftBukkit end + if (this.getGameRules().getBoolean(GameRules.RULE_WEATHER_CYCLE) && this.isRaining()) { + this.resetWeatherCycle(); + } +@@ -321,52 +377,52 @@ + this.tickTime(); + } + +- profilerfiller.popPush("tickPending"); ++ gameprofilerfiller.popPush("tickPending"); + if (!this.isDebug() && flag) { + j = this.getGameTime(); +- profilerfiller.push("blockTicks"); ++ gameprofilerfiller.push("blockTicks"); + this.blockTicks.tick(j, 65536, this::tickBlock); +- profilerfiller.popPush("fluidTicks"); ++ gameprofilerfiller.popPush("fluidTicks"); + this.fluidTicks.tick(j, 65536, this::tickFluid); +- profilerfiller.pop(); ++ gameprofilerfiller.pop(); + } + +- profilerfiller.popPush("raid"); ++ gameprofilerfiller.popPush("raid"); + if (flag) { + this.raids.tick(); + } + +- profilerfiller.popPush("chunkSource"); +- this.getChunkSource().tick(booleansupplier, true); +- profilerfiller.popPush("blockEvents"); ++ gameprofilerfiller.popPush("chunkSource"); ++ this.getChunkSource().tick(hasTimeLeft, true); ++ gameprofilerfiller.popPush("blockEvents"); + if (flag) { + this.runBlockEvents(); + } + + this.handlingTick = false; +- profilerfiller.pop(); +- boolean flag1 = !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); ++ gameprofilerfiller.pop(); ++ boolean flag1 = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players + + if (flag1) { + this.resetEmptyTime(); + } + + if (flag1 || this.emptyTime++ < 300) { +- profilerfiller.push("entities"); ++ gameprofilerfiller.push("entities"); + if (this.dragonFight != null && flag) { +- profilerfiller.push("dragonFight"); ++ gameprofilerfiller.push("dragonFight"); + this.dragonFight.tick(); +- profilerfiller.pop(); ++ gameprofilerfiller.pop(); + } + + this.entityTickList.forEach((entity) -> { + if (!entity.isRemoved()) { +- if (this.shouldDiscardEntity(entity)) { ++ if (false && this.shouldDiscardEntity(entity)) { // CraftBukkit - We prevent spawning in general, so this butchering is not needed + entity.discard(); + } else if (!tickratemanager.isEntityFrozen(entity)) { +- profilerfiller.push("checkDespawn"); ++ gameprofilerfiller.push("checkDespawn"); + entity.checkDespawn(); +- profilerfiller.pop(); ++ gameprofilerfiller.pop(); + if (this.chunkSource.chunkMap.getDistanceManager().inEntityTickingRange(entity.chunkPosition().toLong())) { + Entity entity1 = entity.getVehicle(); + +@@ -378,26 +434,25 @@ + entity.stopRiding(); + } + +- profilerfiller.push("tick"); ++ gameprofilerfiller.push("tick"); + this.guardEntityTick(this::tickNonPassenger, entity); +- profilerfiller.pop(); ++ gameprofilerfiller.pop(); + } + } + } + }); +- profilerfiller.pop(); ++ gameprofilerfiller.pop(); + this.tickBlockEntities(); + } + +- profilerfiller.push("entityManagement"); ++ gameprofilerfiller.push("entityManagement"); + this.entityManager.tick(); +- profilerfiller.pop(); ++ gameprofilerfiller.pop(); + } + + @Override +- @Override +- public boolean shouldTickBlocksAt(long i) { +- return this.chunkSource.chunkMap.getDistanceManager().inBlockTickingRange(i); ++ public boolean shouldTickBlocksAt(long chunkPos) { ++ return this.chunkSource.chunkMap.getDistanceManager().inBlockTickingRange(chunkPos); + } + + protected void tickTime() { +@@ -413,185 +468,185 @@ + } + } + +- public void setDayTime(long i) { +- this.serverLevelData.setDayTime(i); ++ public void setDayTime(long time) { ++ this.serverLevelData.setDayTime(time); + } + +- public void tickCustomSpawners(boolean flag, boolean flag1) { ++ public void tickCustomSpawners(boolean spawnEnemies, boolean spawnFriendlies) { + Iterator iterator = this.customSpawners.iterator(); + + while (iterator.hasNext()) { +- CustomSpawner customspawner = (CustomSpawner) iterator.next(); ++ CustomSpawner mobspawner = (CustomSpawner) iterator.next(); + +- customspawner.tick(this, flag, flag1); ++ mobspawner.tick(this, spawnEnemies, spawnFriendlies); + } + + } + + private boolean shouldDiscardEntity(Entity entity) { +- return !this.server.isSpawningAnimals() && (entity instanceof Animal || entity instanceof WaterAnimal) ? true : !this.server.areNpcsEnabled() && entity instanceof Npc; ++ return !this.server.isSpawningAnimals() && (entity instanceof Animal || entity instanceof WaterAnimal) ? true : !this.server.areNpcsEnabled() && entity instanceof NPC; + } + + private void wakeUpAllPlayers() { + this.sleepStatus.removeAllSleepers(); +- ((List) this.players.stream().filter(LivingEntity::isSleeping).collect(Collectors.toList())).forEach((serverplayer) -> { +- serverplayer.stopSleepInBed(false, false); ++ (this.players.stream().filter(LivingEntity::isSleeping).collect(Collectors.toList())).forEach((entityplayer) -> { // CraftBukkit - decompile error ++ entityplayer.stopSleepInBed(false, false); + }); + } + +- public void tickChunk(LevelChunk levelchunk, int i) { +- ChunkPos chunkpos = levelchunk.getPos(); ++ public void tickChunk(LevelChunk chunk, int randomTickSpeed) { ++ ChunkPos chunkcoordintpair = chunk.getPos(); + boolean flag = this.isRaining(); +- int j = chunkpos.getMinBlockX(); +- int k = chunkpos.getMinBlockZ(); +- ProfilerFiller profilerfiller = this.getProfiler(); ++ int j = chunkcoordintpair.getMinBlockX(); ++ int k = chunkcoordintpair.getMinBlockZ(); ++ ProfilerFiller gameprofilerfiller = this.getProfiler(); + +- profilerfiller.push("thunder"); ++ gameprofilerfiller.push("thunder"); + if (flag && this.isThundering() && this.random.nextInt(100000) == 0) { +- BlockPos blockpos = this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15)); ++ BlockPos blockposition = this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15)); + +- if (this.isRainingAt(blockpos)) { +- DifficultyInstance difficultyinstance = this.getCurrentDifficultyAt(blockpos); +- boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultyinstance.getEffectiveDifficulty() * 0.01D && !this.getBlockState(blockpos.below()).is(Blocks.LIGHTNING_ROD); ++ if (this.isRainingAt(blockposition)) { ++ DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); ++ boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * 0.01D && !this.getBlockState(blockposition.below()).is(Blocks.LIGHTNING_ROD); + + if (flag1) { +- SkeletonHorse skeletonhorse = (SkeletonHorse) EntityType.SKELETON_HORSE.create(this); ++ SkeletonHorse entityhorseskeleton = (SkeletonHorse) EntityType.SKELETON_HORSE.create(this); + +- if (skeletonhorse != null) { +- skeletonhorse.setTrap(true); +- skeletonhorse.setAge(0); +- skeletonhorse.setPos((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ()); +- this.addFreshEntity(skeletonhorse); ++ if (entityhorseskeleton != null) { ++ entityhorseskeleton.setTrap(true); ++ entityhorseskeleton.setAge(0); ++ entityhorseskeleton.setPos((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()); ++ this.addFreshEntity(entityhorseskeleton, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); // CraftBukkit + } + } + +- LightningBolt lightningbolt = (LightningBolt) EntityType.LIGHTNING_BOLT.create(this); ++ LightningBolt entitylightning = (LightningBolt) EntityType.LIGHTNING_BOLT.create(this); + +- if (lightningbolt != null) { +- lightningbolt.moveTo(Vec3.atBottomCenterOf(blockpos)); +- lightningbolt.setVisualOnly(flag1); +- this.addFreshEntity(lightningbolt); ++ if (entitylightning != null) { ++ entitylightning.moveTo(Vec3.atBottomCenterOf(blockposition)); ++ entitylightning.setVisualOnly(flag1); ++ this.strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.WEATHER); // CraftBukkit + } + } + } + +- profilerfiller.popPush("iceandsnow"); ++ gameprofilerfiller.popPush("iceandsnow"); + +- for (int l = 0; l < i; ++l) { ++ for (int l = 0; l < randomTickSpeed; ++l) { + if (this.random.nextInt(48) == 0) { + this.tickPrecipitation(this.getBlockRandomPos(j, 0, k, 15)); + } + } + +- profilerfiller.popPush("tickBlocks"); +- if (i > 0) { +- LevelChunkSection[] alevelchunksection = levelchunk.getSections(); ++ gameprofilerfiller.popPush("tickBlocks"); ++ if (randomTickSpeed > 0) { ++ LevelChunkSection[] achunksection = chunk.getSections(); + +- for (int i1 = 0; i1 < alevelchunksection.length; ++i1) { +- LevelChunkSection levelchunksection = alevelchunksection[i1]; ++ for (int i1 = 0; i1 < achunksection.length; ++i1) { ++ LevelChunkSection chunksection = achunksection[i1]; + +- if (levelchunksection.isRandomlyTicking()) { +- int j1 = levelchunk.getSectionYFromSectionIndex(i1); ++ if (chunksection.isRandomlyTicking()) { ++ int j1 = chunk.getSectionYFromSectionIndex(i1); + int k1 = SectionPos.sectionToBlockCoord(j1); + +- for (int l1 = 0; l1 < i; ++l1) { +- BlockPos blockpos1 = this.getBlockRandomPos(j, k1, k, 15); ++ for (int l1 = 0; l1 < randomTickSpeed; ++l1) { ++ BlockPos blockposition1 = this.getBlockRandomPos(j, k1, k, 15); + +- profilerfiller.push("randomTick"); +- BlockState blockstate = levelchunksection.getBlockState(blockpos1.getX() - j, blockpos1.getY() - k1, blockpos1.getZ() - k); ++ gameprofilerfiller.push("randomTick"); ++ IBlockData iblockdata = chunksection.getBlockState(blockposition1.getX() - j, blockposition1.getY() - k1, blockposition1.getZ() - k); + +- if (blockstate.isRandomlyTicking()) { +- blockstate.randomTick(this, blockpos1, this.random); ++ if (iblockdata.isRandomlyTicking()) { ++ iblockdata.randomTick(this, blockposition1, this.random); + } + +- FluidState fluidstate = blockstate.getFluidState(); ++ FluidState fluid = iblockdata.getFluidState(); + +- if (fluidstate.isRandomlyTicking()) { +- fluidstate.randomTick(this, blockpos1, this.random); ++ if (fluid.isRandomlyTicking()) { ++ fluid.randomTick(this, blockposition1, this.random); + } + +- profilerfiller.pop(); ++ gameprofilerfiller.pop(); + } + } + } + } + +- profilerfiller.pop(); ++ gameprofilerfiller.pop(); + } + + @VisibleForTesting +- public void tickPrecipitation(BlockPos blockpos) { +- BlockPos blockpos1 = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, blockpos); +- BlockPos blockpos2 = blockpos1.below(); +- Biome biome = (Biome) this.getBiome(blockpos1).value(); ++ public void tickPrecipitation(BlockPos blockposition) { ++ BlockPos blockposition1 = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, blockposition); ++ BlockPos blockposition2 = blockposition1.below(); ++ Biome biomebase = (Biome) this.getBiome(blockposition1).value(); + +- if (biome.shouldFreeze(this, blockpos2)) { +- this.setBlockAndUpdate(blockpos2, Blocks.ICE.defaultBlockState()); ++ if (biomebase.shouldFreeze(this, blockposition2)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition2, Blocks.ICE.defaultBlockState(), null); // CraftBukkit + } + + if (this.isRaining()) { + int i = this.getGameRules().getInt(GameRules.RULE_SNOW_ACCUMULATION_HEIGHT); + +- if (i > 0 && biome.shouldSnow(this, blockpos1)) { +- BlockState blockstate = this.getBlockState(blockpos1); ++ if (i > 0 && biomebase.shouldSnow(this, blockposition1)) { ++ IBlockData iblockdata = this.getBlockState(blockposition1); + +- if (blockstate.is(Blocks.SNOW)) { +- int j = (Integer) blockstate.getValue(SnowLayerBlock.LAYERS); ++ if (iblockdata.is(Blocks.SNOW)) { ++ int j = (Integer) iblockdata.getValue(SnowLayerBlock.LAYERS); + + if (j < Math.min(i, 8)) { +- BlockState blockstate1 = (BlockState) blockstate.setValue(SnowLayerBlock.LAYERS, j + 1); ++ IBlockData iblockdata1 = (IBlockData) iblockdata.setValue(SnowLayerBlock.LAYERS, j + 1); + +- Block.pushEntitiesUp(blockstate, blockstate1, this, blockpos1); +- this.setBlockAndUpdate(blockpos1, blockstate1); ++ Block.pushEntitiesUp(iblockdata, iblockdata1, this, blockposition1); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, iblockdata1, null); // CraftBukkit + } + } else { +- this.setBlockAndUpdate(blockpos1, Blocks.SNOW.defaultBlockState()); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, Blocks.SNOW.defaultBlockState(), null); // CraftBukkit + } + } + +- Biome.Precipitation biome_precipitation = biome.getPrecipitationAt(blockpos2); ++ Biome.Precipitation biomebase_precipitation = biomebase.getPrecipitationAt(blockposition2); + +- if (biome_precipitation != Biome.Precipitation.NONE) { +- BlockState blockstate2 = this.getBlockState(blockpos2); ++ if (biomebase_precipitation != Biome.Precipitation.NONE) { ++ IBlockData iblockdata2 = this.getBlockState(blockposition2); + +- blockstate2.getBlock().handlePrecipitation(blockstate2, this, blockpos2, biome_precipitation); ++ iblockdata2.getBlock().handlePrecipitation(iblockdata2, this, blockposition2, biomebase_precipitation); + } + } + + } + +- private Optional findLightningRod(BlockPos blockpos) { ++ private Optional findLightningRod(BlockPos pos) { + Optional optional = this.getPoiManager().findClosest((holder) -> { + return holder.is(PoiTypes.LIGHTNING_ROD); +- }, (blockpos1) -> { +- return blockpos1.getY() == this.getHeight(Heightmap.Types.WORLD_SURFACE, blockpos1.getX(), blockpos1.getZ()) - 1; +- }, blockpos, 128, PoiManager.Occupancy.ANY); ++ }, (blockposition1) -> { ++ return blockposition1.getY() == this.getHeight(Heightmap.Types.WORLD_SURFACE, blockposition1.getX(), blockposition1.getZ()) - 1; ++ }, pos, 128, PoiManager.Occupancy.ANY); + +- return optional.map((blockpos1) -> { +- return blockpos1.above(1); ++ return optional.map((blockposition1) -> { ++ return blockposition1.above(1); + }); + } + +- protected BlockPos findLightningTargetAround(BlockPos blockpos) { +- BlockPos blockpos1 = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, blockpos); +- Optional optional = this.findLightningRod(blockpos1); ++ protected BlockPos findLightningTargetAround(BlockPos pos) { ++ BlockPos blockposition1 = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, pos); ++ Optional optional = this.findLightningRod(blockposition1); + + if (optional.isPresent()) { + return (BlockPos) optional.get(); + } else { +- AABB aabb = AABB.encapsulatingFullBlocks(blockpos1, new BlockPos(blockpos1.atY(this.getMaxBuildHeight()))).inflate(3.0D); +- List list = this.getEntitiesOfClass(LivingEntity.class, aabb, (livingentity) -> { +- return livingentity != null && livingentity.isAlive() && this.canSeeSky(livingentity.blockPosition()); ++ AABB axisalignedbb = AABB.encapsulatingFullBlocks(blockposition1, new BlockPos(blockposition1.atY(this.getMaxBuildHeight()))).inflate(3.0D); ++ List list = this.getEntitiesOfClass(LivingEntity.class, axisalignedbb, (entityliving) -> { ++ return entityliving != null && entityliving.isAlive() && this.canSeeSky(entityliving.blockPosition()); + }); + + if (!list.isEmpty()) { + return ((LivingEntity) list.get(this.random.nextInt(list.size()))).blockPosition(); + } else { +- if (blockpos1.getY() == this.getMinBuildHeight() - 1) { +- blockpos1 = blockpos1.above(2); ++ if (blockposition1.getY() == this.getMinBuildHeight() - 1) { ++ blockposition1 = blockposition1.above(2); + } + +- return blockpos1; ++ return blockposition1; + } + } + } +@@ -608,20 +663,20 @@ + if (this.canSleepThroughNights()) { + if (!this.getServer().isSingleplayer() || this.getServer().isPublished()) { + int i = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE); +- MutableComponent mutablecomponent; ++ MutableComponent ichatmutablecomponent; + + if (this.sleepStatus.areEnoughSleeping(i)) { +- mutablecomponent = Component.translatable("sleep.skipping_night"); ++ ichatmutablecomponent = Component.translatable("sleep.skipping_night"); + } else { +- mutablecomponent = Component.translatable("sleep.players_sleeping", this.sleepStatus.amountSleeping(), this.sleepStatus.sleepersNeeded(i)); ++ ichatmutablecomponent = Component.translatable("sleep.players_sleeping", this.sleepStatus.amountSleeping(), this.sleepStatus.sleepersNeeded(i)); + } + + Iterator iterator = this.players.iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- serverplayer.displayClientMessage(mutablecomponent, true); ++ entityplayer.displayClientMessage(ichatmutablecomponent, true); + } + + } +@@ -636,7 +691,6 @@ + } + + @Override +- @Override + public ServerScoreboard getScoreboard() { + return this.server.getScoreboard(); + } +@@ -707,67 +761,102 @@ + this.rainLevel = Mth.clamp(this.rainLevel, 0.0F, 1.0F); + } + ++ /* CraftBukkit start + if (this.oRainLevel != this.rainLevel) { +- this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, this.rainLevel), this.dimension()); ++ this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.RAIN_LEVEL_CHANGE, this.rainLevel), this.dimension()); + } + + if (this.oThunderLevel != this.thunderLevel) { +- this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, this.thunderLevel), this.dimension()); ++ this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, this.thunderLevel), this.dimension()); + } + + if (flag != this.isRaining()) { + if (flag) { +- this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.STOP_RAINING, 0.0F)); ++ this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.STOP_RAINING, 0.0F)); + } else { +- this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.START_RAINING, 0.0F)); ++ this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.START_RAINING, 0.0F)); + } + +- this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, this.rainLevel)); +- this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, this.thunderLevel)); ++ this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.RAIN_LEVEL_CHANGE, this.rainLevel)); ++ this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, this.thunderLevel)); + } ++ // */ ++ for (int idx = 0; idx < this.players.size(); ++idx) { ++ if (((ServerPlayer) this.players.get(idx)).level() == this) { ++ ((ServerPlayer) this.players.get(idx)).tickWeather(); ++ } ++ } + ++ if (flag != this.isRaining()) { ++ // Only send weather packets to those affected ++ for (int idx = 0; idx < this.players.size(); ++idx) { ++ if (((ServerPlayer) this.players.get(idx)).level() == this) { ++ ((ServerPlayer) this.players.get(idx)).setPlayerWeather((!flag ? WeatherType.DOWNFALL : WeatherType.CLEAR), false); ++ } ++ } ++ } ++ for (int idx = 0; idx < this.players.size(); ++idx) { ++ if (((ServerPlayer) this.players.get(idx)).level() == this) { ++ ((ServerPlayer) this.players.get(idx)).updateWeather(this.oRainLevel, this.rainLevel, this.oThunderLevel, this.thunderLevel); ++ } ++ } ++ // CraftBukkit end ++ + } + + @VisibleForTesting + public void resetWeatherCycle() { +- this.serverLevelData.setRainTime(0); ++ // CraftBukkit start + this.serverLevelData.setRaining(false); +- this.serverLevelData.setThunderTime(0); ++ // If we stop due to everyone sleeping we should reset the weather duration to some other random value. ++ // Not that everyone ever manages to get the whole server to sleep at the same time.... ++ if (!this.serverLevelData.isRaining()) { ++ this.serverLevelData.setRainTime(0); ++ } ++ // CraftBukkit end + this.serverLevelData.setThundering(false); ++ // CraftBukkit start ++ // If we stop due to everyone sleeping we should reset the weather duration to some other random value. ++ // Not that everyone ever manages to get the whole server to sleep at the same time.... ++ if (!this.serverLevelData.isThundering()) { ++ this.serverLevelData.setThunderTime(0); ++ } ++ // CraftBukkit end + } + + public void resetEmptyTime() { + this.emptyTime = 0; + } + +- private void tickFluid(BlockPos blockpos, Fluid fluid) { +- FluidState fluidstate = this.getFluidState(blockpos); ++ private void tickFluid(BlockPos pos, Fluid fluid) { ++ FluidState fluid = this.getFluidState(pos); + +- if (fluidstate.is(fluid)) { +- fluidstate.tick(this, blockpos); ++ if (fluid.is(fluid)) { ++ fluid.tick(this, pos); + } + + } + +- private void tickBlock(BlockPos blockpos, Block block) { +- BlockState blockstate = this.getBlockState(blockpos); ++ private void tickBlock(BlockPos pos, Block block) { ++ IBlockData iblockdata = this.getBlockState(pos); + +- if (blockstate.is(block)) { +- blockstate.tick(this, blockpos, this.random); ++ if (iblockdata.is(block)) { ++ iblockdata.tick(this, pos, this.random); + } + + } + + public void tickNonPassenger(Entity entity) { + entity.setOldPosAndRot(); +- ProfilerFiller profilerfiller = this.getProfiler(); ++ ProfilerFiller gameprofilerfiller = this.getProfiler(); + + ++entity.tickCount; + this.getProfiler().push(() -> { + return BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()).toString(); + }); +- profilerfiller.incrementCounter("tickNonPassenger"); ++ gameprofilerfiller.incrementCounter("tickNonPassenger"); + entity.tick(); ++ entity.postTick(); // CraftBukkit + this.getProfiler().pop(); + Iterator iterator = entity.getPassengers().iterator(); + +@@ -779,91 +868,100 @@ + + } + +- private void tickPassenger(Entity entity, Entity entity1) { +- if (!entity1.isRemoved() && entity1.getVehicle() == entity) { +- if (entity1 instanceof Player || this.entityTickList.contains(entity1)) { +- entity1.setOldPosAndRot(); +- ++entity1.tickCount; +- ProfilerFiller profilerfiller = this.getProfiler(); ++ private void tickPassenger(Entity ridingEntity, Entity passengerEntity) { ++ if (!passengerEntity.isRemoved() && passengerEntity.getVehicle() == ridingEntity) { ++ if (passengerEntity instanceof Player || this.entityTickList.contains(passengerEntity)) { ++ passengerEntity.setOldPosAndRot(); ++ ++passengerEntity.tickCount; ++ ProfilerFiller gameprofilerfiller = this.getProfiler(); + +- profilerfiller.push(() -> { +- return BuiltInRegistries.ENTITY_TYPE.getKey(entity1.getType()).toString(); ++ gameprofilerfiller.push(() -> { ++ return BuiltInRegistries.ENTITY_TYPE.getKey(passengerEntity.getType()).toString(); + }); +- profilerfiller.incrementCounter("tickPassenger"); +- entity1.rideTick(); +- profilerfiller.pop(); +- Iterator iterator = entity1.getPassengers().iterator(); ++ gameprofilerfiller.incrementCounter("tickPassenger"); ++ passengerEntity.rideTick(); ++ passengerEntity.postTick(); // CraftBukkit ++ gameprofilerfiller.pop(); ++ Iterator iterator = passengerEntity.getPassengers().iterator(); + + while (iterator.hasNext()) { + Entity entity2 = (Entity) iterator.next(); + +- this.tickPassenger(entity1, entity2); ++ this.tickPassenger(passengerEntity, entity2); + } + + } + } else { +- entity1.stopRiding(); ++ passengerEntity.stopRiding(); + } + } + + @Override +- @Override +- public boolean mayInteract(Player player, BlockPos blockpos) { +- return !this.server.isUnderSpawnProtection(this, blockpos, player) && this.getWorldBorder().isWithinBounds(blockpos); ++ public boolean mayInteract(Player player, BlockPos pos) { ++ return !this.server.isUnderSpawnProtection(this, pos, player) && this.getWorldBorder().isWithinBounds(pos); + } + +- public void save(@Nullable ProgressListener progresslistener, boolean flag, boolean flag1) { +- ServerChunkCache serverchunkcache = this.getChunkSource(); ++ public void save(@Nullable ProgressListener progress, boolean flush, boolean skipSave) { ++ ServerChunkCache chunkproviderserver = this.getChunkSource(); + +- if (!flag1) { +- if (progresslistener != null) { +- progresslistener.progressStartNoAbort(Component.translatable("menu.savingLevel")); ++ if (!skipSave) { ++ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit ++ if (progress != null) { ++ progress.progressStartNoAbort(Component.translatable("menu.savingLevel")); + } + + this.saveLevelData(); +- if (progresslistener != null) { +- progresslistener.progressStage(Component.translatable("menu.savingChunks")); ++ if (progress != null) { ++ progress.progressStage(Component.translatable("menu.savingChunks")); + } + +- serverchunkcache.save(flag); +- if (flag) { ++ chunkproviderserver.save(flush); ++ if (flush) { + this.entityManager.saveAll(); + } else { + this.entityManager.autoSave(); + } + + } ++ ++ // CraftBukkit start - moved from MinecraftServer.saveChunks ++ ServerLevel worldserver1 = this; ++ ++ serverLevelData.setWorldBorder(worldserver1.getWorldBorder().createSettings()); ++ serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save()); ++ convertable.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData()); ++ // CraftBukkit end + } + + private void saveLevelData() { + if (this.dragonFight != null) { +- this.server.getWorldData().setEndDragonFightData(this.dragonFight.saveData()); ++ this.serverLevelData.setEndDragonFightData(this.dragonFight.saveData()); // CraftBukkit + } + + this.getChunkSource().getDataStorage().save(); + } + +- public List getEntities(EntityTypeTest entitytypetest, Predicate predicate) { ++ public List getEntities(EntityTypeTest typeTest, Predicate predicate) { + List list = Lists.newArrayList(); + +- this.getEntities(entitytypetest, predicate, (List) list); ++ this.getEntities(typeTest, predicate, (List) list); + return list; + } + +- public void getEntities(EntityTypeTest entitytypetest, Predicate predicate, List list) { +- this.getEntities(entitytypetest, predicate, list, Integer.MAX_VALUE); ++ public void getEntities(EntityTypeTest typeTest, Predicate predicate, List output) { ++ this.getEntities(typeTest, predicate, output, Integer.MAX_VALUE); + } + +- public void getEntities(EntityTypeTest entitytypetest, Predicate predicate, List list, int i) { +- this.getEntities().get(entitytypetest, (entity) -> { ++ public void getEntities(EntityTypeTest typeTest, Predicate predicate, List output, int maxResults) { ++ this.getEntities().get(typeTest, (entity) -> { + if (predicate.test(entity)) { +- list.add(entity); +- if (list.size() >= i) { +- return AbortableIterationConsumer.Continuation.ABORT; ++ output.add(entity); ++ if (output.size() >= maxResults) { ++ return AbortableIterationConsumer.a.ABORT; + } + } + +- return AbortableIterationConsumer.Continuation.CONTINUE; ++ return AbortableIterationConsumer.a.CONTINUE; + }); + } + +@@ -875,16 +973,16 @@ + return this.getPlayers(predicate, Integer.MAX_VALUE); + } + +- public List getPlayers(Predicate predicate, int i) { ++ public List getPlayers(Predicate predicate, int maxResults) { + List list = Lists.newArrayList(); + Iterator iterator = this.players.iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- if (predicate.test(serverplayer)) { +- list.add(serverplayer); +- if (list.size() >= i) { ++ if (predicate.test(entityplayer)) { ++ list.add(entityplayer); ++ if (list.size() >= maxResults) { + return list; + } + } +@@ -901,93 +999,154 @@ + } + + @Override +- @Override + public boolean addFreshEntity(Entity entity) { +- return this.addEntity(entity); ++ // CraftBukkit start ++ return this.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.DEFAULT); + } + ++ @Override ++ public boolean addFreshEntity(Entity entity, CreatureSpawnEvent.SpawnReason reason) { ++ return this.addEntity(entity, reason); ++ // CraftBukkit end ++ } ++ + public boolean addWithUUID(Entity entity) { +- return this.addEntity(entity); ++ // CraftBukkit start ++ return this.addWithUUID(entity, CreatureSpawnEvent.SpawnReason.DEFAULT); + } + ++ public boolean addWithUUID(Entity entity, CreatureSpawnEvent.SpawnReason reason) { ++ return this.addEntity(entity, reason); ++ // CraftBukkit end ++ } ++ + public void addDuringTeleport(Entity entity) { +- this.addEntity(entity); ++ // CraftBukkit start ++ // SPIGOT-6415: Don't call spawn event for entities which travel trough worlds, ++ // since it is only an implementation detail, that a new entity is created when ++ // they are traveling between worlds. ++ this.addDuringTeleport(entity, null); + } + +- public void addDuringCommandTeleport(ServerPlayer serverplayer) { +- this.addPlayer(serverplayer); ++ public void addDuringTeleport(Entity entity, CreatureSpawnEvent.SpawnReason reason) { ++ this.addEntity(entity, reason); ++ // CraftBukkit end + } + +- public void addDuringPortalTeleport(ServerPlayer serverplayer) { +- this.addPlayer(serverplayer); ++ public void addDuringCommandTeleport(ServerPlayer player) { ++ this.addPlayer(player); + } + +- public void addNewPlayer(ServerPlayer serverplayer) { +- this.addPlayer(serverplayer); ++ public void addDuringPortalTeleport(ServerPlayer player) { ++ this.addPlayer(player); + } + +- public void addRespawnedPlayer(ServerPlayer serverplayer) { +- this.addPlayer(serverplayer); ++ public void addNewPlayer(ServerPlayer player) { ++ this.addPlayer(player); + } + +- private void addPlayer(ServerPlayer serverplayer) { +- Entity entity = (Entity) this.getEntities().get(serverplayer.getUUID()); ++ public void addRespawnedPlayer(ServerPlayer player) { ++ this.addPlayer(player); ++ } + ++ private void addPlayer(ServerPlayer player) { ++ Entity entity = (Entity) this.getEntities().get(player.getUUID()); ++ + if (entity != null) { +- ServerLevel.LOGGER.warn("Force-added player with duplicate UUID {}", serverplayer.getUUID()); ++ ServerLevel.LOGGER.warn("Force-added player with duplicate UUID {}", player.getUUID()); + entity.unRide(); + this.removePlayerImmediately((ServerPlayer) entity, Entity.RemovalReason.DISCARDED); + } + +- this.entityManager.addNewEntity(serverplayer); ++ this.entityManager.addNewEntity(player); + } + +- private boolean addEntity(Entity entity) { ++ // CraftBukkit start ++ private boolean addEntity(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { + if (entity.isRemoved()) { +- ServerLevel.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityType.getKey(entity.getType())); ++ // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getKey(entity.getType())); // CraftBukkit + return false; + } else { ++ // SPIGOT-6415: Don't call spawn event when reason is null. For example when an entity teleports to a new world. ++ if (spawnReason != null && !CraftEventFactory.doEntityAddEventCalling(this, entity, spawnReason)) { ++ return false; ++ } ++ // CraftBukkit end ++ + return this.entityManager.addNewEntity(entity); + } + } + + public boolean tryAddFreshEntityWithPassengers(Entity entity) { +- Stream stream = entity.getSelfAndPassengers().map(Entity::getUUID); ++ // CraftBukkit start ++ return this.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ public boolean tryAddFreshEntityWithPassengers(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ // CraftBukkit end ++ Stream stream = entity.getSelfAndPassengers().map(Entity::getUUID); // CraftBukkit - decompile error + PersistentEntitySectionManager persistententitysectionmanager = this.entityManager; + + Objects.requireNonNull(this.entityManager); + if (stream.anyMatch(persistententitysectionmanager::isLoaded)) { + return false; + } else { +- this.addFreshEntityWithPassengers(entity); ++ this.addFreshEntityWithPassengers(entity, reason); // CraftBukkit + return true; + } + } + +- public void unload(LevelChunk levelchunk) { +- levelchunk.clearAllBlockEntities(); +- levelchunk.unregisterTickContainerFromLevel(this); ++ public void unload(LevelChunk chunk) { ++ chunk.clearAllBlockEntities(); ++ chunk.unregisterTickContainerFromLevel(this); + } + +- public void removePlayerImmediately(ServerPlayer serverplayer, Entity.RemovalReason entity_removalreason) { +- serverplayer.remove(entity_removalreason); ++ public void removePlayerImmediately(ServerPlayer player, Entity.RemovalReason reason) { ++ player.remove(reason); + } + ++ // CraftBukkit start ++ public boolean strikeLightning(Entity entitylightning) { ++ return this.strikeLightning(entitylightning, LightningStrikeEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean strikeLightning(Entity entitylightning, LightningStrikeEvent.Cause cause) { ++ LightningStrikeEvent lightning = CraftEventFactory.callLightningStrikeEvent((org.bukkit.entity.LightningStrike) entitylightning.getBukkitEntity(), cause); ++ ++ if (lightning.isCancelled()) { ++ return false; ++ } ++ ++ return this.addFreshEntity(entitylightning); ++ } ++ // CraftBukkit end ++ + @Override +- @Override +- public void destroyBlockProgress(int i, BlockPos blockpos, int j) { ++ public void destroyBlockProgress(int breakerId, BlockPos pos, int progress) { + Iterator iterator = this.server.getPlayerList().getPlayers().iterator(); + ++ // CraftBukkit start ++ Player entityhuman = null; ++ Entity entity = this.getEntity(breakerId); ++ if (entity instanceof Player) entityhuman = (Player) entity; ++ // CraftBukkit end ++ + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- if (serverplayer != null && serverplayer.level() == this && serverplayer.getId() != i) { +- double d0 = (double) blockpos.getX() - serverplayer.getX(); +- double d1 = (double) blockpos.getY() - serverplayer.getY(); +- double d2 = (double) blockpos.getZ() - serverplayer.getZ(); ++ if (entityplayer != null && entityplayer.level() == this && entityplayer.getId() != breakerId) { ++ double d0 = (double) pos.getX() - entityplayer.getX(); ++ double d1 = (double) pos.getY() - entityplayer.getY(); ++ double d2 = (double) pos.getZ() - entityplayer.getZ(); + ++ // CraftBukkit start ++ if (entityhuman != null && !entityplayer.getBukkitEntity().canSee(entityhuman.getBukkitEntity())) { ++ continue; ++ } ++ // CraftBukkit end ++ + if (d0 * d0 + d1 * d1 + d2 * d2 < 1024.0D) { +- serverplayer.connection.send(new ClientboundBlockDestructionPacket(i, blockpos, j)); ++ entityplayer.connection.send(new ClientboundBlockDestructionPacket(breakerId, pos, progress)); + } + } + } +@@ -995,32 +1154,28 @@ + } + + @Override +- @Override +- public void playSeededSound(@Nullable Player player, double d0, double d1, double d2, Holder holder, SoundSource soundsource, float f, float f1, long i) { +- this.server.getPlayerList().broadcast(player, d0, d1, d2, (double) ((SoundEvent) holder.value()).getRange(f), this.dimension(), new ClientboundSoundPacket(holder, soundsource, d0, d1, d2, f, f1, i)); ++ public void playSeededSound(@Nullable Player player, double x, double d1, double y, Holder holder, SoundSource z, float f, float sound, long source) { ++ this.server.getPlayerList().broadcast(player, x, d1, y, (double) ((SoundEvent) holder.value()).getRange(f), this.dimension(), new ClientboundSoundPacket(holder, z, x, d1, y, f, sound, source)); + } + + @Override +- @Override +- public void playSeededSound(@Nullable Player player, Entity entity, Holder holder, SoundSource soundsource, float f, float f1, long i) { +- this.server.getPlayerList().broadcast(player, entity.getX(), entity.getY(), entity.getZ(), (double) ((SoundEvent) holder.value()).getRange(f), this.dimension(), new ClientboundSoundEntityPacket(holder, soundsource, entity, f, f1, i)); ++ public void playSeededSound(@Nullable Player player, Entity entity, Holder sound, SoundSource category, float volume, float pitch, long seed) { ++ this.server.getPlayerList().broadcast(player, entity.getX(), entity.getY(), entity.getZ(), (double) ((SoundEvent) sound.value()).getRange(volume), this.dimension(), new ClientboundSoundEntityPacket(sound, category, entity, volume, pitch, seed)); + } + + @Override +- @Override +- public void globalLevelEvent(int i, BlockPos blockpos, int j) { ++ public void globalLevelEvent(int id, BlockPos pos, int data) { + if (this.getGameRules().getBoolean(GameRules.RULE_GLOBAL_SOUND_EVENTS)) { +- this.server.getPlayerList().broadcastAll(new ClientboundLevelEventPacket(i, blockpos, j, true)); ++ this.server.getPlayerList().broadcastAll(new ClientboundLevelEventPacket(id, pos, data, true)); + } else { +- this.levelEvent((Player) null, i, blockpos, j); ++ this.levelEvent((Player) null, id, pos, data); + } + + } + + @Override +- @Override +- public void levelEvent(@Nullable Player player, int i, BlockPos blockpos, int j) { +- this.server.getPlayerList().broadcast(player, (double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), 64.0D, this.dimension(), new ClientboundLevelEventPacket(i, blockpos, j, false)); ++ public void levelEvent(@Nullable Player player, int type, BlockPos pos, int data) { ++ this.server.getPlayerList().broadcast(player, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), 64.0D, this.dimension(), new ClientboundLevelEventPacket(type, pos, data, false)); + } + + public int getLogicalHeight() { +@@ -1028,34 +1183,43 @@ + } + + @Override +- @Override +- public void gameEvent(GameEvent gameevent, Vec3 vec3, GameEvent.Context gameevent_context) { +- this.gameEventDispatcher.post(gameevent, vec3, gameevent_context); ++ public void gameEvent(GameEvent event, Vec3 position, GameEvent.Context context) { ++ this.gameEventDispatcher.post(event, position, context); + } + + @Override +- @Override +- public void sendBlockUpdated(BlockPos blockpos, BlockState blockstate, BlockState blockstate1, int i) { ++ public void sendBlockUpdated(BlockPos pos, IBlockData oldState, IBlockData newState, int flags) { + if (this.isUpdatingNavigations) { + String s = "recursive call to sendBlockUpdated"; + + Util.logAndPauseIfInIde("recursive call to sendBlockUpdated", new IllegalStateException("recursive call to sendBlockUpdated")); + } + +- this.getChunkSource().blockChanged(blockpos); +- VoxelShape voxelshape = blockstate.getCollisionShape(this, blockpos); +- VoxelShape voxelshape1 = blockstate1.getCollisionShape(this, blockpos); ++ this.getChunkSource().blockChanged(pos); ++ VoxelShape voxelshape = oldState.getCollisionShape(this, pos); ++ VoxelShape voxelshape1 = newState.getCollisionShape(this, pos); + + if (Shapes.joinIsNotEmpty(voxelshape, voxelshape1, BooleanOp.NOT_SAME)) { + List list = new ObjectArrayList(); + Iterator iterator = this.navigatingMobs.iterator(); + + while (iterator.hasNext()) { +- Mob mob = (Mob) iterator.next(); +- PathNavigation pathnavigation = mob.getNavigation(); ++ // CraftBukkit start - fix SPIGOT-6362 ++ Mob entityinsentient; ++ try { ++ entityinsentient = (Mob) iterator.next(); ++ } catch (java.util.ConcurrentModificationException ex) { ++ // This can happen because the pathfinder update below may trigger a chunk load, which in turn may cause more navigators to register ++ // In this case we just run the update again across all the iterators as the chunk will then be loaded ++ // As this is a relative edge case it is much faster than copying navigators (on either read or write) ++ sendBlockUpdated(pos, oldState, newState, flags); ++ return; ++ } ++ // CraftBukkit end ++ PathNavigation navigationabstract = entityinsentient.getNavigation(); + +- if (pathnavigation.shouldRecomputePath(blockpos)) { +- list.add(pathnavigation); ++ if (navigationabstract.shouldRecomputePath(pos)) { ++ list.add(navigationabstract); + } + } + +@@ -1064,9 +1228,9 @@ + iterator = list.iterator(); + + while (iterator.hasNext()) { +- PathNavigation pathnavigation1 = (PathNavigation) iterator.next(); ++ PathNavigation navigationabstract1 = (PathNavigation) iterator.next(); + +- pathnavigation1.recomputePath(); ++ navigationabstract1.recomputePath(); + } + } finally { + this.isUpdatingNavigations = false; +@@ -1076,51 +1240,48 @@ + } + + @Override +- @Override +- public void updateNeighborsAt(BlockPos blockpos, Block block) { +- this.neighborUpdater.updateNeighborsAtExceptFromFacing(blockpos, block, (Direction) null); ++ public void updateNeighborsAt(BlockPos pos, Block block) { ++ this.neighborUpdater.updateNeighborsAtExceptFromFacing(pos, block, (Direction) null); + } + + @Override +- @Override +- public void updateNeighborsAtExceptFromFacing(BlockPos blockpos, Block block, Direction direction) { +- this.neighborUpdater.updateNeighborsAtExceptFromFacing(blockpos, block, direction); ++ public void updateNeighborsAtExceptFromFacing(BlockPos pos, Block blockType, Direction skipSide) { ++ this.neighborUpdater.updateNeighborsAtExceptFromFacing(pos, blockType, skipSide); + } + + @Override +- @Override +- public void neighborChanged(BlockPos blockpos, Block block, BlockPos blockpos1) { +- this.neighborUpdater.neighborChanged(blockpos, block, blockpos1); ++ public void neighborChanged(BlockPos pos, Block block, BlockPos fromPos) { ++ this.neighborUpdater.neighborChanged(pos, block, fromPos); + } + + @Override +- @Override +- public void neighborChanged(BlockState blockstate, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { +- this.neighborUpdater.neighborChanged(blockstate, blockpos, block, blockpos1, flag); ++ public void neighborChanged(IBlockData state, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ this.neighborUpdater.neighborChanged(state, pos, block, fromPos, isMoving); + } + + @Override +- @Override +- public void broadcastEntityEvent(Entity entity, byte b0) { +- this.getChunkSource().broadcastAndSend(entity, new ClientboundEntityEventPacket(entity, b0)); ++ public void broadcastEntityEvent(Entity entity, byte state) { ++ this.getChunkSource().broadcastAndSend(entity, new ClientboundEntityEventPacket(entity, state)); + } + + @Override +- @Override +- public void broadcastDamageEvent(Entity entity, DamageSource damagesource) { +- this.getChunkSource().broadcastAndSend(entity, new ClientboundDamageEventPacket(entity, damagesource)); ++ public void broadcastDamageEvent(Entity entity, DamageSource damageSource) { ++ this.getChunkSource().broadcastAndSend(entity, new ClientboundDamageEventPacket(entity, damageSource)); + } + + @Override +- @Override + public ServerChunkCache getChunkSource() { + return this.chunkSource; + } + + @Override +- @Override +- public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.ExplosionInteraction level_explosioninteraction, ParticleOptions particleoptions, ParticleOptions particleoptions1, SoundEvent soundevent) { +- Explosion explosion = this.explode(entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, level_explosioninteraction, false, particleoptions, particleoptions1, soundevent); ++ public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.a world_a, ParticleOptions particleparam, ParticleOptions particleparam1, SoundEvent soundeffect) { ++ Explosion explosion = this.explode(entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, world_a, false, particleparam, particleparam1, soundeffect); ++ // CraftBukkit start ++ if (explosion.wasCanceled) { ++ return explosion; ++ } ++ // CraftBukkit end + + if (!explosion.interactsWithBlocks()) { + explosion.clearToBlow(); +@@ -1129,10 +1290,10 @@ + Iterator iterator = this.players.iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- if (serverplayer.distanceToSqr(d0, d1, d2) < 4096.0D) { +- serverplayer.connection.send(new ClientboundExplodePacket(d0, d1, d2, f, explosion.getToBlow(), (Vec3) explosion.getHitPlayers().get(serverplayer), explosion.getBlockInteraction(), explosion.getSmallExplosionParticles(), explosion.getLargeExplosionParticles(), explosion.getExplosionSound())); ++ if (entityplayer.distanceToSqr(d0, d1, d2) < 4096.0D) { ++ entityplayer.connection.send(new ClientboundExplodePacket(d0, d1, d2, f, explosion.getToBlow(), (Vec3) explosion.getHitPlayers().get(entityplayer), explosion.getBlockInteraction(), explosion.getSmallExplosionParticles(), explosion.getLargeExplosionParticles(), explosion.getExplosionSound())); + } + } + +@@ -1140,50 +1301,46 @@ + } + + @Override +- @Override +- public void blockEvent(BlockPos blockpos, Block block, int i, int j) { +- this.blockEvents.add(new BlockEventData(blockpos, block, i, j)); ++ public void blockEvent(BlockPos pos, Block block, int eventID, int eventParam) { ++ this.blockEvents.add(new BlockEventData(pos, block, eventID, eventParam)); + } + + private void runBlockEvents() { + this.blockEventsToReschedule.clear(); + + while (!this.blockEvents.isEmpty()) { +- BlockEventData blockeventdata = (BlockEventData) this.blockEvents.removeFirst(); ++ BlockEventData blockactiondata = (BlockEventData) this.blockEvents.removeFirst(); + +- if (this.shouldTickBlocksAt(blockeventdata.pos())) { +- if (this.doBlockEvent(blockeventdata)) { +- this.server.getPlayerList().broadcast((Player) null, (double) blockeventdata.pos().getX(), (double) blockeventdata.pos().getY(), (double) blockeventdata.pos().getZ(), 64.0D, this.dimension(), new ClientboundBlockEventPacket(blockeventdata.pos(), blockeventdata.block(), blockeventdata.paramA(), blockeventdata.paramB())); ++ if (this.shouldTickBlocksAt(blockactiondata.pos())) { ++ if (this.doBlockEvent(blockactiondata)) { ++ this.server.getPlayerList().broadcast((Player) null, (double) blockactiondata.pos().getX(), (double) blockactiondata.pos().getY(), (double) blockactiondata.pos().getZ(), 64.0D, this.dimension(), new ClientboundBlockEventPacket(blockactiondata.pos(), blockactiondata.block(), blockactiondata.paramA(), blockactiondata.paramB())); + } + } else { +- this.blockEventsToReschedule.add(blockeventdata); ++ this.blockEventsToReschedule.add(blockactiondata); + } + } + + this.blockEvents.addAll(this.blockEventsToReschedule); + } + +- private boolean doBlockEvent(BlockEventData blockeventdata) { +- BlockState blockstate = this.getBlockState(blockeventdata.pos()); ++ private boolean doBlockEvent(BlockEventData event) { ++ IBlockData iblockdata = this.getBlockState(event.pos()); + +- return blockstate.is(blockeventdata.block()) ? blockstate.triggerEvent(this, blockeventdata.pos(), blockeventdata.paramA(), blockeventdata.paramB()) : false; ++ return iblockdata.is(event.block()) ? iblockdata.triggerEvent(this, event.pos(), event.paramA(), event.paramB()) : false; + } + + @Override +- @Override + public LevelTicks getBlockTicks() { + return this.blockTicks; + } + + @Override +- @Override + public LevelTicks getFluidTicks() { + return this.fluidTicks; + } + + @Nonnull + @Override +- @Override + public MinecraftServer getServer() { + return this.server; + } +@@ -1196,14 +1353,21 @@ + return this.server.getStructureManager(); + } + +- public int sendParticles(T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6) { +- ClientboundLevelParticlesPacket clientboundlevelparticlespacket = new ClientboundLevelParticlesPacket(t0, false, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i); ++ public int sendParticles(T type, double posX, double d1, double posY, int i, double posZ, double d4, double particleCount, double xOffset) { ++ // CraftBukkit - visibility api support ++ return sendParticles(null, type, posX, d1, posY, i, posZ, d4, particleCount, xOffset, false); ++ } ++ ++ public int sendParticles(ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { ++ ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(t0, force, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i); ++ // CraftBukkit end + int j = 0; + + for (int k = 0; k < this.players.size(); ++k) { +- ServerPlayer serverplayer = (ServerPlayer) this.players.get(k); ++ ServerPlayer entityplayer = (ServerPlayer) this.players.get(k); ++ if (sender != null && !entityplayer.getBukkitEntity().canSee(sender.getBukkitEntity())) continue; // CraftBukkit + +- if (this.sendParticles(serverplayer, false, d0, d1, d2, clientboundlevelparticlespacket)) { ++ if (this.sendParticles(entityplayer, force, d0, d1, d2, packetplayoutworldparticles)) { // CraftBukkit + ++j; + } + } +@@ -1211,20 +1375,20 @@ + return j; + } + +- public boolean sendParticles(ServerPlayer serverplayer, T t0, boolean flag, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6) { +- Packet packet = new ClientboundLevelParticlesPacket(t0, flag, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i); ++ public boolean sendParticles(ServerPlayer player, T type, boolean longDistance, double posX, double d1, double posY, int i, double posZ, double d4, double particleCount, double xOffset) { ++ Packet packet = new ClientboundLevelParticlesPacket(type, longDistance, posX, d1, posY, (float) posZ, (float) d4, (float) particleCount, (float) xOffset, i); + +- return this.sendParticles(serverplayer, flag, d0, d1, d2, packet); ++ return this.sendParticles(player, longDistance, posX, d1, posY, packet); + } + +- private boolean sendParticles(ServerPlayer serverplayer, boolean flag, double d0, double d1, double d2, Packet packet) { +- if (serverplayer.level() != this) { ++ private boolean sendParticles(ServerPlayer player, boolean longDistance, double posX, double d1, double posY, Packet packet) { ++ if (player.level() != this) { + return false; + } else { +- BlockPos blockpos = serverplayer.blockPosition(); ++ BlockPos blockposition = player.blockPosition(); + +- if (blockpos.closerToCenterThan(new Vec3(d0, d1, d2), flag ? 512.0D : 32.0D)) { +- serverplayer.connection.send(packet); ++ if (blockposition.closerToCenterThan(new Vec3(posX, d1, posY), longDistance ? 512.0D : 32.0D)) { ++ player.connection.send(packet); + return true; + } else { + return false; +@@ -1234,36 +1398,35 @@ + + @Nullable + @Override +- @Override +- public Entity getEntity(int i) { +- return (Entity) this.getEntities().get(i); ++ public Entity getEntity(int id) { ++ return (Entity) this.getEntities().get(id); + } + + /** @deprecated */ + @Deprecated + @Nullable +- public Entity getEntityOrPart(int i) { +- Entity entity = (Entity) this.getEntities().get(i); ++ public Entity getEntityOrPart(int id) { ++ Entity entity = (Entity) this.getEntities().get(id); + +- return entity != null ? entity : (Entity) this.dragonParts.get(i); ++ return entity != null ? entity : (Entity) this.dragonParts.get(id); + } + + @Nullable +- public Entity getEntity(UUID uuid) { +- return (Entity) this.getEntities().get(uuid); ++ public Entity getEntity(UUID uniqueId) { ++ return (Entity) this.getEntities().get(uniqueId); + } + + @Nullable +- public BlockPos findNearestMapStructure(TagKey tagkey, BlockPos blockpos, int i, boolean flag) { +- if (!this.server.getWorldData().worldGenOptions().generateStructures()) { ++ public BlockPos findNearestMapStructure(TagKey structureTag, BlockPos pos, int radius, boolean skipExistingChunks) { ++ if (!this.serverLevelData.worldGenOptions().generateStructures()) { // CraftBukkit + return null; + } else { +- Optional> optional = this.registryAccess().registryOrThrow(Registries.STRUCTURE).getTag(tagkey); ++ Optional> optional = this.registryAccess().registryOrThrow(Registries.STRUCTURE).getTag(structureTag); + + if (optional.isEmpty()) { + return null; + } else { +- Pair> pair = this.getChunkSource().getGenerator().findNearestMapStructure(this, (HolderSet) optional.get(), blockpos, i, flag); ++ Pair> pair = this.getChunkSource().getGenerator().findNearestMapStructure(this, (HolderSet) optional.get(), pos, radius, skipExistingChunks); + + return pair != null ? (BlockPos) pair.getFirst() : null; + } +@@ -1271,24 +1434,21 @@ + } + + @Nullable +- public Pair> findClosestBiome3d(Predicate> predicate, BlockPos blockpos, int i, int j, int k) { +- return this.getChunkSource().getGenerator().getBiomeSource().findClosestBiome3d(blockpos, i, j, k, predicate, this.getChunkSource().randomState().sampler(), this); ++ public Pair> findClosestBiome3d(Predicate> biomePredicate, BlockPos pos, int i, int j, int k) { ++ return this.getChunkSource().getGenerator().getBiomeSource().findClosestBiome3d(pos, i, j, k, biomePredicate, this.getChunkSource().randomState().sampler(), this); + } + + @Override +- @Override + public RecipeManager getRecipeManager() { + return this.server.getRecipeManager(); + } + + @Override +- @Override + public TickRateManager tickRateManager() { + return this.server.tickRateManager(); + } + + @Override +- @Override + public boolean noSave() { + return this.noSave; + } +@@ -1299,86 +1459,92 @@ + + @Nullable + @Override +- @Override +- public MapItemSavedData getMapData(String s) { +- return (MapItemSavedData) this.getServer().overworld().getDataStorage().get(MapItemSavedData.factory(), s); ++ public MapItemSavedData getMapData(String mapName) { ++ // CraftBukkit start ++ MapItemSavedData worldmap = (MapItemSavedData) this.getServer().overworld().getDataStorage().get(MapItemSavedData.factory(), mapName); ++ if (worldmap != null) { ++ worldmap.id = mapName; ++ } ++ return worldmap; ++ // CraftBukkit end + } + + @Override +- @Override +- public void setMapData(String s, MapItemSavedData mapitemsaveddata) { +- this.getServer().overworld().getDataStorage().set(s, mapitemsaveddata); ++ public void setMapData(String mapName, MapItemSavedData data) { ++ // CraftBukkit start ++ data.id = mapName; ++ MapInitializeEvent event = new MapInitializeEvent(data.mapView); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ // CraftBukkit end ++ this.getServer().overworld().getDataStorage().set(mapName, data); + } + + @Override +- @Override + public int getFreeMapId() { + return ((MapIndex) this.getServer().overworld().getDataStorage().computeIfAbsent(MapIndex.factory(), "idcounts")).getFreeAuxValueForMap(); + } + +- public void setDefaultSpawnPos(BlockPos blockpos, float f) { +- ChunkPos chunkpos = new ChunkPos(new BlockPos(this.levelData.getXSpawn(), 0, this.levelData.getZSpawn())); ++ public void setDefaultSpawnPos(BlockPos pos, float angle) { ++ ChunkPos chunkcoordintpair = new ChunkPos(new BlockPos(this.levelData.getXSpawn(), 0, this.levelData.getZSpawn())); + +- this.levelData.setSpawn(blockpos, f); +- this.getChunkSource().removeRegionTicket(TicketType.START, chunkpos, 11, Unit.INSTANCE); +- this.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(blockpos), 11, Unit.INSTANCE); +- this.getServer().getPlayerList().broadcastAll(new ClientboundSetDefaultSpawnPositionPacket(blockpos, f)); ++ this.levelData.setSpawn(pos, angle); ++ this.getChunkSource().removeRegionTicket(TicketType.START, chunkcoordintpair, 11, Unit.INSTANCE); ++ this.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(pos), 11, Unit.INSTANCE); ++ this.getServer().getPlayerList().broadcastAll(new ClientboundSetDefaultSpawnPositionPacket(pos, angle)); + } + + public LongSet getForcedChunks() { +- ForcedChunksSavedData forcedchunkssaveddata = (ForcedChunksSavedData) this.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks"); ++ ForcedChunksSavedData forcedchunk = (ForcedChunksSavedData) this.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks"); + +- return (LongSet) (forcedchunkssaveddata != null ? LongSets.unmodifiable(forcedchunkssaveddata.getChunks()) : LongSets.EMPTY_SET); ++ return (LongSet) (forcedchunk != null ? LongSets.unmodifiable(forcedchunk.getChunks()) : LongSets.EMPTY_SET); + } + +- public boolean setChunkForced(int i, int j, boolean flag) { +- ForcedChunksSavedData forcedchunkssaveddata = (ForcedChunksSavedData) this.getDataStorage().computeIfAbsent(ForcedChunksSavedData.factory(), "chunks"); +- ChunkPos chunkpos = new ChunkPos(i, j); +- long k = chunkpos.toLong(); ++ public boolean setChunkForced(int chunkX, int chunkZ, boolean add) { ++ ForcedChunksSavedData forcedchunk = (ForcedChunksSavedData) this.getDataStorage().computeIfAbsent(ForcedChunksSavedData.factory(), "chunks"); ++ ChunkPos chunkcoordintpair = new ChunkPos(chunkX, chunkZ); ++ long k = chunkcoordintpair.toLong(); + boolean flag1; + +- if (flag) { +- flag1 = forcedchunkssaveddata.getChunks().add(k); ++ if (add) { ++ flag1 = forcedchunk.getChunks().add(k); + if (flag1) { +- this.getChunk(i, j); ++ this.getChunk(chunkX, chunkZ); + } + } else { +- flag1 = forcedchunkssaveddata.getChunks().remove(k); ++ flag1 = forcedchunk.getChunks().remove(k); + } + +- forcedchunkssaveddata.setDirty(flag1); ++ forcedchunk.setDirty(flag1); + if (flag1) { +- this.getChunkSource().updateChunkForced(chunkpos, flag); ++ this.getChunkSource().updateChunkForced(chunkcoordintpair, add); + } + + return flag1; + } + + @Override +- @Override + public List players() { + return this.players; + } + + @Override +- @Override +- public void onBlockStateChange(BlockPos blockpos, BlockState blockstate, BlockState blockstate1) { +- Optional> optional = PoiTypes.forState(blockstate); +- Optional> optional1 = PoiTypes.forState(blockstate1); ++ public void onBlockStateChange(BlockPos pos, IBlockData blockState, IBlockData newState) { ++ Optional> optional = PoiTypes.forState(blockState); ++ Optional> optional1 = PoiTypes.forState(newState); + + if (!Objects.equals(optional, optional1)) { +- BlockPos blockpos1 = blockpos.immutable(); ++ BlockPos blockposition1 = pos.immutable(); + + optional.ifPresent((holder) -> { + this.getServer().execute(() -> { +- this.getPoiManager().remove(blockpos1); +- DebugPackets.sendPoiRemovedPacket(this, blockpos1); ++ this.getPoiManager().remove(blockposition1); ++ DebugPackets.sendPoiRemovedPacket(this, blockposition1); + }); + }); + optional1.ifPresent((holder) -> { + this.getServer().execute(() -> { +- this.getPoiManager().add(blockpos1, holder); +- DebugPackets.sendPoiAddedPacket(this, blockpos1); ++ this.getPoiManager().add(blockposition1, holder); ++ DebugPackets.sendPoiAddedPacket(this, blockposition1); + }); + }); + } +@@ -1388,20 +1554,20 @@ + return this.getChunkSource().getPoiManager(); + } + +- public boolean isVillage(BlockPos blockpos) { +- return this.isCloseToVillage(blockpos, 1); ++ public boolean isVillage(BlockPos pos) { ++ return this.isCloseToVillage(pos, 1); + } + +- public boolean isVillage(SectionPos sectionpos) { +- return this.isVillage(sectionpos.center()); ++ public boolean isVillage(SectionPos pos) { ++ return this.isVillage(pos.center()); + } + +- public boolean isCloseToVillage(BlockPos blockpos, int i) { +- return i > 6 ? false : this.sectionsToVillage(SectionPos.of(blockpos)) <= i; ++ public boolean isCloseToVillage(BlockPos pos, int sections) { ++ return sections > 6 ? false : this.sectionsToVillage(SectionPos.of(pos)) <= sections; + } + +- public int sectionsToVillage(SectionPos sectionpos) { +- return this.getPoiManager().sectionsToVillage(sectionpos); ++ public int sectionsToVillage(SectionPos pos) { ++ return this.getPoiManager().sectionsToVillage(pos); + } + + public Raids getRaids() { +@@ -1409,28 +1575,28 @@ + } + + @Nullable +- public Raid getRaidAt(BlockPos blockpos) { +- return this.raids.getNearbyRaid(blockpos, 9216); ++ public Raid getRaidAt(BlockPos pos) { ++ return this.raids.getNearbyRaid(pos, 9216); + } + +- public boolean isRaided(BlockPos blockpos) { +- return this.getRaidAt(blockpos) != null; ++ public boolean isRaided(BlockPos pos) { ++ return this.getRaidAt(pos) != null; + } + +- public void onReputationEvent(ReputationEventType reputationeventtype, Entity entity, ReputationEventHandler reputationeventhandler) { +- reputationeventhandler.onReputationEventFrom(reputationeventtype, entity); ++ public void onReputationEvent(ReputationEventType type, Entity target, ReputationEventHandler host) { ++ host.onReputationEventFrom(type, target); + } + + public void saveDebugReport(Path path) throws IOException { +- ChunkMap chunkmap = this.getChunkSource().chunkMap; ++ ChunkMap playerchunkmap = this.getChunkSource().chunkMap; + BufferedWriter bufferedwriter = Files.newBufferedWriter(path.resolve("stats.txt")); + + try { +- bufferedwriter.write(String.format(Locale.ROOT, "spawning_chunks: %d\n", chunkmap.getDistanceManager().getNaturalSpawnChunkCount())); +- NaturalSpawner.SpawnState naturalspawner_spawnstate = this.getChunkSource().getLastSpawnState(); ++ bufferedwriter.write(String.format(Locale.ROOT, "spawning_chunks: %d\n", playerchunkmap.getDistanceManager().getNaturalSpawnChunkCount())); ++ NaturalSpawner.SpawnState spawnercreature_d = this.getChunkSource().getLastSpawnState(); + +- if (naturalspawner_spawnstate != null) { +- ObjectIterator objectiterator = naturalspawner_spawnstate.getMobCategoryCounts().object2IntEntrySet().iterator(); ++ if (spawnercreature_d != null) { ++ ObjectIterator objectiterator = spawnercreature_d.getMobCategoryCounts().object2IntEntrySet().iterator(); + + while (objectiterator.hasNext()) { + Entry entry = (Entry) objectiterator.next(); +@@ -1443,7 +1609,7 @@ + bufferedwriter.write(String.format(Locale.ROOT, "block_entity_tickers: %d\n", this.blockEntityTickers.size())); + bufferedwriter.write(String.format(Locale.ROOT, "block_ticks: %d\n", this.getBlockTicks().count())); + bufferedwriter.write(String.format(Locale.ROOT, "fluid_ticks: %d\n", this.getFluidTicks().count())); +- bufferedwriter.write("distance_manager: " + chunkmap.getDistanceManager().getDebugStatus() + "\n"); ++ bufferedwriter.write("distance_manager: " + playerchunkmap.getDistanceManager().getDebugStatus() + "\n"); + bufferedwriter.write(String.format(Locale.ROOT, "pending_tasks: %d\n", this.getChunkSource().getPendingTasksCount())); + } catch (Throwable throwable) { + if (bufferedwriter != null) { +@@ -1488,7 +1654,7 @@ + BufferedWriter bufferedwriter2 = Files.newBufferedWriter(path1); + + try { +- chunkmap.dumpChunks(bufferedwriter2); ++ playerchunkmap.dumpChunks(bufferedwriter2); + } catch (Throwable throwable4) { + if (bufferedwriter2 != null) { + try { +@@ -1570,52 +1736,55 @@ + + } + +- private static void dumpEntities(Writer writer, Iterable iterable) throws IOException { +- CsvOutput csvoutput = CsvOutput.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("uuid").addColumn("type").addColumn("alive").addColumn("display_name").addColumn("custom_name").build(writer); +- Iterator iterator = iterable.iterator(); ++ private static void dumpEntities(Writer writer, Iterable entities) throws IOException { ++ CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("uuid").addColumn("type").addColumn("alive").addColumn("display_name").addColumn("custom_name").build(writer); ++ Iterator iterator = entities.iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); +- Component component = entity.getCustomName(); +- Component component1 = entity.getDisplayName(); ++ Component ichatbasecomponent = entity.getCustomName(); ++ Component ichatbasecomponent1 = entity.getDisplayName(); + +- csvoutput.writeRow(entity.getX(), entity.getY(), entity.getZ(), entity.getUUID(), BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()), entity.isAlive(), component1.getString(), component != null ? component.getString() : null); ++ csvwriter.writeRow(entity.getX(), entity.getY(), entity.getZ(), entity.getUUID(), BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()), entity.isAlive(), ichatbasecomponent1.getString(), ichatbasecomponent != null ? ichatbasecomponent.getString() : null); + } + + } + +- private void dumpBlockEntityTickers(Writer writer) throws IOException { +- CsvOutput csvoutput = CsvOutput.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("type").build(writer); ++ private void dumpBlockEntityTickers(Writer output) throws IOException { ++ CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("type").build(output); + Iterator iterator = this.blockEntityTickers.iterator(); + + while (iterator.hasNext()) { + TickingBlockEntity tickingblockentity = (TickingBlockEntity) iterator.next(); +- BlockPos blockpos = tickingblockentity.getPos(); ++ BlockPos blockposition = tickingblockentity.getPos(); + +- csvoutput.writeRow(blockpos.getX(), blockpos.getY(), blockpos.getZ(), tickingblockentity.getType()); ++ csvwriter.writeRow(blockposition.getX(), blockposition.getY(), blockposition.getZ(), tickingblockentity.getType()); + } + + } + + @VisibleForTesting +- public void clearBlockEvents(BoundingBox boundingbox) { +- this.blockEvents.removeIf((blockeventdata) -> { +- return boundingbox.isInside(blockeventdata.pos()); ++ public void clearBlockEvents(BoundingBox boundingBox) { ++ this.blockEvents.removeIf((blockactiondata) -> { ++ return boundingBox.isInside(blockactiondata.pos()); + }); + } + + @Override +- @Override +- public void blockUpdated(BlockPos blockpos, Block block) { ++ public void blockUpdated(BlockPos pos, Block block) { + if (!this.isDebug()) { +- this.updateNeighborsAt(blockpos, block); ++ // CraftBukkit start ++ if (populating) { ++ return; ++ } ++ // CraftBukkit end ++ this.updateNeighborsAt(pos, block); + } + + } + + @Override +- @Override +- public float getShade(Direction direction, boolean flag) { ++ public float getShade(Direction direction, boolean shade) { + return 1.0F; + } + +@@ -1623,19 +1792,17 @@ + return this.getEntities().getAll(); + } + +- @Override + public String toString() { + return "ServerLevel[" + this.serverLevelData.getLevelName() + "]"; + } + + public boolean isFlat() { +- return this.server.getWorldData().isFlatWorld(); ++ return this.serverLevelData.isFlatWorld(); // CraftBukkit + } + + @Override +- @Override + public long getSeed() { +- return this.server.getWorldData().worldGenOptions().seed(); ++ return this.serverLevelData.worldGenOptions().seed(); // CraftBukkit + } + + @Nullable +@@ -1644,7 +1811,6 @@ + } + + @Override +- @Override + public ServerLevel getLevel() { + return this; + } +@@ -1656,19 +1822,19 @@ + }), this.blockEntityTickers.size(), getTypeCount(this.blockEntityTickers, TickingBlockEntity::getType), this.getBlockTicks().count(), this.getFluidTicks().count(), this.gatherChunkSourceStats()); + } + +- private static String getTypeCount(Iterable iterable, Function function) { ++ private static String getTypeCount(Iterable objects, Function typeGetter) { + try { + Object2IntOpenHashMap object2intopenhashmap = new Object2IntOpenHashMap(); +- Iterator iterator = iterable.iterator(); ++ Iterator iterator = objects.iterator(); // CraftBukkit - decompile error + + while (iterator.hasNext()) { + T t0 = iterator.next(); +- String s = (String) function.apply(t0); ++ String s = (String) typeGetter.apply(t0); + + object2intopenhashmap.addTo(s, 1); + } + +- return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(Entry::getIntValue).reversed()).limit(5L).map((entry) -> { ++ return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(Entry::getIntValue).reversed()).limit(5L).map((entry) -> { // CraftBukkit - decompile error + String s1 = (String) entry.getKey(); + + return s1 + ":" + entry.getIntValue(); +@@ -1678,87 +1844,99 @@ + } + } + +- public static void makeObsidianPlatform(ServerLevel serverlevel) { +- BlockPos blockpos = ServerLevel.END_SPAWN_POINT; +- int i = blockpos.getX(); +- int j = blockpos.getY() - 2; +- int k = blockpos.getZ(); ++ public static void makeObsidianPlatform(ServerLevel serverLevel) { ++ // CraftBukkit start ++ ServerLevel.makeObsidianPlatform(serverLevel, null); ++ } + +- BlockPos.betweenClosed(i - 2, j + 1, k - 2, i + 2, j + 3, k + 2).forEach((blockpos1) -> { +- serverlevel.setBlockAndUpdate(blockpos1, Blocks.AIR.defaultBlockState()); ++ public static void makeObsidianPlatform(ServerLevel worldserver, Entity entity) { ++ // CraftBukkit end ++ BlockPos blockposition = ServerLevel.END_SPAWN_POINT; ++ int i = blockposition.getX(); ++ int j = blockposition.getY() - 2; ++ int k = blockposition.getZ(); ++ ++ // CraftBukkit start ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(worldserver); ++ BlockPos.betweenClosed(i - 2, j + 1, k - 2, i + 2, j + 3, k + 2).forEach((blockposition1) -> { ++ blockList.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3); + }); +- BlockPos.betweenClosed(i - 2, j, k - 2, i + 2, j, k + 2).forEach((blockpos1) -> { +- serverlevel.setBlockAndUpdate(blockpos1, Blocks.OBSIDIAN.defaultBlockState()); ++ BlockPos.betweenClosed(i - 2, j, k - 2, i + 2, j, k + 2).forEach((blockposition1) -> { ++ blockList.setBlock(blockposition1, Blocks.OBSIDIAN.defaultBlockState(), 3); + }); ++ org.bukkit.World bworld = worldserver.getWorld(); ++ org.bukkit.event.world.PortalCreateEvent portalEvent = new org.bukkit.event.world.PortalCreateEvent((List) (List) blockList.getList(), bworld, (entity == null) ? null : entity.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM); ++ ++ worldserver.getCraftServer().getPluginManager().callEvent(portalEvent); ++ if (!portalEvent.isCancelled()) { ++ blockList.updateList(); ++ } ++ // CraftBukkit end + } + + @Override +- @Override +- protected LevelEntityGetter getEntities() { ++ public LevelEntityGetter getEntities() { + return this.entityManager.getEntityGetter(); + } + +- public void addLegacyChunkEntities(Stream stream) { +- this.entityManager.addLegacyChunkEntities(stream); ++ public void addLegacyChunkEntities(Stream entities) { ++ this.entityManager.addLegacyChunkEntities(entities); + } + +- public void addWorldGenChunkEntities(Stream stream) { +- this.entityManager.addWorldGenChunkEntities(stream); ++ public void addWorldGenChunkEntities(Stream entities) { ++ this.entityManager.addWorldGenChunkEntities(entities); + } + +- public void startTickingChunk(LevelChunk levelchunk) { +- levelchunk.unpackTicks(this.getLevelData().getGameTime()); ++ public void startTickingChunk(LevelChunk chunk) { ++ chunk.unpackTicks(this.getLevelData().getGameTime()); + } + +- public void onStructureStartsAvailable(ChunkAccess chunkaccess) { ++ public void onStructureStartsAvailable(ChunkAccess chunk) { + this.server.execute(() -> { +- this.structureCheck.onStructureLoad(chunkaccess.getPos(), chunkaccess.getAllStarts()); ++ this.structureCheck.onStructureLoad(chunk.getPos(), chunk.getAllStarts()); + }); + } + + @Override +- @Override + public void close() throws IOException { + super.close(); + this.entityManager.close(); + } + + @Override +- @Override + public String gatherChunkSourceStats() { + String s = this.chunkSource.gatherStats(); + + return "Chunks[S] W: " + s + " E: " + this.entityManager.gatherStats(); + } + +- public boolean areEntitiesLoaded(long i) { +- return this.entityManager.areEntitiesLoaded(i); ++ public boolean areEntitiesLoaded(long chunkPos) { ++ return this.entityManager.areEntitiesLoaded(chunkPos); + } + +- private boolean isPositionTickingWithEntitiesLoaded(long i) { +- return this.areEntitiesLoaded(i) && this.chunkSource.isPositionTicking(i); ++ private boolean isPositionTickingWithEntitiesLoaded(long chunkPos) { ++ return this.areEntitiesLoaded(chunkPos) && this.chunkSource.isPositionTicking(chunkPos); + } + +- public boolean isPositionEntityTicking(BlockPos blockpos) { +- return this.entityManager.canPositionTick(blockpos) && this.chunkSource.chunkMap.getDistanceManager().inEntityTickingRange(ChunkPos.asLong(blockpos)); ++ public boolean isPositionEntityTicking(BlockPos pos) { ++ return this.entityManager.canPositionTick(pos) && this.chunkSource.chunkMap.getDistanceManager().inEntityTickingRange(ChunkPos.asLong(pos)); + } + +- public boolean isNaturalSpawningAllowed(BlockPos blockpos) { +- return this.entityManager.canPositionTick(blockpos); ++ public boolean isNaturalSpawningAllowed(BlockPos pos) { ++ return this.entityManager.canPositionTick(pos); + } + +- public boolean isNaturalSpawningAllowed(ChunkPos chunkpos) { +- return this.entityManager.canPositionTick(chunkpos); ++ public boolean isNaturalSpawningAllowed(ChunkPos chunkPos) { ++ return this.entityManager.canPositionTick(chunkPos); + } + + @Override +- @Override + public FeatureFlagSet enabledFeatures() { + return this.server.getWorldData().enabledFeatures(); + } + +- public RandomSource getRandomSequence(ResourceLocation resourcelocation) { +- return this.randomSequences.get(resourcelocation); ++ public RandomSource getRandomSequence(ResourceLocation location) { ++ return this.randomSequences.get(location); + } + + public RandomSequences getRandomSequences() { +@@ -1766,50 +1944,44 @@ + } + + @Override +- @Override +- public CrashReportCategory fillReportDetails(CrashReport crashreport) { +- CrashReportCategory crashreportcategory = super.fillReportDetails(crashreport); ++ public CrashReportCategory fillReportDetails(CrashReport report) { ++ CrashReportCategory crashreportsystemdetails = super.fillReportDetails(report); + +- crashreportcategory.setDetail("Loaded entity count", () -> { ++ crashreportsystemdetails.setDetail("Loaded entity count", () -> { + return String.valueOf(this.entityManager.count()); + }); +- return crashreportcategory; ++ return crashreportsystemdetails; + } + +- private final class EntityCallbacks implements LevelCallback { ++ private final class a implements LevelCallback { + +- EntityCallbacks() {} ++ a() {} + +- @Override + public void onCreated(Entity entity) {} + +- @Override + public void onDestroyed(Entity entity) { + ServerLevel.this.getScoreboard().entityRemoved(entity); + } + +- @Override + public void onTickingStart(Entity entity) { + ServerLevel.this.entityTickList.add(entity); + } + +- @Override + public void onTickingEnd(Entity entity) { + ServerLevel.this.entityTickList.remove(entity); + } + +- @Override + public void onTrackingStart(Entity entity) { + ServerLevel.this.getChunkSource().addEntity(entity); + if (entity instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) entity; ++ ServerPlayer entityplayer = (ServerPlayer) entity; + +- ServerLevel.this.players.add(serverplayer); ++ ServerLevel.this.players.add(entityplayer); + ServerLevel.this.updateSleepingPlayerList(); + } + + if (entity instanceof Mob) { +- Mob mob = (Mob) entity; ++ Mob entityinsentient = (Mob) entity; + + if (ServerLevel.this.isUpdatingNavigations) { + String s = "onTrackingStart called during navigation iteration"; +@@ -1817,36 +1989,37 @@ + Util.logAndPauseIfInIde("onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")); + } + +- ServerLevel.this.navigatingMobs.add(mob); ++ ServerLevel.this.navigatingMobs.add(entityinsentient); + } + + if (entity instanceof EnderDragon) { +- EnderDragon enderdragon = (EnderDragon) entity; +- EnderDragonPart[] aenderdragonpart = enderdragon.getSubEntities(); +- int i = aenderdragonpart.length; ++ EnderDragon entityenderdragon = (EnderDragon) entity; ++ EnderDragonPart[] aentitycomplexpart = entityenderdragon.getSubEntities(); ++ int i = aentitycomplexpart.length; + + for (int j = 0; j < i; ++j) { +- EnderDragonPart enderdragonpart = aenderdragonpart[j]; ++ EnderDragonPart entitycomplexpart = aentitycomplexpart[j]; + +- ServerLevel.this.dragonParts.put(enderdragonpart.getId(), enderdragonpart); ++ ServerLevel.this.dragonParts.put(entitycomplexpart.getId(), entitycomplexpart); + } + } + + entity.updateDynamicGameEventListener(DynamicGameEventListener::add); ++ entity.inWorld = true; // CraftBukkit - Mark entity as in world ++ entity.valid = true; // CraftBukkit + } + +- @Override + public void onTrackingEnd(Entity entity) { + ServerLevel.this.getChunkSource().removeEntity(entity); + if (entity instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) entity; ++ ServerPlayer entityplayer = (ServerPlayer) entity; + +- ServerLevel.this.players.remove(serverplayer); ++ ServerLevel.this.players.remove(entityplayer); + ServerLevel.this.updateSleepingPlayerList(); + } + + if (entity instanceof Mob) { +- Mob mob = (Mob) entity; ++ Mob entityinsentient = (Mob) entity; + + if (ServerLevel.this.isUpdatingNavigations) { + String s = "onTrackingStart called during navigation iteration"; +@@ -1854,25 +2027,32 @@ + Util.logAndPauseIfInIde("onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")); + } + +- ServerLevel.this.navigatingMobs.remove(mob); ++ ServerLevel.this.navigatingMobs.remove(entityinsentient); + } + + if (entity instanceof EnderDragon) { +- EnderDragon enderdragon = (EnderDragon) entity; +- EnderDragonPart[] aenderdragonpart = enderdragon.getSubEntities(); +- int i = aenderdragonpart.length; ++ EnderDragon entityenderdragon = (EnderDragon) entity; ++ EnderDragonPart[] aentitycomplexpart = entityenderdragon.getSubEntities(); ++ int i = aentitycomplexpart.length; + + for (int j = 0; j < i; ++j) { +- EnderDragonPart enderdragonpart = aenderdragonpart[j]; ++ EnderDragonPart entitycomplexpart = aentitycomplexpart[j]; + +- ServerLevel.this.dragonParts.remove(enderdragonpart.getId()); ++ ServerLevel.this.dragonParts.remove(entitycomplexpart.getId()); + } + } + + entity.updateDynamicGameEventListener(DynamicGameEventListener::remove); ++ // CraftBukkit start ++ entity.valid = false; ++ if (!(entity instanceof ServerPlayer)) { ++ for (ServerPlayer player : players) { ++ player.getBukkitEntity().onEntityRemove(entity); ++ } ++ } ++ // CraftBukkit end + } + +- @Override + public void onSectionChange(Entity entity) { + entity.updateDynamicGameEventListener(DynamicGameEventListener::move); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/level/ServerPlayer.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/level/ServerPlayer.java.patch new file mode 100644 index 0000000000..93b505809a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/level/ServerPlayer.java.patch @@ -0,0 +1,2612 @@ +--- a/net/minecraft/server/level/ServerPlayer.java ++++ b/net/minecraft/server/level/ServerPlayer.java +@@ -33,6 +33,7 @@ + import net.minecraft.core.registries.BuiltInRegistries; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.Tag; + import net.minecraft.network.PacketSendListener; + import net.minecraft.network.chat.ChatType; + import net.minecraft.network.chat.CommonComponents; +@@ -94,8 +95,8 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.util.Unit; + import net.minecraft.world.Container; +-import net.minecraft.world.InteractionHand; +-import net.minecraft.world.MenuProvider; ++import net.minecraft.world.EnumHand; ++import net.minecraft.world.ITileInventory; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.effect.MobEffects; +@@ -118,6 +119,7 @@ + import net.minecraft.world.entity.projectile.AbstractArrow; + import net.minecraft.world.entity.vehicle.AbstractMinecart; + import net.minecraft.world.entity.vehicle.Boat; ++import net.minecraft.world.food.FoodData; + import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.inventory.ContainerListener; + import net.minecraft.world.inventory.ContainerSynchronizer; +@@ -131,6 +133,7 @@ + import net.minecraft.world.item.ServerItemCooldowns; + import net.minecraft.world.item.WrittenBookItem; + import net.minecraft.world.item.crafting.RecipeHolder; ++import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.item.trading.MerchantOffers; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.GameRules; +@@ -138,24 +141,50 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.ChestBlock; + import net.minecraft.world.level.block.HorizontalDirectionalBlock; + import net.minecraft.world.level.block.NetherPortalBlock; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.CommandBlockEntity; + import net.minecraft.world.level.block.entity.SignBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.border.WorldBorder; ++import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.portal.PortalInfo; +-import net.minecraft.world.level.storage.LevelData; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.scores.PlayerTeam; + import net.minecraft.world.scores.ScoreAccess; + import net.minecraft.world.scores.ScoreHolder; ++import org.slf4j.Logger; ++import net.minecraft.world.damagesource.CombatTracker; ++import net.minecraft.world.scores.Scoreboard; + import net.minecraft.world.scores.Team; + import net.minecraft.world.scores.criteria.ObjectiveCriteria; +-import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.WeatherType; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.CraftWorldBorder; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.event.CraftPortalEvent; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftDimensionUtil; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.entity.EntityExhaustionEvent; ++import org.bukkit.event.player.PlayerBedLeaveEvent; ++import org.bukkit.event.player.PlayerChangedMainHandEvent; ++import org.bukkit.event.player.PlayerChangedWorldEvent; ++import org.bukkit.event.player.PlayerLocaleChangeEvent; ++import org.bukkit.event.player.PlayerPortalEvent; ++import org.bukkit.event.player.PlayerSpawnChangeEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; ++import org.bukkit.event.player.PlayerToggleSneakEvent; ++import org.bukkit.inventory.MainHand; ++// CraftBukkit end + + public class ServerPlayer extends Player { + +@@ -177,14 +206,14 @@ + private float lastSentHealth = -1.0E8F; + private int lastSentFood = -99999999; + private boolean lastFoodSaturationZero = true; +- private int lastSentExp = -99999999; +- private int spawnInvulnerableTime = 60; ++ public int lastSentExp = -99999999; ++ public int spawnInvulnerableTime = 60; + private ChatVisiblity chatVisibility; + private boolean canChatColor; + private long lastActionTime; + @Nullable + private Entity camera; +- private boolean isChangingDimension; ++ public boolean isChangingDimension; + private boolean seenCredits; + private final ServerRecipeBook recipeBook; + @Nullable +@@ -192,7 +221,7 @@ + private int levitationStartTime; + private boolean disconnected; + private int requestedViewDistance; +- private String language; ++ public String language = "en_us"; // CraftBukkit - default + @Nullable + private Vec3 startingToFallPosition; + @Nullable +@@ -217,8 +246,22 @@ + private int containerCounter; + public boolean wonGame; + +- public ServerPlayer(MinecraftServer minecraftserver, ServerLevel serverlevel, GameProfile gameprofile, ClientInformation clientinformation) { +- super(serverlevel, serverlevel.getSharedSpawnPos(), serverlevel.getSharedSpawnAngle(), gameprofile); ++ // CraftBukkit start ++ public String displayName; ++ public Component listName; ++ public org.bukkit.Location compassTarget; ++ public int newExp = 0; ++ public int newLevel = 0; ++ public int newTotalExp = 0; ++ public boolean keepLevel = false; ++ public double maxHealthCache; ++ public boolean joining = true; ++ public boolean sentListPacket = false; ++ public String kickLeaveMessage = null; // SPIGOT-3034: Forward leave message to PlayerQuitEvent ++ // CraftBukkit end ++ ++ public ServerPlayer(MinecraftServer minecraftserver, ServerLevel worldserver, GameProfile gameprofile, ClientInformation clientinformation) { ++ super(worldserver, worldserver.getSharedSpawnPos(), worldserver.getSharedSpawnAngle(), gameprofile); + this.chatVisibility = ChatVisiblity.FULL; + this.canChatColor = true; + this.lastActionTime = Util.getMillis(); +@@ -231,55 +274,49 @@ + this.wardenSpawnTracker = new WardenSpawnTracker(0, 0, 0); + this.containerSynchronizer = new ContainerSynchronizer() { + @Override +- @Override +- public void sendInitialData(AbstractContainerMenu abstractcontainermenu, NonNullList nonnulllist, ItemStack itemstack, int[] aint) { +- ServerPlayer.this.connection.send(new ClientboundContainerSetContentPacket(abstractcontainermenu.containerId, abstractcontainermenu.incrementStateId(), nonnulllist, itemstack)); ++ public void sendInitialData(AbstractContainerMenu container, NonNullList items, ItemStack carriedItem, int[] initialData) { ++ ServerPlayer.this.connection.send(new ClientboundContainerSetContentPacket(container.containerId, container.incrementStateId(), items, carriedItem)); + +- for (int i = 0; i < aint.length; ++i) { +- this.broadcastDataValue(abstractcontainermenu, i, aint[i]); ++ for (int i = 0; i < initialData.length; ++i) { ++ this.broadcastDataValue(container, i, initialData[i]); + } + + } + + @Override +- @Override +- public void sendSlotChange(AbstractContainerMenu abstractcontainermenu, int i, ItemStack itemstack) { +- ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(abstractcontainermenu.containerId, abstractcontainermenu.incrementStateId(), i, itemstack)); ++ public void sendSlotChange(AbstractContainerMenu container, int slot, ItemStack itemStack) { ++ ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(container.containerId, container.incrementStateId(), slot, itemStack)); + } + + @Override +- @Override +- public void sendCarriedChange(AbstractContainerMenu abstractcontainermenu, ItemStack itemstack) { +- ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(-1, abstractcontainermenu.incrementStateId(), -1, itemstack)); ++ public void sendCarriedChange(AbstractContainerMenu containerMenu, ItemStack stack) { ++ ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(-1, containerMenu.incrementStateId(), -1, stack)); + } + + @Override +- @Override +- public void sendDataChange(AbstractContainerMenu abstractcontainermenu, int i, int j) { +- this.broadcastDataValue(abstractcontainermenu, i, j); ++ public void sendDataChange(AbstractContainerMenu container, int id, int value) { ++ this.broadcastDataValue(container, id, value); + } + +- private void broadcastDataValue(AbstractContainerMenu abstractcontainermenu, int i, int j) { +- ServerPlayer.this.connection.send(new ClientboundContainerSetDataPacket(abstractcontainermenu.containerId, i, j)); ++ private void broadcastDataValue(AbstractContainerMenu container, int id, int value) { ++ ServerPlayer.this.connection.send(new ClientboundContainerSetDataPacket(container.containerId, id, value)); + } + }; + this.containerListener = new ContainerListener() { + @Override +- @Override +- public void slotChanged(AbstractContainerMenu abstractcontainermenu, int i, ItemStack itemstack) { +- Slot slot = abstractcontainermenu.getSlot(i); ++ public void slotChanged(AbstractContainerMenu containerToSend, int dataSlotIndex, ItemStack stack) { ++ Slot slot = containerToSend.getSlot(dataSlotIndex); + + if (!(slot instanceof ResultSlot)) { + if (slot.container == ServerPlayer.this.getInventory()) { +- CriteriaTriggers.INVENTORY_CHANGED.trigger(ServerPlayer.this, ServerPlayer.this.getInventory(), itemstack); ++ CriteriaTriggers.INVENTORY_CHANGED.trigger(ServerPlayer.this, ServerPlayer.this.getInventory(), stack); + } + + } + } + + @Override +- @Override +- public void dataChanged(AbstractContainerMenu abstractcontainermenu, int i, int j) {} ++ public void dataChanged(AbstractContainerMenu containerMenu, int dataSlotIndex, int value) {} + }; + this.textFilter = minecraftserver.createTextFilterForPlayer(this); + this.gameMode = minecraftserver.createGameModeForPlayer(this); +@@ -287,16 +324,23 @@ + this.stats = minecraftserver.getPlayerList().getPlayerStats(this); + this.advancements = minecraftserver.getPlayerList().getPlayerAdvancements(this); + this.setMaxUpStep(1.0F); +- this.fudgeSpawnLocation(serverlevel); ++ this.fudgeSpawnLocation(worldserver); + this.updateOptions(clientinformation); ++ ++ // CraftBukkit start ++ this.displayName = this.getScoreboardName(); ++ this.bukkitPickUpLoot = true; ++ this.maxHealthCache = this.getMaxHealth(); + } + +- private void fudgeSpawnLocation(ServerLevel serverlevel) { +- BlockPos blockpos = serverlevel.getSharedSpawnPos(); ++ // Yes, this doesn't match Vanilla, but it's the best we can do for now. ++ // If this is an issue, PRs are welcome ++ public final BlockPos getSpawnPoint(ServerLevel worldserver) { ++ BlockPos blockposition = worldserver.getSharedSpawnPos(); + +- if (serverlevel.dimensionType().hasSkyLight() && serverlevel.getServer().getWorldData().getGameType() != GameType.ADVENTURE) { +- int i = Math.max(0, this.server.getSpawnRadius(serverlevel)); +- int j = Mth.floor(serverlevel.getWorldBorder().getDistanceToBorder((double) blockpos.getX(), (double) blockpos.getZ())); ++ if (worldserver.dimensionType().hasSkyLight() && worldserver.serverLevelData.getGameType() != GameType.ADVENTURE) { ++ int i = Math.max(0, this.server.getSpawnRadius(worldserver)); ++ int j = Mth.floor(worldserver.getWorldBorder().getDistanceToBorder((double) blockposition.getX(), (double) blockposition.getZ())); + + if (j < i) { + i = j; +@@ -316,35 +360,71 @@ + int i2 = (k1 + j1 * l1) % i1; + int j2 = i2 % (i * 2 + 1); + int k2 = i2 / (i * 2 + 1); +- BlockPos blockpos1 = PlayerRespawnLogic.getOverworldRespawnPos(serverlevel, blockpos.getX() + j2 - i, blockpos.getZ() + k2 - i); ++ BlockPos blockposition1 = PlayerRespawnLogic.getOverworldRespawnPos(worldserver, blockposition.getX() + j2 - i, blockposition.getZ() + k2 - i); + +- if (blockpos1 != null) { +- this.moveTo(blockpos1, 0.0F, 0.0F); +- if (serverlevel.noCollision((Entity) this)) { ++ if (blockposition1 != null) { ++ return blockposition1; ++ } ++ } ++ } ++ ++ return blockposition; ++ } ++ // CraftBukkit end ++ ++ private void fudgeSpawnLocation(ServerLevel level) { ++ BlockPos blockposition = level.getSharedSpawnPos(); ++ ++ if (level.dimensionType().hasSkyLight() && level.serverLevelData.getGameType() != GameType.ADVENTURE) { // CraftBukkit ++ int i = Math.max(0, this.server.getSpawnRadius(level)); ++ int j = Mth.floor(level.getWorldBorder().getDistanceToBorder((double) blockposition.getX(), (double) blockposition.getZ())); ++ ++ if (j < i) { ++ i = j; ++ } ++ ++ if (j <= 1) { ++ i = 1; ++ } ++ ++ long k = (long) (i * 2 + 1); ++ long l = k * k; ++ int i1 = l > 2147483647L ? Integer.MAX_VALUE : (int) l; ++ int j1 = this.getCoprime(i1); ++ int k1 = RandomSource.create().nextInt(i1); ++ ++ for (int l1 = 0; l1 < i1; ++l1) { ++ int i2 = (k1 + j1 * l1) % i1; ++ int j2 = i2 % (i * 2 + 1); ++ int k2 = i2 / (i * 2 + 1); ++ BlockPos blockposition1 = PlayerRespawnLogic.getOverworldRespawnPos(level, blockposition.getX() + j2 - i, blockposition.getZ() + k2 - i); ++ ++ if (blockposition1 != null) { ++ this.moveTo(blockposition1, 0.0F, 0.0F); ++ if (level.noCollision((Entity) this)) { + break; + } + } + } + } else { +- this.moveTo(blockpos, 0.0F, 0.0F); ++ this.moveTo(blockposition, 0.0F, 0.0F); + +- while (!serverlevel.noCollision((Entity) this) && this.getY() < (double) (serverlevel.getMaxBuildHeight() - 1)) { ++ while (!level.noCollision((Entity) this) && this.getY() < (double) (level.getMaxBuildHeight() - 1)) { + this.setPos(this.getX(), this.getY() + 1.0D, this.getZ()); + } + } + + } + +- private int getCoprime(int i) { +- return i <= 16 ? i - 1 : 17; ++ private int getCoprime(int spawnArea) { ++ return spawnArea <= 16 ? spawnArea - 1 : 17; + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("warden_spawn_tracker", 10)) { +- DataResult dataresult = WardenSpawnTracker.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compoundtag.get("warden_spawn_tracker"))); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("warden_spawn_tracker", 10)) { ++ DataResult dataresult = WardenSpawnTracker.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compound.get("warden_spawn_tracker"))); // CraftBukkit - decompile error + Logger logger = ServerPlayer.LOGGER; + + Objects.requireNonNull(logger); +@@ -353,27 +433,36 @@ + }); + } + +- if (compoundtag.contains("enteredNetherPosition", 10)) { +- CompoundTag compoundtag1 = compoundtag.getCompound("enteredNetherPosition"); ++ if (compound.contains("enteredNetherPosition", 10)) { ++ CompoundTag nbttagcompound1 = compound.getCompound("enteredNetherPosition"); + +- this.enteredNetherPosition = new Vec3(compoundtag1.getDouble("x"), compoundtag1.getDouble("y"), compoundtag1.getDouble("z")); ++ this.enteredNetherPosition = new Vec3(nbttagcompound1.getDouble("x"), nbttagcompound1.getDouble("y"), nbttagcompound1.getDouble("z")); + } + +- this.seenCredits = compoundtag.getBoolean("seenCredits"); +- if (compoundtag.contains("recipeBook", 10)) { +- this.recipeBook.fromNbt(compoundtag.getCompound("recipeBook"), this.server.getRecipeManager()); ++ this.seenCredits = compound.getBoolean("seenCredits"); ++ if (compound.contains("recipeBook", 10)) { ++ this.recipeBook.fromNbt(compound.getCompound("recipeBook"), this.server.getRecipeManager()); + } ++ this.getBukkitEntity().readExtraData(compound); // CraftBukkit + + if (this.isSleeping()) { + this.stopSleeping(); + } + +- if (compoundtag.contains("SpawnX", 99) && compoundtag.contains("SpawnY", 99) && compoundtag.contains("SpawnZ", 99)) { +- this.respawnPosition = new BlockPos(compoundtag.getInt("SpawnX"), compoundtag.getInt("SpawnY"), compoundtag.getInt("SpawnZ")); +- this.respawnForced = compoundtag.getBoolean("SpawnForced"); +- this.respawnAngle = compoundtag.getFloat("SpawnAngle"); +- if (compoundtag.contains("SpawnDimension")) { +- DataResult dataresult1 = Level.RESOURCE_KEY_CODEC.parse(NbtOps.INSTANCE, compoundtag.get("SpawnDimension")); ++ // CraftBukkit start ++ String spawnWorld = compound.getString("SpawnWorld"); ++ CraftWorld oldWorld = (CraftWorld) Bukkit.getWorld(spawnWorld); ++ if (oldWorld != null) { ++ this.respawnDimension = oldWorld.getHandle().dimension(); ++ } ++ // CraftBukkit end ++ ++ if (compound.contains("SpawnX", 99) && compound.contains("SpawnY", 99) && compound.contains("SpawnZ", 99)) { ++ this.respawnPosition = new BlockPos(compound.getInt("SpawnX"), compound.getInt("SpawnY"), compound.getInt("SpawnZ")); ++ this.respawnForced = compound.getBoolean("SpawnForced"); ++ this.respawnAngle = compound.getFloat("SpawnAngle"); ++ if (compound.contains("SpawnDimension")) { ++ DataResult> dataresult1 = Level.RESOURCE_KEY_CODEC.parse(NbtOps.INSTANCE, compound.get("SpawnDimension")); // CraftBukkit - decompile error + Logger logger1 = ServerPlayer.LOGGER; + + Objects.requireNonNull(logger1); +@@ -384,88 +473,122 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- DataResult dataresult = WardenSpawnTracker.CODEC.encodeStart(NbtOps.INSTANCE, this.wardenSpawnTracker); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ DataResult dataresult = WardenSpawnTracker.CODEC.encodeStart(NbtOps.INSTANCE, this.wardenSpawnTracker); // CraftBukkit - decompile error + Logger logger = ServerPlayer.LOGGER; + + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((tag) -> { +- compoundtag.put("warden_spawn_tracker", tag); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("warden_spawn_tracker", nbtbase); + }); +- this.storeGameTypes(compoundtag); +- compoundtag.putBoolean("seenCredits", this.seenCredits); ++ this.storeGameTypes(compound); ++ compound.putBoolean("seenCredits", this.seenCredits); + if (this.enteredNetherPosition != null) { +- CompoundTag compoundtag1 = new CompoundTag(); ++ CompoundTag nbttagcompound1 = new CompoundTag(); + +- compoundtag1.putDouble("x", this.enteredNetherPosition.x); +- compoundtag1.putDouble("y", this.enteredNetherPosition.y); +- compoundtag1.putDouble("z", this.enteredNetherPosition.z); +- compoundtag.put("enteredNetherPosition", compoundtag1); ++ nbttagcompound1.putDouble("x", this.enteredNetherPosition.x); ++ nbttagcompound1.putDouble("y", this.enteredNetherPosition.y); ++ nbttagcompound1.putDouble("z", this.enteredNetherPosition.z); ++ compound.put("enteredNetherPosition", nbttagcompound1); + } + + Entity entity = this.getRootVehicle(); + Entity entity1 = this.getVehicle(); + +- if (entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger()) { +- CompoundTag compoundtag2 = new CompoundTag(); +- CompoundTag compoundtag3 = new CompoundTag(); ++ // CraftBukkit start - handle non-persistent vehicles ++ boolean persistVehicle = true; ++ if (entity1 != null) { ++ Entity vehicle; ++ for (vehicle = entity1; vehicle != null; vehicle = vehicle.getVehicle()) { ++ if (!vehicle.persist) { ++ persistVehicle = false; ++ break; ++ } ++ } ++ } + +- entity.save(compoundtag3); +- compoundtag2.putUUID("Attach", entity1.getUUID()); +- compoundtag2.put("Entity", compoundtag3); +- compoundtag.put("RootVehicle", compoundtag2); ++ if (persistVehicle && entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger()) { ++ // CraftBukkit end ++ CompoundTag nbttagcompound2 = new CompoundTag(); ++ CompoundTag nbttagcompound3 = new CompoundTag(); ++ ++ entity.save(nbttagcompound3); ++ nbttagcompound2.putUUID("Attach", entity1.getUUID()); ++ nbttagcompound2.put("Entity", nbttagcompound3); ++ compound.put("RootVehicle", nbttagcompound2); + } + +- compoundtag.put("recipeBook", this.recipeBook.toNbt()); +- compoundtag.putString("Dimension", this.level().dimension().location().toString()); ++ compound.put("recipeBook", this.recipeBook.toNbt()); ++ compound.putString("Dimension", this.level().dimension().location().toString()); + if (this.respawnPosition != null) { +- compoundtag.putInt("SpawnX", this.respawnPosition.getX()); +- compoundtag.putInt("SpawnY", this.respawnPosition.getY()); +- compoundtag.putInt("SpawnZ", this.respawnPosition.getZ()); +- compoundtag.putBoolean("SpawnForced", this.respawnForced); +- compoundtag.putFloat("SpawnAngle", this.respawnAngle); ++ compound.putInt("SpawnX", this.respawnPosition.getX()); ++ compound.putInt("SpawnY", this.respawnPosition.getY()); ++ compound.putInt("SpawnZ", this.respawnPosition.getZ()); ++ compound.putBoolean("SpawnForced", this.respawnForced); ++ compound.putFloat("SpawnAngle", this.respawnAngle); + dataresult = ResourceLocation.CODEC.encodeStart(NbtOps.INSTANCE, this.respawnDimension.location()); + logger = ServerPlayer.LOGGER; + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((tag) -> { +- compoundtag.put("SpawnDimension", tag); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("SpawnDimension", nbtbase); + }); + } ++ this.getBukkitEntity().setExtraData(compound); // CraftBukkit + + } + +- public void setExperiencePoints(int i) { ++ // CraftBukkit start - World fallback code, either respawn location or global spawn ++ public void spawnIn(Level world) { ++ this.setLevel(world); ++ if (world == null) { ++ this.unsetRemoved(); ++ Vec3 position = null; ++ if (this.respawnDimension != null) { ++ world = this.server.getLevel(this.respawnDimension); ++ if (world != null && this.getRespawnPosition() != null) { ++ position = Player.findRespawnPositionAndUseSpawnBlock((ServerLevel) world, this.getRespawnPosition(), this.getRespawnAngle(), false, false).orElse(null); ++ } ++ } ++ if (world == null || position == null) { ++ world = ((CraftWorld) Bukkit.getServer().getWorlds().get(0)).getHandle(); ++ position = Vec3.atCenterOf(world.getSharedSpawnPos()); ++ } ++ this.setLevel(world); ++ this.setPos(position); ++ } ++ this.gameMode.setLevel((ServerLevel) world); ++ } ++ // CraftBukkit end ++ ++ public void setExperiencePoints(int experiencePoints) { + float f = (float) this.getXpNeededForNextLevel(); + float f1 = (f - 1.0F) / f; + +- this.experienceProgress = Mth.clamp((float) i / f, 0.0F, f1); ++ this.experienceProgress = Mth.clamp((float) experiencePoints / f, 0.0F, f1); + this.lastSentExp = -1; + } + +- public void setExperienceLevels(int i) { +- this.experienceLevel = i; ++ public void setExperienceLevels(int level) { ++ this.experienceLevel = level; + this.lastSentExp = -1; + } + + @Override +- @Override +- public void giveExperienceLevels(int i) { +- super.giveExperienceLevels(i); ++ public void giveExperienceLevels(int levels) { ++ super.giveExperienceLevels(levels); + this.lastSentExp = -1; + } + + @Override +- @Override +- public void onEnchantmentPerformed(ItemStack itemstack, int i) { +- super.onEnchantmentPerformed(itemstack, i); ++ public void onEnchantmentPerformed(ItemStack enchantedItem, int cost) { ++ super.onEnchantmentPerformed(enchantedItem, cost); + this.lastSentExp = -1; + } + +- private void initMenu(AbstractContainerMenu abstractcontainermenu) { +- abstractcontainermenu.addSlotListener(this.containerListener); +- abstractcontainermenu.setSynchronizer(this.containerSynchronizer); ++ public void initMenu(AbstractContainerMenu menu) { ++ menu.addSlotListener(this.containerListener); ++ menu.setSynchronizer(this.containerSynchronizer); + } + + public void initInventoryMenu() { +@@ -473,34 +596,34 @@ + } + + @Override +- @Override + public void onEnterCombat() { + super.onEnterCombat(); + this.connection.send(new ClientboundPlayerCombatEnterPacket()); + } + + @Override +- @Override + public void onLeaveCombat() { + super.onLeaveCombat(); + this.connection.send(new ClientboundPlayerCombatEndPacket(this.getCombatTracker())); + } + + @Override +- @Override +- protected void onInsideBlock(BlockState blockstate) { +- CriteriaTriggers.ENTER_BLOCK.trigger(this, blockstate); ++ protected void onInsideBlock(IBlockData state) { ++ CriteriaTriggers.ENTER_BLOCK.trigger(this, state); + } + + @Override +- @Override + protected ItemCooldowns createItemCooldowns() { + return new ServerItemCooldowns(this); + } + + @Override +- @Override + public void tick() { ++ // CraftBukkit start ++ if (this.joining) { ++ this.joining = false; ++ } ++ // CraftBukkit end + this.gameMode.tick(); + this.wardenSpawnTracker.tick(); + --this.spawnInvulnerableTime; +@@ -557,7 +680,7 @@ + } + + if (this.getHealth() != this.lastSentHealth || this.lastSentFood != this.foodData.getFoodLevel() || this.foodData.getSaturationLevel() == 0.0F != this.lastFoodSaturationZero) { +- this.connection.send(new ClientboundSetHealthPacket(this.getHealth(), this.foodData.getFoodLevel(), this.foodData.getSaturationLevel())); ++ this.connection.send(new ClientboundSetHealthPacket(this.getBukkitEntity().getScaledHealth(), this.foodData.getFoodLevel(), this.foodData.getSaturationLevel())); // CraftBukkit + this.lastSentHealth = this.getHealth(); + this.lastSentFood = this.foodData.getFoodLevel(); + this.lastFoodSaturationZero = this.foodData.getSaturationLevel() == 0.0F; +@@ -588,6 +711,12 @@ + this.updateScoreForCriteria(ObjectiveCriteria.EXPERIENCE, Mth.ceil((float) this.lastRecordedExperience)); + } + ++ // CraftBukkit start - Force max health updates ++ if (this.maxHealthCache != this.getMaxHealth()) { ++ this.getBukkitEntity().updateScaledHealth(); ++ } ++ // CraftBukkit end ++ + if (this.experienceLevel != this.lastRecordedLevel) { + this.lastRecordedLevel = this.experienceLevel; + this.updateScoreForCriteria(ObjectiveCriteria.LEVEL, Mth.ceil((float) this.lastRecordedLevel)); +@@ -602,17 +731,30 @@ + CriteriaTriggers.LOCATION.trigger(this); + } + ++ // CraftBukkit start - initialize oldLevel, fire PlayerLevelChangeEvent, and tick client-sided world border ++ if (this.oldLevel == -1) { ++ this.oldLevel = this.experienceLevel; ++ } ++ ++ if (this.oldLevel != this.experienceLevel) { ++ CraftEventFactory.callPlayerLevelChangeEvent(this.getBukkitEntity(), this.oldLevel, this.experienceLevel); ++ this.oldLevel = this.experienceLevel; ++ } ++ ++ if (this.getBukkitEntity().hasClientWorldBorder()) { ++ ((CraftWorldBorder) this.getBukkitEntity().getWorldBorder()).getHandle().tick(); ++ } ++ // CraftBukkit end + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking player"); +- CrashReportCategory crashreportcategory = crashreport.addCategory("Player being ticked"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Player being ticked"); + +- this.fillCrashReportCategory(crashreportcategory); ++ this.fillCrashReportCategory(crashreportsystemdetails); + throw new ReportedException(crashreport); + } + } + + @Override +- @Override + public void resetFallDistance() { + if (this.getHealth() > 0.0F && this.startingToFallPosition != null) { + CriteriaTriggers.FALL_FROM_HEIGHT.trigger(this, this.startingToFallPosition); +@@ -644,41 +786,79 @@ + + } + +- private void updateScoreForCriteria(ObjectiveCriteria objectivecriteria, int i) { +- this.getScoreboard().forAllObjectives(objectivecriteria, this, (scoreaccess) -> { +- scoreaccess.set(i); ++ private void updateScoreForCriteria(ObjectiveCriteria criteria, int points) { ++ // CraftBukkit - Use our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(criteria, this, (scoreaccess) -> { ++ scoreaccess.set(points); + }); + } + + @Override +- @Override +- public void die(DamageSource damagesource) { ++ public void die(DamageSource cause) { + this.gameEvent(GameEvent.ENTITY_DIE); + boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); ++ // CraftBukkit start - fire PlayerDeathEvent ++ if (this.isRemoved()) { ++ return; ++ } ++ java.util.List loot = new java.util.ArrayList(this.getInventory().getContainerSize()); ++ boolean keepInventory = this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || this.isSpectator(); + +- if (flag) { +- Component component = this.getCombatTracker().getDeathMessage(); ++ if (!keepInventory) { ++ for (ItemStack item : this.getInventory().getContents()) { ++ if (!item.isEmpty() && !EnchantmentHelper.hasVanishingCurse(item)) { ++ loot.add(CraftItemStack.asCraftMirror(item)); ++ } ++ } ++ } ++ // SPIGOT-5071: manually add player loot tables (SPIGOT-5195 - ignores keepInventory rule) ++ this.dropFromLootTable(cause, this.lastHurtByPlayerTime > 0); ++ for (org.bukkit.inventory.ItemStack item : this.drops) { ++ loot.add(item); ++ } ++ this.drops.clear(); // SPIGOT-5188: make sure to clear + +- this.connection.send(new ClientboundPlayerCombatKillPacket(this.getId(), component), PacketSendListener.exceptionallySend(() -> { ++ Component defaultMessage = this.getCombatTracker().getDeathMessage(); ++ ++ String deathmessage = defaultMessage.getString(); ++ keepLevel = keepInventory; // SPIGOT-2222: pre-set keepLevel ++ org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, deathmessage, keepInventory); ++ ++ // SPIGOT-943 - only call if they have an inventory open ++ if (this.containerMenu != this.inventoryMenu) { ++ this.closeContainer(); ++ } ++ ++ String deathMessage = event.getDeathMessage(); ++ ++ if (deathMessage != null && deathMessage.length() > 0 && flag) { // TODO: allow plugins to override? ++ Component ichatbasecomponent; ++ if (deathMessage.equals(deathmessage)) { ++ ichatbasecomponent = this.getCombatTracker().getDeathMessage(); ++ } else { ++ ichatbasecomponent = org.bukkit.craftbukkit.util.CraftChatMessage.fromStringOrNull(deathMessage); ++ } ++ ++ this.connection.send(new ClientboundPlayerCombatKillPacket(this.getId(), ichatbasecomponent), PacketSendListener.exceptionallySend(() -> { + boolean flag1 = true; +- String s = component.getString(256); +- MutableComponent mutablecomponent = Component.translatable("death.attack.message_too_long", Component.literal(s).withStyle(ChatFormatting.YELLOW)); +- MutableComponent mutablecomponent1 = Component.translatable("death.attack.even_more_magic", this.getDisplayName()).withStyle((style) -> { +- return style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, mutablecomponent)); ++ String s = ichatbasecomponent.getString(256); ++ MutableComponent ichatmutablecomponent = Component.translatable("death.attack.message_too_long", Component.literal(s).withStyle(ChatFormatting.YELLOW)); ++ MutableComponent ichatmutablecomponent1 = Component.translatable("death.attack.even_more_magic", this.getDisplayName()).withStyle((chatmodifier) -> { ++ return chatmodifier.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, ichatmutablecomponent)); + }); + +- return new ClientboundPlayerCombatKillPacket(this.getId(), mutablecomponent1); ++ return new ClientboundPlayerCombatKillPacket(this.getId(), ichatmutablecomponent1); + })); +- PlayerTeam playerteam = this.getTeam(); ++ PlayerTeam scoreboardteam = this.getTeam(); + +- if (playerteam != null && playerteam.getDeathMessageVisibility() != Team.Visibility.ALWAYS) { +- if (playerteam.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OTHER_TEAMS) { +- this.server.getPlayerList().broadcastSystemToTeam(this, component); +- } else if (playerteam.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OWN_TEAM) { +- this.server.getPlayerList().broadcastSystemToAllExceptTeam(this, component); ++ if (scoreboardteam != null && scoreboardteam.getDeathMessageVisibility() != Team.Visibility.ALWAYS) { ++ if (scoreboardteam.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OTHER_TEAMS) { ++ this.server.getPlayerList().broadcastSystemToTeam(this, ichatbasecomponent); ++ } else if (scoreboardteam.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OWN_TEAM) { ++ this.server.getPlayerList().broadcastSystemToAllExceptTeam(this, ichatbasecomponent); + } + } else { +- this.server.getPlayerList().broadcastSystemMessage(component, false); ++ this.server.getPlayerList().broadcastSystemMessage(ichatbasecomponent, false); + } + } else { + this.connection.send(new ClientboundPlayerCombatKillPacket(this.getId(), CommonComponents.EMPTY)); +@@ -688,18 +868,24 @@ + if (this.level().getGameRules().getBoolean(GameRules.RULE_FORGIVE_DEAD_PLAYERS)) { + this.tellNeutralMobsThatIDied(); + } +- +- if (!this.isSpectator()) { +- this.dropAllDeathLoot(damagesource); ++ // SPIGOT-5478 must be called manually now ++ this.dropExperience(); ++ // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. ++ if (!event.getKeepInventory()) { ++ this.getInventory().clearContent(); + } + +- this.getScoreboard().forAllObjectives(ObjectiveCriteria.DEATH_COUNT, this, ScoreAccess::increment); +- LivingEntity livingentity = this.getKillCredit(); ++ this.setCamera(this); // Remove spectated target ++ // CraftBukkit end + +- if (livingentity != null) { +- this.awardStat(Stats.ENTITY_KILLED_BY.get(livingentity.getType())); +- livingentity.awardKillScore(this, this.deathScore, damagesource); +- this.createWitherRose(livingentity); ++ // CraftBukkit - Get our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(ObjectiveCriteria.DEATH_COUNT, this, ScoreAccess::increment); ++ LivingEntity entityliving = this.getKillCredit(); ++ ++ if (entityliving != null) { ++ this.awardStat(Stats.ENTITY_KILLED_BY.get(entityliving.getType())); ++ entityliving.awardKillScore(this, this.deathScore, cause); ++ this.createWitherRose(entityliving); + } + + this.level().broadcastEntityEvent(this, (byte) 3); +@@ -714,121 +900,130 @@ + } + + private void tellNeutralMobsThatIDied() { +- AABB aabb = (new AABB(this.blockPosition())).inflate(32.0D, 10.0D, 32.0D); ++ AABB axisalignedbb = (new AABB(this.blockPosition())).inflate(32.0D, 10.0D, 32.0D); + +- this.level().getEntitiesOfClass(Mob.class, aabb, EntitySelector.NO_SPECTATORS).stream().filter((mob) -> { +- return mob instanceof NeutralMob; +- }).forEach((mob) -> { +- ((NeutralMob) mob).playerDied(this); ++ this.level().getEntitiesOfClass(Mob.class, axisalignedbb, EntitySelector.NO_SPECTATORS).stream().filter((entityinsentient) -> { ++ return entityinsentient instanceof NeutralMob; ++ }).forEach((entityinsentient) -> { ++ ((NeutralMob) entityinsentient).playerDied(this); + }); + } + + @Override +- @Override +- public void awardKillScore(Entity entity, int i, DamageSource damagesource) { +- if (entity != this) { +- super.awardKillScore(entity, i, damagesource); +- this.increaseScore(i); +- this.getScoreboard().forAllObjectives(ObjectiveCriteria.KILL_COUNT_ALL, this, ScoreAccess::increment); +- if (entity instanceof Player) { ++ public void awardKillScore(Entity killed, int scoreValue, DamageSource damageSource) { ++ if (killed != this) { ++ super.awardKillScore(killed, scoreValue, damageSource); ++ this.increaseScore(scoreValue); ++ // CraftBukkit - Get our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(ObjectiveCriteria.KILL_COUNT_ALL, this, ScoreAccess::increment); ++ if (killed instanceof Player) { + this.awardStat(Stats.PLAYER_KILLS); +- this.getScoreboard().forAllObjectives(ObjectiveCriteria.KILL_COUNT_PLAYERS, this, ScoreAccess::increment); ++ // CraftBukkit - Get our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(ObjectiveCriteria.KILL_COUNT_PLAYERS, this, ScoreAccess::increment); + } else { + this.awardStat(Stats.MOB_KILLS); + } + +- this.handleTeamKill(this, entity, ObjectiveCriteria.TEAM_KILL); +- this.handleTeamKill(entity, this, ObjectiveCriteria.KILLED_BY_TEAM); +- CriteriaTriggers.PLAYER_KILLED_ENTITY.trigger(this, entity, damagesource); ++ this.handleTeamKill(this, killed, ObjectiveCriteria.TEAM_KILL); ++ this.handleTeamKill(killed, this, ObjectiveCriteria.KILLED_BY_TEAM); ++ CriteriaTriggers.PLAYER_KILLED_ENTITY.trigger(this, killed, damageSource); + } + } + +- private void handleTeamKill(ScoreHolder scoreholder, ScoreHolder scoreholder1, ObjectiveCriteria[] aobjectivecriteria) { +- PlayerTeam playerteam = this.getScoreboard().getPlayersTeam(scoreholder1.getScoreboardName()); ++ private void handleTeamKill(ScoreHolder scoreholder, ScoreHolder scoreholder1, ObjectiveCriteria[] aiscoreboardcriteria) { ++ PlayerTeam scoreboardteam = this.getScoreboard().getPlayersTeam(scoreholder1.getScoreboardName()); + +- if (playerteam != null) { +- int i = playerteam.getColor().getId(); ++ if (scoreboardteam != null) { ++ int i = scoreboardteam.getColor().getId(); + +- if (i >= 0 && i < aobjectivecriteria.length) { +- this.getScoreboard().forAllObjectives(aobjectivecriteria[i], scoreholder, ScoreAccess::increment); ++ if (i >= 0 && i < aiscoreboardcriteria.length) { ++ // CraftBukkit - Get our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(aiscoreboardcriteria[i], scoreholder, ScoreAccess::increment); + } + } + + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- if (this.isInvulnerableTo(damagesource)) { ++ public boolean hurt(DamageSource source, float amount) { ++ if (this.isInvulnerableTo(source)) { + return false; + } else { +- boolean flag = this.server.isDedicatedServer() && this.isPvpAllowed() && damagesource.is(DamageTypeTags.IS_FALL); ++ boolean flag = this.server.isDedicatedServer() && this.isPvpAllowed() && source.is(DamageTypeTags.IS_FALL); + +- if (!flag && this.spawnInvulnerableTime > 0 && !damagesource.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { ++ if (!flag && this.spawnInvulnerableTime > 0 && !source.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { + return false; + } else { +- Entity entity = damagesource.getEntity(); ++ Entity entity = source.getEntity(); + + if (entity instanceof Player) { +- Player player = (Player) entity; ++ Player entityhuman = (Player) entity; + +- if (!this.canHarmPlayer(player)) { ++ if (!this.canHarmPlayer(entityhuman)) { + return false; + } + } + + if (entity instanceof AbstractArrow) { +- AbstractArrow abstractarrow = (AbstractArrow) entity; +- Entity entity1 = abstractarrow.getOwner(); ++ AbstractArrow entityarrow = (AbstractArrow) entity; ++ Entity entity1 = entityarrow.getOwner(); + + if (entity1 instanceof Player) { +- Player player1 = (Player) entity1; ++ Player entityhuman1 = (Player) entity1; + +- if (!this.canHarmPlayer(player1)) { ++ if (!this.canHarmPlayer(entityhuman1)) { + return false; + } + } + } + +- return super.hurt(damagesource, f); ++ return super.hurt(source, amount); + } + } + } + + @Override +- @Override +- public boolean canHarmPlayer(Player player) { +- return !this.isPvpAllowed() ? false : super.canHarmPlayer(player); ++ public boolean canHarmPlayer(Player other) { ++ return !this.isPvpAllowed() ? false : super.canHarmPlayer(other); + } + + private boolean isPvpAllowed() { +- return this.server.isPvpAllowed(); ++ // CraftBukkit - this.server.isPvpAllowed() -> this.world.pvpMode ++ return this.level().pvpMode; + } + + @Nullable + @Override +- @Override +- protected PortalInfo findDimensionEntryPoint(ServerLevel serverlevel) { +- PortalInfo portalinfo = super.findDimensionEntryPoint(serverlevel); ++ protected PortalInfo findDimensionEntryPoint(ServerLevel destination) { ++ PortalInfo shapedetectorshape = super.findDimensionEntryPoint(destination); ++ destination = (shapedetectorshape == null) ? destination : shapedetectorshape.world; // CraftBukkit + +- if (portalinfo != null && this.level().dimension() == Level.OVERWORLD && serverlevel.dimension() == Level.END) { +- Vec3 vec3 = portalinfo.pos.add(0.0D, -1.0D, 0.0D); ++ if (shapedetectorshape != null && this.level().getTypeKey() == LevelStem.OVERWORLD && destination != null && destination.getTypeKey() == LevelStem.END) { // CraftBukkit ++ Vec3 vec3d = shapedetectorshape.pos.add(0.0D, -1.0D, 0.0D); + +- return new PortalInfo(vec3, Vec3.ZERO, 90.0F, 0.0F); ++ return new PortalInfo(vec3d, Vec3.ZERO, 90.0F, 0.0F, destination, shapedetectorshape.portalEventInfo); // CraftBukkit + } else { +- return portalinfo; ++ return shapedetectorshape; + } + } + + @Nullable + @Override +- @Override +- public Entity changeDimension(ServerLevel serverlevel) { +- this.isChangingDimension = true; +- ServerLevel serverlevel1 = this.serverLevel(); +- ResourceKey resourcekey = serverlevel1.dimension(); ++ public Entity changeDimension(ServerLevel server) { ++ // CraftBukkit start ++ return changeDimension(server, TeleportCause.UNKNOWN); ++ } + +- if (resourcekey == Level.END && serverlevel.dimension() == Level.OVERWORLD) { ++ @Nullable ++ public Entity changeDimension(ServerLevel worldserver, PlayerTeleportEvent.TeleportCause cause) { ++ // CraftBukkit end ++ if (this.isSleeping()) return this; // CraftBukkit - SPIGOT-3154 ++ // this.isChangingDimension = true; // CraftBukkit - Moved down and into PlayerList#changeDimension ++ ServerLevel worldserver1 = this.serverLevel(); ++ ResourceKey resourcekey = worldserver1.getTypeKey(); // CraftBukkit ++ ++ if (resourcekey == LevelStem.END && worldserver != null && worldserver.getTypeKey() == LevelStem.OVERWORLD) { // CraftBukkit ++ this.isChangingDimension = true; // CraftBukkit - Moved down from above + this.unRide(); + this.serverLevel().removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); + if (!this.wonGame) { +@@ -839,139 +1034,200 @@ + + return this; + } else { +- LevelData leveldata = serverlevel.getLevelData(); ++ // CraftBukkit start ++ /* ++ WorldData worlddata = worldserver.getLevelData(); + +- this.connection.send(new ClientboundRespawnPacket(this.createCommonSpawnInfo(serverlevel), (byte) 3)); +- this.connection.send(new ClientboundChangeDifficultyPacket(leveldata.getDifficulty(), leveldata.isDifficultyLocked())); ++ this.connection.send(new PacketPlayOutRespawn(this.createCommonSpawnInfo(worldserver), (byte) 3)); ++ this.connection.send(new PacketPlayOutServerDifficulty(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); + PlayerList playerlist = this.server.getPlayerList(); + + playerlist.sendPlayerPermissionLevel(this); +- serverlevel1.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); ++ worldserver1.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); + this.unsetRemoved(); +- PortalInfo portalinfo = this.findDimensionEntryPoint(serverlevel); ++ */ ++ // CraftBukkit end ++ PortalInfo shapedetectorshape = this.findDimensionEntryPoint(worldserver); + +- if (portalinfo != null) { +- serverlevel1.getProfiler().push("moving"); +- if (resourcekey == Level.OVERWORLD && serverlevel.dimension() == Level.NETHER) { ++ if (shapedetectorshape != null) { ++ worldserver1.getProfiler().push("moving"); ++ worldserver = shapedetectorshape.world; // CraftBukkit ++ if (worldserver == null) { } else // CraftBukkit - empty to fall through to null to event ++ if (resourcekey == LevelStem.OVERWORLD && worldserver.getTypeKey() == LevelStem.NETHER) { // CraftBukkit + this.enteredNetherPosition = this.position(); +- } else if (serverlevel.dimension() == Level.END) { +- this.createEndPlatform(serverlevel, BlockPos.containing(portalinfo.pos)); ++ } else if (worldserver.getTypeKey() == LevelStem.END && shapedetectorshape.portalEventInfo != null && shapedetectorshape.portalEventInfo.getCanCreatePortal()) { // CraftBukkit ++ this.createEndPlatform(worldserver, BlockPos.containing(shapedetectorshape.pos)); + } ++ // CraftBukkit start ++ } else { ++ return null; ++ } ++ Location enter = this.getBukkitEntity().getLocation(); ++ Location exit = (worldserver == null) ? null : CraftLocation.toBukkit(shapedetectorshape.pos, worldserver.getWorld(), shapedetectorshape.yRot, shapedetectorshape.xRot); ++ PlayerTeleportEvent tpEvent = new PlayerTeleportEvent(this.getBukkitEntity(), enter, exit, cause); ++ Bukkit.getServer().getPluginManager().callEvent(tpEvent); ++ if (tpEvent.isCancelled() || tpEvent.getTo() == null) { ++ return null; ++ } ++ exit = tpEvent.getTo(); ++ worldserver = ((CraftWorld) exit.getWorld()).getHandle(); ++ // CraftBukkit end + +- serverlevel1.getProfiler().pop(); +- serverlevel1.getProfiler().push("placing"); +- this.setServerLevel(serverlevel); +- this.connection.teleport(portalinfo.pos.x, portalinfo.pos.y, portalinfo.pos.z, portalinfo.yRot, portalinfo.xRot); ++ worldserver1.getProfiler().pop(); ++ worldserver1.getProfiler().push("placing"); ++ if (true) { // CraftBukkit ++ this.isChangingDimension = true; // CraftBukkit - Set teleport invulnerability only if player changing worlds ++ ++ this.connection.send(new ClientboundRespawnPacket(this.createCommonSpawnInfo(worldserver), (byte) 3)); ++ this.connection.send(new ClientboundChangeDifficultyPacket(this.level().getDifficulty(), this.level().getLevelData().isDifficultyLocked())); ++ PlayerList playerlist = this.server.getPlayerList(); ++ ++ playerlist.sendPlayerPermissionLevel(this); ++ worldserver1.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); ++ this.unsetRemoved(); ++ ++ // CraftBukkit end ++ this.setServerLevel(worldserver); ++ this.connection.teleport(exit); // CraftBukkit - use internal teleport without event + this.connection.resetPosition(); +- serverlevel.addDuringPortalTeleport(this); +- serverlevel1.getProfiler().pop(); +- this.triggerDimensionChangeTriggers(serverlevel1); ++ worldserver.addDuringPortalTeleport(this); ++ worldserver1.getProfiler().pop(); ++ this.triggerDimensionChangeTriggers(worldserver1); + this.connection.send(new ClientboundPlayerAbilitiesPacket(this.getAbilities())); +- playerlist.sendLevelInfo(this, serverlevel); ++ playerlist.sendLevelInfo(this, worldserver); + playerlist.sendAllPlayerInfo(this); + Iterator iterator = this.getActiveEffects().iterator(); + + while (iterator.hasNext()) { +- MobEffectInstance mobeffectinstance = (MobEffectInstance) iterator.next(); ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); + +- this.connection.send(new ClientboundUpdateMobEffectPacket(this.getId(), mobeffectinstance)); ++ this.connection.send(new ClientboundUpdateMobEffectPacket(this.getId(), mobeffect)); + } + + this.connection.send(new ClientboundLevelEventPacket(1032, BlockPos.ZERO, 0, false)); + this.lastSentExp = -1; + this.lastSentHealth = -1.0F; + this.lastSentFood = -1; ++ ++ // CraftBukkit start ++ PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.getBukkitEntity(), worldserver1.getWorld()); ++ this.level().getCraftServer().getPluginManager().callEvent(changeEvent); ++ // CraftBukkit end + } + + return this; + } + } + +- private void createEndPlatform(ServerLevel serverlevel, BlockPos blockpos) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = blockpos.mutable(); ++ // CraftBukkit start ++ @Override ++ protected CraftPortalEvent callPortalEvent(Entity entity, ServerLevel exitWorldServer, Vec3 exitPosition, TeleportCause cause, int searchRadius, int creationRadius) { ++ Location enter = this.getBukkitEntity().getLocation(); ++ Location exit = CraftLocation.toBukkit(exitPosition, exitWorldServer.getWorld(), getYRot(), getXRot()); ++ PlayerPortalEvent event = new PlayerPortalEvent(this.getBukkitEntity(), enter, exit, cause, searchRadius, true, creationRadius); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null) { ++ return null; ++ } ++ return new CraftPortalEvent(event); ++ } ++ // CraftBukkit end + ++ private void createEndPlatform(ServerLevel level, BlockPos pos) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(level); // CraftBukkit ++ + for (int i = -2; i <= 2; ++i) { + for (int j = -2; j <= 2; ++j) { + for (int k = -1; k < 3; ++k) { +- BlockState blockstate = k == -1 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); ++ IBlockData iblockdata = k == -1 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); + +- serverlevel.setBlockAndUpdate(blockpos_mutableblockpos.set(blockpos).move(j, k, i), blockstate); ++ blockList.setBlock(blockposition_mutableblockposition.set(pos).move(j, k, i), iblockdata, 3); // CraftBukkit + } + } + } ++ // CraftBukkit start - call portal event ++ org.bukkit.event.world.PortalCreateEvent portalEvent = new org.bukkit.event.world.PortalCreateEvent((List) (List) blockList.getList(), level.getWorld(), this.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM); ++ level.getCraftServer().getPluginManager().callEvent(portalEvent); ++ if (!portalEvent.isCancelled()) { ++ blockList.updateList(); ++ } ++ // CraftBukkit end + + } + + @Override +- @Override +- protected Optional getExitPortal(ServerLevel serverlevel, BlockPos blockpos, boolean flag, WorldBorder worldborder) { +- Optional optional = super.getExitPortal(serverlevel, blockpos, flag, worldborder); ++ protected Optional getExitPortal(ServerLevel worldserver, BlockPos blockposition, boolean flag, WorldBorder worldborder, int searchRadius, boolean canCreatePortal, int createRadius) { // CraftBukkit ++ Optional optional = super.getExitPortal(worldserver, blockposition, flag, worldborder, searchRadius, canCreatePortal, createRadius); // CraftBukkit + +- if (optional.isPresent()) { ++ if (optional.isPresent() || !canCreatePortal) { // CraftBukkit + return optional; + } else { +- Direction.Axis direction_axis = (Direction.Axis) this.level().getBlockState(this.portalEntrancePos).getOptionalValue(NetherPortalBlock.AXIS).orElse(Direction.Axis.X); +- Optional optional1 = serverlevel.getPortalForcer().createPortal(blockpos, direction_axis); ++ Direction.Axis enumdirection_enumaxis = (Direction.Axis) this.level().getBlockState(this.portalEntrancePos).getOptionalValue(NetherPortalBlock.AXIS).orElse(Direction.Axis.X); ++ Optional optional1 = worldserver.getPortalForcer().createPortal(blockposition, enumdirection_enumaxis, this, createRadius); // CraftBukkit + + if (optional1.isEmpty()) { +- ServerPlayer.LOGGER.error("Unable to create a portal, likely target out of worldborder"); ++ // EntityPlayer.LOGGER.error("Unable to create a portal, likely target out of worldborder"); // CraftBukkit + } + + return optional1; + } + } + +- private void triggerDimensionChangeTriggers(ServerLevel serverlevel) { +- ResourceKey resourcekey = serverlevel.dimension(); ++ public void triggerDimensionChangeTriggers(ServerLevel level) { ++ ResourceKey resourcekey = level.dimension(); + ResourceKey resourcekey1 = this.level().dimension(); ++ // CraftBukkit start ++ ResourceKey maindimensionkey = CraftDimensionUtil.getMainDimensionKey(level); ++ ResourceKey maindimensionkey1 = CraftDimensionUtil.getMainDimensionKey(this.level()); + +- CriteriaTriggers.CHANGED_DIMENSION.trigger(this, resourcekey, resourcekey1); +- if (resourcekey == Level.NETHER && resourcekey1 == Level.OVERWORLD && this.enteredNetherPosition != null) { ++ CriteriaTriggers.CHANGED_DIMENSION.trigger(this, maindimensionkey, maindimensionkey1); ++ if (maindimensionkey != resourcekey || maindimensionkey1 != resourcekey1) { ++ CriteriaTriggers.CHANGED_DIMENSION.trigger(this, resourcekey, resourcekey1); ++ } ++ ++ if (maindimensionkey == Level.NETHER && maindimensionkey1 == Level.OVERWORLD && this.enteredNetherPosition != null) { ++ // CraftBukkit end + CriteriaTriggers.NETHER_TRAVEL.trigger(this, this.enteredNetherPosition); + } + +- if (resourcekey1 != Level.NETHER) { ++ if (maindimensionkey1 != Level.NETHER) { // CraftBukkit + this.enteredNetherPosition = null; + } + + } + + @Override +- @Override +- public boolean broadcastToPlayer(ServerPlayer serverplayer) { +- return serverplayer.isSpectator() ? this.getCamera() == this : (this.isSpectator() ? false : super.broadcastToPlayer(serverplayer)); ++ public boolean broadcastToPlayer(ServerPlayer player) { ++ return player.isSpectator() ? this.getCamera() == this : (this.isSpectator() ? false : super.broadcastToPlayer(player)); + } + + @Override +- @Override +- public void take(Entity entity, int i) { +- super.take(entity, i); ++ public void take(Entity entity, int quantity) { ++ super.take(entity, quantity); + this.containerMenu.broadcastChanges(); + } + +- @Override +- @Override +- public Either startSleepInBed(BlockPos blockpos) { +- Direction direction = (Direction) this.level().getBlockState(blockpos).getValue(HorizontalDirectionalBlock.FACING); +- ++ // CraftBukkit start - moved bed result checks from below into separate method ++ private Either getBedResult(BlockPos blockposition, Direction enumdirection) { + if (!this.isSleeping() && this.isAlive()) { +- if (!this.level().dimensionType().natural()) { ++ if (!this.level().dimensionType().natural() || !this.level().dimensionType().bedWorks()) { + return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_HERE); +- } else if (!this.bedInRange(blockpos, direction)) { ++ } else if (!this.bedInRange(blockposition, enumdirection)) { + return Either.left(Player.BedSleepingProblem.TOO_FAR_AWAY); +- } else if (this.bedBlocked(blockpos, direction)) { ++ } else if (this.bedBlocked(blockposition, enumdirection)) { + return Either.left(Player.BedSleepingProblem.OBSTRUCTED); + } else { +- this.setRespawnPosition(this.level().dimension(), blockpos, this.getYRot(), false, true); ++ this.setRespawnPosition(this.level().dimension(), blockposition, this.getYRot(), false, true, PlayerSpawnChangeEvent.Cause.BED); // CraftBukkit + if (this.level().isDay()) { + return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_NOW); + } else { + if (!this.isCreative()) { + double d0 = 8.0D; + double d1 = 5.0D; +- Vec3 vec3 = Vec3.atBottomCenterOf(blockpos); +- List list = this.level().getEntitiesOfClass(Monster.class, new AABB(vec3.x() - 8.0D, vec3.y() - 5.0D, vec3.z() - 8.0D, vec3.x() + 8.0D, vec3.y() + 5.0D, vec3.z() + 8.0D), (monster) -> { +- return monster.isPreventingPlayerRest(this); ++ Vec3 vec3d = Vec3.atBottomCenterOf(blockposition); ++ List list = this.level().getEntitiesOfClass(Monster.class, new AABB(vec3d.x() - 8.0D, vec3d.y() - 5.0D, vec3d.z() - 8.0D, vec3d.x() + 8.0D, vec3d.y() + 5.0D, vec3d.z() + 8.0D), (entitymonster) -> { ++ return entitymonster.isPreventingPlayerRest(this); + }); + + if (!list.isEmpty()) { +@@ -979,7 +1235,36 @@ + } + } + +- Either either = super.startSleepInBed(blockpos).ifRight((unit) -> { ++ return Either.right(Unit.INSTANCE); ++ } ++ } ++ } else { ++ return Either.left(Player.BedSleepingProblem.OTHER_PROBLEM); ++ } ++ } ++ ++ @Override ++ public Either startSleepInBed(BlockPos blockposition, boolean force) { ++ Direction enumdirection = (Direction) this.level().getBlockState(blockposition).getValue(HorizontalDirectionalBlock.FACING); ++ Either bedResult = this.getBedResult(blockposition, enumdirection); ++ ++ if (bedResult.left().orElse(null) == Player.BedSleepingProblem.OTHER_PROBLEM) { ++ return bedResult; // return immediately if the result is not bypassable by plugins ++ } ++ ++ if (force) { ++ bedResult = Either.right(Unit.INSTANCE); ++ } ++ ++ bedResult = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBedEnterEvent(this, blockposition, bedResult); ++ if (bedResult.left().isPresent()) { ++ return bedResult; ++ } ++ ++ { ++ { ++ { ++ Either either = super.startSleepInBed(blockposition, force).ifRight((unit) -> { + this.awardStat(Stats.SLEEP_IN_BED); + CriteriaTriggers.SLEPT_IN_BED.trigger(this); + }); +@@ -992,85 +1277,95 @@ + return either; + } + } +- } else { +- return Either.left(Player.BedSleepingProblem.OTHER_PROBLEM); + } ++ // CraftBukkit end + } + + @Override +- @Override +- public void startSleeping(BlockPos blockpos) { ++ public void startSleeping(BlockPos pos) { + this.resetStat(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)); +- super.startSleeping(blockpos); ++ super.startSleeping(pos); + } + +- private boolean bedInRange(BlockPos blockpos, Direction direction) { +- return this.isReachableBedBlock(blockpos) || this.isReachableBedBlock(blockpos.relative(direction.getOpposite())); ++ private boolean bedInRange(BlockPos pos, Direction direction) { ++ return this.isReachableBedBlock(pos) || this.isReachableBedBlock(pos.relative(direction.getOpposite())); + } + +- private boolean isReachableBedBlock(BlockPos blockpos) { +- Vec3 vec3 = Vec3.atBottomCenterOf(blockpos); ++ private boolean isReachableBedBlock(BlockPos pos) { ++ Vec3 vec3d = Vec3.atBottomCenterOf(pos); + +- return Math.abs(this.getX() - vec3.x()) <= 3.0D && Math.abs(this.getY() - vec3.y()) <= 2.0D && Math.abs(this.getZ() - vec3.z()) <= 3.0D; ++ return Math.abs(this.getX() - vec3d.x()) <= 3.0D && Math.abs(this.getY() - vec3d.y()) <= 2.0D && Math.abs(this.getZ() - vec3d.z()) <= 3.0D; + } + +- private boolean bedBlocked(BlockPos blockpos, Direction direction) { +- BlockPos blockpos1 = blockpos.above(); ++ private boolean bedBlocked(BlockPos pos, Direction direction) { ++ BlockPos blockposition1 = pos.above(); + +- return !this.freeAt(blockpos1) || !this.freeAt(blockpos1.relative(direction.getOpposite())); ++ return !this.freeAt(blockposition1) || !this.freeAt(blockposition1.relative(direction.getOpposite())); + } + + @Override +- @Override +- public void stopSleepInBed(boolean flag, boolean flag1) { ++ public void stopSleepInBed(boolean wakeImmediately, boolean updateLevelForSleepingPlayers) { ++ if (!this.isSleeping()) return; // CraftBukkit - Can't leave bed if not in one! ++ // CraftBukkit start - fire PlayerBedLeaveEvent ++ CraftPlayer player = this.getBukkitEntity(); ++ BlockPos bedPosition = this.getSleepingPos().orElse(null); ++ ++ org.bukkit.block.Block bed; ++ if (bedPosition != null) { ++ bed = this.level().getWorld().getBlockAt(bedPosition.getX(), bedPosition.getY(), bedPosition.getZ()); ++ } else { ++ bed = this.level().getWorld().getBlockAt(player.getLocation()); ++ } ++ ++ PlayerBedLeaveEvent event = new PlayerBedLeaveEvent(player, bed, true); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + if (this.isSleeping()) { + this.serverLevel().getChunkSource().broadcastAndSend(this, new ClientboundAnimatePacket(this, 2)); + } + +- super.stopSleepInBed(flag, flag1); ++ super.stopSleepInBed(wakeImmediately, updateLevelForSleepingPlayers); + if (this.connection != null) { +- this.connection.teleport(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); ++ this.connection.teleport(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot(), TeleportCause.EXIT_BED); // CraftBukkit + } + + } + + @Override +- @Override +- public void dismountTo(double d0, double d1, double d2) { ++ public void dismountTo(double x, double d1, double y) { + this.removeVehicle(); +- this.setPos(d0, d1, d2); ++ this.setPos(x, d1, y); + } + + @Override +- @Override +- public boolean isInvulnerableTo(DamageSource damagesource) { +- return super.isInvulnerableTo(damagesource) || this.isChangingDimension(); ++ public boolean isInvulnerableTo(DamageSource source) { ++ return super.isInvulnerableTo(source) || this.isChangingDimension(); + } + + @Override +- @Override +- protected void checkFallDamage(double d0, boolean flag, BlockState blockstate, BlockPos blockpos) {} ++ protected void checkFallDamage(double y, boolean flag, IBlockData onGround, BlockPos state) {} + + @Override +- @Override +- protected void onChangedBlock(BlockPos blockpos) { ++ protected void onChangedBlock(BlockPos pos) { + if (!this.isSpectator()) { +- super.onChangedBlock(blockpos); ++ super.onChangedBlock(pos); + } + + } + +- public void doCheckFallDamage(double d0, double d1, double d2, boolean flag) { ++ public void doCheckFallDamage(double movementX, double d1, double movementY, boolean flag) { + if (!this.touchingUnloadedChunk()) { +- this.checkSupportingBlock(flag, new Vec3(d0, d1, d2)); +- BlockPos blockpos = this.getOnPosLegacy(); ++ this.checkSupportingBlock(flag, new Vec3(movementX, d1, movementY)); ++ BlockPos blockposition = this.getOnPosLegacy(); + +- super.checkFallDamage(d1, flag, this.level().getBlockState(blockpos), blockpos); ++ super.checkFallDamage(d1, flag, this.level().getBlockState(blockposition), blockposition); + } + } + + @Override +- @Override + protected void pushEntities() { + if (this.level().tickRateManager().runsNormally()) { + super.pushEntities(); +@@ -1079,126 +1374,163 @@ + } + + @Override +- @Override +- public void openTextEdit(SignBlockEntity signblockentity, boolean flag) { +- this.connection.send(new ClientboundBlockUpdatePacket(this.level(), signblockentity.getBlockPos())); +- this.connection.send(new ClientboundOpenSignEditorPacket(signblockentity.getBlockPos(), flag)); ++ public void openTextEdit(SignBlockEntity signEntity, boolean isFrontText) { ++ this.connection.send(new ClientboundBlockUpdatePacket(this.level(), signEntity.getBlockPos())); ++ this.connection.send(new ClientboundOpenSignEditorPacket(signEntity.getBlockPos(), isFrontText)); + } + +- private void nextContainerCounter() { ++ public int nextContainerCounter() { // CraftBukkit - void -> int + this.containerCounter = this.containerCounter % 100 + 1; ++ return containerCounter; // CraftBukkit + } + + @Override +- @Override +- public OptionalInt openMenu(@Nullable MenuProvider menuprovider) { +- if (menuprovider == null) { ++ public OptionalInt openMenu(@Nullable ITileInventory menu) { ++ if (menu == null) { + return OptionalInt.empty(); + } else { ++ // CraftBukkit start - SPIGOT-6552: Handle inventory closing in CraftEventFactory#callInventoryOpenEvent(...) ++ /* + if (this.containerMenu != this.inventoryMenu) { + this.closeContainer(); + } ++ */ ++ // CraftBukkit end + + this.nextContainerCounter(); +- AbstractContainerMenu abstractcontainermenu = menuprovider.createMenu(this.containerCounter, this.getInventory(), this); ++ AbstractContainerMenu container = menu.createMenu(this.containerCounter, this.getInventory(), this); + +- if (abstractcontainermenu == null) { ++ // CraftBukkit start - Inventory open hook ++ if (container != null) { ++ container.setTitle(menu.getDisplayName()); ++ ++ boolean cancelled = false; ++ container = CraftEventFactory.callInventoryOpenEvent(this, container, cancelled); ++ if (container == null && !cancelled) { // Let pre-cancelled events fall through ++ // SPIGOT-5263 - close chest if cancelled ++ if (menu instanceof Container) { ++ ((Container) menu).stopOpen(this); ++ } else if (menu instanceof ChestBlock.DoubleInventory) { ++ // SPIGOT-5355 - double chests too :( ++ ((ChestBlock.DoubleInventory) menu).inventorylargechest.stopOpen(this); ++ } ++ return OptionalInt.empty(); ++ } ++ } ++ // CraftBukkit end ++ if (container == null) { + if (this.isSpectator()) { + this.displayClientMessage(Component.translatable("container.spectatorCantOpen").withStyle(ChatFormatting.RED), true); + } + + return OptionalInt.empty(); + } else { +- this.connection.send(new ClientboundOpenScreenPacket(abstractcontainermenu.containerId, abstractcontainermenu.getType(), menuprovider.getDisplayName())); +- this.initMenu(abstractcontainermenu); +- this.containerMenu = abstractcontainermenu; ++ // CraftBukkit start ++ this.containerMenu = container; ++ this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); ++ // CraftBukkit end ++ this.initMenu(container); + return OptionalInt.of(this.containerCounter); + } + } + } + + @Override +- @Override +- public void sendMerchantOffers(int i, MerchantOffers merchantoffers, int j, int k, boolean flag, boolean flag1) { +- this.connection.send(new ClientboundMerchantOffersPacket(i, merchantoffers, j, k, flag, flag1)); ++ public void sendMerchantOffers(int containerId, MerchantOffers offers, int level, int xp, boolean showProgress, boolean canRestock) { ++ this.connection.send(new ClientboundMerchantOffersPacket(containerId, offers, level, xp, showProgress, canRestock)); + } + + @Override +- @Override +- public void openHorseInventory(AbstractHorse abstracthorse, Container container) { ++ public void openHorseInventory(AbstractHorse horse, Container inventory) { ++ // CraftBukkit start - Inventory open hook ++ this.nextContainerCounter(); ++ AbstractContainerMenu container = new HorseInventoryMenu(this.containerCounter, this.getInventory(), inventory, horse); ++ container.setTitle(horse.getDisplayName()); ++ container = CraftEventFactory.callInventoryOpenEvent(this, container); ++ ++ if (container == null) { ++ inventory.stopOpen(this); ++ return; ++ } ++ // CraftBukkit end + if (this.containerMenu != this.inventoryMenu) { + this.closeContainer(); + } + +- this.nextContainerCounter(); +- this.connection.send(new ClientboundHorseScreenOpenPacket(this.containerCounter, container.getContainerSize(), abstracthorse.getId())); +- this.containerMenu = new HorseInventoryMenu(this.containerCounter, this.getInventory(), container, abstracthorse); ++ // this.nextContainerCounter(); // CraftBukkit - moved up ++ this.connection.send(new ClientboundHorseScreenOpenPacket(this.containerCounter, inventory.getContainerSize(), horse.getId())); ++ this.containerMenu = container; // CraftBukkit + this.initMenu(this.containerMenu); + } + + @Override +- @Override +- public void openItemGui(ItemStack itemstack, InteractionHand interactionhand) { +- if (itemstack.is(Items.WRITTEN_BOOK)) { +- if (WrittenBookItem.resolveBookComponents(itemstack, this.createCommandSourceStack(), this)) { ++ public void openItemGui(ItemStack stack, EnumHand hand) { ++ if (stack.is(Items.WRITTEN_BOOK)) { ++ if (WrittenBookItem.resolveBookComponents(stack, this.createCommandSourceStack(), this)) { + this.containerMenu.broadcastChanges(); + } + +- this.connection.send(new ClientboundOpenBookPacket(interactionhand)); ++ this.connection.send(new ClientboundOpenBookPacket(hand)); + } + + } + + @Override +- @Override +- public void openCommandBlock(CommandBlockEntity commandblockentity) { +- this.connection.send(ClientboundBlockEntityDataPacket.create(commandblockentity, BlockEntity::saveWithoutMetadata)); ++ public void openCommandBlock(CommandBlockEntity commandBlock) { ++ this.connection.send(ClientboundBlockEntityDataPacket.create(commandBlock, BlockEntity::saveWithoutMetadata)); + } + + @Override +- @Override + public void closeContainer() { ++ CraftEventFactory.handleInventoryCloseEvent(this); // CraftBukkit + this.connection.send(new ClientboundContainerClosePacket(this.containerMenu.containerId)); + this.doCloseContainer(); + } + + @Override +- @Override + public void doCloseContainer() { + this.containerMenu.removed(this); + this.inventoryMenu.transferState(this.containerMenu); + this.containerMenu = this.inventoryMenu; + } + +- public void setPlayerInput(float f, float f1, boolean flag, boolean flag1) { ++ public void setPlayerInput(float strafe, float forward, boolean jumping, boolean sneaking) { + if (this.isPassenger()) { +- if (f >= -1.0F && f <= 1.0F) { +- this.xxa = f; ++ if (strafe >= -1.0F && strafe <= 1.0F) { ++ this.xxa = strafe; + } + +- if (f1 >= -1.0F && f1 <= 1.0F) { +- this.zza = f1; ++ if (forward >= -1.0F && forward <= 1.0F) { ++ this.zza = forward; + } + +- this.jumping = flag; +- this.setShiftKeyDown(flag1); ++ this.jumping = jumping; ++ // CraftBukkit start ++ if (sneaking != this.isShiftKeyDown()) { ++ PlayerToggleSneakEvent event = new PlayerToggleSneakEvent(this.getBukkitEntity(), sneaking); ++ this.server.server.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ this.setShiftKeyDown(sneaking); + } + + } + + @Override +- @Override +- public void travel(Vec3 vec3) { ++ public void travel(Vec3 travelVector) { + double d0 = this.getX(); + double d1 = this.getY(); + double d2 = this.getZ(); + +- super.travel(vec3); ++ super.travel(travelVector); + this.checkMovementStatistics(this.getX() - d0, this.getY() - d1, this.getZ() - d2); + } + + @Override +- @Override + public void rideTick() { + double d0 = this.getX(); + double d1 = this.getY(); +@@ -1216,19 +1548,19 @@ + i = Math.round((float) Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2) * 100.0F); + if (i > 0) { + this.awardStat(Stats.SWIM_ONE_CM, i); +- this.causeFoodExhaustion(0.01F * (float) i * 0.01F); ++ this.causeFoodExhaustion(0.01F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.SWIM); // CraftBukkit - EntityExhaustionEvent + } + } else if (this.isEyeInFluid(FluidTags.WATER)) { + i = Math.round((float) Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2) * 100.0F); + if (i > 0) { + this.awardStat(Stats.WALK_UNDER_WATER_ONE_CM, i); +- this.causeFoodExhaustion(0.01F * (float) i * 0.01F); ++ this.causeFoodExhaustion(0.01F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.WALK_UNDERWATER); // CraftBukkit - EntityExhaustionEvent + } + } else if (this.isInWater()) { + i = Math.round((float) Math.sqrt(d0 * d0 + d2 * d2) * 100.0F); + if (i > 0) { + this.awardStat(Stats.WALK_ON_WATER_ONE_CM, i); +- this.causeFoodExhaustion(0.01F * (float) i * 0.01F); ++ this.causeFoodExhaustion(0.01F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.WALK_ON_WATER); // CraftBukkit - EntityExhaustionEvent + } + } else if (this.onClimbable()) { + if (d1 > 0.0D) { +@@ -1239,13 +1571,13 @@ + if (i > 0) { + if (this.isSprinting()) { + this.awardStat(Stats.SPRINT_ONE_CM, i); +- this.causeFoodExhaustion(0.1F * (float) i * 0.01F); ++ this.causeFoodExhaustion(0.1F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.SPRINT); // CraftBukkit - EntityExhaustionEvent + } else if (this.isCrouching()) { + this.awardStat(Stats.CROUCH_ONE_CM, i); +- this.causeFoodExhaustion(0.0F * (float) i * 0.01F); ++ this.causeFoodExhaustion(0.0F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.CROUCH); // CraftBukkit - EntityExhaustionEvent + } else { + this.awardStat(Stats.WALK_ONE_CM, i); +- this.causeFoodExhaustion(0.0F * (float) i * 0.01F); ++ this.causeFoodExhaustion(0.0F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.WALK); // CraftBukkit - EntityExhaustionEvent + } + } + } else if (this.isFallFlying()) { +@@ -1286,53 +1618,46 @@ + } + + @Override +- @Override +- public void awardStat(Stat stat, int i) { +- this.stats.increment(this, stat, i); +- this.getScoreboard().forAllObjectives(stat, this, (scoreaccess) -> { +- scoreaccess.add(i); ++ public void awardStat(Stat stat, int amount) { ++ this.stats.increment(this, stat, amount); ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(stat, this, (scoreaccess) -> { ++ scoreaccess.add(amount); + }); + } + + @Override +- @Override + public void resetStat(Stat stat) { + this.stats.setValue(this, stat, 0); +- this.getScoreboard().forAllObjectives(stat, this, ScoreAccess::reset); ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(stat, this, ScoreAccess::reset); // CraftBukkit - Get our scores instead + } + + @Override +- @Override +- public int awardRecipes(Collection> collection) { +- return this.recipeBook.addRecipes(collection, this); ++ public int awardRecipes(Collection> recipes) { ++ return this.recipeBook.addRecipes(recipes, this); + } + + @Override +- @Override + public void triggerRecipeCrafted(RecipeHolder recipeholder, List list) { + CriteriaTriggers.RECIPE_CRAFTED.trigger(this, recipeholder.id(), list); + } + + @Override +- @Override + public void awardRecipesByKey(List list) { +- List> list1 = (List) list.stream().flatMap((resourcelocation) -> { +- return this.server.getRecipeManager().byKey(resourcelocation).stream(); ++ List> list1 = (List) list.stream().flatMap((minecraftkey) -> { ++ return this.server.getRecipeManager().byKey(minecraftkey).stream(); + }).collect(Collectors.toList()); + + this.awardRecipes(list1); + } + + @Override +- @Override +- public int resetRecipes(Collection> collection) { +- return this.recipeBook.removeRecipes(collection, this); ++ public int resetRecipes(Collection> recipes) { ++ return this.recipeBook.removeRecipes(recipes, this); + } + + @Override +- @Override +- public void giveExperiencePoints(int i) { +- super.giveExperiencePoints(i); ++ public void giveExperiencePoints(int xpPoints) { ++ super.giveExperiencePoints(xpPoints); + this.lastSentExp = -1; + } + +@@ -1351,16 +1676,15 @@ + + public void resetSentInfo() { + this.lastSentHealth = -1.0E8F; ++ this.lastSentExp = -1; // CraftBukkit - Added to reset + } + + @Override +- @Override +- public void displayClientMessage(Component component, boolean flag) { +- this.sendSystemMessage(component, flag); ++ public void displayClientMessage(Component chatComponent, boolean actionBar) { ++ this.sendSystemMessage(chatComponent, actionBar); + } + + @Override +- @Override + protected void completeUsingItem() { + if (!this.useItem.isEmpty() && this.isUsingItem()) { + this.connection.send(new ClientboundEntityEventPacket(this, (byte) 9)); +@@ -1370,62 +1694,60 @@ + } + + @Override +- @Override +- public void lookAt(EntityAnchorArgument.Anchor entityanchorargument_anchor, Vec3 vec3) { +- super.lookAt(entityanchorargument_anchor, vec3); +- this.connection.send(new ClientboundPlayerLookAtPacket(entityanchorargument_anchor, vec3.x, vec3.y, vec3.z)); ++ public void lookAt(EntityAnchorArgument.Anchor anchor, Vec3 target) { ++ super.lookAt(anchor, target); ++ this.connection.send(new ClientboundPlayerLookAtPacket(anchor, target.x, target.y, target.z)); + } + +- public void lookAt(EntityAnchorArgument.Anchor entityanchorargument_anchor, Entity entity, EntityAnchorArgument.Anchor entityanchorargument_anchor1) { +- Vec3 vec3 = entityanchorargument_anchor1.apply(entity); ++ public void lookAt(EntityAnchorArgument.Anchor fromAnchor, Entity entity, EntityAnchorArgument.Anchor toAnchor) { ++ Vec3 vec3d = toAnchor.apply(entity); + +- super.lookAt(entityanchorargument_anchor, vec3); +- this.connection.send(new ClientboundPlayerLookAtPacket(entityanchorargument_anchor, entity, entityanchorargument_anchor1)); ++ super.lookAt(fromAnchor, vec3d); ++ this.connection.send(new ClientboundPlayerLookAtPacket(fromAnchor, entity, toAnchor)); + } + +- public void restoreFrom(ServerPlayer serverplayer, boolean flag) { +- this.wardenSpawnTracker = serverplayer.wardenSpawnTracker; +- this.chatSession = serverplayer.chatSession; +- this.gameMode.setGameModeForPlayer(serverplayer.gameMode.getGameModeForPlayer(), serverplayer.gameMode.getPreviousGameModeForPlayer()); ++ public void restoreFrom(ServerPlayer that, boolean keepEverything) { ++ this.wardenSpawnTracker = that.wardenSpawnTracker; ++ this.chatSession = that.chatSession; ++ this.gameMode.setGameModeForPlayer(that.gameMode.getGameModeForPlayer(), that.gameMode.getPreviousGameModeForPlayer()); + this.onUpdateAbilities(); +- if (flag) { +- this.getInventory().replaceWith(serverplayer.getInventory()); +- this.setHealth(serverplayer.getHealth()); +- this.foodData = serverplayer.foodData; +- this.experienceLevel = serverplayer.experienceLevel; +- this.totalExperience = serverplayer.totalExperience; +- this.experienceProgress = serverplayer.experienceProgress; +- this.setScore(serverplayer.getScore()); +- this.portalEntrancePos = serverplayer.portalEntrancePos; +- } else if (this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || serverplayer.isSpectator()) { +- this.getInventory().replaceWith(serverplayer.getInventory()); +- this.experienceLevel = serverplayer.experienceLevel; +- this.totalExperience = serverplayer.totalExperience; +- this.experienceProgress = serverplayer.experienceProgress; +- this.setScore(serverplayer.getScore()); ++ if (keepEverything) { ++ this.getInventory().replaceWith(that.getInventory()); ++ this.setHealth(that.getHealth()); ++ this.foodData = that.foodData; ++ this.experienceLevel = that.experienceLevel; ++ this.totalExperience = that.totalExperience; ++ this.experienceProgress = that.experienceProgress; ++ this.setScore(that.getScore()); ++ this.portalEntrancePos = that.portalEntrancePos; ++ } else if (this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || that.isSpectator()) { ++ this.getInventory().replaceWith(that.getInventory()); ++ this.experienceLevel = that.experienceLevel; ++ this.totalExperience = that.totalExperience; ++ this.experienceProgress = that.experienceProgress; ++ this.setScore(that.getScore()); + } + +- this.enchantmentSeed = serverplayer.enchantmentSeed; +- this.enderChestInventory = serverplayer.enderChestInventory; +- this.getEntityData().set(ServerPlayer.DATA_PLAYER_MODE_CUSTOMISATION, (Byte) serverplayer.getEntityData().get(ServerPlayer.DATA_PLAYER_MODE_CUSTOMISATION)); ++ this.enchantmentSeed = that.enchantmentSeed; ++ this.enderChestInventory = that.enderChestInventory; ++ this.getEntityData().set(ServerPlayer.DATA_PLAYER_MODE_CUSTOMISATION, (Byte) that.getEntityData().get(ServerPlayer.DATA_PLAYER_MODE_CUSTOMISATION)); + this.lastSentExp = -1; + this.lastSentHealth = -1.0F; + this.lastSentFood = -1; +- this.recipeBook.copyOverData(serverplayer.recipeBook); +- this.seenCredits = serverplayer.seenCredits; +- this.enteredNetherPosition = serverplayer.enteredNetherPosition; +- this.chunkTrackingView = serverplayer.chunkTrackingView; +- this.setShoulderEntityLeft(serverplayer.getShoulderEntityLeft()); +- this.setShoulderEntityRight(serverplayer.getShoulderEntityRight()); +- this.setLastDeathLocation(serverplayer.getLastDeathLocation()); ++ // this.recipeBook.copyOverData(entityplayer.recipeBook); // CraftBukkit ++ this.seenCredits = that.seenCredits; ++ this.enteredNetherPosition = that.enteredNetherPosition; ++ this.chunkTrackingView = that.chunkTrackingView; ++ this.setShoulderEntityLeft(that.getShoulderEntityLeft()); ++ this.setShoulderEntityRight(that.getShoulderEntityRight()); ++ this.setLastDeathLocation(that.getLastDeathLocation()); + } + + @Override +- @Override +- protected void onEffectAdded(MobEffectInstance mobeffectinstance, @Nullable Entity entity) { +- super.onEffectAdded(mobeffectinstance, entity); +- this.connection.send(new ClientboundUpdateMobEffectPacket(this.getId(), mobeffectinstance)); +- if (mobeffectinstance.getEffect() == MobEffects.LEVITATION) { ++ protected void onEffectAdded(MobEffectInstance effectInstance, @Nullable Entity entity) { ++ super.onEffectAdded(effectInstance, entity); ++ this.connection.send(new ClientboundUpdateMobEffectPacket(this.getId(), effectInstance)); ++ if (effectInstance.getEffect() == MobEffects.LEVITATION) { + this.levitationStartTime = this.tickCount; + this.levitationStartPos = this.position(); + } +@@ -1434,19 +1756,17 @@ + } + + @Override +- @Override +- protected void onEffectUpdated(MobEffectInstance mobeffectinstance, boolean flag, @Nullable Entity entity) { +- super.onEffectUpdated(mobeffectinstance, flag, entity); +- this.connection.send(new ClientboundUpdateMobEffectPacket(this.getId(), mobeffectinstance)); ++ protected void onEffectUpdated(MobEffectInstance effectInstance, boolean forced, @Nullable Entity entity) { ++ super.onEffectUpdated(effectInstance, forced, entity); ++ this.connection.send(new ClientboundUpdateMobEffectPacket(this.getId(), effectInstance)); + CriteriaTriggers.EFFECTS_CHANGED.trigger(this, entity); + } + + @Override +- @Override +- protected void onEffectRemoved(MobEffectInstance mobeffectinstance) { +- super.onEffectRemoved(mobeffectinstance); +- this.connection.send(new ClientboundRemoveMobEffectPacket(this.getId(), mobeffectinstance.getEffect())); +- if (mobeffectinstance.getEffect() == MobEffects.LEVITATION) { ++ protected void onEffectRemoved(MobEffectInstance effect) { ++ super.onEffectRemoved(effect); ++ this.connection.send(new ClientboundRemoveMobEffectPacket(this.getId(), effect.getEffect())); ++ if (effect.getEffect() == MobEffects.LEVITATION) { + this.levitationStartPos = null; + } + +@@ -1454,32 +1774,35 @@ + } + + @Override +- @Override +- public void teleportTo(double d0, double d1, double d2) { +- this.connection.teleport(d0, d1, d2, this.getYRot(), this.getXRot(), RelativeMovement.ROTATION); ++ public void teleportTo(double x, double d1, double y) { ++ this.connection.teleport(x, d1, y, this.getYRot(), this.getXRot(), RelativeMovement.ROTATION); + } + + @Override +- @Override +- public void teleportRelative(double d0, double d1, double d2) { +- this.connection.teleport(this.getX() + d0, this.getY() + d1, this.getZ() + d2, this.getYRot(), this.getXRot(), RelativeMovement.ALL); ++ public void teleportRelative(double dx, double d1, double dy) { ++ this.connection.teleport(this.getX() + dx, this.getY() + d1, this.getZ() + dy, this.getYRot(), this.getXRot(), RelativeMovement.ALL); + } + + @Override +- @Override +- public boolean teleportTo(ServerLevel serverlevel, double d0, double d1, double d2, Set set, float f, float f1) { +- ChunkPos chunkpos = new ChunkPos(BlockPos.containing(d0, d1, d2)); ++ public boolean teleportTo(ServerLevel level, double x, double d1, double y, Set set, float z, float f1) { ++ // CraftBukkit start ++ return teleportTo(level, x, d1, y, set, z, f1, TeleportCause.UNKNOWN); ++ } + +- serverlevel.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, chunkpos, 1, this.getId()); ++ public boolean teleportTo(ServerLevel worldserver, double d0, double d1, double d2, Set set, float f, float f1, TeleportCause cause) { ++ // CraftBukkit end ++ ChunkPos chunkcoordintpair = new ChunkPos(BlockPos.containing(d0, d1, d2)); ++ ++ worldserver.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, chunkcoordintpair, 1, this.getId()); + this.stopRiding(); + if (this.isSleeping()) { + this.stopSleepInBed(true, true); + } + +- if (serverlevel == this.level()) { +- this.connection.teleport(d0, d1, d2, f, f1, set); ++ if (worldserver == this.level()) { ++ this.connection.teleport(d0, d1, d2, f, f1, set, cause); // CraftBukkit + } else { +- this.teleportTo(serverlevel, d0, d1, d2, f, f1); ++ this.teleportTo(worldserver, d0, d1, d2, f, f1, cause); // CraftBukkit + } + + this.setYHeadRot(f); +@@ -1487,26 +1810,22 @@ + } + + @Override +- @Override +- public void moveTo(double d0, double d1, double d2) { +- super.moveTo(d0, d1, d2); ++ public void moveTo(double x, double d1, double y) { ++ super.moveTo(x, d1, y); + this.connection.resetPosition(); + } + + @Override +- @Override +- public void crit(Entity entity) { +- this.serverLevel().getChunkSource().broadcastAndSend(this, new ClientboundAnimatePacket(entity, 4)); ++ public void crit(Entity entityHit) { ++ this.serverLevel().getChunkSource().broadcastAndSend(this, new ClientboundAnimatePacket(entityHit, 4)); + } + + @Override +- @Override +- public void magicCrit(Entity entity) { +- this.serverLevel().getChunkSource().broadcastAndSend(this, new ClientboundAnimatePacket(entity, 5)); ++ public void magicCrit(Entity entityHit) { ++ this.serverLevel().getChunkSource().broadcastAndSend(this, new ClientboundAnimatePacket(entityHit, 5)); + } + + @Override +- @Override + public void onUpdateAbilities() { + if (this.connection != null) { + this.connection.send(new ClientboundPlayerAbilitiesPacket(this.getAbilities())); +@@ -1518,12 +1837,12 @@ + return (ServerLevel) this.level(); + } + +- public boolean setGameMode(GameType gametype) { +- if (!this.gameMode.changeGameModeForPlayer(gametype)) { ++ public boolean setGameMode(GameType gameMode) { ++ if (!this.gameMode.changeGameModeForPlayer(gameMode)) { + return false; + } else { +- this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, (float) gametype.getId())); +- if (gametype == GameType.SPECTATOR) { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, (float) gameMode.getId())); ++ if (gameMode == GameType.SPECTATOR) { + this.removeEntitiesOnShoulder(); + this.stopRiding(); + } else { +@@ -1537,32 +1856,29 @@ + } + + @Override +- @Override + public boolean isSpectator() { + return this.gameMode.getGameModeForPlayer() == GameType.SPECTATOR; + } + + @Override +- @Override + public boolean isCreative() { + return this.gameMode.getGameModeForPlayer() == GameType.CREATIVE; + } + + @Override +- @Override + public void sendSystemMessage(Component component) { + this.sendSystemMessage(component, false); + } + +- public void sendSystemMessage(Component component, boolean flag) { +- if (this.acceptsSystemMessages(flag)) { +- this.connection.send(new ClientboundSystemChatPacket(component, flag), PacketSendListener.exceptionallySend(() -> { ++ public void sendSystemMessage(Component component, boolean bypassHiddenChat) { ++ if (this.acceptsSystemMessages(bypassHiddenChat)) { ++ this.connection.send(new ClientboundSystemChatPacket(component, bypassHiddenChat), PacketSendListener.exceptionallySend(() -> { + if (this.acceptsSystemMessages(false)) { + boolean flag1 = true; + String s = component.getString(256); +- MutableComponent mutablecomponent = Component.literal(s).withStyle(ChatFormatting.YELLOW); ++ MutableComponent ichatmutablecomponent = Component.literal(s).withStyle(ChatFormatting.YELLOW); + +- return new ClientboundSystemChatPacket(Component.translatable("multiplayer.message_not_delivered", mutablecomponent).withStyle(ChatFormatting.RED), false); ++ return new ClientboundSystemChatPacket(Component.translatable("multiplayer.message_not_delivered", ichatmutablecomponent).withStyle(ChatFormatting.RED), false); + } else { + return null; + } +@@ -1570,9 +1886,9 @@ + } + } + +- public void sendChatMessage(OutgoingChatMessage outgoingchatmessage, boolean flag, ChatType.Bound chattype_bound) { ++ public void sendChatMessage(OutgoingChatMessage message, boolean filtered, ChatType.Bound boundType) { + if (this.acceptsChatMessages()) { +- outgoingchatmessage.sendToPlayer(this, flag, chattype_bound); ++ message.sendToPlayer(this, filtered, boundType); + } + + } +@@ -1590,6 +1906,16 @@ + } + + public void updateOptions(ClientInformation clientinformation) { ++ // CraftBukkit start ++ if (getMainArm() != clientinformation.mainHand()) { ++ PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(getBukkitEntity(), getMainArm() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT); ++ this.server.server.getPluginManager().callEvent(event); ++ } ++ if (!this.language.equals(clientinformation.language())) { ++ PlayerLocaleChangeEvent event = new PlayerLocaleChangeEvent(getBukkitEntity(), clientinformation.language()); ++ this.server.server.getPluginManager().callEvent(event); ++ } ++ // CraftBukkit end + this.language = clientinformation.language(); + this.requestedViewDistance = clientinformation.viewDistance(); + this.chatVisibility = clientinformation.chatVisibility(); +@@ -1602,9 +1928,9 @@ + + public ClientInformation clientInformation() { + byte b0 = (Byte) this.getEntityData().get(ServerPlayer.DATA_PLAYER_MODE_CUSTOMISATION); +- HumanoidArm humanoidarm = (HumanoidArm) HumanoidArm.BY_ID.apply((Byte) this.getEntityData().get(ServerPlayer.DATA_PLAYER_MAIN_HAND)); ++ HumanoidArm enummainhand = (HumanoidArm) HumanoidArm.BY_ID.apply((Byte) this.getEntityData().get(ServerPlayer.DATA_PLAYER_MAIN_HAND)); + +- return new ClientInformation(this.language, this.requestedViewDistance, this.chatVisibility, this.canChatColor, b0, humanoidarm, this.textFilteringEnabled, this.allowsListing); ++ return new ClientInformation(this.language, this.requestedViewDistance, this.chatVisibility, this.canChatColor, b0, enummainhand, this.textFilteringEnabled, this.allowsListing); + } + + public boolean canChatInColor() { +@@ -1615,8 +1941,8 @@ + return this.chatVisibility; + } + +- private boolean acceptsSystemMessages(boolean flag) { +- return this.chatVisibility == ChatVisiblity.HIDDEN ? flag : true; ++ private boolean acceptsSystemMessages(boolean bypassHiddenChat) { ++ return this.chatVisibility == ChatVisiblity.HIDDEN ? bypassHiddenChat : true; + } + + private boolean acceptsChatMessages() { +@@ -1627,12 +1953,11 @@ + return this.requestedViewDistance; + } + +- public void sendServerStatus(ServerStatus serverstatus) { +- this.connection.send(new ClientboundServerDataPacket(serverstatus.description(), serverstatus.favicon().map(ServerStatus.Favicon::iconBytes), serverstatus.enforcesSecureChat())); ++ public void sendServerStatus(ServerStatus serverStatus) { ++ this.connection.send(new ClientboundServerDataPacket(serverStatus.description(), serverStatus.favicon().map(ServerStatus.a::iconBytes), serverStatus.enforcesSecureChat())); + } + + @Override +- @Override + protected int getPermissionLevel() { + return this.server.getProfilePermissions(this.getGameProfile()); + } +@@ -1650,7 +1975,6 @@ + } + + @Override +- @Override + protected void updateInvisibilityStatus() { + if (this.isSpectator()) { + this.removeEffectParticles(); +@@ -1665,20 +1989,20 @@ + return (Entity) (this.camera == null ? this : this.camera); + } + +- public void setCamera(@Nullable Entity entity) { ++ public void setCamera(@Nullable Entity entityToSpectate) { + Entity entity1 = this.getCamera(); + +- this.camera = (Entity) (entity == null ? this : entity); ++ this.camera = (Entity) (entityToSpectate == null ? this : entityToSpectate); + if (entity1 != this.camera) { +- Level level = this.camera.level(); ++ Level world = this.camera.level(); + +- if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; + +- this.teleportTo(serverlevel, this.camera.getX(), this.camera.getY(), this.camera.getZ(), Set.of(), this.getYRot(), this.getXRot()); ++ this.teleportTo(worldserver, this.camera.getX(), this.camera.getY(), this.camera.getZ(), Set.of(), this.getYRot(), this.getXRot(), TeleportCause.SPECTATE); // CraftBukkit + } + +- if (entity != null) { ++ if (entityToSpectate != null) { + this.serverLevel().getChunkSource().move(this); + } + +@@ -1689,7 +2013,6 @@ + } + + @Override +- @Override + protected void processPortalCooldown() { + if (!this.isChangingDimension) { + super.processPortalCooldown(); +@@ -1698,12 +2021,11 @@ + } + + @Override +- @Override +- public void attack(Entity entity) { ++ public void attack(Entity targetEntity) { + if (this.gameMode.getGameModeForPlayer() == GameType.SPECTATOR) { +- this.setCamera(entity); ++ this.setCamera(targetEntity); + } else { +- super.attack(entity); ++ super.attack(targetEntity); + } + + } +@@ -1714,13 +2036,12 @@ + + @Nullable + public Component getTabListDisplayName() { +- return null; ++ return listName; // CraftBukkit + } + + @Override +- @Override +- public void swing(InteractionHand interactionhand) { +- super.swing(interactionhand); ++ public void swing(EnumHand hand) { ++ super.swing(hand); + this.resetAttackStrengthTicker(); + } + +@@ -1736,28 +2057,38 @@ + return this.advancements; + } + +- public void teleportTo(ServerLevel serverlevel, double d0, double d1, double d2, float f, float f1) { ++ // CraftBukkit start ++ public void teleportTo(ServerLevel newLevel, double x, double d1, double y, float f, float z) { ++ this.teleportTo(newLevel, x, d1, y, f, z, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.UNKNOWN); ++ } ++ ++ public void teleportTo(ServerLevel worldserver, double d0, double d1, double d2, float f, float f1, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { ++ // CraftBukkit end + this.setCamera(this); + this.stopRiding(); +- if (serverlevel == this.level()) { ++ /* CraftBukkit start - replace with bukkit handling for multi-world ++ if (worldserver == this.level()) { + this.connection.teleport(d0, d1, d2, f, f1); + } else { +- ServerLevel serverlevel1 = this.serverLevel(); +- LevelData leveldata = serverlevel.getLevelData(); ++ WorldServer worldserver1 = this.serverLevel(); ++ WorldData worlddata = worldserver.getLevelData(); + +- this.connection.send(new ClientboundRespawnPacket(this.createCommonSpawnInfo(serverlevel), (byte) 3)); +- this.connection.send(new ClientboundChangeDifficultyPacket(leveldata.getDifficulty(), leveldata.isDifficultyLocked())); ++ this.connection.send(new PacketPlayOutRespawn(this.createCommonSpawnInfo(worldserver), (byte) 3)); ++ this.connection.send(new PacketPlayOutServerDifficulty(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); + this.server.getPlayerList().sendPlayerPermissionLevel(this); +- serverlevel1.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); ++ worldserver1.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); + this.unsetRemoved(); + this.moveTo(d0, d1, d2, f, f1); +- this.setServerLevel(serverlevel); +- serverlevel.addDuringCommandTeleport(this); +- this.triggerDimensionChangeTriggers(serverlevel1); ++ this.setServerLevel(worldserver); ++ worldserver.addDuringCommandTeleport(this); ++ this.triggerDimensionChangeTriggers(worldserver1); + this.connection.teleport(d0, d1, d2, f, f1); +- this.server.getPlayerList().sendLevelInfo(this, serverlevel); ++ this.server.getPlayerList().sendLevelInfo(this, worldserver); + this.server.getPlayerList().sendAllPlayerInfo(this); + } ++ */ ++ this.getBukkitEntity().teleport(new Location(worldserver.getWorld(), d0, d1, d2, f, f1), cause); ++ // CraftBukkit end + + } + +@@ -1778,15 +2109,41 @@ + return this.respawnForced; + } + +- public void setRespawnPosition(ResourceKey resourcekey, @Nullable BlockPos blockpos, float f, boolean flag, boolean flag1) { +- if (blockpos != null) { +- boolean flag2 = blockpos.equals(this.respawnPosition) && resourcekey.equals(this.respawnDimension); ++ public void setRespawnPosition(ResourceKey dimension, @Nullable BlockPos position, float angle, boolean forced, boolean sendMessage) { ++ // CraftBukkit start ++ this.setRespawnPosition(dimension, position, angle, forced, sendMessage, PlayerSpawnChangeEvent.Cause.UNKNOWN); ++ } + ++ public void setRespawnPosition(ResourceKey resourcekey, @Nullable BlockPos blockposition, float f, boolean flag, boolean flag1, PlayerSpawnChangeEvent.Cause cause) { ++ ServerLevel newWorld = this.server.getLevel(resourcekey); ++ Location newSpawn = (blockposition != null) ? CraftLocation.toBukkit(blockposition, newWorld.getWorld(), f, 0) : null; ++ ++ PlayerSpawnChangeEvent event = new PlayerSpawnChangeEvent(this.getBukkitEntity(), newSpawn, flag, cause); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ newSpawn = event.getNewSpawn(); ++ flag = event.isForced(); ++ ++ if (newSpawn != null) { ++ resourcekey = ((CraftWorld) newSpawn.getWorld()).getHandle().dimension(); ++ blockposition = BlockPos.containing(newSpawn.getX(), newSpawn.getY(), newSpawn.getZ()); ++ f = newSpawn.getYaw(); ++ } else { ++ resourcekey = Level.OVERWORLD; ++ blockposition = null; ++ f = 0.0F; ++ } ++ // CraftBukkit end ++ if (blockposition != null) { ++ boolean flag2 = blockposition.equals(this.respawnPosition) && resourcekey.equals(this.respawnDimension); ++ + if (flag1 && !flag2) { + this.sendSystemMessage(Component.translatable("block.minecraft.set_spawn")); + } + +- this.respawnPosition = blockpos; ++ this.respawnPosition = blockposition; + this.respawnDimension = resourcekey; + this.respawnAngle = f; + this.respawnForced = flag; +@@ -1803,8 +2160,8 @@ + return this.lastSectionPos; + } + +- public void setLastSectionPos(SectionPos sectionpos) { +- this.lastSectionPos = sectionpos; ++ public void setLastSectionPos(SectionPos sectionPos) { ++ this.lastSectionPos = sectionPos; + } + + public ChunkTrackingView getChunkTrackingView() { +@@ -1816,31 +2173,29 @@ + } + + @Override +- @Override +- public void playNotifySound(SoundEvent soundevent, SoundSource soundsource, float f, float f1) { +- this.connection.send(new ClientboundSoundPacket(BuiltInRegistries.SOUND_EVENT.wrapAsHolder(soundevent), soundsource, this.getX(), this.getY(), this.getZ(), f, f1, this.random.nextLong())); ++ public void playNotifySound(SoundEvent sound, SoundSource source, float volume, float pitch) { ++ this.connection.send(new ClientboundSoundPacket(BuiltInRegistries.SOUND_EVENT.wrapAsHolder(sound), source, this.getX(), this.getY(), this.getZ(), volume, pitch, this.random.nextLong())); + } + + @Override +- @Override +- public ItemEntity drop(ItemStack itemstack, boolean flag, boolean flag1) { +- ItemEntity itementity = super.drop(itemstack, flag, flag1); ++ public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean traceItem) { ++ ItemEntity entityitem = super.drop(droppedItem, dropAround, traceItem); + +- if (itementity == null) { ++ if (entityitem == null) { + return null; + } else { +- this.level().addFreshEntity(itementity); +- ItemStack itemstack1 = itementity.getItem(); ++ this.level().addFreshEntity(entityitem); ++ ItemStack itemstack1 = entityitem.getItem(); + +- if (flag1) { ++ if (traceItem) { + if (!itemstack1.isEmpty()) { +- this.awardStat(Stats.ITEM_DROPPED.get(itemstack1.getItem()), itemstack.getCount()); ++ this.awardStat(Stats.ITEM_DROPPED.get(itemstack1.getItem()), droppedItem.getCount()); + } + + this.awardStat(Stats.DROP); + } + +- return itementity; ++ return entityitem; + } + } + +@@ -1848,65 +2203,62 @@ + return this.textFilter; + } + +- public void setServerLevel(ServerLevel serverlevel) { +- this.setLevel(serverlevel); +- this.gameMode.setLevel(serverlevel); ++ public void setServerLevel(ServerLevel level) { ++ this.setLevel(level); ++ this.gameMode.setLevel(level); + } + + @Nullable +- private static GameType readPlayerMode(@Nullable CompoundTag compoundtag, String s) { +- return compoundtag != null && compoundtag.contains(s, 99) ? GameType.byId(compoundtag.getInt(s)) : null; ++ private static GameType readPlayerMode(@Nullable CompoundTag tag, String key) { ++ return tag != null && tag.contains(key, 99) ? GameType.byId(tag.getInt(key)) : null; + } + +- private GameType calculateGameModeForNewPlayer(@Nullable GameType gametype) { +- GameType gametype1 = this.server.getForcedGameType(); ++ private GameType calculateGameModeForNewPlayer(@Nullable GameType gameType) { ++ GameType enumgamemode1 = this.server.getForcedGameType(); + +- return gametype1 != null ? gametype1 : (gametype != null ? gametype : this.server.getDefaultGameType()); ++ return enumgamemode1 != null ? enumgamemode1 : (gameType != null ? gameType : this.server.getDefaultGameType()); + } + +- public void loadGameTypes(@Nullable CompoundTag compoundtag) { +- this.gameMode.setGameModeForPlayer(this.calculateGameModeForNewPlayer(readPlayerMode(compoundtag, "playerGameType")), readPlayerMode(compoundtag, "previousPlayerGameType")); ++ public void loadGameTypes(@Nullable CompoundTag tag) { ++ this.gameMode.setGameModeForPlayer(this.calculateGameModeForNewPlayer(readPlayerMode(tag, "playerGameType")), readPlayerMode(tag, "previousPlayerGameType")); + } + +- private void storeGameTypes(CompoundTag compoundtag) { +- compoundtag.putInt("playerGameType", this.gameMode.getGameModeForPlayer().getId()); +- GameType gametype = this.gameMode.getPreviousGameModeForPlayer(); ++ private void storeGameTypes(CompoundTag tag) { ++ tag.putInt("playerGameType", this.gameMode.getGameModeForPlayer().getId()); ++ GameType enumgamemode = this.gameMode.getPreviousGameModeForPlayer(); + +- if (gametype != null) { +- compoundtag.putInt("previousPlayerGameType", gametype.getId()); ++ if (enumgamemode != null) { ++ tag.putInt("previousPlayerGameType", enumgamemode.getId()); + } + + } + + @Override +- @Override + public boolean isTextFilteringEnabled() { + return this.textFilteringEnabled; + } + +- public boolean shouldFilterMessageTo(ServerPlayer serverplayer) { +- return serverplayer == this ? false : this.textFilteringEnabled || serverplayer.textFilteringEnabled; ++ public boolean shouldFilterMessageTo(ServerPlayer player) { ++ return player == this ? false : this.textFilteringEnabled || player.textFilteringEnabled; + } + + @Override +- @Override +- public boolean mayInteract(Level level, BlockPos blockpos) { +- return super.mayInteract(level, blockpos) && level.mayInteract(this, blockpos); ++ public boolean mayInteract(Level level, BlockPos pos) { ++ return super.mayInteract(level, pos) && level.mayInteract(this, pos); + } + + @Override +- @Override +- protected void updateUsingItem(ItemStack itemstack) { +- CriteriaTriggers.USING_ITEM.trigger(this, itemstack); +- super.updateUsingItem(itemstack); ++ protected void updateUsingItem(ItemStack usingItem) { ++ CriteriaTriggers.USING_ITEM.trigger(this, usingItem); ++ super.updateUsingItem(usingItem); + } + +- public boolean drop(boolean flag) { +- Inventory inventory = this.getInventory(); +- ItemStack itemstack = inventory.removeFromSelected(flag); ++ public boolean drop(boolean dropStack) { ++ Inventory playerinventory = this.getInventory(); ++ ItemStack itemstack = playerinventory.removeFromSelected(dropStack); + +- this.containerMenu.findSlot(inventory, inventory.selected).ifPresent((i) -> { +- this.containerMenu.setRemoteSlot(i, inventory.getSelected()); ++ this.containerMenu.findSlot(playerinventory, playerinventory.selected).ifPresent((i) -> { ++ this.containerMenu.setRemoteSlot(i, playerinventory.getSelected()); + }); + return this.drop(itemstack, false, true) != null; + } +@@ -1916,25 +2268,23 @@ + } + + @Override +- @Override + public Optional getWardenSpawnTracker() { + return Optional.of(this.wardenSpawnTracker); + } + + @Override +- @Override +- public void onItemPickup(ItemEntity itementity) { +- super.onItemPickup(itementity); +- Entity entity = itementity.getOwner(); ++ public void onItemPickup(ItemEntity itemEntity) { ++ super.onItemPickup(itemEntity); ++ Entity entity = itemEntity.getOwner(); + + if (entity != null) { +- CriteriaTriggers.THROWN_ITEM_PICKED_UP_BY_PLAYER.trigger(this, itementity.getItem(), entity); ++ CriteriaTriggers.THROWN_ITEM_PICKED_UP_BY_PLAYER.trigger(this, itemEntity.getItem(), entity); + } + + } + +- public void setChatSession(RemoteChatSession remotechatsession) { +- this.chatSession = remotechatsession; ++ public void setChatSession(RemoteChatSession chatSession) { ++ this.chatSession = chatSession; + } + + @Nullable +@@ -1943,28 +2293,26 @@ + } + + @Override +- @Override +- public void indicateDamage(double d0, double d1) { +- this.hurtDir = (float) (Mth.atan2(d1, d0) * 57.2957763671875D - (double) this.getYRot()); ++ public void indicateDamage(double xDistance, double d1) { ++ this.hurtDir = (float) (Mth.atan2(d1, xDistance) * 57.2957763671875D - (double) this.getYRot()); + this.connection.send(new ClientboundHurtAnimationPacket(this)); + } + + @Override +- @Override +- public boolean startRiding(Entity entity, boolean flag) { +- if (!super.startRiding(entity, flag)) { ++ public boolean startRiding(Entity vehicle, boolean force) { ++ if (!super.startRiding(vehicle, force)) { + return false; + } else { +- entity.positionRider(this); ++ vehicle.positionRider(this); + this.connection.teleport(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); +- if (entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; +- Iterator iterator = livingentity.getActiveEffects().iterator(); ++ if (vehicle instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) vehicle; ++ Iterator iterator = entityliving.getActiveEffects().iterator(); + + while (iterator.hasNext()) { +- MobEffectInstance mobeffectinstance = (MobEffectInstance) iterator.next(); ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); + +- this.connection.send(new ClientboundUpdateMobEffectPacket(entity.getId(), mobeffectinstance)); ++ this.connection.send(new ClientboundUpdateMobEffectPacket(vehicle.getId(), mobeffect)); + } + } + +@@ -1973,25 +2321,166 @@ + } + + @Override +- @Override + public void stopRiding() { + Entity entity = this.getVehicle(); + + super.stopRiding(); + if (entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; +- Iterator iterator = livingentity.getActiveEffects().iterator(); ++ LivingEntity entityliving = (LivingEntity) entity; ++ Iterator iterator = entityliving.getActiveEffects().iterator(); + + while (iterator.hasNext()) { +- MobEffectInstance mobeffectinstance = (MobEffectInstance) iterator.next(); ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); + +- this.connection.send(new ClientboundRemoveMobEffectPacket(entity.getId(), mobeffectinstance.getEffect())); ++ this.connection.send(new ClientboundRemoveMobEffectPacket(entity.getId(), mobeffect.getEffect())); + } + } + + } + +- public CommonPlayerSpawnInfo createCommonSpawnInfo(ServerLevel serverlevel) { +- return new CommonPlayerSpawnInfo(serverlevel.dimensionTypeId(), serverlevel.dimension(), BiomeManager.obfuscateSeed(serverlevel.getSeed()), this.gameMode.getGameModeForPlayer(), this.gameMode.getPreviousGameModeForPlayer(), serverlevel.isDebug(), serverlevel.isFlat(), this.getLastDeathLocation(), this.getPortalCooldown()); ++ public CommonPlayerSpawnInfo createCommonSpawnInfo(ServerLevel worldserver) { ++ return new CommonPlayerSpawnInfo(worldserver.dimensionTypeId(), worldserver.dimension(), BiomeManager.obfuscateSeed(worldserver.getSeed()), this.gameMode.getGameModeForPlayer(), this.gameMode.getPreviousGameModeForPlayer(), worldserver.isDebug(), worldserver.isFlat(), this.getLastDeathLocation(), this.getPortalCooldown()); + } ++ ++ // CraftBukkit start - Add per-player time and weather. ++ public long timeOffset = 0; ++ public boolean relativeTime = true; ++ ++ public long getPlayerTime() { ++ if (this.relativeTime) { ++ // Adds timeOffset to the current server time. ++ return this.level().getDayTime() + this.timeOffset; ++ } else { ++ // Adds timeOffset to the beginning of this day. ++ return this.level().getDayTime() - (this.level().getDayTime() % 24000) + this.timeOffset; ++ } ++ } ++ ++ public WeatherType weather = null; ++ ++ public WeatherType getPlayerWeather() { ++ return this.weather; ++ } ++ ++ public void setPlayerWeather(WeatherType type, boolean plugin) { ++ if (!plugin && this.weather != null) { ++ return; ++ } ++ ++ if (plugin) { ++ this.weather = type; ++ } ++ ++ if (type == WeatherType.DOWNFALL) { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.STOP_RAINING, 0)); ++ } else { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.START_RAINING, 0)); ++ } ++ } ++ ++ private float pluginRainPosition; ++ private float pluginRainPositionPrevious; ++ ++ public void updateWeather(float oldRain, float newRain, float oldThunder, float newThunder) { ++ if (this.weather == null) { ++ // Vanilla ++ if (oldRain != newRain) { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, newRain)); ++ } ++ } else { ++ // Plugin ++ if (pluginRainPositionPrevious != pluginRainPosition) { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, pluginRainPosition)); ++ } ++ } ++ ++ if (oldThunder != newThunder) { ++ if (weather == WeatherType.DOWNFALL || weather == null) { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, newThunder)); ++ } else { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, 0)); ++ } ++ } ++ } ++ ++ public void tickWeather() { ++ if (this.weather == null) return; ++ ++ pluginRainPositionPrevious = pluginRainPosition; ++ if (weather == WeatherType.DOWNFALL) { ++ pluginRainPosition += 0.01; ++ } else { ++ pluginRainPosition -= 0.01; ++ } ++ ++ pluginRainPosition = Mth.clamp(pluginRainPosition, 0.0F, 1.0F); ++ } ++ ++ public void resetPlayerWeather() { ++ this.weather = null; ++ this.setPlayerWeather(this.level().getLevelData().isRaining() ? WeatherType.DOWNFALL : WeatherType.CLEAR, false); ++ } ++ ++ @Override ++ public String toString() { ++ return super.toString() + "(" + this.getScoreboardName() + " at " + this.getX() + "," + this.getY() + "," + this.getZ() + ")"; ++ } ++ ++ // SPIGOT-1903, MC-98153 ++ public void forceSetPositionRotation(double x, double y, double z, float yaw, float pitch) { ++ this.moveTo(x, y, z, yaw, pitch); ++ this.connection.resetPosition(); ++ } ++ ++ @Override ++ public boolean isImmobile() { ++ return super.isImmobile() || !getBukkitEntity().isOnline(); ++ } ++ ++ @Override ++ public Scoreboard getScoreboard() { ++ return getBukkitEntity().getScoreboard().getHandle(); ++ } ++ ++ public void reset() { ++ float exp = 0; ++ boolean keepInventory = this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY); ++ ++ if (this.keepLevel) { // CraftBukkit - SPIGOT-6687: Only use keepLevel (was pre-set with RULE_KEEPINVENTORY value in PlayerDeathEvent) ++ exp = this.experienceProgress; ++ this.newTotalExp = this.totalExperience; ++ this.newLevel = this.experienceLevel; ++ } ++ ++ this.setHealth(this.getMaxHealth()); ++ this.stopUsingItem(); // CraftBukkit - SPIGOT-6682: Clear active item on reset ++ this.setRemainingFireTicks(0); ++ this.fallDistance = 0; ++ this.foodData = new FoodData(this); ++ this.experienceLevel = this.newLevel; ++ this.totalExperience = this.newTotalExp; ++ this.experienceProgress = 0; ++ this.deathTime = 0; ++ this.setArrowCount(0, true); // CraftBukkit - ArrowBodyCountChangeEvent ++ this.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.DEATH); ++ this.effectsDirty = true; ++ this.containerMenu = this.inventoryMenu; ++ this.lastHurtByPlayer = null; ++ this.lastHurtByMob = null; ++ this.combatTracker = new CombatTracker(this); ++ this.lastSentExp = -1; ++ if (this.keepLevel) { // CraftBukkit - SPIGOT-6687: Only use keepLevel (was pre-set with RULE_KEEPINVENTORY value in PlayerDeathEvent) ++ this.experienceProgress = exp; ++ } else { ++ this.giveExperiencePoints(this.newExp); ++ } ++ this.keepLevel = false; ++ this.setDeltaMovement(0, 0, 0); // CraftBukkit - SPIGOT-6948: Reset velocity on death ++ } ++ ++ @Override ++ public CraftPlayer getBukkitEntity() { ++ return (CraftPlayer) super.getBukkitEntity(); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/level/ServerPlayerGameMode.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/level/ServerPlayerGameMode.java.patch new file mode 100644 index 0000000000..78a8dc985d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/level/ServerPlayerGameMode.java.patch @@ -0,0 +1,669 @@ +--- a/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -9,22 +9,42 @@ + import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; + import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; + import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; +-import net.minecraft.server.network.ServerGamePacketListenerImpl; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; ++import net.minecraft.world.ITileInventory; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; +-import net.minecraft.world.MenuProvider; ++import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.item.DoubleHighBlockItem; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.GameType; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.GameMasterBlock; ++import net.minecraft.world.level.block.TrapDoorBlock; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; ++import org.slf4j.Logger; ++ ++// CraftBukkit start ++import java.util.ArrayList; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.network.ServerGamePacketListenerImpl; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.CakeBlock; ++import net.minecraft.world.level.block.DoorBlock; ++import net.minecraft.world.level.block.state.properties.BlockPropertyDoubleBlockHalf; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; +-import org.slf4j.Logger; ++import org.bukkit.GameMode; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockBreakEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.Event; ++import org.bukkit.event.block.Action; ++import org.bukkit.event.player.PlayerGameModeChangeEvent; ++import org.bukkit.event.player.PlayerInteractEvent; ++// CraftBukkit end + + public class ServerPlayerGameMode { + +@@ -43,31 +63,38 @@ + private int delayedTickStart; + private int lastSentState; + +- public ServerPlayerGameMode(ServerPlayer serverplayer) { ++ public ServerPlayerGameMode(ServerPlayer player) { + this.gameModeForPlayer = GameType.DEFAULT_MODE; + this.destroyPos = BlockPos.ZERO; + this.delayedDestroyPos = BlockPos.ZERO; + this.lastSentState = -1; +- this.player = serverplayer; +- this.level = serverplayer.serverLevel(); ++ this.player = player; ++ this.level = player.serverLevel(); + } + +- public boolean changeGameModeForPlayer(GameType gametype) { +- if (gametype == this.gameModeForPlayer) { ++ public boolean changeGameModeForPlayer(GameType gameModeForPlayer) { ++ if (gameModeForPlayer == this.gameModeForPlayer) { + return false; + } else { +- this.setGameModeForPlayer(gametype, this.previousGameModeForPlayer); ++ // CraftBukkit start ++ PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(player.getBukkitEntity(), GameMode.getByValue(gameModeForPlayer.getId())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ this.setGameModeForPlayer(gameModeForPlayer, this.previousGameModeForPlayer); + this.player.onUpdateAbilities(); +- this.player.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player)); ++ this.player.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player), this.player); // CraftBukkit + this.level.updateSleepingPlayerList(); + return true; + } + } + +- protected void setGameModeForPlayer(GameType gametype, @Nullable GameType gametype1) { +- this.previousGameModeForPlayer = gametype1; +- this.gameModeForPlayer = gametype; +- gametype.updatePlayerAbilities(this.player.getAbilities()); ++ protected void setGameModeForPlayer(GameType gameModeForPlayer, @Nullable GameType previousGameModeForPlayer) { ++ this.previousGameModeForPlayer = previousGameModeForPlayer; ++ this.gameModeForPlayer = gameModeForPlayer; ++ gameModeForPlayer.updatePlayerAbilities(this.player.getAbilities()); + } + + public GameType getGameModeForPlayer() { +@@ -88,15 +115,15 @@ + } + + public void tick() { +- ++this.gameTicks; +- BlockState blockstate; ++ this.gameTicks = MinecraftServer.currentTick; // CraftBukkit; ++ IBlockData iblockdata; + + if (this.hasDelayedDestroy) { +- blockstate = this.level.getBlockState(this.delayedDestroyPos); +- if (blockstate.isAir()) { ++ iblockdata = this.level.getBlockState(this.delayedDestroyPos); ++ if (iblockdata.isAir()) { + this.hasDelayedDestroy = false; + } else { +- float f = this.incrementDestroyProgress(blockstate, this.delayedDestroyPos, this.delayedTickStart); ++ float f = this.incrementDestroyProgress(iblockdata, this.delayedDestroyPos, this.delayedTickStart); + + if (f >= 1.0F) { + this.hasDelayedDestroy = false; +@@ -104,193 +131,321 @@ + } + } + } else if (this.isDestroyingBlock) { +- blockstate = this.level.getBlockState(this.destroyPos); +- if (blockstate.isAir()) { ++ iblockdata = this.level.getBlockState(this.destroyPos); ++ if (iblockdata.isAir()) { + this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); + this.lastSentState = -1; + this.isDestroyingBlock = false; + } else { +- this.incrementDestroyProgress(blockstate, this.destroyPos, this.destroyProgressStart); ++ this.incrementDestroyProgress(iblockdata, this.destroyPos, this.destroyProgressStart); + } + } + + } + +- private float incrementDestroyProgress(BlockState blockstate, BlockPos blockpos, int i) { +- int j = this.gameTicks - i; +- float f = blockstate.getDestroyProgress(this.player, this.player.level(), blockpos) * (float) (j + 1); ++ private float incrementDestroyProgress(IBlockData state, BlockPos pos, int startTick) { ++ int j = this.gameTicks - startTick; ++ float f = state.getDestroyProgress(this.player, this.player.level(), pos) * (float) (j + 1); + int k = (int) (f * 10.0F); + + if (k != this.lastSentState) { +- this.level.destroyBlockProgress(this.player.getId(), blockpos, k); ++ this.level.destroyBlockProgress(this.player.getId(), pos, k); + this.lastSentState = k; + } + + return f; + } + +- private void debugLogging(BlockPos blockpos, boolean flag, int i, String s) {} ++ private void debugLogging(BlockPos pos, boolean flag, int sequence, String message) {} + +- public void handleBlockBreakAction(BlockPos blockpos, ServerboundPlayerActionPacket.Action serverboundplayeractionpacket_action, Direction direction, int i, int j) { +- if (this.player.getEyePosition().distanceToSqr(Vec3.atCenterOf(blockpos)) > ServerGamePacketListenerImpl.MAX_INTERACTION_DISTANCE) { +- this.debugLogging(blockpos, false, j, "too far"); +- } else if (blockpos.getY() >= i) { +- this.player.connection.send(new ClientboundBlockUpdatePacket(blockpos, this.level.getBlockState(blockpos))); +- this.debugLogging(blockpos, false, j, "too high"); ++ public void handleBlockBreakAction(BlockPos pos, ServerboundPlayerActionPacket.EnumPlayerDigType action, Direction face, int maxBuildHeight, int sequence) { ++ if (this.player.getEyePosition().distanceToSqr(Vec3.atCenterOf(pos)) > ServerGamePacketListenerImpl.MAX_INTERACTION_DISTANCE) { ++ this.debugLogging(pos, false, sequence, "too far"); ++ } else if (pos.getY() >= maxBuildHeight) { ++ this.player.connection.send(new ClientboundBlockUpdatePacket(pos, this.level.getBlockState(pos))); ++ this.debugLogging(pos, false, sequence, "too high"); + } else { +- BlockState blockstate; ++ IBlockData iblockdata; + +- if (serverboundplayeractionpacket_action == ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK) { +- if (!this.level.mayInteract(this.player, blockpos)) { +- this.player.connection.send(new ClientboundBlockUpdatePacket(blockpos, this.level.getBlockState(blockpos))); +- this.debugLogging(blockpos, false, j, "may not interact"); ++ if (action == ServerboundPlayerActionPacket.EnumPlayerDigType.START_DESTROY_BLOCK) { ++ if (!this.level.mayInteract(this.player, pos)) { ++ // CraftBukkit start - fire PlayerInteractEvent ++ CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, pos, face, this.player.getInventory().getSelected(), EnumHand.MAIN_HAND); ++ this.player.connection.send(new ClientboundBlockUpdatePacket(pos, this.level.getBlockState(pos))); ++ this.debugLogging(pos, false, sequence, "may not interact"); ++ // Update any tile entity data for this block ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ if (tileentity != null) { ++ this.player.connection.send(tileentity.getUpdatePacket()); ++ } ++ // CraftBukkit end + return; + } + ++ // CraftBukkit start ++ PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, pos, face, this.player.getInventory().getSelected(), EnumHand.MAIN_HAND); ++ if (event.isCancelled()) { ++ // Let the client know the block still exists ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ // Update any tile entity data for this block ++ BlockEntity tileentity = this.level.getBlockEntity(pos); ++ if (tileentity != null) { ++ this.player.connection.send(tileentity.getUpdatePacket()); ++ } ++ return; ++ } ++ // CraftBukkit end ++ + if (this.isCreative()) { +- this.destroyAndAck(blockpos, j, "creative destroy"); ++ this.destroyAndAck(pos, sequence, "creative destroy"); + return; + } + +- if (this.player.blockActionRestricted(this.level, blockpos, this.gameModeForPlayer)) { +- this.player.connection.send(new ClientboundBlockUpdatePacket(blockpos, this.level.getBlockState(blockpos))); +- this.debugLogging(blockpos, false, j, "block action restricted"); ++ if (this.player.blockActionRestricted(this.level, pos, this.gameModeForPlayer)) { ++ this.player.connection.send(new ClientboundBlockUpdatePacket(pos, this.level.getBlockState(pos))); ++ this.debugLogging(pos, false, sequence, "block action restricted"); + return; + } + + this.destroyProgressStart = this.gameTicks; + float f = 1.0F; + +- blockstate = this.level.getBlockState(blockpos); +- if (!blockstate.isAir()) { +- blockstate.attack(this.level, blockpos, this.player); +- f = blockstate.getDestroyProgress(this.player, this.player.level(), blockpos); ++ iblockdata = this.level.getBlockState(pos); ++ // CraftBukkit start - Swings at air do *NOT* exist. ++ if (event.useInteractedBlock() == Event.Result.DENY) { ++ // If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door. ++ IBlockData data = this.level.getBlockState(pos); ++ if (data.getBlock() instanceof DoorBlock) { ++ // For some reason *BOTH* the bottom/top part have to be marked updated. ++ boolean bottom = data.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER; ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, bottom ? pos.above() : pos.below())); ++ } else if (data.getBlock() instanceof TrapDoorBlock) { ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ } ++ } else if (!iblockdata.isAir()) { ++ iblockdata.attack(this.level, pos, this.player); ++ f = iblockdata.getDestroyProgress(this.player, this.player.level(), pos); + } + +- if (!blockstate.isAir() && f >= 1.0F) { +- this.destroyAndAck(blockpos, j, "insta mine"); ++ if (event.useItemInHand() == Event.Result.DENY) { ++ // If we 'insta destroyed' then the client needs to be informed. ++ if (f > 1.0f) { ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ } ++ return; ++ } ++ org.bukkit.event.block.BlockDamageEvent blockEvent = CraftEventFactory.callBlockDamageEvent(this.player, pos, this.player.getInventory().getSelected(), f >= 1.0f); ++ ++ if (blockEvent.isCancelled()) { ++ // Let the client know the block still exists ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ return; ++ } ++ ++ if (blockEvent.getInstaBreak()) { ++ f = 2.0f; ++ } ++ // CraftBukkit end ++ ++ if (!iblockdata.isAir() && f >= 1.0F) { ++ this.destroyAndAck(pos, sequence, "insta mine"); + } else { + if (this.isDestroyingBlock) { + this.player.connection.send(new ClientboundBlockUpdatePacket(this.destroyPos, this.level.getBlockState(this.destroyPos))); +- this.debugLogging(blockpos, false, j, "abort destroying since another started (client insta mine, server disagreed)"); ++ this.debugLogging(pos, false, sequence, "abort destroying since another started (client insta mine, server disagreed)"); + } + + this.isDestroyingBlock = true; +- this.destroyPos = blockpos.immutable(); ++ this.destroyPos = pos.immutable(); + int k = (int) (f * 10.0F); + +- this.level.destroyBlockProgress(this.player.getId(), blockpos, k); +- this.debugLogging(blockpos, true, j, "actual start of destroying"); ++ this.level.destroyBlockProgress(this.player.getId(), pos, k); ++ this.debugLogging(pos, true, sequence, "actual start of destroying"); + this.lastSentState = k; + } +- } else if (serverboundplayeractionpacket_action == ServerboundPlayerActionPacket.Action.STOP_DESTROY_BLOCK) { +- if (blockpos.equals(this.destroyPos)) { ++ } else if (action == ServerboundPlayerActionPacket.EnumPlayerDigType.STOP_DESTROY_BLOCK) { ++ if (pos.equals(this.destroyPos)) { + int l = this.gameTicks - this.destroyProgressStart; + +- blockstate = this.level.getBlockState(blockpos); +- if (!blockstate.isAir()) { +- float f1 = blockstate.getDestroyProgress(this.player, this.player.level(), blockpos) * (float) (l + 1); ++ iblockdata = this.level.getBlockState(pos); ++ if (!iblockdata.isAir()) { ++ float f1 = iblockdata.getDestroyProgress(this.player, this.player.level(), pos) * (float) (l + 1); + + if (f1 >= 0.7F) { + this.isDestroyingBlock = false; +- this.level.destroyBlockProgress(this.player.getId(), blockpos, -1); +- this.destroyAndAck(blockpos, j, "destroyed"); ++ this.level.destroyBlockProgress(this.player.getId(), pos, -1); ++ this.destroyAndAck(pos, sequence, "destroyed"); + return; + } + + if (!this.hasDelayedDestroy) { + this.isDestroyingBlock = false; + this.hasDelayedDestroy = true; +- this.delayedDestroyPos = blockpos; ++ this.delayedDestroyPos = pos; + this.delayedTickStart = this.destroyProgressStart; + } + } + } + +- this.debugLogging(blockpos, true, j, "stopped destroying"); +- } else if (serverboundplayeractionpacket_action == ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK) { ++ this.debugLogging(pos, true, sequence, "stopped destroying"); ++ } else if (action == ServerboundPlayerActionPacket.EnumPlayerDigType.ABORT_DESTROY_BLOCK) { + this.isDestroyingBlock = false; +- if (!Objects.equals(this.destroyPos, blockpos)) { +- ServerPlayerGameMode.LOGGER.warn("Mismatch in destroy block pos: {} {}", this.destroyPos, blockpos); ++ if (!Objects.equals(this.destroyPos, pos)) { ++ ServerPlayerGameMode.LOGGER.debug("Mismatch in destroy block pos: {} {}", this.destroyPos, pos); // CraftBukkit - SPIGOT-5457 sent by client when interact event cancelled + this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); +- this.debugLogging(blockpos, true, j, "aborted mismatched destroying"); ++ this.debugLogging(pos, true, sequence, "aborted mismatched destroying"); + } + +- this.level.destroyBlockProgress(this.player.getId(), blockpos, -1); +- this.debugLogging(blockpos, true, j, "aborted destroying"); ++ this.level.destroyBlockProgress(this.player.getId(), pos, -1); ++ this.debugLogging(pos, true, sequence, "aborted destroying"); ++ ++ CraftEventFactory.callBlockDamageAbortEvent(this.player, pos, this.player.getInventory().getSelected()); // CraftBukkit + } + + } + } + +- public void destroyAndAck(BlockPos blockpos, int i, String s) { +- if (this.destroyBlock(blockpos)) { +- this.debugLogging(blockpos, true, i, s); ++ public void destroyAndAck(BlockPos pos, int sequence, String message) { ++ if (this.destroyBlock(pos)) { ++ this.debugLogging(pos, true, sequence, message); + } else { +- this.player.connection.send(new ClientboundBlockUpdatePacket(blockpos, this.level.getBlockState(blockpos))); +- this.debugLogging(blockpos, false, i, s); ++ this.player.connection.send(new ClientboundBlockUpdatePacket(pos, this.level.getBlockState(pos))); ++ this.debugLogging(pos, false, sequence, message); + } + + } + +- public boolean destroyBlock(BlockPos blockpos) { +- BlockState blockstate = this.level.getBlockState(blockpos); ++ public boolean destroyBlock(BlockPos pos) { ++ IBlockData iblockdata = this.level.getBlockState(pos); ++ // CraftBukkit start - fire BlockBreakEvent ++ org.bukkit.block.Block bblock = CraftBlock.at(level, pos); ++ BlockBreakEvent event = null; + +- if (!this.player.getMainHandItem().getItem().canAttackBlock(blockstate, this.level, blockpos, this.player)) { ++ if (this.player instanceof ServerPlayer) { ++ // Sword + Creative mode pre-cancel ++ boolean isSwordNoBreak = !this.player.getMainHandItem().getItem().canAttackBlock(iblockdata, this.level, pos, this.player); ++ ++ // Tell client the block is gone immediately then process events ++ // Don't tell the client if its a creative sword break because its not broken! ++ if (level.getBlockEntity(pos) == null && !isSwordNoBreak) { ++ ClientboundBlockUpdatePacket packet = new ClientboundBlockUpdatePacket(pos, Blocks.AIR.defaultBlockState()); ++ this.player.connection.send(packet); ++ } ++ ++ event = new BlockBreakEvent(bblock, this.player.getBukkitEntity()); ++ ++ // Sword + Creative mode pre-cancel ++ event.setCancelled(isSwordNoBreak); ++ ++ // Calculate default block experience ++ IBlockData nmsData = this.level.getBlockState(pos); ++ Block nmsBlock = nmsData.getBlock(); ++ ++ ItemStack itemstack = this.player.getItemBySlot(EquipmentSlot.MAINHAND); ++ ++ if (nmsBlock != null && !event.isCancelled() && !this.isCreative() && this.player.hasCorrectToolForDrops(nmsBlock.defaultBlockState())) { ++ event.setExpToDrop(nmsBlock.getExpDrop(nmsData, this.level, pos, itemstack, true)); ++ } ++ ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ if (isSwordNoBreak) { ++ return false; ++ } ++ // Let the client know the block still exists ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ ++ // Brute force all possible updates ++ for (Direction dir : Direction.values()) { ++ this.player.connection.send(new ClientboundBlockUpdatePacket(level, pos.relative(dir))); ++ } ++ ++ // Update any tile entity data for this block ++ BlockEntity tileentity = this.level.getBlockEntity(pos); ++ if (tileentity != null) { ++ this.player.connection.send(tileentity.getUpdatePacket()); ++ } ++ return false; ++ } ++ } ++ // CraftBukkit end ++ ++ if (false && !this.player.getMainHandItem().getItem().canAttackBlock(iblockdata, this.level, pos, this.player)) { // CraftBukkit - false + return false; + } else { +- BlockEntity blockentity = this.level.getBlockEntity(blockpos); +- Block block = blockstate.getBlock(); ++ iblockdata = this.level.getBlockState(pos); // CraftBukkit - update state from plugins ++ if (iblockdata.isAir()) return false; // CraftBukkit - A plugin set block to air without cancelling ++ BlockEntity tileentity = this.level.getBlockEntity(pos); ++ Block block = iblockdata.getBlock(); + + if (block instanceof GameMasterBlock && !this.player.canUseGameMasterBlocks()) { +- this.level.sendBlockUpdated(blockpos, blockstate, blockstate, 3); ++ this.level.sendBlockUpdated(pos, iblockdata, iblockdata, 3); + return false; +- } else if (this.player.blockActionRestricted(this.level, blockpos, this.gameModeForPlayer)) { ++ } else if (this.player.blockActionRestricted(this.level, pos, this.gameModeForPlayer)) { + return false; + } else { +- BlockState blockstate1 = block.playerWillDestroy(this.level, blockpos, blockstate, this.player); +- boolean flag = this.level.removeBlock(blockpos, false); ++ // CraftBukkit start ++ org.bukkit.block.BlockState state = bblock.getState(); ++ level.captureDrops = new ArrayList<>(); ++ // CraftBukkit end ++ IBlockData iblockdata1 = block.playerWillDestroy(this.level, pos, iblockdata, this.player); ++ boolean flag = this.level.removeBlock(pos, false); + + if (flag) { +- block.destroy(this.level, blockpos, blockstate1); ++ block.destroy(this.level, pos, iblockdata1); + } + + if (this.isCreative()) { +- return true; ++ // return true; // CraftBukkit + } else { + ItemStack itemstack = this.player.getMainHandItem(); + ItemStack itemstack1 = itemstack.copy(); +- boolean flag1 = this.player.hasCorrectToolForDrops(blockstate1); ++ boolean flag1 = this.player.hasCorrectToolForDrops(iblockdata1); + +- itemstack.mineBlock(this.level, blockstate1, blockpos, this.player); +- if (flag && flag1) { +- block.playerDestroy(this.level, this.player, blockpos, blockstate1, blockentity, itemstack1); ++ itemstack.mineBlock(this.level, iblockdata1, pos, this.player); ++ if (flag && flag1 && event.isDropItems()) { // CraftBukkit - Check if block should drop items ++ block.playerDestroy(this.level, this.player, pos, iblockdata1, tileentity, itemstack1); + } + +- return true; ++ // return true; // CraftBukkit + } ++ // CraftBukkit start ++ if (event.isDropItems()) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, level.captureDrops); ++ } ++ level.captureDrops = null; ++ ++ // Drop event experience ++ if (flag && event != null) { ++ iblockdata.getBlock().popExperience(this.level, pos, event.getExpToDrop()); ++ } ++ ++ return true; ++ // CraftBukkit end + } + } + } + +- public InteractionResult useItem(ServerPlayer serverplayer, Level level, ItemStack itemstack, InteractionHand interactionhand) { ++ public InteractionResult useItem(ServerPlayer player, Level level, ItemStack stack, EnumHand hand) { + if (this.gameModeForPlayer == GameType.SPECTATOR) { + return InteractionResult.PASS; +- } else if (serverplayer.getCooldowns().isOnCooldown(itemstack.getItem())) { ++ } else if (player.getCooldowns().isOnCooldown(stack.getItem())) { + return InteractionResult.PASS; + } else { +- int i = itemstack.getCount(); +- int j = itemstack.getDamageValue(); +- InteractionResultHolder interactionresultholder = itemstack.use(level, serverplayer, interactionhand); +- ItemStack itemstack1 = (ItemStack) interactionresultholder.getObject(); ++ int i = stack.getCount(); ++ int j = stack.getDamageValue(); ++ InteractionResultHolder interactionresultwrapper = stack.use(level, player, hand); ++ ItemStack itemstack1 = (ItemStack) interactionresultwrapper.getObject(); + +- if (itemstack1 == itemstack && itemstack1.getCount() == i && itemstack1.getUseDuration() <= 0 && itemstack1.getDamageValue() == j) { +- return interactionresultholder.getResult(); +- } else if (interactionresultholder.getResult() == InteractionResult.FAIL && itemstack1.getUseDuration() > 0 && !serverplayer.isUsingItem()) { +- return interactionresultholder.getResult(); ++ if (itemstack1 == stack && itemstack1.getCount() == i && itemstack1.getUseDuration() <= 0 && itemstack1.getDamageValue() == j) { ++ return interactionresultwrapper.getResult(); ++ } else if (interactionresultwrapper.getResult() == InteractionResult.FAIL && itemstack1.getUseDuration() > 0 && !player.isUsingItem()) { ++ return interactionresultwrapper.getResult(); + } else { +- if (itemstack != itemstack1) { +- serverplayer.setItemInHand(interactionhand, itemstack1); ++ if (stack != itemstack1) { ++ player.setItemInHand(hand, itemstack1); + } + + if (this.isCreative() && itemstack1 != ItemStack.EMPTY) { +@@ -301,72 +456,112 @@ + } + + if (itemstack1.isEmpty()) { +- serverplayer.setItemInHand(interactionhand, ItemStack.EMPTY); ++ player.setItemInHand(hand, ItemStack.EMPTY); + } + +- if (!serverplayer.isUsingItem()) { +- serverplayer.inventoryMenu.sendAllDataToRemote(); ++ if (!player.isUsingItem()) { ++ player.inventoryMenu.sendAllDataToRemote(); + } + +- return interactionresultholder.getResult(); ++ return interactionresultwrapper.getResult(); + } + } + } + +- public InteractionResult useItemOn(ServerPlayer serverplayer, Level level, ItemStack itemstack, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- BlockPos blockpos = blockhitresult.getBlockPos(); +- BlockState blockstate = level.getBlockState(blockpos); ++ // CraftBukkit start - whole method ++ public boolean interactResult = false; ++ public boolean firedInteract = false; ++ public BlockPos interactPosition; ++ public EnumHand interactHand; ++ public ItemStack interactItemStack; ++ public InteractionResult useItemOn(ServerPlayer player, Level level, ItemStack stack, EnumHand hand, BlockHitResult hitResult) { ++ BlockPos blockposition = hitResult.getBlockPos(); ++ IBlockData iblockdata = level.getBlockState(blockposition); ++ InteractionResult enuminteractionresult = InteractionResult.PASS; ++ boolean cancelledBlock = false; + +- if (!blockstate.getBlock().isEnabled(level.enabledFeatures())) { ++ if (!iblockdata.getBlock().isEnabled(level.enabledFeatures())) { + return InteractionResult.FAIL; + } else if (this.gameModeForPlayer == GameType.SPECTATOR) { +- MenuProvider menuprovider = blockstate.getMenuProvider(level, blockpos); ++ ITileInventory itileinventory = iblockdata.getMenuProvider(level, blockposition); ++ cancelledBlock = !(itileinventory instanceof ITileInventory); ++ } + +- if (menuprovider != null) { +- serverplayer.openMenu(menuprovider); ++ if (player.getCooldowns().isOnCooldown(stack.getItem())) { ++ cancelledBlock = true; ++ } ++ ++ PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, blockposition, hitResult.getDirection(), stack, cancelledBlock, hand, hitResult.getLocation()); ++ firedInteract = true; ++ interactResult = event.useItemInHand() == Event.Result.DENY; ++ interactPosition = blockposition.immutable(); ++ interactHand = hand; ++ interactItemStack = stack.copy(); ++ ++ if (event.useInteractedBlock() == Event.Result.DENY) { ++ // If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door. ++ if (iblockdata.getBlock() instanceof DoorBlock) { ++ boolean bottom = iblockdata.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER; ++ player.connection.send(new ClientboundBlockUpdatePacket(level, bottom ? blockposition.above() : blockposition.below())); ++ } else if (iblockdata.getBlock() instanceof CakeBlock) { ++ player.getBukkitEntity().sendHealthUpdate(); // SPIGOT-1341 - reset health for cake ++ } else if (interactItemStack.getItem() instanceof DoubleHighBlockItem) { ++ // send a correcting update to the client, as it already placed the upper half of the bisected item ++ player.connection.send(new ClientboundBlockUpdatePacket(level, blockposition.relative(hitResult.getDirection()).above())); ++ ++ // send a correcting update to the client for the block above as well, this because of replaceable blocks (such as grass, sea grass etc) ++ player.connection.send(new ClientboundBlockUpdatePacket(level, blockposition.above())); ++ } ++ player.getBukkitEntity().updateInventory(); // SPIGOT-2867 ++ enuminteractionresult = (event.useItemInHand() != Event.Result.ALLOW) ? InteractionResult.SUCCESS : InteractionResult.PASS; ++ } else if (this.gameModeForPlayer == GameType.SPECTATOR) { ++ ITileInventory itileinventory = iblockdata.getMenuProvider(level, blockposition); ++ ++ if (itileinventory != null) { ++ player.openMenu(itileinventory); + return InteractionResult.SUCCESS; + } else { + return InteractionResult.PASS; + } + } else { +- boolean flag = !serverplayer.getMainHandItem().isEmpty() || !serverplayer.getOffhandItem().isEmpty(); +- boolean flag1 = serverplayer.isSecondaryUseActive() && flag; +- ItemStack itemstack1 = itemstack.copy(); ++ boolean flag = !player.getMainHandItem().isEmpty() || !player.getOffhandItem().isEmpty(); ++ boolean flag1 = player.isSecondaryUseActive() && flag; ++ ItemStack itemstack1 = stack.copy(); + + if (!flag1) { +- InteractionResult interactionresult = blockstate.use(level, serverplayer, interactionhand, blockhitresult); ++ enuminteractionresult = iblockdata.use(level, player, hand, hitResult); + +- if (interactionresult.consumesAction()) { +- CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(serverplayer, blockpos, itemstack1); +- return interactionresult; ++ if (enuminteractionresult.consumesAction()) { ++ CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(player, blockposition, itemstack1); ++ return enuminteractionresult; + } + } + +- if (!itemstack.isEmpty() && !serverplayer.getCooldowns().isOnCooldown(itemstack.getItem())) { +- UseOnContext useoncontext = new UseOnContext(serverplayer, interactionhand, blockhitresult); +- InteractionResult interactionresult1; ++ if (!stack.isEmpty() && enuminteractionresult != InteractionResult.SUCCESS && !interactResult) { // add !interactResult SPIGOT-764 ++ UseOnContext itemactioncontext = new UseOnContext(player, hand, hitResult); ++ InteractionResult enuminteractionresult1; + + if (this.isCreative()) { +- int i = itemstack.getCount(); ++ int i = stack.getCount(); + +- interactionresult1 = itemstack.useOn(useoncontext); +- itemstack.setCount(i); ++ enuminteractionresult1 = stack.useOn(itemactioncontext); ++ stack.setCount(i); + } else { +- interactionresult1 = itemstack.useOn(useoncontext); ++ enuminteractionresult1 = stack.useOn(itemactioncontext); + } + +- if (interactionresult1.consumesAction()) { +- CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(serverplayer, blockpos, itemstack1); ++ if (enuminteractionresult1.consumesAction()) { ++ CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(player, blockposition, itemstack1); + } + +- return interactionresult1; +- } else { +- return InteractionResult.PASS; ++ return enuminteractionresult1; + } + } ++ return enuminteractionresult; ++ // CraftBukkit end + } + +- public void setLevel(ServerLevel serverlevel) { +- this.level = serverlevel; ++ public void setLevel(ServerLevel serverLevel) { ++ this.level = serverLevel; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/level/TicketType.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/level/TicketType.java.patch new file mode 100644 index 0000000000..18da33a426 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/level/TicketType.java.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/server/level/TicketType.java ++++ b/net/minecraft/server/level/TicketType.java +@@ -10,7 +10,7 @@ + + private final String name; + private final Comparator comparator; +- private final long timeout; ++ public long timeout; + public static final TicketType START = create("start", (unit, unit1) -> { + return 0; + }); +@@ -23,22 +23,23 @@ + public static final TicketType PORTAL = create("portal", Vec3i::compareTo, 300); + public static final TicketType POST_TELEPORT = create("post_teleport", Integer::compareTo, 5); + public static final TicketType UNKNOWN = create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1); ++ public static final TicketType PLUGIN = create("plugin", (a, b) -> 0); // CraftBukkit ++ public static final TicketType PLUGIN_TICKET = create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit + +- public static TicketType create(String s, Comparator comparator) { +- return new TicketType<>(s, comparator, 0L); ++ public static TicketType create(String name, Comparator comparator) { ++ return new TicketType<>(name, comparator, 0L); + } + +- public static TicketType create(String s, Comparator comparator, int i) { +- return new TicketType<>(s, comparator, (long) i); ++ public static TicketType create(String name, Comparator comparator, int lifespan) { ++ return new TicketType<>(name, comparator, (long) lifespan); + } + +- protected TicketType(String s, Comparator comparator, long i) { +- this.name = s; ++ protected TicketType(String name, Comparator comparator, long timeout) { ++ this.name = name; + this.comparator = comparator; +- this.timeout = i; ++ this.timeout = timeout; + } + +- @Override + public String toString() { + return this.name; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/level/WorldGenRegion.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/level/WorldGenRegion.java.patch new file mode 100644 index 0000000000..b9d59ab7b8 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/level/WorldGenRegion.java.patch @@ -0,0 +1,592 @@ +--- a/net/minecraft/server/level/WorldGenRegion.java ++++ b/net/minecraft/server/level/WorldGenRegion.java +@@ -37,7 +37,7 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.EntityBlock; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.border.WorldBorder; + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkSource; +@@ -67,11 +67,11 @@ + private final LevelData levelData; + private final RandomSource random; + private final DimensionType dimensionType; +- private final WorldGenTickAccess blockTicks = new WorldGenTickAccess<>((blockpos) -> { +- return this.getChunk(blockpos).getBlockTicks(); ++ private final WorldGenTickAccess blockTicks = new WorldGenTickAccess<>((blockposition) -> { ++ return this.getChunk(blockposition).getBlockTicks(); + }); +- private final WorldGenTickAccess fluidTicks = new WorldGenTickAccess<>((blockpos) -> { +- return this.getChunk(blockpos).getFluidTicks(); ++ private final WorldGenTickAccess fluidTicks = new WorldGenTickAccess<>((blockposition) -> { ++ return this.getChunk(blockposition).getFluidTicks(); + }); + private final BiomeManager biomeManager; + private final ChunkPos firstPos; +@@ -84,31 +84,31 @@ + private final AtomicLong subTickCount = new AtomicLong(); + private static final ResourceLocation WORLDGEN_REGION_RANDOM = new ResourceLocation("worldgen_region_random"); + +- public WorldGenRegion(ServerLevel serverlevel, List list, ChunkStatus chunkstatus, int i) { +- this.generatingStatus = chunkstatus; +- this.writeRadiusCutoff = i; +- int j = Mth.floor(Math.sqrt((double) list.size())); ++ public WorldGenRegion(ServerLevel level, List cache, ChunkStatus generatingStatus, int writeRadiusCutoff) { ++ this.generatingStatus = generatingStatus; ++ this.writeRadiusCutoff = writeRadiusCutoff; ++ int j = Mth.floor(Math.sqrt((double) cache.size())); + +- if (j * j != list.size()) { ++ if (j * j != cache.size()) { + throw (IllegalStateException) Util.pauseInIde(new IllegalStateException("Cache size is not a square.")); + } else { +- this.cache = list; +- this.center = (ChunkAccess) list.get(list.size() / 2); ++ this.cache = cache; ++ this.center = (ChunkAccess) cache.get(cache.size() / 2); + this.size = j; +- this.level = serverlevel; +- this.seed = serverlevel.getSeed(); +- this.levelData = serverlevel.getLevelData(); +- this.random = serverlevel.getChunkSource().randomState().getOrCreateRandomFactory(WorldGenRegion.WORLDGEN_REGION_RANDOM).at(this.center.getPos().getWorldPosition()); +- this.dimensionType = serverlevel.dimensionType(); ++ this.level = level; ++ this.seed = level.getSeed(); ++ this.levelData = level.getLevelData(); ++ this.random = level.getChunkSource().randomState().getOrCreateRandomFactory(WorldGenRegion.WORLDGEN_REGION_RANDOM).at(this.center.getPos().getWorldPosition()); ++ this.dimensionType = level.dimensionType(); + this.biomeManager = new BiomeManager(this, BiomeManager.obfuscateSeed(this.seed)); +- this.firstPos = ((ChunkAccess) list.get(0)).getPos(); +- this.lastPos = ((ChunkAccess) list.get(list.size() - 1)).getPos(); +- this.structureManager = serverlevel.structureManager().forWorldGenRegion(this); ++ this.firstPos = ((ChunkAccess) cache.get(0)).getPos(); ++ this.lastPos = ((ChunkAccess) cache.get(cache.size() - 1)).getPos(); ++ this.structureManager = level.structureManager().forWorldGenRegion(this); + } + } + +- public boolean isOldChunkAround(ChunkPos chunkpos, int i) { +- return this.level.getChunkSource().chunkMap.isOldChunkAround(chunkpos, i); ++ public boolean isOldChunkAround(ChunkPos pos, int radius) { ++ return this.level.getChunkSource().chunkMap.isOldChunkAround(pos, radius); + } + + public ChunkPos getCenter() { +@@ -116,153 +116,139 @@ + } + + @Override +- @Override +- public void setCurrentlyGenerating(@Nullable Supplier supplier) { +- this.currentlyGenerating = supplier; ++ public void setCurrentlyGenerating(@Nullable Supplier currentlyGenerating) { ++ this.currentlyGenerating = currentlyGenerating; + } + + @Override +- @Override +- public ChunkAccess getChunk(int i, int j) { +- return this.getChunk(i, j, ChunkStatus.EMPTY); ++ public ChunkAccess getChunk(int chunkX, int chunkZ) { ++ return this.getChunk(chunkX, chunkZ, ChunkStatus.EMPTY); + } + + @Nullable + @Override +- @Override +- public ChunkAccess getChunk(int i, int j, ChunkStatus chunkstatus, boolean flag) { +- ChunkAccess chunkaccess; ++ public ChunkAccess getChunk(int x, int z, ChunkStatus requiredStatus, boolean nonnull) { ++ ChunkAccess ichunkaccess; + +- if (this.hasChunk(i, j)) { +- int k = i - this.firstPos.x; +- int l = j - this.firstPos.z; ++ if (this.hasChunk(x, z)) { ++ int k = x - this.firstPos.x; ++ int l = z - this.firstPos.z; + +- chunkaccess = (ChunkAccess) this.cache.get(k + l * this.size); +- if (chunkaccess.getStatus().isOrAfter(chunkstatus)) { +- return chunkaccess; ++ ichunkaccess = (ChunkAccess) this.cache.get(k + l * this.size); ++ if (ichunkaccess.getStatus().isOrAfter(requiredStatus)) { ++ return ichunkaccess; + } + } else { +- chunkaccess = null; ++ ichunkaccess = null; + } + +- if (!flag) { ++ if (!nonnull) { + return null; + } else { +- WorldGenRegion.LOGGER.error("Requested chunk : {} {}", i, j); ++ WorldGenRegion.LOGGER.error("Requested chunk : {} {}", x, z); + WorldGenRegion.LOGGER.error("Region bounds : {} {} | {} {}", new Object[]{this.firstPos.x, this.firstPos.z, this.lastPos.x, this.lastPos.z}); +- if (chunkaccess != null) { +- throw (RuntimeException) Util.pauseInIde(new RuntimeException(String.format(Locale.ROOT, "Chunk is not of correct status. Expecting %s, got %s | %s %s", chunkstatus, chunkaccess.getStatus(), i, j))); ++ if (ichunkaccess != null) { ++ throw (RuntimeException) Util.pauseInIde(new RuntimeException(String.format(Locale.ROOT, "Chunk is not of correct status. Expecting %s, got %s | %s %s", requiredStatus, ichunkaccess.getStatus(), x, z))); + } else { +- throw (RuntimeException) Util.pauseInIde(new RuntimeException(String.format(Locale.ROOT, "We are asking a region for a chunk out of bound | %s %s", i, j))); ++ throw (RuntimeException) Util.pauseInIde(new RuntimeException(String.format(Locale.ROOT, "We are asking a region for a chunk out of bound | %s %s", x, z))); + } + } + } + + @Override +- @Override +- public boolean hasChunk(int i, int j) { +- return i >= this.firstPos.x && i <= this.lastPos.x && j >= this.firstPos.z && j <= this.lastPos.z; ++ public boolean hasChunk(int chunkX, int chunkZ) { ++ return chunkX >= this.firstPos.x && chunkX <= this.lastPos.x && chunkZ >= this.firstPos.z && chunkZ <= this.lastPos.z; + } + + @Override +- @Override +- public BlockState getBlockState(BlockPos blockpos) { +- return this.getChunk(SectionPos.blockToSectionCoord(blockpos.getX()), SectionPos.blockToSectionCoord(blockpos.getZ())).getBlockState(blockpos); ++ public IBlockData getBlockState(BlockPos pos) { ++ return this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())).getBlockState(pos); + } + + @Override +- @Override +- public FluidState getFluidState(BlockPos blockpos) { +- return this.getChunk(blockpos).getFluidState(blockpos); ++ public FluidState getFluidState(BlockPos pos) { ++ return this.getChunk(pos).getFluidState(pos); + } + + @Nullable + @Override +- @Override +- public Player getNearestPlayer(double d0, double d1, double d2, double d3, Predicate predicate) { ++ public Player getNearestPlayer(double x, double d1, double y, double d3, Predicate z) { + return null; + } + + @Override +- @Override + public int getSkyDarken() { + return 0; + } + + @Override +- @Override + public BiomeManager getBiomeManager() { + return this.biomeManager; + } + + @Override +- @Override +- public Holder getUncachedNoiseBiome(int i, int j, int k) { +- return this.level.getUncachedNoiseBiome(i, j, k); ++ public Holder getUncachedNoiseBiome(int x, int y, int z) { ++ return this.level.getUncachedNoiseBiome(x, y, z); + } + + @Override +- @Override +- public float getShade(Direction direction, boolean flag) { ++ public float getShade(Direction direction, boolean shade) { + return 1.0F; + } + + @Override +- @Override + public LevelLightEngine getLightEngine() { + return this.level.getLightEngine(); + } + + @Override +- @Override +- public boolean destroyBlock(BlockPos blockpos, boolean flag, @Nullable Entity entity, int i) { +- BlockState blockstate = this.getBlockState(blockpos); ++ public boolean destroyBlock(BlockPos pos, boolean dropBlock, @Nullable Entity entity, int recursionLeft) { ++ IBlockData iblockdata = this.getBlockState(pos); + +- if (blockstate.isAir()) { ++ if (iblockdata.isAir()) { + return false; + } else { +- if (flag) { +- BlockEntity blockentity = blockstate.hasBlockEntity() ? this.getBlockEntity(blockpos) : null; ++ if (false) { // CraftBukkit - SPIGOT-6833: Do not drop during world generation ++ BlockEntity tileentity = iblockdata.hasBlockEntity() ? this.getBlockEntity(pos) : null; + +- Block.dropResources(blockstate, this.level, blockpos, blockentity, entity, ItemStack.EMPTY); ++ Block.dropResources(iblockdata, this.level, pos, tileentity, entity, ItemStack.EMPTY); + } + +- return this.setBlock(blockpos, Blocks.AIR.defaultBlockState(), 3, i); ++ return this.setBlock(pos, Blocks.AIR.defaultBlockState(), 3, recursionLeft); + } + } + + @Nullable + @Override +- @Override +- public BlockEntity getBlockEntity(BlockPos blockpos) { +- ChunkAccess chunkaccess = this.getChunk(blockpos); +- BlockEntity blockentity = chunkaccess.getBlockEntity(blockpos); ++ public BlockEntity getBlockEntity(BlockPos pos) { ++ ChunkAccess ichunkaccess = this.getChunk(pos); ++ BlockEntity tileentity = ichunkaccess.getBlockEntity(pos); + +- if (blockentity != null) { +- return blockentity; ++ if (tileentity != null) { ++ return tileentity; + } else { +- CompoundTag compoundtag = chunkaccess.getBlockEntityNbt(blockpos); +- BlockState blockstate = chunkaccess.getBlockState(blockpos); ++ CompoundTag nbttagcompound = ichunkaccess.getBlockEntityNbt(pos); ++ IBlockData iblockdata = ichunkaccess.getBlockState(pos); + +- if (compoundtag != null) { +- if ("DUMMY".equals(compoundtag.getString("id"))) { +- if (!blockstate.hasBlockEntity()) { ++ if (nbttagcompound != null) { ++ if ("DUMMY".equals(nbttagcompound.getString("id"))) { ++ if (!iblockdata.hasBlockEntity()) { + return null; + } + +- blockentity = ((EntityBlock) blockstate.getBlock()).newBlockEntity(blockpos, blockstate); ++ tileentity = ((EntityBlock) iblockdata.getBlock()).newBlockEntity(pos, iblockdata); + } else { +- blockentity = BlockEntity.loadStatic(blockpos, blockstate, compoundtag); ++ tileentity = BlockEntity.loadStatic(pos, iblockdata, nbttagcompound); + } + +- if (blockentity != null) { +- chunkaccess.setBlockEntity(blockentity); +- return blockentity; ++ if (tileentity != null) { ++ ichunkaccess.setBlockEntity(tileentity); ++ return tileentity; + } + } + +- if (blockstate.hasBlockEntity()) { +- WorldGenRegion.LOGGER.warn("Tried to access a block entity before it was created. {}", blockpos); ++ if (iblockdata.hasBlockEntity()) { ++ WorldGenRegion.LOGGER.warn("Tried to access a block entity before it was created. {}", pos); + } + + return null; +@@ -270,80 +256,84 @@ + } + + @Override +- @Override +- public boolean ensureCanWrite(BlockPos blockpos) { +- int i = SectionPos.blockToSectionCoord(blockpos.getX()); +- int j = SectionPos.blockToSectionCoord(blockpos.getZ()); +- ChunkPos chunkpos = this.getCenter(); +- int k = Math.abs(chunkpos.x - i); +- int l = Math.abs(chunkpos.z - j); ++ public boolean ensureCanWrite(BlockPos pos) { ++ int i = SectionPos.blockToSectionCoord(pos.getX()); ++ int j = SectionPos.blockToSectionCoord(pos.getZ()); ++ ChunkPos chunkcoordintpair = this.getCenter(); ++ int k = Math.abs(chunkcoordintpair.x - i); ++ int l = Math.abs(chunkcoordintpair.z - j); + + if (k <= this.writeRadiusCutoff && l <= this.writeRadiusCutoff) { + if (this.center.isUpgrading()) { + LevelHeightAccessor levelheightaccessor = this.center.getHeightAccessorForGeneration(); + +- if (blockpos.getY() < levelheightaccessor.getMinBuildHeight() || blockpos.getY() >= levelheightaccessor.getMaxBuildHeight()) { ++ if (pos.getY() < levelheightaccessor.getMinBuildHeight() || pos.getY() >= levelheightaccessor.getMaxBuildHeight()) { + return false; + } + } + + return true; + } else { +- Util.logAndPauseIfInIde("Detected setBlock in a far chunk [" + i + ", " + j + "], pos: " + blockpos + ", status: " + this.generatingStatus + (this.currentlyGenerating == null ? "" : ", currently generating: " + (String) this.currentlyGenerating.get())); ++ Util.logAndPauseIfInIde("Detected setBlock in a far chunk [" + i + ", " + j + "], pos: " + pos + ", status: " + this.generatingStatus + (this.currentlyGenerating == null ? "" : ", currently generating: " + (String) this.currentlyGenerating.get())); + return false; + } + } + + @Override +- @Override +- public boolean setBlock(BlockPos blockpos, BlockState blockstate, int i, int j) { +- if (!this.ensureCanWrite(blockpos)) { ++ public boolean setBlock(BlockPos pos, IBlockData state, int flags, int recursionLeft) { ++ if (!this.ensureCanWrite(pos)) { + return false; + } else { +- ChunkAccess chunkaccess = this.getChunk(blockpos); +- BlockState blockstate1 = chunkaccess.setBlockState(blockpos, blockstate, false); ++ ChunkAccess ichunkaccess = this.getChunk(pos); ++ IBlockData iblockdata1 = ichunkaccess.setBlockState(pos, state, false); + +- if (blockstate1 != null) { +- this.level.onBlockStateChange(blockpos, blockstate1, blockstate); ++ if (iblockdata1 != null) { ++ this.level.onBlockStateChange(pos, iblockdata1, state); + } + +- if (blockstate.hasBlockEntity()) { +- if (chunkaccess.getStatus().getChunkType() == ChunkStatus.ChunkType.LEVELCHUNK) { +- BlockEntity blockentity = ((EntityBlock) blockstate.getBlock()).newBlockEntity(blockpos, blockstate); ++ if (state.hasBlockEntity()) { ++ if (ichunkaccess.getStatus().getChunkType() == ChunkStatus.Type.LEVELCHUNK) { ++ BlockEntity tileentity = ((EntityBlock) state.getBlock()).newBlockEntity(pos, state); + +- if (blockentity != null) { +- chunkaccess.setBlockEntity(blockentity); ++ if (tileentity != null) { ++ ichunkaccess.setBlockEntity(tileentity); + } else { +- chunkaccess.removeBlockEntity(blockpos); ++ ichunkaccess.removeBlockEntity(pos); + } + } else { +- CompoundTag compoundtag = new CompoundTag(); ++ CompoundTag nbttagcompound = new CompoundTag(); + +- compoundtag.putInt("x", blockpos.getX()); +- compoundtag.putInt("y", blockpos.getY()); +- compoundtag.putInt("z", blockpos.getZ()); +- compoundtag.putString("id", "DUMMY"); +- chunkaccess.setBlockEntityNbt(compoundtag); ++ nbttagcompound.putInt("x", pos.getX()); ++ nbttagcompound.putInt("y", pos.getY()); ++ nbttagcompound.putInt("z", pos.getZ()); ++ nbttagcompound.putString("id", "DUMMY"); ++ ichunkaccess.setBlockEntityNbt(nbttagcompound); + } +- } else if (blockstate1 != null && blockstate1.hasBlockEntity()) { +- chunkaccess.removeBlockEntity(blockpos); ++ } else if (iblockdata1 != null && iblockdata1.hasBlockEntity()) { ++ ichunkaccess.removeBlockEntity(pos); + } + +- if (blockstate.hasPostProcess(this, blockpos)) { +- this.markPosForPostprocessing(blockpos); ++ if (state.hasPostProcess(this, pos)) { ++ this.markPosForPostprocessing(pos); + } + + return true; + } + } + +- private void markPosForPostprocessing(BlockPos blockpos) { +- this.getChunk(blockpos).markPosForPostprocessing(blockpos); ++ private void markPosForPostprocessing(BlockPos pos) { ++ this.getChunk(pos).markPosForPostprocessing(pos); + } + + @Override +- @Override + public boolean addFreshEntity(Entity entity) { ++ // CraftBukkit start ++ return addFreshEntity(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ @Override ++ public boolean addFreshEntity(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ // CraftBukkit end + int i = SectionPos.blockToSectionCoord(entity.getBlockX()); + int j = SectionPos.blockToSectionCoord(entity.getBlockZ()); + +@@ -352,19 +342,16 @@ + } + + @Override +- @Override +- public boolean removeBlock(BlockPos blockpos, boolean flag) { +- return this.setBlock(blockpos, Blocks.AIR.defaultBlockState(), 3); ++ public boolean removeBlock(BlockPos pos, boolean isMoving) { ++ return this.setBlock(pos, Blocks.AIR.defaultBlockState(), 3); + } + + @Override +- @Override + public WorldBorder getWorldBorder() { + return this.level.getWorldBorder(); + } + + @Override +- @Override + public boolean isClientSide() { + return false; + } +@@ -372,33 +359,28 @@ + /** @deprecated */ + @Deprecated + @Override +- @Override + public ServerLevel getLevel() { + return this.level; + } + + @Override +- @Override + public RegistryAccess registryAccess() { + return this.level.registryAccess(); + } + + @Override +- @Override + public FeatureFlagSet enabledFeatures() { + return this.level.enabledFeatures(); + } + + @Override +- @Override + public LevelData getLevelData() { + return this.levelData; + } + + @Override +- @Override +- public DifficultyInstance getCurrentDifficultyAt(BlockPos blockpos) { +- if (!this.hasChunk(SectionPos.blockToSectionCoord(blockpos.getX()), SectionPos.blockToSectionCoord(blockpos.getZ()))) { ++ public DifficultyInstance getCurrentDifficultyAt(BlockPos pos) { ++ if (!this.hasChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()))) { + throw new RuntimeException("We are asking a region for a chunk out of bound"); + } else { + return new DifficultyInstance(this.level.getDifficulty(), this.level.getDayTime(), 0L, this.level.getMoonBrightness()); +@@ -407,119 +389,98 @@ + + @Nullable + @Override +- @Override + public MinecraftServer getServer() { + return this.level.getServer(); + } + + @Override +- @Override + public ChunkSource getChunkSource() { + return this.level.getChunkSource(); + } + + @Override +- @Override + public long getSeed() { + return this.seed; + } + + @Override +- @Override + public LevelTickAccess getBlockTicks() { + return this.blockTicks; + } + + @Override +- @Override + public LevelTickAccess getFluidTicks() { + return this.fluidTicks; + } + + @Override +- @Override + public int getSeaLevel() { + return this.level.getSeaLevel(); + } + + @Override +- @Override + public RandomSource getRandom() { + return this.random; + } + + @Override +- @Override +- public int getHeight(Heightmap.Types heightmap_types, int i, int j) { +- return this.getChunk(SectionPos.blockToSectionCoord(i), SectionPos.blockToSectionCoord(j)).getHeight(heightmap_types, i & 15, j & 15) + 1; ++ public int getHeight(Heightmap.Types heightmapType, int x, int z) { ++ return this.getChunk(SectionPos.blockToSectionCoord(x), SectionPos.blockToSectionCoord(z)).getHeight(heightmapType, x & 15, z & 15) + 1; + } + + @Override +- @Override +- public void playSound(@Nullable Player player, BlockPos blockpos, SoundEvent soundevent, SoundSource soundsource, float f, float f1) {} ++ public void playSound(@Nullable Player player, BlockPos pos, SoundEvent sound, SoundSource category, float volume, float pitch) {} + + @Override +- @Override +- public void addParticle(ParticleOptions particleoptions, double d0, double d1, double d2, double d3, double d4, double d5) {} ++ public void addParticle(ParticleOptions particleData, double x, double d1, double y, double d3, double z, double d5) {} + + @Override +- @Override +- public void levelEvent(@Nullable Player player, int i, BlockPos blockpos, int j) {} ++ public void levelEvent(@Nullable Player player, int type, BlockPos pos, int data) {} + + @Override +- @Override +- public void gameEvent(GameEvent gameevent, Vec3 vec3, GameEvent.Context gameevent_context) {} ++ public void gameEvent(GameEvent event, Vec3 position, GameEvent.Context context) {} + + @Override +- @Override + public DimensionType dimensionType() { + return this.dimensionType; + } + + @Override +- @Override +- public boolean isStateAtPosition(BlockPos blockpos, Predicate predicate) { +- return predicate.test(this.getBlockState(blockpos)); ++ public boolean isStateAtPosition(BlockPos pos, Predicate state) { ++ return state.test(this.getBlockState(pos)); + } + + @Override +- @Override +- public boolean isFluidAtPosition(BlockPos blockpos, Predicate predicate) { +- return predicate.test(this.getFluidState(blockpos)); ++ public boolean isFluidAtPosition(BlockPos pos, Predicate predicate) { ++ return predicate.test(this.getFluidState(pos)); + } + + @Override +- @Override +- public List getEntities(EntityTypeTest entitytypetest, AABB aabb, Predicate predicate) { ++ public List getEntities(EntityTypeTest entityTypeTest, AABB bounds, Predicate predicate) { + return Collections.emptyList(); + } + + @Override +- @Override +- public List getEntities(@Nullable Entity entity, AABB aabb, @Nullable Predicate predicate) { ++ public List getEntities(@Nullable Entity entity, AABB boundingBox, @Nullable Predicate predicate) { + return Collections.emptyList(); + } + + @Override +- @Override + public List players() { + return Collections.emptyList(); + } + + @Override +- @Override + public int getMinBuildHeight() { + return this.level.getMinBuildHeight(); + } + + @Override +- @Override + public int getHeight() { + return this.level.getHeight(); + } + + @Override +- @Override + public long nextSubTickCount() { + return this.subTickCount.getAndIncrement(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/network/LegacyQueryHandler.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/network/LegacyQueryHandler.java.patch new file mode 100644 index 0000000000..a64a289029 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/network/LegacyQueryHandler.java.patch @@ -0,0 +1,59 @@ +--- a/net/minecraft/server/network/LegacyQueryHandler.java ++++ b/net/minecraft/server/network/LegacyQueryHandler.java +@@ -20,7 +20,6 @@ + this.server = serverinfo; + } + +- @Override + public void channelRead(ChannelHandlerContext channelhandlercontext, Object object) { + ByteBuf bytebuf = (ByteBuf) object; + +@@ -36,10 +35,11 @@ + SocketAddress socketaddress = channelhandlercontext.channel().remoteAddress(); + int i = bytebuf.readableBytes(); + String s; ++ org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(socketaddress, server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); // CraftBukkit + + if (i == 0) { + LegacyQueryHandler.LOGGER.debug("Ping: (<1.3.x) from {}", socketaddress); +- s = createVersion0Response(this.server); ++ s = createVersion0Response(this.server, event); // CraftBukkit + sendFlushAndClose(channelhandlercontext, createLegacyDisconnectPacket(channelhandlercontext.alloc(), s)); + } else { + if (bytebuf.readUnsignedByte() != 1) { +@@ -56,7 +56,7 @@ + LegacyQueryHandler.LOGGER.debug("Ping: (1.4-1.5.x) from {}", socketaddress); + } + +- s = createVersion1Response(this.server); ++ s = createVersion1Response(this.server, event); // CraftBukkit + sendFlushAndClose(channelhandlercontext, createLegacyDisconnectPacket(channelhandlercontext.alloc(), s)); + } + +@@ -107,16 +107,20 @@ + } + } + +- private static String createVersion0Response(ServerInfo serverinfo) { +- return String.format(Locale.ROOT, "%s\u00a7%d\u00a7%d", serverinfo.getMotd(), serverinfo.getPlayerCount(), serverinfo.getMaxPlayers()); ++ // CraftBukkit start ++ private static String createVersion0Response(ServerInfo serverinfo, org.bukkit.event.server.ServerListPingEvent event) { ++ return String.format(Locale.ROOT, "%s\u00a7%d\u00a7%d", event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); ++ // CraftBukkit end + } + +- private static String createVersion1Response(ServerInfo serverinfo) { +- return String.format(Locale.ROOT, "\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, serverinfo.getServerVersion(), serverinfo.getMotd(), serverinfo.getPlayerCount(), serverinfo.getMaxPlayers()); ++ // CraftBukkit start ++ private static String createVersion1Response(ServerInfo serverinfo, org.bukkit.event.server.ServerListPingEvent event) { ++ return String.format(Locale.ROOT, "\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, serverinfo.getServerVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); ++ // CraftBukkit end + } + +- private static void sendFlushAndClose(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf) { +- channelhandlercontext.pipeline().firstContext().writeAndFlush(bytebuf).addListener(ChannelFutureListener.CLOSE); ++ private static void sendFlushAndClose(ChannelHandlerContext channelhandlercontext, ByteBuf context) { ++ channelhandlercontext.pipeline().firstContext().writeAndFlush(context).addListener(ChannelFutureListener.CLOSE); + } + + private static ByteBuf createLegacyDisconnectPacket(ByteBufAllocator bytebufallocator, String s) { diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerCommonPacketListenerImpl.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerCommonPacketListenerImpl.java.patch new file mode 100644 index 0000000000..f05e92b025 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerCommonPacketListenerImpl.java.patch @@ -0,0 +1,258 @@ +--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java +@@ -4,6 +4,7 @@ + import com.mojang.logging.LogUtils; + import java.util.Objects; + import javax.annotation.Nullable; ++import net.minecraft.ChatFormatting; + import net.minecraft.CrashReport; + import net.minecraft.CrashReportCategory; + import net.minecraft.ReportedException; +@@ -20,12 +21,26 @@ + import net.minecraft.network.protocol.common.ServerboundKeepAlivePacket; + import net.minecraft.network.protocol.common.ServerboundPongPacket; + import net.minecraft.network.protocol.common.ServerboundResourcePackPacket; ++import net.minecraft.network.protocol.game.ClientboundSetDefaultSpawnPositionPacket; ++import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ClientInformation; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.VisibleForDebug; + import net.minecraft.util.thread.BlockableEventLoop; + import org.slf4j.Logger; + ++// CraftBukkit start ++import io.netty.buffer.ByteBuf; ++import java.util.concurrent.ExecutionException; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.bukkit.event.player.PlayerKickEvent; ++import org.bukkit.event.player.PlayerResourcePackStatusEvent; ++// CraftBukkit end ++ + public abstract class ServerCommonPacketListenerImpl implements ServerCommonPacketListener { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -39,16 +54,26 @@ + private int latency; + private volatile boolean suspendFlushingOnServerThread = false; + +- public ServerCommonPacketListenerImpl(MinecraftServer minecraftserver, Connection connection, CommonListenerCookie commonlistenercookie) { ++ public ServerCommonPacketListenerImpl(MinecraftServer minecraftserver, Connection networkmanager, CommonListenerCookie commonlistenercookie, ServerPlayer player) { // CraftBukkit + this.server = minecraftserver; +- this.connection = connection; ++ this.connection = networkmanager; + this.keepAliveTime = Util.getMillis(); + this.latency = commonlistenercookie.latency(); ++ // CraftBukkit start - add fields and methods ++ this.player = player; ++ this.cserver = minecraftserver.server; + } ++ protected final ServerPlayer player; ++ protected final org.bukkit.craftbukkit.CraftServer cserver; ++ public boolean processedDisconnect; + ++ public CraftPlayer getCraftPlayer() { ++ return (this.player == null) ? null : (CraftPlayer) this.player.getBukkitEntity(); ++ // CraftBukkit end ++ } ++ + @Override +- @Override +- public void onDisconnect(Component component) { ++ public void onDisconnect(Component reason) { + if (this.isSingleplayerOwner()) { + ServerCommonPacketListenerImpl.LOGGER.info("Stopping singleplayer server as player logged out"); + this.server.halt(false); +@@ -57,8 +82,8 @@ + } + + @Override +- @Override + public void handleKeepAlive(ServerboundKeepAlivePacket serverboundkeepalivepacket) { ++ PacketUtils.ensureRunningOnSameThread(serverboundkeepalivepacket, this, this.player.serverLevel()); // CraftBukkit + if (this.keepAlivePending && serverboundkeepalivepacket.getId() == this.keepAliveChallenge) { + int i = (int) (Util.getMillis() - this.keepAliveTime); + +@@ -71,21 +96,67 @@ + } + + @Override +- @Override + public void handlePong(ServerboundPongPacket serverboundpongpacket) {} + ++ // CraftBukkit start ++ private static final ResourceLocation CUSTOM_REGISTER = new ResourceLocation("register"); ++ private static final ResourceLocation CUSTOM_UNREGISTER = new ResourceLocation("unregister"); ++ + @Override +- @Override +- public void handleCustomPayload(ServerboundCustomPayloadPacket serverboundcustompayloadpacket) {} ++ public void handleCustomPayload(ServerboundCustomPayloadPacket serverboundcustompayloadpacket) { ++ if (!(serverboundcustompayloadpacket.payload() instanceof ServerboundCustomPayloadPacket.UnknownPayload)) { ++ return; ++ } ++ PacketUtils.ensureRunningOnSameThread(serverboundcustompayloadpacket, this, this.player.serverLevel()); ++ ResourceLocation identifier = serverboundcustompayloadpacket.payload().id(); ++ ByteBuf payload = ((ServerboundCustomPayloadPacket.UnknownPayload)serverboundcustompayloadpacket.payload()).data(); + ++ if (identifier.equals(CUSTOM_REGISTER)) { ++ try { ++ String channels = payload.toString(com.google.common.base.Charsets.UTF_8); ++ for (String channel : channels.split("\0")) { ++ getCraftPlayer().addChannel(channel); ++ } ++ } catch (Exception ex) { ++ ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t register custom payload", ex); ++ this.disconnect("Invalid payload REGISTER!"); ++ } ++ } else if (identifier.equals(CUSTOM_UNREGISTER)) { ++ try { ++ String channels = payload.toString(com.google.common.base.Charsets.UTF_8); ++ for (String channel : channels.split("\0")) { ++ getCraftPlayer().removeChannel(channel); ++ } ++ } catch (Exception ex) { ++ ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t unregister custom payload", ex); ++ this.disconnect("Invalid payload UNREGISTER!"); ++ } ++ } else { ++ try { ++ byte[] data = new byte[payload.readableBytes()]; ++ payload.readBytes(data); ++ cserver.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), identifier.toString(), data); ++ } catch (Exception ex) { ++ ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t dispatch custom payload", ex); ++ this.disconnect("Invalid custom payload!"); ++ } ++ } ++ ++ } ++ ++ public final boolean isDisconnected() { ++ return !this.player.joining && !this.connection.isConnected(); ++ } ++ // CraftBukkit end ++ + @Override +- @Override + public void handleResourcePackResponse(ServerboundResourcePackPacket serverboundresourcepackpacket) { + PacketUtils.ensureRunningOnSameThread(serverboundresourcepackpacket, this, (BlockableEventLoop) this.server); +- if (serverboundresourcepackpacket.action() == ServerboundResourcePackPacket.Action.DECLINED && this.server.isResourcePackRequired()) { ++ if (serverboundresourcepackpacket.action() == ServerboundResourcePackPacket.a.DECLINED && this.server.isResourcePackRequired()) { + ServerCommonPacketListenerImpl.LOGGER.info("Disconnecting {} due to resource pack {} rejection", this.playerProfile().getName(), serverboundresourcepackpacket.id()); + this.disconnect(Component.translatable("multiplayer.requiredTexturePrompt.disconnect")); + } ++ this.cserver.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getCraftPlayer(), serverboundresourcepackpacket.id(), PlayerResourcePackStatusEvent.Status.values()[serverboundresourcepackpacket.action().ordinal()])); // CraftBukkit + + } + +@@ -93,7 +164,7 @@ + this.server.getProfiler().push("keepAlive"); + long i = Util.getMillis(); + +- if (i - this.keepAliveTime >= 15000L) { ++ if (i - this.keepAliveTime >= 25000L) { // CraftBukkit + if (this.keepAlivePending) { + this.disconnect(ServerCommonPacketListenerImpl.TIMEOUT_DISCONNECTION_MESSAGE); + } else { +@@ -121,31 +192,90 @@ + } + + public void send(Packet packet, @Nullable PacketSendListener packetsendlistener) { ++ // CraftBukkit start ++ if (packet == null) { ++ return; ++ } else if (packet instanceof ClientboundSetDefaultSpawnPositionPacket) { ++ ClientboundSetDefaultSpawnPositionPacket packet6 = (ClientboundSetDefaultSpawnPositionPacket) packet; ++ this.player.compassTarget = CraftLocation.toBukkit(packet6.pos, this.getCraftPlayer().getWorld()); ++ } ++ // CraftBukkit end + boolean flag = !this.suspendFlushingOnServerThread || !this.server.isSameThread(); + + try { + this.connection.send(packet, packetsendlistener, flag); + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Sending packet"); +- CrashReportCategory crashreportcategory = crashreport.addCategory("Packet being sent"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Packet being sent"); + +- crashreportcategory.setDetail("Packet class", () -> { ++ crashreportsystemdetails.setDetail("Packet class", () -> { + return packet.getClass().getCanonicalName(); + }); + throw new ReportedException(crashreport); + } + } + +- public void disconnect(Component component) { +- this.connection.send(new ClientboundDisconnectPacket(component), PacketSendListener.thenRun(() -> { +- this.connection.disconnect(component); ++ // CraftBukkit start ++ @Deprecated ++ public void disconnect(Component ichatbasecomponent) { ++ disconnect(CraftChatMessage.fromComponent(ichatbasecomponent)); ++ } ++ // CraftBukkit end ++ ++ public void disconnect(String s) { ++ // CraftBukkit start - fire PlayerKickEvent ++ if (this.processedDisconnect) { ++ return; ++ } ++ if (!this.cserver.isPrimaryThread()) { ++ Waitable waitable = new Waitable() { ++ @Override ++ protected Object evaluate() { ++ ServerCommonPacketListenerImpl.this.disconnect(s); ++ return null; ++ } ++ }; ++ ++ this.server.processQueue.add(waitable); ++ ++ try { ++ waitable.get(); ++ } catch (InterruptedException e) { ++ Thread.currentThread().interrupt(); ++ } catch (ExecutionException e) { ++ throw new RuntimeException(e); ++ } ++ return; ++ } ++ ++ String leaveMessage = ChatFormatting.YELLOW + this.player.getScoreboardName() + " left the game."; ++ ++ PlayerKickEvent event = new PlayerKickEvent(this.player.getBukkitEntity(), s, leaveMessage); ++ ++ if (this.cserver.getServer().isRunning()) { ++ this.cserver.getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ // Do not kick the player ++ return; ++ } ++ this.player.kickLeaveMessage = event.getLeaveMessage(); // CraftBukkit - SPIGOT-3034: Forward leave message to PlayerQuitEvent ++ // Send the possibly modified leave message ++ final Component ichatbasecomponent = CraftChatMessage.fromString(event.getReason(), true)[0]; ++ // CraftBukkit end ++ ++ this.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), PacketSendListener.thenRun(() -> { ++ this.connection.disconnect(ichatbasecomponent); + })); ++ this.onDisconnect(ichatbasecomponent); // CraftBukkit - fire quit instantly + this.connection.setReadOnly(); + MinecraftServer minecraftserver = this.server; +- Connection connection = this.connection; ++ Connection networkmanager = this.connection; + + Objects.requireNonNull(this.connection); +- minecraftserver.executeBlocking(connection::handleDisconnection); ++ // CraftBukkit - Don't wait ++ minecraftserver.wrapRunnable(networkmanager::handleDisconnection); + } + + protected boolean isSingleplayerOwner() { diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java.patch new file mode 100644 index 0000000000..0134548fc6 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java.patch @@ -0,0 +1,103 @@ +--- a/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java +@@ -44,27 +44,24 @@ + private ConfigurationTask currentTask; + private ClientInformation clientInformation; + +- public ServerConfigurationPacketListenerImpl(MinecraftServer minecraftserver, Connection connection, CommonListenerCookie commonlistenercookie) { +- super(minecraftserver, connection, commonlistenercookie); ++ public ServerConfigurationPacketListenerImpl(MinecraftServer minecraftserver, Connection networkmanager, CommonListenerCookie commonlistenercookie, ServerPlayer player) { // CraftBukkit ++ super(minecraftserver, networkmanager, commonlistenercookie, player); // CraftBukkit + this.gameProfile = commonlistenercookie.gameProfile(); + this.clientInformation = commonlistenercookie.clientInformation(); + } + + @Override +- @Override + protected GameProfile playerProfile() { + return this.gameProfile; + } + + @Override +- @Override +- public void onDisconnect(Component component) { +- ServerConfigurationPacketListenerImpl.LOGGER.info("{} lost connection: {}", this.gameProfile, component.getString()); +- super.onDisconnect(component); ++ public void onDisconnect(Component reason) { ++ ServerConfigurationPacketListenerImpl.LOGGER.info("{} lost connection: {}", this.gameProfile, reason.getString()); ++ super.onDisconnect(reason); + } + + @Override +- @Override + public boolean isAcceptingMessages() { + return this.connection.isConnected(); + } +@@ -93,13 +90,11 @@ + } + + @Override +- @Override + public void handleClientInformation(ServerboundClientInformationPacket serverboundclientinformationpacket) { + this.clientInformation = serverboundclientinformationpacket.information(); + } + + @Override +- @Override + public void handleResourcePackResponse(ServerboundResourcePackPacket serverboundresourcepackpacket) { + super.handleResourcePackResponse(serverboundresourcepackpacket); + if (serverboundresourcepackpacket.action().isTerminal()) { +@@ -109,7 +104,6 @@ + } + + @Override +- @Override + public void handleConfigurationFinished(ServerboundFinishConfigurationPacket serverboundfinishconfigurationpacket) { + this.connection.suspendInboundAfterProtocolChange(); + PacketUtils.ensureRunningOnSameThread(serverboundfinishconfigurationpacket, this, (BlockableEventLoop) this.server); +@@ -123,16 +117,16 @@ + return; + } + +- Component component = playerlist.canPlayerLogin(this.connection.getRemoteAddress(), this.gameProfile); ++ Component ichatbasecomponent = null; // CraftBukkit - login checks already completed + +- if (component != null) { +- this.disconnect(component); ++ if (ichatbasecomponent != null) { ++ this.disconnect(ichatbasecomponent); + return; + } + +- ServerPlayer serverplayer = playerlist.getPlayerForLogin(this.gameProfile, this.clientInformation); ++ ServerPlayer entityplayer = playerlist.getPlayerForLogin(this.gameProfile, this.clientInformation, this.player); // CraftBukkit + +- playerlist.placeNewPlayer(this.connection, serverplayer, this.createCookie(this.clientInformation)); ++ playerlist.placeNewPlayer(this.connection, entityplayer, this.createCookie(this.clientInformation)); + this.connection.resumeInboundAfterProtocolChange(); + } catch (Exception exception) { + ServerConfigurationPacketListenerImpl.LOGGER.error("Couldn't place player in world", exception); +@@ -143,7 +137,6 @@ + } + + @Override +- @Override + public void tick() { + this.keepConnectionAlive(); + } +@@ -162,11 +155,11 @@ + } + } + +- private void finishCurrentTask(ConfigurationTask.Type configurationtask_type) { +- ConfigurationTask.Type configurationtask_type1 = this.currentTask != null ? this.currentTask.type() : null; ++ private void finishCurrentTask(ConfigurationTask.a configurationtask_a) { ++ ConfigurationTask.a configurationtask_a1 = this.currentTask != null ? this.currentTask.type() : null; + +- if (!configurationtask_type.equals(configurationtask_type1)) { +- throw new IllegalStateException("Unexpected request for task finish, current task: " + configurationtask_type1 + ", requested: " + configurationtask_type); ++ if (!configurationtask_a.equals(configurationtask_a1)) { ++ throw new IllegalStateException("Unexpected request for task finish, current task: " + configurationtask_a1 + ", requested: " + configurationtask_a); + } else { + this.currentTask = null; + this.startNextTask(); diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerConnectionListener.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerConnectionListener.java.patch new file mode 100644 index 0000000000..5789ca1f2e --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerConnectionListener.java.patch @@ -0,0 +1,151 @@ +--- a/net/minecraft/server/network/ServerConnectionListener.java ++++ b/net/minecraft/server/network/ServerConnectionListener.java +@@ -62,12 +62,12 @@ + private final List channels = Collections.synchronizedList(Lists.newArrayList()); + final List connections = Collections.synchronizedList(Lists.newArrayList()); + +- public ServerConnectionListener(MinecraftServer minecraftserver) { +- this.server = minecraftserver; ++ public ServerConnectionListener(MinecraftServer server) { ++ this.server = server; + this.running = true; + } + +- public void startTcpServerListener(@Nullable InetAddress inetaddress, int i) throws IOException { ++ public void startTcpServerListener(@Nullable InetAddress address, int port) throws IOException { + List list = this.channels; + + synchronized (this.channels) { +@@ -85,7 +85,6 @@ + } + + this.channels.add(((ServerBootstrap) ((ServerBootstrap) (new ServerBootstrap()).channel(oclass)).childHandler(new ChannelInitializer() { +- @Override + protected void initChannel(Channel channel) { + Connection.setInitialProtocolAttributes(channel); + +@@ -99,33 +98,42 @@ + + Connection.configureSerialization(channelpipeline, PacketFlow.SERVERBOUND, (BandwidthDebugMonitor) null); + int j = ServerConnectionListener.this.server.getRateLimitPacketsPerSecond(); +- Object object = j > 0 ? new RateKickingConnection(j) : new Connection(PacketFlow.SERVERBOUND); ++ Connection object = j > 0 ? new RateKickingConnection(j) : new Connection(PacketFlow.SERVERBOUND); // CraftBukkit - decompile error + + ServerConnectionListener.this.connections.add(object); + ((Connection) object).configurePacketHandler(channelpipeline); + ((Connection) object).setListenerForServerboundHandshake(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object)); + } +- }).group(eventloopgroup).localAddress(inetaddress, i)).bind().syncUninterruptibly()); ++ }).group(eventloopgroup).localAddress(address, port)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit + } + } + ++ // CraftBukkit start ++ public void acceptConnections() { ++ synchronized (this.channels) { ++ for (ChannelFuture future : this.channels) { ++ future.channel().config().setAutoRead(true); ++ } ++ } ++ } ++ // CraftBukkit end ++ + public SocketAddress startMemoryChannel() { + List list = this.channels; + ChannelFuture channelfuture; + + synchronized (this.channels) { + channelfuture = ((ServerBootstrap) ((ServerBootstrap) (new ServerBootstrap()).channel(LocalServerChannel.class)).childHandler(new ChannelInitializer() { +- @Override + protected void initChannel(Channel channel) { + Connection.setInitialProtocolAttributes(channel); +- Connection connection = new Connection(PacketFlow.SERVERBOUND); ++ Connection networkmanager = new Connection(PacketFlow.SERVERBOUND); + +- connection.setListenerForServerboundHandshake(new MemoryServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, connection)); +- ServerConnectionListener.this.connections.add(connection); ++ networkmanager.setListenerForServerboundHandshake(new MemoryServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, networkmanager)); ++ ServerConnectionListener.this.connections.add(networkmanager); + ChannelPipeline channelpipeline = channel.pipeline(); + + Connection.configureInMemoryPipeline(channelpipeline, PacketFlow.SERVERBOUND); +- connection.configurePacketHandler(channelpipeline); ++ networkmanager.configurePacketHandler(channelpipeline); + } + }).group((EventLoopGroup) ServerConnectionListener.SERVER_EVENT_GROUP.get()).localAddress(LocalAddress.ANY)).bind().syncUninterruptibly(); + this.channels.add(channelfuture); +@@ -157,28 +165,28 @@ + Iterator iterator = this.connections.iterator(); + + while (iterator.hasNext()) { +- Connection connection = (Connection) iterator.next(); ++ Connection networkmanager = (Connection) iterator.next(); + +- if (!connection.isConnecting()) { +- if (connection.isConnected()) { ++ if (!networkmanager.isConnecting()) { ++ if (networkmanager.isConnected()) { + try { +- connection.tick(); ++ networkmanager.tick(); + } catch (Exception exception) { +- if (connection.isMemoryConnection()) { ++ if (networkmanager.isMemoryConnection()) { + throw new ReportedException(CrashReport.forThrowable(exception, "Ticking memory connection")); + } + +- ServerConnectionListener.LOGGER.warn("Failed to handle packet for {}", connection.getLoggableAddress(this.server.logIPs()), exception); +- MutableComponent mutablecomponent = Component.literal("Internal server error"); ++ ServerConnectionListener.LOGGER.warn("Failed to handle packet for {}", networkmanager.getLoggableAddress(this.server.logIPs()), exception); ++ MutableComponent ichatmutablecomponent = Component.literal("Internal server error"); + +- connection.send(new ClientboundDisconnectPacket(mutablecomponent), PacketSendListener.thenRun(() -> { +- connection.disconnect(mutablecomponent); ++ networkmanager.send(new ClientboundDisconnectPacket(ichatmutablecomponent), PacketSendListener.thenRun(() -> { ++ networkmanager.disconnect(ichatmutablecomponent); + })); +- connection.setReadOnly(); ++ networkmanager.setReadOnly(); + } + } else { + iterator.remove(); +- connection.handleDisconnection(); ++ networkmanager.handleDisconnection(); + } + } + } +@@ -201,27 +209,26 @@ + private final int jitter; + private final List queuedMessages = Lists.newArrayList(); + +- public LatencySimulator(int i, int j) { +- this.delay = i; +- this.jitter = j; ++ public LatencySimulator(int delay, int jitter) { ++ this.delay = delay; ++ this.jitter = jitter; + } + +- @Override + public void channelRead(ChannelHandlerContext channelhandlercontext, Object object) { + this.delayDownstream(channelhandlercontext, object); + } + +- private void delayDownstream(ChannelHandlerContext channelhandlercontext, Object object) { ++ private void delayDownstream(ChannelHandlerContext ctx, Object msg) { + int i = this.delay + (int) (Math.random() * (double) this.jitter); + +- this.queuedMessages.add(new ServerConnectionListener.LatencySimulator.DelayedMessage(channelhandlercontext, object)); ++ this.queuedMessages.add(new ServerConnectionListener.LatencySimulator.DelayedMessage(ctx, msg)); + ServerConnectionListener.LatencySimulator.TIMER.newTimeout(this::onTimeout, (long) i, TimeUnit.MILLISECONDS); + } + + private void onTimeout(Timeout timeout) { +- ServerConnectionListener.LatencySimulator.DelayedMessage serverconnectionlistener_latencysimulator_delayedmessage = (ServerConnectionListener.LatencySimulator.DelayedMessage) this.queuedMessages.remove(0); ++ ServerConnectionListener.LatencySimulator.DelayedMessage serverconnection_latencysimulator_delayedmessage = (ServerConnectionListener.LatencySimulator.DelayedMessage) this.queuedMessages.remove(0); + +- serverconnectionlistener_latencysimulator_delayedmessage.ctx.fireChannelRead(serverconnectionlistener_latencysimulator_delayedmessage.msg); ++ serverconnection_latencysimulator_delayedmessage.ctx.fireChannelRead(serverconnection_latencysimulator_delayedmessage.msg); + } + + private static class DelayedMessage { diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch new file mode 100644 index 0000000000..b586b52e06 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch @@ -0,0 +1,3151 @@ +--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -3,7 +3,6 @@ + import com.google.common.collect.Lists; + import com.google.common.primitives.Floats; + import com.mojang.authlib.GameProfile; +-import com.mojang.brigadier.CommandDispatcher; + import com.mojang.brigadier.ParseResults; + import com.mojang.brigadier.StringReader; + import com.mojang.logging.LogUtils; +@@ -60,6 +59,7 @@ + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.PacketUtils; + import net.minecraft.network.protocol.common.ServerboundClientInformationPacket; ++import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; + import net.minecraft.network.protocol.game.ClientboundBlockChangedAckPacket; + import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; + import net.minecraft.network.protocol.game.ClientboundCommandSuggestionsPacket; +@@ -70,6 +70,8 @@ + import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; + import net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket; + import net.minecraft.network.protocol.game.ClientboundSetCarriedItemPacket; ++import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; ++import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket; + import net.minecraft.network.protocol.game.ClientboundStartConfigurationPacket; + import net.minecraft.network.protocol.game.ClientboundSystemChatPacket; + import net.minecraft.network.protocol.game.ClientboundTagQueryPacket; +@@ -133,20 +135,19 @@ + import net.minecraft.util.SignatureValidator; + import net.minecraft.util.StringUtil; + import net.minecraft.world.Container; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.ExperienceOrb; + import net.minecraft.world.entity.HasCustomInventoryScreen; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MoverType; ++import net.minecraft.world.entity.Mob; + import net.minecraft.world.entity.PlayerRideableJumping; + import net.minecraft.world.entity.RelativeMovement; +-import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.ChatVisiblity; + import net.minecraft.world.entity.player.Inventory; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.player.ProfilePublicKey; + import net.minecraft.world.entity.projectile.AbstractArrow; + import net.minecraft.world.entity.vehicle.Boat; +@@ -154,14 +155,13 @@ + import net.minecraft.world.inventory.AnvilMenu; + import net.minecraft.world.inventory.BeaconMenu; + import net.minecraft.world.inventory.CrafterMenu; +-import net.minecraft.world.inventory.MerchantMenu; +-import net.minecraft.world.inventory.RecipeBookMenu; + import net.minecraft.world.item.BlockItem; + import net.minecraft.world.item.BucketItem; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.BaseCommandBlock; ++import net.minecraft.world.level.ClipContext; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.GameType; + import net.minecraft.world.level.Level; +@@ -175,15 +175,72 @@ + import net.minecraft.world.level.block.entity.SignBlockEntity; + import net.minecraft.world.level.block.entity.StructureBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.BlockHitResult; ++import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.mojang.datafixers.util.Pair; ++import java.util.Arrays; ++import java.util.concurrent.ExecutionException; ++import java.util.concurrent.atomic.AtomicInteger; ++import java.util.function.Function; ++import net.minecraft.network.chat.OutgoingChatMessage; ++import net.minecraft.world.entity.animal.Bucketable; ++import net.minecraft.world.entity.animal.allay.Allay; ++import net.minecraft.world.entity.item.ItemEntity; ++import net.minecraft.world.inventory.InventoryClickType; ++import net.minecraft.world.inventory.MerchantMenu; ++import net.minecraft.world.inventory.RecipeBookMenu; ++import net.minecraft.world.inventory.Slot; ++import net.minecraft.world.item.crafting.RecipeHolder; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftEntity; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.craftbukkit.util.LazyPlayerSet; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Event; ++import org.bukkit.event.block.Action; ++import org.bukkit.event.inventory.ClickType; ++import org.bukkit.event.inventory.CraftItemEvent; ++import org.bukkit.event.inventory.InventoryAction; ++import org.bukkit.event.inventory.InventoryClickEvent; ++import org.bukkit.event.inventory.InventoryCreativeEvent; ++import org.bukkit.event.inventory.InventoryType.SlotType; ++import org.bukkit.event.inventory.SmithItemEvent; ++import org.bukkit.event.player.AsyncPlayerChatEvent; ++import org.bukkit.event.player.PlayerAnimationEvent; ++import org.bukkit.event.player.PlayerAnimationType; ++import org.bukkit.event.player.PlayerChatEvent; ++import org.bukkit.event.player.PlayerCommandPreprocessEvent; ++import org.bukkit.event.player.PlayerInteractAtEntityEvent; ++import org.bukkit.event.player.PlayerInteractEntityEvent; ++import org.bukkit.event.player.PlayerItemHeldEvent; ++import org.bukkit.event.player.PlayerMoveEvent; ++import org.bukkit.event.player.PlayerRespawnEvent.RespawnReason; ++import org.bukkit.event.player.PlayerSwapHandItemsEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++import org.bukkit.event.player.PlayerToggleFlightEvent; ++import org.bukkit.event.player.PlayerToggleSneakEvent; ++import org.bukkit.event.player.PlayerToggleSprintEvent; ++import org.bukkit.inventory.CraftingInventory; ++import org.bukkit.inventory.EquipmentSlot; ++import org.bukkit.inventory.InventoryView; ++import org.bukkit.inventory.SmithingInventory; ++// CraftBukkit end ++ + public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl implements ServerGamePacketListener, ServerPlayerConnection, TickablePacketListener { + + static final Logger LOGGER = LogUtils.getLogger(); +@@ -195,7 +252,9 @@ + public final PlayerChunkSender chunkSender; + private int tickCount; + private int ackBlockChangesUpTo = -1; +- private int chatSpamTickCount; ++ // CraftBukkit start - multithreaded fields ++ private final AtomicInteger chatSpamTickCount = new AtomicInteger(); ++ // CraftBukkit end + private int dropSpamTickCount; + private double firstGoodX; + private double firstGoodY; +@@ -229,22 +288,37 @@ + private final FutureChain chatMessageChain; + private boolean waitingForSwitchToConfig; + +- public ServerGamePacketListenerImpl(MinecraftServer minecraftserver, Connection connection, ServerPlayer serverplayer, CommonListenerCookie commonlistenercookie) { +- super(minecraftserver, connection, commonlistenercookie); +- this.chunkSender = new PlayerChunkSender(connection.isMemoryConnection()); +- connection.setListener(this); +- this.player = serverplayer; +- serverplayer.connection = this; +- serverplayer.getTextFilter().join(); +- UUID uuid = serverplayer.getUUID(); ++ public ServerGamePacketListenerImpl(MinecraftServer minecraftserver, Connection networkmanager, ServerPlayer entityplayer, CommonListenerCookie commonlistenercookie) { ++ super(minecraftserver, networkmanager, commonlistenercookie, entityplayer); // CraftBukkit ++ this.chunkSender = new PlayerChunkSender(networkmanager.isMemoryConnection()); ++ networkmanager.setListener(this); ++ this.player = entityplayer; ++ entityplayer.connection = this; ++ entityplayer.getTextFilter().join(); ++ UUID uuid = entityplayer.getUUID(); + + Objects.requireNonNull(minecraftserver); + this.signedMessageDecoder = SignedMessageChain.Decoder.unsigned(uuid, minecraftserver::enforceSecureProfile); +- this.chatMessageChain = new FutureChain(minecraftserver); ++ this.chatMessageChain = new FutureChain(minecraftserver.chatExecutor); // CraftBukkit - async chat + } + ++ // CraftBukkit start - add fields ++ private int lastTick = MinecraftServer.currentTick; ++ private int allowedPlayerTicks = 1; ++ private int lastDropTick = MinecraftServer.currentTick; ++ private int lastBookTick = MinecraftServer.currentTick; ++ private int dropCount = 0; ++ ++ // Get position of last block hit for BlockDamageLevel.STOPPED ++ private double lastPosX = Double.MAX_VALUE; ++ private double lastPosY = Double.MAX_VALUE; ++ private double lastPosZ = Double.MAX_VALUE; ++ private float lastPitch = Float.MAX_VALUE; ++ private float lastYaw = Float.MAX_VALUE; ++ private boolean justTeleported = false; ++ // CraftBukkit end ++ + @Override +- @Override + public void tick() { + if (this.ackBlockChangesUpTo > -1) { + this.send(new ClientboundBlockChangedAckPacket(this.ackBlockChangesUpTo)); +@@ -295,15 +369,21 @@ + } + + this.keepConnectionAlive(); ++ // CraftBukkit start ++ for (int spam; (spam = this.chatSpamTickCount.get()) > 0 && !chatSpamTickCount.compareAndSet(spam, spam - 1); ) ; ++ /* Use thread-safe field access instead + if (this.chatSpamTickCount > 0) { + --this.chatSpamTickCount; + } ++ */ ++ // CraftBukkit end + + if (this.dropSpamTickCount > 0) { + --this.dropSpamTickCount; + } + + if (this.player.getLastActionTime() > 0L && this.server.getPlayerIdleTimeout() > 0 && Util.getMillis() - this.player.getLastActionTime() > (long) this.server.getPlayerIdleTimeout() * 1000L * 60L) { ++ this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 + this.disconnect(Component.translatable("multiplayer.disconnect.idling")); + } + +@@ -319,25 +399,22 @@ + } + + @Override +- @Override + public boolean isAcceptingMessages() { + return this.connection.isConnected() && !this.waitingForSwitchToConfig; + } + + @Override +- @Override + public boolean shouldHandleMessage(Packet packet) { + return super.shouldHandleMessage(packet) ? true : this.waitingForSwitchToConfig && this.connection.isConnected() && packet instanceof ServerboundConfigurationAcknowledgedPacket; + } + + @Override +- @Override + protected GameProfile playerProfile() { + return this.player.getGameProfile(); + } + +- private CompletableFuture filterTextPacket(T t0, BiFunction> bifunction) { +- return ((CompletableFuture) bifunction.apply(this.player.getTextFilter(), t0)).thenApply((object) -> { ++ private CompletableFuture filterTextPacket(T message, BiFunction> processor) { ++ return ((CompletableFuture) processor.apply(this.player.getTextFilter(), message)).thenApply((object) -> { + if (!this.isAcceptingMessages()) { + ServerGamePacketListenerImpl.LOGGER.debug("Ignoring packet due to disconnection"); + throw new CancellationException("disconnected"); +@@ -347,65 +424,90 @@ + }); + } + +- private CompletableFuture filterTextPacket(String s) { +- return this.filterTextPacket(s, TextFilter::processStreamMessage); ++ private CompletableFuture filterTextPacket(String text) { ++ return this.filterTextPacket(text, TextFilter::processStreamMessage); + } + +- private CompletableFuture> filterTextPacket(List list) { +- return this.filterTextPacket(list, TextFilter::processMessageBundle); ++ private CompletableFuture> filterTextPacket(List texts) { ++ return this.filterTextPacket(texts, TextFilter::processMessageBundle); + } + + @Override +- @Override +- public void handlePlayerInput(ServerboundPlayerInputPacket serverboundplayerinputpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundplayerinputpacket, this, this.player.serverLevel()); +- this.player.setPlayerInput(serverboundplayerinputpacket.getXxa(), serverboundplayerinputpacket.getZza(), serverboundplayerinputpacket.isJumping(), serverboundplayerinputpacket.isShiftKeyDown()); ++ public void handlePlayerInput(ServerboundPlayerInputPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ this.player.setPlayerInput(packet.getXxa(), packet.getZza(), packet.isJumping(), packet.isShiftKeyDown()); + } + +- private static boolean containsInvalidValues(double d0, double d1, double d2, float f, float f1) { +- return Double.isNaN(d0) || Double.isNaN(d1) || Double.isNaN(d2) || !Floats.isFinite(f1) || !Floats.isFinite(f); ++ private static boolean containsInvalidValues(double x, double d1, double y, float f, float z) { ++ return Double.isNaN(x) || Double.isNaN(d1) || Double.isNaN(y) || !Floats.isFinite(z) || !Floats.isFinite(f); + } + +- private static double clampHorizontal(double d0) { +- return Mth.clamp(d0, -3.0E7D, 3.0E7D); ++ private static double clampHorizontal(double value) { ++ return Mth.clamp(value, -3.0E7D, 3.0E7D); + } + +- private static double clampVertical(double d0) { +- return Mth.clamp(d0, -2.0E7D, 2.0E7D); ++ private static double clampVertical(double value) { ++ return Mth.clamp(value, -2.0E7D, 2.0E7D); + } + + @Override +- @Override +- public void handleMoveVehicle(ServerboundMoveVehiclePacket serverboundmovevehiclepacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundmovevehiclepacket, this, this.player.serverLevel()); +- if (containsInvalidValues(serverboundmovevehiclepacket.getX(), serverboundmovevehiclepacket.getY(), serverboundmovevehiclepacket.getZ(), serverboundmovevehiclepacket.getYRot(), serverboundmovevehiclepacket.getXRot())) { ++ public void handleMoveVehicle(ServerboundMoveVehiclePacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (containsInvalidValues(packet.getX(), packet.getY(), packet.getZ(), packet.getYRot(), packet.getXRot())) { + this.disconnect(Component.translatable("multiplayer.disconnect.invalid_vehicle_movement")); + } else { + Entity entity = this.player.getRootVehicle(); + + if (entity != this.player && entity.getControllingPassenger() == this.player && entity == this.lastVehicle) { +- ServerLevel serverlevel = this.player.serverLevel(); ++ ServerLevel worldserver = this.player.serverLevel(); + double d0 = entity.getX(); + double d1 = entity.getY(); + double d2 = entity.getZ(); +- double d3 = clampHorizontal(serverboundmovevehiclepacket.getX()); +- double d4 = clampVertical(serverboundmovevehiclepacket.getY()); +- double d5 = clampHorizontal(serverboundmovevehiclepacket.getZ()); +- float f = Mth.wrapDegrees(serverboundmovevehiclepacket.getYRot()); +- float f1 = Mth.wrapDegrees(serverboundmovevehiclepacket.getXRot()); ++ double d3 = clampHorizontal(packet.getX()); ++ double d4 = clampVertical(packet.getY()); ++ double d5 = clampHorizontal(packet.getZ()); ++ float f = Mth.wrapDegrees(packet.getYRot()); ++ float f1 = Mth.wrapDegrees(packet.getXRot()); + double d6 = d3 - this.vehicleFirstGoodX; + double d7 = d4 - this.vehicleFirstGoodY; + double d8 = d5 - this.vehicleFirstGoodZ; + double d9 = entity.getDeltaMovement().lengthSqr(); + double d10 = d6 * d6 + d7 * d7 + d8 * d8; + +- if (d10 - d9 > 100.0D && !this.isSingleplayerOwner()) { ++ ++ // CraftBukkit start - handle custom speeds and skipped ticks ++ this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick; ++ this.allowedPlayerTicks = Math.max(this.allowedPlayerTicks, 1); ++ this.lastTick = (int) (System.currentTimeMillis() / 50); ++ ++ ++this.receivedMovePacketCount; ++ int i = this.receivedMovePacketCount - this.knownMovePacketCount; ++ if (i > Math.max(this.allowedPlayerTicks, 5)) { ++ ServerGamePacketListenerImpl.LOGGER.debug(this.player.getScoreboardName() + " is sending move packets too frequently (" + i + " packets since last tick)"); ++ i = 1; ++ } ++ ++ if (d10 > 0) { ++ allowedPlayerTicks -= 1; ++ } else { ++ allowedPlayerTicks = 20; ++ } ++ double speed; ++ if (player.getAbilities().flying) { ++ speed = player.getAbilities().flyingSpeed * 20f; ++ } else { ++ speed = player.getAbilities().walkingSpeed * 10f; ++ } ++ speed *= 2f; // TODO: Get the speed of the vehicle instead of the player ++ ++ if (d10 - d9 > Math.max(100.0D, Math.pow((double) (10.0F * (float) i * speed), 2)) && !this.isSingleplayerOwner()) { ++ // CraftBukkit end + ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", new Object[]{entity.getName().getString(), this.player.getName().getString(), d6, d7, d8}); + this.send(new ClientboundMoveVehiclePacket(entity)); + return; + } + +- boolean flag = serverlevel.noCollision(entity, entity.getBoundingBox().deflate(0.0625D)); ++ boolean flag = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D)); + + d6 = d3 - this.vehicleLastGoodX; + d7 = d4 - this.vehicleLastGoodY - 1.0E-6D; +@@ -413,14 +515,14 @@ + boolean flag1 = entity.verticalCollisionBelow; + + if (entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; ++ LivingEntity entityliving = (LivingEntity) entity; + +- if (livingentity.onClimbable()) { +- livingentity.resetFallDistance(); ++ if (entityliving.onClimbable()) { ++ entityliving.resetFallDistance(); + } + } + +- entity.move(MoverType.PLAYER, new Vec3(d6, d7, d8)); ++ entity.move(EnumMoveType.PLAYER, new Vec3(d6, d7, d8)); + double d11 = d7; + + d6 = d3 - entity.getX(); +@@ -439,14 +541,72 @@ + } + + entity.absMoveTo(d3, d4, d5, f, f1); +- boolean flag3 = serverlevel.noCollision(entity, entity.getBoundingBox().deflate(0.0625D)); ++ player.absMoveTo(d3, d4, d5, this.player.getYRot(), this.player.getXRot()); // CraftBukkit ++ boolean flag3 = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D)); + + if (flag && (flag2 || !flag3)) { + entity.absMoveTo(d0, d1, d2, f, f1); ++ player.absMoveTo(d0, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit + this.send(new ClientboundMoveVehiclePacket(entity)); + return; + } + ++ // CraftBukkit start - fire PlayerMoveEvent ++ Player player = this.getCraftPlayer(); ++ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. ++ Location to = player.getLocation().clone(); // Start off the To location as the Players current location. ++ ++ // If the packet contains movement information then we update the To location with the correct XYZ. ++ to.setX(packet.getX()); ++ to.setY(packet.getY()); ++ to.setZ(packet.getZ()); ++ ++ ++ // If the packet contains look information then we update the To location with the correct Yaw & Pitch. ++ to.setYaw(packet.getYRot()); ++ to.setPitch(packet.getXRot()); ++ ++ // Prevent 40 event-calls for less than a single pixel of movement >.> ++ double delta = Math.pow(this.lastPosX - to.getX(), 2) + Math.pow(this.lastPosY - to.getY(), 2) + Math.pow(this.lastPosZ - to.getZ(), 2); ++ float deltaAngle = Math.abs(this.lastYaw - to.getYaw()) + Math.abs(this.lastPitch - to.getPitch()); ++ ++ if ((delta > 1f / 256 || deltaAngle > 10f) && !this.player.isImmobile()) { ++ this.lastPosX = to.getX(); ++ this.lastPosY = to.getY(); ++ this.lastPosZ = to.getZ(); ++ this.lastYaw = to.getYaw(); ++ this.lastPitch = to.getPitch(); ++ ++ // Skip the first time we do this ++ if (from.getX() != Double.MAX_VALUE) { ++ Location oldTo = to.clone(); ++ PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ // If the event is cancelled we move the player back to their old location. ++ if (event.isCancelled()) { ++ teleport(from); ++ return; ++ } ++ ++ // If a Plugin has changed the To destination then we teleport the Player ++ // there to avoid any 'Moved wrongly' or 'Moved too quickly' errors. ++ // We only do this if the Event was not cancelled. ++ if (!oldTo.equals(event.getTo()) && !event.isCancelled()) { ++ this.player.getBukkitEntity().teleport(event.getTo(), PlayerTeleportEvent.TeleportCause.PLUGIN); ++ return; ++ } ++ ++ // Check to see if the Players Location has some how changed during the call of the event. ++ // This can happen due to a plugin teleporting the player instead of using .setTo() ++ if (!from.equals(this.getCraftPlayer().getLocation()) && this.justTeleported) { ++ this.justTeleported = false; ++ return; ++ } ++ } ++ } ++ // CraftBukkit end ++ + this.player.serverLevel().getChunkSource().move(this.player); + this.player.checkMovementStatistics(this.player.getX() - d0, this.player.getY() - d1, this.player.getZ() - d2); + this.clientVehicleIsFloating = d11 >= -0.03125D && !flag1 && !this.server.isFlightAllowed() && !entity.isNoGravity() && this.noBlocksAround(entity); +@@ -463,10 +623,9 @@ + } + + @Override +- @Override +- public void handleAcceptTeleportPacket(ServerboundAcceptTeleportationPacket serverboundacceptteleportationpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundacceptteleportationpacket, this, this.player.serverLevel()); +- if (serverboundacceptteleportationpacket.getId() == this.awaitingTeleport) { ++ public void handleAcceptTeleportPacket(ServerboundAcceptTeleportationPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (packet.getId() == this.awaitingTeleport) { + if (this.awaitingPositionFromClient == null) { + this.disconnect(Component.translatable("multiplayer.disconnect.invalid_player_movement")); + return; +@@ -481,35 +640,34 @@ + } + + this.awaitingPositionFromClient = null; ++ this.player.serverLevel().getChunkSource().move(this.player); // CraftBukkit + } + + } + + @Override +- @Override +- public void handleRecipeBookSeenRecipePacket(ServerboundRecipeBookSeenRecipePacket serverboundrecipebookseenrecipepacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundrecipebookseenrecipepacket, this, this.player.serverLevel()); +- Optional optional = this.server.getRecipeManager().byKey(serverboundrecipebookseenrecipepacket.getRecipe()); +- ServerRecipeBook serverrecipebook = this.player.getRecipeBook(); ++ public void handleRecipeBookSeenRecipePacket(ServerboundRecipeBookSeenRecipePacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ Optional> optional = this.server.getRecipeManager().byKey(packet.getRecipe()); // CraftBukkit - decompile error ++ ServerRecipeBook recipebookserver = this.player.getRecipeBook(); + +- Objects.requireNonNull(serverrecipebook); +- optional.ifPresent(serverrecipebook::removeHighlight); ++ Objects.requireNonNull(recipebookserver); ++ optional.ifPresent(recipebookserver::removeHighlight); + } + + @Override +- @Override +- public void handleRecipeBookChangeSettingsPacket(ServerboundRecipeBookChangeSettingsPacket serverboundrecipebookchangesettingspacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundrecipebookchangesettingspacket, this, this.player.serverLevel()); +- this.player.getRecipeBook().setBookSetting(serverboundrecipebookchangesettingspacket.getBookType(), serverboundrecipebookchangesettingspacket.isOpen(), serverboundrecipebookchangesettingspacket.isFiltering()); ++ public void handleRecipeBookChangeSettingsPacket(ServerboundRecipeBookChangeSettingsPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ CraftEventFactory.callRecipeBookSettingsEvent(this.player, packet.getBookType(), packet.isOpen(), packet.isFiltering()); // CraftBukkit ++ this.player.getRecipeBook().setBookSetting(packet.getBookType(), packet.isOpen(), packet.isFiltering()); + } + + @Override +- @Override +- public void handleSeenAdvancements(ServerboundSeenAdvancementsPacket serverboundseenadvancementspacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundseenadvancementspacket, this, this.player.serverLevel()); +- if (serverboundseenadvancementspacket.getAction() == ServerboundSeenAdvancementsPacket.Action.OPENED_TAB) { +- ResourceLocation resourcelocation = (ResourceLocation) Objects.requireNonNull(serverboundseenadvancementspacket.getTab()); +- AdvancementHolder advancementholder = this.server.getAdvancements().get(resourcelocation); ++ public void handleSeenAdvancements(ServerboundSeenAdvancementsPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (packet.getAction() == ServerboundSeenAdvancementsPacket.Status.OPENED_TAB) { ++ ResourceLocation minecraftkey = (ResourceLocation) Objects.requireNonNull(packet.getTab()); ++ AdvancementHolder advancementholder = this.server.getAdvancements().get(minecraftkey); + + if (advancementholder != null) { + this.player.getAdvancements().setSelectedTab(advancementholder); +@@ -519,10 +677,15 @@ + } + + @Override +- @Override +- public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket serverboundcommandsuggestionpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundcommandsuggestionpacket, this, this.player.serverLevel()); +- StringReader stringreader = new StringReader(serverboundcommandsuggestionpacket.getCommand()); ++ public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ // CraftBukkit start ++ if (chatSpamTickCount.addAndGet(1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { ++ this.disconnect(Component.translatable("disconnect.spam")); ++ return; ++ } ++ // CraftBukkit end ++ StringReader stringreader = new StringReader(packet.getCommand()); + + if (stringreader.canRead() && stringreader.peek() == '/') { + stringreader.skip(); +@@ -531,70 +694,70 @@ + ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); + + this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { +- this.send(new ClientboundCommandSuggestionsPacket(serverboundcommandsuggestionpacket.getId(), suggestions)); ++ if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer ++ this.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions)); + }); + } + + @Override +- @Override +- public void handleSetCommandBlock(ServerboundSetCommandBlockPacket serverboundsetcommandblockpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundsetcommandblockpacket, this, this.player.serverLevel()); ++ public void handleSetCommandBlock(ServerboundSetCommandBlockPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + if (!this.server.isCommandBlockEnabled()) { + this.player.sendSystemMessage(Component.translatable("advMode.notEnabled")); + } else if (!this.player.canUseGameMasterBlocks()) { + this.player.sendSystemMessage(Component.translatable("advMode.notAllowed")); + } else { +- BaseCommandBlock basecommandblock = null; +- CommandBlockEntity commandblockentity = null; +- BlockPos blockpos = serverboundsetcommandblockpacket.getPos(); +- BlockEntity blockentity = this.player.level().getBlockEntity(blockpos); ++ BaseCommandBlock commandblocklistenerabstract = null; ++ CommandBlockEntity tileentitycommand = null; ++ BlockPos blockposition = packet.getPos(); ++ BlockEntity tileentity = this.player.level().getBlockEntity(blockposition); + +- if (blockentity instanceof CommandBlockEntity) { +- commandblockentity = (CommandBlockEntity) blockentity; +- basecommandblock = commandblockentity.getCommandBlock(); ++ if (tileentity instanceof CommandBlockEntity) { ++ tileentitycommand = (CommandBlockEntity) tileentity; ++ commandblocklistenerabstract = tileentitycommand.getCommandBlock(); + } + +- String s = serverboundsetcommandblockpacket.getCommand(); +- boolean flag = serverboundsetcommandblockpacket.isTrackOutput(); ++ String s = packet.getCommand(); ++ boolean flag = packet.isTrackOutput(); + +- if (basecommandblock != null) { +- CommandBlockEntity.Mode commandblockentity_mode = commandblockentity.getMode(); +- BlockState blockstate = this.player.level().getBlockState(blockpos); +- Direction direction = (Direction) blockstate.getValue(CommandBlock.FACING); +- BlockState blockstate1; ++ if (commandblocklistenerabstract != null) { ++ CommandBlockEntity.Type tileentitycommand_type = tileentitycommand.getMode(); ++ IBlockData iblockdata = this.player.level().getBlockState(blockposition); ++ Direction enumdirection = (Direction) iblockdata.getValue(CommandBlock.FACING); ++ IBlockData iblockdata1; + +- switch (serverboundsetcommandblockpacket.getMode()) { ++ switch (packet.getMode()) { + case SEQUENCE: +- blockstate1 = Blocks.CHAIN_COMMAND_BLOCK.defaultBlockState(); ++ iblockdata1 = Blocks.CHAIN_COMMAND_BLOCK.defaultBlockState(); + break; + case AUTO: +- blockstate1 = Blocks.REPEATING_COMMAND_BLOCK.defaultBlockState(); ++ iblockdata1 = Blocks.REPEATING_COMMAND_BLOCK.defaultBlockState(); + break; + case REDSTONE: + default: +- blockstate1 = Blocks.COMMAND_BLOCK.defaultBlockState(); ++ iblockdata1 = Blocks.COMMAND_BLOCK.defaultBlockState(); + } + +- BlockState blockstate2 = (BlockState) ((BlockState) blockstate1.setValue(CommandBlock.FACING, direction)).setValue(CommandBlock.CONDITIONAL, serverboundsetcommandblockpacket.isConditional()); ++ IBlockData iblockdata2 = (IBlockData) ((IBlockData) iblockdata1.setValue(CommandBlock.FACING, enumdirection)).setValue(CommandBlock.CONDITIONAL, packet.isConditional()); + +- if (blockstate2 != blockstate) { +- this.player.level().setBlock(blockpos, blockstate2, 2); +- blockentity.setBlockState(blockstate2); +- this.player.level().getChunkAt(blockpos).setBlockEntity(blockentity); ++ if (iblockdata2 != iblockdata) { ++ this.player.level().setBlock(blockposition, iblockdata2, 2); ++ tileentity.setBlockState(iblockdata2); ++ this.player.level().getChunkAt(blockposition).setBlockEntity(tileentity); + } + +- basecommandblock.setCommand(s); +- basecommandblock.setTrackOutput(flag); ++ commandblocklistenerabstract.setCommand(s); ++ commandblocklistenerabstract.setTrackOutput(flag); + if (!flag) { +- basecommandblock.setLastOutput((Component) null); ++ commandblocklistenerabstract.setLastOutput((Component) null); + } + +- commandblockentity.setAutomatic(serverboundsetcommandblockpacket.isAutomatic()); +- if (commandblockentity_mode != serverboundsetcommandblockpacket.getMode()) { +- commandblockentity.onModeSwitch(); ++ tileentitycommand.setAutomatic(packet.isAutomatic()); ++ if (tileentitycommand_type != packet.getMode()) { ++ tileentitycommand.onModeSwitch(); + } + +- basecommandblock.onUpdated(); ++ commandblocklistenerabstract.onUpdated(); + if (!StringUtil.isNullOrEmpty(s)) { + this.player.sendSystemMessage(Component.translatable("advMode.setCommand.success", s)); + } +@@ -604,213 +767,218 @@ + } + + @Override +- @Override +- public void handleSetCommandMinecart(ServerboundSetCommandMinecartPacket serverboundsetcommandminecartpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundsetcommandminecartpacket, this, this.player.serverLevel()); ++ public void handleSetCommandMinecart(ServerboundSetCommandMinecartPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + if (!this.server.isCommandBlockEnabled()) { + this.player.sendSystemMessage(Component.translatable("advMode.notEnabled")); + } else if (!this.player.canUseGameMasterBlocks()) { + this.player.sendSystemMessage(Component.translatable("advMode.notAllowed")); + } else { +- BaseCommandBlock basecommandblock = serverboundsetcommandminecartpacket.getCommandBlock(this.player.level()); ++ BaseCommandBlock commandblocklistenerabstract = packet.getCommandBlock(this.player.level()); + +- if (basecommandblock != null) { +- basecommandblock.setCommand(serverboundsetcommandminecartpacket.getCommand()); +- basecommandblock.setTrackOutput(serverboundsetcommandminecartpacket.isTrackOutput()); +- if (!serverboundsetcommandminecartpacket.isTrackOutput()) { +- basecommandblock.setLastOutput((Component) null); ++ if (commandblocklistenerabstract != null) { ++ commandblocklistenerabstract.setCommand(packet.getCommand()); ++ commandblocklistenerabstract.setTrackOutput(packet.isTrackOutput()); ++ if (!packet.isTrackOutput()) { ++ commandblocklistenerabstract.setLastOutput((Component) null); + } + +- basecommandblock.onUpdated(); +- this.player.sendSystemMessage(Component.translatable("advMode.setCommand.success", serverboundsetcommandminecartpacket.getCommand())); ++ commandblocklistenerabstract.onUpdated(); ++ this.player.sendSystemMessage(Component.translatable("advMode.setCommand.success", packet.getCommand())); + } + + } + } + + @Override +- @Override +- public void handlePickItem(ServerboundPickItemPacket serverboundpickitempacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundpickitempacket, this, this.player.serverLevel()); +- this.player.getInventory().pickSlot(serverboundpickitempacket.getSlot()); ++ public void handlePickItem(ServerboundPickItemPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ this.player.getInventory().pickSlot(packet.getSlot()); + this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, 0, this.player.getInventory().selected, this.player.getInventory().getItem(this.player.getInventory().selected))); +- this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, 0, serverboundpickitempacket.getSlot(), this.player.getInventory().getItem(serverboundpickitempacket.getSlot()))); ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, 0, packet.getSlot(), this.player.getInventory().getItem(packet.getSlot()))); + this.player.connection.send(new ClientboundSetCarriedItemPacket(this.player.getInventory().selected)); + } + + @Override +- @Override +- public void handleRenameItem(ServerboundRenameItemPacket serverboundrenameitempacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundrenameitempacket, this, this.player.serverLevel()); +- AbstractContainerMenu abstractcontainermenu = this.player.containerMenu; ++ public void handleRenameItem(ServerboundRenameItemPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ AbstractContainerMenu container = this.player.containerMenu; + +- if (abstractcontainermenu instanceof AnvilMenu) { +- AnvilMenu anvilmenu = (AnvilMenu) abstractcontainermenu; ++ if (container instanceof AnvilMenu) { ++ AnvilMenu containeranvil = (AnvilMenu) container; + +- if (!anvilmenu.stillValid(this.player)) { +- ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, anvilmenu); ++ if (!containeranvil.stillValid(this.player)) { ++ ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, containeranvil); + return; + } + +- anvilmenu.setItemName(serverboundrenameitempacket.getName()); ++ containeranvil.setItemName(packet.getName()); + } + + } + + @Override +- @Override +- public void handleSetBeaconPacket(ServerboundSetBeaconPacket serverboundsetbeaconpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundsetbeaconpacket, this, this.player.serverLevel()); +- AbstractContainerMenu abstractcontainermenu = this.player.containerMenu; ++ public void handleSetBeaconPacket(ServerboundSetBeaconPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ AbstractContainerMenu container = this.player.containerMenu; + +- if (abstractcontainermenu instanceof BeaconMenu) { +- BeaconMenu beaconmenu = (BeaconMenu) abstractcontainermenu; ++ if (container instanceof BeaconMenu) { ++ BeaconMenu containerbeacon = (BeaconMenu) container; + + if (!this.player.containerMenu.stillValid(this.player)) { + ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu); + return; + } + +- beaconmenu.updateEffects(serverboundsetbeaconpacket.getPrimary(), serverboundsetbeaconpacket.getSecondary()); ++ containerbeacon.updateEffects(packet.getPrimary(), packet.getSecondary()); + } + + } + + @Override +- @Override +- public void handleSetStructureBlock(ServerboundSetStructureBlockPacket serverboundsetstructureblockpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundsetstructureblockpacket, this, this.player.serverLevel()); ++ public void handleSetStructureBlock(ServerboundSetStructureBlockPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + if (this.player.canUseGameMasterBlocks()) { +- BlockPos blockpos = serverboundsetstructureblockpacket.getPos(); +- BlockState blockstate = this.player.level().getBlockState(blockpos); +- BlockEntity blockentity = this.player.level().getBlockEntity(blockpos); ++ BlockPos blockposition = packet.getPos(); ++ IBlockData iblockdata = this.player.level().getBlockState(blockposition); ++ BlockEntity tileentity = this.player.level().getBlockEntity(blockposition); + +- if (blockentity instanceof StructureBlockEntity) { +- StructureBlockEntity structureblockentity = (StructureBlockEntity) blockentity; ++ if (tileentity instanceof StructureBlockEntity) { ++ StructureBlockEntity tileentitystructure = (StructureBlockEntity) tileentity; + +- structureblockentity.setMode(serverboundsetstructureblockpacket.getMode()); +- structureblockentity.setStructureName(serverboundsetstructureblockpacket.getName()); +- structureblockentity.setStructurePos(serverboundsetstructureblockpacket.getOffset()); +- structureblockentity.setStructureSize(serverboundsetstructureblockpacket.getSize()); +- structureblockentity.setMirror(serverboundsetstructureblockpacket.getMirror()); +- structureblockentity.setRotation(serverboundsetstructureblockpacket.getRotation()); +- structureblockentity.setMetaData(serverboundsetstructureblockpacket.getData()); +- structureblockentity.setIgnoreEntities(serverboundsetstructureblockpacket.isIgnoreEntities()); +- structureblockentity.setShowAir(serverboundsetstructureblockpacket.isShowAir()); +- structureblockentity.setShowBoundingBox(serverboundsetstructureblockpacket.isShowBoundingBox()); +- structureblockentity.setIntegrity(serverboundsetstructureblockpacket.getIntegrity()); +- structureblockentity.setSeed(serverboundsetstructureblockpacket.getSeed()); +- if (structureblockentity.hasStructureName()) { +- String s = structureblockentity.getStructureName(); ++ tileentitystructure.setMode(packet.getMode()); ++ tileentitystructure.setStructureName(packet.getName()); ++ tileentitystructure.setStructurePos(packet.getOffset()); ++ tileentitystructure.setStructureSize(packet.getSize()); ++ tileentitystructure.setMirror(packet.getMirror()); ++ tileentitystructure.setRotation(packet.getRotation()); ++ tileentitystructure.setMetaData(packet.getData()); ++ tileentitystructure.setIgnoreEntities(packet.isIgnoreEntities()); ++ tileentitystructure.setShowAir(packet.isShowAir()); ++ tileentitystructure.setShowBoundingBox(packet.isShowBoundingBox()); ++ tileentitystructure.setIntegrity(packet.getIntegrity()); ++ tileentitystructure.setSeed(packet.getSeed()); ++ if (tileentitystructure.hasStructureName()) { ++ String s = tileentitystructure.getStructureName(); + +- if (serverboundsetstructureblockpacket.getUpdateType() == StructureBlockEntity.UpdateType.SAVE_AREA) { +- if (structureblockentity.saveStructure()) { ++ if (packet.getUpdateType() == StructureBlockEntity.UpdateType.SAVE_AREA) { ++ if (tileentitystructure.saveStructure()) { + this.player.displayClientMessage(Component.translatable("structure_block.save_success", s), false); + } else { + this.player.displayClientMessage(Component.translatable("structure_block.save_failure", s), false); + } +- } else if (serverboundsetstructureblockpacket.getUpdateType() == StructureBlockEntity.UpdateType.LOAD_AREA) { +- if (!structureblockentity.isStructureLoadable()) { ++ } else if (packet.getUpdateType() == StructureBlockEntity.UpdateType.LOAD_AREA) { ++ if (!tileentitystructure.isStructureLoadable()) { + this.player.displayClientMessage(Component.translatable("structure_block.load_not_found", s), false); +- } else if (structureblockentity.placeStructureIfSameSize(this.player.serverLevel())) { ++ } else if (tileentitystructure.placeStructureIfSameSize(this.player.serverLevel())) { + this.player.displayClientMessage(Component.translatable("structure_block.load_success", s), false); + } else { + this.player.displayClientMessage(Component.translatable("structure_block.load_prepare", s), false); + } +- } else if (serverboundsetstructureblockpacket.getUpdateType() == StructureBlockEntity.UpdateType.SCAN_AREA) { +- if (structureblockentity.detectSize()) { ++ } else if (packet.getUpdateType() == StructureBlockEntity.UpdateType.SCAN_AREA) { ++ if (tileentitystructure.detectSize()) { + this.player.displayClientMessage(Component.translatable("structure_block.size_success", s), false); + } else { + this.player.displayClientMessage(Component.translatable("structure_block.size_failure"), false); + } + } + } else { +- this.player.displayClientMessage(Component.translatable("structure_block.invalid_structure_name", serverboundsetstructureblockpacket.getName()), false); ++ this.player.displayClientMessage(Component.translatable("structure_block.invalid_structure_name", packet.getName()), false); + } + +- structureblockentity.setChanged(); +- this.player.level().sendBlockUpdated(blockpos, blockstate, blockstate, 3); ++ tileentitystructure.setChanged(); ++ this.player.level().sendBlockUpdated(blockposition, iblockdata, iblockdata, 3); + } + + } + } + + @Override +- @Override +- public void handleSetJigsawBlock(ServerboundSetJigsawBlockPacket serverboundsetjigsawblockpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundsetjigsawblockpacket, this, this.player.serverLevel()); ++ public void handleSetJigsawBlock(ServerboundSetJigsawBlockPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + if (this.player.canUseGameMasterBlocks()) { +- BlockPos blockpos = serverboundsetjigsawblockpacket.getPos(); +- BlockState blockstate = this.player.level().getBlockState(blockpos); +- BlockEntity blockentity = this.player.level().getBlockEntity(blockpos); ++ BlockPos blockposition = packet.getPos(); ++ IBlockData iblockdata = this.player.level().getBlockState(blockposition); ++ BlockEntity tileentity = this.player.level().getBlockEntity(blockposition); + +- if (blockentity instanceof JigsawBlockEntity) { +- JigsawBlockEntity jigsawblockentity = (JigsawBlockEntity) blockentity; ++ if (tileentity instanceof JigsawBlockEntity) { ++ JigsawBlockEntity tileentityjigsaw = (JigsawBlockEntity) tileentity; + +- jigsawblockentity.setName(serverboundsetjigsawblockpacket.getName()); +- jigsawblockentity.setTarget(serverboundsetjigsawblockpacket.getTarget()); +- jigsawblockentity.setPool(ResourceKey.create(Registries.TEMPLATE_POOL, serverboundsetjigsawblockpacket.getPool())); +- jigsawblockentity.setFinalState(serverboundsetjigsawblockpacket.getFinalState()); +- jigsawblockentity.setJoint(serverboundsetjigsawblockpacket.getJoint()); +- jigsawblockentity.setPlacementPriority(serverboundsetjigsawblockpacket.getPlacementPriority()); +- jigsawblockentity.setSelectionPriority(serverboundsetjigsawblockpacket.getSelectionPriority()); +- jigsawblockentity.setChanged(); +- this.player.level().sendBlockUpdated(blockpos, blockstate, blockstate, 3); ++ tileentityjigsaw.setName(packet.getName()); ++ tileentityjigsaw.setTarget(packet.getTarget()); ++ tileentityjigsaw.setPool(ResourceKey.create(Registries.TEMPLATE_POOL, packet.getPool())); ++ tileentityjigsaw.setFinalState(packet.getFinalState()); ++ tileentityjigsaw.setJoint(packet.getJoint()); ++ tileentityjigsaw.setPlacementPriority(packet.getPlacementPriority()); ++ tileentityjigsaw.setSelectionPriority(packet.getSelectionPriority()); ++ tileentityjigsaw.setChanged(); ++ this.player.level().sendBlockUpdated(blockposition, iblockdata, iblockdata, 3); + } + + } + } + + @Override +- @Override +- public void handleJigsawGenerate(ServerboundJigsawGeneratePacket serverboundjigsawgeneratepacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundjigsawgeneratepacket, this, this.player.serverLevel()); ++ public void handleJigsawGenerate(ServerboundJigsawGeneratePacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + if (this.player.canUseGameMasterBlocks()) { +- BlockPos blockpos = serverboundjigsawgeneratepacket.getPos(); +- BlockEntity blockentity = this.player.level().getBlockEntity(blockpos); ++ BlockPos blockposition = packet.getPos(); ++ BlockEntity tileentity = this.player.level().getBlockEntity(blockposition); + +- if (blockentity instanceof JigsawBlockEntity) { +- JigsawBlockEntity jigsawblockentity = (JigsawBlockEntity) blockentity; ++ if (tileentity instanceof JigsawBlockEntity) { ++ JigsawBlockEntity tileentityjigsaw = (JigsawBlockEntity) tileentity; + +- jigsawblockentity.generate(this.player.serverLevel(), serverboundjigsawgeneratepacket.levels(), serverboundjigsawgeneratepacket.keepJigsaws()); ++ tileentityjigsaw.generate(this.player.serverLevel(), packet.levels(), packet.keepJigsaws()); + } + + } + } + + @Override +- @Override +- public void handleSelectTrade(ServerboundSelectTradePacket serverboundselecttradepacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundselecttradepacket, this, this.player.serverLevel()); +- int i = serverboundselecttradepacket.getItem(); +- AbstractContainerMenu abstractcontainermenu = this.player.containerMenu; ++ public void handleSelectTrade(ServerboundSelectTradePacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ int i = packet.getItem(); ++ AbstractContainerMenu container = this.player.containerMenu; + +- if (abstractcontainermenu instanceof MerchantMenu) { +- MerchantMenu merchantmenu = (MerchantMenu) abstractcontainermenu; ++ if (container instanceof MerchantMenu) { ++ MerchantMenu containermerchant = (MerchantMenu) container; ++ // CraftBukkit start ++ final org.bukkit.event.inventory.TradeSelectEvent tradeSelectEvent = CraftEventFactory.callTradeSelectEvent(this.player, i, containermerchant); ++ if (tradeSelectEvent.isCancelled()) { ++ this.player.getBukkitEntity().updateInventory(); ++ return; ++ } ++ // CraftBukkit end + +- if (!merchantmenu.stillValid(this.player)) { +- ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, merchantmenu); ++ if (!containermerchant.stillValid(this.player)) { ++ ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, containermerchant); + return; + } + +- merchantmenu.setSelectionHint(i); +- merchantmenu.tryMoveItems(i); ++ containermerchant.setSelectionHint(i); ++ containermerchant.tryMoveItems(i); + } + + } + + @Override +- @Override +- public void handleEditBook(ServerboundEditBookPacket serverboundeditbookpacket) { +- int i = serverboundeditbookpacket.getSlot(); ++ public void handleEditBook(ServerboundEditBookPacket packet) { ++ // CraftBukkit start ++ if (this.lastBookTick + 20 > MinecraftServer.currentTick) { ++ this.disconnect("Book edited too quickly!"); ++ return; ++ } ++ this.lastBookTick = MinecraftServer.currentTick; ++ // CraftBukkit end ++ int i = packet.getSlot(); + + if (Inventory.isHotbarSlot(i) || i == 40) { + List list = Lists.newArrayList(); +- Optional optional = serverboundeditbookpacket.getTitle(); ++ Optional optional = packet.getTitle(); + + Objects.requireNonNull(list); + optional.ifPresent(list::add); +- Stream stream = serverboundeditbookpacket.getPages().stream().limit(100L); ++ Stream stream = packet.getPages().stream().limit(100L); // CraftBukkit - decompile error + + Objects.requireNonNull(list); + stream.forEach(list::add); +@@ -824,101 +992,100 @@ + } + } + +- private void updateBookContents(List list, int i) { +- ItemStack itemstack = this.player.getInventory().getItem(i); ++ private void updateBookContents(List pages, int index) { ++ ItemStack itemstack = this.player.getInventory().getItem(index); + + if (itemstack.is(Items.WRITABLE_BOOK)) { +- this.updateBookPages(list, UnaryOperator.identity(), itemstack); ++ this.updateBookPages(pages, UnaryOperator.identity(), itemstack.copy(), index, itemstack); // CraftBukkit + } + } + +- private void signBook(FilteredText filteredtext, List list, int i) { +- ItemStack itemstack = this.player.getInventory().getItem(i); ++ private void signBook(FilteredText title, List pages, int index) { ++ ItemStack itemstack = this.player.getInventory().getItem(index); + + if (itemstack.is(Items.WRITABLE_BOOK)) { + ItemStack itemstack1 = new ItemStack(Items.WRITTEN_BOOK); +- CompoundTag compoundtag = itemstack.getTag(); ++ CompoundTag nbttagcompound = itemstack.getTag(); + +- if (compoundtag != null) { +- itemstack1.setTag(compoundtag.copy()); ++ if (nbttagcompound != null) { ++ itemstack1.setTag(nbttagcompound.copy()); + } + + itemstack1.addTagElement("author", StringTag.valueOf(this.player.getName().getString())); + if (this.player.isTextFilteringEnabled()) { +- itemstack1.addTagElement("title", StringTag.valueOf(filteredtext.filteredOrEmpty())); ++ itemstack1.addTagElement("title", StringTag.valueOf(title.filteredOrEmpty())); + } else { +- itemstack1.addTagElement("filtered_title", StringTag.valueOf(filteredtext.filteredOrEmpty())); +- itemstack1.addTagElement("title", StringTag.valueOf(filteredtext.raw())); ++ itemstack1.addTagElement("filtered_title", StringTag.valueOf(title.filteredOrEmpty())); ++ itemstack1.addTagElement("title", StringTag.valueOf(title.raw())); + } + +- this.updateBookPages(list, (s) -> { ++ this.updateBookPages(pages, (s) -> { + return Component.Serializer.toJson(Component.literal(s)); +- }, itemstack1); +- this.player.getInventory().setItem(i, itemstack1); ++ }, itemstack1, index, itemstack); // CraftBukkit ++ this.player.getInventory().setItem(index, itemstack); // CraftBukkit - event factory updates the hand book + } + } + +- private void updateBookPages(List list, UnaryOperator unaryoperator, ItemStack itemstack) { +- ListTag listtag = new ListTag(); ++ private void updateBookPages(List list, UnaryOperator unaryoperator, ItemStack itemstack, int slot, ItemStack handItem) { // CraftBukkit ++ ListTag nbttaglist = new ListTag(); + + if (this.player.isTextFilteringEnabled()) { +- Stream stream = list.stream().map((filteredtext) -> { ++ Stream stream = list.stream().map((filteredtext) -> { // CraftBukkit - decompile error + return StringTag.valueOf((String) unaryoperator.apply(filteredtext.filteredOrEmpty())); + }); + +- Objects.requireNonNull(listtag); +- stream.forEach(listtag::add); ++ Objects.requireNonNull(nbttaglist); ++ stream.forEach(nbttaglist::add); + } else { +- CompoundTag compoundtag = new CompoundTag(); ++ CompoundTag nbttagcompound = new CompoundTag(); + int i = 0; + + for (int j = list.size(); i < j; ++i) { + FilteredText filteredtext = (FilteredText) list.get(i); + String s = filteredtext.raw(); + +- listtag.add(StringTag.valueOf((String) unaryoperator.apply(s))); ++ nbttaglist.add(StringTag.valueOf((String) unaryoperator.apply(s))); + if (filteredtext.isFiltered()) { +- compoundtag.putString(String.valueOf(i), (String) unaryoperator.apply(filteredtext.filteredOrEmpty())); ++ nbttagcompound.putString(String.valueOf(i), (String) unaryoperator.apply(filteredtext.filteredOrEmpty())); + } + } + +- if (!compoundtag.isEmpty()) { +- itemstack.addTagElement("filtered_pages", compoundtag); ++ if (!nbttagcompound.isEmpty()) { ++ itemstack.addTagElement("filtered_pages", nbttagcompound); + } + } + +- itemstack.addTagElement("pages", listtag); ++ itemstack.addTagElement("pages", nbttaglist); ++ CraftEventFactory.handleEditBookEvent(player, slot, handItem, itemstack); // CraftBukkit + } + + @Override +- @Override +- public void handleEntityTagQuery(ServerboundEntityTagQuery serverboundentitytagquery) { +- PacketUtils.ensureRunningOnSameThread(serverboundentitytagquery, this, this.player.serverLevel()); ++ public void handleEntityTagQuery(ServerboundEntityTagQuery packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + if (this.player.hasPermissions(2)) { +- Entity entity = this.player.level().getEntity(serverboundentitytagquery.getEntityId()); ++ Entity entity = this.player.level().getEntity(packet.getEntityId()); + + if (entity != null) { +- CompoundTag compoundtag = entity.saveWithoutId(new CompoundTag()); ++ CompoundTag nbttagcompound = entity.saveWithoutId(new CompoundTag()); + +- this.player.connection.send(new ClientboundTagQueryPacket(serverboundentitytagquery.getTransactionId(), compoundtag)); ++ this.player.connection.send(new ClientboundTagQueryPacket(packet.getTransactionId(), nbttagcompound)); + } + + } + } + + @Override +- @Override + public void handleContainerSlotStateChanged(ServerboundContainerSlotStateChangedPacket serverboundcontainerslotstatechangedpacket) { + PacketUtils.ensureRunningOnSameThread(serverboundcontainerslotstatechangedpacket, this, this.player.serverLevel()); + if (!this.player.isSpectator() && serverboundcontainerslotstatechangedpacket.containerId() == this.player.containerMenu.containerId) { +- AbstractContainerMenu abstractcontainermenu = this.player.containerMenu; ++ AbstractContainerMenu container = this.player.containerMenu; + +- if (abstractcontainermenu instanceof CrafterMenu) { +- CrafterMenu craftermenu = (CrafterMenu) abstractcontainermenu; +- Container container = craftermenu.getContainer(); ++ if (container instanceof CrafterMenu) { ++ CrafterMenu craftermenu = (CrafterMenu) container; ++ Container iinventory = craftermenu.getContainer(); + +- if (container instanceof CrafterBlockEntity) { +- CrafterBlockEntity crafterblockentity = (CrafterBlockEntity) container; ++ if (iinventory instanceof CrafterBlockEntity) { ++ CrafterBlockEntity crafterblockentity = (CrafterBlockEntity) iinventory; + + crafterblockentity.setSlotState(serverboundcontainerslotstatechangedpacket.slotId(), serverboundcontainerslotstatechangedpacket.newState()); + } +@@ -928,27 +1095,25 @@ + } + + @Override +- @Override +- public void handleBlockEntityTagQuery(ServerboundBlockEntityTagQuery serverboundblockentitytagquery) { +- PacketUtils.ensureRunningOnSameThread(serverboundblockentitytagquery, this, this.player.serverLevel()); ++ public void handleBlockEntityTagQuery(ServerboundBlockEntityTagQuery packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + if (this.player.hasPermissions(2)) { +- BlockEntity blockentity = this.player.level().getBlockEntity(serverboundblockentitytagquery.getPos()); +- CompoundTag compoundtag = blockentity != null ? blockentity.saveWithoutMetadata() : null; ++ BlockEntity tileentity = this.player.level().getBlockEntity(packet.getPos()); ++ CompoundTag nbttagcompound = tileentity != null ? tileentity.saveWithoutMetadata() : null; + +- this.player.connection.send(new ClientboundTagQueryPacket(serverboundblockentitytagquery.getTransactionId(), compoundtag)); ++ this.player.connection.send(new ClientboundTagQueryPacket(packet.getTransactionId(), nbttagcompound)); + } + } + + @Override +- @Override +- public void handleMovePlayer(ServerboundMovePlayerPacket serverboundmoveplayerpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundmoveplayerpacket, this, this.player.serverLevel()); +- if (containsInvalidValues(serverboundmoveplayerpacket.getX(0.0D), serverboundmoveplayerpacket.getY(0.0D), serverboundmoveplayerpacket.getZ(0.0D), serverboundmoveplayerpacket.getYRot(0.0F), serverboundmoveplayerpacket.getXRot(0.0F))) { ++ public void handleMovePlayer(ServerboundMovePlayerPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (containsInvalidValues(packet.getX(0.0D), packet.getY(0.0D), packet.getZ(0.0D), packet.getYRot(0.0F), packet.getXRot(0.0F))) { + this.disconnect(Component.translatable("multiplayer.disconnect.invalid_player_movement")); + } else { +- ServerLevel serverlevel = this.player.serverLevel(); ++ ServerLevel worldserver = this.player.serverLevel(); + +- if (!this.player.wonGame) { ++ if (!this.player.wonGame && !this.player.isImmobile()) { // CraftBukkit + if (this.tickCount == 0) { + this.resetPosition(); + } +@@ -958,19 +1123,27 @@ + this.awaitingTeleportTime = this.tickCount; + this.teleport(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); + } +- ++ this.allowedPlayerTicks = 20; // CraftBukkit + } else { + this.awaitingTeleportTime = this.tickCount; +- double d0 = clampHorizontal(serverboundmoveplayerpacket.getX(this.player.getX())); +- double d1 = clampVertical(serverboundmoveplayerpacket.getY(this.player.getY())); +- double d2 = clampHorizontal(serverboundmoveplayerpacket.getZ(this.player.getZ())); +- float f = Mth.wrapDegrees(serverboundmoveplayerpacket.getYRot(this.player.getYRot())); +- float f1 = Mth.wrapDegrees(serverboundmoveplayerpacket.getXRot(this.player.getXRot())); ++ double d0 = clampHorizontal(packet.getX(this.player.getX())); ++ double d1 = clampVertical(packet.getY(this.player.getY())); ++ double d2 = clampHorizontal(packet.getZ(this.player.getZ())); ++ float f = Mth.wrapDegrees(packet.getYRot(this.player.getYRot())); ++ float f1 = Mth.wrapDegrees(packet.getXRot(this.player.getXRot())); + + if (this.player.isPassenger()) { + this.player.absMoveTo(this.player.getX(), this.player.getY(), this.player.getZ(), f, f1); + this.player.serverLevel().getChunkSource().move(this.player); ++ this.allowedPlayerTicks = 20; // CraftBukkit + } else { ++ // CraftBukkit - Make sure the move is valid but then reset it for plugins to modify ++ double prevX = player.getX(); ++ double prevY = player.getY(); ++ double prevZ = player.getZ(); ++ float prevYaw = player.getYRot(); ++ float prevPitch = player.getXRot(); ++ // CraftBukkit end + double d3 = this.player.getX(); + double d4 = this.player.getY(); + double d5 = this.player.getZ(); +@@ -986,19 +1159,37 @@ + } + + } else { +- if (serverlevel.tickRateManager().runsNormally()) { ++ if (worldserver.tickRateManager().runsNormally()) { + ++this.receivedMovePacketCount; + int i = this.receivedMovePacketCount - this.knownMovePacketCount; + +- if (i > 5) { ++ // CraftBukkit start - handle custom speeds and skipped ticks ++ this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick; ++ this.allowedPlayerTicks = Math.max(this.allowedPlayerTicks, 1); ++ this.lastTick = (int) (System.currentTimeMillis() / 50); ++ ++ if (i > Math.max(this.allowedPlayerTicks, 5)) { + ServerGamePacketListenerImpl.LOGGER.debug("{} is sending move packets too frequently ({} packets since last tick)", this.player.getName().getString(), i); + i = 1; + } + ++ if (packet.hasRot || d10 > 0) { ++ allowedPlayerTicks -= 1; ++ } else { ++ allowedPlayerTicks = 20; ++ } ++ double speed; ++ if (player.getAbilities().flying) { ++ speed = player.getAbilities().flyingSpeed * 20f; ++ } else { ++ speed = player.getAbilities().walkingSpeed * 10f; ++ } ++ + if (!this.player.isChangingDimension() && (!this.player.level().getGameRules().getBoolean(GameRules.RULE_DISABLE_ELYTRA_MOVEMENT_CHECK) || !this.player.isFallFlying())) { + float f2 = this.player.isFallFlying() ? 300.0F : 100.0F; + +- if (d10 - d9 > (double) (f2 * (float) i) && !this.isSingleplayerOwner()) { ++ if (d10 - d9 > Math.max(f2, Math.pow((double) (10.0F * (float) i * speed), 2)) && !this.isSingleplayerOwner()) { ++ // CraftBukkit end + ServerGamePacketListenerImpl.LOGGER.warn("{} moved too quickly! {},{},{}", new Object[]{this.player.getName().getString(), d6, d7, d8}); + this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot()); + return; +@@ -1006,20 +1197,21 @@ + } + } + +- AABB aabb = this.player.getBoundingBox(); ++ AABB axisalignedbb = this.player.getBoundingBox(); + + d6 = d0 - this.lastGoodX; + d7 = d1 - this.lastGoodY; + d8 = d2 - this.lastGoodZ; + boolean flag = d7 > 0.0D; + +- if (this.player.onGround() && !serverboundmoveplayerpacket.isOnGround() && flag) { ++ if (this.player.onGround() && !packet.isOnGround() && flag) { + this.player.jumpFromGround(); + } + + boolean flag1 = this.player.verticalCollisionBelow; + +- this.player.move(MoverType.PLAYER, new Vec3(d6, d7, d8)); ++ this.player.move(EnumMoveType.PLAYER, new Vec3(d6, d7, d8)); ++ this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move + double d11 = d7; + + d6 = d0 - this.player.getX(); +@@ -1037,15 +1229,76 @@ + ServerGamePacketListenerImpl.LOGGER.warn("{} moved wrongly!", this.player.getName().getString()); + } + +- if (!this.player.noPhysics && !this.player.isSleeping() && (flag2 && serverlevel.noCollision(this.player, aabb) || this.isPlayerCollidingWithAnythingNew(serverlevel, aabb, d0, d1, d2))) { +- this.teleport(d3, d4, d5, f, f1); +- this.player.doCheckFallDamage(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5, serverboundmoveplayerpacket.isOnGround()); ++ if (!this.player.noPhysics && !this.player.isSleeping() && (flag2 && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb, d0, d1, d2))) { ++ this.internalTeleport(d3, d4, d5, f, f1, Collections.emptySet()); // CraftBukkit - SPIGOT-1807: Don't call teleport event, when the client thinks the player is falling, because the chunks are not loaded on the client yet. ++ this.player.doCheckFallDamage(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5, packet.isOnGround()); + } else { ++ // CraftBukkit start - fire PlayerMoveEvent ++ // Reset to old location first ++ this.player.absMoveTo(prevX, prevY, prevZ, prevYaw, prevPitch); ++ ++ Player player = this.getCraftPlayer(); ++ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. ++ Location to = player.getLocation().clone(); // Start off the To location as the Players current location. ++ ++ // If the packet contains movement information then we update the To location with the correct XYZ. ++ if (packet.hasPos) { ++ to.setX(packet.x); ++ to.setY(packet.y); ++ to.setZ(packet.z); ++ } ++ ++ // If the packet contains look information then we update the To location with the correct Yaw & Pitch. ++ if (packet.hasRot) { ++ to.setYaw(packet.yRot); ++ to.setPitch(packet.xRot); ++ } ++ ++ // Prevent 40 event-calls for less than a single pixel of movement >.> ++ double delta = Math.pow(this.lastPosX - to.getX(), 2) + Math.pow(this.lastPosY - to.getY(), 2) + Math.pow(this.lastPosZ - to.getZ(), 2); ++ float deltaAngle = Math.abs(this.lastYaw - to.getYaw()) + Math.abs(this.lastPitch - to.getPitch()); ++ ++ if ((delta > 1f / 256 || deltaAngle > 10f) && !this.player.isImmobile()) { ++ this.lastPosX = to.getX(); ++ this.lastPosY = to.getY(); ++ this.lastPosZ = to.getZ(); ++ this.lastYaw = to.getYaw(); ++ this.lastPitch = to.getPitch(); ++ ++ // Skip the first time we do this ++ if (from.getX() != Double.MAX_VALUE) { ++ Location oldTo = to.clone(); ++ PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ // If the event is cancelled we move the player back to their old location. ++ if (event.isCancelled()) { ++ teleport(from); ++ return; ++ } ++ ++ // If a Plugin has changed the To destination then we teleport the Player ++ // there to avoid any 'Moved wrongly' or 'Moved too quickly' errors. ++ // We only do this if the Event was not cancelled. ++ if (!oldTo.equals(event.getTo()) && !event.isCancelled()) { ++ this.player.getBukkitEntity().teleport(event.getTo(), PlayerTeleportEvent.TeleportCause.PLUGIN); ++ return; ++ } ++ ++ // Check to see if the Players Location has some how changed during the call of the event. ++ // This can happen due to a plugin teleporting the player instead of using .setTo() ++ if (!from.equals(this.getCraftPlayer().getLocation()) && this.justTeleported) { ++ this.justTeleported = false; ++ return; ++ } ++ } ++ } ++ // CraftBukkit end + this.player.absMoveTo(d0, d1, d2, f, f1); + this.clientIsFloating = d11 >= -0.03125D && !flag1 && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR && !this.server.isFlightAllowed() && !this.player.getAbilities().mayfly && !this.player.hasEffect(MobEffects.LEVITATION) && !this.player.isFallFlying() && !this.player.isAutoSpinAttack() && this.noBlocksAround(this.player); + this.player.serverLevel().getChunkSource().move(this.player); +- this.player.doCheckFallDamage(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5, serverboundmoveplayerpacket.isOnGround()); +- this.player.setOnGroundWithKnownMovement(serverboundmoveplayerpacket.isOnGround(), new Vec3(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5)); ++ this.player.doCheckFallDamage(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5, packet.isOnGround()); ++ this.player.setOnGroundWithKnownMovement(packet.isOnGround(), new Vec3(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5)); + if (flag) { + this.player.resetFallDistance(); + } +@@ -1062,10 +1315,10 @@ + } + } + +- private boolean isPlayerCollidingWithAnythingNew(LevelReader levelreader, AABB aabb, double d0, double d1, double d2) { +- AABB aabb1 = this.player.getBoundingBox().move(d0 - this.player.getX(), d1 - this.player.getY(), d2 - this.player.getZ()); +- Iterable iterable = levelreader.getCollisions(this.player, aabb1.deflate(9.999999747378752E-6D)); +- VoxelShape voxelshape = Shapes.create(aabb.deflate(9.999999747378752E-6D)); ++ private boolean isPlayerCollidingWithAnythingNew(LevelReader level, AABB box, double x, double d1, double y) { ++ AABB axisalignedbb1 = this.player.getBoundingBox().move(x - this.player.getX(), d1 - this.player.getY(), y - this.player.getZ()); ++ Iterable iterable = level.getCollisions(this.player, axisalignedbb1.deflate(9.999999747378752E-6D)); ++ VoxelShape voxelshape = Shapes.create(box.deflate(9.999999747378752E-6D)); + Iterator iterator = iterable.iterator(); + + VoxelShape voxelshape1; +@@ -1081,11 +1334,68 @@ + return true; + } + +- public void teleport(double d0, double d1, double d2, float f, float f1) { +- this.teleport(d0, d1, d2, f, f1, Collections.emptySet()); ++ // CraftBukkit start - Delegate to teleport(Location) ++ public void teleport(double x, double d1, double y, float f, float z) { ++ this.teleport(x, d1, y, f, z, PlayerTeleportEvent.TeleportCause.UNKNOWN); + } + +- public void teleport(double d0, double d1, double d2, float f, float f1, Set set) { ++ public void teleport(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { ++ this.teleport(d0, d1, d2, f, f1, Collections.emptySet(), cause); ++ } ++ ++ public void teleport(double x, double d1, double y, float f, float z, Set set) { ++ this.teleport(x, d1, y, f, z, set, PlayerTeleportEvent.TeleportCause.UNKNOWN); ++ } ++ ++ public boolean teleport(double d0, double d1, double d2, float f, float f1, Set set, PlayerTeleportEvent.TeleportCause cause) { // CraftBukkit - Return event status ++ Player player = this.getCraftPlayer(); ++ Location from = player.getLocation(); ++ ++ double x = d0; ++ double y = d1; ++ double z = d2; ++ float yaw = f; ++ float pitch = f1; ++ ++ Location to = new Location(this.getCraftPlayer().getWorld(), x, y, z, yaw, pitch); ++ // SPIGOT-5171: Triggered on join ++ if (from.equals(to)) { ++ this.internalTeleport(d0, d1, d2, f, f1, set); ++ return false; // CraftBukkit - Return event status ++ } ++ ++ PlayerTeleportEvent event = new PlayerTeleportEvent(player, from.clone(), to.clone(), cause); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled() || !to.equals(event.getTo())) { ++ set.clear(); // Can't relative teleport ++ to = event.isCancelled() ? event.getFrom() : event.getTo(); ++ d0 = to.getX(); ++ d1 = to.getY(); ++ d2 = to.getZ(); ++ f = to.getYaw(); ++ f1 = to.getPitch(); ++ } ++ ++ this.internalTeleport(d0, d1, d2, f, f1, set); ++ return event.isCancelled(); // CraftBukkit - Return event status ++ } ++ ++ public void teleport(Location dest) { ++ internalTeleport(dest.getX(), dest.getY(), dest.getZ(), dest.getYaw(), dest.getPitch(), Collections.emptySet()); ++ } ++ ++ private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set set) { ++ // CraftBukkit start ++ if (Float.isNaN(f)) { ++ f = 0; ++ } ++ if (Float.isNaN(f1)) { ++ f1 = 0; ++ } ++ ++ this.justTeleported = true; ++ // CraftBukkit end + double d3 = set.contains(RelativeMovement.X) ? this.player.getX() : 0.0D; + double d4 = set.contains(RelativeMovement.Y) ? this.player.getY() : 0.0D; + double d5 = set.contains(RelativeMovement.Z) ? this.player.getZ() : 0.0D; +@@ -1097,33 +1407,73 @@ + this.awaitingTeleport = 0; + } + ++ // CraftBukkit start - update last location ++ this.lastPosX = this.awaitingPositionFromClient.x; ++ this.lastPosY = this.awaitingPositionFromClient.y; ++ this.lastPosZ = this.awaitingPositionFromClient.z; ++ this.lastYaw = f; ++ this.lastPitch = f1; ++ // CraftBukkit end ++ + this.awaitingTeleportTime = this.tickCount; + this.player.absMoveTo(d0, d1, d2, f, f1); + this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport)); + } + + @Override +- @Override +- public void handlePlayerAction(ServerboundPlayerActionPacket serverboundplayeractionpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundplayeractionpacket, this, this.player.serverLevel()); +- BlockPos blockpos = serverboundplayeractionpacket.getPos(); ++ public void handlePlayerAction(ServerboundPlayerActionPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit ++ BlockPos blockposition = packet.getPos(); + + this.player.resetLastActionTime(); +- ServerboundPlayerActionPacket.Action serverboundplayeractionpacket_action = serverboundplayeractionpacket.getAction(); ++ ServerboundPlayerActionPacket.EnumPlayerDigType packetplayinblockdig_enumplayerdigtype = packet.getAction(); + +- switch (serverboundplayeractionpacket_action) { ++ switch (packetplayinblockdig_enumplayerdigtype) { + case SWAP_ITEM_WITH_OFFHAND: + if (!this.player.isSpectator()) { +- ItemStack itemstack = this.player.getItemInHand(InteractionHand.OFF_HAND); ++ ItemStack itemstack = this.player.getItemInHand(EnumHand.OFF_HAND); + +- this.player.setItemInHand(InteractionHand.OFF_HAND, this.player.getItemInHand(InteractionHand.MAIN_HAND)); +- this.player.setItemInHand(InteractionHand.MAIN_HAND, itemstack); ++ // CraftBukkit start - inspiration taken from DispenserRegistry (See SpigotCraft#394) ++ CraftItemStack mainHand = CraftItemStack.asCraftMirror(itemstack); ++ CraftItemStack offHand = CraftItemStack.asCraftMirror(this.player.getItemInHand(EnumHand.MAIN_HAND)); ++ PlayerSwapHandItemsEvent swapItemsEvent = new PlayerSwapHandItemsEvent(getCraftPlayer(), mainHand.clone(), offHand.clone()); ++ this.cserver.getPluginManager().callEvent(swapItemsEvent); ++ if (swapItemsEvent.isCancelled()) { ++ return; ++ } ++ if (swapItemsEvent.getOffHandItem().equals(offHand)) { ++ this.player.setItemInHand(EnumHand.OFF_HAND, this.player.getItemInHand(EnumHand.MAIN_HAND)); ++ } else { ++ this.player.setItemInHand(EnumHand.OFF_HAND, CraftItemStack.asNMSCopy(swapItemsEvent.getOffHandItem())); ++ } ++ if (swapItemsEvent.getMainHandItem().equals(mainHand)) { ++ this.player.setItemInHand(EnumHand.MAIN_HAND, itemstack); ++ } else { ++ this.player.setItemInHand(EnumHand.MAIN_HAND, CraftItemStack.asNMSCopy(swapItemsEvent.getMainHandItem())); ++ } ++ // CraftBukkit end + this.player.stopUsingItem(); + } + + return; + case DROP_ITEM: + if (!this.player.isSpectator()) { ++ // limit how quickly items can be dropped ++ // If the ticks aren't the same then the count starts from 0 and we update the lastDropTick. ++ if (this.lastDropTick != MinecraftServer.currentTick) { ++ this.dropCount = 0; ++ this.lastDropTick = MinecraftServer.currentTick; ++ } else { ++ // Else we increment the drop count and check the amount. ++ this.dropCount++; ++ if (this.dropCount >= 20) { ++ LOGGER.warn(this.player.getScoreboardName() + " dropped their items too quickly!"); ++ this.disconnect("You dropped your items too quickly (Hacking?)"); ++ return; ++ } ++ } ++ // CraftBukkit end + this.player.drop(false); + } + +@@ -1140,109 +1490,152 @@ + case START_DESTROY_BLOCK: + case ABORT_DESTROY_BLOCK: + case STOP_DESTROY_BLOCK: +- this.player.gameMode.handleBlockBreakAction(blockpos, serverboundplayeractionpacket_action, serverboundplayeractionpacket.getDirection(), this.player.level().getMaxBuildHeight(), serverboundplayeractionpacket.getSequence()); +- this.player.connection.ackBlockChangesUpTo(serverboundplayeractionpacket.getSequence()); ++ this.player.gameMode.handleBlockBreakAction(blockposition, packetplayinblockdig_enumplayerdigtype, packet.getDirection(), this.player.level().getMaxBuildHeight(), packet.getSequence()); ++ this.player.connection.ackBlockChangesUpTo(packet.getSequence()); + return; + default: + throw new IllegalArgumentException("Invalid player action"); + } + } + +- private static boolean wasBlockPlacementAttempt(ServerPlayer serverplayer, ItemStack itemstack) { +- if (itemstack.isEmpty()) { ++ private static boolean wasBlockPlacementAttempt(ServerPlayer player, ItemStack stack) { ++ if (stack.isEmpty()) { + return false; + } else { +- Item item = itemstack.getItem(); ++ Item item = stack.getItem(); + +- return (item instanceof BlockItem || item instanceof BucketItem) && !serverplayer.getCooldowns().isOnCooldown(item); ++ return (item instanceof BlockItem || item instanceof BucketItem) && !player.getCooldowns().isOnCooldown(item); + } + } + + @Override +- @Override +- public void handleUseItemOn(ServerboundUseItemOnPacket serverbounduseitemonpacket) { +- PacketUtils.ensureRunningOnSameThread(serverbounduseitemonpacket, this, this.player.serverLevel()); +- this.player.connection.ackBlockChangesUpTo(serverbounduseitemonpacket.getSequence()); +- ServerLevel serverlevel = this.player.serverLevel(); +- InteractionHand interactionhand = serverbounduseitemonpacket.getHand(); +- ItemStack itemstack = this.player.getItemInHand(interactionhand); ++ public void handleUseItemOn(ServerboundUseItemOnPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit ++ this.player.connection.ackBlockChangesUpTo(packet.getSequence()); ++ ServerLevel worldserver = this.player.serverLevel(); ++ EnumHand enumhand = packet.getHand(); ++ ItemStack itemstack = this.player.getItemInHand(enumhand); + +- if (itemstack.isItemEnabled(serverlevel.enabledFeatures())) { +- BlockHitResult blockhitresult = serverbounduseitemonpacket.getHitResult(); +- Vec3 vec3 = blockhitresult.getLocation(); +- BlockPos blockpos = blockhitresult.getBlockPos(); +- Vec3 vec31 = Vec3.atCenterOf(blockpos); ++ if (itemstack.isItemEnabled(worldserver.enabledFeatures())) { ++ BlockHitResult movingobjectpositionblock = packet.getHitResult(); ++ Vec3 vec3d = movingobjectpositionblock.getLocation(); ++ BlockPos blockposition = movingobjectpositionblock.getBlockPos(); ++ Vec3 vec3d1 = Vec3.atCenterOf(blockposition); + +- if (this.player.getEyePosition().distanceToSqr(vec31) <= ServerGamePacketListenerImpl.MAX_INTERACTION_DISTANCE) { +- Vec3 vec32 = vec3.subtract(vec31); ++ if (this.player.getEyePosition().distanceToSqr(vec3d1) <= ServerGamePacketListenerImpl.MAX_INTERACTION_DISTANCE) { ++ Vec3 vec3d2 = vec3d.subtract(vec3d1); + double d0 = 1.0000001D; + +- if (Math.abs(vec32.x()) < 1.0000001D && Math.abs(vec32.y()) < 1.0000001D && Math.abs(vec32.z()) < 1.0000001D) { +- Direction direction = blockhitresult.getDirection(); ++ if (Math.abs(vec3d2.x()) < 1.0000001D && Math.abs(vec3d2.y()) < 1.0000001D && Math.abs(vec3d2.z()) < 1.0000001D) { ++ Direction enumdirection = movingobjectpositionblock.getDirection(); + + this.player.resetLastActionTime(); + int i = this.player.level().getMaxBuildHeight(); + +- if (blockpos.getY() < i) { +- if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D) < 64.0D && serverlevel.mayInteract(this.player, blockpos)) { +- InteractionResult interactionresult = this.player.gameMode.useItemOn(this.player, serverlevel, itemstack, interactionhand, blockhitresult); ++ if (blockposition.getY() < i) { ++ if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.mayInteract(this.player, blockposition)) { ++ this.player.stopUsingItem(); // CraftBukkit - SPIGOT-4706 ++ InteractionResult enuminteractionresult = this.player.gameMode.useItemOn(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock); + +- if (direction == Direction.UP && !interactionresult.consumesAction() && blockpos.getY() >= i - 1 && wasBlockPlacementAttempt(this.player, itemstack)) { +- MutableComponent mutablecomponent = Component.translatable("build.tooHigh", i - 1).withStyle(ChatFormatting.RED); ++ if (enumdirection == Direction.UP && !enuminteractionresult.consumesAction() && blockposition.getY() >= i - 1 && wasBlockPlacementAttempt(this.player, itemstack)) { ++ MutableComponent ichatmutablecomponent = Component.translatable("build.tooHigh", i - 1).withStyle(ChatFormatting.RED); + +- this.player.sendSystemMessage(mutablecomponent, true); +- } else if (interactionresult.shouldSwing()) { +- this.player.swing(interactionhand, true); ++ this.player.sendSystemMessage(ichatmutablecomponent, true); ++ } else if (enuminteractionresult.shouldSwing()) { ++ this.player.swing(enumhand, true); + } + } + } else { +- MutableComponent mutablecomponent1 = Component.translatable("build.tooHigh", i - 1).withStyle(ChatFormatting.RED); ++ MutableComponent ichatmutablecomponent1 = Component.translatable("build.tooHigh", i - 1).withStyle(ChatFormatting.RED); + +- this.player.sendSystemMessage(mutablecomponent1, true); ++ this.player.sendSystemMessage(ichatmutablecomponent1, true); + } + +- this.player.connection.send(new ClientboundBlockUpdatePacket(serverlevel, blockpos)); +- this.player.connection.send(new ClientboundBlockUpdatePacket(serverlevel, blockpos.relative(direction))); ++ this.player.connection.send(new ClientboundBlockUpdatePacket(worldserver, blockposition)); ++ this.player.connection.send(new ClientboundBlockUpdatePacket(worldserver, blockposition.relative(enumdirection))); + } else { +- ServerGamePacketListenerImpl.LOGGER.warn("Rejecting UseItemOnPacket from {}: Location {} too far away from hit block {}.", new Object[]{this.player.getGameProfile().getName(), vec3, blockpos}); ++ ServerGamePacketListenerImpl.LOGGER.warn("Rejecting UseItemOnPacket from {}: Location {} too far away from hit block {}.", new Object[]{this.player.getGameProfile().getName(), vec3d, blockposition}); + } + } + } + } + + @Override +- @Override +- public void handleUseItem(ServerboundUseItemPacket serverbounduseitempacket) { +- PacketUtils.ensureRunningOnSameThread(serverbounduseitempacket, this, this.player.serverLevel()); +- this.ackBlockChangesUpTo(serverbounduseitempacket.getSequence()); +- ServerLevel serverlevel = this.player.serverLevel(); +- InteractionHand interactionhand = serverbounduseitempacket.getHand(); +- ItemStack itemstack = this.player.getItemInHand(interactionhand); ++ public void handleUseItem(ServerboundUseItemPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit ++ this.ackBlockChangesUpTo(packet.getSequence()); ++ ServerLevel worldserver = this.player.serverLevel(); ++ EnumHand enumhand = packet.getHand(); ++ ItemStack itemstack = this.player.getItemInHand(enumhand); + + this.player.resetLastActionTime(); +- if (!itemstack.isEmpty() && itemstack.isItemEnabled(serverlevel.enabledFeatures())) { +- InteractionResult interactionresult = this.player.gameMode.useItem(this.player, serverlevel, itemstack, interactionhand); ++ if (!itemstack.isEmpty() && itemstack.isItemEnabled(worldserver.enabledFeatures())) { ++ // CraftBukkit start ++ // Raytrace to look for 'rogue armswings' ++ float f1 = this.player.getXRot(); ++ float f2 = this.player.getYRot(); ++ double d0 = this.player.getX(); ++ double d1 = this.player.getY() + (double) this.player.getEyeHeight(); ++ double d2 = this.player.getZ(); ++ Vec3 vec3d = new Vec3(d0, d1, d2); + +- if (interactionresult.shouldSwing()) { +- this.player.swing(interactionhand, true); ++ float f3 = Mth.cos(-f2 * 0.017453292F - 3.1415927F); ++ float f4 = Mth.sin(-f2 * 0.017453292F - 3.1415927F); ++ float f5 = -Mth.cos(-f1 * 0.017453292F); ++ float f6 = Mth.sin(-f1 * 0.017453292F); ++ float f7 = f4 * f5; ++ float f8 = f3 * f5; ++ double d3 = player.gameMode.getGameModeForPlayer()== GameType.CREATIVE ? 5.0D : 4.5D; ++ Vec3 vec3d1 = vec3d.add((double) f7 * d3, (double) f6 * d3, (double) f8 * d3); ++ HitResult movingobjectposition = this.player.level().clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)); ++ ++ boolean cancelled; ++ if (movingobjectposition == null || movingobjectposition.getType() != HitResult.EnumMovingObjectType.BLOCK) { ++ org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.RIGHT_CLICK_AIR, itemstack, enumhand); ++ cancelled = event.useItemInHand() == Event.Result.DENY; ++ } else { ++ BlockHitResult movingobjectpositionblock = (BlockHitResult) movingobjectposition; ++ if (player.gameMode.firedInteract && player.gameMode.interactPosition.equals(movingobjectpositionblock.getBlockPos()) && player.gameMode.interactHand == enumhand && ItemStack.isSameItemSameTags(player.gameMode.interactItemStack, itemstack)) { ++ cancelled = player.gameMode.interactResult; ++ } else { ++ org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), itemstack, true, enumhand, movingobjectpositionblock.getLocation()); ++ cancelled = event.useItemInHand() == Event.Result.DENY; ++ } ++ player.gameMode.firedInteract = false; + } + ++ if (cancelled) { ++ this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524 ++ return; ++ } ++ itemstack = this.player.getItemInHand(enumhand); // Update in case it was changed in the event ++ if (itemstack.isEmpty()) { ++ return; ++ } ++ // CraftBukkit end ++ InteractionResult enuminteractionresult = this.player.gameMode.useItem(this.player, worldserver, itemstack, enumhand); ++ ++ if (enuminteractionresult.shouldSwing()) { ++ this.player.swing(enumhand, true); ++ } ++ + } + } + + @Override +- @Override +- public void handleTeleportToEntityPacket(ServerboundTeleportToEntityPacket serverboundteleporttoentitypacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundteleporttoentitypacket, this, this.player.serverLevel()); ++ public void handleTeleportToEntityPacket(ServerboundTeleportToEntityPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + if (this.player.isSpectator()) { + Iterator iterator = this.server.getAllLevels().iterator(); + + while (iterator.hasNext()) { +- ServerLevel serverlevel = (ServerLevel) iterator.next(); +- Entity entity = serverboundteleporttoentitypacket.getEntity(serverlevel); ++ ServerLevel worldserver = (ServerLevel) iterator.next(); ++ Entity entity = packet.getEntity(worldserver); + + if (entity != null) { +- this.player.teleportTo(serverlevel, entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot()); ++ this.player.teleportTo(worldserver, entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot(), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.SPECTATE); // CraftBukkit + return; + } + } +@@ -1251,104 +1644,136 @@ + } + + @Override +- @Override +- public void handlePaddleBoat(ServerboundPaddleBoatPacket serverboundpaddleboatpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundpaddleboatpacket, this, this.player.serverLevel()); ++ public void handlePaddleBoat(ServerboundPaddleBoatPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + Entity entity = this.player.getControlledVehicle(); + + if (entity instanceof Boat) { +- Boat boat = (Boat) entity; ++ Boat entityboat = (Boat) entity; + +- boat.setPaddleState(serverboundpaddleboatpacket.getLeft(), serverboundpaddleboatpacket.getRight()); ++ entityboat.setPaddleState(packet.getLeft(), packet.getRight()); + } + + } + + @Override +- @Override +- public void onDisconnect(Component component) { +- ServerGamePacketListenerImpl.LOGGER.info("{} lost connection: {}", this.player.getName().getString(), component.getString()); ++ public void onDisconnect(Component reason) { ++ // CraftBukkit start - Rarely it would send a disconnect line twice ++ if (this.processedDisconnect) { ++ return; ++ } else { ++ this.processedDisconnect = true; ++ } ++ // CraftBukkit end ++ ServerGamePacketListenerImpl.LOGGER.info("{} lost connection: {}", this.player.getName().getString(), reason.getString()); + this.removePlayerFromWorld(); +- super.onDisconnect(component); ++ super.onDisconnect(reason); + } + + private void removePlayerFromWorld() { + this.chatMessageChain.close(); ++ // CraftBukkit start - Replace vanilla quit message handling with our own. ++ /* + this.server.invalidateStatus(); +- this.server.getPlayerList().broadcastSystemMessage(Component.translatable("multiplayer.player.left", this.player.getDisplayName()).withStyle(ChatFormatting.YELLOW), false); ++ this.server.getPlayerList().broadcastSystemMessage(IChatBaseComponent.translatable("multiplayer.player.left", this.player.getDisplayName()).withStyle(EnumChatFormat.YELLOW), false); ++ */ ++ + this.player.disconnect(); +- this.server.getPlayerList().remove(this.player); ++ String quitMessage = this.server.getPlayerList().remove(this.player); ++ if ((quitMessage != null) && (quitMessage.length() > 0)) { ++ this.server.getPlayerList().broadcastMessage(CraftChatMessage.fromString(quitMessage)); ++ } ++ // CraftBukkit end + this.player.getTextFilter().leave(); + } + +- public void ackBlockChangesUpTo(int i) { +- if (i < 0) { ++ public void ackBlockChangesUpTo(int sequence) { ++ if (sequence < 0) { + throw new IllegalArgumentException("Expected packet sequence nr >= 0"); + } else { +- this.ackBlockChangesUpTo = Math.max(i, this.ackBlockChangesUpTo); ++ this.ackBlockChangesUpTo = Math.max(sequence, this.ackBlockChangesUpTo); + } + } + + @Override +- @Override +- public void handleSetCarriedItem(ServerboundSetCarriedItemPacket serverboundsetcarrieditempacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundsetcarrieditempacket, this, this.player.serverLevel()); +- if (serverboundsetcarrieditempacket.getSlot() >= 0 && serverboundsetcarrieditempacket.getSlot() < Inventory.getSelectionSize()) { +- if (this.player.getInventory().selected != serverboundsetcarrieditempacket.getSlot() && this.player.getUsedItemHand() == InteractionHand.MAIN_HAND) { ++ public void handleSetCarriedItem(ServerboundSetCarriedItemPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit ++ if (packet.getSlot() >= 0 && packet.getSlot() < Inventory.getSelectionSize()) { ++ PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getCraftPlayer(), this.player.getInventory().selected, packet.getSlot()); ++ this.cserver.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ this.send(new ClientboundSetCarriedItemPacket(this.player.getInventory().selected)); ++ this.player.resetLastActionTime(); ++ return; ++ } ++ // CraftBukkit end ++ if (this.player.getInventory().selected != packet.getSlot() && this.player.getUsedItemHand() == EnumHand.MAIN_HAND) { + this.player.stopUsingItem(); + } + +- this.player.getInventory().selected = serverboundsetcarrieditempacket.getSlot(); ++ this.player.getInventory().selected = packet.getSlot(); + this.player.resetLastActionTime(); + } else { + ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); ++ this.disconnect("Invalid hotbar selection (Hacking?)"); // CraftBukkit + } + } + + @Override +- @Override +- public void handleChat(ServerboundChatPacket serverboundchatpacket) { +- if (isChatMessageIllegal(serverboundchatpacket.message())) { ++ public void handleChat(ServerboundChatPacket packet) { ++ // CraftBukkit start - async chat ++ // SPIGOT-3638 ++ if (this.server.isStopped()) { ++ return; ++ } ++ // CraftBukkit end ++ if (isChatMessageIllegal(packet.message())) { + this.disconnect(Component.translatable("multiplayer.disconnect.illegal_characters")); + } else { +- Optional optional = this.tryHandleChat(serverboundchatpacket.lastSeenMessages()); ++ Optional optional = this.tryHandleChat(packet.lastSeenMessages()); + + if (optional.isPresent()) { +- this.server.submit(() -> { ++ // this.server.submit(() -> { // CraftBukkit - async chat + PlayerChatMessage playerchatmessage; + + try { +- playerchatmessage = this.getSignedMessage(serverboundchatpacket, (LastSeenMessages) optional.get()); +- } catch (SignedMessageChain.DecodeException signedmessagechain_decodeexception) { +- this.handleMessageDecodeFailure(signedmessagechain_decodeexception); ++ playerchatmessage = this.getSignedMessage(packet, (LastSeenMessages) optional.get()); ++ } catch (SignedMessageChain.DecodeException signedmessagechain_a) { ++ this.handleMessageDecodeFailure(signedmessagechain_a); + return; + } + +- CompletableFuture completablefuture = this.filterTextPacket(playerchatmessage.signedContent()); +- Component component = this.server.getChatDecorator().decorate(this.player, playerchatmessage.decoratedContent()); ++ CompletableFuture completablefuture = this.filterTextPacket(playerchatmessage.signedContent()).thenApplyAsync(Function.identity(), this.server.chatExecutor); // CraftBukkit - async chat ++ Component ichatbasecomponent = this.server.getChatDecorator().decorate(this.player, playerchatmessage.decoratedContent()); + + this.chatMessageChain.append(completablefuture, (filteredtext) -> { +- PlayerChatMessage playerchatmessage1 = playerchatmessage.withUnsignedContent(component).filter(filteredtext.mask()); ++ PlayerChatMessage playerchatmessage1 = playerchatmessage.withUnsignedContent(ichatbasecomponent).filter(filteredtext.mask()); + + this.broadcastChatMessage(playerchatmessage1); + }); +- }); ++ // }); // CraftBukkit - async chat + } + + } + } + + @Override +- @Override +- public void handleChatCommand(ServerboundChatCommandPacket serverboundchatcommandpacket) { +- if (isChatMessageIllegal(serverboundchatcommandpacket.command())) { ++ public void handleChatCommand(ServerboundChatCommandPacket packet) { ++ if (isChatMessageIllegal(packet.command())) { + this.disconnect(Component.translatable("multiplayer.disconnect.illegal_characters")); + } else { +- Optional optional = this.tryHandleChat(serverboundchatcommandpacket.lastSeenMessages()); ++ Optional optional = this.tryHandleChat(packet.lastSeenMessages()); + + if (optional.isPresent()) { + this.server.submit(() -> { +- this.performChatCommand(serverboundchatcommandpacket, (LastSeenMessages) optional.get()); ++ // CraftBukkit start - SPIGOT-7346: Prevent disconnected players from executing commands ++ if (player.hasDisconnected()) { ++ return; ++ } ++ // CraftBukkit end ++ ++ this.performChatCommand(packet, (LastSeenMessages) optional.get()); + this.detectRateSpam(); + }); + } +@@ -1356,61 +1781,74 @@ + } + } + +- private void performChatCommand(ServerboundChatCommandPacket serverboundchatcommandpacket, LastSeenMessages lastseenmessages) { +- ParseResults parseresults = this.parseCommand(serverboundchatcommandpacket.command()); ++ private void performChatCommand(ServerboundChatCommandPacket packet, LastSeenMessages lastSeenMessages) { ++ // CraftBukkit start ++ String command = "/" + packet.command(); ++ ServerGamePacketListenerImpl.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + command); + ++ PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(getCraftPlayer(), command, new LazyPlayerSet(server)); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ command = event.getMessage().substring(1); ++ ++ ParseResults parseresults = this.parseCommand(command); ++ // CraftBukkit end ++ + Map map; + + try { +- map = this.collectSignedArguments(serverboundchatcommandpacket, SignableCommand.of(parseresults), lastseenmessages); +- } catch (SignedMessageChain.DecodeException signedmessagechain_decodeexception) { +- this.handleMessageDecodeFailure(signedmessagechain_decodeexception); ++ map = (packet.command().equals(command)) ? this.collectSignedArguments(packet, SignableCommand.of(parseresults), lastSeenMessages) : Collections.emptyMap(); // CraftBukkit ++ } catch (SignedMessageChain.DecodeException signedmessagechain_a) { ++ this.handleMessageDecodeFailure(signedmessagechain_a); + return; + } + +- CommandSigningContext.SignedArguments commandsigningcontext_signedarguments = new CommandSigningContext.SignedArguments(map); ++ CommandSigningContext.a commandsigningcontext_a = new CommandSigningContext.a(map); + +- parseresults = Commands.mapSource(parseresults, (commandsourcestack) -> { +- return commandsourcestack.withSigningContext(commandsigningcontext_signedarguments, this.chatMessageChain); ++ parseresults = Commands.mapSource(parseresults, (commandlistenerwrapper) -> { // CraftBukkit - decompile error ++ return commandlistenerwrapper.withSigningContext(commandsigningcontext_a, this.chatMessageChain); + }); +- this.server.getCommands().performCommand(parseresults, serverboundchatcommandpacket.command()); ++ this.server.getCommands().performCommand(parseresults, command); // CraftBukkit + } + +- private void handleMessageDecodeFailure(SignedMessageChain.DecodeException signedmessagechain_decodeexception) { +- ServerGamePacketListenerImpl.LOGGER.warn("Failed to update secure chat state for {}: '{}'", this.player.getGameProfile().getName(), signedmessagechain_decodeexception.getComponent().getString()); +- if (signedmessagechain_decodeexception.shouldDisconnect()) { +- this.disconnect(signedmessagechain_decodeexception.getComponent()); ++ private void handleMessageDecodeFailure(SignedMessageChain.DecodeException exception) { ++ ServerGamePacketListenerImpl.LOGGER.warn("Failed to update secure chat state for {}: '{}'", this.player.getGameProfile().getName(), exception.getComponent().getString()); ++ if (exception.shouldDisconnect()) { ++ this.disconnect(exception.getComponent()); + } else { +- this.player.sendSystemMessage(signedmessagechain_decodeexception.getComponent().copy().withStyle(ChatFormatting.RED)); ++ this.player.sendSystemMessage(exception.getComponent().copy().withStyle(ChatFormatting.RED)); + } + + } + +- private Map collectSignedArguments(ServerboundChatCommandPacket serverboundchatcommandpacket, SignableCommand signablecommand, LastSeenMessages lastseenmessages) throws SignedMessageChain.DecodeException { ++ private Map collectSignedArguments(ServerboundChatCommandPacket packet, SignableCommand command, LastSeenMessages lastSeenMessages) throws SignedMessageChain.DecodeException { + Map map = new Object2ObjectOpenHashMap(); +- Iterator iterator = signablecommand.arguments().iterator(); ++ Iterator iterator = command.arguments().iterator(); + + while (iterator.hasNext()) { +- SignableCommand.Argument signablecommand_argument = (SignableCommand.Argument) iterator.next(); +- MessageSignature messagesignature = serverboundchatcommandpacket.argumentSignatures().get(signablecommand_argument.name()); +- SignedMessageBody signedmessagebody = new SignedMessageBody(signablecommand_argument.value(), serverboundchatcommandpacket.timeStamp(), serverboundchatcommandpacket.salt(), lastseenmessages); ++ SignableCommand.a signablecommand_a = (SignableCommand.a) iterator.next(); ++ MessageSignature messagesignature = packet.argumentSignatures().get(signablecommand_a.name()); ++ SignedMessageBody signedmessagebody = new SignedMessageBody(signablecommand_a.value(), packet.timeStamp(), packet.salt(), lastSeenMessages); + +- map.put(signablecommand_argument.name(), this.signedMessageDecoder.unpack(messagesignature, signedmessagebody)); ++ map.put(signablecommand_a.name(), this.signedMessageDecoder.unpack(messagesignature, signedmessagebody)); + } + + return map; + } + +- private ParseResults parseCommand(String s) { +- CommandDispatcher commanddispatcher = this.server.getCommands().getDispatcher(); ++ private ParseResults parseCommand(String command) { ++ com.mojang.brigadier.CommandDispatcher com_mojang_brigadier_commanddispatcher = this.server.getCommands().getDispatcher(); + +- return commanddispatcher.parse(s, this.player.createCommandSourceStack()); ++ return com_mojang_brigadier_commanddispatcher.parse(command, this.player.createCommandSourceStack()); + } + +- private Optional tryHandleChat(LastSeenMessages.Update lastseenmessages_update) { +- Optional optional = this.unpackAndApplyLastSeen(lastseenmessages_update); ++ private Optional tryHandleChat(LastSeenMessages.Update lastseenmessages_b) { ++ Optional optional = this.unpackAndApplyLastSeen(lastseenmessages_b); + +- if (this.player.getChatVisibility() == ChatVisiblity.HIDDEN) { ++ if (this.player.isRemoved() || this.player.getChatVisibility() == ChatVisiblity.HIDDEN) { // CraftBukkit - dead men tell no tales + this.send(new ClientboundSystemChatPacket(Component.translatable("chat.disabled.options").withStyle(ChatFormatting.RED), false)); + return Optional.empty(); + } else { +@@ -1419,11 +1857,11 @@ + } + } + +- private Optional unpackAndApplyLastSeen(LastSeenMessages.Update lastseenmessages_update) { ++ private Optional unpackAndApplyLastSeen(LastSeenMessages.Update update) { + LastSeenMessagesValidator lastseenmessagesvalidator = this.lastSeenMessages; + + synchronized (this.lastSeenMessages) { +- Optional optional = this.lastSeenMessages.applyUpdate(lastseenmessages_update); ++ Optional optional = this.lastSeenMessages.applyUpdate(update); + + if (optional.isEmpty()) { + ServerGamePacketListenerImpl.LOGGER.warn("Failed to validate message acknowledgements from {}", this.player.getName().getString()); +@@ -1434,9 +1872,9 @@ + } + } + +- private static boolean isChatMessageIllegal(String s) { +- for (int i = 0; i < s.length(); ++i) { +- if (!SharedConstants.isAllowedChatCharacter(s.charAt(i))) { ++ private static boolean isChatMessageIllegal(String message) { ++ for (int i = 0; i < message.length(); ++i) { ++ if (!SharedConstants.isAllowedChatCharacter(message.charAt(i))) { + return true; + } + } +@@ -1444,32 +1882,161 @@ + return false; + } + +- private PlayerChatMessage getSignedMessage(ServerboundChatPacket serverboundchatpacket, LastSeenMessages lastseenmessages) throws SignedMessageChain.DecodeException { +- SignedMessageBody signedmessagebody = new SignedMessageBody(serverboundchatpacket.message(), serverboundchatpacket.timeStamp(), serverboundchatpacket.salt(), lastseenmessages); ++ // CraftBukkit start - add method ++ public void chat(String s, PlayerChatMessage original, boolean async) { ++ if (s.isEmpty() || this.player.getChatVisibility() == ChatVisiblity.HIDDEN) { ++ return; ++ } ++ OutgoingChatMessage outgoing = OutgoingChatMessage.create(original); + +- return this.signedMessageDecoder.unpack(serverboundchatpacket.signature(), signedmessagebody); ++ if (!async && s.startsWith("/")) { ++ this.handleCommand(s); ++ } else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { ++ // Do nothing, this is coming from a plugin ++ } else { ++ Player player = this.getCraftPlayer(); ++ AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(server)); ++ String originalFormat = event.getFormat(), originalMessage = event.getMessage(); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (PlayerChatEvent.getHandlerList().getRegisteredListeners().length != 0) { ++ // Evil plugins still listening to deprecated event ++ final PlayerChatEvent queueEvent = new PlayerChatEvent(player, event.getMessage(), event.getFormat(), event.getRecipients()); ++ queueEvent.setCancelled(event.isCancelled()); ++ Waitable waitable = new Waitable() { ++ @Override ++ protected Object evaluate() { ++ org.bukkit.Bukkit.getPluginManager().callEvent(queueEvent); ++ ++ if (queueEvent.isCancelled()) { ++ return null; ++ } ++ ++ String message = String.format(queueEvent.getFormat(), queueEvent.getPlayer().getDisplayName(), queueEvent.getMessage()); ++ if (((LazyPlayerSet) queueEvent.getRecipients()).isLazy()) { ++ if (originalFormat.equals(queueEvent.getFormat()) && originalMessage.equals(queueEvent.getMessage()) && queueEvent.getPlayer().getName().equalsIgnoreCase(queueEvent.getPlayer().getDisplayName())) { ++ ServerGamePacketListenerImpl.this.server.getPlayerList().broadcastChatMessage(original, ServerGamePacketListenerImpl.this.player, ChatType.bind(ChatType.CHAT, (Entity) ServerGamePacketListenerImpl.this.player)); ++ return null; ++ } ++ ++ for (ServerPlayer recipient : server.getPlayerList().players) { ++ recipient.getBukkitEntity().sendMessage(ServerGamePacketListenerImpl.this.player.getUUID(), message); ++ } ++ } else { ++ for (Player player : queueEvent.getRecipients()) { ++ player.sendMessage(ServerGamePacketListenerImpl.this.player.getUUID(), message); ++ } ++ } ++ ServerGamePacketListenerImpl.this.server.console.sendMessage(message); ++ ++ return null; ++ }}; ++ if (async) { ++ server.processQueue.add(waitable); ++ } else { ++ waitable.run(); ++ } ++ try { ++ waitable.get(); ++ } catch (InterruptedException e) { ++ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on! ++ } catch (ExecutionException e) { ++ throw new RuntimeException("Exception processing chat event", e.getCause()); ++ } ++ } else { ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ s = String.format(event.getFormat(), event.getPlayer().getDisplayName(), event.getMessage()); ++ if (((LazyPlayerSet) event.getRecipients()).isLazy()) { ++ if (originalFormat.equals(event.getFormat()) && originalMessage.equals(event.getMessage()) && event.getPlayer().getName().equalsIgnoreCase(event.getPlayer().getDisplayName())) { ++ ServerGamePacketListenerImpl.this.server.getPlayerList().broadcastChatMessage(original, ServerGamePacketListenerImpl.this.player, ChatType.bind(ChatType.CHAT, (Entity) ServerGamePacketListenerImpl.this.player)); ++ return; ++ } ++ ++ for (ServerPlayer recipient : server.getPlayerList().players) { ++ recipient.getBukkitEntity().sendMessage(ServerGamePacketListenerImpl.this.player.getUUID(), s); ++ } ++ } else { ++ for (Player recipient : event.getRecipients()) { ++ recipient.sendMessage(ServerGamePacketListenerImpl.this.player.getUUID(), s); ++ } ++ } ++ server.console.sendMessage(s); ++ } ++ } + } + +- private void broadcastChatMessage(PlayerChatMessage playerchatmessage) { +- this.server.getPlayerList().broadcastChatMessage(playerchatmessage, this.player, ChatType.bind(ChatType.CHAT, (Entity) this.player)); ++ private void handleCommand(String s) { ++ this.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + s); ++ ++ CraftPlayer player = this.getCraftPlayer(); ++ ++ PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(player, s, new LazyPlayerSet(server)); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ try { ++ if (this.cserver.dispatchCommand(event.getPlayer(), event.getMessage().substring(1))) { ++ return; ++ } ++ } catch (org.bukkit.command.CommandException ex) { ++ player.sendMessage(org.bukkit.ChatColor.RED + "An internal error occurred while attempting to perform this command"); ++ java.util.logging.Logger.getLogger(ServerGamePacketListenerImpl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); ++ return; ++ } ++ } ++ // CraftBukkit end ++ ++ private PlayerChatMessage getSignedMessage(ServerboundChatPacket packet, LastSeenMessages lastSeenMessages) throws SignedMessageChain.DecodeException { ++ SignedMessageBody signedmessagebody = new SignedMessageBody(packet.message(), packet.timeStamp(), packet.salt(), lastSeenMessages); ++ ++ return this.signedMessageDecoder.unpack(packet.signature(), signedmessagebody); ++ } ++ ++ private void broadcastChatMessage(PlayerChatMessage message) { ++ // CraftBukkit start ++ String s = message.signedContent(); ++ if (s.isEmpty()) { ++ LOGGER.warn(this.player.getScoreboardName() + " tried to send an empty message"); ++ } else if (getCraftPlayer().isConversing()) { ++ final String conversationInput = s; ++ this.server.processQueue.add(new Runnable() { ++ @Override ++ public void run() { ++ getCraftPlayer().acceptConversationInput(conversationInput); ++ } ++ }); ++ } else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { // Re-add "Command Only" flag check ++ this.send(new ClientboundSystemChatPacket(Component.translatable("chat.cannotSend").withStyle(ChatFormatting.RED), false)); ++ } else { ++ this.chat(s, message, true); ++ } ++ // this.server.getPlayerList().broadcastChatMessage(playerchatmessage, this.player, ChatMessageType.bind(ChatMessageType.CHAT, (Entity) this.player)); ++ // CraftBukkit end + this.detectRateSpam(); + } + + private void detectRateSpam() { +- this.chatSpamTickCount += 20; +- if (this.chatSpamTickCount > 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { ++ // CraftBukkit start - replaced with thread safe throttle ++ // this.chatSpamTickCount += 20; ++ if (this.chatSpamTickCount.addAndGet(20) > 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { ++ // CraftBukkit end + this.disconnect(Component.translatable("disconnect.spam")); + } + + } + + @Override +- @Override +- public void handleChatAck(ServerboundChatAckPacket serverboundchatackpacket) { ++ public void handleChatAck(ServerboundChatAckPacket packet) { + LastSeenMessagesValidator lastseenmessagesvalidator = this.lastSeenMessages; + + synchronized (this.lastSeenMessages) { +- if (!this.lastSeenMessages.applyOffset(serverboundchatackpacket.offset())) { ++ if (!this.lastSeenMessages.applyOffset(packet.offset())) { + ServerGamePacketListenerImpl.LOGGER.warn("Failed to validate message acknowledgements from {}", this.player.getName().getString()); + this.disconnect(ServerGamePacketListenerImpl.CHAT_VALIDATION_FAILED); + } +@@ -1478,22 +2045,69 @@ + } + + @Override +- @Override +- public void handleAnimate(ServerboundSwingPacket serverboundswingpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundswingpacket, this, this.player.serverLevel()); ++ public void handleAnimate(ServerboundSwingPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.resetLastActionTime(); +- this.player.swing(serverboundswingpacket.getHand()); ++ // CraftBukkit start - Raytrace to look for 'rogue armswings' ++ float f1 = this.player.getXRot(); ++ float f2 = this.player.getYRot(); ++ double d0 = this.player.getX(); ++ double d1 = this.player.getY() + (double) this.player.getEyeHeight(); ++ double d2 = this.player.getZ(); ++ Location origin = new Location(this.player.level().getWorld(), d0, d1, d2, f2, f1); ++ ++ double d3 = player.gameMode.getGameModeForPlayer() == GameType.CREATIVE ? 5.0D : 4.5D; ++ // SPIGOT-5607: Only call interact event if no block or entity is being clicked. Use bukkit ray trace method, because it handles blocks and entities at the same time ++ // SPIGOT-7429: Make sure to call PlayerInteractEvent for spectators and non-pickable entities ++ org.bukkit.util.RayTraceResult result = this.player.level().getWorld().rayTrace(origin, origin.getDirection(), d3, org.bukkit.FluidCollisionMode.NEVER, false, 0.1, entity -> { ++ Entity handle = ((CraftEntity) entity).getHandle(); ++ return entity != this.player.getBukkitEntity() && this.player.getBukkitEntity().canSee(entity) && !handle.isSpectator() && handle.isPickable() && !handle.isPassengerOfSameVehicle(player); ++ }); ++ if (result == null) { ++ CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_AIR, this.player.getInventory().getSelected(), EnumHand.MAIN_HAND); ++ } ++ ++ // Arm swing animation ++ PlayerAnimationEvent event = new PlayerAnimationEvent(this.getCraftPlayer(), (packet.getHand() == EnumHand.MAIN_HAND) ? PlayerAnimationType.ARM_SWING : PlayerAnimationType.OFF_ARM_SWING); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) return; ++ // CraftBukkit end ++ this.player.swing(packet.getHand()); + } + + @Override +- @Override +- public void handlePlayerCommand(ServerboundPlayerCommandPacket serverboundplayercommandpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundplayercommandpacket, this, this.player.serverLevel()); ++ public void handlePlayerCommand(ServerboundPlayerCommandPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ // CraftBukkit start ++ if (this.player.isRemoved()) return; ++ switch (packet.getAction()) { ++ case PRESS_SHIFT_KEY: ++ case RELEASE_SHIFT_KEY: ++ PlayerToggleSneakEvent event = new PlayerToggleSneakEvent(this.getCraftPlayer(), packet.getAction() == ServerboundPlayerCommandPacket.EnumPlayerAction.PRESS_SHIFT_KEY); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ break; ++ case START_SPRINTING: ++ case STOP_SPRINTING: ++ PlayerToggleSprintEvent e2 = new PlayerToggleSprintEvent(this.getCraftPlayer(), packet.getAction() == ServerboundPlayerCommandPacket.EnumPlayerAction.START_SPRINTING); ++ this.cserver.getPluginManager().callEvent(e2); ++ ++ if (e2.isCancelled()) { ++ return; ++ } ++ break; ++ } ++ // CraftBukkit end + this.player.resetLastActionTime(); + Entity entity; +- PlayerRideableJumping playerrideablejumping; ++ PlayerRideableJumping ijumpable; + +- switch (serverboundplayercommandpacket.getAction()) { ++ switch (packet.getAction()) { + case PRESS_SHIFT_KEY: + this.player.setShiftKeyDown(true); + break; +@@ -1515,19 +2129,19 @@ + case START_RIDING_JUMP: + entity = this.player.getControlledVehicle(); + if (entity instanceof PlayerRideableJumping) { +- playerrideablejumping = (PlayerRideableJumping) entity; +- int i = serverboundplayercommandpacket.getData(); ++ ijumpable = (PlayerRideableJumping) entity; ++ int i = packet.getData(); + +- if (playerrideablejumping.canJump() && i > 0) { +- playerrideablejumping.handleStartJump(i); ++ if (ijumpable.canJump() && i > 0) { ++ ijumpable.handleStartJump(i); + } + } + break; + case STOP_RIDING_JUMP: + entity = this.player.getControlledVehicle(); + if (entity instanceof PlayerRideableJumping) { +- playerrideablejumping = (PlayerRideableJumping) entity; +- playerrideablejumping.handleStopJump(); ++ ijumpable = (PlayerRideableJumping) entity; ++ ijumpable.handleStopJump(); + } + break; + case OPEN_INVENTORY: +@@ -1549,11 +2163,11 @@ + + } + +- public void addPendingMessage(PlayerChatMessage playerchatmessage) { +- MessageSignature messagesignature = playerchatmessage.signature(); ++ public void addPendingMessage(PlayerChatMessage message) { ++ MessageSignature messagesignature = message.signature(); + + if (messagesignature != null) { +- this.messageSignatureCache.push(playerchatmessage.signedBody(), playerchatmessage.signature()); ++ this.messageSignatureCache.push(message.signedBody(), message.signature()); + LastSeenMessagesValidator lastseenmessagesvalidator = this.lastSeenMessages; + int i; + +@@ -1569,13 +2183,19 @@ + } + } + +- public void sendPlayerChatMessage(PlayerChatMessage playerchatmessage, ChatType.Bound chattype_bound) { +- this.send(new ClientboundPlayerChatPacket(playerchatmessage.link().sender(), playerchatmessage.link().index(), playerchatmessage.signature(), playerchatmessage.signedBody().pack(this.messageSignatureCache), playerchatmessage.unsignedContent(), playerchatmessage.filterMask(), chattype_bound.toNetwork(this.player.level().registryAccess()))); +- this.addPendingMessage(playerchatmessage); ++ public void sendPlayerChatMessage(PlayerChatMessage chatMessage, ChatType.Bound boundType) { ++ // CraftBukkit start - SPIGOT-7262: if hidden we have to send as disguised message. Query whether we should send at all (but changing this may not be expected). ++ if (!getCraftPlayer().canSee(chatMessage.link().sender())) { ++ sendDisguisedChatMessage(chatMessage.decoratedContent(), boundType); ++ return; ++ } ++ // CraftBukkit end ++ this.send(new ClientboundPlayerChatPacket(chatMessage.link().sender(), chatMessage.link().index(), chatMessage.signature(), chatMessage.signedBody().pack(this.messageSignatureCache), chatMessage.unsignedContent(), chatMessage.filterMask(), boundType.toNetwork(this.player.level().registryAccess()))); ++ this.addPendingMessage(chatMessage); + } + +- public void sendDisguisedChatMessage(Component component, ChatType.Bound chattype_bound) { +- this.send(new ClientboundDisguisedChatPacket(component, chattype_bound.toNetwork(this.player.level().registryAccess()))); ++ public void sendDisguisedChatMessage(Component message, ChatType.Bound boundType) { ++ this.send(new ClientboundDisguisedChatPacket(message, boundType.toNetwork(this.player.level().registryAccess()))); + } + + public SocketAddress getRemoteAddress() { +@@ -1589,40 +2209,77 @@ + } + + @Override +- @Override +- public void handlePingRequest(ServerboundPingRequestPacket serverboundpingrequestpacket) { +- this.connection.send(new ClientboundPongResponsePacket(serverboundpingrequestpacket.getTime())); ++ public void handlePingRequest(ServerboundPingRequestPacket packetstatusinping) { ++ this.connection.send(new ClientboundPongResponsePacket(packetstatusinping.getTime())); + } + + @Override +- @Override +- public void handleInteract(ServerboundInteractPacket serverboundinteractpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundinteractpacket, this, this.player.serverLevel()); +- final ServerLevel serverlevel = this.player.serverLevel(); +- final Entity entity = serverboundinteractpacket.getTarget(serverlevel); ++ public void handleInteract(ServerboundInteractPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit ++ final ServerLevel worldserver = this.player.serverLevel(); ++ final Entity entity = packet.getTarget(worldserver); + + this.player.resetLastActionTime(); +- this.player.setShiftKeyDown(serverboundinteractpacket.isUsingSecondaryAction()); ++ this.player.setShiftKeyDown(packet.isUsingSecondaryAction()); + if (entity != null) { +- if (!serverlevel.getWorldBorder().isWithinBounds(entity.blockPosition())) { ++ if (!worldserver.getWorldBorder().isWithinBounds(entity.blockPosition())) { + return; + } + +- AABB aabb = entity.getBoundingBox(); ++ AABB axisalignedbb = entity.getBoundingBox(); + +- if (aabb.distanceToSqr(this.player.getEyePosition()) < ServerGamePacketListenerImpl.MAX_INTERACTION_DISTANCE) { +- serverboundinteractpacket.dispatch(new ServerboundInteractPacket.Handler() { +- private void performInteraction(InteractionHand interactionhand, ServerGamePacketListenerImpl.EntityInteraction servergamepacketlistenerimpl_entityinteraction) { +- ItemStack itemstack = ServerGamePacketListenerImpl.this.player.getItemInHand(interactionhand); ++ if (axisalignedbb.distanceToSqr(this.player.getEyePosition()) < ServerGamePacketListenerImpl.MAX_INTERACTION_DISTANCE) { ++ packet.dispatch(new ServerboundInteractPacket.Handler() { ++ private void performInteraction(EnumHand enumhand, ServerGamePacketListenerImpl.EntityInteraction playerconnection_a, PlayerInteractEntityEvent event) { // CraftBukkit ++ ItemStack itemstack = ServerGamePacketListenerImpl.this.player.getItemInHand(enumhand); + +- if (itemstack.isItemEnabled(serverlevel.enabledFeatures())) { ++ if (itemstack.isItemEnabled(worldserver.enabledFeatures())) { + ItemStack itemstack1 = itemstack.copy(); +- InteractionResult interactionresult = servergamepacketlistenerimpl_entityinteraction.run(ServerGamePacketListenerImpl.this.player, entity, interactionhand); ++ // CraftBukkit start ++ ItemStack itemInHand = ServerGamePacketListenerImpl.this.player.getItemInHand(enumhand); ++ boolean triggerLeashUpdate = itemInHand != null && itemInHand.getItem() == Items.LEAD && entity instanceof Mob; ++ Item origItem = player.getInventory().getSelected() == null ? null : player.getInventory().getSelected().getItem(); + +- if (interactionresult.consumesAction()) { ++ cserver.getPluginManager().callEvent(event); ++ ++ // Entity in bucket - SPIGOT-4048 and SPIGOT-6859a ++ if ((entity instanceof Bucketable && entity instanceof LivingEntity && origItem != null && origItem.asItem() == Items.WATER_BUCKET) && (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem)) { ++ send(new ClientboundAddEntityPacket(entity)); ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ ++ if (triggerLeashUpdate && (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem)) { ++ // Refresh the current leash state ++ send(new ClientboundSetEntityLinkPacket(entity, ((Mob) entity).getLeashHolder())); ++ } ++ ++ if (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem) { ++ // Refresh the current entity metadata ++ entity.getEntityData().refresh(player); ++ // SPIGOT-7136 - Allays ++ if (entity instanceof Allay) { ++ send(new ClientboundSetEquipmentPacket(entity.getId(), Arrays.stream(net.minecraft.world.entity.EquipmentSlot.values()).map((slot) -> Pair.of(slot, ((LivingEntity) entity).getItemBySlot(slot).copy())).collect(Collectors.toList()))); ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ } ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ InteractionResult enuminteractionresult = playerconnection_a.run(ServerGamePacketListenerImpl.this.player, entity, enumhand); ++ ++ // CraftBukkit start ++ if (!itemInHand.isEmpty() && itemInHand.getCount() <= -1) { ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ // CraftBukkit end ++ ++ if (enuminteractionresult.consumesAction()) { + CriteriaTriggers.PLAYER_INTERACTED_WITH_ENTITY.trigger(ServerGamePacketListenerImpl.this.player, itemstack1, entity); +- if (interactionresult.shouldSwing()) { +- ServerGamePacketListenerImpl.this.player.swing(interactionhand, true); ++ if (enuminteractionresult.shouldSwing()) { ++ ServerGamePacketListenerImpl.this.player.swing(enumhand, true); + } + } + +@@ -1630,27 +2287,30 @@ + } + + @Override +- @Override +- public void onInteraction(InteractionHand interactionhand) { +- this.performInteraction(interactionhand, Player::interactOn); ++ public void onInteraction(EnumHand hand) { ++ this.performInteraction(hand, net.minecraft.world.entity.player.Player::interactOn, new PlayerInteractEntityEvent(getCraftPlayer(), entity.getBukkitEntity(), (hand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); // CraftBukkit + } + + @Override +- @Override +- public void onInteraction(InteractionHand interactionhand, Vec3 vec3) { +- this.performInteraction(interactionhand, (serverplayer, entity1, interactionhand1) -> { +- return entity1.interactAt(serverplayer, vec3, interactionhand1); +- }); ++ public void onInteraction(EnumHand hand, Vec3 interactionLocation) { ++ this.performInteraction(hand, (entityplayer, entity1, enumhand1) -> { ++ return entity1.interactAt(entityplayer, interactionLocation, enumhand1); ++ }, new PlayerInteractAtEntityEvent(getCraftPlayer(), entity.getBukkitEntity(), new org.bukkit.util.Vector(interactionLocation.x, interactionLocation.y, interactionLocation.z), (hand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); // CraftBukkit + } + + @Override +- @Override + public void onAttack() { +- if (!(entity instanceof ItemEntity) && !(entity instanceof ExperienceOrb) && !(entity instanceof AbstractArrow) && entity != ServerGamePacketListenerImpl.this.player) { +- ItemStack itemstack = ServerGamePacketListenerImpl.this.player.getItemInHand(InteractionHand.MAIN_HAND); ++ // CraftBukkit ++ if (!(entity instanceof ItemEntity) && !(entity instanceof ExperienceOrb) && !(entity instanceof AbstractArrow) && (entity != ServerGamePacketListenerImpl.this.player || player.isSpectator())) { ++ ItemStack itemstack = ServerGamePacketListenerImpl.this.player.getItemInHand(EnumHand.MAIN_HAND); + +- if (itemstack.isItemEnabled(serverlevel.enabledFeatures())) { ++ if (itemstack.isItemEnabled(worldserver.enabledFeatures())) { + ServerGamePacketListenerImpl.this.player.attack(entity); ++ // CraftBukkit start ++ if (!itemstack.isEmpty() && itemstack.getCount() <= -1) { ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ // CraftBukkit end + } + } else { + ServerGamePacketListenerImpl.this.disconnect(Component.translatable("multiplayer.disconnect.invalid_entity_attacked")); +@@ -1664,24 +2324,23 @@ + } + + @Override +- @Override +- public void handleClientCommand(ServerboundClientCommandPacket serverboundclientcommandpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundclientcommandpacket, this, this.player.serverLevel()); ++ public void handleClientCommand(ServerboundClientCommandPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + this.player.resetLastActionTime(); +- ServerboundClientCommandPacket.Action serverboundclientcommandpacket_action = serverboundclientcommandpacket.getAction(); ++ ServerboundClientCommandPacket.EnumClientCommand packetplayinclientcommand_enumclientcommand = packet.getAction(); + +- switch (serverboundclientcommandpacket_action) { ++ switch (packetplayinclientcommand_enumclientcommand) { + case PERFORM_RESPAWN: + if (this.player.wonGame) { + this.player.wonGame = false; +- this.player = this.server.getPlayerList().respawn(this.player, true); ++ this.player = this.server.getPlayerList().respawn(this.player, true, RespawnReason.END_PORTAL); + CriteriaTriggers.CHANGED_DIMENSION.trigger(this.player, Level.END, Level.OVERWORLD); + } else { + if (this.player.getHealth() > 0.0F) { + return; + } + +- this.player = this.server.getPlayerList().respawn(this.player, false); ++ this.player = this.server.getPlayerList().respawn(this.player, false, RespawnReason.DEATH); + if (this.server.isHardcore()) { + this.player.setGameMode(GameType.SPECTATOR); + ((GameRules.BooleanValue) this.player.level().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS)).set(false, this.server); +@@ -1695,41 +2354,322 @@ + } + + @Override +- @Override +- public void handleContainerClose(ServerboundContainerClosePacket serverboundcontainerclosepacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundcontainerclosepacket, this, this.player.serverLevel()); ++ public void handleContainerClose(ServerboundContainerClosePacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ ++ if (this.player.isImmobile()) return; // CraftBukkit ++ CraftEventFactory.handleInventoryCloseEvent(this.player); // CraftBukkit ++ + this.player.doCloseContainer(); + } + + @Override +- @Override +- public void handleContainerClick(ServerboundContainerClickPacket serverboundcontainerclickpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundcontainerclickpacket, this, this.player.serverLevel()); ++ public void handleContainerClick(ServerboundContainerClickPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.resetLastActionTime(); +- if (this.player.containerMenu.containerId == serverboundcontainerclickpacket.getContainerId()) { +- if (this.player.isSpectator()) { ++ if (this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu.stillValid(this.player)) { // CraftBukkit ++ boolean cancelled = this.player.isSpectator(); // CraftBukkit - see below if ++ if (false/*this.player.isSpectator()*/) { // CraftBukkit + this.player.containerMenu.sendAllDataToRemote(); + } else if (!this.player.containerMenu.stillValid(this.player)) { + ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu); + } else { +- int i = serverboundcontainerclickpacket.getSlotNum(); ++ int i = packet.getSlotNum(); + + if (!this.player.containerMenu.isValidSlotIndex(i)) { + ServerGamePacketListenerImpl.LOGGER.debug("Player {} clicked invalid slot index: {}, available slots: {}", new Object[]{this.player.getName(), i, this.player.containerMenu.slots.size()}); + } else { +- boolean flag = serverboundcontainerclickpacket.getStateId() != this.player.containerMenu.getStateId(); ++ boolean flag = packet.getStateId() != this.player.containerMenu.getStateId(); + + this.player.containerMenu.suppressRemoteUpdates(); +- this.player.containerMenu.clicked(i, serverboundcontainerclickpacket.getButtonNum(), serverboundcontainerclickpacket.getClickType(), this.player); +- ObjectIterator objectiterator = Int2ObjectMaps.fastIterable(serverboundcontainerclickpacket.getChangedSlots()).iterator(); ++ // CraftBukkit start - Call InventoryClickEvent ++ if (packet.getSlotNum() < -1 && packet.getSlotNum() != -999) { ++ return; ++ } + ++ InventoryView inventory = this.player.containerMenu.getBukkitView(); ++ SlotType type = inventory.getSlotType(packet.getSlotNum()); ++ ++ InventoryClickEvent event; ++ ClickType click = ClickType.UNKNOWN; ++ InventoryAction action = InventoryAction.UNKNOWN; ++ ++ ItemStack itemstack = ItemStack.EMPTY; ++ ++ switch (packet.getClickType()) { ++ case PICKUP: ++ if (packet.getButtonNum() == 0) { ++ click = ClickType.LEFT; ++ } else if (packet.getButtonNum() == 1) { ++ click = ClickType.RIGHT; ++ } ++ if (packet.getButtonNum() == 0 || packet.getButtonNum() == 1) { ++ action = InventoryAction.NOTHING; // Don't want to repeat ourselves ++ if (packet.getSlotNum() == -999) { ++ if (!player.containerMenu.getCarried().isEmpty()) { ++ action = packet.getButtonNum() == 0 ? InventoryAction.DROP_ALL_CURSOR : InventoryAction.DROP_ONE_CURSOR; ++ } ++ } else if (packet.getSlotNum() < 0) { ++ action = InventoryAction.NOTHING; ++ } else { ++ Slot slot = this.player.containerMenu.getSlot(packet.getSlotNum()); ++ if (slot != null) { ++ ItemStack clickedItem = slot.getItem(); ++ ItemStack cursor = player.containerMenu.getCarried(); ++ if (clickedItem.isEmpty()) { ++ if (!cursor.isEmpty()) { ++ action = packet.getButtonNum() == 0 ? InventoryAction.PLACE_ALL : InventoryAction.PLACE_ONE; ++ } ++ } else if (slot.mayPickup(player)) { ++ if (cursor.isEmpty()) { ++ action = packet.getButtonNum() == 0 ? InventoryAction.PICKUP_ALL : InventoryAction.PICKUP_HALF; ++ } else if (slot.mayPlace(cursor)) { ++ if (ItemStack.isSameItemSameTags(clickedItem, cursor)) { ++ int toPlace = packet.getButtonNum() == 0 ? cursor.getCount() : 1; ++ toPlace = Math.min(toPlace, clickedItem.getMaxStackSize() - clickedItem.getCount()); ++ toPlace = Math.min(toPlace, slot.container.getMaxStackSize() - clickedItem.getCount()); ++ if (toPlace == 1) { ++ action = InventoryAction.PLACE_ONE; ++ } else if (toPlace == cursor.getCount()) { ++ action = InventoryAction.PLACE_ALL; ++ } else if (toPlace < 0) { ++ action = toPlace != -1 ? InventoryAction.PICKUP_SOME : InventoryAction.PICKUP_ONE; // this happens with oversized stacks ++ } else if (toPlace != 0) { ++ action = InventoryAction.PLACE_SOME; ++ } ++ } else if (cursor.getCount() <= slot.getMaxStackSize()) { ++ action = InventoryAction.SWAP_WITH_CURSOR; ++ } ++ } else if (ItemStack.isSameItemSameTags(cursor, clickedItem)) { ++ if (clickedItem.getCount() >= 0) { ++ if (clickedItem.getCount() + cursor.getCount() <= cursor.getMaxStackSize()) { ++ // As of 1.5, this is result slots only ++ action = InventoryAction.PICKUP_ALL; ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ break; ++ // TODO check on updates ++ case QUICK_MOVE: ++ if (packet.getButtonNum() == 0) { ++ click = ClickType.SHIFT_LEFT; ++ } else if (packet.getButtonNum() == 1) { ++ click = ClickType.SHIFT_RIGHT; ++ } ++ if (packet.getButtonNum() == 0 || packet.getButtonNum() == 1) { ++ if (packet.getSlotNum() < 0) { ++ action = InventoryAction.NOTHING; ++ } else { ++ Slot slot = this.player.containerMenu.getSlot(packet.getSlotNum()); ++ if (slot != null && slot.mayPickup(this.player) && slot.hasItem()) { ++ action = InventoryAction.MOVE_TO_OTHER_INVENTORY; ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } ++ } ++ break; ++ case SWAP: ++ if ((packet.getButtonNum() >= 0 && packet.getButtonNum() < 9) || packet.getButtonNum() == 40) { ++ click = (packet.getButtonNum() == 40) ? ClickType.SWAP_OFFHAND : ClickType.NUMBER_KEY; ++ Slot clickedSlot = this.player.containerMenu.getSlot(packet.getSlotNum()); ++ if (clickedSlot.mayPickup(player)) { ++ ItemStack hotbar = this.player.getInventory().getItem(packet.getButtonNum()); ++ boolean canCleanSwap = hotbar.isEmpty() || (clickedSlot.container == player.getInventory() && clickedSlot.mayPlace(hotbar)); // the slot will accept the hotbar item ++ if (clickedSlot.hasItem()) { ++ if (canCleanSwap) { ++ action = InventoryAction.HOTBAR_SWAP; ++ } else { ++ action = InventoryAction.HOTBAR_MOVE_AND_READD; ++ } ++ } else if (!clickedSlot.hasItem() && !hotbar.isEmpty() && clickedSlot.mayPlace(hotbar)) { ++ action = InventoryAction.HOTBAR_SWAP; ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } ++ break; ++ case CLONE: ++ if (packet.getButtonNum() == 2) { ++ click = ClickType.MIDDLE; ++ if (packet.getSlotNum() < 0) { ++ action = InventoryAction.NOTHING; ++ } else { ++ Slot slot = this.player.containerMenu.getSlot(packet.getSlotNum()); ++ if (slot != null && slot.hasItem() && player.getAbilities().instabuild && player.containerMenu.getCarried().isEmpty()) { ++ action = InventoryAction.CLONE_STACK; ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } ++ } else { ++ click = ClickType.UNKNOWN; ++ action = InventoryAction.UNKNOWN; ++ } ++ break; ++ case THROW: ++ if (packet.getSlotNum() >= 0) { ++ if (packet.getButtonNum() == 0) { ++ click = ClickType.DROP; ++ Slot slot = this.player.containerMenu.getSlot(packet.getSlotNum()); ++ if (slot != null && slot.hasItem() && slot.mayPickup(player) && !slot.getItem().isEmpty() && slot.getItem().getItem() != Item.byBlock(Blocks.AIR)) { ++ action = InventoryAction.DROP_ONE_SLOT; ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } else if (packet.getButtonNum() == 1) { ++ click = ClickType.CONTROL_DROP; ++ Slot slot = this.player.containerMenu.getSlot(packet.getSlotNum()); ++ if (slot != null && slot.hasItem() && slot.mayPickup(player) && !slot.getItem().isEmpty() && slot.getItem().getItem() != Item.byBlock(Blocks.AIR)) { ++ action = InventoryAction.DROP_ALL_SLOT; ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } ++ } else { ++ // Sane default (because this happens when they are holding nothing. Don't ask why.) ++ click = ClickType.LEFT; ++ if (packet.getButtonNum() == 1) { ++ click = ClickType.RIGHT; ++ } ++ action = InventoryAction.NOTHING; ++ } ++ break; ++ case QUICK_CRAFT: ++ this.player.containerMenu.clicked(packet.getSlotNum(), packet.getButtonNum(), packet.getClickType(), this.player); ++ break; ++ case PICKUP_ALL: ++ click = ClickType.DOUBLE_CLICK; ++ action = InventoryAction.NOTHING; ++ if (packet.getSlotNum() >= 0 && !this.player.containerMenu.getCarried().isEmpty()) { ++ ItemStack cursor = this.player.containerMenu.getCarried(); ++ action = InventoryAction.NOTHING; ++ // Quick check for if we have any of the item ++ if (inventory.getTopInventory().contains(CraftMagicNumbers.getMaterial(cursor.getItem())) || inventory.getBottomInventory().contains(CraftMagicNumbers.getMaterial(cursor.getItem()))) { ++ action = InventoryAction.COLLECT_TO_CURSOR; ++ } ++ } ++ break; ++ default: ++ break; ++ } ++ ++ if (packet.getClickType() != InventoryClickType.QUICK_CRAFT) { ++ if (click == ClickType.NUMBER_KEY) { ++ event = new InventoryClickEvent(inventory, type, packet.getSlotNum(), click, action, packet.getButtonNum()); ++ } else { ++ event = new InventoryClickEvent(inventory, type, packet.getSlotNum(), click, action); ++ } ++ ++ org.bukkit.inventory.Inventory top = inventory.getTopInventory(); ++ if (packet.getSlotNum() == 0 && top instanceof CraftingInventory) { ++ org.bukkit.inventory.Recipe recipe = ((CraftingInventory) top).getRecipe(); ++ if (recipe != null) { ++ if (click == ClickType.NUMBER_KEY) { ++ event = new CraftItemEvent(recipe, inventory, type, packet.getSlotNum(), click, action, packet.getButtonNum()); ++ } else { ++ event = new CraftItemEvent(recipe, inventory, type, packet.getSlotNum(), click, action); ++ } ++ } ++ } ++ ++ if (packet.getSlotNum() == 3 && top instanceof SmithingInventory) { ++ org.bukkit.inventory.ItemStack result = ((SmithingInventory) top).getResult(); ++ if (result != null) { ++ if (click == ClickType.NUMBER_KEY) { ++ event = new SmithItemEvent(inventory, type, packet.getSlotNum(), click, action, packet.getButtonNum()); ++ } else { ++ event = new SmithItemEvent(inventory, type, packet.getSlotNum(), click, action); ++ } ++ } ++ } ++ ++ event.setCancelled(cancelled); ++ AbstractContainerMenu oldContainer = this.player.containerMenu; // SPIGOT-1224 ++ cserver.getPluginManager().callEvent(event); ++ if (this.player.containerMenu != oldContainer) { ++ return; ++ } ++ ++ switch (event.getResult()) { ++ case ALLOW: ++ case DEFAULT: ++ this.player.containerMenu.clicked(i, packet.getButtonNum(), packet.getClickType(), this.player); ++ break; ++ case DENY: ++ /* Needs enum constructor in InventoryAction ++ if (action.modifiesOtherSlots()) { ++ ++ } else { ++ if (action.modifiesCursor()) { ++ this.player.playerConnection.sendPacket(new Packet103SetSlot(-1, -1, this.player.inventory.getCarried())); ++ } ++ if (action.modifiesClicked()) { ++ this.player.playerConnection.sendPacket(new Packet103SetSlot(this.player.activeContainer.windowId, packet102windowclick.slot, this.player.activeContainer.getSlot(packet102windowclick.slot).getItem())); ++ } ++ }*/ ++ switch (action) { ++ // Modified other slots ++ case PICKUP_ALL: ++ case MOVE_TO_OTHER_INVENTORY: ++ case HOTBAR_MOVE_AND_READD: ++ case HOTBAR_SWAP: ++ case COLLECT_TO_CURSOR: ++ case UNKNOWN: ++ this.player.containerMenu.sendAllDataToRemote(); ++ break; ++ // Modified cursor and clicked ++ case PICKUP_SOME: ++ case PICKUP_HALF: ++ case PICKUP_ONE: ++ case PLACE_ALL: ++ case PLACE_SOME: ++ case PLACE_ONE: ++ case SWAP_WITH_CURSOR: ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(-1, -1, this.player.inventoryMenu.incrementStateId(), this.player.containerMenu.getCarried())); ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(this.player.containerMenu.containerId, this.player.inventoryMenu.incrementStateId(), packet.getSlotNum(), this.player.containerMenu.getSlot(packet.getSlotNum()).getItem())); ++ break; ++ // Modified clicked only ++ case DROP_ALL_SLOT: ++ case DROP_ONE_SLOT: ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(this.player.containerMenu.containerId, this.player.inventoryMenu.incrementStateId(), packet.getSlotNum(), this.player.containerMenu.getSlot(packet.getSlotNum()).getItem())); ++ break; ++ // Modified cursor only ++ case DROP_ALL_CURSOR: ++ case DROP_ONE_CURSOR: ++ case CLONE_STACK: ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(-1, -1, this.player.inventoryMenu.incrementStateId(), this.player.containerMenu.getCarried())); ++ break; ++ // Nothing ++ case NOTHING: ++ break; ++ } ++ } ++ ++ if (event instanceof CraftItemEvent || event instanceof SmithItemEvent) { ++ // Need to update the inventory on crafting to ++ // correctly support custom recipes ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ } ++ // CraftBukkit end ++ ObjectIterator objectiterator = Int2ObjectMaps.fastIterable(packet.getChangedSlots()).iterator(); ++ + while (objectiterator.hasNext()) { + Entry entry = (Entry) objectiterator.next(); + + this.player.containerMenu.setRemoteSlotNoCopy(entry.getIntKey(), (ItemStack) entry.getValue()); + } + +- this.player.containerMenu.setRemoteCarried(serverboundcontainerclickpacket.getCarriedItem()); ++ this.player.containerMenu.setRemoteCarried(packet.getCarriedItem()); + this.player.containerMenu.resumeRemoteUpdates(); + if (flag) { + this.player.containerMenu.broadcastFullState(); +@@ -1743,31 +2683,39 @@ + } + + @Override +- @Override +- public void handlePlaceRecipe(ServerboundPlaceRecipePacket serverboundplacerecipepacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundplacerecipepacket, this, this.player.serverLevel()); ++ public void handlePlaceRecipe(ServerboundPlaceRecipePacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + this.player.resetLastActionTime(); +- if (!this.player.isSpectator() && this.player.containerMenu.containerId == serverboundplacerecipepacket.getContainerId() && this.player.containerMenu instanceof RecipeBookMenu) { ++ if (!this.player.isSpectator() && this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu instanceof RecipeBookMenu) { + if (!this.player.containerMenu.stillValid(this.player)) { + ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu); + } else { +- this.server.getRecipeManager().byKey(serverboundplacerecipepacket.getRecipe()).ifPresent((recipeholder) -> { +- ((RecipeBookMenu) this.player.containerMenu).handlePlacement(serverboundplacerecipepacket.isShiftDown(), recipeholder, this.player); ++ // CraftBukkit start - implement PlayerRecipeBookClickEvent ++ org.bukkit.inventory.Recipe recipe = this.cserver.getRecipe(CraftNamespacedKey.fromMinecraft(packet.getRecipe())); ++ if (recipe == null) { ++ return; ++ } ++ org.bukkit.event.player.PlayerRecipeBookClickEvent event = CraftEventFactory.callRecipeBookClickEvent(this.player, recipe, packet.isShiftDown()); ++ ++ // Cast to keyed should be safe as the recipe will never be a MerchantRecipe. ++ this.server.getRecipeManager().byKey(CraftNamespacedKey.toMinecraft(((org.bukkit.Keyed) event.getRecipe()).getKey())).ifPresent((recipeholder) -> { ++ ((RecipeBookMenu) this.player.containerMenu).handlePlacement(event.isShiftClick(), recipeholder, this.player); + }); ++ // CraftBukkit end + } + } + } + + @Override +- @Override +- public void handleContainerButtonClick(ServerboundContainerButtonClickPacket serverboundcontainerbuttonclickpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundcontainerbuttonclickpacket, this, this.player.serverLevel()); ++ public void handleContainerButtonClick(ServerboundContainerButtonClickPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.resetLastActionTime(); +- if (this.player.containerMenu.containerId == serverboundcontainerbuttonclickpacket.getContainerId() && !this.player.isSpectator()) { ++ if (this.player.containerMenu.containerId == packet.getContainerId() && !this.player.isSpectator()) { + if (!this.player.containerMenu.stillValid(this.player)) { + ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu); + } else { +- boolean flag = this.player.containerMenu.clickMenuButton(this.player, serverboundcontainerbuttonclickpacket.getButtonId()); ++ boolean flag = this.player.containerMenu.clickMenuButton(this.player, packet.getButtonId()); + + if (flag) { + this.player.containerMenu.broadcastChanges(); +@@ -1778,36 +2726,72 @@ + } + + @Override +- @Override +- public void handleSetCreativeModeSlot(ServerboundSetCreativeModeSlotPacket serverboundsetcreativemodeslotpacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundsetcreativemodeslotpacket, this, this.player.serverLevel()); ++ public void handleSetCreativeModeSlot(ServerboundSetCreativeModeSlotPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + if (this.player.gameMode.isCreative()) { +- boolean flag = serverboundsetcreativemodeslotpacket.getSlotNum() < 0; +- ItemStack itemstack = serverboundsetcreativemodeslotpacket.getItem(); ++ boolean flag = packet.getSlotNum() < 0; ++ ItemStack itemstack = packet.getItem(); + + if (!itemstack.isItemEnabled(this.player.level().enabledFeatures())) { + return; + } + +- CompoundTag compoundtag = BlockItem.getBlockEntityData(itemstack); ++ CompoundTag nbttagcompound = BlockItem.getBlockEntityData(itemstack); + +- if (!itemstack.isEmpty() && compoundtag != null && compoundtag.contains("x") && compoundtag.contains("y") && compoundtag.contains("z")) { +- BlockPos blockpos = BlockEntity.getPosFromTag(compoundtag); ++ if (!itemstack.isEmpty() && nbttagcompound != null && nbttagcompound.contains("x") && nbttagcompound.contains("y") && nbttagcompound.contains("z")) { ++ BlockPos blockposition = BlockEntity.getPosFromTag(nbttagcompound); + +- if (this.player.level().isLoaded(blockpos)) { +- BlockEntity blockentity = this.player.level().getBlockEntity(blockpos); ++ if (this.player.level().isLoaded(blockposition)) { ++ BlockEntity tileentity = this.player.level().getBlockEntity(blockposition); + +- if (blockentity != null) { +- blockentity.saveToItem(itemstack); ++ if (tileentity != null) { ++ tileentity.saveToItem(itemstack); + } + } + } + +- boolean flag1 = serverboundsetcreativemodeslotpacket.getSlotNum() >= 1 && serverboundsetcreativemodeslotpacket.getSlotNum() <= 45; ++ boolean flag1 = packet.getSlotNum() >= 1 && packet.getSlotNum() <= 45; + boolean flag2 = itemstack.isEmpty() || itemstack.getDamageValue() >= 0 && itemstack.getCount() <= 64 && !itemstack.isEmpty(); ++ if (flag || (flag1 && !ItemStack.matches(this.player.inventoryMenu.getSlot(packet.getSlotNum()).getItem(), packet.getItem()))) { // Insist on valid slot ++ // CraftBukkit start - Call click event ++ InventoryView inventory = this.player.inventoryMenu.getBukkitView(); ++ org.bukkit.inventory.ItemStack item = CraftItemStack.asBukkitCopy(packet.getItem()); + ++ SlotType type = SlotType.QUICKBAR; ++ if (flag) { ++ type = SlotType.OUTSIDE; ++ } else if (packet.getSlotNum() < 36) { ++ if (packet.getSlotNum() >= 5 && packet.getSlotNum() < 9) { ++ type = SlotType.ARMOR; ++ } else { ++ type = SlotType.CONTAINER; ++ } ++ } ++ InventoryCreativeEvent event = new InventoryCreativeEvent(inventory, type, flag ? -999 : packet.getSlotNum(), item); ++ cserver.getPluginManager().callEvent(event); ++ ++ itemstack = CraftItemStack.asNMSCopy(event.getCursor()); ++ ++ switch (event.getResult()) { ++ case ALLOW: ++ // Plugin cleared the id / stacksize checks ++ flag2 = true; ++ break; ++ case DEFAULT: ++ break; ++ case DENY: ++ // Reset the slot ++ if (packet.getSlotNum() >= 0) { ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(this.player.inventoryMenu.containerId, this.player.inventoryMenu.incrementStateId(), packet.getSlotNum(), this.player.inventoryMenu.getSlot(packet.getSlotNum()).getItem())); ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(-1, this.player.inventoryMenu.incrementStateId(), -1, ItemStack.EMPTY)); ++ } ++ return; ++ } ++ } ++ // CraftBukkit end ++ + if (flag1 && flag2) { +- this.player.inventoryMenu.getSlot(serverboundsetcreativemodeslotpacket.getSlotNum()).setByPlayer(itemstack); ++ this.player.inventoryMenu.getSlot(packet.getSlotNum()).setByPlayer(itemstack); + this.player.inventoryMenu.broadcastChanges(); + } else if (flag && flag2 && this.dropSpamTickCount < 200) { + this.dropSpamTickCount += 20; +@@ -1818,76 +2802,81 @@ + } + + @Override +- @Override +- public void handleSignUpdate(ServerboundSignUpdatePacket serverboundsignupdatepacket) { +- List list = (List) Stream.of(serverboundsignupdatepacket.getLines()).map(ChatFormatting::stripFormatting).collect(Collectors.toList()); ++ public void handleSignUpdate(ServerboundSignUpdatePacket packet) { ++ List list = (List) Stream.of(packet.getLines()).map(ChatFormatting::stripFormatting).collect(Collectors.toList()); + + this.filterTextPacket(list).thenAcceptAsync((list1) -> { +- this.updateSignText(serverboundsignupdatepacket, list1); ++ this.updateSignText(packet, list1); + }, this.server); + } + +- private void updateSignText(ServerboundSignUpdatePacket serverboundsignupdatepacket, List list) { ++ private void updateSignText(ServerboundSignUpdatePacket packet, List filteredText) { ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.resetLastActionTime(); +- ServerLevel serverlevel = this.player.serverLevel(); +- BlockPos blockpos = serverboundsignupdatepacket.getPos(); ++ ServerLevel worldserver = this.player.serverLevel(); ++ BlockPos blockposition = packet.getPos(); + +- if (serverlevel.hasChunkAt(blockpos)) { +- BlockEntity blockentity = serverlevel.getBlockEntity(blockpos); ++ if (worldserver.hasChunkAt(blockposition)) { ++ BlockEntity tileentity = worldserver.getBlockEntity(blockposition); + +- if (!(blockentity instanceof SignBlockEntity)) { ++ if (!(tileentity instanceof SignBlockEntity)) { + return; + } + +- SignBlockEntity signblockentity = (SignBlockEntity) blockentity; ++ SignBlockEntity tileentitysign = (SignBlockEntity) tileentity; + +- signblockentity.updateSignText(this.player, serverboundsignupdatepacket.isFrontText(), list); ++ tileentitysign.updateSignText(this.player, packet.isFrontText(), filteredText); + } + + } + + @Override +- @Override +- public void handlePlayerAbilities(ServerboundPlayerAbilitiesPacket serverboundplayerabilitiespacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundplayerabilitiespacket, this, this.player.serverLevel()); +- this.player.getAbilities().flying = serverboundplayerabilitiespacket.isFlying() && this.player.getAbilities().mayfly; ++ public void handlePlayerAbilities(ServerboundPlayerAbilitiesPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ // CraftBukkit start ++ if (this.player.getAbilities().mayfly && this.player.getAbilities().flying != packet.isFlying()) { ++ PlayerToggleFlightEvent event = new PlayerToggleFlightEvent(this.player.getBukkitEntity(), packet.isFlying()); ++ this.cserver.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ this.player.getAbilities().flying = packet.isFlying(); // Actually set the player's flying status ++ } else { ++ this.player.onUpdateAbilities(); // Tell the player their ability was reverted ++ } ++ } ++ // CraftBukkit end + } + + @Override +- @Override + public void handleClientInformation(ServerboundClientInformationPacket serverboundclientinformationpacket) { + PacketUtils.ensureRunningOnSameThread(serverboundclientinformationpacket, this, this.player.serverLevel()); + this.player.updateOptions(serverboundclientinformationpacket.information()); + } + + @Override +- @Override +- public void handleChangeDifficulty(ServerboundChangeDifficultyPacket serverboundchangedifficultypacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundchangedifficultypacket, this, this.player.serverLevel()); ++ public void handleChangeDifficulty(ServerboundChangeDifficultyPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + if (this.player.hasPermissions(2) || this.isSingleplayerOwner()) { +- this.server.setDifficulty(serverboundchangedifficultypacket.getDifficulty(), false); ++ this.server.setDifficulty(packet.getDifficulty(), false); + } + } + + @Override +- @Override +- public void handleLockDifficulty(ServerboundLockDifficultyPacket serverboundlockdifficultypacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundlockdifficultypacket, this, this.player.serverLevel()); ++ public void handleLockDifficulty(ServerboundLockDifficultyPacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + if (this.player.hasPermissions(2) || this.isSingleplayerOwner()) { +- this.server.setDifficultyLocked(serverboundlockdifficultypacket.isLocked()); ++ this.server.setDifficultyLocked(packet.isLocked()); + } + } + + @Override +- @Override +- public void handleChatSessionUpdate(ServerboundChatSessionUpdatePacket serverboundchatsessionupdatepacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundchatsessionupdatepacket, this, this.player.serverLevel()); +- RemoteChatSession.Data remotechatsession_data = serverboundchatsessionupdatepacket.chatSession(); +- ProfilePublicKey.Data profilepublickey_data = this.chatSession != null ? this.chatSession.profilePublicKey().data() : null; +- ProfilePublicKey.Data profilepublickey_data1 = remotechatsession_data.profilePublicKey(); ++ public void handleChatSessionUpdate(ServerboundChatSessionUpdatePacket packet) { ++ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ RemoteChatSession.Data remotechatsession_a = packet.chatSession(); ++ ProfilePublicKey.Data profilepublickey_a = this.chatSession != null ? this.chatSession.profilePublicKey().data() : null; ++ ProfilePublicKey.Data profilepublickey_a1 = remotechatsession_a.profilePublicKey(); + +- if (!Objects.equals(profilepublickey_data, profilepublickey_data1)) { +- if (profilepublickey_data != null && profilepublickey_data1.expiresAt().isBefore(profilepublickey_data.expiresAt())) { ++ if (!Objects.equals(profilepublickey_a, profilepublickey_a1)) { ++ if (profilepublickey_a != null && profilepublickey_a1.expiresAt().isBefore(profilepublickey_a.expiresAt())) { + this.disconnect(ProfilePublicKey.EXPIRED_PROFILE_PUBLIC_KEY); + } else { + try { +@@ -1898,10 +2887,10 @@ + return; + } + +- this.resetPlayerChatState(remotechatsession_data.validate(this.player.getGameProfile(), signaturevalidator)); +- } catch (ProfilePublicKey.ValidationException profilepublickey_validationexception) { +- ServerGamePacketListenerImpl.LOGGER.error("Failed to validate profile key: {}", profilepublickey_validationexception.getMessage()); +- this.disconnect(profilepublickey_validationexception.getComponent()); ++ this.resetPlayerChatState(remotechatsession_a.validate(this.player.getGameProfile(), signaturevalidator)); ++ } catch (ProfilePublicKey.b profilepublickey_b) { ++ ServerGamePacketListenerImpl.LOGGER.error("Failed to validate profile key: {}", profilepublickey_b.getMessage()); ++ this.disconnect(profilepublickey_b.getComponent()); + } + + } +@@ -1909,33 +2898,30 @@ + } + + @Override +- @Override + public void handleConfigurationAcknowledged(ServerboundConfigurationAcknowledgedPacket serverboundconfigurationacknowledgedpacket) { + if (!this.waitingForSwitchToConfig) { + throw new IllegalStateException("Client acknowledged config, but none was requested"); + } else { +- this.connection.setListener(new ServerConfigurationPacketListenerImpl(this.server, this.connection, this.createCookie(this.player.clientInformation()))); ++ this.connection.setListener(new ServerConfigurationPacketListenerImpl(this.server, this.connection, this.createCookie(this.player.clientInformation()), this.player)); // CraftBukkit + } + } + + @Override +- @Override + public void handleChunkBatchReceived(ServerboundChunkBatchReceivedPacket serverboundchunkbatchreceivedpacket) { + PacketUtils.ensureRunningOnSameThread(serverboundchunkbatchreceivedpacket, this, this.player.serverLevel()); + this.chunkSender.onChunkBatchReceivedByClient(serverboundchunkbatchreceivedpacket.desiredChunksPerTick()); + } + +- private void resetPlayerChatState(RemoteChatSession remotechatsession) { +- this.chatSession = remotechatsession; +- this.signedMessageDecoder = remotechatsession.createMessageDecoder(this.player.getUUID()); ++ private void resetPlayerChatState(RemoteChatSession chatSession) { ++ this.chatSession = chatSession; ++ this.signedMessageDecoder = chatSession.createMessageDecoder(this.player.getUUID()); + this.chatMessageChain.append(() -> { +- this.player.setChatSession(remotechatsession); ++ this.player.setChatSession(chatSession); + this.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.INITIALIZE_CHAT), List.of(this.player))); + }); + } + + @Override +- @Override + public ServerPlayer getPlayer() { + return this.player; + } +@@ -1943,6 +2929,6 @@ + @FunctionalInterface + private interface EntityInteraction { + +- InteractionResult run(ServerPlayer player, Entity entity, InteractionHand hand); ++ InteractionResult run(ServerPlayer player, Entity entity, EnumHand hand); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java.patch new file mode 100644 index 0000000000..9e2351225b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java.patch @@ -0,0 +1,123 @@ +--- a/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +@@ -11,60 +11,101 @@ + import net.minecraft.network.protocol.status.ServerStatus; + import net.minecraft.server.MinecraftServer; + ++// CraftBukkit start ++import java.net.InetAddress; ++import java.util.HashMap; ++// CraftBukkit end ++ + public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketListener { + ++ // CraftBukkit start - add fields ++ private static final HashMap throttleTracker = new HashMap(); ++ private static int throttleCounter = 0; ++ // CraftBukkit end + private static final Component IGNORE_STATUS_REASON = Component.translatable("disconnect.ignoring_status_request"); + private final MinecraftServer server; + private final Connection connection; + +- public ServerHandshakePacketListenerImpl(MinecraftServer minecraftserver, Connection connection) { +- this.server = minecraftserver; ++ public ServerHandshakePacketListenerImpl(MinecraftServer server, Connection connection) { ++ this.server = server; + this.connection = connection; + } + + @Override +- @Override +- public void handleIntention(ClientIntentionPacket clientintentionpacket) { +- switch (clientintentionpacket.intention()) { ++ public void handleIntention(ClientIntentionPacket packet) { ++ this.connection.hostname = packet.hostName() + ":" + packet.port(); // CraftBukkit - set hostname ++ switch (packet.intention()) { + case LOGIN: + this.connection.setClientboundProtocolAfterHandshake(ClientIntent.LOGIN); +- if (clientintentionpacket.protocolVersion() != SharedConstants.getCurrentVersion().getProtocolVersion()) { +- MutableComponent mutablecomponent; ++ // CraftBukkit start - Connection throttle ++ try { ++ long currentTime = System.currentTimeMillis(); ++ long connectionThrottle = this.server.server.getConnectionThrottle(); ++ InetAddress address = ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getAddress(); + +- if (clientintentionpacket.protocolVersion() < 754) { +- mutablecomponent = Component.translatable("multiplayer.disconnect.outdated_client", SharedConstants.getCurrentVersion().getName()); ++ synchronized (throttleTracker) { ++ if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { ++ throttleTracker.put(address, currentTime); ++ MutableComponent chatmessage = Component.literal("Connection throttled! Please wait before reconnecting."); ++ this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); ++ this.connection.disconnect(chatmessage); ++ return; ++ } ++ ++ throttleTracker.put(address, currentTime); ++ throttleCounter++; ++ if (throttleCounter > 200) { ++ throttleCounter = 0; ++ ++ // Cleanup stale entries ++ java.util.Iterator iter = throttleTracker.entrySet().iterator(); ++ while (iter.hasNext()) { ++ java.util.Map.Entry entry = (java.util.Map.Entry) iter.next(); ++ if (entry.getValue() > connectionThrottle) { ++ iter.remove(); ++ } ++ } ++ } ++ } ++ } catch (Throwable t) { ++ org.apache.logging.log4j.LogManager.getLogger().debug("Failed to check connection throttle", t); ++ } ++ // CraftBukkit end ++ if (packet.protocolVersion() != SharedConstants.getCurrentVersion().getProtocolVersion()) { ++ MutableComponent ichatmutablecomponent; ++ ++ if (packet.protocolVersion() < 754) { ++ ichatmutablecomponent = Component.translatable("multiplayer.disconnect.outdated_client", SharedConstants.getCurrentVersion().getName()); + } else { +- mutablecomponent = Component.translatable("multiplayer.disconnect.incompatible", SharedConstants.getCurrentVersion().getName()); ++ ichatmutablecomponent = Component.translatable("multiplayer.disconnect.incompatible", SharedConstants.getCurrentVersion().getName()); + } + +- this.connection.send(new ClientboundLoginDisconnectPacket(mutablecomponent)); +- this.connection.disconnect(mutablecomponent); ++ this.connection.send(new ClientboundLoginDisconnectPacket(ichatmutablecomponent)); ++ this.connection.disconnect(ichatmutablecomponent); + } else { + this.connection.setListener(new ServerLoginPacketListenerImpl(this.server, this.connection)); + } + break; + case STATUS: +- ServerStatus serverstatus = this.server.getStatus(); ++ ServerStatus serverping = this.server.getStatus(); + +- if (this.server.repliesToStatus() && serverstatus != null) { ++ if (this.server.repliesToStatus() && serverping != null) { + this.connection.setClientboundProtocolAfterHandshake(ClientIntent.STATUS); +- this.connection.setListener(new ServerStatusPacketListenerImpl(serverstatus, this.connection)); ++ this.connection.setListener(new ServerStatusPacketListenerImpl(serverping, this.connection)); + } else { + this.connection.disconnect(ServerHandshakePacketListenerImpl.IGNORE_STATUS_REASON); + } + break; + default: +- throw new UnsupportedOperationException("Invalid intention " + clientintentionpacket.intention()); ++ throw new UnsupportedOperationException("Invalid intention " + packet.intention()); + } + + } + + @Override +- @Override +- public void onDisconnect(Component component) {} ++ public void onDisconnect(Component reason) {} + + @Override +- @Override + public boolean isAcceptingMessages() { + return this.connection.isConnected(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerLoginPacketListenerImpl.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerLoginPacketListenerImpl.java.patch new file mode 100644 index 0000000000..54daae88c3 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerLoginPacketListenerImpl.java.patch @@ -0,0 +1,306 @@ +--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -32,6 +32,7 @@ + import net.minecraft.network.protocol.login.ServerboundKeyPacket; + import net.minecraft.network.protocol.login.ServerboundLoginAcknowledgedPacket; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.players.PlayerList; + import net.minecraft.util.Crypt; + import net.minecraft.util.CryptException; +@@ -39,6 +40,10 @@ + import net.minecraft.world.entity.player.Player; + import org.apache.commons.lang3.Validate; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.bukkit.event.player.AsyncPlayerPreLoginEvent; ++import org.bukkit.event.player.PlayerPreLoginEvent; ++// CraftBukkit end + + public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, TickablePacketListener { + +@@ -48,31 +53,31 @@ + private static final Component DISCONNECT_UNEXPECTED_QUERY = Component.translatable("multiplayer.disconnect.unexpected_query_response"); + private final byte[] challenge; + final MinecraftServer server; +- final Connection connection; +- private volatile ServerLoginPacketListenerImpl.State state; ++ public final Connection connection; ++ private volatile ServerLoginPacketListenerImpl.EnumProtocolState state; + private int tick; + @Nullable + String requestedUsername; + @Nullable + private GameProfile authenticatedProfile; + private final String serverId; ++ private ServerPlayer player; // CraftBukkit + +- public ServerLoginPacketListenerImpl(MinecraftServer minecraftserver, Connection connection) { +- this.state = ServerLoginPacketListenerImpl.State.HELLO; ++ public ServerLoginPacketListenerImpl(MinecraftServer server, Connection connection) { ++ this.state = ServerLoginPacketListenerImpl.EnumProtocolState.HELLO; + this.serverId = ""; +- this.server = minecraftserver; ++ this.server = server; + this.connection = connection; + this.challenge = Ints.toByteArray(RandomSource.create().nextInt()); + } + + @Override +- @Override + public void tick() { +- if (this.state == ServerLoginPacketListenerImpl.State.VERIFYING) { ++ if (this.state == ServerLoginPacketListenerImpl.EnumProtocolState.VERIFYING) { + this.verifyLoginAndFinishConnectionSetup((GameProfile) Objects.requireNonNull(this.authenticatedProfile)); + } + +- if (this.state == ServerLoginPacketListenerImpl.State.WAITING_FOR_DUPE_DISCONNECT && !this.isPlayerAlreadyInWorld((GameProfile) Objects.requireNonNull(this.authenticatedProfile))) { ++ if (this.state == ServerLoginPacketListenerImpl.EnumProtocolState.WAITING_FOR_DUPE_DISCONNECT && !this.isPlayerAlreadyInWorld((GameProfile) Objects.requireNonNull(this.authenticatedProfile))) { + this.finishLoginAndWaitForClient(this.authenticatedProfile); + } + +@@ -82,17 +87,23 @@ + + } + ++ // CraftBukkit start ++ @Deprecated ++ public void disconnect(String s) { ++ disconnect(Component.literal(s)); ++ } ++ // CraftBukkit end ++ + @Override +- @Override + public boolean isAcceptingMessages() { + return this.connection.isConnected(); + } + +- public void disconnect(Component component) { ++ public void disconnect(Component reason) { + try { +- ServerLoginPacketListenerImpl.LOGGER.info("Disconnecting {}: {}", this.getUserName(), component.getString()); +- this.connection.send(new ClientboundLoginDisconnectPacket(component)); +- this.connection.disconnect(component); ++ ServerLoginPacketListenerImpl.LOGGER.info("Disconnecting {}: {}", this.getUserName(), reason.getString()); ++ this.connection.send(new ClientboundLoginDisconnectPacket(reason)); ++ this.connection.disconnect(reason); + } catch (Exception exception) { + ServerLoginPacketListenerImpl.LOGGER.error("Error whilst disconnecting player", exception); + } +@@ -104,9 +115,8 @@ + } + + @Override +- @Override +- public void onDisconnect(Component component) { +- ServerLoginPacketListenerImpl.LOGGER.info("{} lost connection: {}", this.getUserName(), component.getString()); ++ public void onDisconnect(Component reason) { ++ ServerLoginPacketListenerImpl.LOGGER.info("{} lost connection: {}", this.getUserName(), reason.getString()); + } + + public String getUserName() { +@@ -116,18 +126,17 @@ + } + + @Override +- @Override +- public void handleHello(ServerboundHelloPacket serverboundhellopacket) { +- Validate.validState(this.state == ServerLoginPacketListenerImpl.State.HELLO, "Unexpected hello packet", new Object[0]); +- Validate.validState(Player.isValidUsername(serverboundhellopacket.name()), "Invalid characters in username", new Object[0]); +- this.requestedUsername = serverboundhellopacket.name(); ++ public void handleHello(ServerboundHelloPacket packet) { ++ Validate.validState(this.state == ServerLoginPacketListenerImpl.EnumProtocolState.HELLO, "Unexpected hello packet", new Object[0]); ++ Validate.validState(Player.isValidUsername(packet.name()), "Invalid characters in username", new Object[0]); ++ this.requestedUsername = packet.name(); + GameProfile gameprofile = this.server.getSingleplayerProfile(); + + if (gameprofile != null && this.requestedUsername.equalsIgnoreCase(gameprofile.getName())) { + this.startClientVerification(gameprofile); + } else { + if (this.server.usesAuthentication() && !this.connection.isMemoryConnection()) { +- this.state = ServerLoginPacketListenerImpl.State.KEY; ++ this.state = ServerLoginPacketListenerImpl.EnumProtocolState.KEY; + this.connection.send(new ClientboundHelloPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.challenge)); + } else { + this.startClientVerification(UUIDUtil.createOfflineProfile(this.requestedUsername)); +@@ -138,15 +147,17 @@ + + void startClientVerification(GameProfile gameprofile) { + this.authenticatedProfile = gameprofile; +- this.state = ServerLoginPacketListenerImpl.State.VERIFYING; ++ this.state = ServerLoginPacketListenerImpl.EnumProtocolState.VERIFYING; + } + + private void verifyLoginAndFinishConnectionSetup(GameProfile gameprofile) { + PlayerList playerlist = this.server.getPlayerList(); +- Component component = playerlist.canPlayerLogin(this.connection.getRemoteAddress(), gameprofile); ++ // CraftBukkit start - fire PlayerLoginEvent ++ this.player = playerlist.canPlayerLogin(this, gameprofile); // CraftBukkit + +- if (component != null) { +- this.disconnect(component); ++ if (this.player == null) { ++ // this.disconnect(ichatbasecomponent); ++ // CraftBukkit end + } else { + if (this.server.getCompressionThreshold() >= 0 && !this.connection.isMemoryConnection()) { + this.connection.send(new ClientboundLoginCompressionPacket(this.server.getCompressionThreshold()), PacketSendListener.thenRun(() -> { +@@ -154,10 +165,10 @@ + })); + } + +- boolean flag = playerlist.disconnectAllPlayersWithProfile(gameprofile); ++ boolean flag = playerlist.disconnectAllPlayersWithProfile(gameprofile, this.player); // CraftBukkit - add player reference + + if (flag) { +- this.state = ServerLoginPacketListenerImpl.State.WAITING_FOR_DUPE_DISCONNECT; ++ this.state = ServerLoginPacketListenerImpl.EnumProtocolState.WAITING_FOR_DUPE_DISCONNECT; + } else { + this.finishLoginAndWaitForClient(gameprofile); + } +@@ -166,37 +177,35 @@ + } + + private void finishLoginAndWaitForClient(GameProfile gameprofile) { +- this.state = ServerLoginPacketListenerImpl.State.PROTOCOL_SWITCHING; ++ this.state = ServerLoginPacketListenerImpl.EnumProtocolState.PROTOCOL_SWITCHING; + this.connection.send(new ClientboundGameProfilePacket(gameprofile)); + } + + @Override +- @Override +- public void handleKey(ServerboundKeyPacket serverboundkeypacket) { +- Validate.validState(this.state == ServerLoginPacketListenerImpl.State.KEY, "Unexpected key packet", new Object[0]); ++ public void handleKey(ServerboundKeyPacket packet) { ++ Validate.validState(this.state == ServerLoginPacketListenerImpl.EnumProtocolState.KEY, "Unexpected key packet", new Object[0]); + + final String s; + + try { + PrivateKey privatekey = this.server.getKeyPair().getPrivate(); + +- if (!serverboundkeypacket.isChallengeValid(this.challenge, privatekey)) { ++ if (!packet.isChallengeValid(this.challenge, privatekey)) { + throw new IllegalStateException("Protocol error"); + } + +- SecretKey secretkey = serverboundkeypacket.getSecretKey(privatekey); ++ SecretKey secretkey = packet.getSecretKey(privatekey); + Cipher cipher = Crypt.getCipher(2, secretkey); + Cipher cipher1 = Crypt.getCipher(1, secretkey); + + s = (new BigInteger(Crypt.digestData("", this.server.getKeyPair().getPublic(), secretkey))).toString(16); +- this.state = ServerLoginPacketListenerImpl.State.AUTHENTICATING; ++ this.state = ServerLoginPacketListenerImpl.EnumProtocolState.AUTHENTICATING; + this.connection.setEncryptionKey(cipher, cipher1); +- } catch (CryptException cryptexception) { +- throw new IllegalStateException("Protocol error", cryptexception); ++ } catch (CryptException cryptographyexception) { ++ throw new IllegalStateException("Protocol error", cryptographyexception); + } + + Thread thread = new Thread("User Authenticator #" + ServerLoginPacketListenerImpl.UNIQUE_THREAD_ID.incrementAndGet()) { +- @Override + public void run() { + String s1 = (String) Objects.requireNonNull(ServerLoginPacketListenerImpl.this.requestedUsername, "Player name not initialized"); + +@@ -206,6 +215,43 @@ + if (profileresult != null) { + GameProfile gameprofile = profileresult.profile(); + ++ // CraftBukkit start - fire PlayerPreLoginEvent ++ if (!connection.isConnected()) { ++ return; ++ } ++ ++ String playerName = gameprofile.getName(); ++ java.net.InetAddress address = ((java.net.InetSocketAddress) connection.getRemoteAddress()).getAddress(); ++ java.util.UUID uniqueId = gameprofile.getId(); ++ final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server; ++ ++ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId); ++ server.getPluginManager().callEvent(asyncEvent); ++ ++ if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { ++ final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); ++ if (asyncEvent.getResult() != PlayerPreLoginEvent.Result.ALLOWED) { ++ event.disallow(asyncEvent.getResult(), asyncEvent.getKickMessage()); ++ } ++ Waitable waitable = new Waitable() { ++ @Override ++ protected PlayerPreLoginEvent.Result evaluate() { ++ server.getPluginManager().callEvent(event); ++ return event.getResult(); ++ }}; ++ ++ ServerLoginPacketListenerImpl.this.server.processQueue.add(waitable); ++ if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) { ++ disconnect(event.getKickMessage()); ++ return; ++ } ++ } else { ++ if (asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { ++ disconnect(asyncEvent.getKickMessage()); ++ return; ++ } ++ } ++ // CraftBukkit end + ServerLoginPacketListenerImpl.LOGGER.info("UUID of player {} is {}", gameprofile.getName(), gameprofile.getId()); + ServerLoginPacketListenerImpl.this.startClientVerification(gameprofile); + } else if (ServerLoginPacketListenerImpl.this.server.isSingleplayer()) { +@@ -223,6 +269,11 @@ + ServerLoginPacketListenerImpl.this.disconnect(Component.translatable("multiplayer.disconnect.authservers_down")); + ServerLoginPacketListenerImpl.LOGGER.error("Couldn't verify username because servers are unavailable"); + } ++ // CraftBukkit start - catch all exceptions ++ } catch (Exception exception) { ++ disconnect("Failed to verify username!"); ++ server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + s1, exception); ++ // CraftBukkit end + } + + } +@@ -240,35 +291,32 @@ + } + + @Override +- @Override + public void handleCustomQueryPacket(ServerboundCustomQueryAnswerPacket serverboundcustomqueryanswerpacket) { + this.disconnect(ServerLoginPacketListenerImpl.DISCONNECT_UNEXPECTED_QUERY); + } + + @Override +- @Override + public void handleLoginAcknowledgement(ServerboundLoginAcknowledgedPacket serverboundloginacknowledgedpacket) { +- Validate.validState(this.state == ServerLoginPacketListenerImpl.State.PROTOCOL_SWITCHING, "Unexpected login acknowledgement packet", new Object[0]); ++ Validate.validState(this.state == ServerLoginPacketListenerImpl.EnumProtocolState.PROTOCOL_SWITCHING, "Unexpected login acknowledgement packet", new Object[0]); + CommonListenerCookie commonlistenercookie = CommonListenerCookie.createInitial((GameProfile) Objects.requireNonNull(this.authenticatedProfile)); +- ServerConfigurationPacketListenerImpl serverconfigurationpacketlistenerimpl = new ServerConfigurationPacketListenerImpl(this.server, this.connection, commonlistenercookie); ++ ServerConfigurationPacketListenerImpl serverconfigurationpacketlistenerimpl = new ServerConfigurationPacketListenerImpl(this.server, this.connection, commonlistenercookie, this.player); // CraftBukkit + + this.connection.setListener(serverconfigurationpacketlistenerimpl); + serverconfigurationpacketlistenerimpl.startConfiguration(); +- this.state = ServerLoginPacketListenerImpl.State.ACCEPTED; ++ this.state = ServerLoginPacketListenerImpl.EnumProtocolState.ACCEPTED; + } + + @Override +- @Override +- public void fillListenerSpecificCrashDetails(CrashReportCategory crashreportcategory) { +- crashreportcategory.setDetail("Login phase", () -> { ++ public void fillListenerSpecificCrashDetails(CrashReportCategory crashreportsystemdetails) { ++ crashreportsystemdetails.setDetail("Login phase", () -> { + return this.state.toString(); + }); + } + +- private static enum State { ++ private static enum EnumProtocolState { + + HELLO, KEY, AUTHENTICATING, NEGOTIATING, VERIFYING, WAITING_FOR_DUPE_DISCONNECT, PROTOCOL_SWITCHING, ACCEPTED; + +- private State() {} ++ private EnumProtocolState() {} + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerStatusPacketListenerImpl.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerStatusPacketListenerImpl.java.patch new file mode 100644 index 0000000000..540cc32d8a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/network/ServerStatusPacketListenerImpl.java.patch @@ -0,0 +1,166 @@ +--- a/net/minecraft/server/network/ServerStatusPacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerStatusPacketListenerImpl.java +@@ -1,5 +1,12 @@ + package net.minecraft.server.network; + ++// CraftBukkit start ++import com.mojang.authlib.GameProfile; ++import java.net.InetSocketAddress; ++import java.util.Collections; ++import java.util.Iterator; ++import java.util.Optional; ++import net.minecraft.SharedConstants; + import net.minecraft.network.Connection; + import net.minecraft.network.chat.Component; + import net.minecraft.network.protocol.status.ClientboundPongResponsePacket; +@@ -8,6 +15,12 @@ + import net.minecraft.network.protocol.status.ServerStatusPacketListener; + import net.minecraft.network.protocol.status.ServerboundPingRequestPacket; + import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerPlayer; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.craftbukkit.util.CraftIconCache; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class ServerStatusPacketListenerImpl implements ServerStatusPacketListener { + +@@ -16,36 +29,126 @@ + private final Connection connection; + private boolean hasRequestedStatus; + +- public ServerStatusPacketListenerImpl(ServerStatus serverstatus, Connection connection) { +- this.status = serverstatus; ++ public ServerStatusPacketListenerImpl(ServerStatus status, Connection connection) { ++ this.status = status; + this.connection = connection; + } + + @Override +- @Override +- public void onDisconnect(Component component) {} ++ public void onDisconnect(Component reason) {} + + @Override +- @Override + public boolean isAcceptingMessages() { + return this.connection.isConnected(); + } + + @Override +- @Override +- public void handleStatusRequest(ServerboundStatusRequestPacket serverboundstatusrequestpacket) { ++ public void handleStatusRequest(ServerboundStatusRequestPacket packet) { + if (this.hasRequestedStatus) { + this.connection.disconnect(ServerStatusPacketListenerImpl.DISCONNECT_REASON); + } else { + this.hasRequestedStatus = true; +- this.connection.send(new ClientboundStatusResponsePacket(this.status)); ++ // CraftBukkit start ++ // this.connection.send(new PacketStatusOutServerInfo(this.status)); ++ MinecraftServer server = MinecraftServer.getServer(); ++ final Object[] players = server.getPlayerList().players.toArray(); ++ class ServerListPingEvent extends org.bukkit.event.server.ServerListPingEvent { ++ ++ CraftIconCache icon = server.server.getServerIcon(); ++ ++ ServerListPingEvent() { ++ super(connection.hostname, ((InetSocketAddress) connection.getRemoteAddress()).getAddress(), server.getMotd(), server.getPlayerList().getMaxPlayers()); ++ } ++ ++ @Override ++ public void setServerIcon(org.bukkit.util.CachedServerIcon icon) { ++ if (!(icon instanceof CraftIconCache)) { ++ throw new IllegalArgumentException(icon + " was not created by " + org.bukkit.craftbukkit.CraftServer.class); ++ } ++ this.icon = (CraftIconCache) icon; ++ } ++ ++ @Override ++ public Iterator iterator() throws UnsupportedOperationException { ++ return new Iterator() { ++ int i; ++ int ret = Integer.MIN_VALUE; ++ ServerPlayer player; ++ ++ @Override ++ public boolean hasNext() { ++ if (player != null) { ++ return true; ++ } ++ final Object[] currentPlayers = players; ++ for (int length = currentPlayers.length, i = this.i; i < length; i++) { ++ final ServerPlayer player = (ServerPlayer) currentPlayers[i]; ++ if (player != null) { ++ this.i = i + 1; ++ this.player = player; ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ @Override ++ public Player next() { ++ if (!hasNext()) { ++ throw new java.util.NoSuchElementException(); ++ } ++ final ServerPlayer player = this.player; ++ this.player = null; ++ this.ret = this.i - 1; ++ return player.getBukkitEntity(); ++ } ++ ++ @Override ++ public void remove() { ++ final Object[] currentPlayers = players; ++ final int i = this.ret; ++ if (i < 0 || currentPlayers[i] == null) { ++ throw new IllegalStateException(); ++ } ++ currentPlayers[i] = null; ++ } ++ }; ++ } ++ } ++ ++ ServerListPingEvent event = new ServerListPingEvent(); ++ server.server.getPluginManager().callEvent(event); ++ ++ java.util.List profiles = new java.util.ArrayList(players.length); ++ for (Object player : players) { ++ if (player != null) { ++ ServerPlayer entityPlayer = ((ServerPlayer) player); ++ if (entityPlayer.allowsListing()) { ++ profiles.add(entityPlayer.getGameProfile()); ++ } else { ++ profiles.add(MinecraftServer.ANONYMOUS_PLAYER_PROFILE); ++ } ++ } ++ } ++ ++ ServerStatus.ServerPingPlayerSample playerSample = new ServerStatus.ServerPingPlayerSample(event.getMaxPlayers(), profiles.size(), (server.hidesOnlinePlayers()) ? Collections.emptyList() : profiles); ++ ++ ServerStatus ping = new ServerStatus( ++ CraftChatMessage.fromString(event.getMotd(), true)[0], ++ Optional.of(playerSample), ++ Optional.of(new ServerStatus.Version(server.getServerModName() + " " + server.getServerVersion(), SharedConstants.getCurrentVersion().getProtocolVersion())), ++ (event.icon.value != null) ? Optional.of(new ServerStatus.a(event.icon.value)) : Optional.empty(), ++ server.enforceSecureProfile() ++ ); ++ ++ this.connection.send(new ClientboundStatusResponsePacket(ping)); ++ // CraftBukkit end + } + } + + @Override +- @Override +- public void handlePingRequest(ServerboundPingRequestPacket serverboundpingrequestpacket) { +- this.connection.send(new ClientboundPongResponsePacket(serverboundpingrequestpacket.getTime())); ++ public void handlePingRequest(ServerboundPingRequestPacket packet) { ++ this.connection.send(new ClientboundPongResponsePacket(packet.getTime())); + this.connection.disconnect(ServerStatusPacketListenerImpl.DISCONNECT_REASON); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/players/BanListEntry.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/players/BanListEntry.java.patch new file mode 100644 index 0000000000..e468725695 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/players/BanListEntry.java.patch @@ -0,0 +1,94 @@ +--- a/net/minecraft/server/players/BanListEntry.java ++++ b/net/minecraft/server/players/BanListEntry.java +@@ -18,38 +18,38 @@ + protected final Date expires; + protected final String reason; + +- public BanListEntry(@Nullable T t0, @Nullable Date date, @Nullable String s, @Nullable Date date1, @Nullable String s1) { +- super(t0); +- this.created = date == null ? new Date() : date; +- this.source = s == null ? "(Unknown)" : s; +- this.expires = date1; +- this.reason = s1 == null ? "Banned by an operator." : s1; ++ public BanListEntry(@Nullable T user, @Nullable Date created, @Nullable String source, @Nullable Date expires, @Nullable String reason) { ++ super(user); ++ this.created = created == null ? new Date() : created; ++ this.source = source == null ? "(Unknown)" : source; ++ this.expires = expires; ++ this.reason = reason == null ? "Banned by an operator." : reason; + } + +- protected BanListEntry(@Nullable T t0, JsonObject jsonobject) { +- super(t0); ++ protected BanListEntry(@Nullable T user, JsonObject entryData) { ++ super(checkExpiry(user, entryData)); // CraftBukkit + + Date date; + + try { +- date = jsonobject.has("created") ? BanListEntry.DATE_FORMAT.parse(jsonobject.get("created").getAsString()) : new Date(); ++ date = entryData.has("created") ? BanListEntry.DATE_FORMAT.parse(entryData.get("created").getAsString()) : new Date(); + } catch (ParseException parseexception) { + date = new Date(); + } + + this.created = date; +- this.source = jsonobject.has("source") ? jsonobject.get("source").getAsString() : "(Unknown)"; ++ this.source = entryData.has("source") ? entryData.get("source").getAsString() : "(Unknown)"; + + Date date1; + + try { +- date1 = jsonobject.has("expires") ? BanListEntry.DATE_FORMAT.parse(jsonobject.get("expires").getAsString()) : null; ++ date1 = entryData.has("expires") ? BanListEntry.DATE_FORMAT.parse(entryData.get("expires").getAsString()) : null; + } catch (ParseException parseexception1) { + date1 = null; + } + + this.expires = date1; +- this.reason = jsonobject.has("reason") ? jsonobject.get("reason").getAsString() : "Banned by an operator."; ++ this.reason = entryData.has("reason") ? entryData.get("reason").getAsString() : "Banned by an operator."; + } + + public Date getCreated() { +@@ -72,17 +72,33 @@ + public abstract Component getDisplayName(); + + @Override +- @Override + boolean hasExpired() { + return this.expires == null ? false : this.expires.before(new Date()); + } + + @Override +- @Override +- protected void serialize(JsonObject jsonobject) { +- jsonobject.addProperty("created", BanListEntry.DATE_FORMAT.format(this.created)); +- jsonobject.addProperty("source", this.source); +- jsonobject.addProperty("expires", this.expires == null ? "forever" : BanListEntry.DATE_FORMAT.format(this.expires)); +- jsonobject.addProperty("reason", this.reason); ++ protected void serialize(JsonObject data) { ++ data.addProperty("created", BanListEntry.DATE_FORMAT.format(this.created)); ++ data.addProperty("source", this.source); ++ data.addProperty("expires", this.expires == null ? "forever" : BanListEntry.DATE_FORMAT.format(this.expires)); ++ data.addProperty("reason", this.reason); + } ++ ++ // CraftBukkit start ++ private static T checkExpiry(T object, JsonObject jsonobject) { ++ Date expires = null; ++ ++ try { ++ expires = jsonobject.has("expires") ? DATE_FORMAT.parse(jsonobject.get("expires").getAsString()) : null; ++ } catch (ParseException ex) { ++ // Guess we don't have a date ++ } ++ ++ if (expires == null || expires.after(new Date())) { ++ return object; ++ } else { ++ return null; ++ } ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/players/GameProfileCache.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/players/GameProfileCache.java.patch new file mode 100644 index 0000000000..cec110ac1f --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/players/GameProfileCache.java.patch @@ -0,0 +1,226 @@ +--- a/net/minecraft/server/players/GameProfileCache.java ++++ b/net/minecraft/server/players/GameProfileCache.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.server.players; + + import com.google.common.collect.ImmutableList; +@@ -60,41 +61,39 @@ + @Nullable + private Executor executor; + +- public GameProfileCache(GameProfileRepository gameprofilerepository, File file) { +- this.profileRepository = gameprofilerepository; ++ public GameProfileCache(GameProfileRepository profileRepository, File file) { ++ this.profileRepository = profileRepository; + this.file = file; + Lists.reverse(this.load()).forEach(this::safeAdd); + } + +- private void safeAdd(GameProfileCache.GameProfileInfo gameprofilecache_gameprofileinfo) { +- GameProfile gameprofile = gameprofilecache_gameprofileinfo.getProfile(); ++ private void safeAdd(GameProfileCache.GameProfileInfo profile) { ++ GameProfile gameprofile = profile.getProfile(); + +- gameprofilecache_gameprofileinfo.setLastAccess(this.getNextOperation()); +- this.profilesByName.put(gameprofile.getName().toLowerCase(Locale.ROOT), gameprofilecache_gameprofileinfo); +- this.profilesByUUID.put(gameprofile.getId(), gameprofilecache_gameprofileinfo); ++ profile.setLastAccess(this.getNextOperation()); ++ this.profilesByName.put(gameprofile.getName().toLowerCase(Locale.ROOT), profile); ++ this.profilesByUUID.put(gameprofile.getId(), profile); + } + +- private static Optional lookupGameProfile(GameProfileRepository gameprofilerepository, String s) { +- if (!Player.isValidUsername(s)) { +- return createUnknownProfile(s); ++ private static Optional lookupGameProfile(GameProfileRepository profileRepo, String name) { ++ if (!Player.isValidUsername(name)) { ++ return createUnknownProfile(name); + } else { + final AtomicReference atomicreference = new AtomicReference(); + ProfileLookupCallback profilelookupcallback = new ProfileLookupCallback() { +- @Override + public void onProfileLookupSucceeded(GameProfile gameprofile) { + atomicreference.set(gameprofile); + } + +- @Override + public void onProfileLookupFailed(String s1, Exception exception) { +- atomicreference.set((Object) null); ++ atomicreference.set(null); // CraftBukkit - decompile error + } + }; + +- gameprofilerepository.findProfilesByNames(new String[]{s}, profilelookupcallback); ++ profileRepo.findProfilesByNames(new String[]{name}, profilelookupcallback); + GameProfile gameprofile = (GameProfile) atomicreference.get(); + +- return gameprofile != null ? Optional.of(gameprofile) : createUnknownProfile(s); ++ return gameprofile != null ? Optional.of(gameprofile) : createUnknownProfile(name); + } + } + +@@ -102,23 +101,23 @@ + return usesAuthentication() ? Optional.empty() : Optional.of(UUIDUtil.createOfflineProfile(s)); + } + +- public static void setUsesAuthentication(boolean flag) { +- GameProfileCache.usesAuthentication = flag; ++ public static void setUsesAuthentication(boolean onlineMode) { ++ GameProfileCache.usesAuthentication = onlineMode; + } + + private static boolean usesAuthentication() { + return GameProfileCache.usesAuthentication; + } + +- public void add(GameProfile gameprofile) { ++ public void add(GameProfile gameProfile) { + Calendar calendar = Calendar.getInstance(); + + calendar.setTime(new Date()); + calendar.add(2, 1); + Date date = calendar.getTime(); +- GameProfileCache.GameProfileInfo gameprofilecache_gameprofileinfo = new GameProfileCache.GameProfileInfo(gameprofile, date); ++ GameProfileCache.GameProfileInfo usercache_usercacheentry = new GameProfileCache.GameProfileInfo(gameProfile, date); + +- this.safeAdd(gameprofilecache_gameprofileinfo); ++ this.safeAdd(usercache_usercacheentry); + this.save(); + } + +@@ -126,23 +125,23 @@ + return this.operationCount.incrementAndGet(); + } + +- public Optional get(String s) { +- String s1 = s.toLowerCase(Locale.ROOT); +- GameProfileCache.GameProfileInfo gameprofilecache_gameprofileinfo = (GameProfileCache.GameProfileInfo) this.profilesByName.get(s1); ++ public Optional get(String name) { ++ String s1 = name.toLowerCase(Locale.ROOT); ++ GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByName.get(s1); + boolean flag = false; + +- if (gameprofilecache_gameprofileinfo != null && (new Date()).getTime() >= gameprofilecache_gameprofileinfo.expirationDate.getTime()) { +- this.profilesByUUID.remove(gameprofilecache_gameprofileinfo.getProfile().getId()); +- this.profilesByName.remove(gameprofilecache_gameprofileinfo.getProfile().getName().toLowerCase(Locale.ROOT)); ++ if (usercache_usercacheentry != null && (new Date()).getTime() >= usercache_usercacheentry.expirationDate.getTime()) { ++ this.profilesByUUID.remove(usercache_usercacheentry.getProfile().getId()); ++ this.profilesByName.remove(usercache_usercacheentry.getProfile().getName().toLowerCase(Locale.ROOT)); + flag = true; +- gameprofilecache_gameprofileinfo = null; ++ usercache_usercacheentry = null; + } + + Optional optional; + +- if (gameprofilecache_gameprofileinfo != null) { +- gameprofilecache_gameprofileinfo.setLastAccess(this.getNextOperation()); +- optional = Optional.of(gameprofilecache_gameprofileinfo.getProfile()); ++ if (usercache_usercacheentry != null) { ++ usercache_usercacheentry.setLastAccess(this.getNextOperation()); ++ optional = Optional.of(usercache_usercacheentry.getProfile()); + } else { + optional = lookupGameProfile(this.profileRepository, s1); + if (optional.isPresent()) { +@@ -180,18 +179,18 @@ + } + + public Optional get(UUID uuid) { +- GameProfileCache.GameProfileInfo gameprofilecache_gameprofileinfo = (GameProfileCache.GameProfileInfo) this.profilesByUUID.get(uuid); ++ GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByUUID.get(uuid); + +- if (gameprofilecache_gameprofileinfo == null) { ++ if (usercache_usercacheentry == null) { + return Optional.empty(); + } else { +- gameprofilecache_gameprofileinfo.setLastAccess(this.getNextOperation()); +- return Optional.of(gameprofilecache_gameprofileinfo.getProfile()); ++ usercache_usercacheentry.setLastAccess(this.getNextOperation()); ++ return Optional.of(usercache_usercacheentry.getProfile()); + } + } + +- public void setExecutor(Executor executor) { +- this.executor = executor; ++ public void setExecutor(Executor exectutor) { ++ this.executor = exectutor; + } + + public void clearExecutor() { +@@ -263,8 +262,8 @@ + JsonArray jsonarray = new JsonArray(); + DateFormat dateformat = createDateFormat(); + +- this.getTopMRUProfiles(1000).forEach((gameprofilecache_gameprofileinfo) -> { +- jsonarray.add(writeGameProfile(gameprofilecache_gameprofileinfo, dateformat)); ++ this.getTopMRUProfiles(1000).forEach((usercache_usercacheentry) -> { ++ jsonarray.add(writeGameProfile(usercache_usercacheentry, dateformat)); + }); + String s = this.gson.toJson(jsonarray); + +@@ -294,22 +293,22 @@ + + } + +- private Stream getTopMRUProfiles(int i) { +- return ImmutableList.copyOf(this.profilesByUUID.values()).stream().sorted(Comparator.comparing(GameProfileCache.GameProfileInfo::getLastAccess).reversed()).limit((long) i); ++ private Stream getTopMRUProfiles(int limit) { ++ return ImmutableList.copyOf(this.profilesByUUID.values()).stream().sorted(Comparator.comparing(GameProfileCache.GameProfileInfo::getLastAccess).reversed()).limit((long) limit); + } + +- private static JsonElement writeGameProfile(GameProfileCache.GameProfileInfo gameprofilecache_gameprofileinfo, DateFormat dateformat) { ++ private static JsonElement writeGameProfile(GameProfileCache.GameProfileInfo profileInfo, DateFormat dateFormat) { + JsonObject jsonobject = new JsonObject(); + +- jsonobject.addProperty("name", gameprofilecache_gameprofileinfo.getProfile().getName()); +- jsonobject.addProperty("uuid", gameprofilecache_gameprofileinfo.getProfile().getId().toString()); +- jsonobject.addProperty("expiresOn", dateformat.format(gameprofilecache_gameprofileinfo.getExpirationDate())); ++ jsonobject.addProperty("name", profileInfo.getProfile().getName()); ++ jsonobject.addProperty("uuid", profileInfo.getProfile().getId().toString()); ++ jsonobject.addProperty("expiresOn", dateFormat.format(profileInfo.getExpirationDate())); + return jsonobject; + } + +- private static Optional readGameProfile(JsonElement jsonelement, DateFormat dateformat) { +- if (jsonelement.isJsonObject()) { +- JsonObject jsonobject = jsonelement.getAsJsonObject(); ++ private static Optional readGameProfile(JsonElement json, DateFormat dateFormat) { ++ if (json.isJsonObject()) { ++ JsonObject jsonobject = json.getAsJsonObject(); + JsonElement jsonelement1 = jsonobject.get("name"); + JsonElement jsonelement2 = jsonobject.get("uuid"); + JsonElement jsonelement3 = jsonobject.get("expiresOn"); +@@ -321,7 +320,7 @@ + + if (jsonelement3 != null) { + try { +- date = dateformat.parse(jsonelement3.getAsString()); ++ date = dateFormat.parse(jsonelement3.getAsString()); + } catch (ParseException parseexception) { + ; + } +@@ -354,9 +353,9 @@ + final Date expirationDate; + private volatile long lastAccess; + +- GameProfileInfo(GameProfile gameprofile, Date date) { +- this.profile = gameprofile; +- this.expirationDate = date; ++ GameProfileInfo(GameProfile profile, Date expirationDate) { ++ this.profile = profile; ++ this.expirationDate = expirationDate; + } + + public GameProfile getProfile() { +@@ -367,8 +366,8 @@ + return this.expirationDate; + } + +- public void setLastAccess(long i) { +- this.lastAccess = i; ++ public void setLastAccess(long lastAccess) { ++ this.lastAccess = lastAccess; + } + + public long getLastAccess() { diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/players/OldUsersConverter.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/players/OldUsersConverter.java.patch new file mode 100644 index 0000000000..a95c085fb3 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/players/OldUsersConverter.java.patch @@ -0,0 +1,470 @@ +--- a/net/minecraft/server/players/OldUsersConverter.java ++++ b/net/minecraft/server/players/OldUsersConverter.java +@@ -21,6 +21,9 @@ + import java.util.UUID; + import javax.annotation.Nullable; + import net.minecraft.core.UUIDUtil; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.NbtAccounter; ++import net.minecraft.nbt.NbtIo; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.dedicated.DedicatedServer; + import net.minecraft.util.StringUtil; +@@ -37,8 +40,8 @@ + + public OldUsersConverter() {} + +- static List readOldListFormat(File file, Map map) throws IOException { +- List list = Files.readLines(file, StandardCharsets.UTF_8); ++ static List readOldListFormat(File inFile, Map read) throws IOException { ++ List list = Files.readLines(inFile, StandardCharsets.UTF_8); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +@@ -48,22 +51,22 @@ + if (!s.startsWith("#") && s.length() >= 1) { + String[] astring = s.split("\\|"); + +- map.put(astring[0].toLowerCase(Locale.ROOT), astring); ++ read.put(astring[0].toLowerCase(Locale.ROOT), astring); + } + } + + return list; + } + +- private static void lookupPlayers(MinecraftServer minecraftserver, Collection collection, ProfileLookupCallback profilelookupcallback) { +- String[] astring = (String[]) collection.stream().filter((s) -> { ++ private static void lookupPlayers(MinecraftServer server, Collection names, ProfileLookupCallback callback) { ++ String[] astring = (String[]) names.stream().filter((s) -> { + return !StringUtil.isNullOrEmpty(s); + }).toArray((i) -> { + return new String[i]; + }); + +- if (minecraftserver.usesAuthentication()) { +- minecraftserver.getProfileRepository().findProfilesByNames(astring, profilelookupcallback); ++ if (server.usesAuthentication()) { ++ server.getProfileRepository().findProfilesByNames(astring, callback); + } else { + String[] astring1 = astring; + int i = astring.length; +@@ -71,21 +74,21 @@ + for (int j = 0; j < i; ++j) { + String s = astring1[j]; + +- profilelookupcallback.onProfileLookupSucceeded(UUIDUtil.createOfflineProfile(s)); ++ callback.onProfileLookupSucceeded(UUIDUtil.createOfflineProfile(s)); + } + } + + } + +- public static boolean convertUserBanlist(final MinecraftServer minecraftserver) { +- final UserBanList userbanlist = new UserBanList(PlayerList.USERBANLIST_FILE); ++ public static boolean convertUserBanlist(final MinecraftServer server) { ++ final UserBanList gameprofilebanlist = new UserBanList(PlayerList.USERBANLIST_FILE); + + if (OldUsersConverter.OLD_USERBANLIST.exists() && OldUsersConverter.OLD_USERBANLIST.isFile()) { +- if (userbanlist.getFile().exists()) { ++ if (gameprofilebanlist.getFile().exists()) { + try { +- userbanlist.load(); ++ gameprofilebanlist.load(); + } catch (IOException ioexception) { +- OldUsersConverter.LOGGER.warn("Could not load existing file {}", userbanlist.getFile().getName(), ioexception); ++ OldUsersConverter.LOGGER.warn("Could not load existing file {}", gameprofilebanlist.getFile().getName()); // CraftBukkit - don't print stacktrace + } + } + +@@ -94,9 +97,8 @@ + + readOldListFormat(OldUsersConverter.OLD_USERBANLIST, map); + ProfileLookupCallback profilelookupcallback = new ProfileLookupCallback() { +- @Override + public void onProfileLookupSucceeded(GameProfile gameprofile) { +- minecraftserver.getProfileCache().add(gameprofile); ++ server.getProfileCache().add(gameprofile); + String[] astring = (String[]) map.get(gameprofile.getName().toLowerCase(Locale.ROOT)); + + if (astring == null) { +@@ -108,11 +110,10 @@ + Date date1 = astring.length > 3 ? OldUsersConverter.parseDate(astring[3], (Date) null) : null; + String s1 = astring.length > 4 ? astring[4] : null; + +- userbanlist.add(new UserBanListEntry(gameprofile, date, s, date1, s1)); ++ gameprofilebanlist.add(new UserBanListEntry(gameprofile, date, s, date1, s1)); + } + } + +- @Override + public void onProfileLookupFailed(String s, Exception exception) { + OldUsersConverter.LOGGER.warn("Could not lookup user banlist entry for {}", s, exception); + if (!(exception instanceof ProfileNotFoundException)) { +@@ -121,15 +122,15 @@ + } + }; + +- lookupPlayers(minecraftserver, map.keySet(), profilelookupcallback); +- userbanlist.save(); ++ lookupPlayers(server, map.keySet(), profilelookupcallback); ++ gameprofilebanlist.save(); + renameOldFile(OldUsersConverter.OLD_USERBANLIST); + return true; + } catch (IOException ioexception1) { + OldUsersConverter.LOGGER.warn("Could not read old user banlist to convert it!", ioexception1); + return false; +- } catch (OldUsersConverter.ConversionError oldusersconverter_conversionerror) { +- OldUsersConverter.LOGGER.error("Conversion failed, please try again later", oldusersconverter_conversionerror); ++ } catch (OldUsersConverter.ConversionError namereferencingfileconverter_fileconversionexception) { ++ OldUsersConverter.LOGGER.error("Conversion failed, please try again later", namereferencingfileconverter_fileconversionexception); + return false; + } + } else { +@@ -137,7 +138,7 @@ + } + } + +- public static boolean convertIpBanlist(MinecraftServer minecraftserver) { ++ public static boolean convertIpBanlist(MinecraftServer server) { + IpBanList ipbanlist = new IpBanList(PlayerList.IPBANLIST_FILE); + + if (OldUsersConverter.OLD_IPBANLIST.exists() && OldUsersConverter.OLD_IPBANLIST.isFile()) { +@@ -145,7 +146,7 @@ + try { + ipbanlist.load(); + } catch (IOException ioexception) { +- OldUsersConverter.LOGGER.warn("Could not load existing file {}", ipbanlist.getFile().getName(), ioexception); ++ OldUsersConverter.LOGGER.warn("Could not load existing file {}", ipbanlist.getFile().getName()); // CraftBukkit - don't print stacktrace + } + } + +@@ -178,28 +179,26 @@ + } + } + +- public static boolean convertOpsList(final MinecraftServer minecraftserver) { +- final ServerOpList serveroplist = new ServerOpList(PlayerList.OPLIST_FILE); ++ public static boolean convertOpsList(final MinecraftServer server) { ++ final ServerOpList oplist = new ServerOpList(PlayerList.OPLIST_FILE); + + if (OldUsersConverter.OLD_OPLIST.exists() && OldUsersConverter.OLD_OPLIST.isFile()) { +- if (serveroplist.getFile().exists()) { ++ if (oplist.getFile().exists()) { + try { +- serveroplist.load(); ++ oplist.load(); + } catch (IOException ioexception) { +- OldUsersConverter.LOGGER.warn("Could not load existing file {}", serveroplist.getFile().getName(), ioexception); ++ OldUsersConverter.LOGGER.warn("Could not load existing file {}", oplist.getFile().getName()); // CraftBukkit - don't print stacktrace + } + } + + try { + List list = Files.readLines(OldUsersConverter.OLD_OPLIST, StandardCharsets.UTF_8); + ProfileLookupCallback profilelookupcallback = new ProfileLookupCallback() { +- @Override + public void onProfileLookupSucceeded(GameProfile gameprofile) { +- minecraftserver.getProfileCache().add(gameprofile); +- serveroplist.add(new ServerOpListEntry(gameprofile, minecraftserver.getOperatorUserPermissionLevel(), false)); ++ server.getProfileCache().add(gameprofile); ++ oplist.add(new ServerOpListEntry(gameprofile, server.getOperatorUserPermissionLevel(), false)); + } + +- @Override + public void onProfileLookupFailed(String s, Exception exception) { + OldUsersConverter.LOGGER.warn("Could not lookup oplist entry for {}", s, exception); + if (!(exception instanceof ProfileNotFoundException)) { +@@ -208,15 +207,15 @@ + } + }; + +- lookupPlayers(minecraftserver, list, profilelookupcallback); +- serveroplist.save(); ++ lookupPlayers(server, list, profilelookupcallback); ++ oplist.save(); + renameOldFile(OldUsersConverter.OLD_OPLIST); + return true; + } catch (IOException ioexception1) { + OldUsersConverter.LOGGER.warn("Could not read old oplist to convert it!", ioexception1); + return false; +- } catch (OldUsersConverter.ConversionError oldusersconverter_conversionerror) { +- OldUsersConverter.LOGGER.error("Conversion failed, please try again later", oldusersconverter_conversionerror); ++ } catch (OldUsersConverter.ConversionError namereferencingfileconverter_fileconversionexception) { ++ OldUsersConverter.LOGGER.error("Conversion failed, please try again later", namereferencingfileconverter_fileconversionexception); + return false; + } + } else { +@@ -224,28 +223,26 @@ + } + } + +- public static boolean convertWhiteList(final MinecraftServer minecraftserver) { +- final UserWhiteList userwhitelist = new UserWhiteList(PlayerList.WHITELIST_FILE); ++ public static boolean convertWhiteList(final MinecraftServer server) { ++ final UserWhiteList whitelist = new UserWhiteList(PlayerList.WHITELIST_FILE); + + if (OldUsersConverter.OLD_WHITELIST.exists() && OldUsersConverter.OLD_WHITELIST.isFile()) { +- if (userwhitelist.getFile().exists()) { ++ if (whitelist.getFile().exists()) { + try { +- userwhitelist.load(); ++ whitelist.load(); + } catch (IOException ioexception) { +- OldUsersConverter.LOGGER.warn("Could not load existing file {}", userwhitelist.getFile().getName(), ioexception); ++ OldUsersConverter.LOGGER.warn("Could not load existing file {}", whitelist.getFile().getName()); // CraftBukkit - don't print stacktrace + } + } + + try { + List list = Files.readLines(OldUsersConverter.OLD_WHITELIST, StandardCharsets.UTF_8); + ProfileLookupCallback profilelookupcallback = new ProfileLookupCallback() { +- @Override + public void onProfileLookupSucceeded(GameProfile gameprofile) { +- minecraftserver.getProfileCache().add(gameprofile); +- userwhitelist.add(new UserWhiteListEntry(gameprofile)); ++ server.getProfileCache().add(gameprofile); ++ whitelist.add(new UserWhiteListEntry(gameprofile)); + } + +- @Override + public void onProfileLookupFailed(String s, Exception exception) { + OldUsersConverter.LOGGER.warn("Could not lookup user whitelist entry for {}", s, exception); + if (!(exception instanceof ProfileNotFoundException)) { +@@ -254,15 +251,15 @@ + } + }; + +- lookupPlayers(minecraftserver, list, profilelookupcallback); +- userwhitelist.save(); ++ lookupPlayers(server, list, profilelookupcallback); ++ whitelist.save(); + renameOldFile(OldUsersConverter.OLD_WHITELIST); + return true; + } catch (IOException ioexception1) { + OldUsersConverter.LOGGER.warn("Could not read old whitelist to convert it!", ioexception1); + return false; +- } catch (OldUsersConverter.ConversionError oldusersconverter_conversionerror) { +- OldUsersConverter.LOGGER.error("Conversion failed, please try again later", oldusersconverter_conversionerror); ++ } catch (OldUsersConverter.ConversionError namereferencingfileconverter_fileconversionexception) { ++ OldUsersConverter.LOGGER.error("Conversion failed, please try again later", namereferencingfileconverter_fileconversionexception); + return false; + } + } else { +@@ -271,43 +268,41 @@ + } + + @Nullable +- public static UUID convertMobOwnerIfNecessary(final MinecraftServer minecraftserver, String s) { +- if (!StringUtil.isNullOrEmpty(s) && s.length() <= 16) { +- Optional optional = minecraftserver.getProfileCache().get(s).map(GameProfile::getId); ++ public static UUID convertMobOwnerIfNecessary(final MinecraftServer server, String username) { ++ if (!StringUtil.isNullOrEmpty(username) && username.length() <= 16) { ++ Optional optional = server.getProfileCache().get(username).map(GameProfile::getId); + + if (optional.isPresent()) { + return (UUID) optional.get(); +- } else if (!minecraftserver.isSingleplayer() && minecraftserver.usesAuthentication()) { ++ } else if (!server.isSingleplayer() && server.usesAuthentication()) { + final List list = Lists.newArrayList(); + ProfileLookupCallback profilelookupcallback = new ProfileLookupCallback() { +- @Override + public void onProfileLookupSucceeded(GameProfile gameprofile) { +- minecraftserver.getProfileCache().add(gameprofile); ++ server.getProfileCache().add(gameprofile); + list.add(gameprofile); + } + +- @Override + public void onProfileLookupFailed(String s1, Exception exception) { + OldUsersConverter.LOGGER.warn("Could not lookup user whitelist entry for {}", s1, exception); + } + }; + +- lookupPlayers(minecraftserver, Lists.newArrayList(new String[]{s}), profilelookupcallback); ++ lookupPlayers(server, Lists.newArrayList(new String[]{username}), profilelookupcallback); + return !list.isEmpty() ? ((GameProfile) list.get(0)).getId() : null; + } else { +- return UUIDUtil.createOfflinePlayerUUID(s); ++ return UUIDUtil.createOfflinePlayerUUID(username); + } + } else { + try { +- return UUID.fromString(s); ++ return UUID.fromString(username); + } catch (IllegalArgumentException illegalargumentexception) { + return null; + } + } + } + +- public static boolean convertPlayers(final DedicatedServer dedicatedserver) { +- final File file = getWorldPlayersDirectory(dedicatedserver); ++ public static boolean convertPlayers(final DedicatedServer server) { ++ final File file = getWorldPlayersDirectory(server); + final File file1 = new File(file.getParentFile(), "playerdata"); + final File file2 = new File(file.getParentFile(), "unknownplayers"); + +@@ -333,15 +328,13 @@ + try { + final String[] astring = (String[]) list.toArray(new String[list.size()]); + ProfileLookupCallback profilelookupcallback = new ProfileLookupCallback() { +- @Override + public void onProfileLookupSucceeded(GameProfile gameprofile) { +- dedicatedserver.getProfileCache().add(gameprofile); ++ server.getProfileCache().add(gameprofile); + UUID uuid = gameprofile.getId(); + + this.movePlayerFile(file1, this.getFileNameForProfile(gameprofile.getName()), uuid.toString()); + } + +- @Override + public void onProfileLookupFailed(String s2, Exception exception) { + OldUsersConverter.LOGGER.warn("Could not lookup user uuid for {}", s2, exception); + if (exception instanceof ProfileNotFoundException) { +@@ -353,13 +346,37 @@ + } + } + +- private void movePlayerFile(File file4, String s2, String s3) { +- File file5 = new File(file, s2 + ".dat"); +- File file6 = new File(file4, s3 + ".dat"); ++ private void movePlayerFile(File file, String oldFileName, String newFileName) { ++ File file5 = new File(file, oldFileName + ".dat"); ++ File file6 = new File(file, newFileName + ".dat"); + +- OldUsersConverter.ensureDirectoryExists(file4); ++ // CraftBukkit start - Use old file name to seed lastKnownName ++ CompoundTag root = null; ++ ++ try { ++ root = NbtIo.readCompressed(new java.io.FileInputStream(file5), NbtAccounter.unlimitedHeap()); ++ } catch (Exception exception) { ++ exception.printStackTrace(); ++ } ++ ++ if (root != null) { ++ if (!root.contains("bukkit")) { ++ root.put("bukkit", new CompoundTag()); ++ } ++ CompoundTag data = root.getCompound("bukkit"); ++ data.putString("lastKnownName", oldFileName); ++ ++ try { ++ NbtIo.writeCompressed(root, new java.io.FileOutputStream(file2)); ++ } catch (Exception exception) { ++ exception.printStackTrace(); ++ } ++ } ++ // CraftBukkit end ++ ++ OldUsersConverter.ensureDirectoryExists(file); + if (!file5.renameTo(file6)) { +- throw new OldUsersConverter.ConversionError("Could not convert file for " + s2); ++ throw new OldUsersConverter.ConversionError("Could not convert file for " + oldFileName); + } + } + +@@ -385,10 +402,10 @@ + } + }; + +- lookupPlayers(dedicatedserver, Lists.newArrayList(astring), profilelookupcallback); ++ lookupPlayers(server, Lists.newArrayList(astring), profilelookupcallback); + return true; +- } catch (OldUsersConverter.ConversionError oldusersconverter_conversionerror) { +- OldUsersConverter.LOGGER.error("Conversion failed, please try again later", oldusersconverter_conversionerror); ++ } catch (OldUsersConverter.ConversionError namereferencingfileconverter_fileconversionexception) { ++ OldUsersConverter.LOGGER.error("Conversion failed, please try again later", namereferencingfileconverter_fileconversionexception); + return false; + } + } else { +@@ -396,20 +413,20 @@ + } + } + +- static void ensureDirectoryExists(File file) { +- if (file.exists()) { +- if (!file.isDirectory()) { +- throw new OldUsersConverter.ConversionError("Can't create directory " + file.getName() + " in world save directory."); ++ static void ensureDirectoryExists(File dir) { ++ if (dir.exists()) { ++ if (!dir.isDirectory()) { ++ throw new OldUsersConverter.ConversionError("Can't create directory " + dir.getName() + " in world save directory."); + } +- } else if (!file.mkdirs()) { +- throw new OldUsersConverter.ConversionError("Can't create directory " + file.getName() + " in world save directory."); ++ } else if (!dir.mkdirs()) { ++ throw new OldUsersConverter.ConversionError("Can't create directory " + dir.getName() + " in world save directory."); + } + } + +- public static boolean serverReadyAfterUserconversion(MinecraftServer minecraftserver) { ++ public static boolean serverReadyAfterUserconversion(MinecraftServer server) { + boolean flag = areOldUserlistsRemoved(); + +- flag = flag && areOldPlayersConverted(minecraftserver); ++ flag = flag && areOldPlayersConverted(server); + return flag; + } + +@@ -463,8 +480,8 @@ + } + } + +- private static boolean areOldPlayersConverted(MinecraftServer minecraftserver) { +- File file = getWorldPlayersDirectory(minecraftserver); ++ private static boolean areOldPlayersConverted(MinecraftServer server) { ++ File file = getWorldPlayersDirectory(server); + + if (file.exists() && file.isDirectory() && (file.list().length > 0 || !file.delete())) { + OldUsersConverter.LOGGER.warn("**** DETECTED OLD PLAYER DIRECTORY IN THE WORLD SAVE"); +@@ -476,23 +493,23 @@ + } + } + +- private static File getWorldPlayersDirectory(MinecraftServer minecraftserver) { +- return minecraftserver.getWorldPath(LevelResource.PLAYER_OLD_DATA_DIR).toFile(); ++ private static File getWorldPlayersDirectory(MinecraftServer server) { ++ return server.getWorldPath(LevelResource.PLAYER_OLD_DATA_DIR).toFile(); + } + +- private static void renameOldFile(File file) { +- File file1 = new File(file.getName() + ".converted"); ++ private static void renameOldFile(File convertedFile) { ++ File file1 = new File(convertedFile.getName() + ".converted"); + +- file.renameTo(file1); ++ convertedFile.renameTo(file1); + } + +- static Date parseDate(String s, Date date) { ++ static Date parseDate(String input, Date defaultValue) { + Date date1; + + try { +- date1 = BanListEntry.DATE_FORMAT.parse(s); ++ date1 = BanListEntry.DATE_FORMAT.parse(input); + } catch (ParseException parseexception) { +- date1 = date; ++ date1 = defaultValue; + } + + return date1; +@@ -500,12 +517,12 @@ + + private static class ConversionError extends RuntimeException { + +- ConversionError(String s, Throwable throwable) { +- super(s, throwable); ++ ConversionError(String message, Throwable cause) { ++ super(message, cause); + } + +- ConversionError(String s) { +- super(s); ++ ConversionError(String message) { ++ super(message); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/players/PlayerList.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/players/PlayerList.java.patch new file mode 100644 index 0000000000..cefa7bbc6a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/players/PlayerList.java.patch @@ -0,0 +1,1533 @@ +--- a/net/minecraft/server/players/PlayerList.java ++++ b/net/minecraft/server/players/PlayerList.java +@@ -74,6 +74,7 @@ + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.network.CommonListenerCookie; + import net.minecraft.server.network.ServerGamePacketListenerImpl; ++import net.minecraft.server.network.ServerLoginPacketListenerImpl; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.ServerStatsCounter; +@@ -84,11 +85,10 @@ + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.border.BorderChangeListener; + import net.minecraft.world.level.border.WorldBorder; + import net.minecraft.world.level.dimension.DimensionType; +@@ -101,6 +101,25 @@ + import net.minecraft.world.scores.PlayerTeam; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.stream.Collectors; ++import net.minecraft.server.dedicated.DedicatedServer; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerChangedWorldEvent; ++import org.bukkit.event.player.PlayerJoinEvent; ++import org.bukkit.event.player.PlayerLoginEvent; ++import org.bukkit.event.player.PlayerQuitEvent; ++import org.bukkit.event.player.PlayerRespawnEvent; ++import org.bukkit.event.player.PlayerRespawnEvent.RespawnReason; ++import org.bukkit.event.player.PlayerSpawnChangeEvent; ++// CraftBukkit end ++ + public abstract class PlayerList { + + public static final File USERBANLIST_FILE = new File("banned-players.json"); +@@ -113,140 +132,216 @@ + private static final int SEND_PLAYER_INFO_INTERVAL = 600; + private static final SimpleDateFormat BAN_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z"); + private final MinecraftServer server; +- private final List players = Lists.newArrayList(); ++ public final List players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety + private final Map playersByUUID = Maps.newHashMap(); + private final UserBanList bans; + private final IpBanList ipBans; + private final ServerOpList ops; + private final UserWhiteList whitelist; +- private final Map stats; +- private final Map advancements; +- private final PlayerDataStorage playerIo; ++ // CraftBukkit start ++ // private final Map stats; ++ // private final Map advancements; ++ // CraftBukkit end ++ public final PlayerDataStorage playerIo; + private boolean doWhiteList; + private final LayeredRegistryAccess registries; +- protected final int maxPlayers; ++ public int maxPlayers; + private int viewDistance; + private int simulationDistance; + private boolean allowCheatsForAllPlayers; + private static final boolean ALLOW_LOGOUTIVATOR = false; + private int sendAllPlayerInfoIn; + +- public PlayerList(MinecraftServer minecraftserver, LayeredRegistryAccess layeredregistryaccess, PlayerDataStorage playerdatastorage, int i) { ++ // CraftBukkit start ++ private CraftServer cserver; ++ ++ public PlayerList(MinecraftServer server, LayeredRegistryAccess registries, PlayerDataStorage playerIo, int maxPlayers) { ++ this.cserver = server.server = new CraftServer((DedicatedServer) server, this); ++ server.console = org.bukkit.craftbukkit.command.ColouredConsoleSender.getInstance(); ++ server.reader.addCompleter(new org.bukkit.craftbukkit.command.ConsoleCommandCompleter(server.server)); ++ // CraftBukkit end ++ + this.bans = new UserBanList(PlayerList.USERBANLIST_FILE); + this.ipBans = new IpBanList(PlayerList.IPBANLIST_FILE); + this.ops = new ServerOpList(PlayerList.OPLIST_FILE); + this.whitelist = new UserWhiteList(PlayerList.WHITELIST_FILE); +- this.stats = Maps.newHashMap(); +- this.advancements = Maps.newHashMap(); +- this.server = minecraftserver; +- this.registries = layeredregistryaccess; +- this.maxPlayers = i; +- this.playerIo = playerdatastorage; ++ // CraftBukkit start ++ // this.stats = Maps.newHashMap(); ++ // this.advancements = Maps.newHashMap(); ++ // CraftBukkit end ++ this.server = server; ++ this.registries = registries; ++ this.maxPlayers = maxPlayers; ++ this.playerIo = playerIo; + } + +- public void placeNewPlayer(Connection connection, ServerPlayer serverplayer, CommonListenerCookie commonlistenercookie) { +- GameProfile gameprofile = serverplayer.getGameProfile(); +- GameProfileCache gameprofilecache = this.server.getProfileCache(); ++ public void placeNewPlayer(Connection networkmanager, ServerPlayer entityplayer, CommonListenerCookie commonlistenercookie) { ++ GameProfile gameprofile = entityplayer.getGameProfile(); ++ GameProfileCache usercache = this.server.getProfileCache(); + String s; + +- if (gameprofilecache != null) { +- Optional optional = gameprofilecache.get(gameprofile.getId()); ++ if (usercache != null) { ++ Optional optional = usercache.get(gameprofile.getId()); + + s = (String) optional.map(GameProfile::getName).orElse(gameprofile.getName()); +- gameprofilecache.add(gameprofile); ++ usercache.add(gameprofile); + } else { + s = gameprofile.getName(); + } + +- CompoundTag compoundtag = this.load(serverplayer); ++ CompoundTag nbttagcompound = this.load(entityplayer); + ResourceKey resourcekey; ++ // CraftBukkit start - Better rename detection ++ if (nbttagcompound != null && nbttagcompound.contains("bukkit")) { ++ CompoundTag bukkit = nbttagcompound.getCompound("bukkit"); ++ s = bukkit.contains("lastKnownName", 8) ? bukkit.getString("lastKnownName") : s; ++ } ++ // CraftBukkit end + +- if (compoundtag != null) { +- DataResult dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, compoundtag.get("Dimension"))); ++ if (nbttagcompound != null) { ++ DataResult> dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, nbttagcompound.get("Dimension"))); // CraftBukkit - decompile error + Logger logger = PlayerList.LOGGER; + + Objects.requireNonNull(logger); +- resourcekey = (ResourceKey) dataresult.resultOrPartial(logger::error).orElse(Level.OVERWORLD); ++ resourcekey = (ResourceKey) dataresult.resultOrPartial(logger::error).orElse(entityplayer.serverLevel().dimension()); // CraftBukkit - SPIGOT-7507: If no dimension, fall back to existing dimension loaded from "WorldUUID", which in turn defaults to World.OVERWORLD + } else { +- resourcekey = Level.OVERWORLD; ++ resourcekey = entityplayer.serverLevel().dimension(); // CraftBukkit - SPIGOT-7507: If no dimension, fall back to existing dimension loaded from "WorldUUID", which in turn defaults to World.OVERWORLD + } + + ResourceKey resourcekey1 = resourcekey; +- ServerLevel serverlevel = this.server.getLevel(resourcekey1); +- ServerLevel serverlevel1; ++ ServerLevel worldserver = this.server.getLevel(resourcekey1); ++ ServerLevel worldserver1; + +- if (serverlevel == null) { ++ if (worldserver == null) { + PlayerList.LOGGER.warn("Unknown respawn dimension {}, defaulting to overworld", resourcekey1); +- serverlevel1 = this.server.overworld(); ++ worldserver1 = this.server.overworld(); + } else { +- serverlevel1 = serverlevel; ++ worldserver1 = worldserver; + } + +- serverplayer.setServerLevel(serverlevel1); +- String s1 = connection.getLoggableAddress(this.server.logIPs()); ++ entityplayer.setServerLevel(worldserver1); ++ String s1 = networkmanager.getLoggableAddress(this.server.logIPs()); + +- PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ({}, {}, {})", new Object[]{serverplayer.getName().getString(), s1, serverplayer.getId(), serverplayer.getX(), serverplayer.getY(), serverplayer.getZ()}); +- LevelData leveldata = serverlevel1.getLevelData(); ++ // CraftBukkit - Moved message to after join ++ // PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ({}, {}, {})", new Object[]{entityplayer.getName().getString(), s1, entityplayer.getId(), entityplayer.getX(), entityplayer.getY(), entityplayer.getZ()}); ++ LevelData worlddata = worldserver1.getLevelData(); + +- serverplayer.loadGameTypes(compoundtag); +- ServerGamePacketListenerImpl servergamepacketlistenerimpl = new ServerGamePacketListenerImpl(this.server, connection, serverplayer, commonlistenercookie); +- GameRules gamerules = serverlevel1.getGameRules(); ++ entityplayer.loadGameTypes(nbttagcompound); ++ ServerGamePacketListenerImpl playerconnection = new ServerGamePacketListenerImpl(this.server, networkmanager, entityplayer, commonlistenercookie); ++ GameRules gamerules = worldserver1.getGameRules(); + boolean flag = gamerules.getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN); + boolean flag1 = gamerules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO); + boolean flag2 = gamerules.getBoolean(GameRules.RULE_LIMITED_CRAFTING); + +- servergamepacketlistenerimpl.send(new ClientboundLoginPacket(serverplayer.getId(), leveldata.isHardcore(), this.server.levelKeys(), this.getMaxPlayers(), this.viewDistance, this.simulationDistance, flag1, !flag, flag2, serverplayer.createCommonSpawnInfo(serverlevel1))); +- servergamepacketlistenerimpl.send(new ClientboundChangeDifficultyPacket(leveldata.getDifficulty(), leveldata.isDifficultyLocked())); +- servergamepacketlistenerimpl.send(new ClientboundPlayerAbilitiesPacket(serverplayer.getAbilities())); +- servergamepacketlistenerimpl.send(new ClientboundSetCarriedItemPacket(serverplayer.getInventory().selected)); +- servergamepacketlistenerimpl.send(new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes())); +- this.sendPlayerPermissionLevel(serverplayer); +- serverplayer.getStats().markAllDirty(); +- serverplayer.getRecipeBook().sendInitialRecipeBook(serverplayer); +- this.updateEntireScoreboard(serverlevel1.getScoreboard(), serverplayer); ++ playerconnection.send(new ClientboundLoginPacket(entityplayer.getId(), worlddata.isHardcore(), this.server.levelKeys(), this.getMaxPlayers(), this.viewDistance, this.simulationDistance, flag1, !flag, flag2, entityplayer.createCommonSpawnInfo(worldserver1))); ++ entityplayer.getBukkitEntity().sendSupportedChannels(); // CraftBukkit ++ playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); ++ playerconnection.send(new ClientboundPlayerAbilitiesPacket(entityplayer.getAbilities())); ++ playerconnection.send(new ClientboundSetCarriedItemPacket(entityplayer.getInventory().selected)); ++ playerconnection.send(new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes())); ++ this.sendPlayerPermissionLevel(entityplayer); ++ entityplayer.getStats().markAllDirty(); ++ entityplayer.getRecipeBook().sendInitialRecipeBook(entityplayer); ++ this.updateEntireScoreboard(worldserver1.getScoreboard(), entityplayer); + this.server.invalidateStatus(); +- MutableComponent mutablecomponent; ++ MutableComponent ichatmutablecomponent; + +- if (serverplayer.getGameProfile().getName().equalsIgnoreCase(s)) { +- mutablecomponent = Component.translatable("multiplayer.player.joined", serverplayer.getDisplayName()); ++ if (entityplayer.getGameProfile().getName().equalsIgnoreCase(s)) { ++ ichatmutablecomponent = Component.translatable("multiplayer.player.joined", entityplayer.getDisplayName()); + } else { +- mutablecomponent = Component.translatable("multiplayer.player.joined.renamed", serverplayer.getDisplayName(), s); ++ ichatmutablecomponent = Component.translatable("multiplayer.player.joined.renamed", entityplayer.getDisplayName(), s); + } ++ // CraftBukkit start ++ ichatmutablecomponent.withStyle(ChatFormatting.YELLOW); ++ String joinMessage = CraftChatMessage.fromComponent(ichatmutablecomponent); + +- this.broadcastSystemMessage(mutablecomponent.withStyle(ChatFormatting.YELLOW), false); +- servergamepacketlistenerimpl.teleport(serverplayer.getX(), serverplayer.getY(), serverplayer.getZ(), serverplayer.getYRot(), serverplayer.getXRot()); +- ServerStatus serverstatus = this.server.getStatus(); ++ playerconnection.teleport(entityplayer.getX(), entityplayer.getY(), entityplayer.getZ(), entityplayer.getYRot(), entityplayer.getXRot()); ++ ServerStatus serverping = this.server.getStatus(); + +- if (serverstatus != null) { +- serverplayer.sendServerStatus(serverstatus); ++ if (serverping != null) { ++ entityplayer.sendServerStatus(serverping); + } + +- serverplayer.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); +- this.players.add(serverplayer); +- this.playersByUUID.put(serverplayer.getUUID(), serverplayer); +- this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(serverplayer))); +- this.sendLevelInfo(serverplayer, serverlevel1); +- serverlevel1.addNewPlayer(serverplayer); +- this.server.getCustomBossEvents().onPlayerConnect(serverplayer); +- Iterator iterator = serverplayer.getActiveEffects().iterator(); ++ // entityplayer.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below ++ this.players.add(entityplayer); ++ this.playersByUUID.put(entityplayer.getUUID(), entityplayer); ++ // this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer))); // CraftBukkit - replaced with loop below + ++ // CraftBukkit start ++ CraftPlayer bukkitPlayer = entityplayer.getBukkitEntity(); ++ ++ // Ensure that player inventory is populated with its viewer ++ entityplayer.containerMenu.transferTo(entityplayer.containerMenu, bukkitPlayer); ++ ++ PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(bukkitPlayer, joinMessage); ++ cserver.getPluginManager().callEvent(playerJoinEvent); ++ ++ if (!entityplayer.connection.isAcceptingMessages()) { ++ return; ++ } ++ ++ joinMessage = playerJoinEvent.getJoinMessage(); ++ ++ if (joinMessage != null && joinMessage.length() > 0) { ++ for (Component line : org.bukkit.craftbukkit.util.CraftChatMessage.fromString(joinMessage)) { ++ server.getPlayerList().broadcastSystemMessage(line, false); ++ } ++ } ++ // CraftBukkit end ++ ++ // CraftBukkit start - sendAll above replaced with this loop ++ ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer)); ++ ++ for (int i = 0; i < this.players.size(); ++i) { ++ ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i); ++ ++ if (entityplayer1.getBukkitEntity().canSee(bukkitPlayer)) { ++ entityplayer1.connection.send(packet); ++ } ++ ++ if (!bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { ++ continue; ++ } ++ ++ entityplayer.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer1))); ++ } ++ entityplayer.sentListPacket = true; ++ // CraftBukkit end ++ ++ entityplayer.getEntityData().refresh(entityplayer); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn ++ ++ this.sendLevelInfo(entityplayer, worldserver1); ++ ++ // CraftBukkit start - Only add if the player wasn't moved in the event ++ if (entityplayer.level() == worldserver1 && !worldserver1.players().contains(entityplayer)) { ++ worldserver1.addNewPlayer(entityplayer); ++ this.server.getCustomBossEvents().onPlayerConnect(entityplayer); ++ } ++ ++ worldserver1 = entityplayer.serverLevel(); // CraftBukkit - Update in case join event changed it ++ // CraftBukkit end ++ Iterator iterator = entityplayer.getActiveEffects().iterator(); ++ + while (iterator.hasNext()) { +- MobEffectInstance mobeffectinstance = (MobEffectInstance) iterator.next(); ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); + +- servergamepacketlistenerimpl.send(new ClientboundUpdateMobEffectPacket(serverplayer.getId(), mobeffectinstance)); ++ playerconnection.send(new ClientboundUpdateMobEffectPacket(entityplayer.getId(), mobeffect)); + } + +- if (compoundtag != null && compoundtag.contains("RootVehicle", 10)) { +- CompoundTag compoundtag1 = compoundtag.getCompound("RootVehicle"); +- Entity entity = EntityType.loadEntityRecursive(compoundtag1.getCompound("Entity"), serverlevel1, (entity1) -> { +- return !serverlevel1.addWithUUID(entity1) ? null : entity1; ++ if (nbttagcompound != null && nbttagcompound.contains("RootVehicle", 10)) { ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("RootVehicle"); ++ // CraftBukkit start ++ ServerLevel finalWorldServer = worldserver1; ++ Entity entity = EntityType.loadEntityRecursive(nbttagcompound1.getCompound("Entity"), finalWorldServer, (entity1) -> { ++ return !finalWorldServer.addWithUUID(entity1) ? null : entity1; ++ // CraftBukkit end + }); + + if (entity != null) { + UUID uuid; + +- if (compoundtag1.hasUUID("Attach")) { +- uuid = compoundtag1.getUUID("Attach"); ++ if (nbttagcompound1.hasUUID("Attach")) { ++ uuid = nbttagcompound1.getUUID("Attach"); + } else { + uuid = null; + } +@@ -255,20 +350,20 @@ + Entity entity1; + + if (entity.getUUID().equals(uuid)) { +- serverplayer.startRiding(entity, true); ++ entityplayer.startRiding(entity, true); + } else { + iterator1 = entity.getIndirectPassengers().iterator(); + + while (iterator1.hasNext()) { + entity1 = (Entity) iterator1.next(); + if (entity1.getUUID().equals(uuid)) { +- serverplayer.startRiding(entity1, true); ++ entityplayer.startRiding(entity1, true); + break; + } + } + } + +- if (!serverplayer.isPassenger()) { ++ if (!entityplayer.isPassenger()) { + PlayerList.LOGGER.warn("Couldn't reattach entity to player"); + entity.discard(); + iterator1 = entity.getIndirectPassengers().iterator(); +@@ -281,17 +376,19 @@ + } + } + +- serverplayer.initInventoryMenu(); ++ entityplayer.initInventoryMenu(); ++ // CraftBukkit - Moved from above, added world ++ PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", entityplayer.getName().getString(), s1, entityplayer.getId(), worldserver1.serverLevelData.getLevelName(), entityplayer.getX(), entityplayer.getY(), entityplayer.getZ()); + } + +- protected void updateEntireScoreboard(ServerScoreboard serverscoreboard, ServerPlayer serverplayer) { ++ public void updateEntireScoreboard(ServerScoreboard scoreboard, ServerPlayer player) { + Set set = Sets.newHashSet(); +- Iterator iterator = serverscoreboard.getPlayerTeams().iterator(); ++ Iterator iterator = scoreboard.getPlayerTeams().iterator(); + + while (iterator.hasNext()) { +- PlayerTeam playerteam = (PlayerTeam) iterator.next(); ++ PlayerTeam scoreboardteam = (PlayerTeam) iterator.next(); + +- serverplayer.connection.send(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerteam, true)); ++ player.connection.send(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(scoreboardteam, true)); + } + + DisplaySlot[] adisplayslot = DisplaySlot.values(); +@@ -299,285 +396,445 @@ + + for (int j = 0; j < i; ++j) { + DisplaySlot displayslot = adisplayslot[j]; +- Objective objective = serverscoreboard.getDisplayObjective(displayslot); ++ Objective scoreboardobjective = scoreboard.getDisplayObjective(displayslot); + +- if (objective != null && !set.contains(objective)) { +- List> list = serverscoreboard.getStartTrackingPackets(objective); ++ if (scoreboardobjective != null && !set.contains(scoreboardobjective)) { ++ List> list = scoreboard.getStartTrackingPackets(scoreboardobjective); + Iterator iterator1 = list.iterator(); + + while (iterator1.hasNext()) { + Packet packet = (Packet) iterator1.next(); + +- serverplayer.connection.send(packet); ++ player.connection.send(packet); + } + +- set.add(objective); ++ set.add(scoreboardobjective); + } + } + + } + +- public void addWorldborderListener(ServerLevel serverlevel) { +- serverlevel.getWorldBorder().addListener(new BorderChangeListener() { ++ public void addWorldborderListener(ServerLevel level) { ++ if (playerIo != null) return; // CraftBukkit ++ level.getWorldBorder().addListener(new BorderChangeListener() { + @Override +- @Override +- public void onBorderSizeSet(WorldBorder worldborder, double d0) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderSizePacket(worldborder)); ++ public void onBorderSizeSet(WorldBorder border, double size) { ++ PlayerList.this.broadcastAll(new ClientboundSetBorderSizePacket(border), border.world); // CraftBukkit + } + + @Override +- @Override +- public void onBorderSizeLerping(WorldBorder worldborder, double d0, double d1, long i) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderLerpSizePacket(worldborder)); ++ public void onBorderSizeLerping(WorldBorder border, double oldSize, double d1, long newSize) { ++ PlayerList.this.broadcastAll(new ClientboundSetBorderLerpSizePacket(border), border.world); // CraftBukkit + } + + @Override +- @Override +- public void onBorderCenterSet(WorldBorder worldborder, double d0, double d1) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderCenterPacket(worldborder)); ++ public void onBorderCenterSet(WorldBorder border, double x, double d1) { ++ PlayerList.this.broadcastAll(new ClientboundSetBorderCenterPacket(border), border.world); // CraftBukkit + } + + @Override +- @Override +- public void onBorderSetWarningTime(WorldBorder worldborder, int i) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDelayPacket(worldborder)); ++ public void onBorderSetWarningTime(WorldBorder border, int warningTime) { ++ PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDelayPacket(border), border.world); // CraftBukkit + } + + @Override +- @Override +- public void onBorderSetWarningBlocks(WorldBorder worldborder, int i) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDistancePacket(worldborder)); ++ public void onBorderSetWarningBlocks(WorldBorder border, int warningBlocks) { ++ PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDistancePacket(border), border.world); // CraftBukkit + } + + @Override +- @Override +- public void onBorderSetDamagePerBlock(WorldBorder worldborder, double d0) {} ++ public void onBorderSetDamagePerBlock(WorldBorder border, double damagePerBlock) {} + + @Override +- @Override +- public void onBorderSetDamageSafeZOne(WorldBorder worldborder, double d0) {} ++ public void onBorderSetDamageSafeZOne(WorldBorder border, double damageSafeZone) {} + }); + } + + @Nullable +- public CompoundTag load(ServerPlayer serverplayer) { +- CompoundTag compoundtag = this.server.getWorldData().getLoadedPlayerTag(); +- CompoundTag compoundtag1; ++ public CompoundTag load(ServerPlayer player) { ++ CompoundTag nbttagcompound = this.server.getWorldData().getLoadedPlayerTag(); ++ CompoundTag nbttagcompound1; + +- if (this.server.isSingleplayerOwner(serverplayer.getGameProfile()) && compoundtag != null) { +- compoundtag1 = compoundtag; +- serverplayer.load(compoundtag); ++ if (this.server.isSingleplayerOwner(player.getGameProfile()) && nbttagcompound != null) { ++ nbttagcompound1 = nbttagcompound; ++ player.load(nbttagcompound); + PlayerList.LOGGER.debug("loading single player"); + } else { +- compoundtag1 = this.playerIo.load(serverplayer); ++ nbttagcompound1 = this.playerIo.load(player); + } + +- return compoundtag1; ++ return nbttagcompound1; + } + +- protected void save(ServerPlayer serverplayer) { +- this.playerIo.save(serverplayer); +- ServerStatsCounter serverstatscounter = (ServerStatsCounter) this.stats.get(serverplayer.getUUID()); ++ protected void save(ServerPlayer player) { ++ if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit ++ this.playerIo.save(player); ++ ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit + +- if (serverstatscounter != null) { +- serverstatscounter.save(); ++ if (serverstatisticmanager != null) { ++ serverstatisticmanager.save(); + } + +- PlayerAdvancements playeradvancements = (PlayerAdvancements) this.advancements.get(serverplayer.getUUID()); ++ PlayerAdvancements advancementdataplayer = (PlayerAdvancements) player.getAdvancements(); // CraftBukkit + +- if (playeradvancements != null) { +- playeradvancements.save(); ++ if (advancementdataplayer != null) { ++ advancementdataplayer.save(); + } + + } + +- public void remove(ServerPlayer serverplayer) { +- ServerLevel serverlevel = serverplayer.serverLevel(); ++ public String remove(ServerPlayer entityplayer) { // CraftBukkit - return string ++ ServerLevel worldserver = entityplayer.serverLevel(); + +- serverplayer.awardStat(Stats.LEAVE_GAME); +- this.save(serverplayer); +- if (serverplayer.isPassenger()) { +- Entity entity = serverplayer.getRootVehicle(); ++ entityplayer.awardStat(Stats.LEAVE_GAME); + ++ // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it ++ // See SPIGOT-5799, SPIGOT-6145 ++ if (entityplayer.containerMenu != entityplayer.inventoryMenu) { ++ entityplayer.closeContainer(); ++ } ++ ++ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(entityplayer.getBukkitEntity(), entityplayer.kickLeaveMessage != null ? entityplayer.kickLeaveMessage : "\u00A7e" + entityplayer.getScoreboardName() + " left the game"); ++ cserver.getPluginManager().callEvent(playerQuitEvent); ++ entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); ++ ++ entityplayer.doTick(); // SPIGOT-924 ++ // CraftBukkit end ++ ++ this.save(entityplayer); ++ if (entityplayer.isPassenger()) { ++ Entity entity = entityplayer.getRootVehicle(); ++ + if (entity.hasExactlyOnePlayerPassenger()) { + PlayerList.LOGGER.debug("Removing player mount"); +- serverplayer.stopRiding(); ++ entityplayer.stopRiding(); + entity.getPassengersAndSelf().forEach((entity1) -> { + entity1.setRemoved(Entity.RemovalReason.UNLOADED_WITH_PLAYER); + }); + } + } + +- serverplayer.unRide(); +- serverlevel.removePlayerImmediately(serverplayer, Entity.RemovalReason.UNLOADED_WITH_PLAYER); +- serverplayer.getAdvancements().stopListening(); +- this.players.remove(serverplayer); +- this.server.getCustomBossEvents().onPlayerDisconnect(serverplayer); +- UUID uuid = serverplayer.getUUID(); +- ServerPlayer serverplayer1 = (ServerPlayer) this.playersByUUID.get(uuid); ++ entityplayer.unRide(); ++ worldserver.removePlayerImmediately(entityplayer, Entity.RemovalReason.UNLOADED_WITH_PLAYER); ++ entityplayer.getAdvancements().stopListening(); ++ this.players.remove(entityplayer); ++ this.server.getCustomBossEvents().onPlayerDisconnect(entityplayer); ++ UUID uuid = entityplayer.getUUID(); ++ ServerPlayer entityplayer1 = (ServerPlayer) this.playersByUUID.get(uuid); + +- if (serverplayer1 == serverplayer) { ++ if (entityplayer1 == entityplayer) { + this.playersByUUID.remove(uuid); +- this.stats.remove(uuid); +- this.advancements.remove(uuid); ++ // CraftBukkit start ++ // this.stats.remove(uuid); ++ // this.advancements.remove(uuid); ++ // CraftBukkit end + } + +- this.broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(serverplayer.getUUID()))); ++ // CraftBukkit start ++ // this.broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID()))); ++ ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID())); ++ for (int i = 0; i < players.size(); i++) { ++ ServerPlayer entityplayer2 = (ServerPlayer) this.players.get(i); ++ ++ if (entityplayer2.getBukkitEntity().canSee(entityplayer.getBukkitEntity())) { ++ entityplayer2.connection.send(packet); ++ } else { ++ entityplayer2.getBukkitEntity().onEntityRemove(entityplayer); ++ } ++ } ++ // This removes the scoreboard (and player reference) for the specific player in the manager ++ cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); ++ // CraftBukkit end ++ ++ return playerQuitEvent.getQuitMessage(); // CraftBukkit + } + +- @Nullable +- public Component canPlayerLogin(SocketAddress socketaddress, GameProfile gameprofile) { +- MutableComponent mutablecomponent; ++ // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer ++ public ServerPlayer canPlayerLogin(ServerLoginPacketListenerImpl loginlistener, GameProfile gameprofile) { ++ MutableComponent ichatmutablecomponent; + +- if (this.bans.isBanned(gameprofile)) { +- UserBanListEntry userbanlistentry = (UserBanListEntry) this.bans.get(gameprofile); ++ // Moved from processLogin ++ UUID uuid = gameprofile.getId(); ++ List list = Lists.newArrayList(); + +- mutablecomponent = Component.translatable("multiplayer.disconnect.banned.reason", userbanlistentry.getReason()); +- if (userbanlistentry.getExpires() != null) { +- mutablecomponent.append((Component) Component.translatable("multiplayer.disconnect.banned.expiration", PlayerList.BAN_DATE_FORMAT.format(userbanlistentry.getExpires()))); ++ ServerPlayer entityplayer; ++ ++ for (int i = 0; i < this.players.size(); ++i) { ++ entityplayer = (ServerPlayer) this.players.get(i); ++ if (entityplayer.getUUID().equals(uuid)) { ++ list.add(entityplayer); + } ++ } + +- return mutablecomponent; ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ entityplayer = (ServerPlayer) iterator.next(); ++ save(entityplayer); // CraftBukkit - Force the player's inventory to be saved ++ entityplayer.connection.disconnect(Component.translatable("multiplayer.disconnect.duplicate_login")); ++ } ++ ++ // Instead of kicking then returning, we need to store the kick reason ++ // in the event, check with plugins to see if it's ok, and THEN kick ++ // depending on the outcome. ++ SocketAddress socketaddress = loginlistener.connection.getRemoteAddress(); ++ ++ ServerPlayer entity = new ServerPlayer(this.server, this.server.getLevel(Level.OVERWORLD), gameprofile, ClientInformation.createDefault()); ++ Player player = entity.getBukkitEntity(); ++ PlayerLoginEvent event = new PlayerLoginEvent(player, loginlistener.connection.hostname, ((java.net.InetSocketAddress) socketaddress).getAddress()); ++ ++ if (getBans().isBanned(gameprofile) && !getBans().get(gameprofile).hasExpired()) { ++ UserBanListEntry gameprofilebanentry = (UserBanListEntry) this.bans.get(gameprofile); ++ ++ ichatmutablecomponent = Component.translatable("multiplayer.disconnect.banned.reason", gameprofilebanentry.getReason()); ++ if (gameprofilebanentry.getExpires() != null) { ++ ichatmutablecomponent.append((Component) Component.translatable("multiplayer.disconnect.banned.expiration", PlayerList.BAN_DATE_FORMAT.format(gameprofilebanentry.getExpires()))); ++ } ++ ++ // return chatmessage; ++ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(ichatmutablecomponent)); + } else if (!this.isWhiteListed(gameprofile)) { +- return Component.translatable("multiplayer.disconnect.not_whitelisted"); +- } else if (this.ipBans.isBanned(socketaddress)) { +- IpBanListEntry ipbanlistentry = this.ipBans.get(socketaddress); ++ ichatmutablecomponent = Component.translatable("multiplayer.disconnect.not_whitelisted"); ++ event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, CraftChatMessage.fromComponent(ichatmutablecomponent)); ++ } else if (getIpBans().isBanned(socketaddress) && !getIpBans().get(socketaddress).hasExpired()) { ++ IpBanListEntry ipbanentry = this.ipBans.get(socketaddress); + +- mutablecomponent = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipbanlistentry.getReason()); +- if (ipbanlistentry.getExpires() != null) { +- mutablecomponent.append((Component) Component.translatable("multiplayer.disconnect.banned_ip.expiration", PlayerList.BAN_DATE_FORMAT.format(ipbanlistentry.getExpires()))); ++ ichatmutablecomponent = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipbanentry.getReason()); ++ if (ipbanentry.getExpires() != null) { ++ ichatmutablecomponent.append((Component) Component.translatable("multiplayer.disconnect.banned_ip.expiration", PlayerList.BAN_DATE_FORMAT.format(ipbanentry.getExpires()))); + } + +- return mutablecomponent; ++ // return chatmessage; ++ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(ichatmutablecomponent)); + } else { +- return this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile) ? Component.translatable("multiplayer.disconnect.server_full") : null; ++ // return this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile) ? IChatBaseComponent.translatable("multiplayer.disconnect.server_full") : null; ++ if (this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile)) { ++ event.disallow(PlayerLoginEvent.Result.KICK_FULL, "The server is full"); ++ } + } ++ ++ cserver.getPluginManager().callEvent(event); ++ if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) { ++ loginlistener.disconnect(event.getKickMessage()); ++ return null; ++ } ++ return entity; + } + +- public ServerPlayer getPlayerForLogin(GameProfile gameprofile, ClientInformation clientinformation) { +- return new ServerPlayer(this.server, this.server.overworld(), gameprofile, clientinformation); ++ // CraftBukkit start - added EntityPlayer ++ public ServerPlayer getPlayerForLogin(GameProfile gameprofile, ClientInformation clientinformation, ServerPlayer player) { ++ player.updateOptions(clientinformation); ++ return player; ++ // CraftBukkit end + } + +- public boolean disconnectAllPlayersWithProfile(GameProfile gameprofile) { ++ public boolean disconnectAllPlayersWithProfile(GameProfile gameprofile, ServerPlayer player) { // CraftBukkit - added EntityPlayer ++ /* CraftBukkit startMoved up + UUID uuid = gameprofile.getId(); +- Set set = Sets.newIdentityHashSet(); ++ Set set = Sets.newIdentityHashSet(); + Iterator iterator = this.players.iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ EntityPlayer entityplayer = (EntityPlayer) iterator.next(); + +- if (serverplayer.getUUID().equals(uuid)) { +- set.add(serverplayer); ++ if (entityplayer.getUUID().equals(uuid)) { ++ set.add(entityplayer); + } + } + +- ServerPlayer serverplayer1 = (ServerPlayer) this.playersByUUID.get(gameprofile.getId()); ++ EntityPlayer entityplayer1 = (EntityPlayer) this.playersByUUID.get(gameprofile.getId()); + +- if (serverplayer1 != null) { +- set.add(serverplayer1); ++ if (entityplayer1 != null) { ++ set.add(entityplayer1); + } + + Iterator iterator1 = set.iterator(); + + while (iterator1.hasNext()) { +- ServerPlayer serverplayer2 = (ServerPlayer) iterator1.next(); ++ EntityPlayer entityplayer2 = (EntityPlayer) iterator1.next(); + +- serverplayer2.connection.disconnect(PlayerList.DUPLICATE_LOGIN_DISCONNECT_MESSAGE); ++ entityplayer2.connection.disconnect(PlayerList.DUPLICATE_LOGIN_DISCONNECT_MESSAGE); + } + + return !set.isEmpty(); ++ */ ++ return player == null; ++ // CraftBukkit end + } + +- public ServerPlayer respawn(ServerPlayer serverplayer, boolean flag) { +- this.players.remove(serverplayer); +- serverplayer.serverLevel().removePlayerImmediately(serverplayer, Entity.RemovalReason.DISCARDED); +- BlockPos blockpos = serverplayer.getRespawnPosition(); +- float f = serverplayer.getRespawnAngle(); +- boolean flag1 = serverplayer.isRespawnForced(); +- ServerLevel serverlevel = this.server.getLevel(serverplayer.getRespawnDimension()); ++ // CraftBukkit start ++ public ServerPlayer respawn(ServerPlayer entityplayer, boolean flag, RespawnReason reason) { ++ return this.respawn(entityplayer, this.server.getLevel(entityplayer.getRespawnDimension()), flag, null, true, reason); ++ } ++ ++ public ServerPlayer respawn(ServerPlayer entityplayer, ServerLevel worldserver, boolean flag, Location location, boolean avoidSuffocation, RespawnReason reason) { ++ entityplayer.stopRiding(); // CraftBukkit ++ this.players.remove(entityplayer); ++ entityplayer.serverLevel().removePlayerImmediately(entityplayer, Entity.RemovalReason.DISCARDED); ++ BlockPos blockposition = entityplayer.getRespawnPosition(); ++ float f = entityplayer.getRespawnAngle(); ++ boolean flag1 = entityplayer.isRespawnForced(); ++ /* CraftBukkit start ++ WorldServer worldserver = this.server.getLevel(entityplayer.getRespawnDimension()); + Optional optional; + +- if (serverlevel != null && blockpos != null) { +- optional = Player.findRespawnPositionAndUseSpawnBlock(serverlevel, blockpos, f, flag1, flag); ++ if (worldserver != null && blockposition != null) { ++ optional = EntityHuman.findRespawnPositionAndUseSpawnBlock(worldserver, blockposition, f, flag1, flag); + } else { + optional = Optional.empty(); + } + +- ServerLevel serverlevel1 = serverlevel != null && optional.isPresent() ? serverlevel : this.server.overworld(); +- ServerPlayer serverplayer1 = new ServerPlayer(this.server, serverlevel1, serverplayer.getGameProfile(), serverplayer.clientInformation()); ++ WorldServer worldserver1 = worldserver != null && optional.isPresent() ? worldserver : this.server.overworld(); ++ EntityPlayer entityplayer1 = new EntityPlayer(this.server, worldserver1, entityplayer.getGameProfile(), entityplayer.clientInformation()); ++ // */ ++ ServerPlayer entityplayer1 = entityplayer; ++ org.bukkit.World fromWorld = entityplayer.getBukkitEntity().getWorld(); ++ entityplayer.wonGame = false; ++ // CraftBukkit end + +- serverplayer1.connection = serverplayer.connection; +- serverplayer1.restoreFrom(serverplayer, flag); +- serverplayer1.setId(serverplayer.getId()); +- serverplayer1.setMainArm(serverplayer.getMainArm()); +- Iterator iterator = serverplayer.getTags().iterator(); ++ entityplayer1.connection = entityplayer.connection; ++ entityplayer1.restoreFrom(entityplayer, flag); ++ entityplayer1.setId(entityplayer.getId()); ++ entityplayer1.setMainArm(entityplayer.getMainArm()); ++ Iterator iterator = entityplayer.getTags().iterator(); + + while (iterator.hasNext()) { + String s = (String) iterator.next(); + +- serverplayer1.addTag(s); ++ entityplayer1.addTag(s); + } + + boolean flag2 = false; + +- if (optional.isPresent()) { +- BlockState blockstate = serverlevel1.getBlockState(blockpos); +- boolean flag3 = blockstate.is(Blocks.RESPAWN_ANCHOR); +- Vec3 vec3 = (Vec3) optional.get(); +- float f1; ++ // CraftBukkit start - fire PlayerRespawnEvent ++ if (location == null) { ++ boolean isBedSpawn = false; ++ ServerLevel worldserver1 = this.server.getLevel(entityplayer.getRespawnDimension()); ++ if (worldserver1 != null) { ++ Optional optional; + +- if (!blockstate.is(BlockTags.BEDS) && !flag3) { +- f1 = f; +- } else { +- Vec3 vec31 = Vec3.atBottomCenterOf(blockpos).subtract(vec3).normalize(); ++ if (blockposition != null) { ++ optional = net.minecraft.world.entity.player.Player.findRespawnPositionAndUseSpawnBlock(worldserver1, blockposition, f, flag1, flag); ++ } else { ++ optional = Optional.empty(); ++ } + +- f1 = (float) Mth.wrapDegrees(Mth.atan2(vec31.z, vec31.x) * 57.2957763671875D - 90.0D); ++ if (optional.isPresent()) { ++ IBlockData iblockdata = worldserver1.getBlockState(blockposition); ++ boolean flag3 = iblockdata.is(Blocks.RESPAWN_ANCHOR); ++ Vec3 vec3d = (Vec3) optional.get(); ++ float f1; ++ ++ if (!iblockdata.is(BlockTags.BEDS) && !flag3) { ++ f1 = f; ++ } else { ++ Vec3 vec3d1 = Vec3.atBottomCenterOf(blockposition).subtract(vec3d).normalize(); ++ ++ f1 = (float) Mth.wrapDegrees(Mth.atan2(vec3d1.z, vec3d1.x) * 57.2957763671875D - 90.0D); ++ } ++ ++ // entityplayer1.setRespawnPosition(worldserver1.dimension(), blockposition, f, flag1, false); // CraftBukkit - not required, just copies old location into reused entity ++ flag2 = !flag && flag3; ++ isBedSpawn = true; ++ location = CraftLocation.toBukkit(vec3d, worldserver1.getWorld(), f1, 0.0F); ++ } else if (blockposition != null) { ++ entityplayer1.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F)); ++ entityplayer1.setRespawnPosition(null, null, 0f, false, false, PlayerSpawnChangeEvent.Cause.RESET); // CraftBukkit - SPIGOT-5988: Clear respawn location when obstructed ++ } + } + +- serverplayer1.moveTo(vec3.x, vec3.y, vec3.z, f1, 0.0F); +- serverplayer1.setRespawnPosition(serverlevel1.dimension(), blockpos, f, flag1, false); +- flag2 = !flag && flag3; +- } else if (blockpos != null) { +- serverplayer1.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F)); ++ if (location == null) { ++ worldserver1 = this.server.getLevel(Level.OVERWORLD); ++ blockposition = entityplayer1.getSpawnPoint(worldserver1); ++ location = CraftLocation.toBukkit(blockposition, worldserver1.getWorld()).add(0.5F, 0.1F, 0.5F); ++ } ++ ++ Player respawnPlayer = entityplayer1.getBukkitEntity(); ++ PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !flag2, flag2, reason); ++ cserver.getPluginManager().callEvent(respawnEvent); ++ ++ location = respawnEvent.getRespawnLocation(); ++ if (!flag) entityplayer.reset(); // SPIGOT-4785 ++ } else { ++ location.setWorld(worldserver.getWorld()); + } ++ ServerLevel worldserver1 = ((CraftWorld) location.getWorld()).getHandle(); ++ entityplayer1.spawnIn(worldserver1); ++ entityplayer1.unsetRemoved(); ++ entityplayer1.setShiftKeyDown(false); ++ entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + +- while (!serverlevel1.noCollision((Entity) serverplayer1) && serverplayer1.getY() < (double) serverlevel1.getMaxBuildHeight()) { +- serverplayer1.setPos(serverplayer1.getX(), serverplayer1.getY() + 1.0D, serverplayer1.getZ()); ++ while (avoidSuffocation && !worldserver1.noCollision((Entity) entityplayer1) && entityplayer1.getY() < (double) worldserver1.getMaxBuildHeight()) { ++ // CraftBukkit end ++ entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); + } + + int i = flag ? 1 : 0; +- ServerLevel serverlevel2 = serverplayer1.serverLevel(); +- LevelData leveldata = serverlevel2.getLevelData(); ++ ServerLevel worldserver2 = entityplayer1.serverLevel(); ++ LevelData worlddata = worldserver2.getLevelData(); + +- serverplayer1.connection.send(new ClientboundRespawnPacket(serverplayer1.createCommonSpawnInfo(serverlevel2), (byte) i)); +- serverplayer1.connection.teleport(serverplayer1.getX(), serverplayer1.getY(), serverplayer1.getZ(), serverplayer1.getYRot(), serverplayer1.getXRot()); +- serverplayer1.connection.send(new ClientboundSetDefaultSpawnPositionPacket(serverlevel1.getSharedSpawnPos(), serverlevel1.getSharedSpawnAngle())); +- serverplayer1.connection.send(new ClientboundChangeDifficultyPacket(leveldata.getDifficulty(), leveldata.isDifficultyLocked())); +- serverplayer1.connection.send(new ClientboundSetExperiencePacket(serverplayer1.experienceProgress, serverplayer1.totalExperience, serverplayer1.experienceLevel)); +- this.sendLevelInfo(serverplayer1, serverlevel1); +- this.sendPlayerPermissionLevel(serverplayer1); +- serverlevel1.addRespawnedPlayer(serverplayer1); +- this.players.add(serverplayer1); +- this.playersByUUID.put(serverplayer1.getUUID(), serverplayer1); +- serverplayer1.initInventoryMenu(); +- serverplayer1.setHealth(serverplayer1.getHealth()); ++ entityplayer1.connection.send(new ClientboundRespawnPacket(entityplayer1.createCommonSpawnInfo(worldserver2), (byte) i)); ++ entityplayer1.connection.teleport(CraftLocation.toBukkit(entityplayer1.position(), worldserver2.getWorld(), entityplayer1.getYRot(), entityplayer1.getXRot())); // CraftBukkit ++ entityplayer1.connection.send(new ClientboundSetDefaultSpawnPositionPacket(worldserver1.getSharedSpawnPos(), worldserver1.getSharedSpawnAngle())); ++ entityplayer1.connection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); ++ entityplayer1.connection.send(new ClientboundSetExperiencePacket(entityplayer1.experienceProgress, entityplayer1.totalExperience, entityplayer1.experienceLevel)); ++ this.sendLevelInfo(entityplayer1, worldserver1); ++ this.sendPlayerPermissionLevel(entityplayer1); ++ if (!entityplayer.connection.isDisconnected()) { ++ worldserver1.addRespawnedPlayer(entityplayer1); ++ this.players.add(entityplayer1); ++ this.playersByUUID.put(entityplayer1.getUUID(), entityplayer1); ++ } ++ // entityplayer1.initInventoryMenu(); ++ entityplayer1.setHealth(entityplayer1.getHealth()); + if (flag2) { +- serverplayer1.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, (double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), 1.0F, 1.0F, serverlevel1.getRandom().nextLong())); ++ entityplayer1.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), 1.0F, 1.0F, worldserver1.getRandom().nextLong())); + } ++ // Added from changeDimension ++ sendAllPlayerInfo(entityplayer); // Update health, etc... ++ entityplayer.onUpdateAbilities(); ++ for (MobEffectInstance mobEffect : entityplayer.getActiveEffects()) { ++ entityplayer.connection.send(new ClientboundUpdateMobEffectPacket(entityplayer.getId(), mobEffect)); ++ } + +- return serverplayer1; ++ // Fire advancement trigger ++ entityplayer.triggerDimensionChangeTriggers(((CraftWorld) fromWorld).getHandle()); ++ ++ // Don't fire on respawn ++ if (fromWorld != location.getWorld()) { ++ PlayerChangedWorldEvent event = new PlayerChangedWorldEvent(entityplayer.getBukkitEntity(), fromWorld); ++ server.server.getPluginManager().callEvent(event); ++ } ++ ++ // Save player file again if they were disconnected ++ if (entityplayer.connection.isDisconnected()) { ++ this.save(entityplayer); ++ } ++ // CraftBukkit end ++ return entityplayer1; + } + +- public void sendPlayerPermissionLevel(ServerPlayer serverplayer) { +- GameProfile gameprofile = serverplayer.getGameProfile(); ++ public void sendPlayerPermissionLevel(ServerPlayer player) { ++ GameProfile gameprofile = player.getGameProfile(); + int i = this.server.getProfilePermissions(gameprofile); + +- this.sendPlayerPermissionLevel(serverplayer, i); ++ this.sendPlayerPermissionLevel(player, i); + } + + public void tick() { + if (++this.sendAllPlayerInfoIn > 600) { +- this.broadcastAll(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY), this.players)); ++ // CraftBukkit start ++ for (int i = 0; i < this.players.size(); ++i) { ++ final ServerPlayer target = (ServerPlayer) this.players.get(i); ++ ++ target.connection.send(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY), this.players.stream().filter(new Predicate() { ++ @Override ++ public boolean test(ServerPlayer input) { ++ return target.getBukkitEntity().canSee(input.getBukkitEntity()); ++ } ++ }).collect(Collectors.toList()))); ++ } ++ // CraftBukkit end + this.sendAllPlayerInfoIn = 0; + } + +@@ -587,56 +844,75 @@ + Iterator iterator = this.players.iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- serverplayer.connection.send(packet); ++ entityplayer.connection.send(packet); + } + + } + +- public void broadcastAll(Packet packet, ResourceKey resourcekey) { ++ // CraftBukkit start - add a world/entity limited version ++ public void broadcastAll(Packet packet, net.minecraft.world.entity.player.Player entityhuman) { ++ for (int i = 0; i < this.players.size(); ++i) { ++ ServerPlayer entityplayer = this.players.get(i); ++ if (entityhuman != null && !entityplayer.getBukkitEntity().canSee(entityhuman.getBukkitEntity())) { ++ continue; ++ } ++ ((ServerPlayer) this.players.get(i)).connection.send(packet); ++ } ++ } ++ ++ public void broadcastAll(Packet packet, Level world) { ++ for (int i = 0; i < world.players().size(); ++i) { ++ ((ServerPlayer) world.players().get(i)).connection.send(packet); ++ } ++ ++ } ++ // CraftBukkit end ++ ++ public void broadcastAll(Packet packet, ResourceKey dimension) { + Iterator iterator = this.players.iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- if (serverplayer.level().dimension() == resourcekey) { +- serverplayer.connection.send(packet); ++ if (entityplayer.level().dimension() == dimension) { ++ entityplayer.connection.send(packet); + } + } + + } + +- public void broadcastSystemToTeam(Player player, Component component) { +- PlayerTeam playerteam = player.getTeam(); ++ public void broadcastSystemToTeam(net.minecraft.world.entity.player.Player player, Component message) { ++ PlayerTeam scoreboardteam = player.getTeam(); + +- if (playerteam != null) { +- Collection collection = playerteam.getPlayers(); ++ if (scoreboardteam != null) { ++ Collection collection = scoreboardteam.getPlayers(); + Iterator iterator = collection.iterator(); + + while (iterator.hasNext()) { + String s = (String) iterator.next(); +- ServerPlayer serverplayer = this.getPlayerByName(s); ++ ServerPlayer entityplayer = this.getPlayerByName(s); + +- if (serverplayer != null && serverplayer != player) { +- serverplayer.sendSystemMessage(component); ++ if (entityplayer != null && entityplayer != player) { ++ entityplayer.sendSystemMessage(message); + } + } + + } + } + +- public void broadcastSystemToAllExceptTeam(Player player, Component component) { +- PlayerTeam playerteam = player.getTeam(); ++ public void broadcastSystemToAllExceptTeam(net.minecraft.world.entity.player.Player player, Component message) { ++ PlayerTeam scoreboardteam = player.getTeam(); + +- if (playerteam == null) { +- this.broadcastSystemMessage(component, false); ++ if (scoreboardteam == null) { ++ this.broadcastSystemMessage(message, false); + } else { + for (int i = 0; i < this.players.size(); ++i) { +- ServerPlayer serverplayer = (ServerPlayer) this.players.get(i); ++ ServerPlayer entityplayer = (ServerPlayer) this.players.get(i); + +- if (serverplayer.getTeam() != playerteam) { +- serverplayer.sendSystemMessage(component); ++ if (entityplayer.getTeam() != scoreboardteam) { ++ entityplayer.sendSystemMessage(message); + } + } + +@@ -661,78 +937,85 @@ + return this.ipBans; + } + +- public void op(GameProfile gameprofile) { +- this.ops.add(new ServerOpListEntry(gameprofile, this.server.getOperatorUserPermissionLevel(), this.ops.canBypassPlayerLimit(gameprofile))); +- ServerPlayer serverplayer = this.getPlayer(gameprofile.getId()); ++ public void op(GameProfile profile) { ++ this.ops.add(new ServerOpListEntry(profile, this.server.getOperatorUserPermissionLevel(), this.ops.canBypassPlayerLimit(profile))); ++ ServerPlayer entityplayer = this.getPlayer(profile.getId()); + +- if (serverplayer != null) { +- this.sendPlayerPermissionLevel(serverplayer); ++ if (entityplayer != null) { ++ this.sendPlayerPermissionLevel(entityplayer); + } + + } + +- public void deop(GameProfile gameprofile) { +- this.ops.remove((Object) gameprofile); +- ServerPlayer serverplayer = this.getPlayer(gameprofile.getId()); ++ public void deop(GameProfile profile) { ++ this.ops.remove(profile); // CraftBukkit - decompile error ++ ServerPlayer entityplayer = this.getPlayer(profile.getId()); + +- if (serverplayer != null) { +- this.sendPlayerPermissionLevel(serverplayer); ++ if (entityplayer != null) { ++ this.sendPlayerPermissionLevel(entityplayer); + } + + } + +- private void sendPlayerPermissionLevel(ServerPlayer serverplayer, int i) { +- if (serverplayer.connection != null) { ++ private void sendPlayerPermissionLevel(ServerPlayer player, int permLevel) { ++ if (player.connection != null) { + byte b0; + +- if (i <= 0) { ++ if (permLevel <= 0) { + b0 = 24; +- } else if (i >= 4) { ++ } else if (permLevel >= 4) { + b0 = 28; + } else { +- b0 = (byte) (24 + i); ++ b0 = (byte) (24 + permLevel); + } + +- serverplayer.connection.send(new ClientboundEntityEventPacket(serverplayer, b0)); ++ player.connection.send(new ClientboundEntityEventPacket(player, b0)); + } + +- this.server.getCommands().sendCommands(serverplayer); ++ player.getBukkitEntity().recalculatePermissions(); // CraftBukkit ++ this.server.getCommands().sendCommands(player); + } + +- public boolean isWhiteListed(GameProfile gameprofile) { +- return !this.doWhiteList || this.ops.contains(gameprofile) || this.whitelist.contains(gameprofile); ++ public boolean isWhiteListed(GameProfile profile) { ++ return !this.doWhiteList || this.ops.contains(profile) || this.whitelist.contains(profile); + } + +- public boolean isOp(GameProfile gameprofile) { +- return this.ops.contains(gameprofile) || this.server.isSingleplayerOwner(gameprofile) && this.server.getWorldData().getAllowCommands() || this.allowCheatsForAllPlayers; ++ public boolean isOp(GameProfile profile) { ++ return this.ops.contains(profile) || this.server.isSingleplayerOwner(profile) && this.server.getWorldData().getAllowCommands() || this.allowCheatsForAllPlayers; + } + + @Nullable +- public ServerPlayer getPlayerByName(String s) { ++ public ServerPlayer getPlayerByName(String username) { + int i = this.players.size(); + + for (int j = 0; j < i; ++j) { +- ServerPlayer serverplayer = (ServerPlayer) this.players.get(j); ++ ServerPlayer entityplayer = (ServerPlayer) this.players.get(j); + +- if (serverplayer.getGameProfile().getName().equalsIgnoreCase(s)) { +- return serverplayer; ++ if (entityplayer.getGameProfile().getName().equalsIgnoreCase(username)) { ++ return entityplayer; + } + } + + return null; + } + +- public void broadcast(@Nullable Player player, double d0, double d1, double d2, double d3, ResourceKey resourcekey, Packet packet) { ++ public void broadcast(@Nullable net.minecraft.world.entity.player.Player except, double x, double d1, double y, double d3, ResourceKey z, Packet packet) { + for (int i = 0; i < this.players.size(); ++i) { +- ServerPlayer serverplayer = (ServerPlayer) this.players.get(i); ++ ServerPlayer entityplayer = (ServerPlayer) this.players.get(i); + +- if (serverplayer != player && serverplayer.level().dimension() == resourcekey) { +- double d4 = d0 - serverplayer.getX(); +- double d5 = d1 - serverplayer.getY(); +- double d6 = d2 - serverplayer.getZ(); ++ // CraftBukkit start - Test if player receiving packet can see the source of the packet ++ if (except != null && !entityplayer.getBukkitEntity().canSee(except.getBukkitEntity())) { ++ continue; ++ } ++ // CraftBukkit end + ++ if (entityplayer != except && entityplayer.level().dimension() == z) { ++ double d4 = x - entityplayer.getX(); ++ double d5 = d1 - entityplayer.getY(); ++ double d6 = y - entityplayer.getZ(); ++ + if (d4 * d4 + d5 * d5 + d6 * d6 < d3 * d3) { +- serverplayer.connection.send(packet); ++ entityplayer.connection.send(packet); + } + } + } +@@ -764,26 +1047,38 @@ + + public void reloadWhiteList() {} + +- public void sendLevelInfo(ServerPlayer serverplayer, ServerLevel serverlevel) { +- WorldBorder worldborder = this.server.overworld().getWorldBorder(); ++ public void sendLevelInfo(ServerPlayer player, ServerLevel level) { ++ WorldBorder worldborder = player.level().getWorldBorder(); // CraftBukkit + +- serverplayer.connection.send(new ClientboundInitializeBorderPacket(worldborder)); +- serverplayer.connection.send(new ClientboundSetTimePacket(serverlevel.getGameTime(), serverlevel.getDayTime(), serverlevel.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); +- serverplayer.connection.send(new ClientboundSetDefaultSpawnPositionPacket(serverlevel.getSharedSpawnPos(), serverlevel.getSharedSpawnAngle())); +- if (serverlevel.isRaining()) { +- serverplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.START_RAINING, 0.0F)); +- serverplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, serverlevel.getRainLevel(1.0F))); +- serverplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, serverlevel.getThunderLevel(1.0F))); ++ player.connection.send(new ClientboundInitializeBorderPacket(worldborder)); ++ player.connection.send(new ClientboundSetTimePacket(level.getGameTime(), level.getDayTime(), level.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); ++ player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(level.getSharedSpawnPos(), level.getSharedSpawnAngle())); ++ if (level.isRaining()) { ++ // CraftBukkit start - handle player weather ++ // entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.START_RAINING, 0.0F)); ++ // entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.RAIN_LEVEL_CHANGE, worldserver.getRainLevel(1.0F))); ++ // entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, worldserver.getThunderLevel(1.0F))); ++ player.setPlayerWeather(org.bukkit.WeatherType.DOWNFALL, false); ++ player.updateWeather(-level.rainLevel, level.rainLevel, -level.thunderLevel, level.thunderLevel); ++ // CraftBukkit end + } + +- serverplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LEVEL_CHUNKS_LOAD_START, 0.0F)); +- this.server.tickRateManager().updateJoiningPlayer(serverplayer); ++ player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LEVEL_CHUNKS_LOAD_START, 0.0F)); ++ this.server.tickRateManager().updateJoiningPlayer(player); + } + +- public void sendAllPlayerInfo(ServerPlayer serverplayer) { +- serverplayer.inventoryMenu.sendAllDataToRemote(); +- serverplayer.resetSentInfo(); +- serverplayer.connection.send(new ClientboundSetCarriedItemPacket(serverplayer.getInventory().selected)); ++ public void sendAllPlayerInfo(ServerPlayer player) { ++ player.inventoryMenu.sendAllDataToRemote(); ++ // entityplayer.resetSentInfo(); ++ player.getBukkitEntity().updateScaledHealth(); // CraftBukkit - Update scaled health on respawn and worldchange ++ player.getEntityData().refresh(player); // CraftBukkkit - SPIGOT-7218: sync metadata ++ player.connection.send(new ClientboundSetCarriedItemPacket(player.getInventory().selected)); ++ // CraftBukkit start - from GameRules ++ int i = player.level().getGameRules().getBoolean(GameRules.RULE_REDUCEDDEBUGINFO) ? 22 : 23; ++ player.connection.send(new ClientboundEntityEventPacket(player, (byte) i)); ++ float immediateRespawn = player.level().getGameRules().getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN) ? 1.0F: 0.0F; ++ player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.IMMEDIATE_RESPAWN, immediateRespawn)); ++ // CraftBukkit end + } + + public int getPlayerCount() { +@@ -798,19 +1093,19 @@ + return this.doWhiteList; + } + +- public void setUsingWhiteList(boolean flag) { +- this.doWhiteList = flag; ++ public void setUsingWhiteList(boolean whitelistEnabled) { ++ this.doWhiteList = whitelistEnabled; + } + +- public List getPlayersWithAddress(String s) { ++ public List getPlayersWithAddress(String address) { + List list = Lists.newArrayList(); + Iterator iterator = this.players.iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- if (serverplayer.getIpAddress().equals(s)) { +- list.add(serverplayer); ++ if (entityplayer.getIpAddress().equals(address)) { ++ list.add(entityplayer); + } + } + +@@ -834,84 +1129,101 @@ + return null; + } + +- public void setAllowCheatsForAllPlayers(boolean flag) { +- this.allowCheatsForAllPlayers = flag; ++ public void setAllowCheatsForAllPlayers(boolean allowCheatsForAllPlayers) { ++ this.allowCheatsForAllPlayers = allowCheatsForAllPlayers; + } + + public void removeAll() { +- for (int i = 0; i < this.players.size(); ++i) { +- ((ServerPlayer) this.players.get(i)).connection.disconnect(Component.translatable("multiplayer.disconnect.server_shutdown")); ++ // CraftBukkit start - disconnect safely ++ for (ServerPlayer player : this.players) { ++ player.connection.disconnect(this.server.server.getShutdownMessage()); // CraftBukkit - add custom shutdown message + } ++ // CraftBukkit end + + } + +- public void broadcastSystemMessage(Component component, boolean flag) { +- this.broadcastSystemMessage(component, (serverplayer) -> { +- return component; +- }, flag); ++ // CraftBukkit start ++ public void broadcastMessage(Component[] iChatBaseComponents) { ++ for (Component component : iChatBaseComponents) { ++ broadcastSystemMessage(component, false); ++ } + } ++ // CraftBukkit end + +- public void broadcastSystemMessage(Component component, Function function, boolean flag) { +- this.server.sendSystemMessage(component); ++ public void broadcastSystemMessage(Component message, boolean bypassHiddenChat) { ++ this.broadcastSystemMessage(message, (entityplayer) -> { ++ return message; ++ }, bypassHiddenChat); ++ } ++ ++ public void broadcastSystemMessage(Component serverMessage, Function playerMessageFactory, boolean bypassHiddenChat) { ++ this.server.sendSystemMessage(serverMessage); + Iterator iterator = this.players.iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); +- Component component1 = (Component) function.apply(serverplayer); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ Component ichatbasecomponent1 = (Component) playerMessageFactory.apply(entityplayer); + +- if (component1 != null) { +- serverplayer.sendSystemMessage(component1, flag); ++ if (ichatbasecomponent1 != null) { ++ entityplayer.sendSystemMessage(ichatbasecomponent1, bypassHiddenChat); + } + } + + } + +- public void broadcastChatMessage(PlayerChatMessage playerchatmessage, CommandSourceStack commandsourcestack, ChatType.Bound chattype_bound) { +- Objects.requireNonNull(commandsourcestack); +- this.broadcastChatMessage(playerchatmessage, commandsourcestack::shouldFilterMessageTo, commandsourcestack.getPlayer(), chattype_bound); ++ public void broadcastChatMessage(PlayerChatMessage message, CommandSourceStack sender, ChatType.Bound boundChatType) { ++ Objects.requireNonNull(sender); ++ this.broadcastChatMessage(message, sender::shouldFilterMessageTo, sender.getPlayer(), boundChatType); + } + +- public void broadcastChatMessage(PlayerChatMessage playerchatmessage, ServerPlayer serverplayer, ChatType.Bound chattype_bound) { +- Objects.requireNonNull(serverplayer); +- this.broadcastChatMessage(playerchatmessage, serverplayer::shouldFilterMessageTo, serverplayer, chattype_bound); ++ public void broadcastChatMessage(PlayerChatMessage message, ServerPlayer sender, ChatType.Bound boundChatType) { ++ Objects.requireNonNull(sender); ++ this.broadcastChatMessage(message, sender::shouldFilterMessageTo, sender, boundChatType); + } + +- private void broadcastChatMessage(PlayerChatMessage playerchatmessage, Predicate predicate, @Nullable ServerPlayer serverplayer, ChatType.Bound chattype_bound) { +- boolean flag = this.verifyChatTrusted(playerchatmessage); ++ private void broadcastChatMessage(PlayerChatMessage message, Predicate shouldFilterMessageTo, @Nullable ServerPlayer sender, ChatType.Bound boundChatType) { ++ boolean flag = this.verifyChatTrusted(message); + +- this.server.logChatMessage(playerchatmessage.decoratedContent(), chattype_bound, flag ? null : "Not Secure"); +- OutgoingChatMessage outgoingchatmessage = OutgoingChatMessage.create(playerchatmessage); ++ this.server.logChatMessage(message.decoratedContent(), boundChatType, flag ? null : "Not Secure"); ++ OutgoingChatMessage outgoingchatmessage = OutgoingChatMessage.create(message); + boolean flag1 = false; + + boolean flag2; + +- for (Iterator iterator = this.players.iterator(); iterator.hasNext(); flag1 |= flag2 && playerchatmessage.isFullyFiltered()) { +- ServerPlayer serverplayer1 = (ServerPlayer) iterator.next(); ++ for (Iterator iterator = this.players.iterator(); iterator.hasNext(); flag1 |= flag2 && message.isFullyFiltered()) { ++ ServerPlayer entityplayer1 = (ServerPlayer) iterator.next(); + +- flag2 = predicate.test(serverplayer1); +- serverplayer1.sendChatMessage(outgoingchatmessage, flag2, chattype_bound); ++ flag2 = shouldFilterMessageTo.test(entityplayer1); ++ entityplayer1.sendChatMessage(outgoingchatmessage, flag2, boundChatType); + } + +- if (flag1 && serverplayer != null) { +- serverplayer.sendSystemMessage(PlayerList.CHAT_FILTERED_FULL); ++ if (flag1 && sender != null) { ++ sender.sendSystemMessage(PlayerList.CHAT_FILTERED_FULL); + } + + } + +- private boolean verifyChatTrusted(PlayerChatMessage playerchatmessage) { +- return playerchatmessage.hasSignature() && !playerchatmessage.hasExpiredServer(Instant.now()); ++ private boolean verifyChatTrusted(PlayerChatMessage message) { ++ return message.hasSignature() && !message.hasExpiredServer(Instant.now()); + } + +- public ServerStatsCounter getPlayerStats(Player player) { +- UUID uuid = player.getUUID(); +- ServerStatsCounter serverstatscounter = (ServerStatsCounter) this.stats.get(uuid); ++ // CraftBukkit start ++ public ServerStatsCounter getPlayerStats(ServerPlayer entityhuman) { ++ ServerStatsCounter serverstatisticmanager = entityhuman.getStats(); ++ return serverstatisticmanager == null ? getPlayerStats(entityhuman.getUUID(), entityhuman.getDisplayName().getString()) : serverstatisticmanager; ++ } + +- if (serverstatscounter == null) { ++ public ServerStatsCounter getPlayerStats(UUID uuid, String displayName) { ++ ServerPlayer entityhuman = this.getPlayer(uuid); ++ ServerStatsCounter serverstatisticmanager = entityhuman == null ? null : (ServerStatsCounter) entityhuman.getStats(); ++ // CraftBukkit end ++ ++ if (serverstatisticmanager == null) { + File file = this.server.getWorldPath(LevelResource.PLAYER_STATS_DIR).toFile(); + File file1 = new File(file, uuid + ".json"); + + if (!file1.exists()) { +- File file2 = new File(file, player.getName().getString() + ".json"); ++ File file2 = new File(file, displayName + ".json"); // CraftBukkit + Path path = file2.toPath(); + + if (FileUtil.isPathNormalized(path) && FileUtil.isPathPortable(path) && path.startsWith(file.getPath()) && file2.isFile()) { +@@ -919,53 +1231,53 @@ + } + } + +- serverstatscounter = new ServerStatsCounter(this.server, file1); +- this.stats.put(uuid, serverstatscounter); ++ serverstatisticmanager = new ServerStatsCounter(this.server, file1); ++ // this.stats.put(uuid, serverstatisticmanager); // CraftBukkit + } + +- return serverstatscounter; ++ return serverstatisticmanager; + } + +- public PlayerAdvancements getPlayerAdvancements(ServerPlayer serverplayer) { +- UUID uuid = serverplayer.getUUID(); +- PlayerAdvancements playeradvancements = (PlayerAdvancements) this.advancements.get(uuid); ++ public PlayerAdvancements getPlayerAdvancements(ServerPlayer player) { ++ UUID uuid = player.getUUID(); ++ PlayerAdvancements advancementdataplayer = (PlayerAdvancements) player.getAdvancements(); // CraftBukkit + +- if (playeradvancements == null) { ++ if (advancementdataplayer == null) { + Path path = this.server.getWorldPath(LevelResource.PLAYER_ADVANCEMENTS_DIR).resolve(uuid + ".json"); + +- playeradvancements = new PlayerAdvancements(this.server.getFixerUpper(), this, this.server.getAdvancements(), path, serverplayer); +- this.advancements.put(uuid, playeradvancements); ++ advancementdataplayer = new PlayerAdvancements(this.server.getFixerUpper(), this, this.server.getAdvancements(), path, player); ++ // this.advancements.put(uuid, advancementdataplayer); // CraftBukkit + } + +- playeradvancements.setPlayer(serverplayer); +- return playeradvancements; ++ advancementdataplayer.setPlayer(player); ++ return advancementdataplayer; + } + +- public void setViewDistance(int i) { +- this.viewDistance = i; +- this.broadcastAll(new ClientboundSetChunkCacheRadiusPacket(i)); ++ public void setViewDistance(int viewDistance) { ++ this.viewDistance = viewDistance; ++ this.broadcastAll(new ClientboundSetChunkCacheRadiusPacket(viewDistance)); + Iterator iterator = this.server.getAllLevels().iterator(); + + while (iterator.hasNext()) { +- ServerLevel serverlevel = (ServerLevel) iterator.next(); ++ ServerLevel worldserver = (ServerLevel) iterator.next(); + +- if (serverlevel != null) { +- serverlevel.getChunkSource().setViewDistance(i); ++ if (worldserver != null) { ++ worldserver.getChunkSource().setViewDistance(viewDistance); + } + } + + } + +- public void setSimulationDistance(int i) { +- this.simulationDistance = i; +- this.broadcastAll(new ClientboundSetSimulationDistancePacket(i)); ++ public void setSimulationDistance(int simulationDistance) { ++ this.simulationDistance = simulationDistance; ++ this.broadcastAll(new ClientboundSetSimulationDistancePacket(simulationDistance)); + Iterator iterator = this.server.getAllLevels().iterator(); + + while (iterator.hasNext()) { +- ServerLevel serverlevel = (ServerLevel) iterator.next(); ++ ServerLevel worldserver = (ServerLevel) iterator.next(); + +- if (serverlevel != null) { +- serverlevel.getChunkSource().setSimulationDistance(i); ++ if (worldserver != null) { ++ worldserver.getChunkSource().setSimulationDistance(simulationDistance); + } + } + +@@ -976,32 +1288,39 @@ + } + + @Nullable +- public ServerPlayer getPlayer(UUID uuid) { +- return (ServerPlayer) this.playersByUUID.get(uuid); ++ public ServerPlayer getPlayer(UUID playerUUID) { ++ return (ServerPlayer) this.playersByUUID.get(playerUUID); + } + +- public boolean canBypassPlayerLimit(GameProfile gameprofile) { ++ public boolean canBypassPlayerLimit(GameProfile profile) { + return false; + } + + public void reloadResources() { +- Iterator iterator = this.advancements.values().iterator(); ++ // CraftBukkit start ++ /*Iterator iterator = this.advancements.values().iterator(); + + while (iterator.hasNext()) { +- PlayerAdvancements playeradvancements = (PlayerAdvancements) iterator.next(); ++ AdvancementDataPlayer advancementdataplayer = (AdvancementDataPlayer) iterator.next(); + +- playeradvancements.reload(this.server.getAdvancements()); ++ advancementdataplayer.reload(this.server.getAdvancements()); ++ }*/ ++ ++ for (ServerPlayer player : players) { ++ player.getAdvancements().reload(this.server.getAdvancements()); ++ player.getAdvancements().flushDirty(player); // CraftBukkit - trigger immediate flush of advancements + } ++ // CraftBukkit end + + this.broadcastAll(new ClientboundUpdateTagsPacket(TagNetworkSerialization.serializeTagsToNetwork(this.registries))); +- ClientboundUpdateRecipesPacket clientboundupdaterecipespacket = new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes()); ++ ClientboundUpdateRecipesPacket packetplayoutrecipeupdate = new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes()); + Iterator iterator1 = this.players.iterator(); + + while (iterator1.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator1.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator1.next(); + +- serverplayer.connection.send(clientboundupdaterecipespacket); +- serverplayer.getRecipeBook().sendInitialRecipeBook(serverplayer); ++ entityplayer.connection.send(packetplayoutrecipeupdate); ++ entityplayer.getRecipeBook().sendInitialRecipeBook(entityplayer); + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/players/SleepStatus.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/players/SleepStatus.java.patch new file mode 100644 index 0000000000..f0ac08abc2 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/players/SleepStatus.java.patch @@ -0,0 +1,69 @@ +--- a/net/minecraft/server/players/SleepStatus.java ++++ b/net/minecraft/server/players/SleepStatus.java +@@ -13,18 +13,21 @@ + + public SleepStatus() {} + +- public boolean areEnoughSleeping(int i) { +- return this.sleepingPlayers >= this.sleepersNeeded(i); ++ public boolean areEnoughSleeping(int requiredSleepPercentage) { ++ return this.sleepingPlayers >= this.sleepersNeeded(requiredSleepPercentage); + } + +- public boolean areEnoughDeepSleeping(int i, List list) { +- int j = (int) list.stream().filter(Player::isSleepingLongEnough).count(); ++ public boolean areEnoughDeepSleeping(int requiredSleepPercentage, List sleepingPlayers) { ++ // CraftBukkit start ++ int j = (int) sleepingPlayers.stream().filter((eh) -> { return eh.isSleepingLongEnough() || eh.fauxSleeping; }).count(); ++ boolean anyDeepSleep = sleepingPlayers.stream().anyMatch(Player::isSleepingLongEnough); + +- return j >= this.sleepersNeeded(i); ++ return anyDeepSleep && j >= this.sleepersNeeded(requiredSleepPercentage); ++ // CraftBukkit end + } + +- public int sleepersNeeded(int i) { +- return Math.max(1, Mth.ceil((float) (this.activePlayers * i) / 100.0F)); ++ public int sleepersNeeded(int requiredSleepPercentage) { ++ return Math.max(1, Mth.ceil((float) (this.activePlayers * requiredSleepPercentage) / 100.0F)); + } + + public void removeAllSleepers() { +@@ -35,25 +38,31 @@ + return this.sleepingPlayers; + } + +- public boolean update(List list) { ++ public boolean update(List players) { + int i = this.activePlayers; + int j = this.sleepingPlayers; + + this.activePlayers = 0; + this.sleepingPlayers = 0; +- Iterator iterator = list.iterator(); ++ Iterator iterator = players.iterator(); ++ boolean anySleep = false; // CraftBukkit + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- if (!serverplayer.isSpectator()) { ++ if (!entityplayer.isSpectator()) { + ++this.activePlayers; +- if (serverplayer.isSleeping()) { ++ if (entityplayer.isSleeping() || entityplayer.fauxSleeping) { // CraftBukkit + ++this.sleepingPlayers; + } ++ // CraftBukkit start ++ if (entityplayer.isSleeping()) { ++ anySleep = true; ++ } ++ // CraftBukkit end + } + } + +- return (j > 0 || this.sleepingPlayers > 0) && (i != this.activePlayers || j != this.sleepingPlayers); ++ return anySleep && (j > 0 || this.sleepingPlayers > 0) && (i != this.activePlayers || j != this.sleepingPlayers); // CraftBukkit + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/players/StoredUserList.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/players/StoredUserList.java.patch new file mode 100644 index 0000000000..bfdc8efdc4 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/players/StoredUserList.java.patch @@ -0,0 +1,111 @@ +--- a/net/minecraft/server/players/StoredUserList.java ++++ b/net/minecraft/server/players/StoredUserList.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.server.players; + + import com.google.common.collect.Lists; +@@ -40,8 +41,8 @@ + return this.file; + } + +- public void add(V v0) { +- this.map.put(this.getKeyForUser(v0.getUser()), v0); ++ public void add(V entry) { ++ this.map.put(this.getKeyForUser(entry.getUser()), entry); + + try { + this.save(); +@@ -52,13 +53,13 @@ + } + + @Nullable +- public V get(K k0) { ++ public V get(K obj) { + this.removeExpired(); +- return (StoredUserEntry) this.map.get(this.getKeyForUser(k0)); ++ return (V) this.map.get(this.getKeyForUser(obj)); // CraftBukkit - fix decompile error + } + +- public void remove(K k0) { +- this.map.remove(this.getKeyForUser(k0)); ++ public void remove(K user) { ++ this.map.remove(this.getKeyForUser(user)); + + try { + this.save(); +@@ -68,8 +69,8 @@ + + } + +- public void remove(StoredUserEntry storeduserentry) { +- this.remove(storeduserentry.getUser()); ++ public void remove(StoredUserEntry entry) { ++ this.remove(entry.getUser()); + } + + public String[] getUserList() { +@@ -80,12 +81,12 @@ + return this.map.size() < 1; + } + +- protected String getKeyForUser(K k0) { +- return k0.toString(); ++ protected String getKeyForUser(K obj) { ++ return obj.toString(); + } + +- protected boolean contains(K k0) { +- return this.map.containsKey(this.getKeyForUser(k0)); ++ protected boolean contains(K entry) { ++ return this.map.containsKey(this.getKeyForUser(entry)); + } + + private void removeExpired() { +@@ -93,7 +94,7 @@ + Iterator iterator = this.map.values().iterator(); + + while (iterator.hasNext()) { +- V v0 = (StoredUserEntry) iterator.next(); ++ V v0 = (V) iterator.next(); // CraftBukkit - decompile error + + if (v0.hasExpired()) { + list.add(v0.getUser()); +@@ -103,7 +104,7 @@ + iterator = list.iterator(); + + while (iterator.hasNext()) { +- K k0 = iterator.next(); ++ K k0 = (K) iterator.next(); // CraftBukkit - decompile error + + this.map.remove(this.getKeyForUser(k0)); + } +@@ -118,11 +119,11 @@ + + public void save() throws IOException { + JsonArray jsonarray = new JsonArray(); +- Stream stream = this.map.values().stream().map((storeduserentry) -> { ++ Stream stream = this.map.values().stream().map((jsonlistentry) -> { // CraftBukkit - decompile error + JsonObject jsonobject = new JsonObject(); + +- Objects.requireNonNull(storeduserentry); +- return (JsonObject) Util.make(jsonobject, storeduserentry::serialize); ++ Objects.requireNonNull(jsonlistentry); ++ return (JsonObject) Util.make(jsonobject, jsonlistentry::serialize); + }); + + Objects.requireNonNull(jsonarray); +@@ -168,10 +169,10 @@ + while (iterator.hasNext()) { + JsonElement jsonelement = (JsonElement) iterator.next(); + JsonObject jsonobject = GsonHelper.convertToJsonObject(jsonelement, "entry"); +- StoredUserEntry storeduserentry = this.createEntry(jsonobject); ++ StoredUserEntry jsonlistentry = this.createEntry(jsonobject); + +- if (storeduserentry.getUser() != null) { +- this.map.put(this.getKeyForUser(storeduserentry.getUser()), storeduserentry); ++ if (jsonlistentry.getUser() != null) { ++ this.map.put(this.getKeyForUser(jsonlistentry.getUser()), (V) jsonlistentry); // CraftBukkit - decompile error + } + } + } catch (Throwable throwable) { diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/players/UserBanListEntry.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/players/UserBanListEntry.java.patch new file mode 100644 index 0000000000..2786e1c198 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/players/UserBanListEntry.java.patch @@ -0,0 +1,70 @@ +--- a/net/minecraft/server/players/UserBanListEntry.java ++++ b/net/minecraft/server/players/UserBanListEntry.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.server.players; + + import com.google.gson.JsonObject; +@@ -9,30 +10,28 @@ + + public class UserBanListEntry extends BanListEntry { + +- public UserBanListEntry(@Nullable GameProfile gameprofile) { +- this(gameprofile, (Date) null, (String) null, (Date) null, (String) null); ++ public UserBanListEntry(@Nullable GameProfile user) { ++ this(user, (Date) null, (String) null, (Date) null, (String) null); + } + +- public UserBanListEntry(@Nullable GameProfile gameprofile, @Nullable Date date, @Nullable String s, @Nullable Date date1, @Nullable String s1) { +- super(gameprofile, date, s, date1, s1); ++ public UserBanListEntry(@Nullable GameProfile profile, @Nullable Date created, @Nullable String source, @Nullable Date expires, @Nullable String reason) { ++ super(profile, created, source, expires, reason); + } + +- public UserBanListEntry(JsonObject jsonobject) { +- super(createGameProfile(jsonobject), jsonobject); ++ public UserBanListEntry(JsonObject entryData) { ++ super(createGameProfile(entryData), entryData); + } + + @Override +- @Override +- protected void serialize(JsonObject jsonobject) { ++ protected void serialize(JsonObject data) { + if (this.getUser() != null) { +- jsonobject.addProperty("uuid", ((GameProfile) this.getUser()).getId().toString()); +- jsonobject.addProperty("name", ((GameProfile) this.getUser()).getName()); +- super.serialize(jsonobject); ++ data.addProperty("uuid", ((GameProfile) this.getUser()).getId().toString()); ++ data.addProperty("name", ((GameProfile) this.getUser()).getName()); ++ super.serialize(data); + } + } + + @Override +- @Override + public Component getDisplayName() { + GameProfile gameprofile = (GameProfile) this.getUser(); + +@@ -40,9 +39,9 @@ + } + + @Nullable +- private static GameProfile createGameProfile(JsonObject jsonobject) { +- if (jsonobject.has("uuid") && jsonobject.has("name")) { +- String s = jsonobject.get("uuid").getAsString(); ++ private static GameProfile createGameProfile(JsonObject json) { ++ if (json.has("uuid") && json.has("name")) { ++ String s = json.get("uuid").getAsString(); + + UUID uuid; + +@@ -52,7 +51,7 @@ + return null; + } + +- return new GameProfile(uuid, jsonobject.get("name").getAsString()); ++ return new GameProfile(uuid, json.get("name").getAsString()); + } else { + return null; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/rcon/RconConsoleSource.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/rcon/RconConsoleSource.java.patch new file mode 100644 index 0000000000..98a621e9cc --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/rcon/RconConsoleSource.java.patch @@ -0,0 +1,72 @@ +--- a/net/minecraft/server/rcon/RconConsoleSource.java ++++ b/net/minecraft/server/rcon/RconConsoleSource.java +@@ -8,15 +8,23 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; +- ++// CraftBukkit start ++import java.net.SocketAddress; ++import org.bukkit.craftbukkit.command.CraftRemoteConsoleCommandSender; ++// CraftBukkit end + public class RconConsoleSource implements CommandSource { + + private static final String RCON = "Rcon"; + private static final Component RCON_COMPONENT = Component.literal("Rcon"); + private final StringBuffer buffer = new StringBuffer(); + private final MinecraftServer server; ++ // CraftBukkit start ++ public final SocketAddress socketAddress; ++ private final CraftRemoteConsoleCommandSender remoteConsole = new CraftRemoteConsoleCommandSender(this); + +- public RconConsoleSource(MinecraftServer minecraftserver) { ++ public RconConsoleSource(MinecraftServer minecraftserver, SocketAddress socketAddress) { ++ this.socketAddress = socketAddress; ++ // CraftBukkit end + this.server = minecraftserver; + } + +@@ -29,31 +37,38 @@ + } + + public CommandSourceStack createCommandSourceStack() { +- ServerLevel serverlevel = this.server.overworld(); ++ ServerLevel worldserver = this.server.overworld(); + +- return new CommandSourceStack(this, Vec3.atLowerCornerOf(serverlevel.getSharedSpawnPos()), Vec2.ZERO, serverlevel, 4, "Rcon", RconConsoleSource.RCON_COMPONENT, this.server, (Entity) null); ++ return new CommandSourceStack(this, Vec3.atLowerCornerOf(worldserver.getSharedSpawnPos()), Vec2.ZERO, worldserver, 4, "Rcon", RconConsoleSource.RCON_COMPONENT, this.server, (Entity) null); + } + ++ // CraftBukkit start - Send a String ++ public void sendMessage(String message) { ++ this.buffer.append(message); ++ } ++ + @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return this.remoteConsole; ++ } ++ // CraftBukkit end ++ + @Override + public void sendSystemMessage(Component component) { + this.buffer.append(component.getString()); + } + + @Override +- @Override + public boolean acceptsSuccess() { + return true; + } + + @Override +- @Override + public boolean acceptsFailure() { + return true; + } + + @Override +- @Override + public boolean shouldInformAdmins() { + return this.server.shouldRconBroadcast(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/server/rcon/thread/RconClient.java.patch b/patch-remap/mache-spigotflower/net/minecraft/server/rcon/thread/RconClient.java.patch new file mode 100644 index 0000000000..ffec7f2dcb --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/server/rcon/thread/RconClient.java.patch @@ -0,0 +1,126 @@ +--- a/net/minecraft/server/rcon/thread/RconClient.java ++++ b/net/minecraft/server/rcon/thread/RconClient.java +@@ -8,9 +8,12 @@ + import java.net.Socket; + import java.nio.charset.StandardCharsets; + import java.util.Locale; ++import org.slf4j.Logger; + import net.minecraft.server.ServerInterface; ++// CraftBukkit start ++import net.minecraft.server.dedicated.DedicatedServer; + import net.minecraft.server.rcon.PktUtils; +-import org.slf4j.Logger; ++import net.minecraft.server.rcon.RconConsoleSource; + + public class RconClient extends GenericThread { + +@@ -24,12 +27,15 @@ + private final Socket client; + private final byte[] buf = new byte[1460]; + private final String rconPassword; +- private final ServerInterface serverInterface; ++ // CraftBukkit start ++ private final DedicatedServer serverInterface; ++ private final RconConsoleSource rconConsoleSource; ++ // CraftBukkit end + +- RconClient(ServerInterface serverinterface, String s, Socket socket) { +- super("RCON Client " + socket.getInetAddress()); +- this.serverInterface = serverinterface; +- this.client = socket; ++ RconClient(ServerInterface serverInterface, String rconPassword, Socket client) { ++ super("RCON Client " + client.getInetAddress()); ++ this.serverInterface = (DedicatedServer) serverInterface; // CraftBukkit ++ this.client = client; + + try { + this.client.setSoTimeout(0); +@@ -37,13 +43,15 @@ + this.running = false; + } + +- this.rconPassword = s; ++ this.rconPassword = rconPassword; ++ this.rconConsoleSource = new net.minecraft.server.rcon.RconConsoleSource(this.serverInterface, client.getRemoteSocketAddress()); // CraftBukkit + } + +- @Override + public void run() { +- while (true) { +- try { ++ // CraftBukkit start - decompile error: switch try / while statement ++ try { ++ while (true) { ++ // CraftBukkit end + if (!this.running) { + return; + } +@@ -72,7 +80,7 @@ + String s = PktUtils.stringFromByteArray(this.buf, k, i); + + try { +- this.sendCmdResponse(l, this.serverInterface.runCommand(s)); ++ this.sendCmdResponse(l, this.serverInterface.runCommand(this.rconConsoleSource, s)); // CraftBukkit + } catch (Exception exception) { + this.sendCmdResponse(l, "Error executing: " + s + " (" + exception.getMessage() + ")"); + } +@@ -99,6 +107,7 @@ + continue; + } + } ++ } // CraftBukkit - decompile error: switch try / while statement + } catch (IOException ioexception) { + return; + } catch (Exception exception1) { +@@ -110,17 +119,19 @@ + this.running = false; + } + +- return; +- } ++ // CraftBukkit start - decompile error: switch try / while statement ++ // return; ++ // } ++ // CraftBukkit end + } + +- private void send(int i, int j, String s) throws IOException { ++ private void send(int id, int j, String message) throws IOException { + ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(1248); + DataOutputStream dataoutputstream = new DataOutputStream(bytearrayoutputstream); +- byte[] abyte = s.getBytes(StandardCharsets.UTF_8); ++ byte[] abyte = message.getBytes(StandardCharsets.UTF_8); + + dataoutputstream.writeInt(Integer.reverseBytes(abyte.length + 10)); +- dataoutputstream.writeInt(Integer.reverseBytes(i)); ++ dataoutputstream.writeInt(Integer.reverseBytes(id)); + dataoutputstream.writeInt(Integer.reverseBytes(j)); + dataoutputstream.write(abyte); + dataoutputstream.write(0); +@@ -132,21 +143,20 @@ + this.send(-1, 2, ""); + } + +- private void sendCmdResponse(int i, String s) throws IOException { +- int j = s.length(); ++ private void sendCmdResponse(int id, String message) throws IOException { ++ int j = message.length(); + + do { + int k = 4096 <= j ? 4096 : j; + +- this.send(i, 0, s.substring(0, k)); +- s = s.substring(k); +- j = s.length(); ++ this.send(id, 0, message.substring(0, k)); ++ message = message.substring(k); ++ j = message.length(); + } while (0 != j); + + } + + @Override +- @Override + public void stop() { + this.running = false; + this.closeSocket(); diff --git a/patch-remap/mache-spigotflower/net/minecraft/stats/ServerRecipeBook.java.patch b/patch-remap/mache-spigotflower/net/minecraft/stats/ServerRecipeBook.java.patch new file mode 100644 index 0000000000..c30fcca472 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/stats/ServerRecipeBook.java.patch @@ -0,0 +1,171 @@ +--- a/net/minecraft/stats/ServerRecipeBook.java ++++ b/net/minecraft/stats/ServerRecipeBook.java +@@ -20,6 +20,8 @@ + import net.minecraft.world.item.crafting.RecipeManager; + import org.slf4j.Logger; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public class ServerRecipeBook extends RecipeBook { + + public static final String RECIPE_BOOK_TAG = "recipeBook"; +@@ -27,113 +29,114 @@ + + public ServerRecipeBook() {} + +- public int addRecipes(Collection> collection, ServerPlayer serverplayer) { ++ public int addRecipes(Collection> recipes, ServerPlayer player) { + List list = Lists.newArrayList(); + int i = 0; +- Iterator iterator = collection.iterator(); ++ Iterator iterator = recipes.iterator(); + + while (iterator.hasNext()) { + RecipeHolder recipeholder = (RecipeHolder) iterator.next(); +- ResourceLocation resourcelocation = recipeholder.id(); ++ ResourceLocation minecraftkey = recipeholder.id(); + +- if (!this.known.contains(resourcelocation) && !recipeholder.value().isSpecial()) { +- this.add(resourcelocation); +- this.addHighlight(resourcelocation); +- list.add(resourcelocation); +- CriteriaTriggers.RECIPE_UNLOCKED.trigger(serverplayer, recipeholder); ++ if (!this.known.contains(minecraftkey) && !recipeholder.value().isSpecial() && CraftEventFactory.handlePlayerRecipeListUpdateEvent(player, minecraftkey)) { // CraftBukkit ++ this.add(minecraftkey); ++ this.addHighlight(minecraftkey); ++ list.add(minecraftkey); ++ CriteriaTriggers.RECIPE_UNLOCKED.trigger(player, recipeholder); + ++i; + } + } + + if (list.size() > 0) { +- this.sendRecipes(ClientboundRecipePacket.State.ADD, serverplayer, list); ++ this.sendRecipes(ClientboundRecipePacket.Action.ADD, player, list); + } + + return i; + } + +- public int removeRecipes(Collection> collection, ServerPlayer serverplayer) { ++ public int removeRecipes(Collection> recipes, ServerPlayer player) { + List list = Lists.newArrayList(); + int i = 0; +- Iterator iterator = collection.iterator(); ++ Iterator iterator = recipes.iterator(); + + while (iterator.hasNext()) { + RecipeHolder recipeholder = (RecipeHolder) iterator.next(); +- ResourceLocation resourcelocation = recipeholder.id(); ++ ResourceLocation minecraftkey = recipeholder.id(); + +- if (this.known.contains(resourcelocation)) { +- this.remove(resourcelocation); +- list.add(resourcelocation); ++ if (this.known.contains(minecraftkey)) { ++ this.remove(minecraftkey); ++ list.add(minecraftkey); + ++i; + } + } + +- this.sendRecipes(ClientboundRecipePacket.State.REMOVE, serverplayer, list); ++ this.sendRecipes(ClientboundRecipePacket.Action.REMOVE, player, list); + return i; + } + +- private void sendRecipes(ClientboundRecipePacket.State clientboundrecipepacket_state, ServerPlayer serverplayer, List list) { +- serverplayer.connection.send(new ClientboundRecipePacket(clientboundrecipepacket_state, list, Collections.emptyList(), this.getBookSettings())); ++ private void sendRecipes(ClientboundRecipePacket.Action state, ServerPlayer player, List recipes) { ++ if (player.connection == null) return; // SPIGOT-4478 during PlayerLoginEvent ++ player.connection.send(new ClientboundRecipePacket(state, recipes, Collections.emptyList(), this.getBookSettings())); + } + + public CompoundTag toNbt() { +- CompoundTag compoundtag = new CompoundTag(); ++ CompoundTag nbttagcompound = new CompoundTag(); + +- this.getBookSettings().write(compoundtag); +- ListTag listtag = new ListTag(); ++ this.getBookSettings().write(nbttagcompound); ++ ListTag nbttaglist = new ListTag(); + Iterator iterator = this.known.iterator(); + + while (iterator.hasNext()) { +- ResourceLocation resourcelocation = (ResourceLocation) iterator.next(); ++ ResourceLocation minecraftkey = (ResourceLocation) iterator.next(); + +- listtag.add(StringTag.valueOf(resourcelocation.toString())); ++ nbttaglist.add(StringTag.valueOf(minecraftkey.toString())); + } + +- compoundtag.put("recipes", listtag); +- ListTag listtag1 = new ListTag(); ++ nbttagcompound.put("recipes", nbttaglist); ++ ListTag nbttaglist1 = new ListTag(); + Iterator iterator1 = this.highlight.iterator(); + + while (iterator1.hasNext()) { +- ResourceLocation resourcelocation1 = (ResourceLocation) iterator1.next(); ++ ResourceLocation minecraftkey1 = (ResourceLocation) iterator1.next(); + +- listtag1.add(StringTag.valueOf(resourcelocation1.toString())); ++ nbttaglist1.add(StringTag.valueOf(minecraftkey1.toString())); + } + +- compoundtag.put("toBeDisplayed", listtag1); +- return compoundtag; ++ nbttagcompound.put("toBeDisplayed", nbttaglist1); ++ return nbttagcompound; + } + +- public void fromNbt(CompoundTag compoundtag, RecipeManager recipemanager) { +- this.setBookSettings(RecipeBookSettings.read(compoundtag)); +- ListTag listtag = compoundtag.getList("recipes", 8); ++ public void fromNbt(CompoundTag tag, RecipeManager recipeManager) { ++ this.setBookSettings(RecipeBookSettings.read(tag)); ++ ListTag nbttaglist = tag.getList("recipes", 8); + +- this.loadRecipes(listtag, this::add, recipemanager); +- ListTag listtag1 = compoundtag.getList("toBeDisplayed", 8); ++ this.loadRecipes(nbttaglist, this::add, recipeManager); ++ ListTag nbttaglist1 = tag.getList("toBeDisplayed", 8); + +- this.loadRecipes(listtag1, this::addHighlight, recipemanager); ++ this.loadRecipes(nbttaglist1, this::addHighlight, recipeManager); + } + +- private void loadRecipes(ListTag listtag, Consumer> consumer, RecipeManager recipemanager) { +- for (int i = 0; i < listtag.size(); ++i) { +- String s = listtag.getString(i); ++ private void loadRecipes(ListTag tags, Consumer> recipeConsumer, RecipeManager recipeManager) { ++ for (int i = 0; i < tags.size(); ++i) { ++ String s = tags.getString(i); + + try { +- ResourceLocation resourcelocation = new ResourceLocation(s); +- Optional> optional = recipemanager.byKey(resourcelocation); ++ ResourceLocation minecraftkey = new ResourceLocation(s); ++ Optional> optional = recipeManager.byKey(minecraftkey); + + if (optional.isEmpty()) { +- ServerRecipeBook.LOGGER.error("Tried to load unrecognized recipe: {} removed now.", resourcelocation); ++ ServerRecipeBook.LOGGER.error("Tried to load unrecognized recipe: {} removed now.", minecraftkey); + } else { +- consumer.accept((RecipeHolder) optional.get()); ++ recipeConsumer.accept((RecipeHolder) optional.get()); + } +- } catch (ResourceLocationException resourcelocationexception) { ++ } catch (ResourceLocationException resourcekeyinvalidexception) { + ServerRecipeBook.LOGGER.error("Tried to load improperly formatted recipe: {} removed now.", s); + } + } + + } + +- public void sendInitialRecipeBook(ServerPlayer serverplayer) { +- serverplayer.connection.send(new ClientboundRecipePacket(ClientboundRecipePacket.State.INIT, this.known, this.highlight, this.getBookSettings())); ++ public void sendInitialRecipeBook(ServerPlayer player) { ++ player.connection.send(new ClientboundRecipePacket(ClientboundRecipePacket.Action.INIT, this.known, this.highlight, this.getBookSettings())); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/stats/ServerStatsCounter.java.patch b/patch-remap/mache-spigotflower/net/minecraft/stats/ServerStatsCounter.java.patch new file mode 100644 index 0000000000..ba76ef509e --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/stats/ServerStatsCounter.java.patch @@ -0,0 +1,184 @@ +--- a/net/minecraft/stats/ServerStatsCounter.java ++++ b/net/minecraft/stats/ServerStatsCounter.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.stats; + + import com.google.common.collect.Maps; +@@ -44,12 +45,12 @@ + private final File file; + private final Set> dirty = Sets.newHashSet(); + +- public ServerStatsCounter(MinecraftServer minecraftserver, File file) { +- this.server = minecraftserver; ++ public ServerStatsCounter(MinecraftServer server, File file) { ++ this.server = server; + this.file = file; + if (file.isFile()) { + try { +- this.parseLocal(minecraftserver.getFixerUpper(), FileUtils.readFileToString(file)); ++ this.parseLocal(server.getFixerUpper(), FileUtils.readFileToString(file)); + } catch (IOException ioexception) { + ServerStatsCounter.LOGGER.error("Couldn't read statistics file {}", file, ioexception); + } catch (JsonParseException jsonparseexception) { +@@ -69,9 +70,8 @@ + } + + @Override +- @Override +- public void setValue(Player player, Stat stat, int i) { +- super.setValue(player, stat, i); ++ public void setValue(Player player, Stat stat, int value) { ++ super.setValue(player, stat, value); + this.dirty.add(stat); + } + +@@ -82,9 +82,9 @@ + return set; + } + +- public void parseLocal(DataFixer datafixer, String s) { ++ public void parseLocal(DataFixer fixerUpper, String json) { + try { +- JsonReader jsonreader = new JsonReader(new StringReader(s)); ++ JsonReader jsonreader = new JsonReader(new StringReader(json)); + + label48: + { +@@ -93,15 +93,15 @@ + JsonElement jsonelement = Streams.parse(jsonreader); + + if (!jsonelement.isJsonNull()) { +- CompoundTag compoundtag = fromJson(jsonelement.getAsJsonObject()); ++ CompoundTag nbttagcompound = fromJson(jsonelement.getAsJsonObject()); + +- compoundtag = DataFixTypes.STATS.updateToCurrentVersion(datafixer, compoundtag, NbtUtils.getDataVersion(compoundtag, 1343)); +- if (!compoundtag.contains("stats", 10)) { ++ nbttagcompound = DataFixTypes.STATS.updateToCurrentVersion(fixerUpper, nbttagcompound, NbtUtils.getDataVersion(nbttagcompound, 1343)); ++ if (!nbttagcompound.contains("stats", 10)) { + break label48; + } + +- CompoundTag compoundtag1 = compoundtag.getCompound("stats"); +- Iterator iterator = compoundtag1.getAllKeys().iterator(); ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("stats"); ++ Iterator iterator = nbttagcompound1.getAllKeys().iterator(); + + while (true) { + if (!iterator.hasNext()) { +@@ -110,22 +110,22 @@ + + String s1 = (String) iterator.next(); + +- if (compoundtag1.contains(s1, 10)) { +- Util.ifElse(BuiltInRegistries.STAT_TYPE.getOptional(new ResourceLocation(s1)), (stattype) -> { +- CompoundTag compoundtag2 = compoundtag1.getCompound(s1); +- Iterator iterator1 = compoundtag2.getAllKeys().iterator(); ++ if (nbttagcompound1.contains(s1, 10)) { ++ Util.ifElse(BuiltInRegistries.STAT_TYPE.getOptional(new ResourceLocation(s1)), (statisticwrapper) -> { ++ CompoundTag nbttagcompound2 = nbttagcompound1.getCompound(s1); ++ Iterator iterator1 = nbttagcompound2.getAllKeys().iterator(); + + while (iterator1.hasNext()) { + String s2 = (String) iterator1.next(); + +- if (compoundtag2.contains(s2, 99)) { +- Util.ifElse(this.getStat(stattype, s2), (stat) -> { +- this.stats.put(stat, compoundtag2.getInt(s2)); ++ if (nbttagcompound2.contains(s2, 99)) { ++ Util.ifElse(this.getStat(statisticwrapper, s2), (statistic) -> { ++ this.stats.put(statistic, nbttagcompound2.getInt(s2)); + }, () -> { + ServerStatsCounter.LOGGER.warn("Invalid statistic in {}: Don't know what {} is", this.file, s2); + }); + } else { +- ServerStatsCounter.LOGGER.warn("Invalid statistic value in {}: Don't know what {} is for key {}", new Object[]{this.file, compoundtag2.get(s2), s2}); ++ ServerStatsCounter.LOGGER.warn("Invalid statistic value in {}: Don't know what {} is for key {}", new Object[]{this.file, nbttagcompound2.get(s2), s2}); + } + } + +@@ -158,36 +158,35 @@ + + } + +- private Optional> getStat(StatType stattype, String s) { +- Optional optional = Optional.ofNullable(ResourceLocation.tryParse(s)); +- Registry registry = stattype.getRegistry(); ++ private Optional> getStat(StatType type, String location) { ++ // CraftBukkit - decompile error start ++ Optional optional = Optional.ofNullable(ResourceLocation.tryParse(location)); ++ Registry iregistry = type.getRegistry(); + +- Objects.requireNonNull(registry); +- optional = optional.flatMap(registry::getOptional); +- Objects.requireNonNull(stattype); +- return optional.map(stattype::get); ++ return optional.flatMap(iregistry::getOptional).map(type::get); ++ // CraftBukkit - decompile error end + } + +- private static CompoundTag fromJson(JsonObject jsonobject) { +- CompoundTag compoundtag = new CompoundTag(); +- Iterator iterator = jsonobject.entrySet().iterator(); ++ private static CompoundTag fromJson(JsonObject json) { ++ CompoundTag nbttagcompound = new CompoundTag(); ++ Iterator iterator = json.entrySet().iterator(); + + while (iterator.hasNext()) { + Entry entry = (Entry) iterator.next(); + JsonElement jsonelement = (JsonElement) entry.getValue(); + + if (jsonelement.isJsonObject()) { +- compoundtag.put((String) entry.getKey(), fromJson(jsonelement.getAsJsonObject())); ++ nbttagcompound.put((String) entry.getKey(), fromJson(jsonelement.getAsJsonObject())); + } else if (jsonelement.isJsonPrimitive()) { + JsonPrimitive jsonprimitive = jsonelement.getAsJsonPrimitive(); + + if (jsonprimitive.isNumber()) { +- compoundtag.putInt((String) entry.getKey(), jsonprimitive.getAsInt()); ++ nbttagcompound.putInt((String) entry.getKey(), jsonprimitive.getAsInt()); + } + } + } + +- return compoundtag; ++ return nbttagcompound; + } + + protected String toJson() { +@@ -196,11 +195,11 @@ + + while (objectiterator.hasNext()) { + it.unimi.dsi.fastutil.objects.Object2IntMap.Entry> it_unimi_dsi_fastutil_objects_object2intmap_entry = (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry) objectiterator.next(); +- Stat stat = (Stat) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey(); ++ Stat statistic = (Stat) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey(); + +- ((JsonObject) map.computeIfAbsent(stat.getType(), (stattype) -> { ++ ((JsonObject) map.computeIfAbsent(statistic.getType(), (statisticwrapper) -> { + return new JsonObject(); +- })).addProperty(getKey(stat).toString(), it_unimi_dsi_fastutil_objects_object2intmap_entry.getIntValue()); ++ })).addProperty(getKey(statistic).toString(), it_unimi_dsi_fastutil_objects_object2intmap_entry.getIntValue()); + } + + JsonObject jsonobject = new JsonObject(); +@@ -227,16 +226,16 @@ + this.dirty.addAll(this.stats.keySet()); + } + +- public void sendStats(ServerPlayer serverplayer) { ++ public void sendStats(ServerPlayer player) { + Object2IntMap> object2intmap = new Object2IntOpenHashMap(); + Iterator iterator = this.getDirty().iterator(); + + while (iterator.hasNext()) { +- Stat stat = (Stat) iterator.next(); ++ Stat statistic = (Stat) iterator.next(); + +- object2intmap.put(stat, this.getValue(stat)); ++ object2intmap.put(statistic, this.getValue(statistic)); + } + +- serverplayer.connection.send(new ClientboundAwardStatsPacket(object2intmap)); ++ player.connection.send(new ClientboundAwardStatsPacket(object2intmap)); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/stats/StatsCounter.java.patch b/patch-remap/mache-spigotflower/net/minecraft/stats/StatsCounter.java.patch new file mode 100644 index 0000000000..66ccf90461 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/stats/StatsCounter.java.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/stats/StatsCounter.java ++++ b/net/minecraft/stats/StatsCounter.java +@@ -13,18 +13,24 @@ + this.stats.defaultReturnValue(0); + } + +- public void increment(Player player, Stat stat, int i) { +- int j = (int) Math.min((long) this.getValue(stat) + (long) i, 2147483647L); ++ public void increment(Player player, Stat stat, int amount) { ++ int j = (int) Math.min((long) this.getValue(stat) + (long) amount, 2147483647L); + ++ // CraftBukkit start - fire Statistic events ++ org.bukkit.event.Cancellable cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.handleStatisticsIncrease(player, stat, this.getValue(stat), j); ++ if (cancellable != null && cancellable.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.setValue(player, stat, j); + } + +- public void setValue(Player player, Stat stat, int i) { +- this.stats.put(stat, i); ++ public void setValue(Player player, Stat stat, int value) { ++ this.stats.put(stat, value); + } + +- public int getValue(StatType stattype, T t0) { +- return stattype.contains(t0) ? this.getValue(stattype.get(t0)) : 0; ++ public int getValue(StatType type, T value) { ++ return type.contains(value) ? this.getValue(type.get(value)) : 0; + } + + public int getValue(Stat stat) { diff --git a/patch-remap/mache-spigotflower/net/minecraft/util/SpawnUtil.java.patch b/patch-remap/mache-spigotflower/net/minecraft/util/SpawnUtil.java.patch new file mode 100644 index 0000000000..dfb8f72e66 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/util/SpawnUtil.java.patch @@ -0,0 +1,104 @@ +--- a/net/minecraft/util/SpawnUtil.java ++++ b/net/minecraft/util/SpawnUtil.java +@@ -7,33 +7,39 @@ + import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.LeavesBlock; + import net.minecraft.world.level.block.StainedGlassBlock; + import net.minecraft.world.level.block.StainedGlassPaneBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public class SpawnUtil { + + public SpawnUtil() {} + +- public static Optional trySpawnMob(EntityType entitytype, MobSpawnType mobspawntype, ServerLevel serverlevel, BlockPos blockpos, int i, int j, int k, SpawnUtil.Strategy spawnutil_strategy) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = blockpos.mutable(); ++ public static Optional trySpawnMob(EntityType entityType, EnumMobSpawn spawnType, ServerLevel level, BlockPos pos, int attempts, int j, int yOffset, SpawnUtil.Strategy strategy) { ++ // CraftBukkit start ++ return trySpawnMob(entityType, spawnType, level, pos, attempts, j, yOffset, strategy, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } + ++ public static Optional trySpawnMob(EntityType entitytypes, EnumMobSpawn enummobspawn, ServerLevel worldserver, BlockPos blockposition, int i, int j, int k, SpawnUtil.Strategy spawnutil_a, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ // CraftBukkit end ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = blockposition.mutable(); ++ + for (int l = 0; l < i; ++l) { +- int i1 = Mth.randomBetweenInclusive(serverlevel.random, -j, j); +- int j1 = Mth.randomBetweenInclusive(serverlevel.random, -j, j); ++ int i1 = Mth.randomBetweenInclusive(worldserver.random, -j, j); ++ int j1 = Mth.randomBetweenInclusive(worldserver.random, -j, j); + +- blockpos_mutableblockpos.setWithOffset(blockpos, i1, k, j1); +- if (serverlevel.getWorldBorder().isWithinBounds((BlockPos) blockpos_mutableblockpos) && moveToPossibleSpawnPosition(serverlevel, k, blockpos_mutableblockpos, spawnutil_strategy)) { +- T t0 = (Mob) entitytype.create(serverlevel, (CompoundTag) null, (Consumer) null, blockpos_mutableblockpos, mobspawntype, false, false); ++ blockposition_mutableblockposition.setWithOffset(blockposition, i1, k, j1); ++ if (worldserver.getWorldBorder().isWithinBounds((BlockPos) blockposition_mutableblockposition) && moveToPossibleSpawnPosition(worldserver, k, blockposition_mutableblockposition, spawnutil_a)) { ++ T t0 = entitytypes.create(worldserver, (CompoundTag) null, null, blockposition_mutableblockposition, enummobspawn, false, false); // CraftBukkit - decompile error + + if (t0 != null) { +- if (t0.checkSpawnRules(serverlevel, mobspawntype) && t0.checkSpawnObstruction(serverlevel)) { +- serverlevel.addFreshEntityWithPassengers(t0); ++ if (t0.checkSpawnRules(worldserver, enummobspawn) && t0.checkSpawnObstruction(worldserver)) { ++ worldserver.addFreshEntityWithPassengers(t0, reason); // CraftBukkit + return Optional.of(t0); + } + +@@ -45,21 +51,21 @@ + return Optional.empty(); + } + +- private static boolean moveToPossibleSpawnPosition(ServerLevel serverlevel, int i, BlockPos.MutableBlockPos blockpos_mutableblockpos, SpawnUtil.Strategy spawnutil_strategy) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos1 = (new BlockPos.MutableBlockPos()).set(blockpos_mutableblockpos); +- BlockState blockstate = serverlevel.getBlockState(blockpos_mutableblockpos1); ++ private static boolean moveToPossibleSpawnPosition(ServerLevel level, int yOffset, BlockPos.MutableBlockPos pos, SpawnUtil.Strategy strategy) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition1 = (new BlockPos.MutableBlockPos()).set(pos); ++ IBlockData iblockdata = level.getBlockState(blockposition_mutableblockposition1); + +- for (int j = i; j >= -i; --j) { +- blockpos_mutableblockpos.move(Direction.DOWN); +- blockpos_mutableblockpos1.setWithOffset(blockpos_mutableblockpos, Direction.UP); +- BlockState blockstate1 = serverlevel.getBlockState(blockpos_mutableblockpos); ++ for (int j = yOffset; j >= -yOffset; --j) { ++ pos.move(Direction.DOWN); ++ blockposition_mutableblockposition1.setWithOffset(pos, Direction.UP); ++ IBlockData iblockdata1 = level.getBlockState(pos); + +- if (spawnutil_strategy.canSpawnOn(serverlevel, blockpos_mutableblockpos, blockstate1, blockpos_mutableblockpos1, blockstate)) { +- blockpos_mutableblockpos.move(Direction.UP); ++ if (strategy.canSpawnOn(level, pos, iblockdata1, blockposition_mutableblockposition1, iblockdata)) { ++ pos.move(Direction.UP); + return true; + } + +- blockstate = blockstate1; ++ iblockdata = iblockdata1; + } + + return false; +@@ -69,13 +75,13 @@ + + /** @deprecated */ + @Deprecated +- SpawnUtil.Strategy LEGACY_IRON_GOLEM = (serverlevel, blockpos, blockstate, blockpos1, blockstate1) -> { +- return !blockstate.is(Blocks.COBWEB) && !blockstate.is(Blocks.CACTUS) && !blockstate.is(Blocks.GLASS_PANE) && !(blockstate.getBlock() instanceof StainedGlassPaneBlock) && !(blockstate.getBlock() instanceof StainedGlassBlock) && !(blockstate.getBlock() instanceof LeavesBlock) && !blockstate.is(Blocks.CONDUIT) && !blockstate.is(Blocks.ICE) && !blockstate.is(Blocks.TNT) && !blockstate.is(Blocks.GLOWSTONE) && !blockstate.is(Blocks.BEACON) && !blockstate.is(Blocks.SEA_LANTERN) && !blockstate.is(Blocks.FROSTED_ICE) && !blockstate.is(Blocks.TINTED_GLASS) && !blockstate.is(Blocks.GLASS) ? (blockstate1.isAir() || blockstate1.liquid()) && (blockstate.isSolid() || blockstate.is(Blocks.POWDER_SNOW)) : false; ++ SpawnUtil.Strategy LEGACY_IRON_GOLEM = (worldserver, blockposition, iblockdata, blockposition1, iblockdata1) -> { ++ return !iblockdata.is(Blocks.COBWEB) && !iblockdata.is(Blocks.CACTUS) && !iblockdata.is(Blocks.GLASS_PANE) && !(iblockdata.getBlock() instanceof StainedGlassPaneBlock) && !(iblockdata.getBlock() instanceof StainedGlassBlock) && !(iblockdata.getBlock() instanceof LeavesBlock) && !iblockdata.is(Blocks.CONDUIT) && !iblockdata.is(Blocks.ICE) && !iblockdata.is(Blocks.TNT) && !iblockdata.is(Blocks.GLOWSTONE) && !iblockdata.is(Blocks.BEACON) && !iblockdata.is(Blocks.SEA_LANTERN) && !iblockdata.is(Blocks.FROSTED_ICE) && !iblockdata.is(Blocks.TINTED_GLASS) && !iblockdata.is(Blocks.GLASS) ? (iblockdata1.isAir() || iblockdata1.liquid()) && (iblockdata.isSolid() || iblockdata.is(Blocks.POWDER_SNOW)) : false; + }; +- SpawnUtil.Strategy ON_TOP_OF_COLLIDER = (serverlevel, blockpos, blockstate, blockpos1, blockstate1) -> { +- return blockstate1.getCollisionShape(serverlevel, blockpos1).isEmpty() && Block.isFaceFull(blockstate.getCollisionShape(serverlevel, blockpos), Direction.UP); ++ SpawnUtil.Strategy ON_TOP_OF_COLLIDER = (worldserver, blockposition, iblockdata, blockposition1, iblockdata1) -> { ++ return iblockdata1.getCollisionShape(worldserver, blockposition1).isEmpty() && Block.isFaceFull(iblockdata.getCollisionShape(worldserver, blockposition), Direction.UP); + }; + +- boolean canSpawnOn(ServerLevel level, BlockPos blockPos, BlockState blockState, BlockPos blockPos1, BlockState blockState1); ++ boolean canSpawnOn(ServerLevel level, BlockPos blockposition, IBlockData iblockdata, BlockPos blockposition1, IBlockData iblockdata1); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/util/datafix/DataFixers.java.patch b/patch-remap/mache-spigotflower/net/minecraft/util/datafix/DataFixers.java.patch new file mode 100644 index 0000000000..058bda8c75 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/util/datafix/DataFixers.java.patch @@ -0,0 +1,1460 @@ +--- a/net/minecraft/util/datafix/DataFixers.java ++++ b/net/minecraft/util/datafix/DataFixers.java +@@ -21,183 +21,7 @@ + import java.util.stream.Stream; + import net.minecraft.SharedConstants; + import net.minecraft.Util; +-import net.minecraft.util.datafix.fixes.AbstractArrowPickupFix; +-import net.minecraft.util.datafix.fixes.AddFlagIfNotPresentFix; +-import net.minecraft.util.datafix.fixes.AddNewChoices; +-import net.minecraft.util.datafix.fixes.AdvancementsFix; +-import net.minecraft.util.datafix.fixes.AdvancementsRenameFix; +-import net.minecraft.util.datafix.fixes.AttributesRename; +-import net.minecraft.util.datafix.fixes.BedItemColorFix; +-import net.minecraft.util.datafix.fixes.BiomeFix; +-import net.minecraft.util.datafix.fixes.BitStorageAlignFix; +-import net.minecraft.util.datafix.fixes.BlendingDataFix; +-import net.minecraft.util.datafix.fixes.BlendingDataRemoveFromNetherEndFix; +-import net.minecraft.util.datafix.fixes.BlockEntityBannerColorFix; +-import net.minecraft.util.datafix.fixes.BlockEntityBlockStateFix; +-import net.minecraft.util.datafix.fixes.BlockEntityCustomNameToComponentFix; +-import net.minecraft.util.datafix.fixes.BlockEntityIdFix; +-import net.minecraft.util.datafix.fixes.BlockEntityJukeboxFix; +-import net.minecraft.util.datafix.fixes.BlockEntityKeepPacked; +-import net.minecraft.util.datafix.fixes.BlockEntityRenameFix; +-import net.minecraft.util.datafix.fixes.BlockEntityShulkerBoxColorFix; +-import net.minecraft.util.datafix.fixes.BlockEntitySignDoubleSidedEditableTextFix; +-import net.minecraft.util.datafix.fixes.BlockEntitySignTextStrictJsonFix; +-import net.minecraft.util.datafix.fixes.BlockEntityUUIDFix; +-import net.minecraft.util.datafix.fixes.BlockNameFlatteningFix; +-import net.minecraft.util.datafix.fixes.BlockRenameFix; +-import net.minecraft.util.datafix.fixes.BlockRenameFixWithJigsaw; +-import net.minecraft.util.datafix.fixes.BlockStateStructureTemplateFix; +-import net.minecraft.util.datafix.fixes.CatTypeFix; +-import net.minecraft.util.datafix.fixes.CauldronRenameFix; +-import net.minecraft.util.datafix.fixes.CavesAndCliffsRenames; +-import net.minecraft.util.datafix.fixes.ChunkBedBlockEntityInjecterFix; +-import net.minecraft.util.datafix.fixes.ChunkBiomeFix; +-import net.minecraft.util.datafix.fixes.ChunkDeleteIgnoredLightDataFix; +-import net.minecraft.util.datafix.fixes.ChunkDeleteLightFix; +-import net.minecraft.util.datafix.fixes.ChunkHeightAndBiomeFix; +-import net.minecraft.util.datafix.fixes.ChunkLightRemoveFix; +-import net.minecraft.util.datafix.fixes.ChunkPalettedStorageFix; +-import net.minecraft.util.datafix.fixes.ChunkProtoTickListFix; +-import net.minecraft.util.datafix.fixes.ChunkRenamesFix; +-import net.minecraft.util.datafix.fixes.ChunkStatusFix; +-import net.minecraft.util.datafix.fixes.ChunkStatusFix2; +-import net.minecraft.util.datafix.fixes.ChunkStructuresTemplateRenameFix; +-import net.minecraft.util.datafix.fixes.ChunkToProtochunkFix; +-import net.minecraft.util.datafix.fixes.ColorlessShulkerEntityFix; +-import net.minecraft.util.datafix.fixes.CriteriaRenameFix; +-import net.minecraft.util.datafix.fixes.DecoratedPotFieldRenameFix; +-import net.minecraft.util.datafix.fixes.DropInvalidSignDataFix; +-import net.minecraft.util.datafix.fixes.DyeItemRenameFix; +-import net.minecraft.util.datafix.fixes.EffectDurationFix; +-import net.minecraft.util.datafix.fixes.EntityArmorStandSilentFix; +-import net.minecraft.util.datafix.fixes.EntityBlockStateFix; +-import net.minecraft.util.datafix.fixes.EntityBrushableBlockFieldsRenameFix; +-import net.minecraft.util.datafix.fixes.EntityCatSplitFix; +-import net.minecraft.util.datafix.fixes.EntityCodSalmonFix; +-import net.minecraft.util.datafix.fixes.EntityCustomNameToComponentFix; +-import net.minecraft.util.datafix.fixes.EntityElderGuardianSplitFix; +-import net.minecraft.util.datafix.fixes.EntityEquipmentToArmorAndHandFix; +-import net.minecraft.util.datafix.fixes.EntityGoatMissingStateFix; +-import net.minecraft.util.datafix.fixes.EntityHealthFix; +-import net.minecraft.util.datafix.fixes.EntityHorseSaddleFix; +-import net.minecraft.util.datafix.fixes.EntityHorseSplitFix; +-import net.minecraft.util.datafix.fixes.EntityIdFix; +-import net.minecraft.util.datafix.fixes.EntityItemFrameDirectionFix; +-import net.minecraft.util.datafix.fixes.EntityMinecartIdentifiersFix; +-import net.minecraft.util.datafix.fixes.EntityPaintingFieldsRenameFix; +-import net.minecraft.util.datafix.fixes.EntityPaintingItemFrameDirectionFix; +-import net.minecraft.util.datafix.fixes.EntityPaintingMotiveFix; +-import net.minecraft.util.datafix.fixes.EntityProjectileOwnerFix; +-import net.minecraft.util.datafix.fixes.EntityPufferfishRenameFix; +-import net.minecraft.util.datafix.fixes.EntityRavagerRenameFix; +-import net.minecraft.util.datafix.fixes.EntityRedundantChanceTagsFix; +-import net.minecraft.util.datafix.fixes.EntityRidingToPassengersFix; +-import net.minecraft.util.datafix.fixes.EntityShulkerColorFix; +-import net.minecraft.util.datafix.fixes.EntityShulkerRotationFix; +-import net.minecraft.util.datafix.fixes.EntitySkeletonSplitFix; +-import net.minecraft.util.datafix.fixes.EntityStringUuidFix; +-import net.minecraft.util.datafix.fixes.EntityTheRenameningFix; +-import net.minecraft.util.datafix.fixes.EntityTippedArrowFix; +-import net.minecraft.util.datafix.fixes.EntityUUIDFix; +-import net.minecraft.util.datafix.fixes.EntityVariantFix; +-import net.minecraft.util.datafix.fixes.EntityWolfColorFix; +-import net.minecraft.util.datafix.fixes.EntityZombieSplitFix; +-import net.minecraft.util.datafix.fixes.EntityZombieVillagerTypeFix; +-import net.minecraft.util.datafix.fixes.EntityZombifiedPiglinRenameFix; +-import net.minecraft.util.datafix.fixes.FeatureFlagRemoveFix; +-import net.minecraft.util.datafix.fixes.FilteredBooksFix; +-import net.minecraft.util.datafix.fixes.FilteredSignsFix; +-import net.minecraft.util.datafix.fixes.FixProjectileStoredItem; +-import net.minecraft.util.datafix.fixes.ForcePoiRebuild; +-import net.minecraft.util.datafix.fixes.FurnaceRecipeFix; +-import net.minecraft.util.datafix.fixes.GoatHornIdFix; +-import net.minecraft.util.datafix.fixes.GossipUUIDFix; +-import net.minecraft.util.datafix.fixes.HeightmapRenamingFix; +-import net.minecraft.util.datafix.fixes.IglooMetadataRemovalFix; +-import net.minecraft.util.datafix.fixes.ItemBannerColorFix; +-import net.minecraft.util.datafix.fixes.ItemCustomNameToComponentFix; +-import net.minecraft.util.datafix.fixes.ItemIdFix; +-import net.minecraft.util.datafix.fixes.ItemLoreFix; +-import net.minecraft.util.datafix.fixes.ItemPotionFix; +-import net.minecraft.util.datafix.fixes.ItemRemoveBlockEntityTagFix; +-import net.minecraft.util.datafix.fixes.ItemRenameFix; +-import net.minecraft.util.datafix.fixes.ItemShulkerBoxColorFix; +-import net.minecraft.util.datafix.fixes.ItemSpawnEggFix; +-import net.minecraft.util.datafix.fixes.ItemStackEnchantmentNamesFix; +-import net.minecraft.util.datafix.fixes.ItemStackMapIdFix; +-import net.minecraft.util.datafix.fixes.ItemStackSpawnEggFix; +-import net.minecraft.util.datafix.fixes.ItemStackTheFlatteningFix; +-import net.minecraft.util.datafix.fixes.ItemStackUUIDFix; +-import net.minecraft.util.datafix.fixes.ItemWaterPotionFix; +-import net.minecraft.util.datafix.fixes.ItemWrittenBookPagesStrictJsonFix; +-import net.minecraft.util.datafix.fixes.JigsawPropertiesFix; +-import net.minecraft.util.datafix.fixes.JigsawRotationFix; +-import net.minecraft.util.datafix.fixes.LeavesFix; +-import net.minecraft.util.datafix.fixes.LegacyDragonFightFix; +-import net.minecraft.util.datafix.fixes.LevelDataGeneratorOptionsFix; +-import net.minecraft.util.datafix.fixes.LevelFlatGeneratorInfoFix; +-import net.minecraft.util.datafix.fixes.LevelLegacyWorldGenSettingsFix; +-import net.minecraft.util.datafix.fixes.LevelUUIDFix; +-import net.minecraft.util.datafix.fixes.MapIdFix; +-import net.minecraft.util.datafix.fixes.MemoryExpiryDataFix; +-import net.minecraft.util.datafix.fixes.MissingDimensionFix; +-import net.minecraft.util.datafix.fixes.MobEffectIdFix; +-import net.minecraft.util.datafix.fixes.MobSpawnerEntityIdentifiersFix; +-import net.minecraft.util.datafix.fixes.NamedEntityFix; +-import net.minecraft.util.datafix.fixes.NamespacedTypeRenameFix; +-import net.minecraft.util.datafix.fixes.NewVillageFix; +-import net.minecraft.util.datafix.fixes.ObjectiveDisplayNameFix; +-import net.minecraft.util.datafix.fixes.ObjectiveRenderTypeFix; +-import net.minecraft.util.datafix.fixes.OminousBannerBlockEntityRenameFix; +-import net.minecraft.util.datafix.fixes.OminousBannerRenameFix; +-import net.minecraft.util.datafix.fixes.OptionsAccessibilityOnboardFix; +-import net.minecraft.util.datafix.fixes.OptionsAddTextBackgroundFix; +-import net.minecraft.util.datafix.fixes.OptionsAmbientOcclusionFix; +-import net.minecraft.util.datafix.fixes.OptionsForceVBOFix; +-import net.minecraft.util.datafix.fixes.OptionsKeyLwjgl3Fix; +-import net.minecraft.util.datafix.fixes.OptionsKeyTranslationFix; +-import net.minecraft.util.datafix.fixes.OptionsLowerCaseLanguageFix; +-import net.minecraft.util.datafix.fixes.OptionsProgrammerArtFix; +-import net.minecraft.util.datafix.fixes.OptionsRenameFieldFix; +-import net.minecraft.util.datafix.fixes.OverreachingTickFix; +-import net.minecraft.util.datafix.fixes.PlayerUUIDFix; +-import net.minecraft.util.datafix.fixes.PoiTypeRemoveFix; +-import net.minecraft.util.datafix.fixes.PoiTypeRenameFix; +-import net.minecraft.util.datafix.fixes.PrimedTntBlockStateFixer; +-import net.minecraft.util.datafix.fixes.RandomSequenceSettingsFix; +-import net.minecraft.util.datafix.fixes.RecipesFix; +-import net.minecraft.util.datafix.fixes.RecipesRenameningFix; +-import net.minecraft.util.datafix.fixes.RedstoneWireConnectionsFix; +-import net.minecraft.util.datafix.fixes.References; +-import net.minecraft.util.datafix.fixes.RemapChunkStatusFix; +-import net.minecraft.util.datafix.fixes.RemoveGolemGossipFix; +-import net.minecraft.util.datafix.fixes.RenamedCoralFansFix; +-import net.minecraft.util.datafix.fixes.RenamedCoralFix; +-import net.minecraft.util.datafix.fixes.ReorganizePoi; +-import net.minecraft.util.datafix.fixes.SavedDataFeaturePoolElementFix; +-import net.minecraft.util.datafix.fixes.SavedDataUUIDFix; +-import net.minecraft.util.datafix.fixes.ScoreboardDisplaySlotFix; +-import net.minecraft.util.datafix.fixes.SpawnerDataFix; +-import net.minecraft.util.datafix.fixes.StatsCounterFix; +-import net.minecraft.util.datafix.fixes.StatsRenameFix; +-import net.minecraft.util.datafix.fixes.StriderGravityFix; +-import net.minecraft.util.datafix.fixes.StructureReferenceCountFix; +-import net.minecraft.util.datafix.fixes.StructureSettingsFlattenFix; +-import net.minecraft.util.datafix.fixes.StructuresBecomeConfiguredFix; +-import net.minecraft.util.datafix.fixes.TeamDisplayNameFix; +-import net.minecraft.util.datafix.fixes.TrappedChestBlockEntityFix; +-import net.minecraft.util.datafix.fixes.VariantRenameFix; +-import net.minecraft.util.datafix.fixes.VillagerDataFix; +-import net.minecraft.util.datafix.fixes.VillagerFollowRangeFix; +-import net.minecraft.util.datafix.fixes.VillagerRebuildLevelAndXpFix; +-import net.minecraft.util.datafix.fixes.VillagerTradeFix; +-import net.minecraft.util.datafix.fixes.WallPropertyFix; +-import net.minecraft.util.datafix.fixes.WeaponSmithChestLootTableFix; +-import net.minecraft.util.datafix.fixes.WorldGenSettingsDisallowOldCustomWorldsFix; +-import net.minecraft.util.datafix.fixes.WorldGenSettingsFix; +-import net.minecraft.util.datafix.fixes.WorldGenSettingsHeightAndBiomeFix; +-import net.minecraft.util.datafix.fixes.WriteAndReadFix; +-import net.minecraft.util.datafix.fixes.ZombieVillagerRebuildXpFix; ++import net.minecraft.util.datafix.fixes.*; + import net.minecraft.util.datafix.schemas.NamespacedSchema; + import net.minecraft.util.datafix.schemas.V100; + import net.minecraft.util.datafix.schemas.V102; +@@ -289,599 +113,613 @@ + return DataFixers.dataFixer; + } + +- private static synchronized DataFixer createFixerUpper(Set set) { ++ private static synchronized DataFixer createFixerUpper(Set typeReferences) { + DataFixerBuilder datafixerbuilder = new DataFixerBuilder(SharedConstants.getCurrentVersion().getDataVersion().getVersion()); + + addFixers(datafixerbuilder); +- if (set.isEmpty()) { ++ if (typeReferences.isEmpty()) { + return datafixerbuilder.buildUnoptimized(); + } else { + ExecutorService executorservice = Executors.newSingleThreadExecutor((new ThreadFactoryBuilder()).setNameFormat("Datafixer Bootstrap").setDaemon(true).setPriority(1).build()); + +- return datafixerbuilder.buildOptimized(set, executorservice); ++ return datafixerbuilder.buildOptimized(typeReferences, executorservice); + } + } + +- private static void addFixers(DataFixerBuilder datafixerbuilder) { +- datafixerbuilder.addSchema(99, V99::new); +- Schema schema = datafixerbuilder.addSchema(100, V100::new); ++ private static void addFixers(DataFixerBuilder builder) { ++ builder.addSchema(99, V99::new); ++ Schema schema = builder.addSchema(100, V100::new); + +- datafixerbuilder.addFixer(new EntityEquipmentToArmorAndHandFix(schema, true)); +- Schema schema1 = datafixerbuilder.addSchema(101, DataFixers.SAME); ++ builder.addFixer(new EntityEquipmentToArmorAndHandFix(schema, true)); ++ Schema schema1 = builder.addSchema(101, DataFixers.SAME); + +- datafixerbuilder.addFixer(new BlockEntitySignTextStrictJsonFix(schema1, false)); +- Schema schema2 = datafixerbuilder.addSchema(102, V102::new); ++ builder.addFixer(new BlockEntitySignTextStrictJsonFix(schema1, false)); ++ Schema schema2 = builder.addSchema(102, V102::new); + +- datafixerbuilder.addFixer(new ItemIdFix(schema2, true)); +- datafixerbuilder.addFixer(new ItemPotionFix(schema2, false)); +- Schema schema3 = datafixerbuilder.addSchema(105, DataFixers.SAME); ++ builder.addFixer(new ItemIdFix(schema2, true)); ++ builder.addFixer(new ItemPotionFix(schema2, false)); ++ Schema schema3 = builder.addSchema(105, DataFixers.SAME); + +- datafixerbuilder.addFixer(new ItemSpawnEggFix(schema3, true)); +- Schema schema4 = datafixerbuilder.addSchema(106, V106::new); ++ builder.addFixer(new ItemSpawnEggFix(schema3, true)); ++ Schema schema4 = builder.addSchema(106, V106::new); + +- datafixerbuilder.addFixer(new MobSpawnerEntityIdentifiersFix(schema4, true)); +- Schema schema5 = datafixerbuilder.addSchema(107, V107::new); ++ builder.addFixer(new MobSpawnerEntityIdentifiersFix(schema4, true)); ++ Schema schema5 = builder.addSchema(107, V107::new); + +- datafixerbuilder.addFixer(new EntityMinecartIdentifiersFix(schema5, true)); +- Schema schema6 = datafixerbuilder.addSchema(108, DataFixers.SAME); ++ builder.addFixer(new EntityMinecartIdentifiersFix(schema5, true)); ++ Schema schema6 = builder.addSchema(108, DataFixers.SAME); + +- datafixerbuilder.addFixer(new EntityStringUuidFix(schema6, true)); +- Schema schema7 = datafixerbuilder.addSchema(109, DataFixers.SAME); ++ builder.addFixer(new EntityStringUuidFix(schema6, true)); ++ Schema schema7 = builder.addSchema(109, DataFixers.SAME); + +- datafixerbuilder.addFixer(new EntityHealthFix(schema7, true)); +- Schema schema8 = datafixerbuilder.addSchema(110, DataFixers.SAME); ++ builder.addFixer(new EntityHealthFix(schema7, true)); ++ Schema schema8 = builder.addSchema(110, DataFixers.SAME); + +- datafixerbuilder.addFixer(new EntityHorseSaddleFix(schema8, true)); +- Schema schema9 = datafixerbuilder.addSchema(111, DataFixers.SAME); ++ builder.addFixer(new EntityHorseSaddleFix(schema8, true)); ++ Schema schema9 = builder.addSchema(111, DataFixers.SAME); + +- datafixerbuilder.addFixer(new EntityPaintingItemFrameDirectionFix(schema9, true)); +- Schema schema10 = datafixerbuilder.addSchema(113, DataFixers.SAME); ++ builder.addFixer(new EntityPaintingItemFrameDirectionFix(schema9, true)); ++ Schema schema10 = builder.addSchema(113, DataFixers.SAME); + +- datafixerbuilder.addFixer(new EntityRedundantChanceTagsFix(schema10, true)); +- Schema schema11 = datafixerbuilder.addSchema(135, V135::new); ++ builder.addFixer(new EntityRedundantChanceTagsFix(schema10, true)); ++ Schema schema11 = builder.addSchema(135, V135::new); + +- datafixerbuilder.addFixer(new EntityRidingToPassengersFix(schema11, true)); +- Schema schema12 = datafixerbuilder.addSchema(143, V143::new); ++ builder.addFixer(new EntityRidingToPassengersFix(schema11, true)); ++ Schema schema12 = builder.addSchema(143, V143::new); + +- datafixerbuilder.addFixer(new EntityTippedArrowFix(schema12, true)); +- Schema schema13 = datafixerbuilder.addSchema(147, DataFixers.SAME); ++ builder.addFixer(new EntityTippedArrowFix(schema12, true)); ++ Schema schema13 = builder.addSchema(147, DataFixers.SAME); + +- datafixerbuilder.addFixer(new EntityArmorStandSilentFix(schema13, true)); +- Schema schema14 = datafixerbuilder.addSchema(165, DataFixers.SAME); ++ builder.addFixer(new EntityArmorStandSilentFix(schema13, true)); ++ Schema schema14 = builder.addSchema(165, DataFixers.SAME); + +- datafixerbuilder.addFixer(new ItemWrittenBookPagesStrictJsonFix(schema14, true)); +- Schema schema15 = datafixerbuilder.addSchema(501, V501::new); ++ builder.addFixer(new ItemWrittenBookPagesStrictJsonFix(schema14, true)); ++ Schema schema15 = builder.addSchema(501, V501::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema15, "Add 1.10 entities fix", References.ENTITY)); +- Schema schema16 = datafixerbuilder.addSchema(502, DataFixers.SAME); ++ builder.addFixer(new AddNewChoices(schema15, "Add 1.10 entities fix", DataConverterTypes.ENTITY)); ++ Schema schema16 = builder.addSchema(502, DataFixers.SAME); + +- datafixerbuilder.addFixer(ItemRenameFix.create(schema16, "cooked_fished item renamer", (s) -> { ++ builder.addFixer(ItemRenameFix.create(schema16, "cooked_fished item renamer", (s) -> { + return Objects.equals(NamespacedSchema.ensureNamespaced(s), "minecraft:cooked_fished") ? "minecraft:cooked_fish" : s; + })); +- datafixerbuilder.addFixer(new EntityZombieVillagerTypeFix(schema16, false)); +- Schema schema17 = datafixerbuilder.addSchema(505, DataFixers.SAME); ++ builder.addFixer(new EntityZombieVillagerTypeFix(schema16, false)); ++ Schema schema17 = builder.addSchema(505, DataFixers.SAME); + +- datafixerbuilder.addFixer(new OptionsForceVBOFix(schema17, false)); +- Schema schema18 = datafixerbuilder.addSchema(700, V700::new); ++ builder.addFixer(new OptionsForceVBOFix(schema17, false)); ++ Schema schema18 = builder.addSchema(700, V700::new); + +- datafixerbuilder.addFixer(new EntityElderGuardianSplitFix(schema18, true)); +- Schema schema19 = datafixerbuilder.addSchema(701, V701::new); ++ builder.addFixer(new EntityElderGuardianSplitFix(schema18, true)); ++ Schema schema19 = builder.addSchema(701, V701::new); + +- datafixerbuilder.addFixer(new EntitySkeletonSplitFix(schema19, true)); +- Schema schema20 = datafixerbuilder.addSchema(702, V702::new); ++ builder.addFixer(new EntitySkeletonSplitFix(schema19, true)); ++ Schema schema20 = builder.addSchema(702, V702::new); + +- datafixerbuilder.addFixer(new EntityZombieSplitFix(schema20, true)); +- Schema schema21 = datafixerbuilder.addSchema(703, V703::new); ++ builder.addFixer(new EntityZombieSplitFix(schema20, true)); ++ Schema schema21 = builder.addSchema(703, V703::new); + +- datafixerbuilder.addFixer(new EntityHorseSplitFix(schema21, true)); +- Schema schema22 = datafixerbuilder.addSchema(704, V704::new); ++ builder.addFixer(new EntityHorseSplitFix(schema21, true)); ++ Schema schema22 = builder.addSchema(704, V704::new); + +- datafixerbuilder.addFixer(new BlockEntityIdFix(schema22, true)); +- Schema schema23 = datafixerbuilder.addSchema(705, V705::new); ++ builder.addFixer(new BlockEntityIdFix(schema22, true)); ++ Schema schema23 = builder.addSchema(705, V705::new); + +- datafixerbuilder.addFixer(new EntityIdFix(schema23, true)); +- Schema schema24 = datafixerbuilder.addSchema(804, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new EntityIdFix(schema23, true)); ++ Schema schema24 = builder.addSchema(804, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new ItemBannerColorFix(schema24, true)); +- Schema schema25 = datafixerbuilder.addSchema(806, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new ItemBannerColorFix(schema24, true)); ++ Schema schema25 = builder.addSchema(806, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new ItemWaterPotionFix(schema25, false)); +- Schema schema26 = datafixerbuilder.addSchema(808, V808::new); ++ builder.addFixer(new ItemWaterPotionFix(schema25, false)); ++ Schema schema26 = builder.addSchema(808, V808::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema26, "added shulker box", References.BLOCK_ENTITY)); +- Schema schema27 = datafixerbuilder.addSchema(808, 1, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new AddNewChoices(schema26, "added shulker box", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema27 = builder.addSchema(808, 1, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new EntityShulkerColorFix(schema27, false)); +- Schema schema28 = datafixerbuilder.addSchema(813, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new EntityShulkerColorFix(schema27, false)); ++ Schema schema28 = builder.addSchema(813, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new ItemShulkerBoxColorFix(schema28, false)); +- datafixerbuilder.addFixer(new BlockEntityShulkerBoxColorFix(schema28, false)); +- Schema schema29 = datafixerbuilder.addSchema(816, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new ItemShulkerBoxColorFix(schema28, false)); ++ builder.addFixer(new BlockEntityShulkerBoxColorFix(schema28, false)); ++ Schema schema29 = builder.addSchema(816, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new OptionsLowerCaseLanguageFix(schema29, false)); +- Schema schema30 = datafixerbuilder.addSchema(820, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new OptionsLowerCaseLanguageFix(schema29, false)); ++ Schema schema30 = builder.addSchema(820, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(ItemRenameFix.create(schema30, "totem item renamer", createRenamer("minecraft:totem", "minecraft:totem_of_undying"))); +- Schema schema31 = datafixerbuilder.addSchema(1022, V1022::new); ++ builder.addFixer(ItemRenameFix.create(schema30, "totem item renamer", createRenamer("minecraft:totem", "minecraft:totem_of_undying"))); ++ Schema schema31 = builder.addSchema(1022, V1022::new); + +- datafixerbuilder.addFixer(new WriteAndReadFix(schema31, "added shoulder entities to players", References.PLAYER)); +- Schema schema32 = datafixerbuilder.addSchema(1125, V1125::new); ++ builder.addFixer(new WriteAndReadFix(schema31, "added shoulder entities to players", DataConverterTypes.PLAYER)); ++ Schema schema32 = builder.addSchema(1125, V1125::new); + +- datafixerbuilder.addFixer(new ChunkBedBlockEntityInjecterFix(schema32, true)); +- datafixerbuilder.addFixer(new BedItemColorFix(schema32, false)); +- Schema schema33 = datafixerbuilder.addSchema(1344, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new ChunkBedBlockEntityInjecterFix(schema32, true)); ++ builder.addFixer(new BedItemColorFix(schema32, false)); ++ Schema schema33 = builder.addSchema(1344, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new OptionsKeyLwjgl3Fix(schema33, false)); +- Schema schema34 = datafixerbuilder.addSchema(1446, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new OptionsKeyLwjgl3Fix(schema33, false)); ++ Schema schema34 = builder.addSchema(1446, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new OptionsKeyTranslationFix(schema34, false)); +- Schema schema35 = datafixerbuilder.addSchema(1450, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new OptionsKeyTranslationFix(schema34, false)); ++ Schema schema35 = builder.addSchema(1450, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new BlockStateStructureTemplateFix(schema35, false)); +- Schema schema36 = datafixerbuilder.addSchema(1451, V1451::new); ++ builder.addFixer(new BlockStateStructureTemplateFix(schema35, false)); ++ Schema schema36 = builder.addSchema(1451, V1451::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema36, "AddTrappedChestFix", References.BLOCK_ENTITY)); +- Schema schema37 = datafixerbuilder.addSchema(1451, 1, V1451_1::new); ++ builder.addFixer(new AddNewChoices(schema36, "AddTrappedChestFix", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema37 = builder.addSchema(1451, 1, V1451_1::new); + +- datafixerbuilder.addFixer(new ChunkPalettedStorageFix(schema37, true)); +- Schema schema38 = datafixerbuilder.addSchema(1451, 2, V1451_2::new); ++ builder.addFixer(new ChunkPalettedStorageFix(schema37, true)); ++ Schema schema38 = builder.addSchema(1451, 2, V1451_2::new); + +- datafixerbuilder.addFixer(new BlockEntityBlockStateFix(schema38, true)); +- Schema schema39 = datafixerbuilder.addSchema(1451, 3, V1451_3::new); ++ builder.addFixer(new BlockEntityBlockStateFix(schema38, true)); ++ Schema schema39 = builder.addSchema(1451, 3, V1451_3::new); + +- datafixerbuilder.addFixer(new EntityBlockStateFix(schema39, true)); +- datafixerbuilder.addFixer(new ItemStackMapIdFix(schema39, false)); +- Schema schema40 = datafixerbuilder.addSchema(1451, 4, V1451_4::new); ++ builder.addFixer(new EntityBlockStateFix(schema39, true)); ++ builder.addFixer(new ItemStackMapIdFix(schema39, false)); ++ Schema schema40 = builder.addSchema(1451, 4, V1451_4::new); + +- datafixerbuilder.addFixer(new BlockNameFlatteningFix(schema40, true)); +- datafixerbuilder.addFixer(new ItemStackTheFlatteningFix(schema40, false)); +- Schema schema41 = datafixerbuilder.addSchema(1451, 5, V1451_5::new); ++ builder.addFixer(new BlockNameFlatteningFix(schema40, true)); ++ builder.addFixer(new ItemStackTheFlatteningFix(schema40, false)); ++ Schema schema41 = builder.addSchema(1451, 5, V1451_5::new); + +- datafixerbuilder.addFixer(new ItemRemoveBlockEntityTagFix(schema41, false, Set.of("minecraft:note_block", "minecraft:flower_pot", "minecraft:dandelion", "minecraft:poppy", "minecraft:blue_orchid", "minecraft:allium", "minecraft:azure_bluet", "minecraft:red_tulip", "minecraft:orange_tulip", "minecraft:white_tulip", "minecraft:pink_tulip", "minecraft:oxeye_daisy", "minecraft:cactus", "minecraft:brown_mushroom", "minecraft:red_mushroom", "minecraft:oak_sapling", "minecraft:spruce_sapling", "minecraft:birch_sapling", "minecraft:jungle_sapling", "minecraft:acacia_sapling", "minecraft:dark_oak_sapling", "minecraft:dead_bush", "minecraft:fern"))); +- datafixerbuilder.addFixer(new AddNewChoices(schema41, "RemoveNoteBlockFlowerPotFix", References.BLOCK_ENTITY)); +- datafixerbuilder.addFixer(new ItemStackSpawnEggFix(schema41, false, "minecraft:spawn_egg")); +- datafixerbuilder.addFixer(new EntityWolfColorFix(schema41, false)); +- datafixerbuilder.addFixer(new BlockEntityBannerColorFix(schema41, false)); +- datafixerbuilder.addFixer(new LevelFlatGeneratorInfoFix(schema41, false)); +- Schema schema42 = datafixerbuilder.addSchema(1451, 6, V1451_6::new); ++ builder.addFixer(new ItemRemoveBlockEntityTagFix(schema41, false, Set.of("minecraft:note_block", "minecraft:flower_pot", "minecraft:dandelion", "minecraft:poppy", "minecraft:blue_orchid", "minecraft:allium", "minecraft:azure_bluet", "minecraft:red_tulip", "minecraft:orange_tulip", "minecraft:white_tulip", "minecraft:pink_tulip", "minecraft:oxeye_daisy", "minecraft:cactus", "minecraft:brown_mushroom", "minecraft:red_mushroom", "minecraft:oak_sapling", "minecraft:spruce_sapling", "minecraft:birch_sapling", "minecraft:jungle_sapling", "minecraft:acacia_sapling", "minecraft:dark_oak_sapling", "minecraft:dead_bush", "minecraft:fern"))); ++ builder.addFixer(new AddNewChoices(schema41, "RemoveNoteBlockFlowerPotFix", DataConverterTypes.BLOCK_ENTITY)); ++ builder.addFixer(new ItemStackSpawnEggFix(schema41, false, "minecraft:spawn_egg")); ++ builder.addFixer(new EntityWolfColorFix(schema41, false)); ++ builder.addFixer(new BlockEntityBannerColorFix(schema41, false)); ++ builder.addFixer(new LevelFlatGeneratorInfoFix(schema41, false)); ++ Schema schema42 = builder.addSchema(1451, 6, V1451_6::new); + +- datafixerbuilder.addFixer(new StatsCounterFix(schema42, true)); +- datafixerbuilder.addFixer(new BlockEntityJukeboxFix(schema42, false)); +- Schema schema43 = datafixerbuilder.addSchema(1451, 7, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new StatsCounterFix(schema42, true)); ++ builder.addFixer(new BlockEntityJukeboxFix(schema42, false)); ++ Schema schema43 = builder.addSchema(1451, 7, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new VillagerTradeFix(schema43, false)); +- Schema schema44 = datafixerbuilder.addSchema(1456, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new VillagerTradeFix(schema43, false)); ++ Schema schema44 = builder.addSchema(1456, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new EntityItemFrameDirectionFix(schema44, false)); +- Schema schema45 = datafixerbuilder.addSchema(1458, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new EntityItemFrameDirectionFix(schema44, false)); ++ Schema schema45 = builder.addSchema(1458, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new EntityCustomNameToComponentFix(schema45, false)); +- datafixerbuilder.addFixer(new ItemCustomNameToComponentFix(schema45, false)); +- datafixerbuilder.addFixer(new BlockEntityCustomNameToComponentFix(schema45, false)); +- Schema schema46 = datafixerbuilder.addSchema(1460, V1460::new); ++ // CraftBukkit start ++ builder.addFixer(new com.mojang.datafixers.DataFix(schema45, false) { ++ @Override ++ protected com.mojang.datafixers.TypeRewriteRule makeRule() { ++ return this.fixTypeEverywhereTyped("Player CustomName", this.getInputSchema().getType(DataConverterTypes.PLAYER), (typed) -> { ++ return typed.update(DSL.remainderFinder(), (dynamic) -> { ++ return EntityCustomNameToComponentFix.fixTagCustomName(dynamic); ++ }); ++ }); ++ } ++ }); ++ // CraftBukkit end ++ builder.addFixer(new EntityCustomNameToComponentFix(schema45, false)); ++ builder.addFixer(new ItemCustomNameToComponentFix(schema45, false)); ++ builder.addFixer(new BlockEntityCustomNameToComponentFix(schema45, false)); ++ Schema schema46 = builder.addSchema(1460, V1460::new); + +- datafixerbuilder.addFixer(new EntityPaintingMotiveFix(schema46, false)); +- Schema schema47 = datafixerbuilder.addSchema(1466, V1466::new); ++ builder.addFixer(new EntityPaintingMotiveFix(schema46, false)); ++ Schema schema47 = builder.addSchema(1466, V1466::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema47, "Add DUMMY block entity", References.BLOCK_ENTITY)); +- datafixerbuilder.addFixer(new ChunkToProtochunkFix(schema47, true)); +- Schema schema48 = datafixerbuilder.addSchema(1470, V1470::new); ++ builder.addFixer(new AddNewChoices(schema47, "Add DUMMY block entity", DataConverterTypes.BLOCK_ENTITY)); ++ builder.addFixer(new ChunkToProtochunkFix(schema47, true)); ++ Schema schema48 = builder.addSchema(1470, V1470::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema48, "Add 1.13 entities fix", References.ENTITY)); +- Schema schema49 = datafixerbuilder.addSchema(1474, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new AddNewChoices(schema48, "Add 1.13 entities fix", DataConverterTypes.ENTITY)); ++ Schema schema49 = builder.addSchema(1474, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new ColorlessShulkerEntityFix(schema49, false)); +- datafixerbuilder.addFixer(BlockRenameFix.create(schema49, "Colorless shulker block fixer", (s) -> { ++ builder.addFixer(new ColorlessShulkerEntityFix(schema49, false)); ++ builder.addFixer(BlockRenameFix.create(schema49, "Colorless shulker block fixer", (s) -> { + return Objects.equals(NamespacedSchema.ensureNamespaced(s), "minecraft:purple_shulker_box") ? "minecraft:shulker_box" : s; + })); +- datafixerbuilder.addFixer(ItemRenameFix.create(schema49, "Colorless shulker item fixer", (s) -> { ++ builder.addFixer(ItemRenameFix.create(schema49, "Colorless shulker item fixer", (s) -> { + return Objects.equals(NamespacedSchema.ensureNamespaced(s), "minecraft:purple_shulker_box") ? "minecraft:shulker_box" : s; + })); +- Schema schema50 = datafixerbuilder.addSchema(1475, DataFixers.SAME_NAMESPACED); ++ Schema schema50 = builder.addSchema(1475, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(BlockRenameFix.create(schema50, "Flowing fixer", createRenamer(ImmutableMap.of("minecraft:flowing_water", "minecraft:water", "minecraft:flowing_lava", "minecraft:lava")))); +- Schema schema51 = datafixerbuilder.addSchema(1480, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(BlockRenameFix.create(schema50, "Flowing fixer", createRenamer(ImmutableMap.of("minecraft:flowing_water", "minecraft:water", "minecraft:flowing_lava", "minecraft:lava")))); ++ Schema schema51 = builder.addSchema(1480, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(BlockRenameFix.create(schema51, "Rename coral blocks", createRenamer(RenamedCoralFix.RENAMED_IDS))); +- datafixerbuilder.addFixer(ItemRenameFix.create(schema51, "Rename coral items", createRenamer(RenamedCoralFix.RENAMED_IDS))); +- Schema schema52 = datafixerbuilder.addSchema(1481, V1481::new); ++ builder.addFixer(BlockRenameFix.create(schema51, "Rename coral blocks", createRenamer(DataConverterCoral.RENAMED_IDS))); ++ builder.addFixer(ItemRenameFix.create(schema51, "Rename coral items", createRenamer(DataConverterCoral.RENAMED_IDS))); ++ Schema schema52 = builder.addSchema(1481, V1481::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema52, "Add conduit", References.BLOCK_ENTITY)); +- Schema schema53 = datafixerbuilder.addSchema(1483, V1483::new); ++ builder.addFixer(new AddNewChoices(schema52, "Add conduit", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema53 = builder.addSchema(1483, V1483::new); + +- datafixerbuilder.addFixer(new EntityPufferfishRenameFix(schema53, true)); +- datafixerbuilder.addFixer(ItemRenameFix.create(schema53, "Rename pufferfish egg item", createRenamer(EntityPufferfishRenameFix.RENAMED_IDS))); +- Schema schema54 = datafixerbuilder.addSchema(1484, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new EntityPufferfishRenameFix(schema53, true)); ++ builder.addFixer(ItemRenameFix.create(schema53, "Rename pufferfish egg item", createRenamer(EntityPufferfishRenameFix.RENAMED_IDS))); ++ Schema schema54 = builder.addSchema(1484, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(ItemRenameFix.create(schema54, "Rename seagrass items", createRenamer(ImmutableMap.of("minecraft:sea_grass", "minecraft:seagrass", "minecraft:tall_sea_grass", "minecraft:tall_seagrass")))); +- datafixerbuilder.addFixer(BlockRenameFix.create(schema54, "Rename seagrass blocks", createRenamer(ImmutableMap.of("minecraft:sea_grass", "minecraft:seagrass", "minecraft:tall_sea_grass", "minecraft:tall_seagrass")))); +- datafixerbuilder.addFixer(new HeightmapRenamingFix(schema54, false)); +- Schema schema55 = datafixerbuilder.addSchema(1486, V1486::new); ++ builder.addFixer(ItemRenameFix.create(schema54, "Rename seagrass items", createRenamer(ImmutableMap.of("minecraft:sea_grass", "minecraft:seagrass", "minecraft:tall_sea_grass", "minecraft:tall_seagrass")))); ++ builder.addFixer(BlockRenameFix.create(schema54, "Rename seagrass blocks", createRenamer(ImmutableMap.of("minecraft:sea_grass", "minecraft:seagrass", "minecraft:tall_sea_grass", "minecraft:tall_seagrass")))); ++ builder.addFixer(new HeightmapRenamingFix(schema54, false)); ++ Schema schema55 = builder.addSchema(1486, V1486::new); + +- datafixerbuilder.addFixer(new EntityCodSalmonFix(schema55, true)); +- datafixerbuilder.addFixer(ItemRenameFix.create(schema55, "Rename cod/salmon egg items", createRenamer(EntityCodSalmonFix.RENAMED_EGG_IDS))); +- Schema schema56 = datafixerbuilder.addSchema(1487, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new EntityCodSalmonFix(schema55, true)); ++ builder.addFixer(ItemRenameFix.create(schema55, "Rename cod/salmon egg items", createRenamer(EntityCodSalmonFix.RENAMED_EGG_IDS))); ++ Schema schema56 = builder.addSchema(1487, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(ItemRenameFix.create(schema56, "Rename prismarine_brick(s)_* blocks", createRenamer(ImmutableMap.of("minecraft:prismarine_bricks_slab", "minecraft:prismarine_brick_slab", "minecraft:prismarine_bricks_stairs", "minecraft:prismarine_brick_stairs")))); +- datafixerbuilder.addFixer(BlockRenameFix.create(schema56, "Rename prismarine_brick(s)_* items", createRenamer(ImmutableMap.of("minecraft:prismarine_bricks_slab", "minecraft:prismarine_brick_slab", "minecraft:prismarine_bricks_stairs", "minecraft:prismarine_brick_stairs")))); +- Schema schema57 = datafixerbuilder.addSchema(1488, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(ItemRenameFix.create(schema56, "Rename prismarine_brick(s)_* blocks", createRenamer(ImmutableMap.of("minecraft:prismarine_bricks_slab", "minecraft:prismarine_brick_slab", "minecraft:prismarine_bricks_stairs", "minecraft:prismarine_brick_stairs")))); ++ builder.addFixer(BlockRenameFix.create(schema56, "Rename prismarine_brick(s)_* items", createRenamer(ImmutableMap.of("minecraft:prismarine_bricks_slab", "minecraft:prismarine_brick_slab", "minecraft:prismarine_bricks_stairs", "minecraft:prismarine_brick_stairs")))); ++ Schema schema57 = builder.addSchema(1488, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(BlockRenameFix.create(schema57, "Rename kelp/kelptop", createRenamer(ImmutableMap.of("minecraft:kelp_top", "minecraft:kelp", "minecraft:kelp", "minecraft:kelp_plant")))); +- datafixerbuilder.addFixer(ItemRenameFix.create(schema57, "Rename kelptop", createRenamer("minecraft:kelp_top", "minecraft:kelp"))); +- datafixerbuilder.addFixer(new NamedEntityFix(schema57, false, "Command block block entity custom name fix", References.BLOCK_ENTITY, "minecraft:command_block") { ++ builder.addFixer(BlockRenameFix.create(schema57, "Rename kelp/kelptop", createRenamer(ImmutableMap.of("minecraft:kelp_top", "minecraft:kelp", "minecraft:kelp", "minecraft:kelp_plant")))); ++ builder.addFixer(ItemRenameFix.create(schema57, "Rename kelptop", createRenamer("minecraft:kelp_top", "minecraft:kelp"))); ++ builder.addFixer(new NamedEntityFix(schema57, false, "Command block block entity custom name fix", DataConverterTypes.BLOCK_ENTITY, "minecraft:command_block") { + @Override +- @Override + protected Typed fix(Typed typed) { + return typed.update(DSL.remainderFinder(), EntityCustomNameToComponentFix::fixTagCustomName); + } + }); +- datafixerbuilder.addFixer(new NamedEntityFix(schema57, false, "Command block minecart custom name fix", References.ENTITY, "minecraft:commandblock_minecart") { ++ builder.addFixer(new NamedEntityFix(schema57, false, "Command block minecart custom name fix", DataConverterTypes.ENTITY, "minecraft:commandblock_minecart") { + @Override +- @Override + protected Typed fix(Typed typed) { + return typed.update(DSL.remainderFinder(), EntityCustomNameToComponentFix::fixTagCustomName); + } + }); +- datafixerbuilder.addFixer(new IglooMetadataRemovalFix(schema57, false)); +- Schema schema58 = datafixerbuilder.addSchema(1490, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new IglooMetadataRemovalFix(schema57, false)); ++ Schema schema58 = builder.addSchema(1490, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(BlockRenameFix.create(schema58, "Rename melon_block", createRenamer("minecraft:melon_block", "minecraft:melon"))); +- datafixerbuilder.addFixer(ItemRenameFix.create(schema58, "Rename melon_block/melon/speckled_melon", createRenamer(ImmutableMap.of("minecraft:melon_block", "minecraft:melon", "minecraft:melon", "minecraft:melon_slice", "minecraft:speckled_melon", "minecraft:glistering_melon_slice")))); +- Schema schema59 = datafixerbuilder.addSchema(1492, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(BlockRenameFix.create(schema58, "Rename melon_block", createRenamer("minecraft:melon_block", "minecraft:melon"))); ++ builder.addFixer(ItemRenameFix.create(schema58, "Rename melon_block/melon/speckled_melon", createRenamer(ImmutableMap.of("minecraft:melon_block", "minecraft:melon", "minecraft:melon", "minecraft:melon_slice", "minecraft:speckled_melon", "minecraft:glistering_melon_slice")))); ++ Schema schema59 = builder.addSchema(1492, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new ChunkStructuresTemplateRenameFix(schema59, false)); +- Schema schema60 = datafixerbuilder.addSchema(1494, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new ChunkStructuresTemplateRenameFix(schema59, false)); ++ Schema schema60 = builder.addSchema(1494, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new ItemStackEnchantmentNamesFix(schema60, false)); +- Schema schema61 = datafixerbuilder.addSchema(1496, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new ItemStackEnchantmentNamesFix(schema60, false)); ++ Schema schema61 = builder.addSchema(1496, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new LeavesFix(schema61, false)); +- Schema schema62 = datafixerbuilder.addSchema(1500, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new LeavesFix(schema61, false)); ++ Schema schema62 = builder.addSchema(1500, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new BlockEntityKeepPacked(schema62, false)); +- Schema schema63 = datafixerbuilder.addSchema(1501, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new BlockEntityKeepPacked(schema62, false)); ++ Schema schema63 = builder.addSchema(1501, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new AdvancementsFix(schema63, false)); +- Schema schema64 = datafixerbuilder.addSchema(1502, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new AdvancementsFix(schema63, false)); ++ Schema schema64 = builder.addSchema(1502, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new NamespacedTypeRenameFix(schema64, "Recipes fix", References.RECIPE, createRenamer(RecipesFix.RECIPES))); +- Schema schema65 = datafixerbuilder.addSchema(1506, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new NamespacedTypeRenameFix(schema64, "Recipes fix", DataConverterTypes.RECIPE, createRenamer(DataConverterRecipes.RECIPES))); ++ Schema schema65 = builder.addSchema(1506, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new LevelDataGeneratorOptionsFix(schema65, false)); +- Schema schema66 = datafixerbuilder.addSchema(1510, V1510::new); ++ builder.addFixer(new LevelDataGeneratorOptionsFix(schema65, false)); ++ Schema schema66 = builder.addSchema(1510, V1510::new); + +- datafixerbuilder.addFixer(BlockRenameFix.create(schema66, "Block renamening fix", createRenamer(EntityTheRenameningFix.RENAMED_BLOCKS))); +- datafixerbuilder.addFixer(ItemRenameFix.create(schema66, "Item renamening fix", createRenamer(EntityTheRenameningFix.RENAMED_ITEMS))); +- datafixerbuilder.addFixer(new NamespacedTypeRenameFix(schema66, "Recipes renamening fix", References.RECIPE, createRenamer(RecipesRenameningFix.RECIPES))); +- datafixerbuilder.addFixer(new EntityTheRenameningFix(schema66, true)); +- datafixerbuilder.addFixer(new StatsRenameFix(schema66, "SwimStatsRenameFix", ImmutableMap.of("minecraft:swim_one_cm", "minecraft:walk_on_water_one_cm", "minecraft:dive_one_cm", "minecraft:walk_under_water_one_cm"))); +- Schema schema67 = datafixerbuilder.addSchema(1514, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(BlockRenameFix.create(schema66, "Block renamening fix", createRenamer(EntityTheRenameningFix.RENAMED_BLOCKS))); ++ builder.addFixer(ItemRenameFix.create(schema66, "Item renamening fix", createRenamer(EntityTheRenameningFix.RENAMED_ITEMS))); ++ builder.addFixer(new NamespacedTypeRenameFix(schema66, "Recipes renamening fix", DataConverterTypes.RECIPE, createRenamer(DataConverterRecipeRename.RECIPES))); ++ builder.addFixer(new EntityTheRenameningFix(schema66, true)); ++ builder.addFixer(new StatsRenameFix(schema66, "SwimStatsRenameFix", ImmutableMap.of("minecraft:swim_one_cm", "minecraft:walk_on_water_one_cm", "minecraft:dive_one_cm", "minecraft:walk_under_water_one_cm"))); ++ Schema schema67 = builder.addSchema(1514, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new ObjectiveDisplayNameFix(schema67, false)); +- datafixerbuilder.addFixer(new TeamDisplayNameFix(schema67, false)); +- datafixerbuilder.addFixer(new ObjectiveRenderTypeFix(schema67, false)); +- Schema schema68 = datafixerbuilder.addSchema(1515, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new ObjectiveDisplayNameFix(schema67, false)); ++ builder.addFixer(new TeamDisplayNameFix(schema67, false)); ++ builder.addFixer(new ObjectiveRenderTypeFix(schema67, false)); ++ Schema schema68 = builder.addSchema(1515, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(BlockRenameFix.create(schema68, "Rename coral fan blocks", createRenamer(RenamedCoralFansFix.RENAMED_IDS))); +- Schema schema69 = datafixerbuilder.addSchema(1624, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(BlockRenameFix.create(schema68, "Rename coral fan blocks", createRenamer(DataConverterCoralFan.RENAMED_IDS))); ++ Schema schema69 = builder.addSchema(1624, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new TrappedChestBlockEntityFix(schema69, false)); +- Schema schema70 = datafixerbuilder.addSchema(1800, V1800::new); ++ builder.addFixer(new TrappedChestBlockEntityFix(schema69, false)); ++ Schema schema70 = builder.addSchema(1800, V1800::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema70, "Added 1.14 mobs fix", References.ENTITY)); +- datafixerbuilder.addFixer(ItemRenameFix.create(schema70, "Rename dye items", createRenamer(DyeItemRenameFix.RENAMED_IDS))); +- Schema schema71 = datafixerbuilder.addSchema(1801, V1801::new); ++ builder.addFixer(new AddNewChoices(schema70, "Added 1.14 mobs fix", DataConverterTypes.ENTITY)); ++ builder.addFixer(ItemRenameFix.create(schema70, "Rename dye items", createRenamer(DataConverterDye.RENAMED_IDS))); ++ Schema schema71 = builder.addSchema(1801, V1801::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema71, "Added Illager Beast", References.ENTITY)); +- Schema schema72 = datafixerbuilder.addSchema(1802, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new AddNewChoices(schema71, "Added Illager Beast", DataConverterTypes.ENTITY)); ++ Schema schema72 = builder.addSchema(1802, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(BlockRenameFix.create(schema72, "Rename sign blocks & stone slabs", createRenamer(ImmutableMap.of("minecraft:stone_slab", "minecraft:smooth_stone_slab", "minecraft:sign", "minecraft:oak_sign", "minecraft:wall_sign", "minecraft:oak_wall_sign")))); +- datafixerbuilder.addFixer(ItemRenameFix.create(schema72, "Rename sign item & stone slabs", createRenamer(ImmutableMap.of("minecraft:stone_slab", "minecraft:smooth_stone_slab", "minecraft:sign", "minecraft:oak_sign")))); +- Schema schema73 = datafixerbuilder.addSchema(1803, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(BlockRenameFix.create(schema72, "Rename sign blocks & stone slabs", createRenamer(ImmutableMap.of("minecraft:stone_slab", "minecraft:smooth_stone_slab", "minecraft:sign", "minecraft:oak_sign", "minecraft:wall_sign", "minecraft:oak_wall_sign")))); ++ builder.addFixer(ItemRenameFix.create(schema72, "Rename sign item & stone slabs", createRenamer(ImmutableMap.of("minecraft:stone_slab", "minecraft:smooth_stone_slab", "minecraft:sign", "minecraft:oak_sign")))); ++ Schema schema73 = builder.addSchema(1803, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new ItemLoreFix(schema73, false)); +- Schema schema74 = datafixerbuilder.addSchema(1904, V1904::new); ++ builder.addFixer(new ItemLoreFix(schema73, false)); ++ Schema schema74 = builder.addSchema(1904, V1904::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema74, "Added Cats", References.ENTITY)); +- datafixerbuilder.addFixer(new EntityCatSplitFix(schema74, false)); +- Schema schema75 = datafixerbuilder.addSchema(1905, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new AddNewChoices(schema74, "Added Cats", DataConverterTypes.ENTITY)); ++ builder.addFixer(new EntityCatSplitFix(schema74, false)); ++ Schema schema75 = builder.addSchema(1905, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new ChunkStatusFix(schema75, false)); +- Schema schema76 = datafixerbuilder.addSchema(1906, V1906::new); ++ builder.addFixer(new ChunkStatusFix(schema75, false)); ++ Schema schema76 = builder.addSchema(1906, V1906::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema76, "Add POI Blocks", References.BLOCK_ENTITY)); +- Schema schema77 = datafixerbuilder.addSchema(1909, V1909::new); ++ builder.addFixer(new AddNewChoices(schema76, "Add POI Blocks", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema77 = builder.addSchema(1909, V1909::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema77, "Add jigsaw", References.BLOCK_ENTITY)); +- Schema schema78 = datafixerbuilder.addSchema(1911, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new AddNewChoices(schema77, "Add jigsaw", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema78 = builder.addSchema(1911, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new ChunkStatusFix2(schema78, false)); +- Schema schema79 = datafixerbuilder.addSchema(1914, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new ChunkStatusFix2(schema78, false)); ++ Schema schema79 = builder.addSchema(1914, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new WeaponSmithChestLootTableFix(schema79, false)); +- Schema schema80 = datafixerbuilder.addSchema(1917, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new WeaponSmithChestLootTableFix(schema79, false)); ++ Schema schema80 = builder.addSchema(1917, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new CatTypeFix(schema80, false)); +- Schema schema81 = datafixerbuilder.addSchema(1918, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new CatTypeFix(schema80, false)); ++ Schema schema81 = builder.addSchema(1918, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new VillagerDataFix(schema81, "minecraft:villager")); +- datafixerbuilder.addFixer(new VillagerDataFix(schema81, "minecraft:zombie_villager")); +- Schema schema82 = datafixerbuilder.addSchema(1920, V1920::new); ++ builder.addFixer(new VillagerDataFix(schema81, "minecraft:villager")); ++ builder.addFixer(new VillagerDataFix(schema81, "minecraft:zombie_villager")); ++ Schema schema82 = builder.addSchema(1920, V1920::new); + +- datafixerbuilder.addFixer(new NewVillageFix(schema82, false)); +- datafixerbuilder.addFixer(new AddNewChoices(schema82, "Add campfire", References.BLOCK_ENTITY)); +- Schema schema83 = datafixerbuilder.addSchema(1925, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new NewVillageFix(schema82, false)); ++ builder.addFixer(new AddNewChoices(schema82, "Add campfire", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema83 = builder.addSchema(1925, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new MapIdFix(schema83, false)); +- Schema schema84 = datafixerbuilder.addSchema(1928, V1928::new); ++ builder.addFixer(new MapIdFix(schema83, false)); ++ Schema schema84 = builder.addSchema(1928, V1928::new); + +- datafixerbuilder.addFixer(new EntityRavagerRenameFix(schema84, true)); +- datafixerbuilder.addFixer(ItemRenameFix.create(schema84, "Rename ravager egg item", createRenamer(EntityRavagerRenameFix.RENAMED_IDS))); +- Schema schema85 = datafixerbuilder.addSchema(1929, V1929::new); ++ builder.addFixer(new EntityRavagerRenameFix(schema84, true)); ++ builder.addFixer(ItemRenameFix.create(schema84, "Rename ravager egg item", createRenamer(EntityRavagerRenameFix.RENAMED_IDS))); ++ Schema schema85 = builder.addSchema(1929, V1929::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema85, "Add Wandering Trader and Trader Llama", References.ENTITY)); +- Schema schema86 = datafixerbuilder.addSchema(1931, V1931::new); ++ builder.addFixer(new AddNewChoices(schema85, "Add Wandering Trader and Trader Llama", DataConverterTypes.ENTITY)); ++ Schema schema86 = builder.addSchema(1931, V1931::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema86, "Added Fox", References.ENTITY)); +- Schema schema87 = datafixerbuilder.addSchema(1936, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new AddNewChoices(schema86, "Added Fox", DataConverterTypes.ENTITY)); ++ Schema schema87 = builder.addSchema(1936, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new OptionsAddTextBackgroundFix(schema87, false)); +- Schema schema88 = datafixerbuilder.addSchema(1946, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new OptionsAddTextBackgroundFix(schema87, false)); ++ Schema schema88 = builder.addSchema(1946, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new ReorganizePoi(schema88, false)); +- Schema schema89 = datafixerbuilder.addSchema(1948, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new ReorganizePoi(schema88, false)); ++ Schema schema89 = builder.addSchema(1948, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new OminousBannerRenameFix(schema89)); +- Schema schema90 = datafixerbuilder.addSchema(1953, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new OminousBannerRenameFix(schema89)); ++ Schema schema90 = builder.addSchema(1953, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new OminousBannerBlockEntityRenameFix(schema90, false)); +- Schema schema91 = datafixerbuilder.addSchema(1955, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new OminousBannerBlockEntityRenameFix(schema90, false)); ++ Schema schema91 = builder.addSchema(1955, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new VillagerRebuildLevelAndXpFix(schema91, false)); +- datafixerbuilder.addFixer(new ZombieVillagerRebuildXpFix(schema91, false)); +- Schema schema92 = datafixerbuilder.addSchema(1961, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new VillagerRebuildLevelAndXpFix(schema91, false)); ++ builder.addFixer(new ZombieVillagerRebuildXpFix(schema91, false)); ++ Schema schema92 = builder.addSchema(1961, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new ChunkLightRemoveFix(schema92, false)); +- Schema schema93 = datafixerbuilder.addSchema(1963, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new ChunkLightRemoveFix(schema92, false)); ++ Schema schema93 = builder.addSchema(1963, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new RemoveGolemGossipFix(schema93, false)); +- Schema schema94 = datafixerbuilder.addSchema(2100, V2100::new); ++ builder.addFixer(new RemoveGolemGossipFix(schema93, false)); ++ Schema schema94 = builder.addSchema(2100, V2100::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema94, "Added Bee and Bee Stinger", References.ENTITY)); +- datafixerbuilder.addFixer(new AddNewChoices(schema94, "Add beehive", References.BLOCK_ENTITY)); +- datafixerbuilder.addFixer(new NamespacedTypeRenameFix(schema94, "Rename sugar recipe", References.RECIPE, createRenamer("minecraft:sugar", "sugar_from_sugar_cane"))); +- datafixerbuilder.addFixer(new AdvancementsRenameFix(schema94, false, "Rename sugar recipe advancement", createRenamer("minecraft:recipes/misc/sugar", "minecraft:recipes/misc/sugar_from_sugar_cane"))); +- Schema schema95 = datafixerbuilder.addSchema(2202, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new AddNewChoices(schema94, "Added Bee and Bee Stinger", DataConverterTypes.ENTITY)); ++ builder.addFixer(new AddNewChoices(schema94, "Add beehive", DataConverterTypes.BLOCK_ENTITY)); ++ builder.addFixer(new NamespacedTypeRenameFix(schema94, "Rename sugar recipe", DataConverterTypes.RECIPE, createRenamer("minecraft:sugar", "sugar_from_sugar_cane"))); ++ builder.addFixer(new AdvancementsRenameFix(schema94, false, "Rename sugar recipe advancement", createRenamer("minecraft:recipes/misc/sugar", "minecraft:recipes/misc/sugar_from_sugar_cane"))); ++ Schema schema95 = builder.addSchema(2202, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new ChunkBiomeFix(schema95, false)); +- Schema schema96 = datafixerbuilder.addSchema(2209, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new ChunkBiomeFix(schema95, false)); ++ Schema schema96 = builder.addSchema(2209, DataFixers.SAME_NAMESPACED); + UnaryOperator unaryoperator = createRenamer("minecraft:bee_hive", "minecraft:beehive"); + +- datafixerbuilder.addFixer(ItemRenameFix.create(schema96, "Rename bee_hive item to beehive", unaryoperator)); +- datafixerbuilder.addFixer(new PoiTypeRenameFix(schema96, "Rename bee_hive poi to beehive", unaryoperator)); +- datafixerbuilder.addFixer(BlockRenameFix.create(schema96, "Rename bee_hive block to beehive", unaryoperator)); +- Schema schema97 = datafixerbuilder.addSchema(2211, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(ItemRenameFix.create(schema96, "Rename bee_hive item to beehive", unaryoperator)); ++ builder.addFixer(new PoiTypeRenameFix(schema96, "Rename bee_hive poi to beehive", unaryoperator)); ++ builder.addFixer(BlockRenameFix.create(schema96, "Rename bee_hive block to beehive", unaryoperator)); ++ Schema schema97 = builder.addSchema(2211, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new StructureReferenceCountFix(schema97, false)); +- Schema schema98 = datafixerbuilder.addSchema(2218, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new StructureReferenceCountFix(schema97, false)); ++ Schema schema98 = builder.addSchema(2218, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new ForcePoiRebuild(schema98, false)); +- Schema schema99 = datafixerbuilder.addSchema(2501, V2501::new); ++ builder.addFixer(new ForcePoiRebuild(schema98, false)); ++ Schema schema99 = builder.addSchema(2501, V2501::new); + +- datafixerbuilder.addFixer(new FurnaceRecipeFix(schema99, true)); +- Schema schema100 = datafixerbuilder.addSchema(2502, V2502::new); ++ builder.addFixer(new FurnaceRecipeFix(schema99, true)); ++ Schema schema100 = builder.addSchema(2502, V2502::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema100, "Added Hoglin", References.ENTITY)); +- Schema schema101 = datafixerbuilder.addSchema(2503, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new AddNewChoices(schema100, "Added Hoglin", DataConverterTypes.ENTITY)); ++ Schema schema101 = builder.addSchema(2503, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new WallPropertyFix(schema101, false)); +- datafixerbuilder.addFixer(new AdvancementsRenameFix(schema101, false, "Composter category change", createRenamer("minecraft:recipes/misc/composter", "minecraft:recipes/decorations/composter"))); +- Schema schema102 = datafixerbuilder.addSchema(2505, V2505::new); ++ builder.addFixer(new WallPropertyFix(schema101, false)); ++ builder.addFixer(new AdvancementsRenameFix(schema101, false, "Composter category change", createRenamer("minecraft:recipes/misc/composter", "minecraft:recipes/decorations/composter"))); ++ Schema schema102 = builder.addSchema(2505, V2505::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema102, "Added Piglin", References.ENTITY)); +- datafixerbuilder.addFixer(new MemoryExpiryDataFix(schema102, "minecraft:villager")); +- Schema schema103 = datafixerbuilder.addSchema(2508, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new AddNewChoices(schema102, "Added Piglin", DataConverterTypes.ENTITY)); ++ builder.addFixer(new MemoryExpiryDataFix(schema102, "minecraft:villager")); ++ Schema schema103 = builder.addSchema(2508, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(ItemRenameFix.create(schema103, "Renamed fungi items to fungus", createRenamer(ImmutableMap.of("minecraft:warped_fungi", "minecraft:warped_fungus", "minecraft:crimson_fungi", "minecraft:crimson_fungus")))); +- datafixerbuilder.addFixer(BlockRenameFix.create(schema103, "Renamed fungi blocks to fungus", createRenamer(ImmutableMap.of("minecraft:warped_fungi", "minecraft:warped_fungus", "minecraft:crimson_fungi", "minecraft:crimson_fungus")))); +- Schema schema104 = datafixerbuilder.addSchema(2509, V2509::new); ++ builder.addFixer(ItemRenameFix.create(schema103, "Renamed fungi items to fungus", createRenamer(ImmutableMap.of("minecraft:warped_fungi", "minecraft:warped_fungus", "minecraft:crimson_fungi", "minecraft:crimson_fungus")))); ++ builder.addFixer(BlockRenameFix.create(schema103, "Renamed fungi blocks to fungus", createRenamer(ImmutableMap.of("minecraft:warped_fungi", "minecraft:warped_fungus", "minecraft:crimson_fungi", "minecraft:crimson_fungus")))); ++ Schema schema104 = builder.addSchema(2509, V2509::new); + +- datafixerbuilder.addFixer(new EntityZombifiedPiglinRenameFix(schema104)); +- datafixerbuilder.addFixer(ItemRenameFix.create(schema104, "Rename zombie pigman egg item", createRenamer(EntityZombifiedPiglinRenameFix.RENAMED_IDS))); +- Schema schema105 = datafixerbuilder.addSchema(2511, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new EntityZombifiedPiglinRenameFix(schema104)); ++ builder.addFixer(ItemRenameFix.create(schema104, "Rename zombie pigman egg item", createRenamer(EntityZombifiedPiglinRenameFix.RENAMED_IDS))); ++ Schema schema105 = builder.addSchema(2511, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new EntityProjectileOwnerFix(schema105)); +- Schema schema106 = datafixerbuilder.addSchema(2514, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new EntityProjectileOwnerFix(schema105)); ++ Schema schema106 = builder.addSchema(2514, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new EntityUUIDFix(schema106)); +- datafixerbuilder.addFixer(new BlockEntityUUIDFix(schema106)); +- datafixerbuilder.addFixer(new PlayerUUIDFix(schema106)); +- datafixerbuilder.addFixer(new LevelUUIDFix(schema106)); +- datafixerbuilder.addFixer(new SavedDataUUIDFix(schema106)); +- datafixerbuilder.addFixer(new ItemStackUUIDFix(schema106)); +- Schema schema107 = datafixerbuilder.addSchema(2516, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new EntityUUIDFix(schema106)); ++ builder.addFixer(new BlockEntityUUIDFix(schema106)); ++ builder.addFixer(new PlayerUUIDFix(schema106)); ++ builder.addFixer(new LevelUUIDFix(schema106)); ++ builder.addFixer(new SavedDataUUIDFix(schema106)); ++ builder.addFixer(new ItemStackUUIDFix(schema106)); ++ Schema schema107 = builder.addSchema(2516, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new GossipUUIDFix(schema107, "minecraft:villager")); +- datafixerbuilder.addFixer(new GossipUUIDFix(schema107, "minecraft:zombie_villager")); +- Schema schema108 = datafixerbuilder.addSchema(2518, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new GossipUUIDFix(schema107, "minecraft:villager")); ++ builder.addFixer(new GossipUUIDFix(schema107, "minecraft:zombie_villager")); ++ Schema schema108 = builder.addSchema(2518, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new JigsawPropertiesFix(schema108, false)); +- datafixerbuilder.addFixer(new JigsawRotationFix(schema108, false)); +- Schema schema109 = datafixerbuilder.addSchema(2519, V2519::new); ++ builder.addFixer(new JigsawPropertiesFix(schema108, false)); ++ builder.addFixer(new JigsawRotationFix(schema108, false)); ++ Schema schema109 = builder.addSchema(2519, V2519::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema109, "Added Strider", References.ENTITY)); +- Schema schema110 = datafixerbuilder.addSchema(2522, V2522::new); ++ builder.addFixer(new AddNewChoices(schema109, "Added Strider", DataConverterTypes.ENTITY)); ++ Schema schema110 = builder.addSchema(2522, V2522::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema110, "Added Zoglin", References.ENTITY)); +- Schema schema111 = datafixerbuilder.addSchema(2523, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new AddNewChoices(schema110, "Added Zoglin", DataConverterTypes.ENTITY)); ++ Schema schema111 = builder.addSchema(2523, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new AttributesRename(schema111)); +- Schema schema112 = datafixerbuilder.addSchema(2527, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new AttributesRename(schema111)); ++ Schema schema112 = builder.addSchema(2527, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new BitStorageAlignFix(schema112)); +- Schema schema113 = datafixerbuilder.addSchema(2528, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new BitStorageAlignFix(schema112)); ++ Schema schema113 = builder.addSchema(2528, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(ItemRenameFix.create(schema113, "Rename soul fire torch and soul fire lantern", createRenamer(ImmutableMap.of("minecraft:soul_fire_torch", "minecraft:soul_torch", "minecraft:soul_fire_lantern", "minecraft:soul_lantern")))); +- datafixerbuilder.addFixer(BlockRenameFix.create(schema113, "Rename soul fire torch and soul fire lantern", createRenamer(ImmutableMap.of("minecraft:soul_fire_torch", "minecraft:soul_torch", "minecraft:soul_fire_wall_torch", "minecraft:soul_wall_torch", "minecraft:soul_fire_lantern", "minecraft:soul_lantern")))); +- Schema schema114 = datafixerbuilder.addSchema(2529, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(ItemRenameFix.create(schema113, "Rename soul fire torch and soul fire lantern", createRenamer(ImmutableMap.of("minecraft:soul_fire_torch", "minecraft:soul_torch", "minecraft:soul_fire_lantern", "minecraft:soul_lantern")))); ++ builder.addFixer(BlockRenameFix.create(schema113, "Rename soul fire torch and soul fire lantern", createRenamer(ImmutableMap.of("minecraft:soul_fire_torch", "minecraft:soul_torch", "minecraft:soul_fire_wall_torch", "minecraft:soul_wall_torch", "minecraft:soul_fire_lantern", "minecraft:soul_lantern")))); ++ Schema schema114 = builder.addSchema(2529, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new StriderGravityFix(schema114, false)); +- Schema schema115 = datafixerbuilder.addSchema(2531, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new StriderGravityFix(schema114, false)); ++ Schema schema115 = builder.addSchema(2531, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new RedstoneWireConnectionsFix(schema115)); +- Schema schema116 = datafixerbuilder.addSchema(2533, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new RedstoneWireConnectionsFix(schema115)); ++ Schema schema116 = builder.addSchema(2533, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new VillagerFollowRangeFix(schema116)); +- Schema schema117 = datafixerbuilder.addSchema(2535, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new VillagerFollowRangeFix(schema116)); ++ Schema schema117 = builder.addSchema(2535, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new EntityShulkerRotationFix(schema117)); +- Schema schema118 = datafixerbuilder.addSchema(2538, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new EntityShulkerRotationFix(schema117)); ++ Schema schema118 = builder.addSchema(2538, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new LevelLegacyWorldGenSettingsFix(schema118)); +- Schema schema119 = datafixerbuilder.addSchema(2550, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new LevelLegacyWorldGenSettingsFix(schema118)); ++ Schema schema119 = builder.addSchema(2550, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new WorldGenSettingsFix(schema119)); +- Schema schema120 = datafixerbuilder.addSchema(2551, V2551::new); ++ builder.addFixer(new WorldGenSettingsFix(schema119)); ++ Schema schema120 = builder.addSchema(2551, V2551::new); + +- datafixerbuilder.addFixer(new WriteAndReadFix(schema120, "add types to WorldGenData", References.WORLD_GEN_SETTINGS)); +- Schema schema121 = datafixerbuilder.addSchema(2552, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new WriteAndReadFix(schema120, "add types to WorldGenData", DataConverterTypes.WORLD_GEN_SETTINGS)); ++ Schema schema121 = builder.addSchema(2552, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new NamespacedTypeRenameFix(schema121, "Nether biome rename", References.BIOME, createRenamer("minecraft:nether", "minecraft:nether_wastes"))); +- Schema schema122 = datafixerbuilder.addSchema(2553, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new NamespacedTypeRenameFix(schema121, "Nether biome rename", DataConverterTypes.BIOME, createRenamer("minecraft:nether", "minecraft:nether_wastes"))); ++ Schema schema122 = builder.addSchema(2553, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new NamespacedTypeRenameFix(schema122, "Biomes fix", References.BIOME, createRenamer(BiomeFix.BIOMES))); +- Schema schema123 = datafixerbuilder.addSchema(2558, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new NamespacedTypeRenameFix(schema122, "Biomes fix", DataConverterTypes.BIOME, createRenamer(DataConverterBiome.BIOMES))); ++ Schema schema123 = builder.addSchema(2558, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new MissingDimensionFix(schema123, false)); +- datafixerbuilder.addFixer(new OptionsRenameFieldFix(schema123, false, "Rename swapHands setting", "key_key.swapHands", "key_key.swapOffhand")); +- Schema schema124 = datafixerbuilder.addSchema(2568, V2568::new); ++ builder.addFixer(new MissingDimensionFix(schema123, false)); ++ builder.addFixer(new OptionsRenameFieldFix(schema123, false, "Rename swapHands setting", "key_key.swapHands", "key_key.swapOffhand")); ++ Schema schema124 = builder.addSchema(2568, V2568::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema124, "Added Piglin Brute", References.ENTITY)); +- Schema schema125 = datafixerbuilder.addSchema(2571, V2571::new); ++ builder.addFixer(new AddNewChoices(schema124, "Added Piglin Brute", DataConverterTypes.ENTITY)); ++ Schema schema125 = builder.addSchema(2571, V2571::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema125, "Added Goat", References.ENTITY)); +- Schema schema126 = datafixerbuilder.addSchema(2679, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new AddNewChoices(schema125, "Added Goat", DataConverterTypes.ENTITY)); ++ Schema schema126 = builder.addSchema(2679, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new CauldronRenameFix(schema126, false)); +- Schema schema127 = datafixerbuilder.addSchema(2680, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new CauldronRenameFix(schema126, false)); ++ Schema schema127 = builder.addSchema(2680, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(ItemRenameFix.create(schema127, "Renamed grass path item to dirt path", createRenamer("minecraft:grass_path", "minecraft:dirt_path"))); +- datafixerbuilder.addFixer(BlockRenameFixWithJigsaw.create(schema127, "Renamed grass path block to dirt path", createRenamer("minecraft:grass_path", "minecraft:dirt_path"))); +- Schema schema128 = datafixerbuilder.addSchema(2684, V2684::new); ++ builder.addFixer(ItemRenameFix.create(schema127, "Renamed grass path item to dirt path", createRenamer("minecraft:grass_path", "minecraft:dirt_path"))); ++ builder.addFixer(BlockRenameFixWithJigsaw.create(schema127, "Renamed grass path block to dirt path", createRenamer("minecraft:grass_path", "minecraft:dirt_path"))); ++ Schema schema128 = builder.addSchema(2684, V2684::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema128, "Added Sculk Sensor", References.BLOCK_ENTITY)); +- Schema schema129 = datafixerbuilder.addSchema(2686, V2686::new); ++ builder.addFixer(new AddNewChoices(schema128, "Added Sculk Sensor", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema129 = builder.addSchema(2686, V2686::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema129, "Added Axolotl", References.ENTITY)); +- Schema schema130 = datafixerbuilder.addSchema(2688, V2688::new); ++ builder.addFixer(new AddNewChoices(schema129, "Added Axolotl", DataConverterTypes.ENTITY)); ++ Schema schema130 = builder.addSchema(2688, V2688::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema130, "Added Glow Squid", References.ENTITY)); +- datafixerbuilder.addFixer(new AddNewChoices(schema130, "Added Glow Item Frame", References.ENTITY)); +- Schema schema131 = datafixerbuilder.addSchema(2690, DataFixers.SAME_NAMESPACED); +- ImmutableMap immutablemap = ImmutableMap.builder().put("minecraft:weathered_copper_block", "minecraft:oxidized_copper_block").put("minecraft:semi_weathered_copper_block", "minecraft:weathered_copper_block").put("minecraft:lightly_weathered_copper_block", "minecraft:exposed_copper_block").put("minecraft:weathered_cut_copper", "minecraft:oxidized_cut_copper").put("minecraft:semi_weathered_cut_copper", "minecraft:weathered_cut_copper").put("minecraft:lightly_weathered_cut_copper", "minecraft:exposed_cut_copper").put("minecraft:weathered_cut_copper_stairs", "minecraft:oxidized_cut_copper_stairs").put("minecraft:semi_weathered_cut_copper_stairs", "minecraft:weathered_cut_copper_stairs").put("minecraft:lightly_weathered_cut_copper_stairs", "minecraft:exposed_cut_copper_stairs").put("minecraft:weathered_cut_copper_slab", "minecraft:oxidized_cut_copper_slab").put("minecraft:semi_weathered_cut_copper_slab", "minecraft:weathered_cut_copper_slab").put("minecraft:lightly_weathered_cut_copper_slab", "minecraft:exposed_cut_copper_slab").put("minecraft:waxed_semi_weathered_copper", "minecraft:waxed_weathered_copper").put("minecraft:waxed_lightly_weathered_copper", "minecraft:waxed_exposed_copper").put("minecraft:waxed_semi_weathered_cut_copper", "minecraft:waxed_weathered_cut_copper").put("minecraft:waxed_lightly_weathered_cut_copper", "minecraft:waxed_exposed_cut_copper").put("minecraft:waxed_semi_weathered_cut_copper_stairs", "minecraft:waxed_weathered_cut_copper_stairs").put("minecraft:waxed_lightly_weathered_cut_copper_stairs", "minecraft:waxed_exposed_cut_copper_stairs").put("minecraft:waxed_semi_weathered_cut_copper_slab", "minecraft:waxed_weathered_cut_copper_slab").put("minecraft:waxed_lightly_weathered_cut_copper_slab", "minecraft:waxed_exposed_cut_copper_slab").build(); ++ builder.addFixer(new AddNewChoices(schema130, "Added Glow Squid", DataConverterTypes.ENTITY)); ++ builder.addFixer(new AddNewChoices(schema130, "Added Glow Item Frame", DataConverterTypes.ENTITY)); ++ Schema schema131 = builder.addSchema(2690, DataFixers.SAME_NAMESPACED); ++ // CraftBukkit - decompile error ++ ImmutableMap immutablemap = ImmutableMap.builder().put("minecraft:weathered_copper_block", "minecraft:oxidized_copper_block").put("minecraft:semi_weathered_copper_block", "minecraft:weathered_copper_block").put("minecraft:lightly_weathered_copper_block", "minecraft:exposed_copper_block").put("minecraft:weathered_cut_copper", "minecraft:oxidized_cut_copper").put("minecraft:semi_weathered_cut_copper", "minecraft:weathered_cut_copper").put("minecraft:lightly_weathered_cut_copper", "minecraft:exposed_cut_copper").put("minecraft:weathered_cut_copper_stairs", "minecraft:oxidized_cut_copper_stairs").put("minecraft:semi_weathered_cut_copper_stairs", "minecraft:weathered_cut_copper_stairs").put("minecraft:lightly_weathered_cut_copper_stairs", "minecraft:exposed_cut_copper_stairs").put("minecraft:weathered_cut_copper_slab", "minecraft:oxidized_cut_copper_slab").put("minecraft:semi_weathered_cut_copper_slab", "minecraft:weathered_cut_copper_slab").put("minecraft:lightly_weathered_cut_copper_slab", "minecraft:exposed_cut_copper_slab").put("minecraft:waxed_semi_weathered_copper", "minecraft:waxed_weathered_copper").put("minecraft:waxed_lightly_weathered_copper", "minecraft:waxed_exposed_copper").put("minecraft:waxed_semi_weathered_cut_copper", "minecraft:waxed_weathered_cut_copper").put("minecraft:waxed_lightly_weathered_cut_copper", "minecraft:waxed_exposed_cut_copper").put("minecraft:waxed_semi_weathered_cut_copper_stairs", "minecraft:waxed_weathered_cut_copper_stairs").put("minecraft:waxed_lightly_weathered_cut_copper_stairs", "minecraft:waxed_exposed_cut_copper_stairs").put("minecraft:waxed_semi_weathered_cut_copper_slab", "minecraft:waxed_weathered_cut_copper_slab").put("minecraft:waxed_lightly_weathered_cut_copper_slab", "minecraft:waxed_exposed_cut_copper_slab").build(); + +- datafixerbuilder.addFixer(ItemRenameFix.create(schema131, "Renamed copper block items to new oxidized terms", createRenamer(immutablemap))); +- datafixerbuilder.addFixer(BlockRenameFixWithJigsaw.create(schema131, "Renamed copper blocks to new oxidized terms", createRenamer(immutablemap))); +- Schema schema132 = datafixerbuilder.addSchema(2691, DataFixers.SAME_NAMESPACED); +- ImmutableMap immutablemap1 = ImmutableMap.builder().put("minecraft:waxed_copper", "minecraft:waxed_copper_block").put("minecraft:oxidized_copper_block", "minecraft:oxidized_copper").put("minecraft:weathered_copper_block", "minecraft:weathered_copper").put("minecraft:exposed_copper_block", "minecraft:exposed_copper").build(); ++ builder.addFixer(ItemRenameFix.create(schema131, "Renamed copper block items to new oxidized terms", createRenamer(immutablemap))); ++ builder.addFixer(BlockRenameFixWithJigsaw.create(schema131, "Renamed copper blocks to new oxidized terms", createRenamer(immutablemap))); ++ Schema schema132 = builder.addSchema(2691, DataFixers.SAME_NAMESPACED); ++ // CraftBukkit - decompile error ++ ImmutableMap immutablemap1 = ImmutableMap.builder().put("minecraft:waxed_copper", "minecraft:waxed_copper_block").put("minecraft:oxidized_copper_block", "minecraft:oxidized_copper").put("minecraft:weathered_copper_block", "minecraft:weathered_copper").put("minecraft:exposed_copper_block", "minecraft:exposed_copper").build(); + +- datafixerbuilder.addFixer(ItemRenameFix.create(schema132, "Rename copper item suffixes", createRenamer(immutablemap1))); +- datafixerbuilder.addFixer(BlockRenameFixWithJigsaw.create(schema132, "Rename copper blocks suffixes", createRenamer(immutablemap1))); +- Schema schema133 = datafixerbuilder.addSchema(2693, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(ItemRenameFix.create(schema132, "Rename copper item suffixes", createRenamer(immutablemap1))); ++ builder.addFixer(BlockRenameFixWithJigsaw.create(schema132, "Rename copper blocks suffixes", createRenamer(immutablemap1))); ++ Schema schema133 = builder.addSchema(2693, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new AddFlagIfNotPresentFix(schema133, References.WORLD_GEN_SETTINGS, "has_increased_height_already", false)); +- Schema schema134 = datafixerbuilder.addSchema(2696, DataFixers.SAME_NAMESPACED); +- ImmutableMap immutablemap2 = ImmutableMap.builder().put("minecraft:grimstone", "minecraft:deepslate").put("minecraft:grimstone_slab", "minecraft:cobbled_deepslate_slab").put("minecraft:grimstone_stairs", "minecraft:cobbled_deepslate_stairs").put("minecraft:grimstone_wall", "minecraft:cobbled_deepslate_wall").put("minecraft:polished_grimstone", "minecraft:polished_deepslate").put("minecraft:polished_grimstone_slab", "minecraft:polished_deepslate_slab").put("minecraft:polished_grimstone_stairs", "minecraft:polished_deepslate_stairs").put("minecraft:polished_grimstone_wall", "minecraft:polished_deepslate_wall").put("minecraft:grimstone_tiles", "minecraft:deepslate_tiles").put("minecraft:grimstone_tile_slab", "minecraft:deepslate_tile_slab").put("minecraft:grimstone_tile_stairs", "minecraft:deepslate_tile_stairs").put("minecraft:grimstone_tile_wall", "minecraft:deepslate_tile_wall").put("minecraft:grimstone_bricks", "minecraft:deepslate_bricks").put("minecraft:grimstone_brick_slab", "minecraft:deepslate_brick_slab").put("minecraft:grimstone_brick_stairs", "minecraft:deepslate_brick_stairs").put("minecraft:grimstone_brick_wall", "minecraft:deepslate_brick_wall").put("minecraft:chiseled_grimstone", "minecraft:chiseled_deepslate").build(); ++ builder.addFixer(new AddFlagIfNotPresentFix(schema133, DataConverterTypes.WORLD_GEN_SETTINGS, "has_increased_height_already", false)); ++ Schema schema134 = builder.addSchema(2696, DataFixers.SAME_NAMESPACED); ++ // CraftBukkit - decompile error ++ ImmutableMap immutablemap2 = ImmutableMap.builder().put("minecraft:grimstone", "minecraft:deepslate").put("minecraft:grimstone_slab", "minecraft:cobbled_deepslate_slab").put("minecraft:grimstone_stairs", "minecraft:cobbled_deepslate_stairs").put("minecraft:grimstone_wall", "minecraft:cobbled_deepslate_wall").put("minecraft:polished_grimstone", "minecraft:polished_deepslate").put("minecraft:polished_grimstone_slab", "minecraft:polished_deepslate_slab").put("minecraft:polished_grimstone_stairs", "minecraft:polished_deepslate_stairs").put("minecraft:polished_grimstone_wall", "minecraft:polished_deepslate_wall").put("minecraft:grimstone_tiles", "minecraft:deepslate_tiles").put("minecraft:grimstone_tile_slab", "minecraft:deepslate_tile_slab").put("minecraft:grimstone_tile_stairs", "minecraft:deepslate_tile_stairs").put("minecraft:grimstone_tile_wall", "minecraft:deepslate_tile_wall").put("minecraft:grimstone_bricks", "minecraft:deepslate_bricks").put("minecraft:grimstone_brick_slab", "minecraft:deepslate_brick_slab").put("minecraft:grimstone_brick_stairs", "minecraft:deepslate_brick_stairs").put("minecraft:grimstone_brick_wall", "minecraft:deepslate_brick_wall").put("minecraft:chiseled_grimstone", "minecraft:chiseled_deepslate").build(); + +- datafixerbuilder.addFixer(ItemRenameFix.create(schema134, "Renamed grimstone block items to deepslate", createRenamer(immutablemap2))); +- datafixerbuilder.addFixer(BlockRenameFixWithJigsaw.create(schema134, "Renamed grimstone blocks to deepslate", createRenamer(immutablemap2))); +- Schema schema135 = datafixerbuilder.addSchema(2700, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(ItemRenameFix.create(schema134, "Renamed grimstone block items to deepslate", createRenamer(immutablemap2))); ++ builder.addFixer(BlockRenameFixWithJigsaw.create(schema134, "Renamed grimstone blocks to deepslate", createRenamer(immutablemap2))); ++ Schema schema135 = builder.addSchema(2700, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(BlockRenameFixWithJigsaw.create(schema135, "Renamed cave vines blocks", createRenamer(ImmutableMap.of("minecraft:cave_vines_head", "minecraft:cave_vines", "minecraft:cave_vines_body", "minecraft:cave_vines_plant")))); +- Schema schema136 = datafixerbuilder.addSchema(2701, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(BlockRenameFixWithJigsaw.create(schema135, "Renamed cave vines blocks", createRenamer(ImmutableMap.of("minecraft:cave_vines_head", "minecraft:cave_vines", "minecraft:cave_vines_body", "minecraft:cave_vines_plant")))); ++ Schema schema136 = builder.addSchema(2701, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new SavedDataFeaturePoolElementFix(schema136)); +- Schema schema137 = datafixerbuilder.addSchema(2702, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new SavedDataFeaturePoolElementFix(schema136)); ++ Schema schema137 = builder.addSchema(2702, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new AbstractArrowPickupFix(schema137)); +- Schema schema138 = datafixerbuilder.addSchema(2704, V2704::new); ++ builder.addFixer(new AbstractArrowPickupFix(schema137)); ++ Schema schema138 = builder.addSchema(2704, V2704::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema138, "Added Goat", References.ENTITY)); +- Schema schema139 = datafixerbuilder.addSchema(2707, V2707::new); ++ builder.addFixer(new AddNewChoices(schema138, "Added Goat", DataConverterTypes.ENTITY)); ++ Schema schema139 = builder.addSchema(2707, V2707::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema139, "Added Marker", References.ENTITY)); +- datafixerbuilder.addFixer(new AddFlagIfNotPresentFix(schema139, References.WORLD_GEN_SETTINGS, "has_increased_height_already", true)); +- Schema schema140 = datafixerbuilder.addSchema(2710, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new AddNewChoices(schema139, "Added Marker", DataConverterTypes.ENTITY)); ++ builder.addFixer(new AddFlagIfNotPresentFix(schema139, DataConverterTypes.WORLD_GEN_SETTINGS, "has_increased_height_already", true)); ++ Schema schema140 = builder.addSchema(2710, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new StatsRenameFix(schema140, "Renamed play_one_minute stat to play_time", ImmutableMap.of("minecraft:play_one_minute", "minecraft:play_time"))); +- Schema schema141 = datafixerbuilder.addSchema(2717, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new StatsRenameFix(schema140, "Renamed play_one_minute stat to play_time", ImmutableMap.of("minecraft:play_one_minute", "minecraft:play_time"))); ++ Schema schema141 = builder.addSchema(2717, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(ItemRenameFix.create(schema141, "Rename azalea_leaves_flowers", createRenamer(ImmutableMap.of("minecraft:azalea_leaves_flowers", "minecraft:flowering_azalea_leaves")))); +- datafixerbuilder.addFixer(BlockRenameFix.create(schema141, "Rename azalea_leaves_flowers items", createRenamer(ImmutableMap.of("minecraft:azalea_leaves_flowers", "minecraft:flowering_azalea_leaves")))); +- Schema schema142 = datafixerbuilder.addSchema(2825, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(ItemRenameFix.create(schema141, "Rename azalea_leaves_flowers", createRenamer(ImmutableMap.of("minecraft:azalea_leaves_flowers", "minecraft:flowering_azalea_leaves")))); ++ builder.addFixer(BlockRenameFix.create(schema141, "Rename azalea_leaves_flowers items", createRenamer(ImmutableMap.of("minecraft:azalea_leaves_flowers", "minecraft:flowering_azalea_leaves")))); ++ Schema schema142 = builder.addSchema(2825, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new AddFlagIfNotPresentFix(schema142, References.WORLD_GEN_SETTINGS, "has_increased_height_already", false)); +- Schema schema143 = datafixerbuilder.addSchema(2831, V2831::new); ++ builder.addFixer(new AddFlagIfNotPresentFix(schema142, DataConverterTypes.WORLD_GEN_SETTINGS, "has_increased_height_already", false)); ++ Schema schema143 = builder.addSchema(2831, V2831::new); + +- datafixerbuilder.addFixer(new SpawnerDataFix(schema143)); +- Schema schema144 = datafixerbuilder.addSchema(2832, V2832::new); ++ builder.addFixer(new SpawnerDataFix(schema143)); ++ Schema schema144 = builder.addSchema(2832, V2832::new); + +- datafixerbuilder.addFixer(new WorldGenSettingsHeightAndBiomeFix(schema144)); +- datafixerbuilder.addFixer(new ChunkHeightAndBiomeFix(schema144)); +- Schema schema145 = datafixerbuilder.addSchema(2833, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new WorldGenSettingsHeightAndBiomeFix(schema144)); ++ builder.addFixer(new ChunkHeightAndBiomeFix(schema144)); ++ Schema schema145 = builder.addSchema(2833, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new WorldGenSettingsDisallowOldCustomWorldsFix(schema145)); +- Schema schema146 = datafixerbuilder.addSchema(2838, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new WorldGenSettingsDisallowOldCustomWorldsFix(schema145)); ++ Schema schema146 = builder.addSchema(2838, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new NamespacedTypeRenameFix(schema146, "Caves and Cliffs biome renames", References.BIOME, createRenamer(CavesAndCliffsRenames.RENAMES))); +- Schema schema147 = datafixerbuilder.addSchema(2841, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new NamespacedTypeRenameFix(schema146, "Caves and Cliffs biome renames", DataConverterTypes.BIOME, createRenamer(CavesAndCliffsRenames.RENAMES))); ++ Schema schema147 = builder.addSchema(2841, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new ChunkProtoTickListFix(schema147)); +- Schema schema148 = datafixerbuilder.addSchema(2842, V2842::new); ++ builder.addFixer(new ChunkProtoTickListFix(schema147)); ++ Schema schema148 = builder.addSchema(2842, V2842::new); + +- datafixerbuilder.addFixer(new ChunkRenamesFix(schema148)); +- Schema schema149 = datafixerbuilder.addSchema(2843, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new ChunkRenamesFix(schema148)); ++ Schema schema149 = builder.addSchema(2843, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new OverreachingTickFix(schema149)); +- datafixerbuilder.addFixer(new NamespacedTypeRenameFix(schema149, "Remove Deep Warm Ocean", References.BIOME, createRenamer("minecraft:deep_warm_ocean", "minecraft:warm_ocean"))); +- Schema schema150 = datafixerbuilder.addSchema(2846, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new OverreachingTickFix(schema149)); ++ builder.addFixer(new NamespacedTypeRenameFix(schema149, "Remove Deep Warm Ocean", DataConverterTypes.BIOME, createRenamer("minecraft:deep_warm_ocean", "minecraft:warm_ocean"))); ++ Schema schema150 = builder.addSchema(2846, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new AdvancementsRenameFix(schema150, false, "Rename some C&C part 2 advancements", createRenamer(ImmutableMap.of("minecraft:husbandry/play_jukebox_in_meadows", "minecraft:adventure/play_jukebox_in_meadows", "minecraft:adventure/caves_and_cliff", "minecraft:adventure/fall_from_world_height", "minecraft:adventure/ride_strider_in_overworld_lava", "minecraft:nether/ride_strider_in_overworld_lava")))); +- Schema schema151 = datafixerbuilder.addSchema(2852, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new AdvancementsRenameFix(schema150, false, "Rename some C&C part 2 advancements", createRenamer(ImmutableMap.of("minecraft:husbandry/play_jukebox_in_meadows", "minecraft:adventure/play_jukebox_in_meadows", "minecraft:adventure/caves_and_cliff", "minecraft:adventure/fall_from_world_height", "minecraft:adventure/ride_strider_in_overworld_lava", "minecraft:nether/ride_strider_in_overworld_lava")))); ++ Schema schema151 = builder.addSchema(2852, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new WorldGenSettingsDisallowOldCustomWorldsFix(schema151)); +- Schema schema152 = datafixerbuilder.addSchema(2967, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new WorldGenSettingsDisallowOldCustomWorldsFix(schema151)); ++ Schema schema152 = builder.addSchema(2967, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new StructureSettingsFlattenFix(schema152)); +- Schema schema153 = datafixerbuilder.addSchema(2970, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new StructureSettingsFlattenFix(schema152)); ++ Schema schema153 = builder.addSchema(2970, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new StructuresBecomeConfiguredFix(schema153)); +- Schema schema154 = datafixerbuilder.addSchema(3076, V3076::new); ++ builder.addFixer(new StructuresBecomeConfiguredFix(schema153)); ++ Schema schema154 = builder.addSchema(3076, V3076::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema154, "Added Sculk Catalyst", References.BLOCK_ENTITY)); +- Schema schema155 = datafixerbuilder.addSchema(3077, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new AddNewChoices(schema154, "Added Sculk Catalyst", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema155 = builder.addSchema(3077, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new ChunkDeleteIgnoredLightDataFix(schema155)); +- Schema schema156 = datafixerbuilder.addSchema(3078, V3078::new); ++ builder.addFixer(new ChunkDeleteIgnoredLightDataFix(schema155)); ++ Schema schema156 = builder.addSchema(3078, V3078::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema156, "Added Frog", References.ENTITY)); +- datafixerbuilder.addFixer(new AddNewChoices(schema156, "Added Tadpole", References.ENTITY)); +- datafixerbuilder.addFixer(new AddNewChoices(schema156, "Added Sculk Shrieker", References.BLOCK_ENTITY)); +- Schema schema157 = datafixerbuilder.addSchema(3081, V3081::new); ++ builder.addFixer(new AddNewChoices(schema156, "Added Frog", DataConverterTypes.ENTITY)); ++ builder.addFixer(new AddNewChoices(schema156, "Added Tadpole", DataConverterTypes.ENTITY)); ++ builder.addFixer(new AddNewChoices(schema156, "Added Sculk Shrieker", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema157 = builder.addSchema(3081, V3081::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema157, "Added Warden", References.ENTITY)); +- Schema schema158 = datafixerbuilder.addSchema(3082, V3082::new); ++ builder.addFixer(new AddNewChoices(schema157, "Added Warden", DataConverterTypes.ENTITY)); ++ Schema schema158 = builder.addSchema(3082, V3082::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema158, "Added Chest Boat", References.ENTITY)); +- Schema schema159 = datafixerbuilder.addSchema(3083, V3083::new); ++ builder.addFixer(new AddNewChoices(schema158, "Added Chest Boat", DataConverterTypes.ENTITY)); ++ Schema schema159 = builder.addSchema(3083, V3083::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema159, "Added Allay", References.ENTITY)); +- Schema schema160 = datafixerbuilder.addSchema(3084, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new AddNewChoices(schema159, "Added Allay", DataConverterTypes.ENTITY)); ++ Schema schema160 = builder.addSchema(3084, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new NamespacedTypeRenameFix(schema160, "game_event_renames_3084", References.GAME_EVENT_NAME, createRenamer(ImmutableMap.builder().put("minecraft:block_press", "minecraft:block_activate").put("minecraft:block_switch", "minecraft:block_activate").put("minecraft:block_unpress", "minecraft:block_deactivate").put("minecraft:block_unswitch", "minecraft:block_deactivate").put("minecraft:drinking_finish", "minecraft:drink").put("minecraft:elytra_free_fall", "minecraft:elytra_glide").put("minecraft:entity_damaged", "minecraft:entity_damage").put("minecraft:entity_dying", "minecraft:entity_die").put("minecraft:entity_killed", "minecraft:entity_die").put("minecraft:mob_interact", "minecraft:entity_interact").put("minecraft:ravager_roar", "minecraft:entity_roar").put("minecraft:ring_bell", "minecraft:block_change").put("minecraft:shulker_close", "minecraft:container_close").put("minecraft:shulker_open", "minecraft:container_open").put("minecraft:wolf_shaking", "minecraft:entity_shake").build()))); +- Schema schema161 = datafixerbuilder.addSchema(3086, DataFixers.SAME_NAMESPACED); +- TypeReference typereference = References.ENTITY; +- Int2ObjectOpenHashMap int2objectopenhashmap = (Int2ObjectOpenHashMap) Util.make(new Int2ObjectOpenHashMap(), (int2objectopenhashmap1) -> { ++ // CraftBukkit - decompile error ++ builder.addFixer(new NamespacedTypeRenameFix(schema160, "game_event_renames_3084", DataConverterTypes.GAME_EVENT_NAME, createRenamer(ImmutableMap.builder().put("minecraft:block_press", "minecraft:block_activate").put("minecraft:block_switch", "minecraft:block_activate").put("minecraft:block_unpress", "minecraft:block_deactivate").put("minecraft:block_unswitch", "minecraft:block_deactivate").put("minecraft:drinking_finish", "minecraft:drink").put("minecraft:elytra_free_fall", "minecraft:elytra_glide").put("minecraft:entity_damaged", "minecraft:entity_damage").put("minecraft:entity_dying", "minecraft:entity_die").put("minecraft:entity_killed", "minecraft:entity_die").put("minecraft:mob_interact", "minecraft:entity_interact").put("minecraft:ravager_roar", "minecraft:entity_roar").put("minecraft:ring_bell", "minecraft:block_change").put("minecraft:shulker_close", "minecraft:container_close").put("minecraft:shulker_open", "minecraft:container_open").put("minecraft:wolf_shaking", "minecraft:entity_shake").build()))); ++ Schema schema161 = builder.addSchema(3086, DataFixers.SAME_NAMESPACED); ++ TypeReference typereference = DataConverterTypes.ENTITY; ++ Int2ObjectOpenHashMap int2objectopenhashmap = (Int2ObjectOpenHashMap) Util.make(new Int2ObjectOpenHashMap(), (int2objectopenhashmap1) -> { // CraftBukkit - decompile error + int2objectopenhashmap1.defaultReturnValue("minecraft:tabby"); + int2objectopenhashmap1.put(0, "minecraft:tabby"); + int2objectopenhashmap1.put(1, "minecraft:black"); +@@ -897,160 +735,161 @@ + }); + + Objects.requireNonNull(int2objectopenhashmap); +- datafixerbuilder.addFixer(new EntityVariantFix(schema161, "Change cat variant type", typereference, "minecraft:cat", "CatType", int2objectopenhashmap::get)); +- ImmutableMap immutablemap3 = ImmutableMap.builder().put("textures/entity/cat/tabby.png", "minecraft:tabby").put("textures/entity/cat/black.png", "minecraft:black").put("textures/entity/cat/red.png", "minecraft:red").put("textures/entity/cat/siamese.png", "minecraft:siamese").put("textures/entity/cat/british_shorthair.png", "minecraft:british").put("textures/entity/cat/calico.png", "minecraft:calico").put("textures/entity/cat/persian.png", "minecraft:persian").put("textures/entity/cat/ragdoll.png", "minecraft:ragdoll").put("textures/entity/cat/white.png", "minecraft:white").put("textures/entity/cat/jellie.png", "minecraft:jellie").put("textures/entity/cat/all_black.png", "minecraft:all_black").build(); ++ builder.addFixer(new EntityVariantFix(schema161, "Change cat variant type", typereference, "minecraft:cat", "CatType", int2objectopenhashmap::get)); ++ // CraftBukkit - decompile error ++ ImmutableMap immutablemap3 = ImmutableMap.builder().put("textures/entity/cat/tabby.png", "minecraft:tabby").put("textures/entity/cat/black.png", "minecraft:black").put("textures/entity/cat/red.png", "minecraft:red").put("textures/entity/cat/siamese.png", "minecraft:siamese").put("textures/entity/cat/british_shorthair.png", "minecraft:british").put("textures/entity/cat/calico.png", "minecraft:calico").put("textures/entity/cat/persian.png", "minecraft:persian").put("textures/entity/cat/ragdoll.png", "minecraft:ragdoll").put("textures/entity/cat/white.png", "minecraft:white").put("textures/entity/cat/jellie.png", "minecraft:jellie").put("textures/entity/cat/all_black.png", "minecraft:all_black").build(); + +- datafixerbuilder.addFixer(new CriteriaRenameFix(schema161, "Migrate cat variant advancement", "minecraft:husbandry/complete_catalogue", (s) -> { ++ builder.addFixer(new CriteriaRenameFix(schema161, "Migrate cat variant advancement", "minecraft:husbandry/complete_catalogue", (s) -> { + return (String) immutablemap3.getOrDefault(s, s); + })); +- Schema schema162 = datafixerbuilder.addSchema(3087, DataFixers.SAME_NAMESPACED); ++ Schema schema162 = builder.addSchema(3087, DataFixers.SAME_NAMESPACED); + +- typereference = References.ENTITY; ++ typereference = DataConverterTypes.ENTITY; + int2objectopenhashmap = (Int2ObjectOpenHashMap) Util.make(new Int2ObjectOpenHashMap(), (int2objectopenhashmap1) -> { + int2objectopenhashmap1.put(0, "minecraft:temperate"); + int2objectopenhashmap1.put(1, "minecraft:warm"); + int2objectopenhashmap1.put(2, "minecraft:cold"); + }); + Objects.requireNonNull(int2objectopenhashmap); +- datafixerbuilder.addFixer(new EntityVariantFix(schema162, "Change frog variant type", typereference, "minecraft:frog", "Variant", int2objectopenhashmap::get)); +- Schema schema163 = datafixerbuilder.addSchema(3090, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new EntityVariantFix(schema162, "Change frog variant type", typereference, "minecraft:frog", "Variant", int2objectopenhashmap::get)); ++ Schema schema163 = builder.addSchema(3090, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new EntityPaintingFieldsRenameFix(schema163)); +- Schema schema164 = datafixerbuilder.addSchema(3093, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new EntityPaintingFieldsRenameFix(schema163)); ++ Schema schema164 = builder.addSchema(3093, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new EntityGoatMissingStateFix(schema164)); +- Schema schema165 = datafixerbuilder.addSchema(3094, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new EntityGoatMissingStateFix(schema164)); ++ Schema schema165 = builder.addSchema(3094, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new GoatHornIdFix(schema165)); +- Schema schema166 = datafixerbuilder.addSchema(3097, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new GoatHornIdFix(schema165)); ++ Schema schema166 = builder.addSchema(3097, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new FilteredBooksFix(schema166)); +- datafixerbuilder.addFixer(new FilteredSignsFix(schema166)); ++ builder.addFixer(new FilteredBooksFix(schema166)); ++ builder.addFixer(new FilteredSignsFix(schema166)); + Map map = Map.of("minecraft:british", "minecraft:british_shorthair"); + +- datafixerbuilder.addFixer(new VariantRenameFix(schema166, "Rename british shorthair", References.ENTITY, "minecraft:cat", map)); +- datafixerbuilder.addFixer(new CriteriaRenameFix(schema166, "Migrate cat variant advancement for british shorthair", "minecraft:husbandry/complete_catalogue", (s) -> { ++ builder.addFixer(new VariantRenameFix(schema166, "Rename british shorthair", DataConverterTypes.ENTITY, "minecraft:cat", map)); ++ builder.addFixer(new CriteriaRenameFix(schema166, "Migrate cat variant advancement for british shorthair", "minecraft:husbandry/complete_catalogue", (s) -> { + return (String) map.getOrDefault(s, s); + })); + Set set = Set.of("minecraft:unemployed", "minecraft:nitwit"); + + Objects.requireNonNull(set); +- datafixerbuilder.addFixer(new PoiTypeRemoveFix(schema166, "Remove unpopulated villager PoI types", set::contains)); +- Schema schema167 = datafixerbuilder.addSchema(3108, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new PoiTypeRemoveFix(schema166, "Remove unpopulated villager PoI types", set::contains)); ++ Schema schema167 = builder.addSchema(3108, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new BlendingDataRemoveFromNetherEndFix(schema167)); +- Schema schema168 = datafixerbuilder.addSchema(3201, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new BlendingDataRemoveFromNetherEndFix(schema167)); ++ Schema schema168 = builder.addSchema(3201, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new OptionsProgrammerArtFix(schema168)); +- Schema schema169 = datafixerbuilder.addSchema(3202, V3202::new); ++ builder.addFixer(new OptionsProgrammerArtFix(schema168)); ++ Schema schema169 = builder.addSchema(3202, V3202::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema169, "Added Hanging Sign", References.BLOCK_ENTITY)); +- Schema schema170 = datafixerbuilder.addSchema(3203, V3203::new); ++ builder.addFixer(new AddNewChoices(schema169, "Added Hanging Sign", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema170 = builder.addSchema(3203, V3203::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema170, "Added Camel", References.ENTITY)); +- Schema schema171 = datafixerbuilder.addSchema(3204, V3204::new); ++ builder.addFixer(new AddNewChoices(schema170, "Added Camel", DataConverterTypes.ENTITY)); ++ Schema schema171 = builder.addSchema(3204, V3204::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema171, "Added Chiseled Bookshelf", References.BLOCK_ENTITY)); +- Schema schema172 = datafixerbuilder.addSchema(3209, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new AddNewChoices(schema171, "Added Chiseled Bookshelf", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema172 = builder.addSchema(3209, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new ItemStackSpawnEggFix(schema172, false, "minecraft:pig_spawn_egg")); +- Schema schema173 = datafixerbuilder.addSchema(3214, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new ItemStackSpawnEggFix(schema172, false, "minecraft:pig_spawn_egg")); ++ Schema schema173 = builder.addSchema(3214, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new OptionsAmbientOcclusionFix(schema173)); +- Schema schema174 = datafixerbuilder.addSchema(3319, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new OptionsAmbientOcclusionFix(schema173)); ++ Schema schema174 = builder.addSchema(3319, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new OptionsAccessibilityOnboardFix(schema174)); +- Schema schema175 = datafixerbuilder.addSchema(3322, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new OptionsAccessibilityOnboardFix(schema174)); ++ Schema schema175 = builder.addSchema(3322, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new EffectDurationFix(schema175)); +- Schema schema176 = datafixerbuilder.addSchema(3325, V3325::new); ++ builder.addFixer(new EffectDurationFix(schema175)); ++ Schema schema176 = builder.addSchema(3325, V3325::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema176, "Added displays", References.ENTITY)); +- Schema schema177 = datafixerbuilder.addSchema(3326, V3326::new); ++ builder.addFixer(new AddNewChoices(schema176, "Added displays", DataConverterTypes.ENTITY)); ++ Schema schema177 = builder.addSchema(3326, V3326::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema177, "Added Sniffer", References.ENTITY)); +- Schema schema178 = datafixerbuilder.addSchema(3327, V3327::new); ++ builder.addFixer(new AddNewChoices(schema177, "Added Sniffer", DataConverterTypes.ENTITY)); ++ Schema schema178 = builder.addSchema(3327, V3327::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema178, "Archaeology", References.BLOCK_ENTITY)); +- Schema schema179 = datafixerbuilder.addSchema(3328, V3328::new); ++ builder.addFixer(new AddNewChoices(schema178, "Archaeology", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema179 = builder.addSchema(3328, V3328::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema179, "Added interaction", References.ENTITY)); +- Schema schema180 = datafixerbuilder.addSchema(3438, V3438::new); ++ builder.addFixer(new AddNewChoices(schema179, "Added interaction", DataConverterTypes.ENTITY)); ++ Schema schema180 = builder.addSchema(3438, V3438::new); + +- datafixerbuilder.addFixer(BlockEntityRenameFix.create(schema180, "Rename Suspicious Sand to Brushable Block", createRenamer("minecraft:suspicious_sand", "minecraft:brushable_block"))); +- datafixerbuilder.addFixer(new EntityBrushableBlockFieldsRenameFix(schema180)); +- datafixerbuilder.addFixer(ItemRenameFix.create(schema180, "Pottery shard renaming", createRenamer(ImmutableMap.of("minecraft:pottery_shard_archer", "minecraft:archer_pottery_shard", "minecraft:pottery_shard_prize", "minecraft:prize_pottery_shard", "minecraft:pottery_shard_arms_up", "minecraft:arms_up_pottery_shard", "minecraft:pottery_shard_skull", "minecraft:skull_pottery_shard")))); +- datafixerbuilder.addFixer(new AddNewChoices(schema180, "Added calibrated sculk sensor", References.BLOCK_ENTITY)); +- Schema schema181 = datafixerbuilder.addSchema(3439, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(BlockEntityRenameFix.create(schema180, "Rename Suspicious Sand to Brushable Block", createRenamer("minecraft:suspicious_sand", "minecraft:brushable_block"))); ++ builder.addFixer(new EntityBrushableBlockFieldsRenameFix(schema180)); ++ builder.addFixer(ItemRenameFix.create(schema180, "Pottery shard renaming", createRenamer(ImmutableMap.of("minecraft:pottery_shard_archer", "minecraft:archer_pottery_shard", "minecraft:pottery_shard_prize", "minecraft:prize_pottery_shard", "minecraft:pottery_shard_arms_up", "minecraft:arms_up_pottery_shard", "minecraft:pottery_shard_skull", "minecraft:skull_pottery_shard")))); ++ builder.addFixer(new AddNewChoices(schema180, "Added calibrated sculk sensor", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema181 = builder.addSchema(3439, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new BlockEntitySignDoubleSidedEditableTextFix(schema181, "Updated sign text format for Signs", "minecraft:sign")); +- datafixerbuilder.addFixer(new BlockEntitySignDoubleSidedEditableTextFix(schema181, "Updated sign text format for Hanging Signs", "minecraft:hanging_sign")); +- Schema schema182 = datafixerbuilder.addSchema(3440, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new BlockEntitySignDoubleSidedEditableTextFix(schema181, "Updated sign text format for Signs", "minecraft:sign")); ++ builder.addFixer(new BlockEntitySignDoubleSidedEditableTextFix(schema181, "Updated sign text format for Hanging Signs", "minecraft:hanging_sign")); ++ Schema schema182 = builder.addSchema(3440, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new NamespacedTypeRenameFix(schema182, "Replace experimental 1.20 overworld", References.MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST, createRenamer("minecraft:overworld_update_1_20", "minecraft:overworld"))); +- datafixerbuilder.addFixer(new FeatureFlagRemoveFix(schema182, "Remove 1.20 feature toggle", Set.of("minecraft:update_1_20"))); +- Schema schema183 = datafixerbuilder.addSchema(3441, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new NamespacedTypeRenameFix(schema182, "Replace experimental 1.20 overworld", DataConverterTypes.MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST, createRenamer("minecraft:overworld_update_1_20", "minecraft:overworld"))); ++ builder.addFixer(new FeatureFlagRemoveFix(schema182, "Remove 1.20 feature toggle", Set.of("minecraft:update_1_20"))); ++ Schema schema183 = builder.addSchema(3441, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new BlendingDataFix(schema183)); +- Schema schema184 = datafixerbuilder.addSchema(3447, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new BlendingDataFix(schema183)); ++ Schema schema184 = builder.addSchema(3447, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(ItemRenameFix.create(schema184, "Pottery shard item renaming to Pottery sherd", createRenamer((Map) Stream.of("minecraft:angler_pottery_shard", "minecraft:archer_pottery_shard", "minecraft:arms_up_pottery_shard", "minecraft:blade_pottery_shard", "minecraft:brewer_pottery_shard", "minecraft:burn_pottery_shard", "minecraft:danger_pottery_shard", "minecraft:explorer_pottery_shard", "minecraft:friend_pottery_shard", "minecraft:heart_pottery_shard", "minecraft:heartbreak_pottery_shard", "minecraft:howl_pottery_shard", "minecraft:miner_pottery_shard", "minecraft:mourner_pottery_shard", "minecraft:plenty_pottery_shard", "minecraft:prize_pottery_shard", "minecraft:sheaf_pottery_shard", "minecraft:shelter_pottery_shard", "minecraft:skull_pottery_shard", "minecraft:snort_pottery_shard").collect(Collectors.toMap(Function.identity(), (s) -> { ++ builder.addFixer(ItemRenameFix.create(schema184, "Pottery shard item renaming to Pottery sherd", createRenamer((Map) Stream.of("minecraft:angler_pottery_shard", "minecraft:archer_pottery_shard", "minecraft:arms_up_pottery_shard", "minecraft:blade_pottery_shard", "minecraft:brewer_pottery_shard", "minecraft:burn_pottery_shard", "minecraft:danger_pottery_shard", "minecraft:explorer_pottery_shard", "minecraft:friend_pottery_shard", "minecraft:heart_pottery_shard", "minecraft:heartbreak_pottery_shard", "minecraft:howl_pottery_shard", "minecraft:miner_pottery_shard", "minecraft:mourner_pottery_shard", "minecraft:plenty_pottery_shard", "minecraft:prize_pottery_shard", "minecraft:sheaf_pottery_shard", "minecraft:shelter_pottery_shard", "minecraft:skull_pottery_shard", "minecraft:snort_pottery_shard").collect(Collectors.toMap(Function.identity(), (s) -> { + return s.replace("_pottery_shard", "_pottery_sherd"); + }))))); +- Schema schema185 = datafixerbuilder.addSchema(3448, V3448::new); ++ Schema schema185 = builder.addSchema(3448, V3448::new); + +- datafixerbuilder.addFixer(new DecoratedPotFieldRenameFix(schema185)); +- Schema schema186 = datafixerbuilder.addSchema(3450, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new DecoratedPotFieldRenameFix(schema185)); ++ Schema schema186 = builder.addSchema(3450, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new RemapChunkStatusFix(schema186, "Remove liquid_carvers and heightmap chunk statuses", createRenamer(Map.of("minecraft:liquid_carvers", "minecraft:carvers", "minecraft:heightmaps", "minecraft:spawn")))); +- Schema schema187 = datafixerbuilder.addSchema(3451, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new RemapChunkStatusFix(schema186, "Remove liquid_carvers and heightmap chunk statuses", createRenamer(Map.of("minecraft:liquid_carvers", "minecraft:carvers", "minecraft:heightmaps", "minecraft:spawn")))); ++ Schema schema187 = builder.addSchema(3451, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new ChunkDeleteLightFix(schema187)); +- Schema schema188 = datafixerbuilder.addSchema(3459, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new ChunkDeleteLightFix(schema187)); ++ Schema schema188 = builder.addSchema(3459, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new LegacyDragonFightFix(schema188)); +- Schema schema189 = datafixerbuilder.addSchema(3564, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new LegacyDragonFightFix(schema188)); ++ Schema schema189 = builder.addSchema(3564, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new DropInvalidSignDataFix(schema189, "Drop invalid sign datafix data", "minecraft:sign")); +- datafixerbuilder.addFixer(new DropInvalidSignDataFix(schema189, "Drop invalid hanging sign datafix data", "minecraft:hanging_sign")); +- Schema schema190 = datafixerbuilder.addSchema(3565, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new DropInvalidSignDataFix(schema189, "Drop invalid sign datafix data", "minecraft:sign")); ++ builder.addFixer(new DropInvalidSignDataFix(schema189, "Drop invalid hanging sign datafix data", "minecraft:hanging_sign")); ++ Schema schema190 = builder.addSchema(3565, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new RandomSequenceSettingsFix(schema190)); +- Schema schema191 = datafixerbuilder.addSchema(3566, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new RandomSequenceSettingsFix(schema190)); ++ Schema schema191 = builder.addSchema(3566, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new ScoreboardDisplaySlotFix(schema191)); +- Schema schema192 = datafixerbuilder.addSchema(3568, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new ScoreboardDisplaySlotFix(schema191)); ++ Schema schema192 = builder.addSchema(3568, DataFixers.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new MobEffectIdFix(schema192)); +- Schema schema193 = datafixerbuilder.addSchema(3682, V3682::new); ++ builder.addFixer(new MobEffectIdFix(schema192)); ++ Schema schema193 = builder.addSchema(3682, V3682::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema193, "Added Crafter", References.BLOCK_ENTITY)); +- Schema schema194 = datafixerbuilder.addSchema(3683, V3683::new); ++ builder.addFixer(new AddNewChoices(schema193, "Added Crafter", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema194 = builder.addSchema(3683, V3683::new); + +- datafixerbuilder.addFixer(new PrimedTntBlockStateFixer(schema194)); +- Schema schema195 = datafixerbuilder.addSchema(3685, V3685::new); ++ builder.addFixer(new PrimedTntBlockStateFixer(schema194)); ++ Schema schema195 = builder.addSchema(3685, V3685::new); + +- datafixerbuilder.addFixer(new FixProjectileStoredItem(schema195)); +- Schema schema196 = datafixerbuilder.addSchema(3689, V3689::new); ++ builder.addFixer(new FixProjectileStoredItem(schema195)); ++ Schema schema196 = builder.addSchema(3689, V3689::new); + +- datafixerbuilder.addFixer(new AddNewChoices(schema196, "Added Breeze", References.ENTITY)); +- datafixerbuilder.addFixer(new AddNewChoices(schema196, "Added Trial Spawner", References.BLOCK_ENTITY)); +- Schema schema197 = datafixerbuilder.addSchema(3692, DataFixers.SAME_NAMESPACED); ++ builder.addFixer(new AddNewChoices(schema196, "Added Breeze", DataConverterTypes.ENTITY)); ++ builder.addFixer(new AddNewChoices(schema196, "Added Trial Spawner", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema197 = builder.addSchema(3692, DataFixers.SAME_NAMESPACED); + UnaryOperator unaryoperator1 = createRenamer(Map.of("minecraft:grass", "minecraft:short_grass")); + +- datafixerbuilder.addFixer(BlockRenameFixWithJigsaw.create(schema197, "Rename grass block to short_grass", unaryoperator1)); +- datafixerbuilder.addFixer(ItemRenameFix.create(schema197, "Rename grass item to short_grass", unaryoperator1)); ++ builder.addFixer(BlockRenameFixWithJigsaw.create(schema197, "Rename grass block to short_grass", unaryoperator1)); ++ builder.addFixer(ItemRenameFix.create(schema197, "Rename grass item to short_grass", unaryoperator1)); + } + +- private static UnaryOperator createRenamer(Map map) { ++ private static UnaryOperator createRenamer(Map renameMap) { + return (s) -> { +- return (String) map.getOrDefault(s, s); ++ return (String) renameMap.getOrDefault(s, s); + }; + } + +- private static UnaryOperator createRenamer(String s, String s1) { ++ private static UnaryOperator createRenamer(String oldName, String newName) { + return (s2) -> { +- return Objects.equals(s2, s) ? s1 : s2; ++ return Objects.equals(s2, oldName) ? newName : s2; + }; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java.patch b/patch-remap/mache-spigotflower/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java.patch new file mode 100644 index 0000000000..aafb3e922d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java ++++ b/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java +@@ -15,14 +15,13 @@ + + public class ItemStackMapIdFix extends DataFix { + +- public ItemStackMapIdFix(Schema schema, boolean flag) { +- super(schema, flag); ++ public ItemStackMapIdFix(Schema outputSchema, boolean changesType) { ++ super(outputSchema, changesType); + } + +- @Override + public TypeRewriteRule makeRule() { +- Type type = this.getInputSchema().getType(References.ITEM_STACK); +- OpticFinder> opticfinder = DSL.fieldFinder("id", DSL.named(References.ITEM_NAME.typeName(), NamespacedSchema.namespacedString())); ++ Type type = this.getInputSchema().getType(DataConverterTypes.ITEM_STACK); ++ OpticFinder> opticfinder = DSL.fieldFinder("id", DSL.named(DataConverterTypes.ITEM_NAME.typeName(), NamespacedSchema.namespacedString())); + OpticFinder opticfinder1 = type.findField("tag"); + + return this.fixTypeEverywhereTyped("ItemInstanceMapIdFix", type, (typed) -> { +@@ -33,7 +32,7 @@ + Typed typed1 = typed.getOrCreateTyped(opticfinder1); + Dynamic dynamic1 = (Dynamic) typed1.get(DSL.remainderFinder()); + +- dynamic1 = dynamic1.set("map", dynamic1.createInt(dynamic.get("Damage").asInt(0))); ++ if (!dynamic1.getElement("map").result().isPresent()) dynamic1 = dynamic1.set("map", dynamic1.createInt(dynamic.get("Damage").asInt(0))); // CraftBukkit + return typed.set(opticfinder1, typed1.set(DSL.remainderFinder(), dynamic1)); + } else { + return typed; diff --git a/patch-remap/mache-spigotflower/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java.patch b/patch-remap/mache-spigotflower/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java.patch new file mode 100644 index 0000000000..b73428dfd5 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java.patch @@ -0,0 +1,54 @@ +--- a/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java ++++ b/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java +@@ -348,14 +348,13 @@ + }).collect(Collectors.toSet()); + private static final Set DAMAGE_IDS = Sets.newHashSet(new String[]{"minecraft:bow", "minecraft:carrot_on_a_stick", "minecraft:chainmail_boots", "minecraft:chainmail_chestplate", "minecraft:chainmail_helmet", "minecraft:chainmail_leggings", "minecraft:diamond_axe", "minecraft:diamond_boots", "minecraft:diamond_chestplate", "minecraft:diamond_helmet", "minecraft:diamond_hoe", "minecraft:diamond_leggings", "minecraft:diamond_pickaxe", "minecraft:diamond_shovel", "minecraft:diamond_sword", "minecraft:elytra", "minecraft:fishing_rod", "minecraft:flint_and_steel", "minecraft:golden_axe", "minecraft:golden_boots", "minecraft:golden_chestplate", "minecraft:golden_helmet", "minecraft:golden_hoe", "minecraft:golden_leggings", "minecraft:golden_pickaxe", "minecraft:golden_shovel", "minecraft:golden_sword", "minecraft:iron_axe", "minecraft:iron_boots", "minecraft:iron_chestplate", "minecraft:iron_helmet", "minecraft:iron_hoe", "minecraft:iron_leggings", "minecraft:iron_pickaxe", "minecraft:iron_shovel", "minecraft:iron_sword", "minecraft:leather_boots", "minecraft:leather_chestplate", "minecraft:leather_helmet", "minecraft:leather_leggings", "minecraft:shears", "minecraft:shield", "minecraft:stone_axe", "minecraft:stone_hoe", "minecraft:stone_pickaxe", "minecraft:stone_shovel", "minecraft:stone_sword", "minecraft:wooden_axe", "minecraft:wooden_hoe", "minecraft:wooden_pickaxe", "minecraft:wooden_shovel", "minecraft:wooden_sword"}); + +- public ItemStackTheFlatteningFix(Schema schema, boolean flag) { +- super(schema, flag); ++ public ItemStackTheFlatteningFix(Schema outputSchema, boolean changesType) { ++ super(outputSchema, changesType); + } + +- @Override + public TypeRewriteRule makeRule() { +- Type type = this.getInputSchema().getType(References.ITEM_STACK); +- OpticFinder> opticfinder = DSL.fieldFinder("id", DSL.named(References.ITEM_NAME.typeName(), NamespacedSchema.namespacedString())); ++ Type type = this.getInputSchema().getType(DataConverterTypes.ITEM_STACK); ++ OpticFinder> opticfinder = DSL.fieldFinder("id", DSL.named(DataConverterTypes.ITEM_NAME.typeName(), NamespacedSchema.namespacedString())); + OpticFinder opticfinder1 = type.findField("tag"); + + return this.fixTypeEverywhereTyped("ItemInstanceTheFlatteningFix", type, (typed) -> { +@@ -370,14 +369,14 @@ + String s = updateItem((String) ((Pair) optional.get()).getSecond(), i); + + if (s != null) { +- typed1 = typed.set(opticfinder, Pair.of(References.ITEM_NAME.typeName(), s)); ++ typed1 = typed.set(opticfinder, Pair.of(DataConverterTypes.ITEM_NAME.typeName(), s)); + } + + if (ItemStackTheFlatteningFix.DAMAGE_IDS.contains(((Pair) optional.get()).getSecond())) { + Typed typed2 = typed.getOrCreateTyped(opticfinder1); + Dynamic dynamic1 = (Dynamic) typed2.get(DSL.remainderFinder()); + +- dynamic1 = dynamic1.set("Damage", dynamic1.createInt(i)); ++ if (i != 0) dynamic1 = dynamic1.set("Damage", dynamic1.createInt(i)); // CraftBukkit + typed1 = typed1.set(opticfinder1, typed2.set(DSL.remainderFinder(), dynamic1)); + } + +@@ -388,11 +387,11 @@ + } + + @Nullable +- public static String updateItem(@Nullable String s, int i) { +- if (ItemStackTheFlatteningFix.IDS.contains(s)) { +- String s1 = (String) ItemStackTheFlatteningFix.MAP.get(s + "." + i); ++ public static String updateItem(@Nullable String item, int dataValue) { ++ if (ItemStackTheFlatteningFix.IDS.contains(item)) { ++ String s1 = (String) ItemStackTheFlatteningFix.MAP.get(item + "." + dataValue); + +- return s1 == null ? (String) ItemStackTheFlatteningFix.MAP.get(s + ".0") : s1; ++ return s1 == null ? (String) ItemStackTheFlatteningFix.MAP.get(item + ".0") : s1; + } else { + return null; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/util/worldupdate/WorldUpgrader.java.patch b/patch-remap/mache-spigotflower/net/minecraft/util/worldupdate/WorldUpgrader.java.patch new file mode 100644 index 0000000000..37805ff336 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/util/worldupdate/WorldUpgrader.java.patch @@ -0,0 +1,152 @@ +--- a/net/minecraft/util/worldupdate/WorldUpgrader.java ++++ b/net/minecraft/util/worldupdate/WorldUpgrader.java +@@ -64,13 +64,13 @@ + private static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$"); + private final DimensionDataStorage overworldDataStorage; + +- public WorldUpgrader(LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess, DataFixer datafixer, Registry registry, boolean flag) { +- this.dimensions = registry; +- this.levels = (Set) registry.registryKeySet().stream().map(Registries::levelStemToLevel).collect(Collectors.toUnmodifiableSet()); +- this.eraseCache = flag; +- this.dataFixer = datafixer; +- this.levelStorage = levelstoragesource_levelstorageaccess; +- this.overworldDataStorage = new DimensionDataStorage(this.levelStorage.getDimensionPath(Level.OVERWORLD).resolve("data").toFile(), datafixer); ++ public WorldUpgrader(LevelStorageSource.LevelStorageAccess levelStoarge, DataFixer dataFixer, Registry dimensions, boolean eraseCache) { ++ this.dimensions = dimensions; ++ this.levels = (Set) java.util.stream.Stream.of(levelStoarge.dimensionType).map(Registries::levelStemToLevel).collect(Collectors.toUnmodifiableSet()); // CraftBukkit ++ this.eraseCache = eraseCache; ++ this.dataFixer = dataFixer; ++ this.levelStorage = levelStoarge; ++ this.overworldDataStorage = new DimensionDataStorage(this.levelStorage.getDimensionPath(Level.OVERWORLD).resolve("data").toFile(), dataFixer); + this.thread = WorldUpgrader.THREAD_FACTORY.newThread(this::work); + this.thread.setUncaughtExceptionHandler((thread, throwable) -> { + WorldUpgrader.LOGGER.error("Error upgrading world", throwable); +@@ -133,48 +133,48 @@ + for (Iterator iterator2 = this.levels.iterator(); iterator2.hasNext(); f1 += f2) { + ResourceKey resourcekey2 = (ResourceKey) iterator2.next(); + ListIterator listiterator = (ListIterator) immutablemap.get(resourcekey2); +- ChunkStorage chunkstorage = (ChunkStorage) immutablemap1.get(resourcekey2); ++ ChunkStorage ichunkloader = (ChunkStorage) immutablemap1.get(resourcekey2); + + if (listiterator.hasNext()) { +- ChunkPos chunkpos = (ChunkPos) listiterator.next(); ++ ChunkPos chunkcoordintpair = (ChunkPos) listiterator.next(); + boolean flag1 = false; + + try { +- CompoundTag compoundtag = (CompoundTag) ((Optional) chunkstorage.read(chunkpos).join()).orElse((Object) null); ++ CompoundTag nbttagcompound = (CompoundTag) ((Optional) ichunkloader.read(chunkcoordintpair).join()).orElse((Object) null); + +- if (compoundtag != null) { +- int j = ChunkStorage.getVersion(compoundtag); ++ if (nbttagcompound != null) { ++ int j = ChunkStorage.getVersion(nbttagcompound); + ChunkGenerator chunkgenerator = ((LevelStem) this.dimensions.getOrThrow(Registries.levelToLevelStem(resourcekey2))).generator(); +- CompoundTag compoundtag1 = chunkstorage.upgradeChunkTag(resourcekey2, () -> { ++ CompoundTag nbttagcompound1 = ichunkloader.upgradeChunkTag(Registries.levelToLevelStem(resourcekey2), () -> { // CraftBukkit + return this.overworldDataStorage; +- }, compoundtag, chunkgenerator.getTypeNameForDataFixer()); +- ChunkPos chunkpos1 = new ChunkPos(compoundtag1.getInt("xPos"), compoundtag1.getInt("zPos")); ++ }, nbttagcompound, chunkgenerator.getTypeNameForDataFixer(), chunkcoordintpair, null); // CraftBukkit ++ ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); + +- if (!chunkpos1.equals(chunkpos)) { +- WorldUpgrader.LOGGER.warn("Chunk {} has invalid position {}", chunkpos, chunkpos1); ++ if (!chunkcoordintpair1.equals(chunkcoordintpair)) { ++ WorldUpgrader.LOGGER.warn("Chunk {} has invalid position {}", chunkcoordintpair, chunkcoordintpair1); + } + + boolean flag2 = j < SharedConstants.getCurrentVersion().getDataVersion().getVersion(); + + if (this.eraseCache) { +- flag2 = flag2 || compoundtag1.contains("Heightmaps"); +- compoundtag1.remove("Heightmaps"); +- flag2 = flag2 || compoundtag1.contains("isLightOn"); +- compoundtag1.remove("isLightOn"); +- ListTag listtag = compoundtag1.getList("sections", 10); ++ flag2 = flag2 || nbttagcompound1.contains("Heightmaps"); ++ nbttagcompound1.remove("Heightmaps"); ++ flag2 = flag2 || nbttagcompound1.contains("isLightOn"); ++ nbttagcompound1.remove("isLightOn"); ++ ListTag nbttaglist = nbttagcompound1.getList("sections", 10); + +- for (int k = 0; k < listtag.size(); ++k) { +- CompoundTag compoundtag2 = listtag.getCompound(k); ++ for (int k = 0; k < nbttaglist.size(); ++k) { ++ CompoundTag nbttagcompound2 = nbttaglist.getCompound(k); + +- flag2 = flag2 || compoundtag2.contains("BlockLight"); +- compoundtag2.remove("BlockLight"); +- flag2 = flag2 || compoundtag2.contains("SkyLight"); +- compoundtag2.remove("SkyLight"); ++ flag2 = flag2 || nbttagcompound2.contains("BlockLight"); ++ nbttagcompound2.remove("BlockLight"); ++ flag2 = flag2 || nbttagcompound2.contains("SkyLight"); ++ nbttagcompound2.remove("SkyLight"); + } + } + + if (flag2) { +- chunkstorage.write(chunkpos, compoundtag1); ++ ichunkloader.write(chunkcoordintpair, nbttagcompound1); + flag1 = true; + } + } +@@ -185,7 +185,7 @@ + throw reportedexception; + } + +- WorldUpgrader.LOGGER.error("Error upgrading chunk {}", chunkpos, throwable); ++ WorldUpgrader.LOGGER.error("Error upgrading chunk {}", chunkcoordintpair, throwable); + } + + if (flag1) { +@@ -211,10 +211,10 @@ + UnmodifiableIterator unmodifiableiterator = immutablemap1.values().iterator(); + + while (unmodifiableiterator.hasNext()) { +- ChunkStorage chunkstorage1 = (ChunkStorage) unmodifiableiterator.next(); ++ ChunkStorage ichunkloader1 = (ChunkStorage) unmodifiableiterator.next(); + + try { +- chunkstorage1.close(); ++ ichunkloader1.close(); + } catch (IOException ioexception) { + WorldUpgrader.LOGGER.error("Error upgrading chunk", ioexception); + } +@@ -227,8 +227,8 @@ + } + } + +- private List getAllChunkPos(ResourceKey resourcekey) { +- File file = this.levelStorage.getDimensionPath(resourcekey).toFile(); ++ private List getAllChunkPos(ResourceKey level) { ++ File file = this.levelStorage.getDimensionPath(level).toFile(); + File file1 = new File(file, "region"); + File[] afile = file1.listFiles((file2, s) -> { + return s.endsWith(".mca"); +@@ -255,10 +255,10 @@ + try { + for (int i1 = 0; i1 < 32; ++i1) { + for (int j1 = 0; j1 < 32; ++j1) { +- ChunkPos chunkpos = new ChunkPos(i1 + k, j1 + l); ++ ChunkPos chunkcoordintpair = new ChunkPos(i1 + k, j1 + l); + +- if (regionfile.doesChunkExist(chunkpos)) { +- list.add(chunkpos); ++ if (regionfile.doesChunkExist(chunkcoordintpair)) { ++ list.add(chunkcoordintpair); + } + } + } +@@ -291,8 +291,8 @@ + return this.levels; + } + +- public float dimensionProgress(ResourceKey resourcekey) { +- return this.progressMap.getFloat(resourcekey); ++ public float dimensionProgress(ResourceKey level) { ++ return this.progressMap.getFloat(level); + } + + public float getProgress() { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/CompoundContainer.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/CompoundContainer.java.patch new file mode 100644 index 0000000000..af3a93c2fd --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/CompoundContainer.java.patch @@ -0,0 +1,175 @@ +--- a/net/minecraft/world/CompoundContainer.java ++++ b/net/minecraft/world/CompoundContainer.java +@@ -3,102 +3,140 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import org.bukkit.Location; ++ ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class CompoundContainer implements Container { + +- private final Container container1; +- private final Container container2; ++ public final Container container1; ++ public final Container container2; + +- public CompoundContainer(Container container, Container container1) { +- this.container1 = container; +- this.container2 = container1; ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ ++ public List getContents() { ++ List result = new ArrayList(this.getContainerSize()); ++ for (int i = 0; i < this.getContainerSize(); i++) { ++ result.add(this.getItem(i)); ++ } ++ return result; + } + ++ public void onOpen(CraftHumanEntity who) { ++ this.container1.onOpen(who); ++ this.container2.onOpen(who); ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ this.container1.onClose(who); ++ this.container2.onClose(who); ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return null; // This method won't be called since CraftInventoryDoubleChest doesn't defer to here ++ } ++ ++ public void setMaxStackSize(int size) { ++ this.container1.setMaxStackSize(size); ++ this.container2.setMaxStackSize(size); ++ } ++ + @Override ++ public Location getLocation() { ++ return container1.getLocation(); // TODO: right? ++ } ++ // CraftBukkit end ++ ++ public CompoundContainer(Container container1, Container container2) { ++ this.container1 = container1; ++ this.container2 = container2; ++ } ++ + @Override + public int getContainerSize() { + return this.container1.getContainerSize() + this.container2.getContainerSize(); + } + + @Override +- @Override + public boolean isEmpty() { + return this.container1.isEmpty() && this.container2.isEmpty(); + } + +- public boolean contains(Container container) { +- return this.container1 == container || this.container2 == container; ++ public boolean contains(Container inventory) { ++ return this.container1 == inventory || this.container2 == inventory; + } + + @Override +- @Override +- public ItemStack getItem(int i) { +- return i >= this.container1.getContainerSize() ? this.container2.getItem(i - this.container1.getContainerSize()) : this.container1.getItem(i); ++ public ItemStack getItem(int index) { ++ return index >= this.container1.getContainerSize() ? this.container2.getItem(index - this.container1.getContainerSize()) : this.container1.getItem(index); + } + + @Override +- @Override +- public ItemStack removeItem(int i, int j) { +- return i >= this.container1.getContainerSize() ? this.container2.removeItem(i - this.container1.getContainerSize(), j) : this.container1.removeItem(i, j); ++ public ItemStack removeItem(int index, int count) { ++ return index >= this.container1.getContainerSize() ? this.container2.removeItem(index - this.container1.getContainerSize(), count) : this.container1.removeItem(index, count); + } + + @Override +- @Override +- public ItemStack removeItemNoUpdate(int i) { +- return i >= this.container1.getContainerSize() ? this.container2.removeItemNoUpdate(i - this.container1.getContainerSize()) : this.container1.removeItemNoUpdate(i); ++ public ItemStack removeItemNoUpdate(int index) { ++ return index >= this.container1.getContainerSize() ? this.container2.removeItemNoUpdate(index - this.container1.getContainerSize()) : this.container1.removeItemNoUpdate(index); + } + + @Override +- @Override +- public void setItem(int i, ItemStack itemstack) { +- if (i >= this.container1.getContainerSize()) { +- this.container2.setItem(i - this.container1.getContainerSize(), itemstack); ++ public void setItem(int index, ItemStack stack) { ++ if (index >= this.container1.getContainerSize()) { ++ this.container2.setItem(index - this.container1.getContainerSize(), stack); + } else { +- this.container1.setItem(i, itemstack); ++ this.container1.setItem(index, stack); + } + + } + + @Override +- @Override + public int getMaxStackSize() { +- return this.container1.getMaxStackSize(); ++ return Math.min(this.container1.getMaxStackSize(), this.container2.getMaxStackSize()); // CraftBukkit - check both sides + } + + @Override +- @Override + public void setChanged() { + this.container1.setChanged(); + this.container2.setChanged(); + } + + @Override +- @Override + public boolean stillValid(Player player) { + return this.container1.stillValid(player) && this.container2.stillValid(player); + } + + @Override +- @Override + public void startOpen(Player player) { + this.container1.startOpen(player); + this.container2.startOpen(player); + } + + @Override +- @Override + public void stopOpen(Player player) { + this.container1.stopOpen(player); + this.container2.stopOpen(player); + } + + @Override +- @Override +- public boolean canPlaceItem(int i, ItemStack itemstack) { +- return i >= this.container1.getContainerSize() ? this.container2.canPlaceItem(i - this.container1.getContainerSize(), itemstack) : this.container1.canPlaceItem(i, itemstack); ++ public boolean canPlaceItem(int index, ItemStack stack) { ++ return index >= this.container1.getContainerSize() ? this.container2.canPlaceItem(index - this.container1.getContainerSize(), stack) : this.container1.canPlaceItem(index, stack); + } + + @Override +- @Override + public void clearContent() { + this.container1.clearContent(); + this.container2.clearContent(); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/Container.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/Container.java.patch new file mode 100644 index 0000000000..9919e667b7 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/Container.java.patch @@ -0,0 +1,86 @@ +--- a/net/minecraft/world/Container.java ++++ b/net/minecraft/world/Container.java +@@ -6,8 +6,12 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; ++// CraftBukkit start ++import net.minecraft.world.item.crafting.RecipeHolder; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.BlockEntity; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++// CraftBukkit end + + public interface Container extends Clearable { + +@@ -26,9 +30,7 @@ + + void setItem(int slot, ItemStack stack); + +- default int getMaxStackSize() { +- return 64; +- } ++ int getMaxStackSize(); // CraftBukkit + + void setChanged(); + +@@ -38,11 +40,11 @@ + + default void stopOpen(Player player) {} + +- default boolean canPlaceItem(int i, ItemStack itemstack) { ++ default boolean canPlaceItem(int index, ItemStack stack) { + return true; + } + +- default boolean canTakeItem(Container container, int i, ItemStack itemstack) { ++ default boolean canTakeItem(Container target, int index, ItemStack stack) { + return true; + } + +@@ -78,14 +80,39 @@ + return false; + } + +- static boolean stillValidBlockEntity(BlockEntity blockentity, Player player) { +- return stillValidBlockEntity(blockentity, player, 8); ++ static boolean stillValidBlockEntity(BlockEntity blockEntity, Player player) { ++ return stillValidBlockEntity(blockEntity, player, 8); + } + +- static boolean stillValidBlockEntity(BlockEntity blockentity, Player player, int i) { +- Level level = blockentity.getLevel(); +- BlockPos blockpos = blockentity.getBlockPos(); ++ static boolean stillValidBlockEntity(BlockEntity blockEntity, Player player, int maxDistance) { ++ Level world = blockEntity.getLevel(); ++ BlockPos blockposition = blockEntity.getBlockPos(); + +- return level == null ? false : (level.getBlockEntity(blockpos) != blockentity ? false : player.distanceToSqr((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D) <= (double) (i * i)); ++ return world == null ? false : (world.getBlockEntity(blockposition) != blockEntity ? false : player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) <= (double) (maxDistance * maxDistance)); + } ++ ++ // CraftBukkit start ++ java.util.List getContents(); ++ ++ void onOpen(CraftHumanEntity who); ++ ++ void onClose(CraftHumanEntity who); ++ ++ java.util.List getViewers(); ++ ++ org.bukkit.inventory.InventoryHolder getOwner(); ++ ++ void setMaxStackSize(int size); ++ ++ org.bukkit.Location getLocation(); ++ ++ default RecipeHolder getCurrentRecipe() { ++ return null; ++ } ++ ++ default void setCurrentRecipe(RecipeHolder recipe) { ++ } ++ ++ int MAX_STACK = 64; ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/LockCode.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/LockCode.java.patch new file mode 100644 index 0000000000..17b2d74885 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/LockCode.java.patch @@ -0,0 +1,58 @@ +--- a/net/minecraft/world/LockCode.java ++++ b/net/minecraft/world/LockCode.java +@@ -4,29 +4,46 @@ + import net.minecraft.nbt.CompoundTag; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.ChatColor; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++// CraftBukkit end ++ + @Immutable + public class LockCode { + + public static final LockCode NO_LOCK = new LockCode(""); + public static final String TAG_LOCK = "Lock"; +- private final String key; ++ public final String key; + +- public LockCode(String s) { +- this.key = s; ++ public LockCode(String key) { ++ this.key = key; + } + +- public boolean unlocksWith(ItemStack itemstack) { +- return this.key.isEmpty() || !itemstack.isEmpty() && itemstack.hasCustomHoverName() && this.key.equals(itemstack.getHoverName().getString()); ++ public boolean unlocksWith(ItemStack stack) { ++ // CraftBukkit start - SPIGOT-6307: Check for color codes if the lock contains color codes ++ if (this.key.isEmpty()) return true; ++ if (!stack.isEmpty() && stack.hasCustomHoverName()) { ++ if (this.key.indexOf(ChatColor.COLOR_CHAR) == -1) { ++ // The lock key contains no color codes, so let's ignore colors in the item display name (vanilla Minecraft behavior): ++ return this.key.equals(stack.getHoverName().getString()); ++ } else { ++ // The lock key contains color codes, so let's take them into account: ++ return this.key.equals(CraftChatMessage.fromComponent(stack.getHoverName())); ++ } ++ } ++ return false; ++ // CraftBukkit end + } + +- public void addToTag(CompoundTag compoundtag) { ++ public void addToTag(CompoundTag nbt) { + if (!this.key.isEmpty()) { +- compoundtag.putString("Lock", this.key); ++ nbt.putString("Lock", this.key); + } + + } + +- public static LockCode fromTag(CompoundTag compoundtag) { +- return compoundtag.contains("Lock", 8) ? new LockCode(compoundtag.getString("Lock")) : LockCode.NO_LOCK; ++ public static LockCode fromTag(CompoundTag nbt) { ++ return nbt.contains("Lock", 8) ? new LockCode(nbt.getString("Lock")) : LockCode.NO_LOCK; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/SimpleContainer.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/SimpleContainer.java.patch new file mode 100644 index 0000000000..5b0227ad71 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/SimpleContainer.java.patch @@ -0,0 +1,361 @@ +--- a/net/minecraft/world/SimpleContainer.java ++++ b/net/minecraft/world/SimpleContainer.java +@@ -14,42 +14,99 @@ + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class SimpleContainer implements Container, StackedContentsCompatible { + + private final int size; +- private final NonNullList items; ++ public final NonNullList items; + @Nullable + private List listeners; + +- public SimpleContainer(int i) { ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ protected org.bukkit.inventory.InventoryHolder bukkitOwner; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return bukkitOwner; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return null; ++ } ++ ++ public SimpleContainer(SimpleContainer original) { ++ this(original.size); ++ for (int slot = 0; slot < original.size; slot++) { ++ this.items.set(slot, original.items.get(slot).copy()); ++ } ++ } ++ ++ public SimpleContainer(int size) { ++ this(size, null); ++ } ++ ++ public SimpleContainer(int i, org.bukkit.inventory.InventoryHolder owner) { ++ this.bukkitOwner = owner; ++ // CraftBukkit end + this.size = i; + this.items = NonNullList.withSize(i, ItemStack.EMPTY); + } + +- public SimpleContainer(ItemStack... aitemstack) { +- this.size = aitemstack.length; +- this.items = NonNullList.of(ItemStack.EMPTY, aitemstack); ++ public SimpleContainer(ItemStack... items) { ++ this.size = items.length; ++ this.items = NonNullList.of(ItemStack.EMPTY, items); + } + +- public void addListener(ContainerListener containerlistener) { ++ public void addListener(ContainerListener listener) { + if (this.listeners == null) { + this.listeners = Lists.newArrayList(); + } + +- this.listeners.add(containerlistener); ++ this.listeners.add(listener); + } + +- public void removeListener(ContainerListener containerlistener) { ++ public void removeListener(ContainerListener listener) { + if (this.listeners != null) { +- this.listeners.remove(containerlistener); ++ this.listeners.remove(listener); + } + + } + + @Override +- @Override +- public ItemStack getItem(int i) { +- return i >= 0 && i < this.items.size() ? (ItemStack) this.items.get(i) : ItemStack.EMPTY; ++ public ItemStack getItem(int index) { ++ return index >= 0 && index < this.items.size() ? (ItemStack) this.items.get(index) : ItemStack.EMPTY; + } + + public List removeAllItems() { +@@ -62,9 +119,8 @@ + } + + @Override +- @Override +- public ItemStack removeItem(int i, int j) { +- ItemStack itemstack = ContainerHelper.removeItem(this.items, i, j); ++ public ItemStack removeItem(int index, int count) { ++ ItemStack itemstack = ContainerHelper.removeItem(this.items, index, count); + + if (!itemstack.isEmpty()) { + this.setChanged(); +@@ -73,18 +129,18 @@ + return itemstack; + } + +- public ItemStack removeItemType(Item item, int i) { ++ public ItemStack removeItemType(Item item, int amount) { + ItemStack itemstack = new ItemStack(item, 0); + + for (int j = this.size - 1; j >= 0; --j) { + ItemStack itemstack1 = this.getItem(j); + + if (itemstack1.getItem().equals(item)) { +- int k = i - itemstack.getCount(); ++ int k = amount - itemstack.getCount(); + ItemStack itemstack2 = itemstack1.split(k); + + itemstack.grow(itemstack2.getCount()); +- if (itemstack.getCount() == i) { ++ if (itemstack.getCount() == amount) { + break; + } + } +@@ -97,11 +153,11 @@ + return itemstack; + } + +- public ItemStack addItem(ItemStack itemstack) { +- if (itemstack.isEmpty()) { ++ public ItemStack addItem(ItemStack stack) { ++ if (stack.isEmpty()) { + return ItemStack.EMPTY; + } else { +- ItemStack itemstack1 = itemstack.copy(); ++ ItemStack itemstack1 = stack.copy(); + + this.moveItemToOccupiedSlotsWithSameType(itemstack1); + if (itemstack1.isEmpty()) { +@@ -113,14 +169,14 @@ + } + } + +- public boolean canAddItem(ItemStack itemstack) { ++ public boolean canAddItem(ItemStack stack) { + boolean flag = false; + Iterator iterator = this.items.iterator(); + + while (iterator.hasNext()) { + ItemStack itemstack1 = (ItemStack) iterator.next(); + +- if (itemstack1.isEmpty() || ItemStack.isSameItemSameTags(itemstack1, itemstack) && itemstack1.getCount() < itemstack1.getMaxStackSize()) { ++ if (itemstack1.isEmpty() || ItemStack.isSameItemSameTags(itemstack1, stack) && itemstack1.getCount() < itemstack1.getMaxStackSize()) { + flag = true; + break; + } +@@ -130,37 +186,33 @@ + } + + @Override +- @Override +- public ItemStack removeItemNoUpdate(int i) { +- ItemStack itemstack = (ItemStack) this.items.get(i); ++ public ItemStack removeItemNoUpdate(int index) { ++ ItemStack itemstack = (ItemStack) this.items.get(index); + + if (itemstack.isEmpty()) { + return ItemStack.EMPTY; + } else { +- this.items.set(i, ItemStack.EMPTY); ++ this.items.set(index, ItemStack.EMPTY); + return itemstack; + } + } + + @Override +- @Override +- public void setItem(int i, ItemStack itemstack) { +- this.items.set(i, itemstack); +- if (!itemstack.isEmpty() && itemstack.getCount() > this.getMaxStackSize()) { +- itemstack.setCount(this.getMaxStackSize()); ++ public void setItem(int index, ItemStack stack) { ++ this.items.set(index, stack); ++ if (!stack.isEmpty() && stack.getCount() > this.getMaxStackSize()) { ++ stack.setCount(this.getMaxStackSize()); + } + + this.setChanged(); + } + + @Override +- @Override + public int getContainerSize() { + return this.size; + } + + @Override +- @Override + public boolean isEmpty() { + Iterator iterator = this.items.iterator(); + +@@ -178,72 +230,67 @@ + } + + @Override +- @Override + public void setChanged() { + if (this.listeners != null) { + Iterator iterator = this.listeners.iterator(); + + while (iterator.hasNext()) { +- ContainerListener containerlistener = (ContainerListener) iterator.next(); ++ ContainerListener iinventorylistener = (ContainerListener) iterator.next(); + +- containerlistener.containerChanged(this); ++ iinventorylistener.containerChanged(this); + } + } + + } + + @Override +- @Override + public boolean stillValid(Player player) { + return true; + } + + @Override +- @Override + public void clearContent() { + this.items.clear(); + this.setChanged(); + } + + @Override +- @Override +- public void fillStackedContents(StackedContents stackedcontents) { ++ public void fillStackedContents(StackedContents helper) { + Iterator iterator = this.items.iterator(); + + while (iterator.hasNext()) { + ItemStack itemstack = (ItemStack) iterator.next(); + +- stackedcontents.accountStack(itemstack); ++ helper.accountStack(itemstack); + } + + } + +- @Override + public String toString() { + return ((List) this.items.stream().filter((itemstack) -> { + return !itemstack.isEmpty(); + }).collect(Collectors.toList())).toString(); + } + +- private void moveItemToEmptySlots(ItemStack itemstack) { ++ private void moveItemToEmptySlots(ItemStack stack) { + for (int i = 0; i < this.size; ++i) { + ItemStack itemstack1 = this.getItem(i); + + if (itemstack1.isEmpty()) { +- this.setItem(i, itemstack.copyAndClear()); ++ this.setItem(i, stack.copyAndClear()); + return; + } + } + + } + +- private void moveItemToOccupiedSlotsWithSameType(ItemStack itemstack) { ++ private void moveItemToOccupiedSlotsWithSameType(ItemStack stack) { + for (int i = 0; i < this.size; ++i) { + ItemStack itemstack1 = this.getItem(i); + +- if (ItemStack.isSameItemSameTags(itemstack1, itemstack)) { +- this.moveItemsBetweenStacks(itemstack, itemstack1); +- if (itemstack.isEmpty()) { ++ if (ItemStack.isSameItemSameTags(itemstack1, stack)) { ++ this.moveItemsBetweenStacks(stack, itemstack1); ++ if (stack.isEmpty()) { + return; + } + } +@@ -251,23 +298,23 @@ + + } + +- private void moveItemsBetweenStacks(ItemStack itemstack, ItemStack itemstack1) { +- int i = Math.min(this.getMaxStackSize(), itemstack1.getMaxStackSize()); +- int j = Math.min(itemstack.getCount(), i - itemstack1.getCount()); ++ private void moveItemsBetweenStacks(ItemStack stack, ItemStack other) { ++ int i = Math.min(this.getMaxStackSize(), other.getMaxStackSize()); ++ int j = Math.min(stack.getCount(), i - other.getCount()); + + if (j > 0) { +- itemstack1.grow(j); +- itemstack.shrink(j); ++ other.grow(j); ++ stack.shrink(j); + this.setChanged(); + } + + } + +- public void fromTag(ListTag listtag) { ++ public void fromTag(ListTag containerNbt) { + this.clearContent(); + +- for (int i = 0; i < listtag.size(); ++i) { +- ItemStack itemstack = ItemStack.of(listtag.getCompound(i)); ++ for (int i = 0; i < containerNbt.size(); ++i) { ++ ItemStack itemstack = ItemStack.of(containerNbt.getCompound(i)); + + if (!itemstack.isEmpty()) { + this.addItem(itemstack); +@@ -277,17 +324,17 @@ + } + + public ListTag createTag() { +- ListTag listtag = new ListTag(); ++ ListTag nbttaglist = new ListTag(); + + for (int i = 0; i < this.getContainerSize(); ++i) { + ItemStack itemstack = this.getItem(i); + + if (!itemstack.isEmpty()) { +- listtag.add(itemstack.save(new CompoundTag())); ++ nbttaglist.add(itemstack.save(new CompoundTag())); + } + } + +- return listtag; ++ return nbttaglist; + } + + public NonNullList getItems() { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/damagesource/DamageSource.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/damagesource/DamageSource.java.patch new file mode 100644 index 0000000000..13387c1b1c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/damagesource/DamageSource.java.patch @@ -0,0 +1,151 @@ +--- a/net/minecraft/world/damagesource/DamageSource.java ++++ b/net/minecraft/world/damagesource/DamageSource.java +@@ -20,8 +20,39 @@ + private final Entity directEntity; + @Nullable + private final Vec3 damageSourcePosition; ++ // CraftBukkit start ++ private boolean sweep; ++ private boolean melting; ++ private boolean poison; + +- @Override ++ public boolean isSweep() { ++ return sweep; ++ } ++ ++ public DamageSource sweep() { ++ this.sweep = true; ++ return this; ++ } ++ ++ public boolean isMelting() { ++ return melting; ++ } ++ ++ public DamageSource melting() { ++ this.melting = true; ++ return this; ++ } ++ ++ public boolean isPoison() { ++ return poison; ++ } ++ ++ public DamageSource poison() { ++ this.poison = true; ++ return this; ++ } ++ // CraftBukkit end ++ + public String toString() { + return "DamageSource (" + this.type().msgId() + ")"; + } +@@ -34,27 +65,27 @@ + return this.causingEntity != this.directEntity; + } + +- private DamageSource(Holder holder, @Nullable Entity entity, @Nullable Entity entity1, @Nullable Vec3 vec3) { +- this.type = holder; +- this.causingEntity = entity1; +- this.directEntity = entity; +- this.damageSourcePosition = vec3; ++ private DamageSource(Holder type, @Nullable Entity directEntity, @Nullable Entity causingEntity, @Nullable Vec3 damageSourcePosition) { ++ this.type = type; ++ this.causingEntity = causingEntity; ++ this.directEntity = directEntity; ++ this.damageSourcePosition = damageSourcePosition; + } + +- public DamageSource(Holder holder, @Nullable Entity entity, @Nullable Entity entity1) { +- this(holder, entity, entity1, (Vec3) null); ++ public DamageSource(Holder type, @Nullable Entity directEntity, @Nullable Entity causingEntity) { ++ this(type, directEntity, causingEntity, (Vec3) null); + } + +- public DamageSource(Holder holder, Vec3 vec3) { +- this(holder, (Entity) null, (Entity) null, vec3); ++ public DamageSource(Holder type, Vec3 damageSourcePosition) { ++ this(type, (Entity) null, (Entity) null, damageSourcePosition); + } + +- public DamageSource(Holder holder, @Nullable Entity entity) { +- this(holder, entity, entity); ++ public DamageSource(Holder type, @Nullable Entity entity) { ++ this(type, entity, entity); + } + +- public DamageSource(Holder holder) { +- this(holder, (Entity) null, (Entity) null, (Vec3) null); ++ public DamageSource(Holder type) { ++ this(type, (Entity) null, (Entity) null, (Vec3) null); + } + + @Nullable +@@ -67,30 +98,30 @@ + return this.causingEntity; + } + +- public Component getLocalizedDeathMessage(LivingEntity livingentity) { ++ public Component getLocalizedDeathMessage(LivingEntity livingEntity) { + String s = "death.attack." + this.type().msgId(); + + if (this.causingEntity == null && this.directEntity == null) { +- LivingEntity livingentity1 = livingentity.getKillCredit(); ++ LivingEntity entityliving1 = livingEntity.getKillCredit(); + String s1 = s + ".player"; + +- return livingentity1 != null ? Component.translatable(s1, livingentity.getDisplayName(), livingentity1.getDisplayName()) : Component.translatable(s, livingentity.getDisplayName()); ++ return entityliving1 != null ? Component.translatable(s1, livingEntity.getDisplayName(), entityliving1.getDisplayName()) : Component.translatable(s, livingEntity.getDisplayName()); + } else { +- Component component = this.causingEntity == null ? this.directEntity.getDisplayName() : this.causingEntity.getDisplayName(); ++ Component ichatbasecomponent = this.causingEntity == null ? this.directEntity.getDisplayName() : this.causingEntity.getDisplayName(); + Entity entity = this.causingEntity; + ItemStack itemstack; + + if (entity instanceof LivingEntity) { +- LivingEntity livingentity2 = (LivingEntity) entity; ++ LivingEntity entityliving2 = (LivingEntity) entity; + +- itemstack = livingentity2.getMainHandItem(); ++ itemstack = entityliving2.getMainHandItem(); + } else { + itemstack = ItemStack.EMPTY; + } + + ItemStack itemstack1 = itemstack; + +- return !itemstack1.isEmpty() && itemstack1.hasCustomHoverName() ? Component.translatable(s + ".item", livingentity.getDisplayName(), component, itemstack1.getDisplayName()) : Component.translatable(s, livingentity.getDisplayName(), component); ++ return !itemstack1.isEmpty() && itemstack1.hasCustomHoverName() ? Component.translatable(s + ".item", livingEntity.getDisplayName(), ichatbasecomponent, itemstack1.getDisplayName()) : Component.translatable(s, livingEntity.getDisplayName(), ichatbasecomponent); + } + } + +@@ -123,9 +154,9 @@ + boolean flag; + + if (entity instanceof Player) { +- Player player = (Player) entity; ++ Player entityhuman = (Player) entity; + +- if (player.getAbilities().instabuild) { ++ if (entityhuman.getAbilities().instabuild) { + flag = true; + return flag; + } +@@ -145,12 +176,12 @@ + return this.damageSourcePosition; + } + +- public boolean is(TagKey tagkey) { +- return this.type.is(tagkey); ++ public boolean is(TagKey damageTypeKey) { ++ return this.type.is(damageTypeKey); + } + +- public boolean is(ResourceKey resourcekey) { +- return this.type.is(resourcekey); ++ public boolean is(ResourceKey damageTypeKey) { ++ return this.type.is(damageTypeKey); + } + + public DamageType type() { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/damagesource/DamageSources.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/damagesource/DamageSources.java.patch new file mode 100644 index 0000000000..083f16ce4a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/damagesource/DamageSources.java.patch @@ -0,0 +1,139 @@ +--- a/net/minecraft/world/damagesource/DamageSources.java ++++ b/net/minecraft/world/damagesource/DamageSources.java +@@ -41,9 +41,15 @@ + private final DamageSource stalagmite; + private final DamageSource outsideBorder; + private final DamageSource genericKill; ++ // CraftBukkit start ++ public final DamageSource melting; ++ public final DamageSource poison; + +- public DamageSources(RegistryAccess registryaccess) { +- this.damageTypes = registryaccess.registryOrThrow(Registries.DAMAGE_TYPE); ++ public DamageSources(RegistryAccess registry) { ++ this.damageTypes = registry.registryOrThrow(Registries.DAMAGE_TYPE); ++ this.melting = this.source(DamageTypes.ON_FIRE).melting(); ++ this.poison = this.source(DamageTypes.MAGIC).poison(); ++ // CraftBukkit end + this.inFire = this.source(DamageTypes.IN_FIRE); + this.lightningBolt = this.source(DamageTypes.LIGHTNING_BOLT); + this.onFire = this.source(DamageTypes.ON_FIRE); +@@ -69,16 +75,16 @@ + this.genericKill = this.source(DamageTypes.GENERIC_KILL); + } + +- private DamageSource source(ResourceKey resourcekey) { +- return new DamageSource(this.damageTypes.getHolderOrThrow(resourcekey)); ++ private DamageSource source(ResourceKey damageTypeKey) { ++ return new DamageSource(this.damageTypes.getHolderOrThrow(damageTypeKey)); + } + +- private DamageSource source(ResourceKey resourcekey, @Nullable Entity entity) { +- return new DamageSource(this.damageTypes.getHolderOrThrow(resourcekey), entity); ++ private DamageSource source(ResourceKey damageTypeKey, @Nullable Entity entity) { ++ return new DamageSource(this.damageTypes.getHolderOrThrow(damageTypeKey), entity); + } + +- private DamageSource source(ResourceKey resourcekey, @Nullable Entity entity, @Nullable Entity entity1) { +- return new DamageSource(this.damageTypes.getHolderOrThrow(resourcekey), entity, entity1); ++ private DamageSource source(ResourceKey damageTypeKey, @Nullable Entity causingEntity, @Nullable Entity directEntity) { ++ return new DamageSource(this.damageTypes.getHolderOrThrow(damageTypeKey), causingEntity, directEntity); + } + + public DamageSource inFire() { +@@ -177,52 +183,52 @@ + return this.source(DamageTypes.FALLING_STALACTITE, entity); + } + +- public DamageSource sting(LivingEntity livingentity) { +- return this.source(DamageTypes.STING, livingentity); ++ public DamageSource sting(LivingEntity entity) { ++ return this.source(DamageTypes.STING, entity); + } + +- public DamageSource mobAttack(LivingEntity livingentity) { +- return this.source(DamageTypes.MOB_ATTACK, livingentity); ++ public DamageSource mobAttack(LivingEntity mob) { ++ return this.source(DamageTypes.MOB_ATTACK, mob); + } + +- public DamageSource noAggroMobAttack(LivingEntity livingentity) { +- return this.source(DamageTypes.MOB_ATTACK_NO_AGGRO, livingentity); ++ public DamageSource noAggroMobAttack(LivingEntity mob) { ++ return this.source(DamageTypes.MOB_ATTACK_NO_AGGRO, mob); + } + + public DamageSource playerAttack(Player player) { + return this.source(DamageTypes.PLAYER_ATTACK, player); + } + +- public DamageSource arrow(AbstractArrow abstractarrow, @Nullable Entity entity) { +- return this.source(DamageTypes.ARROW, abstractarrow, entity); ++ public DamageSource arrow(AbstractArrow arrow, @Nullable Entity shooter) { ++ return this.source(DamageTypes.ARROW, arrow, shooter); + } + +- public DamageSource trident(Entity entity, @Nullable Entity entity1) { +- return this.source(DamageTypes.TRIDENT, entity, entity1); ++ public DamageSource trident(Entity trident, @Nullable Entity thrower) { ++ return this.source(DamageTypes.TRIDENT, trident, thrower); + } + +- public DamageSource mobProjectile(Entity entity, @Nullable LivingEntity livingentity) { +- return this.source(DamageTypes.MOB_PROJECTILE, entity, livingentity); ++ public DamageSource mobProjectile(Entity projectile, @Nullable LivingEntity thrower) { ++ return this.source(DamageTypes.MOB_PROJECTILE, projectile, thrower); + } + +- public DamageSource fireworks(FireworkRocketEntity fireworkrocketentity, @Nullable Entity entity) { +- return this.source(DamageTypes.FIREWORKS, fireworkrocketentity, entity); ++ public DamageSource fireworks(FireworkRocketEntity firework, @Nullable Entity shooter) { ++ return this.source(DamageTypes.FIREWORKS, firework, shooter); + } + +- public DamageSource fireball(Fireball fireball, @Nullable Entity entity) { +- return entity == null ? this.source(DamageTypes.UNATTRIBUTED_FIREBALL, fireball) : this.source(DamageTypes.FIREBALL, fireball, entity); ++ public DamageSource fireball(Fireball fireball, @Nullable Entity thrower) { ++ return thrower == null ? this.source(DamageTypes.UNATTRIBUTED_FIREBALL, fireball) : this.source(DamageTypes.FIREBALL, fireball, thrower); + } + +- public DamageSource witherSkull(WitherSkull witherskull, Entity entity) { +- return this.source(DamageTypes.WITHER_SKULL, witherskull, entity); ++ public DamageSource witherSkull(WitherSkull witherSkull, Entity shooter) { ++ return this.source(DamageTypes.WITHER_SKULL, witherSkull, shooter); + } + +- public DamageSource thrown(Entity entity, @Nullable Entity entity1) { +- return this.source(DamageTypes.THROWN, entity, entity1); ++ public DamageSource thrown(Entity causingEntity, @Nullable Entity directEntity) { ++ return this.source(DamageTypes.THROWN, causingEntity, directEntity); + } + +- public DamageSource indirectMagic(Entity entity, @Nullable Entity entity1) { +- return this.source(DamageTypes.INDIRECT_MAGIC, entity, entity1); ++ public DamageSource indirectMagic(Entity causingEntity, @Nullable Entity directEntity) { ++ return this.source(DamageTypes.INDIRECT_MAGIC, causingEntity, directEntity); + } + + public DamageSource thorns(Entity entity) { +@@ -233,16 +239,16 @@ + return explosion != null ? this.explosion(explosion.getDirectSourceEntity(), explosion.getIndirectSourceEntity()) : this.explosion((Entity) null, (Entity) null); + } + +- public DamageSource explosion(@Nullable Entity entity, @Nullable Entity entity1) { +- return this.source(entity1 != null && entity != null ? DamageTypes.PLAYER_EXPLOSION : DamageTypes.EXPLOSION, entity, entity1); ++ public DamageSource explosion(@Nullable Entity causingEntity, @Nullable Entity directEntity) { ++ return this.source(directEntity != null && causingEntity != null ? DamageTypes.PLAYER_EXPLOSION : DamageTypes.EXPLOSION, causingEntity, directEntity); + } + + public DamageSource sonicBoom(Entity entity) { + return this.source(DamageTypes.SONIC_BOOM, entity); + } + +- public DamageSource badRespawnPointExplosion(Vec3 vec3) { +- return new DamageSource(this.damageTypes.getHolderOrThrow(DamageTypes.BAD_RESPAWN_POINT), vec3); ++ public DamageSource badRespawnPointExplosion(Vec3 position) { ++ return new DamageSource(this.damageTypes.getHolderOrThrow(DamageTypes.BAD_RESPAWN_POINT), position); + } + + public DamageSource outOfBorder() { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/effect/HealOrHarmMobEffect.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/effect/HealOrHarmMobEffect.java.patch new file mode 100644 index 0000000000..7ca073964d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/effect/HealOrHarmMobEffect.java.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/effect/HealOrHarmMobEffect.java ++++ b/net/minecraft/world/effect/HealOrHarmMobEffect.java +@@ -8,37 +8,35 @@ + + private final boolean isHarm; + +- public HealOrHarmMobEffect(MobEffectCategory mobeffectcategory, int i, boolean flag) { +- super(mobeffectcategory, i); ++ public HealOrHarmMobEffect(MobEffectCategory mobeffectinfo, int i, boolean flag) { ++ super(mobeffectinfo, i); + this.isHarm = flag; + } + + @Override +- @Override +- public void applyEffectTick(LivingEntity livingentity, int i) { +- super.applyEffectTick(livingentity, i); +- if (this.isHarm == livingentity.isInvertedHealAndHarm()) { +- livingentity.heal((float) Math.max(4 << i, 0)); ++ public void applyEffectTick(LivingEntity livingEntity, int amplifier) { ++ super.applyEffectTick(livingEntity, amplifier); ++ if (this.isHarm == livingEntity.isInvertedHealAndHarm()) { ++ livingEntity.heal((float) Math.max(4 << amplifier, 0), org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.MAGIC); // CraftBukkit + } else { +- livingentity.hurt(livingentity.damageSources().magic(), (float) (6 << i)); ++ livingEntity.hurt(livingEntity.damageSources().magic(), (float) (6 << amplifier)); + } + + } + + @Override +- @Override +- public void applyInstantenousEffect(@Nullable Entity entity, @Nullable Entity entity1, LivingEntity livingentity, int i, double d0) { ++ public void applyInstantenousEffect(@Nullable Entity source, @Nullable Entity indirectSource, LivingEntity livingEntity, int amplifier, double health) { + int j; + +- if (this.isHarm == livingentity.isInvertedHealAndHarm()) { +- j = (int) (d0 * (double) (4 << i) + 0.5D); +- livingentity.heal((float) j); ++ if (this.isHarm == livingEntity.isInvertedHealAndHarm()) { ++ j = (int) (health * (double) (4 << amplifier) + 0.5D); ++ livingEntity.heal((float) j, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.MAGIC); // CraftBukkit + } else { +- j = (int) (d0 * (double) (6 << i) + 0.5D); +- if (entity == null) { +- livingentity.hurt(livingentity.damageSources().magic(), (float) j); ++ j = (int) (health * (double) (6 << amplifier) + 0.5D); ++ if (source == null) { ++ livingEntity.hurt(livingEntity.damageSources().magic(), (float) j); + } else { +- livingentity.hurt(livingentity.damageSources().indirectMagic(entity, entity1), (float) j); ++ livingEntity.hurt(livingEntity.damageSources().indirectMagic(source, indirectSource), (float) j); + } + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/effect/HungerMobEffect.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/effect/HungerMobEffect.java.patch new file mode 100644 index 0000000000..8966bea205 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/effect/HungerMobEffect.java.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/effect/HungerMobEffect.java ++++ b/net/minecraft/world/effect/HungerMobEffect.java +@@ -5,24 +5,22 @@ + + class HungerMobEffect extends MobEffect { + +- protected HungerMobEffect(MobEffectCategory mobeffectcategory, int i) { +- super(mobeffectcategory, i); ++ protected HungerMobEffect(MobEffectCategory category, int color) { ++ super(category, color); + } + + @Override +- @Override +- public void applyEffectTick(LivingEntity livingentity, int i) { +- super.applyEffectTick(livingentity, i); +- if (livingentity instanceof Player) { +- Player player = (Player) livingentity; ++ public void applyEffectTick(LivingEntity livingEntity, int amplifier) { ++ super.applyEffectTick(livingEntity, amplifier); ++ if (livingEntity instanceof Player) { ++ Player entityhuman = (Player) livingEntity; + +- player.causeFoodExhaustion(0.005F * (float) (i + 1)); ++ entityhuman.causeFoodExhaustion(0.005F * (float) (amplifier + 1), org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.HUNGER_EFFECT); // CraftBukkit - EntityExhaustionEvent + } + + } + + @Override +- @Override + public boolean shouldApplyEffectTickThisTick(int i, int j) { + return true; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/effect/MobEffectUtil.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/effect/MobEffectUtil.java.patch new file mode 100644 index 0000000000..cb9791d6f1 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/effect/MobEffectUtil.java.patch @@ -0,0 +1,74 @@ +--- a/net/minecraft/world/effect/MobEffectUtil.java ++++ b/net/minecraft/world/effect/MobEffectUtil.java +@@ -15,47 +15,53 @@ + + public MobEffectUtil() {} + +- public static Component formatDuration(MobEffectInstance mobeffectinstance, float f, float f1) { +- if (mobeffectinstance.isInfiniteDuration()) { ++ public static Component formatDuration(MobEffectInstance mobeffect, float f, float f1) { ++ if (mobeffect.isInfiniteDuration()) { + return Component.translatable("effect.duration.infinite"); + } else { +- int i = Mth.floor((float) mobeffectinstance.getDuration() * f); ++ int i = Mth.floor((float) mobeffect.getDuration() * f); + + return Component.literal(StringUtil.formatTickDuration(i, f1)); + } + } + +- public static boolean hasDigSpeed(LivingEntity livingentity) { +- return livingentity.hasEffect(MobEffects.DIG_SPEED) || livingentity.hasEffect(MobEffects.CONDUIT_POWER); ++ public static boolean hasDigSpeed(LivingEntity entity) { ++ return entity.hasEffect(MobEffects.DIG_SPEED) || entity.hasEffect(MobEffects.CONDUIT_POWER); + } + +- public static int getDigSpeedAmplification(LivingEntity livingentity) { ++ public static int getDigSpeedAmplification(LivingEntity entity) { + int i = 0; + int j = 0; + +- if (livingentity.hasEffect(MobEffects.DIG_SPEED)) { +- i = livingentity.getEffect(MobEffects.DIG_SPEED).getAmplifier(); ++ if (entity.hasEffect(MobEffects.DIG_SPEED)) { ++ i = entity.getEffect(MobEffects.DIG_SPEED).getAmplifier(); + } + +- if (livingentity.hasEffect(MobEffects.CONDUIT_POWER)) { +- j = livingentity.getEffect(MobEffects.CONDUIT_POWER).getAmplifier(); ++ if (entity.hasEffect(MobEffects.CONDUIT_POWER)) { ++ j = entity.getEffect(MobEffects.CONDUIT_POWER).getAmplifier(); + } + + return Math.max(i, j); + } + +- public static boolean hasWaterBreathing(LivingEntity livingentity) { +- return livingentity.hasEffect(MobEffects.WATER_BREATHING) || livingentity.hasEffect(MobEffects.CONDUIT_POWER); ++ public static boolean hasWaterBreathing(LivingEntity entity) { ++ return entity.hasEffect(MobEffects.WATER_BREATHING) || entity.hasEffect(MobEffects.CONDUIT_POWER); + } + +- public static List addEffectToPlayersAround(ServerLevel serverlevel, @Nullable Entity entity, Vec3 vec3, double d0, MobEffectInstance mobeffectinstance, int i) { +- MobEffect mobeffect = mobeffectinstance.getEffect(); +- List list = serverlevel.getPlayers((serverplayer) -> { +- return serverplayer.gameMode.isSurvival() && (entity == null || !entity.isAlliedTo((Entity) serverplayer)) && vec3.closerThan(serverplayer.position(), d0) && (!serverplayer.hasEffect(mobeffect) || serverplayer.getEffect(mobeffect).getAmplifier() < mobeffectinstance.getAmplifier() || serverplayer.getEffect(mobeffect).endsWithin(i - 1)); ++ public static List addEffectToPlayersAround(ServerLevel level, @Nullable Entity source, Vec3 pos, double radius, MobEffectInstance mobeffect, int effect) { ++ // CraftBukkit start ++ return addEffectToPlayersAround(level, source, pos, radius, mobeffect, effect, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public static List addEffectToPlayersAround(ServerLevel worldserver, @Nullable Entity entity, Vec3 vec3d, double d0, MobEffectInstance mobeffect, int i, org.bukkit.event.entity.EntityPotionEffectEvent.Cause cause) { ++ // CraftBukkit end ++ MobEffect mobeffectlist = mobeffect.getEffect(); ++ List list = worldserver.getPlayers((entityplayer) -> { ++ return entityplayer.gameMode.isSurvival() && (entity == null || !entity.isAlliedTo((Entity) entityplayer)) && vec3d.closerThan(entityplayer.position(), d0) && (!entityplayer.hasEffect(mobeffectlist) || entityplayer.getEffect(mobeffectlist).getAmplifier() < mobeffect.getAmplifier() || entityplayer.getEffect(mobeffectlist).endsWithin(i - 1)); + }); + +- list.forEach((serverplayer) -> { +- serverplayer.addEffect(new MobEffectInstance(mobeffectinstance), entity); ++ list.forEach((entityplayer) -> { ++ entityplayer.addEffect(new MobEffectInstance(mobeffect), entity, cause); // CraftBukkit + }); + return list; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/effect/PoisonMobEffect.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/effect/PoisonMobEffect.java.patch new file mode 100644 index 0000000000..ef14fc65ec --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/effect/PoisonMobEffect.java.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/effect/PoisonMobEffect.java ++++ b/net/minecraft/world/effect/PoisonMobEffect.java +@@ -4,22 +4,20 @@ + + class PoisonMobEffect extends MobEffect { + +- protected PoisonMobEffect(MobEffectCategory mobeffectcategory, int i) { +- super(mobeffectcategory, i); ++ protected PoisonMobEffect(MobEffectCategory category, int color) { ++ super(category, color); + } + + @Override +- @Override +- public void applyEffectTick(LivingEntity livingentity, int i) { +- super.applyEffectTick(livingentity, i); +- if (livingentity.getHealth() > 1.0F) { +- livingentity.hurt(livingentity.damageSources().magic(), 1.0F); ++ public void applyEffectTick(LivingEntity livingEntity, int amplifier) { ++ super.applyEffectTick(livingEntity, amplifier); ++ if (livingEntity.getHealth() > 1.0F) { ++ livingEntity.hurt(livingEntity.damageSources().poison, 1.0F); // CraftBukkit - DamageSource.MAGIC -> CraftEventFactory.POISON + } + + } + + @Override +- @Override + public boolean shouldApplyEffectTickThisTick(int i, int j) { + int k = 25 >> j; + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/effect/RegenerationMobEffect.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/effect/RegenerationMobEffect.java.patch new file mode 100644 index 0000000000..d907f473e0 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/effect/RegenerationMobEffect.java.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/effect/RegenerationMobEffect.java ++++ b/net/minecraft/world/effect/RegenerationMobEffect.java +@@ -4,22 +4,20 @@ + + class RegenerationMobEffect extends MobEffect { + +- protected RegenerationMobEffect(MobEffectCategory mobeffectcategory, int i) { +- super(mobeffectcategory, i); ++ protected RegenerationMobEffect(MobEffectCategory category, int color) { ++ super(category, color); + } + + @Override +- @Override +- public void applyEffectTick(LivingEntity livingentity, int i) { +- super.applyEffectTick(livingentity, i); +- if (livingentity.getHealth() < livingentity.getMaxHealth()) { +- livingentity.heal(1.0F); ++ public void applyEffectTick(LivingEntity livingEntity, int amplifier) { ++ super.applyEffectTick(livingEntity, amplifier); ++ if (livingEntity.getHealth() < livingEntity.getMaxHealth()) { ++ livingEntity.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.MAGIC_REGEN); // CraftBukkit + } + + } + + @Override +- @Override + public boolean shouldApplyEffectTickThisTick(int i, int j) { + int k = 50 >> j; + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/effect/SaturationMobEffect.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/effect/SaturationMobEffect.java.patch new file mode 100644 index 0000000000..592eaabf01 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/effect/SaturationMobEffect.java.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/world/effect/SaturationMobEffect.java ++++ b/net/minecraft/world/effect/SaturationMobEffect.java +@@ -2,21 +2,32 @@ + + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.player.Player; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + class SaturationMobEffect extends InstantenousMobEffect { + +- protected SaturationMobEffect(MobEffectCategory mobeffectcategory, int i) { +- super(mobeffectcategory, i); ++ protected SaturationMobEffect(MobEffectCategory category, int color) { ++ super(category, color); + } + + @Override +- @Override +- public void applyEffectTick(LivingEntity livingentity, int i) { +- super.applyEffectTick(livingentity, i); +- if (!livingentity.level().isClientSide && livingentity instanceof Player) { +- Player player = (Player) livingentity; ++ public void applyEffectTick(LivingEntity livingEntity, int amplifier) { ++ super.applyEffectTick(livingEntity, amplifier); ++ if (!livingEntity.level().isClientSide && livingEntity instanceof Player) { ++ Player entityhuman = (Player) livingEntity; + +- player.getFoodData().eat(i + 1, 1.0F); ++ // CraftBukkit start ++ int oldFoodLevel = entityhuman.getFoodData().foodLevel; ++ org.bukkit.event.entity.FoodLevelChangeEvent event = CraftEventFactory.callFoodLevelChangeEvent(entityhuman, amplifier + 1 + oldFoodLevel); ++ if (!event.isCancelled()) { ++ entityhuman.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, 1.0F); ++ } ++ ++ ((CraftPlayer) entityhuman.getBukkitEntity()).sendHealthUpdate(); ++ // CraftBukkit end + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/AgeableMob.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/AgeableMob.java.patch new file mode 100644 index 0000000000..3dfd9f6366 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/AgeableMob.java.patch @@ -0,0 +1,205 @@ +--- a/net/minecraft/world/entity/AgeableMob.java ++++ b/net/minecraft/world/entity/AgeableMob.java +@@ -20,33 +20,32 @@ + protected int age; + protected int forcedAge; + protected int forcedAgeTimer; ++ public boolean ageLocked; // CraftBukkit + +- protected AgeableMob(EntityType entitytype, Level level) { +- super(entitytype, level); ++ protected AgeableMob(EntityType entityType, Level level) { ++ super(entityType, level); + } + + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- if (spawngroupdata == null) { +- spawngroupdata = new AgeableMob.AgeableMobGroupData(true); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ if (spawnData == null) { ++ spawnData = new AgeableMob.AgeableMobGroupData(true); + } + +- AgeableMob.AgeableMobGroupData ageablemob_ageablemobgroupdata = (AgeableMob.AgeableMobGroupData) spawngroupdata; ++ AgeableMob.AgeableMobGroupData entityageable_a = (AgeableMob.AgeableMobGroupData) spawnData; + +- if (ageablemob_ageablemobgroupdata.isShouldSpawnBaby() && ageablemob_ageablemobgroupdata.getGroupSize() > 0 && serverlevelaccessor.getRandom().nextFloat() <= ageablemob_ageablemobgroupdata.getBabySpawnChance()) { ++ if (entityageable_a.isShouldSpawnBaby() && entityageable_a.getGroupSize() > 0 && level.getRandom().nextFloat() <= entityageable_a.getBabySpawnChance()) { + this.setAge(-24000); + } + +- ageablemob_ageablemobgroupdata.increaseGroupSizeByOne(); +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, (SpawnGroupData) spawngroupdata, compoundtag); ++ entityageable_a.increaseGroupSizeByOne(); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + + @Nullable + public abstract AgeableMob getBreedOffspring(ServerLevel level, AgeableMob otherParent); + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(AgeableMob.DATA_BABY_ID, false); +@@ -60,11 +59,11 @@ + return this.level().isClientSide ? ((Boolean) this.entityData.get(AgeableMob.DATA_BABY_ID) ? -1 : 1) : this.age; + } + +- public void ageUp(int i, boolean flag) { ++ public void ageUp(int amount, boolean forced) { + int j = this.getAge(); + int k = j; + +- j += i * 20; ++ j += amount * 20; + if (j > 0) { + j = 0; + } +@@ -72,7 +71,7 @@ + int l = j - k; + + this.setAge(j); +- if (flag) { ++ if (forced) { + this.forcedAge += l; + if (this.forcedAgeTimer == 0) { + this.forcedAgeTimer = 40; +@@ -85,52 +84,50 @@ + + } + +- public void ageUp(int i) { +- this.ageUp(i, false); ++ public void ageUp(int amount) { ++ this.ageUp(amount, false); + } + +- public void setAge(int i) { ++ public void setAge(int age) { + int j = this.getAge(); + +- this.age = i; +- if (j < 0 && i >= 0 || j >= 0 && i < 0) { +- this.entityData.set(AgeableMob.DATA_BABY_ID, i < 0); ++ this.age = age; ++ if (j < 0 && age >= 0 || j >= 0 && age < 0) { ++ this.entityData.set(AgeableMob.DATA_BABY_ID, age < 0); + this.ageBoundaryReached(); + } + + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("Age", this.getAge()); +- compoundtag.putInt("ForcedAge", this.forcedAge); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("Age", this.getAge()); ++ compound.putInt("ForcedAge", this.forcedAge); ++ compound.putBoolean("AgeLocked", this.ageLocked); // CraftBukkit + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setAge(compoundtag.getInt("Age")); +- this.forcedAge = compoundtag.getInt("ForcedAge"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setAge(compound.getInt("Age")); ++ this.forcedAge = compound.getInt("ForcedAge"); ++ this.ageLocked = compound.getBoolean("AgeLocked"); // CraftBukkit + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- if (AgeableMob.DATA_BABY_ID.equals(entitydataaccessor)) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ if (AgeableMob.DATA_BABY_ID.equals(key)) { + this.refreshDimensions(); + } + +- super.onSyncedDataUpdated(entitydataaccessor); ++ super.onSyncedDataUpdated(key); + } + + @Override +- @Override + public void aiStep() { + super.aiStep(); +- if (this.level().isClientSide) { ++ if (this.level().isClientSide || ageLocked) { // CraftBukkit + if (this.forcedAgeTimer > 0) { + if (this.forcedAgeTimer % 4 == 0) { + this.level().addParticle(ParticleTypes.HAPPY_VILLAGER, this.getRandomX(1.0D), this.getRandomY() + 0.5D, this.getRandomZ(1.0D), 0.0D, 0.0D, 0.0D); +@@ -157,9 +154,9 @@ + Entity entity = this.getVehicle(); + + if (entity instanceof Boat) { +- Boat boat = (Boat) entity; ++ Boat entityboat = (Boat) entity; + +- if (!boat.hasEnoughSpaceFor(this)) { ++ if (!entityboat.hasEnoughSpaceFor(this)) { + this.stopRiding(); + } + } +@@ -168,38 +165,36 @@ + } + + @Override +- @Override + public boolean isBaby() { + return this.getAge() < 0; + } + + @Override +- @Override +- public void setBaby(boolean flag) { +- this.setAge(flag ? -24000 : 0); ++ public void setBaby(boolean baby) { ++ this.setAge(baby ? -24000 : 0); + } + +- public static int getSpeedUpSecondsWhenFeeding(int i) { +- return (int) ((float) (i / 20) * 0.1F); ++ public static int getSpeedUpSecondsWhenFeeding(int ticksUntilAdult) { ++ return (int) ((float) (ticksUntilAdult / 20) * 0.1F); + } + +- public static class AgeableMobGroupData implements SpawnGroupData { ++ public static class AgeableMobGroupData implements GroupDataEntity { + + private int groupSize; + private final boolean shouldSpawnBaby; + private final float babySpawnChance; + +- private AgeableMobGroupData(boolean flag, float f) { +- this.shouldSpawnBaby = flag; +- this.babySpawnChance = f; ++ private AgeableMobGroupData(boolean shouldSpawnBaby, float babySpawnChance) { ++ this.shouldSpawnBaby = shouldSpawnBaby; ++ this.babySpawnChance = babySpawnChance; + } + +- public AgeableMobGroupData(boolean flag) { +- this(flag, 0.05F); ++ public AgeableMobGroupData(boolean shouldSpawnBaby) { ++ this(shouldSpawnBaby, 0.05F); + } + +- public AgeableMobGroupData(float f) { +- this(true, f); ++ public AgeableMobGroupData(float babySpawnChance) { ++ this(true, babySpawnChance); + } + + public int getGroupSize() { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/AreaEffectCloud.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/AreaEffectCloud.java.patch new file mode 100644 index 0000000000..f891ebc906 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/AreaEffectCloud.java.patch @@ -0,0 +1,465 @@ +--- a/net/minecraft/world/entity/AreaEffectCloud.java ++++ b/net/minecraft/world/entity/AreaEffectCloud.java +@@ -28,8 +28,11 @@ + import net.minecraft.world.item.alchemy.PotionUtils; + import net.minecraft.world.item.alchemy.Potions; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.material.PushReaction; ++import net.minecraft.world.level.material.EnumPistonReaction; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.entity.LivingEntity; ++// CraftBukkit end + + public class AreaEffectCloud extends Entity implements TraceableEntity { + +@@ -45,23 +48,23 @@ + public static final float DEFAULT_WIDTH = 6.0F; + public static final float HEIGHT = 0.5F; + private static final String TAG_EFFECTS = "effects"; +- private Potion potion; +- private final List effects; ++ public Potion potion; ++ public List effects; + private final Map victims; + private int duration; +- private int waitTime; +- private int reapplicationDelay; ++ public int waitTime; ++ public int reapplicationDelay; + private boolean fixedColor; +- private int durationOnUse; +- private float radiusOnUse; +- private float radiusPerTick; ++ public int durationOnUse; ++ public float radiusOnUse; ++ public float radiusPerTick; + @Nullable +- private LivingEntity owner; ++ private net.minecraft.world.entity.LivingEntity owner; + @Nullable + private UUID ownerUUID; + +- public AreaEffectCloud(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public AreaEffectCloud(EntityType entityType, Level level) { ++ super(entityType, level); + this.potion = Potions.EMPTY; + this.effects = Lists.newArrayList(); + this.victims = Maps.newHashMap(); +@@ -71,13 +74,12 @@ + this.noPhysics = true; + } + +- public AreaEffectCloud(Level level, double d0, double d1, double d2) { ++ public AreaEffectCloud(Level level, double x, double d1, double y) { + this(EntityType.AREA_EFFECT_CLOUD, level); +- this.setPos(d0, d1, d2); ++ this.setPos(x, d1, y); + } + + @Override +- @Override + protected void defineSynchedData() { + this.getEntityData().define(AreaEffectCloud.DATA_COLOR, 0); + this.getEntityData().define(AreaEffectCloud.DATA_RADIUS, 3.0F); +@@ -85,15 +87,14 @@ + this.getEntityData().define(AreaEffectCloud.DATA_PARTICLE, ParticleTypes.ENTITY_EFFECT); + } + +- public void setRadius(float f) { ++ public void setRadius(float radius) { + if (!this.level().isClientSide) { +- this.getEntityData().set(AreaEffectCloud.DATA_RADIUS, Mth.clamp(f, 0.0F, 32.0F)); ++ this.getEntityData().set(AreaEffectCloud.DATA_RADIUS, Mth.clamp(radius, 0.0F, 32.0F)); + } + + } + + @Override +- @Override + public void refreshDimensions() { + double d0 = this.getX(); + double d1 = this.getY(); +@@ -115,7 +116,7 @@ + + } + +- private void updateColor() { ++ public void updateColor() { + if (this.potion == Potions.EMPTY && this.effects.isEmpty()) { + this.getEntityData().set(AreaEffectCloud.DATA_COLOR, 0); + } else { +@@ -124,8 +125,8 @@ + + } + +- public void addEffect(MobEffectInstance mobeffectinstance) { +- this.effects.add(mobeffectinstance); ++ public void addEffect(MobEffectInstance effectInstance) { ++ this.effects.add(effectInstance); + if (!this.fixedColor) { + this.updateColor(); + } +@@ -136,21 +137,21 @@ + return (Integer) this.getEntityData().get(AreaEffectCloud.DATA_COLOR); + } + +- public void setFixedColor(int i) { ++ public void setFixedColor(int color) { + this.fixedColor = true; +- this.getEntityData().set(AreaEffectCloud.DATA_COLOR, i); ++ this.getEntityData().set(AreaEffectCloud.DATA_COLOR, color); + } + + public ParticleOptions getParticle() { + return (ParticleOptions) this.getEntityData().get(AreaEffectCloud.DATA_PARTICLE); + } + +- public void setParticle(ParticleOptions particleoptions) { +- this.getEntityData().set(AreaEffectCloud.DATA_PARTICLE, particleoptions); ++ public void setParticle(ParticleOptions particleOption) { ++ this.getEntityData().set(AreaEffectCloud.DATA_PARTICLE, particleOption); + } + +- protected void setWaiting(boolean flag) { +- this.getEntityData().set(AreaEffectCloud.DATA_WAITING, flag); ++ protected void setWaiting(boolean waiting) { ++ this.getEntityData().set(AreaEffectCloud.DATA_WAITING, waiting); + } + + public boolean isWaiting() { +@@ -161,12 +162,11 @@ + return this.duration; + } + +- public void setDuration(int i) { +- this.duration = i; ++ public void setDuration(int duration) { ++ this.duration = duration; + } + + @Override +- @Override + public void tick() { + super.tick(); + boolean flag = this.isWaiting(); +@@ -177,7 +177,7 @@ + return; + } + +- ParticleOptions particleoptions = this.getParticle(); ++ ParticleOptions particleparam = this.getParticle(); + int i; + float f1; + +@@ -199,7 +199,7 @@ + double d4; + double d5; + +- if (particleoptions.getType() == ParticleTypes.ENTITY_EFFECT) { ++ if (particleparam.getType() == ParticleTypes.ENTITY_EFFECT) { + int k = flag && this.random.nextBoolean() ? 16777215 : this.getColor(); + + d3 = (double) ((float) (k >> 16 & 255) / 255.0F); +@@ -215,7 +215,7 @@ + d5 = (0.5D - this.random.nextDouble()) * 0.15D; + } + +- this.level().addAlwaysVisibleParticle(particleoptions, d0, d1, d2, d3, d4, d5); ++ this.level().addAlwaysVisibleParticle(particleparam, d0, d1, d2, d3, d4, d5); + } + } else { + if (this.tickCount >= this.waitTime + this.duration) { +@@ -251,41 +251,53 @@ + Iterator iterator = this.potion.getEffects().iterator(); + + while (iterator.hasNext()) { +- MobEffectInstance mobeffectinstance = (MobEffectInstance) iterator.next(); ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); + +- list.add(new MobEffectInstance(mobeffectinstance.getEffect(), mobeffectinstance.mapDuration((l) -> { ++ list.add(new MobEffectInstance(mobeffect.getEffect(), mobeffect.mapDuration((l) -> { + return l / 4; +- }), mobeffectinstance.getAmplifier(), mobeffectinstance.isAmbient(), mobeffectinstance.isVisible())); ++ }), mobeffect.getAmplifier(), mobeffect.isAmbient(), mobeffect.isVisible())); + } + + list.addAll(this.effects); + if (list.isEmpty()) { + this.victims.clear(); + } else { +- List list1 = this.level().getEntitiesOfClass(LivingEntity.class, this.getBoundingBox()); ++ List list1 = this.level().getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, this.getBoundingBox()); + + if (!list1.isEmpty()) { + Iterator iterator1 = list1.iterator(); + ++ List entities = new java.util.ArrayList(); // CraftBukkit + while (iterator1.hasNext()) { +- LivingEntity livingentity = (LivingEntity) iterator1.next(); ++ net.minecraft.world.entity.LivingEntity entityliving = (net.minecraft.world.entity.LivingEntity) iterator1.next(); + +- if (!this.victims.containsKey(livingentity) && livingentity.isAffectedByPotions()) { +- double d6 = livingentity.getX() - this.getX(); +- double d7 = livingentity.getZ() - this.getZ(); ++ if (!this.victims.containsKey(entityliving) && entityliving.isAffectedByPotions()) { ++ double d6 = entityliving.getX() - this.getX(); ++ double d7 = entityliving.getZ() - this.getZ(); + double d8 = d6 * d6 + d7 * d7; + + if (d8 <= (double) (f * f)) { +- this.victims.put(livingentity, this.tickCount + this.reapplicationDelay); ++ // CraftBukkit start ++ entities.add((LivingEntity) entityliving.getBukkitEntity()); ++ } ++ } ++ } ++ org.bukkit.event.entity.AreaEffectCloudApplyEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callAreaEffectCloudApplyEvent(this, entities); ++ if (!event.isCancelled()) { ++ for (LivingEntity entity : event.getAffectedEntities()) { ++ if (entity instanceof CraftLivingEntity) { ++ net.minecraft.world.entity.LivingEntity entityliving = ((CraftLivingEntity) entity).getHandle(); ++ // CraftBukkit end ++ this.victims.put(entityliving, this.tickCount + this.reapplicationDelay); + Iterator iterator2 = list.iterator(); + + while (iterator2.hasNext()) { +- MobEffectInstance mobeffectinstance1 = (MobEffectInstance) iterator2.next(); ++ MobEffectInstance mobeffect1 = (MobEffectInstance) iterator2.next(); + +- if (mobeffectinstance1.getEffect().isInstantenous()) { +- mobeffectinstance1.getEffect().applyInstantenousEffect(this, this.getOwner(), livingentity, mobeffectinstance1.getAmplifier(), 0.5D); ++ if (mobeffect1.getEffect().isInstantenous()) { ++ mobeffect1.getEffect().applyInstantenousEffect(this, this.getOwner(), entityliving, mobeffect1.getAmplifier(), 0.5D); + } else { +- livingentity.addEffect(new MobEffectInstance(mobeffectinstance1), this); ++ entityliving.addEffect(new MobEffectInstance(mobeffect1), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AREA_EFFECT_CLOUD); // CraftBukkit + } + } + +@@ -320,48 +332,47 @@ + return this.radiusOnUse; + } + +- public void setRadiusOnUse(float f) { +- this.radiusOnUse = f; ++ public void setRadiusOnUse(float radiusOnUse) { ++ this.radiusOnUse = radiusOnUse; + } + + public float getRadiusPerTick() { + return this.radiusPerTick; + } + +- public void setRadiusPerTick(float f) { +- this.radiusPerTick = f; ++ public void setRadiusPerTick(float radiusPerTick) { ++ this.radiusPerTick = radiusPerTick; + } + + public int getDurationOnUse() { + return this.durationOnUse; + } + +- public void setDurationOnUse(int i) { +- this.durationOnUse = i; ++ public void setDurationOnUse(int durationOnUse) { ++ this.durationOnUse = durationOnUse; + } + + public int getWaitTime() { + return this.waitTime; + } + +- public void setWaitTime(int i) { +- this.waitTime = i; ++ public void setWaitTime(int waitTime) { ++ this.waitTime = waitTime; + } + +- public void setOwner(@Nullable LivingEntity livingentity) { +- this.owner = livingentity; +- this.ownerUUID = livingentity == null ? null : livingentity.getUUID(); ++ public void setOwner(@Nullable net.minecraft.world.entity.LivingEntity owner) { ++ this.owner = owner; ++ this.ownerUUID = owner == null ? null : owner.getUUID(); + } + + @Nullable + @Override +- @Override +- public LivingEntity getOwner() { ++ public net.minecraft.world.entity.LivingEntity getOwner() { + if (this.owner == null && this.ownerUUID != null && this.level() instanceof ServerLevel) { + Entity entity = ((ServerLevel) this.level()).getEntity(this.ownerUUID); + +- if (entity instanceof LivingEntity) { +- this.owner = (LivingEntity) entity; ++ if (entity instanceof net.minecraft.world.entity.LivingEntity) { ++ this.owner = (net.minecraft.world.entity.LivingEntity) entity; + } + } + +@@ -369,46 +380,45 @@ + } + + @Override +- @Override +- protected void readAdditionalSaveData(CompoundTag compoundtag) { +- this.tickCount = compoundtag.getInt("Age"); +- this.duration = compoundtag.getInt("Duration"); +- this.waitTime = compoundtag.getInt("WaitTime"); +- this.reapplicationDelay = compoundtag.getInt("ReapplicationDelay"); +- this.durationOnUse = compoundtag.getInt("DurationOnUse"); +- this.radiusOnUse = compoundtag.getFloat("RadiusOnUse"); +- this.radiusPerTick = compoundtag.getFloat("RadiusPerTick"); +- this.setRadius(compoundtag.getFloat("Radius")); +- if (compoundtag.hasUUID("Owner")) { +- this.ownerUUID = compoundtag.getUUID("Owner"); ++ protected void readAdditionalSaveData(CompoundTag compound) { ++ this.tickCount = compound.getInt("Age"); ++ this.duration = compound.getInt("Duration"); ++ this.waitTime = compound.getInt("WaitTime"); ++ this.reapplicationDelay = compound.getInt("ReapplicationDelay"); ++ this.durationOnUse = compound.getInt("DurationOnUse"); ++ this.radiusOnUse = compound.getFloat("RadiusOnUse"); ++ this.radiusPerTick = compound.getFloat("RadiusPerTick"); ++ this.setRadius(compound.getFloat("Radius")); ++ if (compound.hasUUID("Owner")) { ++ this.ownerUUID = compound.getUUID("Owner"); + } + +- if (compoundtag.contains("Particle", 8)) { ++ if (compound.contains("Particle", 8)) { + try { +- this.setParticle(ParticleArgument.readParticle(new StringReader(compoundtag.getString("Particle")), (HolderLookup) BuiltInRegistries.PARTICLE_TYPE.asLookup())); ++ this.setParticle(ParticleArgument.readParticle(new StringReader(compound.getString("Particle")), (HolderLookup) BuiltInRegistries.PARTICLE_TYPE.asLookup())); + } catch (CommandSyntaxException commandsyntaxexception) { +- AreaEffectCloud.LOGGER.warn("Couldn't load custom particle {}", compoundtag.getString("Particle"), commandsyntaxexception); ++ AreaEffectCloud.LOGGER.warn("Couldn't load custom particle {}", compound.getString("Particle"), commandsyntaxexception); + } + } + +- if (compoundtag.contains("Color", 99)) { +- this.setFixedColor(compoundtag.getInt("Color")); ++ if (compound.contains("Color", 99)) { ++ this.setFixedColor(compound.getInt("Color")); + } + +- if (compoundtag.contains("Potion", 8)) { +- this.setPotion(PotionUtils.getPotion(compoundtag)); ++ if (compound.contains("Potion", 8)) { ++ this.setPotion(PotionUtils.getPotion(compound)); + } + +- if (compoundtag.contains("effects", 9)) { +- ListTag listtag = compoundtag.getList("effects", 10); ++ if (compound.contains("effects", 9)) { ++ ListTag nbttaglist = compound.getList("effects", 10); + + this.effects.clear(); + +- for (int i = 0; i < listtag.size(); ++i) { +- MobEffectInstance mobeffectinstance = MobEffectInstance.load(listtag.getCompound(i)); ++ for (int i = 0; i < nbttaglist.size(); ++i) { ++ MobEffectInstance mobeffect = MobEffectInstance.load(nbttaglist.getCompound(i)); + +- if (mobeffectinstance != null) { +- this.addEffect(mobeffectinstance); ++ if (mobeffect != null) { ++ this.addEffect(mobeffect); + } + } + } +@@ -416,52 +426,50 @@ + } + + @Override +- @Override +- protected void addAdditionalSaveData(CompoundTag compoundtag) { +- compoundtag.putInt("Age", this.tickCount); +- compoundtag.putInt("Duration", this.duration); +- compoundtag.putInt("WaitTime", this.waitTime); +- compoundtag.putInt("ReapplicationDelay", this.reapplicationDelay); +- compoundtag.putInt("DurationOnUse", this.durationOnUse); +- compoundtag.putFloat("RadiusOnUse", this.radiusOnUse); +- compoundtag.putFloat("RadiusPerTick", this.radiusPerTick); +- compoundtag.putFloat("Radius", this.getRadius()); +- compoundtag.putString("Particle", this.getParticle().writeToString()); ++ protected void addAdditionalSaveData(CompoundTag compound) { ++ compound.putInt("Age", this.tickCount); ++ compound.putInt("Duration", this.duration); ++ compound.putInt("WaitTime", this.waitTime); ++ compound.putInt("ReapplicationDelay", this.reapplicationDelay); ++ compound.putInt("DurationOnUse", this.durationOnUse); ++ compound.putFloat("RadiusOnUse", this.radiusOnUse); ++ compound.putFloat("RadiusPerTick", this.radiusPerTick); ++ compound.putFloat("Radius", this.getRadius()); ++ compound.putString("Particle", this.getParticle().writeToString()); + if (this.ownerUUID != null) { +- compoundtag.putUUID("Owner", this.ownerUUID); ++ compound.putUUID("Owner", this.ownerUUID); + } + + if (this.fixedColor) { +- compoundtag.putInt("Color", this.getColor()); ++ compound.putInt("Color", this.getColor()); + } + + if (this.potion != Potions.EMPTY) { +- compoundtag.putString("Potion", BuiltInRegistries.POTION.getKey(this.potion).toString()); ++ compound.putString("Potion", BuiltInRegistries.POTION.getKey(this.potion).toString()); + } + + if (!this.effects.isEmpty()) { +- ListTag listtag = new ListTag(); ++ ListTag nbttaglist = new ListTag(); + Iterator iterator = this.effects.iterator(); + + while (iterator.hasNext()) { +- MobEffectInstance mobeffectinstance = (MobEffectInstance) iterator.next(); ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); + +- listtag.add(mobeffectinstance.save(new CompoundTag())); ++ nbttaglist.add(mobeffect.save(new CompoundTag())); + } + +- compoundtag.put("effects", listtag); ++ compound.put("effects", nbttaglist); + } + + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- if (AreaEffectCloud.DATA_RADIUS.equals(entitydataaccessor)) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ if (AreaEffectCloud.DATA_RADIUS.equals(key)) { + this.refreshDimensions(); + } + +- super.onSyncedDataUpdated(entitydataaccessor); ++ super.onSyncedDataUpdated(key); + } + + public Potion getPotion() { +@@ -469,14 +477,12 @@ + } + + @Override +- @Override +- public PushReaction getPistonPushReaction() { +- return PushReaction.IGNORE; ++ public EnumPistonReaction getPistonPushReaction() { ++ return EnumPistonReaction.IGNORE; + } + + @Override +- @Override +- public EntityDimensions getDimensions(Pose pose) { ++ public EntityDimensions getDimensions(EntityPose pose) { + return EntityDimensions.scalable(this.getRadius() * 2.0F, 0.5F); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/Entity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/Entity.java.patch new file mode 100644 index 0000000000..3ecafee161 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/Entity.java.patch @@ -0,0 +1,4014 @@ +--- a/net/minecraft/world/entity/Entity.java ++++ b/net/minecraft/world/entity/Entity.java +@@ -70,9 +70,9 @@ + import net.minecraft.tags.TagKey; + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; ++import net.minecraft.world.INamableTileEntity; + import net.minecraft.world.InteractionResult; +-import net.minecraft.world.Nameable; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.damagesource.DamageSources; + import net.minecraft.world.entity.item.ItemEntity; +@@ -87,28 +87,29 @@ + import net.minecraft.world.level.ClipContext; + import net.minecraft.world.level.Explosion; + import net.minecraft.world.level.GameRules; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.EnumRenderType; + import net.minecraft.world.level.block.FenceGateBlock; + import net.minecraft.world.level.block.HoneyBlock; + import net.minecraft.world.level.block.Mirror; +-import net.minecraft.world.level.block.RenderShape; + import net.minecraft.world.level.block.Rotation; + import net.minecraft.world.level.block.SoundType; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.border.WorldBorder; + import net.minecraft.world.level.dimension.DimensionType; ++import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.entity.EntityAccess; + import net.minecraft.world.level.entity.EntityInLevelCallback; + import net.minecraft.world.level.gameevent.DynamicGameEventListener; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.levelgen.Heightmap; ++import net.minecraft.world.level.material.EnumPistonReaction; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; +-import net.minecraft.world.level.material.PushReaction; + import net.minecraft.world.level.portal.PortalInfo; + import net.minecraft.world.level.portal.PortalShape; + import net.minecraft.world.phys.AABB; +@@ -125,9 +126,63 @@ + import net.minecraft.world.scores.Team; + import org.joml.Vector3f; + import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.Server; ++import org.bukkit.block.BlockFace; ++import org.bukkit.command.CommandSender; ++import org.bukkit.craftbukkit.event.CraftPortalEvent; ++import org.bukkit.entity.Hanging; ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.entity.Vehicle; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.hanging.HangingBreakByEntityEvent; ++import org.bukkit.event.vehicle.VehicleBlockCollisionEvent; ++import org.bukkit.event.vehicle.VehicleEnterEvent; ++import org.bukkit.event.vehicle.VehicleExitEvent; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.entity.CraftEntity; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.Pose; ++import org.bukkit.event.entity.EntityAirChangeEvent; ++import org.bukkit.event.entity.EntityCombustEvent; ++import org.bukkit.event.entity.EntityDropItemEvent; ++import org.bukkit.event.entity.EntityPortalEvent; ++import org.bukkit.event.entity.EntityPoseChangeEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++import org.bukkit.plugin.PluginManager; ++// CraftBukkit end + +-public abstract class Entity implements Nameable, EntityAccess, CommandSource, ScoreHolder { ++public abstract class Entity implements INamableTileEntity, EntityAccess, CommandSource, ScoreHolder { + ++ // CraftBukkit start ++ private static final int CURRENT_LEVEL = 2; ++ static boolean isLevelAtLeast(CompoundTag tag, int level) { ++ return tag.contains("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; ++ } ++ ++ private CraftEntity bukkitEntity; ++ ++ public CraftEntity getBukkitEntity() { ++ if (bukkitEntity == null) { ++ bukkitEntity = CraftEntity.getEntity(level.getCraftServer(), this); ++ } ++ return bukkitEntity; ++ } ++ ++ @Override ++ public CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return getBukkitEntity(); ++ } ++ ++ // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ public int getDefaultMaxAirSupply() { ++ return TOTAL_AIR_SUPPLY; ++ } ++ // CraftBukkit end ++ + private static final Logger LOGGER = LogUtils.getLogger(); + public static final String ID_TAG = "id"; + public static final String PASSENGERS_TAG = "Passengers"; +@@ -151,7 +206,7 @@ + private final EntityType type; + private int id; + public boolean blocksBuilding; +- private ImmutableList passengers; ++ public ImmutableList passengers; + protected int boardingCooldown; + @Nullable + private Entity vehicle; +@@ -168,7 +223,7 @@ + public float yRotO; + public float xRotO; + private AABB bb; +- private boolean onGround; ++ public boolean onGround; + public boolean horizontalCollision; + public boolean verticalCollision; + public boolean verticalCollisionBelow; +@@ -190,10 +245,10 @@ + public double zOld; + private float maxUpStep; + public boolean noPhysics; +- protected final RandomSource random; ++ public final RandomSource random; + public int tickCount; + private int remainingFireTicks; +- protected boolean wasTouchingWater; ++ public boolean wasTouchingWater; + protected Object2DoubleMap> fluidHeight; + protected boolean wasEyeInWater; + private final Set> fluidOnEyes; +@@ -213,13 +268,13 @@ + private static final EntityDataAccessor DATA_CUSTOM_NAME_VISIBLE = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_SILENT = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_NO_GRAVITY = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.BOOLEAN); +- protected static final EntityDataAccessor DATA_POSE = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.POSE); ++ protected static final EntityDataAccessor DATA_POSE = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.POSE); + private static final EntityDataAccessor DATA_TICKS_FROZEN = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.INT); + private EntityInLevelCallback levelCallback; + private final VecDeltaCodec packetPositionCodec; + public boolean noCulling; + public boolean hasImpulse; +- private int portalCooldown; ++ public int portalCooldown; + protected boolean isInsidePortal; + protected int portalTime; + protected BlockPos portalEntrancePos; +@@ -239,11 +294,34 @@ + private boolean onGroundNoBlocks; + private float crystalSoundIntensity; + private int lastCrystalSoundPlayTick; +- private boolean hasVisualFire; ++ public boolean hasVisualFire; + @Nullable +- private BlockState feetBlockState; ++ private IBlockData feetBlockState; ++ // CraftBukkit start ++ public boolean persist = true; ++ public boolean visibleByDefault = true; ++ public boolean valid; ++ public boolean inWorld = false; ++ public boolean generation; ++ public int maxAirTicks = getDefaultMaxAirSupply(); // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only ++ public boolean lastDamageCancelled; // SPIGOT-5339, SPIGOT-6252, SPIGOT-6777: Keep track if the event was canceled ++ public boolean persistentInvisibility = false; ++ public BlockPos lastLavaContact; ++ // Marks an entity, that it was removed by a plugin via Entity#remove ++ // Main use case currently is for SPIGOT-7487, preventing dropping of leash when leash is removed ++ public boolean pluginRemoved = false; + +- public Entity(EntityType entitytype, Level level) { ++ public float getBukkitYaw() { ++ return this.yRot; ++ } ++ ++ public boolean isChunkLoaded() { ++ return level.hasChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); ++ } ++ // CraftBukkit end ++ ++ public Entity(EntityType entityType, Level level) { + this.id = Entity.ENTITY_COUNTER.incrementAndGet(); + this.passengers = ImmutableList.of(); + this.deltaMovement = Vec3.ZERO; +@@ -264,9 +342,9 @@ + this.mainSupportingBlockPos = Optional.empty(); + this.onGroundNoBlocks = false; + this.feetBlockState = null; +- this.type = entitytype; ++ this.type = entityType; + this.level = level; +- this.dimensions = entitytype.getDimensions(); ++ this.dimensions = entityType.getDimensions(); + this.position = Vec3.ZERO; + this.blockPosition = BlockPos.ZERO; + this.chunkPosition = ChunkPos.ZERO; +@@ -277,24 +355,24 @@ + this.entityData.define(Entity.DATA_CUSTOM_NAME, Optional.empty()); + this.entityData.define(Entity.DATA_SILENT, false); + this.entityData.define(Entity.DATA_NO_GRAVITY, false); +- this.entityData.define(Entity.DATA_POSE, Pose.STANDING); ++ this.entityData.define(Entity.DATA_POSE, EntityPose.STANDING); + this.entityData.define(Entity.DATA_TICKS_FROZEN, 0); + this.defineSynchedData(); + this.setPos(0.0D, 0.0D, 0.0D); +- this.eyeHeight = this.getEyeHeight(Pose.STANDING, this.dimensions); ++ this.eyeHeight = this.getEyeHeight(EntityPose.STANDING, this.dimensions); + } + +- public boolean isColliding(BlockPos blockpos, BlockState blockstate) { +- VoxelShape voxelshape = blockstate.getCollisionShape(this.level(), blockpos, CollisionContext.of(this)); +- VoxelShape voxelshape1 = voxelshape.move((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ()); ++ public boolean isColliding(BlockPos pos, IBlockData state) { ++ VoxelShape voxelshape = state.getCollisionShape(this.level(), pos, CollisionContext.of(this)); ++ VoxelShape voxelshape1 = voxelshape.move((double) pos.getX(), (double) pos.getY(), (double) pos.getZ()); + + return Shapes.joinIsNotEmpty(voxelshape1, Shapes.create(this.getBoundingBox()), BooleanOp.AND); + } + + public int getTeamColor() { +- PlayerTeam playerteam = this.getTeam(); ++ PlayerTeam scoreboardteam = this.getTeam(); + +- return playerteam != null && playerteam.getColor().getColor() != null ? playerteam.getColor().getColor() : 16777215; ++ return scoreboardteam != null && scoreboardteam.getColor().getColor() != null ? scoreboardteam.getColor().getColor() : 16777215; + } + + public boolean isSpectator() { +@@ -312,8 +390,8 @@ + + } + +- public void syncPacketPositionCodec(double d0, double d1, double d2) { +- this.packetPositionCodec.setBase(new Vec3(d0, d1, d2)); ++ public void syncPacketPositionCodec(double x, double d1, double y) { ++ this.packetPositionCodec.setBase(new Vec3(x, d1, y)); + } + + public VecDeltaCodec getPositionCodec() { +@@ -325,25 +403,24 @@ + } + + @Override +- @Override + public int getId() { + return this.id; + } + +- public void setId(int i) { +- this.id = i; ++ public void setId(int id) { ++ this.id = id; + } + + public Set getTags() { + return this.tags; + } + +- public boolean addTag(String s) { +- return this.tags.size() >= 1024 ? false : this.tags.add(s); ++ public boolean addTag(String tag) { ++ return this.tags.size() >= 1024 ? false : this.tags.add(tag); + } + +- public boolean removeTag(String s) { +- return this.tags.remove(s); ++ public boolean removeTag(String tag) { ++ return this.tags.remove(tag); + } + + public void kill() { +@@ -361,57 +438,88 @@ + return this.entityData; + } + +- @Override + public boolean equals(Object object) { + return object instanceof Entity ? ((Entity) object).id == this.id : false; + } + +- @Override + public int hashCode() { + return this.id; + } + +- public void remove(Entity.RemovalReason entity_removalreason) { +- this.setRemoved(entity_removalreason); ++ public void remove(Entity.RemovalReason reason) { ++ this.setRemoved(reason); + } + + public void onClientRemoval() {} + +- public void setPose(Pose pose) { ++ public void setPose(EntityPose pose) { ++ // CraftBukkit start ++ if (pose == this.getPose()) { ++ return; ++ } ++ this.level.getCraftServer().getPluginManager().callEvent(new EntityPoseChangeEvent(this.getBukkitEntity(), Pose.values()[pose.ordinal()])); ++ // CraftBukkit end + this.entityData.set(Entity.DATA_POSE, pose); + } + +- public Pose getPose() { +- return (Pose) this.entityData.get(Entity.DATA_POSE); ++ public EntityPose getPose() { ++ return (EntityPose) this.entityData.get(Entity.DATA_POSE); + } + +- public boolean hasPose(Pose pose) { ++ public boolean hasPose(EntityPose pose) { + return this.getPose() == pose; + } + +- public boolean closerThan(Entity entity, double d0) { +- return this.position().closerThan(entity.position(), d0); ++ public boolean closerThan(Entity entity, double distance) { ++ return this.position().closerThan(entity.position(), distance); + } + +- public boolean closerThan(Entity entity, double d0, double d1) { ++ public boolean closerThan(Entity entity, double horizontalDistance, double d1) { + double d2 = entity.getX() - this.getX(); + double d3 = entity.getY() - this.getY(); + double d4 = entity.getZ() - this.getZ(); + +- return Mth.lengthSquared(d2, d4) < Mth.square(d0) && Mth.square(d3) < Mth.square(d1); ++ return Mth.lengthSquared(d2, d4) < Mth.square(horizontalDistance) && Mth.square(d3) < Mth.square(d1); + } + +- protected void setRot(float f, float f1) { +- this.setYRot(f % 360.0F); +- this.setXRot(f1 % 360.0F); ++ protected void setRot(float yRot, float xRot) { ++ // CraftBukkit start - yaw was sometimes set to NaN, so we need to set it back to 0 ++ if (Float.isNaN(yRot)) { ++ yRot = 0; ++ } ++ ++ if (yRot == Float.POSITIVE_INFINITY || yRot == Float.NEGATIVE_INFINITY) { ++ if (this instanceof ServerPlayer) { ++ this.level.getCraftServer().getLogger().warning(this.getScoreboardName() + " was caught trying to crash the server with an invalid yaw"); ++ ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Infinite yaw (Hacking?)"); ++ } ++ yRot = 0; ++ } ++ ++ // pitch was sometimes set to NaN, so we need to set it back to 0 ++ if (Float.isNaN(xRot)) { ++ xRot = 0; ++ } ++ ++ if (xRot == Float.POSITIVE_INFINITY || xRot == Float.NEGATIVE_INFINITY) { ++ if (this instanceof ServerPlayer) { ++ this.level.getCraftServer().getLogger().warning(this.getScoreboardName() + " was caught trying to crash the server with an invalid pitch"); ++ ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Infinite pitch (Hacking?)"); ++ } ++ xRot = 0; ++ } ++ // CraftBukkit end ++ ++ this.setYRot(yRot % 360.0F); ++ this.setXRot(xRot % 360.0F); + } + +- public final void setPos(Vec3 vec3) { +- this.setPos(vec3.x(), vec3.y(), vec3.z()); ++ public final void setPos(Vec3 pos) { ++ this.setPos(pos.x(), pos.y(), pos.z()); + } + +- public void setPos(double d0, double d1, double d2) { +- this.setPosRaw(d0, d1, d2); ++ public void setPos(double x, double d1, double y) { ++ this.setPosRaw(x, d1, y); + this.setBoundingBox(this.makeBoundingBox()); + } + +@@ -423,9 +531,9 @@ + this.setPos(this.position.x, this.position.y, this.position.z); + } + +- public void turn(double d0, double d1) { ++ public void turn(double yRot, double d1) { + float f = (float) d1 * 0.15F; +- float f1 = (float) d0 * 0.15F; ++ float f1 = (float) yRot * 0.15F; + + this.setXRot(this.getXRot() + f); + this.setYRot(this.getYRot() + f1); +@@ -443,6 +551,15 @@ + this.baseTick(); + } + ++ // CraftBukkit start ++ public void postTick() { ++ // No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle ++ if (!(this instanceof ServerPlayer)) { ++ this.handleNetherPortal(); ++ } ++ } ++ // CraftBukkit end ++ + public void baseTick() { + this.level().getProfiler().push("entityBaseTick"); + this.feetBlockState = null; +@@ -457,7 +574,7 @@ + this.walkDistO = this.walkDist; + this.xRotO = this.getXRot(); + this.yRotO = this.getYRot(); +- this.handleNetherPortal(); ++ if (this instanceof ServerPlayer) this.handleNetherPortal(); // CraftBukkit - // Moved up to postTick + if (this.canSpawnSprintParticle()) { + this.spawnSprintParticle(); + } +@@ -492,6 +609,10 @@ + if (this.isInLava()) { + this.lavaHurt(); + this.fallDistance *= 0.5F; ++ // CraftBukkit start ++ } else { ++ this.lastLavaContact = null; ++ // CraftBukkit end + } + + this.checkBelowWorld(); +@@ -503,8 +624,8 @@ + this.level().getProfiler().pop(); + } + +- public void setSharedFlagOnFire(boolean flag) { +- this.setSharedFlag(0, flag || this.hasVisualFire); ++ public void setSharedFlagOnFire(boolean isOnFire) { ++ this.setSharedFlag(0, isOnFire || this.hasVisualFire); + } + + public void checkBelowWorld() { +@@ -518,8 +639,8 @@ + this.portalCooldown = this.getDimensionChangingDelay(); + } + +- public void setPortalCooldown(int i) { +- this.portalCooldown = i; ++ public void setPortalCooldown(int portalCooldown) { ++ this.portalCooldown = portalCooldown; + } + + public int getPortalCooldown() { +@@ -543,19 +664,52 @@ + + public void lavaHurt() { + if (!this.fireImmune()) { +- this.setSecondsOnFire(15); ++ // CraftBukkit start - Fallen in lava TODO: this event spams! ++ if (this instanceof net.minecraft.world.entity.LivingEntity && remainingFireTicks <= 0) { ++ // not on fire yet ++ org.bukkit.block.Block damager = (lastLavaContact == null) ? null : org.bukkit.craftbukkit.block.CraftBlock.at(level, lastLavaContact); ++ org.bukkit.entity.Entity damagee = this.getBukkitEntity(); ++ EntityCombustEvent combustEvent = new org.bukkit.event.entity.EntityCombustByBlockEvent(damager, damagee, 15); ++ this.level.getCraftServer().getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ this.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ } else { ++ // This will be called every single tick the entity is in lava, so don't throw an event ++ this.setSecondsOnFire(15, false); ++ } ++ CraftEventFactory.blockDamage = (lastLavaContact) == null ? null : org.bukkit.craftbukkit.block.CraftBlock.at(level, lastLavaContact); + if (this.hurt(this.damageSources().lava(), 4.0F)) { + this.playSound(SoundEvents.GENERIC_BURN, 0.4F, 2.0F + this.random.nextFloat() * 0.4F); + } ++ CraftEventFactory.blockDamage = null; ++ // CraftBukkit end - we also don't throw an event unless the object in lava is living, to save on some event calls + + } + } + +- public void setSecondsOnFire(int i) { ++ public void setSecondsOnFire(int seconds) { ++ // CraftBukkit start ++ this.setSecondsOnFire(seconds, true); ++ } ++ ++ public void setSecondsOnFire(int i, boolean callEvent) { ++ if (callEvent) { ++ EntityCombustEvent event = new EntityCombustEvent(this.getBukkitEntity(), i); ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ i = event.getDuration(); ++ } ++ // CraftBukkit end + int j = i * 20; + +- if (this instanceof LivingEntity) { +- j = ProtectionEnchantment.getFireAfterDampener((LivingEntity) this, j); ++ if (this instanceof net.minecraft.world.entity.LivingEntity) { ++ j = ProtectionEnchantment.getFireAfterDampener((net.minecraft.world.entity.LivingEntity) this, j); + } + + if (this.remainingFireTicks < j) { +@@ -564,8 +718,8 @@ + + } + +- public void setRemainingFireTicks(int i) { +- this.remainingFireTicks = i; ++ public void setRemainingFireTicks(int remainingFireTicks) { ++ this.remainingFireTicks = remainingFireTicks; + } + + public int getRemainingFireTicks() { +@@ -580,39 +734,39 @@ + this.discard(); + } + +- public boolean isFree(double d0, double d1, double d2) { +- return this.isFree(this.getBoundingBox().move(d0, d1, d2)); ++ public boolean isFree(double x, double d1, double y) { ++ return this.isFree(this.getBoundingBox().move(x, d1, y)); + } + +- private boolean isFree(AABB aabb) { +- return this.level().noCollision(this, aabb) && !this.level().containsAnyLiquid(aabb); ++ private boolean isFree(AABB box) { ++ return this.level().noCollision(this, box) && !this.level().containsAnyLiquid(box); + } + +- public void setOnGround(boolean flag) { +- this.onGround = flag; +- this.checkSupportingBlock(flag, (Vec3) null); ++ public void setOnGround(boolean onGround) { ++ this.onGround = onGround; ++ this.checkSupportingBlock(onGround, (Vec3) null); + } + +- public void setOnGroundWithKnownMovement(boolean flag, Vec3 vec3) { +- this.onGround = flag; +- this.checkSupportingBlock(flag, vec3); ++ public void setOnGroundWithKnownMovement(boolean onGround, Vec3 movement) { ++ this.onGround = onGround; ++ this.checkSupportingBlock(onGround, movement); + } + +- public boolean isSupportedBy(BlockPos blockpos) { +- return this.mainSupportingBlockPos.isPresent() && ((BlockPos) this.mainSupportingBlockPos.get()).equals(blockpos); ++ public boolean isSupportedBy(BlockPos pos) { ++ return this.mainSupportingBlockPos.isPresent() && ((BlockPos) this.mainSupportingBlockPos.get()).equals(pos); + } + +- protected void checkSupportingBlock(boolean flag, @Nullable Vec3 vec3) { +- if (flag) { +- AABB aabb = this.getBoundingBox(); +- AABB aabb1 = new AABB(aabb.minX, aabb.minY - 1.0E-6D, aabb.minZ, aabb.maxX, aabb.minY, aabb.maxZ); +- Optional optional = this.level.findSupportingBlock(this, aabb1); ++ protected void checkSupportingBlock(boolean onGround, @Nullable Vec3 movement) { ++ if (onGround) { ++ AABB axisalignedbb = this.getBoundingBox(); ++ AABB axisalignedbb1 = new AABB(axisalignedbb.minX, axisalignedbb.minY - 1.0E-6D, axisalignedbb.minZ, axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.maxZ); ++ Optional optional = this.level.findSupportingBlock(this, axisalignedbb1); + + if (!optional.isPresent() && !this.onGroundNoBlocks) { +- if (vec3 != null) { +- AABB aabb2 = aabb1.move(-vec3.x, 0.0D, -vec3.z); ++ if (movement != null) { ++ AABB axisalignedbb2 = axisalignedbb1.move(-movement.x, 0.0D, -movement.z); + +- optional = this.level.findSupportingBlock(this, aabb2); ++ optional = this.level.findSupportingBlock(this, axisalignedbb2); + this.mainSupportingBlockPos = optional; + } + } else { +@@ -633,103 +787,125 @@ + return this.onGround; + } + +- public void move(MoverType movertype, Vec3 vec3) { ++ public void move(EnumMoveType type, Vec3 pos) { + if (this.noPhysics) { +- this.setPos(this.getX() + vec3.x, this.getY() + vec3.y, this.getZ() + vec3.z); ++ this.setPos(this.getX() + pos.x, this.getY() + pos.y, this.getZ() + pos.z); + } else { + this.wasOnFire = this.isOnFire(); +- if (movertype == MoverType.PISTON) { +- vec3 = this.limitPistonMovement(vec3); +- if (vec3.equals(Vec3.ZERO)) { ++ if (type == EnumMoveType.PISTON) { ++ pos = this.limitPistonMovement(pos); ++ if (pos.equals(Vec3.ZERO)) { + return; + } + } + + this.level().getProfiler().push("move"); + if (this.stuckSpeedMultiplier.lengthSqr() > 1.0E-7D) { +- vec3 = vec3.multiply(this.stuckSpeedMultiplier); ++ pos = pos.multiply(this.stuckSpeedMultiplier); + this.stuckSpeedMultiplier = Vec3.ZERO; + this.setDeltaMovement(Vec3.ZERO); + } + +- vec3 = this.maybeBackOffFromEdge(vec3, movertype); +- Vec3 vec31 = this.collide(vec3); +- double d0 = vec31.lengthSqr(); ++ pos = this.maybeBackOffFromEdge(pos, type); ++ Vec3 vec3d1 = this.collide(pos); ++ double d0 = vec3d1.lengthSqr(); + + if (d0 > 1.0E-7D) { + if (this.fallDistance != 0.0F && d0 >= 1.0D) { +- BlockHitResult blockhitresult = this.level().clip(new ClipContext(this.position(), this.position().add(vec31), ClipContext.Block.FALLDAMAGE_RESETTING, ClipContext.Fluid.WATER, this)); ++ BlockHitResult movingobjectpositionblock = this.level().clip(new ClipContext(this.position(), this.position().add(vec3d1), ClipContext.Block.FALLDAMAGE_RESETTING, ClipContext.Fluid.WATER, this)); + +- if (blockhitresult.getType() != HitResult.Type.MISS) { ++ if (movingobjectpositionblock.getType() != HitResult.EnumMovingObjectType.MISS) { + this.resetFallDistance(); + } + } + +- this.setPos(this.getX() + vec31.x, this.getY() + vec31.y, this.getZ() + vec31.z); ++ this.setPos(this.getX() + vec3d1.x, this.getY() + vec3d1.y, this.getZ() + vec3d1.z); + } + + this.level().getProfiler().pop(); + this.level().getProfiler().push("rest"); +- boolean flag = !Mth.equal(vec3.x, vec31.x); +- boolean flag1 = !Mth.equal(vec3.z, vec31.z); ++ boolean flag = !Mth.equal(pos.x, vec3d1.x); ++ boolean flag1 = !Mth.equal(pos.z, vec3d1.z); + + this.horizontalCollision = flag || flag1; +- this.verticalCollision = vec3.y != vec31.y; +- this.verticalCollisionBelow = this.verticalCollision && vec3.y < 0.0D; ++ this.verticalCollision = pos.y != vec3d1.y; ++ this.verticalCollisionBelow = this.verticalCollision && pos.y < 0.0D; + if (this.horizontalCollision) { +- this.minorHorizontalCollision = this.isHorizontalCollisionMinor(vec31); ++ this.minorHorizontalCollision = this.isHorizontalCollisionMinor(vec3d1); + } else { + this.minorHorizontalCollision = false; + } + +- this.setOnGroundWithKnownMovement(this.verticalCollisionBelow, vec31); +- BlockPos blockpos = this.getOnPosLegacy(); +- BlockState blockstate = this.level().getBlockState(blockpos); ++ this.setOnGroundWithKnownMovement(this.verticalCollisionBelow, vec3d1); ++ BlockPos blockposition = this.getOnPosLegacy(); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); + +- this.checkFallDamage(vec31.y, this.onGround(), blockstate, blockpos); ++ this.checkFallDamage(vec3d1.y, this.onGround(), iblockdata, blockposition); + if (this.isRemoved()) { + this.level().getProfiler().pop(); + } else { + if (this.horizontalCollision) { +- Vec3 vec32 = this.getDeltaMovement(); ++ Vec3 vec3d2 = this.getDeltaMovement(); + +- this.setDeltaMovement(flag ? 0.0D : vec32.x, vec32.y, flag1 ? 0.0D : vec32.z); ++ this.setDeltaMovement(flag ? 0.0D : vec3d2.x, vec3d2.y, flag1 ? 0.0D : vec3d2.z); + } + +- Block block = blockstate.getBlock(); ++ Block block = iblockdata.getBlock(); + +- if (vec3.y != vec31.y) { ++ if (pos.y != vec3d1.y) { + block.updateEntityAfterFallOn(this.level(), this); + } + ++ // CraftBukkit start ++ if (horizontalCollision && getBukkitEntity() instanceof Vehicle) { ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ org.bukkit.block.Block bl = this.level.getWorld().getBlockAt(Mth.floor(this.getX()), Mth.floor(this.getY()), Mth.floor(this.getZ())); ++ ++ if (pos.x > vec3d1.x) { ++ bl = bl.getRelative(BlockFace.EAST); ++ } else if (pos.x < vec3d1.x) { ++ bl = bl.getRelative(BlockFace.WEST); ++ } else if (pos.z > vec3d1.z) { ++ bl = bl.getRelative(BlockFace.SOUTH); ++ } else if (pos.z < vec3d1.z) { ++ bl = bl.getRelative(BlockFace.NORTH); ++ } ++ ++ if (!bl.getType().isAir()) { ++ VehicleBlockCollisionEvent event = new VehicleBlockCollisionEvent(vehicle, bl); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ } ++ } ++ // CraftBukkit end ++ + if (this.onGround()) { +- block.stepOn(this.level(), blockpos, blockstate, this); ++ block.stepOn(this.level(), blockposition, iblockdata, this); + } + + Entity.MovementEmission entity_movementemission = this.getMovementEmission(); + + if (entity_movementemission.emitsAnything() && !this.isPassenger()) { +- double d1 = vec31.x; +- double d2 = vec31.y; +- double d3 = vec31.z; ++ double d1 = vec3d1.x; ++ double d2 = vec3d1.y; ++ double d3 = vec3d1.z; + +- this.flyDist += (float) (vec31.length() * 0.6D); +- BlockPos blockpos1 = this.getOnPos(); +- BlockState blockstate1 = this.level().getBlockState(blockpos1); +- boolean flag2 = this.isStateClimbable(blockstate1); ++ this.flyDist += (float) (vec3d1.length() * 0.6D); ++ BlockPos blockposition1 = this.getOnPos(); ++ IBlockData iblockdata1 = this.level().getBlockState(blockposition1); ++ boolean flag2 = this.isStateClimbable(iblockdata1); + + if (!flag2) { + d2 = 0.0D; + } + +- this.walkDist += (float) vec31.horizontalDistance() * 0.6F; ++ this.walkDist += (float) vec3d1.horizontalDistance() * 0.6F; + this.moveDist += (float) Math.sqrt(d1 * d1 + d2 * d2 + d3 * d3) * 0.6F; +- if (this.moveDist > this.nextStep && !blockstate1.isAir()) { +- boolean flag3 = blockpos1.equals(blockpos); +- boolean flag4 = this.vibrationAndSoundEffectsFromBlock(blockpos, blockstate, entity_movementemission.emitsSounds(), flag3, vec3); ++ if (this.moveDist > this.nextStep && !iblockdata1.isAir()) { ++ boolean flag3 = blockposition1.equals(blockposition); ++ boolean flag4 = this.vibrationAndSoundEffectsFromBlock(blockposition, iblockdata, entity_movementemission.emitsSounds(), flag3, pos); + + if (!flag3) { +- flag4 |= this.vibrationAndSoundEffectsFromBlock(blockpos1, blockstate1, false, entity_movementemission.emitsEvents(), vec3); ++ flag4 |= this.vibrationAndSoundEffectsFromBlock(blockposition1, iblockdata1, false, entity_movementemission.emitsEvents(), pos); + } + + if (flag4) { +@@ -744,7 +920,7 @@ + this.gameEvent(GameEvent.SWIM); + } + } +- } else if (blockstate1.isAir()) { ++ } else if (iblockdata1.isAir()) { + this.processFlappingMovement(); + } + } +@@ -753,8 +929,8 @@ + float f = this.getBlockSpeedFactor(); + + this.setDeltaMovement(this.getDeltaMovement().multiply((double) f, 1.0D, (double) f)); +- if (this.level().getBlockStatesIfLoaded(this.getBoundingBox().deflate(1.0E-6D)).noneMatch((blockstate2) -> { +- return blockstate2.is(BlockTags.FIRE) || blockstate2.is(Blocks.LAVA); ++ if (this.level().getBlockStatesIfLoaded(this.getBoundingBox().deflate(1.0E-6D)).noneMatch((iblockdata2) -> { ++ return iblockdata2.is(BlockTags.FIRE) || iblockdata2.is(Blocks.LAVA); + })) { + if (this.remainingFireTicks <= 0) { + this.setRemainingFireTicks(-this.getFireImmuneTicks()); +@@ -774,23 +950,23 @@ + } + } + +- private boolean isStateClimbable(BlockState blockstate) { +- return blockstate.is(BlockTags.CLIMBABLE) || blockstate.is(Blocks.POWDER_SNOW); ++ private boolean isStateClimbable(IBlockData state) { ++ return state.is(BlockTags.CLIMBABLE) || state.is(Blocks.POWDER_SNOW); + } + +- private boolean vibrationAndSoundEffectsFromBlock(BlockPos blockpos, BlockState blockstate, boolean flag, boolean flag1, Vec3 vec3) { +- if (blockstate.isAir()) { ++ private boolean vibrationAndSoundEffectsFromBlock(BlockPos pos, IBlockData state, boolean playStepSound, boolean broadcastGameEvent, Vec3 vec3d) { ++ if (state.isAir()) { + return false; + } else { +- boolean flag2 = this.isStateClimbable(blockstate); ++ boolean flag2 = this.isStateClimbable(state); + +- if ((this.onGround() || flag2 || this.isCrouching() && vec3.y == 0.0D || this.isOnRails()) && !this.isSwimming()) { +- if (flag) { +- this.walkingStepSound(blockpos, blockstate); ++ if ((this.onGround() || flag2 || this.isCrouching() && vec3d.y == 0.0D || this.isOnRails()) && !this.isSwimming()) { ++ if (playStepSound) { ++ this.walkingStepSound(pos, state); + } + +- if (flag1) { +- this.level().gameEvent(GameEvent.STEP, this.position(), GameEvent.Context.of(this, blockstate)); ++ if (broadcastGameEvent) { ++ this.level().gameEvent(GameEvent.STEP, this.position(), GameEvent.Context.of(this, state)); + } + + return true; +@@ -800,7 +976,7 @@ + } + } + +- protected boolean isHorizontalCollisionMinor(Vec3 vec3) { ++ protected boolean isHorizontalCollisionMinor(Vec3 deltaMovement) { + return false; + } + +@@ -809,9 +985,9 @@ + this.checkInsideBlocks(); + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Checking entity block collision"); +- CrashReportCategory crashreportcategory = crashreport.addCategory("Entity being checked for collision"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being checked for collision"); + +- this.fillCrashReportCategory(crashreportcategory); ++ this.fillCrashReportCategory(crashreportsystemdetails); + throw new ReportedException(crashreport); + } + } +@@ -852,20 +1028,20 @@ + return this.getOnPos(1.0E-5F); + } + +- protected BlockPos getOnPos(float f) { ++ protected BlockPos getOnPos(float yOffset) { + if (this.mainSupportingBlockPos.isPresent()) { +- BlockPos blockpos = (BlockPos) this.mainSupportingBlockPos.get(); ++ BlockPos blockposition = (BlockPos) this.mainSupportingBlockPos.get(); + +- if (f <= 1.0E-5F) { +- return blockpos; ++ if (yOffset <= 1.0E-5F) { ++ return blockposition; + } else { +- BlockState blockstate = this.level().getBlockState(blockpos); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); + +- return ((double) f > 0.5D || !blockstate.is(BlockTags.FENCES)) && !blockstate.is(BlockTags.WALLS) && !(blockstate.getBlock() instanceof FenceGateBlock) ? blockpos.atY(Mth.floor(this.position.y - (double) f)) : blockpos; ++ return ((double) yOffset > 0.5D || !iblockdata.is(BlockTags.FENCES)) && !iblockdata.is(BlockTags.WALLS) && !(iblockdata.getBlock() instanceof FenceGateBlock) ? blockposition.atY(Mth.floor(this.position.y - (double) yOffset)) : blockposition; + } + } else { + int i = Mth.floor(this.position.x); +- int j = Mth.floor(this.position.y - (double) f); ++ int j = Mth.floor(this.position.y - (double) yOffset); + int k = Mth.floor(this.position.z); + + return new BlockPos(i, j, k); +@@ -880,19 +1056,19 @@ + } + + protected float getBlockSpeedFactor() { +- BlockState blockstate = this.level().getBlockState(this.blockPosition()); +- float f = blockstate.getBlock().getSpeedFactor(); ++ IBlockData iblockdata = this.level().getBlockState(this.blockPosition()); ++ float f = iblockdata.getBlock().getSpeedFactor(); + +- return !blockstate.is(Blocks.WATER) && !blockstate.is(Blocks.BUBBLE_COLUMN) ? ((double) f == 1.0D ? this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getSpeedFactor() : f) : f; ++ return !iblockdata.is(Blocks.WATER) && !iblockdata.is(Blocks.BUBBLE_COLUMN) ? ((double) f == 1.0D ? this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getSpeedFactor() : f) : f; + } + +- protected Vec3 maybeBackOffFromEdge(Vec3 vec3, MoverType movertype) { +- return vec3; ++ protected Vec3 maybeBackOffFromEdge(Vec3 vec, EnumMoveType mover) { ++ return vec; + } + +- protected Vec3 limitPistonMovement(Vec3 vec3) { +- if (vec3.lengthSqr() <= 1.0E-7D) { +- return vec3; ++ protected Vec3 limitPistonMovement(Vec3 pos) { ++ if (pos.lengthSqr() <= 1.0E-7D) { ++ return pos; + } else { + long i = this.level().getGameTime(); + +@@ -903,14 +1079,14 @@ + + double d0; + +- if (vec3.x != 0.0D) { +- d0 = this.applyPistonMovementRestriction(Direction.Axis.X, vec3.x); ++ if (pos.x != 0.0D) { ++ d0 = this.applyPistonMovementRestriction(Direction.Axis.X, pos.x); + return Math.abs(d0) <= 9.999999747378752E-6D ? Vec3.ZERO : new Vec3(d0, 0.0D, 0.0D); +- } else if (vec3.y != 0.0D) { +- d0 = this.applyPistonMovementRestriction(Direction.Axis.Y, vec3.y); ++ } else if (pos.y != 0.0D) { ++ d0 = this.applyPistonMovementRestriction(Direction.Axis.Y, pos.y); + return Math.abs(d0) <= 9.999999747378752E-6D ? Vec3.ZERO : new Vec3(0.0D, d0, 0.0D); +- } else if (vec3.z != 0.0D) { +- d0 = this.applyPistonMovementRestriction(Direction.Axis.Z, vec3.z); ++ } else if (pos.z != 0.0D) { ++ d0 = this.applyPistonMovementRestriction(Direction.Axis.Z, pos.z); + return Math.abs(d0) <= 9.999999747378752E-6D ? Vec3.ZERO : new Vec3(0.0D, 0.0D, d0); + } else { + return Vec3.ZERO; +@@ -918,95 +1094,95 @@ + } + } + +- private double applyPistonMovementRestriction(Direction.Axis direction_axis, double d0) { +- int i = direction_axis.ordinal(); +- double d1 = Mth.clamp(d0 + this.pistonDeltas[i], -0.51D, 0.51D); ++ private double applyPistonMovementRestriction(Direction.Axis axis, double distance) { ++ int i = axis.ordinal(); ++ double d1 = Mth.clamp(distance + this.pistonDeltas[i], -0.51D, 0.51D); + +- d0 = d1 - this.pistonDeltas[i]; ++ distance = d1 - this.pistonDeltas[i]; + this.pistonDeltas[i] = d1; +- return d0; ++ return distance; + } + +- private Vec3 collide(Vec3 vec3) { +- AABB aabb = this.getBoundingBox(); +- List list = this.level().getEntityCollisions(this, aabb.expandTowards(vec3)); +- Vec3 vec31 = vec3.lengthSqr() == 0.0D ? vec3 : collideBoundingBox(this, vec3, aabb, this.level(), list); +- boolean flag = vec3.x != vec31.x; +- boolean flag1 = vec3.y != vec31.y; +- boolean flag2 = vec3.z != vec31.z; +- boolean flag3 = this.onGround() || flag1 && vec3.y < 0.0D; ++ private Vec3 collide(Vec3 vec) { ++ AABB axisalignedbb = this.getBoundingBox(); ++ List list = this.level().getEntityCollisions(this, axisalignedbb.expandTowards(vec)); ++ Vec3 vec3d1 = vec.lengthSqr() == 0.0D ? vec : collideBoundingBox(this, vec, axisalignedbb, this.level(), list); ++ boolean flag = vec.x != vec3d1.x; ++ boolean flag1 = vec.y != vec3d1.y; ++ boolean flag2 = vec.z != vec3d1.z; ++ boolean flag3 = this.onGround() || flag1 && vec.y < 0.0D; + + if (this.maxUpStep() > 0.0F && flag3 && (flag || flag2)) { +- Vec3 vec32 = collideBoundingBox(this, new Vec3(vec3.x, (double) this.maxUpStep(), vec3.z), aabb, this.level(), list); +- Vec3 vec33 = collideBoundingBox(this, new Vec3(0.0D, (double) this.maxUpStep(), 0.0D), aabb.expandTowards(vec3.x, 0.0D, vec3.z), this.level(), list); ++ Vec3 vec3d2 = collideBoundingBox(this, new Vec3(vec.x, (double) this.maxUpStep(), vec.z), axisalignedbb, this.level(), list); ++ Vec3 vec3d3 = collideBoundingBox(this, new Vec3(0.0D, (double) this.maxUpStep(), 0.0D), axisalignedbb.expandTowards(vec.x, 0.0D, vec.z), this.level(), list); + +- if (vec33.y < (double) this.maxUpStep()) { +- Vec3 vec34 = collideBoundingBox(this, new Vec3(vec3.x, 0.0D, vec3.z), aabb.move(vec33), this.level(), list).add(vec33); ++ if (vec3d3.y < (double) this.maxUpStep()) { ++ Vec3 vec3d4 = collideBoundingBox(this, new Vec3(vec.x, 0.0D, vec.z), axisalignedbb.move(vec3d3), this.level(), list).add(vec3d3); + +- if (vec34.horizontalDistanceSqr() > vec32.horizontalDistanceSqr()) { +- vec32 = vec34; ++ if (vec3d4.horizontalDistanceSqr() > vec3d2.horizontalDistanceSqr()) { ++ vec3d2 = vec3d4; + } + } + +- if (vec32.horizontalDistanceSqr() > vec31.horizontalDistanceSqr()) { +- return vec32.add(collideBoundingBox(this, new Vec3(0.0D, -vec32.y + vec3.y, 0.0D), aabb.move(vec32), this.level(), list)); ++ if (vec3d2.horizontalDistanceSqr() > vec3d1.horizontalDistanceSqr()) { ++ return vec3d2.add(collideBoundingBox(this, new Vec3(0.0D, -vec3d2.y + vec.y, 0.0D), axisalignedbb.move(vec3d2), this.level(), list)); + } + } + +- return vec31; ++ return vec3d1; + } + +- public static Vec3 collideBoundingBox(@Nullable Entity entity, Vec3 vec3, AABB aabb, Level level, List list) { +- Builder builder = ImmutableList.builderWithExpectedSize(list.size() + 1); ++ public static Vec3 collideBoundingBox(@Nullable Entity entity, Vec3 vec, AABB collisionBox, Level level, List potentialHits) { ++ Builder builder = ImmutableList.builderWithExpectedSize(potentialHits.size() + 1); + +- if (!list.isEmpty()) { +- builder.addAll(list); ++ if (!potentialHits.isEmpty()) { ++ builder.addAll(potentialHits); + } + + WorldBorder worldborder = level.getWorldBorder(); +- boolean flag = entity != null && worldborder.isInsideCloseToBorder(entity, aabb.expandTowards(vec3)); ++ boolean flag = entity != null && worldborder.isInsideCloseToBorder(entity, collisionBox.expandTowards(vec)); + + if (flag) { + builder.add(worldborder.getCollisionShape()); + } + +- builder.addAll(level.getBlockCollisions(entity, aabb.expandTowards(vec3))); +- return collideWithShapes(vec3, aabb, builder.build()); ++ builder.addAll(level.getBlockCollisions(entity, collisionBox.expandTowards(vec))); ++ return collideWithShapes(vec, collisionBox, builder.build()); + } + +- private static Vec3 collideWithShapes(Vec3 vec3, AABB aabb, List list) { +- if (list.isEmpty()) { +- return vec3; ++ private static Vec3 collideWithShapes(Vec3 deltaMovement, AABB entityBB, List shapes) { ++ if (shapes.isEmpty()) { ++ return deltaMovement; + } else { +- double d0 = vec3.x; +- double d1 = vec3.y; +- double d2 = vec3.z; ++ double d0 = deltaMovement.x; ++ double d1 = deltaMovement.y; ++ double d2 = deltaMovement.z; + + if (d1 != 0.0D) { +- d1 = Shapes.collide(Direction.Axis.Y, aabb, list, d1); ++ d1 = Shapes.collide(Direction.Axis.Y, entityBB, shapes, d1); + if (d1 != 0.0D) { +- aabb = aabb.move(0.0D, d1, 0.0D); ++ entityBB = entityBB.move(0.0D, d1, 0.0D); + } + } + + boolean flag = Math.abs(d0) < Math.abs(d2); + + if (flag && d2 != 0.0D) { +- d2 = Shapes.collide(Direction.Axis.Z, aabb, list, d2); ++ d2 = Shapes.collide(Direction.Axis.Z, entityBB, shapes, d2); + if (d2 != 0.0D) { +- aabb = aabb.move(0.0D, 0.0D, d2); ++ entityBB = entityBB.move(0.0D, 0.0D, d2); + } + } + + if (d0 != 0.0D) { +- d0 = Shapes.collide(Direction.Axis.X, aabb, list, d0); ++ d0 = Shapes.collide(Direction.Axis.X, entityBB, shapes, d0); + if (!flag && d0 != 0.0D) { +- aabb = aabb.move(d0, 0.0D, 0.0D); ++ entityBB = entityBB.move(d0, 0.0D, 0.0D); + } + } + + if (!flag && d2 != 0.0D) { +- d2 = Shapes.collide(Direction.Axis.Z, aabb, list, d2); ++ d2 = Shapes.collide(Direction.Axis.Z, entityBB, shapes, d2); + } + + return new Vec3(d0, d1, d2); +@@ -1029,32 +1205,46 @@ + return SoundEvents.GENERIC_SPLASH; + } + ++ // CraftBukkit start - Add delegate methods ++ public SoundEvent getSwimSound0() { ++ return getSwimSound(); ++ } ++ ++ public SoundEvent getSwimSplashSound0() { ++ return getSwimSplashSound(); ++ } ++ ++ public SoundEvent getSwimHighSpeedSplashSound0() { ++ return getSwimHighSpeedSplashSound(); ++ } ++ // CraftBukkit end ++ + protected void checkInsideBlocks() { +- AABB aabb = this.getBoundingBox(); +- BlockPos blockpos = BlockPos.containing(aabb.minX + 1.0E-7D, aabb.minY + 1.0E-7D, aabb.minZ + 1.0E-7D); +- BlockPos blockpos1 = BlockPos.containing(aabb.maxX - 1.0E-7D, aabb.maxY - 1.0E-7D, aabb.maxZ - 1.0E-7D); ++ AABB axisalignedbb = this.getBoundingBox(); ++ BlockPos blockposition = BlockPos.containing(axisalignedbb.minX + 1.0E-7D, axisalignedbb.minY + 1.0E-7D, axisalignedbb.minZ + 1.0E-7D); ++ BlockPos blockposition1 = BlockPos.containing(axisalignedbb.maxX - 1.0E-7D, axisalignedbb.maxY - 1.0E-7D, axisalignedbb.maxZ - 1.0E-7D); + +- if (this.level().hasChunksAt(blockpos, blockpos1)) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ if (this.level().hasChunksAt(blockposition, blockposition1)) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + +- for (int i = blockpos.getX(); i <= blockpos1.getX(); ++i) { +- for (int j = blockpos.getY(); j <= blockpos1.getY(); ++j) { +- for (int k = blockpos.getZ(); k <= blockpos1.getZ(); ++k) { ++ for (int i = blockposition.getX(); i <= blockposition1.getX(); ++i) { ++ for (int j = blockposition.getY(); j <= blockposition1.getY(); ++j) { ++ for (int k = blockposition.getZ(); k <= blockposition1.getZ(); ++k) { + if (!this.isAlive()) { + return; + } + +- blockpos_mutableblockpos.set(i, j, k); +- BlockState blockstate = this.level().getBlockState(blockpos_mutableblockpos); ++ blockposition_mutableblockposition.set(i, j, k); ++ IBlockData iblockdata = this.level().getBlockState(blockposition_mutableblockposition); + + try { +- blockstate.entityInside(this.level(), blockpos_mutableblockpos, this); +- this.onInsideBlock(blockstate); ++ iblockdata.entityInside(this.level(), blockposition_mutableblockposition, this); ++ this.onInsideBlock(iblockdata); + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Colliding entity with block"); +- CrashReportCategory crashreportcategory = crashreport.addCategory("Block being collided with"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being collided with"); + +- CrashReportCategory.populateBlockDetails(crashreportcategory, this.level(), blockpos_mutableblockpos, blockstate); ++ CrashReportCategory.populateBlockDetails(crashreportsystemdetails, this.level(), blockposition_mutableblockposition, iblockdata); + throw new ReportedException(crashreport); + } + } +@@ -1064,19 +1254,19 @@ + + } + +- protected void onInsideBlock(BlockState blockstate) {} ++ protected void onInsideBlock(IBlockData state) {} + +- public void gameEvent(GameEvent gameevent, @Nullable Entity entity) { +- this.level().gameEvent(entity, gameevent, this.position); ++ public void gameEvent(GameEvent event, @Nullable Entity entity) { ++ this.level().gameEvent(entity, event, this.position); + } + +- public void gameEvent(GameEvent gameevent) { +- this.gameEvent(gameevent, this); ++ public void gameEvent(GameEvent event) { ++ this.gameEvent(event, this); + } + +- private void walkingStepSound(BlockPos blockpos, BlockState blockstate) { +- this.playStepSound(blockpos, blockstate); +- if (this.shouldPlayAmethystStepSound(blockstate)) { ++ private void walkingStepSound(BlockPos pos, IBlockData state) { ++ this.playStepSound(pos, state); ++ if (this.shouldPlayAmethystStepSound(state)) { + this.playAmethystStepSound(); + } + +@@ -1085,40 +1275,40 @@ + protected void waterSwimSound() { + Entity entity = (Entity) Objects.requireNonNullElse(this.getControllingPassenger(), this); + float f = entity == this ? 0.35F : 0.4F; +- Vec3 vec3 = entity.getDeltaMovement(); +- float f1 = Math.min(1.0F, (float) Math.sqrt(vec3.x * vec3.x * 0.20000000298023224D + vec3.y * vec3.y + vec3.z * vec3.z * 0.20000000298023224D) * f); ++ Vec3 vec3d = entity.getDeltaMovement(); ++ float f1 = Math.min(1.0F, (float) Math.sqrt(vec3d.x * vec3d.x * 0.20000000298023224D + vec3d.y * vec3d.y + vec3d.z * vec3d.z * 0.20000000298023224D) * f); + + this.playSwimSound(f1); + } + +- protected BlockPos getPrimaryStepSoundBlockPos(BlockPos blockpos) { +- BlockPos blockpos1 = blockpos.above(); +- BlockState blockstate = this.level().getBlockState(blockpos1); ++ protected BlockPos getPrimaryStepSoundBlockPos(BlockPos pos) { ++ BlockPos blockposition1 = pos.above(); ++ IBlockData iblockdata = this.level().getBlockState(blockposition1); + +- return !blockstate.is(BlockTags.INSIDE_STEP_SOUND_BLOCKS) && !blockstate.is(BlockTags.COMBINATION_STEP_SOUND_BLOCKS) ? blockpos : blockpos1; ++ return !iblockdata.is(BlockTags.INSIDE_STEP_SOUND_BLOCKS) && !iblockdata.is(BlockTags.COMBINATION_STEP_SOUND_BLOCKS) ? pos : blockposition1; + } + +- protected void playCombinationStepSounds(BlockState blockstate, BlockState blockstate1) { +- SoundType soundtype = blockstate.getSoundType(); ++ protected void playCombinationStepSounds(IBlockData primaryState, IBlockData secondaryState) { ++ SoundType soundeffecttype = primaryState.getSoundType(); + +- this.playSound(soundtype.getStepSound(), soundtype.getVolume() * 0.15F, soundtype.getPitch()); +- this.playMuffledStepSound(blockstate1); ++ this.playSound(soundeffecttype.getStepSound(), soundeffecttype.getVolume() * 0.15F, soundeffecttype.getPitch()); ++ this.playMuffledStepSound(secondaryState); + } + +- protected void playMuffledStepSound(BlockState blockstate) { +- SoundType soundtype = blockstate.getSoundType(); ++ protected void playMuffledStepSound(IBlockData state) { ++ SoundType soundeffecttype = state.getSoundType(); + +- this.playSound(soundtype.getStepSound(), soundtype.getVolume() * 0.05F, soundtype.getPitch() * 0.8F); ++ this.playSound(soundeffecttype.getStepSound(), soundeffecttype.getVolume() * 0.05F, soundeffecttype.getPitch() * 0.8F); + } + +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { +- SoundType soundtype = blockstate.getSoundType(); ++ protected void playStepSound(BlockPos pos, IBlockData state) { ++ SoundType soundeffecttype = state.getSoundType(); + +- this.playSound(soundtype.getStepSound(), soundtype.getVolume() * 0.15F, soundtype.getPitch()); ++ this.playSound(soundeffecttype.getStepSound(), soundeffecttype.getVolume() * 0.15F, soundeffecttype.getPitch()); + } + +- private boolean shouldPlayAmethystStepSound(BlockState blockstate) { +- return blockstate.is(BlockTags.CRYSTAL_SOUND_BLOCKS) && this.tickCount >= this.lastCrystalSoundPlayTick + 20; ++ private boolean shouldPlayAmethystStepSound(IBlockData state) { ++ return state.is(BlockTags.CRYSTAL_SOUND_BLOCKS) && this.tickCount >= this.lastCrystalSoundPlayTick + 20; + } + + private void playAmethystStepSound() { +@@ -1131,8 +1321,8 @@ + this.lastCrystalSoundPlayTick = this.tickCount; + } + +- protected void playSwimSound(float f) { +- this.playSound(this.getSwimSound(), f, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); ++ protected void playSwimSound(float volume) { ++ this.playSound(this.getSwimSound(), volume, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); + } + + protected void onFlap() {} +@@ -1141,16 +1331,16 @@ + return false; + } + +- public void playSound(SoundEvent soundevent, float f, float f1) { ++ public void playSound(SoundEvent sound, float volume, float pitch) { + if (!this.isSilent()) { +- this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), soundevent, this.getSoundSource(), f, f1); ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), sound, this.getSoundSource(), volume, pitch); + } + + } + +- public void playSound(SoundEvent soundevent) { ++ public void playSound(SoundEvent sound) { + if (!this.isSilent()) { +- this.playSound(soundevent, 1.0F, 1.0F); ++ this.playSound(sound, 1.0F, 1.0F); + } + + } +@@ -1159,16 +1349,16 @@ + return (Boolean) this.entityData.get(Entity.DATA_SILENT); + } + +- public void setSilent(boolean flag) { +- this.entityData.set(Entity.DATA_SILENT, flag); ++ public void setSilent(boolean isSilent) { ++ this.entityData.set(Entity.DATA_SILENT, isSilent); + } + + public boolean isNoGravity() { + return (Boolean) this.entityData.get(Entity.DATA_NO_GRAVITY); + } + +- public void setNoGravity(boolean flag) { +- this.entityData.set(Entity.DATA_NO_GRAVITY, flag); ++ public void setNoGravity(boolean noGravity) { ++ this.entityData.set(Entity.DATA_NO_GRAVITY, noGravity); + } + + protected Entity.MovementEmission getMovementEmission() { +@@ -1179,18 +1369,18 @@ + return false; + } + +- protected void checkFallDamage(double d0, boolean flag, BlockState blockstate, BlockPos blockpos) { ++ protected void checkFallDamage(double y, boolean flag, IBlockData onGround, BlockPos state) { + if (flag) { + if (this.fallDistance > 0.0F) { +- blockstate.getBlock().fallOn(this.level(), blockstate, blockpos, this, this.fallDistance); +- this.level().gameEvent(GameEvent.HIT_GROUND, this.position, GameEvent.Context.of(this, (BlockState) this.mainSupportingBlockPos.map((blockpos1) -> { +- return this.level().getBlockState(blockpos1); +- }).orElse(blockstate))); ++ onGround.getBlock().fallOn(this.level(), onGround, state, this, this.fallDistance); ++ this.level().gameEvent(GameEvent.HIT_GROUND, this.position, GameEvent.Context.of(this, (IBlockData) this.mainSupportingBlockPos.map((blockposition1) -> { ++ return this.level().getBlockState(blockposition1); ++ }).orElse(onGround))); + } + + this.resetFallDistance(); +- } else if (d0 < 0.0D) { +- this.fallDistance -= (float) d0; ++ } else if (y < 0.0D) { ++ this.fallDistance -= (float) y; + } + + } +@@ -1199,7 +1389,7 @@ + return this.getType().fireImmune(); + } + +- public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { ++ public boolean causeFallDamage(float fallDistance, float multiplier, DamageSource source) { + if (this.type.is(EntityTypeTags.FALL_DAMAGE_IMMUNE)) { + return false; + } else { +@@ -1209,7 +1399,7 @@ + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); + +- entity.causeFallDamage(f, f1, damagesource); ++ entity.causeFallDamage(fallDistance, multiplier, source); + } + } + +@@ -1222,9 +1412,9 @@ + } + + private boolean isInRain() { +- BlockPos blockpos = this.blockPosition(); ++ BlockPos blockposition = this.blockPosition(); + +- return this.level().isRainingAt(blockpos) || this.level().isRainingAt(BlockPos.containing((double) blockpos.getX(), this.getBoundingBox().maxY, (double) blockpos.getZ())); ++ return this.level().isRainingAt(blockposition) || this.level().isRainingAt(BlockPos.containing((double) blockposition.getX(), this.getBoundingBox().maxY, (double) blockposition.getZ())); + } + + private boolean isInBubbleColumn() { +@@ -1273,9 +1463,9 @@ + Entity entity = this.getVehicle(); + + if (entity instanceof Boat) { +- Boat boat = (Boat) entity; ++ Boat entityboat = (Boat) entity; + +- if (!boat.isUnderWater()) { ++ if (!entityboat.isUnderWater()) { + this.wasTouchingWater = false; + return; + } +@@ -1302,19 +1492,19 @@ + Entity entity = this.getVehicle(); + + if (entity instanceof Boat) { +- Boat boat = (Boat) entity; ++ Boat entityboat = (Boat) entity; + +- if (!boat.isUnderWater() && boat.getBoundingBox().maxY >= d0 && boat.getBoundingBox().minY <= d0) { ++ if (!entityboat.isUnderWater() && entityboat.getBoundingBox().maxY >= d0 && entityboat.getBoundingBox().minY <= d0) { + return; + } + } + +- BlockPos blockpos = BlockPos.containing(this.getX(), d0, this.getZ()); +- FluidState fluidstate = this.level().getFluidState(blockpos); +- double d1 = (double) ((float) blockpos.getY() + fluidstate.getHeight(this.level(), blockpos)); ++ BlockPos blockposition = BlockPos.containing(this.getX(), d0, this.getZ()); ++ FluidState fluid = this.level().getFluidState(blockposition); ++ double d1 = (double) ((float) blockposition.getY() + fluid.getHeight(this.level(), blockposition)); + + if (d1 > d0) { +- Stream stream = fluidstate.getTags(); ++ Stream stream = fluid.getTags(); + Set set = this.fluidOnEyes; + + Objects.requireNonNull(this.fluidOnEyes); +@@ -1326,8 +1516,8 @@ + protected void doWaterSplashEffect() { + Entity entity = (Entity) Objects.requireNonNullElse(this.getControllingPassenger(), this); + float f = entity == this ? 0.2F : 0.9F; +- Vec3 vec3 = entity.getDeltaMovement(); +- float f1 = Math.min(1.0F, (float) Math.sqrt(vec3.x * vec3.x * 0.20000000298023224D + vec3.y * vec3.y + vec3.z * vec3.z * 0.20000000298023224D) * f); ++ Vec3 vec3d = entity.getDeltaMovement(); ++ float f1 = Math.min(1.0F, (float) Math.sqrt(vec3d.x * vec3d.x * 0.20000000298023224D + vec3d.y * vec3d.y + vec3d.z * vec3d.z * 0.20000000298023224D) * f); + + if (f1 < 0.25F) { + this.playSound(this.getSwimSplashSound(), f1, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); +@@ -1344,13 +1534,13 @@ + for (i = 0; (float) i < 1.0F + this.dimensions.width * 20.0F; ++i) { + d0 = (this.random.nextDouble() * 2.0D - 1.0D) * (double) this.dimensions.width; + d1 = (this.random.nextDouble() * 2.0D - 1.0D) * (double) this.dimensions.width; +- this.level().addParticle(ParticleTypes.BUBBLE, this.getX() + d0, (double) (f2 + 1.0F), this.getZ() + d1, vec3.x, vec3.y - this.random.nextDouble() * 0.20000000298023224D, vec3.z); ++ this.level().addParticle(ParticleTypes.BUBBLE, this.getX() + d0, (double) (f2 + 1.0F), this.getZ() + d1, vec3d.x, vec3d.y - this.random.nextDouble() * 0.20000000298023224D, vec3d.z); + } + + for (i = 0; (float) i < 1.0F + this.dimensions.width * 20.0F; ++i) { + d0 = (this.random.nextDouble() * 2.0D - 1.0D) * (double) this.dimensions.width; + d1 = (this.random.nextDouble() * 2.0D - 1.0D) * (double) this.dimensions.width; +- this.level().addParticle(ParticleTypes.SPLASH, this.getX() + d0, (double) (f2 + 1.0F), this.getZ() + d1, vec3.x, vec3.y, vec3.z); ++ this.level().addParticle(ParticleTypes.SPLASH, this.getX() + d0, (double) (f2 + 1.0F), this.getZ() + d1, vec3d.x, vec3d.y, vec3d.z); + } + + this.gameEvent(GameEvent.SPLASH); +@@ -1358,11 +1548,11 @@ + + /** @deprecated */ + @Deprecated +- protected BlockState getBlockStateOnLegacy() { ++ protected IBlockData getBlockStateOnLegacy() { + return this.level().getBlockState(this.getOnPosLegacy()); + } + +- public BlockState getBlockStateOn() { ++ public IBlockData getBlockStateOn() { + return this.level().getBlockState(this.getOnPos()); + } + +@@ -1371,53 +1561,53 @@ + } + + protected void spawnSprintParticle() { +- BlockPos blockpos = this.getOnPosLegacy(); +- BlockState blockstate = this.level().getBlockState(blockpos); ++ BlockPos blockposition = this.getOnPosLegacy(); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); + +- if (blockstate.getRenderShape() != RenderShape.INVISIBLE) { +- Vec3 vec3 = this.getDeltaMovement(); +- BlockPos blockpos1 = this.blockPosition(); ++ if (iblockdata.getRenderShape() != EnumRenderType.INVISIBLE) { ++ Vec3 vec3d = this.getDeltaMovement(); ++ BlockPos blockposition1 = this.blockPosition(); + double d0 = this.getX() + (this.random.nextDouble() - 0.5D) * (double) this.dimensions.width; + double d1 = this.getZ() + (this.random.nextDouble() - 0.5D) * (double) this.dimensions.width; + +- if (blockpos1.getX() != blockpos.getX()) { +- d0 = Mth.clamp(d0, (double) blockpos.getX(), (double) blockpos.getX() + 1.0D); ++ if (blockposition1.getX() != blockposition.getX()) { ++ d0 = Mth.clamp(d0, (double) blockposition.getX(), (double) blockposition.getX() + 1.0D); + } + +- if (blockpos1.getZ() != blockpos.getZ()) { +- d1 = Mth.clamp(d1, (double) blockpos.getZ(), (double) blockpos.getZ() + 1.0D); ++ if (blockposition1.getZ() != blockposition.getZ()) { ++ d1 = Mth.clamp(d1, (double) blockposition.getZ(), (double) blockposition.getZ() + 1.0D); + } + +- this.level().addParticle(new BlockParticleOption(ParticleTypes.BLOCK, blockstate), d0, this.getY() + 0.1D, d1, vec3.x * -4.0D, 1.5D, vec3.z * -4.0D); ++ this.level().addParticle(new BlockParticleOption(ParticleTypes.BLOCK, iblockdata), d0, this.getY() + 0.1D, d1, vec3d.x * -4.0D, 1.5D, vec3d.z * -4.0D); + } + + } + +- public boolean isEyeInFluid(TagKey tagkey) { +- return this.fluidOnEyes.contains(tagkey); ++ public boolean isEyeInFluid(TagKey fluidTag) { ++ return this.fluidOnEyes.contains(fluidTag); + } + + public boolean isInLava() { + return !this.firstTick && this.fluidHeight.getDouble(FluidTags.LAVA) > 0.0D; + } + +- public void moveRelative(float f, Vec3 vec3) { +- Vec3 vec31 = getInputVector(vec3, f, this.getYRot()); ++ public void moveRelative(float amount, Vec3 relative) { ++ Vec3 vec3d1 = getInputVector(relative, amount, this.getYRot()); + +- this.setDeltaMovement(this.getDeltaMovement().add(vec31)); ++ this.setDeltaMovement(this.getDeltaMovement().add(vec3d1)); + } + +- private static Vec3 getInputVector(Vec3 vec3, float f, float f1) { +- double d0 = vec3.lengthSqr(); ++ private static Vec3 getInputVector(Vec3 relative, float motionScaler, float facing) { ++ double d0 = relative.lengthSqr(); + + if (d0 < 1.0E-7D) { + return Vec3.ZERO; + } else { +- Vec3 vec31 = (d0 > 1.0D ? vec3.normalize() : vec3).scale((double) f); +- float f2 = Mth.sin(f1 * 0.017453292F); +- float f3 = Mth.cos(f1 * 0.017453292F); ++ Vec3 vec3d1 = (d0 > 1.0D ? relative.normalize() : relative).scale((double) motionScaler); ++ float f2 = Mth.sin(facing * 0.017453292F); ++ float f3 = Mth.cos(facing * 0.017453292F); + +- return new Vec3(vec31.x * (double) f3 - vec31.z * (double) f2, vec31.y, vec31.z * (double) f3 + vec31.x * (double) f2); ++ return new Vec3(vec3d1.x * (double) f3 - vec3d1.z * (double) f2, vec3d1.y, vec3d1.z * (double) f3 + vec3d1.x * (double) f2); + } + } + +@@ -1427,40 +1617,41 @@ + return this.level().hasChunkAt(this.getBlockX(), this.getBlockZ()) ? this.level().getLightLevelDependentMagicValue(BlockPos.containing(this.getX(), this.getEyeY(), this.getZ())) : 0.0F; + } + +- public void absMoveTo(double d0, double d1, double d2, float f, float f1) { +- this.absMoveTo(d0, d1, d2); ++ public void absMoveTo(double x, double d1, double y, float f, float z) { ++ this.absMoveTo(x, d1, y); + this.setYRot(f % 360.0F); +- this.setXRot(Mth.clamp(f1, -90.0F, 90.0F) % 360.0F); ++ this.setXRot(Mth.clamp(z, -90.0F, 90.0F) % 360.0F); + this.yRotO = this.getYRot(); + this.xRotO = this.getXRot(); + } + +- public void absMoveTo(double d0, double d1, double d2) { +- double d3 = Mth.clamp(d0, -3.0E7D, 3.0E7D); +- double d4 = Mth.clamp(d2, -3.0E7D, 3.0E7D); ++ public void absMoveTo(double x, double d1, double y) { ++ double d3 = Mth.clamp(x, -3.0E7D, 3.0E7D); ++ double d4 = Mth.clamp(y, -3.0E7D, 3.0E7D); + + this.xo = d3; + this.yo = d1; + this.zo = d4; + this.setPos(d3, d1, d4); ++ if (valid) level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit + } + +- public void moveTo(Vec3 vec3) { +- this.moveTo(vec3.x, vec3.y, vec3.z); ++ public void moveTo(Vec3 vec) { ++ this.moveTo(vec.x, vec.y, vec.z); + } + +- public void moveTo(double d0, double d1, double d2) { +- this.moveTo(d0, d1, d2, this.getYRot(), this.getXRot()); ++ public void moveTo(double x, double d1, double y) { ++ this.moveTo(x, d1, y, this.getYRot(), this.getXRot()); + } + +- public void moveTo(BlockPos blockpos, float f, float f1) { +- this.moveTo((double) blockpos.getX() + 0.5D, (double) blockpos.getY(), (double) blockpos.getZ() + 0.5D, f, f1); ++ public void moveTo(BlockPos pos, float yRot, float xRot) { ++ this.moveTo((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, yRot, xRot); + } + +- public void moveTo(double d0, double d1, double d2, float f, float f1) { +- this.setPosRaw(d0, d1, d2); ++ public void moveTo(double x, double d1, double y, float f, float z) { ++ this.setPosRaw(x, d1, y); + this.setYRot(f); +- this.setXRot(f1); ++ this.setXRot(z); + this.setOldPosAndRot(); + this.reapplyPosition(); + } +@@ -1488,10 +1679,10 @@ + return Mth.sqrt(f * f + f1 * f1 + f2 * f2); + } + +- public double distanceToSqr(double d0, double d1, double d2) { +- double d3 = this.getX() - d0; ++ public double distanceToSqr(double x, double d1, double y) { ++ double d3 = this.getX() - x; + double d4 = this.getY() - d1; +- double d5 = this.getZ() - d2; ++ double d5 = this.getZ() - y; + + return d3 * d3 + d4 * d4 + d5 * d5; + } +@@ -1500,10 +1691,10 @@ + return this.distanceToSqr(entity.position()); + } + +- public double distanceToSqr(Vec3 vec3) { +- double d0 = this.getX() - vec3.x; +- double d1 = this.getY() - vec3.y; +- double d2 = this.getZ() - vec3.z; ++ public double distanceToSqr(Vec3 vec) { ++ double d0 = this.getX() - vec.x; ++ double d1 = this.getY() - vec.y; ++ double d2 = this.getZ() - vec.z; + + return d0 * d0 + d1 * d1 + d2 * d2; + } +@@ -1544,8 +1735,8 @@ + } + } + +- public void push(double d0, double d1, double d2) { +- this.setDeltaMovement(this.getDeltaMovement().add(d0, d1, d2)); ++ public void push(double x, double d1, double y) { ++ this.setDeltaMovement(this.getDeltaMovement().add(x, d1, y)); + this.hasImpulse = true; + } + +@@ -1553,8 +1744,8 @@ + this.hurtMarked = true; + } + +- public boolean hurt(DamageSource damagesource, float f) { +- if (this.isInvulnerableTo(damagesource)) { ++ public boolean hurt(DamageSource source, float amount) { ++ if (this.isInvulnerableTo(source)) { + return false; + } else { + this.markHurt(); +@@ -1562,21 +1753,21 @@ + } + } + +- public final Vec3 getViewVector(float f) { +- return this.calculateViewVector(this.getViewXRot(f), this.getViewYRot(f)); ++ public final Vec3 getViewVector(float partialTicks) { ++ return this.calculateViewVector(this.getViewXRot(partialTicks), this.getViewYRot(partialTicks)); + } + +- public float getViewXRot(float f) { +- return f == 1.0F ? this.getXRot() : Mth.lerp(f, this.xRotO, this.getXRot()); ++ public float getViewXRot(float partialTicks) { ++ return partialTicks == 1.0F ? this.getXRot() : Mth.lerp(partialTicks, this.xRotO, this.getXRot()); + } + +- public float getViewYRot(float f) { +- return f == 1.0F ? this.getYRot() : Mth.lerp(f, this.yRotO, this.getYRot()); ++ public float getViewYRot(float partialTick) { ++ return partialTick == 1.0F ? this.getYRot() : Mth.lerp(partialTick, this.yRotO, this.getYRot()); + } + +- protected final Vec3 calculateViewVector(float f, float f1) { +- float f2 = f * 0.017453292F; +- float f3 = -f1 * 0.017453292F; ++ protected final Vec3 calculateViewVector(float xRot, float yRot) { ++ float f2 = xRot * 0.017453292F; ++ float f3 = -yRot * 0.017453292F; + float f4 = Mth.cos(f3); + float f5 = Mth.sin(f3); + float f6 = Mth.cos(f2); +@@ -1585,44 +1776,44 @@ + return new Vec3((double) (f5 * f6), (double) (-f7), (double) (f4 * f6)); + } + +- public final Vec3 getUpVector(float f) { +- return this.calculateUpVector(this.getViewXRot(f), this.getViewYRot(f)); ++ public final Vec3 getUpVector(float partialTicks) { ++ return this.calculateUpVector(this.getViewXRot(partialTicks), this.getViewYRot(partialTicks)); + } + +- protected final Vec3 calculateUpVector(float f, float f1) { +- return this.calculateViewVector(f - 90.0F, f1); ++ protected final Vec3 calculateUpVector(float xRot, float yRot) { ++ return this.calculateViewVector(xRot - 90.0F, yRot); + } + + public final Vec3 getEyePosition() { + return new Vec3(this.getX(), this.getEyeY(), this.getZ()); + } + +- public final Vec3 getEyePosition(float f) { +- double d0 = Mth.lerp((double) f, this.xo, this.getX()); +- double d1 = Mth.lerp((double) f, this.yo, this.getY()) + (double) this.getEyeHeight(); +- double d2 = Mth.lerp((double) f, this.zo, this.getZ()); ++ public final Vec3 getEyePosition(float partialTicks) { ++ double d0 = Mth.lerp((double) partialTicks, this.xo, this.getX()); ++ double d1 = Mth.lerp((double) partialTicks, this.yo, this.getY()) + (double) this.getEyeHeight(); ++ double d2 = Mth.lerp((double) partialTicks, this.zo, this.getZ()); + + return new Vec3(d0, d1, d2); + } + +- public Vec3 getLightProbePosition(float f) { +- return this.getEyePosition(f); ++ public Vec3 getLightProbePosition(float partialTicks) { ++ return this.getEyePosition(partialTicks); + } + +- public final Vec3 getPosition(float f) { +- double d0 = Mth.lerp((double) f, this.xo, this.getX()); +- double d1 = Mth.lerp((double) f, this.yo, this.getY()); +- double d2 = Mth.lerp((double) f, this.zo, this.getZ()); ++ public final Vec3 getPosition(float partialTicks) { ++ double d0 = Mth.lerp((double) partialTicks, this.xo, this.getX()); ++ double d1 = Mth.lerp((double) partialTicks, this.yo, this.getY()); ++ double d2 = Mth.lerp((double) partialTicks, this.zo, this.getZ()); + + return new Vec3(d0, d1, d2); + } + +- public HitResult pick(double d0, float f, boolean flag) { +- Vec3 vec3 = this.getEyePosition(f); +- Vec3 vec31 = this.getViewVector(f); +- Vec3 vec32 = vec3.add(vec31.x * d0, vec31.y * d0, vec31.z * d0); ++ public HitResult pick(double hitDistance, float f, boolean partialTicks) { ++ Vec3 vec3d = this.getEyePosition(f); ++ Vec3 vec3d1 = this.getViewVector(f); ++ Vec3 vec3d2 = vec3d.add(vec3d1.x * hitDistance, vec3d1.y * hitDistance, vec3d1.z * hitDistance); + +- return this.level().clip(new ClipContext(vec3, vec32, ClipContext.Block.OUTLINE, flag ? ClipContext.Fluid.ANY : ClipContext.Fluid.NONE, this)); ++ return this.level().clip(new ClipContext(vec3d, vec3d2, ClipContext.Block.OUTLINE, partialTicks ? ClipContext.Fluid.ANY : ClipContext.Fluid.NONE, this)); + } + + public boolean canBeHitByProjectile() { +@@ -1637,23 +1828,29 @@ + return false; + } + +- public void awardKillScore(Entity entity, int i, DamageSource damagesource) { +- if (entity instanceof ServerPlayer) { +- CriteriaTriggers.ENTITY_KILLED_PLAYER.trigger((ServerPlayer) entity, this, damagesource); ++ // CraftBukkit start - collidable API ++ public boolean canCollideWithBukkit(Entity entity) { ++ return isPushable(); ++ } ++ // CraftBukkit end ++ ++ public void awardKillScore(Entity killed, int scoreValue, DamageSource source) { ++ if (killed instanceof ServerPlayer) { ++ CriteriaTriggers.ENTITY_KILLED_PLAYER.trigger((ServerPlayer) killed, this, source); + } + + } + +- public boolean shouldRender(double d0, double d1, double d2) { +- double d3 = this.getX() - d0; ++ public boolean shouldRender(double x, double d1, double y) { ++ double d3 = this.getX() - x; + double d4 = this.getY() - d1; +- double d5 = this.getZ() - d2; ++ double d5 = this.getZ() - y; + double d6 = d3 * d3 + d4 * d4 + d5 * d5; + + return this.shouldRenderAtSqrDistance(d6); + } + +- public boolean shouldRenderAtSqrDistance(double d0) { ++ public boolean shouldRenderAtSqrDistance(double distance) { + double d1 = this.getBoundingBox().getSize(); + + if (Double.isNaN(d1)) { +@@ -1661,154 +1858,208 @@ + } + + d1 *= 64.0D * Entity.viewScale; +- return d0 < d1 * d1; ++ return distance < d1 * d1; + } + +- public boolean saveAsPassenger(CompoundTag compoundtag) { ++ public boolean saveAsPassenger(CompoundTag compound) { ++ // CraftBukkit start - allow excluding certain data when saving ++ return saveAsPassenger(compound, true); ++ } ++ ++ public boolean saveAsPassenger(CompoundTag nbttagcompound, boolean includeAll) { ++ // CraftBukkit end + if (this.removalReason != null && !this.removalReason.shouldSave()) { + return false; + } else { + String s = this.getEncodeId(); + +- if (s == null) { ++ if (!this.persist || s == null) { // CraftBukkit - persist flag + return false; + } else { +- compoundtag.putString("id", s); +- this.saveWithoutId(compoundtag); ++ nbttagcompound.putString("id", s); ++ this.saveWithoutId(nbttagcompound, includeAll); // CraftBukkit - pass on includeAll + return true; + } + } + } + +- public boolean save(CompoundTag compoundtag) { +- return this.isPassenger() ? false : this.saveAsPassenger(compoundtag); ++ public boolean save(CompoundTag compound) { ++ return this.isPassenger() ? false : this.saveAsPassenger(compound); + } + +- public CompoundTag saveWithoutId(CompoundTag compoundtag) { ++ public CompoundTag saveWithoutId(CompoundTag compound) { ++ // CraftBukkit start - allow excluding certain data when saving ++ return saveWithoutId(compound, true); ++ } ++ ++ public CompoundTag saveWithoutId(CompoundTag nbttagcompound, boolean includeAll) { ++ // CraftBukkit end + try { +- if (this.vehicle != null) { +- compoundtag.put("Pos", this.newDoubleList(this.vehicle.getX(), this.getY(), this.vehicle.getZ())); +- } else { +- compoundtag.put("Pos", this.newDoubleList(this.getX(), this.getY(), this.getZ())); ++ // CraftBukkit start - selectively save position ++ if (includeAll) { ++ if (this.vehicle != null) { ++ nbttagcompound.put("Pos", this.newDoubleList(this.vehicle.getX(), this.getY(), this.vehicle.getZ())); ++ } else { ++ nbttagcompound.put("Pos", this.newDoubleList(this.getX(), this.getY(), this.getZ())); ++ } + } ++ // CraftBukkit end + +- Vec3 vec3 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + +- compoundtag.put("Motion", this.newDoubleList(vec3.x, vec3.y, vec3.z)); +- compoundtag.put("Rotation", this.newFloatList(this.getYRot(), this.getXRot())); +- compoundtag.putFloat("FallDistance", this.fallDistance); +- compoundtag.putShort("Fire", (short) this.remainingFireTicks); +- compoundtag.putShort("Air", (short) this.getAirSupply()); +- compoundtag.putBoolean("OnGround", this.onGround()); +- compoundtag.putBoolean("Invulnerable", this.invulnerable); +- compoundtag.putInt("PortalCooldown", this.portalCooldown); +- compoundtag.putUUID("UUID", this.getUUID()); +- Component component = this.getCustomName(); ++ nbttagcompound.put("Motion", this.newDoubleList(vec3d.x, vec3d.y, vec3d.z)); + +- if (component != null) { +- compoundtag.putString("CustomName", Component.Serializer.toJson(component)); ++ // CraftBukkit start - Checking for NaN pitch/yaw and resetting to zero ++ // TODO: make sure this is the best way to address this. ++ if (Float.isNaN(this.yRot)) { ++ this.yRot = 0; + } + ++ if (Float.isNaN(this.xRot)) { ++ this.xRot = 0; ++ } ++ // CraftBukkit end ++ ++ nbttagcompound.put("Rotation", this.newFloatList(this.getYRot(), this.getXRot())); ++ nbttagcompound.putFloat("FallDistance", this.fallDistance); ++ nbttagcompound.putShort("Fire", (short) this.remainingFireTicks); ++ nbttagcompound.putShort("Air", (short) this.getAirSupply()); ++ nbttagcompound.putBoolean("OnGround", this.onGround()); ++ nbttagcompound.putBoolean("Invulnerable", this.invulnerable); ++ nbttagcompound.putInt("PortalCooldown", this.portalCooldown); ++ // CraftBukkit start - selectively save uuid and world ++ if (includeAll) { ++ nbttagcompound.putUUID("UUID", this.getUUID()); ++ // PAIL: Check above UUID reads 1.8 properly, ie: UUIDMost / UUIDLeast ++ nbttagcompound.putLong("WorldUUIDLeast", ((ServerLevel) this.level).getWorld().getUID().getLeastSignificantBits()); ++ nbttagcompound.putLong("WorldUUIDMost", ((ServerLevel) this.level).getWorld().getUID().getMostSignificantBits()); ++ } ++ nbttagcompound.putInt("Bukkit.updateLevel", CURRENT_LEVEL); ++ if (!this.persist) { ++ nbttagcompound.putBoolean("Bukkit.persist", this.persist); ++ } ++ if (!this.visibleByDefault) { ++ nbttagcompound.putBoolean("Bukkit.visibleByDefault", this.visibleByDefault); ++ } ++ if (this.persistentInvisibility) { ++ nbttagcompound.putBoolean("Bukkit.invisible", this.persistentInvisibility); ++ } ++ // SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ if (maxAirTicks != getDefaultMaxAirSupply()) { ++ nbttagcompound.putInt("Bukkit.MaxAirSupply", getMaxAirSupply()); ++ } ++ // CraftBukkit end ++ Component ichatbasecomponent = this.getCustomName(); ++ ++ if (ichatbasecomponent != null) { ++ nbttagcompound.putString("CustomName", Component.Serializer.toJson(ichatbasecomponent)); ++ } ++ + if (this.isCustomNameVisible()) { +- compoundtag.putBoolean("CustomNameVisible", this.isCustomNameVisible()); ++ nbttagcompound.putBoolean("CustomNameVisible", this.isCustomNameVisible()); + } + + if (this.isSilent()) { +- compoundtag.putBoolean("Silent", this.isSilent()); ++ nbttagcompound.putBoolean("Silent", this.isSilent()); + } + + if (this.isNoGravity()) { +- compoundtag.putBoolean("NoGravity", this.isNoGravity()); ++ nbttagcompound.putBoolean("NoGravity", this.isNoGravity()); + } + + if (this.hasGlowingTag) { +- compoundtag.putBoolean("Glowing", true); ++ nbttagcompound.putBoolean("Glowing", true); + } + + int i = this.getTicksFrozen(); + + if (i > 0) { +- compoundtag.putInt("TicksFrozen", this.getTicksFrozen()); ++ nbttagcompound.putInt("TicksFrozen", this.getTicksFrozen()); + } + + if (this.hasVisualFire) { +- compoundtag.putBoolean("HasVisualFire", this.hasVisualFire); ++ nbttagcompound.putBoolean("HasVisualFire", this.hasVisualFire); + } + +- ListTag listtag; ++ ListTag nbttaglist; + Iterator iterator; + + if (!this.tags.isEmpty()) { +- listtag = new ListTag(); ++ nbttaglist = new ListTag(); + iterator = this.tags.iterator(); + + while (iterator.hasNext()) { + String s = (String) iterator.next(); + +- listtag.add(StringTag.valueOf(s)); ++ nbttaglist.add(StringTag.valueOf(s)); + } + +- compoundtag.put("Tags", listtag); ++ nbttagcompound.put("Tags", nbttaglist); + } + +- this.addAdditionalSaveData(compoundtag); ++ this.addAdditionalSaveData(nbttagcompound, includeAll); // CraftBukkit - pass on includeAll + if (this.isVehicle()) { +- listtag = new ListTag(); ++ nbttaglist = new ListTag(); + iterator = this.getPassengers().iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); +- CompoundTag compoundtag1 = new CompoundTag(); ++ CompoundTag nbttagcompound1 = new CompoundTag(); + +- if (entity.saveAsPassenger(compoundtag1)) { +- listtag.add(compoundtag1); ++ if (entity.saveAsPassenger(nbttagcompound1, includeAll)) { // CraftBukkit - pass on includeAll ++ nbttaglist.add(nbttagcompound1); + } + } + +- if (!listtag.isEmpty()) { +- compoundtag.put("Passengers", listtag); ++ if (!nbttaglist.isEmpty()) { ++ nbttagcompound.put("Passengers", nbttaglist); + } + } + +- return compoundtag; ++ // CraftBukkit start - stores eventually existing bukkit values ++ if (this.bukkitEntity != null) { ++ this.bukkitEntity.storeBukkitValues(nbttagcompound); ++ } ++ // CraftBukkit end ++ return nbttagcompound; + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT"); +- CrashReportCategory crashreportcategory = crashreport.addCategory("Entity being saved"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being saved"); + +- this.fillCrashReportCategory(crashreportcategory); ++ this.fillCrashReportCategory(crashreportsystemdetails); + throw new ReportedException(crashreport); + } + } + +- public void load(CompoundTag compoundtag) { ++ public void load(CompoundTag compound) { + try { +- ListTag listtag = compoundtag.getList("Pos", 6); +- ListTag listtag1 = compoundtag.getList("Motion", 6); +- ListTag listtag2 = compoundtag.getList("Rotation", 5); +- double d0 = listtag1.getDouble(0); +- double d1 = listtag1.getDouble(1); +- double d2 = listtag1.getDouble(2); ++ ListTag nbttaglist = compound.getList("Pos", 6); ++ ListTag nbttaglist1 = compound.getList("Motion", 6); ++ ListTag nbttaglist2 = compound.getList("Rotation", 5); ++ double d0 = nbttaglist1.getDouble(0); ++ double d1 = nbttaglist1.getDouble(1); ++ double d2 = nbttaglist1.getDouble(2); + + this.setDeltaMovement(Math.abs(d0) > 10.0D ? 0.0D : d0, Math.abs(d1) > 10.0D ? 0.0D : d1, Math.abs(d2) > 10.0D ? 0.0D : d2); + double d3 = 3.0000512E7D; + +- this.setPosRaw(Mth.clamp(listtag.getDouble(0), -3.0000512E7D, 3.0000512E7D), Mth.clamp(listtag.getDouble(1), -2.0E7D, 2.0E7D), Mth.clamp(listtag.getDouble(2), -3.0000512E7D, 3.0000512E7D)); +- this.setYRot(listtag2.getFloat(0)); +- this.setXRot(listtag2.getFloat(1)); ++ this.setPosRaw(Mth.clamp(nbttaglist.getDouble(0), -3.0000512E7D, 3.0000512E7D), Mth.clamp(nbttaglist.getDouble(1), -2.0E7D, 2.0E7D), Mth.clamp(nbttaglist.getDouble(2), -3.0000512E7D, 3.0000512E7D)); ++ this.setYRot(nbttaglist2.getFloat(0)); ++ this.setXRot(nbttaglist2.getFloat(1)); + this.setOldPosAndRot(); + this.setYHeadRot(this.getYRot()); + this.setYBodyRot(this.getYRot()); +- this.fallDistance = compoundtag.getFloat("FallDistance"); +- this.remainingFireTicks = compoundtag.getShort("Fire"); +- if (compoundtag.contains("Air")) { +- this.setAirSupply(compoundtag.getShort("Air")); ++ this.fallDistance = compound.getFloat("FallDistance"); ++ this.remainingFireTicks = compound.getShort("Fire"); ++ if (compound.contains("Air")) { ++ this.setAirSupply(compound.getShort("Air")); + } + +- this.onGround = compoundtag.getBoolean("OnGround"); +- this.invulnerable = compoundtag.getBoolean("Invulnerable"); +- this.portalCooldown = compoundtag.getInt("PortalCooldown"); +- if (compoundtag.hasUUID("UUID")) { +- this.uuid = compoundtag.getUUID("UUID"); ++ this.onGround = compound.getBoolean("OnGround"); ++ this.invulnerable = compound.getBoolean("Invulnerable"); ++ this.portalCooldown = compound.getInt("PortalCooldown"); ++ if (compound.hasUUID("UUID")) { ++ this.uuid = compound.getUUID("UUID"); + this.stringUUID = this.uuid.toString(); + } + +@@ -1816,8 +2067,8 @@ + if (Double.isFinite((double) this.getYRot()) && Double.isFinite((double) this.getXRot())) { + this.reapplyPosition(); + this.setRot(this.getYRot(), this.getXRot()); +- if (compoundtag.contains("CustomName", 8)) { +- String s = compoundtag.getString("CustomName"); ++ if (compound.contains("CustomName", 8)) { ++ String s = compound.getString("CustomName"); + + try { + this.setCustomName(Component.Serializer.fromJson(s)); +@@ -1826,23 +2077,23 @@ + } + } + +- this.setCustomNameVisible(compoundtag.getBoolean("CustomNameVisible")); +- this.setSilent(compoundtag.getBoolean("Silent")); +- this.setNoGravity(compoundtag.getBoolean("NoGravity")); +- this.setGlowingTag(compoundtag.getBoolean("Glowing")); +- this.setTicksFrozen(compoundtag.getInt("TicksFrozen")); +- this.hasVisualFire = compoundtag.getBoolean("HasVisualFire"); +- if (compoundtag.contains("Tags", 9)) { ++ this.setCustomNameVisible(compound.getBoolean("CustomNameVisible")); ++ this.setSilent(compound.getBoolean("Silent")); ++ this.setNoGravity(compound.getBoolean("NoGravity")); ++ this.setGlowingTag(compound.getBoolean("Glowing")); ++ this.setTicksFrozen(compound.getInt("TicksFrozen")); ++ this.hasVisualFire = compound.getBoolean("HasVisualFire"); ++ if (compound.contains("Tags", 9)) { + this.tags.clear(); +- ListTag listtag3 = compoundtag.getList("Tags", 8); +- int i = Math.min(listtag3.size(), 1024); ++ ListTag nbttaglist3 = compound.getList("Tags", 8); ++ int i = Math.min(nbttaglist3.size(), 1024); + + for (int j = 0; j < i; ++j) { +- this.tags.add(listtag3.getString(j)); ++ this.tags.add(nbttaglist3.getString(j)); + } + } + +- this.readAdditionalSaveData(compoundtag); ++ this.readAdditionalSaveData(compound); + if (this.repositionEntityAfterLoad()) { + this.reapplyPosition(); + } +@@ -1853,11 +2104,50 @@ + } else { + throw new IllegalStateException("Entity has invalid position"); + } ++ ++ // CraftBukkit start ++ this.persist = !compound.contains("Bukkit.persist") || compound.getBoolean("Bukkit.persist"); ++ this.visibleByDefault = !compound.contains("Bukkit.visibleByDefault") || compound.getBoolean("Bukkit.visibleByDefault"); ++ // SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ if (compound.contains("Bukkit.MaxAirSupply")) { ++ maxAirTicks = compound.getInt("Bukkit.MaxAirSupply"); ++ } ++ // CraftBukkit end ++ ++ // CraftBukkit start - Reset world ++ if (this instanceof ServerPlayer) { ++ Server server = Bukkit.getServer(); ++ org.bukkit.World bworld = null; ++ ++ // TODO: Remove World related checks, replaced with WorldUID ++ String worldName = compound.getString("world"); ++ ++ if (compound.contains("WorldUUIDMost") && compound.contains("WorldUUIDLeast")) { ++ UUID uid = new UUID(compound.getLong("WorldUUIDMost"), compound.getLong("WorldUUIDLeast")); ++ bworld = server.getWorld(uid); ++ } else { ++ bworld = server.getWorld(worldName); ++ } ++ ++ if (bworld == null) { ++ bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getLevel(Level.OVERWORLD).getWorld(); ++ } ++ ++ ((ServerPlayer) this).setLevel(bworld == null ? null : ((CraftWorld) bworld).getHandle()); ++ } ++ this.getBukkitEntity().readBukkitValues(compound); ++ if (compound.contains("Bukkit.invisible")) { ++ boolean bukkitInvisible = compound.getBoolean("Bukkit.invisible"); ++ this.setInvisible(bukkitInvisible); ++ this.persistentInvisibility = bukkitInvisible; ++ } ++ // CraftBukkit end ++ + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT"); +- CrashReportCategory crashreportcategory = crashreport.addCategory("Entity being loaded"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being loaded"); + +- this.fillCrashReportCategory(crashreportcategory); ++ this.fillCrashReportCategory(crashreportsystemdetails); + throw new ReportedException(crashreport); + } + } +@@ -1867,72 +2157,91 @@ + } + + @Nullable +- protected final String getEncodeId() { +- EntityType entitytype = this.getType(); +- ResourceLocation resourcelocation = EntityType.getKey(entitytype); ++ public final String getEncodeId() { ++ EntityType entitytypes = this.getType(); ++ ResourceLocation minecraftkey = EntityType.getKey(entitytypes); + +- return entitytype.canSerialize() && resourcelocation != null ? resourcelocation.toString() : null; ++ return entitytypes.canSerialize() && minecraftkey != null ? minecraftkey.toString() : null; + } + ++ // CraftBukkit start - allow excluding certain data when saving ++ protected void addAdditionalSaveData(CompoundTag nbttagcompound, boolean includeAll) { ++ addAdditionalSaveData(nbttagcompound); ++ } ++ // CraftBukkit end ++ + protected abstract void readAdditionalSaveData(CompoundTag compound); + + protected abstract void addAdditionalSaveData(CompoundTag compound); + +- protected ListTag newDoubleList(double... adouble) { +- ListTag listtag = new ListTag(); +- double[] adouble1 = adouble; +- int i = adouble.length; ++ protected ListTag newDoubleList(double... numbers) { ++ ListTag nbttaglist = new ListTag(); ++ double[] adouble1 = numbers; ++ int i = numbers.length; + + for (int j = 0; j < i; ++j) { + double d0 = adouble1[j]; + +- listtag.add(DoubleTag.valueOf(d0)); ++ nbttaglist.add(DoubleTag.valueOf(d0)); + } + +- return listtag; ++ return nbttaglist; + } + +- protected ListTag newFloatList(float... afloat) { +- ListTag listtag = new ListTag(); +- float[] afloat1 = afloat; +- int i = afloat.length; ++ protected ListTag newFloatList(float... numbers) { ++ ListTag nbttaglist = new ListTag(); ++ float[] afloat1 = numbers; ++ int i = numbers.length; + + for (int j = 0; j < i; ++j) { + float f = afloat1[j]; + +- listtag.add(FloatTag.valueOf(f)); ++ nbttaglist.add(FloatTag.valueOf(f)); + } + +- return listtag; ++ return nbttaglist; + } + + @Nullable +- public ItemEntity spawnAtLocation(ItemLike itemlike) { +- return this.spawnAtLocation(itemlike, 0); ++ public ItemEntity spawnAtLocation(IMaterial item) { ++ return this.spawnAtLocation(item, 0); + } + + @Nullable +- public ItemEntity spawnAtLocation(ItemLike itemlike, int i) { +- return this.spawnAtLocation(new ItemStack(itemlike), (float) i); ++ public ItemEntity spawnAtLocation(IMaterial item, int offsetY) { ++ return this.spawnAtLocation(new ItemStack(item), (float) offsetY); + } + + @Nullable +- public ItemEntity spawnAtLocation(ItemStack itemstack) { +- return this.spawnAtLocation(itemstack, 0.0F); ++ public ItemEntity spawnAtLocation(ItemStack stack) { ++ return this.spawnAtLocation(stack, 0.0F); + } + + @Nullable +- public ItemEntity spawnAtLocation(ItemStack itemstack, float f) { +- if (itemstack.isEmpty()) { ++ public ItemEntity spawnAtLocation(ItemStack stack, float offsetY) { ++ if (stack.isEmpty()) { + return null; + } else if (this.level().isClientSide) { + return null; + } else { +- ItemEntity itementity = new ItemEntity(this.level(), this.getX(), this.getY() + (double) f, this.getZ(), itemstack); ++ // CraftBukkit start - Capture drops for death event ++ if (this instanceof net.minecraft.world.entity.LivingEntity && !((net.minecraft.world.entity.LivingEntity) this).forceDrops) { ++ ((net.minecraft.world.entity.LivingEntity) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(stack)); ++ return null; ++ } ++ // CraftBukkit end ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY() + (double) offsetY, this.getZ(), stack); + +- itementity.setDefaultPickUpDelay(); +- this.level().addFreshEntity(itementity); +- return itementity; ++ entityitem.setDefaultPickUpDelay(); ++ // CraftBukkit start ++ EntityDropItemEvent event = new EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return null; ++ } ++ // CraftBukkit end ++ this.level().addFreshEntity(entityitem); ++ return entityitem; + } + } + +@@ -1945,17 +2254,17 @@ + return false; + } else { + float f = this.dimensions.width * 0.8F; +- AABB aabb = AABB.ofSize(this.getEyePosition(), (double) f, 1.0E-6D, (double) f); ++ AABB axisalignedbb = AABB.ofSize(this.getEyePosition(), (double) f, 1.0E-6D, (double) f); + +- return BlockPos.betweenClosedStream(aabb).anyMatch((blockpos) -> { +- BlockState blockstate = this.level().getBlockState(blockpos); ++ return BlockPos.betweenClosedStream(axisalignedbb).anyMatch((blockposition) -> { ++ IBlockData iblockdata = this.level().getBlockState(blockposition); + +- return !blockstate.isAir() && blockstate.isSuffocating(this.level(), blockpos) && Shapes.joinIsNotEmpty(blockstate.getCollisionShape(this.level(), blockpos).move((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ()), Shapes.create(aabb), BooleanOp.AND); ++ return !iblockdata.isAir() && iblockdata.isSuffocating(this.level(), blockposition) && Shapes.joinIsNotEmpty(iblockdata.getCollisionShape(this.level(), blockposition).move((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()), Shapes.create(axisalignedbb), BooleanOp.AND); + }); + } + } + +- public InteractionResult interact(Player player, InteractionHand interactionhand) { ++ public InteractionResult interact(Player player, EnumHand hand) { + return InteractionResult.PASS; + } + +@@ -1975,19 +2284,19 @@ + } + } + +- public final void positionRider(Entity entity) { +- if (this.hasPassenger(entity)) { +- this.positionRider(entity, Entity::setPos); ++ public final void positionRider(Entity passenger) { ++ if (this.hasPassenger(passenger)) { ++ this.positionRider(passenger, Entity::setPos); + } + } + +- protected void positionRider(Entity entity, Entity.MoveFunction entity_movefunction) { +- Vec3 vec3 = this.getPassengerRidingPosition(entity); ++ protected void positionRider(Entity passenger, Entity.MoveFunction callback) { ++ Vec3 vec3d = this.getPassengerRidingPosition(passenger); + +- entity_movefunction.accept(entity, vec3.x, vec3.y + (double) entity.getMyRidingOffset(this), vec3.z); ++ callback.accept(passenger, vec3d.x, vec3d.y + (double) passenger.getMyRidingOffset(this), vec3d.z); + } + +- public void onPassengerTurned(Entity entity) {} ++ public void onPassengerTurned(Entity entityToUpdate) {} + + public float getMyRidingOffset(Entity entity) { + return this.ridingOffset(entity); +@@ -2001,41 +2310,53 @@ + return (new Vec3(this.getPassengerAttachmentPoint(entity, this.dimensions, 1.0F).rotateY(-this.yRot * 0.017453292F))).add(this.position()); + } + +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height, 0.0F); + } + +- public boolean startRiding(Entity entity) { +- return this.startRiding(entity, false); ++ public boolean startRiding(Entity vehicle) { ++ return this.startRiding(vehicle, false); + } + + public boolean showVehicleHealth() { +- return this instanceof LivingEntity; ++ return this instanceof net.minecraft.world.entity.LivingEntity; + } + +- public boolean startRiding(Entity entity, boolean flag) { +- if (entity == this.vehicle) { ++ public boolean startRiding(Entity vehicle, boolean force) { ++ if (vehicle == this.vehicle) { + return false; +- } else if (!entity.couldAcceptPassenger()) { ++ } else if (!vehicle.couldAcceptPassenger()) { + return false; + } else { +- for (Entity entity1 = entity; entity1.vehicle != null; entity1 = entity1.vehicle) { ++ for (Entity entity1 = vehicle; entity1.vehicle != null; entity1 = entity1.vehicle) { + if (entity1.vehicle == this) { + return false; + } + } + +- if (!flag && (!this.canRide(entity) || !entity.canAddPassenger(this))) { ++ if (!force && (!this.canRide(vehicle) || !vehicle.canAddPassenger(this))) { + return false; + } else { ++ // CraftBukkit start ++ if (vehicle.getBukkitEntity() instanceof Vehicle && this.getBukkitEntity() instanceof LivingEntity) { ++ VehicleEnterEvent event = new VehicleEnterEvent((Vehicle) vehicle.getBukkitEntity(), this.getBukkitEntity()); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ if (event.isCancelled()) { ++ return false; ++ } ++ } ++ // CraftBukkit end + if (this.isPassenger()) { + this.stopRiding(); + } + +- this.setPose(Pose.STANDING); +- this.vehicle = entity; ++ this.setPose(EntityPose.STANDING); ++ this.vehicle = vehicle; + this.vehicle.addPassenger(this); +- entity.getIndirectPassengersStream().filter((entity2) -> { ++ vehicle.getIndirectPassengersStream().filter((entity2) -> { + return entity2 instanceof ServerPlayer; + }).forEach((entity2) -> { + CriteriaTriggers.START_RIDING_TRIGGER.trigger((ServerPlayer) entity2); +@@ -2045,7 +2366,7 @@ + } + } + +- protected boolean canRide(Entity entity) { ++ protected boolean canRide(Entity vehicle) { + return !this.isShiftKeyDown() && this.boardingCooldown <= 0; + } + +@@ -2061,7 +2382,7 @@ + Entity entity = this.vehicle; + + this.vehicle = null; +- entity.removePassenger(this); ++ if (!entity.removePassenger(this)) this.vehicle = entity; // CraftBukkit + } + + } +@@ -2070,32 +2391,51 @@ + this.removeVehicle(); + } + +- protected void addPassenger(Entity entity) { +- if (entity.getVehicle() != this) { ++ protected void addPassenger(Entity passenger) { ++ if (passenger.getVehicle() != this) { + throw new IllegalStateException("Use x.startRiding(y), not y.addPassenger(x)"); + } else { + if (this.passengers.isEmpty()) { +- this.passengers = ImmutableList.of(entity); ++ this.passengers = ImmutableList.of(passenger); + } else { + List list = Lists.newArrayList(this.passengers); + +- if (!this.level().isClientSide && entity instanceof Player && !(this.getFirstPassenger() instanceof Player)) { +- list.add(0, entity); ++ if (!this.level().isClientSide && passenger instanceof Player && !(this.getFirstPassenger() instanceof Player)) { ++ list.add(0, passenger); + } else { +- list.add(entity); ++ list.add(passenger); + } + + this.passengers = ImmutableList.copyOf(list); + } + +- this.gameEvent(GameEvent.ENTITY_MOUNT, entity); ++ this.gameEvent(GameEvent.ENTITY_MOUNT, passenger); + } + } + +- protected void removePassenger(Entity entity) { ++ protected boolean removePassenger(Entity entity) { // CraftBukkit + if (entity.getVehicle() == this) { + throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); + } else { ++ // CraftBukkit start ++ CraftEntity craft = (CraftEntity) entity.getBukkitEntity().getVehicle(); ++ Entity orig = craft == null ? null : craft.getHandle(); ++ if (getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { ++ VehicleExitEvent event = new VehicleExitEvent( ++ (Vehicle) getBukkitEntity(), ++ (LivingEntity) entity.getBukkitEntity() ++ ); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ CraftEntity craftn = (CraftEntity) entity.getBukkitEntity().getVehicle(); ++ Entity n = craftn == null ? null : craftn.getHandle(); ++ if (event.isCancelled() || n != orig) { ++ return false; ++ } ++ } ++ // CraftBukkit end + if (this.passengers.size() == 1 && this.passengers.get(0) == entity) { + this.passengers = ImmutableList.of(); + } else { +@@ -2107,9 +2447,10 @@ + entity.boardingCooldown = 60; + this.gameEvent(GameEvent.ENTITY_DISMOUNT, entity); + } ++ return true; // CraftBukkit + } + +- protected boolean canAddPassenger(Entity entity) { ++ protected boolean canAddPassenger(Entity passenger) { + return this.passengers.isEmpty(); + } + +@@ -2142,8 +2483,8 @@ + return this.getYRot(); + } + +- public void lerpHeadTo(float f, int i) { +- this.setYHeadRot(f); ++ public void lerpHeadTo(float yaw, int pitch) { ++ this.setYHeadRot(yaw); + } + + public float getPickRadius() { +@@ -2158,11 +2499,11 @@ + if (!(this instanceof Player)) { + return Vec3.ZERO; + } else { +- Player player = (Player) this; +- boolean flag = player.getOffhandItem().is(item) && !player.getMainHandItem().is(item); +- HumanoidArm humanoidarm = flag ? player.getMainArm().getOpposite() : player.getMainArm(); ++ Player entityhuman = (Player) this; ++ boolean flag = entityhuman.getOffhandItem().is(item) && !entityhuman.getMainHandItem().is(item); ++ HumanoidArm enummainhand = flag ? entityhuman.getMainArm().getOpposite() : entityhuman.getMainArm(); + +- return this.calculateViewVector(0.0F, this.getYRot() + (float) (humanoidarm == HumanoidArm.RIGHT ? 80 : -80)).scale(0.5D); ++ return this.calculateViewVector(0.0F, this.getYRot() + (float) (enummainhand == HumanoidArm.RIGHT ? 80 : -80)).scale(0.5D); + } + } + +@@ -2174,12 +2515,12 @@ + return Vec3.directionFromRotation(this.getRotationVector()); + } + +- public void handleInsidePortal(BlockPos blockpos) { ++ public void handleInsidePortal(BlockPos pos) { + if (this.isOnPortalCooldown()) { + this.setPortalCooldown(); + } else { +- if (!this.level().isClientSide && !blockpos.equals(this.portalEntrancePos)) { +- this.portalEntrancePos = blockpos.immutable(); ++ if (!this.level().isClientSide && !pos.equals(this.portalEntrancePos)) { ++ this.portalEntrancePos = pos.immutable(); + } + + this.isInsidePortal = true; +@@ -2189,18 +2530,24 @@ + protected void handleNetherPortal() { + if (this.level() instanceof ServerLevel) { + int i = this.getPortalWaitTime(); +- ServerLevel serverlevel = (ServerLevel) this.level(); ++ ServerLevel worldserver = (ServerLevel) this.level(); + + if (this.isInsidePortal) { +- MinecraftServer minecraftserver = serverlevel.getServer(); +- ResourceKey resourcekey = this.level().dimension() == Level.NETHER ? Level.OVERWORLD : Level.NETHER; +- ServerLevel serverlevel1 = minecraftserver.getLevel(resourcekey); ++ MinecraftServer minecraftserver = worldserver.getServer(); ++ ResourceKey resourcekey = this.level().getTypeKey() == LevelStem.NETHER ? Level.OVERWORLD : Level.NETHER; // CraftBukkit ++ ServerLevel worldserver1 = minecraftserver.getLevel(resourcekey); + +- if (serverlevel1 != null && minecraftserver.isNetherEnabled() && !this.isPassenger() && this.portalTime++ >= i) { ++ if (true && !this.isPassenger() && this.portalTime++ >= i) { // CraftBukkit + this.level().getProfiler().push("portal"); + this.portalTime = i; + this.setPortalCooldown(); +- this.changeDimension(serverlevel1); ++ // CraftBukkit start ++ if (this instanceof ServerPlayer) { ++ ((ServerPlayer) this).changeDimension(worldserver1, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL); ++ } else { ++ this.changeDimension(worldserver1); ++ } ++ // CraftBukkit end + this.level().getProfiler().pop(); + } + +@@ -2223,21 +2570,21 @@ + return 300; + } + +- public void lerpMotion(double d0, double d1, double d2) { +- this.setDeltaMovement(d0, d1, d2); ++ public void lerpMotion(double x, double d1, double y) { ++ this.setDeltaMovement(x, d1, y); + } + +- public void handleDamageEvent(DamageSource damagesource) {} ++ public void handleDamageEvent(DamageSource damageSource) {} + +- public void handleEntityEvent(byte b0) { +- switch (b0) { ++ public void handleEntityEvent(byte id) { ++ switch (id) { + case 53: + HoneyBlock.showSlideParticles(this); + default: + } + } + +- public void animateHurt(float f) {} ++ public void animateHurt(float yaw) {} + + public Iterable getHandSlots() { + return Entity.EMPTY_LIST; +@@ -2251,7 +2598,7 @@ + return Iterables.concat(this.getHandSlots(), this.getArmorSlots()); + } + +- public void setItemSlot(EquipmentSlot equipmentslot, ItemStack itemstack) {} ++ public void setItemSlot(EquipmentSlot slot, ItemStack stack) {} + + public boolean isOnFire() { + boolean flag = this.level() != null && this.level().isClientSide; +@@ -2275,8 +2622,8 @@ + return !this.getType().is(EntityTypeTags.NON_CONTROLLING_RIDER); + } + +- public void setShiftKeyDown(boolean flag) { +- this.setSharedFlag(1, flag); ++ public void setShiftKeyDown(boolean keyDown) { ++ this.setSharedFlag(1, keyDown); + } + + public boolean isShiftKeyDown() { +@@ -2300,15 +2647,15 @@ + } + + public boolean isCrouching() { +- return this.hasPose(Pose.CROUCHING); ++ return this.hasPose(EntityPose.CROUCHING); + } + + public boolean isSprinting() { + return this.getSharedFlag(3); + } + +- public void setSprinting(boolean flag) { +- this.setSharedFlag(3, flag); ++ public void setSprinting(boolean sprinting) { ++ this.setSharedFlag(3, sprinting); + } + + public boolean isSwimming() { +@@ -2316,23 +2663,30 @@ + } + + public boolean isVisuallySwimming() { +- return this.hasPose(Pose.SWIMMING); ++ return this.hasPose(EntityPose.SWIMMING); + } + + public boolean isVisuallyCrawling() { + return this.isVisuallySwimming() && !this.isInWater(); + } + +- public void setSwimming(boolean flag) { +- this.setSharedFlag(4, flag); ++ public void setSwimming(boolean swimming) { ++ // CraftBukkit start ++ if (valid && this.isSwimming() != swimming && this instanceof net.minecraft.world.entity.LivingEntity) { ++ if (CraftEventFactory.callToggleSwimEvent((net.minecraft.world.entity.LivingEntity) this, swimming).isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ this.setSharedFlag(4, swimming); + } + + public final boolean hasGlowingTag() { + return this.hasGlowingTag; + } + +- public final void setGlowingTag(boolean flag) { +- this.hasGlowingTag = flag; ++ public final void setGlowingTag(boolean hasGlowingTag) { ++ this.hasGlowingTag = hasGlowingTag; + this.setSharedFlag(6, this.isCurrentlyGlowing()); + } + +@@ -2348,9 +2702,9 @@ + if (player.isSpectator()) { + return false; + } else { +- PlayerTeam playerteam = this.getTeam(); ++ PlayerTeam scoreboardteam = this.getTeam(); + +- return playerteam != null && player != null && player.getTeam() == playerteam && playerteam.canSeeFriendlyInvisibles() ? false : this.isInvisible(); ++ return scoreboardteam != null && player != null && player.getTeam() == scoreboardteam && scoreboardteam.canSeeFriendlyInvisibles() ? false : this.isInvisible(); + } + } + +@@ -2358,7 +2712,7 @@ + return false; + } + +- public void updateDynamicGameEventListener(BiConsumer, ServerLevel> biconsumer) {} ++ public void updateDynamicGameEventListener(BiConsumer, ServerLevel> listenerConsumer) {} + + @Nullable + public PlayerTeam getTeam() { +@@ -2373,43 +2727,58 @@ + return this.getTeam() != null ? this.getTeam().isAlliedTo(team) : false; + } + +- public void setInvisible(boolean flag) { +- this.setSharedFlag(5, flag); ++ // CraftBukkit - start ++ public void setInvisible(boolean invisible) { ++ if (!this.persistentInvisibility) { // Prevent Minecraft from removing our invisibility flag ++ this.setSharedFlag(5, invisible); ++ } ++ // CraftBukkit - end + } + +- protected boolean getSharedFlag(int i) { +- return ((Byte) this.entityData.get(Entity.DATA_SHARED_FLAGS_ID) & 1 << i) != 0; ++ public boolean getSharedFlag(int flag) { ++ return ((Byte) this.entityData.get(Entity.DATA_SHARED_FLAGS_ID) & 1 << flag) != 0; + } + +- protected void setSharedFlag(int i, boolean flag) { ++ public void setSharedFlag(int flag, boolean set) { + byte b0 = (Byte) this.entityData.get(Entity.DATA_SHARED_FLAGS_ID); + +- if (flag) { +- this.entityData.set(Entity.DATA_SHARED_FLAGS_ID, (byte) (b0 | 1 << i)); ++ if (set) { ++ this.entityData.set(Entity.DATA_SHARED_FLAGS_ID, (byte) (b0 | 1 << flag)); + } else { +- this.entityData.set(Entity.DATA_SHARED_FLAGS_ID, (byte) (b0 & ~(1 << i))); ++ this.entityData.set(Entity.DATA_SHARED_FLAGS_ID, (byte) (b0 & ~(1 << flag))); + } + + } + + public int getMaxAirSupply() { +- return 300; ++ return maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() + } + + public int getAirSupply() { + return (Integer) this.entityData.get(Entity.DATA_AIR_SUPPLY_ID); + } + +- public void setAirSupply(int i) { +- this.entityData.set(Entity.DATA_AIR_SUPPLY_ID, i); ++ public void setAirSupply(int air) { ++ // CraftBukkit start ++ EntityAirChangeEvent event = new EntityAirChangeEvent(this.getBukkitEntity(), air); ++ // Suppress during worldgen ++ if (this.valid) { ++ event.getEntity().getServer().getPluginManager().callEvent(event); ++ } ++ if (event.isCancelled() && this.getAirSupply() != air) { ++ this.entityData.markDirty(Entity.DATA_AIR_SUPPLY_ID); ++ return; ++ } ++ this.entityData.set(Entity.DATA_AIR_SUPPLY_ID, event.getAmount()); ++ // CraftBukkit end + } + + public int getTicksFrozen() { + return (Integer) this.entityData.get(Entity.DATA_TICKS_FROZEN); + } + +- public void setTicksFrozen(int i) { +- this.entityData.set(Entity.DATA_TICKS_FROZEN, i); ++ public void setTicksFrozen(int ticksFrozen) { ++ this.entityData.set(Entity.DATA_TICKS_FROZEN, ticksFrozen); + } + + public float getPercentFrozen() { +@@ -2426,43 +2795,73 @@ + return 140; + } + +- public void thunderHit(ServerLevel serverlevel, LightningBolt lightningbolt) { ++ public void thunderHit(ServerLevel level, LightningBolt lightning) { + this.setRemainingFireTicks(this.remainingFireTicks + 1); ++ // CraftBukkit start ++ final org.bukkit.entity.Entity thisBukkitEntity = this.getBukkitEntity(); ++ final org.bukkit.entity.Entity stormBukkitEntity = lightning.getBukkitEntity(); ++ final PluginManager pluginManager = Bukkit.getPluginManager(); ++ // CraftBukkit end ++ + if (this.remainingFireTicks == 0) { +- this.setSecondsOnFire(8); ++ // CraftBukkit start - Call a combust event when lightning strikes ++ EntityCombustByEntityEvent entityCombustEvent = new EntityCombustByEntityEvent(stormBukkitEntity, thisBukkitEntity, 8); ++ pluginManager.callEvent(entityCombustEvent); ++ if (!entityCombustEvent.isCancelled()) { ++ this.setSecondsOnFire(entityCombustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + +- this.hurt(this.damageSources().lightningBolt(), 5.0F); ++ // CraftBukkit start ++ if (thisBukkitEntity instanceof Hanging) { ++ HangingBreakByEntityEvent hangingEvent = new HangingBreakByEntityEvent((Hanging) thisBukkitEntity, stormBukkitEntity); ++ pluginManager.callEvent(hangingEvent); ++ ++ if (hangingEvent.isCancelled()) { ++ return; ++ } ++ } ++ ++ if (this.fireImmune()) { ++ return; ++ } ++ CraftEventFactory.entityDamage = lightning; ++ if (!this.hurt(this.damageSources().lightningBolt(), 5.0F)) { ++ CraftEventFactory.entityDamage = null; ++ return; ++ } ++ // CraftBukkit end + } + +- public void onAboveBubbleCol(boolean flag) { +- Vec3 vec3 = this.getDeltaMovement(); ++ public void onAboveBubbleCol(boolean downwards) { ++ Vec3 vec3d = this.getDeltaMovement(); + double d0; + +- if (flag) { +- d0 = Math.max(-0.9D, vec3.y - 0.03D); ++ if (downwards) { ++ d0 = Math.max(-0.9D, vec3d.y - 0.03D); + } else { +- d0 = Math.min(1.8D, vec3.y + 0.1D); ++ d0 = Math.min(1.8D, vec3d.y + 0.1D); + } + +- this.setDeltaMovement(vec3.x, d0, vec3.z); ++ this.setDeltaMovement(vec3d.x, d0, vec3d.z); + } + +- public void onInsideBubbleColumn(boolean flag) { +- Vec3 vec3 = this.getDeltaMovement(); ++ public void onInsideBubbleColumn(boolean downwards) { ++ Vec3 vec3d = this.getDeltaMovement(); + double d0; + +- if (flag) { +- d0 = Math.max(-0.3D, vec3.y - 0.03D); ++ if (downwards) { ++ d0 = Math.max(-0.3D, vec3d.y - 0.03D); + } else { +- d0 = Math.min(0.7D, vec3.y + 0.06D); ++ d0 = Math.min(0.7D, vec3d.y + 0.06D); + } + +- this.setDeltaMovement(vec3.x, d0, vec3.z); ++ this.setDeltaMovement(vec3d.x, d0, vec3d.z); + this.resetFallDistance(); + } + +- public boolean killedEntity(ServerLevel serverlevel, LivingEntity livingentity) { ++ public boolean killedEntity(ServerLevel level, net.minecraft.world.entity.LivingEntity entity) { + return true; + } + +@@ -2477,68 +2876,67 @@ + this.fallDistance = 0.0F; + } + +- protected void moveTowardsClosestSpace(double d0, double d1, double d2) { +- BlockPos blockpos = BlockPos.containing(d0, d1, d2); +- Vec3 vec3 = new Vec3(d0 - (double) blockpos.getX(), d1 - (double) blockpos.getY(), d2 - (double) blockpos.getZ()); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); +- Direction direction = Direction.UP; ++ protected void moveTowardsClosestSpace(double x, double d1, double y) { ++ BlockPos blockposition = BlockPos.containing(x, d1, y); ++ Vec3 vec3d = new Vec3(x - (double) blockposition.getX(), d1 - (double) blockposition.getY(), y - (double) blockposition.getZ()); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ Direction enumdirection = Direction.UP; + double d3 = Double.MAX_VALUE; +- Direction[] adirection = new Direction[]{Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST, Direction.UP}; +- int i = adirection.length; ++ Direction[] aenumdirection = new Direction[]{Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST, Direction.UP}; ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction1 = adirection[j]; ++ Direction enumdirection1 = aenumdirection[j]; + +- blockpos_mutableblockpos.setWithOffset(blockpos, direction1); +- if (!this.level().getBlockState(blockpos_mutableblockpos).isCollisionShapeFullBlock(this.level(), blockpos_mutableblockpos)) { +- double d4 = vec3.get(direction1.getAxis()); +- double d5 = direction1.getAxisDirection() == Direction.AxisDirection.POSITIVE ? 1.0D - d4 : d4; ++ blockposition_mutableblockposition.setWithOffset(blockposition, enumdirection1); ++ if (!this.level().getBlockState(blockposition_mutableblockposition).isCollisionShapeFullBlock(this.level(), blockposition_mutableblockposition)) { ++ double d4 = vec3d.get(enumdirection1.getAxis()); ++ double d5 = enumdirection1.getAxisDirection() == Direction.AxisDirection.POSITIVE ? 1.0D - d4 : d4; + + if (d5 < d3) { + d3 = d5; +- direction = direction1; ++ enumdirection = enumdirection1; + } + } + } + + float f = this.random.nextFloat() * 0.2F + 0.1F; +- float f1 = (float) direction.getAxisDirection().getStep(); +- Vec3 vec31 = this.getDeltaMovement().scale(0.75D); ++ float f1 = (float) enumdirection.getAxisDirection().getStep(); ++ Vec3 vec3d1 = this.getDeltaMovement().scale(0.75D); + +- if (direction.getAxis() == Direction.Axis.X) { +- this.setDeltaMovement((double) (f1 * f), vec31.y, vec31.z); +- } else if (direction.getAxis() == Direction.Axis.Y) { +- this.setDeltaMovement(vec31.x, (double) (f1 * f), vec31.z); +- } else if (direction.getAxis() == Direction.Axis.Z) { +- this.setDeltaMovement(vec31.x, vec31.y, (double) (f1 * f)); ++ if (enumdirection.getAxis() == Direction.Axis.X) { ++ this.setDeltaMovement((double) (f1 * f), vec3d1.y, vec3d1.z); ++ } else if (enumdirection.getAxis() == Direction.Axis.Y) { ++ this.setDeltaMovement(vec3d1.x, (double) (f1 * f), vec3d1.z); ++ } else if (enumdirection.getAxis() == Direction.Axis.Z) { ++ this.setDeltaMovement(vec3d1.x, vec3d1.y, (double) (f1 * f)); + } + + } + +- public void makeStuckInBlock(BlockState blockstate, Vec3 vec3) { ++ public void makeStuckInBlock(IBlockData state, Vec3 motionMultiplier) { + this.resetFallDistance(); +- this.stuckSpeedMultiplier = vec3; ++ this.stuckSpeedMultiplier = motionMultiplier; + } + +- private static Component removeAction(Component component) { +- MutableComponent mutablecomponent = component.plainCopy().setStyle(component.getStyle().withClickEvent((ClickEvent) null)); +- Iterator iterator = component.getSiblings().iterator(); ++ private static Component removeAction(Component name) { ++ MutableComponent ichatmutablecomponent = name.plainCopy().setStyle(name.getStyle().withClickEvent((ClickEvent) null)); ++ Iterator iterator = name.getSiblings().iterator(); + + while (iterator.hasNext()) { +- Component component1 = (Component) iterator.next(); ++ Component ichatbasecomponent1 = (Component) iterator.next(); + +- mutablecomponent.append(removeAction(component1)); ++ ichatmutablecomponent.append(removeAction(ichatbasecomponent1)); + } + +- return mutablecomponent; ++ return ichatmutablecomponent; + } + + @Override +- @Override + public Component getName() { +- Component component = this.getCustomName(); ++ Component ichatbasecomponent = this.getCustomName(); + +- return component != null ? removeAction(component) : this.getTypeName(); ++ return ichatbasecomponent != null ? removeAction(ichatbasecomponent) : this.getTypeName(); + } + + protected Component getTypeName() { +@@ -2553,9 +2951,9 @@ + return 0.0F; + } + +- public void setYHeadRot(float f) {} ++ public void setYHeadRot(float yHeadRot) {} + +- public void setYBodyRot(float f) {} ++ public void setYBodyRot(float yBodyRot) {} + + public boolean isAttackable() { + return true; +@@ -2565,23 +2963,22 @@ + return false; + } + +- @Override + public String toString() { + String s = this.level() == null ? "~NULL~" : this.level().toString(); + + return this.removalReason != null ? String.format(Locale.ROOT, "%s['%s'/%d, l='%s', x=%.2f, y=%.2f, z=%.2f, removed=%s]", this.getClass().getSimpleName(), this.getName().getString(), this.id, s, this.getX(), this.getY(), this.getZ(), this.removalReason) : String.format(Locale.ROOT, "%s['%s'/%d, l='%s', x=%.2f, y=%.2f, z=%.2f]", this.getClass().getSimpleName(), this.getName().getString(), this.id, s, this.getX(), this.getY(), this.getZ()); + } + +- public boolean isInvulnerableTo(DamageSource damagesource) { +- return this.isRemoved() || this.invulnerable && !damagesource.is(DamageTypeTags.BYPASSES_INVULNERABILITY) && !damagesource.isCreativePlayer() || damagesource.is(DamageTypeTags.IS_FIRE) && this.fireImmune() || damagesource.is(DamageTypeTags.IS_FALL) && this.getType().is(EntityTypeTags.FALL_DAMAGE_IMMUNE); ++ public boolean isInvulnerableTo(DamageSource source) { ++ return this.isRemoved() || this.invulnerable && !source.is(DamageTypeTags.BYPASSES_INVULNERABILITY) && !source.isCreativePlayer() || source.is(DamageTypeTags.IS_FIRE) && this.fireImmune() || source.is(DamageTypeTags.IS_FALL) && this.getType().is(EntityTypeTags.FALL_DAMAGE_IMMUNE); + } + + public boolean isInvulnerable() { + return this.invulnerable; + } + +- public void setInvulnerable(boolean flag) { +- this.invulnerable = flag; ++ public void setInvulnerable(boolean isInvulnerable) { ++ this.invulnerable = isInvulnerable; + } + + public void copyPosition(Entity entity) { +@@ -2589,42 +2986,77 @@ + } + + public void restoreFrom(Entity entity) { +- CompoundTag compoundtag = entity.saveWithoutId(new CompoundTag()); ++ CompoundTag nbttagcompound = entity.saveWithoutId(new CompoundTag()); + +- compoundtag.remove("Dimension"); +- this.load(compoundtag); ++ nbttagcompound.remove("Dimension"); ++ this.load(nbttagcompound); + this.portalCooldown = entity.portalCooldown; + this.portalEntrancePos = entity.portalEntrancePos; + } + + @Nullable +- public Entity changeDimension(ServerLevel serverlevel) { ++ public Entity changeDimension(ServerLevel destination) { ++ // CraftBukkit start ++ return teleportTo(destination, null); ++ } ++ ++ @Nullable ++ public Entity teleportTo(ServerLevel worldserver, Vec3 location) { ++ // CraftBukkit end + if (this.level() instanceof ServerLevel && !this.isRemoved()) { + this.level().getProfiler().push("changeDimension"); +- this.unRide(); ++ // CraftBukkit start ++ // this.unRide(); ++ if (worldserver == null) { ++ return null; ++ } ++ // CraftBukkit end + this.level().getProfiler().push("reposition"); +- PortalInfo portalinfo = this.findDimensionEntryPoint(serverlevel); ++ PortalInfo shapedetectorshape = (location == null) ? this.findDimensionEntryPoint(worldserver) : new PortalInfo(new Vec3(location.x(), location.y(), location.z()), Vec3.ZERO, this.yRot, this.xRot, worldserver, null); // CraftBukkit + +- if (portalinfo == null) { ++ if (shapedetectorshape == null) { + return null; + } else { ++ // CraftBukkit start ++ worldserver = shapedetectorshape.world; ++ if (worldserver == level) { ++ // SPIGOT-6782: Just move the entity if a plugin changed the world to the one the entity is already in ++ moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, shapedetectorshape.xRot); ++ setDeltaMovement(shapedetectorshape.speed); ++ return this; ++ } ++ this.unRide(); ++ // CraftBukkit end ++ + this.level().getProfiler().popPush("reloading"); +- Entity entity = this.getType().create(serverlevel); ++ Entity entity = this.getType().create(worldserver); + + if (entity != null) { + entity.restoreFrom(this); +- entity.moveTo(portalinfo.pos.x, portalinfo.pos.y, portalinfo.pos.z, portalinfo.yRot, entity.getXRot()); +- entity.setDeltaMovement(portalinfo.speed); +- serverlevel.addDuringTeleport(entity); +- if (serverlevel.dimension() == Level.END) { +- ServerLevel.makeObsidianPlatform(serverlevel); ++ entity.moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, entity.getXRot()); ++ entity.setDeltaMovement(shapedetectorshape.speed); ++ // CraftBukkit start - Don't spawn the new entity if the current entity isn't spawned ++ if (this.inWorld) { ++ worldserver.addDuringTeleport(entity); ++ if (worldserver.getTypeKey() == LevelStem.END) { // CraftBukkit ++ ServerLevel.makeObsidianPlatform(worldserver, this); // CraftBukkit ++ } + } ++ // CraftBukkit end ++ // CraftBukkit start - Forward the CraftEntity to the new entity ++ this.getBukkitEntity().setHandle(entity); ++ entity.bukkitEntity = this.getBukkitEntity(); ++ ++ if (this instanceof Mob) { ++ ((Mob) this).dropLeash(true, false); // Unleash to prevent duping of leads. ++ } ++ // CraftBukkit end + } + + this.removeAfterChangingDimensions(); + this.level().getProfiler().pop(); + ((ServerLevel) this.level()).resetEmptyTime(); +- serverlevel.resetEmptyTime(); ++ worldserver.resetEmptyTime(); + this.level().getProfiler().pop(); + return entity; + } +@@ -2638,70 +3070,105 @@ + } + + @Nullable +- protected PortalInfo findDimensionEntryPoint(ServerLevel serverlevel) { +- boolean flag = this.level().dimension() == Level.END && serverlevel.dimension() == Level.OVERWORLD; +- boolean flag1 = serverlevel.dimension() == Level.END; ++ protected PortalInfo findDimensionEntryPoint(ServerLevel destination) { ++ // CraftBukkit start ++ if (destination == null) { ++ return null; ++ } ++ boolean flag = this.level().getTypeKey() == LevelStem.END && destination.getTypeKey() == LevelStem.OVERWORLD; // fromEndToOverworld ++ boolean flag1 = destination.getTypeKey() == LevelStem.END; // targetIsEnd ++ // CraftBukkit end + + if (!flag && !flag1) { +- boolean flag2 = serverlevel.dimension() == Level.NETHER; ++ boolean flag2 = destination.getTypeKey() == LevelStem.NETHER; // CraftBukkit + +- if (this.level().dimension() != Level.NETHER && !flag2) { ++ if (this.level().getTypeKey() != LevelStem.NETHER && !flag2) { // CraftBukkit + return null; + } else { +- WorldBorder worldborder = serverlevel.getWorldBorder(); +- double d0 = DimensionType.getTeleportationScale(this.level().dimensionType(), serverlevel.dimensionType()); +- BlockPos blockpos = worldborder.clampToBounds(this.getX() * d0, this.getY(), this.getZ() * d0); ++ WorldBorder worldborder = destination.getWorldBorder(); ++ double d0 = DimensionType.getTeleportationScale(this.level().dimensionType(), destination.dimensionType()); ++ BlockPos blockposition = worldborder.clampToBounds(this.getX() * d0, this.getY(), this.getZ() * d0); ++ // CraftBukkit start ++ CraftPortalEvent event = callPortalEvent(this, destination, new Vec3(blockposition.getX(), blockposition.getY(), blockposition.getZ()), PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, flag2 ? 16 : 128, 16); ++ if (event == null) { ++ return null; ++ } ++ final ServerLevel worldserverFinal = destination = ((CraftWorld) event.getTo().getWorld()).getHandle(); ++ worldborder = worldserverFinal.getWorldBorder(); ++ blockposition = worldborder.clampToBounds(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); + +- return (PortalInfo) this.getExitPortal(serverlevel, blockpos, flag2, worldborder).map((blockutil_foundrectangle) -> { +- BlockState blockstate = this.level().getBlockState(this.portalEntrancePos); +- Direction.Axis direction_axis; +- Vec3 vec3; ++ return (PortalInfo) this.getExitPortal(destination, blockposition, flag2, worldborder, event.getSearchRadius(), event.getCanCreatePortal(), event.getCreationRadius()).map((blockutil_rectangle) -> { ++ // CraftBukkit end ++ IBlockData iblockdata = this.level().getBlockState(this.portalEntrancePos); ++ Direction.Axis enumdirection_enumaxis; ++ Vec3 vec3d; + +- if (blockstate.hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) { +- direction_axis = (Direction.Axis) blockstate.getValue(BlockStateProperties.HORIZONTAL_AXIS); +- BlockUtil.FoundRectangle blockutil_foundrectangle1 = BlockUtil.getLargestRectangleAround(this.portalEntrancePos, direction_axis, 21, Direction.Axis.Y, 21, (blockpos1) -> { +- return this.level().getBlockState(blockpos1) == blockstate; ++ if (iblockdata.hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) { ++ enumdirection_enumaxis = (Direction.Axis) iblockdata.getValue(BlockStateProperties.HORIZONTAL_AXIS); ++ BlockUtil.FoundRectangle blockutil_rectangle1 = BlockUtil.getLargestRectangleAround(this.portalEntrancePos, enumdirection_enumaxis, 21, Direction.Axis.Y, 21, (blockposition1) -> { ++ return this.level().getBlockState(blockposition1) == iblockdata; + }); + +- vec3 = this.getRelativePortalPosition(direction_axis, blockutil_foundrectangle1); ++ vec3d = this.getRelativePortalPosition(enumdirection_enumaxis, blockutil_rectangle1); + } else { +- direction_axis = Direction.Axis.X; +- vec3 = new Vec3(0.5D, 0.0D, 0.0D); ++ enumdirection_enumaxis = Direction.Axis.X; ++ vec3d = new Vec3(0.5D, 0.0D, 0.0D); + } + +- return PortalShape.createPortalInfo(serverlevel, blockutil_foundrectangle, direction_axis, vec3, this, this.getDeltaMovement(), this.getYRot(), this.getXRot()); +- }).orElse((Object) null); ++ return PortalShape.createPortalInfo(worldserverFinal, blockutil_rectangle, enumdirection_enumaxis, vec3d, this, this.getDeltaMovement(), this.getYRot(), this.getXRot(), event); // CraftBukkit ++ }).orElse(null); // CraftBukkit - decompile error + } + } else { +- BlockPos blockpos1; ++ BlockPos blockposition1; + + if (flag1) { +- blockpos1 = ServerLevel.END_SPAWN_POINT; ++ blockposition1 = ServerLevel.END_SPAWN_POINT; + } else { +- blockpos1 = serverlevel.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, serverlevel.getSharedSpawnPos()); ++ blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSharedSpawnPos()); + } ++ // CraftBukkit start ++ CraftPortalEvent event = callPortalEvent(this, destination, new Vec3(blockposition1.getX() + 0.5D, blockposition1.getY(), blockposition1.getZ() + 0.5D), PlayerTeleportEvent.TeleportCause.END_PORTAL, 0, 0); ++ if (event == null) { ++ return null; ++ } + +- return new PortalInfo(new Vec3((double) blockpos1.getX() + 0.5D, (double) blockpos1.getY(), (double) blockpos1.getZ() + 0.5D), this.getDeltaMovement(), this.getYRot(), this.getXRot()); ++ return new PortalInfo(new Vec3(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()), this.getDeltaMovement(), this.getYRot(), this.getXRot(), ((CraftWorld) event.getTo().getWorld()).getHandle(), event); ++ // CraftBukkit end + } + } + +- protected Vec3 getRelativePortalPosition(Direction.Axis direction_axis, BlockUtil.FoundRectangle blockutil_foundrectangle) { +- return PortalShape.getRelativePosition(blockutil_foundrectangle, direction_axis, this.position(), this.getDimensions(this.getPose())); ++ protected Vec3 getRelativePortalPosition(Direction.Axis axis, BlockUtil.FoundRectangle portal) { ++ return PortalShape.getRelativePosition(portal, axis, this.position(), this.getDimensions(this.getPose())); + } + +- protected Optional getExitPortal(ServerLevel serverlevel, BlockPos blockpos, boolean flag, WorldBorder worldborder) { +- return serverlevel.getPortalForcer().findPortalAround(blockpos, flag, worldborder); ++ // CraftBukkit start ++ protected CraftPortalEvent callPortalEvent(Entity entity, ServerLevel exitWorldServer, Vec3 exitPosition, PlayerTeleportEvent.TeleportCause cause, int searchRadius, int creationRadius) { ++ org.bukkit.entity.Entity bukkitEntity = entity.getBukkitEntity(); ++ Location enter = bukkitEntity.getLocation(); ++ Location exit = CraftLocation.toBukkit(exitPosition, exitWorldServer.getWorld()); ++ ++ EntityPortalEvent event = new EntityPortalEvent(bukkitEntity, enter, exit, searchRadius); ++ event.getEntity().getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null || !entity.isAlive()) { ++ return null; ++ } ++ return new CraftPortalEvent(event); + } + ++ protected Optional getExitPortal(ServerLevel worldserver, BlockPos blockposition, boolean flag, WorldBorder worldborder, int searchRadius, boolean canCreatePortal, int createRadius) { ++ return worldserver.getPortalForcer().findPortalAround(blockposition, worldborder, searchRadius); ++ // CraftBukkit end ++ } ++ + public boolean canChangeDimensions() { + return !this.isPassenger() && !this.isVehicle(); + } + +- public float getBlockExplosionResistance(Explosion explosion, BlockGetter blockgetter, BlockPos blockpos, BlockState blockstate, FluidState fluidstate, float f) { +- return f; ++ public float getBlockExplosionResistance(Explosion explosion, BlockGetter level, BlockPos pos, IBlockData blockState, FluidState fluidState, float explosionPower) { ++ return explosionPower; + } + +- public boolean shouldBlockExplode(Explosion explosion, BlockGetter blockgetter, BlockPos blockpos, BlockState blockstate, float f) { ++ public boolean shouldBlockExplode(Explosion explosion, BlockGetter level, BlockPos pos, IBlockData blockState, float explosionPower) { + return true; + } + +@@ -2713,25 +3180,25 @@ + return false; + } + +- public void fillCrashReportCategory(CrashReportCategory crashreportcategory) { +- crashreportcategory.setDetail("Entity Type", () -> { +- ResourceLocation resourcelocation = EntityType.getKey(this.getType()); ++ public void fillCrashReportCategory(CrashReportCategory category) { ++ category.setDetail("Entity Type", () -> { ++ ResourceLocation minecraftkey = EntityType.getKey(this.getType()); + +- return resourcelocation + " (" + this.getClass().getCanonicalName() + ")"; ++ return minecraftkey + " (" + this.getClass().getCanonicalName() + ")"; + }); +- crashreportcategory.setDetail("Entity ID", (Object) this.id); +- crashreportcategory.setDetail("Entity Name", () -> { ++ category.setDetail("Entity ID", (Object) this.id); ++ category.setDetail("Entity Name", () -> { + return this.getName().getString(); + }); +- crashreportcategory.setDetail("Entity's Exact location", (Object) String.format(Locale.ROOT, "%.2f, %.2f, %.2f", this.getX(), this.getY(), this.getZ())); +- crashreportcategory.setDetail("Entity's Block location", (Object) CrashReportCategory.formatLocation(this.level(), Mth.floor(this.getX()), Mth.floor(this.getY()), Mth.floor(this.getZ()))); +- Vec3 vec3 = this.getDeltaMovement(); ++ category.setDetail("Entity's Exact location", (Object) String.format(Locale.ROOT, "%.2f, %.2f, %.2f", this.getX(), this.getY(), this.getZ())); ++ category.setDetail("Entity's Block location", (Object) CrashReportCategory.formatLocation(this.level(), Mth.floor(this.getX()), Mth.floor(this.getY()), Mth.floor(this.getZ()))); ++ Vec3 vec3d = this.getDeltaMovement(); + +- crashreportcategory.setDetail("Entity's Momentum", (Object) String.format(Locale.ROOT, "%.2f, %.2f, %.2f", vec3.x, vec3.y, vec3.z)); +- crashreportcategory.setDetail("Entity's Passengers", () -> { ++ category.setDetail("Entity's Momentum", (Object) String.format(Locale.ROOT, "%.2f, %.2f, %.2f", vec3d.x, vec3d.y, vec3d.z)); ++ category.setDetail("Entity's Passengers", () -> { + return this.getPassengers().toString(); + }); +- crashreportcategory.setDetail("Entity's Vehicle", () -> { ++ category.setDetail("Entity's Vehicle", () -> { + return String.valueOf(this.getVehicle()); + }); + } +@@ -2740,13 +3207,12 @@ + return this.isOnFire() && !this.isSpectator(); + } + +- public void setUUID(UUID uuid) { +- this.uuid = uuid; ++ public void setUUID(UUID uniqueId) { ++ this.uuid = uniqueId; + this.stringUUID = this.uuid.toString(); + } + + @Override +- @Override + public UUID getUUID() { + return this.uuid; + } +@@ -2756,7 +3222,6 @@ + } + + @Override +- @Override + public String getScoreboardName() { + return this.stringUUID; + } +@@ -2769,85 +3234,92 @@ + return Entity.viewScale; + } + +- public static void setViewScale(double d0) { +- Entity.viewScale = d0; ++ public static void setViewScale(double renderDistWeight) { ++ Entity.viewScale = renderDistWeight; + } + + @Override +- @Override + public Component getDisplayName() { +- return PlayerTeam.formatNameForTeam(this.getTeam(), this.getName()).withStyle((style) -> { +- return style.withHoverEvent(this.createHoverEvent()).withInsertion(this.getStringUUID()); ++ return PlayerTeam.formatNameForTeam(this.getTeam(), this.getName()).withStyle((chatmodifier) -> { ++ return chatmodifier.withHoverEvent(this.createHoverEvent()).withInsertion(this.getStringUUID()); + }); + } + +- public void setCustomName(@Nullable Component component) { +- this.entityData.set(Entity.DATA_CUSTOM_NAME, Optional.ofNullable(component)); ++ public void setCustomName(@Nullable Component name) { ++ this.entityData.set(Entity.DATA_CUSTOM_NAME, Optional.ofNullable(name)); + } + + @Nullable + @Override +- @Override + public Component getCustomName() { + return (Component) ((Optional) this.entityData.get(Entity.DATA_CUSTOM_NAME)).orElse((Object) null); + } + + @Override +- @Override + public boolean hasCustomName() { + return ((Optional) this.entityData.get(Entity.DATA_CUSTOM_NAME)).isPresent(); + } + +- public void setCustomNameVisible(boolean flag) { +- this.entityData.set(Entity.DATA_CUSTOM_NAME_VISIBLE, flag); ++ public void setCustomNameVisible(boolean alwaysRenderNameTag) { ++ this.entityData.set(Entity.DATA_CUSTOM_NAME_VISIBLE, alwaysRenderNameTag); + } + + public boolean isCustomNameVisible() { + return (Boolean) this.entityData.get(Entity.DATA_CUSTOM_NAME_VISIBLE); + } + +- public final void teleportToWithTicket(double d0, double d1, double d2) { ++ public final void teleportToWithTicket(double x, double d1, double y) { + if (this.level() instanceof ServerLevel) { +- ChunkPos chunkpos = new ChunkPos(BlockPos.containing(d0, d1, d2)); ++ ChunkPos chunkcoordintpair = new ChunkPos(BlockPos.containing(x, d1, y)); + +- ((ServerLevel) this.level()).getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, chunkpos, 0, this.getId()); +- this.level().getChunk(chunkpos.x, chunkpos.z); +- this.teleportTo(d0, d1, d2); ++ ((ServerLevel) this.level()).getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, chunkcoordintpair, 0, this.getId()); ++ this.level().getChunk(chunkcoordintpair.x, chunkcoordintpair.z); ++ this.teleportTo(x, d1, y); + } + } + +- public boolean teleportTo(ServerLevel serverlevel, double d0, double d1, double d2, Set set, float f, float f1) { ++ // CraftBukkit start ++ public boolean teleportTo(ServerLevel worldserver, double d0, double d1, double d2, Set set, float f, float f1, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { ++ return this.teleportTo(worldserver, d0, d1, d2, set, f, f1); ++ } ++ // CraftBukkit end ++ ++ public boolean teleportTo(ServerLevel level, double x, double d1, double y, Set set, float z, float f1) { + float f2 = Mth.clamp(f1, -90.0F, 90.0F); + +- if (serverlevel == this.level()) { +- this.moveTo(d0, d1, d2, f, f2); ++ if (level == this.level()) { ++ this.moveTo(x, d1, y, z, f2); + this.teleportPassengers(); +- this.setYHeadRot(f); ++ this.setYHeadRot(z); + } else { + this.unRide(); +- Entity entity = this.getType().create(serverlevel); ++ Entity entity = this.getType().create(level); + + if (entity == null) { + return false; + } + + entity.restoreFrom(this); +- entity.moveTo(d0, d1, d2, f, f2); +- entity.setYHeadRot(f); ++ entity.moveTo(x, d1, y, z, f2); ++ entity.setYHeadRot(z); + this.setRemoved(Entity.RemovalReason.CHANGED_DIMENSION); +- serverlevel.addDuringTeleport(entity); ++ // CraftBukkit start - Don't spawn the new entity if the current entity isn't spawned ++ if (inWorld) { ++ level.addDuringTeleport(entity); ++ } ++ // CraftBukkit end + } + + return true; + } + +- public void dismountTo(double d0, double d1, double d2) { +- this.teleportTo(d0, d1, d2); ++ public void dismountTo(double x, double d1, double y) { ++ this.teleportTo(x, d1, y); + } + +- public void teleportTo(double d0, double d1, double d2) { ++ public void teleportTo(double x, double d1, double y) { + if (this.level() instanceof ServerLevel) { +- this.moveTo(d0, d1, d2, this.getYRot(), this.getXRot()); ++ this.moveTo(x, d1, y, this.getYRot(), this.getXRot()); + this.teleportPassengers(); + } + } +@@ -2865,18 +3337,18 @@ + }); + } + +- public void teleportRelative(double d0, double d1, double d2) { +- this.teleportTo(this.getX() + d0, this.getY() + d1, this.getZ() + d2); ++ public void teleportRelative(double dx, double d1, double dy) { ++ this.teleportTo(this.getX() + dx, this.getY() + d1, this.getZ() + dy); + } + + public boolean shouldShowName() { + return this.isCustomNameVisible(); + } + +- public void onSyncedDataUpdated(List> list) {} ++ public void onSyncedDataUpdated(List> dataValues) {} + +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- if (Entity.DATA_POSE.equals(entitydataaccessor)) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ if (Entity.DATA_POSE.equals(key)) { + this.refreshDimensions(); + } + +@@ -2885,31 +3357,31 @@ + /** @deprecated */ + @Deprecated + protected void fixupDimensions() { +- Pose pose = this.getPose(); +- EntityDimensions entitydimensions = this.getDimensions(pose); ++ EntityPose entitypose = this.getPose(); ++ EntityDimensions entitysize = this.getDimensions(entitypose); + +- this.dimensions = entitydimensions; +- this.eyeHeight = this.getEyeHeight(pose, entitydimensions); ++ this.dimensions = entitysize; ++ this.eyeHeight = this.getEyeHeight(entitypose, entitysize); + } + + public void refreshDimensions() { +- EntityDimensions entitydimensions = this.dimensions; +- Pose pose = this.getPose(); +- EntityDimensions entitydimensions1 = this.getDimensions(pose); ++ EntityDimensions entitysize = this.dimensions; ++ EntityPose entitypose = this.getPose(); ++ EntityDimensions entitysize1 = this.getDimensions(entitypose); + +- this.dimensions = entitydimensions1; +- this.eyeHeight = this.getEyeHeight(pose, entitydimensions1); ++ this.dimensions = entitysize1; ++ this.eyeHeight = this.getEyeHeight(entitypose, entitysize1); + this.reapplyPosition(); +- boolean flag = (double) entitydimensions1.width <= 4.0D && (double) entitydimensions1.height <= 4.0D; ++ boolean flag = (double) entitysize1.width <= 4.0D && (double) entitysize1.height <= 4.0D; + +- if (!this.level().isClientSide && !this.firstTick && !this.noPhysics && flag && (entitydimensions1.width > entitydimensions.width || entitydimensions1.height > entitydimensions.height) && !(this instanceof Player)) { +- Vec3 vec3 = this.position().add(0.0D, (double) entitydimensions.height / 2.0D, 0.0D); +- double d0 = (double) Math.max(0.0F, entitydimensions1.width - entitydimensions.width) + 1.0E-6D; +- double d1 = (double) Math.max(0.0F, entitydimensions1.height - entitydimensions.height) + 1.0E-6D; +- VoxelShape voxelshape = Shapes.create(AABB.ofSize(vec3, d0, d1, d0)); ++ if (!this.level().isClientSide && !this.firstTick && !this.noPhysics && flag && (entitysize1.width > entitysize.width || entitysize1.height > entitysize.height) && !(this instanceof Player)) { ++ Vec3 vec3d = this.position().add(0.0D, (double) entitysize.height / 2.0D, 0.0D); ++ double d0 = (double) Math.max(0.0F, entitysize1.width - entitysize.width) + 1.0E-6D; ++ double d1 = (double) Math.max(0.0F, entitysize1.height - entitysize.height) + 1.0E-6D; ++ VoxelShape voxelshape = Shapes.create(AABB.ofSize(vec3d, d0, d1, d0)); + +- this.level().findFreePosition(this, voxelshape, vec3, (double) entitydimensions1.width, (double) entitydimensions1.height, (double) entitydimensions1.width).ifPresent((vec31) -> { +- this.setPos(vec31.add(0.0D, (double) (-entitydimensions1.height) / 2.0D, 0.0D)); ++ this.level().findFreePosition(this, voxelshape, vec3d, (double) entitysize1.width, (double) entitysize1.height, (double) entitysize1.width).ifPresent((vec3d1) -> { ++ this.setPos(vec3d1.add(0.0D, (double) (-entitysize1.height) / 2.0D, 0.0D)); + }); + } + +@@ -2927,12 +3399,11 @@ + return new HoverEvent(HoverEvent.Action.SHOW_ENTITY, new HoverEvent.EntityTooltipInfo(this.getType(), this.getUUID(), this.getName())); + } + +- public boolean broadcastToPlayer(ServerPlayer serverplayer) { ++ public boolean broadcastToPlayer(ServerPlayer player) { + return true; + } + + @Override +- @Override + public final AABB getBoundingBox() { + return this.bb; + } +@@ -2941,15 +3412,34 @@ + return this.getBoundingBox(); + } + +- public final void setBoundingBox(AABB aabb) { +- this.bb = aabb; ++ public final void setBoundingBox(AABB bb) { ++ // CraftBukkit start - block invalid bounding boxes ++ double minX = bb.minX, ++ minY = bb.minY, ++ minZ = bb.minZ, ++ maxX = bb.maxX, ++ maxY = bb.maxY, ++ maxZ = bb.maxZ; ++ double len = bb.maxX - bb.minX; ++ if (len < 0) maxX = minX; ++ if (len > 64) maxX = minX + 64.0; ++ ++ len = bb.maxY - bb.minY; ++ if (len < 0) maxY = minY; ++ if (len > 64) maxY = minY + 64.0; ++ ++ len = bb.maxZ - bb.minZ; ++ if (len < 0) maxZ = minZ; ++ if (len > 64) maxZ = minZ + 64.0; ++ this.bb = new AABB(minX, minY, minZ, maxX, maxY, maxZ); ++ // CraftBukkit end + } + +- protected float getEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return entitydimensions.height * 0.85F; ++ protected float getEyeHeight(EntityPose pose, EntityDimensions dimensions) { ++ return dimensions.height * 0.85F; + } + +- public float getEyeHeight(Pose pose) { ++ public float getEyeHeight(EntityPose pose) { + return this.getEyeHeight(pose, this.getDimensions(pose)); + } + +@@ -2957,7 +3447,7 @@ + return this.eyeHeight; + } + +- public Vec3 getLeashOffset(float f) { ++ public Vec3 getLeashOffset(float partialTick) { + return this.getLeashOffset(); + } + +@@ -2965,12 +3455,11 @@ + return new Vec3(0.0D, (double) this.getEyeHeight(), (double) (this.getBbWidth() * 0.4F)); + } + +- public SlotAccess getSlot(int i) { ++ public SlotAccess getSlot(int slot) { + return SlotAccess.NULL; + } + + @Override +- @Override + public void sendSystemMessage(Component component) {} + + public Level getCommandSenderWorld() { +@@ -2982,7 +3471,7 @@ + return this.level().getServer(); + } + +- public InteractionResult interactAt(Player player, Vec3 vec3, InteractionHand interactionhand) { ++ public InteractionResult interactAt(Player player, Vec3 vec, EnumHand hand) { + return InteractionResult.PASS; + } + +@@ -2990,22 +3479,22 @@ + return false; + } + +- public void doEnchantDamageEffects(LivingEntity livingentity, Entity entity) { +- if (entity instanceof LivingEntity) { +- EnchantmentHelper.doPostHurtEffects((LivingEntity) entity, livingentity); ++ public void doEnchantDamageEffects(net.minecraft.world.entity.LivingEntity attacker, Entity target) { ++ if (target instanceof net.minecraft.world.entity.LivingEntity) { ++ EnchantmentHelper.doPostHurtEffects((net.minecraft.world.entity.LivingEntity) target, attacker); + } + +- EnchantmentHelper.doPostDamageEffects(livingentity, entity); ++ EnchantmentHelper.doPostDamageEffects(attacker, target); + } + +- public void startSeenByPlayer(ServerPlayer serverplayer) {} ++ public void startSeenByPlayer(ServerPlayer serverPlayer) {} + +- public void stopSeenByPlayer(ServerPlayer serverplayer) {} ++ public void stopSeenByPlayer(ServerPlayer serverPlayer) {} + +- public float rotate(Rotation rotation) { ++ public float rotate(Rotation transformRotation) { + float f = Mth.wrapDegrees(this.getYRot()); + +- switch (rotation) { ++ switch (transformRotation) { + case CLOCKWISE_180: + return f + 180.0F; + case COUNTERCLOCKWISE_90: +@@ -3017,10 +3506,10 @@ + } + } + +- public float mirror(Mirror mirror) { ++ public float mirror(Mirror transformMirror) { + float f = Mth.wrapDegrees(this.getYRot()); + +- switch (mirror) { ++ switch (transformMirror) { + case FRONT_BACK: + return -f; + case LEFT_RIGHT: +@@ -3035,7 +3524,7 @@ + } + + @Nullable +- public LivingEntity getControllingPassenger() { ++ public net.minecraft.world.entity.LivingEntity getControllingPassenger() { + return null; + } + +@@ -3077,13 +3566,11 @@ + } + + @Override +- @Override + public Stream getSelfAndPassengers() { + return Stream.concat(Stream.of(this), this.getIndirectPassengersStream()); + } + + @Override +- @Override + public Stream getPassengersAndSelf() { + return Stream.concat(this.passengers.stream().flatMap(Entity::getPassengersAndSelf), Stream.of(this)); + } +@@ -3129,12 +3616,12 @@ + } + + public boolean isControlledByLocalInstance() { +- LivingEntity livingentity = this.getControllingPassenger(); ++ net.minecraft.world.entity.LivingEntity entityliving = this.getControllingPassenger(); + +- if (livingentity instanceof Player) { +- Player player = (Player) livingentity; ++ if (entityliving instanceof Player) { ++ Player entityhuman = (Player) entityliving; + +- return player.isLocalPlayer(); ++ return entityhuman.isLocalPlayer(); + } else { + return this.isEffectiveAi(); + } +@@ -3144,16 +3631,16 @@ + return !this.level().isClientSide; + } + +- protected static Vec3 getCollisionHorizontalEscapeVector(double d0, double d1, float f) { +- double d2 = (d0 + d1 + 9.999999747378752E-6D) / 2.0D; +- float f1 = -Mth.sin(f * 0.017453292F); +- float f2 = Mth.cos(f * 0.017453292F); ++ protected static Vec3 getCollisionHorizontalEscapeVector(double vehicleWidth, double d1, float passengerWidth) { ++ double d2 = (vehicleWidth + d1 + 9.999999747378752E-6D) / 2.0D; ++ float f1 = -Mth.sin(passengerWidth * 0.017453292F); ++ float f2 = Mth.cos(passengerWidth * 0.017453292F); + float f3 = Math.max(Math.abs(f1), Math.abs(f2)); + + return new Vec3((double) f1 * d2 / (double) f3, 0.0D, (double) f2 * d2 / (double) f3); + } + +- public Vec3 getDismountLocationForPassenger(LivingEntity livingentity) { ++ public Vec3 getDismountLocationForPassenger(net.minecraft.world.entity.LivingEntity passenger) { + return new Vec3(this.getX(), this.getBoundingBox().maxY, this.getZ()); + } + +@@ -3167,15 +3654,15 @@ + return this.vehicle != null && this.vehicle.getControllingPassenger() == this ? this.vehicle : null; + } + +- public PushReaction getPistonPushReaction() { +- return PushReaction.NORMAL; ++ public EnumPistonReaction getPistonPushReaction() { ++ return EnumPistonReaction.NORMAL; + } + + public SoundSource getSoundSource() { + return SoundSource.NEUTRAL; + } + +- protected int getFireImmuneTicks() { ++ public int getFireImmuneTicks() { + return 1; + } + +@@ -3187,33 +3674,30 @@ + return 0; + } + +- public boolean hasPermissions(int i) { +- return this.getPermissionLevel() >= i; ++ public boolean hasPermissions(int level) { ++ return this.getPermissionLevel() >= level; + } + + @Override +- @Override + public boolean acceptsSuccess() { + return this.level().getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK); + } + + @Override +- @Override + public boolean acceptsFailure() { + return true; + } + + @Override +- @Override + public boolean shouldInformAdmins() { + return true; + } + +- public void lookAt(EntityAnchorArgument.Anchor entityanchorargument_anchor, Vec3 vec3) { +- Vec3 vec31 = entityanchorargument_anchor.apply(this); +- double d0 = vec3.x - vec31.x; +- double d1 = vec3.y - vec31.y; +- double d2 = vec3.z - vec31.z; ++ public void lookAt(EntityAnchorArgument.Anchor anchor, Vec3 target) { ++ Vec3 vec3d1 = anchor.apply(this); ++ double d0 = target.x - vec3d1.x; ++ double d1 = target.y - vec3d1.y; ++ double d2 = target.z - vec3d1.z; + double d3 = Math.sqrt(d0 * d0 + d2 * d2); + + this.setXRot(Mth.wrapDegrees((float) (-(Mth.atan2(d1, d3) * 57.2957763671875D)))); +@@ -3223,90 +3707,95 @@ + this.yRotO = this.getYRot(); + } + +- public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { ++ public boolean updateFluidHeightAndDoFluidPushing(TagKey fluidTag, double motionScale) { + if (this.touchingUnloadedChunk()) { + return false; + } else { +- AABB aabb = this.getBoundingBox().deflate(0.001D); +- int i = Mth.floor(aabb.minX); +- int j = Mth.ceil(aabb.maxX); +- int k = Mth.floor(aabb.minY); +- int l = Mth.ceil(aabb.maxY); +- int i1 = Mth.floor(aabb.minZ); +- int j1 = Mth.ceil(aabb.maxZ); ++ AABB axisalignedbb = this.getBoundingBox().deflate(0.001D); ++ int i = Mth.floor(axisalignedbb.minX); ++ int j = Mth.ceil(axisalignedbb.maxX); ++ int k = Mth.floor(axisalignedbb.minY); ++ int l = Mth.ceil(axisalignedbb.maxY); ++ int i1 = Mth.floor(axisalignedbb.minZ); ++ int j1 = Mth.ceil(axisalignedbb.maxZ); + double d1 = 0.0D; + boolean flag = this.isPushedByFluid(); + boolean flag1 = false; +- Vec3 vec3 = Vec3.ZERO; ++ Vec3 vec3d = Vec3.ZERO; + int k1 = 0; +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + + for (int l1 = i; l1 < j; ++l1) { + for (int i2 = k; i2 < l; ++i2) { + for (int j2 = i1; j2 < j1; ++j2) { +- blockpos_mutableblockpos.set(l1, i2, j2); +- FluidState fluidstate = this.level().getFluidState(blockpos_mutableblockpos); ++ blockposition_mutableblockposition.set(l1, i2, j2); ++ FluidState fluid = this.level().getFluidState(blockposition_mutableblockposition); + +- if (fluidstate.is(tagkey)) { +- double d2 = (double) ((float) i2 + fluidstate.getHeight(this.level(), blockpos_mutableblockpos)); ++ if (fluid.is(fluidTag)) { ++ double d2 = (double) ((float) i2 + fluid.getHeight(this.level(), blockposition_mutableblockposition)); + +- if (d2 >= aabb.minY) { ++ if (d2 >= axisalignedbb.minY) { + flag1 = true; +- d1 = Math.max(d2 - aabb.minY, d1); ++ d1 = Math.max(d2 - axisalignedbb.minY, d1); + if (flag) { +- Vec3 vec31 = fluidstate.getFlow(this.level(), blockpos_mutableblockpos); ++ Vec3 vec3d1 = fluid.getFlow(this.level(), blockposition_mutableblockposition); + + if (d1 < 0.4D) { +- vec31 = vec31.scale(d1); ++ vec3d1 = vec3d1.scale(d1); + } + +- vec3 = vec3.add(vec31); ++ vec3d = vec3d.add(vec3d1); + ++k1; + } ++ // CraftBukkit start - store last lava contact location ++ if (fluidTag == FluidTags.LAVA) { ++ this.lastLavaContact = blockposition_mutableblockposition.immutable(); ++ } ++ // CraftBukkit end + } + } + } + } + } + +- if (vec3.length() > 0.0D) { ++ if (vec3d.length() > 0.0D) { + if (k1 > 0) { +- vec3 = vec3.scale(1.0D / (double) k1); ++ vec3d = vec3d.scale(1.0D / (double) k1); + } + + if (!(this instanceof Player)) { +- vec3 = vec3.normalize(); ++ vec3d = vec3d.normalize(); + } + +- Vec3 vec32 = this.getDeltaMovement(); ++ Vec3 vec3d2 = this.getDeltaMovement(); + +- vec3 = vec3.scale(d0 * 1.0D); ++ vec3d = vec3d.scale(motionScale * 1.0D); + double d3 = 0.003D; + +- if (Math.abs(vec32.x) < 0.003D && Math.abs(vec32.z) < 0.003D && vec3.length() < 0.0045000000000000005D) { +- vec3 = vec3.normalize().scale(0.0045000000000000005D); ++ if (Math.abs(vec3d2.x) < 0.003D && Math.abs(vec3d2.z) < 0.003D && vec3d.length() < 0.0045000000000000005D) { ++ vec3d = vec3d.normalize().scale(0.0045000000000000005D); + } + +- this.setDeltaMovement(this.getDeltaMovement().add(vec3)); ++ this.setDeltaMovement(this.getDeltaMovement().add(vec3d)); + } + +- this.fluidHeight.put(tagkey, d1); ++ this.fluidHeight.put(fluidTag, d1); + return flag1; + } + } + + public boolean touchingUnloadedChunk() { +- AABB aabb = this.getBoundingBox().inflate(1.0D); +- int i = Mth.floor(aabb.minX); +- int j = Mth.ceil(aabb.maxX); +- int k = Mth.floor(aabb.minZ); +- int l = Mth.ceil(aabb.maxZ); ++ AABB axisalignedbb = this.getBoundingBox().inflate(1.0D); ++ int i = Mth.floor(axisalignedbb.minX); ++ int j = Mth.ceil(axisalignedbb.maxX); ++ int k = Mth.floor(axisalignedbb.minZ); ++ int l = Mth.ceil(axisalignedbb.maxZ); + + return !this.level().hasChunksAt(i, k, j, l); + } + +- public double getFluidHeight(TagKey tagkey) { +- return this.fluidHeight.getDouble(tagkey); ++ public double getFluidHeight(TagKey fluidTag) { ++ return this.fluidHeight.getDouble(fluidTag); + } + + public double getFluidJumpThreshold() { +@@ -3329,7 +3818,7 @@ + return new ClientboundAddEntityPacket(this); + } + +- public EntityDimensions getDimensions(Pose pose) { ++ public EntityDimensions getDimensions(EntityPose pose) { + return this.type.getDimensions(); + } + +@@ -3342,12 +3831,11 @@ + } + + @Override +- @Override + public BlockPos blockPosition() { + return this.blockPosition; + } + +- public BlockState getFeetBlockState() { ++ public IBlockData getFeetBlockState() { + if (this.feetBlockState == null) { + this.feetBlockState = this.level().getBlockState(this.blockPosition()); + } +@@ -3363,16 +3851,16 @@ + return this.deltaMovement; + } + +- public void setDeltaMovement(Vec3 vec3) { +- this.deltaMovement = vec3; ++ public void setDeltaMovement(Vec3 deltaMovement) { ++ this.deltaMovement = deltaMovement; + } + +- public void addDeltaMovement(Vec3 vec3) { +- this.setDeltaMovement(this.getDeltaMovement().add(vec3)); ++ public void addDeltaMovement(Vec3 addend) { ++ this.setDeltaMovement(this.getDeltaMovement().add(addend)); + } + +- public void setDeltaMovement(double d0, double d1, double d2) { +- this.setDeltaMovement(new Vec3(d0, d1, d2)); ++ public void setDeltaMovement(double x, double d1, double y) { ++ this.setDeltaMovement(new Vec3(x, d1, y)); + } + + public final int getBlockX() { +@@ -3383,12 +3871,12 @@ + return this.position.x; + } + +- public double getX(double d0) { +- return this.position.x + (double) this.getBbWidth() * d0; ++ public double getX(double scale) { ++ return this.position.x + (double) this.getBbWidth() * scale; + } + +- public double getRandomX(double d0) { +- return this.getX((2.0D * this.random.nextDouble() - 1.0D) * d0); ++ public double getRandomX(double scale) { ++ return this.getX((2.0D * this.random.nextDouble() - 1.0D) * scale); + } + + public final int getBlockY() { +@@ -3399,8 +3887,8 @@ + return this.position.y; + } + +- public double getY(double d0) { +- return this.position.y + (double) this.getBbHeight() * d0; ++ public double getY(double scale) { ++ return this.position.y + (double) this.getBbHeight() * scale; + } + + public double getRandomY() { +@@ -3419,20 +3907,20 @@ + return this.position.z; + } + +- public double getZ(double d0) { +- return this.position.z + (double) this.getBbWidth() * d0; ++ public double getZ(double scale) { ++ return this.position.z + (double) this.getBbWidth() * scale; + } + +- public double getRandomZ(double d0) { +- return this.getZ((2.0D * this.random.nextDouble() - 1.0D) * d0); ++ public double getRandomZ(double scale) { ++ return this.getZ((2.0D * this.random.nextDouble() - 1.0D) * scale); + } + +- public final void setPosRaw(double d0, double d1, double d2) { +- if (this.position.x != d0 || this.position.y != d1 || this.position.z != d2) { +- this.position = new Vec3(d0, d1, d2); +- int i = Mth.floor(d0); ++ public final void setPosRaw(double x, double d1, double y) { ++ if (this.position.x != x || this.position.y != d1 || this.position.z != y) { ++ this.position = new Vec3(x, d1, y); ++ int i = Mth.floor(x); + int j = Mth.floor(d1); +- int k = Mth.floor(d2); ++ int k = Mth.floor(y); + + if (i != this.blockPosition.getX() || j != this.blockPosition.getY() || k != this.blockPosition.getZ()) { + this.blockPosition = new BlockPos(i, j, k); +@@ -3449,22 +3937,22 @@ + + public void checkDespawn() {} + +- public Vec3 getRopeHoldPosition(float f) { +- return this.getPosition(f).add(0.0D, (double) this.eyeHeight * 0.7D, 0.0D); ++ public Vec3 getRopeHoldPosition(float partialTicks) { ++ return this.getPosition(partialTicks).add(0.0D, (double) this.eyeHeight * 0.7D, 0.0D); + } + +- public void recreateFromPacket(ClientboundAddEntityPacket clientboundaddentitypacket) { +- int i = clientboundaddentitypacket.getId(); +- double d0 = clientboundaddentitypacket.getX(); +- double d1 = clientboundaddentitypacket.getY(); +- double d2 = clientboundaddentitypacket.getZ(); ++ public void recreateFromPacket(ClientboundAddEntityPacket packet) { ++ int i = packet.getId(); ++ double d0 = packet.getX(); ++ double d1 = packet.getY(); ++ double d2 = packet.getZ(); + + this.syncPacketPositionCodec(d0, d1, d2); + this.moveTo(d0, d1, d2); +- this.setXRot(clientboundaddentitypacket.getXRot()); +- this.setYRot(clientboundaddentitypacket.getYRot()); ++ this.setXRot(packet.getXRot()); ++ this.setYRot(packet.getYRot()); + this.setId(i); +- this.setUUID(clientboundaddentitypacket.getUUID()); ++ this.setUUID(packet.getUUID()); + } + + @Nullable +@@ -3472,8 +3960,8 @@ + return null; + } + +- public void setIsInPowderSnow(boolean flag) { +- this.isInPowderSnow = flag; ++ public void setIsInPowderSnow(boolean isInPowderSnow) { ++ this.isInPowderSnow = isInPowderSnow; + } + + public boolean canFreeze() { +@@ -3492,11 +3980,11 @@ + return this.getYRot(); + } + +- public void setYRot(float f) { +- if (!Float.isFinite(f)) { +- Util.logAndPauseIfInIde("Invalid entity rotation: " + f + ", discarding."); ++ public void setYRot(float yRot) { ++ if (!Float.isFinite(yRot)) { ++ Util.logAndPauseIfInIde("Invalid entity rotation: " + yRot + ", discarding."); + } else { +- this.yRot = f; ++ this.yRot = yRot; + } + } + +@@ -3504,11 +3992,11 @@ + return this.xRot; + } + +- public void setXRot(float f) { +- if (!Float.isFinite(f)) { +- Util.logAndPauseIfInIde("Invalid entity rotation: " + f + ", discarding."); ++ public void setXRot(float xRot) { ++ if (!Float.isFinite(xRot)) { ++ Util.logAndPauseIfInIde("Invalid entity rotation: " + xRot + ", discarding."); + } else { +- this.xRot = f; ++ this.xRot = xRot; + } + } + +@@ -3520,8 +4008,8 @@ + return this.maxUpStep; + } + +- public void setMaxUpStep(float f) { +- this.maxUpStep = f; ++ public void setMaxUpStep(float maxUpStep) { ++ this.maxUpStep = maxUpStep; + } + + public final boolean isRemoved() { +@@ -3534,10 +4022,9 @@ + } + + @Override +- @Override +- public final void setRemoved(Entity.RemovalReason entity_removalreason) { ++ public final void setRemoved(Entity.RemovalReason removalReason) { + if (this.removalReason == null) { +- this.removalReason = entity_removalreason; ++ this.removalReason = removalReason; + } + + if (this.removalReason.shouldDestroy()) { +@@ -3545,32 +4032,29 @@ + } + + this.getPassengers().forEach(Entity::stopRiding); +- this.levelCallback.onRemove(entity_removalreason); ++ this.levelCallback.onRemove(removalReason); + } + +- protected void unsetRemoved() { ++ public void unsetRemoved() { + this.removalReason = null; + } + + @Override +- @Override +- public void setLevelCallback(EntityInLevelCallback entityinlevelcallback) { +- this.levelCallback = entityinlevelcallback; ++ public void setLevelCallback(EntityInLevelCallback levelCallback) { ++ this.levelCallback = levelCallback; + } + + @Override +- @Override + public boolean shouldBeSaved() { + return this.removalReason != null && !this.removalReason.shouldSave() ? false : (this.isPassenger() ? false : !this.isVehicle() || !this.hasExactlyOnePlayerPassenger()); + } + + @Override +- @Override + public boolean isAlwaysTicking() { + return false; + } + +- public boolean mayInteract(Level level, BlockPos blockpos) { ++ public boolean mayInteract(Level level, BlockPos pos) { + return true; + } + +@@ -3647,6 +4131,6 @@ + @FunctionalInterface + public interface MoveFunction { + +- void accept(Entity entity, double x, double d, double y); ++ void accept(Entity entity, double x, double d1, double y); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/EntitySelector.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/EntitySelector.java.patch new file mode 100644 index 0000000000..45bfd4506f --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/EntitySelector.java.patch @@ -0,0 +1,72 @@ +--- a/net/minecraft/world/entity/EntitySelector.java ++++ b/net/minecraft/world/entity/EntitySelector.java +@@ -31,33 +31,33 @@ + + private EntitySelector() {} + +- public static Predicate withinDistance(double d0, double d1, double d2, double d3) { ++ public static Predicate withinDistance(double x, double d1, double y, double d3) { + double d4 = d3 * d3; + + return (entity) -> { +- return entity != null && entity.distanceToSqr(d0, d1, d2) <= d4; ++ return entity != null && entity.distanceToSqr(x, d1, y) <= d4; + }; + } + + public static Predicate pushableBy(Entity entity) { +- PlayerTeam playerteam = entity.getTeam(); +- Team.CollisionRule team_collisionrule = playerteam == null ? Team.CollisionRule.ALWAYS : playerteam.getCollisionRule(); ++ PlayerTeam scoreboardteam = entity.getTeam(); ++ Team.CollisionRule scoreboardteambase_enumteampush = scoreboardteam == null ? Team.CollisionRule.ALWAYS : scoreboardteam.getCollisionRule(); + +- return (Predicate) (team_collisionrule == Team.CollisionRule.NEVER ? Predicates.alwaysFalse() : EntitySelector.NO_SPECTATORS.and((entity1) -> { +- if (!entity1.isPushable()) { ++ return (Predicate) (scoreboardteambase_enumteampush == Team.CollisionRule.NEVER ? Predicates.alwaysFalse() : EntitySelector.NO_SPECTATORS.and((entity1) -> { ++ if (!entity1.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(entity1)) { // CraftBukkit - collidable API + return false; + } else if (entity.level().isClientSide && (!(entity1 instanceof Player) || !((Player) entity1).isLocalPlayer())) { + return false; + } else { +- PlayerTeam playerteam1 = entity1.getTeam(); +- Team.CollisionRule team_collisionrule1 = playerteam1 == null ? Team.CollisionRule.ALWAYS : playerteam1.getCollisionRule(); ++ PlayerTeam scoreboardteam1 = entity1.getTeam(); ++ Team.CollisionRule scoreboardteambase_enumteampush1 = scoreboardteam1 == null ? Team.CollisionRule.ALWAYS : scoreboardteam1.getCollisionRule(); + +- if (team_collisionrule1 == Team.CollisionRule.NEVER) { ++ if (scoreboardteambase_enumteampush1 == Team.CollisionRule.NEVER) { + return false; + } else { +- boolean flag = playerteam != null && playerteam.isAlliedTo(playerteam1); ++ boolean flag = scoreboardteam != null && scoreboardteam.isAlliedTo(scoreboardteam1); + +- return (team_collisionrule == Team.CollisionRule.PUSH_OWN_TEAM || team_collisionrule1 == Team.CollisionRule.PUSH_OWN_TEAM) && flag ? false : team_collisionrule != Team.CollisionRule.PUSH_OTHER_TEAMS && team_collisionrule1 != Team.CollisionRule.PUSH_OTHER_TEAMS || flag; ++ return (scoreboardteambase_enumteampush == Team.CollisionRule.PUSH_OWN_TEAM || scoreboardteambase_enumteampush1 == Team.CollisionRule.PUSH_OWN_TEAM) && flag ? false : scoreboardteambase_enumteampush != Team.CollisionRule.PUSH_OTHER_TEAMS && scoreboardteambase_enumteampush1 != Team.CollisionRule.PUSH_OTHER_TEAMS || flag; + } + } + })); +@@ -84,20 +84,19 @@ + + private final ItemStack itemStack; + +- public MobCanWearArmorEntitySelector(ItemStack itemstack) { +- this.itemStack = itemstack; ++ public MobCanWearArmorEntitySelector(ItemStack stack) { ++ this.itemStack = stack; + } + +- @Override + public boolean test(@Nullable Entity entity) { + if (!entity.isAlive()) { + return false; + } else if (!(entity instanceof LivingEntity)) { + return false; + } else { +- LivingEntity livingentity = (LivingEntity) entity; ++ LivingEntity entityliving = (LivingEntity) entity; + +- return livingentity.canTakeItem(this.itemStack); ++ return entityliving.canTakeItem(this.itemStack); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/EntityType.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/EntityType.java.patch new file mode 100644 index 0000000000..42fdbf9a00 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/EntityType.java.patch @@ -0,0 +1,517 @@ +--- a/net/minecraft/world/entity/EntityType.java ++++ b/net/minecraft/world/entity/EntityType.java +@@ -27,7 +27,7 @@ + import net.minecraft.server.level.ServerLevel; + import net.minecraft.tags.TagKey; + import net.minecraft.util.Mth; +-import net.minecraft.util.datafix.fixes.References; ++import net.minecraft.util.datafix.fixes.DataConverterTypes; + import net.minecraft.world.entity.ambient.Bat; + import net.minecraft.world.entity.animal.Bee; + import net.minecraft.world.entity.animal.Cat; +@@ -154,12 +154,13 @@ + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.entity.EntityTypeTest; + import net.minecraft.world.level.pathfinder.WalkNodeEvaluator; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.entity.CreatureSpawnEvent; + import org.slf4j.Logger; + + public class EntityType implements FeatureElement, EntityTypeTest { +@@ -170,7 +171,7 @@ + private static final float MAGIC_HORSE_WIDTH = 1.3964844F; + private static final int DISPLAY_TRACKING_RANGE = 10; + public static final EntityType ALLAY = register("allay", EntityType.Builder.of(Allay::new, MobCategory.CREATURE).sized(0.35F, 0.6F).clientTrackingRange(8).updateInterval(2)); +- public static final EntityType AREA_EFFECT_CLOUD = register("area_effect_cloud", EntityType.Builder.of(AreaEffectCloud::new, MobCategory.MISC).fireImmune().sized(6.0F, 0.5F).clientTrackingRange(10).updateInterval(Integer.MAX_VALUE)); ++ public static final EntityType AREA_EFFECT_CLOUD = register("area_effect_cloud", EntityType.Builder.of(AreaEffectCloud::new, MobCategory.MISC).fireImmune().sized(6.0F, 0.5F).clientTrackingRange(10).updateInterval(10)); // CraftBukkit - SPIGOT-3729: track area effect clouds + public static final EntityType ARMOR_STAND = register("armor_stand", EntityType.Builder.of(ArmorStand::new, MobCategory.MISC).sized(0.5F, 1.975F).clientTrackingRange(10)); + public static final EntityType ARROW = register("arrow", EntityType.Builder.of(Arrow::new, MobCategory.MISC).sized(0.5F, 0.5F).clientTrackingRange(4).updateInterval(20)); + public static final EntityType AXOLOTL = register("axolotl", EntityType.Builder.of(Axolotl::new, MobCategory.AXOLOTLS).sized(0.75F, 0.42F).clientTrackingRange(10)); +@@ -313,113 +314,136 @@ + private final EntityDimensions dimensions; + private final FeatureFlagSet requiredFeatures; + +- private static EntityType register(String s, EntityType.Builder entitytype_builder) { +- return (EntityType) Registry.register(BuiltInRegistries.ENTITY_TYPE, s, entitytype_builder.build(s)); ++ private static EntityType register(String key, EntityType.Builder builder) { // CraftBukkit - decompile error ++ return (EntityType) Registry.register(BuiltInRegistries.ENTITY_TYPE, key, (EntityType) builder.build(key)); // CraftBukkit - decompile error + } + +- public static ResourceLocation getKey(EntityType entitytype) { +- return BuiltInRegistries.ENTITY_TYPE.getKey(entitytype); ++ public static ResourceLocation getKey(EntityType entityType) { ++ return BuiltInRegistries.ENTITY_TYPE.getKey(entityType); + } + +- public static Optional> byString(String s) { +- return BuiltInRegistries.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(s)); ++ public static Optional> byString(String key) { ++ return BuiltInRegistries.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(key)); + } + +- public EntityType(EntityType.EntityFactory entitytype_entityfactory, MobCategory mobcategory, boolean flag, boolean flag1, boolean flag2, boolean flag3, ImmutableSet immutableset, EntityDimensions entitydimensions, int i, int j, FeatureFlagSet featureflagset) { ++ public EntityType(EntityType.EntityFactory factory, MobCategory category, boolean serialize, boolean summon, boolean fireImmune, boolean canSpawnFarFromPlayer, ImmutableSet immuneTo, EntityDimensions dimensions, int clientTrackingRange, int updateInterval, FeatureFlagSet requiredFeatures) { + this.builtInRegistryHolder = BuiltInRegistries.ENTITY_TYPE.createIntrusiveHolder(this); +- this.factory = entitytype_entityfactory; +- this.category = mobcategory; +- this.canSpawnFarFromPlayer = flag3; +- this.serialize = flag; +- this.summon = flag1; +- this.fireImmune = flag2; +- this.immuneTo = immutableset; +- this.dimensions = entitydimensions; +- this.clientTrackingRange = i; +- this.updateInterval = j; +- this.requiredFeatures = featureflagset; ++ this.factory = factory; ++ this.category = category; ++ this.canSpawnFarFromPlayer = canSpawnFarFromPlayer; ++ this.serialize = serialize; ++ this.summon = summon; ++ this.fireImmune = fireImmune; ++ this.immuneTo = immuneTo; ++ this.dimensions = dimensions; ++ this.clientTrackingRange = clientTrackingRange; ++ this.updateInterval = updateInterval; ++ this.requiredFeatures = requiredFeatures; + } + + @Nullable +- public T spawn(ServerLevel serverlevel, @Nullable ItemStack itemstack, @Nullable Player player, BlockPos blockpos, MobSpawnType mobspawntype, boolean flag, boolean flag1) { +- CompoundTag compoundtag; +- Consumer consumer; ++ public T spawn(ServerLevel serverLevel, @Nullable ItemStack stack, @Nullable Player player, BlockPos pos, EnumMobSpawn spawnType, boolean shouldOffsetY, boolean shouldOffsetYMore) { ++ // CraftBukkit start ++ return this.spawn(serverLevel, stack, player, pos, spawnType, shouldOffsetY, shouldOffsetYMore, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG); ++ } + ++ @Nullable ++ public T spawn(ServerLevel worldserver, @Nullable ItemStack itemstack, @Nullable Player entityhuman, BlockPos blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end ++ CompoundTag nbttagcompound; ++ Consumer consumer; // CraftBukkit - decompile error ++ + if (itemstack != null) { +- compoundtag = itemstack.getTag(); +- consumer = createDefaultStackConfig(serverlevel, itemstack, player); ++ nbttagcompound = itemstack.getTag(); ++ consumer = createDefaultStackConfig(worldserver, itemstack, entityhuman); + } else { + consumer = (entity) -> { + }; +- compoundtag = null; ++ nbttagcompound = null; + } + +- return this.spawn(serverlevel, compoundtag, consumer, blockpos, mobspawntype, flag, flag1); ++ return this.spawn(worldserver, nbttagcompound, consumer, blockposition, enummobspawn, flag, flag1, spawnReason); // CraftBukkit + } + +- public static Consumer createDefaultStackConfig(ServerLevel serverlevel, ItemStack itemstack, @Nullable Player player) { ++ public static Consumer createDefaultStackConfig(ServerLevel serverLevel, ItemStack stack, @Nullable Player player) { + return appendDefaultStackConfig((entity) -> { +- }, serverlevel, itemstack, player); ++ }, serverLevel, stack, player); + } + +- public static Consumer appendDefaultStackConfig(Consumer consumer, ServerLevel serverlevel, ItemStack itemstack, @Nullable Player player) { +- return appendCustomEntityStackConfig(appendCustomNameConfig(consumer, itemstack), serverlevel, itemstack, player); ++ public static Consumer appendDefaultStackConfig(Consumer consumer, ServerLevel serverLevel, ItemStack stack, @Nullable Player player) { ++ return appendCustomEntityStackConfig(appendCustomNameConfig(consumer, stack), serverLevel, stack, player); + } + +- public static Consumer appendCustomNameConfig(Consumer consumer, ItemStack itemstack) { +- return itemstack.hasCustomHoverName() ? consumer.andThen((entity) -> { +- entity.setCustomName(itemstack.getHoverName()); ++ public static Consumer appendCustomNameConfig(Consumer consumer, ItemStack stack) { ++ return stack.hasCustomHoverName() ? consumer.andThen((entity) -> { ++ entity.setCustomName(stack.getHoverName()); + }) : consumer; + } + +- public static Consumer appendCustomEntityStackConfig(Consumer consumer, ServerLevel serverlevel, ItemStack itemstack, @Nullable Player player) { +- CompoundTag compoundtag = itemstack.getTag(); ++ public static Consumer appendCustomEntityStackConfig(Consumer consumer, ServerLevel level, ItemStack stack, @Nullable Player player) { ++ CompoundTag nbttagcompound = stack.getTag(); + +- return compoundtag != null ? consumer.andThen((entity) -> { +- updateCustomEntityTag(serverlevel, player, entity, compoundtag); ++ return nbttagcompound != null ? consumer.andThen((entity) -> { ++ try { updateCustomEntityTag(level, player, entity, nbttagcompound); } catch (Throwable t) { LOGGER.warn("Error loading spawn egg NBT", t); } // CraftBukkit - SPIGOT-5665 + }) : consumer; + } + + @Nullable +- public T spawn(ServerLevel serverlevel, BlockPos blockpos, MobSpawnType mobspawntype) { +- return this.spawn(serverlevel, (CompoundTag) null, (Consumer) null, blockpos, mobspawntype, false, false); ++ public T spawn(ServerLevel level, BlockPos pos, EnumMobSpawn spawnType) { ++ // CraftBukkit start ++ return this.spawn(level, pos, spawnType, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); + } + + @Nullable +- public T spawn(ServerLevel serverlevel, @Nullable CompoundTag compoundtag, @Nullable Consumer consumer, BlockPos blockpos, MobSpawnType mobspawntype, boolean flag, boolean flag1) { +- T t0 = this.create(serverlevel, compoundtag, consumer, blockpos, mobspawntype, flag, flag1); ++ public T spawn(ServerLevel worldserver, BlockPos blockposition, EnumMobSpawn enummobspawn, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ return this.spawn(worldserver, (CompoundTag) null, null, blockposition, enummobspawn, false, false, spawnReason); // CraftBukkit - decompile error ++ // CraftBukkit end ++ } + ++ @Nullable ++ public T spawn(ServerLevel level, @Nullable CompoundTag compound, @Nullable Consumer consumer, BlockPos pos, EnumMobSpawn spawnType, boolean shouldOffsetY, boolean shouldOffsetYMore) { ++ // CraftBukkit start ++ return this.spawn(level, compound, consumer, pos, spawnType, shouldOffsetY, shouldOffsetYMore, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ @Nullable ++ public T spawn(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Consumer consumer, BlockPos blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end ++ T t0 = this.create(worldserver, nbttagcompound, consumer, blockposition, enummobspawn, flag, flag1); ++ + if (t0 != null) { +- serverlevel.addFreshEntityWithPassengers(t0); ++ worldserver.addFreshEntityWithPassengers(t0, spawnReason); ++ return !t0.isRemoved() ? t0 : null; // Don't return an entity when CreatureSpawnEvent is canceled ++ // CraftBukkit end + } + + return t0; + } + + @Nullable +- public T create(ServerLevel serverlevel, @Nullable CompoundTag compoundtag, @Nullable Consumer consumer, BlockPos blockpos, MobSpawnType mobspawntype, boolean flag, boolean flag1) { +- T t0 = this.create(serverlevel); ++ public T create(ServerLevel level, @Nullable CompoundTag nbt, @Nullable Consumer consumer, BlockPos pos, EnumMobSpawn spawnType, boolean shouldOffsetY, boolean shouldOffsetYMore) { ++ T t0 = this.create(level); + + if (t0 == null) { + return null; + } else { + double d0; + +- if (flag) { +- t0.setPos((double) blockpos.getX() + 0.5D, (double) (blockpos.getY() + 1), (double) blockpos.getZ() + 0.5D); +- d0 = getYOffset(serverlevel, blockpos, flag1, t0.getBoundingBox()); ++ if (shouldOffsetY) { ++ t0.setPos((double) pos.getX() + 0.5D, (double) (pos.getY() + 1), (double) pos.getZ() + 0.5D); ++ d0 = getYOffset(level, pos, shouldOffsetYMore, t0.getBoundingBox()); + } else { + d0 = 0.0D; + } + +- t0.moveTo((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + d0, (double) blockpos.getZ() + 0.5D, Mth.wrapDegrees(serverlevel.random.nextFloat() * 360.0F), 0.0F); ++ t0.moveTo((double) pos.getX() + 0.5D, (double) pos.getY() + d0, (double) pos.getZ() + 0.5D, Mth.wrapDegrees(level.random.nextFloat() * 360.0F), 0.0F); + if (t0 instanceof Mob) { +- Mob mob = (Mob) t0; ++ Mob entityinsentient = (Mob) t0; + +- mob.yHeadRot = mob.getYRot(); +- mob.yBodyRot = mob.getYRot(); +- mob.finalizeSpawn(serverlevel, serverlevel.getCurrentDifficultyAt(mob.blockPosition()), mobspawntype, (SpawnGroupData) null, compoundtag); +- mob.playAmbientSound(); ++ entityinsentient.yHeadRot = entityinsentient.getYRot(); ++ entityinsentient.yBodyRot = entityinsentient.getYRot(); ++ entityinsentient.finalizeSpawn(level, level.getCurrentDifficultyAt(entityinsentient.blockPosition()), spawnType, (GroupDataEntity) null, nbt); ++ entityinsentient.playAmbientSound(); + } + + if (consumer != null) { +@@ -430,30 +454,30 @@ + } + } + +- protected static double getYOffset(LevelReader levelreader, BlockPos blockpos, boolean flag, AABB aabb) { +- AABB aabb1 = new AABB(blockpos); ++ protected static double getYOffset(LevelReader level, BlockPos pos, boolean shouldOffsetYMore, AABB box) { ++ AABB axisalignedbb1 = new AABB(pos); + +- if (flag) { +- aabb1 = aabb1.expandTowards(0.0D, -1.0D, 0.0D); ++ if (shouldOffsetYMore) { ++ axisalignedbb1 = axisalignedbb1.expandTowards(0.0D, -1.0D, 0.0D); + } + +- Iterable iterable = levelreader.getCollisions((Entity) null, aabb1); ++ Iterable iterable = level.getCollisions((Entity) null, axisalignedbb1); + +- return 1.0D + Shapes.collide(Direction.Axis.Y, aabb, iterable, flag ? -2.0D : -1.0D); ++ return 1.0D + Shapes.collide(Direction.Axis.Y, box, iterable, shouldOffsetYMore ? -2.0D : -1.0D); + } + +- public static void updateCustomEntityTag(Level level, @Nullable Player player, @Nullable Entity entity, @Nullable CompoundTag compoundtag) { +- if (compoundtag != null && compoundtag.contains("EntityTag", 10)) { ++ public static void updateCustomEntityTag(Level level, @Nullable Player player, @Nullable Entity spawnedEntity, @Nullable CompoundTag itemNBT) { ++ if (itemNBT != null && itemNBT.contains("EntityTag", 10)) { + MinecraftServer minecraftserver = level.getServer(); + +- if (minecraftserver != null && entity != null) { +- if (level.isClientSide || !entity.onlyOpCanSetNbt() || player != null && minecraftserver.getPlayerList().isOp(player.getGameProfile())) { +- CompoundTag compoundtag1 = entity.saveWithoutId(new CompoundTag()); +- UUID uuid = entity.getUUID(); ++ if (minecraftserver != null && spawnedEntity != null) { ++ if (level.isClientSide || !spawnedEntity.onlyOpCanSetNbt() || player != null && minecraftserver.getPlayerList().isOp(player.getGameProfile())) { ++ CompoundTag nbttagcompound1 = spawnedEntity.saveWithoutId(new CompoundTag()); ++ UUID uuid = spawnedEntity.getUUID(); + +- compoundtag1.merge(compoundtag.getCompound("EntityTag")); +- entity.setUUID(uuid); +- entity.load(compoundtag1); ++ nbttagcompound1.merge(itemNBT.getCompound("EntityTag")); ++ spawnedEntity.setUUID(uuid); ++ spawnedEntity.load(nbttagcompound1); + } + } + } +@@ -495,7 +519,6 @@ + return this.description; + } + +- @Override + public String toString() { + return this.getDescriptionId(); + } +@@ -508,9 +531,9 @@ + + public ResourceLocation getDefaultLootTable() { + if (this.lootTable == null) { +- ResourceLocation resourcelocation = BuiltInRegistries.ENTITY_TYPE.getKey(this); ++ ResourceLocation minecraftkey = BuiltInRegistries.ENTITY_TYPE.getKey(this); + +- this.lootTable = resourcelocation.withPrefix("entities/"); ++ this.lootTable = minecraftkey.withPrefix("entities/"); + } + + return this.lootTable; +@@ -525,7 +548,6 @@ + } + + @Override +- @Override + public FeatureFlagSet requiredFeatures() { + return this.requiredFeatures; + } +@@ -535,42 +557,42 @@ + return !this.isEnabled(level.enabledFeatures()) ? null : this.factory.create(this, level); + } + +- public static Optional create(CompoundTag compoundtag, Level level) { +- return Util.ifElse(by(compoundtag).map((entitytype) -> { +- return entitytype.create(level); ++ public static Optional create(CompoundTag tag, Level level) { ++ return Util.ifElse(by(tag).map((entitytypes) -> { ++ return entitytypes.create(level); + }), (entity) -> { +- entity.load(compoundtag); ++ entity.load(tag); + }, () -> { +- EntityType.LOGGER.warn("Skipping Entity with id {}", compoundtag.getString("id")); ++ EntityType.LOGGER.warn("Skipping Entity with id {}", tag.getString("id")); + }); + } + +- public AABB getAABB(double d0, double d1, double d2) { ++ public AABB getAABB(double x, double d1, double y) { + float f = this.getWidth() / 2.0F; + +- return new AABB(d0 - (double) f, d1, d2 - (double) f, d0 + (double) f, d1 + (double) this.getHeight(), d2 + (double) f); ++ return new AABB(x - (double) f, d1, y - (double) f, x + (double) f, d1 + (double) this.getHeight(), y + (double) f); + } + +- public boolean isBlockDangerous(BlockState blockstate) { +- return this.immuneTo.contains(blockstate.getBlock()) ? false : (!this.fireImmune && WalkNodeEvaluator.isBurningBlock(blockstate) ? true : blockstate.is(Blocks.WITHER_ROSE) || blockstate.is(Blocks.SWEET_BERRY_BUSH) || blockstate.is(Blocks.CACTUS) || blockstate.is(Blocks.POWDER_SNOW)); ++ public boolean isBlockDangerous(IBlockData state) { ++ return this.immuneTo.contains(state.getBlock()) ? false : (!this.fireImmune && WalkNodeEvaluator.isBurningBlock(state) ? true : state.is(Blocks.WITHER_ROSE) || state.is(Blocks.SWEET_BERRY_BUSH) || state.is(Blocks.CACTUS) || state.is(Blocks.POWDER_SNOW)); + } + + public EntityDimensions getDimensions() { + return this.dimensions; + } + +- public static Optional> by(CompoundTag compoundtag) { +- return BuiltInRegistries.ENTITY_TYPE.getOptional(new ResourceLocation(compoundtag.getString("id"))); ++ public static Optional> by(CompoundTag compound) { ++ return BuiltInRegistries.ENTITY_TYPE.getOptional(new ResourceLocation(compound.getString("id"))); + } + + @Nullable +- public static Entity loadEntityRecursive(CompoundTag compoundtag, Level level, Function function) { +- return (Entity) loadStaticEntity(compoundtag, level).map(function).map((entity) -> { +- if (compoundtag.contains("Passengers", 9)) { +- ListTag listtag = compoundtag.getList("Passengers", 10); ++ public static Entity loadEntityRecursive(CompoundTag compound, Level level, Function entityFunction) { ++ return (Entity) loadStaticEntity(compound, level).map(entityFunction).map((entity) -> { ++ if (compound.contains("Passengers", 9)) { ++ ListTag nbttaglist = compound.getList("Passengers", 10); + +- for (int i = 0; i < listtag.size(); ++i) { +- Entity entity1 = loadEntityRecursive(listtag.getCompound(i), level, function); ++ for (int i = 0; i < nbttaglist.size(); ++i) { ++ Entity entity1 = loadEntityRecursive(nbttaglist.getCompound(i), level, entityFunction); + + if (entity1 != null) { + entity1.startRiding(entity, true); +@@ -579,43 +601,39 @@ + } + + return entity; +- }).orElse((Object) null); ++ }).orElse(null); // CraftBukkit - decompile error + } + +- public static Stream loadEntitiesRecursive(final List list, final Level level) { +- final Spliterator spliterator = list.spliterator(); ++ public static Stream loadEntitiesRecursive(final List tags, final Level level) { ++ final Spliterator spliterator = tags.spliterator(); + + return StreamSupport.stream(new Spliterator() { +- @Override + public boolean tryAdvance(Consumer consumer) { +- return spliterator.tryAdvance((tag) -> { +- EntityType.loadEntityRecursive((CompoundTag) tag, level, (entity) -> { ++ return spliterator.tryAdvance((nbtbase) -> { ++ EntityType.loadEntityRecursive((CompoundTag) nbtbase, level, (entity) -> { + consumer.accept(entity); + return entity; + }); + }); + } + +- @Override + public Spliterator trySplit() { + return null; + } + +- @Override + public long estimateSize() { +- return (long) list.size(); ++ return (long) tags.size(); + } + +- @Override + public int characteristics() { + return 1297; + } + }, false); + } + +- private static Optional loadStaticEntity(CompoundTag compoundtag, Level level) { ++ private static Optional loadStaticEntity(CompoundTag compound, Level level) { + try { +- return create(compoundtag, level); ++ return create(compound, level); + } catch (RuntimeException runtimeexception) { + EntityType.LOGGER.warn("Exception loading entity: ", runtimeexception); + return Optional.empty(); +@@ -634,8 +652,8 @@ + return this != EntityType.PLAYER && this != EntityType.LLAMA_SPIT && this != EntityType.WITHER && this != EntityType.BAT && this != EntityType.ITEM_FRAME && this != EntityType.GLOW_ITEM_FRAME && this != EntityType.LEASH_KNOT && this != EntityType.PAINTING && this != EntityType.END_CRYSTAL && this != EntityType.EVOKER_FANGS; + } + +- public boolean is(TagKey> tagkey) { +- return this.builtInRegistryHolder.is(tagkey); ++ public boolean is(TagKey> tag) { ++ return this.builtInRegistryHolder.is(tag); + } + + public boolean is(HolderSet> holderset) { +@@ -643,13 +661,11 @@ + } + + @Nullable +- @Override + public T tryCast(Entity entity) { +- return entity.getType() == this ? entity : null; ++ return entity.getType() == this ? (T) entity : null; // CraftBukkit - decompile error + } + + @Override +- @Override + public Class getBaseClass() { + return Entity.class; + } +@@ -674,25 +690,25 @@ + private EntityDimensions dimensions = EntityDimensions.scalable(0.6F, 1.8F); + private FeatureFlagSet requiredFeatures; + +- private Builder(EntityType.EntityFactory entitytype_entityfactory, MobCategory mobcategory) { ++ private Builder(EntityType.EntityFactory factory, MobCategory category) { + this.requiredFeatures = FeatureFlags.VANILLA_SET; +- this.factory = entitytype_entityfactory; +- this.category = mobcategory; +- this.canSpawnFarFromPlayer = mobcategory == MobCategory.CREATURE || mobcategory == MobCategory.MISC; ++ this.factory = factory; ++ this.category = category; ++ this.canSpawnFarFromPlayer = category == MobCategory.CREATURE || category == MobCategory.MISC; + } + +- public static EntityType.Builder of(EntityType.EntityFactory entitytype_entityfactory, MobCategory mobcategory) { +- return new EntityType.Builder<>(entitytype_entityfactory, mobcategory); ++ public static EntityType.Builder of(EntityType.EntityFactory factory, MobCategory category) { // CraftBukkit - decompile error ++ return new EntityType.Builder<>(factory, category); + } + +- public static EntityType.Builder createNothing(MobCategory mobcategory) { +- return new EntityType.Builder<>((entitytype, level) -> { ++ public static EntityType.Builder createNothing(MobCategory category) { ++ return new EntityType.Builder<>((entitytypes, world) -> { + return null; +- }, mobcategory); ++ }, category); + } + +- public EntityType.Builder sized(float f, float f1) { +- this.dimensions = EntityDimensions.scalable(f, f1); ++ public EntityType.Builder sized(float width, float height) { ++ this.dimensions = EntityDimensions.scalable(width, height); + return this; + } + +@@ -711,8 +727,8 @@ + return this; + } + +- public EntityType.Builder immuneTo(Block... ablock) { +- this.immuneTo = ImmutableSet.copyOf(ablock); ++ public EntityType.Builder immuneTo(Block... blocks) { ++ this.immuneTo = ImmutableSet.copyOf(blocks); + return this; + } + +@@ -721,24 +737,24 @@ + return this; + } + +- public EntityType.Builder clientTrackingRange(int i) { +- this.clientTrackingRange = i; ++ public EntityType.Builder clientTrackingRange(int clientTrackingRange) { ++ this.clientTrackingRange = clientTrackingRange; + return this; + } + +- public EntityType.Builder updateInterval(int i) { +- this.updateInterval = i; ++ public EntityType.Builder updateInterval(int updateInterval) { ++ this.updateInterval = updateInterval; + return this; + } + +- public EntityType.Builder requiredFeatures(FeatureFlag... afeatureflag) { +- this.requiredFeatures = FeatureFlags.REGISTRY.subset(afeatureflag); ++ public EntityType.Builder requiredFeatures(FeatureFlag... requiredFeatures) { ++ this.requiredFeatures = FeatureFlags.REGISTRY.subset(requiredFeatures); + return this; + } + +- public EntityType build(String s) { ++ public EntityType build(String key) { + if (this.serialize) { +- Util.fetchChoiceType(References.ENTITY_TREE, s); ++ Util.fetchChoiceType(DataConverterTypes.ENTITY_TREE, key); + } + + return new EntityType<>(this.factory, this.category, this.serialize, this.summon, this.fireImmune, this.canSpawnFarFromPlayer, this.immuneTo, this.dimensions, this.clientTrackingRange, this.updateInterval, this.requiredFeatures); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ExperienceOrb.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ExperienceOrb.java.patch new file mode 100644 index 0000000000..efa96db50e --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ExperienceOrb.java.patch @@ -0,0 +1,356 @@ +--- a/net/minecraft/world/entity/ExperienceOrb.java ++++ b/net/minecraft/world/entity/ExperienceOrb.java +@@ -20,6 +20,12 @@ + import net.minecraft.world.level.entity.EntityTypeTest; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.player.PlayerExpCooldownChangeEvent; ++// CraftBukkit end + + public class ExperienceOrb extends Entity { + +@@ -30,38 +36,36 @@ + private static final double ORB_MERGE_DISTANCE = 0.5D; + private int age; + private int health; +- private int value; ++ public int value; + private int count; + private Player followingPlayer; + +- public ExperienceOrb(Level level, double d0, double d1, double d2, int i) { ++ public ExperienceOrb(Level level, double x, double d1, double y, int i) { + this(EntityType.EXPERIENCE_ORB, level); +- this.setPos(d0, d1, d2); ++ this.setPos(x, d1, y); + this.setYRot((float) (this.random.nextDouble() * 360.0D)); + this.setDeltaMovement((this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D, this.random.nextDouble() * 0.2D * 2.0D, (this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D); + this.value = i; + } + +- public ExperienceOrb(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public ExperienceOrb(EntityType entityType, Level level) { ++ super(entityType, level); + this.health = 5; + this.count = 1; + } + + @Override +- @Override + protected Entity.MovementEmission getMovementEmission() { + return Entity.MovementEmission.NONE; + } + + @Override +- @Override + protected void defineSynchedData() {} + + @Override +- @Override + public void tick() { + super.tick(); ++ Player prevTarget = this.followingPlayer;// CraftBukkit - store old target + this.xo = this.getX(); + this.yo = this.getY(); + this.zo = this.getZ(); +@@ -87,18 +91,33 @@ + this.followingPlayer = null; + } + +- if (this.followingPlayer != null) { +- Vec3 vec3 = new Vec3(this.followingPlayer.getX() - this.getX(), this.followingPlayer.getY() + (double) this.followingPlayer.getEyeHeight() / 2.0D - this.getY(), this.followingPlayer.getZ() - this.getZ()); +- double d0 = vec3.lengthSqr(); ++ // CraftBukkit start ++ boolean cancelled = false; ++ if (this.followingPlayer != prevTarget) { ++ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(this, followingPlayer, (followingPlayer != null) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.FORGOT_TARGET); ++ LivingEntity target = (event.getTarget() == null) ? null : ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getTarget()).getHandle(); ++ cancelled = event.isCancelled(); + ++ if (cancelled) { ++ followingPlayer = prevTarget; ++ } else { ++ followingPlayer = (target instanceof Player) ? (Player) target : null; ++ } ++ } ++ ++ if (this.followingPlayer != null && !cancelled) { ++ // CraftBukkit end ++ Vec3 vec3d = new Vec3(this.followingPlayer.getX() - this.getX(), this.followingPlayer.getY() + (double) this.followingPlayer.getEyeHeight() / 2.0D - this.getY(), this.followingPlayer.getZ() - this.getZ()); ++ double d0 = vec3d.lengthSqr(); ++ + if (d0 < 64.0D) { + double d1 = 1.0D - Math.sqrt(d0) / 8.0D; + +- this.setDeltaMovement(this.getDeltaMovement().add(vec3.normalize().scale(d1 * d1 * 0.1D))); ++ this.setDeltaMovement(this.getDeltaMovement().add(vec3d.normalize().scale(d1 * d1 * 0.1D))); + } + } + +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + float f = 0.98F; + + if (this.onGround()) { +@@ -118,7 +137,6 @@ + } + + @Override +- @Override + protected BlockPos getBlockPosBelowThatAffectsMyMovement() { + return this.getOnPos(0.999999F); + } +@@ -133,78 +151,76 @@ + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- ExperienceOrb experienceorb = (ExperienceOrb) iterator.next(); ++ ExperienceOrb entityexperienceorb = (ExperienceOrb) iterator.next(); + +- this.merge(experienceorb); ++ this.merge(entityexperienceorb); + } + } + + } + +- public static void award(ServerLevel serverlevel, Vec3 vec3, int i) { +- while (i > 0) { +- int j = getExperienceValue(i); ++ public static void award(ServerLevel level, Vec3 pos, int amount) { ++ while (amount > 0) { ++ int j = getExperienceValue(amount); + +- i -= j; +- if (!tryMergeToExisting(serverlevel, vec3, j)) { +- serverlevel.addFreshEntity(new ExperienceOrb(serverlevel, vec3.x(), vec3.y(), vec3.z(), j)); ++ amount -= j; ++ if (!tryMergeToExisting(level, pos, j)) { ++ level.addFreshEntity(new ExperienceOrb(level, pos.x(), pos.y(), pos.z(), j)); + } + } + + } + +- private static boolean tryMergeToExisting(ServerLevel serverlevel, Vec3 vec3, int i) { +- AABB aabb = AABB.ofSize(vec3, 1.0D, 1.0D, 1.0D); +- int j = serverlevel.getRandom().nextInt(40); +- List list = serverlevel.getEntities(EntityTypeTest.forClass(ExperienceOrb.class), aabb, (experienceorb) -> { +- return canMerge(experienceorb, j, i); ++ private static boolean tryMergeToExisting(ServerLevel level, Vec3 pos, int amount) { ++ AABB axisalignedbb = AABB.ofSize(pos, 1.0D, 1.0D, 1.0D); ++ int j = level.getRandom().nextInt(40); ++ List list = level.getEntities(EntityTypeTest.forClass(ExperienceOrb.class), axisalignedbb, (entityexperienceorb) -> { ++ return canMerge(entityexperienceorb, j, amount); + }); + + if (!list.isEmpty()) { +- ExperienceOrb experienceorb = (ExperienceOrb) list.get(0); ++ ExperienceOrb entityexperienceorb = (ExperienceOrb) list.get(0); + +- ++experienceorb.count; +- experienceorb.age = 0; ++ ++entityexperienceorb.count; ++ entityexperienceorb.age = 0; + return true; + } else { + return false; + } + } + +- private boolean canMerge(ExperienceOrb experienceorb) { +- return experienceorb != this && canMerge(experienceorb, this.getId(), this.value); ++ private boolean canMerge(ExperienceOrb orb) { ++ return orb != this && canMerge(orb, this.getId(), this.value); + } + +- private static boolean canMerge(ExperienceOrb experienceorb, int i, int j) { +- return !experienceorb.isRemoved() && (experienceorb.getId() - i) % 40 == 0 && experienceorb.value == j; ++ private static boolean canMerge(ExperienceOrb orb, int amount, int other) { ++ return !orb.isRemoved() && (orb.getId() - amount) % 40 == 0 && orb.value == other; + } + +- private void merge(ExperienceOrb experienceorb) { +- this.count += experienceorb.count; +- this.age = Math.min(this.age, experienceorb.age); +- experienceorb.discard(); ++ private void merge(ExperienceOrb orb) { ++ this.count += orb.count; ++ this.age = Math.min(this.age, orb.age); ++ orb.discard(); + } + + private void setUnderwaterMovement() { +- Vec3 vec3 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + +- this.setDeltaMovement(vec3.x * 0.9900000095367432D, Math.min(vec3.y + 5.000000237487257E-4D, 0.05999999865889549D), vec3.z * 0.9900000095367432D); ++ this.setDeltaMovement(vec3d.x * 0.9900000095367432D, Math.min(vec3d.y + 5.000000237487257E-4D, 0.05999999865889549D), vec3d.z * 0.9900000095367432D); + } + + @Override +- @Override + protected void doWaterSplashEffect() {} + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- if (this.isInvulnerableTo(damagesource)) { ++ public boolean hurt(DamageSource source, float amount) { ++ if (this.isInvulnerableTo(source)) { + return false; + } else if (this.level().isClientSide) { + return true; + } else { + this.markHurt(); +- this.health = (int) ((float) this.health - f); ++ this.health = (int) ((float) this.health - amount); + if (this.health <= 0) { + this.discard(); + } +@@ -214,34 +230,31 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- compoundtag.putShort("Health", (short) this.health); +- compoundtag.putShort("Age", (short) this.age); +- compoundtag.putShort("Value", (short) this.value); +- compoundtag.putInt("Count", this.count); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ compound.putShort("Health", (short) this.health); ++ compound.putShort("Age", (short) this.age); ++ compound.putShort("Value", (short) this.value); ++ compound.putInt("Count", this.count); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- this.health = compoundtag.getShort("Health"); +- this.age = compoundtag.getShort("Age"); +- this.value = compoundtag.getShort("Value"); +- this.count = Math.max(compoundtag.getInt("Count"), 1); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ this.health = compound.getShort("Health"); ++ this.age = compound.getShort("Age"); ++ this.value = compound.getShort("Value"); ++ this.count = Math.max(compound.getInt("Count"), 1); + } + + @Override +- @Override +- public void playerTouch(Player player) { ++ public void playerTouch(Player entity) { + if (!this.level().isClientSide) { +- if (player.takeXpDelay == 0) { +- player.takeXpDelay = 2; +- player.take(this, 1); +- int i = this.repairPlayerItems(player, this.value); ++ if (entity.takeXpDelay == 0) { ++ entity.takeXpDelay = CraftEventFactory.callPlayerXpCooldownEvent(entity, 2, PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2; ++ entity.take(this, 1); ++ int i = this.repairPlayerItems(entity, this.value); + + if (i > 0) { +- player.giveExperiencePoints(i); ++ entity.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(entity, i).getAmount()); // CraftBukkit - this.value -> event.getAmount() + } + + --this.count; +@@ -253,28 +266,36 @@ + } + } + +- private int repairPlayerItems(Player player, int i) { ++ private int repairPlayerItems(Player player, int repairAmount) { + Entry entry = EnchantmentHelper.getRandomItemWith(Enchantments.MENDING, player, ItemStack::isDamaged); + + if (entry != null) { + ItemStack itemstack = (ItemStack) entry.getValue(); +- int j = Math.min(this.xpToDurability(i), itemstack.getDamageValue()); ++ int j = Math.min(this.xpToDurability(repairAmount), itemstack.getDamageValue()); ++ // CraftBukkit start ++ org.bukkit.event.player.PlayerItemMendEvent event = CraftEventFactory.callPlayerItemMendEvent(player, this, itemstack, entry.getKey(), j); ++ j = event.getRepairAmount(); ++ if (event.isCancelled()) { ++ return repairAmount; ++ } ++ // CraftBukkit end + + itemstack.setDamageValue(itemstack.getDamageValue() - j); +- int k = i - this.durabilityToXp(j); ++ int k = repairAmount - this.durabilityToXp(j); ++ this.value = k; // CraftBukkit - update exp value of orb for PlayerItemMendEvent calls + + return k > 0 ? this.repairPlayerItems(player, k) : 0; + } else { +- return i; ++ return repairAmount; + } + } + +- private int durabilityToXp(int i) { +- return i / 2; ++ private int durabilityToXp(int durability) { ++ return durability / 2; + } + +- private int xpToDurability(int i) { +- return i * 2; ++ private int xpToDurability(int xp) { ++ return xp * 2; + } + + public int getValue() { +@@ -285,24 +306,39 @@ + return this.value >= 2477 ? 10 : (this.value >= 1237 ? 9 : (this.value >= 617 ? 8 : (this.value >= 307 ? 7 : (this.value >= 149 ? 6 : (this.value >= 73 ? 5 : (this.value >= 37 ? 4 : (this.value >= 17 ? 3 : (this.value >= 7 ? 2 : (this.value >= 3 ? 1 : 0))))))))); + } + +- public static int getExperienceValue(int i) { +- return i >= 2477 ? 2477 : (i >= 1237 ? 1237 : (i >= 617 ? 617 : (i >= 307 ? 307 : (i >= 149 ? 149 : (i >= 73 ? 73 : (i >= 37 ? 37 : (i >= 17 ? 17 : (i >= 7 ? 7 : (i >= 3 ? 3 : 1))))))))); ++ public static int getExperienceValue(int expValue) { ++ // CraftBukkit start ++ if (expValue > 162670129) return expValue - 100000; ++ if (expValue > 81335063) return 81335063; ++ if (expValue > 40667527) return 40667527; ++ if (expValue > 20333759) return 20333759; ++ if (expValue > 10166857) return 10166857; ++ if (expValue > 5083423) return 5083423; ++ if (expValue > 2541701) return 2541701; ++ if (expValue > 1270849) return 1270849; ++ if (expValue > 635413) return 635413; ++ if (expValue > 317701) return 317701; ++ if (expValue > 158849) return 158849; ++ if (expValue > 79423) return 79423; ++ if (expValue > 39709) return 39709; ++ if (expValue > 19853) return 19853; ++ if (expValue > 9923) return 9923; ++ if (expValue > 4957) return 4957; ++ // CraftBukkit end ++ return expValue >= 2477 ? 2477 : (expValue >= 1237 ? 1237 : (expValue >= 617 ? 617 : (expValue >= 307 ? 307 : (expValue >= 149 ? 149 : (expValue >= 73 ? 73 : (expValue >= 37 ? 37 : (expValue >= 17 ? 17 : (expValue >= 7 ? 7 : (expValue >= 3 ? 3 : 1))))))))); + } + + @Override +- @Override + public boolean isAttackable() { + return false; + } + + @Override +- @Override + public Packet getAddEntityPacket() { + return new ClientboundAddExperienceOrbPacket(this); + } + + @Override +- @Override + public SoundSource getSoundSource() { + return SoundSource.AMBIENT; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/Interaction.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/Interaction.java.patch new file mode 100644 index 0000000000..8332b045b6 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/Interaction.java.patch @@ -0,0 +1,276 @@ +--- a/net/minecraft/world/entity/Interaction.java ++++ b/net/minecraft/world/entity/Interaction.java +@@ -16,14 +16,20 @@ + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; + import net.minecraft.server.level.ServerPlayer; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.material.PushReaction; ++import net.minecraft.world.level.material.EnumPistonReaction; + import net.minecraft.world.phys.AABB; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.world.damagesource.DamageSource; ++import net.minecraft.world.entity.player.Player; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityDamageEvent; ++// CraftBukkit end ++ + public class Interaction extends Entity implements Attackable, Targeting { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -36,17 +42,16 @@ + private static final String TAG_INTERACTION = "interaction"; + private static final String TAG_RESPONSE = "response"; + @Nullable +- private Interaction.PlayerAction attack; ++ public Interaction.PlayerAction attack; + @Nullable +- private Interaction.PlayerAction interaction; ++ public Interaction.PlayerAction interaction; + +- public Interaction(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Interaction(EntityType entityType, Level level) { ++ super(entityType, level); + this.noPhysics = true; + } + + @Override +- @Override + protected void defineSynchedData() { + this.entityData.define(Interaction.DATA_WIDTH_ID, 1.0F); + this.entityData.define(Interaction.DATA_HEIGHT_ID, 1.0F); +@@ -54,21 +59,20 @@ + } + + @Override +- @Override +- protected void readAdditionalSaveData(CompoundTag compoundtag) { +- if (compoundtag.contains("width", 99)) { +- this.setWidth(compoundtag.getFloat("width")); ++ protected void readAdditionalSaveData(CompoundTag compound) { ++ if (compound.contains("width", 99)) { ++ this.setWidth(compound.getFloat("width")); + } + +- if (compoundtag.contains("height", 99)) { +- this.setHeight(compoundtag.getFloat("height")); ++ if (compound.contains("height", 99)) { ++ this.setHeight(compound.getFloat("height")); + } + +- DataResult dataresult; ++ DataResult> dataresult; // CraftBukkit - decompile error + Logger logger; + +- if (compoundtag.contains("attack")) { +- dataresult = Interaction.PlayerAction.CODEC.decode(NbtOps.INSTANCE, compoundtag.get("attack")); ++ if (compound.contains("attack")) { ++ dataresult = Interaction.PlayerAction.CODEC.decode(NbtOps.INSTANCE, compound.get("attack")); + logger = Interaction.LOGGER; + Objects.requireNonNull(logger); + dataresult.resultOrPartial(Util.prefix("Interaction entity", logger::error)).ifPresent((pair) -> { +@@ -78,8 +82,8 @@ + this.attack = null; + } + +- if (compoundtag.contains("interaction")) { +- dataresult = Interaction.PlayerAction.CODEC.decode(NbtOps.INSTANCE, compoundtag.get("interaction")); ++ if (compound.contains("interaction")) { ++ dataresult = Interaction.PlayerAction.CODEC.decode(NbtOps.INSTANCE, compound.get("interaction")); + logger = Interaction.LOGGER; + Objects.requireNonNull(logger); + dataresult.resultOrPartial(Util.prefix("Interaction entity", logger::error)).ifPresent((pair) -> { +@@ -89,75 +93,75 @@ + this.interaction = null; + } + +- this.setResponse(compoundtag.getBoolean("response")); ++ this.setResponse(compound.getBoolean("response")); + this.setBoundingBox(this.makeBoundingBox()); + } + + @Override +- @Override +- protected void addAdditionalSaveData(CompoundTag compoundtag) { +- compoundtag.putFloat("width", this.getWidth()); +- compoundtag.putFloat("height", this.getHeight()); ++ protected void addAdditionalSaveData(CompoundTag compound) { ++ compound.putFloat("width", this.getWidth()); ++ compound.putFloat("height", this.getHeight()); + if (this.attack != null) { +- Interaction.PlayerAction.CODEC.encodeStart(NbtOps.INSTANCE, this.attack).result().ifPresent((tag) -> { +- compoundtag.put("attack", tag); ++ Interaction.PlayerAction.CODEC.encodeStart(NbtOps.INSTANCE, this.attack).result().ifPresent((nbtbase) -> { ++ compound.put("attack", nbtbase); + }); + } + + if (this.interaction != null) { +- Interaction.PlayerAction.CODEC.encodeStart(NbtOps.INSTANCE, this.interaction).result().ifPresent((tag) -> { +- compoundtag.put("interaction", tag); ++ Interaction.PlayerAction.CODEC.encodeStart(NbtOps.INSTANCE, this.interaction).result().ifPresent((nbtbase) -> { ++ compound.put("interaction", nbtbase); + }); + } + +- compoundtag.putBoolean("response", this.getResponse()); ++ compound.putBoolean("response", this.getResponse()); + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- super.onSyncedDataUpdated(entitydataaccessor); +- if (Interaction.DATA_HEIGHT_ID.equals(entitydataaccessor) || Interaction.DATA_WIDTH_ID.equals(entitydataaccessor)) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ super.onSyncedDataUpdated(key); ++ if (Interaction.DATA_HEIGHT_ID.equals(key) || Interaction.DATA_WIDTH_ID.equals(key)) { + this.setBoundingBox(this.makeBoundingBox()); + } + + } + + @Override +- @Override + public boolean canBeHitByProjectile() { + return false; + } + + @Override +- @Override + public boolean isPickable() { + return true; + } + + @Override +- @Override +- public PushReaction getPistonPushReaction() { +- return PushReaction.IGNORE; ++ public EnumPistonReaction getPistonPushReaction() { ++ return EnumPistonReaction.IGNORE; + } + + @Override +- @Override + public boolean isIgnoringBlockTriggers() { + return true; + } + + @Override +- @Override + public boolean skipAttackInteraction(Entity entity) { + if (entity instanceof Player) { +- Player player = (Player) entity; ++ Player entityhuman = (Player) entity; ++ // CraftBukkit start ++ DamageSource source = entityhuman.damageSources().playerAttack(entityhuman); ++ EntityDamageEvent event = CraftEventFactory.callNonLivingEntityDamageEvent(this, source, 1.0F, false); ++ if (event.isCancelled()) { ++ return true; ++ } ++ // CraftBukkit end + +- this.attack = new Interaction.PlayerAction(player.getUUID(), this.level().getGameTime()); +- if (player instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) player; ++ this.attack = new Interaction.PlayerAction(entityhuman.getUUID(), this.level().getGameTime()); ++ if (entityhuman instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entityhuman; + +- CriteriaTriggers.PLAYER_HURT_ENTITY.trigger(serverplayer, this, player.damageSources().generic(), 1.0F, 1.0F, false); ++ CriteriaTriggers.PLAYER_HURT_ENTITY.trigger(entityplayer, this, source, (float) event.getFinalDamage(), 1.0F, false); // CraftBukkit + } + + return !this.getResponse(); +@@ -167,8 +171,7 @@ + } + + @Override +- @Override +- public InteractionResult interact(Player player, InteractionHand interactionhand) { ++ public InteractionResult interact(Player player, EnumHand hand) { + if (this.level().isClientSide) { + return this.getResponse() ? InteractionResult.SUCCESS : InteractionResult.CONSUME; + } else { +@@ -178,44 +181,41 @@ + } + + @Override +- @Override + public void tick() {} + + @Nullable + @Override +- @Override + public LivingEntity getLastAttacker() { + return this.attack != null ? this.level().getPlayerByUUID(this.attack.player()) : null; + } + + @Nullable + @Override +- @Override + public LivingEntity getTarget() { + return this.interaction != null ? this.level().getPlayerByUUID(this.interaction.player()) : null; + } + +- private void setWidth(float f) { +- this.entityData.set(Interaction.DATA_WIDTH_ID, f); ++ public void setWidth(float width) { ++ this.entityData.set(Interaction.DATA_WIDTH_ID, width); + } + +- private float getWidth() { ++ public float getWidth() { + return (Float) this.entityData.get(Interaction.DATA_WIDTH_ID); + } + +- private void setHeight(float f) { +- this.entityData.set(Interaction.DATA_HEIGHT_ID, f); ++ public void setHeight(float height) { ++ this.entityData.set(Interaction.DATA_HEIGHT_ID, height); + } + +- private float getHeight() { ++ public float getHeight() { + return (Float) this.entityData.get(Interaction.DATA_HEIGHT_ID); + } + +- private void setResponse(boolean flag) { +- this.entityData.set(Interaction.DATA_RESPONSE_ID, flag); ++ public void setResponse(boolean response) { ++ this.entityData.set(Interaction.DATA_RESPONSE_ID, response); + } + +- private boolean getResponse() { ++ public boolean getResponse() { + return (Boolean) this.entityData.get(Interaction.DATA_RESPONSE_ID); + } + +@@ -224,18 +224,16 @@ + } + + @Override +- @Override +- public EntityDimensions getDimensions(Pose pose) { ++ public EntityDimensions getDimensions(EntityPose pose) { + return this.getDimensions(); + } + + @Override +- @Override + protected AABB makeBoundingBox() { + return this.getDimensions().makeBoundingBox(this.position()); + } + +- private static record PlayerAction(UUID player, long timestamp) { ++ public static record PlayerAction(UUID player, long timestamp) { + + public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { + return instance.group(UUIDUtil.CODEC.fieldOf("player").forGetter(Interaction.PlayerAction::player), Codec.LONG.fieldOf("timestamp").forGetter(Interaction.PlayerAction::timestamp)).apply(instance, Interaction.PlayerAction::new); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ItemBasedSteering.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ItemBasedSteering.java.patch new file mode 100644 index 0000000000..10c4c3615c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ItemBasedSteering.java.patch @@ -0,0 +1,76 @@ +--- a/net/minecraft/world/entity/ItemBasedSteering.java ++++ b/net/minecraft/world/entity/ItemBasedSteering.java +@@ -13,13 +13,13 @@ + private final SynchedEntityData entityData; + private final EntityDataAccessor boostTimeAccessor; + private final EntityDataAccessor hasSaddleAccessor; +- private boolean boosting; +- private int boostTime; ++ public boolean boosting; ++ public int boostTime; + +- public ItemBasedSteering(SynchedEntityData synchedentitydata, EntityDataAccessor entitydataaccessor, EntityDataAccessor entitydataaccessor1) { +- this.entityData = synchedentitydata; +- this.boostTimeAccessor = entitydataaccessor; +- this.hasSaddleAccessor = entitydataaccessor1; ++ public ItemBasedSteering(SynchedEntityData entityData, EntityDataAccessor boostTimeAccessor, EntityDataAccessor hasSaddleAccessor) { ++ this.entityData = entityData; ++ this.boostTimeAccessor = boostTimeAccessor; ++ this.hasSaddleAccessor = hasSaddleAccessor; + } + + public void onSynced() { +@@ -27,13 +27,13 @@ + this.boostTime = 0; + } + +- public boolean boost(RandomSource randomsource) { ++ public boolean boost(RandomSource random) { + if (this.boosting) { + return false; + } else { + this.boosting = true; + this.boostTime = 0; +- this.entityData.set(this.boostTimeAccessor, randomsource.nextInt(841) + 140); ++ this.entityData.set(this.boostTimeAccessor, random.nextInt(841) + 140); + return true; + } + } +@@ -49,22 +49,30 @@ + return this.boosting ? 1.0F + 1.15F * Mth.sin((float) this.boostTime / (float) this.boostTimeTotal() * 3.1415927F) : 1.0F; + } + +- private int boostTimeTotal() { ++ public int boostTimeTotal() { + return (Integer) this.entityData.get(this.boostTimeAccessor); + } + +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- compoundtag.putBoolean("Saddle", this.hasSaddle()); ++ // CraftBukkit add setBoostTicks(int) ++ public void setBoostTicks(int ticks) { ++ this.boosting = true; ++ this.boostTime = 0; ++ this.entityData.set(this.boostTimeAccessor, ticks); + } ++ // CraftBukkit end + +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- this.setSaddle(compoundtag.getBoolean("Saddle")); ++ public void addAdditionalSaveData(CompoundTag nbt) { ++ nbt.putBoolean("Saddle", this.hasSaddle()); + } + +- public void setSaddle(boolean flag) { +- this.entityData.set(this.hasSaddleAccessor, flag); ++ public void readAdditionalSaveData(CompoundTag nbt) { ++ this.setSaddle(nbt.getBoolean("Saddle")); + } + ++ public void setSaddle(boolean saddled) { ++ this.entityData.set(this.hasSaddleAccessor, saddled); ++ } ++ + public boolean hasSaddle() { + return (Boolean) this.entityData.get(this.hasSaddleAccessor); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/LightningBolt.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/LightningBolt.java.patch new file mode 100644 index 0000000000..0a431bb5f7 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/LightningBolt.java.patch @@ -0,0 +1,296 @@ +--- a/net/minecraft/world/entity/LightningBolt.java ++++ b/net/minecraft/world/entity/LightningBolt.java +@@ -24,39 +24,41 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.LightningRodBlock; + import net.minecraft.world.level.block.WeatheringCopper; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class LightningBolt extends Entity { + + private static final int START_LIFE = 2; + private static final double DAMAGE_RADIUS = 3.0D; + private static final double DETECTION_RADIUS = 15.0D; +- private int life; ++ public int life; + public long seed; +- private int flashes; +- private boolean visualOnly; ++ public int flashes; ++ public boolean visualOnly; + @Nullable + private ServerPlayer cause; + private final Set hitEntities = Sets.newHashSet(); + private int blocksSetOnFire; + +- public LightningBolt(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public LightningBolt(EntityType entityType, Level level) { ++ super(entityType, level); + this.noCulling = true; + this.life = 2; + this.seed = this.random.nextLong(); + this.flashes = this.random.nextInt(3) + 1; + } + +- public void setVisualOnly(boolean flag) { +- this.visualOnly = flag; ++ public void setVisualOnly(boolean visualOnly) { ++ this.visualOnly = visualOnly; + } + + @Override +- @Override + public SoundSource getSoundSource() { + return SoundSource.WEATHER; + } +@@ -66,22 +68,21 @@ + return this.cause; + } + +- public void setCause(@Nullable ServerPlayer serverplayer) { +- this.cause = serverplayer; ++ public void setCause(@Nullable ServerPlayer cause) { ++ this.cause = cause; + } + + private void powerLightningRod() { +- BlockPos blockpos = this.getStrikePosition(); +- BlockState blockstate = this.level().getBlockState(blockpos); ++ BlockPos blockposition = this.getStrikePosition(); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); + +- if (blockstate.is(Blocks.LIGHTNING_ROD)) { +- ((LightningRodBlock) blockstate.getBlock()).onLightningStrike(blockstate, this.level(), blockpos); ++ if (iblockdata.is(Blocks.LIGHTNING_ROD)) { ++ ((LightningRodBlock) iblockdata.getBlock()).onLightningStrike(iblockdata, this.level(), blockposition); + } + + } + + @Override +- @Override + public void tick() { + super.tick(); + if (this.life == 2) { +@@ -89,9 +90,9 @@ + this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.LIGHTNING_BOLT_THUNDER, SoundSource.WEATHER, 10000.0F, 0.8F + this.random.nextFloat() * 0.2F, false); + this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.LIGHTNING_BOLT_IMPACT, SoundSource.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F, false); + } else { +- Difficulty difficulty = this.level().getDifficulty(); ++ Difficulty enumdifficulty = this.level().getDifficulty(); + +- if (difficulty == Difficulty.NORMAL || difficulty == Difficulty.HARD) { ++ if (enumdifficulty == Difficulty.NORMAL || enumdifficulty == Difficulty.HARD) { + this.spawnFire(4); + } + +@@ -111,14 +112,14 @@ + list = this.level().getEntities((Entity) this, new AABB(this.getX() - 15.0D, this.getY() - 15.0D, this.getZ() - 15.0D, this.getX() + 15.0D, this.getY() + 6.0D + 15.0D, this.getZ() + 15.0D), (entity) -> { + return entity.isAlive() && !this.hitEntities.contains(entity); + }); +- iterator = ((ServerLevel) this.level()).getPlayers((serverplayer) -> { +- return serverplayer.distanceTo(this) < 256.0F; ++ iterator = ((ServerLevel) this.level()).getPlayers((entityplayer) -> { ++ return entityplayer.distanceTo(this) < 256.0F; + }).iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- CriteriaTriggers.LIGHTNING_STRIKE.trigger(serverplayer, this, list); ++ CriteriaTriggers.LIGHTNING_STRIKE.trigger(entityplayer, this, list); + } + } + +@@ -131,7 +132,7 @@ + } + } + +- if (this.life >= 0) { ++ if (this.life >= 0 && !this.visualOnly) { // CraftBukkit - add !this.visualOnly + if (!(this.level() instanceof ServerLevel)) { + this.level().setSkyFlashTime(2); + } else if (!this.visualOnly) { +@@ -154,117 +155,122 @@ + } + + private BlockPos getStrikePosition() { +- Vec3 vec3 = this.position(); ++ Vec3 vec3d = this.position(); + +- return BlockPos.containing(vec3.x, vec3.y - 1.0E-6D, vec3.z); ++ return BlockPos.containing(vec3d.x, vec3d.y - 1.0E-6D, vec3d.z); + } + +- private void spawnFire(int i) { ++ private void spawnFire(int extraIgnitions) { + if (!this.visualOnly && !this.level().isClientSide && this.level().getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) { +- BlockPos blockpos = this.blockPosition(); +- BlockState blockstate = BaseFireBlock.getState(this.level(), blockpos); ++ BlockPos blockposition = this.blockPosition(); ++ IBlockData iblockdata = BaseFireBlock.getState(this.level(), blockposition); + +- if (this.level().getBlockState(blockpos).isAir() && blockstate.canSurvive(this.level(), blockpos)) { +- this.level().setBlockAndUpdate(blockpos, blockstate); +- ++this.blocksSetOnFire; ++ if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) { ++ // CraftBukkit start - add "!visualOnly" ++ if (!visualOnly && !CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition, this).isCancelled()) { ++ this.level().setBlockAndUpdate(blockposition, iblockdata); ++ ++this.blocksSetOnFire; ++ } ++ // CraftBukkit end + } + +- for (int j = 0; j < i; ++j) { +- BlockPos blockpos1 = blockpos.offset(this.random.nextInt(3) - 1, this.random.nextInt(3) - 1, this.random.nextInt(3) - 1); ++ for (int j = 0; j < extraIgnitions; ++j) { ++ BlockPos blockposition1 = blockposition.offset(this.random.nextInt(3) - 1, this.random.nextInt(3) - 1, this.random.nextInt(3) - 1); + +- blockstate = BaseFireBlock.getState(this.level(), blockpos1); +- if (this.level().getBlockState(blockpos1).isAir() && blockstate.canSurvive(this.level(), blockpos1)) { +- this.level().setBlockAndUpdate(blockpos1, blockstate); +- ++this.blocksSetOnFire; ++ iblockdata = BaseFireBlock.getState(this.level(), blockposition1); ++ if (this.level().getBlockState(blockposition1).isAir() && iblockdata.canSurvive(this.level(), blockposition1)) { ++ // CraftBukkit start - add "!visualOnly" ++ if (!visualOnly && !CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition1, this).isCancelled()) { ++ this.level().setBlockAndUpdate(blockposition1, iblockdata); ++ ++this.blocksSetOnFire; ++ } ++ // CraftBukkit end + } + } + + } + } + +- private static void clearCopperOnLightningStrike(Level level, BlockPos blockpos) { +- BlockState blockstate = level.getBlockState(blockpos); +- BlockPos blockpos1; +- BlockState blockstate1; ++ private static void clearCopperOnLightningStrike(Level level, BlockPos pos) { ++ IBlockData iblockdata = level.getBlockState(pos); ++ BlockPos blockposition1; ++ IBlockData iblockdata1; + +- if (blockstate.is(Blocks.LIGHTNING_ROD)) { +- blockpos1 = blockpos.relative(((Direction) blockstate.getValue(LightningRodBlock.FACING)).getOpposite()); +- blockstate1 = level.getBlockState(blockpos1); ++ if (iblockdata.is(Blocks.LIGHTNING_ROD)) { ++ blockposition1 = pos.relative(((Direction) iblockdata.getValue(LightningRodBlock.FACING)).getOpposite()); ++ iblockdata1 = level.getBlockState(blockposition1); + } else { +- blockpos1 = blockpos; +- blockstate1 = blockstate; ++ blockposition1 = pos; ++ iblockdata1 = iblockdata; + } + +- if (blockstate1.getBlock() instanceof WeatheringCopper) { +- level.setBlockAndUpdate(blockpos1, WeatheringCopper.getFirst(level.getBlockState(blockpos1))); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = blockpos.mutable(); ++ if (iblockdata1.getBlock() instanceof WeatheringCopper) { ++ level.setBlockAndUpdate(blockposition1, WeatheringCopper.getFirst(level.getBlockState(blockposition1))); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); + int i = level.random.nextInt(3) + 3; + + for (int j = 0; j < i; ++j) { + int k = level.random.nextInt(8) + 1; + +- randomWalkCleaningCopper(level, blockpos1, blockpos_mutableblockpos, k); ++ randomWalkCleaningCopper(level, blockposition1, blockposition_mutableblockposition, k); + } + + } + } + +- private static void randomWalkCleaningCopper(Level level, BlockPos blockpos, BlockPos.MutableBlockPos blockpos_mutableblockpos, int i) { +- blockpos_mutableblockpos.set(blockpos); ++ private static void randomWalkCleaningCopper(Level level, BlockPos pos, BlockPos.MutableBlockPos mutable, int steps) { ++ mutable.set(pos); + +- for (int j = 0; j < i; ++j) { +- Optional optional = randomStepCleaningCopper(level, blockpos_mutableblockpos); ++ for (int j = 0; j < steps; ++j) { ++ Optional optional = randomStepCleaningCopper(level, mutable); + + if (optional.isEmpty()) { + break; + } + +- blockpos_mutableblockpos.set((Vec3i) optional.get()); ++ mutable.set((Vec3i) optional.get()); + } + + } + +- private static Optional randomStepCleaningCopper(Level level, BlockPos blockpos) { +- Iterator iterator = BlockPos.randomInCube(level.random, 10, blockpos, 1).iterator(); ++ private static Optional randomStepCleaningCopper(Level level, BlockPos pos) { ++ Iterator iterator = BlockPos.randomInCube(level.random, 10, pos, 1).iterator(); + +- BlockPos blockpos1; +- BlockState blockstate; ++ BlockPos blockposition1; ++ IBlockData iblockdata; + + do { + if (!iterator.hasNext()) { + return Optional.empty(); + } + +- blockpos1 = (BlockPos) iterator.next(); +- blockstate = level.getBlockState(blockpos1); +- } while (!(blockstate.getBlock() instanceof WeatheringCopper)); ++ blockposition1 = (BlockPos) iterator.next(); ++ iblockdata = level.getBlockState(blockposition1); ++ } while (!(iblockdata.getBlock() instanceof WeatheringCopper)); + +- WeatheringCopper.getPrevious(blockstate).ifPresent((blockstate1) -> { +- level.setBlockAndUpdate(blockpos1, blockstate1); ++ BlockPos blockposition1Final = blockposition1; // CraftBukkit - decompile error ++ WeatheringCopper.getPrevious(iblockdata).ifPresent((iblockdata1) -> { ++ level.setBlockAndUpdate(blockposition1Final, iblockdata1); // CraftBukkit - decompile error + }); +- level.levelEvent(3002, blockpos1, -1); +- return Optional.of(blockpos1); ++ level.levelEvent(3002, blockposition1, -1); ++ return Optional.of(blockposition1); + } + + @Override +- @Override +- public boolean shouldRenderAtSqrDistance(double d0) { ++ public boolean shouldRenderAtSqrDistance(double distance) { + double d1 = 64.0D * getViewScale(); + +- return d0 < d1 * d1; ++ return distance < d1 * d1; + } + + @Override +- @Override + protected void defineSynchedData() {} + + @Override +- @Override +- protected void readAdditionalSaveData(CompoundTag compoundtag) {} ++ protected void readAdditionalSaveData(CompoundTag compound) {} + + @Override +- @Override +- protected void addAdditionalSaveData(CompoundTag compoundtag) {} ++ protected void addAdditionalSaveData(CompoundTag compound) {} + + public int getBlocksSetOnFire() { + return this.blocksSetOnFire; diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/LivingEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/LivingEntity.java.patch new file mode 100644 index 0000000000..aed1d14b87 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/LivingEntity.java.patch @@ -0,0 +1,4042 @@ +--- a/net/minecraft/world/entity/LivingEntity.java ++++ b/net/minecraft/world/entity/LivingEntity.java +@@ -29,6 +29,8 @@ + import net.minecraft.core.particles.ItemParticleOption; + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.FloatTag; ++import net.minecraft.nbt.IntTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtOps; + import net.minecraft.nbt.Tag; +@@ -59,7 +61,7 @@ + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.world.Difficulty; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.damagesource.CombatRules; + import net.minecraft.world.damagesource.CombatTracker; + import net.minecraft.world.damagesource.DamageSource; +@@ -76,20 +78,19 @@ + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.attributes.DefaultAttributes; + import net.minecraft.world.entity.ai.targeting.TargetingConditions; +-import net.minecraft.world.entity.animal.FlyingAnimal; ++import net.minecraft.world.entity.animal.EntityBird; + import net.minecraft.world.entity.animal.Wolf; + import net.minecraft.world.entity.boss.wither.WitherBoss; + import net.minecraft.world.entity.item.ItemEntity; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.AbstractArrow; + import net.minecraft.world.food.FoodProperties; + import net.minecraft.world.item.AxeItem; + import net.minecraft.world.item.ElytraItem; ++import net.minecraft.world.item.EnumAnimation; + import net.minecraft.world.item.Equipable; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +-import net.minecraft.world.item.UseAnim; + import net.minecraft.world.item.alchemy.PotionUtils; + import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.item.enchantment.Enchantments; +@@ -104,7 +105,7 @@ + import net.minecraft.world.level.block.PowderSnowBlock; + import net.minecraft.world.level.block.SoundType; + import net.minecraft.world.level.block.TrapDoorBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.entity.EntityTypeTest; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.Fluid; +@@ -119,6 +120,26 @@ + import net.minecraft.world.scores.PlayerTeam; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.HashSet; ++import java.util.Set; ++import com.google.common.base.Function; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.attribute.CraftAttributeMap; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.Player; ++import org.bukkit.event.entity.ArrowBodyCountChangeEvent; ++import org.bukkit.event.entity.EntityDamageEvent; ++import org.bukkit.event.entity.EntityDamageEvent.DamageModifier; ++import org.bukkit.event.entity.EntityPotionEffectEvent; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++import org.bukkit.event.entity.EntityResurrectEvent; ++import org.bukkit.event.entity.EntityTeleportEvent; ++import org.bukkit.event.player.PlayerItemConsumeEvent; ++// CraftBukkit end ++ + public abstract class LivingEntity extends Entity implements Attackable { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -146,23 +167,23 @@ + protected static final int LIVING_ENTITY_FLAG_OFF_HAND = 2; + protected static final int LIVING_ENTITY_FLAG_SPIN_ATTACK = 4; + protected static final EntityDataAccessor DATA_LIVING_ENTITY_FLAGS = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.BYTE); +- private static final EntityDataAccessor DATA_HEALTH_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.FLOAT); ++ public static final EntityDataAccessor DATA_HEALTH_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.FLOAT); + private static final EntityDataAccessor DATA_EFFECT_COLOR_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_EFFECT_AMBIENCE_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.BOOLEAN); +- private static final EntityDataAccessor DATA_ARROW_COUNT_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.INT); ++ public static final EntityDataAccessor DATA_ARROW_COUNT_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_STINGER_COUNT_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.INT); + private static final EntityDataAccessor> SLEEPING_POS_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.OPTIONAL_BLOCK_POS); + protected static final float DEFAULT_EYE_HEIGHT = 1.74F; + protected static final EntityDimensions SLEEPING_DIMENSIONS = EntityDimensions.fixed(0.2F, 0.2F); + public static final float EXTRA_RENDER_CULLING_SIZE_WITH_BIG_HAT = 0.5F; + private final AttributeMap attributes; +- private final CombatTracker combatTracker = new CombatTracker(this); +- private final Map activeEffects = Maps.newHashMap(); ++ public CombatTracker combatTracker = new CombatTracker(this); ++ public final Map activeEffects = Maps.newHashMap(); + private final NonNullList lastHandItemStacks; + private final NonNullList lastArmorItemStacks; + public boolean swinging; + private boolean discardFriction; +- public InteractionHand swingingArm; ++ public EnumHand swingingArm; + public int swingTime; + public int removeArrowTime; + public int removeStingerTime; +@@ -173,7 +194,7 @@ + public float attackAnim; + protected int attackStrengthTicker; + public final WalkAnimationState walkAnimation; +- public final int invulnerableDuration; ++ public int invulnerableDuration; + public final float timeOffs; + public final float rotA; + public float yBodyRot; +@@ -181,7 +202,7 @@ + public float yHeadRot; + public float yHeadRotO; + @Nullable +- protected Player lastHurtByPlayer; ++ public net.minecraft.world.entity.player.Player lastHurtByPlayer; + protected int lastHurtByPlayerTime; + protected boolean dead; + protected int noActionTime; +@@ -191,7 +212,7 @@ + protected float animStepO; + protected float rotOffs; + protected int deathScore; +- protected float lastHurt; ++ public float lastHurt; + protected boolean jumping; + public float xxa; + public float yya; +@@ -204,10 +225,10 @@ + protected double lerpXRot; + protected double lerpYHeadRot; + protected int lerpHeadSteps; +- private boolean effectsDirty; ++ public boolean effectsDirty; + @Nullable +- private LivingEntity lastHurtByMob; +- private int lastHurtByMobTimestamp; ++ public LivingEntity lastHurtByMob; ++ public int lastHurtByMobTimestamp; + private LivingEntity lastHurtMob; + private int lastHurtMobTimestamp; + private float speed; +@@ -226,9 +247,23 @@ + private float swimAmountO; + protected Brain brain; + private boolean skipDropExperience; ++ // CraftBukkit start ++ public int expToDrop; ++ public boolean forceDrops; ++ public ArrayList drops = new ArrayList(); ++ public final org.bukkit.craftbukkit.attribute.CraftAttributeMap craftAttributes; ++ public boolean collides = true; ++ public Set collidableExemptions = new HashSet<>(); ++ public boolean bukkitPickUpLoot; + +- protected LivingEntity(EntityType entitytype, Level level) { +- super(entitytype, level); ++ @Override ++ public float getBukkitYaw() { ++ return getYHeadRot(); ++ } ++ // CraftBukkit end ++ ++ protected LivingEntity(EntityType entityType, Level level) { ++ super(entityType, level); + this.lastHandItemStacks = NonNullList.withSize(2, ItemStack.EMPTY); + this.lastArmorItemStacks = NonNullList.withSize(4, ItemStack.EMPTY); + this.discardFriction = false; +@@ -237,8 +272,10 @@ + this.effectsDirty = true; + this.useItem = ItemStack.EMPTY; + this.lastClimbablePos = Optional.empty(); +- this.attributes = new AttributeMap(DefaultAttributes.getSupplier(entitytype)); +- this.setHealth(this.getMaxHealth()); ++ this.attributes = new AttributeMap(DefaultAttributes.getSupplier(entityType)); ++ this.craftAttributes = new CraftAttributeMap(attributes); // CraftBukkit ++ // CraftBukkit - setHealth(getMaxHealth()) inlined and simplified to skip the instanceof check for EntityPlayer, as getBukkitEntity() is not initialized in constructor ++ this.entityData.set(LivingEntity.DATA_HEALTH_ID, (float) this.getAttribute(Attributes.MAX_HEALTH).getValue()); + this.blocksBuilding = true; + this.rotA = (float) ((Math.random() + 1.0D) * 0.009999999776482582D); + this.reapplyPosition(); +@@ -246,9 +283,9 @@ + this.setYRot((float) (Math.random() * 6.2831854820251465D)); + this.yHeadRot = this.getYRot(); + this.setMaxUpStep(0.6F); +- NbtOps nbtops = NbtOps.INSTANCE; ++ NbtOps dynamicopsnbt = NbtOps.INSTANCE; + +- this.brain = this.makeBrain(new Dynamic(nbtops, (Tag) nbtops.createMap((Map) ImmutableMap.of(nbtops.createString("memories"), (Tag) nbtops.emptyMap())))); ++ this.brain = this.makeBrain(new Dynamic(dynamicopsnbt, (Tag) dynamicopsnbt.createMap((Map) ImmutableMap.of(dynamicopsnbt.createString("memories"), (Tag) dynamicopsnbt.emptyMap())))); + } + + public Brain getBrain() { +@@ -264,17 +301,15 @@ + } + + @Override +- @Override + public void kill() { + this.hurt(this.damageSources().genericKill(), Float.MAX_VALUE); + } + +- public boolean canAttackType(EntityType entitytype) { ++ public boolean canAttackType(EntityType entityType) { + return true; + } + + @Override +- @Override + protected void defineSynchedData() { + this.entityData.define(LivingEntity.DATA_LIVING_ENTITY_FLAGS, (byte) 0); + this.entityData.define(LivingEntity.DATA_EFFECT_COLOR_ID, 0); +@@ -290,8 +325,7 @@ + } + + @Override +- @Override +- protected void checkFallDamage(double d0, boolean flag, BlockState blockstate, BlockPos blockpos) { ++ protected void checkFallDamage(double y, boolean flag, IBlockData onGround, BlockPos state) { + if (!this.isInWater()) { + this.updateInWaterStateAndDoWaterCurrentPushing(); + } +@@ -301,29 +335,35 @@ + this.tryAddSoulSpeed(); + } + +- if (!this.level().isClientSide && this.fallDistance > 3.0F && flag && !blockstate.isAir()) { ++ if (!this.level().isClientSide && this.fallDistance > 3.0F && flag && !onGround.isAir()) { + double d1 = this.getX(); + double d2 = this.getY(); + double d3 = this.getZ(); +- BlockPos blockpos1 = this.blockPosition(); ++ BlockPos blockposition1 = this.blockPosition(); + +- if (blockpos.getX() != blockpos1.getX() || blockpos.getZ() != blockpos1.getZ()) { +- double d4 = d1 - (double) blockpos.getX() - 0.5D; +- double d5 = d3 - (double) blockpos.getZ() - 0.5D; ++ if (state.getX() != blockposition1.getX() || state.getZ() != blockposition1.getZ()) { ++ double d4 = d1 - (double) state.getX() - 0.5D; ++ double d5 = d3 - (double) state.getZ() - 0.5D; + double d6 = Math.max(Math.abs(d4), Math.abs(d5)); + +- d1 = (double) blockpos.getX() + 0.5D + d4 / d6 * 0.5D; +- d3 = (double) blockpos.getZ() + 0.5D + d5 / d6 * 0.5D; ++ d1 = (double) state.getX() + 0.5D + d4 / d6 * 0.5D; ++ d3 = (double) state.getZ() + 0.5D + d5 / d6 * 0.5D; + } + + float f = (float) Mth.ceil(this.fallDistance - 3.0F); + double d7 = Math.min((double) (0.2F + f / 15.0F), 2.5D); + int i = (int) (150.0D * d7); + +- ((ServerLevel) this.level()).sendParticles(new BlockParticleOption(ParticleTypes.BLOCK, blockstate), d1, d2, d3, i, 0.0D, 0.0D, 0.0D, 0.15000000596046448D); ++ // CraftBukkit start - visiblity api ++ if (this instanceof ServerPlayer) { ++ ((ServerLevel) this.level()).sendParticles((ServerPlayer) this, new BlockParticleOption(ParticleTypes.BLOCK, onGround), this.getX(), this.getY(), this.getZ(), i, 0.0D, 0.0D, 0.0D, 0.15000000596046448D, false); ++ } else { ++ ((ServerLevel) this.level()).sendParticles(new BlockParticleOption(ParticleTypes.BLOCK, onGround), d1, d2, d3, i, 0.0D, 0.0D, 0.0D, 0.15000000596046448D); ++ } ++ // CraftBukkit end + } + +- super.checkFallDamage(d0, flag, blockstate, blockpos); ++ super.checkFallDamage(y, flag, onGround, state); + if (flag) { + this.lastClimbablePos = Optional.empty(); + } +@@ -334,12 +374,11 @@ + return this.getType().is(EntityTypeTags.CAN_BREATHE_UNDER_WATER); + } + +- public float getSwimAmount(float f) { +- return Mth.lerp(f, this.swimAmountO, this.swimAmount); ++ public float getSwimAmount(float partialTicks) { ++ return Mth.lerp(partialTicks, this.swimAmountO, this.swimAmount); + } + + @Override +- @Override + public void baseTick() { + this.oAttackAnim = this.attackAnim; + if (this.firstTick) { +@@ -357,7 +396,7 @@ + } + + if (this.isAlive()) { +- boolean flag = this instanceof Player; ++ boolean flag = this instanceof net.minecraft.world.entity.player.Player; + + if (!this.level().isClientSide) { + if (this.isInWall()) { +@@ -376,20 +415,20 @@ + } + + if (this.isEyeInFluid(FluidTags.WATER) && !this.level().getBlockState(BlockPos.containing(this.getX(), this.getEyeY(), this.getZ())).is(Blocks.BUBBLE_COLUMN)) { +- boolean flag1 = !this.canBreatheUnderwater() && !MobEffectUtil.hasWaterBreathing(this) && (!flag || !((Player) this).getAbilities().invulnerable); ++ boolean flag1 = !this.canBreatheUnderwater() && !MobEffectUtil.hasWaterBreathing(this) && (!flag || !((net.minecraft.world.entity.player.Player) this).getAbilities().invulnerable); + + if (flag1) { + this.setAirSupply(this.decreaseAirSupply(this.getAirSupply())); + if (this.getAirSupply() == -20) { + this.setAirSupply(0); +- Vec3 vec3 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + + for (int i = 0; i < 8; ++i) { + double d2 = this.random.nextDouble() - this.random.nextDouble(); + double d3 = this.random.nextDouble() - this.random.nextDouble(); + double d4 = this.random.nextDouble() - this.random.nextDouble(); + +- this.level().addParticle(ParticleTypes.BUBBLE, this.getX() + d2, this.getY() + d3, this.getZ() + d4, vec3.x, vec3.y, vec3.z); ++ this.level().addParticle(ParticleTypes.BUBBLE, this.getX() + d2, this.getY() + d3, this.getZ() + d4, vec3d.x, vec3d.y, vec3d.z); + } + + this.hurt(this.damageSources().drown(), 2.0F); +@@ -404,11 +443,11 @@ + } + + if (!this.level().isClientSide) { +- BlockPos blockpos = this.blockPosition(); ++ BlockPos blockposition = this.blockPosition(); + +- if (!Objects.equal(this.lastPos, blockpos)) { +- this.lastPos = blockpos; +- this.onChangedBlock(blockpos); ++ if (!Objects.equal(this.lastPos, blockposition)) { ++ this.lastPos = blockposition; ++ this.onChangedBlock(blockposition); + } + } + } +@@ -461,9 +500,9 @@ + } + + protected void spawnSoulSpeedParticle() { +- Vec3 vec3 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + +- this.level().addParticle(ParticleTypes.SOUL, this.getX() + (this.random.nextDouble() - 0.5D) * (double) this.getBbWidth(), this.getY() + 0.1D, this.getZ() + (this.random.nextDouble() - 0.5D) * (double) this.getBbWidth(), vec3.x * -0.2D, 0.1D, vec3.z * -0.2D); ++ this.level().addParticle(ParticleTypes.SOUL, this.getX() + (this.random.nextDouble() - 0.5D) * (double) this.getBbWidth(), this.getY() + 0.1D, this.getZ() + (this.random.nextDouble() - 0.5D) * (double) this.getBbWidth(), vec3d.x * -0.2D, 0.1D, vec3d.z * -0.2D); + float f = this.random.nextFloat() * 0.4F + this.random.nextFloat() > 0.9F ? 0.6F : 0.0F; + + this.playSound(SoundEvents.SOUL_ESCAPE, f, 0.6F + this.random.nextFloat() * 0.4F); +@@ -474,21 +513,20 @@ + } + + @Override +- @Override + protected float getBlockSpeedFactor() { + return this.onSoulSpeedBlock() && EnchantmentHelper.getEnchantmentLevel(Enchantments.SOUL_SPEED, this) > 0 ? 1.0F : super.getBlockSpeedFactor(); + } + +- protected boolean shouldRemoveSoulSpeed(BlockState blockstate) { +- return !blockstate.isAir() || this.isFallFlying(); ++ protected boolean shouldRemoveSoulSpeed(IBlockData state) { ++ return !state.isAir() || this.isFallFlying(); + } + + protected void removeSoulSpeed() { +- AttributeInstance attributeinstance = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); + +- if (attributeinstance != null) { +- if (attributeinstance.getModifier(LivingEntity.SPEED_MODIFIER_SOUL_SPEED_UUID) != null) { +- attributeinstance.removeModifier(LivingEntity.SPEED_MODIFIER_SOUL_SPEED_UUID); ++ if (attributemodifiable != null) { ++ if (attributemodifiable.getModifier(LivingEntity.SPEED_MODIFIER_SOUL_SPEED_UUID) != null) { ++ attributemodifiable.removeModifier(LivingEntity.SPEED_MODIFIER_SOUL_SPEED_UUID); + } + + } +@@ -499,18 +537,18 @@ + int i = EnchantmentHelper.getEnchantmentLevel(Enchantments.SOUL_SPEED, this); + + if (i > 0 && this.onSoulSpeedBlock()) { +- AttributeInstance attributeinstance = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); + +- if (attributeinstance == null) { ++ if (attributemodifiable == null) { + return; + } + +- attributeinstance.addTransientModifier(new AttributeModifier(LivingEntity.SPEED_MODIFIER_SOUL_SPEED_UUID, "Soul speed boost", (double) (0.03F * (1.0F + (float) i * 0.35F)), AttributeModifier.Operation.ADDITION)); ++ attributemodifiable.addTransientModifier(new AttributeModifier(LivingEntity.SPEED_MODIFIER_SOUL_SPEED_UUID, "Soul speed boost", (double) (0.03F * (1.0F + (float) i * 0.35F)), AttributeModifier.Operation.ADDITION)); + if (this.getRandom().nextFloat() < 0.04F) { + ItemStack itemstack = this.getItemBySlot(EquipmentSlot.FEET); + +- itemstack.hurtAndBreak(1, this, (livingentity) -> { +- livingentity.broadcastBreakEvent(EquipmentSlot.FEET); ++ itemstack.hurtAndBreak(1, this, (entityliving) -> { ++ entityliving.broadcastBreakEvent(EquipmentSlot.FEET); + }); + } + } +@@ -519,11 +557,11 @@ + } + + protected void removeFrost() { +- AttributeInstance attributeinstance = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); + +- if (attributeinstance != null) { +- if (attributeinstance.getModifier(LivingEntity.SPEED_MODIFIER_POWDER_SNOW_UUID) != null) { +- attributeinstance.removeModifier(LivingEntity.SPEED_MODIFIER_POWDER_SNOW_UUID); ++ if (attributemodifiable != null) { ++ if (attributemodifiable.getModifier(LivingEntity.SPEED_MODIFIER_POWDER_SNOW_UUID) != null) { ++ attributemodifiable.removeModifier(LivingEntity.SPEED_MODIFIER_POWDER_SNOW_UUID); + } + + } +@@ -534,25 +572,25 @@ + int i = this.getTicksFrozen(); + + if (i > 0) { +- AttributeInstance attributeinstance = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); + +- if (attributeinstance == null) { ++ if (attributemodifiable == null) { + return; + } + + float f = -0.05F * this.getPercentFrozen(); + +- attributeinstance.addTransientModifier(new AttributeModifier(LivingEntity.SPEED_MODIFIER_POWDER_SNOW_UUID, "Powder snow slow", (double) f, AttributeModifier.Operation.ADDITION)); ++ attributemodifiable.addTransientModifier(new AttributeModifier(LivingEntity.SPEED_MODIFIER_POWDER_SNOW_UUID, "Powder snow slow", (double) f, AttributeModifier.Operation.ADDITION)); + } + } + + } + +- protected void onChangedBlock(BlockPos blockpos) { ++ protected void onChangedBlock(BlockPos pos) { + int i = EnchantmentHelper.getEnchantmentLevel(Enchantments.FROST_WALKER, this); + + if (i > 0) { +- FrostWalkerEnchantment.onEntityMoved(this, this.level(), blockpos, i); ++ FrostWalkerEnchantment.onEntityMoved(this, this.level(), pos, i); + } + + if (this.shouldRemoveSoulSpeed(this.getBlockStateOnLegacy())) { +@@ -591,14 +629,14 @@ + return !this.isBaby(); + } + +- protected int decreaseAirSupply(int i) { ++ protected int decreaseAirSupply(int currentAir) { + int j = EnchantmentHelper.getRespiration(this); + +- return j > 0 && this.random.nextInt(j + 1) > 0 ? i : i - 1; ++ return j > 0 && this.random.nextInt(j + 1) > 0 ? currentAir : currentAir - 1; + } + +- protected int increaseAirSupply(int i) { +- return Math.min(i + 4, this.getMaxAirSupply()); ++ protected int increaseAirSupply(int currentAir) { ++ return Math.min(currentAir + 4, this.getMaxAirSupply()); + } + + public int getExperienceReward() { +@@ -619,7 +657,6 @@ + } + + @Override +- @Override + public LivingEntity getLastAttacker() { + return this.getLastHurtByMob(); + } +@@ -628,13 +665,13 @@ + return this.lastHurtByMobTimestamp; + } + +- public void setLastHurtByPlayer(@Nullable Player player) { ++ public void setLastHurtByPlayer(@Nullable net.minecraft.world.entity.player.Player player) { + this.lastHurtByPlayer = player; + this.lastHurtByPlayerTime = this.tickCount; + } + +- public void setLastHurtByMob(@Nullable LivingEntity livingentity) { +- this.lastHurtByMob = livingentity; ++ public void setLastHurtByMob(@Nullable LivingEntity livingEntity) { ++ this.lastHurtByMob = livingEntity; + this.lastHurtByMobTimestamp = this.tickCount; + } + +@@ -661,34 +698,40 @@ + return this.noActionTime; + } + +- public void setNoActionTime(int i) { +- this.noActionTime = i; ++ public void setNoActionTime(int idleTime) { ++ this.noActionTime = idleTime; + } + + public boolean shouldDiscardFriction() { + return this.discardFriction; + } + +- public void setDiscardFriction(boolean flag) { +- this.discardFriction = flag; ++ public void setDiscardFriction(boolean discardFriction) { ++ this.discardFriction = discardFriction; + } + +- protected boolean doesEmitEquipEvent(EquipmentSlot equipmentslot) { ++ protected boolean doesEmitEquipEvent(EquipmentSlot slot) { + return true; + } + +- public void onEquipItem(EquipmentSlot equipmentslot, ItemStack itemstack, ItemStack itemstack1) { ++ public void onEquipItem(EquipmentSlot slot, ItemStack oldItem, ItemStack newItem) { ++ // CraftBukkit start ++ onEquipItem(slot, oldItem, newItem, false); ++ } ++ ++ public void onEquipItem(EquipmentSlot enumitemslot, ItemStack itemstack, ItemStack itemstack1, boolean silent) { ++ // CraftBukkit end + boolean flag = itemstack1.isEmpty() && itemstack.isEmpty(); + + if (!flag && !ItemStack.isSameItemSameTags(itemstack, itemstack1) && !this.firstTick) { + Equipable equipable = Equipable.get(itemstack1); + + if (!this.level().isClientSide() && !this.isSpectator()) { +- if (!this.isSilent() && equipable != null && equipable.getEquipmentSlot() == equipmentslot) { +- this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), equipable.getEquipSound(), this.getSoundSource(), 1.0F, 1.0F); ++ if (!this.isSilent() && equipable != null && equipable.getEquipmentSlot() == enumitemslot && !silent) { // CraftBukkit ++ this.level().playSound((net.minecraft.world.entity.player.Player) null, this.getX(), this.getY(), this.getZ(), equipable.getEquipSound(), this.getSoundSource(), 1.0F, 1.0F); + } + +- if (this.doesEmitEquipEvent(equipmentslot)) { ++ if (this.doesEmitEquipEvent(enumitemslot)) { + this.gameEvent(equipable != null ? GameEvent.EQUIP : GameEvent.UNEQUIP); + } + } +@@ -697,129 +740,177 @@ + } + + @Override +- @Override +- public void remove(Entity.RemovalReason entity_removalreason) { +- super.remove(entity_removalreason); ++ public void remove(Entity.RemovalReason reason) { ++ super.remove(reason); + this.brain.clearMemories(); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- compoundtag.putFloat("Health", this.getHealth()); +- compoundtag.putShort("HurtTime", (short) this.hurtTime); +- compoundtag.putInt("HurtByTimestamp", this.lastHurtByMobTimestamp); +- compoundtag.putShort("DeathTime", (short) this.deathTime); +- compoundtag.putFloat("AbsorptionAmount", this.getAbsorptionAmount()); +- compoundtag.put("Attributes", this.getAttributes().save()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ compound.putFloat("Health", this.getHealth()); ++ compound.putShort("HurtTime", (short) this.hurtTime); ++ compound.putInt("HurtByTimestamp", this.lastHurtByMobTimestamp); ++ compound.putShort("DeathTime", (short) this.deathTime); ++ compound.putFloat("AbsorptionAmount", this.getAbsorptionAmount()); ++ compound.put("Attributes", this.getAttributes().save()); + if (!this.activeEffects.isEmpty()) { +- ListTag listtag = new ListTag(); ++ ListTag nbttaglist = new ListTag(); + Iterator iterator = this.activeEffects.values().iterator(); + + while (iterator.hasNext()) { +- MobEffectInstance mobeffectinstance = (MobEffectInstance) iterator.next(); ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); + +- listtag.add(mobeffectinstance.save(new CompoundTag())); ++ nbttaglist.add(mobeffect.save(new CompoundTag())); + } + +- compoundtag.put("active_effects", listtag); ++ compound.put("active_effects", nbttaglist); + } + +- compoundtag.putBoolean("FallFlying", this.isFallFlying()); +- this.getSleepingPos().ifPresent((blockpos) -> { +- compoundtag.putInt("SleepingX", blockpos.getX()); +- compoundtag.putInt("SleepingY", blockpos.getY()); +- compoundtag.putInt("SleepingZ", blockpos.getZ()); ++ compound.putBoolean("FallFlying", this.isFallFlying()); ++ this.getSleepingPos().ifPresent((blockposition) -> { ++ compound.putInt("SleepingX", blockposition.getX()); ++ compound.putInt("SleepingY", blockposition.getY()); ++ compound.putInt("SleepingZ", blockposition.getZ()); + }); + DataResult dataresult = this.brain.serializeStart(NbtOps.INSTANCE); + Logger logger = LivingEntity.LOGGER; + + java.util.Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((tag) -> { +- compoundtag.put("Brain", tag); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("Brain", nbtbase); + }); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- this.internalSetAbsorptionAmount(compoundtag.getFloat("AbsorptionAmount")); +- if (compoundtag.contains("Attributes", 9) && this.level() != null && !this.level().isClientSide) { +- this.getAttributes().load(compoundtag.getList("Attributes", 10)); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ this.internalSetAbsorptionAmount(compound.getFloat("AbsorptionAmount")); ++ if (compound.contains("Attributes", 9) && this.level() != null && !this.level().isClientSide) { ++ this.getAttributes().load(compound.getList("Attributes", 10)); + } + +- if (compoundtag.contains("active_effects", 9)) { +- ListTag listtag = compoundtag.getList("active_effects", 10); ++ if (compound.contains("active_effects", 9)) { ++ ListTag nbttaglist = compound.getList("active_effects", 10); + +- for (int i = 0; i < listtag.size(); ++i) { +- CompoundTag compoundtag1 = listtag.getCompound(i); +- MobEffectInstance mobeffectinstance = MobEffectInstance.load(compoundtag1); ++ for (int i = 0; i < nbttaglist.size(); ++i) { ++ CompoundTag nbttagcompound1 = nbttaglist.getCompound(i); ++ MobEffectInstance mobeffect = MobEffectInstance.load(nbttagcompound1); + +- if (mobeffectinstance != null) { +- this.activeEffects.put(mobeffectinstance.getEffect(), mobeffectinstance); ++ if (mobeffect != null) { ++ this.activeEffects.put(mobeffect.getEffect(), mobeffect); + } + } + } + +- if (compoundtag.contains("Health", 99)) { +- this.setHealth(compoundtag.getFloat("Health")); ++ // CraftBukkit start ++ if (compound.contains("Bukkit.MaxHealth")) { ++ Tag nbtbase = compound.get("Bukkit.MaxHealth"); ++ if (nbtbase.getId() == 5) { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(((FloatTag) nbtbase).getAsDouble()); ++ } else if (nbtbase.getId() == 3) { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(((IntTag) nbtbase).getAsDouble()); ++ } + } ++ // CraftBukkit end + +- this.hurtTime = compoundtag.getShort("HurtTime"); +- this.deathTime = compoundtag.getShort("DeathTime"); +- this.lastHurtByMobTimestamp = compoundtag.getInt("HurtByTimestamp"); +- if (compoundtag.contains("Team", 8)) { +- String s = compoundtag.getString("Team"); +- PlayerTeam playerteam = this.level().getScoreboard().getPlayerTeam(s); +- boolean flag = playerteam != null && this.level().getScoreboard().addPlayerToTeam(this.getStringUUID(), playerteam); ++ if (compound.contains("Health", 99)) { ++ this.setHealth(compound.getFloat("Health")); ++ } + ++ this.hurtTime = compound.getShort("HurtTime"); ++ this.deathTime = compound.getShort("DeathTime"); ++ this.lastHurtByMobTimestamp = compound.getInt("HurtByTimestamp"); ++ if (compound.contains("Team", 8)) { ++ String s = compound.getString("Team"); ++ PlayerTeam scoreboardteam = this.level().getScoreboard().getPlayerTeam(s); ++ boolean flag = scoreboardteam != null && this.level().getScoreboard().addPlayerToTeam(this.getStringUUID(), scoreboardteam); ++ + if (!flag) { + LivingEntity.LOGGER.warn("Unable to add mob to team \"{}\" (that team probably doesn't exist)", s); + } + } + +- if (compoundtag.getBoolean("FallFlying")) { ++ if (compound.getBoolean("FallFlying")) { + this.setSharedFlag(7, true); + } + +- if (compoundtag.contains("SleepingX", 99) && compoundtag.contains("SleepingY", 99) && compoundtag.contains("SleepingZ", 99)) { +- BlockPos blockpos = new BlockPos(compoundtag.getInt("SleepingX"), compoundtag.getInt("SleepingY"), compoundtag.getInt("SleepingZ")); ++ if (compound.contains("SleepingX", 99) && compound.contains("SleepingY", 99) && compound.contains("SleepingZ", 99)) { ++ BlockPos blockposition = new BlockPos(compound.getInt("SleepingX"), compound.getInt("SleepingY"), compound.getInt("SleepingZ")); + +- this.setSleepingPos(blockpos); +- this.entityData.set(LivingEntity.DATA_POSE, Pose.SLEEPING); ++ this.setSleepingPos(blockposition); ++ this.entityData.set(LivingEntity.DATA_POSE, EntityPose.SLEEPING); + if (!this.firstTick) { +- this.setPosToBed(blockpos); ++ this.setPosToBed(blockposition); + } + } + +- if (compoundtag.contains("Brain", 10)) { +- this.brain = this.makeBrain(new Dynamic(NbtOps.INSTANCE, compoundtag.get("Brain"))); ++ if (compound.contains("Brain", 10)) { ++ this.brain = this.makeBrain(new Dynamic(NbtOps.INSTANCE, compound.get("Brain"))); + } + + } + ++ // CraftBukkit start ++ private boolean isTickingEffects = false; ++ private List effectsToProcess = Lists.newArrayList(); ++ ++ private static class ProcessableEffect { ++ ++ private MobEffect type; ++ private MobEffectInstance effect; ++ private final EntityPotionEffectEvent.Cause cause; ++ ++ private ProcessableEffect(MobEffectInstance effect, EntityPotionEffectEvent.Cause cause) { ++ this.effect = effect; ++ this.cause = cause; ++ } ++ ++ private ProcessableEffect(MobEffect type, EntityPotionEffectEvent.Cause cause) { ++ this.type = type; ++ this.cause = cause; ++ } ++ } ++ // CraftBukkit end ++ + protected void tickEffects() { + Iterator iterator = this.activeEffects.keySet().iterator(); + ++ isTickingEffects = true; // CraftBukkit + try { + while (iterator.hasNext()) { +- MobEffect mobeffect = (MobEffect) iterator.next(); +- MobEffectInstance mobeffectinstance = (MobEffectInstance) this.activeEffects.get(mobeffect); ++ MobEffect mobeffectlist = (MobEffect) iterator.next(); ++ MobEffectInstance mobeffect = (MobEffectInstance) this.activeEffects.get(mobeffectlist); + +- if (!mobeffectinstance.tick(this, () -> { +- this.onEffectUpdated(mobeffectinstance, true, (Entity) null); ++ if (!mobeffect.tick(this, () -> { ++ this.onEffectUpdated(mobeffect, true, (Entity) null); + })) { + if (!this.level().isClientSide) { ++ // CraftBukkit start ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, mobeffect, null, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.EXPIRATION); ++ if (event.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end + iterator.remove(); +- this.onEffectRemoved(mobeffectinstance); ++ this.onEffectRemoved(mobeffect); + } +- } else if (mobeffectinstance.getDuration() % 600 == 0) { +- this.onEffectUpdated(mobeffectinstance, false, (Entity) null); ++ } else if (mobeffect.getDuration() % 600 == 0) { ++ this.onEffectUpdated(mobeffect, false, (Entity) null); + } + } + } catch (ConcurrentModificationException concurrentmodificationexception) { + ; + } ++ // CraftBukkit start ++ isTickingEffects = false; ++ for (ProcessableEffect e : effectsToProcess) { ++ if (e.effect != null) { ++ addEffect(e.effect, e.cause); ++ } else { ++ removeEffect(e.type, e.cause); ++ } ++ } ++ effectsToProcess.clear(); ++ // CraftBukkit end + + if (this.effectsDirty) { + if (!this.level().isClientSide) { +@@ -880,7 +971,7 @@ + + } + +- public double getVisibilityPercent(@Nullable Entity entity) { ++ public double getVisibilityPercent(@Nullable Entity lookingEntity) { + double d0 = 1.0D; + + if (this.isDiscrete()) { +@@ -897,11 +988,11 @@ + d0 *= 0.7D * (double) f; + } + +- if (entity != null) { ++ if (lookingEntity != null) { + ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); +- EntityType entitytype = entity.getType(); ++ EntityType entitytypes = lookingEntity.getType(); + +- if (entitytype == EntityType.SKELETON && itemstack.is(Items.SKELETON_SKULL) || entitytype == EntityType.ZOMBIE && itemstack.is(Items.ZOMBIE_HEAD) || entitytype == EntityType.PIGLIN && itemstack.is(Items.PIGLIN_HEAD) || entitytype == EntityType.PIGLIN_BRUTE && itemstack.is(Items.PIGLIN_HEAD) || entitytype == EntityType.CREEPER && itemstack.is(Items.CREEPER_HEAD)) { ++ if (entitytypes == EntityType.SKELETON && itemstack.is(Items.SKELETON_SKULL) || entitytypes == EntityType.ZOMBIE && itemstack.is(Items.ZOMBIE_HEAD) || entitytypes == EntityType.PIGLIN && itemstack.is(Items.PIGLIN_HEAD) || entitytypes == EntityType.PIGLIN_BRUTE && itemstack.is(Items.PIGLIN_HEAD) || entitytypes == EntityType.CREEPER && itemstack.is(Items.CREEPER_HEAD)) { + d0 *= 0.5D; + } + } +@@ -909,12 +1000,12 @@ + return d0; + } + +- public boolean canAttack(LivingEntity livingentity) { +- return livingentity instanceof Player && this.level().getDifficulty() == Difficulty.PEACEFUL ? false : livingentity.canBeSeenAsEnemy(); ++ public boolean canAttack(LivingEntity target) { ++ return target instanceof net.minecraft.world.entity.player.Player && this.level().getDifficulty() == Difficulty.PEACEFUL ? false : target.canBeSeenAsEnemy(); + } + +- public boolean canAttack(LivingEntity livingentity, TargetingConditions targetingconditions) { +- return targetingconditions.test(this, livingentity); ++ public boolean canAttack(LivingEntity livingentity, TargetingConditions condition) { ++ return condition.test(this, livingentity); + } + + public boolean canBeSeenAsEnemy() { +@@ -925,18 +1016,18 @@ + return !this.isSpectator() && this.isAlive(); + } + +- public static boolean areAllEffectsAmbient(Collection collection) { +- Iterator iterator = collection.iterator(); ++ public static boolean areAllEffectsAmbient(Collection potionEffects) { ++ Iterator iterator = potionEffects.iterator(); + +- MobEffectInstance mobeffectinstance; ++ MobEffectInstance mobeffect; + + do { + if (!iterator.hasNext()) { + return true; + } + +- mobeffectinstance = (MobEffectInstance) iterator.next(); +- } while (!mobeffectinstance.isVisible() || mobeffectinstance.isAmbient()); ++ mobeffect = (MobEffectInstance) iterator.next(); ++ } while (!mobeffect.isVisible() || mobeffect.isAmbient()); + + return false; + } +@@ -946,7 +1037,13 @@ + this.entityData.set(LivingEntity.DATA_EFFECT_COLOR_ID, 0); + } + ++ // CraftBukkit start + public boolean removeAllEffects() { ++ return removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean removeAllEffects(EntityPotionEffectEvent.Cause cause) { ++ // CraftBukkit end + if (this.level().isClientSide) { + return false; + } else { +@@ -955,7 +1052,14 @@ + boolean flag; + + for (flag = false; iterator.hasNext(); flag = true) { +- this.onEffectRemoved((MobEffectInstance) iterator.next()); ++ // CraftBukkit start ++ MobEffectInstance effect = (MobEffectInstance) iterator.next(); ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, effect, null, cause, EntityPotionEffectEvent.Action.CLEARED); ++ if (event.isCancelled()) { ++ continue; ++ } ++ this.onEffectRemoved(effect); ++ // CraftBukkit end + iterator.remove(); + } + +@@ -971,45 +1075,75 @@ + return this.activeEffects; + } + +- public boolean hasEffect(MobEffect mobeffect) { +- return this.activeEffects.containsKey(mobeffect); ++ public boolean hasEffect(MobEffect effect) { ++ return this.activeEffects.containsKey(effect); + } + + @Nullable +- public MobEffectInstance getEffect(MobEffect mobeffect) { +- return (MobEffectInstance) this.activeEffects.get(mobeffect); ++ public MobEffectInstance getEffect(MobEffect effect) { ++ return (MobEffectInstance) this.activeEffects.get(effect); + } + +- public final boolean addEffect(MobEffectInstance mobeffectinstance) { +- return this.addEffect(mobeffectinstance, (Entity) null); ++ public final boolean addEffect(MobEffectInstance effectInstance) { ++ return this.addEffect(effectInstance, (Entity) null); + } + +- public boolean addEffect(MobEffectInstance mobeffectinstance, @Nullable Entity entity) { +- if (!this.canBeAffected(mobeffectinstance)) { ++ // CraftBukkit start ++ public boolean addEffect(MobEffectInstance mobeffect, EntityPotionEffectEvent.Cause cause) { ++ return this.addEffect(mobeffect, (Entity) null, cause); ++ } ++ ++ public boolean addEffect(MobEffectInstance effectInstance, @Nullable Entity entity) { ++ return this.addEffect(effectInstance, entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean addEffect(MobEffectInstance mobeffect, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause) { ++ if (isTickingEffects) { ++ effectsToProcess.add(new ProcessableEffect(mobeffect, cause)); ++ return true; ++ } ++ // CraftBukkit end ++ ++ if (!this.canBeAffected(mobeffect)) { + return false; + } else { +- MobEffectInstance mobeffectinstance1 = (MobEffectInstance) this.activeEffects.get(mobeffectinstance.getEffect()); ++ MobEffectInstance mobeffect1 = (MobEffectInstance) this.activeEffects.get(mobeffect.getEffect()); + boolean flag = false; + +- if (mobeffectinstance1 == null) { +- this.activeEffects.put(mobeffectinstance.getEffect(), mobeffectinstance); +- this.onEffectAdded(mobeffectinstance, entity); ++ // CraftBukkit start ++ boolean override = false; ++ if (mobeffect1 != null) { ++ override = new MobEffectInstance(mobeffect1).update(mobeffect); ++ } ++ ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, mobeffect1, mobeffect, cause, override); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ ++ if (mobeffect1 == null) { ++ this.activeEffects.put(mobeffect.getEffect(), mobeffect); ++ this.onEffectAdded(mobeffect, entity); + flag = true; +- } else if (mobeffectinstance1.update(mobeffectinstance)) { +- this.onEffectUpdated(mobeffectinstance1, true, entity); ++ // CraftBukkit start ++ } else if (event.isOverride()) { ++ mobeffect1.update(mobeffect); ++ this.onEffectUpdated(mobeffect1, true, entity); ++ // CraftBukkit end + flag = true; + } + +- mobeffectinstance.onEffectStarted(this); ++ mobeffect.onEffectStarted(this); + return flag; + } + } + +- public boolean canBeAffected(MobEffectInstance mobeffectinstance) { +- if (this.getMobType() == MobType.UNDEAD) { +- MobEffect mobeffect = mobeffectinstance.getEffect(); ++ public boolean canBeAffected(MobEffectInstance effectInstance) { ++ if (this.getMobType() == EnumMonsterType.UNDEAD) { ++ MobEffect mobeffectlist = effectInstance.getEffect(); + +- if (mobeffect == MobEffects.REGENERATION || mobeffect == MobEffects.POISON) { ++ if (mobeffectlist == MobEffects.REGENERATION || mobeffectlist == MobEffects.POISON) { + return false; + } + } +@@ -1017,83 +1151,109 @@ + return true; + } + +- public void forceAddEffect(MobEffectInstance mobeffectinstance, @Nullable Entity entity) { +- if (this.canBeAffected(mobeffectinstance)) { +- MobEffectInstance mobeffectinstance1 = (MobEffectInstance) this.activeEffects.put(mobeffectinstance.getEffect(), mobeffectinstance); ++ public void forceAddEffect(MobEffectInstance instance, @Nullable Entity entity) { ++ if (this.canBeAffected(instance)) { ++ MobEffectInstance mobeffect1 = (MobEffectInstance) this.activeEffects.put(instance.getEffect(), instance); + +- if (mobeffectinstance1 == null) { +- this.onEffectAdded(mobeffectinstance, entity); ++ if (mobeffect1 == null) { ++ this.onEffectAdded(instance, entity); + } else { +- this.onEffectUpdated(mobeffectinstance, true, entity); ++ this.onEffectUpdated(instance, true, entity); + } + + } + } + + public boolean isInvertedHealAndHarm() { +- return this.getMobType() == MobType.UNDEAD; ++ return this.getMobType() == EnumMonsterType.UNDEAD; + } + ++ // CraftBukkit start + @Nullable +- public MobEffectInstance removeEffectNoUpdate(@Nullable MobEffect mobeffect) { +- return (MobEffectInstance) this.activeEffects.remove(mobeffect); ++ public MobEffectInstance removeEffectNoUpdate(@Nullable MobEffect effect) { ++ return c(effect, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); + } + +- public boolean removeEffect(MobEffect mobeffect) { +- MobEffectInstance mobeffectinstance = this.removeEffectNoUpdate(mobeffect); ++ @Nullable ++ public MobEffectInstance c(@Nullable MobEffect mobeffectlist, EntityPotionEffectEvent.Cause cause) { ++ if (isTickingEffects) { ++ effectsToProcess.add(new ProcessableEffect(mobeffectlist, cause)); ++ return null; ++ } + +- if (mobeffectinstance != null) { +- this.onEffectRemoved(mobeffectinstance); ++ MobEffectInstance effect = this.activeEffects.get(mobeffectlist); ++ if (effect == null) { ++ return null; ++ } ++ ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, effect, null, cause); ++ if (event.isCancelled()) { ++ return null; ++ } ++ ++ return (MobEffectInstance) this.activeEffects.remove(mobeffectlist); ++ } ++ ++ public boolean removeEffect(MobEffect effect) { ++ return removeEffect(effect, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean removeEffect(MobEffect mobeffectlist, EntityPotionEffectEvent.Cause cause) { ++ MobEffectInstance mobeffect = this.c(mobeffectlist, cause); ++ // CraftBukkit end ++ ++ if (mobeffect != null) { ++ this.onEffectRemoved(mobeffect); + return true; + } else { + return false; + } + } + +- protected void onEffectAdded(MobEffectInstance mobeffectinstance, @Nullable Entity entity) { ++ protected void onEffectAdded(MobEffectInstance effectInstance, @Nullable Entity entity) { + this.effectsDirty = true; + if (!this.level().isClientSide) { +- mobeffectinstance.getEffect().addAttributeModifiers(this.getAttributes(), mobeffectinstance.getAmplifier()); +- this.sendEffectToPassengers(mobeffectinstance); ++ effectInstance.getEffect().addAttributeModifiers(this.getAttributes(), effectInstance.getAmplifier()); ++ this.sendEffectToPassengers(effectInstance); + } + + } + +- public void sendEffectToPassengers(MobEffectInstance mobeffectinstance) { ++ public void sendEffectToPassengers(MobEffectInstance effectInstance) { + Iterator iterator = this.getPassengers().iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); + + if (entity instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) entity; ++ ServerPlayer entityplayer = (ServerPlayer) entity; + +- serverplayer.connection.send(new ClientboundUpdateMobEffectPacket(this.getId(), mobeffectinstance)); ++ entityplayer.connection.send(new ClientboundUpdateMobEffectPacket(this.getId(), effectInstance)); + } + } + + } + +- protected void onEffectUpdated(MobEffectInstance mobeffectinstance, boolean flag, @Nullable Entity entity) { ++ protected void onEffectUpdated(MobEffectInstance effectInstance, boolean forced, @Nullable Entity entity) { + this.effectsDirty = true; +- if (flag && !this.level().isClientSide) { +- MobEffect mobeffect = mobeffectinstance.getEffect(); ++ if (forced && !this.level().isClientSide) { ++ MobEffect mobeffectlist = effectInstance.getEffect(); + +- mobeffect.removeAttributeModifiers(this.getAttributes()); +- mobeffect.addAttributeModifiers(this.getAttributes(), mobeffectinstance.getAmplifier()); ++ mobeffectlist.removeAttributeModifiers(this.getAttributes()); ++ mobeffectlist.addAttributeModifiers(this.getAttributes(), effectInstance.getAmplifier()); + this.refreshDirtyAttributes(); + } + + if (!this.level().isClientSide) { +- this.sendEffectToPassengers(mobeffectinstance); ++ this.sendEffectToPassengers(effectInstance); + } + + } + +- protected void onEffectRemoved(MobEffectInstance mobeffectinstance) { ++ protected void onEffectRemoved(MobEffectInstance effectInstance) { + this.effectsDirty = true; + if (!this.level().isClientSide) { +- mobeffectinstance.getEffect().removeAttributeModifiers(this.getAttributes()); ++ effectInstance.getEffect().removeAttributeModifiers(this.getAttributes()); + this.refreshDirtyAttributes(); + Iterator iterator = this.getPassengers().iterator(); + +@@ -1101,9 +1261,9 @@ + Entity entity = (Entity) iterator.next(); + + if (entity instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) entity; ++ ServerPlayer entityplayer = (ServerPlayer) entity; + +- serverplayer.connection.send(new ClientboundRemoveMobEffectPacket(this.getId(), mobeffectinstance.getEffect())); ++ entityplayer.connection.send(new ClientboundRemoveMobEffectPacket(this.getId(), effectInstance.getEffect())); + } + } + } +@@ -1114,22 +1274,22 @@ + Iterator iterator = this.getAttributes().getDirtyAttributes().iterator(); + + while (iterator.hasNext()) { +- AttributeInstance attributeinstance = (AttributeInstance) iterator.next(); ++ AttributeInstance attributemodifiable = (AttributeInstance) iterator.next(); + +- this.onAttributeUpdated(attributeinstance.getAttribute()); ++ this.onAttributeUpdated(attributemodifiable.getAttribute()); + } + + } + +- private void onAttributeUpdated(Attribute attribute) { ++ private void onAttributeUpdated(Attribute attributebase) { + float f; + +- if (attribute == Attributes.MAX_HEALTH) { ++ if (attributebase == Attributes.MAX_HEALTH) { + f = this.getMaxHealth(); + if (this.getHealth() > f) { + this.setHealth(f); + } +- } else if (attribute == Attributes.MAX_ABSORPTION) { ++ } else if (attributebase == Attributes.MAX_ABSORPTION) { + f = this.getMaxAbsorption(); + if (this.getAbsorptionAmount() > f) { + this.setAbsorptionAmount(f); +@@ -1138,21 +1298,56 @@ + + } + +- public void heal(float f) { ++ // CraftBukkit start - Delegate so we can handle providing a reason for health being regained ++ public void heal(float healAmount) { ++ heal(healAmount, EntityRegainHealthEvent.RegainReason.CUSTOM); ++ } ++ ++ public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason) { + float f1 = this.getHealth(); + + if (f1 > 0.0F) { +- this.setHealth(f1 + f); ++ EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason); ++ // Suppress during worldgen ++ if (this.valid) { ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (!event.isCancelled()) { ++ this.setHealth((float) (this.getHealth() + event.getAmount())); ++ } ++ // CraftBukkit end + } + + } + + public float getHealth() { ++ // CraftBukkit start - Use unscaled health ++ if (this instanceof ServerPlayer) { ++ return (float) ((ServerPlayer) this).getBukkitEntity().getHealth(); ++ } ++ // CraftBukkit end + return (Float) this.entityData.get(LivingEntity.DATA_HEALTH_ID); + } + +- public void setHealth(float f) { +- this.entityData.set(LivingEntity.DATA_HEALTH_ID, Mth.clamp(f, 0.0F, this.getMaxHealth())); ++ public void setHealth(float health) { ++ // CraftBukkit start - Handle scaled health ++ if (this instanceof ServerPlayer) { ++ org.bukkit.craftbukkit.entity.CraftPlayer player = ((ServerPlayer) this).getBukkitEntity(); ++ // Squeeze ++ if (health < 0.0F) { ++ player.setRealHealth(0.0D); ++ } else if (health > player.getMaxHealth()) { ++ player.setRealHealth(player.getMaxHealth()); ++ } else { ++ player.setRealHealth(health); ++ } ++ ++ player.updateScaledHealth(false); ++ return; ++ } ++ // CraftBukkit end ++ this.entityData.set(LivingEntity.DATA_HEALTH_ID, Mth.clamp(health, 0.0F, this.getMaxHealth())); + } + + public boolean isDeadOrDying() { +@@ -1160,15 +1355,14 @@ + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- if (this.isInvulnerableTo(damagesource)) { ++ public boolean hurt(DamageSource source, float amount) { ++ if (this.isInvulnerableTo(source)) { + return false; + } else if (this.level().isClientSide) { + return false; +- } else if (this.isDeadOrDying()) { ++ } else if (this.isRemoved() || this.dead || this.getHealth() <= 0.0F) { // CraftBukkit - Don't allow entities that got set to dead/killed elsewhere to get damaged and die + return false; +- } else if (damagesource.is(DamageTypeTags.IS_FIRE) && this.hasEffect(MobEffects.FIRE_RESISTANCE)) { ++ } else if (source.is(DamageTypeTags.IS_FIRE) && this.hasEffect(MobEffects.FIRE_RESISTANCE)) { + return false; + } else { + if (this.isSleeping() && !this.level().isClientSide) { +@@ -1176,82 +1370,93 @@ + } + + this.noActionTime = 0; +- float f1 = f; +- boolean flag = false; ++ float f1 = amount; ++ boolean flag = amount > 0.0F && this.isDamageSourceBlocked(source); // Copied from below + float f2 = 0.0F; + +- if (f > 0.0F && this.isDamageSourceBlocked(damagesource)) { +- this.hurtCurrentlyUsedShield(f); +- f2 = f; +- f = 0.0F; +- if (!damagesource.is(DamageTypeTags.IS_PROJECTILE)) { +- Entity entity = damagesource.getDirectEntity(); ++ // CraftBukkit - Moved into damageEntity0(DamageSource, float) ++ if (false && amount > 0.0F && this.isDamageSourceBlocked(source)) { ++ this.hurtCurrentlyUsedShield(amount); ++ f2 = amount; ++ amount = 0.0F; ++ if (!source.is(DamageTypeTags.IS_PROJECTILE)) { ++ Entity entity = source.getDirectEntity(); + + if (entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; ++ LivingEntity entityliving = (LivingEntity) entity; + +- this.blockUsingShield(livingentity); ++ this.blockUsingShield(entityliving); + } + } + + flag = true; + } + +- if (damagesource.is(DamageTypeTags.IS_FREEZING) && this.getType().is(EntityTypeTags.FREEZE_HURTS_EXTRA_TYPES)) { +- f *= 5.0F; ++ if (source.is(DamageTypeTags.IS_FREEZING) && this.getType().is(EntityTypeTags.FREEZE_HURTS_EXTRA_TYPES)) { ++ amount *= 5.0F; + } + + this.walkAnimation.setSpeed(1.5F); + boolean flag1 = true; + +- if ((float) this.invulnerableTime > 10.0F && !damagesource.is(DamageTypeTags.BYPASSES_COOLDOWN)) { +- if (f <= this.lastHurt) { ++ if ((float) this.invulnerableTime > (float) this.invulnerableDuration / 2.0F && !source.is(DamageTypeTags.BYPASSES_COOLDOWN)) { // CraftBukkit - restore use of maxNoDamageTicks ++ if (amount <= this.lastHurt) { + return false; + } + +- this.actuallyHurt(damagesource, f - this.lastHurt); +- this.lastHurt = f; ++ // CraftBukkit start ++ if (!this.damageEntity0(source, amount - this.lastHurt)) { ++ return false; ++ } ++ // CraftBukkit end ++ this.lastHurt = amount; + flag1 = false; + } else { +- this.lastHurt = f; +- this.invulnerableTime = 20; +- this.actuallyHurt(damagesource, f); ++ // CraftBukkit start ++ if (!this.damageEntity0(source, amount)) { ++ return false; ++ } ++ this.lastHurt = amount; ++ this.invulnerableTime = this.invulnerableDuration; // CraftBukkit - restore use of maxNoDamageTicks ++ // this.damageEntity0(damagesource, f); ++ // CraftBukkit end + this.hurtDuration = 10; + this.hurtTime = this.hurtDuration; + } + +- if (damagesource.is(DamageTypeTags.DAMAGES_HELMET) && !this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { +- this.hurtHelmet(damagesource, f); +- f *= 0.75F; ++ // CraftBukkit - Moved into damageEntity0(DamageSource, float) ++ if (false && source.is(DamageTypeTags.DAMAGES_HELMET) && !this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { ++ this.hurtHelmet(source, amount); ++ amount *= 0.75F; + } + +- Entity entity1 = damagesource.getEntity(); ++ Entity entity1 = source.getEntity(); + + if (entity1 != null) { + if (entity1 instanceof LivingEntity) { +- LivingEntity livingentity1 = (LivingEntity) entity1; ++ LivingEntity entityliving1 = (LivingEntity) entity1; + +- if (!damagesource.is(DamageTypeTags.NO_ANGER)) { +- this.setLastHurtByMob(livingentity1); ++ if (!source.is(DamageTypeTags.NO_ANGER)) { ++ this.setLastHurtByMob(entityliving1); + } + } + +- if (entity1 instanceof Player) { +- Player player = (Player) entity1; ++ if (entity1 instanceof net.minecraft.world.entity.player.Player) { ++ net.minecraft.world.entity.player.Player entityhuman = (net.minecraft.world.entity.player.Player) entity1; + + this.lastHurtByPlayerTime = 100; +- this.lastHurtByPlayer = player; ++ this.lastHurtByPlayer = entityhuman; + } else if (entity1 instanceof Wolf) { +- Wolf wolf = (Wolf) entity1; ++ Wolf entitywolf = (Wolf) entity1; + +- if (wolf.isTame()) { ++ if (entitywolf.isTame()) { + this.lastHurtByPlayerTime = 100; +- LivingEntity livingentity2 = wolf.getOwner(); ++ LivingEntity entityliving2 = entitywolf.getOwner(); + +- if (livingentity2 instanceof Player) { +- Player player1 = (Player) livingentity2; ++ if (entityliving2 instanceof net.minecraft.world.entity.player.Player) { ++ net.minecraft.world.entity.player.Player entityhuman1 = (net.minecraft.world.entity.player.Player) entityliving2; + +- this.lastHurtByPlayer = player1; ++ this.lastHurtByPlayer = entityhuman1; + } else { + this.lastHurtByPlayer = null; + } +@@ -1263,14 +1468,14 @@ + if (flag) { + this.level().broadcastEntityEvent(this, (byte) 29); + } else { +- this.level().broadcastDamageEvent(this, damagesource); ++ this.level().broadcastDamageEvent(this, source); + } + +- if (!damagesource.is(DamageTypeTags.NO_IMPACT) && (!flag || f > 0.0F)) { ++ if (!source.is(DamageTypeTags.NO_IMPACT) && (!flag || amount > 0.0F)) { + this.markHurt(); + } + +- if (entity1 != null && !damagesource.is(DamageTypeTags.NO_KNOCKBACK)) { ++ if (entity1 != null && !source.is(DamageTypeTags.NO_KNOCKBACK)) { + double d0 = entity1.getX() - this.getX(); + + double d1; +@@ -1287,86 +1492,101 @@ + } + + if (this.isDeadOrDying()) { +- if (!this.checkTotemDeathProtection(damagesource)) { +- SoundEvent soundevent = this.getDeathSound(); ++ if (!this.checkTotemDeathProtection(source)) { ++ SoundEvent soundeffect = this.getDeathSound(); + +- if (flag1 && soundevent != null) { +- this.playSound(soundevent, this.getSoundVolume(), this.getVoicePitch()); ++ if (flag1 && soundeffect != null) { ++ this.playSound(soundeffect, this.getSoundVolume(), this.getVoicePitch()); + } + +- this.die(damagesource); ++ this.die(source); + } + } else if (flag1) { +- this.playHurtSound(damagesource); ++ this.playHurtSound(source); + } + +- boolean flag2 = !flag || f > 0.0F; ++ boolean flag2 = !flag || amount > 0.0F; + + if (flag2) { +- this.lastDamageSource = damagesource; ++ this.lastDamageSource = source; + this.lastDamageStamp = this.level().getGameTime(); + } + + if (this instanceof ServerPlayer) { +- CriteriaTriggers.ENTITY_HURT_PLAYER.trigger((ServerPlayer) this, damagesource, f1, f, flag); ++ CriteriaTriggers.ENTITY_HURT_PLAYER.trigger((ServerPlayer) this, source, f1, amount, flag); + if (f2 > 0.0F && f2 < 3.4028235E37F) { + ((ServerPlayer) this).awardStat(Stats.DAMAGE_BLOCKED_BY_SHIELD, Math.round(f2 * 10.0F)); + } + } + + if (entity1 instanceof ServerPlayer) { +- CriteriaTriggers.PLAYER_HURT_ENTITY.trigger((ServerPlayer) entity1, this, damagesource, f1, f, flag); ++ CriteriaTriggers.PLAYER_HURT_ENTITY.trigger((ServerPlayer) entity1, this, source, f1, amount, flag); + } + + return flag2; + } + } + +- protected void blockUsingShield(LivingEntity livingentity) { +- livingentity.blockedByShield(this); ++ protected void blockUsingShield(LivingEntity attacker) { ++ attacker.blockedByShield(this); + } + +- protected void blockedByShield(LivingEntity livingentity) { +- livingentity.knockback(0.5D, livingentity.getX() - this.getX(), livingentity.getZ() - this.getZ()); ++ protected void blockedByShield(LivingEntity defender) { ++ defender.knockback(0.5D, defender.getX() - this.getX(), defender.getZ() - this.getZ()); + } + +- private boolean checkTotemDeathProtection(DamageSource damagesource) { +- if (damagesource.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { ++ private boolean checkTotemDeathProtection(DamageSource damageSource) { ++ if (damageSource.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { + return false; + } else { + ItemStack itemstack = null; +- InteractionHand[] ainteractionhand = InteractionHand.values(); +- int i = ainteractionhand.length; ++ EnumHand[] aenumhand = EnumHand.values(); ++ int i = aenumhand.length; + ++ // CraftBukkit start ++ EnumHand hand = null; ++ ItemStack itemstack1 = ItemStack.EMPTY; + for (int j = 0; j < i; ++j) { +- InteractionHand interactionhand = ainteractionhand[j]; +- ItemStack itemstack1 = this.getItemInHand(interactionhand); ++ EnumHand enumhand = aenumhand[j]; ++ itemstack1 = this.getItemInHand(enumhand); + + if (itemstack1.is(Items.TOTEM_OF_UNDYING)) { ++ hand = enumhand; // CraftBukkit + itemstack = itemstack1.copy(); +- itemstack1.shrink(1); ++ // itemstack1.subtract(1); // CraftBukkit + break; + } + } + +- if (itemstack != null) { +- if (this instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) this; ++ org.bukkit.inventory.EquipmentSlot handSlot = (hand != null) ? org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand) : null; ++ EntityResurrectEvent event = new EntityResurrectEvent((org.bukkit.entity.LivingEntity) this.getBukkitEntity(), handSlot); ++ event.setCancelled(itemstack == null); ++ this.level().getCraftServer().getPluginManager().callEvent(event); + +- serverplayer.awardStat(Stats.ITEM_USED.get(Items.TOTEM_OF_UNDYING)); +- CriteriaTriggers.USED_TOTEM.trigger(serverplayer, itemstack); ++ if (!event.isCancelled()) { ++ if (!itemstack1.isEmpty()) { ++ itemstack1.shrink(1); ++ } ++ if (itemstack != null && this instanceof ServerPlayer) { ++ // CraftBukkit end ++ ServerPlayer entityplayer = (ServerPlayer) this; ++ ++ entityplayer.awardStat(Stats.ITEM_USED.get(Items.TOTEM_OF_UNDYING)); ++ CriteriaTriggers.USED_TOTEM.trigger(entityplayer, itemstack); + this.gameEvent(GameEvent.ITEM_INTERACT_FINISH); + } + + this.setHealth(1.0F); +- this.removeAllEffects(); +- this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 900, 1)); +- this.addEffect(new MobEffectInstance(MobEffects.ABSORPTION, 100, 1)); +- this.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 800, 0)); ++ // CraftBukkit start ++ this.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 900, 1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ this.addEffect(new MobEffectInstance(MobEffects.ABSORPTION, 100, 1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ this.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 800, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ // CraftBukkit end + this.level().broadcastEntityEvent(this, (byte) 35); + } + +- return itemstack != null; ++ return !event.isCancelled(); + } + } + +@@ -1379,60 +1599,60 @@ + return this.lastDamageSource; + } + +- protected void playHurtSound(DamageSource damagesource) { +- SoundEvent soundevent = this.getHurtSound(damagesource); ++ protected void playHurtSound(DamageSource source) { ++ SoundEvent soundeffect = this.getHurtSound(source); + +- if (soundevent != null) { +- this.playSound(soundevent, this.getSoundVolume(), this.getVoicePitch()); ++ if (soundeffect != null) { ++ this.playSound(soundeffect, this.getSoundVolume(), this.getVoicePitch()); + } + + } + +- public boolean isDamageSourceBlocked(DamageSource damagesource) { +- Entity entity = damagesource.getDirectEntity(); ++ public boolean isDamageSourceBlocked(DamageSource damageSource) { ++ Entity entity = damageSource.getDirectEntity(); + boolean flag = false; + + if (entity instanceof AbstractArrow) { +- AbstractArrow abstractarrow = (AbstractArrow) entity; ++ AbstractArrow entityarrow = (AbstractArrow) entity; + +- if (abstractarrow.getPierceLevel() > 0) { ++ if (entityarrow.getPierceLevel() > 0) { + flag = true; + } + } + +- if (!damagesource.is(DamageTypeTags.BYPASSES_SHIELD) && this.isBlocking() && !flag) { +- Vec3 vec3 = damagesource.getSourcePosition(); ++ if (!damageSource.is(DamageTypeTags.BYPASSES_SHIELD) && this.isBlocking() && !flag) { ++ Vec3 vec3d = damageSource.getSourcePosition(); + +- if (vec3 != null) { +- Vec3 vec31 = this.calculateViewVector(0.0F, this.getYHeadRot()); +- Vec3 vec32 = vec3.vectorTo(this.position()); ++ if (vec3d != null) { ++ Vec3 vec3d1 = this.calculateViewVector(0.0F, this.getYHeadRot()); ++ Vec3 vec3d2 = vec3d.vectorTo(this.position()); + +- vec32 = (new Vec3(vec32.x, 0.0D, vec32.z)).normalize(); +- return vec32.dot(vec31) < 0.0D; ++ vec3d2 = (new Vec3(vec3d2.x, 0.0D, vec3d2.z)).normalize(); ++ return vec3d2.dot(vec3d1) < 0.0D; + } + } + + return false; + } + +- private void breakItem(ItemStack itemstack) { +- if (!itemstack.isEmpty()) { ++ private void breakItem(ItemStack stack) { ++ if (!stack.isEmpty()) { + if (!this.isSilent()) { + this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.ITEM_BREAK, this.getSoundSource(), 0.8F, 0.8F + this.level().random.nextFloat() * 0.4F, false); + } + +- this.spawnItemParticles(itemstack, 5); ++ this.spawnItemParticles(stack, 5); + } + + } + +- public void die(DamageSource damagesource) { ++ public void die(DamageSource damageSource) { + if (!this.isRemoved() && !this.dead) { +- Entity entity = damagesource.getEntity(); +- LivingEntity livingentity = this.getKillCredit(); ++ Entity entity = damageSource.getEntity(); ++ LivingEntity entityliving = this.getKillCredit(); + +- if (this.deathScore >= 0 && livingentity != null) { +- livingentity.awardKillScore(this, this.deathScore, damagesource); ++ if (this.deathScore >= 0 && entityliving != null) { ++ entityliving.awardKillScore(this, this.deathScore, damageSource); + } + + if (this.isSleeping()) { +@@ -1445,54 +1665,62 @@ + + this.dead = true; + this.getCombatTracker().recheckStatus(); +- Level level = this.level(); ++ Level world = this.level(); + +- if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; + +- if (entity == null || entity.killedEntity(serverlevel, this)) { ++ if (entity == null || entity.killedEntity(worldserver, this)) { + this.gameEvent(GameEvent.ENTITY_DIE); +- this.dropAllDeathLoot(damagesource); +- this.createWitherRose(livingentity); ++ this.dropAllDeathLoot(damageSource); ++ this.createWitherRose(entityliving); + } + + this.level().broadcastEntityEvent(this, (byte) 3); + } + +- this.setPose(Pose.DYING); ++ this.setPose(EntityPose.DYING); + } + } + +- protected void createWitherRose(@Nullable LivingEntity livingentity) { ++ protected void createWitherRose(@Nullable LivingEntity entitySource) { + if (!this.level().isClientSide) { + boolean flag = false; + +- if (livingentity instanceof WitherBoss) { ++ if (entitySource instanceof WitherBoss) { + if (this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- BlockPos blockpos = this.blockPosition(); +- BlockState blockstate = Blocks.WITHER_ROSE.defaultBlockState(); ++ BlockPos blockposition = this.blockPosition(); ++ IBlockData iblockdata = Blocks.WITHER_ROSE.defaultBlockState(); + +- if (this.level().getBlockState(blockpos).isAir() && blockstate.canSurvive(this.level(), blockpos)) { +- this.level().setBlock(blockpos, blockstate, 3); +- flag = true; ++ if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) { ++ // CraftBukkit start - call EntityBlockFormEvent for Wither Rose ++ flag = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this.level(), blockposition, iblockdata, 3, this); ++ // CraftBukkit end + } + } + + if (!flag) { +- ItemEntity itementity = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), new ItemStack(Items.WITHER_ROSE)); ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), new ItemStack(Items.WITHER_ROSE)); + +- this.level().addFreshEntity(itementity); ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ CraftEventFactory.callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ this.level().addFreshEntity(entityitem); + } + } + + } + } + +- protected void dropAllDeathLoot(DamageSource damagesource) { +- Entity entity = damagesource.getEntity(); ++ protected void dropAllDeathLoot(DamageSource damageSource) { ++ Entity entity = damageSource.getEntity(); + int i; + +- if (entity instanceof Player) { ++ if (entity instanceof net.minecraft.world.entity.player.Player) { + i = EnchantmentHelper.getMobLooting((LivingEntity) entity); + } else { + i = 0; +@@ -1500,25 +1728,44 @@ + + boolean flag = this.lastHurtByPlayerTime > 0; + ++ this.dropEquipment(); // CraftBukkit - from below + if (this.shouldDropLoot() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +- this.dropFromLootTable(damagesource, flag); +- this.dropCustomDeathLoot(damagesource, i, flag); ++ this.dropFromLootTable(damageSource, flag); ++ this.dropCustomDeathLoot(damageSource, i, flag); + } ++ // CraftBukkit start - Call death event ++ CraftEventFactory.callEntityDeathEvent(this, this.drops); ++ this.drops = new ArrayList<>(); ++ // CraftBukkit end + +- this.dropEquipment(); ++ // this.dropInventory();// CraftBukkit - moved up + this.dropExperience(); + } + + protected void dropEquipment() {} + +- protected void dropExperience() { ++ // CraftBukkit start ++ public int getExpReward() { + if (this.level() instanceof ServerLevel && !this.wasExperienceConsumed() && (this.isAlwaysExperienceDropper() || this.lastHurtByPlayerTime > 0 && this.shouldDropExperience() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT))) { +- ExperienceOrb.award((ServerLevel) this.level(), this.position(), this.getExperienceReward()); ++ int i = this.getExperienceReward(); ++ return i; ++ } else { ++ return 0; + } ++ } ++ // CraftBukkit end + ++ protected void dropExperience() { ++ // CraftBukkit start - Update getExpReward() above if the removed if() changes! ++ if (true && !(this instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon)) { // CraftBukkit - SPIGOT-2420: Special case ender dragon will drop the xp over time ++ ExperienceOrb.award((ServerLevel) this.level(), this.position(), this.expToDrop); ++ this.expToDrop = 0; ++ } ++ // CraftBukkit end ++ + } + +- protected void dropCustomDeathLoot(DamageSource damagesource, int i, boolean flag) {} ++ protected void dropCustomDeathLoot(DamageSource damageSource, int looting, boolean hitByPlayer) {} + + public ResourceLocation getLootTable() { + return this.getType().getDefaultLootTable(); +@@ -1528,35 +1775,35 @@ + return 0L; + } + +- protected void dropFromLootTable(DamageSource damagesource, boolean flag) { +- ResourceLocation resourcelocation = this.getLootTable(); +- LootTable loottable = this.level().getServer().getLootData().getLootTable(resourcelocation); +- LootParams.Builder lootparams_builder = (new LootParams.Builder((ServerLevel) this.level())).withParameter(LootContextParams.THIS_ENTITY, this).withParameter(LootContextParams.ORIGIN, this.position()).withParameter(LootContextParams.DAMAGE_SOURCE, damagesource).withOptionalParameter(LootContextParams.KILLER_ENTITY, damagesource.getEntity()).withOptionalParameter(LootContextParams.DIRECT_KILLER_ENTITY, damagesource.getDirectEntity()); ++ protected void dropFromLootTable(DamageSource damageSource, boolean hitByPlayer) { ++ ResourceLocation minecraftkey = this.getLootTable(); ++ LootTable loottable = this.level().getServer().getLootData().getLootTable(minecraftkey); ++ LootParams.Builder lootparams_a = (new LootParams.Builder((ServerLevel) this.level())).withParameter(LootContextParams.THIS_ENTITY, this).withParameter(LootContextParams.ORIGIN, this.position()).withParameter(LootContextParams.DAMAGE_SOURCE, damageSource).withOptionalParameter(LootContextParams.KILLER_ENTITY, damageSource.getEntity()).withOptionalParameter(LootContextParams.DIRECT_KILLER_ENTITY, damageSource.getDirectEntity()); + +- if (flag && this.lastHurtByPlayer != null) { +- lootparams_builder = lootparams_builder.withParameter(LootContextParams.LAST_DAMAGE_PLAYER, this.lastHurtByPlayer).withLuck(this.lastHurtByPlayer.getLuck()); ++ if (hitByPlayer && this.lastHurtByPlayer != null) { ++ lootparams_a = lootparams_a.withParameter(LootContextParams.LAST_DAMAGE_PLAYER, this.lastHurtByPlayer).withLuck(this.lastHurtByPlayer.getLuck()); + } + +- LootParams lootparams = lootparams_builder.create(LootContextParamSets.ENTITY); ++ LootParams lootparams = lootparams_a.create(LootContextParamSets.ENTITY); + + loottable.getRandomItems(lootparams, this.getLootTableSeed(), this::spawnAtLocation); + } + +- public void knockback(double d0, double d1, double d2) { +- d0 *= 1.0D - this.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE); +- if (d0 > 0.0D) { ++ public void knockback(double strength, double d1, double x) { ++ strength *= 1.0D - this.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE); ++ if (strength > 0.0D) { + this.hasImpulse = true; +- Vec3 vec3 = this.getDeltaMovement(); +- Vec3 vec31 = (new Vec3(d1, 0.0D, d2)).normalize().scale(d0); ++ Vec3 vec3d = this.getDeltaMovement(); ++ Vec3 vec3d1 = (new Vec3(d1, 0.0D, x)).normalize().scale(strength); + +- this.setDeltaMovement(vec3.x / 2.0D - vec31.x, this.onGround() ? Math.min(0.4D, vec3.y / 2.0D + d0) : vec3.y, vec3.z / 2.0D - vec31.z); ++ this.setDeltaMovement(vec3d.x / 2.0D - vec3d1.x, this.onGround() ? Math.min(0.4D, vec3d.y / 2.0D + strength) : vec3d.y, vec3d.z / 2.0D - vec3d1.z); + } + } + +- public void indicateDamage(double d0, double d1) {} ++ public void indicateDamage(double xDistance, double d1) {} + + @Nullable +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.GENERIC_HURT; + } + +@@ -1565,8 +1812,8 @@ + return SoundEvents.GENERIC_DEATH; + } + +- private SoundEvent getFallDamageSound(int i) { +- return i > 4 ? this.getFallSounds().big() : this.getFallSounds().small(); ++ private SoundEvent getFallDamageSound(int height) { ++ return height > 4 ? this.getFallSounds().big() : this.getFallSounds().small(); + } + + public void skipDropExperience() { +@@ -1582,30 +1829,52 @@ + } + + protected AABB getHitbox() { +- AABB aabb = this.getBoundingBox(); ++ AABB axisalignedbb = this.getBoundingBox(); + Entity entity = this.getVehicle(); + + if (entity != null) { +- Vec3 vec3 = entity.getPassengerRidingPosition(this); ++ Vec3 vec3d = entity.getPassengerRidingPosition(this); + +- return aabb.setMinY(Math.max(vec3.y, aabb.minY)); ++ return axisalignedbb.setMinY(Math.max(vec3d.y, axisalignedbb.minY)); + } else { +- return aabb; ++ return axisalignedbb; + } + } + +- public LivingEntity.Fallsounds getFallSounds() { +- return new LivingEntity.Fallsounds(SoundEvents.GENERIC_SMALL_FALL, SoundEvents.GENERIC_BIG_FALL); ++ public LivingEntity.a getFallSounds() { ++ return new LivingEntity.a(SoundEvents.GENERIC_SMALL_FALL, SoundEvents.GENERIC_BIG_FALL); + } + +- protected SoundEvent getDrinkingSound(ItemStack itemstack) { +- return itemstack.getDrinkingSound(); ++ protected SoundEvent getDrinkingSound(ItemStack stack) { ++ return stack.getDrinkingSound(); + } + +- public SoundEvent getEatingSound(ItemStack itemstack) { +- return itemstack.getEatingSound(); ++ public SoundEvent getEatingSound(ItemStack stack) { ++ return stack.getEatingSound(); + } + ++ // CraftBukkit start - Add delegate methods ++ public SoundEvent getHurtSound0(DamageSource damagesource) { ++ return getHurtSound(damagesource); ++ } ++ ++ public SoundEvent getDeathSound0() { ++ return getDeathSound(); ++ } ++ ++ public SoundEvent getFallDamageSound0(int fallHeight) { ++ return getFallDamageSound(fallHeight); ++ } ++ ++ public SoundEvent getDrinkingSound0(ItemStack itemstack) { ++ return getDrinkingSound(itemstack); ++ } ++ ++ public SoundEvent getEatingSound0(ItemStack itemstack) { ++ return getEatingSound(itemstack); ++ } ++ // CraftBukkit end ++ + public Optional getLastClimbablePos() { + return this.lastClimbablePos; + } +@@ -1614,14 +1883,14 @@ + if (this.isSpectator()) { + return false; + } else { +- BlockPos blockpos = this.blockPosition(); +- BlockState blockstate = this.getFeetBlockState(); ++ BlockPos blockposition = this.blockPosition(); ++ IBlockData iblockdata = this.getFeetBlockState(); + +- if (blockstate.is(BlockTags.CLIMBABLE)) { +- this.lastClimbablePos = Optional.of(blockpos); ++ if (iblockdata.is(BlockTags.CLIMBABLE)) { ++ this.lastClimbablePos = Optional.of(blockposition); + return true; +- } else if (blockstate.getBlock() instanceof TrapDoorBlock && this.trapdoorUsableAsLadder(blockpos, blockstate)) { +- this.lastClimbablePos = Optional.of(blockpos); ++ } else if (iblockdata.getBlock() instanceof TrapDoorBlock && this.trapdoorUsableAsLadder(blockposition, iblockdata)) { ++ this.lastClimbablePos = Optional.of(blockposition); + return true; + } else { + return false; +@@ -1629,11 +1898,11 @@ + } + } + +- private boolean trapdoorUsableAsLadder(BlockPos blockpos, BlockState blockstate) { +- if ((Boolean) blockstate.getValue(TrapDoorBlock.OPEN)) { +- BlockState blockstate1 = this.level().getBlockState(blockpos.below()); ++ private boolean trapdoorUsableAsLadder(BlockPos pos, IBlockData state) { ++ if ((Boolean) state.getValue(TrapDoorBlock.OPEN)) { ++ IBlockData iblockdata1 = this.level().getBlockState(pos.below()); + +- if (blockstate1.is(Blocks.LADDER) && blockstate1.getValue(LadderBlock.FACING) == blockstate.getValue(TrapDoorBlock.FACING)) { ++ if (iblockdata1.is(Blocks.LADDER) && iblockdata1.getValue(LadderBlock.FACING) == state.getValue(TrapDoorBlock.FACING)) { + return true; + } + } +@@ -1642,35 +1911,38 @@ + } + + @Override +- @Override + public boolean isAlive() { + return !this.isRemoved() && this.getHealth() > 0.0F; + } + + @Override +- @Override +- public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { +- boolean flag = super.causeFallDamage(f, f1, damagesource); +- int i = this.calculateFallDamage(f, f1); ++ public boolean causeFallDamage(float fallDistance, float multiplier, DamageSource source) { ++ boolean flag = super.causeFallDamage(fallDistance, multiplier, source); ++ int i = this.calculateFallDamage(fallDistance, multiplier); + + if (i > 0) { ++ // CraftBukkit start ++ if (!this.hurt(source, (float) i)) { ++ return true; ++ } ++ // CraftBukkit end + this.playSound(this.getFallDamageSound(i), 1.0F, 1.0F); + this.playBlockFallSound(); +- this.hurt(damagesource, (float) i); ++ // this.damageEntity(damagesource, (float) i); // CraftBukkit - moved up + return true; + } else { + return flag; + } + } + +- protected int calculateFallDamage(float f, float f1) { ++ protected int calculateFallDamage(float fallDistance, float damageMultiplier) { + if (this.getType().is(EntityTypeTags.FALL_DAMAGE_IMMUNE)) { + return 0; + } else { +- MobEffectInstance mobeffectinstance = this.getEffect(MobEffects.JUMP); +- float f2 = mobeffectinstance == null ? 0.0F : (float) (mobeffectinstance.getAmplifier() + 1); ++ MobEffectInstance mobeffect = this.getEffect(MobEffects.JUMP); ++ float f2 = mobeffect == null ? 0.0F : (float) (mobeffect.getAmplifier() + 1); + +- return Mth.ceil((f - 3.0F - f2) * f1); ++ return Mth.ceil((fallDistance - 3.0F - f2) * damageMultiplier); + } + } + +@@ -1679,20 +1951,19 @@ + int i = Mth.floor(this.getX()); + int j = Mth.floor(this.getY() - 0.20000000298023224D); + int k = Mth.floor(this.getZ()); +- BlockState blockstate = this.level().getBlockState(new BlockPos(i, j, k)); ++ IBlockData iblockdata = this.level().getBlockState(new BlockPos(i, j, k)); + +- if (!blockstate.isAir()) { +- SoundType soundtype = blockstate.getSoundType(); ++ if (!iblockdata.isAir()) { ++ SoundType soundeffecttype = iblockdata.getSoundType(); + +- this.playSound(soundtype.getFallSound(), soundtype.getVolume() * 0.5F, soundtype.getPitch() * 0.75F); ++ this.playSound(soundeffecttype.getFallSound(), soundeffecttype.getVolume() * 0.5F, soundeffecttype.getPitch() * 0.75F); + } + + } + } + + @Override +- @Override +- public void animateHurt(float f) { ++ public void animateHurt(float yaw) { + this.hurtDuration = 10; + this.hurtTime = this.hurtDuration; + } +@@ -1701,87 +1972,231 @@ + return Mth.floor(this.getAttributeValue(Attributes.ARMOR)); + } + +- protected void hurtArmor(DamageSource damagesource, float f) {} ++ protected void hurtArmor(DamageSource damageSource, float damageAmount) {} + +- protected void hurtHelmet(DamageSource damagesource, float f) {} ++ protected void hurtHelmet(DamageSource damageSource, float damageAmount) {} + +- protected void hurtCurrentlyUsedShield(float f) {} ++ protected void hurtCurrentlyUsedShield(float damageAmount) {} + +- protected float getDamageAfterArmorAbsorb(DamageSource damagesource, float f) { +- if (!damagesource.is(DamageTypeTags.BYPASSES_ARMOR)) { +- this.hurtArmor(damagesource, f); +- f = CombatRules.getDamageAfterAbsorb(f, (float) this.getArmorValue(), (float) this.getAttributeValue(Attributes.ARMOR_TOUGHNESS)); ++ protected float getDamageAfterArmorAbsorb(DamageSource damageSource, float damageAmount) { ++ if (!damageSource.is(DamageTypeTags.BYPASSES_ARMOR)) { ++ // this.hurtArmor(damagesource, f); // CraftBukkit - Moved into damageEntity0(DamageSource, float) ++ damageAmount = CombatRules.getDamageAfterAbsorb(damageAmount, (float) this.getArmorValue(), (float) this.getAttributeValue(Attributes.ARMOR_TOUGHNESS)); + } + +- return f; ++ return damageAmount; + } + +- protected float getDamageAfterMagicAbsorb(DamageSource damagesource, float f) { +- if (damagesource.is(DamageTypeTags.BYPASSES_EFFECTS)) { +- return f; ++ protected float getDamageAfterMagicAbsorb(DamageSource damageSource, float damageAmount) { ++ if (damageSource.is(DamageTypeTags.BYPASSES_EFFECTS)) { ++ return damageAmount; + } else { + int i; + +- if (this.hasEffect(MobEffects.DAMAGE_RESISTANCE) && !damagesource.is(DamageTypeTags.BYPASSES_RESISTANCE)) { ++ // CraftBukkit - Moved to damageEntity0(DamageSource, float) ++ if (false && this.hasEffect(MobEffects.DAMAGE_RESISTANCE) && !damageSource.is(DamageTypeTags.BYPASSES_RESISTANCE)) { + i = (this.getEffect(MobEffects.DAMAGE_RESISTANCE).getAmplifier() + 1) * 5; + int j = 25 - i; +- float f1 = f * (float) j; +- float f2 = f; ++ float f1 = damageAmount * (float) j; ++ float f2 = damageAmount; + +- f = Math.max(f1 / 25.0F, 0.0F); +- float f3 = f2 - f; ++ damageAmount = Math.max(f1 / 25.0F, 0.0F); ++ float f3 = f2 - damageAmount; + + if (f3 > 0.0F && f3 < 3.4028235E37F) { + if (this instanceof ServerPlayer) { + ((ServerPlayer) this).awardStat(Stats.DAMAGE_RESISTED, Math.round(f3 * 10.0F)); +- } else if (damagesource.getEntity() instanceof ServerPlayer) { +- ((ServerPlayer) damagesource.getEntity()).awardStat(Stats.DAMAGE_DEALT_RESISTED, Math.round(f3 * 10.0F)); ++ } else if (damageSource.getEntity() instanceof ServerPlayer) { ++ ((ServerPlayer) damageSource.getEntity()).awardStat(Stats.DAMAGE_DEALT_RESISTED, Math.round(f3 * 10.0F)); + } + } + } + +- if (f <= 0.0F) { ++ if (damageAmount <= 0.0F) { + return 0.0F; +- } else if (damagesource.is(DamageTypeTags.BYPASSES_ENCHANTMENTS)) { +- return f; ++ } else if (damageSource.is(DamageTypeTags.BYPASSES_ENCHANTMENTS)) { ++ return damageAmount; + } else { +- i = EnchantmentHelper.getDamageProtection(this.getArmorSlots(), damagesource); ++ i = EnchantmentHelper.getDamageProtection(this.getArmorSlots(), damageSource); + if (i > 0) { +- f = CombatRules.getDamageAfterMagicAbsorb(f, (float) i); ++ damageAmount = CombatRules.getDamageAfterMagicAbsorb(damageAmount, (float) i); + } + +- return f; ++ return damageAmount; + } + } + } + +- protected void actuallyHurt(DamageSource damagesource, float f) { +- if (!this.isInvulnerableTo(damagesource)) { +- f = this.getDamageAfterArmorAbsorb(damagesource, f); +- f = this.getDamageAfterMagicAbsorb(damagesource, f); +- float f1 = f; ++ // CraftBukkit start ++ protected boolean damageEntity0(final DamageSource damagesource, float f) { // void -> boolean, add final ++ if (!this.isInvulnerableTo(damagesource)) { ++ final boolean human = this instanceof net.minecraft.world.entity.player.Player; ++ float originalDamage = f; ++ Function hardHat = new Function() { ++ @Override ++ public Double apply(Double f) { ++ if (damagesource.is(DamageTypeTags.DAMAGES_HELMET) && !LivingEntity.this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { ++ return -(f - (f * 0.75F)); + +- f = Math.max(f - this.getAbsorptionAmount(), 0.0F); +- this.setAbsorptionAmount(this.getAbsorptionAmount() - (f1 - f)); +- float f2 = f1 - f; ++ } ++ return -0.0; ++ } ++ }; ++ float hardHatModifier = hardHat.apply((double) f).floatValue(); ++ f += hardHatModifier; + ++ Function blocking = new Function() { ++ @Override ++ public Double apply(Double f) { ++ return -((LivingEntity.this.isDamageSourceBlocked(damagesource)) ? f : 0.0); ++ } ++ }; ++ float blockingModifier = blocking.apply((double) f).floatValue(); ++ f += blockingModifier; ++ ++ Function armor = new Function() { ++ @Override ++ public Double apply(Double f) { ++ return -(f - LivingEntity.this.getDamageAfterArmorAbsorb(damagesource, f.floatValue())); ++ } ++ }; ++ float armorModifier = armor.apply((double) f).floatValue(); ++ f += armorModifier; ++ ++ Function resistance = new Function() { ++ @Override ++ public Double apply(Double f) { ++ if (!damagesource.is(DamageTypeTags.BYPASSES_EFFECTS) && LivingEntity.this.hasEffect(MobEffects.DAMAGE_RESISTANCE) && !damagesource.is(DamageTypeTags.BYPASSES_RESISTANCE)) { ++ int i = (LivingEntity.this.getEffect(MobEffects.DAMAGE_RESISTANCE).getAmplifier() + 1) * 5; ++ int j = 25 - i; ++ float f1 = f.floatValue() * (float) j; ++ return -(f - (f1 / 25.0F)); ++ } ++ return -0.0; ++ } ++ }; ++ float resistanceModifier = resistance.apply((double) f).floatValue(); ++ f += resistanceModifier; ++ ++ Function magic = new Function() { ++ @Override ++ public Double apply(Double f) { ++ return -(f - LivingEntity.this.getDamageAfterMagicAbsorb(damagesource, f.floatValue())); ++ } ++ }; ++ float magicModifier = magic.apply((double) f).floatValue(); ++ f += magicModifier; ++ ++ Function absorption = new Function() { ++ @Override ++ public Double apply(Double f) { ++ return -(Math.max(f - Math.max(f - LivingEntity.this.getAbsorptionAmount(), 0.0F), 0.0F)); ++ } ++ }; ++ float absorptionModifier = absorption.apply((double) f).floatValue(); ++ ++ EntityDamageEvent event = CraftEventFactory.handleLivingEntityDamageEvent(this, damagesource, originalDamage, hardHatModifier, blockingModifier, armorModifier, resistanceModifier, magicModifier, absorptionModifier, hardHat, blocking, armor, resistance, magic, absorption); ++ if (damagesource.getEntity() instanceof net.minecraft.world.entity.player.Player) { ++ ((net.minecraft.world.entity.player.Player) damagesource.getEntity()).resetAttackStrengthTicker(); // Moved from EntityHuman in order to make the cooldown reset get called after the damage event is fired ++ } ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ f = (float) event.getFinalDamage(); ++ ++ // Resistance ++ if (event.getDamage(DamageModifier.RESISTANCE) < 0) { ++ float f3 = (float) -event.getDamage(DamageModifier.RESISTANCE); ++ if (f3 > 0.0F && f3 < 3.4028235E37F) { ++ if (this instanceof ServerPlayer) { ++ ((ServerPlayer) this).awardStat(Stats.DAMAGE_RESISTED, Math.round(f3 * 10.0F)); ++ } else if (damagesource.getEntity() instanceof ServerPlayer) { ++ ((ServerPlayer) damagesource.getEntity()).awardStat(Stats.DAMAGE_DEALT_RESISTED, Math.round(f3 * 10.0F)); ++ } ++ } ++ } ++ ++ // Apply damage to helmet ++ if (damagesource.is(DamageTypeTags.DAMAGES_HELMET) && !this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { ++ this.hurtHelmet(damagesource, f); ++ } ++ ++ // Apply damage to armor ++ if (!damagesource.is(DamageTypeTags.BYPASSES_ARMOR)) { ++ float armorDamage = (float) (event.getDamage() + event.getDamage(DamageModifier.BLOCKING) + event.getDamage(DamageModifier.HARD_HAT)); ++ this.hurtArmor(damagesource, armorDamage); ++ } ++ ++ // Apply blocking code // PAIL: steal from above ++ if (event.getDamage(DamageModifier.BLOCKING) < 0) { ++ this.level().broadcastEntityEvent(this, (byte) 29); // SPIGOT-4635 - shield damage sound ++ this.hurtCurrentlyUsedShield((float) -event.getDamage(DamageModifier.BLOCKING)); ++ Entity entity = damagesource.getDirectEntity(); ++ ++ if (entity instanceof LivingEntity) { ++ this.blockUsingShield((LivingEntity) entity); ++ } ++ } ++ ++ absorptionModifier = (float) -event.getDamage(DamageModifier.ABSORPTION); ++ this.setAbsorptionAmount(Math.max(this.getAbsorptionAmount() - absorptionModifier, 0.0F)); ++ float f2 = absorptionModifier; ++ ++ if (f2 > 0.0F && f2 < 3.4028235E37F && this instanceof net.minecraft.world.entity.player.Player) { ++ ((net.minecraft.world.entity.player.Player) this).awardStat(Stats.DAMAGE_ABSORBED, Math.round(f2 * 10.0F)); ++ } + if (f2 > 0.0F && f2 < 3.4028235E37F) { + Entity entity = damagesource.getEntity(); + + if (entity instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) entity; ++ ServerPlayer entityplayer = (ServerPlayer) entity; + +- serverplayer.awardStat(Stats.DAMAGE_DEALT_ABSORBED, Math.round(f2 * 10.0F)); ++ entityplayer.awardStat(Stats.DAMAGE_DEALT_ABSORBED, Math.round(f2 * 10.0F)); + } + } + +- if (f != 0.0F) { ++ if (f > 0 || !human) { ++ if (human) { ++ // PAIL: Be sure to drag all this code from the EntityHuman subclass each update. ++ ((net.minecraft.world.entity.player.Player) this).causeFoodExhaustion(damagesource.getFoodExhaustion(), org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.DAMAGED); // CraftBukkit - EntityExhaustionEvent ++ if (f < 3.4028235E37F) { ++ ((net.minecraft.world.entity.player.Player) this).awardStat(Stats.DAMAGE_TAKEN, Math.round(f * 10.0F)); ++ } ++ } ++ // CraftBukkit end + this.getCombatTracker().recordDamage(damagesource, f); + this.setHealth(this.getHealth() - f); +- this.setAbsorptionAmount(this.getAbsorptionAmount() - f); ++ // CraftBukkit start ++ if (!human) { ++ this.setAbsorptionAmount(this.getAbsorptionAmount() - f); ++ } + this.gameEvent(GameEvent.ENTITY_DAMAGE); ++ ++ return true; ++ } else { ++ // Duplicate triggers if blocking ++ if (event.getDamage(DamageModifier.BLOCKING) < 0) { ++ if (this instanceof ServerPlayer) { ++ CriteriaTriggers.ENTITY_HURT_PLAYER.trigger((ServerPlayer) this, damagesource, f, originalDamage, true); ++ f2 = (float) -event.getDamage(DamageModifier.BLOCKING); ++ if (f2 > 0.0F && f2 < 3.4028235E37F) { ++ ((ServerPlayer) this).awardStat(Stats.DAMAGE_BLOCKED_BY_SHIELD, Math.round(originalDamage * 10.0F)); ++ } ++ } ++ ++ if (damagesource.getEntity() instanceof ServerPlayer) { ++ CriteriaTriggers.PLAYER_HURT_ENTITY.trigger((ServerPlayer) damagesource.getEntity(), this, damagesource, f, originalDamage, true); ++ } ++ ++ return false; ++ } else { ++ return originalDamage > 0; ++ } ++ // CraftBukkit end + } + } ++ return false; // CraftBukkit + } + + public CombatTracker getCombatTracker() { +@@ -1805,39 +2220,49 @@ + return (Integer) this.entityData.get(LivingEntity.DATA_ARROW_COUNT_ID); + } + +- public final void setArrowCount(int i) { +- this.entityData.set(LivingEntity.DATA_ARROW_COUNT_ID, i); ++ public final void setArrowCount(int count) { ++ // CraftBukkit start ++ setArrowCount(count, false); + } + ++ public final void setArrowCount(int i, boolean flag) { ++ ArrowBodyCountChangeEvent event = CraftEventFactory.callArrowBodyCountChangeEvent(this, getArrowCount(), i, flag); ++ if (event.isCancelled()) { ++ return; ++ } ++ this.entityData.set(LivingEntity.DATA_ARROW_COUNT_ID, event.getNewAmount()); ++ } ++ // CraftBukkit end ++ + public final int getStingerCount() { + return (Integer) this.entityData.get(LivingEntity.DATA_STINGER_COUNT_ID); + } + +- public final void setStingerCount(int i) { +- this.entityData.set(LivingEntity.DATA_STINGER_COUNT_ID, i); ++ public final void setStingerCount(int stingerCount) { ++ this.entityData.set(LivingEntity.DATA_STINGER_COUNT_ID, stingerCount); + } + + private int getCurrentSwingDuration() { + return MobEffectUtil.hasDigSpeed(this) ? 6 - (1 + MobEffectUtil.getDigSpeedAmplification(this)) : (this.hasEffect(MobEffects.DIG_SLOWDOWN) ? 6 + (1 + this.getEffect(MobEffects.DIG_SLOWDOWN).getAmplifier()) * 2 : 6); + } + +- public void swing(InteractionHand interactionhand) { +- this.swing(interactionhand, false); ++ public void swing(EnumHand hand) { ++ this.swing(hand, false); + } + +- public void swing(InteractionHand interactionhand, boolean flag) { ++ public void swing(EnumHand hand, boolean updateSelf) { + if (!this.swinging || this.swingTime >= this.getCurrentSwingDuration() / 2 || this.swingTime < 0) { + this.swingTime = -1; + this.swinging = true; +- this.swingingArm = interactionhand; ++ this.swingingArm = hand; + if (this.level() instanceof ServerLevel) { +- ClientboundAnimatePacket clientboundanimatepacket = new ClientboundAnimatePacket(this, interactionhand == InteractionHand.MAIN_HAND ? 0 : 3); +- ServerChunkCache serverchunkcache = ((ServerLevel) this.level()).getChunkSource(); ++ ClientboundAnimatePacket packetplayoutanimation = new ClientboundAnimatePacket(this, hand == EnumHand.MAIN_HAND ? 0 : 3); ++ ServerChunkCache chunkproviderserver = ((ServerLevel) this.level()).getChunkSource(); + +- if (flag) { +- serverchunkcache.broadcastAndSend(this, clientboundanimatepacket); ++ if (updateSelf) { ++ chunkproviderserver.broadcastAndSend(this, packetplayoutanimation); + } else { +- serverchunkcache.broadcast(this, clientboundanimatepacket); ++ chunkproviderserver.broadcast(this, packetplayoutanimation); + } + } + } +@@ -1845,35 +2270,33 @@ + } + + @Override +- @Override +- public void handleDamageEvent(DamageSource damagesource) { ++ public void handleDamageEvent(DamageSource damageSource) { + this.walkAnimation.setSpeed(1.5F); + this.invulnerableTime = 20; + this.hurtDuration = 10; + this.hurtTime = this.hurtDuration; +- SoundEvent soundevent = this.getHurtSound(damagesource); ++ SoundEvent soundeffect = this.getHurtSound(damageSource); + +- if (soundevent != null) { +- this.playSound(soundevent, this.getSoundVolume(), (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); ++ if (soundeffect != null) { ++ this.playSound(soundeffect, this.getSoundVolume(), (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); + } + + this.hurt(this.damageSources().generic(), 0.0F); +- this.lastDamageSource = damagesource; ++ this.lastDamageSource = damageSource; + this.lastDamageStamp = this.level().getGameTime(); + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- switch (b0) { ++ public void handleEntityEvent(byte id) { ++ switch (id) { + case 3: +- SoundEvent soundevent = this.getDeathSound(); ++ SoundEvent soundeffect = this.getDeathSound(); + +- if (soundevent != null) { +- this.playSound(soundevent, this.getSoundVolume(), (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); ++ if (soundeffect != null) { ++ this.playSound(soundeffect, this.getSoundVolume(), (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); + } + +- if (!(this instanceof Player)) { ++ if (!(this instanceof net.minecraft.world.entity.player.Player)) { + this.setHealth(0.0F); + this.die(this.damageSources().generic()); + } +@@ -1928,7 +2351,7 @@ + this.makePoofParticles(); + break; + default: +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } +@@ -1952,7 +2375,6 @@ + } + + @Override +- @Override + protected void onBelowWorld() { + this.hurt(this.damageSources().fellOutOfWorld(), 4.0F); + } +@@ -1978,16 +2400,16 @@ + return this.getAttributes().getInstance(attribute); + } + +- public double getAttributeValue(Holder holder) { +- return this.getAttributeValue((Attribute) holder.value()); ++ public double getAttributeValue(Holder attribute) { ++ return this.getAttributeValue((Attribute) attribute.value()); + } + + public double getAttributeValue(Attribute attribute) { + return this.getAttributes().getValue(attribute); + } + +- public double getAttributeBaseValue(Holder holder) { +- return this.getAttributeBaseValue((Attribute) holder.value()); ++ public double getAttributeBaseValue(Holder attribute) { ++ return this.getAttributeBaseValue((Attribute) attribute.value()); + } + + public double getAttributeBaseValue(Attribute attribute) { +@@ -1998,8 +2420,8 @@ + return this.attributes; + } + +- public MobType getMobType() { +- return MobType.UNDEFINED; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.UNDEFINED; + } + + public ItemStack getMainHandItem() { +@@ -2020,48 +2442,52 @@ + return predicate.test(this.getMainHandItem()) || predicate.test(this.getOffhandItem()); + } + +- public ItemStack getItemInHand(InteractionHand interactionhand) { +- if (interactionhand == InteractionHand.MAIN_HAND) { ++ public ItemStack getItemInHand(EnumHand hand) { ++ if (hand == EnumHand.MAIN_HAND) { + return this.getItemBySlot(EquipmentSlot.MAINHAND); +- } else if (interactionhand == InteractionHand.OFF_HAND) { ++ } else if (hand == EnumHand.OFF_HAND) { + return this.getItemBySlot(EquipmentSlot.OFFHAND); + } else { +- throw new IllegalArgumentException("Invalid hand " + interactionhand); ++ throw new IllegalArgumentException("Invalid hand " + hand); + } + } + +- public void setItemInHand(InteractionHand interactionhand, ItemStack itemstack) { +- if (interactionhand == InteractionHand.MAIN_HAND) { +- this.setItemSlot(EquipmentSlot.MAINHAND, itemstack); ++ public void setItemInHand(EnumHand hand, ItemStack stack) { ++ if (hand == EnumHand.MAIN_HAND) { ++ this.setItemSlot(EquipmentSlot.MAINHAND, stack); + } else { +- if (interactionhand != InteractionHand.OFF_HAND) { +- throw new IllegalArgumentException("Invalid hand " + interactionhand); ++ if (hand != EnumHand.OFF_HAND) { ++ throw new IllegalArgumentException("Invalid hand " + hand); + } + +- this.setItemSlot(EquipmentSlot.OFFHAND, itemstack); ++ this.setItemSlot(EquipmentSlot.OFFHAND, stack); + } + + } + +- public boolean hasItemInSlot(EquipmentSlot equipmentslot) { +- return !this.getItemBySlot(equipmentslot).isEmpty(); ++ public boolean hasItemInSlot(EquipmentSlot slot) { ++ return !this.getItemBySlot(slot).isEmpty(); + } + + @Override +- @Override + public abstract Iterable getArmorSlots(); + + public abstract ItemStack getItemBySlot(EquipmentSlot slot); + ++ // CraftBukkit start ++ public void setItemSlot(EquipmentSlot enumitemslot, ItemStack itemstack, boolean silent) { ++ this.setItemSlot(enumitemslot, itemstack); ++ } ++ // CraftBukkit end ++ + @Override +- @Override + public abstract void setItemSlot(EquipmentSlot slot, ItemStack stack); + +- protected void verifyEquippedItem(ItemStack itemstack) { +- CompoundTag compoundtag = itemstack.getTag(); ++ protected void verifyEquippedItem(ItemStack stack) { ++ CompoundTag nbttagcompound = stack.getTag(); + +- if (compoundtag != null) { +- itemstack.getItem().verifyTagAfterLoad(compoundtag); ++ if (nbttagcompound != null) { ++ stack.getItem().verifyTagAfterLoad(nbttagcompound); + } + + } +@@ -2083,14 +2509,13 @@ + } + + @Override +- @Override +- public void setSprinting(boolean flag) { +- super.setSprinting(flag); +- AttributeInstance attributeinstance = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ public void setSprinting(boolean sprinting) { ++ super.setSprinting(sprinting); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); + +- attributeinstance.removeModifier(LivingEntity.SPEED_MODIFIER_SPRINTING.getId()); +- if (flag) { +- attributeinstance.addTransientModifier(LivingEntity.SPEED_MODIFIER_SPRINTING); ++ attributemodifiable.removeModifier(LivingEntity.SPEED_MODIFIER_SPRINTING.getId()); ++ if (sprinting) { ++ attributemodifiable.addTransientModifier(LivingEntity.SPEED_MODIFIER_SPRINTING); + } + + } +@@ -2108,7 +2533,6 @@ + } + + @Override +- @Override + public void push(Entity entity) { + if (!this.isSleeping()) { + super.push(entity); +@@ -2116,24 +2540,23 @@ + + } + +- private void dismountVehicle(Entity entity) { +- Vec3 vec3; ++ private void dismountVehicle(Entity vehicle) { ++ Vec3 vec3d; + + if (this.isRemoved()) { +- vec3 = this.position(); +- } else if (!entity.isRemoved() && !this.level().getBlockState(entity.blockPosition()).is(BlockTags.PORTALS)) { +- vec3 = entity.getDismountLocationForPassenger(this); ++ vec3d = this.position(); ++ } else if (!vehicle.isRemoved() && !this.level().getBlockState(vehicle.blockPosition()).is(BlockTags.PORTALS)) { ++ vec3d = vehicle.getDismountLocationForPassenger(this); + } else { +- double d0 = Math.max(this.getY(), entity.getY()); ++ double d0 = Math.max(this.getY(), vehicle.getY()); + +- vec3 = new Vec3(this.getX(), d0, this.getZ()); ++ vec3d = new Vec3(this.getX(), d0, this.getZ()); + } + +- this.dismountTo(vec3.x, vec3.y, vec3.z); ++ this.dismountTo(vec3d.x, vec3d.y, vec3d.z); + } + + @Override +- @Override + public boolean shouldShowName() { + return this.isCustomNameVisible(); + } +@@ -2147,9 +2570,9 @@ + } + + protected void jumpFromGround() { +- Vec3 vec3 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + +- this.setDeltaMovement(vec3.x, (double) this.getJumpPower(), vec3.z); ++ this.setDeltaMovement(vec3d.x, (double) this.getJumpPower(), vec3d.z); + if (this.isSprinting()) { + float f = this.getYRot() * 0.017453292F; + +@@ -2163,7 +2586,7 @@ + this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.03999999910593033D, 0.0D)); + } + +- protected void jumpInLiquid(TagKey tagkey) { ++ protected void jumpInLiquid(TagKey fluidTag) { + this.setDeltaMovement(this.getDeltaMovement().add(0.0D, 0.03999999910593033D, 0.0D)); + } + +@@ -2171,11 +2594,11 @@ + return 0.8F; + } + +- public boolean canStandOnFluid(FluidState fluidstate) { ++ public boolean canStandOnFluid(FluidState fluidState) { + return false; + } + +- public void travel(Vec3 vec3) { ++ public void travel(Vec3 travelVector) { + if (this.isControlledByLocalInstance()) { + double d0 = 0.08D; + boolean flag = this.getDeltaMovement().y <= 0.0D; +@@ -2184,11 +2607,11 @@ + d0 = 0.01D; + } + +- FluidState fluidstate = this.level().getFluidState(this.blockPosition()); ++ FluidState fluid = this.level().getFluidState(this.blockPosition()); + double d1; + float f; + +- if (this.isInWater() && this.isAffectedByFluids() && !this.canStandOnFluid(fluidstate)) { ++ if (this.isInWater() && this.isAffectedByFluids() && !this.canStandOnFluid(fluid)) { + d1 = this.getY(); + f = this.isSprinting() ? 0.9F : this.getWaterSlowDown(); + float f1 = 0.02F; +@@ -2211,31 +2634,31 @@ + f = 0.96F; + } + +- this.moveRelative(f1, vec3); +- this.move(MoverType.SELF, this.getDeltaMovement()); +- Vec3 vec31 = this.getDeltaMovement(); ++ this.moveRelative(f1, travelVector); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); ++ Vec3 vec3d1 = this.getDeltaMovement(); + + if (this.horizontalCollision && this.onClimbable()) { +- vec31 = new Vec3(vec31.x, 0.2D, vec31.z); ++ vec3d1 = new Vec3(vec3d1.x, 0.2D, vec3d1.z); + } + +- this.setDeltaMovement(vec31.multiply((double) f, 0.800000011920929D, (double) f)); +- Vec3 vec32 = this.getFluidFallingAdjustedMovement(d0, flag, this.getDeltaMovement()); ++ this.setDeltaMovement(vec3d1.multiply((double) f, 0.800000011920929D, (double) f)); ++ Vec3 vec3d2 = this.getFluidFallingAdjustedMovement(d0, flag, this.getDeltaMovement()); + +- this.setDeltaMovement(vec32); +- if (this.horizontalCollision && this.isFree(vec32.x, vec32.y + 0.6000000238418579D - this.getY() + d1, vec32.z)) { +- this.setDeltaMovement(vec32.x, 0.30000001192092896D, vec32.z); ++ this.setDeltaMovement(vec3d2); ++ if (this.horizontalCollision && this.isFree(vec3d2.x, vec3d2.y + 0.6000000238418579D - this.getY() + d1, vec3d2.z)) { ++ this.setDeltaMovement(vec3d2.x, 0.30000001192092896D, vec3d2.z); + } +- } else if (this.isInLava() && this.isAffectedByFluids() && !this.canStandOnFluid(fluidstate)) { ++ } else if (this.isInLava() && this.isAffectedByFluids() && !this.canStandOnFluid(fluid)) { + d1 = this.getY(); +- this.moveRelative(0.02F, vec3); +- this.move(MoverType.SELF, this.getDeltaMovement()); +- Vec3 vec33; ++ this.moveRelative(0.02F, travelVector); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); ++ Vec3 vec3d3; + + if (this.getFluidHeight(FluidTags.LAVA) <= this.getFluidJumpThreshold()) { + this.setDeltaMovement(this.getDeltaMovement().multiply(0.5D, 0.800000011920929D, 0.5D)); +- vec33 = this.getFluidFallingAdjustedMovement(d0, flag, this.getDeltaMovement()); +- this.setDeltaMovement(vec33); ++ vec3d3 = this.getFluidFallingAdjustedMovement(d0, flag, this.getDeltaMovement()); ++ this.setDeltaMovement(vec3d3); + } else { + this.setDeltaMovement(this.getDeltaMovement().scale(0.5D)); + } +@@ -2244,41 +2667,41 @@ + this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -d0 / 4.0D, 0.0D)); + } + +- vec33 = this.getDeltaMovement(); +- if (this.horizontalCollision && this.isFree(vec33.x, vec33.y + 0.6000000238418579D - this.getY() + d1, vec33.z)) { +- this.setDeltaMovement(vec33.x, 0.30000001192092896D, vec33.z); ++ vec3d3 = this.getDeltaMovement(); ++ if (this.horizontalCollision && this.isFree(vec3d3.x, vec3d3.y + 0.6000000238418579D - this.getY() + d1, vec3d3.z)) { ++ this.setDeltaMovement(vec3d3.x, 0.30000001192092896D, vec3d3.z); + } + } else if (this.isFallFlying()) { + this.checkSlowFallDistance(); +- Vec3 vec34 = this.getDeltaMovement(); +- Vec3 vec35 = this.getLookAngle(); ++ Vec3 vec3d4 = this.getDeltaMovement(); ++ Vec3 vec3d5 = this.getLookAngle(); + + f = this.getXRot() * 0.017453292F; +- double d2 = Math.sqrt(vec35.x * vec35.x + vec35.z * vec35.z); +- double d3 = vec34.horizontalDistance(); +- double d4 = vec35.length(); ++ double d2 = Math.sqrt(vec3d5.x * vec3d5.x + vec3d5.z * vec3d5.z); ++ double d3 = vec3d4.horizontalDistance(); ++ double d4 = vec3d5.length(); + double d5 = Math.cos((double) f); + + d5 = d5 * d5 * Math.min(1.0D, d4 / 0.4D); +- vec34 = this.getDeltaMovement().add(0.0D, d0 * (-1.0D + d5 * 0.75D), 0.0D); ++ vec3d4 = this.getDeltaMovement().add(0.0D, d0 * (-1.0D + d5 * 0.75D), 0.0D); + double d6; + +- if (vec34.y < 0.0D && d2 > 0.0D) { +- d6 = vec34.y * -0.1D * d5; +- vec34 = vec34.add(vec35.x * d6 / d2, d6, vec35.z * d6 / d2); ++ if (vec3d4.y < 0.0D && d2 > 0.0D) { ++ d6 = vec3d4.y * -0.1D * d5; ++ vec3d4 = vec3d4.add(vec3d5.x * d6 / d2, d6, vec3d5.z * d6 / d2); + } + + if (f < 0.0F && d2 > 0.0D) { + d6 = d3 * (double) (-Mth.sin(f)) * 0.04D; +- vec34 = vec34.add(-vec35.x * d6 / d2, d6 * 3.2D, -vec35.z * d6 / d2); ++ vec3d4 = vec3d4.add(-vec3d5.x * d6 / d2, d6 * 3.2D, -vec3d5.z * d6 / d2); + } + + if (d2 > 0.0D) { +- vec34 = vec34.add((vec35.x / d2 * d3 - vec34.x) * 0.1D, 0.0D, (vec35.z / d2 * d3 - vec34.z) * 0.1D); ++ vec3d4 = vec3d4.add((vec3d5.x / d2 * d3 - vec3d4.x) * 0.1D, 0.0D, (vec3d5.z / d2 * d3 - vec3d4.z) * 0.1D); + } + +- this.setDeltaMovement(vec34.multiply(0.9900000095367432D, 0.9800000190734863D, 0.9900000095367432D)); +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.setDeltaMovement(vec3d4.multiply(0.9900000095367432D, 0.9800000190734863D, 0.9900000095367432D)); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + if (this.horizontalCollision && !this.level().isClientSide) { + d6 = this.getDeltaMovement().horizontalDistance(); + double d7 = d3 - d6; +@@ -2291,19 +2714,20 @@ + } + + if (this.onGround() && !this.level().isClientSide) { ++ if (getSharedFlag(7) && !CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) // CraftBukkit + this.setSharedFlag(7, false); + } + } else { +- BlockPos blockpos = this.getBlockPosBelowThatAffectsMyMovement(); +- float f4 = this.level().getBlockState(blockpos).getBlock().getFriction(); ++ BlockPos blockposition = this.getBlockPosBelowThatAffectsMyMovement(); ++ float f4 = this.level().getBlockState(blockposition).getBlock().getFriction(); + + f = this.onGround() ? f4 * 0.91F : 0.91F; +- Vec3 vec36 = this.handleRelativeFrictionAndCalculateMovement(vec3, f4); +- double d8 = vec36.y; ++ Vec3 vec3d6 = this.handleRelativeFrictionAndCalculateMovement(travelVector, f4); ++ double d8 = vec3d6.y; + + if (this.hasEffect(MobEffects.LEVITATION)) { +- d8 += (0.05D * (double) (this.getEffect(MobEffects.LEVITATION).getAmplifier() + 1) - vec36.y) * 0.2D; +- } else if (this.level().isClientSide && !this.level().hasChunkAt(blockpos)) { ++ d8 += (0.05D * (double) (this.getEffect(MobEffects.LEVITATION).getAmplifier() + 1) - vec3d6.y) * 0.2D; ++ } else if (this.level().isClientSide && !this.level().hasChunkAt(blockposition)) { + if (this.getY() > (double) this.level().getMinBuildHeight()) { + d8 = -0.1D; + } else { +@@ -2314,23 +2738,23 @@ + } + + if (this.shouldDiscardFriction()) { +- this.setDeltaMovement(vec36.x, d8, vec36.z); ++ this.setDeltaMovement(vec3d6.x, d8, vec3d6.z); + } else { +- this.setDeltaMovement(vec36.x * (double) f, d8 * 0.9800000190734863D, vec36.z * (double) f); ++ this.setDeltaMovement(vec3d6.x * (double) f, d8 * 0.9800000190734863D, vec3d6.z * (double) f); + } + } + } + +- this.calculateEntityAnimation(this instanceof FlyingAnimal); ++ this.calculateEntityAnimation(this instanceof EntityBird); + } + +- private void travelRidden(Player player, Vec3 vec3) { +- Vec3 vec31 = this.getRiddenInput(player, vec3); ++ private void travelRidden(net.minecraft.world.entity.player.Player player, Vec3 travelVector) { ++ Vec3 vec3d1 = this.getRiddenInput(player, travelVector); + +- this.tickRidden(player, vec31); ++ this.tickRidden(player, vec3d1); + if (this.isControlledByLocalInstance()) { + this.setSpeed(this.getRiddenSpeed(player)); +- this.travel(vec31); ++ this.travel(vec3d1); + } else { + this.calculateEntityAnimation(false); + this.setDeltaMovement(Vec3.ZERO); +@@ -2339,98 +2763,97 @@ + + } + +- protected void tickRidden(Player player, Vec3 vec3) {} ++ protected void tickRidden(net.minecraft.world.entity.player.Player player, Vec3 travelVector) {} + +- protected Vec3 getRiddenInput(Player player, Vec3 vec3) { +- return vec3; ++ protected Vec3 getRiddenInput(net.minecraft.world.entity.player.Player player, Vec3 travelVector) { ++ return travelVector; + } + +- protected float getRiddenSpeed(Player player) { ++ protected float getRiddenSpeed(net.minecraft.world.entity.player.Player player) { + return this.getSpeed(); + } + +- public void calculateEntityAnimation(boolean flag) { +- float f = (float) Mth.length(this.getX() - this.xo, flag ? this.getY() - this.yo : 0.0D, this.getZ() - this.zo); ++ public void calculateEntityAnimation(boolean includeHeight) { ++ float f = (float) Mth.length(this.getX() - this.xo, includeHeight ? this.getY() - this.yo : 0.0D, this.getZ() - this.zo); + + this.updateWalkAnimation(f); + } + +- protected void updateWalkAnimation(float f) { +- float f1 = Math.min(f * 4.0F, 1.0F); ++ protected void updateWalkAnimation(float partialTick) { ++ float f1 = Math.min(partialTick * 4.0F, 1.0F); + + this.walkAnimation.update(f1, 0.4F); + } + +- public Vec3 handleRelativeFrictionAndCalculateMovement(Vec3 vec3, float f) { +- this.moveRelative(this.getFrictionInfluencedSpeed(f), vec3); ++ public Vec3 handleRelativeFrictionAndCalculateMovement(Vec3 deltaMovement, float friction) { ++ this.moveRelative(this.getFrictionInfluencedSpeed(friction), deltaMovement); + this.setDeltaMovement(this.handleOnClimbable(this.getDeltaMovement())); +- this.move(MoverType.SELF, this.getDeltaMovement()); +- Vec3 vec31 = this.getDeltaMovement(); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); ++ Vec3 vec3d1 = this.getDeltaMovement(); + + if ((this.horizontalCollision || this.jumping) && (this.onClimbable() || this.getFeetBlockState().is(Blocks.POWDER_SNOW) && PowderSnowBlock.canEntityWalkOnPowderSnow(this))) { +- vec31 = new Vec3(vec31.x, 0.2D, vec31.z); ++ vec3d1 = new Vec3(vec3d1.x, 0.2D, vec3d1.z); + } + +- return vec31; ++ return vec3d1; + } + +- public Vec3 getFluidFallingAdjustedMovement(double d0, boolean flag, Vec3 vec3) { ++ public Vec3 getFluidFallingAdjustedMovement(double gravity, boolean flag, Vec3 isFalling) { + if (!this.isNoGravity() && !this.isSprinting()) { + double d1; + +- if (flag && Math.abs(vec3.y - 0.005D) >= 0.003D && Math.abs(vec3.y - d0 / 16.0D) < 0.003D) { ++ if (flag && Math.abs(isFalling.y - 0.005D) >= 0.003D && Math.abs(isFalling.y - gravity / 16.0D) < 0.003D) { + d1 = -0.003D; + } else { +- d1 = vec3.y - d0 / 16.0D; ++ d1 = isFalling.y - gravity / 16.0D; + } + +- return new Vec3(vec3.x, d1, vec3.z); ++ return new Vec3(isFalling.x, d1, isFalling.z); + } else { +- return vec3; ++ return isFalling; + } + } + +- private Vec3 handleOnClimbable(Vec3 vec3) { ++ private Vec3 handleOnClimbable(Vec3 deltaMovement) { + if (this.onClimbable()) { + this.resetFallDistance(); + float f = 0.15F; +- double d0 = Mth.clamp(vec3.x, -0.15000000596046448D, 0.15000000596046448D); +- double d1 = Mth.clamp(vec3.z, -0.15000000596046448D, 0.15000000596046448D); +- double d2 = Math.max(vec3.y, -0.15000000596046448D); ++ double d0 = Mth.clamp(deltaMovement.x, -0.15000000596046448D, 0.15000000596046448D); ++ double d1 = Mth.clamp(deltaMovement.z, -0.15000000596046448D, 0.15000000596046448D); ++ double d2 = Math.max(deltaMovement.y, -0.15000000596046448D); + +- if (d2 < 0.0D && !this.getFeetBlockState().is(Blocks.SCAFFOLDING) && this.isSuppressingSlidingDownLadder() && this instanceof Player) { ++ if (d2 < 0.0D && !this.getFeetBlockState().is(Blocks.SCAFFOLDING) && this.isSuppressingSlidingDownLadder() && this instanceof net.minecraft.world.entity.player.Player) { + d2 = 0.0D; + } + +- vec3 = new Vec3(d0, d2, d1); ++ deltaMovement = new Vec3(d0, d2, d1); + } + +- return vec3; ++ return deltaMovement; + } + +- private float getFrictionInfluencedSpeed(float f) { +- return this.onGround() ? this.getSpeed() * (0.21600002F / (f * f * f)) : this.getFlyingSpeed(); ++ private float getFrictionInfluencedSpeed(float friction) { ++ return this.onGround() ? this.getSpeed() * (0.21600002F / (friction * friction * friction)) : this.getFlyingSpeed(); + } + + protected float getFlyingSpeed() { +- return this.getControllingPassenger() instanceof Player ? this.getSpeed() * 0.1F : 0.02F; ++ return this.getControllingPassenger() instanceof net.minecraft.world.entity.player.Player ? this.getSpeed() * 0.1F : 0.02F; + } + + public float getSpeed() { + return this.speed; + } + +- public void setSpeed(float f) { +- this.speed = f; ++ public void setSpeed(float speed) { ++ this.speed = speed; + } + +- public boolean doHurtTarget(Entity entity) { +- this.setLastHurtMob(entity); ++ public boolean doHurtTarget(Entity target) { ++ this.setLastHurtMob(target); + return false; + } + + @Override +- @Override + public void tick() { + super.tick(); + this.updatingUsingItem(); +@@ -2462,7 +2885,7 @@ + } + } + +- this.detectEquipmentUpdates(); ++ this.detectEquipmentUpdatesPublic(); // CraftBukkit + if (this.tickCount % 20 == 0) { + this.getCombatTracker().recheckStatus(); + } +@@ -2559,7 +2982,7 @@ + this.refreshDirtyAttributes(); + } + +- private void detectEquipmentUpdates() { ++ public void detectEquipmentUpdatesPublic() { // CraftBukkit + Map map = this.collectEquipmentChanges(); + + if (map != null) { +@@ -2574,38 +2997,38 @@ + @Nullable + private Map collectEquipmentChanges() { + Map map = null; +- EquipmentSlot[] aequipmentslot = EquipmentSlot.values(); +- int i = aequipmentslot.length; ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ int i = aenumitemslot.length; + + for (int j = 0; j < i; ++j) { +- EquipmentSlot equipmentslot = aequipmentslot[j]; ++ EquipmentSlot enumitemslot = aenumitemslot[j]; + ItemStack itemstack; + +- switch (equipmentslot.getType()) { ++ switch (enumitemslot.getType()) { + case HAND: +- itemstack = this.getLastHandItem(equipmentslot); ++ itemstack = this.getLastHandItem(enumitemslot); + break; + case ARMOR: +- itemstack = this.getLastArmorItem(equipmentslot); ++ itemstack = this.getLastArmorItem(enumitemslot); + break; + default: + continue; + } + +- ItemStack itemstack1 = this.getItemBySlot(equipmentslot); ++ ItemStack itemstack1 = this.getItemBySlot(enumitemslot); + + if (this.equipmentHasChanged(itemstack, itemstack1)) { + if (map == null) { + map = Maps.newEnumMap(EquipmentSlot.class); + } + +- map.put(equipmentslot, itemstack1); ++ map.put(enumitemslot, itemstack1); + if (!itemstack.isEmpty()) { +- this.getAttributes().removeAttributeModifiers(itemstack.getAttributeModifiers(equipmentslot)); ++ this.getAttributes().removeAttributeModifiers(itemstack.getAttributeModifiers(enumitemslot)); + } + + if (!itemstack1.isEmpty()) { +- this.getAttributes().addTransientAttributeModifiers(itemstack1.getAttributeModifiers(equipmentslot)); ++ this.getAttributes().addTransientAttributeModifiers(itemstack1.getAttributeModifiers(enumitemslot)); + } + } + } +@@ -2613,61 +3036,61 @@ + return map; + } + +- public boolean equipmentHasChanged(ItemStack itemstack, ItemStack itemstack1) { +- return !ItemStack.matches(itemstack1, itemstack); ++ public boolean equipmentHasChanged(ItemStack oldItem, ItemStack newItem) { ++ return !ItemStack.matches(newItem, oldItem); + } + +- private void handleHandSwap(Map map) { +- ItemStack itemstack = (ItemStack) map.get(EquipmentSlot.MAINHAND); +- ItemStack itemstack1 = (ItemStack) map.get(EquipmentSlot.OFFHAND); ++ private void handleHandSwap(Map hands) { ++ ItemStack itemstack = (ItemStack) hands.get(EquipmentSlot.MAINHAND); ++ ItemStack itemstack1 = (ItemStack) hands.get(EquipmentSlot.OFFHAND); + + if (itemstack != null && itemstack1 != null && ItemStack.matches(itemstack, this.getLastHandItem(EquipmentSlot.OFFHAND)) && ItemStack.matches(itemstack1, this.getLastHandItem(EquipmentSlot.MAINHAND))) { + ((ServerLevel) this.level()).getChunkSource().broadcast(this, new ClientboundEntityEventPacket(this, (byte) 55)); +- map.remove(EquipmentSlot.MAINHAND); +- map.remove(EquipmentSlot.OFFHAND); ++ hands.remove(EquipmentSlot.MAINHAND); ++ hands.remove(EquipmentSlot.OFFHAND); + this.setLastHandItem(EquipmentSlot.MAINHAND, itemstack.copy()); + this.setLastHandItem(EquipmentSlot.OFFHAND, itemstack1.copy()); + } + + } + +- private void handleEquipmentChanges(Map map) { +- List> list = Lists.newArrayListWithCapacity(map.size()); ++ private void handleEquipmentChanges(Map equipments) { ++ List> list = Lists.newArrayListWithCapacity(equipments.size()); + +- map.forEach((equipmentslot, itemstack) -> { ++ equipments.forEach((enumitemslot, itemstack) -> { + ItemStack itemstack1 = itemstack.copy(); + +- list.add(Pair.of(equipmentslot, itemstack1)); +- switch (equipmentslot.getType()) { ++ list.add(Pair.of(enumitemslot, itemstack1)); ++ switch (enumitemslot.getType()) { + case HAND: +- this.setLastHandItem(equipmentslot, itemstack1); ++ this.setLastHandItem(enumitemslot, itemstack1); + break; + case ARMOR: +- this.setLastArmorItem(equipmentslot, itemstack1); ++ this.setLastArmorItem(enumitemslot, itemstack1); + } + + }); + ((ServerLevel) this.level()).getChunkSource().broadcast(this, new ClientboundSetEquipmentPacket(this.getId(), list)); + } + +- private ItemStack getLastArmorItem(EquipmentSlot equipmentslot) { +- return (ItemStack) this.lastArmorItemStacks.get(equipmentslot.getIndex()); ++ private ItemStack getLastArmorItem(EquipmentSlot slot) { ++ return (ItemStack) this.lastArmorItemStacks.get(slot.getIndex()); + } + +- private void setLastArmorItem(EquipmentSlot equipmentslot, ItemStack itemstack) { +- this.lastArmorItemStacks.set(equipmentslot.getIndex(), itemstack); ++ private void setLastArmorItem(EquipmentSlot slot, ItemStack stack) { ++ this.lastArmorItemStacks.set(slot.getIndex(), stack); + } + +- private ItemStack getLastHandItem(EquipmentSlot equipmentslot) { +- return (ItemStack) this.lastHandItemStacks.get(equipmentslot.getIndex()); ++ private ItemStack getLastHandItem(EquipmentSlot slot) { ++ return (ItemStack) this.lastHandItemStacks.get(slot.getIndex()); + } + +- private void setLastHandItem(EquipmentSlot equipmentslot, ItemStack itemstack) { +- this.lastHandItemStacks.set(equipmentslot.getIndex(), itemstack); ++ private void setLastHandItem(EquipmentSlot slot, ItemStack stack) { ++ this.lastHandItemStacks.set(slot.getIndex(), stack); + } + +- protected float tickHeadTurn(float f, float f1) { +- float f2 = Mth.wrapDegrees(f - this.yBodyRot); ++ protected float tickHeadTurn(float yRot, float animStep) { ++ float f2 = Mth.wrapDegrees(yRot - this.yBodyRot); + + this.yBodyRot += f2 * 0.3F; + float f3 = Mth.wrapDegrees(this.getYRot() - this.yBodyRot); +@@ -2680,10 +3103,10 @@ + boolean flag = f3 < -90.0F || f3 >= 90.0F; + + if (flag) { +- f1 *= -1.0F; ++ animStep *= -1.0F; + } + +- return f1; ++ return animStep; + } + + protected float getMaxHeadRotationRelativeToBody() { +@@ -2712,20 +3135,20 @@ + --this.lerpHeadSteps; + } + +- Vec3 vec3 = this.getDeltaMovement(); +- double d0 = vec3.x; +- double d1 = vec3.y; +- double d2 = vec3.z; ++ Vec3 vec3d = this.getDeltaMovement(); ++ double d0 = vec3d.x; ++ double d1 = vec3d.y; ++ double d2 = vec3d.z; + +- if (Math.abs(vec3.x) < 0.003D) { ++ if (Math.abs(vec3d.x) < 0.003D) { + d0 = 0.0D; + } + +- if (Math.abs(vec3.y) < 0.003D) { ++ if (Math.abs(vec3d.y) < 0.003D) { + d1 = 0.0D; + } + +- if (Math.abs(vec3.z) < 0.003D) { ++ if (Math.abs(vec3d.z) < 0.003D) { + d2 = 0.0D; + } + +@@ -2772,8 +3195,8 @@ + this.xxa *= 0.98F; + this.zza *= 0.98F; + this.updateFallFlying(); +- AABB aabb = this.getBoundingBox(); +- Vec3 vec31 = new Vec3((double) this.xxa, (double) this.yya, (double) this.zza); ++ AABB axisalignedbb = this.getBoundingBox(); ++ Vec3 vec3d1 = new Vec3((double) this.xxa, (double) this.yya, (double) this.zza); + + if (this.hasEffect(MobEffects.SLOW_FALLING) || this.hasEffect(MobEffects.LEVITATION)) { + this.resetFallDistance(); +@@ -2781,18 +3204,18 @@ + + label104: + { +- LivingEntity livingentity = this.getControllingPassenger(); ++ LivingEntity entityliving = this.getControllingPassenger(); + +- if (livingentity instanceof Player) { +- Player player = (Player) livingentity; ++ if (entityliving instanceof net.minecraft.world.entity.player.Player) { ++ net.minecraft.world.entity.player.Player entityhuman = (net.minecraft.world.entity.player.Player) entityliving; + + if (this.isAlive()) { +- this.travelRidden(player, vec31); ++ this.travelRidden(entityhuman, vec3d1); + break label104; + } + } + +- this.travel(vec31); ++ this.travel(vec3d1); + } + + this.level().getProfiler().pop(); +@@ -2817,7 +3240,7 @@ + this.level().getProfiler().push("push"); + if (this.autoSpinAttackTicks > 0) { + --this.autoSpinAttackTicks; +- this.checkAutoSpinAttack(aabb, this.getBoundingBox()); ++ this.checkAutoSpinAttack(axisalignedbb, this.getBoundingBox()); + } + + this.pushEntities(); +@@ -2846,8 +3269,8 @@ + int j = i / 10; + + if (j % 2 == 0) { +- itemstack.hurtAndBreak(1, this, (livingentity) -> { +- livingentity.broadcastBreakEvent(EquipmentSlot.CHEST); ++ itemstack.hurtAndBreak(1, this, (entityliving) -> { ++ entityliving.broadcastBreakEvent(EquipmentSlot.CHEST); + }); + } + +@@ -2861,6 +3284,7 @@ + } + + if (!this.level().isClientSide) { ++ if (flag != this.getSharedFlag(7) && !CraftEventFactory.callToggleGlideEvent(this, flag).isCancelled()) // CraftBukkit + this.setSharedFlag(7, flag); + } + +@@ -2870,7 +3294,7 @@ + + protected void pushEntities() { + if (this.level().isClientSide()) { +- this.level().getEntities(EntityTypeTest.forClass(Player.class), this.getBoundingBox(), EntitySelector.pushableBy(this)).forEach(this::doPush); ++ this.level().getEntities(EntityTypeTest.forClass(net.minecraft.world.entity.player.Player.class), this.getBoundingBox(), EntitySelector.pushableBy(this)).forEach(this::doPush); + } else { + List list = this.level().getEntities((Entity) this, this.getBoundingBox(), EntitySelector.pushableBy(this)); + +@@ -2906,9 +3330,9 @@ + } + } + +- protected void checkAutoSpinAttack(AABB aabb, AABB aabb1) { +- AABB aabb2 = aabb.minmax(aabb1); +- List list = this.level().getEntities(this, aabb2); ++ protected void checkAutoSpinAttack(AABB boundingBoxBeforeSpin, AABB boundingBoxAfterSpin) { ++ AABB axisalignedbb2 = boundingBoxBeforeSpin.minmax(boundingBoxAfterSpin); ++ List list = this.level().getEntities(this, axisalignedbb2); + + if (!list.isEmpty()) { + Iterator iterator = list.iterator(); +@@ -2937,14 +3361,13 @@ + entity.push(this); + } + +- protected void doAutoAttackOnTouch(LivingEntity livingentity) {} ++ protected void doAutoAttackOnTouch(LivingEntity target) {} + + public boolean isAutoSpinAttack() { + return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 4) != 0; + } + + @Override +- @Override + public void stopRiding() { + Entity entity = this.getVehicle(); + +@@ -2956,7 +3379,6 @@ + } + + @Override +- @Override + public void rideTick() { + super.rideTick(); + this.oRun = this.run; +@@ -2965,7 +3387,6 @@ + } + + @Override +- @Override + public void lerpTo(double d0, double d1, double d2, float f, float f1, int i) { + this.lerpX = d0; + this.lerpY = d1; +@@ -2976,58 +3397,52 @@ + } + + @Override +- @Override + public double lerpTargetX() { + return this.lerpSteps > 0 ? this.lerpX : this.getX(); + } + + @Override +- @Override + public double lerpTargetY() { + return this.lerpSteps > 0 ? this.lerpY : this.getY(); + } + + @Override +- @Override + public double lerpTargetZ() { + return this.lerpSteps > 0 ? this.lerpZ : this.getZ(); + } + + @Override +- @Override + public float lerpTargetXRot() { + return this.lerpSteps > 0 ? (float) this.lerpXRot : this.getXRot(); + } + + @Override +- @Override + public float lerpTargetYRot() { + return this.lerpSteps > 0 ? (float) this.lerpYRot : this.getYRot(); + } + + @Override +- @Override +- public void lerpHeadTo(float f, int i) { +- this.lerpYHeadRot = (double) f; +- this.lerpHeadSteps = i; ++ public void lerpHeadTo(float yaw, int pitch) { ++ this.lerpYHeadRot = (double) yaw; ++ this.lerpHeadSteps = pitch; + } + +- public void setJumping(boolean flag) { +- this.jumping = flag; ++ public void setJumping(boolean jumping) { ++ this.jumping = jumping; + } + +- public void onItemPickup(ItemEntity itementity) { +- Entity entity = itementity.getOwner(); ++ public void onItemPickup(ItemEntity itemEntity) { ++ Entity entity = itemEntity.getOwner(); + + if (entity instanceof ServerPlayer) { +- CriteriaTriggers.THROWN_ITEM_PICKED_UP_BY_ENTITY.trigger((ServerPlayer) entity, itementity.getItem(), this); ++ CriteriaTriggers.THROWN_ITEM_PICKED_UP_BY_ENTITY.trigger((ServerPlayer) entity, itemEntity.getItem(), this); + } + + } + +- public void take(Entity entity, int i) { ++ public void take(Entity entity, int amount) { + if (!entity.isRemoved() && !this.level().isClientSide && (entity instanceof ItemEntity || entity instanceof AbstractArrow || entity instanceof ExperienceOrb)) { +- ((ServerLevel) this.level()).getChunkSource().broadcast(entity, new ClientboundTakeItemEntityPacket(entity.getId(), this.getId(), i)); ++ ((ServerLevel) this.level()).getChunkSource().broadcast(entity, new ClientboundTakeItemEntityPacket(entity.getId(), this.getId(), amount)); + } + + } +@@ -3036,75 +3451,75 @@ + if (entity.level() != this.level()) { + return false; + } else { +- Vec3 vec3 = new Vec3(this.getX(), this.getEyeY(), this.getZ()); +- Vec3 vec31 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); ++ Vec3 vec3d = new Vec3(this.getX(), this.getEyeY(), this.getZ()); ++ Vec3 vec3d1 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); + +- return vec31.distanceTo(vec3) > 128.0D ? false : this.level().clip(new ClipContext(vec3, vec31, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() == HitResult.Type.MISS; ++ return vec3d1.distanceTo(vec3d) > 128.0D ? false : this.level().clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() == HitResult.EnumMovingObjectType.MISS; + } + } + + @Override +- @Override +- public float getViewYRot(float f) { +- return f == 1.0F ? this.yHeadRot : Mth.lerp(f, this.yHeadRotO, this.yHeadRot); ++ public float getViewYRot(float partialTicks) { ++ return partialTicks == 1.0F ? this.yHeadRot : Mth.lerp(partialTicks, this.yHeadRotO, this.yHeadRot); + } + +- public float getAttackAnim(float f) { ++ public float getAttackAnim(float partialTick) { + float f1 = this.attackAnim - this.oAttackAnim; + + if (f1 < 0.0F) { + ++f1; + } + +- return this.oAttackAnim + f1 * f; ++ return this.oAttackAnim + f1 * partialTick; + } + + @Override +- @Override + public boolean isPickable() { +- return !this.isRemoved(); ++ return !this.isRemoved() && this.collides; // CraftBukkit + } + + @Override +- @Override + public boolean isPushable() { +- return this.isAlive() && !this.isSpectator() && !this.onClimbable(); ++ return this.isAlive() && !this.isSpectator() && !this.onClimbable() && this.collides; // CraftBukkit + } + ++ // CraftBukkit start - collidable API + @Override ++ public boolean canCollideWithBukkit(Entity entity) { ++ return isPushable() && this.collides != this.collidableExemptions.contains(entity.getUUID()); ++ } ++ // CraftBukkit end ++ + @Override + public float getYHeadRot() { + return this.yHeadRot; + } + + @Override +- @Override +- public void setYHeadRot(float f) { +- this.yHeadRot = f; ++ public void setYHeadRot(float rotation) { ++ this.yHeadRot = rotation; + } + + @Override +- @Override +- public void setYBodyRot(float f) { +- this.yBodyRot = f; ++ public void setYBodyRot(float offset) { ++ this.yBodyRot = offset; + } + + @Override +- @Override +- protected Vec3 getRelativePortalPosition(Direction.Axis direction_axis, BlockUtil.FoundRectangle blockutil_foundrectangle) { +- return resetForwardDirectionOfRelativePortalPosition(super.getRelativePortalPosition(direction_axis, blockutil_foundrectangle)); ++ protected Vec3 getRelativePortalPosition(Direction.Axis axis, BlockUtil.FoundRectangle portal) { ++ return resetForwardDirectionOfRelativePortalPosition(super.getRelativePortalPosition(axis, portal)); + } + +- public static Vec3 resetForwardDirectionOfRelativePortalPosition(Vec3 vec3) { +- return new Vec3(vec3.x, vec3.y, 0.0D); ++ public static Vec3 resetForwardDirectionOfRelativePortalPosition(Vec3 relativePortalPosition) { ++ return new Vec3(relativePortalPosition.x, relativePortalPosition.y, 0.0D); + } + + public float getAbsorptionAmount() { + return this.absorptionAmount; + } + +- public final void setAbsorptionAmount(float f) { +- this.internalSetAbsorptionAmount(Mth.clamp(f, 0.0F, this.getMaxAbsorption())); ++ public final void setAbsorptionAmount(float absorptionAmount) { ++ this.internalSetAbsorptionAmount(Mth.clamp(absorptionAmount, 0.0F, this.getMaxAbsorption())); + } + + protected void internalSetAbsorptionAmount(float f) { +@@ -3125,8 +3540,8 @@ + return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 1) > 0; + } + +- public InteractionHand getUsedItemHand() { +- return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND; ++ public EnumHand getUsedItemHand() { ++ return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? EnumHand.OFF_HAND : EnumHand.MAIN_HAND; + } + + private void updatingUsingItem() { +@@ -3141,13 +3556,13 @@ + + } + +- protected void updateUsingItem(ItemStack itemstack) { +- itemstack.onUseTick(this.level(), this, this.getUseItemRemainingTicks()); ++ protected void updateUsingItem(ItemStack usingItem) { ++ usingItem.onUseTick(this.level(), this, this.getUseItemRemainingTicks()); + if (this.shouldTriggerItemUseEffects()) { +- this.triggerItemUseEffects(itemstack, 5); ++ this.triggerItemUseEffects(usingItem, 5); + } + +- if (--this.useItemRemaining == 0 && !this.level().isClientSide && !itemstack.useOnRelease()) { ++ if (--this.useItemRemaining == 0 && !this.level().isClientSide && !usingItem.useOnRelease()) { + this.completeUsingItem(); + } + +@@ -3155,8 +3570,8 @@ + + private boolean shouldTriggerItemUseEffects() { + int i = this.getUseItemRemainingTicks(); +- FoodProperties foodproperties = this.useItem.getItem().getFoodProperties(); +- boolean flag = foodproperties != null && foodproperties.isFastFood(); ++ FoodProperties foodinfo = this.useItem.getItem().getFoodProperties(); ++ boolean flag = foodinfo != null && foodinfo.isFastFood(); + + flag |= i <= this.useItem.getUseDuration() - 7; + return flag && i % 4 == 0; +@@ -3172,28 +3587,28 @@ + + } + +- protected void setLivingEntityFlag(int i, boolean flag) { ++ protected void setLivingEntityFlag(int key, boolean value) { + byte b0 = (Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS); + int j; + +- if (flag) { +- j = b0 | i; ++ if (value) { ++ j = b0 | key; + } else { +- j = b0 & ~i; ++ j = b0 & ~key; + } + + this.entityData.set(LivingEntity.DATA_LIVING_ENTITY_FLAGS, (byte) j); + } + +- public void startUsingItem(InteractionHand interactionhand) { +- ItemStack itemstack = this.getItemInHand(interactionhand); ++ public void startUsingItem(EnumHand hand) { ++ ItemStack itemstack = this.getItemInHand(hand); + + if (!itemstack.isEmpty() && !this.isUsingItem()) { + this.useItem = itemstack; + this.useItemRemaining = itemstack.getUseDuration(); + if (!this.level().isClientSide) { + this.setLivingEntityFlag(1, true); +- this.setLivingEntityFlag(2, interactionhand == InteractionHand.OFF_HAND); ++ this.setLivingEntityFlag(2, hand == EnumHand.OFF_HAND); + this.gameEvent(GameEvent.ITEM_INTERACT_START); + } + +@@ -3201,14 +3616,13 @@ + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- super.onSyncedDataUpdated(entitydataaccessor); +- if (LivingEntity.SLEEPING_POS_ID.equals(entitydataaccessor)) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ super.onSyncedDataUpdated(key); ++ if (LivingEntity.SLEEPING_POS_ID.equals(key)) { + if (this.level().isClientSide) { + this.getSleepingPos().ifPresent(this::setPosToBed); + } +- } else if (LivingEntity.DATA_LIVING_ENTITY_FLAGS.equals(entitydataaccessor) && this.level().isClientSide) { ++ } else if (LivingEntity.DATA_LIVING_ENTITY_FLAGS.equals(key) && this.level().isClientSide) { + if (this.isUsingItem() && this.useItem.isEmpty()) { + this.useItem = this.getItemInHand(this.getUsedItemHand()); + if (!this.useItem.isEmpty()) { +@@ -3223,58 +3637,76 @@ + } + + @Override +- @Override +- public void lookAt(EntityAnchorArgument.Anchor entityanchorargument_anchor, Vec3 vec3) { +- super.lookAt(entityanchorargument_anchor, vec3); ++ public void lookAt(EntityAnchorArgument.Anchor anchor, Vec3 target) { ++ super.lookAt(anchor, target); + this.yHeadRotO = this.yHeadRot; + this.yBodyRot = this.yHeadRot; + this.yBodyRotO = this.yBodyRot; + } + +- protected void triggerItemUseEffects(ItemStack itemstack, int i) { +- if (!itemstack.isEmpty() && this.isUsingItem()) { +- if (itemstack.getUseAnimation() == UseAnim.DRINK) { +- this.playSound(this.getDrinkingSound(itemstack), 0.5F, this.level().random.nextFloat() * 0.1F + 0.9F); ++ protected void triggerItemUseEffects(ItemStack stack, int amount) { ++ if (!stack.isEmpty() && this.isUsingItem()) { ++ if (stack.getUseAnimation() == EnumAnimation.DRINK) { ++ this.playSound(this.getDrinkingSound(stack), 0.5F, this.level().random.nextFloat() * 0.1F + 0.9F); + } + +- if (itemstack.getUseAnimation() == UseAnim.EAT) { +- this.spawnItemParticles(itemstack, i); +- this.playSound(this.getEatingSound(itemstack), 0.5F + 0.5F * (float) this.random.nextInt(2), (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); ++ if (stack.getUseAnimation() == EnumAnimation.EAT) { ++ this.spawnItemParticles(stack, amount); ++ this.playSound(this.getEatingSound(stack), 0.5F + 0.5F * (float) this.random.nextInt(2), (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); + } + + } + } + +- private void spawnItemParticles(ItemStack itemstack, int i) { +- for (int j = 0; j < i; ++j) { +- Vec3 vec3 = new Vec3(((double) this.random.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, 0.0D); ++ private void spawnItemParticles(ItemStack stack, int amount) { ++ for (int j = 0; j < amount; ++j) { ++ Vec3 vec3d = new Vec3(((double) this.random.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, 0.0D); + +- vec3 = vec3.xRot(-this.getXRot() * 0.017453292F); +- vec3 = vec3.yRot(-this.getYRot() * 0.017453292F); ++ vec3d = vec3d.xRot(-this.getXRot() * 0.017453292F); ++ vec3d = vec3d.yRot(-this.getYRot() * 0.017453292F); + double d0 = (double) (-this.random.nextFloat()) * 0.6D - 0.3D; +- Vec3 vec31 = new Vec3(((double) this.random.nextFloat() - 0.5D) * 0.3D, d0, 0.6D); ++ Vec3 vec3d1 = new Vec3(((double) this.random.nextFloat() - 0.5D) * 0.3D, d0, 0.6D); + +- vec31 = vec31.xRot(-this.getXRot() * 0.017453292F); +- vec31 = vec31.yRot(-this.getYRot() * 0.017453292F); +- vec31 = vec31.add(this.getX(), this.getEyeY(), this.getZ()); +- this.level().addParticle(new ItemParticleOption(ParticleTypes.ITEM, itemstack), vec31.x, vec31.y, vec31.z, vec3.x, vec3.y + 0.05D, vec3.z); ++ vec3d1 = vec3d1.xRot(-this.getXRot() * 0.017453292F); ++ vec3d1 = vec3d1.yRot(-this.getYRot() * 0.017453292F); ++ vec3d1 = vec3d1.add(this.getX(), this.getEyeY(), this.getZ()); ++ this.level().addParticle(new ItemParticleOption(ParticleTypes.ITEM, stack), vec3d1.x, vec3d1.y, vec3d1.z, vec3d.x, vec3d.y + 0.05D, vec3d.z); + } + + } + + protected void completeUsingItem() { + if (!this.level().isClientSide || this.isUsingItem()) { +- InteractionHand interactionhand = this.getUsedItemHand(); ++ EnumHand enumhand = this.getUsedItemHand(); + +- if (!this.useItem.equals(this.getItemInHand(interactionhand))) { ++ if (!this.useItem.equals(this.getItemInHand(enumhand))) { + this.releaseUsingItem(); + } else { + if (!this.useItem.isEmpty() && this.isUsingItem()) { + this.triggerItemUseEffects(this.useItem, 16); +- ItemStack itemstack = this.useItem.finishUsingItem(this.level(), this); ++ // CraftBukkit start - fire PlayerItemConsumeEvent ++ ItemStack itemstack; ++ if (this instanceof ServerPlayer) { ++ org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(this.useItem); ++ org.bukkit.inventory.EquipmentSlot hand = org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(enumhand); ++ PlayerItemConsumeEvent event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem, hand); ++ this.level().getCraftServer().getPluginManager().callEvent(event); + ++ if (event.isCancelled()) { ++ // Update client ++ ((ServerPlayer) this).getBukkitEntity().updateInventory(); ++ ((ServerPlayer) this).getBukkitEntity().updateScaledHealth(); ++ return; ++ } ++ ++ itemstack = (craftItem.equals(event.getItem())) ? this.useItem.finishUsingItem(this.level(), this) : CraftItemStack.asNMSCopy(event.getItem()).finishUsingItem(this.level(), this); ++ } else { ++ itemstack = this.useItem.finishUsingItem(this.level(), this); ++ } ++ // CraftBukkit end ++ + if (itemstack != this.useItem) { +- this.setItemInHand(interactionhand, itemstack); ++ this.setItemInHand(enumhand, itemstack); + } + + this.stopUsingItem(); +@@ -3325,7 +3757,7 @@ + if (this.isUsingItem() && !this.useItem.isEmpty()) { + Item item = this.useItem.getItem(); + +- return item.getUseAnimation(this.useItem) != UseAnim.BLOCK ? false : item.getUseDuration(this.useItem) - this.useItemRemaining >= 5; ++ return item.getUseAnimation(this.useItem) != EnumAnimation.BLOCK ? false : item.getUseDuration(this.useItem) - this.useItemRemaining >= 5; + } else { + return false; + } +@@ -3340,62 +3772,92 @@ + } + + @Override +- @Override + public boolean isVisuallySwimming() { +- return super.isVisuallySwimming() || !this.isFallFlying() && this.hasPose(Pose.FALL_FLYING); ++ return super.isVisuallySwimming() || !this.isFallFlying() && this.hasPose(EntityPose.FALL_FLYING); + } + + public int getFallFlyingTicks() { + return this.fallFlyTicks; + } + +- public boolean randomTeleport(double d0, double d1, double d2, boolean flag) { ++ public boolean randomTeleport(double x, double d1, double y, boolean flag) { ++ // CraftBukkit start ++ return randomTeleport(x, d1, y, flag, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.UNKNOWN).orElse(false); ++ } ++ ++ public Optional randomTeleport(double d0, double d1, double d2, boolean flag, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { ++ // CraftBukkit end + double d3 = this.getX(); + double d4 = this.getY(); + double d5 = this.getZ(); + double d6 = d1; + boolean flag1 = false; +- BlockPos blockpos = BlockPos.containing(d0, d1, d2); +- Level level = this.level(); ++ BlockPos blockposition = BlockPos.containing(d0, d1, d2); ++ Level world = this.level(); + +- if (level.hasChunkAt(blockpos)) { ++ if (world.hasChunkAt(blockposition)) { + boolean flag2 = false; + +- while (!flag2 && blockpos.getY() > level.getMinBuildHeight()) { +- BlockPos blockpos1 = blockpos.below(); +- BlockState blockstate = level.getBlockState(blockpos1); ++ while (!flag2 && blockposition.getY() > world.getMinBuildHeight()) { ++ BlockPos blockposition1 = blockposition.below(); ++ IBlockData iblockdata = world.getBlockState(blockposition1); + +- if (blockstate.blocksMotion()) { ++ if (iblockdata.blocksMotion()) { + flag2 = true; + } else { + --d6; +- blockpos = blockpos1; ++ blockposition = blockposition1; + } + } + + if (flag2) { +- this.teleportTo(d0, d6, d2); +- if (level.noCollision((Entity) this) && !level.containsAnyLiquid(this.getBoundingBox())) { ++ // CraftBukkit start - Teleport event ++ // this.teleportTo(d0, d6, d2); ++ ++ // first set position, to check if the place to teleport is valid ++ this.setPos(d0, d6, d2); ++ if (world.noCollision((Entity) this) && !world.containsAnyLiquid(this.getBoundingBox())) { + flag1 = true; + } ++ // now revert and call event if the teleport place is valid ++ this.setPos(d3, d4, d5); ++ ++ if (flag1) { ++ if (!(this instanceof ServerPlayer)) { ++ EntityTeleportEvent teleport = new EntityTeleportEvent(this.getBukkitEntity(), new Location(this.level().getWorld(), d3, d4, d5), new Location(this.level().getWorld(), d0, d6, d2)); ++ this.level().getCraftServer().getPluginManager().callEvent(teleport); ++ if (!teleport.isCancelled()) { ++ Location to = teleport.getTo(); ++ this.teleportTo(to.getX(), to.getY(), to.getZ()); ++ } else { ++ return Optional.empty(); ++ } ++ } else { ++ // player teleport event is called in the underlining code ++ if (((ServerPlayer) this).connection.teleport(d0, d6, d2, this.getYRot(), this.getXRot(), java.util.Collections.emptySet(), cause)) { ++ return Optional.empty(); ++ } ++ } ++ } ++ // CraftBukkit end + } + } + + if (!flag1) { +- this.teleportTo(d3, d4, d5); +- return false; ++ // this.enderTeleportTo(d3, d4, d5); // CraftBukkit - already set the location back ++ return Optional.of(false); // CraftBukkit + } else { + if (flag) { +- level.broadcastEntityEvent(this, (byte) 46); ++ world.broadcastEntityEvent(this, (byte) 46); + } + + if (this instanceof PathfinderMob) { +- PathfinderMob pathfindermob = (PathfinderMob) this; ++ PathfinderMob entitycreature = (PathfinderMob) this; + +- pathfindermob.getNavigation().stop(); ++ entitycreature.getNavigation().stop(); + } + +- return true; ++ return Optional.of(true); // CraftBukkit + } + } + +@@ -3407,36 +3869,34 @@ + return true; + } + +- public void setRecordPlayingNearby(BlockPos blockpos, boolean flag) {} ++ public void setRecordPlayingNearby(BlockPos jukebox, boolean partyParrot) {} + +- public boolean canTakeItem(ItemStack itemstack) { ++ public boolean canTakeItem(ItemStack stack) { + return false; + } + + @Override +- @Override +- public EntityDimensions getDimensions(Pose pose) { +- return pose == Pose.SLEEPING ? LivingEntity.SLEEPING_DIMENSIONS : super.getDimensions(pose).scale(this.getScale()); ++ public EntityDimensions getDimensions(EntityPose pose) { ++ return pose == EntityPose.SLEEPING ? LivingEntity.SLEEPING_DIMENSIONS : super.getDimensions(pose).scale(this.getScale()); + } + +- public ImmutableList getDismountPoses() { +- return ImmutableList.of(Pose.STANDING); ++ public ImmutableList getDismountPoses() { ++ return ImmutableList.of(EntityPose.STANDING); + } + +- public AABB getLocalBoundsForPose(Pose pose) { +- EntityDimensions entitydimensions = this.getDimensions(pose); ++ public AABB getLocalBoundsForPose(EntityPose pose) { ++ EntityDimensions entitysize = this.getDimensions(pose); + +- return new AABB((double) (-entitydimensions.width / 2.0F), 0.0D, (double) (-entitydimensions.width / 2.0F), (double) (entitydimensions.width / 2.0F), (double) entitydimensions.height, (double) (entitydimensions.width / 2.0F)); ++ return new AABB((double) (-entitysize.width / 2.0F), 0.0D, (double) (-entitysize.width / 2.0F), (double) (entitysize.width / 2.0F), (double) entitysize.height, (double) (entitysize.width / 2.0F)); + } + +- protected boolean wouldNotSuffocateAtTargetPose(Pose pose) { +- AABB aabb = this.getDimensions(pose).makeBoundingBox(this.position()); ++ protected boolean wouldNotSuffocateAtTargetPose(EntityPose entitypose) { ++ AABB axisalignedbb = this.getDimensions(entitypose).makeBoundingBox(this.position()); + +- return this.level().noBlockCollision(this, aabb); ++ return this.level().noBlockCollision(this, axisalignedbb); + } + + @Override +- @Override + public boolean canChangeDimensions() { + return super.canChangeDimensions() && !this.isSleeping(); + } +@@ -3445,8 +3905,8 @@ + return (Optional) this.entityData.get(LivingEntity.SLEEPING_POS_ID); + } + +- public void setSleepingPos(BlockPos blockpos) { +- this.entityData.set(LivingEntity.SLEEPING_POS_ID, Optional.of(blockpos)); ++ public void setSleepingPos(BlockPos pos) { ++ this.entityData.set(LivingEntity.SLEEPING_POS_ID, Optional.of(pos)); + } + + public void clearSleepingPos() { +@@ -3457,110 +3917,108 @@ + return this.getSleepingPos().isPresent(); + } + +- public void startSleeping(BlockPos blockpos) { ++ public void startSleeping(BlockPos pos) { + if (this.isPassenger()) { + this.stopRiding(); + } + +- BlockState blockstate = this.level().getBlockState(blockpos); ++ IBlockData iblockdata = this.level().getBlockState(pos); + +- if (blockstate.getBlock() instanceof BedBlock) { +- this.level().setBlock(blockpos, (BlockState) blockstate.setValue(BedBlock.OCCUPIED, true), 3); ++ if (iblockdata.getBlock() instanceof BedBlock) { ++ this.level().setBlock(pos, (IBlockData) iblockdata.setValue(BedBlock.OCCUPIED, true), 3); + } + +- this.setPose(Pose.SLEEPING); +- this.setPosToBed(blockpos); +- this.setSleepingPos(blockpos); ++ this.setPose(EntityPose.SLEEPING); ++ this.setPosToBed(pos); ++ this.setSleepingPos(pos); + this.setDeltaMovement(Vec3.ZERO); + this.hasImpulse = true; + } + +- private void setPosToBed(BlockPos blockpos) { +- this.setPos((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.6875D, (double) blockpos.getZ() + 0.5D); ++ private void setPosToBed(BlockPos pos) { ++ this.setPos((double) pos.getX() + 0.5D, (double) pos.getY() + 0.6875D, (double) pos.getZ() + 0.5D); + } + + private boolean checkBedExists() { +- return (Boolean) this.getSleepingPos().map((blockpos) -> { +- return this.level().getBlockState(blockpos).getBlock() instanceof BedBlock; ++ return (Boolean) this.getSleepingPos().map((blockposition) -> { ++ return this.level().getBlockState(blockposition).getBlock() instanceof BedBlock; + }).orElse(false); + } + + public void stopSleeping() { +- Optional optional = this.getSleepingPos(); +- Level level = this.level(); ++ Optional optional = this.getSleepingPos(); // CraftBukkit - decompile error ++ Level world = this.level(); + +- java.util.Objects.requireNonNull(level); +- optional.filter(level::hasChunkAt).ifPresent((blockpos) -> { +- BlockState blockstate = this.level().getBlockState(blockpos); ++ java.util.Objects.requireNonNull(world); ++ optional.filter(world::hasChunkAt).ifPresent((blockposition) -> { ++ IBlockData iblockdata = this.level().getBlockState(blockposition); + +- if (blockstate.getBlock() instanceof BedBlock) { +- Direction direction = (Direction) blockstate.getValue(BedBlock.FACING); ++ if (iblockdata.getBlock() instanceof BedBlock) { ++ Direction enumdirection = (Direction) iblockdata.getValue(BedBlock.FACING); + +- this.level().setBlock(blockpos, (BlockState) blockstate.setValue(BedBlock.OCCUPIED, false), 3); +- Vec3 vec3 = (Vec3) BedBlock.findStandUpPosition(this.getType(), this.level(), blockpos, direction, this.getYRot()).orElseGet(() -> { +- BlockPos blockpos1 = blockpos.above(); ++ this.level().setBlock(blockposition, (IBlockData) iblockdata.setValue(BedBlock.OCCUPIED, false), 3); ++ Vec3 vec3d = (Vec3) BedBlock.findStandUpPosition(this.getType(), this.level(), blockposition, enumdirection, this.getYRot()).orElseGet(() -> { ++ BlockPos blockposition1 = blockposition.above(); + +- return new Vec3((double) blockpos1.getX() + 0.5D, (double) blockpos1.getY() + 0.1D, (double) blockpos1.getZ() + 0.5D); ++ return new Vec3((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.1D, (double) blockposition1.getZ() + 0.5D); + }); +- Vec3 vec31 = Vec3.atBottomCenterOf(blockpos).subtract(vec3).normalize(); +- float f = (float) Mth.wrapDegrees(Mth.atan2(vec31.z, vec31.x) * 57.2957763671875D - 90.0D); ++ Vec3 vec3d1 = Vec3.atBottomCenterOf(blockposition).subtract(vec3d).normalize(); ++ float f = (float) Mth.wrapDegrees(Mth.atan2(vec3d1.z, vec3d1.x) * 57.2957763671875D - 90.0D); + +- this.setPos(vec3.x, vec3.y, vec3.z); ++ this.setPos(vec3d.x, vec3d.y, vec3d.z); + this.setYRot(f); + this.setXRot(0.0F); + } + + }); +- Vec3 vec3 = this.position(); ++ Vec3 vec3d = this.position(); + +- this.setPose(Pose.STANDING); +- this.setPos(vec3.x, vec3.y, vec3.z); ++ this.setPose(EntityPose.STANDING); ++ this.setPos(vec3d.x, vec3d.y, vec3d.z); + this.clearSleepingPos(); + } + + @Nullable + public Direction getBedOrientation() { +- BlockPos blockpos = (BlockPos) this.getSleepingPos().orElse((Object) null); ++ BlockPos blockposition = (BlockPos) this.getSleepingPos().orElse(null); // CraftBukkit - decompile error + +- return blockpos != null ? BedBlock.getBedOrientation(this.level(), blockpos) : null; ++ return blockposition != null ? BedBlock.getBedOrientation(this.level(), blockposition) : null; + } + + @Override +- @Override + public boolean isInWall() { + return !this.isSleeping() && super.isInWall(); + } + + @Override +- @Override +- protected final float getEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return pose == Pose.SLEEPING ? 0.2F : this.getStandingEyeHeight(pose, entitydimensions); ++ protected final float getEyeHeight(EntityPose pose, EntityDimensions size) { ++ return pose == EntityPose.SLEEPING ? 0.2F : this.getStandingEyeHeight(pose, size); + } + +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return super.getEyeHeight(pose, entitydimensions); ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions dimensions) { ++ return super.getEyeHeight(pose, dimensions); + } + +- public ItemStack getProjectile(ItemStack itemstack) { ++ public ItemStack getProjectile(ItemStack weaponStack) { + return ItemStack.EMPTY; + } + +- public ItemStack eat(Level level, ItemStack itemstack) { +- if (itemstack.isEdible()) { +- level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), this.getEatingSound(itemstack), SoundSource.NEUTRAL, 1.0F, 1.0F + (level.random.nextFloat() - level.random.nextFloat()) * 0.4F); +- this.addEatEffect(itemstack, level, this); +- if (!(this instanceof Player) || !((Player) this).getAbilities().instabuild) { +- itemstack.shrink(1); ++ public ItemStack eat(Level level, ItemStack food) { ++ if (food.isEdible()) { ++ level.playSound((net.minecraft.world.entity.player.Player) null, this.getX(), this.getY(), this.getZ(), this.getEatingSound(food), SoundSource.NEUTRAL, 1.0F, 1.0F + (level.random.nextFloat() - level.random.nextFloat()) * 0.4F); ++ this.addEatEffect(food, level, this); ++ if (!(this instanceof net.minecraft.world.entity.player.Player) || !((net.minecraft.world.entity.player.Player) this).getAbilities().instabuild) { ++ food.shrink(1); + } + + this.gameEvent(GameEvent.EAT); + } + +- return itemstack; ++ return food; + } + +- private void addEatEffect(ItemStack itemstack, Level level, LivingEntity livingentity) { +- Item item = itemstack.getItem(); ++ private void addEatEffect(ItemStack food, Level level, LivingEntity livingEntity) { ++ Item item = food.getItem(); + + if (item.isEdible()) { + List> list = item.getFoodProperties().getEffects(); +@@ -3570,15 +4028,15 @@ + Pair pair = (Pair) iterator.next(); + + if (!level.isClientSide && pair.getFirst() != null && level.random.nextFloat() < (Float) pair.getSecond()) { +- livingentity.addEffect(new MobEffectInstance((MobEffectInstance) pair.getFirst())); ++ livingEntity.addEffect(new MobEffectInstance((MobEffectInstance) pair.getFirst()), EntityPotionEffectEvent.Cause.FOOD); // CraftBukkit + } + } + } + + } + +- private static byte entityEventForEquipmentBreak(EquipmentSlot equipmentslot) { +- switch (equipmentslot) { ++ private static byte entityEventForEquipmentBreak(EquipmentSlot slot) { ++ switch (slot) { + case MAINHAND: + return 47; + case OFFHAND: +@@ -3596,16 +4054,15 @@ + } + } + +- public void broadcastBreakEvent(EquipmentSlot equipmentslot) { +- this.level().broadcastEntityEvent(this, entityEventForEquipmentBreak(equipmentslot)); ++ public void broadcastBreakEvent(EquipmentSlot slot) { ++ this.level().broadcastEntityEvent(this, entityEventForEquipmentBreak(slot)); + } + +- public void broadcastBreakEvent(InteractionHand interactionhand) { +- this.broadcastBreakEvent(interactionhand == InteractionHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND); ++ public void broadcastBreakEvent(EnumHand hand) { ++ this.broadcastBreakEvent(hand == EnumHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND); + } + + @Override +- @Override + public AABB getBoundingBoxForCulling() { + if (this.getItemBySlot(EquipmentSlot.HEAD).is(Items.DRAGON_HEAD)) { + float f = 0.5F; +@@ -3616,33 +4073,31 @@ + } + } + +- public static EquipmentSlot getEquipmentSlotForItem(ItemStack itemstack) { +- Equipable equipable = Equipable.get(itemstack); ++ public static EquipmentSlot getEquipmentSlotForItem(ItemStack item) { ++ Equipable equipable = Equipable.get(item); + + return equipable != null ? equipable.getEquipmentSlot() : EquipmentSlot.MAINHAND; + } + +- private static SlotAccess createEquipmentSlotAccess(LivingEntity livingentity, EquipmentSlot equipmentslot) { +- return equipmentslot != EquipmentSlot.HEAD && equipmentslot != EquipmentSlot.MAINHAND && equipmentslot != EquipmentSlot.OFFHAND ? SlotAccess.forEquipmentSlot(livingentity, equipmentslot, (itemstack) -> { +- return itemstack.isEmpty() || Mob.getEquipmentSlotForItem(itemstack) == equipmentslot; +- }) : SlotAccess.forEquipmentSlot(livingentity, equipmentslot); ++ private static SlotAccess createEquipmentSlotAccess(LivingEntity entity, EquipmentSlot slot) { ++ return slot != EquipmentSlot.HEAD && slot != EquipmentSlot.MAINHAND && slot != EquipmentSlot.OFFHAND ? SlotAccess.forEquipmentSlot(entity, slot, (itemstack) -> { ++ return itemstack.isEmpty() || Mob.getEquipmentSlotForItem(itemstack) == slot; ++ }) : SlotAccess.forEquipmentSlot(entity, slot); + } + + @Nullable +- private static EquipmentSlot getEquipmentSlot(int i) { +- return i == 100 + EquipmentSlot.HEAD.getIndex() ? EquipmentSlot.HEAD : (i == 100 + EquipmentSlot.CHEST.getIndex() ? EquipmentSlot.CHEST : (i == 100 + EquipmentSlot.LEGS.getIndex() ? EquipmentSlot.LEGS : (i == 100 + EquipmentSlot.FEET.getIndex() ? EquipmentSlot.FEET : (i == 98 ? EquipmentSlot.MAINHAND : (i == 99 ? EquipmentSlot.OFFHAND : null))))); ++ private static EquipmentSlot getEquipmentSlot(int index) { ++ return index == 100 + EquipmentSlot.HEAD.getIndex() ? EquipmentSlot.HEAD : (index == 100 + EquipmentSlot.CHEST.getIndex() ? EquipmentSlot.CHEST : (index == 100 + EquipmentSlot.LEGS.getIndex() ? EquipmentSlot.LEGS : (index == 100 + EquipmentSlot.FEET.getIndex() ? EquipmentSlot.FEET : (index == 98 ? EquipmentSlot.MAINHAND : (index == 99 ? EquipmentSlot.OFFHAND : null))))); + } + + @Override +- @Override +- public SlotAccess getSlot(int i) { +- EquipmentSlot equipmentslot = getEquipmentSlot(i); ++ public SlotAccess getSlot(int slot) { ++ EquipmentSlot enumitemslot = getEquipmentSlot(slot); + +- return equipmentslot != null ? createEquipmentSlotAccess(this, equipmentslot) : super.getSlot(i); ++ return enumitemslot != null ? createEquipmentSlotAccess(this, enumitemslot) : super.getSlot(slot); + } + + @Override +- @Override + public boolean canFreeze() { + if (this.isSpectator()) { + return false; +@@ -3654,35 +4109,32 @@ + } + + @Override +- @Override + public boolean isCurrentlyGlowing() { + return !this.level().isClientSide() && this.hasEffect(MobEffects.GLOWING) || super.isCurrentlyGlowing(); + } + + @Override +- @Override + public float getVisualRotationYInDegrees() { + return this.yBodyRot; + } + + @Override +- @Override +- public void recreateFromPacket(ClientboundAddEntityPacket clientboundaddentitypacket) { +- double d0 = clientboundaddentitypacket.getX(); +- double d1 = clientboundaddentitypacket.getY(); +- double d2 = clientboundaddentitypacket.getZ(); +- float f = clientboundaddentitypacket.getYRot(); +- float f1 = clientboundaddentitypacket.getXRot(); ++ public void recreateFromPacket(ClientboundAddEntityPacket packet) { ++ double d0 = packet.getX(); ++ double d1 = packet.getY(); ++ double d2 = packet.getZ(); ++ float f = packet.getYRot(); ++ float f1 = packet.getXRot(); + + this.syncPacketPositionCodec(d0, d1, d2); +- this.yBodyRot = clientboundaddentitypacket.getYHeadRot(); +- this.yHeadRot = clientboundaddentitypacket.getYHeadRot(); ++ this.yBodyRot = packet.getYHeadRot(); ++ this.yHeadRot = packet.getYHeadRot(); + this.yBodyRotO = this.yBodyRot; + this.yHeadRotO = this.yHeadRot; +- this.setId(clientboundaddentitypacket.getId()); +- this.setUUID(clientboundaddentitypacket.getUUID()); ++ this.setId(packet.getId()); ++ this.setUUID(packet.getUUID()); + this.absMoveTo(d0, d1, d2, f, f1); +- this.setDeltaMovement(clientboundaddentitypacket.getXa(), clientboundaddentitypacket.getYa(), clientboundaddentitypacket.getZa()); ++ this.setDeltaMovement(packet.getXa(), packet.getYa(), packet.getZa()); + } + + public boolean canDisableShield() { +@@ -3690,21 +4142,18 @@ + } + + @Override +- @Override + public float maxUpStep() { + float f = super.maxUpStep(); + +- return this.getControllingPassenger() instanceof Player ? Math.max(f, 1.0F) : f; ++ return this.getControllingPassenger() instanceof net.minecraft.world.entity.player.Player ? Math.max(f, 1.0F) : f; + } + + @Override +- @Override + public Vec3 getPassengerRidingPosition(Entity entity) { + return (new Vec3(this.getPassengerAttachmentPoint(entity, this.getDimensions(this.getPose()), this.getScale()).rotateY(-this.yBodyRot * 0.017453292F))).add(this.position()); + } + + @Override +- @Override + public float getMyRidingOffset(Entity entity) { + return this.ridingOffset(entity) * this.getScale(); + } +@@ -3713,7 +4162,7 @@ + this.yHeadRot = (float) Mth.rotLerp(1.0D / (double) i, (double) this.yHeadRot, d0); + } + +- public static record Fallsounds(SoundEvent small, SoundEvent big) { ++ public static record a(SoundEvent small, SoundEvent big) { + + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/Mob.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/Mob.java.patch new file mode 100644 index 0000000000..2ec43eca63 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/Mob.java.patch @@ -0,0 +1,1787 @@ +--- a/net/minecraft/world/entity/Mob.java ++++ b/net/minecraft/world/entity/Mob.java +@@ -25,13 +25,14 @@ + import net.minecraft.network.syncher.SynchedEntityData; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.tags.TagKey; + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.world.Difficulty; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; +@@ -49,7 +50,7 @@ + import net.minecraft.world.entity.decoration.HangingEntity; + import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; + import net.minecraft.world.entity.item.ItemEntity; +-import net.minecraft.world.entity.monster.Enemy; ++import net.minecraft.world.entity.monster.IMonster; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.vehicle.Boat; + import net.minecraft.world.item.ArmorItem; +@@ -66,7 +67,7 @@ + import net.minecraft.world.item.SwordItem; + import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.level.GameRules; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; +@@ -75,6 +76,16 @@ + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.AABB; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++import org.bukkit.event.entity.EntityUnleashEvent; ++import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; ++// CraftBukkit end + + public abstract class Mob extends LivingEntity implements Targeting { + +@@ -100,21 +111,21 @@ + protected JumpControl jumpControl; + private final BodyRotationControl bodyRotationControl; + protected PathNavigation navigation; +- protected final GoalSelector goalSelector; +- protected final GoalSelector targetSelector; ++ public GoalSelector goalSelector; ++ public GoalSelector targetSelector; + @Nullable + private LivingEntity target; + private final Sensing sensing; + private final NonNullList handItems; +- protected final float[] handDropChances; ++ public final float[] handDropChances; + private final NonNullList armorItems; +- protected final float[] armorDropChances; ++ public final float[] armorDropChances; + private boolean canPickUpLoot; + private boolean persistenceRequired; + private final Map pathfindingMalus; + @Nullable +- private ResourceLocation lootTable; +- private long lootTableSeed; ++ public ResourceLocation lootTable; ++ public long lootTableSeed; + @Nullable + private Entity leashHolder; + private int delayedLeashHolderId; +@@ -123,8 +134,10 @@ + private BlockPos restrictCenter; + private float restrictRadius; + +- protected Mob(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public boolean aware = true; // CraftBukkit ++ ++ protected Mob(EntityType entityType, Level level) { ++ super(entityType, level); + this.handItems = NonNullList.withSize(2, ItemStack.EMPTY); + this.handDropChances = new float[2]; + this.armorItems = NonNullList.withSize(4, ItemStack.EMPTY); +@@ -148,6 +161,12 @@ + + } + ++ // CraftBukkit start ++ public void setPersistenceRequired(boolean persistenceRequired) { ++ this.persistenceRequired = persistenceRequired; ++ } ++ // CraftBukkit end ++ + protected void registerGoals() {} + + public static AttributeSupplier.Builder createMobAttributes() { +@@ -162,31 +181,31 @@ + return false; + } + +- public float getPathfindingMalus(BlockPathTypes blockpathtypes) { +- Mob mob; ++ public float getPathfindingMalus(BlockPathTypes nodeType) { ++ Mob entityinsentient; + label17: + { + Entity entity = this.getControlledVehicle(); + + if (entity instanceof Mob) { +- Mob mob1 = (Mob) entity; ++ Mob entityinsentient1 = (Mob) entity; + +- if (mob1.shouldPassengersInheritMalus()) { +- mob = mob1; ++ if (entityinsentient1.shouldPassengersInheritMalus()) { ++ entityinsentient = entityinsentient1; + break label17; + } + } + +- mob = this; ++ entityinsentient = this; + } + +- Float ofloat = (Float) mob.pathfindingMalus.get(blockpathtypes); ++ Float ofloat = (Float) entityinsentient.pathfindingMalus.get(nodeType); + +- return ofloat == null ? blockpathtypes.getMalus() : ofloat; ++ return ofloat == null ? nodeType.getMalus() : ofloat; + } + +- public void setPathfindingMalus(BlockPathTypes blockpathtypes, float f) { +- this.pathfindingMalus.put(blockpathtypes, f); ++ public void setPathfindingMalus(BlockPathTypes nodeType, float malus) { ++ this.pathfindingMalus.put(nodeType, malus); + } + + public void onPathfindingStart() {} +@@ -205,9 +224,9 @@ + Entity entity = this.getControlledVehicle(); + + if (entity instanceof Mob) { +- Mob mob = (Mob) entity; ++ Mob entityinsentient = (Mob) entity; + +- return mob.getMoveControl(); ++ return entityinsentient.getMoveControl(); + } else { + return this.moveControl; + } +@@ -221,9 +240,9 @@ + Entity entity = this.getControlledVehicle(); + + if (entity instanceof Mob) { +- Mob mob = (Mob) entity; ++ Mob entityinsentient = (Mob) entity; + +- return mob.getNavigation(); ++ return entityinsentient.getNavigation(); + } else { + return this.navigation; + } +@@ -231,22 +250,21 @@ + + @Nullable + @Override +- @Override + public LivingEntity getControllingPassenger() { + Entity entity = this.getFirstPassenger(); +- Mob mob; ++ Mob entityinsentient; + + if (!this.isNoAi() && entity instanceof Mob) { +- Mob mob1 = (Mob) entity; ++ Mob entityinsentient1 = (Mob) entity; + + if (entity.canControlVehicle()) { +- mob = mob1; +- return mob; ++ entityinsentient = entityinsentient1; ++ return entityinsentient; + } + } + +- mob = null; +- return mob; ++ entityinsentient = null; ++ return entityinsentient; + } + + public Sensing getSensing() { +@@ -255,22 +273,51 @@ + + @Nullable + @Override +- @Override + public LivingEntity getTarget() { + return this.target; + } + +- public void setTarget(@Nullable LivingEntity livingentity) { +- this.target = livingentity; ++ public void setTarget(@Nullable LivingEntity target) { ++ // CraftBukkit start - fire event ++ setTarget(target, EntityTargetEvent.TargetReason.UNKNOWN, true); + } + ++ public boolean setTarget(LivingEntity entityliving, EntityTargetEvent.TargetReason reason, boolean fireEvent) { ++ if (getTarget() == entityliving) return false; ++ if (fireEvent) { ++ if (reason == EntityTargetEvent.TargetReason.UNKNOWN && getTarget() != null && entityliving == null) { ++ reason = getTarget().isAlive() ? EntityTargetEvent.TargetReason.FORGOT_TARGET : EntityTargetEvent.TargetReason.TARGET_DIED; ++ } ++ if (reason == EntityTargetEvent.TargetReason.UNKNOWN) { ++ this.level().getCraftServer().getLogger().log(java.util.logging.Level.WARNING, "Unknown target reason, please report on the issue tracker", new Exception()); ++ } ++ CraftLivingEntity ctarget = null; ++ if (entityliving != null) { ++ ctarget = (CraftLivingEntity) entityliving.getBukkitEntity(); ++ } ++ EntityTargetLivingEntityEvent event = new EntityTargetLivingEntityEvent(this.getBukkitEntity(), ctarget, reason); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ if (event.getTarget() != null) { ++ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ } else { ++ entityliving = null; ++ } ++ } ++ this.target = entityliving; ++ return true; ++ // CraftBukkit end ++ } ++ + @Override +- @Override +- public boolean canAttackType(EntityType entitytype) { +- return entitytype != EntityType.GHAST; ++ public boolean canAttackType(EntityType type) { ++ return type != EntityType.GHAST; + } + +- public boolean canFireProjectileWeapon(ProjectileWeaponItem projectileweaponitem) { ++ public boolean canFireProjectileWeapon(ProjectileWeaponItem projectileWeapon) { + return false; + } + +@@ -279,7 +326,6 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Mob.DATA_MOB_FLAGS_ID, (byte) 0); +@@ -290,16 +336,15 @@ + } + + public void playAmbientSound() { +- SoundEvent soundevent = this.getAmbientSound(); ++ SoundEvent soundeffect = this.getAmbientSound(); + +- if (soundevent != null) { +- this.playSound(soundevent, this.getSoundVolume(), this.getVoicePitch()); ++ if (soundeffect != null) { ++ this.playSound(soundeffect, this.getSoundVolume(), this.getVoicePitch()); + } + + } + + @Override +- @Override + public void baseTick() { + super.baseTick(); + this.level().getProfiler().push("mobBaseTick"); +@@ -312,10 +357,9 @@ + } + + @Override +- @Override +- protected void playHurtSound(DamageSource damagesource) { ++ protected void playHurtSound(DamageSource source) { + this.resetAmbientSoundTime(); +- super.playHurtSound(damagesource); ++ super.playHurtSound(source); + } + + private void resetAmbientSoundTime() { +@@ -323,7 +367,6 @@ + } + + @Override +- @Override + public int getExperienceReward() { + if (this.xpReward > 0) { + int i = this.xpReward; +@@ -365,18 +408,16 @@ + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 20) { ++ public void handleEntityEvent(byte id) { ++ if (id == 20) { + this.spawnAnim(); + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } + + @Override +- @Override + public void tick() { + super.tick(); + if (!this.level().isClientSide) { +@@ -392,16 +433,15 @@ + boolean flag = !(this.getControllingPassenger() instanceof Mob); + boolean flag1 = !(this.getVehicle() instanceof Boat); + +- this.goalSelector.setControlFlag(Goal.Flag.MOVE, flag); +- this.goalSelector.setControlFlag(Goal.Flag.JUMP, flag && flag1); +- this.goalSelector.setControlFlag(Goal.Flag.LOOK, flag); ++ this.goalSelector.setControlFlag(Goal.Type.MOVE, flag); ++ this.goalSelector.setControlFlag(Goal.Type.JUMP, flag && flag1); ++ this.goalSelector.setControlFlag(Goal.Type.LOOK, flag); + } + + @Override +- @Override +- protected float tickHeadTurn(float f, float f1) { ++ protected float tickHeadTurn(float yRot, float animStep) { + this.bodyRotationControl.clientTick(); +- return f1; ++ return animStep; + } + + @Nullable +@@ -409,41 +449,46 @@ + return null; + } + ++ // CraftBukkit start - Add delegate method ++ public SoundEvent getAmbientSound0() { ++ return getAmbientSound(); ++ } ++ // CraftBukkit end ++ + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putBoolean("CanPickUpLoot", this.canPickUpLoot()); +- compoundtag.putBoolean("PersistenceRequired", this.persistenceRequired); +- ListTag listtag = new ListTag(); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putBoolean("CanPickUpLoot", this.canPickUpLoot()); ++ compound.putBoolean("PersistenceRequired", this.persistenceRequired); ++ ListTag nbttaglist = new ListTag(); + +- CompoundTag compoundtag1; ++ CompoundTag nbttagcompound1; + +- for (Iterator iterator = this.armorItems.iterator(); iterator.hasNext(); listtag.add(compoundtag1)) { ++ for (Iterator iterator = this.armorItems.iterator(); iterator.hasNext(); nbttaglist.add(nbttagcompound1)) { + ItemStack itemstack = (ItemStack) iterator.next(); + +- compoundtag1 = new CompoundTag(); ++ nbttagcompound1 = new CompoundTag(); + if (!itemstack.isEmpty()) { +- itemstack.save(compoundtag1); ++ itemstack.save(nbttagcompound1); + } + } + +- compoundtag.put("ArmorItems", listtag); +- ListTag listtag1 = new ListTag(); ++ compound.put("ArmorItems", nbttaglist); ++ ListTag nbttaglist1 = new ListTag(); + +- CompoundTag compoundtag2; ++ CompoundTag nbttagcompound2; + +- for (Iterator iterator1 = this.handItems.iterator(); iterator1.hasNext(); listtag1.add(compoundtag2)) { ++ for (Iterator iterator1 = this.handItems.iterator(); iterator1.hasNext(); nbttaglist1.add(nbttagcompound2)) { + ItemStack itemstack1 = (ItemStack) iterator1.next(); + +- compoundtag2 = new CompoundTag(); ++ nbttagcompound2 = new CompoundTag(); + if (!itemstack1.isEmpty()) { +- itemstack1.save(compoundtag2); ++ itemstack1.save(nbttagcompound2); + } + } + +- compoundtag.put("HandItems", listtag1); +- ListTag listtag2 = new ListTag(); ++ compound.put("HandItems", nbttaglist1); ++ ListTag nbttaglist2 = new ListTag(); + float[] afloat = this.armorDropChances; + int i = afloat.length; + +@@ -452,11 +497,11 @@ + for (j = 0; j < i; ++j) { + float f = afloat[j]; + +- listtag2.add(FloatTag.valueOf(f)); ++ nbttaglist2.add(FloatTag.valueOf(f)); + } + +- compoundtag.put("ArmorDropChances", listtag2); +- ListTag listtag3 = new ListTag(); ++ compound.put("ArmorDropChances", nbttaglist2); ++ ListTag nbttaglist3 = new ListTag(); + float[] afloat1 = this.handDropChances; + + j = afloat1.length; +@@ -464,157 +509,166 @@ + for (int k = 0; k < j; ++k) { + float f1 = afloat1[k]; + +- listtag3.add(FloatTag.valueOf(f1)); ++ nbttaglist3.add(FloatTag.valueOf(f1)); + } + +- compoundtag.put("HandDropChances", listtag3); +- if (this.leashHolder != null) { +- compoundtag2 = new CompoundTag(); ++ compound.put("HandDropChances", nbttaglist3); ++ if (this.leashHolder != null && !this.leashHolder.pluginRemoved) { // CraftBukkit - SPIGOT-7487: Don't save (and possible drop) leash, when the holder was removed by a plugin ++ nbttagcompound2 = new CompoundTag(); + if (this.leashHolder instanceof LivingEntity) { + UUID uuid = this.leashHolder.getUUID(); + +- compoundtag2.putUUID("UUID", uuid); ++ nbttagcompound2.putUUID("UUID", uuid); + } else if (this.leashHolder instanceof HangingEntity) { +- BlockPos blockpos = ((HangingEntity) this.leashHolder).getPos(); ++ BlockPos blockposition = ((HangingEntity) this.leashHolder).getPos(); + +- compoundtag2.putInt("X", blockpos.getX()); +- compoundtag2.putInt("Y", blockpos.getY()); +- compoundtag2.putInt("Z", blockpos.getZ()); ++ nbttagcompound2.putInt("X", blockposition.getX()); ++ nbttagcompound2.putInt("Y", blockposition.getY()); ++ nbttagcompound2.putInt("Z", blockposition.getZ()); + } + +- compoundtag.put("Leash", compoundtag2); ++ compound.put("Leash", nbttagcompound2); + } else if (this.leashInfoTag != null) { +- compoundtag.put("Leash", this.leashInfoTag.copy()); ++ compound.put("Leash", this.leashInfoTag.copy()); + } + +- compoundtag.putBoolean("LeftHanded", this.isLeftHanded()); ++ compound.putBoolean("LeftHanded", this.isLeftHanded()); + if (this.lootTable != null) { +- compoundtag.putString("DeathLootTable", this.lootTable.toString()); ++ compound.putString("DeathLootTable", this.lootTable.toString()); + if (this.lootTableSeed != 0L) { +- compoundtag.putLong("DeathLootTableSeed", this.lootTableSeed); ++ compound.putLong("DeathLootTableSeed", this.lootTableSeed); + } + } + + if (this.isNoAi()) { +- compoundtag.putBoolean("NoAI", this.isNoAi()); ++ compound.putBoolean("NoAI", this.isNoAi()); + } + ++ compound.putBoolean("Bukkit.Aware", this.aware); // CraftBukkit + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("CanPickUpLoot", 1)) { +- this.setCanPickUpLoot(compoundtag.getBoolean("CanPickUpLoot")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ ++ // CraftBukkit start - If looting or persistence is false only use it if it was set after we started using it ++ if (compound.contains("CanPickUpLoot", 1)) { ++ boolean data = compound.getBoolean("CanPickUpLoot"); ++ if (isLevelAtLeast(compound, 1) || data) { ++ this.setCanPickUpLoot(data); ++ } + } + +- this.persistenceRequired = compoundtag.getBoolean("PersistenceRequired"); +- ListTag listtag; ++ boolean data = compound.getBoolean("PersistenceRequired"); ++ if (isLevelAtLeast(compound, 1) || data) { ++ this.persistenceRequired = data; ++ } ++ // CraftBukkit end ++ ListTag nbttaglist; + int i; + +- if (compoundtag.contains("ArmorItems", 9)) { +- listtag = compoundtag.getList("ArmorItems", 10); ++ if (compound.contains("ArmorItems", 9)) { ++ nbttaglist = compound.getList("ArmorItems", 10); + + for (i = 0; i < this.armorItems.size(); ++i) { +- this.armorItems.set(i, ItemStack.of(listtag.getCompound(i))); ++ this.armorItems.set(i, ItemStack.of(nbttaglist.getCompound(i))); + } + } + +- if (compoundtag.contains("HandItems", 9)) { +- listtag = compoundtag.getList("HandItems", 10); ++ if (compound.contains("HandItems", 9)) { ++ nbttaglist = compound.getList("HandItems", 10); + + for (i = 0; i < this.handItems.size(); ++i) { +- this.handItems.set(i, ItemStack.of(listtag.getCompound(i))); ++ this.handItems.set(i, ItemStack.of(nbttaglist.getCompound(i))); + } + } + +- if (compoundtag.contains("ArmorDropChances", 9)) { +- listtag = compoundtag.getList("ArmorDropChances", 5); ++ if (compound.contains("ArmorDropChances", 9)) { ++ nbttaglist = compound.getList("ArmorDropChances", 5); + +- for (i = 0; i < listtag.size(); ++i) { +- this.armorDropChances[i] = listtag.getFloat(i); ++ for (i = 0; i < nbttaglist.size(); ++i) { ++ this.armorDropChances[i] = nbttaglist.getFloat(i); + } + } + +- if (compoundtag.contains("HandDropChances", 9)) { +- listtag = compoundtag.getList("HandDropChances", 5); ++ if (compound.contains("HandDropChances", 9)) { ++ nbttaglist = compound.getList("HandDropChances", 5); + +- for (i = 0; i < listtag.size(); ++i) { +- this.handDropChances[i] = listtag.getFloat(i); ++ for (i = 0; i < nbttaglist.size(); ++i) { ++ this.handDropChances[i] = nbttaglist.getFloat(i); + } + } + +- if (compoundtag.contains("Leash", 10)) { +- this.leashInfoTag = compoundtag.getCompound("Leash"); ++ if (compound.contains("Leash", 10)) { ++ this.leashInfoTag = compound.getCompound("Leash"); + } + +- this.setLeftHanded(compoundtag.getBoolean("LeftHanded")); +- if (compoundtag.contains("DeathLootTable", 8)) { +- this.lootTable = new ResourceLocation(compoundtag.getString("DeathLootTable")); +- this.lootTableSeed = compoundtag.getLong("DeathLootTableSeed"); ++ this.setLeftHanded(compound.getBoolean("LeftHanded")); ++ if (compound.contains("DeathLootTable", 8)) { ++ this.lootTable = new ResourceLocation(compound.getString("DeathLootTable")); ++ this.lootTableSeed = compound.getLong("DeathLootTableSeed"); + } + +- this.setNoAi(compoundtag.getBoolean("NoAI")); ++ this.setNoAi(compound.getBoolean("NoAI")); ++ // CraftBukkit start ++ if (compound.contains("Bukkit.Aware")) { ++ this.aware = compound.getBoolean("Bukkit.Aware"); ++ } ++ // CraftBukkit end + } + + @Override +- @Override +- protected void dropFromLootTable(DamageSource damagesource, boolean flag) { +- super.dropFromLootTable(damagesource, flag); ++ protected void dropFromLootTable(DamageSource damageSource, boolean attackedRecently) { ++ super.dropFromLootTable(damageSource, attackedRecently); + this.lootTable = null; + } + + @Override +- @Override + public final ResourceLocation getLootTable() { + return this.lootTable == null ? this.getDefaultLootTable() : this.lootTable; + } + +- protected ResourceLocation getDefaultLootTable() { ++ public ResourceLocation getDefaultLootTable() { + return super.getLootTable(); + } + + @Override +- @Override + public long getLootTableSeed() { + return this.lootTableSeed; + } + +- public void setZza(float f) { +- this.zza = f; ++ public void setZza(float amount) { ++ this.zza = amount; + } + +- public void setYya(float f) { +- this.yya = f; ++ public void setYya(float amount) { ++ this.yya = amount; + } + +- public void setXxa(float f) { +- this.xxa = f; ++ public void setXxa(float amount) { ++ this.xxa = amount; + } + + @Override +- @Override +- public void setSpeed(float f) { +- super.setSpeed(f); +- this.setZza(f); ++ public void setSpeed(float speed) { ++ super.setSpeed(speed); ++ this.setZza(speed); + } + + @Override +- @Override + public void aiStep() { + super.aiStep(); + this.level().getProfiler().push("looting"); + if (!this.level().isClientSide && this.canPickUpLoot() && this.isAlive() && !this.dead && this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- Vec3i vec3i = this.getPickupReach(); +- List list = this.level().getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate((double) vec3i.getX(), (double) vec3i.getY(), (double) vec3i.getZ())); ++ Vec3i baseblockposition = this.getPickupReach(); ++ List list = this.level().getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate((double) baseblockposition.getX(), (double) baseblockposition.getY(), (double) baseblockposition.getZ())); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- ItemEntity itementity = (ItemEntity) iterator.next(); ++ ItemEntity entityitem = (ItemEntity) iterator.next(); + +- if (!itementity.isRemoved() && !itementity.getItem().isEmpty() && !itementity.hasPickUpDelay() && this.wantsToPickUp(itementity.getItem())) { +- this.pickUpItem(itementity); ++ if (!entityitem.isRemoved() && !entityitem.getItem().isEmpty() && !entityitem.hasPickUpDelay() && this.wantsToPickUp(entityitem.getItem())) { ++ this.pickUpItem(entityitem); + } + } + } +@@ -626,46 +680,60 @@ + return Mob.ITEM_PICKUP_REACH; + } + +- protected void pickUpItem(ItemEntity itementity) { +- ItemStack itemstack = itementity.getItem(); +- ItemStack itemstack1 = this.equipItemIfPossible(itemstack.copy()); ++ protected void pickUpItem(ItemEntity itemEntity) { ++ ItemStack itemstack = itemEntity.getItem(); ++ ItemStack itemstack1 = this.equipItemIfPossible(itemstack.copy(), itemEntity); // CraftBukkit - add item + + if (!itemstack1.isEmpty()) { +- this.onItemPickup(itementity); +- this.take(itementity, itemstack1.getCount()); ++ this.onItemPickup(itemEntity); ++ this.take(itemEntity, itemstack1.getCount()); + itemstack.shrink(itemstack1.getCount()); + if (itemstack.isEmpty()) { +- itementity.discard(); ++ itemEntity.discard(); + } + } + + } + +- public ItemStack equipItemIfPossible(ItemStack itemstack) { +- EquipmentSlot equipmentslot = getEquipmentSlotForItem(itemstack); +- ItemStack itemstack1 = this.getItemBySlot(equipmentslot); ++ public ItemStack equipItemIfPossible(ItemStack stack) { ++ // CraftBukkit start - add item ++ return this.equipItemIfPossible(stack, null); ++ } ++ ++ public ItemStack equipItemIfPossible(ItemStack itemstack, ItemEntity entityitem) { ++ // CraftBukkit end ++ EquipmentSlot enumitemslot = getEquipmentSlotForItem(itemstack); ++ ItemStack itemstack1 = this.getItemBySlot(enumitemslot); + boolean flag = this.canReplaceCurrentItem(itemstack, itemstack1); + +- if (equipmentslot.isArmor() && !flag) { +- equipmentslot = EquipmentSlot.MAINHAND; +- itemstack1 = this.getItemBySlot(equipmentslot); ++ if (enumitemslot.isArmor() && !flag) { ++ enumitemslot = EquipmentSlot.MAINHAND; ++ itemstack1 = this.getItemBySlot(enumitemslot); + flag = itemstack1.isEmpty(); + } + +- if (flag && this.canHoldItem(itemstack)) { +- double d0 = (double) this.getEquipmentDropChance(equipmentslot); ++ // CraftBukkit start ++ boolean canPickup = flag && this.canHoldItem(itemstack); ++ if (entityitem != null) { ++ canPickup = !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, entityitem, 0, !canPickup).isCancelled(); ++ } ++ if (canPickup) { ++ // CraftBukkit end ++ double d0 = (double) this.getEquipmentDropChance(enumitemslot); + + if (!itemstack1.isEmpty() && (double) Math.max(this.random.nextFloat() - 0.1F, 0.0F) < d0) { ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation(itemstack1); ++ this.forceDrops = false; // CraftBukkit + } + +- if (equipmentslot.isArmor() && itemstack.getCount() > 1) { ++ if (enumitemslot.isArmor() && itemstack.getCount() > 1) { + ItemStack itemstack2 = itemstack.copyWithCount(1); + +- this.setItemSlotAndDropWhenKilled(equipmentslot, itemstack2); ++ this.setItemSlotAndDropWhenKilled(enumitemslot, itemstack2); + return itemstack2; + } else { +- this.setItemSlotAndDropWhenKilled(equipmentslot, itemstack); ++ this.setItemSlotAndDropWhenKilled(enumitemslot, itemstack); + return itemstack; + } + } else { +@@ -673,71 +741,71 @@ + } + } + +- protected void setItemSlotAndDropWhenKilled(EquipmentSlot equipmentslot, ItemStack itemstack) { +- this.setItemSlot(equipmentslot, itemstack); +- this.setGuaranteedDrop(equipmentslot); ++ protected void setItemSlotAndDropWhenKilled(EquipmentSlot slot, ItemStack stack) { ++ this.setItemSlot(slot, stack); ++ this.setGuaranteedDrop(slot); + this.persistenceRequired = true; + } + +- public void setGuaranteedDrop(EquipmentSlot equipmentslot) { +- switch (equipmentslot.getType()) { ++ public void setGuaranteedDrop(EquipmentSlot slot) { ++ switch (slot.getType()) { + case HAND: +- this.handDropChances[equipmentslot.getIndex()] = 2.0F; ++ this.handDropChances[slot.getIndex()] = 2.0F; + break; + case ARMOR: +- this.armorDropChances[equipmentslot.getIndex()] = 2.0F; ++ this.armorDropChances[slot.getIndex()] = 2.0F; + } + + } + +- protected boolean canReplaceCurrentItem(ItemStack itemstack, ItemStack itemstack1) { +- if (itemstack1.isEmpty()) { ++ protected boolean canReplaceCurrentItem(ItemStack candidate, ItemStack existing) { ++ if (existing.isEmpty()) { + return true; +- } else if (itemstack.getItem() instanceof SwordItem) { +- if (!(itemstack1.getItem() instanceof SwordItem)) { ++ } else if (candidate.getItem() instanceof SwordItem) { ++ if (!(existing.getItem() instanceof SwordItem)) { + return true; + } else { +- SwordItem sworditem = (SwordItem) itemstack.getItem(); +- SwordItem sworditem1 = (SwordItem) itemstack1.getItem(); ++ SwordItem itemsword = (SwordItem) candidate.getItem(); ++ SwordItem itemsword1 = (SwordItem) existing.getItem(); + +- return sworditem.getDamage() != sworditem1.getDamage() ? sworditem.getDamage() > sworditem1.getDamage() : this.canReplaceEqualItem(itemstack, itemstack1); ++ return itemsword.getDamage() != itemsword1.getDamage() ? itemsword.getDamage() > itemsword1.getDamage() : this.canReplaceEqualItem(candidate, existing); + } +- } else if (itemstack.getItem() instanceof BowItem && itemstack1.getItem() instanceof BowItem) { +- return this.canReplaceEqualItem(itemstack, itemstack1); +- } else if (itemstack.getItem() instanceof CrossbowItem && itemstack1.getItem() instanceof CrossbowItem) { +- return this.canReplaceEqualItem(itemstack, itemstack1); ++ } else if (candidate.getItem() instanceof BowItem && existing.getItem() instanceof BowItem) { ++ return this.canReplaceEqualItem(candidate, existing); ++ } else if (candidate.getItem() instanceof CrossbowItem && existing.getItem() instanceof CrossbowItem) { ++ return this.canReplaceEqualItem(candidate, existing); + } else { +- Item item = itemstack.getItem(); ++ Item item = candidate.getItem(); + + if (item instanceof ArmorItem) { +- ArmorItem armoritem = (ArmorItem) item; ++ ArmorItem itemarmor = (ArmorItem) item; + +- if (EnchantmentHelper.hasBindingCurse(itemstack1)) { ++ if (EnchantmentHelper.hasBindingCurse(existing)) { + return false; +- } else if (!(itemstack1.getItem() instanceof ArmorItem)) { ++ } else if (!(existing.getItem() instanceof ArmorItem)) { + return true; + } else { +- ArmorItem armoritem1 = (ArmorItem) itemstack1.getItem(); ++ ArmorItem itemarmor1 = (ArmorItem) existing.getItem(); + +- return armoritem.getDefense() != armoritem1.getDefense() ? armoritem.getDefense() > armoritem1.getDefense() : (armoritem.getToughness() != armoritem1.getToughness() ? armoritem.getToughness() > armoritem1.getToughness() : this.canReplaceEqualItem(itemstack, itemstack1)); ++ return itemarmor.getDefense() != itemarmor1.getDefense() ? itemarmor.getDefense() > itemarmor1.getDefense() : (itemarmor.getToughness() != itemarmor1.getToughness() ? itemarmor.getToughness() > itemarmor1.getToughness() : this.canReplaceEqualItem(candidate, existing)); + } + } else { +- if (itemstack.getItem() instanceof DiggerItem) { +- if (itemstack1.getItem() instanceof BlockItem) { ++ if (candidate.getItem() instanceof DiggerItem) { ++ if (existing.getItem() instanceof BlockItem) { + return true; + } + +- Item item1 = itemstack1.getItem(); ++ Item item1 = existing.getItem(); + + if (item1 instanceof DiggerItem) { +- DiggerItem diggeritem = (DiggerItem) item1; +- DiggerItem diggeritem1 = (DiggerItem) itemstack.getItem(); ++ DiggerItem itemtool = (DiggerItem) item1; ++ DiggerItem itemtool1 = (DiggerItem) candidate.getItem(); + +- if (diggeritem1.getAttackDamage() != diggeritem.getAttackDamage()) { +- return diggeritem1.getAttackDamage() > diggeritem.getAttackDamage(); ++ if (itemtool1.getAttackDamage() != itemtool.getAttackDamage()) { ++ return itemtool1.getAttackDamage() > itemtool.getAttackDamage(); + } + +- return this.canReplaceEqualItem(itemstack, itemstack1); ++ return this.canReplaceEqualItem(candidate, existing); + } + } + +@@ -746,23 +814,23 @@ + } + } + +- public boolean canReplaceEqualItem(ItemStack itemstack, ItemStack itemstack1) { +- return itemstack.getDamageValue() >= itemstack1.getDamageValue() && (!itemstack.hasTag() || itemstack1.hasTag()) ? (itemstack.hasTag() && itemstack1.hasTag() ? itemstack.getTag().getAllKeys().stream().anyMatch((s) -> { ++ public boolean canReplaceEqualItem(ItemStack candidate, ItemStack existing) { ++ return candidate.getDamageValue() >= existing.getDamageValue() && (!candidate.hasTag() || existing.hasTag()) ? (candidate.hasTag() && existing.hasTag() ? candidate.getTag().getAllKeys().stream().anyMatch((s) -> { + return !s.equals("Damage"); +- }) && !itemstack1.getTag().getAllKeys().stream().anyMatch((s) -> { ++ }) && !existing.getTag().getAllKeys().stream().anyMatch((s) -> { + return !s.equals("Damage"); + }) : false) : true; + } + +- public boolean canHoldItem(ItemStack itemstack) { ++ public boolean canHoldItem(ItemStack stack) { + return true; + } + +- public boolean wantsToPickUp(ItemStack itemstack) { +- return this.canHoldItem(itemstack); ++ public boolean wantsToPickUp(ItemStack stack) { ++ return this.canHoldItem(stack); + } + +- public boolean removeWhenFarAway(double d0) { ++ public boolean removeWhenFarAway(double distanceToClosestPlayer) { + return true; + } + +@@ -775,15 +843,14 @@ + } + + @Override +- @Override + public void checkDespawn() { + if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.shouldDespawnInPeaceful()) { + this.discard(); + } else if (!this.isPersistenceRequired() && !this.requiresCustomPersistence()) { +- Player player = this.level().getNearestPlayer(this, -1.0D); ++ Player entityhuman = this.level().getNearestPlayer(this, -1.0D); + +- if (player != null) { +- double d0 = player.distanceToSqr((Entity) this); ++ if (entityhuman != null) { ++ double d0 = entityhuman.distanceToSqr((Entity) this); + int i = this.getType().getCategory().getDespawnDistance(); + int j = i * i; + +@@ -807,9 +874,9 @@ + } + + @Override +- @Override + protected final void serverAiStep() { + ++this.noActionTime; ++ if (!this.aware) return; // CraftBukkit + this.level().getProfiler().push("sensing"); + this.sensing.tick(); + this.level().getProfiler().pop(); +@@ -867,15 +934,15 @@ + return 10; + } + +- public void lookAt(Entity entity, float f, float f1) { ++ public void lookAt(Entity entity, float maxYRotIncrease, float maxXRotIncrease) { + double d0 = entity.getX() - this.getX(); + double d1 = entity.getZ() - this.getZ(); + double d2; + + if (entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; ++ LivingEntity entityliving = (LivingEntity) entity; + +- d2 = livingentity.getEyeY() - this.getEyeY(); ++ d2 = entityliving.getEyeY() - this.getEyeY(); + } else { + d2 = (entity.getBoundingBox().minY + entity.getBoundingBox().maxY) / 2.0D - this.getEyeY(); + } +@@ -884,48 +951,47 @@ + float f2 = (float) (Mth.atan2(d1, d0) * 57.2957763671875D) - 90.0F; + float f3 = (float) (-(Mth.atan2(d2, d3) * 57.2957763671875D)); + +- this.setXRot(this.rotlerp(this.getXRot(), f3, f1)); +- this.setYRot(this.rotlerp(this.getYRot(), f2, f)); ++ this.setXRot(this.rotlerp(this.getXRot(), f3, maxXRotIncrease)); ++ this.setYRot(this.rotlerp(this.getYRot(), f2, maxYRotIncrease)); + } + +- private float rotlerp(float f, float f1, float f2) { +- float f3 = Mth.wrapDegrees(f1 - f); ++ private float rotlerp(float angle, float targetAngle, float maxIncrease) { ++ float f3 = Mth.wrapDegrees(targetAngle - angle); + +- if (f3 > f2) { +- f3 = f2; ++ if (f3 > maxIncrease) { ++ f3 = maxIncrease; + } + +- if (f3 < -f2) { +- f3 = -f2; ++ if (f3 < -maxIncrease) { ++ f3 = -maxIncrease; + } + +- return f + f3; ++ return angle + f3; + } + +- public static boolean checkMobSpawnRules(EntityType entitytype, LevelAccessor levelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- BlockPos blockpos1 = blockpos.below(); ++ public static boolean checkMobSpawnRules(EntityType type, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ BlockPos blockposition1 = pos.below(); + +- return mobspawntype == MobSpawnType.SPAWNER || levelaccessor.getBlockState(blockpos1).isValidSpawn(levelaccessor, blockpos1, entitytype); ++ return spawnType == EnumMobSpawn.SPAWNER || level.getBlockState(blockposition1).isValidSpawn(level, blockposition1, type); + } + +- public boolean checkSpawnRules(LevelAccessor levelaccessor, MobSpawnType mobspawntype) { ++ public boolean checkSpawnRules(LevelAccessor level, EnumMobSpawn reason) { + return true; + } + +- public boolean checkSpawnObstruction(LevelReader levelreader) { +- return !levelreader.containsAnyLiquid(this.getBoundingBox()) && levelreader.isUnobstructed(this); ++ public boolean checkSpawnObstruction(LevelReader level) { ++ return !level.containsAnyLiquid(this.getBoundingBox()) && level.isUnobstructed(this); + } + + public int getMaxSpawnClusterSize() { + return 4; + } + +- public boolean isMaxGroupSizeReached(int i) { ++ public boolean isMaxGroupSizeReached(int size) { + return false; + } + + @Override +- @Override + public int getMaxFallDistance() { + if (this.getTarget() == null) { + return 3; +@@ -942,78 +1008,73 @@ + } + + @Override +- @Override + public Iterable getHandSlots() { + return this.handItems; + } + + @Override +- @Override + public Iterable getArmorSlots() { + return this.armorItems; + } + + @Override +- @Override +- public ItemStack getItemBySlot(EquipmentSlot equipmentslot) { +- switch (equipmentslot.getType()) { ++ public ItemStack getItemBySlot(EquipmentSlot slot) { ++ switch (slot.getType()) { + case HAND: +- return (ItemStack) this.handItems.get(equipmentslot.getIndex()); ++ return (ItemStack) this.handItems.get(slot.getIndex()); + case ARMOR: +- return (ItemStack) this.armorItems.get(equipmentslot.getIndex()); ++ return (ItemStack) this.armorItems.get(slot.getIndex()); + default: + return ItemStack.EMPTY; + } + } + + @Override +- @Override +- public void setItemSlot(EquipmentSlot equipmentslot, ItemStack itemstack) { +- this.verifyEquippedItem(itemstack); +- switch (equipmentslot.getType()) { ++ public void setItemSlot(EquipmentSlot slot, ItemStack stack) { ++ this.verifyEquippedItem(stack); ++ switch (slot.getType()) { + case HAND: +- this.onEquipItem(equipmentslot, (ItemStack) this.handItems.set(equipmentslot.getIndex(), itemstack), itemstack); ++ this.onEquipItem(slot, (ItemStack) this.handItems.set(slot.getIndex(), stack), stack); + break; + case ARMOR: +- this.onEquipItem(equipmentslot, (ItemStack) this.armorItems.set(equipmentslot.getIndex(), itemstack), itemstack); ++ this.onEquipItem(slot, (ItemStack) this.armorItems.set(slot.getIndex(), stack), stack); + } + + } + + @Override +- @Override +- protected void dropCustomDeathLoot(DamageSource damagesource, int i, boolean flag) { +- super.dropCustomDeathLoot(damagesource, i, flag); +- EquipmentSlot[] aequipmentslot = EquipmentSlot.values(); +- int j = aequipmentslot.length; ++ protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { ++ super.dropCustomDeathLoot(source, looting, recentlyHit); ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ int j = aenumitemslot.length; + + for (int k = 0; k < j; ++k) { +- EquipmentSlot equipmentslot = aequipmentslot[k]; +- ItemStack itemstack = this.getItemBySlot(equipmentslot); +- float f = this.getEquipmentDropChance(equipmentslot); ++ EquipmentSlot enumitemslot = aenumitemslot[k]; ++ ItemStack itemstack = this.getItemBySlot(enumitemslot); ++ float f = this.getEquipmentDropChance(enumitemslot); + boolean flag1 = f > 1.0F; + +- if (!itemstack.isEmpty() && !EnchantmentHelper.hasVanishingCurse(itemstack) && (flag || flag1) && Math.max(this.random.nextFloat() - (float) i * 0.01F, 0.0F) < f) { ++ if (!itemstack.isEmpty() && !EnchantmentHelper.hasVanishingCurse(itemstack) && (recentlyHit || flag1) && Math.max(this.random.nextFloat() - (float) looting * 0.01F, 0.0F) < f) { + if (!flag1 && itemstack.isDamageableItem()) { + itemstack.setDamageValue(itemstack.getMaxDamage() - this.random.nextInt(1 + this.random.nextInt(Math.max(itemstack.getMaxDamage() - 3, 1)))); + } + + this.spawnAtLocation(itemstack); +- this.setItemSlot(equipmentslot, ItemStack.EMPTY); ++ this.setItemSlot(enumitemslot, ItemStack.EMPTY); + } + } + + } + +- protected float getEquipmentDropChance(EquipmentSlot equipmentslot) { ++ protected float getEquipmentDropChance(EquipmentSlot slot) { + float f; + +- switch (equipmentslot.getType()) { ++ switch (slot.getType()) { + case HAND: +- f = this.handDropChances[equipmentslot.getIndex()]; ++ f = this.handDropChances[slot.getIndex()]; + break; + case ARMOR: +- f = this.armorDropChances[equipmentslot.getIndex()]; ++ f = this.armorDropChances[slot.getIndex()]; + break; + default: + f = 0.0F; +@@ -1022,43 +1083,43 @@ + return f; + } + +- protected void populateDefaultEquipmentSlots(RandomSource randomsource, DifficultyInstance difficultyinstance) { +- if (randomsource.nextFloat() < 0.15F * difficultyinstance.getSpecialMultiplier()) { +- int i = randomsource.nextInt(2); ++ protected void populateDefaultEquipmentSlots(RandomSource random, DifficultyInstance difficulty) { ++ if (random.nextFloat() < 0.15F * difficulty.getSpecialMultiplier()) { ++ int i = random.nextInt(2); + float f = this.level().getDifficulty() == Difficulty.HARD ? 0.1F : 0.25F; + +- if (randomsource.nextFloat() < 0.095F) { ++ if (random.nextFloat() < 0.095F) { + ++i; + } + +- if (randomsource.nextFloat() < 0.095F) { ++ if (random.nextFloat() < 0.095F) { + ++i; + } + +- if (randomsource.nextFloat() < 0.095F) { ++ if (random.nextFloat() < 0.095F) { + ++i; + } + + boolean flag = true; +- EquipmentSlot[] aequipmentslot = EquipmentSlot.values(); +- int j = aequipmentslot.length; ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ int j = aenumitemslot.length; + + for (int k = 0; k < j; ++k) { +- EquipmentSlot equipmentslot = aequipmentslot[k]; ++ EquipmentSlot enumitemslot = aenumitemslot[k]; + +- if (equipmentslot.getType() == EquipmentSlot.Type.ARMOR) { +- ItemStack itemstack = this.getItemBySlot(equipmentslot); ++ if (enumitemslot.getType() == EquipmentSlot.Function.ARMOR) { ++ ItemStack itemstack = this.getItemBySlot(enumitemslot); + +- if (!flag && randomsource.nextFloat() < f) { ++ if (!flag && random.nextFloat() < f) { + break; + } + + flag = false; + if (itemstack.isEmpty()) { +- Item item = getEquipmentForSlot(equipmentslot, i); ++ Item item = getEquipmentForSlot(enumitemslot, i); + + if (item != null) { +- this.setItemSlot(equipmentslot, new ItemStack(item)); ++ this.setItemSlot(enumitemslot, new ItemStack(item)); + } + } + } +@@ -1068,54 +1129,54 @@ + } + + @Nullable +- public static Item getEquipmentForSlot(EquipmentSlot equipmentslot, int i) { +- switch (equipmentslot) { ++ public static Item getEquipmentForSlot(EquipmentSlot slot, int chance) { ++ switch (slot) { + case HEAD: +- if (i == 0) { ++ if (chance == 0) { + return Items.LEATHER_HELMET; +- } else if (i == 1) { ++ } else if (chance == 1) { + return Items.GOLDEN_HELMET; +- } else if (i == 2) { ++ } else if (chance == 2) { + return Items.CHAINMAIL_HELMET; +- } else if (i == 3) { ++ } else if (chance == 3) { + return Items.IRON_HELMET; +- } else if (i == 4) { ++ } else if (chance == 4) { + return Items.DIAMOND_HELMET; + } + case CHEST: +- if (i == 0) { ++ if (chance == 0) { + return Items.LEATHER_CHESTPLATE; +- } else if (i == 1) { ++ } else if (chance == 1) { + return Items.GOLDEN_CHESTPLATE; +- } else if (i == 2) { ++ } else if (chance == 2) { + return Items.CHAINMAIL_CHESTPLATE; +- } else if (i == 3) { ++ } else if (chance == 3) { + return Items.IRON_CHESTPLATE; +- } else if (i == 4) { ++ } else if (chance == 4) { + return Items.DIAMOND_CHESTPLATE; + } + case LEGS: +- if (i == 0) { ++ if (chance == 0) { + return Items.LEATHER_LEGGINGS; +- } else if (i == 1) { ++ } else if (chance == 1) { + return Items.GOLDEN_LEGGINGS; +- } else if (i == 2) { ++ } else if (chance == 2) { + return Items.CHAINMAIL_LEGGINGS; +- } else if (i == 3) { ++ } else if (chance == 3) { + return Items.IRON_LEGGINGS; +- } else if (i == 4) { ++ } else if (chance == 4) { + return Items.DIAMOND_LEGGINGS; + } + case FEET: +- if (i == 0) { ++ if (chance == 0) { + return Items.LEATHER_BOOTS; +- } else if (i == 1) { ++ } else if (chance == 1) { + return Items.GOLDEN_BOOTS; +- } else if (i == 2) { ++ } else if (chance == 2) { + return Items.CHAINMAIL_BOOTS; +- } else if (i == 3) { ++ } else if (chance == 3) { + return Items.IRON_BOOTS; +- } else if (i == 4) { ++ } else if (chance == 4) { + return Items.DIAMOND_BOOTS; + } + default: +@@ -1123,42 +1184,42 @@ + } + } + +- protected void populateDefaultEquipmentEnchantments(RandomSource randomsource, DifficultyInstance difficultyinstance) { +- float f = difficultyinstance.getSpecialMultiplier(); ++ protected void populateDefaultEquipmentEnchantments(RandomSource random, DifficultyInstance difficulty) { ++ float f = difficulty.getSpecialMultiplier(); + +- this.enchantSpawnedWeapon(randomsource, f); +- EquipmentSlot[] aequipmentslot = EquipmentSlot.values(); +- int i = aequipmentslot.length; ++ this.enchantSpawnedWeapon(random, f); ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ int i = aenumitemslot.length; + + for (int j = 0; j < i; ++j) { +- EquipmentSlot equipmentslot = aequipmentslot[j]; ++ EquipmentSlot enumitemslot = aenumitemslot[j]; + +- if (equipmentslot.getType() == EquipmentSlot.Type.ARMOR) { +- this.enchantSpawnedArmor(randomsource, f, equipmentslot); ++ if (enumitemslot.getType() == EquipmentSlot.Function.ARMOR) { ++ this.enchantSpawnedArmor(random, f, enumitemslot); + } + } + + } + +- protected void enchantSpawnedWeapon(RandomSource randomsource, float f) { +- if (!this.getMainHandItem().isEmpty() && randomsource.nextFloat() < 0.25F * f) { +- this.setItemSlot(EquipmentSlot.MAINHAND, EnchantmentHelper.enchantItem(randomsource, this.getMainHandItem(), (int) (5.0F + f * (float) randomsource.nextInt(18)), false)); ++ protected void enchantSpawnedWeapon(RandomSource random, float chanceMultiplier) { ++ if (!this.getMainHandItem().isEmpty() && random.nextFloat() < 0.25F * chanceMultiplier) { ++ this.setItemSlot(EquipmentSlot.MAINHAND, EnchantmentHelper.enchantItem(random, this.getMainHandItem(), (int) (5.0F + chanceMultiplier * (float) random.nextInt(18)), false)); + } + + } + +- protected void enchantSpawnedArmor(RandomSource randomsource, float f, EquipmentSlot equipmentslot) { +- ItemStack itemstack = this.getItemBySlot(equipmentslot); ++ protected void enchantSpawnedArmor(RandomSource random, float chanceMultiplier, EquipmentSlot slot) { ++ ItemStack itemstack = this.getItemBySlot(slot); + +- if (!itemstack.isEmpty() && randomsource.nextFloat() < 0.5F * f) { +- this.setItemSlot(equipmentslot, EnchantmentHelper.enchantItem(randomsource, itemstack, (int) (5.0F + f * (float) randomsource.nextInt(18)), false)); ++ if (!itemstack.isEmpty() && random.nextFloat() < 0.5F * chanceMultiplier) { ++ this.setItemSlot(slot, EnchantmentHelper.enchantItem(random, itemstack, (int) (5.0F + chanceMultiplier * (float) random.nextInt(18)), false)); + } + + } + + @Nullable +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- RandomSource randomsource = serverlevelaccessor.getRandom(); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ RandomSource randomsource = level.getRandom(); + + this.getAttribute(Attributes.FOLLOW_RANGE).addPermanentModifier(new AttributeModifier("Random spawn bonus", randomsource.triangle(0.0D, 0.11485000000000001D), AttributeModifier.Operation.MULTIPLY_BASE)); + if (randomsource.nextFloat() < 0.05F) { +@@ -1167,20 +1228,20 @@ + this.setLeftHanded(false); + } + +- return spawngroupdata; ++ return spawnData; + } + + public void setPersistenceRequired() { + this.persistenceRequired = true; + } + +- public void setDropChance(EquipmentSlot equipmentslot, float f) { +- switch (equipmentslot.getType()) { ++ public void setDropChance(EquipmentSlot slot, float chance) { ++ switch (slot.getType()) { + case HAND: +- this.handDropChances[equipmentslot.getIndex()] = f; ++ this.handDropChances[slot.getIndex()] = chance; + break; + case ARMOR: +- this.armorDropChances[equipmentslot.getIndex()] = f; ++ this.armorDropChances[slot.getIndex()] = chance; + } + + } +@@ -1189,16 +1250,15 @@ + return this.canPickUpLoot; + } + +- public void setCanPickUpLoot(boolean flag) { +- this.canPickUpLoot = flag; ++ public void setCanPickUpLoot(boolean canPickUpLoot) { ++ this.canPickUpLoot = canPickUpLoot; + } + + @Override +- @Override + public boolean canTakeItem(ItemStack itemstack) { +- EquipmentSlot equipmentslot = getEquipmentSlotForItem(itemstack); ++ EquipmentSlot enumitemslot = getEquipmentSlotForItem(itemstack); + +- return this.getItemBySlot(equipmentslot).isEmpty() && this.canPickUpLoot(); ++ return this.getItemBySlot(enumitemslot).isEmpty() && this.canPickUpLoot(); + } + + public boolean isPersistenceRequired() { +@@ -1206,55 +1266,66 @@ + } + + @Override +- @Override +- public final InteractionResult interact(Player player, InteractionHand interactionhand) { ++ public final InteractionResult interact(Player player, EnumHand hand) { + if (!this.isAlive()) { + return InteractionResult.PASS; + } else if (this.getLeashHolder() == player) { ++ // CraftBukkit start - fire PlayerUnleashEntityEvent ++ if (CraftEventFactory.callPlayerUnleashEntityEvent(this, player, hand).isCancelled()) { ++ ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, this.getLeashHolder())); ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.dropLeash(true, !player.getAbilities().instabuild); + this.gameEvent(GameEvent.ENTITY_INTERACT, player); + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { +- InteractionResult interactionresult = this.checkAndHandleImportantInteractions(player, interactionhand); ++ InteractionResult enuminteractionresult = this.checkAndHandleImportantInteractions(player, hand); + +- if (interactionresult.consumesAction()) { ++ if (enuminteractionresult.consumesAction()) { + this.gameEvent(GameEvent.ENTITY_INTERACT, player); +- return interactionresult; ++ return enuminteractionresult; + } else { +- interactionresult = this.mobInteract(player, interactionhand); +- if (interactionresult.consumesAction()) { ++ enuminteractionresult = this.mobInteract(player, hand); ++ if (enuminteractionresult.consumesAction()) { + this.gameEvent(GameEvent.ENTITY_INTERACT, player); +- return interactionresult; ++ return enuminteractionresult; + } else { +- return super.interact(player, interactionhand); ++ return super.interact(player, hand); + } + } + } + } + +- private InteractionResult checkAndHandleImportantInteractions(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ private InteractionResult checkAndHandleImportantInteractions(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (itemstack.is(Items.LEAD) && this.canBeLeashed(player)) { ++ // CraftBukkit start - fire PlayerLeashEntityEvent ++ if (CraftEventFactory.callPlayerLeashEntityEvent(this, player, player, hand).isCancelled()) { ++ ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, this.getLeashHolder())); ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.setLeashedTo(player, true); + itemstack.shrink(1); + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { + if (itemstack.is(Items.NAME_TAG)) { +- InteractionResult interactionresult = itemstack.interactLivingEntity(player, this, interactionhand); ++ InteractionResult enuminteractionresult = itemstack.interactLivingEntity(player, this, hand); + +- if (interactionresult.consumesAction()) { +- return interactionresult; ++ if (enuminteractionresult.consumesAction()) { ++ return enuminteractionresult; + } + } + + if (itemstack.getItem() instanceof SpawnEggItem) { + if (this.level() instanceof ServerLevel) { +- SpawnEggItem spawneggitem = (SpawnEggItem) itemstack.getItem(); +- Optional optional = spawneggitem.spawnOffspringFromSpawnEgg(player, this, this.getType(), (ServerLevel) this.level(), this.position(), itemstack); ++ SpawnEggItem itemmonsteregg = (SpawnEggItem) itemstack.getItem(); ++ Optional optional = itemmonsteregg.spawnOffspringFromSpawnEgg(player, this, (EntityType) this.getType(), (ServerLevel) this.level(), this.position(), itemstack); // CraftBukkit - decompile error + +- optional.ifPresent((mob) -> { +- this.onOffspringSpawnedFromEgg(player, mob); ++ optional.ifPresent((entityinsentient) -> { ++ this.onOffspringSpawnedFromEgg(player, entityinsentient); + }); + return optional.isPresent() ? InteractionResult.SUCCESS : InteractionResult.PASS; + } else { +@@ -1266,9 +1337,9 @@ + } + } + +- protected void onOffspringSpawnedFromEgg(Player player, Mob mob) {} ++ protected void onOffspringSpawnedFromEgg(Player player, Mob child) {} + +- protected InteractionResult mobInteract(Player player, InteractionHand interactionhand) { ++ protected InteractionResult mobInteract(Player player, EnumHand hand) { + return InteractionResult.PASS; + } + +@@ -1276,13 +1347,13 @@ + return this.isWithinRestriction(this.blockPosition()); + } + +- public boolean isWithinRestriction(BlockPos blockpos) { +- return this.restrictRadius == -1.0F ? true : this.restrictCenter.distSqr(blockpos) < (double) (this.restrictRadius * this.restrictRadius); ++ public boolean isWithinRestriction(BlockPos pos) { ++ return this.restrictRadius == -1.0F ? true : this.restrictCenter.distSqr(pos) < (double) (this.restrictRadius * this.restrictRadius); + } + +- public void restrictTo(BlockPos blockpos, int i) { +- this.restrictCenter = blockpos; +- this.restrictRadius = (float) i; ++ public void restrictTo(BlockPos pos, int distance) { ++ this.restrictCenter = pos; ++ this.restrictRadius = (float) distance; + } + + public BlockPos getRestrictCenter() { +@@ -1301,12 +1372,19 @@ + return this.restrictRadius != -1.0F; + } + ++ // CraftBukkit start + @Nullable +- public T convertTo(EntityType entitytype, boolean flag) { ++ public T convertTo(EntityType entityType, boolean transferInventory) { ++ return this.convertTo(entityType, transferInventory, EntityTransformEvent.TransformReason.UNKNOWN, CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ @Nullable ++ public T convertTo(EntityType entitytypes, boolean flag, EntityTransformEvent.TransformReason transformReason, CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end + if (this.isRemoved()) { + return null; + } else { +- T t0 = (Mob) entitytype.create(this.level()); ++ T t0 = entitytypes.create(this.level()); // CraftBukkit - decompile error + + if (t0 == null) { + return null; +@@ -1326,21 +1404,26 @@ + t0.setInvulnerable(this.isInvulnerable()); + if (flag) { + t0.setCanPickUpLoot(this.canPickUpLoot()); +- EquipmentSlot[] aequipmentslot = EquipmentSlot.values(); +- int i = aequipmentslot.length; ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ int i = aenumitemslot.length; + + for (int j = 0; j < i; ++j) { +- EquipmentSlot equipmentslot = aequipmentslot[j]; +- ItemStack itemstack = this.getItemBySlot(equipmentslot); ++ EquipmentSlot enumitemslot = aenumitemslot[j]; ++ ItemStack itemstack = this.getItemBySlot(enumitemslot); + + if (!itemstack.isEmpty()) { +- t0.setItemSlot(equipmentslot, itemstack.copyAndClear()); +- t0.setDropChance(equipmentslot, this.getEquipmentDropChance(equipmentslot)); ++ t0.setItemSlot(enumitemslot, itemstack.copyAndClear()); ++ t0.setDropChance(enumitemslot, this.getEquipmentDropChance(enumitemslot)); + } + } + } + +- this.level().addFreshEntity(t0); ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, t0, transformReason).isCancelled()) { ++ return null; ++ } ++ this.level().addFreshEntity(t0, spawnReason); ++ // CraftBukkit end + if (this.isPassenger()) { + Entity entity = this.getVehicle(); + +@@ -1361,21 +1444,24 @@ + + if (this.leashHolder != null) { + if (!this.isAlive() || !this.leashHolder.isAlive()) { +- this.dropLeash(true, true); ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE)); // CraftBukkit ++ this.dropLeash(true, !this.leashHolder.pluginRemoved);// CraftBukkit - SPIGOT-7487: Don't drop leash, when the holder was removed by a plugin + } + + } + } + +- public void dropLeash(boolean flag, boolean flag1) { ++ public void dropLeash(boolean broadcastPacket, boolean dropLeash) { + if (this.leashHolder != null) { + this.leashHolder = null; + this.leashInfoTag = null; +- if (!this.level().isClientSide && flag1) { +- this.spawnAtLocation((ItemLike) Items.LEAD); ++ if (!this.level().isClientSide && dropLeash) { ++ this.forceDrops = true; // CraftBukkit ++ this.spawnAtLocation((IMaterial) Items.LEAD); ++ this.forceDrops = false; // CraftBukkit + } + +- if (!this.level().isClientSide && flag && this.level() instanceof ServerLevel) { ++ if (!this.level().isClientSide && broadcastPacket && this.level() instanceof ServerLevel) { + ((ServerLevel) this.level()).getChunkSource().broadcast(this, new ClientboundSetEntityLinkPacket(this, (Entity) null)); + } + } +@@ -1383,7 +1469,7 @@ + } + + public boolean canBeLeashed(Player player) { +- return !this.isLeashed() && !(this instanceof Enemy); ++ return !this.isLeashed() && !(this instanceof IMonster); + } + + public boolean isLeashed() { +@@ -1399,10 +1485,10 @@ + return this.leashHolder; + } + +- public void setLeashedTo(Entity entity, boolean flag) { +- this.leashHolder = entity; ++ public void setLeashedTo(Entity leashHolder, boolean broadcastPacket) { ++ this.leashHolder = leashHolder; + this.leashInfoTag = null; +- if (!this.level().isClientSide && flag && this.level() instanceof ServerLevel) { ++ if (!this.level().isClientSide && broadcastPacket && this.level() instanceof ServerLevel) { + ((ServerLevel) this.level()).getChunkSource().broadcast(this, new ClientboundSetEntityLinkPacket(this, this.leashHolder)); + } + +@@ -1412,17 +1498,17 @@ + + } + +- public void setDelayedLeashHolderId(int i) { +- this.delayedLeashHolderId = i; ++ public void setDelayedLeashHolderId(int leashHolderID) { ++ this.delayedLeashHolderId = leashHolderID; + this.dropLeash(false, false); + } + + @Override +- @Override +- public boolean startRiding(Entity entity, boolean flag) { +- boolean flag1 = super.startRiding(entity, flag); ++ public boolean startRiding(Entity entity, boolean force) { ++ boolean flag1 = super.startRiding(entity, force); + + if (flag1 && this.isLeashed()) { ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit + this.dropLeash(true, true); + } + +@@ -1440,14 +1526,16 @@ + return; + } + } else if (this.leashInfoTag.contains("X", 99) && this.leashInfoTag.contains("Y", 99) && this.leashInfoTag.contains("Z", 99)) { +- BlockPos blockpos = NbtUtils.readBlockPos(this.leashInfoTag); ++ BlockPos blockposition = NbtUtils.readBlockPos(this.leashInfoTag); + +- this.setLeashedTo(LeashFenceKnotEntity.getOrCreateKnot(this.level(), blockpos), true); ++ this.setLeashedTo(LeashFenceKnotEntity.getOrCreateKnot(this.level(), blockposition), true); + return; + } + + if (this.tickCount > 100) { +- this.spawnAtLocation((ItemLike) Items.LEAD); ++ this.forceDrops = true; // CraftBukkit ++ this.spawnAtLocation((IMaterial) Items.LEAD); ++ this.forceDrops = false; // CraftBukkit + this.leashInfoTag = null; + } + } +@@ -1455,27 +1543,26 @@ + } + + @Override +- @Override + public boolean isEffectiveAi() { + return super.isEffectiveAi() && !this.isNoAi(); + } + +- public void setNoAi(boolean flag) { ++ public void setNoAi(boolean noAi) { + byte b0 = (Byte) this.entityData.get(Mob.DATA_MOB_FLAGS_ID); + +- this.entityData.set(Mob.DATA_MOB_FLAGS_ID, flag ? (byte) (b0 | 1) : (byte) (b0 & -2)); ++ this.entityData.set(Mob.DATA_MOB_FLAGS_ID, noAi ? (byte) (b0 | 1) : (byte) (b0 & -2)); + } + +- public void setLeftHanded(boolean flag) { ++ public void setLeftHanded(boolean leftHanded) { + byte b0 = (Byte) this.entityData.get(Mob.DATA_MOB_FLAGS_ID); + +- this.entityData.set(Mob.DATA_MOB_FLAGS_ID, flag ? (byte) (b0 | 2) : (byte) (b0 & -3)); ++ this.entityData.set(Mob.DATA_MOB_FLAGS_ID, leftHanded ? (byte) (b0 | 2) : (byte) (b0 & -3)); + } + +- public void setAggressive(boolean flag) { ++ public void setAggressive(boolean aggressive) { + byte b0 = (Byte) this.entityData.get(Mob.DATA_MOB_FLAGS_ID); + +- this.entityData.set(Mob.DATA_MOB_FLAGS_ID, flag ? (byte) (b0 | 4) : (byte) (b0 & -5)); ++ this.entityData.set(Mob.DATA_MOB_FLAGS_ID, aggressive ? (byte) (b0 | 4) : (byte) (b0 & -5)); + } + + public boolean isNoAi() { +@@ -1490,36 +1577,34 @@ + return ((Byte) this.entityData.get(Mob.DATA_MOB_FLAGS_ID) & 4) != 0; + } + +- public void setBaby(boolean flag) {} ++ public void setBaby(boolean baby) {} + + @Override +- @Override + public HumanoidArm getMainArm() { + return this.isLeftHanded() ? HumanoidArm.LEFT : HumanoidArm.RIGHT; + } + +- public boolean isWithinMeleeAttackRange(LivingEntity livingentity) { +- return this.getAttackBoundingBox().intersects(livingentity.getHitbox()); ++ public boolean isWithinMeleeAttackRange(LivingEntity entity) { ++ return this.getAttackBoundingBox().intersects(entity.getHitbox()); + } + + protected AABB getAttackBoundingBox() { + Entity entity = this.getVehicle(); +- AABB aabb; ++ AABB axisalignedbb; + + if (entity != null) { +- AABB aabb1 = entity.getBoundingBox(); +- AABB aabb2 = this.getBoundingBox(); ++ AABB axisalignedbb1 = entity.getBoundingBox(); ++ AABB axisalignedbb2 = this.getBoundingBox(); + +- aabb = new AABB(Math.min(aabb2.minX, aabb1.minX), aabb2.minY, Math.min(aabb2.minZ, aabb1.minZ), Math.max(aabb2.maxX, aabb1.maxX), aabb2.maxY, Math.max(aabb2.maxZ, aabb1.maxZ)); ++ axisalignedbb = new AABB(Math.min(axisalignedbb2.minX, axisalignedbb1.minX), axisalignedbb2.minY, Math.min(axisalignedbb2.minZ, axisalignedbb1.minZ), Math.max(axisalignedbb2.maxX, axisalignedbb1.maxX), axisalignedbb2.maxY, Math.max(axisalignedbb2.maxZ, axisalignedbb1.maxZ)); + } else { +- aabb = this.getBoundingBox(); ++ axisalignedbb = this.getBoundingBox(); + } + +- return aabb.inflate(Mob.DEFAULT_ATTACK_REACH, 0.0D, Mob.DEFAULT_ATTACK_REACH); ++ return axisalignedbb.inflate(Mob.DEFAULT_ATTACK_REACH, 0.0D, Mob.DEFAULT_ATTACK_REACH); + } + + @Override +- @Override + public boolean doHurtTarget(Entity entity) { + float f = (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE); + float f1 = (float) this.getAttributeValue(Attributes.ATTACK_KNOCKBACK); +@@ -1532,7 +1617,14 @@ + int i = EnchantmentHelper.getFireAspect(this); + + if (i > 0) { +- entity.setSecondsOnFire(i * 4); ++ // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), i * 4); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ entity.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + + boolean flag = entity.hurt(this.damageSources().mobAttack(this), f); +@@ -1544,9 +1636,9 @@ + } + + if (entity instanceof Player) { +- Player player = (Player) entity; ++ Player entityhuman = (Player) entity; + +- this.maybeDisableShield(player, this.getMainHandItem(), player.isUsingItem() ? player.getUseItem() : ItemStack.EMPTY); ++ this.maybeDisableShield(entityhuman, this.getMainHandItem(), entityhuman.isUsingItem() ? entityhuman.getUseItem() : ItemStack.EMPTY); + } + + this.doEnchantDamageEffects(this, entity); +@@ -1556,8 +1648,8 @@ + return flag; + } + +- private void maybeDisableShield(Player player, ItemStack itemstack, ItemStack itemstack1) { +- if (!itemstack.isEmpty() && !itemstack1.isEmpty() && itemstack.getItem() instanceof AxeItem && itemstack1.is(Items.SHIELD)) { ++ private void maybeDisableShield(Player player, ItemStack mobItemStack, ItemStack playerItemStack) { ++ if (!mobItemStack.isEmpty() && !playerItemStack.isEmpty() && mobItemStack.getItem() instanceof AxeItem && playerItemStack.is(Items.SHIELD)) { + float f = 0.25F + (float) EnchantmentHelper.getBlockEfficiency(this) * 0.05F; + + if (this.random.nextFloat() < f) { +@@ -1571,10 +1663,10 @@ + protected boolean isSunBurnTick() { + if (this.level().isDay() && !this.level().isClientSide) { + float f = this.getLightLevelDependentMagicValue(); +- BlockPos blockpos = BlockPos.containing(this.getX(), this.getEyeY(), this.getZ()); ++ BlockPos blockposition = BlockPos.containing(this.getX(), this.getEyeY(), this.getZ()); + boolean flag = this.isInWaterRainOrBubble() || this.isInPowderSnow || this.wasInPowderSnow; + +- if (f > 0.5F && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && !flag && this.level().canSeeSky(blockpos)) { ++ if (f > 0.5F && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && !flag && this.level().canSeeSky(blockposition)) { + return true; + } + } +@@ -1583,10 +1675,9 @@ + } + + @Override +- @Override +- protected void jumpInLiquid(TagKey tagkey) { ++ protected void jumpInLiquid(TagKey fluidTag) { + if (this.getNavigation().canFloat()) { +- super.jumpInLiquid(tagkey); ++ super.jumpInLiquid(fluidTag); + } else { + this.setDeltaMovement(this.getDeltaMovement().add(0.0D, 0.3D, 0.0D)); + } +@@ -1595,20 +1686,20 @@ + + @VisibleForTesting + public void removeFreeWill() { +- this.removeAllGoals((goal) -> { ++ this.removeAllGoals((pathfindergoal) -> { + return true; + }); + this.getBrain().removeAllBehaviors(); + } + +- public void removeAllGoals(Predicate predicate) { +- this.goalSelector.removeAllGoals(predicate); ++ public void removeAllGoals(Predicate filter) { ++ this.goalSelector.removeAllGoals(filter); + } + + @Override +- @Override + protected void removeAfterChangingDimensions() { + super.removeAfterChangingDimensions(); ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit + this.dropLeash(true, false); + this.getAllSlots().forEach((itemstack) -> { + if (!itemstack.isEmpty()) { +@@ -1620,10 +1711,9 @@ + + @Nullable + @Override +- @Override + public ItemStack getPickResult() { +- SpawnEggItem spawneggitem = SpawnEggItem.byId(this.getType()); ++ SpawnEggItem itemmonsteregg = SpawnEggItem.byId(this.getType()); + +- return spawneggitem == null ? null : new ItemStack(spawneggitem); ++ return itemmonsteregg == null ? null : new ItemStack(itemmonsteregg); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/NeutralMob.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/NeutralMob.java.patch new file mode 100644 index 0000000000..35220dcb91 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/NeutralMob.java.patch @@ -0,0 +1,86 @@ +--- a/net/minecraft/world/entity/NeutralMob.java ++++ b/net/minecraft/world/entity/NeutralMob.java +@@ -25,21 +25,21 @@ + + void startPersistentAngerTimer(); + +- default void addPersistentAngerSaveData(CompoundTag compoundtag) { +- compoundtag.putInt("AngerTime", this.getRemainingPersistentAngerTime()); ++ default void addPersistentAngerSaveData(CompoundTag nbt) { ++ nbt.putInt("AngerTime", this.getRemainingPersistentAngerTime()); + if (this.getPersistentAngerTarget() != null) { +- compoundtag.putUUID("AngryAt", this.getPersistentAngerTarget()); ++ nbt.putUUID("AngryAt", this.getPersistentAngerTarget()); + } + + } + +- default void readPersistentAngerSaveData(Level level, CompoundTag compoundtag) { +- this.setRemainingPersistentAngerTime(compoundtag.getInt("AngerTime")); ++ default void readPersistentAngerSaveData(Level level, CompoundTag tag) { ++ this.setRemainingPersistentAngerTime(tag.getInt("AngerTime")); + if (level instanceof ServerLevel) { +- if (!compoundtag.hasUUID("AngryAt")) { ++ if (!tag.hasUUID("AngryAt")) { + this.setPersistentAngerTarget((UUID) null); + } else { +- UUID uuid = compoundtag.getUUID("AngryAt"); ++ UUID uuid = tag.getUUID("AngryAt"); + + this.setPersistentAngerTarget(uuid); + Entity entity = ((ServerLevel) level).getEntity(uuid); +@@ -58,19 +58,19 @@ + } + } + +- default void updatePersistentAnger(ServerLevel serverlevel, boolean flag) { +- LivingEntity livingentity = this.getTarget(); ++ default void updatePersistentAnger(ServerLevel serverLevel, boolean updateAnger) { ++ LivingEntity entityliving = this.getTarget(); + UUID uuid = this.getPersistentAngerTarget(); + +- if ((livingentity == null || livingentity.isDeadOrDying()) && uuid != null && serverlevel.getEntity(uuid) instanceof Mob) { ++ if ((entityliving == null || entityliving.isDeadOrDying()) && uuid != null && serverLevel.getEntity(uuid) instanceof Mob) { + this.stopBeingAngry(); + } else { +- if (livingentity != null && !Objects.equals(uuid, livingentity.getUUID())) { +- this.setPersistentAngerTarget(livingentity.getUUID()); ++ if (entityliving != null && !Objects.equals(uuid, entityliving.getUUID())) { ++ this.setPersistentAngerTarget(entityliving.getUUID()); + this.startPersistentAngerTimer(); + } + +- if (this.getRemainingPersistentAngerTime() > 0 && (livingentity == null || livingentity.getType() != EntityType.PLAYER || !flag)) { ++ if (this.getRemainingPersistentAngerTime() > 0 && (entityliving == null || entityliving.getType() != EntityType.PLAYER || !updateAnger)) { + this.setRemainingPersistentAngerTime(this.getRemainingPersistentAngerTime() - 1); + if (this.getRemainingPersistentAngerTime() == 0) { + this.stopBeingAngry(); +@@ -80,8 +80,8 @@ + } + } + +- default boolean isAngryAt(LivingEntity livingentity) { +- return !this.canAttack(livingentity) ? false : (livingentity.getType() == EntityType.PLAYER && this.isAngryAtAllPlayers(livingentity.level()) ? true : livingentity.getUUID().equals(this.getPersistentAngerTarget())); ++ default boolean isAngryAt(LivingEntity target) { ++ return !this.canAttack(target) ? false : (target.getType() == EntityType.PLAYER && this.isAngryAtAllPlayers(target.level()) ? true : target.getUUID().equals(this.getPersistentAngerTarget())); + } + + default boolean isAngryAtAllPlayers(Level level) { +@@ -108,7 +108,7 @@ + default void stopBeingAngry() { + this.setLastHurtByMob((LivingEntity) null); + this.setPersistentAngerTarget((UUID) null); +- this.setTarget((LivingEntity) null); ++ this.setTarget((LivingEntity) null, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET, true); // CraftBukkit + this.setRemainingPersistentAngerTime(0); + } + +@@ -121,6 +121,8 @@ + + void setTarget(@Nullable LivingEntity livingEntity); + ++ boolean setTarget(@Nullable LivingEntity entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent); // CraftBukkit ++ + boolean canAttack(LivingEntity entity); + + @Nullable diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/PathfinderMob.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/PathfinderMob.java.patch new file mode 100644 index 0000000000..de4068ef8c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/PathfinderMob.java.patch @@ -0,0 +1,97 @@ +--- a/net/minecraft/world/entity/PathfinderMob.java ++++ b/net/minecraft/world/entity/PathfinderMob.java +@@ -8,27 +8,29 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.event.entity.EntityUnleashEvent; ++// CraftBukkit end + + public abstract class PathfinderMob extends Mob { + + protected static final float DEFAULT_WALK_TARGET_VALUE = 0.0F; + +- protected PathfinderMob(EntityType entitytype, Level level) { +- super(entitytype, level); ++ protected PathfinderMob(EntityType entityType, Level level) { ++ super(entityType, level); + } + +- public float getWalkTargetValue(BlockPos blockpos) { +- return this.getWalkTargetValue(blockpos, this.level()); ++ public float getWalkTargetValue(BlockPos pos) { ++ return this.getWalkTargetValue(pos, this.level()); + } + +- public float getWalkTargetValue(BlockPos blockpos, LevelReader levelreader) { ++ public float getWalkTargetValue(BlockPos pos, LevelReader level) { + return 0.0F; + } + + @Override +- @Override +- public boolean checkSpawnRules(LevelAccessor levelaccessor, MobSpawnType mobspawntype) { +- return this.getWalkTargetValue(this.blockPosition(), levelaccessor) >= 0.0F; ++ public boolean checkSpawnRules(LevelAccessor level, EnumMobSpawn spawnReason) { ++ return this.getWalkTargetValue(this.blockPosition(), level) >= 0.0F; + } + + public boolean isPathFinding() { +@@ -36,13 +38,12 @@ + } + + public boolean isPanicking() { +- return this.brain.hasMemoryValue(MemoryModuleType.IS_PANICKING) ? this.brain.getMemory(MemoryModuleType.IS_PANICKING).isPresent() : this.goalSelector.getRunningGoals().anyMatch((wrappedgoal) -> { +- return wrappedgoal.getGoal() instanceof PanicGoal; ++ return this.brain.hasMemoryValue(MemoryModuleType.IS_PANICKING) ? this.brain.getMemory(MemoryModuleType.IS_PANICKING).isPresent() : this.goalSelector.getRunningGoals().anyMatch((pathfindergoalwrapped) -> { ++ return pathfindergoalwrapped.getGoal() instanceof PanicGoal; + }); + } + + @Override +- @Override + protected void tickLeash() { + super.tickLeash(); + Entity entity = this.getLeashHolder(); +@@ -53,6 +54,7 @@ + + if (this instanceof TamableAnimal && ((TamableAnimal) this).isInSittingPose()) { + if (f > 10.0F) { ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit + this.dropLeash(true, true); + } + +@@ -61,8 +63,9 @@ + + this.onLeashDistance(f); + if (f > 10.0F) { ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit + this.dropLeash(true, true); +- this.goalSelector.disableControlFlag(Goal.Flag.MOVE); ++ this.goalSelector.disableControlFlag(Goal.Type.MOVE); + } else if (f > 6.0F) { + double d0 = (entity.getX() - this.getX()) / (double) f; + double d1 = (entity.getY() - this.getY()) / (double) f; +@@ -71,11 +74,11 @@ + this.setDeltaMovement(this.getDeltaMovement().add(Math.copySign(d0 * d0 * 0.4D, d0), Math.copySign(d1 * d1 * 0.4D, d1), Math.copySign(d2 * d2 * 0.4D, d2))); + this.checkSlowFallDistance(); + } else if (this.shouldStayCloseToLeashHolder() && !this.isPanicking()) { +- this.goalSelector.enableControlFlag(Goal.Flag.MOVE); ++ this.goalSelector.enableControlFlag(Goal.Type.MOVE); + float f1 = 2.0F; +- Vec3 vec3 = (new Vec3(entity.getX() - this.getX(), entity.getY() - this.getY(), entity.getZ() - this.getZ())).normalize().scale((double) Math.max(f - 2.0F, 0.0F)); ++ Vec3 vec3d = (new Vec3(entity.getX() - this.getX(), entity.getY() - this.getY(), entity.getZ() - this.getZ())).normalize().scale((double) Math.max(f - 2.0F, 0.0F)); + +- this.getNavigation().moveTo(this.getX() + vec3.x, this.getY() + vec3.y, this.getZ() + vec3.z, this.followLeashSpeed()); ++ this.getNavigation().moveTo(this.getX() + vec3d.x, this.getY() + vec3d.y, this.getZ() + vec3d.z, this.followLeashSpeed()); + } + } + +@@ -89,5 +92,5 @@ + return 1.0D; + } + +- protected void onLeashDistance(float f) {} ++ protected void onLeashDistance(float distance) {} + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/attributes/Attributes.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/attributes/Attributes.java.patch new file mode 100644 index 0000000000..7b73e410cf --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/attributes/Attributes.java.patch @@ -0,0 +1,17 @@ +--- a/net/minecraft/world/entity/ai/attributes/Attributes.java ++++ b/net/minecraft/world/entity/ai/attributes/Attributes.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.world.entity.ai.attributes; + + import net.minecraft.core.Registry; +@@ -22,7 +23,7 @@ + + public Attributes() {} + +- private static Attribute register(String s, Attribute attribute) { +- return (Attribute) Registry.register(BuiltInRegistries.ATTRIBUTE, s, attribute); ++ private static Attribute register(String id, Attribute attribute) { ++ return (Attribute) Registry.register(BuiltInRegistries.ATTRIBUTE, id, attribute); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java.patch new file mode 100644 index 0000000000..800821493a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java.patch @@ -0,0 +1,64 @@ +--- a/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java ++++ b/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java +@@ -9,36 +9,49 @@ + import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.entity.npc.VillagerProfession; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftVillager; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.VillagerCareerChangeEvent; ++// CraftBukkit end ++ + public class AssignProfessionFromJobSite { + + public AssignProfessionFromJobSite() {} + + public static BehaviorControl create() { +- return BehaviorBuilder.create((behaviorbuilder_instance) -> { +- return behaviorbuilder_instance.group(behaviorbuilder_instance.present(MemoryModuleType.POTENTIAL_JOB_SITE), behaviorbuilder_instance.registered(MemoryModuleType.JOB_SITE)).apply(behaviorbuilder_instance, (memoryaccessor, memoryaccessor1) -> { +- return (serverlevel, villager, i) -> { +- GlobalPos globalpos = (GlobalPos) behaviorbuilder_instance.get(memoryaccessor); ++ return BehaviorBuilder.create((behaviorbuilder_b) -> { ++ return behaviorbuilder_b.group(behaviorbuilder_b.present(MemoryModuleType.POTENTIAL_JOB_SITE), behaviorbuilder_b.registered(MemoryModuleType.JOB_SITE)).apply(behaviorbuilder_b, (memoryaccessor, memoryaccessor1) -> { ++ return (worldserver, entityvillager, i) -> { ++ GlobalPos globalpos = (GlobalPos) behaviorbuilder_b.get(memoryaccessor); + +- if (!globalpos.pos().closerToCenterThan(villager.position(), 2.0D) && !villager.assignProfessionWhenSpawned()) { ++ if (!globalpos.pos().closerToCenterThan(entityvillager.position(), 2.0D) && !entityvillager.assignProfessionWhenSpawned()) { + return false; + } else { + memoryaccessor.erase(); + memoryaccessor1.set(globalpos); +- serverlevel.broadcastEntityEvent(villager, (byte) 14); +- if (villager.getVillagerData().getProfession() != VillagerProfession.NONE) { ++ worldserver.broadcastEntityEvent(entityvillager, (byte) 14); ++ if (entityvillager.getVillagerData().getProfession() != VillagerProfession.NONE) { + return true; + } else { +- MinecraftServer minecraftserver = serverlevel.getServer(); ++ MinecraftServer minecraftserver = worldserver.getServer(); + +- Optional.ofNullable(minecraftserver.getLevel(globalpos.dimension())).flatMap((serverlevel1) -> { +- return serverlevel1.getPoiManager().getType(globalpos.pos()); ++ Optional.ofNullable(minecraftserver.getLevel(globalpos.dimension())).flatMap((worldserver1) -> { ++ return worldserver1.getPoiManager().getType(globalpos.pos()); + }).flatMap((holder) -> { + return BuiltInRegistries.VILLAGER_PROFESSION.stream().filter((villagerprofession) -> { + return villagerprofession.heldJobSite().test(holder); + }).findFirst(); + }).ifPresent((villagerprofession) -> { +- villager.setVillagerData(villager.getVillagerData().setProfession(villagerprofession)); +- villager.refreshBrain(serverlevel); ++ // CraftBukkit start - Fire VillagerCareerChangeEvent where Villager gets employed ++ VillagerCareerChangeEvent event = CraftEventFactory.callVillagerCareerChangeEvent(entityvillager, CraftVillager.CraftProfession.minecraftToBukkit(villagerprofession), VillagerCareerChangeEvent.ChangeReason.EMPLOYED); ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ entityvillager.setVillagerData(entityvillager.getVillagerData().setProfession(CraftVillager.CraftProfession.bukkitToMinecraft(event.getProfession()))); ++ // CraftBukkit end ++ entityvillager.refreshBrain(worldserver); + }); + return true; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java.patch new file mode 100644 index 0000000000..c71300b983 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java.patch @@ -0,0 +1,64 @@ +--- a/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java ++++ b/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java +@@ -7,31 +7,48 @@ + import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + import net.minecraft.world.entity.ai.memory.WalkTarget; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++// CraftBukkit end + + public class BabyFollowAdult { + + public BabyFollowAdult() {} + +- public static OneShot create(UniformInt uniformint, float f) { +- return create(uniformint, (livingentity) -> { +- return f; ++ public static OneShot create(UniformInt followRange, float speedModifier) { ++ return create(followRange, (entityliving) -> { ++ return speedModifier; + }); + } + +- public static OneShot create(UniformInt uniformint, Function function) { +- return BehaviorBuilder.create((behaviorbuilder_instance) -> { +- return behaviorbuilder_instance.group(behaviorbuilder_instance.present(MemoryModuleType.NEAREST_VISIBLE_ADULT), behaviorbuilder_instance.registered(MemoryModuleType.LOOK_TARGET), behaviorbuilder_instance.absent(MemoryModuleType.WALK_TARGET)).apply(behaviorbuilder_instance, (memoryaccessor, memoryaccessor1, memoryaccessor2) -> { +- return (serverlevel, ageablemob, i) -> { +- if (!ageablemob.isBaby()) { ++ public static OneShot create(UniformInt followRange, Function speedModifier) { ++ return BehaviorBuilder.create((behaviorbuilder_b) -> { ++ return behaviorbuilder_b.group(behaviorbuilder_b.present(MemoryModuleType.NEAREST_VISIBLE_ADULT), behaviorbuilder_b.registered(MemoryModuleType.LOOK_TARGET), behaviorbuilder_b.absent(MemoryModuleType.WALK_TARGET)).apply(behaviorbuilder_b, (memoryaccessor, memoryaccessor1, memoryaccessor2) -> { ++ return (worldserver, entityageable, i) -> { ++ if (!entityageable.isBaby()) { + return false; + } else { +- AgeableMob ageablemob1 = (AgeableMob) behaviorbuilder_instance.get(memoryaccessor); ++ LivingEntity entityageable1 = (AgeableMob) behaviorbuilder_b.get(memoryaccessor); // CraftBukkit - type + +- if (ageablemob.closerThan(ageablemob1, (double) (uniformint.getMaxValue() + 1)) && !ageablemob.closerThan(ageablemob1, (double) uniformint.getMinValue())) { +- WalkTarget walktarget = new WalkTarget(new EntityTracker(ageablemob1, false), (Float) function.apply(ageablemob), uniformint.getMinValue() - 1); ++ if (entityageable.closerThan(entityageable1, (double) (followRange.getMaxValue() + 1)) && !entityageable.closerThan(entityageable1, (double) followRange.getMinValue())) { ++ // CraftBukkit start ++ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(entityageable, entityageable1, EntityTargetEvent.TargetReason.FOLLOW_LEADER); ++ if (event.isCancelled()) { ++ return false; ++ } ++ if (event.getTarget() == null) { ++ memoryaccessor.erase(); ++ return true; ++ } ++ entityageable1 = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ // CraftBukkit end ++ WalkTarget memorytarget = new WalkTarget(new EntityTracker(entityageable1, false), (Float) speedModifier.apply(entityageable), followRange.getMinValue() - 1); + +- memoryaccessor1.set(new EntityTracker(ageablemob1, true)); +- memoryaccessor2.set(walktarget); ++ memoryaccessor1.set(new EntityTracker(entityageable1, true)); ++ memoryaccessor2.set(memorytarget); + return true; + } else { + return false; diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java.patch new file mode 100644 index 0000000000..4844ae346e --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java.patch @@ -0,0 +1,265 @@ +--- a/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java ++++ b/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java +@@ -24,174 +24,182 @@ + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.ProjectileWeaponItem; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.Vec3; + + public class BehaviorUtils { + + private BehaviorUtils() {} + +- public static void lockGazeAndWalkToEachOther(LivingEntity livingentity, LivingEntity livingentity1, float f) { +- lookAtEachOther(livingentity, livingentity1); +- setWalkAndLookTargetMemoriesToEachOther(livingentity, livingentity1, f); ++ public static void lockGazeAndWalkToEachOther(LivingEntity firstEntity, LivingEntity secondEntity, float speed) { ++ lookAtEachOther(firstEntity, secondEntity); ++ setWalkAndLookTargetMemoriesToEachOther(firstEntity, secondEntity, speed); + } + +- public static boolean entityIsVisible(Brain brain, LivingEntity livingentity) { ++ public static boolean entityIsVisible(Brain brain, LivingEntity target) { + Optional optional = brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES); + +- return optional.isPresent() && ((NearestVisibleLivingEntities) optional.get()).contains(livingentity); ++ return optional.isPresent() && ((NearestVisibleLivingEntities) optional.get()).contains(target); + } + +- public static boolean targetIsValid(Brain brain, MemoryModuleType memorymoduletype, EntityType entitytype) { +- return targetIsValid(brain, memorymoduletype, (livingentity) -> { +- return livingentity.getType() == entitytype; ++ public static boolean targetIsValid(Brain brains, MemoryModuleType memorymodule, EntityType entityType) { ++ return targetIsValid(brains, memorymodule, (entityliving) -> { ++ return entityliving.getType() == entityType; + }); + } + +- private static boolean targetIsValid(Brain brain, MemoryModuleType memorymoduletype, Predicate predicate) { +- return brain.getMemory(memorymoduletype).filter(predicate).filter(LivingEntity::isAlive).filter((livingentity) -> { +- return entityIsVisible(brain, livingentity); ++ private static boolean targetIsValid(Brain brain, MemoryModuleType memoryType, Predicate livingPredicate) { ++ return brain.getMemory(memoryType).filter(livingPredicate).filter(LivingEntity::isAlive).filter((entityliving) -> { ++ return entityIsVisible(brain, entityliving); + }).isPresent(); + } + +- private static void lookAtEachOther(LivingEntity livingentity, LivingEntity livingentity1) { +- lookAtEntity(livingentity, livingentity1); +- lookAtEntity(livingentity1, livingentity); ++ private static void lookAtEachOther(LivingEntity firstEntity, LivingEntity secondEntity) { ++ lookAtEntity(firstEntity, secondEntity); ++ lookAtEntity(secondEntity, firstEntity); + } + +- public static void lookAtEntity(LivingEntity livingentity, LivingEntity livingentity1) { +- livingentity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (Object) (new EntityTracker(livingentity1, true))); ++ public static void lookAtEntity(LivingEntity entity, LivingEntity target) { ++ entity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (new EntityTracker(target, true))); // CraftBukkit - decompile error + } + +- private static void setWalkAndLookTargetMemoriesToEachOther(LivingEntity livingentity, LivingEntity livingentity1, float f) { ++ private static void setWalkAndLookTargetMemoriesToEachOther(LivingEntity firstEntity, LivingEntity secondEntity, float speed) { + boolean flag = true; + +- setWalkAndLookTargetMemories(livingentity, (Entity) livingentity1, f, 2); +- setWalkAndLookTargetMemories(livingentity1, (Entity) livingentity, f, 2); ++ setWalkAndLookTargetMemories(firstEntity, (Entity) secondEntity, speed, 2); ++ setWalkAndLookTargetMemories(secondEntity, (Entity) firstEntity, speed, 2); + } + +- public static void setWalkAndLookTargetMemories(LivingEntity livingentity, Entity entity, float f, int i) { +- setWalkAndLookTargetMemories(livingentity, (PositionTracker) (new EntityTracker(entity, true)), f, i); ++ public static void setWalkAndLookTargetMemories(LivingEntity livingEntity, Entity target, float speed, int distance) { ++ setWalkAndLookTargetMemories(livingEntity, (PositionTracker) (new EntityTracker(target, true)), speed, distance); + } + +- public static void setWalkAndLookTargetMemories(LivingEntity livingentity, BlockPos blockpos, float f, int i) { +- setWalkAndLookTargetMemories(livingentity, (PositionTracker) (new BlockPosTracker(blockpos)), f, i); ++ public static void setWalkAndLookTargetMemories(LivingEntity livingEntity, BlockPos pos, float speed, int distance) { ++ setWalkAndLookTargetMemories(livingEntity, (PositionTracker) (new BlockPosTracker(pos)), speed, distance); + } + +- public static void setWalkAndLookTargetMemories(LivingEntity livingentity, PositionTracker positiontracker, float f, int i) { +- WalkTarget walktarget = new WalkTarget(positiontracker, f, i); ++ public static void setWalkAndLookTargetMemories(LivingEntity entity, PositionTracker positionTracker, float speedModifier, int closeEnoughDist) { ++ WalkTarget memorytarget = new WalkTarget(positionTracker, speedModifier, closeEnoughDist); + +- livingentity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (Object) positiontracker); +- livingentity.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (Object) walktarget); ++ entity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, positionTracker); // CraftBukkit - decompile error ++ entity.getBrain().setMemory(MemoryModuleType.WALK_TARGET, memorytarget); // CraftBukkit - decompile error + } + +- public static void throwItem(LivingEntity livingentity, ItemStack itemstack, Vec3 vec3) { +- Vec3 vec31 = new Vec3(0.30000001192092896D, 0.30000001192092896D, 0.30000001192092896D); ++ public static void throwItem(LivingEntity livingEntity, ItemStack stack, Vec3 offset) { ++ Vec3 vec3d1 = new Vec3(0.30000001192092896D, 0.30000001192092896D, 0.30000001192092896D); + +- throwItem(livingentity, itemstack, vec3, vec31, 0.3F); ++ throwItem(livingEntity, stack, offset, vec3d1, 0.3F); + } + +- public static void throwItem(LivingEntity livingentity, ItemStack itemstack, Vec3 vec3, Vec3 vec31, float f) { +- double d0 = livingentity.getEyeY() - (double) f; +- ItemEntity itementity = new ItemEntity(livingentity.level(), livingentity.getX(), d0, livingentity.getZ(), itemstack); ++ public static void throwItem(LivingEntity entity, ItemStack stack, Vec3 offset, Vec3 speedMultiplier, float yOffset) { ++ if (stack.isEmpty()) return; // CraftBukkit - SPIGOT-4940: no empty loot ++ double d0 = entity.getEyeY() - (double) yOffset; ++ ItemEntity entityitem = new ItemEntity(entity.level(), entity.getX(), d0, entity.getZ(), stack); + +- itementity.setThrower(livingentity); +- Vec3 vec32 = vec3.subtract(livingentity.position()); ++ entityitem.setThrower(entity); ++ Vec3 vec3d2 = offset.subtract(entity.position()); + +- vec32 = vec32.normalize().multiply(vec31.x, vec31.y, vec31.z); +- itementity.setDeltaMovement(vec32); +- itementity.setDefaultPickUpDelay(); +- livingentity.level().addFreshEntity(itementity); ++ vec3d2 = vec3d2.normalize().multiply(speedMultiplier.x, speedMultiplier.y, speedMultiplier.z); ++ entityitem.setDeltaMovement(vec3d2); ++ entityitem.setDefaultPickUpDelay(); ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(entity.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ entityitem.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ entity.level().addFreshEntity(entityitem); + } + +- public static SectionPos findSectionClosestToVillage(ServerLevel serverlevel, SectionPos sectionpos, int i) { +- int j = serverlevel.sectionsToVillage(sectionpos); +- Stream stream = SectionPos.cube(sectionpos, i).filter((sectionpos1) -> { +- return serverlevel.sectionsToVillage(sectionpos1) < j; ++ public static SectionPos findSectionClosestToVillage(ServerLevel serverLevel, SectionPos sectionPos, int radius) { ++ int j = serverLevel.sectionsToVillage(sectionPos); ++ Stream stream = SectionPos.cube(sectionPos, radius).filter((sectionposition1) -> { // CraftBukkit - decompile error ++ return serverLevel.sectionsToVillage(sectionposition1) < j; + }); + +- Objects.requireNonNull(serverlevel); +- return (SectionPos) stream.min(Comparator.comparingInt(serverlevel::sectionsToVillage)).orElse(sectionpos); ++ Objects.requireNonNull(serverLevel); ++ return (SectionPos) stream.min(Comparator.comparingInt(serverLevel::sectionsToVillage)).orElse(sectionPos); + } + +- public static boolean isWithinAttackRange(Mob mob, LivingEntity livingentity, int i) { ++ public static boolean isWithinAttackRange(Mob mob, LivingEntity target, int cooldown) { + Item item = mob.getMainHandItem().getItem(); + + if (item instanceof ProjectileWeaponItem) { +- ProjectileWeaponItem projectileweaponitem = (ProjectileWeaponItem) item; ++ ProjectileWeaponItem itemprojectileweapon = (ProjectileWeaponItem) item; + +- if (mob.canFireProjectileWeapon(projectileweaponitem)) { +- int j = projectileweaponitem.getDefaultProjectileRange() - i; ++ if (mob.canFireProjectileWeapon(itemprojectileweapon)) { ++ int j = itemprojectileweapon.getDefaultProjectileRange() - cooldown; + +- return mob.closerThan(livingentity, (double) j); ++ return mob.closerThan(target, (double) j); + } + } + +- return mob.isWithinMeleeAttackRange(livingentity); ++ return mob.isWithinMeleeAttackRange(target); + } + +- public static boolean isOtherTargetMuchFurtherAwayThanCurrentAttackTarget(LivingEntity livingentity, LivingEntity livingentity1, double d0) { +- Optional optional = livingentity.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET); ++ public static boolean isOtherTargetMuchFurtherAwayThanCurrentAttackTarget(LivingEntity livingEntity, LivingEntity target, double distance) { ++ Optional optional = livingEntity.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET); + + if (optional.isEmpty()) { + return false; + } else { +- double d1 = livingentity.distanceToSqr(((LivingEntity) optional.get()).position()); +- double d2 = livingentity.distanceToSqr(livingentity1.position()); ++ double d1 = livingEntity.distanceToSqr(((LivingEntity) optional.get()).position()); ++ double d2 = livingEntity.distanceToSqr(target.position()); + +- return d2 > d1 + d0 * d0; ++ return d2 > d1 + distance * distance; + } + } + +- public static boolean canSee(LivingEntity livingentity, LivingEntity livingentity1) { +- Brain brain = livingentity.getBrain(); ++ public static boolean canSee(LivingEntity livingEntity, LivingEntity target) { ++ Brain behaviorcontroller = livingEntity.getBrain(); + +- return !brain.hasMemoryValue(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES) ? false : ((NearestVisibleLivingEntities) brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES).get()).contains(livingentity1); ++ return !behaviorcontroller.hasMemoryValue(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES) ? false : ((NearestVisibleLivingEntities) behaviorcontroller.getMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES).get()).contains(target); + } + +- public static LivingEntity getNearestTarget(LivingEntity livingentity, Optional optional, LivingEntity livingentity1) { +- return optional.isEmpty() ? livingentity1 : getTargetNearestMe(livingentity, (LivingEntity) optional.get(), livingentity1); ++ public static LivingEntity getNearestTarget(LivingEntity centerEntity, Optional optionalEntity, LivingEntity livingEntity) { ++ return optionalEntity.isEmpty() ? livingEntity : getTargetNearestMe(centerEntity, (LivingEntity) optionalEntity.get(), livingEntity); + } + +- public static LivingEntity getTargetNearestMe(LivingEntity livingentity, LivingEntity livingentity1, LivingEntity livingentity2) { +- Vec3 vec3 = livingentity1.position(); +- Vec3 vec31 = livingentity2.position(); ++ public static LivingEntity getTargetNearestMe(LivingEntity centerEntity, LivingEntity livingEntity1, LivingEntity livingEntity2) { ++ Vec3 vec3d = livingEntity1.position(); ++ Vec3 vec3d1 = livingEntity2.position(); + +- return livingentity.distanceToSqr(vec3) < livingentity.distanceToSqr(vec31) ? livingentity1 : livingentity2; ++ return centerEntity.distanceToSqr(vec3d) < centerEntity.distanceToSqr(vec3d1) ? livingEntity1 : livingEntity2; + } + +- public static Optional getLivingEntityFromUUIDMemory(LivingEntity livingentity, MemoryModuleType memorymoduletype) { +- Optional optional = livingentity.getBrain().getMemory(memorymoduletype); ++ public static Optional getLivingEntityFromUUIDMemory(LivingEntity livingEntity, MemoryModuleType targetMemory) { ++ Optional optional = livingEntity.getBrain().getMemory(targetMemory); + + return optional.map((uuid) -> { +- return ((ServerLevel) livingentity.level()).getEntity(uuid); ++ return ((ServerLevel) livingEntity.level()).getEntity(uuid); + }).map((entity) -> { +- LivingEntity livingentity1; ++ LivingEntity entityliving1; + + if (entity instanceof LivingEntity) { +- LivingEntity livingentity2 = (LivingEntity) entity; ++ LivingEntity entityliving2 = (LivingEntity) entity; + +- livingentity1 = livingentity2; ++ entityliving1 = entityliving2; + } else { +- livingentity1 = null; ++ entityliving1 = null; + } + +- return livingentity1; ++ return entityliving1; + }); + } + + @Nullable +- public static Vec3 getRandomSwimmablePos(PathfinderMob pathfindermob, int i, int j) { +- Vec3 vec3 = DefaultRandomPos.getPos(pathfindermob, i, j); ++ public static Vec3 getRandomSwimmablePos(PathfinderMob pathfinder, int radius, int verticalDistance) { ++ Vec3 vec3d = DefaultRandomPos.getPos(pathfinder, radius, verticalDistance); + +- for (int k = 0; vec3 != null && !pathfindermob.level().getBlockState(BlockPos.containing(vec3)).isPathfindable(pathfindermob.level(), BlockPos.containing(vec3), PathComputationType.WATER) && k++ < 10; vec3 = DefaultRandomPos.getPos(pathfindermob, i, j)) { ++ for (int k = 0; vec3d != null && !pathfinder.level().getBlockState(BlockPos.containing(vec3d)).isPathfindable(pathfinder.level(), BlockPos.containing(vec3d), PathMode.WATER) && k++ < 10; vec3d = DefaultRandomPos.getPos(pathfinder, radius, verticalDistance)) { + ; + } + +- return vec3; ++ return vec3d; + } + +- public static boolean isBreeding(LivingEntity livingentity) { +- return livingentity.getBrain().hasMemoryValue(MemoryModuleType.BREED_TARGET); ++ public static boolean isBreeding(LivingEntity entity) { ++ return entity.getBrain().hasMemoryValue(MemoryModuleType.BREED_TARGET); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java.patch new file mode 100644 index 0000000000..a16e8b5dd6 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java ++++ b/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java +@@ -13,25 +13,39 @@ + + public GoToWantedItem() {} + +- public static BehaviorControl create(float f, boolean flag, int i) { +- return create((livingentity) -> { ++ public static BehaviorControl create(float speedModifier, boolean hasTarget, int maxDistToWalk) { ++ return create((entityliving) -> { + return true; +- }, f, flag, i); ++ }, speedModifier, hasTarget, maxDistToWalk); + } + +- public static BehaviorControl create(Predicate predicate, float f, boolean flag, int i) { +- return BehaviorBuilder.create((behaviorbuilder_instance) -> { +- BehaviorBuilder> behaviorbuilder = flag ? behaviorbuilder_instance.registered(MemoryModuleType.WALK_TARGET) : behaviorbuilder_instance.absent(MemoryModuleType.WALK_TARGET); ++ public static BehaviorControl create(Predicate canWalkToItem, float speedModifier, boolean hasTarget, int maxDistToWalk) { ++ return BehaviorBuilder.create((behaviorbuilder_b) -> { ++ BehaviorBuilder> behaviorbuilder = hasTarget ? behaviorbuilder_b.registered(MemoryModuleType.WALK_TARGET) : behaviorbuilder_b.absent(MemoryModuleType.WALK_TARGET); + +- return behaviorbuilder_instance.group(behaviorbuilder_instance.registered(MemoryModuleType.LOOK_TARGET), behaviorbuilder, behaviorbuilder_instance.present(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM), behaviorbuilder_instance.registered(MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS)).apply(behaviorbuilder_instance, (memoryaccessor, memoryaccessor1, memoryaccessor2, memoryaccessor3) -> { +- return (serverlevel, livingentity, j) -> { +- ItemEntity itementity = (ItemEntity) behaviorbuilder_instance.get(memoryaccessor2); ++ return behaviorbuilder_b.group(behaviorbuilder_b.registered(MemoryModuleType.LOOK_TARGET), behaviorbuilder, behaviorbuilder_b.present(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM), behaviorbuilder_b.registered(MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS)).apply(behaviorbuilder_b, (memoryaccessor, memoryaccessor1, memoryaccessor2, memoryaccessor3) -> { ++ return (worldserver, entityliving, j) -> { ++ ItemEntity entityitem = (ItemEntity) behaviorbuilder_b.get(memoryaccessor2); + +- if (behaviorbuilder_instance.tryGet(memoryaccessor3).isEmpty() && predicate.test(livingentity) && itementity.closerThan(livingentity, (double) i) && livingentity.level().getWorldBorder().isWithinBounds(itementity.blockPosition())) { +- WalkTarget walktarget = new WalkTarget(new EntityTracker(itementity, false), f, 0); ++ if (behaviorbuilder_b.tryGet(memoryaccessor3).isEmpty() && canWalkToItem.test(entityliving) && entityitem.closerThan(entityliving, (double) maxDistToWalk) && entityliving.level().getWorldBorder().isWithinBounds(entityitem.blockPosition())) { ++ // CraftBukkit start ++ if (entityliving instanceof net.minecraft.world.entity.animal.allay.Allay) { ++ org.bukkit.event.entity.EntityTargetEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTargetEvent(entityliving, entityitem, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_ENTITY); + +- memoryaccessor.set(new EntityTracker(itementity, true)); +- memoryaccessor1.set(walktarget); ++ if (event.isCancelled()) { ++ return false; ++ } ++ if (!(event.getTarget() instanceof ItemEntity)) { ++ memoryaccessor2.erase(); ++ } ++ ++ entityitem = (ItemEntity) ((org.bukkit.craftbukkit.entity.CraftEntity) event.getTarget()).getHandle(); ++ } ++ // CraftBukkit end ++ WalkTarget memorytarget = new WalkTarget(new EntityTracker(entityitem, false), speedModifier, 0); ++ ++ memoryaccessor.set(new EntityTracker(entityitem, true)); ++ memoryaccessor1.set(memorytarget); + return true; + } else { + return false; diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java.patch new file mode 100644 index 0000000000..e46f834276 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java.patch @@ -0,0 +1,194 @@ +--- a/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java ++++ b/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java +@@ -21,10 +21,15 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.gameevent.GameEvent; ++ ++// CraftBukkit start ++import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.CropBlock; + import net.minecraft.world.level.block.FarmBlock; +-import net.minecraft.world.level.block.state.BlockState; +-import net.minecraft.world.level.gameevent.GameEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class HarvestFarmland extends Behavior { + +@@ -40,113 +45,113 @@ + super(ImmutableMap.of(MemoryModuleType.LOOK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.SECONDARY_JOB_SITE, MemoryStatus.VALUE_PRESENT)); + } + +- @Override +- protected boolean checkExtraStartConditions(ServerLevel serverlevel, Villager villager) { +- if (!serverlevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ protected boolean checkExtraStartConditions(ServerLevel level, Villager owner) { ++ if (!level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { + return false; +- } else if (villager.getVillagerData().getProfession() != VillagerProfession.FARMER) { ++ } else if (owner.getVillagerData().getProfession() != VillagerProfession.FARMER) { + return false; + } else { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = villager.blockPosition().mutable(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = owner.blockPosition().mutable(); + + this.validFarmlandAroundVillager.clear(); + + for (int i = -1; i <= 1; ++i) { + for (int j = -1; j <= 1; ++j) { + for (int k = -1; k <= 1; ++k) { +- blockpos_mutableblockpos.set(villager.getX() + (double) i, villager.getY() + (double) j, villager.getZ() + (double) k); +- if (this.validPos(blockpos_mutableblockpos, serverlevel)) { +- this.validFarmlandAroundVillager.add(new BlockPos(blockpos_mutableblockpos)); ++ blockposition_mutableblockposition.set(owner.getX() + (double) i, owner.getY() + (double) j, owner.getZ() + (double) k); ++ if (this.validPos(blockposition_mutableblockposition, level)) { ++ this.validFarmlandAroundVillager.add(new BlockPos(blockposition_mutableblockposition)); + } + } + } + } + +- this.aboveFarmlandPos = this.getValidFarmland(serverlevel); ++ this.aboveFarmlandPos = this.getValidFarmland(level); + return this.aboveFarmlandPos != null; + } + } + + @Nullable +- private BlockPos getValidFarmland(ServerLevel serverlevel) { +- return this.validFarmlandAroundVillager.isEmpty() ? null : (BlockPos) this.validFarmlandAroundVillager.get(serverlevel.getRandom().nextInt(this.validFarmlandAroundVillager.size())); ++ private BlockPos getValidFarmland(ServerLevel serverLevel) { ++ return this.validFarmlandAroundVillager.isEmpty() ? null : (BlockPos) this.validFarmlandAroundVillager.get(serverLevel.getRandom().nextInt(this.validFarmlandAroundVillager.size())); + } + +- private boolean validPos(BlockPos blockpos, ServerLevel serverlevel) { +- BlockState blockstate = serverlevel.getBlockState(blockpos); +- Block block = blockstate.getBlock(); +- Block block1 = serverlevel.getBlockState(blockpos.below()).getBlock(); ++ private boolean validPos(BlockPos pos, ServerLevel serverLevel) { ++ IBlockData iblockdata = serverLevel.getBlockState(pos); ++ Block block = iblockdata.getBlock(); ++ Block block1 = serverLevel.getBlockState(pos.below()).getBlock(); + +- return block instanceof CropBlock && ((CropBlock) block).isMaxAge(blockstate) || blockstate.isAir() && block1 instanceof FarmBlock; ++ return block instanceof CropBlock && ((CropBlock) block).isMaxAge(iblockdata) || iblockdata.isAir() && block1 instanceof FarmBlock; + } + +- @Override +- protected void start(ServerLevel serverlevel, Villager villager, long i) { +- if (i > this.nextOkStartTime && this.aboveFarmlandPos != null) { +- villager.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (Object) (new BlockPosTracker(this.aboveFarmlandPos))); +- villager.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (Object) (new WalkTarget(new BlockPosTracker(this.aboveFarmlandPos), 0.5F, 1))); ++ protected void start(ServerLevel level, Villager entity, long gameTime) { ++ if (gameTime > this.nextOkStartTime && this.aboveFarmlandPos != null) { ++ entity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (new BlockPosTracker(this.aboveFarmlandPos))); // CraftBukkit - decompile error ++ entity.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (new WalkTarget(new BlockPosTracker(this.aboveFarmlandPos), 0.5F, 1))); // CraftBukkit - decompile error + } + + } + +- @Override +- protected void stop(ServerLevel serverlevel, Villager villager, long i) { +- villager.getBrain().eraseMemory(MemoryModuleType.LOOK_TARGET); +- villager.getBrain().eraseMemory(MemoryModuleType.WALK_TARGET); ++ protected void stop(ServerLevel level, Villager entity, long gameTime) { ++ entity.getBrain().eraseMemory(MemoryModuleType.LOOK_TARGET); ++ entity.getBrain().eraseMemory(MemoryModuleType.WALK_TARGET); + this.timeWorkedSoFar = 0; +- this.nextOkStartTime = i + 40L; ++ this.nextOkStartTime = gameTime + 40L; + } + +- @Override +- protected void tick(ServerLevel serverlevel, Villager villager, long i) { +- if (this.aboveFarmlandPos == null || this.aboveFarmlandPos.closerToCenterThan(villager.position(), 1.0D)) { +- if (this.aboveFarmlandPos != null && i > this.nextOkStartTime) { +- BlockState blockstate = serverlevel.getBlockState(this.aboveFarmlandPos); +- Block block = blockstate.getBlock(); +- Block block1 = serverlevel.getBlockState(this.aboveFarmlandPos.below()).getBlock(); ++ protected void tick(ServerLevel level, Villager owner, long gameTime) { ++ if (this.aboveFarmlandPos == null || this.aboveFarmlandPos.closerToCenterThan(owner.position(), 1.0D)) { ++ if (this.aboveFarmlandPos != null && gameTime > this.nextOkStartTime) { ++ IBlockData iblockdata = level.getBlockState(this.aboveFarmlandPos); ++ Block block = iblockdata.getBlock(); ++ Block block1 = level.getBlockState(this.aboveFarmlandPos.below()).getBlock(); + +- if (block instanceof CropBlock && ((CropBlock) block).isMaxAge(blockstate)) { +- serverlevel.destroyBlock(this.aboveFarmlandPos, true, villager); ++ if (block instanceof CropBlock && ((CropBlock) block).isMaxAge(iblockdata)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(owner, this.aboveFarmlandPos, Blocks.AIR.defaultBlockState())) { // CraftBukkit ++ level.destroyBlock(this.aboveFarmlandPos, true, owner); ++ } // CraftBukkit + } + +- if (blockstate.isAir() && block1 instanceof FarmBlock && villager.hasFarmSeeds()) { +- SimpleContainer simplecontainer = villager.getInventory(); ++ if (iblockdata.isAir() && block1 instanceof FarmBlock && owner.hasFarmSeeds()) { ++ SimpleContainer inventorysubcontainer = owner.getInventory(); + +- for (int j = 0; j < simplecontainer.getContainerSize(); ++j) { +- ItemStack itemstack = simplecontainer.getItem(j); ++ for (int j = 0; j < inventorysubcontainer.getContainerSize(); ++j) { ++ ItemStack itemstack = inventorysubcontainer.getItem(j); + boolean flag = false; + + if (!itemstack.isEmpty() && itemstack.is(ItemTags.VILLAGER_PLANTABLE_SEEDS)) { + Item item = itemstack.getItem(); + + if (item instanceof BlockItem) { +- BlockItem blockitem = (BlockItem) item; +- BlockState blockstate1 = blockitem.getBlock().defaultBlockState(); ++ BlockItem itemblock = (BlockItem) item; ++ IBlockData iblockdata1 = itemblock.getBlock().defaultBlockState(); + +- serverlevel.setBlockAndUpdate(this.aboveFarmlandPos, blockstate1); +- serverlevel.gameEvent(GameEvent.BLOCK_PLACE, this.aboveFarmlandPos, GameEvent.Context.of(villager, blockstate1)); ++ if (CraftEventFactory.callEntityChangeBlockEvent(owner, this.aboveFarmlandPos, iblockdata1)) { // CraftBukkit ++ level.setBlockAndUpdate(this.aboveFarmlandPos, iblockdata1); ++ level.gameEvent(GameEvent.BLOCK_PLACE, this.aboveFarmlandPos, GameEvent.Context.of(owner, iblockdata1)); + flag = true; ++ } // CraftBukkit + } + } + + if (flag) { +- serverlevel.playSound((Player) null, (double) this.aboveFarmlandPos.getX(), (double) this.aboveFarmlandPos.getY(), (double) this.aboveFarmlandPos.getZ(), SoundEvents.CROP_PLANTED, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.playSound((Player) null, (double) this.aboveFarmlandPos.getX(), (double) this.aboveFarmlandPos.getY(), (double) this.aboveFarmlandPos.getZ(), SoundEvents.CROP_PLANTED, SoundSource.BLOCKS, 1.0F, 1.0F); + itemstack.shrink(1); + if (itemstack.isEmpty()) { +- simplecontainer.setItem(j, ItemStack.EMPTY); ++ inventorysubcontainer.setItem(j, ItemStack.EMPTY); + } + break; + } + } + } + +- if (block instanceof CropBlock && !((CropBlock) block).isMaxAge(blockstate)) { ++ if (block instanceof CropBlock && !((CropBlock) block).isMaxAge(iblockdata)) { + this.validFarmlandAroundVillager.remove(this.aboveFarmlandPos); +- this.aboveFarmlandPos = this.getValidFarmland(serverlevel); ++ this.aboveFarmlandPos = this.getValidFarmland(level); + if (this.aboveFarmlandPos != null) { +- this.nextOkStartTime = i + 20L; +- villager.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (Object) (new WalkTarget(new BlockPosTracker(this.aboveFarmlandPos), 0.5F, 1))); +- villager.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (Object) (new BlockPosTracker(this.aboveFarmlandPos))); ++ this.nextOkStartTime = gameTime + 20L; ++ owner.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (new WalkTarget(new BlockPosTracker(this.aboveFarmlandPos), 0.5F, 1))); // CraftBukkit - decompile error ++ owner.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (new BlockPosTracker(this.aboveFarmlandPos))); // CraftBukkit - decompile error + } + } + } +@@ -155,8 +160,7 @@ + } + } + +- @Override +- protected boolean canStillUse(ServerLevel serverlevel, Villager villager, long i) { ++ protected boolean canStillUse(ServerLevel level, Villager entity, long gameTime) { + return this.timeWorkedSoFar < 200; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java.patch new file mode 100644 index 0000000000..bdad18f8e6 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java.patch @@ -0,0 +1,224 @@ +--- a/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java ++++ b/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java +@@ -18,7 +18,7 @@ + import net.minecraft.world.entity.ai.behavior.declarative.MemoryAccessor; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + import net.minecraft.world.level.block.DoorBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.pathfinder.Node; + import net.minecraft.world.level.pathfinder.Path; + import org.apache.commons.lang3.mutable.MutableInt; +@@ -36,53 +36,67 @@ + MutableObject mutableobject = new MutableObject((Object) null); + MutableInt mutableint = new MutableInt(0); + +- return BehaviorBuilder.create((behaviorbuilder_instance) -> { +- return behaviorbuilder_instance.group(behaviorbuilder_instance.present(MemoryModuleType.PATH), behaviorbuilder_instance.registered(MemoryModuleType.DOORS_TO_CLOSE), behaviorbuilder_instance.registered(MemoryModuleType.NEAREST_LIVING_ENTITIES)).apply(behaviorbuilder_instance, (memoryaccessor, memoryaccessor1, memoryaccessor2) -> { +- return (serverlevel, livingentity, i) -> { +- Path path = (Path) behaviorbuilder_instance.get(memoryaccessor); +- Optional> optional = behaviorbuilder_instance.tryGet(memoryaccessor1); ++ return BehaviorBuilder.create((behaviorbuilder_b) -> { ++ return behaviorbuilder_b.group(behaviorbuilder_b.present(MemoryModuleType.PATH), behaviorbuilder_b.registered(MemoryModuleType.DOORS_TO_CLOSE), behaviorbuilder_b.registered(MemoryModuleType.NEAREST_LIVING_ENTITIES)).apply(behaviorbuilder_b, (memoryaccessor, memoryaccessor1, memoryaccessor2) -> { ++ return (worldserver, entityliving, i) -> { ++ Path pathentity = (Path) behaviorbuilder_b.get(memoryaccessor); ++ Optional> optional = behaviorbuilder_b.tryGet(memoryaccessor1); + +- if (!path.notStarted() && !path.isDone()) { +- if (Objects.equals(mutableobject.getValue(), path.getNextNode())) { ++ if (!pathentity.notStarted() && !pathentity.isDone()) { ++ if (Objects.equals(mutableobject.getValue(), pathentity.getNextNode())) { + mutableint.setValue(20); + } else if (mutableint.decrementAndGet() > 0) { + return false; + } + +- mutableobject.setValue(path.getNextNode()); +- Node node = path.getPreviousNode(); +- Node node1 = path.getNextNode(); +- BlockPos blockpos = node.asBlockPos(); +- BlockState blockstate = serverlevel.getBlockState(blockpos); ++ mutableobject.setValue(pathentity.getNextNode()); ++ Node pathpoint = pathentity.getPreviousNode(); ++ Node pathpoint1 = pathentity.getNextNode(); ++ BlockPos blockposition = pathpoint.asBlockPos(); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); + +- if (blockstate.is(BlockTags.WOODEN_DOORS, (blockbehaviour_blockstatebase) -> { +- return blockbehaviour_blockstatebase.getBlock() instanceof DoorBlock; ++ if (iblockdata.is(BlockTags.WOODEN_DOORS, (blockbase_blockdata) -> { ++ return blockbase_blockdata.getBlock() instanceof DoorBlock; + })) { +- DoorBlock doorblock = (DoorBlock) blockstate.getBlock(); ++ DoorBlock blockdoor = (DoorBlock) iblockdata.getBlock(); + +- if (!doorblock.isOpen(blockstate)) { +- doorblock.setOpen(livingentity, serverlevel, blockstate, blockpos, true); ++ if (!blockdoor.isOpen(iblockdata)) { ++ // CraftBukkit start - entities opening doors ++ org.bukkit.event.entity.EntityInteractEvent event = new org.bukkit.event.entity.EntityInteractEvent(entityliving.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(entityliving.level(), blockposition)); ++ entityliving.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ blockdoor.setOpen(entityliving, worldserver, iblockdata, blockposition, true); + } + +- optional = rememberDoorToClose(memoryaccessor1, optional, serverlevel, blockpos); ++ optional = rememberDoorToClose(memoryaccessor1, optional, worldserver, blockposition); + } + +- BlockPos blockpos1 = node1.asBlockPos(); +- BlockState blockstate1 = serverlevel.getBlockState(blockpos1); ++ BlockPos blockposition1 = pathpoint1.asBlockPos(); ++ IBlockData iblockdata1 = worldserver.getBlockState(blockposition1); + +- if (blockstate1.is(BlockTags.WOODEN_DOORS, (blockbehaviour_blockstatebase) -> { +- return blockbehaviour_blockstatebase.getBlock() instanceof DoorBlock; ++ if (iblockdata1.is(BlockTags.WOODEN_DOORS, (blockbase_blockdata) -> { ++ return blockbase_blockdata.getBlock() instanceof DoorBlock; + })) { +- DoorBlock doorblock1 = (DoorBlock) blockstate1.getBlock(); ++ DoorBlock blockdoor1 = (DoorBlock) iblockdata1.getBlock(); + +- if (!doorblock1.isOpen(blockstate1)) { +- doorblock1.setOpen(livingentity, serverlevel, blockstate1, blockpos1, true); +- optional = rememberDoorToClose(memoryaccessor1, optional, serverlevel, blockpos1); ++ if (!blockdoor1.isOpen(iblockdata1)) { ++ // CraftBukkit start - entities opening doors ++ org.bukkit.event.entity.EntityInteractEvent event = new org.bukkit.event.entity.EntityInteractEvent(entityliving.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(entityliving.level(), blockposition1)); ++ entityliving.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ blockdoor1.setOpen(entityliving, worldserver, iblockdata1, blockposition1, true); ++ optional = rememberDoorToClose(memoryaccessor1, optional, worldserver, blockposition1); + } + } + + optional.ifPresent((set) -> { +- closeDoorsThatIHaveOpenedOrPassedThrough(serverlevel, livingentity, node, node1, set, behaviorbuilder_instance.tryGet(memoryaccessor2)); ++ closeDoorsThatIHaveOpenedOrPassedThrough(worldserver, entityliving, pathpoint, pathpoint1, set, behaviorbuilder_b.tryGet(memoryaccessor2)); + }); + return true; + } else { +@@ -93,32 +107,32 @@ + }); + } + +- public static void closeDoorsThatIHaveOpenedOrPassedThrough(ServerLevel serverlevel, LivingEntity livingentity, @Nullable Node node, @Nullable Node node1, Set set, Optional> optional) { +- Iterator iterator = set.iterator(); ++ public static void closeDoorsThatIHaveOpenedOrPassedThrough(ServerLevel level, LivingEntity entity, @Nullable Node previous, @Nullable Node next, Set doorPositions, Optional> nearestLivingEntities) { ++ Iterator iterator = doorPositions.iterator(); + + while (iterator.hasNext()) { + GlobalPos globalpos = (GlobalPos) iterator.next(); +- BlockPos blockpos = globalpos.pos(); ++ BlockPos blockposition = globalpos.pos(); + +- if ((node == null || !node.asBlockPos().equals(blockpos)) && (node1 == null || !node1.asBlockPos().equals(blockpos))) { +- if (isDoorTooFarAway(serverlevel, livingentity, globalpos)) { ++ if ((previous == null || !previous.asBlockPos().equals(blockposition)) && (next == null || !next.asBlockPos().equals(blockposition))) { ++ if (isDoorTooFarAway(level, entity, globalpos)) { + iterator.remove(); + } else { +- BlockState blockstate = serverlevel.getBlockState(blockpos); ++ IBlockData iblockdata = level.getBlockState(blockposition); + +- if (!blockstate.is(BlockTags.WOODEN_DOORS, (blockbehaviour_blockstatebase) -> { +- return blockbehaviour_blockstatebase.getBlock() instanceof DoorBlock; ++ if (!iblockdata.is(BlockTags.WOODEN_DOORS, (blockbase_blockdata) -> { ++ return blockbase_blockdata.getBlock() instanceof DoorBlock; + })) { + iterator.remove(); + } else { +- DoorBlock doorblock = (DoorBlock) blockstate.getBlock(); ++ DoorBlock blockdoor = (DoorBlock) iblockdata.getBlock(); + +- if (!doorblock.isOpen(blockstate)) { ++ if (!blockdoor.isOpen(iblockdata)) { + iterator.remove(); +- } else if (areOtherMobsComingThroughDoor(livingentity, blockpos, optional)) { ++ } else if (areOtherMobsComingThroughDoor(entity, blockposition, nearestLivingEntities)) { + iterator.remove(); + } else { +- doorblock.setOpen(livingentity, serverlevel, blockstate, blockpos, false); ++ blockdoor.setOpen(entity, level, iblockdata, blockposition, false); + iterator.remove(); + } + } +@@ -128,52 +142,52 @@ + + } + +- private static boolean areOtherMobsComingThroughDoor(LivingEntity livingentity, BlockPos blockpos, Optional> optional) { +- return optional.isEmpty() ? false : ((List) optional.get()).stream().filter((livingentity1) -> { +- return livingentity1.getType() == livingentity.getType(); +- }).filter((livingentity1) -> { +- return blockpos.closerToCenterThan(livingentity1.position(), 2.0D); +- }).anyMatch((livingentity1) -> { +- return isMobComingThroughDoor(livingentity1.getBrain(), blockpos); ++ private static boolean areOtherMobsComingThroughDoor(LivingEntity entity, BlockPos pos, Optional> nearestLivingEntities) { ++ return nearestLivingEntities.isEmpty() ? false : (nearestLivingEntities.get()).stream().filter((entityliving1) -> { // CraftBukkit - decompile error ++ return entityliving1.getType() == entity.getType(); ++ }).filter((entityliving1) -> { ++ return pos.closerToCenterThan(entityliving1.position(), 2.0D); ++ }).anyMatch((entityliving1) -> { ++ return isMobComingThroughDoor(entityliving1.getBrain(), pos); + }); + } + +- private static boolean isMobComingThroughDoor(Brain brain, BlockPos blockpos) { ++ private static boolean isMobComingThroughDoor(Brain brain, BlockPos pos) { + if (!brain.hasMemoryValue(MemoryModuleType.PATH)) { + return false; + } else { +- Path path = (Path) brain.getMemory(MemoryModuleType.PATH).get(); ++ Path pathentity = (Path) brain.getMemory(MemoryModuleType.PATH).get(); + +- if (path.isDone()) { ++ if (pathentity.isDone()) { + return false; + } else { +- Node node = path.getPreviousNode(); ++ Node pathpoint = pathentity.getPreviousNode(); + +- if (node == null) { ++ if (pathpoint == null) { + return false; + } else { +- Node node1 = path.getNextNode(); ++ Node pathpoint1 = pathentity.getNextNode(); + +- return blockpos.equals(node.asBlockPos()) || blockpos.equals(node1.asBlockPos()); ++ return pos.equals(pathpoint.asBlockPos()) || pos.equals(pathpoint1.asBlockPos()); + } + } + } + } + +- private static boolean isDoorTooFarAway(ServerLevel serverlevel, LivingEntity livingentity, GlobalPos globalpos) { +- return globalpos.dimension() != serverlevel.dimension() || !globalpos.pos().closerToCenterThan(livingentity.position(), 3.0D); ++ private static boolean isDoorTooFarAway(ServerLevel level, LivingEntity entity, GlobalPos pos) { ++ return pos.dimension() != level.dimension() || !pos.pos().closerToCenterThan(entity.position(), 3.0D); + } + +- private static Optional> rememberDoorToClose(MemoryAccessor> memoryaccessor, Optional> optional, ServerLevel serverlevel, BlockPos blockpos) { +- GlobalPos globalpos = GlobalPos.of(serverlevel.dimension(), blockpos); ++ private static Optional> rememberDoorToClose(MemoryAccessor> doorsToClose, Optional> doorPositions, ServerLevel level, BlockPos pos) { ++ GlobalPos globalpos = GlobalPos.of(level.dimension(), pos); + +- return Optional.of((Set) optional.map((set) -> { ++ return Optional.of((Set) doorPositions.map((set) -> { + set.add(globalpos); + return set; + }).orElseGet(() -> { + Set set = Sets.newHashSet(new GlobalPos[]{globalpos}); + +- memoryaccessor.set(set); ++ doorsToClose.set(set); + return set; + })); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java.patch new file mode 100644 index 0000000000..06b749cbaa --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java.patch @@ -0,0 +1,242 @@ +--- a/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java ++++ b/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java +@@ -13,6 +13,7 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundSource; + import net.minecraft.util.Mth; +@@ -29,6 +30,10 @@ + import net.minecraft.world.level.pathfinder.Path; + import net.minecraft.world.level.pathfinder.WalkNodeEvaluator; + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end + + public class PrepareRamNearestTarget extends Behavior { + +@@ -43,69 +48,72 @@ + private Optional reachedRamPositionTimestamp = Optional.empty(); + private Optional ramCandidate = Optional.empty(); + +- public PrepareRamNearestTarget(ToIntFunction tointfunction, int i, int j, float f, TargetingConditions targetingconditions, int k, Function function) { ++ public PrepareRamNearestTarget(ToIntFunction getCooldownOnFall, int minRamDistance, int maxRamDistance, float walkSpeed, TargetingConditions ramTargeting, int ramPrepareTime, Function getPrepareRamSound) { + super(ImmutableMap.of(MemoryModuleType.LOOK_TARGET, MemoryStatus.REGISTERED, MemoryModuleType.RAM_COOLDOWN_TICKS, MemoryStatus.VALUE_ABSENT, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryStatus.VALUE_PRESENT, MemoryModuleType.RAM_TARGET, MemoryStatus.VALUE_ABSENT), 160); +- this.getCooldownOnFail = tointfunction; +- this.minRamDistance = i; +- this.maxRamDistance = j; +- this.walkSpeed = f; +- this.ramTargeting = targetingconditions; +- this.ramPrepareTime = k; +- this.getPrepareRamSound = function; ++ this.getCooldownOnFail = getCooldownOnFall; ++ this.minRamDistance = minRamDistance; ++ this.maxRamDistance = maxRamDistance; ++ this.walkSpeed = walkSpeed; ++ this.ramTargeting = ramTargeting; ++ this.ramPrepareTime = ramPrepareTime; ++ this.getPrepareRamSound = getPrepareRamSound; + } + +- @Override +- protected void start(ServerLevel serverlevel, PathfinderMob pathfindermob, long i) { +- Brain brain = pathfindermob.getBrain(); ++ protected void start(ServerLevel level, PathfinderMob entity, long gameTime) { ++ Brain behaviorcontroller = entity.getBrain(); + +- brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES).flatMap((nearestvisiblelivingentities) -> { +- return nearestvisiblelivingentities.findClosest((livingentity) -> { +- return this.ramTargeting.test(pathfindermob, livingentity); ++ behaviorcontroller.getMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES).flatMap((nearestvisiblelivingentities) -> { ++ return nearestvisiblelivingentities.findClosest((entityliving) -> { ++ return this.ramTargeting.test(entity, entityliving); + }); +- }).ifPresent((livingentity) -> { +- this.chooseRamPosition(pathfindermob, livingentity); ++ }).ifPresent((entityliving) -> { ++ // CraftBukkit start ++ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entity, entityliving, (entityliving instanceof ServerPlayer) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.CLOSEST_ENTITY); ++ if (event.isCancelled() || event.getTarget() == null) { ++ return; ++ } ++ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ // CraftBukkit end ++ this.chooseRamPosition(entity, entityliving); + }); + } + +- @Override +- protected void stop(ServerLevel serverlevel, E e0, long i) { +- Brain brain = e0.getBrain(); ++ protected void stop(ServerLevel level, E entity, long gameTime) { ++ Brain behaviorcontroller = entity.getBrain(); + +- if (!brain.hasMemoryValue(MemoryModuleType.RAM_TARGET)) { +- serverlevel.broadcastEntityEvent(e0, (byte) 59); +- brain.setMemory(MemoryModuleType.RAM_COOLDOWN_TICKS, (Object) this.getCooldownOnFail.applyAsInt(e0)); ++ if (!behaviorcontroller.hasMemoryValue(MemoryModuleType.RAM_TARGET)) { ++ level.broadcastEntityEvent(entity, (byte) 59); ++ behaviorcontroller.setMemory(MemoryModuleType.RAM_COOLDOWN_TICKS, this.getCooldownOnFail.applyAsInt(entity)); // CraftBukkit - decompile error + } + + } + +- @Override +- protected boolean canStillUse(ServerLevel serverlevel, PathfinderMob pathfindermob, long i) { ++ protected boolean canStillUse(ServerLevel level, PathfinderMob entity, long gameTime) { + return this.ramCandidate.isPresent() && ((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getTarget().isAlive(); + } + +- @Override +- protected void tick(ServerLevel serverlevel, E e0, long i) { ++ protected void tick(ServerLevel level, E owner, long gameTime) { + if (!this.ramCandidate.isEmpty()) { +- e0.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (Object) (new WalkTarget(((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getStartPosition(), this.walkSpeed, 0))); +- e0.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (Object) (new EntityTracker(((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getTarget(), true))); ++ owner.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (new WalkTarget(((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getStartPosition(), this.walkSpeed, 0))); // CraftBukkit - decompile error ++ owner.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (new EntityTracker(((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getTarget(), true))); // CraftBukkit - decompile error + boolean flag = !((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getTarget().blockPosition().equals(((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getTargetPosition()); + + if (flag) { +- serverlevel.broadcastEntityEvent(e0, (byte) 59); +- e0.getNavigation().stop(); +- this.chooseRamPosition(e0, ((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).target); ++ level.broadcastEntityEvent(owner, (byte) 59); ++ owner.getNavigation().stop(); ++ this.chooseRamPosition(owner, ((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).target); + } else { +- BlockPos blockpos = e0.blockPosition(); ++ BlockPos blockposition = owner.blockPosition(); + +- if (blockpos.equals(((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getStartPosition())) { +- serverlevel.broadcastEntityEvent(e0, (byte) 58); ++ if (blockposition.equals(((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getStartPosition())) { ++ level.broadcastEntityEvent(owner, (byte) 58); + if (this.reachedRamPositionTimestamp.isEmpty()) { +- this.reachedRamPositionTimestamp = Optional.of(i); ++ this.reachedRamPositionTimestamp = Optional.of(gameTime); + } + +- if (i - (Long) this.reachedRamPositionTimestamp.get() >= (long) this.ramPrepareTime) { +- e0.getBrain().setMemory(MemoryModuleType.RAM_TARGET, (Object) this.getEdgeOfBlock(blockpos, ((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getTargetPosition())); +- serverlevel.playSound((Player) null, (Entity) e0, (SoundEvent) this.getPrepareRamSound.apply(e0), SoundSource.NEUTRAL, 1.0F, e0.getVoicePitch()); ++ if (gameTime - (Long) this.reachedRamPositionTimestamp.get() >= (long) this.ramPrepareTime) { ++ owner.getBrain().setMemory(MemoryModuleType.RAM_TARGET, this.getEdgeOfBlock(blockposition, ((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getTargetPosition())); // CraftBukkit - decompile error ++ level.playSound((Player) null, (Entity) owner, (SoundEvent) this.getPrepareRamSound.apply(owner), SoundSource.NEUTRAL, 1.0F, owner.getVoicePitch()); + this.ramCandidate = Optional.empty(); + } + } +@@ -114,68 +122,68 @@ + } + } + +- private Vec3 getEdgeOfBlock(BlockPos blockpos, BlockPos blockpos1) { ++ private Vec3 getEdgeOfBlock(BlockPos pos, BlockPos other) { + double d0 = 0.5D; +- double d1 = 0.5D * (double) Mth.sign((double) (blockpos1.getX() - blockpos.getX())); +- double d2 = 0.5D * (double) Mth.sign((double) (blockpos1.getZ() - blockpos.getZ())); ++ double d1 = 0.5D * (double) Mth.sign((double) (other.getX() - pos.getX())); ++ double d2 = 0.5D * (double) Mth.sign((double) (other.getZ() - pos.getZ())); + +- return Vec3.atBottomCenterOf(blockpos1).add(d1, 0.0D, d2); ++ return Vec3.atBottomCenterOf(other).add(d1, 0.0D, d2); + } + +- private Optional calculateRammingStartPosition(PathfinderMob pathfindermob, LivingEntity livingentity) { +- BlockPos blockpos = livingentity.blockPosition(); ++ private Optional calculateRammingStartPosition(PathfinderMob pathfinder, LivingEntity entity) { ++ BlockPos blockposition = entity.blockPosition(); + +- if (!this.isWalkableBlock(pathfindermob, blockpos)) { ++ if (!this.isWalkableBlock(pathfinder, blockposition)) { + return Optional.empty(); + } else { + List list = Lists.newArrayList(); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = blockpos.mutable(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = blockposition.mutable(); + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); ++ Direction enumdirection = (Direction) iterator.next(); + +- blockpos_mutableblockpos.set(blockpos); ++ blockposition_mutableblockposition.set(blockposition); + int i = 0; + + while (true) { + if (i < this.maxRamDistance) { +- if (this.isWalkableBlock(pathfindermob, blockpos_mutableblockpos.move(direction))) { ++ if (this.isWalkableBlock(pathfinder, blockposition_mutableblockposition.move(enumdirection))) { + ++i; + continue; + } + +- blockpos_mutableblockpos.move(direction.getOpposite()); ++ blockposition_mutableblockposition.move(enumdirection.getOpposite()); + } + +- if (blockpos_mutableblockpos.distManhattan(blockpos) >= this.minRamDistance) { +- list.add(blockpos_mutableblockpos.immutable()); ++ if (blockposition_mutableblockposition.distManhattan(blockposition) >= this.minRamDistance) { ++ list.add(blockposition_mutableblockposition.immutable()); + } + break; + } + } + +- PathNavigation pathnavigation = pathfindermob.getNavigation(); +- Stream stream = list.stream(); +- BlockPos blockpos1 = pathfindermob.blockPosition(); ++ PathNavigation navigationabstract = pathfinder.getNavigation(); ++ Stream stream = list.stream(); // CraftBukkit - decompile error ++ BlockPos blockposition1 = pathfinder.blockPosition(); + +- Objects.requireNonNull(blockpos1); +- return stream.sorted(Comparator.comparingDouble(blockpos1::distSqr)).filter((blockpos2) -> { +- Path path = pathnavigation.createPath(blockpos2, 0); ++ Objects.requireNonNull(blockposition1); ++ return stream.sorted(Comparator.comparingDouble(blockposition1::distSqr)).filter((blockposition2) -> { ++ Path pathentity = navigationabstract.createPath(blockposition2, 0); + +- return path != null && path.canReach(); ++ return pathentity != null && pathentity.canReach(); + }).findFirst(); + } + } + +- private boolean isWalkableBlock(PathfinderMob pathfindermob, BlockPos blockpos) { +- return pathfindermob.getNavigation().isStableDestination(blockpos) && pathfindermob.getPathfindingMalus(WalkNodeEvaluator.getBlockPathTypeStatic(pathfindermob.level(), blockpos.mutable())) == 0.0F; ++ private boolean isWalkableBlock(PathfinderMob pathfinder, BlockPos pos) { ++ return pathfinder.getNavigation().isStableDestination(pos) && pathfinder.getPathfindingMalus(WalkNodeEvaluator.getBlockPathTypeStatic(pathfinder.level(), pos.mutable())) == 0.0F; + } + +- private void chooseRamPosition(PathfinderMob pathfindermob, LivingEntity livingentity) { ++ private void chooseRamPosition(PathfinderMob pathfinder, LivingEntity entity) { + this.reachedRamPositionTimestamp = Optional.empty(); +- this.ramCandidate = this.calculateRammingStartPosition(pathfindermob, livingentity).map((blockpos) -> { +- return new PrepareRamNearestTarget.RamCandidate(blockpos, livingentity.blockPosition(), livingentity); ++ this.ramCandidate = this.calculateRammingStartPosition(pathfinder, entity).map((blockposition) -> { ++ return new PrepareRamNearestTarget.RamCandidate(blockposition, entity.blockPosition(), entity); + }); + } + +@@ -185,10 +193,10 @@ + private final BlockPos targetPosition; + final LivingEntity target; + +- public RamCandidate(BlockPos blockpos, BlockPos blockpos1, LivingEntity livingentity) { +- this.startPosition = blockpos; +- this.targetPosition = blockpos1; +- this.target = livingentity; ++ public RamCandidate(BlockPos startPosition, BlockPos targetPosition, LivingEntity target) { ++ this.startPosition = startPosition; ++ this.targetPosition = targetPosition; ++ this.target = target; + } + + public BlockPos getStartPosition() { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/ResetProfession.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/ResetProfession.java.patch new file mode 100644 index 0000000000..710a6595f5 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/ResetProfession.java.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/world/entity/ai/behavior/ResetProfession.java ++++ b/net/minecraft/world/entity/ai/behavior/ResetProfession.java +@@ -6,19 +6,32 @@ + import net.minecraft.world.entity.npc.VillagerData; + import net.minecraft.world.entity.npc.VillagerProfession; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftVillager; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.VillagerCareerChangeEvent; ++// CraftBukkit end ++ + public class ResetProfession { + + public ResetProfession() {} + + public static BehaviorControl create() { +- return BehaviorBuilder.create((behaviorbuilder_instance) -> { +- return behaviorbuilder_instance.group(behaviorbuilder_instance.absent(MemoryModuleType.JOB_SITE)).apply(behaviorbuilder_instance, (memoryaccessor) -> { +- return (serverlevel, villager, i) -> { +- VillagerData villagerdata = villager.getVillagerData(); ++ return BehaviorBuilder.create((behaviorbuilder_b) -> { ++ return behaviorbuilder_b.group(behaviorbuilder_b.absent(MemoryModuleType.JOB_SITE)).apply(behaviorbuilder_b, (memoryaccessor) -> { ++ return (worldserver, entityvillager, i) -> { ++ VillagerData villagerdata = entityvillager.getVillagerData(); + +- if (villagerdata.getProfession() != VillagerProfession.NONE && villagerdata.getProfession() != VillagerProfession.NITWIT && villager.getVillagerXp() == 0 && villagerdata.getLevel() <= 1) { +- villager.setVillagerData(villager.getVillagerData().setProfession(VillagerProfession.NONE)); +- villager.refreshBrain(serverlevel); ++ if (villagerdata.getProfession() != VillagerProfession.NONE && villagerdata.getProfession() != VillagerProfession.NITWIT && entityvillager.getVillagerXp() == 0 && villagerdata.getLevel() <= 1) { ++ // CraftBukkit start ++ VillagerCareerChangeEvent event = CraftEventFactory.callVillagerCareerChangeEvent(entityvillager, CraftVillager.CraftProfession.minecraftToBukkit(VillagerProfession.NONE), VillagerCareerChangeEvent.ChangeReason.LOSING_JOB); ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ entityvillager.setVillagerData(entityvillager.getVillagerData().setProfession(CraftVillager.CraftProfession.bukkitToMinecraft(event.getProfession()))); ++ // CraftBukkit end ++ entityvillager.refreshBrain(worldserver); + return true; + } else { + return false; diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/StartAttacking.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/StartAttacking.java.patch new file mode 100644 index 0000000000..c39091b3d5 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/StartAttacking.java.patch @@ -0,0 +1,70 @@ +--- a/net/minecraft/world/entity/ai/behavior/StartAttacking.java ++++ b/net/minecraft/world/entity/ai/behavior/StartAttacking.java +@@ -3,39 +3,55 @@ + import java.util.Optional; + import java.util.function.Function; + import java.util.function.Predicate; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; + import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end + + public class StartAttacking { + + public StartAttacking() {} + +- public static BehaviorControl create(Function> function) { +- return create((mob) -> { ++ public static BehaviorControl create(Function> targetFinder) { ++ return create((entityinsentient) -> { + return true; +- }, function); ++ }, targetFinder); + } + +- public static BehaviorControl create(Predicate predicate, Function> function) { +- return BehaviorBuilder.create((behaviorbuilder_instance) -> { +- return behaviorbuilder_instance.group(behaviorbuilder_instance.absent(MemoryModuleType.ATTACK_TARGET), behaviorbuilder_instance.registered(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)).apply(behaviorbuilder_instance, (memoryaccessor, memoryaccessor1) -> { +- return (serverlevel, mob, i) -> { +- if (!predicate.test(mob)) { ++ public static BehaviorControl create(Predicate canAttack, Function> targetFinder) { ++ return BehaviorBuilder.create((behaviorbuilder_b) -> { ++ return behaviorbuilder_b.group(behaviorbuilder_b.absent(MemoryModuleType.ATTACK_TARGET), behaviorbuilder_b.registered(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)).apply(behaviorbuilder_b, (memoryaccessor, memoryaccessor1) -> { ++ return (worldserver, entityinsentient, i) -> { ++ if (!canAttack.test(entityinsentient)) { + return false; + } else { +- Optional optional = (Optional) function.apply(mob); ++ Optional optional = (Optional) targetFinder.apply(entityinsentient); + + if (optional.isEmpty()) { + return false; + } else { +- LivingEntity livingentity = (LivingEntity) optional.get(); ++ LivingEntity entityliving = (LivingEntity) optional.get(); + +- if (!mob.canAttack(livingentity)) { ++ if (!entityinsentient.canAttack(entityliving)) { + return false; + } else { +- memoryaccessor.set(livingentity); ++ // CraftBukkit start ++ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entityinsentient, entityliving, (entityliving instanceof ServerPlayer) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.CLOSEST_ENTITY); ++ if (event.isCancelled()) { ++ return false; ++ } ++ if (event.getTarget() == null) { ++ memoryaccessor.erase(); ++ return true; ++ } ++ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ // CraftBukkit end ++ memoryaccessor.set(entityliving); + memoryaccessor1.erase(); + return true; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java.patch new file mode 100644 index 0000000000..1b23c07bc1 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java.patch @@ -0,0 +1,85 @@ +--- a/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java ++++ b/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java +@@ -8,40 +8,58 @@ + import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end ++ + public class StopAttackingIfTargetInvalid { + + private static final int TIMEOUT_TO_GET_WITHIN_ATTACK_RANGE = 200; + + public StopAttackingIfTargetInvalid() {} + +- public static BehaviorControl create(BiConsumer biconsumer) { +- return create((livingentity) -> { ++ public static BehaviorControl create(BiConsumer onStopAttacking) { ++ return create((entityliving) -> { + return false; +- }, biconsumer, true); ++ }, onStopAttacking, true); + } + +- public static BehaviorControl create(Predicate predicate) { +- return create(predicate, (mob, livingentity) -> { ++ public static BehaviorControl create(Predicate canStopAttacking) { ++ return create(canStopAttacking, (entityinsentient, entityliving) -> { + }, true); + } + + public static BehaviorControl create() { +- return create((livingentity) -> { ++ return create((entityliving) -> { + return false; +- }, (mob, livingentity) -> { ++ }, (entityinsentient, entityliving) -> { + }, true); + } + +- public static BehaviorControl create(Predicate predicate, BiConsumer biconsumer, boolean flag) { +- return BehaviorBuilder.create((behaviorbuilder_instance) -> { +- return behaviorbuilder_instance.group(behaviorbuilder_instance.present(MemoryModuleType.ATTACK_TARGET), behaviorbuilder_instance.registered(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)).apply(behaviorbuilder_instance, (memoryaccessor, memoryaccessor1) -> { +- return (serverlevel, mob, i) -> { +- LivingEntity livingentity = (LivingEntity) behaviorbuilder_instance.get(memoryaccessor); ++ public static BehaviorControl create(Predicate canStopAttacking, BiConsumer onStopAttacking, boolean canGrowTiredOfTryingToReachTarget) { ++ return BehaviorBuilder.create((behaviorbuilder_b) -> { ++ return behaviorbuilder_b.group(behaviorbuilder_b.present(MemoryModuleType.ATTACK_TARGET), behaviorbuilder_b.registered(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)).apply(behaviorbuilder_b, (memoryaccessor, memoryaccessor1) -> { ++ return (worldserver, entityinsentient, i) -> { ++ LivingEntity entityliving = (LivingEntity) behaviorbuilder_b.get(memoryaccessor); + +- if (mob.canAttack(livingentity) && (!flag || !isTiredOfTryingToReachTarget(mob, behaviorbuilder_instance.tryGet(memoryaccessor1))) && livingentity.isAlive() && livingentity.level() == mob.level() && !predicate.test(livingentity)) { ++ if (entityinsentient.canAttack(entityliving) && (!canGrowTiredOfTryingToReachTarget || !isTiredOfTryingToReachTarget(entityinsentient, behaviorbuilder_b.tryGet(memoryaccessor1))) && entityliving.isAlive() && entityliving.level() == entityinsentient.level() && !canStopAttacking.test(entityliving)) { + return true; + } else { +- biconsumer.accept(mob, livingentity); ++ // CraftBukkit start ++ LivingEntity old = entityinsentient.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); ++ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entityinsentient, null, (old != null && !old.isAlive()) ? EntityTargetEvent.TargetReason.TARGET_DIED : EntityTargetEvent.TargetReason.FORGOT_TARGET); ++ if (event.isCancelled()) { ++ return false; ++ } ++ if (event.getTarget() == null) { ++ memoryaccessor.erase(); ++ return true; ++ } ++ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ // CraftBukkit end ++ onStopAttacking.accept(entityinsentient, entityliving); + memoryaccessor.erase(); + return true; + } +@@ -50,7 +68,7 @@ + }); + } + +- private static boolean isTiredOfTryingToReachTarget(LivingEntity livingentity, Optional optional) { +- return optional.isPresent() && livingentity.level().getGameTime() - (Long) optional.get() > 200L; ++ private static boolean isTiredOfTryingToReachTarget(LivingEntity entity, Optional timeSinceInvalidTarget) { ++ return timeSinceInvalidTarget.isPresent() && entity.level().getGameTime() - (Long) timeSinceInvalidTarget.get() > 200L; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java.patch new file mode 100644 index 0000000000..ba7b4eae76 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java.patch @@ -0,0 +1,188 @@ +--- a/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java ++++ b/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java +@@ -17,6 +17,10 @@ + import net.minecraft.world.entity.ai.village.poi.PoiTypes; + import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.level.pathfinder.Path; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++// CraftBukkit end + + public class VillagerMakeLove extends Behavior { + +@@ -28,112 +32,113 @@ + super(ImmutableMap.of(MemoryModuleType.BREED_TARGET, MemoryStatus.VALUE_PRESENT, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryStatus.VALUE_PRESENT), 350, 350); + } + +- @Override +- protected boolean checkExtraStartConditions(ServerLevel serverlevel, Villager villager) { +- return this.isBreedingPossible(villager); ++ protected boolean checkExtraStartConditions(ServerLevel level, Villager owner) { ++ return this.isBreedingPossible(owner); + } + +- @Override +- protected boolean canStillUse(ServerLevel serverlevel, Villager villager, long i) { +- return i <= this.birthTimestamp && this.isBreedingPossible(villager); ++ protected boolean canStillUse(ServerLevel level, Villager entity, long gameTime) { ++ return gameTime <= this.birthTimestamp && this.isBreedingPossible(entity); + } + +- @Override +- protected void start(ServerLevel serverlevel, Villager villager, long i) { +- AgeableMob ageablemob = (AgeableMob) villager.getBrain().getMemory(MemoryModuleType.BREED_TARGET).get(); ++ protected void start(ServerLevel level, Villager entity, long gameTime) { ++ AgeableMob entityageable = (AgeableMob) entity.getBrain().getMemory(MemoryModuleType.BREED_TARGET).get(); + +- BehaviorUtils.lockGazeAndWalkToEachOther(villager, ageablemob, 0.5F); +- serverlevel.broadcastEntityEvent(ageablemob, (byte) 18); +- serverlevel.broadcastEntityEvent(villager, (byte) 18); +- int j = 275 + villager.getRandom().nextInt(50); ++ BehaviorUtils.lockGazeAndWalkToEachOther(entity, entityageable, 0.5F); ++ level.broadcastEntityEvent(entityageable, (byte) 18); ++ level.broadcastEntityEvent(entity, (byte) 18); ++ int j = 275 + entity.getRandom().nextInt(50); + +- this.birthTimestamp = i + (long) j; ++ this.birthTimestamp = gameTime + (long) j; + } + +- @Override +- protected void tick(ServerLevel serverlevel, Villager villager, long i) { +- Villager villager1 = (Villager) villager.getBrain().getMemory(MemoryModuleType.BREED_TARGET).get(); ++ protected void tick(ServerLevel level, Villager owner, long gameTime) { ++ Villager entityvillager1 = (Villager) owner.getBrain().getMemory(MemoryModuleType.BREED_TARGET).get(); + +- if (villager.distanceToSqr((Entity) villager1) <= 5.0D) { +- BehaviorUtils.lockGazeAndWalkToEachOther(villager, villager1, 0.5F); +- if (i >= this.birthTimestamp) { +- villager.eatAndDigestFood(); +- villager1.eatAndDigestFood(); +- this.tryToGiveBirth(serverlevel, villager, villager1); +- } else if (villager.getRandom().nextInt(35) == 0) { +- serverlevel.broadcastEntityEvent(villager1, (byte) 12); +- serverlevel.broadcastEntityEvent(villager, (byte) 12); ++ if (owner.distanceToSqr((Entity) entityvillager1) <= 5.0D) { ++ BehaviorUtils.lockGazeAndWalkToEachOther(owner, entityvillager1, 0.5F); ++ if (gameTime >= this.birthTimestamp) { ++ owner.eatAndDigestFood(); ++ entityvillager1.eatAndDigestFood(); ++ this.tryToGiveBirth(level, owner, entityvillager1); ++ } else if (owner.getRandom().nextInt(35) == 0) { ++ level.broadcastEntityEvent(entityvillager1, (byte) 12); ++ level.broadcastEntityEvent(owner, (byte) 12); + } + + } + } + +- private void tryToGiveBirth(ServerLevel serverlevel, Villager villager, Villager villager1) { +- Optional optional = this.takeVacantBed(serverlevel, villager); ++ private void tryToGiveBirth(ServerLevel level, Villager parent, Villager partner) { ++ Optional optional = this.takeVacantBed(level, parent); + + if (optional.isEmpty()) { +- serverlevel.broadcastEntityEvent(villager1, (byte) 13); +- serverlevel.broadcastEntityEvent(villager, (byte) 13); ++ level.broadcastEntityEvent(partner, (byte) 13); ++ level.broadcastEntityEvent(parent, (byte) 13); + } else { +- Optional optional1 = this.breed(serverlevel, villager, villager1); ++ Optional optional1 = this.breed(level, parent, partner); + + if (optional1.isPresent()) { +- this.giveBedToChild(serverlevel, (Villager) optional1.get(), (BlockPos) optional.get()); ++ this.giveBedToChild(level, (Villager) optional1.get(), (BlockPos) optional.get()); + } else { +- serverlevel.getPoiManager().release((BlockPos) optional.get()); +- DebugPackets.sendPoiTicketCountPacket(serverlevel, (BlockPos) optional.get()); ++ level.getPoiManager().release((BlockPos) optional.get()); ++ DebugPackets.sendPoiTicketCountPacket(level, (BlockPos) optional.get()); + } + } + + } + +- @Override +- protected void stop(ServerLevel serverlevel, Villager villager, long i) { +- villager.getBrain().eraseMemory(MemoryModuleType.BREED_TARGET); ++ protected void stop(ServerLevel level, Villager entity, long gameTime) { ++ entity.getBrain().eraseMemory(MemoryModuleType.BREED_TARGET); + } + + private boolean isBreedingPossible(Villager villager) { +- Brain brain = villager.getBrain(); +- Optional optional = brain.getMemory(MemoryModuleType.BREED_TARGET).filter((ageablemob) -> { +- return ageablemob.getType() == EntityType.VILLAGER; ++ Brain behaviorcontroller = villager.getBrain(); ++ Optional optional = behaviorcontroller.getMemory(MemoryModuleType.BREED_TARGET).filter((entityageable) -> { ++ return entityageable.getType() == EntityType.VILLAGER; + }); + +- return optional.isEmpty() ? false : BehaviorUtils.targetIsValid(brain, MemoryModuleType.BREED_TARGET, EntityType.VILLAGER) && villager.canBreed() && ((AgeableMob) optional.get()).canBreed(); ++ return optional.isEmpty() ? false : BehaviorUtils.targetIsValid(behaviorcontroller, MemoryModuleType.BREED_TARGET, EntityType.VILLAGER) && villager.canBreed() && ((AgeableMob) optional.get()).canBreed(); + } + +- private Optional takeVacantBed(ServerLevel serverlevel, Villager villager) { +- return serverlevel.getPoiManager().take((holder) -> { ++ private Optional takeVacantBed(ServerLevel level, Villager villager) { ++ return level.getPoiManager().take((holder) -> { + return holder.is(PoiTypes.HOME); +- }, (holder, blockpos) -> { +- return this.canReach(villager, blockpos, holder); ++ }, (holder, blockposition) -> { ++ return this.canReach(villager, blockposition, holder); + }, villager.blockPosition(), 48); + } + +- private boolean canReach(Villager villager, BlockPos blockpos, Holder holder) { +- Path path = villager.getNavigation().createPath(blockpos, ((PoiType) holder.value()).validRange()); ++ private boolean canReach(Villager villager, BlockPos pos, Holder poiType) { ++ Path pathentity = villager.getNavigation().createPath(pos, ((PoiType) poiType.value()).validRange()); + +- return path != null && path.canReach(); ++ return pathentity != null && pathentity.canReach(); + } + +- private Optional breed(ServerLevel serverlevel, Villager villager, Villager villager1) { +- Villager villager2 = villager.getBreedOffspring(serverlevel, villager1); ++ private Optional breed(ServerLevel level, Villager parent, Villager partner) { ++ Villager entityvillager2 = parent.getBreedOffspring(level, partner); + +- if (villager2 == null) { ++ if (entityvillager2 == null) { + return Optional.empty(); + } else { +- villager.setAge(6000); +- villager1.setAge(6000); +- villager2.setAge(-24000); +- villager2.moveTo(villager.getX(), villager.getY(), villager.getZ(), 0.0F, 0.0F); +- serverlevel.addFreshEntityWithPassengers(villager2); +- serverlevel.broadcastEntityEvent(villager2, (byte) 12); +- return Optional.of(villager2); ++ entityvillager2.setAge(-24000); ++ entityvillager2.moveTo(parent.getX(), parent.getY(), parent.getZ(), 0.0F, 0.0F); ++ // CraftBukkit start - call EntityBreedEvent ++ if (CraftEventFactory.callEntityBreedEvent(entityvillager2, parent, partner, null, null, 0).isCancelled()) { ++ return Optional.empty(); ++ } ++ // Move age setting down ++ parent.setAge(6000); ++ partner.setAge(6000); ++ level.addFreshEntityWithPassengers(entityvillager2, CreatureSpawnEvent.SpawnReason.BREEDING); ++ // CraftBukkit end ++ level.broadcastEntityEvent(entityvillager2, (byte) 12); ++ return Optional.of(entityvillager2); + } + } + +- private void giveBedToChild(ServerLevel serverlevel, Villager villager, BlockPos blockpos) { +- GlobalPos globalpos = GlobalPos.of(serverlevel.dimension(), blockpos); ++ private void giveBedToChild(ServerLevel level, Villager villager, BlockPos pos) { ++ GlobalPos globalpos = GlobalPos.of(level.dimension(), pos); + +- villager.getBrain().setMemory(MemoryModuleType.HOME, (Object) globalpos); ++ villager.getBrain().setMemory(MemoryModuleType.HOME, globalpos); // CraftBukkit - decompile error + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java.patch new file mode 100644 index 0000000000..306170f0fc --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java.patch @@ -0,0 +1,71 @@ +--- a/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java ++++ b/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java +@@ -14,16 +14,16 @@ + protected int lastBreakProgress; + protected int doorBreakTime; + +- public BreakDoorGoal(Mob mob, Predicate predicate) { ++ public BreakDoorGoal(Mob mob, Predicate validDifficulties) { + super(mob); + this.lastBreakProgress = -1; + this.doorBreakTime = -1; +- this.validDifficulties = predicate; ++ this.validDifficulties = validDifficulties; + } + +- public BreakDoorGoal(Mob mob, int i, Predicate predicate) { +- this(mob, predicate); +- this.doorBreakTime = i; ++ public BreakDoorGoal(Mob mob, int doorBreakTime, Predicate validDifficulties) { ++ this(mob, validDifficulties); ++ this.doorBreakTime = doorBreakTime; + } + + protected int getDoorBreakTime() { +@@ -31,33 +31,28 @@ + } + + @Override +- @Override + public boolean canUse() { + return !super.canUse() ? false : (!this.mob.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? false : this.isValidDifficulty(this.mob.level().getDifficulty()) && !this.isOpen()); + } + + @Override +- @Override + public void start() { + super.start(); + this.breakTime = 0; + } + + @Override +- @Override + public boolean canContinueToUse() { + return this.breakTime <= this.getDoorBreakTime() && !this.isOpen() && this.doorPos.closerToCenterThan(this.mob.position(), 2.0D) && this.isValidDifficulty(this.mob.level().getDifficulty()); + } + + @Override +- @Override + public void stop() { + super.stop(); + this.mob.level().destroyBlockProgress(this.mob.getId(), this.doorPos, -1); + } + + @Override +- @Override + public void tick() { + super.tick(); + if (this.mob.getRandom().nextInt(20) == 0) { +@@ -76,6 +71,12 @@ + } + + if (this.breakTime == this.getDoorBreakTime() && this.isValidDifficulty(this.mob.level().getDifficulty())) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreakDoorEvent(this.mob, this.doorPos).isCancelled()) { ++ this.start(); ++ return; ++ } ++ // CraftBukkit end + this.mob.level().removeBlock(this.doorPos, false); + this.mob.level().levelEvent(1021, this.doorPos, 0); + this.mob.level().levelEvent(2001, this.doorPos, Block.getId(this.mob.level().getBlockState(this.doorPos))); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/EatBlockGoal.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/EatBlockGoal.java.patch new file mode 100644 index 0000000000..e2ef797088 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/EatBlockGoal.java.patch @@ -0,0 +1,98 @@ +--- a/net/minecraft/world/entity/ai/goal/EatBlockGoal.java ++++ b/net/minecraft/world/entity/ai/goal/EatBlockGoal.java +@@ -8,13 +8,17 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.predicate.BlockStatePredicate; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class EatBlockGoal extends Goal { + + private static final int EAT_ANIMATION_TICKS = 40; +- private static final Predicate IS_TALL_GRASS = BlockStatePredicate.forBlock(Blocks.SHORT_GRASS); ++ private static final Predicate IS_TALL_GRASS = BlockStatePredicate.forBlock(Blocks.SHORT_GRASS); + private final Mob mob; + private final Level level; + private int eatAnimationTick; +@@ -22,23 +26,21 @@ + public EatBlockGoal(Mob mob) { + this.mob = mob; + this.level = mob.level(); +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK, Goal.Flag.JUMP)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK, Goal.Type.JUMP)); + } + + @Override +- @Override + public boolean canUse() { + if (this.mob.getRandom().nextInt(this.mob.isBaby() ? 50 : 1000) != 0) { + return false; + } else { +- BlockPos blockpos = this.mob.blockPosition(); ++ BlockPos blockposition = this.mob.blockPosition(); + +- return EatBlockGoal.IS_TALL_GRASS.test(this.level.getBlockState(blockpos)) ? true : this.level.getBlockState(blockpos.below()).is(Blocks.GRASS_BLOCK); ++ return EatBlockGoal.IS_TALL_GRASS.test(this.level.getBlockState(blockposition)) ? true : this.level.getBlockState(blockposition.below()).is(Blocks.GRASS_BLOCK); + } + } + + @Override +- @Override + public void start() { + this.eatAnimationTick = this.adjustedTickDelay(40); + this.level.broadcastEntityEvent(this.mob, (byte) 10); +@@ -46,13 +48,11 @@ + } + + @Override +- @Override + public void stop() { + this.eatAnimationTick = 0; + } + + @Override +- @Override + public boolean canContinueToUse() { + return this.eatAnimationTick > 0; + } +@@ -62,25 +62,24 @@ + } + + @Override +- @Override + public void tick() { + this.eatAnimationTick = Math.max(0, this.eatAnimationTick - 1); + if (this.eatAnimationTick == this.adjustedTickDelay(4)) { +- BlockPos blockpos = this.mob.blockPosition(); ++ BlockPos blockposition = this.mob.blockPosition(); + +- if (EatBlockGoal.IS_TALL_GRASS.test(this.level.getBlockState(blockpos))) { +- if (this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- this.level.destroyBlock(blockpos, false); ++ if (EatBlockGoal.IS_TALL_GRASS.test(this.level.getBlockState(blockposition))) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition, Blocks.AIR.defaultBlockState(), !this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit ++ this.level.destroyBlock(blockposition, false); + } + + this.mob.ate(); + } else { +- BlockPos blockpos1 = blockpos.below(); ++ BlockPos blockposition1 = blockposition.below(); + +- if (this.level.getBlockState(blockpos1).is(Blocks.GRASS_BLOCK)) { +- if (this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- this.level.levelEvent(2001, blockpos1, Block.getId(Blocks.GRASS_BLOCK.defaultBlockState())); +- this.level.setBlock(blockpos1, Blocks.DIRT.defaultBlockState(), 2); ++ if (this.level.getBlockState(blockposition1).is(Blocks.GRASS_BLOCK)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition1, Blocks.AIR.defaultBlockState(), !this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit ++ this.level.levelEvent(2001, blockposition1, Block.getId(Blocks.GRASS_BLOCK.defaultBlockState())); ++ this.level.setBlock(blockposition1, Blocks.DIRT.defaultBlockState(), 2); + } + + this.mob.ate(); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java.patch new file mode 100644 index 0000000000..384d76fe1a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java.patch @@ -0,0 +1,172 @@ +--- a/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java ++++ b/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java +@@ -10,9 +10,14 @@ + import net.minecraft.world.entity.ai.navigation.PathNavigation; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.LeavesBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.level.pathfinder.WalkNodeEvaluator; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTeleportEvent; ++// CraftBukkit end + + public class FollowOwnerGoal extends Goal { + +@@ -31,41 +36,39 @@ + private float oldWaterCost; + private final boolean canFly; + +- public FollowOwnerGoal(TamableAnimal tamableanimal, double d0, float f, float f1, boolean flag) { +- this.tamable = tamableanimal; +- this.level = tamableanimal.level(); +- this.speedModifier = d0; +- this.navigation = tamableanimal.getNavigation(); ++ public FollowOwnerGoal(TamableAnimal tamable, double speedModifier, float f, float startDistance, boolean stopDistance) { ++ this.tamable = tamable; ++ this.level = tamable.level(); ++ this.speedModifier = speedModifier; ++ this.navigation = tamable.getNavigation(); + this.startDistance = f; +- this.stopDistance = f1; +- this.canFly = flag; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); +- if (!(tamableanimal.getNavigation() instanceof GroundPathNavigation) && !(tamableanimal.getNavigation() instanceof FlyingPathNavigation)) { ++ this.stopDistance = startDistance; ++ this.canFly = stopDistance; ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); ++ if (!(tamable.getNavigation() instanceof GroundPathNavigation) && !(tamable.getNavigation() instanceof FlyingPathNavigation)) { + throw new IllegalArgumentException("Unsupported mob type for FollowOwnerGoal"); + } + } + + @Override +- @Override + public boolean canUse() { +- LivingEntity livingentity = this.tamable.getOwner(); ++ LivingEntity entityliving = this.tamable.getOwner(); + +- if (livingentity == null) { ++ if (entityliving == null) { + return false; +- } else if (livingentity.isSpectator()) { ++ } else if (entityliving.isSpectator()) { + return false; + } else if (this.unableToMove()) { + return false; +- } else if (this.tamable.distanceToSqr((Entity) livingentity) < (double) (this.startDistance * this.startDistance)) { ++ } else if (this.tamable.distanceToSqr((Entity) entityliving) < (double) (this.startDistance * this.startDistance)) { + return false; + } else { +- this.owner = livingentity; ++ this.owner = entityliving; + return true; + } + } + + @Override +- @Override + public boolean canContinueToUse() { + return this.navigation.isDone() ? false : (this.unableToMove() ? false : this.tamable.distanceToSqr((Entity) this.owner) > (double) (this.stopDistance * this.stopDistance)); + } +@@ -75,7 +78,6 @@ + } + + @Override +- @Override + public void start() { + this.timeToRecalcPath = 0; + this.oldWaterCost = this.tamable.getPathfindingMalus(BlockPathTypes.WATER); +@@ -83,7 +85,6 @@ + } + + @Override +- @Override + public void stop() { + this.owner = null; + this.navigation.stop(); +@@ -91,7 +92,6 @@ + } + + @Override +- @Override + public void tick() { + this.tamable.getLookControl().setLookAt(this.owner, 10.0F, (float) this.tamable.getMaxHeadXRot()); + if (--this.timeToRecalcPath <= 0) { +@@ -106,13 +106,13 @@ + } + + private void teleportToOwner() { +- BlockPos blockpos = this.owner.blockPosition(); ++ BlockPos blockposition = this.owner.blockPosition(); + + for (int i = 0; i < 10; ++i) { + int j = this.randomIntInclusive(-3, 3); + int k = this.randomIntInclusive(-1, 1); + int l = this.randomIntInclusive(-3, 3); +- boolean flag = this.maybeTeleportTo(blockpos.getX() + j, blockpos.getY() + k, blockpos.getZ() + l); ++ boolean flag = this.maybeTeleportTo(blockposition.getX() + j, blockposition.getY() + k, blockposition.getZ() + l); + + if (flag) { + return; +@@ -121,37 +121,44 @@ + + } + +- private boolean maybeTeleportTo(int i, int j, int k) { +- if (Math.abs((double) i - this.owner.getX()) < 2.0D && Math.abs((double) k - this.owner.getZ()) < 2.0D) { ++ private boolean maybeTeleportTo(int x, int y, int z) { ++ if (Math.abs((double) x - this.owner.getX()) < 2.0D && Math.abs((double) z - this.owner.getZ()) < 2.0D) { + return false; +- } else if (!this.canTeleportTo(new BlockPos(i, j, k))) { ++ } else if (!this.canTeleportTo(new BlockPos(x, y, z))) { + return false; + } else { +- this.tamable.moveTo((double) i + 0.5D, (double) j, (double) k + 0.5D, this.tamable.getYRot(), this.tamable.getXRot()); ++ // CraftBukkit start ++ EntityTeleportEvent event = CraftEventFactory.callEntityTeleportEvent(this.tamable, (double) x + 0.5D, (double) y, (double) z + 0.5D); ++ if (event.isCancelled()) { ++ return false; ++ } ++ Location to = event.getTo(); ++ this.tamable.moveTo(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch()); ++ // CraftBukkit end + this.navigation.stop(); + return true; + } + } + +- private boolean canTeleportTo(BlockPos blockpos) { +- BlockPathTypes blockpathtypes = WalkNodeEvaluator.getBlockPathTypeStatic(this.level, blockpos.mutable()); ++ private boolean canTeleportTo(BlockPos pos) { ++ BlockPathTypes pathtype = WalkNodeEvaluator.getBlockPathTypeStatic(this.level, pos.mutable()); + +- if (blockpathtypes != BlockPathTypes.WALKABLE) { ++ if (pathtype != BlockPathTypes.WALKABLE) { + return false; + } else { +- BlockState blockstate = this.level.getBlockState(blockpos.below()); ++ IBlockData iblockdata = this.level.getBlockState(pos.below()); + +- if (!this.canFly && blockstate.getBlock() instanceof LeavesBlock) { ++ if (!this.canFly && iblockdata.getBlock() instanceof LeavesBlock) { + return false; + } else { +- BlockPos blockpos1 = blockpos.subtract(this.tamable.blockPosition()); ++ BlockPos blockposition1 = pos.subtract(this.tamable.blockPosition()); + +- return this.level.noCollision(this.tamable, this.tamable.getBoundingBox().move(blockpos1)); ++ return this.level.noCollision(this.tamable, this.tamable.getBoundingBox().move(blockposition1)); + } + } + } + +- private int randomIntInclusive(int i, int j) { +- return this.tamable.getRandom().nextInt(j - i + 1) + i; ++ private int randomIntInclusive(int min, int max) { ++ return this.tamable.getRandom().nextInt(max - min + 1) + min; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java.patch new file mode 100644 index 0000000000..03ae7adb12 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java.patch @@ -0,0 +1,164 @@ +--- a/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java ++++ b/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java +@@ -20,6 +20,10 @@ + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class RemoveBlockGoal extends MoveToBlockGoal { + +@@ -28,14 +32,13 @@ + private int ticksSinceReachedGoal; + private static final int WAIT_AFTER_BLOCK_FOUND = 20; + +- public RemoveBlockGoal(Block block, PathfinderMob pathfindermob, double d0, int i) { +- super(pathfindermob, d0, 24, i); +- this.blockToRemove = block; +- this.removerMob = pathfindermob; ++ public RemoveBlockGoal(Block blockToRemove, PathfinderMob removerMob, double speedModifier, int i) { ++ super(removerMob, speedModifier, 24, i); ++ this.blockToRemove = blockToRemove; ++ this.removerMob = removerMob; + } + + @Override +- @Override + public boolean canUse() { + if (!this.removerMob.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { + return false; +@@ -52,65 +55,67 @@ + } + + @Override +- @Override + public void stop() { + super.stop(); + this.removerMob.fallDistance = 1.0F; + } + + @Override +- @Override + public void start() { + super.start(); + this.ticksSinceReachedGoal = 0; + } + +- public void playDestroyProgressSound(LevelAccessor levelaccessor, BlockPos blockpos) {} ++ public void playDestroyProgressSound(LevelAccessor level, BlockPos pos) {} + +- public void playBreakSound(Level level, BlockPos blockpos) {} ++ public void playBreakSound(Level level, BlockPos pos) {} + + @Override +- @Override + public void tick() { + super.tick(); +- Level level = this.removerMob.level(); +- BlockPos blockpos = this.removerMob.blockPosition(); +- BlockPos blockpos1 = this.getPosWithBlock(blockpos, level); ++ Level world = this.removerMob.level(); ++ BlockPos blockposition = this.removerMob.blockPosition(); ++ BlockPos blockposition1 = this.getPosWithBlock(blockposition, world); + RandomSource randomsource = this.removerMob.getRandom(); + +- if (this.isReachedTarget() && blockpos1 != null) { +- Vec3 vec3; ++ if (this.isReachedTarget() && blockposition1 != null) { ++ Vec3 vec3d; + double d0; + + if (this.ticksSinceReachedGoal > 0) { +- vec3 = this.removerMob.getDeltaMovement(); +- this.removerMob.setDeltaMovement(vec3.x, 0.3D, vec3.z); +- if (!level.isClientSide) { ++ vec3d = this.removerMob.getDeltaMovement(); ++ this.removerMob.setDeltaMovement(vec3d.x, 0.3D, vec3d.z); ++ if (!world.isClientSide) { + d0 = 0.08D; +- ((ServerLevel) level).sendParticles(new ItemParticleOption(ParticleTypes.ITEM, new ItemStack(Items.EGG)), (double) blockpos1.getX() + 0.5D, (double) blockpos1.getY() + 0.7D, (double) blockpos1.getZ() + 0.5D, 3, ((double) randomsource.nextFloat() - 0.5D) * 0.08D, ((double) randomsource.nextFloat() - 0.5D) * 0.08D, ((double) randomsource.nextFloat() - 0.5D) * 0.08D, 0.15000000596046448D); ++ ((ServerLevel) world).sendParticles(new ItemParticleOption(ParticleTypes.ITEM, new ItemStack(Items.EGG)), (double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.7D, (double) blockposition1.getZ() + 0.5D, 3, ((double) randomsource.nextFloat() - 0.5D) * 0.08D, ((double) randomsource.nextFloat() - 0.5D) * 0.08D, ((double) randomsource.nextFloat() - 0.5D) * 0.08D, 0.15000000596046448D); + } + } + + if (this.ticksSinceReachedGoal % 2 == 0) { +- vec3 = this.removerMob.getDeltaMovement(); +- this.removerMob.setDeltaMovement(vec3.x, -0.3D, vec3.z); ++ vec3d = this.removerMob.getDeltaMovement(); ++ this.removerMob.setDeltaMovement(vec3d.x, -0.3D, vec3d.z); + if (this.ticksSinceReachedGoal % 6 == 0) { +- this.playDestroyProgressSound(level, this.blockPos); ++ this.playDestroyProgressSound(world, this.blockPos); + } + } + + if (this.ticksSinceReachedGoal > 60) { +- level.removeBlock(blockpos1, false); +- if (!level.isClientSide) { ++ // CraftBukkit start - Step on eggs ++ if (!CraftEventFactory.callEntityInteractEvent(this.removerMob, CraftBlock.at(world, blockposition1))) { ++ return; ++ } ++ // CraftBukkit end ++ world.removeBlock(blockposition1, false); ++ if (!world.isClientSide) { + for (int i = 0; i < 20; ++i) { + d0 = randomsource.nextGaussian() * 0.02D; + double d1 = randomsource.nextGaussian() * 0.02D; + double d2 = randomsource.nextGaussian() * 0.02D; + +- ((ServerLevel) level).sendParticles(ParticleTypes.POOF, (double) blockpos1.getX() + 0.5D, (double) blockpos1.getY(), (double) blockpos1.getZ() + 0.5D, 1, d0, d1, d2, 0.15000000596046448D); ++ ((ServerLevel) world).sendParticles(ParticleTypes.POOF, (double) blockposition1.getX() + 0.5D, (double) blockposition1.getY(), (double) blockposition1.getZ() + 0.5D, 1, d0, d1, d2, 0.15000000596046448D); + } + +- this.playBreakSound(level, blockpos1); ++ this.playBreakSound(world, blockposition1); + } + } + +@@ -120,19 +125,19 @@ + } + + @Nullable +- private BlockPos getPosWithBlock(BlockPos blockpos, BlockGetter blockgetter) { +- if (blockgetter.getBlockState(blockpos).is(this.blockToRemove)) { +- return blockpos; ++ private BlockPos getPosWithBlock(BlockPos pos, BlockGetter level) { ++ if (level.getBlockState(pos).is(this.blockToRemove)) { ++ return pos; + } else { +- BlockPos[] ablockpos = new BlockPos[]{blockpos.below(), blockpos.west(), blockpos.east(), blockpos.north(), blockpos.south(), blockpos.below().below()}; +- BlockPos[] ablockpos1 = ablockpos; +- int i = ablockpos.length; ++ BlockPos[] ablockposition = new BlockPos[]{pos.below(), pos.west(), pos.east(), pos.north(), pos.south(), pos.below().below()}; ++ BlockPos[] ablockposition1 = ablockposition; ++ int i = ablockposition.length; + + for (int j = 0; j < i; ++j) { +- BlockPos blockpos1 = ablockpos1[j]; ++ BlockPos blockposition1 = ablockposition1[j]; + +- if (blockgetter.getBlockState(blockpos1).is(this.blockToRemove)) { +- return blockpos1; ++ if (level.getBlockState(blockposition1).is(this.blockToRemove)) { ++ return blockposition1; + } + } + +@@ -141,10 +146,9 @@ + } + + @Override +- @Override +- protected boolean isValidTarget(LevelReader levelreader, BlockPos blockpos) { +- ChunkAccess chunkaccess = levelreader.getChunk(SectionPos.blockToSectionCoord(blockpos.getX()), SectionPos.blockToSectionCoord(blockpos.getZ()), ChunkStatus.FULL, false); ++ protected boolean isValidTarget(LevelReader level, BlockPos pos) { ++ ChunkAccess ichunkaccess = level.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()), ChunkStatus.FULL, false); + +- return chunkaccess == null ? false : chunkaccess.getBlockState(blockpos).is(this.blockToRemove) && chunkaccess.getBlockState(blockpos.above()).isAir() && chunkaccess.getBlockState(blockpos.above(2)).isAir(); ++ return ichunkaccess == null ? false : ichunkaccess.getBlockState(pos).is(this.blockToRemove) && ichunkaccess.getBlockState(pos.above()).isAir() && ichunkaccess.getBlockState(pos.above(2)).isAir(); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java.patch new file mode 100644 index 0000000000..65c3c694d5 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java.patch @@ -0,0 +1,83 @@ +--- a/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java ++++ b/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java +@@ -6,6 +6,10 @@ + import net.minecraft.world.entity.animal.horse.AbstractHorse; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class RunAroundLikeCrazyGoal extends Goal { + +@@ -15,24 +19,23 @@ + private double posY; + private double posZ; + +- public RunAroundLikeCrazyGoal(AbstractHorse abstracthorse, double d0) { +- this.horse = abstracthorse; +- this.speedModifier = d0; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ public RunAroundLikeCrazyGoal(AbstractHorse horse, double speedModifier) { ++ this.horse = horse; ++ this.speedModifier = speedModifier; ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +- @Override + public boolean canUse() { + if (!this.horse.isTamed() && this.horse.isVehicle()) { +- Vec3 vec3 = DefaultRandomPos.getPos(this.horse, 5, 4); ++ Vec3 vec3d = DefaultRandomPos.getPos(this.horse, 5, 4); + +- if (vec3 == null) { ++ if (vec3d == null) { + return false; + } else { +- this.posX = vec3.x; +- this.posY = vec3.y; +- this.posZ = vec3.z; ++ this.posX = vec3d.x; ++ this.posY = vec3d.y; ++ this.posZ = vec3d.z; + return true; + } + } else { +@@ -41,19 +44,16 @@ + } + + @Override +- @Override + public void start() { + this.horse.getNavigation().moveTo(this.posX, this.posY, this.posZ, this.speedModifier); + } + + @Override +- @Override + public boolean canContinueToUse() { + return !this.horse.isTamed() && !this.horse.getNavigation().isDone() && this.horse.isVehicle(); + } + + @Override +- @Override + public void tick() { + if (!this.horse.isTamed() && this.horse.getRandom().nextInt(this.adjustedTickDelay(50)) == 0) { + Entity entity = this.horse.getFirstPassenger(); +@@ -63,12 +63,12 @@ + } + + if (entity instanceof Player) { +- Player player = (Player) entity; ++ Player entityhuman = (Player) entity; + int i = this.horse.getTemper(); + int j = this.horse.getMaxTemper(); + +- if (j > 0 && this.horse.getRandom().nextInt(j) < i) { +- this.horse.tameWithName(player); ++ if (j > 0 && this.horse.getRandom().nextInt(j) < i && !CraftEventFactory.callEntityTameEvent(this.horse, ((CraftHumanEntity) this.horse.getBukkitEntity().getPassenger()).getHandle()).isCancelled()) { // CraftBukkit - fire EntityTameEvent ++ this.horse.tameWithName(entityhuman); + return; + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java.patch new file mode 100644 index 0000000000..650dab2046 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java.patch @@ -0,0 +1,51 @@ +--- a/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java ++++ b/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java +@@ -9,42 +9,38 @@ + + private final TamableAnimal mob; + +- public SitWhenOrderedToGoal(TamableAnimal tamableanimal) { +- this.mob = tamableanimal; +- this.setFlags(EnumSet.of(Goal.Flag.JUMP, Goal.Flag.MOVE)); ++ public SitWhenOrderedToGoal(TamableAnimal mob) { ++ this.mob = mob; ++ this.setFlags(EnumSet.of(Goal.Type.JUMP, Goal.Type.MOVE)); + } + + @Override +- @Override + public boolean canContinueToUse() { + return this.mob.isOrderedToSit(); + } + + @Override +- @Override + public boolean canUse() { + if (!this.mob.isTame()) { +- return false; ++ return this.mob.isOrderedToSit() && this.mob.getTarget() == null; // CraftBukkit - Allow sitting for wild animals + } else if (this.mob.isInWaterOrBubble()) { + return false; + } else if (!this.mob.onGround()) { + return false; + } else { +- LivingEntity livingentity = this.mob.getOwner(); ++ LivingEntity entityliving = this.mob.getOwner(); + +- return livingentity == null ? true : (this.mob.distanceToSqr((Entity) livingentity) < 144.0D && livingentity.getLastHurtByMob() != null ? false : this.mob.isOrderedToSit()); ++ return entityliving == null ? true : (this.mob.distanceToSqr((Entity) entityliving) < 144.0D && entityliving.getLastHurtByMob() != null ? false : this.mob.isOrderedToSit()); + } + } + + @Override +- @Override + public void start() { + this.mob.getNavigation().stop(); + this.mob.setInSittingPose(true); + } + + @Override +- @Override + public void stop() { + this.mob.setInSittingPose(false); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/TemptGoal.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/TemptGoal.java.patch new file mode 100644 index 0000000000..80d9fe2eda --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/goal/TemptGoal.java.patch @@ -0,0 +1,99 @@ +--- a/net/minecraft/world/entity/ai/goal/TemptGoal.java ++++ b/net/minecraft/world/entity/ai/goal/TemptGoal.java +@@ -6,8 +6,13 @@ + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.PathfinderMob; + import net.minecraft.world.entity.ai.targeting.TargetingConditions; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.crafting.Ingredient; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++// CraftBukkit end + + public class TemptGoal extends Goal { + +@@ -21,39 +26,46 @@ + private double pRotX; + private double pRotY; + @Nullable +- protected Player player; ++ protected LivingEntity player; // CraftBukkit + private int calmDown; + private boolean isRunning; + private final Ingredient items; + private final boolean canScare; + +- public TemptGoal(PathfinderMob pathfindermob, double d0, Ingredient ingredient, boolean flag) { +- this.mob = pathfindermob; +- this.speedModifier = d0; +- this.items = ingredient; +- this.canScare = flag; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ public TemptGoal(PathfinderMob mob, double speedModifier, Ingredient recipeitemstack, boolean items) { ++ this.mob = mob; ++ this.speedModifier = speedModifier; ++ this.items = recipeitemstack; ++ this.canScare = items; ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + this.targetingConditions = TemptGoal.TEMP_TARGETING.copy().selector(this::shouldFollow); + } + + @Override +- @Override + public boolean canUse() { + if (this.calmDown > 0) { + --this.calmDown; + return false; + } else { + this.player = this.mob.level().getNearestPlayer(this.targetingConditions, this.mob); ++ // CraftBukkit start ++ if (this.player != null) { ++ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(this.mob, this.player, EntityTargetEvent.TargetReason.TEMPT); ++ if (event.isCancelled()) { ++ return false; ++ } ++ this.player = (event.getTarget() == null) ? null : ((CraftLivingEntity) event.getTarget()).getHandle(); ++ } ++ // CraftBukkit end + return this.player != null; + } + } + +- private boolean shouldFollow(LivingEntity livingentity) { +- return this.items.test(livingentity.getMainHandItem()) || this.items.test(livingentity.getOffhandItem()); ++ private boolean shouldFollow(LivingEntity entity) { ++ return this.items.test(entity.getMainHandItem()) || this.items.test(entity.getOffhandItem()); + } + + @Override +- @Override + public boolean canContinueToUse() { + if (this.canScare()) { + if (this.mob.distanceToSqr((Entity) this.player) < 36.0D) { +@@ -82,7 +94,6 @@ + } + + @Override +- @Override + public void start() { + this.px = this.player.getX(); + this.py = this.player.getY(); +@@ -91,7 +102,6 @@ + } + + @Override +- @Override + public void stop() { + this.player = null; + this.mob.getNavigation().stop(); +@@ -100,7 +110,6 @@ + } + + @Override +- @Override + public void tick() { + this.mob.getLookControl().setLookAt(this.player, (float) (this.mob.getMaxHeadYRot() + 20), (float) this.mob.getMaxHeadXRot()); + if (this.mob.distanceToSqr((Entity) this.player) < 6.25D) { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/sensing/TemptingSensor.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/sensing/TemptingSensor.java.patch new file mode 100644 index 0000000000..e2f2cc9fb1 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/sensing/TemptingSensor.java.patch @@ -0,0 +1,87 @@ +--- a/net/minecraft/world/entity/ai/sensing/TemptingSensor.java ++++ b/net/minecraft/world/entity/ai/sensing/TemptingSensor.java +@@ -17,6 +17,13 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.crafting.Ingredient; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++// CraftBukkit end + + public class TemptingSensor extends Sensor { + +@@ -24,30 +31,39 @@ + private static final TargetingConditions TEMPT_TARGETING = TargetingConditions.forNonCombat().range(10.0D).ignoreLineOfSight(); + private final Ingredient temptations; + +- public TemptingSensor(Ingredient ingredient) { +- this.temptations = ingredient; ++ public TemptingSensor(Ingredient temptations) { ++ this.temptations = temptations; + } + +- @Override +- protected void doTick(ServerLevel serverlevel, PathfinderMob pathfindermob) { +- Brain brain = pathfindermob.getBrain(); +- Stream stream = serverlevel.players().stream().filter(EntitySelector.NO_SPECTATORS).filter((serverplayer) -> { +- return TemptingSensor.TEMPT_TARGETING.test(pathfindermob, serverplayer); +- }).filter((serverplayer) -> { +- return pathfindermob.closerThan(serverplayer, 10.0D); +- }).filter(this::playerHoldingTemptation).filter((serverplayer) -> { +- return !pathfindermob.hasPassenger((Entity) serverplayer); ++ protected void doTick(ServerLevel level, PathfinderMob entity) { ++ Brain behaviorcontroller = entity.getBrain(); ++ Stream stream = level.players().stream().filter(EntitySelector.NO_SPECTATORS).filter((entityplayer) -> { // CraftBukkit - decompile error ++ return TemptingSensor.TEMPT_TARGETING.test(entity, entityplayer); ++ }).filter((entityplayer) -> { ++ return entity.closerThan(entityplayer, 10.0D); ++ }).filter(this::playerHoldingTemptation).filter((entityplayer) -> { ++ return !entity.hasPassenger((Entity) entityplayer); + }); + +- Objects.requireNonNull(pathfindermob); +- List list = (List) stream.sorted(Comparator.comparingDouble(pathfindermob::distanceToSqr)).collect(Collectors.toList()); ++ Objects.requireNonNull(entity); ++ List list = (List) stream.sorted(Comparator.comparingDouble(entity::distanceToSqr)).collect(Collectors.toList()); + + if (!list.isEmpty()) { +- Player player = (Player) list.get(0); ++ Player entityhuman = (Player) list.get(0); + +- brain.setMemory(MemoryModuleType.TEMPTING_PLAYER, (Object) player); ++ // CraftBukkit start ++ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(entity, entityhuman, EntityTargetEvent.TargetReason.TEMPT); ++ if (event.isCancelled()) { ++ return; ++ } ++ if (event.getTarget() instanceof HumanEntity) { ++ behaviorcontroller.setMemory(MemoryModuleType.TEMPTING_PLAYER, ((CraftHumanEntity) event.getTarget()).getHandle()); ++ } else { ++ behaviorcontroller.eraseMemory(MemoryModuleType.TEMPTING_PLAYER); ++ } ++ // CraftBukkit end + } else { +- brain.eraseMemory(MemoryModuleType.TEMPTING_PLAYER); ++ behaviorcontroller.eraseMemory(MemoryModuleType.TEMPTING_PLAYER); + } + + } +@@ -56,12 +72,11 @@ + return this.isTemptation(player.getMainHandItem()) || this.isTemptation(player.getOffhandItem()); + } + +- private boolean isTemptation(ItemStack itemstack) { +- return this.temptations.test(itemstack); ++ private boolean isTemptation(ItemStack stack) { ++ return this.temptations.test(stack); + } + + @Override +- @Override + public Set> requires() { + return ImmutableSet.of(MemoryModuleType.TEMPTING_PLAYER); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/village/VillageSiege.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/village/VillageSiege.java.patch new file mode 100644 index 0000000000..e6c81383dd --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ai/village/VillageSiege.java.patch @@ -0,0 +1,135 @@ +--- a/net/minecraft/world/entity/ai/village/VillageSiege.java ++++ b/net/minecraft/world/entity/ai/village/VillageSiege.java +@@ -9,8 +9,8 @@ + import net.minecraft.tags.BiomeTags; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.monster.Monster; + import net.minecraft.world.entity.monster.Zombie; + import net.minecraft.world.entity.player.Player; +@@ -35,20 +35,19 @@ + } + + @Override +- @Override +- public int tick(ServerLevel serverlevel, boolean flag, boolean flag1) { +- if (!serverlevel.isDay() && flag) { +- float f = serverlevel.getTimeOfDay(0.0F); ++ public int tick(ServerLevel level, boolean spawnHostiles, boolean spawnPassives) { ++ if (!level.isDay() && spawnHostiles) { ++ float f = level.getTimeOfDay(0.0F); + + if ((double) f == 0.5D) { +- this.siegeState = serverlevel.random.nextInt(10) == 0 ? VillageSiege.State.SIEGE_TONIGHT : VillageSiege.State.SIEGE_DONE; ++ this.siegeState = level.random.nextInt(10) == 0 ? VillageSiege.State.SIEGE_TONIGHT : VillageSiege.State.SIEGE_DONE; + } + + if (this.siegeState == VillageSiege.State.SIEGE_DONE) { + return 0; + } else { + if (!this.hasSetupSiege) { +- if (!this.tryToSetupSiege(serverlevel)) { ++ if (!this.tryToSetupSiege(level)) { + return 0; + } + +@@ -61,7 +60,7 @@ + } else { + this.nextSpawnTime = 2; + if (this.zombiesToSpawn > 0) { +- this.trySpawn(serverlevel); ++ this.trySpawn(level); + --this.zombiesToSpawn; + } else { + this.siegeState = VillageSiege.State.SIEGE_DONE; +@@ -77,23 +76,23 @@ + } + } + +- private boolean tryToSetupSiege(ServerLevel serverlevel) { +- Iterator iterator = serverlevel.players().iterator(); ++ private boolean tryToSetupSiege(ServerLevel level) { ++ Iterator iterator = level.players().iterator(); + + while (iterator.hasNext()) { +- Player player = (Player) iterator.next(); ++ Player entityhuman = (Player) iterator.next(); + +- if (!player.isSpectator()) { +- BlockPos blockpos = player.blockPosition(); ++ if (!entityhuman.isSpectator()) { ++ BlockPos blockposition = entityhuman.blockPosition(); + +- if (serverlevel.isVillage(blockpos) && !serverlevel.getBiome(blockpos).is(BiomeTags.WITHOUT_ZOMBIE_SIEGES)) { ++ if (level.isVillage(blockposition) && !level.getBiome(blockposition).is(BiomeTags.WITHOUT_ZOMBIE_SIEGES)) { + for (int i = 0; i < 10; ++i) { +- float f = serverlevel.random.nextFloat() * 6.2831855F; ++ float f = level.random.nextFloat() * 6.2831855F; + +- this.spawnX = blockpos.getX() + Mth.floor(Mth.cos(f) * 32.0F); +- this.spawnY = blockpos.getY(); +- this.spawnZ = blockpos.getZ() + Mth.floor(Mth.sin(f) * 32.0F); +- if (this.findRandomSpawnPos(serverlevel, new BlockPos(this.spawnX, this.spawnY, this.spawnZ)) != null) { ++ this.spawnX = blockposition.getX() + Mth.floor(Mth.cos(f) * 32.0F); ++ this.spawnY = blockposition.getY(); ++ this.spawnZ = blockposition.getZ() + Mth.floor(Mth.sin(f) * 32.0F); ++ if (this.findRandomSpawnPos(level, new BlockPos(this.spawnX, this.spawnY, this.spawnZ)) != null) { + this.nextSpawnTime = 0; + this.zombiesToSpawn = 20; + break; +@@ -108,35 +107,35 @@ + return false; + } + +- private void trySpawn(ServerLevel serverlevel) { +- Vec3 vec3 = this.findRandomSpawnPos(serverlevel, new BlockPos(this.spawnX, this.spawnY, this.spawnZ)); ++ private void trySpawn(ServerLevel level) { ++ Vec3 vec3d = this.findRandomSpawnPos(level, new BlockPos(this.spawnX, this.spawnY, this.spawnZ)); + +- if (vec3 != null) { +- Zombie zombie; ++ if (vec3d != null) { ++ Zombie entityzombie; + + try { +- zombie = new Zombie(serverlevel); +- zombie.finalizeSpawn(serverlevel, serverlevel.getCurrentDifficultyAt(zombie.blockPosition()), MobSpawnType.EVENT, (SpawnGroupData) null, (CompoundTag) null); ++ entityzombie = new Zombie(level); ++ entityzombie.finalizeSpawn(level, level.getCurrentDifficultyAt(entityzombie.blockPosition()), EnumMobSpawn.EVENT, (GroupDataEntity) null, (CompoundTag) null); + } catch (Exception exception) { +- VillageSiege.LOGGER.warn("Failed to create zombie for village siege at {}", vec3, exception); ++ VillageSiege.LOGGER.warn("Failed to create zombie for village siege at {}", vec3d, exception); + return; + } + +- zombie.moveTo(vec3.x, vec3.y, vec3.z, serverlevel.random.nextFloat() * 360.0F, 0.0F); +- serverlevel.addFreshEntityWithPassengers(zombie); ++ entityzombie.moveTo(vec3d.x, vec3d.y, vec3d.z, level.random.nextFloat() * 360.0F, 0.0F); ++ level.addFreshEntityWithPassengers(entityzombie, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_INVASION); // CraftBukkit + } + } + + @Nullable +- private Vec3 findRandomSpawnPos(ServerLevel serverlevel, BlockPos blockpos) { ++ private Vec3 findRandomSpawnPos(ServerLevel level, BlockPos pos) { + for (int i = 0; i < 10; ++i) { +- int j = blockpos.getX() + serverlevel.random.nextInt(16) - 8; +- int k = blockpos.getZ() + serverlevel.random.nextInt(16) - 8; +- int l = serverlevel.getHeight(Heightmap.Types.WORLD_SURFACE, j, k); +- BlockPos blockpos1 = new BlockPos(j, l, k); ++ int j = pos.getX() + level.random.nextInt(16) - 8; ++ int k = pos.getZ() + level.random.nextInt(16) - 8; ++ int l = level.getHeight(Heightmap.Types.WORLD_SURFACE, j, k); ++ BlockPos blockposition1 = new BlockPos(j, l, k); + +- if (serverlevel.isVillage(blockpos1) && Monster.checkMonsterSpawnRules(EntityType.ZOMBIE, serverlevel, MobSpawnType.EVENT, blockpos1, serverlevel.random)) { +- return Vec3.atBottomCenterOf(blockpos1); ++ if (level.isVillage(blockposition1) && Monster.checkMonsterSpawnRules(EntityType.ZOMBIE, level, EnumMobSpawn.EVENT, blockposition1, level.random)) { ++ return Vec3.atBottomCenterOf(blockposition1); + } + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/ambient/Bat.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ambient/Bat.java.patch new file mode 100644 index 0000000000..4b6356a12b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/ambient/Bat.java.patch @@ -0,0 +1,274 @@ +--- a/net/minecraft/world/entity/ambient/Bat.java ++++ b/net/minecraft/world/entity/ambient/Bat.java +@@ -16,18 +16,21 @@ + import net.minecraft.world.entity.AnimationState; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.targeting.TargetingConditions; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class Bat extends AmbientCreature { + +@@ -41,8 +44,8 @@ + @Nullable + private BlockPos targetPosition; + +- public Bat(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Bat(EntityType entityType, Level level) { ++ super(entityType, level); + if (!level.isClientSide) { + this.setResting(true); + } +@@ -50,61 +53,51 @@ + } + + @Override +- @Override + public boolean isFlapping() { + return !this.isResting() && (float) this.tickCount % 10.0F == 0.0F; + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Bat.DATA_ID_FLAGS, (byte) 0); + } + + @Override +- @Override + protected float getSoundVolume() { + return 0.1F; + } + + @Override +- @Override + public float getVoicePitch() { + return super.getVoicePitch() * 0.95F; + } + + @Nullable + @Override +- @Override + public SoundEvent getAmbientSound() { + return this.isResting() && this.random.nextInt(4) != 0 ? null : SoundEvents.BAT_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.BAT_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.BAT_DEATH; + } + + @Override +- @Override + public boolean isPushable() { + return false; + } + + @Override +- @Override + protected void doPush(Entity entity) {} + + @Override +- @Override + protected void pushEntities() {} + + public static AttributeSupplier.Builder createAttributes() { +@@ -115,10 +108,10 @@ + return ((Byte) this.entityData.get(Bat.DATA_ID_FLAGS) & 1) != 0; + } + +- public void setResting(boolean flag) { ++ public void setResting(boolean isResting) { + byte b0 = (Byte) this.entityData.get(Bat.DATA_ID_FLAGS); + +- if (flag) { ++ if (isResting) { + this.entityData.set(Bat.DATA_ID_FLAGS, (byte) (b0 | 1)); + } else { + this.entityData.set(Bat.DATA_ID_FLAGS, (byte) (b0 & -2)); +@@ -127,7 +120,6 @@ + } + + @Override +- @Override + public void tick() { + super.tick(); + if (this.isResting()) { +@@ -141,30 +133,29 @@ + } + + @Override +- @Override + protected void customServerAiStep() { + super.customServerAiStep(); +- BlockPos blockpos = this.blockPosition(); +- BlockPos blockpos1 = blockpos.above(); ++ BlockPos blockposition = this.blockPosition(); ++ BlockPos blockposition1 = blockposition.above(); + + if (this.isResting()) { + boolean flag = this.isSilent(); + +- if (this.level().getBlockState(blockpos1).isRedstoneConductor(this.level(), blockpos)) { ++ if (this.level().getBlockState(blockposition1).isRedstoneConductor(this.level(), blockposition)) { + if (this.random.nextInt(200) == 0) { + this.yHeadRot = (float) this.random.nextInt(360); + } + +- if (this.level().getNearestPlayer(Bat.BAT_RESTING_TARGETING, this) != null) { ++ if (this.level().getNearestPlayer(Bat.BAT_RESTING_TARGETING, this) != null && CraftEventFactory.handleBatToggleSleepEvent(this, true)) { // CraftBukkit - Call BatToggleSleepEvent + this.setResting(false); + if (!flag) { +- this.level().levelEvent((Player) null, 1025, blockpos, 0); ++ this.level().levelEvent((Player) null, 1025, blockposition, 0); + } + } +- } else { ++ } else if (CraftEventFactory.handleBatToggleSleepEvent(this, true)) { // CraftBukkit - Call BatToggleSleepEvent + this.setResting(false); + if (!flag) { +- this.level().levelEvent((Player) null, 1025, blockpos, 0); ++ this.level().levelEvent((Player) null, 1025, blockposition, 0); + } + } + } else { +@@ -179,16 +170,16 @@ + double d0 = (double) this.targetPosition.getX() + 0.5D - this.getX(); + double d1 = (double) this.targetPosition.getY() + 0.1D - this.getY(); + double d2 = (double) this.targetPosition.getZ() + 0.5D - this.getZ(); +- Vec3 vec3 = this.getDeltaMovement(); +- Vec3 vec31 = vec3.add((Math.signum(d0) * 0.5D - vec3.x) * 0.10000000149011612D, (Math.signum(d1) * 0.699999988079071D - vec3.y) * 0.10000000149011612D, (Math.signum(d2) * 0.5D - vec3.z) * 0.10000000149011612D); ++ Vec3 vec3d = this.getDeltaMovement(); ++ Vec3 vec3d1 = vec3d.add((Math.signum(d0) * 0.5D - vec3d.x) * 0.10000000149011612D, (Math.signum(d1) * 0.699999988079071D - vec3d.y) * 0.10000000149011612D, (Math.signum(d2) * 0.5D - vec3d.z) * 0.10000000149011612D); + +- this.setDeltaMovement(vec31); +- float f = (float) (Mth.atan2(vec31.z, vec31.x) * 57.2957763671875D) - 90.0F; ++ this.setDeltaMovement(vec3d1); ++ float f = (float) (Mth.atan2(vec3d1.z, vec3d1.x) * 57.2957763671875D) - 90.0F; + float f1 = Mth.wrapDegrees(f - this.getYRot()); + + this.zza = 0.5F; + this.setYRot(this.getYRot() + f1); +- if (this.random.nextInt(100) == 0 && this.level().getBlockState(blockpos1).isRedstoneConductor(this.level(), blockpos1)) { ++ if (this.random.nextInt(100) == 0 && this.level().getBlockState(blockposition1).isRedstoneConductor(this.level(), blockposition1) && CraftEventFactory.handleBatToggleSleepEvent(this, false)) { // CraftBukkit - Call BatToggleSleepEvent + this.setResting(true); + } + } +@@ -196,63 +187,57 @@ + } + + @Override +- @Override + protected Entity.MovementEmission getMovementEmission() { + return Entity.MovementEmission.EVENTS; + } + + @Override +- @Override +- protected void checkFallDamage(double d0, boolean flag, BlockState blockstate, BlockPos blockpos) {} ++ protected void checkFallDamage(double y, boolean flag, IBlockData onGround, BlockPos state) {} + + @Override +- @Override + public boolean isIgnoringBlockTriggers() { + return true; + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- if (this.isInvulnerableTo(damagesource)) { ++ public boolean hurt(DamageSource source, float amount) { ++ if (this.isInvulnerableTo(source)) { + return false; + } else { +- if (!this.level().isClientSide && this.isResting()) { ++ if (!this.level().isClientSide && this.isResting() && CraftEventFactory.handleBatToggleSleepEvent(this, true)) { // CraftBukkit - Call BatToggleSleepEvent + this.setResting(false); + } + +- return super.hurt(damagesource, f); ++ return super.hurt(source, amount); + } + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.entityData.set(Bat.DATA_ID_FLAGS, compoundtag.getByte("BatFlags")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.entityData.set(Bat.DATA_ID_FLAGS, compound.getByte("BatFlags")); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putByte("BatFlags", (Byte) this.entityData.get(Bat.DATA_ID_FLAGS)); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putByte("BatFlags", (Byte) this.entityData.get(Bat.DATA_ID_FLAGS)); + } + +- public static boolean checkBatSpawnRules(EntityType entitytype, LevelAccessor levelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- if (blockpos.getY() >= levelaccessor.getSeaLevel()) { ++ public static boolean checkBatSpawnRules(EntityType bat, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ if (pos.getY() >= level.getSeaLevel()) { + return false; + } else { +- int i = levelaccessor.getMaxLocalRawBrightness(blockpos); ++ int i = level.getMaxLocalRawBrightness(pos); + byte b0 = 4; + + if (isHalloween()) { + b0 = 7; +- } else if (randomsource.nextBoolean()) { ++ } else if (random.nextBoolean()) { + return false; + } + +- return i > randomsource.nextInt(b0) ? false : checkMobSpawnRules(entitytype, levelaccessor, mobspawntype, blockpos, randomsource); ++ return i > random.nextInt(b0) ? false : checkMobSpawnRules(bat, level, spawnType, pos, random); + } + } + +@@ -265,9 +250,8 @@ + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return entitydimensions.height / 2.0F; ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { ++ return size.height / 2.0F; + } + + private void setupAnimationStates() { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Animal.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Animal.java.patch new file mode 100644 index 0000000000..c9a1609d12 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Animal.java.patch @@ -0,0 +1,329 @@ +--- a/net/minecraft/world/entity/animal/Animal.java ++++ b/net/minecraft/world/entity/animal/Animal.java +@@ -12,13 +12,13 @@ + import net.minecraft.stats.Stats; + import net.minecraft.tags.BlockTags; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.ExperienceOrb; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +@@ -29,22 +29,27 @@ + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.pathfinder.BlockPathTypes; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityBreedEvent; ++import org.bukkit.event.entity.EntityEnterLoveModeEvent; ++// CraftBukkit end + + public abstract class Animal extends AgeableMob { + + protected static final int PARENT_AGE_AFTER_BREEDING = 6000; +- private int inLove; ++ public int inLove; + @Nullable +- private UUID loveCause; ++ public UUID loveCause; ++ public ItemStack breedItem; // CraftBukkit - Add breedItem variable + +- protected Animal(EntityType entitytype, Level level) { +- super(entitytype, level); ++ protected Animal(EntityType entityType, Level level) { ++ super(entityType, level); + this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, 16.0F); + this.setPathfindingMalus(BlockPathTypes.DAMAGE_FIRE, -1.0F); + } + + @Override +- @Override + protected void customServerAiStep() { + if (this.getAge() != 0) { + this.inLove = 0; +@@ -54,7 +59,6 @@ + } + + @Override +- @Override + public void aiStep() { + super.aiStep(); + if (this.getAge() != 0) { +@@ -75,89 +79,86 @@ + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- if (this.isInvulnerableTo(damagesource)) { ++ public boolean hurt(DamageSource source, float amount) { ++ if (this.isInvulnerableTo(source)) { + return false; + } else { ++ // CraftBukkit start ++ boolean result = super.hurt(source, amount); ++ if (result) { + this.inLove = 0; +- return super.hurt(damagesource, f); ++ } ++ return result; ++ // CraftBukkit end + } + } + + @Override +- @Override +- public float getWalkTargetValue(BlockPos blockpos, LevelReader levelreader) { +- return levelreader.getBlockState(blockpos.below()).is(Blocks.GRASS_BLOCK) ? 10.0F : levelreader.getPathfindingCostFromLightLevels(blockpos); ++ public float getWalkTargetValue(BlockPos pos, LevelReader level) { ++ return level.getBlockState(pos.below()).is(Blocks.GRASS_BLOCK) ? 10.0F : level.getPathfindingCostFromLightLevels(pos); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("InLove", this.inLove); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("InLove", this.inLove); + if (this.loveCause != null) { +- compoundtag.putUUID("LoveCause", this.loveCause); ++ compound.putUUID("LoveCause", this.loveCause); + } + + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.inLove = compoundtag.getInt("InLove"); +- this.loveCause = compoundtag.hasUUID("LoveCause") ? compoundtag.getUUID("LoveCause") : null; ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.inLove = compound.getInt("InLove"); ++ this.loveCause = compound.hasUUID("LoveCause") ? compound.getUUID("LoveCause") : null; + } + +- public static boolean checkAnimalSpawnRules(EntityType entitytype, LevelAccessor levelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- boolean flag = MobSpawnType.ignoresLightRequirements(mobspawntype) || isBrightEnoughToSpawn(levelaccessor, blockpos); ++ public static boolean checkAnimalSpawnRules(EntityType animal, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ boolean flag = EnumMobSpawn.ignoresLightRequirements(spawnType) || isBrightEnoughToSpawn(level, pos); + +- return levelaccessor.getBlockState(blockpos.below()).is(BlockTags.ANIMALS_SPAWNABLE_ON) && flag; ++ return level.getBlockState(pos.below()).is(BlockTags.ANIMALS_SPAWNABLE_ON) && flag; + } + +- protected static boolean isBrightEnoughToSpawn(BlockAndTintGetter blockandtintgetter, BlockPos blockpos) { +- return blockandtintgetter.getRawBrightness(blockpos, 0) > 8; ++ protected static boolean isBrightEnoughToSpawn(BlockAndTintGetter level, BlockPos pos) { ++ return level.getRawBrightness(pos, 0) > 8; + } + + @Override +- @Override + public int getAmbientSoundInterval() { + return 120; + } + + @Override +- @Override +- public boolean removeWhenFarAway(double d0) { ++ public boolean removeWhenFarAway(double distanceToClosestPlayer) { + return false; + } + + @Override +- @Override + public int getExperienceReward() { + return 1 + this.level().random.nextInt(3); + } + +- public boolean isFood(ItemStack itemstack) { +- return itemstack.is(Items.WHEAT); ++ public boolean isFood(ItemStack stack) { ++ return stack.is(Items.WHEAT); + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (this.isFood(itemstack)) { + int i = this.getAge(); + + if (!this.level().isClientSide && i == 0 && this.canFallInLove()) { +- this.usePlayerItem(player, interactionhand, itemstack); ++ this.usePlayerItem(player, hand, itemstack); + this.setInLove(player); + return InteractionResult.SUCCESS; + } + + if (this.isBaby()) { +- this.usePlayerItem(player, interactionhand, itemstack); ++ this.usePlayerItem(player, hand, itemstack); + this.ageUp(getSpeedUpSecondsWhenFeeding(-i), true); + return InteractionResult.sidedSuccess(this.level().isClientSide); + } +@@ -167,12 +168,12 @@ + } + } + +- return super.mobInteract(player, interactionhand); ++ return super.mobInteract(player, hand); + } + +- protected void usePlayerItem(Player player, InteractionHand interactionhand, ItemStack itemstack) { ++ protected void usePlayerItem(Player player, EnumHand hand, ItemStack stack) { + if (!player.getAbilities().instabuild) { +- itemstack.shrink(1); ++ stack.shrink(1); + } + + } +@@ -182,16 +183,23 @@ + } + + public void setInLove(@Nullable Player player) { +- this.inLove = 600; ++ // CraftBukkit start ++ EntityEnterLoveModeEvent entityEnterLoveModeEvent = CraftEventFactory.callEntityEnterLoveModeEvent(player, this, 600); ++ if (entityEnterLoveModeEvent.isCancelled()) { ++ return; ++ } ++ this.inLove = entityEnterLoveModeEvent.getTicksInLove(); ++ // CraftBukkit end + if (player != null) { + this.loveCause = player.getUUID(); + } ++ this.breedItem = player.getInventory().getSelected(); // CraftBukkit + + this.level().broadcastEntityEvent(this, (byte) 18); + } + +- public void setInLoveTime(int i) { +- this.inLove = i; ++ public void setInLoveTime(int inLove) { ++ this.inLove = inLove; + } + + public int getInLoveTime() { +@@ -203,9 +211,9 @@ + if (this.loveCause == null) { + return null; + } else { +- Player player = this.level().getPlayerByUUID(this.loveCause); ++ Player entityhuman = this.level().getPlayerByUUID(this.loveCause); + +- return player instanceof ServerPlayer ? (ServerPlayer) player : null; ++ return entityhuman instanceof ServerPlayer ? (ServerPlayer) entityhuman : null; + } + } + +@@ -217,43 +225,63 @@ + this.inLove = 0; + } + +- public boolean canMate(Animal animal) { +- return animal == this ? false : (animal.getClass() != this.getClass() ? false : this.isInLove() && animal.isInLove()); ++ public boolean canMate(Animal otherAnimal) { ++ return otherAnimal == this ? false : (otherAnimal.getClass() != this.getClass() ? false : this.isInLove() && otherAnimal.isInLove()); + } + +- public void spawnChildFromBreeding(ServerLevel serverlevel, Animal animal) { +- AgeableMob ageablemob = this.getBreedOffspring(serverlevel, animal); ++ public void spawnChildFromBreeding(ServerLevel level, Animal mate) { ++ AgeableMob entityageable = this.getBreedOffspring(level, mate); + +- if (ageablemob != null) { +- ageablemob.setBaby(true); +- ageablemob.moveTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F); +- this.finalizeSpawnChildFromBreeding(serverlevel, animal, ageablemob); +- serverlevel.addFreshEntityWithPassengers(ageablemob); ++ if (entityageable != null) { ++ entityageable.setBaby(true); ++ entityageable.moveTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F); ++ // CraftBukkit start - call EntityBreedEvent ++ ServerPlayer breeder = Optional.ofNullable(this.getLoveCause()).or(() -> { ++ return Optional.ofNullable(mate.getLoveCause()); ++ }).orElse(null); ++ int experience = this.getRandom().nextInt(7) + 1; ++ EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(entityageable, this, mate, breeder, this.breedItem, experience); ++ if (entityBreedEvent.isCancelled()) { ++ return; ++ } ++ experience = entityBreedEvent.getExperience(); ++ this.finalizeSpawnChildFromBreeding(level, mate, entityageable, experience); ++ level.addFreshEntityWithPassengers(entityageable, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); ++ // CraftBukkit end + } + } + +- public void finalizeSpawnChildFromBreeding(ServerLevel serverlevel, Animal animal, @Nullable AgeableMob ageablemob) { ++ public void finalizeSpawnChildFromBreeding(ServerLevel level, Animal animal, @Nullable AgeableMob baby) { ++ // CraftBukkit start ++ this.finalizeSpawnChildFromBreeding(level, animal, baby, this.getRandom().nextInt(7) + 1); ++ } ++ ++ public void finalizeSpawnChildFromBreeding(ServerLevel worldserver, Animal entityanimal, @Nullable AgeableMob entityageable, int experience) { ++ // CraftBukkit end + Optional.ofNullable(this.getLoveCause()).or(() -> { +- return Optional.ofNullable(animal.getLoveCause()); +- }).ifPresent((serverplayer) -> { +- serverplayer.awardStat(Stats.ANIMALS_BRED); +- CriteriaTriggers.BRED_ANIMALS.trigger(serverplayer, this, animal, ageablemob); ++ return Optional.ofNullable(entityanimal.getLoveCause()); ++ }).ifPresent((entityplayer) -> { ++ entityplayer.awardStat(Stats.ANIMALS_BRED); ++ CriteriaTriggers.BRED_ANIMALS.trigger(entityplayer, this, entityanimal, entityageable); + }); + this.setAge(6000); +- animal.setAge(6000); ++ entityanimal.setAge(6000); + this.resetLove(); +- animal.resetLove(); +- serverlevel.broadcastEntityEvent(this, (byte) 18); +- if (serverlevel.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +- serverlevel.addFreshEntity(new ExperienceOrb(serverlevel, this.getX(), this.getY(), this.getZ(), this.getRandom().nextInt(7) + 1)); ++ entityanimal.resetLove(); ++ worldserver.broadcastEntityEvent(this, (byte) 18); ++ if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { ++ // CraftBukkit start - use event experience ++ if (experience > 0) { ++ worldserver.addFreshEntity(new ExperienceOrb(worldserver, this.getX(), this.getY(), this.getZ(), experience)); ++ } ++ // CraftBukkit end + } + + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 18) { ++ public void handleEntityEvent(byte id) { ++ if (id == 18) { + for (int i = 0; i < 7; ++i) { + double d0 = this.random.nextGaussian() * 0.02D; + double d1 = this.random.nextGaussian() * 0.02D; +@@ -262,7 +290,7 @@ + this.level().addParticle(ParticleTypes.HEART, this.getRandomX(1.0D), this.getRandomY() + 0.5D, this.getRandomZ(1.0D), d0, d1, d2); + } + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Bee.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Bee.java.patch new file mode 100644 index 0000000000..dcaa5d7d5d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Bee.java.patch @@ -0,0 +1,1181 @@ +--- a/net/minecraft/world/entity/animal/Bee.java ++++ b/net/minecraft/world/entity/animal/Bee.java +@@ -39,13 +39,13 @@ + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobType; + import net.minecraft.world.entity.NeutralMob; + import net.minecraft.world.entity.PathfinderMob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.FlyingMoveControl; +@@ -82,15 +82,20 @@ + import net.minecraft.world.level.block.entity.BeehiveBlockEntity; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BlockEntityType; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.block.state.properties.BlockPropertyDoubleBlockHalf; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; +-import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.level.pathfinder.Path; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityPotionEffectEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end + +-public class Bee extends Animal implements NeutralMob, FlyingAnimal { ++public class Bee extends Animal implements NeutralMob, EntityBird { + + public static final float FLAP_DEGREES_PER_TICK = 120.32113F; + public static final int TICKS_PER_FLAP = Mth.ceil(1.4959966F); +@@ -124,7 +129,7 @@ + private float rollAmountO; + private int timeSinceSting; + int ticksWithoutNectarSinceExitingHive; +- private int stayOutOfHiveCountdown; ++ public int stayOutOfHiveCountdown; + private int numCropsGrownSincePollination; + private static final int COOLDOWN_BEFORE_LOCATING_NEW_HIVE = 200; + int remainingCooldownBeforeLocatingNewHive; +@@ -133,14 +138,14 @@ + @Nullable + BlockPos savedFlowerPos; + @Nullable +- BlockPos hivePos; ++ public BlockPos hivePos; + Bee.BeePollinateGoal beePollinateGoal; + Bee.BeeGoToHiveGoal goToHiveGoal; + private Bee.BeeGoToKnownFlowerGoal goToKnownFlowerGoal; + private int underWaterTicks; + +- public Bee(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Bee(EntityType entityType, Level level) { ++ super(entityType, level); + this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(this.random, 20, 60); + this.moveControl = new FlyingMoveControl(this, 20, true); + this.lookControl = new Bee.BeeLookControl(this); +@@ -152,7 +157,6 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Bee.DATA_FLAGS_ID, (byte) 0); +@@ -160,13 +164,11 @@ + } + + @Override +- @Override +- public float getWalkTargetValue(BlockPos blockpos, LevelReader levelreader) { +- return levelreader.getBlockState(blockpos).isAir() ? 10.0F : 0.0F; ++ public float getWalkTargetValue(BlockPos pos, LevelReader level) { ++ return level.getBlockState(pos).isAir() ? 10.0F : 0.0F; + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new Bee.BeeAttackGoal(this, 1.399999976158142D, true)); + this.goalSelector.addGoal(1, new Bee.BeeEnterHiveGoal()); +@@ -189,49 +191,53 @@ + } + + @Override ++ public void addAdditionalSaveData(CompoundTag compound) { ++ // CraftBukkit start - selectively save data ++ addAdditionalSaveData(compound, true); ++ } ++ + @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- if (this.hasHive()) { +- compoundtag.put("HivePos", NbtUtils.writeBlockPos(this.getHivePos())); ++ public void addAdditionalSaveData(CompoundTag nbttagcompound, boolean includeAll) { ++ // CraftBukkit end ++ super.addAdditionalSaveData(nbttagcompound); ++ if (includeAll && this.hasHive()) { // CraftBukkit - selectively save hive ++ nbttagcompound.put("HivePos", NbtUtils.writeBlockPos(this.getHivePos())); + } + +- if (this.hasSavedFlowerPos()) { +- compoundtag.put("FlowerPos", NbtUtils.writeBlockPos(this.getSavedFlowerPos())); ++ if (includeAll && this.hasSavedFlowerPos()) { // CraftBukkit - selectively save flower ++ nbttagcompound.put("FlowerPos", NbtUtils.writeBlockPos(this.getSavedFlowerPos())); + } + +- compoundtag.putBoolean("HasNectar", this.hasNectar()); +- compoundtag.putBoolean("HasStung", this.hasStung()); +- compoundtag.putInt("TicksSincePollination", this.ticksWithoutNectarSinceExitingHive); +- compoundtag.putInt("CannotEnterHiveTicks", this.stayOutOfHiveCountdown); +- compoundtag.putInt("CropsGrownSincePollination", this.numCropsGrownSincePollination); +- this.addPersistentAngerSaveData(compoundtag); ++ nbttagcompound.putBoolean("HasNectar", this.hasNectar()); ++ nbttagcompound.putBoolean("HasStung", this.hasStung()); ++ nbttagcompound.putInt("TicksSincePollination", this.ticksWithoutNectarSinceExitingHive); ++ nbttagcompound.putInt("CannotEnterHiveTicks", this.stayOutOfHiveCountdown); ++ nbttagcompound.putInt("CropsGrownSincePollination", this.numCropsGrownSincePollination); ++ this.addPersistentAngerSaveData(nbttagcompound); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { ++ public void readAdditionalSaveData(CompoundTag compound) { + this.hivePos = null; +- if (compoundtag.contains("HivePos")) { +- this.hivePos = NbtUtils.readBlockPos(compoundtag.getCompound("HivePos")); ++ if (compound.contains("HivePos")) { ++ this.hivePos = NbtUtils.readBlockPos(compound.getCompound("HivePos")); + } + + this.savedFlowerPos = null; +- if (compoundtag.contains("FlowerPos")) { +- this.savedFlowerPos = NbtUtils.readBlockPos(compoundtag.getCompound("FlowerPos")); ++ if (compound.contains("FlowerPos")) { ++ this.savedFlowerPos = NbtUtils.readBlockPos(compound.getCompound("FlowerPos")); + } + +- super.readAdditionalSaveData(compoundtag); +- this.setHasNectar(compoundtag.getBoolean("HasNectar")); +- this.setHasStung(compoundtag.getBoolean("HasStung")); +- this.ticksWithoutNectarSinceExitingHive = compoundtag.getInt("TicksSincePollination"); +- this.stayOutOfHiveCountdown = compoundtag.getInt("CannotEnterHiveTicks"); +- this.numCropsGrownSincePollination = compoundtag.getInt("CropsGrownSincePollination"); +- this.readPersistentAngerSaveData(this.level(), compoundtag); ++ super.readAdditionalSaveData(compound); ++ this.setHasNectar(compound.getBoolean("HasNectar")); ++ this.setHasStung(compound.getBoolean("HasStung")); ++ this.ticksWithoutNectarSinceExitingHive = compound.getInt("TicksSincePollination"); ++ this.stayOutOfHiveCountdown = compound.getInt("CannotEnterHiveTicks"); ++ this.numCropsGrownSincePollination = compound.getInt("CropsGrownSincePollination"); ++ this.readPersistentAngerSaveData(this.level(), compound); + } + + @Override +- @Override + public boolean doHurtTarget(Entity entity) { + boolean flag = entity.hurt(this.damageSources().sting(this), (float) ((int) this.getAttributeValue(Attributes.ATTACK_DAMAGE))); + +@@ -248,7 +254,7 @@ + } + + if (b0 > 0) { +- ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.POISON, b0 * 20, 0), this); ++ ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.POISON, b0 * 20, 0), this, EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + +@@ -261,7 +267,6 @@ + } + + @Override +- @Override + public void tick() { + super.tick(); + if (this.hasNectar() && this.getCropsGrownSincePollination() < 10 && this.random.nextFloat() < 0.05F) { +@@ -273,15 +278,15 @@ + this.updateRollAmount(); + } + +- private void spawnFluidParticle(Level level, double d0, double d1, double d2, double d3, double d4, ParticleOptions particleoptions) { +- level.addParticle(particleoptions, Mth.lerp(level.random.nextDouble(), d0, d1), d4, Mth.lerp(level.random.nextDouble(), d2, d3), 0.0D, 0.0D, 0.0D); ++ private void spawnFluidParticle(Level level, double startX, double d1, double endX, double d3, double startZ, ParticleOptions particleparam) { ++ level.addParticle(particleparam, Mth.lerp(level.random.nextDouble(), startX, d1), startZ, Mth.lerp(level.random.nextDouble(), endX, d3), 0.0D, 0.0D, 0.0D); + } + +- void pathfindRandomlyTowards(BlockPos blockpos) { +- Vec3 vec3 = Vec3.atBottomCenterOf(blockpos); ++ void pathfindRandomlyTowards(BlockPos pos) { ++ Vec3 vec3d = Vec3.atBottomCenterOf(pos); + byte b0 = 0; +- BlockPos blockpos1 = this.blockPosition(); +- int i = (int) vec3.y - blockpos1.getY(); ++ BlockPos blockposition1 = this.blockPosition(); ++ int i = (int) vec3d.y - blockposition1.getY(); + + if (i > 2) { + b0 = 4; +@@ -291,18 +296,18 @@ + + int j = 6; + int k = 8; +- int l = blockpos1.distManhattan(blockpos); ++ int l = blockposition1.distManhattan(pos); + + if (l < 15) { + j = l / 2; + k = l / 2; + } + +- Vec3 vec31 = AirRandomPos.getPosTowards(this, j, k, b0, vec3, 0.3141592741012573D); ++ Vec3 vec3d1 = AirRandomPos.getPosTowards(this, j, k, b0, vec3d, 0.3141592741012573D); + +- if (vec31 != null) { ++ if (vec3d1 != null) { + this.navigation.setMaxVisitedNodesMultiplier(0.5F); +- this.navigation.moveTo(vec31.x, vec31.y, vec31.z, 1.0D); ++ this.navigation.moveTo(vec3d1.x, vec3d1.y, vec3d1.z, 1.0D); + } + } + +@@ -315,8 +320,8 @@ + return this.savedFlowerPos != null; + } + +- public void setSavedFlowerPos(BlockPos blockpos) { +- this.savedFlowerPos = blockpos; ++ public void setSavedFlowerPos(BlockPos savedFlowerPos) { ++ this.savedFlowerPos = savedFlowerPos; + } + + @VisibleForDebug +@@ -343,12 +348,12 @@ + } + } + +- public void setStayOutOfHiveCountdown(int i) { +- this.stayOutOfHiveCountdown = i; ++ public void setStayOutOfHiveCountdown(int stayOutOfHiveCountdown) { ++ this.stayOutOfHiveCountdown = stayOutOfHiveCountdown; + } + +- public float getRollAmount(float f) { +- return Mth.lerp(f, this.rollAmountO, this.rollAmount); ++ public float getRollAmount(float partialTick) { ++ return Mth.lerp(partialTick, this.rollAmountO, this.rollAmount); + } + + private void updateRollAmount() { +@@ -362,7 +367,6 @@ + } + + @Override +- @Override + protected void customServerAiStep() { + boolean flag = this.hasStung(); + +@@ -401,47 +405,42 @@ + if (this.hivePos == null) { + return false; + } else { +- BlockEntity blockentity = this.level().getBlockEntity(this.hivePos); ++ BlockEntity tileentity = this.level().getBlockEntity(this.hivePos); + +- return blockentity instanceof BeehiveBlockEntity && ((BeehiveBlockEntity) blockentity).isFireNearby(); ++ return tileentity instanceof BeehiveBlockEntity && ((BeehiveBlockEntity) tileentity).isFireNearby(); + } + } + + @Override +- @Override + public int getRemainingPersistentAngerTime() { + return (Integer) this.entityData.get(Bee.DATA_REMAINING_ANGER_TIME); + } + + @Override +- @Override +- public void setRemainingPersistentAngerTime(int i) { +- this.entityData.set(Bee.DATA_REMAINING_ANGER_TIME, i); ++ public void setRemainingPersistentAngerTime(int time) { ++ this.entityData.set(Bee.DATA_REMAINING_ANGER_TIME, time); + } + + @Nullable + @Override +- @Override + public UUID getPersistentAngerTarget() { + return this.persistentAngerTarget; + } + + @Override +- @Override +- public void setPersistentAngerTarget(@Nullable UUID uuid) { +- this.persistentAngerTarget = uuid; ++ public void setPersistentAngerTarget(@Nullable UUID target) { ++ this.persistentAngerTarget = target; + } + + @Override +- @Override + public void startPersistentAngerTimer() { + this.setRemainingPersistentAngerTime(Bee.PERSISTENT_ANGER_TIME.sample(this.random)); + } + +- private boolean doesHiveHaveSpace(BlockPos blockpos) { +- BlockEntity blockentity = this.level().getBlockEntity(blockpos); ++ private boolean doesHiveHaveSpace(BlockPos hivePos) { ++ BlockEntity tileentity = this.level().getBlockEntity(hivePos); + +- return blockentity instanceof BeehiveBlockEntity ? !((BeehiveBlockEntity) blockentity).isFull() : false; ++ return tileentity instanceof BeehiveBlockEntity ? !((BeehiveBlockEntity) tileentity).isFull() : false; + } + + @VisibleForDebug +@@ -461,7 +460,6 @@ + } + + @Override +- @Override + protected void sendDebugPackets() { + super.sendDebugPackets(); + DebugPackets.sendBeeInfo(this); +@@ -480,7 +478,6 @@ + } + + @Override +- @Override + public void aiStep() { + super.aiStep(); + if (!this.level().isClientSide) { +@@ -512,9 +509,9 @@ + } else if (this.isTooFarAway(this.hivePos)) { + return false; + } else { +- BlockEntity blockentity = this.level().getBlockEntity(this.hivePos); ++ BlockEntity tileentity = this.level().getBlockEntity(this.hivePos); + +- return blockentity != null && blockentity.getType() == BlockEntityType.BEEHIVE; ++ return tileentity != null && tileentity.getType() == BlockEntityType.BEEHIVE; + } + } + +@@ -522,45 +519,45 @@ + return this.getFlag(8); + } + +- void setHasNectar(boolean flag) { +- if (flag) { ++ public void setHasNectar(boolean hasNectar) { ++ if (hasNectar) { + this.resetTicksWithoutNectarSinceExitingHive(); + } + +- this.setFlag(8, flag); ++ this.setFlag(8, hasNectar); + } + + public boolean hasStung() { + return this.getFlag(4); + } + +- private void setHasStung(boolean flag) { +- this.setFlag(4, flag); ++ public void setHasStung(boolean hasStung) { ++ this.setFlag(4, hasStung); + } + + private boolean isRolling() { + return this.getFlag(2); + } + +- private void setRolling(boolean flag) { +- this.setFlag(2, flag); ++ private void setRolling(boolean isRolling) { ++ this.setFlag(2, isRolling); + } + +- boolean isTooFarAway(BlockPos blockpos) { +- return !this.closerThan(blockpos, 32); ++ boolean isTooFarAway(BlockPos pos) { ++ return !this.closerThan(pos, 32); + } + +- private void setFlag(int i, boolean flag) { +- if (flag) { +- this.entityData.set(Bee.DATA_FLAGS_ID, (byte) ((Byte) this.entityData.get(Bee.DATA_FLAGS_ID) | i)); ++ private void setFlag(int flagId, boolean value) { ++ if (value) { ++ this.entityData.set(Bee.DATA_FLAGS_ID, (byte) ((Byte) this.entityData.get(Bee.DATA_FLAGS_ID) | flagId)); + } else { +- this.entityData.set(Bee.DATA_FLAGS_ID, (byte) ((Byte) this.entityData.get(Bee.DATA_FLAGS_ID) & ~i)); ++ this.entityData.set(Bee.DATA_FLAGS_ID, (byte) ((Byte) this.entityData.get(Bee.DATA_FLAGS_ID) & ~flagId)); + } + + } + +- private boolean getFlag(int i) { +- return ((Byte) this.entityData.get(Bee.DATA_FLAGS_ID) & i) != 0; ++ private boolean getFlag(int flagId) { ++ return ((Byte) this.entityData.get(Bee.DATA_FLAGS_ID) & flagId) != 0; + } + + public static AttributeSupplier.Builder createAttributes() { +@@ -568,17 +565,14 @@ + } + + @Override +- @Override + protected PathNavigation createNavigation(Level level) { +- FlyingPathNavigation flyingpathnavigation = new FlyingPathNavigation(this, level) { ++ FlyingPathNavigation navigationflying = new FlyingPathNavigation(this, level) { + @Override +- @Override +- public boolean isStableDestination(BlockPos blockpos) { +- return !this.level.getBlockState(blockpos.below()).isAir(); ++ public boolean isStableDestination(BlockPos pos) { ++ return !this.level.getBlockState(pos.below()).isAir(); + } + + @Override +- @Override + public void tick() { + if (!Bee.this.beePollinateGoal.isPollinating()) { + super.tick(); +@@ -586,75 +580,64 @@ + } + }; + +- flyingpathnavigation.setCanOpenDoors(false); +- flyingpathnavigation.setCanFloat(false); +- flyingpathnavigation.setCanPassDoors(true); +- return flyingpathnavigation; ++ navigationflying.setCanOpenDoors(false); ++ navigationflying.setCanFloat(false); ++ navigationflying.setCanPassDoors(true); ++ return navigationflying; + } + + @Override +- @Override +- public boolean isFood(ItemStack itemstack) { +- return itemstack.is(ItemTags.FLOWERS); ++ public boolean isFood(ItemStack stack) { ++ return stack.is(ItemTags.FLOWERS); + } + +- boolean isFlowerValid(BlockPos blockpos) { +- return this.level().isLoaded(blockpos) && this.level().getBlockState(blockpos).is(BlockTags.FLOWERS); ++ boolean isFlowerValid(BlockPos pos) { ++ return this.level().isLoaded(pos) && this.level().getBlockState(pos).is(BlockTags.FLOWERS); + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) {} ++ protected void playStepSound(BlockPos pos, IBlockData block) {} + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return null; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.BEE_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.BEE_DEATH; + } + + @Override +- @Override + protected float getSoundVolume() { + return 0.4F; + } + + @Nullable + @Override +- @Override +- public Bee getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { +- return (Bee) EntityType.BEE.create(serverlevel); ++ public Bee getBreedOffspring(ServerLevel level, AgeableMob otherParent) { ++ return (Bee) EntityType.BEE.create(level); + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return this.isBaby() ? entitydimensions.height * 0.5F : entitydimensions.height * 0.5F; ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { ++ return this.isBaby() ? size.height * 0.5F : size.height * 0.5F; + } + + @Override +- @Override +- protected void checkFallDamage(double d0, boolean flag, BlockState blockstate, BlockPos blockpos) {} ++ protected void checkFallDamage(double y, boolean flag, IBlockData onGround, BlockPos state) {} + + @Override +- @Override + public boolean isFlapping() { + return this.isFlying() && this.tickCount % Bee.TICKS_PER_FLAP == 0; + } + + @Override +- @Override + public boolean isFlying() { + return !this.onGround(); + } +@@ -665,39 +648,38 @@ + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- if (this.isInvulnerableTo(damagesource)) { ++ public boolean hurt(DamageSource source, float amount) { ++ if (this.isInvulnerableTo(source)) { + return false; + } else { +- if (!this.level().isClientSide) { ++ // CraftBukkit start - Only stop pollinating if entity was damaged ++ boolean result = super.hurt(source, amount); ++ if (result && !this.level().isClientSide) { ++ // CraftBukkit end + this.beePollinateGoal.stopPollinating(); + } + +- return super.hurt(damagesource, f); ++ return result; // CraftBukkit + } + } + + @Override +- @Override +- public MobType getMobType() { +- return MobType.ARTHROPOD; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.ARTHROPOD; + } + + @Override +- @Override +- protected void jumpInLiquid(TagKey tagkey) { ++ protected void jumpInLiquid(TagKey fluidTag) { + this.setDeltaMovement(this.getDeltaMovement().add(0.0D, 0.01D, 0.0D)); + } + + @Override +- @Override + public Vec3 getLeashOffset() { + return new Vec3(0.0D, (double) (0.5F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.2F)); + } + +- boolean closerThan(BlockPos blockpos, int i) { +- return blockpos.closerThan(this.blockPosition(), (double) i); ++ boolean closerThan(BlockPos pos, int distance) { ++ return pos.closerThan(this.blockPosition(), (double) distance); + } + + private class BeePollinateGoal extends Bee.BaseBeeGoal { +@@ -705,8 +687,8 @@ + private static final int MIN_POLLINATION_TICKS = 400; + private static final int MIN_FIND_FLOWER_RETRY_COOLDOWN = 20; + private static final int MAX_FIND_FLOWER_RETRY_COOLDOWN = 60; +- private final Predicate VALID_POLLINATION_BLOCKS = (blockstate) -> { +- return blockstate.hasProperty(BlockStateProperties.WATERLOGGED) && (Boolean) blockstate.getValue(BlockStateProperties.WATERLOGGED) ? false : (blockstate.is(BlockTags.FLOWERS) ? (blockstate.is(Blocks.SUNFLOWER) ? blockstate.getValue(DoublePlantBlock.HALF) == DoubleBlockHalf.UPPER : true) : false); ++ private final Predicate VALID_POLLINATION_BLOCKS = (iblockdata) -> { ++ return iblockdata.hasProperty(BlockStateProperties.WATERLOGGED) && (Boolean) iblockdata.getValue(BlockStateProperties.WATERLOGGED) ? false : (iblockdata.is(BlockTags.FLOWERS) ? (iblockdata.is(Blocks.SUNFLOWER) ? iblockdata.getValue(DoublePlantBlock.HALF) == BlockPropertyDoubleBlockHalf.UPPER : true) : false); + }; + private static final double ARRIVAL_THRESHOLD = 0.1D; + private static final int POSITION_CHANGE_CHANCE = 25; +@@ -723,11 +705,10 @@ + + BeePollinateGoal() { + super(); +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +- @Override + public boolean canBeeUse() { + if (Bee.this.remainingCooldownBeforeLocatingNewFlower > 0) { + return false; +@@ -750,7 +731,6 @@ + } + + @Override +- @Override + public boolean canBeeContinueToUse() { + if (!this.pollinating) { + return false; +@@ -781,7 +761,6 @@ + } + + @Override +- @Override + public void start() { + this.successfulPollinatingTicks = 0; + this.pollinatingTicks = 0; +@@ -791,7 +770,6 @@ + } + + @Override +- @Override + public void stop() { + if (this.hasPollinatedLongEnough()) { + Bee.this.setHasNectar(true); +@@ -803,26 +781,24 @@ + } + + @Override +- @Override + public boolean requiresUpdateEveryTick() { + return true; + } + + @Override +- @Override + public void tick() { + ++this.pollinatingTicks; + if (this.pollinatingTicks > 600) { + Bee.this.savedFlowerPos = null; + } else { +- Vec3 vec3 = Vec3.atBottomCenterOf(Bee.this.savedFlowerPos).add(0.0D, 0.6000000238418579D, 0.0D); ++ Vec3 vec3d = Vec3.atBottomCenterOf(Bee.this.savedFlowerPos).add(0.0D, 0.6000000238418579D, 0.0D); + +- if (vec3.distanceTo(Bee.this.position()) > 1.0D) { +- this.hoverPos = vec3; ++ if (vec3d.distanceTo(Bee.this.position()) > 1.0D) { ++ this.hoverPos = vec3d; + this.setWantedPos(); + } else { + if (this.hoverPos == null) { +- this.hoverPos = vec3; ++ this.hoverPos = vec3d; + } + + boolean flag = Bee.this.position().distanceTo(this.hoverPos) <= 0.1D; +@@ -835,13 +811,13 @@ + boolean flag2 = Bee.this.random.nextInt(25) == 0; + + if (flag2) { +- this.hoverPos = new Vec3(vec3.x() + (double) this.getOffset(), vec3.y(), vec3.z() + (double) this.getOffset()); ++ this.hoverPos = new Vec3(vec3d.x() + (double) this.getOffset(), vec3d.y(), vec3d.z() + (double) this.getOffset()); + Bee.this.navigation.stop(); + } else { + flag1 = false; + } + +- Bee.this.getLookControl().setLookAt(vec3.x(), vec3.y(), vec3.z()); ++ Bee.this.getLookControl().setLookAt(vec3d.x(), vec3d.y(), vec3d.z()); + } + + if (flag1) { +@@ -871,17 +847,17 @@ + return this.findNearestBlock(this.VALID_POLLINATION_BLOCKS, 5.0D); + } + +- private Optional findNearestBlock(Predicate predicate, double d0) { +- BlockPos blockpos = Bee.this.blockPosition(); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ private Optional findNearestBlock(Predicate predicate, double distance) { ++ BlockPos blockposition = Bee.this.blockPosition(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + +- for (int i = 0; (double) i <= d0; i = i > 0 ? -i : 1 - i) { +- for (int j = 0; (double) j < d0; ++j) { ++ for (int i = 0; (double) i <= distance; i = i > 0 ? -i : 1 - i) { ++ for (int j = 0; (double) j < distance; ++j) { + for (int k = 0; k <= j; k = k > 0 ? -k : 1 - k) { + for (int l = k < j && k > -j ? j : 0; l <= j; l = l > 0 ? -l : 1 - l) { +- blockpos_mutableblockpos.setWithOffset(blockpos, k, i - 1, l); +- if (blockpos.closerThan(blockpos_mutableblockpos, d0) && predicate.test(Bee.this.level().getBlockState(blockpos_mutableblockpos))) { +- return Optional.of(blockpos_mutableblockpos); ++ blockposition_mutableblockposition.setWithOffset(blockposition, k, i - 1, l); ++ if (blockposition.closerThan(blockposition_mutableblockposition, distance) && predicate.test(Bee.this.level().getBlockState(blockposition_mutableblockposition))) { ++ return Optional.of(blockposition_mutableblockposition); + } + } + } +@@ -899,7 +875,6 @@ + } + + @Override +- @Override + public void tick() { + if (!Bee.this.isAngry()) { + super.tick(); +@@ -907,7 +882,6 @@ + } + + @Override +- @Override + protected boolean resetXRotOnTick() { + return !Bee.this.beePollinateGoal.isPollinating(); + } +@@ -915,18 +889,16 @@ + + private class BeeAttackGoal extends MeleeAttackGoal { + +- BeeAttackGoal(PathfinderMob pathfindermob, double d0, boolean flag) { +- super(pathfindermob, d0, flag); ++ BeeAttackGoal(PathfinderMob mob, double speedModifier, boolean flag) { ++ super(mob, speedModifier, flag); + } + + @Override +- @Override + public boolean canUse() { + return super.canUse() && Bee.this.isAngry() && !Bee.this.hasStung(); + } + + @Override +- @Override + public boolean canContinueToUse() { + return super.canContinueToUse() && Bee.this.isAngry() && !Bee.this.hasStung(); + } +@@ -939,15 +911,14 @@ + } + + @Override +- @Override + public boolean canBeeUse() { + if (Bee.this.hasHive() && Bee.this.wantsToEnterHive() && Bee.this.hivePos.closerToCenterThan(Bee.this.position(), 2.0D)) { +- BlockEntity blockentity = Bee.this.level().getBlockEntity(Bee.this.hivePos); ++ BlockEntity tileentity = Bee.this.level().getBlockEntity(Bee.this.hivePos); + +- if (blockentity instanceof BeehiveBlockEntity) { +- BeehiveBlockEntity beehiveblockentity = (BeehiveBlockEntity) blockentity; ++ if (tileentity instanceof BeehiveBlockEntity) { ++ BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) tileentity; + +- if (!beehiveblockentity.isFull()) { ++ if (!tileentitybeehive.isFull()) { + return true; + } + +@@ -959,20 +930,18 @@ + } + + @Override +- @Override + public boolean canBeeContinueToUse() { + return false; + } + + @Override +- @Override + public void start() { +- BlockEntity blockentity = Bee.this.level().getBlockEntity(Bee.this.hivePos); ++ BlockEntity tileentity = Bee.this.level().getBlockEntity(Bee.this.hivePos); + +- if (blockentity instanceof BeehiveBlockEntity) { +- BeehiveBlockEntity beehiveblockentity = (BeehiveBlockEntity) blockentity; ++ if (tileentity instanceof BeehiveBlockEntity) { ++ BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) tileentity; + +- beehiveblockentity.addOccupant(Bee.this, Bee.this.hasNectar()); ++ tileentitybeehive.addOccupant(Bee.this, Bee.this.hasNectar()); + } + + } +@@ -985,19 +954,16 @@ + } + + @Override +- @Override + public boolean canBeeUse() { + return Bee.this.remainingCooldownBeforeLocatingNewHive == 0 && !Bee.this.hasHive() && Bee.this.wantsToEnterHive(); + } + + @Override +- @Override + public boolean canBeeContinueToUse() { + return false; + } + + @Override +- @Override + public void start() { + Bee.this.remainingCooldownBeforeLocatingNewHive = 200; + List list = this.findNearbyHivesWithSpace(); +@@ -1005,7 +971,7 @@ + if (!list.isEmpty()) { + Iterator iterator = list.iterator(); + +- BlockPos blockpos; ++ BlockPos blockposition; + + do { + if (!iterator.hasNext()) { +@@ -1014,22 +980,22 @@ + return; + } + +- blockpos = (BlockPos) iterator.next(); +- } while (Bee.this.goToHiveGoal.isTargetBlacklisted(blockpos)); ++ blockposition = (BlockPos) iterator.next(); ++ } while (Bee.this.goToHiveGoal.isTargetBlacklisted(blockposition)); + +- Bee.this.hivePos = blockpos; ++ Bee.this.hivePos = blockposition; + } + } + + private List findNearbyHivesWithSpace() { +- BlockPos blockpos = Bee.this.blockPosition(); +- PoiManager poimanager = ((ServerLevel) Bee.this.level()).getPoiManager(); +- Stream stream = poimanager.getInRange((holder) -> { ++ BlockPos blockposition = Bee.this.blockPosition(); ++ PoiManager villageplace = ((ServerLevel) Bee.this.level()).getPoiManager(); ++ Stream stream = villageplace.getInRange((holder) -> { + return holder.is(PoiTypeTags.BEE_HOME); +- }, blockpos, 20, PoiManager.Occupancy.ANY); ++ }, blockposition, 20, PoiManager.Occupancy.ANY); + +- return (List) stream.map(PoiRecord::getPos).filter(Bee.this::doesHiveHaveSpace).sorted(Comparator.comparingDouble((blockpos1) -> { +- return blockpos1.distSqr(blockpos); ++ return (List) stream.map(PoiRecord::getPos).filter(Bee.this::doesHiveHaveSpace).sorted(Comparator.comparingDouble((blockposition1) -> { ++ return blockposition1.distSqr(blockposition); + })).collect(Collectors.toList()); + } + } +@@ -1048,25 +1014,22 @@ + + BeeGoToHiveGoal() { + super(); +- this.travellingTicks = Bee.this.level().random.nextInt(10); ++ this.travellingTicks = Bee.this.random.nextInt(10); // CraftBukkit - SPIGOT-7495: Give Bees another chance and let them use their own random, avoid concurrency issues + this.blacklistedTargets = Lists.newArrayList(); +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +- @Override + public boolean canBeeUse() { + return Bee.this.hivePos != null && !Bee.this.hasRestriction() && Bee.this.wantsToEnterHive() && !this.hasReachedTarget(Bee.this.hivePos) && Bee.this.level().getBlockState(Bee.this.hivePos).is(BlockTags.BEEHIVES); + } + + @Override +- @Override + public boolean canBeeContinueToUse() { + return this.canBeeUse(); + } + + @Override +- @Override + public void start() { + this.travellingTicks = 0; + this.ticksStuck = 0; +@@ -1074,7 +1037,6 @@ + } + + @Override +- @Override + public void stop() { + this.travellingTicks = 0; + this.ticksStuck = 0; +@@ -1083,7 +1045,6 @@ + } + + @Override +- @Override + public void tick() { + if (Bee.this.hivePos != null) { + ++this.travellingTicks; +@@ -1116,18 +1077,18 @@ + } + } + +- private boolean pathfindDirectlyTowards(BlockPos blockpos) { ++ private boolean pathfindDirectlyTowards(BlockPos pos) { + Bee.this.navigation.setMaxVisitedNodesMultiplier(10.0F); +- Bee.this.navigation.moveTo((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), 1.0D); ++ Bee.this.navigation.moveTo((double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), 1.0D); + return Bee.this.navigation.getPath() != null && Bee.this.navigation.getPath().canReach(); + } + +- boolean isTargetBlacklisted(BlockPos blockpos) { +- return this.blacklistedTargets.contains(blockpos); ++ boolean isTargetBlacklisted(BlockPos pos) { ++ return this.blacklistedTargets.contains(pos); + } + +- private void blacklistTarget(BlockPos blockpos) { +- this.blacklistedTargets.add(blockpos); ++ private void blacklistTarget(BlockPos pos) { ++ this.blacklistedTargets.add(pos); + + while (this.blacklistedTargets.size() > 3) { + this.blacklistedTargets.remove(0); +@@ -1152,13 +1113,13 @@ + Bee.this.remainingCooldownBeforeLocatingNewHive = 200; + } + +- private boolean hasReachedTarget(BlockPos blockpos) { +- if (Bee.this.closerThan(blockpos, 2)) { ++ private boolean hasReachedTarget(BlockPos pos) { ++ if (Bee.this.closerThan(pos, 2)) { + return true; + } else { +- Path path = Bee.this.navigation.getPath(); ++ Path pathentity = Bee.this.navigation.getPath(); + +- return path != null && path.getTarget().equals(blockpos) && path.canReach() && path.isDone(); ++ return pathentity != null && pathentity.getTarget().equals(pos) && pathentity.canReach() && pathentity.isDone(); + } + } + } +@@ -1170,31 +1131,27 @@ + + BeeGoToKnownFlowerGoal() { + super(); +- this.travellingTicks = Bee.this.level().random.nextInt(10); +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ this.travellingTicks = Bee.this.random.nextInt(10); // CraftBukkit - SPIGOT-7495: Give Bees another chance and let them use their own random, avoid concurrency issues ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +- @Override + public boolean canBeeUse() { + return Bee.this.savedFlowerPos != null && !Bee.this.hasRestriction() && this.wantsToGoToKnownFlower() && Bee.this.isFlowerValid(Bee.this.savedFlowerPos) && !Bee.this.closerThan(Bee.this.savedFlowerPos, 2); + } + + @Override +- @Override + public boolean canBeeContinueToUse() { + return this.canBeeUse(); + } + + @Override +- @Override + public void start() { + this.travellingTicks = 0; + super.start(); + } + + @Override +- @Override + public void stop() { + this.travellingTicks = 0; + Bee.this.navigation.stop(); +@@ -1202,7 +1159,6 @@ + } + + @Override +- @Override + public void tick() { + if (Bee.this.savedFlowerPos != null) { + ++this.travellingTicks; +@@ -1232,55 +1188,52 @@ + } + + @Override +- @Override + public boolean canBeeUse() { + return Bee.this.getCropsGrownSincePollination() >= 10 ? false : (Bee.this.random.nextFloat() < 0.3F ? false : Bee.this.hasNectar() && Bee.this.isHiveValid()); + } + + @Override +- @Override + public boolean canBeeContinueToUse() { + return this.canBeeUse(); + } + + @Override +- @Override + public void tick() { + if (Bee.this.random.nextInt(this.adjustedTickDelay(30)) == 0) { + for (int i = 1; i <= 2; ++i) { +- BlockPos blockpos = Bee.this.blockPosition().below(i); +- BlockState blockstate = Bee.this.level().getBlockState(blockpos); +- Block block = blockstate.getBlock(); +- BlockState blockstate1 = null; ++ BlockPos blockposition = Bee.this.blockPosition().below(i); ++ IBlockData iblockdata = Bee.this.level().getBlockState(blockposition); ++ Block block = iblockdata.getBlock(); ++ IBlockData iblockdata1 = null; + +- if (blockstate.is(BlockTags.BEE_GROWABLES)) { ++ if (iblockdata.is(BlockTags.BEE_GROWABLES)) { + if (block instanceof CropBlock) { +- CropBlock cropblock = (CropBlock) block; ++ CropBlock blockcrops = (CropBlock) block; + +- if (!cropblock.isMaxAge(blockstate)) { +- blockstate1 = cropblock.getStateForAge(cropblock.getAge(blockstate) + 1); ++ if (!blockcrops.isMaxAge(iblockdata)) { ++ iblockdata1 = blockcrops.getStateForAge(blockcrops.getAge(iblockdata) + 1); + } + } else { + int j; + + if (block instanceof StemBlock) { +- j = (Integer) blockstate.getValue(StemBlock.AGE); ++ j = (Integer) iblockdata.getValue(StemBlock.AGE); + if (j < 7) { +- blockstate1 = (BlockState) blockstate.setValue(StemBlock.AGE, j + 1); ++ iblockdata1 = (IBlockData) iblockdata.setValue(StemBlock.AGE, j + 1); + } +- } else if (blockstate.is(Blocks.SWEET_BERRY_BUSH)) { +- j = (Integer) blockstate.getValue(SweetBerryBushBlock.AGE); ++ } else if (iblockdata.is(Blocks.SWEET_BERRY_BUSH)) { ++ j = (Integer) iblockdata.getValue(SweetBerryBushBlock.AGE); + if (j < 3) { +- blockstate1 = (BlockState) blockstate.setValue(SweetBerryBushBlock.AGE, j + 1); ++ iblockdata1 = (IBlockData) iblockdata.setValue(SweetBerryBushBlock.AGE, j + 1); + } +- } else if (blockstate.is(Blocks.CAVE_VINES) || blockstate.is(Blocks.CAVE_VINES_PLANT)) { +- ((BonemealableBlock) blockstate.getBlock()).performBonemeal((ServerLevel) Bee.this.level(), Bee.this.random, blockpos, blockstate); ++ } else if (iblockdata.is(Blocks.CAVE_VINES) || iblockdata.is(Blocks.CAVE_VINES_PLANT)) { ++ ((BonemealableBlock) iblockdata.getBlock()).performBonemeal((ServerLevel) Bee.this.level(), Bee.this.random, blockposition, iblockdata); + } + } + +- if (blockstate1 != null) { +- Bee.this.level().levelEvent(2005, blockpos, 0); +- Bee.this.level().setBlockAndUpdate(blockpos, blockstate1); ++ if (iblockdata1 != null && CraftEventFactory.callEntityChangeBlockEvent(Bee.this, blockposition, iblockdata1)) { // CraftBukkit ++ Bee.this.level().levelEvent(2005, blockposition, 0); ++ Bee.this.level().setBlockAndUpdate(blockposition, iblockdata1); + Bee.this.incrementNumCropsGrownSincePollination(); + } + } +@@ -1295,68 +1248,63 @@ + private static final int WANDER_THRESHOLD = 22; + + BeeWanderGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +- @Override + public boolean canUse() { + return Bee.this.navigation.isDone() && Bee.this.random.nextInt(10) == 0; + } + + @Override +- @Override + public boolean canContinueToUse() { + return Bee.this.navigation.isInProgress(); + } + + @Override +- @Override + public void start() { +- Vec3 vec3 = this.findPos(); ++ Vec3 vec3d = this.findPos(); + +- if (vec3 != null) { +- Bee.this.navigation.moveTo(Bee.this.navigation.createPath(BlockPos.containing(vec3), 1), 1.0D); ++ if (vec3d != null) { ++ Bee.this.navigation.moveTo(Bee.this.navigation.createPath(BlockPos.containing(vec3d), 1), 1.0D); + } + + } + + @Nullable + private Vec3 findPos() { +- Vec3 vec3; ++ Vec3 vec3d; + + if (Bee.this.isHiveValid() && !Bee.this.closerThan(Bee.this.hivePos, 22)) { +- Vec3 vec31 = Vec3.atCenterOf(Bee.this.hivePos); ++ Vec3 vec3d1 = Vec3.atCenterOf(Bee.this.hivePos); + +- vec3 = vec31.subtract(Bee.this.position()).normalize(); ++ vec3d = vec3d1.subtract(Bee.this.position()).normalize(); + } else { +- vec3 = Bee.this.getViewVector(0.0F); ++ vec3d = Bee.this.getViewVector(0.0F); + } + + boolean flag = true; +- Vec3 vec32 = HoverRandomPos.getPos(Bee.this, 8, 7, vec3.x, vec3.z, 1.5707964F, 3, 1); ++ Vec3 vec3d2 = HoverRandomPos.getPos(Bee.this, 8, 7, vec3d.x, vec3d.z, 1.5707964F, 3, 1); + +- return vec32 != null ? vec32 : AirAndWaterRandomPos.getPos(Bee.this, 8, 4, -2, vec3.x, vec3.z, 1.5707963705062866D); ++ return vec3d2 != null ? vec3d2 : AirAndWaterRandomPos.getPos(Bee.this, 8, 4, -2, vec3d.x, vec3d.z, 1.5707963705062866D); + } + } + + private class BeeHurtByOtherGoal extends HurtByTargetGoal { + +- BeeHurtByOtherGoal(Bee bee) { +- super(bee); ++ BeeHurtByOtherGoal(Bee entitybee) { ++ super(entitybee); + } + + @Override +- @Override + public boolean canContinueToUse() { + return Bee.this.isAngry() && super.canContinueToUse(); + } + + @Override +- @Override +- protected void alertOther(Mob mob, LivingEntity livingentity) { +- if (mob instanceof Bee && this.mob.hasLineOfSight(livingentity)) { +- mob.setTarget(livingentity); ++ protected void alertOther(Mob mob, LivingEntity target) { ++ if (mob instanceof Bee && this.mob.hasLineOfSight(target)) { ++ mob.setTarget(target, EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY, true); // CraftBukkit - reason + } + + } +@@ -1364,19 +1312,17 @@ + + private static class BeeBecomeAngryTargetGoal extends NearestAttackableTargetGoal { + +- BeeBecomeAngryTargetGoal(Bee bee) { +- Objects.requireNonNull(bee); +- super(bee, Player.class, 10, true, false, bee::isAngryAt); ++ BeeBecomeAngryTargetGoal(Bee mob) { ++ // Objects.requireNonNull(entitybee); // CraftBukkit - decompile error ++ super(mob, Player.class, 10, true, false, mob::isAngryAt); + } + + @Override +- @Override + public boolean canUse() { + return this.beeCanTarget() && super.canUse(); + } + + @Override +- @Override + public boolean canContinueToUse() { + boolean flag = this.beeCanTarget(); + +@@ -1389,9 +1335,9 @@ + } + + private boolean beeCanTarget() { +- Bee bee = (Bee) this.mob; ++ Bee entitybee = (Bee) this.mob; + +- return bee.isAngry() && !bee.hasStung(); ++ return entitybee.isAngry() && !entitybee.hasStung(); + } + } + +@@ -1404,13 +1350,11 @@ + public abstract boolean canBeeContinueToUse(); + + @Override +- @Override + public boolean canUse() { + return this.canBeeUse() && !Bee.this.isAngry(); + } + + @Override +- @Override + public boolean canContinueToUse() { + return this.canBeeContinueToUse() && !Bee.this.isAngry(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Bucketable.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Bucketable.java.patch new file mode 100644 index 0000000000..407c4e5da4 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Bucketable.java.patch @@ -0,0 +1,155 @@ +--- a/net/minecraft/world/entity/animal/Bucketable.java ++++ b/net/minecraft/world/entity/animal/Bucketable.java +@@ -3,9 +3,10 @@ + import java.util.Optional; + import net.minecraft.advancements.CriteriaTriggers; + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +@@ -14,6 +15,10 @@ + import net.minecraft.world.item.ItemUtils; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerBucketEntityEvent; ++// CraftBukkit end + + public interface Bucketable { + +@@ -31,84 +36,96 @@ + + /** @deprecated */ + @Deprecated +- static void saveDefaultDataToBucketTag(Mob mob, ItemStack itemstack) { +- CompoundTag compoundtag = itemstack.getOrCreateTag(); ++ static void saveDefaultDataToBucketTag(Mob mob, ItemStack bucket) { ++ CompoundTag nbttagcompound = bucket.getOrCreateTag(); + + if (mob.hasCustomName()) { +- itemstack.setHoverName(mob.getCustomName()); ++ bucket.setHoverName(mob.getCustomName()); + } + + if (mob.isNoAi()) { +- compoundtag.putBoolean("NoAI", mob.isNoAi()); ++ nbttagcompound.putBoolean("NoAI", mob.isNoAi()); + } + + if (mob.isSilent()) { +- compoundtag.putBoolean("Silent", mob.isSilent()); ++ nbttagcompound.putBoolean("Silent", mob.isSilent()); + } + + if (mob.isNoGravity()) { +- compoundtag.putBoolean("NoGravity", mob.isNoGravity()); ++ nbttagcompound.putBoolean("NoGravity", mob.isNoGravity()); + } + + if (mob.hasGlowingTag()) { +- compoundtag.putBoolean("Glowing", mob.hasGlowingTag()); ++ nbttagcompound.putBoolean("Glowing", mob.hasGlowingTag()); + } + + if (mob.isInvulnerable()) { +- compoundtag.putBoolean("Invulnerable", mob.isInvulnerable()); ++ nbttagcompound.putBoolean("Invulnerable", mob.isInvulnerable()); + } + +- compoundtag.putFloat("Health", mob.getHealth()); ++ nbttagcompound.putFloat("Health", mob.getHealth()); + } + + /** @deprecated */ + @Deprecated +- static void loadDefaultDataFromBucketTag(Mob mob, CompoundTag compoundtag) { +- if (compoundtag.contains("NoAI")) { +- mob.setNoAi(compoundtag.getBoolean("NoAI")); ++ static void loadDefaultDataFromBucketTag(Mob mob, CompoundTag tag) { ++ if (tag.contains("NoAI")) { ++ mob.setNoAi(tag.getBoolean("NoAI")); + } + +- if (compoundtag.contains("Silent")) { +- mob.setSilent(compoundtag.getBoolean("Silent")); ++ if (tag.contains("Silent")) { ++ mob.setSilent(tag.getBoolean("Silent")); + } + +- if (compoundtag.contains("NoGravity")) { +- mob.setNoGravity(compoundtag.getBoolean("NoGravity")); ++ if (tag.contains("NoGravity")) { ++ mob.setNoGravity(tag.getBoolean("NoGravity")); + } + +- if (compoundtag.contains("Glowing")) { +- mob.setGlowingTag(compoundtag.getBoolean("Glowing")); ++ if (tag.contains("Glowing")) { ++ mob.setGlowingTag(tag.getBoolean("Glowing")); + } + +- if (compoundtag.contains("Invulnerable")) { +- mob.setInvulnerable(compoundtag.getBoolean("Invulnerable")); ++ if (tag.contains("Invulnerable")) { ++ mob.setInvulnerable(tag.getBoolean("Invulnerable")); + } + +- if (compoundtag.contains("Health", 99)) { +- mob.setHealth(compoundtag.getFloat("Health")); ++ if (tag.contains("Health", 99)) { ++ mob.setHealth(tag.getFloat("Health")); + } + + } + +- static Optional bucketMobPickup(Player player, InteractionHand interactionhand, T t0) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ static Optional bucketMobPickup(Player player, EnumHand hand, T entity) { ++ ItemStack itemstack = player.getItemInHand(hand); + +- if (itemstack.getItem() == Items.WATER_BUCKET && t0.isAlive()) { +- t0.playSound(((Bucketable) t0).getPickupSound(), 1.0F, 1.0F); +- ItemStack itemstack1 = ((Bucketable) t0).getBucketItemStack(); ++ if (itemstack.getItem() == Items.WATER_BUCKET && entity.isAlive()) { ++ // CraftBukkit start ++ // t0.playSound(((Bucketable) t0).getPickupSound(), 1.0F, 1.0F); // CraftBukkit - moved down ++ ItemStack itemstack1 = ((Bucketable) entity).getBucketItemStack(); + +- ((Bucketable) t0).saveToBucketTag(itemstack1); ++ ((Bucketable) entity).saveToBucketTag(itemstack1); ++ ++ PlayerBucketEntityEvent playerBucketFishEvent = CraftEventFactory.callPlayerFishBucketEvent(entity, player, itemstack, itemstack1, hand); ++ itemstack1 = CraftItemStack.asNMSCopy(playerBucketFishEvent.getEntityBucket()); ++ if (playerBucketFishEvent.isCancelled()) { ++ ((ServerPlayer) player).containerMenu.sendAllDataToRemote(); // We need to update inventory to resync client's bucket ++ ((ServerPlayer) player).connection.send(new ClientboundAddEntityPacket(entity)); // We need to play out these packets as the client assumes the fish is gone ++ entity.getEntityData().refresh((ServerPlayer) player); // Need to send data such as the display name to client ++ return Optional.of(InteractionResult.FAIL); ++ } ++ entity.playSound(((Bucketable) entity).getPickupSound(), 1.0F, 1.0F); ++ // CraftBukkit end + ItemStack itemstack2 = ItemUtils.createFilledResult(itemstack, player, itemstack1, false); + +- player.setItemInHand(interactionhand, itemstack2); +- Level level = t0.level(); ++ player.setItemInHand(hand, itemstack2); ++ Level world = entity.level(); + +- if (!level.isClientSide) { ++ if (!world.isClientSide) { + CriteriaTriggers.FILLED_BUCKET.trigger((ServerPlayer) player, itemstack1); + } + +- t0.discard(); +- return Optional.of(InteractionResult.sidedSuccess(level.isClientSide)); ++ entity.discard(); ++ return Optional.of(InteractionResult.sidedSuccess(world.isClientSide)); + } else { + return Optional.empty(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Cat.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Cat.java.patch new file mode 100644 index 0000000000..f6079cb1f7 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Cat.java.patch @@ -0,0 +1,635 @@ +--- a/net/minecraft/world/entity/animal/Cat.java ++++ b/net/minecraft/world/entity/animal/Cat.java +@@ -22,19 +22,19 @@ + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.TamableAnimal; + import net.minecraft.world.entity.VariantHolder; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -65,7 +65,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.BedBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.storage.loot.BuiltInLootTables; + import net.minecraft.world.level.storage.loot.LootParams; + import net.minecraft.world.level.storage.loot.LootTable; +@@ -94,8 +94,8 @@ + private float relaxStateOneAmount; + private float relaxStateOneAmountO; + +- public Cat(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Cat(EntityType entityType, Level level) { ++ super(entityType, level); + } + + public ResourceLocation getResourceLocation() { +@@ -103,7 +103,6 @@ + } + + @Override +- @Override + protected void registerGoals() { + this.temptGoal = new Cat.CatTemptGoal(this, 0.6D, Cat.TEMPT_INGREDIENT, true); + this.goalSelector.addGoal(1, new FloatGoal(this)); +@@ -124,26 +123,24 @@ + } + + @Override +- @Override + public CatVariant getVariant() { + return (CatVariant) this.entityData.get(Cat.DATA_VARIANT_ID); + } + +- @Override +- public void setVariant(CatVariant catvariant) { +- this.entityData.set(Cat.DATA_VARIANT_ID, catvariant); ++ public void setVariant(CatVariant variant) { ++ this.entityData.set(Cat.DATA_VARIANT_ID, variant); + } + +- public void setLying(boolean flag) { +- this.entityData.set(Cat.IS_LYING, flag); ++ public void setLying(boolean lying) { ++ this.entityData.set(Cat.IS_LYING, lying); + } + + public boolean isLying() { + return (Boolean) this.entityData.get(Cat.IS_LYING); + } + +- public void setRelaxStateOne(boolean flag) { +- this.entityData.set(Cat.RELAX_STATE_ONE, flag); ++ public void setRelaxStateOne(boolean relaxStateOne) { ++ this.entityData.set(Cat.RELAX_STATE_ONE, relaxStateOne); + } + + public boolean isRelaxStateOne() { +@@ -154,12 +151,11 @@ + return DyeColor.byId((Integer) this.entityData.get(Cat.DATA_COLLAR_COLOR)); + } + +- public void setCollarColor(DyeColor dyecolor) { +- this.entityData.set(Cat.DATA_COLLAR_COLOR, dyecolor.getId()); ++ public void setCollarColor(DyeColor color) { ++ this.entityData.set(Cat.DATA_COLLAR_COLOR, color.getId()); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Cat.DATA_VARIANT_ID, (CatVariant) BuiltInRegistries.CAT_VARIANT.getOrThrow(CatVariant.BLACK)); +@@ -169,47 +165,44 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putString("variant", BuiltInRegistries.CAT_VARIANT.getKey(this.getVariant()).toString()); +- compoundtag.putByte("CollarColor", (byte) this.getCollarColor().getId()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putString("variant", BuiltInRegistries.CAT_VARIANT.getKey(this.getVariant()).toString()); ++ compound.putByte("CollarColor", (byte) this.getCollarColor().getId()); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- CatVariant catvariant = (CatVariant) BuiltInRegistries.CAT_VARIANT.get(ResourceLocation.tryParse(compoundtag.getString("variant"))); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ CatVariant catvariant = (CatVariant) BuiltInRegistries.CAT_VARIANT.get(ResourceLocation.tryParse(compound.getString("variant"))); + + if (catvariant != null) { + this.setVariant(catvariant); + } + +- if (compoundtag.contains("CollarColor", 99)) { +- this.setCollarColor(DyeColor.byId(compoundtag.getInt("CollarColor"))); ++ if (compound.contains("CollarColor", 99)) { ++ this.setCollarColor(DyeColor.byId(compound.getInt("CollarColor"))); + } + + } + + @Override +- @Override + public void customServerAiStep() { + if (this.getMoveControl().hasWanted()) { + double d0 = this.getMoveControl().getSpeedModifier(); + + if (d0 == 0.6D) { +- this.setPose(Pose.CROUCHING); ++ this.setPose(EntityPose.CROUCHING); + this.setSprinting(false); + } else if (d0 == 1.33D) { +- this.setPose(Pose.STANDING); ++ this.setPose(EntityPose.STANDING); + this.setSprinting(true); + } else { +- this.setPose(Pose.STANDING); ++ this.setPose(EntityPose.STANDING); + this.setSprinting(false); + } + } else { +- this.setPose(Pose.STANDING); ++ this.setPose(EntityPose.STANDING); + this.setSprinting(false); + } + +@@ -217,13 +210,11 @@ + + @Nullable + @Override +- @Override + protected SoundEvent getAmbientSound() { + return this.isTame() ? (this.isInLove() ? SoundEvents.CAT_PURR : (this.random.nextInt(4) == 0 ? SoundEvents.CAT_PURREOW : SoundEvents.CAT_AMBIENT)) : SoundEvents.CAT_STRAY_AMBIENT; + } + + @Override +- @Override + public int getAmbientSoundInterval() { + return 120; + } +@@ -233,13 +224,11 @@ + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.CAT_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.CAT_DEATH; + } +@@ -249,13 +238,12 @@ + } + + @Override +- @Override +- protected void usePlayerItem(Player player, InteractionHand interactionhand, ItemStack itemstack) { +- if (this.isFood(itemstack)) { ++ protected void usePlayerItem(Player player, EnumHand hand, ItemStack stack) { ++ if (this.isFood(stack)) { + this.playSound(SoundEvents.CAT_EAT, 1.0F, 1.0F); + } + +- super.usePlayerItem(player, interactionhand, itemstack); ++ super.usePlayerItem(player, hand, stack); + } + + private float getAttackDamage() { +@@ -263,13 +251,11 @@ + } + + @Override +- @Override + public boolean doHurtTarget(Entity entity) { + return entity.hurt(this.damageSources().mobAttack(this), this.getAttackDamage()); + } + + @Override +- @Override + public void tick() { + super.tick(); + if (this.temptGoal != null && this.temptGoal.isRunning() && !this.isTame() && this.tickCount % 100 == 0) { +@@ -311,116 +297,112 @@ + + } + +- public float getLieDownAmount(float f) { +- return Mth.lerp(f, this.lieDownAmountO, this.lieDownAmount); ++ public float getLieDownAmount(float partialTicks) { ++ return Mth.lerp(partialTicks, this.lieDownAmountO, this.lieDownAmount); + } + +- public float getLieDownAmountTail(float f) { +- return Mth.lerp(f, this.lieDownAmountOTail, this.lieDownAmountTail); ++ public float getLieDownAmountTail(float partialTicks) { ++ return Mth.lerp(partialTicks, this.lieDownAmountOTail, this.lieDownAmountTail); + } + +- public float getRelaxStateOneAmount(float f) { +- return Mth.lerp(f, this.relaxStateOneAmountO, this.relaxStateOneAmount); ++ public float getRelaxStateOneAmount(float partialTicks) { ++ return Mth.lerp(partialTicks, this.relaxStateOneAmountO, this.relaxStateOneAmount); + } + + @Nullable + @Override +- @Override +- public Cat getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { +- Cat cat = (Cat) EntityType.CAT.create(serverlevel); ++ public Cat getBreedOffspring(ServerLevel level, AgeableMob otherParent) { ++ Cat entitycat = (Cat) EntityType.CAT.create(level); + +- if (cat != null && ageablemob instanceof Cat) { +- Cat cat1 = (Cat) ageablemob; ++ if (entitycat != null && otherParent instanceof Cat) { ++ Cat entitycat1 = (Cat) otherParent; + + if (this.random.nextBoolean()) { +- cat.setVariant(this.getVariant()); ++ entitycat.setVariant(this.getVariant()); + } else { +- cat.setVariant(cat1.getVariant()); ++ entitycat.setVariant(entitycat1.getVariant()); + } + + if (this.isTame()) { +- cat.setOwnerUUID(this.getOwnerUUID()); +- cat.setTame(true); ++ entitycat.setOwnerUUID(this.getOwnerUUID()); ++ entitycat.setTame(true); + if (this.random.nextBoolean()) { +- cat.setCollarColor(this.getCollarColor()); ++ entitycat.setCollarColor(this.getCollarColor()); + } else { +- cat.setCollarColor(cat1.getCollarColor()); ++ entitycat.setCollarColor(entitycat1.getCollarColor()); + } + } + } + +- return cat; ++ return entitycat; + } + + @Override +- @Override +- public boolean canMate(Animal animal) { ++ public boolean canMate(Animal otherAnimal) { + if (!this.isTame()) { + return false; +- } else if (!(animal instanceof Cat)) { ++ } else if (!(otherAnimal instanceof Cat)) { + return false; + } else { +- Cat cat = (Cat) animal; ++ Cat entitycat = (Cat) otherAnimal; + +- return cat.isTame() && super.canMate(animal); ++ return entitycat.isTame() && super.canMate(otherAnimal); + } + } + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- spawngroupdata = super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); +- boolean flag = serverlevelaccessor.getMoonBrightness() > 0.9F; ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ spawnData = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ boolean flag = level.getMoonBrightness() > 0.9F; + TagKey tagkey = flag ? CatVariantTags.FULL_MOON_SPAWNS : CatVariantTags.DEFAULT_SPAWNS; + + BuiltInRegistries.CAT_VARIANT.getTag(tagkey).flatMap((holderset_named) -> { +- return holderset_named.getRandomElement(serverlevelaccessor.getRandom()); ++ return holderset_named.getRandomElement(level.getRandom()); + }).ifPresent((holder) -> { + this.setVariant((CatVariant) holder.value()); + }); +- ServerLevel serverlevel = serverlevelaccessor.getLevel(); ++ ServerLevel worldserver = level.getLevel(); + +- if (serverlevel.structureManager().getStructureWithPieceAt(this.blockPosition(), StructureTags.CATS_SPAWN_AS_BLACK).isValid()) { ++ if (worldserver.structureManager().getStructureWithPieceAt(this.blockPosition(), StructureTags.CATS_SPAWN_AS_BLACK).isValid()) { + this.setVariant((CatVariant) BuiltInRegistries.CAT_VARIANT.getOrThrow(CatVariant.ALL_BLACK)); + this.setPersistenceRequired(); + } + +- return spawngroupdata; ++ return spawnData; + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + Item item = itemstack.getItem(); + + if (this.level().isClientSide) { + return this.isTame() && this.isOwnedBy(player) ? InteractionResult.SUCCESS : (this.isFood(itemstack) && (this.getHealth() < this.getMaxHealth() || !this.isTame()) ? InteractionResult.SUCCESS : InteractionResult.PASS); + } else { +- InteractionResult interactionresult; ++ InteractionResult enuminteractionresult; + + if (this.isTame()) { + if (this.isOwnedBy(player)) { + if (!(item instanceof DyeItem)) { + if (item.isEdible() && this.isFood(itemstack) && this.getHealth() < this.getMaxHealth()) { +- this.usePlayerItem(player, interactionhand, itemstack); ++ this.usePlayerItem(player, hand, itemstack); + this.heal((float) item.getFoodProperties().getNutrition()); + return InteractionResult.CONSUME; + } + +- interactionresult = super.mobInteract(player, interactionhand); +- if (!interactionresult.consumesAction() || this.isBaby()) { ++ enuminteractionresult = super.mobInteract(player, hand); ++ if (!enuminteractionresult.consumesAction() || this.isBaby()) { + this.setOrderedToSit(!this.isOrderedToSit()); + } + +- return interactionresult; ++ return enuminteractionresult; + } + +- DyeColor dyecolor = ((DyeItem) item).getDyeColor(); ++ DyeColor enumcolor = ((DyeItem) item).getDyeColor(); + +- if (dyecolor != this.getCollarColor()) { +- this.setCollarColor(dyecolor); ++ if (enumcolor != this.getCollarColor()) { ++ this.setCollarColor(enumcolor); + if (!player.getAbilities().instabuild) { + itemstack.shrink(1); + } +@@ -430,8 +412,8 @@ + } + } + } else if (this.isFood(itemstack)) { +- this.usePlayerItem(player, interactionhand, itemstack); +- if (this.random.nextInt(3) == 0) { ++ this.usePlayerItem(player, hand, itemstack); ++ if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit + this.tame(player); + this.setOrderedToSit(true); + this.level().broadcastEntityEvent(this, (byte) 7); +@@ -443,35 +425,31 @@ + return InteractionResult.CONSUME; + } + +- interactionresult = super.mobInteract(player, interactionhand); +- if (interactionresult.consumesAction()) { ++ enuminteractionresult = super.mobInteract(player, hand); ++ if (enuminteractionresult.consumesAction()) { + this.setPersistenceRequired(); + } + +- return interactionresult; ++ return enuminteractionresult; + } + } + + @Override +- @Override +- public boolean isFood(ItemStack itemstack) { +- return Cat.TEMPT_INGREDIENT.test(itemstack); ++ public boolean isFood(ItemStack stack) { ++ return Cat.TEMPT_INGREDIENT.test(stack); + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return entitydimensions.height * 0.5F; ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { ++ return size.height * 0.5F; + } + + @Override +- @Override +- public boolean removeWhenFarAway(double d0) { ++ public boolean removeWhenFarAway(double distanceToClosestPlayer) { + return !this.isTame() && this.tickCount > 2400; + } + + @Override +- @Override + protected void reassessTameGoals() { + if (this.avoidPlayersGoal == null) { + this.avoidPlayersGoal = new Cat.CatAvoidEntityGoal<>(this, Player.class, 16.0F, 0.8D, 1.33D); +@@ -485,30 +463,27 @@ + } + + @Override +- @Override + public boolean isSteppingCarefully() { + return this.isCrouching() || super.isSteppingCarefully(); + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height - 0.1875F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.1875F * f, 0.0F); + } + + private static class CatTemptGoal extends TemptGoal { + + @Nullable +- private Player selectedPlayer; ++ private LivingEntity selectedPlayer; // CraftBukkit + private final Cat cat; + +- public CatTemptGoal(Cat cat, double d0, Ingredient ingredient, boolean flag) { +- super(cat, d0, ingredient, flag); ++ public CatTemptGoal(Cat cat, double speedModifier, Ingredient recipeitemstack, boolean items) { ++ super(cat, speedModifier, recipeitemstack, items); + this.cat = cat; + } + + @Override +- @Override + public void tick() { + super.tick(); + if (this.selectedPlayer == null && this.mob.getRandom().nextInt(this.adjustedTickDelay(600)) == 0) { +@@ -520,13 +495,11 @@ + } + + @Override +- @Override + protected boolean canScare() { + return this.selectedPlayer != null && this.selectedPlayer.equals(this.player) ? false : super.canScare(); + } + + @Override +- @Override + public boolean canUse() { + return super.canUse() && !this.cat.isTame(); + } +@@ -546,18 +519,17 @@ + } + + @Override +- @Override + public boolean canUse() { + if (!this.cat.isTame()) { + return false; + } else if (this.cat.isOrderedToSit()) { + return false; + } else { +- LivingEntity livingentity = this.cat.getOwner(); ++ LivingEntity entityliving = this.cat.getOwner(); + +- if (livingentity instanceof Player) { +- this.ownerPlayer = (Player) livingentity; +- if (!livingentity.isSleeping()) { ++ if (entityliving instanceof Player) { ++ this.ownerPlayer = (Player) entityliving; ++ if (!entityliving.isSleeping()) { + return false; + } + +@@ -565,14 +537,14 @@ + return false; + } + +- BlockPos blockpos = this.ownerPlayer.blockPosition(); +- BlockState blockstate = this.cat.level().getBlockState(blockpos); ++ BlockPos blockposition = this.ownerPlayer.blockPosition(); ++ IBlockData iblockdata = this.cat.level().getBlockState(blockposition); + +- if (blockstate.is(BlockTags.BEDS)) { +- this.goalPos = (BlockPos) blockstate.getOptionalValue(BedBlock.FACING).map((direction) -> { +- return blockpos.relative(direction.getOpposite()); ++ if (iblockdata.is(BlockTags.BEDS)) { ++ this.goalPos = (BlockPos) iblockdata.getOptionalValue(BedBlock.FACING).map((enumdirection) -> { ++ return blockposition.relative(enumdirection.getOpposite()); + }).orElseGet(() -> { +- return new BlockPos(blockpos); ++ return new BlockPos(blockposition); + }); + return !this.spaceIsOccupied(); + } +@@ -586,7 +558,7 @@ + List list = this.cat.level().getEntitiesOfClass(Cat.class, (new AABB(this.goalPos)).inflate(2.0D)); + Iterator iterator = list.iterator(); + +- Cat cat; ++ Cat entitycat; + + do { + do { +@@ -594,21 +566,19 @@ + return false; + } + +- cat = (Cat) iterator.next(); +- } while (cat == this.cat); +- } while (!cat.isLying() && !cat.isRelaxStateOne()); ++ entitycat = (Cat) iterator.next(); ++ } while (entitycat == this.cat); ++ } while (!entitycat.isLying() && !entitycat.isRelaxStateOne()); + + return true; + } + + @Override +- @Override + public boolean canContinueToUse() { + return this.cat.isTame() && !this.cat.isOrderedToSit() && this.ownerPlayer != null && this.ownerPlayer.isSleeping() && this.goalPos != null && !this.spaceIsOccupied(); + } + + @Override +- @Override + public void start() { + if (this.goalPos != null) { + this.cat.setInSittingPose(false); +@@ -618,7 +588,6 @@ + } + + @Override +- @Override + public void stop() { + this.cat.setLying(false); + float f = this.cat.level().getTimeOfDay(1.0F); +@@ -634,11 +603,11 @@ + + private void giveMorningGift() { + RandomSource randomsource = this.cat.getRandom(); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + +- blockpos_mutableblockpos.set(this.cat.isLeashed() ? this.cat.getLeashHolder().blockPosition() : this.cat.blockPosition()); +- this.cat.randomTeleport((double) (blockpos_mutableblockpos.getX() + randomsource.nextInt(11) - 5), (double) (blockpos_mutableblockpos.getY() + randomsource.nextInt(5) - 2), (double) (blockpos_mutableblockpos.getZ() + randomsource.nextInt(11) - 5), false); +- blockpos_mutableblockpos.set(this.cat.blockPosition()); ++ blockposition_mutableblockposition.set(this.cat.isLeashed() ? this.cat.getLeashHolder().blockPosition() : this.cat.blockPosition()); ++ this.cat.randomTeleport((double) (blockposition_mutableblockposition.getX() + randomsource.nextInt(11) - 5), (double) (blockposition_mutableblockposition.getY() + randomsource.nextInt(5) - 2), (double) (blockposition_mutableblockposition.getZ() + randomsource.nextInt(11) - 5), false); ++ blockposition_mutableblockposition.set(this.cat.blockPosition()); + LootTable loottable = this.cat.level().getServer().getLootData().getLootTable(BuiltInLootTables.CAT_MORNING_GIFT); + LootParams lootparams = (new LootParams.Builder((ServerLevel) this.cat.level())).withParameter(LootContextParams.ORIGIN, this.cat.position()).withParameter(LootContextParams.THIS_ENTITY, this.cat).create(LootContextParamSets.GIFT); + List list = loottable.getRandomItems(lootparams); +@@ -647,13 +616,20 @@ + while (iterator.hasNext()) { + ItemStack itemstack = (ItemStack) iterator.next(); + +- this.cat.level().addFreshEntity(new ItemEntity(this.cat.level(), (double) blockpos_mutableblockpos.getX() - (double) Mth.sin(this.cat.yBodyRot * 0.017453292F), (double) blockpos_mutableblockpos.getY(), (double) blockpos_mutableblockpos.getZ() + (double) Mth.cos(this.cat.yBodyRot * 0.017453292F), itemstack)); ++ // CraftBukkit start ++ ItemEntity entityitem = new ItemEntity(this.cat.level(), (double) blockposition_mutableblockposition.getX() - (double) Mth.sin(this.cat.yBodyRot * 0.017453292F), (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + (double) Mth.cos(this.cat.yBodyRot * 0.017453292F), itemstack); ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.cat.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ entityitem.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ continue; ++ } ++ this.cat.level().addFreshEntity(entityitem); ++ // CraftBukkit end + } + + } + + @Override +- @Override + public void tick() { + if (this.ownerPlayer != null && this.goalPos != null) { + this.cat.setInSittingPose(false); +@@ -679,22 +655,20 @@ + + private final Cat cat; + +- public CatAvoidEntityGoal(Cat cat, Class oclass, float f, double d0, double d1) { +- Predicate predicate = EntitySelector.NO_CREATIVE_OR_SPECTATOR; ++ public CatAvoidEntityGoal(Cat cat, Class entityClassToAvoid, float maxDist, double walkSpeedModifier, double d1) { ++ // Predicate predicate = IEntitySelector.NO_CREATIVE_OR_SPECTATOR; // CraftBukkit - decompile error + +- Objects.requireNonNull(predicate); +- super(cat, oclass, f, d0, d1, predicate::test); ++ // Objects.requireNonNull(predicate); // CraftBukkit - decompile error ++ super(cat, entityClassToAvoid, maxDist, walkSpeedModifier, d1, EntitySelector.NO_CREATIVE_OR_SPECTATOR::test); // CraftBukkit - decompile error + this.cat = cat; + } + + @Override +- @Override + public boolean canUse() { + return !this.cat.isTame() && super.canUse(); + } + + @Override +- @Override + public boolean canContinueToUse() { + return !this.cat.isTame() && super.canContinueToUse(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Chicken.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Chicken.java.patch new file mode 100644 index 0000000000..54b4b4d892 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Chicken.java.patch @@ -0,0 +1,217 @@ +--- a/net/minecraft/world/entity/animal/Chicken.java ++++ b/net/minecraft/world/entity/animal/Chicken.java +@@ -11,10 +11,10 @@ + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.BreedGoal; +@@ -29,9 +29,9 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.item.crafting.Ingredient; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.Vec3; +@@ -49,14 +49,13 @@ + public int eggTime; + public boolean isChickenJockey; + +- public Chicken(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Chicken(EntityType entityType, Level level) { ++ super(entityType, level); + this.eggTime = this.random.nextInt(6000) + 6000; + this.setPathfindingMalus(BlockPathTypes.WATER, 0.0F); + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(1, new PanicGoal(this, 1.4D)); +@@ -69,9 +68,8 @@ + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return this.isBaby() ? entitydimensions.height * 0.85F : entitydimensions.height * 0.92F; ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { ++ return this.isBaby() ? size.height * 0.85F : size.height * 0.92F; + } + + public static AttributeSupplier.Builder createAttributes() { +@@ -79,7 +77,6 @@ + } + + @Override +- @Override + public void aiStep() { + super.aiStep(); + this.oFlap = this.flap; +@@ -91,16 +88,18 @@ + } + + this.flapping *= 0.9F; +- Vec3 vec3 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + +- if (!this.onGround() && vec3.y < 0.0D) { +- this.setDeltaMovement(vec3.multiply(1.0D, 0.6D, 1.0D)); ++ if (!this.onGround() && vec3d.y < 0.0D) { ++ this.setDeltaMovement(vec3d.multiply(1.0D, 0.6D, 1.0D)); + } + + this.flap += this.flapping * 2.0F; + if (!this.level().isClientSide && this.isAlive() && !this.isBaby() && !this.isChickenJockey() && --this.eggTime <= 0) { + this.playSound(SoundEvents.CHICKEN_EGG, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); +- this.spawnAtLocation((ItemLike) Items.EGG); ++ this.forceDrops = true; // CraftBukkit ++ this.spawnAtLocation((IMaterial) Items.EGG); ++ this.forceDrops = false; // CraftBukkit + this.gameEvent(GameEvent.ENTITY_PLACE); + this.eggTime = this.random.nextInt(6000) + 6000; + } +@@ -108,106 +107,92 @@ + } + + @Override +- @Override + protected boolean isFlapping() { + return this.flyDist > this.nextFlap; + } + + @Override +- @Override + protected void onFlap() { + this.nextFlap = this.flyDist + this.flapSpeed / 2.0F; + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.CHICKEN_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.CHICKEN_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.CHICKEN_DEATH; + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.CHICKEN_STEP, 0.15F, 1.0F); + } + + @Nullable + @Override +- @Override +- public Chicken getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { +- return (Chicken) EntityType.CHICKEN.create(serverlevel); ++ public Chicken getBreedOffspring(ServerLevel level, AgeableMob otherParent) { ++ return (Chicken) EntityType.CHICKEN.create(level); + } + + @Override +- @Override +- public boolean isFood(ItemStack itemstack) { +- return Chicken.FOOD_ITEMS.test(itemstack); ++ public boolean isFood(ItemStack stack) { ++ return Chicken.FOOD_ITEMS.test(stack); + } + + @Override +- @Override + public int getExperienceReward() { + return this.isChickenJockey() ? 10 : super.getExperienceReward(); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.isChickenJockey = compoundtag.getBoolean("IsChickenJockey"); +- if (compoundtag.contains("EggLayTime")) { +- this.eggTime = compoundtag.getInt("EggLayTime"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.isChickenJockey = compound.getBoolean("IsChickenJockey"); ++ if (compound.contains("EggLayTime")) { ++ this.eggTime = compound.getInt("EggLayTime"); + } + + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putBoolean("IsChickenJockey", this.isChickenJockey); +- compoundtag.putInt("EggLayTime", this.eggTime); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putBoolean("IsChickenJockey", this.isChickenJockey); ++ compound.putInt("EggLayTime", this.eggTime); + } + + @Override +- @Override +- public boolean removeWhenFarAway(double d0) { ++ public boolean removeWhenFarAway(double distanceToClosestPlayer) { + return this.isChickenJockey(); + } + + @Override +- @Override +- protected void positionRider(Entity entity, Entity.MoveFunction entity_movefunction) { +- super.positionRider(entity, entity_movefunction); +- if (entity instanceof LivingEntity) { +- ((LivingEntity) entity).yBodyRot = this.yBodyRot; ++ protected void positionRider(Entity passenger, Entity.MoveFunction callback) { ++ super.positionRider(passenger, callback); ++ if (passenger instanceof LivingEntity) { ++ ((LivingEntity) passenger).yBodyRot = this.yBodyRot; + } + + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height, -0.1F * f); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height, -0.1F * f); + } + + public boolean isChickenJockey() { + return this.isChickenJockey; + } + +- public void setChickenJockey(boolean flag) { +- this.isChickenJockey = flag; ++ public void setChickenJockey(boolean isChickenJockey) { ++ this.isChickenJockey = isChickenJockey; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Cow.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Cow.java.patch new file mode 100644 index 0000000000..55f9ccdc5b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Cow.java.patch @@ -0,0 +1,136 @@ +--- a/net/minecraft/world/entity/animal/Cow.java ++++ b/net/minecraft/world/entity/animal/Cow.java +@@ -5,15 +5,15 @@ + import net.minecraft.server.level.ServerLevel; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.BreedGoal; +@@ -30,17 +30,22 @@ + import net.minecraft.world.item.Items; + import net.minecraft.world.item.crafting.Ingredient; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerBucketFillEvent; ++// CraftBukkit end ++ + public class Cow extends Animal { + +- public Cow(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Cow(EntityType entityType, Level level) { ++ super(entityType, level); + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(1, new PanicGoal(this, 2.0D)); +@@ -57,67 +62,66 @@ + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.COW_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.COW_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.COW_DEATH; + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.COW_STEP, 0.15F, 1.0F); + } + + @Override +- @Override + protected float getSoundVolume() { + return 0.4F; + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (itemstack.is(Items.BUCKET) && !this.isBaby()) { ++ // CraftBukkit start - Got milk? ++ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level(), player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand); ++ ++ if (event.isCancelled()) { ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end ++ + player.playSound(SoundEvents.COW_MILK, 1.0F, 1.0F); +- ItemStack itemstack1 = ItemUtils.createFilledResult(itemstack, player, Items.MILK_BUCKET.getDefaultInstance()); ++ ItemStack itemstack1 = ItemUtils.createFilledResult(itemstack, player, CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit + +- player.setItemInHand(interactionhand, itemstack1); ++ player.setItemInHand(hand, itemstack1); + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { +- return super.mobInteract(player, interactionhand); ++ return super.mobInteract(player, hand); + } + } + + @Nullable + @Override +- @Override +- public Cow getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { +- return (Cow) EntityType.COW.create(serverlevel); ++ public Cow getBreedOffspring(ServerLevel level, AgeableMob otherParent) { ++ return (Cow) EntityType.COW.create(level); + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return this.isBaby() ? entitydimensions.height * 0.95F : 1.3F; ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { ++ return this.isBaby() ? size.height * 0.95F : 1.3F; + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height - 0.03125F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.03125F * f, 0.0F); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Dolphin.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Dolphin.java.patch new file mode 100644 index 0000000000..4771a068aa --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Dolphin.java.patch @@ -0,0 +1,640 @@ +--- a/net/minecraft/world/entity/animal/Dolphin.java ++++ b/net/minecraft/world/entity/animal/Dolphin.java +@@ -19,20 +19,20 @@ + import net.minecraft.tags.StructureTags; + import net.minecraft.util.Mth; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.SmoothSwimmingLookControl; +@@ -44,8 +44,8 @@ + import net.minecraft.world.entity.ai.goal.Goal; + import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; + import net.minecraft.world.entity.ai.goal.MeleeAttackGoal; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalRandomSwim; + import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal; +-import net.minecraft.world.entity.ai.goal.RandomSwimmingGoal; + import net.minecraft.world.entity.ai.goal.TryFindWaterGoal; + import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal; + import net.minecraft.world.entity.ai.navigation.PathNavigation; +@@ -58,23 +58,33 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityPotionEffectEvent; ++// CraftBukkit end + + public class Dolphin extends WaterAnimal { + ++ // CraftBukkit start - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ @Override ++ public int getDefaultMaxAirSupply() { ++ return TOTAL_AIR_SUPPLY; ++ } ++ // CraftBukkit end + private static final EntityDataAccessor TREASURE_POS = SynchedEntityData.defineId(Dolphin.class, EntityDataSerializers.BLOCK_POS); + private static final EntityDataAccessor GOT_FISH = SynchedEntityData.defineId(Dolphin.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor MOISTNESS_LEVEL = SynchedEntityData.defineId(Dolphin.class, EntityDataSerializers.INT); + static final TargetingConditions SWIM_WITH_PLAYER_TARGETING = TargetingConditions.forNonCombat().range(10.0D).ignoreLineOfSight(); + public static final int TOTAL_AIR_SUPPLY = 4800; + private static final int TOTAL_MOISTNESS_LEVEL = 2400; +- public static final Predicate ALLOWED_ITEMS = (itementity) -> { +- return !itementity.hasPickUpDelay() && itementity.isAlive() && itementity.isInWater(); ++ public static final Predicate ALLOWED_ITEMS = (entityitem) -> { ++ return !entityitem.hasPickUpDelay() && entityitem.isAlive() && entityitem.isInWater(); + }; + +- public Dolphin(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Dolphin(EntityType entityType, Level level) { ++ super(entityType, level); + this.moveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02F, 0.1F, true); + this.lookControl = new SmoothSwimmingLookControl(this, 10); + this.setCanPickUpLoot(true); +@@ -82,19 +92,17 @@ + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + this.setAirSupply(this.getMaxAirSupply()); + this.setXRot(0.0F); +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); ++ return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + + @Override +- @Override +- protected void handleAirSupply(int i) {} ++ protected void handleAirSupply(int airSupply) {} + +- public void setTreasurePos(BlockPos blockpos) { +- this.entityData.set(Dolphin.TREASURE_POS, blockpos); ++ public void setTreasurePos(BlockPos pos) { ++ this.entityData.set(Dolphin.TREASURE_POS, pos); + } + + public BlockPos getTreasurePos() { +@@ -105,20 +113,19 @@ + return (Boolean) this.entityData.get(Dolphin.GOT_FISH); + } + +- public void setGotFish(boolean flag) { +- this.entityData.set(Dolphin.GOT_FISH, flag); ++ public void setGotFish(boolean gotFish) { ++ this.entityData.set(Dolphin.GOT_FISH, gotFish); + } + + public int getMoistnessLevel() { + return (Integer) this.entityData.get(Dolphin.MOISTNESS_LEVEL); + } + +- public void setMoisntessLevel(int i) { +- this.entityData.set(Dolphin.MOISTNESS_LEVEL, i); ++ public void setMoisntessLevel(int moistnessLevel) { ++ this.entityData.set(Dolphin.MOISTNESS_LEVEL, moistnessLevel); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Dolphin.TREASURE_POS, BlockPos.ZERO); +@@ -127,37 +134,34 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("TreasurePosX", this.getTreasurePos().getX()); +- compoundtag.putInt("TreasurePosY", this.getTreasurePos().getY()); +- compoundtag.putInt("TreasurePosZ", this.getTreasurePos().getZ()); +- compoundtag.putBoolean("GotFish", this.gotFish()); +- compoundtag.putInt("Moistness", this.getMoistnessLevel()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("TreasurePosX", this.getTreasurePos().getX()); ++ compound.putInt("TreasurePosY", this.getTreasurePos().getY()); ++ compound.putInt("TreasurePosZ", this.getTreasurePos().getZ()); ++ compound.putBoolean("GotFish", this.gotFish()); ++ compound.putInt("Moistness", this.getMoistnessLevel()); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- int i = compoundtag.getInt("TreasurePosX"); +- int j = compoundtag.getInt("TreasurePosY"); +- int k = compoundtag.getInt("TreasurePosZ"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ int i = compound.getInt("TreasurePosX"); ++ int j = compound.getInt("TreasurePosY"); ++ int k = compound.getInt("TreasurePosZ"); + + this.setTreasurePos(new BlockPos(i, j, k)); +- super.readAdditionalSaveData(compoundtag); +- this.setGotFish(compoundtag.getBoolean("GotFish")); +- this.setMoisntessLevel(compoundtag.getInt("Moistness")); ++ super.readAdditionalSaveData(compound); ++ this.setGotFish(compound.getBoolean("GotFish")); ++ this.setMoisntessLevel(compound.getInt("Moistness")); + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new BreathAirGoal(this)); + this.goalSelector.addGoal(0, new TryFindWaterGoal(this)); + this.goalSelector.addGoal(1, new Dolphin.DolphinSwimToTreasureGoal(this)); + this.goalSelector.addGoal(2, new Dolphin.DolphinSwimWithPlayerGoal(this, 4.0D)); +- this.goalSelector.addGoal(4, new RandomSwimmingGoal(this, 1.0D, 10)); ++ this.goalSelector.addGoal(4, new PathfinderGoalRandomSwim(this, 1.0D, 10)); + this.goalSelector.addGoal(4, new RandomLookAroundGoal(this)); + this.goalSelector.addGoal(5, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(5, new DolphinJumpGoal(this, 10)); +@@ -173,13 +177,11 @@ + } + + @Override +- @Override + protected PathNavigation createNavigation(Level level) { + return new WaterBoundPathNavigation(this, level); + } + + @Override +- @Override + public boolean doHurtTarget(Entity entity) { + boolean flag = entity.hurt(this.damageSources().mobAttack(this), (float) ((int) this.getAttributeValue(Attributes.ATTACK_DAMAGE))); + +@@ -192,68 +194,65 @@ + } + + @Override +- @Override + public int getMaxAirSupply() { +- return 4800; ++ return maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() + } + + @Override +- @Override +- protected int increaseAirSupply(int i) { ++ protected int increaseAirSupply(int currentAir) { + return this.getMaxAirSupply(); + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.3F; + } + + @Override +- @Override + public int getMaxHeadXRot() { + return 1; + } + + @Override +- @Override + public int getMaxHeadYRot() { + return 1; + } + + @Override +- @Override + protected boolean canRide(Entity entity) { + return true; + } + + @Override +- @Override + public boolean canTakeItem(ItemStack itemstack) { +- EquipmentSlot equipmentslot = Mob.getEquipmentSlotForItem(itemstack); ++ EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(itemstack); + +- return !this.getItemBySlot(equipmentslot).isEmpty() ? false : equipmentslot == EquipmentSlot.MAINHAND && super.canTakeItem(itemstack); ++ return !this.getItemBySlot(enumitemslot).isEmpty() ? false : enumitemslot == EquipmentSlot.MAINHAND && super.canTakeItem(itemstack); + } + + @Override +- @Override +- protected void pickUpItem(ItemEntity itementity) { ++ protected void pickUpItem(ItemEntity itemEntity) { + if (this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty()) { +- ItemStack itemstack = itementity.getItem(); ++ ItemStack itemstack = itemEntity.getItem(); + + if (this.canHoldItem(itemstack)) { +- this.onItemPickup(itementity); ++ // CraftBukkit start - call EntityPickupItemEvent ++ if (CraftEventFactory.callEntityPickupItemEvent(this, itemEntity, 0, false).isCancelled()) { ++ return; ++ } ++ itemstack = itemEntity.getItem(); // CraftBukkit- update ItemStack from event ++ // CraftBukkit start ++ this.onItemPickup(itemEntity); + this.setItemSlot(EquipmentSlot.MAINHAND, itemstack); + this.setGuaranteedDrop(EquipmentSlot.MAINHAND); +- this.take(itementity, itemstack.getCount()); +- itementity.discard(); ++ this.take(itemEntity, itemstack.getCount()); ++ itemEntity.discard(); + } + } + + } + + @Override +- @Override + public void tick() { + super.tick(); + if (this.isNoAi()) { +@@ -276,14 +275,14 @@ + } + + if (this.level().isClientSide && this.isInWater() && this.getDeltaMovement().lengthSqr() > 0.03D) { +- Vec3 vec3 = this.getViewVector(0.0F); ++ Vec3 vec3d = this.getViewVector(0.0F); + float f = Mth.cos(this.getYRot() * 0.017453292F) * 0.3F; + float f1 = Mth.sin(this.getYRot() * 0.017453292F) * 0.3F; + float f2 = 1.2F - this.random.nextFloat() * 0.7F; + + for (int i = 0; i < 2; ++i) { +- this.level().addParticle(ParticleTypes.DOLPHIN, this.getX() - vec3.x * (double) f2 + (double) f, this.getY() - vec3.y, this.getZ() - vec3.z * (double) f2 + (double) f1, 0.0D, 0.0D, 0.0D); +- this.level().addParticle(ParticleTypes.DOLPHIN, this.getX() - vec3.x * (double) f2 - (double) f, this.getY() - vec3.y, this.getZ() - vec3.z * (double) f2 - (double) f1, 0.0D, 0.0D, 0.0D); ++ this.level().addParticle(ParticleTypes.DOLPHIN, this.getX() - vec3d.x * (double) f2 + (double) f, this.getY() - vec3d.y, this.getZ() - vec3d.z * (double) f2 + (double) f1, 0.0D, 0.0D, 0.0D); ++ this.level().addParticle(ParticleTypes.DOLPHIN, this.getX() - vec3d.x * (double) f2 - (double) f, this.getY() - vec3d.y, this.getZ() - vec3d.z * (double) f2 - (double) f1, 0.0D, 0.0D, 0.0D); + } + } + +@@ -291,31 +290,29 @@ + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 38) { ++ public void handleEntityEvent(byte id) { ++ if (id == 38) { + this.addParticlesAroundSelf(ParticleTypes.HAPPY_VILLAGER); + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } + +- private void addParticlesAroundSelf(ParticleOptions particleoptions) { ++ private void addParticlesAroundSelf(ParticleOptions particleOption) { + for (int i = 0; i < 7; ++i) { + double d0 = this.random.nextGaussian() * 0.01D; + double d1 = this.random.nextGaussian() * 0.01D; + double d2 = this.random.nextGaussian() * 0.01D; + +- this.level().addParticle(particleoptions, this.getRandomX(1.0D), this.getRandomY() + 0.2D, this.getRandomZ(1.0D), d0, d1, d2); ++ this.level().addParticle(particleOption, this.getRandomX(1.0D), this.getRandomY() + 0.2D, this.getRandomZ(1.0D), d0, d1, d2); + } + + } + + @Override +- @Override +- protected InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ protected InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (!itemstack.isEmpty() && itemstack.is(ItemTags.FISHES)) { + if (!this.level().isClientSide) { +@@ -329,66 +326,59 @@ + + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { +- return super.mobInteract(player, interactionhand); ++ return super.mobInteract(player, hand); + } + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.DOLPHIN_HURT; + } + + @Nullable + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.DOLPHIN_DEATH; + } + + @Nullable + @Override +- @Override + protected SoundEvent getAmbientSound() { + return this.isInWater() ? SoundEvents.DOLPHIN_AMBIENT_WATER : SoundEvents.DOLPHIN_AMBIENT; + } + + @Override +- @Override + protected SoundEvent getSwimSplashSound() { + return SoundEvents.DOLPHIN_SPLASH; + } + + @Override +- @Override + protected SoundEvent getSwimSound() { + return SoundEvents.DOLPHIN_SWIM; + } + + protected boolean closeToNextPos() { +- BlockPos blockpos = this.getNavigation().getTargetPos(); ++ BlockPos blockposition = this.getNavigation().getTargetPos(); + +- return blockpos != null ? blockpos.closerToCenterThan(this.position(), 12.0D) : false; ++ return blockposition != null ? blockposition.closerToCenterThan(this.position(), 12.0D) : false; + } + + @Override +- @Override +- public void travel(Vec3 vec3) { ++ public void travel(Vec3 travelVector) { + if (this.isEffectiveAi() && this.isInWater()) { +- this.moveRelative(this.getSpeed(), vec3); +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.moveRelative(this.getSpeed(), travelVector); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + this.setDeltaMovement(this.getDeltaMovement().scale(0.9D)); + if (this.getTarget() == null) { + this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.005D, 0.0D)); + } + } else { +- super.travel(vec3); ++ super.travel(travelVector); + } + + } + + @Override +- @Override + public boolean canBeLeashed(Player player) { + return true; + } +@@ -400,43 +390,39 @@ + + DolphinSwimToTreasureGoal(Dolphin dolphin) { + this.dolphin = dolphin; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + } + + @Override +- @Override + public boolean isInterruptable() { + return false; + } + + @Override +- @Override + public boolean canUse() { + return this.dolphin.gotFish() && this.dolphin.getAirSupply() >= 100; + } + + @Override +- @Override + public boolean canContinueToUse() { +- BlockPos blockpos = this.dolphin.getTreasurePos(); ++ BlockPos blockposition = this.dolphin.getTreasurePos(); + +- return !BlockPos.containing((double) blockpos.getX(), this.dolphin.getY(), (double) blockpos.getZ()).closerToCenterThan(this.dolphin.position(), 4.0D) && !this.stuck && this.dolphin.getAirSupply() >= 100; ++ return !BlockPos.containing((double) blockposition.getX(), this.dolphin.getY(), (double) blockposition.getZ()).closerToCenterThan(this.dolphin.position(), 4.0D) && !this.stuck && this.dolphin.getAirSupply() >= 100; + } + + @Override +- @Override + public void start() { + if (this.dolphin.level() instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) this.dolphin.level(); ++ ServerLevel worldserver = (ServerLevel) this.dolphin.level(); + + this.stuck = false; + this.dolphin.getNavigation().stop(); +- BlockPos blockpos = this.dolphin.blockPosition(); +- BlockPos blockpos1 = serverlevel.findNearestMapStructure(StructureTags.DOLPHIN_LOCATED, blockpos, 50, false); ++ BlockPos blockposition = this.dolphin.blockPosition(); ++ BlockPos blockposition1 = worldserver.findNearestMapStructure(StructureTags.DOLPHIN_LOCATED, blockposition, 50, false); + +- if (blockpos1 != null) { +- this.dolphin.setTreasurePos(blockpos1); +- serverlevel.broadcastEntityEvent(this.dolphin, (byte) 38); ++ if (blockposition1 != null) { ++ this.dolphin.setTreasurePos(blockposition1); ++ worldserver.broadcastEntityEvent(this.dolphin, (byte) 38); + } else { + this.stuck = true; + } +@@ -444,46 +430,44 @@ + } + + @Override +- @Override + public void stop() { +- BlockPos blockpos = this.dolphin.getTreasurePos(); ++ BlockPos blockposition = this.dolphin.getTreasurePos(); + +- if (BlockPos.containing((double) blockpos.getX(), this.dolphin.getY(), (double) blockpos.getZ()).closerToCenterThan(this.dolphin.position(), 4.0D) || this.stuck) { ++ if (BlockPos.containing((double) blockposition.getX(), this.dolphin.getY(), (double) blockposition.getZ()).closerToCenterThan(this.dolphin.position(), 4.0D) || this.stuck) { + this.dolphin.setGotFish(false); + } + + } + + @Override +- @Override + public void tick() { +- Level level = this.dolphin.level(); ++ Level world = this.dolphin.level(); + + if (this.dolphin.closeToNextPos() || this.dolphin.getNavigation().isDone()) { +- Vec3 vec3 = Vec3.atCenterOf(this.dolphin.getTreasurePos()); +- Vec3 vec31 = DefaultRandomPos.getPosTowards(this.dolphin, 16, 1, vec3, 0.39269909262657166D); ++ Vec3 vec3d = Vec3.atCenterOf(this.dolphin.getTreasurePos()); ++ Vec3 vec3d1 = DefaultRandomPos.getPosTowards(this.dolphin, 16, 1, vec3d, 0.39269909262657166D); + +- if (vec31 == null) { +- vec31 = DefaultRandomPos.getPosTowards(this.dolphin, 8, 4, vec3, 1.5707963705062866D); ++ if (vec3d1 == null) { ++ vec3d1 = DefaultRandomPos.getPosTowards(this.dolphin, 8, 4, vec3d, 1.5707963705062866D); + } + +- if (vec31 != null) { +- BlockPos blockpos = BlockPos.containing(vec31); ++ if (vec3d1 != null) { ++ BlockPos blockposition = BlockPos.containing(vec3d1); + +- if (!level.getFluidState(blockpos).is(FluidTags.WATER) || !level.getBlockState(blockpos).isPathfindable(level, blockpos, PathComputationType.WATER)) { +- vec31 = DefaultRandomPos.getPosTowards(this.dolphin, 8, 5, vec3, 1.5707963705062866D); ++ if (!world.getFluidState(blockposition).is(FluidTags.WATER) || !world.getBlockState(blockposition).isPathfindable(world, blockposition, PathMode.WATER)) { ++ vec3d1 = DefaultRandomPos.getPosTowards(this.dolphin, 8, 5, vec3d, 1.5707963705062866D); + } + } + +- if (vec31 == null) { ++ if (vec3d1 == null) { + this.stuck = true; + return; + } + +- this.dolphin.getLookControl().setLookAt(vec31.x, vec31.y, vec31.z, (float) (this.dolphin.getMaxHeadYRot() + 20), (float) this.dolphin.getMaxHeadXRot()); +- this.dolphin.getNavigation().moveTo(vec31.x, vec31.y, vec31.z, 1.3D); +- if (level.random.nextInt(this.adjustedTickDelay(80)) == 0) { +- level.broadcastEntityEvent(this.dolphin, (byte) 38); ++ this.dolphin.getLookControl().setLookAt(vec3d1.x, vec3d1.y, vec3d1.z, (float) (this.dolphin.getMaxHeadYRot() + 20), (float) this.dolphin.getMaxHeadXRot()); ++ this.dolphin.getNavigation().moveTo(vec3d1.x, vec3d1.y, vec3d1.z, 1.3D); ++ if (world.random.nextInt(this.adjustedTickDelay(80)) == 0) { ++ world.broadcastEntityEvent(this.dolphin, (byte) 38); + } + } + +@@ -497,40 +481,35 @@ + @Nullable + private Player player; + +- DolphinSwimWithPlayerGoal(Dolphin dolphin, double d0) { ++ DolphinSwimWithPlayerGoal(Dolphin dolphin, double speedModifier) { + this.dolphin = dolphin; +- this.speedModifier = d0; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ this.speedModifier = speedModifier; ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + } + + @Override +- @Override + public boolean canUse() { + this.player = this.dolphin.level().getNearestPlayer(Dolphin.SWIM_WITH_PLAYER_TARGETING, this.dolphin); + return this.player == null ? false : this.player.isSwimming() && this.dolphin.getTarget() != this.player; + } + + @Override +- @Override + public boolean canContinueToUse() { + return this.player != null && this.player.isSwimming() && this.dolphin.distanceToSqr((Entity) this.player) < 256.0D; + } + + @Override +- @Override + public void start() { +- this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin); ++ this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin, EntityPotionEffectEvent.Cause.DOLPHIN); // CraftBukkit + } + + @Override +- @Override + public void stop() { + this.player = null; + this.dolphin.getNavigation().stop(); + } + + @Override +- @Override + public void tick() { + this.dolphin.getLookControl().setLookAt(this.player, (float) (this.dolphin.getMaxHeadYRot() + 20), (float) this.dolphin.getMaxHeadXRot()); + if (this.dolphin.distanceToSqr((Entity) this.player) < 6.25D) { +@@ -540,7 +519,7 @@ + } + + if (this.player.isSwimming() && this.player.level().random.nextInt(6) == 0) { +- this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin); ++ this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin, EntityPotionEffectEvent.Cause.DOLPHIN); // CraftBukkit + } + + } +@@ -553,7 +532,6 @@ + PlayWithItemsGoal() {} + + @Override +- @Override + public boolean canUse() { + if (this.cooldown > Dolphin.this.tickCount) { + return false; +@@ -565,7 +543,6 @@ + } + + @Override +- @Override + public void start() { + List list = Dolphin.this.level().getEntitiesOfClass(ItemEntity.class, Dolphin.this.getBoundingBox().inflate(8.0D, 8.0D, 8.0D), Dolphin.ALLOWED_ITEMS); + +@@ -578,7 +555,6 @@ + } + + @Override +- @Override + public void stop() { + ItemStack itemstack = Dolphin.this.getItemBySlot(EquipmentSlot.MAINHAND); + +@@ -591,7 +567,6 @@ + } + + @Override +- @Override + public void tick() { + List list = Dolphin.this.level().getEntitiesOfClass(ItemEntity.class, Dolphin.this.getBoundingBox().inflate(8.0D, 8.0D, 8.0D), Dolphin.ALLOWED_ITEMS); + ItemStack itemstack = Dolphin.this.getItemBySlot(EquipmentSlot.MAINHAND); +@@ -605,19 +580,19 @@ + + } + +- private void drop(ItemStack itemstack) { +- if (!itemstack.isEmpty()) { ++ private void drop(ItemStack stack) { ++ if (!stack.isEmpty()) { + double d0 = Dolphin.this.getEyeY() - 0.30000001192092896D; +- ItemEntity itementity = new ItemEntity(Dolphin.this.level(), Dolphin.this.getX(), d0, Dolphin.this.getZ(), itemstack); ++ ItemEntity entityitem = new ItemEntity(Dolphin.this.level(), Dolphin.this.getX(), d0, Dolphin.this.getZ(), stack); + +- itementity.setPickUpDelay(40); +- itementity.setThrower(Dolphin.this); ++ entityitem.setPickUpDelay(40); ++ entityitem.setThrower(Dolphin.this); + float f = 0.3F; + float f1 = Dolphin.this.random.nextFloat() * 6.2831855F; + float f2 = 0.02F * Dolphin.this.random.nextFloat(); + +- itementity.setDeltaMovement((double) (0.3F * -Mth.sin(Dolphin.this.getYRot() * 0.017453292F) * Mth.cos(Dolphin.this.getXRot() * 0.017453292F) + Mth.cos(f1) * f2), (double) (0.3F * Mth.sin(Dolphin.this.getXRot() * 0.017453292F) * 1.5F), (double) (0.3F * Mth.cos(Dolphin.this.getYRot() * 0.017453292F) * Mth.cos(Dolphin.this.getXRot() * 0.017453292F) + Mth.sin(f1) * f2)); +- Dolphin.this.level().addFreshEntity(itementity); ++ entityitem.setDeltaMovement((double) (0.3F * -Mth.sin(Dolphin.this.getYRot() * 0.017453292F) * Mth.cos(Dolphin.this.getXRot() * 0.017453292F) + Mth.cos(f1) * f2), (double) (0.3F * Mth.sin(Dolphin.this.getXRot() * 0.017453292F) * 1.5F), (double) (0.3F * Mth.cos(Dolphin.this.getYRot() * 0.017453292F) * Mth.cos(Dolphin.this.getXRot() * 0.017453292F) + Mth.sin(f1) * f2)); ++ Dolphin.this.level().addFreshEntity(entityitem); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Fox.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Fox.java.patch new file mode 100644 index 0000000000..925e988439 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Fox.java.patch @@ -0,0 +1,1551 @@ +--- a/net/minecraft/world/entity/animal/Fox.java ++++ b/net/minecraft/world/entity/animal/Fox.java +@@ -35,20 +35,20 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.util.StringRepresentable; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.ExperienceOrb; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.TamableAnimal; + import net.minecraft.world.entity.VariantHolder; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -62,12 +62,12 @@ + import net.minecraft.world.entity.ai.goal.FloatGoal; + import net.minecraft.world.entity.ai.goal.FollowParentGoal; + import net.minecraft.world.entity.ai.goal.Goal; +-import net.minecraft.world.entity.ai.goal.JumpGoal; + import net.minecraft.world.entity.ai.goal.LeapAtTargetGoal; + import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; + import net.minecraft.world.entity.ai.goal.MeleeAttackGoal; + import net.minecraft.world.entity.ai.goal.MoveToBlockGoal; + import net.minecraft.world.entity.ai.goal.PanicGoal; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalWaterJumpAbstract; + import net.minecraft.world.entity.ai.goal.StrollThroughVillageGoal; + import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal; + import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; +@@ -88,7 +88,7 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.CaveVines; + import net.minecraft.world.level.block.SweetBerryBushBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.Vec3; +@@ -105,18 +105,18 @@ + private static final int FLAG_SLEEPING = 32; + private static final int FLAG_FACEPLANTED = 64; + private static final int FLAG_DEFENDING = 128; +- private static final EntityDataAccessor> DATA_TRUSTED_ID_0 = SynchedEntityData.defineId(Fox.class, EntityDataSerializers.OPTIONAL_UUID); +- private static final EntityDataAccessor> DATA_TRUSTED_ID_1 = SynchedEntityData.defineId(Fox.class, EntityDataSerializers.OPTIONAL_UUID); +- static final Predicate ALLOWED_ITEMS = (itementity) -> { +- return !itementity.hasPickUpDelay() && itementity.isAlive(); ++ public static final EntityDataAccessor> DATA_TRUSTED_ID_0 = SynchedEntityData.defineId(Fox.class, EntityDataSerializers.OPTIONAL_UUID); ++ public static final EntityDataAccessor> DATA_TRUSTED_ID_1 = SynchedEntityData.defineId(Fox.class, EntityDataSerializers.OPTIONAL_UUID); ++ static final Predicate ALLOWED_ITEMS = (entityitem) -> { ++ return !entityitem.hasPickUpDelay() && entityitem.isAlive(); + }; + private static final Predicate TRUSTED_TARGET_SELECTOR = (entity) -> { + if (!(entity instanceof LivingEntity)) { + return false; + } else { +- LivingEntity livingentity = (LivingEntity) entity; ++ LivingEntity entityliving = (LivingEntity) entity; + +- return livingentity.getLastHurtMob() != null && livingentity.getLastHurtMobTimestamp() < livingentity.tickCount + 600; ++ return entityliving.getLastHurtMob() != null && entityliving.getLastHurtMobTimestamp() < entityliving.tickCount + 600; + } + }; + static final Predicate STALKABLE_PREY = (entity) -> { +@@ -135,17 +135,16 @@ + float crouchAmountO; + private int ticksSinceEaten; + +- public Fox(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Fox(EntityType entityType, Level level) { ++ super(entityType, level); + this.lookControl = new Fox.FoxLookControl(); +- this.moveControl = new Fox.FoxMoveControl(); ++ this.moveControl = new Fox.m(); + this.setPathfindingMalus(BlockPathTypes.DANGER_OTHER, 0.0F); + this.setPathfindingMalus(BlockPathTypes.DAMAGE_OTHER, 0.0F); + this.setCanPickUpLoot(true); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Fox.DATA_TRUSTED_ID_0, Optional.empty()); +@@ -155,27 +154,26 @@ + } + + @Override +- @Override + protected void registerGoals() { +- this.landTargetGoal = new NearestAttackableTargetGoal<>(this, Animal.class, 10, false, false, (livingentity) -> { +- return livingentity instanceof Chicken || livingentity instanceof Rabbit; ++ this.landTargetGoal = new NearestAttackableTargetGoal<>(this, Animal.class, 10, false, false, (entityliving) -> { ++ return entityliving instanceof Chicken || entityliving instanceof Rabbit; + }); + this.turtleEggTargetGoal = new NearestAttackableTargetGoal<>(this, Turtle.class, 10, false, false, Turtle.BABY_ON_LAND_SELECTOR); +- this.fishTargetGoal = new NearestAttackableTargetGoal<>(this, AbstractFish.class, 20, false, false, (livingentity) -> { +- return livingentity instanceof AbstractSchoolingFish; ++ this.fishTargetGoal = new NearestAttackableTargetGoal<>(this, AbstractFish.class, 20, false, false, (entityliving) -> { ++ return entityliving instanceof AbstractSchoolingFish; + }); + this.goalSelector.addGoal(0, new Fox.FoxFloatGoal()); + this.goalSelector.addGoal(0, new ClimbOnTopOfPowderSnowGoal(this, this.level())); + this.goalSelector.addGoal(1, new Fox.FaceplantGoal()); + this.goalSelector.addGoal(2, new Fox.FoxPanicGoal(2.2D)); + this.goalSelector.addGoal(3, new Fox.FoxBreedGoal(1.0D)); +- this.goalSelector.addGoal(4, new AvoidEntityGoal<>(this, Player.class, 16.0F, 1.6D, 1.4D, (livingentity) -> { +- return Fox.AVOID_PLAYERS.test(livingentity) && !this.trusts(livingentity.getUUID()) && !this.isDefending(); ++ this.goalSelector.addGoal(4, new AvoidEntityGoal<>(this, Player.class, 16.0F, 1.6D, 1.4D, (entityliving) -> { ++ return Fox.AVOID_PLAYERS.test(entityliving) && !this.trusts(entityliving.getUUID()) && !this.isDefending(); + })); +- this.goalSelector.addGoal(4, new AvoidEntityGoal<>(this, Wolf.class, 8.0F, 1.6D, 1.4D, (livingentity) -> { +- return !((Wolf) livingentity).isTame() && !this.isDefending(); ++ this.goalSelector.addGoal(4, new AvoidEntityGoal<>(this, Wolf.class, 8.0F, 1.6D, 1.4D, (entityliving) -> { ++ return !((Wolf) entityliving).isTame() && !this.isDefending(); + })); +- this.goalSelector.addGoal(4, new AvoidEntityGoal<>(this, PolarBear.class, 8.0F, 1.6D, 1.4D, (livingentity) -> { ++ this.goalSelector.addGoal(4, new AvoidEntityGoal<>(this, PolarBear.class, 8.0F, 1.6D, 1.4D, (entityliving) -> { + return !this.isDefending(); + })); + this.goalSelector.addGoal(5, new Fox.StalkPreyGoal()); +@@ -191,19 +189,17 @@ + this.goalSelector.addGoal(11, new Fox.FoxSearchForItemsGoal()); + this.goalSelector.addGoal(12, new Fox.FoxLookAtPlayerGoal(this, Player.class, 24.0F)); + this.goalSelector.addGoal(13, new Fox.PerchAndSearchGoal()); +- this.targetSelector.addGoal(3, new Fox.DefendTrustedTargetGoal(LivingEntity.class, false, false, (livingentity) -> { +- return Fox.TRUSTED_TARGET_SELECTOR.test(livingentity) && !this.trusts(livingentity.getUUID()); ++ this.targetSelector.addGoal(3, new Fox.DefendTrustedTargetGoal(LivingEntity.class, false, false, (entityliving) -> { ++ return Fox.TRUSTED_TARGET_SELECTOR.test(entityliving) && !this.trusts(entityliving.getUUID()); + })); + } + + @Override +- @Override +- public SoundEvent getEatingSound(ItemStack itemstack) { ++ public SoundEvent getEatingSound(ItemStack itemStack) { + return SoundEvents.FOX_EAT; + } + + @Override +- @Override + public void aiStep() { + if (!this.level().isClientSide && this.isAlive() && this.isEffectiveAi()) { + ++this.ticksSinceEaten; +@@ -224,9 +220,9 @@ + } + } + +- LivingEntity livingentity = this.getTarget(); ++ LivingEntity entityliving = this.getTarget(); + +- if (livingentity == null || !livingentity.isAlive()) { ++ if (entityliving == null || !entityliving.isAlive()) { + this.setIsCrouching(false); + this.setIsInterested(false); + } +@@ -246,20 +242,18 @@ + } + + @Override +- @Override + protected boolean isImmobile() { + return this.isDeadOrDying(); + } + +- private boolean canEat(ItemStack itemstack) { +- return itemstack.getItem().isEdible() && this.getTarget() == null && this.onGround() && !this.isSleeping(); ++ private boolean canEat(ItemStack stack) { ++ return stack.getItem().isEdible() && this.getTarget() == null && this.onGround() && !this.isSleeping(); + } + + @Override +- @Override +- protected void populateDefaultEquipmentSlots(RandomSource randomsource, DifficultyInstance difficultyinstance) { +- if (randomsource.nextFloat() < 0.2F) { +- float f = randomsource.nextFloat(); ++ protected void populateDefaultEquipmentSlots(RandomSource random, DifficultyInstance difficulty) { ++ if (random.nextFloat() < 0.2F) { ++ float f = random.nextFloat(); + ItemStack itemstack; + + if (f < 0.05F) { +@@ -267,7 +261,7 @@ + } else if (f < 0.2F) { + itemstack = new ItemStack(Items.EGG); + } else if (f < 0.4F) { +- itemstack = randomsource.nextBoolean() ? new ItemStack(Items.RABBIT_FOOT) : new ItemStack(Items.RABBIT_HIDE); ++ itemstack = random.nextBoolean() ? new ItemStack(Items.RABBIT_FOOT) : new ItemStack(Items.RABBIT_HIDE); + } else if (f < 0.6F) { + itemstack = new ItemStack(Items.WHEAT); + } else if (f < 0.8F) { +@@ -282,20 +276,19 @@ + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 45) { ++ public void handleEntityEvent(byte id) { ++ if (id == 45) { + ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND); + + if (!itemstack.isEmpty()) { + for (int i = 0; i < 8; ++i) { +- Vec3 vec3 = (new Vec3(((double) this.random.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, 0.0D)).xRot(-this.getXRot() * 0.017453292F).yRot(-this.getYRot() * 0.017453292F); ++ Vec3 vec3d = (new Vec3(((double) this.random.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, 0.0D)).xRot(-this.getXRot() * 0.017453292F).yRot(-this.getYRot() * 0.017453292F); + +- this.level().addParticle(new ItemParticleOption(ParticleTypes.ITEM, itemstack), this.getX() + this.getLookAngle().x / 2.0D, this.getY(), this.getZ() + this.getLookAngle().z / 2.0D, vec3.x, vec3.y + 0.05D, vec3.z); ++ this.level().addParticle(new ItemParticleOption(ParticleTypes.ITEM, itemstack), this.getX() + this.getLookAngle().x / 2.0D, this.getY(), this.getZ() + this.getLookAngle().z / 2.0D, vec3d.x, vec3d.y + 0.05D, vec3d.z); + } + } + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } +@@ -306,51 +299,49 @@ + + @Nullable + @Override +- @Override +- public Fox getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { +- Fox fox = (Fox) EntityType.FOX.create(serverlevel); ++ public Fox getBreedOffspring(ServerLevel level, AgeableMob otherParent) { ++ Fox entityfox = (Fox) EntityType.FOX.create(level); + +- if (fox != null) { +- fox.setVariant(this.random.nextBoolean() ? this.getVariant() : ((Fox) ageablemob).getVariant()); ++ if (entityfox != null) { ++ entityfox.setVariant(this.random.nextBoolean() ? this.getVariant() : ((Fox) otherParent).getVariant()); + } + +- return fox; ++ return entityfox; + } + +- public static boolean checkFoxSpawnRules(EntityType entitytype, LevelAccessor levelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- return levelaccessor.getBlockState(blockpos.below()).is(BlockTags.FOXES_SPAWNABLE_ON) && isBrightEnoughToSpawn(levelaccessor, blockpos); ++ public static boolean checkFoxSpawnRules(EntityType fox, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ return level.getBlockState(pos.below()).is(BlockTags.FOXES_SPAWNABLE_ON) && isBrightEnoughToSpawn(level, pos); + } + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- Holder holder = serverlevelaccessor.getBiome(this.blockPosition()); +- Fox.Type fox_type = Fox.Type.byBiome(holder); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ Holder holder = level.getBiome(this.blockPosition()); ++ Fox.Type entityfox_type = Fox.Type.byBiome(holder); + boolean flag = false; + +- if (spawngroupdata instanceof Fox.FoxGroupData) { +- Fox.FoxGroupData fox_foxgroupdata = (Fox.FoxGroupData) spawngroupdata; ++ if (spawnData instanceof Fox.FoxGroupData) { ++ Fox.FoxGroupData entityfox_i = (Fox.FoxGroupData) spawnData; + +- fox_type = fox_foxgroupdata.type; +- if (fox_foxgroupdata.getGroupSize() >= 2) { ++ entityfox_type = entityfox_i.type; ++ if (entityfox_i.getGroupSize() >= 2) { + flag = true; + } + } else { +- spawngroupdata = new Fox.FoxGroupData(fox_type); ++ spawnData = new Fox.FoxGroupData(entityfox_type); + } + +- this.setVariant(fox_type); ++ this.setVariant(entityfox_type); + if (flag) { + this.setAge(-24000); + } + +- if (serverlevelaccessor instanceof ServerLevel) { ++ if (level instanceof ServerLevel) { + this.setTargetGoals(); + } + +- this.populateDefaultEquipmentSlots(serverlevelaccessor.getRandom(), difficultyinstance); +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, (SpawnGroupData) spawngroupdata, compoundtag); ++ this.populateDefaultEquipmentSlots(level.getRandom(), difficulty); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + + private void setTargetGoals() { +@@ -367,30 +358,26 @@ + } + + @Override +- @Override +- protected void usePlayerItem(Player player, InteractionHand interactionhand, ItemStack itemstack) { +- if (this.isFood(itemstack)) { +- this.playSound(this.getEatingSound(itemstack), 1.0F, 1.0F); ++ protected void usePlayerItem(Player player, EnumHand hand, ItemStack stack) { ++ if (this.isFood(stack)) { ++ this.playSound(this.getEatingSound(stack), 1.0F, 1.0F); + } + +- super.usePlayerItem(player, interactionhand, itemstack); ++ super.usePlayerItem(player, hand, stack); + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return this.isBaby() ? entitydimensions.height * 0.85F : 0.4F; ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { ++ return this.isBaby() ? size.height * 0.85F : 0.4F; + } + + @Override +- @Override + public Fox.Type getVariant() { + return Fox.Type.byId((Integer) this.entityData.get(Fox.DATA_TYPE_ID)); + } + +- @Override +- public void setVariant(Fox.Type fox_type) { +- this.entityData.set(Fox.DATA_TYPE_ID, fox_type.getId()); ++ public void setVariant(Fox.Type variant) { ++ this.entityData.set(Fox.DATA_TYPE_ID, variant.getId()); + } + + List getTrustedUUIDs() { +@@ -411,45 +398,43 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); + List list = this.getTrustedUUIDs(); +- ListTag listtag = new ListTag(); ++ ListTag nbttaglist = new ListTag(); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { + UUID uuid = (UUID) iterator.next(); + + if (uuid != null) { +- listtag.add(NbtUtils.createUUID(uuid)); ++ nbttaglist.add(NbtUtils.createUUID(uuid)); + } + } + +- compoundtag.put("Trusted", listtag); +- compoundtag.putBoolean("Sleeping", this.isSleeping()); +- compoundtag.putString("Type", this.getVariant().getSerializedName()); +- compoundtag.putBoolean("Sitting", this.isSitting()); +- compoundtag.putBoolean("Crouching", this.isCrouching()); ++ compound.put("Trusted", nbttaglist); ++ compound.putBoolean("Sleeping", this.isSleeping()); ++ compound.putString("Type", this.getVariant().getSerializedName()); ++ compound.putBoolean("Sitting", this.isSitting()); ++ compound.putBoolean("Crouching", this.isCrouching()); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- ListTag listtag = compoundtag.getList("Trusted", 11); +- Iterator iterator = listtag.iterator(); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ ListTag nbttaglist = compound.getList("Trusted", 11); ++ Iterator iterator = nbttaglist.iterator(); + + while (iterator.hasNext()) { +- Tag tag = (Tag) iterator.next(); ++ Tag nbtbase = (Tag) iterator.next(); + +- this.addTrustedUUID(NbtUtils.loadUUID(tag)); ++ this.addTrustedUUID(NbtUtils.loadUUID(nbtbase)); + } + +- this.setSleeping(compoundtag.getBoolean("Sleeping")); +- this.setVariant(Fox.Type.byName(compoundtag.getString("Type"))); +- this.setSitting(compoundtag.getBoolean("Sitting")); +- this.setIsCrouching(compoundtag.getBoolean("Crouching")); ++ this.setSleeping(compound.getBoolean("Sleeping")); ++ this.setVariant(Fox.Type.byName(compound.getString("Type"))); ++ this.setSitting(compound.getBoolean("Sitting")); ++ this.setIsCrouching(compound.getBoolean("Crouching")); + if (this.level() instanceof ServerLevel) { + this.setTargetGoals(); + } +@@ -460,89 +445,86 @@ + return this.getFlag(1); + } + +- public void setSitting(boolean flag) { +- this.setFlag(1, flag); ++ public void setSitting(boolean sitting) { ++ this.setFlag(1, sitting); + } + + public boolean isFaceplanted() { + return this.getFlag(64); + } + +- void setFaceplanted(boolean flag) { +- this.setFlag(64, flag); ++ void setFaceplanted(boolean faceplanted) { ++ this.setFlag(64, faceplanted); + } + + boolean isDefending() { + return this.getFlag(128); + } + +- void setDefending(boolean flag) { +- this.setFlag(128, flag); ++ void setDefending(boolean defending) { ++ this.setFlag(128, defending); + } + + @Override +- @Override + public boolean isSleeping() { + return this.getFlag(32); + } + +- void setSleeping(boolean flag) { +- this.setFlag(32, flag); ++ public void setSleeping(boolean sleeping) { ++ this.setFlag(32, sleeping); + } + +- private void setFlag(int i, boolean flag) { +- if (flag) { +- this.entityData.set(Fox.DATA_FLAGS_ID, (byte) ((Byte) this.entityData.get(Fox.DATA_FLAGS_ID) | i)); ++ private void setFlag(int flagId, boolean value) { ++ if (value) { ++ this.entityData.set(Fox.DATA_FLAGS_ID, (byte) ((Byte) this.entityData.get(Fox.DATA_FLAGS_ID) | flagId)); + } else { +- this.entityData.set(Fox.DATA_FLAGS_ID, (byte) ((Byte) this.entityData.get(Fox.DATA_FLAGS_ID) & ~i)); ++ this.entityData.set(Fox.DATA_FLAGS_ID, (byte) ((Byte) this.entityData.get(Fox.DATA_FLAGS_ID) & ~flagId)); + } + + } + +- private boolean getFlag(int i) { +- return ((Byte) this.entityData.get(Fox.DATA_FLAGS_ID) & i) != 0; ++ private boolean getFlag(int flagId) { ++ return ((Byte) this.entityData.get(Fox.DATA_FLAGS_ID) & flagId) != 0; + } + + @Override +- @Override + public boolean canTakeItem(ItemStack itemstack) { +- EquipmentSlot equipmentslot = Mob.getEquipmentSlotForItem(itemstack); ++ EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(itemstack); + +- return !this.getItemBySlot(equipmentslot).isEmpty() ? false : equipmentslot == EquipmentSlot.MAINHAND && super.canTakeItem(itemstack); ++ return !this.getItemBySlot(enumitemslot).isEmpty() ? false : enumitemslot == EquipmentSlot.MAINHAND && super.canTakeItem(itemstack); + } + + @Override +- @Override +- public boolean canHoldItem(ItemStack itemstack) { +- Item item = itemstack.getItem(); ++ public boolean canHoldItem(ItemStack stack) { ++ Item item = stack.getItem(); + ItemStack itemstack1 = this.getItemBySlot(EquipmentSlot.MAINHAND); + + return itemstack1.isEmpty() || this.ticksSinceEaten > 0 && item.isEdible() && !itemstack1.getItem().isEdible(); + } + +- private void spitOutItem(ItemStack itemstack) { +- if (!itemstack.isEmpty() && !this.level().isClientSide) { +- ItemEntity itementity = new ItemEntity(this.level(), this.getX() + this.getLookAngle().x, this.getY() + 1.0D, this.getZ() + this.getLookAngle().z, itemstack); ++ private void spitOutItem(ItemStack stack) { ++ if (!stack.isEmpty() && !this.level().isClientSide) { ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX() + this.getLookAngle().x, this.getY() + 1.0D, this.getZ() + this.getLookAngle().z, stack); + +- itementity.setPickUpDelay(40); +- itementity.setThrower(this); ++ entityitem.setPickUpDelay(40); ++ entityitem.setThrower(this); + this.playSound(SoundEvents.FOX_SPIT, 1.0F, 1.0F); +- this.level().addFreshEntity(itementity); ++ this.level().addFreshEntity(entityitem); + } + } + +- private void dropItemStack(ItemStack itemstack) { +- ItemEntity itementity = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), itemstack); ++ private void dropItemStack(ItemStack stack) { ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), stack); + +- this.level().addFreshEntity(itementity); ++ this.level().addFreshEntity(entityitem); + } + + @Override +- @Override +- protected void pickUpItem(ItemEntity itementity) { +- ItemStack itemstack = itementity.getItem(); ++ protected void pickUpItem(ItemEntity itemEntity) { ++ ItemStack itemstack = itemEntity.getItem(); + +- if (this.canHoldItem(itemstack)) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, itemEntity, itemstack.getCount() - 1, !this.canHoldItem(itemstack)).isCancelled()) { // CraftBukkit - call EntityPickupItemEvent ++ itemstack = itemEntity.getItem(); // CraftBukkit - update ItemStack from event + int i = itemstack.getCount(); + + if (i > 1) { +@@ -550,18 +532,17 @@ + } + + this.spitOutItem(this.getItemBySlot(EquipmentSlot.MAINHAND)); +- this.onItemPickup(itementity); ++ this.onItemPickup(itemEntity); + this.setItemSlot(EquipmentSlot.MAINHAND, itemstack.split(1)); + this.setGuaranteedDrop(EquipmentSlot.MAINHAND); +- this.take(itementity, itemstack.getCount()); +- itementity.discard(); ++ this.take(itemEntity, itemstack.getCount()); ++ itemEntity.discard(); + this.ticksSinceEaten = 0; + } + + } + + @Override +- @Override + public void tick() { + super.tick(); + if (this.isEffectiveAi()) { +@@ -576,10 +557,10 @@ + } + + if (this.isFaceplanted() && this.level().random.nextFloat() < 0.2F) { +- BlockPos blockpos = this.blockPosition(); +- BlockState blockstate = this.level().getBlockState(blockpos); ++ BlockPos blockposition = this.blockPosition(); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); + +- this.level().levelEvent(2001, blockpos, Block.getId(blockstate)); ++ this.level().levelEvent(2001, blockposition, Block.getId(iblockdata)); + } + } + +@@ -603,23 +584,21 @@ + } + + @Override +- @Override +- public boolean isFood(ItemStack itemstack) { +- return itemstack.is(ItemTags.FOX_FOOD); ++ public boolean isFood(ItemStack stack) { ++ return stack.is(ItemTags.FOX_FOOD); + } + + @Override +- @Override +- protected void onOffspringSpawnedFromEgg(Player player, Mob mob) { +- ((Fox) mob).addTrustedUUID(player.getUUID()); ++ protected void onOffspringSpawnedFromEgg(Player player, Mob child) { ++ ((Fox) child).addTrustedUUID(player.getUUID()); + } + + public boolean isPouncing() { + return this.getFlag(16); + } + +- public void setIsPouncing(boolean flag) { +- this.setFlag(16, flag); ++ public void setIsPouncing(boolean isPouncing) { ++ this.setFlag(16, isPouncing); + } + + public boolean isJumping() { +@@ -630,46 +609,43 @@ + return this.crouchAmount == 3.0F; + } + +- public void setIsCrouching(boolean flag) { +- this.setFlag(4, flag); ++ public void setIsCrouching(boolean isCrouching) { ++ this.setFlag(4, isCrouching); + } + + @Override +- @Override + public boolean isCrouching() { + return this.getFlag(4); + } + +- public void setIsInterested(boolean flag) { +- this.setFlag(8, flag); ++ public void setIsInterested(boolean isInterested) { ++ this.setFlag(8, isInterested); + } + + public boolean isInterested() { + return this.getFlag(8); + } + +- public float getHeadRollAngle(float f) { +- return Mth.lerp(f, this.interestedAngleO, this.interestedAngle) * 0.11F * 3.1415927F; ++ public float getHeadRollAngle(float partialTick) { ++ return Mth.lerp(partialTick, this.interestedAngleO, this.interestedAngle) * 0.11F * 3.1415927F; + } + +- public float getCrouchAmount(float f) { +- return Mth.lerp(f, this.crouchAmountO, this.crouchAmount); ++ public float getCrouchAmount(float partialTick) { ++ return Mth.lerp(partialTick, this.crouchAmountO, this.crouchAmount); + } + + @Override +- @Override +- public void setTarget(@Nullable LivingEntity livingentity) { +- if (this.isDefending() && livingentity == null) { ++ public void setTarget(@Nullable LivingEntity livingEntity) { ++ if (this.isDefending() && livingEntity == null) { + this.setDefending(false); + } + +- super.setTarget(livingentity); ++ super.setTarget(livingEntity); + } + + @Override +- @Override +- protected int calculateFallDamage(float f, float f1) { +- return Mth.ceil((f - 5.0F) * f1); ++ protected int calculateFallDamage(float distance, float damageMultiplier) { ++ return Mth.ceil((distance - 5.0F) * damageMultiplier); + } + + void wakeUp() { +@@ -690,12 +666,11 @@ + } + + @Override +- @Override + public void playAmbientSound() { +- SoundEvent soundevent = this.getAmbientSound(); ++ SoundEvent soundeffect = this.getAmbientSound(); + +- if (soundevent == SoundEvents.FOX_SCREECH) { +- this.playSound(soundevent, 2.0F, this.getVoicePitch()); ++ if (soundeffect == SoundEvents.FOX_SCREECH) { ++ this.playSound(soundeffect, 2.0F, this.getVoicePitch()); + } else { + super.playAmbientSound(); + } +@@ -704,7 +679,6 @@ + + @Nullable + @Override +- @Override + protected SoundEvent getAmbientSound() { + if (this.isSleeping()) { + return SoundEvents.FOX_SLEEP; +@@ -723,14 +697,12 @@ + + @Nullable + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.FOX_HURT; + } + + @Nullable + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.FOX_DEATH; + } +@@ -740,8 +712,7 @@ + } + + @Override +- @Override +- protected void dropAllDeathLoot(DamageSource damagesource) { ++ protected void dropAllDeathLoot(DamageSource damageSource) { + ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND); + + if (!itemstack.isEmpty()) { +@@ -749,18 +720,17 @@ + this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); + } + +- super.dropAllDeathLoot(damagesource); ++ super.dropAllDeathLoot(damageSource); + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height + -0.0625F * f, -0.25F * f); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + -0.0625F * f, -0.25F * f); + } + +- public static boolean isPathClear(Fox fox, LivingEntity livingentity) { +- double d0 = livingentity.getZ() - fox.getZ(); +- double d1 = livingentity.getX() - fox.getX(); ++ public static boolean isPathClear(Fox fox, LivingEntity livingEntity) { ++ double d0 = livingEntity.getZ() - fox.getZ(); ++ double d1 = livingEntity.getX() - fox.getX(); + double d2 = d0 / d1; + boolean flag = true; + +@@ -779,7 +749,6 @@ + } + + @Override +- @Override + public Vec3 getLeashOffset() { + return new Vec3(0.0D, (double) (0.55F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); + } +@@ -791,7 +760,6 @@ + } + + @Override +- @Override + public void tick() { + if (!Fox.this.isSleeping()) { + super.tick(); +@@ -800,20 +768,18 @@ + } + + @Override +- @Override + protected boolean resetXRotOnTick() { + return !Fox.this.isPouncing() && !Fox.this.isCrouching() && !Fox.this.isInterested() && !Fox.this.isFaceplanted(); + } + } + +- private class FoxMoveControl extends MoveControl { ++ private class m extends MoveControl { + +- public FoxMoveControl() { ++ public m() { + super(Fox.this); + } + + @Override +- @Override + public void tick() { + if (Fox.this.canMove()) { + super.tick(); +@@ -829,14 +795,12 @@ + } + + @Override +- @Override + public void start() { + super.start(); + Fox.this.clearStates(); + } + + @Override +- @Override + public boolean canUse() { + return Fox.this.isInWater() && Fox.this.getFluidHeight(FluidTags.WATER) > 0.25D || Fox.this.isInLava(); + } +@@ -847,35 +811,30 @@ + int countdown; + + public FaceplantGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.LOOK, Goal.Flag.JUMP, Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.LOOK, Goal.Type.JUMP, Goal.Type.MOVE)); + } + + @Override +- @Override + public boolean canUse() { + return Fox.this.isFaceplanted(); + } + + @Override +- @Override + public boolean canContinueToUse() { + return this.canUse() && this.countdown > 0; + } + + @Override +- @Override + public void start() { + this.countdown = this.adjustedTickDelay(40); + } + + @Override +- @Override + public void stop() { + Fox.this.setFaceplanted(false); + } + + @Override +- @Override + public void tick() { + --this.countdown; + } +@@ -888,7 +847,6 @@ + } + + @Override +- @Override + public boolean shouldPanic() { + return !Fox.this.isDefending() && super.shouldPanic(); + } +@@ -901,7 +859,6 @@ + } + + @Override +- @Override + public void start() { + ((Fox) this.animal).clearStates(); + ((Fox) this.partner).clearStates(); +@@ -909,41 +866,52 @@ + } + + @Override +- @Override + protected void breed() { +- ServerLevel serverlevel = (ServerLevel) this.level; +- Fox fox = (Fox) this.animal.getBreedOffspring(serverlevel, this.partner); ++ ServerLevel worldserver = (ServerLevel) this.level; ++ Fox entityfox = (Fox) this.animal.getBreedOffspring(worldserver, this.partner); + +- if (fox != null) { +- ServerPlayer serverplayer = this.animal.getLoveCause(); +- ServerPlayer serverplayer1 = this.partner.getLoveCause(); +- ServerPlayer serverplayer2 = serverplayer; ++ if (entityfox != null) { ++ ServerPlayer entityplayer = this.animal.getLoveCause(); ++ ServerPlayer entityplayer1 = this.partner.getLoveCause(); ++ ServerPlayer entityplayer2 = entityplayer; + +- if (serverplayer != null) { +- fox.addTrustedUUID(serverplayer.getUUID()); ++ if (entityplayer != null) { ++ entityfox.addTrustedUUID(entityplayer.getUUID()); + } else { +- serverplayer2 = serverplayer1; ++ entityplayer2 = entityplayer1; + } + +- if (serverplayer1 != null && serverplayer != serverplayer1) { +- fox.addTrustedUUID(serverplayer1.getUUID()); ++ if (entityplayer1 != null && entityplayer != entityplayer1) { ++ entityfox.addTrustedUUID(entityplayer1.getUUID()); + } ++ // CraftBukkit start - call EntityBreedEvent ++ entityfox.setAge(-24000); ++ entityfox.moveTo(this.animal.getX(), this.animal.getY(), this.animal.getZ(), 0.0F, 0.0F); ++ int experience = this.animal.getRandom().nextInt(7) + 1; ++ org.bukkit.event.entity.EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(entityfox, animal, partner, entityplayer, this.animal.breedItem, experience); ++ if (entityBreedEvent.isCancelled()) { ++ return; ++ } ++ experience = entityBreedEvent.getExperience(); ++ // CraftBukkit end + +- if (serverplayer2 != null) { +- serverplayer2.awardStat(Stats.ANIMALS_BRED); +- CriteriaTriggers.BRED_ANIMALS.trigger(serverplayer2, this.animal, this.partner, fox); ++ if (entityplayer2 != null) { ++ entityplayer2.awardStat(Stats.ANIMALS_BRED); ++ CriteriaTriggers.BRED_ANIMALS.trigger(entityplayer2, this.animal, this.partner, entityfox); + } + + this.animal.setAge(6000); + this.partner.setAge(6000); + this.animal.resetLove(); + this.partner.resetLove(); +- fox.setAge(-24000); +- fox.moveTo(this.animal.getX(), this.animal.getY(), this.animal.getZ(), 0.0F, 0.0F); +- serverlevel.addFreshEntityWithPassengers(fox); ++ worldserver.addFreshEntityWithPassengers(entityfox, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - added SpawnReason + this.level.broadcastEntityEvent(this.animal, (byte) 18); + if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), this.animal.getRandom().nextInt(7) + 1)); ++ // CraftBukkit start - use event experience ++ if (experience > 0) { ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience)); ++ } ++ // CraftBukkit end + } + + } +@@ -953,38 +921,35 @@ + private class StalkPreyGoal extends Goal { + + public StalkPreyGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + } + + @Override +- @Override + public boolean canUse() { + if (Fox.this.isSleeping()) { + return false; + } else { +- LivingEntity livingentity = Fox.this.getTarget(); ++ LivingEntity entityliving = Fox.this.getTarget(); + +- return livingentity != null && livingentity.isAlive() && Fox.STALKABLE_PREY.test(livingentity) && Fox.this.distanceToSqr((Entity) livingentity) > 36.0D && !Fox.this.isCrouching() && !Fox.this.isInterested() && !Fox.this.jumping; ++ return entityliving != null && entityliving.isAlive() && Fox.STALKABLE_PREY.test(entityliving) && Fox.this.distanceToSqr((Entity) entityliving) > 36.0D && !Fox.this.isCrouching() && !Fox.this.isInterested() && !Fox.this.jumping; + } + } + + @Override +- @Override + public void start() { + Fox.this.setSitting(false); + Fox.this.setFaceplanted(false); + } + + @Override +- @Override + public void stop() { +- LivingEntity livingentity = Fox.this.getTarget(); ++ LivingEntity entityliving = Fox.this.getTarget(); + +- if (livingentity != null && Fox.isPathClear(Fox.this, livingentity)) { ++ if (entityliving != null && Fox.isPathClear(Fox.this, entityliving)) { + Fox.this.setIsInterested(true); + Fox.this.setIsCrouching(true); + Fox.this.getNavigation().stop(); +- Fox.this.getLookControl().setLookAt(livingentity, (float) Fox.this.getMaxHeadYRot(), (float) Fox.this.getMaxHeadXRot()); ++ Fox.this.getLookControl().setLookAt(entityliving, (float) Fox.this.getMaxHeadYRot(), (float) Fox.this.getMaxHeadXRot()); + } else { + Fox.this.setIsInterested(false); + Fox.this.setIsCrouching(false); +@@ -993,44 +958,42 @@ + } + + @Override +- @Override + public void tick() { +- LivingEntity livingentity = Fox.this.getTarget(); ++ LivingEntity entityliving = Fox.this.getTarget(); + +- if (livingentity != null) { +- Fox.this.getLookControl().setLookAt(livingentity, (float) Fox.this.getMaxHeadYRot(), (float) Fox.this.getMaxHeadXRot()); +- if (Fox.this.distanceToSqr((Entity) livingentity) <= 36.0D) { ++ if (entityliving != null) { ++ Fox.this.getLookControl().setLookAt(entityliving, (float) Fox.this.getMaxHeadYRot(), (float) Fox.this.getMaxHeadXRot()); ++ if (Fox.this.distanceToSqr((Entity) entityliving) <= 36.0D) { + Fox.this.setIsInterested(true); + Fox.this.setIsCrouching(true); + Fox.this.getNavigation().stop(); + } else { +- Fox.this.getNavigation().moveTo((Entity) livingentity, 1.5D); ++ Fox.this.getNavigation().moveTo((Entity) entityliving, 1.5D); + } + + } + } + } + +- public class FoxPounceGoal extends JumpGoal { ++ public class FoxPounceGoal extends PathfinderGoalWaterJumpAbstract { + + public FoxPounceGoal() {} + + @Override +- @Override + public boolean canUse() { + if (!Fox.this.isFullyCrouched()) { + return false; + } else { +- LivingEntity livingentity = Fox.this.getTarget(); ++ LivingEntity entityliving = Fox.this.getTarget(); + +- if (livingentity != null && livingentity.isAlive()) { +- if (livingentity.getMotionDirection() != livingentity.getDirection()) { ++ if (entityliving != null && entityliving.isAlive()) { ++ if (entityliving.getMotionDirection() != entityliving.getDirection()) { + return false; + } else { +- boolean flag = Fox.isPathClear(Fox.this, livingentity); ++ boolean flag = Fox.isPathClear(Fox.this, entityliving); + + if (!flag) { +- Fox.this.getNavigation().createPath((Entity) livingentity, 0); ++ Fox.this.getNavigation().createPath((Entity) entityliving, 0); + Fox.this.setIsCrouching(false); + Fox.this.setIsInterested(false); + } +@@ -1044,11 +1007,10 @@ + } + + @Override +- @Override + public boolean canContinueToUse() { +- LivingEntity livingentity = Fox.this.getTarget(); ++ LivingEntity entityliving = Fox.this.getTarget(); + +- if (livingentity != null && livingentity.isAlive()) { ++ if (entityliving != null && entityliving.isAlive()) { + double d0 = Fox.this.getDeltaMovement().y; + + return (d0 * d0 >= 0.05000000074505806D || Math.abs(Fox.this.getXRot()) >= 15.0F || !Fox.this.onGround()) && !Fox.this.isFaceplanted(); +@@ -1058,31 +1020,28 @@ + } + + @Override +- @Override + public boolean isInterruptable() { + return false; + } + + @Override +- @Override + public void start() { + Fox.this.setJumping(true); + Fox.this.setIsPouncing(true); + Fox.this.setIsInterested(false); +- LivingEntity livingentity = Fox.this.getTarget(); ++ LivingEntity entityliving = Fox.this.getTarget(); + +- if (livingentity != null) { +- Fox.this.getLookControl().setLookAt(livingentity, 60.0F, 30.0F); +- Vec3 vec3 = (new Vec3(livingentity.getX() - Fox.this.getX(), livingentity.getY() - Fox.this.getY(), livingentity.getZ() - Fox.this.getZ())).normalize(); ++ if (entityliving != null) { ++ Fox.this.getLookControl().setLookAt(entityliving, 60.0F, 30.0F); ++ Vec3 vec3d = (new Vec3(entityliving.getX() - Fox.this.getX(), entityliving.getY() - Fox.this.getY(), entityliving.getZ() - Fox.this.getZ())).normalize(); + +- Fox.this.setDeltaMovement(Fox.this.getDeltaMovement().add(vec3.x * 0.8D, 0.9D, vec3.z * 0.8D)); ++ Fox.this.setDeltaMovement(Fox.this.getDeltaMovement().add(vec3d.x * 0.8D, 0.9D, vec3d.z * 0.8D)); + } + + Fox.this.getNavigation().stop(); + } + + @Override +- @Override + public void stop() { + Fox.this.setIsCrouching(false); + Fox.this.crouchAmount = 0.0F; +@@ -1092,29 +1051,28 @@ + } + + @Override +- @Override + public void tick() { +- LivingEntity livingentity = Fox.this.getTarget(); ++ LivingEntity entityliving = Fox.this.getTarget(); + +- if (livingentity != null) { +- Fox.this.getLookControl().setLookAt(livingentity, 60.0F, 30.0F); ++ if (entityliving != null) { ++ Fox.this.getLookControl().setLookAt(entityliving, 60.0F, 30.0F); + } + + if (!Fox.this.isFaceplanted()) { +- Vec3 vec3 = Fox.this.getDeltaMovement(); ++ Vec3 vec3d = Fox.this.getDeltaMovement(); + +- if (vec3.y * vec3.y < 0.029999999329447746D && Fox.this.getXRot() != 0.0F) { ++ if (vec3d.y * vec3d.y < 0.029999999329447746D && Fox.this.getXRot() != 0.0F) { + Fox.this.setXRot(Mth.rotLerp(0.2F, Fox.this.getXRot(), 0.0F)); + } else { +- double d0 = vec3.horizontalDistance(); +- double d1 = Math.signum(-vec3.y) * Math.acos(d0 / vec3.length()) * 57.2957763671875D; ++ double d0 = vec3d.horizontalDistance(); ++ double d1 = Math.signum(-vec3d.y) * Math.acos(d0 / vec3d.length()) * 57.2957763671875D; + + Fox.this.setXRot((float) d1); + } + } + +- if (livingentity != null && Fox.this.distanceTo(livingentity) <= 2.0F) { +- Fox.this.doHurtTarget(livingentity); ++ if (entityliving != null && Fox.this.distanceTo(entityliving) <= 2.0F) { ++ Fox.this.doHurtTarget(entityliving); + } else if (Fox.this.getXRot() > 0.0F && Fox.this.onGround() && (float) Fox.this.getDeltaMovement().y != 0.0F && Fox.this.level().getBlockState(Fox.this.blockPosition()).is(Blocks.SNOW)) { + Fox.this.setXRot(60.0F); + Fox.this.setTarget((LivingEntity) null); +@@ -1133,7 +1091,6 @@ + } + + @Override +- @Override + public boolean canUse() { + if (!Fox.this.isSleeping() && this.mob.getTarget() == null) { + if (Fox.this.level().isThundering() && Fox.this.level().canSeeSky(this.mob.blockPosition())) { +@@ -1143,9 +1100,9 @@ + return false; + } else { + this.interval = 100; +- BlockPos blockpos = this.mob.blockPosition(); ++ BlockPos blockposition = this.mob.blockPosition(); + +- return Fox.this.level().isDay() && Fox.this.level().canSeeSky(blockpos) && !((ServerLevel) Fox.this.level()).isVillage(blockpos) && this.setWantedPos(); ++ return Fox.this.level().isDay() && Fox.this.level().canSeeSky(blockposition) && !((ServerLevel) Fox.this.level()).isVillage(blockposition) && this.setWantedPos(); + } + } else { + return false; +@@ -1153,7 +1110,6 @@ + } + + @Override +- @Override + public void start() { + Fox.this.clearStates(); + super.start(); +@@ -1167,31 +1123,28 @@ + } + + @Override +- @Override +- protected void checkAndPerformAttack(LivingEntity livingentity) { +- if (this.canPerformAttack(livingentity)) { ++ protected void checkAndPerformAttack(LivingEntity entityliving) { ++ if (this.canPerformAttack(entityliving)) { + this.resetAttackCooldown(); +- this.mob.doHurtTarget(livingentity); ++ this.mob.doHurtTarget(entityliving); + Fox.this.playSound(SoundEvents.FOX_BITE, 1.0F, 1.0F); + } + + } + + @Override +- @Override + public void start() { + Fox.this.setIsInterested(false); + super.start(); + } + + @Override +- @Override + public boolean canUse() { + return !Fox.this.isSitting() && !Fox.this.isSleeping() && !Fox.this.isCrouching() && !Fox.this.isFaceplanted() && super.canUse(); + } + } + +- private class SleepGoal extends Fox.FoxBehaviorGoal { ++ private class SleepGoal extends Fox.d { + + private static final int WAIT_TIME_BEFORE_SLEEP = reducedTickDelay(140); + private int countdown; +@@ -1199,17 +1152,15 @@ + public SleepGoal() { + super(); + this.countdown = Fox.this.random.nextInt(Fox.SleepGoal.WAIT_TIME_BEFORE_SLEEP); +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK, Goal.Flag.JUMP)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK, Goal.Type.JUMP)); + } + + @Override +- @Override + public boolean canUse() { + return Fox.this.xxa == 0.0F && Fox.this.yya == 0.0F && Fox.this.zza == 0.0F ? this.canSleep() || Fox.this.isSleeping() : false; + } + + @Override +- @Override + public boolean canContinueToUse() { + return this.canSleep(); + } +@@ -1224,14 +1175,12 @@ + } + + @Override +- @Override + public void stop() { + this.countdown = Fox.this.random.nextInt(Fox.SleepGoal.WAIT_TIME_BEFORE_SLEEP); + Fox.this.clearStates(); + } + + @Override +- @Override + public void start() { + Fox.this.setSitting(false); + Fox.this.setIsCrouching(false); +@@ -1247,25 +1196,22 @@ + + private final Fox fox; + +- public FoxFollowParentGoal(Fox fox, double d0) { +- super(fox, d0); +- this.fox = fox; ++ public FoxFollowParentGoal(Fox entityfox, double d0) { ++ super(entityfox, d0); ++ this.fox = entityfox; + } + + @Override +- @Override + public boolean canUse() { + return !this.fox.isDefending() && super.canUse(); + } + + @Override +- @Override + public boolean canContinueToUse() { + return !this.fox.isDefending() && super.canContinueToUse(); + } + + @Override +- @Override + public void start() { + this.fox.clearStates(); + super.start(); +@@ -1279,20 +1225,17 @@ + } + + @Override +- @Override + public void start() { + Fox.this.clearStates(); + super.start(); + } + + @Override +- @Override + public boolean canUse() { + return super.canUse() && this.canFoxMove(); + } + + @Override +- @Override + public boolean canContinueToUse() { + return super.canContinueToUse() && this.canFoxMove(); + } +@@ -1312,27 +1255,23 @@ + } + + @Override +- @Override + public double acceptedDistance() { + return 2.0D; + } + + @Override +- @Override + public boolean shouldRecalculatePath() { + return this.tryTicks % 100 == 0; + } + + @Override +- @Override +- protected boolean isValidTarget(LevelReader levelreader, BlockPos blockpos) { +- BlockState blockstate = levelreader.getBlockState(blockpos); ++ protected boolean isValidTarget(LevelReader level, BlockPos pos) { ++ IBlockData iblockdata = level.getBlockState(pos); + +- return blockstate.is(Blocks.SWEET_BERRY_BUSH) && (Integer) blockstate.getValue(SweetBerryBushBlock.AGE) >= 2 || CaveVines.hasGlowBerries(blockstate); ++ return iblockdata.is(Blocks.SWEET_BERRY_BUSH) && (Integer) iblockdata.getValue(SweetBerryBushBlock.AGE) >= 2 || CaveVines.hasGlowBerries(iblockdata); + } + + @Override +- @Override + public void tick() { + if (this.isReachedTarget()) { + if (this.ticksWaited >= 40) { +@@ -1349,25 +1288,30 @@ + + protected void onReachedTarget() { + if (Fox.this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- BlockState blockstate = Fox.this.level().getBlockState(this.blockPos); ++ IBlockData iblockdata = Fox.this.level().getBlockState(this.blockPos); + +- if (blockstate.is(Blocks.SWEET_BERRY_BUSH)) { +- this.pickSweetBerries(blockstate); +- } else if (CaveVines.hasGlowBerries(blockstate)) { +- this.pickGlowBerry(blockstate); ++ if (iblockdata.is(Blocks.SWEET_BERRY_BUSH)) { ++ this.pickSweetBerries(iblockdata); ++ } else if (CaveVines.hasGlowBerries(iblockdata)) { ++ this.pickGlowBerry(iblockdata); + } + + } + } + +- private void pickGlowBerry(BlockState blockstate) { +- CaveVines.use(Fox.this, blockstate, Fox.this.level(), this.blockPos); ++ private void pickGlowBerry(IBlockData state) { ++ CaveVines.use(Fox.this, state, Fox.this.level(), this.blockPos); + } + +- private void pickSweetBerries(BlockState blockstate) { +- int i = (Integer) blockstate.getValue(SweetBerryBushBlock.AGE); ++ private void pickSweetBerries(IBlockData state) { ++ int i = (Integer) state.getValue(SweetBerryBushBlock.AGE); + +- blockstate.setValue(SweetBerryBushBlock.AGE, 1); ++ state.setValue(SweetBerryBushBlock.AGE, 1); ++ // CraftBukkit start - call EntityChangeBlockEvent ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(Fox.this, this.blockPos, state.setValue(SweetBerryBushBlock.AGE, 1))) { ++ return; ++ } ++ // CraftBukkit end + int j = 1 + Fox.this.level().random.nextInt(2) + (i == 3 ? 1 : 0); + ItemStack itemstack = Fox.this.getItemBySlot(EquipmentSlot.MAINHAND); + +@@ -1381,18 +1325,16 @@ + } + + Fox.this.playSound(SoundEvents.SWEET_BERRY_BUSH_PICK_BERRIES, 1.0F, 1.0F); +- Fox.this.level().setBlock(this.blockPos, (BlockState) blockstate.setValue(SweetBerryBushBlock.AGE, 1), 2); ++ Fox.this.level().setBlock(this.blockPos, (IBlockData) state.setValue(SweetBerryBushBlock.AGE, 1), 2); + Fox.this.level().gameEvent(GameEvent.BLOCK_CHANGE, this.blockPos, GameEvent.Context.of((Entity) Fox.this)); + } + + @Override +- @Override + public boolean canUse() { + return !Fox.this.isSleeping() && super.canUse(); + } + + @Override +- @Override + public void start() { + this.ticksWaited = 0; + Fox.this.setSitting(false); +@@ -1403,11 +1345,10 @@ + private class FoxSearchForItemsGoal extends Goal { + + public FoxSearchForItemsGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +- @Override + public boolean canUse() { + if (!Fox.this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty()) { + return false; +@@ -1427,7 +1368,6 @@ + } + + @Override +- @Override + public void tick() { + List list = Fox.this.level().getEntitiesOfClass(ItemEntity.class, Fox.this.getBoundingBox().inflate(8.0D, 8.0D, 8.0D), Fox.ALLOWED_ITEMS); + ItemStack itemstack = Fox.this.getItemBySlot(EquipmentSlot.MAINHAND); +@@ -1439,7 +1379,6 @@ + } + + @Override +- @Override + public void start() { + List list = Fox.this.level().getEntitiesOfClass(ItemEntity.class, Fox.this.getBoundingBox().inflate(8.0D, 8.0D, 8.0D), Fox.ALLOWED_ITEMS); + +@@ -1452,24 +1391,22 @@ + + private class FoxLookAtPlayerGoal extends LookAtPlayerGoal { + +- public FoxLookAtPlayerGoal(Mob mob, Class oclass, float f) { +- super(mob, oclass, f); ++ public FoxLookAtPlayerGoal(Mob mob, Class lookAtType, float lookDistance) { ++ super(mob, lookAtType, lookDistance); + } + + @Override +- @Override + public boolean canUse() { + return super.canUse() && !Fox.this.isFaceplanted() && !Fox.this.isInterested(); + } + + @Override +- @Override + public boolean canContinueToUse() { + return super.canContinueToUse() && !Fox.this.isFaceplanted() && !Fox.this.isInterested(); + } + } + +- private class PerchAndSearchGoal extends Fox.FoxBehaviorGoal { ++ private class PerchAndSearchGoal extends Fox.d { + + private double relX; + private double relZ; +@@ -1478,23 +1415,20 @@ + + public PerchAndSearchGoal() { + super(); +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + } + + @Override +- @Override + public boolean canUse() { + return Fox.this.getLastHurtByMob() == null && Fox.this.getRandom().nextFloat() < 0.02F && !Fox.this.isSleeping() && Fox.this.getTarget() == null && Fox.this.getNavigation().isDone() && !this.alertable() && !Fox.this.isPouncing() && !Fox.this.isCrouching(); + } + + @Override +- @Override + public boolean canContinueToUse() { + return this.looksRemaining > 0; + } + + @Override +- @Override + public void start() { + this.resetLook(); + this.looksRemaining = 2 + Fox.this.getRandom().nextInt(3); +@@ -1503,13 +1437,11 @@ + } + + @Override +- @Override + public void stop() { + Fox.this.setSitting(false); + } + + @Override +- @Override + public void tick() { + --this.lookTime; + if (this.lookTime <= 0) { +@@ -1537,12 +1469,11 @@ + private LivingEntity trustedLastHurt; + private int timestamp; + +- public DefendTrustedTargetGoal(Class oclass, boolean flag, boolean flag1, @Nullable Predicate predicate) { ++ public DefendTrustedTargetGoal(Class oclass, boolean flag, boolean flag1, @Nullable Predicate predicate) { // CraftBukkit - decompile error + super(Fox.this, oclass, 10, flag, flag1, predicate); + } + + @Override +- @Override + public boolean canUse() { + if (this.randomInterval > 0 && this.mob.getRandom().nextInt(this.randomInterval) != 0) { + return false; +@@ -1556,11 +1487,11 @@ + Entity entity = ((ServerLevel) Fox.this.level()).getEntity(uuid); + + if (entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; ++ LivingEntity entityliving = (LivingEntity) entity; + +- this.trustedLastHurt = livingentity; +- this.trustedLastHurtBy = livingentity.getLastHurtByMob(); +- int i = livingentity.getLastHurtByMobTimestamp(); ++ this.trustedLastHurt = entityliving; ++ this.trustedLastHurtBy = entityliving.getLastHurtByMob(); ++ int i = entityliving.getLastHurtByMobTimestamp(); + + return i != this.timestamp && this.canAttack(this.trustedLastHurtBy, this.targetConditions); + } +@@ -1572,7 +1503,6 @@ + } + + @Override +- @Override + public void start() { + this.setTarget(this.trustedLastHurtBy); + this.target = this.trustedLastHurtBy; +@@ -1592,7 +1522,7 @@ + RED(0, "red"), SNOW(1, "snow"); + + public static final StringRepresentable.EnumCodec CODEC = StringRepresentable.fromEnum(Fox.Type::values); +- private static final IntFunction BY_ID = ByIdMap.continuous(Fox.Type::getId, values(), ByIdMap.OutOfBoundsStrategy.ZERO); ++ private static final IntFunction BY_ID = ByIdMap.continuous(Fox.Type::getId, values(), ByIdMap.a.ZERO); + private final int id; + private final String name; + +@@ -1602,7 +1532,6 @@ + } + + @Override +- @Override + public String getSerializedName() { + return this.name; + } +@@ -1611,16 +1540,16 @@ + return this.id; + } + +- public static Fox.Type byName(String s) { +- return (Fox.Type) Fox.Type.CODEC.byName(s, Fox.Type.RED); ++ public static Fox.Type byName(String name) { ++ return (Fox.Type) Fox.Type.CODEC.byName(name, Fox.Type.RED); + } + +- public static Fox.Type byId(int i) { +- return (Fox.Type) Fox.Type.BY_ID.apply(i); ++ public static Fox.Type byId(int index) { ++ return (Fox.Type) Fox.Type.BY_ID.apply(index); + } + +- public static Fox.Type byBiome(Holder holder) { +- return holder.is(BiomeTags.SPAWNS_SNOW_FOXES) ? Fox.Type.SNOW : Fox.Type.RED; ++ public static Fox.Type byBiome(Holder biome) { ++ return biome.is(BiomeTags.SPAWNS_SNOW_FOXES) ? Fox.Type.SNOW : Fox.Type.RED; + } + } + +@@ -1628,22 +1557,22 @@ + + public final Fox.Type type; + +- public FoxGroupData(Fox.Type fox_type) { ++ public FoxGroupData(Fox.Type type) { + super(false); +- this.type = fox_type; ++ this.type = type; + } + } + +- private abstract class FoxBehaviorGoal extends Goal { ++ private abstract class d extends Goal { + + private final TargetingConditions alertableTargeting = TargetingConditions.forCombat().range(12.0D).ignoreLineOfSight().selector(Fox.this.new FoxAlertableEntitiesSelector()); + +- FoxBehaviorGoal() {} ++ d() {} + + protected boolean hasShelter() { +- BlockPos blockpos = BlockPos.containing(Fox.this.getX(), Fox.this.getBoundingBox().maxY, Fox.this.getZ()); ++ BlockPos blockposition = BlockPos.containing(Fox.this.getX(), Fox.this.getBoundingBox().maxY, Fox.this.getZ()); + +- return !Fox.this.level().canSeeSky(blockpos) && Fox.this.getWalkTargetValue(blockpos) >= 0.0F; ++ return !Fox.this.level().canSeeSky(blockposition) && Fox.this.getWalkTargetValue(blockposition) >= 0.0F; + } + + protected boolean alertable() { +@@ -1655,9 +1584,8 @@ + + public FoxAlertableEntitiesSelector() {} + +- @Override +- public boolean test(LivingEntity livingentity) { +- return livingentity instanceof Fox ? false : (!(livingentity instanceof Chicken) && !(livingentity instanceof Rabbit) && !(livingentity instanceof Monster) ? (livingentity instanceof TamableAnimal ? !((TamableAnimal) livingentity).isTame() : (livingentity instanceof Player && (livingentity.isSpectator() || ((Player) livingentity).isCreative()) ? false : (Fox.this.trusts(livingentity.getUUID()) ? false : !livingentity.isSleeping() && !livingentity.isDiscrete()))) : true); ++ public boolean test(LivingEntity entity) { ++ return entity instanceof Fox ? false : (!(entity instanceof Chicken) && !(entity instanceof Rabbit) && !(entity instanceof Monster) ? (entity instanceof TamableAnimal ? !((TamableAnimal) entity).isTame() : (entity instanceof Player && (entity.isSpectator() || ((Player) entity).isCreative()) ? false : (Fox.this.trusts(entity.getUUID()) ? false : !entity.isSleeping() && !entity.isDiscrete()))) : true); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/IronGolem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/IronGolem.java.patch new file mode 100644 index 0000000000..04b4e7defe --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/IronGolem.java.patch @@ -0,0 +1,368 @@ +--- a/net/minecraft/world/entity/animal/IronGolem.java ++++ b/net/minecraft/world/entity/animal/IronGolem.java +@@ -17,7 +17,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.util.TimeUtil; + import net.minecraft.util.valueproviders.UniformInt; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; +@@ -39,14 +39,14 @@ + import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; + import net.minecraft.world.entity.ai.goal.target.ResetUniversalAngerTargetGoal; + import net.minecraft.world.entity.monster.Creeper; +-import net.minecraft.world.entity.monster.Enemy; ++import net.minecraft.world.entity.monster.IMonster; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.NaturalSpawner; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.Vec3; + +@@ -61,13 +61,12 @@ + @Nullable + private UUID persistentAngerTarget; + +- public IronGolem(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public IronGolem(EntityType entityType, Level level) { ++ super(entityType, level); + this.setMaxUpStep(1.0F); + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new MeleeAttackGoal(this, 1.0D, true)); + this.goalSelector.addGoal(2, new MoveTowardsTargetGoal(this, 0.9D, 32.0F)); +@@ -79,14 +78,13 @@ + this.targetSelector.addGoal(1, new DefendVillageTargetGoal(this)); + this.targetSelector.addGoal(2, new HurtByTargetGoal(this, new Class[0])); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt)); +- this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Mob.class, 5, false, false, (livingentity) -> { +- return livingentity instanceof Enemy && !(livingentity instanceof Creeper); ++ this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Mob.class, 5, false, false, (entityliving) -> { ++ return entityliving instanceof IMonster && !(entityliving instanceof Creeper); + })); + this.targetSelector.addGoal(4, new ResetUniversalAngerTargetGoal<>(this, false)); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(IronGolem.DATA_FLAGS_ID, (byte) 0); +@@ -97,23 +95,20 @@ + } + + @Override +- @Override +- protected int decreaseAirSupply(int i) { +- return i; ++ protected int decreaseAirSupply(int air) { ++ return air; + } + + @Override +- @Override + protected void doPush(Entity entity) { +- if (entity instanceof Enemy && !(entity instanceof Creeper) && this.getRandom().nextInt(20) == 0) { +- this.setTarget((LivingEntity) entity); ++ if (entity instanceof IMonster && !(entity instanceof Creeper) && this.getRandom().nextInt(20) == 0) { ++ this.setTarget((LivingEntity) entity, org.bukkit.event.entity.EntityTargetLivingEntityEvent.TargetReason.COLLISION, true); // CraftBukkit - set reason + } + + super.doPush(entity); + } + + @Override +- @Override + public void aiStep() { + super.aiStep(); + if (this.attackAnimationTick > 0) { +@@ -131,60 +126,51 @@ + } + + @Override +- @Override + public boolean canSpawnSprintParticle() { + return this.getDeltaMovement().horizontalDistanceSqr() > 2.500000277905201E-7D && this.random.nextInt(5) == 0; + } + + @Override +- @Override +- public boolean canAttackType(EntityType entitytype) { +- return this.isPlayerCreated() && entitytype == EntityType.PLAYER ? false : (entitytype == EntityType.CREEPER ? false : super.canAttackType(entitytype)); ++ public boolean canAttackType(EntityType type) { ++ return this.isPlayerCreated() && type == EntityType.PLAYER ? false : (type == EntityType.CREEPER ? false : super.canAttackType(type)); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putBoolean("PlayerCreated", this.isPlayerCreated()); +- this.addPersistentAngerSaveData(compoundtag); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putBoolean("PlayerCreated", this.isPlayerCreated()); ++ this.addPersistentAngerSaveData(compound); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setPlayerCreated(compoundtag.getBoolean("PlayerCreated")); +- this.readPersistentAngerSaveData(this.level(), compoundtag); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setPlayerCreated(compound.getBoolean("PlayerCreated")); ++ this.readPersistentAngerSaveData(this.level(), compound); + } + + @Override +- @Override + public void startPersistentAngerTimer() { + this.setRemainingPersistentAngerTime(IronGolem.PERSISTENT_ANGER_TIME.sample(this.random)); + } + + @Override +- @Override +- public void setRemainingPersistentAngerTime(int i) { +- this.remainingPersistentAngerTime = i; ++ public void setRemainingPersistentAngerTime(int time) { ++ this.remainingPersistentAngerTime = time; + } + + @Override +- @Override + public int getRemainingPersistentAngerTime() { + return this.remainingPersistentAngerTime; + } + + @Override +- @Override +- public void setPersistentAngerTarget(@Nullable UUID uuid) { +- this.persistentAngerTarget = uuid; ++ public void setPersistentAngerTarget(@Nullable UUID target) { ++ this.persistentAngerTarget = target; + } + + @Nullable + @Override +- @Override + public UUID getPersistentAngerTarget() { + return this.persistentAngerTarget; + } +@@ -194,7 +180,6 @@ + } + + @Override +- @Override + public boolean doHurtTarget(Entity entity) { + this.attackAnimationTick = 10; + this.level().broadcastEntityEvent(this, (byte) 4); +@@ -206,9 +191,9 @@ + double d0; + + if (entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; ++ LivingEntity entityliving = (LivingEntity) entity; + +- d0 = livingentity.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE); ++ d0 = entityliving.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE); + } else { + d0 = 0.0D; + } +@@ -225,12 +210,11 @@ + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- IronGolem.Crackiness irongolem_crackiness = this.getCrackiness(); +- boolean flag = super.hurt(damagesource, f); ++ public boolean hurt(DamageSource source, float amount) { ++ IronGolem.Crackiness entityirongolem_cracklevel = this.getCrackiness(); ++ boolean flag = super.hurt(source, amount); + +- if (flag && this.getCrackiness() != irongolem_crackiness) { ++ if (flag && this.getCrackiness() != entityirongolem_cracklevel) { + this.playSound(SoundEvents.IRON_GOLEM_DAMAGE, 1.0F, 1.0F); + } + +@@ -242,17 +226,16 @@ + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 4) { ++ public void handleEntityEvent(byte id) { ++ if (id == 4) { + this.attackAnimationTick = 10; + this.playSound(SoundEvents.IRON_GOLEM_ATTACK, 1.0F, 1.0F); +- } else if (b0 == 11) { ++ } else if (id == 11) { + this.offerFlowerTick = 400; +- } else if (b0 == 34) { ++ } else if (id == 34) { + this.offerFlowerTick = 0; + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } +@@ -261,8 +244,8 @@ + return this.attackAnimationTick; + } + +- public void offerFlower(boolean flag) { +- if (flag) { ++ public void offerFlower(boolean offeringFlower) { ++ if (offeringFlower) { + this.offerFlowerTick = 400; + this.level().broadcastEntityEvent(this, (byte) 11); + } else { +@@ -273,21 +256,18 @@ + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.IRON_GOLEM_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.IRON_GOLEM_DEATH; + } + + @Override +- @Override +- protected InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ protected InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (!itemstack.is(Items.IRON_INGOT)) { + return InteractionResult.PASS; +@@ -311,8 +291,7 @@ + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.IRON_GOLEM_STEP, 1.0F, 1.0F); + } + +@@ -324,10 +303,10 @@ + return ((Byte) this.entityData.get(IronGolem.DATA_FLAGS_ID) & 1) != 0; + } + +- public void setPlayerCreated(boolean flag) { ++ public void setPlayerCreated(boolean playerCreated) { + byte b0 = (Byte) this.entityData.get(IronGolem.DATA_FLAGS_ID); + +- if (flag) { ++ if (playerCreated) { + this.entityData.set(IronGolem.DATA_FLAGS_ID, (byte) (b0 | 1)); + } else { + this.entityData.set(IronGolem.DATA_FLAGS_ID, (byte) (b0 & -2)); +@@ -336,36 +315,33 @@ + } + + @Override +- @Override +- public void die(DamageSource damagesource) { +- super.die(damagesource); ++ public void die(DamageSource cause) { ++ super.die(cause); + } + + @Override +- @Override +- public boolean checkSpawnObstruction(LevelReader levelreader) { +- BlockPos blockpos = this.blockPosition(); +- BlockPos blockpos1 = blockpos.below(); +- BlockState blockstate = levelreader.getBlockState(blockpos1); ++ public boolean checkSpawnObstruction(LevelReader level) { ++ BlockPos blockposition = this.blockPosition(); ++ BlockPos blockposition1 = blockposition.below(); ++ IBlockData iblockdata = level.getBlockState(blockposition1); + +- if (!blockstate.entityCanStandOn(levelreader, blockpos1, this)) { ++ if (!iblockdata.entityCanStandOn(level, blockposition1, this)) { + return false; + } else { + for (int i = 1; i < 3; ++i) { +- BlockPos blockpos2 = blockpos.above(i); +- BlockState blockstate1 = levelreader.getBlockState(blockpos2); ++ BlockPos blockposition2 = blockposition.above(i); ++ IBlockData iblockdata1 = level.getBlockState(blockposition2); + +- if (!NaturalSpawner.isValidEmptySpawnBlock(levelreader, blockpos2, blockstate1, blockstate1.getFluidState(), EntityType.IRON_GOLEM)) { ++ if (!NaturalSpawner.isValidEmptySpawnBlock(level, blockposition2, iblockdata1, iblockdata1.getFluidState(), EntityType.IRON_GOLEM)) { + return false; + } + } + +- return NaturalSpawner.isValidEmptySpawnBlock(levelreader, blockpos, levelreader.getBlockState(blockpos), Fluids.EMPTY.defaultFluidState(), EntityType.IRON_GOLEM) && levelreader.isUnobstructed(this); ++ return NaturalSpawner.isValidEmptySpawnBlock(level, blockposition, level.getBlockState(blockposition), Fluids.EMPTY.defaultFluidState(), EntityType.IRON_GOLEM) && level.isUnobstructed(this); + } + } + + @Override +- @Override + public Vec3 getLeashOffset() { + return new Vec3(0.0D, (double) (0.875F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); + } +@@ -374,8 +350,8 @@ + + NONE(1.0F), LOW(0.75F), MEDIUM(0.5F), HIGH(0.25F); + +- private static final List BY_DAMAGE = (List) Stream.of(values()).sorted(Comparator.comparingDouble((irongolem_crackiness) -> { +- return (double) irongolem_crackiness.fraction; ++ private static final List BY_DAMAGE = (List) Stream.of(values()).sorted(Comparator.comparingDouble((entityirongolem_cracklevel) -> { ++ return (double) entityirongolem_cracklevel.fraction; + })).collect(ImmutableList.toImmutableList()); + private final float fraction; + +@@ -383,20 +359,20 @@ + this.fraction = f; + } + +- public static IronGolem.Crackiness byFraction(float f) { ++ public static IronGolem.Crackiness byFraction(float fraction) { + Iterator iterator = IronGolem.Crackiness.BY_DAMAGE.iterator(); + +- IronGolem.Crackiness irongolem_crackiness; ++ IronGolem.Crackiness entityirongolem_cracklevel; + + do { + if (!iterator.hasNext()) { + return IronGolem.Crackiness.NONE; + } + +- irongolem_crackiness = (IronGolem.Crackiness) iterator.next(); +- } while (f >= irongolem_crackiness.fraction); ++ entityirongolem_cracklevel = (IronGolem.Crackiness) iterator.next(); ++ } while (fraction >= entityirongolem_cracklevel.fraction); + +- return irongolem_crackiness; ++ return entityirongolem_cracklevel; + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/MushroomCow.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/MushroomCow.java.patch new file mode 100644 index 0000000000..69a1e22854 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/MushroomCow.java.patch @@ -0,0 +1,343 @@ +--- a/net/minecraft/world/entity/animal/MushroomCow.java ++++ b/net/minecraft/world/entity/animal/MushroomCow.java +@@ -19,13 +19,13 @@ + import net.minecraft.tags.ItemTags; + import net.minecraft.util.RandomSource; + import net.minecraft.util.StringRepresentable; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.LightningBolt; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.Shearable; + import net.minecraft.world.entity.VariantHolder; + import net.minecraft.world.entity.item.ItemEntity; +@@ -39,37 +39,42 @@ + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.SuspiciousEffectHolder; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityDropItemEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++// CraftBukkit end ++ + public class MushroomCow extends Cow implements Shearable, VariantHolder { + + private static final EntityDataAccessor DATA_TYPE = SynchedEntityData.defineId(MushroomCow.class, EntityDataSerializers.STRING); + private static final int MUTATE_CHANCE = 1024; + private static final String TAG_STEW_EFFECTS = "stew_effects"; + @Nullable +- private List stewEffects; ++ private List stewEffects; + @Nullable + private UUID lastLightningBoltUUID; + +- public MushroomCow(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public MushroomCow(EntityType entityType, Level level) { ++ super(entityType, level); + } + + @Override +- @Override +- public float getWalkTargetValue(BlockPos blockpos, LevelReader levelreader) { +- return levelreader.getBlockState(blockpos.below()).is(Blocks.MYCELIUM) ? 10.0F : levelreader.getPathfindingCostFromLightLevels(blockpos); ++ public float getWalkTargetValue(BlockPos pos, LevelReader level) { ++ return level.getBlockState(pos.below()).is(Blocks.MYCELIUM) ? 10.0F : level.getPathfindingCostFromLightLevels(pos); + } + +- public static boolean checkMushroomSpawnRules(EntityType entitytype, LevelAccessor levelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- return levelaccessor.getBlockState(blockpos.below()).is(BlockTags.MOOSHROOMS_SPAWNABLE_ON) && isBrightEnoughToSpawn(levelaccessor, blockpos); ++ public static boolean checkMushroomSpawnRules(EntityType mushroomCow, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource randomSource) { ++ return level.getBlockState(pos.below()).is(BlockTags.MOOSHROOMS_SPAWNABLE_ON) && isBrightEnoughToSpawn(level, pos); + } + + @Override +- @Override +- public void thunderHit(ServerLevel serverlevel, LightningBolt lightningbolt) { +- UUID uuid = lightningbolt.getUUID(); ++ public void thunderHit(ServerLevel level, LightningBolt lightning) { ++ UUID uuid = lightning.getUUID(); + + if (!uuid.equals(this.lastLightningBoltUUID)) { + this.setVariant(this.getVariant() == MushroomCow.MushroomType.RED ? MushroomCow.MushroomType.BROWN : MushroomCow.MushroomType.RED); +@@ -80,16 +85,14 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(MushroomCow.DATA_TYPE, MushroomCow.MushroomType.RED.type); + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (itemstack.is(Items.BOWL) && !this.isBaby()) { + boolean flag = false; +@@ -106,23 +109,28 @@ + + ItemStack itemstack2 = ItemUtils.createFilledResult(itemstack, player, itemstack1, false); + +- player.setItemInHand(interactionhand, itemstack2); +- SoundEvent soundevent; ++ player.setItemInHand(hand, itemstack2); ++ SoundEvent soundeffect; + + if (flag) { +- soundevent = SoundEvents.MOOSHROOM_MILK_SUSPICIOUSLY; ++ soundeffect = SoundEvents.MOOSHROOM_MILK_SUSPICIOUSLY; + } else { +- soundevent = SoundEvents.MOOSHROOM_MILK; ++ soundeffect = SoundEvents.MOOSHROOM_MILK; + } + +- this.playSound(soundevent, 1.0F, 1.0F); ++ this.playSound(soundeffect, 1.0F, 1.0F); + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else if (itemstack.is(Items.SHEARS) && this.readyForShearing()) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) { ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.shear(SoundSource.PLAYERS); + this.gameEvent(GameEvent.SHEAR, player); + if (!this.level().isClientSide) { +- itemstack.hurtAndBreak(1, player, (player1) -> { +- player1.broadcastBreakEvent(interactionhand); ++ itemstack.hurtAndBreak(1, player, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(hand); + }); + } + +@@ -133,7 +141,7 @@ + this.level().addParticle(ParticleTypes.SMOKE, this.getX() + this.random.nextDouble() / 2.0D, this.getY(0.5D), this.getZ() + this.random.nextDouble() / 2.0D, 0.0D, this.random.nextDouble() / 5.0D, 0.0D); + } + } else { +- Optional> optional = this.getEffectsFromItemStack(itemstack); ++ Optional> optional = this.getEffectsFromItemStack(itemstack); + + if (optional.isEmpty()) { + return InteractionResult.PASS; +@@ -153,37 +161,51 @@ + + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { +- return super.mobInteract(player, interactionhand); ++ return super.mobInteract(player, hand); + } + } + + @Override +- @Override +- public void shear(SoundSource soundsource) { +- this.level().playSound((Player) null, (Entity) this, SoundEvents.MOOSHROOM_SHEAR, soundsource, 1.0F, 1.0F); ++ public void shear(SoundSource category) { ++ this.level().playSound((Player) null, (Entity) this, SoundEvents.MOOSHROOM_SHEAR, category, 1.0F, 1.0F); + if (!this.level().isClientSide()) { +- Cow cow = (Cow) EntityType.COW.create(this.level()); ++ Cow entitycow = (Cow) EntityType.COW.create(this.level()); + +- if (cow != null) { ++ if (entitycow != null) { + ((ServerLevel) this.level()).sendParticles(ParticleTypes.EXPLOSION, this.getX(), this.getY(0.5D), this.getZ(), 1, 0.0D, 0.0D, 0.0D, 0.0D); +- this.discard(); +- cow.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); +- cow.setHealth(this.getHealth()); +- cow.yBodyRot = this.yBodyRot; ++ // this.discard(); // CraftBukkit - moved down ++ entitycow.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); ++ entitycow.setHealth(this.getHealth()); ++ entitycow.yBodyRot = this.yBodyRot; + if (this.hasCustomName()) { +- cow.setCustomName(this.getCustomName()); +- cow.setCustomNameVisible(this.isCustomNameVisible()); ++ entitycow.setCustomName(this.getCustomName()); ++ entitycow.setCustomNameVisible(this.isCustomNameVisible()); + } + + if (this.isPersistenceRequired()) { +- cow.setPersistenceRequired(); ++ entitycow.setPersistenceRequired(); + } + +- cow.setInvulnerable(this.isInvulnerable()); +- this.level().addFreshEntity(cow); ++ entitycow.setInvulnerable(this.isInvulnerable()); ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, entitycow, EntityTransformEvent.TransformReason.SHEARED).isCancelled()) { ++ return; ++ } ++ this.level().addFreshEntity(entitycow, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SHEARED); + ++ this.discard(); // CraftBukkit - from above ++ // CraftBukkit end ++ + for (int i = 0; i < 5; ++i) { +- this.level().addFreshEntity(new ItemEntity(this.level(), this.getX(), this.getY(1.0D), this.getZ(), new ItemStack(this.getVariant().blockState.getBlock()))); ++ // CraftBukkit start ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY(1.0D), this.getZ(), new ItemStack(this.getVariant().blockState.getBlock())); ++ EntityDropItemEvent event = new EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ continue; ++ } ++ this.level().addFreshEntity(entityitem); ++ // CraftBukkit end + } + } + } +@@ -191,79 +213,73 @@ + } + + @Override +- @Override + public boolean readyForShearing() { + return this.isAlive() && !this.isBaby(); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putString("Type", this.getVariant().getSerializedName()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putString("Type", this.getVariant().getSerializedName()); + if (this.stewEffects != null) { +- SuspiciousEffectHolder.EffectEntry.LIST_CODEC.encodeStart(NbtOps.INSTANCE, this.stewEffects).result().ifPresent((tag) -> { +- compoundtag.put("stew_effects", tag); ++ SuspiciousEffectHolder.a.LIST_CODEC.encodeStart(NbtOps.INSTANCE, this.stewEffects).result().ifPresent((nbtbase) -> { ++ compound.put("stew_effects", nbtbase); + }); + } + + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setVariant(MushroomCow.MushroomType.byType(compoundtag.getString("Type"))); +- if (compoundtag.contains("stew_effects", 9)) { +- SuspiciousEffectHolder.EffectEntry.LIST_CODEC.parse(NbtOps.INSTANCE, compoundtag.get("stew_effects")).result().ifPresent((list) -> { ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setVariant(MushroomCow.MushroomType.byType(compound.getString("Type"))); ++ if (compound.contains("stew_effects", 9)) { ++ SuspiciousEffectHolder.a.LIST_CODEC.parse(NbtOps.INSTANCE, compound.get("stew_effects")).result().ifPresent((list) -> { + this.stewEffects = list; + }); + } + + } + +- private Optional> getEffectsFromItemStack(ItemStack itemstack) { ++ private Optional> getEffectsFromItemStack(ItemStack itemstack) { + SuspiciousEffectHolder suspiciouseffectholder = SuspiciousEffectHolder.tryGet(itemstack.getItem()); + + return suspiciouseffectholder != null ? Optional.of(suspiciouseffectholder.getSuspiciousEffects()) : Optional.empty(); + } + +- @Override +- public void setVariant(MushroomCow.MushroomType mushroomcow_mushroomtype) { +- this.entityData.set(MushroomCow.DATA_TYPE, mushroomcow_mushroomtype.type); ++ public void setVariant(MushroomCow.MushroomType variant) { ++ this.entityData.set(MushroomCow.DATA_TYPE, variant.type); + } + + @Override +- @Override + public MushroomCow.MushroomType getVariant() { + return MushroomCow.MushroomType.byType((String) this.entityData.get(MushroomCow.DATA_TYPE)); + } + + @Nullable + @Override +- @Override +- public MushroomCow getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { +- MushroomCow mushroomcow = (MushroomCow) EntityType.MOOSHROOM.create(serverlevel); ++ public MushroomCow getBreedOffspring(ServerLevel level, AgeableMob otherParent) { ++ MushroomCow entitymushroomcow = (MushroomCow) EntityType.MOOSHROOM.create(level); + +- if (mushroomcow != null) { +- mushroomcow.setVariant(this.getOffspringType((MushroomCow) ageablemob)); ++ if (entitymushroomcow != null) { ++ entitymushroomcow.setVariant(this.getOffspringType((MushroomCow) otherParent)); + } + +- return mushroomcow; ++ return entitymushroomcow; + } + +- private MushroomCow.MushroomType getOffspringType(MushroomCow mushroomcow) { +- MushroomCow.MushroomType mushroomcow_mushroomtype = this.getVariant(); +- MushroomCow.MushroomType mushroomcow_mushroomtype1 = mushroomcow.getVariant(); +- MushroomCow.MushroomType mushroomcow_mushroomtype2; ++ private MushroomCow.MushroomType getOffspringType(MushroomCow mate) { ++ MushroomCow.MushroomType entitymushroomcow_type = this.getVariant(); ++ MushroomCow.MushroomType entitymushroomcow_type1 = mate.getVariant(); ++ MushroomCow.MushroomType entitymushroomcow_type2; + +- if (mushroomcow_mushroomtype == mushroomcow_mushroomtype1 && this.random.nextInt(1024) == 0) { +- mushroomcow_mushroomtype2 = mushroomcow_mushroomtype == MushroomCow.MushroomType.BROWN ? MushroomCow.MushroomType.RED : MushroomCow.MushroomType.BROWN; ++ if (entitymushroomcow_type == entitymushroomcow_type1 && this.random.nextInt(1024) == 0) { ++ entitymushroomcow_type2 = entitymushroomcow_type == MushroomCow.MushroomType.BROWN ? MushroomCow.MushroomType.RED : MushroomCow.MushroomType.BROWN; + } else { +- mushroomcow_mushroomtype2 = this.random.nextBoolean() ? mushroomcow_mushroomtype : mushroomcow_mushroomtype1; ++ entitymushroomcow_type2 = this.random.nextBoolean() ? entitymushroomcow_type : entitymushroomcow_type1; + } + +- return mushroomcow_mushroomtype2; ++ return entitymushroomcow_type2; + } + + public static enum MushroomType implements StringRepresentable { +@@ -272,25 +288,24 @@ + + public static final StringRepresentable.EnumCodec CODEC = StringRepresentable.fromEnum(MushroomCow.MushroomType::values); + final String type; +- final BlockState blockState; ++ final IBlockData blockState; + +- private MushroomType(String s, BlockState blockstate) { ++ private MushroomType(String s, IBlockData iblockdata) { + this.type = s; +- this.blockState = blockstate; ++ this.blockState = iblockdata; + } + +- public BlockState getBlockState() { ++ public IBlockData getBlockState() { + return this.blockState; + } + + @Override +- @Override + public String getSerializedName() { + return this.type; + } + +- static MushroomCow.MushroomType byType(String s) { +- return (MushroomCow.MushroomType) MushroomCow.MushroomType.CODEC.byName(s, MushroomCow.MushroomType.RED); ++ static MushroomCow.MushroomType byType(String name) { ++ return (MushroomCow.MushroomType) MushroomCow.MushroomType.CODEC.byName(name, MushroomCow.MushroomType.RED); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Ocelot.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Ocelot.java.patch new file mode 100644 index 0000000000..deaff815cc --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Ocelot.java.patch @@ -0,0 +1,353 @@ +--- a/net/minecraft/world/entity/animal/Ocelot.java ++++ b/net/minecraft/world/entity/animal/Ocelot.java +@@ -16,19 +16,19 @@ + import net.minecraft.tags.BlockTags; + import net.minecraft.util.RandomSource; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.AvoidEntityGoal; +@@ -49,7 +49,7 @@ + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +@@ -65,43 +65,39 @@ + @Nullable + private Ocelot.OcelotTemptGoal temptGoal; + +- public Ocelot(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Ocelot(EntityType entityType, Level level) { ++ super(entityType, level); + this.reassessTrustingGoals(); + } + +- boolean isTrusting() { ++ public boolean isTrusting() { + return (Boolean) this.entityData.get(Ocelot.DATA_TRUSTING); + } + +- private void setTrusting(boolean flag) { +- this.entityData.set(Ocelot.DATA_TRUSTING, flag); ++ public void setTrusting(boolean trusting) { ++ this.entityData.set(Ocelot.DATA_TRUSTING, trusting); + this.reassessTrustingGoals(); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putBoolean("Trusting", this.isTrusting()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putBoolean("Trusting", this.isTrusting()); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setTrusting(compoundtag.getBoolean("Trusting")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setTrusting(compound.getBoolean("Trusting")); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Ocelot.DATA_TRUSTING, false); + } + + @Override +- @Override + protected void registerGoals() { + this.temptGoal = new Ocelot.OcelotTemptGoal(this, 0.6D, Ocelot.TEMPT_INGREDIENT, true); + this.goalSelector.addGoal(1, new FloatGoal(this)); +@@ -116,31 +112,29 @@ + } + + @Override +- @Override + public void customServerAiStep() { + if (this.getMoveControl().hasWanted()) { + double d0 = this.getMoveControl().getSpeedModifier(); + + if (d0 == 0.6D) { +- this.setPose(Pose.CROUCHING); ++ this.setPose(EntityPose.CROUCHING); + this.setSprinting(false); + } else if (d0 == 1.33D) { +- this.setPose(Pose.STANDING); ++ this.setPose(EntityPose.STANDING); + this.setSprinting(true); + } else { +- this.setPose(Pose.STANDING); ++ this.setPose(EntityPose.STANDING); + this.setSprinting(false); + } + } else { +- this.setPose(Pose.STANDING); ++ this.setPose(EntityPose.STANDING); + this.setSprinting(false); + } + + } + + @Override +- @Override +- public boolean removeWhenFarAway(double d0) { ++ public boolean removeWhenFarAway(double distanceToClosestPlayer) { + return !this.isTrusting() && this.tickCount > 2400; + } + +@@ -150,25 +144,21 @@ + + @Nullable + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.OCELOT_AMBIENT; + } + + @Override +- @Override + public int getAmbientSoundInterval() { + return 900; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.OCELOT_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.OCELOT_DEATH; + } +@@ -178,20 +168,18 @@ + } + + @Override +- @Override + public boolean doHurtTarget(Entity entity) { + return entity.hurt(this.damageSources().mobAttack(this), this.getAttackDamage()); + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if ((this.temptGoal == null || this.temptGoal.isRunning()) && !this.isTrusting() && this.isFood(itemstack) && player.distanceToSqr((Entity) this) < 9.0D) { +- this.usePlayerItem(player, interactionhand, itemstack); ++ this.usePlayerItem(player, hand, itemstack); + if (!this.level().isClientSide) { +- if (this.random.nextInt(3) == 0) { ++ if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit - added event call and isCancelled check + this.setTrusting(true); + this.spawnTrustingParticles(true); + this.level().broadcastEntityEvent(this, (byte) 41); +@@ -203,28 +191,27 @@ + + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { +- return super.mobInteract(player, interactionhand); ++ return super.mobInteract(player, hand); + } + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 41) { ++ public void handleEntityEvent(byte id) { ++ if (id == 41) { + this.spawnTrustingParticles(true); +- } else if (b0 == 40) { ++ } else if (id == 40) { + this.spawnTrustingParticles(false); + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } + +- private void spawnTrustingParticles(boolean flag) { +- SimpleParticleType simpleparticletype = ParticleTypes.HEART; ++ private void spawnTrustingParticles(boolean isTrusted) { ++ SimpleParticleType particletype = ParticleTypes.HEART; + +- if (!flag) { +- simpleparticletype = ParticleTypes.SMOKE; ++ if (!isTrusted) { ++ particletype = ParticleTypes.SMOKE; + } + + for (int i = 0; i < 7; ++i) { +@@ -232,7 +219,7 @@ + double d1 = this.random.nextGaussian() * 0.02D; + double d2 = this.random.nextGaussian() * 0.02D; + +- this.level().addParticle(simpleparticletype, this.getRandomX(1.0D), this.getRandomY() + 0.5D, this.getRandomZ(1.0D), d0, d1, d2); ++ this.level().addParticle(particletype, this.getRandomX(1.0D), this.getRandomY() + 0.5D, this.getRandomZ(1.0D), d0, d1, d2); + } + + } +@@ -251,34 +238,31 @@ + + @Nullable + @Override +- @Override +- public Ocelot getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { +- return (Ocelot) EntityType.OCELOT.create(serverlevel); ++ public Ocelot getBreedOffspring(ServerLevel level, AgeableMob otherParent) { ++ return (Ocelot) EntityType.OCELOT.create(level); + } + + @Override +- @Override +- public boolean isFood(ItemStack itemstack) { +- return Ocelot.TEMPT_INGREDIENT.test(itemstack); ++ public boolean isFood(ItemStack stack) { ++ return Ocelot.TEMPT_INGREDIENT.test(stack); + } + +- public static boolean checkOcelotSpawnRules(EntityType entitytype, LevelAccessor levelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- return randomsource.nextInt(3) != 0; ++ public static boolean checkOcelotSpawnRules(EntityType ocelot, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ return random.nextInt(3) != 0; + } + + @Override +- @Override +- public boolean checkSpawnObstruction(LevelReader levelreader) { +- if (levelreader.isUnobstructed(this) && !levelreader.containsAnyLiquid(this.getBoundingBox())) { +- BlockPos blockpos = this.blockPosition(); ++ public boolean checkSpawnObstruction(LevelReader level) { ++ if (level.isUnobstructed(this) && !level.containsAnyLiquid(this.getBoundingBox())) { ++ BlockPos blockposition = this.blockPosition(); + +- if (blockpos.getY() < levelreader.getSeaLevel()) { ++ if (blockposition.getY() < level.getSeaLevel()) { + return false; + } + +- BlockState blockstate = levelreader.getBlockState(blockpos.below()); ++ IBlockData iblockdata = level.getBlockState(blockposition.below()); + +- if (blockstate.is(Blocks.GRASS_BLOCK) || blockstate.is(BlockTags.LEAVES)) { ++ if (iblockdata.is(Blocks.GRASS_BLOCK) || iblockdata.is(BlockTags.LEAVES)) { + return true; + } + } +@@ -288,44 +272,39 @@ + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- if (spawngroupdata == null) { +- spawngroupdata = new AgeableMob.AgeableMobGroupData(1.0F); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ if (spawnData == null) { ++ spawnData = new AgeableMob.AgeableMobGroupData(1.0F); + } + +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, (SpawnGroupData) spawngroupdata, compoundtag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + + @Override +- @Override + public Vec3 getLeashOffset() { + return new Vec3(0.0D, (double) (0.5F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); + } + + @Override +- @Override + public boolean isSteppingCarefully() { + return this.isCrouching() || super.isSteppingCarefully(); + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height - 0.0625F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.0625F * f, 0.0F); + } + + private static class OcelotTemptGoal extends TemptGoal { + + private final Ocelot ocelot; + +- public OcelotTemptGoal(Ocelot ocelot, double d0, Ingredient ingredient, boolean flag) { +- super(ocelot, d0, ingredient, flag); ++ public OcelotTemptGoal(Ocelot ocelot, double speedModifier, Ingredient recipeitemstack, boolean items) { ++ super(ocelot, speedModifier, recipeitemstack, items); + this.ocelot = ocelot; + } + + @Override +- @Override + protected boolean canScare() { + return super.canScare() && !this.ocelot.isTrusting(); + } +@@ -335,22 +314,20 @@ + + private final Ocelot ocelot; + +- public OcelotAvoidEntityGoal(Ocelot ocelot, Class oclass, float f, double d0, double d1) { +- Predicate predicate = EntitySelector.NO_CREATIVE_OR_SPECTATOR; ++ public OcelotAvoidEntityGoal(Ocelot ocelot, Class entityClassToAvoid, float maxDist, double walkSpeedModifier, double d1) { ++ // Predicate predicate = IEntitySelector.NO_CREATIVE_OR_SPECTATOR; // CraftBukkit - decompile error + +- Objects.requireNonNull(predicate); +- super(ocelot, oclass, f, d0, d1, predicate::test); ++ // Objects.requireNonNull(predicate); // CraftBukkit - decompile error ++ super(ocelot, entityClassToAvoid, maxDist, walkSpeedModifier, d1, EntitySelector.NO_CREATIVE_OR_SPECTATOR::test); // CraftBukkit - decompile error + this.ocelot = ocelot; + } + + @Override +- @Override + public boolean canUse() { + return !this.ocelot.isTrusting() && super.canUse(); + } + + @Override +- @Override + public boolean canContinueToUse() { + return !this.ocelot.isTrusting() && super.canContinueToUse(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Panda.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Panda.java.patch new file mode 100644 index 0000000000..7282f1c9fc --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Panda.java.patch @@ -0,0 +1,958 @@ +--- a/net/minecraft/world/entity/animal/Panda.java ++++ b/net/minecraft/world/entity/animal/Panda.java +@@ -22,7 +22,7 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.util.StringRepresentable; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; +@@ -30,11 +30,11 @@ + import net.minecraft.world.entity.EntityDimensions; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.MoveControl; +@@ -58,15 +58,20 @@ + import net.minecraft.world.item.Items; + import net.minecraft.world.item.crafting.Ingredient; + import net.minecraft.world.level.GameRules; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end ++ + public class Panda extends Animal { + + private static final EntityDataAccessor UNHAPPY_COUNTER = SynchedEntityData.defineId(Panda.class, EntityDataSerializers.INT); +@@ -94,14 +99,14 @@ + private float rollAmount; + private float rollAmountO; + Panda.PandaLookAtPlayerGoal lookAtPlayerGoal; +- static final Predicate PANDA_ITEMS = (itementity) -> { +- ItemStack itemstack = itementity.getItem(); ++ static final Predicate PANDA_ITEMS = (entityitem) -> { ++ ItemStack itemstack = entityitem.getItem(); + +- return (itemstack.is(Blocks.BAMBOO.asItem()) || itemstack.is(Blocks.CAKE.asItem())) && itementity.isAlive() && !itementity.hasPickUpDelay(); ++ return (itemstack.is(Blocks.BAMBOO.asItem()) || itemstack.is(Blocks.CAKE.asItem())) && entityitem.isAlive() && !entityitem.hasPickUpDelay(); + }; + +- public Panda(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Panda(EntityType entityType, Level level) { ++ super(entityType, level); + this.moveControl = new Panda.PandaMoveControl(this); + if (!this.isBaby()) { + this.setCanPickUpLoot(true); +@@ -110,19 +115,18 @@ + } + + @Override +- @Override + public boolean canTakeItem(ItemStack itemstack) { +- EquipmentSlot equipmentslot = Mob.getEquipmentSlotForItem(itemstack); ++ EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(itemstack); + +- return !this.getItemBySlot(equipmentslot).isEmpty() ? false : equipmentslot == EquipmentSlot.MAINHAND && super.canTakeItem(itemstack); ++ return !this.getItemBySlot(enumitemslot).isEmpty() ? false : enumitemslot == EquipmentSlot.MAINHAND && super.canTakeItem(itemstack); + } + + public int getUnhappyCounter() { + return (Integer) this.entityData.get(Panda.UNHAPPY_COUNTER); + } + +- public void setUnhappyCounter(int i) { +- this.entityData.set(Panda.UNHAPPY_COUNTER, i); ++ public void setUnhappyCounter(int unhappyCounter) { ++ this.entityData.set(Panda.UNHAPPY_COUNTER, unhappyCounter); + } + + public boolean isSneezing() { +@@ -133,37 +137,37 @@ + return this.getFlag(8); + } + +- public void sit(boolean flag) { +- this.setFlag(8, flag); ++ public void sit(boolean sitting) { ++ this.setFlag(8, sitting); + } + + public boolean isOnBack() { + return this.getFlag(16); + } + +- public void setOnBack(boolean flag) { +- this.setFlag(16, flag); ++ public void setOnBack(boolean onBack) { ++ this.setFlag(16, onBack); + } + + public boolean isEating() { + return (Integer) this.entityData.get(Panda.EAT_COUNTER) > 0; + } + +- public void eat(boolean flag) { +- this.entityData.set(Panda.EAT_COUNTER, flag ? 1 : 0); ++ public void eat(boolean eating) { ++ this.entityData.set(Panda.EAT_COUNTER, eating ? 1 : 0); + } + + private int getEatCounter() { + return (Integer) this.entityData.get(Panda.EAT_COUNTER); + } + +- private void setEatCounter(int i) { +- this.entityData.set(Panda.EAT_COUNTER, i); ++ private void setEatCounter(int eatCounter) { ++ this.entityData.set(Panda.EAT_COUNTER, eatCounter); + } + +- public void sneeze(boolean flag) { +- this.setFlag(2, flag); +- if (!flag) { ++ public void sneeze(boolean sneezing) { ++ this.setFlag(2, sneezing); ++ if (!sneezing) { + this.setSneezeCounter(0); + } + +@@ -173,44 +177,43 @@ + return (Integer) this.entityData.get(Panda.SNEEZE_COUNTER); + } + +- public void setSneezeCounter(int i) { +- this.entityData.set(Panda.SNEEZE_COUNTER, i); ++ public void setSneezeCounter(int sneezeCounter) { ++ this.entityData.set(Panda.SNEEZE_COUNTER, sneezeCounter); + } + + public Panda.Gene getMainGene() { + return Panda.Gene.byId((Byte) this.entityData.get(Panda.MAIN_GENE_ID)); + } + +- public void setMainGene(Panda.Gene panda_gene) { +- if (panda_gene.getId() > 6) { +- panda_gene = Panda.Gene.getRandom(this.random); ++ public void setMainGene(Panda.Gene pandaType) { ++ if (pandaType.getId() > 6) { ++ pandaType = Panda.Gene.getRandom(this.random); + } + +- this.entityData.set(Panda.MAIN_GENE_ID, (byte) panda_gene.getId()); ++ this.entityData.set(Panda.MAIN_GENE_ID, (byte) pandaType.getId()); + } + + public Panda.Gene getHiddenGene() { + return Panda.Gene.byId((Byte) this.entityData.get(Panda.HIDDEN_GENE_ID)); + } + +- public void setHiddenGene(Panda.Gene panda_gene) { +- if (panda_gene.getId() > 6) { +- panda_gene = Panda.Gene.getRandom(this.random); ++ public void setHiddenGene(Panda.Gene pandaType) { ++ if (pandaType.getId() > 6) { ++ pandaType = Panda.Gene.getRandom(this.random); + } + +- this.entityData.set(Panda.HIDDEN_GENE_ID, (byte) panda_gene.getId()); ++ this.entityData.set(Panda.HIDDEN_GENE_ID, (byte) pandaType.getId()); + } + + public boolean isRolling() { + return this.getFlag(4); + } + +- public void roll(boolean flag) { +- this.setFlag(4, flag); ++ public void roll(boolean rolling) { ++ this.setFlag(4, rolling); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Panda.UNHAPPY_COUNTER, 0); +@@ -221,58 +224,54 @@ + this.entityData.define(Panda.EAT_COUNTER, 0); + } + +- private boolean getFlag(int i) { +- return ((Byte) this.entityData.get(Panda.DATA_ID_FLAGS) & i) != 0; ++ private boolean getFlag(int flag) { ++ return ((Byte) this.entityData.get(Panda.DATA_ID_FLAGS) & flag) != 0; + } + +- private void setFlag(int i, boolean flag) { ++ private void setFlag(int flagId, boolean value) { + byte b0 = (Byte) this.entityData.get(Panda.DATA_ID_FLAGS); + +- if (flag) { +- this.entityData.set(Panda.DATA_ID_FLAGS, (byte) (b0 | i)); ++ if (value) { ++ this.entityData.set(Panda.DATA_ID_FLAGS, (byte) (b0 | flagId)); + } else { +- this.entityData.set(Panda.DATA_ID_FLAGS, (byte) (b0 & ~i)); ++ this.entityData.set(Panda.DATA_ID_FLAGS, (byte) (b0 & ~flagId)); + } + + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putString("MainGene", this.getMainGene().getSerializedName()); +- compoundtag.putString("HiddenGene", this.getHiddenGene().getSerializedName()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putString("MainGene", this.getMainGene().getSerializedName()); ++ compound.putString("HiddenGene", this.getHiddenGene().getSerializedName()); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setMainGene(Panda.Gene.byName(compoundtag.getString("MainGene"))); +- this.setHiddenGene(Panda.Gene.byName(compoundtag.getString("HiddenGene"))); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setMainGene(Panda.Gene.byName(compound.getString("MainGene"))); ++ this.setHiddenGene(Panda.Gene.byName(compound.getString("HiddenGene"))); + } + + @Nullable + @Override +- @Override +- public AgeableMob getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { +- Panda panda = (Panda) EntityType.PANDA.create(serverlevel); ++ public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob otherParent) { ++ Panda entitypanda = (Panda) EntityType.PANDA.create(level); + +- if (panda != null) { +- if (ageablemob instanceof Panda) { +- Panda panda1 = (Panda) ageablemob; ++ if (entitypanda != null) { ++ if (otherParent instanceof Panda) { ++ Panda entitypanda1 = (Panda) otherParent; + +- panda.setGeneFromParents(this, panda1); ++ entitypanda.setGeneFromParents(this, entitypanda1); + } + +- panda.setAttributes(); ++ entitypanda.setAttributes(); + } + +- return panda; ++ return entitypanda; + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(2, new Panda.PandaPanicGoal(this, 2.0D)); +@@ -322,19 +321,16 @@ + } + + @Override +- @Override + public boolean isAggressive() { + return this.getVariant() == Panda.Gene.AGGRESSIVE; + } + + @Override +- @Override + public boolean canBeLeashed(Player player) { + return false; + } + + @Override +- @Override + public boolean doHurtTarget(Entity entity) { + this.playSound(SoundEvents.PANDA_BITE, 1.0F, 1.0F); + if (!this.isAggressive()) { +@@ -345,7 +341,6 @@ + } + + @Override +- @Override + public void tick() { + super.tick(); + if (this.isWorried()) { +@@ -357,16 +352,16 @@ + } + } + +- LivingEntity livingentity = this.getTarget(); ++ LivingEntity entityliving = this.getTarget(); + +- if (livingentity == null) { ++ if (entityliving == null) { + this.gotBamboo = false; + this.didBite = false; + } + + if (this.getUnhappyCounter() > 0) { +- if (livingentity != null) { +- this.lookAt(livingentity, 90.0F, 90.0F); ++ if (entityliving != null) { ++ this.lookAt(entityliving, 90.0F, 90.0F); + } + + if (this.getUnhappyCounter() == 29 || this.getUnhappyCounter() == 14) { +@@ -439,16 +434,16 @@ + this.playSound(SoundEvents.PANDA_EAT, 0.5F + 0.5F * (float) this.random.nextInt(2), (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); + + for (int i = 0; i < 6; ++i) { +- Vec3 vec3 = new Vec3(((double) this.random.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, ((double) this.random.nextFloat() - 0.5D) * 0.1D); ++ Vec3 vec3d = new Vec3(((double) this.random.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, ((double) this.random.nextFloat() - 0.5D) * 0.1D); + +- vec3 = vec3.xRot(-this.getXRot() * 0.017453292F); +- vec3 = vec3.yRot(-this.getYRot() * 0.017453292F); ++ vec3d = vec3d.xRot(-this.getXRot() * 0.017453292F); ++ vec3d = vec3d.yRot(-this.getYRot() * 0.017453292F); + double d0 = (double) (-this.random.nextFloat()) * 0.6D - 0.3D; +- Vec3 vec31 = new Vec3(((double) this.random.nextFloat() - 0.5D) * 0.8D, d0, 1.0D + ((double) this.random.nextFloat() - 0.5D) * 0.4D); ++ Vec3 vec3d1 = new Vec3(((double) this.random.nextFloat() - 0.5D) * 0.8D, d0, 1.0D + ((double) this.random.nextFloat() - 0.5D) * 0.4D); + +- vec31 = vec31.yRot(-this.yBodyRot * 0.017453292F); +- vec31 = vec31.add(this.getX(), this.getEyeY() + 1.0D, this.getZ()); +- this.level().addParticle(new ItemParticleOption(ParticleTypes.ITEM, this.getItemBySlot(EquipmentSlot.MAINHAND)), vec31.x, vec31.y, vec31.z, vec3.x, vec3.y + 0.05D, vec3.z); ++ vec3d1 = vec3d1.yRot(-this.yBodyRot * 0.017453292F); ++ vec3d1 = vec3d1.add(this.getX(), this.getEyeY() + 1.0D, this.getZ()); ++ this.level().addParticle(new ItemParticleOption(ParticleTypes.ITEM, this.getItemBySlot(EquipmentSlot.MAINHAND)), vec3d1.x, vec3d1.y, vec3d1.z, vec3d.x, vec3d.y + 0.05D, vec3d.z); + } + } + +@@ -484,16 +479,16 @@ + + } + +- public float getSitAmount(float f) { +- return Mth.lerp(f, this.sitAmountO, this.sitAmount); ++ public float getSitAmount(float partialTick) { ++ return Mth.lerp(partialTick, this.sitAmountO, this.sitAmount); + } + +- public float getLieOnBackAmount(float f) { +- return Mth.lerp(f, this.onBackAmountO, this.onBackAmount); ++ public float getLieOnBackAmount(float partialTick) { ++ return Mth.lerp(partialTick, this.onBackAmountO, this.onBackAmount); + } + +- public float getRollAmount(float f) { +- return Mth.lerp(f, this.rollAmountO, this.rollAmount); ++ public float getRollAmount(float partialTick) { ++ return Mth.lerp(partialTick, this.rollAmountO, this.rollAmount); + } + + private void handleRoll() { +@@ -502,18 +497,18 @@ + this.roll(false); + } else { + if (!this.level().isClientSide) { +- Vec3 vec3 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + + if (this.rollCounter == 1) { + float f = this.getYRot() * 0.017453292F; + float f1 = this.isBaby() ? 0.1F : 0.2F; + +- this.rollDelta = new Vec3(vec3.x + (double) (-Mth.sin(f) * f1), 0.0D, vec3.z + (double) (Mth.cos(f) * f1)); ++ this.rollDelta = new Vec3(vec3d.x + (double) (-Mth.sin(f) * f1), 0.0D, vec3d.z + (double) (Mth.cos(f) * f1)); + this.setDeltaMovement(this.rollDelta.add(0.0D, 0.27D, 0.0D)); + } else if ((float) this.rollCounter != 7.0F && (float) this.rollCounter != 15.0F && (float) this.rollCounter != 23.0F) { +- this.setDeltaMovement(this.rollDelta.x, vec3.y, this.rollDelta.z); ++ this.setDeltaMovement(this.rollDelta.x, vec3d.y, this.rollDelta.z); + } else { +- this.setDeltaMovement(0.0D, this.onGround() ? 0.27D : vec3.y, 0.0D); ++ this.setDeltaMovement(0.0D, this.onGround() ? 0.27D : vec3d.y, 0.0D); + } + } + +@@ -521,83 +516,80 @@ + } + + private void afterSneeze() { +- Vec3 vec3 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + +- this.level().addParticle(ParticleTypes.SNEEZE, this.getX() - (double) (this.getBbWidth() + 1.0F) * 0.5D * (double) Mth.sin(this.yBodyRot * 0.017453292F), this.getEyeY() - 0.10000000149011612D, this.getZ() + (double) (this.getBbWidth() + 1.0F) * 0.5D * (double) Mth.cos(this.yBodyRot * 0.017453292F), vec3.x, 0.0D, vec3.z); ++ this.level().addParticle(ParticleTypes.SNEEZE, this.getX() - (double) (this.getBbWidth() + 1.0F) * 0.5D * (double) Mth.sin(this.yBodyRot * 0.017453292F), this.getEyeY() - 0.10000000149011612D, this.getZ() + (double) (this.getBbWidth() + 1.0F) * 0.5D * (double) Mth.cos(this.yBodyRot * 0.017453292F), vec3d.x, 0.0D, vec3d.z); + this.playSound(SoundEvents.PANDA_SNEEZE, 1.0F, 1.0F); + List list = this.level().getEntitiesOfClass(Panda.class, this.getBoundingBox().inflate(10.0D)); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- Panda panda = (Panda) iterator.next(); ++ Panda entitypanda = (Panda) iterator.next(); + +- if (!panda.isBaby() && panda.onGround() && !panda.isInWater() && panda.canPerformAction()) { +- panda.jumpFromGround(); ++ if (!entitypanda.isBaby() && entitypanda.onGround() && !entitypanda.isInWater() && entitypanda.canPerformAction()) { ++ entitypanda.jumpFromGround(); + } + } + + if (!this.level().isClientSide() && this.random.nextInt(700) == 0 && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +- this.spawnAtLocation((ItemLike) Items.SLIME_BALL); ++ this.spawnAtLocation((IMaterial) Items.SLIME_BALL); + } + + } + + @Override +- @Override +- protected void pickUpItem(ItemEntity itementity) { +- if (this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty() && Panda.PANDA_ITEMS.test(itementity)) { +- this.onItemPickup(itementity); +- ItemStack itemstack = itementity.getItem(); ++ protected void pickUpItem(ItemEntity itemEntity) { ++ if (!CraftEventFactory.callEntityPickupItemEvent(this, itemEntity, 0, !(this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty() && Panda.PANDA_ITEMS.test(itemEntity))).isCancelled()) { // CraftBukkit ++ this.onItemPickup(itemEntity); ++ ItemStack itemstack = itemEntity.getItem(); + + this.setItemSlot(EquipmentSlot.MAINHAND, itemstack); + this.setGuaranteedDrop(EquipmentSlot.MAINHAND); +- this.take(itementity, itemstack.getCount()); +- itementity.discard(); ++ this.take(itemEntity, itemstack.getCount()); ++ itemEntity.discard(); + } + + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { ++ public boolean hurt(DamageSource source, float amount) { + if (!this.level().isClientSide) { + this.sit(false); + } + +- return super.hurt(damagesource, f); ++ return super.hurt(source, amount); + } + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- RandomSource randomsource = serverlevelaccessor.getRandom(); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ RandomSource randomsource = level.getRandom(); + + this.setMainGene(Panda.Gene.getRandom(randomsource)); + this.setHiddenGene(Panda.Gene.getRandom(randomsource)); + this.setAttributes(); +- if (spawngroupdata == null) { +- spawngroupdata = new AgeableMob.AgeableMobGroupData(0.2F); ++ if (spawnData == null) { ++ spawnData = new AgeableMob.AgeableMobGroupData(0.2F); + } + +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, (SpawnGroupData) spawngroupdata, compoundtag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + +- public void setGeneFromParents(Panda panda, @Nullable Panda panda1) { +- if (panda1 == null) { ++ public void setGeneFromParents(Panda father, @Nullable Panda mother) { ++ if (mother == null) { + if (this.random.nextBoolean()) { +- this.setMainGene(panda.getOneOfGenesRandomly()); ++ this.setMainGene(father.getOneOfGenesRandomly()); + this.setHiddenGene(Panda.Gene.getRandom(this.random)); + } else { + this.setMainGene(Panda.Gene.getRandom(this.random)); +- this.setHiddenGene(panda.getOneOfGenesRandomly()); ++ this.setHiddenGene(father.getOneOfGenesRandomly()); + } + } else if (this.random.nextBoolean()) { +- this.setMainGene(panda.getOneOfGenesRandomly()); +- this.setHiddenGene(panda1.getOneOfGenesRandomly()); ++ this.setMainGene(father.getOneOfGenesRandomly()); ++ this.setHiddenGene(mother.getOneOfGenesRandomly()); + } else { +- this.setMainGene(panda1.getOneOfGenesRandomly()); +- this.setHiddenGene(panda.getOneOfGenesRandomly()); ++ this.setMainGene(mother.getOneOfGenesRandomly()); ++ this.setHiddenGene(father.getOneOfGenesRandomly()); + } + + if (this.random.nextInt(32) == 0) { +@@ -635,9 +627,8 @@ + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (this.isScared()) { + return InteractionResult.PASS; +@@ -650,10 +641,10 @@ + } + + if (this.isBaby()) { +- this.usePlayerItem(player, interactionhand, itemstack); ++ this.usePlayerItem(player, hand, itemstack); + this.ageUp((int) ((float) (-this.getAge() / 20) * 0.1F), true); + } else if (!this.level().isClientSide && this.getAge() == 0 && this.canFallInLove()) { +- this.usePlayerItem(player, interactionhand, itemstack); ++ this.usePlayerItem(player, hand, itemstack); + this.setInLove(player); + } else { + if (this.level().isClientSide || this.isSitting() || this.isInWater()) { +@@ -669,7 +660,7 @@ + } + + this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(itemstack.getItem(), 1)); +- this.usePlayerItem(player, interactionhand, itemstack); ++ this.usePlayerItem(player, hand, itemstack); + } + + return InteractionResult.SUCCESS; +@@ -680,38 +671,33 @@ + + @Nullable + @Override +- @Override + protected SoundEvent getAmbientSound() { + return this.isAggressive() ? SoundEvents.PANDA_AGGRESSIVE_AMBIENT : (this.isWorried() ? SoundEvents.PANDA_WORRIED_AMBIENT : SoundEvents.PANDA_AMBIENT); + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.PANDA_STEP, 0.15F, 1.0F); + } + + @Override +- @Override +- public boolean isFood(ItemStack itemstack) { +- return itemstack.is(Blocks.BAMBOO.asItem()); ++ public boolean isFood(ItemStack stack) { ++ return stack.is(Blocks.BAMBOO.asItem()); + } + +- private boolean isFoodOrCake(ItemStack itemstack) { +- return this.isFood(itemstack) || itemstack.is(Blocks.CAKE.asItem()); ++ private boolean isFoodOrCake(ItemStack stack) { ++ return this.isFood(stack) || stack.is(Blocks.CAKE.asItem()); + } + + @Nullable + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.PANDA_DEATH; + } + + @Nullable + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.PANDA_HURT; + } + +@@ -720,9 +706,8 @@ + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height - (this.isBaby() ? 0.4375F : 0.0F) * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - (this.isBaby() ? 0.4375F : 0.0F) * f, 0.0F); + } + + private static class PandaMoveControl extends MoveControl { +@@ -735,7 +720,6 @@ + } + + @Override +- @Override + public void tick() { + if (this.panda.canPerformAction()) { + super.tick(); +@@ -748,7 +732,7 @@ + NORMAL(0, "normal", false), LAZY(1, "lazy", false), WORRIED(2, "worried", false), PLAYFUL(3, "playful", false), BROWN(4, "brown", true), WEAK(5, "weak", true), AGGRESSIVE(6, "aggressive", false); + + public static final StringRepresentable.EnumCodec CODEC = StringRepresentable.fromEnum(Panda.Gene::values); +- private static final IntFunction BY_ID = ByIdMap.continuous(Panda.Gene::getId, values(), ByIdMap.OutOfBoundsStrategy.ZERO); ++ private static final IntFunction BY_ID = ByIdMap.continuous(Panda.Gene::getId, values(), ByIdMap.a.ZERO); + private static final int MAX_GENE = 6; + private final int id; + private final String name; +@@ -765,7 +749,6 @@ + } + + @Override +- @Override + public String getSerializedName() { + return this.name; + } +@@ -774,20 +757,20 @@ + return this.isRecessive; + } + +- static Panda.Gene getVariantFromGenes(Panda.Gene panda_gene, Panda.Gene panda_gene1) { +- return panda_gene.isRecessive() ? (panda_gene == panda_gene1 ? panda_gene : Panda.Gene.NORMAL) : panda_gene; ++ static Panda.Gene getVariantFromGenes(Panda.Gene mainGene, Panda.Gene hiddenGene) { ++ return mainGene.isRecessive() ? (mainGene == hiddenGene ? mainGene : Panda.Gene.NORMAL) : mainGene; + } + +- public static Panda.Gene byId(int i) { +- return (Panda.Gene) Panda.Gene.BY_ID.apply(i); ++ public static Panda.Gene byId(int index) { ++ return (Panda.Gene) Panda.Gene.BY_ID.apply(index); + } + +- public static Panda.Gene byName(String s) { +- return (Panda.Gene) Panda.Gene.CODEC.byName(s, Panda.Gene.NORMAL); ++ public static Panda.Gene byName(String name) { ++ return (Panda.Gene) Panda.Gene.CODEC.byName(name, Panda.Gene.NORMAL); + } + +- public static Panda.Gene getRandom(RandomSource randomsource) { +- int i = randomsource.nextInt(16); ++ public static Panda.Gene getRandom(RandomSource random) { ++ int i = random.nextInt(16); + + return i == 0 ? Panda.Gene.LAZY : (i == 1 ? Panda.Gene.WORRIED : (i == 2 ? Panda.Gene.PLAYFUL : (i == 4 ? Panda.Gene.AGGRESSIVE : (i < 9 ? Panda.Gene.WEAK : (i < 11 ? Panda.Gene.BROWN : Panda.Gene.NORMAL))))); + } +@@ -797,19 +780,17 @@ + + private final Panda panda; + +- public PandaPanicGoal(Panda panda, double d0) { +- super(panda, d0); ++ public PandaPanicGoal(Panda panda, double speedModifier) { ++ super(panda, speedModifier); + this.panda = panda; + } + + @Override +- @Override + protected boolean shouldPanic() { + return this.mob.isFreezing() || this.mob.isOnFire(); + } + + @Override +- @Override + public boolean canContinueToUse() { + if (this.panda.isSitting()) { + this.panda.getNavigation().stop(); +@@ -825,13 +806,12 @@ + private final Panda panda; + private int unhappyCooldown; + +- public PandaBreedGoal(Panda panda, double d0) { +- super(panda, d0); ++ public PandaBreedGoal(Panda panda, double speedModifier) { ++ super(panda, speedModifier); + this.panda = panda; + } + + @Override +- @Override + public boolean canUse() { + if (super.canUse() && this.panda.getUnhappyCounter() == 0) { + if (!this.canFindBamboo()) { +@@ -839,9 +819,9 @@ + this.panda.setUnhappyCounter(32); + this.unhappyCooldown = this.panda.tickCount + 600; + if (this.panda.isEffectiveAi()) { +- Player player = this.level.getNearestPlayer(Panda.BREED_TARGETING, this.panda); ++ Player entityhuman = this.level.getNearestPlayer(Panda.BREED_TARGETING, this.panda); + +- this.panda.lookAtPlayerGoal.setTarget(player); ++ this.panda.lookAtPlayerGoal.setTarget(entityhuman); + } + } + +@@ -855,15 +835,15 @@ + } + + private boolean canFindBamboo() { +- BlockPos blockpos = this.panda.blockPosition(); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ BlockPos blockposition = this.panda.blockPosition(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 8; ++j) { + for (int k = 0; k <= j; k = k > 0 ? -k : 1 - k) { + for (int l = k < j && k > -j ? j : 0; l <= j; l = l > 0 ? -l : 1 - l) { +- blockpos_mutableblockpos.setWithOffset(blockpos, k, i, l); +- if (this.level.getBlockState(blockpos_mutableblockpos).is(Blocks.BAMBOO)) { ++ blockposition_mutableblockposition.setWithOffset(blockposition, k, i, l); ++ if (this.level.getBlockState(blockposition_mutableblockposition).is(Blocks.BAMBOO)) { + return true; + } + } +@@ -879,13 +859,12 @@ + + private final Panda panda; + +- public PandaAttackGoal(Panda panda, double d0, boolean flag) { +- super(panda, d0, flag); ++ public PandaAttackGoal(Panda panda, double speedModifier, boolean flag) { ++ super(panda, speedModifier, flag); + this.panda = panda; + } + + @Override +- @Override + public boolean canUse() { + return this.panda.canPerformAction() && super.canUse(); + } +@@ -895,16 +874,15 @@ + + private final Panda panda; + +- public PandaAvoidGoal(Panda panda, Class oclass, float f, double d0, double d1) { +- Predicate predicate = EntitySelector.NO_SPECTATORS; ++ public PandaAvoidGoal(Panda panda, Class entityClassToAvoid, float maxDist, double walkSpeedModifier, double d1) { ++ // Predicate predicate = IEntitySelector.NO_SPECTATORS; + +- Objects.requireNonNull(predicate); +- super(panda, oclass, f, d0, d1, predicate::test); ++ // Objects.requireNonNull(predicate); ++ super(panda, entityClassToAvoid, maxDist, walkSpeedModifier, d1, EntitySelector.NO_SPECTATORS::test); + this.panda = panda; + } + + @Override +- @Override + public boolean canUse() { + return this.panda.isWorried() && this.panda.canPerformAction() && super.canUse(); + } +@@ -915,11 +893,10 @@ + private int cooldown; + + public PandaSitGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +- @Override + public boolean canUse() { + if (this.cooldown <= Panda.this.tickCount && !Panda.this.isBaby() && !Panda.this.isInWater() && Panda.this.canPerformAction() && Panda.this.getUnhappyCounter() <= 0) { + List list = Panda.this.level().getEntitiesOfClass(ItemEntity.class, Panda.this.getBoundingBox().inflate(6.0D, 6.0D, 6.0D), Panda.PANDA_ITEMS); +@@ -931,13 +908,11 @@ + } + + @Override +- @Override + public boolean canContinueToUse() { + return !Panda.this.isInWater() && (Panda.this.isLazy() || Panda.this.random.nextInt(reducedTickDelay(600)) != 1) ? Panda.this.random.nextInt(reducedTickDelay(2000)) != 1 : false; + } + + @Override +- @Override + public void tick() { + if (!Panda.this.isSitting() && !Panda.this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty()) { + Panda.this.tryToSit(); +@@ -946,7 +921,6 @@ + } + + @Override +- @Override + public void start() { + List list = Panda.this.level().getEntitiesOfClass(ItemEntity.class, Panda.this.getBoundingBox().inflate(8.0D, 8.0D, 8.0D), Panda.PANDA_ITEMS); + +@@ -960,7 +934,6 @@ + } + + @Override +- @Override + public void stop() { + ItemStack itemstack = Panda.this.getItemBySlot(EquipmentSlot.MAINHAND); + +@@ -986,26 +959,22 @@ + } + + @Override +- @Override + public boolean canUse() { + return this.cooldown < this.panda.tickCount && this.panda.isLazy() && this.panda.canPerformAction() && this.panda.random.nextInt(reducedTickDelay(400)) == 1; + } + + @Override +- @Override + public boolean canContinueToUse() { + return !this.panda.isInWater() && (this.panda.isLazy() || this.panda.random.nextInt(reducedTickDelay(600)) != 1) ? this.panda.random.nextInt(reducedTickDelay(2000)) != 1 : false; + } + + @Override +- @Override + public void start() { + this.panda.setOnBack(true); + this.cooldown = 0; + } + + @Override +- @Override + public void stop() { + this.panda.setOnBack(false); + this.cooldown = this.panda.tickCount + 200; +@@ -1021,19 +990,16 @@ + } + + @Override +- @Override + public boolean canUse() { + return this.panda.isBaby() && this.panda.canPerformAction() ? (this.panda.isWeak() && this.panda.random.nextInt(reducedTickDelay(500)) == 1 ? true : this.panda.random.nextInt(reducedTickDelay(6000)) == 1) : false; + } + + @Override +- @Override + public boolean canContinueToUse() { + return false; + } + + @Override +- @Override + public void start() { + this.panda.sneeze(true); + } +@@ -1043,23 +1009,21 @@ + + private final Panda panda; + +- public PandaLookAtPlayerGoal(Panda panda, Class oclass, float f) { +- super(panda, oclass, f); ++ public PandaLookAtPlayerGoal(Panda panda, Class lookAtType, float lookDistance) { ++ super(panda, lookAtType, lookDistance); + this.panda = panda; + } + +- public void setTarget(LivingEntity livingentity) { +- this.lookAt = livingentity; ++ public void setTarget(LivingEntity lookAt) { ++ this.lookAt = lookAt; + } + + @Override +- @Override + public boolean canContinueToUse() { + return this.lookAt != null && super.canContinueToUse(); + } + + @Override +- @Override + public boolean canUse() { + if (this.mob.getRandom().nextFloat() >= this.probability) { + return false; +@@ -1068,7 +1032,7 @@ + if (this.lookAtType == Player.class) { + this.lookAt = this.mob.level().getNearestPlayer(this.lookAtContext, this.mob, this.mob.getX(), this.mob.getEyeY(), this.mob.getZ()); + } else { +- this.lookAt = this.mob.level().getNearestEntity(this.mob.level().getEntitiesOfClass(this.lookAtType, this.mob.getBoundingBox().inflate((double) this.lookDistance, 3.0D, (double) this.lookDistance), (livingentity) -> { ++ this.lookAt = this.mob.level().getNearestEntity(this.mob.level().getEntitiesOfClass(this.lookAtType, this.mob.getBoundingBox().inflate((double) this.lookDistance, 3.0D, (double) this.lookDistance), (entityliving) -> { + return true; + }), this.lookAtContext, this.mob, this.mob.getX(), this.mob.getEyeY(), this.mob.getZ()); + } +@@ -1079,7 +1043,6 @@ + } + + @Override +- @Override + public void tick() { + if (this.lookAt != null) { + super.tick(); +@@ -1094,11 +1057,10 @@ + + public PandaRollGoal(Panda panda) { + this.panda = panda; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK, Goal.Flag.JUMP)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK, Goal.Type.JUMP)); + } + + @Override +- @Override + public boolean canUse() { + if ((this.panda.isBaby() || this.panda.isPlayful()) && this.panda.onGround()) { + if (!this.panda.canPerformAction()) { +@@ -1118,19 +1080,16 @@ + } + + @Override +- @Override + public boolean canContinueToUse() { + return false; + } + + @Override +- @Override + public void start() { + this.panda.roll(true); + } + + @Override +- @Override + public boolean isInterruptable() { + return false; + } +@@ -1140,13 +1099,12 @@ + + private final Panda panda; + +- public PandaHurtByTargetGoal(Panda panda, Class... aclass) { +- super(panda, aclass); ++ public PandaHurtByTargetGoal(Panda panda, Class... entityClassToIgnoreDamage) { ++ super(panda, entityClassToIgnoreDamage); + this.panda = panda; + } + + @Override +- @Override + public boolean canContinueToUse() { + if (!this.panda.gotBamboo && !this.panda.didBite) { + return super.canContinueToUse(); +@@ -1157,10 +1115,9 @@ + } + + @Override +- @Override +- protected void alertOther(Mob mob, LivingEntity livingentity) { ++ protected void alertOther(Mob mob, LivingEntity target) { + if (mob instanceof Panda && mob.isAggressive()) { +- mob.setTarget(livingentity); ++ mob.setTarget(target, EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY, true); // CraftBukkit + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Parrot.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Parrot.java.patch new file mode 100644 index 0000000000..425ef5d4fa --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Parrot.java.patch @@ -0,0 +1,525 @@ +--- a/net/minecraft/world/entity/animal/Parrot.java ++++ b/net/minecraft/world/entity/animal/Parrot.java +@@ -29,7 +29,7 @@ + import net.minecraft.util.StringRepresentable; + import net.minecraft.world.Difficulty; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffectInstance; +@@ -37,12 +37,12 @@ + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.PathfinderMob; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.VariantHolder; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -53,8 +53,8 @@ + import net.minecraft.world.entity.ai.goal.LandOnOwnersShoulderGoal; + import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; + import net.minecraft.world.entity.ai.goal.PanicGoal; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalRandomFly; + import net.minecraft.world.entity.ai.goal.SitWhenOrderedToGoal; +-import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomFlyingGoal; + import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation; + import net.minecraft.world.entity.ai.navigation.PathNavigation; + import net.minecraft.world.entity.ai.util.LandRandomPos; +@@ -67,16 +67,15 @@ + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.LeavesBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Parrot extends ShoulderRidingEntity implements VariantHolder, FlyingAnimal { ++public class Parrot extends ShoulderRidingEntity implements VariantHolder, EntityBird { + + private static final EntityDataAccessor DATA_VARIANT_ID = SynchedEntityData.defineId(Parrot.class, EntityDataSerializers.INT); + private static final Predicate NOT_PARROT_PREDICATE = new Predicate() { +- @Override + public boolean test(@Nullable Mob mob) { + return mob != null && Parrot.MOB_SOUND_MAP.containsKey(mob.getType()); + } +@@ -130,8 +129,8 @@ + @Nullable + private BlockPos jukebox; + +- public Parrot(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Parrot(EntityType entityType, Level level) { ++ super(entityType, level); + this.moveControl = new FlyingMoveControl(this, 10, false); + this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F); + this.setPathfindingMalus(BlockPathTypes.DAMAGE_FIRE, -1.0F); +@@ -140,31 +139,28 @@ + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- this.setVariant((Parrot.Variant) Util.getRandom((Object[]) Parrot.Variant.values(), serverlevelaccessor.getRandom())); +- if (spawngroupdata == null) { +- spawngroupdata = new AgeableMob.AgeableMobGroupData(false); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ this.setVariant((Parrot.Variant) Util.getRandom((Object[]) Parrot.Variant.values(), level.getRandom())); ++ if (spawnData == null) { ++ spawnData = new AgeableMob.AgeableMobGroupData(false); + } + +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, (SpawnGroupData) spawngroupdata, compoundtag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + + @Override +- @Override + public boolean isBaby() { + return false; + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new PanicGoal(this, 1.25D)); + this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(1, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this)); + this.goalSelector.addGoal(2, new FollowOwnerGoal(this, 1.0D, 5.0F, 1.0F, true)); +- this.goalSelector.addGoal(2, new Parrot.ParrotWanderGoal(this, 1.0D)); ++ this.goalSelector.addGoal(2, new Parrot.a(this, 1.0D)); + this.goalSelector.addGoal(3, new LandOnOwnersShoulderGoal(this)); + this.goalSelector.addGoal(3, new FollowMobGoal(this, 1.0D, 3.0F, 7.0F)); + } +@@ -174,24 +170,21 @@ + } + + @Override +- @Override + protected PathNavigation createNavigation(Level level) { +- FlyingPathNavigation flyingpathnavigation = new FlyingPathNavigation(this, level); ++ FlyingPathNavigation navigationflying = new FlyingPathNavigation(this, level); + +- flyingpathnavigation.setCanOpenDoors(false); +- flyingpathnavigation.setCanFloat(true); +- flyingpathnavigation.setCanPassDoors(true); +- return flyingpathnavigation; ++ navigationflying.setCanOpenDoors(false); ++ navigationflying.setCanFloat(true); ++ navigationflying.setCanPassDoors(true); ++ return navigationflying; + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return entitydimensions.height * 0.6F; ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { ++ return size.height * 0.6F; + } + + @Override +- @Override + public void aiStep() { + if (this.jukebox == null || !this.jukebox.closerToCenterThan(this.position(), 3.46D) || !this.level().getBlockState(this.jukebox).is(Blocks.JUKEBOX)) { + this.partyParrot = false; +@@ -207,10 +200,9 @@ + } + + @Override +- @Override +- public void setRecordPlayingNearby(BlockPos blockpos, boolean flag) { +- this.jukebox = blockpos; +- this.partyParrot = flag; ++ public void setRecordPlayingNearby(BlockPos pos, boolean isPartying) { ++ this.jukebox = pos; ++ this.partyParrot = isPartying; + } + + public boolean isPartyParrot() { +@@ -227,26 +219,26 @@ + } + + this.flapping *= 0.9F; +- Vec3 vec3 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + +- if (!this.onGround() && vec3.y < 0.0D) { +- this.setDeltaMovement(vec3.multiply(1.0D, 0.6D, 1.0D)); ++ if (!this.onGround() && vec3d.y < 0.0D) { ++ this.setDeltaMovement(vec3d.multiply(1.0D, 0.6D, 1.0D)); + } + + this.flap += this.flapping * 2.0F; + } + +- public static boolean imitateNearbyMobs(Level level, Entity entity) { +- if (entity.isAlive() && !entity.isSilent() && level.random.nextInt(2) == 0) { +- List list = level.getEntitiesOfClass(Mob.class, entity.getBoundingBox().inflate(20.0D), Parrot.NOT_PARROT_PREDICATE); ++ public static boolean imitateNearbyMobs(Level level, Entity parrot) { ++ if (parrot.isAlive() && !parrot.isSilent() && level.random.nextInt(2) == 0) { ++ List list = level.getEntitiesOfClass(Mob.class, parrot.getBoundingBox().inflate(20.0D), Parrot.NOT_PARROT_PREDICATE); + + if (!list.isEmpty()) { +- Mob mob = (Mob) list.get(level.random.nextInt(list.size())); ++ Mob entityinsentient = (Mob) list.get(level.random.nextInt(list.size())); + +- if (!mob.isSilent()) { +- SoundEvent soundevent = getImitatedSound(mob.getType()); ++ if (!entityinsentient.isSilent()) { ++ SoundEvent soundeffect = getImitatedSound(entityinsentient.getType()); + +- level.playSound((Player) null, entity.getX(), entity.getY(), entity.getZ(), soundevent, entity.getSoundSource(), 0.7F, getPitch(level.random)); ++ level.playSound((Player) null, parrot.getX(), parrot.getY(), parrot.getZ(), soundeffect, parrot.getSoundSource(), 0.7F, getPitch(level.random)); + return true; + } + } +@@ -258,9 +250,8 @@ + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (!this.isTame() && Parrot.TAME_FOOD.contains(itemstack.getItem())) { + if (!player.getAbilities().instabuild) { +@@ -272,7 +263,7 @@ + } + + if (!this.level().isClientSide) { +- if (this.random.nextInt(10) == 0) { ++ if (this.random.nextInt(10) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit + this.tame(player); + this.level().broadcastEntityEvent(this, (byte) 7); + } else { +@@ -286,7 +277,7 @@ + itemstack.shrink(1); + } + +- this.addEffect(new MobEffectInstance(MobEffects.POISON, 900)); ++ this.addEffect(new MobEffectInstance(MobEffects.POISON, 900), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.FOOD); // CraftBukkit + if (player.isCreative() || !this.isInvulnerable()) { + this.hurt(this.damageSources().playerAttack(player), Float.MAX_VALUE); + } +@@ -299,119 +290,104 @@ + + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { +- return super.mobInteract(player, interactionhand); ++ return super.mobInteract(player, hand); + } + } + + @Override +- @Override +- public boolean isFood(ItemStack itemstack) { ++ public boolean isFood(ItemStack stack) { + return false; + } + +- public static boolean checkParrotSpawnRules(EntityType entitytype, LevelAccessor levelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- return levelaccessor.getBlockState(blockpos.below()).is(BlockTags.PARROTS_SPAWNABLE_ON) && isBrightEnoughToSpawn(levelaccessor, blockpos); ++ public static boolean checkParrotSpawnRules(EntityType parrot, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ return level.getBlockState(pos.below()).is(BlockTags.PARROTS_SPAWNABLE_ON) && isBrightEnoughToSpawn(level, pos); + } + + @Override +- @Override +- protected void checkFallDamage(double d0, boolean flag, BlockState blockstate, BlockPos blockpos) {} ++ protected void checkFallDamage(double y, boolean flag, IBlockData onGround, BlockPos state) {} + + @Override +- @Override +- public boolean canMate(Animal animal) { ++ public boolean canMate(Animal otherAnimal) { + return false; + } + + @Nullable + @Override +- @Override +- public AgeableMob getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { ++ public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob otherParent) { + return null; + } + + @Override +- @Override + public boolean doHurtTarget(Entity entity) { + return entity.hurt(this.damageSources().mobAttack(this), 3.0F); + } + + @Nullable + @Override +- @Override + public SoundEvent getAmbientSound() { + return getAmbient(this.level(), this.level().random); + } + +- public static SoundEvent getAmbient(Level level, RandomSource randomsource) { +- if (level.getDifficulty() != Difficulty.PEACEFUL && randomsource.nextInt(1000) == 0) { ++ public static SoundEvent getAmbient(Level level, RandomSource random) { ++ if (level.getDifficulty() != Difficulty.PEACEFUL && random.nextInt(1000) == 0) { + List> list = Lists.newArrayList(Parrot.MOB_SOUND_MAP.keySet()); + +- return getImitatedSound((EntityType) list.get(randomsource.nextInt(list.size()))); ++ return getImitatedSound((EntityType) list.get(random.nextInt(list.size()))); + } else { + return SoundEvents.PARROT_AMBIENT; + } + } + +- private static SoundEvent getImitatedSound(EntityType entitytype) { +- return (SoundEvent) Parrot.MOB_SOUND_MAP.getOrDefault(entitytype, SoundEvents.PARROT_AMBIENT); ++ private static SoundEvent getImitatedSound(EntityType type) { ++ return (SoundEvent) Parrot.MOB_SOUND_MAP.getOrDefault(type, SoundEvents.PARROT_AMBIENT); + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.PARROT_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.PARROT_DEATH; + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.PARROT_STEP, 0.15F, 1.0F); + } + + @Override +- @Override + protected boolean isFlapping() { + return this.flyDist > this.nextFlap; + } + + @Override +- @Override + protected void onFlap() { + this.playSound(SoundEvents.PARROT_FLY, 0.15F, 1.0F); + this.nextFlap = this.flyDist + this.flapSpeed / 2.0F; + } + + @Override +- @Override + public float getVoicePitch() { + return getPitch(this.random); + } + +- public static float getPitch(RandomSource randomsource) { +- return (randomsource.nextFloat() - randomsource.nextFloat()) * 0.2F + 1.0F; ++ public static float getPitch(RandomSource random) { ++ return (random.nextFloat() - random.nextFloat()) * 0.2F + 1.0F; + } + + @Override +- @Override + public SoundSource getSoundSource() { + return SoundSource.NEUTRAL; + } + + @Override +- @Override + public boolean isPushable() { +- return true; ++ return super.isPushable(); // CraftBukkit - collidable API + } + + @Override +- @Override + protected void doPush(Entity entity) { + if (!(entity instanceof Player)) { + super.doPush(entity); +@@ -419,67 +395,61 @@ + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- if (this.isInvulnerableTo(damagesource)) { ++ public boolean hurt(DamageSource source, float amount) { ++ if (this.isInvulnerableTo(source)) { + return false; + } else { +- if (!this.level().isClientSide) { ++ // CraftBukkit start ++ boolean result = super.hurt(source, amount); ++ if (!this.level().isClientSide && result) { ++ // CraftBukkit end + this.setOrderedToSit(false); + } + +- return super.hurt(damagesource, f); ++ return result; // CraftBukkit + } + } + + @Override +- @Override + public Parrot.Variant getVariant() { + return Parrot.Variant.byId((Integer) this.entityData.get(Parrot.DATA_VARIANT_ID)); + } + +- @Override +- public void setVariant(Parrot.Variant parrot_variant) { +- this.entityData.set(Parrot.DATA_VARIANT_ID, parrot_variant.id); ++ public void setVariant(Parrot.Variant variant) { ++ this.entityData.set(Parrot.DATA_VARIANT_ID, variant.id); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Parrot.DATA_VARIANT_ID, 0); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("Variant", this.getVariant().id); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("Variant", this.getVariant().id); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setVariant(Parrot.Variant.byId(compoundtag.getInt("Variant"))); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setVariant(Parrot.Variant.byId(compound.getInt("Variant"))); + } + + @Override +- @Override + public boolean isFlying() { + return !this.onGround(); + } + + @Override +- @Override + public Vec3 getLeashOffset() { + return new Vec3(0.0D, (double) (0.5F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height - 0.4375F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.4375F * f, 0.0F); + } + + public static enum Variant implements StringRepresentable { +@@ -487,7 +457,7 @@ + RED_BLUE(0, "red_blue"), BLUE(1, "blue"), GREEN(2, "green"), YELLOW_BLUE(3, "yellow_blue"), GRAY(4, "gray"); + + public static final Codec CODEC = StringRepresentable.fromEnum(Parrot.Variant::values); +- private static final IntFunction BY_ID = ByIdMap.continuous(Parrot.Variant::getId, values(), ByIdMap.OutOfBoundsStrategy.CLAMP); ++ private static final IntFunction BY_ID = ByIdMap.continuous(Parrot.Variant::getId, values(), ByIdMap.a.CLAMP); + final int id; + private final String name; + +@@ -500,57 +470,55 @@ + return this.id; + } + +- public static Parrot.Variant byId(int i) { +- return (Parrot.Variant) Parrot.Variant.BY_ID.apply(i); ++ public static Parrot.Variant byId(int id) { ++ return (Parrot.Variant) Parrot.Variant.BY_ID.apply(id); + } + + @Override +- @Override + public String getSerializedName() { + return this.name; + } + } + +- private static class ParrotWanderGoal extends WaterAvoidingRandomFlyingGoal { ++ private static class a extends PathfinderGoalRandomFly { + +- public ParrotWanderGoal(PathfinderMob pathfindermob, double d0) { +- super(pathfindermob, d0); ++ public a(PathfinderMob mob, double speedModifier) { ++ super(mob, speedModifier); + } + + @Nullable + @Override +- @Override + protected Vec3 getPosition() { +- Vec3 vec3 = null; ++ Vec3 vec3d = null; + + if (this.mob.isInWater()) { +- vec3 = LandRandomPos.getPos(this.mob, 15, 15); ++ vec3d = LandRandomPos.getPos(this.mob, 15, 15); + } + + if (this.mob.getRandom().nextFloat() >= this.probability) { +- vec3 = this.getTreePos(); ++ vec3d = this.getTreePos(); + } + +- return vec3 == null ? super.getPosition() : vec3; ++ return vec3d == null ? super.getPosition() : vec3d; + } + + @Nullable + private Vec3 getTreePos() { +- BlockPos blockpos = this.mob.blockPosition(); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); +- BlockPos.MutableBlockPos blockpos_mutableblockpos1 = new BlockPos.MutableBlockPos(); ++ BlockPos blockposition = this.mob.blockPosition(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition1 = new BlockPos.MutableBlockPos(); + Iterable iterable = BlockPos.betweenClosed(Mth.floor(this.mob.getX() - 3.0D), Mth.floor(this.mob.getY() - 6.0D), Mth.floor(this.mob.getZ() - 3.0D), Mth.floor(this.mob.getX() + 3.0D), Mth.floor(this.mob.getY() + 6.0D), Mth.floor(this.mob.getZ() + 3.0D)); + Iterator iterator = iterable.iterator(); + + while (iterator.hasNext()) { +- BlockPos blockpos1 = (BlockPos) iterator.next(); ++ BlockPos blockposition1 = (BlockPos) iterator.next(); + +- if (!blockpos.equals(blockpos1)) { +- BlockState blockstate = this.mob.level().getBlockState(blockpos_mutableblockpos1.setWithOffset(blockpos1, Direction.DOWN)); +- boolean flag = blockstate.getBlock() instanceof LeavesBlock || blockstate.is(BlockTags.LOGS); ++ if (!blockposition.equals(blockposition1)) { ++ IBlockData iblockdata = this.mob.level().getBlockState(blockposition_mutableblockposition1.setWithOffset(blockposition1, Direction.DOWN)); ++ boolean flag = iblockdata.getBlock() instanceof LeavesBlock || iblockdata.is(BlockTags.LOGS); + +- if (flag && this.mob.level().isEmptyBlock(blockpos1) && this.mob.level().isEmptyBlock(blockpos_mutableblockpos.setWithOffset(blockpos1, Direction.UP))) { +- return Vec3.atBottomCenterOf(blockpos1); ++ if (flag && this.mob.level().isEmptyBlock(blockposition1) && this.mob.level().isEmptyBlock(blockposition_mutableblockposition.setWithOffset(blockposition1, Direction.UP))) { ++ return Vec3.atBottomCenterOf(blockposition1); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Pig.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Pig.java.patch new file mode 100644 index 0000000000..760608d1fa --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Pig.java.patch @@ -0,0 +1,386 @@ +--- a/net/minecraft/world/entity/animal/Pig.java ++++ b/net/minecraft/world/entity/animal/Pig.java +@@ -13,20 +13,20 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.Difficulty; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.ISteerable; + import net.minecraft.world.entity.ItemBasedSteering; +-import net.minecraft.world.entity.ItemSteerable; + import net.minecraft.world.entity.LightningBolt; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.Saddleable; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -44,27 +44,30 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.item.crafting.Ingredient; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Pig extends Animal implements ItemSteerable, Saddleable { ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + ++public class Pig extends Animal implements ISteerable, Saddleable { ++ + private static final EntityDataAccessor DATA_SADDLE_ID = SynchedEntityData.defineId(Pig.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_BOOST_TIME = SynchedEntityData.defineId(Pig.class, EntityDataSerializers.INT); + private static final Ingredient FOOD_ITEMS = Ingredient.of(Items.CARROT, Items.POTATO, Items.BEETROOT); +- private final ItemBasedSteering steering; ++ public final ItemBasedSteering steering; + +- public Pig(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Pig(EntityType entityType, Level level) { ++ super(entityType, level); + this.steering = new ItemBasedSteering(this.entityData, Pig.DATA_BOOST_TIME, Pig.DATA_SADDLE_ID); + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(1, new PanicGoal(this, 1.25D)); +@@ -83,16 +86,15 @@ + + @Nullable + @Override +- @Override + public LivingEntity getControllingPassenger() { + if (this.isSaddled()) { + Entity entity = this.getFirstPassenger(); + + if (entity instanceof Player) { +- Player player = (Player) entity; ++ Player entityhuman = (Player) entity; + +- if (player.isHolding(Items.CARROT_ON_A_STICK)) { +- return player; ++ if (entityhuman.isHolding(Items.CARROT_ON_A_STICK)) { ++ return entityhuman; + } + } + } +@@ -101,17 +103,15 @@ + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- if (Pig.DATA_BOOST_TIME.equals(entitydataaccessor) && this.level().isClientSide) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ if (Pig.DATA_BOOST_TIME.equals(key) && this.level().isClientSide) { + this.steering.onSynced(); + } + +- super.onSyncedDataUpdated(entitydataaccessor); ++ super.onSyncedDataUpdated(key); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Pig.DATA_SADDLE_ID, false); +@@ -119,47 +119,40 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- this.steering.addAdditionalSaveData(compoundtag); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ this.steering.addAdditionalSaveData(compound); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.steering.readAdditionalSaveData(compoundtag); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.steering.readAdditionalSaveData(compound); + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.PIG_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.PIG_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.PIG_DEATH; + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.PIG_STEP, 0.15F, 1.0F); + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- boolean flag = this.isFood(player.getItemInHand(interactionhand)); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ boolean flag = this.isFood(player.getItemInHand(hand)); + + if (!flag && this.isSaddled() && !this.isVehicle() && !player.isSecondaryUseActive()) { + if (!this.level().isClientSide) { +@@ -168,167 +161,159 @@ + + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { +- InteractionResult interactionresult = super.mobInteract(player, interactionhand); ++ InteractionResult enuminteractionresult = super.mobInteract(player, hand); + +- if (!interactionresult.consumesAction()) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ if (!enuminteractionresult.consumesAction()) { ++ ItemStack itemstack = player.getItemInHand(hand); + +- return itemstack.is(Items.SADDLE) ? itemstack.interactLivingEntity(player, this, interactionhand) : InteractionResult.PASS; ++ return itemstack.is(Items.SADDLE) ? itemstack.interactLivingEntity(player, this, hand) : InteractionResult.PASS; + } else { +- return interactionresult; ++ return enuminteractionresult; + } + } + } + + @Override +- @Override + public boolean isSaddleable() { + return this.isAlive() && !this.isBaby(); + } + + @Override +- @Override + protected void dropEquipment() { + super.dropEquipment(); + if (this.isSaddled()) { +- this.spawnAtLocation((ItemLike) Items.SADDLE); ++ this.spawnAtLocation((IMaterial) Items.SADDLE); + } + + } + + @Override +- @Override + public boolean isSaddled() { + return this.steering.hasSaddle(); + } + + @Override +- @Override +- public void equipSaddle(@Nullable SoundSource soundsource) { ++ public void equipSaddle(@Nullable SoundSource source) { + this.steering.setSaddle(true); +- if (soundsource != null) { +- this.level().playSound((Player) null, (Entity) this, SoundEvents.PIG_SADDLE, soundsource, 0.5F, 1.0F); ++ if (source != null) { ++ this.level().playSound((Player) null, (Entity) this, SoundEvents.PIG_SADDLE, source, 0.5F, 1.0F); + } + + } + + @Override +- @Override +- public Vec3 getDismountLocationForPassenger(LivingEntity livingentity) { +- Direction direction = this.getMotionDirection(); ++ public Vec3 getDismountLocationForPassenger(LivingEntity livingEntity) { ++ Direction enumdirection = this.getMotionDirection(); + +- if (direction.getAxis() == Direction.Axis.Y) { +- return super.getDismountLocationForPassenger(livingentity); ++ if (enumdirection.getAxis() == Direction.Axis.Y) { ++ return super.getDismountLocationForPassenger(livingEntity); + } else { +- int[][] aint = DismountHelper.offsetsForDirection(direction); +- BlockPos blockpos = this.blockPosition(); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); +- UnmodifiableIterator unmodifiableiterator = livingentity.getDismountPoses().iterator(); ++ int[][] aint = DismountHelper.offsetsForDirection(enumdirection); ++ BlockPos blockposition = this.blockPosition(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ UnmodifiableIterator unmodifiableiterator = livingEntity.getDismountPoses().iterator(); + + while (unmodifiableiterator.hasNext()) { +- Pose pose = (Pose) unmodifiableiterator.next(); +- AABB aabb = livingentity.getLocalBoundsForPose(pose); ++ EntityPose entitypose = (EntityPose) unmodifiableiterator.next(); ++ AABB axisalignedbb = livingEntity.getLocalBoundsForPose(entitypose); + int[][] aint1 = aint; + int i = aint.length; + + for (int j = 0; j < i; ++j) { + int[] aint2 = aint1[j]; + +- blockpos_mutableblockpos.set(blockpos.getX() + aint2[0], blockpos.getY(), blockpos.getZ() + aint2[1]); +- double d0 = this.level().getBlockFloorHeight(blockpos_mutableblockpos); ++ blockposition_mutableblockposition.set(blockposition.getX() + aint2[0], blockposition.getY(), blockposition.getZ() + aint2[1]); ++ double d0 = this.level().getBlockFloorHeight(blockposition_mutableblockposition); + + if (DismountHelper.isBlockFloorValid(d0)) { +- Vec3 vec3 = Vec3.upFromBottomCenterOf(blockpos_mutableblockpos, d0); ++ Vec3 vec3d = Vec3.upFromBottomCenterOf(blockposition_mutableblockposition, d0); + +- if (DismountHelper.canDismountTo(this.level(), livingentity, aabb.move(vec3))) { +- livingentity.setPose(pose); +- return vec3; ++ if (DismountHelper.canDismountTo(this.level(), livingEntity, axisalignedbb.move(vec3d))) { ++ livingEntity.setPose(entitypose); ++ return vec3d; + } + } + } + } + +- return super.getDismountLocationForPassenger(livingentity); ++ return super.getDismountLocationForPassenger(livingEntity); + } + } + + @Override +- @Override +- public void thunderHit(ServerLevel serverlevel, LightningBolt lightningbolt) { +- if (serverlevel.getDifficulty() != Difficulty.PEACEFUL) { +- ZombifiedPiglin zombifiedpiglin = (ZombifiedPiglin) EntityType.ZOMBIFIED_PIGLIN.create(serverlevel); ++ public void thunderHit(ServerLevel level, LightningBolt lightning) { ++ if (level.getDifficulty() != Difficulty.PEACEFUL) { ++ ZombifiedPiglin entitypigzombie = (ZombifiedPiglin) EntityType.ZOMBIFIED_PIGLIN.create(level); + +- if (zombifiedpiglin != null) { +- zombifiedpiglin.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.GOLDEN_SWORD)); +- zombifiedpiglin.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); +- zombifiedpiglin.setNoAi(this.isNoAi()); +- zombifiedpiglin.setBaby(this.isBaby()); ++ if (entitypigzombie != null) { ++ entitypigzombie.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.GOLDEN_SWORD)); ++ entitypigzombie.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); ++ entitypigzombie.setNoAi(this.isNoAi()); ++ entitypigzombie.setBaby(this.isBaby()); + if (this.hasCustomName()) { +- zombifiedpiglin.setCustomName(this.getCustomName()); +- zombifiedpiglin.setCustomNameVisible(this.isCustomNameVisible()); ++ entitypigzombie.setCustomName(this.getCustomName()); ++ entitypigzombie.setCustomNameVisible(this.isCustomNameVisible()); + } + +- zombifiedpiglin.setPersistenceRequired(); +- serverlevel.addFreshEntity(zombifiedpiglin); ++ entitypigzombie.setPersistenceRequired(); ++ // CraftBukkit start ++ if (CraftEventFactory.callPigZapEvent(this, lightning, entitypigzombie).isCancelled()) { ++ return; ++ } ++ // CraftBukkit - added a reason for spawning this creature ++ level.addFreshEntity(entitypigzombie, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); ++ // CraftBukkit end + this.discard(); + } else { +- super.thunderHit(serverlevel, lightningbolt); ++ super.thunderHit(level, lightning); + } + } else { +- super.thunderHit(serverlevel, lightningbolt); ++ super.thunderHit(level, lightning); + } + + } + + @Override +- @Override +- protected void tickRidden(Player player, Vec3 vec3) { +- super.tickRidden(player, vec3); ++ protected void tickRidden(Player player, Vec3 travelVector) { ++ super.tickRidden(player, travelVector); + this.setRot(player.getYRot(), player.getXRot() * 0.5F); + this.yRotO = this.yBodyRot = this.yHeadRot = this.getYRot(); + this.steering.tickBoost(); + } + + @Override +- @Override +- protected Vec3 getRiddenInput(Player player, Vec3 vec3) { ++ protected Vec3 getRiddenInput(Player player, Vec3 travelVector) { + return new Vec3(0.0D, 0.0D, 1.0D); + } + + @Override +- @Override + protected float getRiddenSpeed(Player player) { + return (float) (this.getAttributeValue(Attributes.MOVEMENT_SPEED) * 0.225D * (double) this.steering.boostFactor()); + } + + @Override +- @Override + public boolean boost() { + return this.steering.boost(this.getRandom()); + } + + @Nullable + @Override +- @Override +- public Pig getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { +- return (Pig) EntityType.PIG.create(serverlevel); ++ public Pig getBreedOffspring(ServerLevel level, AgeableMob otherParent) { ++ return (Pig) EntityType.PIG.create(level); + } + + @Override +- @Override +- public boolean isFood(ItemStack itemstack) { +- return Pig.FOOD_ITEMS.test(itemstack); ++ public boolean isFood(ItemStack stack) { ++ return Pig.FOOD_ITEMS.test(stack); + } + + @Override +- @Override + public Vec3 getLeashOffset() { + return new Vec3(0.0D, (double) (0.6F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height - 0.03125F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.03125F * f, 0.0F); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Pufferfish.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Pufferfish.java.patch new file mode 100644 index 0000000000..b99f78dc65 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Pufferfish.java.patch @@ -0,0 +1,232 @@ +--- a/net/minecraft/world/entity/animal/Pufferfish.java ++++ b/net/minecraft/world/entity/animal/Pufferfish.java +@@ -15,11 +15,11 @@ + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.goal.Goal; + import net.minecraft.world.entity.ai.targeting.TargetingConditions; + import net.minecraft.world.entity.player.Player; +@@ -32,21 +32,20 @@ + private static final EntityDataAccessor PUFF_STATE = SynchedEntityData.defineId(Pufferfish.class, EntityDataSerializers.INT); + int inflateCounter; + int deflateTimer; +- private static final Predicate SCARY_MOB = (livingentity) -> { +- return livingentity instanceof Player && ((Player) livingentity).isCreative() ? false : livingentity.getType() == EntityType.AXOLOTL || livingentity.getMobType() != MobType.WATER; ++ private static final Predicate SCARY_MOB = (entityliving) -> { ++ return entityliving instanceof Player && ((Player) entityliving).isCreative() ? false : entityliving.getType() == EntityType.AXOLOTL || entityliving.getMobType() != EnumMonsterType.WATER; + }; + static final TargetingConditions targetingConditions = TargetingConditions.forNonCombat().ignoreInvisibilityTesting().ignoreLineOfSight().selector(Pufferfish.SCARY_MOB); + public static final int STATE_SMALL = 0; + public static final int STATE_MID = 1; + public static final int STATE_FULL = 2; + +- public Pufferfish(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Pufferfish(EntityType entityType, Level level) { ++ super(entityType, level); + this.refreshDimensions(); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Pufferfish.PUFF_STATE, 0); +@@ -56,49 +55,43 @@ + return (Integer) this.entityData.get(Pufferfish.PUFF_STATE); + } + +- public void setPuffState(int i) { +- this.entityData.set(Pufferfish.PUFF_STATE, i); ++ public void setPuffState(int puffState) { ++ this.entityData.set(Pufferfish.PUFF_STATE, puffState); + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- if (Pufferfish.PUFF_STATE.equals(entitydataaccessor)) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ if (Pufferfish.PUFF_STATE.equals(key)) { + this.refreshDimensions(); + } + +- super.onSyncedDataUpdated(entitydataaccessor); ++ super.onSyncedDataUpdated(key); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("PuffState", this.getPuffState()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("PuffState", this.getPuffState()); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setPuffState(Math.min(compoundtag.getInt("PuffState"), 2)); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setPuffState(Math.min(compound.getInt("PuffState"), 2)); + } + + @Override +- @Override + public ItemStack getBucketItemStack() { + return new ItemStack(Items.PUFFERFISH_BUCKET); + } + + @Override +- @Override + protected void registerGoals() { + super.registerGoals(); + this.goalSelector.addGoal(1, new Pufferfish.PufferfishPuffGoal(this)); + } + + @Override +- @Override + public void tick() { + if (!this.level().isClientSide && this.isAlive() && this.isEffectiveAi()) { + if (this.inflateCounter > 0) { +@@ -128,20 +121,19 @@ + } + + @Override +- @Override + public void aiStep() { + super.aiStep(); + if (this.isAlive() && this.getPuffState() > 0) { +- List list = this.level().getEntitiesOfClass(Mob.class, this.getBoundingBox().inflate(0.3D), (mob) -> { +- return Pufferfish.targetingConditions.test(this, mob); ++ List list = this.level().getEntitiesOfClass(Mob.class, this.getBoundingBox().inflate(0.3D), (entityinsentient) -> { ++ return Pufferfish.targetingConditions.test(this, entityinsentient); + }); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- Mob mob = (Mob) iterator.next(); ++ Mob entityinsentient = (Mob) iterator.next(); + +- if (mob.isAlive()) { +- this.touch(mob); ++ if (entityinsentient.isAlive()) { ++ this.touch(entityinsentient); + } + } + } +@@ -152,59 +144,53 @@ + int i = this.getPuffState(); + + if (mob.hurt(this.damageSources().mobAttack(this), (float) (1 + i))) { +- mob.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * i, 0), this); ++ mob.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * i, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + this.playSound(SoundEvents.PUFFER_FISH_STING, 1.0F, 1.0F); + } + + } + + @Override +- @Override +- public void playerTouch(Player player) { ++ public void playerTouch(Player entity) { + int i = this.getPuffState(); + +- if (player instanceof ServerPlayer && i > 0 && player.hurt(this.damageSources().mobAttack(this), (float) (1 + i))) { ++ if (entity instanceof ServerPlayer && i > 0 && entity.hurt(this.damageSources().mobAttack(this), (float) (1 + i))) { + if (!this.isSilent()) { +- ((ServerPlayer) player).connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.PUFFER_FISH_STING, 0.0F)); ++ ((ServerPlayer) entity).connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.PUFFER_FISH_STING, 0.0F)); + } + +- player.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * i, 0), this); ++ entity.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * i, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.PUFFER_FISH_AMBIENT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.PUFFER_FISH_DEATH; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.PUFFER_FISH_HURT; + } + + @Override +- @Override + protected SoundEvent getFlopSound() { + return SoundEvents.PUFFER_FISH_FLOP; + } + + @Override +- @Override +- public EntityDimensions getDimensions(Pose pose) { ++ public EntityDimensions getDimensions(EntityPose pose) { + return super.getDimensions(pose).scale(getScale(this.getPuffState())); + } + +- private static float getScale(int i) { +- switch (i) { ++ private static float getScale(int puffState) { ++ switch (puffState) { + case 0: + return 0.5F; + case 1: +@@ -218,29 +204,26 @@ + + private final Pufferfish fish; + +- public PufferfishPuffGoal(Pufferfish pufferfish) { +- this.fish = pufferfish; ++ public PufferfishPuffGoal(Pufferfish fish) { ++ this.fish = fish; + } + + @Override +- @Override + public boolean canUse() { +- List list = this.fish.level().getEntitiesOfClass(LivingEntity.class, this.fish.getBoundingBox().inflate(2.0D), (livingentity) -> { +- return Pufferfish.targetingConditions.test(this.fish, livingentity); ++ List list = this.fish.level().getEntitiesOfClass(LivingEntity.class, this.fish.getBoundingBox().inflate(2.0D), (entityliving) -> { ++ return Pufferfish.targetingConditions.test(this.fish, entityliving); + }); + + return !list.isEmpty(); + } + + @Override +- @Override + public void start() { + this.fish.inflateCounter = 1; + this.fish.deflateTimer = 0; + } + + @Override +- @Override + public void stop() { + this.fish.inflateCounter = 0; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Rabbit.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Rabbit.java.patch new file mode 100644 index 0000000000..a8a28e38ce --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Rabbit.java.patch @@ -0,0 +1,582 @@ +--- a/net/minecraft/world/entity/animal/Rabbit.java ++++ b/net/minecraft/world/entity/animal/Rabbit.java +@@ -27,10 +27,10 @@ + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.VariantHolder; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -62,10 +62,13 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.CarrotBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.pathfinder.Path; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class Rabbit extends Animal implements VariantHolder { + +@@ -85,16 +88,14 @@ + private int jumpDelayTicks; + int moreCarrotTicks; + +- public Rabbit(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Rabbit(EntityType entityType, Level level) { ++ super(entityType, level); + this.jumpControl = new Rabbit.RabbitJumpControl(this); + this.moveControl = new Rabbit.RabbitMoveControl(this); +- this.setSpeedModifier(0.0D); + } + + @Override +- @Override +- protected void registerGoals() { ++ public void registerGoals() { + this.goalSelector.addGoal(1, new FloatGoal(this)); + this.goalSelector.addGoal(1, new ClimbOnTopOfPowderSnowGoal(this, this.level())); + this.goalSelector.addGoal(1, new Rabbit.RabbitPanicGoal(this, 2.2D)); +@@ -109,7 +110,6 @@ + } + + @Override +- @Override + protected float getJumpPower() { + float f = 0.3F; + +@@ -117,12 +117,12 @@ + f = 0.5F; + } + +- Path path = this.navigation.getPath(); ++ Path pathentity = this.navigation.getPath(); + +- if (path != null && !path.isDone()) { +- Vec3 vec3 = path.getNextEntityPos(this); ++ if (pathentity != null && !pathentity.isDone()) { ++ Vec3 vec3d = pathentity.getNextEntityPos(this); + +- if (vec3.y > this.getY() + 0.5D) { ++ if (vec3d.y > this.getY() + 0.5D) { + f = 0.5F; + } + } +@@ -135,7 +135,6 @@ + } + + @Override +- @Override + protected void jumpFromGround() { + super.jumpFromGround(); + double d0 = this.moveControl.getSpeedModifier(); +@@ -154,20 +153,19 @@ + + } + +- public float getJumpCompletion(float f) { +- return this.jumpDuration == 0 ? 0.0F : ((float) this.jumpTicks + f) / (float) this.jumpDuration; ++ public float getJumpCompletion(float partialTick) { ++ return this.jumpDuration == 0 ? 0.0F : ((float) this.jumpTicks + partialTick) / (float) this.jumpDuration; + } + +- public void setSpeedModifier(double d0) { +- this.getNavigation().setSpeedModifier(d0); +- this.moveControl.setWantedPosition(this.moveControl.getWantedX(), this.moveControl.getWantedY(), this.moveControl.getWantedZ(), d0); ++ public void setSpeedModifier(double speedModifier) { ++ this.getNavigation().setSpeedModifier(speedModifier); ++ this.moveControl.setWantedPosition(this.moveControl.getWantedX(), this.moveControl.getWantedY(), this.moveControl.getWantedZ(), speedModifier); + } + + @Override +- @Override +- public void setJumping(boolean flag) { +- super.setJumping(flag); +- if (flag) { ++ public void setJumping(boolean jumping) { ++ super.setJumping(jumping); ++ if (jumping) { + this.playSound(this.getJumpSound(), this.getSoundVolume(), ((this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F) * 0.8F); + } + +@@ -180,14 +178,12 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Rabbit.DATA_TYPE_ID, Rabbit.Variant.BROWN.id); + } + + @Override +- @Override + public void customServerAiStep() { + if (this.jumpDelayTicks > 0) { + --this.jumpDelayTicks; +@@ -207,31 +203,31 @@ + } + + if (this.getVariant() == Rabbit.Variant.EVIL && this.jumpDelayTicks == 0) { +- LivingEntity livingentity = this.getTarget(); ++ LivingEntity entityliving = this.getTarget(); + +- if (livingentity != null && this.distanceToSqr((Entity) livingentity) < 16.0D) { +- this.facePoint(livingentity.getX(), livingentity.getZ()); +- this.moveControl.setWantedPosition(livingentity.getX(), livingentity.getY(), livingentity.getZ(), this.moveControl.getSpeedModifier()); ++ if (entityliving != null && this.distanceToSqr((Entity) entityliving) < 16.0D) { ++ this.facePoint(entityliving.getX(), entityliving.getZ()); ++ this.moveControl.setWantedPosition(entityliving.getX(), entityliving.getY(), entityliving.getZ(), this.moveControl.getSpeedModifier()); + this.startJumping(); + this.wasOnGround = true; + } + } + +- Rabbit.RabbitJumpControl rabbit_rabbitjumpcontrol = (Rabbit.RabbitJumpControl) this.jumpControl; ++ Rabbit.RabbitJumpControl entityrabbit_controllerjumprabbit = (Rabbit.RabbitJumpControl) this.jumpControl; + +- if (!rabbit_rabbitjumpcontrol.wantJump()) { ++ if (!entityrabbit_controllerjumprabbit.wantJump()) { + if (this.moveControl.hasWanted() && this.jumpDelayTicks == 0) { +- Path path = this.navigation.getPath(); +- Vec3 vec3 = new Vec3(this.moveControl.getWantedX(), this.moveControl.getWantedY(), this.moveControl.getWantedZ()); ++ Path pathentity = this.navigation.getPath(); ++ Vec3 vec3d = new Vec3(this.moveControl.getWantedX(), this.moveControl.getWantedY(), this.moveControl.getWantedZ()); + +- if (path != null && !path.isDone()) { +- vec3 = path.getNextEntityPos(this); ++ if (pathentity != null && !pathentity.isDone()) { ++ vec3d = pathentity.getNextEntityPos(this); + } + +- this.facePoint(vec3.x, vec3.z); ++ this.facePoint(vec3d.x, vec3d.z); + this.startJumping(); + } +- } else if (!rabbit_rabbitjumpcontrol.canJump()) { ++ } else if (!entityrabbit_controllerjumprabbit.canJump()) { + this.enableJumpControl(); + } + } +@@ -240,13 +236,12 @@ + } + + @Override +- @Override + public boolean canSpawnSprintParticle() { + return false; + } + +- private void facePoint(double d0, double d1) { +- this.setYRot((float) (Mth.atan2(d1 - this.getZ(), d0 - this.getX()) * 57.2957763671875D) - 90.0F); ++ private void facePoint(double x, double d1) { ++ this.setYRot((float) (Mth.atan2(d1 - this.getZ(), x - this.getX()) * 57.2957763671875D) - 90.0F); + } + + private void enableJumpControl() { +@@ -272,7 +267,6 @@ + } + + @Override +- @Override + public void aiStep() { + super.aiStep(); + if (this.jumpTicks != this.jumpDuration) { +@@ -290,19 +284,17 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("RabbitType", this.getVariant().id); +- compoundtag.putInt("MoreCarrotTicks", this.moreCarrotTicks); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("RabbitType", this.getVariant().id); ++ compound.putInt("MoreCarrotTicks", this.moreCarrotTicks); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setVariant(Rabbit.Variant.byId(compoundtag.getInt("RabbitType"))); +- this.moreCarrotTicks = compoundtag.getInt("MoreCarrotTicks"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setVariant(Rabbit.Variant.byId(compound.getInt("RabbitType"))); ++ this.moreCarrotTicks = compound.getInt("MoreCarrotTicks"); + } + + protected SoundEvent getJumpSound() { +@@ -310,25 +302,21 @@ + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.RABBIT_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.RABBIT_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.RABBIT_DEATH; + } + + @Override +- @Override + public boolean doHurtTarget(Entity entity) { + if (this.getVariant() == Rabbit.Variant.EVIL) { + this.playSound(SoundEvents.RABBIT_ATTACK, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); +@@ -339,61 +327,56 @@ + } + + @Override +- @Override + public SoundSource getSoundSource() { + return this.getVariant() == Rabbit.Variant.EVIL ? SoundSource.HOSTILE : SoundSource.NEUTRAL; + } + +- private static boolean isTemptingItem(ItemStack itemstack) { +- return itemstack.is(Items.CARROT) || itemstack.is(Items.GOLDEN_CARROT) || itemstack.is(Blocks.DANDELION.asItem()); ++ private static boolean isTemptingItem(ItemStack stack) { ++ return stack.is(Items.CARROT) || stack.is(Items.GOLDEN_CARROT) || stack.is(Blocks.DANDELION.asItem()); + } + + @Nullable + @Override +- @Override +- public Rabbit getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { +- Rabbit rabbit = (Rabbit) EntityType.RABBIT.create(serverlevel); ++ public Rabbit getBreedOffspring(ServerLevel level, AgeableMob otherParent) { ++ Rabbit entityrabbit = (Rabbit) EntityType.RABBIT.create(level); + +- if (rabbit != null) { +- Rabbit.Variant rabbit_variant = getRandomRabbitVariant(serverlevel, this.blockPosition()); ++ if (entityrabbit != null) { ++ Rabbit.Variant entityrabbit_variant = getRandomRabbitVariant(level, this.blockPosition()); + + if (this.random.nextInt(20) != 0) { + label15: + { +- if (ageablemob instanceof Rabbit) { +- Rabbit rabbit1 = (Rabbit) ageablemob; ++ if (otherParent instanceof Rabbit) { ++ Rabbit entityrabbit1 = (Rabbit) otherParent; + + if (this.random.nextBoolean()) { +- rabbit_variant = rabbit1.getVariant(); ++ entityrabbit_variant = entityrabbit1.getVariant(); + break label15; + } + } + +- rabbit_variant = this.getVariant(); ++ entityrabbit_variant = this.getVariant(); + } + } + +- rabbit.setVariant(rabbit_variant); ++ entityrabbit.setVariant(entityrabbit_variant); + } + +- return rabbit; ++ return entityrabbit; + } + + @Override +- @Override +- public boolean isFood(ItemStack itemstack) { +- return isTemptingItem(itemstack); ++ public boolean isFood(ItemStack stack) { ++ return isTemptingItem(stack); + } + + @Override +- @Override + public Rabbit.Variant getVariant() { + return Rabbit.Variant.byId((Integer) this.entityData.get(Rabbit.DATA_TYPE_ID)); + } + +- @Override +- public void setVariant(Rabbit.Variant rabbit_variant) { +- if (rabbit_variant == Rabbit.Variant.EVIL) { ++ public void setVariant(Rabbit.Variant variant) { ++ if (variant == Rabbit.Variant.EVIL) { + this.getAttribute(Attributes.ARMOR).setBaseValue(8.0D); + this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.4D, true)); + this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[0])).setAlertOthers()); +@@ -404,34 +387,33 @@ + } + } + +- this.entityData.set(Rabbit.DATA_TYPE_ID, rabbit_variant.id); ++ this.entityData.set(Rabbit.DATA_TYPE_ID, variant.id); + } + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- Rabbit.Variant rabbit_variant = getRandomRabbitVariant(serverlevelaccessor, this.blockPosition()); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ Rabbit.Variant entityrabbit_variant = getRandomRabbitVariant(level, this.blockPosition()); + +- if (spawngroupdata instanceof Rabbit.RabbitGroupData) { +- rabbit_variant = ((Rabbit.RabbitGroupData) spawngroupdata).variant; ++ if (spawnData instanceof Rabbit.RabbitGroupData) { ++ entityrabbit_variant = ((Rabbit.RabbitGroupData) spawnData).variant; + } else { +- spawngroupdata = new Rabbit.RabbitGroupData(rabbit_variant); ++ spawnData = new Rabbit.RabbitGroupData(entityrabbit_variant); + } + +- this.setVariant(rabbit_variant); +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, (SpawnGroupData) spawngroupdata, compoundtag); ++ this.setVariant(entityrabbit_variant); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + +- private static Rabbit.Variant getRandomRabbitVariant(LevelAccessor levelaccessor, BlockPos blockpos) { +- Holder holder = levelaccessor.getBiome(blockpos); +- int i = levelaccessor.getRandom().nextInt(100); ++ private static Rabbit.Variant getRandomRabbitVariant(LevelAccessor level, BlockPos pos) { ++ Holder holder = level.getBiome(pos); ++ int i = level.getRandom().nextInt(100); + + return holder.is(BiomeTags.SPAWNS_WHITE_RABBITS) ? (i < 80 ? Rabbit.Variant.WHITE : Rabbit.Variant.WHITE_SPLOTCHED) : (holder.is(BiomeTags.SPAWNS_GOLD_RABBITS) ? Rabbit.Variant.GOLD : (i < 50 ? Rabbit.Variant.BROWN : (i < 90 ? Rabbit.Variant.SALT : Rabbit.Variant.BLACK))); + } + +- public static boolean checkRabbitSpawnRules(EntityType entitytype, LevelAccessor levelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- return levelaccessor.getBlockState(blockpos.below()).is(BlockTags.RABBITS_SPAWNABLE_ON) && isBrightEnoughToSpawn(levelaccessor, blockpos); ++ public static boolean checkRabbitSpawnRules(EntityType rabbit, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ return level.getBlockState(pos.below()).is(BlockTags.RABBITS_SPAWNABLE_ON) && isBrightEnoughToSpawn(level, pos); + } + + boolean wantsMoreFood() { +@@ -439,20 +421,18 @@ + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 1) { ++ public void handleEntityEvent(byte id) { ++ if (id == 1) { + this.spawnSprintParticle(); + this.jumpDuration = 10; + this.jumpTicks = 0; + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } + + @Override +- @Override + public Vec3 getLeashOffset() { + return new Vec3(0.0D, (double) (0.6F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); + } +@@ -475,12 +455,11 @@ + return this.canJump; + } + +- public void setCanJump(boolean flag) { +- this.canJump = flag; ++ public void setCanJump(boolean canJump) { ++ this.canJump = canJump; + } + + @Override +- @Override + public void tick() { + if (this.jump) { + this.rabbit.startJumping(); +@@ -501,7 +480,6 @@ + } + + @Override +- @Override + public void tick() { + if (this.rabbit.onGround() && !this.rabbit.jumping && !((Rabbit.RabbitJumpControl) this.rabbit.jumpControl).wantJump()) { + this.rabbit.setSpeedModifier(0.0D); +@@ -513,13 +491,12 @@ + } + + @Override +- @Override +- public void setWantedPosition(double d0, double d1, double d2, double d3) { ++ public void setWantedPosition(double x, double d1, double y, double d3) { + if (this.rabbit.isInWater()) { + d3 = 1.5D; + } + +- super.setWantedPosition(d0, d1, d2, d3); ++ super.setWantedPosition(x, d1, y, d3); + if (d3 > 0.0D) { + this.nextJumpSpeed = d3; + } +@@ -531,13 +508,12 @@ + + private final Rabbit rabbit; + +- public RabbitPanicGoal(Rabbit rabbit, double d0) { +- super(rabbit, d0); ++ public RabbitPanicGoal(Rabbit rabbit, double speedModifier) { ++ super(rabbit, speedModifier); + this.rabbit = rabbit; + } + + @Override +- @Override + public void tick() { + super.tick(); + this.rabbit.setSpeedModifier(this.speedModifier); +@@ -548,13 +524,12 @@ + + private final Rabbit rabbit; + +- public RabbitAvoidEntityGoal(Rabbit rabbit, Class oclass, float f, double d0, double d1) { +- super(rabbit, oclass, f, d0, d1); ++ public RabbitAvoidEntityGoal(Rabbit rabbit, Class entityClassToAvoid, float maxDist, double walkSpeedModifier, double d1) { ++ super(rabbit, entityClassToAvoid, maxDist, walkSpeedModifier, d1); + this.rabbit = rabbit; + } + + @Override +- @Override + public boolean canUse() { + return this.rabbit.getVariant() != Rabbit.Variant.EVIL && super.canUse(); + } +@@ -572,7 +547,6 @@ + } + + @Override +- @Override + public boolean canUse() { + if (this.nextStartTick <= 0) { + if (!this.rabbit.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +@@ -587,32 +561,40 @@ + } + + @Override +- @Override + public boolean canContinueToUse() { + return this.canRaid && super.canContinueToUse(); + } + + @Override +- @Override + public void tick() { + super.tick(); + this.rabbit.getLookControl().setLookAt((double) this.blockPos.getX() + 0.5D, (double) (this.blockPos.getY() + 1), (double) this.blockPos.getZ() + 0.5D, 10.0F, (float) this.rabbit.getMaxHeadXRot()); + if (this.isReachedTarget()) { +- Level level = this.rabbit.level(); +- BlockPos blockpos = this.blockPos.above(); +- BlockState blockstate = level.getBlockState(blockpos); +- Block block = blockstate.getBlock(); ++ Level world = this.rabbit.level(); ++ BlockPos blockposition = this.blockPos.above(); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ Block block = iblockdata.getBlock(); + + if (this.canRaid && block instanceof CarrotBlock) { +- int i = (Integer) blockstate.getValue(CarrotBlock.AGE); ++ int i = (Integer) iblockdata.getValue(CarrotBlock.AGE); + + if (i == 0) { +- level.setBlock(blockpos, Blocks.AIR.defaultBlockState(), 2); +- level.destroyBlock(blockpos, true, this.rabbit); ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.rabbit, blockposition, Blocks.AIR.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end ++ world.setBlock(blockposition, Blocks.AIR.defaultBlockState(), 2); ++ world.destroyBlock(blockposition, true, this.rabbit); + } else { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(CarrotBlock.AGE, i - 1), 2); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of((Entity) this.rabbit)); +- level.levelEvent(2001, blockpos, Block.getId(blockstate)); ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.rabbit, blockposition, iblockdata.setValue(CarrotBlock.AGE, i - 1))) { ++ return; ++ } ++ // CraftBukkit end ++ world.setBlock(blockposition, (IBlockData) iblockdata.setValue(CarrotBlock.AGE, i - 1), 2); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of((Entity) this.rabbit)); ++ world.levelEvent(2001, blockposition, Block.getId(iblockdata)); + } + + this.rabbit.moreCarrotTicks = 40; +@@ -625,13 +607,12 @@ + } + + @Override +- @Override +- protected boolean isValidTarget(LevelReader levelreader, BlockPos blockpos) { +- BlockState blockstate = levelreader.getBlockState(blockpos); ++ protected boolean isValidTarget(LevelReader level, BlockPos pos) { ++ IBlockData iblockdata = level.getBlockState(pos); + +- if (blockstate.is(Blocks.FARMLAND) && this.wantsToRaid && !this.canRaid) { +- blockstate = levelreader.getBlockState(blockpos.above()); +- if (blockstate.getBlock() instanceof CarrotBlock && ((CarrotBlock) blockstate.getBlock()).isMaxAge(blockstate)) { ++ if (iblockdata.is(Blocks.FARMLAND) && this.wantsToRaid && !this.canRaid) { ++ iblockdata = level.getBlockState(pos.above()); ++ if (iblockdata.getBlock() instanceof CarrotBlock && ((CarrotBlock) iblockdata.getBlock()).isMaxAge(iblockdata)) { + this.canRaid = true; + return true; + } +@@ -656,7 +637,6 @@ + } + + @Override +- @Override + public String getSerializedName() { + return this.name; + } +@@ -665,8 +645,8 @@ + return this.id; + } + +- public static Rabbit.Variant byId(int i) { +- return (Rabbit.Variant) Rabbit.Variant.BY_ID.apply(i); ++ public static Rabbit.Variant byId(int id) { ++ return (Rabbit.Variant) Rabbit.Variant.BY_ID.apply(id); + } + } + +@@ -674,9 +654,9 @@ + + public final Rabbit.Variant variant; + +- public RabbitGroupData(Rabbit.Variant rabbit_variant) { ++ public RabbitGroupData(Rabbit.Variant variant) { + super(1.0F); +- this.variant = rabbit_variant; ++ this.variant = variant; + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Sheep.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Sheep.java.patch new file mode 100644 index 0000000000..4fc3f9cf94 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Sheep.java.patch @@ -0,0 +1,514 @@ +--- a/net/minecraft/world/entity/animal/Sheep.java ++++ b/net/minecraft/world/entity/animal/Sheep.java +@@ -21,18 +21,18 @@ + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.Shearable; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.BreedGoal; +@@ -47,30 +47,36 @@ + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.inventory.AbstractContainerMenu; +-import net.minecraft.world.inventory.CraftingContainer; ++import net.minecraft.world.inventory.InventoryCrafting; + import net.minecraft.world.inventory.MenuType; ++import net.minecraft.world.inventory.ResultContainer; + import net.minecraft.world.inventory.TransientCraftingContainer; +-import net.minecraft.world.item.DyeColor; +-import net.minecraft.world.item.DyeItem; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +-import net.minecraft.world.item.crafting.CraftingRecipe; + import net.minecraft.world.item.crafting.Ingredient; ++import net.minecraft.world.item.crafting.RecipeCrafting; + import net.minecraft.world.item.crafting.RecipeType; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.storage.loot.BuiltInLootTables; + import org.joml.Vector3f; ++import net.minecraft.world.item.DyeColor; ++import net.minecraft.world.item.DyeItem; ++import net.minecraft.world.item.Item; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.SheepRegrowWoolEvent; ++import org.bukkit.inventory.InventoryView; ++// CraftBukkit end + + public class Sheep extends Animal implements Shearable { + + private static final int EAT_ANIMATION_TICKS = 40; + private static final EntityDataAccessor DATA_WOOL_ID = SynchedEntityData.defineId(Sheep.class, EntityDataSerializers.BYTE); +- private static final Map ITEM_BY_DYE = (Map) Util.make(Maps.newEnumMap(DyeColor.class), (enummap) -> { ++ private static final Map ITEM_BY_DYE = (Map) Util.make(Maps.newEnumMap(DyeColor.class), (enummap) -> { + enummap.put(DyeColor.WHITE, Blocks.WHITE_WOOL); + enummap.put(DyeColor.ORANGE, Blocks.ORANGE_WOOL); + enummap.put(DyeColor.MAGENTA, Blocks.MAGENTA_WOOL); +@@ -88,33 +94,32 @@ + enummap.put(DyeColor.RED, Blocks.RED_WOOL); + enummap.put(DyeColor.BLACK, Blocks.BLACK_WOOL); + }); +- private static final Map COLORARRAY_BY_COLOR = Maps.newEnumMap((Map) Arrays.stream(DyeColor.values()).collect(Collectors.toMap((dyecolor) -> { +- return dyecolor; ++ private static final Map COLORARRAY_BY_COLOR = Maps.newEnumMap((Map) Arrays.stream(DyeColor.values()).collect(Collectors.toMap((enumcolor) -> { ++ return enumcolor; + }, Sheep::createSheepColor))); + private int eatAnimationTick; + private EatBlockGoal eatBlockGoal; + +- private static float[] createSheepColor(DyeColor dyecolor) { +- if (dyecolor == DyeColor.WHITE) { ++ private static float[] createSheepColor(DyeColor dyeColor) { ++ if (dyeColor == DyeColor.WHITE) { + return new float[]{0.9019608F, 0.9019608F, 0.9019608F}; + } else { +- float[] afloat = dyecolor.getTextureDiffuseColors(); ++ float[] afloat = dyeColor.getTextureDiffuseColors(); + float f = 0.75F; + + return new float[]{afloat[0] * 0.75F, afloat[1] * 0.75F, afloat[2] * 0.75F}; + } + } + +- public static float[] getColorArray(DyeColor dyecolor) { +- return (float[]) Sheep.COLORARRAY_BY_COLOR.get(dyecolor); ++ public static float[] getColorArray(DyeColor dyeColor) { ++ return (float[]) Sheep.COLORARRAY_BY_COLOR.get(dyeColor); + } + +- public Sheep(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Sheep(EntityType entityType, Level level) { ++ super(entityType, level); + } + + @Override +- @Override + protected void registerGoals() { + this.eatBlockGoal = new EatBlockGoal(this); + this.goalSelector.addGoal(0, new FloatGoal(this)); +@@ -129,14 +134,12 @@ + } + + @Override +- @Override + protected void customServerAiStep() { + this.eatAnimationTick = this.eatBlockGoal.getEatAnimationTick(); + super.customServerAiStep(); + } + + @Override +- @Override + public void aiStep() { + if (this.level().isClientSide) { + this.eatAnimationTick = Math.max(0, this.eatAnimationTick - 1); +@@ -150,95 +153,92 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Sheep.DATA_WOOL_ID, (byte) 0); + } + + @Override +- @Override + public ResourceLocation getDefaultLootTable() { + if (this.isSheared()) { + return this.getType().getDefaultLootTable(); + } else { +- ResourceLocation resourcelocation; ++ ResourceLocation minecraftkey; + + switch (this.getColor()) { + case WHITE: +- resourcelocation = BuiltInLootTables.SHEEP_WHITE; ++ minecraftkey = BuiltInLootTables.SHEEP_WHITE; + break; + case ORANGE: +- resourcelocation = BuiltInLootTables.SHEEP_ORANGE; ++ minecraftkey = BuiltInLootTables.SHEEP_ORANGE; + break; + case MAGENTA: +- resourcelocation = BuiltInLootTables.SHEEP_MAGENTA; ++ minecraftkey = BuiltInLootTables.SHEEP_MAGENTA; + break; + case LIGHT_BLUE: +- resourcelocation = BuiltInLootTables.SHEEP_LIGHT_BLUE; ++ minecraftkey = BuiltInLootTables.SHEEP_LIGHT_BLUE; + break; + case YELLOW: +- resourcelocation = BuiltInLootTables.SHEEP_YELLOW; ++ minecraftkey = BuiltInLootTables.SHEEP_YELLOW; + break; + case LIME: +- resourcelocation = BuiltInLootTables.SHEEP_LIME; ++ minecraftkey = BuiltInLootTables.SHEEP_LIME; + break; + case PINK: +- resourcelocation = BuiltInLootTables.SHEEP_PINK; ++ minecraftkey = BuiltInLootTables.SHEEP_PINK; + break; + case GRAY: +- resourcelocation = BuiltInLootTables.SHEEP_GRAY; ++ minecraftkey = BuiltInLootTables.SHEEP_GRAY; + break; + case LIGHT_GRAY: +- resourcelocation = BuiltInLootTables.SHEEP_LIGHT_GRAY; ++ minecraftkey = BuiltInLootTables.SHEEP_LIGHT_GRAY; + break; + case CYAN: +- resourcelocation = BuiltInLootTables.SHEEP_CYAN; ++ minecraftkey = BuiltInLootTables.SHEEP_CYAN; + break; + case PURPLE: +- resourcelocation = BuiltInLootTables.SHEEP_PURPLE; ++ minecraftkey = BuiltInLootTables.SHEEP_PURPLE; + break; + case BLUE: +- resourcelocation = BuiltInLootTables.SHEEP_BLUE; ++ minecraftkey = BuiltInLootTables.SHEEP_BLUE; + break; + case BROWN: +- resourcelocation = BuiltInLootTables.SHEEP_BROWN; ++ minecraftkey = BuiltInLootTables.SHEEP_BROWN; + break; + case GREEN: +- resourcelocation = BuiltInLootTables.SHEEP_GREEN; ++ minecraftkey = BuiltInLootTables.SHEEP_GREEN; + break; + case RED: +- resourcelocation = BuiltInLootTables.SHEEP_RED; ++ minecraftkey = BuiltInLootTables.SHEEP_RED; + break; + case BLACK: +- resourcelocation = BuiltInLootTables.SHEEP_BLACK; ++ minecraftkey = BuiltInLootTables.SHEEP_BLACK; + break; + default: + throw new IncompatibleClassChangeError(); + } + +- return resourcelocation; ++ return minecraftkey; + } + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 10) { ++ public void handleEntityEvent(byte id) { ++ if (id == 10) { + this.eatAnimationTick = 40; + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } + +- public float getHeadEatPositionScale(float f) { +- return this.eatAnimationTick <= 0 ? 0.0F : (this.eatAnimationTick >= 4 && this.eatAnimationTick <= 36 ? 1.0F : (this.eatAnimationTick < 4 ? ((float) this.eatAnimationTick - f) / 4.0F : -((float) (this.eatAnimationTick - 40) - f) / 4.0F)); ++ public float getHeadEatPositionScale(float partialTick) { ++ return this.eatAnimationTick <= 0 ? 0.0F : (this.eatAnimationTick >= 4 && this.eatAnimationTick <= 36 ? 1.0F : (this.eatAnimationTick < 4 ? ((float) this.eatAnimationTick - partialTick) / 4.0F : -((float) (this.eatAnimationTick - 40) - partialTick) / 4.0F)); + } + +- public float getHeadEatAngleScale(float f) { ++ public float getHeadEatAngleScale(float partialTick) { + if (this.eatAnimationTick > 4 && this.eatAnimationTick <= 36) { +- float f1 = ((float) (this.eatAnimationTick - 4) - f) / 32.0F; ++ float f1 = ((float) (this.eatAnimationTick - 4) - partialTick) / 32.0F; + + return 0.62831855F + 0.21991149F * Mth.sin(f1 * 28.7F); + } else { +@@ -247,86 +247,84 @@ + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (itemstack.is(Items.SHEARS)) { + if (!this.level().isClientSide && this.readyForShearing()) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) { ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.shear(SoundSource.PLAYERS); + this.gameEvent(GameEvent.SHEAR, player); +- itemstack.hurtAndBreak(1, player, (player1) -> { +- player1.broadcastBreakEvent(interactionhand); ++ itemstack.hurtAndBreak(1, player, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(hand); + }); + return InteractionResult.SUCCESS; + } else { + return InteractionResult.CONSUME; + } + } else { +- return super.mobInteract(player, interactionhand); ++ return super.mobInteract(player, hand); + } + } + + @Override +- @Override +- public void shear(SoundSource soundsource) { +- this.level().playSound((Player) null, (Entity) this, SoundEvents.SHEEP_SHEAR, soundsource, 1.0F, 1.0F); ++ public void shear(SoundSource category) { ++ this.level().playSound((Player) null, (Entity) this, SoundEvents.SHEEP_SHEAR, category, 1.0F, 1.0F); + this.setSheared(true); + int i = 1 + this.random.nextInt(3); + + for (int j = 0; j < i; ++j) { +- ItemEntity itementity = this.spawnAtLocation((ItemLike) Sheep.ITEM_BY_DYE.get(this.getColor()), 1); ++ this.forceDrops = true; // CraftBukkit ++ ItemEntity entityitem = this.spawnAtLocation((IMaterial) Sheep.ITEM_BY_DYE.get(this.getColor()), 1); ++ this.forceDrops = false; // CraftBukkit + +- if (itementity != null) { +- itementity.setDeltaMovement(itementity.getDeltaMovement().add((double) ((this.random.nextFloat() - this.random.nextFloat()) * 0.1F), (double) (this.random.nextFloat() * 0.05F), (double) ((this.random.nextFloat() - this.random.nextFloat()) * 0.1F))); ++ if (entityitem != null) { ++ entityitem.setDeltaMovement(entityitem.getDeltaMovement().add((double) ((this.random.nextFloat() - this.random.nextFloat()) * 0.1F), (double) (this.random.nextFloat() * 0.05F), (double) ((this.random.nextFloat() - this.random.nextFloat()) * 0.1F))); + } + } + + } + + @Override +- @Override + public boolean readyForShearing() { + return this.isAlive() && !this.isSheared() && !this.isBaby(); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putBoolean("Sheared", this.isSheared()); +- compoundtag.putByte("Color", (byte) this.getColor().getId()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putBoolean("Sheared", this.isSheared()); ++ compound.putByte("Color", (byte) this.getColor().getId()); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setSheared(compoundtag.getBoolean("Sheared")); +- this.setColor(DyeColor.byId(compoundtag.getByte("Color"))); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setSheared(compound.getBoolean("Sheared")); ++ this.setColor(DyeColor.byId(compound.getByte("Color"))); + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.SHEEP_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.SHEEP_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.SHEEP_DEATH; + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.SHEEP_STEP, 0.15F, 1.0F); + } + +@@ -334,20 +332,20 @@ + return DyeColor.byId((Byte) this.entityData.get(Sheep.DATA_WOOL_ID) & 15); + } + +- public void setColor(DyeColor dyecolor) { ++ public void setColor(DyeColor dyeColor) { + byte b0 = (Byte) this.entityData.get(Sheep.DATA_WOOL_ID); + +- this.entityData.set(Sheep.DATA_WOOL_ID, (byte) (b0 & 240 | dyecolor.getId() & 15)); ++ this.entityData.set(Sheep.DATA_WOOL_ID, (byte) (b0 & 240 | dyeColor.getId() & 15)); + } + + public boolean isSheared() { + return ((Byte) this.entityData.get(Sheep.DATA_WOOL_ID) & 16) != 0; + } + +- public void setSheared(boolean flag) { ++ public void setSheared(boolean sheared) { + byte b0 = (Byte) this.entityData.get(Sheep.DATA_WOOL_ID); + +- if (flag) { ++ if (sheared) { + this.entityData.set(Sheep.DATA_WOOL_ID, (byte) (b0 | 16)); + } else { + this.entityData.set(Sheep.DATA_WOOL_ID, (byte) (b0 & -17)); +@@ -355,28 +353,32 @@ + + } + +- public static DyeColor getRandomSheepColor(RandomSource randomsource) { +- int i = randomsource.nextInt(100); ++ public static DyeColor getRandomSheepColor(RandomSource random) { ++ int i = random.nextInt(100); + +- return i < 5 ? DyeColor.BLACK : (i < 10 ? DyeColor.GRAY : (i < 15 ? DyeColor.LIGHT_GRAY : (i < 18 ? DyeColor.BROWN : (randomsource.nextInt(500) == 0 ? DyeColor.PINK : DyeColor.WHITE)))); ++ return i < 5 ? DyeColor.BLACK : (i < 10 ? DyeColor.GRAY : (i < 15 ? DyeColor.LIGHT_GRAY : (i < 18 ? DyeColor.BROWN : (random.nextInt(500) == 0 ? DyeColor.PINK : DyeColor.WHITE)))); + } + + @Nullable + @Override +- @Override +- public Sheep getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { +- Sheep sheep = (Sheep) EntityType.SHEEP.create(serverlevel); ++ public Sheep getBreedOffspring(ServerLevel level, AgeableMob otherParent) { ++ Sheep entitysheep = (Sheep) EntityType.SHEEP.create(level); + +- if (sheep != null) { +- sheep.setColor(this.getOffspringColor(this, (Sheep) ageablemob)); ++ if (entitysheep != null) { ++ entitysheep.setColor(this.getOffspringColor(this, (Sheep) otherParent)); + } + +- return sheep; ++ return entitysheep; + } + + @Override +- @Override + public void ate() { ++ // CraftBukkit start ++ SheepRegrowWoolEvent event = new SheepRegrowWoolEvent((org.bukkit.entity.Sheep) this.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) return; ++ // CraftBukkit end + super.ate(); + this.setSheared(false); + if (this.isBaby()) { +@@ -387,57 +389,60 @@ + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- this.setColor(getRandomSheepColor(serverlevelaccessor.getRandom())); +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ this.setColor(getRandomSheepColor(level.getRandom())); ++ return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + +- private DyeColor getOffspringColor(Animal animal, Animal animal1) { +- DyeColor dyecolor = ((Sheep) animal).getColor(); +- DyeColor dyecolor1 = ((Sheep) animal1).getColor(); +- CraftingContainer craftingcontainer = makeContainer(dyecolor, dyecolor1); +- Optional optional = this.level().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftingcontainer, this.level()).map((recipeholder) -> { +- return ((CraftingRecipe) recipeholder.value()).assemble(craftingcontainer, this.level().registryAccess()); ++ private DyeColor getOffspringColor(Animal father, Animal mother) { ++ DyeColor enumcolor = ((Sheep) father).getColor(); ++ DyeColor enumcolor1 = ((Sheep) mother).getColor(); ++ InventoryCrafting inventorycrafting = makeContainer(enumcolor, enumcolor1); ++ Optional optional = this.level().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, inventorycrafting, this.level()).map((recipeholder) -> { // CraftBukkit - decompile error ++ return ((RecipeCrafting) recipeholder.value()).assemble(inventorycrafting, this.level().registryAccess()); + }).map(ItemStack::getItem); + + Objects.requireNonNull(DyeItem.class); + optional = optional.filter(DyeItem.class::isInstance); + Objects.requireNonNull(DyeItem.class); + return (DyeColor) optional.map(DyeItem.class::cast).map(DyeItem::getDyeColor).orElseGet(() -> { +- return this.level().random.nextBoolean() ? dyecolor : dyecolor1; ++ return this.level().random.nextBoolean() ? enumcolor : enumcolor1; + }); + } + +- private static CraftingContainer makeContainer(DyeColor dyecolor, DyeColor dyecolor1) { ++ private static InventoryCrafting makeContainer(DyeColor fatherColor, DyeColor motherColor) { + TransientCraftingContainer transientcraftingcontainer = new TransientCraftingContainer(new AbstractContainerMenu((MenuType) null, -1) { + @Override +- @Override +- public ItemStack quickMoveStack(Player player, int i) { ++ public ItemStack quickMoveStack(Player player, int index) { + return ItemStack.EMPTY; + } + + @Override +- @Override + public boolean stillValid(Player player) { + return false; + } ++ ++ // CraftBukkit start ++ @Override ++ public InventoryView getBukkitView() { ++ return null; // TODO: O.O ++ } ++ // CraftBukkit end + }, 2, 1); + +- transientcraftingcontainer.setItem(0, new ItemStack(DyeItem.byColor(dyecolor))); +- transientcraftingcontainer.setItem(1, new ItemStack(DyeItem.byColor(dyecolor1))); ++ transientcraftingcontainer.setItem(0, new ItemStack(DyeItem.byColor(fatherColor))); ++ transientcraftingcontainer.setItem(1, new ItemStack(DyeItem.byColor(motherColor))); ++ transientcraftingcontainer.resultInventory = new ResultContainer(); // CraftBukkit - add result slot for event + return transientcraftingcontainer; + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return 0.95F * entitydimensions.height; ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { ++ return 0.95F * size.height; + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height - 0.0625F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.0625F * f, 0.0F); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/SnowGolem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/SnowGolem.java.patch new file mode 100644 index 0000000000..3b935e9150 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/SnowGolem.java.patch @@ -0,0 +1,265 @@ +--- a/net/minecraft/world/entity/animal/SnowGolem.java ++++ b/net/minecraft/world/entity/animal/SnowGolem.java +@@ -11,15 +11,15 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.tags.BiomeTags; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.Shearable; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -28,7 +28,7 @@ + import net.minecraft.world.entity.ai.goal.RangedAttackGoal; + import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal; + import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; +-import net.minecraft.world.entity.monster.Enemy; ++import net.minecraft.world.entity.monster.IMonster; + import net.minecraft.world.entity.monster.RangedAttackMob; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.Snowball; +@@ -37,9 +37,12 @@ + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackMob { + +@@ -47,19 +50,18 @@ + private static final byte PUMPKIN_FLAG = 16; + private static final float EYE_HEIGHT = 1.7F; + +- public SnowGolem(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public SnowGolem(EntityType entityType, Level level) { ++ super(entityType, level); + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new RangedAttackGoal(this, 1.25D, 20, 10.0F)); + this.goalSelector.addGoal(2, new WaterAvoidingRandomStrollGoal(this, 1.0D, 1.0000001E-5F)); + this.goalSelector.addGoal(3, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(4, new RandomLookAroundGoal(this)); +- this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Mob.class, 10, true, false, (livingentity) -> { +- return livingentity instanceof Enemy; ++ this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Mob.class, 10, true, false, (entityliving) -> { ++ return entityliving instanceof IMonster; + })); + } + +@@ -68,59 +70,58 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(SnowGolem.DATA_PUMPKIN_ID, (byte) 16); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putBoolean("Pumpkin", this.hasPumpkin()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putBoolean("Pumpkin", this.hasPumpkin()); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("Pumpkin")) { +- this.setPumpkin(compoundtag.getBoolean("Pumpkin")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("Pumpkin")) { ++ this.setPumpkin(compound.getBoolean("Pumpkin")); + } + + } + + @Override +- @Override + public boolean isSensitiveToWater() { + return true; + } + + @Override +- @Override + public void aiStep() { + super.aiStep(); + if (!this.level().isClientSide) { + if (this.level().getBiome(this.blockPosition()).is(BiomeTags.SNOW_GOLEM_MELTS)) { +- this.hurt(this.damageSources().onFire(), 1.0F); ++ this.hurt(this.damageSources().melting, 1.0F); // CraftBukkit - DamageSource.BURN -> CraftEventFactory.MELTING + } + + if (!this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { + return; + } + +- BlockState blockstate = Blocks.SNOW.defaultBlockState(); ++ IBlockData iblockdata = Blocks.SNOW.defaultBlockState(); + + for (int i = 0; i < 4; ++i) { + int j = Mth.floor(this.getX() + (double) ((float) (i % 2 * 2 - 1) * 0.25F)); + int k = Mth.floor(this.getY()); + int l = Mth.floor(this.getZ() + (double) ((float) (i / 2 % 2 * 2 - 1) * 0.25F)); +- BlockPos blockpos = new BlockPos(j, k, l); ++ BlockPos blockposition = new BlockPos(j, k, l); + +- if (this.level().getBlockState(blockpos).isAir() && blockstate.canSurvive(this.level(), blockpos)) { +- this.level().setBlockAndUpdate(blockpos, blockstate); +- this.level().gameEvent(GameEvent.BLOCK_PLACE, blockpos, GameEvent.Context.of(this, blockstate)); ++ if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handleBlockFormEvent(this.level(), blockposition, iblockdata, this)) { ++ continue; ++ } ++ // CraftBukkit end ++ this.level().gameEvent(GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(this, iblockdata)); + } + } + } +@@ -128,37 +129,39 @@ + } + + @Override +- @Override +- public void performRangedAttack(LivingEntity livingentity, float f) { +- Snowball snowball = new Snowball(this.level(), this); +- double d0 = livingentity.getEyeY() - 1.100000023841858D; +- double d1 = livingentity.getX() - this.getX(); +- double d2 = d0 - snowball.getY(); +- double d3 = livingentity.getZ() - this.getZ(); ++ public void performRangedAttack(LivingEntity target, float distanceFactor) { ++ Snowball entitysnowball = new Snowball(this.level(), this); ++ double d0 = target.getEyeY() - 1.100000023841858D; ++ double d1 = target.getX() - this.getX(); ++ double d2 = d0 - entitysnowball.getY(); ++ double d3 = target.getZ() - this.getZ(); + double d4 = Math.sqrt(d1 * d1 + d3 * d3) * 0.20000000298023224D; + +- snowball.shoot(d1, d2 + d4, d3, 1.6F, 12.0F); ++ entitysnowball.shoot(d1, d2 + d4, d3, 1.6F, 12.0F); + this.playSound(SoundEvents.SNOW_GOLEM_SHOOT, 1.0F, 0.4F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); +- this.level().addFreshEntity(snowball); ++ this.level().addFreshEntity(entitysnowball); + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 1.7F; + } + + @Override +- @Override +- protected InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ protected InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (itemstack.is(Items.SHEARS) && this.readyForShearing()) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) { ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.shear(SoundSource.PLAYERS); + this.gameEvent(GameEvent.SHEAR, player); + if (!this.level().isClientSide) { +- itemstack.hurtAndBreak(1, player, (player1) -> { +- player1.broadcastBreakEvent(interactionhand); ++ itemstack.hurtAndBreak(1, player, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(hand); + }); + } + +@@ -169,18 +172,18 @@ + } + + @Override +- @Override +- public void shear(SoundSource soundsource) { +- this.level().playSound((Player) null, (Entity) this, SoundEvents.SNOW_GOLEM_SHEAR, soundsource, 1.0F, 1.0F); ++ public void shear(SoundSource category) { ++ this.level().playSound((Player) null, (Entity) this, SoundEvents.SNOW_GOLEM_SHEAR, category, 1.0F, 1.0F); + if (!this.level().isClientSide()) { + this.setPumpkin(false); ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation(new ItemStack(Items.CARVED_PUMPKIN), 1.7F); ++ this.forceDrops = false; // CraftBukkit + } + + } + + @Override +- @Override + public boolean readyForShearing() { + return this.isAlive() && this.hasPumpkin(); + } +@@ -189,10 +192,10 @@ + return ((Byte) this.entityData.get(SnowGolem.DATA_PUMPKIN_ID) & 16) != 0; + } + +- public void setPumpkin(boolean flag) { ++ public void setPumpkin(boolean pumpkinEquipped) { + byte b0 = (Byte) this.entityData.get(SnowGolem.DATA_PUMPKIN_ID); + +- if (flag) { ++ if (pumpkinEquipped) { + this.entityData.set(SnowGolem.DATA_PUMPKIN_ID, (byte) (b0 | 16)); + } else { + this.entityData.set(SnowGolem.DATA_PUMPKIN_ID, (byte) (b0 & -17)); +@@ -202,27 +205,23 @@ + + @Nullable + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.SNOW_GOLEM_AMBIENT; + } + + @Nullable + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.SNOW_GOLEM_HURT; + } + + @Nullable + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.SNOW_GOLEM_DEATH; + } + + @Override +- @Override + public Vec3 getLeashOffset() { + return new Vec3(0.0D, (double) (0.75F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Turtle.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Turtle.java.patch new file mode 100644 index 0000000000..b2ddaa4b7b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Turtle.java.patch @@ -0,0 +1,769 @@ +--- a/net/minecraft/world/entity/animal/Turtle.java ++++ b/net/minecraft/world/entity/animal/Turtle.java +@@ -23,14 +23,14 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.ExperienceOrb; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LightningBolt; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.MoveControl; +@@ -56,7 +56,7 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.TurtleEggBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.Vec3; +@@ -72,12 +72,12 @@ + private static final EntityDataAccessor TRAVELLING = SynchedEntityData.defineId(Turtle.class, EntityDataSerializers.BOOLEAN); + public static final Ingredient FOOD_ITEMS = Ingredient.of(Blocks.SEAGRASS.asItem()); + int layEggCounter; +- public static final Predicate BABY_ON_LAND_SELECTOR = (livingentity) -> { +- return livingentity.isBaby() && !livingentity.isInWater(); ++ public static final Predicate BABY_ON_LAND_SELECTOR = (entityliving) -> { ++ return entityliving.isBaby() && !entityliving.isInWater(); + }; + +- public Turtle(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Turtle(EntityType entityType, Level level) { ++ super(entityType, level); + this.setPathfindingMalus(BlockPathTypes.WATER, 0.0F); + this.setPathfindingMalus(BlockPathTypes.DOOR_IRON_CLOSED, -1.0F); + this.setPathfindingMalus(BlockPathTypes.DOOR_WOOD_CLOSED, -1.0F); +@@ -86,16 +86,16 @@ + this.setMaxUpStep(1.0F); + } + +- public void setHomePos(BlockPos blockpos) { +- this.entityData.set(Turtle.HOME_POS, blockpos); ++ public void setHomePos(BlockPos homePos) { ++ this.entityData.set(Turtle.HOME_POS, homePos); + } + + BlockPos getHomePos() { + return (BlockPos) this.entityData.get(Turtle.HOME_POS); + } + +- void setTravelPos(BlockPos blockpos) { +- this.entityData.set(Turtle.TRAVEL_POS, blockpos); ++ void setTravelPos(BlockPos travelPos) { ++ this.entityData.set(Turtle.TRAVEL_POS, travelPos); + } + + BlockPos getTravelPos() { +@@ -106,37 +106,36 @@ + return (Boolean) this.entityData.get(Turtle.HAS_EGG); + } + +- void setHasEgg(boolean flag) { +- this.entityData.set(Turtle.HAS_EGG, flag); ++ void setHasEgg(boolean hasEgg) { ++ this.entityData.set(Turtle.HAS_EGG, hasEgg); + } + + public boolean isLayingEgg() { + return (Boolean) this.entityData.get(Turtle.LAYING_EGG); + } + +- void setLayingEgg(boolean flag) { +- this.layEggCounter = flag ? 1 : 0; +- this.entityData.set(Turtle.LAYING_EGG, flag); ++ void setLayingEgg(boolean isLayingEgg) { ++ this.layEggCounter = isLayingEgg ? 1 : 0; ++ this.entityData.set(Turtle.LAYING_EGG, isLayingEgg); + } + + boolean isGoingHome() { + return (Boolean) this.entityData.get(Turtle.GOING_HOME); + } + +- void setGoingHome(boolean flag) { +- this.entityData.set(Turtle.GOING_HOME, flag); ++ void setGoingHome(boolean isGoingHome) { ++ this.entityData.set(Turtle.GOING_HOME, isGoingHome); + } + + boolean isTravelling() { + return (Boolean) this.entityData.get(Turtle.TRAVELLING); + } + +- void setTravelling(boolean flag) { +- this.entityData.set(Turtle.TRAVELLING, flag); ++ void setTravelling(boolean isTravelling) { ++ this.entityData.set(Turtle.TRAVELLING, isTravelling); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Turtle.HOME_POS, BlockPos.ZERO); +@@ -148,50 +147,46 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("HomePosX", this.getHomePos().getX()); +- compoundtag.putInt("HomePosY", this.getHomePos().getY()); +- compoundtag.putInt("HomePosZ", this.getHomePos().getZ()); +- compoundtag.putBoolean("HasEgg", this.hasEgg()); +- compoundtag.putInt("TravelPosX", this.getTravelPos().getX()); +- compoundtag.putInt("TravelPosY", this.getTravelPos().getY()); +- compoundtag.putInt("TravelPosZ", this.getTravelPos().getZ()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("HomePosX", this.getHomePos().getX()); ++ compound.putInt("HomePosY", this.getHomePos().getY()); ++ compound.putInt("HomePosZ", this.getHomePos().getZ()); ++ compound.putBoolean("HasEgg", this.hasEgg()); ++ compound.putInt("TravelPosX", this.getTravelPos().getX()); ++ compound.putInt("TravelPosY", this.getTravelPos().getY()); ++ compound.putInt("TravelPosZ", this.getTravelPos().getZ()); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- int i = compoundtag.getInt("HomePosX"); +- int j = compoundtag.getInt("HomePosY"); +- int k = compoundtag.getInt("HomePosZ"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ int i = compound.getInt("HomePosX"); ++ int j = compound.getInt("HomePosY"); ++ int k = compound.getInt("HomePosZ"); + + this.setHomePos(new BlockPos(i, j, k)); +- super.readAdditionalSaveData(compoundtag); +- this.setHasEgg(compoundtag.getBoolean("HasEgg")); +- int l = compoundtag.getInt("TravelPosX"); +- int i1 = compoundtag.getInt("TravelPosY"); +- int j1 = compoundtag.getInt("TravelPosZ"); ++ super.readAdditionalSaveData(compound); ++ this.setHasEgg(compound.getBoolean("HasEgg")); ++ int l = compound.getInt("TravelPosX"); ++ int i1 = compound.getInt("TravelPosY"); ++ int j1 = compound.getInt("TravelPosZ"); + + this.setTravelPos(new BlockPos(l, i1, j1)); + } + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + this.setHomePos(this.blockPosition()); + this.setTravelPos(BlockPos.ZERO); +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); ++ return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + +- public static boolean checkTurtleSpawnRules(EntityType entitytype, LevelAccessor levelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- return blockpos.getY() < levelaccessor.getSeaLevel() + 4 && TurtleEggBlock.onSand(levelaccessor, blockpos) && isBrightEnoughToSpawn(levelaccessor, blockpos); ++ public static boolean checkTurtleSpawnRules(EntityType turtle, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ return pos.getY() < level.getSeaLevel() + 4 && TurtleEggBlock.onSand(level, pos) && isBrightEnoughToSpawn(level, pos); + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new Turtle.TurtlePanicGoal(this, 1.2D)); + this.goalSelector.addGoal(1, new Turtle.TurtleBreedGoal(this, 1.0D)); +@@ -209,116 +204,99 @@ + } + + @Override +- @Override + public boolean isPushedByFluid() { + return false; + } + + @Override +- @Override +- public MobType getMobType() { +- return MobType.WATER; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.WATER; + } + + @Override +- @Override + public int getAmbientSoundInterval() { + return 200; + } + + @Nullable + @Override +- @Override + protected SoundEvent getAmbientSound() { + return !this.isInWater() && this.onGround() && !this.isBaby() ? SoundEvents.TURTLE_AMBIENT_LAND : super.getAmbientSound(); + } + + @Override +- @Override +- protected void playSwimSound(float f) { +- super.playSwimSound(f * 1.5F); ++ protected void playSwimSound(float volume) { ++ super.playSwimSound(volume * 1.5F); + } + + @Override +- @Override + protected SoundEvent getSwimSound() { + return SoundEvents.TURTLE_SWIM; + } + + @Nullable + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return this.isBaby() ? SoundEvents.TURTLE_HURT_BABY : SoundEvents.TURTLE_HURT; + } + + @Nullable + @Override +- @Override + protected SoundEvent getDeathSound() { + return this.isBaby() ? SoundEvents.TURTLE_DEATH_BABY : SoundEvents.TURTLE_DEATH; + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { +- SoundEvent soundevent = this.isBaby() ? SoundEvents.TURTLE_SHAMBLE_BABY : SoundEvents.TURTLE_SHAMBLE; ++ protected void playStepSound(BlockPos pos, IBlockData block) { ++ SoundEvent soundeffect = this.isBaby() ? SoundEvents.TURTLE_SHAMBLE_BABY : SoundEvents.TURTLE_SHAMBLE; + +- this.playSound(soundevent, 0.15F, 1.0F); ++ this.playSound(soundeffect, 0.15F, 1.0F); + } + + @Override +- @Override + public boolean canFallInLove() { + return super.canFallInLove() && !this.hasEgg(); + } + + @Override +- @Override + protected float nextStep() { + return this.moveDist + 0.15F; + } + + @Override +- @Override + public float getScale() { + return this.isBaby() ? 0.3F : 1.0F; + } + + @Override +- @Override + protected PathNavigation createNavigation(Level level) { + return new Turtle.TurtlePathNavigation(this, level); + } + + @Nullable + @Override +- @Override +- public AgeableMob getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { +- return (AgeableMob) EntityType.TURTLE.create(serverlevel); ++ public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob otherParent) { ++ return (AgeableMob) EntityType.TURTLE.create(level); + } + + @Override +- @Override +- public boolean isFood(ItemStack itemstack) { +- return itemstack.is(Blocks.SEAGRASS.asItem()); ++ public boolean isFood(ItemStack stack) { ++ return stack.is(Blocks.SEAGRASS.asItem()); + } + + @Override +- @Override +- public float getWalkTargetValue(BlockPos blockpos, LevelReader levelreader) { +- return !this.isGoingHome() && levelreader.getFluidState(blockpos).is(FluidTags.WATER) ? 10.0F : (TurtleEggBlock.onSand(levelreader, blockpos) ? 10.0F : levelreader.getPathfindingCostFromLightLevels(blockpos)); ++ public float getWalkTargetValue(BlockPos pos, LevelReader level) { ++ return !this.isGoingHome() && level.getFluidState(pos).is(FluidTags.WATER) ? 10.0F : (TurtleEggBlock.onSand(level, pos) ? 10.0F : level.getPathfindingCostFromLightLevels(pos)); + } + + @Override +- @Override + public void aiStep() { + super.aiStep(); + if (this.isAlive() && this.isLayingEgg() && this.layEggCounter >= 1 && this.layEggCounter % 5 == 0) { +- BlockPos blockpos = this.blockPosition(); ++ BlockPos blockposition = this.blockPosition(); + +- if (TurtleEggBlock.onSand(this.level(), blockpos)) { +- this.level().levelEvent(2001, blockpos, Block.getId(this.level().getBlockState(blockpos.below()))); ++ if (TurtleEggBlock.onSand(this.level(), blockposition)) { ++ this.level().levelEvent(2001, blockposition, Block.getId(this.level().getBlockState(blockposition.below()))); + this.gameEvent(GameEvent.ENTITY_ACTION); + } + } +@@ -326,47 +304,46 @@ + } + + @Override +- @Override + protected void ageBoundaryReached() { + super.ageBoundaryReached(); + if (!this.isBaby() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation(Items.SCUTE, 1); ++ this.forceDrops = false; // CraftBukkit + } + + } + + @Override +- @Override +- public void travel(Vec3 vec3) { ++ public void travel(Vec3 travelVector) { + if (this.isControlledByLocalInstance() && this.isInWater()) { +- this.moveRelative(0.1F, vec3); +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.moveRelative(0.1F, travelVector); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + this.setDeltaMovement(this.getDeltaMovement().scale(0.9D)); + if (this.getTarget() == null && (!this.isGoingHome() || !this.getHomePos().closerToCenterThan(this.position(), 20.0D))) { + this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.005D, 0.0D)); + } + } else { +- super.travel(vec3); ++ super.travel(travelVector); + } + + } + + @Override +- @Override + public boolean canBeLeashed(Player player) { + return false; + } + + @Override +- @Override +- public void thunderHit(ServerLevel serverlevel, LightningBolt lightningbolt) { ++ public void thunderHit(ServerLevel level, LightningBolt lightning) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = lightning; // CraftBukkit + this.hurt(this.damageSources().lightningBolt(), Float.MAX_VALUE); ++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = null; // CraftBukkit + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height + (this.isBaby() ? 0.0F : 0.15625F) * f, -0.25F * f); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + (this.isBaby() ? 0.0F : 0.15625F) * f, -0.25F * f); + } + + private static class TurtleMoveControl extends MoveControl { +@@ -395,7 +372,6 @@ + } + + @Override +- @Override + public void tick() { + this.updateSpeed(); + if (this.operation == MoveControl.Operation.MOVE_TO && !this.turtle.getNavigation().isDone()) { +@@ -425,22 +401,21 @@ + + private static class TurtlePanicGoal extends PanicGoal { + +- TurtlePanicGoal(Turtle turtle, double d0) { +- super(turtle, d0); ++ TurtlePanicGoal(Turtle turtle, double speedModifier) { ++ super(turtle, speedModifier); + } + + @Override +- @Override + public boolean canUse() { + if (!this.shouldPanic()) { + return false; + } else { +- BlockPos blockpos = this.lookForWater(this.mob.level(), this.mob, 7); ++ BlockPos blockposition = this.lookForWater(this.mob.level(), this.mob, 7); + +- if (blockpos != null) { +- this.posX = (double) blockpos.getX(); +- this.posY = (double) blockpos.getY(); +- this.posZ = (double) blockpos.getZ(); ++ if (blockposition != null) { ++ this.posX = (double) blockposition.getX(); ++ this.posY = (double) blockposition.getY(); ++ this.posZ = (double) blockposition.getZ(); + return true; + } else { + return this.findRandomPosition(); +@@ -453,29 +428,27 @@ + + private final Turtle turtle; + +- TurtleBreedGoal(Turtle turtle, double d0) { +- super(turtle, d0); ++ TurtleBreedGoal(Turtle turtle, double speedModifier) { ++ super(turtle, speedModifier); + this.turtle = turtle; + } + + @Override +- @Override + public boolean canUse() { + return super.canUse() && !this.turtle.hasEgg(); + } + + @Override +- @Override + protected void breed() { +- ServerPlayer serverplayer = this.animal.getLoveCause(); ++ ServerPlayer entityplayer = this.animal.getLoveCause(); + +- if (serverplayer == null && this.partner.getLoveCause() != null) { +- serverplayer = this.partner.getLoveCause(); ++ if (entityplayer == null && this.partner.getLoveCause() != null) { ++ entityplayer = this.partner.getLoveCause(); + } + +- if (serverplayer != null) { +- serverplayer.awardStat(Stats.ANIMALS_BRED); +- CriteriaTriggers.BRED_ANIMALS.trigger(serverplayer, this.animal, this.partner, (AgeableMob) null); ++ if (entityplayer != null) { ++ entityplayer.awardStat(Stats.ANIMALS_BRED); ++ CriteriaTriggers.BRED_ANIMALS.trigger(entityplayer, this.animal, this.partner, (AgeableMob) null); + } + + this.turtle.setHasEgg(true); +@@ -496,41 +469,40 @@ + + private final Turtle turtle; + +- TurtleLayEggGoal(Turtle turtle, double d0) { +- super(turtle, d0, 16); ++ TurtleLayEggGoal(Turtle turtle, double speedModifier) { ++ super(turtle, speedModifier, 16); + this.turtle = turtle; + } + + @Override +- @Override + public boolean canUse() { + return this.turtle.hasEgg() && this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 9.0D) ? super.canUse() : false; + } + + @Override +- @Override + public boolean canContinueToUse() { + return super.canContinueToUse() && this.turtle.hasEgg() && this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 9.0D); + } + + @Override +- @Override + public void tick() { + super.tick(); +- BlockPos blockpos = this.turtle.blockPosition(); ++ BlockPos blockposition = this.turtle.blockPosition(); + + if (!this.turtle.isInWater() && this.isReachedTarget()) { + if (this.turtle.layEggCounter < 1) { + this.turtle.setLayingEgg(true); + } else if (this.turtle.layEggCounter > this.adjustedTickDelay(200)) { +- Level level = this.turtle.level(); ++ Level world = this.turtle.level(); + +- level.playSound((Player) null, blockpos, SoundEvents.TURTLE_LAY_EGG, SoundSource.BLOCKS, 0.3F, 0.9F + level.random.nextFloat() * 0.2F); +- BlockPos blockpos1 = this.blockPos.above(); +- BlockState blockstate = (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1); ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.turtle, this.blockPos.above(), (IBlockData) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1))) { // CraftBukkit ++ world.playSound((Player) null, blockposition, SoundEvents.TURTLE_LAY_EGG, SoundSource.BLOCKS, 0.3F, 0.9F + world.random.nextFloat() * 0.2F); ++ BlockPos blockposition1 = this.blockPos.above(); ++ IBlockData iblockdata = (IBlockData) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1); + +- level.setBlock(blockpos1, blockstate, 3); +- level.gameEvent(GameEvent.BLOCK_PLACE, blockpos1, GameEvent.Context.of(this.turtle, blockstate)); ++ world.setBlock(blockposition1, iblockdata, 3); ++ world.gameEvent(GameEvent.BLOCK_PLACE, blockposition1, GameEvent.Context.of(this.turtle, iblockdata)); ++ } // CraftBukkit + this.turtle.setHasEgg(false); + this.turtle.setLayingEgg(false); + this.turtle.setInLoveTime(600); +@@ -544,9 +516,8 @@ + } + + @Override +- @Override +- protected boolean isValidTarget(LevelReader levelreader, BlockPos blockpos) { +- return !levelreader.isEmptyBlock(blockpos.above()) ? false : TurtleEggBlock.isSand(levelreader, blockpos); ++ protected boolean isValidTarget(LevelReader level, BlockPos pos) { ++ return !level.isEmptyBlock(pos.above()) ? false : TurtleEggBlock.isSand(level, pos); + } + } + +@@ -555,34 +526,30 @@ + private static final int GIVE_UP_TICKS = 1200; + private final Turtle turtle; + +- TurtleGoToWaterGoal(Turtle turtle, double d0) { +- super(turtle, turtle.isBaby() ? 2.0D : d0, 24); ++ TurtleGoToWaterGoal(Turtle turtle, double speedModifier) { ++ super(turtle, turtle.isBaby() ? 2.0D : speedModifier, 24); + this.turtle = turtle; + this.verticalSearchStart = -1; + } + + @Override +- @Override + public boolean canContinueToUse() { + return !this.turtle.isInWater() && this.tryTicks <= 1200 && this.isValidTarget(this.turtle.level(), this.blockPos); + } + + @Override +- @Override + public boolean canUse() { + return this.turtle.isBaby() && !this.turtle.isInWater() ? super.canUse() : (!this.turtle.isGoingHome() && !this.turtle.isInWater() && !this.turtle.hasEgg() ? super.canUse() : false); + } + + @Override +- @Override + public boolean shouldRecalculatePath() { + return this.tryTicks % 160 == 0; + } + + @Override +- @Override +- protected boolean isValidTarget(LevelReader levelreader, BlockPos blockpos) { +- return levelreader.getBlockState(blockpos).is(Blocks.WATER); ++ protected boolean isValidTarget(LevelReader level, BlockPos pos) { ++ return level.getBlockState(pos).is(Blocks.WATER); + } + } + +@@ -594,19 +561,17 @@ + private int closeToHomeTryTicks; + private static final int GIVE_UP_TICKS = 600; + +- TurtleGoHomeGoal(Turtle turtle, double d0) { ++ TurtleGoHomeGoal(Turtle turtle, double speedModifier) { + this.turtle = turtle; +- this.speedModifier = d0; ++ this.speedModifier = speedModifier; + } + + @Override +- @Override + public boolean canUse() { + return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(reducedTickDelay(700)) != 0 ? false : !this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 64.0D))); + } + + @Override +- @Override + public void start() { + this.turtle.setGoingHome(true); + this.stuck = false; +@@ -614,45 +579,42 @@ + } + + @Override +- @Override + public void stop() { + this.turtle.setGoingHome(false); + } + + @Override +- @Override + public boolean canContinueToUse() { + return !this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 7.0D) && !this.stuck && this.closeToHomeTryTicks <= this.adjustedTickDelay(600); + } + + @Override +- @Override + public void tick() { +- BlockPos blockpos = this.turtle.getHomePos(); +- boolean flag = blockpos.closerToCenterThan(this.turtle.position(), 16.0D); ++ BlockPos blockposition = this.turtle.getHomePos(); ++ boolean flag = blockposition.closerToCenterThan(this.turtle.position(), 16.0D); + + if (flag) { + ++this.closeToHomeTryTicks; + } + + if (this.turtle.getNavigation().isDone()) { +- Vec3 vec3 = Vec3.atBottomCenterOf(blockpos); +- Vec3 vec31 = DefaultRandomPos.getPosTowards(this.turtle, 16, 3, vec3, 0.3141592741012573D); ++ Vec3 vec3d = Vec3.atBottomCenterOf(blockposition); ++ Vec3 vec3d1 = DefaultRandomPos.getPosTowards(this.turtle, 16, 3, vec3d, 0.3141592741012573D); + +- if (vec31 == null) { +- vec31 = DefaultRandomPos.getPosTowards(this.turtle, 8, 7, vec3, 1.5707963705062866D); ++ if (vec3d1 == null) { ++ vec3d1 = DefaultRandomPos.getPosTowards(this.turtle, 8, 7, vec3d, 1.5707963705062866D); + } + +- if (vec31 != null && !flag && !this.turtle.level().getBlockState(BlockPos.containing(vec31)).is(Blocks.WATER)) { +- vec31 = DefaultRandomPos.getPosTowards(this.turtle, 16, 5, vec3, 1.5707963705062866D); ++ if (vec3d1 != null && !flag && !this.turtle.level().getBlockState(BlockPos.containing(vec3d1)).is(Blocks.WATER)) { ++ vec3d1 = DefaultRandomPos.getPosTowards(this.turtle, 16, 5, vec3d, 1.5707963705062866D); + } + +- if (vec31 == null) { ++ if (vec3d1 == null) { + this.stuck = true; + return; + } + +- this.turtle.getNavigation().moveTo(vec31.x, vec31.y, vec31.z, this.speedModifier); ++ this.turtle.getNavigation().moveTo(vec3d1.x, vec3d1.y, vec3d1.z, this.speedModifier); + } + + } +@@ -664,19 +626,17 @@ + private final double speedModifier; + private boolean stuck; + +- TurtleTravelGoal(Turtle turtle, double d0) { ++ TurtleTravelGoal(Turtle turtle, double speedModifier) { + this.turtle = turtle; +- this.speedModifier = d0; ++ this.speedModifier = speedModifier; + } + + @Override +- @Override + public boolean canUse() { + return !this.turtle.isGoingHome() && !this.turtle.hasEgg() && this.turtle.isInWater(); + } + + @Override +- @Override + public void start() { + boolean flag = true; + boolean flag1 = true; +@@ -689,52 +649,49 @@ + j = 0; + } + +- BlockPos blockpos = BlockPos.containing((double) i + this.turtle.getX(), (double) j + this.turtle.getY(), (double) k + this.turtle.getZ()); ++ BlockPos blockposition = BlockPos.containing((double) i + this.turtle.getX(), (double) j + this.turtle.getY(), (double) k + this.turtle.getZ()); + +- this.turtle.setTravelPos(blockpos); ++ this.turtle.setTravelPos(blockposition); + this.turtle.setTravelling(true); + this.stuck = false; + } + + @Override +- @Override + public void tick() { + if (this.turtle.getNavigation().isDone()) { +- Vec3 vec3 = Vec3.atBottomCenterOf(this.turtle.getTravelPos()); +- Vec3 vec31 = DefaultRandomPos.getPosTowards(this.turtle, 16, 3, vec3, 0.3141592741012573D); ++ Vec3 vec3d = Vec3.atBottomCenterOf(this.turtle.getTravelPos()); ++ Vec3 vec3d1 = DefaultRandomPos.getPosTowards(this.turtle, 16, 3, vec3d, 0.3141592741012573D); + +- if (vec31 == null) { +- vec31 = DefaultRandomPos.getPosTowards(this.turtle, 8, 7, vec3, 1.5707963705062866D); ++ if (vec3d1 == null) { ++ vec3d1 = DefaultRandomPos.getPosTowards(this.turtle, 8, 7, vec3d, 1.5707963705062866D); + } + +- if (vec31 != null) { +- int i = Mth.floor(vec31.x); +- int j = Mth.floor(vec31.z); ++ if (vec3d1 != null) { ++ int i = Mth.floor(vec3d1.x); ++ int j = Mth.floor(vec3d1.z); + boolean flag = true; + + if (!this.turtle.level().hasChunksAt(i - 34, j - 34, i + 34, j + 34)) { +- vec31 = null; ++ vec3d1 = null; + } + } + +- if (vec31 == null) { ++ if (vec3d1 == null) { + this.stuck = true; + return; + } + +- this.turtle.getNavigation().moveTo(vec31.x, vec31.y, vec31.z, this.speedModifier); ++ this.turtle.getNavigation().moveTo(vec3d1.x, vec3d1.y, vec3d1.z, this.speedModifier); + } + + } + + @Override +- @Override + public boolean canContinueToUse() { + return !this.turtle.getNavigation().isDone() && !this.stuck && !this.turtle.isGoingHome() && !this.turtle.isInLove() && !this.turtle.hasEgg(); + } + + @Override +- @Override + public void stop() { + this.turtle.setTravelling(false); + super.stop(); +@@ -745,13 +702,12 @@ + + private final Turtle turtle; + +- TurtleRandomStrollGoal(Turtle turtle, double d0, int i) { +- super(turtle, d0, i); ++ TurtleRandomStrollGoal(Turtle turtle, double speedModifier, int i) { ++ super(turtle, speedModifier, i); + this.turtle = turtle; + } + + @Override +- @Override + public boolean canUse() { + return !this.mob.isInWater() && !this.turtle.isGoingHome() && !this.turtle.hasEgg() ? super.canUse() : false; + } +@@ -764,19 +720,18 @@ + } + + @Override +- @Override +- public boolean isStableDestination(BlockPos blockpos) { +- Mob mob = this.mob; ++ public boolean isStableDestination(BlockPos pos) { ++ Mob entityinsentient = this.mob; + +- if (mob instanceof Turtle) { +- Turtle turtle = (Turtle) mob; ++ if (entityinsentient instanceof Turtle) { ++ Turtle entityturtle = (Turtle) entityinsentient; + +- if (turtle.isTravelling()) { +- return this.level.getBlockState(blockpos).is(Blocks.WATER); ++ if (entityturtle.isTravelling()) { ++ return this.level.getBlockState(pos).is(Blocks.WATER); + } + } + +- return !this.level.getBlockState(blockpos.below()).isAir(); ++ return !this.level.getBlockState(pos.below()).isAir(); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Wolf.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Wolf.java.patch new file mode 100644 index 0000000000..75050baf96 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/Wolf.java.patch @@ -0,0 +1,589 @@ +--- a/net/minecraft/world/entity/animal/Wolf.java ++++ b/net/minecraft/world/entity/animal/Wolf.java +@@ -17,18 +17,18 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.util.TimeUtil; + import net.minecraft.util.valueproviders.UniformInt; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.NeutralMob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.TamableAnimal; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -64,21 +64,27 @@ + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class Wolf extends TamableAnimal implements NeutralMob { + + private static final EntityDataAccessor DATA_INTERESTED_ID = SynchedEntityData.defineId(Wolf.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_COLLAR_COLOR = SynchedEntityData.defineId(Wolf.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_REMAINING_ANGER_TIME = SynchedEntityData.defineId(Wolf.class, EntityDataSerializers.INT); +- public static final Predicate PREY_SELECTOR = (livingentity) -> { +- EntityType entitytype = livingentity.getType(); ++ public static final Predicate PREY_SELECTOR = (entityliving) -> { ++ EntityType entitytypes = entityliving.getType(); + +- return entitytype == EntityType.SHEEP || entitytype == EntityType.RABBIT || entitytype == EntityType.FOX; ++ return entitytypes == EntityType.SHEEP || entitytypes == EntityType.RABBIT || entitytypes == EntityType.FOX; + }; + private static final float START_HEALTH = 8.0F; + private static final float TAME_HEALTH = 20.0F; +@@ -92,15 +98,14 @@ + @Nullable + private UUID persistentAngerTarget; + +- public Wolf(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Wolf(EntityType entityType, Level level) { ++ super(entityType, level); + this.setTame(false); + this.setPathfindingMalus(BlockPathTypes.POWDER_SNOW, -1.0F); + this.setPathfindingMalus(BlockPathTypes.DANGER_POWDER_SNOW, -1.0F); + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new FloatGoal(this)); + this.goalSelector.addGoal(1, new Wolf.WolfPanicGoal(1.5D)); +@@ -129,7 +134,6 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Wolf.DATA_INTERESTED_ID, false); +@@ -138,56 +142,48 @@ + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.WOLF_STEP, 0.15F, 1.0F); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putByte("CollarColor", (byte) this.getCollarColor().getId()); +- this.addPersistentAngerSaveData(compoundtag); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putByte("CollarColor", (byte) this.getCollarColor().getId()); ++ this.addPersistentAngerSaveData(compound); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("CollarColor", 99)) { +- this.setCollarColor(DyeColor.byId(compoundtag.getInt("CollarColor"))); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("CollarColor", 99)) { ++ this.setCollarColor(DyeColor.byId(compound.getInt("CollarColor"))); + } + +- this.readPersistentAngerSaveData(this.level(), compoundtag); ++ this.readPersistentAngerSaveData(this.level(), compound); + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return this.isAngry() ? SoundEvents.WOLF_GROWL : (this.random.nextInt(3) == 0 ? (this.isTame() && this.getHealth() < 10.0F ? SoundEvents.WOLF_WHINE : SoundEvents.WOLF_PANT) : SoundEvents.WOLF_AMBIENT); + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.WOLF_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.WOLF_DEATH; + } + + @Override +- @Override + protected float getSoundVolume() { + return 0.4F; + } + + @Override +- @Override + public void aiStep() { + super.aiStep(); + if (!this.level().isClientSide && this.isWet && !this.isShaking && !this.isPathFinding() && this.onGround()) { +@@ -204,7 +200,6 @@ + } + + @Override +- @Override + public void tick() { + super.tick(); + if (this.isAlive()) { +@@ -239,13 +234,13 @@ + if (this.shakeAnim > 0.4F) { + float f = (float) this.getY(); + int i = (int) (Mth.sin((this.shakeAnim - 0.4F) * 3.1415927F) * 7.0F); +- Vec3 vec3 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + + for (int j = 0; j < i; ++j) { + float f1 = (this.random.nextFloat() * 2.0F - 1.0F) * this.getBbWidth() * 0.5F; + float f2 = (this.random.nextFloat() * 2.0F - 1.0F) * this.getBbWidth() * 0.5F; + +- this.level().addParticle(ParticleTypes.SPLASH, this.getX() + (double) f1, (double) (f + 0.8F), this.getZ() + (double) f2, vec3.x, vec3.y, vec3.z); ++ this.level().addParticle(ParticleTypes.SPLASH, this.getX() + (double) f1, (double) (f + 0.8F), this.getZ() + (double) f2, vec3d.x, vec3d.y, vec3d.z); + } + } + } +@@ -260,25 +255,24 @@ + } + + @Override +- @Override +- public void die(DamageSource damagesource) { ++ public void die(DamageSource cause) { + this.isWet = false; + this.isShaking = false; + this.shakeAnimO = 0.0F; + this.shakeAnim = 0.0F; +- super.die(damagesource); ++ super.die(cause); + } + + public boolean isWet() { + return this.isWet; + } + +- public float getWetShade(float f) { +- return Math.min(0.5F + Mth.lerp(f, this.shakeAnimO, this.shakeAnim) / 2.0F * 0.5F, 1.0F); ++ public float getWetShade(float partialTicks) { ++ return Math.min(0.5F + Mth.lerp(partialTicks, this.shakeAnimO, this.shakeAnim) / 2.0F * 0.5F, 1.0F); + } + +- public float getBodyRollAngle(float f, float f1) { +- float f2 = (Mth.lerp(f, this.shakeAnimO, this.shakeAnim) + f1) / 1.8F; ++ public float getBodyRollAngle(float partialTicks, float offset) { ++ float f2 = (Mth.lerp(partialTicks, this.shakeAnimO, this.shakeAnim) + offset) / 1.8F; + + if (f2 < 0.0F) { + f2 = 0.0F; +@@ -289,44 +283,44 @@ + return Mth.sin(f2 * 3.1415927F) * Mth.sin(f2 * 3.1415927F * 11.0F) * 0.15F * 3.1415927F; + } + +- public float getHeadRollAngle(float f) { +- return Mth.lerp(f, this.interestedAngleO, this.interestedAngle) * 0.15F * 3.1415927F; ++ public float getHeadRollAngle(float partialTicks) { ++ return Mth.lerp(partialTicks, this.interestedAngleO, this.interestedAngle) * 0.15F * 3.1415927F; + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return entitydimensions.height * 0.8F; ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { ++ return size.height * 0.8F; + } + + @Override +- @Override + public int getMaxHeadXRot() { + return this.isInSittingPose() ? 20 : super.getMaxHeadXRot(); + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- if (this.isInvulnerableTo(damagesource)) { ++ public boolean hurt(DamageSource source, float amount) { ++ if (this.isInvulnerableTo(source)) { + return false; + } else { +- Entity entity = damagesource.getEntity(); ++ Entity entity = source.getEntity(); + +- if (!this.level().isClientSide) { +- this.setOrderedToSit(false); +- } ++ // CraftBukkit - move diff down + + if (entity != null && !(entity instanceof Player) && !(entity instanceof AbstractArrow)) { +- f = (f + 1.0F) / 2.0F; ++ amount = (amount + 1.0F) / 2.0F; + } + +- return super.hurt(damagesource, f); ++ // CraftBukkit start ++ boolean result = super.hurt(source, amount); ++ if (!this.level().isClientSide && result) { ++ this.setOrderedToSit(false); ++ } ++ return result; ++ // CraftBukkit end + } + } + + @Override +- @Override + public boolean doHurtTarget(Entity entity) { + boolean flag = entity.hurt(this.damageSources().mobAttack(this), (float) ((int) this.getAttributeValue(Attributes.ATTACK_DAMAGE))); + +@@ -338,12 +332,11 @@ + } + + @Override +- @Override +- public void setTame(boolean flag) { +- super.setTame(flag); +- if (flag) { ++ public void setTame(boolean tamed) { ++ super.setTame(tamed); ++ if (tamed) { + this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(20.0D); +- this.setHealth(20.0F); ++ this.setHealth(this.getMaxHealth()); // CraftBukkit - 20.0 -> getMaxHealth() + } else { + this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(8.0D); + } +@@ -352,9 +345,8 @@ + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + Item item = itemstack.getItem(); + + if (this.level().isClientSide) { +@@ -367,17 +359,17 @@ + itemstack.shrink(1); + } + +- this.heal((float) item.getFoodProperties().getNutrition()); ++ this.heal((float) item.getFoodProperties().getNutrition(), EntityRegainHealthEvent.RegainReason.EATING); // CraftBukkit + return InteractionResult.SUCCESS; + } else { + if (item instanceof DyeItem) { +- DyeItem dyeitem = (DyeItem) item; ++ DyeItem itemdye = (DyeItem) item; + + if (this.isOwnedBy(player)) { +- DyeColor dyecolor = dyeitem.getDyeColor(); ++ DyeColor enumcolor = itemdye.getDyeColor(); + +- if (dyecolor != this.getCollarColor()) { +- this.setCollarColor(dyecolor); ++ if (enumcolor != this.getCollarColor()) { ++ this.setCollarColor(enumcolor); + if (!player.getAbilities().instabuild) { + itemstack.shrink(1); + } +@@ -385,20 +377,20 @@ + return InteractionResult.SUCCESS; + } + +- return super.mobInteract(player, interactionhand); ++ return super.mobInteract(player, hand); + } + } + +- InteractionResult interactionresult = super.mobInteract(player, interactionhand); ++ InteractionResult enuminteractionresult = super.mobInteract(player, hand); + +- if ((!interactionresult.consumesAction() || this.isBaby()) && this.isOwnedBy(player)) { ++ if ((!enuminteractionresult.consumesAction() || this.isBaby()) && this.isOwnedBy(player)) { + this.setOrderedToSit(!this.isOrderedToSit()); + this.jumping = false; + this.navigation.stop(); +- this.setTarget((LivingEntity) null); ++ this.setTarget((LivingEntity) null, EntityTargetEvent.TargetReason.FORGOT_TARGET, true); // CraftBukkit - reason + return InteractionResult.SUCCESS; + } else { +- return interactionresult; ++ return enuminteractionresult; + } + } + } else if (itemstack.is(Items.BONE) && !this.isAngry()) { +@@ -406,7 +398,8 @@ + itemstack.shrink(1); + } + +- if (this.random.nextInt(3) == 0) { ++ // CraftBukkit - added event call and isCancelled check. ++ if (this.random.nextInt(3) == 0 && !CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { + this.tame(player); + this.navigation.stop(); + this.setTarget((LivingEntity) null); +@@ -418,21 +411,20 @@ + + return InteractionResult.SUCCESS; + } else { +- return super.mobInteract(player, interactionhand); ++ return super.mobInteract(player, hand); + } + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 8) { ++ public void handleEntityEvent(byte id) { ++ if (id == 8) { + this.isShaking = true; + this.shakeAnim = 0.0F; + this.shakeAnimO = 0.0F; +- } else if (b0 == 56) { ++ } else if (id == 56) { + this.cancelShake(); + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } +@@ -442,93 +434,84 @@ + } + + @Override +- @Override +- public boolean isFood(ItemStack itemstack) { +- Item item = itemstack.getItem(); ++ public boolean isFood(ItemStack stack) { ++ Item item = stack.getItem(); + + return item.isEdible() && item.getFoodProperties().isMeat(); + } + + @Override +- @Override + public int getMaxSpawnClusterSize() { + return 8; + } + + @Override +- @Override + public int getRemainingPersistentAngerTime() { + return (Integer) this.entityData.get(Wolf.DATA_REMAINING_ANGER_TIME); + } + + @Override +- @Override +- public void setRemainingPersistentAngerTime(int i) { +- this.entityData.set(Wolf.DATA_REMAINING_ANGER_TIME, i); ++ public void setRemainingPersistentAngerTime(int time) { ++ this.entityData.set(Wolf.DATA_REMAINING_ANGER_TIME, time); + } + + @Override +- @Override + public void startPersistentAngerTimer() { + this.setRemainingPersistentAngerTime(Wolf.PERSISTENT_ANGER_TIME.sample(this.random)); + } + + @Nullable + @Override +- @Override + public UUID getPersistentAngerTarget() { + return this.persistentAngerTarget; + } + + @Override +- @Override +- public void setPersistentAngerTarget(@Nullable UUID uuid) { +- this.persistentAngerTarget = uuid; ++ public void setPersistentAngerTarget(@Nullable UUID target) { ++ this.persistentAngerTarget = target; + } + + public DyeColor getCollarColor() { + return DyeColor.byId((Integer) this.entityData.get(Wolf.DATA_COLLAR_COLOR)); + } + +- public void setCollarColor(DyeColor dyecolor) { +- this.entityData.set(Wolf.DATA_COLLAR_COLOR, dyecolor.getId()); ++ public void setCollarColor(DyeColor collarColor) { ++ this.entityData.set(Wolf.DATA_COLLAR_COLOR, collarColor.getId()); + } + + @Nullable + @Override +- @Override +- public Wolf getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { +- Wolf wolf = (Wolf) EntityType.WOLF.create(serverlevel); ++ public Wolf getBreedOffspring(ServerLevel level, AgeableMob otherParent) { ++ Wolf entitywolf = (Wolf) EntityType.WOLF.create(level); + +- if (wolf != null) { ++ if (entitywolf != null) { + UUID uuid = this.getOwnerUUID(); + + if (uuid != null) { +- wolf.setOwnerUUID(uuid); +- wolf.setTame(true); ++ entitywolf.setOwnerUUID(uuid); ++ entitywolf.setTame(true); + } + } + +- return wolf; ++ return entitywolf; + } + +- public void setIsInterested(boolean flag) { +- this.entityData.set(Wolf.DATA_INTERESTED_ID, flag); ++ public void setIsInterested(boolean isInterested) { ++ this.entityData.set(Wolf.DATA_INTERESTED_ID, isInterested); + } + + @Override +- @Override +- public boolean canMate(Animal animal) { +- if (animal == this) { ++ public boolean canMate(Animal otherAnimal) { ++ if (otherAnimal == this) { + return false; + } else if (!this.isTame()) { + return false; +- } else if (!(animal instanceof Wolf)) { ++ } else if (!(otherAnimal instanceof Wolf)) { + return false; + } else { +- Wolf wolf = (Wolf) animal; ++ Wolf entitywolf = (Wolf) otherAnimal; + +- return !wolf.isTame() ? false : (wolf.isInSittingPose() ? false : this.isInLove() && wolf.isInLove()); ++ return !entitywolf.isTame() ? false : (entitywolf.isInSittingPose() ? false : this.isInLove() && entitywolf.isInLove()); + } + } + +@@ -537,15 +520,14 @@ + } + + @Override +- @Override +- public boolean wantsToAttack(LivingEntity livingentity, LivingEntity livingentity1) { +- if (!(livingentity instanceof Creeper) && !(livingentity instanceof Ghast)) { +- if (livingentity instanceof Wolf) { +- Wolf wolf = (Wolf) livingentity; ++ public boolean wantsToAttack(LivingEntity target, LivingEntity owner) { ++ if (!(target instanceof Creeper) && !(target instanceof Ghast)) { ++ if (target instanceof Wolf) { ++ Wolf entitywolf = (Wolf) target; + +- return !wolf.isTame() || wolf.getOwner() != livingentity1; ++ return !entitywolf.isTame() || entitywolf.getOwner() != owner; + } else { +- return livingentity instanceof Player && livingentity1 instanceof Player && !((Player) livingentity1).canHarmPlayer((Player) livingentity) ? false : (livingentity instanceof AbstractHorse && ((AbstractHorse) livingentity).isTamed() ? false : !(livingentity instanceof TamableAnimal) || !((TamableAnimal) livingentity).isTame()); ++ return target instanceof Player && owner instanceof Player && !((Player) owner).canHarmPlayer((Player) target) ? false : (target instanceof AbstractHorse && ((AbstractHorse) target).isTamed() ? false : !(target instanceof TamableAnimal) || !((TamableAnimal) target).isTame()); + } + } else { + return false; +@@ -553,25 +535,22 @@ + } + + @Override +- @Override + public boolean canBeLeashed(Player player) { + return !this.isAngry() && super.canBeLeashed(player); + } + + @Override +- @Override + public Vec3 getLeashOffset() { + return new Vec3(0.0D, (double) (0.6F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height - 0.03125F * f, -0.0625F * f); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.03125F * f, -0.0625F * f); + } + +- public static boolean checkWolfSpawnRules(EntityType entitytype, LevelAccessor levelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- return levelaccessor.getBlockState(blockpos.below()).is(BlockTags.WOLVES_SPAWNABLE_ON) && isBrightEnoughToSpawn(levelaccessor, blockpos); ++ public static boolean checkWolfSpawnRules(EntityType wolf, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ return level.getBlockState(pos.below()).is(BlockTags.WOLVES_SPAWNABLE_ON) && isBrightEnoughToSpawn(level, pos); + } + + private class WolfPanicGoal extends PanicGoal { +@@ -581,7 +560,6 @@ + } + + @Override +- @Override + protected boolean shouldPanic() { + return this.mob.isFreezing() || this.mob.isOnFire(); + } +@@ -591,13 +569,12 @@ + + private final Wolf wolf; + +- public WolfAvoidEntityGoal(Wolf wolf, Class oclass, float f, double d0, double d1) { +- super(wolf, oclass, f, d0, d1); +- this.wolf = wolf; ++ public WolfAvoidEntityGoal(Wolf entitywolf, Class oclass, float f, double d0, double d1) { ++ super(entitywolf, oclass, f, d0, d1); ++ this.wolf = entitywolf; + } + + @Override +- @Override + public boolean canUse() { + return super.canUse() && this.toAvoid instanceof Llama ? !this.wolf.isTame() && this.avoidLlama((Llama) this.toAvoid) : false; + } +@@ -607,14 +584,12 @@ + } + + @Override +- @Override + public void start() { + Wolf.this.setTarget((LivingEntity) null); + super.start(); + } + + @Override +- @Override + public void tick() { + Wolf.this.setTarget((LivingEntity) null); + super.tick(); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/allay/Allay.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/allay/Allay.java.patch new file mode 100644 index 0000000000..c50b963739 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/allay/Allay.java.patch @@ -0,0 +1,710 @@ +--- a/net/minecraft/world/entity/animal/allay/Allay.java ++++ b/net/minecraft/world/entity/animal/allay/Allay.java +@@ -28,18 +28,18 @@ + import net.minecraft.tags.GameEventTags; + import net.minecraft.tags.TagKey; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.PathfinderMob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -61,7 +61,7 @@ + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.DynamicGameEventListener; + import net.minecraft.world.level.gameevent.EntityPositionSource; + import net.minecraft.world.level.gameevent.GameEvent; +@@ -92,40 +92,44 @@ + private final DynamicGameEventListener dynamicJukeboxListener; + private final SimpleContainer inventory = new SimpleContainer(1); + @Nullable +- private BlockPos jukeboxPos; +- private long duplicationCooldown; ++ public BlockPos jukeboxPos; ++ public long duplicationCooldown; + private float holdingItemAnimationTicks; + private float holdingItemAnimationTicks0; + private float dancingAnimationTicks; + private float spinningAnimationTicks; + private float spinningAnimationTicks0; ++ public boolean forceDancing = false; // CraftBukkit + +- public Allay(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Allay(EntityType entityType, Level level) { ++ super(entityType, level); + this.moveControl = new FlyingMoveControl(this, 20, true); + this.setCanPickUpLoot(this.canPickUpLoot()); +- this.vibrationUser = new Allay.VibrationUser(); ++ this.vibrationUser = new Allay.b(); + this.vibrationData = new VibrationSystem.Data(); + this.dynamicVibrationListener = new DynamicGameEventListener<>(new VibrationSystem.Listener(this)); + this.dynamicJukeboxListener = new DynamicGameEventListener<>(new Allay.JukeboxListener(this.vibrationUser.getPositionSource(), GameEvent.JUKEBOX_PLAY.getNotificationRadius())); + } + ++ // CraftBukkit start ++ public void setCanDuplicate(boolean canDuplicate) { ++ this.entityData.set(Allay.DATA_CAN_DUPLICATE, canDuplicate); ++ } ++ // CraftBukkit end ++ + @Override +- @Override + protected Brain.Provider brainProvider() { + return Brain.provider(Allay.MEMORY_TYPES, Allay.SENSOR_TYPES); + } + + @Override +- @Override + protected Brain makeBrain(Dynamic dynamic) { + return AllayAi.makeBrain(this.brainProvider().makeBrain(dynamic)); + } + + @Override +- @Override + public Brain getBrain() { +- return super.getBrain(); ++ return (Brain) super.getBrain(); // CraftBukkit - decompile error + } + + public static AttributeSupplier.Builder createAttributes() { +@@ -133,18 +137,16 @@ + } + + @Override +- @Override + protected PathNavigation createNavigation(Level level) { +- FlyingPathNavigation flyingpathnavigation = new FlyingPathNavigation(this, level); ++ FlyingPathNavigation navigationflying = new FlyingPathNavigation(this, level); + +- flyingpathnavigation.setCanOpenDoors(false); +- flyingpathnavigation.setCanFloat(true); +- flyingpathnavigation.setCanPassDoors(true); +- return flyingpathnavigation; ++ navigationflying.setCanOpenDoors(false); ++ navigationflying.setCanFloat(true); ++ navigationflying.setCanPassDoors(true); ++ return navigationflying; + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Allay.DATA_DANCING, false); +@@ -152,20 +154,19 @@ + } + + @Override +- @Override +- public void travel(Vec3 vec3) { ++ public void travel(Vec3 travelVector) { + if (this.isControlledByLocalInstance()) { + if (this.isInWater()) { +- this.moveRelative(0.02F, vec3); +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.moveRelative(0.02F, travelVector); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + this.setDeltaMovement(this.getDeltaMovement().scale(0.800000011920929D)); + } else if (this.isInLava()) { +- this.moveRelative(0.02F, vec3); +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.moveRelative(0.02F, travelVector); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + this.setDeltaMovement(this.getDeltaMovement().scale(0.5D)); + } else { +- this.moveRelative(this.getSpeed(), vec3); +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.moveRelative(this.getSpeed(), travelVector); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + this.setDeltaMovement(this.getDeltaMovement().scale(0.9100000262260437D)); + } + } +@@ -174,62 +175,53 @@ + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return entitydimensions.height * 0.6F; ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions dimensions) { ++ return dimensions.height * 0.6F; + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- Entity entity = damagesource.getEntity(); ++ public boolean hurt(DamageSource source, float amount) { ++ Entity entity = source.getEntity(); + + if (entity instanceof Player) { +- Player player = (Player) entity; ++ Player entityhuman = (Player) entity; + Optional optional = this.getBrain().getMemory(MemoryModuleType.LIKED_PLAYER); + +- if (optional.isPresent() && player.getUUID().equals(optional.get())) { ++ if (optional.isPresent() && entityhuman.getUUID().equals(optional.get())) { + return false; + } + } + +- return super.hurt(damagesource, f); ++ return super.hurt(source, amount); + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) {} ++ protected void playStepSound(BlockPos pos, IBlockData state) {} + + @Override +- @Override +- protected void checkFallDamage(double d0, boolean flag, BlockState blockstate, BlockPos blockpos) {} ++ protected void checkFallDamage(double y, boolean flag, IBlockData onGround, BlockPos state) {} + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return this.hasItemInSlot(EquipmentSlot.MAINHAND) ? SoundEvents.ALLAY_AMBIENT_WITH_ITEM : SoundEvents.ALLAY_AMBIENT_WITHOUT_ITEM; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.ALLAY_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.ALLAY_DEATH; + } + + @Override +- @Override + protected float getSoundVolume() { + return 0.4F; + } + + @Override +- @Override + protected void customServerAiStep() { + this.level().getProfiler().push("allayBrain"); + this.getBrain().tick((ServerLevel) this.level(), this); +@@ -241,11 +233,10 @@ + } + + @Override +- @Override + public void aiStep() { + super.aiStep(); + if (!this.level().isClientSide && this.isAlive() && this.tickCount % 10 == 0) { +- this.heal(1.0F); ++ this.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit + } + + if (this.isDancing() && this.shouldStopDancing() && this.tickCount % 20 == 0) { +@@ -257,7 +248,6 @@ + } + + @Override +- @Override + public void tick() { + super.tick(); + if (this.level().isClientSide) { +@@ -293,18 +283,16 @@ + } + + @Override +- @Override + public boolean canPickUpLoot() { + return !this.isOnPickupCooldown() && this.hasItemInHand(); + } + + public boolean hasItemInHand() { +- return !this.getItemInHand(InteractionHand.MAIN_HAND).isEmpty(); ++ return !this.getItemInHand(EnumHand.MAIN_HAND).isEmpty(); + } + + @Override +- @Override +- public boolean canTakeItem(ItemStack itemstack) { ++ public boolean canTakeItem(ItemStack stack) { + return false; + } + +@@ -313,13 +301,17 @@ + } + + @Override +- @Override +- protected InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); +- ItemStack itemstack1 = this.getItemInHand(InteractionHand.MAIN_HAND); ++ protected InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ItemStack itemstack1 = this.getItemInHand(EnumHand.MAIN_HAND); + + if (this.isDancing() && this.isDuplicationItem(itemstack) && this.canDuplicate()) { +- this.duplicateAllay(); ++ // CraftBukkit start - handle cancel duplication ++ Allay allay = this.duplicateAllay(); ++ if (allay == null) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + this.level().broadcastEntityEvent(this, (byte) 18); + this.level().playSound(player, (Entity) this, SoundEvents.AMETHYST_BLOCK_CHIME, SoundSource.NEUTRAL, 2.0F, 1.0F); + this.removeInteractionItem(player, itemstack); +@@ -327,15 +319,15 @@ + } else if (itemstack1.isEmpty() && !itemstack.isEmpty()) { + ItemStack itemstack2 = itemstack.copyWithCount(1); + +- this.setItemInHand(InteractionHand.MAIN_HAND, itemstack2); ++ this.setItemInHand(EnumHand.MAIN_HAND, itemstack2); + this.removeInteractionItem(player, itemstack); + this.level().playSound(player, (Entity) this, SoundEvents.ALLAY_ITEM_GIVEN, SoundSource.NEUTRAL, 2.0F, 1.0F); +- this.getBrain().setMemory(MemoryModuleType.LIKED_PLAYER, (Object) player.getUUID()); ++ this.getBrain().setMemory(MemoryModuleType.LIKED_PLAYER, player.getUUID()); // CraftBukkit - decompile error + return InteractionResult.SUCCESS; +- } else if (!itemstack1.isEmpty() && interactionhand == InteractionHand.MAIN_HAND && itemstack.isEmpty()) { ++ } else if (!itemstack1.isEmpty() && hand == EnumHand.MAIN_HAND && itemstack.isEmpty()) { + this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); + this.level().playSound(player, (Entity) this, SoundEvents.ALLAY_ITEM_TAKEN, SoundSource.NEUTRAL, 2.0F, 1.0F); +- this.swing(InteractionHand.MAIN_HAND); ++ this.swing(EnumHand.MAIN_HAND); + Iterator iterator = this.getInventory().removeAllItems().iterator(); + + while (iterator.hasNext()) { +@@ -348,17 +340,17 @@ + player.addItem(itemstack1); + return InteractionResult.SUCCESS; + } else { +- return super.mobInteract(player, interactionhand); ++ return super.mobInteract(player, hand); + } + } + +- public void setJukeboxPlaying(BlockPos blockpos, boolean flag) { +- if (flag) { ++ public void setJukeboxPlaying(BlockPos jukeboxPos, boolean jukeboxPlaying) { ++ if (jukeboxPlaying) { + if (!this.isDancing()) { +- this.jukeboxPos = blockpos; ++ this.jukeboxPos = jukeboxPos; + this.setDancing(true); + } +- } else if (blockpos.equals(this.jukeboxPos) || this.jukeboxPos == null) { ++ } else if (jukeboxPos.equals(this.jukeboxPos) || this.jukeboxPos == null) { + this.jukeboxPos = null; + this.setDancing(false); + } +@@ -366,79 +358,72 @@ + } + + @Override +- @Override + public SimpleContainer getInventory() { + return this.inventory; + } + + @Override +- @Override + protected Vec3i getPickupReach() { + return Allay.ITEM_PICKUP_REACH; + } + + @Override +- @Override +- public boolean wantsToPickUp(ItemStack itemstack) { +- ItemStack itemstack1 = this.getItemInHand(InteractionHand.MAIN_HAND); ++ public boolean wantsToPickUp(ItemStack stack) { ++ ItemStack itemstack1 = this.getItemInHand(EnumHand.MAIN_HAND); + +- return !itemstack1.isEmpty() && this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && this.inventory.canAddItem(itemstack) && this.allayConsidersItemEqual(itemstack1, itemstack); ++ return !itemstack1.isEmpty() && this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && this.inventory.canAddItem(stack) && this.allayConsidersItemEqual(itemstack1, stack); + } + +- private boolean allayConsidersItemEqual(ItemStack itemstack, ItemStack itemstack1) { +- return ItemStack.isSameItem(itemstack, itemstack1) && !this.hasNonMatchingPotion(itemstack, itemstack1); ++ private boolean allayConsidersItemEqual(ItemStack first, ItemStack second) { ++ return ItemStack.isSameItem(first, second) && !this.hasNonMatchingPotion(first, second); + } + +- private boolean hasNonMatchingPotion(ItemStack itemstack, ItemStack itemstack1) { +- CompoundTag compoundtag = itemstack.getTag(); +- boolean flag = compoundtag != null && compoundtag.contains("Potion"); ++ private boolean hasNonMatchingPotion(ItemStack first, ItemStack second) { ++ CompoundTag nbttagcompound = first.getTag(); ++ boolean flag = nbttagcompound != null && nbttagcompound.contains("Potion"); + + if (!flag) { + return false; + } else { +- CompoundTag compoundtag1 = itemstack1.getTag(); +- boolean flag1 = compoundtag1 != null && compoundtag1.contains("Potion"); ++ CompoundTag nbttagcompound1 = second.getTag(); ++ boolean flag1 = nbttagcompound1 != null && nbttagcompound1.contains("Potion"); + + if (!flag1) { + return true; + } else { +- Tag tag = compoundtag.get("Potion"); +- Tag tag1 = compoundtag1.get("Potion"); ++ Tag nbtbase = nbttagcompound.get("Potion"); ++ Tag nbtbase1 = nbttagcompound1.get("Potion"); + +- return tag != null && tag1 != null && !tag.equals(tag1); ++ return nbtbase != null && nbtbase1 != null && !nbtbase.equals(nbtbase1); + } + } + } + + @Override +- @Override +- protected void pickUpItem(ItemEntity itementity) { +- InventoryCarrier.pickUpItem(this, this, itementity); ++ protected void pickUpItem(ItemEntity itemEntity) { ++ InventoryCarrier.pickUpItem(this, this, itemEntity); + } + + @Override +- @Override + protected void sendDebugPackets() { + super.sendDebugPackets(); + DebugPackets.sendEntityBrain(this); + } + + @Override +- @Override + public boolean isFlapping() { + return !this.onGround(); + } + + @Override +- @Override +- public void updateDynamicGameEventListener(BiConsumer, ServerLevel> biconsumer) { +- Level level = this.level(); ++ public void updateDynamicGameEventListener(BiConsumer, ServerLevel> listenerConsumer) { ++ Level world = this.level(); + +- if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; + +- biconsumer.accept(this.dynamicVibrationListener, serverlevel); +- biconsumer.accept(this.dynamicJukeboxListener, serverlevel); ++ listenerConsumer.accept(this.dynamicVibrationListener, worldserver); ++ listenerConsumer.accept(this.dynamicJukeboxListener, worldserver); + } + + } +@@ -447,18 +432,19 @@ + return (Boolean) this.entityData.get(Allay.DATA_DANCING); + } + +- public void setDancing(boolean flag) { +- if (!this.level().isClientSide && this.isEffectiveAi() && (!flag || !this.isPanicking())) { +- this.entityData.set(Allay.DATA_DANCING, flag); ++ public void setDancing(boolean dancing) { ++ if (!this.level().isClientSide && this.isEffectiveAi() && (!dancing || !this.isPanicking())) { ++ this.entityData.set(Allay.DATA_DANCING, dancing); + } + } + + private boolean shouldStopDancing() { ++ if (this.forceDancing) {return false;} // CraftBukkit + return this.jukeboxPos == null || !this.jukeboxPos.closerToCenterThan(this.position(), (double) GameEvent.JUKEBOX_PLAY.getNotificationRadius()) || !this.level().getBlockState(this.jukeboxPos).is(Blocks.JUKEBOX); + } + +- public float getHoldingItemAnimationProgress(float f) { +- return Mth.lerp(f, this.holdingItemAnimationTicks0, this.holdingItemAnimationTicks) / 5.0F; ++ public float getHoldingItemAnimationProgress(float partialTick) { ++ return Mth.lerp(partialTick, this.holdingItemAnimationTicks0, this.holdingItemAnimationTicks) / 5.0F; + } + + public boolean isSpinning() { +@@ -467,18 +453,16 @@ + return f < 15.0F; + } + +- public float getSpinningProgress(float f) { +- return Mth.lerp(f, this.spinningAnimationTicks0, this.spinningAnimationTicks) / 15.0F; ++ public float getSpinningProgress(float partialTick) { ++ return Mth.lerp(partialTick, this.spinningAnimationTicks0, this.spinningAnimationTicks) / 15.0F; + } + + @Override +- @Override +- public boolean equipmentHasChanged(ItemStack itemstack, ItemStack itemstack1) { +- return !this.allayConsidersItemEqual(itemstack, itemstack1); ++ public boolean equipmentHasChanged(ItemStack oldItem, ItemStack newItem) { ++ return !this.allayConsidersItemEqual(oldItem, newItem); + } + + @Override +- @Override + protected void dropEquipment() { + super.dropEquipment(); + this.inventory.removeAllItems().forEach(this::spawnAtLocation); +@@ -492,48 +476,44 @@ + } + + @Override +- @Override +- public boolean removeWhenFarAway(double d0) { ++ public boolean removeWhenFarAway(double distanceToClosestPlayer) { + return false; + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- this.writeInventoryToTag(compoundtag); +- DataResult dataresult = VibrationSystem.Data.CODEC.encodeStart(NbtOps.INSTANCE, this.vibrationData); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ this.writeInventoryToTag(compound); ++ DataResult dataresult = VibrationSystem.Data.CODEC.encodeStart(NbtOps.INSTANCE, this.vibrationData); // CraftBukkit - decompile error + Logger logger = Allay.LOGGER; + + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((tag) -> { +- compoundtag.put("listener", tag); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("listener", nbtbase); + }); +- compoundtag.putLong("DuplicationCooldown", this.duplicationCooldown); +- compoundtag.putBoolean("CanDuplicate", this.canDuplicate()); ++ compound.putLong("DuplicationCooldown", this.duplicationCooldown); ++ compound.putBoolean("CanDuplicate", this.canDuplicate()); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.readInventoryFromTag(compoundtag); +- if (compoundtag.contains("listener", 10)) { +- DataResult dataresult = VibrationSystem.Data.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compoundtag.getCompound("listener"))); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.readInventoryFromTag(compound); ++ if (compound.contains("listener", 10)) { ++ DataResult dataresult = VibrationSystem.Data.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compound.getCompound("listener"))); // CraftBukkit - decompile error + Logger logger = Allay.LOGGER; + + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((vibrationsystem_data) -> { +- this.vibrationData = vibrationsystem_data; ++ dataresult.resultOrPartial(logger::error).ifPresent((vibrationsystem_a) -> { ++ this.vibrationData = vibrationsystem_a; + }); + } + +- this.duplicationCooldown = (long) compoundtag.getInt("DuplicationCooldown"); +- this.entityData.set(Allay.DATA_CAN_DUPLICATE, compoundtag.getBoolean("CanDuplicate")); ++ this.duplicationCooldown = (long) compound.getInt("DuplicationCooldown"); ++ this.entityData.set(Allay.DATA_CAN_DUPLICATE, compound.getBoolean("CanDuplicate")); + } + + @Override +- @Override + protected boolean shouldStayCloseToLeashHolder() { + return false; + } +@@ -549,11 +529,11 @@ + + } + +- private boolean isDuplicationItem(ItemStack itemstack) { +- return Allay.DUPLICATION_ITEM.test(itemstack); ++ private boolean isDuplicationItem(ItemStack stack) { ++ return Allay.DUPLICATION_ITEM.test(stack); + } + +- private void duplicateAllay() { ++ public Allay duplicateAllay() { // CraftBukkit - return allay + Allay allay = (Allay) EntityType.ALLAY.create(this.level()); + + if (allay != null) { +@@ -561,48 +541,45 @@ + allay.setPersistenceRequired(); + allay.resetDuplicationCooldown(); + this.resetDuplicationCooldown(); +- this.level().addFreshEntity(allay); ++ this.level().addFreshEntity(allay, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DUPLICATION); // CraftBukkit - reason for duplicated allay + } +- ++ return allay; // CraftBukkit + } + +- private void resetDuplicationCooldown() { ++ public void resetDuplicationCooldown() { + this.duplicationCooldown = 6000L; + this.entityData.set(Allay.DATA_CAN_DUPLICATE, false); + } + +- private boolean canDuplicate() { ++ public boolean canDuplicate() { + return (Boolean) this.entityData.get(Allay.DATA_CAN_DUPLICATE); + } + +- private void removeInteractionItem(Player player, ItemStack itemstack) { ++ private void removeInteractionItem(Player player, ItemStack stack) { + if (!player.getAbilities().instabuild) { +- itemstack.shrink(1); ++ stack.shrink(1); + } + + } + + @Override +- @Override + public Vec3 getLeashOffset() { + return new Vec3(0.0D, (double) this.getEyeHeight() * 0.6D, (double) this.getBbWidth() * 0.1D); + } + + @Override +- @Override + protected float ridingOffset(Entity entity) { + return 0.04F; + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 18) { ++ public void handleEntityEvent(byte id) { ++ if (id == 18) { + for (int i = 0; i < 3; ++i) { + this.spawnHeartParticle(); + } + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } +@@ -616,39 +593,34 @@ + } + + @Override +- @Override + public VibrationSystem.Data getVibrationData() { + return this.vibrationData; + } + + @Override +- @Override + public VibrationSystem.User getVibrationUser() { + return this.vibrationUser; + } + +- private class VibrationUser implements VibrationSystem.User { ++ private class b implements VibrationSystem.User { + + private static final int VIBRATION_EVENT_LISTENER_RANGE = 16; + private final PositionSource positionSource = new EntityPositionSource(Allay.this, Allay.this.getEyeHeight()); + +- VibrationUser() {} ++ b() {} + + @Override +- @Override + public int getListenerRadius() { + return 16; + } + + @Override +- @Override + public PositionSource getPositionSource() { + return this.positionSource; + } + + @Override +- @Override +- public boolean canReceiveVibration(ServerLevel serverlevel, BlockPos blockpos, GameEvent gameevent, GameEvent.Context gameevent_context) { ++ public boolean canReceiveVibration(ServerLevel level, BlockPos pos, GameEvent gameEvent, GameEvent.Context context) { + if (Allay.this.isNoAi()) { + return false; + } else { +@@ -659,22 +631,20 @@ + } else { + GlobalPos globalpos = (GlobalPos) optional.get(); + +- return globalpos.dimension().equals(serverlevel.dimension()) && globalpos.pos().equals(blockpos); ++ return globalpos.dimension().equals(level.dimension()) && globalpos.pos().equals(pos); + } + } + } + + @Override +- @Override +- public void onReceiveVibration(ServerLevel serverlevel, BlockPos blockpos, GameEvent gameevent, @Nullable Entity entity, @Nullable Entity entity1, float f) { +- if (gameevent == GameEvent.NOTE_BLOCK_PLAY) { +- AllayAi.hearNoteblock(Allay.this, new BlockPos(blockpos)); ++ public void onReceiveVibration(ServerLevel level, BlockPos pos, GameEvent gameEvent, @Nullable Entity entity, @Nullable Entity playerEntity, float distance) { ++ if (gameEvent == GameEvent.NOTE_BLOCK_PLAY) { ++ AllayAi.hearNoteblock(Allay.this, new BlockPos(pos)); + } + + } + + @Override +- @Override + public TagKey getListenableEvents() { + return GameEventTags.ALLAY_CAN_LISTEN; + } +@@ -691,25 +661,22 @@ + } + + @Override +- @Override + public PositionSource getListenerSource() { + return this.listenerSource; + } + + @Override +- @Override + public int getListenerRadius() { + return this.listenerRadius; + } + + @Override +- @Override +- public boolean handleGameEvent(ServerLevel serverlevel, GameEvent gameevent, GameEvent.Context gameevent_context, Vec3 vec3) { +- if (gameevent == GameEvent.JUKEBOX_PLAY) { +- Allay.this.setJukeboxPlaying(BlockPos.containing(vec3), true); ++ public boolean handleGameEvent(ServerLevel level, GameEvent gameEvent, GameEvent.Context context, Vec3 pos) { ++ if (gameEvent == GameEvent.JUKEBOX_PLAY) { ++ Allay.this.setJukeboxPlaying(BlockPos.containing(pos), true); + return true; +- } else if (gameevent == GameEvent.JUKEBOX_STOP_PLAY) { +- Allay.this.setJukeboxPlaying(BlockPos.containing(vec3), false); ++ } else if (gameEvent == GameEvent.JUKEBOX_STOP_PLAY) { ++ Allay.this.setJukeboxPlaying(BlockPos.containing(pos), false); + return true; + } else { + return false; diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/axolotl/Axolotl.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/axolotl/Axolotl.java.patch new file mode 100644 index 0000000000..3db2df16b3 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/axolotl/Axolotl.java.patch @@ -0,0 +1,657 @@ +--- a/net/minecraft/world/entity/animal/axolotl/Axolotl.java ++++ b/net/minecraft/world/entity/animal/axolotl/Axolotl.java +@@ -26,7 +26,7 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.util.StringRepresentable; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffectInstance; +@@ -34,15 +34,15 @@ + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; ++import net.minecraft.world.entity.EnumMoveType; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LerpingModel; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.VariantHolder; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -68,9 +68,16 @@ + + public class Axolotl extends Animal implements LerpingModel, VariantHolder, Bucketable { + ++ // CraftBukkit start - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ @Override ++ public int getDefaultMaxAirSupply() { ++ return AXOLOTL_TOTAL_AIR_SUPPLY; ++ } ++ // CraftBukkit end + public static final int TOTAL_PLAYDEAD_TIME = 200; + protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_ADULT, SensorType.HURT_BY, SensorType.AXOLOTL_ATTACKABLES, SensorType.AXOLOTL_TEMPTATIONS); +- protected static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.BREED_TARGET, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.LOOK_TARGET, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.PATH, MemoryModuleType.ATTACK_TARGET, MemoryModuleType.ATTACK_COOLING_DOWN, MemoryModuleType.NEAREST_VISIBLE_ADULT, new MemoryModuleType[]{MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.PLAY_DEAD_TICKS, MemoryModuleType.NEAREST_ATTACKABLE, MemoryModuleType.TEMPTING_PLAYER, MemoryModuleType.TEMPTATION_COOLDOWN_TICKS, MemoryModuleType.IS_TEMPTED, MemoryModuleType.HAS_HUNTING_COOLDOWN, MemoryModuleType.IS_PANICKING}); ++ // CraftBukkit - decompile error ++ protected static final ImmutableList> MEMORY_TYPES = ImmutableList.>of(MemoryModuleType.BREED_TARGET, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.LOOK_TARGET, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.PATH, MemoryModuleType.ATTACK_TARGET, MemoryModuleType.ATTACK_COOLING_DOWN, MemoryModuleType.NEAREST_VISIBLE_ADULT, new MemoryModuleType[]{MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.PLAY_DEAD_TICKS, MemoryModuleType.NEAREST_ATTACKABLE, MemoryModuleType.TEMPTING_PLAYER, MemoryModuleType.TEMPTATION_COOLDOWN_TICKS, MemoryModuleType.IS_TEMPTED, MemoryModuleType.HAS_HUNTING_COOLDOWN, MemoryModuleType.IS_PANICKING}); + private static final EntityDataAccessor DATA_VARIANT = SynchedEntityData.defineId(Axolotl.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_PLAYING_DEAD = SynchedEntityData.defineId(Axolotl.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor FROM_BUCKET = SynchedEntityData.defineId(Axolotl.class, EntityDataSerializers.BOOLEAN); +@@ -83,8 +90,8 @@ + private final Map modelRotationValues = Maps.newHashMap(); + private static final int REGEN_BUFF_BASE_DURATION = 100; + +- public Axolotl(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Axolotl(EntityType entityType, Level level) { ++ super(entityType, level); + this.setPathfindingMalus(BlockPathTypes.WATER, 0.0F); + this.moveControl = new Axolotl.AxolotlMoveControl(this); + this.lookControl = new Axolotl.AxolotlLookControl(this, 20); +@@ -92,19 +99,16 @@ + } + + @Override +- @Override + public Map getModelRotationValues() { + return this.modelRotationValues; + } + + @Override +- @Override +- public float getWalkTargetValue(BlockPos blockpos, LevelReader levelreader) { ++ public float getWalkTargetValue(BlockPos pos, LevelReader level) { + return 0.0F; + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Axolotl.DATA_VARIANT, 0); +@@ -113,23 +117,20 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("Variant", this.getVariant().getId()); +- compoundtag.putBoolean("FromBucket", this.fromBucket()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("Variant", this.getVariant().getId()); ++ compound.putBoolean("FromBucket", this.fromBucket()); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setVariant(Axolotl.Variant.byId(compoundtag.getInt("Variant"))); +- this.setFromBucket(compoundtag.getBoolean("FromBucket")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setVariant(Axolotl.Variant.byId(compound.getInt("Variant"))); ++ this.setFromBucket(compound.getBoolean("FromBucket")); + } + + @Override +- @Override + public void playAmbientSound() { + if (!this.isPlayingDead()) { + super.playAmbientSound(); +@@ -137,34 +138,32 @@ + } + + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + boolean flag = false; + +- if (mobspawntype == MobSpawnType.BUCKET) { +- return (SpawnGroupData) spawngroupdata; ++ if (reason == EnumMobSpawn.BUCKET) { ++ return (GroupDataEntity) spawnData; + } else { +- RandomSource randomsource = serverlevelaccessor.getRandom(); ++ RandomSource randomsource = level.getRandom(); + +- if (spawngroupdata instanceof Axolotl.AxolotlGroupData) { +- if (((Axolotl.AxolotlGroupData) spawngroupdata).getGroupSize() >= 2) { ++ if (spawnData instanceof Axolotl.AxolotlGroupData) { ++ if (((Axolotl.AxolotlGroupData) spawnData).getGroupSize() >= 2) { + flag = true; + } + } else { +- spawngroupdata = new Axolotl.AxolotlGroupData(new Axolotl.Variant[]{Axolotl.Variant.getCommonSpawnVariant(randomsource), Axolotl.Variant.getCommonSpawnVariant(randomsource)}); ++ spawnData = new Axolotl.AxolotlGroupData(new Axolotl.Variant[]{Axolotl.Variant.getCommonSpawnVariant(randomsource), Axolotl.Variant.getCommonSpawnVariant(randomsource)}); + } + +- this.setVariant(((Axolotl.AxolotlGroupData) spawngroupdata).getVariant(randomsource)); ++ this.setVariant(((Axolotl.AxolotlGroupData) spawnData).getVariant(randomsource)); + if (flag) { + this.setAge(-24000); + } + +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, (SpawnGroupData) spawngroupdata, compoundtag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + } + + @Override +- @Override + public void baseTick() { + int i = this.getAirSupply(); + +@@ -175,9 +174,9 @@ + + } + +- protected void handleAirSupply(int i) { ++ protected void handleAirSupply(int airSupply) { + if (this.isAlive() && !this.isInWaterRainOrBubble()) { +- this.setAirSupply(i - 1); ++ this.setAirSupply(airSupply - 1); + if (this.getAirSupply() == -20) { + this.setAirSupply(0); + this.hurt(this.damageSources().dryOut(), 2.0F); +@@ -195,46 +194,40 @@ + } + + @Override +- @Override + public int getMaxAirSupply() { +- return 6000; ++ return maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() + } + + @Override +- @Override + public Axolotl.Variant getVariant() { + return Axolotl.Variant.byId((Integer) this.entityData.get(Axolotl.DATA_VARIANT)); + } + +- @Override + public void setVariant(Axolotl.Variant axolotl_variant) { + this.entityData.set(Axolotl.DATA_VARIANT, axolotl_variant.getId()); + } + +- private static boolean useRareVariant(RandomSource randomsource) { +- return randomsource.nextInt(1200) == 0; ++ private static boolean useRareVariant(RandomSource random) { ++ return random.nextInt(1200) == 0; + } + + @Override +- @Override +- public boolean checkSpawnObstruction(LevelReader levelreader) { +- return levelreader.isUnobstructed(this); ++ public boolean checkSpawnObstruction(LevelReader level) { ++ return level.isUnobstructed(this); + } + + @Override +- @Override + public boolean isPushedByFluid() { + return false; + } + + @Override +- @Override +- public MobType getMobType() { +- return MobType.WATER; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.WATER; + } + +- public void setPlayingDead(boolean flag) { +- this.entityData.set(Axolotl.DATA_PLAYING_DEAD, flag); ++ public void setPlayingDead(boolean playingDead) { ++ this.entityData.set(Axolotl.DATA_PLAYING_DEAD, playingDead); + } + + public boolean isPlayingDead() { +@@ -242,22 +235,19 @@ + } + + @Override +- @Override + public boolean fromBucket() { + return (Boolean) this.entityData.get(Axolotl.FROM_BUCKET); + } + + @Override +- @Override +- public void setFromBucket(boolean flag) { +- this.entityData.set(Axolotl.FROM_BUCKET, flag); ++ public void setFromBucket(boolean fromBucket) { ++ this.entityData.set(Axolotl.FROM_BUCKET, fromBucket); + } + + @Nullable + @Override +- @Override +- public AgeableMob getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { +- Axolotl axolotl = (Axolotl) EntityType.AXOLOTL.create(serverlevel); ++ public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob otherParent) { ++ Axolotl axolotl = (Axolotl) EntityType.AXOLOTL.create(level); + + if (axolotl != null) { + Axolotl.Variant axolotl_variant; +@@ -265,7 +255,7 @@ + if (useRareVariant(this.random)) { + axolotl_variant = Axolotl.Variant.getRareSpawnVariant(this.random); + } else { +- axolotl_variant = this.random.nextBoolean() ? this.getVariant() : ((Axolotl) ageablemob).getVariant(); ++ axolotl_variant = this.random.nextBoolean() ? this.getVariant() : ((Axolotl) otherParent).getVariant(); + } + + axolotl.setVariant(axolotl_variant); +@@ -276,19 +266,16 @@ + } + + @Override +- @Override +- public boolean isFood(ItemStack itemstack) { +- return itemstack.is(ItemTags.AXOLOTL_TEMPT_ITEMS); ++ public boolean isFood(ItemStack stack) { ++ return stack.is(ItemTags.AXOLOTL_TEMPT_ITEMS); + } + + @Override +- @Override + public boolean canBeLeashed(Player player) { + return true; + } + + @Override +- @Override + protected void customServerAiStep() { + this.level().getProfiler().push("axolotlBrain"); + this.getBrain().tick((ServerLevel) this.level(), this); +@@ -309,18 +296,16 @@ + } + + @Override +- @Override + protected PathNavigation createNavigation(Level level) { + return new AmphibiousPathNavigation(this, level); + } + + @Override +- @Override +- public boolean doHurtTarget(Entity entity) { +- boolean flag = entity.hurt(this.damageSources().mobAttack(this), (float) ((int) this.getAttributeValue(Attributes.ATTACK_DAMAGE))); ++ public boolean doHurtTarget(Entity target) { ++ boolean flag = target.hurt(this.damageSources().mobAttack(this), (float) ((int) this.getAttributeValue(Attributes.ATTACK_DAMAGE))); + + if (flag) { +- this.doEnchantDamageEffects(this, entity); ++ this.doEnchantDamageEffects(this, target); + this.playSound(SoundEvents.AXOLOTL_ATTACK, 1.0F, 1.0F); + } + +@@ -328,105 +313,95 @@ + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { ++ public boolean hurt(DamageSource source, float amount) { + float f1 = this.getHealth(); + +- if (!this.level().isClientSide && !this.isNoAi() && this.level().random.nextInt(3) == 0 && ((float) this.level().random.nextInt(3) < f || f1 / this.getMaxHealth() < 0.5F) && f < f1 && this.isInWater() && (damagesource.getEntity() != null || damagesource.getDirectEntity() != null) && !this.isPlayingDead()) { ++ if (!this.level().isClientSide && !this.isNoAi() && this.level().random.nextInt(3) == 0 && ((float) this.level().random.nextInt(3) < amount || f1 / this.getMaxHealth() < 0.5F) && amount < f1 && this.isInWater() && (source.getEntity() != null || source.getDirectEntity() != null) && !this.isPlayingDead()) { + this.brain.setMemory(MemoryModuleType.PLAY_DEAD_TICKS, (int) 200); + } + +- return super.hurt(damagesource, f); ++ return super.hurt(source, amount); + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return entitydimensions.height * 0.655F; ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions dimensions) { ++ return dimensions.height * 0.655F; + } + + @Override +- @Override + public int getMaxHeadXRot() { + return 1; + } + + @Override +- @Override + public int getMaxHeadYRot() { + return 1; + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- return (InteractionResult) Bucketable.bucketMobPickup(player, interactionhand, this).orElse(super.mobInteract(player, interactionhand)); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ return (InteractionResult) Bucketable.bucketMobPickup(player, hand, this).orElse(super.mobInteract(player, hand)); + } + + @Override +- @Override +- public void saveToBucketTag(ItemStack itemstack) { +- Bucketable.saveDefaultDataToBucketTag(this, itemstack); +- CompoundTag compoundtag = itemstack.getOrCreateTag(); ++ public void saveToBucketTag(ItemStack stack) { ++ Bucketable.saveDefaultDataToBucketTag(this, stack); ++ CompoundTag nbttagcompound = stack.getOrCreateTag(); + +- compoundtag.putInt("Variant", this.getVariant().getId()); +- compoundtag.putInt("Age", this.getAge()); +- Brain brain = this.getBrain(); ++ nbttagcompound.putInt("Variant", this.getVariant().getId()); ++ nbttagcompound.putInt("Age", this.getAge()); ++ Brain behaviorcontroller = this.getBrain(); + +- if (brain.hasMemoryValue(MemoryModuleType.HAS_HUNTING_COOLDOWN)) { +- compoundtag.putLong("HuntingCooldown", brain.getTimeUntilExpiry(MemoryModuleType.HAS_HUNTING_COOLDOWN)); ++ if (behaviorcontroller.hasMemoryValue(MemoryModuleType.HAS_HUNTING_COOLDOWN)) { ++ nbttagcompound.putLong("HuntingCooldown", behaviorcontroller.getTimeUntilExpiry(MemoryModuleType.HAS_HUNTING_COOLDOWN)); + } + + } + + @Override +- @Override +- public void loadFromBucketTag(CompoundTag compoundtag) { +- Bucketable.loadDefaultDataFromBucketTag(this, compoundtag); +- this.setVariant(Axolotl.Variant.byId(compoundtag.getInt("Variant"))); +- if (compoundtag.contains("Age")) { +- this.setAge(compoundtag.getInt("Age")); ++ public void loadFromBucketTag(CompoundTag tag) { ++ Bucketable.loadDefaultDataFromBucketTag(this, tag); ++ this.setVariant(Axolotl.Variant.byId(tag.getInt("Variant"))); ++ if (tag.contains("Age")) { ++ this.setAge(tag.getInt("Age")); + } + +- if (compoundtag.contains("HuntingCooldown")) { +- this.getBrain().setMemoryWithExpiry(MemoryModuleType.HAS_HUNTING_COOLDOWN, true, compoundtag.getLong("HuntingCooldown")); ++ if (tag.contains("HuntingCooldown")) { ++ this.getBrain().setMemoryWithExpiry(MemoryModuleType.HAS_HUNTING_COOLDOWN, true, tag.getLong("HuntingCooldown")); + } + + } + + @Override +- @Override + public ItemStack getBucketItemStack() { + return new ItemStack(Items.AXOLOTL_BUCKET); + } + + @Override +- @Override + public SoundEvent getPickupSound() { + return SoundEvents.BUCKET_FILL_AXOLOTL; + } + + @Override +- @Override + public boolean canBeSeenAsEnemy() { + return !this.isPlayingDead() && super.canBeSeenAsEnemy(); + } + +- public static void onStopAttacking(Axolotl axolotl, LivingEntity livingentity) { +- Level level = axolotl.level(); ++ public static void onStopAttacking(Axolotl axolotl, LivingEntity target) { ++ Level world = axolotl.level(); + +- if (livingentity.isDeadOrDying()) { +- DamageSource damagesource = livingentity.getLastDamageSource(); ++ if (target.isDeadOrDying()) { ++ DamageSource damagesource = target.getLastDamageSource(); + + if (damagesource != null) { + Entity entity = damagesource.getEntity(); + + if (entity != null && entity.getType() == EntityType.PLAYER) { +- Player player = (Player) entity; +- List list = level.getEntitiesOfClass(Player.class, axolotl.getBoundingBox().inflate(20.0D)); ++ Player entityhuman = (Player) entity; ++ List list = world.getEntitiesOfClass(Player.class, axolotl.getBoundingBox().inflate(20.0D)); + +- if (list.contains(player)) { +- axolotl.applySupportingEffects(player); ++ if (list.contains(entityhuman)) { ++ axolotl.applySupportingEffects(entityhuman); + } + } + } +@@ -435,113 +410,100 @@ + } + + public void applySupportingEffects(Player player) { +- MobEffectInstance mobeffectinstance = player.getEffect(MobEffects.REGENERATION); ++ MobEffectInstance mobeffect = player.getEffect(MobEffects.REGENERATION); + +- if (mobeffectinstance == null || mobeffectinstance.endsWithin(2399)) { +- int i = mobeffectinstance != null ? mobeffectinstance.getDuration() : 0; ++ if (mobeffect == null || mobeffect.endsWithin(2399)) { ++ int i = mobeffect != null ? mobeffect.getDuration() : 0; + int j = Math.min(2400, 100 + i); + +- player.addEffect(new MobEffectInstance(MobEffects.REGENERATION, j, 0), this); ++ player.addEffect(new MobEffectInstance(MobEffects.REGENERATION, j, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AXOLOTL); // CraftBukkit + } + + player.removeEffect(MobEffects.DIG_SLOWDOWN); + } + + @Override +- @Override + public boolean requiresCustomPersistence() { + return super.requiresCustomPersistence() || this.fromBucket(); + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.AXOLOTL_HURT; + } + + @Nullable + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.AXOLOTL_DEATH; + } + + @Nullable + @Override +- @Override + protected SoundEvent getAmbientSound() { + return this.isInWater() ? SoundEvents.AXOLOTL_IDLE_WATER : SoundEvents.AXOLOTL_IDLE_AIR; + } + + @Override +- @Override + protected SoundEvent getSwimSplashSound() { + return SoundEvents.AXOLOTL_SPLASH; + } + + @Override +- @Override + protected SoundEvent getSwimSound() { + return SoundEvents.AXOLOTL_SWIM; + } + + @Override +- @Override + protected Brain.Provider brainProvider() { + return Brain.provider(Axolotl.MEMORY_TYPES, Axolotl.SENSOR_TYPES); + } + + @Override +- @Override + protected Brain makeBrain(Dynamic dynamic) { + return AxolotlAi.makeBrain(this.brainProvider().makeBrain(dynamic)); + } + + @Override +- @Override + public Brain getBrain() { +- return super.getBrain(); ++ return (Brain) super.getBrain(); // CraftBukkit - decompile error + } + + @Override +- @Override + protected void sendDebugPackets() { + super.sendDebugPackets(); + DebugPackets.sendEntityBrain(this); + } + + @Override +- @Override +- public void travel(Vec3 vec3) { ++ public void travel(Vec3 travelVector) { + if (this.isControlledByLocalInstance() && this.isInWater()) { +- this.moveRelative(this.getSpeed(), vec3); +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.moveRelative(this.getSpeed(), travelVector); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + this.setDeltaMovement(this.getDeltaMovement().scale(0.9D)); + } else { +- super.travel(vec3); ++ super.travel(travelVector); + } + + } + + @Override +- @Override +- protected void usePlayerItem(Player player, InteractionHand interactionhand, ItemStack itemstack) { +- if (itemstack.is(Items.TROPICAL_FISH_BUCKET)) { +- player.setItemInHand(interactionhand, new ItemStack(Items.WATER_BUCKET)); ++ protected void usePlayerItem(Player player, EnumHand hand, ItemStack stack) { ++ if (stack.is(Items.TROPICAL_FISH_BUCKET)) { ++ player.setItemInHand(hand, new ItemStack(Items.WATER_BUCKET)); + } else { +- super.usePlayerItem(player, interactionhand, itemstack); ++ super.usePlayerItem(player, hand, stack); + } + + } + + @Override +- @Override +- public boolean removeWhenFarAway(double d0) { ++ public boolean removeWhenFarAway(double distanceToClosestPlayer) { + return !this.fromBucket() && !this.hasCustomName(); + } + +- public static boolean checkAxolotlSpawnRules(EntityType entitytype, ServerLevelAccessor serverlevelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- return serverlevelaccessor.getBlockState(blockpos.below()).is(BlockTags.AXOLOTLS_SPAWNABLE_ON); ++ public static boolean checkAxolotlSpawnRules(EntityType axolotl, ServerLevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ return level.getBlockState(pos.below()).is(BlockTags.AXOLOTLS_SPAWNABLE_ON); + } + + private static class AxolotlMoveControl extends SmoothSwimmingMoveControl { +@@ -554,7 +516,6 @@ + } + + @Override +- @Override + public void tick() { + if (!this.axolotl.isPlayingDead()) { + super.tick(); +@@ -570,7 +531,6 @@ + } + + @Override +- @Override + public void tick() { + if (!Axolotl.this.isPlayingDead()) { + super.tick(); +@@ -583,7 +543,7 @@ + + LUCY(0, "lucy", true), WILD(1, "wild", true), GOLD(2, "gold", true), CYAN(3, "cyan", true), BLUE(4, "blue", false); + +- private static final IntFunction BY_ID = ByIdMap.continuous(Axolotl.Variant::getId, values(), ByIdMap.OutOfBoundsStrategy.ZERO); ++ private static final IntFunction BY_ID = ByIdMap.continuous(Axolotl.Variant::getId, values(), ByIdMap.a.ZERO); + public static final Codec CODEC = StringRepresentable.fromEnum(Axolotl.Variant::values); + private final int id; + private final String name; +@@ -604,31 +564,30 @@ + } + + @Override +- @Override + public String getSerializedName() { + return this.name; + } + +- public static Axolotl.Variant byId(int i) { +- return (Axolotl.Variant) Axolotl.Variant.BY_ID.apply(i); ++ public static Axolotl.Variant byId(int id) { ++ return (Axolotl.Variant) Axolotl.Variant.BY_ID.apply(id); + } + +- public static Axolotl.Variant getCommonSpawnVariant(RandomSource randomsource) { +- return getSpawnVariant(randomsource, true); ++ public static Axolotl.Variant getCommonSpawnVariant(RandomSource random) { ++ return getSpawnVariant(random, true); + } + +- public static Axolotl.Variant getRareSpawnVariant(RandomSource randomsource) { +- return getSpawnVariant(randomsource, false); ++ public static Axolotl.Variant getRareSpawnVariant(RandomSource random) { ++ return getSpawnVariant(random, false); + } + +- private static Axolotl.Variant getSpawnVariant(RandomSource randomsource, boolean flag) { ++ private static Axolotl.Variant getSpawnVariant(RandomSource random, boolean common) { + Axolotl.Variant[] aaxolotl_variant = (Axolotl.Variant[]) Arrays.stream(values()).filter((axolotl_variant) -> { +- return axolotl_variant.common == flag; ++ return axolotl_variant.common == common; + }).toArray((i) -> { + return new Axolotl.Variant[i]; + }); + +- return (Axolotl.Variant) Util.getRandom((Object[]) aaxolotl_variant, randomsource); ++ return (Axolotl.Variant) Util.getRandom((Object[]) aaxolotl_variant, random); + } + } + +@@ -636,13 +595,13 @@ + + public final Axolotl.Variant[] types; + +- public AxolotlGroupData(Axolotl.Variant... aaxolotl_variant) { ++ public AxolotlGroupData(Axolotl.Variant... types) { + super(false); +- this.types = aaxolotl_variant; ++ this.types = types; + } + +- public Axolotl.Variant getVariant(RandomSource randomsource) { +- return this.types[randomsource.nextInt(this.types.length)]; ++ public Axolotl.Variant getVariant(RandomSource random) { ++ return this.types[random.nextInt(this.types.length)]; + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/frog/Tadpole.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/frog/Tadpole.java.patch new file mode 100644 index 0000000000..ea6d1967a5 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/frog/Tadpole.java.patch @@ -0,0 +1,282 @@ +--- a/net/minecraft/world/entity/animal/frog/Tadpole.java ++++ b/net/minecraft/world/entity/animal/frog/Tadpole.java +@@ -10,14 +10,14 @@ + import net.minecraft.server.level.ServerLevel; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -41,48 +41,42 @@ + public static int ticksToBeFrog = Math.abs(-24000); + public static float HITBOX_WIDTH = 0.4F; + public static float HITBOX_HEIGHT = 0.3F; +- private int age; ++ public int age; + protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.HURT_BY, SensorType.FROG_TEMPTATIONS); + protected static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.LOOK_TARGET, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.PATH, MemoryModuleType.NEAREST_VISIBLE_ADULT, MemoryModuleType.TEMPTATION_COOLDOWN_TICKS, MemoryModuleType.IS_TEMPTED, MemoryModuleType.TEMPTING_PLAYER, MemoryModuleType.BREED_TARGET, MemoryModuleType.IS_PANICKING); + +- public Tadpole(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Tadpole(EntityType entityType, Level level) { ++ super(entityType, level); + this.moveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02F, 0.1F, true); + this.lookControl = new SmoothSwimmingLookControl(this, 10); + } + + @Override +- @Override + protected PathNavigation createNavigation(Level level) { + return new WaterBoundPathNavigation(this, level); + } + + @Override +- @Override + protected Brain.Provider brainProvider() { + return Brain.provider(Tadpole.MEMORY_TYPES, Tadpole.SENSOR_TYPES); + } + + @Override +- @Override + protected Brain makeBrain(Dynamic dynamic) { + return TadpoleAi.makeBrain(this.brainProvider().makeBrain(dynamic)); + } + + @Override +- @Override + public Brain getBrain() { +- return super.getBrain(); ++ return (Brain) super.getBrain(); // CraftBukkit - decompile error + } + + @Override +- @Override + protected SoundEvent getFlopSound() { + return SoundEvents.TADPOLE_FLOP; + } + + @Override +- @Override + protected void customServerAiStep() { + this.level().getProfiler().push("tadpoleBrain"); + this.getBrain().tick((ServerLevel) this.level(), this); +@@ -98,7 +92,6 @@ + } + + @Override +- @Override + public void aiStep() { + super.aiStep(); + if (!this.level().isClientSide) { +@@ -108,114 +101,101 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("Age", this.age); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("Age", this.age); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setAge(compoundtag.getInt("Age")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setAge(compound.getInt("Age")); + } + + @Nullable + @Override +- @Override + protected SoundEvent getAmbientSound() { + return null; + } + + @Nullable + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.TADPOLE_HURT; + } + + @Nullable + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.TADPOLE_DEATH; + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (this.isFood(itemstack)) { + this.feed(player, itemstack); + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { +- return (InteractionResult) Bucketable.bucketMobPickup(player, interactionhand, this).orElse(super.mobInteract(player, interactionhand)); ++ return (InteractionResult) Bucketable.bucketMobPickup(player, hand, this).orElse(super.mobInteract(player, hand)); + } + } + + @Override +- @Override + protected void sendDebugPackets() { + super.sendDebugPackets(); + DebugPackets.sendEntityBrain(this); + } + + @Override +- @Override + public boolean fromBucket() { + return true; + } + + @Override +- @Override +- public void setFromBucket(boolean flag) {} ++ public void setFromBucket(boolean fromBucket) {} + + @Override +- @Override +- public void saveToBucketTag(ItemStack itemstack) { +- Bucketable.saveDefaultDataToBucketTag(this, itemstack); +- CompoundTag compoundtag = itemstack.getOrCreateTag(); ++ public void saveToBucketTag(ItemStack stack) { ++ Bucketable.saveDefaultDataToBucketTag(this, stack); ++ CompoundTag nbttagcompound = stack.getOrCreateTag(); + +- compoundtag.putInt("Age", this.getAge()); ++ nbttagcompound.putInt("Age", this.getAge()); + } + + @Override +- @Override +- public void loadFromBucketTag(CompoundTag compoundtag) { +- Bucketable.loadDefaultDataFromBucketTag(this, compoundtag); +- if (compoundtag.contains("Age")) { +- this.setAge(compoundtag.getInt("Age")); ++ public void loadFromBucketTag(CompoundTag tag) { ++ Bucketable.loadDefaultDataFromBucketTag(this, tag); ++ if (tag.contains("Age")) { ++ this.setAge(tag.getInt("Age")); + } + + } + + @Override +- @Override + public ItemStack getBucketItemStack() { + return new ItemStack(Items.TADPOLE_BUCKET); + } + + @Override +- @Override + public SoundEvent getPickupSound() { + return SoundEvents.BUCKET_FILL_TADPOLE; + } + +- private boolean isFood(ItemStack itemstack) { +- return Frog.TEMPTATION_ITEM.test(itemstack); ++ private boolean isFood(ItemStack stack) { ++ return Frog.TEMPTATION_ITEM.test(stack); + } + +- private void feed(Player player, ItemStack itemstack) { +- this.usePlayerItem(player, itemstack); ++ private void feed(Player player, ItemStack stack) { ++ this.usePlayerItem(player, stack); + this.ageUp(AgeableMob.getSpeedUpSecondsWhenFeeding(this.getTicksLeftUntilAdult())); + this.level().addParticle(ParticleTypes.HAPPY_VILLAGER, this.getRandomX(1.0D), this.getRandomY() + 0.5D, this.getRandomZ(1.0D), 0.0D, 0.0D, 0.0D); + } + +- private void usePlayerItem(Player player, ItemStack itemstack) { ++ private void usePlayerItem(Player player, ItemStack stack) { + if (!player.getAbilities().instabuild) { +- itemstack.shrink(1); ++ stack.shrink(1); + } + + } +@@ -224,12 +204,12 @@ + return this.age; + } + +- private void ageUp(int i) { +- this.setAge(this.age + i * 20); ++ private void ageUp(int offset) { ++ this.setAge(this.age + offset * 20); + } + +- private void setAge(int i) { +- this.age = i; ++ private void setAge(int age) { ++ this.age = age; + if (this.age >= Tadpole.ticksToBeFrog) { + this.ageUp(); + } +@@ -237,15 +217,15 @@ + } + + private void ageUp() { +- Level level = this.level(); ++ Level world = this.level(); + +- if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; + Frog frog = (Frog) EntityType.FROG.create(this.level()); + + if (frog != null) { + frog.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); +- frog.finalizeSpawn(serverlevel, this.level().getCurrentDifficultyAt(frog.blockPosition()), MobSpawnType.CONVERSION, (SpawnGroupData) null, (CompoundTag) null); ++ frog.finalizeSpawn(worldserver, this.level().getCurrentDifficultyAt(frog.blockPosition()), EnumMobSpawn.CONVERSION, (GroupDataEntity) null, (CompoundTag) null); + frog.setNoAi(this.isNoAi()); + if (this.hasCustomName()) { + frog.setCustomName(this.getCustomName()); +@@ -253,8 +233,14 @@ + } + + frog.setPersistenceRequired(); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTransformEvent(this, frog, org.bukkit.event.entity.EntityTransformEvent.TransformReason.METAMORPHOSIS).isCancelled()) { ++ this.setAge(0); // Sets the age to 0 for avoid a loop if the event is canceled ++ return; ++ } ++ // CraftBukkit end + this.playSound(SoundEvents.TADPOLE_GROW_UP, 0.15F, 1.0F); +- serverlevel.addFreshEntityWithPassengers(frog); ++ worldserver.addFreshEntityWithPassengers(frog, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.METAMORPHOSIS); // CraftBukkit - add SpawnReason + this.discard(); + } + } +@@ -266,7 +252,6 @@ + } + + @Override +- @Override + public boolean shouldDropExperience() { + return false; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/goat/Goat.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/goat/Goat.java.patch new file mode 100644 index 0000000000..3c43e07589 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/goat/Goat.java.patch @@ -0,0 +1,388 @@ +--- a/net/minecraft/world/entity/animal/goat/Goat.java ++++ b/net/minecraft/world/entity/animal/goat/Goat.java +@@ -22,17 +22,17 @@ + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -50,11 +50,17 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.ServerLevelAccessor; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerBucketFillEvent; ++// CraftBukkit end ++ + public class Goat extends Animal { + + public static final EntityDimensions LONG_JUMPING_DIMENSIONS = EntityDimensions.scalable(0.9F, 1.3F).scale(0.7F); +@@ -66,13 +72,13 @@ + public static final double GOAT_SCREAMING_CHANCE = 0.02D; + public static final double UNIHORN_CHANCE = 0.10000000149011612D; + private static final EntityDataAccessor DATA_IS_SCREAMING_GOAT = SynchedEntityData.defineId(Goat.class, EntityDataSerializers.BOOLEAN); +- private static final EntityDataAccessor DATA_HAS_LEFT_HORN = SynchedEntityData.defineId(Goat.class, EntityDataSerializers.BOOLEAN); +- private static final EntityDataAccessor DATA_HAS_RIGHT_HORN = SynchedEntityData.defineId(Goat.class, EntityDataSerializers.BOOLEAN); ++ public static final EntityDataAccessor DATA_HAS_LEFT_HORN = SynchedEntityData.defineId(Goat.class, EntityDataSerializers.BOOLEAN); ++ public static final EntityDataAccessor DATA_HAS_RIGHT_HORN = SynchedEntityData.defineId(Goat.class, EntityDataSerializers.BOOLEAN); + private boolean isLoweringHead; + private int lowerHeadTick; + +- public Goat(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Goat(EntityType entityType, Level level) { ++ super(entityType, level); + this.getNavigation().setCanFloat(true); + this.setPathfindingMalus(BlockPathTypes.POWDER_SNOW, -1.0F); + this.setPathfindingMalus(BlockPathTypes.DANGER_POWDER_SNOW, -1.0F); +@@ -87,13 +93,11 @@ + } + + @Override +- @Override + protected Brain.Provider brainProvider() { + return Brain.provider(Goat.MEMORY_TYPES, Goat.SENSOR_TYPES); + } + + @Override +- @Override + protected Brain makeBrain(Dynamic dynamic) { + return GoatAi.makeBrain(this.brainProvider().makeBrain(dynamic)); + } +@@ -103,7 +107,6 @@ + } + + @Override +- @Override + protected void ageBoundaryReached() { + if (this.isBaby()) { + this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(1.0D); +@@ -116,32 +119,27 @@ + } + + @Override +- @Override +- protected int calculateFallDamage(float f, float f1) { +- return super.calculateFallDamage(f, f1) - 10; ++ protected int calculateFallDamage(float fallDistance, float damageMultiplier) { ++ return super.calculateFallDamage(fallDistance, damageMultiplier) - 10; + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return this.isScreamingGoat() ? SoundEvents.GOAT_SCREAMING_AMBIENT : SoundEvents.GOAT_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return this.isScreamingGoat() ? SoundEvents.GOAT_SCREAMING_HURT : SoundEvents.GOAT_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return this.isScreamingGoat() ? SoundEvents.GOAT_SCREAMING_DEATH : SoundEvents.GOAT_DEATH; + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { ++ protected void playStepSound(BlockPos pos, IBlockData state) { + this.playSound(SoundEvents.GOAT_STEP, 0.15F, 1.0F); + } + +@@ -151,9 +149,8 @@ + + @Nullable + @Override +- @Override +- public Goat getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { +- Goat goat = (Goat) EntityType.GOAT.create(serverlevel); ++ public Goat getBreedOffspring(ServerLevel level, AgeableMob otherParent) { ++ Goat goat = (Goat) EntityType.GOAT.create(level); + + if (goat != null) { + boolean flag; +@@ -161,8 +158,8 @@ + { + label21: + { +- GoatAi.initMemories(goat, serverlevel.getRandom()); +- Object object = serverlevel.getRandom().nextBoolean() ? this : ageablemob; ++ GoatAi.initMemories(goat, level.getRandom()); ++ Object object = level.getRandom().nextBoolean() ? this : otherParent; + + if (object instanceof Goat) { + Goat goat1 = (Goat) object; +@@ -172,7 +169,7 @@ + } + } + +- if (serverlevel.getRandom().nextDouble() >= 0.02D) { ++ if (level.getRandom().nextDouble() >= 0.02D) { + flag = false; + break label22; + } +@@ -190,13 +187,11 @@ + } + + @Override +- @Override + public Brain getBrain() { +- return super.getBrain(); ++ return (Brain) super.getBrain(); // CraftBukkit - decompile error + } + + @Override +- @Override + protected void customServerAiStep() { + this.level().getProfiler().push("goatBrain"); + this.getBrain().tick((ServerLevel) this.level(), this); +@@ -208,112 +203,108 @@ + } + + @Override +- @Override + public int getMaxHeadYRot() { + return 15; + } + + @Override +- @Override +- public void setYHeadRot(float f) { ++ public void setYHeadRot(float rotation) { + int i = this.getMaxHeadYRot(); +- float f1 = Mth.degreesDifference(this.yBodyRot, f); ++ float f1 = Mth.degreesDifference(this.yBodyRot, rotation); + float f2 = Mth.clamp(f1, (float) (-i), (float) i); + + super.setYHeadRot(this.yBodyRot + f2); + } + + @Override +- @Override +- public SoundEvent getEatingSound(ItemStack itemstack) { ++ public SoundEvent getEatingSound(ItemStack stack) { + return this.isScreamingGoat() ? SoundEvents.GOAT_SCREAMING_EAT : SoundEvents.GOAT_EAT; + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (itemstack.is(Items.BUCKET) && !this.isBaby()) { ++ // CraftBukkit start - Got milk? ++ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level(), player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand); ++ ++ if (event.isCancelled()) { ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + player.playSound(this.getMilkingSound(), 1.0F, 1.0F); +- ItemStack itemstack1 = ItemUtils.createFilledResult(itemstack, player, Items.MILK_BUCKET.getDefaultInstance()); ++ ItemStack itemstack1 = ItemUtils.createFilledResult(itemstack, player, CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit + +- player.setItemInHand(interactionhand, itemstack1); ++ player.setItemInHand(hand, itemstack1); + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { +- InteractionResult interactionresult = super.mobInteract(player, interactionhand); ++ InteractionResult enuminteractionresult = super.mobInteract(player, hand); + +- if (interactionresult.consumesAction() && this.isFood(itemstack)) { ++ if (enuminteractionresult.consumesAction() && this.isFood(itemstack)) { + this.level().playSound((Player) null, (Entity) this, this.getEatingSound(itemstack), SoundSource.NEUTRAL, 1.0F, Mth.randomBetween(this.level().random, 0.8F, 1.2F)); + } + +- return interactionresult; ++ return enuminteractionresult; + } + } + + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- RandomSource randomsource = serverlevelaccessor.getRandom(); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ RandomSource randomsource = level.getRandom(); + + GoatAi.initMemories(this, randomsource); + this.setScreamingGoat(randomsource.nextDouble() < 0.02D); + this.ageBoundaryReached(); + if (!this.isBaby() && (double) randomsource.nextFloat() < 0.10000000149011612D) { +- EntityDataAccessor entitydataaccessor = randomsource.nextBoolean() ? Goat.DATA_HAS_LEFT_HORN : Goat.DATA_HAS_RIGHT_HORN; ++ EntityDataAccessor datawatcherobject = randomsource.nextBoolean() ? Goat.DATA_HAS_LEFT_HORN : Goat.DATA_HAS_RIGHT_HORN; + +- this.entityData.set(entitydataaccessor, false); ++ this.entityData.set(datawatcherobject, false); + } + +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); ++ return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + + @Override +- @Override + protected void sendDebugPackets() { + super.sendDebugPackets(); + DebugPackets.sendEntityBrain(this); + } + + @Override +- @Override +- public EntityDimensions getDimensions(Pose pose) { +- return pose == Pose.LONG_JUMPING ? Goat.LONG_JUMPING_DIMENSIONS.scale(this.getScale()) : super.getDimensions(pose); ++ public EntityDimensions getDimensions(EntityPose pose) { ++ return pose == EntityPose.LONG_JUMPING ? Goat.LONG_JUMPING_DIMENSIONS.scale(this.getScale()) : super.getDimensions(pose); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putBoolean("IsScreamingGoat", this.isScreamingGoat()); +- compoundtag.putBoolean("HasLeftHorn", this.hasLeftHorn()); +- compoundtag.putBoolean("HasRightHorn", this.hasRightHorn()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putBoolean("IsScreamingGoat", this.isScreamingGoat()); ++ compound.putBoolean("HasLeftHorn", this.hasLeftHorn()); ++ compound.putBoolean("HasRightHorn", this.hasRightHorn()); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setScreamingGoat(compoundtag.getBoolean("IsScreamingGoat")); +- this.entityData.set(Goat.DATA_HAS_LEFT_HORN, compoundtag.getBoolean("HasLeftHorn")); +- this.entityData.set(Goat.DATA_HAS_RIGHT_HORN, compoundtag.getBoolean("HasRightHorn")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setScreamingGoat(compound.getBoolean("IsScreamingGoat")); ++ this.entityData.set(Goat.DATA_HAS_LEFT_HORN, compound.getBoolean("HasLeftHorn")); ++ this.entityData.set(Goat.DATA_HAS_RIGHT_HORN, compound.getBoolean("HasRightHorn")); + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 58) { ++ public void handleEntityEvent(byte id) { ++ if (id == 58) { + this.isLoweringHead = true; +- } else if (b0 == 59) { ++ } else if (id == 59) { + this.isLoweringHead = false; + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } + + @Override +- @Override + public void aiStep() { + if (this.isLoweringHead) { + ++this.lowerHeadTick; +@@ -326,7 +317,6 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Goat.DATA_IS_SCREAMING_GOAT, false); +@@ -349,25 +339,25 @@ + if (!flag && !flag1) { + return false; + } else { +- EntityDataAccessor entitydataaccessor; ++ EntityDataAccessor datawatcherobject; + + if (!flag) { +- entitydataaccessor = Goat.DATA_HAS_RIGHT_HORN; ++ datawatcherobject = Goat.DATA_HAS_RIGHT_HORN; + } else if (!flag1) { +- entitydataaccessor = Goat.DATA_HAS_LEFT_HORN; ++ datawatcherobject = Goat.DATA_HAS_LEFT_HORN; + } else { +- entitydataaccessor = this.random.nextBoolean() ? Goat.DATA_HAS_LEFT_HORN : Goat.DATA_HAS_RIGHT_HORN; ++ datawatcherobject = this.random.nextBoolean() ? Goat.DATA_HAS_LEFT_HORN : Goat.DATA_HAS_RIGHT_HORN; + } + +- this.entityData.set(entitydataaccessor, false); +- Vec3 vec3 = this.position(); ++ this.entityData.set(datawatcherobject, false); ++ Vec3 vec3d = this.position(); + ItemStack itemstack = this.createHorn(); + double d0 = (double) Mth.randomBetween(this.random, -0.2F, 0.2F); + double d1 = (double) Mth.randomBetween(this.random, 0.3F, 0.7F); + double d2 = (double) Mth.randomBetween(this.random, -0.2F, 0.2F); +- ItemEntity itementity = new ItemEntity(this.level(), vec3.x(), vec3.y(), vec3.z(), itemstack, d0, d1, d2); ++ ItemEntity entityitem = new ItemEntity(this.level(), vec3d.x(), vec3d.y(), vec3d.z(), itemstack, d0, d1, d2); + +- this.level().addFreshEntity(itementity); ++ this.level().addFreshEntity(entityitem); + return true; + } + } +@@ -386,21 +376,20 @@ + return (Boolean) this.entityData.get(Goat.DATA_IS_SCREAMING_GOAT); + } + +- public void setScreamingGoat(boolean flag) { +- this.entityData.set(Goat.DATA_IS_SCREAMING_GOAT, flag); ++ public void setScreamingGoat(boolean isScreamingGoat) { ++ this.entityData.set(Goat.DATA_IS_SCREAMING_GOAT, isScreamingGoat); + } + + public float getRammingXHeadRot() { + return (float) this.lowerHeadTick / 20.0F * 30.0F * 0.017453292F; + } + +- public static boolean checkGoatSpawnRules(EntityType entitytype, LevelAccessor levelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- return levelaccessor.getBlockState(blockpos.below()).is(BlockTags.GOATS_SPAWNABLE_ON) && isBrightEnoughToSpawn(levelaccessor, blockpos); ++ public static boolean checkGoatSpawnRules(EntityType goat, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ return level.getBlockState(pos.below()).is(BlockTags.GOATS_SPAWNABLE_ON) && isBrightEnoughToSpawn(level, pos); + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height - 0.1875F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.1875F * f, 0.0F); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/horse/AbstractHorse.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/horse/AbstractHorse.java.patch new file mode 100644 index 0000000000..b10cb8d2bc --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/horse/AbstractHorse.java.patch @@ -0,0 +1,1184 @@ +--- a/net/minecraft/world/entity/animal/horse/AbstractHorse.java ++++ b/net/minecraft/world/entity/animal/horse/AbstractHorse.java +@@ -27,26 +27,26 @@ + import net.minecraft.world.Container; + import net.minecraft.world.ContainerListener; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.HasCustomInventoryScreen; + import net.minecraft.world.entity.HumanoidArm; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.OwnableEntity; + import net.minecraft.world.entity.PlayerRideableJumping; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.Saddleable; + import net.minecraft.world.entity.SlotAccess; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.Attribute; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -72,13 +72,18 @@ + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.SoundType; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++// CraftBukkit end ++ + public abstract class AbstractHorse extends Animal implements ContainerListener, HasCustomInventoryScreen, OwnableEntity, PlayerRideableJumping, Saddleable { + + public static final int EQUIPMENT_SLOT_OFFSET = 400; +@@ -105,8 +110,8 @@ + }); + private static final float BACKWARDS_MOVE_SPEED_FACTOR = 0.25F; + private static final float SIDEWAYS_MOVE_SPEED_FACTOR = 0.5F; +- private static final Predicate PARENT_HORSE_SELECTOR = (livingentity) -> { +- return livingentity instanceof AbstractHorse && ((AbstractHorse) livingentity).isBred(); ++ private static final Predicate PARENT_HORSE_SELECTOR = (entityliving) -> { ++ return entityliving instanceof AbstractHorse && ((AbstractHorse) entityliving).isBred(); + }; + private static final TargetingConditions MOMMY_TARGETING = TargetingConditions.forNonCombat().range(16.0D).ignoreLineOfSight().selector(AbstractHorse.PARENT_HORSE_SELECTOR); + private static final Ingredient FOOD_ITEMS = Ingredient.of(Items.WHEAT, Items.SUGAR, Blocks.HAY_BLOCK.asItem(), Items.APPLE, Items.GOLDEN_CARROT, Items.GOLDEN_APPLE, Items.ENCHANTED_GOLDEN_APPLE); +@@ -126,7 +131,7 @@ + public int tailCounter; + public int sprintCounter; + protected boolean isJumping; +- protected SimpleContainer inventory; ++ public SimpleContainer inventory; + protected int temper; + protected float playerJumpPendingScale; + protected boolean allowStandSliding; +@@ -140,15 +145,15 @@ + protected int gallopSoundCounter; + @Nullable + private UUID owner; ++ public int maxDomestication = 100; // CraftBukkit - store max domestication value + +- protected AbstractHorse(EntityType entitytype, Level level) { +- super(entitytype, level); ++ protected AbstractHorse(EntityType entityType, Level level) { ++ super(entityType, level); + this.setMaxUpStep(1.0F); + this.createInventory(); + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new PanicGoal(this, 1.2D)); + this.goalSelector.addGoal(1, new RunAroundLikeCrazyGoal(this, 1.2D)); +@@ -170,23 +175,22 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(AbstractHorse.DATA_ID_FLAGS, (byte) 0); + } + +- protected boolean getFlag(int i) { +- return ((Byte) this.entityData.get(AbstractHorse.DATA_ID_FLAGS) & i) != 0; ++ protected boolean getFlag(int flagId) { ++ return ((Byte) this.entityData.get(AbstractHorse.DATA_ID_FLAGS) & flagId) != 0; + } + +- protected void setFlag(int i, boolean flag) { ++ protected void setFlag(int flagId, boolean value) { + byte b0 = (Byte) this.entityData.get(AbstractHorse.DATA_ID_FLAGS); + +- if (flag) { +- this.entityData.set(AbstractHorse.DATA_ID_FLAGS, (byte) (b0 | i)); ++ if (value) { ++ this.entityData.set(AbstractHorse.DATA_ID_FLAGS, (byte) (b0 | flagId)); + } else { +- this.entityData.set(AbstractHorse.DATA_ID_FLAGS, (byte) (b0 & ~i)); ++ this.entityData.set(AbstractHorse.DATA_ID_FLAGS, (byte) (b0 & ~flagId)); + } + + } +@@ -197,7 +201,6 @@ + + @Nullable + @Override +- @Override + public UUID getOwnerUUID() { + return this.owner; + } +@@ -210,18 +213,17 @@ + return this.isJumping; + } + +- public void setTamed(boolean flag) { +- this.setFlag(2, flag); ++ public void setTamed(boolean tamed) { ++ this.setFlag(2, tamed); + } + +- public void setIsJumping(boolean flag) { +- this.isJumping = flag; ++ public void setIsJumping(boolean jumping) { ++ this.isJumping = jumping; + } + + @Override +- @Override +- protected void onLeashDistance(float f) { +- if (f > 6.0F && this.isEating()) { ++ protected void onLeashDistance(float distance) { ++ if (distance > 6.0F && this.isEating()) { + this.setEating(false); + } + +@@ -239,34 +241,31 @@ + return this.getFlag(8); + } + +- public void setBred(boolean flag) { +- this.setFlag(8, flag); ++ public void setBred(boolean breeding) { ++ this.setFlag(8, breeding); + } + + @Override +- @Override + public boolean isSaddleable() { + return this.isAlive() && !this.isBaby() && this.isTamed(); + } + + @Override +- @Override +- public void equipSaddle(@Nullable SoundSource soundsource) { ++ public void equipSaddle(@Nullable SoundSource source) { + this.inventory.setItem(0, new ItemStack(Items.SADDLE)); + } + +- public void equipArmor(Player player, ItemStack itemstack) { +- if (this.isArmor(itemstack)) { +- this.inventory.setItem(1, itemstack.copyWithCount(1)); ++ public void equipArmor(Player player, ItemStack armor) { ++ if (this.isArmor(armor)) { ++ this.inventory.setItem(1, armor.copyWithCount(1)); + if (!player.getAbilities().instabuild) { +- itemstack.shrink(1); ++ armor.shrink(1); + } + } + + } + + @Override +- @Override + public boolean isSaddled() { + return this.getFlag(4); + } +@@ -275,19 +274,18 @@ + return this.temper; + } + +- public void setTemper(int i) { +- this.temper = i; ++ public void setTemper(int temper) { ++ this.temper = temper; + } + +- public int modifyTemper(int i) { +- int j = Mth.clamp(this.getTemper() + i, 0, this.getMaxTemper()); ++ public int modifyTemper(int addedTemper) { ++ int j = Mth.clamp(this.getTemper() + addedTemper, 0, this.getMaxTemper()); + + this.setTemper(j); + return j; + } + + @Override +- @Override + public boolean isPushable() { + return !this.isVehicle(); + } +@@ -295,35 +293,34 @@ + private void eating() { + this.openMouth(); + if (!this.isSilent()) { +- SoundEvent soundevent = this.getEatingSound(); ++ SoundEvent soundeffect = this.getEatingSound(); + +- if (soundevent != null) { +- this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), soundevent, this.getSoundSource(), 1.0F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F); ++ if (soundeffect != null) { ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), soundeffect, this.getSoundSource(), 1.0F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F); + } + } + + } + + @Override +- @Override +- public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { +- if (f > 1.0F) { ++ public boolean causeFallDamage(float fallDistance, float multiplier, DamageSource source) { ++ if (fallDistance > 1.0F) { + this.playSound(SoundEvents.HORSE_LAND, 0.4F, 1.0F); + } + +- int i = this.calculateFallDamage(f, f1); ++ int i = this.calculateFallDamage(fallDistance, multiplier); + + if (i <= 0) { + return false; + } else { +- this.hurt(damagesource, (float) i); ++ this.hurt(source, (float) i); + if (this.isVehicle()) { + Iterator iterator = this.getIndirectPassengers().iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); + +- entity.hurt(damagesource, (float) i); ++ entity.hurt(source, (float) i); + } + } + +@@ -333,25 +330,24 @@ + } + + @Override +- @Override +- protected int calculateFallDamage(float f, float f1) { +- return Mth.ceil((f * 0.5F - 3.0F) * f1); ++ protected int calculateFallDamage(float distance, float damageMultiplier) { ++ return Mth.ceil((distance * 0.5F - 3.0F) * damageMultiplier); + } + + protected int getInventorySize() { + return 2; + } + +- protected void createInventory() { +- SimpleContainer simplecontainer = this.inventory; ++ public void createInventory() { ++ SimpleContainer inventorysubcontainer = this.inventory; + +- this.inventory = new SimpleContainer(this.getInventorySize()); +- if (simplecontainer != null) { +- simplecontainer.removeListener(this); +- int i = Math.min(simplecontainer.getContainerSize(), this.inventory.getContainerSize()); ++ this.inventory = new SimpleContainer(this.getInventorySize(), (org.bukkit.entity.AbstractHorse) this.getBukkitEntity()); // CraftBukkit ++ if (inventorysubcontainer != null) { ++ inventorysubcontainer.removeListener(this); ++ int i = Math.min(inventorysubcontainer.getContainerSize(), this.inventory.getContainerSize()); + + for (int j = 0; j < i; ++j) { +- ItemStack itemstack = simplecontainer.getItem(j); ++ ItemStack itemstack = inventorysubcontainer.getItem(j); + + if (!itemstack.isEmpty()) { + this.inventory.setItem(j, itemstack.copy()); +@@ -370,8 +366,7 @@ + } + + @Override +- @Override +- public void containerChanged(Container container) { ++ public void containerChanged(Container invBasic) { + boolean flag = this.isSaddled(); + + this.updateContainerEquipment(); +@@ -386,9 +381,8 @@ + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- boolean flag = super.hurt(damagesource, f); ++ public boolean hurt(DamageSource source, float amount) { ++ boolean flag = super.hurt(source, amount); + + if (flag && this.random.nextInt(3) == 0) { + this.standIfPossible(); +@@ -412,38 +406,37 @@ + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { +- if (!blockstate.liquid()) { +- BlockState blockstate1 = this.level().getBlockState(blockpos.above()); +- SoundType soundtype = blockstate.getSoundType(); ++ protected void playStepSound(BlockPos pos, IBlockData block) { ++ if (!block.liquid()) { ++ IBlockData iblockdata1 = this.level().getBlockState(pos.above()); ++ SoundType soundeffecttype = block.getSoundType(); + +- if (blockstate1.is(Blocks.SNOW)) { +- soundtype = blockstate1.getSoundType(); ++ if (iblockdata1.is(Blocks.SNOW)) { ++ soundeffecttype = iblockdata1.getSoundType(); + } + + if (this.isVehicle() && this.canGallop) { + ++this.gallopSoundCounter; + if (this.gallopSoundCounter > 5 && this.gallopSoundCounter % 3 == 0) { +- this.playGallopSound(soundtype); ++ this.playGallopSound(soundeffecttype); + } else if (this.gallopSoundCounter <= 5) { +- this.playSound(SoundEvents.HORSE_STEP_WOOD, soundtype.getVolume() * 0.15F, soundtype.getPitch()); ++ this.playSound(SoundEvents.HORSE_STEP_WOOD, soundeffecttype.getVolume() * 0.15F, soundeffecttype.getPitch()); + } +- } else if (this.isWoodSoundType(soundtype)) { +- this.playSound(SoundEvents.HORSE_STEP_WOOD, soundtype.getVolume() * 0.15F, soundtype.getPitch()); ++ } else if (this.isWoodSoundType(soundeffecttype)) { ++ this.playSound(SoundEvents.HORSE_STEP_WOOD, soundeffecttype.getVolume() * 0.15F, soundeffecttype.getPitch()); + } else { +- this.playSound(SoundEvents.HORSE_STEP, soundtype.getVolume() * 0.15F, soundtype.getPitch()); ++ this.playSound(SoundEvents.HORSE_STEP, soundeffecttype.getVolume() * 0.15F, soundeffecttype.getPitch()); + } + + } + } + +- private boolean isWoodSoundType(SoundType soundtype) { +- return soundtype == SoundType.WOOD || soundtype == SoundType.NETHER_WOOD || soundtype == SoundType.STEM || soundtype == SoundType.CHERRY_WOOD || soundtype == SoundType.BAMBOO_WOOD; ++ private boolean isWoodSoundType(SoundType soundType) { ++ return soundType == SoundType.WOOD || soundType == SoundType.NETHER_WOOD || soundType == SoundType.STEM || soundType == SoundType.CHERRY_WOOD || soundType == SoundType.BAMBOO_WOOD; + } + +- protected void playGallopSound(SoundType soundtype) { +- this.playSound(SoundEvents.HORSE_GALLOP, soundtype.getVolume() * 0.15F, soundtype.getPitch()); ++ protected void playGallopSound(SoundType soundType) { ++ this.playSound(SoundEvents.HORSE_GALLOP, soundType.getVolume() * 0.15F, soundType.getPitch()); + } + + public static AttributeSupplier.Builder createBaseHorseAttributes() { +@@ -451,29 +444,25 @@ + } + + @Override +- @Override + public int getMaxSpawnClusterSize() { + return 6; + } + + public int getMaxTemper() { +- return 100; ++ return this.maxDomestication; // CraftBukkit - return stored max domestication instead of 100 + } + + @Override +- @Override + protected float getSoundVolume() { + return 0.8F; + } + + @Override +- @Override + public int getAmbientSoundInterval() { + return 400; + } + + @Override +- @Override + public void openCustomInventoryScreen(Player player) { + if (!this.level().isClientSide && (!this.isVehicle() || this.hasPassenger((Entity) player)) && this.isTamed()) { + player.openHorseInventory(this, this.inventory); +@@ -481,38 +470,38 @@ + + } + +- public InteractionResult fedFood(Player player, ItemStack itemstack) { +- boolean flag = this.handleEating(player, itemstack); ++ public InteractionResult fedFood(Player player, ItemStack stack) { ++ boolean flag = this.handleEating(player, stack); + + if (flag & !player.getAbilities().instabuild) { +- itemstack.shrink(1); ++ stack.shrink(1); + } + + return this.level().isClientSide ? InteractionResult.CONSUME : (flag ? InteractionResult.SUCCESS : InteractionResult.PASS); + } + +- protected boolean handleEating(Player player, ItemStack itemstack) { ++ protected boolean handleEating(Player player, ItemStack stack) { + boolean flag = false; + float f = 0.0F; + short short0 = 0; + byte b0 = 0; + +- if (itemstack.is(Items.WHEAT)) { ++ if (stack.is(Items.WHEAT)) { + f = 2.0F; + short0 = 20; + b0 = 3; +- } else if (itemstack.is(Items.SUGAR)) { ++ } else if (stack.is(Items.SUGAR)) { + f = 1.0F; + short0 = 30; + b0 = 3; +- } else if (itemstack.is(Blocks.HAY_BLOCK.asItem())) { ++ } else if (stack.is(Blocks.HAY_BLOCK.asItem())) { + f = 20.0F; + short0 = 180; +- } else if (itemstack.is(Items.APPLE)) { ++ } else if (stack.is(Items.APPLE)) { + f = 3.0F; + short0 = 60; + b0 = 3; +- } else if (itemstack.is(Items.GOLDEN_CARROT)) { ++ } else if (stack.is(Items.GOLDEN_CARROT)) { + f = 4.0F; + short0 = 60; + b0 = 5; +@@ -520,7 +509,7 @@ + flag = true; + this.setInLove(player); + } +- } else if (itemstack.is(Items.GOLDEN_APPLE) || itemstack.is(Items.ENCHANTED_GOLDEN_APPLE)) { ++ } else if (stack.is(Items.GOLDEN_APPLE) || stack.is(Items.ENCHANTED_GOLDEN_APPLE)) { + f = 10.0F; + short0 = 240; + b0 = 10; +@@ -531,7 +520,7 @@ + } + + if (this.getHealth() < this.getMaxHealth() && f > 0.0F) { +- this.heal(f); ++ this.heal(f, EntityRegainHealthEvent.RegainReason.EATING); // CraftBukkit + flag = true; + } + +@@ -568,15 +557,13 @@ + } + + @Override +- @Override + public boolean isImmobile() { + return super.isImmobile() && this.isVehicle() && this.isSaddled() || this.isEating() || this.isStanding(); + } + + @Override +- @Override +- public boolean isFood(ItemStack itemstack) { +- return AbstractHorse.FOOD_ITEMS.test(itemstack); ++ public boolean isFood(ItemStack stack) { ++ return AbstractHorse.FOOD_ITEMS.test(stack); + } + + private void moveTail() { +@@ -584,7 +571,6 @@ + } + + @Override +- @Override + protected void dropEquipment() { + super.dropEquipment(); + if (this.inventory != null) { +@@ -600,7 +586,6 @@ + } + + @Override +- @Override + public void aiStep() { + if (this.random.nextInt(200) == 0) { + this.moveTail(); +@@ -609,7 +594,7 @@ + super.aiStep(); + if (!this.level().isClientSide && this.isAlive()) { + if (this.random.nextInt(900) == 0 && this.deathTime == 0) { +- this.heal(1.0F); ++ this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit + } + + if (this.canEatGrass()) { +@@ -629,10 +614,10 @@ + + protected void followMommy() { + if (this.isBred() && this.isBaby() && !this.isEating()) { +- LivingEntity livingentity = this.level().getNearestEntity(AbstractHorse.class, AbstractHorse.MOMMY_TARGETING, this, this.getX(), this.getY(), this.getZ(), this.getBoundingBox().inflate(16.0D)); ++ LivingEntity entityliving = this.level().getNearestEntity(AbstractHorse.class, AbstractHorse.MOMMY_TARGETING, this, this.getX(), this.getY(), this.getZ(), this.getBoundingBox().inflate(16.0D)); + +- if (livingentity != null && this.distanceToSqr((Entity) livingentity) > 4.0D) { +- this.navigation.createPath((Entity) livingentity, 0); ++ if (entityliving != null && this.distanceToSqr((Entity) entityliving) > 4.0D) { ++ this.navigation.createPath((Entity) entityliving, 0); + } + } + +@@ -643,7 +628,6 @@ + } + + @Override +- @Override + public void tick() { + super.tick(); + if (this.mouthCounter > 0 && ++this.mouthCounter > 30) { +@@ -712,20 +696,19 @@ + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { ++ public InteractionResult mobInteract(Player player, EnumHand hand) { + if (!this.isVehicle() && !this.isBaby()) { + if (this.isTamed() && player.isSecondaryUseActive()) { + this.openCustomInventoryScreen(player); + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ ItemStack itemstack = player.getItemInHand(hand); + + if (!itemstack.isEmpty()) { +- InteractionResult interactionresult = itemstack.interactLivingEntity(player, this, interactionhand); ++ InteractionResult enuminteractionresult = itemstack.interactLivingEntity(player, this, hand); + +- if (interactionresult.consumesAction()) { +- return interactionresult; ++ if (enuminteractionresult.consumesAction()) { ++ return enuminteractionresult; + } + + if (this.canWearArmor() && this.isArmor(itemstack) && !this.isWearingArmor()) { +@@ -738,7 +721,7 @@ + return InteractionResult.sidedSuccess(this.level().isClientSide); + } + } else { +- return super.mobInteract(player, interactionhand); ++ return super.mobInteract(player, hand); + } + } + +@@ -750,16 +733,16 @@ + + } + +- public void setEating(boolean flag) { +- this.setFlag(16, flag); ++ public void setEating(boolean eating) { ++ this.setFlag(16, eating); + } + +- public void setStanding(boolean flag) { +- if (flag) { ++ public void setStanding(boolean standing) { ++ if (standing) { + this.setEating(false); + } + +- this.setFlag(32, flag); ++ this.setFlag(32, standing); + } + + @Nullable +@@ -778,10 +761,10 @@ + public void makeMad() { + if (!this.isStanding()) { + this.standIfPossible(); +- SoundEvent soundevent = this.getAngrySound(); ++ SoundEvent soundeffect = this.getAngrySound(); + +- if (soundevent != null) { +- this.playSound(soundevent, this.getSoundVolume(), this.getVoicePitch()); ++ if (soundeffect != null) { ++ this.playSound(soundeffect, this.getSoundVolume(), this.getVoicePitch()); + } + } + +@@ -799,22 +782,21 @@ + } + + @Override +- @Override +- protected void tickRidden(Player player, Vec3 vec3) { +- super.tickRidden(player, vec3); +- Vec2 vec2 = this.getRiddenRotation(player); ++ protected void tickRidden(Player player, Vec3 travelVector) { ++ super.tickRidden(player, travelVector); ++ Vec2 vec2f = this.getRiddenRotation(player); + +- this.setRot(vec2.y, vec2.x); ++ this.setRot(vec2f.y, vec2f.x); + this.yRotO = this.yBodyRot = this.yHeadRot = this.getYRot(); + if (this.isControlledByLocalInstance()) { +- if (vec3.z <= 0.0D) { ++ if (travelVector.z <= 0.0D) { + this.gallopSoundCounter = 0; + } + + if (this.onGround()) { + this.setIsJumping(false); + if (this.playerJumpPendingScale > 0.0F && !this.isJumping()) { +- this.executeRidersJump(this.playerJumpPendingScale, vec3); ++ this.executeRidersJump(this.playerJumpPendingScale, travelVector); + } + + this.playerJumpPendingScale = 0.0F; +@@ -823,13 +805,12 @@ + + } + +- protected Vec2 getRiddenRotation(LivingEntity livingentity) { +- return new Vec2(livingentity.getXRot() * 0.5F, livingentity.getYRot()); ++ protected Vec2 getRiddenRotation(LivingEntity entity) { ++ return new Vec2(entity.getXRot() * 0.5F, entity.getYRot()); + } + + @Override +- @Override +- protected Vec3 getRiddenInput(Player player, Vec3 vec3) { ++ protected Vec3 getRiddenInput(Player player, Vec3 travelVector) { + if (this.onGround() && this.playerJumpPendingScale == 0.0F && this.isStanding() && !this.allowStandSliding) { + return Vec3.ZERO; + } else { +@@ -845,24 +826,23 @@ + } + + @Override +- @Override + protected float getRiddenSpeed(Player player) { + return (float) this.getAttributeValue(Attributes.MOVEMENT_SPEED); + } + +- protected void executeRidersJump(float f, Vec3 vec3) { +- double d0 = this.getCustomJump() * (double) f * (double) this.getBlockJumpFactor(); ++ protected void executeRidersJump(float playerJumpPendingScale, Vec3 travelVector) { ++ double d0 = this.getCustomJump() * (double) playerJumpPendingScale * (double) this.getBlockJumpFactor(); + double d1 = d0 + (double) this.getJumpBoostPower(); +- Vec3 vec31 = this.getDeltaMovement(); ++ Vec3 vec3d1 = this.getDeltaMovement(); + +- this.setDeltaMovement(vec31.x, d1, vec31.z); ++ this.setDeltaMovement(vec3d1.x, d1, vec3d1.z); + this.setIsJumping(true); + this.hasImpulse = true; +- if (vec3.z > 0.0D) { ++ if (travelVector.z > 0.0D) { + float f1 = Mth.sin(this.getYRot() * 0.017453292F); + float f2 = Mth.cos(this.getYRot() * 0.017453292F); + +- this.setDeltaMovement(this.getDeltaMovement().add((double) (-0.4F * f1 * f), 0.0D, (double) (0.4F * f2 * f))); ++ this.setDeltaMovement(this.getDeltaMovement().add((double) (-0.4F * f1 * playerJumpPendingScale), 0.0D, (double) (0.4F * f2 * playerJumpPendingScale))); + } + + } +@@ -872,37 +852,36 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putBoolean("EatingHaystack", this.isEating()); +- compoundtag.putBoolean("Bred", this.isBred()); +- compoundtag.putInt("Temper", this.getTemper()); +- compoundtag.putBoolean("Tame", this.isTamed()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putBoolean("EatingHaystack", this.isEating()); ++ compound.putBoolean("Bred", this.isBred()); ++ compound.putInt("Temper", this.getTemper()); ++ compound.putBoolean("Tame", this.isTamed()); + if (this.getOwnerUUID() != null) { +- compoundtag.putUUID("Owner", this.getOwnerUUID()); ++ compound.putUUID("Owner", this.getOwnerUUID()); + } ++ compound.putInt("Bukkit.MaxDomestication", this.maxDomestication); // CraftBukkit + + if (!this.inventory.getItem(0).isEmpty()) { +- compoundtag.put("SaddleItem", this.inventory.getItem(0).save(new CompoundTag())); ++ compound.put("SaddleItem", this.inventory.getItem(0).save(new CompoundTag())); + } + + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setEating(compoundtag.getBoolean("EatingHaystack")); +- this.setBred(compoundtag.getBoolean("Bred")); +- this.setTemper(compoundtag.getInt("Temper")); +- this.setTamed(compoundtag.getBoolean("Tame")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setEating(compound.getBoolean("EatingHaystack")); ++ this.setBred(compound.getBoolean("Bred")); ++ this.setTemper(compound.getInt("Temper")); ++ this.setTamed(compound.getBoolean("Tame")); + UUID uuid; + +- if (compoundtag.hasUUID("Owner")) { +- uuid = compoundtag.getUUID("Owner"); ++ if (compound.hasUUID("Owner")) { ++ uuid = compound.getUUID("Owner"); + } else { +- String s = compoundtag.getString("Owner"); ++ String s = compound.getString("Owner"); + + uuid = OldUsersConverter.convertMobOwnerIfNecessary(this.getServer(), s); + } +@@ -910,9 +889,14 @@ + if (uuid != null) { + this.setOwnerUUID(uuid); + } ++ // CraftBukkit start ++ if (compound.contains("Bukkit.MaxDomestication")) { ++ this.maxDomestication = compound.getInt("Bukkit.MaxDomestication"); ++ } ++ // CraftBukkit end + +- if (compoundtag.contains("SaddleItem", 10)) { +- ItemStack itemstack = ItemStack.of(compoundtag.getCompound("SaddleItem")); ++ if (compound.contains("SaddleItem", 10)) { ++ ItemStack itemstack = ItemStack.of(compound.getCompound("SaddleItem")); + + if (itemstack.is(Items.SADDLE)) { + this.inventory.setItem(0, itemstack); +@@ -923,8 +907,7 @@ + } + + @Override +- @Override +- public boolean canMate(Animal animal) { ++ public boolean canMate(Animal otherAnimal) { + return false; + } + +@@ -934,156 +917,158 @@ + + @Nullable + @Override +- @Override +- public AgeableMob getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { ++ public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob otherParent) { + return null; + } + +- protected void setOffspringAttributes(AgeableMob ageablemob, AbstractHorse abstracthorse) { +- this.setOffspringAttribute(ageablemob, abstracthorse, Attributes.MAX_HEALTH, (double) AbstractHorse.MIN_HEALTH, (double) AbstractHorse.MAX_HEALTH); +- this.setOffspringAttribute(ageablemob, abstracthorse, Attributes.JUMP_STRENGTH, (double) AbstractHorse.MIN_JUMP_STRENGTH, (double) AbstractHorse.MAX_JUMP_STRENGTH); +- this.setOffspringAttribute(ageablemob, abstracthorse, Attributes.MOVEMENT_SPEED, (double) AbstractHorse.MIN_MOVEMENT_SPEED, (double) AbstractHorse.MAX_MOVEMENT_SPEED); ++ protected void setOffspringAttributes(AgeableMob parent, AbstractHorse child) { ++ this.setOffspringAttribute(parent, child, Attributes.MAX_HEALTH, (double) AbstractHorse.MIN_HEALTH, (double) AbstractHorse.MAX_HEALTH); ++ this.setOffspringAttribute(parent, child, Attributes.JUMP_STRENGTH, (double) AbstractHorse.MIN_JUMP_STRENGTH, (double) AbstractHorse.MAX_JUMP_STRENGTH); ++ this.setOffspringAttribute(parent, child, Attributes.MOVEMENT_SPEED, (double) AbstractHorse.MIN_MOVEMENT_SPEED, (double) AbstractHorse.MAX_MOVEMENT_SPEED); + } + +- private void setOffspringAttribute(AgeableMob ageablemob, AbstractHorse abstracthorse, Attribute attribute, double d0, double d1) { +- double d2 = createOffspringAttribute(this.getAttributeBaseValue(attribute), ageablemob.getAttributeBaseValue(attribute), d0, d1, this.random); ++ private void setOffspringAttribute(AgeableMob otherParent, AbstractHorse child, Attribute attribute, double min, double d1) { ++ double d2 = createOffspringAttribute(this.getAttributeBaseValue(attribute), otherParent.getAttributeBaseValue(attribute), min, d1, this.random); + +- abstracthorse.getAttribute(attribute).setBaseValue(d2); ++ child.getAttribute(attribute).setBaseValue(d2); + } + +- static double createOffspringAttribute(double d0, double d1, double d2, double d3, RandomSource randomsource) { +- if (d3 <= d2) { ++ static double createOffspringAttribute(double value1, double d1, double value2, double d3, RandomSource min) { ++ if (d3 <= value2) { + throw new IllegalArgumentException("Incorrect range for an attribute"); + } else { +- d0 = Mth.clamp(d0, d2, d3); +- d1 = Mth.clamp(d1, d2, d3); +- double d4 = 0.15D * (d3 - d2); +- double d5 = Math.abs(d0 - d1) + d4 * 2.0D; +- double d6 = (d0 + d1) / 2.0D; +- double d7 = (randomsource.nextDouble() + randomsource.nextDouble() + randomsource.nextDouble()) / 3.0D - 0.5D; ++ value1 = Mth.clamp(value1, value2, d3); ++ d1 = Mth.clamp(d1, value2, d3); ++ double d4 = 0.15D * (d3 - value2); ++ double d5 = Math.abs(value1 - d1) + d4 * 2.0D; ++ double d6 = (value1 + d1) / 2.0D; ++ double d7 = (min.nextDouble() + min.nextDouble() + min.nextDouble()) / 3.0D - 0.5D; + double d8 = d6 + d5 * d7; + double d9; + + if (d8 > d3) { + d9 = d8 - d3; + return d3 - d9; +- } else if (d8 < d2) { +- d9 = d2 - d8; +- return d2 + d9; ++ } else if (d8 < value2) { ++ d9 = value2 - d8; ++ return value2 + d9; + } else { + return d8; + } + } + } + +- public float getEatAnim(float f) { +- return Mth.lerp(f, this.eatAnimO, this.eatAnim); ++ public float getEatAnim(float partialTick) { ++ return Mth.lerp(partialTick, this.eatAnimO, this.eatAnim); + } + +- public float getStandAnim(float f) { +- return Mth.lerp(f, this.standAnimO, this.standAnim); ++ public float getStandAnim(float partialTick) { ++ return Mth.lerp(partialTick, this.standAnimO, this.standAnim); + } + +- public float getMouthAnim(float f) { +- return Mth.lerp(f, this.mouthAnimO, this.mouthAnim); ++ public float getMouthAnim(float partialTick) { ++ return Mth.lerp(partialTick, this.mouthAnimO, this.mouthAnim); + } + + @Override +- @Override +- public void onPlayerJump(int i) { ++ public void onPlayerJump(int jumpPower) { + if (this.isSaddled()) { +- if (i < 0) { +- i = 0; ++ if (jumpPower < 0) { ++ jumpPower = 0; + } else { + this.allowStandSliding = true; + this.standIfPossible(); + } + +- if (i >= 90) { ++ if (jumpPower >= 90) { + this.playerJumpPendingScale = 1.0F; + } else { +- this.playerJumpPendingScale = 0.4F + 0.4F * (float) i / 90.0F; ++ this.playerJumpPendingScale = 0.4F + 0.4F * (float) jumpPower / 90.0F; + } + + } + } + + @Override +- @Override + public boolean canJump() { + return this.isSaddled(); + } + + @Override +- @Override +- public void handleStartJump(int i) { ++ public void handleStartJump(int jumpPower) { ++ // CraftBukkit start ++ float power; ++ if (jumpPower >= 90) { ++ power = 1.0F; ++ } else { ++ power = 0.4F + 0.4F * (float) jumpPower / 90.0F; ++ } ++ if (!CraftEventFactory.callHorseJumpEvent(this, power)) { ++ return; ++ } ++ // CraftBukkit end + this.allowStandSliding = true; + this.standIfPossible(); + this.playJumpSound(); + } + + @Override +- @Override + public void handleStopJump() {} + +- protected void spawnTamingParticles(boolean flag) { +- SimpleParticleType simpleparticletype = flag ? ParticleTypes.HEART : ParticleTypes.SMOKE; ++ protected void spawnTamingParticles(boolean tamed) { ++ SimpleParticleType particletype = tamed ? ParticleTypes.HEART : ParticleTypes.SMOKE; + + for (int i = 0; i < 7; ++i) { + double d0 = this.random.nextGaussian() * 0.02D; + double d1 = this.random.nextGaussian() * 0.02D; + double d2 = this.random.nextGaussian() * 0.02D; + +- this.level().addParticle(simpleparticletype, this.getRandomX(1.0D), this.getRandomY() + 0.5D, this.getRandomZ(1.0D), d0, d1, d2); ++ this.level().addParticle(particletype, this.getRandomX(1.0D), this.getRandomY() + 0.5D, this.getRandomZ(1.0D), d0, d1, d2); + } + + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 7) { ++ public void handleEntityEvent(byte id) { ++ if (id == 7) { + this.spawnTamingParticles(true); +- } else if (b0 == 6) { ++ } else if (id == 6) { + this.spawnTamingParticles(false); + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } + + @Override +- @Override +- protected void positionRider(Entity entity, Entity.MoveFunction entity_movefunction) { +- super.positionRider(entity, entity_movefunction); +- if (entity instanceof LivingEntity) { +- ((LivingEntity) entity).yBodyRot = this.yBodyRot; ++ protected void positionRider(Entity passenger, Entity.MoveFunction callback) { ++ super.positionRider(passenger, callback); ++ if (passenger instanceof LivingEntity) { ++ ((LivingEntity) passenger).yBodyRot = this.yBodyRot; + } + + } + +- protected static float generateMaxHealth(IntUnaryOperator intunaryoperator) { +- return 15.0F + (float) intunaryoperator.applyAsInt(8) + (float) intunaryoperator.applyAsInt(9); ++ protected static float generateMaxHealth(IntUnaryOperator operator) { ++ return 15.0F + (float) operator.applyAsInt(8) + (float) operator.applyAsInt(9); + } + +- protected static double generateJumpStrength(DoubleSupplier doublesupplier) { +- return 0.4000000059604645D + doublesupplier.getAsDouble() * 0.2D + doublesupplier.getAsDouble() * 0.2D + doublesupplier.getAsDouble() * 0.2D; ++ protected static double generateJumpStrength(DoubleSupplier supplier) { ++ return 0.4000000059604645D + supplier.getAsDouble() * 0.2D + supplier.getAsDouble() * 0.2D + supplier.getAsDouble() * 0.2D; + } + +- protected static double generateSpeed(DoubleSupplier doublesupplier) { +- return (0.44999998807907104D + doublesupplier.getAsDouble() * 0.3D + doublesupplier.getAsDouble() * 0.3D + doublesupplier.getAsDouble() * 0.3D) * 0.25D; ++ protected static double generateSpeed(DoubleSupplier supplier) { ++ return (0.44999998807907104D + supplier.getAsDouble() * 0.3D + supplier.getAsDouble() * 0.3D + supplier.getAsDouble() * 0.3D) * 0.25D; + } + + @Override +- @Override + public boolean onClimbable() { + return false; + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return entitydimensions.height * 0.95F; ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { ++ return size.height * 0.95F; + } + + public boolean canWearArmor() { +@@ -1094,25 +1079,23 @@ + return !this.getItemBySlot(EquipmentSlot.CHEST).isEmpty(); + } + +- public boolean isArmor(ItemStack itemstack) { ++ public boolean isArmor(ItemStack stack) { + return false; + } + +- private SlotAccess createEquipmentSlotAccess(final int i, final Predicate predicate) { ++ private SlotAccess createEquipmentSlotAccess(final int slot, final Predicate stackFilter) { + return new SlotAccess() { + @Override +- @Override + public ItemStack get() { +- return AbstractHorse.this.inventory.getItem(i); ++ return AbstractHorse.this.inventory.getItem(slot); + } + + @Override +- @Override +- public boolean set(ItemStack itemstack) { +- if (!predicate.test(itemstack)) { ++ public boolean set(ItemStack carried) { ++ if (!stackFilter.test(carried)) { + return false; + } else { +- AbstractHorse.this.inventory.setItem(i, itemstack); ++ AbstractHorse.this.inventory.setItem(slot, carried); + AbstractHorse.this.updateContainerEquipment(); + return true; + } +@@ -1121,9 +1104,8 @@ + } + + @Override +- @Override +- public SlotAccess getSlot(int i) { +- int j = i - 400; ++ public SlotAccess getSlot(int slot) { ++ int j = slot - 400; + + if (j >= 0 && j < 2 && j < this.inventory.getContainerSize()) { + if (j == 0) { +@@ -1143,22 +1125,21 @@ + } + } + +- int k = i - 500 + 2; ++ int k = slot - 500 + 2; + +- return k >= 2 && k < this.inventory.getContainerSize() ? SlotAccess.forContainer(this.inventory, k) : super.getSlot(i); ++ return k >= 2 && k < this.inventory.getContainerSize() ? SlotAccess.forContainer(this.inventory, k) : super.getSlot(slot); + } + + @Nullable + @Override +- @Override + public LivingEntity getControllingPassenger() { + if (this.isSaddled()) { + Entity entity = this.getFirstPassenger(); + + if (entity instanceof Player) { +- Player player = (Player) entity; ++ Player entityhuman = (Player) entity; + +- return player; ++ return entityhuman; + } + } + +@@ -1166,38 +1147,38 @@ + } + + @Nullable +- private Vec3 getDismountLocationInDirection(Vec3 vec3, LivingEntity livingentity) { +- double d0 = this.getX() + vec3.x; ++ private Vec3 getDismountLocationInDirection(Vec3 direction, LivingEntity passenger) { ++ double d0 = this.getX() + direction.x; + double d1 = this.getBoundingBox().minY; +- double d2 = this.getZ() + vec3.z; +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); +- UnmodifiableIterator unmodifiableiterator = livingentity.getDismountPoses().iterator(); ++ double d2 = this.getZ() + direction.z; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ UnmodifiableIterator unmodifiableiterator = passenger.getDismountPoses().iterator(); + + while (unmodifiableiterator.hasNext()) { +- Pose pose = (Pose) unmodifiableiterator.next(); ++ EntityPose entitypose = (EntityPose) unmodifiableiterator.next(); + +- blockpos_mutableblockpos.set(d0, d1, d2); ++ blockposition_mutableblockposition.set(d0, d1, d2); + double d3 = this.getBoundingBox().maxY + 0.75D; + + while (true) { +- double d4 = this.level().getBlockFloorHeight(blockpos_mutableblockpos); ++ double d4 = this.level().getBlockFloorHeight(blockposition_mutableblockposition); + +- if ((double) blockpos_mutableblockpos.getY() + d4 > d3) { ++ if ((double) blockposition_mutableblockposition.getY() + d4 > d3) { + break; + } + + if (DismountHelper.isBlockFloorValid(d4)) { +- AABB aabb = livingentity.getLocalBoundsForPose(pose); +- Vec3 vec31 = new Vec3(d0, (double) blockpos_mutableblockpos.getY() + d4, d2); ++ AABB axisalignedbb = passenger.getLocalBoundsForPose(entitypose); ++ Vec3 vec3d1 = new Vec3(d0, (double) blockposition_mutableblockposition.getY() + d4, d2); + +- if (DismountHelper.canDismountTo(this.level(), livingentity, aabb.move(vec31))) { +- livingentity.setPose(pose); +- return vec31; ++ if (DismountHelper.canDismountTo(this.level(), passenger, axisalignedbb.move(vec3d1))) { ++ passenger.setPose(entitypose); ++ return vec3d1; + } + } + +- blockpos_mutableblockpos.move(Direction.UP); +- if ((double) blockpos_mutableblockpos.getY() >= d3) { ++ blockposition_mutableblockposition.move(Direction.UP); ++ if ((double) blockposition_mutableblockposition.getY() >= d3) { + break; + } + } +@@ -1207,37 +1188,35 @@ + } + + @Override +- @Override +- public Vec3 getDismountLocationForPassenger(LivingEntity livingentity) { +- Vec3 vec3 = getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingentity.getBbWidth(), this.getYRot() + (livingentity.getMainArm() == HumanoidArm.RIGHT ? 90.0F : -90.0F)); +- Vec3 vec31 = this.getDismountLocationInDirection(vec3, livingentity); ++ public Vec3 getDismountLocationForPassenger(LivingEntity livingEntity) { ++ Vec3 vec3d = getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingEntity.getBbWidth(), this.getYRot() + (livingEntity.getMainArm() == HumanoidArm.RIGHT ? 90.0F : -90.0F)); ++ Vec3 vec3d1 = this.getDismountLocationInDirection(vec3d, livingEntity); + +- if (vec31 != null) { +- return vec31; ++ if (vec3d1 != null) { ++ return vec3d1; + } else { +- Vec3 vec32 = getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingentity.getBbWidth(), this.getYRot() + (livingentity.getMainArm() == HumanoidArm.LEFT ? 90.0F : -90.0F)); +- Vec3 vec33 = this.getDismountLocationInDirection(vec32, livingentity); ++ Vec3 vec3d2 = getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingEntity.getBbWidth(), this.getYRot() + (livingEntity.getMainArm() == HumanoidArm.LEFT ? 90.0F : -90.0F)); ++ Vec3 vec3d3 = this.getDismountLocationInDirection(vec3d2, livingEntity); + +- return vec33 != null ? vec33 : this.position(); ++ return vec3d3 != null ? vec3d3 : this.position(); + } + } + +- protected void randomizeAttributes(RandomSource randomsource) {} ++ protected void randomizeAttributes(RandomSource random) {} + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- if (spawngroupdata == null) { +- spawngroupdata = new AgeableMob.AgeableMobGroupData(0.2F); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ if (spawnData == null) { ++ spawnData = new AgeableMob.AgeableMobGroupData(0.2F); + } + +- this.randomizeAttributes(serverlevelaccessor.getRandom()); +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, (SpawnGroupData) spawngroupdata, compoundtag); ++ this.randomizeAttributes(level.getRandom()); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + +- public boolean hasInventoryChanged(Container container) { +- return this.inventory != container; ++ public boolean hasInventoryChanged(Container inventory) { ++ return this.inventory != inventory; + } + + public int getAmbientStandInterval() { +@@ -1245,12 +1224,11 @@ + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, this.getPassengersRidingOffsetY(entitydimensions, f) + 0.15F * this.standAnimO * f, -0.7F * this.standAnimO * f); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, this.getPassengersRidingOffsetY(entitysize, f) + 0.15F * this.standAnimO * f, -0.7F * this.standAnimO * f); + } + +- protected float getPassengersRidingOffsetY(EntityDimensions entitydimensions, float f) { +- return entitydimensions.height + (this.isBaby() ? 0.125F : -0.15625F) * f; ++ protected float getPassengersRidingOffsetY(EntityDimensions entitysize, float f) { ++ return entitysize.height + (this.isBaby() ? 0.125F : -0.15625F) * f; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/horse/Llama.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/horse/Llama.java.patch new file mode 100644 index 0000000000..6d6ced965a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/horse/Llama.java.patch @@ -0,0 +1,572 @@ +--- a/net/minecraft/world/entity/animal/horse/Llama.java ++++ b/net/minecraft/world/entity/animal/horse/Llama.java +@@ -25,10 +25,10 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.VariantHolder; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -59,7 +59,7 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.WoolCarpetBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +@@ -76,22 +76,27 @@ + @Nullable + private Llama caravanTail; + +- public Llama(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Llama(EntityType entityType, Level level) { ++ super(entityType, level); + } + + public boolean isTraderLlama() { + return false; + } + +- private void setStrength(int i) { +- this.entityData.set(Llama.DATA_STRENGTH_ID, Math.max(1, Math.min(5, i))); ++ // CraftBukkit start ++ public void setStrengthPublic(int i) { ++ this.setStrength(i); + } ++ // CraftBukkit end ++ private void setStrength(int strength) { ++ this.entityData.set(Llama.DATA_STRENGTH_ID, Math.max(1, Math.min(5, strength))); ++ } + +- private void setRandomStrength(RandomSource randomsource) { +- int i = randomsource.nextFloat() < 0.04F ? 5 : 3; ++ private void setRandomStrength(RandomSource random) { ++ int i = random.nextFloat() < 0.04F ? 5 : 3; + +- this.setStrength(1 + randomsource.nextInt(i)); ++ this.setStrength(1 + random.nextInt(i)); + } + + public int getStrength() { +@@ -99,32 +104,29 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("Variant", this.getVariant().id); +- compoundtag.putInt("Strength", this.getStrength()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("Variant", this.getVariant().id); ++ compound.putInt("Strength", this.getStrength()); + if (!this.inventory.getItem(1).isEmpty()) { +- compoundtag.put("DecorItem", this.inventory.getItem(1).save(new CompoundTag())); ++ compound.put("DecorItem", this.inventory.getItem(1).save(new CompoundTag())); + } + + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- this.setStrength(compoundtag.getInt("Strength")); +- super.readAdditionalSaveData(compoundtag); +- this.setVariant(Llama.Variant.byId(compoundtag.getInt("Variant"))); +- if (compoundtag.contains("DecorItem", 10)) { +- this.inventory.setItem(1, ItemStack.of(compoundtag.getCompound("DecorItem"))); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ this.setStrength(compound.getInt("Strength")); ++ super.readAdditionalSaveData(compound); ++ this.setVariant(Llama.Variant.byId(compound.getInt("Variant"))); ++ if (compound.contains("DecorItem", 10)) { ++ this.inventory.setItem(1, ItemStack.of(compound.getCompound("DecorItem"))); + } + + this.updateContainerEquipment(); + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(1, new RunAroundLikeCrazyGoal(this, 1.2D)); +@@ -146,7 +148,6 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Llama.DATA_STRENGTH_ID, 0); +@@ -155,41 +156,36 @@ + } + + @Override +- @Override + public Llama.Variant getVariant() { + return Llama.Variant.byId((Integer) this.entityData.get(Llama.DATA_VARIANT_ID)); + } + +- @Override +- public void setVariant(Llama.Variant llama_variant) { +- this.entityData.set(Llama.DATA_VARIANT_ID, llama_variant.id); ++ public void setVariant(Llama.Variant variant) { ++ this.entityData.set(Llama.DATA_VARIANT_ID, variant.id); + } + + @Override +- @Override + protected int getInventorySize() { + return this.hasChest() ? 2 + 3 * this.getInventoryColumns() : super.getInventorySize(); + } + + @Override +- @Override +- public boolean isFood(ItemStack itemstack) { +- return Llama.FOOD_ITEMS.test(itemstack); ++ public boolean isFood(ItemStack stack) { ++ return Llama.FOOD_ITEMS.test(stack); + } + + @Override +- @Override +- protected boolean handleEating(Player player, ItemStack itemstack) { ++ protected boolean handleEating(Player player, ItemStack stack) { + byte b0 = 0; + byte b1 = 0; + float f = 0.0F; + boolean flag = false; + +- if (itemstack.is(Items.WHEAT)) { ++ if (stack.is(Items.WHEAT)) { + b0 = 10; + b1 = 3; + f = 2.0F; +- } else if (itemstack.is(Blocks.HAY_BLOCK.asItem())) { ++ } else if (stack.is(Blocks.HAY_BLOCK.asItem())) { + b0 = 90; + b1 = 6; + f = 10.0F; +@@ -221,9 +217,9 @@ + } + + if (flag && !this.isSilent()) { +- SoundEvent soundevent = this.getEatingSound(); ++ SoundEvent soundeffect = this.getEatingSound(); + +- if (soundevent != null) { ++ if (soundeffect != null) { + this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), this.getEatingSound(), this.getSoundSource(), 1.0F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F); + } + } +@@ -232,126 +228,109 @@ + } + + @Override +- @Override + public boolean isImmobile() { + return this.isDeadOrDying() || this.isEating(); + } + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- RandomSource randomsource = serverlevelaccessor.getRandom(); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ RandomSource randomsource = level.getRandom(); + + this.setRandomStrength(randomsource); +- Llama.Variant llama_variant; ++ Llama.Variant entityllama_variant; + +- if (spawngroupdata instanceof Llama.LlamaGroupData) { +- llama_variant = ((Llama.LlamaGroupData) spawngroupdata).variant; ++ if (spawnData instanceof Llama.LlamaGroupData) { ++ entityllama_variant = ((Llama.LlamaGroupData) spawnData).variant; + } else { +- llama_variant = (Llama.Variant) Util.getRandom((Object[]) Llama.Variant.values(), randomsource); +- spawngroupdata = new Llama.LlamaGroupData(llama_variant); ++ entityllama_variant = (Llama.Variant) Util.getRandom((Object[]) Llama.Variant.values(), randomsource); ++ spawnData = new Llama.LlamaGroupData(entityllama_variant); + } + +- this.setVariant(llama_variant); +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, (SpawnGroupData) spawngroupdata, compoundtag); ++ this.setVariant(entityllama_variant); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + + @Override +- @Override + protected boolean canPerformRearing() { + return false; + } + + @Override +- @Override + protected SoundEvent getAngrySound() { + return SoundEvents.LLAMA_ANGRY; + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.LLAMA_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.LLAMA_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.LLAMA_DEATH; + } + + @Nullable + @Override +- @Override + protected SoundEvent getEatingSound() { + return SoundEvents.LLAMA_EAT; + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.LLAMA_STEP, 0.15F, 1.0F); + } + + @Override +- @Override + protected void playChestEquipsSound() { + this.playSound(SoundEvents.LLAMA_CHEST, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); + } + + @Override +- @Override + public int getInventoryColumns() { + return this.getStrength(); + } + + @Override +- @Override + public boolean canWearArmor() { + return true; + } + + @Override +- @Override + public boolean isWearingArmor() { + return !this.inventory.getItem(1).isEmpty(); + } + + @Override +- @Override +- public boolean isArmor(ItemStack itemstack) { +- return itemstack.is(ItemTags.WOOL_CARPETS); ++ public boolean isArmor(ItemStack stack) { ++ return stack.is(ItemTags.WOOL_CARPETS); + } + + @Override +- @Override + public boolean isSaddleable() { + return false; + } + + @Override +- @Override +- public void containerChanged(Container container) { +- DyeColor dyecolor = this.getSwag(); ++ public void containerChanged(Container invBasic) { ++ DyeColor enumcolor = this.getSwag(); + +- super.containerChanged(container); +- DyeColor dyecolor1 = this.getSwag(); ++ super.containerChanged(invBasic); ++ DyeColor enumcolor1 = this.getSwag(); + +- if (this.tickCount > 20 && dyecolor1 != null && dyecolor1 != dyecolor) { ++ if (this.tickCount > 20 && enumcolor1 != null && enumcolor1 != enumcolor) { + this.playSound(SoundEvents.LLAMA_SWAG, 0.5F, 1.0F); + } + + } + + @Override +- @Override + protected void updateContainerEquipment() { + if (!this.level().isClientSide) { + super.updateContainerEquipment(); +@@ -359,13 +338,13 @@ + } + } + +- private void setSwag(@Nullable DyeColor dyecolor) { +- this.entityData.set(Llama.DATA_SWAG_ID, dyecolor == null ? -1 : dyecolor.getId()); ++ private void setSwag(@Nullable DyeColor color) { ++ this.entityData.set(Llama.DATA_SWAG_ID, color == null ? -1 : color.getId()); + } + + @Nullable +- private static DyeColor getDyeColor(ItemStack itemstack) { +- Block block = Block.byItem(itemstack.getItem()); ++ private static DyeColor getDyeColor(ItemStack stack) { ++ Block block = Block.byItem(stack.getItem()); + + return block instanceof WoolCarpetBlock ? ((WoolCarpetBlock) block).getColor() : null; + } +@@ -378,37 +357,34 @@ + } + + @Override +- @Override + public int getMaxTemper() { + return 30; + } + + @Override +- @Override +- public boolean canMate(Animal animal) { +- return animal != this && animal instanceof Llama && this.canParent() && ((Llama) animal).canParent(); ++ public boolean canMate(Animal otherAnimal) { ++ return otherAnimal != this && otherAnimal instanceof Llama && this.canParent() && ((Llama) otherAnimal).canParent(); + } + + @Nullable + @Override +- @Override +- public Llama getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { +- Llama llama = this.makeNewLlama(); ++ public Llama getBreedOffspring(ServerLevel level, AgeableMob otherParent) { ++ Llama entityllama = this.makeNewLlama(); + +- if (llama != null) { +- this.setOffspringAttributes(ageablemob, llama); +- Llama llama1 = (Llama) ageablemob; +- int i = this.random.nextInt(Math.max(this.getStrength(), llama1.getStrength())) + 1; ++ if (entityllama != null) { ++ this.setOffspringAttributes(otherParent, entityllama); ++ Llama entityllama1 = (Llama) otherParent; ++ int i = this.random.nextInt(Math.max(this.getStrength(), entityllama1.getStrength())) + 1; + + if (this.random.nextFloat() < 0.03F) { + ++i; + } + +- llama.setStrength(i); +- llama.setVariant(this.random.nextBoolean() ? this.getVariant() : llama1.getVariant()); ++ entityllama.setStrength(i); ++ entityllama.setVariant(this.random.nextBoolean() ? this.getVariant() : entityllama1.getVariant()); + } + +- return llama; ++ return entityllama; + } + + @Nullable +@@ -416,43 +392,42 @@ + return (Llama) EntityType.LLAMA.create(this.level()); + } + +- private void spit(LivingEntity livingentity) { +- LlamaSpit llamaspit = new LlamaSpit(this.level(), this); +- double d0 = livingentity.getX() - this.getX(); +- double d1 = livingentity.getY(0.3333333333333333D) - llamaspit.getY(); +- double d2 = livingentity.getZ() - this.getZ(); ++ private void spit(LivingEntity target) { ++ LlamaSpit entityllamaspit = new LlamaSpit(this.level(), this); ++ double d0 = target.getX() - this.getX(); ++ double d1 = target.getY(0.3333333333333333D) - entityllamaspit.getY(); ++ double d2 = target.getZ() - this.getZ(); + double d3 = Math.sqrt(d0 * d0 + d2 * d2) * 0.20000000298023224D; + +- llamaspit.shoot(d0, d1 + d3, d2, 1.5F, 10.0F); ++ entityllamaspit.shoot(d0, d1 + d3, d2, 1.5F, 10.0F); + if (!this.isSilent()) { + this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.LLAMA_SPIT, this.getSoundSource(), 1.0F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F); + } + +- this.level().addFreshEntity(llamaspit); ++ this.level().addFreshEntity(entityllamaspit); + this.didSpit = true; + } + +- void setDidSpit(boolean flag) { +- this.didSpit = flag; ++ void setDidSpit(boolean didSpit) { ++ this.didSpit = didSpit; + } + + @Override +- @Override +- public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { +- int i = this.calculateFallDamage(f, f1); ++ public boolean causeFallDamage(float fallDistance, float multiplier, DamageSource source) { ++ int i = this.calculateFallDamage(fallDistance, multiplier); + + if (i <= 0) { + return false; + } else { +- if (f >= 6.0F) { +- this.hurt(damagesource, (float) i); ++ if (fallDistance >= 6.0F) { ++ this.hurt(source, (float) i); + if (this.isVehicle()) { + Iterator iterator = this.getIndirectPassengers().iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); + +- entity.hurt(damagesource, (float) i); ++ entity.hurt(source, (float) i); + } + } + } +@@ -470,8 +445,8 @@ + this.caravanHead = null; + } + +- public void joinCaravan(Llama llama) { +- this.caravanHead = llama; ++ public void joinCaravan(Llama caravanHead) { ++ this.caravanHead = caravanHead; + this.caravanHead.caravanTail = this; + } + +@@ -489,13 +464,11 @@ + } + + @Override +- @Override + protected double followLeashSpeed() { + return 2.0D; + } + + @Override +- @Override + protected void followMommy() { + if (!this.inCaravan() && this.isBaby()) { + super.followMommy(); +@@ -504,27 +477,23 @@ + } + + @Override +- @Override + public boolean canEatGrass() { + return false; + } + + @Override +- @Override +- public void performRangedAttack(LivingEntity livingentity, float f) { +- this.spit(livingentity); ++ public void performRangedAttack(LivingEntity target, float distanceFactor) { ++ this.spit(target); + } + + @Override +- @Override + public Vec3 getLeashOffset() { + return new Vec3(0.0D, 0.75D * (double) this.getEyeHeight(), (double) this.getBbWidth() * 0.5D); + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height - (this.isBaby() ? 0.8125F : 0.5F) * f, -0.3F * f); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - (this.isBaby() ? 0.8125F : 0.5F) * f, -0.3F * f); + } + + public static enum Variant implements StringRepresentable { +@@ -532,7 +501,7 @@ + CREAMY(0, "creamy"), WHITE(1, "white"), BROWN(2, "brown"), GRAY(3, "gray"); + + public static final Codec CODEC = StringRepresentable.fromEnum(Llama.Variant::values); +- private static final IntFunction BY_ID = ByIdMap.continuous(Llama.Variant::getId, values(), ByIdMap.OutOfBoundsStrategy.CLAMP); ++ private static final IntFunction BY_ID = ByIdMap.continuous(Llama.Variant::getId, values(), ByIdMap.a.CLAMP); + final int id; + private final String name; + +@@ -545,12 +514,11 @@ + return this.id; + } + +- public static Llama.Variant byId(int i) { +- return (Llama.Variant) Llama.Variant.BY_ID.apply(i); ++ public static Llama.Variant byId(int id) { ++ return (Llama.Variant) Llama.Variant.BY_ID.apply(id); + } + + @Override +- @Override + public String getSerializedName() { + return this.name; + } +@@ -563,15 +531,14 @@ + } + + @Override +- @Override + public boolean canContinueToUse() { +- Mob mob = this.mob; ++ Mob entityinsentient = this.mob; + +- if (mob instanceof Llama) { +- Llama llama = (Llama) mob; ++ if (entityinsentient instanceof Llama) { ++ Llama entityllama = (Llama) entityinsentient; + +- if (llama.didSpit) { +- llama.setDidSpit(false); ++ if (entityllama.didSpit) { ++ entityllama.setDidSpit(false); + return false; + } + } +@@ -583,13 +550,12 @@ + private static class LlamaAttackWolfGoal extends NearestAttackableTargetGoal { + + public LlamaAttackWolfGoal(Llama llama) { +- super(llama, Wolf.class, 16, false, true, (livingentity) -> { +- return !((Wolf) livingentity).isTame(); ++ super(llama, Wolf.class, 16, false, true, (entityliving) -> { ++ return !((Wolf) entityliving).isTame(); + }); + } + + @Override +- @Override + protected double getFollowDistance() { + return super.getFollowDistance() * 0.25D; + } +@@ -599,9 +565,9 @@ + + public final Llama.Variant variant; + +- LlamaGroupData(Llama.Variant llama_variant) { ++ LlamaGroupData(Llama.Variant variant) { + super(true); +- this.variant = llama_variant; ++ this.variant = variant; + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java.patch new file mode 100644 index 0000000000..89e76d1707 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java.patch @@ -0,0 +1,152 @@ +--- a/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java ++++ b/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java +@@ -5,10 +5,10 @@ + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.DifficultyInstance; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LightningBolt; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.goal.Goal; + import net.minecraft.world.entity.monster.Skeleton; + import net.minecraft.world.item.ItemStack; +@@ -19,47 +19,45 @@ + + private final SkeletonHorse horse; + +- public SkeletonTrapGoal(SkeletonHorse skeletonhorse) { +- this.horse = skeletonhorse; ++ public SkeletonTrapGoal(SkeletonHorse horse) { ++ this.horse = horse; + } + + @Override +- @Override + public boolean canUse() { + return this.horse.level().hasNearbyAlivePlayer(this.horse.getX(), this.horse.getY(), this.horse.getZ(), 10.0D); + } + + @Override +- @Override + public void tick() { +- ServerLevel serverlevel = (ServerLevel) this.horse.level(); +- DifficultyInstance difficultyinstance = serverlevel.getCurrentDifficultyAt(this.horse.blockPosition()); ++ ServerLevel worldserver = (ServerLevel) this.horse.level(); ++ DifficultyInstance difficultydamagescaler = worldserver.getCurrentDifficultyAt(this.horse.blockPosition()); + + this.horse.setTrap(false); + this.horse.setTamed(true); + this.horse.setAge(0); +- LightningBolt lightningbolt = (LightningBolt) EntityType.LIGHTNING_BOLT.create(serverlevel); ++ LightningBolt entitylightning = (LightningBolt) EntityType.LIGHTNING_BOLT.create(worldserver); + +- if (lightningbolt != null) { +- lightningbolt.moveTo(this.horse.getX(), this.horse.getY(), this.horse.getZ()); +- lightningbolt.setVisualOnly(true); +- serverlevel.addFreshEntity(lightningbolt); +- Skeleton skeleton = this.createSkeleton(difficultyinstance, this.horse); ++ if (entitylightning != null) { ++ entitylightning.moveTo(this.horse.getX(), this.horse.getY(), this.horse.getZ()); ++ entitylightning.setVisualOnly(true); ++ worldserver.strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.TRAP); // CraftBukkit ++ Skeleton entityskeleton = this.createSkeleton(difficultydamagescaler, this.horse); + +- if (skeleton != null) { +- skeleton.startRiding(this.horse); +- serverlevel.addFreshEntityWithPassengers(skeleton); ++ if (entityskeleton != null) { ++ entityskeleton.startRiding(this.horse); ++ worldserver.addFreshEntityWithPassengers(entityskeleton, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.TRAP); // CraftBukkit + + for (int i = 0; i < 3; ++i) { +- AbstractHorse abstracthorse = this.createHorse(difficultyinstance); ++ AbstractHorse entityhorseabstract = this.createHorse(difficultydamagescaler); + +- if (abstracthorse != null) { +- Skeleton skeleton1 = this.createSkeleton(difficultyinstance, abstracthorse); ++ if (entityhorseabstract != null) { ++ Skeleton entityskeleton1 = this.createSkeleton(difficultydamagescaler, entityhorseabstract); + +- if (skeleton1 != null) { +- skeleton1.startRiding(abstracthorse); +- abstracthorse.push(this.horse.getRandom().triangle(0.0D, 1.1485D), 0.0D, this.horse.getRandom().triangle(0.0D, 1.1485D)); +- serverlevel.addFreshEntityWithPassengers(abstracthorse); ++ if (entityskeleton1 != null) { ++ entityskeleton1.startRiding(entityhorseabstract); ++ entityhorseabstract.push(this.horse.getRandom().triangle(0.0D, 1.1485D), 0.0D, this.horse.getRandom().triangle(0.0D, 1.1485D)); ++ worldserver.addFreshEntityWithPassengers(entityhorseabstract, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.JOCKEY); // CraftBukkit + } + } + } +@@ -69,43 +67,43 @@ + } + + @Nullable +- private AbstractHorse createHorse(DifficultyInstance difficultyinstance) { +- SkeletonHorse skeletonhorse = (SkeletonHorse) EntityType.SKELETON_HORSE.create(this.horse.level()); ++ private AbstractHorse createHorse(DifficultyInstance difficulty) { ++ SkeletonHorse entityhorseskeleton = (SkeletonHorse) EntityType.SKELETON_HORSE.create(this.horse.level()); + +- if (skeletonhorse != null) { +- skeletonhorse.finalizeSpawn((ServerLevel) this.horse.level(), difficultyinstance, MobSpawnType.TRIGGERED, (SpawnGroupData) null, (CompoundTag) null); +- skeletonhorse.setPos(this.horse.getX(), this.horse.getY(), this.horse.getZ()); +- skeletonhorse.invulnerableTime = 60; +- skeletonhorse.setPersistenceRequired(); +- skeletonhorse.setTamed(true); +- skeletonhorse.setAge(0); ++ if (entityhorseskeleton != null) { ++ entityhorseskeleton.finalizeSpawn((ServerLevel) this.horse.level(), difficulty, EnumMobSpawn.TRIGGERED, (GroupDataEntity) null, (CompoundTag) null); ++ entityhorseskeleton.setPos(this.horse.getX(), this.horse.getY(), this.horse.getZ()); ++ entityhorseskeleton.invulnerableTime = 60; ++ entityhorseskeleton.setPersistenceRequired(); ++ entityhorseskeleton.setTamed(true); ++ entityhorseskeleton.setAge(0); + } + +- return skeletonhorse; ++ return entityhorseskeleton; + } + + @Nullable +- private Skeleton createSkeleton(DifficultyInstance difficultyinstance, AbstractHorse abstracthorse) { +- Skeleton skeleton = (Skeleton) EntityType.SKELETON.create(abstracthorse.level()); ++ private Skeleton createSkeleton(DifficultyInstance difficulty, AbstractHorse horse) { ++ Skeleton entityskeleton = (Skeleton) EntityType.SKELETON.create(horse.level()); + +- if (skeleton != null) { +- skeleton.finalizeSpawn((ServerLevel) abstracthorse.level(), difficultyinstance, MobSpawnType.TRIGGERED, (SpawnGroupData) null, (CompoundTag) null); +- skeleton.setPos(abstracthorse.getX(), abstracthorse.getY(), abstracthorse.getZ()); +- skeleton.invulnerableTime = 60; +- skeleton.setPersistenceRequired(); +- if (skeleton.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { +- skeleton.setItemSlot(EquipmentSlot.HEAD, new ItemStack(Items.IRON_HELMET)); ++ if (entityskeleton != null) { ++ entityskeleton.finalizeSpawn((ServerLevel) horse.level(), difficulty, EnumMobSpawn.TRIGGERED, (GroupDataEntity) null, (CompoundTag) null); ++ entityskeleton.setPos(horse.getX(), horse.getY(), horse.getZ()); ++ entityskeleton.invulnerableTime = 60; ++ entityskeleton.setPersistenceRequired(); ++ if (entityskeleton.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { ++ entityskeleton.setItemSlot(EquipmentSlot.HEAD, new ItemStack(Items.IRON_HELMET)); + } + +- skeleton.setItemSlot(EquipmentSlot.MAINHAND, EnchantmentHelper.enchantItem(skeleton.getRandom(), this.disenchant(skeleton.getMainHandItem()), (int) (5.0F + difficultyinstance.getSpecialMultiplier() * (float) skeleton.getRandom().nextInt(18)), false)); +- skeleton.setItemSlot(EquipmentSlot.HEAD, EnchantmentHelper.enchantItem(skeleton.getRandom(), this.disenchant(skeleton.getItemBySlot(EquipmentSlot.HEAD)), (int) (5.0F + difficultyinstance.getSpecialMultiplier() * (float) skeleton.getRandom().nextInt(18)), false)); ++ entityskeleton.setItemSlot(EquipmentSlot.MAINHAND, EnchantmentHelper.enchantItem(entityskeleton.getRandom(), this.disenchant(entityskeleton.getMainHandItem()), (int) (5.0F + difficulty.getSpecialMultiplier() * (float) entityskeleton.getRandom().nextInt(18)), false)); ++ entityskeleton.setItemSlot(EquipmentSlot.HEAD, EnchantmentHelper.enchantItem(entityskeleton.getRandom(), this.disenchant(entityskeleton.getItemBySlot(EquipmentSlot.HEAD)), (int) (5.0F + difficulty.getSpecialMultiplier() * (float) entityskeleton.getRandom().nextInt(18)), false)); + } + +- return skeleton; ++ return entityskeleton; + } + +- private ItemStack disenchant(ItemStack itemstack) { +- itemstack.removeTagKey("Enchantments"); +- return itemstack; ++ private ItemStack disenchant(ItemStack stack) { ++ stack.removeTagKey("Enchantments"); ++ return stack; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/horse/TraderLlama.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/horse/TraderLlama.java.patch new file mode 100644 index 0000000000..68a8273a33 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/horse/TraderLlama.java.patch @@ -0,0 +1,149 @@ +--- a/net/minecraft/world/entity/animal/horse/TraderLlama.java ++++ b/net/minecraft/world/entity/animal/horse/TraderLlama.java +@@ -7,9 +7,9 @@ + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.goal.Goal; + import net.minecraft.world.entity.ai.goal.PanicGoal; + import net.minecraft.world.entity.ai.goal.target.TargetGoal; +@@ -23,54 +23,48 @@ + + private int despawnDelay = 47999; + +- public TraderLlama(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public TraderLlama(EntityType entityType, Level level) { ++ super(entityType, level); + } + + @Override +- @Override + public boolean isTraderLlama() { + return true; + } + + @Nullable + @Override +- @Override + protected Llama makeNewLlama() { + return (Llama) EntityType.TRADER_LLAMA.create(this.level()); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("DespawnDelay", this.despawnDelay); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("DespawnDelay", this.despawnDelay); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("DespawnDelay", 99)) { +- this.despawnDelay = compoundtag.getInt("DespawnDelay"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("DespawnDelay", 99)) { ++ this.despawnDelay = compound.getInt("DespawnDelay"); + } + + } + + @Override +- @Override + protected void registerGoals() { + super.registerGoals(); + this.goalSelector.addGoal(1, new PanicGoal(this, 2.0D)); + this.targetSelector.addGoal(1, new TraderLlama.TraderLlamaDefendWanderingTraderGoal(this)); + } + +- public void setDespawnDelay(int i) { +- this.despawnDelay = i; ++ public void setDespawnDelay(int despawnDelay) { ++ this.despawnDelay = despawnDelay; + } + + @Override +- @Override + protected void doPlayerRide(Player player) { + Entity entity = this.getLeashHolder(); + +@@ -80,7 +74,6 @@ + } + + @Override +- @Override + public void aiStep() { + super.aiStep(); + if (!this.level().isClientSide) { +@@ -114,17 +107,16 @@ + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- if (mobspawntype == MobSpawnType.EVENT) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ if (reason == EnumMobSpawn.EVENT) { + this.setAge(0); + } + +- if (spawngroupdata == null) { +- spawngroupdata = new AgeableMob.AgeableMobGroupData(false); ++ if (spawnData == null) { ++ spawnData = new AgeableMob.AgeableMobGroupData(false); + } + +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, (SpawnGroupData) spawngroupdata, compoundtag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + + protected static class TraderLlamaDefendWanderingTraderGoal extends TargetGoal { +@@ -136,11 +128,10 @@ + public TraderLlamaDefendWanderingTraderGoal(Llama llama) { + super(llama, false); + this.llama = llama; +- this.setFlags(EnumSet.of(Goal.Flag.TARGET)); ++ this.setFlags(EnumSet.of(Goal.Type.TARGET)); + } + + @Override +- @Override + public boolean canUse() { + if (!this.llama.isLeashed()) { + return false; +@@ -150,10 +141,10 @@ + if (!(entity instanceof WanderingTrader)) { + return false; + } else { +- WanderingTrader wanderingtrader = (WanderingTrader) entity; ++ WanderingTrader entityvillagertrader = (WanderingTrader) entity; + +- this.ownerLastHurtBy = wanderingtrader.getLastHurtByMob(); +- int i = wanderingtrader.getLastHurtByMobTimestamp(); ++ this.ownerLastHurtBy = entityvillagertrader.getLastHurtByMob(); ++ int i = entityvillagertrader.getLastHurtByMobTimestamp(); + + return i != this.timestamp && this.canAttack(this.ownerLastHurtBy, TargetingConditions.DEFAULT); + } +@@ -161,9 +152,8 @@ + } + + @Override +- @Override + public void start() { +- this.mob.setTarget(this.ownerLastHurtBy); ++ this.mob.setTarget(this.ownerLastHurtBy, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_OWNER, true); // CraftBukkit + Entity entity = this.llama.getLeashHolder(); + + if (entity instanceof WanderingTrader) { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/sniffer/Sniffer.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/sniffer/Sniffer.java.patch new file mode 100644 index 0000000000..d1e4b68506 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/animal/sniffer/Sniffer.java.patch @@ -0,0 +1,459 @@ +--- a/net/minecraft/world/entity/animal/sniffer/Sniffer.java ++++ b/net/minecraft/world/entity/animal/sniffer/Sniffer.java +@@ -25,16 +25,16 @@ + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.ItemTags; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.AnimationState; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -46,8 +46,8 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.RenderShape; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.EnumRenderType; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.level.pathfinder.Path; +@@ -81,24 +81,31 @@ + return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.10000000149011612D).add(Attributes.MAX_HEALTH, 14.0D); + } + +- public Sniffer(EntityType entitytype, Level level) { +- super(entitytype, level); +- this.entityData.define(Sniffer.DATA_STATE, Sniffer.State.IDLING); +- this.entityData.define(Sniffer.DATA_DROP_SEED_AT_TICK, 0); ++ public Sniffer(EntityType entityType, Level level) { ++ super(entityType, level); ++ // this.entityData.define(Sniffer.DATA_STATE, Sniffer.State.IDLING); // CraftBukkit - moved down to appropriate location ++ // this.entityData.define(Sniffer.DATA_DROP_SEED_AT_TICK, 0); // CraftBukkit - moved down to appropriate location + this.getNavigation().setCanFloat(true); + this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); + this.setPathfindingMalus(BlockPathTypes.DANGER_POWDER_SNOW, -1.0F); + this.setPathfindingMalus(BlockPathTypes.DAMAGE_CAUTIOUS, -1.0F); + } + ++ // CraftBukkit start - SPIGOT-7295: moved from constructor to appropriate location + @Override ++ protected void defineSynchedData() { ++ super.defineSynchedData(); ++ this.entityData.define(Sniffer.DATA_STATE, Sniffer.State.IDLING); ++ this.entityData.define(Sniffer.DATA_DROP_SEED_AT_TICK, 0); ++ } ++ // CraftBukkit end ++ + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions dimensions) { + return this.getDimensions(pose).height * 0.6F; + } + + @Override +- @Override + public void onPathfindingStart() { + super.onPathfindingStart(); + if (this.isOnFire() || this.isInWater()) { +@@ -108,14 +115,12 @@ + } + + @Override +- @Override + public void onPathfindingDone() { + this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); + } + + @Override +- @Override +- public EntityDimensions getDimensions(Pose pose) { ++ public EntityDimensions getDimensions(EntityPose pose) { + return this.entityData.hasItem(Sniffer.DATA_STATE) && this.getState() == Sniffer.State.DIGGING ? Sniffer.DIGGING_DIMENSIONS.scale(this.getScale()) : super.getDimensions(pose); + } + +@@ -136,28 +141,27 @@ + } + + private BlockPos getHeadBlock() { +- Vec3 vec3 = this.getHeadPosition(); ++ Vec3 vec3d = this.getHeadPosition(); + +- return BlockPos.containing(vec3.x(), this.getY() + 0.20000000298023224D, vec3.z()); ++ return BlockPos.containing(vec3d.x(), this.getY() + 0.20000000298023224D, vec3d.z()); + } + + private Vec3 getHeadPosition() { + return this.position().add(this.getForward().scale(2.25D)); + } + +- private Sniffer.State getState() { ++ public Sniffer.State getState() { + return (Sniffer.State) this.entityData.get(Sniffer.DATA_STATE); + } + +- private Sniffer setState(Sniffer.State sniffer_state) { +- this.entityData.set(Sniffer.DATA_STATE, sniffer_state); ++ private Sniffer setState(Sniffer.State state) { ++ this.entityData.set(Sniffer.DATA_STATE, state); + return this; + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- if (Sniffer.DATA_STATE.equals(entitydataaccessor)) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ if (Sniffer.DATA_STATE.equals(key)) { + Sniffer.State sniffer_state = this.getState(); + + this.resetAnimations(); +@@ -181,7 +185,7 @@ + this.refreshDimensions(); + } + +- super.onSyncedDataUpdated(entitydataaccessor); ++ super.onSyncedDataUpdated(key); + } + + private void resetAnimations() { +@@ -192,8 +196,8 @@ + this.scentingAnimationState.stop(); + } + +- public Sniffer transitionTo(Sniffer.State sniffer_state) { +- switch (sniffer_state) { ++ public Sniffer transitionTo(Sniffer.State state) { ++ switch (state) { + case SCENTING: + this.setState(Sniffer.State.SCENTING).onScentingStart(); + break; +@@ -233,69 +237,76 @@ + return this; + } + +- public Sniffer onDiggingComplete(boolean flag) { +- if (flag) { ++ public Sniffer onDiggingComplete(boolean storeExploredPosition) { ++ if (storeExploredPosition) { + this.storeExploredPosition(this.getOnPos()); + } + + return this; + } + +- Optional calculateDigPosition() { ++ public Optional calculateDigPosition() { + return IntStream.range(0, 5).mapToObj((i) -> { + return LandRandomPos.getPos(this, 10 + 2 * i, 3); +- }).filter(Objects::nonNull).map(BlockPos::containing).filter((blockpos) -> { +- return this.level().getWorldBorder().isWithinBounds(blockpos); ++ }).filter(Objects::nonNull).map(BlockPos::containing).filter((blockposition) -> { ++ return this.level().getWorldBorder().isWithinBounds(blockposition); + }).map(BlockPos::below).filter(this::canDig).findFirst(); + } + +- boolean canDig() { ++ public boolean canDig() { + return !this.isPanicking() && !this.isTempted() && !this.isBaby() && !this.isInWater() && this.onGround() && !this.isPassenger() && this.canDig(this.getHeadBlock().below()); + } + +- private boolean canDig(BlockPos blockpos) { +- return this.level().getBlockState(blockpos).is(BlockTags.SNIFFER_DIGGABLE_BLOCK) && this.getExploredPositions().noneMatch((globalpos) -> { +- return GlobalPos.of(this.level().dimension(), blockpos).equals(globalpos); +- }) && (Boolean) Optional.ofNullable(this.getNavigation().createPath(blockpos, 1)).map(Path::canReach).orElse(false); ++ private boolean canDig(BlockPos pos) { ++ return this.level().getBlockState(pos).is(BlockTags.SNIFFER_DIGGABLE_BLOCK) && this.getExploredPositions().noneMatch((globalpos) -> { ++ return GlobalPos.of(this.level().dimension(), pos).equals(globalpos); ++ }) && (Boolean) Optional.ofNullable(this.getNavigation().createPath(pos, 1)).map(Path::canReach).orElse(false); + } + + private void dropSeed() { + if (!this.level().isClientSide() && (Integer) this.entityData.get(Sniffer.DATA_DROP_SEED_AT_TICK) == this.tickCount) { +- ServerLevel serverlevel = (ServerLevel) this.level(); +- LootTable loottable = serverlevel.getServer().getLootData().getLootTable(BuiltInLootTables.SNIFFER_DIGGING); +- LootParams lootparams = (new LootParams.Builder(serverlevel)).withParameter(LootContextParams.ORIGIN, this.getHeadPosition()).withParameter(LootContextParams.THIS_ENTITY, this).create(LootContextParamSets.GIFT); ++ ServerLevel worldserver = (ServerLevel) this.level(); ++ LootTable loottable = worldserver.getServer().getLootData().getLootTable(BuiltInLootTables.SNIFFER_DIGGING); ++ LootParams lootparams = (new LootParams.Builder(worldserver)).withParameter(LootContextParams.ORIGIN, this.getHeadPosition()).withParameter(LootContextParams.THIS_ENTITY, this).create(LootContextParamSets.GIFT); + List list = loottable.getRandomItems(lootparams); +- BlockPos blockpos = this.getHeadBlock(); ++ BlockPos blockposition = this.getHeadBlock(); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { + ItemStack itemstack = (ItemStack) iterator.next(); +- ItemEntity itementity = new ItemEntity(serverlevel, (double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), itemstack); ++ ItemEntity entityitem = new ItemEntity(worldserver, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), itemstack); + +- itementity.setDefaultPickUpDelay(); +- serverlevel.addFreshEntity(itementity); ++ // CraftBukkit start - handle EntityDropItemEvent ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end ++ entityitem.setDefaultPickUpDelay(); ++ worldserver.addFreshEntity(entityitem); + } + + this.playSound(SoundEvents.SNIFFER_DROP_SEED, 1.0F, 1.0F); + } + } + +- private Sniffer emitDiggingParticles(AnimationState animationstate) { +- boolean flag = animationstate.getAccumulatedTime() > 1700L && animationstate.getAccumulatedTime() < 6000L; ++ private Sniffer emitDiggingParticles(AnimationState animationState) { ++ boolean flag = animationState.getAccumulatedTime() > 1700L && animationState.getAccumulatedTime() < 6000L; + + if (flag) { +- BlockPos blockpos = this.getHeadBlock(); +- BlockState blockstate = this.level().getBlockState(blockpos.below()); ++ BlockPos blockposition = this.getHeadBlock(); ++ IBlockData iblockdata = this.level().getBlockState(blockposition.below()); + +- if (blockstate.getRenderShape() != RenderShape.INVISIBLE) { ++ if (iblockdata.getRenderShape() != EnumRenderType.INVISIBLE) { + for (int i = 0; i < 30; ++i) { +- Vec3 vec3 = Vec3.atCenterOf(blockpos).add(0.0D, -0.6499999761581421D, 0.0D); ++ Vec3 vec3d = Vec3.atCenterOf(blockposition).add(0.0D, -0.6499999761581421D, 0.0D); + +- this.level().addParticle(new BlockParticleOption(ParticleTypes.BLOCK, blockstate), vec3.x, vec3.y, vec3.z, 0.0D, 0.0D, 0.0D); ++ this.level().addParticle(new BlockParticleOption(ParticleTypes.BLOCK, iblockdata), vec3d.x, vec3d.y, vec3d.z, 0.0D, 0.0D, 0.0D); + } + + if (this.tickCount % 10 == 0) { +- this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), blockstate.getSoundType().getHitSound(), this.getSoundSource(), 0.5F, 0.5F, false); ++ this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), iblockdata.getSoundType().getHitSound(), this.getSoundSource(), 0.5F, 0.5F, false); + } + } + } +@@ -307,20 +318,19 @@ + return this; + } + +- private Sniffer storeExploredPosition(BlockPos blockpos) { ++ public Sniffer storeExploredPosition(BlockPos pos) { + List list = (List) this.getExploredPositions().limit(20L).collect(Collectors.toList()); + +- list.add(0, GlobalPos.of(this.level().dimension(), blockpos)); +- this.getBrain().setMemory(MemoryModuleType.SNIFFER_EXPLORED_POSITIONS, (Object) list); ++ list.add(0, GlobalPos.of(this.level().dimension(), pos)); ++ this.getBrain().setMemory(MemoryModuleType.SNIFFER_EXPLORED_POSITIONS, list); // CraftBukkit - decompile error + return this; + } + +- private Stream getExploredPositions() { ++ public Stream getExploredPositions() { + return this.getBrain().getMemory(MemoryModuleType.SNIFFER_EXPLORED_POSITIONS).stream().flatMap(Collection::stream); + } + + @Override +- @Override + protected void jumpFromGround() { + super.jumpFromGround(); + double d0 = this.moveControl.getSpeedModifier(); +@@ -336,26 +346,23 @@ + } + + @Override +- @Override +- public void spawnChildFromBreeding(ServerLevel serverlevel, Animal animal) { ++ public void spawnChildFromBreeding(ServerLevel level, Animal mate) { + ItemStack itemstack = new ItemStack(Items.SNIFFER_EGG); +- ItemEntity itementity = new ItemEntity(serverlevel, this.position().x(), this.position().y(), this.position().z(), itemstack); ++ ItemEntity entityitem = new ItemEntity(level, this.position().x(), this.position().y(), this.position().z(), itemstack); + +- itementity.setDefaultPickUpDelay(); +- this.finalizeSpawnChildFromBreeding(serverlevel, animal, (AgeableMob) null); ++ entityitem.setDefaultPickUpDelay(); ++ this.finalizeSpawnChildFromBreeding(level, mate, (AgeableMob) null); + this.playSound(SoundEvents.SNIFFER_EGG_PLOP, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 0.5F); +- serverlevel.addFreshEntity(itementity); ++ level.addFreshEntity(entityitem); + } + + @Override +- @Override +- public void die(DamageSource damagesource) { ++ public void die(DamageSource damageSource) { + this.transitionTo(Sniffer.State.IDLING); +- super.die(damagesource); ++ super.die(damageSource); + } + + @Override +- @Override + public void tick() { + switch (this.getState()) { + case DIGGING: +@@ -369,27 +376,24 @@ + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + boolean flag = this.isFood(itemstack); +- InteractionResult interactionresult = super.mobInteract(player, interactionhand); ++ InteractionResult enuminteractionresult = super.mobInteract(player, hand); + +- if (interactionresult.consumesAction() && flag) { ++ if (enuminteractionresult.consumesAction() && flag) { + this.level().playSound((Player) null, (Entity) this, this.getEatingSound(itemstack), SoundSource.NEUTRAL, 1.0F, Mth.randomBetween(this.level().random, 0.8F, 1.2F)); + } + +- return interactionresult; ++ return enuminteractionresult; + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height + 0.34375F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.34375F * f, 0.0F); + } + + @Override +- @Override + public float getNameTagOffsetY() { + return super.getNameTagOffsetY() + 0.3F; + } +@@ -402,98 +406,83 @@ + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { ++ protected void playStepSound(BlockPos pos, IBlockData state) { + this.playSound(SoundEvents.SNIFFER_STEP, 0.15F, 1.0F); + } + + @Override +- @Override +- public SoundEvent getEatingSound(ItemStack itemstack) { ++ public SoundEvent getEatingSound(ItemStack stack) { + return SoundEvents.SNIFFER_EAT; + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return Set.of(Sniffer.State.DIGGING, Sniffer.State.SEARCHING).contains(this.getState()) ? null : SoundEvents.SNIFFER_IDLE; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.SNIFFER_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.SNIFFER_DEATH; + } + + @Override +- @Override + public int getMaxHeadYRot() { + return 50; + } + + @Override +- @Override +- public void setBaby(boolean flag) { +- this.setAge(flag ? -48000 : 0); ++ public void setBaby(boolean baby) { ++ this.setAge(baby ? -48000 : 0); + } + + @Override +- @Override +- public AgeableMob getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { +- return (AgeableMob) EntityType.SNIFFER.create(serverlevel); ++ public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob otherParent) { ++ return (AgeableMob) EntityType.SNIFFER.create(level); + } + + @Override +- @Override +- public boolean canMate(Animal animal) { +- if (!(animal instanceof Sniffer)) { ++ public boolean canMate(Animal otherAnimal) { ++ if (!(otherAnimal instanceof Sniffer)) { + return false; + } else { +- Sniffer sniffer = (Sniffer) animal; ++ Sniffer sniffer = (Sniffer) otherAnimal; + Set set = Set.of(Sniffer.State.IDLING, Sniffer.State.SCENTING, Sniffer.State.FEELING_HAPPY); + +- return set.contains(this.getState()) && set.contains(sniffer.getState()) && super.canMate(animal); ++ return set.contains(this.getState()) && set.contains(sniffer.getState()) && super.canMate(otherAnimal); + } + } + + @Override +- @Override + public AABB getBoundingBoxForCulling() { + return super.getBoundingBoxForCulling().inflate(0.6000000238418579D); + } + + @Override +- @Override +- public boolean isFood(ItemStack itemstack) { +- return itemstack.is(ItemTags.SNIFFER_FOOD); ++ public boolean isFood(ItemStack stack) { ++ return stack.is(ItemTags.SNIFFER_FOOD); + } + + @Override +- @Override + protected Brain makeBrain(Dynamic dynamic) { + return SnifferAi.makeBrain(this.brainProvider().makeBrain(dynamic)); + } + + @Override +- @Override + public Brain getBrain() { +- return super.getBrain(); ++ return (Brain) super.getBrain(); // CraftBukkit - decompile error + } + + @Override +- @Override + protected Brain.Provider brainProvider() { + return Brain.provider(SnifferAi.MEMORY_TYPES, SnifferAi.SENSOR_TYPES); + } + + @Override +- @Override + protected void customServerAiStep() { + this.level().getProfiler().push("snifferBrain"); + this.getBrain().tick((ServerLevel) this.level(), this); +@@ -504,7 +493,6 @@ + } + + @Override +- @Override + protected void sendDebugPackets() { + super.sendDebugPackets(); + DebugPackets.sendEntityBrain(this); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java.patch new file mode 100644 index 0000000000..4c556c047e --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java.patch @@ -0,0 +1,201 @@ +--- a/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java ++++ b/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java +@@ -19,6 +19,10 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.BaseFireBlock; + import net.minecraft.world.level.dimension.end.EndDragonFight; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end + + public class EndCrystal extends Entity { + +@@ -26,90 +30,99 @@ + private static final EntityDataAccessor DATA_SHOW_BOTTOM = SynchedEntityData.defineId(EndCrystal.class, EntityDataSerializers.BOOLEAN); + public int time; + +- public EndCrystal(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public EndCrystal(EntityType entityType, Level level) { ++ super(entityType, level); + this.blocksBuilding = true; + this.time = this.random.nextInt(100000); + } + +- public EndCrystal(Level level, double d0, double d1, double d2) { ++ public EndCrystal(Level level, double x, double d1, double y) { + this(EntityType.END_CRYSTAL, level); +- this.setPos(d0, d1, d2); ++ this.setPos(x, d1, y); + } + + @Override +- @Override + protected Entity.MovementEmission getMovementEmission() { + return Entity.MovementEmission.NONE; + } + + @Override +- @Override + protected void defineSynchedData() { + this.getEntityData().define(EndCrystal.DATA_BEAM_TARGET, Optional.empty()); + this.getEntityData().define(EndCrystal.DATA_SHOW_BOTTOM, true); + } + + @Override +- @Override + public void tick() { + ++this.time; + if (this.level() instanceof ServerLevel) { +- BlockPos blockpos = this.blockPosition(); ++ BlockPos blockposition = this.blockPosition(); + +- if (((ServerLevel) this.level()).getDragonFight() != null && this.level().getBlockState(blockpos).isAir()) { +- this.level().setBlockAndUpdate(blockpos, BaseFireBlock.getState(this.level(), blockpos)); ++ if (((ServerLevel) this.level()).getDragonFight() != null && this.level().getBlockState(blockposition).isAir()) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition, this).isCancelled()) { ++ this.level().setBlockAndUpdate(blockposition, BaseFireBlock.getState(this.level(), blockposition)); ++ } ++ // CraftBukkit end + } + } + + } + + @Override +- @Override +- protected void addAdditionalSaveData(CompoundTag compoundtag) { ++ protected void addAdditionalSaveData(CompoundTag compound) { + if (this.getBeamTarget() != null) { +- compoundtag.put("BeamTarget", NbtUtils.writeBlockPos(this.getBeamTarget())); ++ compound.put("BeamTarget", NbtUtils.writeBlockPos(this.getBeamTarget())); + } + +- compoundtag.putBoolean("ShowBottom", this.showsBottom()); ++ compound.putBoolean("ShowBottom", this.showsBottom()); + } + + @Override +- @Override +- protected void readAdditionalSaveData(CompoundTag compoundtag) { +- if (compoundtag.contains("BeamTarget", 10)) { +- this.setBeamTarget(NbtUtils.readBlockPos(compoundtag.getCompound("BeamTarget"))); ++ protected void readAdditionalSaveData(CompoundTag compound) { ++ if (compound.contains("BeamTarget", 10)) { ++ this.setBeamTarget(NbtUtils.readBlockPos(compound.getCompound("BeamTarget"))); + } + +- if (compoundtag.contains("ShowBottom", 1)) { +- this.setShowBottom(compoundtag.getBoolean("ShowBottom")); ++ if (compound.contains("ShowBottom", 1)) { ++ this.setShowBottom(compound.getBoolean("ShowBottom")); + } + + } + + @Override +- @Override + public boolean isPickable() { + return true; + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- if (this.isInvulnerableTo(damagesource)) { ++ public boolean hurt(DamageSource source, float amount) { ++ if (this.isInvulnerableTo(source)) { + return false; +- } else if (damagesource.getEntity() instanceof EnderDragon) { ++ } else if (source.getEntity() instanceof EnderDragon) { + return false; + } else { + if (!this.isRemoved() && !this.level().isClientSide) { ++ // CraftBukkit start - All non-living entities need this ++ if (CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, false)) { ++ return false; ++ } ++ // CraftBukkit end + this.remove(Entity.RemovalReason.KILLED); +- if (!damagesource.is(DamageTypeTags.IS_EXPLOSION)) { +- DamageSource damagesource1 = damagesource.getEntity() != null ? this.damageSources().explosion(this, damagesource.getEntity()) : null; ++ if (!source.is(DamageTypeTags.IS_EXPLOSION)) { ++ DamageSource damagesource1 = source.getEntity() != null ? this.damageSources().explosion(this, source.getEntity()) : null; + +- this.level().explode(this, damagesource1, (ExplosionDamageCalculator) null, this.getX(), this.getY(), this.getZ(), 6.0F, false, Level.ExplosionInteraction.BLOCK); ++ // CraftBukkit start ++ ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent(this, 6.0F, false); ++ if (event.isCancelled()) { ++ this.unsetRemoved(); ++ return false; ++ } ++ this.level().explode(this, damagesource1, (ExplosionDamageCalculator) null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.BLOCK); ++ // CraftBukkit end + } + +- this.onDestroyedBy(damagesource); ++ this.onDestroyedBy(source); + } + + return true; +@@ -117,25 +130,24 @@ + } + + @Override +- @Override + public void kill() { + this.onDestroyedBy(this.damageSources().generic()); + super.kill(); + } + +- private void onDestroyedBy(DamageSource damagesource) { ++ private void onDestroyedBy(DamageSource source) { + if (this.level() instanceof ServerLevel) { +- EndDragonFight enddragonfight = ((ServerLevel) this.level()).getDragonFight(); ++ EndDragonFight enderdragonbattle = ((ServerLevel) this.level()).getDragonFight(); + +- if (enddragonfight != null) { +- enddragonfight.onCrystalDestroyed(this, damagesource); ++ if (enderdragonbattle != null) { ++ enderdragonbattle.onCrystalDestroyed(this, source); + } + } + + } + +- public void setBeamTarget(@Nullable BlockPos blockpos) { +- this.getEntityData().set(EndCrystal.DATA_BEAM_TARGET, Optional.ofNullable(blockpos)); ++ public void setBeamTarget(@Nullable BlockPos beamTarget) { ++ this.getEntityData().set(EndCrystal.DATA_BEAM_TARGET, Optional.ofNullable(beamTarget)); + } + + @Nullable +@@ -143,8 +155,8 @@ + return (BlockPos) ((Optional) this.getEntityData().get(EndCrystal.DATA_BEAM_TARGET)).orElse((Object) null); + } + +- public void setShowBottom(boolean flag) { +- this.getEntityData().set(EndCrystal.DATA_SHOW_BOTTOM, flag); ++ public void setShowBottom(boolean showBottom) { ++ this.getEntityData().set(EndCrystal.DATA_SHOW_BOTTOM, showBottom); + } + + public boolean showsBottom() { +@@ -152,13 +164,11 @@ + } + + @Override +- @Override +- public boolean shouldRenderAtSqrDistance(double d0) { +- return super.shouldRenderAtSqrDistance(d0) || this.getBeamTarget() != null; ++ public boolean shouldRenderAtSqrDistance(double distance) { ++ return super.shouldRenderAtSqrDistance(distance) || this.getBeamTarget() != null; + } + + @Override +- @Override + public ItemStack getPickResult() { + return new ItemStack(Items.END_CRYSTAL); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java.patch new file mode 100644 index 0000000000..7bcd3d3e31 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java.patch @@ -0,0 +1,1042 @@ +--- a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java ++++ b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +@@ -25,10 +25,10 @@ + import net.minecraft.world.entity.EntityDimensions; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.ExperienceOrb; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.targeting.TargetingConditions; +@@ -36,11 +36,11 @@ + import net.minecraft.world.entity.boss.enderdragon.phases.DragonPhaseInstance; + import net.minecraft.world.entity.boss.enderdragon.phases.EnderDragonPhase; + import net.minecraft.world.entity.boss.enderdragon.phases.EnderDragonPhaseManager; +-import net.minecraft.world.entity.monster.Enemy; ++import net.minecraft.world.entity.monster.IMonster; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.dimension.end.EndDragonFight; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.levelgen.Heightmap; +@@ -48,13 +48,25 @@ + import net.minecraft.world.level.pathfinder.BinaryHeap; + import net.minecraft.world.level.pathfinder.Node; + import net.minecraft.world.level.pathfinder.Path; +-import net.minecraft.world.phys.AABB; +-import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + import org.slf4j.Logger; + +-public class EnderDragon extends Mob implements Enemy { ++// CraftBukkit start ++import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.level.Explosion; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.entity.BlockEntity; ++import net.minecraft.world.level.storage.loot.LootParams; ++import net.minecraft.world.level.storage.loot.parameters.LootContextParams; ++import net.minecraft.world.phys.AABB; ++import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.entity.EntityExplodeEvent; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++// CraftBukkit end + ++public class EnderDragon extends Mob implements IMonster { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + public static final EntityDataAccessor DATA_PHASE = SynchedEntityData.defineId(EnderDragon.class, EntityDataSerializers.INT); + private static final TargetingConditions CRYSTAL_DESTROY_TARGETING = TargetingConditions.forCombat().range(64.0D); +@@ -65,7 +77,7 @@ + private static final String DRAGON_PHASE_KEY = "DragonPhase"; + public final double[][] positions = new double[64][3]; + public int posPointer = -1; +- private final EnderDragonPart[] subEntities; ++ public final EnderDragonPart[] subEntities; + public final EnderDragonPart head; + private final EnderDragonPart neck; + private final EnderDragonPart body; +@@ -90,8 +102,9 @@ + private final Node[] nodes; + private final int[] nodeAdjacency; + private final BinaryHeap openSet; ++ private final Explosion explosionSource; // CraftBukkit - reusable source for CraftTNTPrimed.getSource() + +- public EnderDragon(EntityType entitytype, Level level) { ++ public EnderDragon(EntityType entityType, Level level) { + super(EntityType.ENDER_DRAGON, level); + this.fightOrigin = BlockPos.ZERO; + this.growlTime = 100; +@@ -111,14 +124,15 @@ + this.noPhysics = true; + this.noCulling = true; + this.phaseManager = new EnderDragonPhaseManager(this); ++ this.explosionSource = new Explosion(level, this, null, null, Double.NaN, Double.NaN, Double.NaN, Float.NaN, true, Explosion.Effect.DESTROY, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); // CraftBukkit + } + +- public void setDragonFight(EndDragonFight enddragonfight) { +- this.dragonFight = enddragonfight; ++ public void setDragonFight(EndDragonFight dragonFight) { ++ this.dragonFight = dragonFight; + } + +- public void setFightOrigin(BlockPos blockpos) { +- this.fightOrigin = blockpos; ++ public void setFightOrigin(BlockPos fightOrigin) { ++ this.fightOrigin = fightOrigin; + } + + public BlockPos getFightOrigin() { +@@ -130,7 +144,6 @@ + } + + @Override +- @Override + public boolean isFlapping() { + float f = Mth.cos(this.flapTime * 6.2831855F); + float f1 = Mth.cos(this.oFlapTime * 6.2831855F); +@@ -139,7 +152,6 @@ + } + + @Override +- @Override + public void onFlap() { + if (this.level().isClientSide && !this.isSilent()) { + this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.ENDER_DRAGON_FLAP, this.getSoundSource(), 5.0F, 0.8F + this.random.nextFloat() * 0.3F, false); +@@ -148,34 +160,32 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.getEntityData().define(EnderDragon.DATA_PHASE, EnderDragonPhase.HOVERING.getId()); + } + +- public double[] getLatencyPos(int i, float f) { ++ public double[] getLatencyPos(int bufferIndexOffset, float partialTicks) { + if (this.isDeadOrDying()) { +- f = 0.0F; ++ partialTicks = 0.0F; + } + +- f = 1.0F - f; +- int j = this.posPointer - i & 63; +- int k = this.posPointer - i - 1 & 63; ++ partialTicks = 1.0F - partialTicks; ++ int j = this.posPointer - bufferIndexOffset & 63; ++ int k = this.posPointer - bufferIndexOffset - 1 & 63; + double[] adouble = new double[3]; + double d0 = this.positions[j][0]; + double d1 = Mth.wrapDegrees(this.positions[k][0] - d0); + +- adouble[0] = d0 + d1 * (double) f; ++ adouble[0] = d0 + d1 * (double) partialTicks; + d0 = this.positions[j][1]; + d1 = this.positions[k][1] - d0; +- adouble[1] = d0 + d1 * (double) f; +- adouble[2] = Mth.lerp((double) f, this.positions[j][2], this.positions[k][2]); ++ adouble[1] = d0 + d1 * (double) partialTicks; ++ adouble[2] = Mth.lerp((double) partialTicks, this.positions[j][2], this.positions[k][2]); + return adouble; + } + + @Override +- @Override + public void aiStep() { + this.processFlappingMovement(); + if (this.level().isClientSide) { +@@ -187,14 +197,14 @@ + } + + if (this.dragonFight == null) { +- Level level = this.level(); ++ Level world = this.level(); + +- if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; +- EndDragonFight enddragonfight = serverlevel.getDragonFight(); ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ EndDragonFight enderdragonbattle = worldserver.getDragonFight(); + +- if (enddragonfight != null && this.getUUID().equals(enddragonfight.getDragonUUID())) { +- this.dragonFight = enddragonfight; ++ if (enderdragonbattle != null && this.getUUID().equals(enderdragonbattle.getDragonUUID())) { ++ this.dragonFight = enderdragonbattle; + } + } + } +@@ -211,10 +221,10 @@ + this.level().addParticle(ParticleTypes.EXPLOSION, this.getX() + (double) f1, this.getY() + 2.0D + (double) f, this.getZ() + (double) f2, 0.0D, 0.0D, 0.0D); + } else { + this.checkCrystals(); +- Vec3 vec3 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + +- f = 0.2F / ((float) vec3.horizontalDistance() * 10.0F + 1.0F); +- f *= (float) Math.pow(2.0D, vec3.y); ++ f = 0.2F / ((float) vec3d.horizontalDistance() * 10.0F + 1.0F); ++ f *= (float) Math.pow(2.0D, vec3d.y); + if (this.phaseManager.getCurrentPhase().isSitting()) { + this.flapTime += 0.1F; + } else if (this.inWall) { +@@ -252,22 +262,22 @@ + + this.phaseManager.getCurrentPhase().doClientTick(); + } else { +- DragonPhaseInstance dragonphaseinstance = this.phaseManager.getCurrentPhase(); ++ DragonPhaseInstance idragoncontroller = this.phaseManager.getCurrentPhase(); + +- dragonphaseinstance.doServerTick(); +- if (this.phaseManager.getCurrentPhase() != dragonphaseinstance) { +- dragonphaseinstance = this.phaseManager.getCurrentPhase(); +- dragonphaseinstance.doServerTick(); ++ idragoncontroller.doServerTick(); ++ if (this.phaseManager.getCurrentPhase() != idragoncontroller) { ++ idragoncontroller = this.phaseManager.getCurrentPhase(); ++ idragoncontroller.doServerTick(); + } + +- Vec3 vec31 = dragonphaseinstance.getFlyTargetLocation(); ++ Vec3 vec3d1 = idragoncontroller.getFlyTargetLocation(); + +- if (vec31 != null) { +- double d0 = vec31.x - this.getX(); +- double d1 = vec31.y - this.getY(); +- double d2 = vec31.z - this.getZ(); ++ if (vec3d1 != null && idragoncontroller.getPhase() != EnderDragonPhase.HOVERING) { // CraftBukkit - Don't move when hovering ++ double d0 = vec3d1.x - this.getX(); ++ double d1 = vec3d1.y - this.getY(); ++ double d2 = vec3d1.z - this.getZ(); + double d3 = d0 * d0 + d1 * d1 + d2 * d2; +- float f6 = dragonphaseinstance.getFlySpeed(); ++ float f6 = idragoncontroller.getFlySpeed(); + double d4 = Math.sqrt(d0 * d0 + d2 * d2); + + if (d4 > 0.0D) { +@@ -276,14 +286,14 @@ + + this.setDeltaMovement(this.getDeltaMovement().add(0.0D, d1 * 0.01D, 0.0D)); + this.setYRot(Mth.wrapDegrees(this.getYRot())); +- Vec3 vec32 = vec31.subtract(this.getX(), this.getY(), this.getZ()).normalize(); +- Vec3 vec33 = (new Vec3((double) Mth.sin(this.getYRot() * 0.017453292F), this.getDeltaMovement().y, (double) (-Mth.cos(this.getYRot() * 0.017453292F)))).normalize(); ++ Vec3 vec3d2 = vec3d1.subtract(this.getX(), this.getY(), this.getZ()).normalize(); ++ Vec3 vec3d3 = (new Vec3((double) Mth.sin(this.getYRot() * 0.017453292F), this.getDeltaMovement().y, (double) (-Mth.cos(this.getYRot() * 0.017453292F)))).normalize(); + +- f3 = Math.max(((float) vec33.dot(vec32) + 0.5F) / 1.5F, 0.0F); ++ f3 = Math.max(((float) vec3d3.dot(vec3d2) + 0.5F) / 1.5F, 0.0F); + if (Math.abs(d0) > 9.999999747378752E-6D || Math.abs(d2) > 9.999999747378752E-6D) { + f4 = Mth.clamp(Mth.wrapDegrees(180.0F - (float) Mth.atan2(d0, d2) * 57.295776F - this.getYRot()), -50.0F, 50.0F); + this.yRotA *= 0.8F; +- this.yRotA += f4 * dragonphaseinstance.getTurnSpeed(); ++ this.yRotA += f4 * idragoncontroller.getTurnSpeed(); + this.setYRot(this.getYRot() + this.yRotA * 0.1F); + } + +@@ -291,23 +301,23 @@ + f5 = 0.06F; + this.moveRelative(0.06F * (f3 * f4 + (1.0F - f4)), new Vec3(0.0D, 0.0D, -1.0D)); + if (this.inWall) { +- this.move(MoverType.SELF, this.getDeltaMovement().scale(0.800000011920929D)); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement().scale(0.800000011920929D)); + } else { +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + } + +- Vec3 vec34 = this.getDeltaMovement().normalize(); +- double d5 = 0.8D + 0.15D * (vec34.dot(vec33) + 1.0D) / 2.0D; ++ Vec3 vec3d4 = this.getDeltaMovement().normalize(); ++ double d5 = 0.8D + 0.15D * (vec3d4.dot(vec3d3) + 1.0D) / 2.0D; + + this.setDeltaMovement(this.getDeltaMovement().multiply(d5, 0.9100000262260437D, d5)); + } + } + + this.yBodyRot = this.getYRot(); +- Vec3[] avec3 = new Vec3[this.subEntities.length]; ++ Vec3[] avec3d = new Vec3[this.subEntities.length]; + + for (int j = 0; j < this.subEntities.length; ++j) { +- avec3[j] = new Vec3(this.subEntities[j].getX(), this.subEntities[j].getY(), this.subEntities[j].getZ()); ++ avec3d[j] = new Vec3(this.subEntities[j].getX(), this.subEntities[j].getY(), this.subEntities[j].getZ()); + } + + float f7 = (float) (this.getLatencyPos(5, 1.0F)[1] - this.getLatencyPos(10, 1.0F)[1]) * 10.0F * 0.017453292F; +@@ -338,18 +348,18 @@ + int k; + + for (k = 0; k < 3; ++k) { +- EnderDragonPart enderdragonpart = null; ++ EnderDragonPart entitycomplexpart = null; + + if (k == 0) { +- enderdragonpart = this.tail1; ++ entitycomplexpart = this.tail1; + } + + if (k == 1) { +- enderdragonpart = this.tail2; ++ entitycomplexpart = this.tail2; + } + + if (k == 2) { +- enderdragonpart = this.tail3; ++ entitycomplexpart = this.tail3; + } + + double[] adouble1 = this.getLatencyPos(12 + k * 2, 1.0F); +@@ -360,7 +370,7 @@ + f5 = 1.5F; + float f17 = (float) (k + 1) * 2.0F; + +- this.tickPart(enderdragonpart, (double) (-(f11 * 1.5F + f3 * f17) * f8), adouble1[1] - adouble[1] - (double) ((f17 + 1.5F) * f9) + 1.5D, (double) ((f12 * 1.5F + f4 * f17) * f8)); ++ this.tickPart(entitycomplexpart, (double) (-(f11 * 1.5F + f3 * f17) * f8), adouble1[1] - adouble[1] - (double) ((f17 + 1.5F) * f9) + 1.5D, (double) ((f12 * 1.5F + f4 * f17) * f8)); + } + + if (!this.level().isClientSide) { +@@ -371,20 +381,20 @@ + } + + for (k = 0; k < this.subEntities.length; ++k) { +- this.subEntities[k].xo = avec3[k].x; +- this.subEntities[k].yo = avec3[k].y; +- this.subEntities[k].zo = avec3[k].z; +- this.subEntities[k].xOld = avec3[k].x; +- this.subEntities[k].yOld = avec3[k].y; +- this.subEntities[k].zOld = avec3[k].z; ++ this.subEntities[k].xo = avec3d[k].x; ++ this.subEntities[k].yo = avec3d[k].y; ++ this.subEntities[k].zo = avec3d[k].z; ++ this.subEntities[k].xOld = avec3d[k].x; ++ this.subEntities[k].yOld = avec3d[k].y; ++ this.subEntities[k].zOld = avec3d[k].z; + } + + } + } + } + +- private void tickPart(EnderDragonPart enderdragonpart, double d0, double d1, double d2) { +- enderdragonpart.setPos(this.getX() + d0, this.getY() + d1, this.getZ() + d2); ++ private void tickPart(EnderDragonPart part, double offsetX, double d1, double offsetY) { ++ part.setPos(this.getX() + offsetX, this.getY() + d1, this.getZ() + offsetY); + } + + private float getHeadYOffset() { +@@ -403,35 +413,42 @@ + if (this.nearestCrystal.isRemoved()) { + this.nearestCrystal = null; + } else if (this.tickCount % 10 == 0 && this.getHealth() < this.getMaxHealth()) { +- this.setHealth(this.getHealth() + 1.0F); ++ // CraftBukkit start ++ EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), 1.0F, EntityRegainHealthEvent.RegainReason.ENDER_CRYSTAL); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ this.setHealth((float) (this.getHealth() + event.getAmount())); ++ } ++ // CraftBukkit end + } + } + + if (this.random.nextInt(10) == 0) { + List list = this.level().getEntitiesOfClass(EndCrystal.class, this.getBoundingBox().inflate(32.0D)); +- EndCrystal endcrystal = null; ++ EndCrystal entityendercrystal = null; + double d0 = Double.MAX_VALUE; + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- EndCrystal endcrystal1 = (EndCrystal) iterator.next(); +- double d1 = endcrystal1.distanceToSqr((Entity) this); ++ EndCrystal entityendercrystal1 = (EndCrystal) iterator.next(); ++ double d1 = entityendercrystal1.distanceToSqr((Entity) this); + + if (d1 < d0) { + d0 = d1; +- endcrystal = endcrystal1; ++ entityendercrystal = entityendercrystal1; + } + } + +- this.nearestCrystal = endcrystal; ++ this.nearestCrystal = entityendercrystal; + } + + } + +- private void knockBack(List list) { ++ private void knockBack(List entities) { + double d0 = (this.body.getBoundingBox().minX + this.body.getBoundingBox().maxX) / 2.0D; + double d1 = (this.body.getBoundingBox().minZ + this.body.getBoundingBox().maxZ) / 2.0D; +- Iterator iterator = list.iterator(); ++ Iterator iterator = entities.iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); +@@ -451,8 +468,8 @@ + + } + +- private void hurt(List list) { +- Iterator iterator = list.iterator(); ++ private void hurt(List entities) { ++ Iterator iterator = entities.iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); +@@ -465,29 +482,36 @@ + + } + +- private float rotWrap(double d0) { +- return (float) Mth.wrapDegrees(d0); ++ private float rotWrap(double angle) { ++ return (float) Mth.wrapDegrees(angle); + } + +- private boolean checkWalls(AABB aabb) { +- int i = Mth.floor(aabb.minX); +- int j = Mth.floor(aabb.minY); +- int k = Mth.floor(aabb.minZ); +- int l = Mth.floor(aabb.maxX); +- int i1 = Mth.floor(aabb.maxY); +- int j1 = Mth.floor(aabb.maxZ); ++ private boolean checkWalls(AABB area) { ++ int i = Mth.floor(area.minX); ++ int j = Mth.floor(area.minY); ++ int k = Mth.floor(area.minZ); ++ int l = Mth.floor(area.maxX); ++ int i1 = Mth.floor(area.maxY); ++ int j1 = Mth.floor(area.maxZ); + boolean flag = false; + boolean flag1 = false; ++ // CraftBukkit start - Create a list to hold all the destroyed blocks ++ List destroyedBlocks = new java.util.ArrayList(); ++ // CraftBukkit end + + for (int k1 = i; k1 <= l; ++k1) { + for (int l1 = j; l1 <= i1; ++l1) { + for (int i2 = k; i2 <= j1; ++i2) { +- BlockPos blockpos = new BlockPos(k1, l1, i2); +- BlockState blockstate = this.level().getBlockState(blockpos); ++ BlockPos blockposition = new BlockPos(k1, l1, i2); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); + +- if (!blockstate.isAir() && !blockstate.is(BlockTags.DRAGON_TRANSPARENT)) { +- if (this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && !blockstate.is(BlockTags.DRAGON_IMMUNE)) { +- flag1 = this.level().removeBlock(blockpos, false) || flag1; ++ if (!iblockdata.isAir() && !iblockdata.is(BlockTags.DRAGON_TRANSPARENT)) { ++ if (this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && !iblockdata.is(BlockTags.DRAGON_IMMUNE)) { ++ // CraftBukkit start - Add blocks to list rather than destroying them ++ // flag1 = this.level().removeBlock(blockposition, false) || flag1; ++ flag1 = true; ++ destroyedBlocks.add(CraftBlock.at(this.level(), blockposition)); ++ // CraftBukkit end + } else { + flag = true; + } +@@ -496,31 +520,76 @@ + } + } + ++ // CraftBukkit start - Set off an EntityExplodeEvent for the dragon exploding all these blocks ++ // SPIGOT-4882: don't fire event if nothing hit ++ if (!flag1) { ++ return flag; ++ } ++ ++ org.bukkit.entity.Entity bukkitEntity = this.getBukkitEntity(); ++ EntityExplodeEvent event = new EntityExplodeEvent(bukkitEntity, bukkitEntity.getLocation(), destroyedBlocks, 0F); ++ bukkitEntity.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ // This flag literally means 'Dragon hit something hard' (Obsidian, White Stone or Bedrock) and will cause the dragon to slow down. ++ // We should consider adding an event extension for it, or perhaps returning true if the event is cancelled. ++ return flag; ++ } else if (event.getYield() == 0F) { ++ // Yield zero ==> no drops ++ for (org.bukkit.block.Block block : event.blockList()) { ++ this.level().removeBlock(new BlockPos(block.getX(), block.getY(), block.getZ()), false); ++ } ++ } else { ++ for (org.bukkit.block.Block block : event.blockList()) { ++ org.bukkit.Material blockId = block.getType(); ++ if (blockId.isAir()) { ++ continue; ++ } ++ ++ CraftBlock craftBlock = ((CraftBlock) block); ++ BlockPos blockposition = craftBlock.getPosition(); ++ ++ Block nmsBlock = craftBlock.getNMS().getBlock(); ++ if (nmsBlock.dropFromExplosion(explosionSource)) { ++ BlockEntity tileentity = craftBlock.getNMS().hasBlockEntity() ? this.level().getBlockEntity(blockposition) : null; ++ LootParams.Builder loottableinfo_builder = (new LootParams.Builder((ServerLevel) this.level())).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockposition)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withParameter(LootContextParams.EXPLOSION_RADIUS, 1.0F / event.getYield()).withOptionalParameter(LootContextParams.BLOCK_ENTITY, tileentity); ++ ++ craftBlock.getNMS().getDrops(loottableinfo_builder).forEach((itemstack) -> { ++ Block.popResource(this.level(), blockposition, itemstack); ++ }); ++ craftBlock.getNMS().spawnAfterBreak((ServerLevel) this.level(), blockposition, ItemStack.EMPTY, false); ++ } ++ nmsBlock.wasExploded(this.level(), blockposition, explosionSource); ++ ++ this.level().removeBlock(blockposition, false); ++ } ++ } ++ // CraftBukkit end ++ + if (flag1) { +- BlockPos blockpos1 = new BlockPos(i + this.random.nextInt(l - i + 1), j + this.random.nextInt(i1 - j + 1), k + this.random.nextInt(j1 - k + 1)); ++ BlockPos blockposition1 = new BlockPos(i + this.random.nextInt(l - i + 1), j + this.random.nextInt(i1 - j + 1), k + this.random.nextInt(j1 - k + 1)); + +- this.level().levelEvent(2008, blockpos1, 0); ++ this.level().levelEvent(2008, blockposition1, 0); + } + + return flag; + } + +- public boolean hurt(EnderDragonPart enderdragonpart, DamageSource damagesource, float f) { ++ public boolean hurt(EnderDragonPart part, DamageSource source, float damage) { + if (this.phaseManager.getCurrentPhase().getPhase() == EnderDragonPhase.DYING) { + return false; + } else { +- f = this.phaseManager.getCurrentPhase().onHurt(damagesource, f); +- if (enderdragonpart != this.head) { +- f = f / 4.0F + Math.min(f, 1.0F); ++ damage = this.phaseManager.getCurrentPhase().onHurt(source, damage); ++ if (part != this.head) { ++ damage = damage / 4.0F + Math.min(damage, 1.0F); + } + +- if (f < 0.01F) { ++ if (damage < 0.01F) { + return false; + } else { +- if (damagesource.getEntity() instanceof Player || damagesource.is(DamageTypeTags.ALWAYS_HURTS_ENDER_DRAGONS)) { ++ if (source.getEntity() instanceof Player || source.is(DamageTypeTags.ALWAYS_HURTS_ENDER_DRAGONS)) { + float f1 = this.getHealth(); + +- this.reallyHurt(damagesource, f); ++ this.reallyHurt(source, damage); + if (this.isDeadOrDying() && !this.phaseManager.getCurrentPhase().isSitting()) { + this.setHealth(1.0F); + this.phaseManager.setPhase(EnderDragonPhase.DYING); +@@ -541,17 +610,15 @@ + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- return !this.level().isClientSide ? this.hurt(this.body, damagesource, f) : false; ++ public boolean hurt(DamageSource source, float amount) { ++ return !this.level().isClientSide ? this.hurt(this.body, source, amount) : false; + } + +- protected boolean reallyHurt(DamageSource damagesource, float f) { +- return super.hurt(damagesource, f); ++ protected boolean reallyHurt(DamageSource damageSource, float amount) { ++ return super.hurt(damageSource, amount); + } + + @Override +- @Override + public void kill() { + this.remove(Entity.RemovalReason.KILLED); + this.gameEvent(GameEvent.ENTITY_DIE); +@@ -562,7 +629,21 @@ + + } + ++ // CraftBukkit start - SPIGOT-2420: Special case, the ender dragon drops 12000 xp for the first kill and 500 xp for every other kill and this over time. + @Override ++ public int getExpReward() { ++ // CraftBukkit - Moved from #tickDeath method ++ boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT); ++ short short0 = 500; ++ ++ if (this.dragonFight != null && !this.dragonFight.hasPreviouslyKilledDragon()) { ++ short0 = 12000; ++ } ++ ++ return flag ? short0 : 0; ++ } ++ // CraftBukkit end ++ + @Override + protected void tickDeath() { + if (this.dragonFight != null) { +@@ -578,15 +659,20 @@ + this.level().addParticle(ParticleTypes.EXPLOSION_EMITTER, this.getX() + (double) f, this.getY() + 2.0D + (double) f1, this.getZ() + (double) f2, 0.0D, 0.0D, 0.0D); + } + ++ // CraftBukkit start - SPIGOT-2420: Moved up to #getExpReward method ++ /* + boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT); + short short0 = 500; + + if (this.dragonFight != null && !this.dragonFight.hasPreviouslyKilledDragon()) { + short0 = 12000; + } ++ */ ++ int short0 = expToDrop; ++ // CraftBukkit end + + if (this.level() instanceof ServerLevel) { +- if (this.dragonDeathTime > 150 && this.dragonDeathTime % 5 == 0 && flag) { ++ if (this.dragonDeathTime > 150 && this.dragonDeathTime % 5 == 0 && true) { // CraftBukkit - SPIGOT-2420: Already checked for the game rule when calculating the xp + ExperienceOrb.award((ServerLevel) this.level(), this.position(), Mth.floor((float) short0 * 0.08F)); + } + +@@ -595,9 +681,9 @@ + } + } + +- this.move(MoverType.SELF, new Vec3(0.0D, 0.10000000149011612D, 0.0D)); ++ this.move(EnumMoveType.SELF, new Vec3(0.0D, 0.10000000149011612D, 0.0D)); + if (this.dragonDeathTime == 200 && this.level() instanceof ServerLevel) { +- if (flag) { ++ if (true) { // CraftBukkit - SPIGOT-2420: Already checked for the game rule when calculating the xp + ExperienceOrb.award((ServerLevel) this.level(), this.position(), Mth.floor((float) short0 * 0.2F)); + } + +@@ -670,10 +756,10 @@ + return this.findClosestNode(this.getX(), this.getY(), this.getZ()); + } + +- public int findClosestNode(double d0, double d1, double d2) { ++ public int findClosestNode(double x, double d1, double y) { + float f = 10000.0F; + int i = 0; +- Node node = new Node(Mth.floor(d0), Mth.floor(d1), Mth.floor(d2)); ++ Node pathpoint = new Node(Mth.floor(x), Mth.floor(d1), Mth.floor(y)); + byte b0 = 0; + + if (this.dragonFight == null || this.dragonFight.getCrystalsAlive() == 0) { +@@ -682,7 +768,7 @@ + + for (int j = b0; j < 24; ++j) { + if (this.nodes[j] != null) { +- float f1 = this.nodes[j].distanceToSqr(node); ++ float f1 = this.nodes[j].distanceToSqr(pathpoint); + + if (f1 < f) { + f = f1; +@@ -695,28 +781,28 @@ + } + + @Nullable +- public Path findPath(int i, int j, @Nullable Node node) { +- Node node1; ++ public Path findPath(int startIndex, int finishIndex, @Nullable Node andThen) { ++ Node pathpoint1; + + for (int k = 0; k < 24; ++k) { +- node1 = this.nodes[k]; +- node1.closed = false; +- node1.f = 0.0F; +- node1.g = 0.0F; +- node1.h = 0.0F; +- node1.cameFrom = null; +- node1.heapIdx = -1; ++ pathpoint1 = this.nodes[k]; ++ pathpoint1.closed = false; ++ pathpoint1.f = 0.0F; ++ pathpoint1.g = 0.0F; ++ pathpoint1.h = 0.0F; ++ pathpoint1.cameFrom = null; ++ pathpoint1.heapIdx = -1; + } + +- Node node2 = this.nodes[i]; ++ Node pathpoint2 = this.nodes[startIndex]; + +- node1 = this.nodes[j]; +- node2.g = 0.0F; +- node2.h = node2.distanceTo(node1); +- node2.f = node2.h; ++ pathpoint1 = this.nodes[finishIndex]; ++ pathpoint2.g = 0.0F; ++ pathpoint2.h = pathpoint2.distanceTo(pathpoint1); ++ pathpoint2.f = pathpoint2.h; + this.openSet.clear(); +- this.openSet.insert(node2); +- Node node3 = node2; ++ this.openSet.insert(pathpoint2); ++ Node pathpoint3 = pathpoint2; + byte b0 = 0; + + if (this.dragonFight == null || this.dragonFight.getCrystalsAlive() == 0) { +@@ -725,28 +811,28 @@ + + label70: + while (!this.openSet.isEmpty()) { +- Node node4 = this.openSet.pop(); ++ Node pathpoint4 = this.openSet.pop(); + +- if (node4.equals(node1)) { +- if (node != null) { +- node.cameFrom = node1; +- node1 = node; ++ if (pathpoint4.equals(pathpoint1)) { ++ if (andThen != null) { ++ andThen.cameFrom = pathpoint1; ++ pathpoint1 = andThen; + } + +- return this.reconstructPath(node2, node1); ++ return this.reconstructPath(pathpoint2, pathpoint1); + } + +- if (node4.distanceTo(node1) < node3.distanceTo(node1)) { +- node3 = node4; ++ if (pathpoint4.distanceTo(pathpoint1) < pathpoint3.distanceTo(pathpoint1)) { ++ pathpoint3 = pathpoint4; + } + +- node4.closed = true; ++ pathpoint4.closed = true; + int l = 0; + int i1 = 0; + + while (true) { + if (i1 < 24) { +- if (this.nodes[i1] != node4) { ++ if (this.nodes[i1] != pathpoint4) { + ++i1; + continue; + } +@@ -762,20 +848,20 @@ + } + + if ((this.nodeAdjacency[l] & 1 << i1) > 0) { +- Node node5 = this.nodes[i1]; ++ Node pathpoint5 = this.nodes[i1]; + +- if (!node5.closed) { +- float f = node4.g + node4.distanceTo(node5); ++ if (!pathpoint5.closed) { ++ float f = pathpoint4.g + pathpoint4.distanceTo(pathpoint5); + +- if (!node5.inOpenSet() || f < node5.g) { +- node5.cameFrom = node4; +- node5.g = f; +- node5.h = node5.distanceTo(node1); +- if (node5.inOpenSet()) { +- this.openSet.changeCost(node5, node5.g + node5.h); ++ if (!pathpoint5.inOpenSet() || f < pathpoint5.g) { ++ pathpoint5.cameFrom = pathpoint4; ++ pathpoint5.g = f; ++ pathpoint5.h = pathpoint5.distanceTo(pathpoint1); ++ if (pathpoint5.inOpenSet()) { ++ this.openSet.changeCost(pathpoint5, pathpoint5.g + pathpoint5.h); + } else { +- node5.f = node5.g + node5.h; +- this.openSet.insert(node5); ++ pathpoint5.f = pathpoint5.g + pathpoint5.h; ++ this.openSet.insert(pathpoint5); + } + } + } +@@ -786,57 +872,60 @@ + } + } + +- if (node3 == node2) { ++ if (pathpoint3 == pathpoint2) { + return null; + } else { +- EnderDragon.LOGGER.debug("Failed to find path from {} to {}", i, j); +- if (node != null) { +- node.cameFrom = node3; +- node3 = node; ++ EnderDragon.LOGGER.debug("Failed to find path from {} to {}", startIndex, finishIndex); ++ if (andThen != null) { ++ andThen.cameFrom = pathpoint3; ++ pathpoint3 = andThen; + } + +- return this.reconstructPath(node2, node3); ++ return this.reconstructPath(pathpoint2, pathpoint3); + } + } + +- private Path reconstructPath(Node node, Node node1) { ++ private Path reconstructPath(Node start, Node finish) { + List list = Lists.newArrayList(); +- Node node2 = node1; ++ Node pathpoint2 = finish; + +- list.add(0, node1); ++ list.add(0, finish); + +- while (node2.cameFrom != null) { +- node2 = node2.cameFrom; +- list.add(0, node2); ++ while (pathpoint2.cameFrom != null) { ++ pathpoint2 = pathpoint2.cameFrom; ++ list.add(0, pathpoint2); + } + +- return new Path(list, new BlockPos(node1.x, node1.y, node1.z), true); ++ return new Path(list, new BlockPos(finish.x, finish.y, finish.z), true); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("DragonPhase", this.phaseManager.getCurrentPhase().getPhase().getId()); +- compoundtag.putInt("DragonDeathTime", this.dragonDeathTime); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("DragonPhase", this.phaseManager.getCurrentPhase().getPhase().getId()); ++ compound.putInt("DragonDeathTime", this.dragonDeathTime); ++ compound.putInt("Bukkit.expToDrop", expToDrop); // CraftBukkit - SPIGOT-2420: The ender dragon drops xp over time which can also happen between server starts + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("DragonPhase")) { +- this.phaseManager.setPhase(EnderDragonPhase.getById(compoundtag.getInt("DragonPhase"))); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("DragonPhase")) { ++ this.phaseManager.setPhase(EnderDragonPhase.getById(compound.getInt("DragonPhase"))); + } + +- if (compoundtag.contains("DragonDeathTime")) { +- this.dragonDeathTime = compoundtag.getInt("DragonDeathTime"); ++ if (compound.contains("DragonDeathTime")) { ++ this.dragonDeathTime = compound.getInt("DragonDeathTime"); + } + ++ // CraftBukkit start - SPIGOT-2420: The ender dragon drops xp over time which can also happen between server starts ++ if (compound.contains("Bukkit.expToDrop")) { ++ this.expToDrop = compound.getInt("Bukkit.expToDrop"); ++ } ++ // CraftBukkit end + } + + @Override +- @Override + public void checkDespawn() {} + + public EnderDragonPart[] getSubEntities() { +@@ -844,115 +933,109 @@ + } + + @Override +- @Override + public boolean isPickable() { + return false; + } + + @Override +- @Override + public SoundSource getSoundSource() { + return SoundSource.HOSTILE; + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.ENDER_DRAGON_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.ENDER_DRAGON_HURT; + } + + @Override +- @Override + protected float getSoundVolume() { + return 5.0F; + } + +- public float getHeadPartYOffset(int i, double[] adouble, double[] adouble1) { +- DragonPhaseInstance dragonphaseinstance = this.phaseManager.getCurrentPhase(); +- EnderDragonPhase enderdragonphase = dragonphaseinstance.getPhase(); ++ public float getHeadPartYOffset(int partIndex, double[] spineEndOffsets, double[] headPartOffsets) { ++ DragonPhaseInstance idragoncontroller = this.phaseManager.getCurrentPhase(); ++ EnderDragonPhase dragoncontrollerphase = idragoncontroller.getPhase(); + double d0; + +- if (enderdragonphase != EnderDragonPhase.LANDING && enderdragonphase != EnderDragonPhase.TAKEOFF) { +- if (dragonphaseinstance.isSitting()) { +- d0 = (double) i; +- } else if (i == 6) { ++ if (dragoncontrollerphase != EnderDragonPhase.LANDING && dragoncontrollerphase != EnderDragonPhase.TAKEOFF) { ++ if (idragoncontroller.isSitting()) { ++ d0 = (double) partIndex; ++ } else if (partIndex == 6) { + d0 = 0.0D; + } else { +- d0 = adouble1[1] - adouble[1]; ++ d0 = headPartOffsets[1] - spineEndOffsets[1]; + } + } else { +- BlockPos blockpos = this.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.fightOrigin)); +- double d1 = Math.max(Math.sqrt(blockpos.distToCenterSqr(this.position())) / 4.0D, 1.0D); ++ BlockPos blockposition = this.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.fightOrigin)); ++ double d1 = Math.max(Math.sqrt(blockposition.distToCenterSqr(this.position())) / 4.0D, 1.0D); + +- d0 = (double) i / d1; ++ d0 = (double) partIndex / d1; + } + + return (float) d0; + } + +- public Vec3 getHeadLookVector(float f) { +- DragonPhaseInstance dragonphaseinstance = this.phaseManager.getCurrentPhase(); +- EnderDragonPhase enderdragonphase = dragonphaseinstance.getPhase(); ++ public Vec3 getHeadLookVector(float partialTicks) { ++ DragonPhaseInstance idragoncontroller = this.phaseManager.getCurrentPhase(); ++ EnderDragonPhase dragoncontrollerphase = idragoncontroller.getPhase(); + float f1; +- Vec3 vec3; ++ Vec3 vec3d; + +- if (enderdragonphase != EnderDragonPhase.LANDING && enderdragonphase != EnderDragonPhase.TAKEOFF) { +- if (dragonphaseinstance.isSitting()) { ++ if (dragoncontrollerphase != EnderDragonPhase.LANDING && dragoncontrollerphase != EnderDragonPhase.TAKEOFF) { ++ if (idragoncontroller.isSitting()) { + float f2 = this.getXRot(); + + f1 = 1.5F; + this.setXRot(-45.0F); +- vec3 = this.getViewVector(f); ++ vec3d = this.getViewVector(partialTicks); + this.setXRot(f2); + } else { +- vec3 = this.getViewVector(f); ++ vec3d = this.getViewVector(partialTicks); + } + } else { +- BlockPos blockpos = this.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.fightOrigin)); ++ BlockPos blockposition = this.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.fightOrigin)); + +- f1 = Math.max((float) Math.sqrt(blockpos.distToCenterSqr(this.position())) / 4.0F, 1.0F); ++ f1 = Math.max((float) Math.sqrt(blockposition.distToCenterSqr(this.position())) / 4.0F, 1.0F); + float f3 = 6.0F / f1; + float f4 = this.getXRot(); + float f5 = 1.5F; + + this.setXRot(-f3 * 1.5F * 5.0F); +- vec3 = this.getViewVector(f); ++ vec3d = this.getViewVector(partialTicks); + this.setXRot(f4); + } + +- return vec3; ++ return vec3d; + } + +- public void onCrystalDestroyed(EndCrystal endcrystal, BlockPos blockpos, DamageSource damagesource) { +- Player player; ++ public void onCrystalDestroyed(EndCrystal crystal, BlockPos pos, DamageSource damageSource) { ++ Player entityhuman; + +- if (damagesource.getEntity() instanceof Player) { +- player = (Player) damagesource.getEntity(); ++ if (damageSource.getEntity() instanceof Player) { ++ entityhuman = (Player) damageSource.getEntity(); + } else { +- player = this.level().getNearestPlayer(EnderDragon.CRYSTAL_DESTROY_TARGETING, (double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ()); ++ entityhuman = this.level().getNearestPlayer(EnderDragon.CRYSTAL_DESTROY_TARGETING, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ()); + } + +- if (endcrystal == this.nearestCrystal) { +- this.hurt(this.head, this.damageSources().explosion(endcrystal, player), 10.0F); ++ if (crystal == this.nearestCrystal) { ++ this.hurt(this.head, this.damageSources().explosion(crystal, entityhuman), 10.0F); + } + +- this.phaseManager.getCurrentPhase().onCrystalDestroyed(endcrystal, blockpos, damagesource, player); ++ this.phaseManager.getCurrentPhase().onCrystalDestroyed(crystal, pos, damageSource, entityhuman); + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- if (EnderDragon.DATA_PHASE.equals(entitydataaccessor) && this.level().isClientSide) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ if (EnderDragon.DATA_PHASE.equals(key) && this.level().isClientSide) { + this.phaseManager.setPhase(EnderDragonPhase.getById((Integer) this.getEntityData().get(EnderDragon.DATA_PHASE))); + } + +- super.onSyncedDataUpdated(entitydataaccessor); ++ super.onSyncedDataUpdated(key); + } + + public EnderDragonPhaseManager getPhaseManager() { +@@ -965,44 +1048,38 @@ + } + + @Override +- @Override +- public boolean addEffect(MobEffectInstance mobeffectinstance, @Nullable Entity entity) { ++ public boolean addEffect(MobEffectInstance effectInstance, @Nullable Entity entity) { + return false; + } + + @Override +- @Override + protected boolean canRide(Entity entity) { + return false; + } + + @Override +- @Override + public boolean canChangeDimensions() { + return false; + } + + @Override +- @Override +- public void recreateFromPacket(ClientboundAddEntityPacket clientboundaddentitypacket) { +- super.recreateFromPacket(clientboundaddentitypacket); +- EnderDragonPart[] aenderdragonpart = this.getSubEntities(); ++ public void recreateFromPacket(ClientboundAddEntityPacket packet) { ++ super.recreateFromPacket(packet); ++ EnderDragonPart[] aentitycomplexpart = this.getSubEntities(); + +- for (int i = 0; i < aenderdragonpart.length; ++i) { +- aenderdragonpart[i].setId(i + clientboundaddentitypacket.getId()); ++ for (int i = 0; i < aentitycomplexpart.length; ++i) { ++ aentitycomplexpart[i].setId(i + packet.getId()); + } + + } + + @Override +- @Override +- public boolean canAttack(LivingEntity livingentity) { +- return livingentity.canBeSeenAsEnemy(); ++ public boolean canAttack(LivingEntity target) { ++ return target.canBeSeenAsEnemy(); + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { + return new Vector3f(0.0F, this.body.getBbHeight(), 0.0F); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhaseManager.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhaseManager.java.patch new file mode 100644 index 0000000000..cb3cd3f470 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhaseManager.java.patch @@ -0,0 +1,76 @@ +--- a/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhaseManager.java ++++ b/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhaseManager.java +@@ -5,6 +5,11 @@ + import net.minecraft.world.entity.boss.enderdragon.EnderDragon; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftEnderDragon; ++import org.bukkit.event.entity.EnderDragonChangePhaseEvent; ++// CraftBukkit end ++ + public class EnderDragonPhaseManager { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -13,23 +18,36 @@ + @Nullable + private DragonPhaseInstance currentPhase; + +- public EnderDragonPhaseManager(EnderDragon enderdragon) { +- this.dragon = enderdragon; ++ public EnderDragonPhaseManager(EnderDragon dragon) { ++ this.dragon = dragon; + this.setPhase(EnderDragonPhase.HOVERING); + } + +- public void setPhase(EnderDragonPhase enderdragonphase) { +- if (this.currentPhase == null || enderdragonphase != this.currentPhase.getPhase()) { ++ public void setPhase(EnderDragonPhase phase) { ++ if (this.currentPhase == null || phase != this.currentPhase.getPhase()) { + if (this.currentPhase != null) { + this.currentPhase.end(); + } + +- this.currentPhase = this.getPhase(enderdragonphase); ++ // CraftBukkit start - Call EnderDragonChangePhaseEvent ++ EnderDragonChangePhaseEvent event = new EnderDragonChangePhaseEvent( ++ (CraftEnderDragon) this.dragon.getBukkitEntity(), ++ (this.currentPhase == null) ? null : CraftEnderDragon.getBukkitPhase(this.currentPhase.getPhase()), ++ CraftEnderDragon.getBukkitPhase(phase) ++ ); ++ this.dragon.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ phase = CraftEnderDragon.getMinecraftPhase(event.getNewPhase()); ++ // CraftBukkit end ++ ++ this.currentPhase = this.getPhase(phase); + if (!this.dragon.level().isClientSide) { +- this.dragon.getEntityData().set(EnderDragon.DATA_PHASE, enderdragonphase.getId()); ++ this.dragon.getEntityData().set(EnderDragon.DATA_PHASE, phase.getId()); + } + +- EnderDragonPhaseManager.LOGGER.debug("Dragon is now in phase {} on the {}", enderdragonphase, this.dragon.level().isClientSide ? "client" : "server"); ++ EnderDragonPhaseManager.LOGGER.debug("Dragon is now in phase {} on the {}", phase, this.dragon.level().isClientSide ? "client" : "server"); + this.currentPhase.begin(); + } + } +@@ -38,13 +56,13 @@ + return this.currentPhase; + } + +- public T getPhase(EnderDragonPhase enderdragonphase) { +- int i = enderdragonphase.getId(); ++ public T getPhase(EnderDragonPhase phase) { ++ int i = phase.getId(); + + if (this.phases[i] == null) { +- this.phases[i] = enderdragonphase.createInstance(this.dragon); ++ this.phases[i] = phase.createInstance(this.dragon); + } + +- return this.phases[i]; ++ return (T) this.phases[i]; // CraftBukkit - decompile error + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/boss/wither/WitherBoss.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/boss/wither/WitherBoss.java.patch new file mode 100644 index 0000000000..3777093190 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/boss/wither/WitherBoss.java.patch @@ -0,0 +1,627 @@ +--- a/net/minecraft/world/entity/boss/wither/WitherBoss.java ++++ b/net/minecraft/world/entity/boss/wither/WitherBoss.java +@@ -5,17 +5,6 @@ + import java.util.List; + import java.util.function.Predicate; + import javax.annotation.Nullable; +-import net.minecraft.core.BlockPos; +-import net.minecraft.core.particles.ParticleTypes; +-import net.minecraft.nbt.CompoundTag; +-import net.minecraft.network.chat.Component; +-import net.minecraft.network.syncher.EntityDataAccessor; +-import net.minecraft.network.syncher.EntityDataSerializers; +-import net.minecraft.network.syncher.SynchedEntityData; +-import net.minecraft.server.level.ServerBossEvent; +-import net.minecraft.server.level.ServerPlayer; +-import net.minecraft.sounds.SoundEvent; +-import net.minecraft.sounds.SoundEvents; + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.DamageTypeTags; + import net.minecraft.util.Mth; +@@ -26,17 +15,17 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobType; + import net.minecraft.world.entity.PowerableMob; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.FlyingMoveControl; + import net.minecraft.world.entity.ai.goal.Goal; + import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalRandomFly; + import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal; + import net.minecraft.world.entity.ai.goal.RangedAttackGoal; +-import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomFlyingGoal; + import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal; + import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; + import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation; +@@ -50,10 +39,30 @@ + import net.minecraft.world.entity.projectile.WitherSkull; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.GameRules; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.particles.ParticleTypes; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.network.chat.Component; ++import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; ++import net.minecraft.network.syncher.EntityDataAccessor; ++import net.minecraft.network.syncher.EntityDataSerializers; ++import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerBossEvent; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundEvents; ++import net.minecraft.world.level.block.Blocks; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end + + public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob { + +@@ -70,14 +79,14 @@ + private final int[] nextHeadUpdate = new int[2]; + private final int[] idleHeadUpdates = new int[2]; + private int destroyBlocksTick; +- private final ServerBossEvent bossEvent; +- private static final Predicate LIVING_ENTITY_SELECTOR = (livingentity) -> { +- return livingentity.getMobType() != MobType.UNDEAD && livingentity.attackable(); ++ public final ServerBossEvent bossEvent; ++ private static final Predicate LIVING_ENTITY_SELECTOR = (entityliving) -> { ++ return entityliving.getMobType() != EnumMonsterType.UNDEAD && entityliving.attackable(); + }; + private static final TargetingConditions TARGETING_CONDITIONS = TargetingConditions.forCombat().range(20.0D).selector(WitherBoss.LIVING_ENTITY_SELECTOR); + +- public WitherBoss(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public WitherBoss(EntityType entityType, Level level) { ++ super(entityType, level); + this.bossEvent = (ServerBossEvent) (new ServerBossEvent(this.getDisplayName(), BossEvent.BossBarColor.PURPLE, BossEvent.BossBarOverlay.PROGRESS)).setDarkenScreen(true); + this.moveControl = new FlyingMoveControl(this, 10, false); + this.setHealth(this.getMaxHealth()); +@@ -85,22 +94,20 @@ + } + + @Override +- @Override + protected PathNavigation createNavigation(Level level) { +- FlyingPathNavigation flyingpathnavigation = new FlyingPathNavigation(this, level); ++ FlyingPathNavigation navigationflying = new FlyingPathNavigation(this, level); + +- flyingpathnavigation.setCanOpenDoors(false); +- flyingpathnavigation.setCanFloat(true); +- flyingpathnavigation.setCanPassDoors(true); +- return flyingpathnavigation; ++ navigationflying.setCanOpenDoors(false); ++ navigationflying.setCanFloat(true); ++ navigationflying.setCanPassDoors(true); ++ return navigationflying; + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new WitherBoss.WitherDoNothingGoal()); + this.goalSelector.addGoal(2, new RangedAttackGoal(this, 1.0D, 40, 20.0F)); +- this.goalSelector.addGoal(5, new WaterAvoidingRandomFlyingGoal(this, 1.0D)); ++ this.goalSelector.addGoal(5, new PathfinderGoalRandomFly(this, 1.0D)); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(7, new RandomLookAroundGoal(this)); + this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0])); +@@ -108,7 +115,6 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(WitherBoss.DATA_TARGET_A, 0); +@@ -118,17 +124,15 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("Invul", this.getInvulnerableTicks()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("Invul", this.getInvulnerableTicks()); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setInvulnerableTicks(compoundtag.getInt("Invul")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setInvulnerableTicks(compound.getInt("Invul")); + if (this.hasCustomName()) { + this.bossEvent.setName(this.getDisplayName()); + } +@@ -136,60 +140,55 @@ + } + + @Override +- @Override +- public void setCustomName(@Nullable Component component) { +- super.setCustomName(component); ++ public void setCustomName(@Nullable Component name) { ++ super.setCustomName(name); + this.bossEvent.setName(this.getDisplayName()); + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.WITHER_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.WITHER_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.WITHER_DEATH; + } + + @Override +- @Override + public void aiStep() { +- Vec3 vec3 = this.getDeltaMovement().multiply(1.0D, 0.6D, 1.0D); ++ Vec3 vec3d = this.getDeltaMovement().multiply(1.0D, 0.6D, 1.0D); + + if (!this.level().isClientSide && this.getAlternativeTarget(0) > 0) { + Entity entity = this.level().getEntity(this.getAlternativeTarget(0)); + + if (entity != null) { +- double d0 = vec3.y; ++ double d0 = vec3d.y; + + if (this.getY() < entity.getY() || !this.isPowered() && this.getY() < entity.getY() + 5.0D) { + d0 = Math.max(0.0D, d0); + d0 += 0.3D - d0 * 0.6000000238418579D; + } + +- vec3 = new Vec3(vec3.x, d0, vec3.z); +- Vec3 vec31 = new Vec3(entity.getX() - this.getX(), 0.0D, entity.getZ() - this.getZ()); ++ vec3d = new Vec3(vec3d.x, d0, vec3d.z); ++ Vec3 vec3d1 = new Vec3(entity.getX() - this.getX(), 0.0D, entity.getZ() - this.getZ()); + +- if (vec31.horizontalDistanceSqr() > 9.0D) { +- Vec3 vec32 = vec31.normalize(); ++ if (vec3d1.horizontalDistanceSqr() > 9.0D) { ++ Vec3 vec3d2 = vec3d1.normalize(); + +- vec3 = vec3.add(vec32.x * 0.3D - vec3.x * 0.6D, 0.0D, vec32.z * 0.3D - vec3.z * 0.6D); ++ vec3d = vec3d.add(vec3d2.x * 0.3D - vec3d.x * 0.6D, 0.0D, vec3d2.z * 0.3D - vec3d.z * 0.6D); + } + } + } + +- this.setDeltaMovement(vec3); +- if (vec3.horizontalDistanceSqr() > 0.05D) { +- this.setYRot((float) Mth.atan2(vec3.z, vec3.x) * 57.295776F - 90.0F); ++ this.setDeltaMovement(vec3d); ++ if (vec3d.horizontalDistanceSqr() > 0.05D) { ++ this.setYRot((float) Mth.atan2(vec3d.z, vec3d.x) * 57.295776F - 90.0F); + } + + super.aiStep(); +@@ -251,7 +250,6 @@ + } + + @Override +- @Override + protected void customServerAiStep() { + int i; + +@@ -259,15 +257,40 @@ + i = this.getInvulnerableTicks() - 1; + this.bossEvent.setProgress(1.0F - (float) i / 220.0F); + if (i <= 0) { +- this.level().explode(this, this.getX(), this.getEyeY(), this.getZ(), 7.0F, false, Level.ExplosionInteraction.MOB); ++ // CraftBukkit start ++ // this.level().explode(this, this.getX(), this.getEyeY(), this.getZ(), 7.0F, false, World.a.MOB); ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), 7.0F, false); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ this.level().explode(this, this.getX(), this.getEyeY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.MOB); ++ } ++ // CraftBukkit end ++ + if (!this.isSilent()) { +- this.level().globalLevelEvent(1023, this.blockPosition(), 0); ++ // CraftBukkit start - Use relative location for far away sounds ++ // this.level().globalLevelEvent(1023, new BlockPosition(this), 0); ++ int viewDistance = ((ServerLevel) this.level()).getCraftServer().getViewDistance() * 16; ++ for (ServerPlayer player : (List) MinecraftServer.getServer().getPlayerList().players) { ++ double deltaX = this.getX() - player.getX(); ++ double deltaZ = this.getZ() - player.getZ(); ++ double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; ++ if (distanceSquared > viewDistance * viewDistance) { ++ double deltaLength = Math.sqrt(distanceSquared); ++ double relativeX = player.getX() + (deltaX / deltaLength) * viewDistance; ++ double relativeZ = player.getZ() + (deltaZ / deltaLength) * viewDistance; ++ player.connection.send(new ClientboundLevelEventPacket(1023, new BlockPos((int) relativeX, (int) this.getY(), (int) relativeZ), 0, true)); ++ } else { ++ player.connection.send(new ClientboundLevelEventPacket(1023, this.blockPosition(), 0, true)); ++ } ++ } ++ // CraftBukkit end + } + } + + this.setInvulnerableTicks(i); + if (this.tickCount % 10 == 0) { +- this.heal(10.0F); ++ this.heal(10.0F, EntityRegainHealthEvent.RegainReason.WITHER_SPAWN); // CraftBukkit + } + + } else { +@@ -297,10 +320,10 @@ + + j = this.getAlternativeTarget(i); + if (j > 0) { +- LivingEntity livingentity = (LivingEntity) this.level().getEntity(j); ++ LivingEntity entityliving = (LivingEntity) this.level().getEntity(j); + +- if (livingentity != null && this.canAttack(livingentity) && this.distanceToSqr((Entity) livingentity) <= 900.0D && this.hasLineOfSight(livingentity)) { +- this.performRangedAttack(i + 1, livingentity); ++ if (entityliving != null && this.canAttack(entityliving) && this.distanceToSqr((Entity) entityliving) <= 900.0D && this.hasLineOfSight(entityliving)) { ++ this.performRangedAttack(i + 1, entityliving); + this.nextHeadUpdate[i - 1] = this.tickCount + 40 + this.random.nextInt(20); + this.idleHeadUpdates[i - 1] = 0; + } else { +@@ -310,9 +333,10 @@ + List list = this.level().getNearbyEntities(LivingEntity.class, WitherBoss.TARGETING_CONDITIONS, this, this.getBoundingBox().inflate(20.0D, 8.0D, 20.0D)); + + if (!list.isEmpty()) { +- LivingEntity livingentity1 = (LivingEntity) list.get(this.random.nextInt(list.size())); ++ LivingEntity entityliving1 = (LivingEntity) list.get(this.random.nextInt(list.size())); + +- this.setAlternativeTarget(i, livingentity1.getId()); ++ if (CraftEventFactory.callEntityTargetLivingEvent(this, entityliving1, EntityTargetEvent.TargetReason.CLOSEST_ENTITY).isCancelled()) continue; // CraftBukkit ++ this.setAlternativeTarget(i, entityliving1.getId()); + } + } + } +@@ -338,11 +362,16 @@ + int i2 = j + j1; + int j2 = i + l1; + int k2 = i1 + k1; +- BlockPos blockpos = new BlockPos(i2, j2, k2); +- BlockState blockstate = this.level().getBlockState(blockpos); ++ BlockPos blockposition = new BlockPos(i2, j2, k2); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); + +- if (canDestroy(blockstate)) { +- flag = this.level().destroyBlock(blockpos, true, this) || flag; ++ if (canDestroy(iblockdata)) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState())) { ++ continue; ++ } ++ // CraftBukkit end ++ flag = this.level().destroyBlock(blockposition, true, this) || flag; + } + } + } +@@ -355,15 +384,15 @@ + } + + if (this.tickCount % 20 == 0) { +- this.heal(1.0F); ++ this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit + } + + this.bossEvent.setProgress(this.getHealth() / this.getMaxHealth()); + } + } + +- public static boolean canDestroy(BlockState blockstate) { +- return !blockstate.isAir() && !blockstate.is(BlockTags.WITHER_IMMUNE); ++ public static boolean canDestroy(IBlockData state) { ++ return !state.isAir() && !state.is(BlockTags.WITHER_IMMUNE); + } + + public void makeInvulnerable() { +@@ -373,51 +402,48 @@ + } + + @Override +- @Override +- public void makeStuckInBlock(BlockState blockstate, Vec3 vec3) {} ++ public void makeStuckInBlock(IBlockData state, Vec3 motionMultiplier) {} + + @Override +- @Override +- public void startSeenByPlayer(ServerPlayer serverplayer) { +- super.startSeenByPlayer(serverplayer); +- this.bossEvent.addPlayer(serverplayer); ++ public void startSeenByPlayer(ServerPlayer player) { ++ super.startSeenByPlayer(player); ++ this.bossEvent.addPlayer(player); + } + + @Override +- @Override +- public void stopSeenByPlayer(ServerPlayer serverplayer) { +- super.stopSeenByPlayer(serverplayer); +- this.bossEvent.removePlayer(serverplayer); ++ public void stopSeenByPlayer(ServerPlayer player) { ++ super.stopSeenByPlayer(player); ++ this.bossEvent.removePlayer(player); + } + +- private double getHeadX(int i) { +- if (i <= 0) { ++ private double getHeadX(int head) { ++ if (head <= 0) { + return this.getX(); + } else { +- float f = (this.yBodyRot + (float) (180 * (i - 1))) * 0.017453292F; ++ float f = (this.yBodyRot + (float) (180 * (head - 1))) * 0.017453292F; + float f1 = Mth.cos(f); + + return this.getX() + (double) f1 * 1.3D; + } + } + +- private double getHeadY(int i) { +- return i <= 0 ? this.getY() + 3.0D : this.getY() + 2.2D; ++ private double getHeadY(int head) { ++ return head <= 0 ? this.getY() + 3.0D : this.getY() + 2.2D; + } + +- private double getHeadZ(int i) { +- if (i <= 0) { ++ private double getHeadZ(int head) { ++ if (head <= 0) { + return this.getZ(); + } else { +- float f = (this.yBodyRot + (float) (180 * (i - 1))) * 0.017453292F; ++ float f = (this.yBodyRot + (float) (180 * (head - 1))) * 0.017453292F; + float f1 = Mth.sin(f); + + return this.getZ() + (double) f1 * 1.3D; + } + } + +- private float rotlerp(float f, float f1, float f2) { +- float f3 = Mth.wrapDegrees(f1 - f); ++ private float rotlerp(float angle, float f1, float f2) { ++ float f3 = Mth.wrapDegrees(f1 - angle); + + if (f3 > f2) { + f3 = f2; +@@ -427,60 +453,58 @@ + f3 = -f2; + } + +- return f + f3; ++ return angle + f3; + } + +- private void performRangedAttack(int i, LivingEntity livingentity) { +- this.performRangedAttack(i, livingentity.getX(), livingentity.getY() + (double) livingentity.getEyeHeight() * 0.5D, livingentity.getZ(), i == 0 && this.random.nextFloat() < 0.001F); ++ private void performRangedAttack(int head, LivingEntity target) { ++ this.performRangedAttack(head, target.getX(), target.getY() + (double) target.getEyeHeight() * 0.5D, target.getZ(), head == 0 && this.random.nextFloat() < 0.001F); + } + +- private void performRangedAttack(int i, double d0, double d1, double d2, boolean flag) { ++ private void performRangedAttack(int head, double x, double d1, double y, boolean flag) { + if (!this.isSilent()) { + this.level().levelEvent((Player) null, 1024, this.blockPosition(), 0); + } + +- double d3 = this.getHeadX(i); +- double d4 = this.getHeadY(i); +- double d5 = this.getHeadZ(i); +- double d6 = d0 - d3; ++ double d3 = this.getHeadX(head); ++ double d4 = this.getHeadY(head); ++ double d5 = this.getHeadZ(head); ++ double d6 = x - d3; + double d7 = d1 - d4; +- double d8 = d2 - d5; +- WitherSkull witherskull = new WitherSkull(this.level(), this, d6, d7, d8); ++ double d8 = y - d5; ++ WitherSkull entitywitherskull = new WitherSkull(this.level(), this, d6, d7, d8); + +- witherskull.setOwner(this); ++ entitywitherskull.setOwner(this); + if (flag) { +- witherskull.setDangerous(true); ++ entitywitherskull.setDangerous(true); + } + +- witherskull.setPosRaw(d3, d4, d5); +- this.level().addFreshEntity(witherskull); ++ entitywitherskull.setPosRaw(d3, d4, d5); ++ this.level().addFreshEntity(entitywitherskull); + } + + @Override +- @Override +- public void performRangedAttack(LivingEntity livingentity, float f) { +- this.performRangedAttack(0, livingentity); ++ public void performRangedAttack(LivingEntity target, float distanceFactor) { ++ this.performRangedAttack(0, target); + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- if (this.isInvulnerableTo(damagesource)) { ++ public boolean hurt(DamageSource source, float amount) { ++ if (this.isInvulnerableTo(source)) { + return false; +- } else if (!damagesource.is(DamageTypeTags.WITHER_IMMUNE_TO) && !(damagesource.getEntity() instanceof WitherBoss)) { +- if (this.getInvulnerableTicks() > 0 && !damagesource.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { ++ } else if (!source.is(DamageTypeTags.WITHER_IMMUNE_TO) && !(source.getEntity() instanceof WitherBoss)) { ++ if (this.getInvulnerableTicks() > 0 && !source.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { + return false; + } else { + Entity entity; + + if (this.isPowered()) { +- entity = damagesource.getDirectEntity(); ++ entity = source.getDirectEntity(); + if (entity instanceof AbstractArrow) { + return false; + } + } + +- entity = damagesource.getEntity(); ++ entity = source.getEntity(); + if (entity != null && !(entity instanceof Player) && entity instanceof LivingEntity && ((LivingEntity) entity).getMobType() == this.getMobType()) { + return false; + } else { +@@ -492,7 +516,7 @@ + this.idleHeadUpdates[i] += 3; + } + +- return super.hurt(damagesource, f); ++ return super.hurt(source, amount); + } + } + } else { +@@ -501,19 +525,17 @@ + } + + @Override +- @Override +- protected void dropCustomDeathLoot(DamageSource damagesource, int i, boolean flag) { +- super.dropCustomDeathLoot(damagesource, i, flag); +- ItemEntity itementity = this.spawnAtLocation((ItemLike) Items.NETHER_STAR); ++ protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { ++ super.dropCustomDeathLoot(source, looting, recentlyHit); ++ ItemEntity entityitem = this.spawnAtLocation((IMaterial) Items.NETHER_STAR); + +- if (itementity != null) { +- itementity.setExtendedLifetime(); ++ if (entityitem != null) { ++ entityitem.setExtendedLifetime(); + } + + } + + @Override +- @Override + public void checkDespawn() { + if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.shouldDespawnInPeaceful()) { + this.discard(); +@@ -523,8 +545,7 @@ + } + + @Override +- @Override +- public boolean addEffect(MobEffectInstance mobeffectinstance, @Nullable Entity entity) { ++ public boolean addEffect(MobEffectInstance effectInstance, @Nullable Entity entity) { + return false; + } + +@@ -532,68 +553,62 @@ + return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 300.0D).add(Attributes.MOVEMENT_SPEED, 0.6000000238418579D).add(Attributes.FLYING_SPEED, 0.6000000238418579D).add(Attributes.FOLLOW_RANGE, 40.0D).add(Attributes.ARMOR, 4.0D); + } + +- public float getHeadYRot(int i) { +- return this.yRotHeads[i]; ++ public float getHeadYRot(int head) { ++ return this.yRotHeads[head]; + } + +- public float getHeadXRot(int i) { +- return this.xRotHeads[i]; ++ public float getHeadXRot(int head) { ++ return this.xRotHeads[head]; + } + + public int getInvulnerableTicks() { + return (Integer) this.entityData.get(WitherBoss.DATA_ID_INV); + } + +- public void setInvulnerableTicks(int i) { +- this.entityData.set(WitherBoss.DATA_ID_INV, i); ++ public void setInvulnerableTicks(int invulnerableTicks) { ++ this.entityData.set(WitherBoss.DATA_ID_INV, invulnerableTicks); + } + +- public int getAlternativeTarget(int i) { +- return (Integer) this.entityData.get((EntityDataAccessor) WitherBoss.DATA_TARGETS.get(i)); ++ public int getAlternativeTarget(int head) { ++ return (Integer) this.entityData.get((EntityDataAccessor) WitherBoss.DATA_TARGETS.get(head)); + } + +- public void setAlternativeTarget(int i, int j) { +- this.entityData.set((EntityDataAccessor) WitherBoss.DATA_TARGETS.get(i), j); ++ public void setAlternativeTarget(int targetOffset, int newId) { ++ this.entityData.set((EntityDataAccessor) WitherBoss.DATA_TARGETS.get(targetOffset), newId); + } + + @Override +- @Override + public boolean isPowered() { + return this.getHealth() <= this.getMaxHealth() / 2.0F; + } + + @Override +- @Override +- public MobType getMobType() { +- return MobType.UNDEAD; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.UNDEAD; + } + + @Override +- @Override + protected boolean canRide(Entity entity) { + return false; + } + + @Override +- @Override + public boolean canChangeDimensions() { + return false; + } + + @Override +- @Override +- public boolean canBeAffected(MobEffectInstance mobeffectinstance) { +- return mobeffectinstance.getEffect() == MobEffects.WITHER ? false : super.canBeAffected(mobeffectinstance); ++ public boolean canBeAffected(MobEffectInstance potioneffect) { ++ return potioneffect.getEffect() == MobEffects.WITHER ? false : super.canBeAffected(potioneffect); + } + + private class WitherDoNothingGoal extends Goal { + + public WitherDoNothingGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.JUMP, Goal.Flag.LOOK)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.JUMP, Goal.Type.LOOK)); + } + + @Override +- @Override + public boolean canUse() { + return WitherBoss.this.getInvulnerableTicks() > 0; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/decoration/ArmorStand.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/decoration/ArmorStand.java.patch new file mode 100644 index 0000000000..65bf674bb6 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/decoration/ArmorStand.java.patch @@ -0,0 +1,1126 @@ +--- a/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -18,31 +18,36 @@ + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.tags.DamageTypeTags; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.HumanoidArm; + import net.minecraft.world.entity.LightningBolt; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.vehicle.AbstractMinecart; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; ++import net.minecraft.world.level.EnumSkyBlock; + import net.minecraft.world.level.Explosion; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.gameevent.GameEvent; +-import net.minecraft.world.level.material.PushReaction; ++import net.minecraft.world.level.material.EnumPistonReaction; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.inventory.EquipmentSlot; ++import org.bukkit.craftbukkit.CraftEquipmentSlot; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerArmorStandManipulateEvent; ++// CraftBukkit end + + public class ArmorStand extends LivingEntity { + +@@ -74,22 +79,22 @@ + public static final EntityDataAccessor DATA_LEFT_LEG_POSE = SynchedEntityData.defineId(ArmorStand.class, EntityDataSerializers.ROTATIONS); + public static final EntityDataAccessor DATA_RIGHT_LEG_POSE = SynchedEntityData.defineId(ArmorStand.class, EntityDataSerializers.ROTATIONS); + private static final Predicate RIDABLE_MINECARTS = (entity) -> { +- return entity instanceof AbstractMinecart && ((AbstractMinecart) entity).getMinecartType() == AbstractMinecart.Type.RIDEABLE; ++ return entity instanceof AbstractMinecart && ((AbstractMinecart) entity).getMinecartType() == AbstractMinecart.EnumMinecartType.RIDEABLE; + }; + private final NonNullList handItems; + private final NonNullList armorItems; + private boolean invisible; + public long lastHit; +- private int disabledSlots; +- private Rotations headPose; +- private Rotations bodyPose; +- private Rotations leftArmPose; +- private Rotations rightArmPose; +- private Rotations leftLegPose; +- private Rotations rightLegPose; ++ public int disabledSlots; ++ public Rotations headPose; ++ public Rotations bodyPose; ++ public Rotations leftArmPose; ++ public Rotations rightArmPose; ++ public Rotations leftLegPose; ++ public Rotations rightLegPose; + +- public ArmorStand(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public ArmorStand(EntityType entityType, Level level) { ++ super(entityType, level); + this.handItems = NonNullList.withSize(2, ItemStack.EMPTY); + this.armorItems = NonNullList.withSize(4, ItemStack.EMPTY); + this.headPose = ArmorStand.DEFAULT_HEAD_POSE; +@@ -101,12 +106,18 @@ + this.setMaxUpStep(0.0F); + } + +- public ArmorStand(Level level, double d0, double d1, double d2) { ++ public ArmorStand(Level level, double x, double d1, double y) { + this(EntityType.ARMOR_STAND, level); +- this.setPos(d0, d1, d2); ++ this.setPos(x, d1, y); + } + ++ // CraftBukkit start - SPIGOT-3607, SPIGOT-3637 + @Override ++ public float getBukkitYaw() { ++ return this.getYRot(); ++ } ++ // CraftBukkit end ++ + @Override + public void refreshDimensions() { + double d0 = this.getX(); +@@ -122,13 +133,11 @@ + } + + @Override +- @Override + public boolean isEffectiveAi() { + return super.isEffectiveAi() && this.hasPhysics(); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(ArmorStand.DATA_CLIENT_FLAGS, (byte) 0); +@@ -141,194 +150,191 @@ + } + + @Override +- @Override + public Iterable getHandSlots() { + return this.handItems; + } + + @Override +- @Override + public Iterable getArmorSlots() { + return this.armorItems; + } + + @Override +- @Override +- public ItemStack getItemBySlot(EquipmentSlot equipmentslot) { +- switch (equipmentslot.getType()) { ++ public ItemStack getItemBySlot(net.minecraft.world.entity.EquipmentSlot slot) { ++ switch (slot.getType()) { + case HAND: +- return (ItemStack) this.handItems.get(equipmentslot.getIndex()); ++ return (ItemStack) this.handItems.get(slot.getIndex()); + case ARMOR: +- return (ItemStack) this.armorItems.get(equipmentslot.getIndex()); ++ return (ItemStack) this.armorItems.get(slot.getIndex()); + default: + return ItemStack.EMPTY; + } + } + + @Override ++ public void setItemSlot(net.minecraft.world.entity.EquipmentSlot slot, ItemStack stack) { ++ // CraftBukkit start ++ this.setItemSlot(slot, stack, false); ++ } ++ + @Override +- public void setItemSlot(EquipmentSlot equipmentslot, ItemStack itemstack) { ++ public void setItemSlot(net.minecraft.world.entity.EquipmentSlot enumitemslot, ItemStack itemstack, boolean silent) { ++ // CraftBukkit end + this.verifyEquippedItem(itemstack); +- switch (equipmentslot.getType()) { ++ switch (enumitemslot.getType()) { + case HAND: +- this.onEquipItem(equipmentslot, (ItemStack) this.handItems.set(equipmentslot.getIndex(), itemstack), itemstack); ++ this.onEquipItem(enumitemslot, (ItemStack) this.handItems.set(enumitemslot.getIndex(), itemstack), itemstack, silent); // CraftBukkit + break; + case ARMOR: +- this.onEquipItem(equipmentslot, (ItemStack) this.armorItems.set(equipmentslot.getIndex(), itemstack), itemstack); ++ this.onEquipItem(enumitemslot, (ItemStack) this.armorItems.set(enumitemslot.getIndex(), itemstack), itemstack, silent); // CraftBukkit + } + + } + + @Override +- @Override + public boolean canTakeItem(ItemStack itemstack) { +- EquipmentSlot equipmentslot = Mob.getEquipmentSlotForItem(itemstack); ++ net.minecraft.world.entity.EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(itemstack); + +- return this.getItemBySlot(equipmentslot).isEmpty() && !this.isDisabled(equipmentslot); ++ return this.getItemBySlot(enumitemslot).isEmpty() && !this.isDisabled(enumitemslot); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- ListTag listtag = new ListTag(); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ ListTag nbttaglist = new ListTag(); + +- CompoundTag compoundtag1; ++ CompoundTag nbttagcompound1; + +- for (Iterator iterator = this.armorItems.iterator(); iterator.hasNext(); listtag.add(compoundtag1)) { ++ for (Iterator iterator = this.armorItems.iterator(); iterator.hasNext(); nbttaglist.add(nbttagcompound1)) { + ItemStack itemstack = (ItemStack) iterator.next(); + +- compoundtag1 = new CompoundTag(); ++ nbttagcompound1 = new CompoundTag(); + if (!itemstack.isEmpty()) { +- itemstack.save(compoundtag1); ++ itemstack.save(nbttagcompound1); + } + } + +- compoundtag.put("ArmorItems", listtag); +- ListTag listtag1 = new ListTag(); ++ compound.put("ArmorItems", nbttaglist); ++ ListTag nbttaglist1 = new ListTag(); + +- CompoundTag compoundtag2; ++ CompoundTag nbttagcompound2; + +- for (Iterator iterator1 = this.handItems.iterator(); iterator1.hasNext(); listtag1.add(compoundtag2)) { ++ for (Iterator iterator1 = this.handItems.iterator(); iterator1.hasNext(); nbttaglist1.add(nbttagcompound2)) { + ItemStack itemstack1 = (ItemStack) iterator1.next(); + +- compoundtag2 = new CompoundTag(); ++ nbttagcompound2 = new CompoundTag(); + if (!itemstack1.isEmpty()) { +- itemstack1.save(compoundtag2); ++ itemstack1.save(nbttagcompound2); + } + } + +- compoundtag.put("HandItems", listtag1); +- compoundtag.putBoolean("Invisible", this.isInvisible()); +- compoundtag.putBoolean("Small", this.isSmall()); +- compoundtag.putBoolean("ShowArms", this.isShowArms()); +- compoundtag.putInt("DisabledSlots", this.disabledSlots); +- compoundtag.putBoolean("NoBasePlate", this.isNoBasePlate()); ++ compound.put("HandItems", nbttaglist1); ++ compound.putBoolean("Invisible", this.isInvisible()); ++ compound.putBoolean("Small", this.isSmall()); ++ compound.putBoolean("ShowArms", this.isShowArms()); ++ compound.putInt("DisabledSlots", this.disabledSlots); ++ compound.putBoolean("NoBasePlate", this.isNoBasePlate()); + if (this.isMarker()) { +- compoundtag.putBoolean("Marker", this.isMarker()); ++ compound.putBoolean("Marker", this.isMarker()); + } + +- compoundtag.put("Pose", this.writePose()); ++ compound.put("Pose", this.writePose()); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- ListTag listtag; ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ ListTag nbttaglist; + int i; + +- if (compoundtag.contains("ArmorItems", 9)) { +- listtag = compoundtag.getList("ArmorItems", 10); ++ if (compound.contains("ArmorItems", 9)) { ++ nbttaglist = compound.getList("ArmorItems", 10); + + for (i = 0; i < this.armorItems.size(); ++i) { +- this.armorItems.set(i, ItemStack.of(listtag.getCompound(i))); ++ this.armorItems.set(i, ItemStack.of(nbttaglist.getCompound(i))); + } + } + +- if (compoundtag.contains("HandItems", 9)) { +- listtag = compoundtag.getList("HandItems", 10); ++ if (compound.contains("HandItems", 9)) { ++ nbttaglist = compound.getList("HandItems", 10); + + for (i = 0; i < this.handItems.size(); ++i) { +- this.handItems.set(i, ItemStack.of(listtag.getCompound(i))); ++ this.handItems.set(i, ItemStack.of(nbttaglist.getCompound(i))); + } + } + +- this.setInvisible(compoundtag.getBoolean("Invisible")); +- this.setSmall(compoundtag.getBoolean("Small")); +- this.setShowArms(compoundtag.getBoolean("ShowArms")); +- this.disabledSlots = compoundtag.getInt("DisabledSlots"); +- this.setNoBasePlate(compoundtag.getBoolean("NoBasePlate")); +- this.setMarker(compoundtag.getBoolean("Marker")); ++ this.setInvisible(compound.getBoolean("Invisible")); ++ this.setSmall(compound.getBoolean("Small")); ++ this.setShowArms(compound.getBoolean("ShowArms")); ++ this.disabledSlots = compound.getInt("DisabledSlots"); ++ this.setNoBasePlate(compound.getBoolean("NoBasePlate")); ++ this.setMarker(compound.getBoolean("Marker")); + this.noPhysics = !this.hasPhysics(); +- CompoundTag compoundtag1 = compoundtag.getCompound("Pose"); ++ CompoundTag nbttagcompound1 = compound.getCompound("Pose"); + +- this.readPose(compoundtag1); ++ this.readPose(nbttagcompound1); + } + +- private void readPose(CompoundTag compoundtag) { +- ListTag listtag = compoundtag.getList("Head", 5); ++ private void readPose(CompoundTag compound) { ++ ListTag nbttaglist = compound.getList("Head", 5); + +- this.setHeadPose(listtag.isEmpty() ? ArmorStand.DEFAULT_HEAD_POSE : new Rotations(listtag)); +- ListTag listtag1 = compoundtag.getList("Body", 5); ++ this.setHeadPose(nbttaglist.isEmpty() ? ArmorStand.DEFAULT_HEAD_POSE : new Rotations(nbttaglist)); ++ ListTag nbttaglist1 = compound.getList("Body", 5); + +- this.setBodyPose(listtag1.isEmpty() ? ArmorStand.DEFAULT_BODY_POSE : new Rotations(listtag1)); +- ListTag listtag2 = compoundtag.getList("LeftArm", 5); ++ this.setBodyPose(nbttaglist1.isEmpty() ? ArmorStand.DEFAULT_BODY_POSE : new Rotations(nbttaglist1)); ++ ListTag nbttaglist2 = compound.getList("LeftArm", 5); + +- this.setLeftArmPose(listtag2.isEmpty() ? ArmorStand.DEFAULT_LEFT_ARM_POSE : new Rotations(listtag2)); +- ListTag listtag3 = compoundtag.getList("RightArm", 5); ++ this.setLeftArmPose(nbttaglist2.isEmpty() ? ArmorStand.DEFAULT_LEFT_ARM_POSE : new Rotations(nbttaglist2)); ++ ListTag nbttaglist3 = compound.getList("RightArm", 5); + +- this.setRightArmPose(listtag3.isEmpty() ? ArmorStand.DEFAULT_RIGHT_ARM_POSE : new Rotations(listtag3)); +- ListTag listtag4 = compoundtag.getList("LeftLeg", 5); ++ this.setRightArmPose(nbttaglist3.isEmpty() ? ArmorStand.DEFAULT_RIGHT_ARM_POSE : new Rotations(nbttaglist3)); ++ ListTag nbttaglist4 = compound.getList("LeftLeg", 5); + +- this.setLeftLegPose(listtag4.isEmpty() ? ArmorStand.DEFAULT_LEFT_LEG_POSE : new Rotations(listtag4)); +- ListTag listtag5 = compoundtag.getList("RightLeg", 5); ++ this.setLeftLegPose(nbttaglist4.isEmpty() ? ArmorStand.DEFAULT_LEFT_LEG_POSE : new Rotations(nbttaglist4)); ++ ListTag nbttaglist5 = compound.getList("RightLeg", 5); + +- this.setRightLegPose(listtag5.isEmpty() ? ArmorStand.DEFAULT_RIGHT_LEG_POSE : new Rotations(listtag5)); ++ this.setRightLegPose(nbttaglist5.isEmpty() ? ArmorStand.DEFAULT_RIGHT_LEG_POSE : new Rotations(nbttaglist5)); + } + + private CompoundTag writePose() { +- CompoundTag compoundtag = new CompoundTag(); ++ CompoundTag nbttagcompound = new CompoundTag(); + + if (!ArmorStand.DEFAULT_HEAD_POSE.equals(this.headPose)) { +- compoundtag.put("Head", this.headPose.save()); ++ nbttagcompound.put("Head", this.headPose.save()); + } + + if (!ArmorStand.DEFAULT_BODY_POSE.equals(this.bodyPose)) { +- compoundtag.put("Body", this.bodyPose.save()); ++ nbttagcompound.put("Body", this.bodyPose.save()); + } + + if (!ArmorStand.DEFAULT_LEFT_ARM_POSE.equals(this.leftArmPose)) { +- compoundtag.put("LeftArm", this.leftArmPose.save()); ++ nbttagcompound.put("LeftArm", this.leftArmPose.save()); + } + + if (!ArmorStand.DEFAULT_RIGHT_ARM_POSE.equals(this.rightArmPose)) { +- compoundtag.put("RightArm", this.rightArmPose.save()); ++ nbttagcompound.put("RightArm", this.rightArmPose.save()); + } + + if (!ArmorStand.DEFAULT_LEFT_LEG_POSE.equals(this.leftLegPose)) { +- compoundtag.put("LeftLeg", this.leftLegPose.save()); ++ nbttagcompound.put("LeftLeg", this.leftLegPose.save()); + } + + if (!ArmorStand.DEFAULT_RIGHT_LEG_POSE.equals(this.rightLegPose)) { +- compoundtag.put("RightLeg", this.rightLegPose.save()); ++ nbttagcompound.put("RightLeg", this.rightLegPose.save()); + } + +- return compoundtag; ++ return nbttagcompound; + } + + @Override +- @Override + public boolean isPushable() { + return false; + } + + @Override +- @Override + protected void doPush(Entity entity) {} + + @Override +- @Override + protected void pushEntities() { + List list = this.level().getEntities((Entity) this, this.getBoundingBox(), ArmorStand.RIDABLE_MINECARTS); + Iterator iterator = list.iterator(); +@@ -344,9 +350,8 @@ + } + + @Override +- @Override +- public InteractionResult interactAt(Player player, Vec3 vec3, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult interactAt(net.minecraft.world.entity.player.Player player, Vec3 vec, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (!this.isMarker() && !itemstack.is(Items.NAME_TAG)) { + if (player.isSpectator()) { +@@ -354,25 +359,25 @@ + } else if (player.level().isClientSide) { + return InteractionResult.CONSUME; + } else { +- EquipmentSlot equipmentslot = Mob.getEquipmentSlotForItem(itemstack); ++ net.minecraft.world.entity.EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(itemstack); + + if (itemstack.isEmpty()) { +- EquipmentSlot equipmentslot1 = this.getClickedSlot(vec3); +- EquipmentSlot equipmentslot2 = this.isDisabled(equipmentslot1) ? equipmentslot : equipmentslot1; ++ net.minecraft.world.entity.EquipmentSlot enumitemslot1 = this.getClickedSlot(vec); ++ net.minecraft.world.entity.EquipmentSlot enumitemslot2 = this.isDisabled(enumitemslot1) ? enumitemslot : enumitemslot1; + +- if (this.hasItemInSlot(equipmentslot2) && this.swapItem(player, equipmentslot2, itemstack, interactionhand)) { ++ if (this.hasItemInSlot(enumitemslot2) && this.swapItem(player, enumitemslot2, itemstack, hand)) { + return InteractionResult.SUCCESS; + } + } else { +- if (this.isDisabled(equipmentslot)) { ++ if (this.isDisabled(enumitemslot)) { + return InteractionResult.FAIL; + } + +- if (equipmentslot.getType() == EquipmentSlot.Type.HAND && !this.isShowArms()) { ++ if (enumitemslot.getType() == net.minecraft.world.entity.EquipmentSlot.Function.HAND && !this.isShowArms()) { + return InteractionResult.FAIL; + } + +- if (this.swapItem(player, equipmentslot, itemstack, interactionhand)) { ++ if (this.swapItem(player, enumitemslot, itemstack, hand)) { + return InteractionResult.SUCCESS; + } + } +@@ -384,96 +389,124 @@ + } + } + +- private EquipmentSlot getClickedSlot(Vec3 vec3) { +- EquipmentSlot equipmentslot = EquipmentSlot.MAINHAND; ++ private net.minecraft.world.entity.EquipmentSlot getClickedSlot(Vec3 vector) { ++ net.minecraft.world.entity.EquipmentSlot enumitemslot = net.minecraft.world.entity.EquipmentSlot.MAINHAND; + boolean flag = this.isSmall(); +- double d0 = flag ? vec3.y * 2.0D : vec3.y; +- EquipmentSlot equipmentslot1 = EquipmentSlot.FEET; ++ double d0 = flag ? vector.y * 2.0D : vector.y; ++ net.minecraft.world.entity.EquipmentSlot enumitemslot1 = net.minecraft.world.entity.EquipmentSlot.FEET; + +- if (d0 >= 0.1D && d0 < 0.1D + (flag ? 0.8D : 0.45D) && this.hasItemInSlot(equipmentslot1)) { +- equipmentslot = EquipmentSlot.FEET; +- } else if (d0 >= 0.9D + (flag ? 0.3D : 0.0D) && d0 < 0.9D + (flag ? 1.0D : 0.7D) && this.hasItemInSlot(EquipmentSlot.CHEST)) { +- equipmentslot = EquipmentSlot.CHEST; +- } else if (d0 >= 0.4D && d0 < 0.4D + (flag ? 1.0D : 0.8D) && this.hasItemInSlot(EquipmentSlot.LEGS)) { +- equipmentslot = EquipmentSlot.LEGS; +- } else if (d0 >= 1.6D && this.hasItemInSlot(EquipmentSlot.HEAD)) { +- equipmentslot = EquipmentSlot.HEAD; +- } else if (!this.hasItemInSlot(EquipmentSlot.MAINHAND) && this.hasItemInSlot(EquipmentSlot.OFFHAND)) { +- equipmentslot = EquipmentSlot.OFFHAND; ++ if (d0 >= 0.1D && d0 < 0.1D + (flag ? 0.8D : 0.45D) && this.hasItemInSlot(enumitemslot1)) { ++ enumitemslot = net.minecraft.world.entity.EquipmentSlot.FEET; ++ } else if (d0 >= 0.9D + (flag ? 0.3D : 0.0D) && d0 < 0.9D + (flag ? 1.0D : 0.7D) && this.hasItemInSlot(net.minecraft.world.entity.EquipmentSlot.CHEST)) { ++ enumitemslot = net.minecraft.world.entity.EquipmentSlot.CHEST; ++ } else if (d0 >= 0.4D && d0 < 0.4D + (flag ? 1.0D : 0.8D) && this.hasItemInSlot(net.minecraft.world.entity.EquipmentSlot.LEGS)) { ++ enumitemslot = net.minecraft.world.entity.EquipmentSlot.LEGS; ++ } else if (d0 >= 1.6D && this.hasItemInSlot(net.minecraft.world.entity.EquipmentSlot.HEAD)) { ++ enumitemslot = net.minecraft.world.entity.EquipmentSlot.HEAD; ++ } else if (!this.hasItemInSlot(net.minecraft.world.entity.EquipmentSlot.MAINHAND) && this.hasItemInSlot(net.minecraft.world.entity.EquipmentSlot.OFFHAND)) { ++ enumitemslot = net.minecraft.world.entity.EquipmentSlot.OFFHAND; + } + +- return equipmentslot; ++ return enumitemslot; + } + +- private boolean isDisabled(EquipmentSlot equipmentslot) { +- return (this.disabledSlots & 1 << equipmentslot.getFilterFlag()) != 0 || equipmentslot.getType() == EquipmentSlot.Type.HAND && !this.isShowArms(); ++ private boolean isDisabled(net.minecraft.world.entity.EquipmentSlot slot) { ++ return (this.disabledSlots & 1 << slot.getFilterFlag()) != 0 || slot.getType() == net.minecraft.world.entity.EquipmentSlot.Function.HAND && !this.isShowArms(); + } + +- private boolean swapItem(Player player, EquipmentSlot equipmentslot, ItemStack itemstack, InteractionHand interactionhand) { +- ItemStack itemstack1 = this.getItemBySlot(equipmentslot); ++ private boolean swapItem(net.minecraft.world.entity.player.Player player, net.minecraft.world.entity.EquipmentSlot slot, ItemStack stack, EnumHand hand) { ++ ItemStack itemstack1 = this.getItemBySlot(slot); + +- if (!itemstack1.isEmpty() && (this.disabledSlots & 1 << equipmentslot.getFilterFlag() + 8) != 0) { ++ if (!itemstack1.isEmpty() && (this.disabledSlots & 1 << slot.getFilterFlag() + 8) != 0) { + return false; +- } else if (itemstack1.isEmpty() && (this.disabledSlots & 1 << equipmentslot.getFilterFlag() + 16) != 0) { ++ } else if (itemstack1.isEmpty() && (this.disabledSlots & 1 << slot.getFilterFlag() + 16) != 0) { + return false; +- } else if (player.getAbilities().instabuild && itemstack1.isEmpty() && !itemstack.isEmpty()) { +- this.setItemSlot(equipmentslot, itemstack.copyWithCount(1)); ++ // CraftBukkit start ++ } else { ++ org.bukkit.inventory.ItemStack armorStandItem = CraftItemStack.asCraftMirror(itemstack1); ++ org.bukkit.inventory.ItemStack playerHeldItem = CraftItemStack.asCraftMirror(stack); ++ ++ Player player1 = (Player) player.getBukkitEntity(); ++ org.bukkit.entity.ArmorStand self = (org.bukkit.entity.ArmorStand) this.getBukkitEntity(); ++ ++ EquipmentSlot slot1 = CraftEquipmentSlot.getSlot(slot); ++ EquipmentSlot hand = CraftEquipmentSlot.getHand(hand); ++ PlayerArmorStandManipulateEvent armorStandManipulateEvent = new PlayerArmorStandManipulateEvent(player1, self, playerHeldItem, armorStandItem, slot1, hand); ++ this.level().getCraftServer().getPluginManager().callEvent(armorStandManipulateEvent); ++ ++ if (armorStandManipulateEvent.isCancelled()) { ++ return true; ++ } ++ ++ if (player.getAbilities().instabuild && itemstack1.isEmpty() && !stack.isEmpty()) { ++ // CraftBukkit end ++ this.setItemSlot(slot, stack.copyWithCount(1)); + return true; +- } else if (!itemstack.isEmpty() && itemstack.getCount() > 1) { ++ } else if (!stack.isEmpty() && stack.getCount() > 1) { + if (!itemstack1.isEmpty()) { + return false; + } else { +- this.setItemSlot(equipmentslot, itemstack.split(1)); ++ this.setItemSlot(slot, stack.split(1)); + return true; + } + } else { +- this.setItemSlot(equipmentslot, itemstack); +- player.setItemInHand(interactionhand, itemstack1); ++ this.setItemSlot(slot, stack); ++ player.setItemInHand(hand, itemstack1); + return true; + } ++ } // CraftBukkit + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { ++ public boolean hurt(DamageSource source, float amount) { + if (!this.level().isClientSide && !this.isRemoved()) { +- if (damagesource.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { ++ if (source.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount)) { ++ return false; ++ } ++ // CraftBukkit end + this.kill(); + return false; +- } else if (!this.isInvulnerableTo(damagesource) && !this.invisible && !this.isMarker()) { +- if (damagesource.is(DamageTypeTags.IS_EXPLOSION)) { +- this.brokenByAnything(damagesource); ++ } else if (!this.isInvulnerableTo(source) && (true || !this.invisible) && !this.isMarker()) { // CraftBukkit ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, true, this.invisible)) { ++ return false; ++ } ++ // CraftBukkit end ++ if (source.is(DamageTypeTags.IS_EXPLOSION)) { ++ this.brokenByAnything(source); + this.kill(); + return false; +- } else if (damagesource.is(DamageTypeTags.IGNITES_ARMOR_STANDS)) { ++ } else if (source.is(DamageTypeTags.IGNITES_ARMOR_STANDS)) { + if (this.isOnFire()) { +- this.causeDamage(damagesource, 0.15F); ++ this.causeDamage(source, 0.15F); + } else { + this.setSecondsOnFire(5); + } + + return false; +- } else if (damagesource.is(DamageTypeTags.BURNS_ARMOR_STANDS) && this.getHealth() > 0.5F) { +- this.causeDamage(damagesource, 4.0F); ++ } else if (source.is(DamageTypeTags.BURNS_ARMOR_STANDS) && this.getHealth() > 0.5F) { ++ this.causeDamage(source, 4.0F); + return false; + } else { +- boolean flag = damagesource.is(DamageTypeTags.CAN_BREAK_ARMOR_STAND); +- boolean flag1 = damagesource.is(DamageTypeTags.ALWAYS_KILLS_ARMOR_STANDS); ++ boolean flag = source.is(DamageTypeTags.CAN_BREAK_ARMOR_STAND); ++ boolean flag1 = source.is(DamageTypeTags.ALWAYS_KILLS_ARMOR_STANDS); + + if (!flag && !flag1) { + return false; + } else { +- Entity entity = damagesource.getEntity(); ++ Entity entity = source.getEntity(); + +- if (entity instanceof Player) { +- Player player = (Player) entity; ++ if (entity instanceof net.minecraft.world.entity.player.Player) { ++ net.minecraft.world.entity.player.Player entityhuman = (net.minecraft.world.entity.player.Player) entity; + +- if (!player.getAbilities().mayBuild) { ++ if (!entityhuman.getAbilities().mayBuild) { + return false; + } + } + +- if (damagesource.isCreativePlayer()) { ++ if (source.isCreativePlayer()) { + this.playBrokenSound(); + this.showBreakingParticles(); + this.kill(); +@@ -483,12 +516,12 @@ + + if (i - this.lastHit > 5L && !flag1) { + this.level().broadcastEntityEvent(this, (byte) 32); +- this.gameEvent(GameEvent.ENTITY_DAMAGE, damagesource.getEntity()); ++ this.gameEvent(GameEvent.ENTITY_DAMAGE, source.getEntity()); + this.lastHit = i; + } else { +- this.brokenByPlayer(damagesource); ++ this.brokenByPlayer(source); + this.showBreakingParticles(); +- this.kill(); ++ this.discard(); // CraftBukkit - SPIGOT-4890: remain as this.discard() since above damagesource method will call death event + } + + return true; +@@ -504,22 +537,20 @@ + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 32) { ++ public void handleEntityEvent(byte id) { ++ if (id == 32) { + if (this.level().isClientSide) { + this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.ARMOR_STAND_HIT, this.getSoundSource(), 0.3F, 1.0F, false); + this.lastHit = this.level().getGameTime(); + } + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } + + @Override +- @Override +- public boolean shouldRenderAtSqrDistance(double d0) { ++ public boolean shouldRenderAtSqrDistance(double distance) { + double d1 = this.getBoundingBox().getSize() * 4.0D; + + if (Double.isNaN(d1) || d1 == 0.0D) { +@@ -527,7 +558,7 @@ + } + + d1 *= 64.0D; +- return d0 < d1 * d1; ++ return distance < d1 * d1; + } + + private void showBreakingParticles() { +@@ -537,34 +568,34 @@ + + } + +- private void causeDamage(DamageSource damagesource, float f) { ++ private void causeDamage(DamageSource damageSource, float amount) { + float f1 = this.getHealth(); + +- f1 -= f; ++ f1 -= amount; + if (f1 <= 0.5F) { +- this.brokenByAnything(damagesource); ++ this.brokenByAnything(damageSource); + this.kill(); + } else { + this.setHealth(f1); +- this.gameEvent(GameEvent.ENTITY_DAMAGE, damagesource.getEntity()); ++ this.gameEvent(GameEvent.ENTITY_DAMAGE, damageSource.getEntity()); + } + + } + +- private void brokenByPlayer(DamageSource damagesource) { ++ private void brokenByPlayer(DamageSource damageSource) { + ItemStack itemstack = new ItemStack(Items.ARMOR_STAND); + + if (this.hasCustomName()) { + itemstack.setHoverName(this.getCustomName()); + } + +- Block.popResource(this.level(), this.blockPosition(), itemstack); +- this.brokenByAnything(damagesource); ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops ++ this.brokenByAnything(damageSource); + } + +- private void brokenByAnything(DamageSource damagesource) { ++ private void brokenByAnything(DamageSource damageSource) { + this.playBrokenSound(); +- this.dropAllDeathLoot(damagesource); ++ // this.dropAllDeathLoot(damagesource); // CraftBukkit - moved down + + ItemStack itemstack; + int i; +@@ -572,7 +603,7 @@ + for (i = 0; i < this.handItems.size(); ++i) { + itemstack = (ItemStack) this.handItems.get(i); + if (!itemstack.isEmpty()) { +- Block.popResource(this.level(), this.blockPosition().above(), itemstack); ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops + this.handItems.set(i, ItemStack.EMPTY); + } + } +@@ -580,209 +611,205 @@ + for (i = 0; i < this.armorItems.size(); ++i) { + itemstack = (ItemStack) this.armorItems.get(i); + if (!itemstack.isEmpty()) { +- Block.popResource(this.level(), this.blockPosition().above(), itemstack); ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops + this.armorItems.set(i, ItemStack.EMPTY); + } + } ++ this.dropAllDeathLoot(damageSource); // CraftBukkit - moved from above + + } + + private void playBrokenSound() { +- this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.ARMOR_STAND_BREAK, this.getSoundSource(), 1.0F, 1.0F); ++ this.level().playSound((net.minecraft.world.entity.player.Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.ARMOR_STAND_BREAK, this.getSoundSource(), 1.0F, 1.0F); + } + + @Override +- @Override +- protected float tickHeadTurn(float f, float f1) { ++ protected float tickHeadTurn(float yRot, float animStep) { + this.yBodyRotO = this.yRotO; + this.yBodyRot = this.getYRot(); + return 0.0F; + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return entitydimensions.height * (this.isBaby() ? 0.5F : 0.9F); ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { ++ return size.height * (this.isBaby() ? 0.5F : 0.9F); + } + + @Override +- @Override +- public void travel(Vec3 vec3) { ++ public void travel(Vec3 travelVector) { + if (this.hasPhysics()) { +- super.travel(vec3); ++ super.travel(travelVector); + } + } + + @Override +- @Override +- public void setYBodyRot(float f) { +- this.yBodyRotO = this.yRotO = f; +- this.yHeadRotO = this.yHeadRot = f; ++ public void setYBodyRot(float offset) { ++ this.yBodyRotO = this.yRotO = offset; ++ this.yHeadRotO = this.yHeadRot = offset; + } + + @Override +- @Override +- public void setYHeadRot(float f) { +- this.yBodyRotO = this.yRotO = f; +- this.yHeadRotO = this.yHeadRot = f; ++ public void setYHeadRot(float rotation) { ++ this.yBodyRotO = this.yRotO = rotation; ++ this.yHeadRotO = this.yHeadRot = rotation; + } + + @Override +- @Override + public void tick() { + super.tick(); +- Rotations rotations = (Rotations) this.entityData.get(ArmorStand.DATA_HEAD_POSE); ++ Rotations vector3f = (Rotations) this.entityData.get(ArmorStand.DATA_HEAD_POSE); + +- if (!this.headPose.equals(rotations)) { +- this.setHeadPose(rotations); ++ if (!this.headPose.equals(vector3f)) { ++ this.setHeadPose(vector3f); + } + +- Rotations rotations1 = (Rotations) this.entityData.get(ArmorStand.DATA_BODY_POSE); ++ Rotations vector3f1 = (Rotations) this.entityData.get(ArmorStand.DATA_BODY_POSE); + +- if (!this.bodyPose.equals(rotations1)) { +- this.setBodyPose(rotations1); ++ if (!this.bodyPose.equals(vector3f1)) { ++ this.setBodyPose(vector3f1); + } + +- Rotations rotations2 = (Rotations) this.entityData.get(ArmorStand.DATA_LEFT_ARM_POSE); ++ Rotations vector3f2 = (Rotations) this.entityData.get(ArmorStand.DATA_LEFT_ARM_POSE); + +- if (!this.leftArmPose.equals(rotations2)) { +- this.setLeftArmPose(rotations2); ++ if (!this.leftArmPose.equals(vector3f2)) { ++ this.setLeftArmPose(vector3f2); + } + +- Rotations rotations3 = (Rotations) this.entityData.get(ArmorStand.DATA_RIGHT_ARM_POSE); ++ Rotations vector3f3 = (Rotations) this.entityData.get(ArmorStand.DATA_RIGHT_ARM_POSE); + +- if (!this.rightArmPose.equals(rotations3)) { +- this.setRightArmPose(rotations3); ++ if (!this.rightArmPose.equals(vector3f3)) { ++ this.setRightArmPose(vector3f3); + } + +- Rotations rotations4 = (Rotations) this.entityData.get(ArmorStand.DATA_LEFT_LEG_POSE); ++ Rotations vector3f4 = (Rotations) this.entityData.get(ArmorStand.DATA_LEFT_LEG_POSE); + +- if (!this.leftLegPose.equals(rotations4)) { +- this.setLeftLegPose(rotations4); ++ if (!this.leftLegPose.equals(vector3f4)) { ++ this.setLeftLegPose(vector3f4); + } + +- Rotations rotations5 = (Rotations) this.entityData.get(ArmorStand.DATA_RIGHT_LEG_POSE); ++ Rotations vector3f5 = (Rotations) this.entityData.get(ArmorStand.DATA_RIGHT_LEG_POSE); + +- if (!this.rightLegPose.equals(rotations5)) { +- this.setRightLegPose(rotations5); ++ if (!this.rightLegPose.equals(vector3f5)) { ++ this.setRightLegPose(vector3f5); + } + + } + + @Override +- @Override + protected void updateInvisibilityStatus() { + this.setInvisible(this.invisible); + } + + @Override +- @Override +- public void setInvisible(boolean flag) { +- this.invisible = flag; +- super.setInvisible(flag); ++ public void setInvisible(boolean invisible) { ++ this.invisible = invisible; ++ super.setInvisible(invisible); + } + + @Override +- @Override + public boolean isBaby() { + return this.isSmall(); + } + ++ // CraftBukkit start + @Override ++ public boolean shouldDropExperience() { ++ return true; // MC-157395, SPIGOT-5193 even baby (small) armor stands should drop ++ } ++ // CraftBukkit end ++ + @Override + public void kill() { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event + this.remove(Entity.RemovalReason.KILLED); + this.gameEvent(GameEvent.ENTITY_DIE); + } + + @Override +- @Override + public boolean ignoreExplosion(Explosion explosion) { + return this.isInvisible(); + } + + @Override +- @Override +- public PushReaction getPistonPushReaction() { +- return this.isMarker() ? PushReaction.IGNORE : super.getPistonPushReaction(); ++ public EnumPistonReaction getPistonPushReaction() { ++ return this.isMarker() ? EnumPistonReaction.IGNORE : super.getPistonPushReaction(); + } + + @Override +- @Override + public boolean isIgnoringBlockTriggers() { + return this.isMarker(); + } + +- private void setSmall(boolean flag) { +- this.entityData.set(ArmorStand.DATA_CLIENT_FLAGS, this.setBit((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS), 1, flag)); ++ public void setSmall(boolean small) { ++ this.entityData.set(ArmorStand.DATA_CLIENT_FLAGS, this.setBit((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS), 1, small)); + } + + public boolean isSmall() { + return ((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS) & 1) != 0; + } + +- public void setShowArms(boolean flag) { +- this.entityData.set(ArmorStand.DATA_CLIENT_FLAGS, this.setBit((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS), 4, flag)); ++ public void setShowArms(boolean showArms) { ++ this.entityData.set(ArmorStand.DATA_CLIENT_FLAGS, this.setBit((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS), 4, showArms)); + } + + public boolean isShowArms() { + return ((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS) & 4) != 0; + } + +- public void setNoBasePlate(boolean flag) { +- this.entityData.set(ArmorStand.DATA_CLIENT_FLAGS, this.setBit((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS), 8, flag)); ++ public void setNoBasePlate(boolean noBasePlate) { ++ this.entityData.set(ArmorStand.DATA_CLIENT_FLAGS, this.setBit((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS), 8, noBasePlate)); + } + + public boolean isNoBasePlate() { + return ((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS) & 8) != 0; + } + +- private void setMarker(boolean flag) { +- this.entityData.set(ArmorStand.DATA_CLIENT_FLAGS, this.setBit((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS), 16, flag)); ++ public void setMarker(boolean marker) { ++ this.entityData.set(ArmorStand.DATA_CLIENT_FLAGS, this.setBit((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS), 16, marker)); + } + + public boolean isMarker() { + return ((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS) & 16) != 0; + } + +- private byte setBit(byte b0, int i, boolean flag) { +- if (flag) { +- b0 = (byte) (b0 | i); ++ private byte setBit(byte oldBit, int offset, boolean value) { ++ if (value) { ++ oldBit = (byte) (oldBit | offset); + } else { +- b0 = (byte) (b0 & ~i); ++ oldBit = (byte) (oldBit & ~offset); + } + +- return b0; ++ return oldBit; + } + +- public void setHeadPose(Rotations rotations) { +- this.headPose = rotations; +- this.entityData.set(ArmorStand.DATA_HEAD_POSE, rotations); ++ public void setHeadPose(Rotations headPose) { ++ this.headPose = headPose; ++ this.entityData.set(ArmorStand.DATA_HEAD_POSE, headPose); + } + +- public void setBodyPose(Rotations rotations) { +- this.bodyPose = rotations; +- this.entityData.set(ArmorStand.DATA_BODY_POSE, rotations); ++ public void setBodyPose(Rotations bodyPose) { ++ this.bodyPose = bodyPose; ++ this.entityData.set(ArmorStand.DATA_BODY_POSE, bodyPose); + } + +- public void setLeftArmPose(Rotations rotations) { +- this.leftArmPose = rotations; +- this.entityData.set(ArmorStand.DATA_LEFT_ARM_POSE, rotations); ++ public void setLeftArmPose(Rotations leftArmPose) { ++ this.leftArmPose = leftArmPose; ++ this.entityData.set(ArmorStand.DATA_LEFT_ARM_POSE, leftArmPose); + } + +- public void setRightArmPose(Rotations rotations) { +- this.rightArmPose = rotations; +- this.entityData.set(ArmorStand.DATA_RIGHT_ARM_POSE, rotations); ++ public void setRightArmPose(Rotations rightArmPose) { ++ this.rightArmPose = rightArmPose; ++ this.entityData.set(ArmorStand.DATA_RIGHT_ARM_POSE, rightArmPose); + } + +- public void setLeftLegPose(Rotations rotations) { +- this.leftLegPose = rotations; +- this.entityData.set(ArmorStand.DATA_LEFT_LEG_POSE, rotations); ++ public void setLeftLegPose(Rotations leftLegPose) { ++ this.leftLegPose = leftLegPose; ++ this.entityData.set(ArmorStand.DATA_LEFT_LEG_POSE, leftLegPose); + } + +- public void setRightLegPose(Rotations rotations) { +- this.rightLegPose = rotations; +- this.entityData.set(ArmorStand.DATA_RIGHT_LEG_POSE, rotations); ++ public void setRightLegPose(Rotations rightLegPose) { ++ this.rightLegPose = rightLegPose; ++ this.entityData.set(ArmorStand.DATA_RIGHT_LEG_POSE, rightLegPose); + } + + public Rotations getHeadPose() { +@@ -810,117 +837,103 @@ + } + + @Override +- @Override + public boolean isPickable() { + return super.isPickable() && !this.isMarker(); + } + + @Override +- @Override + public boolean skipAttackInteraction(Entity entity) { +- return entity instanceof Player && !this.level().mayInteract((Player) entity, this.blockPosition()); ++ return entity instanceof net.minecraft.world.entity.player.Player && !this.level().mayInteract((net.minecraft.world.entity.player.Player) entity, this.blockPosition()); + } + + @Override +- @Override + public HumanoidArm getMainArm() { + return HumanoidArm.RIGHT; + } + + @Override +- @Override +- public LivingEntity.Fallsounds getFallSounds() { +- return new LivingEntity.Fallsounds(SoundEvents.ARMOR_STAND_FALL, SoundEvents.ARMOR_STAND_FALL); ++ public LivingEntity.a getFallSounds() { ++ return new LivingEntity.a(SoundEvents.ARMOR_STAND_FALL, SoundEvents.ARMOR_STAND_FALL); + } + + @Nullable + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.ARMOR_STAND_HIT; + } + + @Nullable + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.ARMOR_STAND_BREAK; + } + + @Override +- @Override +- public void thunderHit(ServerLevel serverlevel, LightningBolt lightningbolt) {} ++ public void thunderHit(ServerLevel level, LightningBolt lightning) {} + + @Override +- @Override + public boolean isAffectedByPotions() { + return false; + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- if (ArmorStand.DATA_CLIENT_FLAGS.equals(entitydataaccessor)) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ if (ArmorStand.DATA_CLIENT_FLAGS.equals(key)) { + this.refreshDimensions(); + this.blocksBuilding = !this.isMarker(); + } + +- super.onSyncedDataUpdated(entitydataaccessor); ++ super.onSyncedDataUpdated(key); + } + + @Override +- @Override + public boolean attackable() { + return false; + } + + @Override +- @Override +- public EntityDimensions getDimensions(Pose pose) { ++ public EntityDimensions getDimensions(EntityPose pose) { + return this.getDimensionsMarker(this.isMarker()); + } + +- private EntityDimensions getDimensionsMarker(boolean flag) { +- return flag ? ArmorStand.MARKER_DIMENSIONS : (this.isBaby() ? ArmorStand.BABY_DIMENSIONS : this.getType().getDimensions()); ++ private EntityDimensions getDimensionsMarker(boolean isMarker) { ++ return isMarker ? ArmorStand.MARKER_DIMENSIONS : (this.isBaby() ? ArmorStand.BABY_DIMENSIONS : this.getType().getDimensions()); + } + + @Override +- @Override +- public Vec3 getLightProbePosition(float f) { ++ public Vec3 getLightProbePosition(float partialTicks) { + if (this.isMarker()) { +- AABB aabb = this.getDimensionsMarker(false).makeBoundingBox(this.position()); +- BlockPos blockpos = this.blockPosition(); ++ AABB axisalignedbb = this.getDimensionsMarker(false).makeBoundingBox(this.position()); ++ BlockPos blockposition = this.blockPosition(); + int i = Integer.MIN_VALUE; +- Iterator iterator = BlockPos.betweenClosed(BlockPos.containing(aabb.minX, aabb.minY, aabb.minZ), BlockPos.containing(aabb.maxX, aabb.maxY, aabb.maxZ)).iterator(); ++ Iterator iterator = BlockPos.betweenClosed(BlockPos.containing(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.minZ), BlockPos.containing(axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.maxZ)).iterator(); + + while (iterator.hasNext()) { +- BlockPos blockpos1 = (BlockPos) iterator.next(); +- int j = Math.max(this.level().getBrightness(LightLayer.BLOCK, blockpos1), this.level().getBrightness(LightLayer.SKY, blockpos1)); ++ BlockPos blockposition1 = (BlockPos) iterator.next(); ++ int j = Math.max(this.level().getBrightness(EnumSkyBlock.BLOCK, blockposition1), this.level().getBrightness(EnumSkyBlock.SKY, blockposition1)); + + if (j == 15) { +- return Vec3.atCenterOf(blockpos1); ++ return Vec3.atCenterOf(blockposition1); + } + + if (j > i) { + i = j; +- blockpos = blockpos1.immutable(); ++ blockposition = blockposition1.immutable(); + } + } + +- return Vec3.atCenterOf(blockpos); ++ return Vec3.atCenterOf(blockposition); + } else { +- return super.getLightProbePosition(f); ++ return super.getLightProbePosition(partialTicks); + } + } + + @Override +- @Override + public ItemStack getPickResult() { + return new ItemStack(Items.ARMOR_STAND); + } + + @Override +- @Override + public boolean canBeSeenByAnyone() { + return !this.isInvisible() && !this.isMarker(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/decoration/HangingEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/decoration/HangingEntity.java.patch new file mode 100644 index 0000000000..481dcb7081 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/decoration/HangingEntity.java.patch @@ -0,0 +1,420 @@ +--- a/net/minecraft/world/entity/decoration/HangingEntity.java ++++ b/net/minecraft/world/entity/decoration/HangingEntity.java +@@ -3,16 +3,11 @@ + import com.mojang.logging.LogUtils; + import java.util.function.Predicate; + import javax.annotation.Nullable; +-import net.minecraft.core.BlockPos; +-import net.minecraft.core.Direction; +-import net.minecraft.nbt.CompoundTag; +-import net.minecraft.server.level.ServerLevel; +-import net.minecraft.util.Mth; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.LightningBolt; +-import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; +@@ -20,11 +15,22 @@ + import net.minecraft.world.level.block.DiodeBlock; + import net.minecraft.world.level.block.Mirror; + import net.minecraft.world.level.block.Rotation; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import org.apache.commons.lang3.Validate; + import org.slf4j.Logger; ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.Direction; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.server.level.ServerLevel; ++// CraftBukkit start ++import net.minecraft.tags.DamageTypeTags; ++import net.minecraft.util.Mth; ++import org.bukkit.entity.Hanging; ++import org.bukkit.event.hanging.HangingBreakByEntityEvent; ++import org.bukkit.event.hanging.HangingBreakEvent; ++// CraftBukkit end + + public abstract class HangingEntity extends Entity { + +@@ -33,27 +39,26 @@ + return entity instanceof HangingEntity; + }; + private int checkInterval; +- protected BlockPos pos; ++ public BlockPos pos; + protected Direction direction; + +- protected HangingEntity(EntityType entitytype, Level level) { +- super(entitytype, level); ++ protected HangingEntity(EntityType entityType, Level level) { ++ super(entityType, level); + this.direction = Direction.SOUTH; + } + +- protected HangingEntity(EntityType entitytype, Level level, BlockPos blockpos) { +- this(entitytype, level); +- this.pos = blockpos; ++ protected HangingEntity(EntityType entityType, Level level, BlockPos pos) { ++ this(entityType, level); ++ this.pos = pos; + } + + @Override +- @Override + protected void defineSynchedData() {} + +- protected void setDirection(Direction direction) { +- Validate.notNull(direction); +- Validate.isTrue(direction.getAxis().isHorizontal()); +- this.direction = direction; ++ public void setDirection(Direction facingDirection) { ++ Validate.notNull(facingDirection); ++ Validate.isTrue(facingDirection.getAxis().isHorizontal()); ++ this.direction = facingDirection; + this.setYRot((float) (this.direction.get2DDataValue() * 90)); + this.yRotO = this.getYRot(); + this.recalculateBoundingBox(); +@@ -61,26 +66,37 @@ + + protected void recalculateBoundingBox() { + if (this.direction != null) { +- double d0 = (double) this.pos.getX() + 0.5D; +- double d1 = (double) this.pos.getY() + 0.5D; +- double d2 = (double) this.pos.getZ() + 0.5D; ++ // CraftBukkit start code moved in to calculateBoundingBox ++ this.setBoundingBox(calculateBoundingBox(this, this.pos, this.direction, this.getWidth(), this.getHeight())); ++ // CraftBukkit end ++ } ++ } ++ ++ // CraftBukkit start - break out BB calc into own method ++ public static AABB calculateBoundingBox(@Nullable Entity entity, BlockPos blockPosition, Direction direction, int width, int height) { ++ { ++ double d0 = (double) blockPosition.getX() + 0.5D; ++ double d1 = (double) blockPosition.getY() + 0.5D; ++ double d2 = (double) blockPosition.getZ() + 0.5D; + double d3 = 0.46875D; +- double d4 = this.offs(this.getWidth()); +- double d5 = this.offs(this.getHeight()); ++ double d4 = offs(width); ++ double d5 = offs(height); + +- d0 -= (double) this.direction.getStepX() * 0.46875D; +- d2 -= (double) this.direction.getStepZ() * 0.46875D; ++ d0 -= (double) direction.getStepX() * 0.46875D; ++ d2 -= (double) direction.getStepZ() * 0.46875D; + d1 += d5; +- Direction direction = this.direction.getCounterClockWise(); ++ Direction enumdirection = direction.getCounterClockWise(); + +- d0 += d4 * (double) direction.getStepX(); +- d2 += d4 * (double) direction.getStepZ(); +- this.setPosRaw(d0, d1, d2); +- double d6 = (double) this.getWidth(); +- double d7 = (double) this.getHeight(); +- double d8 = (double) this.getWidth(); ++ d0 += d4 * (double) enumdirection.getStepX(); ++ d2 += d4 * (double) enumdirection.getStepZ(); ++ if (entity != null) { ++ entity.setPosRaw(d0, d1, d2); ++ } ++ double d6 = (double) width; ++ double d7 = (double) height; ++ double d8 = (double) width; + +- if (this.direction.getAxis() == Direction.Axis.Z) { ++ if (direction.getAxis() == Direction.Axis.Z) { + d8 = 1.0D; + } else { + d6 = 1.0D; +@@ -89,22 +105,40 @@ + d6 /= 32.0D; + d7 /= 32.0D; + d8 /= 32.0D; +- this.setBoundingBox(new AABB(d0 - d6, d1 - d7, d2 - d8, d0 + d6, d1 + d7, d2 + d8)); ++ return new AABB(d0 - d6, d1 - d7, d2 - d8, d0 + d6, d1 + d7, d2 + d8); + } + } ++ // CraftBukkit end + +- private double offs(int i) { ++ private static double offs(int i) { // CraftBukkit - static + return i % 32 == 0 ? 0.5D : 0.0D; + } + + @Override +- @Override + public void tick() { + if (!this.level().isClientSide) { + this.checkBelowWorld(); + if (this.checkInterval++ == 100) { + this.checkInterval = 0; + if (!this.isRemoved() && !this.survives()) { ++ // CraftBukkit start - fire break events ++ IBlockData material = this.level().getBlockState(this.blockPosition()); ++ HangingBreakEvent.RemoveCause cause; ++ ++ if (!material.isAir()) { ++ // TODO: This feels insufficient to catch 100% of suffocation cases ++ cause = HangingBreakEvent.RemoveCause.OBSTRUCTION; ++ } else { ++ cause = HangingBreakEvent.RemoveCause.PHYSICS; ++ } ++ ++ HangingBreakEvent event = new HangingBreakEvent((Hanging) this.getBukkitEntity(), cause); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (this.isRemoved() || event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.discard(); + this.dropItem((Entity) null); + } +@@ -119,19 +153,19 @@ + } else { + int i = Math.max(1, this.getWidth() / 16); + int j = Math.max(1, this.getHeight() / 16); +- BlockPos blockpos = this.pos.relative(this.direction.getOpposite()); +- Direction direction = this.direction.getCounterClockWise(); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ BlockPos blockposition = this.pos.relative(this.direction.getOpposite()); ++ Direction enumdirection = this.direction.getCounterClockWise(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + + for (int k = 0; k < i; ++k) { + for (int l = 0; l < j; ++l) { + int i1 = (i - 1) / -2; + int j1 = (j - 1) / -2; + +- blockpos_mutableblockpos.set(blockpos).move(direction, k + i1).move(Direction.UP, l + j1); +- BlockState blockstate = this.level().getBlockState(blockpos_mutableblockpos); ++ blockposition_mutableblockposition.set(blockposition).move(enumdirection, k + i1).move(Direction.UP, l + j1); ++ IBlockData iblockdata = this.level().getBlockState(blockposition_mutableblockposition); + +- if (!blockstate.isSolid() && !DiodeBlock.isDiode(blockstate)) { ++ if (!iblockdata.isSolid() && !DiodeBlock.isDiode(iblockdata)) { + return false; + } + } +@@ -142,39 +176,51 @@ + } + + @Override +- @Override + public boolean isPickable() { + return true; + } + + @Override +- @Override + public boolean skipAttackInteraction(Entity entity) { + if (entity instanceof Player) { +- Player player = (Player) entity; ++ Player entityhuman = (Player) entity; + +- return !this.level().mayInteract(player, this.pos) ? true : this.hurt(this.damageSources().playerAttack(player), 0.0F); ++ return !this.level().mayInteract(entityhuman, this.pos) ? true : this.hurt(this.damageSources().playerAttack(entityhuman), 0.0F); + } else { + return false; + } + } + + @Override +- @Override + public Direction getDirection() { + return this.direction; + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- if (this.isInvulnerableTo(damagesource)) { ++ public boolean hurt(DamageSource source, float amount) { ++ if (this.isInvulnerableTo(source)) { + return false; + } else { + if (!this.isRemoved() && !this.level().isClientSide) { ++ // CraftBukkit start - fire break events ++ Entity damager = (source.isIndirect()) ? source.getEntity() : source.getDirectEntity(); ++ HangingBreakEvent event; ++ if (damager != null) { ++ event = new HangingBreakByEntityEvent((Hanging) this.getBukkitEntity(), damager.getBukkitEntity(), source.is(DamageTypeTags.IS_EXPLOSION) ? HangingBreakEvent.RemoveCause.EXPLOSION : HangingBreakEvent.RemoveCause.ENTITY); ++ } else { ++ event = new HangingBreakEvent((Hanging) this.getBukkitEntity(), source.is(DamageTypeTags.IS_EXPLOSION) ? HangingBreakEvent.RemoveCause.EXPLOSION : HangingBreakEvent.RemoveCause.DEFAULT); ++ } ++ ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (this.isRemoved() || event.isCancelled()) { ++ return true; ++ } ++ // CraftBukkit end ++ + this.kill(); + this.markHurt(); +- this.dropItem(damagesource.getEntity()); ++ this.dropItem(source.getEntity()); + } + + return true; +@@ -182,9 +228,20 @@ + } + + @Override +- @Override +- public void move(MoverType movertype, Vec3 vec3) { +- if (!this.level().isClientSide && !this.isRemoved() && vec3.lengthSqr() > 0.0D) { ++ public void move(EnumMoveType type, Vec3 pos) { ++ if (!this.level().isClientSide && !this.isRemoved() && pos.lengthSqr() > 0.0D) { ++ if (this.isRemoved()) return; // CraftBukkit ++ ++ // CraftBukkit start - fire break events ++ // TODO - Does this need its own cause? Seems to only be triggered by pistons ++ HangingBreakEvent event = new HangingBreakEvent((Hanging) this.getBukkitEntity(), HangingBreakEvent.RemoveCause.PHYSICS); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (this.isRemoved() || event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ + this.kill(); + this.dropItem((Entity) null); + } +@@ -192,34 +249,40 @@ + } + + @Override +- @Override +- public void push(double d0, double d1, double d2) { +- if (!this.level().isClientSide && !this.isRemoved() && d0 * d0 + d1 * d1 + d2 * d2 > 0.0D) { ++ public void push(double x, double d1, double y) { ++ if (false && !this.level().isClientSide && !this.isRemoved() && x * x + d1 * d1 + y * y > 0.0D) { // CraftBukkit - not needed + this.kill(); + this.dropItem((Entity) null); + } + + } + ++ // CraftBukkit start - selectively save tile position + @Override ++ public void addAdditionalSaveData(CompoundTag nbttagcompound, boolean includeAll) { ++ if (includeAll) { ++ addAdditionalSaveData(nbttagcompound); ++ } ++ } ++ // CraftBukkit end ++ + @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- BlockPos blockpos = this.getPos(); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ BlockPos blockposition = this.getPos(); + +- compoundtag.putInt("TileX", blockpos.getX()); +- compoundtag.putInt("TileY", blockpos.getY()); +- compoundtag.putInt("TileZ", blockpos.getZ()); ++ compound.putInt("TileX", blockposition.getX()); ++ compound.putInt("TileY", blockposition.getY()); ++ compound.putInt("TileZ", blockposition.getZ()); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- BlockPos blockpos = new BlockPos(compoundtag.getInt("TileX"), compoundtag.getInt("TileY"), compoundtag.getInt("TileZ")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ BlockPos blockposition = new BlockPos(compound.getInt("TileX"), compound.getInt("TileY"), compound.getInt("TileZ")); + +- if (!blockpos.closerThan(this.blockPosition(), 16.0D)) { +- HangingEntity.LOGGER.error("Hanging entity at invalid position: {}", blockpos); ++ if (!blockposition.closerThan(this.blockPosition(), 16.0D)) { ++ HangingEntity.LOGGER.error("Hanging entity at invalid position: {}", blockposition); + } else { +- this.pos = blockpos; ++ this.pos = blockposition; + } + } + +@@ -232,25 +295,22 @@ + public abstract void playPlacementSound(); + + @Override +- @Override +- public ItemEntity spawnAtLocation(ItemStack itemstack, float f) { +- ItemEntity itementity = new ItemEntity(this.level(), this.getX() + (double) ((float) this.direction.getStepX() * 0.15F), this.getY() + (double) f, this.getZ() + (double) ((float) this.direction.getStepZ() * 0.15F), itemstack); ++ public ItemEntity spawnAtLocation(ItemStack stack, float offsetY) { ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX() + (double) ((float) this.direction.getStepX() * 0.15F), this.getY() + (double) offsetY, this.getZ() + (double) ((float) this.direction.getStepZ() * 0.15F), stack); + +- itementity.setDefaultPickUpDelay(); +- this.level().addFreshEntity(itementity); +- return itementity; ++ entityitem.setDefaultPickUpDelay(); ++ this.level().addFreshEntity(entityitem); ++ return entityitem; + } + + @Override +- @Override + protected boolean repositionEntityAfterLoad() { + return false; + } + + @Override +- @Override +- public void setPos(double d0, double d1, double d2) { +- this.pos = BlockPos.containing(d0, d1, d2); ++ public void setPos(double x, double d1, double y) { ++ this.pos = BlockPos.containing(x, d1, y); + this.recalculateBoundingBox(); + this.hasImpulse = true; + } +@@ -260,10 +320,9 @@ + } + + @Override +- @Override +- public float rotate(Rotation rotation) { ++ public float rotate(Rotation transformRotation) { + if (this.direction.getAxis() != Direction.Axis.Y) { +- switch (rotation) { ++ switch (transformRotation) { + case CLOCKWISE_180: + this.direction = this.direction.getOpposite(); + break; +@@ -277,7 +336,7 @@ + + float f = Mth.wrapDegrees(this.getYRot()); + +- switch (rotation) { ++ switch (transformRotation) { + case CLOCKWISE_180: + return f + 180.0F; + case COUNTERCLOCKWISE_90: +@@ -290,16 +349,13 @@ + } + + @Override +- @Override +- public float mirror(Mirror mirror) { +- return this.rotate(mirror.getRotation(this.direction)); ++ public float mirror(Mirror transformMirror) { ++ return this.rotate(transformMirror.getRotation(this.direction)); + } + + @Override +- @Override +- public void thunderHit(ServerLevel serverlevel, LightningBolt lightningbolt) {} ++ public void thunderHit(ServerLevel level, LightningBolt lightning) {} + + @Override +- @Override + public void refreshDimensions() {} + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/decoration/ItemFrame.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/decoration/ItemFrame.java.patch new file mode 100644 index 0000000000..d7ff28b655 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/decoration/ItemFrame.java.patch @@ -0,0 +1,544 @@ +--- a/net/minecraft/world/entity/decoration/ItemFrame.java ++++ b/net/minecraft/world/entity/decoration/ItemFrame.java +@@ -16,14 +16,14 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.tags.DamageTypeTags; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.SlotAccess; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; +@@ -33,7 +33,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.DiodeBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.saveddata.maps.MapItemSavedData; + import net.minecraft.world.phys.AABB; +@@ -44,50 +44,47 @@ + public class ItemFrame extends HangingEntity { + + private static final Logger LOGGER = LogUtils.getLogger(); +- private static final EntityDataAccessor DATA_ITEM = SynchedEntityData.defineId(ItemFrame.class, EntityDataSerializers.ITEM_STACK); +- private static final EntityDataAccessor DATA_ROTATION = SynchedEntityData.defineId(ItemFrame.class, EntityDataSerializers.INT); ++ public static final EntityDataAccessor DATA_ITEM = SynchedEntityData.defineId(ItemFrame.class, EntityDataSerializers.ITEM_STACK); ++ public static final EntityDataAccessor DATA_ROTATION = SynchedEntityData.defineId(ItemFrame.class, EntityDataSerializers.INT); + public static final int NUM_ROTATIONS = 8; +- private float dropChance; +- private boolean fixed; ++ public float dropChance; ++ public boolean fixed; + +- public ItemFrame(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public ItemFrame(EntityType entityType, Level level) { ++ super(entityType, level); + this.dropChance = 1.0F; + } + +- public ItemFrame(Level level, BlockPos blockpos, Direction direction) { +- this(EntityType.ITEM_FRAME, level, blockpos, direction); ++ public ItemFrame(Level level, BlockPos pos, Direction facingDirection) { ++ this(EntityType.ITEM_FRAME, level, pos, facingDirection); + } + +- public ItemFrame(EntityType entitytype, Level level, BlockPos blockpos, Direction direction) { +- super(entitytype, level, blockpos); ++ public ItemFrame(EntityType entityType, Level level, BlockPos pos, Direction direction) { ++ super(entityType, level, pos); + this.dropChance = 1.0F; + this.setDirection(direction); + } + + @Override +- @Override +- protected float getEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.0F; + } + + @Override +- @Override + protected void defineSynchedData() { + this.getEntityData().define(ItemFrame.DATA_ITEM, ItemStack.EMPTY); + this.getEntityData().define(ItemFrame.DATA_ROTATION, 0); + } + + @Override +- @Override +- protected void setDirection(Direction direction) { +- Validate.notNull(direction); +- this.direction = direction; +- if (direction.getAxis().isHorizontal()) { ++ public void setDirection(Direction facingDirection) { ++ Validate.notNull(facingDirection); ++ this.direction = facingDirection; ++ if (facingDirection.getAxis().isHorizontal()) { + this.setXRot(0.0F); + this.setYRot((float) (this.direction.get2DDataValue() * 90)); + } else { +- this.setXRot((float) (-90 * direction.getAxisDirection().getStep())); ++ this.setXRot((float) (-90 * facingDirection.getAxisDirection().getStep())); + this.setYRot(0.0F); + } + +@@ -97,21 +94,31 @@ + } + + @Override +- @Override + protected void recalculateBoundingBox() { + if (this.direction != null) { ++ // CraftBukkit start code moved in to calculateBoundingBox ++ this.setBoundingBox(calculateBoundingBox(this, this.pos, this.direction, this.getWidth(), this.getHeight())); ++ // CraftBukkit end ++ } ++ } ++ ++ // CraftBukkit start - break out BB calc into own method ++ public static AABB calculateBoundingBox(@Nullable Entity entity, BlockPos blockPosition, Direction direction, int width, int height) { ++ { + double d0 = 0.46875D; +- double d1 = (double) this.pos.getX() + 0.5D - (double) this.direction.getStepX() * 0.46875D; +- double d2 = (double) this.pos.getY() + 0.5D - (double) this.direction.getStepY() * 0.46875D; +- double d3 = (double) this.pos.getZ() + 0.5D - (double) this.direction.getStepZ() * 0.46875D; ++ double d1 = (double) blockPosition.getX() + 0.5D - (double) direction.getStepX() * 0.46875D; ++ double d2 = (double) blockPosition.getY() + 0.5D - (double) direction.getStepY() * 0.46875D; ++ double d3 = (double) blockPosition.getZ() + 0.5D - (double) direction.getStepZ() * 0.46875D; + +- this.setPosRaw(d1, d2, d3); +- double d4 = (double) this.getWidth(); +- double d5 = (double) this.getHeight(); +- double d6 = (double) this.getWidth(); +- Direction.Axis direction_axis = this.direction.getAxis(); ++ if (entity != null) { ++ entity.setPosRaw(d1, d2, d3); ++ } ++ double d4 = (double) width; ++ double d5 = (double) height; ++ double d6 = (double) width; ++ Direction.Axis enumdirection_enumaxis = direction.getAxis(); + +- switch (direction_axis) { ++ switch (enumdirection_enumaxis) { + case X: + d4 = 1.0D; + break; +@@ -125,66 +132,67 @@ + d4 /= 32.0D; + d5 /= 32.0D; + d6 /= 32.0D; +- this.setBoundingBox(new AABB(d1 - d4, d2 - d5, d3 - d6, d1 + d4, d2 + d5, d3 + d6)); ++ return new AABB(d1 - d4, d2 - d5, d3 - d6, d1 + d4, d2 + d5, d3 + d6); + } + } ++ // CraftBukkit end + + @Override +- @Override + public boolean survives() { + if (this.fixed) { + return true; + } else if (!this.level().noCollision((Entity) this)) { + return false; + } else { +- BlockState blockstate = this.level().getBlockState(this.pos.relative(this.direction.getOpposite())); ++ IBlockData iblockdata = this.level().getBlockState(this.pos.relative(this.direction.getOpposite())); + +- return !blockstate.isSolid() && (!this.direction.getAxis().isHorizontal() || !DiodeBlock.isDiode(blockstate)) ? false : this.level().getEntities((Entity) this, this.getBoundingBox(), ItemFrame.HANGING_ENTITY).isEmpty(); ++ return !iblockdata.isSolid() && (!this.direction.getAxis().isHorizontal() || !DiodeBlock.isDiode(iblockdata)) ? false : this.level().getEntities((Entity) this, this.getBoundingBox(), ItemFrame.HANGING_ENTITY).isEmpty(); + } + } + + @Override +- @Override +- public void move(MoverType movertype, Vec3 vec3) { ++ public void move(EnumMoveType type, Vec3 pos) { + if (!this.fixed) { +- super.move(movertype, vec3); ++ super.move(type, pos); + } + + } + + @Override +- @Override +- public void push(double d0, double d1, double d2) { ++ public void push(double x, double d1, double y) { + if (!this.fixed) { +- super.push(d0, d1, d2); ++ super.push(x, d1, y); + } + + } + + @Override +- @Override + public void kill() { + this.removeFramedMap(this.getItem()); + super.kill(); + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { ++ public boolean hurt(DamageSource source, float amount) { + if (this.fixed) { +- return !damagesource.is(DamageTypeTags.BYPASSES_INVULNERABILITY) && !damagesource.isCreativePlayer() ? false : super.hurt(damagesource, f); +- } else if (this.isInvulnerableTo(damagesource)) { ++ return !source.is(DamageTypeTags.BYPASSES_INVULNERABILITY) && !source.isCreativePlayer() ? false : super.hurt(source, amount); ++ } else if (this.isInvulnerableTo(source)) { + return false; +- } else if (!damagesource.is(DamageTypeTags.IS_EXPLOSION) && !this.getItem().isEmpty()) { ++ } else if (!source.is(DamageTypeTags.IS_EXPLOSION) && !this.getItem().isEmpty()) { + if (!this.level().isClientSide) { +- this.dropItem(damagesource.getEntity(), false); +- this.gameEvent(GameEvent.BLOCK_CHANGE, damagesource.getEntity()); ++ // CraftBukkit start - fire EntityDamageEvent ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, false) || this.isRemoved()) { ++ return true; ++ } ++ // CraftBukkit end ++ this.dropItem(source.getEntity(), false); ++ this.gameEvent(GameEvent.BLOCK_CHANGE, source.getEntity()); + this.playSound(this.getRemoveItemSound(), 1.0F, 1.0F); + } + + return true; + } else { +- return super.hurt(damagesource, f); ++ return super.hurt(source, amount); + } + } + +@@ -193,32 +201,28 @@ + } + + @Override +- @Override + public int getWidth() { + return 12; + } + + @Override +- @Override + public int getHeight() { + return 12; + } + + @Override +- @Override +- public boolean shouldRenderAtSqrDistance(double d0) { ++ public boolean shouldRenderAtSqrDistance(double distance) { + double d1 = 16.0D; + + d1 *= 64.0D * getViewScale(); +- return d0 < d1 * d1; ++ return distance < d1 * d1; + } + + @Override +- @Override +- public void dropItem(@Nullable Entity entity) { ++ public void dropItem(@Nullable Entity brokenEntity) { + this.playSound(this.getBreakSound(), 1.0F, 1.0F); +- this.dropItem(entity, true); +- this.gameEvent(GameEvent.BLOCK_CHANGE, entity); ++ this.dropItem(brokenEntity, true); ++ this.gameEvent(GameEvent.BLOCK_CHANGE, brokenEntity); + } + + public SoundEvent getBreakSound() { +@@ -226,7 +230,6 @@ + } + + @Override +- @Override + public void playPlacementSound() { + this.playSound(this.getPlaceSound(), 1.0F, 1.0F); + } +@@ -235,7 +238,7 @@ + return SoundEvents.ITEM_FRAME_PLACE; + } + +- private void dropItem(@Nullable Entity entity, boolean flag) { ++ private void dropItem(@Nullable Entity entity, boolean dropSelf) { + if (!this.fixed) { + ItemStack itemstack = this.getItem(); + +@@ -247,15 +250,15 @@ + + } else { + if (entity instanceof Player) { +- Player player = (Player) entity; ++ Player entityhuman = (Player) entity; + +- if (player.getAbilities().instabuild) { ++ if (entityhuman.getAbilities().instabuild) { + this.removeFramedMap(itemstack); + return; + } + } + +- if (flag) { ++ if (dropSelf) { + this.spawnAtLocation(this.getFrameItemStack()); + } + +@@ -271,17 +274,17 @@ + } + } + +- private void removeFramedMap(ItemStack itemstack) { ++ private void removeFramedMap(ItemStack stack) { + this.getFramedMapId().ifPresent((i) -> { +- MapItemSavedData mapitemsaveddata = MapItem.getSavedData(i, this.level()); ++ MapItemSavedData worldmap = MapItem.getSavedData(i, this.level()); + +- if (mapitemsaveddata != null) { +- mapitemsaveddata.removedFromFrame(this.pos, this.getId()); +- mapitemsaveddata.setDirty(true); ++ if (worldmap != null) { ++ worldmap.removedFromFrame(this.pos, this.getId()); ++ worldmap.setDirty(true); + } + + }); +- itemstack.setEntityRepresentation((Entity) null); ++ stack.setEntityRepresentation((Entity) null); + } + + public ItemStack getItem() { +@@ -306,18 +309,24 @@ + return this.getFramedMapId().isPresent(); + } + +- public void setItem(ItemStack itemstack) { +- this.setItem(itemstack, true); ++ public void setItem(ItemStack stack) { ++ this.setItem(stack, true); + } + +- public void setItem(ItemStack itemstack, boolean flag) { ++ public void setItem(ItemStack stack, boolean updateNeighbours) { ++ // CraftBukkit start ++ this.setItem(stack, updateNeighbours, true); ++ } ++ ++ public void setItem(ItemStack itemstack, boolean flag, boolean playSound) { ++ // CraftBukkit end + if (!itemstack.isEmpty()) { + itemstack = itemstack.copyWithCount(1); + } + + this.onItemChanged(itemstack); + this.getEntityData().set(ItemFrame.DATA_ITEM, itemstack); +- if (!itemstack.isEmpty()) { ++ if (!itemstack.isEmpty() && playSound) { // CraftBukkit + this.playSound(this.getAddItemSound(), 1.0F, 1.0F); + } + +@@ -332,36 +341,32 @@ + } + + @Override +- @Override +- public SlotAccess getSlot(int i) { +- return i == 0 ? new SlotAccess() { ++ public SlotAccess getSlot(int slot) { ++ return slot == 0 ? new SlotAccess() { + @Override +- @Override + public ItemStack get() { + return ItemFrame.this.getItem(); + } + + @Override +- @Override +- public boolean set(ItemStack itemstack) { +- ItemFrame.this.setItem(itemstack); ++ public boolean set(ItemStack carried) { ++ ItemFrame.this.setItem(carried); + return true; + } +- } : super.getSlot(i); ++ } : super.getSlot(slot); + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- if (entitydataaccessor.equals(ItemFrame.DATA_ITEM)) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ if (key.equals(ItemFrame.DATA_ITEM)) { + this.onItemChanged(this.getItem()); + } + + } + +- private void onItemChanged(ItemStack itemstack) { +- if (!itemstack.isEmpty() && itemstack.getFrame() != this) { +- itemstack.setEntityRepresentation(this); ++ private void onItemChanged(ItemStack item) { ++ if (!item.isEmpty() && item.getFrame() != this) { ++ item.setEntityRepresentation(this); + } + + this.recalculateBoundingBox(); +@@ -371,44 +376,42 @@ + return (Integer) this.getEntityData().get(ItemFrame.DATA_ROTATION); + } + +- public void setRotation(int i) { +- this.setRotation(i, true); ++ public void setRotation(int rotation) { ++ this.setRotation(rotation, true); + } + +- private void setRotation(int i, boolean flag) { +- this.getEntityData().set(ItemFrame.DATA_ROTATION, i % 8); +- if (flag && this.pos != null) { ++ private void setRotation(int rotation, boolean updateNeighbours) { ++ this.getEntityData().set(ItemFrame.DATA_ROTATION, rotation % 8); ++ if (updateNeighbours && this.pos != null) { + this.level().updateNeighbourForOutputSignal(this.pos, Blocks.AIR); + } + + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); + if (!this.getItem().isEmpty()) { +- compoundtag.put("Item", this.getItem().save(new CompoundTag())); +- compoundtag.putByte("ItemRotation", (byte) this.getRotation()); +- compoundtag.putFloat("ItemDropChance", this.dropChance); ++ compound.put("Item", this.getItem().save(new CompoundTag())); ++ compound.putByte("ItemRotation", (byte) this.getRotation()); ++ compound.putFloat("ItemDropChance", this.dropChance); + } + +- compoundtag.putByte("Facing", (byte) this.direction.get3DDataValue()); +- compoundtag.putBoolean("Invisible", this.isInvisible()); +- compoundtag.putBoolean("Fixed", this.fixed); ++ compound.putByte("Facing", (byte) this.direction.get3DDataValue()); ++ compound.putBoolean("Invisible", this.isInvisible()); ++ compound.putBoolean("Fixed", this.fixed); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- CompoundTag compoundtag1 = compoundtag.getCompound("Item"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ CompoundTag nbttagcompound1 = compound.getCompound("Item"); + +- if (compoundtag1 != null && !compoundtag1.isEmpty()) { +- ItemStack itemstack = ItemStack.of(compoundtag1); ++ if (nbttagcompound1 != null && !nbttagcompound1.isEmpty()) { ++ ItemStack itemstack = ItemStack.of(nbttagcompound1); + + if (itemstack.isEmpty()) { +- ItemFrame.LOGGER.warn("Unable to load item from: {}", compoundtag1); ++ ItemFrame.LOGGER.warn("Unable to load item from: {}", nbttagcompound1); + } + + ItemStack itemstack1 = this.getItem(); +@@ -418,21 +421,20 @@ + } + + this.setItem(itemstack, false); +- this.setRotation(compoundtag.getByte("ItemRotation"), false); +- if (compoundtag.contains("ItemDropChance", 99)) { +- this.dropChance = compoundtag.getFloat("ItemDropChance"); ++ this.setRotation(compound.getByte("ItemRotation"), false); ++ if (compound.contains("ItemDropChance", 99)) { ++ this.dropChance = compound.getFloat("ItemDropChance"); + } + } + +- this.setDirection(Direction.from3DDataValue(compoundtag.getByte("Facing"))); +- this.setInvisible(compoundtag.getBoolean("Invisible")); +- this.fixed = compoundtag.getBoolean("Fixed"); ++ this.setDirection(Direction.from3DDataValue(compound.getByte("Facing"))); ++ this.setInvisible(compound.getBoolean("Invisible")); ++ this.fixed = compound.getBoolean("Fixed"); + } + + @Override +- @Override +- public InteractionResult interact(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult interact(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + boolean flag = !this.getItem().isEmpty(); + boolean flag1 = !itemstack.isEmpty(); + +@@ -442,9 +444,9 @@ + if (!flag) { + if (flag1 && !this.isRemoved()) { + if (itemstack.is(Items.FILLED_MAP)) { +- MapItemSavedData mapitemsaveddata = MapItem.getSavedData(itemstack, this.level()); ++ MapItemSavedData worldmap = MapItem.getSavedData(itemstack, this.level()); + +- if (mapitemsaveddata != null && mapitemsaveddata.isTrackedCountOverLimit(256)) { ++ if (worldmap != null && worldmap.isTrackedCountOverLimit(256)) { + return InteractionResult.FAIL; + } + } +@@ -476,20 +478,17 @@ + } + + @Override +- @Override + public Packet getAddEntityPacket() { + return new ClientboundAddEntityPacket(this, this.direction.get3DDataValue(), this.getPos()); + } + + @Override +- @Override +- public void recreateFromPacket(ClientboundAddEntityPacket clientboundaddentitypacket) { +- super.recreateFromPacket(clientboundaddentitypacket); +- this.setDirection(Direction.from3DDataValue(clientboundaddentitypacket.getData())); ++ public void recreateFromPacket(ClientboundAddEntityPacket packet) { ++ super.recreateFromPacket(packet); ++ this.setDirection(Direction.from3DDataValue(packet.getData())); + } + + @Override +- @Override + public ItemStack getPickResult() { + ItemStack itemstack = this.getItem(); + +@@ -501,11 +500,10 @@ + } + + @Override +- @Override + public float getVisualRotationYInDegrees() { +- Direction direction = this.getDirection(); +- int i = direction.getAxis().isVertical() ? 90 * direction.getAxisDirection().getStep() : 0; ++ Direction enumdirection = this.getDirection(); ++ int i = enumdirection.getAxis().isVertical() ? 90 * enumdirection.getAxisDirection().getStep() : 0; + +- return (float) Mth.wrapDegrees(180 + direction.get2DDataValue() * 90 + this.getRotation() * 45 + i); ++ return (float) Mth.wrapDegrees(180 + enumdirection.get2DDataValue() * 90 + this.getRotation() * 45 + i); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java.patch new file mode 100644 index 0000000000..3eb26f4f9b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java.patch @@ -0,0 +1,237 @@ +--- a/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java ++++ b/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java +@@ -9,15 +9,17 @@ + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientGamePacketListener; + import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; ++import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.tags.BlockTags; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +@@ -25,22 +27,23 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class LeashFenceKnotEntity extends HangingEntity { + + public static final double OFFSET_Y = 0.375D; + +- public LeashFenceKnotEntity(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public LeashFenceKnotEntity(EntityType entityType, Level level) { ++ super(entityType, level); + } + +- public LeashFenceKnotEntity(Level level, BlockPos blockpos) { +- super(EntityType.LEASH_KNOT, level, blockpos); +- this.setPos((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ()); ++ public LeashFenceKnotEntity(Level level, BlockPos pos) { ++ super(EntityType.LEASH_KNOT, level, pos); ++ this.setPos((double) pos.getX(), (double) pos.getY(), (double) pos.getZ()); + } + + @Override +- @Override + protected void recalculateBoundingBox() { + this.setPosRaw((double) this.pos.getX() + 0.5D, (double) this.pos.getY() + 0.375D, (double) this.pos.getZ() + 0.5D); + double d0 = (double) this.getType().getWidth() / 2.0D; +@@ -50,50 +53,41 @@ + } + + @Override +- @Override +- public void setDirection(Direction direction) {} ++ public void setDirection(Direction facingDirection) {} + + @Override +- @Override + public int getWidth() { + return 9; + } + + @Override +- @Override + public int getHeight() { + return 9; + } + + @Override +- @Override +- protected float getEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.0625F; + } + + @Override +- @Override +- public boolean shouldRenderAtSqrDistance(double d0) { +- return d0 < 1024.0D; ++ public boolean shouldRenderAtSqrDistance(double distance) { ++ return distance < 1024.0D; + } + + @Override +- @Override +- public void dropItem(@Nullable Entity entity) { ++ public void dropItem(@Nullable Entity brokenEntity) { + this.playSound(SoundEvents.LEASH_KNOT_BREAK, 1.0F, 1.0F); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) {} ++ public void addAdditionalSaveData(CompoundTag compound) {} + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) {} ++ public void readAdditionalSaveData(CompoundTag compound) {} + + @Override +- @Override +- public InteractionResult interact(Player player, InteractionHand interactionhand) { ++ public InteractionResult interact(Player player, EnumHand hand) { + if (this.level().isClientSide) { + return InteractionResult.SUCCESS; + } else { +@@ -103,10 +97,16 @@ + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- Mob mob = (Mob) iterator.next(); ++ Mob entityinsentient = (Mob) iterator.next(); + +- if (mob.getLeashHolder() == player) { +- mob.setLeashedTo(this, true); ++ if (entityinsentient.getLeashHolder() == player) { ++ // CraftBukkit start ++ if (CraftEventFactory.callPlayerLeashEntityEvent(entityinsentient, this, player, hand).isCancelled()) { ++ ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(entityinsentient, entityinsentient.getLeashHolder())); ++ continue; ++ } ++ // CraftBukkit end ++ entityinsentient.setLeashedTo(this, true); + flag = true; + } + } +@@ -114,18 +114,32 @@ + boolean flag1 = false; + + if (!flag) { +- this.discard(); +- if (player.getAbilities().instabuild) { ++ // CraftBukkit start - Move below ++ // this.discard(); ++ boolean die = true; ++ // CraftBukkit end ++ if (true || player.getAbilities().instabuild) { // CraftBukkit - Process for non-creative as well + Iterator iterator1 = list.iterator(); + + while (iterator1.hasNext()) { +- Mob mob1 = (Mob) iterator1.next(); ++ Mob entityinsentient1 = (Mob) iterator1.next(); + +- if (mob1.isLeashed() && mob1.getLeashHolder() == this) { +- mob1.dropLeash(true, false); ++ if (entityinsentient1.isLeashed() && entityinsentient1.getLeashHolder() == this) { ++ // CraftBukkit start ++ if (CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient1, player, hand).isCancelled()) { ++ die = false; ++ continue; ++ } ++ entityinsentient1.dropLeash(true, !player.getAbilities().instabuild); // false -> survival mode boolean ++ // CraftBukkit end + flag1 = true; + } + } ++ // CraftBukkit start ++ if (die) { ++ this.discard(); ++ } ++ // CraftBukkit end + } + } + +@@ -138,54 +152,49 @@ + } + + @Override +- @Override + public boolean survives() { + return this.level().getBlockState(this.pos).is(BlockTags.FENCES); + } + +- public static LeashFenceKnotEntity getOrCreateKnot(Level level, BlockPos blockpos) { +- int i = blockpos.getX(); +- int j = blockpos.getY(); +- int k = blockpos.getZ(); ++ public static LeashFenceKnotEntity getOrCreateKnot(Level level, BlockPos pos) { ++ int i = pos.getX(); ++ int j = pos.getY(); ++ int k = pos.getZ(); + List list = level.getEntitiesOfClass(LeashFenceKnotEntity.class, new AABB((double) i - 1.0D, (double) j - 1.0D, (double) k - 1.0D, (double) i + 1.0D, (double) j + 1.0D, (double) k + 1.0D)); + Iterator iterator = list.iterator(); + +- LeashFenceKnotEntity leashfenceknotentity; ++ LeashFenceKnotEntity entityleash; + + do { + if (!iterator.hasNext()) { +- LeashFenceKnotEntity leashfenceknotentity1 = new LeashFenceKnotEntity(level, blockpos); ++ LeashFenceKnotEntity entityleash1 = new LeashFenceKnotEntity(level, pos); + +- level.addFreshEntity(leashfenceknotentity1); +- return leashfenceknotentity1; ++ level.addFreshEntity(entityleash1); ++ return entityleash1; + } + +- leashfenceknotentity = (LeashFenceKnotEntity) iterator.next(); +- } while (!leashfenceknotentity.getPos().equals(blockpos)); ++ entityleash = (LeashFenceKnotEntity) iterator.next(); ++ } while (!entityleash.getPos().equals(pos)); + +- return leashfenceknotentity; ++ return entityleash; + } + + @Override +- @Override + public void playPlacementSound() { + this.playSound(SoundEvents.LEASH_KNOT_PLACE, 1.0F, 1.0F); + } + + @Override +- @Override + public Packet getAddEntityPacket() { + return new ClientboundAddEntityPacket(this, 0, this.getPos()); + } + + @Override +- @Override +- public Vec3 getRopeHoldPosition(float f) { +- return this.getPosition(f).add(0.0D, 0.2D, 0.0D); ++ public Vec3 getRopeHoldPosition(float partialTicks) { ++ return this.getPosition(partialTicks).add(0.0D, 0.2D, 0.0D); + } + + @Override +- @Override + public ItemStack getPickResult() { + return new ItemStack(Items.LEAD); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/item/FallingBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/item/FallingBlockEntity.java.patch new file mode 100644 index 0000000000..2dae9a8de8 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/item/FallingBlockEntity.java.patch @@ -0,0 +1,450 @@ +--- a/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -26,13 +26,13 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MoverType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.context.BlockPlaceContext; + import net.minecraft.world.item.context.DirectionalPlaceContext; + import net.minecraft.world.level.ClipContext; + import net.minecraft.world.level.GameRules; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.AnvilBlock; + import net.minecraft.world.level.block.Block; +@@ -41,7 +41,7 @@ + import net.minecraft.world.level.block.Fallable; + import net.minecraft.world.level.block.FallingBlock; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.BlockHitResult; +@@ -49,55 +49,65 @@ + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class FallingBlockEntity extends Entity { + + private static final Logger LOGGER = LogUtils.getLogger(); +- private BlockState blockState; ++ private IBlockData blockState; + public int time; + public boolean dropItem; +- private boolean cancelDrop; +- private boolean hurtEntities; +- private int fallDamageMax; +- private float fallDamagePerDistance; ++ public boolean cancelDrop; ++ public boolean hurtEntities; ++ public int fallDamageMax; ++ public float fallDamagePerDistance; + @Nullable + public CompoundTag blockData; + protected static final EntityDataAccessor DATA_START_POS = SynchedEntityData.defineId(FallingBlockEntity.class, EntityDataSerializers.BLOCK_POS); + +- public FallingBlockEntity(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public FallingBlockEntity(EntityType entityType, Level level) { ++ super(entityType, level); + this.blockState = Blocks.SAND.defaultBlockState(); + this.dropItem = true; + this.fallDamageMax = 40; + } + +- private FallingBlockEntity(Level level, double d0, double d1, double d2, BlockState blockstate) { ++ private FallingBlockEntity(Level level, double x, double d1, double y, IBlockData iblockdata) { + this(EntityType.FALLING_BLOCK, level); +- this.blockState = blockstate; ++ this.blockState = iblockdata; + this.blocksBuilding = true; +- this.setPos(d0, d1, d2); ++ this.setPos(x, d1, y); + this.setDeltaMovement(Vec3.ZERO); +- this.xo = d0; ++ this.xo = x; + this.yo = d1; +- this.zo = d2; ++ this.zo = y; + this.setStartPos(this.blockPosition()); + } + +- public static FallingBlockEntity fall(Level level, BlockPos blockpos, BlockState blockstate) { +- FallingBlockEntity fallingblockentity = new FallingBlockEntity(level, (double) blockpos.getX() + 0.5D, (double) blockpos.getY(), (double) blockpos.getZ() + 0.5D, blockstate.hasProperty(BlockStateProperties.WATERLOGGED) ? (BlockState) blockstate.setValue(BlockStateProperties.WATERLOGGED, false) : blockstate); ++ public static FallingBlockEntity fall(Level level, BlockPos pos, IBlockData blockState) { ++ // CraftBukkit start ++ return fall(level, pos, blockState, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } + +- level.setBlock(blockpos, blockstate.getFluidState().createLegacyBlock(), 3); +- level.addFreshEntity(fallingblockentity); +- return fallingblockentity; ++ public static FallingBlockEntity fall(Level world, BlockPos blockposition, IBlockData iblockdata, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end ++ FallingBlockEntity entityfallingblock = new FallingBlockEntity(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, iblockdata.hasProperty(BlockStateProperties.WATERLOGGED) ? (IBlockData) iblockdata.setValue(BlockStateProperties.WATERLOGGED, false) : iblockdata); ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entityfallingblock, blockposition, iblockdata.getFluidState().createLegacyBlock())) return entityfallingblock; // CraftBukkit ++ ++ world.setBlock(blockposition, iblockdata.getFluidState().createLegacyBlock(), 3); ++ world.addFreshEntity(entityfallingblock, spawnReason); // CraftBukkit ++ return entityfallingblock; + } + + @Override +- @Override + public boolean isAttackable() { + return false; + } + +- public void setStartPos(BlockPos blockpos) { +- this.entityData.set(FallingBlockEntity.DATA_START_POS, blockpos); ++ public void setStartPos(BlockPos startPos) { ++ this.entityData.set(FallingBlockEntity.DATA_START_POS, startPos); + } + + public BlockPos getStartPos() { +@@ -105,25 +115,21 @@ + } + + @Override +- @Override + protected Entity.MovementEmission getMovementEmission() { + return Entity.MovementEmission.NONE; + } + + @Override +- @Override + protected void defineSynchedData() { + this.entityData.define(FallingBlockEntity.DATA_START_POS, BlockPos.ZERO); + } + + @Override +- @Override + public boolean isPickable() { + return !this.isRemoved(); + } + + @Override +- @Override + public void tick() { + if (this.blockState.isAir()) { + this.discard(); +@@ -135,89 +141,95 @@ + this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.04D, 0.0D)); + } + +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + if (!this.level().isClientSide) { +- BlockPos blockpos = this.blockPosition(); ++ BlockPos blockposition = this.blockPosition(); + boolean flag = this.blockState.getBlock() instanceof ConcretePowderBlock; +- boolean flag1 = flag && this.level().getFluidState(blockpos).is(FluidTags.WATER); ++ boolean flag1 = flag && this.level().getFluidState(blockposition).is(FluidTags.WATER); + double d0 = this.getDeltaMovement().lengthSqr(); + + if (flag && d0 > 1.0D) { +- BlockHitResult blockhitresult = this.level().clip(new ClipContext(new Vec3(this.xo, this.yo, this.zo), this.position(), ClipContext.Block.COLLIDER, ClipContext.Fluid.SOURCE_ONLY, this)); ++ BlockHitResult movingobjectpositionblock = this.level().clip(new ClipContext(new Vec3(this.xo, this.yo, this.zo), this.position(), ClipContext.Block.COLLIDER, ClipContext.Fluid.SOURCE_ONLY, this)); + +- if (blockhitresult.getType() != HitResult.Type.MISS && this.level().getFluidState(blockhitresult.getBlockPos()).is(FluidTags.WATER)) { +- blockpos = blockhitresult.getBlockPos(); ++ if (movingobjectpositionblock.getType() != HitResult.EnumMovingObjectType.MISS && this.level().getFluidState(movingobjectpositionblock.getBlockPos()).is(FluidTags.WATER)) { ++ blockposition = movingobjectpositionblock.getBlockPos(); + flag1 = true; + } + } + + if (!this.onGround() && !flag1) { +- if (!this.level().isClientSide && (this.time > 100 && (blockpos.getY() <= this.level().getMinBuildHeight() || blockpos.getY() > this.level().getMaxBuildHeight()) || this.time > 600)) { ++ if (!this.level().isClientSide && (this.time > 100 && (blockposition.getY() <= this.level().getMinBuildHeight() || blockposition.getY() > this.level().getMaxBuildHeight()) || this.time > 600)) { + if (this.dropItem && this.level().getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { +- this.spawnAtLocation((ItemLike) block); ++ this.spawnAtLocation((IMaterial) block); + } + + this.discard(); + } + } else { +- BlockState blockstate = this.level().getBlockState(blockpos); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); + + this.setDeltaMovement(this.getDeltaMovement().multiply(0.7D, -0.5D, 0.7D)); +- if (!blockstate.is(Blocks.MOVING_PISTON)) { ++ if (!iblockdata.is(Blocks.MOVING_PISTON)) { + if (!this.cancelDrop) { +- boolean flag2 = blockstate.canBeReplaced((BlockPlaceContext) (new DirectionalPlaceContext(this.level(), blockpos, Direction.DOWN, ItemStack.EMPTY, Direction.UP))); +- boolean flag3 = FallingBlock.isFree(this.level().getBlockState(blockpos.below())) && (!flag || !flag1); +- boolean flag4 = this.blockState.canSurvive(this.level(), blockpos) && !flag3; ++ boolean flag2 = iblockdata.canBeReplaced((BlockPlaceContext) (new DirectionalPlaceContext(this.level(), blockposition, Direction.DOWN, ItemStack.EMPTY, Direction.UP))); ++ boolean flag3 = FallingBlock.isFree(this.level().getBlockState(blockposition.below())) && (!flag || !flag1); ++ boolean flag4 = this.blockState.canSurvive(this.level(), blockposition) && !flag3; + + if (flag2 && flag4) { +- if (this.blockState.hasProperty(BlockStateProperties.WATERLOGGED) && this.level().getFluidState(blockpos).getType() == Fluids.WATER) { +- this.blockState = (BlockState) this.blockState.setValue(BlockStateProperties.WATERLOGGED, true); ++ if (this.blockState.hasProperty(BlockStateProperties.WATERLOGGED) && this.level().getFluidState(blockposition).getType() == Fluids.WATER) { ++ this.blockState = (IBlockData) this.blockState.setValue(BlockStateProperties.WATERLOGGED, true); + } + +- if (this.level().setBlock(blockpos, this.blockState, 3)) { +- ((ServerLevel) this.level()).getChunkSource().chunkMap.broadcast(this, new ClientboundBlockUpdatePacket(blockpos, this.level().getBlockState(blockpos))); ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, this.blockState)) { ++ this.discard(); // SPIGOT-6586 called before the event in previous versions ++ return; ++ } ++ // CraftBukkit end ++ if (this.level().setBlock(blockposition, this.blockState, 3)) { ++ ((ServerLevel) this.level()).getChunkSource().chunkMap.broadcast(this, new ClientboundBlockUpdatePacket(blockposition, this.level().getBlockState(blockposition))); + this.discard(); + if (block instanceof Fallable) { +- ((Fallable) block).onLand(this.level(), blockpos, this.blockState, blockstate, this); ++ ((Fallable) block).onLand(this.level(), blockposition, this.blockState, iblockdata, this); + } + + if (this.blockData != null && this.blockState.hasBlockEntity()) { +- BlockEntity blockentity = this.level().getBlockEntity(blockpos); ++ BlockEntity tileentity = this.level().getBlockEntity(blockposition); + +- if (blockentity != null) { +- CompoundTag compoundtag = blockentity.saveWithoutMetadata(); ++ if (tileentity != null) { ++ CompoundTag nbttagcompound = tileentity.saveWithoutMetadata(); + Iterator iterator = this.blockData.getAllKeys().iterator(); + + while (iterator.hasNext()) { + String s = (String) iterator.next(); + +- compoundtag.put(s, this.blockData.get(s).copy()); ++ nbttagcompound.put(s, this.blockData.get(s).copy()); + } + + try { +- blockentity.load(compoundtag); ++ tileentity.load(nbttagcompound); + } catch (Exception exception) { + FallingBlockEntity.LOGGER.error("Failed to load block entity from falling block", exception); + } + +- blockentity.setChanged(); ++ tileentity.setChanged(); + } + } + } else if (this.dropItem && this.level().getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { + this.discard(); +- this.callOnBrokenAfterFall(block, blockpos); +- this.spawnAtLocation((ItemLike) block); ++ this.callOnBrokenAfterFall(block, blockposition); ++ this.spawnAtLocation((IMaterial) block); + } + } else { + this.discard(); + if (this.dropItem && this.level().getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { +- this.callOnBrokenAfterFall(block, blockpos); +- this.spawnAtLocation((ItemLike) block); ++ this.callOnBrokenAfterFall(block, blockposition); ++ this.spawnAtLocation((IMaterial) block); + } + } + } else { + this.discard(); +- this.callOnBrokenAfterFall(block, blockpos); ++ this.callOnBrokenAfterFall(block, blockposition); + } + } + } +@@ -227,20 +239,19 @@ + } + } + +- public void callOnBrokenAfterFall(Block block, BlockPos blockpos) { ++ public void callOnBrokenAfterFall(Block block, BlockPos pos) { + if (block instanceof Fallable) { +- ((Fallable) block).onBrokenAfterFall(this.level(), blockpos, this); ++ ((Fallable) block).onBrokenAfterFall(this.level(), pos, this); + } + + } + + @Override +- @Override +- public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { ++ public boolean causeFallDamage(float fallDistance, float multiplier, DamageSource source) { + if (!this.hurtEntities) { + return false; + } else { +- int i = Mth.ceil(f - 1.0F); ++ int i = Mth.ceil(fallDistance - 1.0F); + + if (i < 0) { + return false; +@@ -261,17 +272,19 @@ + float f2 = (float) Math.min(Mth.floor((float) i * this.fallDamagePerDistance), this.fallDamageMax); + + this.level().getEntities((Entity) this, this.getBoundingBox(), predicate).forEach((entity) -> { ++ CraftEventFactory.entityDamage = this; // CraftBukkit + entity.hurt(damagesource2, f2); ++ CraftEventFactory.entityDamage = null; // CraftBukkit + }); + boolean flag = this.blockState.is(BlockTags.ANVIL); + + if (flag && f2 > 0.0F && this.random.nextFloat() < 0.05F + (float) i * 0.05F) { +- BlockState blockstate = AnvilBlock.damage(this.blockState); ++ IBlockData iblockdata = AnvilBlock.damage(this.blockState); + +- if (blockstate == null) { ++ if (iblockdata == null) { + this.cancelDrop = true; + } else { +- this.blockState = blockstate; ++ this.blockState = iblockdata; + } + } + +@@ -281,53 +294,51 @@ + } + + @Override +- @Override +- protected void addAdditionalSaveData(CompoundTag compoundtag) { +- compoundtag.put("BlockState", NbtUtils.writeBlockState(this.blockState)); +- compoundtag.putInt("Time", this.time); +- compoundtag.putBoolean("DropItem", this.dropItem); +- compoundtag.putBoolean("HurtEntities", this.hurtEntities); +- compoundtag.putFloat("FallHurtAmount", this.fallDamagePerDistance); +- compoundtag.putInt("FallHurtMax", this.fallDamageMax); ++ protected void addAdditionalSaveData(CompoundTag compound) { ++ compound.put("BlockState", NbtUtils.writeBlockState(this.blockState)); ++ compound.putInt("Time", this.time); ++ compound.putBoolean("DropItem", this.dropItem); ++ compound.putBoolean("HurtEntities", this.hurtEntities); ++ compound.putFloat("FallHurtAmount", this.fallDamagePerDistance); ++ compound.putInt("FallHurtMax", this.fallDamageMax); + if (this.blockData != null) { +- compoundtag.put("TileEntityData", this.blockData); ++ compound.put("TileEntityData", this.blockData); + } + +- compoundtag.putBoolean("CancelDrop", this.cancelDrop); ++ compound.putBoolean("CancelDrop", this.cancelDrop); + } + + @Override +- @Override +- protected void readAdditionalSaveData(CompoundTag compoundtag) { +- this.blockState = NbtUtils.readBlockState(this.level().holderLookup(Registries.BLOCK), compoundtag.getCompound("BlockState")); +- this.time = compoundtag.getInt("Time"); +- if (compoundtag.contains("HurtEntities", 99)) { +- this.hurtEntities = compoundtag.getBoolean("HurtEntities"); +- this.fallDamagePerDistance = compoundtag.getFloat("FallHurtAmount"); +- this.fallDamageMax = compoundtag.getInt("FallHurtMax"); ++ protected void readAdditionalSaveData(CompoundTag compound) { ++ this.blockState = NbtUtils.readBlockState(this.level().holderLookup(Registries.BLOCK), compound.getCompound("BlockState")); ++ this.time = compound.getInt("Time"); ++ if (compound.contains("HurtEntities", 99)) { ++ this.hurtEntities = compound.getBoolean("HurtEntities"); ++ this.fallDamagePerDistance = compound.getFloat("FallHurtAmount"); ++ this.fallDamageMax = compound.getInt("FallHurtMax"); + } else if (this.blockState.is(BlockTags.ANVIL)) { + this.hurtEntities = true; + } + +- if (compoundtag.contains("DropItem", 99)) { +- this.dropItem = compoundtag.getBoolean("DropItem"); ++ if (compound.contains("DropItem", 99)) { ++ this.dropItem = compound.getBoolean("DropItem"); + } + +- if (compoundtag.contains("TileEntityData", 10)) { +- this.blockData = compoundtag.getCompound("TileEntityData").copy(); ++ if (compound.contains("TileEntityData", 10)) { ++ this.blockData = compound.getCompound("TileEntityData").copy(); + } + +- this.cancelDrop = compoundtag.getBoolean("CancelDrop"); ++ this.cancelDrop = compound.getBoolean("CancelDrop"); + if (this.blockState.isAir()) { + this.blockState = Blocks.SAND.defaultBlockState(); + } + + } + +- public void setHurtsEntities(float f, int i) { ++ public void setHurtsEntities(float fallDamagePerDistance, int fallDamageMax) { + this.hurtEntities = true; +- this.fallDamagePerDistance = f; +- this.fallDamageMax = i; ++ this.fallDamagePerDistance = fallDamagePerDistance; ++ this.fallDamageMax = fallDamageMax; + } + + public void disableDrop() { +@@ -335,49 +346,43 @@ + } + + @Override +- @Override + public boolean displayFireAnimation() { + return false; + } + + @Override +- @Override +- public void fillCrashReportCategory(CrashReportCategory crashreportcategory) { +- super.fillCrashReportCategory(crashreportcategory); +- crashreportcategory.setDetail("Immitating BlockState", (Object) this.blockState.toString()); ++ public void fillCrashReportCategory(CrashReportCategory category) { ++ super.fillCrashReportCategory(category); ++ category.setDetail("Immitating BlockState", (Object) this.blockState.toString()); + } + +- public BlockState getBlockState() { ++ public IBlockData getBlockState() { + return this.blockState; + } + + @Override +- @Override + protected Component getTypeName() { + return Component.translatable("entity.minecraft.falling_block_type", this.blockState.getBlock().getName()); + } + + @Override +- @Override + public boolean onlyOpCanSetNbt() { + return true; + } + + @Override +- @Override + public Packet getAddEntityPacket() { + return new ClientboundAddEntityPacket(this, Block.getId(this.getBlockState())); + } + + @Override +- @Override +- public void recreateFromPacket(ClientboundAddEntityPacket clientboundaddentitypacket) { +- super.recreateFromPacket(clientboundaddentitypacket); +- this.blockState = Block.stateById(clientboundaddentitypacket.getData()); ++ public void recreateFromPacket(ClientboundAddEntityPacket packet) { ++ super.recreateFromPacket(packet); ++ this.blockState = Block.stateById(packet.getData()); + this.blocksBuilding = true; +- double d0 = clientboundaddentitypacket.getX(); +- double d1 = clientboundaddentitypacket.getY(); +- double d2 = clientboundaddentitypacket.getZ(); ++ double d0 = packet.getX(); ++ double d1 = packet.getY(); ++ double d2 = packet.getZ(); + + this.setPos(d0, d1, d2); + this.setStartPos(this.blockPosition()); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/item/ItemEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/item/ItemEntity.java.patch new file mode 100644 index 0000000000..120c953258 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/item/ItemEntity.java.patch @@ -0,0 +1,623 @@ +--- a/net/minecraft/world/entity/item/ItemEntity.java ++++ b/net/minecraft/world/entity/item/ItemEntity.java +@@ -5,15 +5,6 @@ + import java.util.Objects; + import java.util.UUID; + import javax.annotation.Nullable; +-import net.minecraft.core.BlockPos; +-import net.minecraft.nbt.CompoundTag; +-import net.minecraft.network.chat.Component; +-import net.minecraft.network.syncher.EntityDataAccessor; +-import net.minecraft.network.syncher.EntityDataSerializers; +-import net.minecraft.network.syncher.SynchedEntityData; +-import net.minecraft.server.level.ServerLevel; +-import net.minecraft.sounds.SoundSource; +-import net.minecraft.stats.Stats; + import net.minecraft.tags.DamageTypeTags; + import net.minecraft.tags.FluidTags; + import net.minecraft.tags.ItemTags; +@@ -21,15 +12,30 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MoverType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.TraceableEntity; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3; ++import net.minecraft.core.BlockPos; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.network.chat.Component; ++import net.minecraft.network.syncher.EntityDataAccessor; ++import net.minecraft.network.syncher.EntityDataSerializers; ++import net.minecraft.network.syncher.SynchedEntityData; ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.sounds.SoundSource; ++import net.minecraft.stats.Stats; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.entity.Player; ++import org.bukkit.event.entity.EntityPickupItemEvent; ++import org.bukkit.event.player.PlayerPickupItemEvent; ++// CraftBukkit end + + public class ItemEntity extends Entity implements TraceableEntity { + +@@ -37,64 +43,63 @@ + private static final int LIFETIME = 6000; + private static final int INFINITE_PICKUP_DELAY = 32767; + private static final int INFINITE_LIFETIME = -32768; +- private int age; +- private int pickupDelay; ++ public int age; ++ public int pickupDelay; + private int health; + @Nullable +- private UUID thrower; ++ public UUID thrower; + @Nullable + private Entity cachedThrower; + @Nullable +- private UUID target; ++ public UUID target; + public final float bobOffs; ++ private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit + +- public ItemEntity(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public ItemEntity(EntityType entityType, Level level) { ++ super(entityType, level); + this.health = 5; + this.bobOffs = this.random.nextFloat() * 3.1415927F * 2.0F; + this.setYRot(this.random.nextFloat() * 360.0F); + } + +- public ItemEntity(Level level, double d0, double d1, double d2, ItemStack itemstack) { +- this(level, d0, d1, d2, itemstack, level.random.nextDouble() * 0.2D - 0.1D, 0.2D, level.random.nextDouble() * 0.2D - 0.1D); ++ public ItemEntity(Level level, double posX, double d1, double posY, ItemStack itemstack) { ++ this(level, posX, d1, posY, itemstack, level.random.nextDouble() * 0.2D - 0.1D, 0.2D, level.random.nextDouble() * 0.2D - 0.1D); + } + +- public ItemEntity(Level level, double d0, double d1, double d2, ItemStack itemstack, double d3, double d4, double d5) { ++ public ItemEntity(Level level, double posX, double d1, double posY, ItemStack itemstack, double posZ, double d4, double itemStack) { + this(EntityType.ITEM, level); +- this.setPos(d0, d1, d2); +- this.setDeltaMovement(d3, d4, d5); ++ this.setPos(posX, d1, posY); ++ this.setDeltaMovement(posZ, d4, itemStack); + this.setItem(itemstack); + } + +- private ItemEntity(ItemEntity itementity) { +- super(itementity.getType(), itementity.level()); ++ private ItemEntity(ItemEntity other) { ++ super(other.getType(), other.level()); + this.health = 5; +- this.setItem(itementity.getItem().copy()); +- this.copyPosition(itementity); +- this.age = itementity.age; +- this.bobOffs = itementity.bobOffs; ++ this.setItem(other.getItem().copy()); ++ this.copyPosition(other); ++ this.age = other.age; ++ this.bobOffs = other.bobOffs; + } + + @Override +- @Override + public boolean dampensVibrations() { + return this.getItem().is(ItemTags.DAMPENS_VIBRATIONS); + } + + @Nullable + @Override +- @Override + public Entity getOwner() { + if (this.cachedThrower != null && !this.cachedThrower.isRemoved()) { + return this.cachedThrower; + } else { + if (this.thrower != null) { +- Level level = this.level(); ++ Level world = this.level(); + +- if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; + +- this.cachedThrower = serverlevel.getEntity(this.thrower); ++ this.cachedThrower = worldserver.getEntity(this.thrower); + return this.cachedThrower; + } + } +@@ -104,44 +109,43 @@ + } + + @Override +- @Override + public void restoreFrom(Entity entity) { + super.restoreFrom(entity); + if (entity instanceof ItemEntity) { +- ItemEntity itementity = (ItemEntity) entity; ++ ItemEntity entityitem = (ItemEntity) entity; + +- this.cachedThrower = itementity.cachedThrower; ++ this.cachedThrower = entityitem.cachedThrower; + } + + } + + @Override +- @Override + protected Entity.MovementEmission getMovementEmission() { + return Entity.MovementEmission.NONE; + } + + @Override +- @Override + protected void defineSynchedData() { + this.getEntityData().define(ItemEntity.DATA_ITEM, ItemStack.EMPTY); + } + + @Override +- @Override + public void tick() { + if (this.getItem().isEmpty()) { + this.discard(); + } else { + super.tick(); +- if (this.pickupDelay > 0 && this.pickupDelay != 32767) { +- --this.pickupDelay; +- } ++ // CraftBukkit start - Use wall time for pickup and despawn timers ++ int elapsedTicks = MinecraftServer.currentTick - this.lastTick; ++ if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; ++ if (this.age != -32768) this.age += elapsedTicks; ++ this.lastTick = MinecraftServer.currentTick; ++ // CraftBukkit end + + this.xo = this.getX(); + this.yo = this.getY(); + this.zo = this.getZ(); +- Vec3 vec3 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + float f = this.getEyeHeight() - 0.11111111F; + + if (this.isInWater() && this.getFluidHeight(FluidTags.WATER) > (double) f) { +@@ -162,7 +166,7 @@ + } + + if (!this.onGround() || this.getDeltaMovement().horizontalDistanceSqr() > 9.999999747378752E-6D || (this.tickCount + this.getId()) % 4 == 0) { +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + float f1 = 0.98F; + + if (this.onGround()) { +@@ -171,10 +175,10 @@ + + this.setDeltaMovement(this.getDeltaMovement().multiply((double) f1, 0.98D, (double) f1)); + if (this.onGround()) { +- Vec3 vec31 = this.getDeltaMovement(); ++ Vec3 vec3d1 = this.getDeltaMovement(); + +- if (vec31.y < 0.0D) { +- this.setDeltaMovement(vec31.multiply(1.0D, -0.5D, 1.0D)); ++ if (vec3d1.y < 0.0D) { ++ this.setDeltaMovement(vec3d1.multiply(1.0D, -0.5D, 1.0D)); + } + } + } +@@ -186,13 +190,15 @@ + this.mergeWithNeighbours(); + } + ++ /* CraftBukkit start - moved up + if (this.age != -32768) { + ++this.age; + } ++ // CraftBukkit end */ + + this.hasImpulse |= this.updateInWaterStateAndDoFluidPushing(); + if (!this.level().isClientSide) { +- double d0 = this.getDeltaMovement().subtract(vec3).lengthSqr(); ++ double d0 = this.getDeltaMovement().subtract(vec3d).lengthSqr(); + + if (d0 > 0.01D) { + this.hasImpulse = true; +@@ -200,6 +206,12 @@ + } + + if (!this.level().isClientSide && this.age >= 6000) { ++ // CraftBukkit start - fire ItemDespawnEvent ++ if (CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { ++ this.age = 0; ++ return; ++ } ++ // CraftBukkit end + this.discard(); + } + +@@ -207,35 +219,34 @@ + } + + @Override +- @Override + protected BlockPos getBlockPosBelowThatAffectsMyMovement() { + return this.getOnPos(0.999999F); + } + + private void setUnderwaterMovement() { +- Vec3 vec3 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + +- this.setDeltaMovement(vec3.x * 0.9900000095367432D, vec3.y + (double) (vec3.y < 0.05999999865889549D ? 5.0E-4F : 0.0F), vec3.z * 0.9900000095367432D); ++ this.setDeltaMovement(vec3d.x * 0.9900000095367432D, vec3d.y + (double) (vec3d.y < 0.05999999865889549D ? 5.0E-4F : 0.0F), vec3d.z * 0.9900000095367432D); + } + + private void setUnderLavaMovement() { +- Vec3 vec3 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + +- this.setDeltaMovement(vec3.x * 0.949999988079071D, vec3.y + (double) (vec3.y < 0.05999999865889549D ? 5.0E-4F : 0.0F), vec3.z * 0.949999988079071D); ++ this.setDeltaMovement(vec3d.x * 0.949999988079071D, vec3d.y + (double) (vec3d.y < 0.05999999865889549D ? 5.0E-4F : 0.0F), vec3d.z * 0.949999988079071D); + } + + private void mergeWithNeighbours() { + if (this.isMergable()) { +- List list = this.level().getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate(0.5D, 0.0D, 0.5D), (itementity) -> { +- return itementity != this && itementity.isMergable(); ++ List list = this.level().getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate(0.5D, 0.0D, 0.5D), (entityitem) -> { ++ return entityitem != this && entityitem.isMergable(); + }); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- ItemEntity itementity = (ItemEntity) iterator.next(); ++ ItemEntity entityitem = (ItemEntity) iterator.next(); + +- if (itementity.isMergable()) { +- this.tryToMerge(itementity); ++ if (entityitem.isMergable()) { ++ this.tryToMerge(entityitem); + if (this.isRemoved()) { + break; + } +@@ -251,69 +262,77 @@ + return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < 6000 && itemstack.getCount() < itemstack.getMaxStackSize(); + } + +- private void tryToMerge(ItemEntity itementity) { ++ private void tryToMerge(ItemEntity itemEntity) { + ItemStack itemstack = this.getItem(); +- ItemStack itemstack1 = itementity.getItem(); ++ ItemStack itemstack1 = itemEntity.getItem(); + +- if (Objects.equals(this.target, itementity.target) && areMergable(itemstack, itemstack1)) { ++ if (Objects.equals(this.target, itemEntity.target) && areMergable(itemstack, itemstack1)) { + if (itemstack1.getCount() < itemstack.getCount()) { +- merge(this, itemstack, itementity, itemstack1); ++ merge(this, itemstack, itemEntity, itemstack1); + } else { +- merge(itementity, itemstack1, this, itemstack); ++ merge(itemEntity, itemstack1, this, itemstack); + } + + } + } + +- public static boolean areMergable(ItemStack itemstack, ItemStack itemstack1) { +- return !itemstack1.is(itemstack.getItem()) ? false : (itemstack1.getCount() + itemstack.getCount() > itemstack1.getMaxStackSize() ? false : (itemstack1.hasTag() ^ itemstack.hasTag() ? false : !itemstack1.hasTag() || itemstack1.getTag().equals(itemstack.getTag()))); ++ public static boolean areMergable(ItemStack destinationStack, ItemStack originStack) { ++ return !originStack.is(destinationStack.getItem()) ? false : (originStack.getCount() + destinationStack.getCount() > originStack.getMaxStackSize() ? false : (originStack.hasTag() ^ destinationStack.hasTag() ? false : !originStack.hasTag() || originStack.getTag().equals(destinationStack.getTag()))); + } + +- public static ItemStack merge(ItemStack itemstack, ItemStack itemstack1, int i) { +- int j = Math.min(Math.min(itemstack.getMaxStackSize(), i) - itemstack.getCount(), itemstack1.getCount()); +- ItemStack itemstack2 = itemstack.copyWithCount(itemstack.getCount() + j); ++ public static ItemStack merge(ItemStack destinationStack, ItemStack originStack, int amount) { ++ int j = Math.min(Math.min(destinationStack.getMaxStackSize(), amount) - destinationStack.getCount(), originStack.getCount()); ++ ItemStack itemstack2 = destinationStack.copyWithCount(destinationStack.getCount() + j); + +- itemstack1.shrink(j); ++ originStack.shrink(j); + return itemstack2; + } + +- private static void merge(ItemEntity itementity, ItemStack itemstack, ItemStack itemstack1) { +- ItemStack itemstack2 = merge(itemstack, itemstack1, 64); ++ private static void merge(ItemEntity destinationEntity, ItemStack destinationStack, ItemStack originStack) { ++ ItemStack itemstack2 = merge(destinationStack, originStack, 64); + +- itementity.setItem(itemstack2); ++ destinationEntity.setItem(itemstack2); + } + +- private static void merge(ItemEntity itementity, ItemStack itemstack, ItemEntity itementity1, ItemStack itemstack1) { +- merge(itementity, itemstack, itemstack1); +- itementity.pickupDelay = Math.max(itementity.pickupDelay, itementity1.pickupDelay); +- itementity.age = Math.min(itementity.age, itementity1.age); +- if (itemstack1.isEmpty()) { +- itementity1.discard(); ++ private static void merge(ItemEntity destinationEntity, ItemStack destinationStack, ItemEntity originEntity, ItemStack originStack) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callItemMergeEvent(originEntity, destinationEntity)) { ++ return; + } ++ // CraftBukkit end ++ merge(destinationEntity, destinationStack, originStack); ++ destinationEntity.pickupDelay = Math.max(destinationEntity.pickupDelay, originEntity.pickupDelay); ++ destinationEntity.age = Math.min(destinationEntity.age, originEntity.age); ++ if (originStack.isEmpty()) { ++ originEntity.discard(); ++ } + + } + + @Override +- @Override + public boolean fireImmune() { + return this.getItem().getItem().isFireResistant() || super.fireImmune(); + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- if (this.isInvulnerableTo(damagesource)) { ++ public boolean hurt(DamageSource source, float amount) { ++ if (this.isInvulnerableTo(source)) { + return false; +- } else if (!this.getItem().isEmpty() && this.getItem().is(Items.NETHER_STAR) && damagesource.is(DamageTypeTags.IS_EXPLOSION)) { ++ } else if (!this.getItem().isEmpty() && this.getItem().is(Items.NETHER_STAR) && source.is(DamageTypeTags.IS_EXPLOSION)) { + return false; +- } else if (!this.getItem().getItem().canBeHurtBy(damagesource)) { ++ } else if (!this.getItem().getItem().canBeHurtBy(source)) { + return false; + } else if (this.level().isClientSide) { + return true; + } else { ++ // CraftBukkit start ++ if (CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount)) { ++ return false; ++ } ++ // CraftBukkit end + this.markHurt(); +- this.health = (int) ((float) this.health - f); +- this.gameEvent(GameEvent.ENTITY_DAMAGE, damagesource.getEntity()); ++ this.health = (int) ((float) this.health - amount); ++ this.gameEvent(GameEvent.ENTITY_DAMAGE, source.getEntity()); + if (this.health <= 0) { + this.getItem().onDestroyed(this); + this.discard(); +@@ -324,46 +343,44 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- compoundtag.putShort("Health", (short) this.health); +- compoundtag.putShort("Age", (short) this.age); +- compoundtag.putShort("PickupDelay", (short) this.pickupDelay); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ compound.putShort("Health", (short) this.health); ++ compound.putShort("Age", (short) this.age); ++ compound.putShort("PickupDelay", (short) this.pickupDelay); + if (this.thrower != null) { +- compoundtag.putUUID("Thrower", this.thrower); ++ compound.putUUID("Thrower", this.thrower); + } + + if (this.target != null) { +- compoundtag.putUUID("Owner", this.target); ++ compound.putUUID("Owner", this.target); + } + + if (!this.getItem().isEmpty()) { +- compoundtag.put("Item", this.getItem().save(new CompoundTag())); ++ compound.put("Item", this.getItem().save(new CompoundTag())); + } + + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- this.health = compoundtag.getShort("Health"); +- this.age = compoundtag.getShort("Age"); +- if (compoundtag.contains("PickupDelay")) { +- this.pickupDelay = compoundtag.getShort("PickupDelay"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ this.health = compound.getShort("Health"); ++ this.age = compound.getShort("Age"); ++ if (compound.contains("PickupDelay")) { ++ this.pickupDelay = compound.getShort("PickupDelay"); + } + +- if (compoundtag.hasUUID("Owner")) { +- this.target = compoundtag.getUUID("Owner"); ++ if (compound.hasUUID("Owner")) { ++ this.target = compound.getUUID("Owner"); + } + +- if (compoundtag.hasUUID("Thrower")) { +- this.thrower = compoundtag.getUUID("Thrower"); ++ if (compound.hasUUID("Thrower")) { ++ this.thrower = compound.getUUID("Thrower"); + this.cachedThrower = null; + } + +- CompoundTag compoundtag1 = compoundtag.getCompound("Item"); ++ CompoundTag nbttagcompound1 = compound.getCompound("Item"); + +- this.setItem(ItemStack.of(compoundtag1)); ++ this.setItem(ItemStack.of(nbttagcompound1)); + if (this.getItem().isEmpty()) { + this.discard(); + } +@@ -371,46 +388,82 @@ + } + + @Override +- @Override +- public void playerTouch(Player player) { ++ public void playerTouch(net.minecraft.world.entity.player.Player entity) { + if (!this.level().isClientSide) { + ItemStack itemstack = this.getItem(); + Item item = itemstack.getItem(); + int i = itemstack.getCount(); + +- if (this.pickupDelay == 0 && (this.target == null || this.target.equals(player.getUUID())) && player.getInventory().add(itemstack)) { +- player.take(this, i); ++ // CraftBukkit start - fire PlayerPickupItemEvent ++ int canHold = entity.getInventory().canHold(itemstack); ++ int remaining = i - canHold; ++ ++ if (this.pickupDelay <= 0 && canHold > 0) { ++ itemstack.setCount(canHold); ++ // Call legacy event ++ PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent((Player) entity.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); ++ playerEvent.setCancelled(!playerEvent.getPlayer().getCanPickupItems()); ++ this.level().getCraftServer().getPluginManager().callEvent(playerEvent); ++ if (playerEvent.isCancelled()) { ++ itemstack.setCount(i); // SPIGOT-5294 - restore count ++ return; ++ } ++ ++ // Call newer event afterwards ++ EntityPickupItemEvent entityEvent = new EntityPickupItemEvent((Player) entity.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); ++ entityEvent.setCancelled(!entityEvent.getEntity().getCanPickupItems()); ++ this.level().getCraftServer().getPluginManager().callEvent(entityEvent); ++ if (entityEvent.isCancelled()) { ++ itemstack.setCount(i); // SPIGOT-5294 - restore count ++ return; ++ } ++ ++ // Update the ItemStack if it was changed in the event ++ ItemStack current = this.getItem(); ++ if (!itemstack.equals(current)) { ++ itemstack = current; ++ } else { ++ itemstack.setCount(canHold + remaining); // = i ++ } ++ ++ // Possibly < 0; fix here so we do not have to modify code below ++ this.pickupDelay = 0; ++ } else if (this.pickupDelay == 0) { ++ // ensure that the code below isn't triggered if canHold says we can't pick the items up ++ this.pickupDelay = -1; ++ } ++ // CraftBukkit end ++ ++ if (this.pickupDelay == 0 && (this.target == null || this.target.equals(entity.getUUID())) && entity.getInventory().add(itemstack)) { ++ entity.take(this, i); + if (itemstack.isEmpty()) { + this.discard(); + itemstack.setCount(i); + } + +- player.awardStat(Stats.ITEM_PICKED_UP.get(item), i); +- player.onItemPickup(this); ++ entity.awardStat(Stats.ITEM_PICKED_UP.get(item), i); ++ entity.onItemPickup(this); + } + + } + } + + @Override +- @Override + public Component getName() { +- Component component = this.getCustomName(); ++ Component ichatbasecomponent = this.getCustomName(); + +- return (Component) (component != null ? component : Component.translatable(this.getItem().getDescriptionId())); ++ return (Component) (ichatbasecomponent != null ? ichatbasecomponent : Component.translatable(this.getItem().getDescriptionId())); + } + + @Override +- @Override + public boolean isAttackable() { + return false; + } + + @Nullable + @Override +- @Override +- public Entity changeDimension(ServerLevel serverlevel) { +- Entity entity = super.changeDimension(serverlevel); ++ public Entity changeDimension(ServerLevel server) { ++ Entity entity = super.changeDimension(server); + + if (!this.level().isClientSide && entity instanceof ItemEntity) { + ((ItemEntity) entity).mergeWithNeighbours(); +@@ -423,22 +476,21 @@ + return (ItemStack) this.getEntityData().get(ItemEntity.DATA_ITEM); + } + +- public void setItem(ItemStack itemstack) { +- this.getEntityData().set(ItemEntity.DATA_ITEM, itemstack); ++ public void setItem(ItemStack stack) { ++ this.getEntityData().set(ItemEntity.DATA_ITEM, stack); + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- super.onSyncedDataUpdated(entitydataaccessor); +- if (ItemEntity.DATA_ITEM.equals(entitydataaccessor)) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ super.onSyncedDataUpdated(key); ++ if (ItemEntity.DATA_ITEM.equals(key)) { + this.getItem().setEntityRepresentation(this); + } + + } + +- public void setTarget(@Nullable UUID uuid) { +- this.target = uuid; ++ public void setTarget(@Nullable UUID target) { ++ this.target = target; + } + + public void setThrower(Entity entity) { +@@ -462,8 +514,8 @@ + this.pickupDelay = 32767; + } + +- public void setPickUpDelay(int i) { +- this.pickupDelay = i; ++ public void setPickUpDelay(int pickupDelay) { ++ this.pickupDelay = pickupDelay; + } + + public boolean hasPickUpDelay() { +@@ -483,8 +535,8 @@ + this.age = 5999; + } + +- public float getSpin(float f) { +- return ((float) this.getAge() + f) / 20.0F + this.bobOffs; ++ public float getSpin(float partialTicks) { ++ return ((float) this.getAge() + partialTicks) / 20.0F + this.bobOffs; + } + + public ItemEntity copy() { +@@ -492,13 +544,11 @@ + } + + @Override +- @Override + public SoundSource getSoundSource() { + return SoundSource.AMBIENT; + } + + @Override +- @Override + public float getVisualRotationYInDegrees() { + return 180.0F - this.getSpin(0.5F) / 6.2831855F * 360.0F; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/item/PrimedTnt.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/item/PrimedTnt.java.patch new file mode 100644 index 0000000000..505e77488a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/item/PrimedTnt.java.patch @@ -0,0 +1,198 @@ +--- a/net/minecraft/world/entity/item/PrimedTnt.java ++++ b/net/minecraft/world/entity/item/PrimedTnt.java +@@ -10,70 +10,73 @@ + import net.minecraft.network.syncher.SynchedEntityData; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.TraceableEntity; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end ++ + public class PrimedTnt extends Entity implements TraceableEntity { + + private static final EntityDataAccessor DATA_FUSE_ID = SynchedEntityData.defineId(PrimedTnt.class, EntityDataSerializers.INT); +- private static final EntityDataAccessor DATA_BLOCK_STATE_ID = SynchedEntityData.defineId(PrimedTnt.class, EntityDataSerializers.BLOCK_STATE); ++ private static final EntityDataAccessor DATA_BLOCK_STATE_ID = SynchedEntityData.defineId(PrimedTnt.class, EntityDataSerializers.BLOCK_STATE); + private static final int DEFAULT_FUSE_TIME = 80; + private static final String TAG_BLOCK_STATE = "block_state"; + public static final String TAG_FUSE = "fuse"; + @Nullable +- private LivingEntity owner; ++ public LivingEntity owner; ++ public float yield = 4; // CraftBukkit - add field ++ public boolean isIncendiary = false; // CraftBukkit - add field + +- public PrimedTnt(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public PrimedTnt(EntityType entityType, Level level) { ++ super(entityType, level); + this.blocksBuilding = true; + } + +- public PrimedTnt(Level level, double d0, double d1, double d2, @Nullable LivingEntity livingentity) { ++ public PrimedTnt(Level level, double x, double d1, double y, @Nullable LivingEntity entityliving) { + this(EntityType.TNT, level); +- this.setPos(d0, d1, d2); ++ this.setPos(x, d1, y); + double d3 = level.random.nextDouble() * 6.2831854820251465D; + + this.setDeltaMovement(-Math.sin(d3) * 0.02D, 0.20000000298023224D, -Math.cos(d3) * 0.02D); + this.setFuse(80); +- this.xo = d0; ++ this.xo = x; + this.yo = d1; +- this.zo = d2; +- this.owner = livingentity; ++ this.zo = y; ++ this.owner = entityliving; + } + + @Override +- @Override + protected void defineSynchedData() { + this.entityData.define(PrimedTnt.DATA_FUSE_ID, 80); + this.entityData.define(PrimedTnt.DATA_BLOCK_STATE_ID, Blocks.TNT.defaultBlockState()); + } + + @Override +- @Override + protected Entity.MovementEmission getMovementEmission() { + return Entity.MovementEmission.NONE; + } + + @Override +- @Override + public boolean isPickable() { + return !this.isRemoved(); + } + + @Override +- @Override + public void tick() { + if (!this.isNoGravity()) { + this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.04D, 0.0D)); + } + +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + this.setDeltaMovement(this.getDeltaMovement().scale(0.98D)); + if (this.onGround()) { + this.setDeltaMovement(this.getDeltaMovement().multiply(0.7D, -0.5D, 0.7D)); +@@ -83,10 +86,13 @@ + + this.setFuse(i); + if (i <= 0) { +- this.discard(); ++ // CraftBukkit start - Need to reverse the order of the explosion and the entity death so we have a location for the event ++ // this.discard(); + if (!this.level().isClientSide) { + this.explode(); + } ++ this.discard(); ++ // CraftBukkit end + } else { + this.updateInWaterStateAndDoFluidPushing(); + if (this.level().isClientSide) { +@@ -97,66 +103,66 @@ + } + + private void explode() { +- float f = 4.0F; ++ // CraftBukkit start ++ // float f = 4.0F; ++ ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent((org.bukkit.entity.Explosive)this.getBukkitEntity()); + +- this.level().explode(this, this.getX(), this.getY(0.0625D), this.getZ(), 4.0F, Level.ExplosionInteraction.TNT); ++ if (!event.isCancelled()) { ++ this.level().explode(this, this.getX(), this.getY(0.0625D), this.getZ(), event.getRadius(), event.getFire(), Level.a.TNT); ++ } ++ // CraftBukkit end + } + + @Override +- @Override +- protected void addAdditionalSaveData(CompoundTag compoundtag) { +- compoundtag.putShort("fuse", (short) this.getFuse()); +- compoundtag.put("block_state", NbtUtils.writeBlockState(this.getBlockState())); ++ protected void addAdditionalSaveData(CompoundTag compound) { ++ compound.putShort("fuse", (short) this.getFuse()); ++ compound.put("block_state", NbtUtils.writeBlockState(this.getBlockState())); + } + + @Override +- @Override +- protected void readAdditionalSaveData(CompoundTag compoundtag) { +- this.setFuse(compoundtag.getShort("fuse")); +- if (compoundtag.contains("block_state", 10)) { +- this.setBlockState(NbtUtils.readBlockState(this.level().holderLookup(Registries.BLOCK), compoundtag.getCompound("block_state"))); ++ protected void readAdditionalSaveData(CompoundTag compound) { ++ this.setFuse(compound.getShort("fuse")); ++ if (compound.contains("block_state", 10)) { ++ this.setBlockState(NbtUtils.readBlockState(this.level().holderLookup(Registries.BLOCK), compound.getCompound("block_state"))); + } + + } + + @Nullable + @Override +- @Override + public LivingEntity getOwner() { + return this.owner; + } + + @Override +- @Override + public void restoreFrom(Entity entity) { + super.restoreFrom(entity); + if (entity instanceof PrimedTnt) { +- PrimedTnt primedtnt = (PrimedTnt) entity; ++ PrimedTnt entitytntprimed = (PrimedTnt) entity; + +- this.owner = primedtnt.owner; ++ this.owner = entitytntprimed.owner; + } + + } + + @Override +- @Override +- protected float getEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.15F; + } + +- public void setFuse(int i) { +- this.entityData.set(PrimedTnt.DATA_FUSE_ID, i); ++ public void setFuse(int life) { ++ this.entityData.set(PrimedTnt.DATA_FUSE_ID, life); + } + + public int getFuse() { + return (Integer) this.entityData.get(PrimedTnt.DATA_FUSE_ID); + } + +- public void setBlockState(BlockState blockstate) { +- this.entityData.set(PrimedTnt.DATA_BLOCK_STATE_ID, blockstate); ++ public void setBlockState(IBlockData iblockdata) { ++ this.entityData.set(PrimedTnt.DATA_BLOCK_STATE_ID, iblockdata); + } + +- public BlockState getBlockState() { +- return (BlockState) this.entityData.get(PrimedTnt.DATA_BLOCK_STATE_ID); ++ public IBlockData getBlockState() { ++ return (IBlockData) this.entityData.get(PrimedTnt.DATA_BLOCK_STATE_ID); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/AbstractSkeleton.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/AbstractSkeleton.java.patch new file mode 100644 index 0000000000..c6647fe81c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/AbstractSkeleton.java.patch @@ -0,0 +1,224 @@ +--- a/net/minecraft/world/entity/monster/AbstractSkeleton.java ++++ b/net/minecraft/world/entity/monster/AbstractSkeleton.java +@@ -12,14 +12,14 @@ + import net.minecraft.world.DifficultyInstance; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; + import net.minecraft.world.entity.PathfinderMob; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.AvoidEntityGoal; +@@ -44,34 +44,31 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public abstract class AbstractSkeleton extends Monster implements RangedAttackMob { + + private final RangedBowAttackGoal bowGoal = new RangedBowAttackGoal<>(this, 1.0D, 20, 15.0F); + private final MeleeAttackGoal meleeGoal = new MeleeAttackGoal(this, 1.2D, false) { + @Override +- @Override + public void stop() { + super.stop(); + AbstractSkeleton.this.setAggressive(false); + } + + @Override +- @Override + public void start() { + super.start(); + AbstractSkeleton.this.setAggressive(true); + } + }; + +- protected AbstractSkeleton(EntityType entitytype, Level level) { +- super(entitytype, level); ++ protected AbstractSkeleton(EntityType entityType, Level level) { ++ super(entityType, level); + this.reassessWeaponGoal(); + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(2, new RestrictSunGoal(this)); + this.goalSelector.addGoal(3, new FleeSunGoal(this, 1.0D)); +@@ -90,21 +87,18 @@ + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(this.getStepSound(), 0.15F, 1.0F); + } + + abstract SoundEvent getStepSound(); + + @Override +- @Override +- public MobType getMobType() { +- return MobType.UNDEAD; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.UNDEAD; + } + + @Override +- @Override + public void aiStep() { + boolean flag = this.isSunBurnTick(); + +@@ -132,37 +126,34 @@ + } + + @Override +- @Override + public void rideTick() { + super.rideTick(); + Entity entity = this.getControlledVehicle(); + + if (entity instanceof PathfinderMob) { +- PathfinderMob pathfindermob = (PathfinderMob) entity; ++ PathfinderMob entitycreature = (PathfinderMob) entity; + +- this.yBodyRot = pathfindermob.yBodyRot; ++ this.yBodyRot = entitycreature.yBodyRot; + } + + } + + @Override +- @Override +- protected void populateDefaultEquipmentSlots(RandomSource randomsource, DifficultyInstance difficultyinstance) { +- super.populateDefaultEquipmentSlots(randomsource, difficultyinstance); ++ protected void populateDefaultEquipmentSlots(RandomSource random, DifficultyInstance difficulty) { ++ super.populateDefaultEquipmentSlots(random, difficulty); + this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.BOW)); + } + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- spawngroupdata = super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); +- RandomSource randomsource = serverlevelaccessor.getRandom(); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ spawnData = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ RandomSource randomsource = level.getRandom(); + +- this.populateDefaultEquipmentSlots(randomsource, difficultyinstance); +- this.populateDefaultEquipmentEnchantments(randomsource, difficultyinstance); ++ this.populateDefaultEquipmentSlots(randomsource, difficulty); ++ this.populateDefaultEquipmentEnchantments(randomsource, difficulty); + this.reassessWeaponGoal(); +- this.setCanPickUpLoot(randomsource.nextFloat() < 0.55F * difficultyinstance.getSpecialMultiplier()); ++ this.setCanPickUpLoot(randomsource.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); + if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { + LocalDate localdate = LocalDate.now(); + int i = localdate.get(ChronoField.DAY_OF_MONTH); +@@ -174,7 +165,7 @@ + } + } + +- return spawngroupdata; ++ return spawnData; + } + + public void reassessWeaponGoal() { +@@ -200,41 +191,48 @@ + } + + @Override +- @Override +- public void performRangedAttack(LivingEntity livingentity, float f) { ++ public void performRangedAttack(LivingEntity target, float distanceFactor) { + ItemStack itemstack = this.getProjectile(this.getItemInHand(ProjectileUtil.getWeaponHoldingHand(this, Items.BOW))); +- AbstractArrow abstractarrow = this.getArrow(itemstack, f); +- double d0 = livingentity.getX() - this.getX(); +- double d1 = livingentity.getY(0.3333333333333333D) - abstractarrow.getY(); +- double d2 = livingentity.getZ() - this.getZ(); ++ AbstractArrow entityarrow = this.getArrow(itemstack, distanceFactor); ++ double d0 = target.getX() - this.getX(); ++ double d1 = target.getY(0.3333333333333333D) - entityarrow.getY(); ++ double d2 = target.getZ() - this.getZ(); + double d3 = Math.sqrt(d0 * d0 + d2 * d2); + +- abstractarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level().getDifficulty().getId() * 4)); ++ entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level().getDifficulty().getId() * 4)); ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), null, entityarrow, net.minecraft.world.EnumHand.MAIN_HAND, 0.8F, true); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ ++ if (event.getProjectile() == entityarrow.getBukkitEntity()) { ++ this.level().addFreshEntity(entityarrow); ++ } ++ // CraftBukkit end + this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); +- this.level().addFreshEntity(abstractarrow); ++ // this.level().addFreshEntity(entityarrow); // CraftBukkit - moved up + } + +- protected AbstractArrow getArrow(ItemStack itemstack, float f) { +- return ProjectileUtil.getMobArrow(this, itemstack, f); ++ protected AbstractArrow getArrow(ItemStack arrowStack, float velocity) { ++ return ProjectileUtil.getMobArrow(this, arrowStack, velocity); + } + + @Override +- @Override +- public boolean canFireProjectileWeapon(ProjectileWeaponItem projectileweaponitem) { +- return projectileweaponitem == Items.BOW; ++ public boolean canFireProjectileWeapon(ProjectileWeaponItem projectileWeapon) { ++ return projectileWeapon == Items.BOW; + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); + this.reassessWeaponGoal(); + } + + @Override +- @Override +- public void setItemSlot(EquipmentSlot equipmentslot, ItemStack itemstack) { +- super.setItemSlot(equipmentslot, itemstack); ++ public void setItemSlot(EquipmentSlot slot, ItemStack stack) { ++ super.setItemSlot(slot, stack); + if (!this.level().isClientSide) { + this.reassessWeaponGoal(); + } +@@ -242,13 +240,11 @@ + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 1.74F; + } + + @Override +- @Override + protected float ridingOffset(Entity entity) { + return -0.7F; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/CaveSpider.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/CaveSpider.java.patch new file mode 100644 index 0000000000..439e539560 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/CaveSpider.java.patch @@ -0,0 +1,76 @@ +--- a/net/minecraft/world/entity/monster/CaveSpider.java ++++ b/net/minecraft/world/entity/monster/CaveSpider.java +@@ -8,11 +8,11 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.level.Level; +@@ -21,8 +21,8 @@ + + public class CaveSpider extends Spider { + +- public CaveSpider(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public CaveSpider(EntityType entityType, Level level) { ++ super(entityType, level); + } + + public static AttributeSupplier.Builder createCaveSpider() { +@@ -30,7 +30,6 @@ + } + + @Override +- @Override + public boolean doHurtTarget(Entity entity) { + if (super.doHurtTarget(entity)) { + if (entity instanceof LivingEntity) { +@@ -43,7 +42,7 @@ + } + + if (b0 > 0) { +- ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.POISON, b0 * 20, 0), this); ++ ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.POISON, b0 * 20, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + +@@ -55,25 +54,21 @@ + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- return spawngroupdata; ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ return spawnData; + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.45F; + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height, 0.0F); + } + + @Override +- @Override + protected float ridingOffset(Entity entity) { + return entity.getBbWidth() <= this.getBbWidth() ? -0.21875F : 0.0F; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Creeper.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Creeper.java.patch new file mode 100644 index 0000000000..8177e70fa5 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Creeper.java.patch @@ -0,0 +1,322 @@ +--- a/net/minecraft/world/entity/monster/Creeper.java ++++ b/net/minecraft/world/entity/monster/Creeper.java +@@ -12,7 +12,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.tags.ItemTags; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffectInstance; +@@ -39,27 +39,32 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end ++ + public class Creeper extends Monster implements PowerableMob { + + private static final EntityDataAccessor DATA_SWELL_DIR = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_IS_POWERED = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_IS_IGNITED = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.BOOLEAN); + private int oldSwell; +- private int swell; +- private int maxSwell = 30; +- private int explosionRadius = 3; ++ public int swell; ++ public int maxSwell = 30; ++ public int explosionRadius = 3; + private int droppedSkulls; + +- public Creeper(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Creeper(EntityType entityType, Level level) { ++ super(entityType, level); + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new FloatGoal(this)); + this.goalSelector.addGoal(2, new SwellGoal(this)); +@@ -78,17 +83,15 @@ + } + + @Override +- @Override + public int getMaxFallDistance() { + return this.getTarget() == null ? 3 : 3 + (int) (this.getHealth() - 1.0F); + } + + @Override +- @Override +- public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { +- boolean flag = super.causeFallDamage(f, f1, damagesource); ++ public boolean causeFallDamage(float fallDistance, float multiplier, DamageSource source) { ++ boolean flag = super.causeFallDamage(fallDistance, multiplier, source); + +- this.swell += (int) (f * 1.5F); ++ this.swell += (int) (fallDistance * 1.5F); + if (this.swell > this.maxSwell - 5) { + this.swell = this.maxSwell - 5; + } +@@ -97,7 +100,6 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Creeper.DATA_SWELL_DIR, -1); +@@ -106,39 +108,36 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); + if ((Boolean) this.entityData.get(Creeper.DATA_IS_POWERED)) { +- compoundtag.putBoolean("powered", true); ++ compound.putBoolean("powered", true); + } + +- compoundtag.putShort("Fuse", (short) this.maxSwell); +- compoundtag.putByte("ExplosionRadius", (byte) this.explosionRadius); +- compoundtag.putBoolean("ignited", this.isIgnited()); ++ compound.putShort("Fuse", (short) this.maxSwell); ++ compound.putByte("ExplosionRadius", (byte) this.explosionRadius); ++ compound.putBoolean("ignited", this.isIgnited()); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.entityData.set(Creeper.DATA_IS_POWERED, compoundtag.getBoolean("powered")); +- if (compoundtag.contains("Fuse", 99)) { +- this.maxSwell = compoundtag.getShort("Fuse"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.entityData.set(Creeper.DATA_IS_POWERED, compound.getBoolean("powered")); ++ if (compound.contains("Fuse", 99)) { ++ this.maxSwell = compound.getShort("Fuse"); + } + +- if (compoundtag.contains("ExplosionRadius", 99)) { +- this.explosionRadius = compoundtag.getByte("ExplosionRadius"); ++ if (compound.contains("ExplosionRadius", 99)) { ++ this.explosionRadius = compound.getByte("ExplosionRadius"); + } + +- if (compoundtag.getBoolean("ignited")) { ++ if (compound.getBoolean("ignited")) { + this.ignite(); + } + + } + + @Override +- @Override + public void tick() { + if (this.isAlive()) { + this.oldSwell = this.swell; +@@ -168,107 +167,119 @@ + } + + @Override +- @Override +- public void setTarget(@Nullable LivingEntity livingentity) { +- if (!(livingentity instanceof Goat)) { +- super.setTarget(livingentity); ++ public void setTarget(@Nullable LivingEntity target) { ++ if (!(target instanceof Goat)) { ++ super.setTarget(target); + } + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.CREEPER_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.CREEPER_DEATH; + } + + @Override +- @Override +- protected void dropCustomDeathLoot(DamageSource damagesource, int i, boolean flag) { +- super.dropCustomDeathLoot(damagesource, i, flag); +- Entity entity = damagesource.getEntity(); ++ protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { ++ super.dropCustomDeathLoot(source, looting, recentlyHit); ++ Entity entity = source.getEntity(); + + if (entity != this && entity instanceof Creeper) { +- Creeper creeper = (Creeper) entity; ++ Creeper entitycreeper = (Creeper) entity; + +- if (creeper.canDropMobsSkull()) { +- creeper.increaseDroppedSkulls(); +- this.spawnAtLocation((ItemLike) Items.CREEPER_HEAD); ++ if (entitycreeper.canDropMobsSkull()) { ++ entitycreeper.increaseDroppedSkulls(); ++ this.spawnAtLocation((IMaterial) Items.CREEPER_HEAD); + } + } + + } + + @Override +- @Override + public boolean doHurtTarget(Entity entity) { + return true; + } + + @Override +- @Override + public boolean isPowered() { + return (Boolean) this.entityData.get(Creeper.DATA_IS_POWERED); + } + +- public float getSwelling(float f) { +- return Mth.lerp(f, (float) this.oldSwell, (float) this.swell) / (float) (this.maxSwell - 2); ++ public float getSwelling(float partialTicks) { ++ return Mth.lerp(partialTicks, (float) this.oldSwell, (float) this.swell) / (float) (this.maxSwell - 2); + } + + public int getSwellDir() { + return (Integer) this.entityData.get(Creeper.DATA_SWELL_DIR); + } + +- public void setSwellDir(int i) { +- this.entityData.set(Creeper.DATA_SWELL_DIR, i); ++ public void setSwellDir(int state) { ++ this.entityData.set(Creeper.DATA_SWELL_DIR, state); + } + + @Override +- @Override +- public void thunderHit(ServerLevel serverlevel, LightningBolt lightningbolt) { +- super.thunderHit(serverlevel, lightningbolt); ++ public void thunderHit(ServerLevel level, LightningBolt lightning) { ++ super.thunderHit(level, lightning); ++ // CraftBukkit start ++ if (CraftEventFactory.callCreeperPowerEvent(this, lightning, org.bukkit.event.entity.CreeperPowerEvent.PowerCause.LIGHTNING).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.entityData.set(Creeper.DATA_IS_POWERED, true); + } + ++ // CraftBukkit start ++ public void setPowered(boolean powered) { ++ this.entityData.set(Creeper.DATA_IS_POWERED, powered); ++ } ++ // CraftBukkit end ++ + @Override +- @Override +- protected InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ protected InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (itemstack.is(ItemTags.CREEPER_IGNITERS)) { +- SoundEvent soundevent = itemstack.is(Items.FIRE_CHARGE) ? SoundEvents.FIRECHARGE_USE : SoundEvents.FLINTANDSTEEL_USE; ++ SoundEvent soundeffect = itemstack.is(Items.FIRE_CHARGE) ? SoundEvents.FIRECHARGE_USE : SoundEvents.FLINTANDSTEEL_USE; + +- this.level().playSound(player, this.getX(), this.getY(), this.getZ(), soundevent, this.getSoundSource(), 1.0F, this.random.nextFloat() * 0.4F + 0.8F); ++ this.level().playSound(player, this.getX(), this.getY(), this.getZ(), soundeffect, this.getSoundSource(), 1.0F, this.random.nextFloat() * 0.4F + 0.8F); + if (!this.level().isClientSide) { + this.ignite(); +- if (!itemstack.isDamageableItem()) { ++ if (itemstack.getItem().getMaxDamage() == 0) { // CraftBukkit - fix MC-264285: unbreakable flint and steels are completely consumed when igniting a creeper + itemstack.shrink(1); + } else { +- itemstack.hurtAndBreak(1, player, (player1) -> { +- player1.broadcastBreakEvent(interactionhand); ++ itemstack.hurtAndBreak(1, player, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(hand); + }); + } + } + + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { +- return super.mobInteract(player, interactionhand); ++ return super.mobInteract(player, hand); + } + } + +- private void explodeCreeper() { ++ public void explodeCreeper() { + if (!this.level().isClientSide) { + float f = this.isPowered() ? 2.0F : 1.0F; + ++ // CraftBukkit start ++ ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent(this, this.explosionRadius * f, false); ++ if (!event.isCancelled()) { ++ // CraftBukkit end + this.dead = true; +- this.level().explode(this, this.getX(), this.getY(), this.getZ(), (float) this.explosionRadius * f, Level.ExplosionInteraction.MOB); ++ this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.MOB); // CraftBukkit + this.discard(); + this.spawnLingeringCloud(); ++ // CraftBukkit start ++ } else { ++ swell = 0; ++ } ++ // CraftBukkit end + } + + } +@@ -277,22 +288,23 @@ + Collection collection = this.getActiveEffects(); + + if (!collection.isEmpty()) { +- AreaEffectCloud areaeffectcloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); ++ AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); + +- areaeffectcloud.setRadius(2.5F); +- areaeffectcloud.setRadiusOnUse(-0.5F); +- areaeffectcloud.setWaitTime(10); +- areaeffectcloud.setDuration(areaeffectcloud.getDuration() / 2); +- areaeffectcloud.setRadiusPerTick(-areaeffectcloud.getRadius() / (float) areaeffectcloud.getDuration()); ++ entityareaeffectcloud.setOwner(this); // CraftBukkit ++ entityareaeffectcloud.setRadius(2.5F); ++ entityareaeffectcloud.setRadiusOnUse(-0.5F); ++ entityareaeffectcloud.setWaitTime(10); ++ entityareaeffectcloud.setDuration(entityareaeffectcloud.getDuration() / 2); ++ entityareaeffectcloud.setRadiusPerTick(-entityareaeffectcloud.getRadius() / (float) entityareaeffectcloud.getDuration()); + Iterator iterator = collection.iterator(); + + while (iterator.hasNext()) { +- MobEffectInstance mobeffectinstance = (MobEffectInstance) iterator.next(); ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); + +- areaeffectcloud.addEffect(new MobEffectInstance(mobeffectinstance)); ++ entityareaeffectcloud.addEffect(new MobEffectInstance(mobeffect)); + } + +- this.level().addFreshEntity(areaeffectcloud); ++ this.level().addFreshEntity(entityareaeffectcloud, CreatureSpawnEvent.SpawnReason.EXPLOSION); // CraftBukkit + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Drowned.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Drowned.java.patch new file mode 100644 index 0000000000..df3f563a57 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Drowned.java.patch @@ -0,0 +1,509 @@ +--- a/net/minecraft/world/entity/monster/Drowned.java ++++ b/net/minecraft/world/entity/monster/Drowned.java +@@ -13,15 +13,15 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.world.Difficulty; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.PathfinderMob; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.MoveControl; + import net.minecraft.world.entity.ai.goal.Goal; +@@ -56,11 +56,11 @@ + + public static final float NAUTILUS_SHELL_CHANCE = 0.03F; + boolean searchingForLand; +- protected final WaterBoundPathNavigation waterNavigation; +- protected final GroundPathNavigation groundNavigation; ++ public final WaterBoundPathNavigation waterNavigation; ++ public final GroundPathNavigation groundNavigation; + +- public Drowned(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Drowned(EntityType entityType, Level level) { ++ super(entityType, level); + this.setMaxUpStep(1.0F); + this.moveControl = new Drowned.DrownedMoveControl(this); + this.setPathfindingMalus(BlockPathTypes.WATER, 0.0F); +@@ -69,7 +69,6 @@ + } + + @Override +- @Override + protected void addBehaviourGoals() { + this.goalSelector.addGoal(1, new Drowned.DrownedGoToWaterGoal(this, 1.0D)); + this.goalSelector.addGoal(2, new Drowned.DrownedTridentAttackGoal(this, 1.0D, 40, 10.0F)); +@@ -86,79 +85,70 @@ + } + + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- spawngroupdata = super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); +- if (this.getItemBySlot(EquipmentSlot.OFFHAND).isEmpty() && serverlevelaccessor.getRandom().nextFloat() < 0.03F) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ spawnData = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ if (this.getItemBySlot(EquipmentSlot.OFFHAND).isEmpty() && level.getRandom().nextFloat() < 0.03F) { + this.setItemSlot(EquipmentSlot.OFFHAND, new ItemStack(Items.NAUTILUS_SHELL)); + this.setGuaranteedDrop(EquipmentSlot.OFFHAND); + } + +- return spawngroupdata; ++ return spawnData; + } + +- public static boolean checkDrownedSpawnRules(EntityType entitytype, ServerLevelAccessor serverlevelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- if (!serverlevelaccessor.getFluidState(blockpos.below()).is(FluidTags.WATER) && !MobSpawnType.isSpawner(mobspawntype)) { ++ public static boolean checkDrownedSpawnRules(EntityType drowned, ServerLevelAccessor serverLevel, EnumMobSpawn mobSpawnType, BlockPos pos, RandomSource random) { ++ if (!serverLevel.getFluidState(pos.below()).is(FluidTags.WATER) && !EnumMobSpawn.isSpawner(mobSpawnType)) { + return false; + } else { +- Holder holder = serverlevelaccessor.getBiome(blockpos); +- boolean flag = serverlevelaccessor.getDifficulty() != Difficulty.PEACEFUL && (MobSpawnType.ignoresLightRequirements(mobspawntype) || isDarkEnoughToSpawn(serverlevelaccessor, blockpos, randomsource)) && (MobSpawnType.isSpawner(mobspawntype) || serverlevelaccessor.getFluidState(blockpos).is(FluidTags.WATER)); ++ Holder holder = serverLevel.getBiome(pos); ++ boolean flag = serverLevel.getDifficulty() != Difficulty.PEACEFUL && (EnumMobSpawn.ignoresLightRequirements(mobSpawnType) || isDarkEnoughToSpawn(serverLevel, pos, random)) && (EnumMobSpawn.isSpawner(mobSpawnType) || serverLevel.getFluidState(pos).is(FluidTags.WATER)); + +- return flag && MobSpawnType.isSpawner(mobspawntype) ? true : (holder.is(BiomeTags.MORE_FREQUENT_DROWNED_SPAWNS) ? randomsource.nextInt(15) == 0 && flag : randomsource.nextInt(40) == 0 && isDeepEnoughToSpawn(serverlevelaccessor, blockpos) && flag); ++ return flag && EnumMobSpawn.isSpawner(mobSpawnType) ? true : (holder.is(BiomeTags.MORE_FREQUENT_DROWNED_SPAWNS) ? random.nextInt(15) == 0 && flag : random.nextInt(40) == 0 && isDeepEnoughToSpawn(serverLevel, pos) && flag); + } + } + +- private static boolean isDeepEnoughToSpawn(LevelAccessor levelaccessor, BlockPos blockpos) { +- return blockpos.getY() < levelaccessor.getSeaLevel() - 5; ++ private static boolean isDeepEnoughToSpawn(LevelAccessor level, BlockPos pos) { ++ return pos.getY() < level.getSeaLevel() - 5; + } + + @Override +- @Override + protected boolean supportsBreakDoorGoal() { + return false; + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return this.isInWater() ? SoundEvents.DROWNED_AMBIENT_WATER : SoundEvents.DROWNED_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return this.isInWater() ? SoundEvents.DROWNED_HURT_WATER : SoundEvents.DROWNED_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return this.isInWater() ? SoundEvents.DROWNED_DEATH_WATER : SoundEvents.DROWNED_DEATH; + } + + @Override +- @Override + protected SoundEvent getStepSound() { + return SoundEvents.DROWNED_STEP; + } + + @Override +- @Override + protected SoundEvent getSwimSound() { + return SoundEvents.DROWNED_SWIM; + } + + @Override +- @Override + protected ItemStack getSkull() { + return ItemStack.EMPTY; + } + + @Override +- @Override +- protected void populateDefaultEquipmentSlots(RandomSource randomsource, DifficultyInstance difficultyinstance) { +- if ((double) randomsource.nextFloat() > 0.9D) { +- int i = randomsource.nextInt(16); ++ protected void populateDefaultEquipmentSlots(RandomSource random, DifficultyInstance difficulty) { ++ if ((double) random.nextFloat() > 0.9D) { ++ int i = random.nextInt(16); + + if (i < 10) { + this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.TRIDENT)); +@@ -170,29 +160,25 @@ + } + + @Override +- @Override +- protected boolean canReplaceCurrentItem(ItemStack itemstack, ItemStack itemstack1) { +- return itemstack1.is(Items.NAUTILUS_SHELL) ? false : (itemstack1.is(Items.TRIDENT) ? (itemstack.is(Items.TRIDENT) ? itemstack.getDamageValue() < itemstack1.getDamageValue() : false) : (itemstack.is(Items.TRIDENT) ? true : super.canReplaceCurrentItem(itemstack, itemstack1))); ++ protected boolean canReplaceCurrentItem(ItemStack candidate, ItemStack existing) { ++ return existing.is(Items.NAUTILUS_SHELL) ? false : (existing.is(Items.TRIDENT) ? (candidate.is(Items.TRIDENT) ? candidate.getDamageValue() < existing.getDamageValue() : false) : (candidate.is(Items.TRIDENT) ? true : super.canReplaceCurrentItem(candidate, existing))); + } + + @Override +- @Override + protected boolean convertsInWater() { + return false; + } + + @Override +- @Override +- public boolean checkSpawnObstruction(LevelReader levelreader) { +- return levelreader.isUnobstructed(this); ++ public boolean checkSpawnObstruction(LevelReader level) { ++ return level.isUnobstructed(this); + } + +- public boolean okTarget(@Nullable LivingEntity livingentity) { +- return livingentity != null ? !this.level().isDay() || livingentity.isInWater() : false; ++ public boolean okTarget(@Nullable LivingEntity target) { ++ return target != null ? !this.level().isDay() || target.isInWater() : false; + } + + @Override +- @Override + public boolean isPushedByFluid() { + return !this.isSwimming(); + } +@@ -201,27 +187,25 @@ + if (this.searchingForLand) { + return true; + } else { +- LivingEntity livingentity = this.getTarget(); ++ LivingEntity entityliving = this.getTarget(); + +- return livingentity != null && livingentity.isInWater(); ++ return entityliving != null && entityliving.isInWater(); + } + } + + @Override +- @Override +- public void travel(Vec3 vec3) { ++ public void travel(Vec3 travelVector) { + if (this.isControlledByLocalInstance() && this.isInWater() && this.wantsToSwim()) { +- this.moveRelative(0.01F, vec3); +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.moveRelative(0.01F, travelVector); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + this.setDeltaMovement(this.getDeltaMovement().scale(0.9D)); + } else { +- super.travel(vec3); ++ super.travel(travelVector); + } + + } + + @Override +- @Override + public void updateSwimming() { + if (!this.level().isClientSide) { + if (this.isEffectiveAi() && this.isInWater() && this.wantsToSwim()) { +@@ -236,19 +220,18 @@ + } + + @Override +- @Override + public boolean isVisuallySwimming() { + return this.isSwimming(); + } + + protected boolean closeToNextPos() { +- Path path = this.getNavigation().getPath(); ++ Path pathentity = this.getNavigation().getPath(); + +- if (path != null) { +- BlockPos blockpos = path.getTarget(); ++ if (pathentity != null) { ++ BlockPos blockposition = pathentity.getTarget(); + +- if (blockpos != null) { +- double d0 = this.distanceToSqr((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ()); ++ if (blockposition != null) { ++ double d0 = this.distanceToSqr((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()); + + if (d0 < 4.0D) { + return true; +@@ -260,21 +243,20 @@ + } + + @Override +- @Override +- public void performRangedAttack(LivingEntity livingentity, float f) { +- ThrownTrident throwntrident = new ThrownTrident(this.level(), this, new ItemStack(Items.TRIDENT)); +- double d0 = livingentity.getX() - this.getX(); +- double d1 = livingentity.getY(0.3333333333333333D) - throwntrident.getY(); +- double d2 = livingentity.getZ() - this.getZ(); ++ public void performRangedAttack(LivingEntity target, float distanceFactor) { ++ ThrownTrident entitythrowntrident = new ThrownTrident(this.level(), this, this.getItemInHand(net.minecraft.world.entity.projectile.ProjectileUtil.getWeaponHoldingHand(this, Items.TRIDENT))); // CraftBukkit - Use Trident in hand like skeletons (SPIGOT-7025) ++ double d0 = target.getX() - this.getX(); ++ double d1 = target.getY(0.3333333333333333D) - entitythrowntrident.getY(); ++ double d2 = target.getZ() - this.getZ(); + double d3 = Math.sqrt(d0 * d0 + d2 * d2); + +- throwntrident.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level().getDifficulty().getId() * 4)); ++ entitythrowntrident.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level().getDifficulty().getId() * 4)); + this.playSound(SoundEvents.DROWNED_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); +- this.level().addFreshEntity(throwntrident); ++ this.level().addFreshEntity(entitythrowntrident); + } + +- public void setSearchingForLand(boolean flag) { +- this.searchingForLand = flag; ++ public void setSearchingForLand(boolean searchingForLand) { ++ this.searchingForLand = searchingForLand; + } + + private static class DrownedMoveControl extends MoveControl { +@@ -287,12 +269,11 @@ + } + + @Override +- @Override + public void tick() { +- LivingEntity livingentity = this.drowned.getTarget(); ++ LivingEntity entityliving = this.drowned.getTarget(); + + if (this.drowned.wantsToSwim() && this.drowned.isInWater()) { +- if (livingentity != null && livingentity.getY() > this.drowned.getY() || this.drowned.searchingForLand) { ++ if (entityliving != null && entityliving.getY() > this.drowned.getY() || this.drowned.searchingForLand) { + this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(0.0D, 0.002D, 0.0D)); + } + +@@ -336,42 +317,39 @@ + private final double speedModifier; + private final Level level; + +- public DrownedGoToWaterGoal(PathfinderMob pathfindermob, double d0) { +- this.mob = pathfindermob; +- this.speedModifier = d0; +- this.level = pathfindermob.level(); +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ public DrownedGoToWaterGoal(PathfinderMob mob, double speedModifier) { ++ this.mob = mob; ++ this.speedModifier = speedModifier; ++ this.level = mob.level(); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +- @Override + public boolean canUse() { + if (!this.level.isDay()) { + return false; + } else if (this.mob.isInWater()) { + return false; + } else { +- Vec3 vec3 = this.getWaterPos(); ++ Vec3 vec3d = this.getWaterPos(); + +- if (vec3 == null) { ++ if (vec3d == null) { + return false; + } else { +- this.wantedX = vec3.x; +- this.wantedY = vec3.y; +- this.wantedZ = vec3.z; ++ this.wantedX = vec3d.x; ++ this.wantedY = vec3d.y; ++ this.wantedZ = vec3d.z; + return true; + } + } + } + + @Override +- @Override + public boolean canContinueToUse() { + return !this.mob.getNavigation().isDone(); + } + + @Override +- @Override + public void start() { + this.mob.getNavigation().moveTo(this.wantedX, this.wantedY, this.wantedZ, this.speedModifier); + } +@@ -379,13 +357,13 @@ + @Nullable + private Vec3 getWaterPos() { + RandomSource randomsource = this.mob.getRandom(); +- BlockPos blockpos = this.mob.blockPosition(); ++ BlockPos blockposition = this.mob.blockPosition(); + + for (int i = 0; i < 10; ++i) { +- BlockPos blockpos1 = blockpos.offset(randomsource.nextInt(20) - 10, 2 - randomsource.nextInt(8), randomsource.nextInt(20) - 10); ++ BlockPos blockposition1 = blockposition.offset(randomsource.nextInt(20) - 10, 2 - randomsource.nextInt(8), randomsource.nextInt(20) - 10); + +- if (this.level.getBlockState(blockpos1).is(Blocks.WATER)) { +- return Vec3.atBottomCenterOf(blockpos1); ++ if (this.level.getBlockState(blockposition1).is(Blocks.WATER)) { ++ return Vec3.atBottomCenterOf(blockposition1); + } + } + +@@ -397,27 +375,24 @@ + + private final Drowned drowned; + +- public DrownedTridentAttackGoal(RangedAttackMob rangedattackmob, double d0, int i, float f) { +- super(rangedattackmob, d0, i, f); +- this.drowned = (Drowned) rangedattackmob; ++ public DrownedTridentAttackGoal(RangedAttackMob rangedAttackMob, double speedModifier, int i, float attackInterval) { ++ super(rangedAttackMob, speedModifier, i, attackInterval); ++ this.drowned = (Drowned) rangedAttackMob; + } + + @Override +- @Override + public boolean canUse() { + return super.canUse() && this.drowned.getMainHandItem().is(Items.TRIDENT); + } + + @Override +- @Override + public void start() { + super.start(); + this.drowned.setAggressive(true); +- this.drowned.startUsingItem(InteractionHand.MAIN_HAND); ++ this.drowned.startUsingItem(EnumHand.MAIN_HAND); + } + + @Override +- @Override + public void stop() { + super.stop(); + this.drowned.stopUsingItem(); +@@ -429,19 +404,17 @@ + + private final Drowned drowned; + +- public DrownedAttackGoal(Drowned drowned, double d0, boolean flag) { +- super((Zombie) drowned, d0, flag); ++ public DrownedAttackGoal(Drowned drowned, double speedModifier, boolean flag) { ++ super((Zombie) drowned, speedModifier, flag); + this.drowned = drowned; + } + + @Override +- @Override + public boolean canUse() { + return super.canUse() && this.drowned.okTarget(this.drowned.getTarget()); + } + + @Override +- @Override + public boolean canContinueToUse() { + return super.canContinueToUse() && this.drowned.okTarget(this.drowned.getTarget()); + } +@@ -451,33 +424,29 @@ + + private final Drowned drowned; + +- public DrownedGoToBeachGoal(Drowned drowned, double d0) { +- super(drowned, d0, 8, 2); ++ public DrownedGoToBeachGoal(Drowned drowned, double speedModifier) { ++ super(drowned, speedModifier, 8, 2); + this.drowned = drowned; + } + + @Override +- @Override + public boolean canUse() { + return super.canUse() && !this.drowned.level().isDay() && this.drowned.isInWater() && this.drowned.getY() >= (double) (this.drowned.level().getSeaLevel() - 3); + } + + @Override +- @Override + public boolean canContinueToUse() { + return super.canContinueToUse(); + } + + @Override +- @Override +- protected boolean isValidTarget(LevelReader levelreader, BlockPos blockpos) { +- BlockPos blockpos1 = blockpos.above(); ++ protected boolean isValidTarget(LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.above(); + +- return levelreader.isEmptyBlock(blockpos1) && levelreader.isEmptyBlock(blockpos1.above()) ? levelreader.getBlockState(blockpos).entityCanStandOn(levelreader, blockpos, this.drowned) : false; ++ return level.isEmptyBlock(blockposition1) && level.isEmptyBlock(blockposition1.above()) ? level.getBlockState(pos).entityCanStandOn(level, pos, this.drowned) : false; + } + + @Override +- @Override + public void start() { + this.drowned.setSearchingForLand(false); + this.drowned.navigation = this.drowned.groundNavigation; +@@ -485,7 +454,6 @@ + } + + @Override +- @Override + public void stop() { + super.stop(); + } +@@ -498,49 +466,44 @@ + private final int seaLevel; + private boolean stuck; + +- public DrownedSwimUpGoal(Drowned drowned, double d0, int i) { ++ public DrownedSwimUpGoal(Drowned drowned, double speedModifier, int i) { + this.drowned = drowned; +- this.speedModifier = d0; ++ this.speedModifier = speedModifier; + this.seaLevel = i; + } + + @Override +- @Override + public boolean canUse() { + return !this.drowned.level().isDay() && this.drowned.isInWater() && this.drowned.getY() < (double) (this.seaLevel - 2); + } + + @Override +- @Override + public boolean canContinueToUse() { + return this.canUse() && !this.stuck; + } + + @Override +- @Override + public void tick() { + if (this.drowned.getY() < (double) (this.seaLevel - 1) && (this.drowned.getNavigation().isDone() || this.drowned.closeToNextPos())) { +- Vec3 vec3 = DefaultRandomPos.getPosTowards(this.drowned, 4, 8, new Vec3(this.drowned.getX(), (double) (this.seaLevel - 1), this.drowned.getZ()), 1.5707963705062866D); ++ Vec3 vec3d = DefaultRandomPos.getPosTowards(this.drowned, 4, 8, new Vec3(this.drowned.getX(), (double) (this.seaLevel - 1), this.drowned.getZ()), 1.5707963705062866D); + +- if (vec3 == null) { ++ if (vec3d == null) { + this.stuck = true; + return; + } + +- this.drowned.getNavigation().moveTo(vec3.x, vec3.y, vec3.z, this.speedModifier); ++ this.drowned.getNavigation().moveTo(vec3d.x, vec3d.y, vec3d.z, this.speedModifier); + } + + } + + @Override +- @Override + public void start() { + this.drowned.setSearchingForLand(true); + this.stuck = false; + } + + @Override +- @Override + public void stop() { + this.drowned.setSearchingForLand(false); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/ElderGuardian.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/ElderGuardian.java.patch new file mode 100644 index 0000000000..405c41eae7 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/ElderGuardian.java.patch @@ -0,0 +1,75 @@ +--- a/net/minecraft/world/entity/monster/ElderGuardian.java ++++ b/net/minecraft/world/entity/monster/ElderGuardian.java +@@ -27,8 +27,8 @@ + private static final int EFFECT_AMPLIFIER = 2; + private static final int EFFECT_DISPLAY_LIMIT = 1200; + +- public ElderGuardian(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public ElderGuardian(EntityType entityType, Level level) { ++ super(entityType, level); + this.setPersistenceRequired(); + if (this.randomStrollGoal != null) { + this.randomStrollGoal.setInterval(400); +@@ -41,45 +41,39 @@ + } + + @Override +- @Override + public int getAttackDuration() { + return 60; + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return this.isInWaterOrBubble() ? SoundEvents.ELDER_GUARDIAN_AMBIENT : SoundEvents.ELDER_GUARDIAN_AMBIENT_LAND; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return this.isInWaterOrBubble() ? SoundEvents.ELDER_GUARDIAN_HURT : SoundEvents.ELDER_GUARDIAN_HURT_LAND; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return this.isInWaterOrBubble() ? SoundEvents.ELDER_GUARDIAN_DEATH : SoundEvents.ELDER_GUARDIAN_DEATH_LAND; + } + + @Override +- @Override + protected SoundEvent getFlopSound() { + return SoundEvents.ELDER_GUARDIAN_FLOP; + } + + @Override +- @Override + protected void customServerAiStep() { + super.customServerAiStep(); + if ((this.tickCount + this.getId()) % 1200 == 0) { +- MobEffectInstance mobeffectinstance = new MobEffectInstance(MobEffects.DIG_SLOWDOWN, 6000, 2); +- List list = MobEffectUtil.addEffectToPlayersAround((ServerLevel) this.level(), this, this.position(), 50.0D, mobeffectinstance, 1200); ++ MobEffectInstance mobeffect = new MobEffectInstance(MobEffects.DIG_SLOWDOWN, 6000, 2); ++ List list = MobEffectUtil.addEffectToPlayersAround((ServerLevel) this.level(), this, this.position(), 50.0D, mobeffect, 1200, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + +- list.forEach((serverplayer) -> { +- serverplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, this.isSilent() ? 0.0F : 1.0F)); ++ list.forEach((entityplayer) -> { ++ entityplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, this.isSilent() ? 0.0F : 1.0F)); + }); + } + +@@ -90,8 +84,7 @@ + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height + 0.353125F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.353125F * f, 0.0F); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/EnderMan.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/EnderMan.java.patch new file mode 100644 index 0000000000..637fe4721d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/EnderMan.java.patch @@ -0,0 +1,613 @@ +--- a/net/minecraft/world/entity/monster/EnderMan.java ++++ b/net/minecraft/world/entity/monster/EnderMan.java +@@ -30,10 +30,10 @@ + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.NeutralMob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -61,7 +61,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.level.storage.loot.LootParams; +@@ -71,13 +71,18 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end ++ + public class EnderMan extends Monster implements NeutralMob { + + private static final UUID SPEED_MODIFIER_ATTACKING_UUID = UUID.fromString("020E0DFB-87AE-4653-9556-831010E291A0"); + private static final AttributeModifier SPEED_MODIFIER_ATTACKING = new AttributeModifier(EnderMan.SPEED_MODIFIER_ATTACKING_UUID, "Attacking speed boost", 0.15000000596046448D, AttributeModifier.Operation.ADDITION); + private static final int DELAY_BETWEEN_CREEPY_STARE_SOUND = 400; + private static final int MIN_DEAGGRESSION_TIME = 600; +- private static final EntityDataAccessor> DATA_CARRY_STATE = SynchedEntityData.defineId(EnderMan.class, EntityDataSerializers.OPTIONAL_BLOCK_STATE); ++ private static final EntityDataAccessor> DATA_CARRY_STATE = SynchedEntityData.defineId(EnderMan.class, EntityDataSerializers.OPTIONAL_BLOCK_STATE); + private static final EntityDataAccessor DATA_CREEPY = SynchedEntityData.defineId(EnderMan.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_STARED_AT = SynchedEntityData.defineId(EnderMan.class, EntityDataSerializers.BOOLEAN); + private int lastStareSound = Integer.MIN_VALUE; +@@ -87,14 +92,13 @@ + @Nullable + private UUID persistentAngerTarget; + +- public EnderMan(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public EnderMan(EntityType entityType, Level level) { ++ super(entityType, level); + this.setMaxUpStep(1.0F); + this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(1, new EnderMan.EndermanFreezeWhenLookedAt(this)); +@@ -115,28 +119,37 @@ + } + + @Override ++ public void setTarget(@Nullable LivingEntity livingEntity) { ++ // CraftBukkit start - fire event ++ setTarget(livingEntity, EntityTargetEvent.TargetReason.UNKNOWN, true); ++ } ++ + @Override +- public void setTarget(@Nullable LivingEntity livingentity) { +- super.setTarget(livingentity); +- AttributeInstance attributeinstance = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ public boolean setTarget(LivingEntity entityliving, EntityTargetEvent.TargetReason reason, boolean fireEvent) { ++ if (!super.setTarget(entityliving, reason, fireEvent)) { ++ return false; ++ } ++ entityliving = getTarget(); ++ // CraftBukkit end ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); + +- if (livingentity == null) { ++ if (entityliving == null) { + this.targetChangeTime = 0; + this.entityData.set(EnderMan.DATA_CREEPY, false); + this.entityData.set(EnderMan.DATA_STARED_AT, false); +- attributeinstance.removeModifier(EnderMan.SPEED_MODIFIER_ATTACKING.getId()); ++ attributemodifiable.removeModifier(EnderMan.SPEED_MODIFIER_ATTACKING.getId()); + } else { + this.targetChangeTime = this.tickCount; + this.entityData.set(EnderMan.DATA_CREEPY, true); +- if (!attributeinstance.hasModifier(EnderMan.SPEED_MODIFIER_ATTACKING)) { +- attributeinstance.addTransientModifier(EnderMan.SPEED_MODIFIER_ATTACKING); ++ if (!attributemodifiable.hasModifier(EnderMan.SPEED_MODIFIER_ATTACKING)) { ++ attributemodifiable.addTransientModifier(EnderMan.SPEED_MODIFIER_ATTACKING); + } + } ++ return true; + + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(EnderMan.DATA_CARRY_STATE, Optional.empty()); +@@ -145,32 +158,27 @@ + } + + @Override +- @Override + public void startPersistentAngerTimer() { + this.setRemainingPersistentAngerTime(EnderMan.PERSISTENT_ANGER_TIME.sample(this.random)); + } + + @Override +- @Override +- public void setRemainingPersistentAngerTime(int i) { +- this.remainingPersistentAngerTime = i; ++ public void setRemainingPersistentAngerTime(int time) { ++ this.remainingPersistentAngerTime = time; + } + + @Override +- @Override + public int getRemainingPersistentAngerTime() { + return this.remainingPersistentAngerTime; + } + + @Override +- @Override +- public void setPersistentAngerTarget(@Nullable UUID uuid) { +- this.persistentAngerTarget = uuid; ++ public void setPersistentAngerTarget(@Nullable UUID target) { ++ this.persistentAngerTarget = target; + } + + @Nullable + @Override +- @Override + public UUID getPersistentAngerTarget() { + return this.persistentAngerTarget; + } +@@ -186,43 +194,40 @@ + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- if (EnderMan.DATA_CREEPY.equals(entitydataaccessor) && this.hasBeenStaredAt() && this.level().isClientSide) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ if (EnderMan.DATA_CREEPY.equals(key) && this.hasBeenStaredAt() && this.level().isClientSide) { + this.playStareSound(); + } + +- super.onSyncedDataUpdated(entitydataaccessor); ++ super.onSyncedDataUpdated(key); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- BlockState blockstate = this.getCarriedBlock(); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ IBlockData iblockdata = this.getCarriedBlock(); + +- if (blockstate != null) { +- compoundtag.put("carriedBlockState", NbtUtils.writeBlockState(blockstate)); ++ if (iblockdata != null) { ++ compound.put("carriedBlockState", NbtUtils.writeBlockState(iblockdata)); + } + +- this.addPersistentAngerSaveData(compoundtag); ++ this.addPersistentAngerSaveData(compound); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- BlockState blockstate = null; ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ IBlockData iblockdata = null; + +- if (compoundtag.contains("carriedBlockState", 10)) { +- blockstate = NbtUtils.readBlockState(this.level().holderLookup(Registries.BLOCK), compoundtag.getCompound("carriedBlockState")); +- if (blockstate.isAir()) { +- blockstate = null; ++ if (compound.contains("carriedBlockState", 10)) { ++ iblockdata = NbtUtils.readBlockState(this.level().holderLookup(Registries.BLOCK), compound.getCompound("carriedBlockState")); ++ if (iblockdata.isAir()) { ++ iblockdata = null; + } + } + +- this.setCarriedBlock(blockstate); +- this.readPersistentAngerSaveData(this.level(), compoundtag); ++ this.setCarriedBlock(iblockdata); ++ this.readPersistentAngerSaveData(this.level(), compound); + } + + boolean isLookingAtMe(Player player) { +@@ -231,31 +236,28 @@ + if (itemstack.is(Blocks.CARVED_PUMPKIN.asItem())) { + return false; + } else { +- Vec3 vec3 = player.getViewVector(1.0F).normalize(); +- Vec3 vec31 = new Vec3(this.getX() - player.getX(), this.getEyeY() - player.getEyeY(), this.getZ() - player.getZ()); +- double d0 = vec31.length(); ++ Vec3 vec3d = player.getViewVector(1.0F).normalize(); ++ Vec3 vec3d1 = new Vec3(this.getX() - player.getX(), this.getEyeY() - player.getEyeY(), this.getZ() - player.getZ()); ++ double d0 = vec3d1.length(); + +- vec31 = vec31.normalize(); +- double d1 = vec3.dot(vec31); ++ vec3d1 = vec3d1.normalize(); ++ double d1 = vec3d.dot(vec3d1); + + return d1 > 1.0D - 0.025D / d0 ? player.hasLineOfSight(this) : false; + } + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 2.55F; + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height - 0.09375F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.09375F * f, 0.0F); + } + + @Override +- @Override + public void aiStep() { + if (this.level().isClientSide) { + for (int i = 0; i < 2; ++i) { +@@ -272,13 +274,11 @@ + } + + @Override +- @Override + public boolean isSensitiveToWater() { + return true; + } + + @Override +- @Override + protected void customServerAiStep() { + if (this.level().isDay() && this.tickCount >= this.targetChangeTime + 600) { + float f = this.getLightLevelDependentMagicValue(); +@@ -292,7 +292,7 @@ + super.customServerAiStep(); + } + +- protected boolean teleport() { ++ public boolean teleport() { + if (!this.level().isClientSide() && this.isAlive()) { + double d0 = this.getX() + (this.random.nextDouble() - 0.5D) * 64.0D; + double d1 = this.getY() + (double) (this.random.nextInt(64) - 32); +@@ -304,35 +304,35 @@ + } + } + +- boolean teleportTowards(Entity entity) { +- Vec3 vec3 = new Vec3(this.getX() - entity.getX(), this.getY(0.5D) - entity.getEyeY(), this.getZ() - entity.getZ()); ++ public boolean teleportTowards(Entity target) { ++ Vec3 vec3d = new Vec3(this.getX() - target.getX(), this.getY(0.5D) - target.getEyeY(), this.getZ() - target.getZ()); + +- vec3 = vec3.normalize(); ++ vec3d = vec3d.normalize(); + double d0 = 16.0D; +- double d1 = this.getX() + (this.random.nextDouble() - 0.5D) * 8.0D - vec3.x * 16.0D; +- double d2 = this.getY() + (double) (this.random.nextInt(16) - 8) - vec3.y * 16.0D; +- double d3 = this.getZ() + (this.random.nextDouble() - 0.5D) * 8.0D - vec3.z * 16.0D; ++ double d1 = this.getX() + (this.random.nextDouble() - 0.5D) * 8.0D - vec3d.x * 16.0D; ++ double d2 = this.getY() + (double) (this.random.nextInt(16) - 8) - vec3d.y * 16.0D; ++ double d3 = this.getZ() + (this.random.nextDouble() - 0.5D) * 8.0D - vec3d.z * 16.0D; + + return this.teleport(d1, d2, d3); + } + +- private boolean teleport(double d0, double d1, double d2) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(d0, d1, d2); ++ private boolean teleport(double x, double d1, double y) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(x, d1, y); + +- while (blockpos_mutableblockpos.getY() > this.level().getMinBuildHeight() && !this.level().getBlockState(blockpos_mutableblockpos).blocksMotion()) { +- blockpos_mutableblockpos.move(Direction.DOWN); ++ while (blockposition_mutableblockposition.getY() > this.level().getMinBuildHeight() && !this.level().getBlockState(blockposition_mutableblockposition).blocksMotion()) { ++ blockposition_mutableblockposition.move(Direction.DOWN); + } + +- BlockState blockstate = this.level().getBlockState(blockpos_mutableblockpos); +- boolean flag = blockstate.blocksMotion(); +- boolean flag1 = blockstate.getFluidState().is(FluidTags.WATER); ++ IBlockData iblockdata = this.level().getBlockState(blockposition_mutableblockposition); ++ boolean flag = iblockdata.blocksMotion(); ++ boolean flag1 = iblockdata.getFluidState().is(FluidTags.WATER); + + if (flag && !flag1) { +- Vec3 vec3 = this.position(); +- boolean flag2 = this.randomTeleport(d0, d1, d2, true); ++ Vec3 vec3d = this.position(); ++ boolean flag2 = this.randomTeleport(x, d1, y, true); + + if (flag2) { +- this.level().gameEvent(GameEvent.TELEPORT, vec3, GameEvent.Context.of((Entity) this)); ++ this.level().gameEvent(GameEvent.TELEPORT, vec3d, GameEvent.Context.of((Entity) this)); + if (!this.isSilent()) { + this.level().playSound((Player) null, this.xo, this.yo, this.zo, SoundEvents.ENDERMAN_TELEPORT, this.getSoundSource(), 1.0F, 1.0F); + this.playSound(SoundEvents.ENDERMAN_TELEPORT, 1.0F, 1.0F); +@@ -346,35 +346,31 @@ + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return this.isCreepy() ? SoundEvents.ENDERMAN_SCREAM : SoundEvents.ENDERMAN_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.ENDERMAN_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.ENDERMAN_DEATH; + } + + @Override +- @Override +- protected void dropCustomDeathLoot(DamageSource damagesource, int i, boolean flag) { +- super.dropCustomDeathLoot(damagesource, i, flag); +- BlockState blockstate = this.getCarriedBlock(); ++ protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { ++ super.dropCustomDeathLoot(source, looting, recentlyHit); ++ IBlockData iblockdata = this.getCarriedBlock(); + +- if (blockstate != null) { ++ if (iblockdata != null) { + ItemStack itemstack = new ItemStack(Items.DIAMOND_AXE); + + itemstack.enchant(Enchantments.SILK_TOUCH, 1); +- LootParams.Builder lootparams_builder = (new LootParams.Builder((ServerLevel) this.level())).withParameter(LootContextParams.ORIGIN, this.position()).withParameter(LootContextParams.TOOL, itemstack).withOptionalParameter(LootContextParams.THIS_ENTITY, this); +- List list = blockstate.getDrops(lootparams_builder); ++ LootParams.Builder lootparams_a = (new LootParams.Builder((ServerLevel) this.level())).withParameter(LootContextParams.ORIGIN, this.position()).withParameter(LootContextParams.TOOL, itemstack).withOptionalParameter(LootContextParams.THIS_ENTITY, this); ++ List list = iblockdata.getDrops(lootparams_a); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +@@ -386,33 +382,32 @@ + + } + +- public void setCarriedBlock(@Nullable BlockState blockstate) { +- this.entityData.set(EnderMan.DATA_CARRY_STATE, Optional.ofNullable(blockstate)); ++ public void setCarriedBlock(@Nullable IBlockData state) { ++ this.entityData.set(EnderMan.DATA_CARRY_STATE, Optional.ofNullable(state)); + } + + @Nullable +- public BlockState getCarriedBlock() { +- return (BlockState) ((Optional) this.entityData.get(EnderMan.DATA_CARRY_STATE)).orElse((Object) null); ++ public IBlockData getCarriedBlock() { ++ return (IBlockData) ((Optional) this.entityData.get(EnderMan.DATA_CARRY_STATE)).orElse((Object) null); + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- if (this.isInvulnerableTo(damagesource)) { ++ public boolean hurt(DamageSource source, float amount) { ++ if (this.isInvulnerableTo(source)) { + return false; + } else { +- boolean flag = damagesource.getDirectEntity() instanceof ThrownPotion; ++ boolean flag = source.getDirectEntity() instanceof ThrownPotion; + boolean flag1; + +- if (!damagesource.is(DamageTypeTags.IS_PROJECTILE) && !flag) { +- flag1 = super.hurt(damagesource, f); +- if (!this.level().isClientSide() && !(damagesource.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0) { ++ if (!source.is(DamageTypeTags.IS_PROJECTILE) && !flag) { ++ flag1 = super.hurt(source, amount); ++ if (!this.level().isClientSide() && !(source.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0) { + this.teleport(); + } + + return flag1; + } else { +- flag1 = flag && this.hurtWithCleanWater(damagesource, (ThrownPotion) damagesource.getDirectEntity(), f); ++ flag1 = flag && this.hurtWithCleanWater(source, (ThrownPotion) source.getDirectEntity(), amount); + + for (int i = 0; i < 64; ++i) { + if (this.teleport()) { +@@ -425,13 +420,13 @@ + } + } + +- private boolean hurtWithCleanWater(DamageSource damagesource, ThrownPotion thrownpotion, float f) { +- ItemStack itemstack = thrownpotion.getItem(); +- Potion potion = PotionUtils.getPotion(itemstack); ++ private boolean hurtWithCleanWater(DamageSource source, ThrownPotion potion, float amount) { ++ ItemStack itemstack = potion.getItem(); ++ Potion potionregistry = PotionUtils.getPotion(itemstack); + List list = PotionUtils.getMobEffects(itemstack); +- boolean flag = potion == Potions.WATER && list.isEmpty(); ++ boolean flag = potionregistry == Potions.WATER && list.isEmpty(); + +- return flag ? super.hurt(damagesource, f) : false; ++ return flag ? super.hurt(source, amount) : false; + } + + public boolean isCreepy() { +@@ -447,7 +442,6 @@ + } + + @Override +- @Override + public boolean requiresCustomPersistence() { + return super.requiresCustomPersistence() || this.getCarriedBlock() != null; + } +@@ -460,11 +454,10 @@ + + public EndermanFreezeWhenLookedAt(EnderMan enderman) { + this.enderman = enderman; +- this.setFlags(EnumSet.of(Goal.Flag.JUMP, Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.JUMP, Goal.Type.MOVE)); + } + + @Override +- @Override + public boolean canUse() { + this.target = this.enderman.getTarget(); + if (!(this.target instanceof Player)) { +@@ -477,13 +470,11 @@ + } + + @Override +- @Override + public void start() { + this.enderman.getNavigation().stop(); + } + + @Override +- @Override + public void tick() { + this.enderman.getLookControl().setLookAt(this.target.getX(), this.target.getEyeY(), this.target.getZ()); + } +@@ -498,38 +489,38 @@ + } + + @Override +- @Override + public boolean canUse() { + return this.enderman.getCarriedBlock() == null ? false : (!this.enderman.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? false : this.enderman.getRandom().nextInt(reducedTickDelay(2000)) == 0); + } + + @Override +- @Override + public void tick() { + RandomSource randomsource = this.enderman.getRandom(); +- Level level = this.enderman.level(); ++ Level world = this.enderman.level(); + int i = Mth.floor(this.enderman.getX() - 1.0D + randomsource.nextDouble() * 2.0D); + int j = Mth.floor(this.enderman.getY() + randomsource.nextDouble() * 2.0D); + int k = Mth.floor(this.enderman.getZ() - 1.0D + randomsource.nextDouble() * 2.0D); +- BlockPos blockpos = new BlockPos(i, j, k); +- BlockState blockstate = level.getBlockState(blockpos); +- BlockPos blockpos1 = blockpos.below(); +- BlockState blockstate1 = level.getBlockState(blockpos1); +- BlockState blockstate2 = this.enderman.getCarriedBlock(); ++ BlockPos blockposition = new BlockPos(i, j, k); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ BlockPos blockposition1 = blockposition.below(); ++ IBlockData iblockdata1 = world.getBlockState(blockposition1); ++ IBlockData iblockdata2 = this.enderman.getCarriedBlock(); + +- if (blockstate2 != null) { +- blockstate2 = Block.updateFromNeighbourShapes(blockstate2, this.enderman.level(), blockpos); +- if (this.canPlaceBlock(level, blockpos, blockstate2, blockstate, blockstate1, blockpos1)) { +- level.setBlock(blockpos, blockstate2, 3); +- level.gameEvent(GameEvent.BLOCK_PLACE, blockpos, GameEvent.Context.of(this.enderman, blockstate2)); +- this.enderman.setCarriedBlock((BlockState) null); ++ if (iblockdata2 != null) { ++ iblockdata2 = Block.updateFromNeighbourShapes(iblockdata2, this.enderman.level(), blockposition); ++ if (this.canPlaceBlock(world, blockposition, iblockdata2, iblockdata, iblockdata1, blockposition1)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockposition, iblockdata2)) { // CraftBukkit - Place event ++ world.setBlock(blockposition, iblockdata2, 3); ++ world.gameEvent(GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(this.enderman, iblockdata2)); ++ this.enderman.setCarriedBlock((IBlockData) null); ++ } // CraftBukkit + } + + } + } + +- private boolean canPlaceBlock(Level level, BlockPos blockpos, BlockState blockstate, BlockState blockstate1, BlockState blockstate2, BlockPos blockpos1) { +- return blockstate1.isAir() && !blockstate2.isAir() && !blockstate2.is(Blocks.BEDROCK) && blockstate2.isCollisionShapeFullBlock(level, blockpos1) && blockstate.canSurvive(level, blockpos) && level.getEntities(this.enderman, AABB.unitCubeFromLowerCorner(Vec3.atLowerCornerOf(blockpos))).isEmpty(); ++ private boolean canPlaceBlock(Level level, BlockPos destinationPos, IBlockData carriedState, IBlockData destinationState, IBlockData belowDestinationState, BlockPos belowDestinationPos) { ++ return destinationState.isAir() && !belowDestinationState.isAir() && !belowDestinationState.is(Blocks.BEDROCK) && belowDestinationState.isCollisionShapeFullBlock(level, belowDestinationPos) && carriedState.canSurvive(level, destinationPos) && level.getEntities(this.enderman, AABB.unitCubeFromLowerCorner(Vec3.atLowerCornerOf(destinationPos))).isEmpty(); + } + } + +@@ -542,30 +533,30 @@ + } + + @Override +- @Override + public boolean canUse() { + return this.enderman.getCarriedBlock() != null ? false : (!this.enderman.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? false : this.enderman.getRandom().nextInt(reducedTickDelay(20)) == 0); + } + + @Override +- @Override + public void tick() { + RandomSource randomsource = this.enderman.getRandom(); +- Level level = this.enderman.level(); ++ Level world = this.enderman.level(); + int i = Mth.floor(this.enderman.getX() - 2.0D + randomsource.nextDouble() * 4.0D); + int j = Mth.floor(this.enderman.getY() + randomsource.nextDouble() * 3.0D); + int k = Mth.floor(this.enderman.getZ() - 2.0D + randomsource.nextDouble() * 4.0D); +- BlockPos blockpos = new BlockPos(i, j, k); +- BlockState blockstate = level.getBlockState(blockpos); +- Vec3 vec3 = new Vec3((double) this.enderman.getBlockX() + 0.5D, (double) j + 0.5D, (double) this.enderman.getBlockZ() + 0.5D); +- Vec3 vec31 = new Vec3((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D); +- BlockHitResult blockhitresult = level.clip(new ClipContext(vec3, vec31, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.enderman)); +- boolean flag = blockhitresult.getBlockPos().equals(blockpos); ++ BlockPos blockposition = new BlockPos(i, j, k); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ Vec3 vec3d = new Vec3((double) this.enderman.getBlockX() + 0.5D, (double) j + 0.5D, (double) this.enderman.getBlockZ() + 0.5D); ++ Vec3 vec3d1 = new Vec3((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D); ++ BlockHitResult movingobjectpositionblock = world.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.enderman)); ++ boolean flag = movingobjectpositionblock.getBlockPos().equals(blockposition); + +- if (blockstate.is(BlockTags.ENDERMAN_HOLDABLE) && flag) { +- level.removeBlock(blockpos, false); +- level.gameEvent(GameEvent.BLOCK_DESTROY, blockpos, GameEvent.Context.of(this.enderman, blockstate)); +- this.enderman.setCarriedBlock(blockstate.getBlock().defaultBlockState()); ++ if (iblockdata.is(BlockTags.ENDERMAN_HOLDABLE) && flag) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockposition, Blocks.AIR.defaultBlockState())) { // CraftBukkit - Place event ++ world.removeBlock(blockposition, false); ++ world.gameEvent(GameEvent.BLOCK_DESTROY, blockposition, GameEvent.Context.of(this.enderman, iblockdata)); ++ this.enderman.setCarriedBlock(iblockdata.getBlock().defaultBlockState()); ++ } // CraftBukkit + } + + } +@@ -582,24 +573,22 @@ + private final TargetingConditions continueAggroTargetConditions = TargetingConditions.forCombat().ignoreLineOfSight(); + private final Predicate isAngerInducing; + +- public EndermanLookForPlayerGoal(EnderMan enderman, @Nullable Predicate predicate) { +- super(enderman, Player.class, 10, false, false, predicate); ++ public EndermanLookForPlayerGoal(EnderMan enderman, @Nullable Predicate selectionPredicate) { ++ super(enderman, Player.class, 10, false, false, selectionPredicate); + this.enderman = enderman; +- this.isAngerInducing = (livingentity) -> { +- return (enderman.isLookingAtMe((Player) livingentity) || enderman.isAngryAt(livingentity)) && !enderman.hasIndirectPassenger(livingentity); ++ this.isAngerInducing = (entityliving) -> { ++ return (enderman.isLookingAtMe((Player) entityliving) || enderman.isAngryAt(entityliving)) && !enderman.hasIndirectPassenger(entityliving); + }; + this.startAggroTargetConditions = TargetingConditions.forCombat().range(this.getFollowDistance()).selector(this.isAngerInducing); + } + + @Override +- @Override + public boolean canUse() { + this.pendingTarget = this.enderman.level().getNearestPlayer(this.startAggroTargetConditions, this.enderman); + return this.pendingTarget != null; + } + + @Override +- @Override + public void start() { + this.aggroTime = this.adjustedTickDelay(5); + this.teleportTime = 0; +@@ -607,14 +596,12 @@ + } + + @Override +- @Override + public void stop() { + this.pendingTarget = null; + super.stop(); + } + + @Override +- @Override + public boolean canContinueToUse() { + if (this.pendingTarget != null) { + if (!this.isAngerInducing.test(this.pendingTarget)) { +@@ -639,7 +626,6 @@ + } + + @Override +- @Override + public void tick() { + if (this.enderman.getTarget() == null) { + super.setTarget((LivingEntity) null); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Evoker.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Evoker.java.patch new file mode 100644 index 0000000000..1a3b8ee1a8 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Evoker.java.patch @@ -0,0 +1,379 @@ +--- a/net/minecraft/world/entity/monster/Evoker.java ++++ b/net/minecraft/world/entity/monster/Evoker.java +@@ -12,11 +12,11 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.AvoidEntityGoal; +@@ -35,7 +35,7 @@ + import net.minecraft.world.item.DyeColor; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.VoxelShape; +@@ -46,13 +46,12 @@ + @Nullable + private Sheep wololoTarget; + +- public Evoker(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Evoker(EntityType entityType, Level level) { ++ super(entityType, level); + this.xpReward = 10; + } + + @Override +- @Override + protected void registerGoals() { + super.registerGoals(); + this.goalSelector.addGoal(0, new FloatGoal(this)); +@@ -75,61 +74,52 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); + } + + @Override +- @Override + public SoundEvent getCelebrateSound() { + return SoundEvents.EVOKER_CELEBRATE; + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); + } + + @Override +- @Override + protected void customServerAiStep() { + super.customServerAiStep(); + } + + @Override +- @Override + public boolean isAlliedTo(Entity entity) { +- return entity == null ? false : (entity == this ? true : (super.isAlliedTo(entity) ? true : (entity instanceof Vex ? this.isAlliedTo((Entity) ((Vex) entity).getOwner()) : (entity instanceof LivingEntity && ((LivingEntity) entity).getMobType() == MobType.ILLAGER ? this.getTeam() == null && entity.getTeam() == null : false)))); ++ return entity == null ? false : (entity == this ? true : (super.isAlliedTo(entity) ? true : (entity instanceof Vex ? this.isAlliedTo((Entity) ((Vex) entity).getOwner()) : (entity instanceof LivingEntity && ((LivingEntity) entity).getMobType() == EnumMonsterType.ILLAGER ? this.getTeam() == null && entity.getTeam() == null : false)))); + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.EVOKER_AMBIENT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.EVOKER_DEATH; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.EVOKER_HURT; + } + +- void setWololoTarget(@Nullable Sheep sheep) { +- this.wololoTarget = sheep; ++ void setWololoTarget(@Nullable Sheep wololoTarget) { ++ this.wololoTarget = wololoTarget; + } + + @Nullable +@@ -138,14 +128,12 @@ + } + + @Override +- @Override + protected SoundEvent getCastingSoundEvent() { + return SoundEvents.EVOKER_CAST_SPELL; + } + + @Override +- @Override +- public void applyRaidBuffs(int i, boolean flag) {} ++ public void applyRaidBuffs(int wave, boolean unusedFalse) {} + + private class EvokerCastingSpellGoal extends SpellcasterIllager.SpellcasterCastingSpellGoal { + +@@ -154,7 +142,6 @@ + } + + @Override +- @Override + public void tick() { + if (Evoker.this.getTarget() != null) { + Evoker.this.getLookControl().setLookAt(Evoker.this.getTarget(), (float) Evoker.this.getMaxHeadYRot(), (float) Evoker.this.getMaxHeadXRot()); +@@ -174,7 +161,6 @@ + } + + @Override +- @Override + public boolean canUse() { + if (!super.canUse()) { + return false; +@@ -186,52 +172,47 @@ + } + + @Override +- @Override + protected int getCastingTime() { + return 100; + } + + @Override +- @Override + protected int getCastingInterval() { + return 340; + } + + @Override +- @Override + protected void performSpellCasting() { +- ServerLevel serverlevel = (ServerLevel) Evoker.this.level(); +- PlayerTeam playerteam = Evoker.this.getTeam(); ++ ServerLevel worldserver = (ServerLevel) Evoker.this.level(); ++ PlayerTeam scoreboardteam = Evoker.this.getTeam(); + + for (int i = 0; i < 3; ++i) { +- BlockPos blockpos = Evoker.this.blockPosition().offset(-2 + Evoker.this.random.nextInt(5), 1, -2 + Evoker.this.random.nextInt(5)); +- Vex vex = (Vex) EntityType.VEX.create(Evoker.this.level()); ++ BlockPos blockposition = Evoker.this.blockPosition().offset(-2 + Evoker.this.random.nextInt(5), 1, -2 + Evoker.this.random.nextInt(5)); ++ Vex entityvex = (Vex) EntityType.VEX.create(Evoker.this.level()); + +- if (vex != null) { +- vex.moveTo(blockpos, 0.0F, 0.0F); +- vex.finalizeSpawn(serverlevel, Evoker.this.level().getCurrentDifficultyAt(blockpos), MobSpawnType.MOB_SUMMONED, (SpawnGroupData) null, (CompoundTag) null); +- vex.setOwner(Evoker.this); +- vex.setBoundOrigin(blockpos); +- vex.setLimitedLife(20 * (30 + Evoker.this.random.nextInt(90))); +- if (playerteam != null) { +- serverlevel.getScoreboard().addPlayerToTeam(vex.getScoreboardName(), playerteam); ++ if (entityvex != null) { ++ entityvex.moveTo(blockposition, 0.0F, 0.0F); ++ entityvex.finalizeSpawn(worldserver, Evoker.this.level().getCurrentDifficultyAt(blockposition), EnumMobSpawn.MOB_SUMMONED, (GroupDataEntity) null, (CompoundTag) null); ++ entityvex.setOwner(Evoker.this); ++ entityvex.setBoundOrigin(blockposition); ++ entityvex.setLimitedLife(20 * (30 + Evoker.this.random.nextInt(90))); ++ if (scoreboardteam != null) { ++ worldserver.getScoreboard().addPlayerToTeam(entityvex.getScoreboardName(), scoreboardteam); + } + +- serverlevel.addFreshEntityWithPassengers(vex); +- serverlevel.gameEvent(GameEvent.ENTITY_PLACE, blockpos, GameEvent.Context.of((Entity) Evoker.this)); ++ worldserver.addFreshEntityWithPassengers(entityvex, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPELL); // CraftBukkit - Add SpawnReason ++ worldserver.gameEvent(GameEvent.ENTITY_PLACE, blockposition, GameEvent.Context.of((Entity) Evoker.this)); + } + } + + } + + @Override +- @Override + protected SoundEvent getSpellPrepareSound() { + return SoundEvents.EVOKER_PREPARE_SUMMON; + } + + @Override +- @Override + protected SpellcasterIllager.IllagerSpell getSpell() { + return SpellcasterIllager.IllagerSpell.SUMMON_VEX; + } +@@ -244,27 +225,24 @@ + } + + @Override +- @Override + protected int getCastingTime() { + return 40; + } + + @Override +- @Override + protected int getCastingInterval() { + return 100; + } + + @Override +- @Override + protected void performSpellCasting() { +- LivingEntity livingentity = Evoker.this.getTarget(); +- double d0 = Math.min(livingentity.getY(), Evoker.this.getY()); +- double d1 = Math.max(livingentity.getY(), Evoker.this.getY()) + 1.0D; +- float f = (float) Mth.atan2(livingentity.getZ() - Evoker.this.getZ(), livingentity.getX() - Evoker.this.getX()); ++ LivingEntity entityliving = Evoker.this.getTarget(); ++ double d0 = Math.min(entityliving.getY(), Evoker.this.getY()); ++ double d1 = Math.max(entityliving.getY(), Evoker.this.getY()) + 1.0D; ++ float f = (float) Mth.atan2(entityliving.getZ() - Evoker.this.getZ(), entityliving.getX() - Evoker.this.getX()); + int i; + +- if (Evoker.this.distanceToSqr((Entity) livingentity) < 9.0D) { ++ if (Evoker.this.distanceToSqr((Entity) entityliving) < 9.0D) { + float f1; + + for (i = 0; i < 5; ++i) { +@@ -287,19 +265,19 @@ + + } + +- private void createSpellEntity(double d0, double d1, double d2, double d3, float f, int i) { +- BlockPos blockpos = BlockPos.containing(d0, d3, d1); ++ private void createSpellEntity(double x, double d1, double z, double d3, float minY, int i) { ++ BlockPos blockposition = BlockPos.containing(x, d3, d1); + boolean flag = false; + double d4 = 0.0D; + + do { +- BlockPos blockpos1 = blockpos.below(); +- BlockState blockstate = Evoker.this.level().getBlockState(blockpos1); ++ BlockPos blockposition1 = blockposition.below(); ++ IBlockData iblockdata = Evoker.this.level().getBlockState(blockposition1); + +- if (blockstate.isFaceSturdy(Evoker.this.level(), blockpos1, Direction.UP)) { +- if (!Evoker.this.level().isEmptyBlock(blockpos)) { +- BlockState blockstate1 = Evoker.this.level().getBlockState(blockpos); +- VoxelShape voxelshape = blockstate1.getCollisionShape(Evoker.this.level(), blockpos); ++ if (iblockdata.isFaceSturdy(Evoker.this.level(), blockposition1, Direction.UP)) { ++ if (!Evoker.this.level().isEmptyBlock(blockposition)) { ++ IBlockData iblockdata1 = Evoker.this.level().getBlockState(blockposition); ++ VoxelShape voxelshape = iblockdata1.getCollisionShape(Evoker.this.level(), blockposition); + + if (!voxelshape.isEmpty()) { + d4 = voxelshape.max(Direction.Axis.Y); +@@ -310,24 +288,22 @@ + break; + } + +- blockpos = blockpos.below(); +- } while (blockpos.getY() >= Mth.floor(d2) - 1); ++ blockposition = blockposition.below(); ++ } while (blockposition.getY() >= Mth.floor(z) - 1); + + if (flag) { +- Evoker.this.level().addFreshEntity(new EvokerFangs(Evoker.this.level(), d0, (double) blockpos.getY() + d4, d1, f, i, Evoker.this)); +- Evoker.this.level().gameEvent(GameEvent.ENTITY_PLACE, new Vec3(d0, (double) blockpos.getY() + d4, d1), GameEvent.Context.of((Entity) Evoker.this)); ++ Evoker.this.level().addFreshEntity(new EvokerFangs(Evoker.this.level(), x, (double) blockposition.getY() + d4, d1, minY, i, Evoker.this)); ++ Evoker.this.level().gameEvent(GameEvent.ENTITY_PLACE, new Vec3(x, (double) blockposition.getY() + d4, d1), GameEvent.Context.of((Entity) Evoker.this)); + } + + } + + @Override +- @Override + protected SoundEvent getSpellPrepareSound() { + return SoundEvents.EVOKER_PREPARE_ATTACK; + } + + @Override +- @Override + protected SpellcasterIllager.IllagerSpell getSpell() { + return SpellcasterIllager.IllagerSpell.FANGS; + } +@@ -335,8 +311,8 @@ + + public class EvokerWololoSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { + +- private final TargetingConditions wololoTargeting = TargetingConditions.forNonCombat().range(16.0D).selector((livingentity) -> { +- return ((Sheep) livingentity).getColor() == DyeColor.BLUE; ++ private final TargetingConditions wololoTargeting = TargetingConditions.forNonCombat().range(16.0D).selector((entityliving) -> { ++ return ((Sheep) entityliving).getColor() == DyeColor.BLUE; + }); + + public EvokerWololoSpellGoal() { +@@ -344,7 +320,6 @@ + } + + @Override +- @Override + public boolean canUse() { + if (Evoker.this.getTarget() != null) { + return false; +@@ -367,55 +342,47 @@ + } + + @Override +- @Override + public boolean canContinueToUse() { + return Evoker.this.getWololoTarget() != null && this.attackWarmupDelay > 0; + } + + @Override +- @Override + public void stop() { + super.stop(); + Evoker.this.setWololoTarget((Sheep) null); + } + + @Override +- @Override + protected void performSpellCasting() { +- Sheep sheep = Evoker.this.getWololoTarget(); ++ Sheep entitysheep = Evoker.this.getWololoTarget(); + +- if (sheep != null && sheep.isAlive()) { +- sheep.setColor(DyeColor.RED); ++ if (entitysheep != null && entitysheep.isAlive()) { ++ entitysheep.setColor(DyeColor.RED); + } + + } + + @Override +- @Override + protected int getCastWarmupTime() { + return 40; + } + + @Override +- @Override + protected int getCastingTime() { + return 60; + } + + @Override +- @Override + protected int getCastingInterval() { + return 140; + } + + @Override +- @Override + protected SoundEvent getSpellPrepareSound() { + return SoundEvents.EVOKER_PREPARE_WOLOLO; + } + + @Override +- @Override + protected SpellcasterIllager.IllagerSpell getSpell() { + return SpellcasterIllager.IllagerSpell.WOLOLO; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Ghast.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Ghast.java.patch new file mode 100644 index 0000000000..5a986ee4cf --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Ghast.java.patch @@ -0,0 +1,395 @@ +--- a/net/minecraft/world/entity/monster/Ghast.java ++++ b/net/minecraft/world/entity/monster/Ghast.java +@@ -15,12 +15,12 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.FlyingMob; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.MoveControl; +@@ -34,25 +34,24 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Ghast extends FlyingMob implements Enemy { ++public class Ghast extends FlyingMob implements IMonster { + + private static final EntityDataAccessor DATA_IS_CHARGING = SynchedEntityData.defineId(Ghast.class, EntityDataSerializers.BOOLEAN); + private int explosionPower = 1; + +- public Ghast(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Ghast(EntityType entityType, Level level) { ++ super(entityType, level); + this.xpReward = 5; + this.moveControl = new Ghast.GhastMoveControl(this); + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(5, new Ghast.RandomFloatAroundGoal(this)); + this.goalSelector.addGoal(7, new Ghast.GhastLookGoal(this)); + this.goalSelector.addGoal(7, new Ghast.GhastShootFireballGoal(this)); +- this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (livingentity) -> { +- return Math.abs(livingentity.getY() - this.getY()) <= 4.0D; ++ this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (entityliving) -> { ++ return Math.abs(entityliving.getY() - this.getY()) <= 4.0D; + })); + } + +@@ -60,8 +59,8 @@ + return (Boolean) this.entityData.get(Ghast.DATA_IS_CHARGING); + } + +- public void setCharging(boolean flag) { +- this.entityData.set(Ghast.DATA_IS_CHARGING, flag); ++ public void setCharging(boolean charging) { ++ this.entityData.set(Ghast.DATA_IS_CHARGING, charging); + } + + public int getExplosionPower() { +@@ -69,34 +68,30 @@ + } + + @Override +- @Override + protected boolean shouldDespawnInPeaceful() { + return true; + } + +- private static boolean isReflectedFireball(DamageSource damagesource) { +- return damagesource.getDirectEntity() instanceof LargeFireball && damagesource.getEntity() instanceof Player; ++ private static boolean isReflectedFireball(DamageSource damageSource) { ++ return damageSource.getDirectEntity() instanceof LargeFireball && damageSource.getEntity() instanceof Player; + } + + @Override +- @Override +- public boolean isInvulnerableTo(DamageSource damagesource) { +- return !isReflectedFireball(damagesource) && super.isInvulnerableTo(damagesource); ++ public boolean isInvulnerableTo(DamageSource source) { ++ return !isReflectedFireball(source) && super.isInvulnerableTo(source); + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- if (isReflectedFireball(damagesource)) { +- super.hurt(damagesource, 1000.0F); ++ public boolean hurt(DamageSource source, float amount) { ++ if (isReflectedFireball(source)) { ++ super.hurt(source, 1000.0F); + return true; + } else { +- return this.isInvulnerableTo(damagesource) ? false : super.hurt(damagesource, f); ++ return this.isInvulnerableTo(source) ? false : super.hurt(source, amount); + } + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Ghast.DATA_IS_CHARGING, false); +@@ -107,77 +102,66 @@ + } + + @Override +- @Override + public SoundSource getSoundSource() { + return SoundSource.HOSTILE; + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.GHAST_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.GHAST_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.GHAST_DEATH; + } + + @Override +- @Override + protected float getSoundVolume() { + return 5.0F; + } + +- public static boolean checkGhastSpawnRules(EntityType entitytype, LevelAccessor levelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- return levelaccessor.getDifficulty() != Difficulty.PEACEFUL && randomsource.nextInt(20) == 0 && checkMobSpawnRules(entitytype, levelaccessor, mobspawntype, blockpos, randomsource); ++ public static boolean checkGhastSpawnRules(EntityType ghast, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ return level.getDifficulty() != Difficulty.PEACEFUL && random.nextInt(20) == 0 && checkMobSpawnRules(ghast, level, spawnType, pos, random); + } + + @Override +- @Override + public int getMaxSpawnClusterSize() { + return 1; + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height + 0.0625F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.0625F * f, 0.0F); + } + + @Override +- @Override + protected float ridingOffset(Entity entity) { + return 0.5F; + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putByte("ExplosionPower", (byte) this.explosionPower); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putByte("ExplosionPower", (byte) this.explosionPower); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("ExplosionPower", 99)) { +- this.explosionPower = compoundtag.getByte("ExplosionPower"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("ExplosionPower", 99)) { ++ this.explosionPower = compound.getByte("ExplosionPower"); + } + + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 2.6F; + } + +@@ -192,17 +176,16 @@ + } + + @Override +- @Override + public void tick() { + if (this.operation == MoveControl.Operation.MOVE_TO) { + if (this.floatDuration-- <= 0) { + this.floatDuration += this.ghast.getRandom().nextInt(5) + 2; +- Vec3 vec3 = new Vec3(this.wantedX - this.ghast.getX(), this.wantedY - this.ghast.getY(), this.wantedZ - this.ghast.getZ()); +- double d0 = vec3.length(); ++ Vec3 vec3d = new Vec3(this.wantedX - this.ghast.getX(), this.wantedY - this.ghast.getY(), this.wantedZ - this.ghast.getZ()); ++ double d0 = vec3d.length(); + +- vec3 = vec3.normalize(); +- if (this.canReach(vec3, Mth.ceil(d0))) { +- this.ghast.setDeltaMovement(this.ghast.getDeltaMovement().add(vec3.scale(0.1D))); ++ vec3d = vec3d.normalize(); ++ if (this.canReach(vec3d, Mth.ceil(d0))) { ++ this.ghast.setDeltaMovement(this.ghast.getDeltaMovement().add(vec3d.scale(0.1D))); + } else { + this.operation = MoveControl.Operation.WAIT; + } +@@ -211,12 +194,12 @@ + } + } + +- private boolean canReach(Vec3 vec3, int i) { +- AABB aabb = this.ghast.getBoundingBox(); ++ private boolean canReach(Vec3 pos, int length) { ++ AABB axisalignedbb = this.ghast.getBoundingBox(); + +- for (int j = 1; j < i; ++j) { +- aabb = aabb.move(vec3); +- if (!this.ghast.level().noCollision(this.ghast, aabb)) { ++ for (int j = 1; j < length; ++j) { ++ axisalignedbb = axisalignedbb.move(pos); ++ if (!this.ghast.level().noCollision(this.ghast, axisalignedbb)) { + return false; + } + } +@@ -231,20 +214,19 @@ + + public RandomFloatAroundGoal(Ghast ghast) { + this.ghast = ghast; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +- @Override + public boolean canUse() { +- MoveControl movecontrol = this.ghast.getMoveControl(); ++ MoveControl controllermove = this.ghast.getMoveControl(); + +- if (!movecontrol.hasWanted()) { ++ if (!controllermove.hasWanted()) { + return true; + } else { +- double d0 = movecontrol.getWantedX() - this.ghast.getX(); +- double d1 = movecontrol.getWantedY() - this.ghast.getY(); +- double d2 = movecontrol.getWantedZ() - this.ghast.getZ(); ++ double d0 = controllermove.getWantedX() - this.ghast.getX(); ++ double d1 = controllermove.getWantedY() - this.ghast.getY(); ++ double d2 = controllermove.getWantedZ() - this.ghast.getZ(); + double d3 = d0 * d0 + d1 * d1 + d2 * d2; + + return d3 < 1.0D || d3 > 3600.0D; +@@ -252,13 +234,11 @@ + } + + @Override +- @Override + public boolean canContinueToUse() { + return false; + } + + @Override +- @Override + public void start() { + RandomSource randomsource = this.ghast.getRandom(); + double d0 = this.ghast.getX() + (double) ((randomsource.nextFloat() * 2.0F - 1.0F) * 16.0F); +@@ -275,36 +255,33 @@ + + public GhastLookGoal(Ghast ghast) { + this.ghast = ghast; +- this.setFlags(EnumSet.of(Goal.Flag.LOOK)); ++ this.setFlags(EnumSet.of(Goal.Type.LOOK)); + } + + @Override +- @Override + public boolean canUse() { + return true; + } + + @Override +- @Override + public boolean requiresUpdateEveryTick() { + return true; + } + + @Override +- @Override + public void tick() { + if (this.ghast.getTarget() == null) { +- Vec3 vec3 = this.ghast.getDeltaMovement(); ++ Vec3 vec3d = this.ghast.getDeltaMovement(); + +- this.ghast.setYRot(-((float) Mth.atan2(vec3.x, vec3.z)) * 57.295776F); ++ this.ghast.setYRot(-((float) Mth.atan2(vec3d.x, vec3d.z)) * 57.295776F); + this.ghast.yBodyRot = this.ghast.getYRot(); + } else { +- LivingEntity livingentity = this.ghast.getTarget(); ++ LivingEntity entityliving = this.ghast.getTarget(); + double d0 = 64.0D; + +- if (livingentity.distanceToSqr((Entity) this.ghast) < 4096.0D) { +- double d1 = livingentity.getX() - this.ghast.getX(); +- double d2 = livingentity.getZ() - this.ghast.getZ(); ++ if (entityliving.distanceToSqr((Entity) this.ghast) < 4096.0D) { ++ double d1 = entityliving.getX() - this.ghast.getX(); ++ double d2 = entityliving.getZ() - this.ghast.getZ(); + + this.ghast.setYRot(-((float) Mth.atan2(d1, d2)) * 57.295776F); + this.ghast.yBodyRot = this.ghast.getYRot(); +@@ -324,60 +301,57 @@ + } + + @Override +- @Override + public boolean canUse() { + return this.ghast.getTarget() != null; + } + + @Override +- @Override + public void start() { + this.chargeTime = 0; + } + + @Override +- @Override + public void stop() { + this.ghast.setCharging(false); + } + + @Override +- @Override + public boolean requiresUpdateEveryTick() { + return true; + } + + @Override +- @Override + public void tick() { +- LivingEntity livingentity = this.ghast.getTarget(); ++ LivingEntity entityliving = this.ghast.getTarget(); + +- if (livingentity != null) { ++ if (entityliving != null) { + double d0 = 64.0D; + +- if (livingentity.distanceToSqr((Entity) this.ghast) < 4096.0D && this.ghast.hasLineOfSight(livingentity)) { +- Level level = this.ghast.level(); ++ if (entityliving.distanceToSqr((Entity) this.ghast) < 4096.0D && this.ghast.hasLineOfSight(entityliving)) { ++ Level world = this.ghast.level(); + + ++this.chargeTime; + if (this.chargeTime == 10 && !this.ghast.isSilent()) { +- level.levelEvent((Player) null, 1015, this.ghast.blockPosition(), 0); ++ world.levelEvent((Player) null, 1015, this.ghast.blockPosition(), 0); + } + + if (this.chargeTime == 20) { + double d1 = 4.0D; +- Vec3 vec3 = this.ghast.getViewVector(1.0F); +- double d2 = livingentity.getX() - (this.ghast.getX() + vec3.x * 4.0D); +- double d3 = livingentity.getY(0.5D) - (0.5D + this.ghast.getY(0.5D)); +- double d4 = livingentity.getZ() - (this.ghast.getZ() + vec3.z * 4.0D); ++ Vec3 vec3d = this.ghast.getViewVector(1.0F); ++ double d2 = entityliving.getX() - (this.ghast.getX() + vec3d.x * 4.0D); ++ double d3 = entityliving.getY(0.5D) - (0.5D + this.ghast.getY(0.5D)); ++ double d4 = entityliving.getZ() - (this.ghast.getZ() + vec3d.z * 4.0D); + + if (!this.ghast.isSilent()) { +- level.levelEvent((Player) null, 1016, this.ghast.blockPosition(), 0); ++ world.levelEvent((Player) null, 1016, this.ghast.blockPosition(), 0); + } + +- LargeFireball largefireball = new LargeFireball(level, this.ghast, d2, d3, d4, this.ghast.getExplosionPower()); ++ LargeFireball entitylargefireball = new LargeFireball(world, this.ghast, d2, d3, d4, this.ghast.getExplosionPower()); + +- largefireball.setPos(this.ghast.getX() + vec3.x * 4.0D, this.ghast.getY(0.5D) + 0.5D, largefireball.getZ() + vec3.z * 4.0D); +- level.addFreshEntity(largefireball); ++ // CraftBukkit - set bukkitYield when setting explosionpower ++ entitylargefireball.bukkitYield = entitylargefireball.explosionPower = this.ghast.getExplosionPower(); ++ entitylargefireball.setPos(this.ghast.getX() + vec3d.x * 4.0D, this.ghast.getY(0.5D) + 0.5D, entitylargefireball.getZ() + vec3d.z * 4.0D); ++ world.addFreshEntity(entitylargefireball); + this.chargeTime = -40; + } + } else if (this.chargeTime > 0) { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Guardian.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Guardian.java.patch new file mode 100644 index 0000000000..83f18b5691 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Guardian.java.patch @@ -0,0 +1,486 @@ +--- a/net/minecraft/world/entity/monster/Guardian.java ++++ b/net/minecraft/world/entity/monster/Guardian.java +@@ -19,12 +19,12 @@ + import net.minecraft.world.damagesource.DamageTypes; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.LookControl; +@@ -62,10 +62,11 @@ + private int clientSideAttackTime; + private boolean clientSideTouchedGround; + @Nullable +- protected RandomStrollGoal randomStrollGoal; ++ public RandomStrollGoal randomStrollGoal; ++ public Guardian.GuardianAttackGoal guardianAttackGoal; // CraftBukkit - add field + +- public Guardian(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Guardian(EntityType entityType, Level level) { ++ super(entityType, level); + this.xpReward = 10; + this.setPathfindingMalus(BlockPathTypes.WATER, 0.0F); + this.moveControl = new Guardian.GuardianMoveControl(this); +@@ -74,19 +75,18 @@ + } + + @Override +- @Override + protected void registerGoals() { +- MoveTowardsRestrictionGoal movetowardsrestrictiongoal = new MoveTowardsRestrictionGoal(this, 1.0D); ++ MoveTowardsRestrictionGoal pathfindergoalmovetowardsrestriction = new MoveTowardsRestrictionGoal(this, 1.0D); + + this.randomStrollGoal = new RandomStrollGoal(this, 1.0D, 80); +- this.goalSelector.addGoal(4, new Guardian.GuardianAttackGoal(this)); +- this.goalSelector.addGoal(5, movetowardsrestrictiongoal); ++ this.goalSelector.addGoal(4, guardianAttackGoal = new Guardian.GuardianAttackGoal(this)); // CraftBukkit - assign field ++ this.goalSelector.addGoal(5, pathfindergoalmovetowardsrestriction); + this.goalSelector.addGoal(7, this.randomStrollGoal); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Guardian.class, 12.0F, 0.01F)); + this.goalSelector.addGoal(9, new RandomLookAroundGoal(this)); +- this.randomStrollGoal.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); +- movetowardsrestrictiongoal.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ this.randomStrollGoal.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); ++ pathfindergoalmovetowardsrestriction.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, LivingEntity.class, 10, true, false, new Guardian.GuardianAttackSelector(this))); + } + +@@ -95,13 +95,11 @@ + } + + @Override +- @Override + protected PathNavigation createNavigation(Level level) { + return new WaterBoundPathNavigation(this, level); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Guardian.DATA_ID_MOVING, false); +@@ -109,25 +107,24 @@ + } + + @Override +- @Override +- public MobType getMobType() { +- return MobType.WATER; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.WATER; + } + + public boolean isMoving() { + return (Boolean) this.entityData.get(Guardian.DATA_ID_MOVING); + } + +- void setMoving(boolean flag) { +- this.entityData.set(Guardian.DATA_ID_MOVING, flag); ++ void setMoving(boolean moving) { ++ this.entityData.set(Guardian.DATA_ID_MOVING, moving); + } + + public int getAttackDuration() { + return 80; + } + +- void setActiveAttackTarget(int i) { +- this.entityData.set(Guardian.DATA_ID_ATTACK_TARGET, i); ++ public void setActiveAttackTarget(int activeAttackTargetId) { ++ this.entityData.set(Guardian.DATA_ID_ATTACK_TARGET, activeAttackTargetId); + } + + public boolean hasActiveAttackTarget() { +@@ -157,10 +154,9 @@ + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- super.onSyncedDataUpdated(entitydataaccessor); +- if (Guardian.DATA_ID_ATTACK_TARGET.equals(entitydataaccessor)) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ super.onSyncedDataUpdated(key); ++ if (Guardian.DATA_ID_ATTACK_TARGET.equals(key)) { + this.clientSideAttackTime = 0; + this.clientSideCachedAttackTarget = null; + } +@@ -168,63 +164,55 @@ + } + + @Override +- @Override + public int getAmbientSoundInterval() { + return 160; + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return this.isInWaterOrBubble() ? SoundEvents.GUARDIAN_AMBIENT : SoundEvents.GUARDIAN_AMBIENT_LAND; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return this.isInWaterOrBubble() ? SoundEvents.GUARDIAN_HURT : SoundEvents.GUARDIAN_HURT_LAND; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return this.isInWaterOrBubble() ? SoundEvents.GUARDIAN_DEATH : SoundEvents.GUARDIAN_DEATH_LAND; + } + + @Override +- @Override + protected Entity.MovementEmission getMovementEmission() { + return Entity.MovementEmission.EVENTS; + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return entitydimensions.height * 0.5F; ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { ++ return size.height * 0.5F; + } + + @Override +- @Override +- public float getWalkTargetValue(BlockPos blockpos, LevelReader levelreader) { +- return levelreader.getFluidState(blockpos).is(FluidTags.WATER) ? 10.0F + levelreader.getPathfindingCostFromLightLevels(blockpos) : super.getWalkTargetValue(blockpos, levelreader); ++ public float getWalkTargetValue(BlockPos pos, LevelReader level) { ++ return level.getFluidState(pos).is(FluidTags.WATER) ? 10.0F + level.getPathfindingCostFromLightLevels(pos) : super.getWalkTargetValue(pos, level); + } + + @Override +- @Override + public void aiStep() { + if (this.isAlive()) { + if (this.level().isClientSide) { + this.clientSideTailAnimationO = this.clientSideTailAnimation; +- Vec3 vec3; ++ Vec3 vec3d; + + if (!this.isInWater()) { + this.clientSideTailAnimationSpeed = 2.0F; +- vec3 = this.getDeltaMovement(); +- if (vec3.y > 0.0D && this.clientSideTouchedGround && !this.isSilent()) { ++ vec3d = this.getDeltaMovement(); ++ if (vec3d.y > 0.0D && this.clientSideTouchedGround && !this.isSilent()) { + this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), this.getFlopSound(), this.getSoundSource(), 1.0F, 1.0F, false); + } + +- this.clientSideTouchedGround = vec3.y < 0.0D && this.level().loadedAndEntityCanStandOn(this.blockPosition().below(), this); ++ this.clientSideTouchedGround = vec3d.y < 0.0D && this.level().loadedAndEntityCanStandOn(this.blockPosition().below(), this); + } else if (this.isMoving()) { + if (this.clientSideTailAnimationSpeed < 0.5F) { + this.clientSideTailAnimationSpeed = 4.0F; +@@ -246,10 +234,10 @@ + } + + if (this.isMoving() && this.isInWater()) { +- vec3 = this.getViewVector(0.0F); ++ vec3d = this.getViewVector(0.0F); + + for (int i = 0; i < 2; ++i) { +- this.level().addParticle(ParticleTypes.BUBBLE, this.getRandomX(0.5D) - vec3.x * 1.5D, this.getRandomY() - vec3.y * 1.5D, this.getRandomZ(0.5D) - vec3.z * 1.5D, 0.0D, 0.0D, 0.0D); ++ this.level().addParticle(ParticleTypes.BUBBLE, this.getRandomX(0.5D) - vec3d.x * 1.5D, this.getRandomY() - vec3d.y * 1.5D, this.getRandomZ(0.5D) - vec3d.z * 1.5D, 0.0D, 0.0D, 0.0D); + } + } + +@@ -258,15 +246,15 @@ + ++this.clientSideAttackTime; + } + +- LivingEntity livingentity = this.getActiveAttackTarget(); ++ LivingEntity entityliving = this.getActiveAttackTarget(); + +- if (livingentity != null) { +- this.getLookControl().setLookAt(livingentity, 90.0F, 90.0F); ++ if (entityliving != null) { ++ this.getLookControl().setLookAt(entityliving, 90.0F, 90.0F); + this.getLookControl().tick(); + double d0 = (double) this.getAttackAnimationScale(0.0F); +- double d1 = livingentity.getX() - this.getX(); +- double d2 = livingentity.getY(0.5D) - this.getEyeY(); +- double d3 = livingentity.getZ() - this.getZ(); ++ double d1 = entityliving.getX() - this.getX(); ++ double d2 = entityliving.getY(0.5D) - this.getEyeY(); ++ double d3 = entityliving.getZ() - this.getZ(); + double d4 = Math.sqrt(d1 * d1 + d2 * d2 + d3 * d3); + + d1 /= d4; +@@ -303,16 +291,16 @@ + return SoundEvents.GUARDIAN_FLOP; + } + +- public float getTailAnimation(float f) { +- return Mth.lerp(f, this.clientSideTailAnimationO, this.clientSideTailAnimation); ++ public float getTailAnimation(float partialTick) { ++ return Mth.lerp(partialTick, this.clientSideTailAnimationO, this.clientSideTailAnimation); + } + +- public float getSpikesAnimation(float f) { +- return Mth.lerp(f, this.clientSideSpikesAnimationO, this.clientSideSpikesAnimation); ++ public float getSpikesAnimation(float partialTick) { ++ return Mth.lerp(partialTick, this.clientSideSpikesAnimationO, this.clientSideSpikesAnimation); + } + +- public float getAttackAnimationScale(float f) { +- return ((float) this.clientSideAttackTime + f) / (float) this.getAttackDuration(); ++ public float getAttackAnimationScale(float partialTick) { ++ return ((float) this.clientSideAttackTime + partialTick) / (float) this.getAttackDuration(); + } + + public float getClientSideAttackTime() { +@@ -320,28 +308,26 @@ + } + + @Override +- @Override +- public boolean checkSpawnObstruction(LevelReader levelreader) { +- return levelreader.isUnobstructed(this); ++ public boolean checkSpawnObstruction(LevelReader level) { ++ return level.isUnobstructed(this); + } + +- public static boolean checkGuardianSpawnRules(EntityType entitytype, LevelAccessor levelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- return (randomsource.nextInt(20) == 0 || !levelaccessor.canSeeSkyFromBelowWater(blockpos)) && levelaccessor.getDifficulty() != Difficulty.PEACEFUL && (MobSpawnType.isSpawner(mobspawntype) || levelaccessor.getFluidState(blockpos).is(FluidTags.WATER)) && levelaccessor.getFluidState(blockpos.below()).is(FluidTags.WATER); ++ public static boolean checkGuardianSpawnRules(EntityType guardian, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ return (random.nextInt(20) == 0 || !level.canSeeSkyFromBelowWater(pos)) && level.getDifficulty() != Difficulty.PEACEFUL && (EnumMobSpawn.isSpawner(spawnType) || level.getFluidState(pos).is(FluidTags.WATER)) && level.getFluidState(pos.below()).is(FluidTags.WATER); + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { ++ public boolean hurt(DamageSource source, float amount) { + if (this.level().isClientSide) { + return false; + } else { +- if (!this.isMoving() && !damagesource.is(DamageTypeTags.AVOIDS_GUARDIAN_THORNS) && !damagesource.is(DamageTypes.THORNS)) { +- Entity entity = damagesource.getDirectEntity(); ++ if (!this.isMoving() && !source.is(DamageTypeTags.AVOIDS_GUARDIAN_THORNS) && !source.is(DamageTypes.THORNS)) { ++ Entity entity = source.getDirectEntity(); + + if (entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; ++ LivingEntity entityliving = (LivingEntity) entity; + +- livingentity.hurt(this.damageSources().thorns(this), 2.0F); ++ entityliving.hurt(this.damageSources().thorns(this), 2.0F); + } + } + +@@ -349,36 +335,33 @@ + this.randomStrollGoal.trigger(); + } + +- return super.hurt(damagesource, f); ++ return super.hurt(source, amount); + } + } + + @Override +- @Override + public int getMaxHeadXRot() { + return 180; + } + + @Override +- @Override +- public void travel(Vec3 vec3) { ++ public void travel(Vec3 travelVector) { + if (this.isControlledByLocalInstance() && this.isInWater()) { +- this.moveRelative(0.1F, vec3); +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.moveRelative(0.1F, travelVector); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + this.setDeltaMovement(this.getDeltaMovement().scale(0.9D)); + if (!this.isMoving() && this.getTarget() == null) { + this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.005D, 0.0D)); + } + } else { +- super.travel(vec3); ++ super.travel(travelVector); + } + + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height + 0.125F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.125F * f, 0.0F); + } + + private static class GuardianMoveControl extends MoveControl { +@@ -391,15 +374,14 @@ + } + + @Override +- @Override + public void tick() { + if (this.operation == MoveControl.Operation.MOVE_TO && !this.guardian.getNavigation().isDone()) { +- Vec3 vec3 = new Vec3(this.wantedX - this.guardian.getX(), this.wantedY - this.guardian.getY(), this.wantedZ - this.guardian.getZ()); +- double d0 = vec3.length(); +- double d1 = vec3.x / d0; +- double d2 = vec3.y / d0; +- double d3 = vec3.z / d0; +- float f = (float) (Mth.atan2(vec3.z, vec3.x) * 57.2957763671875D) - 90.0F; ++ Vec3 vec3d = new Vec3(this.wantedX - this.guardian.getX(), this.wantedY - this.guardian.getY(), this.wantedZ - this.guardian.getZ()); ++ double d0 = vec3d.length(); ++ double d1 = vec3d.x / d0; ++ double d2 = vec3d.y / d0; ++ double d3 = vec3d.z / d0; ++ float f = (float) (Mth.atan2(vec3d.z, vec3d.x) * 57.2957763671875D) - 90.0F; + + this.guardian.setYRot(this.rotlerp(this.guardian.getYRot(), f, 90.0F)); + this.guardian.yBodyRot = this.guardian.getYRot(); +@@ -413,15 +395,15 @@ + double d7 = Math.sin((double) (this.guardian.tickCount + this.guardian.getId()) * 0.75D) * 0.05D; + + this.guardian.setDeltaMovement(this.guardian.getDeltaMovement().add(d4 * d5, d7 * (d6 + d5) * 0.25D + (double) f2 * d2 * 0.1D, d4 * d6)); +- LookControl lookcontrol = this.guardian.getLookControl(); ++ LookControl controllerlook = this.guardian.getLookControl(); + double d8 = this.guardian.getX() + d1 * 2.0D; + double d9 = this.guardian.getEyeY() + d2 / d0; + double d10 = this.guardian.getZ() + d3 * 2.0D; +- double d11 = lookcontrol.getWantedX(); +- double d12 = lookcontrol.getWantedY(); +- double d13 = lookcontrol.getWantedZ(); ++ double d11 = controllerlook.getWantedX(); ++ double d12 = controllerlook.getWantedY(); ++ double d13 = controllerlook.getWantedZ(); + +- if (!lookcontrol.isLookingAtTarget()) { ++ if (!controllerlook.isLookingAtTarget()) { + d11 = d8; + d12 = d9; + d13 = d10; +@@ -436,48 +418,44 @@ + } + } + +- private static class GuardianAttackGoal extends Goal { ++ public static class GuardianAttackGoal extends Goal { + + private final Guardian guardian; +- private int attackTime; ++ public int attackTime; + private final boolean elder; + + public GuardianAttackGoal(Guardian guardian) { + this.guardian = guardian; + this.elder = guardian instanceof ElderGuardian; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + } + + @Override +- @Override + public boolean canUse() { +- LivingEntity livingentity = this.guardian.getTarget(); ++ LivingEntity entityliving = this.guardian.getTarget(); + +- return livingentity != null && livingentity.isAlive(); ++ return entityliving != null && entityliving.isAlive(); + } + + @Override +- @Override + public boolean canContinueToUse() { + return super.canContinueToUse() && (this.elder || this.guardian.getTarget() != null && this.guardian.distanceToSqr((Entity) this.guardian.getTarget()) > 9.0D); + } + + @Override +- @Override + public void start() { + this.attackTime = -10; + this.guardian.getNavigation().stop(); +- LivingEntity livingentity = this.guardian.getTarget(); ++ LivingEntity entityliving = this.guardian.getTarget(); + +- if (livingentity != null) { +- this.guardian.getLookControl().setLookAt(livingentity, 90.0F, 90.0F); ++ if (entityliving != null) { ++ this.guardian.getLookControl().setLookAt(entityliving, 90.0F, 90.0F); + } + + this.guardian.hasImpulse = true; + } + + @Override +- @Override + public void stop() { + this.guardian.setActiveAttackTarget(0); + this.guardian.setTarget((LivingEntity) null); +@@ -485,25 +463,23 @@ + } + + @Override +- @Override + public boolean requiresUpdateEveryTick() { + return true; + } + + @Override +- @Override + public void tick() { +- LivingEntity livingentity = this.guardian.getTarget(); ++ LivingEntity entityliving = this.guardian.getTarget(); + +- if (livingentity != null) { ++ if (entityliving != null) { + this.guardian.getNavigation().stop(); +- this.guardian.getLookControl().setLookAt(livingentity, 90.0F, 90.0F); +- if (!this.guardian.hasLineOfSight(livingentity)) { ++ this.guardian.getLookControl().setLookAt(entityliving, 90.0F, 90.0F); ++ if (!this.guardian.hasLineOfSight(entityliving)) { + this.guardian.setTarget((LivingEntity) null); + } else { + ++this.attackTime; + if (this.attackTime == 0) { +- this.guardian.setActiveAttackTarget(livingentity.getId()); ++ this.guardian.setActiveAttackTarget(entityliving.getId()); + if (!this.guardian.isSilent()) { + this.guardian.level().broadcastEntityEvent(this.guardian, (byte) 21); + } +@@ -518,8 +494,8 @@ + f += 2.0F; + } + +- livingentity.hurt(this.guardian.damageSources().indirectMagic(this.guardian, this.guardian), f); +- livingentity.hurt(this.guardian.damageSources().mobAttack(this.guardian), (float) this.guardian.getAttributeValue(Attributes.ATTACK_DAMAGE)); ++ entityliving.hurt(this.guardian.damageSources().indirectMagic(this.guardian, this.guardian), f); ++ entityliving.hurt(this.guardian.damageSources().mobAttack(this.guardian), (float) this.guardian.getAttributeValue(Attributes.ATTACK_DAMAGE)); + this.guardian.setTarget((LivingEntity) null); + } + +@@ -537,9 +513,8 @@ + this.guardian = guardian; + } + +- @Override +- public boolean test(@Nullable LivingEntity livingentity) { +- return (livingentity instanceof Player || livingentity instanceof Squid || livingentity instanceof Axolotl) && livingentity.distanceToSqr((Entity) this.guardian) > 9.0D; ++ public boolean test(@Nullable LivingEntity entity) { ++ return (entity instanceof Player || entity instanceof Squid || entity instanceof Axolotl) && entity.distanceToSqr((Entity) this.guardian) > 9.0D; + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Husk.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Husk.java.patch new file mode 100644 index 0000000000..8e2bdfbae2 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Husk.java.patch @@ -0,0 +1,102 @@ +--- a/net/minecraft/world/entity/monster/Husk.java ++++ b/net/minecraft/world/entity/monster/Husk.java +@@ -10,8 +10,8 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; +@@ -20,66 +20,58 @@ + + public class Husk extends Zombie { + +- public Husk(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Husk(EntityType entityType, Level level) { ++ super(entityType, level); + } + +- public static boolean checkHuskSpawnRules(EntityType entitytype, ServerLevelAccessor serverlevelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- return checkMonsterSpawnRules(entitytype, serverlevelaccessor, mobspawntype, blockpos, randomsource) && (MobSpawnType.isSpawner(mobspawntype) || serverlevelaccessor.canSeeSky(blockpos)); ++ public static boolean checkHuskSpawnRules(EntityType husk, ServerLevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ return checkMonsterSpawnRules(husk, level, spawnType, pos, random) && (EnumMobSpawn.isSpawner(spawnType) || level.canSeeSky(pos)); + } + + @Override +- @Override + protected boolean isSunSensitive() { + return false; + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.HUSK_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.HUSK_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.HUSK_DEATH; + } + + @Override +- @Override + protected SoundEvent getStepSound() { + return SoundEvents.HUSK_STEP; + } + + @Override +- @Override + public boolean doHurtTarget(Entity entity) { + boolean flag = super.doHurtTarget(entity); + + if (flag && this.getMainHandItem().isEmpty() && entity instanceof LivingEntity) { + float f = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty(); + +- ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.HUNGER, 140 * (int) f), this); ++ ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.HUNGER, 140 * (int) f), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + + return flag; + } + + @Override +- @Override + protected boolean convertsInWater() { + return true; + } + + @Override +- @Override + protected void doUnderWaterConversion() { + this.convertToZombieType(EntityType.ZOMBIE); + if (!this.isSilent()) { +@@ -89,14 +81,12 @@ + } + + @Override +- @Override + protected ItemStack getSkull() { + return ItemStack.EMPTY; + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height + 0.125F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.125F * f, 0.0F); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Illusioner.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Illusioner.java.patch new file mode 100644 index 0000000000..6ea8c71c90 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Illusioner.java.patch @@ -0,0 +1,259 @@ +--- a/net/minecraft/world/entity/monster/Illusioner.java ++++ b/net/minecraft/world/entity/monster/Illusioner.java +@@ -12,12 +12,12 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.FloatGoal; +@@ -47,8 +47,8 @@ + private int clientSideIllusionTicks; + private final Vec3[][] clientSideIllusionOffsets; + +- public Illusioner(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Illusioner(EntityType entityType, Level level) { ++ super(entityType, level); + this.xpReward = 5; + this.clientSideIllusionOffsets = new Vec3[2][4]; + +@@ -60,7 +60,6 @@ + } + + @Override +- @Override + protected void registerGoals() { + super.registerGoals(); + this.goalSelector.addGoal(0, new FloatGoal(this)); +@@ -82,26 +81,22 @@ + } + + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.BOW)); +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); ++ return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + } + + @Override +- @Override + public AABB getBoundingBoxForCulling() { + return this.getBoundingBox().inflate(3.0D, 0.0D, 3.0D); + } + + @Override +- @Override + public void aiStep() { + super.aiStep(); + if (this.level().isClientSide && this.isInvisible()) { +@@ -142,81 +137,72 @@ + } + + @Override +- @Override + public SoundEvent getCelebrateSound() { + return SoundEvents.ILLUSIONER_AMBIENT; + } + +- public Vec3[] getIllusionOffsets(float f) { ++ public Vec3[] getIllusionOffsets(float partialTick) { + if (this.clientSideIllusionTicks <= 0) { + return this.clientSideIllusionOffsets[1]; + } else { +- double d0 = (double) (((float) this.clientSideIllusionTicks - f) / 3.0F); ++ double d0 = (double) (((float) this.clientSideIllusionTicks - partialTick) / 3.0F); + + d0 = Math.pow(d0, 0.25D); +- Vec3[] avec3 = new Vec3[4]; ++ Vec3[] avec3d = new Vec3[4]; + + for (int i = 0; i < 4; ++i) { +- avec3[i] = this.clientSideIllusionOffsets[1][i].scale(1.0D - d0).add(this.clientSideIllusionOffsets[0][i].scale(d0)); ++ avec3d[i] = this.clientSideIllusionOffsets[1][i].scale(1.0D - d0).add(this.clientSideIllusionOffsets[0][i].scale(d0)); + } + +- return avec3; ++ return avec3d; + } + } + + @Override +- @Override + public boolean isAlliedTo(Entity entity) { +- return super.isAlliedTo(entity) ? true : (entity instanceof LivingEntity && ((LivingEntity) entity).getMobType() == MobType.ILLAGER ? this.getTeam() == null && entity.getTeam() == null : false); ++ return super.isAlliedTo(entity) ? true : (entity instanceof LivingEntity && ((LivingEntity) entity).getMobType() == EnumMonsterType.ILLAGER ? this.getTeam() == null && entity.getTeam() == null : false); + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.ILLUSIONER_AMBIENT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.ILLUSIONER_DEATH; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.ILLUSIONER_HURT; + } + + @Override +- @Override + protected SoundEvent getCastingSoundEvent() { + return SoundEvents.ILLUSIONER_CAST_SPELL; + } + + @Override +- @Override +- public void applyRaidBuffs(int i, boolean flag) {} ++ public void applyRaidBuffs(int wave, boolean unusedFalse) {} + + @Override +- @Override +- public void performRangedAttack(LivingEntity livingentity, float f) { ++ public void performRangedAttack(LivingEntity target, float distanceFactor) { + ItemStack itemstack = this.getProjectile(this.getItemInHand(ProjectileUtil.getWeaponHoldingHand(this, Items.BOW))); +- AbstractArrow abstractarrow = ProjectileUtil.getMobArrow(this, itemstack, f); +- double d0 = livingentity.getX() - this.getX(); +- double d1 = livingentity.getY(0.3333333333333333D) - abstractarrow.getY(); +- double d2 = livingentity.getZ() - this.getZ(); ++ AbstractArrow entityarrow = ProjectileUtil.getMobArrow(this, itemstack, distanceFactor); ++ double d0 = target.getX() - this.getX(); ++ double d1 = target.getY(0.3333333333333333D) - entityarrow.getY(); ++ double d2 = target.getZ() - this.getZ(); + double d3 = Math.sqrt(d0 * d0 + d2 * d2); + +- abstractarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level().getDifficulty().getId() * 4)); ++ entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level().getDifficulty().getId() * 4)); + this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); +- this.level().addFreshEntity(abstractarrow); ++ this.level().addFreshEntity(entityarrow); + } + + @Override +- @Override +- public AbstractIllager.IllagerArmPose getArmPose() { +- return this.isCastingSpell() ? AbstractIllager.IllagerArmPose.SPELLCASTING : (this.isAggressive() ? AbstractIllager.IllagerArmPose.BOW_AND_ARROW : AbstractIllager.IllagerArmPose.CROSSED); ++ public AbstractIllager.a getArmPose() { ++ return this.isCastingSpell() ? AbstractIllager.a.SPELLCASTING : (this.isAggressive() ? AbstractIllager.a.BOW_AND_ARROW : AbstractIllager.a.CROSSED); + } + + private class IllusionerMirrorSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { +@@ -226,38 +212,32 @@ + } + + @Override +- @Override + public boolean canUse() { + return !super.canUse() ? false : !Illusioner.this.hasEffect(MobEffects.INVISIBILITY); + } + + @Override +- @Override + protected int getCastingTime() { + return 20; + } + + @Override +- @Override + protected int getCastingInterval() { + return 340; + } + + @Override +- @Override + protected void performSpellCasting() { +- Illusioner.this.addEffect(new MobEffectInstance(MobEffects.INVISIBILITY, 1200)); ++ Illusioner.this.addEffect(new MobEffectInstance(MobEffects.INVISIBILITY, 1200), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ILLUSION); // CraftBukkit + } + + @Nullable + @Override +- @Override + protected SoundEvent getSpellPrepareSound() { + return SoundEvents.ILLUSIONER_PREPARE_MIRROR; + } + + @Override +- @Override + protected SpellcasterIllager.IllagerSpell getSpell() { + return SpellcasterIllager.IllagerSpell.DISAPPEAR; + } +@@ -272,49 +252,42 @@ + } + + @Override +- @Override + public boolean canUse() { + return !super.canUse() ? false : (Illusioner.this.getTarget() == null ? false : (Illusioner.this.getTarget().getId() == this.lastTargetId ? false : Illusioner.this.level().getCurrentDifficultyAt(Illusioner.this.blockPosition()).isHarderThan((float) Difficulty.NORMAL.ordinal()))); + } + + @Override +- @Override + public void start() { + super.start(); +- LivingEntity livingentity = Illusioner.this.getTarget(); ++ LivingEntity entityliving = Illusioner.this.getTarget(); + +- if (livingentity != null) { +- this.lastTargetId = livingentity.getId(); ++ if (entityliving != null) { ++ this.lastTargetId = entityliving.getId(); + } + + } + + @Override +- @Override + protected int getCastingTime() { + return 20; + } + + @Override +- @Override + protected int getCastingInterval() { + return 180; + } + + @Override +- @Override + protected void performSpellCasting() { +- Illusioner.this.getTarget().addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 400), Illusioner.this); ++ Illusioner.this.getTarget().addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 400), Illusioner.this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + + @Override +- @Override + protected SoundEvent getSpellPrepareSound() { + return SoundEvents.ILLUSIONER_PREPARE_BLINDNESS; + } + + @Override +- @Override + protected SpellcasterIllager.IllagerSpell getSpell() { + return SpellcasterIllager.IllagerSpell.BLINDNESS; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Phantom.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Phantom.java.patch new file mode 100644 index 0000000000..e797fedef8 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Phantom.java.patch @@ -0,0 +1,489 @@ +--- a/net/minecraft/world/entity/monster/Phantom.java ++++ b/net/minecraft/world/entity/monster/Phantom.java +@@ -19,15 +19,15 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.FlyingMob; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.BodyRotationControl; + import net.minecraft.world.entity.ai.control.LookControl; +@@ -42,7 +42,7 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Phantom extends FlyingMob implements Enemy { ++public class Phantom extends FlyingMob implements IMonster { + + public static final float FLAP_DEGREES_PER_TICK = 7.448451F; + public static final int TICKS_PER_FLAP = Mth.ceil(24.166098F); +@@ -51,8 +51,8 @@ + BlockPos anchorPoint; + Phantom.AttackPhase attackPhase; + +- public Phantom(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Phantom(EntityType entityType, Level level) { ++ super(entityType, level); + this.moveTargetPoint = Vec3.ZERO; + this.anchorPoint = BlockPos.ZERO; + this.attackPhase = Phantom.AttackPhase.CIRCLE; +@@ -62,19 +62,16 @@ + } + + @Override +- @Override + public boolean isFlapping() { + return (this.getUniqueFlapTickOffset() + this.tickCount) % Phantom.TICKS_PER_FLAP == 0; + } + + @Override +- @Override + protected BodyRotationControl createBodyControl() { + return new Phantom.PhantomBodyRotationControl(this); + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new Phantom.PhantomAttackStrategyGoal()); + this.goalSelector.addGoal(2, new Phantom.PhantomSweepAttackGoal()); +@@ -83,14 +80,13 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Phantom.ID_SIZE, 0); + } + +- public void setPhantomSize(int i) { +- this.entityData.set(Phantom.ID_SIZE, Mth.clamp(i, 0, 64)); ++ public void setPhantomSize(int phantomSize) { ++ this.entityData.set(Phantom.ID_SIZE, Mth.clamp(phantomSize, 0, 64)); + } + + private void updatePhantomSizeInfo() { +@@ -103,19 +99,17 @@ + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return entitydimensions.height * 0.35F; ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { ++ return size.height * 0.35F; + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- if (Phantom.ID_SIZE.equals(entitydataaccessor)) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ if (Phantom.ID_SIZE.equals(key)) { + this.updatePhantomSizeInfo(); + } + +- super.onSyncedDataUpdated(entitydataaccessor); ++ super.onSyncedDataUpdated(key); + } + + public int getUniqueFlapTickOffset() { +@@ -123,13 +117,11 @@ + } + + @Override +- @Override + protected boolean shouldDespawnInPeaceful() { + return true; + } + + @Override +- @Override + public void tick() { + super.tick(); + if (this.level().isClientSide) { +@@ -152,7 +144,6 @@ + } + + @Override +- @Override + public void aiStep() { + if (this.isAlive() && this.isSunBurnTick()) { + this.setSecondsOnFire(8); +@@ -162,105 +153,90 @@ + } + + @Override +- @Override + protected void customServerAiStep() { + super.customServerAiStep(); + } + + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + this.anchorPoint = this.blockPosition().above(5); + this.setPhantomSize(0); +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); ++ return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("AX")) { +- this.anchorPoint = new BlockPos(compoundtag.getInt("AX"), compoundtag.getInt("AY"), compoundtag.getInt("AZ")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("AX")) { ++ this.anchorPoint = new BlockPos(compound.getInt("AX"), compound.getInt("AY"), compound.getInt("AZ")); + } + +- this.setPhantomSize(compoundtag.getInt("Size")); ++ this.setPhantomSize(compound.getInt("Size")); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("AX", this.anchorPoint.getX()); +- compoundtag.putInt("AY", this.anchorPoint.getY()); +- compoundtag.putInt("AZ", this.anchorPoint.getZ()); +- compoundtag.putInt("Size", this.getPhantomSize()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("AX", this.anchorPoint.getX()); ++ compound.putInt("AY", this.anchorPoint.getY()); ++ compound.putInt("AZ", this.anchorPoint.getZ()); ++ compound.putInt("Size", this.getPhantomSize()); + } + + @Override +- @Override +- public boolean shouldRenderAtSqrDistance(double d0) { ++ public boolean shouldRenderAtSqrDistance(double distance) { + return true; + } + + @Override +- @Override + public SoundSource getSoundSource() { + return SoundSource.HOSTILE; + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.PHANTOM_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.PHANTOM_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.PHANTOM_DEATH; + } + + @Override +- @Override +- public MobType getMobType() { +- return MobType.UNDEAD; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.UNDEAD; + } + + @Override +- @Override + protected float getSoundVolume() { + return 1.0F; + } + + @Override +- @Override +- public boolean canAttackType(EntityType entitytype) { ++ public boolean canAttackType(EntityType type) { + return true; + } + + @Override +- @Override +- public EntityDimensions getDimensions(Pose pose) { ++ public EntityDimensions getDimensions(EntityPose pose) { + int i = this.getPhantomSize(); +- EntityDimensions entitydimensions = super.getDimensions(pose); ++ EntityDimensions entitysize = super.getDimensions(pose); + +- return entitydimensions.scale(1.0F + 0.15F * (float) i); ++ return entitysize.scale(1.0F + 0.15F * (float) i); + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height * 0.675F, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height * 0.675F, 0.0F); + } + + @Override +- @Override + protected float ridingOffset(Entity entity) { + return -0.125F; + } +@@ -281,7 +257,6 @@ + } + + @Override +- @Override + public void tick() { + if (Phantom.this.horizontalCollision) { + Phantom.this.setYRot(Phantom.this.getYRot() + 180.0F); +@@ -320,9 +295,9 @@ + double d6 = (double) (this.speed * Mth.cos(f5 * 0.017453292F)) * Math.abs(d0 / d5); + double d7 = (double) (this.speed * Mth.sin(f5 * 0.017453292F)) * Math.abs(d2 / d5); + double d8 = (double) (this.speed * Mth.sin(f4 * 0.017453292F)) * Math.abs(d1 / d5); +- Vec3 vec3 = Phantom.this.getDeltaMovement(); ++ Vec3 vec3d = Phantom.this.getDeltaMovement(); + +- Phantom.this.setDeltaMovement(vec3.add((new Vec3(d6, d8, d7)).subtract(vec3).scale(0.2D))); ++ Phantom.this.setDeltaMovement(vec3d.add((new Vec3(d6, d8, d7)).subtract(vec3d).scale(0.2D))); + } + + } +@@ -335,7 +310,6 @@ + } + + @Override +- @Override + public void tick() {} + } + +@@ -346,7 +320,6 @@ + } + + @Override +- @Override + public void clientTick() { + Phantom.this.yHeadRot = Phantom.this.yBodyRot; + Phantom.this.yBodyRot = Phantom.this.getYRot(); +@@ -360,15 +333,13 @@ + PhantomAttackStrategyGoal() {} + + @Override +- @Override + public boolean canUse() { +- LivingEntity livingentity = Phantom.this.getTarget(); ++ LivingEntity entityliving = Phantom.this.getTarget(); + +- return livingentity != null ? Phantom.this.canAttack(livingentity, TargetingConditions.DEFAULT) : false; ++ return entityliving != null ? Phantom.this.canAttack(entityliving, TargetingConditions.DEFAULT) : false; + } + + @Override +- @Override + public void start() { + this.nextSweepTick = this.adjustedTickDelay(10); + Phantom.this.attackPhase = Phantom.AttackPhase.CIRCLE; +@@ -376,13 +347,11 @@ + } + + @Override +- @Override + public void stop() { + Phantom.this.anchorPoint = Phantom.this.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, Phantom.this.anchorPoint).above(10 + Phantom.this.random.nextInt(20)); + } + + @Override +- @Override + public void tick() { + if (Phantom.this.attackPhase == Phantom.AttackPhase.CIRCLE) { + --this.nextSweepTick; +@@ -405,7 +374,7 @@ + } + } + +- private class PhantomSweepAttackGoal extends Phantom.PhantomMoveTargetGoal { ++ private class PhantomSweepAttackGoal extends Phantom.h { + + private static final int CAT_SEARCH_TICK_DELAY = 20; + private boolean isScaredOfCat; +@@ -416,25 +385,23 @@ + } + + @Override +- @Override + public boolean canUse() { + return Phantom.this.getTarget() != null && Phantom.this.attackPhase == Phantom.AttackPhase.SWOOP; + } + + @Override +- @Override + public boolean canContinueToUse() { +- LivingEntity livingentity = Phantom.this.getTarget(); ++ LivingEntity entityliving = Phantom.this.getTarget(); + +- if (livingentity == null) { ++ if (entityliving == null) { + return false; +- } else if (!livingentity.isAlive()) { ++ } else if (!entityliving.isAlive()) { + return false; + } else { +- if (livingentity instanceof Player) { +- Player player = (Player) livingentity; ++ if (entityliving instanceof Player) { ++ Player entityhuman = (Player) entityliving; + +- if (livingentity.isSpectator() || player.isCreative()) { ++ if (entityliving.isSpectator() || entityhuman.isCreative()) { + return false; + } + } +@@ -448,9 +415,9 @@ + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- Cat cat = (Cat) iterator.next(); ++ Cat entitycat = (Cat) iterator.next(); + +- cat.hiss(); ++ entitycat.hiss(); + } + + this.isScaredOfCat = !list.isEmpty(); +@@ -462,25 +429,22 @@ + } + + @Override +- @Override + public void start() {} + + @Override +- @Override + public void stop() { + Phantom.this.setTarget((LivingEntity) null); + Phantom.this.attackPhase = Phantom.AttackPhase.CIRCLE; + } + + @Override +- @Override + public void tick() { +- LivingEntity livingentity = Phantom.this.getTarget(); ++ LivingEntity entityliving = Phantom.this.getTarget(); + +- if (livingentity != null) { +- Phantom.this.moveTargetPoint = new Vec3(livingentity.getX(), livingentity.getY(0.5D), livingentity.getZ()); +- if (Phantom.this.getBoundingBox().inflate(0.20000000298023224D).intersects(livingentity.getBoundingBox())) { +- Phantom.this.doHurtTarget(livingentity); ++ if (entityliving != null) { ++ Phantom.this.moveTargetPoint = new Vec3(entityliving.getX(), entityliving.getY(0.5D), entityliving.getZ()); ++ if (Phantom.this.getBoundingBox().inflate(0.20000000298023224D).intersects(entityliving.getBoundingBox())) { ++ Phantom.this.doHurtTarget(entityliving); + Phantom.this.attackPhase = Phantom.AttackPhase.CIRCLE; + if (!Phantom.this.isSilent()) { + Phantom.this.level().levelEvent(1039, Phantom.this.blockPosition(), 0); +@@ -493,7 +457,7 @@ + } + } + +- private class PhantomCircleAroundAnchorGoal extends Phantom.PhantomMoveTargetGoal { ++ private class PhantomCircleAroundAnchorGoal extends Phantom.h { + + private float angle; + private float distance; +@@ -505,13 +469,11 @@ + } + + @Override +- @Override + public boolean canUse() { + return Phantom.this.getTarget() == null || Phantom.this.attackPhase == Phantom.AttackPhase.CIRCLE; + } + + @Override +- @Override + public void start() { + this.distance = 5.0F + Phantom.this.random.nextFloat() * 10.0F; + this.height = -4.0F + Phantom.this.random.nextFloat() * 9.0F; +@@ -520,7 +482,6 @@ + } + + @Override +- @Override + public void tick() { + if (Phantom.this.random.nextInt(this.adjustedTickDelay(350)) == 0) { + this.height = -4.0F + Phantom.this.random.nextFloat() * 9.0F; +@@ -573,7 +534,6 @@ + PhantomAttackPlayerTargetGoal() {} + + @Override +- @Override + public boolean canUse() { + if (this.nextScanTick > 0) { + --this.nextScanTick; +@@ -583,14 +543,14 @@ + List list = Phantom.this.level().getNearbyPlayers(this.attackTargeting, Phantom.this, Phantom.this.getBoundingBox().inflate(16.0D, 64.0D, 16.0D)); + + if (!list.isEmpty()) { +- list.sort(Comparator.comparing(Entity::getY).reversed()); ++ list.sort(Comparator.comparing((Entity e) -> { return e.getY(); }).reversed()); // CraftBukkit - decompile error + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- Player player = (Player) iterator.next(); ++ Player entityhuman = (Player) iterator.next(); + +- if (Phantom.this.canAttack(player, TargetingConditions.DEFAULT)) { +- Phantom.this.setTarget(player); ++ if (Phantom.this.canAttack(entityhuman, TargetingConditions.DEFAULT)) { ++ Phantom.this.setTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit - reason + return true; + } + } +@@ -601,18 +561,17 @@ + } + + @Override +- @Override + public boolean canContinueToUse() { +- LivingEntity livingentity = Phantom.this.getTarget(); ++ LivingEntity entityliving = Phantom.this.getTarget(); + +- return livingentity != null ? Phantom.this.canAttack(livingentity, TargetingConditions.DEFAULT) : false; ++ return entityliving != null ? Phantom.this.canAttack(entityliving, TargetingConditions.DEFAULT) : false; + } + } + +- private abstract class PhantomMoveTargetGoal extends Goal { ++ private abstract class h extends Goal { + +- public PhantomMoveTargetGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ public h() { ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + protected boolean touchingTarget() { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Ravager.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Ravager.java.patch new file mode 100644 index 0000000000..02751015fc --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Ravager.java.patch @@ -0,0 +1,306 @@ +--- a/net/minecraft/world/entity/monster/Ravager.java ++++ b/net/minecraft/world/entity/monster/Ravager.java +@@ -36,13 +36,17 @@ + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.LeavesBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class Ravager extends Raider { + + private static final Predicate NO_RAVAGER_AND_ALIVE = (entity) -> { +@@ -60,15 +64,14 @@ + private int stunnedTick; + private int roarTick; + +- public Ravager(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Ravager(EntityType entityType, Level level) { ++ super(entityType, level); + this.setMaxUpStep(1.0F); + this.xpReward = 20; + this.setPathfindingMalus(BlockPathTypes.LEAVES, 0.0F); + } + + @Override +- @Override + protected void registerGoals() { + super.registerGoals(); + this.goalSelector.addGoal(0, new FloatGoal(this)); +@@ -78,22 +81,21 @@ + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); + this.targetSelector.addGoal(2, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers()); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, true)); +- this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, true, (livingentity) -> { +- return !livingentity.isBaby(); ++ this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, true, (entityliving) -> { ++ return !entityliving.isBaby(); + })); + this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); + } + + @Override +- @Override + protected void updateControlFlags() { + boolean flag = !(this.getControllingPassenger() instanceof Mob) || this.getControllingPassenger().getType().is(EntityTypeTags.RAIDERS); + boolean flag1 = !(this.getVehicle() instanceof Boat); + +- this.goalSelector.setControlFlag(Goal.Flag.MOVE, flag); +- this.goalSelector.setControlFlag(Goal.Flag.JUMP, flag && flag1); +- this.goalSelector.setControlFlag(Goal.Flag.LOOK, flag); +- this.goalSelector.setControlFlag(Goal.Flag.TARGET, flag); ++ this.goalSelector.setControlFlag(Goal.Type.MOVE, flag); ++ this.goalSelector.setControlFlag(Goal.Type.JUMP, flag && flag1); ++ this.goalSelector.setControlFlag(Goal.Type.LOOK, flag); ++ this.goalSelector.setControlFlag(Goal.Type.TARGET, flag); + } + + public static AttributeSupplier.Builder createAttributes() { +@@ -101,43 +103,37 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("AttackTick", this.attackTick); +- compoundtag.putInt("StunTick", this.stunnedTick); +- compoundtag.putInt("RoarTick", this.roarTick); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("AttackTick", this.attackTick); ++ compound.putInt("StunTick", this.stunnedTick); ++ compound.putInt("RoarTick", this.roarTick); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.attackTick = compoundtag.getInt("AttackTick"); +- this.stunnedTick = compoundtag.getInt("StunTick"); +- this.roarTick = compoundtag.getInt("RoarTick"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.attackTick = compound.getInt("AttackTick"); ++ this.stunnedTick = compound.getInt("StunTick"); ++ this.roarTick = compound.getInt("RoarTick"); + } + + @Override +- @Override + public SoundEvent getCelebrateSound() { + return SoundEvents.RAVAGER_CELEBRATE; + } + + @Override +- @Override + public int getMaxHeadYRot() { + return 45; + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height + 0.0625F * f, -0.0625F * f); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.0625F * f, -0.0625F * f); + } + + @Override +- @Override + public void aiStep() { + super.aiStep(); + if (this.isAlive()) { +@@ -152,16 +148,21 @@ + + if (this.horizontalCollision && this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { + boolean flag = false; +- AABB aabb = this.getBoundingBox().inflate(0.2D); +- Iterator iterator = BlockPos.betweenClosed(Mth.floor(aabb.minX), Mth.floor(aabb.minY), Mth.floor(aabb.minZ), Mth.floor(aabb.maxX), Mth.floor(aabb.maxY), Mth.floor(aabb.maxZ)).iterator(); ++ AABB axisalignedbb = this.getBoundingBox().inflate(0.2D); ++ Iterator iterator = BlockPos.betweenClosed(Mth.floor(axisalignedbb.minX), Mth.floor(axisalignedbb.minY), Mth.floor(axisalignedbb.minZ), Mth.floor(axisalignedbb.maxX), Mth.floor(axisalignedbb.maxY), Mth.floor(axisalignedbb.maxZ)).iterator(); + + while (iterator.hasNext()) { +- BlockPos blockpos = (BlockPos) iterator.next(); +- BlockState blockstate = this.level().getBlockState(blockpos); +- Block block = blockstate.getBlock(); ++ BlockPos blockposition = (BlockPos) iterator.next(); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); ++ Block block = iblockdata.getBlock(); + + if (block instanceof LeavesBlock) { +- flag = this.level().destroyBlock(blockpos, true, this) || flag; ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState())) { ++ continue; ++ } ++ // CraftBukkit end ++ flag = this.level().destroyBlock(blockposition, true, this) || flag; + } + } + +@@ -205,31 +206,28 @@ + } + + @Override +- @Override + protected boolean isImmobile() { + return super.isImmobile() || this.attackTick > 0 || this.stunnedTick > 0 || this.roarTick > 0; + } + + @Override +- @Override + public boolean hasLineOfSight(Entity entity) { + return this.stunnedTick <= 0 && this.roarTick <= 0 ? super.hasLineOfSight(entity) : false; + } + + @Override +- @Override +- protected void blockedByShield(LivingEntity livingentity) { ++ protected void blockedByShield(LivingEntity entity) { + if (this.roarTick == 0) { + if (this.random.nextDouble() < 0.5D) { + this.stunnedTick = 40; + this.playSound(SoundEvents.RAVAGER_STUNNED, 1.0F, 1.0F); + this.level().broadcastEntityEvent(this, (byte) 39); +- livingentity.push(this); ++ entity.push(this); + } else { +- this.strongKnockback(livingentity); ++ this.strongKnockback(entity); + } + +- livingentity.hurtMarked = true; ++ entity.hurtMarked = true; + } + + } +@@ -238,23 +236,23 @@ + if (this.isAlive()) { + List list = this.level().getEntitiesOfClass(LivingEntity.class, this.getBoundingBox().inflate(4.0D), Ravager.NO_RAVAGER_AND_ALIVE); + +- LivingEntity livingentity; ++ LivingEntity entityliving; + +- for (Iterator iterator = list.iterator(); iterator.hasNext(); this.strongKnockback(livingentity)) { +- livingentity = (LivingEntity) iterator.next(); +- if (!(livingentity instanceof AbstractIllager)) { +- livingentity.hurt(this.damageSources().mobAttack(this), 6.0F); ++ for (Iterator iterator = list.iterator(); iterator.hasNext(); this.strongKnockback(entityliving)) { ++ entityliving = (LivingEntity) iterator.next(); ++ if (!(entityliving instanceof AbstractIllager)) { ++ entityliving.hurt(this.damageSources().mobAttack(this), 6.0F); + } + } + +- Vec3 vec3 = this.getBoundingBox().getCenter(); ++ Vec3 vec3d = this.getBoundingBox().getCenter(); + + for (int i = 0; i < 40; ++i) { + double d0 = this.random.nextGaussian() * 0.2D; + double d1 = this.random.nextGaussian() * 0.2D; + double d2 = this.random.nextGaussian() * 0.2D; + +- this.level().addParticle(ParticleTypes.POOF, vec3.x, vec3.y, vec3.z, d0, d1, d2); ++ this.level().addParticle(ParticleTypes.POOF, vec3d.x, vec3d.y, vec3d.z, d0, d1, d2); + } + + this.gameEvent(GameEvent.ENTITY_ACTION); +@@ -271,16 +269,15 @@ + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 4) { ++ public void handleEntityEvent(byte id) { ++ if (id == 4) { + this.attackTick = 10; + this.playSound(SoundEvents.RAVAGER_ATTACK, 1.0F, 1.0F); +- } else if (b0 == 39) { ++ } else if (id == 39) { + this.stunnedTick = 40; + } + +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + public int getAttackTick() { +@@ -296,7 +293,6 @@ + } + + @Override +- @Override + public boolean doHurtTarget(Entity entity) { + this.attackTick = 10; + this.level().broadcastEntityEvent(this, (byte) 4); +@@ -306,50 +302,42 @@ + + @Nullable + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.RAVAGER_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.RAVAGER_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.RAVAGER_DEATH; + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.RAVAGER_STEP, 0.15F, 1.0F); + } + + @Override +- @Override +- public boolean checkSpawnObstruction(LevelReader levelreader) { +- return !levelreader.containsAnyLiquid(this.getBoundingBox()); ++ public boolean checkSpawnObstruction(LevelReader level) { ++ return !level.containsAnyLiquid(this.getBoundingBox()); + } + + @Override +- @Override +- public void applyRaidBuffs(int i, boolean flag) {} ++ public void applyRaidBuffs(int wave, boolean unusedFalse) {} + + @Override +- @Override + public boolean canBeLeader() { + return false; + } + + @Override +- @Override + protected AABB getAttackBoundingBox() { +- AABB aabb = super.getAttackBoundingBox(); ++ AABB axisalignedbb = super.getAttackBoundingBox(); + +- return aabb.deflate(0.05D, 0.0D, 0.05D); ++ return axisalignedbb.deflate(0.05D, 0.0D, 0.05D); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Shulker.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Shulker.java.patch new file mode 100644 index 0000000000..281a1fe86b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Shulker.java.patch @@ -0,0 +1,821 @@ +--- a/net/minecraft/world/entity/monster/Shulker.java ++++ b/net/minecraft/world/entity/monster/Shulker.java +@@ -25,14 +25,14 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMoveType; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.VariantHolder; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -52,20 +52,26 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.entity.EntityTypeTest; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Shulker extends AbstractGolem implements VariantHolder>, Enemy { ++// CraftBukkit start ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.entity.EntityTeleportEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + ++public class Shulker extends AbstractGolem implements VariantHolder>, IMonster { ++ + private static final UUID COVERED_ARMOR_MODIFIER_UUID = UUID.fromString("7E0292F2-9434-48D5-A29F-9583AF7DF27F"); + private static final AttributeModifier COVERED_ARMOR_MODIFIER = new AttributeModifier(Shulker.COVERED_ARMOR_MODIFIER_UUID, "Covered armor bonus", 20.0D, AttributeModifier.Operation.ADDITION); + protected static final EntityDataAccessor DATA_ATTACH_FACE_ID = SynchedEntityData.defineId(Shulker.class, EntityDataSerializers.DIRECTION); + protected static final EntityDataAccessor DATA_PEEK_ID = SynchedEntityData.defineId(Shulker.class, EntityDataSerializers.BYTE); +- protected static final EntityDataAccessor DATA_COLOR_ID = SynchedEntityData.defineId(Shulker.class, EntityDataSerializers.BYTE); ++ public static final EntityDataAccessor DATA_COLOR_ID = SynchedEntityData.defineId(Shulker.class, EntityDataSerializers.BYTE); + private static final int TELEPORT_STEPS = 6; + private static final byte NO_COLOR = 16; + private static final byte DEFAULT_COLOR = 16; +@@ -74,9 +80,9 @@ + private static final int OTHER_SHULKER_LIMIT = 5; + private static final float PEEK_PER_TICK = 0.05F; + static final Vector3f FORWARD = (Vector3f) Util.make(() -> { +- Vec3i vec3i = Direction.SOUTH.getNormal(); ++ Vec3i baseblockposition = Direction.SOUTH.getNormal(); + +- return new Vector3f((float) vec3i.getX(), (float) vec3i.getY(), (float) vec3i.getZ()); ++ return new Vector3f((float) baseblockposition.getX(), (float) baseblockposition.getY(), (float) baseblockposition.getZ()); + }); + private float currentPeekAmountO; + private float currentPeekAmount; +@@ -85,14 +91,13 @@ + private int clientSideTeleportInterpolation; + private static final float MAX_LID_OPEN = 1.0F; + +- public Shulker(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Shulker(EntityType entityType, Level level) { ++ super(entityType, level); + this.xpReward = 5; + this.lookControl = new Shulker.ShulkerLookControl(this); + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new LookAtPlayerGoal(this, Player.class, 8.0F, 0.02F, true)); + this.goalSelector.addGoal(4, new Shulker.ShulkerAttackGoal()); +@@ -104,25 +109,21 @@ + } + + @Override +- @Override + protected Entity.MovementEmission getMovementEmission() { + return Entity.MovementEmission.NONE; + } + + @Override +- @Override + public SoundSource getSoundSource() { + return SoundSource.HOSTILE; + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.SHULKER_AMBIENT; + } + + @Override +- @Override + public void playAmbientSound() { + if (!this.isClosed()) { + super.playAmbientSound(); +@@ -131,19 +132,16 @@ + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.SHULKER_DEATH; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return this.isClosed() ? SoundEvents.SHULKER_HURT_CLOSED : SoundEvents.SHULKER_HURT; + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Shulker.DATA_ATTACH_FACE_ID, Direction.DOWN); +@@ -156,34 +154,30 @@ + } + + @Override +- @Override + protected BodyRotationControl createBodyControl() { + return new Shulker.ShulkerBodyRotationControl(this); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setAttachFace(Direction.from3DDataValue(compoundtag.getByte("AttachFace"))); +- this.entityData.set(Shulker.DATA_PEEK_ID, compoundtag.getByte("Peek")); +- if (compoundtag.contains("Color", 99)) { +- this.entityData.set(Shulker.DATA_COLOR_ID, compoundtag.getByte("Color")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setAttachFace(Direction.from3DDataValue(compound.getByte("AttachFace"))); ++ this.entityData.set(Shulker.DATA_PEEK_ID, compound.getByte("Peek")); ++ if (compound.contains("Color", 99)) { ++ this.entityData.set(Shulker.DATA_COLOR_ID, compound.getByte("Color")); + } + + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putByte("AttachFace", (byte) this.getAttachFace().get3DDataValue()); +- compoundtag.putByte("Peek", (Byte) this.entityData.get(Shulker.DATA_PEEK_ID)); +- compoundtag.putByte("Color", (Byte) this.entityData.get(Shulker.DATA_COLOR_ID)); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putByte("AttachFace", (byte) this.getAttachFace().get3DDataValue()); ++ compound.putByte("Peek", (Byte) this.entityData.get(Shulker.DATA_PEEK_ID)); ++ compound.putByte("Color", (Byte) this.entityData.get(Shulker.DATA_COLOR_ID)); + } + + @Override +- @Override + public void tick() { + super.tick(); + if (!this.level().isClientSide && !this.isPassenger() && !this.canStayAt(this.blockPosition(), this.getAttachFace())) { +@@ -205,10 +199,10 @@ + } + + private void findNewAttachment() { +- Direction direction = this.findAttachableSurface(this.blockPosition()); ++ Direction enumdirection = this.findAttachableSurface(this.blockPosition()); + +- if (direction != null) { +- this.setAttachFace(direction); ++ if (enumdirection != null) { ++ this.setAttachFace(enumdirection); + } else { + this.teleportSomewhere(); + } +@@ -216,17 +210,16 @@ + } + + @Override +- @Override + protected AABB makeBoundingBox() { + float f = getPhysicalPeek(this.currentPeekAmount); +- Direction direction = this.getAttachFace().getOpposite(); ++ Direction enumdirection = this.getAttachFace().getOpposite(); + float f1 = this.getType().getWidth() / 2.0F; + +- return getProgressAabb(direction, f).move(this.getX() - (double) f1, this.getY(), this.getZ() - (double) f1); ++ return getProgressAabb(enumdirection, f).move(this.getX() - (double) f1, this.getY(), this.getZ() - (double) f1); + } + +- private static float getPhysicalPeek(float f) { +- return 0.5F - Mth.sin((0.5F + f) * 3.1415927F) * 0.5F; ++ private static float getPhysicalPeek(float peek) { ++ return 0.5F - Mth.sin((0.5F + peek) * 3.1415927F) * 0.5F; + } + + private boolean updatePeekAmount() { +@@ -250,11 +243,11 @@ + this.reapplyPosition(); + float f = getPhysicalPeek(this.currentPeekAmount); + float f1 = getPhysicalPeek(this.currentPeekAmountO); +- Direction direction = this.getAttachFace().getOpposite(); ++ Direction enumdirection = this.getAttachFace().getOpposite(); + float f2 = f - f1; + + if (f2 > 0.0F) { +- List list = this.level().getEntities((Entity) this, getProgressDeltaAabb(direction, f1, f).move(this.getX() - 0.5D, this.getY(), this.getZ() - 0.5D), EntitySelector.NO_SPECTATORS.and((entity) -> { ++ List list = this.level().getEntities((Entity) this, getProgressDeltaAabb(enumdirection, f1, f).move(this.getX() - 0.5D, this.getY(), this.getZ() - 0.5D), EntitySelector.NO_SPECTATORS.and((entity) -> { + return !entity.isPassengerOfSameVehicle(this); + })); + Iterator iterator = list.iterator(); +@@ -263,38 +256,36 @@ + Entity entity = (Entity) iterator.next(); + + if (!(entity instanceof Shulker) && !entity.noPhysics) { +- entity.move(MoverType.SHULKER, new Vec3((double) (f2 * (float) direction.getStepX()), (double) (f2 * (float) direction.getStepY()), (double) (f2 * (float) direction.getStepZ()))); ++ entity.move(EnumMoveType.SHULKER, new Vec3((double) (f2 * (float) enumdirection.getStepX()), (double) (f2 * (float) enumdirection.getStepY()), (double) (f2 * (float) enumdirection.getStepZ()))); + } + } + + } + } + +- public static AABB getProgressAabb(Direction direction, float f) { +- return getProgressDeltaAabb(direction, -1.0F, f); ++ public static AABB getProgressAabb(Direction direction, float delta) { ++ return getProgressDeltaAabb(direction, -1.0F, delta); + } + +- public static AABB getProgressDeltaAabb(Direction direction, float f, float f1) { +- double d0 = (double) Math.max(f, f1); +- double d1 = (double) Math.min(f, f1); ++ public static AABB getProgressDeltaAabb(Direction direction, float delta, float deltaO) { ++ double d0 = (double) Math.max(delta, deltaO); ++ double d1 = (double) Math.min(delta, deltaO); + + return (new AABB(BlockPos.ZERO)).expandTowards((double) direction.getStepX() * d0, (double) direction.getStepY() * d0, (double) direction.getStepZ() * d0).contract((double) (-direction.getStepX()) * (1.0D + d1), (double) (-direction.getStepY()) * (1.0D + d1), (double) (-direction.getStepZ()) * (1.0D + d1)); + } + + @Override +- @Override +- public boolean startRiding(Entity entity, boolean flag) { ++ public boolean startRiding(Entity entity, boolean force) { + if (this.level().isClientSide()) { + this.clientOldAttachPosition = null; + this.clientSideTeleportInterpolation = 0; + } + + this.setAttachFace(Direction.DOWN); +- return super.startRiding(entity, flag); ++ return super.startRiding(entity, force); + } + + @Override +- @Override + public void stopRiding() { + super.stopRiding(); + if (this.level().isClientSide) { +@@ -307,54 +298,49 @@ + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + this.setYRot(0.0F); + this.yHeadRot = this.getYRot(); + this.setOldPosAndRot(); +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); ++ return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + + @Override +- @Override +- public void move(MoverType movertype, Vec3 vec3) { +- if (movertype == MoverType.SHULKER_BOX) { ++ public void move(EnumMoveType type, Vec3 pos) { ++ if (type == EnumMoveType.SHULKER_BOX) { + this.teleportSomewhere(); + } else { +- super.move(movertype, vec3); ++ super.move(type, pos); + } + + } + + @Override +- @Override + public Vec3 getDeltaMovement() { + return Vec3.ZERO; + } + + @Override +- @Override +- public void setDeltaMovement(Vec3 vec3) {} ++ public void setDeltaMovement(Vec3 deltaMovement) {} + + @Override +- @Override +- public void setPos(double d0, double d1, double d2) { +- BlockPos blockpos = this.blockPosition(); ++ public void setPos(double x, double d1, double y) { ++ BlockPos blockposition = this.blockPosition(); + + if (this.isPassenger()) { +- super.setPos(d0, d1, d2); ++ super.setPos(x, d1, y); + } else { +- super.setPos((double) Mth.floor(d0) + 0.5D, (double) Mth.floor(d1 + 0.5D), (double) Mth.floor(d2) + 0.5D); ++ super.setPos((double) Mth.floor(x) + 0.5D, (double) Mth.floor(d1 + 0.5D), (double) Mth.floor(y) + 0.5D); + } + + if (this.tickCount != 0) { +- BlockPos blockpos1 = this.blockPosition(); ++ BlockPos blockposition1 = this.blockPosition(); + +- if (!blockpos1.equals(blockpos)) { ++ if (!blockposition1.equals(blockposition)) { + this.entityData.set(Shulker.DATA_PEEK_ID, (byte) 0); + this.hasImpulse = true; +- if (this.level().isClientSide && !this.isPassenger() && !blockpos1.equals(this.clientOldAttachPosition)) { +- this.clientOldAttachPosition = blockpos; ++ if (this.level().isClientSide && !this.isPassenger() && !blockposition1.equals(this.clientOldAttachPosition)) { ++ this.clientOldAttachPosition = blockposition; + this.clientSideTeleportInterpolation = 6; + this.xOld = this.getX(); + this.yOld = this.getY(); +@@ -366,44 +352,44 @@ + } + + @Nullable +- protected Direction findAttachableSurface(BlockPos blockpos) { +- Direction[] adirection = Direction.values(); +- int i = adirection.length; ++ protected Direction findAttachableSurface(BlockPos pos) { ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; ++ Direction enumdirection = aenumdirection[j]; + +- if (this.canStayAt(blockpos, direction)) { +- return direction; ++ if (this.canStayAt(pos, enumdirection)) { ++ return enumdirection; + } + } + + return null; + } + +- boolean canStayAt(BlockPos blockpos, Direction direction) { +- if (this.isPositionBlocked(blockpos)) { ++ boolean canStayAt(BlockPos pos, Direction facing) { ++ if (this.isPositionBlocked(pos)) { + return false; + } else { +- Direction direction1 = direction.getOpposite(); ++ Direction enumdirection1 = facing.getOpposite(); + +- if (!this.level().loadedAndEntityCanStandOnFace(blockpos.relative(direction), this, direction1)) { ++ if (!this.level().loadedAndEntityCanStandOnFace(pos.relative(facing), this, enumdirection1)) { + return false; + } else { +- AABB aabb = getProgressAabb(direction1, 1.0F).move(blockpos).deflate(1.0E-6D); ++ AABB axisalignedbb = getProgressAabb(enumdirection1, 1.0F).move(pos).deflate(1.0E-6D); + +- return this.level().noCollision(this, aabb); ++ return this.level().noCollision(this, axisalignedbb); + } + } + } + +- private boolean isPositionBlocked(BlockPos blockpos) { +- BlockState blockstate = this.level().getBlockState(blockpos); ++ private boolean isPositionBlocked(BlockPos pos) { ++ IBlockData iblockdata = this.level().getBlockState(pos); + +- if (blockstate.isAir()) { ++ if (iblockdata.isAir()) { + return false; + } else { +- boolean flag = blockstate.is(Blocks.MOVING_PISTON) && blockpos.equals(this.blockPosition()); ++ boolean flag = iblockdata.is(Blocks.MOVING_PISTON) && pos.equals(this.blockPosition()); + + return !flag; + } +@@ -411,20 +397,28 @@ + + protected boolean teleportSomewhere() { + if (!this.isNoAi() && this.isAlive()) { +- BlockPos blockpos = this.blockPosition(); ++ BlockPos blockposition = this.blockPosition(); + + for (int i = 0; i < 5; ++i) { +- BlockPos blockpos1 = blockpos.offset(Mth.randomBetweenInclusive(this.random, -8, 8), Mth.randomBetweenInclusive(this.random, -8, 8), Mth.randomBetweenInclusive(this.random, -8, 8)); ++ BlockPos blockposition1 = blockposition.offset(Mth.randomBetweenInclusive(this.random, -8, 8), Mth.randomBetweenInclusive(this.random, -8, 8), Mth.randomBetweenInclusive(this.random, -8, 8)); + +- if (blockpos1.getY() > this.level().getMinBuildHeight() && this.level().isEmptyBlock(blockpos1) && this.level().getWorldBorder().isWithinBounds(blockpos1) && this.level().noCollision(this, (new AABB(blockpos1)).deflate(1.0E-6D))) { +- Direction direction = this.findAttachableSurface(blockpos1); ++ if (blockposition1.getY() > this.level().getMinBuildHeight() && this.level().isEmptyBlock(blockposition1) && this.level().getWorldBorder().isWithinBounds(blockposition1) && this.level().noCollision(this, (new AABB(blockposition1)).deflate(1.0E-6D))) { ++ Direction enumdirection = this.findAttachableSurface(blockposition1); + +- if (direction != null) { ++ if (enumdirection != null) { ++ // CraftBukkit start ++ EntityTeleportEvent teleportEvent = CraftEventFactory.callEntityTeleportEvent(this, blockposition1.getX(), blockposition1.getY(), blockposition1.getZ()); ++ if (teleportEvent.isCancelled()) { ++ return false; ++ } else { ++ blockposition1 = CraftLocation.toBlockPosition(teleportEvent.getTo()); ++ } ++ // CraftBukkit end + this.unRide(); +- this.setAttachFace(direction); ++ this.setAttachFace(enumdirection); + this.playSound(SoundEvents.SHULKER_TELEPORT, 1.0F, 1.0F); +- this.setPos((double) blockpos1.getX() + 0.5D, (double) blockpos1.getY(), (double) blockpos1.getZ() + 0.5D); +- this.level().gameEvent(GameEvent.TELEPORT, blockpos, GameEvent.Context.of((Entity) this)); ++ this.setPos((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY(), (double) blockposition1.getZ() + 0.5D); ++ this.level().gameEvent(GameEvent.TELEPORT, blockposition, GameEvent.Context.of((Entity) this)); + this.entityData.set(Shulker.DATA_PEEK_ID, (byte) 0); + this.setTarget((LivingEntity) null); + return true; +@@ -439,7 +433,6 @@ + } + + @Override +- @Override + public void lerpTo(double d0, double d1, double d2, float f, float f1, int i) { + this.lerpSteps = 0; + this.setPos(d0, d1, d2); +@@ -447,24 +440,23 @@ + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { ++ public boolean hurt(DamageSource source, float amount) { + Entity entity; + + if (this.isClosed()) { +- entity = damagesource.getDirectEntity(); ++ entity = source.getDirectEntity(); + if (entity instanceof AbstractArrow) { + return false; + } + } + +- if (!super.hurt(damagesource, f)) { ++ if (!super.hurt(source, amount)) { + return false; + } else { + if ((double) this.getHealth() < (double) this.getMaxHealth() * 0.5D && this.random.nextInt(4) == 0) { + this.teleportSomewhere(); +- } else if (damagesource.is(DamageTypeTags.IS_PROJECTILE)) { +- entity = damagesource.getDirectEntity(); ++ } else if (source.is(DamageTypeTags.IS_PROJECTILE)) { ++ entity = source.getDirectEntity(); + if (entity != null && entity.getType() == EntityType.SHULKER_BULLET) { + this.hitByShulkerBullet(); + } +@@ -479,20 +471,20 @@ + } + + private void hitByShulkerBullet() { +- Vec3 vec3 = this.position(); +- AABB aabb = this.getBoundingBox(); ++ Vec3 vec3d = this.position(); ++ AABB axisalignedbb = this.getBoundingBox(); + + if (!this.isClosed() && this.teleportSomewhere()) { +- int i = this.level().getEntities((EntityTypeTest) EntityType.SHULKER, aabb.inflate(8.0D), Entity::isAlive).size(); ++ int i = this.level().getEntities((EntityTypeTest) EntityType.SHULKER, axisalignedbb.inflate(8.0D), Entity::isAlive).size(); + float f = (float) (i - 1) / 5.0F; + + if (this.level().random.nextFloat() >= f) { +- Shulker shulker = (Shulker) EntityType.SHULKER.create(this.level()); ++ Shulker entityshulker = (Shulker) EntityType.SHULKER.create(this.level()); + +- if (shulker != null) { +- shulker.setVariant(this.getVariant()); +- shulker.moveTo(vec3); +- this.level().addFreshEntity(shulker); ++ if (entityshulker != null) { ++ entityshulker.setVariant(this.getVariant()); ++ entityshulker.moveTo(vec3d); ++ this.level().addFreshEntity(entityshulker, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - the mysteries of life + } + + } +@@ -500,7 +492,6 @@ + } + + @Override +- @Override + public boolean canBeCollidedWith() { + return this.isAlive(); + } +@@ -509,28 +500,27 @@ + return (Direction) this.entityData.get(Shulker.DATA_ATTACH_FACE_ID); + } + +- private void setAttachFace(Direction direction) { +- this.entityData.set(Shulker.DATA_ATTACH_FACE_ID, direction); ++ public void setAttachFace(Direction attachFace) { ++ this.entityData.set(Shulker.DATA_ATTACH_FACE_ID, attachFace); + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- if (Shulker.DATA_ATTACH_FACE_ID.equals(entitydataaccessor)) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ if (Shulker.DATA_ATTACH_FACE_ID.equals(key)) { + this.setBoundingBox(this.makeBoundingBox()); + } + +- super.onSyncedDataUpdated(entitydataaccessor); ++ super.onSyncedDataUpdated(key); + } + +- private int getRawPeekAmount() { ++ public int getRawPeekAmount() { + return (Byte) this.entityData.get(Shulker.DATA_PEEK_ID); + } + +- void setRawPeekAmount(int i) { ++ public void setRawPeekAmount(int peekAmount) { + if (!this.level().isClientSide) { + this.getAttribute(Attributes.ARMOR).removeModifier(Shulker.COVERED_ARMOR_MODIFIER.getId()); +- if (i == 0) { ++ if (peekAmount == 0) { + this.getAttribute(Attributes.ARMOR).addPermanentModifier(Shulker.COVERED_ARMOR_MODIFIER); + this.playSound(SoundEvents.SHULKER_CLOSE, 1.0F, 1.0F); + this.gameEvent(GameEvent.CONTAINER_CLOSE); +@@ -540,52 +530,47 @@ + } + } + +- this.entityData.set(Shulker.DATA_PEEK_ID, (byte) i); ++ this.entityData.set(Shulker.DATA_PEEK_ID, (byte) peekAmount); + } + +- public float getClientPeekAmount(float f) { +- return Mth.lerp(f, this.currentPeekAmountO, this.currentPeekAmount); ++ public float getClientPeekAmount(float partialTick) { ++ return Mth.lerp(partialTick, this.currentPeekAmountO, this.currentPeekAmount); + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.5F; + } + + @Override +- @Override +- public void recreateFromPacket(ClientboundAddEntityPacket clientboundaddentitypacket) { +- super.recreateFromPacket(clientboundaddentitypacket); ++ public void recreateFromPacket(ClientboundAddEntityPacket packet) { ++ super.recreateFromPacket(packet); + this.yBodyRot = 0.0F; + this.yBodyRotO = 0.0F; + } + + @Override +- @Override + public int getMaxHeadXRot() { + return 180; + } + + @Override +- @Override + public int getMaxHeadYRot() { + return 180; + } + + @Override +- @Override + public void push(Entity entity) {} + +- public Optional getRenderPosition(float f) { ++ public Optional getRenderPosition(float partial) { + if (this.clientOldAttachPosition != null && this.clientSideTeleportInterpolation > 0) { +- double d0 = (double) ((float) this.clientSideTeleportInterpolation - f) / 6.0D; ++ double d0 = (double) ((float) this.clientSideTeleportInterpolation - partial) / 6.0D; + + d0 *= d0; +- BlockPos blockpos = this.blockPosition(); +- double d1 = (double) (blockpos.getX() - this.clientOldAttachPosition.getX()) * d0; +- double d2 = (double) (blockpos.getY() - this.clientOldAttachPosition.getY()) * d0; +- double d3 = (double) (blockpos.getZ() - this.clientOldAttachPosition.getZ()) * d0; ++ BlockPos blockposition = this.blockPosition(); ++ double d1 = (double) (blockposition.getX() - this.clientOldAttachPosition.getX()) * d0; ++ double d2 = (double) (blockposition.getY() - this.clientOldAttachPosition.getY()) * d0; ++ double d3 = (double) (blockposition.getZ() - this.clientOldAttachPosition.getZ()) * d0; + + return Optional.of(new Vec3(-d1, -d2, -d3)); + } else { +@@ -593,15 +578,13 @@ + } + } + +- @Override +- public void setVariant(Optional optional) { +- this.entityData.set(Shulker.DATA_COLOR_ID, (Byte) optional.map((dyecolor) -> { +- return (byte) dyecolor.getId(); ++ public void setVariant(Optional variant) { ++ this.entityData.set(Shulker.DATA_COLOR_ID, (Byte) variant.map((enumcolor) -> { ++ return (byte) enumcolor.getId(); + }).orElse((byte) 16)); + } + + @Override +- @Override + public Optional getVariant() { + return Optional.ofNullable(this.getColor()); + } +@@ -620,16 +603,14 @@ + } + + @Override +- @Override + protected void clampHeadRotationToBody() {} + + @Override +- @Override + protected Optional getYRotD() { +- Direction direction = Shulker.this.getAttachFace().getOpposite(); +- Vector3f vector3f = direction.getRotation().transform(new Vector3f(Shulker.FORWARD)); +- Vec3i vec3i = direction.getNormal(); +- Vector3f vector3f1 = new Vector3f((float) vec3i.getX(), (float) vec3i.getY(), (float) vec3i.getZ()); ++ Direction enumdirection = Shulker.this.getAttachFace().getOpposite(); ++ Vector3f vector3f = enumdirection.getRotation().transform(new Vector3f(Shulker.FORWARD)); ++ Vec3i baseblockposition = enumdirection.getNormal(); ++ Vector3f vector3f1 = new Vector3f((float) baseblockposition.getX(), (float) baseblockposition.getY(), (float) baseblockposition.getZ()); + + vector3f1.cross(vector3f); + double d0 = this.wantedX - this.mob.getX(); +@@ -643,7 +624,6 @@ + } + + @Override +- @Override + protected Optional getXRotD() { + return Optional.of(0.0F); + } +@@ -654,51 +634,46 @@ + private int attackTime; + + public ShulkerAttackGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + } + + @Override +- @Override + public boolean canUse() { +- LivingEntity livingentity = Shulker.this.getTarget(); ++ LivingEntity entityliving = Shulker.this.getTarget(); + +- return livingentity != null && livingentity.isAlive() ? Shulker.this.level().getDifficulty() != Difficulty.PEACEFUL : false; ++ return entityliving != null && entityliving.isAlive() ? Shulker.this.level().getDifficulty() != Difficulty.PEACEFUL : false; + } + + @Override +- @Override + public void start() { + this.attackTime = 20; + Shulker.this.setRawPeekAmount(100); + } + + @Override +- @Override + public void stop() { + Shulker.this.setRawPeekAmount(0); + } + + @Override +- @Override + public boolean requiresUpdateEveryTick() { + return true; + } + + @Override +- @Override + public void tick() { + if (Shulker.this.level().getDifficulty() != Difficulty.PEACEFUL) { + --this.attackTime; +- LivingEntity livingentity = Shulker.this.getTarget(); ++ LivingEntity entityliving = Shulker.this.getTarget(); + +- if (livingentity != null) { +- Shulker.this.getLookControl().setLookAt(livingentity, 180.0F, 180.0F); +- double d0 = Shulker.this.distanceToSqr((Entity) livingentity); ++ if (entityliving != null) { ++ Shulker.this.getLookControl().setLookAt(entityliving, 180.0F, 180.0F); ++ double d0 = Shulker.this.distanceToSqr((Entity) entityliving); + + if (d0 < 400.0D) { + if (this.attackTime <= 0) { + this.attackTime = 20 + Shulker.this.random.nextInt(10) * 20 / 2; +- Shulker.this.level().addFreshEntity(new ShulkerBullet(Shulker.this.level(), Shulker.this, livingentity, Shulker.this.getAttachFace().getAxis())); ++ Shulker.this.level().addFreshEntity(new ShulkerBullet(Shulker.this.level(), Shulker.this, entityliving, Shulker.this.getAttachFace().getAxis())); + Shulker.this.playSound(SoundEvents.SHULKER_SHOOT, 2.0F, (Shulker.this.random.nextFloat() - Shulker.this.random.nextFloat()) * 0.2F + 1.0F); + } + } else { +@@ -718,26 +693,22 @@ + ShulkerPeekGoal() {} + + @Override +- @Override + public boolean canUse() { + return Shulker.this.getTarget() == null && Shulker.this.random.nextInt(reducedTickDelay(40)) == 0 && Shulker.this.canStayAt(Shulker.this.blockPosition(), Shulker.this.getAttachFace()); + } + + @Override +- @Override + public boolean canContinueToUse() { + return Shulker.this.getTarget() == null && this.peekTime > 0; + } + + @Override +- @Override + public void start() { + this.peekTime = this.adjustedTickDelay(20 * (1 + Shulker.this.random.nextInt(3))); + Shulker.this.setRawPeekAmount(30); + } + + @Override +- @Override + public void stop() { + if (Shulker.this.getTarget() == null) { + Shulker.this.setRawPeekAmount(0); +@@ -746,7 +717,6 @@ + } + + @Override +- @Override + public void tick() { + --this.peekTime; + } +@@ -754,45 +724,41 @@ + + private class ShulkerNearestAttackGoal extends NearestAttackableTargetGoal { + +- public ShulkerNearestAttackGoal(Shulker shulker) { +- super(shulker, Player.class, true); ++ public ShulkerNearestAttackGoal(Shulker entityshulker) { ++ super(entityshulker, Player.class, true); + } + + @Override +- @Override + public boolean canUse() { + return Shulker.this.level().getDifficulty() == Difficulty.PEACEFUL ? false : super.canUse(); + } + + @Override +- @Override +- protected AABB getTargetSearchArea(double d0) { +- Direction direction = ((Shulker) this.mob).getAttachFace(); ++ protected AABB getTargetSearchArea(double targetDistance) { ++ Direction enumdirection = ((Shulker) this.mob).getAttachFace(); + +- return direction.getAxis() == Direction.Axis.X ? this.mob.getBoundingBox().inflate(4.0D, d0, d0) : (direction.getAxis() == Direction.Axis.Z ? this.mob.getBoundingBox().inflate(d0, d0, 4.0D) : this.mob.getBoundingBox().inflate(d0, 4.0D, d0)); ++ return enumdirection.getAxis() == Direction.Axis.X ? this.mob.getBoundingBox().inflate(4.0D, targetDistance, targetDistance) : (enumdirection.getAxis() == Direction.Axis.Z ? this.mob.getBoundingBox().inflate(targetDistance, targetDistance, 4.0D) : this.mob.getBoundingBox().inflate(targetDistance, 4.0D, targetDistance)); + } + } + + private static class ShulkerDefenseAttackGoal extends NearestAttackableTargetGoal { + + public ShulkerDefenseAttackGoal(Shulker shulker) { +- super(shulker, LivingEntity.class, 10, true, false, (livingentity) -> { +- return livingentity instanceof Enemy; ++ super(shulker, LivingEntity.class, 10, true, false, (entityliving) -> { ++ return entityliving instanceof IMonster; + }); + } + + @Override +- @Override + public boolean canUse() { + return this.mob.getTeam() == null ? false : super.canUse(); + } + + @Override +- @Override +- protected AABB getTargetSearchArea(double d0) { +- Direction direction = ((Shulker) this.mob).getAttachFace(); ++ protected AABB getTargetSearchArea(double targetDistance) { ++ Direction enumdirection = ((Shulker) this.mob).getAttachFace(); + +- return direction.getAxis() == Direction.Axis.X ? this.mob.getBoundingBox().inflate(4.0D, d0, d0) : (direction.getAxis() == Direction.Axis.Z ? this.mob.getBoundingBox().inflate(d0, d0, 4.0D) : this.mob.getBoundingBox().inflate(d0, 4.0D, d0)); ++ return enumdirection.getAxis() == Direction.Axis.X ? this.mob.getBoundingBox().inflate(4.0D, targetDistance, targetDistance) : (enumdirection.getAxis() == Direction.Axis.Z ? this.mob.getBoundingBox().inflate(targetDistance, targetDistance, 4.0D) : this.mob.getBoundingBox().inflate(targetDistance, 4.0D, targetDistance)); + } + } + +@@ -803,7 +769,6 @@ + } + + @Override +- @Override + public void clientTick() {} + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Silverfish.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Silverfish.java.patch new file mode 100644 index 0000000000..5049a1156e --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Silverfish.java.patch @@ -0,0 +1,270 @@ +--- a/net/minecraft/world/entity/monster/Silverfish.java ++++ b/net/minecraft/world/entity/monster/Silverfish.java +@@ -11,10 +11,10 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.Pose; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.ClimbOnTopOfPowderSnowGoal; +@@ -31,20 +31,23 @@ + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.InfestedBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class Silverfish extends Monster { + + @Nullable + private Silverfish.SilverfishWakeUpFriendsGoal friendsGoal; + +- public Silverfish(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Silverfish(EntityType entityType, Level level) { ++ super(entityType, level); + } + + @Override +- @Override + protected void registerGoals() { + this.friendsGoal = new Silverfish.SilverfishWakeUpFriendsGoal(this); + this.goalSelector.addGoal(1, new FloatGoal(this)); +@@ -57,8 +60,7 @@ + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.13F; + } + +@@ -67,89 +69,78 @@ + } + + @Override +- @Override + protected Entity.MovementEmission getMovementEmission() { + return Entity.MovementEmission.EVENTS; + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.SILVERFISH_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.SILVERFISH_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.SILVERFISH_DEATH; + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.SILVERFISH_STEP, 0.15F, 1.0F); + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- if (this.isInvulnerableTo(damagesource)) { ++ public boolean hurt(DamageSource source, float amount) { ++ if (this.isInvulnerableTo(source)) { + return false; + } else { +- if ((damagesource.getEntity() != null || damagesource.is(DamageTypeTags.ALWAYS_TRIGGERS_SILVERFISH)) && this.friendsGoal != null) { ++ if ((source.getEntity() != null || source.is(DamageTypeTags.ALWAYS_TRIGGERS_SILVERFISH)) && this.friendsGoal != null) { + this.friendsGoal.notifyHurt(); + } + +- return super.hurt(damagesource, f); ++ return super.hurt(source, amount); + } + } + + @Override +- @Override + public void tick() { + this.yBodyRot = this.getYRot(); + super.tick(); + } + + @Override +- @Override +- public void setYBodyRot(float f) { +- this.setYRot(f); +- super.setYBodyRot(f); ++ public void setYBodyRot(float offset) { ++ this.setYRot(offset); ++ super.setYBodyRot(offset); + } + + @Override +- @Override +- public float getWalkTargetValue(BlockPos blockpos, LevelReader levelreader) { +- return InfestedBlock.isCompatibleHostBlock(levelreader.getBlockState(blockpos.below())) ? 10.0F : super.getWalkTargetValue(blockpos, levelreader); ++ public float getWalkTargetValue(BlockPos pos, LevelReader level) { ++ return InfestedBlock.isCompatibleHostBlock(level.getBlockState(pos.below())) ? 10.0F : super.getWalkTargetValue(pos, level); + } + +- public static boolean checkSilverfishSpawnRules(EntityType entitytype, LevelAccessor levelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- if (checkAnyLightMonsterSpawnRules(entitytype, levelaccessor, mobspawntype, blockpos, randomsource)) { +- Player player = levelaccessor.getNearestPlayer((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D, 5.0D, true); ++ public static boolean checkSilverfishSpawnRules(EntityType silverfish, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ if (checkAnyLightMonsterSpawnRules(silverfish, level, spawnType, pos, random)) { ++ Player entityhuman = level.getNearestPlayer((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, 5.0D, true); + +- return player == null; ++ return entityhuman == null; + } else { + return false; + } + } + + @Override +- @Override +- public MobType getMobType() { +- return MobType.ARTHROPOD; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.ARTHROPOD; + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height - 0.0625F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.0625F * f, 0.0F); + } + + private static class SilverfishWakeUpFriendsGoal extends Goal { +@@ -169,32 +160,35 @@ + } + + @Override +- @Override + public boolean canUse() { + return this.lookForFriends > 0; + } + + @Override +- @Override + public void tick() { + --this.lookForFriends; + if (this.lookForFriends <= 0) { +- Level level = this.silverfish.level(); ++ Level world = this.silverfish.level(); + RandomSource randomsource = this.silverfish.getRandom(); +- BlockPos blockpos = this.silverfish.blockPosition(); ++ BlockPos blockposition = this.silverfish.blockPosition(); + + for (int i = 0; i <= 5 && i >= -5; i = (i <= 0 ? 1 : 0) - i) { + for (int j = 0; j <= 10 && j >= -10; j = (j <= 0 ? 1 : 0) - j) { + for (int k = 0; k <= 10 && k >= -10; k = (k <= 0 ? 1 : 0) - k) { +- BlockPos blockpos1 = blockpos.offset(j, i, k); +- BlockState blockstate = level.getBlockState(blockpos1); +- Block block = blockstate.getBlock(); ++ BlockPos blockposition1 = blockposition.offset(j, i, k); ++ IBlockData iblockdata = world.getBlockState(blockposition1); ++ Block block = iblockdata.getBlock(); + + if (block instanceof InfestedBlock) { +- if (level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- level.destroyBlock(blockpos1, true, this.silverfish); ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.silverfish, blockposition1, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState())) { ++ continue; ++ } ++ // CraftBukkit end ++ if (world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ world.destroyBlock(blockposition1, true, this.silverfish); + } else { +- level.setBlock(blockpos1, ((InfestedBlock) block).hostStateByInfested(level.getBlockState(blockpos1)), 3); ++ world.setBlock(blockposition1, ((InfestedBlock) block).hostStateByInfested(world.getBlockState(blockposition1)), 3); + } + + if (randomsource.nextBoolean()) { +@@ -217,11 +211,10 @@ + + public SilverfishMergeWithStoneGoal(Silverfish silverfish) { + super(silverfish, 1.0D, 10); +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +- @Override + public boolean canUse() { + if (this.mob.getTarget() != null) { + return false; +@@ -232,10 +225,10 @@ + + if (this.mob.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && randomsource.nextInt(reducedTickDelay(10)) == 0) { + this.selectedDirection = Direction.getRandom(randomsource); +- BlockPos blockpos = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5D, this.mob.getZ()).relative(this.selectedDirection); +- BlockState blockstate = this.mob.level().getBlockState(blockpos); ++ BlockPos blockposition = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5D, this.mob.getZ()).relative(this.selectedDirection); ++ IBlockData iblockdata = this.mob.level().getBlockState(blockposition); + +- if (InfestedBlock.isCompatibleHostBlock(blockstate)) { ++ if (InfestedBlock.isCompatibleHostBlock(iblockdata)) { + this.doMerge = true; + return true; + } +@@ -247,23 +240,26 @@ + } + + @Override +- @Override + public boolean canContinueToUse() { + return this.doMerge ? false : super.canContinueToUse(); + } + + @Override +- @Override + public void start() { + if (!this.doMerge) { + super.start(); + } else { +- Level level = this.mob.level(); +- BlockPos blockpos = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5D, this.mob.getZ()).relative(this.selectedDirection); +- BlockState blockstate = level.getBlockState(blockpos); ++ Level world = this.mob.level(); ++ BlockPos blockposition = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5D, this.mob.getZ()).relative(this.selectedDirection); ++ IBlockData iblockdata = world.getBlockState(blockposition); + +- if (InfestedBlock.isCompatibleHostBlock(blockstate)) { +- level.setBlock(blockpos, InfestedBlock.infestedStateByHost(blockstate), 3); ++ if (InfestedBlock.isCompatibleHostBlock(iblockdata)) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition, InfestedBlock.infestedStateByHost(iblockdata))) { ++ return; ++ } ++ // CraftBukkit end ++ world.setBlock(blockposition, InfestedBlock.infestedStateByHost(iblockdata), 3); + this.mob.spawnAnim(); + this.mob.discard(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Skeleton.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Skeleton.java.patch new file mode 100644 index 0000000000..a2c1a0f8d3 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Skeleton.java.patch @@ -0,0 +1,148 @@ +--- a/net/minecraft/world/entity/monster/Skeleton.java ++++ b/net/minecraft/world/entity/monster/Skeleton.java +@@ -11,23 +11,22 @@ + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Items; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + + public class Skeleton extends AbstractSkeleton { + + private static final int TOTAL_CONVERSION_TIME = 300; +- private static final EntityDataAccessor DATA_STRAY_CONVERSION_ID = SynchedEntityData.defineId(Skeleton.class, EntityDataSerializers.BOOLEAN); ++ public static final EntityDataAccessor DATA_STRAY_CONVERSION_ID = SynchedEntityData.defineId(Skeleton.class, EntityDataSerializers.BOOLEAN); + public static final String CONVERSION_TAG = "StrayConversionTime"; + private int inPowderSnowTime; +- private int conversionTime; ++ public int conversionTime; + +- public Skeleton(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Skeleton(EntityType entityType, Level level) { ++ super(entityType, level); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.getEntityData().define(Skeleton.DATA_STRAY_CONVERSION_ID, false); +@@ -37,18 +36,16 @@ + return (Boolean) this.getEntityData().get(Skeleton.DATA_STRAY_CONVERSION_ID); + } + +- public void setFreezeConverting(boolean flag) { +- this.entityData.set(Skeleton.DATA_STRAY_CONVERSION_ID, flag); ++ public void setFreezeConverting(boolean isFrozen) { ++ this.entityData.set(Skeleton.DATA_STRAY_CONVERSION_ID, isFrozen); + } + + @Override +- @Override + public boolean isShaking() { + return this.isFreezeConverting(); + } + + @Override +- @Override + public void tick() { + if (!this.level().isClientSide && this.isAlive() && !this.isNoAi()) { + if (this.isInPowderSnow) { +@@ -73,29 +70,27 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("StrayConversionTime", this.isFreezeConverting() ? this.conversionTime : -1); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("StrayConversionTime", this.isFreezeConverting() ? this.conversionTime : -1); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("StrayConversionTime", 99) && compoundtag.getInt("StrayConversionTime") > -1) { +- this.startFreezeConversion(compoundtag.getInt("StrayConversionTime")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("StrayConversionTime", 99) && compound.getInt("StrayConversionTime") > -1) { ++ this.startFreezeConversion(compound.getInt("StrayConversionTime")); + } + + } + +- private void startFreezeConversion(int i) { +- this.conversionTime = i; ++ public void startFreezeConversion(int conversionTime) { ++ this.conversionTime = conversionTime; + this.setFreezeConverting(true); + } + + protected void doFreezeConversion() { +- this.convertTo(EntityType.STRAY, true); ++ this.convertTo(EntityType.STRAY, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.FROZEN, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.FROZEN); // CraftBukkit - add spawn and transform reasons + if (!this.isSilent()) { + this.level().levelEvent((Player) null, 1048, this.blockPosition(), 0); + } +@@ -103,47 +98,41 @@ + } + + @Override +- @Override + public boolean canFreeze() { + return false; + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.SKELETON_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.SKELETON_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.SKELETON_DEATH; + } + + @Override +- @Override + SoundEvent getStepSound() { + return SoundEvents.SKELETON_STEP; + } + + @Override +- @Override +- protected void dropCustomDeathLoot(DamageSource damagesource, int i, boolean flag) { +- super.dropCustomDeathLoot(damagesource, i, flag); +- Entity entity = damagesource.getEntity(); ++ protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { ++ super.dropCustomDeathLoot(source, looting, recentlyHit); ++ Entity entity = source.getEntity(); + + if (entity instanceof Creeper) { +- Creeper creeper = (Creeper) entity; ++ Creeper entitycreeper = (Creeper) entity; + +- if (creeper.canDropMobsSkull()) { +- creeper.increaseDroppedSkulls(); +- this.spawnAtLocation((ItemLike) Items.SKELETON_SKULL); ++ if (entitycreeper.canDropMobsSkull()) { ++ entitycreeper.increaseDroppedSkulls(); ++ this.spawnAtLocation((IMaterial) Items.SKELETON_SKULL); + } + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Slime.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Slime.java.patch new file mode 100644 index 0000000000..99e617d50f --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Slime.java.patch @@ -0,0 +1,603 @@ +--- a/net/minecraft/world/entity/monster/Slime.java ++++ b/net/minecraft/world/entity/monster/Slime.java +@@ -23,12 +23,12 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.MoveControl; + import net.minecraft.world.entity.ai.goal.Goal; +@@ -44,8 +44,16 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Slime extends Mob implements Enemy { ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTransformEvent; ++import org.bukkit.event.entity.SlimeSplitEvent; ++// CraftBukkit end + ++public class Slime extends Mob implements IMonster { ++ + private static final EntityDataAccessor ID_SIZE = SynchedEntityData.defineId(Slime.class, EntityDataSerializers.INT); + public static final int MIN_SIZE = 1; + public static final int MAX_SIZE = 127; +@@ -54,41 +62,38 @@ + public float oSquish; + private boolean wasOnGround; + +- public Slime(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Slime(EntityType entityType, Level level) { ++ super(entityType, level); + this.fixupDimensions(); + this.moveControl = new Slime.SlimeMoveControl(this); + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new Slime.SlimeFloatGoal(this)); + this.goalSelector.addGoal(2, new Slime.SlimeAttackGoal(this)); + this.goalSelector.addGoal(3, new Slime.SlimeRandomDirectionGoal(this)); + this.goalSelector.addGoal(5, new Slime.SlimeKeepOnJumpingGoal(this)); +- this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (livingentity) -> { +- return Math.abs(livingentity.getY() - this.getY()) <= 4.0D; ++ this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (entityliving) -> { ++ return Math.abs(entityliving.getY() - this.getY()) <= 4.0D; + })); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); + } + + @Override +- @Override + public SoundSource getSoundSource() { + return SoundSource.HOSTILE; + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Slime.ID_SIZE, 1); + } + + @VisibleForTesting +- public void setSize(int i, boolean flag) { +- int j = Mth.clamp(i, 1, 127); ++ public void setSize(int size, boolean resetHealth) { ++ int j = Mth.clamp(size, 1, 127); + + this.entityData.set(Slime.ID_SIZE, j); + this.reapplyPosition(); +@@ -96,7 +101,7 @@ + this.getAttribute(Attributes.MAX_HEALTH).setBaseValue((double) (j * j)); + this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue((double) (0.2F + 0.1F * (float) j)); + this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue((double) j); +- if (flag) { ++ if (resetHealth) { + this.setHealth(this.getMaxHealth()); + } + +@@ -108,19 +113,17 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("Size", this.getSize() - 1); +- compoundtag.putBoolean("wasOnGround", this.wasOnGround); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("Size", this.getSize() - 1); ++ compound.putBoolean("wasOnGround", this.wasOnGround); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- this.setSize(compoundtag.getInt("Size") + 1, false); +- super.readAdditionalSaveData(compoundtag); +- this.wasOnGround = compoundtag.getBoolean("wasOnGround"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ this.setSize(compound.getInt("Size") + 1, false); ++ super.readAdditionalSaveData(compound); ++ this.wasOnGround = compound.getBoolean("wasOnGround"); + } + + public boolean isTiny() { +@@ -132,13 +135,11 @@ + } + + @Override +- @Override + protected boolean shouldDespawnInPeaceful() { + return this.getSize() > 0; + } + + @Override +- @Override + public void tick() { + this.squish += (this.targetSquish - this.squish) * 0.5F; + this.oSquish = this.squish; +@@ -174,7 +175,6 @@ + } + + @Override +- @Override + public void refreshDimensions() { + double d0 = this.getX(); + double d1 = this.getY(); +@@ -185,9 +185,8 @@ + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- if (Slime.ID_SIZE.equals(entitydataaccessor)) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ if (Slime.ID_SIZE.equals(key)) { + this.refreshDimensions(); + this.setYRot(this.yHeadRot); + this.yBodyRot = this.yHeadRot; +@@ -196,52 +195,71 @@ + } + } + +- super.onSyncedDataUpdated(entitydataaccessor); ++ super.onSyncedDataUpdated(key); + } + + @Override +- @Override + public EntityType getType() { +- return super.getType(); ++ return (EntityType) super.getType(); // CraftBukkit - decompile error + } + + @Override +- @Override +- public void remove(Entity.RemovalReason entity_removalreason) { ++ public void remove(Entity.RemovalReason reason) { + int i = this.getSize(); + + if (!this.level().isClientSide && i > 1 && this.isDeadOrDying()) { +- Component component = this.getCustomName(); ++ Component ichatbasecomponent = this.getCustomName(); + boolean flag = this.isNoAi(); + float f = (float) i / 4.0F; + int j = i / 2; + int k = 2 + this.random.nextInt(3); + ++ // CraftBukkit start ++ SlimeSplitEvent event = new SlimeSplitEvent((org.bukkit.entity.Slime) this.getBukkitEntity(), k); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled() && event.getCount() > 0) { ++ k = event.getCount(); ++ } else { ++ super.remove(reason); ++ return; ++ } ++ List slimes = new ArrayList<>(j); ++ // CraftBukkit end ++ + for (int l = 0; l < k; ++l) { + float f1 = ((float) (l % 2) - 0.5F) * f; + float f2 = ((float) (l / 2) - 0.5F) * f; +- Slime slime = (Slime) this.getType().create(this.level()); ++ Slime entityslime = (Slime) this.getType().create(this.level()); + +- if (slime != null) { ++ if (entityslime != null) { + if (this.isPersistenceRequired()) { +- slime.setPersistenceRequired(); ++ entityslime.setPersistenceRequired(); + } + +- slime.setCustomName(component); +- slime.setNoAi(flag); +- slime.setInvulnerable(this.isInvulnerable()); +- slime.setSize(j, true); +- slime.moveTo(this.getX() + (double) f1, this.getY() + 0.5D, this.getZ() + (double) f2, this.random.nextFloat() * 360.0F, 0.0F); +- this.level().addFreshEntity(slime); ++ entityslime.setCustomName(ichatbasecomponent); ++ entityslime.setNoAi(flag); ++ entityslime.setInvulnerable(this.isInvulnerable()); ++ entityslime.setSize(j, true); ++ entityslime.moveTo(this.getX() + (double) f1, this.getY() + 0.5D, this.getZ() + (double) f2, this.random.nextFloat() * 360.0F, 0.0F); ++ slimes.add(entityslime); // CraftBukkit + } + } ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, slimes, EntityTransformEvent.TransformReason.SPLIT).isCancelled()) { ++ super.remove(reason); ++ return; ++ } ++ for (LivingEntity living : slimes) { ++ this.level().addFreshEntity(living, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SLIME_SPLIT); // CraftBukkit - SpawnReason ++ } ++ // CraftBukkit end + } + +- super.remove(entity_removalreason); ++ super.remove(reason); + } + + @Override +- @Override + public void push(Entity entity) { + super.push(entity); + if (entity instanceof IronGolem && this.isDealsDamage()) { +@@ -251,36 +269,33 @@ + } + + @Override +- @Override +- public void playerTouch(Player player) { ++ public void playerTouch(Player entity) { + if (this.isDealsDamage()) { +- this.dealDamage(player); ++ this.dealDamage(entity); + } + + } + +- protected void dealDamage(LivingEntity livingentity) { ++ protected void dealDamage(LivingEntity livingEntity) { + if (this.isAlive()) { + int i = this.getSize(); + +- if (this.distanceToSqr((Entity) livingentity) < 0.6D * (double) i * 0.6D * (double) i && this.hasLineOfSight(livingentity) && livingentity.hurt(this.damageSources().mobAttack(this), this.getAttackDamage())) { ++ if (this.distanceToSqr((Entity) livingEntity) < 0.6D * (double) i * 0.6D * (double) i && this.hasLineOfSight(livingEntity) && livingEntity.hurt(this.damageSources().mobAttack(this), this.getAttackDamage())) { + this.playSound(SoundEvents.SLIME_ATTACK, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); +- this.doEnchantDamageEffects(this, livingentity); ++ this.doEnchantDamageEffects(this, livingEntity); + } + } + + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return 0.625F * entitydimensions.height; ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { ++ return 0.625F * size.height; + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height - 0.015625F * (float) this.getSize() * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.015625F * (float) this.getSize() * f, 0.0F); + } + + protected boolean isDealsDamage() { +@@ -292,13 +307,11 @@ + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return this.isTiny() ? SoundEvents.SLIME_HURT_SMALL : SoundEvents.SLIME_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return this.isTiny() ? SoundEvents.SLIME_DEATH_SMALL : SoundEvents.SLIME_DEATH; + } +@@ -307,28 +320,28 @@ + return this.isTiny() ? SoundEvents.SLIME_SQUISH_SMALL : SoundEvents.SLIME_SQUISH; + } + +- public static boolean checkSlimeSpawnRules(EntityType entitytype, LevelAccessor levelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- if (MobSpawnType.isSpawner(mobspawntype)) { +- return checkMobSpawnRules(entitytype, levelaccessor, mobspawntype, blockpos, randomsource); ++ public static boolean checkSlimeSpawnRules(EntityType slime, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ if (EnumMobSpawn.isSpawner(spawnType)) { ++ return checkMobSpawnRules(slime, level, spawnType, pos, random); + } else { +- if (levelaccessor.getDifficulty() != Difficulty.PEACEFUL) { +- if (mobspawntype == MobSpawnType.SPAWNER) { +- return checkMobSpawnRules(entitytype, levelaccessor, mobspawntype, blockpos, randomsource); ++ if (level.getDifficulty() != Difficulty.PEACEFUL) { ++ if (spawnType == EnumMobSpawn.SPAWNER) { ++ return checkMobSpawnRules(slime, level, spawnType, pos, random); + } + +- if (levelaccessor.getBiome(blockpos).is(BiomeTags.ALLOWS_SURFACE_SLIME_SPAWNS) && blockpos.getY() > 50 && blockpos.getY() < 70 && randomsource.nextFloat() < 0.5F && randomsource.nextFloat() < levelaccessor.getMoonBrightness() && levelaccessor.getMaxLocalRawBrightness(blockpos) <= randomsource.nextInt(8)) { +- return checkMobSpawnRules(entitytype, levelaccessor, mobspawntype, blockpos, randomsource); ++ if (level.getBiome(pos).is(BiomeTags.ALLOWS_SURFACE_SLIME_SPAWNS) && pos.getY() > 50 && pos.getY() < 70 && random.nextFloat() < 0.5F && random.nextFloat() < level.getMoonBrightness() && level.getMaxLocalRawBrightness(pos) <= random.nextInt(8)) { ++ return checkMobSpawnRules(slime, level, spawnType, pos, random); + } + +- if (!(levelaccessor instanceof WorldGenLevel)) { ++ if (!(level instanceof WorldGenLevel)) { + return false; + } + +- ChunkPos chunkpos = new ChunkPos(blockpos); +- boolean flag = WorldgenRandom.seedSlimeChunk(chunkpos.x, chunkpos.z, ((WorldGenLevel) levelaccessor).getSeed(), 987234911L).nextInt(10) == 0; ++ ChunkPos chunkcoordintpair = new ChunkPos(pos); ++ boolean flag = WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) level).getSeed(), 987234911L).nextInt(10) == 0; + +- if (randomsource.nextInt(10) == 0 && flag && blockpos.getY() < 40) { +- return checkMobSpawnRules(entitytype, levelaccessor, mobspawntype, blockpos, randomsource); ++ if (random.nextInt(10) == 0 && flag && pos.getY() < 40) { ++ return checkMobSpawnRules(slime, level, spawnType, pos, random); + } + } + +@@ -337,13 +350,11 @@ + } + + @Override +- @Override + protected float getSoundVolume() { + return 0.4F * (float) this.getSize(); + } + + @Override +- @Override + public int getMaxHeadXRot() { + return 0; + } +@@ -353,29 +364,27 @@ + } + + @Override +- @Override + protected void jumpFromGround() { +- Vec3 vec3 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + +- this.setDeltaMovement(vec3.x, (double) this.getJumpPower(), vec3.z); ++ this.setDeltaMovement(vec3d.x, (double) this.getJumpPower(), vec3d.z); + this.hasImpulse = true; + } + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- RandomSource randomsource = serverlevelaccessor.getRandom(); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ RandomSource randomsource = level.getRandom(); + int i = randomsource.nextInt(3); + +- if (i < 2 && randomsource.nextFloat() < 0.5F * difficultyinstance.getSpecialMultiplier()) { ++ if (i < 2 && randomsource.nextFloat() < 0.5F * difficulty.getSpecialMultiplier()) { + ++i; + } + + int j = 1 << i; + + this.setSize(j, true); +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); ++ return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + + float getSoundPitch() { +@@ -389,8 +398,7 @@ + } + + @Override +- @Override +- public EntityDimensions getDimensions(Pose pose) { ++ public EntityDimensions getDimensions(EntityPose pose) { + return super.getDimensions(pose).scale(0.255F * (float) this.getSize()); + } + +@@ -407,18 +415,17 @@ + this.yRot = 180.0F * slime.getYRot() / 3.1415927F; + } + +- public void setDirection(float f, boolean flag) { +- this.yRot = f; +- this.isAggressive = flag; ++ public void setDirection(float yRot, boolean aggressive) { ++ this.yRot = yRot; ++ this.isAggressive = aggressive; + } + +- public void setWantedMovement(double d0) { +- this.speedModifier = d0; ++ public void setWantedMovement(double speed) { ++ this.speedModifier = speed; + this.operation = MoveControl.Operation.MOVE_TO; + } + + @Override +- @Override + public void tick() { + this.mob.setYRot(this.rotlerp(this.mob.getYRot(), this.yRot, 90.0F)); + this.mob.yHeadRot = this.mob.getYRot(); +@@ -458,35 +465,32 @@ + + public SlimeFloatGoal(Slime slime) { + this.slime = slime; +- this.setFlags(EnumSet.of(Goal.Flag.JUMP, Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.JUMP, Goal.Type.MOVE)); + slime.getNavigation().setCanFloat(true); + } + + @Override +- @Override + public boolean canUse() { + return (this.slime.isInWater() || this.slime.isInLava()) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl; + } + + @Override +- @Override + public boolean requiresUpdateEveryTick() { + return true; + } + + @Override +- @Override + public void tick() { + if (this.slime.getRandom().nextFloat() < 0.8F) { + this.slime.getJumpControl().jump(); + } + +- MoveControl movecontrol = this.slime.getMoveControl(); ++ MoveControl controllermove = this.slime.getMoveControl(); + +- if (movecontrol instanceof Slime.SlimeMoveControl) { +- Slime.SlimeMoveControl slime_slimemovecontrol = (Slime.SlimeMoveControl) movecontrol; ++ if (controllermove instanceof Slime.SlimeMoveControl) { ++ Slime.SlimeMoveControl entityslime_controllermoveslime = (Slime.SlimeMoveControl) controllermove; + +- slime_slimemovecontrol.setWantedMovement(1.2D); ++ entityslime_controllermoveslime.setWantedMovement(1.2D); + } + + } +@@ -499,53 +503,48 @@ + + public SlimeAttackGoal(Slime slime) { + this.slime = slime; +- this.setFlags(EnumSet.of(Goal.Flag.LOOK)); ++ this.setFlags(EnumSet.of(Goal.Type.LOOK)); + } + + @Override +- @Override + public boolean canUse() { +- LivingEntity livingentity = this.slime.getTarget(); ++ LivingEntity entityliving = this.slime.getTarget(); + +- return livingentity == null ? false : (!this.slime.canAttack(livingentity) ? false : this.slime.getMoveControl() instanceof Slime.SlimeMoveControl); ++ return entityliving == null ? false : (!this.slime.canAttack(entityliving) ? false : this.slime.getMoveControl() instanceof Slime.SlimeMoveControl); + } + + @Override +- @Override + public void start() { + this.growTiredTimer = reducedTickDelay(300); + super.start(); + } + + @Override +- @Override + public boolean canContinueToUse() { +- LivingEntity livingentity = this.slime.getTarget(); ++ LivingEntity entityliving = this.slime.getTarget(); + +- return livingentity == null ? false : (!this.slime.canAttack(livingentity) ? false : --this.growTiredTimer > 0); ++ return entityliving == null ? false : (!this.slime.canAttack(entityliving) ? false : --this.growTiredTimer > 0); + } + + @Override +- @Override + public boolean requiresUpdateEveryTick() { + return true; + } + + @Override +- @Override + public void tick() { +- LivingEntity livingentity = this.slime.getTarget(); ++ LivingEntity entityliving = this.slime.getTarget(); + +- if (livingentity != null) { +- this.slime.lookAt(livingentity, 10.0F, 10.0F); ++ if (entityliving != null) { ++ this.slime.lookAt(entityliving, 10.0F, 10.0F); + } + +- MoveControl movecontrol = this.slime.getMoveControl(); ++ MoveControl controllermove = this.slime.getMoveControl(); + +- if (movecontrol instanceof Slime.SlimeMoveControl) { +- Slime.SlimeMoveControl slime_slimemovecontrol = (Slime.SlimeMoveControl) movecontrol; ++ if (controllermove instanceof Slime.SlimeMoveControl) { ++ Slime.SlimeMoveControl entityslime_controllermoveslime = (Slime.SlimeMoveControl) controllermove; + +- slime_slimemovecontrol.setDirection(this.slime.getYRot(), this.slime.isDealsDamage()); ++ entityslime_controllermoveslime.setDirection(this.slime.getYRot(), this.slime.isDealsDamage()); + } + + } +@@ -559,29 +558,27 @@ + + public SlimeRandomDirectionGoal(Slime slime) { + this.slime = slime; +- this.setFlags(EnumSet.of(Goal.Flag.LOOK)); ++ this.setFlags(EnumSet.of(Goal.Type.LOOK)); + } + + @Override +- @Override + public boolean canUse() { + return this.slime.getTarget() == null && (this.slime.onGround() || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl; + } + + @Override +- @Override + public void tick() { + if (--this.nextRandomizeTime <= 0) { + this.nextRandomizeTime = this.adjustedTickDelay(40 + this.slime.getRandom().nextInt(60)); + this.chosenDegrees = (float) this.slime.getRandom().nextInt(360); + } + +- MoveControl movecontrol = this.slime.getMoveControl(); ++ MoveControl controllermove = this.slime.getMoveControl(); + +- if (movecontrol instanceof Slime.SlimeMoveControl) { +- Slime.SlimeMoveControl slime_slimemovecontrol = (Slime.SlimeMoveControl) movecontrol; ++ if (controllermove instanceof Slime.SlimeMoveControl) { ++ Slime.SlimeMoveControl entityslime_controllermoveslime = (Slime.SlimeMoveControl) controllermove; + +- slime_slimemovecontrol.setDirection(this.chosenDegrees, false); ++ entityslime_controllermoveslime.setDirection(this.chosenDegrees, false); + } + + } +@@ -593,24 +590,22 @@ + + public SlimeKeepOnJumpingGoal(Slime slime) { + this.slime = slime; +- this.setFlags(EnumSet.of(Goal.Flag.JUMP, Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.JUMP, Goal.Type.MOVE)); + } + + @Override +- @Override + public boolean canUse() { + return !this.slime.isPassenger(); + } + + @Override +- @Override + public void tick() { +- MoveControl movecontrol = this.slime.getMoveControl(); ++ MoveControl controllermove = this.slime.getMoveControl(); + +- if (movecontrol instanceof Slime.SlimeMoveControl) { +- Slime.SlimeMoveControl slime_slimemovecontrol = (Slime.SlimeMoveControl) movecontrol; ++ if (controllermove instanceof Slime.SlimeMoveControl) { ++ Slime.SlimeMoveControl entityslime_controllermoveslime = (Slime.SlimeMoveControl) controllermove; + +- slime_slimemovecontrol.setWantedMovement(1.0D); ++ entityslime_controllermoveslime.setWantedMovement(1.0D); + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/SpellcasterIllager.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/SpellcasterIllager.java.patch new file mode 100644 index 0000000000..f412d00c36 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/SpellcasterIllager.java.patch @@ -0,0 +1,215 @@ +--- a/net/minecraft/world/entity/monster/SpellcasterIllager.java ++++ b/net/minecraft/world/entity/monster/SpellcasterIllager.java +@@ -15,6 +15,9 @@ + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.ai.goal.Goal; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public abstract class SpellcasterIllager extends AbstractIllager { + +@@ -22,53 +25,48 @@ + protected int spellCastingTickCount; + private SpellcasterIllager.IllagerSpell currentSpell; + +- protected SpellcasterIllager(EntityType entitytype, Level level) { +- super(entitytype, level); ++ protected SpellcasterIllager(EntityType entityType, Level level) { ++ super(entityType, level); + this.currentSpell = SpellcasterIllager.IllagerSpell.NONE; + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(SpellcasterIllager.DATA_SPELL_CASTING_ID, (byte) 0); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.spellCastingTickCount = compoundtag.getInt("SpellTicks"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.spellCastingTickCount = compound.getInt("SpellTicks"); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("SpellTicks", this.spellCastingTickCount); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("SpellTicks", this.spellCastingTickCount); + } + + @Override +- @Override +- public AbstractIllager.IllagerArmPose getArmPose() { +- return this.isCastingSpell() ? AbstractIllager.IllagerArmPose.SPELLCASTING : (this.isCelebrating() ? AbstractIllager.IllagerArmPose.CELEBRATING : AbstractIllager.IllagerArmPose.CROSSED); ++ public AbstractIllager.a getArmPose() { ++ return this.isCastingSpell() ? AbstractIllager.a.SPELLCASTING : (this.isCelebrating() ? AbstractIllager.a.CELEBRATING : AbstractIllager.a.CROSSED); + } + + public boolean isCastingSpell() { + return this.level().isClientSide ? (Byte) this.entityData.get(SpellcasterIllager.DATA_SPELL_CASTING_ID) > 0 : this.spellCastingTickCount > 0; + } + +- public void setIsCastingSpell(SpellcasterIllager.IllagerSpell spellcasterillager_illagerspell) { +- this.currentSpell = spellcasterillager_illagerspell; +- this.entityData.set(SpellcasterIllager.DATA_SPELL_CASTING_ID, (byte) spellcasterillager_illagerspell.id); ++ public void setIsCastingSpell(SpellcasterIllager.IllagerSpell currentSpell) { ++ this.currentSpell = currentSpell; ++ this.entityData.set(SpellcasterIllager.DATA_SPELL_CASTING_ID, (byte) currentSpell.id); + } + +- protected SpellcasterIllager.IllagerSpell getCurrentSpell() { ++ public SpellcasterIllager.IllagerSpell getCurrentSpell() { + return !this.level().isClientSide ? this.currentSpell : SpellcasterIllager.IllagerSpell.byId((Byte) this.entityData.get(SpellcasterIllager.DATA_SPELL_CASTING_ID)); + } + + @Override +- @Override + protected void customServerAiStep() { + super.customServerAiStep(); + if (this.spellCastingTickCount > 0) { +@@ -78,14 +76,13 @@ + } + + @Override +- @Override + public void tick() { + super.tick(); + if (this.level().isClientSide && this.isCastingSpell()) { +- SpellcasterIllager.IllagerSpell spellcasterillager_illagerspell = this.getCurrentSpell(); +- double d0 = spellcasterillager_illagerspell.spellColor[0]; +- double d1 = spellcasterillager_illagerspell.spellColor[1]; +- double d2 = spellcasterillager_illagerspell.spellColor[2]; ++ SpellcasterIllager.IllagerSpell entityillagerwizard_spell = this.getCurrentSpell(); ++ double d0 = entityillagerwizard_spell.spellColor[0]; ++ double d1 = entityillagerwizard_spell.spellColor[1]; ++ double d2 = entityillagerwizard_spell.spellColor[2]; + float f = this.yBodyRot * 0.017453292F + Mth.cos((float) this.tickCount * 0.6662F) * 0.25F; + float f1 = Mth.cos(f); + float f2 = Mth.sin(f); +@@ -102,13 +99,13 @@ + + protected abstract SoundEvent getCastingSoundEvent(); + +- protected static enum IllagerSpell { ++ public static enum IllagerSpell { + + NONE(0, 0.0D, 0.0D, 0.0D), SUMMON_VEX(1, 0.7D, 0.7D, 0.8D), FANGS(2, 0.4D, 0.3D, 0.35D), WOLOLO(3, 0.7D, 0.5D, 0.2D), DISAPPEAR(4, 0.3D, 0.3D, 0.8D), BLINDNESS(5, 0.1D, 0.1D, 0.2D); + +- private static final IntFunction BY_ID = ByIdMap.continuous((spellcasterillager_illagerspell) -> { +- return spellcasterillager_illagerspell.id; +- }, values(), ByIdMap.OutOfBoundsStrategy.ZERO); ++ private static final IntFunction BY_ID = ByIdMap.continuous((entityillagerwizard_spell) -> { ++ return entityillagerwizard_spell.id; ++ }, values(), ByIdMap.a.ZERO); + final int id; + final double[] spellColor; + +@@ -117,8 +114,8 @@ + this.spellColor = new double[]{d0, d1, d2}; + } + +- public static SpellcasterIllager.IllagerSpell byId(int i) { +- return (SpellcasterIllager.IllagerSpell) SpellcasterIllager.IllagerSpell.BY_ID.apply(i); ++ public static SpellcasterIllager.IllagerSpell byId(int id) { ++ return (SpellcasterIllager.IllagerSpell) SpellcasterIllager.IllagerSpell.BY_ID.apply(id); + } + } + +@@ -130,41 +127,42 @@ + protected SpellcasterUseSpellGoal() {} + + @Override +- @Override + public boolean canUse() { +- LivingEntity livingentity = SpellcasterIllager.this.getTarget(); ++ LivingEntity entityliving = SpellcasterIllager.this.getTarget(); + +- return livingentity != null && livingentity.isAlive() ? (SpellcasterIllager.this.isCastingSpell() ? false : SpellcasterIllager.this.tickCount >= this.nextAttackTickCount) : false; ++ return entityliving != null && entityliving.isAlive() ? (SpellcasterIllager.this.isCastingSpell() ? false : SpellcasterIllager.this.tickCount >= this.nextAttackTickCount) : false; + } + + @Override +- @Override + public boolean canContinueToUse() { +- LivingEntity livingentity = SpellcasterIllager.this.getTarget(); ++ LivingEntity entityliving = SpellcasterIllager.this.getTarget(); + +- return livingentity != null && livingentity.isAlive() && this.attackWarmupDelay > 0; ++ return entityliving != null && entityliving.isAlive() && this.attackWarmupDelay > 0; + } + + @Override +- @Override + public void start() { + this.attackWarmupDelay = this.adjustedTickDelay(this.getCastWarmupTime()); + SpellcasterIllager.this.spellCastingTickCount = this.getCastingTime(); + this.nextAttackTickCount = SpellcasterIllager.this.tickCount + this.getCastingInterval(); +- SoundEvent soundevent = this.getSpellPrepareSound(); ++ SoundEvent soundeffect = this.getSpellPrepareSound(); + +- if (soundevent != null) { +- SpellcasterIllager.this.playSound(soundevent, 1.0F, 1.0F); ++ if (soundeffect != null) { ++ SpellcasterIllager.this.playSound(soundeffect, 1.0F, 1.0F); + } + + SpellcasterIllager.this.setIsCastingSpell(this.getSpell()); + } + + @Override +- @Override + public void tick() { + --this.attackWarmupDelay; + if (this.attackWarmupDelay == 0) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handleEntitySpellCastEvent(SpellcasterIllager.this, this.getSpell())) { ++ return; ++ } ++ // CraftBukkit end + this.performSpellCasting(); + SpellcasterIllager.this.playSound(SpellcasterIllager.this.getCastingSoundEvent(), 1.0F, 1.0F); + } +@@ -190,31 +188,27 @@ + protected class SpellcasterCastingSpellGoal extends Goal { + + public SpellcasterCastingSpellGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + } + + @Override +- @Override + public boolean canUse() { + return SpellcasterIllager.this.getSpellCastingTime() > 0; + } + + @Override +- @Override + public void start() { + super.start(); + SpellcasterIllager.this.navigation.stop(); + } + + @Override +- @Override + public void stop() { + super.stop(); + SpellcasterIllager.this.setIsCastingSpell(SpellcasterIllager.IllagerSpell.NONE); + } + + @Override +- @Override + public void tick() { + if (SpellcasterIllager.this.getTarget() != null) { + SpellcasterIllager.this.getLookControl().setLookAt(SpellcasterIllager.this.getTarget(), (float) SpellcasterIllager.this.getMaxHeadYRot(), (float) SpellcasterIllager.this.getMaxHeadXRot()); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Spider.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Spider.java.patch new file mode 100644 index 0000000000..37be51da3e --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Spider.java.patch @@ -0,0 +1,260 @@ +--- a/net/minecraft/world/entity/monster/Spider.java ++++ b/net/minecraft/world/entity/monster/Spider.java +@@ -17,12 +17,12 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.FloatGoal; +@@ -40,7 +40,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +@@ -49,12 +49,11 @@ + private static final EntityDataAccessor DATA_FLAGS_ID = SynchedEntityData.defineId(Spider.class, EntityDataSerializers.BYTE); + private static final float SPIDER_SPECIAL_EFFECT_CHANCE = 0.1F; + +- public Spider(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Spider(EntityType entityType, Level level) { ++ super(entityType, level); + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new FloatGoal(this)); + this.goalSelector.addGoal(3, new LeapAtTargetGoal(this, 0.4F)); +@@ -68,26 +67,22 @@ + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height * 0.85F, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height * 0.85F, 0.0F); + } + + @Override +- @Override + protected PathNavigation createNavigation(Level level) { + return new WallClimberNavigation(this, level); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Spider.DATA_FLAGS_ID, (byte) 0); + } + + @Override +- @Override + public void tick() { + super.tick(); + if (!this.level().isClientSide) { +@@ -101,64 +96,56 @@ + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.SPIDER_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.SPIDER_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.SPIDER_DEATH; + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.SPIDER_STEP, 0.15F, 1.0F); + } + + @Override +- @Override + public boolean onClimbable() { + return this.isClimbing(); + } + + @Override +- @Override +- public void makeStuckInBlock(BlockState blockstate, Vec3 vec3) { +- if (!blockstate.is(Blocks.COBWEB)) { +- super.makeStuckInBlock(blockstate, vec3); ++ public void makeStuckInBlock(IBlockData state, Vec3 motionMultiplier) { ++ if (!state.is(Blocks.COBWEB)) { ++ super.makeStuckInBlock(state, motionMultiplier); + } + + } + + @Override +- @Override +- public MobType getMobType() { +- return MobType.ARTHROPOD; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.ARTHROPOD; + } + + @Override +- @Override +- public boolean canBeAffected(MobEffectInstance mobeffectinstance) { +- return mobeffectinstance.getEffect() == MobEffects.POISON ? false : super.canBeAffected(mobeffectinstance); ++ public boolean canBeAffected(MobEffectInstance potioneffect) { ++ return potioneffect.getEffect() == MobEffects.POISON ? false : super.canBeAffected(potioneffect); + } + + public boolean isClimbing() { + return ((Byte) this.entityData.get(Spider.DATA_FLAGS_ID) & 1) != 0; + } + +- public void setClimbing(boolean flag) { ++ public void setClimbing(boolean climbing) { + byte b0 = (Byte) this.entityData.get(Spider.DATA_FLAGS_ID); + +- if (flag) { ++ if (climbing) { + b0 = (byte) (b0 | 1); + } else { + b0 &= -2; +@@ -169,48 +156,45 @@ + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- Object object = super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); +- RandomSource randomsource = serverlevelaccessor.getRandom(); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ Object object = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ RandomSource randomsource = level.getRandom(); + + if (randomsource.nextInt(100) == 0) { +- Skeleton skeleton = (Skeleton) EntityType.SKELETON.create(this.level()); ++ Skeleton entityskeleton = (Skeleton) EntityType.SKELETON.create(this.level()); + +- if (skeleton != null) { +- skeleton.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); +- skeleton.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, (SpawnGroupData) null, (CompoundTag) null); +- skeleton.startRiding(this); ++ if (entityskeleton != null) { ++ entityskeleton.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); ++ entityskeleton.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) null, (CompoundTag) null); ++ entityskeleton.startRiding(this); + } + } + + if (object == null) { + object = new Spider.SpiderEffectsGroupData(); +- if (serverlevelaccessor.getDifficulty() == Difficulty.HARD && randomsource.nextFloat() < 0.1F * difficultyinstance.getSpecialMultiplier()) { ++ if (level.getDifficulty() == Difficulty.HARD && randomsource.nextFloat() < 0.1F * difficulty.getSpecialMultiplier()) { + ((Spider.SpiderEffectsGroupData) object).setRandomEffect(randomsource); + } + } + + if (object instanceof Spider.SpiderEffectsGroupData) { +- Spider.SpiderEffectsGroupData spider_spidereffectsgroupdata = (Spider.SpiderEffectsGroupData) object; +- MobEffect mobeffect = spider_spidereffectsgroupdata.effect; ++ Spider.SpiderEffectsGroupData entityspider_groupdataspider = (Spider.SpiderEffectsGroupData) object; ++ MobEffect mobeffectlist = entityspider_groupdataspider.effect; + +- if (mobeffect != null) { +- this.addEffect(new MobEffectInstance(mobeffect, -1)); ++ if (mobeffectlist != null) { ++ this.addEffect(new MobEffectInstance(mobeffectlist, -1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.SPIDER_SPAWN); // CraftBukkit + } + } + +- return (SpawnGroupData) object; ++ return (GroupDataEntity) object; + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.65F; + } + + @Override +- @Override + protected float ridingOffset(Entity entity) { + return entity.getBbWidth() <= this.getBbWidth() ? -0.3125F : 0.0F; + } +@@ -222,13 +206,11 @@ + } + + @Override +- @Override + public boolean canUse() { + return super.canUse() && !this.mob.isVehicle(); + } + + @Override +- @Override + public boolean canContinueToUse() { + float f = this.mob.getLightLevelDependentMagicValue(); + +@@ -243,12 +225,11 @@ + + private static class SpiderTargetGoal extends NearestAttackableTargetGoal { + +- public SpiderTargetGoal(Spider spider, Class oclass) { +- super(spider, oclass, true); ++ public SpiderTargetGoal(Spider spider, Class entityTypeToTarget) { ++ super(spider, entityTypeToTarget, true); + } + + @Override +- @Override + public boolean canUse() { + float f = this.mob.getLightLevelDependentMagicValue(); + +@@ -256,15 +237,15 @@ + } + } + +- public static class SpiderEffectsGroupData implements SpawnGroupData { ++ public static class SpiderEffectsGroupData implements GroupDataEntity { + + @Nullable + public MobEffect effect; + + public SpiderEffectsGroupData() {} + +- public void setRandomEffect(RandomSource randomsource) { +- int i = randomsource.nextInt(5); ++ public void setRandomEffect(RandomSource random) { ++ int i = random.nextInt(5); + + if (i <= 1) { + this.effect = MobEffects.MOVEMENT_SPEED; diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Strider.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Strider.java.patch new file mode 100644 index 0000000000..23d7d3b819 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Strider.java.patch @@ -0,0 +1,677 @@ +--- a/net/minecraft/world/entity/monster/Strider.java ++++ b/net/minecraft/world/entity/monster/Strider.java +@@ -21,22 +21,22 @@ + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; ++import net.minecraft.world.entity.ISteerable; + import net.minecraft.world.entity.ItemBasedSteering; +-import net.minecraft.world.entity.ItemSteerable; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.Saddleable; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -57,25 +57,25 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.item.crafting.Ingredient; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.LiquidBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.pathfinder.BlockPathTypes; +-import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraft.world.level.pathfinder.PathFinder; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.level.pathfinder.WalkNodeEvaluator; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; + import org.joml.Vector3f; + +-public class Strider extends Animal implements ItemSteerable, Saddleable { ++public class Strider extends Animal implements ISteerable, Saddleable { + + private static final UUID SUFFOCATING_MODIFIER_UUID = UUID.fromString("9e362924-01de-4ddd-a2b2-d0f7a405a174"); + private static final AttributeModifier SUFFOCATING_MODIFIER = new AttributeModifier(Strider.SUFFOCATING_MODIFIER_UUID, "Strider suffocating modifier", -0.3400000035762787D, AttributeModifier.Operation.MULTIPLY_BASE); +@@ -86,12 +86,12 @@ + private static final EntityDataAccessor DATA_BOOST_TIME = SynchedEntityData.defineId(Strider.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_SUFFOCATING = SynchedEntityData.defineId(Strider.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_SADDLE_ID = SynchedEntityData.defineId(Strider.class, EntityDataSerializers.BOOLEAN); +- private final ItemBasedSteering steering; ++ public final ItemBasedSteering steering; + @Nullable + private TemptGoal temptGoal; + +- public Strider(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Strider(EntityType entityType, Level level) { ++ super(entityType, level); + this.steering = new ItemBasedSteering(this.entityData, Strider.DATA_BOOST_TIME, Strider.DATA_SADDLE_ID); + this.blocksBuilding = true; + this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); +@@ -100,28 +100,26 @@ + this.setPathfindingMalus(BlockPathTypes.DAMAGE_FIRE, 0.0F); + } + +- public static boolean checkStriderSpawnRules(EntityType entitytype, LevelAccessor levelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = blockpos.mutable(); ++ public static boolean checkStriderSpawnRules(EntityType strider, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); + + do { +- blockpos_mutableblockpos.move(Direction.UP); +- } while (levelaccessor.getFluidState(blockpos_mutableblockpos).is(FluidTags.LAVA)); ++ blockposition_mutableblockposition.move(Direction.UP); ++ } while (level.getFluidState(blockposition_mutableblockposition).is(FluidTags.LAVA)); + +- return levelaccessor.getBlockState(blockpos_mutableblockpos).isAir(); ++ return level.getBlockState(blockposition_mutableblockposition).isAir(); + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- if (Strider.DATA_BOOST_TIME.equals(entitydataaccessor) && this.level().isClientSide) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ if (Strider.DATA_BOOST_TIME.equals(key) && this.level().isClientSide) { + this.steering.onSynced(); + } + +- super.onSyncedDataUpdated(entitydataaccessor); ++ super.onSyncedDataUpdated(key); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Strider.DATA_BOOST_TIME, 0); +@@ -130,43 +128,37 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- this.steering.addAdditionalSaveData(compoundtag); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ this.steering.addAdditionalSaveData(compound); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.steering.readAdditionalSaveData(compoundtag); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.steering.readAdditionalSaveData(compound); + } + + @Override +- @Override + public boolean isSaddled() { + return this.steering.hasSaddle(); + } + + @Override +- @Override + public boolean isSaddleable() { + return this.isAlive() && !this.isBaby(); + } + + @Override +- @Override +- public void equipSaddle(@Nullable SoundSource soundsource) { ++ public void equipSaddle(@Nullable SoundSource source) { + this.steering.setSaddle(true); +- if (soundsource != null) { +- this.level().playSound((Player) null, (Entity) this, SoundEvents.STRIDER_SADDLE, soundsource, 0.5F, 1.0F); ++ if (source != null) { ++ this.level().playSound((Player) null, (Entity) this, SoundEvents.STRIDER_SADDLE, source, 0.5F, 1.0F); + } + + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new PanicGoal(this, 1.65D)); + this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); +@@ -180,14 +172,14 @@ + this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Strider.class, 8.0F)); + } + +- public void setSuffocating(boolean flag) { +- this.entityData.set(Strider.DATA_SUFFOCATING, flag); +- AttributeInstance attributeinstance = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ public void setSuffocating(boolean suffocating) { ++ this.entityData.set(Strider.DATA_SUFFOCATING, suffocating); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); + +- if (attributeinstance != null) { +- attributeinstance.removeModifier(Strider.SUFFOCATING_MODIFIER_UUID); +- if (flag) { +- attributeinstance.addTransientModifier(Strider.SUFFOCATING_MODIFIER); ++ if (attributemodifiable != null) { ++ attributemodifiable.removeModifier(Strider.SUFFOCATING_MODIFIER_UUID); ++ if (suffocating) { ++ attributemodifiable.addTransientModifier(Strider.SUFFOCATING_MODIFIER); + } + } + +@@ -198,39 +190,35 @@ + } + + @Override +- @Override +- public boolean canStandOnFluid(FluidState fluidstate) { +- return fluidstate.is(FluidTags.LAVA); ++ public boolean canStandOnFluid(FluidState fluidState) { ++ return fluidState.is(FluidTags.LAVA); + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { + float f1 = Math.min(0.25F, this.walkAnimation.speed()); + float f2 = this.walkAnimation.position(); + float f3 = 0.12F * Mth.cos(f2 * 1.5F) * 2.0F * f1; + +- return new Vector3f(0.0F, entitydimensions.height + f3 * f, 0.0F); ++ return new Vector3f(0.0F, entitysize.height + f3 * f, 0.0F); + } + + @Override +- @Override +- public boolean checkSpawnObstruction(LevelReader levelreader) { +- return levelreader.isUnobstructed(this); ++ public boolean checkSpawnObstruction(LevelReader level) { ++ return level.isUnobstructed(this); + } + + @Nullable + @Override +- @Override + public LivingEntity getControllingPassenger() { + if (this.isSaddled()) { + Entity entity = this.getFirstPassenger(); + + if (entity instanceof Player) { +- Player player = (Player) entity; ++ Player entityhuman = (Player) entity; + +- if (player.isHolding(Items.WARPED_FUNGUS_ON_A_STICK)) { +- return player; ++ if (entityhuman.isHolding(Items.WARPED_FUNGUS_ON_A_STICK)) { ++ return entityhuman; + } + } + } +@@ -239,46 +227,45 @@ + } + + @Override +- @Override +- public Vec3 getDismountLocationForPassenger(LivingEntity livingentity) { +- Vec3[] avec3 = new Vec3[]{getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingentity.getBbWidth(), livingentity.getYRot()), getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingentity.getBbWidth(), livingentity.getYRot() - 22.5F), getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingentity.getBbWidth(), livingentity.getYRot() + 22.5F), getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingentity.getBbWidth(), livingentity.getYRot() - 45.0F), getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingentity.getBbWidth(), livingentity.getYRot() + 45.0F)}; ++ public Vec3 getDismountLocationForPassenger(LivingEntity livingEntity) { ++ Vec3[] avec3d = new Vec3[]{getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingEntity.getBbWidth(), livingEntity.getYRot()), getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingEntity.getBbWidth(), livingEntity.getYRot() - 22.5F), getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingEntity.getBbWidth(), livingEntity.getYRot() + 22.5F), getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingEntity.getBbWidth(), livingEntity.getYRot() - 45.0F), getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingEntity.getBbWidth(), livingEntity.getYRot() + 45.0F)}; + Set set = Sets.newLinkedHashSet(); + double d0 = this.getBoundingBox().maxY; + double d1 = this.getBoundingBox().minY - 0.5D; +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); +- Vec3[] avec31 = avec3; +- int i = avec3.length; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ Vec3[] avec3d1 = avec3d; ++ int i = avec3d.length; + + for (int j = 0; j < i; ++j) { +- Vec3 vec3 = avec31[j]; ++ Vec3 vec3d = avec3d1[j]; + +- blockpos_mutableblockpos.set(this.getX() + vec3.x, d0, this.getZ() + vec3.z); ++ blockposition_mutableblockposition.set(this.getX() + vec3d.x, d0, this.getZ() + vec3d.z); + + for (double d2 = d0; d2 > d1; --d2) { +- set.add(blockpos_mutableblockpos.immutable()); +- blockpos_mutableblockpos.move(Direction.DOWN); ++ set.add(blockposition_mutableblockposition.immutable()); ++ blockposition_mutableblockposition.move(Direction.DOWN); + } + } + + Iterator iterator = set.iterator(); + + while (iterator.hasNext()) { +- BlockPos blockpos = (BlockPos) iterator.next(); ++ BlockPos blockposition = (BlockPos) iterator.next(); + +- if (!this.level().getFluidState(blockpos).is(FluidTags.LAVA)) { +- double d3 = this.level().getBlockFloorHeight(blockpos); ++ if (!this.level().getFluidState(blockposition).is(FluidTags.LAVA)) { ++ double d3 = this.level().getBlockFloorHeight(blockposition); + + if (DismountHelper.isBlockFloorValid(d3)) { +- Vec3 vec31 = Vec3.upFromBottomCenterOf(blockpos, d3); +- UnmodifiableIterator unmodifiableiterator = livingentity.getDismountPoses().iterator(); ++ Vec3 vec3d1 = Vec3.upFromBottomCenterOf(blockposition, d3); ++ UnmodifiableIterator unmodifiableiterator = livingEntity.getDismountPoses().iterator(); + + while (unmodifiableiterator.hasNext()) { +- Pose pose = (Pose) unmodifiableiterator.next(); +- AABB aabb = livingentity.getLocalBoundsForPose(pose); ++ EntityPose entitypose = (EntityPose) unmodifiableiterator.next(); ++ AABB axisalignedbb = livingEntity.getLocalBoundsForPose(entitypose); + +- if (DismountHelper.canDismountTo(this.level(), livingentity, aabb.move(vec31))) { +- livingentity.setPose(pose); +- return vec31; ++ if (DismountHelper.canDismountTo(this.level(), livingEntity, axisalignedbb.move(vec3d1))) { ++ livingEntity.setPose(entitypose); ++ return vec3d1; + } + } + } +@@ -289,57 +276,49 @@ + } + + @Override +- @Override +- protected void tickRidden(Player player, Vec3 vec3) { ++ protected void tickRidden(Player player, Vec3 travelVector) { + this.setRot(player.getYRot(), player.getXRot() * 0.5F); + this.yRotO = this.yBodyRot = this.yHeadRot = this.getYRot(); + this.steering.tickBoost(); +- super.tickRidden(player, vec3); ++ super.tickRidden(player, travelVector); + } + + @Override +- @Override +- protected Vec3 getRiddenInput(Player player, Vec3 vec3) { ++ protected Vec3 getRiddenInput(Player player, Vec3 travelVector) { + return new Vec3(0.0D, 0.0D, 1.0D); + } + + @Override +- @Override + protected float getRiddenSpeed(Player player) { + return (float) (this.getAttributeValue(Attributes.MOVEMENT_SPEED) * (double) (this.isSuffocating() ? 0.35F : 0.55F) * (double) this.steering.boostFactor()); + } + + @Override +- @Override + protected float nextStep() { + return this.moveDist + 0.6F; + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(this.isInLava() ? SoundEvents.STRIDER_STEP_LAVA : SoundEvents.STRIDER_STEP, 1.0F, 1.0F); + } + + @Override +- @Override + public boolean boost() { + return this.steering.boost(this.getRandom()); + } + + @Override +- @Override +- protected void checkFallDamage(double d0, boolean flag, BlockState blockstate, BlockPos blockpos) { ++ protected void checkFallDamage(double y, boolean flag, IBlockData onGround, BlockPos state) { + this.checkInsideBlocks(); + if (this.isInLava()) { + this.resetFallDistance(); + } else { +- super.checkFallDamage(d0, flag, blockstate, blockpos); ++ super.checkFallDamage(y, flag, onGround, state); + } + } + + @Override +- @Override + public void tick() { + if (this.isBeingTempted() && this.random.nextInt(140) == 0) { + this.playSound(SoundEvents.STRIDER_HAPPY, 1.0F, this.getVoicePitch()); +@@ -352,16 +331,16 @@ + boolean flag1; + label36: + { +- BlockState blockstate = this.level().getBlockState(this.blockPosition()); +- BlockState blockstate1 = this.getBlockStateOnLegacy(); ++ IBlockData iblockdata = this.level().getBlockState(this.blockPosition()); ++ IBlockData iblockdata1 = this.getBlockStateOnLegacy(); + +- flag = blockstate.is(BlockTags.STRIDER_WARM_BLOCKS) || blockstate1.is(BlockTags.STRIDER_WARM_BLOCKS) || this.getFluidHeight(FluidTags.LAVA) > 0.0D; ++ flag = iblockdata.is(BlockTags.STRIDER_WARM_BLOCKS) || iblockdata1.is(BlockTags.STRIDER_WARM_BLOCKS) || this.getFluidHeight(FluidTags.LAVA) > 0.0D; + Entity entity = this.getVehicle(); + + if (entity instanceof Strider) { +- Strider strider = (Strider) entity; ++ Strider entitystrider = (Strider) entity; + +- if (strider.isSuffocating()) { ++ if (entitystrider.isSuffocating()) { + flag1 = true; + break label36; + } +@@ -372,7 +351,14 @@ + + boolean flag2 = flag1; + +- this.setSuffocating(!flag || flag2); ++ // CraftBukkit start ++ boolean suffocating = !flag || flag2; ++ if (suffocating ^ this.isSuffocating()) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callStriderTemperatureChangeEvent(this, suffocating)) { ++ this.setSuffocating(suffocating); ++ } ++ } ++ // CraftBukkit end + } + + super.tick(); +@@ -385,16 +371,15 @@ + } + + @Override +- @Override + protected boolean shouldPassengersInheritMalus() { + return true; + } + + private void floatStrider() { + if (this.isInLava()) { +- CollisionContext collisioncontext = CollisionContext.of(this); ++ CollisionContext voxelshapecollision = CollisionContext.of(this); + +- if (collisioncontext.isAbove(LiquidBlock.STABLE_SHAPE, this.blockPosition(), true) && !this.level().getFluidState(this.blockPosition().above()).is(FluidTags.LAVA)) { ++ if (voxelshapecollision.isAbove(LiquidBlock.STABLE_SHAPE, this.blockPosition(), true) && !this.level().getFluidState(this.blockPosition().above()).is(FluidTags.LAVA)) { + this.setOnGround(true); + } else { + this.setDeltaMovement(this.getDeltaMovement().scale(0.5D).add(0.0D, 0.05D, 0.0D)); +@@ -408,80 +393,68 @@ + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return !this.isPanicking() && !this.isBeingTempted() ? SoundEvents.STRIDER_AMBIENT : null; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.STRIDER_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.STRIDER_DEATH; + } + + @Override +- @Override +- protected boolean canAddPassenger(Entity entity) { ++ protected boolean canAddPassenger(Entity passenger) { + return !this.isVehicle() && !this.isEyeInFluid(FluidTags.LAVA); + } + + @Override +- @Override + public boolean isSensitiveToWater() { + return true; + } + + @Override +- @Override + public boolean isOnFire() { + return false; + } + + @Override +- @Override + protected PathNavigation createNavigation(Level level) { + return new Strider.StriderPathNavigation(this, level); + } + + @Override +- @Override +- public float getWalkTargetValue(BlockPos blockpos, LevelReader levelreader) { +- return levelreader.getBlockState(blockpos).getFluidState().is(FluidTags.LAVA) ? 10.0F : (this.isInLava() ? Float.NEGATIVE_INFINITY : 0.0F); ++ public float getWalkTargetValue(BlockPos pos, LevelReader level) { ++ return level.getBlockState(pos).getFluidState().is(FluidTags.LAVA) ? 10.0F : (this.isInLava() ? Float.NEGATIVE_INFINITY : 0.0F); + } + + @Nullable + @Override +- @Override +- public Strider getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { +- return (Strider) EntityType.STRIDER.create(serverlevel); ++ public Strider getBreedOffspring(ServerLevel level, AgeableMob otherParent) { ++ return (Strider) EntityType.STRIDER.create(level); + } + + @Override +- @Override +- public boolean isFood(ItemStack itemstack) { +- return Strider.FOOD_ITEMS.test(itemstack); ++ public boolean isFood(ItemStack stack) { ++ return Strider.FOOD_ITEMS.test(stack); + } + + @Override +- @Override + protected void dropEquipment() { + super.dropEquipment(); + if (this.isSaddled()) { +- this.spawnAtLocation((ItemLike) Items.SADDLE); ++ this.spawnAtLocation((IMaterial) Items.SADDLE); + } + + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- boolean flag = this.isFood(player.getItemInHand(interactionhand)); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ boolean flag = this.isFood(player.getItemInHand(hand)); + + if (!flag && this.isSaddled() && !this.isVehicle() && !player.isSecondaryUseActive()) { + if (!this.level().isClientSide) { +@@ -490,64 +463,62 @@ + + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { +- InteractionResult interactionresult = super.mobInteract(player, interactionhand); ++ InteractionResult enuminteractionresult = super.mobInteract(player, hand); + +- if (!interactionresult.consumesAction()) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ if (!enuminteractionresult.consumesAction()) { ++ ItemStack itemstack = player.getItemInHand(hand); + +- return itemstack.is(Items.SADDLE) ? itemstack.interactLivingEntity(player, this, interactionhand) : InteractionResult.PASS; ++ return itemstack.is(Items.SADDLE) ? itemstack.interactLivingEntity(player, this, hand) : InteractionResult.PASS; + } else { + if (flag && !this.isSilent()) { + this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.STRIDER_EAT, this.getSoundSource(), 1.0F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F); + } + +- return interactionresult; ++ return enuminteractionresult; + } + } + } + + @Override +- @Override + public Vec3 getLeashOffset() { + return new Vec3(0.0D, (double) (0.6F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); + } + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + if (this.isBaby()) { +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, (SpawnGroupData) spawngroupdata, compoundtag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } else { +- RandomSource randomsource = serverlevelaccessor.getRandom(); ++ RandomSource randomsource = level.getRandom(); + + if (randomsource.nextInt(30) == 0) { +- Mob mob = (Mob) EntityType.ZOMBIFIED_PIGLIN.create(serverlevelaccessor.getLevel()); ++ Mob entityinsentient = (Mob) EntityType.ZOMBIFIED_PIGLIN.create(level.getLevel()); + +- if (mob != null) { +- spawngroupdata = this.spawnJockey(serverlevelaccessor, difficultyinstance, mob, new Zombie.ZombieGroupData(Zombie.getSpawnAsBabyOdds(randomsource), false)); +- mob.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.WARPED_FUNGUS_ON_A_STICK)); ++ if (entityinsentient != null) { ++ spawnData = this.spawnJockey(level, difficulty, entityinsentient, new Zombie.ZombieGroupData(Zombie.getSpawnAsBabyOdds(randomsource), false)); ++ entityinsentient.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.WARPED_FUNGUS_ON_A_STICK)); + this.equipSaddle((SoundSource) null); + } + } else if (randomsource.nextInt(10) == 0) { +- AgeableMob ageablemob = (AgeableMob) EntityType.STRIDER.create(serverlevelaccessor.getLevel()); ++ AgeableMob entityageable = (AgeableMob) EntityType.STRIDER.create(level.getLevel()); + +- if (ageablemob != null) { +- ageablemob.setAge(-24000); +- spawngroupdata = this.spawnJockey(serverlevelaccessor, difficultyinstance, ageablemob, (SpawnGroupData) null); ++ if (entityageable != null) { ++ entityageable.setAge(-24000); ++ spawnData = this.spawnJockey(level, difficulty, entityageable, (GroupDataEntity) null); + } + } else { +- spawngroupdata = new AgeableMob.AgeableMobGroupData(0.5F); ++ spawnData = new AgeableMob.AgeableMobGroupData(0.5F); + } + +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, (SpawnGroupData) spawngroupdata, compoundtag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + } + +- private SpawnGroupData spawnJockey(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, Mob mob, @Nullable SpawnGroupData spawngroupdata) { +- mob.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); +- mob.finalizeSpawn(serverlevelaccessor, difficultyinstance, MobSpawnType.JOCKEY, spawngroupdata, (CompoundTag) null); +- mob.startRiding(this, true); ++ private GroupDataEntity spawnJockey(ServerLevelAccessor serverLevel, DifficultyInstance difficulty, Mob jockey, @Nullable GroupDataEntity spawnData) { ++ jockey.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); ++ jockey.finalizeSpawn(serverLevel, difficulty, EnumMobSpawn.JOCKEY, spawnData, (CompoundTag) null); ++ jockey.startRiding(this, true); + return new AgeableMob.AgeableMobGroupData(0.0F); + } + +@@ -555,39 +526,34 @@ + + private final Strider strider; + +- StriderGoToLavaGoal(Strider strider, double d0) { +- super(strider, d0, 8, 2); ++ StriderGoToLavaGoal(Strider strider, double speedModifier) { ++ super(strider, speedModifier, 8, 2); + this.strider = strider; + } + + @Override +- @Override + public BlockPos getMoveToTarget() { + return this.blockPos; + } + + @Override +- @Override + public boolean canContinueToUse() { + return !this.strider.isInLava() && this.isValidTarget(this.strider.level(), this.blockPos); + } + + @Override +- @Override + public boolean canUse() { + return !this.strider.isInLava() && super.canUse(); + } + + @Override +- @Override + public boolean shouldRecalculatePath() { + return this.tryTicks % 20 == 0; + } + + @Override +- @Override +- protected boolean isValidTarget(LevelReader levelreader, BlockPos blockpos) { +- return levelreader.getBlockState(blockpos).is(Blocks.LAVA) && levelreader.getBlockState(blockpos.above()).isPathfindable(levelreader, blockpos, PathComputationType.LAND); ++ protected boolean isValidTarget(LevelReader level, BlockPos pos) { ++ return level.getBlockState(pos).is(Blocks.LAVA) && level.getBlockState(pos.above()).isPathfindable(level, pos, PathMode.LAND); + } + } + +@@ -598,23 +564,20 @@ + } + + @Override +- @Override +- protected PathFinder createPathFinder(int i) { ++ protected PathFinder createPathFinder(int maxVisitedNodes) { + this.nodeEvaluator = new WalkNodeEvaluator(); + this.nodeEvaluator.setCanPassDoors(true); +- return new PathFinder(this.nodeEvaluator, i); ++ return new PathFinder(this.nodeEvaluator, maxVisitedNodes); + } + + @Override +- @Override +- protected boolean hasValidPathType(BlockPathTypes blockpathtypes) { +- return blockpathtypes != BlockPathTypes.LAVA && blockpathtypes != BlockPathTypes.DAMAGE_FIRE && blockpathtypes != BlockPathTypes.DANGER_FIRE ? super.hasValidPathType(blockpathtypes) : true; ++ protected boolean hasValidPathType(BlockPathTypes pathType) { ++ return pathType != BlockPathTypes.LAVA && pathType != BlockPathTypes.DAMAGE_FIRE && pathType != BlockPathTypes.DANGER_FIRE ? super.hasValidPathType(pathType) : true; + } + + @Override +- @Override +- public boolean isStableDestination(BlockPos blockpos) { +- return this.level.getBlockState(blockpos).is(Blocks.LAVA) || super.isStableDestination(blockpos); ++ public boolean isStableDestination(BlockPos pos) { ++ return this.level.getBlockState(pos).is(Blocks.LAVA) || super.isStableDestination(pos); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Vex.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Vex.java.patch new file mode 100644 index 0000000000..8facc3431a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Vex.java.patch @@ -0,0 +1,449 @@ +--- a/net/minecraft/world/entity/monster/Vex.java ++++ b/net/minecraft/world/entity/monster/Vex.java +@@ -15,15 +15,15 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.PathfinderMob; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.TraceableEntity; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -54,36 +54,32 @@ + Mob owner; + @Nullable + private BlockPos boundOrigin; +- private boolean hasLimitedLife; +- private int limitedLifeTicks; ++ public boolean hasLimitedLife; ++ public int limitedLifeTicks; + +- public Vex(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Vex(EntityType entityType, Level level) { ++ super(entityType, level); + this.moveControl = new Vex.VexMoveControl(this); + this.xpReward = 3; + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return entitydimensions.height - 0.28125F; ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions dimensions) { ++ return dimensions.height - 0.28125F; + } + + @Override +- @Override + public boolean isFlapping() { + return this.tickCount % Vex.TICKS_PER_FLAP == 0; + } + + @Override +- @Override +- public void move(MoverType movertype, Vec3 vec3) { +- super.move(movertype, vec3); ++ public void move(EnumMoveType type, Vec3 pos) { ++ super.move(type, pos); + this.checkInsideBlocks(); + } + + @Override +- @Override + public void tick() { + this.noPhysics = true; + super.tick(); +@@ -97,7 +93,6 @@ + } + + @Override +- @Override + protected void registerGoals() { + super.registerGoals(); + this.goalSelector.addGoal(0, new FloatGoal(this)); +@@ -115,57 +110,52 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Vex.DATA_FLAGS_ID, (byte) 0); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("BoundX")) { +- this.boundOrigin = new BlockPos(compoundtag.getInt("BoundX"), compoundtag.getInt("BoundY"), compoundtag.getInt("BoundZ")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("BoundX")) { ++ this.boundOrigin = new BlockPos(compound.getInt("BoundX"), compound.getInt("BoundY"), compound.getInt("BoundZ")); + } + +- if (compoundtag.contains("LifeTicks")) { +- this.setLimitedLife(compoundtag.getInt("LifeTicks")); ++ if (compound.contains("LifeTicks")) { ++ this.setLimitedLife(compound.getInt("LifeTicks")); + } + + } + + @Override +- @Override + public void restoreFrom(Entity entity) { + super.restoreFrom(entity); + if (entity instanceof Vex) { +- Vex vex = (Vex) entity; ++ Vex entityvex = (Vex) entity; + +- this.owner = vex.getOwner(); ++ this.owner = entityvex.getOwner(); + } + + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); + if (this.boundOrigin != null) { +- compoundtag.putInt("BoundX", this.boundOrigin.getX()); +- compoundtag.putInt("BoundY", this.boundOrigin.getY()); +- compoundtag.putInt("BoundZ", this.boundOrigin.getZ()); ++ compound.putInt("BoundX", this.boundOrigin.getX()); ++ compound.putInt("BoundY", this.boundOrigin.getY()); ++ compound.putInt("BoundZ", this.boundOrigin.getZ()); + } + + if (this.hasLimitedLife) { +- compoundtag.putInt("LifeTicks", this.limitedLifeTicks); ++ compound.putInt("LifeTicks", this.limitedLifeTicks); + } + + } + + @Nullable + @Override +- @Override + public Mob getOwner() { + return this.owner; + } +@@ -175,24 +165,24 @@ + return this.boundOrigin; + } + +- public void setBoundOrigin(@Nullable BlockPos blockpos) { +- this.boundOrigin = blockpos; ++ public void setBoundOrigin(@Nullable BlockPos boundOrigin) { ++ this.boundOrigin = boundOrigin; + } + +- private boolean getVexFlag(int i) { ++ private boolean getVexFlag(int mask) { + byte b0 = (Byte) this.entityData.get(Vex.DATA_FLAGS_ID); + +- return (b0 & i) != 0; ++ return (b0 & mask) != 0; + } + +- private void setVexFlag(int i, boolean flag) { ++ private void setVexFlag(int mask, boolean value) { + byte b0 = (Byte) this.entityData.get(Vex.DATA_FLAGS_ID); + int j; + +- if (flag) { +- j = b0 | i; ++ if (value) { ++ j = b0 | mask; + } else { +- j = b0 & ~i; ++ j = b0 & ~mask; + } + + this.entityData.set(Vex.DATA_FLAGS_ID, (byte) (j & 255)); +@@ -202,95 +192,86 @@ + return this.getVexFlag(1); + } + +- public void setIsCharging(boolean flag) { +- this.setVexFlag(1, flag); ++ public void setIsCharging(boolean charging) { ++ this.setVexFlag(1, charging); + } + +- public void setOwner(Mob mob) { +- this.owner = mob; ++ public void setOwner(Mob owner) { ++ this.owner = owner; + } + +- public void setLimitedLife(int i) { ++ public void setLimitedLife(int limitedLifeTicks) { + this.hasLimitedLife = true; +- this.limitedLifeTicks = i; ++ this.limitedLifeTicks = limitedLifeTicks; + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.VEX_AMBIENT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.VEX_DEATH; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.VEX_HURT; + } + + @Override +- @Override + public float getLightLevelDependentMagicValue() { + return 1.0F; + } + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- RandomSource randomsource = serverlevelaccessor.getRandom(); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ RandomSource randomsource = level.getRandom(); + +- this.populateDefaultEquipmentSlots(randomsource, difficultyinstance); +- this.populateDefaultEquipmentEnchantments(randomsource, difficultyinstance); +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); ++ this.populateDefaultEquipmentSlots(randomsource, difficulty); ++ this.populateDefaultEquipmentEnchantments(randomsource, difficulty); ++ return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + + @Override +- @Override +- protected void populateDefaultEquipmentSlots(RandomSource randomsource, DifficultyInstance difficultyinstance) { ++ protected void populateDefaultEquipmentSlots(RandomSource random, DifficultyInstance difficulty) { + this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.IRON_SWORD)); + this.setDropChance(EquipmentSlot.MAINHAND, 0.0F); + } + + @Override +- @Override + protected float ridingOffset(Entity entity) { + return 0.04F; + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height - 0.0625F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.0625F * f, 0.0F); + } + + private class VexMoveControl extends MoveControl { + +- public VexMoveControl(Vex vex) { +- super(vex); ++ public VexMoveControl(Vex entityvex) { ++ super(entityvex); + } + + @Override +- @Override + public void tick() { + if (this.operation == MoveControl.Operation.MOVE_TO) { +- Vec3 vec3 = new Vec3(this.wantedX - Vex.this.getX(), this.wantedY - Vex.this.getY(), this.wantedZ - Vex.this.getZ()); +- double d0 = vec3.length(); ++ Vec3 vec3d = new Vec3(this.wantedX - Vex.this.getX(), this.wantedY - Vex.this.getY(), this.wantedZ - Vex.this.getZ()); ++ double d0 = vec3d.length(); + + if (d0 < Vex.this.getBoundingBox().getSize()) { + this.operation = MoveControl.Operation.WAIT; + Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().scale(0.5D)); + } else { +- Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().add(vec3.scale(this.speedModifier * 0.05D / d0))); ++ Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().add(vec3d.scale(this.speedModifier * 0.05D / d0))); + if (Vex.this.getTarget() == null) { +- Vec3 vec31 = Vex.this.getDeltaMovement(); ++ Vec3 vec3d1 = Vex.this.getDeltaMovement(); + +- Vex.this.setYRot(-((float) Mth.atan2(vec31.x, vec31.z)) * 57.295776F); ++ Vex.this.setYRot(-((float) Mth.atan2(vec3d1.x, vec3d1.z)) * 57.295776F); + Vex.this.yBodyRot = Vex.this.getYRot(); + } else { + double d1 = Vex.this.getTarget().getX() - Vex.this.getX(); +@@ -308,32 +289,29 @@ + private class VexChargeAttackGoal extends Goal { + + public VexChargeAttackGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +- @Override + public boolean canUse() { +- LivingEntity livingentity = Vex.this.getTarget(); ++ LivingEntity entityliving = Vex.this.getTarget(); + +- return livingentity != null && livingentity.isAlive() && !Vex.this.getMoveControl().hasWanted() && Vex.this.random.nextInt(reducedTickDelay(7)) == 0 ? Vex.this.distanceToSqr((Entity) livingentity) > 4.0D : false; ++ return entityliving != null && entityliving.isAlive() && !Vex.this.getMoveControl().hasWanted() && Vex.this.random.nextInt(reducedTickDelay(7)) == 0 ? Vex.this.distanceToSqr((Entity) entityliving) > 4.0D : false; + } + + @Override +- @Override + public boolean canContinueToUse() { + return Vex.this.getMoveControl().hasWanted() && Vex.this.isCharging() && Vex.this.getTarget() != null && Vex.this.getTarget().isAlive(); + } + + @Override +- @Override + public void start() { +- LivingEntity livingentity = Vex.this.getTarget(); ++ LivingEntity entityliving = Vex.this.getTarget(); + +- if (livingentity != null) { +- Vec3 vec3 = livingentity.getEyePosition(); ++ if (entityliving != null) { ++ Vec3 vec3d = entityliving.getEyePosition(); + +- Vex.this.moveControl.setWantedPosition(vec3.x, vec3.y, vec3.z, 1.0D); ++ Vex.this.moveControl.setWantedPosition(vec3d.x, vec3d.y, vec3d.z, 1.0D); + } + + Vex.this.setIsCharging(true); +@@ -341,33 +319,30 @@ + } + + @Override +- @Override + public void stop() { + Vex.this.setIsCharging(false); + } + + @Override +- @Override + public boolean requiresUpdateEveryTick() { + return true; + } + + @Override +- @Override + public void tick() { +- LivingEntity livingentity = Vex.this.getTarget(); ++ LivingEntity entityliving = Vex.this.getTarget(); + +- if (livingentity != null) { +- if (Vex.this.getBoundingBox().intersects(livingentity.getBoundingBox())) { +- Vex.this.doHurtTarget(livingentity); ++ if (entityliving != null) { ++ if (Vex.this.getBoundingBox().intersects(entityliving.getBoundingBox())) { ++ Vex.this.doHurtTarget(entityliving); + Vex.this.setIsCharging(false); + } else { +- double d0 = Vex.this.distanceToSqr((Entity) livingentity); ++ double d0 = Vex.this.distanceToSqr((Entity) entityliving); + + if (d0 < 9.0D) { +- Vec3 vec3 = livingentity.getEyePosition(); ++ Vec3 vec3d = entityliving.getEyePosition(); + +- Vex.this.moveControl.setWantedPosition(vec3.x, vec3.y, vec3.z, 1.0D); ++ Vex.this.moveControl.setWantedPosition(vec3d.x, vec3d.y, vec3d.z, 1.0D); + } + } + +@@ -378,37 +353,34 @@ + private class VexRandomMoveGoal extends Goal { + + public VexRandomMoveGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +- @Override + public boolean canUse() { + return !Vex.this.getMoveControl().hasWanted() && Vex.this.random.nextInt(reducedTickDelay(7)) == 0; + } + + @Override +- @Override + public boolean canContinueToUse() { + return false; + } + + @Override +- @Override + public void tick() { +- BlockPos blockpos = Vex.this.getBoundOrigin(); ++ BlockPos blockposition = Vex.this.getBoundOrigin(); + +- if (blockpos == null) { +- blockpos = Vex.this.blockPosition(); ++ if (blockposition == null) { ++ blockposition = Vex.this.blockPosition(); + } + + for (int i = 0; i < 3; ++i) { +- BlockPos blockpos1 = blockpos.offset(Vex.this.random.nextInt(15) - 7, Vex.this.random.nextInt(11) - 5, Vex.this.random.nextInt(15) - 7); ++ BlockPos blockposition1 = blockposition.offset(Vex.this.random.nextInt(15) - 7, Vex.this.random.nextInt(11) - 5, Vex.this.random.nextInt(15) - 7); + +- if (Vex.this.level().isEmptyBlock(blockpos1)) { +- Vex.this.moveControl.setWantedPosition((double) blockpos1.getX() + 0.5D, (double) blockpos1.getY() + 0.5D, (double) blockpos1.getZ() + 0.5D, 0.25D); ++ if (Vex.this.level().isEmptyBlock(blockposition1)) { ++ Vex.this.moveControl.setWantedPosition((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.5D, (double) blockposition1.getZ() + 0.5D, 0.25D); + if (Vex.this.getTarget() == null) { +- Vex.this.getLookControl().setLookAt((double) blockpos1.getX() + 0.5D, (double) blockpos1.getY() + 0.5D, (double) blockpos1.getZ() + 0.5D, 180.0F, 20.0F); ++ Vex.this.getLookControl().setLookAt((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.5D, (double) blockposition1.getZ() + 0.5D, 180.0F, 20.0F); + } + break; + } +@@ -421,20 +393,18 @@ + + private final TargetingConditions copyOwnerTargeting = TargetingConditions.forNonCombat().ignoreLineOfSight().ignoreInvisibilityTesting(); + +- public VexCopyOwnerTargetGoal(PathfinderMob pathfindermob) { +- super(pathfindermob, false); ++ public VexCopyOwnerTargetGoal(PathfinderMob entitycreature) { ++ super(entitycreature, false); + } + + @Override +- @Override + public boolean canUse() { + return Vex.this.owner != null && Vex.this.owner.getTarget() != null && this.canAttack(Vex.this.owner.getTarget(), this.copyOwnerTargeting); + } + + @Override +- @Override + public void start() { +- Vex.this.setTarget(Vex.this.owner.getTarget()); ++ Vex.this.setTarget(Vex.this.owner.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.OWNER_ATTACKED_TARGET, true); // CraftBukkit + super.start(); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Witch.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Witch.java.patch new file mode 100644 index 0000000000..adb4184435 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Witch.java.patch @@ -0,0 +1,265 @@ +--- a/net/minecraft/world/entity/monster/Witch.java ++++ b/net/minecraft/world/entity/monster/Witch.java +@@ -17,10 +17,10 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -55,16 +55,15 @@ + private NearestHealableRaiderTargetGoal healRaidersGoal; + private NearestAttackableWitchTargetGoal attackPlayersGoal; + +- public Witch(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Witch(EntityType entityType, Level level) { ++ super(entityType, level); + } + + @Override +- @Override + protected void registerGoals() { + super.registerGoals(); +- this.healRaidersGoal = new NearestHealableRaiderTargetGoal<>(this, Raider.class, true, (livingentity) -> { +- return livingentity != null && this.hasActiveRaid() && livingentity.getType() != EntityType.WITCH; ++ this.healRaidersGoal = new NearestHealableRaiderTargetGoal<>(this, Raider.class, true, (entityliving) -> { ++ return entityliving != null && this.hasActiveRaid() && entityliving.getType() != EntityType.WITCH; + }); + this.attackPlayersGoal = new NearestAttackableWitchTargetGoal<>(this, Player.class, 10, true, false, (Predicate) null); + this.goalSelector.addGoal(1, new FloatGoal(this)); +@@ -78,32 +77,28 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.getEntityData().define(Witch.DATA_USING_ITEM, false); + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.WITCH_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.WITCH_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.WITCH_DEATH; + } + +- public void setUsingItem(boolean flag) { +- this.getEntityData().set(Witch.DATA_USING_ITEM, flag); ++ public void setUsingItem(boolean usingItem) { ++ this.getEntityData().set(Witch.DATA_USING_ITEM, usingItem); + } + + public boolean isDrinkingPotion() { +@@ -115,7 +110,6 @@ + } + + @Override +- @Override + public void aiStep() { + if (!this.level().isClientSide && this.isAlive()) { + this.healRaidersGoal.decrementCooldown(); +@@ -138,9 +132,9 @@ + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- MobEffectInstance mobeffectinstance = (MobEffectInstance) iterator.next(); ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); + +- this.addEffect(new MobEffectInstance(mobeffectinstance)); ++ this.addEffect(new MobEffectInstance(mobeffect), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + } +@@ -149,30 +143,30 @@ + this.getAttribute(Attributes.MOVEMENT_SPEED).removeModifier(Witch.SPEED_MODIFIER_DRINKING.getId()); + } + } else { +- Potion potion = null; ++ Potion potionregistry = null; + + if (this.random.nextFloat() < 0.15F && this.isEyeInFluid(FluidTags.WATER) && !this.hasEffect(MobEffects.WATER_BREATHING)) { +- potion = Potions.WATER_BREATHING; ++ potionregistry = Potions.WATER_BREATHING; + } else if (this.random.nextFloat() < 0.15F && (this.isOnFire() || this.getLastDamageSource() != null && this.getLastDamageSource().is(DamageTypeTags.IS_FIRE)) && !this.hasEffect(MobEffects.FIRE_RESISTANCE)) { +- potion = Potions.FIRE_RESISTANCE; ++ potionregistry = Potions.FIRE_RESISTANCE; + } else if (this.random.nextFloat() < 0.05F && this.getHealth() < this.getMaxHealth()) { +- potion = Potions.HEALING; ++ potionregistry = Potions.HEALING; + } else if (this.random.nextFloat() < 0.5F && this.getTarget() != null && !this.hasEffect(MobEffects.MOVEMENT_SPEED) && this.getTarget().distanceToSqr((Entity) this) > 121.0D) { +- potion = Potions.SWIFTNESS; ++ potionregistry = Potions.SWIFTNESS; + } + +- if (potion != null) { +- this.setItemSlot(EquipmentSlot.MAINHAND, PotionUtils.setPotion(new ItemStack(Items.POTION), potion)); ++ if (potionregistry != null) { ++ this.setItemSlot(EquipmentSlot.MAINHAND, PotionUtils.setPotion(new ItemStack(Items.POTION), potionregistry)); + this.usingTime = this.getMainHandItem().getUseDuration(); + this.setUsingItem(true); + if (!this.isSilent()) { + this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.WITCH_DRINK, this.getSoundSource(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); + } + +- AttributeInstance attributeinstance = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); + +- attributeinstance.removeModifier(Witch.SPEED_MODIFIER_DRINKING.getId()); +- attributeinstance.addTransientModifier(Witch.SPEED_MODIFIER_DRINKING); ++ attributemodifiable.removeModifier(Witch.SPEED_MODIFIER_DRINKING.getId()); ++ attributemodifiable.addTransientModifier(Witch.SPEED_MODIFIER_DRINKING); + } + } + +@@ -185,97 +179,89 @@ + } + + @Override +- @Override + public SoundEvent getCelebrateSound() { + return SoundEvents.WITCH_CELEBRATE; + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 15) { ++ public void handleEntityEvent(byte id) { ++ if (id == 15) { + for (int i = 0; i < this.random.nextInt(35) + 10; ++i) { + this.level().addParticle(ParticleTypes.WITCH, this.getX() + this.random.nextGaussian() * 0.12999999523162842D, this.getBoundingBox().maxY + 0.5D + this.random.nextGaussian() * 0.12999999523162842D, this.getZ() + this.random.nextGaussian() * 0.12999999523162842D, 0.0D, 0.0D, 0.0D); + } + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } + + @Override +- @Override +- protected float getDamageAfterMagicAbsorb(DamageSource damagesource, float f) { +- f = super.getDamageAfterMagicAbsorb(damagesource, f); +- if (damagesource.getEntity() == this) { +- f = 0.0F; ++ protected float getDamageAfterMagicAbsorb(DamageSource source, float damage) { ++ damage = super.getDamageAfterMagicAbsorb(source, damage); ++ if (source.getEntity() == this) { ++ damage = 0.0F; + } + +- if (damagesource.is(DamageTypeTags.WITCH_RESISTANT_TO)) { +- f *= 0.15F; ++ if (source.is(DamageTypeTags.WITCH_RESISTANT_TO)) { ++ damage *= 0.15F; + } + +- return f; ++ return damage; + } + + @Override +- @Override +- public void performRangedAttack(LivingEntity livingentity, float f) { ++ public void performRangedAttack(LivingEntity target, float distanceFactor) { + if (!this.isDrinkingPotion()) { +- Vec3 vec3 = livingentity.getDeltaMovement(); +- double d0 = livingentity.getX() + vec3.x - this.getX(); +- double d1 = livingentity.getEyeY() - 1.100000023841858D - this.getY(); +- double d2 = livingentity.getZ() + vec3.z - this.getZ(); ++ Vec3 vec3d = target.getDeltaMovement(); ++ double d0 = target.getX() + vec3d.x - this.getX(); ++ double d1 = target.getEyeY() - 1.100000023841858D - this.getY(); ++ double d2 = target.getZ() + vec3d.z - this.getZ(); + double d3 = Math.sqrt(d0 * d0 + d2 * d2); +- Potion potion = Potions.HARMING; ++ Potion potionregistry = Potions.HARMING; + +- if (livingentity instanceof Raider) { +- if (livingentity.getHealth() <= 4.0F) { +- potion = Potions.HEALING; ++ if (target instanceof Raider) { ++ if (target.getHealth() <= 4.0F) { ++ potionregistry = Potions.HEALING; + } else { +- potion = Potions.REGENERATION; ++ potionregistry = Potions.REGENERATION; + } + + this.setTarget((LivingEntity) null); +- } else if (d3 >= 8.0D && !livingentity.hasEffect(MobEffects.MOVEMENT_SLOWDOWN)) { +- potion = Potions.SLOWNESS; +- } else if (livingentity.getHealth() >= 8.0F && !livingentity.hasEffect(MobEffects.POISON)) { +- potion = Potions.POISON; +- } else if (d3 <= 3.0D && !livingentity.hasEffect(MobEffects.WEAKNESS) && this.random.nextFloat() < 0.25F) { +- potion = Potions.WEAKNESS; ++ } else if (d3 >= 8.0D && !target.hasEffect(MobEffects.MOVEMENT_SLOWDOWN)) { ++ potionregistry = Potions.SLOWNESS; ++ } else if (target.getHealth() >= 8.0F && !target.hasEffect(MobEffects.POISON)) { ++ potionregistry = Potions.POISON; ++ } else if (d3 <= 3.0D && !target.hasEffect(MobEffects.WEAKNESS) && this.random.nextFloat() < 0.25F) { ++ potionregistry = Potions.WEAKNESS; + } + +- ThrownPotion thrownpotion = new ThrownPotion(this.level(), this); ++ ThrownPotion entitypotion = new ThrownPotion(this.level(), this); + +- thrownpotion.setItem(PotionUtils.setPotion(new ItemStack(Items.SPLASH_POTION), potion)); +- thrownpotion.setXRot(thrownpotion.getXRot() - -20.0F); +- thrownpotion.shoot(d0, d1 + d3 * 0.2D, d2, 0.75F, 8.0F); ++ entitypotion.setItem(PotionUtils.setPotion(new ItemStack(Items.SPLASH_POTION), potionregistry)); ++ entitypotion.setXRot(entitypotion.getXRot() - -20.0F); ++ entitypotion.shoot(d0, d1 + d3 * 0.2D, d2, 0.75F, 8.0F); + if (!this.isSilent()) { + this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.WITCH_THROW, this.getSoundSource(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); + } + +- this.level().addFreshEntity(thrownpotion); ++ this.level().addFreshEntity(entitypotion); + } + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 1.62F; + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height + 0.3125F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.3125F * f, 0.0F); + } + + @Override +- @Override +- public void applyRaidBuffs(int i, boolean flag) {} ++ public void applyRaidBuffs(int wave, boolean unusedFalse) {} + + @Override +- @Override + public boolean canBeLeader() { + return false; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/WitherSkeleton.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/WitherSkeleton.java.patch new file mode 100644 index 0000000000..ecca70df29 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/WitherSkeleton.java.patch @@ -0,0 +1,167 @@ +--- a/net/minecraft/world/entity/monster/WitherSkeleton.java ++++ b/net/minecraft/world/entity/monster/WitherSkeleton.java +@@ -11,119 +11,107 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; + import net.minecraft.world.entity.monster.piglin.AbstractPiglin; + import net.minecraft.world.entity.projectile.AbstractArrow; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + + public class WitherSkeleton extends AbstractSkeleton { + +- public WitherSkeleton(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public WitherSkeleton(EntityType entityType, Level level) { ++ super(entityType, level); + this.setPathfindingMalus(BlockPathTypes.LAVA, 8.0F); + } + + @Override +- @Override + protected void registerGoals() { + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractPiglin.class, true)); + super.registerGoals(); + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.WITHER_SKELETON_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.WITHER_SKELETON_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.WITHER_SKELETON_DEATH; + } + + @Override +- @Override + SoundEvent getStepSound() { + return SoundEvents.WITHER_SKELETON_STEP; + } + + @Override +- @Override +- protected void dropCustomDeathLoot(DamageSource damagesource, int i, boolean flag) { +- super.dropCustomDeathLoot(damagesource, i, flag); +- Entity entity = damagesource.getEntity(); ++ protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { ++ super.dropCustomDeathLoot(source, looting, recentlyHit); ++ Entity entity = source.getEntity(); + + if (entity instanceof Creeper) { +- Creeper creeper = (Creeper) entity; ++ Creeper entitycreeper = (Creeper) entity; + +- if (creeper.canDropMobsSkull()) { +- creeper.increaseDroppedSkulls(); +- this.spawnAtLocation((ItemLike) Items.WITHER_SKELETON_SKULL); ++ if (entitycreeper.canDropMobsSkull()) { ++ entitycreeper.increaseDroppedSkulls(); ++ this.spawnAtLocation((IMaterial) Items.WITHER_SKELETON_SKULL); + } + } + + } + + @Override +- @Override +- protected void populateDefaultEquipmentSlots(RandomSource randomsource, DifficultyInstance difficultyinstance) { ++ protected void populateDefaultEquipmentSlots(RandomSource random, DifficultyInstance difficulty) { + this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.STONE_SWORD)); + } + + @Override +- @Override +- protected void populateDefaultEquipmentEnchantments(RandomSource randomsource, DifficultyInstance difficultyinstance) {} ++ protected void populateDefaultEquipmentEnchantments(RandomSource random, DifficultyInstance difficulty) {} + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- SpawnGroupData spawngroupdata1 = super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ GroupDataEntity groupdataentity1 = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + + this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(4.0D); + this.reassessWeaponGoal(); +- return spawngroupdata1; ++ return groupdataentity1; + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 2.1F; + } + + @Override +- @Override + protected float ridingOffset(Entity entity) { + return -0.875F; + } + + @Override +- @Override + public boolean doHurtTarget(Entity entity) { + if (!super.doHurtTarget(entity)) { + return false; + } else { + if (entity instanceof LivingEntity) { +- ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.WITHER, 200), this); ++ ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.WITHER, 200), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + + return true; +@@ -131,17 +119,15 @@ + } + + @Override +- @Override +- protected AbstractArrow getArrow(ItemStack itemstack, float f) { +- AbstractArrow abstractarrow = super.getArrow(itemstack, f); ++ protected AbstractArrow getArrow(ItemStack arrowStack, float distanceFactor) { ++ AbstractArrow entityarrow = super.getArrow(arrowStack, distanceFactor); + +- abstractarrow.setSecondsOnFire(100); +- return abstractarrow; ++ entityarrow.setSecondsOnFire(100); ++ return entityarrow; + } + + @Override +- @Override +- public boolean canBeAffected(MobEffectInstance mobeffectinstance) { +- return mobeffectinstance.getEffect() == MobEffects.WITHER ? false : super.canBeAffected(mobeffectinstance); ++ public boolean canBeAffected(MobEffectInstance potioneffect) { ++ return potioneffect.getEffect() == MobEffects.WITHER ? false : super.canBeAffected(potioneffect); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Zombie.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Zombie.java.patch new file mode 100644 index 0000000000..1931ef0c75 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/Zombie.java.patch @@ -0,0 +1,693 @@ +--- a/net/minecraft/world/entity/monster/Zombie.java ++++ b/net/minecraft/world/entity/monster/Zombie.java +@@ -6,18 +6,6 @@ + import java.util.UUID; + import java.util.function.Predicate; + import javax.annotation.Nullable; +-import net.minecraft.core.BlockPos; +-import net.minecraft.nbt.CompoundTag; +-import net.minecraft.nbt.NbtOps; +-import net.minecraft.nbt.Tag; +-import net.minecraft.network.syncher.EntityDataAccessor; +-import net.minecraft.network.syncher.EntityDataSerializers; +-import net.minecraft.network.syncher.SynchedEntityData; +-import net.minecraft.server.level.ServerLevel; +-import net.minecraft.sounds.SoundEvent; +-import net.minecraft.sounds.SoundEvents; +-import net.minecraft.sounds.SoundSource; +-import net.minecraft.tags.FluidTags; + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.world.Difficulty; +@@ -25,15 +13,15 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; + import net.minecraft.world.entity.PathfinderMob; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.SpawnPlacements; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; +@@ -64,8 +52,27 @@ + import net.minecraft.world.level.NaturalSpawner; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import org.joml.Vector3f; ++import net.minecraft.core.BlockPos; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.Tag; ++import net.minecraft.network.syncher.EntityDataAccessor; ++import net.minecraft.network.syncher.EntityDataSerializers; ++import net.minecraft.network.syncher.SynchedEntityData; ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundEvents; ++import net.minecraft.sounds.SoundSource; ++import net.minecraft.tags.FluidTags; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++// CraftBukkit end + + public class Zombie extends Monster { + +@@ -73,23 +80,24 @@ + private static final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier(Zombie.SPEED_MODIFIER_BABY_UUID, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE); + private static final EntityDataAccessor DATA_BABY_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_SPECIAL_TYPE_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.INT); +- private static final EntityDataAccessor DATA_DROWNED_CONVERSION_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); ++ public static final EntityDataAccessor DATA_DROWNED_CONVERSION_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); + public static final float ZOMBIE_LEADER_CHANCE = 0.05F; + public static final int REINFORCEMENT_ATTEMPTS = 50; + public static final int REINFORCEMENT_RANGE_MAX = 40; + public static final int REINFORCEMENT_RANGE_MIN = 7; + protected static final float BABY_EYE_HEIGHT_ADJUSTMENT = 0.81F; + private static final float BREAK_DOOR_CHANCE = 0.1F; +- private static final Predicate DOOR_BREAKING_PREDICATE = (difficulty) -> { +- return difficulty == Difficulty.HARD; ++ private static final Predicate DOOR_BREAKING_PREDICATE = (enumdifficulty) -> { ++ return enumdifficulty == Difficulty.HARD; + }; + private final BreakDoorGoal breakDoorGoal; + private boolean canBreakDoors; + private int inWaterTime; +- private int conversionTime; ++ public int conversionTime; ++ private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field + +- public Zombie(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Zombie(EntityType entityType, Level level) { ++ super(entityType, level); + this.breakDoorGoal = new BreakDoorGoal(this, Zombie.DOOR_BREAKING_PREDICATE); + } + +@@ -98,7 +106,6 @@ + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0D, 3)); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); +@@ -122,7 +129,6 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.getEntityData().define(Zombie.DATA_BABY_ID, false); +@@ -138,12 +144,12 @@ + return this.canBreakDoors; + } + +- public void setCanBreakDoors(boolean flag) { ++ public void setCanBreakDoors(boolean canBreakDoors) { + if (this.supportsBreakDoorGoal() && GoalUtils.hasGroundPathNavigation(this)) { +- if (this.canBreakDoors != flag) { +- this.canBreakDoors = flag; +- ((GroundPathNavigation) this.getNavigation()).setCanOpenDoors(flag); +- if (flag) { ++ if (this.canBreakDoors != canBreakDoors) { ++ this.canBreakDoors = canBreakDoors; ++ ((GroundPathNavigation) this.getNavigation()).setCanOpenDoors(canBreakDoors); ++ if (canBreakDoors) { + this.goalSelector.addGoal(1, this.breakDoorGoal); + } else { + this.goalSelector.removeGoal(this.breakDoorGoal); +@@ -161,13 +167,11 @@ + } + + @Override +- @Override + public boolean isBaby() { + return (Boolean) this.getEntityData().get(Zombie.DATA_BABY_ID); + } + + @Override +- @Override + public int getExperienceReward() { + if (this.isBaby()) { + this.xpReward = (int) ((double) this.xpReward * 2.5D); +@@ -177,28 +181,26 @@ + } + + @Override +- @Override +- public void setBaby(boolean flag) { +- this.getEntityData().set(Zombie.DATA_BABY_ID, flag); ++ public void setBaby(boolean childZombie) { ++ this.getEntityData().set(Zombie.DATA_BABY_ID, childZombie); + if (this.level() != null && !this.level().isClientSide) { +- AttributeInstance attributeinstance = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); + +- attributeinstance.removeModifier(Zombie.SPEED_MODIFIER_BABY.getId()); +- if (flag) { +- attributeinstance.addTransientModifier(Zombie.SPEED_MODIFIER_BABY); ++ attributemodifiable.removeModifier(Zombie.SPEED_MODIFIER_BABY.getId()); ++ if (childZombie) { ++ attributemodifiable.addTransientModifier(Zombie.SPEED_MODIFIER_BABY); + } + } + + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- if (Zombie.DATA_BABY_ID.equals(entitydataaccessor)) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ if (Zombie.DATA_BABY_ID.equals(key)) { + this.refreshDimensions(); + } + +- super.onSyncedDataUpdated(entitydataaccessor); ++ super.onSyncedDataUpdated(key); + } + + protected boolean convertsInWater() { +@@ -206,11 +208,13 @@ + } + + @Override +- @Override + public void tick() { + if (!this.level().isClientSide && this.isAlive() && !this.isNoAi()) { + if (this.isUnderWaterConverting()) { +- --this.conversionTime; ++ // CraftBukkit start - Use wall time instead of ticks for conversion ++ int elapsedTicks = MinecraftServer.currentTick - this.lastTick; ++ this.conversionTime -= elapsedTicks; ++ // CraftBukkit end + if (this.conversionTime < 0) { + this.doUnderWaterConversion(); + } +@@ -227,10 +231,10 @@ + } + + super.tick(); ++ this.lastTick = MinecraftServer.currentTick; // CraftBukkit + } + + @Override +- @Override + public void aiStep() { + if (this.isAlive()) { + boolean flag = this.isSunSensitive() && this.isSunBurnTick(); +@@ -259,8 +263,9 @@ + super.aiStep(); + } + +- private void startUnderWaterConversion(int i) { +- this.conversionTime = i; ++ public void startUnderWaterConversion(int conversionTime) { ++ this.lastTick = MinecraftServer.currentTick; // CraftBukkit ++ this.conversionTime = conversionTime; + this.getEntityData().set(Zombie.DATA_DROWNED_CONVERSION_ID, true); + } + +@@ -272,12 +277,16 @@ + + } + +- protected void convertToZombieType(EntityType entitytype) { +- Zombie zombie = (Zombie) this.convertTo(entitytype, true); ++ protected void convertToZombieType(EntityType entityType) { ++ Zombie entityzombie = (Zombie) this.convertTo(entityType, true, EntityTransformEvent.TransformReason.DROWNED, CreatureSpawnEvent.SpawnReason.DROWNED); + +- if (zombie != null) { +- zombie.handleAttributes(zombie.level().getCurrentDifficultyAt(zombie.blockPosition()).getSpecialMultiplier()); +- zombie.setCanBreakDoors(zombie.supportsBreakDoorGoal() && this.canBreakDoors()); ++ if (entityzombie != null) { ++ entityzombie.handleAttributes(entityzombie.level().getCurrentDifficultyAt(entityzombie.blockPosition()).getSpecialMultiplier()); ++ entityzombie.setCanBreakDoors(entityzombie.supportsBreakDoorGoal() && this.canBreakDoors()); ++ // CraftBukkit start - SPIGOT-5208: End conversion to stop event spam ++ } else { ++ ((org.bukkit.entity.Zombie) getBukkitEntity()).setConversionTime(-1); ++ // CraftBukkit end + } + + } +@@ -287,42 +296,41 @@ + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- if (!super.hurt(damagesource, f)) { ++ public boolean hurt(DamageSource source, float amount) { ++ if (!super.hurt(source, amount)) { + return false; + } else if (!(this.level() instanceof ServerLevel)) { + return false; + } else { +- ServerLevel serverlevel = (ServerLevel) this.level(); +- LivingEntity livingentity = this.getTarget(); ++ ServerLevel worldserver = (ServerLevel) this.level(); ++ LivingEntity entityliving = this.getTarget(); + +- if (livingentity == null && damagesource.getEntity() instanceof LivingEntity) { +- livingentity = (LivingEntity) damagesource.getEntity(); ++ if (entityliving == null && source.getEntity() instanceof LivingEntity) { ++ entityliving = (LivingEntity) source.getEntity(); + } + +- if (livingentity != null && this.level().getDifficulty() == Difficulty.HARD && (double) this.random.nextFloat() < this.getAttributeValue(Attributes.SPAWN_REINFORCEMENTS_CHANCE) && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { ++ if (entityliving != null && this.level().getDifficulty() == Difficulty.HARD && (double) this.random.nextFloat() < this.getAttributeValue(Attributes.SPAWN_REINFORCEMENTS_CHANCE) && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { + int i = Mth.floor(this.getX()); + int j = Mth.floor(this.getY()); + int k = Mth.floor(this.getZ()); +- Zombie zombie = new Zombie(this.level()); ++ Zombie entityzombie = new Zombie(this.level()); + + for (int l = 0; l < 50; ++l) { + int i1 = i + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); + int j1 = j + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); + int k1 = k + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); +- BlockPos blockpos = new BlockPos(i1, j1, k1); +- EntityType entitytype = zombie.getType(); +- SpawnPlacements.Type spawnplacements_type = SpawnPlacements.getPlacementType(entitytype); ++ BlockPos blockposition = new BlockPos(i1, j1, k1); ++ EntityType entitytypes = entityzombie.getType(); ++ SpawnPlacements.Surface entitypositiontypes_surface = SpawnPlacements.getPlacementType(entitytypes); + +- if (NaturalSpawner.isSpawnPositionOk(spawnplacements_type, this.level(), blockpos, entitytype) && SpawnPlacements.checkSpawnRules(entitytype, serverlevel, MobSpawnType.REINFORCEMENT, blockpos, this.level().random)) { +- zombie.setPos((double) i1, (double) j1, (double) k1); +- if (!this.level().hasNearbyAlivePlayer((double) i1, (double) j1, (double) k1, 7.0D) && this.level().isUnobstructed(zombie) && this.level().noCollision((Entity) zombie) && !this.level().containsAnyLiquid(zombie.getBoundingBox())) { +- zombie.setTarget(livingentity); +- zombie.finalizeSpawn(serverlevel, this.level().getCurrentDifficultyAt(zombie.blockPosition()), MobSpawnType.REINFORCEMENT, (SpawnGroupData) null, (CompoundTag) null); +- serverlevel.addFreshEntityWithPassengers(zombie); ++ if (NaturalSpawner.isSpawnPositionOk(entitypositiontypes_surface, this.level(), blockposition, entitytypes) && SpawnPlacements.checkSpawnRules(entitytypes, worldserver, EnumMobSpawn.REINFORCEMENT, blockposition, this.level().random)) { ++ entityzombie.setPos((double) i1, (double) j1, (double) k1); ++ if (!this.level().hasNearbyAlivePlayer((double) i1, (double) j1, (double) k1, 7.0D) && this.level().isUnobstructed(entityzombie) && this.level().noCollision((Entity) entityzombie) && !this.level().containsAnyLiquid(entityzombie.getBoundingBox())) { ++ entityzombie.setTarget(entityliving, EntityTargetEvent.TargetReason.REINFORCEMENT_TARGET, true); // CraftBukkit ++ entityzombie.finalizeSpawn(worldserver, this.level().getCurrentDifficultyAt(entityzombie.blockPosition()), EnumMobSpawn.REINFORCEMENT, (GroupDataEntity) null, (CompoundTag) null); ++ worldserver.addFreshEntityWithPassengers(entityzombie, CreatureSpawnEvent.SpawnReason.REINFORCEMENTS); // CraftBukkit + this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).addPermanentModifier(new AttributeModifier("Zombie reinforcement caller charge", -0.05000000074505806D, AttributeModifier.Operation.ADDITION)); +- zombie.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).addPermanentModifier(new AttributeModifier("Zombie reinforcement callee charge", -0.05000000074505806D, AttributeModifier.Operation.ADDITION)); ++ entityzombie.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).addPermanentModifier(new AttributeModifier("Zombie reinforcement callee charge", -0.05000000074505806D, AttributeModifier.Operation.ADDITION)); + break; + } + } +@@ -334,7 +342,6 @@ + } + + @Override +- @Override + public boolean doHurtTarget(Entity entity) { + boolean flag = super.doHurtTarget(entity); + +@@ -342,7 +349,14 @@ + float f = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty(); + + if (this.getMainHandItem().isEmpty() && this.isOnFire() && this.random.nextFloat() < f * 0.3F) { +- entity.setSecondsOnFire(2 * (int) f); ++ // CraftBukkit start ++ EntityCombustByEntityEvent event = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), 2 * (int) f); // PAIL: fixme ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ entity.setSecondsOnFire(event.getDuration(), false); ++ } ++ // CraftBukkit end + } + } + +@@ -350,19 +364,16 @@ + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.ZOMBIE_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.ZOMBIE_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.ZOMBIE_DEATH; + } +@@ -372,23 +383,20 @@ + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(this.getStepSound(), 0.15F, 1.0F); + } + + @Override +- @Override +- public MobType getMobType() { +- return MobType.UNDEAD; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.UNDEAD; + } + + @Override +- @Override +- protected void populateDefaultEquipmentSlots(RandomSource randomsource, DifficultyInstance difficultyinstance) { +- super.populateDefaultEquipmentSlots(randomsource, difficultyinstance); +- if (randomsource.nextFloat() < (this.level().getDifficulty() == Difficulty.HARD ? 0.05F : 0.01F)) { +- int i = randomsource.nextInt(3); ++ protected void populateDefaultEquipmentSlots(RandomSource random, DifficultyInstance difficulty) { ++ super.populateDefaultEquipmentSlots(random, difficulty); ++ if (random.nextFloat() < (this.level().getDifficulty() == Difficulty.HARD ? 0.05F : 0.01F)) { ++ int i = random.nextInt(3); + + if (i == 0) { + this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.IRON_SWORD)); +@@ -400,84 +408,88 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putBoolean("IsBaby", this.isBaby()); +- compoundtag.putBoolean("CanBreakDoors", this.canBreakDoors()); +- compoundtag.putInt("InWaterTime", this.isInWater() ? this.inWaterTime : -1); +- compoundtag.putInt("DrownedConversionTime", this.isUnderWaterConverting() ? this.conversionTime : -1); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putBoolean("IsBaby", this.isBaby()); ++ compound.putBoolean("CanBreakDoors", this.canBreakDoors()); ++ compound.putInt("InWaterTime", this.isInWater() ? this.inWaterTime : -1); ++ compound.putInt("DrownedConversionTime", this.isUnderWaterConverting() ? this.conversionTime : -1); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setBaby(compoundtag.getBoolean("IsBaby")); +- this.setCanBreakDoors(compoundtag.getBoolean("CanBreakDoors")); +- this.inWaterTime = compoundtag.getInt("InWaterTime"); +- if (compoundtag.contains("DrownedConversionTime", 99) && compoundtag.getInt("DrownedConversionTime") > -1) { +- this.startUnderWaterConversion(compoundtag.getInt("DrownedConversionTime")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setBaby(compound.getBoolean("IsBaby")); ++ this.setCanBreakDoors(compound.getBoolean("CanBreakDoors")); ++ this.inWaterTime = compound.getInt("InWaterTime"); ++ if (compound.contains("DrownedConversionTime", 99) && compound.getInt("DrownedConversionTime") > -1) { ++ this.startUnderWaterConversion(compound.getInt("DrownedConversionTime")); + } + + } + + @Override +- @Override +- public boolean killedEntity(ServerLevel serverlevel, LivingEntity livingentity) { +- boolean flag = super.killedEntity(serverlevel, livingentity); ++ public boolean killedEntity(ServerLevel level, LivingEntity entity) { ++ boolean flag = super.killedEntity(level, entity); + +- if ((serverlevel.getDifficulty() == Difficulty.NORMAL || serverlevel.getDifficulty() == Difficulty.HARD) && livingentity instanceof Villager) { +- Villager villager = (Villager) livingentity; ++ if ((level.getDifficulty() == Difficulty.NORMAL || level.getDifficulty() == Difficulty.HARD) && entity instanceof Villager) { ++ Villager entityvillager = (Villager) entity; + +- if (serverlevel.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { ++ if (level.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { + return flag; + } ++ // CraftBukkit start ++ flag = zombifyVillager(level, entityvillager, this.blockPosition(), this.isSilent(), CreatureSpawnEvent.SpawnReason.INFECTION) == null; ++ } + +- ZombieVillager zombievillager = (ZombieVillager) villager.convertTo(EntityType.ZOMBIE_VILLAGER, false); ++ return flag; ++ } + +- if (zombievillager != null) { +- zombievillager.finalizeSpawn(serverlevel, serverlevel.getCurrentDifficultyAt(zombievillager.blockPosition()), MobSpawnType.CONVERSION, new Zombie.ZombieGroupData(false, true), (CompoundTag) null); +- zombievillager.setVillagerData(villager.getVillagerData()); +- zombievillager.setGossips((Tag) villager.getGossips().store(NbtOps.INSTANCE)); +- zombievillager.setTradeOffers(villager.getOffers().createTag()); +- zombievillager.setVillagerXp(villager.getVillagerXp()); +- if (!this.isSilent()) { +- serverlevel.levelEvent((Player) null, 1026, this.blockPosition(), 0); ++ public static ZombieVillager zombifyVillager(ServerLevel worldserver, Villager entityvillager, net.minecraft.core.BlockPos blockPosition, boolean silent, CreatureSpawnEvent.SpawnReason spawnReason) { ++ { ++ ZombieVillager entityzombievillager = (ZombieVillager) entityvillager.convertTo(EntityType.ZOMBIE_VILLAGER, false, EntityTransformEvent.TransformReason.INFECTION, spawnReason); ++ // CraftBukkit end ++ ++ if (entityzombievillager != null) { ++ entityzombievillager.finalizeSpawn(worldserver, worldserver.getCurrentDifficultyAt(entityzombievillager.blockPosition()), EnumMobSpawn.CONVERSION, new Zombie.ZombieGroupData(false, true), (CompoundTag) null); ++ entityzombievillager.setVillagerData(entityvillager.getVillagerData()); ++ entityzombievillager.setGossips((Tag) entityvillager.getGossips().store(NbtOps.INSTANCE)); ++ entityzombievillager.setTradeOffers(entityvillager.getOffers().createTag()); ++ entityzombievillager.setVillagerXp(entityvillager.getVillagerXp()); ++ // CraftBukkit start ++ if (!silent) { ++ worldserver.levelEvent((Player) null, 1026, blockPosition, 0); + } + +- flag = false; ++ // flag = false; + } +- } + +- return flag; ++ return entityzombievillager; ++ } ++ // CraftBukkit end + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return this.isBaby() ? 0.93F : 1.74F; + } + + @Override +- @Override +- public boolean canHoldItem(ItemStack itemstack) { +- return itemstack.is(Items.EGG) && this.isBaby() && this.isPassenger() ? false : super.canHoldItem(itemstack); ++ public boolean canHoldItem(ItemStack stack) { ++ return stack.is(Items.EGG) && this.isBaby() && this.isPassenger() ? false : super.canHoldItem(stack); + } + + @Override +- @Override +- public boolean wantsToPickUp(ItemStack itemstack) { +- return itemstack.is(Items.GLOW_INK_SAC) ? false : super.wantsToPickUp(itemstack); ++ public boolean wantsToPickUp(ItemStack stack) { ++ return stack.is(Items.GLOW_INK_SAC) ? false : super.wantsToPickUp(stack); + } + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- RandomSource randomsource = serverlevelaccessor.getRandom(); +- Object object = super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); +- float f = difficultyinstance.getSpecialMultiplier(); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ RandomSource randomsource = level.getRandom(); ++ Object object = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ float f = difficulty.getSpecialMultiplier(); + + this.setCanPickUpLoot(randomsource.nextFloat() < 0.55F * f); + if (object == null) { +@@ -485,37 +497,37 @@ + } + + if (object instanceof Zombie.ZombieGroupData) { +- Zombie.ZombieGroupData zombie_zombiegroupdata = (Zombie.ZombieGroupData) object; ++ Zombie.ZombieGroupData entityzombie_groupdatazombie = (Zombie.ZombieGroupData) object; + +- if (zombie_zombiegroupdata.isBaby) { ++ if (entityzombie_groupdatazombie.isBaby) { + this.setBaby(true); +- if (zombie_zombiegroupdata.canSpawnJockey) { ++ if (entityzombie_groupdatazombie.canSpawnJockey) { + if ((double) randomsource.nextFloat() < 0.05D) { +- List list = serverlevelaccessor.getEntitiesOfClass(Chicken.class, this.getBoundingBox().inflate(5.0D, 3.0D, 5.0D), EntitySelector.ENTITY_NOT_BEING_RIDDEN); ++ List list = level.getEntitiesOfClass(Chicken.class, this.getBoundingBox().inflate(5.0D, 3.0D, 5.0D), EntitySelector.ENTITY_NOT_BEING_RIDDEN); + + if (!list.isEmpty()) { +- Chicken chicken = (Chicken) list.get(0); ++ Chicken entitychicken = (Chicken) list.get(0); + +- chicken.setChickenJockey(true); +- this.startRiding(chicken); ++ entitychicken.setChickenJockey(true); ++ this.startRiding(entitychicken); + } + } else if ((double) randomsource.nextFloat() < 0.05D) { +- Chicken chicken1 = (Chicken) EntityType.CHICKEN.create(this.level()); ++ Chicken entitychicken1 = (Chicken) EntityType.CHICKEN.create(this.level()); + +- if (chicken1 != null) { +- chicken1.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); +- chicken1.finalizeSpawn(serverlevelaccessor, difficultyinstance, MobSpawnType.JOCKEY, (SpawnGroupData) null, (CompoundTag) null); +- chicken1.setChickenJockey(true); +- this.startRiding(chicken1); +- serverlevelaccessor.addFreshEntity(chicken1); ++ if (entitychicken1 != null) { ++ entitychicken1.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); ++ entitychicken1.finalizeSpawn(level, difficulty, EnumMobSpawn.JOCKEY, (GroupDataEntity) null, (CompoundTag) null); ++ entitychicken1.setChickenJockey(true); ++ this.startRiding(entitychicken1); ++ level.addFreshEntity(entitychicken1, CreatureSpawnEvent.SpawnReason.MOUNT); // CraftBukkit + } + } + } + } + + this.setCanBreakDoors(this.supportsBreakDoorGoal() && randomsource.nextFloat() < f * 0.1F); +- this.populateDefaultEquipmentSlots(randomsource, difficultyinstance); +- this.populateDefaultEquipmentEnchantments(randomsource, difficultyinstance); ++ this.populateDefaultEquipmentSlots(randomsource, difficulty); ++ this.populateDefaultEquipmentEnchantments(randomsource, difficulty); + } + + if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { +@@ -530,23 +542,23 @@ + } + + this.handleAttributes(f); +- return (SpawnGroupData) object; ++ return (GroupDataEntity) object; + } + +- public static boolean getSpawnAsBabyOdds(RandomSource randomsource) { +- return randomsource.nextFloat() < 0.05F; ++ public static boolean getSpawnAsBabyOdds(RandomSource random) { ++ return random.nextFloat() < 0.05F; + } + +- protected void handleAttributes(float f) { ++ protected void handleAttributes(float difficulty) { + this.randomizeReinforcementsChance(); + this.getAttribute(Attributes.KNOCKBACK_RESISTANCE).addPermanentModifier(new AttributeModifier("Random spawn bonus", this.random.nextDouble() * 0.05000000074505806D, AttributeModifier.Operation.ADDITION)); +- double d0 = this.random.nextDouble() * 1.5D * (double) f; ++ double d0 = this.random.nextDouble() * 1.5D * (double) difficulty; + + if (d0 > 1.0D) { + this.getAttribute(Attributes.FOLLOW_RANGE).addPermanentModifier(new AttributeModifier("Random zombie-spawn bonus", d0, AttributeModifier.Operation.MULTIPLY_TOTAL)); + } + +- if (this.random.nextFloat() < f * 0.05F) { ++ if (this.random.nextFloat() < difficulty * 0.05F) { + this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).addPermanentModifier(new AttributeModifier("Leader zombie bonus", this.random.nextDouble() * 0.25D + 0.5D, AttributeModifier.Operation.ADDITION)); + this.getAttribute(Attributes.MAX_HEALTH).addPermanentModifier(new AttributeModifier("Leader zombie bonus", this.random.nextDouble() * 3.0D + 1.0D, AttributeModifier.Operation.MULTIPLY_TOTAL)); + this.setCanBreakDoors(this.supportsBreakDoorGoal()); +@@ -559,31 +571,28 @@ + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height + 0.0625F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.0625F * f, 0.0F); + } + + @Override +- @Override + protected float ridingOffset(Entity entity) { + return -0.7F; + } + + @Override +- @Override +- protected void dropCustomDeathLoot(DamageSource damagesource, int i, boolean flag) { +- super.dropCustomDeathLoot(damagesource, i, flag); +- Entity entity = damagesource.getEntity(); ++ protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { ++ super.dropCustomDeathLoot(source, looting, recentlyHit); ++ Entity entity = source.getEntity(); + + if (entity instanceof Creeper) { +- Creeper creeper = (Creeper) entity; ++ Creeper entitycreeper = (Creeper) entity; + +- if (creeper.canDropMobsSkull()) { ++ if (entitycreeper.canDropMobsSkull()) { + ItemStack itemstack = this.getSkull(); + + if (!itemstack.isEmpty()) { +- creeper.increaseDroppedSkulls(); ++ entitycreeper.increaseDroppedSkulls(); + this.spawnAtLocation(itemstack); + } + } +@@ -597,37 +606,34 @@ + + private class ZombieAttackTurtleEggGoal extends RemoveBlockGoal { + +- ZombieAttackTurtleEggGoal(PathfinderMob pathfindermob, double d0, int i) { +- super(Blocks.TURTLE_EGG, pathfindermob, d0, i); ++ ZombieAttackTurtleEggGoal(PathfinderMob mob, double speedModifier, int i) { ++ super(Blocks.TURTLE_EGG, mob, speedModifier, i); + } + + @Override +- @Override +- public void playDestroyProgressSound(LevelAccessor levelaccessor, BlockPos blockpos) { +- levelaccessor.playSound((Player) null, blockpos, SoundEvents.ZOMBIE_DESTROY_EGG, SoundSource.HOSTILE, 0.5F, 0.9F + Zombie.this.random.nextFloat() * 0.2F); ++ public void playDestroyProgressSound(LevelAccessor level, BlockPos pos) { ++ level.playSound((Player) null, pos, SoundEvents.ZOMBIE_DESTROY_EGG, SoundSource.HOSTILE, 0.5F, 0.9F + Zombie.this.random.nextFloat() * 0.2F); + } + + @Override +- @Override +- public void playBreakSound(Level level, BlockPos blockpos) { +- level.playSound((Player) null, blockpos, SoundEvents.TURTLE_EGG_BREAK, SoundSource.BLOCKS, 0.7F, 0.9F + level.random.nextFloat() * 0.2F); ++ public void playBreakSound(Level level, BlockPos pos) { ++ level.playSound((Player) null, pos, SoundEvents.TURTLE_EGG_BREAK, SoundSource.BLOCKS, 0.7F, 0.9F + level.random.nextFloat() * 0.2F); + } + + @Override +- @Override + public double acceptedDistance() { + return 1.14D; + } + } + +- public static class ZombieGroupData implements SpawnGroupData { ++ public static class ZombieGroupData implements GroupDataEntity { + + public final boolean isBaby; + public final boolean canSpawnJockey; + +- public ZombieGroupData(boolean flag, boolean flag1) { +- this.isBaby = flag; +- this.canSpawnJockey = flag1; ++ public ZombieGroupData(boolean isBaby, boolean canSpawnJockey) { ++ this.isBaby = isBaby; ++ this.canSpawnJockey = canSpawnJockey; + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/ZombieVillager.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/ZombieVillager.java.patch new file mode 100644 index 0000000000..f4dc49b5ce --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/ZombieVillager.java.patch @@ -0,0 +1,449 @@ +--- a/net/minecraft/world/entity/monster/ZombieVillager.java ++++ b/net/minecraft/world/entity/monster/ZombieVillager.java +@@ -15,12 +15,8 @@ + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; +-import net.minecraft.server.level.ServerLevel; +-import net.minecraft.server.level.ServerPlayer; +-import net.minecraft.sounds.SoundEvent; +-import net.minecraft.sounds.SoundEvents; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffectInstance; +@@ -28,9 +24,9 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.ai.village.ReputationEventType; + import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.entity.npc.VillagerData; +@@ -46,37 +42,47 @@ + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.BedBlock; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import org.joml.Vector3f; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundEvents; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++// CraftBukkit end ++ + public class ZombieVillager extends Zombie implements VillagerDataHolder { + + private static final Logger LOGGER = LogUtils.getLogger(); +- private static final EntityDataAccessor DATA_CONVERTING_ID = SynchedEntityData.defineId(ZombieVillager.class, EntityDataSerializers.BOOLEAN); ++ public static final EntityDataAccessor DATA_CONVERTING_ID = SynchedEntityData.defineId(ZombieVillager.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_VILLAGER_DATA = SynchedEntityData.defineId(ZombieVillager.class, EntityDataSerializers.VILLAGER_DATA); + private static final int VILLAGER_CONVERSION_WAIT_MIN = 3600; + private static final int VILLAGER_CONVERSION_WAIT_MAX = 6000; + private static final int MAX_SPECIAL_BLOCKS_COUNT = 14; + private static final int SPECIAL_BLOCK_RADIUS = 4; +- private int villagerConversionTime; ++ public int villagerConversionTime; + @Nullable +- private UUID conversionStarter; ++ public UUID conversionStarter; + @Nullable + private Tag gossips; + @Nullable + private CompoundTag tradeOffers; + private int villagerXp; ++ private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field + +- public ZombieVillager(EntityType entitytype, Level level) { +- super(entitytype, level); +- BuiltInRegistries.VILLAGER_PROFESSION.getRandom(this.random).ifPresent((holder_reference) -> { +- this.setVillagerData(this.getVillagerData().setProfession((VillagerProfession) holder_reference.value())); ++ public ZombieVillager(EntityType entityType, Level level) { ++ super(entityType, level); ++ BuiltInRegistries.VILLAGER_PROFESSION.getRandom(this.random).ifPresent((holder_c) -> { ++ this.setVillagerData(this.getVillagerData().setProfession((VillagerProfession) holder_c.value())); + }); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(ZombieVillager.DATA_CONVERTING_ID, false); +@@ -84,67 +90,68 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- DataResult dataresult = VillagerData.CODEC.encodeStart(NbtOps.INSTANCE, this.getVillagerData()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ DataResult dataresult = VillagerData.CODEC.encodeStart(NbtOps.INSTANCE, this.getVillagerData()); // CraftBukkit - decompile error + Logger logger = ZombieVillager.LOGGER; + + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((tag) -> { +- compoundtag.put("VillagerData", tag); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("VillagerData", nbtbase); + }); + if (this.tradeOffers != null) { +- compoundtag.put("Offers", this.tradeOffers); ++ compound.put("Offers", this.tradeOffers); + } + + if (this.gossips != null) { +- compoundtag.put("Gossips", this.gossips); ++ compound.put("Gossips", this.gossips); + } + +- compoundtag.putInt("ConversionTime", this.isConverting() ? this.villagerConversionTime : -1); ++ compound.putInt("ConversionTime", this.isConverting() ? this.villagerConversionTime : -1); + if (this.conversionStarter != null) { +- compoundtag.putUUID("ConversionPlayer", this.conversionStarter); ++ compound.putUUID("ConversionPlayer", this.conversionStarter); + } + +- compoundtag.putInt("Xp", this.villagerXp); ++ compound.putInt("Xp", this.villagerXp); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("VillagerData", 10)) { +- DataResult dataresult = VillagerData.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compoundtag.get("VillagerData"))); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("VillagerData", 10)) { ++ DataResult dataresult = VillagerData.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compound.get("VillagerData"))); + Logger logger = ZombieVillager.LOGGER; + + Objects.requireNonNull(logger); + dataresult.resultOrPartial(logger::error).ifPresent(this::setVillagerData); + } + +- if (compoundtag.contains("Offers", 10)) { +- this.tradeOffers = compoundtag.getCompound("Offers"); ++ if (compound.contains("Offers", 10)) { ++ this.tradeOffers = compound.getCompound("Offers"); + } + +- if (compoundtag.contains("Gossips", 9)) { +- this.gossips = compoundtag.getList("Gossips", 10); ++ if (compound.contains("Gossips", 9)) { ++ this.gossips = compound.getList("Gossips", 10); + } + +- if (compoundtag.contains("ConversionTime", 99) && compoundtag.getInt("ConversionTime") > -1) { +- this.startConverting(compoundtag.hasUUID("ConversionPlayer") ? compoundtag.getUUID("ConversionPlayer") : null, compoundtag.getInt("ConversionTime")); ++ if (compound.contains("ConversionTime", 99) && compound.getInt("ConversionTime") > -1) { ++ this.startConverting(compound.hasUUID("ConversionPlayer") ? compound.getUUID("ConversionPlayer") : null, compound.getInt("ConversionTime")); + } + +- if (compoundtag.contains("Xp", 3)) { +- this.villagerXp = compoundtag.getInt("Xp"); ++ if (compound.contains("Xp", 3)) { ++ this.villagerXp = compound.getInt("Xp"); + } + + } + + @Override +- @Override + public void tick() { + if (!this.level().isClientSide && this.isAlive() && this.isConverting()) { + int i = this.getConversionProgress(); ++ // CraftBukkit start - Use wall time instead of ticks for villager conversion ++ int elapsedTicks = MinecraftServer.currentTick - this.lastTick; ++ i *= elapsedTicks; ++ // CraftBukkit end + + this.villagerConversionTime -= i; + if (this.villagerConversionTime <= 0) { +@@ -153,12 +160,12 @@ + } + + super.tick(); ++ this.lastTick = MinecraftServer.currentTick; // CraftBukkit + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (itemstack.is(Items.GOLDEN_APPLE)) { + if (this.hasEffect(MobEffects.WEAKNESS)) { +@@ -175,19 +182,17 @@ + return InteractionResult.CONSUME; + } + } else { +- return super.mobInteract(player, interactionhand); ++ return super.mobInteract(player, hand); + } + } + + @Override +- @Override + protected boolean convertsInWater() { + return false; + } + + @Override +- @Override +- public boolean removeWhenFarAway(double d0) { ++ public boolean removeWhenFarAway(double distanceToClosestPlayer) { + return !this.isConverting() && this.villagerXp == 0; + } + +@@ -195,74 +200,83 @@ + return (Boolean) this.getEntityData().get(ZombieVillager.DATA_CONVERTING_ID); + } + +- private void startConverting(@Nullable UUID uuid, int i) { +- this.conversionStarter = uuid; +- this.villagerConversionTime = i; ++ public void startConverting(@Nullable UUID conversionStarter, int villagerConversionTime) { ++ this.conversionStarter = conversionStarter; ++ this.villagerConversionTime = villagerConversionTime; + this.getEntityData().set(ZombieVillager.DATA_CONVERTING_ID, true); +- this.removeEffect(MobEffects.WEAKNESS); +- this.addEffect(new MobEffectInstance(MobEffects.DAMAGE_BOOST, i, Math.min(this.level().getDifficulty().getId() - 1, 0))); ++ // CraftBukkit start ++ this.removeEffect(MobEffects.WEAKNESS, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); ++ this.addEffect(new MobEffectInstance(MobEffects.DAMAGE_BOOST, villagerConversionTime, Math.min(this.level().getDifficulty().getId() - 1, 0)), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); ++ // CraftBukkit end + this.level().broadcastEntityEvent(this, (byte) 16); + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 16) { ++ public void handleEntityEvent(byte id) { ++ if (id == 16) { + if (!this.isSilent()) { + this.level().playLocalSound(this.getX(), this.getEyeY(), this.getZ(), SoundEvents.ZOMBIE_VILLAGER_CURE, this.getSoundSource(), 1.0F + this.random.nextFloat(), this.random.nextFloat() * 0.7F + 0.3F, false); + } + + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + } + +- private void finishConversion(ServerLevel serverlevel) { +- Villager villager = (Villager) this.convertTo(EntityType.VILLAGER, false); +- EquipmentSlot[] aequipmentslot = EquipmentSlot.values(); +- int i = aequipmentslot.length; ++ private void finishConversion(ServerLevel serverLevel) { ++ // CraftBukkit start ++ Villager entityvillager = (Villager) this.convertTo(EntityType.VILLAGER, false, EntityTransformEvent.TransformReason.CURED, CreatureSpawnEvent.SpawnReason.CURED); ++ if (entityvillager == null) { ++ ((org.bukkit.entity.ZombieVillager) getBukkitEntity()).setConversionTime(-1); // SPIGOT-5208: End conversion to stop event spam ++ return; ++ } ++ // CraftBukkit end ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ int i = aenumitemslot.length; + + for (int j = 0; j < i; ++j) { +- EquipmentSlot equipmentslot = aequipmentslot[j]; +- ItemStack itemstack = this.getItemBySlot(equipmentslot); ++ EquipmentSlot enumitemslot = aenumitemslot[j]; ++ ItemStack itemstack = this.getItemBySlot(enumitemslot); + + if (!itemstack.isEmpty()) { + if (EnchantmentHelper.hasBindingCurse(itemstack)) { +- villager.getSlot(equipmentslot.getIndex() + 300).set(itemstack); ++ entityvillager.getSlot(enumitemslot.getIndex() + 300).set(itemstack); + } else { +- double d0 = (double) this.getEquipmentDropChance(equipmentslot); ++ double d0 = (double) this.getEquipmentDropChance(enumitemslot); + + if (d0 > 1.0D) { ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation(itemstack); ++ this.forceDrops = false; // CraftBukkit + } + } + } + } + +- villager.setVillagerData(this.getVillagerData()); ++ entityvillager.setVillagerData(this.getVillagerData()); + if (this.gossips != null) { +- villager.setGossips(this.gossips); ++ entityvillager.setGossips(this.gossips); + } + + if (this.tradeOffers != null) { +- villager.setOffers(new MerchantOffers(this.tradeOffers)); ++ entityvillager.setOffers(new MerchantOffers(this.tradeOffers)); + } + +- villager.setVillagerXp(this.villagerXp); +- villager.finalizeSpawn(serverlevel, serverlevel.getCurrentDifficultyAt(villager.blockPosition()), MobSpawnType.CONVERSION, (SpawnGroupData) null, (CompoundTag) null); +- villager.refreshBrain(serverlevel); ++ entityvillager.setVillagerXp(this.villagerXp); ++ entityvillager.finalizeSpawn(serverLevel, serverLevel.getCurrentDifficultyAt(entityvillager.blockPosition()), EnumMobSpawn.CONVERSION, (GroupDataEntity) null, (CompoundTag) null); ++ entityvillager.refreshBrain(serverLevel); + if (this.conversionStarter != null) { +- Player player = serverlevel.getPlayerByUUID(this.conversionStarter); ++ Player entityhuman = serverLevel.getPlayerByUUID(this.conversionStarter); + +- if (player instanceof ServerPlayer) { +- CriteriaTriggers.CURED_ZOMBIE_VILLAGER.trigger((ServerPlayer) player, this, villager); +- serverlevel.onReputationEvent(ReputationEventType.ZOMBIE_VILLAGER_CURED, player, villager); ++ if (entityhuman instanceof ServerPlayer) { ++ CriteriaTriggers.CURED_ZOMBIE_VILLAGER.trigger((ServerPlayer) entityhuman, this, entityvillager); ++ serverLevel.onReputationEvent(ReputationEventType.ZOMBIE_VILLAGER_CURED, entityhuman, entityvillager); + } + } + +- villager.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0)); ++ entityvillager.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); // CraftBukkit + if (!this.isSilent()) { +- serverlevel.levelEvent((Player) null, 1027, this.blockPosition(), 0); ++ serverLevel.levelEvent((Player) null, 1027, this.blockPosition(), 0); + } + + } +@@ -272,14 +286,14 @@ + + if (this.random.nextFloat() < 0.01F) { + int j = 0; +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + + for (int k = (int) this.getX() - 4; k < (int) this.getX() + 4 && j < 14; ++k) { + for (int l = (int) this.getY() - 4; l < (int) this.getY() + 4 && j < 14; ++l) { + for (int i1 = (int) this.getZ() - 4; i1 < (int) this.getZ() + 4 && j < 14; ++i1) { +- BlockState blockstate = this.level().getBlockState(blockpos_mutableblockpos.set(k, l, i1)); ++ IBlockData iblockdata = this.level().getBlockState(blockposition_mutableblockposition.set(k, l, i1)); + +- if (blockstate.is(Blocks.IRON_BARS) || blockstate.getBlock() instanceof BedBlock) { ++ if (iblockdata.is(Blocks.IRON_BARS) || iblockdata.getBlock() instanceof BedBlock) { + if (this.random.nextFloat() < 0.3F) { + ++i; + } +@@ -295,71 +309,62 @@ + } + + @Override +- @Override + public float getVoicePitch() { + return this.isBaby() ? (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 2.0F : (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F; + } + + @Override +- @Override + public SoundEvent getAmbientSound() { + return SoundEvents.ZOMBIE_VILLAGER_AMBIENT; + } + + @Override +- @Override +- public SoundEvent getHurtSound(DamageSource damagesource) { ++ public SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.ZOMBIE_VILLAGER_HURT; + } + + @Override +- @Override + public SoundEvent getDeathSound() { + return SoundEvents.ZOMBIE_VILLAGER_DEATH; + } + + @Override +- @Override + public SoundEvent getStepSound() { + return SoundEvents.ZOMBIE_VILLAGER_STEP; + } + + @Override +- @Override + protected ItemStack getSkull() { + return ItemStack.EMPTY; + } + +- public void setTradeOffers(CompoundTag compoundtag) { +- this.tradeOffers = compoundtag; ++ public void setTradeOffers(CompoundTag tradeOffers) { ++ this.tradeOffers = tradeOffers; + } + +- public void setGossips(Tag tag) { +- this.gossips = tag; ++ public void setGossips(Tag gossips) { ++ this.gossips = gossips; + } + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- this.setVillagerData(this.getVillagerData().setType(VillagerType.byBiome(serverlevelaccessor.getBiome(this.blockPosition())))); +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ this.setVillagerData(this.getVillagerData().setType(VillagerType.byBiome(level.getBiome(this.blockPosition())))); ++ return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + + @Override +- @Override +- public void setVillagerData(VillagerData villagerdata) { ++ public void setVillagerData(VillagerData data) { + VillagerData villagerdata1 = this.getVillagerData(); + +- if (villagerdata1.getProfession() != villagerdata.getProfession()) { ++ if (villagerdata1.getProfession() != data.getProfession()) { + this.tradeOffers = null; + } + +- this.entityData.set(ZombieVillager.DATA_VILLAGER_DATA, villagerdata); ++ this.entityData.set(ZombieVillager.DATA_VILLAGER_DATA, data); + } + + @Override +- @Override + public VillagerData getVillagerData() { + return (VillagerData) this.entityData.get(ZombieVillager.DATA_VILLAGER_DATA); + } +@@ -368,13 +373,12 @@ + return this.villagerXp; + } + +- public void setVillagerXp(int i) { +- this.villagerXp = i; ++ public void setVillagerXp(int villagerXp) { ++ this.villagerXp = villagerXp; + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height + 0.175F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.175F * f, 0.0F); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/ZombifiedPiglin.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/ZombifiedPiglin.java.patch new file mode 100644 index 0000000000..c9954f35e0 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/ZombifiedPiglin.java.patch @@ -0,0 +1,259 @@ +--- a/net/minecraft/world/entity/monster/ZombifiedPiglin.java ++++ b/net/minecraft/world/entity/monster/ZombifiedPiglin.java +@@ -15,13 +15,13 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.NeutralMob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -58,19 +58,17 @@ + private static final float ZOMBIFIED_PIGLIN_EYE_HEIGHT = 1.79F; + private static final float ZOMBIFIED_PIGLIN_BABY_EYE_HEIGHT_ADJUSTMENT = 0.82F; + +- public ZombifiedPiglin(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public ZombifiedPiglin(EntityType entityType, Level level) { ++ super(entityType, level); + this.setPathfindingMalus(BlockPathTypes.LAVA, 8.0F); + } + + @Override +- @Override +- public void setPersistentAngerTarget(@Nullable UUID uuid) { +- this.persistentAngerTarget = uuid; ++ public void setPersistentAngerTarget(@Nullable UUID target) { ++ this.persistentAngerTarget = target; + } + + @Override +- @Override + protected void addBehaviourGoals() { + this.goalSelector.addGoal(2, new ZombieAttackGoal(this, 1.0D, false)); + this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D)); +@@ -84,30 +82,27 @@ + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return this.isBaby() ? 0.96999997F : 1.79F; + } + + @Override +- @Override + protected boolean convertsInWater() { + return false; + } + + @Override +- @Override + protected void customServerAiStep() { +- AttributeInstance attributeinstance = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); + + if (this.isAngry()) { +- if (!this.isBaby() && !attributeinstance.hasModifier(ZombifiedPiglin.SPEED_MODIFIER_ATTACKING)) { +- attributeinstance.addTransientModifier(ZombifiedPiglin.SPEED_MODIFIER_ATTACKING); ++ if (!this.isBaby() && !attributemodifiable.hasModifier(ZombifiedPiglin.SPEED_MODIFIER_ATTACKING)) { ++ attributemodifiable.addTransientModifier(ZombifiedPiglin.SPEED_MODIFIER_ATTACKING); + } + + this.maybePlayFirstAngerSound(); +- } else if (attributeinstance.hasModifier(ZombifiedPiglin.SPEED_MODIFIER_ATTACKING)) { +- attributeinstance.removeModifier(ZombifiedPiglin.SPEED_MODIFIER_ATTACKING.getId()); ++ } else if (attributemodifiable.hasModifier(ZombifiedPiglin.SPEED_MODIFIER_ATTACKING)) { ++ attributemodifiable.removeModifier(ZombifiedPiglin.SPEED_MODIFIER_ATTACKING.getId()); + } + + this.updatePersistentAnger((ServerLevel) this.level(), true); +@@ -146,16 +141,16 @@ + + private void alertOthers() { + double d0 = this.getAttributeValue(Attributes.FOLLOW_RANGE); +- AABB aabb = AABB.unitCubeFromLowerCorner(this.position()).inflate(d0, 10.0D, d0); ++ AABB axisalignedbb = AABB.unitCubeFromLowerCorner(this.position()).inflate(d0, 10.0D, d0); + +- this.level().getEntitiesOfClass(ZombifiedPiglin.class, aabb, EntitySelector.NO_SPECTATORS).stream().filter((zombifiedpiglin) -> { +- return zombifiedpiglin != this; +- }).filter((zombifiedpiglin) -> { +- return zombifiedpiglin.getTarget() == null; +- }).filter((zombifiedpiglin) -> { +- return !zombifiedpiglin.isAlliedTo((Entity) this.getTarget()); +- }).forEach((zombifiedpiglin) -> { +- zombifiedpiglin.setTarget(this.getTarget()); ++ this.level().getEntitiesOfClass(ZombifiedPiglin.class, axisalignedbb, EntitySelector.NO_SPECTATORS).stream().filter((entitypigzombie) -> { ++ return entitypigzombie != this; ++ }).filter((entitypigzombie) -> { ++ return entitypigzombie.getTarget() == null; ++ }).filter((entitypigzombie) -> { ++ return !entitypigzombie.isAlliedTo((Entity) this.getTarget()); ++ }).forEach((entitypigzombie) -> { ++ entitypigzombie.setTarget(this.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_NEARBY_ENTITY, true); // CraftBukkit + }); + } + +@@ -164,120 +159,112 @@ + } + + @Override +- @Override +- public void setTarget(@Nullable LivingEntity livingentity) { +- if (this.getTarget() == null && livingentity != null) { ++ public boolean setTarget(@Nullable LivingEntity entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) { // CraftBukkit - signature ++ if (this.getTarget() == null && entityliving != null) { + this.playFirstAngerSoundIn = ZombifiedPiglin.FIRST_ANGER_SOUND_DELAY.sample(this.random); + this.ticksUntilNextAlert = ZombifiedPiglin.ALERT_INTERVAL.sample(this.random); + } + +- if (livingentity instanceof Player) { +- this.setLastHurtByPlayer((Player) livingentity); ++ if (entityliving instanceof Player) { ++ this.setLastHurtByPlayer((Player) entityliving); + } + +- super.setTarget(livingentity); ++ return super.setTarget(entityliving, reason, fireEvent); // CraftBukkit + } + + @Override +- @Override + public void startPersistentAngerTimer() { +- this.setRemainingPersistentAngerTime(ZombifiedPiglin.PERSISTENT_ANGER_TIME.sample(this.random)); ++ // CraftBukkit start ++ Entity entity = ((ServerLevel) this.level()).getEntity(getPersistentAngerTarget()); ++ org.bukkit.event.entity.PigZombieAngerEvent event = new org.bukkit.event.entity.PigZombieAngerEvent((org.bukkit.entity.PigZombie) this.getBukkitEntity(), (entity == null) ? null : entity.getBukkitEntity(), ZombifiedPiglin.PERSISTENT_ANGER_TIME.sample(this.random)); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ this.setPersistentAngerTarget(null); ++ return; ++ } ++ this.setRemainingPersistentAngerTime(event.getNewAnger()); ++ // CraftBukkit end + } + +- public static boolean checkZombifiedPiglinSpawnRules(EntityType entitytype, LevelAccessor levelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- return levelaccessor.getDifficulty() != Difficulty.PEACEFUL && !levelaccessor.getBlockState(blockpos.below()).is(Blocks.NETHER_WART_BLOCK); ++ public static boolean checkZombifiedPiglinSpawnRules(EntityType zombifiedPiglin, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ return level.getDifficulty() != Difficulty.PEACEFUL && !level.getBlockState(pos.below()).is(Blocks.NETHER_WART_BLOCK); + } + + @Override +- @Override +- public boolean checkSpawnObstruction(LevelReader levelreader) { +- return levelreader.isUnobstructed(this) && !levelreader.containsAnyLiquid(this.getBoundingBox()); ++ public boolean checkSpawnObstruction(LevelReader level) { ++ return level.isUnobstructed(this) && !level.containsAnyLiquid(this.getBoundingBox()); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- this.addPersistentAngerSaveData(compoundtag); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ this.addPersistentAngerSaveData(compound); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.readPersistentAngerSaveData(this.level(), compoundtag); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.readPersistentAngerSaveData(this.level(), compound); + } + + @Override +- @Override +- public void setRemainingPersistentAngerTime(int i) { +- this.remainingPersistentAngerTime = i; ++ public void setRemainingPersistentAngerTime(int time) { ++ this.remainingPersistentAngerTime = time; + } + + @Override +- @Override + public int getRemainingPersistentAngerTime() { + return this.remainingPersistentAngerTime; + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return this.isAngry() ? SoundEvents.ZOMBIFIED_PIGLIN_ANGRY : SoundEvents.ZOMBIFIED_PIGLIN_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.ZOMBIFIED_PIGLIN_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.ZOMBIFIED_PIGLIN_DEATH; + } + + @Override +- @Override +- protected void populateDefaultEquipmentSlots(RandomSource randomsource, DifficultyInstance difficultyinstance) { ++ protected void populateDefaultEquipmentSlots(RandomSource random, DifficultyInstance difficulty) { + this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.GOLDEN_SWORD)); + } + + @Override +- @Override + protected ItemStack getSkull() { + return ItemStack.EMPTY; + } + + @Override +- @Override + protected void randomizeReinforcementsChance() { + this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(0.0D); + } + + @Nullable + @Override +- @Override + public UUID getPersistentAngerTarget() { + return this.persistentAngerTarget; + } + + @Override +- @Override + public boolean isPreventingPlayerRest(Player player) { + return this.isAngryAt(player); + } + + @Override +- @Override +- public boolean wantsToPickUp(ItemStack itemstack) { +- return this.canHoldItem(itemstack); ++ public boolean wantsToPickUp(ItemStack stack) { ++ return this.canHoldItem(stack); + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height + 0.05F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.05F * f, 0.0F); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java.patch new file mode 100644 index 0000000000..3d2dc4339d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java.patch @@ -0,0 +1,151 @@ +--- a/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java ++++ b/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java +@@ -11,9 +11,9 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + import net.minecraft.world.entity.ai.navigation.GroundPathNavigation; + import net.minecraft.world.entity.ai.util.GoalUtils; +@@ -29,10 +29,10 @@ + protected static final EntityDataAccessor DATA_IMMUNE_TO_ZOMBIFICATION = SynchedEntityData.defineId(AbstractPiglin.class, EntityDataSerializers.BOOLEAN); + protected static final int CONVERSION_TIME = 300; + protected static final float PIGLIN_EYE_HEIGHT = 1.79F; +- protected int timeInOverworld; ++ public int timeInOverworld; + +- public AbstractPiglin(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public AbstractPiglin(EntityType entityType, Level level) { ++ super(entityType, level); + this.setCanPickUpLoot(true); + this.applyOpenDoorsAbility(); + this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, 16.0F); +@@ -47,61 +47,54 @@ + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions dimensions) { + return 1.79F; + } + + @Override +- @Override + protected float ridingOffset(Entity entity) { + return -0.7F; + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height + 0.0625F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.0625F * f, 0.0F); + } + + protected abstract boolean canHunt(); + +- public void setImmuneToZombification(boolean flag) { +- this.getEntityData().set(AbstractPiglin.DATA_IMMUNE_TO_ZOMBIFICATION, flag); ++ public void setImmuneToZombification(boolean immuneToZombification) { ++ this.getEntityData().set(AbstractPiglin.DATA_IMMUNE_TO_ZOMBIFICATION, immuneToZombification); + } + +- protected boolean isImmuneToZombification() { ++ public boolean isImmuneToZombification() { + return (Boolean) this.getEntityData().get(AbstractPiglin.DATA_IMMUNE_TO_ZOMBIFICATION); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(AbstractPiglin.DATA_IMMUNE_TO_ZOMBIFICATION, false); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); + if (this.isImmuneToZombification()) { +- compoundtag.putBoolean("IsImmuneToZombification", true); ++ compound.putBoolean("IsImmuneToZombification", true); + } + +- compoundtag.putInt("TimeInOverworld", this.timeInOverworld); ++ compound.putInt("TimeInOverworld", this.timeInOverworld); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setImmuneToZombification(compoundtag.getBoolean("IsImmuneToZombification")); +- this.timeInOverworld = compoundtag.getInt("TimeInOverworld"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setImmuneToZombification(compound.getBoolean("IsImmuneToZombification")); ++ this.timeInOverworld = compound.getInt("TimeInOverworld"); + } + + @Override +- @Override + protected void customServerAiStep() { + super.customServerAiStep(); + if (this.isConverting()) { +@@ -121,11 +114,11 @@ + return !this.level().dimensionType().piglinSafe() && !this.isImmuneToZombification() && !this.isNoAi(); + } + +- protected void finishConversion(ServerLevel serverlevel) { +- ZombifiedPiglin zombifiedpiglin = (ZombifiedPiglin) this.convertTo(EntityType.ZOMBIFIED_PIGLIN, true); ++ protected void finishConversion(ServerLevel serverLevel) { ++ ZombifiedPiglin entitypigzombie = (ZombifiedPiglin) this.convertTo(EntityType.ZOMBIFIED_PIGLIN, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.PIGLIN_ZOMBIFIED, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.PIGLIN_ZOMBIFIED); // CraftBukkit - add spawn and transform reasons + +- if (zombifiedpiglin != null) { +- zombifiedpiglin.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0)); ++ if (entitypigzombie != null) { ++ entitypigzombie.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0)); + } + + } +@@ -134,13 +127,12 @@ + return !this.isBaby(); + } + +- public abstract PiglinArmPose getArmPose(); ++ public abstract EntityPiglinArmPose getArmPose(); + + @Nullable + @Override +- @Override + public LivingEntity getTarget() { +- return (LivingEntity) this.brain.getMemory(MemoryModuleType.ATTACK_TARGET).orElse((Object) null); ++ return (LivingEntity) this.brain.getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); // CraftBukkit - decompile error + } + + protected boolean isHoldingMeleeWeapon() { +@@ -148,7 +140,6 @@ + } + + @Override +- @Override + public void playAmbientSound() { + if (PiglinAi.isIdle(this)) { + super.playAmbientSound(); +@@ -157,7 +148,6 @@ + } + + @Override +- @Override + protected void sendDebugPackets() { + super.sendDebugPackets(); + DebugPackets.sendEntityBrain(this); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/piglin/Piglin.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/piglin/Piglin.java.patch new file mode 100644 index 0000000000..159757d04c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/piglin/Piglin.java.patch @@ -0,0 +1,595 @@ +--- a/net/minecraft/world/entity/monster/piglin/Piglin.java ++++ b/net/minecraft/world/entity/monster/piglin/Piglin.java +@@ -5,30 +5,22 @@ + import java.util.List; + import java.util.UUID; + import javax.annotation.Nullable; +-import net.minecraft.core.BlockPos; +-import net.minecraft.nbt.CompoundTag; +-import net.minecraft.network.syncher.EntityDataAccessor; +-import net.minecraft.network.syncher.EntityDataSerializers; +-import net.minecraft.network.syncher.SynchedEntityData; +-import net.minecraft.server.level.ServerLevel; +-import net.minecraft.sounds.SoundEvent; +-import net.minecraft.sounds.SoundEvents; + import net.minecraft.util.RandomSource; + import net.minecraft.util.VisibleForDebug; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; +@@ -53,8 +45,28 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start ++import java.util.stream.Collectors; ++import java.util.HashSet; ++import java.util.Set; ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.registries.BuiltInRegistries; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; ++import net.minecraft.nbt.StringTag; ++import net.minecraft.nbt.Tag; ++import net.minecraft.network.syncher.EntityDataAccessor; ++import net.minecraft.network.syncher.EntityDataSerializers; ++import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundEvents; ++import net.minecraft.world.item.Item; ++// CraftBukkit end ++ + public class Piglin extends AbstractPiglin implements CrossbowAttackMob, InventoryCarrier { + + private static final EntityDataAccessor DATA_BABY_ID = SynchedEntityData.defineId(Piglin.class, EntityDataSerializers.BOOLEAN); +@@ -71,60 +83,72 @@ + private static final float PROBABILITY_OF_SPAWNING_AS_BABY = 0.2F; + private static final float BABY_EYE_HEIGHT_ADJUSTMENT = 0.82F; + private static final double PROBABILITY_OF_SPAWNING_WITH_CROSSBOW_INSTEAD_OF_SWORD = 0.5D; +- private final SimpleContainer inventory = new SimpleContainer(8); +- private boolean cannotHunt; ++ public final SimpleContainer inventory = new SimpleContainer(8); ++ public boolean cannotHunt; + protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.NEAREST_ITEMS, SensorType.HURT_BY, SensorType.PIGLIN_SPECIFIC_SENSOR); + protected static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.LOOK_TARGET, MemoryModuleType.DOORS_TO_CLOSE, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ADULT_PIGLINS, MemoryModuleType.NEARBY_ADULT_PIGLINS, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, new MemoryModuleType[]{MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.ATTACK_TARGET, MemoryModuleType.ATTACK_COOLING_DOWN, MemoryModuleType.INTERACTION_TARGET, MemoryModuleType.PATH, MemoryModuleType.ANGRY_AT, MemoryModuleType.UNIVERSAL_ANGER, MemoryModuleType.AVOID_TARGET, MemoryModuleType.ADMIRING_ITEM, MemoryModuleType.TIME_TRYING_TO_REACH_ADMIRE_ITEM, MemoryModuleType.ADMIRING_DISABLED, MemoryModuleType.DISABLE_WALK_TO_ADMIRE_ITEM, MemoryModuleType.CELEBRATE_LOCATION, MemoryModuleType.DANCING, MemoryModuleType.HUNTED_RECENTLY, MemoryModuleType.NEAREST_VISIBLE_BABY_HOGLIN, MemoryModuleType.NEAREST_VISIBLE_NEMESIS, MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED, MemoryModuleType.RIDE_TARGET, MemoryModuleType.VISIBLE_ADULT_PIGLIN_COUNT, MemoryModuleType.VISIBLE_ADULT_HOGLIN_COUNT, MemoryModuleType.NEAREST_VISIBLE_HUNTABLE_HOGLIN, MemoryModuleType.NEAREST_TARGETABLE_PLAYER_NOT_WEARING_GOLD, MemoryModuleType.NEAREST_PLAYER_HOLDING_WANTED_ITEM, MemoryModuleType.ATE_RECENTLY, MemoryModuleType.NEAREST_REPELLENT}); ++ // CraftBukkit start - Custom bartering and interest list ++ public Set allowedBarterItems = new HashSet<>(); ++ public Set interestItems = new HashSet<>(); ++ // CraftBukkit end + +- public Piglin(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Piglin(EntityType entityType, Level level) { ++ super(entityType, level); + this.xpReward = 5; + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); + if (this.isBaby()) { +- compoundtag.putBoolean("IsBaby", true); ++ compound.putBoolean("IsBaby", true); + } + + if (this.cannotHunt) { +- compoundtag.putBoolean("CannotHunt", true); ++ compound.putBoolean("CannotHunt", true); + } + +- this.writeInventoryToTag(compoundtag); ++ this.writeInventoryToTag(compound); ++ // CraftBukkit start ++ ListTag barterList = new ListTag(); ++ allowedBarterItems.stream().map(BuiltInRegistries.ITEM::getKey).map(ResourceLocation::toString).map(StringTag::valueOf).forEach(barterList::add); ++ compound.put("Bukkit.BarterList", barterList); ++ ListTag interestList = new ListTag(); ++ interestItems.stream().map(BuiltInRegistries.ITEM::getKey).map(ResourceLocation::toString).map(StringTag::valueOf).forEach(interestList::add); ++ compound.put("Bukkit.InterestList", interestList); ++ // CraftBukkit end + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setBaby(compoundtag.getBoolean("IsBaby")); +- this.setCannotHunt(compoundtag.getBoolean("CannotHunt")); +- this.readInventoryFromTag(compoundtag); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setBaby(compound.getBoolean("IsBaby")); ++ this.setCannotHunt(compound.getBoolean("CannotHunt")); ++ this.readInventoryFromTag(compound); ++ // CraftBukkit start ++ this.allowedBarterItems = compound.getList("Bukkit.BarterList", 8).stream().map(Tag::getAsString).map(ResourceLocation::tryParse).map(BuiltInRegistries.ITEM::get).collect(Collectors.toCollection(HashSet::new)); ++ this.interestItems = compound.getList("Bukkit.InterestList", 8).stream().map(Tag::getAsString).map(ResourceLocation::tryParse).map(BuiltInRegistries.ITEM::get).collect(Collectors.toCollection(HashSet::new)); ++ // CraftBukkit end + } + + @VisibleForDebug + @Override +- @Override + public SimpleContainer getInventory() { + return this.inventory; + } + + @Override +- @Override +- protected void dropCustomDeathLoot(DamageSource damagesource, int i, boolean flag) { +- super.dropCustomDeathLoot(damagesource, i, flag); +- Entity entity = damagesource.getEntity(); ++ protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { ++ super.dropCustomDeathLoot(source, looting, recentlyHit); ++ Entity entity = source.getEntity(); + + if (entity instanceof Creeper) { +- Creeper creeper = (Creeper) entity; ++ Creeper entitycreeper = (Creeper) entity; + +- if (creeper.canDropMobsSkull()) { ++ if (entitycreeper.canDropMobsSkull()) { + ItemStack itemstack = new ItemStack(Items.PIGLIN_HEAD); + +- creeper.increaseDroppedSkulls(); ++ entitycreeper.increaseDroppedSkulls(); + this.spawnAtLocation(itemstack); + } + } +@@ -132,16 +156,15 @@ + this.inventory.removeAllItems().forEach(this::spawnAtLocation); + } + +- protected ItemStack addToInventory(ItemStack itemstack) { +- return this.inventory.addItem(itemstack); ++ protected ItemStack addToInventory(ItemStack stack) { ++ return this.inventory.addItem(stack); + } + +- protected boolean canAddToInventory(ItemStack itemstack) { +- return this.inventory.canAddItem(itemstack); ++ protected boolean canAddToInventory(ItemStack stack) { ++ return this.inventory.canAddItem(stack); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Piglin.DATA_BABY_ID, false); +@@ -150,10 +173,9 @@ + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- super.onSyncedDataUpdated(entitydataaccessor); +- if (Piglin.DATA_BABY_ID.equals(entitydataaccessor)) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ super.onSyncedDataUpdated(key); ++ if (Piglin.DATA_BABY_ID.equals(key)) { + this.refreshDimensions(); + } + +@@ -163,17 +185,16 @@ + return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 16.0D).add(Attributes.MOVEMENT_SPEED, 0.3499999940395355D).add(Attributes.ATTACK_DAMAGE, 5.0D); + } + +- public static boolean checkPiglinSpawnRules(EntityType entitytype, LevelAccessor levelaccessor, MobSpawnType mobspawntype, BlockPos blockpos, RandomSource randomsource) { +- return !levelaccessor.getBlockState(blockpos.below()).is(Blocks.NETHER_WART_BLOCK); ++ public static boolean checkPiglinSpawnRules(EntityType piglin, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ return !level.getBlockState(pos.below()).is(Blocks.NETHER_WART_BLOCK); + } + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- RandomSource randomsource = serverlevelaccessor.getRandom(); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ RandomSource randomsource = level.getRandom(); + +- if (mobspawntype != MobSpawnType.STRUCTURE) { ++ if (reason != EnumMobSpawn.STRUCTURE) { + if (randomsource.nextFloat() < 0.2F) { + this.setBaby(true); + } else if (this.isAdult()) { +@@ -181,118 +202,106 @@ + } + } + +- PiglinAi.initMemories(this, serverlevelaccessor.getRandom()); +- this.populateDefaultEquipmentSlots(randomsource, difficultyinstance); +- this.populateDefaultEquipmentEnchantments(randomsource, difficultyinstance); +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); ++ PiglinAi.initMemories(this, level.getRandom()); ++ this.populateDefaultEquipmentSlots(randomsource, difficulty); ++ this.populateDefaultEquipmentEnchantments(randomsource, difficulty); ++ return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + + @Override +- @Override + protected boolean shouldDespawnInPeaceful() { + return false; + } + + @Override +- @Override +- public boolean removeWhenFarAway(double d0) { ++ public boolean removeWhenFarAway(double distanceToClosestPlayer) { + return !this.isPersistenceRequired(); + } + + @Override +- @Override +- protected void populateDefaultEquipmentSlots(RandomSource randomsource, DifficultyInstance difficultyinstance) { ++ protected void populateDefaultEquipmentSlots(RandomSource random, DifficultyInstance difficulty) { + if (this.isAdult()) { +- this.maybeWearArmor(EquipmentSlot.HEAD, new ItemStack(Items.GOLDEN_HELMET), randomsource); +- this.maybeWearArmor(EquipmentSlot.CHEST, new ItemStack(Items.GOLDEN_CHESTPLATE), randomsource); +- this.maybeWearArmor(EquipmentSlot.LEGS, new ItemStack(Items.GOLDEN_LEGGINGS), randomsource); +- this.maybeWearArmor(EquipmentSlot.FEET, new ItemStack(Items.GOLDEN_BOOTS), randomsource); ++ this.maybeWearArmor(EquipmentSlot.HEAD, new ItemStack(Items.GOLDEN_HELMET), random); ++ this.maybeWearArmor(EquipmentSlot.CHEST, new ItemStack(Items.GOLDEN_CHESTPLATE), random); ++ this.maybeWearArmor(EquipmentSlot.LEGS, new ItemStack(Items.GOLDEN_LEGGINGS), random); ++ this.maybeWearArmor(EquipmentSlot.FEET, new ItemStack(Items.GOLDEN_BOOTS), random); + } + + } + +- private void maybeWearArmor(EquipmentSlot equipmentslot, ItemStack itemstack, RandomSource randomsource) { +- if (randomsource.nextFloat() < 0.1F) { +- this.setItemSlot(equipmentslot, itemstack); ++ private void maybeWearArmor(EquipmentSlot slot, ItemStack stack, RandomSource random) { ++ if (random.nextFloat() < 0.1F) { ++ this.setItemSlot(slot, stack); + } + + } + + @Override +- @Override + protected Brain.Provider brainProvider() { + return Brain.provider(Piglin.MEMORY_TYPES, Piglin.SENSOR_TYPES); + } + + @Override +- @Override + protected Brain makeBrain(Dynamic dynamic) { + return PiglinAi.makeBrain(this, this.brainProvider().makeBrain(dynamic)); + } + + @Override +- @Override + public Brain getBrain() { +- return super.getBrain(); ++ return (Brain) super.getBrain(); // CraftBukkit - Decompile error + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- InteractionResult interactionresult = super.mobInteract(player, interactionhand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ InteractionResult enuminteractionresult = super.mobInteract(player, hand); + +- if (interactionresult.consumesAction()) { +- return interactionresult; ++ if (enuminteractionresult.consumesAction()) { ++ return enuminteractionresult; + } else if (!this.level().isClientSide) { +- return PiglinAi.mobInteract(this, player, interactionhand); ++ return PiglinAi.mobInteract(this, player, hand); + } else { +- boolean flag = PiglinAi.canAdmire(this, player.getItemInHand(interactionhand)) && this.getArmPose() != PiglinArmPose.ADMIRING_ITEM; ++ boolean flag = PiglinAi.canAdmire(this, player.getItemInHand(hand)) && this.getArmPose() != EntityPiglinArmPose.ADMIRING_ITEM; + + return flag ? InteractionResult.SUCCESS : InteractionResult.PASS; + } + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- float f = super.getStandingEyeHeight(pose, entitydimensions); ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { ++ float f = super.getStandingEyeHeight(pose, size); + + return this.isBaby() ? f - 0.82F : f; + } + + @Override +- @Override +- public void setBaby(boolean flag) { +- this.getEntityData().set(Piglin.DATA_BABY_ID, flag); ++ public void setBaby(boolean childZombie) { ++ this.getEntityData().set(Piglin.DATA_BABY_ID, childZombie); + if (!this.level().isClientSide) { +- AttributeInstance attributeinstance = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); + +- attributeinstance.removeModifier(Piglin.SPEED_MODIFIER_BABY.getId()); +- if (flag) { +- attributeinstance.addTransientModifier(Piglin.SPEED_MODIFIER_BABY); ++ attributemodifiable.removeModifier(Piglin.SPEED_MODIFIER_BABY.getId()); ++ if (childZombie) { ++ attributemodifiable.addTransientModifier(Piglin.SPEED_MODIFIER_BABY); + } + } + + } + + @Override +- @Override + public boolean isBaby() { + return (Boolean) this.getEntityData().get(Piglin.DATA_BABY_ID); + } + +- private void setCannotHunt(boolean flag) { +- this.cannotHunt = flag; ++ private void setCannotHunt(boolean cannotHunt) { ++ this.cannotHunt = cannotHunt; + } + + @Override +- @Override + protected boolean canHunt() { + return !this.cannotHunt; + } + + @Override +- @Override + protected void customServerAiStep() { + this.level().getProfiler().push("piglinBrain"); + this.getBrain().tick((ServerLevel) this.level(), this); +@@ -302,17 +311,15 @@ + } + + @Override +- @Override + public int getExperienceReward() { + return this.xpReward; + } + + @Override +- @Override +- protected void finishConversion(ServerLevel serverlevel) { ++ protected void finishConversion(ServerLevel serverLevel) { + PiglinAi.cancelAdmiring(this); + this.inventory.removeAllItems().forEach(this::spawnAtLocation); +- super.finishConversion(serverlevel); ++ super.finishConversion(serverLevel); + } + + private ItemStack createSpawnWeapon() { +@@ -324,41 +331,37 @@ + } + + @Override +- @Override +- public void setChargingCrossbow(boolean flag) { +- this.entityData.set(Piglin.DATA_IS_CHARGING_CROSSBOW, flag); ++ public void setChargingCrossbow(boolean isCharging) { ++ this.entityData.set(Piglin.DATA_IS_CHARGING_CROSSBOW, isCharging); + } + + @Override +- @Override + public void onCrossbowAttackPerformed() { + this.noActionTime = 0; + } + + @Override +- @Override +- public PiglinArmPose getArmPose() { +- return this.isDancing() ? PiglinArmPose.DANCING : (PiglinAi.isLovedItem(this.getOffhandItem()) ? PiglinArmPose.ADMIRING_ITEM : (this.isAggressive() && this.isHoldingMeleeWeapon() ? PiglinArmPose.ATTACKING_WITH_MELEE_WEAPON : (this.isChargingCrossbow() ? PiglinArmPose.CROSSBOW_CHARGE : (this.isAggressive() && this.isHolding(Items.CROSSBOW) ? PiglinArmPose.CROSSBOW_HOLD : PiglinArmPose.DEFAULT)))); ++ public EntityPiglinArmPose getArmPose() { ++ return this.isDancing() ? EntityPiglinArmPose.DANCING : (PiglinAi.isLovedItem(this.getOffhandItem()) ? EntityPiglinArmPose.ADMIRING_ITEM : (this.isAggressive() && this.isHoldingMeleeWeapon() ? EntityPiglinArmPose.ATTACKING_WITH_MELEE_WEAPON : (this.isChargingCrossbow() ? EntityPiglinArmPose.CROSSBOW_CHARGE : (this.isAggressive() && this.isHolding(Items.CROSSBOW) ? EntityPiglinArmPose.CROSSBOW_HOLD : EntityPiglinArmPose.DEFAULT)))); + } + + public boolean isDancing() { + return (Boolean) this.entityData.get(Piglin.DATA_IS_DANCING); + } + +- public void setDancing(boolean flag) { +- this.entityData.set(Piglin.DATA_IS_DANCING, flag); ++ public void setDancing(boolean dancing) { ++ this.entityData.set(Piglin.DATA_IS_DANCING, dancing); + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- boolean flag = super.hurt(damagesource, f); ++ public boolean hurt(DamageSource source, float amount) { ++ boolean flag = super.hurt(source, amount); + + if (this.level().isClientSide) { + return false; + } else { +- if (flag && damagesource.getEntity() instanceof LivingEntity) { +- PiglinAi.wasHurtBy(this, (LivingEntity) damagesource.getEntity()); ++ if (flag && source.getEntity() instanceof LivingEntity) { ++ PiglinAi.wasHurtBy(this, (LivingEntity) source.getEntity()); + } + + return flag; +@@ -366,116 +369,104 @@ + } + + @Override +- @Override +- public void performRangedAttack(LivingEntity livingentity, float f) { ++ public void performRangedAttack(LivingEntity target, float distanceFactor) { + this.performCrossbowAttack(this, 1.6F); + } + + @Override +- @Override +- public void shootCrossbowProjectile(LivingEntity livingentity, ItemStack itemstack, Projectile projectile, float f) { +- this.shootCrossbowProjectile(this, livingentity, projectile, f, 1.6F); ++ public void shootCrossbowProjectile(LivingEntity target, ItemStack crossbowStack, Projectile projectile, float projectileAngle) { ++ this.shootCrossbowProjectile(this, target, projectile, projectileAngle, 1.6F); + } + + @Override +- @Override +- public boolean canFireProjectileWeapon(ProjectileWeaponItem projectileweaponitem) { +- return projectileweaponitem == Items.CROSSBOW; ++ public boolean canFireProjectileWeapon(ProjectileWeaponItem projectileWeapon) { ++ return projectileWeapon == Items.CROSSBOW; + } + +- protected void holdInMainHand(ItemStack itemstack) { +- this.setItemSlotAndDropWhenKilled(EquipmentSlot.MAINHAND, itemstack); ++ protected void holdInMainHand(ItemStack stack) { ++ this.setItemSlotAndDropWhenKilled(EquipmentSlot.MAINHAND, stack); + } + +- protected void holdInOffHand(ItemStack itemstack) { +- if (itemstack.is(PiglinAi.BARTERING_ITEM)) { +- this.setItemSlot(EquipmentSlot.OFFHAND, itemstack); ++ protected void holdInOffHand(ItemStack stack) { ++ if (stack.is(PiglinAi.BARTERING_ITEM) || allowedBarterItems.contains(stack.getItem())) { // CraftBukkit - Changes to accept custom payment items ++ this.setItemSlot(EquipmentSlot.OFFHAND, stack); + this.setGuaranteedDrop(EquipmentSlot.OFFHAND); + } else { +- this.setItemSlotAndDropWhenKilled(EquipmentSlot.OFFHAND, itemstack); ++ this.setItemSlotAndDropWhenKilled(EquipmentSlot.OFFHAND, stack); + } + + } + + @Override +- @Override +- public boolean wantsToPickUp(ItemStack itemstack) { +- return this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && this.canPickUpLoot() && PiglinAi.wantsToPickup(this, itemstack); ++ public boolean wantsToPickUp(ItemStack stack) { ++ return this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && this.canPickUpLoot() && PiglinAi.wantsToPickup(this, stack); + } + +- protected boolean canReplaceCurrentItem(ItemStack itemstack) { +- EquipmentSlot equipmentslot = Mob.getEquipmentSlotForItem(itemstack); +- ItemStack itemstack1 = this.getItemBySlot(equipmentslot); ++ protected boolean canReplaceCurrentItem(ItemStack candidate) { ++ EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(candidate); ++ ItemStack itemstack1 = this.getItemBySlot(enumitemslot); + +- return this.canReplaceCurrentItem(itemstack, itemstack1); ++ return this.canReplaceCurrentItem(candidate, itemstack1); + } + + @Override +- @Override +- protected boolean canReplaceCurrentItem(ItemStack itemstack, ItemStack itemstack1) { +- if (EnchantmentHelper.hasBindingCurse(itemstack1)) { ++ protected boolean canReplaceCurrentItem(ItemStack candidate, ItemStack existing) { ++ if (EnchantmentHelper.hasBindingCurse(existing)) { + return false; + } else { +- boolean flag = PiglinAi.isLovedItem(itemstack) || itemstack.is(Items.CROSSBOW); +- boolean flag1 = PiglinAi.isLovedItem(itemstack1) || itemstack1.is(Items.CROSSBOW); ++ boolean flag = PiglinAi.isLovedItem(candidate, this) || candidate.is(Items.CROSSBOW); // CraftBukkit ++ boolean flag1 = PiglinAi.isLovedItem(existing, this) || existing.is(Items.CROSSBOW); // CraftBukkit + +- return flag && !flag1 ? true : (!flag && flag1 ? false : (this.isAdult() && !itemstack.is(Items.CROSSBOW) && itemstack1.is(Items.CROSSBOW) ? false : super.canReplaceCurrentItem(itemstack, itemstack1))); ++ return flag && !flag1 ? true : (!flag && flag1 ? false : (this.isAdult() && !candidate.is(Items.CROSSBOW) && existing.is(Items.CROSSBOW) ? false : super.canReplaceCurrentItem(candidate, existing))); + } + } + + @Override +- @Override +- protected void pickUpItem(ItemEntity itementity) { +- this.onItemPickup(itementity); +- PiglinAi.pickUpItem(this, itementity); ++ protected void pickUpItem(ItemEntity itemEntity) { ++ this.onItemPickup(itemEntity); ++ PiglinAi.pickUpItem(this, itemEntity); + } + + @Override +- @Override +- public boolean startRiding(Entity entity, boolean flag) { ++ public boolean startRiding(Entity entity, boolean force) { + if (this.isBaby() && entity.getType() == EntityType.HOGLIN) { + entity = this.getTopPassenger(entity, 3); + } + +- return super.startRiding(entity, flag); ++ return super.startRiding(entity, force); + } + +- private Entity getTopPassenger(Entity entity, int i) { +- List list = entity.getPassengers(); ++ private Entity getTopPassenger(Entity vehicle, int maxPosition) { ++ List list = vehicle.getPassengers(); + +- return i != 1 && !list.isEmpty() ? this.getTopPassenger((Entity) list.get(0), i - 1) : entity; ++ return maxPosition != 1 && !list.isEmpty() ? this.getTopPassenger((Entity) list.get(0), maxPosition - 1) : vehicle; + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { +- return this.level().isClientSide ? null : (SoundEvent) PiglinAi.getSoundForCurrentActivity(this).orElse((Object) null); ++ return this.level().isClientSide ? null : (SoundEvent) PiglinAi.getSoundForCurrentActivity(this).orElse(null); // CraftBukkit - Decompile error + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.PIGLIN_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.PIGLIN_DEATH; + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.PIGLIN_STEP, 0.15F, 1.0F); + } + +- protected void playSoundEvent(SoundEvent soundevent) { +- this.playSound(soundevent, this.getSoundVolume(), this.getVoicePitch()); ++ protected void playSoundEvent(SoundEvent soundEvent) { ++ this.playSound(soundEvent, this.getSoundVolume(), this.getVoicePitch()); + } + + @Override +- @Override + protected void playConvertedSound() { + this.playSoundEvent(SoundEvents.PIGLIN_CONVERTED_TO_ZOMBIFIED); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/piglin/PiglinAi.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/piglin/PiglinAi.java.patch new file mode 100644 index 0000000000..800ab2730d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/piglin/PiglinAi.java.patch @@ -0,0 +1,821 @@ +--- a/net/minecraft/world/entity/monster/piglin/PiglinAi.java ++++ b/net/minecraft/world/entity/monster/piglin/PiglinAi.java +@@ -15,7 +15,7 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.util.TimeUtil; + import net.minecraft.util.valueproviders.UniformInt; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +@@ -73,6 +73,12 @@ + import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; + import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import java.util.stream.Collectors; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.entity.PiglinBarterEvent; ++// CraftBukkit end + + public class PiglinAi { + +@@ -129,8 +135,8 @@ + return brain; + } + +- protected static void initMemories(Piglin piglin, RandomSource randomsource) { +- int i = PiglinAi.TIME_BETWEEN_HUNTS.sample(randomsource); ++ protected static void initMemories(Piglin piglin, RandomSource random) { ++ int i = PiglinAi.TIME_BETWEEN_HUNTS.sample(random); + + piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.HUNTED_RECENTLY, true, (long) i); + } +@@ -144,14 +150,14 @@ + } + + private static void initFightActivity(Piglin piglin, Brain brain) { +- brain.addActivityAndRemoveMemoryWhenStopped(Activity.FIGHT, 10, ImmutableList.of(StopAttackingIfTargetInvalid.create((livingentity) -> { +- return !isNearestValidAttackTarget(piglin, livingentity); ++ brain.addActivityAndRemoveMemoryWhenStopped(Activity.FIGHT, 10, ImmutableList.of(StopAttackingIfTargetInvalid.create((entityliving) -> { ++ return !isNearestValidAttackTarget(piglin, entityliving); + }), BehaviorBuilder.triggerIf(PiglinAi::hasCrossbow, BackUpIfTooClose.create(5, 0.75F)), SetWalkTargetFromAttackTargetIfTargetOutOfReach.create(1.0F), MeleeAttack.create(20), new CrossbowAttack<>(), RememberIfHoglinWasKilled.create(), EraseMemoryIf.create(PiglinAi::isNearZombified, MemoryModuleType.ATTACK_TARGET)), MemoryModuleType.ATTACK_TARGET); + } + + private static void initCelebrateActivity(Brain brain) { +- brain.addActivityAndRemoveMemoryWhenStopped(Activity.CELEBRATE, 10, ImmutableList.of(avoidRepellent(), SetEntityLookTarget.create(PiglinAi::isPlayerHoldingLovedItem, 14.0F), StartAttacking.create(AbstractPiglin::isAdult, PiglinAi::findNearestValidAttackTarget), BehaviorBuilder.triggerIf((piglin) -> { +- return !piglin.isDancing(); ++ brain.addActivityAndRemoveMemoryWhenStopped(Activity.CELEBRATE, 10, ImmutableList.of(avoidRepellent(), SetEntityLookTarget.create(PiglinAi::isPlayerHoldingLovedItem, 14.0F), StartAttacking.create(AbstractPiglin::isAdult, PiglinAi::findNearestValidAttackTarget), BehaviorBuilder.triggerIf((entitypiglin) -> { ++ return !entitypiglin.isDancing(); + }, GoToTargetLocation.create(MemoryModuleType.CELEBRATE_LOCATION, 2, 1.0F)), BehaviorBuilder.triggerIf(Piglin::isDancing, GoToTargetLocation.create(MemoryModuleType.CELEBRATE_LOCATION, 4, 0.6F)), new RunOne<>(ImmutableList.of(Pair.of(SetEntityLookTarget.create(EntityType.PIGLIN, 8.0F), 1), Pair.of(RandomStroll.stroll(0.6F, 2, 1), 1), Pair.of(new DoNothing(10, 20), 1)))), MemoryModuleType.CELEBRATE_LOCATION); + } + +@@ -164,7 +170,8 @@ + } + + private static void initRideHoglinActivity(Brain brain) { +- brain.addActivityAndRemoveMemoryWhenStopped(Activity.RIDE, 10, ImmutableList.of(Mount.create(0.8F), SetEntityLookTarget.create(PiglinAi::isPlayerHoldingLovedItem, 8.0F), BehaviorBuilder.sequence(BehaviorBuilder.triggerIf(Entity::isPassenger), TriggerGate.triggerOneShuffled(ImmutableList.builder().addAll(createLookBehaviors()).add(Pair.of(BehaviorBuilder.triggerIf((piglin) -> { ++ // CraftBukkit - decompile error ++ brain.addActivityAndRemoveMemoryWhenStopped(Activity.RIDE, 10, ImmutableList.of(Mount.create(0.8F), SetEntityLookTarget.create(PiglinAi::isPlayerHoldingLovedItem, 8.0F), BehaviorBuilder.sequence(BehaviorBuilder.triggerIf(Entity::isPassenger), TriggerGate.triggerOneShuffled(ImmutableList., Integer>>builder().addAll(createLookBehaviors()).add(Pair.of(BehaviorBuilder.triggerIf((entitypiglin) -> { + return true; + }), 1)).build())), DismountOrSkipMounting.create(8, PiglinAi::wantsToStopRiding)), MemoryModuleType.RIDE_TARGET); + } +@@ -174,7 +181,7 @@ + } + + private static RunOne createIdleLookBehaviors() { +- return new RunOne<>(ImmutableList.builder().addAll(createLookBehaviors()).add(Pair.of(new DoNothing(30, 60), 1)).build()); ++ return new RunOne<>(ImmutableList., Integer>>builder().addAll(createLookBehaviors()).add(Pair.of(new DoNothing(30, 60), 1)).build()); // CraftBukkit - decompile error + } + + private static RunOne createIdleMovementBehaviors() { +@@ -194,62 +201,66 @@ + } + + protected static void updateActivity(Piglin piglin) { +- Brain brain = piglin.getBrain(); +- Activity activity = (Activity) brain.getActiveNonCoreActivity().orElse((Object) null); ++ Brain behaviorcontroller = piglin.getBrain(); ++ Activity activity = (Activity) behaviorcontroller.getActiveNonCoreActivity().orElse(null); // CraftBukkit - decompile error + +- brain.setActiveActivityToFirstValid(ImmutableList.of(Activity.ADMIRE_ITEM, Activity.FIGHT, Activity.AVOID, Activity.CELEBRATE, Activity.RIDE, Activity.IDLE)); +- Activity activity1 = (Activity) brain.getActiveNonCoreActivity().orElse((Object) null); ++ behaviorcontroller.setActiveActivityToFirstValid(ImmutableList.of(Activity.ADMIRE_ITEM, Activity.FIGHT, Activity.AVOID, Activity.CELEBRATE, Activity.RIDE, Activity.IDLE)); ++ Activity activity1 = (Activity) behaviorcontroller.getActiveNonCoreActivity().orElse(null); // CraftBukkit - decompile error + + if (activity != activity1) { +- Optional optional = getSoundForCurrentActivity(piglin); ++ Optional optional = getSoundForCurrentActivity(piglin); // CraftBukkit - decompile error + + Objects.requireNonNull(piglin); + optional.ifPresent(piglin::playSoundEvent); + } + +- piglin.setAggressive(brain.hasMemoryValue(MemoryModuleType.ATTACK_TARGET)); +- if (!brain.hasMemoryValue(MemoryModuleType.RIDE_TARGET) && isBabyRidingBaby(piglin)) { ++ piglin.setAggressive(behaviorcontroller.hasMemoryValue(MemoryModuleType.ATTACK_TARGET)); ++ if (!behaviorcontroller.hasMemoryValue(MemoryModuleType.RIDE_TARGET) && isBabyRidingBaby(piglin)) { + piglin.stopRiding(); + } + +- if (!brain.hasMemoryValue(MemoryModuleType.CELEBRATE_LOCATION)) { +- brain.eraseMemory(MemoryModuleType.DANCING); ++ if (!behaviorcontroller.hasMemoryValue(MemoryModuleType.CELEBRATE_LOCATION)) { ++ behaviorcontroller.eraseMemory(MemoryModuleType.DANCING); + } + +- piglin.setDancing(brain.hasMemoryValue(MemoryModuleType.DANCING)); ++ piglin.setDancing(behaviorcontroller.hasMemoryValue(MemoryModuleType.DANCING)); + } + +- private static boolean isBabyRidingBaby(Piglin piglin) { +- if (!piglin.isBaby()) { ++ private static boolean isBabyRidingBaby(Piglin passenger) { ++ if (!passenger.isBaby()) { + return false; + } else { +- Entity entity = piglin.getVehicle(); ++ Entity entity = passenger.getVehicle(); + + return entity instanceof Piglin && ((Piglin) entity).isBaby() || entity instanceof Hoglin && ((Hoglin) entity).isBaby(); + } + } + +- protected static void pickUpItem(Piglin piglin, ItemEntity itementity) { ++ protected static void pickUpItem(Piglin piglin, ItemEntity itemEntity) { + stopWalking(piglin); + ItemStack itemstack; + +- if (itementity.getItem().is(Items.GOLD_NUGGET)) { +- piglin.take(itementity, itementity.getItem().getCount()); +- itemstack = itementity.getItem(); +- itementity.discard(); ++ // CraftBukkit start ++ if (itemEntity.getItem().is(Items.GOLD_NUGGET) && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(piglin, itemEntity, 0, false).isCancelled()) { ++ piglin.take(itemEntity, itemEntity.getItem().getCount()); ++ itemstack = itemEntity.getItem(); ++ itemEntity.discard(); ++ } else if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(piglin, itemEntity, itemEntity.getItem().getCount() - 1, false).isCancelled()) { ++ piglin.take(itemEntity, 1); ++ itemstack = removeOneItemFromItemEntity(itemEntity); + } else { +- piglin.take(itementity, 1); +- itemstack = removeOneItemFromItemEntity(itementity); ++ return; + } ++ // CraftBukkit end + +- if (isLovedItem(itemstack)) { ++ if (isLovedItem(itemstack, piglin)) { // CraftBukkit - Changes to allow for custom payment in bartering + piglin.getBrain().eraseMemory(MemoryModuleType.TIME_TRYING_TO_REACH_ADMIRE_ITEM); + holdInOffhand(piglin, itemstack); + admireGoldItem(piglin); + } else if (isFood(itemstack) && !hasEatenRecently(piglin)) { + eat(piglin); + } else { +- boolean flag = !piglin.equipItemIfPossible(itemstack).equals(ItemStack.EMPTY); ++ boolean flag = !piglin.equipItemIfPossible(itemstack, itemEntity).equals(ItemStack.EMPTY); // CraftBukkit + + if (!flag) { + putInInventory(piglin, itemstack); +@@ -257,37 +268,42 @@ + } + } + +- private static void holdInOffhand(Piglin piglin, ItemStack itemstack) { ++ private static void holdInOffhand(Piglin piglin, ItemStack stack) { + if (isHoldingItemInOffHand(piglin)) { +- piglin.spawnAtLocation(piglin.getItemInHand(InteractionHand.OFF_HAND)); ++ piglin.spawnAtLocation(piglin.getItemInHand(EnumHand.OFF_HAND)); + } + +- piglin.holdInOffHand(itemstack); ++ piglin.holdInOffHand(stack); + } + +- private static ItemStack removeOneItemFromItemEntity(ItemEntity itementity) { +- ItemStack itemstack = itementity.getItem(); ++ private static ItemStack removeOneItemFromItemEntity(ItemEntity itemEntity) { ++ ItemStack itemstack = itemEntity.getItem(); + ItemStack itemstack1 = itemstack.split(1); + + if (itemstack.isEmpty()) { +- itementity.discard(); ++ itemEntity.discard(); + } else { +- itementity.setItem(itemstack); ++ itemEntity.setItem(itemstack); + } + + return itemstack1; + } + +- protected static void stopHoldingOffHandItem(Piglin piglin, boolean flag) { +- ItemStack itemstack = piglin.getItemInHand(InteractionHand.OFF_HAND); ++ protected static void stopHoldingOffHandItem(Piglin piglin, boolean shouldBarter) { ++ ItemStack itemstack = piglin.getItemInHand(EnumHand.OFF_HAND); + +- piglin.setItemInHand(InteractionHand.OFF_HAND, ItemStack.EMPTY); ++ piglin.setItemInHand(EnumHand.OFF_HAND, ItemStack.EMPTY); + boolean flag1; + + if (piglin.isAdult()) { +- flag1 = isBarterCurrency(itemstack); +- if (flag && flag1) { +- throwItems(piglin, getBarterResponseItems(piglin)); ++ flag1 = isBarterCurrency(itemstack, piglin); // CraftBukkit - Changes to allow custom payment for bartering ++ if (shouldBarter && flag1) { ++ // CraftBukkit start ++ PiglinBarterEvent event = CraftEventFactory.callPiglinBarterEvent(piglin, getBarterResponseItems(piglin), itemstack); ++ if (!event.isCancelled()) { ++ throwItems(piglin, event.getOutcome().stream().map(CraftItemStack::asNMSCopy).collect(Collectors.toList())); ++ } ++ // CraftBukkit end + } else if (!flag1) { + boolean flag2 = !piglin.equipItemIfPossible(itemstack).isEmpty(); + +@@ -300,7 +316,7 @@ + if (!flag1) { + ItemStack itemstack1 = piglin.getMainHandItem(); + +- if (isLovedItem(itemstack1)) { ++ if (isLovedItem(itemstack1, piglin)) { // CraftBukkit - Changes to allow for custom payment in bartering + putInInventory(piglin, itemstack1); + } else { + throwItems(piglin, Collections.singletonList(itemstack1)); +@@ -315,45 +331,45 @@ + protected static void cancelAdmiring(Piglin piglin) { + if (isAdmiringItem(piglin) && !piglin.getOffhandItem().isEmpty()) { + piglin.spawnAtLocation(piglin.getOffhandItem()); +- piglin.setItemInHand(InteractionHand.OFF_HAND, ItemStack.EMPTY); ++ piglin.setItemInHand(EnumHand.OFF_HAND, ItemStack.EMPTY); + } + + } + +- private static void putInInventory(Piglin piglin, ItemStack itemstack) { +- ItemStack itemstack1 = piglin.addToInventory(itemstack); ++ private static void putInInventory(Piglin piglin, ItemStack stack) { ++ ItemStack itemstack1 = piglin.addToInventory(stack); + + throwItemsTowardRandomPos(piglin, Collections.singletonList(itemstack1)); + } + +- private static void throwItems(Piglin piglin, List list) { +- Optional optional = piglin.getBrain().getMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER); ++ private static void throwItems(Piglin pilgin, List stacks) { ++ Optional optional = pilgin.getBrain().getMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER); + + if (optional.isPresent()) { +- throwItemsTowardPlayer(piglin, (Player) optional.get(), list); ++ throwItemsTowardPlayer(pilgin, (Player) optional.get(), stacks); + } else { +- throwItemsTowardRandomPos(piglin, list); ++ throwItemsTowardRandomPos(pilgin, stacks); + } + + } + +- private static void throwItemsTowardRandomPos(Piglin piglin, List list) { +- throwItemsTowardPos(piglin, list, getRandomNearbyPos(piglin)); ++ private static void throwItemsTowardRandomPos(Piglin piglin, List stacks) { ++ throwItemsTowardPos(piglin, stacks, getRandomNearbyPos(piglin)); + } + +- private static void throwItemsTowardPlayer(Piglin piglin, Player player, List list) { +- throwItemsTowardPos(piglin, list, player.position()); ++ private static void throwItemsTowardPlayer(Piglin piglin, Player player, List stacks) { ++ throwItemsTowardPos(piglin, stacks, player.position()); + } + +- private static void throwItemsTowardPos(Piglin piglin, List list, Vec3 vec3) { +- if (!list.isEmpty()) { +- piglin.swing(InteractionHand.OFF_HAND); +- Iterator iterator = list.iterator(); ++ private static void throwItemsTowardPos(Piglin piglin, List stacks, Vec3 pos) { ++ if (!stacks.isEmpty()) { ++ piglin.swing(EnumHand.OFF_HAND); ++ Iterator iterator = stacks.iterator(); + + while (iterator.hasNext()) { + ItemStack itemstack = (ItemStack) iterator.next(); + +- BehaviorUtils.throwItem(piglin, itemstack, vec3.add(0.0D, 1.0D, 0.0D)); ++ BehaviorUtils.throwItem(piglin, itemstack, pos.add(0.0D, 1.0D, 0.0D)); + } + } + +@@ -366,60 +382,66 @@ + return list; + } + +- private static boolean wantsToDance(LivingEntity livingentity, LivingEntity livingentity1) { +- return livingentity1.getType() != EntityType.HOGLIN ? false : RandomSource.create(livingentity.level().getGameTime()).nextFloat() < 0.1F; ++ private static boolean wantsToDance(LivingEntity piglin, LivingEntity target) { ++ return target.getType() != EntityType.HOGLIN ? false : RandomSource.create(piglin.level().getGameTime()).nextFloat() < 0.1F; + } + +- protected static boolean wantsToPickup(Piglin piglin, ItemStack itemstack) { +- if (piglin.isBaby() && itemstack.is(ItemTags.IGNORED_BY_PIGLIN_BABIES)) { ++ protected static boolean wantsToPickup(Piglin piglin, ItemStack stack) { ++ if (piglin.isBaby() && stack.is(ItemTags.IGNORED_BY_PIGLIN_BABIES)) { + return false; +- } else if (itemstack.is(ItemTags.PIGLIN_REPELLENTS)) { ++ } else if (stack.is(ItemTags.PIGLIN_REPELLENTS)) { + return false; + } else if (isAdmiringDisabled(piglin) && piglin.getBrain().hasMemoryValue(MemoryModuleType.ATTACK_TARGET)) { + return false; +- } else if (isBarterCurrency(itemstack)) { ++ } else if (isBarterCurrency(stack, piglin)) { // CraftBukkit + return isNotHoldingLovedItemInOffHand(piglin); + } else { +- boolean flag = piglin.canAddToInventory(itemstack); ++ boolean flag = piglin.canAddToInventory(stack); + +- return itemstack.is(Items.GOLD_NUGGET) ? flag : (isFood(itemstack) ? !hasEatenRecently(piglin) && flag : (!isLovedItem(itemstack) ? piglin.canReplaceCurrentItem(itemstack) : isNotHoldingLovedItemInOffHand(piglin) && flag)); ++ return stack.is(Items.GOLD_NUGGET) ? flag : (isFood(stack) ? !hasEatenRecently(piglin) && flag : (!isLovedItem(stack) ? piglin.canReplaceCurrentItem(stack) : isNotHoldingLovedItemInOffHand(piglin) && flag)); + } + } + +- protected static boolean isLovedItem(ItemStack itemstack) { +- return itemstack.is(ItemTags.PIGLIN_LOVED); ++ // CraftBukkit start - Added method to allow checking for custom payment items ++ protected static boolean isLovedItem(ItemStack itemstack, Piglin piglin) { ++ return isLovedItem(itemstack) || (piglin.interestItems.contains(itemstack.getItem()) || piglin.allowedBarterItems.contains(itemstack.getItem())); + } ++ // CraftBukkit end + +- private static boolean wantsToStopRiding(Piglin piglin, Entity entity) { +- if (!(entity instanceof Mob)) { ++ protected static boolean isLovedItem(ItemStack item) { ++ return item.is(ItemTags.PIGLIN_LOVED); ++ } ++ ++ private static boolean wantsToStopRiding(Piglin piglin, Entity vehicle) { ++ if (!(vehicle instanceof Mob)) { + return false; + } else { +- Mob mob = (Mob) entity; ++ Mob entityinsentient = (Mob) vehicle; + +- return !mob.isBaby() || !mob.isAlive() || wasHurtRecently(piglin) || wasHurtRecently(mob) || mob instanceof Piglin && mob.getVehicle() == null; ++ return !entityinsentient.isBaby() || !entityinsentient.isAlive() || wasHurtRecently(piglin) || wasHurtRecently(entityinsentient) || entityinsentient instanceof Piglin && entityinsentient.getVehicle() == null; + } + } + +- private static boolean isNearestValidAttackTarget(Piglin piglin, LivingEntity livingentity) { +- return findNearestValidAttackTarget(piglin).filter((livingentity1) -> { +- return livingentity1 == livingentity; ++ private static boolean isNearestValidAttackTarget(Piglin piglin, LivingEntity target) { ++ return findNearestValidAttackTarget(piglin).filter((entityliving1) -> { ++ return entityliving1 == target; + }).isPresent(); + } + + private static boolean isNearZombified(Piglin piglin) { +- Brain brain = piglin.getBrain(); ++ Brain behaviorcontroller = piglin.getBrain(); + +- if (brain.hasMemoryValue(MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED)) { +- LivingEntity livingentity = (LivingEntity) brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED).get(); ++ if (behaviorcontroller.hasMemoryValue(MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED)) { ++ LivingEntity entityliving = (LivingEntity) behaviorcontroller.getMemory(MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED).get(); + +- return piglin.closerThan(livingentity, 6.0D); ++ return piglin.closerThan(entityliving, 6.0D); + } else { + return false; + } + } + + private static Optional findNearestValidAttackTarget(Piglin piglin) { +- Brain brain = piglin.getBrain(); ++ Brain behaviorcontroller = piglin.getBrain(); + + if (isNearZombified(piglin)) { + return Optional.empty(); +@@ -431,18 +453,18 @@ + } else { + Optional optional1; + +- if (brain.hasMemoryValue(MemoryModuleType.UNIVERSAL_ANGER)) { +- optional1 = brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER); ++ if (behaviorcontroller.hasMemoryValue(MemoryModuleType.UNIVERSAL_ANGER)) { ++ optional1 = behaviorcontroller.getMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER); + if (optional1.isPresent()) { + return optional1; + } + } + +- optional1 = brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_NEMESIS); ++ optional1 = behaviorcontroller.getMemory(MemoryModuleType.NEAREST_VISIBLE_NEMESIS); + if (optional1.isPresent()) { + return optional1; + } else { +- Optional optional2 = brain.getMemory(MemoryModuleType.NEAREST_TARGETABLE_PLAYER_NOT_WEARING_GOLD); ++ Optional optional2 = behaviorcontroller.getMemory(MemoryModuleType.NEAREST_TARGETABLE_PLAYER_NOT_WEARING_GOLD); + + return optional2.isPresent() && Sensor.isEntityAttackable(piglin, (LivingEntity) optional2.get()) ? optional2 : Optional.empty(); + } +@@ -450,23 +472,23 @@ + } + } + +- public static void angerNearbyPiglins(Player player, boolean flag) { ++ public static void angerNearbyPiglins(Player player, boolean angerOnlyIfCanSee) { + List list = player.level().getEntitiesOfClass(Piglin.class, player.getBoundingBox().inflate(16.0D)); + +- list.stream().filter(PiglinAi::isIdle).filter((piglin) -> { +- return !flag || BehaviorUtils.canSee(piglin, player); +- }).forEach((piglin) -> { +- if (piglin.level().getGameRules().getBoolean(GameRules.RULE_UNIVERSAL_ANGER)) { +- setAngerTargetToNearestTargetablePlayerIfFound(piglin, player); ++ list.stream().filter(PiglinAi::isIdle).filter((entitypiglin) -> { ++ return !angerOnlyIfCanSee || BehaviorUtils.canSee(entitypiglin, player); ++ }).forEach((entitypiglin) -> { ++ if (entitypiglin.level().getGameRules().getBoolean(GameRules.RULE_UNIVERSAL_ANGER)) { ++ setAngerTargetToNearestTargetablePlayerIfFound(entitypiglin, player); + } else { +- setAngerTarget(piglin, player); ++ setAngerTarget(entitypiglin, player); + } + + }); + } + +- public static InteractionResult mobInteract(Piglin piglin, Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public static InteractionResult mobInteract(Piglin piglin, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (canAdmire(piglin, itemstack)) { + ItemStack itemstack1 = itemstack.split(1); +@@ -480,56 +502,56 @@ + } + } + +- protected static boolean canAdmire(Piglin piglin, ItemStack itemstack) { +- return !isAdmiringDisabled(piglin) && !isAdmiringItem(piglin) && piglin.isAdult() && isBarterCurrency(itemstack); ++ protected static boolean canAdmire(Piglin piglin, ItemStack stack) { ++ return !isAdmiringDisabled(piglin) && !isAdmiringItem(piglin) && piglin.isAdult() && isBarterCurrency(stack, piglin); // CraftBukkit + } + +- protected static void wasHurtBy(Piglin piglin, LivingEntity livingentity) { +- if (!(livingentity instanceof Piglin)) { ++ protected static void wasHurtBy(Piglin piglin, LivingEntity target) { ++ if (!(target instanceof Piglin)) { + if (isHoldingItemInOffHand(piglin)) { + stopHoldingOffHandItem(piglin, false); + } + +- Brain brain = piglin.getBrain(); ++ Brain behaviorcontroller = piglin.getBrain(); + +- brain.eraseMemory(MemoryModuleType.CELEBRATE_LOCATION); +- brain.eraseMemory(MemoryModuleType.DANCING); +- brain.eraseMemory(MemoryModuleType.ADMIRING_ITEM); +- if (livingentity instanceof Player) { +- brain.setMemoryWithExpiry(MemoryModuleType.ADMIRING_DISABLED, true, 400L); ++ behaviorcontroller.eraseMemory(MemoryModuleType.CELEBRATE_LOCATION); ++ behaviorcontroller.eraseMemory(MemoryModuleType.DANCING); ++ behaviorcontroller.eraseMemory(MemoryModuleType.ADMIRING_ITEM); ++ if (target instanceof Player) { ++ behaviorcontroller.setMemoryWithExpiry(MemoryModuleType.ADMIRING_DISABLED, true, 400L); + } + +- getAvoidTarget(piglin).ifPresent((livingentity1) -> { +- if (livingentity1.getType() != livingentity.getType()) { +- brain.eraseMemory(MemoryModuleType.AVOID_TARGET); ++ getAvoidTarget(piglin).ifPresent((entityliving1) -> { ++ if (entityliving1.getType() != target.getType()) { ++ behaviorcontroller.eraseMemory(MemoryModuleType.AVOID_TARGET); + } + + }); + if (piglin.isBaby()) { +- brain.setMemoryWithExpiry(MemoryModuleType.AVOID_TARGET, livingentity, 100L); +- if (Sensor.isEntityAttackableIgnoringLineOfSight(piglin, livingentity)) { +- broadcastAngerTarget(piglin, livingentity); ++ behaviorcontroller.setMemoryWithExpiry(MemoryModuleType.AVOID_TARGET, target, 100L); ++ if (Sensor.isEntityAttackableIgnoringLineOfSight(piglin, target)) { ++ broadcastAngerTarget(piglin, target); + } + +- } else if (livingentity.getType() == EntityType.HOGLIN && hoglinsOutnumberPiglins(piglin)) { +- setAvoidTargetAndDontHuntForAWhile(piglin, livingentity); +- broadcastRetreat(piglin, livingentity); ++ } else if (target.getType() == EntityType.HOGLIN && hoglinsOutnumberPiglins(piglin)) { ++ setAvoidTargetAndDontHuntForAWhile(piglin, target); ++ broadcastRetreat(piglin, target); + } else { +- maybeRetaliate(piglin, livingentity); ++ maybeRetaliate(piglin, target); + } + } + } + +- protected static void maybeRetaliate(AbstractPiglin abstractpiglin, LivingEntity livingentity) { +- if (!abstractpiglin.getBrain().isActive(Activity.AVOID)) { +- if (Sensor.isEntityAttackableIgnoringLineOfSight(abstractpiglin, livingentity)) { +- if (!BehaviorUtils.isOtherTargetMuchFurtherAwayThanCurrentAttackTarget(abstractpiglin, livingentity, 4.0D)) { +- if (livingentity.getType() == EntityType.PLAYER && abstractpiglin.level().getGameRules().getBoolean(GameRules.RULE_UNIVERSAL_ANGER)) { +- setAngerTargetToNearestTargetablePlayerIfFound(abstractpiglin, livingentity); +- broadcastUniversalAnger(abstractpiglin); ++ protected static void maybeRetaliate(AbstractPiglin piglin, LivingEntity target) { ++ if (!piglin.getBrain().isActive(Activity.AVOID)) { ++ if (Sensor.isEntityAttackableIgnoringLineOfSight(piglin, target)) { ++ if (!BehaviorUtils.isOtherTargetMuchFurtherAwayThanCurrentAttackTarget(piglin, target, 4.0D)) { ++ if (target.getType() == EntityType.PLAYER && piglin.level().getGameRules().getBoolean(GameRules.RULE_UNIVERSAL_ANGER)) { ++ setAngerTargetToNearestTargetablePlayerIfFound(piglin, target); ++ broadcastUniversalAnger(piglin); + } else { +- setAngerTarget(abstractpiglin, livingentity); +- broadcastAngerTarget(abstractpiglin, livingentity); ++ setAngerTarget(piglin, target); ++ broadcastAngerTarget(piglin, target); + } + + } +@@ -548,21 +570,21 @@ + } + + private static boolean isNearAvoidTarget(Piglin piglin) { +- Brain brain = piglin.getBrain(); ++ Brain behaviorcontroller = piglin.getBrain(); + +- return !brain.hasMemoryValue(MemoryModuleType.AVOID_TARGET) ? false : ((LivingEntity) brain.getMemory(MemoryModuleType.AVOID_TARGET).get()).closerThan(piglin, 12.0D); ++ return !behaviorcontroller.hasMemoryValue(MemoryModuleType.AVOID_TARGET) ? false : ((LivingEntity) behaviorcontroller.getMemory(MemoryModuleType.AVOID_TARGET).get()).closerThan(piglin, 12.0D); + } + + protected static List getVisibleAdultPiglins(Piglin piglin) { + return (List) piglin.getBrain().getMemory(MemoryModuleType.NEAREST_VISIBLE_ADULT_PIGLINS).orElse(ImmutableList.of()); + } + +- private static List getAdultPiglins(AbstractPiglin abstractpiglin) { +- return (List) abstractpiglin.getBrain().getMemory(MemoryModuleType.NEARBY_ADULT_PIGLINS).orElse(ImmutableList.of()); ++ private static List getAdultPiglins(AbstractPiglin piglin) { ++ return (List) piglin.getBrain().getMemory(MemoryModuleType.NEARBY_ADULT_PIGLINS).orElse(ImmutableList.of()); + } + +- public static boolean isWearingGold(LivingEntity livingentity) { +- Iterable iterable = livingentity.getArmorSlots(); ++ public static boolean isWearingGold(LivingEntity livingEntity) { ++ Iterable iterable = livingEntity.getArmorSlots(); + Iterator iterator = iterable.iterator(); + + Item item; +@@ -586,102 +608,102 @@ + } + + private static BehaviorControl babySometimesRideBabyHoglin() { +- SetEntityLookTargetSometimes.Ticker setentitylooktargetsometimes_ticker = new SetEntityLookTargetSometimes.Ticker(PiglinAi.RIDE_START_INTERVAL); ++ SetEntityLookTargetSometimes.Ticker setentitylooktargetsometimes_a = new SetEntityLookTargetSometimes.Ticker(PiglinAi.RIDE_START_INTERVAL); + +- return CopyMemoryWithExpiry.create((livingentity) -> { +- return livingentity.isBaby() && setentitylooktargetsometimes_ticker.tickDownAndCheck(livingentity.level().random); ++ return CopyMemoryWithExpiry.create((entityliving) -> { ++ return entityliving.isBaby() && setentitylooktargetsometimes_a.tickDownAndCheck(entityliving.level().random); + }, MemoryModuleType.NEAREST_VISIBLE_BABY_HOGLIN, MemoryModuleType.RIDE_TARGET, PiglinAi.RIDE_DURATION); + } + +- protected static void broadcastAngerTarget(AbstractPiglin abstractpiglin, LivingEntity livingentity) { +- getAdultPiglins(abstractpiglin).forEach((abstractpiglin1) -> { +- if (livingentity.getType() != EntityType.HOGLIN || abstractpiglin1.canHunt() && ((Hoglin) livingentity).canBeHunted()) { +- setAngerTargetIfCloserThanCurrent(abstractpiglin1, livingentity); ++ protected static void broadcastAngerTarget(AbstractPiglin piglin, LivingEntity target) { ++ getAdultPiglins(piglin).forEach((entitypiglinabstract1) -> { ++ if (target.getType() != EntityType.HOGLIN || entitypiglinabstract1.canHunt() && ((Hoglin) target).canBeHunted()) { ++ setAngerTargetIfCloserThanCurrent(entitypiglinabstract1, target); + } + }); + } + +- protected static void broadcastUniversalAnger(AbstractPiglin abstractpiglin) { +- getAdultPiglins(abstractpiglin).forEach((abstractpiglin1) -> { +- getNearestVisibleTargetablePlayer(abstractpiglin1).ifPresent((player) -> { +- setAngerTarget(abstractpiglin1, player); ++ protected static void broadcastUniversalAnger(AbstractPiglin piglin) { ++ getAdultPiglins(piglin).forEach((entitypiglinabstract1) -> { ++ getNearestVisibleTargetablePlayer(entitypiglinabstract1).ifPresent((entityhuman) -> { ++ setAngerTarget(entitypiglinabstract1, entityhuman); + }); + }); + } + +- protected static void setAngerTarget(AbstractPiglin abstractpiglin, LivingEntity livingentity) { +- if (Sensor.isEntityAttackableIgnoringLineOfSight(abstractpiglin, livingentity)) { +- abstractpiglin.getBrain().eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE); +- abstractpiglin.getBrain().setMemoryWithExpiry(MemoryModuleType.ANGRY_AT, livingentity.getUUID(), 600L); +- if (livingentity.getType() == EntityType.HOGLIN && abstractpiglin.canHunt()) { +- dontKillAnyMoreHoglinsForAWhile(abstractpiglin); ++ protected static void setAngerTarget(AbstractPiglin piglin, LivingEntity target) { ++ if (Sensor.isEntityAttackableIgnoringLineOfSight(piglin, target)) { ++ piglin.getBrain().eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE); ++ piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.ANGRY_AT, target.getUUID(), 600L); ++ if (target.getType() == EntityType.HOGLIN && piglin.canHunt()) { ++ dontKillAnyMoreHoglinsForAWhile(piglin); + } + +- if (livingentity.getType() == EntityType.PLAYER && abstractpiglin.level().getGameRules().getBoolean(GameRules.RULE_UNIVERSAL_ANGER)) { +- abstractpiglin.getBrain().setMemoryWithExpiry(MemoryModuleType.UNIVERSAL_ANGER, true, 600L); ++ if (target.getType() == EntityType.PLAYER && piglin.level().getGameRules().getBoolean(GameRules.RULE_UNIVERSAL_ANGER)) { ++ piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.UNIVERSAL_ANGER, true, 600L); + } + + } + } + +- private static void setAngerTargetToNearestTargetablePlayerIfFound(AbstractPiglin abstractpiglin, LivingEntity livingentity) { +- Optional optional = getNearestVisibleTargetablePlayer(abstractpiglin); ++ private static void setAngerTargetToNearestTargetablePlayerIfFound(AbstractPiglin piglin, LivingEntity currentTarget) { ++ Optional optional = getNearestVisibleTargetablePlayer(piglin); + + if (optional.isPresent()) { +- setAngerTarget(abstractpiglin, (LivingEntity) optional.get()); ++ setAngerTarget(piglin, (LivingEntity) optional.get()); + } else { +- setAngerTarget(abstractpiglin, livingentity); ++ setAngerTarget(piglin, currentTarget); + } + + } + +- private static void setAngerTargetIfCloserThanCurrent(AbstractPiglin abstractpiglin, LivingEntity livingentity) { +- Optional optional = getAngerTarget(abstractpiglin); +- LivingEntity livingentity1 = BehaviorUtils.getNearestTarget(abstractpiglin, optional, livingentity); ++ private static void setAngerTargetIfCloserThanCurrent(AbstractPiglin piglin, LivingEntity currentTarget) { ++ Optional optional = getAngerTarget(piglin); ++ LivingEntity entityliving1 = BehaviorUtils.getNearestTarget(piglin, optional, currentTarget); + +- if (!optional.isPresent() || optional.get() != livingentity1) { +- setAngerTarget(abstractpiglin, livingentity1); ++ if (!optional.isPresent() || optional.get() != entityliving1) { ++ setAngerTarget(piglin, entityliving1); + } + } + +- private static Optional getAngerTarget(AbstractPiglin abstractpiglin) { +- return BehaviorUtils.getLivingEntityFromUUIDMemory(abstractpiglin, MemoryModuleType.ANGRY_AT); ++ private static Optional getAngerTarget(AbstractPiglin piglin) { ++ return BehaviorUtils.getLivingEntityFromUUIDMemory(piglin, MemoryModuleType.ANGRY_AT); + } + + public static Optional getAvoidTarget(Piglin piglin) { + return piglin.getBrain().hasMemoryValue(MemoryModuleType.AVOID_TARGET) ? piglin.getBrain().getMemory(MemoryModuleType.AVOID_TARGET) : Optional.empty(); + } + +- public static Optional getNearestVisibleTargetablePlayer(AbstractPiglin abstractpiglin) { +- return abstractpiglin.getBrain().hasMemoryValue(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER) ? abstractpiglin.getBrain().getMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER) : Optional.empty(); ++ public static Optional getNearestVisibleTargetablePlayer(AbstractPiglin piglin) { ++ return piglin.getBrain().hasMemoryValue(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER) ? piglin.getBrain().getMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER) : Optional.empty(); + } + +- private static void broadcastRetreat(Piglin piglin, LivingEntity livingentity) { +- getVisibleAdultPiglins(piglin).stream().filter((abstractpiglin) -> { +- return abstractpiglin instanceof Piglin; +- }).forEach((abstractpiglin) -> { +- retreatFromNearestTarget((Piglin) abstractpiglin, livingentity); ++ private static void broadcastRetreat(Piglin piglin, LivingEntity target) { ++ getVisibleAdultPiglins(piglin).stream().filter((entitypiglinabstract) -> { ++ return entitypiglinabstract instanceof Piglin; ++ }).forEach((entitypiglinabstract) -> { ++ retreatFromNearestTarget((Piglin) entitypiglinabstract, target); + }); + } + +- private static void retreatFromNearestTarget(Piglin piglin, LivingEntity livingentity) { +- Brain brain = piglin.getBrain(); +- LivingEntity livingentity1 = BehaviorUtils.getNearestTarget(piglin, brain.getMemory(MemoryModuleType.AVOID_TARGET), livingentity); ++ private static void retreatFromNearestTarget(Piglin piglin, LivingEntity target) { ++ Brain behaviorcontroller = piglin.getBrain(); ++ LivingEntity entityliving1 = BehaviorUtils.getNearestTarget(piglin, behaviorcontroller.getMemory(MemoryModuleType.AVOID_TARGET), target); + +- livingentity1 = BehaviorUtils.getNearestTarget(piglin, brain.getMemory(MemoryModuleType.ATTACK_TARGET), livingentity1); +- setAvoidTargetAndDontHuntForAWhile(piglin, livingentity1); ++ entityliving1 = BehaviorUtils.getNearestTarget(piglin, behaviorcontroller.getMemory(MemoryModuleType.ATTACK_TARGET), entityliving1); ++ setAvoidTargetAndDontHuntForAWhile(piglin, entityliving1); + } + + private static boolean wantsToStopFleeing(Piglin piglin) { +- Brain brain = piglin.getBrain(); ++ Brain behaviorcontroller = piglin.getBrain(); + +- if (!brain.hasMemoryValue(MemoryModuleType.AVOID_TARGET)) { ++ if (!behaviorcontroller.hasMemoryValue(MemoryModuleType.AVOID_TARGET)) { + return true; + } else { +- LivingEntity livingentity = (LivingEntity) brain.getMemory(MemoryModuleType.AVOID_TARGET).get(); +- EntityType entitytype = livingentity.getType(); ++ LivingEntity entityliving = (LivingEntity) behaviorcontroller.getMemory(MemoryModuleType.AVOID_TARGET).get(); ++ EntityType entitytypes = entityliving.getType(); + +- return entitytype == EntityType.HOGLIN ? piglinsEqualOrOutnumberHoglins(piglin) : (isZombified(entitytype) ? !brain.isMemoryValue(MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED, livingentity) : false); ++ return entitytypes == EntityType.HOGLIN ? piglinsEqualOrOutnumberHoglins(piglin) : (isZombified(entitytypes) ? !behaviorcontroller.isMemoryValue(MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED, entityliving) : false); + } + } + +@@ -696,16 +718,16 @@ + return j > i; + } + +- private static void setAvoidTargetAndDontHuntForAWhile(Piglin piglin, LivingEntity livingentity) { ++ private static void setAvoidTargetAndDontHuntForAWhile(Piglin piglin, LivingEntity target) { + piglin.getBrain().eraseMemory(MemoryModuleType.ANGRY_AT); + piglin.getBrain().eraseMemory(MemoryModuleType.ATTACK_TARGET); + piglin.getBrain().eraseMemory(MemoryModuleType.WALK_TARGET); +- piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.AVOID_TARGET, livingentity, (long) PiglinAi.RETREAT_DURATION.sample(piglin.level().random)); ++ piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.AVOID_TARGET, target, (long) PiglinAi.RETREAT_DURATION.sample(piglin.level().random)); + dontKillAnyMoreHoglinsForAWhile(piglin); + } + +- protected static void dontKillAnyMoreHoglinsForAWhile(AbstractPiglin abstractpiglin) { +- abstractpiglin.getBrain().setMemoryWithExpiry(MemoryModuleType.HUNTED_RECENTLY, true, (long) PiglinAi.TIME_BETWEEN_HUNTS.sample(abstractpiglin.level().random)); ++ protected static void dontKillAnyMoreHoglinsForAWhile(AbstractPiglin piglin) { ++ piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.HUNTED_RECENTLY, true, (long) PiglinAi.TIME_BETWEEN_HUNTS.sample(piglin.level().random)); + } + + private static void eat(Piglin piglin) { +@@ -713,61 +735,67 @@ + } + + private static Vec3 getRandomNearbyPos(Piglin piglin) { +- Vec3 vec3 = LandRandomPos.getPos(piglin, 4, 2); ++ Vec3 vec3d = LandRandomPos.getPos(piglin, 4, 2); + +- return vec3 == null ? piglin.position() : vec3; ++ return vec3d == null ? piglin.position() : vec3d; + } + + private static boolean hasEatenRecently(Piglin piglin) { + return piglin.getBrain().hasMemoryValue(MemoryModuleType.ATE_RECENTLY); + } + +- protected static boolean isIdle(AbstractPiglin abstractpiglin) { +- return abstractpiglin.getBrain().isActive(Activity.IDLE); ++ protected static boolean isIdle(AbstractPiglin piglin) { ++ return piglin.getBrain().isActive(Activity.IDLE); + } + +- private static boolean hasCrossbow(LivingEntity livingentity) { +- return livingentity.isHolding(Items.CROSSBOW); ++ private static boolean hasCrossbow(LivingEntity piglin) { ++ return piglin.isHolding(Items.CROSSBOW); + } + +- private static void admireGoldItem(LivingEntity livingentity) { +- livingentity.getBrain().setMemoryWithExpiry(MemoryModuleType.ADMIRING_ITEM, true, 119L); ++ private static void admireGoldItem(LivingEntity piglin) { ++ piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.ADMIRING_ITEM, true, 119L); + } + + private static boolean isAdmiringItem(Piglin piglin) { + return piglin.getBrain().hasMemoryValue(MemoryModuleType.ADMIRING_ITEM); + } + +- private static boolean isBarterCurrency(ItemStack itemstack) { +- return itemstack.is(PiglinAi.BARTERING_ITEM); ++ // CraftBukkit start - Changes to allow custom payment for bartering ++ private static boolean isBarterCurrency(ItemStack itemstack, Piglin piglin) { ++ return isBarterCurrency(itemstack) || piglin.allowedBarterItems.contains(itemstack.getItem()); + } ++ // CraftBukkit end + +- private static boolean isFood(ItemStack itemstack) { +- return itemstack.is(ItemTags.PIGLIN_FOOD); ++ private static boolean isBarterCurrency(ItemStack stack) { ++ return stack.is(PiglinAi.BARTERING_ITEM); + } + ++ private static boolean isFood(ItemStack stack) { ++ return stack.is(ItemTags.PIGLIN_FOOD); ++ } ++ + private static boolean isNearRepellent(Piglin piglin) { + return piglin.getBrain().hasMemoryValue(MemoryModuleType.NEAREST_REPELLENT); + } + +- private static boolean seesPlayerHoldingLovedItem(LivingEntity livingentity) { +- return livingentity.getBrain().hasMemoryValue(MemoryModuleType.NEAREST_PLAYER_HOLDING_WANTED_ITEM); ++ private static boolean seesPlayerHoldingLovedItem(LivingEntity piglin) { ++ return piglin.getBrain().hasMemoryValue(MemoryModuleType.NEAREST_PLAYER_HOLDING_WANTED_ITEM); + } + +- private static boolean doesntSeeAnyPlayerHoldingLovedItem(LivingEntity livingentity) { +- return !seesPlayerHoldingLovedItem(livingentity); ++ private static boolean doesntSeeAnyPlayerHoldingLovedItem(LivingEntity piglin) { ++ return !seesPlayerHoldingLovedItem(piglin); + } + +- public static boolean isPlayerHoldingLovedItem(LivingEntity livingentity) { +- return livingentity.getType() == EntityType.PLAYER && livingentity.isHolding(PiglinAi::isLovedItem); ++ public static boolean isPlayerHoldingLovedItem(LivingEntity player) { ++ return player.getType() == EntityType.PLAYER && player.isHolding(PiglinAi::isLovedItem); + } + + private static boolean isAdmiringDisabled(Piglin piglin) { + return piglin.getBrain().hasMemoryValue(MemoryModuleType.ADMIRING_DISABLED); + } + +- private static boolean wasHurtRecently(LivingEntity livingentity) { +- return livingentity.getBrain().hasMemoryValue(MemoryModuleType.HURT_BY); ++ private static boolean wasHurtRecently(LivingEntity piglin) { ++ return piglin.getBrain().hasMemoryValue(MemoryModuleType.HURT_BY); + } + + private static boolean isHoldingItemInOffHand(Piglin piglin) { +@@ -775,10 +803,10 @@ + } + + private static boolean isNotHoldingLovedItemInOffHand(Piglin piglin) { +- return piglin.getOffhandItem().isEmpty() || !isLovedItem(piglin.getOffhandItem()); ++ return piglin.getOffhandItem().isEmpty() || !isLovedItem(piglin.getOffhandItem(), piglin); // CraftBukkit - Changes to allow custom payment for bartering + } + +- public static boolean isZombified(EntityType entitytype) { +- return entitytype == EntityType.ZOMBIFIED_PIGLIN || entitytype == EntityType.ZOGLIN; ++ public static boolean isZombified(EntityType entityType) { ++ return entityType == EntityType.ZOMBIFIED_PIGLIN || entityType == EntityType.ZOGLIN; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/warden/Warden.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/warden/Warden.java.patch new file mode 100644 index 0000000000..12e0b4c9e6 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/monster/warden/Warden.java.patch @@ -0,0 +1,694 @@ +--- a/net/minecraft/world/entity/monster/warden/Warden.java ++++ b/net/minecraft/world/entity/monster/warden/Warden.java +@@ -38,12 +38,12 @@ + import net.minecraft.world.entity.AnimationState; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -57,8 +57,8 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.ServerLevelAccessor; +-import net.minecraft.world.level.block.RenderShape; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.EnumRenderType; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.DynamicGameEventListener; + import net.minecraft.world.level.gameevent.EntityPositionSource; + import net.minecraft.world.level.gameevent.GameEvent; +@@ -109,12 +109,12 @@ + public AnimationState attackAnimationState = new AnimationState(); + public AnimationState sonicBoomAnimationState = new AnimationState(); + private final DynamicGameEventListener dynamicGameEventListener = new DynamicGameEventListener<>(new VibrationSystem.Listener(this)); +- private final VibrationSystem.User vibrationUser = new Warden.VibrationUser(); ++ private final VibrationSystem.User vibrationUser = new Warden.a(); + private VibrationSystem.Data vibrationData = new VibrationSystem.Data(); + AngerManagement angerManagement = new AngerManagement(this::canTargetEntity, Collections.emptyList()); + +- public Warden(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Warden(EntityType entityType, Level level) { ++ super(entityType, level); + this.xpReward = 5; + this.getNavigation().setCanFloat(true); + this.setPathfindingMalus(BlockPathTypes.UNPASSABLE_RAIL, 0.0F); +@@ -126,57 +126,49 @@ + } + + @Override +- @Override + public Packet getAddEntityPacket() { +- return new ClientboundAddEntityPacket(this, this.hasPose(Pose.EMERGING) ? 1 : 0); ++ return new ClientboundAddEntityPacket(this, this.hasPose(EntityPose.EMERGING) ? 1 : 0); + } + + @Override +- @Override +- public void recreateFromPacket(ClientboundAddEntityPacket clientboundaddentitypacket) { +- super.recreateFromPacket(clientboundaddentitypacket); +- if (clientboundaddentitypacket.getData() == 1) { +- this.setPose(Pose.EMERGING); ++ public void recreateFromPacket(ClientboundAddEntityPacket packet) { ++ super.recreateFromPacket(packet); ++ if (packet.getData() == 1) { ++ this.setPose(EntityPose.EMERGING); + } + + } + + @Override +- @Override +- public boolean checkSpawnObstruction(LevelReader levelreader) { +- return super.checkSpawnObstruction(levelreader) && levelreader.noCollision(this, this.getType().getDimensions().makeBoundingBox(this.position())); ++ public boolean checkSpawnObstruction(LevelReader level) { ++ return super.checkSpawnObstruction(level) && level.noCollision(this, this.getType().getDimensions().makeBoundingBox(this.position())); + } + + @Override +- @Override +- public float getWalkTargetValue(BlockPos blockpos, LevelReader levelreader) { ++ public float getWalkTargetValue(BlockPos pos, LevelReader level) { + return 0.0F; + } + + @Override +- @Override +- public boolean isInvulnerableTo(DamageSource damagesource) { +- return this.isDiggingOrEmerging() && !damagesource.is(DamageTypeTags.BYPASSES_INVULNERABILITY) ? true : super.isInvulnerableTo(damagesource); ++ public boolean isInvulnerableTo(DamageSource source) { ++ return this.isDiggingOrEmerging() && !source.is(DamageTypeTags.BYPASSES_INVULNERABILITY) ? true : super.isInvulnerableTo(source); + } + + boolean isDiggingOrEmerging() { +- return this.hasPose(Pose.DIGGING) || this.hasPose(Pose.EMERGING); ++ return this.hasPose(EntityPose.DIGGING) || this.hasPose(EntityPose.EMERGING); + } + + @Override +- @Override +- protected boolean canRide(Entity entity) { ++ protected boolean canRide(Entity vehicle) { + return false; + } + + @Override +- @Override + public boolean canDisableShield() { + return true; + } + + @Override +- @Override + protected float nextStep() { + return this.moveDist + 0.55F; + } +@@ -186,53 +178,45 @@ + } + + @Override +- @Override + public boolean dampensVibrations() { + return true; + } + + @Override +- @Override + protected float getSoundVolume() { + return 4.0F; + } + + @Nullable + @Override +- @Override + protected SoundEvent getAmbientSound() { +- return !this.hasPose(Pose.ROARING) && !this.isDiggingOrEmerging() ? this.getAngerLevel().getAmbientSound() : null; ++ return !this.hasPose(EntityPose.ROARING) && !this.isDiggingOrEmerging() ? this.getAngerLevel().getAmbientSound() : null; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.WARDEN_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.WARDEN_DEATH; + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { ++ protected void playStepSound(BlockPos pos, IBlockData state) { + this.playSound(SoundEvents.WARDEN_STEP, 10.0F, 1.0F); + } + + @Override +- @Override +- public boolean doHurtTarget(Entity entity) { ++ public boolean doHurtTarget(Entity target) { + this.level().broadcastEntityEvent(this, (byte) 4); + this.playSound(SoundEvents.WARDEN_ATTACK_IMPACT, 10.0F, this.getVoicePitch()); + SonicBoom.setCooldown(this, 40); +- return super.doHurtTarget(entity); ++ return super.doHurtTarget(target); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Warden.CLIENT_ANGER_LEVEL, 0); +@@ -247,14 +231,13 @@ + } + + @Override +- @Override + public void tick() { +- Level level = this.level(); ++ Level world = this.level(); + +- if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; + +- VibrationSystem.Ticker.tick(serverlevel, this.vibrationData, this.vibrationUser); ++ VibrationSystem.Ticker.tick(worldserver, this.vibrationData, this.vibrationUser); + if (this.isPersistenceRequired() || this.requiresCustomPersistence()) { + WardenAi.setDigCooldown(this); + } +@@ -291,20 +274,19 @@ + } + + @Override +- @Override + protected void customServerAiStep() { +- ServerLevel serverlevel = (ServerLevel) this.level(); ++ ServerLevel worldserver = (ServerLevel) this.level(); + +- serverlevel.getProfiler().push("wardenBrain"); +- this.getBrain().tick(serverlevel, this); ++ worldserver.getProfiler().push("wardenBrain"); ++ this.getBrain().tick(worldserver, this); + this.level().getProfiler().pop(); + super.customServerAiStep(); + if ((this.tickCount + this.getId()) % 120 == 0) { +- applyDarknessAround(serverlevel, this.position(), this, 20); ++ applyDarknessAround(worldserver, this.position(), this, 20); + } + + if (this.tickCount % 20 == 0) { +- this.angerManagement.tick(serverlevel, this::canTargetEntity); ++ this.angerManagement.tick(worldserver, this::canTargetEntity); + this.syncClientAngerLevel(); + } + +@@ -312,17 +294,16 @@ + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 4) { ++ public void handleEntityEvent(byte id) { ++ if (id == 4) { + this.roarAnimationState.stop(); + this.attackAnimationState.start(this.tickCount); +- } else if (b0 == 61) { ++ } else if (id == 61) { + this.tendrilAnimation = 10; +- } else if (b0 == 62) { ++ } else if (id == 62) { + this.sonicBoomAnimationState.start(this.tickCount); + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } +@@ -333,26 +314,26 @@ + return 40 - Mth.floor(Mth.clamp(f, 0.0F, 1.0F) * 30.0F); + } + +- public float getTendrilAnimation(float f) { +- return Mth.lerp(f, (float) this.tendrilAnimationO, (float) this.tendrilAnimation) / 10.0F; ++ public float getTendrilAnimation(float partialTick) { ++ return Mth.lerp(partialTick, (float) this.tendrilAnimationO, (float) this.tendrilAnimation) / 10.0F; + } + +- public float getHeartAnimation(float f) { +- return Mth.lerp(f, (float) this.heartAnimationO, (float) this.heartAnimation) / 10.0F; ++ public float getHeartAnimation(float partialTick) { ++ return Mth.lerp(partialTick, (float) this.heartAnimationO, (float) this.heartAnimation) / 10.0F; + } + +- private void clientDiggingParticles(AnimationState animationstate) { +- if ((float) animationstate.getAccumulatedTime() < 4500.0F) { ++ private void clientDiggingParticles(AnimationState animationState) { ++ if ((float) animationState.getAccumulatedTime() < 4500.0F) { + RandomSource randomsource = this.getRandom(); +- BlockState blockstate = this.getBlockStateOn(); ++ IBlockData iblockdata = this.getBlockStateOn(); + +- if (blockstate.getRenderShape() != RenderShape.INVISIBLE) { ++ if (iblockdata.getRenderShape() != EnumRenderType.INVISIBLE) { + for (int i = 0; i < 30; ++i) { + double d0 = this.getX() + (double) Mth.randomBetween(randomsource, -0.7F, 0.7F); + double d1 = this.getY(); + double d2 = this.getZ() + (double) Mth.randomBetween(randomsource, -0.7F, 0.7F); + +- this.level().addParticle(new BlockParticleOption(ParticleTypes.BLOCK, blockstate), d0, d1, d2, 0.0D, 0.0D, 0.0D); ++ this.level().addParticle(new BlockParticleOption(ParticleTypes.BLOCK, iblockdata), d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + } + } +@@ -360,9 +341,8 @@ + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- if (Warden.DATA_POSE.equals(entitydataaccessor)) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ if (Warden.DATA_POSE.equals(key)) { + switch (this.getPose()) { + case EMERGING: + this.emergeAnimationState.start(this.tickCount); +@@ -378,43 +358,38 @@ + } + } + +- super.onSyncedDataUpdated(entitydataaccessor); ++ super.onSyncedDataUpdated(key); + } + + @Override +- @Override + public boolean ignoreExplosion(Explosion explosion) { + return this.isDiggingOrEmerging(); + } + + @Override +- @Override + protected Brain makeBrain(Dynamic dynamic) { + return WardenAi.makeBrain(this, dynamic); + } + + @Override +- @Override + public Brain getBrain() { +- return super.getBrain(); ++ return (Brain) super.getBrain(); // CraftBukkit - decompile error + } + + @Override +- @Override + protected void sendDebugPackets() { + super.sendDebugPackets(); + DebugPackets.sendEntityBrain(this); + } + + @Override +- @Override +- public void updateDynamicGameEventListener(BiConsumer, ServerLevel> biconsumer) { +- Level level = this.level(); ++ public void updateDynamicGameEventListener(BiConsumer, ServerLevel> listenerConsumer) { ++ Level world = this.level(); + +- if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; + +- biconsumer.accept(this.dynamicGameEventListener, serverlevel); ++ listenerConsumer.accept(this.dynamicGameEventListener, worldserver); + } + + } +@@ -424,9 +399,9 @@ + boolean flag; + + if (entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; ++ LivingEntity entityliving = (LivingEntity) entity; + +- if (this.level() == entity.level() && EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(entity) && !this.isAlliedTo(entity) && livingentity.getType() != EntityType.ARMOR_STAND && livingentity.getType() != EntityType.WARDEN && !livingentity.isInvulnerable() && !livingentity.isDeadOrDying() && this.level().getWorldBorder().isWithinBounds(livingentity.getBoundingBox())) { ++ if (this.level() == entity.level() && EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(entity) && !this.isAlliedTo(entity) && entityliving.getType() != EntityType.ARMOR_STAND && entityliving.getType() != EntityType.WARDEN && !entityliving.isInvulnerable() && !entityliving.isDeadOrDying() && this.level().getWorldBorder().isWithinBounds(entityliving.getBoundingBox())) { + flag = true; + return flag; + } +@@ -436,61 +411,59 @@ + return flag; + } + +- public static void applyDarknessAround(ServerLevel serverlevel, Vec3 vec3, @Nullable Entity entity, int i) { +- MobEffectInstance mobeffectinstance = new MobEffectInstance(MobEffects.DARKNESS, 260, 0, false, false); ++ public static void applyDarknessAround(ServerLevel level, Vec3 pos, @Nullable Entity source, int radius) { ++ MobEffectInstance mobeffect = new MobEffectInstance(MobEffects.DARKNESS, 260, 0, false, false); + +- MobEffectUtil.addEffectToPlayersAround(serverlevel, entity, vec3, (double) i, mobeffectinstance, 200); ++ MobEffectUtil.addEffectToPlayersAround(level, source, pos, radius, mobeffect, 200, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.WARDEN); // CraftBukkit - Add EntityPotionEffectEvent.Cause + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- DataResult dataresult = AngerManagement.codec(this::canTargetEntity).encodeStart(NbtOps.INSTANCE, this.angerManagement); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ DataResult dataresult = AngerManagement.codec(this::canTargetEntity).encodeStart(NbtOps.INSTANCE, this.angerManagement); // CraftBukkit - decompile error + Logger logger = Warden.LOGGER; + + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((tag) -> { +- compoundtag.put("anger", tag); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("anger", nbtbase); + }); + dataresult = VibrationSystem.Data.CODEC.encodeStart(NbtOps.INSTANCE, this.vibrationData); + logger = Warden.LOGGER; + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((tag) -> { +- compoundtag.put("listener", tag); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("listener", nbtbase); + }); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); + DataResult dataresult; + Logger logger; + +- if (compoundtag.contains("anger")) { +- dataresult = AngerManagement.codec(this::canTargetEntity).parse(new Dynamic(NbtOps.INSTANCE, compoundtag.get("anger"))); ++ if (compound.contains("anger")) { ++ dataresult = AngerManagement.codec(this::canTargetEntity).parse(new Dynamic(NbtOps.INSTANCE, compound.get("anger"))); + logger = Warden.LOGGER; + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((angermanagement) -> { ++ ((DataResult) dataresult).resultOrPartial(logger::error).ifPresent((angermanagement) -> { // CraftBukkit - decompile error + this.angerManagement = angermanagement; + }); + this.syncClientAngerLevel(); + } + +- if (compoundtag.contains("listener", 10)) { +- dataresult = VibrationSystem.Data.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compoundtag.getCompound("listener"))); ++ if (compound.contains("listener", 10)) { ++ dataresult = VibrationSystem.Data.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compound.getCompound("listener"))); + logger = Warden.LOGGER; + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((vibrationsystem_data) -> { +- this.vibrationData = vibrationsystem_data; ++ ((DataResult) dataresult).resultOrPartial(logger::error).ifPresent((vibrationsystem_a) -> { // CraftBukkit - decompile error ++ this.vibrationData = vibrationsystem_a; + }); + } + + } + + private void playListeningSound() { +- if (!this.hasPose(Pose.ROARING)) { ++ if (!this.hasPose(EntityPose.ROARING)) { + this.playSound(this.getAngerLevel().getListeningSound(), 10.0F, this.getVoicePitch()); + } + +@@ -513,17 +486,17 @@ + } + + @VisibleForTesting +- public void increaseAngerAt(@Nullable Entity entity, int i, boolean flag) { ++ public void increaseAngerAt(@Nullable Entity entity, int offset, boolean playListeningSound) { + if (!this.isNoAi() && this.canTargetEntity(entity)) { + WardenAi.setDigCooldown(this); +- boolean flag1 = !(this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse((Object) null) instanceof Player); +- int j = this.angerManagement.increaseAnger(entity, i); ++ boolean flag1 = !(this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null) instanceof Player); // CraftBukkit - decompile error ++ int j = this.angerManagement.increaseAnger(entity, offset); + + if (entity instanceof Player && flag1 && AngerLevel.byAnger(j).isAngry()) { + this.getBrain().eraseMemory(MemoryModuleType.ATTACK_TARGET); + } + +- if (flag) { ++ if (playListeningSound) { + this.playListeningSound(); + } + } +@@ -536,45 +509,41 @@ + + @Nullable + @Override +- @Override + public LivingEntity getTarget() { +- return (LivingEntity) this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse((Object) null); ++ return (LivingEntity) this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); // CraftBukkit - decompile error + } + + @Override +- @Override +- public boolean removeWhenFarAway(double d0) { ++ public boolean removeWhenFarAway(double distanceToClosestPlayer) { + return false; + } + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + this.getBrain().setMemoryWithExpiry(MemoryModuleType.DIG_COOLDOWN, Unit.INSTANCE, 1200L); +- if (mobspawntype == MobSpawnType.TRIGGERED) { +- this.setPose(Pose.EMERGING); ++ if (reason == EnumMobSpawn.TRIGGERED) { ++ this.setPose(EntityPose.EMERGING); + this.getBrain().setMemoryWithExpiry(MemoryModuleType.IS_EMERGING, Unit.INSTANCE, (long) WardenAi.EMERGE_DURATION); + this.playSound(SoundEvents.WARDEN_AGITATED, 5.0F, 1.0F); + } + +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); ++ return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- boolean flag = super.hurt(damagesource, f); ++ public boolean hurt(DamageSource source, float amount) { ++ boolean flag = super.hurt(source, amount); + + if (!this.level().isClientSide && !this.isNoAi() && !this.isDiggingOrEmerging()) { +- Entity entity = damagesource.getEntity(); ++ Entity entity = source.getEntity(); + + this.increaseAngerAt(entity, AngerLevel.ANGRY.getMinimumAnger() + 20, false); + if (this.brain.getMemory(MemoryModuleType.ATTACK_TARGET).isEmpty() && entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; ++ LivingEntity entityliving = (LivingEntity) entity; + +- if (!damagesource.isIndirect() || this.closerThan(livingentity, 5.0D)) { +- this.setAttackTarget(livingentity); ++ if (!source.isIndirect() || this.closerThan(entityliving, 5.0D)) { ++ this.setAttackTarget(entityliving); + } + } + } +@@ -582,29 +551,26 @@ + return flag; + } + +- public void setAttackTarget(LivingEntity livingentity) { ++ public void setAttackTarget(LivingEntity attackTarget) { + this.getBrain().eraseMemory(MemoryModuleType.ROAR_TARGET); +- this.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, (Object) livingentity); ++ this.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, attackTarget); // CraftBukkit - decompile error + this.getBrain().eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE); + SonicBoom.setCooldown(this, 200); + } + + @Override +- @Override +- public EntityDimensions getDimensions(Pose pose) { +- EntityDimensions entitydimensions = super.getDimensions(pose); ++ public EntityDimensions getDimensions(EntityPose pose) { ++ EntityDimensions entitysize = super.getDimensions(pose); + +- return this.isDiggingOrEmerging() ? EntityDimensions.fixed(entitydimensions.width, 1.0F) : entitydimensions; ++ return this.isDiggingOrEmerging() ? EntityDimensions.fixed(entitysize.width, 1.0F) : entitysize; + } + + @Override +- @Override + public boolean isPushable() { + return !this.isDiggingOrEmerging() && super.isPushable(); + } + + @Override +- @Override + protected void doPush(Entity entity) { + if (!this.isNoAi() && !this.getBrain().hasMemoryValue(MemoryModuleType.TOUCH_COOLDOWN)) { + this.getBrain().setMemoryWithExpiry(MemoryModuleType.TOUCH_COOLDOWN, Unit.INSTANCE, 20L); +@@ -621,19 +587,16 @@ + } + + @Override +- @Override + protected PathNavigation createNavigation(Level level) { + return new GroundPathNavigation(this, level) { + @Override +- @Override +- protected PathFinder createPathFinder(int i) { ++ protected PathFinder createPathFinder(int maxVisitedNodes) { + this.nodeEvaluator = new WalkNodeEvaluator(); + this.nodeEvaluator.setCanPassDoors(true); +- return new PathFinder(this.nodeEvaluator, i) { ++ return new PathFinder(this.nodeEvaluator, maxVisitedNodes) { + @Override +- @Override +- protected float distance(Node node, Node node1) { +- return node.distanceToXZ(node1); ++ protected float distance(Node first, Node second) { ++ return first.distanceToXZ(second); + } + }; + } +@@ -641,65 +604,57 @@ + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { +- return new Vector3f(0.0F, entitydimensions.height + 0.25F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.25F * f, 0.0F); + } + + @Override +- @Override + public VibrationSystem.Data getVibrationData() { + return this.vibrationData; + } + + @Override +- @Override + public VibrationSystem.User getVibrationUser() { + return this.vibrationUser; + } + +- private class VibrationUser implements VibrationSystem.User { ++ private class a implements VibrationSystem.User { + + private static final int GAME_EVENT_LISTENER_RANGE = 16; + private final PositionSource positionSource = new EntityPositionSource(Warden.this, Warden.this.getEyeHeight()); + +- VibrationUser() {} ++ a() {} + + @Override +- @Override + public int getListenerRadius() { + return 16; + } + + @Override +- @Override + public PositionSource getPositionSource() { + return this.positionSource; + } + + @Override +- @Override + public TagKey getListenableEvents() { + return GameEventTags.WARDEN_CAN_LISTEN; + } + + @Override +- @Override + public boolean canTriggerAvoidVibration() { + return true; + } + + @Override +- @Override +- public boolean canReceiveVibration(ServerLevel serverlevel, BlockPos blockpos, GameEvent gameevent, GameEvent.Context gameevent_context) { +- if (!Warden.this.isNoAi() && !Warden.this.isDeadOrDying() && !Warden.this.getBrain().hasMemoryValue(MemoryModuleType.VIBRATION_COOLDOWN) && !Warden.this.isDiggingOrEmerging() && serverlevel.getWorldBorder().isWithinBounds(blockpos)) { +- Entity entity = gameevent_context.sourceEntity(); ++ public boolean canReceiveVibration(ServerLevel level, BlockPos pos, GameEvent gameEvent, GameEvent.Context context) { ++ if (!Warden.this.isNoAi() && !Warden.this.isDeadOrDying() && !Warden.this.getBrain().hasMemoryValue(MemoryModuleType.VIBRATION_COOLDOWN) && !Warden.this.isDiggingOrEmerging() && level.getWorldBorder().isWithinBounds(pos)) { ++ Entity entity = context.sourceEntity(); + boolean flag; + + if (entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; ++ LivingEntity entityliving = (LivingEntity) entity; + +- if (!Warden.this.canTargetEntity(livingentity)) { ++ if (!Warden.this.canTargetEntity(entityliving)) { + flag = false; + return flag; + } +@@ -713,24 +668,23 @@ + } + + @Override +- @Override +- public void onReceiveVibration(ServerLevel serverlevel, BlockPos blockpos, GameEvent gameevent, @Nullable Entity entity, @Nullable Entity entity1, float f) { ++ public void onReceiveVibration(ServerLevel level, BlockPos pos, GameEvent gameEvent, @Nullable Entity entity, @Nullable Entity playerEntity, float distance) { + if (!Warden.this.isDeadOrDying()) { + Warden.this.brain.setMemoryWithExpiry(MemoryModuleType.VIBRATION_COOLDOWN, Unit.INSTANCE, 40L); +- serverlevel.broadcastEntityEvent(Warden.this, (byte) 61); ++ level.broadcastEntityEvent(Warden.this, (byte) 61); + Warden.this.playSound(SoundEvents.WARDEN_TENDRIL_CLICKS, 5.0F, Warden.this.getVoicePitch()); +- BlockPos blockpos1 = blockpos; ++ BlockPos blockposition1 = pos; + +- if (entity1 != null) { +- if (Warden.this.closerThan(entity1, 30.0D)) { ++ if (playerEntity != null) { ++ if (Warden.this.closerThan(playerEntity, 30.0D)) { + if (Warden.this.getBrain().hasMemoryValue(MemoryModuleType.RECENT_PROJECTILE)) { +- if (Warden.this.canTargetEntity(entity1)) { +- blockpos1 = entity1.blockPosition(); ++ if (Warden.this.canTargetEntity(playerEntity)) { ++ blockposition1 = playerEntity.blockPosition(); + } + +- Warden.this.increaseAngerAt(entity1); ++ Warden.this.increaseAngerAt(playerEntity); + } else { +- Warden.this.increaseAngerAt(entity1, 10, true); ++ Warden.this.increaseAngerAt(playerEntity, 10, true); + } + } + +@@ -742,8 +696,8 @@ + if (!Warden.this.getAngerLevel().isAngry()) { + Optional optional = Warden.this.angerManagement.getActiveEntity(); + +- if (entity1 != null || optional.isEmpty() || optional.get() == entity) { +- WardenAi.setDisturbanceLocation(Warden.this, blockpos1); ++ if (playerEntity != null || optional.isEmpty() || optional.get() == entity) { ++ WardenAi.setDisturbanceLocation(Warden.this, blockposition1); + } + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/AbstractVillager.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/AbstractVillager.java.patch new file mode 100644 index 0000000000..bbff4dd88b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/AbstractVillager.java.patch @@ -0,0 +1,330 @@ +--- a/net/minecraft/world/entity/npc/AbstractVillager.java ++++ b/net/minecraft/world/entity/npc/AbstractVillager.java +@@ -20,11 +20,11 @@ + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.SlotAccess; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.trading.Merchant; +@@ -34,9 +34,23 @@ + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.inventory.CraftMerchant; ++import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; ++import org.bukkit.event.entity.VillagerAcquireTradeEvent; ++// CraftBukkit end + +-public abstract class AbstractVillager extends AgeableMob implements InventoryCarrier, Npc, Merchant { ++public abstract class AbstractVillager extends AgeableMob implements InventoryCarrier, NPC, Merchant { + ++ // CraftBukkit start ++ private CraftMerchant craftMerchant; ++ ++ @Override ++ public CraftMerchant getCraftMerchant() { ++ return (craftMerchant == null) ? craftMerchant = new CraftMerchant(this) : craftMerchant; ++ } ++ // CraftBukkit end + private static final EntityDataAccessor DATA_UNHAPPY_COUNTER = SynchedEntityData.defineId(AbstractVillager.class, EntityDataSerializers.INT); + public static final int VILLAGER_SLOT_OFFSET = 300; + private static final int VILLAGER_INVENTORY_SIZE = 8; +@@ -44,60 +58,54 @@ + private Player tradingPlayer; + @Nullable + protected MerchantOffers offers; +- private final SimpleContainer inventory = new SimpleContainer(8); ++ private final SimpleContainer inventory = new SimpleContainer(8, (org.bukkit.craftbukkit.entity.CraftAbstractVillager) this.getBukkitEntity()); // CraftBukkit add argument + +- public AbstractVillager(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public AbstractVillager(EntityType entityType, Level level) { ++ super(entityType, level); + this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, 16.0F); + this.setPathfindingMalus(BlockPathTypes.DAMAGE_FIRE, -1.0F); + } + + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- if (spawngroupdata == null) { +- spawngroupdata = new AgeableMob.AgeableMobGroupData(false); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ if (spawnData == null) { ++ spawnData = new AgeableMob.AgeableMobGroupData(false); + } + +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, (SpawnGroupData) spawngroupdata, compoundtag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + + public int getUnhappyCounter() { + return (Integer) this.entityData.get(AbstractVillager.DATA_UNHAPPY_COUNTER); + } + +- public void setUnhappyCounter(int i) { +- this.entityData.set(AbstractVillager.DATA_UNHAPPY_COUNTER, i); ++ public void setUnhappyCounter(int unhappyCounter) { ++ this.entityData.set(AbstractVillager.DATA_UNHAPPY_COUNTER, unhappyCounter); + } + + @Override +- @Override + public int getVillagerXp() { + return 0; + } + + @Override +- @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return this.isBaby() ? 0.81F : 1.62F; + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(AbstractVillager.DATA_UNHAPPY_COUNTER, 0); + } + + @Override +- @Override + public void setTradingPlayer(@Nullable Player player) { + this.tradingPlayer = player; + } + + @Nullable + @Override +- @Override + public Player getTradingPlayer() { + return this.tradingPlayer; + } +@@ -107,7 +115,6 @@ + } + + @Override +- @Override + public MerchantOffers getOffers() { + if (this.offers == null) { + this.offers = new MerchantOffers(); +@@ -118,21 +125,18 @@ + } + + @Override +- @Override +- public void overrideOffers(@Nullable MerchantOffers merchantoffers) {} ++ public void overrideOffers(@Nullable MerchantOffers offers) {} + + @Override +- @Override +- public void overrideXp(int i) {} ++ public void overrideXp(int xp) {} + + @Override +- @Override +- public void notifyTrade(MerchantOffer merchantoffer) { +- merchantoffer.increaseUses(); ++ public void notifyTrade(MerchantOffer offer) { ++ offer.increaseUses(); + this.ambientSoundTime = -this.getAmbientSoundInterval(); +- this.rewardTradeXp(merchantoffer); ++ this.rewardTradeXp(offer); + if (this.tradingPlayer instanceof ServerPlayer) { +- CriteriaTriggers.TRADE.trigger((ServerPlayer) this.tradingPlayer, this, merchantoffer.getResult()); ++ CriteriaTriggers.TRADE.trigger((ServerPlayer) this.tradingPlayer, this, offer.getResult()); + } + + } +@@ -140,29 +144,26 @@ + protected abstract void rewardTradeXp(MerchantOffer offer); + + @Override +- @Override + public boolean showProgressBar() { + return true; + } + + @Override +- @Override +- public void notifyTradeUpdated(ItemStack itemstack) { ++ public void notifyTradeUpdated(ItemStack stack) { + if (!this.level().isClientSide && this.ambientSoundTime > -this.getAmbientSoundInterval() + 20) { + this.ambientSoundTime = -this.getAmbientSoundInterval(); +- this.playSound(this.getTradeUpdatedSound(!itemstack.isEmpty()), this.getSoundVolume(), this.getVoicePitch()); ++ this.playSound(this.getTradeUpdatedSound(!stack.isEmpty()), this.getSoundVolume(), this.getVoicePitch()); + } + + } + + @Override +- @Override + public SoundEvent getNotifyTradeSound() { + return SoundEvents.VILLAGER_YES; + } + +- protected SoundEvent getTradeUpdatedSound(boolean flag) { +- return flag ? SoundEvents.VILLAGER_YES : SoundEvents.VILLAGER_NO; ++ protected SoundEvent getTradeUpdatedSound(boolean isYesSound) { ++ return isYesSound ? SoundEvents.VILLAGER_YES : SoundEvents.VILLAGER_NO; + } + + public void playCelebrateSound() { +@@ -170,35 +171,32 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- MerchantOffers merchantoffers = this.getOffers(); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ MerchantOffers merchantrecipelist = this.getOffers(); + +- if (!merchantoffers.isEmpty()) { +- compoundtag.put("Offers", merchantoffers.createTag()); ++ if (!merchantrecipelist.isEmpty()) { ++ compound.put("Offers", merchantrecipelist.createTag()); + } + +- this.writeInventoryToTag(compoundtag); ++ this.writeInventoryToTag(compound); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("Offers", 10)) { +- this.offers = new MerchantOffers(compoundtag.getCompound("Offers")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("Offers", 10)) { ++ this.offers = new MerchantOffers(compound.getCompound("Offers")); + } + +- this.readInventoryFromTag(compoundtag); ++ this.readInventoryFromTag(compound); + } + + @Nullable + @Override +- @Override +- public Entity changeDimension(ServerLevel serverlevel) { ++ public Entity changeDimension(ServerLevel server) { + this.stopTrading(); +- return super.changeDimension(serverlevel); ++ return super.changeDimension(server); + } + + protected void stopTrading() { +@@ -206,54 +204,59 @@ + } + + @Override +- @Override +- public void die(DamageSource damagesource) { +- super.die(damagesource); ++ public void die(DamageSource cause) { ++ super.die(cause); + this.stopTrading(); + } + +- protected void addParticlesAroundSelf(ParticleOptions particleoptions) { ++ protected void addParticlesAroundSelf(ParticleOptions particleOption) { + for (int i = 0; i < 5; ++i) { + double d0 = this.random.nextGaussian() * 0.02D; + double d1 = this.random.nextGaussian() * 0.02D; + double d2 = this.random.nextGaussian() * 0.02D; + +- this.level().addParticle(particleoptions, this.getRandomX(1.0D), this.getRandomY() + 1.0D, this.getRandomZ(1.0D), d0, d1, d2); ++ this.level().addParticle(particleOption, this.getRandomX(1.0D), this.getRandomY() + 1.0D, this.getRandomZ(1.0D), d0, d1, d2); + } + + } + + @Override +- @Override + public boolean canBeLeashed(Player player) { + return false; + } + + @Override +- @Override + public SimpleContainer getInventory() { + return this.inventory; + } + + @Override +- @Override +- public SlotAccess getSlot(int i) { +- int j = i - 300; ++ public SlotAccess getSlot(int slot) { ++ int j = slot - 300; + +- return j >= 0 && j < this.inventory.getContainerSize() ? SlotAccess.forContainer(this.inventory, j) : super.getSlot(i); ++ return j >= 0 && j < this.inventory.getContainerSize() ? SlotAccess.forContainer(this.inventory, j) : super.getSlot(slot); + } + + protected abstract void updateTrades(); + +- protected void addOffersFromItemListings(MerchantOffers merchantoffers, VillagerTrades.ItemListing[] avillagertrades_itemlisting, int i) { +- ArrayList arraylist = Lists.newArrayList(avillagertrades_itemlisting); ++ protected void addOffersFromItemListings(MerchantOffers givenMerchantOffers, VillagerTrades.ItemListing[] newTrades, int maxNumbers) { ++ ArrayList arraylist = Lists.newArrayList(newTrades); + int j = 0; + +- while (j < i && !arraylist.isEmpty()) { +- MerchantOffer merchantoffer = ((VillagerTrades.ItemListing) arraylist.remove(this.random.nextInt(arraylist.size()))).getOffer(this, this.random); ++ while (j < maxNumbers && !arraylist.isEmpty()) { ++ MerchantOffer merchantrecipe = ((VillagerTrades.ItemListing) arraylist.remove(this.random.nextInt(arraylist.size()))).getOffer(this, this.random); + +- if (merchantoffer != null) { +- merchantoffers.add(merchantoffer); ++ if (merchantrecipe != null) { ++ // CraftBukkit start ++ VillagerAcquireTradeEvent event = new VillagerAcquireTradeEvent((org.bukkit.entity.AbstractVillager) getBukkitEntity(), merchantrecipe.asBukkit()); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ if (!event.isCancelled()) { ++ givenMerchantOffers.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); ++ } ++ // CraftBukkit end + ++j; + } + } +@@ -261,16 +264,14 @@ + } + + @Override +- @Override +- public Vec3 getRopeHoldPosition(float f) { +- float f1 = Mth.lerp(f, this.yBodyRotO, this.yBodyRot) * 0.017453292F; +- Vec3 vec3 = new Vec3(0.0D, this.getBoundingBox().getYsize() - 1.0D, 0.2D); ++ public Vec3 getRopeHoldPosition(float partialTicks) { ++ float f1 = Mth.lerp(partialTicks, this.yBodyRotO, this.yBodyRot) * 0.017453292F; ++ Vec3 vec3d = new Vec3(0.0D, this.getBoundingBox().getYsize() - 1.0D, 0.2D); + +- return this.getPosition(f).add(vec3.yRot(-f1)); ++ return this.getPosition(partialTicks).add(vec3d.yRot(-f1)); + } + + @Override +- @Override + public boolean isClientSide() { + return this.level().isClientSide; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/InventoryCarrier.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/InventoryCarrier.java.patch new file mode 100644 index 0000000000..6a380696ae --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/InventoryCarrier.java.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/entity/npc/InventoryCarrier.java ++++ b/net/minecraft/world/entity/npc/InventoryCarrier.java +@@ -12,24 +12,31 @@ + + SimpleContainer getInventory(); + +- static void pickUpItem(Mob mob, InventoryCarrier inventorycarrier, ItemEntity itementity) { +- ItemStack itemstack = itementity.getItem(); ++ static void pickUpItem(Mob mob, InventoryCarrier carrier, ItemEntity itemEntity) { ++ ItemStack itemstack = itemEntity.getItem(); + + if (mob.wantsToPickUp(itemstack)) { +- SimpleContainer simplecontainer = inventorycarrier.getInventory(); +- boolean flag = simplecontainer.canAddItem(itemstack); ++ SimpleContainer inventorysubcontainer = carrier.getInventory(); ++ boolean flag = inventorysubcontainer.canAddItem(itemstack); + + if (!flag) { + return; + } + +- mob.onItemPickup(itementity); ++ // CraftBukkit start ++ ItemStack remaining = new SimpleContainer(inventorysubcontainer).addItem(itemstack); ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(mob, itemEntity, remaining.getCount(), false).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ ++ mob.onItemPickup(itemEntity); + int i = itemstack.getCount(); +- ItemStack itemstack1 = simplecontainer.addItem(itemstack); ++ ItemStack itemstack1 = inventorysubcontainer.addItem(itemstack); + +- mob.take(itementity, i - itemstack1.getCount()); ++ mob.take(itemEntity, i - itemstack1.getCount()); + if (itemstack1.isEmpty()) { +- itementity.discard(); ++ itemEntity.discard(); + } else { + itemstack.setCount(itemstack1.getCount()); + } +@@ -37,14 +44,14 @@ + + } + +- default void readInventoryFromTag(CompoundTag compoundtag) { +- if (compoundtag.contains("Inventory", 9)) { +- this.getInventory().fromTag(compoundtag.getList("Inventory", 10)); ++ default void readInventoryFromTag(CompoundTag tag) { ++ if (tag.contains("Inventory", 9)) { ++ this.getInventory().fromTag(tag.getList("Inventory", 10)); + } + + } + +- default void writeInventoryToTag(CompoundTag compoundtag) { +- compoundtag.put("Inventory", this.getInventory().createTag()); ++ default void writeInventoryToTag(CompoundTag tag) { ++ tag.put("Inventory", this.getInventory().createTag()); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/Villager.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/Villager.java.patch new file mode 100644 index 0000000000..4a2f676dd8 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/Villager.java.patch @@ -0,0 +1,1032 @@ +--- a/net/minecraft/world/entity/npc/Villager.java ++++ b/net/minecraft/world/entity/npc/Villager.java +@@ -42,7 +42,7 @@ + import net.minecraft.util.SpawnUtil; + import net.minecraft.world.Difficulty; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.damagesource.DamageSource; +@@ -51,13 +51,13 @@ + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.ExperienceOrb; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LightningBolt; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.ReputationEventHandler; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -92,6 +92,13 @@ + import net.minecraft.world.phys.AABB; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTransformEvent; ++import org.bukkit.event.entity.VillagerReplenishTradeEvent; ++// CraftBukkit end ++ + public class Villager extends AbstractVillager implements ReputationEventHandler, VillagerDataHolder { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -125,85 +132,81 @@ + private boolean assignProfessionWhenSpawned; + private static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.HOME, MemoryModuleType.JOB_SITE, MemoryModuleType.POTENTIAL_JOB_SITE, MemoryModuleType.MEETING_POINT, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.VISIBLE_VILLAGER_BABIES, MemoryModuleType.NEAREST_PLAYERS, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS, new MemoryModuleType[]{MemoryModuleType.WALK_TARGET, MemoryModuleType.LOOK_TARGET, MemoryModuleType.INTERACTION_TARGET, MemoryModuleType.BREED_TARGET, MemoryModuleType.PATH, MemoryModuleType.DOORS_TO_CLOSE, MemoryModuleType.NEAREST_BED, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.NEAREST_HOSTILE, MemoryModuleType.SECONDARY_JOB_SITE, MemoryModuleType.HIDING_PLACE, MemoryModuleType.HEARD_BELL_TIME, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.LAST_SLEPT, MemoryModuleType.LAST_WOKEN, MemoryModuleType.LAST_WORKED_AT_POI, MemoryModuleType.GOLEM_DETECTED_RECENTLY}); + private static final ImmutableList>> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.NEAREST_ITEMS, SensorType.NEAREST_BED, SensorType.HURT_BY, SensorType.VILLAGER_HOSTILES, SensorType.VILLAGER_BABIES, SensorType.SECONDARY_POIS, SensorType.GOLEM_DETECTED); +- public static final Map, BiPredicate>> POI_MEMORIES = ImmutableMap.of(MemoryModuleType.HOME, (villager, holder) -> { ++ public static final Map, BiPredicate>> POI_MEMORIES = ImmutableMap.of(MemoryModuleType.HOME, (entityvillager, holder) -> { + return holder.is(PoiTypes.HOME); +- }, MemoryModuleType.JOB_SITE, (villager, holder) -> { +- return villager.getVillagerData().getProfession().heldJobSite().test(holder); +- }, MemoryModuleType.POTENTIAL_JOB_SITE, (villager, holder) -> { ++ }, MemoryModuleType.JOB_SITE, (entityvillager, holder) -> { ++ return entityvillager.getVillagerData().getProfession().heldJobSite().test(holder); ++ }, MemoryModuleType.POTENTIAL_JOB_SITE, (entityvillager, holder) -> { + return VillagerProfession.ALL_ACQUIRABLE_JOBS.test(holder); +- }, MemoryModuleType.MEETING_POINT, (villager, holder) -> { ++ }, MemoryModuleType.MEETING_POINT, (entityvillager, holder) -> { + return holder.is(PoiTypes.MEETING); + }); + +- public Villager(EntityType entitytype, Level level) { +- this(entitytype, level, VillagerType.PLAINS); ++ public Villager(EntityType entityType, Level level) { ++ this(entityType, level, VillagerType.PLAINS); + } + +- public Villager(EntityType entitytype, Level level, VillagerType villagertype) { +- super(entitytype, level); ++ public Villager(EntityType entityType, Level level, VillagerType villagerType) { ++ super(entityType, level); + this.gossips = new GossipContainer(); + ((GroundPathNavigation) this.getNavigation()).setCanOpenDoors(true); + this.getNavigation().setCanFloat(true); + this.setCanPickUpLoot(true); +- this.setVillagerData(this.getVillagerData().setType(villagertype).setProfession(VillagerProfession.NONE)); ++ this.setVillagerData(this.getVillagerData().setType(villagerType).setProfession(VillagerProfession.NONE)); + } + + @Override +- @Override + public Brain getBrain() { +- return super.getBrain(); ++ return (Brain) super.getBrain(); // CraftBukkit - decompile error + } + + @Override +- @Override + protected Brain.Provider brainProvider() { + return Brain.provider(Villager.MEMORY_TYPES, Villager.SENSOR_TYPES); + } + + @Override +- @Override + protected Brain makeBrain(Dynamic dynamic) { +- Brain brain = this.brainProvider().makeBrain(dynamic); ++ Brain behaviorcontroller = this.brainProvider().makeBrain(dynamic); + +- this.registerBrainGoals(brain); +- return brain; ++ this.registerBrainGoals(behaviorcontroller); ++ return behaviorcontroller; + } + +- public void refreshBrain(ServerLevel serverlevel) { +- Brain brain = this.getBrain(); ++ public void refreshBrain(ServerLevel serverLevel) { ++ Brain behaviorcontroller = this.getBrain(); + +- brain.stopAll(serverlevel, this); +- this.brain = brain.copyWithoutBehaviors(); ++ behaviorcontroller.stopAll(serverLevel, this); ++ this.brain = behaviorcontroller.copyWithoutBehaviors(); + this.registerBrainGoals(this.getBrain()); + } + +- private void registerBrainGoals(Brain brain) { ++ private void registerBrainGoals(Brain villagerBrain) { + VillagerProfession villagerprofession = this.getVillagerData().getProfession(); + + if (this.isBaby()) { +- brain.setSchedule(Schedule.VILLAGER_BABY); +- brain.addActivity(Activity.PLAY, VillagerGoalPackages.getPlayPackage(0.5F)); ++ villagerBrain.setSchedule(Schedule.VILLAGER_BABY); ++ villagerBrain.addActivity(Activity.PLAY, VillagerGoalPackages.getPlayPackage(0.5F)); + } else { +- brain.setSchedule(Schedule.VILLAGER_DEFAULT); +- brain.addActivityWithConditions(Activity.WORK, VillagerGoalPackages.getWorkPackage(villagerprofession, 0.5F), ImmutableSet.of(Pair.of(MemoryModuleType.JOB_SITE, MemoryStatus.VALUE_PRESENT))); ++ villagerBrain.setSchedule(Schedule.VILLAGER_DEFAULT); ++ villagerBrain.addActivityWithConditions(Activity.WORK, VillagerGoalPackages.getWorkPackage(villagerprofession, 0.5F), ImmutableSet.of(Pair.of(MemoryModuleType.JOB_SITE, MemoryStatus.VALUE_PRESENT))); + } + +- brain.addActivity(Activity.CORE, VillagerGoalPackages.getCorePackage(villagerprofession, 0.5F)); +- brain.addActivityWithConditions(Activity.MEET, VillagerGoalPackages.getMeetPackage(villagerprofession, 0.5F), ImmutableSet.of(Pair.of(MemoryModuleType.MEETING_POINT, MemoryStatus.VALUE_PRESENT))); +- brain.addActivity(Activity.REST, VillagerGoalPackages.getRestPackage(villagerprofession, 0.5F)); +- brain.addActivity(Activity.IDLE, VillagerGoalPackages.getIdlePackage(villagerprofession, 0.5F)); +- brain.addActivity(Activity.PANIC, VillagerGoalPackages.getPanicPackage(villagerprofession, 0.5F)); +- brain.addActivity(Activity.PRE_RAID, VillagerGoalPackages.getPreRaidPackage(villagerprofession, 0.5F)); +- brain.addActivity(Activity.RAID, VillagerGoalPackages.getRaidPackage(villagerprofession, 0.5F)); +- brain.addActivity(Activity.HIDE, VillagerGoalPackages.getHidePackage(villagerprofession, 0.5F)); +- brain.setCoreActivities(ImmutableSet.of(Activity.CORE)); +- brain.setDefaultActivity(Activity.IDLE); +- brain.setActiveActivityIfPossible(Activity.IDLE); +- brain.updateActivityFromSchedule(this.level().getDayTime(), this.level().getGameTime()); ++ villagerBrain.addActivity(Activity.CORE, VillagerGoalPackages.getCorePackage(villagerprofession, 0.5F)); ++ villagerBrain.addActivityWithConditions(Activity.MEET, VillagerGoalPackages.getMeetPackage(villagerprofession, 0.5F), ImmutableSet.of(Pair.of(MemoryModuleType.MEETING_POINT, MemoryStatus.VALUE_PRESENT))); ++ villagerBrain.addActivity(Activity.REST, VillagerGoalPackages.getRestPackage(villagerprofession, 0.5F)); ++ villagerBrain.addActivity(Activity.IDLE, VillagerGoalPackages.getIdlePackage(villagerprofession, 0.5F)); ++ villagerBrain.addActivity(Activity.PANIC, VillagerGoalPackages.getPanicPackage(villagerprofession, 0.5F)); ++ villagerBrain.addActivity(Activity.PRE_RAID, VillagerGoalPackages.getPreRaidPackage(villagerprofession, 0.5F)); ++ villagerBrain.addActivity(Activity.RAID, VillagerGoalPackages.getRaidPackage(villagerprofession, 0.5F)); ++ villagerBrain.addActivity(Activity.HIDE, VillagerGoalPackages.getHidePackage(villagerprofession, 0.5F)); ++ villagerBrain.setCoreActivities(ImmutableSet.of(Activity.CORE)); ++ villagerBrain.setDefaultActivity(Activity.IDLE); ++ villagerBrain.setActiveActivityIfPossible(Activity.IDLE); ++ villagerBrain.updateActivityFromSchedule(this.level().getDayTime(), this.level().getGameTime()); + } + + @Override +- @Override + protected void ageBoundaryReached() { + super.ageBoundaryReached(); + if (this.level() instanceof ServerLevel) { +@@ -221,7 +224,6 @@ + } + + @Override +- @Override + protected void customServerAiStep() { + this.level().getProfiler().push("villagerBrain"); + this.getBrain().tick((ServerLevel) this.level(), this); +@@ -238,7 +240,7 @@ + this.increaseProfessionLevelOnUpdate = false; + } + +- this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 200, 0)); ++ this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 200, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.VILLAGER_TRADE); // CraftBukkit + } + } + +@@ -264,7 +266,6 @@ + } + + @Override +- @Override + public void tick() { + super.tick(); + if (this.getUnhappyCounter() > 0) { +@@ -275,9 +276,8 @@ + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (!itemstack.is(Items.VILLAGER_SPAWN_EGG) && this.isAlive() && !this.isTrading() && !this.isSleeping()) { + if (this.isBaby()) { +@@ -286,7 +286,7 @@ + } else { + boolean flag = this.getOffers().isEmpty(); + +- if (interactionhand == InteractionHand.MAIN_HAND) { ++ if (hand == EnumHand.MAIN_HAND) { + if (flag && !this.level().isClientSide) { + this.setUnhappy(); + } +@@ -305,11 +305,11 @@ + } + } + } else { +- return super.mobInteract(player, interactionhand); ++ return super.mobInteract(player, hand); + } + } + +- private void setUnhappy() { ++ public void setUnhappy() { + this.setUnhappyCounter(40); + if (!this.level().isClientSide()) { + this.playSound(SoundEvents.VILLAGER_NO, this.getSoundVolume(), this.getVoicePitch()); +@@ -324,7 +324,6 @@ + } + + @Override +- @Override + public void setTradingPlayer(@Nullable Player player) { + boolean flag = this.getTradingPlayer() != null && player == null; + +@@ -336,7 +335,6 @@ + } + + @Override +- @Override + protected void stopTrading() { + super.stopTrading(); + this.resetSpecialPrices(); +@@ -346,21 +344,19 @@ + Iterator iterator = this.getOffers().iterator(); + + while (iterator.hasNext()) { +- MerchantOffer merchantoffer = (MerchantOffer) iterator.next(); ++ MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); + +- merchantoffer.resetSpecialPriceDiff(); ++ merchantrecipe.resetSpecialPriceDiff(); + } + + } + + @Override +- @Override + public boolean canRestock() { + return true; + } + + @Override +- @Override + public boolean isClientSide() { + return this.level().isClientSide; + } +@@ -370,9 +366,15 @@ + Iterator iterator = this.getOffers().iterator(); + + while (iterator.hasNext()) { +- MerchantOffer merchantoffer = (MerchantOffer) iterator.next(); ++ MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); + +- merchantoffer.resetUses(); ++ // CraftBukkit start ++ VillagerReplenishTradeEvent event = new VillagerReplenishTradeEvent((org.bukkit.entity.Villager) this.getBukkitEntity(), merchantrecipe.asBukkit()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ merchantrecipe.resetUses(); ++ } ++ // CraftBukkit end + } + + this.resendOffersToTradingPlayer(); +@@ -381,11 +383,11 @@ + } + + private void resendOffersToTradingPlayer() { +- MerchantOffers merchantoffers = this.getOffers(); +- Player player = this.getTradingPlayer(); ++ MerchantOffers merchantrecipelist = this.getOffers(); ++ Player entityhuman = this.getTradingPlayer(); + +- if (player != null && !merchantoffers.isEmpty()) { +- player.sendMerchantOffers(player.containerMenu.containerId, merchantoffers, this.getVillagerData().getLevel(), this.getVillagerXp(), this.showProgressBar(), this.canRestock()); ++ if (entityhuman != null && !merchantrecipelist.isEmpty()) { ++ entityhuman.sendMerchantOffers(entityhuman.containerMenu.containerId, merchantrecipelist, this.getVillagerData().getLevel(), this.getVillagerXp(), this.showProgressBar(), this.canRestock()); + } + + } +@@ -393,15 +395,15 @@ + private boolean needsToRestock() { + Iterator iterator = this.getOffers().iterator(); + +- MerchantOffer merchantoffer; ++ MerchantOffer merchantrecipe; + + do { + if (!iterator.hasNext()) { + return false; + } + +- merchantoffer = (MerchantOffer) iterator.next(); +- } while (!merchantoffer.needsRestock()); ++ merchantrecipe = (MerchantOffer) iterator.next(); ++ } while (!merchantrecipe.needsRestock()); + + return true; + } +@@ -439,9 +441,15 @@ + Iterator iterator = this.getOffers().iterator(); + + while (iterator.hasNext()) { +- MerchantOffer merchantoffer = (MerchantOffer) iterator.next(); ++ MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); + +- merchantoffer.resetUses(); ++ // CraftBukkit start ++ VillagerReplenishTradeEvent event = new VillagerReplenishTradeEvent((org.bukkit.entity.Villager) this.getBukkitEntity(), merchantrecipe.asBukkit()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ merchantrecipe.resetUses(); ++ } ++ // CraftBukkit end + } + } + +@@ -456,9 +464,9 @@ + Iterator iterator = this.getOffers().iterator(); + + while (iterator.hasNext()) { +- MerchantOffer merchantoffer = (MerchantOffer) iterator.next(); ++ MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); + +- merchantoffer.updateDemand(); ++ merchantrecipe.updateDemand(); + } + + } +@@ -470,157 +478,147 @@ + Iterator iterator = this.getOffers().iterator(); + + while (iterator.hasNext()) { +- MerchantOffer merchantoffer = (MerchantOffer) iterator.next(); ++ MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); + +- merchantoffer.addToSpecialPriceDiff(-Mth.floor((float) i * merchantoffer.getPriceMultiplier())); ++ merchantrecipe.addToSpecialPriceDiff(-Mth.floor((float) i * merchantrecipe.getPriceMultiplier())); + } + } + + if (player.hasEffect(MobEffects.HERO_OF_THE_VILLAGE)) { +- MobEffectInstance mobeffectinstance = player.getEffect(MobEffects.HERO_OF_THE_VILLAGE); +- int j = mobeffectinstance.getAmplifier(); ++ MobEffectInstance mobeffect = player.getEffect(MobEffects.HERO_OF_THE_VILLAGE); ++ int j = mobeffect.getAmplifier(); + Iterator iterator1 = this.getOffers().iterator(); + + while (iterator1.hasNext()) { +- MerchantOffer merchantoffer1 = (MerchantOffer) iterator1.next(); ++ MerchantOffer merchantrecipe1 = (MerchantOffer) iterator1.next(); + double d0 = 0.3D + 0.0625D * (double) j; +- int k = (int) Math.floor(d0 * (double) merchantoffer1.getBaseCostA().getCount()); ++ int k = (int) Math.floor(d0 * (double) merchantrecipe1.getBaseCostA().getCount()); + +- merchantoffer1.addToSpecialPriceDiff(-Math.max(k, 1)); ++ merchantrecipe1.addToSpecialPriceDiff(-Math.max(k, 1)); + } + } + + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Villager.DATA_VILLAGER_DATA, new VillagerData(VillagerType.PLAINS, VillagerProfession.NONE, 1)); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- DataResult dataresult = VillagerData.CODEC.encodeStart(NbtOps.INSTANCE, this.getVillagerData()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ DataResult dataresult = VillagerData.CODEC.encodeStart(NbtOps.INSTANCE, this.getVillagerData()); // CraftBukkit - decompile error + Logger logger = Villager.LOGGER; + + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((tag) -> { +- compoundtag.put("VillagerData", tag); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("VillagerData", nbtbase); + }); +- compoundtag.putByte("FoodLevel", (byte) this.foodLevel); +- compoundtag.put("Gossips", (Tag) this.gossips.store(NbtOps.INSTANCE)); +- compoundtag.putInt("Xp", this.villagerXp); +- compoundtag.putLong("LastRestock", this.lastRestockGameTime); +- compoundtag.putLong("LastGossipDecay", this.lastGossipDecayTime); +- compoundtag.putInt("RestocksToday", this.numberOfRestocksToday); ++ compound.putByte("FoodLevel", (byte) this.foodLevel); ++ compound.put("Gossips", (Tag) this.gossips.store(NbtOps.INSTANCE)); ++ compound.putInt("Xp", this.villagerXp); ++ compound.putLong("LastRestock", this.lastRestockGameTime); ++ compound.putLong("LastGossipDecay", this.lastGossipDecayTime); ++ compound.putInt("RestocksToday", this.numberOfRestocksToday); + if (this.assignProfessionWhenSpawned) { +- compoundtag.putBoolean("AssignProfessionWhenSpawned", true); ++ compound.putBoolean("AssignProfessionWhenSpawned", true); + } + + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("VillagerData", 10)) { +- DataResult dataresult = VillagerData.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compoundtag.get("VillagerData"))); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("VillagerData", 10)) { ++ DataResult dataresult = VillagerData.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compound.get("VillagerData"))); + Logger logger = Villager.LOGGER; + + Objects.requireNonNull(logger); + dataresult.resultOrPartial(logger::error).ifPresent(this::setVillagerData); + } + +- if (compoundtag.contains("Offers", 10)) { +- this.offers = new MerchantOffers(compoundtag.getCompound("Offers")); ++ if (compound.contains("Offers", 10)) { ++ this.offers = new MerchantOffers(compound.getCompound("Offers")); + } + +- if (compoundtag.contains("FoodLevel", 1)) { +- this.foodLevel = compoundtag.getByte("FoodLevel"); ++ if (compound.contains("FoodLevel", 1)) { ++ this.foodLevel = compound.getByte("FoodLevel"); + } + +- ListTag listtag = compoundtag.getList("Gossips", 10); ++ ListTag nbttaglist = compound.getList("Gossips", 10); + +- this.gossips.update(new Dynamic(NbtOps.INSTANCE, listtag)); +- if (compoundtag.contains("Xp", 3)) { +- this.villagerXp = compoundtag.getInt("Xp"); ++ this.gossips.update(new Dynamic(NbtOps.INSTANCE, nbttaglist)); ++ if (compound.contains("Xp", 3)) { ++ this.villagerXp = compound.getInt("Xp"); + } + +- this.lastRestockGameTime = compoundtag.getLong("LastRestock"); +- this.lastGossipDecayTime = compoundtag.getLong("LastGossipDecay"); ++ this.lastRestockGameTime = compound.getLong("LastRestock"); ++ this.lastGossipDecayTime = compound.getLong("LastGossipDecay"); + this.setCanPickUpLoot(true); + if (this.level() instanceof ServerLevel) { + this.refreshBrain((ServerLevel) this.level()); + } + +- this.numberOfRestocksToday = compoundtag.getInt("RestocksToday"); +- if (compoundtag.contains("AssignProfessionWhenSpawned")) { +- this.assignProfessionWhenSpawned = compoundtag.getBoolean("AssignProfessionWhenSpawned"); ++ this.numberOfRestocksToday = compound.getInt("RestocksToday"); ++ if (compound.contains("AssignProfessionWhenSpawned")) { ++ this.assignProfessionWhenSpawned = compound.getBoolean("AssignProfessionWhenSpawned"); + } + + } + + @Override +- @Override +- public boolean removeWhenFarAway(double d0) { ++ public boolean removeWhenFarAway(double distanceToClosestPlayer) { + return false; + } + + @Nullable + @Override +- @Override + protected SoundEvent getAmbientSound() { + return this.isSleeping() ? null : (this.isTrading() ? SoundEvents.VILLAGER_TRADE : SoundEvents.VILLAGER_AMBIENT); + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.VILLAGER_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.VILLAGER_DEATH; + } + + public void playWorkSound() { +- SoundEvent soundevent = this.getVillagerData().getProfession().workSound(); ++ SoundEvent soundeffect = this.getVillagerData().getProfession().workSound(); + +- if (soundevent != null) { +- this.playSound(soundevent, this.getSoundVolume(), this.getVoicePitch()); ++ if (soundeffect != null) { ++ this.playSound(soundeffect, this.getSoundVolume(), this.getVoicePitch()); + } + + } + + @Override +- @Override +- public void setVillagerData(VillagerData villagerdata) { ++ public void setVillagerData(VillagerData data) { + VillagerData villagerdata1 = this.getVillagerData(); + +- if (villagerdata1.getProfession() != villagerdata.getProfession()) { ++ if (villagerdata1.getProfession() != data.getProfession()) { + this.offers = null; + } + +- this.entityData.set(Villager.DATA_VILLAGER_DATA, villagerdata); ++ this.entityData.set(Villager.DATA_VILLAGER_DATA, data); + } + + @Override +- @Override + public VillagerData getVillagerData() { + return (VillagerData) this.entityData.get(Villager.DATA_VILLAGER_DATA); + } + + @Override +- @Override +- protected void rewardTradeXp(MerchantOffer merchantoffer) { ++ protected void rewardTradeXp(MerchantOffer offer) { + int i = 3 + this.random.nextInt(4); + +- this.villagerXp += merchantoffer.getXp(); ++ this.villagerXp += offer.getXp(); + this.lastTradedPlayer = this.getTradingPlayer(); + if (this.shouldIncreaseLevel()) { + this.updateMerchantTimer = 40; +@@ -628,14 +626,14 @@ + i += 5; + } + +- if (merchantoffer.shouldRewardExp()) { ++ if (offer.shouldRewardExp()) { + this.level().addFreshEntity(new ExperienceOrb(this.level(), this.getX(), this.getY() + 0.5D, this.getZ(), i)); + } + + } + +- public void setChasing(boolean flag) { +- this.chasing = flag; ++ public void setChasing(boolean chasing) { ++ this.chasing = chasing; + } + + public boolean isChasing() { +@@ -643,72 +641,70 @@ + } + + @Override +- @Override +- public void setLastHurtByMob(@Nullable LivingEntity livingentity) { +- if (livingentity != null && this.level() instanceof ServerLevel) { +- ((ServerLevel) this.level()).onReputationEvent(ReputationEventType.VILLAGER_HURT, livingentity, this); +- if (this.isAlive() && livingentity instanceof Player) { ++ public void setLastHurtByMob(@Nullable LivingEntity livingBase) { ++ if (livingBase != null && this.level() instanceof ServerLevel) { ++ ((ServerLevel) this.level()).onReputationEvent(ReputationEventType.VILLAGER_HURT, livingBase, this); ++ if (this.isAlive() && livingBase instanceof Player) { + this.level().broadcastEntityEvent(this, (byte) 13); + } + } + +- super.setLastHurtByMob(livingentity); ++ super.setLastHurtByMob(livingBase); + } + + @Override +- @Override +- public void die(DamageSource damagesource) { +- Villager.LOGGER.info("Villager {} died, message: '{}'", this, damagesource.getLocalizedDeathMessage(this).getString()); +- Entity entity = damagesource.getEntity(); ++ public void die(DamageSource cause) { ++ Villager.LOGGER.info("Villager {} died, message: '{}'", this, cause.getLocalizedDeathMessage(this).getString()); ++ Entity entity = cause.getEntity(); + + if (entity != null) { + this.tellWitnessesThatIWasMurdered(entity); + } + + this.releaseAllPois(); +- super.die(damagesource); ++ super.die(cause); + } + +- private void releaseAllPois() { ++ public void releaseAllPois() { + this.releasePoi(MemoryModuleType.HOME); + this.releasePoi(MemoryModuleType.JOB_SITE); + this.releasePoi(MemoryModuleType.POTENTIAL_JOB_SITE); + this.releasePoi(MemoryModuleType.MEETING_POINT); + } + +- private void tellWitnessesThatIWasMurdered(Entity entity) { +- Level level = this.level(); ++ private void tellWitnessesThatIWasMurdered(Entity murderer) { ++ Level world = this.level(); + +- if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; + Optional optional = this.brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES); + + if (!optional.isEmpty()) { + NearestVisibleLivingEntities nearestvisiblelivingentities = (NearestVisibleLivingEntities) optional.get(); + + Objects.requireNonNull(ReputationEventHandler.class); +- nearestvisiblelivingentities.findAll(ReputationEventHandler.class::isInstance).forEach((livingentity) -> { +- serverlevel.onReputationEvent(ReputationEventType.VILLAGER_KILLED, entity, (ReputationEventHandler) livingentity); ++ nearestvisiblelivingentities.findAll(ReputationEventHandler.class::isInstance).forEach((entityliving) -> { ++ worldserver.onReputationEvent(ReputationEventType.VILLAGER_KILLED, murderer, (ReputationEventHandler) entityliving); + }); + } + } + } + +- public void releasePoi(MemoryModuleType memorymoduletype) { ++ public void releasePoi(MemoryModuleType moduleType) { + if (this.level() instanceof ServerLevel) { + MinecraftServer minecraftserver = ((ServerLevel) this.level()).getServer(); + +- this.brain.getMemory(memorymoduletype).ifPresent((globalpos) -> { +- ServerLevel serverlevel = minecraftserver.getLevel(globalpos.dimension()); ++ this.brain.getMemory(moduleType).ifPresent((globalpos) -> { ++ ServerLevel worldserver = minecraftserver.getLevel(globalpos.dimension()); + +- if (serverlevel != null) { +- PoiManager poimanager = serverlevel.getPoiManager(); +- Optional> optional = poimanager.getType(globalpos.pos()); +- BiPredicate> bipredicate = (BiPredicate) Villager.POI_MEMORIES.get(memorymoduletype); ++ if (worldserver != null) { ++ PoiManager villageplace = worldserver.getPoiManager(); ++ Optional> optional = villageplace.getType(globalpos.pos()); ++ BiPredicate> bipredicate = (BiPredicate) Villager.POI_MEMORIES.get(moduleType); + + if (optional.isPresent() && bipredicate.test(this, (Holder) optional.get())) { +- poimanager.release(globalpos.pos()); +- DebugPackets.sendPoiTicketCountPacket(serverlevel, globalpos.pos()); ++ villageplace.release(globalpos.pos()); ++ DebugPackets.sendPoiTicketCountPacket(worldserver, globalpos.pos()); + } + + } +@@ -717,7 +713,6 @@ + } + + @Override +- @Override + public boolean canBreed() { + return this.foodLevel + this.countFoodPointsInInventory() >= 12 && !this.isSleeping() && this.getAge() == 0; + } +@@ -752,13 +747,13 @@ + } + + public int getPlayerReputation(Player player) { +- return this.gossips.getReputation(player.getUUID(), (gossiptype) -> { ++ return this.gossips.getReputation(player.getUUID(), (reputationtype) -> { + return true; + }); + } + +- private void digestFood(int i) { +- this.foodLevel -= i; ++ private void digestFood(int qty) { ++ this.foodLevel -= qty; + } + + public void eatAndDigestFood() { +@@ -766,8 +761,8 @@ + this.digestFood(12); + } + +- public void setOffers(MerchantOffers merchantoffers) { +- this.offers = merchantoffers; ++ public void setOffers(MerchantOffers offers) { ++ this.offers = offers; + } + + private boolean shouldIncreaseLevel() { +@@ -776,13 +771,12 @@ + return VillagerData.canLevelUp(i) && this.villagerXp >= VillagerData.getMaxXpPerLevel(i); + } + +- private void increaseMerchantCareer() { ++ public void increaseMerchantCareer() { + this.setVillagerData(this.getVillagerData().setLevel(this.getVillagerData().getLevel() + 1)); + this.updateTrades(); + } + + @Override +- @Override + protected Component getTypeName() { + String s = this.getType().getDescriptionId(); + +@@ -790,103 +784,102 @@ + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 12) { ++ public void handleEntityEvent(byte id) { ++ if (id == 12) { + this.addParticlesAroundSelf(ParticleTypes.HEART); +- } else if (b0 == 13) { ++ } else if (id == 13) { + this.addParticlesAroundSelf(ParticleTypes.ANGRY_VILLAGER); +- } else if (b0 == 14) { ++ } else if (id == 14) { + this.addParticlesAroundSelf(ParticleTypes.HAPPY_VILLAGER); +- } else if (b0 == 42) { ++ } else if (id == 42) { + this.addParticlesAroundSelf(ParticleTypes.SPLASH); + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- if (mobspawntype == MobSpawnType.BREEDING) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ if (reason == EnumMobSpawn.BREEDING) { + this.setVillagerData(this.getVillagerData().setProfession(VillagerProfession.NONE)); + } + +- if (mobspawntype == MobSpawnType.COMMAND || mobspawntype == MobSpawnType.SPAWN_EGG || MobSpawnType.isSpawner(mobspawntype) || mobspawntype == MobSpawnType.DISPENSER) { +- this.setVillagerData(this.getVillagerData().setType(VillagerType.byBiome(serverlevelaccessor.getBiome(this.blockPosition())))); ++ if (reason == EnumMobSpawn.COMMAND || reason == EnumMobSpawn.SPAWN_EGG || EnumMobSpawn.isSpawner(reason) || reason == EnumMobSpawn.DISPENSER) { ++ this.setVillagerData(this.getVillagerData().setType(VillagerType.byBiome(level.getBiome(this.blockPosition())))); + } + +- if (mobspawntype == MobSpawnType.STRUCTURE) { ++ if (reason == EnumMobSpawn.STRUCTURE) { + this.assignProfessionWhenSpawned = true; + } + +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); ++ return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + + @Nullable + @Override +- @Override +- public Villager getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { ++ public Villager getBreedOffspring(ServerLevel level, AgeableMob otherParent) { + double d0 = this.random.nextDouble(); + VillagerType villagertype; + + if (d0 < 0.5D) { +- villagertype = VillagerType.byBiome(serverlevel.getBiome(this.blockPosition())); ++ villagertype = VillagerType.byBiome(level.getBiome(this.blockPosition())); + } else if (d0 < 0.75D) { + villagertype = this.getVillagerData().getType(); + } else { +- villagertype = ((Villager) ageablemob).getVillagerData().getType(); ++ villagertype = ((Villager) otherParent).getVillagerData().getType(); + } + +- Villager villager = new Villager(EntityType.VILLAGER, serverlevel, villagertype); ++ Villager entityvillager = new Villager(EntityType.VILLAGER, level, villagertype); + +- villager.finalizeSpawn(serverlevel, serverlevel.getCurrentDifficultyAt(villager.blockPosition()), MobSpawnType.BREEDING, (SpawnGroupData) null, (CompoundTag) null); +- return villager; ++ entityvillager.finalizeSpawn(level, level.getCurrentDifficultyAt(entityvillager.blockPosition()), EnumMobSpawn.BREEDING, (GroupDataEntity) null, (CompoundTag) null); ++ return entityvillager; + } + + @Override +- @Override +- public void thunderHit(ServerLevel serverlevel, LightningBolt lightningbolt) { +- if (serverlevel.getDifficulty() != Difficulty.PEACEFUL) { +- Villager.LOGGER.info("Villager {} was struck by lightning {}.", this, lightningbolt); +- Witch witch = (Witch) EntityType.WITCH.create(serverlevel); ++ public void thunderHit(ServerLevel level, LightningBolt lightning) { ++ if (level.getDifficulty() != Difficulty.PEACEFUL) { ++ Villager.LOGGER.info("Villager {} was struck by lightning {}.", this, lightning); ++ Witch entitywitch = (Witch) EntityType.WITCH.create(level); + +- if (witch != null) { +- witch.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); +- witch.finalizeSpawn(serverlevel, serverlevel.getCurrentDifficultyAt(witch.blockPosition()), MobSpawnType.CONVERSION, (SpawnGroupData) null, (CompoundTag) null); +- witch.setNoAi(this.isNoAi()); ++ if (entitywitch != null) { ++ entitywitch.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); ++ entitywitch.finalizeSpawn(level, level.getCurrentDifficultyAt(entitywitch.blockPosition()), EnumMobSpawn.CONVERSION, (GroupDataEntity) null, (CompoundTag) null); ++ entitywitch.setNoAi(this.isNoAi()); + if (this.hasCustomName()) { +- witch.setCustomName(this.getCustomName()); +- witch.setCustomNameVisible(this.isCustomNameVisible()); ++ entitywitch.setCustomName(this.getCustomName()); ++ entitywitch.setCustomNameVisible(this.isCustomNameVisible()); + } + +- witch.setPersistenceRequired(); +- serverlevel.addFreshEntityWithPassengers(witch); ++ entitywitch.setPersistenceRequired(); ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, entitywitch, EntityTransformEvent.TransformReason.LIGHTNING).isCancelled()) { ++ return; ++ } ++ level.addFreshEntityWithPassengers(entitywitch, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); ++ // CraftBukkit end + this.releaseAllPois(); + this.discard(); + } else { +- super.thunderHit(serverlevel, lightningbolt); ++ super.thunderHit(level, lightning); + } + } else { +- super.thunderHit(serverlevel, lightningbolt); ++ super.thunderHit(level, lightning); + } + + } + + @Override +- @Override +- protected void pickUpItem(ItemEntity itementity) { +- InventoryCarrier.pickUpItem(this, this, itementity); ++ protected void pickUpItem(ItemEntity itemEntity) { ++ InventoryCarrier.pickUpItem(this, this, itemEntity); + } + + @Override +- @Override +- public boolean wantsToPickUp(ItemStack itemstack) { +- Item item = itemstack.getItem(); ++ public boolean wantsToPickUp(ItemStack stack) { ++ Item item = stack.getItem(); + +- return (Villager.WANTED_ITEMS.contains(item) || this.getVillagerData().getProfession().requestedItems().contains(item)) && this.getInventory().canAddItem(itemstack); ++ return (Villager.WANTED_ITEMS.contains(item) || this.getVillagerData().getProfession().requestedItems().contains(item)) && this.getInventory().canAddItem(stack); + } + + public boolean hasExcessFood() { +@@ -898,10 +891,10 @@ + } + + private int countFoodPointsInInventory() { +- SimpleContainer simplecontainer = this.getInventory(); ++ SimpleContainer inventorysubcontainer = this.getInventory(); + + return Villager.FOOD_POINTS.entrySet().stream().mapToInt((entry) -> { +- return simplecontainer.countItem((Item) entry.getKey()) * (Integer) entry.getValue(); ++ return inventorysubcontainer.countItem((Item) entry.getKey()) * (Integer) entry.getValue(); + }).sum(); + } + +@@ -912,7 +905,6 @@ + } + + @Override +- @Override + protected void updateTrades() { + VillagerData villagerdata = this.getVillagerData(); + Int2ObjectMap int2objectmap; +@@ -926,22 +918,22 @@ + } + + if (int2objectmap != null && !int2objectmap.isEmpty()) { +- VillagerTrades.ItemListing[] avillagertrades_itemlisting = (VillagerTrades.ItemListing[]) int2objectmap.get(villagerdata.getLevel()); ++ VillagerTrades.ItemListing[] avillagertrades_imerchantrecipeoption = (VillagerTrades.ItemListing[]) int2objectmap.get(villagerdata.getLevel()); + +- if (avillagertrades_itemlisting != null) { +- MerchantOffers merchantoffers = this.getOffers(); ++ if (avillagertrades_imerchantrecipeoption != null) { ++ MerchantOffers merchantrecipelist = this.getOffers(); + +- this.addOffersFromItemListings(merchantoffers, avillagertrades_itemlisting, 2); ++ this.addOffersFromItemListings(merchantrecipelist, avillagertrades_imerchantrecipeoption, 2); + } + } + } + +- public void gossip(ServerLevel serverlevel, Villager villager, long i) { +- if ((i < this.lastGossipTime || i >= this.lastGossipTime + 1200L) && (i < villager.lastGossipTime || i >= villager.lastGossipTime + 1200L)) { +- this.gossips.transferFrom(villager.gossips, this.random, 10); +- this.lastGossipTime = i; +- villager.lastGossipTime = i; +- this.spawnGolemIfNeeded(serverlevel, i, 5); ++ public void gossip(ServerLevel serverLevel, Villager target, long gameTime) { ++ if ((gameTime < this.lastGossipTime || gameTime >= this.lastGossipTime + 1200L) && (gameTime < target.lastGossipTime || gameTime >= target.lastGossipTime + 1200L)) { ++ this.gossips.transferFrom(target.gossips, this.random, 10); ++ this.lastGossipTime = gameTime; ++ target.lastGossipTime = gameTime; ++ this.spawnGolemIfNeeded(serverLevel, gameTime, 5); + } + } + +@@ -956,50 +948,48 @@ + } + } + +- public void spawnGolemIfNeeded(ServerLevel serverlevel, long i, int j) { +- if (this.wantsToSpawnGolem(i)) { +- AABB aabb = this.getBoundingBox().inflate(10.0D, 10.0D, 10.0D); +- List list = serverlevel.getEntitiesOfClass(Villager.class, aabb); +- List list1 = (List) list.stream().filter((villager) -> { +- return villager.wantsToSpawnGolem(i); ++ public void spawnGolemIfNeeded(ServerLevel serverLevel, long gameTime, int j) { ++ if (this.wantsToSpawnGolem(gameTime)) { ++ AABB axisalignedbb = this.getBoundingBox().inflate(10.0D, 10.0D, 10.0D); ++ List list = serverLevel.getEntitiesOfClass(Villager.class, axisalignedbb); ++ List list1 = (List) list.stream().filter((entityvillager) -> { ++ return entityvillager.wantsToSpawnGolem(gameTime); + }).limit(5L).collect(Collectors.toList()); + + if (list1.size() >= j) { +- if (!SpawnUtil.trySpawnMob(EntityType.IRON_GOLEM, MobSpawnType.MOB_SUMMONED, serverlevel, this.blockPosition(), 10, 8, 6, SpawnUtil.Strategy.LEGACY_IRON_GOLEM).isEmpty()) { ++ if (!SpawnUtil.trySpawnMob(EntityType.IRON_GOLEM, EnumMobSpawn.MOB_SUMMONED, serverLevel, this.blockPosition(), 10, 8, 6, SpawnUtil.Strategy.LEGACY_IRON_GOLEM, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE).isEmpty()) { // CraftBukkit + list.forEach(GolemSensor::golemDetected); + } + } + } + } + +- public boolean wantsToSpawnGolem(long i) { ++ public boolean wantsToSpawnGolem(long gameTime) { + return !this.golemSpawnConditionsMet(this.level().getGameTime()) ? false : !this.brain.hasMemoryValue(MemoryModuleType.GOLEM_DETECTED_RECENTLY); + } + + @Override +- @Override +- public void onReputationEventFrom(ReputationEventType reputationeventtype, Entity entity) { +- if (reputationeventtype == ReputationEventType.ZOMBIE_VILLAGER_CURED) { +- this.gossips.add(entity.getUUID(), GossipType.MAJOR_POSITIVE, 20); +- this.gossips.add(entity.getUUID(), GossipType.MINOR_POSITIVE, 25); +- } else if (reputationeventtype == ReputationEventType.TRADE) { +- this.gossips.add(entity.getUUID(), GossipType.TRADING, 2); +- } else if (reputationeventtype == ReputationEventType.VILLAGER_HURT) { +- this.gossips.add(entity.getUUID(), GossipType.MINOR_NEGATIVE, 25); +- } else if (reputationeventtype == ReputationEventType.VILLAGER_KILLED) { +- this.gossips.add(entity.getUUID(), GossipType.MAJOR_NEGATIVE, 25); ++ public void onReputationEventFrom(ReputationEventType type, Entity target) { ++ if (type == ReputationEventType.ZOMBIE_VILLAGER_CURED) { ++ this.gossips.add(target.getUUID(), GossipType.MAJOR_POSITIVE, 20); ++ this.gossips.add(target.getUUID(), GossipType.MINOR_POSITIVE, 25); ++ } else if (type == ReputationEventType.TRADE) { ++ this.gossips.add(target.getUUID(), GossipType.TRADING, 2); ++ } else if (type == ReputationEventType.VILLAGER_HURT) { ++ this.gossips.add(target.getUUID(), GossipType.MINOR_NEGATIVE, 25); ++ } else if (type == ReputationEventType.VILLAGER_KILLED) { ++ this.gossips.add(target.getUUID(), GossipType.MAJOR_NEGATIVE, 25); + } + + } + + @Override +- @Override + public int getVillagerXp() { + return this.villagerXp; + } + +- public void setVillagerXp(int i) { +- this.villagerXp = i; ++ public void setVillagerXp(int villagerXp) { ++ this.villagerXp = villagerXp; + } + + private void resetNumberOfRestocks() { +@@ -1011,36 +1001,33 @@ + return this.gossips; + } + +- public void setGossips(Tag tag) { +- this.gossips.update(new Dynamic(NbtOps.INSTANCE, tag)); ++ public void setGossips(Tag gossip) { ++ this.gossips.update(new Dynamic(NbtOps.INSTANCE, gossip)); + } + + @Override +- @Override + protected void sendDebugPackets() { + super.sendDebugPackets(); + DebugPackets.sendEntityBrain(this); + } + + @Override +- @Override +- public void startSleeping(BlockPos blockpos) { +- super.startSleeping(blockpos); +- this.brain.setMemory(MemoryModuleType.LAST_SLEPT, (Object) this.level().getGameTime()); ++ public void startSleeping(BlockPos pos) { ++ super.startSleeping(pos); ++ this.brain.setMemory(MemoryModuleType.LAST_SLEPT, this.level().getGameTime()); // CraftBukkit - decompile error + this.brain.eraseMemory(MemoryModuleType.WALK_TARGET); + this.brain.eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE); + } + + @Override +- @Override + public void stopSleeping() { + super.stopSleeping(); +- this.brain.setMemory(MemoryModuleType.LAST_WOKEN, (Object) this.level().getGameTime()); ++ this.brain.setMemory(MemoryModuleType.LAST_WOKEN, this.level().getGameTime()); // CraftBukkit - decompile error + } + +- private boolean golemSpawnConditionsMet(long i) { ++ private boolean golemSpawnConditionsMet(long gameTime) { + Optional optional = this.brain.getMemory(MemoryModuleType.LAST_SLEPT); + +- return optional.isPresent() ? i - (Long) optional.get() < 24000L : false; ++ return optional.isPresent() ? gameTime - (Long) optional.get() < 24000L : false; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/WanderingTrader.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/WanderingTrader.java.patch new file mode 100644 index 0000000000..1977fd62f4 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/WanderingTrader.java.patch @@ -0,0 +1,356 @@ +--- a/net/minecraft/world/entity/npc/WanderingTrader.java ++++ b/net/minecraft/world/entity/npc/WanderingTrader.java +@@ -10,7 +10,7 @@ + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; +@@ -20,11 +20,11 @@ + import net.minecraft.world.entity.ai.goal.AvoidEntityGoal; + import net.minecraft.world.entity.ai.goal.FloatGoal; + import net.minecraft.world.entity.ai.goal.Goal; +-import net.minecraft.world.entity.ai.goal.InteractGoal; + import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; + import net.minecraft.world.entity.ai.goal.LookAtTradingPlayerGoal; + import net.minecraft.world.entity.ai.goal.MoveTowardsRestrictionGoal; + import net.minecraft.world.entity.ai.goal.PanicGoal; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalInteract; + import net.minecraft.world.entity.ai.goal.TradeWithPlayerGoal; + import net.minecraft.world.entity.ai.goal.UseItemGoal; + import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal; +@@ -47,26 +47,33 @@ + import net.minecraft.world.phys.Vec3; + import org.apache.commons.lang3.tuple.Pair; + +-public class WanderingTrader extends AbstractVillager { ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; ++import org.bukkit.entity.AbstractVillager; ++import org.bukkit.event.entity.VillagerAcquireTradeEvent; ++// CraftBukkit end + ++public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVillager { ++ + private static final int NUMBER_OF_TRADE_OFFERS = 5; + @Nullable + private BlockPos wanderTarget; + private int despawnDelay; + +- public WanderingTrader(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public WanderingTrader(EntityType entityType, Level level) { ++ super(entityType, level); ++ this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader + } + + @Override +- @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); +- this.goalSelector.addGoal(0, new UseItemGoal<>(this, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.INVISIBILITY), SoundEvents.WANDERING_TRADER_DISAPPEARED, (wanderingtrader) -> { +- return this.level().isNight() && !wanderingtrader.isInvisible(); ++ this.goalSelector.addGoal(0, new UseItemGoal<>(this, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.INVISIBILITY), SoundEvents.WANDERING_TRADER_DISAPPEARED, (entityvillagertrader) -> { ++ return this.level().isNight() && !entityvillagertrader.isInvisible(); + })); +- this.goalSelector.addGoal(0, new UseItemGoal<>(this, new ItemStack(Items.MILK_BUCKET), SoundEvents.WANDERING_TRADER_REAPPEARED, (wanderingtrader) -> { +- return this.level().isDay() && wanderingtrader.isInvisible(); ++ this.goalSelector.addGoal(0, new UseItemGoal<>(this, new ItemStack(Items.MILK_BUCKET), SoundEvents.WANDERING_TRADER_REAPPEARED, (entityvillagertrader) -> { ++ return this.level().isDay() && entityvillagertrader.isInvisible(); + })); + this.goalSelector.addGoal(1, new TradeWithPlayerGoal(this)); + this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Zombie.class, 8.0F, 0.5D, 0.5D)); +@@ -81,30 +88,27 @@ + this.goalSelector.addGoal(2, new WanderingTrader.WanderToPositionGoal(this, 2.0D, 0.35D)); + this.goalSelector.addGoal(4, new MoveTowardsRestrictionGoal(this, 0.35D)); + this.goalSelector.addGoal(8, new WaterAvoidingRandomStrollGoal(this, 0.35D)); +- this.goalSelector.addGoal(9, new InteractGoal(this, Player.class, 3.0F, 1.0F)); ++ this.goalSelector.addGoal(9, new PathfinderGoalInteract(this, Player.class, 3.0F, 1.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); + } + + @Nullable + @Override +- @Override +- public AgeableMob getBreedOffspring(ServerLevel serverlevel, AgeableMob ageablemob) { ++ public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob otherParent) { + return null; + } + + @Override +- @Override + public boolean showProgressBar() { + return false; + } + + @Override +- @Override +- public InteractionResult mobInteract(Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (!itemstack.is(Items.VILLAGER_SPAWN_EGG) && this.isAlive() && !this.isTrading() && !this.isBaby()) { +- if (interactionhand == InteractionHand.MAIN_HAND) { ++ if (hand == EnumHand.MAIN_HAND) { + player.awardStat(Stats.TALKED_TO_VILLAGER); + } + +@@ -119,29 +123,37 @@ + return InteractionResult.sidedSuccess(this.level().isClientSide); + } + } else { +- return super.mobInteract(player, interactionhand); ++ return super.mobInteract(player, hand); + } + } + + @Override +- @Override + protected void updateTrades() { + if (this.level().enabledFeatures().contains(FeatureFlags.TRADE_REBALANCE)) { + this.experimentalUpdateTrades(); + } else { +- VillagerTrades.ItemListing[] avillagertrades_itemlisting = (VillagerTrades.ItemListing[]) VillagerTrades.WANDERING_TRADER_TRADES.get(1); +- VillagerTrades.ItemListing[] avillagertrades_itemlisting1 = (VillagerTrades.ItemListing[]) VillagerTrades.WANDERING_TRADER_TRADES.get(2); ++ VillagerTrades.ItemListing[] avillagertrades_imerchantrecipeoption = (VillagerTrades.ItemListing[]) VillagerTrades.WANDERING_TRADER_TRADES.get(1); ++ VillagerTrades.ItemListing[] avillagertrades_imerchantrecipeoption1 = (VillagerTrades.ItemListing[]) VillagerTrades.WANDERING_TRADER_TRADES.get(2); + +- if (avillagertrades_itemlisting != null && avillagertrades_itemlisting1 != null) { +- MerchantOffers merchantoffers = this.getOffers(); ++ if (avillagertrades_imerchantrecipeoption != null && avillagertrades_imerchantrecipeoption1 != null) { ++ MerchantOffers merchantrecipelist = this.getOffers(); + +- this.addOffersFromItemListings(merchantoffers, avillagertrades_itemlisting, 5); +- int i = this.random.nextInt(avillagertrades_itemlisting1.length); +- VillagerTrades.ItemListing villagertrades_itemlisting = avillagertrades_itemlisting1[i]; +- MerchantOffer merchantoffer = villagertrades_itemlisting.getOffer(this, this.random); ++ this.addOffersFromItemListings(merchantrecipelist, avillagertrades_imerchantrecipeoption, 5); ++ int i = this.random.nextInt(avillagertrades_imerchantrecipeoption1.length); ++ VillagerTrades.ItemListing villagertrades_imerchantrecipeoption = avillagertrades_imerchantrecipeoption1[i]; ++ MerchantOffer merchantrecipe = villagertrades_imerchantrecipeoption.getOffer(this, this.random); + +- if (merchantoffer != null) { +- merchantoffers.add(merchantoffer); ++ if (merchantrecipe != null) { ++ // CraftBukkit start ++ VillagerAcquireTradeEvent event = new VillagerAcquireTradeEvent((AbstractVillager) getBukkitEntity(), merchantrecipe.asBukkit()); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ if (!event.isCancelled()) { ++ merchantrecipelist.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); ++ } ++ // CraftBukkit end + } + + } +@@ -149,54 +161,50 @@ + } + + private void experimentalUpdateTrades() { +- MerchantOffers merchantoffers = this.getOffers(); ++ MerchantOffers merchantrecipelist = this.getOffers(); + Iterator iterator = VillagerTrades.EXPERIMENTAL_WANDERING_TRADER_TRADES.iterator(); + + while (iterator.hasNext()) { + Pair pair = (Pair) iterator.next(); +- VillagerTrades.ItemListing[] avillagertrades_itemlisting = (VillagerTrades.ItemListing[]) pair.getLeft(); ++ VillagerTrades.ItemListing[] avillagertrades_imerchantrecipeoption = (VillagerTrades.ItemListing[]) pair.getLeft(); + +- this.addOffersFromItemListings(merchantoffers, avillagertrades_itemlisting, (Integer) pair.getRight()); ++ this.addOffersFromItemListings(merchantrecipelist, avillagertrades_imerchantrecipeoption, (Integer) pair.getRight()); + } + + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("DespawnDelay", this.despawnDelay); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("DespawnDelay", this.despawnDelay); + if (this.wanderTarget != null) { +- compoundtag.put("WanderTarget", NbtUtils.writeBlockPos(this.wanderTarget)); ++ compound.put("WanderTarget", NbtUtils.writeBlockPos(this.wanderTarget)); + } + + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("DespawnDelay", 99)) { +- this.despawnDelay = compoundtag.getInt("DespawnDelay"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("DespawnDelay", 99)) { ++ this.despawnDelay = compound.getInt("DespawnDelay"); + } + +- if (compoundtag.contains("WanderTarget")) { +- this.wanderTarget = NbtUtils.readBlockPos(compoundtag.getCompound("WanderTarget")); ++ if (compound.contains("WanderTarget")) { ++ this.wanderTarget = NbtUtils.readBlockPos(compound.getCompound("WanderTarget")); + } + + this.setAge(Math.max(0, this.getAge())); + } + + @Override +- @Override +- public boolean removeWhenFarAway(double d0) { ++ public boolean removeWhenFarAway(double distanceToClosestPlayer) { + return false; + } + + @Override +- @Override +- protected void rewardTradeXp(MerchantOffer merchantoffer) { +- if (merchantoffer.shouldRewardExp()) { ++ protected void rewardTradeXp(MerchantOffer offer) { ++ if (offer.shouldRewardExp()) { + int i = 3 + this.random.nextInt(4); + + this.level().addFreshEntity(new ExperienceOrb(this.level(), this.getX(), this.getY() + 0.5D, this.getZ(), i)); +@@ -205,43 +213,37 @@ + } + + @Override +- @Override + protected SoundEvent getAmbientSound() { + return this.isTrading() ? SoundEvents.WANDERING_TRADER_TRADE : SoundEvents.WANDERING_TRADER_AMBIENT; + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { ++ protected SoundEvent getHurtSound(DamageSource damageSource) { + return SoundEvents.WANDERING_TRADER_HURT; + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.WANDERING_TRADER_DEATH; + } + + @Override +- @Override +- protected SoundEvent getDrinkingSound(ItemStack itemstack) { +- return itemstack.is(Items.MILK_BUCKET) ? SoundEvents.WANDERING_TRADER_DRINK_MILK : SoundEvents.WANDERING_TRADER_DRINK_POTION; ++ protected SoundEvent getDrinkingSound(ItemStack stack) { ++ return stack.is(Items.MILK_BUCKET) ? SoundEvents.WANDERING_TRADER_DRINK_MILK : SoundEvents.WANDERING_TRADER_DRINK_POTION; + } + + @Override +- @Override +- protected SoundEvent getTradeUpdatedSound(boolean flag) { +- return flag ? SoundEvents.WANDERING_TRADER_YES : SoundEvents.WANDERING_TRADER_NO; ++ protected SoundEvent getTradeUpdatedSound(boolean getYesSound) { ++ return getYesSound ? SoundEvents.WANDERING_TRADER_YES : SoundEvents.WANDERING_TRADER_NO; + } + + @Override +- @Override + public SoundEvent getNotifyTradeSound() { + return SoundEvents.WANDERING_TRADER_YES; + } + +- public void setDespawnDelay(int i) { +- this.despawnDelay = i; ++ public void setDespawnDelay(int despawnDelay) { ++ this.despawnDelay = despawnDelay; + } + + public int getDespawnDelay() { +@@ -249,7 +251,6 @@ + } + + @Override +- @Override + public void aiStep() { + super.aiStep(); + if (!this.level().isClientSide) { +@@ -265,8 +266,8 @@ + + } + +- public void setWanderTarget(@Nullable BlockPos blockpos) { +- this.wanderTarget = blockpos; ++ public void setWanderTarget(@Nullable BlockPos wanderTarget) { ++ this.wanderTarget = wanderTarget; + } + + @Nullable +@@ -280,48 +281,45 @@ + final double stopDistance; + final double speedModifier; + +- WanderToPositionGoal(WanderingTrader wanderingtrader, double d0, double d1) { +- this.trader = wanderingtrader; ++ WanderToPositionGoal(WanderingTrader entityvillagertrader, double d0, double d1) { ++ this.trader = entityvillagertrader; + this.stopDistance = d0; + this.speedModifier = d1; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +- @Override + public void stop() { + this.trader.setWanderTarget((BlockPos) null); + WanderingTrader.this.navigation.stop(); + } + + @Override +- @Override + public boolean canUse() { +- BlockPos blockpos = this.trader.getWanderTarget(); ++ BlockPos blockposition = this.trader.getWanderTarget(); + +- return blockpos != null && this.isTooFarAway(blockpos, this.stopDistance); ++ return blockposition != null && this.isTooFarAway(blockposition, this.stopDistance); + } + + @Override +- @Override + public void tick() { +- BlockPos blockpos = this.trader.getWanderTarget(); ++ BlockPos blockposition = this.trader.getWanderTarget(); + +- if (blockpos != null && WanderingTrader.this.navigation.isDone()) { +- if (this.isTooFarAway(blockpos, 10.0D)) { +- Vec3 vec3 = (new Vec3((double) blockpos.getX() - this.trader.getX(), (double) blockpos.getY() - this.trader.getY(), (double) blockpos.getZ() - this.trader.getZ())).normalize(); +- Vec3 vec31 = vec3.scale(10.0D).add(this.trader.getX(), this.trader.getY(), this.trader.getZ()); ++ if (blockposition != null && WanderingTrader.this.navigation.isDone()) { ++ if (this.isTooFarAway(blockposition, 10.0D)) { ++ Vec3 vec3d = (new Vec3((double) blockposition.getX() - this.trader.getX(), (double) blockposition.getY() - this.trader.getY(), (double) blockposition.getZ() - this.trader.getZ())).normalize(); ++ Vec3 vec3d1 = vec3d.scale(10.0D).add(this.trader.getX(), this.trader.getY(), this.trader.getZ()); + +- WanderingTrader.this.navigation.moveTo(vec31.x, vec31.y, vec31.z, this.speedModifier); ++ WanderingTrader.this.navigation.moveTo(vec3d1.x, vec3d1.y, vec3d1.z, this.speedModifier); + } else { +- WanderingTrader.this.navigation.moveTo((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), this.speedModifier); ++ WanderingTrader.this.navigation.moveTo((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), this.speedModifier); + } + } + + } + +- private boolean isTooFarAway(BlockPos blockpos, double d0) { +- return !blockpos.closerToCenterThan(this.trader.position(), d0); ++ private boolean isTooFarAway(BlockPos pos, double distance) { ++ return !pos.closerToCenterThan(this.trader.position(), distance); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/WanderingTraderSpawner.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/WanderingTraderSpawner.java.patch new file mode 100644 index 0000000000..6a29452482 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/npc/WanderingTraderSpawner.java.patch @@ -0,0 +1,193 @@ +--- a/net/minecraft/world/entity/npc/WanderingTraderSpawner.java ++++ b/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +@@ -10,7 +10,7 @@ + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.SpawnPlacements; + import net.minecraft.world.entity.ai.village.poi.PoiManager; + import net.minecraft.world.entity.ai.village.poi.PoiTypes; +@@ -38,24 +38,23 @@ + private int spawnDelay; + private int spawnChance; + +- public WanderingTraderSpawner(ServerLevelData serverleveldata) { +- this.serverLevelData = serverleveldata; ++ public WanderingTraderSpawner(ServerLevelData serverLevelData) { ++ this.serverLevelData = serverLevelData; + this.tickDelay = 1200; +- this.spawnDelay = serverleveldata.getWanderingTraderSpawnDelay(); +- this.spawnChance = serverleveldata.getWanderingTraderSpawnChance(); ++ this.spawnDelay = serverLevelData.getWanderingTraderSpawnDelay(); ++ this.spawnChance = serverLevelData.getWanderingTraderSpawnChance(); + if (this.spawnDelay == 0 && this.spawnChance == 0) { + this.spawnDelay = 24000; +- serverleveldata.setWanderingTraderSpawnDelay(this.spawnDelay); ++ serverLevelData.setWanderingTraderSpawnDelay(this.spawnDelay); + this.spawnChance = 25; +- serverleveldata.setWanderingTraderSpawnChance(this.spawnChance); ++ serverLevelData.setWanderingTraderSpawnChance(this.spawnChance); + } + + } + + @Override +- @Override +- public int tick(ServerLevel serverlevel, boolean flag, boolean flag1) { +- if (!serverlevel.getGameRules().getBoolean(GameRules.RULE_DO_TRADER_SPAWNING)) { ++ public int tick(ServerLevel level, boolean spawnHostiles, boolean spawnPassives) { ++ if (!level.getGameRules().getBoolean(GameRules.RULE_DO_TRADER_SPAWNING)) { + return 0; + } else if (--this.tickDelay > 0) { + return 0; +@@ -67,7 +66,7 @@ + return 0; + } else { + this.spawnDelay = 24000; +- if (!serverlevel.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { ++ if (!level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { + return 0; + } else { + int i = this.spawnChance; +@@ -76,7 +75,7 @@ + this.serverLevelData.setWanderingTraderSpawnChance(this.spawnChance); + if (this.random.nextInt(100) > i) { + return 0; +- } else if (this.spawn(serverlevel)) { ++ } else if (this.spawn(level)) { + this.spawnChance = 25; + return 1; + } else { +@@ -87,41 +86,41 @@ + } + } + +- private boolean spawn(ServerLevel serverlevel) { +- ServerPlayer serverplayer = serverlevel.getRandomPlayer(); ++ private boolean spawn(ServerLevel serverLevel) { ++ ServerPlayer entityplayer = serverLevel.getRandomPlayer(); + +- if (serverplayer == null) { ++ if (entityplayer == null) { + return true; + } else if (this.random.nextInt(10) != 0) { + return false; + } else { +- BlockPos blockpos = serverplayer.blockPosition(); ++ BlockPos blockposition = entityplayer.blockPosition(); + boolean flag = true; +- PoiManager poimanager = serverlevel.getPoiManager(); +- Optional optional = poimanager.find((holder) -> { ++ PoiManager villageplace = serverLevel.getPoiManager(); ++ Optional optional = villageplace.find((holder) -> { + return holder.is(PoiTypes.MEETING); +- }, (blockpos1) -> { ++ }, (blockposition1) -> { + return true; +- }, blockpos, 48, PoiManager.Occupancy.ANY); +- BlockPos blockpos1 = (BlockPos) optional.orElse(blockpos); +- BlockPos blockpos2 = this.findSpawnPositionNear(serverlevel, blockpos1, 48); ++ }, blockposition, 48, PoiManager.Occupancy.ANY); ++ BlockPos blockposition1 = (BlockPos) optional.orElse(blockposition); ++ BlockPos blockposition2 = this.findSpawnPositionNear(serverLevel, blockposition1, 48); + +- if (blockpos2 != null && this.hasEnoughSpace(serverlevel, blockpos2)) { +- if (serverlevel.getBiome(blockpos2).is(BiomeTags.WITHOUT_WANDERING_TRADER_SPAWNS)) { ++ if (blockposition2 != null && this.hasEnoughSpace(serverLevel, blockposition2)) { ++ if (serverLevel.getBiome(blockposition2).is(BiomeTags.WITHOUT_WANDERING_TRADER_SPAWNS)) { + return false; + } + +- WanderingTrader wanderingtrader = (WanderingTrader) EntityType.WANDERING_TRADER.spawn(serverlevel, blockpos2, MobSpawnType.EVENT); ++ WanderingTrader entityvillagertrader = (WanderingTrader) EntityType.WANDERING_TRADER.spawn(serverLevel, blockposition2, EnumMobSpawn.EVENT, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit + +- if (wanderingtrader != null) { ++ if (entityvillagertrader != null) { + for (int i = 0; i < 2; ++i) { +- this.tryToSpawnLlamaFor(serverlevel, wanderingtrader, 4); ++ this.tryToSpawnLlamaFor(serverLevel, entityvillagertrader, 4); + } + +- this.serverLevelData.setWanderingTraderId(wanderingtrader.getUUID()); +- wanderingtrader.setDespawnDelay(48000); +- wanderingtrader.setWanderTarget(blockpos1); +- wanderingtrader.restrictTo(blockpos1, 16); ++ this.serverLevelData.setWanderingTraderId(entityvillagertrader.getUUID()); ++ // entityvillagertrader.setDespawnDelay(48000); // CraftBukkit - moved to EntityVillagerTrader constructor. This lets the value be modified by plugins on CreatureSpawnEvent ++ entityvillagertrader.setWanderTarget(blockposition1); ++ entityvillagertrader.restrictTo(blockposition1, 16); + return true; + } + } +@@ -130,49 +129,49 @@ + } + } + +- private void tryToSpawnLlamaFor(ServerLevel serverlevel, WanderingTrader wanderingtrader, int i) { +- BlockPos blockpos = this.findSpawnPositionNear(serverlevel, wanderingtrader.blockPosition(), i); ++ private void tryToSpawnLlamaFor(ServerLevel serverLevel, WanderingTrader trader, int maxDistance) { ++ BlockPos blockposition = this.findSpawnPositionNear(serverLevel, trader.blockPosition(), maxDistance); + +- if (blockpos != null) { +- TraderLlama traderllama = (TraderLlama) EntityType.TRADER_LLAMA.spawn(serverlevel, blockpos, MobSpawnType.EVENT); ++ if (blockposition != null) { ++ TraderLlama entityllamatrader = (TraderLlama) EntityType.TRADER_LLAMA.spawn(serverLevel, blockposition, EnumMobSpawn.EVENT, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit + +- if (traderllama != null) { +- traderllama.setLeashedTo(wanderingtrader, true); ++ if (entityllamatrader != null) { ++ entityllamatrader.setLeashedTo(trader, true); + } + } + } + + @Nullable +- private BlockPos findSpawnPositionNear(LevelReader levelreader, BlockPos blockpos, int i) { +- BlockPos blockpos1 = null; ++ private BlockPos findSpawnPositionNear(LevelReader level, BlockPos pos, int maxDistance) { ++ BlockPos blockposition1 = null; + + for (int j = 0; j < 10; ++j) { +- int k = blockpos.getX() + this.random.nextInt(i * 2) - i; +- int l = blockpos.getZ() + this.random.nextInt(i * 2) - i; +- int i1 = levelreader.getHeight(Heightmap.Types.WORLD_SURFACE, k, l); +- BlockPos blockpos2 = new BlockPos(k, i1, l); ++ int k = pos.getX() + this.random.nextInt(maxDistance * 2) - maxDistance; ++ int l = pos.getZ() + this.random.nextInt(maxDistance * 2) - maxDistance; ++ int i1 = level.getHeight(Heightmap.Types.WORLD_SURFACE, k, l); ++ BlockPos blockposition2 = new BlockPos(k, i1, l); + +- if (NaturalSpawner.isSpawnPositionOk(SpawnPlacements.Type.ON_GROUND, levelreader, blockpos2, EntityType.WANDERING_TRADER)) { +- blockpos1 = blockpos2; ++ if (NaturalSpawner.isSpawnPositionOk(SpawnPlacements.Surface.ON_GROUND, level, blockposition2, EntityType.WANDERING_TRADER)) { ++ blockposition1 = blockposition2; + break; + } + } + +- return blockpos1; ++ return blockposition1; + } + +- private boolean hasEnoughSpace(BlockGetter blockgetter, BlockPos blockpos) { +- Iterator iterator = BlockPos.betweenClosed(blockpos, blockpos.offset(1, 2, 1)).iterator(); ++ private boolean hasEnoughSpace(BlockGetter level, BlockPos pos) { ++ Iterator iterator = BlockPos.betweenClosed(pos, pos.offset(1, 2, 1)).iterator(); + +- BlockPos blockpos1; ++ BlockPos blockposition1; + + do { + if (!iterator.hasNext()) { + return true; + } + +- blockpos1 = (BlockPos) iterator.next(); +- } while (blockgetter.getBlockState(blockpos1).getCollisionShape(blockgetter, blockpos1).isEmpty()); ++ blockposition1 = (BlockPos) iterator.next(); ++ } while (level.getBlockState(blockposition1).getCollisionShape(level, blockposition1).isEmpty()); + + return false; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/player/Inventory.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/player/Inventory.java.patch new file mode 100644 index 0000000000..9c95f5033b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/player/Inventory.java.patch @@ -0,0 +1,735 @@ +--- a/net/minecraft/world/entity/player/Inventory.java ++++ b/net/minecraft/world/entity/player/Inventory.java +@@ -17,17 +17,24 @@ + import net.minecraft.tags.TagKey; + import net.minecraft.world.Container; + import net.minecraft.world.ContainerHelper; +-import net.minecraft.world.Nameable; ++import net.minecraft.world.INamableTileEntity; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.item.ArmorItem; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + +-public class Inventory implements Container, Nameable { ++// CraftBukkit start ++import java.util.ArrayList; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end + ++public class Inventory implements Container, INamableTileEntity { ++ + public static final int POP_TIME_DURATION = 5; + public static final int INVENTORY_SIZE = 36; + private static final int SELECTION_SIZE = 9; +@@ -43,6 +50,54 @@ + public final Player player; + private int timesChanged; + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ List combined = new ArrayList(items.size() + armor.size() + offhand.size()); ++ for (List sub : this.compartments) { ++ combined.addAll(sub); ++ } ++ ++ return combined; ++ } ++ ++ public List getArmorContents() { ++ return this.armor; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return this.player.getBukkitEntity(); ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return player.getBukkitEntity().getLocation(); ++ } ++ // CraftBukkit end ++ + public Inventory(Player player) { + this.items = NonNullList.withSize(36, ItemStack.EMPTY); + this.armor = NonNullList.withSize(4, ItemStack.EMPTY); +@@ -59,10 +114,32 @@ + return 9; + } + +- private boolean hasRemainingSpaceForItem(ItemStack itemstack, ItemStack itemstack1) { +- return !itemstack.isEmpty() && ItemStack.isSameItemSameTags(itemstack, itemstack1) && itemstack.isStackable() && itemstack.getCount() < itemstack.getMaxStackSize() && itemstack.getCount() < this.getMaxStackSize(); ++ private boolean hasRemainingSpaceForItem(ItemStack destination, ItemStack origin) { ++ return !destination.isEmpty() && ItemStack.isSameItemSameTags(destination, origin) && destination.isStackable() && destination.getCount() < destination.getMaxStackSize() && destination.getCount() < this.getMaxStackSize(); + } + ++ // CraftBukkit start - Watch method above! :D ++ public int canHold(ItemStack itemstack) { ++ int remains = itemstack.getCount(); ++ for (int i = 0; i < this.items.size(); ++i) { ++ ItemStack itemstack1 = this.getItem(i); ++ if (itemstack1.isEmpty()) return itemstack.getCount(); ++ ++ if (this.hasRemainingSpaceForItem(itemstack1, itemstack)) { ++ remains -= (itemstack1.getMaxStackSize() < this.getMaxStackSize() ? itemstack1.getMaxStackSize() : this.getMaxStackSize()) - itemstack1.getCount(); ++ } ++ if (remains <= 0) return itemstack.getCount(); ++ } ++ ItemStack offhandItemStack = this.getItem(this.items.size() + this.armor.size()); ++ if (this.hasRemainingSpaceForItem(offhandItemStack, itemstack)) { ++ remains -= (offhandItemStack.getMaxStackSize() < this.getMaxStackSize() ? offhandItemStack.getMaxStackSize() : this.getMaxStackSize()) - offhandItemStack.getCount(); ++ } ++ if (remains <= 0) return itemstack.getCount(); ++ ++ return itemstack.getCount() - remains; ++ } ++ // CraftBukkit end ++ + public int getFreeSlot() { + for (int i = 0; i < this.items.size(); ++i) { + if (((ItemStack) this.items.get(i)).isEmpty()) { +@@ -73,8 +150,8 @@ + return -1; + } + +- public void setPickedItem(ItemStack itemstack) { +- int i = this.findSlotMatchingItem(itemstack); ++ public void setPickedItem(ItemStack stack) { ++ int i = this.findSlotMatchingItem(stack); + + if (isHotbarSlot(i)) { + this.selected = i; +@@ -89,7 +166,7 @@ + } + } + +- this.items.set(this.selected, itemstack); ++ this.items.set(this.selected, stack); + } else { + this.pickSlot(i); + } +@@ -97,21 +174,21 @@ + } + } + +- public void pickSlot(int i) { ++ public void pickSlot(int index) { + this.selected = this.getSuitableHotbarSlot(); + ItemStack itemstack = (ItemStack) this.items.get(this.selected); + +- this.items.set(this.selected, (ItemStack) this.items.get(i)); +- this.items.set(i, itemstack); ++ this.items.set(this.selected, (ItemStack) this.items.get(index)); ++ this.items.set(index, itemstack); + } + +- public static boolean isHotbarSlot(int i) { +- return i >= 0 && i < 9; ++ public static boolean isHotbarSlot(int index) { ++ return index >= 0 && index < 9; + } + +- public int findSlotMatchingItem(ItemStack itemstack) { ++ public int findSlotMatchingItem(ItemStack stack) { + for (int i = 0; i < this.items.size(); ++i) { +- if (!((ItemStack) this.items.get(i)).isEmpty() && ItemStack.isSameItemSameTags(itemstack, (ItemStack) this.items.get(i))) { ++ if (!((ItemStack) this.items.get(i)).isEmpty() && ItemStack.isSameItemSameTags(stack, (ItemStack) this.items.get(i))) { + return i; + } + } +@@ -119,11 +196,11 @@ + return -1; + } + +- public int findSlotMatchingUnusedItem(ItemStack itemstack) { ++ public int findSlotMatchingUnusedItem(ItemStack stack) { + for (int i = 0; i < this.items.size(); ++i) { + ItemStack itemstack1 = (ItemStack) this.items.get(i); + +- if (!((ItemStack) this.items.get(i)).isEmpty() && ItemStack.isSameItemSameTags(itemstack, (ItemStack) this.items.get(i)) && !((ItemStack) this.items.get(i)).isDamaged() && !itemstack1.isEnchanted() && !itemstack1.hasCustomHoverName()) { ++ if (!((ItemStack) this.items.get(i)).isEmpty() && ItemStack.isSameItemSameTags(stack, (ItemStack) this.items.get(i)) && !((ItemStack) this.items.get(i)).isDamaged() && !itemstack1.isEnchanted() && !itemstack1.hasCustomHoverName()) { + return i; + } + } +@@ -152,8 +229,8 @@ + return this.selected; + } + +- public void swapPaint(double d0) { +- int i = (int) Math.signum(d0); ++ public void swapPaint(double direction) { ++ int i = (int) Math.signum(direction); + + for (this.selected -= i; this.selected < 0; this.selected += 9) { + ; +@@ -165,15 +242,15 @@ + + } + +- public int clearOrCountMatchingItems(Predicate predicate, int i, Container container) { ++ public int clearOrCountMatchingItems(Predicate stackPredicate, int maxCount, Container inventory) { + byte b0 = 0; +- boolean flag = i == 0; +- int j = b0 + ContainerHelper.clearOrCountMatchingItems((Container) this, predicate, i - b0, flag); ++ boolean flag = maxCount == 0; ++ int j = b0 + ContainerHelper.clearOrCountMatchingItems((Container) this, stackPredicate, maxCount - b0, flag); + +- j += ContainerHelper.clearOrCountMatchingItems(container, predicate, i - j, flag); ++ j += ContainerHelper.clearOrCountMatchingItems(inventory, stackPredicate, maxCount - j, flag); + ItemStack itemstack = this.player.containerMenu.getCarried(); + +- j += ContainerHelper.clearOrCountMatchingItems(itemstack, predicate, i - j, flag); ++ j += ContainerHelper.clearOrCountMatchingItems(itemstack, stackPredicate, maxCount - j, flag); + if (itemstack.isEmpty()) { + this.player.containerMenu.setCarried(ItemStack.EMPTY); + } +@@ -181,28 +258,28 @@ + return j; + } + +- private int addResource(ItemStack itemstack) { +- int i = this.getSlotWithRemainingSpace(itemstack); ++ private int addResource(ItemStack stack) { ++ int i = this.getSlotWithRemainingSpace(stack); + + if (i == -1) { + i = this.getFreeSlot(); + } + +- return i == -1 ? itemstack.getCount() : this.addResource(i, itemstack); ++ return i == -1 ? stack.getCount() : this.addResource(i, stack); + } + +- private int addResource(int i, ItemStack itemstack) { +- Item item = itemstack.getItem(); +- int j = itemstack.getCount(); +- ItemStack itemstack1 = this.getItem(i); ++ private int addResource(int slot, ItemStack stack) { ++ Item item = stack.getItem(); ++ int j = stack.getCount(); ++ ItemStack itemstack1 = this.getItem(slot); + + if (itemstack1.isEmpty()) { + itemstack1 = new ItemStack(item, 0); +- if (itemstack.hasTag()) { +- itemstack1.setTag(itemstack.getTag().copy()); ++ if (stack.hasTag()) { ++ itemstack1.setTag(stack.getTag().copy()); + } + +- this.setItem(i, itemstack1); ++ this.setItem(slot, itemstack1); + } + + int k = j; +@@ -225,14 +302,14 @@ + } + } + +- public int getSlotWithRemainingSpace(ItemStack itemstack) { +- if (this.hasRemainingSpaceForItem(this.getItem(this.selected), itemstack)) { ++ public int getSlotWithRemainingSpace(ItemStack stack) { ++ if (this.hasRemainingSpaceForItem(this.getItem(this.selected), stack)) { + return this.selected; +- } else if (this.hasRemainingSpaceForItem(this.getItem(40), itemstack)) { ++ } else if (this.hasRemainingSpaceForItem(this.getItem(40), stack)) { + return 40; + } else { + for (int i = 0; i < this.items.size(); ++i) { +- if (this.hasRemainingSpaceForItem((ItemStack) this.items.get(i), itemstack)) { ++ if (this.hasRemainingSpaceForItem((ItemStack) this.items.get(i), stack)) { + return i; + } + } +@@ -256,26 +333,26 @@ + + } + +- public boolean add(ItemStack itemstack) { +- return this.add(-1, itemstack); ++ public boolean add(ItemStack stack) { ++ return this.add(-1, stack); + } + +- public boolean add(int i, ItemStack itemstack) { +- if (itemstack.isEmpty()) { ++ public boolean add(int slot, ItemStack stack) { ++ if (stack.isEmpty()) { + return false; + } else { + try { +- if (itemstack.isDamaged()) { +- if (i == -1) { +- i = this.getFreeSlot(); ++ if (stack.isDamaged()) { ++ if (slot == -1) { ++ slot = this.getFreeSlot(); + } + +- if (i >= 0) { +- this.items.set(i, itemstack.copyAndClear()); +- ((ItemStack) this.items.get(i)).setPopTime(5); ++ if (slot >= 0) { ++ this.items.set(slot, stack.copyAndClear()); ++ ((ItemStack) this.items.get(slot)).setPopTime(5); + return true; + } else if (this.player.getAbilities().instabuild) { +- itemstack.setCount(0); ++ stack.setCount(0); + return true; + } else { + return false; +@@ -284,58 +361,58 @@ + int j; + + do { +- j = itemstack.getCount(); +- if (i == -1) { +- itemstack.setCount(this.addResource(itemstack)); ++ j = stack.getCount(); ++ if (slot == -1) { ++ stack.setCount(this.addResource(stack)); + } else { +- itemstack.setCount(this.addResource(i, itemstack)); ++ stack.setCount(this.addResource(slot, stack)); + } +- } while (!itemstack.isEmpty() && itemstack.getCount() < j); ++ } while (!stack.isEmpty() && stack.getCount() < j); + +- if (itemstack.getCount() == j && this.player.getAbilities().instabuild) { +- itemstack.setCount(0); ++ if (stack.getCount() == j && this.player.getAbilities().instabuild) { ++ stack.setCount(0); + return true; + } else { +- return itemstack.getCount() < j; ++ return stack.getCount() < j; + } + } + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Adding item to inventory"); +- CrashReportCategory crashreportcategory = crashreport.addCategory("Item being added"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Item being added"); + +- crashreportcategory.setDetail("Item ID", (Object) Item.getId(itemstack.getItem())); +- crashreportcategory.setDetail("Item data", (Object) itemstack.getDamageValue()); +- crashreportcategory.setDetail("Item name", () -> { +- return itemstack.getHoverName().getString(); ++ crashreportsystemdetails.setDetail("Item ID", (Object) Item.getId(stack.getItem())); ++ crashreportsystemdetails.setDetail("Item data", (Object) stack.getDamageValue()); ++ crashreportsystemdetails.setDetail("Item name", () -> { ++ return stack.getHoverName().getString(); + }); + throw new ReportedException(crashreport); + } + } + } + +- public void placeItemBackInInventory(ItemStack itemstack) { +- this.placeItemBackInInventory(itemstack, true); ++ public void placeItemBackInInventory(ItemStack stack) { ++ this.placeItemBackInInventory(stack, true); + } + +- public void placeItemBackInInventory(ItemStack itemstack, boolean flag) { ++ public void placeItemBackInInventory(ItemStack stack, boolean sendPacket) { + while (true) { +- if (!itemstack.isEmpty()) { +- int i = this.getSlotWithRemainingSpace(itemstack); ++ if (!stack.isEmpty()) { ++ int i = this.getSlotWithRemainingSpace(stack); + + if (i == -1) { + i = this.getFreeSlot(); + } + + if (i != -1) { +- int j = itemstack.getMaxStackSize() - this.getItem(i).getCount(); ++ int j = stack.getMaxStackSize() - this.getItem(i).getCount(); + +- if (this.add(i, itemstack.split(j)) && flag && this.player instanceof ServerPlayer) { ++ if (this.add(i, stack.split(j)) && sendPacket && this.player instanceof ServerPlayer) { + ((ServerPlayer) this.player).connection.send(new ClientboundContainerSetSlotPacket(-2, 0, i, this.getItem(i))); + } + continue; + } + +- this.player.drop(itemstack, false); ++ this.player.drop(stack, false); + } + + return; +@@ -343,31 +420,30 @@ + } + + @Override +- @Override +- public ItemStack removeItem(int i, int j) { ++ public ItemStack removeItem(int index, int count) { + List list = null; + + NonNullList nonnulllist; + +- for (Iterator iterator = this.compartments.iterator(); iterator.hasNext(); i -= nonnulllist.size()) { ++ for (Iterator iterator = this.compartments.iterator(); iterator.hasNext(); index -= nonnulllist.size()) { + nonnulllist = (NonNullList) iterator.next(); +- if (i < nonnulllist.size()) { ++ if (index < nonnulllist.size()) { + list = nonnulllist; + break; + } + } + +- return list != null && !((ItemStack) list.get(i)).isEmpty() ? ContainerHelper.removeItem(list, i, j) : ItemStack.EMPTY; ++ return list != null && !((ItemStack) list.get(index)).isEmpty() ? ContainerHelper.removeItem(list, index, count) : ItemStack.EMPTY; + } + +- public void removeItem(ItemStack itemstack) { ++ public void removeItem(ItemStack stack) { + Iterator iterator = this.compartments.iterator(); + + while (iterator.hasNext()) { + NonNullList nonnulllist = (NonNullList) iterator.next(); + + for (int i = 0; i < nonnulllist.size(); ++i) { +- if (nonnulllist.get(i) == itemstack) { ++ if (nonnulllist.get(i) == stack) { + nonnulllist.set(i, ItemStack.EMPTY); + break; + } +@@ -377,24 +453,23 @@ + } + + @Override +- @Override +- public ItemStack removeItemNoUpdate(int i) { ++ public ItemStack removeItemNoUpdate(int index) { + NonNullList nonnulllist = null; + + NonNullList nonnulllist1; + +- for (Iterator iterator = this.compartments.iterator(); iterator.hasNext(); i -= nonnulllist1.size()) { ++ for (Iterator iterator = this.compartments.iterator(); iterator.hasNext(); index -= nonnulllist1.size()) { + nonnulllist1 = (NonNullList) iterator.next(); +- if (i < nonnulllist1.size()) { ++ if (index < nonnulllist1.size()) { + nonnulllist = nonnulllist1; + break; + } + } + +- if (nonnulllist != null && !((ItemStack) nonnulllist.get(i)).isEmpty()) { +- ItemStack itemstack = (ItemStack) nonnulllist.get(i); ++ if (nonnulllist != null && !((ItemStack) nonnulllist.get(index)).isEmpty()) { ++ ItemStack itemstack = (ItemStack) nonnulllist.get(index); + +- nonnulllist.set(i, ItemStack.EMPTY); ++ nonnulllist.set(index, ItemStack.EMPTY); + return itemstack; + } else { + return ItemStack.EMPTY; +@@ -402,73 +477,72 @@ + } + + @Override +- @Override +- public void setItem(int i, ItemStack itemstack) { ++ public void setItem(int index, ItemStack stack) { + NonNullList nonnulllist = null; + + NonNullList nonnulllist1; + +- for (Iterator iterator = this.compartments.iterator(); iterator.hasNext(); i -= nonnulllist1.size()) { ++ for (Iterator iterator = this.compartments.iterator(); iterator.hasNext(); index -= nonnulllist1.size()) { + nonnulllist1 = (NonNullList) iterator.next(); +- if (i < nonnulllist1.size()) { ++ if (index < nonnulllist1.size()) { + nonnulllist = nonnulllist1; + break; + } + } + + if (nonnulllist != null) { +- nonnulllist.set(i, itemstack); ++ nonnulllist.set(index, stack); + } + + } + +- public float getDestroySpeed(BlockState blockstate) { +- return ((ItemStack) this.items.get(this.selected)).getDestroySpeed(blockstate); ++ public float getDestroySpeed(IBlockData state) { ++ return ((ItemStack) this.items.get(this.selected)).getDestroySpeed(state); + } + +- public ListTag save(ListTag listtag) { +- CompoundTag compoundtag; ++ public ListTag save(ListTag listTag) { ++ CompoundTag nbttagcompound; + int i; + + for (i = 0; i < this.items.size(); ++i) { + if (!((ItemStack) this.items.get(i)).isEmpty()) { +- compoundtag = new CompoundTag(); +- compoundtag.putByte("Slot", (byte) i); +- ((ItemStack) this.items.get(i)).save(compoundtag); +- listtag.add(compoundtag); ++ nbttagcompound = new CompoundTag(); ++ nbttagcompound.putByte("Slot", (byte) i); ++ ((ItemStack) this.items.get(i)).save(nbttagcompound); ++ listTag.add(nbttagcompound); + } + } + + for (i = 0; i < this.armor.size(); ++i) { + if (!((ItemStack) this.armor.get(i)).isEmpty()) { +- compoundtag = new CompoundTag(); +- compoundtag.putByte("Slot", (byte) (i + 100)); +- ((ItemStack) this.armor.get(i)).save(compoundtag); +- listtag.add(compoundtag); ++ nbttagcompound = new CompoundTag(); ++ nbttagcompound.putByte("Slot", (byte) (i + 100)); ++ ((ItemStack) this.armor.get(i)).save(nbttagcompound); ++ listTag.add(nbttagcompound); + } + } + + for (i = 0; i < this.offhand.size(); ++i) { + if (!((ItemStack) this.offhand.get(i)).isEmpty()) { +- compoundtag = new CompoundTag(); +- compoundtag.putByte("Slot", (byte) (i + 150)); +- ((ItemStack) this.offhand.get(i)).save(compoundtag); +- listtag.add(compoundtag); ++ nbttagcompound = new CompoundTag(); ++ nbttagcompound.putByte("Slot", (byte) (i + 150)); ++ ((ItemStack) this.offhand.get(i)).save(nbttagcompound); ++ listTag.add(nbttagcompound); + } + } + +- return listtag; ++ return listTag; + } + +- public void load(ListTag listtag) { ++ public void load(ListTag listTag) { + this.items.clear(); + this.armor.clear(); + this.offhand.clear(); + +- for (int i = 0; i < listtag.size(); ++i) { +- CompoundTag compoundtag = listtag.getCompound(i); +- int j = compoundtag.getByte("Slot") & 255; +- ItemStack itemstack = ItemStack.of(compoundtag); ++ for (int i = 0; i < listTag.size(); ++i) { ++ CompoundTag nbttagcompound = listTag.getCompound(i); ++ int j = nbttagcompound.getByte("Slot") & 255; ++ ItemStack itemstack = ItemStack.of(nbttagcompound); + + if (!itemstack.isEmpty()) { + if (j >= 0 && j < this.items.size()) { +@@ -484,13 +558,11 @@ + } + + @Override +- @Override + public int getContainerSize() { + return this.items.size() + this.armor.size() + this.offhand.size(); + } + + @Override +- @Override + public boolean isEmpty() { + Iterator iterator = this.items.iterator(); + +@@ -528,50 +600,48 @@ + } + + @Override +- @Override +- public ItemStack getItem(int i) { ++ public ItemStack getItem(int index) { + List list = null; + + NonNullList nonnulllist; + +- for (Iterator iterator = this.compartments.iterator(); iterator.hasNext(); i -= nonnulllist.size()) { ++ for (Iterator iterator = this.compartments.iterator(); iterator.hasNext(); index -= nonnulllist.size()) { + nonnulllist = (NonNullList) iterator.next(); +- if (i < nonnulllist.size()) { ++ if (index < nonnulllist.size()) { + list = nonnulllist; + break; + } + } + +- return list == null ? ItemStack.EMPTY : (ItemStack) list.get(i); ++ return list == null ? ItemStack.EMPTY : (ItemStack) list.get(index); + } + + @Override +- @Override + public Component getName() { + return Component.translatable("container.inventory"); + } + +- public ItemStack getArmor(int i) { +- return (ItemStack) this.armor.get(i); ++ public ItemStack getArmor(int slot) { ++ return (ItemStack) this.armor.get(slot); + } + +- public void hurtArmor(DamageSource damagesource, float f, int[] aint) { +- if (f > 0.0F) { +- f /= 4.0F; +- if (f < 1.0F) { +- f = 1.0F; ++ public void hurtArmor(DamageSource source, float damage, int[] armorPieces) { ++ if (damage > 0.0F) { ++ damage /= 4.0F; ++ if (damage < 1.0F) { ++ damage = 1.0F; + } + +- int[] aint1 = aint; +- int i = aint.length; ++ int[] aint1 = armorPieces; ++ int i = armorPieces.length; + + for (int j = 0; j < i; ++j) { + int k = aint1[j]; + ItemStack itemstack = (ItemStack) this.armor.get(k); + +- if ((!damagesource.is(DamageTypeTags.IS_FIRE) || !itemstack.getItem().isFireResistant()) && itemstack.getItem() instanceof ArmorItem) { +- itemstack.hurtAndBreak((int) f, this.player, (player) -> { +- player.broadcastBreakEvent(EquipmentSlot.byTypeAndIndex(EquipmentSlot.Type.ARMOR, k)); ++ if ((!source.is(DamageTypeTags.IS_FIRE) || !itemstack.getItem().isFireResistant()) && itemstack.getItem() instanceof ArmorItem) { ++ itemstack.hurtAndBreak((int) damage, this.player, (entityhuman) -> { ++ entityhuman.broadcastBreakEvent(EquipmentSlot.byTypeAndIndex(EquipmentSlot.Function.ARMOR, k)); + }); + } + } +@@ -598,7 +668,6 @@ + } + + @Override +- @Override + public void setChanged() { + ++this.timesChanged; + } +@@ -608,12 +677,11 @@ + } + + @Override +- @Override + public boolean stillValid(Player player) { + return this.player.isRemoved() ? false : player.distanceToSqr((Entity) this.player) <= 64.0D; + } + +- public boolean contains(ItemStack itemstack) { ++ public boolean contains(ItemStack stack) { + Iterator iterator = this.compartments.iterator(); + + while (iterator.hasNext()) { +@@ -623,7 +691,7 @@ + while (iterator1.hasNext()) { + ItemStack itemstack1 = (ItemStack) iterator1.next(); + +- if (!itemstack1.isEmpty() && ItemStack.isSameItemSameTags(itemstack1, itemstack)) { ++ if (!itemstack1.isEmpty() && ItemStack.isSameItemSameTags(itemstack1, stack)) { + return true; + } + } +@@ -632,7 +700,7 @@ + return false; + } + +- public boolean contains(TagKey tagkey) { ++ public boolean contains(TagKey tag) { + Iterator iterator = this.compartments.iterator(); + + while (iterator.hasNext()) { +@@ -642,7 +710,7 @@ + while (iterator1.hasNext()) { + ItemStack itemstack = (ItemStack) iterator1.next(); + +- if (!itemstack.isEmpty() && itemstack.is(tagkey)) { ++ if (!itemstack.isEmpty() && itemstack.is(tag)) { + return true; + } + } +@@ -651,16 +719,15 @@ + return false; + } + +- public void replaceWith(Inventory inventory) { ++ public void replaceWith(Inventory playerInventory) { + for (int i = 0; i < this.getContainerSize(); ++i) { +- this.setItem(i, inventory.getItem(i)); ++ this.setItem(i, playerInventory.getItem(i)); + } + +- this.selected = inventory.selected; ++ this.selected = playerInventory.selected; + } + + @Override +- @Override + public void clearContent() { + Iterator iterator = this.compartments.iterator(); + +@@ -672,20 +739,20 @@ + + } + +- public void fillStackedContents(StackedContents stackedcontents) { ++ public void fillStackedContents(StackedContents stackedContent) { + Iterator iterator = this.items.iterator(); + + while (iterator.hasNext()) { + ItemStack itemstack = (ItemStack) iterator.next(); + +- stackedcontents.accountSimpleStack(itemstack); ++ stackedContent.accountSimpleStack(itemstack); + } + + } + +- public ItemStack removeFromSelected(boolean flag) { ++ public ItemStack removeFromSelected(boolean removeStack) { + ItemStack itemstack = this.getSelected(); + +- return itemstack.isEmpty() ? ItemStack.EMPTY : this.removeItem(this.selected, flag ? itemstack.getCount() : 1); ++ return itemstack.isEmpty() ? ItemStack.EMPTY : this.removeItem(this.selected, removeStack ? itemstack.getCount() : 1); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/player/Player.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/player/Player.java.patch new file mode 100644 index 0000000000..3d87d23b2e --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/player/Player.java.patch @@ -0,0 +1,2227 @@ +--- a/net/minecraft/world/entity/player/Player.java ++++ b/net/minecraft/world/entity/player/Player.java +@@ -28,6 +28,7 @@ + import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtOps; + import net.minecraft.nbt.NbtUtils; ++import net.minecraft.nbt.Tag; + import net.minecraft.network.chat.ClickEvent; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.MutableComponent; +@@ -50,23 +51,23 @@ + import net.minecraft.util.Unit; + import net.minecraft.world.Container; + import net.minecraft.world.Difficulty; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; ++import net.minecraft.world.ITileInventory; + import net.minecraft.world.InteractionResult; +-import net.minecraft.world.MenuProvider; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.effect.MobEffectUtil; + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMonsterType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.HumanoidArm; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.SlotAccess; + import net.minecraft.world.entity.TamableAnimal; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -103,7 +104,7 @@ + import net.minecraft.world.level.block.entity.JigsawBlockEntity; + import net.minecraft.world.level.block.entity.SignBlockEntity; + import net.minecraft.world.level.block.entity.StructureBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.pattern.BlockInWorld; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; +@@ -111,6 +112,16 @@ + import net.minecraft.world.scores.PlayerTeam; + import net.minecraft.world.scores.Scoreboard; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.util.CraftVector; ++import org.bukkit.entity.Item; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.entity.EntityExhaustionEvent; ++import org.bukkit.event.player.PlayerDropItemEvent; ++import org.bukkit.event.player.PlayerVelocityEvent; ++// CraftBukkit end + + public abstract class Player extends LivingEntity { + +@@ -127,7 +138,8 @@ + public static final float SWIMMING_BB_HEIGHT = 0.6F; + public static final float DEFAULT_EYE_HEIGHT = 1.62F; + public static final EntityDimensions STANDING_DIMENSIONS = EntityDimensions.scalable(0.6F, 1.8F); +- private static final Map POSES = ImmutableMap.builder().put(Pose.STANDING, Player.STANDING_DIMENSIONS).put(Pose.SLEEPING, Player.SLEEPING_DIMENSIONS).put(Pose.FALL_FLYING, EntityDimensions.scalable(0.6F, 0.6F)).put(Pose.SWIMMING, EntityDimensions.scalable(0.6F, 0.6F)).put(Pose.SPIN_ATTACK, EntityDimensions.scalable(0.6F, 0.6F)).put(Pose.CROUCHING, EntityDimensions.scalable(0.6F, 1.5F)).put(Pose.DYING, EntityDimensions.fixed(0.2F, 0.2F)).build(); ++ // CraftBukkit - decompile error ++ private static final Map POSES = ImmutableMap.builder().put(EntityPose.STANDING, Player.STANDING_DIMENSIONS).put(EntityPose.SLEEPING, Player.SLEEPING_DIMENSIONS).put(EntityPose.FALL_FLYING, EntityDimensions.scalable(0.6F, 0.6F)).put(EntityPose.SWIMMING, EntityDimensions.scalable(0.6F, 0.6F)).put(EntityPose.SPIN_ATTACK, EntityDimensions.scalable(0.6F, 0.6F)).put(EntityPose.CROUCHING, EntityDimensions.scalable(0.6F, 1.5F)).put(EntityPose.DYING, EntityDimensions.fixed(0.2F, 0.2F)).build(); + private static final EntityDataAccessor DATA_PLAYER_ABSORPTION_ID = SynchedEntityData.defineId(Player.class, EntityDataSerializers.FLOAT); + private static final EntityDataAccessor DATA_SCORE_ID = SynchedEntityData.defineId(Player.class, EntityDataSerializers.INT); + protected static final EntityDataAccessor DATA_PLAYER_MODE_CUSTOMISATION = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE); +@@ -136,10 +148,10 @@ + protected static final EntityDataAccessor DATA_SHOULDER_RIGHT = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG); + private long timeEntitySatOnShoulder; + private final Inventory inventory = new Inventory(this); +- protected PlayerEnderChestContainer enderChestInventory = new PlayerEnderChestContainer(); ++ protected PlayerEnderChestContainer enderChestInventory = new PlayerEnderChestContainer(this); // CraftBukkit - add "this" to constructor + public final InventoryMenu inventoryMenu; + public AbstractContainerMenu containerMenu; +- protected FoodData foodData = new FoodData(); ++ protected FoodData foodData = new FoodData(this); // CraftBukkit - add "this" to constructor + protected int jumpTriggerTime; + public float oBob; + public float bob; +@@ -150,13 +162,13 @@ + public double xCloak; + public double yCloak; + public double zCloak; +- private int sleepCounter; ++ public int sleepCounter; + protected boolean wasUnderwater; + private final Abilities abilities = new Abilities(); + public int experienceLevel; + public int totalExperience; + public float experienceProgress; +- protected int enchantmentSeed; ++ public int enchantmentSeed; + protected final float defaultFlySpeed = 0.02F; + private int lastLevelUpTime; + private final GameProfile gameProfile; +@@ -168,30 +180,40 @@ + public FishingHook fishing; + protected float hurtDir; + +- public Player(Level level, BlockPos blockpos, float f, GameProfile gameprofile) { ++ // CraftBukkit start ++ public boolean fauxSleeping; ++ public int oldLevel = -1; ++ ++ @Override ++ public CraftHumanEntity getBukkitEntity() { ++ return (CraftHumanEntity) super.getBukkitEntity(); ++ } ++ // CraftBukkit end ++ ++ public Player(Level level, BlockPos pos, float yRot, GameProfile gameProfile) { + super(EntityType.PLAYER, level); + this.lastItemInMainHand = ItemStack.EMPTY; + this.cooldowns = this.createItemCooldowns(); + this.lastDeathLocation = Optional.empty(); +- this.setUUID(gameprofile.getId()); +- this.gameProfile = gameprofile; ++ this.setUUID(gameProfile.getId()); ++ this.gameProfile = gameProfile; + this.inventoryMenu = new InventoryMenu(this.inventory, !level.isClientSide, this); + this.containerMenu = this.inventoryMenu; +- this.moveTo((double) blockpos.getX() + 0.5D, (double) (blockpos.getY() + 1), (double) blockpos.getZ() + 0.5D, f, 0.0F); ++ this.moveTo((double) pos.getX() + 0.5D, (double) (pos.getY() + 1), (double) pos.getZ() + 0.5D, yRot, 0.0F); + this.rotOffs = 180.0F; + } + +- public boolean blockActionRestricted(Level level, BlockPos blockpos, GameType gametype) { +- if (!gametype.isBlockPlacingRestricted()) { ++ public boolean blockActionRestricted(Level level, BlockPos pos, GameType gameMode) { ++ if (!gameMode.isBlockPlacingRestricted()) { + return false; +- } else if (gametype == GameType.SPECTATOR) { ++ } else if (gameMode == GameType.SPECTATOR) { + return true; + } else if (this.mayBuild()) { + return false; + } else { + ItemStack itemstack = this.getMainHandItem(); + +- return itemstack.isEmpty() || !itemstack.hasAdventureModeBreakTagForBlock(level.registryAccess().registryOrThrow(Registries.BLOCK), new BlockInWorld(level, blockpos, false)); ++ return itemstack.isEmpty() || !itemstack.hasAdventureModeBreakTagForBlock(level.registryAccess().registryOrThrow(Registries.BLOCK), new BlockInWorld(level, pos, false)); + } + } + +@@ -200,7 +222,6 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Player.DATA_PLAYER_ABSORPTION_ID, 0.0F); +@@ -212,7 +233,6 @@ + } + + @Override +- @Override + public void tick() { + this.noPhysics = this.isSpectator(); + if (this.isSpectator()) { +@@ -289,7 +309,6 @@ + } + + @Override +- @Override + protected float getMaxHeadRotationRelativeToBody() { + return this.isBlocking() ? 15.0F : super.getMaxHeadRotationRelativeToBody(); + } +@@ -315,7 +334,7 @@ + ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); + + if (itemstack.is(Items.TURTLE_HELMET) && !this.isEyeInFluid(FluidTags.WATER)) { +- this.addEffect(new MobEffectInstance(MobEffects.WATER_BREATHING, 200, 0, false, false, true)); ++ this.addEffect(new MobEffectInstance(MobEffects.WATER_BREATHING, 200, 0, false, false, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TURTLE_HELMET); // CraftBukkit + } + + } +@@ -369,134 +388,130 @@ + } + + protected void updatePlayerPose() { +- if (this.canPlayerFitWithinBlocksAndEntitiesWhen(Pose.SWIMMING)) { +- Pose pose; ++ if (this.canPlayerFitWithinBlocksAndEntitiesWhen(EntityPose.SWIMMING)) { ++ EntityPose entitypose; + + if (this.isFallFlying()) { +- pose = Pose.FALL_FLYING; ++ entitypose = EntityPose.FALL_FLYING; + } else if (this.isSleeping()) { +- pose = Pose.SLEEPING; ++ entitypose = EntityPose.SLEEPING; + } else if (this.isSwimming()) { +- pose = Pose.SWIMMING; ++ entitypose = EntityPose.SWIMMING; + } else if (this.isAutoSpinAttack()) { +- pose = Pose.SPIN_ATTACK; ++ entitypose = EntityPose.SPIN_ATTACK; + } else if (this.isShiftKeyDown() && !this.abilities.flying) { +- pose = Pose.CROUCHING; ++ entitypose = EntityPose.CROUCHING; + } else { +- pose = Pose.STANDING; ++ entitypose = EntityPose.STANDING; + } + +- Pose pose1; ++ EntityPose entitypose1; + +- if (!this.isSpectator() && !this.isPassenger() && !this.canPlayerFitWithinBlocksAndEntitiesWhen(pose)) { +- if (this.canPlayerFitWithinBlocksAndEntitiesWhen(Pose.CROUCHING)) { +- pose1 = Pose.CROUCHING; ++ if (!this.isSpectator() && !this.isPassenger() && !this.canPlayerFitWithinBlocksAndEntitiesWhen(entitypose)) { ++ if (this.canPlayerFitWithinBlocksAndEntitiesWhen(EntityPose.CROUCHING)) { ++ entitypose1 = EntityPose.CROUCHING; + } else { +- pose1 = Pose.SWIMMING; ++ entitypose1 = EntityPose.SWIMMING; + } + } else { +- pose1 = pose; ++ entitypose1 = entitypose; + } + +- this.setPose(pose1); ++ this.setPose(entitypose1); + } + } + +- protected boolean canPlayerFitWithinBlocksAndEntitiesWhen(Pose pose) { +- return this.level().noCollision(this, this.getDimensions(pose).makeBoundingBox(this.position()).deflate(1.0E-7D)); ++ protected boolean canPlayerFitWithinBlocksAndEntitiesWhen(EntityPose entitypose) { ++ return this.level().noCollision(this, this.getDimensions(entitypose).makeBoundingBox(this.position()).deflate(1.0E-7D)); + } + + @Override +- @Override + public int getPortalWaitTime() { + return Math.max(1, this.level().getGameRules().getInt(this.abilities.invulnerable ? GameRules.RULE_PLAYERS_NETHER_PORTAL_CREATIVE_DELAY : GameRules.RULE_PLAYERS_NETHER_PORTAL_DEFAULT_DELAY)); + } + + @Override +- @Override + protected SoundEvent getSwimSound() { + return SoundEvents.PLAYER_SWIM; + } + + @Override +- @Override + protected SoundEvent getSwimSplashSound() { + return SoundEvents.PLAYER_SPLASH; + } + + @Override +- @Override + protected SoundEvent getSwimHighSpeedSplashSound() { + return SoundEvents.PLAYER_SPLASH_HIGH_SPEED; + } + + @Override +- @Override + public int getDimensionChangingDelay() { + return 10; + } + + @Override +- @Override +- public void playSound(SoundEvent soundevent, float f, float f1) { +- this.level().playSound(this, this.getX(), this.getY(), this.getZ(), soundevent, this.getSoundSource(), f, f1); ++ public void playSound(SoundEvent sound, float volume, float pitch) { ++ this.level().playSound(this, this.getX(), this.getY(), this.getZ(), sound, this.getSoundSource(), volume, pitch); + } + +- public void playNotifySound(SoundEvent soundevent, SoundSource soundsource, float f, float f1) {} ++ public void playNotifySound(SoundEvent sound, SoundSource source, float volume, float pitch) {} + + @Override +- @Override + public SoundSource getSoundSource() { + return SoundSource.PLAYERS; + } + + @Override +- @Override +- protected int getFireImmuneTicks() { ++ public int getFireImmuneTicks() { + return 20; + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 9) { ++ public void handleEntityEvent(byte id) { ++ if (id == 9) { + this.completeUsingItem(); +- } else if (b0 == 23) { ++ } else if (id == 23) { + this.reducedDebugInfo = false; +- } else if (b0 == 22) { ++ } else if (id == 22) { + this.reducedDebugInfo = true; +- } else if (b0 == 43) { ++ } else if (id == 43) { + this.addParticlesAroundSelf(ParticleTypes.CLOUD); + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } + +- private void addParticlesAroundSelf(ParticleOptions particleoptions) { ++ private void addParticlesAroundSelf(ParticleOptions particleOption) { + for (int i = 0; i < 5; ++i) { + double d0 = this.random.nextGaussian() * 0.02D; + double d1 = this.random.nextGaussian() * 0.02D; + double d2 = this.random.nextGaussian() * 0.02D; + +- this.level().addParticle(particleoptions, this.getRandomX(1.0D), this.getRandomY() + 1.0D, this.getRandomZ(1.0D), d0, d1, d2); ++ this.level().addParticle(particleOption, this.getRandomX(1.0D), this.getRandomY() + 1.0D, this.getRandomZ(1.0D), d0, d1, d2); + } + + } + +- protected void closeContainer() { ++ public void closeContainer() { + this.containerMenu = this.inventoryMenu; + } + + protected void doCloseContainer() {} + + @Override +- @Override + public void rideTick() { + if (!this.level().isClientSide && this.wantsToStopRiding() && this.isPassenger()) { + this.stopRiding(); +- this.setShiftKeyDown(false); +- } else { ++ // CraftBukkit start - SPIGOT-7316: no longer passenger, dismount and return ++ if (!this.isPassenger()) { ++ this.setShiftKeyDown(false); ++ return; ++ } ++ } ++ { ++ // CraftBukkit end + super.rideTick(); + this.oBob = this.bob; + this.bob = 0.0F; +@@ -504,7 +519,6 @@ + } + + @Override +- @Override + protected void serverAiStep() { + super.serverAiStep(); + this.updateSwingTime(); +@@ -512,7 +526,6 @@ + } + + @Override +- @Override + public void aiStep() { + if (this.jumpTriggerTime > 0) { + --this.jumpTriggerTime; +@@ -520,7 +533,8 @@ + + if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.level().getGameRules().getBoolean(GameRules.RULE_NATURAL_REGENERATION)) { + if (this.getHealth() < this.getMaxHealth() && this.tickCount % 20 == 0) { +- this.heal(1.0F); ++ // CraftBukkit - added regain reason of "REGEN" for filtering purposes. ++ this.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.REGEN); + } + + if (this.foodData.needsFood() && this.tickCount % 10 == 0) { +@@ -542,15 +556,15 @@ + + this.bob += (f - this.bob) * 0.4F; + if (this.getHealth() > 0.0F && !this.isSpectator()) { +- AABB aabb; ++ AABB axisalignedbb; + + if (this.isPassenger() && !this.getVehicle().isRemoved()) { +- aabb = this.getBoundingBox().minmax(this.getVehicle().getBoundingBox()).inflate(1.0D, 0.0D, 1.0D); ++ axisalignedbb = this.getBoundingBox().minmax(this.getVehicle().getBoundingBox()).inflate(1.0D, 0.0D, 1.0D); + } else { +- aabb = this.getBoundingBox().inflate(1.0D, 0.5D, 1.0D); ++ axisalignedbb = this.getBoundingBox().inflate(1.0D, 0.5D, 1.0D); + } + +- List list = this.level().getEntities(this, aabb); ++ List list = this.level().getEntities(this, axisalignedbb); + List list1 = Lists.newArrayList(); + Iterator iterator = list.iterator(); + +@@ -577,13 +591,13 @@ + + } + +- private void playShoulderEntityAmbientSound(@Nullable CompoundTag compoundtag) { +- if (compoundtag != null && (!compoundtag.contains("Silent") || !compoundtag.getBoolean("Silent")) && this.level().random.nextInt(200) == 0) { +- String s = compoundtag.getString("id"); ++ private void playShoulderEntityAmbientSound(@Nullable CompoundTag entityCompound) { ++ if (entityCompound != null && (!entityCompound.contains("Silent") || !entityCompound.getBoolean("Silent")) && this.level().random.nextInt(200) == 0) { ++ String s = entityCompound.getString("id"); + +- EntityType.byString(s).filter((entitytype) -> { +- return entitytype == EntityType.PARROT; +- }).ifPresent((entitytype) -> { ++ EntityType.byString(s).filter((entitytypes) -> { ++ return entitytypes == EntityType.PARROT; ++ }).ifPresent((entitytypes) -> { + if (!Parrot.imitateNearbyMobs(this.level(), this)) { + this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), Parrot.getAmbient(this.level(), this.level().random), this.getSoundSource(), 1.0F, Parrot.getPitch(this.level().random)); + } +@@ -601,18 +615,18 @@ + return (Integer) this.entityData.get(Player.DATA_SCORE_ID); + } + +- public void setScore(int i) { +- this.entityData.set(Player.DATA_SCORE_ID, i); ++ public void setScore(int score) { ++ this.entityData.set(Player.DATA_SCORE_ID, score); + } + +- public void increaseScore(int i) { ++ public void increaseScore(int score) { + int j = this.getScore(); + +- this.entityData.set(Player.DATA_SCORE_ID, j + i); ++ this.entityData.set(Player.DATA_SCORE_ID, j + score); + } + +- public void startAutoSpinAttack(int i) { +- this.autoSpinAttackTicks = i; ++ public void startAutoSpinAttack(int attackTicks) { ++ this.autoSpinAttackTicks = attackTicks; + if (!this.level().isClientSide) { + this.removeEntitiesOnShoulder(); + this.setLivingEntityFlag(4, true); +@@ -621,15 +635,14 @@ + } + + @Override +- @Override +- public void die(DamageSource damagesource) { +- super.die(damagesource); ++ public void die(DamageSource cause) { ++ super.die(cause); + this.reapplyPosition(); + if (!this.isSpectator()) { +- this.dropAllDeathLoot(damagesource); ++ this.dropAllDeathLoot(cause); + } + +- if (damagesource != null) { ++ if (cause != null) { + this.setDeltaMovement((double) (-Mth.cos((this.getHurtDir() + this.getYRot()) * 0.017453292F) * 0.1F), 0.10000000149011612D, (double) (-Mth.sin((this.getHurtDir() + this.getYRot()) * 0.017453292F) * 0.1F)); + } else { + this.setDeltaMovement(0.0D, 0.1D, 0.0D); +@@ -644,7 +657,6 @@ + } + + @Override +- @Override + protected void dropEquipment() { + super.dropEquipment(); + if (!this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY)) { +@@ -666,37 +678,42 @@ + } + + @Override +- @Override +- protected SoundEvent getHurtSound(DamageSource damagesource) { +- return damagesource.type().effects().sound(); ++ protected SoundEvent getHurtSound(DamageSource damageSource) { ++ return damageSource.type().effects().sound(); + } + + @Override +- @Override + protected SoundEvent getDeathSound() { + return SoundEvents.PLAYER_DEATH; + } + + @Nullable +- public ItemEntity drop(ItemStack itemstack, boolean flag) { +- return this.drop(itemstack, false, flag); ++ public ItemEntity drop(ItemStack itemStack, boolean includeThrowerName) { ++ return this.drop(itemStack, false, includeThrowerName); + } + + @Nullable +- public ItemEntity drop(ItemStack itemstack, boolean flag, boolean flag1) { ++ public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean includeThrowerName) { ++ // CraftBukkit start - SPIGOT-2942: Add boolean to call event ++ return drop(droppedItem, dropAround, includeThrowerName, true); ++ } ++ ++ @Nullable ++ public ItemEntity drop(ItemStack itemstack, boolean flag, boolean flag1, boolean callEvent) { ++ // CraftBukkit end + if (itemstack.isEmpty()) { + return null; + } else { + if (this.level().isClientSide) { +- this.swing(InteractionHand.MAIN_HAND); ++ this.swing(EnumHand.MAIN_HAND); + } + + double d0 = this.getEyeY() - 0.30000001192092896D; +- ItemEntity itementity = new ItemEntity(this.level(), this.getX(), d0, this.getZ(), itemstack); ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), d0, this.getZ(), itemstack); + +- itementity.setPickUpDelay(40); ++ entityitem.setPickUpDelay(40); + if (flag1) { +- itementity.setThrower(this); ++ entityitem.setThrower(this); + } + + float f; +@@ -705,7 +722,7 @@ + if (flag) { + f = this.random.nextFloat() * 0.5F; + f1 = this.random.nextFloat() * 6.2831855F; +- itementity.setDeltaMovement((double) (-Mth.sin(f1) * f), 0.20000000298023224D, (double) (Mth.cos(f1) * f)); ++ entityitem.setDeltaMovement((double) (-Mth.sin(f1) * f), 0.20000000298023224D, (double) (Mth.cos(f1) * f)); + } else { + f = 0.3F; + f1 = Mth.sin(this.getXRot() * 0.017453292F); +@@ -715,15 +732,42 @@ + float f5 = this.random.nextFloat() * 6.2831855F; + float f6 = 0.02F * this.random.nextFloat(); + +- itementity.setDeltaMovement((double) (-f3 * f2 * 0.3F) + Math.cos((double) f5) * (double) f6, (double) (-f1 * 0.3F + 0.1F + (this.random.nextFloat() - this.random.nextFloat()) * 0.1F), (double) (f4 * f2 * 0.3F) + Math.sin((double) f5) * (double) f6); ++ entityitem.setDeltaMovement((double) (-f3 * f2 * 0.3F) + Math.cos((double) f5) * (double) f6, (double) (-f1 * 0.3F + 0.1F + (this.random.nextFloat() - this.random.nextFloat()) * 0.1F), (double) (f4 * f2 * 0.3F) + Math.sin((double) f5) * (double) f6); + } + +- return itementity; ++ // CraftBukkit start - fire PlayerDropItemEvent ++ if (!callEvent) { // SPIGOT-2942: Add boolean to call event ++ return entityitem; ++ } ++ org.bukkit.entity.Player player = (org.bukkit.entity.Player) this.getBukkitEntity(); ++ Item drop = (Item) entityitem.getBukkitEntity(); ++ ++ PlayerDropItemEvent event = new PlayerDropItemEvent(player, drop); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ org.bukkit.inventory.ItemStack cur = player.getInventory().getItemInHand(); ++ if (flag1 && (cur == null || cur.getAmount() == 0)) { ++ // The complete stack was dropped ++ player.getInventory().setItemInHand(drop.getItemStack()); ++ } else if (flag1 && cur.isSimilar(drop.getItemStack()) && cur.getAmount() < cur.getMaxStackSize() && drop.getItemStack().getAmount() == 1) { ++ // Only one item is dropped ++ cur.setAmount(cur.getAmount() + 1); ++ player.getInventory().setItemInHand(cur); ++ } else { ++ // Fallback ++ player.getInventory().addItem(drop.getItemStack()); ++ } ++ return null; ++ } ++ // CraftBukkit end ++ ++ return entityitem; + } + } + +- public float getDestroySpeed(BlockState blockstate) { +- float f = this.inventory.getDestroySpeed(blockstate); ++ public float getDestroySpeed(IBlockData state) { ++ float f = this.inventory.getDestroySpeed(state); + + if (f > 1.0F) { + int i = EnchantmentHelper.getBlockEfficiency(this); +@@ -770,46 +814,45 @@ + return f; + } + +- public boolean hasCorrectToolForDrops(BlockState blockstate) { +- return !blockstate.requiresCorrectToolForDrops() || this.inventory.getSelected().isCorrectToolForDrops(blockstate); ++ public boolean hasCorrectToolForDrops(IBlockData state) { ++ return !state.requiresCorrectToolForDrops() || this.inventory.getSelected().isCorrectToolForDrops(state); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); + this.setUUID(this.gameProfile.getId()); +- ListTag listtag = compoundtag.getList("Inventory", 10); ++ ListTag nbttaglist = compound.getList("Inventory", 10); + +- this.inventory.load(listtag); +- this.inventory.selected = compoundtag.getInt("SelectedItemSlot"); +- this.sleepCounter = compoundtag.getShort("SleepTimer"); +- this.experienceProgress = compoundtag.getFloat("XpP"); +- this.experienceLevel = compoundtag.getInt("XpLevel"); +- this.totalExperience = compoundtag.getInt("XpTotal"); +- this.enchantmentSeed = compoundtag.getInt("XpSeed"); ++ this.inventory.load(nbttaglist); ++ this.inventory.selected = compound.getInt("SelectedItemSlot"); ++ this.sleepCounter = compound.getShort("SleepTimer"); ++ this.experienceProgress = compound.getFloat("XpP"); ++ this.experienceLevel = compound.getInt("XpLevel"); ++ this.totalExperience = compound.getInt("XpTotal"); ++ this.enchantmentSeed = compound.getInt("XpSeed"); + if (this.enchantmentSeed == 0) { + this.enchantmentSeed = this.random.nextInt(); + } + +- this.setScore(compoundtag.getInt("Score")); +- this.foodData.readAdditionalSaveData(compoundtag); +- this.abilities.loadSaveData(compoundtag); ++ this.setScore(compound.getInt("Score")); ++ this.foodData.readAdditionalSaveData(compound); ++ this.abilities.loadSaveData(compound); + this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue((double) this.abilities.getWalkingSpeed()); +- if (compoundtag.contains("EnderItems", 9)) { +- this.enderChestInventory.fromTag(compoundtag.getList("EnderItems", 10)); ++ if (compound.contains("EnderItems", 9)) { ++ this.enderChestInventory.fromTag(compound.getList("EnderItems", 10)); + } + +- if (compoundtag.contains("ShoulderEntityLeft", 10)) { +- this.setShoulderEntityLeft(compoundtag.getCompound("ShoulderEntityLeft")); ++ if (compound.contains("ShoulderEntityLeft", 10)) { ++ this.setShoulderEntityLeft(compound.getCompound("ShoulderEntityLeft")); + } + +- if (compoundtag.contains("ShoulderEntityRight", 10)) { +- this.setShoulderEntityRight(compoundtag.getCompound("ShoulderEntityRight")); ++ if (compound.contains("ShoulderEntityRight", 10)) { ++ this.setShoulderEntityRight(compound.getCompound("ShoulderEntityRight")); + } + +- if (compoundtag.contains("LastDeathLocation", 10)) { +- DataResult dataresult = GlobalPos.CODEC.parse(NbtOps.INSTANCE, compoundtag.get("LastDeathLocation")); ++ if (compound.contains("LastDeathLocation", 10)) { ++ DataResult dataresult = GlobalPos.CODEC.parse(NbtOps.INSTANCE, compound.get("LastDeathLocation")); // CraftBukkit - decompile error + Logger logger = Player.LOGGER; + + Objects.requireNonNull(logger); +@@ -819,52 +862,49 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- NbtUtils.addCurrentDataVersion(compoundtag); +- compoundtag.put("Inventory", this.inventory.save(new ListTag())); +- compoundtag.putInt("SelectedItemSlot", this.inventory.selected); +- compoundtag.putShort("SleepTimer", (short) this.sleepCounter); +- compoundtag.putFloat("XpP", this.experienceProgress); +- compoundtag.putInt("XpLevel", this.experienceLevel); +- compoundtag.putInt("XpTotal", this.totalExperience); +- compoundtag.putInt("XpSeed", this.enchantmentSeed); +- compoundtag.putInt("Score", this.getScore()); +- this.foodData.addAdditionalSaveData(compoundtag); +- this.abilities.addSaveData(compoundtag); +- compoundtag.put("EnderItems", this.enderChestInventory.createTag()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ NbtUtils.addCurrentDataVersion(compound); ++ compound.put("Inventory", this.inventory.save(new ListTag())); ++ compound.putInt("SelectedItemSlot", this.inventory.selected); ++ compound.putShort("SleepTimer", (short) this.sleepCounter); ++ compound.putFloat("XpP", this.experienceProgress); ++ compound.putInt("XpLevel", this.experienceLevel); ++ compound.putInt("XpTotal", this.totalExperience); ++ compound.putInt("XpSeed", this.enchantmentSeed); ++ compound.putInt("Score", this.getScore()); ++ this.foodData.addAdditionalSaveData(compound); ++ this.abilities.addSaveData(compound); ++ compound.put("EnderItems", this.enderChestInventory.createTag()); + if (!this.getShoulderEntityLeft().isEmpty()) { +- compoundtag.put("ShoulderEntityLeft", this.getShoulderEntityLeft()); ++ compound.put("ShoulderEntityLeft", this.getShoulderEntityLeft()); + } + + if (!this.getShoulderEntityRight().isEmpty()) { +- compoundtag.put("ShoulderEntityRight", this.getShoulderEntityRight()); ++ compound.put("ShoulderEntityRight", this.getShoulderEntityRight()); + } + + this.getLastDeathLocation().flatMap((globalpos) -> { +- DataResult dataresult = GlobalPos.CODEC.encodeStart(NbtOps.INSTANCE, globalpos); ++ DataResult dataresult = GlobalPos.CODEC.encodeStart(NbtOps.INSTANCE, globalpos); // CraftBukkit - decompile error + Logger logger = Player.LOGGER; + + Objects.requireNonNull(logger); + return dataresult.resultOrPartial(logger::error); +- }).ifPresent((tag) -> { +- compoundtag.put("LastDeathLocation", tag); ++ }).ifPresent((nbtbase) -> { ++ compound.put("LastDeathLocation", nbtbase); + }); + } + + @Override +- @Override +- public boolean isInvulnerableTo(DamageSource damagesource) { +- return super.isInvulnerableTo(damagesource) ? true : (damagesource.is(DamageTypeTags.IS_DROWNING) ? !this.level().getGameRules().getBoolean(GameRules.RULE_DROWNING_DAMAGE) : (damagesource.is(DamageTypeTags.IS_FALL) ? !this.level().getGameRules().getBoolean(GameRules.RULE_FALL_DAMAGE) : (damagesource.is(DamageTypeTags.IS_FIRE) ? !this.level().getGameRules().getBoolean(GameRules.RULE_FIRE_DAMAGE) : (damagesource.is(DamageTypeTags.IS_FREEZING) ? !this.level().getGameRules().getBoolean(GameRules.RULE_FREEZE_DAMAGE) : false)))); ++ public boolean isInvulnerableTo(DamageSource source) { ++ return super.isInvulnerableTo(source) ? true : (source.is(DamageTypeTags.IS_DROWNING) ? !this.level().getGameRules().getBoolean(GameRules.RULE_DROWNING_DAMAGE) : (source.is(DamageTypeTags.IS_FALL) ? !this.level().getGameRules().getBoolean(GameRules.RULE_FALL_DAMAGE) : (source.is(DamageTypeTags.IS_FIRE) ? !this.level().getGameRules().getBoolean(GameRules.RULE_FIRE_DAMAGE) : (source.is(DamageTypeTags.IS_FREEZING) ? !this.level().getGameRules().getBoolean(GameRules.RULE_FREEZE_DAMAGE) : false)))); + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- if (this.isInvulnerableTo(damagesource)) { ++ public boolean hurt(DamageSource source, float amount) { ++ if (this.isInvulnerableTo(source)) { + return false; +- } else if (this.abilities.invulnerable && !damagesource.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { ++ } else if (this.abilities.invulnerable && !source.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { + return false; + } else { + this.noActionTime = 0; +@@ -872,80 +912,100 @@ + return false; + } else { + if (!this.level().isClientSide) { +- this.removeEntitiesOnShoulder(); ++ // this.removeEntitiesOnShoulder(); // CraftBukkit - moved down + } + +- if (damagesource.scalesWithDifficulty()) { ++ if (source.scalesWithDifficulty()) { + if (this.level().getDifficulty() == Difficulty.PEACEFUL) { +- f = 0.0F; ++ return false; // CraftBukkit - f = 0.0f -> return false + } + + if (this.level().getDifficulty() == Difficulty.EASY) { +- f = Math.min(f / 2.0F + 1.0F, f); ++ amount = Math.min(amount / 2.0F + 1.0F, amount); + } + + if (this.level().getDifficulty() == Difficulty.HARD) { +- f = f * 3.0F / 2.0F; ++ amount = amount * 3.0F / 2.0F; + } + } + +- return f == 0.0F ? false : super.hurt(damagesource, f); ++ // CraftBukkit start - Don't filter out 0 damage ++ boolean damaged = super.hurt(source, amount); ++ if (damaged) { ++ this.removeEntitiesOnShoulder(); ++ } ++ return damaged; ++ // CraftBukkit end + } + } + } + + @Override +- @Override +- protected void blockUsingShield(LivingEntity livingentity) { +- super.blockUsingShield(livingentity); +- if (livingentity.canDisableShield()) { ++ protected void blockUsingShield(LivingEntity entity) { ++ super.blockUsingShield(entity); ++ if (entity.canDisableShield()) { + this.disableShield(true); + } + + } + + @Override +- @Override + public boolean canBeSeenAsEnemy() { + return !this.getAbilities().invulnerable && super.canBeSeenAsEnemy(); + } + +- public boolean canHarmPlayer(Player player) { +- PlayerTeam playerteam = this.getTeam(); +- PlayerTeam playerteam1 = player.getTeam(); ++ public boolean canHarmPlayer(Player other) { ++ // CraftBukkit start - Change to check OTHER player's scoreboard team according to API ++ // To summarize this method's logic, it's "Can parameter hurt this" ++ org.bukkit.scoreboard.Team team; ++ if (other instanceof ServerPlayer) { ++ ServerPlayer thatPlayer = (ServerPlayer) other; ++ team = thatPlayer.getBukkitEntity().getScoreboard().getPlayerTeam(thatPlayer.getBukkitEntity()); ++ if (team == null || team.allowFriendlyFire()) { ++ return true; ++ } ++ } else { ++ // This should never be called, but is implemented anyway ++ org.bukkit.OfflinePlayer thisPlayer = other.level().getCraftServer().getOfflinePlayer(other.getScoreboardName()); ++ team = other.level().getCraftServer().getScoreboardManager().getMainScoreboard().getPlayerTeam(thisPlayer); ++ if (team == null || team.allowFriendlyFire()) { ++ return true; ++ } ++ } + +- return playerteam == null ? true : (!playerteam.isAlliedTo(playerteam1) ? true : playerteam.isAllowFriendlyFire()); ++ if (this instanceof ServerPlayer) { ++ return !team.hasPlayer(((ServerPlayer) this).getBukkitEntity()); ++ } ++ return !team.hasPlayer(this.level().getCraftServer().getOfflinePlayer(this.getScoreboardName())); ++ // CraftBukkit end + } + + @Override +- @Override +- protected void hurtArmor(DamageSource damagesource, float f) { +- this.inventory.hurtArmor(damagesource, f, Inventory.ALL_ARMOR_SLOTS); ++ protected void hurtArmor(DamageSource damageSource, float damage) { ++ this.inventory.hurtArmor(damageSource, damage, Inventory.ALL_ARMOR_SLOTS); + } + + @Override +- @Override +- protected void hurtHelmet(DamageSource damagesource, float f) { +- this.inventory.hurtArmor(damagesource, f, Inventory.HELMET_SLOT_ONLY); ++ protected void hurtHelmet(DamageSource damageSource, float damageAmount) { ++ this.inventory.hurtArmor(damageSource, damageAmount, Inventory.HELMET_SLOT_ONLY); + } + + @Override +- @Override +- protected void hurtCurrentlyUsedShield(float f) { ++ protected void hurtCurrentlyUsedShield(float damage) { + if (this.useItem.is(Items.SHIELD)) { + if (!this.level().isClientSide) { + this.awardStat(Stats.ITEM_USED.get(this.useItem.getItem())); + } + +- if (f >= 3.0F) { +- int i = 1 + Mth.floor(f); +- InteractionHand interactionhand = this.getUsedItemHand(); ++ if (damage >= 3.0F) { ++ int i = 1 + Mth.floor(damage); ++ EnumHand enumhand = this.getUsedItemHand(); + +- this.useItem.hurtAndBreak(i, this, (player) -> { +- player.broadcastBreakEvent(interactionhand); ++ this.useItem.hurtAndBreak(i, this, (entityhuman) -> { ++ entityhuman.broadcastBreakEvent(enumhand); + }); + if (this.useItem.isEmpty()) { +- if (interactionhand == InteractionHand.MAIN_HAND) { ++ if (enumhand == EnumHand.MAIN_HAND) { + this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); + } else { + this.setItemSlot(EquipmentSlot.OFFHAND, ItemStack.EMPTY); +@@ -959,9 +1019,13 @@ + } + } + ++ // CraftBukkit start + @Override +- @Override +- protected void actuallyHurt(DamageSource damagesource, float f) { ++ protected boolean damageEntity0(DamageSource damagesource, float f) { // void -> boolean ++ if (true) { ++ return super.damageEntity0(damagesource, f); ++ } ++ // CraftBukkit end + if (!this.isInvulnerableTo(damagesource)) { + f = this.getDamageAfterArmorAbsorb(damagesource, f); + f = this.getDamageAfterMagicAbsorb(damagesource, f); +@@ -976,7 +1040,7 @@ + } + + if (f != 0.0F) { +- this.causeFoodExhaustion(damagesource.getFoodExhaustion()); ++ this.causeFoodExhaustion(damagesource.getFoodExhaustion(), EntityExhaustionEvent.ExhaustionReason.DAMAGED); // CraftBukkit - EntityExhaustionEvent + this.getCombatTracker().recordDamage(damagesource, f); + this.setHealth(this.getHealth() - f); + if (f < 3.4028235E37F) { +@@ -986,10 +1050,10 @@ + this.gameEvent(GameEvent.ENTITY_DAMAGE); + } + } ++ return false; // CraftBukkit + } + + @Override +- @Override + protected boolean onSoulSpeedBlock() { + return !this.abilities.flying && super.onSoulSpeedBlock(); + } +@@ -998,59 +1062,59 @@ + return false; + } + +- public void openTextEdit(SignBlockEntity signblockentity, boolean flag) {} ++ public void openTextEdit(SignBlockEntity signEntity, boolean isFrontText) {} + +- public void openMinecartCommandBlock(BaseCommandBlock basecommandblock) {} ++ public void openMinecartCommandBlock(BaseCommandBlock commandEntity) {} + +- public void openCommandBlock(CommandBlockEntity commandblockentity) {} ++ public void openCommandBlock(CommandBlockEntity commandBlockEntity) {} + +- public void openStructureBlock(StructureBlockEntity structureblockentity) {} ++ public void openStructureBlock(StructureBlockEntity structureEntity) {} + +- public void openJigsawBlock(JigsawBlockEntity jigsawblockentity) {} ++ public void openJigsawBlock(JigsawBlockEntity jigsawBlockEntity) {} + +- public void openHorseInventory(AbstractHorse abstracthorse, Container container) {} ++ public void openHorseInventory(AbstractHorse horse, Container inventory) {} + +- public OptionalInt openMenu(@Nullable MenuProvider menuprovider) { ++ public OptionalInt openMenu(@Nullable ITileInventory menu) { + return OptionalInt.empty(); + } + +- public void sendMerchantOffers(int i, MerchantOffers merchantoffers, int j, int k, boolean flag, boolean flag1) {} ++ public void sendMerchantOffers(int containerId, MerchantOffers offers, int villagerLevel, int villagerXp, boolean showProgress, boolean canRestock) {} + +- public void openItemGui(ItemStack itemstack, InteractionHand interactionhand) {} ++ public void openItemGui(ItemStack stack, EnumHand hand) {} + +- public InteractionResult interactOn(Entity entity, InteractionHand interactionhand) { ++ public InteractionResult interactOn(Entity entityToInteractOn, EnumHand hand) { + if (this.isSpectator()) { +- if (entity instanceof MenuProvider) { +- this.openMenu((MenuProvider) entity); ++ if (entityToInteractOn instanceof ITileInventory) { ++ this.openMenu((ITileInventory) entityToInteractOn); + } + + return InteractionResult.PASS; + } else { +- ItemStack itemstack = this.getItemInHand(interactionhand); ++ ItemStack itemstack = this.getItemInHand(hand); + ItemStack itemstack1 = itemstack.copy(); +- InteractionResult interactionresult = entity.interact(this, interactionhand); ++ InteractionResult enuminteractionresult = entityToInteractOn.interact(this, hand); + +- if (interactionresult.consumesAction()) { +- if (this.abilities.instabuild && itemstack == this.getItemInHand(interactionhand) && itemstack.getCount() < itemstack1.getCount()) { ++ if (enuminteractionresult.consumesAction()) { ++ if (this.abilities.instabuild && itemstack == this.getItemInHand(hand) && itemstack.getCount() < itemstack1.getCount()) { + itemstack.setCount(itemstack1.getCount()); + } + +- return interactionresult; ++ return enuminteractionresult; + } else { +- if (!itemstack.isEmpty() && entity instanceof LivingEntity) { ++ if (!itemstack.isEmpty() && entityToInteractOn instanceof LivingEntity) { + if (this.abilities.instabuild) { + itemstack = itemstack1; + } + +- InteractionResult interactionresult1 = itemstack.interactLivingEntity(this, (LivingEntity) entity, interactionhand); ++ InteractionResult enuminteractionresult1 = itemstack.interactLivingEntity(this, (LivingEntity) entityToInteractOn, hand); + +- if (interactionresult1.consumesAction()) { +- this.level().gameEvent(GameEvent.ENTITY_INTERACT, entity.position(), GameEvent.Context.of((Entity) this)); ++ if (enuminteractionresult1.consumesAction()) { ++ this.level().gameEvent(GameEvent.ENTITY_INTERACT, entityToInteractOn.position(), GameEvent.Context.of((Entity) this)); + if (itemstack.isEmpty() && !this.abilities.instabuild) { +- this.setItemInHand(interactionhand, ItemStack.EMPTY); ++ this.setItemInHand(hand, ItemStack.EMPTY); + } + +- return interactionresult1; ++ return enuminteractionresult1; + } + } + +@@ -1060,36 +1124,31 @@ + } + + @Override +- @Override + protected float ridingOffset(Entity entity) { + return -0.6F; + } + + @Override +- @Override + public void removeVehicle() { + super.removeVehicle(); + this.boardingCooldown = 0; + } + + @Override +- @Override + protected boolean isImmobile() { + return super.isImmobile() || this.isSleeping(); + } + + @Override +- @Override + public boolean isAffectedByFluids() { + return !this.abilities.flying; + } + + @Override +- @Override +- protected Vec3 maybeBackOffFromEdge(Vec3 vec3, MoverType movertype) { +- if (!this.abilities.flying && vec3.y <= 0.0D && (movertype == MoverType.SELF || movertype == MoverType.PLAYER) && this.isStayingOnGroundSurface() && this.isAboveGround()) { +- double d0 = vec3.x; +- double d1 = vec3.z; ++ protected Vec3 maybeBackOffFromEdge(Vec3 vec, EnumMoveType mover) { ++ if (!this.abilities.flying && vec.y <= 0.0D && (mover == EnumMoveType.SELF || mover == EnumMoveType.PLAYER) && this.isStayingOnGroundSurface() && this.isAboveGround()) { ++ double d0 = vec.x; ++ double d1 = vec.z; + double d2 = 0.05D; + + while (d0 != 0.0D && this.level().noCollision(this, this.getBoundingBox().move(d0, (double) (-this.maxUpStep()), 0.0D))) { +@@ -1130,33 +1189,33 @@ + } + } + +- vec3 = new Vec3(d0, vec3.y, d1); ++ vec = new Vec3(d0, vec.y, d1); + } + +- return vec3; ++ return vec; + } + + private boolean isAboveGround() { + return this.onGround() || this.fallDistance < this.maxUpStep() && !this.level().noCollision(this, this.getBoundingBox().move(0.0D, (double) (this.fallDistance - this.maxUpStep()), 0.0D)); + } + +- public void attack(Entity entity) { +- if (entity.isAttackable()) { +- if (!entity.skipAttackInteraction(this)) { ++ public void attack(Entity target) { ++ if (target.isAttackable()) { ++ if (!target.skipAttackInteraction(this)) { + float f = (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE); + float f1; + +- if (entity instanceof LivingEntity) { +- f1 = EnchantmentHelper.getDamageBonus(this.getMainHandItem(), ((LivingEntity) entity).getMobType()); ++ if (target instanceof LivingEntity) { ++ f1 = EnchantmentHelper.getDamageBonus(this.getMainHandItem(), ((LivingEntity) target).getMobType()); + } else { +- f1 = EnchantmentHelper.getDamageBonus(this.getMainHandItem(), MobType.UNDEFINED); ++ f1 = EnchantmentHelper.getDamageBonus(this.getMainHandItem(), EnumMonsterType.UNDEFINED); + } + + float f2 = this.getAttackStrengthScale(0.5F); + + f *= 0.2F + f2 * f2 * 0.8F; + f1 *= f2; +- this.resetAttackStrengthTicker(); ++ // this.resetAttackCooldown(); // CraftBukkit - Moved to EntityLiving to reset the cooldown after the damage is dealt + if (f > 0.0F || f1 > 0.0F) { + boolean flag = f2 > 0.9F; + boolean flag1 = false; +@@ -1169,7 +1228,7 @@ + flag1 = true; + } + +- boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround() && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && entity instanceof LivingEntity; ++ boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround() && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity; + + flag2 = flag2 && !this.isSprinting(); + if (flag2) { +@@ -1181,7 +1240,7 @@ + double d0 = (double) (this.walkDist - this.walkDistO); + + if (flag && !flag2 && !flag1 && this.onGround() && d0 < (double) this.getSpeed()) { +- ItemStack itemstack = this.getItemInHand(InteractionHand.MAIN_HAND); ++ ItemStack itemstack = this.getItemInHand(EnumHand.MAIN_HAND); + + if (itemstack.getItem() instanceof SwordItem) { + flag3 = true; +@@ -1192,23 +1251,30 @@ + boolean flag4 = false; + int j = EnchantmentHelper.getFireAspect(this); + +- if (entity instanceof LivingEntity) { +- f3 = ((LivingEntity) entity).getHealth(); +- if (j > 0 && !entity.isOnFire()) { +- flag4 = true; +- entity.setSecondsOnFire(1); ++ if (target instanceof LivingEntity) { ++ f3 = ((LivingEntity) target).getHealth(); ++ if (j > 0 && !target.isOnFire()) { ++ // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), target.getBukkitEntity(), 1); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ flag4 = true; ++ target.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + } + +- Vec3 vec3 = entity.getDeltaMovement(); +- boolean flag5 = entity.hurt(this.damageSources().playerAttack(this), f); ++ Vec3 vec3d = target.getDeltaMovement(); ++ boolean flag5 = target.hurt(this.damageSources().playerAttack(this), f); + + if (flag5) { + if (i > 0) { +- if (entity instanceof LivingEntity) { +- ((LivingEntity) entity).knockback((double) ((float) i * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F))); ++ if (target instanceof LivingEntity) { ++ ((LivingEntity) target).knockback((double) ((float) i * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F))); + } else { +- entity.push((double) (-Mth.sin(this.getYRot() * 0.017453292F) * (float) i * 0.5F), 0.1D, (double) (Mth.cos(this.getYRot() * 0.017453292F) * (float) i * 0.5F)); ++ target.push((double) (-Mth.sin(this.getYRot() * 0.017453292F) * (float) i * 0.5F), 0.1D, (double) (Mth.cos(this.getYRot() * 0.017453292F) * (float) i * 0.5F)); + } + + this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D)); +@@ -1217,15 +1283,18 @@ + + if (flag3) { + float f4 = 1.0F + EnchantmentHelper.getSweepingDamageRatio(this) * f; +- List list = this.level().getEntitiesOfClass(LivingEntity.class, entity.getBoundingBox().inflate(1.0D, 0.25D, 1.0D)); ++ List list = this.level().getEntitiesOfClass(LivingEntity.class, target.getBoundingBox().inflate(1.0D, 0.25D, 1.0D)); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- LivingEntity livingentity = (LivingEntity) iterator.next(); ++ LivingEntity entityliving = (LivingEntity) iterator.next(); + +- if (livingentity != this && livingentity != entity && !this.isAlliedTo((Entity) livingentity) && (!(livingentity instanceof ArmorStand) || !((ArmorStand) livingentity).isMarker()) && this.distanceToSqr((Entity) livingentity) < 9.0D) { +- livingentity.knockback(0.4000000059604645D, (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F))); +- livingentity.hurt(this.damageSources().playerAttack(this), f4); ++ if (entityliving != this && entityliving != target && !this.isAlliedTo((Entity) entityliving) && (!(entityliving instanceof ArmorStand) || !((ArmorStand) entityliving).isMarker()) && this.distanceToSqr((Entity) entityliving) < 9.0D) { ++ // CraftBukkit start - Only apply knockback if the damage hits ++ if (entityliving.hurt(this.damageSources().playerAttack(this).sweep(), f4)) { ++ entityliving.knockback(0.4000000059604645D, (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F))); ++ } ++ // CraftBukkit end + } + } + +@@ -1233,15 +1302,32 @@ + this.sweepAttack(); + } + +- if (entity instanceof ServerPlayer && entity.hurtMarked) { +- ((ServerPlayer) entity).connection.send(new ClientboundSetEntityMotionPacket(entity)); +- entity.hurtMarked = false; +- entity.setDeltaMovement(vec3); ++ if (target instanceof ServerPlayer && target.hurtMarked) { ++ // CraftBukkit start - Add Velocity Event ++ boolean cancelled = false; ++ org.bukkit.entity.Player player = (org.bukkit.entity.Player) target.getBukkitEntity(); ++ org.bukkit.util.Vector velocity = CraftVector.toBukkit(vec3d); ++ ++ PlayerVelocityEvent event = new PlayerVelocityEvent(player, velocity.clone()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ cancelled = true; ++ } else if (!velocity.equals(event.getVelocity())) { ++ player.setVelocity(event.getVelocity()); ++ } ++ ++ if (!cancelled) { ++ ((ServerPlayer) target).connection.send(new ClientboundSetEntityMotionPacket(target)); ++ target.hurtMarked = false; ++ target.setDeltaMovement(vec3d); ++ } ++ // CraftBukkit end + } + + if (flag2) { + this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.getSoundSource(), 1.0F, 1.0F); +- this.crit(entity); ++ this.crit(target); + } + + if (!flag2 && !flag3) { +@@ -1253,50 +1339,62 @@ + } + + if (f1 > 0.0F) { +- this.magicCrit(entity); ++ this.magicCrit(target); + } + +- this.setLastHurtMob(entity); +- if (entity instanceof LivingEntity) { +- EnchantmentHelper.doPostHurtEffects((LivingEntity) entity, this); ++ this.setLastHurtMob(target); ++ if (target instanceof LivingEntity) { ++ EnchantmentHelper.doPostHurtEffects((LivingEntity) target, this); + } + +- EnchantmentHelper.doPostDamageEffects(this, entity); ++ EnchantmentHelper.doPostDamageEffects(this, target); + ItemStack itemstack1 = this.getMainHandItem(); +- Object object = entity; ++ Object object = target; + +- if (entity instanceof EnderDragonPart) { +- object = ((EnderDragonPart) entity).parentMob; ++ if (target instanceof EnderDragonPart) { ++ object = ((EnderDragonPart) target).parentMob; + } + + if (!this.level().isClientSide && !itemstack1.isEmpty() && object instanceof LivingEntity) { + itemstack1.hurtEnemy((LivingEntity) object, this); + if (itemstack1.isEmpty()) { +- this.setItemInHand(InteractionHand.MAIN_HAND, ItemStack.EMPTY); ++ this.setItemInHand(EnumHand.MAIN_HAND, ItemStack.EMPTY); + } + } + +- if (entity instanceof LivingEntity) { +- float f5 = f3 - ((LivingEntity) entity).getHealth(); ++ if (target instanceof LivingEntity) { ++ float f5 = f3 - ((LivingEntity) target).getHealth(); + + this.awardStat(Stats.DAMAGE_DEALT, Math.round(f5 * 10.0F)); + if (j > 0) { +- entity.setSecondsOnFire(j * 4); ++ // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), target.getBukkitEntity(), j * 4); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ target.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + + if (this.level() instanceof ServerLevel && f5 > 2.0F) { + int k = (int) ((double) f5 * 0.5D); + +- ((ServerLevel) this.level()).sendParticles(ParticleTypes.DAMAGE_INDICATOR, entity.getX(), entity.getY(0.5D), entity.getZ(), k, 0.1D, 0.0D, 0.1D, 0.2D); ++ ((ServerLevel) this.level()).sendParticles(ParticleTypes.DAMAGE_INDICATOR, target.getX(), target.getY(0.5D), target.getZ(), k, 0.1D, 0.0D, 0.1D, 0.2D); + } + } + +- this.causeFoodExhaustion(0.1F); ++ this.causeFoodExhaustion(0.1F, EntityExhaustionEvent.ExhaustionReason.ATTACK); // CraftBukkit - EntityExhaustionEvent + } else { + this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F); + if (flag4) { +- entity.clearFire(); ++ target.clearFire(); + } ++ // CraftBukkit start - resync on cancelled event ++ if (this instanceof ServerPlayer) { ++ ((ServerPlayer) this).getBukkitEntity().updateInventory(); ++ } ++ // CraftBukkit end + } + } + +@@ -1305,15 +1403,14 @@ + } + + @Override +- @Override +- protected void doAutoAttackOnTouch(LivingEntity livingentity) { +- this.attack(livingentity); ++ protected void doAutoAttackOnTouch(LivingEntity target) { ++ this.attack(target); + } + +- public void disableShield(boolean flag) { ++ public void disableShield(boolean becauseOfAxe) { + float f = 0.25F + (float) EnchantmentHelper.getBlockEfficiency(this) * 0.05F; + +- if (flag) { ++ if (becauseOfAxe) { + f += 0.75F; + } + +@@ -1325,9 +1422,9 @@ + + } + +- public void crit(Entity entity) {} ++ public void crit(Entity entityHit) {} + +- public void magicCrit(Entity entity) {} ++ public void magicCrit(Entity entityHit) {} + + public void sweepAttack() { + double d0 = (double) (-Mth.sin(this.getYRot() * 0.017453292F)); +@@ -1342,9 +1439,8 @@ + public void respawn() {} + + @Override +- @Override +- public void remove(Entity.RemovalReason entity_removalreason) { +- super.remove(entity_removalreason); ++ public void remove(Entity.RemovalReason reason) { ++ super.remove(reason); + this.inventoryMenu.removed(this); + if (this.containerMenu != null && this.hasContainerOpen()) { + this.doCloseContainer(); +@@ -1368,55 +1464,60 @@ + return this.abilities; + } + +- public void updateTutorialInventoryAction(ItemStack itemstack, ItemStack itemstack1, ClickAction clickaction) {} ++ public void updateTutorialInventoryAction(ItemStack carried, ItemStack clicked, ClickAction action) {} + + public boolean hasContainerOpen() { + return this.containerMenu != this.inventoryMenu; + } + +- public Either startSleepInBed(BlockPos blockpos) { +- this.startSleeping(blockpos); ++ public Either startSleepInBed(BlockPos bedPos) { ++ // CraftBukkit start ++ return this.startSleepInBed(bedPos, false); ++ } ++ ++ public Either startSleepInBed(BlockPos blockposition, boolean force) { ++ // CraftBukkit end ++ this.startSleeping(blockposition); + this.sleepCounter = 0; + return Either.right(Unit.INSTANCE); + } + +- public void stopSleepInBed(boolean flag, boolean flag1) { ++ public void stopSleepInBed(boolean wakeImmediately, boolean updateLevelForSleepingPlayers) { + super.stopSleeping(); +- if (this.level() instanceof ServerLevel && flag1) { ++ if (this.level() instanceof ServerLevel && updateLevelForSleepingPlayers) { + ((ServerLevel) this.level()).updateSleepingPlayerList(); + } + +- this.sleepCounter = flag ? 0 : 100; ++ this.sleepCounter = wakeImmediately ? 0 : 100; + } + + @Override +- @Override + public void stopSleeping() { + this.stopSleepInBed(true, true); + } + +- public static Optional findRespawnPositionAndUseSpawnBlock(ServerLevel serverlevel, BlockPos blockpos, float f, boolean flag, boolean flag1) { +- BlockState blockstate = serverlevel.getBlockState(blockpos); +- Block block = blockstate.getBlock(); ++ public static Optional findRespawnPositionAndUseSpawnBlock(ServerLevel serverLevel, BlockPos spawnBlockPos, float playerOrientation, boolean isRespawnForced, boolean respawnAfterWinningTheGame) { ++ IBlockData iblockdata = serverLevel.getBlockState(spawnBlockPos); ++ Block block = iblockdata.getBlock(); + +- if (block instanceof RespawnAnchorBlock && (flag || (Integer) blockstate.getValue(RespawnAnchorBlock.CHARGE) > 0) && RespawnAnchorBlock.canSetSpawn(serverlevel)) { +- Optional optional = RespawnAnchorBlock.findStandUpPosition(EntityType.PLAYER, serverlevel, blockpos); ++ if (block instanceof RespawnAnchorBlock && (isRespawnForced || (Integer) iblockdata.getValue(RespawnAnchorBlock.CHARGE) > 0) && RespawnAnchorBlock.canSetSpawn(serverLevel)) { ++ Optional optional = RespawnAnchorBlock.findStandUpPosition(EntityType.PLAYER, serverLevel, spawnBlockPos); + +- if (!flag && !flag1 && optional.isPresent()) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(RespawnAnchorBlock.CHARGE, (Integer) blockstate.getValue(RespawnAnchorBlock.CHARGE) - 1), 3); ++ if (!isRespawnForced && !respawnAfterWinningTheGame && optional.isPresent()) { ++ serverLevel.setBlock(spawnBlockPos, (IBlockData) iblockdata.setValue(RespawnAnchorBlock.CHARGE, (Integer) iblockdata.getValue(RespawnAnchorBlock.CHARGE) - 1), 3); + } + + return optional; +- } else if (block instanceof BedBlock && BedBlock.canSetSpawn(serverlevel)) { +- return BedBlock.findStandUpPosition(EntityType.PLAYER, serverlevel, blockpos, (Direction) blockstate.getValue(BedBlock.FACING), f); +- } else if (!flag) { ++ } else if (block instanceof BedBlock && BedBlock.canSetSpawn(serverLevel)) { ++ return BedBlock.findStandUpPosition(EntityType.PLAYER, serverLevel, spawnBlockPos, (Direction) iblockdata.getValue(BedBlock.FACING), playerOrientation); ++ } else if (!isRespawnForced) { + return Optional.empty(); + } else { +- boolean flag2 = block.isPossibleToRespawnInThis(blockstate); +- BlockState blockstate1 = serverlevel.getBlockState(blockpos.above()); +- boolean flag3 = blockstate1.getBlock().isPossibleToRespawnInThis(blockstate1); ++ boolean flag2 = block.isPossibleToRespawnInThis(iblockdata); ++ IBlockData iblockdata1 = serverLevel.getBlockState(spawnBlockPos.above()); ++ boolean flag3 = iblockdata1.getBlock().isPossibleToRespawnInThis(iblockdata1); + +- return flag2 && flag3 ? Optional.of(new Vec3((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.1D, (double) blockpos.getZ() + 0.5D)) : Optional.empty(); ++ return flag2 && flag3 ? Optional.of(new Vec3((double) spawnBlockPos.getX() + 0.5D, (double) spawnBlockPos.getY() + 0.1D, (double) spawnBlockPos.getZ() + 0.5D)) : Optional.empty(); + } + } + +@@ -1428,25 +1529,25 @@ + return this.sleepCounter; + } + +- public void displayClientMessage(Component component, boolean flag) {} ++ public void displayClientMessage(Component chatComponent, boolean actionBar) {} + +- public void awardStat(ResourceLocation resourcelocation) { +- this.awardStat(Stats.CUSTOM.get(resourcelocation)); ++ public void awardStat(ResourceLocation statKey) { ++ this.awardStat(Stats.CUSTOM.get(statKey)); + } + +- public void awardStat(ResourceLocation resourcelocation, int i) { +- this.awardStat(Stats.CUSTOM.get(resourcelocation), i); ++ public void awardStat(ResourceLocation stat, int increment) { ++ this.awardStat(Stats.CUSTOM.get(stat), increment); + } + + public void awardStat(Stat stat) { + this.awardStat(stat, 1); + } + +- public void awardStat(Stat stat, int i) {} ++ public void awardStat(Stat stat, int increment) {} + + public void resetStat(Stat stat) {} + +- public int awardRecipes(Collection> collection) { ++ public int awardRecipes(Collection> recipes) { + return 0; + } + +@@ -1454,26 +1555,24 @@ + + public void awardRecipesByKey(List list) {} + +- public int resetRecipes(Collection> collection) { ++ public int resetRecipes(Collection> recipes) { + return 0; + } + + @Override +- @Override + public void jumpFromGround() { + super.jumpFromGround(); + this.awardStat(Stats.JUMP); + if (this.isSprinting()) { +- this.causeFoodExhaustion(0.2F); ++ this.causeFoodExhaustion(0.2F, EntityExhaustionEvent.ExhaustionReason.JUMP_SPRINT); // CraftBukkit - EntityExhaustionEvent + } else { +- this.causeFoodExhaustion(0.05F); ++ this.causeFoodExhaustion(0.05F, EntityExhaustionEvent.ExhaustionReason.JUMP); // CraftBukkit - EntityExhaustionEvent + } + + } + + @Override +- @Override +- public void travel(Vec3 vec3) { ++ public void travel(Vec3 travelVector) { + double d0; + + if (this.isSwimming() && !this.isPassenger()) { +@@ -1481,28 +1580,31 @@ + double d1 = d0 < -0.2D ? 0.085D : 0.06D; + + if (d0 <= 0.0D || this.jumping || !this.level().getBlockState(BlockPos.containing(this.getX(), this.getY() + 1.0D - 0.1D, this.getZ())).getFluidState().isEmpty()) { +- Vec3 vec31 = this.getDeltaMovement(); ++ Vec3 vec3d1 = this.getDeltaMovement(); + +- this.setDeltaMovement(vec31.add(0.0D, (d0 - vec31.y) * d1, 0.0D)); ++ this.setDeltaMovement(vec3d1.add(0.0D, (d0 - vec3d1.y) * d1, 0.0D)); + } + } + + if (this.abilities.flying && !this.isPassenger()) { + d0 = this.getDeltaMovement().y; +- super.travel(vec3); +- Vec3 vec32 = this.getDeltaMovement(); ++ super.travel(travelVector); ++ Vec3 vec3d2 = this.getDeltaMovement(); + +- this.setDeltaMovement(vec32.x, d0 * 0.6D, vec32.z); ++ this.setDeltaMovement(vec3d2.x, d0 * 0.6D, vec3d2.z); + this.resetFallDistance(); +- this.setSharedFlag(7, false); ++ // CraftBukkit start ++ if (getSharedFlag(7) && !org.bukkit.craftbukkit.event.CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) { ++ this.setSharedFlag(7, false); ++ } ++ // CraftBukkit end + } else { +- super.travel(vec3); ++ super.travel(travelVector); + } + + } + + @Override +- @Override + public void updateSwimming() { + if (this.abilities.flying) { + this.setSwimming(false); +@@ -1512,27 +1614,25 @@ + + } + +- protected boolean freeAt(BlockPos blockpos) { +- return !this.level().getBlockState(blockpos).isSuffocating(this.level(), blockpos); ++ protected boolean freeAt(BlockPos pos) { ++ return !this.level().getBlockState(pos).isSuffocating(this.level(), pos); + } + + @Override +- @Override + public float getSpeed() { + return (float) this.getAttributeValue(Attributes.MOVEMENT_SPEED); + } + + @Override +- @Override +- public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { ++ public boolean causeFallDamage(float fallDistance, float multiplier, DamageSource source) { + if (this.abilities.mayfly) { + return false; + } else { +- if (f >= 2.0F) { +- this.awardStat(Stats.FALL_ONE_CM, (int) Math.round((double) f * 100.0D)); ++ if (fallDistance >= 2.0F) { ++ this.awardStat(Stats.FALL_ONE_CM, (int) Math.round((double) fallDistance * 100.0D)); + } + +- return super.causeFallDamage(f, f1, damagesource); ++ return super.causeFallDamage(fallDistance, multiplier, source); + } + } + +@@ -1550,16 +1650,27 @@ + } + + public void startFallFlying() { +- this.setSharedFlag(7, true); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callToggleGlideEvent(this, true).isCancelled()) { ++ this.setSharedFlag(7, true); ++ } else { ++ // SPIGOT-5542: must toggle like below ++ this.setSharedFlag(7, true); ++ this.setSharedFlag(7, false); ++ } ++ // CraftBukkit end + } + + public void stopFallFlying() { ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) { + this.setSharedFlag(7, true); + this.setSharedFlag(7, false); ++ } ++ // CraftBukkit end + } + + @Override +- @Override + protected void doWaterSplashEffect() { + if (!this.isSpectator()) { + super.doWaterSplashEffect(); +@@ -1568,55 +1679,51 @@ + } + + @Override +- @Override +- protected void playStepSound(BlockPos blockpos, BlockState blockstate) { ++ protected void playStepSound(BlockPos pos, IBlockData state) { + if (this.isInWater()) { + this.waterSwimSound(); +- this.playMuffledStepSound(blockstate); ++ this.playMuffledStepSound(state); + } else { +- BlockPos blockpos1 = this.getPrimaryStepSoundBlockPos(blockpos); ++ BlockPos blockposition1 = this.getPrimaryStepSoundBlockPos(pos); + +- if (!blockpos.equals(blockpos1)) { +- BlockState blockstate1 = this.level().getBlockState(blockpos1); ++ if (!pos.equals(blockposition1)) { ++ IBlockData iblockdata1 = this.level().getBlockState(blockposition1); + +- if (blockstate1.is(BlockTags.COMBINATION_STEP_SOUND_BLOCKS)) { +- this.playCombinationStepSounds(blockstate1, blockstate); ++ if (iblockdata1.is(BlockTags.COMBINATION_STEP_SOUND_BLOCKS)) { ++ this.playCombinationStepSounds(iblockdata1, state); + } else { +- super.playStepSound(blockpos1, blockstate1); ++ super.playStepSound(blockposition1, iblockdata1); + } + } else { +- super.playStepSound(blockpos, blockstate); ++ super.playStepSound(pos, state); + } + } + + } + + @Override +- @Override +- public LivingEntity.Fallsounds getFallSounds() { +- return new LivingEntity.Fallsounds(SoundEvents.PLAYER_SMALL_FALL, SoundEvents.PLAYER_BIG_FALL); ++ public LivingEntity.a getFallSounds() { ++ return new LivingEntity.a(SoundEvents.PLAYER_SMALL_FALL, SoundEvents.PLAYER_BIG_FALL); + } + + @Override +- @Override +- public boolean killedEntity(ServerLevel serverlevel, LivingEntity livingentity) { +- this.awardStat(Stats.ENTITY_KILLED.get(livingentity.getType())); ++ public boolean killedEntity(ServerLevel level, LivingEntity entity) { ++ this.awardStat(Stats.ENTITY_KILLED.get(entity.getType())); + return true; + } + + @Override +- @Override +- public void makeStuckInBlock(BlockState blockstate, Vec3 vec3) { ++ public void makeStuckInBlock(IBlockData state, Vec3 motionMultiplier) { + if (!this.abilities.flying) { +- super.makeStuckInBlock(blockstate, vec3); ++ super.makeStuckInBlock(state, motionMultiplier); + } + + } + +- public void giveExperiencePoints(int i) { +- this.increaseScore(i); +- this.experienceProgress += (float) i / (float) this.getXpNeededForNextLevel(); +- this.totalExperience = Mth.clamp(this.totalExperience + i, 0, Integer.MAX_VALUE); ++ public void giveExperiencePoints(int xpPoints) { ++ this.increaseScore(xpPoints); ++ this.experienceProgress += (float) xpPoints / (float) this.getXpNeededForNextLevel(); ++ this.totalExperience = Mth.clamp(this.totalExperience + xpPoints, 0, Integer.MAX_VALUE); + + while (this.experienceProgress < 0.0F) { + float f = this.experienceProgress * (float) this.getXpNeededForNextLevel(); +@@ -1642,8 +1749,8 @@ + return this.enchantmentSeed; + } + +- public void onEnchantmentPerformed(ItemStack itemstack, int i) { +- this.experienceLevel -= i; ++ public void onEnchantmentPerformed(ItemStack enchantedItem, int levelCost) { ++ this.experienceLevel -= levelCost; + if (this.experienceLevel < 0) { + this.experienceLevel = 0; + this.experienceProgress = 0.0F; +@@ -1653,15 +1760,15 @@ + this.enchantmentSeed = this.random.nextInt(); + } + +- public void giveExperienceLevels(int i) { +- this.experienceLevel += i; ++ public void giveExperienceLevels(int levels) { ++ this.experienceLevel += levels; + if (this.experienceLevel < 0) { + this.experienceLevel = 0; + this.experienceProgress = 0.0F; + this.totalExperience = 0; + } + +- if (i > 0 && this.experienceLevel % 5 == 0 && (float) this.lastLevelUpTime < (float) this.tickCount - 100.0F) { ++ if (levels > 0 && this.experienceLevel % 5 == 0 && (float) this.lastLevelUpTime < (float) this.tickCount - 100.0F) { + float f = this.experienceLevel > 30 ? 1.0F : (float) this.experienceLevel / 30.0F; + + this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_LEVELUP, this.getSoundSource(), f * 0.75F, 1.0F); +@@ -1674,10 +1781,21 @@ + return this.experienceLevel >= 30 ? 112 + (this.experienceLevel - 30) * 9 : (this.experienceLevel >= 15 ? 37 + (this.experienceLevel - 15) * 5 : 7 + this.experienceLevel * 2); + } + +- public void causeFoodExhaustion(float f) { ++ // CraftBukkit start ++ public void causeFoodExhaustion(float exhaustion) { ++ this.causeFoodExhaustion(exhaustion, EntityExhaustionEvent.ExhaustionReason.UNKNOWN); ++ } ++ ++ public void causeFoodExhaustion(float f, EntityExhaustionEvent.ExhaustionReason reason) { ++ // CraftBukkit end + if (!this.abilities.invulnerable) { + if (!this.level().isClientSide) { +- this.foodData.addExhaustion(f); ++ // CraftBukkit start ++ EntityExhaustionEvent event = CraftEventFactory.callPlayerExhaustionEvent(this, reason, f); ++ if (!event.isCancelled()) { ++ this.foodData.addExhaustion(event.getExhaustion()); ++ } ++ // CraftBukkit end + } + + } +@@ -1691,8 +1809,8 @@ + return this.foodData; + } + +- public boolean canEat(boolean flag) { +- return this.abilities.invulnerable || flag || this.foodData.needsFood(); ++ public boolean canEat(boolean canAlwaysEat) { ++ return this.abilities.invulnerable || canAlwaysEat || this.foodData.needsFood(); + } + + public boolean isHurt() { +@@ -1703,19 +1821,18 @@ + return this.abilities.mayBuild; + } + +- public boolean mayUseItemAt(BlockPos blockpos, Direction direction, ItemStack itemstack) { ++ public boolean mayUseItemAt(BlockPos pos, Direction facing, ItemStack stack) { + if (this.abilities.mayBuild) { + return true; + } else { +- BlockPos blockpos1 = blockpos.relative(direction.getOpposite()); +- BlockInWorld blockinworld = new BlockInWorld(this.level(), blockpos1, false); ++ BlockPos blockposition1 = pos.relative(facing.getOpposite()); ++ BlockInWorld shapedetectorblock = new BlockInWorld(this.level(), blockposition1, false); + +- return itemstack.hasAdventureModePlaceTagForBlock(this.level().registryAccess().registryOrThrow(Registries.BLOCK), blockinworld); ++ return stack.hasAdventureModePlaceTagForBlock(this.level().registryAccess().registryOrThrow(Registries.BLOCK), shapedetectorblock); + } + } + + @Override +- @Override + public int getExperienceReward() { + if (!this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) && !this.isSpectator()) { + int i = this.experienceLevel * 7; +@@ -1727,19 +1844,16 @@ + } + + @Override +- @Override + protected boolean isAlwaysExperienceDropper() { + return true; + } + + @Override +- @Override + public boolean shouldShowName() { + return true; + } + + @Override +- @Override + protected Entity.MovementEmission getMovementEmission() { + return !this.abilities.flying && (!this.onGround() || !this.isDiscrete()) ? Entity.MovementEmission.ALL : Entity.MovementEmission.NONE; + } +@@ -1747,7 +1861,6 @@ + public void onUpdateAbilities() {} + + @Override +- @Override + public Component getName() { + return Component.literal(this.gameProfile.getName()); + } +@@ -1757,55 +1870,57 @@ + } + + @Override ++ public ItemStack getItemBySlot(EquipmentSlot slot) { ++ return slot == EquipmentSlot.MAINHAND ? this.inventory.getSelected() : (slot == EquipmentSlot.OFFHAND ? (ItemStack) this.inventory.offhand.get(0) : (slot.getType() == EquipmentSlot.Function.ARMOR ? (ItemStack) this.inventory.armor.get(slot.getIndex()) : ItemStack.EMPTY)); ++ } ++ + @Override +- public ItemStack getItemBySlot(EquipmentSlot equipmentslot) { +- return equipmentslot == EquipmentSlot.MAINHAND ? this.inventory.getSelected() : (equipmentslot == EquipmentSlot.OFFHAND ? (ItemStack) this.inventory.offhand.get(0) : (equipmentslot.getType() == EquipmentSlot.Type.ARMOR ? (ItemStack) this.inventory.armor.get(equipmentslot.getIndex()) : ItemStack.EMPTY)); ++ protected boolean doesEmitEquipEvent(EquipmentSlot slot) { ++ return slot.getType() == EquipmentSlot.Function.ARMOR; + } + + @Override +- @Override +- protected boolean doesEmitEquipEvent(EquipmentSlot equipmentslot) { +- return equipmentslot.getType() == EquipmentSlot.Type.ARMOR; ++ public void setItemSlot(EquipmentSlot slot, ItemStack stack) { ++ // CraftBukkit start ++ setItemSlot(slot, stack, false); + } + + @Override +- @Override +- public void setItemSlot(EquipmentSlot equipmentslot, ItemStack itemstack) { ++ public void setItemSlot(EquipmentSlot enumitemslot, ItemStack itemstack, boolean silent) { ++ // CraftBukkit end + this.verifyEquippedItem(itemstack); +- if (equipmentslot == EquipmentSlot.MAINHAND) { +- this.onEquipItem(equipmentslot, (ItemStack) this.inventory.items.set(this.inventory.selected, itemstack), itemstack); +- } else if (equipmentslot == EquipmentSlot.OFFHAND) { +- this.onEquipItem(equipmentslot, (ItemStack) this.inventory.offhand.set(0, itemstack), itemstack); +- } else if (equipmentslot.getType() == EquipmentSlot.Type.ARMOR) { +- this.onEquipItem(equipmentslot, (ItemStack) this.inventory.armor.set(equipmentslot.getIndex(), itemstack), itemstack); ++ if (enumitemslot == EquipmentSlot.MAINHAND) { ++ this.onEquipItem(enumitemslot, (ItemStack) this.inventory.items.set(this.inventory.selected, itemstack), itemstack, silent); // CraftBukkit ++ } else if (enumitemslot == EquipmentSlot.OFFHAND) { ++ this.onEquipItem(enumitemslot, (ItemStack) this.inventory.offhand.set(0, itemstack), itemstack, silent); // CraftBukkit ++ } else if (enumitemslot.getType() == EquipmentSlot.Function.ARMOR) { ++ this.onEquipItem(enumitemslot, (ItemStack) this.inventory.armor.set(enumitemslot.getIndex(), itemstack), itemstack, silent); // CraftBukkit + } + + } + +- public boolean addItem(ItemStack itemstack) { +- return this.inventory.add(itemstack); ++ public boolean addItem(ItemStack stack) { ++ return this.inventory.add(stack); + } + + @Override +- @Override + public Iterable getHandSlots() { + return Lists.newArrayList(new ItemStack[]{this.getMainHandItem(), this.getOffhandItem()}); + } + + @Override +- @Override + public Iterable getArmorSlots() { + return this.inventory.armor; + } + +- public boolean setEntityOnShoulder(CompoundTag compoundtag) { ++ public boolean setEntityOnShoulder(CompoundTag entityCompound) { + if (!this.isPassenger() && this.onGround() && !this.isInWater() && !this.isInPowderSnow) { + if (this.getShoulderEntityLeft().isEmpty()) { +- this.setShoulderEntityLeft(compoundtag); ++ this.setShoulderEntityLeft(entityCompound); + this.timeEntitySatOnShoulder = this.level().getGameTime(); + return true; + } else if (this.getShoulderEntityRight().isEmpty()) { +- this.setShoulderEntityRight(compoundtag); ++ this.setShoulderEntityRight(entityCompound); + this.timeEntitySatOnShoulder = this.level().getGameTime(); + return true; + } else { +@@ -1818,40 +1933,42 @@ + + protected void removeEntitiesOnShoulder() { + if (this.timeEntitySatOnShoulder + 20L < this.level().getGameTime()) { +- this.respawnEntityOnShoulder(this.getShoulderEntityLeft()); +- this.setShoulderEntityLeft(new CompoundTag()); +- this.respawnEntityOnShoulder(this.getShoulderEntityRight()); +- this.setShoulderEntityRight(new CompoundTag()); ++ // CraftBukkit start ++ if (this.respawnEntityOnShoulder(this.getShoulderEntityLeft())) { ++ this.setShoulderEntityLeft(new CompoundTag()); ++ } ++ if (this.respawnEntityOnShoulder(this.getShoulderEntityRight())) { ++ this.setShoulderEntityRight(new CompoundTag()); ++ } ++ // CraftBukkit end + } + + } + +- private void respawnEntityOnShoulder(CompoundTag compoundtag) { +- if (!this.level().isClientSide && !compoundtag.isEmpty()) { +- EntityType.create(compoundtag, this.level()).ifPresent((entity) -> { ++ private boolean respawnEntityOnShoulder(CompoundTag nbttagcompound) { // CraftBukkit void->boolean ++ if (!this.level().isClientSide && !nbttagcompound.isEmpty()) { ++ return EntityType.create(nbttagcompound, this.level()).map((entity) -> { // CraftBukkit + if (entity instanceof TamableAnimal) { + ((TamableAnimal) entity).setOwnerUUID(this.uuid); + } + + entity.setPos(this.getX(), this.getY() + 0.699999988079071D, this.getZ()); +- ((ServerLevel) this.level()).addWithUUID(entity); +- }); ++ return ((ServerLevel) this.level()).addWithUUID(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit ++ }).orElse(true); // CraftBukkit + } + ++ return true; // CraftBukkit + } + + @Override +- @Override + public abstract boolean isSpectator(); + + @Override +- @Override + public boolean canBeHitByProjectile() { + return !this.isSpectator() && super.canBeHitByProjectile(); + } + + @Override +- @Override + public boolean isSwimming() { + return !this.abilities.flying && !this.isSpectator() && super.isSwimming(); + } +@@ -1859,7 +1976,6 @@ + public abstract boolean isCreative(); + + @Override +- @Override + public boolean isPushedByFluid() { + return !this.abilities.flying; + } +@@ -1869,30 +1985,27 @@ + } + + @Override +- @Override + public Component getDisplayName() { +- MutableComponent mutablecomponent = PlayerTeam.formatNameForTeam(this.getTeam(), this.getName()); ++ MutableComponent ichatmutablecomponent = PlayerTeam.formatNameForTeam(this.getTeam(), this.getName()); + +- return this.decorateDisplayNameComponent(mutablecomponent); ++ return this.decorateDisplayNameComponent(ichatmutablecomponent); + } + +- private MutableComponent decorateDisplayNameComponent(MutableComponent mutablecomponent) { ++ private MutableComponent decorateDisplayNameComponent(MutableComponent displayName) { + String s = this.getGameProfile().getName(); + +- return mutablecomponent.withStyle((style) -> { +- return style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/tell " + s + " ")).withHoverEvent(this.createHoverEvent()).withInsertion(s); ++ return displayName.withStyle((chatmodifier) -> { ++ return chatmodifier.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/tell " + s + " ")).withHoverEvent(this.createHoverEvent()).withInsertion(s); + }); + } + + @Override +- @Override + public String getScoreboardName() { + return this.getGameProfile().getName(); + } + + @Override +- @Override +- public float getStandingEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ public float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + switch (pose) { + case SWIMMING: + case FALL_FLYING: +@@ -1906,30 +2019,27 @@ + } + + @Override +- @Override + protected void internalSetAbsorptionAmount(float f) { + this.getEntityData().set(Player.DATA_PLAYER_ABSORPTION_ID, f); + } + + @Override +- @Override + public float getAbsorptionAmount() { + return (Float) this.getEntityData().get(Player.DATA_PLAYER_ABSORPTION_ID); + } + +- public boolean isModelPartShown(PlayerModelPart playermodelpart) { +- return ((Byte) this.getEntityData().get(Player.DATA_PLAYER_MODE_CUSTOMISATION) & playermodelpart.getMask()) == playermodelpart.getMask(); ++ public boolean isModelPartShown(PlayerModelPart part) { ++ return ((Byte) this.getEntityData().get(Player.DATA_PLAYER_MODE_CUSTOMISATION) & part.getMask()) == part.getMask(); + } + + @Override +- @Override +- public SlotAccess getSlot(int i) { +- if (i >= 0 && i < this.inventory.items.size()) { +- return SlotAccess.forContainer(this.inventory, i); ++ public SlotAccess getSlot(int slot) { ++ if (slot >= 0 && slot < this.inventory.items.size()) { ++ return SlotAccess.forContainer(this.inventory, slot); + } else { +- int j = i - 200; ++ int j = slot - 200; + +- return j >= 0 && j < this.enderChestInventory.getContainerSize() ? SlotAccess.forContainer(this.enderChestInventory, j) : super.getSlot(i); ++ return j >= 0 && j < this.enderChestInventory.getContainerSize() ? SlotAccess.forContainer(this.enderChestInventory, j) : super.getSlot(slot); + } + } + +@@ -1937,48 +2047,46 @@ + return this.reducedDebugInfo; + } + +- public void setReducedDebugInfo(boolean flag) { +- this.reducedDebugInfo = flag; ++ public void setReducedDebugInfo(boolean reducedDebugInfo) { ++ this.reducedDebugInfo = reducedDebugInfo; + } + + @Override +- @Override +- public void setRemainingFireTicks(int i) { +- super.setRemainingFireTicks(this.abilities.invulnerable ? Math.min(i, 1) : i); ++ public void setRemainingFireTicks(int ticks) { ++ super.setRemainingFireTicks(this.abilities.invulnerable ? Math.min(ticks, 1) : ticks); + } + + @Override +- @Override + public HumanoidArm getMainArm() { + return (Byte) this.entityData.get(Player.DATA_PLAYER_MAIN_HAND) == 0 ? HumanoidArm.LEFT : HumanoidArm.RIGHT; + } + +- public void setMainArm(HumanoidArm humanoidarm) { +- this.entityData.set(Player.DATA_PLAYER_MAIN_HAND, (byte) (humanoidarm == HumanoidArm.LEFT ? 0 : 1)); ++ public void setMainArm(HumanoidArm hand) { ++ this.entityData.set(Player.DATA_PLAYER_MAIN_HAND, (byte) (hand == HumanoidArm.LEFT ? 0 : 1)); + } + + public CompoundTag getShoulderEntityLeft() { + return (CompoundTag) this.entityData.get(Player.DATA_SHOULDER_LEFT); + } + +- protected void setShoulderEntityLeft(CompoundTag compoundtag) { +- this.entityData.set(Player.DATA_SHOULDER_LEFT, compoundtag); ++ public void setShoulderEntityLeft(CompoundTag entityCompound) { ++ this.entityData.set(Player.DATA_SHOULDER_LEFT, entityCompound); + } + + public CompoundTag getShoulderEntityRight() { + return (CompoundTag) this.entityData.get(Player.DATA_SHOULDER_RIGHT); + } + +- protected void setShoulderEntityRight(CompoundTag compoundtag) { +- this.entityData.set(Player.DATA_SHOULDER_RIGHT, compoundtag); ++ public void setShoulderEntityRight(CompoundTag entityCompound) { ++ this.entityData.set(Player.DATA_SHOULDER_RIGHT, entityCompound); + } + + public float getCurrentItemAttackStrengthDelay() { + return (float) (1.0D / this.getAttributeValue(Attributes.ATTACK_SPEED) * 20.0D); + } + +- public float getAttackStrengthScale(float f) { +- return Mth.clamp(((float) this.attackStrengthTicker + f) / this.getCurrentItemAttackStrengthDelay(), 0.0F, 1.0F); ++ public float getAttackStrengthScale(float adjustTicks) { ++ return Mth.clamp(((float) this.attackStrengthTicker + adjustTicks) / this.getCurrentItemAttackStrengthDelay(), 0.0F, 1.0F); + } + + public void resetAttackStrengthTicker() { +@@ -1990,7 +2098,6 @@ + } + + @Override +- @Override + protected float getBlockSpeedFactor() { + return !this.abilities.flying && !this.isFallFlying() ? super.getBlockSpeedFactor() : 1.0F; + } +@@ -2004,38 +2111,34 @@ + } + + @Override +- @Override + public boolean canTakeItem(ItemStack itemstack) { +- EquipmentSlot equipmentslot = Mob.getEquipmentSlotForItem(itemstack); ++ EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(itemstack); + +- return this.getItemBySlot(equipmentslot).isEmpty(); ++ return this.getItemBySlot(enumitemslot).isEmpty(); + } + + @Override +- @Override +- public EntityDimensions getDimensions(Pose pose) { ++ public EntityDimensions getDimensions(EntityPose pose) { + return (EntityDimensions) Player.POSES.getOrDefault(pose, Player.STANDING_DIMENSIONS); + } + + @Override +- @Override +- public ImmutableList getDismountPoses() { +- return ImmutableList.of(Pose.STANDING, Pose.CROUCHING, Pose.SWIMMING); ++ public ImmutableList getDismountPoses() { ++ return ImmutableList.of(EntityPose.STANDING, EntityPose.CROUCHING, EntityPose.SWIMMING); + } + + @Override +- @Override +- public ItemStack getProjectile(ItemStack itemstack) { +- if (!(itemstack.getItem() instanceof ProjectileWeaponItem)) { ++ public ItemStack getProjectile(ItemStack shootable) { ++ if (!(shootable.getItem() instanceof ProjectileWeaponItem)) { + return ItemStack.EMPTY; + } else { +- Predicate predicate = ((ProjectileWeaponItem) itemstack.getItem()).getSupportedHeldProjectiles(); ++ Predicate predicate = ((ProjectileWeaponItem) shootable.getItem()).getSupportedHeldProjectiles(); + ItemStack itemstack1 = ProjectileWeaponItem.getHeldProjectile(this, predicate); + + if (!itemstack1.isEmpty()) { + return itemstack1; + } else { +- predicate = ((ProjectileWeaponItem) itemstack.getItem()).getAllSupportedProjectiles(); ++ predicate = ((ProjectileWeaponItem) shootable.getItem()).getAllSupportedProjectiles(); + + for (int i = 0; i < this.inventory.getContainerSize(); ++i) { + ItemStack itemstack2 = this.inventory.getItem(i); +@@ -2051,64 +2154,60 @@ + } + + @Override +- @Override +- public ItemStack eat(Level level, ItemStack itemstack) { +- this.getFoodData().eat(itemstack.getItem(), itemstack); +- this.awardStat(Stats.ITEM_USED.get(itemstack.getItem())); ++ public ItemStack eat(Level level, ItemStack food) { ++ this.getFoodData().eat(food.getItem(), food); ++ this.awardStat(Stats.ITEM_USED.get(food.getItem())); + level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_BURP, SoundSource.PLAYERS, 0.5F, level.random.nextFloat() * 0.1F + 0.9F); + if (this instanceof ServerPlayer) { +- CriteriaTriggers.CONSUME_ITEM.trigger((ServerPlayer) this, itemstack); ++ CriteriaTriggers.CONSUME_ITEM.trigger((ServerPlayer) this, food); + } + +- return super.eat(level, itemstack); ++ return super.eat(level, food); + } + + @Override +- @Override +- protected boolean shouldRemoveSoulSpeed(BlockState blockstate) { +- return this.abilities.flying || super.shouldRemoveSoulSpeed(blockstate); ++ protected boolean shouldRemoveSoulSpeed(IBlockData state) { ++ return this.abilities.flying || super.shouldRemoveSoulSpeed(state); + } + + @Override +- @Override +- public Vec3 getRopeHoldPosition(float f) { ++ public Vec3 getRopeHoldPosition(float partialTicks) { + double d0 = 0.22D * (this.getMainArm() == HumanoidArm.RIGHT ? -1.0D : 1.0D); +- float f1 = Mth.lerp(f * 0.5F, this.getXRot(), this.xRotO) * 0.017453292F; +- float f2 = Mth.lerp(f, this.yBodyRotO, this.yBodyRot) * 0.017453292F; ++ float f1 = Mth.lerp(partialTicks * 0.5F, this.getXRot(), this.xRotO) * 0.017453292F; ++ float f2 = Mth.lerp(partialTicks, this.yBodyRotO, this.yBodyRot) * 0.017453292F; + double d1; + + if (!this.isFallFlying() && !this.isAutoSpinAttack()) { + if (this.isVisuallySwimming()) { +- return this.getPosition(f).add((new Vec3(d0, 0.2D, -0.15D)).xRot(-f1).yRot(-f2)); ++ return this.getPosition(partialTicks).add((new Vec3(d0, 0.2D, -0.15D)).xRot(-f1).yRot(-f2)); + } else { + double d2 = this.getBoundingBox().getYsize() - 1.0D; + + d1 = this.isCrouching() ? -0.2D : 0.07D; +- return this.getPosition(f).add((new Vec3(d0, d2, d1)).yRot(-f2)); ++ return this.getPosition(partialTicks).add((new Vec3(d0, d2, d1)).yRot(-f2)); + } + } else { +- Vec3 vec3 = this.getViewVector(f); +- Vec3 vec31 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getViewVector(partialTicks); ++ Vec3 vec3d1 = this.getDeltaMovement(); + +- d1 = vec31.horizontalDistanceSqr(); +- double d3 = vec3.horizontalDistanceSqr(); ++ d1 = vec3d1.horizontalDistanceSqr(); ++ double d3 = vec3d.horizontalDistanceSqr(); + float f3; + + if (d1 > 0.0D && d3 > 0.0D) { +- double d4 = (vec31.x * vec3.x + vec31.z * vec3.z) / Math.sqrt(d1 * d3); +- double d5 = vec31.x * vec3.z - vec31.z * vec3.x; ++ double d4 = (vec3d1.x * vec3d.x + vec3d1.z * vec3d.z) / Math.sqrt(d1 * d3); ++ double d5 = vec3d1.x * vec3d.z - vec3d1.z * vec3d.x; + + f3 = (float) (Math.signum(d5) * Math.acos(d4)); + } else { + f3 = 0.0F; + } + +- return this.getPosition(f).add((new Vec3(d0, -0.11D, 0.85D)).zRot(-f3).xRot(-f1).yRot(-f2)); ++ return this.getPosition(partialTicks).add((new Vec3(d0, -0.11D, 0.85D)).zRot(-f3).xRot(-f1).yRot(-f2)); + } + } + + @Override +- @Override + public boolean isAlwaysTicking() { + return true; + } +@@ -2118,7 +2217,6 @@ + } + + @Override +- @Override + public boolean shouldBeSaved() { + return false; + } +@@ -2127,31 +2225,27 @@ + return this.lastDeathLocation; + } + +- public void setLastDeathLocation(Optional optional) { +- this.lastDeathLocation = optional; ++ public void setLastDeathLocation(Optional lastDeathLocation) { ++ this.lastDeathLocation = lastDeathLocation; + } + + @Override +- @Override + public float getHurtDir() { + return this.hurtDir; + } + + @Override +- @Override +- public void animateHurt(float f) { +- super.animateHurt(f); +- this.hurtDir = f; ++ public void animateHurt(float yaw) { ++ super.animateHurt(yaw); ++ this.hurtDir = yaw; + } + + @Override +- @Override + public boolean canSprint() { + return true; + } + + @Override +- @Override + protected float getFlyingSpeed() { + return this.abilities.flying && !this.isPassenger() ? (this.isSprinting() ? this.abilities.getFlyingSpeed() * 2.0F : this.abilities.getFlyingSpeed()) : (this.isSprinting() ? 0.025999999F : 0.02F); + } +@@ -2177,8 +2271,8 @@ + this.message = null; + } + +- private BedSleepingProblem(Component component) { +- this.message = component; ++ private BedSleepingProblem(Component ichatbasecomponent) { ++ this.message = ichatbasecomponent; + } + + @Nullable diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/AbstractArrow.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/AbstractArrow.java.patch new file mode 100644 index 0000000000..85f7051cb2 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/AbstractArrow.java.patch @@ -0,0 +1,698 @@ +--- a/net/minecraft/world/entity/projectile/AbstractArrow.java ++++ b/net/minecraft/world/entity/projectile/AbstractArrow.java +@@ -27,11 +27,12 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.Attributes; ++import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.enchantment.EnchantmentHelper; +@@ -39,13 +40,16 @@ + import net.minecraft.world.level.ClipContext; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.player.PlayerPickupArrowEvent; ++// CraftBukkit end + + public abstract class AbstractArrow extends Projectile { + +@@ -56,23 +60,23 @@ + private static final int FLAG_NOPHYSICS = 2; + private static final int FLAG_CROSSBOW = 4; + @Nullable +- private BlockState lastState; +- protected boolean inGround; ++ private IBlockData lastState; ++ public boolean inGround; + protected int inGroundTime; + public AbstractArrow.Pickup pickup; + public int shakeTime; +- private int life; ++ public int life; + private double baseDamage; +- private int knockback; ++ public int knockback; + private SoundEvent soundEvent; + @Nullable + private IntOpenHashSet piercingIgnoreEntityIds; + @Nullable + private List piercedAndKilledEntities; +- private ItemStack pickupItemStack; ++ public ItemStack pickupItemStack; + +- protected AbstractArrow(EntityType entitytype, Level level, ItemStack itemstack) { +- super(entitytype, level); ++ protected AbstractArrow(EntityType entitytypes, Level world, ItemStack itemstack) { ++ super(entitytypes, world); + this.pickup = AbstractArrow.Pickup.DISALLOWED; + this.baseDamage = 2.0D; + this.soundEvent = this.getDefaultHitGroundSoundEvent(); +@@ -83,27 +87,26 @@ + + } + +- protected AbstractArrow(EntityType entitytype, double d0, double d1, double d2, Level level, ItemStack itemstack) { +- this(entitytype, level, itemstack); ++ protected AbstractArrow(EntityType entitytypes, double d0, double d1, double d2, Level world, ItemStack itemstack) { ++ this(entitytypes, world, itemstack); + this.setPos(d0, d1, d2); + } + +- protected AbstractArrow(EntityType entitytype, LivingEntity livingentity, Level level, ItemStack itemstack) { +- this(entitytype, livingentity.getX(), livingentity.getEyeY() - 0.10000000149011612D, livingentity.getZ(), level, itemstack); +- this.setOwner(livingentity); +- if (livingentity instanceof Player) { ++ protected AbstractArrow(EntityType entitytypes, LivingEntity entityliving, Level world, ItemStack itemstack) { ++ this(entitytypes, entityliving.getX(), entityliving.getEyeY() - 0.10000000149011612D, entityliving.getZ(), world, itemstack); ++ this.setOwner(entityliving); ++ if (entityliving instanceof Player) { + this.pickup = AbstractArrow.Pickup.ALLOWED; + } + + } + +- public void setSoundEvent(SoundEvent soundevent) { +- this.soundEvent = soundevent; ++ public void setSoundEvent(SoundEvent soundEvent) { ++ this.soundEvent = soundEvent; + } + + @Override +- @Override +- public boolean shouldRenderAtSqrDistance(double d0) { ++ public boolean shouldRenderAtSqrDistance(double distance) { + double d1 = this.getBoundingBox().getSize() * 10.0D; + + if (Double.isNaN(d1)) { +@@ -111,68 +114,63 @@ + } + + d1 *= 64.0D * getViewScale(); +- return d0 < d1 * d1; ++ return distance < d1 * d1; + } + + @Override +- @Override + protected void defineSynchedData() { + this.entityData.define(AbstractArrow.ID_FLAGS, (byte) 0); + this.entityData.define(AbstractArrow.PIERCE_LEVEL, (byte) 0); + } + + @Override +- @Override +- public void shoot(double d0, double d1, double d2, float f, float f1) { +- super.shoot(d0, d1, d2, f, f1); ++ public void shoot(double x, double d1, double y, float f, float z) { ++ super.shoot(x, d1, y, f, z); + this.life = 0; + } + + @Override +- @Override + public void lerpTo(double d0, double d1, double d2, float f, float f1, int i) { + this.setPos(d0, d1, d2); + this.setRot(f, f1); + } + + @Override +- @Override +- public void lerpMotion(double d0, double d1, double d2) { +- super.lerpMotion(d0, d1, d2); ++ public void lerpMotion(double x, double d1, double y) { ++ super.lerpMotion(x, d1, y); + this.life = 0; + } + + @Override +- @Override + public void tick() { + super.tick(); + boolean flag = this.isNoPhysics(); +- Vec3 vec3 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + + if (this.xRotO == 0.0F && this.yRotO == 0.0F) { +- double d0 = vec3.horizontalDistance(); ++ double d0 = vec3d.horizontalDistance(); + +- this.setYRot((float) (Mth.atan2(vec3.x, vec3.z) * 57.2957763671875D)); +- this.setXRot((float) (Mth.atan2(vec3.y, d0) * 57.2957763671875D)); ++ this.setYRot((float) (Mth.atan2(vec3d.x, vec3d.z) * 57.2957763671875D)); ++ this.setXRot((float) (Mth.atan2(vec3d.y, d0) * 57.2957763671875D)); + this.yRotO = this.getYRot(); + this.xRotO = this.getXRot(); + } + +- BlockPos blockpos = this.blockPosition(); +- BlockState blockstate = this.level().getBlockState(blockpos); +- Vec3 vec31; ++ BlockPos blockposition = this.blockPosition(); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); ++ Vec3 vec3d1; + +- if (!blockstate.isAir() && !flag) { +- VoxelShape voxelshape = blockstate.getCollisionShape(this.level(), blockpos); ++ if (!iblockdata.isAir() && !flag) { ++ VoxelShape voxelshape = iblockdata.getCollisionShape(this.level(), blockposition); + + if (!voxelshape.isEmpty()) { +- vec31 = this.position(); ++ vec3d1 = this.position(); + Iterator iterator = voxelshape.toAabbs().iterator(); + + while (iterator.hasNext()) { +- AABB aabb = (AABB) iterator.next(); ++ AABB axisalignedbb = (AABB) iterator.next(); + +- if (aabb.move(blockpos).contains(vec31)) { ++ if (axisalignedbb.move(blockposition).contains(vec3d1)) { + this.inGround = true; + break; + } +@@ -184,12 +182,12 @@ + --this.shakeTime; + } + +- if (this.isInWaterOrRain() || blockstate.is(Blocks.POWDER_SNOW)) { ++ if (this.isInWaterOrRain() || iblockdata.is(Blocks.POWDER_SNOW)) { + this.clearFire(); + } + + if (this.inGround && !flag) { +- if (this.lastState != blockstate && this.shouldFall()) { ++ if (this.lastState != iblockdata && this.shouldFall()) { + this.startFalling(); + } else if (!this.level().isClientSide) { + this.tickDespawn(); +@@ -198,48 +196,48 @@ + ++this.inGroundTime; + } else { + this.inGroundTime = 0; +- Vec3 vec32 = this.position(); ++ Vec3 vec3d2 = this.position(); + +- vec31 = vec32.add(vec3); +- Object object = this.level().clip(new ClipContext(vec32, vec31, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)); ++ vec3d1 = vec3d2.add(vec3d); ++ Object object = this.level().clip(new ClipContext(vec3d2, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)); + +- if (((HitResult) object).getType() != HitResult.Type.MISS) { +- vec31 = ((HitResult) object).getLocation(); ++ if (((HitResult) object).getType() != HitResult.EnumMovingObjectType.MISS) { ++ vec3d1 = ((HitResult) object).getLocation(); + } + + while (!this.isRemoved()) { +- EntityHitResult entityhitresult = this.findHitEntity(vec32, vec31); ++ EntityHitResult movingobjectpositionentity = this.findHitEntity(vec3d2, vec3d1); + +- if (entityhitresult != null) { +- object = entityhitresult; ++ if (movingobjectpositionentity != null) { ++ object = movingobjectpositionentity; + } + +- if (object != null && ((HitResult) object).getType() == HitResult.Type.ENTITY) { ++ if (object != null && ((HitResult) object).getType() == HitResult.EnumMovingObjectType.ENTITY) { + Entity entity = ((EntityHitResult) object).getEntity(); + Entity entity1 = this.getOwner(); + + if (entity instanceof Player && entity1 instanceof Player && !((Player) entity1).canHarmPlayer((Player) entity)) { + object = null; +- entityhitresult = null; ++ movingobjectpositionentity = null; + } + } + + if (object != null && !flag) { +- this.onHit((HitResult) object); ++ this.preOnHit((HitResult) object); // CraftBukkit - projectile hit event + this.hasImpulse = true; + } + +- if (entityhitresult == null || this.getPierceLevel() <= 0) { ++ if (movingobjectpositionentity == null || this.getPierceLevel() <= 0) { + break; + } + + object = null; + } + +- vec3 = this.getDeltaMovement(); +- double d1 = vec3.x; +- double d2 = vec3.y; +- double d3 = vec3.z; ++ vec3d = this.getDeltaMovement(); ++ double d1 = vec3d.x; ++ double d2 = vec3d.y; ++ double d3 = vec3d.z; + + if (this.isCritArrow()) { + for (int i = 0; i < 4; ++i) { +@@ -250,7 +248,7 @@ + double d4 = this.getX() + d1; + double d5 = this.getY() + d2; + double d6 = this.getZ() + d3; +- double d7 = vec3.horizontalDistance(); ++ double d7 = vec3d.horizontalDistance(); + + if (flag) { + this.setYRot((float) (Mth.atan2(-d1, -d3) * 57.2957763671875D)); +@@ -274,11 +272,11 @@ + f = this.getWaterInertia(); + } + +- this.setDeltaMovement(vec3.scale((double) f)); ++ this.setDeltaMovement(vec3d.scale((double) f)); + if (!this.isNoGravity() && !flag) { +- Vec3 vec33 = this.getDeltaMovement(); ++ Vec3 vec3d3 = this.getDeltaMovement(); + +- this.setDeltaMovement(vec33.x, vec33.y - 0.05000000074505806D, vec33.z); ++ this.setDeltaMovement(vec3d3.x, vec3d3.y - 0.05000000074505806D, vec3d3.z); + } + + this.setPos(d4, d5, d6); +@@ -292,17 +290,16 @@ + + private void startFalling() { + this.inGround = false; +- Vec3 vec3 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + +- this.setDeltaMovement(vec3.multiply((double) (this.random.nextFloat() * 0.2F), (double) (this.random.nextFloat() * 0.2F), (double) (this.random.nextFloat() * 0.2F))); ++ this.setDeltaMovement(vec3d.multiply((double) (this.random.nextFloat() * 0.2F), (double) (this.random.nextFloat() * 0.2F), (double) (this.random.nextFloat() * 0.2F))); + this.life = 0; + } + + @Override +- @Override +- public void move(MoverType movertype, Vec3 vec3) { +- super.move(movertype, vec3); +- if (movertype != MoverType.SELF && this.shouldFall()) { ++ public void move(EnumMoveType type, Vec3 pos) { ++ super.move(type, pos); ++ if (type != EnumMoveType.SELF && this.shouldFall()) { + this.startFalling(); + } + +@@ -328,10 +325,9 @@ + } + + @Override +- @Override +- protected void onHitEntity(EntityHitResult entityhitresult) { +- super.onHitEntity(entityhitresult); +- Entity entity = entityhitresult.getEntity(); ++ protected void onHitEntity(EntityHitResult result) { ++ super.onHitEntity(result); ++ Entity entity = result.getEntity(); + float f = (float) this.getDeltaMovement().length(); + int i = Mth.ceil(Mth.clamp((double) f * this.baseDamage, 0.0D, 2.147483647E9D)); + +@@ -375,7 +371,13 @@ + boolean flag1 = entity.getType().is(EntityTypeTags.DEFLECTS_ARROWS); + + if (this.isOnFire() && !flag && !flag1) { +- entity.setSecondsOnFire(5); ++ // CraftBukkit start ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), 5); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ if (!combustEvent.isCancelled()) { ++ entity.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + + if (entity.hurt(damagesource, (float) i)) { +@@ -384,42 +386,42 @@ + } + + if (entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; ++ LivingEntity entityliving = (LivingEntity) entity; + + if (!this.level().isClientSide && this.getPierceLevel() <= 0) { +- livingentity.setArrowCount(livingentity.getArrowCount() + 1); ++ entityliving.setArrowCount(entityliving.getArrowCount() + 1); + } + + if (this.knockback > 0) { +- double d0 = Math.max(0.0D, 1.0D - livingentity.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE)); +- Vec3 vec3 = this.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D).normalize().scale((double) this.knockback * 0.6D * d0); ++ double d0 = Math.max(0.0D, 1.0D - entityliving.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE)); ++ Vec3 vec3d = this.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D).normalize().scale((double) this.knockback * 0.6D * d0); + +- if (vec3.lengthSqr() > 0.0D) { +- livingentity.push(vec3.x, 0.1D, vec3.z); ++ if (vec3d.lengthSqr() > 0.0D) { ++ entityliving.push(vec3d.x, 0.1D, vec3d.z); + } + } + + if (!this.level().isClientSide && entity1 instanceof LivingEntity) { +- EnchantmentHelper.doPostHurtEffects(livingentity, entity1); +- EnchantmentHelper.doPostDamageEffects((LivingEntity) entity1, livingentity); ++ EnchantmentHelper.doPostHurtEffects(entityliving, entity1); ++ EnchantmentHelper.doPostDamageEffects((LivingEntity) entity1, entityliving); + } + +- this.doPostHurtEffects(livingentity); +- if (entity1 != null && livingentity != entity1 && livingentity instanceof Player && entity1 instanceof ServerPlayer && !this.isSilent()) { ++ this.doPostHurtEffects(entityliving); ++ if (entity1 != null && entityliving != entity1 && entityliving instanceof Player && entity1 instanceof ServerPlayer && !this.isSilent()) { + ((ServerPlayer) entity1).connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.ARROW_HIT_PLAYER, 0.0F)); + } + + if (!entity.isAlive() && this.piercedAndKilledEntities != null) { +- this.piercedAndKilledEntities.add(livingentity); ++ this.piercedAndKilledEntities.add(entityliving); + } + + if (!this.level().isClientSide && entity1 instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) entity1; ++ ServerPlayer entityplayer = (ServerPlayer) entity1; + + if (this.piercedAndKilledEntities != null && this.shotFromCrossbow()) { +- CriteriaTriggers.KILLED_BY_CROSSBOW.trigger(serverplayer, (Collection) this.piercedAndKilledEntities); ++ CriteriaTriggers.KILLED_BY_CROSSBOW.trigger(entityplayer, (Collection) this.piercedAndKilledEntities); + } else if (!entity.isAlive() && this.shotFromCrossbow()) { +- CriteriaTriggers.KILLED_BY_CROSSBOW.trigger(serverplayer, (Collection) Arrays.asList(entity)); ++ CriteriaTriggers.KILLED_BY_CROSSBOW.trigger(entityplayer, (Collection) Arrays.asList(entity)); + } + } + } +@@ -455,16 +457,15 @@ + } + + @Override +- @Override +- protected void onHitBlock(BlockHitResult blockhitresult) { +- this.lastState = this.level().getBlockState(blockhitresult.getBlockPos()); +- super.onHitBlock(blockhitresult); +- Vec3 vec3 = blockhitresult.getLocation().subtract(this.getX(), this.getY(), this.getZ()); ++ protected void onHitBlock(BlockHitResult result) { ++ this.lastState = this.level().getBlockState(result.getBlockPos()); ++ super.onHitBlock(result); ++ Vec3 vec3d = result.getLocation().subtract(this.getX(), this.getY(), this.getZ()); + +- this.setDeltaMovement(vec3); +- Vec3 vec31 = vec3.normalize().scale(0.05000000074505806D); ++ this.setDeltaMovement(vec3d); ++ Vec3 vec3d1 = vec3d.normalize().scale(0.05000000074505806D); + +- this.setPosRaw(this.getX() - vec31.x, this.getY() - vec31.y, this.getZ() - vec31.z); ++ this.setPosRaw(this.getX() - vec3d1.x, this.getY() - vec3d1.y, this.getZ() - vec3d1.z); + this.playSound(this.getHitGroundSoundEvent(), 1.0F, 1.2F / (this.random.nextFloat() * 0.2F + 0.9F)); + this.inGround = true; + this.shakeTime = 7; +@@ -483,70 +484,66 @@ + return this.soundEvent; + } + +- protected void doPostHurtEffects(LivingEntity livingentity) {} ++ protected void doPostHurtEffects(LivingEntity target) {} + + @Nullable +- protected EntityHitResult findHitEntity(Vec3 vec3, Vec3 vec31) { +- return ProjectileUtil.getEntityHitResult(this.level(), this, vec3, vec31, this.getBoundingBox().expandTowards(this.getDeltaMovement()).inflate(1.0D), this::canHitEntity); ++ protected EntityHitResult findHitEntity(Vec3 startVec, Vec3 endVec) { ++ return ProjectileUtil.getEntityHitResult(this.level(), this, startVec, endVec, this.getBoundingBox().expandTowards(this.getDeltaMovement()).inflate(1.0D), this::canHitEntity); + } + + @Override +- @Override +- protected boolean canHitEntity(Entity entity) { +- return super.canHitEntity(entity) && (this.piercingIgnoreEntityIds == null || !this.piercingIgnoreEntityIds.contains(entity.getId())); ++ protected boolean canHitEntity(Entity target) { ++ return super.canHitEntity(target) && (this.piercingIgnoreEntityIds == null || !this.piercingIgnoreEntityIds.contains(target.getId())); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putShort("life", (short) this.life); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putShort("life", (short) this.life); + if (this.lastState != null) { +- compoundtag.put("inBlockState", NbtUtils.writeBlockState(this.lastState)); ++ compound.put("inBlockState", NbtUtils.writeBlockState(this.lastState)); + } + +- compoundtag.putByte("shake", (byte) this.shakeTime); +- compoundtag.putBoolean("inGround", this.inGround); +- compoundtag.putByte("pickup", (byte) this.pickup.ordinal()); +- compoundtag.putDouble("damage", this.baseDamage); +- compoundtag.putBoolean("crit", this.isCritArrow()); +- compoundtag.putByte("PierceLevel", this.getPierceLevel()); +- compoundtag.putString("SoundEvent", BuiltInRegistries.SOUND_EVENT.getKey(this.soundEvent).toString()); +- compoundtag.putBoolean("ShotFromCrossbow", this.shotFromCrossbow()); +- compoundtag.put("item", this.pickupItemStack.save(new CompoundTag())); ++ compound.putByte("shake", (byte) this.shakeTime); ++ compound.putBoolean("inGround", this.inGround); ++ compound.putByte("pickup", (byte) this.pickup.ordinal()); ++ compound.putDouble("damage", this.baseDamage); ++ compound.putBoolean("crit", this.isCritArrow()); ++ compound.putByte("PierceLevel", this.getPierceLevel()); ++ compound.putString("SoundEvent", BuiltInRegistries.SOUND_EVENT.getKey(this.soundEvent).toString()); ++ compound.putBoolean("ShotFromCrossbow", this.shotFromCrossbow()); ++ compound.put("item", this.pickupItemStack.save(new CompoundTag())); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.life = compoundtag.getShort("life"); +- if (compoundtag.contains("inBlockState", 10)) { +- this.lastState = NbtUtils.readBlockState(this.level().holderLookup(Registries.BLOCK), compoundtag.getCompound("inBlockState")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.life = compound.getShort("life"); ++ if (compound.contains("inBlockState", 10)) { ++ this.lastState = NbtUtils.readBlockState(this.level().holderLookup(Registries.BLOCK), compound.getCompound("inBlockState")); + } + +- this.shakeTime = compoundtag.getByte("shake") & 255; +- this.inGround = compoundtag.getBoolean("inGround"); +- if (compoundtag.contains("damage", 99)) { +- this.baseDamage = compoundtag.getDouble("damage"); ++ this.shakeTime = compound.getByte("shake") & 255; ++ this.inGround = compound.getBoolean("inGround"); ++ if (compound.contains("damage", 99)) { ++ this.baseDamage = compound.getDouble("damage"); + } + +- this.pickup = AbstractArrow.Pickup.byOrdinal(compoundtag.getByte("pickup")); +- this.setCritArrow(compoundtag.getBoolean("crit")); +- this.setPierceLevel(compoundtag.getByte("PierceLevel")); +- if (compoundtag.contains("SoundEvent", 8)) { +- this.soundEvent = (SoundEvent) BuiltInRegistries.SOUND_EVENT.getOptional(new ResourceLocation(compoundtag.getString("SoundEvent"))).orElse(this.getDefaultHitGroundSoundEvent()); ++ this.pickup = AbstractArrow.Pickup.byOrdinal(compound.getByte("pickup")); ++ this.setCritArrow(compound.getBoolean("crit")); ++ this.setPierceLevel(compound.getByte("PierceLevel")); ++ if (compound.contains("SoundEvent", 8)) { ++ this.soundEvent = (SoundEvent) BuiltInRegistries.SOUND_EVENT.getOptional(new ResourceLocation(compound.getString("SoundEvent"))).orElse(this.getDefaultHitGroundSoundEvent()); + } + +- this.setShotFromCrossbow(compoundtag.getBoolean("ShotFromCrossbow")); +- if (compoundtag.contains("item", 10)) { +- this.pickupItemStack = ItemStack.of(compoundtag.getCompound("item")); ++ this.setShotFromCrossbow(compound.getBoolean("ShotFromCrossbow")); ++ if (compound.contains("item", 10)) { ++ this.pickupItemStack = ItemStack.of(compound.getCompound("item")); + } + + } + + @Override +- @Override + public void setOwner(@Nullable Entity entity) { + super.setOwner(entity); + if (entity instanceof Player) { +@@ -556,11 +553,25 @@ + } + + @Override +- @Override +- public void playerTouch(Player player) { ++ public void playerTouch(Player entity) { + if (!this.level().isClientSide && (this.inGround || this.isNoPhysics()) && this.shakeTime <= 0) { +- if (this.tryPickup(player)) { +- player.take(this, 1); ++ // CraftBukkit start ++ ItemStack itemstack = this.getPickupItem(); ++ if (this.pickup == Pickup.ALLOWED && !itemstack.isEmpty() && entity.getInventory().canHold(itemstack) > 0) { ++ ItemEntity item = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), itemstack); ++ PlayerPickupArrowEvent event = new PlayerPickupArrowEvent((org.bukkit.entity.Player) entity.getBukkitEntity(), new org.bukkit.craftbukkit.entity.CraftItem(this.level().getCraftServer(), item), (org.bukkit.entity.AbstractArrow) this.getBukkitEntity()); ++ // event.setCancelled(!entityhuman.canPickUpLoot); TODO ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ itemstack = item.getItem(); ++ } ++ ++ if ((this.pickup == AbstractArrow.Pickup.ALLOWED && entity.getInventory().add(itemstack)) || (this.pickup == AbstractArrow.Pickup.CREATIVE_ONLY && entity.getAbilities().instabuild)) { ++ // CraftBukkit end ++ entity.take(this, 1); + this.discard(); + } + +@@ -583,7 +594,6 @@ + } + + @Override +- @Override + protected Entity.MovementEmission getMovementEmission() { + return Entity.MovementEmission.NONE; + } +@@ -592,16 +602,16 @@ + return this.pickupItemStack; + } + +- public void setBaseDamage(double d0) { +- this.baseDamage = d0; ++ public void setBaseDamage(double baseDamage) { ++ this.baseDamage = baseDamage; + } + + public double getBaseDamage() { + return this.baseDamage; + } + +- public void setKnockback(int i) { +- this.knockback = i; ++ public void setKnockback(int knockback) { ++ this.knockback = knockback; + } + + public int getKnockback() { +@@ -609,32 +619,30 @@ + } + + @Override +- @Override + public boolean isAttackable() { + return false; + } + + @Override +- @Override +- protected float getEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.13F; + } + +- public void setCritArrow(boolean flag) { +- this.setFlag(1, flag); ++ public void setCritArrow(boolean critArrow) { ++ this.setFlag(1, critArrow); + } + +- public void setPierceLevel(byte b0) { +- this.entityData.set(AbstractArrow.PIERCE_LEVEL, b0); ++ public void setPierceLevel(byte pierceLevel) { ++ this.entityData.set(AbstractArrow.PIERCE_LEVEL, pierceLevel); + } + +- private void setFlag(int i, boolean flag) { ++ private void setFlag(int id, boolean value) { + byte b0 = (Byte) this.entityData.get(AbstractArrow.ID_FLAGS); + +- if (flag) { +- this.entityData.set(AbstractArrow.ID_FLAGS, (byte) (b0 | i)); ++ if (value) { ++ this.entityData.set(AbstractArrow.ID_FLAGS, (byte) (b0 | id)); + } else { +- this.entityData.set(AbstractArrow.ID_FLAGS, (byte) (b0 & ~i)); ++ this.entityData.set(AbstractArrow.ID_FLAGS, (byte) (b0 & ~id)); + } + + } +@@ -655,11 +663,11 @@ + return (Byte) this.entityData.get(AbstractArrow.PIERCE_LEVEL); + } + +- public void setEnchantmentEffectsFromEntity(LivingEntity livingentity, float f) { +- int i = EnchantmentHelper.getEnchantmentLevel(Enchantments.POWER_ARROWS, livingentity); +- int j = EnchantmentHelper.getEnchantmentLevel(Enchantments.PUNCH_ARROWS, livingentity); ++ public void setEnchantmentEffectsFromEntity(LivingEntity shooter, float velocity) { ++ int i = EnchantmentHelper.getEnchantmentLevel(Enchantments.POWER_ARROWS, shooter); ++ int j = EnchantmentHelper.getEnchantmentLevel(Enchantments.PUNCH_ARROWS, shooter); + +- this.setBaseDamage((double) (f * 2.0F) + this.random.triangle((double) this.level().getDifficulty().getId() * 0.11D, 0.57425D)); ++ this.setBaseDamage((double) (velocity * 2.0F) + this.random.triangle((double) this.level().getDifficulty().getId() * 0.11D, 0.57425D)); + if (i > 0) { + this.setBaseDamage(this.getBaseDamage() + (double) i * 0.5D + 0.5D); + } +@@ -668,7 +676,7 @@ + this.setKnockback(j); + } + +- if (EnchantmentHelper.getEnchantmentLevel(Enchantments.FLAMING_ARROWS, livingentity) > 0) { ++ if (EnchantmentHelper.getEnchantmentLevel(Enchantments.FLAMING_ARROWS, shooter) > 0) { + this.setSecondsOnFire(100); + } + +@@ -678,17 +686,17 @@ + return 0.6F; + } + +- public void setNoPhysics(boolean flag) { +- this.noPhysics = flag; +- this.setFlag(2, flag); ++ public void setNoPhysics(boolean noPhysics) { ++ this.noPhysics = noPhysics; ++ this.setFlag(2, noPhysics); + } + + public boolean isNoPhysics() { + return !this.level().isClientSide ? this.noPhysics : ((Byte) this.entityData.get(AbstractArrow.ID_FLAGS) & 2) != 0; + } + +- public void setShotFromCrossbow(boolean flag) { +- this.setFlag(4, flag); ++ public void setShotFromCrossbow(boolean shotFromCrossbow) { ++ this.setFlag(4, shotFromCrossbow); + } + + public static enum Pickup { +@@ -697,12 +705,12 @@ + + private Pickup() {} + +- public static AbstractArrow.Pickup byOrdinal(int i) { +- if (i < 0 || i > values().length) { +- i = 0; ++ public static AbstractArrow.Pickup byOrdinal(int ordinal) { ++ if (ordinal < 0 || ordinal > values().length) { ++ ordinal = 0; + } + +- return values()[i]; ++ return values()[ordinal]; + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java.patch new file mode 100644 index 0000000000..e2315535a2 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java.patch @@ -0,0 +1,269 @@ +--- a/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java ++++ b/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java +@@ -16,26 +16,35 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public abstract class AbstractHurtingProjectile extends Projectile { + + public double xPower; + public double yPower; + public double zPower; ++ public float bukkitYield = 1; // CraftBukkit ++ public boolean isIncendiary = true; // CraftBukkit + +- protected AbstractHurtingProjectile(EntityType entitytype, Level level) { +- super(entitytype, level); ++ protected AbstractHurtingProjectile(EntityType entityType, Level level) { ++ super(entityType, level); + } + +- protected AbstractHurtingProjectile(EntityType entitytype, double d0, double d1, double d2, Level level) { +- this(entitytype, level); ++ protected AbstractHurtingProjectile(EntityType entitytypes, double d0, double d1, double d2, Level world) { ++ this(entitytypes, world); + this.setPos(d0, d1, d2); + } + +- public AbstractHurtingProjectile(EntityType entitytype, double d0, double d1, double d2, double d3, double d4, double d5, Level level) { +- this(entitytype, level); +- this.moveTo(d0, d1, d2, this.getYRot(), this.getXRot()); ++ public AbstractHurtingProjectile(EntityType entityType, double x, double d1, double y, double d3, double z, double d5, Level offsetX) { ++ this(entityType, offsetX); ++ this.moveTo(x, d1, y, this.getYRot(), this.getXRot()); + this.reapplyPosition(); ++ // CraftBukkit start - Added setDirection method ++ this.setDirection(d3, z, d5); ++ } ++ ++ public void setDirection(double d3, double d4, double d5) { ++ // CraftBukkit end + double d6 = Math.sqrt(d3 * d3 + d4 * d4 + d5 * d5); + + if (d6 != 0.0D) { +@@ -46,19 +55,17 @@ + + } + +- public AbstractHurtingProjectile(EntityType entitytype, LivingEntity livingentity, double d0, double d1, double d2, Level level) { +- this(entitytype, livingentity.getX(), livingentity.getY(), livingentity.getZ(), d0, d1, d2, level); +- this.setOwner(livingentity); +- this.setRot(livingentity.getYRot(), livingentity.getXRot()); ++ public AbstractHurtingProjectile(EntityType entityType, LivingEntity shooter, double offsetX, double d1, double offsetY, Level world) { ++ this(entityType, shooter.getX(), shooter.getY(), shooter.getZ(), offsetX, d1, offsetY, world); ++ this.setOwner(shooter); ++ this.setRot(shooter.getYRot(), shooter.getXRot()); + } + + @Override +- @Override + protected void defineSynchedData() {} + + @Override +- @Override +- public boolean shouldRenderAtSqrDistance(double d0) { ++ public boolean shouldRenderAtSqrDistance(double distance) { + double d1 = this.getBoundingBox().getSize() * 4.0D; + + if (Double.isNaN(d1)) { +@@ -66,7 +73,7 @@ + } + + d1 *= 64.0D; +- return d0 < d1 * d1; ++ return distance < d1 * d1; + } + + protected ClipContext.Block getClipType() { +@@ -74,7 +81,6 @@ + } + + @Override +- @Override + public void tick() { + Entity entity = this.getOwner(); + +@@ -86,17 +92,23 @@ + this.setSecondsOnFire(1); + } + +- HitResult hitresult = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity, this.getClipType()); ++ HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity, this.getClipType()); + +- if (hitresult.getType() != HitResult.Type.MISS) { +- this.onHit(hitresult); ++ if (movingobjectposition.getType() != HitResult.EnumMovingObjectType.MISS) { ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event ++ ++ // CraftBukkit start - Fire ProjectileHitEvent ++ if (this.isRemoved()) { ++ CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); ++ } ++ // CraftBukkit end + } + + this.checkInsideBlocks(); +- Vec3 vec3 = this.getDeltaMovement(); +- double d0 = this.getX() + vec3.x; +- double d1 = this.getY() + vec3.y; +- double d2 = this.getZ() + vec3.z; ++ Vec3 vec3d = this.getDeltaMovement(); ++ double d0 = this.getX() + vec3d.x; ++ double d1 = this.getY() + vec3d.y; ++ double d2 = this.getZ() + vec3d.z; + + ProjectileUtil.rotateTowardsMovement(this, 0.2F); + float f; +@@ -105,7 +117,7 @@ + for (int i = 0; i < 4; ++i) { + float f1 = 0.25F; + +- this.level().addParticle(ParticleTypes.BUBBLE, d0 - vec3.x * 0.25D, d1 - vec3.y * 0.25D, d2 - vec3.z * 0.25D, vec3.x, vec3.y, vec3.z); ++ this.level().addParticle(ParticleTypes.BUBBLE, d0 - vec3d.x * 0.25D, d1 - vec3d.y * 0.25D, d2 - vec3d.z * 0.25D, vec3d.x, vec3d.y, vec3d.z); + } + + f = this.getLiquidInertia(); +@@ -113,11 +125,11 @@ + f = this.getInertia(); + } + +- this.setDeltaMovement(vec3.add(this.xPower, this.yPower, this.zPower).scale((double) f)); +- ParticleOptions particleoptions = this.getTrailParticle(); ++ this.setDeltaMovement(vec3d.add(this.xPower, this.yPower, this.zPower).scale((double) f)); ++ ParticleOptions particleparam = this.getTrailParticle(); + +- if (particleoptions != null) { +- this.level().addParticle(particleoptions, d0, d1 + 0.5D, d2, 0.0D, 0.0D, 0.0D); ++ if (particleparam != null) { ++ this.level().addParticle(particleparam, d0, d1 + 0.5D, d2, 0.0D, 0.0D, 0.0D); + } + + this.setPos(d0, d1, d2); +@@ -125,9 +137,8 @@ + } + + @Override +- @Override +- protected boolean canHitEntity(Entity entity) { +- return super.canHitEntity(entity) && !entity.noPhysics; ++ protected boolean canHitEntity(Entity target) { ++ return super.canHitEntity(target) && !target.noPhysics; + } + + protected boolean shouldBurn() { +@@ -148,57 +159,57 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.put("power", this.newDoubleList(new double[]{this.xPower, this.yPower, this.zPower})); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.put("power", this.newDoubleList(new double[]{this.xPower, this.yPower, this.zPower})); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("power", 9)) { +- ListTag listtag = compoundtag.getList("power", 6); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("power", 9)) { ++ ListTag nbttaglist = compound.getList("power", 6); + +- if (listtag.size() == 3) { +- this.xPower = listtag.getDouble(0); +- this.yPower = listtag.getDouble(1); +- this.zPower = listtag.getDouble(2); ++ if (nbttaglist.size() == 3) { ++ this.xPower = nbttaglist.getDouble(0); ++ this.yPower = nbttaglist.getDouble(1); ++ this.zPower = nbttaglist.getDouble(2); + } + } + + } + + @Override +- @Override + public boolean isPickable() { + return true; + } + + @Override +- @Override + public float getPickRadius() { + return 1.0F; + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- if (this.isInvulnerableTo(damagesource)) { ++ public boolean hurt(DamageSource source, float amount) { ++ if (this.isInvulnerableTo(source)) { + return false; + } else { + this.markHurt(); +- Entity entity = damagesource.getEntity(); ++ Entity entity = source.getEntity(); + + if (entity != null) { + if (!this.level().isClientSide) { +- Vec3 vec3 = entity.getLookAngle(); ++ // CraftBukkit start ++ if (CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, false)) { ++ return false; ++ } ++ // CraftBukkit end ++ Vec3 vec3d = entity.getLookAngle(); + +- this.setDeltaMovement(vec3); +- this.xPower = vec3.x * 0.1D; +- this.yPower = vec3.y * 0.1D; +- this.zPower = vec3.z * 0.1D; ++ this.setDeltaMovement(vec3d); ++ this.xPower = vec3d.x * 0.1D; ++ this.yPower = vec3d.y * 0.1D; ++ this.zPower = vec3d.z * 0.1D; + this.setOwner(entity); + } + +@@ -210,13 +221,11 @@ + } + + @Override +- @Override + public float getLightLevelDependentMagicValue() { + return 1.0F; + } + + @Override +- @Override + public Packet getAddEntityPacket() { + Entity entity = this.getOwner(); + int i = entity == null ? 0 : entity.getId(); +@@ -225,12 +234,11 @@ + } + + @Override +- @Override +- public void recreateFromPacket(ClientboundAddEntityPacket clientboundaddentitypacket) { +- super.recreateFromPacket(clientboundaddentitypacket); +- double d0 = clientboundaddentitypacket.getXa(); +- double d1 = clientboundaddentitypacket.getYa(); +- double d2 = clientboundaddentitypacket.getZa(); ++ public void recreateFromPacket(ClientboundAddEntityPacket packet) { ++ super.recreateFromPacket(packet); ++ double d0 = packet.getXa(); ++ double d1 = packet.getYa(); ++ double d2 = packet.getZa(); + double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2); + + if (d3 != 0.0D) { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/Arrow.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/Arrow.java.patch new file mode 100644 index 0000000000..b915c41dcb --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/Arrow.java.patch @@ -0,0 +1,270 @@ +--- a/net/minecraft/world/entity/projectile/Arrow.java ++++ b/net/minecraft/world/entity/projectile/Arrow.java +@@ -29,51 +29,51 @@ + private static final EntityDataAccessor ID_EFFECT_COLOR = SynchedEntityData.defineId(Arrow.class, EntityDataSerializers.INT); + private static final byte EVENT_POTION_PUFF = 0; + private static final ItemStack DEFAULT_ARROW_STACK = new ItemStack(Items.ARROW); +- private Potion potion; +- private final Set effects; ++ public Potion potion; ++ public final Set effects; + private boolean fixedColor; + +- public Arrow(EntityType entitytype, Level level) { +- super(entitytype, level, Arrow.DEFAULT_ARROW_STACK); ++ public Arrow(EntityType entityType, Level level) { ++ super(entityType, level, Arrow.DEFAULT_ARROW_STACK); + this.potion = Potions.EMPTY; + this.effects = Sets.newHashSet(); + } + +- public Arrow(Level level, double d0, double d1, double d2, ItemStack itemstack) { +- super(EntityType.ARROW, d0, d1, d2, level, itemstack); ++ public Arrow(Level world, double d0, double d1, double d2, ItemStack itemstack) { ++ super(EntityType.ARROW, d0, d1, d2, world, itemstack); + this.potion = Potions.EMPTY; + this.effects = Sets.newHashSet(); + } + +- public Arrow(Level level, LivingEntity livingentity, ItemStack itemstack) { +- super(EntityType.ARROW, livingentity, level, itemstack); ++ public Arrow(Level world, LivingEntity entityliving, ItemStack itemstack) { ++ super(EntityType.ARROW, entityliving, world, itemstack); + this.potion = Potions.EMPTY; + this.effects = Sets.newHashSet(); + } + +- public void setEffectsFromItem(ItemStack itemstack) { +- if (itemstack.is(Items.TIPPED_ARROW)) { +- this.potion = PotionUtils.getPotion(itemstack); +- Collection collection = PotionUtils.getCustomEffects(itemstack); ++ public void setEffectsFromItem(ItemStack stack) { ++ if (stack.is(Items.TIPPED_ARROW)) { ++ this.potion = PotionUtils.getPotion(stack); ++ Collection collection = PotionUtils.getCustomEffects(stack); + + if (!collection.isEmpty()) { + Iterator iterator = collection.iterator(); + + while (iterator.hasNext()) { +- MobEffectInstance mobeffectinstance = (MobEffectInstance) iterator.next(); ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); + +- this.effects.add(new MobEffectInstance(mobeffectinstance)); ++ this.effects.add(new MobEffectInstance(mobeffect)); + } + } + +- int i = getCustomColor(itemstack); ++ int i = getCustomColor(stack); + + if (i == -1) { + this.updateColor(); + } else { + this.setFixedColor(i); + } +- } else if (itemstack.is(Items.ARROW)) { ++ } else if (stack.is(Items.ARROW)) { + this.potion = Potions.EMPTY; + this.effects.clear(); + this.entityData.set(Arrow.ID_EFFECT_COLOR, -1); +@@ -81,13 +81,13 @@ + + } + +- public static int getCustomColor(ItemStack itemstack) { +- CompoundTag compoundtag = itemstack.getTag(); ++ public static int getCustomColor(ItemStack stack) { ++ CompoundTag nbttagcompound = stack.getTag(); + +- return compoundtag != null && compoundtag.contains("CustomPotionColor", 99) ? compoundtag.getInt("CustomPotionColor") : -1; ++ return nbttagcompound != null && nbttagcompound.contains("CustomPotionColor", 99) ? nbttagcompound.getInt("CustomPotionColor") : -1; + } + +- private void updateColor() { ++ public void updateColor() { + this.fixedColor = false; + if (this.potion == Potions.EMPTY && this.effects.isEmpty()) { + this.entityData.set(Arrow.ID_EFFECT_COLOR, -1); +@@ -97,20 +97,18 @@ + + } + +- public void addEffect(MobEffectInstance mobeffectinstance) { +- this.effects.add(mobeffectinstance); ++ public void addEffect(MobEffectInstance effectInstance) { ++ this.effects.add(effectInstance); + this.getEntityData().set(Arrow.ID_EFFECT_COLOR, PotionUtils.getColor((Collection) PotionUtils.getAllEffects(this.potion, this.effects))); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Arrow.ID_EFFECT_COLOR, -1); + } + + @Override +- @Override + public void tick() { + super.tick(); + if (this.level().isClientSide) { +@@ -130,15 +128,15 @@ + + } + +- private void makeParticle(int i) { ++ private void makeParticle(int particleAmount) { + int j = this.getColor(); + +- if (j != -1 && i > 0) { ++ if (j != -1 && particleAmount > 0) { + double d0 = (double) (j >> 16 & 255) / 255.0D; + double d1 = (double) (j >> 8 & 255) / 255.0D; + double d2 = (double) (j >> 0 & 255) / 255.0D; + +- for (int k = 0; k < i; ++k) { ++ for (int k = 0; k < particleAmount; ++k) { + this.level().addParticle(ParticleTypes.ENTITY_EFFECT, this.getRandomX(0.5D), this.getRandomY(), this.getRandomZ(0.5D), d0, d1, d2); + } + +@@ -149,56 +147,54 @@ + return (Integer) this.entityData.get(Arrow.ID_EFFECT_COLOR); + } + +- private void setFixedColor(int i) { ++ public void setFixedColor(int fixedColor) { + this.fixedColor = true; +- this.entityData.set(Arrow.ID_EFFECT_COLOR, i); ++ this.entityData.set(Arrow.ID_EFFECT_COLOR, fixedColor); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); + if (this.potion != Potions.EMPTY) { +- compoundtag.putString("Potion", BuiltInRegistries.POTION.getKey(this.potion).toString()); ++ compound.putString("Potion", BuiltInRegistries.POTION.getKey(this.potion).toString()); + } + + if (this.fixedColor) { +- compoundtag.putInt("Color", this.getColor()); ++ compound.putInt("Color", this.getColor()); + } + + if (!this.effects.isEmpty()) { +- ListTag listtag = new ListTag(); ++ ListTag nbttaglist = new ListTag(); + Iterator iterator = this.effects.iterator(); + + while (iterator.hasNext()) { +- MobEffectInstance mobeffectinstance = (MobEffectInstance) iterator.next(); ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); + +- listtag.add(mobeffectinstance.save(new CompoundTag())); ++ nbttaglist.add(mobeffect.save(new CompoundTag())); + } + +- compoundtag.put("custom_potion_effects", listtag); ++ compound.put("custom_potion_effects", nbttaglist); + } + + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("Potion", 8)) { +- this.potion = PotionUtils.getPotion(compoundtag); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("Potion", 8)) { ++ this.potion = PotionUtils.getPotion(compound); + } + +- Iterator iterator = PotionUtils.getCustomEffects(compoundtag).iterator(); ++ Iterator iterator = PotionUtils.getCustomEffects(compound).iterator(); + + while (iterator.hasNext()) { +- MobEffectInstance mobeffectinstance = (MobEffectInstance) iterator.next(); ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); + +- this.addEffect(mobeffectinstance); ++ this.addEffect(mobeffect); + } + +- if (compoundtag.contains("Color", 99)) { +- this.setFixedColor(compoundtag.getInt("Color")); ++ if (compound.contains("Color", 99)) { ++ this.setFixedColor(compound.getInt("Color")); + } else { + this.updateColor(); + } +@@ -206,34 +202,32 @@ + } + + @Override +- @Override +- protected void doPostHurtEffects(LivingEntity livingentity) { +- super.doPostHurtEffects(livingentity); ++ protected void doPostHurtEffects(LivingEntity living) { ++ super.doPostHurtEffects(living); + Entity entity = this.getEffectSource(); + Iterator iterator = this.potion.getEffects().iterator(); + +- MobEffectInstance mobeffectinstance; ++ MobEffectInstance mobeffect; + + while (iterator.hasNext()) { +- mobeffectinstance = (MobEffectInstance) iterator.next(); +- livingentity.addEffect(new MobEffectInstance(mobeffectinstance.getEffect(), Math.max(mobeffectinstance.mapDuration((i) -> { ++ mobeffect = (MobEffectInstance) iterator.next(); ++ living.addEffect(new MobEffectInstance(mobeffect.getEffect(), Math.max(mobeffect.mapDuration((i) -> { + return i / 8; +- }), 1), mobeffectinstance.getAmplifier(), mobeffectinstance.isAmbient(), mobeffectinstance.isVisible()), entity); ++ }), 1), mobeffect.getAmplifier(), mobeffect.isAmbient(), mobeffect.isVisible()), entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ARROW); // CraftBukkit + } + + if (!this.effects.isEmpty()) { + iterator = this.effects.iterator(); + + while (iterator.hasNext()) { +- mobeffectinstance = (MobEffectInstance) iterator.next(); +- livingentity.addEffect(mobeffectinstance, entity); ++ mobeffect = (MobEffectInstance) iterator.next(); ++ living.addEffect(mobeffect, entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ARROW); // CraftBukkit + } + } + + } + + @Override +- @Override + protected ItemStack getPickupItem() { + ItemStack itemstack = super.getPickupItem(); + +@@ -251,9 +245,8 @@ + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 0) { ++ public void handleEntityEvent(byte id) { ++ if (id == 0) { + int i = this.getColor(); + + if (i != -1) { +@@ -266,7 +259,7 @@ + } + } + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/EvokerFangs.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/EvokerFangs.java.patch new file mode 100644 index 0000000000..4305a3484d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/EvokerFangs.java.patch @@ -0,0 +1,156 @@ +--- a/net/minecraft/world/entity/projectile/EvokerFangs.java ++++ b/net/minecraft/world/entity/projectile/EvokerFangs.java +@@ -19,7 +19,7 @@ + public static final int ATTACK_DURATION = 20; + public static final int LIFE_OFFSET = 2; + public static final int ATTACK_TRIGGER_TICKS = 14; +- private int warmupDelayTicks; ++ public int warmupDelayTicks; + private boolean sentSpikeEvent; + private int lifeTicks; + private boolean clientSideAttackStarted; +@@ -28,31 +28,29 @@ + @Nullable + private UUID ownerUUID; + +- public EvokerFangs(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public EvokerFangs(EntityType entityType, Level level) { ++ super(entityType, level); + this.lifeTicks = 22; + } + +- public EvokerFangs(Level level, double d0, double d1, double d2, float f, int i, LivingEntity livingentity) { ++ public EvokerFangs(Level level, double x, double d1, double y, float f, int z, LivingEntity entityliving) { + this(EntityType.EVOKER_FANGS, level); +- this.warmupDelayTicks = i; +- this.setOwner(livingentity); ++ this.warmupDelayTicks = z; ++ this.setOwner(entityliving); + this.setYRot(f * 57.295776F); +- this.setPos(d0, d1, d2); ++ this.setPos(x, d1, y); + } + + @Override +- @Override + protected void defineSynchedData() {} + +- public void setOwner(@Nullable LivingEntity livingentity) { +- this.owner = livingentity; +- this.ownerUUID = livingentity == null ? null : livingentity.getUUID(); ++ public void setOwner(@Nullable LivingEntity owner) { ++ this.owner = owner; ++ this.ownerUUID = owner == null ? null : owner.getUUID(); + } + + @Nullable + @Override +- @Override + public LivingEntity getOwner() { + if (this.owner == null && this.ownerUUID != null && this.level() instanceof ServerLevel) { + Entity entity = ((ServerLevel) this.level()).getEntity(this.ownerUUID); +@@ -66,27 +64,24 @@ + } + + @Override +- @Override +- protected void readAdditionalSaveData(CompoundTag compoundtag) { +- this.warmupDelayTicks = compoundtag.getInt("Warmup"); +- if (compoundtag.hasUUID("Owner")) { +- this.ownerUUID = compoundtag.getUUID("Owner"); ++ protected void readAdditionalSaveData(CompoundTag compound) { ++ this.warmupDelayTicks = compound.getInt("Warmup"); ++ if (compound.hasUUID("Owner")) { ++ this.ownerUUID = compound.getUUID("Owner"); + } + + } + + @Override +- @Override +- protected void addAdditionalSaveData(CompoundTag compoundtag) { +- compoundtag.putInt("Warmup", this.warmupDelayTicks); ++ protected void addAdditionalSaveData(CompoundTag compound) { ++ compound.putInt("Warmup", this.warmupDelayTicks); + if (this.ownerUUID != null) { +- compoundtag.putUUID("Owner", this.ownerUUID); ++ compound.putUUID("Owner", this.ownerUUID); + } + + } + + @Override +- @Override + public void tick() { + super.tick(); + if (this.level().isClientSide) { +@@ -111,9 +106,9 @@ + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- LivingEntity livingentity = (LivingEntity) iterator.next(); ++ LivingEntity entityliving = (LivingEntity) iterator.next(); + +- this.dealDamageTo(livingentity); ++ this.dealDamageTo(entityliving); + } + } + +@@ -129,28 +124,29 @@ + + } + +- private void dealDamageTo(LivingEntity livingentity) { +- LivingEntity livingentity1 = this.getOwner(); ++ private void dealDamageTo(LivingEntity target) { ++ LivingEntity entityliving1 = this.getOwner(); + +- if (livingentity.isAlive() && !livingentity.isInvulnerable() && livingentity != livingentity1) { +- if (livingentity1 == null) { +- livingentity.hurt(this.damageSources().magic(), 6.0F); ++ if (target.isAlive() && !target.isInvulnerable() && target != entityliving1) { ++ if (entityliving1 == null) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = this; // CraftBukkit ++ target.hurt(this.damageSources().magic(), 6.0F); ++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = null; // CraftBukkit + } else { +- if (livingentity1.isAlliedTo((Entity) livingentity)) { ++ if (entityliving1.isAlliedTo((Entity) target)) { + return; + } + +- livingentity.hurt(this.damageSources().indirectMagic(this, livingentity1), 6.0F); ++ target.hurt(this.damageSources().indirectMagic(this, entityliving1), 6.0F); + } + + } + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- super.handleEntityEvent(b0); +- if (b0 == 4) { ++ public void handleEntityEvent(byte id) { ++ super.handleEntityEvent(id); ++ if (id == 4) { + this.clientSideAttackStarted = true; + if (!this.isSilent()) { + this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.EVOKER_FANGS_ATTACK, this.getSoundSource(), 1.0F, this.random.nextFloat() * 0.2F + 0.85F, false); +@@ -159,13 +155,13 @@ + + } + +- public float getAnimationProgress(float f) { ++ public float getAnimationProgress(float partialTicks) { + if (!this.clientSideAttackStarted) { + return 0.0F; + } else { + int i = this.lifeTicks - 2; + +- return i <= 0 ? 1.0F : 1.0F - ((float) i - f) / 20.0F; ++ return i <= 0 ? 1.0F : 1.0F - ((float) i - partialTicks) / 20.0F; + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/EyeOfEnder.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/EyeOfEnder.java.patch new file mode 100644 index 0000000000..4950464192 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/EyeOfEnder.java.patch @@ -0,0 +1,194 @@ +--- a/net/minecraft/world/entity/projectile/EyeOfEnder.java ++++ b/net/minecraft/world/entity/projectile/EyeOfEnder.java +@@ -19,24 +19,24 @@ + public class EyeOfEnder extends Entity implements ItemSupplier { + + private static final EntityDataAccessor DATA_ITEM_STACK = SynchedEntityData.defineId(EyeOfEnder.class, EntityDataSerializers.ITEM_STACK); +- private double tx; +- private double ty; +- private double tz; +- private int life; +- private boolean surviveAfterDeath; ++ public double tx; ++ public double ty; ++ public double tz; ++ public int life; ++ public boolean surviveAfterDeath; + +- public EyeOfEnder(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public EyeOfEnder(EntityType entityType, Level level) { ++ super(entityType, level); + } + +- public EyeOfEnder(Level level, double d0, double d1, double d2) { ++ public EyeOfEnder(Level level, double x, double d1, double y) { + this(EntityType.EYE_OF_ENDER, level); +- this.setPos(d0, d1, d2); ++ this.setPos(x, d1, y); + } + +- public void setItem(ItemStack itemstack) { +- if (!itemstack.is(Items.ENDER_EYE) || itemstack.hasTag()) { +- this.getEntityData().set(EyeOfEnder.DATA_ITEM_STACK, itemstack.copyWithCount(1)); ++ public void setItem(ItemStack stack) { ++ if (true || !stack.is(Items.ENDER_EYE) || stack.hasTag()) { // CraftBukkit - always allow item changing ++ this.getEntityData().set(EyeOfEnder.DATA_ITEM_STACK, stack.copyWithCount(1)); + } + + } +@@ -46,7 +46,6 @@ + } + + @Override +- @Override + public ItemStack getItem() { + ItemStack itemstack = this.getItemRaw(); + +@@ -54,14 +53,12 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + this.getEntityData().define(EyeOfEnder.DATA_ITEM_STACK, ItemStack.EMPTY); + } + + @Override +- @Override +- public boolean shouldRenderAtSqrDistance(double d0) { ++ public boolean shouldRenderAtSqrDistance(double distance) { + double d1 = this.getBoundingBox().getSize() * 4.0D; + + if (Double.isNaN(d1)) { +@@ -69,13 +66,13 @@ + } + + d1 *= 64.0D; +- return d0 < d1 * d1; ++ return distance < d1 * d1; + } + +- public void signalTo(BlockPos blockpos) { +- double d0 = (double) blockpos.getX(); +- int i = blockpos.getY(); +- double d1 = (double) blockpos.getZ(); ++ public void signalTo(BlockPos pos) { ++ double d0 = (double) pos.getX(); ++ int i = pos.getY(); ++ double d1 = (double) pos.getZ(); + double d2 = d0 - this.getX(); + double d3 = d1 - this.getZ(); + double d4 = Math.sqrt(d2 * d2 + d3 * d3); +@@ -95,13 +92,12 @@ + } + + @Override +- @Override +- public void lerpMotion(double d0, double d1, double d2) { +- this.setDeltaMovement(d0, d1, d2); ++ public void lerpMotion(double x, double d1, double y) { ++ this.setDeltaMovement(x, d1, y); + if (this.xRotO == 0.0F && this.yRotO == 0.0F) { +- double d3 = Math.sqrt(d0 * d0 + d2 * d2); ++ double d3 = Math.sqrt(x * x + y * y); + +- this.setYRot((float) (Mth.atan2(d0, d2) * 57.2957763671875D)); ++ this.setYRot((float) (Mth.atan2(x, y) * 57.2957763671875D)); + this.setXRot((float) (Mth.atan2(d1, d3) * 57.2957763671875D)); + this.yRotO = this.getYRot(); + this.xRotO = this.getXRot(); +@@ -110,24 +106,23 @@ + } + + @Override +- @Override + public void tick() { + super.tick(); +- Vec3 vec3 = this.getDeltaMovement(); +- double d0 = this.getX() + vec3.x; +- double d1 = this.getY() + vec3.y; +- double d2 = this.getZ() + vec3.z; +- double d3 = vec3.horizontalDistance(); ++ Vec3 vec3d = this.getDeltaMovement(); ++ double d0 = this.getX() + vec3d.x; ++ double d1 = this.getY() + vec3d.y; ++ double d2 = this.getZ() + vec3d.z; ++ double d3 = vec3d.horizontalDistance(); + +- this.setXRot(Projectile.lerpRotation(this.xRotO, (float) (Mth.atan2(vec3.y, d3) * 57.2957763671875D))); +- this.setYRot(Projectile.lerpRotation(this.yRotO, (float) (Mth.atan2(vec3.x, vec3.z) * 57.2957763671875D))); ++ this.setXRot(Projectile.lerpRotation(this.xRotO, (float) (Mth.atan2(vec3d.y, d3) * 57.2957763671875D))); ++ this.setYRot(Projectile.lerpRotation(this.yRotO, (float) (Mth.atan2(vec3d.x, vec3d.z) * 57.2957763671875D))); + if (!this.level().isClientSide) { + double d4 = this.tx - d0; + double d5 = this.tz - d2; + float f = (float) Math.sqrt(d4 * d4 + d5 * d5); + float f1 = (float) Mth.atan2(d5, d4); + double d6 = Mth.lerp(0.0025D, d3, (double) f); +- double d7 = vec3.y; ++ double d7 = vec3d.y; + + if (f < 1.0F) { + d6 *= 0.8D; +@@ -136,18 +131,18 @@ + + int i = this.getY() < this.ty ? 1 : -1; + +- vec3 = new Vec3(Math.cos((double) f1) * d6, d7 + ((double) i - d7) * 0.014999999664723873D, Math.sin((double) f1) * d6); +- this.setDeltaMovement(vec3); ++ vec3d = new Vec3(Math.cos((double) f1) * d6, d7 + ((double) i - d7) * 0.014999999664723873D, Math.sin((double) f1) * d6); ++ this.setDeltaMovement(vec3d); + } + + float f2 = 0.25F; + + if (this.isInWater()) { + for (int j = 0; j < 4; ++j) { +- this.level().addParticle(ParticleTypes.BUBBLE, d0 - vec3.x * 0.25D, d1 - vec3.y * 0.25D, d2 - vec3.z * 0.25D, vec3.x, vec3.y, vec3.z); ++ this.level().addParticle(ParticleTypes.BUBBLE, d0 - vec3d.x * 0.25D, d1 - vec3d.y * 0.25D, d2 - vec3d.z * 0.25D, vec3d.x, vec3d.y, vec3d.z); + } + } else { +- this.level().addParticle(ParticleTypes.PORTAL, d0 - vec3.x * 0.25D + this.random.nextDouble() * 0.6D - 0.3D, d1 - vec3.y * 0.25D - 0.5D, d2 - vec3.z * 0.25D + this.random.nextDouble() * 0.6D - 0.3D, vec3.x, vec3.y, vec3.z); ++ this.level().addParticle(ParticleTypes.PORTAL, d0 - vec3d.x * 0.25D + this.random.nextDouble() * 0.6D - 0.3D, d1 - vec3d.y * 0.25D - 0.5D, d2 - vec3d.z * 0.25D + this.random.nextDouble() * 0.6D - 0.3D, vec3d.x, vec3d.y, vec3d.z); + } + + if (!this.level().isClientSide) { +@@ -169,32 +164,28 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { ++ public void addAdditionalSaveData(CompoundTag compound) { + ItemStack itemstack = this.getItemRaw(); + + if (!itemstack.isEmpty()) { +- compoundtag.put("Item", itemstack.save(new CompoundTag())); ++ compound.put("Item", itemstack.save(new CompoundTag())); + } + + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- ItemStack itemstack = ItemStack.of(compoundtag.getCompound("Item")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ ItemStack itemstack = ItemStack.of(compound.getCompound("Item")); + +- this.setItem(itemstack); ++ if (!itemstack.isEmpty()) this.setItem(itemstack); // CraftBukkit - SPIGOT-6103 summon, see also SPIGOT-5474 + } + + @Override +- @Override + public float getLightLevelDependentMagicValue() { + return 1.0F; + } + + @Override +- @Override + public boolean isAttackable() { + return false; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/Fireball.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/Fireball.java.patch new file mode 100644 index 0000000000..750478e696 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/Fireball.java.patch @@ -0,0 +1,81 @@ +--- a/net/minecraft/world/entity/projectile/Fireball.java ++++ b/net/minecraft/world/entity/projectile/Fireball.java +@@ -14,31 +14,30 @@ + + private static final EntityDataAccessor DATA_ITEM_STACK = SynchedEntityData.defineId(Fireball.class, EntityDataSerializers.ITEM_STACK); + +- public Fireball(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public Fireball(EntityType entityType, Level level) { ++ super(entityType, level); + } + +- public Fireball(EntityType entitytype, double d0, double d1, double d2, double d3, double d4, double d5, Level level) { +- super(entitytype, d0, d1, d2, d3, d4, d5, level); ++ public Fireball(EntityType entityType, double x, double d1, double y, double d3, double z, double d5, Level offsetX) { ++ super(entityType, x, d1, y, d3, z, d5, offsetX); + } + +- public Fireball(EntityType entitytype, LivingEntity livingentity, double d0, double d1, double d2, Level level) { +- super(entitytype, livingentity, d0, d1, d2, level); ++ public Fireball(EntityType entityType, LivingEntity shooter, double offsetX, double d1, double offsetY, Level world) { ++ super(entityType, shooter, offsetX, d1, offsetY, world); + } + +- public void setItem(ItemStack itemstack) { +- if (!itemstack.is(Items.FIRE_CHARGE) || itemstack.hasTag()) { +- this.getEntityData().set(Fireball.DATA_ITEM_STACK, itemstack.copyWithCount(1)); ++ public void setItem(ItemStack stack) { ++ if (!stack.is(Items.FIRE_CHARGE) || stack.hasTag()) { ++ this.getEntityData().set(Fireball.DATA_ITEM_STACK, stack.copyWithCount(1)); + } + + } + +- protected ItemStack getItemRaw() { ++ public ItemStack getItemRaw() { + return (ItemStack) this.getEntityData().get(Fireball.DATA_ITEM_STACK); + } + + @Override +- @Override + public ItemStack getItem() { + ItemStack itemstack = this.getItemRaw(); + +@@ -46,29 +45,26 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + this.getEntityData().define(Fireball.DATA_ITEM_STACK, ItemStack.EMPTY); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); + ItemStack itemstack = this.getItemRaw(); + + if (!itemstack.isEmpty()) { +- compoundtag.put("Item", itemstack.save(new CompoundTag())); ++ compound.put("Item", itemstack.save(new CompoundTag())); + } + + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- ItemStack itemstack = ItemStack.of(compoundtag.getCompound("Item")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ ItemStack itemstack = ItemStack.of(compound.getCompound("Item")); + +- this.setItem(itemstack); ++ if (!itemstack.isEmpty()) this.setItem(itemstack); // CraftBukkit - SPIGOT-5474 probably came from bugged earlier versions + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/FireworkRocketEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/FireworkRocketEntity.java.patch new file mode 100644 index 0000000000..433a1e6ea2 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/FireworkRocketEntity.java.patch @@ -0,0 +1,377 @@ +--- a/net/minecraft/world/entity/projectile/FireworkRocketEntity.java ++++ b/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +@@ -15,8 +15,8 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +@@ -27,25 +27,26 @@ + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class FireworkRocketEntity extends Projectile implements ItemSupplier { + +- private static final EntityDataAccessor DATA_ID_FIREWORKS_ITEM = SynchedEntityData.defineId(FireworkRocketEntity.class, EntityDataSerializers.ITEM_STACK); ++ public static final EntityDataAccessor DATA_ID_FIREWORKS_ITEM = SynchedEntityData.defineId(FireworkRocketEntity.class, EntityDataSerializers.ITEM_STACK); + private static final EntityDataAccessor DATA_ATTACHED_TO_TARGET = SynchedEntityData.defineId(FireworkRocketEntity.class, EntityDataSerializers.OPTIONAL_UNSIGNED_INT); +- private static final EntityDataAccessor DATA_SHOT_AT_ANGLE = SynchedEntityData.defineId(FireworkRocketEntity.class, EntityDataSerializers.BOOLEAN); +- private int life; +- private int lifetime; ++ public static final EntityDataAccessor DATA_SHOT_AT_ANGLE = SynchedEntityData.defineId(FireworkRocketEntity.class, EntityDataSerializers.BOOLEAN); ++ public int life; ++ public int lifetime; + @Nullable +- private LivingEntity attachedToEntity; ++ public LivingEntity attachedToEntity; + +- public FireworkRocketEntity(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public FireworkRocketEntity(EntityType entityType, Level level) { ++ super(entityType, level); + } + +- public FireworkRocketEntity(Level level, double d0, double d1, double d2, ItemStack itemstack) { ++ public FireworkRocketEntity(Level level, double x, double d1, double y, ItemStack itemstack) { + super(EntityType.FIREWORK_ROCKET, level); + this.life = 0; +- this.setPos(d0, d1, d2); ++ this.setPos(x, d1, y); + int i = 1; + + if (!itemstack.isEmpty() && itemstack.hasTag()) { +@@ -57,29 +58,28 @@ + this.lifetime = 10 * i + this.random.nextInt(6) + this.random.nextInt(7); + } + +- public FireworkRocketEntity(Level level, @Nullable Entity entity, double d0, double d1, double d2, ItemStack itemstack) { +- this(level, d0, d1, d2, itemstack); +- this.setOwner(entity); ++ public FireworkRocketEntity(Level level, @Nullable Entity shooter, double x, double d1, double y, ItemStack itemstack) { ++ this(level, x, d1, y, itemstack); ++ this.setOwner(shooter); + } + +- public FireworkRocketEntity(Level level, ItemStack itemstack, LivingEntity livingentity) { +- this(level, livingentity, livingentity.getX(), livingentity.getY(), livingentity.getZ(), itemstack); +- this.entityData.set(FireworkRocketEntity.DATA_ATTACHED_TO_TARGET, OptionalInt.of(livingentity.getId())); +- this.attachedToEntity = livingentity; ++ public FireworkRocketEntity(Level level, ItemStack stack, LivingEntity shooter) { ++ this(level, shooter, shooter.getX(), shooter.getY(), shooter.getZ(), stack); ++ this.entityData.set(FireworkRocketEntity.DATA_ATTACHED_TO_TARGET, OptionalInt.of(shooter.getId())); ++ this.attachedToEntity = shooter; + } + +- public FireworkRocketEntity(Level level, ItemStack itemstack, double d0, double d1, double d2, boolean flag) { +- this(level, d0, d1, d2, itemstack); ++ public FireworkRocketEntity(Level level, ItemStack stack, double x, double d1, double y, boolean flag) { ++ this(level, x, d1, y, stack); + this.entityData.set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, flag); + } + +- public FireworkRocketEntity(Level level, ItemStack itemstack, Entity entity, double d0, double d1, double d2, boolean flag) { +- this(level, itemstack, d0, d1, d2, flag); +- this.setOwner(entity); ++ public FireworkRocketEntity(Level level, ItemStack stack, Entity shooter, double x, double d1, double y, boolean flag) { ++ this(level, stack, x, d1, y, flag); ++ this.setOwner(shooter); + } + + @Override +- @Override + protected void defineSynchedData() { + this.entityData.define(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, ItemStack.EMPTY); + this.entityData.define(FireworkRocketEntity.DATA_ATTACHED_TO_TARGET, OptionalInt.empty()); +@@ -87,22 +87,19 @@ + } + + @Override +- @Override +- public boolean shouldRenderAtSqrDistance(double d0) { +- return d0 < 4096.0D && !this.isAttachedToEntity(); ++ public boolean shouldRenderAtSqrDistance(double distance) { ++ return distance < 4096.0D && !this.isAttachedToEntity(); + } + + @Override +- @Override +- public boolean shouldRender(double d0, double d1, double d2) { +- return super.shouldRender(d0, d1, d2) && !this.isAttachedToEntity(); ++ public boolean shouldRender(double x, double d1, double y) { ++ return super.shouldRender(x, d1, y) && !this.isAttachedToEntity(); + } + + @Override +- @Override + public void tick() { + super.tick(); +- Vec3 vec3; ++ Vec3 vec3d; + + if (this.isAttachedToEntity()) { + if (this.attachedToEntity == null) { +@@ -118,18 +115,18 @@ + + if (this.attachedToEntity != null) { + if (this.attachedToEntity.isFallFlying()) { +- Vec3 vec31 = this.attachedToEntity.getLookAngle(); ++ Vec3 vec3d1 = this.attachedToEntity.getLookAngle(); + double d0 = 1.5D; + double d1 = 0.1D; +- Vec3 vec32 = this.attachedToEntity.getDeltaMovement(); ++ Vec3 vec3d2 = this.attachedToEntity.getDeltaMovement(); + +- this.attachedToEntity.setDeltaMovement(vec32.add(vec31.x * 0.1D + (vec31.x * 1.5D - vec32.x) * 0.5D, vec31.y * 0.1D + (vec31.y * 1.5D - vec32.y) * 0.5D, vec31.z * 0.1D + (vec31.z * 1.5D - vec32.z) * 0.5D)); +- vec3 = this.attachedToEntity.getHandHoldingItemAngle(Items.FIREWORK_ROCKET); ++ this.attachedToEntity.setDeltaMovement(vec3d2.add(vec3d1.x * 0.1D + (vec3d1.x * 1.5D - vec3d2.x) * 0.5D, vec3d1.y * 0.1D + (vec3d1.y * 1.5D - vec3d2.y) * 0.5D, vec3d1.z * 0.1D + (vec3d1.z * 1.5D - vec3d2.z) * 0.5D)); ++ vec3d = this.attachedToEntity.getHandHoldingItemAngle(Items.FIREWORK_ROCKET); + } else { +- vec3 = Vec3.ZERO; ++ vec3d = Vec3.ZERO; + } + +- this.setPos(this.attachedToEntity.getX() + vec3.x, this.attachedToEntity.getY() + vec3.y, this.attachedToEntity.getZ() + vec3.z); ++ this.setPos(this.attachedToEntity.getX() + vec3d.x, this.attachedToEntity.getY() + vec3d.y, this.attachedToEntity.getZ() + vec3d.z); + this.setDeltaMovement(this.attachedToEntity.getDeltaMovement()); + } + } else { +@@ -139,15 +136,15 @@ + this.setDeltaMovement(this.getDeltaMovement().multiply(d2, 1.0D, d2).add(0.0D, 0.04D, 0.0D)); + } + +- vec3 = this.getDeltaMovement(); +- this.move(MoverType.SELF, vec3); +- this.setDeltaMovement(vec3); ++ vec3d = this.getDeltaMovement(); ++ this.move(EnumMoveType.SELF, vec3d); ++ this.setDeltaMovement(vec3d); + } + +- HitResult hitresult = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); ++ HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); + + if (!this.noPhysics) { +- this.onHit(hitresult); ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + this.hasImpulse = true; + } + +@@ -162,7 +159,11 @@ + } + + if (!this.level().isClientSide && this.life > this.lifetime) { +- this.explode(); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) { ++ this.explode(); ++ } ++ // CraftBukkit end + } + + } +@@ -175,75 +176,85 @@ + } + + @Override +- @Override +- protected void onHitEntity(EntityHitResult entityhitresult) { +- super.onHitEntity(entityhitresult); ++ protected void onHitEntity(EntityHitResult result) { ++ super.onHitEntity(result); + if (!this.level().isClientSide) { +- this.explode(); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) { ++ this.explode(); ++ } ++ // CraftBukkit end + } + } + + @Override +- @Override +- protected void onHitBlock(BlockHitResult blockhitresult) { +- BlockPos blockpos = new BlockPos(blockhitresult.getBlockPos()); ++ protected void onHitBlock(BlockHitResult result) { ++ BlockPos blockposition = new BlockPos(result.getBlockPos()); + +- this.level().getBlockState(blockpos).entityInside(this.level(), blockpos, this); ++ this.level().getBlockState(blockposition).entityInside(this.level(), blockposition, this); + if (!this.level().isClientSide() && this.hasExplosion()) { +- this.explode(); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) { ++ this.explode(); ++ } ++ // CraftBukkit end + } + +- super.onHitBlock(blockhitresult); ++ super.onHitBlock(result); + } + + private boolean hasExplosion() { + ItemStack itemstack = (ItemStack) this.entityData.get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM); +- CompoundTag compoundtag = itemstack.isEmpty() ? null : itemstack.getTagElement("Fireworks"); +- ListTag listtag = compoundtag != null ? compoundtag.getList("Explosions", 10) : null; ++ CompoundTag nbttagcompound = itemstack.isEmpty() ? null : itemstack.getTagElement("Fireworks"); ++ ListTag nbttaglist = nbttagcompound != null ? nbttagcompound.getList("Explosions", 10) : null; + +- return listtag != null && !listtag.isEmpty(); ++ return nbttaglist != null && !nbttaglist.isEmpty(); + } + + private void dealExplosionDamage() { + float f = 0.0F; + ItemStack itemstack = (ItemStack) this.entityData.get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM); +- CompoundTag compoundtag = itemstack.isEmpty() ? null : itemstack.getTagElement("Fireworks"); +- ListTag listtag = compoundtag != null ? compoundtag.getList("Explosions", 10) : null; ++ CompoundTag nbttagcompound = itemstack.isEmpty() ? null : itemstack.getTagElement("Fireworks"); ++ ListTag nbttaglist = nbttagcompound != null ? nbttagcompound.getList("Explosions", 10) : null; + +- if (listtag != null && !listtag.isEmpty()) { +- f = 5.0F + (float) (listtag.size() * 2); ++ if (nbttaglist != null && !nbttaglist.isEmpty()) { ++ f = 5.0F + (float) (nbttaglist.size() * 2); + } + + if (f > 0.0F) { + if (this.attachedToEntity != null) { +- this.attachedToEntity.hurt(this.damageSources().fireworks(this, this.getOwner()), 5.0F + (float) (listtag.size() * 2)); ++ CraftEventFactory.entityDamage = this; // CraftBukkit ++ this.attachedToEntity.hurt(this.damageSources().fireworks(this, this.getOwner()), 5.0F + (float) (nbttaglist.size() * 2)); ++ CraftEventFactory.entityDamage = null; // CraftBukkit + } + + double d0 = 5.0D; +- Vec3 vec3 = this.position(); ++ Vec3 vec3d = this.position(); + List list = this.level().getEntitiesOfClass(LivingEntity.class, this.getBoundingBox().inflate(5.0D)); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- LivingEntity livingentity = (LivingEntity) iterator.next(); ++ LivingEntity entityliving = (LivingEntity) iterator.next(); + +- if (livingentity != this.attachedToEntity && this.distanceToSqr((Entity) livingentity) <= 25.0D) { ++ if (entityliving != this.attachedToEntity && this.distanceToSqr((Entity) entityliving) <= 25.0D) { + boolean flag = false; + + for (int i = 0; i < 2; ++i) { +- Vec3 vec31 = new Vec3(livingentity.getX(), livingentity.getY(0.5D * (double) i), livingentity.getZ()); +- BlockHitResult blockhitresult = this.level().clip(new ClipContext(vec3, vec31, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)); ++ Vec3 vec3d1 = new Vec3(entityliving.getX(), entityliving.getY(0.5D * (double) i), entityliving.getZ()); ++ BlockHitResult movingobjectpositionblock = this.level().clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)); + +- if (blockhitresult.getType() == HitResult.Type.MISS) { ++ if (movingobjectpositionblock.getType() == HitResult.EnumMovingObjectType.MISS) { + flag = true; + break; + } + } + + if (flag) { +- float f1 = f * (float) Math.sqrt((5.0D - (double) this.distanceTo(livingentity)) / 5.0D); ++ float f1 = f * (float) Math.sqrt((5.0D - (double) this.distanceTo(entityliving)) / 5.0D); + +- livingentity.hurt(this.damageSources().fireworks(this, this.getOwner()), f1); ++ CraftEventFactory.entityDamage = this; // CraftBukkit ++ entityliving.hurt(this.damageSources().fireworks(this, this.getOwner()), f1); ++ CraftEventFactory.entityDamage = null; // CraftBukkit + } + } + } +@@ -260,60 +271,56 @@ + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 17 && this.level().isClientSide) { ++ public void handleEntityEvent(byte id) { ++ if (id == 17 && this.level().isClientSide) { + if (!this.hasExplosion()) { + for (int i = 0; i < this.random.nextInt(3) + 2; ++i) { + this.level().addParticle(ParticleTypes.POOF, this.getX(), this.getY(), this.getZ(), this.random.nextGaussian() * 0.05D, 0.005D, this.random.nextGaussian() * 0.05D); + } + } else { + ItemStack itemstack = (ItemStack) this.entityData.get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM); +- CompoundTag compoundtag = itemstack.isEmpty() ? null : itemstack.getTagElement("Fireworks"); +- Vec3 vec3 = this.getDeltaMovement(); ++ CompoundTag nbttagcompound = itemstack.isEmpty() ? null : itemstack.getTagElement("Fireworks"); ++ Vec3 vec3d = this.getDeltaMovement(); + +- this.level().createFireworks(this.getX(), this.getY(), this.getZ(), vec3.x, vec3.y, vec3.z, compoundtag); ++ this.level().createFireworks(this.getX(), this.getY(), this.getZ(), vec3d.x, vec3d.y, vec3d.z, nbttagcompound); + } + } + +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("Life", this.life); +- compoundtag.putInt("LifeTime", this.lifetime); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("Life", this.life); ++ compound.putInt("LifeTime", this.lifetime); + ItemStack itemstack = (ItemStack) this.entityData.get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM); + + if (!itemstack.isEmpty()) { +- compoundtag.put("FireworksItem", itemstack.save(new CompoundTag())); ++ compound.put("FireworksItem", itemstack.save(new CompoundTag())); + } + +- compoundtag.putBoolean("ShotAtAngle", (Boolean) this.entityData.get(FireworkRocketEntity.DATA_SHOT_AT_ANGLE)); ++ compound.putBoolean("ShotAtAngle", (Boolean) this.entityData.get(FireworkRocketEntity.DATA_SHOT_AT_ANGLE)); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.life = compoundtag.getInt("Life"); +- this.lifetime = compoundtag.getInt("LifeTime"); +- ItemStack itemstack = ItemStack.of(compoundtag.getCompound("FireworksItem")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.life = compound.getInt("Life"); ++ this.lifetime = compound.getInt("LifeTime"); ++ ItemStack itemstack = ItemStack.of(compound.getCompound("FireworksItem")); + + if (!itemstack.isEmpty()) { + this.entityData.set(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, itemstack); + } + +- if (compoundtag.contains("ShotAtAngle")) { +- this.entityData.set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, compoundtag.getBoolean("ShotAtAngle")); ++ if (compound.contains("ShotAtAngle")) { ++ this.entityData.set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, compound.getBoolean("ShotAtAngle")); + } + + } + + @Override +- @Override + public ItemStack getItem() { + ItemStack itemstack = (ItemStack) this.entityData.get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM); + +@@ -321,7 +328,6 @@ + } + + @Override +- @Override + public boolean isAttackable() { + return false; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/FishingHook.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/FishingHook.java.patch new file mode 100644 index 0000000000..6bde94a39a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/FishingHook.java.patch @@ -0,0 +1,743 @@ +--- a/net/minecraft/world/entity/projectile/FishingHook.java ++++ b/net/minecraft/world/entity/projectile/FishingHook.java +@@ -25,15 +25,14 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.ExperienceOrb; +-import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.item.ItemEntity; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.storage.loot.BuiltInLootTables; + import net.minecraft.world.level.storage.loot.LootParams; +@@ -46,6 +45,12 @@ + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.entity.Player; ++import org.bukkit.entity.FishHook; ++import org.bukkit.event.player.PlayerFishEvent; ++// CraftBukkit end ++ + public class FishingHook extends Projectile { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -53,7 +58,7 @@ + private boolean biting; + private int outOfWaterTime; + private static final int MAX_OUT_OF_WATER_TIME = 10; +- private static final EntityDataAccessor DATA_HOOKED_ENTITY = SynchedEntityData.defineId(FishingHook.class, EntityDataSerializers.INT); ++ public static final EntityDataAccessor DATA_HOOKED_ENTITY = SynchedEntityData.defineId(FishingHook.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_BITING = SynchedEntityData.defineId(FishingHook.class, EntityDataSerializers.BOOLEAN); + private int life; + private int nibble; +@@ -62,27 +67,39 @@ + private float fishAngle; + private boolean openWater; + @Nullable +- private Entity hookedIn; +- private FishingHook.FishHookState currentState; ++ public Entity hookedIn; ++ public FishingHook.HookState currentState; + private final int luck; + private final int lureSpeed; + +- private FishingHook(EntityType entitytype, Level level, int i, int j) { +- super(entitytype, level); ++ // CraftBukkit start - Extra variables to enable modification of fishing wait time, values are minecraft defaults ++ public int minWaitTime = 100; ++ public int maxWaitTime = 600; ++ public int minLureTime = 20; ++ public int maxLureTime = 80; ++ public float minLureAngle = 0.0F; ++ public float maxLureAngle = 360.0F; ++ public boolean applyLure = true; ++ public boolean rainInfluenced = true; ++ public boolean skyInfluenced = true; ++ // CraftBukkit end ++ ++ private FishingHook(EntityType entityType, Level level, int luck, int lureSpeed) { ++ super(entityType, level); + this.syncronizedRandom = RandomSource.create(); + this.openWater = true; +- this.currentState = FishingHook.FishHookState.FLYING; ++ this.currentState = FishingHook.HookState.FLYING; + this.noCulling = true; +- this.luck = Math.max(0, i); +- this.lureSpeed = Math.max(0, j); ++ this.luck = Math.max(0, luck); ++ this.lureSpeed = Math.max(0, lureSpeed); + } + +- public FishingHook(EntityType entitytype, Level level) { +- this(entitytype, level, 0, 0); ++ public FishingHook(EntityType entityType, Level level) { ++ this(entityType, level, 0, 0); + } + +- public FishingHook(Player player, Level level, int i, int j) { +- this(EntityType.FISHING_BOBBER, level, i, j); ++ public FishingHook(net.minecraft.world.entity.player.Player player, Level level, int luck, int lureSpeed) { ++ this(EntityType.FISHING_BOBBER, level, luck, lureSpeed); + this.setOwner(player); + float f = player.getXRot(); + float f1 = player.getYRot(); +@@ -95,65 +112,60 @@ + double d2 = player.getZ() - (double) f2 * 0.3D; + + this.moveTo(d0, d1, d2, f1, f); +- Vec3 vec3 = new Vec3((double) (-f3), (double) Mth.clamp(-(f5 / f4), -5.0F, 5.0F), (double) (-f2)); +- double d3 = vec3.length(); ++ Vec3 vec3d = new Vec3((double) (-f3), (double) Mth.clamp(-(f5 / f4), -5.0F, 5.0F), (double) (-f2)); ++ double d3 = vec3d.length(); + +- vec3 = vec3.multiply(0.6D / d3 + this.random.triangle(0.5D, 0.0103365D), 0.6D / d3 + this.random.triangle(0.5D, 0.0103365D), 0.6D / d3 + this.random.triangle(0.5D, 0.0103365D)); +- this.setDeltaMovement(vec3); +- this.setYRot((float) (Mth.atan2(vec3.x, vec3.z) * 57.2957763671875D)); +- this.setXRot((float) (Mth.atan2(vec3.y, vec3.horizontalDistance()) * 57.2957763671875D)); ++ vec3d = vec3d.multiply(0.6D / d3 + this.random.triangle(0.5D, 0.0103365D), 0.6D / d3 + this.random.triangle(0.5D, 0.0103365D), 0.6D / d3 + this.random.triangle(0.5D, 0.0103365D)); ++ this.setDeltaMovement(vec3d); ++ this.setYRot((float) (Mth.atan2(vec3d.x, vec3d.z) * 57.2957763671875D)); ++ this.setXRot((float) (Mth.atan2(vec3d.y, vec3d.horizontalDistance()) * 57.2957763671875D)); + this.yRotO = this.getYRot(); + this.xRotO = this.getXRot(); + } + + @Override +- @Override + protected void defineSynchedData() { + this.getEntityData().define(FishingHook.DATA_HOOKED_ENTITY, 0); + this.getEntityData().define(FishingHook.DATA_BITING, false); + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- if (FishingHook.DATA_HOOKED_ENTITY.equals(entitydataaccessor)) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ if (FishingHook.DATA_HOOKED_ENTITY.equals(key)) { + int i = (Integer) this.getEntityData().get(FishingHook.DATA_HOOKED_ENTITY); + + this.hookedIn = i > 0 ? this.level().getEntity(i - 1) : null; + } + +- if (FishingHook.DATA_BITING.equals(entitydataaccessor)) { ++ if (FishingHook.DATA_BITING.equals(key)) { + this.biting = (Boolean) this.getEntityData().get(FishingHook.DATA_BITING); + if (this.biting) { + this.setDeltaMovement(this.getDeltaMovement().x, (double) (-0.4F * Mth.nextFloat(this.syncronizedRandom, 0.6F, 1.0F)), this.getDeltaMovement().z); + } + } + +- super.onSyncedDataUpdated(entitydataaccessor); ++ super.onSyncedDataUpdated(key); + } + + @Override +- @Override +- public boolean shouldRenderAtSqrDistance(double d0) { ++ public boolean shouldRenderAtSqrDistance(double distance) { + double d1 = 64.0D; + +- return d0 < 4096.0D; ++ return distance < 4096.0D; + } + + @Override +- @Override + public void lerpTo(double d0, double d1, double d2, float f, float f1, int i) {} + + @Override +- @Override + public void tick() { + this.syncronizedRandom.setSeed(this.getUUID().getLeastSignificantBits() ^ this.level().getGameTime()); + super.tick(); +- Player player = this.getPlayerOwner(); ++ net.minecraft.world.entity.player.Player entityhuman = this.getPlayerOwner(); + +- if (player == null) { ++ if (entityhuman == null) { + this.discard(); +- } else if (this.level().isClientSide || !this.shouldStopFishing(player)) { ++ } else if (this.level().isClientSide || !this.shouldStopFishing(entityhuman)) { + if (this.onGround()) { + ++this.life; + if (this.life >= 1200) { +@@ -165,56 +177,56 @@ + } + + float f = 0.0F; +- BlockPos blockpos = this.blockPosition(); +- FluidState fluidstate = this.level().getFluidState(blockpos); ++ BlockPos blockposition = this.blockPosition(); ++ FluidState fluid = this.level().getFluidState(blockposition); + +- if (fluidstate.is(FluidTags.WATER)) { +- f = fluidstate.getHeight(this.level(), blockpos); ++ if (fluid.is(FluidTags.WATER)) { ++ f = fluid.getHeight(this.level(), blockposition); + } + + boolean flag = f > 0.0F; + +- if (this.currentState == FishingHook.FishHookState.FLYING) { ++ if (this.currentState == FishingHook.HookState.FLYING) { + if (this.hookedIn != null) { + this.setDeltaMovement(Vec3.ZERO); +- this.currentState = FishingHook.FishHookState.HOOKED_IN_ENTITY; ++ this.currentState = FishingHook.HookState.HOOKED_IN_ENTITY; + return; + } + + if (flag) { + this.setDeltaMovement(this.getDeltaMovement().multiply(0.3D, 0.2D, 0.3D)); +- this.currentState = FishingHook.FishHookState.BOBBING; ++ this.currentState = FishingHook.HookState.BOBBING; + return; + } + + this.checkCollision(); + } else { +- if (this.currentState == FishingHook.FishHookState.HOOKED_IN_ENTITY) { ++ if (this.currentState == FishingHook.HookState.HOOKED_IN_ENTITY) { + if (this.hookedIn != null) { + if (!this.hookedIn.isRemoved() && this.hookedIn.level().dimension() == this.level().dimension()) { + this.setPos(this.hookedIn.getX(), this.hookedIn.getY(0.8D), this.hookedIn.getZ()); + } else { + this.setHookedEntity((Entity) null); +- this.currentState = FishingHook.FishHookState.FLYING; ++ this.currentState = FishingHook.HookState.FLYING; + } + } + + return; + } + +- if (this.currentState == FishingHook.FishHookState.BOBBING) { +- Vec3 vec3 = this.getDeltaMovement(); +- double d0 = this.getY() + vec3.y - (double) blockpos.getY() - (double) f; ++ if (this.currentState == FishingHook.HookState.BOBBING) { ++ Vec3 vec3d = this.getDeltaMovement(); ++ double d0 = this.getY() + vec3d.y - (double) blockposition.getY() - (double) f; + + if (Math.abs(d0) < 0.01D) { + d0 += Math.signum(d0) * 0.1D; + } + +- this.setDeltaMovement(vec3.x * 0.9D, vec3.y - d0 * (double) this.random.nextFloat() * 0.2D, vec3.z * 0.9D); ++ this.setDeltaMovement(vec3d.x * 0.9D, vec3d.y - d0 * (double) this.random.nextFloat() * 0.2D, vec3d.z * 0.9D); + if (this.nibble <= 0 && this.timeUntilHooked <= 0) { + this.openWater = true; + } else { +- this.openWater = this.openWater && this.outOfWaterTime < 10 && this.calculateOpenWater(blockpos); ++ this.openWater = this.openWater && this.outOfWaterTime < 10 && this.calculateOpenWater(blockposition); + } + + if (flag) { +@@ -224,7 +236,7 @@ + } + + if (!this.level().isClientSide) { +- this.catchingFish(blockpos); ++ this.catchingFish(blockposition); + } + } else { + this.outOfWaterTime = Math.min(10, this.outOfWaterTime + 1); +@@ -232,13 +244,13 @@ + } + } + +- if (!fluidstate.is(FluidTags.WATER)) { ++ if (!fluid.is(FluidTags.WATER)) { + this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.03D, 0.0D)); + } + +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + this.updateRotation(); +- if (this.currentState == FishingHook.FishHookState.FLYING && (this.onGround() || this.horizontalCollision)) { ++ if (this.currentState == FishingHook.HookState.FLYING && (this.onGround() || this.horizontalCollision)) { + this.setDeltaMovement(Vec3.ZERO); + } + +@@ -249,7 +261,7 @@ + } + } + +- private boolean shouldStopFishing(Player player) { ++ private boolean shouldStopFishing(net.minecraft.world.entity.player.Player player) { + ItemStack itemstack = player.getMainHandItem(); + ItemStack itemstack1 = player.getOffhandItem(); + boolean flag = itemstack.is(Items.FISHING_ROD); +@@ -264,49 +276,46 @@ + } + + private void checkCollision() { +- HitResult hitresult = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); ++ HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); + +- this.onHit(hitresult); ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + } + + @Override +- @Override +- protected boolean canHitEntity(Entity entity) { +- return super.canHitEntity(entity) || entity.isAlive() && entity instanceof ItemEntity; ++ protected boolean canHitEntity(Entity target) { ++ return super.canHitEntity(target) || target.isAlive() && target instanceof ItemEntity; + } + + @Override +- @Override +- protected void onHitEntity(EntityHitResult entityhitresult) { +- super.onHitEntity(entityhitresult); ++ protected void onHitEntity(EntityHitResult result) { ++ super.onHitEntity(result); + if (!this.level().isClientSide) { +- this.setHookedEntity(entityhitresult.getEntity()); ++ this.setHookedEntity(result.getEntity()); + } + + } + + @Override +- @Override +- protected void onHitBlock(BlockHitResult blockhitresult) { +- super.onHitBlock(blockhitresult); +- this.setDeltaMovement(this.getDeltaMovement().normalize().scale(blockhitresult.distanceTo(this))); ++ protected void onHitBlock(BlockHitResult result) { ++ super.onHitBlock(result); ++ this.setDeltaMovement(this.getDeltaMovement().normalize().scale(result.distanceTo(this))); + } + +- private void setHookedEntity(@Nullable Entity entity) { +- this.hookedIn = entity; +- this.getEntityData().set(FishingHook.DATA_HOOKED_ENTITY, entity == null ? 0 : entity.getId() + 1); ++ public void setHookedEntity(@Nullable Entity hookedEntity) { ++ this.hookedIn = hookedEntity; ++ this.getEntityData().set(FishingHook.DATA_HOOKED_ENTITY, hookedEntity == null ? 0 : hookedEntity.getId() + 1); + } + +- private void catchingFish(BlockPos blockpos) { +- ServerLevel serverlevel = (ServerLevel) this.level(); ++ private void catchingFish(BlockPos pos) { ++ ServerLevel worldserver = (ServerLevel) this.level(); + int i = 1; +- BlockPos blockpos1 = blockpos.above(); ++ BlockPos blockposition1 = pos.above(); + +- if (this.random.nextFloat() < 0.25F && this.level().isRainingAt(blockpos1)) { ++ if (this.rainInfluenced && this.random.nextFloat() < 0.25F && this.level().isRainingAt(blockposition1)) { // CraftBukkit + ++i; + } + +- if (this.random.nextFloat() < 0.5F && !this.level().canSeeSky(blockpos1)) { ++ if (this.skyInfluenced && this.random.nextFloat() < 0.5F && !this.level().canSeeSky(blockposition1)) { // CraftBukkit + --i; + } + +@@ -316,6 +325,10 @@ + this.timeUntilLured = 0; + this.timeUntilHooked = 0; + this.getEntityData().set(FishingHook.DATA_BITING, false); ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) this.getPlayerOwner().getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.FAILED_ATTEMPT); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ // CraftBukkit end + } + } else { + float f; +@@ -324,7 +337,7 @@ + double d0; + double d1; + double d2; +- BlockState blockstate; ++ IBlockData iblockdata; + + if (this.timeUntilHooked > 0) { + this.timeUntilHooked -= i; +@@ -336,24 +349,31 @@ + d0 = this.getX() + (double) (f1 * (float) this.timeUntilHooked * 0.1F); + d1 = (double) ((float) Mth.floor(this.getY()) + 1.0F); + d2 = this.getZ() + (double) (f2 * (float) this.timeUntilHooked * 0.1F); +- blockstate = serverlevel.getBlockState(BlockPos.containing(d0, d1 - 1.0D, d2)); +- if (blockstate.is(Blocks.WATER)) { ++ iblockdata = worldserver.getBlockState(BlockPos.containing(d0, d1 - 1.0D, d2)); ++ if (iblockdata.is(Blocks.WATER)) { + if (this.random.nextFloat() < 0.15F) { +- serverlevel.sendParticles(ParticleTypes.BUBBLE, d0, d1 - 0.10000000149011612D, d2, 1, (double) f1, 0.1D, (double) f2, 0.0D); ++ worldserver.sendParticles(ParticleTypes.BUBBLE, d0, d1 - 0.10000000149011612D, d2, 1, (double) f1, 0.1D, (double) f2, 0.0D); + } + + float f3 = f1 * 0.04F; + float f4 = f2 * 0.04F; + +- serverlevel.sendParticles(ParticleTypes.FISHING, d0, d1, d2, 0, (double) f4, 0.01D, (double) (-f3), 1.0D); +- serverlevel.sendParticles(ParticleTypes.FISHING, d0, d1, d2, 0, (double) (-f4), 0.01D, (double) f3, 1.0D); ++ worldserver.sendParticles(ParticleTypes.FISHING, d0, d1, d2, 0, (double) f4, 0.01D, (double) (-f3), 1.0D); ++ worldserver.sendParticles(ParticleTypes.FISHING, d0, d1, d2, 0, (double) (-f4), 0.01D, (double) f3, 1.0D); + } + } else { ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) this.getPlayerOwner().getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.BITE); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ if (playerFishEvent.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.playSound(SoundEvents.FISHING_BOBBER_SPLASH, 0.25F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); + double d3 = this.getY() + 0.5D; + +- serverlevel.sendParticles(ParticleTypes.BUBBLE, this.getX(), d3, this.getZ(), (int) (1.0F + this.getBbWidth() * 20.0F), (double) this.getBbWidth(), 0.0D, (double) this.getBbWidth(), 0.20000000298023224D); +- serverlevel.sendParticles(ParticleTypes.FISHING, this.getX(), d3, this.getZ(), (int) (1.0F + this.getBbWidth() * 20.0F), (double) this.getBbWidth(), 0.0D, (double) this.getBbWidth(), 0.20000000298023224D); ++ worldserver.sendParticles(ParticleTypes.BUBBLE, this.getX(), d3, this.getZ(), (int) (1.0F + this.getBbWidth() * 20.0F), (double) this.getBbWidth(), 0.0D, (double) this.getBbWidth(), 0.20000000298023224D); ++ worldserver.sendParticles(ParticleTypes.FISHING, this.getX(), d3, this.getZ(), (int) (1.0F + this.getBbWidth() * 20.0F), (double) this.getBbWidth(), 0.0D, (double) this.getBbWidth(), 0.20000000298023224D); + this.nibble = Mth.nextInt(this.random, 20, 40); + this.getEntityData().set(FishingHook.DATA_BITING, true); + } +@@ -374,65 +394,69 @@ + d0 = this.getX() + (double) (Mth.sin(f1) * f2) * 0.1D; + d1 = (double) ((float) Mth.floor(this.getY()) + 1.0F); + d2 = this.getZ() + (double) (Mth.cos(f1) * f2) * 0.1D; +- blockstate = serverlevel.getBlockState(BlockPos.containing(d0, d1 - 1.0D, d2)); +- if (blockstate.is(Blocks.WATER)) { +- serverlevel.sendParticles(ParticleTypes.SPLASH, d0, d1, d2, 2 + this.random.nextInt(2), 0.10000000149011612D, 0.0D, 0.10000000149011612D, 0.0D); ++ iblockdata = worldserver.getBlockState(BlockPos.containing(d0, d1 - 1.0D, d2)); ++ if (iblockdata.is(Blocks.WATER)) { ++ worldserver.sendParticles(ParticleTypes.SPLASH, d0, d1, d2, 2 + this.random.nextInt(2), 0.10000000149011612D, 0.0D, 0.10000000149011612D, 0.0D); + } + } + + if (this.timeUntilLured <= 0) { +- this.fishAngle = Mth.nextFloat(this.random, 0.0F, 360.0F); +- this.timeUntilHooked = Mth.nextInt(this.random, 20, 80); ++ // CraftBukkit start - logic to modify fishing wait time, lure time, and lure angle ++ this.fishAngle = Mth.nextFloat(this.random, this.minLureAngle, this.maxLureAngle); ++ this.timeUntilHooked = Mth.nextInt(this.random, this.minLureTime, this.maxLureTime); ++ // CraftBukkit end + } + } else { +- this.timeUntilLured = Mth.nextInt(this.random, 100, 600); +- this.timeUntilLured -= this.lureSpeed * 20 * 5; ++ // CraftBukkit start - logic to modify fishing wait time ++ this.timeUntilLured = Mth.nextInt(this.random, this.minWaitTime, this.maxWaitTime); ++ this.timeUntilLured -= (this.applyLure) ? this.lureSpeed * 20 * 5 : 0; ++ // CraftBukkit end + } + } + + } + +- private boolean calculateOpenWater(BlockPos blockpos) { +- FishingHook.OpenWaterType fishinghook_openwatertype = FishingHook.OpenWaterType.INVALID; ++ private boolean calculateOpenWater(BlockPos pos) { ++ FishingHook.WaterPosition entityfishinghook_waterposition = FishingHook.WaterPosition.INVALID; + + for (int i = -1; i <= 2; ++i) { +- FishingHook.OpenWaterType fishinghook_openwatertype1 = this.getOpenWaterTypeForArea(blockpos.offset(-2, i, -2), blockpos.offset(2, i, 2)); ++ FishingHook.WaterPosition entityfishinghook_waterposition1 = this.getOpenWaterTypeForArea(pos.offset(-2, i, -2), pos.offset(2, i, 2)); + +- switch (fishinghook_openwatertype1) { ++ switch (entityfishinghook_waterposition1) { + case INVALID: + return false; + case ABOVE_WATER: +- if (fishinghook_openwatertype == FishingHook.OpenWaterType.INVALID) { ++ if (entityfishinghook_waterposition == FishingHook.WaterPosition.INVALID) { + return false; + } + break; + case INSIDE_WATER: +- if (fishinghook_openwatertype == FishingHook.OpenWaterType.ABOVE_WATER) { ++ if (entityfishinghook_waterposition == FishingHook.WaterPosition.ABOVE_WATER) { + return false; + } + } + +- fishinghook_openwatertype = fishinghook_openwatertype1; ++ entityfishinghook_waterposition = entityfishinghook_waterposition1; + } + + return true; + } + +- private FishingHook.OpenWaterType getOpenWaterTypeForArea(BlockPos blockpos, BlockPos blockpos1) { +- return (FishingHook.OpenWaterType) BlockPos.betweenClosedStream(blockpos, blockpos1).map(this::getOpenWaterTypeForBlock).reduce((fishinghook_openwatertype, fishinghook_openwatertype1) -> { +- return fishinghook_openwatertype == fishinghook_openwatertype1 ? fishinghook_openwatertype : FishingHook.OpenWaterType.INVALID; +- }).orElse(FishingHook.OpenWaterType.INVALID); ++ private FishingHook.WaterPosition getOpenWaterTypeForArea(BlockPos firstPos, BlockPos secondPos) { ++ return (FishingHook.WaterPosition) BlockPos.betweenClosedStream(firstPos, secondPos).map(this::getOpenWaterTypeForBlock).reduce((entityfishinghook_waterposition, entityfishinghook_waterposition1) -> { ++ return entityfishinghook_waterposition == entityfishinghook_waterposition1 ? entityfishinghook_waterposition : FishingHook.WaterPosition.INVALID; ++ }).orElse(FishingHook.WaterPosition.INVALID); + } + +- private FishingHook.OpenWaterType getOpenWaterTypeForBlock(BlockPos blockpos) { +- BlockState blockstate = this.level().getBlockState(blockpos); ++ private FishingHook.WaterPosition getOpenWaterTypeForBlock(BlockPos pos) { ++ IBlockData iblockdata = this.level().getBlockState(pos); + +- if (!blockstate.isAir() && !blockstate.is(Blocks.LILY_PAD)) { +- FluidState fluidstate = blockstate.getFluidState(); ++ if (!iblockdata.isAir() && !iblockdata.is(Blocks.LILY_PAD)) { ++ FluidState fluid = iblockdata.getFluidState(); + +- return fluidstate.is(FluidTags.WATER) && fluidstate.isSource() && blockstate.getCollisionShape(this.level(), blockpos).isEmpty() ? FishingHook.OpenWaterType.INSIDE_WATER : FishingHook.OpenWaterType.INVALID; ++ return fluid.is(FluidTags.WATER) && fluid.isSource() && iblockdata.getCollisionShape(this.level(), pos).isEmpty() ? FishingHook.WaterPosition.INSIDE_WATER : FishingHook.WaterPosition.INVALID; + } else { +- return FishingHook.OpenWaterType.ABOVE_WATER; ++ return FishingHook.WaterPosition.ABOVE_WATER; + } + } + +@@ -441,45 +465,64 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) {} ++ public void addAdditionalSaveData(CompoundTag compound) {} + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) {} ++ public void readAdditionalSaveData(CompoundTag compound) {} + +- public int retrieve(ItemStack itemstack) { +- Player player = this.getPlayerOwner(); ++ public int retrieve(ItemStack stack) { ++ net.minecraft.world.entity.player.Player entityhuman = this.getPlayerOwner(); + +- if (!this.level().isClientSide && player != null && !this.shouldStopFishing(player)) { ++ if (!this.level().isClientSide && entityhuman != null && !this.shouldStopFishing(entityhuman)) { + int i = 0; + + if (this.hookedIn != null) { ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), this.hookedIn.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_ENTITY); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ return 0; ++ } ++ // CraftBukkit end + this.pullEntity(this.hookedIn); +- CriteriaTriggers.FISHING_ROD_HOOKED.trigger((ServerPlayer) player, itemstack, this, Collections.emptyList()); ++ CriteriaTriggers.FISHING_ROD_HOOKED.trigger((ServerPlayer) entityhuman, stack, this, Collections.emptyList()); + this.level().broadcastEntityEvent(this, (byte) 31); + i = this.hookedIn instanceof ItemEntity ? 3 : 5; + } else if (this.nibble > 0) { +- LootParams lootparams = (new LootParams.Builder((ServerLevel) this.level())).withParameter(LootContextParams.ORIGIN, this.position()).withParameter(LootContextParams.TOOL, itemstack).withParameter(LootContextParams.THIS_ENTITY, this).withLuck((float) this.luck + player.getLuck()).create(LootContextParamSets.FISHING); ++ LootParams lootparams = (new LootParams.Builder((ServerLevel) this.level())).withParameter(LootContextParams.ORIGIN, this.position()).withParameter(LootContextParams.TOOL, stack).withParameter(LootContextParams.THIS_ENTITY, this).withLuck((float) this.luck + entityhuman.getLuck()).create(LootContextParamSets.FISHING); + LootTable loottable = this.level().getServer().getLootData().getLootTable(BuiltInLootTables.FISHING); + List list = loottable.getRandomItems(lootparams); + +- CriteriaTriggers.FISHING_ROD_HOOKED.trigger((ServerPlayer) player, itemstack, this, list); ++ CriteriaTriggers.FISHING_ROD_HOOKED.trigger((ServerPlayer) entityhuman, stack, this, list); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { + ItemStack itemstack1 = (ItemStack) iterator.next(); +- ItemEntity itementity = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), itemstack1); +- double d0 = player.getX() - this.getX(); +- double d1 = player.getY() - this.getY(); +- double d2 = player.getZ() - this.getZ(); ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), itemstack1); ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); ++ playerFishEvent.setExpToDrop(this.random.nextInt(6) + 1); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ return 0; ++ } ++ // CraftBukkit end ++ double d0 = entityhuman.getX() - this.getX(); ++ double d1 = entityhuman.getY() - this.getY(); ++ double d2 = entityhuman.getZ() - this.getZ(); + double d3 = 0.1D; + +- itementity.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); +- this.level().addFreshEntity(itementity); +- player.level().addFreshEntity(new ExperienceOrb(player.level(), player.getX(), player.getY() + 0.5D, player.getZ() + 0.5D, this.random.nextInt(6) + 1)); ++ entityitem.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); ++ this.level().addFreshEntity(entityitem); ++ // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() ++ if (playerFishEvent.getExpToDrop() > 0) { ++ entityhuman.level().addFreshEntity(new ExperienceOrb(entityhuman.level(), entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop())); ++ } ++ // CraftBukkit end + if (itemstack1.is(ItemTags.FISHES)) { +- player.awardStat(Stats.FISH_CAUGHT, 1); ++ entityhuman.awardStat(Stats.FISH_CAUGHT, 1); + } + } + +@@ -487,8 +530,25 @@ + } + + if (this.onGround()) { ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.IN_GROUND); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ return 0; ++ } ++ // CraftBukkit end + i = 2; + } ++ // CraftBukkit start ++ if (i == 0) { ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.REEL_IN); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ if (playerFishEvent.isCancelled()) { ++ return 0; ++ } ++ } ++ // CraftBukkit end + + this.discard(); + return i; +@@ -498,65 +558,60 @@ + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 31 && this.level().isClientSide && this.hookedIn instanceof Player && ((Player) this.hookedIn).isLocalPlayer()) { ++ public void handleEntityEvent(byte id) { ++ if (id == 31 && this.level().isClientSide && this.hookedIn instanceof net.minecraft.world.entity.player.Player && ((net.minecraft.world.entity.player.Player) this.hookedIn).isLocalPlayer()) { + this.pullEntity(this.hookedIn); + } + +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + +- protected void pullEntity(Entity entity) { ++ public void pullEntity(Entity entity) { + Entity entity1 = this.getOwner(); + + if (entity1 != null) { +- Vec3 vec3 = (new Vec3(entity1.getX() - this.getX(), entity1.getY() - this.getY(), entity1.getZ() - this.getZ())).scale(0.1D); ++ Vec3 vec3d = (new Vec3(entity1.getX() - this.getX(), entity1.getY() - this.getY(), entity1.getZ() - this.getZ())).scale(0.1D); + +- entity.setDeltaMovement(entity.getDeltaMovement().add(vec3)); ++ entity.setDeltaMovement(entity.getDeltaMovement().add(vec3d)); + } + } + + @Override +- @Override + protected Entity.MovementEmission getMovementEmission() { + return Entity.MovementEmission.NONE; + } + + @Override +- @Override +- public void remove(Entity.RemovalReason entity_removalreason) { ++ public void remove(Entity.RemovalReason reason) { + this.updateOwnerInfo((FishingHook) null); +- super.remove(entity_removalreason); ++ super.remove(reason); + } + + @Override +- @Override + public void onClientRemoval() { + this.updateOwnerInfo((FishingHook) null); + } + + @Override +- @Override +- public void setOwner(@Nullable Entity entity) { +- super.setOwner(entity); ++ public void setOwner(@Nullable Entity owner) { ++ super.setOwner(owner); + this.updateOwnerInfo(this); + } + +- private void updateOwnerInfo(@Nullable FishingHook fishinghook) { +- Player player = this.getPlayerOwner(); ++ private void updateOwnerInfo(@Nullable FishingHook fishingHook) { ++ net.minecraft.world.entity.player.Player entityhuman = this.getPlayerOwner(); + +- if (player != null) { +- player.fishing = fishinghook; ++ if (entityhuman != null) { ++ entityhuman.fishing = fishingHook; + } + + } + + @Nullable +- public Player getPlayerOwner() { ++ public net.minecraft.world.entity.player.Player getPlayerOwner() { + Entity entity = this.getOwner(); + +- return entity instanceof Player ? (Player) entity : null; ++ return entity instanceof net.minecraft.world.entity.player.Player ? (net.minecraft.world.entity.player.Player) entity : null; + } + + @Nullable +@@ -565,13 +620,11 @@ + } + + @Override +- @Override + public boolean canChangeDimensions() { + return false; + } + + @Override +- @Override + public Packet getAddEntityPacket() { + Entity entity = this.getOwner(); + +@@ -579,11 +632,10 @@ + } + + @Override +- @Override +- public void recreateFromPacket(ClientboundAddEntityPacket clientboundaddentitypacket) { +- super.recreateFromPacket(clientboundaddentitypacket); ++ public void recreateFromPacket(ClientboundAddEntityPacket packet) { ++ super.recreateFromPacket(packet); + if (this.getPlayerOwner() == null) { +- int i = clientboundaddentitypacket.getData(); ++ int i = packet.getData(); + + FishingHook.LOGGER.error("Failed to recreate fishing hook on client. {} (id: {}) is not a valid owner.", this.level().getEntity(i), i); + this.kill(); +@@ -591,17 +643,17 @@ + + } + +- private static enum FishHookState { ++ public static enum HookState { + + FLYING, HOOKED_IN_ENTITY, BOBBING; + +- private FishHookState() {} ++ private HookState() {} + } + +- private static enum OpenWaterType { ++ private static enum WaterPosition { + + ABOVE_WATER, INSIDE_WATER, INVALID; + +- private OpenWaterType() {} ++ private WaterPosition() {} + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/LargeFireball.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/LargeFireball.java.patch new file mode 100644 index 0000000000..c0c81bb858 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/LargeFireball.java.patch @@ -0,0 +1,91 @@ +--- a/net/minecraft/world/entity/projectile/LargeFireball.java ++++ b/net/minecraft/world/entity/projectile/LargeFireball.java +@@ -8,39 +8,48 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++import org.bukkit.event.entity.ExplosionPrimeEvent; // CraftBukkit + + public class LargeFireball extends Fireball { + +- private int explosionPower = 1; ++ public int explosionPower = 1; + +- public LargeFireball(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public LargeFireball(EntityType entityType, Level level) { ++ super(entityType, level); ++ isIncendiary = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // CraftBukkit + } + +- public LargeFireball(Level level, LivingEntity livingentity, double d0, double d1, double d2, int i) { +- super(EntityType.FIREBALL, livingentity, d0, d1, d2, level); ++ public LargeFireball(Level level, LivingEntity shooter, double offsetX, double d1, double offsetY, int i) { ++ super(EntityType.FIREBALL, shooter, offsetX, d1, offsetY, level); + this.explosionPower = i; ++ isIncendiary = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // CraftBukkit + } + + @Override +- @Override +- protected void onHit(HitResult hitresult) { +- super.onHit(hitresult); ++ protected void onHit(HitResult result) { ++ super.onHit(result); + if (!this.level().isClientSide) { + boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); + +- this.level().explode(this, this.getX(), this.getY(), this.getZ(), (float) this.explosionPower, flag, Level.ExplosionInteraction.MOB); ++ // CraftBukkit start - fire ExplosionPrimeEvent ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent((org.bukkit.entity.Explosive) this.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ // give 'this' instead of (Entity) null so we know what causes the damage ++ this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.MOB); ++ } ++ // CraftBukkit end + this.discard(); + } + + } + + @Override +- @Override +- protected void onHitEntity(EntityHitResult entityhitresult) { +- super.onHitEntity(entityhitresult); ++ protected void onHitEntity(EntityHitResult result) { ++ super.onHitEntity(result); + if (!this.level().isClientSide) { +- Entity entity = entityhitresult.getEntity(); ++ Entity entity = result.getEntity(); + Entity entity1 = this.getOwner(); + + entity.hurt(this.damageSources().fireball(this, entity1), 6.0F); +@@ -52,18 +61,17 @@ + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putByte("ExplosionPower", (byte) this.explosionPower); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putByte("ExplosionPower", (byte) this.explosionPower); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("ExplosionPower", 99)) { +- this.explosionPower = compoundtag.getByte("ExplosionPower"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("ExplosionPower", 99)) { ++ // CraftBukkit - set bukkitYield when setting explosionpower ++ bukkitYield = this.explosionPower = compound.getByte("ExplosionPower"); + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/LlamaSpit.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/LlamaSpit.java.patch new file mode 100644 index 0000000000..b427a79c2a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/LlamaSpit.java.patch @@ -0,0 +1,102 @@ +--- a/net/minecraft/world/entity/projectile/LlamaSpit.java ++++ b/net/minecraft/world/entity/projectile/LlamaSpit.java +@@ -16,27 +16,26 @@ + + public class LlamaSpit extends Projectile { + +- public LlamaSpit(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public LlamaSpit(EntityType entityType, Level level) { ++ super(entityType, level); + } + +- public LlamaSpit(Level level, Llama llama) { ++ public LlamaSpit(Level level, Llama spitter) { + this(EntityType.LLAMA_SPIT, level); +- this.setOwner(llama); +- this.setPos(llama.getX() - (double) (llama.getBbWidth() + 1.0F) * 0.5D * (double) Mth.sin(llama.yBodyRot * 0.017453292F), llama.getEyeY() - 0.10000000149011612D, llama.getZ() + (double) (llama.getBbWidth() + 1.0F) * 0.5D * (double) Mth.cos(llama.yBodyRot * 0.017453292F)); ++ this.setOwner(spitter); ++ this.setPos(spitter.getX() - (double) (spitter.getBbWidth() + 1.0F) * 0.5D * (double) Mth.sin(spitter.yBodyRot * 0.017453292F), spitter.getEyeY() - 0.10000000149011612D, spitter.getZ() + (double) (spitter.getBbWidth() + 1.0F) * 0.5D * (double) Mth.cos(spitter.yBodyRot * 0.017453292F)); + } + + @Override +- @Override + public void tick() { + super.tick(); +- Vec3 vec3 = this.getDeltaMovement(); +- HitResult hitresult = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); ++ Vec3 vec3d = this.getDeltaMovement(); ++ HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); + +- this.onHit(hitresult); +- double d0 = this.getX() + vec3.x; +- double d1 = this.getY() + vec3.y; +- double d2 = this.getZ() + vec3.z; ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event ++ double d0 = this.getX() + vec3d.x; ++ double d1 = this.getY() + vec3d.y; ++ double d2 = this.getZ() + vec3d.z; + + this.updateRotation(); + float f = 0.99F; +@@ -47,7 +46,7 @@ + } else if (this.isInWaterOrBubble()) { + this.discard(); + } else { +- this.setDeltaMovement(vec3.scale(0.9900000095367432D)); ++ this.setDeltaMovement(vec3d.scale(0.9900000095367432D)); + if (!this.isNoGravity()) { + this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.05999999865889549D, 0.0D)); + } +@@ -57,23 +56,21 @@ + } + + @Override +- @Override +- protected void onHitEntity(EntityHitResult entityhitresult) { +- super.onHitEntity(entityhitresult); ++ protected void onHitEntity(EntityHitResult result) { ++ super.onHitEntity(result); + Entity entity = this.getOwner(); + + if (entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; ++ LivingEntity entityliving = (LivingEntity) entity; + +- entityhitresult.getEntity().hurt(this.damageSources().mobProjectile(this, livingentity), 1.0F); ++ result.getEntity().hurt(this.damageSources().mobProjectile(this, entityliving), 1.0F); + } + + } + + @Override +- @Override +- protected void onHitBlock(BlockHitResult blockhitresult) { +- super.onHitBlock(blockhitresult); ++ protected void onHitBlock(BlockHitResult result) { ++ super.onHitBlock(result); + if (!this.level().isClientSide) { + this.discard(); + } +@@ -81,16 +78,14 @@ + } + + @Override +- @Override + protected void defineSynchedData() {} + + @Override +- @Override +- public void recreateFromPacket(ClientboundAddEntityPacket clientboundaddentitypacket) { +- super.recreateFromPacket(clientboundaddentitypacket); +- double d0 = clientboundaddentitypacket.getXa(); +- double d1 = clientboundaddentitypacket.getYa(); +- double d2 = clientboundaddentitypacket.getZa(); ++ public void recreateFromPacket(ClientboundAddEntityPacket packet) { ++ super.recreateFromPacket(packet); ++ double d0 = packet.getXa(); ++ double d1 = packet.getYa(); ++ double d2 = packet.getZa(); + + for (int i = 0; i < 7; ++i) { + double d3 = 0.4D + 0.1D * (double) i; diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/Projectile.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/Projectile.java.patch new file mode 100644 index 0000000000..12854ec5a0 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/Projectile.java.patch @@ -0,0 +1,323 @@ +--- a/net/minecraft/world/entity/projectile/Projectile.java ++++ b/net/minecraft/world/entity/projectile/Projectile.java +@@ -18,12 +18,15 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.projectiles.ProjectileSource; ++// CraftBukkit end + + public abstract class Projectile extends Entity implements TraceableEntity { + +@@ -34,32 +37,36 @@ + private boolean leftOwner; + private boolean hasBeenShot; + +- Projectile(EntityType entitytype, Level level) { +- super(entitytype, level); ++ // CraftBukkit start ++ private boolean hitCancelled = false; ++ // CraftBukkit end ++ ++ Projectile(EntityType entityType, Level level) { ++ super(entityType, level); + } + +- public void setOwner(@Nullable Entity entity) { +- if (entity != null) { +- this.ownerUUID = entity.getUUID(); +- this.cachedOwner = entity; ++ public void setOwner(@Nullable Entity owner) { ++ if (owner != null) { ++ this.ownerUUID = owner.getUUID(); ++ this.cachedOwner = owner; + } ++ this.projectileSource = (owner != null && owner.getBukkitEntity() instanceof ProjectileSource) ? (ProjectileSource) owner.getBukkitEntity() : null; // CraftBukkit + + } + + @Nullable + @Override +- @Override + public Entity getOwner() { + if (this.cachedOwner != null && !this.cachedOwner.isRemoved()) { + return this.cachedOwner; + } else { + if (this.ownerUUID != null) { +- Level level = this.level(); ++ Level world = this.level(); + +- if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; + +- this.cachedOwner = serverlevel.getEntity(this.ownerUUID); ++ this.cachedOwner = worldserver.getEntity(this.ownerUUID); + return this.cachedOwner; + } + } +@@ -73,17 +80,16 @@ + } + + @Override +- @Override +- protected void addAdditionalSaveData(CompoundTag compoundtag) { ++ protected void addAdditionalSaveData(CompoundTag compound) { + if (this.ownerUUID != null) { +- compoundtag.putUUID("Owner", this.ownerUUID); ++ compound.putUUID("Owner", this.ownerUUID); + } + + if (this.leftOwner) { +- compoundtag.putBoolean("LeftOwner", true); ++ compound.putBoolean("LeftOwner", true); + } + +- compoundtag.putBoolean("HasBeenShot", this.hasBeenShot); ++ compound.putBoolean("HasBeenShot", this.hasBeenShot); + } + + protected boolean ownedBy(Entity entity) { +@@ -91,31 +97,28 @@ + } + + @Override +- @Override +- protected void readAdditionalSaveData(CompoundTag compoundtag) { +- if (compoundtag.hasUUID("Owner")) { +- this.ownerUUID = compoundtag.getUUID("Owner"); ++ protected void readAdditionalSaveData(CompoundTag compound) { ++ if (compound.hasUUID("Owner")) { ++ this.ownerUUID = compound.getUUID("Owner"); + this.cachedOwner = null; + } + +- this.leftOwner = compoundtag.getBoolean("LeftOwner"); +- this.hasBeenShot = compoundtag.getBoolean("HasBeenShot"); ++ this.leftOwner = compound.getBoolean("LeftOwner"); ++ this.hasBeenShot = compound.getBoolean("HasBeenShot"); + } + + @Override +- @Override + public void restoreFrom(Entity entity) { + super.restoreFrom(entity); + if (entity instanceof Projectile) { +- Projectile projectile = (Projectile) entity; ++ Projectile iprojectile = (Projectile) entity; + +- this.cachedOwner = projectile.cachedOwner; ++ this.cachedOwner = iprojectile.cachedOwner; + } + + } + + @Override +- @Override + public void tick() { + if (!this.hasBeenShot) { + this.gameEvent(GameEvent.PROJECTILE_SHOOT, this.getOwner()); +@@ -149,63 +152,77 @@ + return true; + } + +- public void shoot(double d0, double d1, double d2, float f, float f1) { +- Vec3 vec3 = (new Vec3(d0, d1, d2)).normalize().add(this.random.triangle(0.0D, 0.0172275D * (double) f1), this.random.triangle(0.0D, 0.0172275D * (double) f1), this.random.triangle(0.0D, 0.0172275D * (double) f1)).scale((double) f); ++ public void shoot(double x, double d1, double y, float f, float z) { ++ Vec3 vec3d = (new Vec3(x, d1, y)).normalize().add(this.random.triangle(0.0D, 0.0172275D * (double) z), this.random.triangle(0.0D, 0.0172275D * (double) z), this.random.triangle(0.0D, 0.0172275D * (double) z)).scale((double) f); + +- this.setDeltaMovement(vec3); +- double d3 = vec3.horizontalDistance(); ++ this.setDeltaMovement(vec3d); ++ double d3 = vec3d.horizontalDistance(); + +- this.setYRot((float) (Mth.atan2(vec3.x, vec3.z) * 57.2957763671875D)); +- this.setXRot((float) (Mth.atan2(vec3.y, d3) * 57.2957763671875D)); ++ this.setYRot((float) (Mth.atan2(vec3d.x, vec3d.z) * 57.2957763671875D)); ++ this.setXRot((float) (Mth.atan2(vec3d.y, d3) * 57.2957763671875D)); + this.yRotO = this.getYRot(); + this.xRotO = this.getXRot(); + } + +- public void shootFromRotation(Entity entity, float f, float f1, float f2, float f3, float f4) { +- float f5 = -Mth.sin(f1 * 0.017453292F) * Mth.cos(f * 0.017453292F); +- float f6 = -Mth.sin((f + f2) * 0.017453292F); +- float f7 = Mth.cos(f1 * 0.017453292F) * Mth.cos(f * 0.017453292F); ++ public void shootFromRotation(Entity shooter, float x, float y, float z, float velocity, float inaccuracy) { ++ float f5 = -Mth.sin(y * 0.017453292F) * Mth.cos(x * 0.017453292F); ++ float f6 = -Mth.sin((x + z) * 0.017453292F); ++ float f7 = Mth.cos(y * 0.017453292F) * Mth.cos(x * 0.017453292F); + +- this.shoot((double) f5, (double) f6, (double) f7, f3, f4); +- Vec3 vec3 = entity.getDeltaMovement(); ++ this.shoot((double) f5, (double) f6, (double) f7, velocity, inaccuracy); ++ Vec3 vec3d = shooter.getDeltaMovement(); + +- this.setDeltaMovement(this.getDeltaMovement().add(vec3.x, entity.onGround() ? 0.0D : vec3.y, vec3.z)); ++ this.setDeltaMovement(this.getDeltaMovement().add(vec3d.x, shooter.onGround() ? 0.0D : vec3d.y, vec3d.z)); + } + +- protected void onHit(HitResult hitresult) { +- HitResult.Type hitresult_type = hitresult.getType(); ++ // CraftBukkit start - call projectile hit event ++ protected void preOnHit(HitResult movingobjectposition) { ++ org.bukkit.event.entity.ProjectileHitEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); ++ this.hitCancelled = event != null && event.isCancelled(); ++ if (movingobjectposition.getType() == HitResult.EnumMovingObjectType.BLOCK || !this.hitCancelled) { ++ this.onHit(movingobjectposition); ++ } ++ } ++ // CraftBukkit end + +- if (hitresult_type == HitResult.Type.ENTITY) { +- this.onHitEntity((EntityHitResult) hitresult); +- this.level().gameEvent(GameEvent.PROJECTILE_LAND, hitresult.getLocation(), GameEvent.Context.of(this, (BlockState) null)); +- } else if (hitresult_type == HitResult.Type.BLOCK) { +- BlockHitResult blockhitresult = (BlockHitResult) hitresult; ++ protected void onHit(HitResult result) { ++ HitResult.EnumMovingObjectType movingobjectposition_enummovingobjecttype = result.getType(); + +- this.onHitBlock(blockhitresult); +- BlockPos blockpos = blockhitresult.getBlockPos(); ++ if (movingobjectposition_enummovingobjecttype == HitResult.EnumMovingObjectType.ENTITY) { ++ this.onHitEntity((EntityHitResult) result); ++ this.level().gameEvent(GameEvent.PROJECTILE_LAND, result.getLocation(), GameEvent.Context.of(this, (IBlockData) null)); ++ } else if (movingobjectposition_enummovingobjecttype == HitResult.EnumMovingObjectType.BLOCK) { ++ BlockHitResult movingobjectpositionblock = (BlockHitResult) result; + +- this.level().gameEvent(GameEvent.PROJECTILE_LAND, blockpos, GameEvent.Context.of(this, this.level().getBlockState(blockpos))); ++ this.onHitBlock(movingobjectpositionblock); ++ BlockPos blockposition = movingobjectpositionblock.getBlockPos(); ++ ++ this.level().gameEvent(GameEvent.PROJECTILE_LAND, blockposition, GameEvent.Context.of(this, this.level().getBlockState(blockposition))); + } + + } + +- protected void onHitEntity(EntityHitResult entityhitresult) {} ++ protected void onHitEntity(EntityHitResult result) {} + +- protected void onHitBlock(BlockHitResult blockhitresult) { +- BlockState blockstate = this.level().getBlockState(blockhitresult.getBlockPos()); ++ protected void onHitBlock(BlockHitResult result) { ++ // CraftBukkit start - cancellable hit event ++ if (hitCancelled) { ++ return; ++ } ++ // CraftBukkit end ++ IBlockData iblockdata = this.level().getBlockState(result.getBlockPos()); + +- blockstate.onProjectileHit(this.level(), blockstate, blockhitresult, this); ++ iblockdata.onProjectileHit(this.level(), iblockdata, result, this); + } + + @Override +- @Override +- public void lerpMotion(double d0, double d1, double d2) { +- this.setDeltaMovement(d0, d1, d2); ++ public void lerpMotion(double x, double d1, double y) { ++ this.setDeltaMovement(x, d1, y); + if (this.xRotO == 0.0F && this.yRotO == 0.0F) { +- double d3 = Math.sqrt(d0 * d0 + d2 * d2); ++ double d3 = Math.sqrt(x * x + y * y); + + this.setXRot((float) (Mth.atan2(d1, d3) * 57.2957763671875D)); +- this.setYRot((float) (Mth.atan2(d0, d2) * 57.2957763671875D)); ++ this.setYRot((float) (Mth.atan2(x, y) * 57.2957763671875D)); + this.xRotO = this.getXRot(); + this.yRotO = this.getYRot(); + this.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); +@@ -213,38 +230,37 @@ + + } + +- protected boolean canHitEntity(Entity entity) { +- if (!entity.canBeHitByProjectile()) { ++ protected boolean canHitEntity(Entity target) { ++ if (!target.canBeHitByProjectile()) { + return false; + } else { + Entity entity1 = this.getOwner(); + +- return entity1 == null || this.leftOwner || !entity1.isPassengerOfSameVehicle(entity); ++ return entity1 == null || this.leftOwner || !entity1.isPassengerOfSameVehicle(target); + } + } + + protected void updateRotation() { +- Vec3 vec3 = this.getDeltaMovement(); +- double d0 = vec3.horizontalDistance(); ++ Vec3 vec3d = this.getDeltaMovement(); ++ double d0 = vec3d.horizontalDistance(); + +- this.setXRot(lerpRotation(this.xRotO, (float) (Mth.atan2(vec3.y, d0) * 57.2957763671875D))); +- this.setYRot(lerpRotation(this.yRotO, (float) (Mth.atan2(vec3.x, vec3.z) * 57.2957763671875D))); ++ this.setXRot(lerpRotation(this.xRotO, (float) (Mth.atan2(vec3d.y, d0) * 57.2957763671875D))); ++ this.setYRot(lerpRotation(this.yRotO, (float) (Mth.atan2(vec3d.x, vec3d.z) * 57.2957763671875D))); + } + +- protected static float lerpRotation(float f, float f1) { +- while (f1 - f < -180.0F) { +- f -= 360.0F; ++ protected static float lerpRotation(float currentRotation, float targetRotation) { ++ while (targetRotation - currentRotation < -180.0F) { ++ currentRotation -= 360.0F; + } + +- while (f1 - f >= 180.0F) { +- f += 360.0F; ++ while (targetRotation - currentRotation >= 180.0F) { ++ currentRotation += 360.0F; + } + +- return Mth.lerp(0.2F, f, f1); ++ return Mth.lerp(0.2F, currentRotation, targetRotation); + } + + @Override +- @Override + public Packet getAddEntityPacket() { + Entity entity = this.getOwner(); + +@@ -252,10 +268,9 @@ + } + + @Override +- @Override +- public void recreateFromPacket(ClientboundAddEntityPacket clientboundaddentitypacket) { +- super.recreateFromPacket(clientboundaddentitypacket); +- Entity entity = this.level().getEntity(clientboundaddentitypacket.getData()); ++ public void recreateFromPacket(ClientboundAddEntityPacket packet) { ++ super.recreateFromPacket(packet); ++ Entity entity = this.level().getEntity(packet.getData()); + + if (entity != null) { + this.setOwner(entity); +@@ -264,14 +279,13 @@ + } + + @Override +- @Override +- public boolean mayInteract(Level level, BlockPos blockpos) { ++ public boolean mayInteract(Level level, BlockPos pos) { + Entity entity = this.getOwner(); + +- return entity instanceof Player ? entity.mayInteract(level, blockpos) : entity == null || level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); ++ return entity instanceof Player ? entity.mayInteract(level, pos) : entity == null || level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); + } + +- public boolean mayBreak(Level level) { +- return this.getType().is(EntityTypeTags.IMPACT_PROJECTILES) && level.getGameRules().getBoolean(GameRules.RULE_PROJECTILESCANBREAKBLOCKS); ++ public boolean mayBreak(Level world) { ++ return this.getType().is(EntityTypeTags.IMPACT_PROJECTILES) && world.getGameRules().getBoolean(GameRules.RULE_PROJECTILESCANBREAKBLOCKS); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ShulkerBullet.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ShulkerBullet.java.patch new file mode 100644 index 0000000000..761a8a13d2 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ShulkerBullet.java.patch @@ -0,0 +1,400 @@ +--- a/net/minecraft/world/entity/projectile/ShulkerBullet.java ++++ b/net/minecraft/world/entity/projectile/ShulkerBullet.java +@@ -43,69 +43,78 @@ + @Nullable + private UUID targetId; + +- public ShulkerBullet(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public ShulkerBullet(EntityType entityType, Level level) { ++ super(entityType, level); + this.noPhysics = true; + } + +- public ShulkerBullet(Level level, LivingEntity livingentity, Entity entity, Direction.Axis direction_axis) { ++ public ShulkerBullet(Level level, LivingEntity shooter, Entity finalTarget, Direction.Axis axis) { + this(EntityType.SHULKER_BULLET, level); +- this.setOwner(livingentity); +- BlockPos blockpos = livingentity.blockPosition(); +- double d0 = (double) blockpos.getX() + 0.5D; +- double d1 = (double) blockpos.getY() + 0.5D; +- double d2 = (double) blockpos.getZ() + 0.5D; ++ this.setOwner(shooter); ++ BlockPos blockposition = shooter.blockPosition(); ++ double d0 = (double) blockposition.getX() + 0.5D; ++ double d1 = (double) blockposition.getY() + 0.5D; ++ double d2 = (double) blockposition.getZ() + 0.5D; + + this.moveTo(d0, d1, d2, this.getYRot(), this.getXRot()); +- this.finalTarget = entity; ++ this.finalTarget = finalTarget; + this.currentMoveDirection = Direction.UP; +- this.selectNextMoveDirection(direction_axis); ++ this.selectNextMoveDirection(axis); ++ projectileSource = (org.bukkit.entity.LivingEntity) shooter.getBukkitEntity(); // CraftBukkit + } + ++ // CraftBukkit start ++ public Entity getTarget() { ++ return this.finalTarget; ++ } ++ ++ public void setTarget(Entity e) { ++ this.finalTarget = e; ++ this.currentMoveDirection = Direction.UP; ++ this.selectNextMoveDirection(Direction.Axis.X); ++ } ++ // CraftBukkit end ++ + @Override +- @Override + public SoundSource getSoundSource() { + return SoundSource.HOSTILE; + } + + @Override +- @Override +- protected void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); ++ protected void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); + if (this.finalTarget != null) { +- compoundtag.putUUID("Target", this.finalTarget.getUUID()); ++ compound.putUUID("Target", this.finalTarget.getUUID()); + } + + if (this.currentMoveDirection != null) { +- compoundtag.putInt("Dir", this.currentMoveDirection.get3DDataValue()); ++ compound.putInt("Dir", this.currentMoveDirection.get3DDataValue()); + } + +- compoundtag.putInt("Steps", this.flightSteps); +- compoundtag.putDouble("TXD", this.targetDeltaX); +- compoundtag.putDouble("TYD", this.targetDeltaY); +- compoundtag.putDouble("TZD", this.targetDeltaZ); ++ compound.putInt("Steps", this.flightSteps); ++ compound.putDouble("TXD", this.targetDeltaX); ++ compound.putDouble("TYD", this.targetDeltaY); ++ compound.putDouble("TZD", this.targetDeltaZ); + } + + @Override +- @Override +- protected void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.flightSteps = compoundtag.getInt("Steps"); +- this.targetDeltaX = compoundtag.getDouble("TXD"); +- this.targetDeltaY = compoundtag.getDouble("TYD"); +- this.targetDeltaZ = compoundtag.getDouble("TZD"); +- if (compoundtag.contains("Dir", 99)) { +- this.currentMoveDirection = Direction.from3DDataValue(compoundtag.getInt("Dir")); ++ protected void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.flightSteps = compound.getInt("Steps"); ++ this.targetDeltaX = compound.getDouble("TXD"); ++ this.targetDeltaY = compound.getDouble("TYD"); ++ this.targetDeltaZ = compound.getDouble("TZD"); ++ if (compound.contains("Dir", 99)) { ++ this.currentMoveDirection = Direction.from3DDataValue(compound.getInt("Dir")); + } + +- if (compoundtag.hasUUID("Target")) { +- this.targetId = compoundtag.getUUID("Target"); ++ if (compound.hasUUID("Target")) { ++ this.targetId = compound.getUUID("Target"); + } + + } + + @Override +- @Override + protected void defineSynchedData() {} + + @Nullable +@@ -117,65 +126,65 @@ + this.currentMoveDirection = direction; + } + +- private void selectNextMoveDirection(@Nullable Direction.Axis direction_axis) { ++ private void selectNextMoveDirection(@Nullable Direction.Axis axis) { + double d0 = 0.5D; +- BlockPos blockpos; ++ BlockPos blockposition; + + if (this.finalTarget == null) { +- blockpos = this.blockPosition().below(); ++ blockposition = this.blockPosition().below(); + } else { + d0 = (double) this.finalTarget.getBbHeight() * 0.5D; +- blockpos = BlockPos.containing(this.finalTarget.getX(), this.finalTarget.getY() + d0, this.finalTarget.getZ()); ++ blockposition = BlockPos.containing(this.finalTarget.getX(), this.finalTarget.getY() + d0, this.finalTarget.getZ()); + } + +- double d1 = (double) blockpos.getX() + 0.5D; +- double d2 = (double) blockpos.getY() + d0; +- double d3 = (double) blockpos.getZ() + 0.5D; +- Direction direction = null; ++ double d1 = (double) blockposition.getX() + 0.5D; ++ double d2 = (double) blockposition.getY() + d0; ++ double d3 = (double) blockposition.getZ() + 0.5D; ++ Direction enumdirection = null; + +- if (!blockpos.closerToCenterThan(this.position(), 2.0D)) { +- BlockPos blockpos1 = this.blockPosition(); ++ if (!blockposition.closerToCenterThan(this.position(), 2.0D)) { ++ BlockPos blockposition1 = this.blockPosition(); + List list = Lists.newArrayList(); + +- if (direction_axis != Direction.Axis.X) { +- if (blockpos1.getX() < blockpos.getX() && this.level().isEmptyBlock(blockpos1.east())) { ++ if (axis != Direction.Axis.X) { ++ if (blockposition1.getX() < blockposition.getX() && this.level().isEmptyBlock(blockposition1.east())) { + list.add(Direction.EAST); +- } else if (blockpos1.getX() > blockpos.getX() && this.level().isEmptyBlock(blockpos1.west())) { ++ } else if (blockposition1.getX() > blockposition.getX() && this.level().isEmptyBlock(blockposition1.west())) { + list.add(Direction.WEST); + } + } + +- if (direction_axis != Direction.Axis.Y) { +- if (blockpos1.getY() < blockpos.getY() && this.level().isEmptyBlock(blockpos1.above())) { ++ if (axis != Direction.Axis.Y) { ++ if (blockposition1.getY() < blockposition.getY() && this.level().isEmptyBlock(blockposition1.above())) { + list.add(Direction.UP); +- } else if (blockpos1.getY() > blockpos.getY() && this.level().isEmptyBlock(blockpos1.below())) { ++ } else if (blockposition1.getY() > blockposition.getY() && this.level().isEmptyBlock(blockposition1.below())) { + list.add(Direction.DOWN); + } + } + +- if (direction_axis != Direction.Axis.Z) { +- if (blockpos1.getZ() < blockpos.getZ() && this.level().isEmptyBlock(blockpos1.south())) { ++ if (axis != Direction.Axis.Z) { ++ if (blockposition1.getZ() < blockposition.getZ() && this.level().isEmptyBlock(blockposition1.south())) { + list.add(Direction.SOUTH); +- } else if (blockpos1.getZ() > blockpos.getZ() && this.level().isEmptyBlock(blockpos1.north())) { ++ } else if (blockposition1.getZ() > blockposition.getZ() && this.level().isEmptyBlock(blockposition1.north())) { + list.add(Direction.NORTH); + } + } + +- direction = Direction.getRandom(this.random); ++ enumdirection = Direction.getRandom(this.random); + if (list.isEmpty()) { +- for (int i = 5; !this.level().isEmptyBlock(blockpos1.relative(direction)) && i > 0; --i) { +- direction = Direction.getRandom(this.random); ++ for (int i = 5; !this.level().isEmptyBlock(blockposition1.relative(enumdirection)) && i > 0; --i) { ++ enumdirection = Direction.getRandom(this.random); + } + } else { +- direction = (Direction) list.get(this.random.nextInt(list.size())); ++ enumdirection = (Direction) list.get(this.random.nextInt(list.size())); + } + +- d1 = this.getX() + (double) direction.getStepX(); +- d2 = this.getY() + (double) direction.getStepY(); +- d3 = this.getZ() + (double) direction.getStepZ(); ++ d1 = this.getX() + (double) enumdirection.getStepX(); ++ d2 = this.getY() + (double) enumdirection.getStepY(); ++ d3 = this.getZ() + (double) enumdirection.getStepZ(); + } + +- this.setMoveDirection(direction); ++ this.setMoveDirection(enumdirection); + double d4 = d1 - this.getX(); + double d5 = d2 - this.getY(); + double d6 = d3 - this.getZ(); +@@ -196,7 +205,6 @@ + } + + @Override +- @Override + public void checkDespawn() { + if (this.level().getDifficulty() == Difficulty.PEACEFUL) { + this.discard(); +@@ -205,10 +213,9 @@ + } + + @Override +- @Override + public void tick() { + super.tick(); +- Vec3 vec3; ++ Vec3 vec3d; + + if (!this.level().isClientSide) { + if (this.finalTarget == null && this.targetId != null) { +@@ -222,25 +229,25 @@ + this.targetDeltaX = Mth.clamp(this.targetDeltaX * 1.025D, -1.0D, 1.0D); + this.targetDeltaY = Mth.clamp(this.targetDeltaY * 1.025D, -1.0D, 1.0D); + this.targetDeltaZ = Mth.clamp(this.targetDeltaZ * 1.025D, -1.0D, 1.0D); +- vec3 = this.getDeltaMovement(); +- this.setDeltaMovement(vec3.add((this.targetDeltaX - vec3.x) * 0.2D, (this.targetDeltaY - vec3.y) * 0.2D, (this.targetDeltaZ - vec3.z) * 0.2D)); ++ vec3d = this.getDeltaMovement(); ++ this.setDeltaMovement(vec3d.add((this.targetDeltaX - vec3d.x) * 0.2D, (this.targetDeltaY - vec3d.y) * 0.2D, (this.targetDeltaZ - vec3d.z) * 0.2D)); + } else if (!this.isNoGravity()) { + this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.04D, 0.0D)); + } + +- HitResult hitresult = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); ++ HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); + +- if (hitresult.getType() != HitResult.Type.MISS) { +- this.onHit(hitresult); ++ if (movingobjectposition.getType() != HitResult.EnumMovingObjectType.MISS) { ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + } + } + + this.checkInsideBlocks(); +- vec3 = this.getDeltaMovement(); +- this.setPos(this.getX() + vec3.x, this.getY() + vec3.y, this.getZ() + vec3.z); ++ vec3d = this.getDeltaMovement(); ++ this.setPos(this.getX() + vec3d.x, this.getY() + vec3d.y, this.getZ() + vec3d.z); + ProjectileUtil.rotateTowardsMovement(this, 0.5F); + if (this.level().isClientSide) { +- this.level().addParticle(ParticleTypes.END_ROD, this.getX() - vec3.x, this.getY() - vec3.y + 0.15D, this.getZ() - vec3.z, 0.0D, 0.0D, 0.0D); ++ this.level().addParticle(ParticleTypes.END_ROD, this.getX() - vec3d.x, this.getY() - vec3d.y + 0.15D, this.getZ() - vec3d.z, 0.0D, 0.0D, 0.0D); + } else if (this.finalTarget != null && !this.finalTarget.isRemoved()) { + if (this.flightSteps > 0) { + --this.flightSteps; +@@ -250,16 +257,16 @@ + } + + if (this.currentMoveDirection != null) { +- BlockPos blockpos = this.blockPosition(); +- Direction.Axis direction_axis = this.currentMoveDirection.getAxis(); ++ BlockPos blockposition = this.blockPosition(); ++ Direction.Axis enumdirection_enumaxis = this.currentMoveDirection.getAxis(); + +- if (this.level().loadedAndEntityCanStandOn(blockpos.relative(this.currentMoveDirection), this)) { +- this.selectNextMoveDirection(direction_axis); ++ if (this.level().loadedAndEntityCanStandOn(blockposition.relative(this.currentMoveDirection), this)) { ++ this.selectNextMoveDirection(enumdirection_enumaxis); + } else { +- BlockPos blockpos1 = this.finalTarget.blockPosition(); ++ BlockPos blockposition1 = this.finalTarget.blockPosition(); + +- if (direction_axis == Direction.Axis.X && blockpos.getX() == blockpos1.getX() || direction_axis == Direction.Axis.Z && blockpos.getZ() == blockpos1.getZ() || direction_axis == Direction.Axis.Y && blockpos.getY() == blockpos1.getY()) { +- this.selectNextMoveDirection(direction_axis); ++ if (enumdirection_enumaxis == Direction.Axis.X && blockposition.getX() == blockposition1.getX() || enumdirection_enumaxis == Direction.Axis.Z && blockposition.getZ() == blockposition1.getZ() || enumdirection_enumaxis == Direction.Axis.Y && blockposition.getY() == blockposition1.getY()) { ++ this.selectNextMoveDirection(enumdirection_enumaxis); + } + } + } +@@ -268,53 +275,47 @@ + } + + @Override +- @Override +- protected boolean canHitEntity(Entity entity) { +- return super.canHitEntity(entity) && !entity.noPhysics; ++ protected boolean canHitEntity(Entity target) { ++ return super.canHitEntity(target) && !target.noPhysics; + } + + @Override +- @Override + public boolean isOnFire() { + return false; + } + + @Override +- @Override +- public boolean shouldRenderAtSqrDistance(double d0) { +- return d0 < 16384.0D; ++ public boolean shouldRenderAtSqrDistance(double distance) { ++ return distance < 16384.0D; + } + + @Override +- @Override + public float getLightLevelDependentMagicValue() { + return 1.0F; + } + + @Override +- @Override +- protected void onHitEntity(EntityHitResult entityhitresult) { +- super.onHitEntity(entityhitresult); +- Entity entity = entityhitresult.getEntity(); ++ protected void onHitEntity(EntityHitResult result) { ++ super.onHitEntity(result); ++ Entity entity = result.getEntity(); + Entity entity1 = this.getOwner(); +- LivingEntity livingentity = entity1 instanceof LivingEntity ? (LivingEntity) entity1 : null; +- boolean flag = entity.hurt(this.damageSources().mobProjectile(this, livingentity), 4.0F); ++ LivingEntity entityliving = entity1 instanceof LivingEntity ? (LivingEntity) entity1 : null; ++ boolean flag = entity.hurt(this.damageSources().mobProjectile(this, entityliving), 4.0F); + + if (flag) { +- this.doEnchantDamageEffects(livingentity, entity); ++ this.doEnchantDamageEffects(entityliving, entity); + if (entity instanceof LivingEntity) { +- LivingEntity livingentity1 = (LivingEntity) entity; ++ LivingEntity entityliving1 = (LivingEntity) entity; + +- livingentity1.addEffect(new MobEffectInstance(MobEffects.LEVITATION, 200), (Entity) MoreObjects.firstNonNull(entity1, this)); ++ entityliving1.addEffect(new MobEffectInstance(MobEffects.LEVITATION, 200), (Entity) MoreObjects.firstNonNull(entity1, this), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + + } + + @Override +- @Override +- protected void onHitBlock(BlockHitResult blockhitresult) { +- super.onHitBlock(blockhitresult); ++ protected void onHitBlock(BlockHitResult result) { ++ super.onHitBlock(result); + ((ServerLevel) this.level()).sendParticles(ParticleTypes.EXPLOSION, this.getX(), this.getY(), this.getZ(), 2, 0.2D, 0.2D, 0.2D, 0.0D); + this.playSound(SoundEvents.SHULKER_BULLET_HIT, 1.0F, 1.0F); + } +@@ -325,21 +326,23 @@ + } + + @Override +- @Override +- protected void onHit(HitResult hitresult) { +- super.onHit(hitresult); ++ protected void onHit(HitResult result) { ++ super.onHit(result); + this.destroy(); + } + + @Override +- @Override + public boolean isPickable() { + return true; + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { ++ public boolean hurt(DamageSource source, float amount) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, false)) { ++ return false; ++ } ++ // CraftBukkit end + if (!this.level().isClientSide) { + this.playSound(SoundEvents.SHULKER_BULLET_HURT, 1.0F, 1.0F); + ((ServerLevel) this.level()).sendParticles(ParticleTypes.CRIT, this.getX(), this.getY(), this.getZ(), 15, 0.2D, 0.2D, 0.2D, 0.0D); +@@ -350,12 +353,11 @@ + } + + @Override +- @Override +- public void recreateFromPacket(ClientboundAddEntityPacket clientboundaddentitypacket) { +- super.recreateFromPacket(clientboundaddentitypacket); +- double d0 = clientboundaddentitypacket.getXa(); +- double d1 = clientboundaddentitypacket.getYa(); +- double d2 = clientboundaddentitypacket.getZa(); ++ public void recreateFromPacket(ClientboundAddEntityPacket packet) { ++ super.recreateFromPacket(packet); ++ double d0 = packet.getXa(); ++ double d1 = packet.getYa(); ++ double d2 = packet.getZa(); + + this.setDeltaMovement(d0, d1, d2); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/SmallFireball.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/SmallFireball.java.patch new file mode 100644 index 0000000000..1a86ad36f4 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/SmallFireball.java.patch @@ -0,0 +1,109 @@ +--- a/net/minecraft/world/entity/projectile/SmallFireball.java ++++ b/net/minecraft/world/entity/projectile/SmallFireball.java +@@ -12,31 +12,43 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; // CraftBukkit + + public class SmallFireball extends Fireball { + +- public SmallFireball(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public SmallFireball(EntityType entityType, Level level) { ++ super(entityType, level); + } + +- public SmallFireball(Level level, LivingEntity livingentity, double d0, double d1, double d2) { +- super(EntityType.SMALL_FIREBALL, livingentity, d0, d1, d2, level); ++ public SmallFireball(Level level, LivingEntity shooter, double offsetX, double d1, double offsetY) { ++ super(EntityType.SMALL_FIREBALL, shooter, offsetX, d1, offsetY, level); ++ // CraftBukkit start ++ if (this.getOwner() != null && this.getOwner() instanceof Mob) { ++ isIncendiary = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); ++ } ++ // CraftBukkit end + } + +- public SmallFireball(Level level, double d0, double d1, double d2, double d3, double d4, double d5) { +- super(EntityType.SMALL_FIREBALL, d0, d1, d2, d3, d4, d5, level); ++ public SmallFireball(Level level, double x, double d1, double y, double d3, double z, double d5) { ++ super(EntityType.SMALL_FIREBALL, x, d1, y, d3, z, d5, level); + } + + @Override +- @Override +- protected void onHitEntity(EntityHitResult entityhitresult) { +- super.onHitEntity(entityhitresult); ++ protected void onHitEntity(EntityHitResult result) { ++ super.onHitEntity(result); + if (!this.level().isClientSide) { +- Entity entity = entityhitresult.getEntity(); ++ Entity entity = result.getEntity(); + Entity entity1 = this.getOwner(); + int i = entity.getRemainingFireTicks(); + +- entity.setSecondsOnFire(5); ++ // CraftBukkit start - Entity damage by entity event + combust event ++ EntityCombustByEntityEvent event = new EntityCombustByEntityEvent((org.bukkit.entity.Projectile) this.getBukkitEntity(), entity.getBukkitEntity(), 5); ++ entity.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ entity.setSecondsOnFire(event.getDuration(), false); ++ } ++ // CraftBukkit end + if (!entity.hurt(this.damageSources().fireball(this, entity1), 5.0F)) { + entity.setRemainingFireTicks(i); + } else if (entity1 instanceof LivingEntity) { +@@ -47,17 +59,16 @@ + } + + @Override +- @Override +- protected void onHitBlock(BlockHitResult blockhitresult) { +- super.onHitBlock(blockhitresult); ++ protected void onHitBlock(BlockHitResult result) { ++ super.onHitBlock(result); + if (!this.level().isClientSide) { + Entity entity = this.getOwner(); + +- if (!(entity instanceof Mob) || this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- BlockPos blockpos = blockhitresult.getBlockPos().relative(blockhitresult.getDirection()); ++ if (isIncendiary) { // CraftBukkit ++ BlockPos blockposition = result.getBlockPos().relative(result.getDirection()); + +- if (this.level().isEmptyBlock(blockpos)) { +- this.level().setBlockAndUpdate(blockpos, BaseFireBlock.getState(this.level(), blockpos)); ++ if (this.level().isEmptyBlock(blockposition) && !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition, this).isCancelled()) { // CraftBukkit ++ this.level().setBlockAndUpdate(blockposition, BaseFireBlock.getState(this.level(), blockposition)); + } + } + +@@ -65,9 +76,8 @@ + } + + @Override +- @Override +- protected void onHit(HitResult hitresult) { +- super.onHit(hitresult); ++ protected void onHit(HitResult result) { ++ super.onHit(result); + if (!this.level().isClientSide) { + this.discard(); + } +@@ -75,14 +85,12 @@ + } + + @Override +- @Override + public boolean isPickable() { + return false; + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { ++ public boolean hurt(DamageSource source, float amount) { + return false; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/SpectralArrow.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/SpectralArrow.java.patch new file mode 100644 index 0000000000..82f0ba0d12 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/SpectralArrow.java.patch @@ -0,0 +1,72 @@ +--- a/net/minecraft/world/entity/projectile/SpectralArrow.java ++++ b/net/minecraft/world/entity/projectile/SpectralArrow.java +@@ -13,22 +13,21 @@ + public class SpectralArrow extends AbstractArrow { + + private static final ItemStack DEFAULT_ARROW_STACK = new ItemStack(Items.SPECTRAL_ARROW); +- private int duration = 200; ++ public int duration = 200; + +- public SpectralArrow(EntityType entitytype, Level level) { +- super(entitytype, level, SpectralArrow.DEFAULT_ARROW_STACK); ++ public SpectralArrow(EntityType entityType, Level level) { ++ super(entityType, level, SpectralArrow.DEFAULT_ARROW_STACK); + } + +- public SpectralArrow(Level level, LivingEntity livingentity, ItemStack itemstack) { +- super(EntityType.SPECTRAL_ARROW, livingentity, level, itemstack); ++ public SpectralArrow(Level world, LivingEntity entityliving, ItemStack itemstack) { ++ super(EntityType.SPECTRAL_ARROW, entityliving, world, itemstack); + } + +- public SpectralArrow(Level level, double d0, double d1, double d2, ItemStack itemstack) { +- super(EntityType.SPECTRAL_ARROW, d0, d1, d2, level, itemstack); ++ public SpectralArrow(Level world, double d0, double d1, double d2, ItemStack itemstack) { ++ super(EntityType.SPECTRAL_ARROW, d0, d1, d2, world, itemstack); + } + + @Override +- @Override + public void tick() { + super.tick(); + if (this.level().isClientSide && !this.inGround) { +@@ -38,28 +37,25 @@ + } + + @Override +- @Override +- protected void doPostHurtEffects(LivingEntity livingentity) { +- super.doPostHurtEffects(livingentity); +- MobEffectInstance mobeffectinstance = new MobEffectInstance(MobEffects.GLOWING, this.duration, 0); ++ protected void doPostHurtEffects(LivingEntity living) { ++ super.doPostHurtEffects(living); ++ MobEffectInstance mobeffect = new MobEffectInstance(MobEffects.GLOWING, this.duration, 0); + +- livingentity.addEffect(mobeffectinstance, this.getEffectSource()); ++ living.addEffect(mobeffect, this.getEffectSource(), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ARROW); // CraftBukkit + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("Duration")) { +- this.duration = compoundtag.getInt("Duration"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("Duration")) { ++ this.duration = compound.getInt("Duration"); + } + + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("Duration", this.duration); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("Duration", this.duration); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrowableItemProjectile.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrowableItemProjectile.java.patch new file mode 100644 index 0000000000..d23fef44a0 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrowableItemProjectile.java.patch @@ -0,0 +1,87 @@ +--- a/net/minecraft/world/entity/projectile/ThrowableItemProjectile.java ++++ b/net/minecraft/world/entity/projectile/ThrowableItemProjectile.java +@@ -14,33 +14,38 @@ + + private static final EntityDataAccessor DATA_ITEM_STACK = SynchedEntityData.defineId(ThrowableItemProjectile.class, EntityDataSerializers.ITEM_STACK); + +- public ThrowableItemProjectile(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public ThrowableItemProjectile(EntityType entityType, Level level) { ++ super(entityType, level); + } + +- public ThrowableItemProjectile(EntityType entitytype, double d0, double d1, double d2, Level level) { +- super(entitytype, d0, d1, d2, level); ++ public ThrowableItemProjectile(EntityType entityType, double x, double d1, double y, Level world) { ++ super(entityType, x, d1, y, world); + } + +- public ThrowableItemProjectile(EntityType entitytype, LivingEntity livingentity, Level level) { +- super(entitytype, livingentity, level); ++ public ThrowableItemProjectile(EntityType entityType, LivingEntity shooter, Level level) { ++ super(entityType, shooter, level); + } + +- public void setItem(ItemStack itemstack) { +- if (!itemstack.is(this.getDefaultItem()) || itemstack.hasTag()) { +- this.getEntityData().set(ThrowableItemProjectile.DATA_ITEM_STACK, itemstack.copyWithCount(1)); ++ public void setItem(ItemStack stack) { ++ if (!stack.is(this.getDefaultItem()) || stack.hasTag()) { ++ this.getEntityData().set(ThrowableItemProjectile.DATA_ITEM_STACK, stack.copyWithCount(1)); + } + + } + + protected abstract Item getDefaultItem(); + +- protected ItemStack getItemRaw() { ++ // CraftBukkit start ++ public Item getDefaultItemPublic() { ++ return getDefaultItem(); ++ } ++ // CraftBukkit end ++ ++ public ItemStack getItemRaw() { + return (ItemStack) this.getEntityData().get(ThrowableItemProjectile.DATA_ITEM_STACK); + } + + @Override +- @Override + public ItemStack getItem() { + ItemStack itemstack = this.getItemRaw(); + +@@ -48,28 +53,25 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + this.getEntityData().define(ThrowableItemProjectile.DATA_ITEM_STACK, ItemStack.EMPTY); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); + ItemStack itemstack = this.getItemRaw(); + + if (!itemstack.isEmpty()) { +- compoundtag.put("Item", itemstack.save(new CompoundTag())); ++ compound.put("Item", itemstack.save(new CompoundTag())); + } + + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- ItemStack itemstack = ItemStack.of(compoundtag.getCompound("Item")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ ItemStack itemstack = ItemStack.of(compound.getCompound("Item")); + + this.setItem(itemstack); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrowableProjectile.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrowableProjectile.java.patch new file mode 100644 index 0000000000..8a80fdc246 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrowableProjectile.java.patch @@ -0,0 +1,128 @@ +--- a/net/minecraft/world/entity/projectile/ThrowableProjectile.java ++++ b/net/minecraft/world/entity/projectile/ThrowableProjectile.java +@@ -8,30 +8,29 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.TheEndGatewayBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; + + public abstract class ThrowableProjectile extends Projectile { + +- protected ThrowableProjectile(EntityType entitytype, Level level) { +- super(entitytype, level); ++ protected ThrowableProjectile(EntityType entityType, Level level) { ++ super(entityType, level); + } + +- protected ThrowableProjectile(EntityType entitytype, double d0, double d1, double d2, Level level) { +- this(entitytype, level); +- this.setPos(d0, d1, d2); ++ protected ThrowableProjectile(EntityType entityType, double x, double d1, double y, Level world) { ++ this(entityType, world); ++ this.setPos(x, d1, y); + } + +- protected ThrowableProjectile(EntityType entitytype, LivingEntity livingentity, Level level) { +- this(entitytype, livingentity.getX(), livingentity.getEyeY() - 0.10000000149011612D, livingentity.getZ(), level); +- this.setOwner(livingentity); ++ protected ThrowableProjectile(EntityType entityType, LivingEntity shooter, Level level) { ++ this(entityType, shooter.getX(), shooter.getEyeY() - 0.10000000149011612D, shooter.getZ(), level); ++ this.setOwner(shooter); + } + + @Override +- @Override +- public boolean shouldRenderAtSqrDistance(double d0) { ++ public boolean shouldRenderAtSqrDistance(double distance) { + double d1 = this.getBoundingBox().getSize() * 4.0D; + + if (Double.isNaN(d1)) { +@@ -39,43 +38,42 @@ + } + + d1 *= 64.0D; +- return d0 < d1 * d1; ++ return distance < d1 * d1; + } + + @Override +- @Override + public void tick() { + super.tick(); +- HitResult hitresult = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); ++ HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); + boolean flag = false; + +- if (hitresult.getType() == HitResult.Type.BLOCK) { +- BlockPos blockpos = ((BlockHitResult) hitresult).getBlockPos(); +- BlockState blockstate = this.level().getBlockState(blockpos); ++ if (movingobjectposition.getType() == HitResult.EnumMovingObjectType.BLOCK) { ++ BlockPos blockposition = ((BlockHitResult) movingobjectposition).getBlockPos(); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); + +- if (blockstate.is(Blocks.NETHER_PORTAL)) { +- this.handleInsidePortal(blockpos); ++ if (iblockdata.is(Blocks.NETHER_PORTAL)) { ++ this.handleInsidePortal(blockposition); + flag = true; +- } else if (blockstate.is(Blocks.END_GATEWAY)) { +- BlockEntity blockentity = this.level().getBlockEntity(blockpos); ++ } else if (iblockdata.is(Blocks.END_GATEWAY)) { ++ BlockEntity tileentity = this.level().getBlockEntity(blockposition); + +- if (blockentity instanceof TheEndGatewayBlockEntity && TheEndGatewayBlockEntity.canEntityTeleport(this)) { +- TheEndGatewayBlockEntity.teleportEntity(this.level(), blockpos, blockstate, this, (TheEndGatewayBlockEntity) blockentity); ++ if (tileentity instanceof TheEndGatewayBlockEntity && TheEndGatewayBlockEntity.canEntityTeleport(this)) { ++ TheEndGatewayBlockEntity.teleportEntity(this.level(), blockposition, iblockdata, this, (TheEndGatewayBlockEntity) tileentity); + } + + flag = true; + } + } + +- if (hitresult.getType() != HitResult.Type.MISS && !flag) { +- this.onHit(hitresult); ++ if (movingobjectposition.getType() != HitResult.EnumMovingObjectType.MISS && !flag) { ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + } + + this.checkInsideBlocks(); +- Vec3 vec3 = this.getDeltaMovement(); +- double d0 = this.getX() + vec3.x; +- double d1 = this.getY() + vec3.y; +- double d2 = this.getZ() + vec3.z; ++ Vec3 vec3d = this.getDeltaMovement(); ++ double d0 = this.getX() + vec3d.x; ++ double d1 = this.getY() + vec3d.y; ++ double d2 = this.getZ() + vec3d.z; + + this.updateRotation(); + float f; +@@ -84,7 +82,7 @@ + for (int i = 0; i < 4; ++i) { + float f1 = 0.25F; + +- this.level().addParticle(ParticleTypes.BUBBLE, d0 - vec3.x * 0.25D, d1 - vec3.y * 0.25D, d2 - vec3.z * 0.25D, vec3.x, vec3.y, vec3.z); ++ this.level().addParticle(ParticleTypes.BUBBLE, d0 - vec3d.x * 0.25D, d1 - vec3d.y * 0.25D, d2 - vec3d.z * 0.25D, vec3d.x, vec3d.y, vec3d.z); + } + + f = 0.8F; +@@ -92,11 +90,11 @@ + f = 0.99F; + } + +- this.setDeltaMovement(vec3.scale((double) f)); ++ this.setDeltaMovement(vec3d.scale((double) f)); + if (!this.isNoGravity()) { +- Vec3 vec31 = this.getDeltaMovement(); ++ Vec3 vec3d1 = this.getDeltaMovement(); + +- this.setDeltaMovement(vec31.x, vec31.y - (double) this.getGravity(), vec31.z); ++ this.setDeltaMovement(vec3d1.x, vec3d1.y - (double) this.getGravity(), vec3d1.z); + } + + this.setPos(d0, d1, d2); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrownEgg.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrownEgg.java.patch new file mode 100644 index 0000000000..87c11c9e96 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrownEgg.java.patch @@ -0,0 +1,133 @@ +--- a/net/minecraft/world/entity/projectile/ThrownEgg.java ++++ b/net/minecraft/world/entity/projectile/ThrownEgg.java +@@ -1,34 +1,38 @@ + package net.minecraft.world.entity.projectile; + +-import net.minecraft.core.particles.ItemParticleOption; +-import net.minecraft.core.particles.ParticleTypes; +-import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.animal.Chicken; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++import net.minecraft.core.particles.ItemParticleOption; ++import net.minecraft.core.particles.ParticleTypes; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.LivingEntity; ++import org.bukkit.entity.Ageable; ++import org.bukkit.entity.EntityType; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerEggThrowEvent; ++// CraftBukkit end + + public class ThrownEgg extends ThrowableItemProjectile { + +- public ThrownEgg(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public ThrownEgg(net.minecraft.world.entity.EntityType entityType, Level level) { ++ super(entityType, level); + } + +- public ThrownEgg(Level level, LivingEntity livingentity) { +- super(EntityType.EGG, livingentity, level); ++ public ThrownEgg(Level level, LivingEntity shooter) { ++ super(net.minecraft.world.entity.EntityType.EGG, shooter, level); + } + +- public ThrownEgg(Level level, double d0, double d1, double d2) { +- super(EntityType.EGG, d0, d1, d2, level); ++ public ThrownEgg(Level level, double x, double d1, double y) { ++ super(net.minecraft.world.entity.EntityType.EGG, x, d1, y, level); + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 3) { ++ public void handleEntityEvent(byte id) { ++ if (id == 3) { + double d0 = 0.08D; + + for (int i = 0; i < 8; ++i) { +@@ -39,31 +43,56 @@ + } + + @Override +- @Override +- protected void onHitEntity(EntityHitResult entityhitresult) { +- super.onHitEntity(entityhitresult); +- entityhitresult.getEntity().hurt(this.damageSources().thrown(this, this.getOwner()), 0.0F); ++ protected void onHitEntity(EntityHitResult result) { ++ super.onHitEntity(result); ++ result.getEntity().hurt(this.damageSources().thrown(this, this.getOwner()), 0.0F); + } + + @Override +- @Override +- protected void onHit(HitResult hitresult) { +- super.onHit(hitresult); ++ protected void onHit(HitResult result) { ++ super.onHit(result); + if (!this.level().isClientSide) { +- if (this.random.nextInt(8) == 0) { ++ // CraftBukkit start ++ boolean hatching = this.random.nextInt(8) == 0; ++ if (true) { ++ // CraftBukkit end + byte b0 = 1; + + if (this.random.nextInt(32) == 0) { + b0 = 4; + } + ++ // CraftBukkit start ++ EntityType hatchingType = EntityType.CHICKEN; ++ ++ Entity shooter = this.getOwner(); ++ if (!hatching) { ++ b0 = 0; ++ } ++ if (shooter instanceof ServerPlayer) { ++ PlayerEggThrowEvent event = new PlayerEggThrowEvent((Player) shooter.getBukkitEntity(), (org.bukkit.entity.Egg) this.getBukkitEntity(), hatching, b0, hatchingType); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ b0 = event.getNumHatches(); ++ hatching = event.isHatching(); ++ hatchingType = event.getHatchingType(); ++ // If hatching is set to false, ensure child count is 0 ++ if (!hatching) { ++ b0 = 0; ++ } ++ } ++ // CraftBukkit end ++ + for (int i = 0; i < b0; ++i) { +- Chicken chicken = (Chicken) EntityType.CHICKEN.create(this.level()); ++ Entity entitychicken = this.level().getWorld().makeEntity(new org.bukkit.Location(this.level().getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F), hatchingType.getEntityClass()); // CraftBukkit + +- if (chicken != null) { +- chicken.setAge(-24000); +- chicken.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); +- this.level().addFreshEntity(chicken); ++ if (entitychicken != null) { ++ // CraftBukkit start ++ if (entitychicken.getBukkitEntity() instanceof Ageable) { ++ ((Ageable) entitychicken.getBukkitEntity()).setBaby(); ++ } ++ this.level().addFreshEntity(entitychicken, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); ++ // CraftBukkit end + } + } + } +@@ -75,7 +104,6 @@ + } + + @Override +- @Override + protected Item getDefaultItem() { + return Items.EGG; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrownEnderpearl.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrownEnderpearl.java.patch new file mode 100644 index 0000000000..7ba67955be --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrownEnderpearl.java.patch @@ -0,0 +1,133 @@ +--- a/net/minecraft/world/entity/projectile/ThrownEnderpearl.java ++++ b/net/minecraft/world/entity/projectile/ThrownEnderpearl.java +@@ -17,34 +17,37 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++// CraftBukkit end + + public class ThrownEnderpearl extends ThrowableItemProjectile { + +- public ThrownEnderpearl(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public ThrownEnderpearl(EntityType entityType, Level level) { ++ super(entityType, level); + } + +- public ThrownEnderpearl(Level level, LivingEntity livingentity) { +- super(EntityType.ENDER_PEARL, livingentity, level); ++ public ThrownEnderpearl(Level level, LivingEntity shooter) { ++ super(EntityType.ENDER_PEARL, shooter, level); + } + + @Override +- @Override + protected Item getDefaultItem() { + return Items.ENDER_PEARL; + } + + @Override +- @Override +- protected void onHitEntity(EntityHitResult entityhitresult) { +- super.onHitEntity(entityhitresult); +- entityhitresult.getEntity().hurt(this.damageSources().thrown(this, this.getOwner()), 0.0F); ++ protected void onHitEntity(EntityHitResult result) { ++ super.onHitEntity(result); ++ result.getEntity().hurt(this.damageSources().thrown(this, this.getOwner()), 0.0F); + } + + @Override +- @Override +- protected void onHit(HitResult hitresult) { +- super.onHit(hitresult); ++ protected void onHit(HitResult result) { ++ super.onHit(result); + + for (int i = 0; i < 32; ++i) { + this.level().addParticle(ParticleTypes.PORTAL, this.getX(), this.getY() + this.random.nextDouble() * 2.0D, this.getZ(), this.random.nextGaussian(), 0.0D, this.random.nextGaussian()); +@@ -54,26 +57,39 @@ + Entity entity = this.getOwner(); + + if (entity instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) entity; ++ ServerPlayer entityplayer = (ServerPlayer) entity; + +- if (serverplayer.connection.isAcceptingMessages() && serverplayer.level() == this.level() && !serverplayer.isSleeping()) { +- if (this.random.nextFloat() < 0.05F && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { +- Endermite endermite = (Endermite) EntityType.ENDERMITE.create(this.level()); ++ if (entityplayer.connection.isAcceptingMessages() && entityplayer.level() == this.level() && !entityplayer.isSleeping()) { ++ // CraftBukkit start - Fire PlayerTeleportEvent ++ org.bukkit.craftbukkit.entity.CraftPlayer player = entityplayer.getBukkitEntity(); ++ org.bukkit.Location location = getBukkitEntity().getLocation(); ++ location.setPitch(player.getLocation().getPitch()); ++ location.setYaw(player.getLocation().getYaw()); + +- if (endermite != null) { +- endermite.moveTo(entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot()); +- this.level().addFreshEntity(endermite); ++ PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.ENDER_PEARL); ++ Bukkit.getPluginManager().callEvent(teleEvent); ++ ++ if (!teleEvent.isCancelled() && entityplayer.connection.isAcceptingMessages()) { ++ if (this.random.nextFloat() < 0.05F && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { ++ Endermite entityendermite = (Endermite) EntityType.ENDERMITE.create(this.level()); ++ ++ if (entityendermite != null) { ++ entityendermite.moveTo(entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot()); ++ this.level().addFreshEntity(entityendermite, CreatureSpawnEvent.SpawnReason.ENDER_PEARL); ++ } + } +- } + +- if (entity.isPassenger()) { +- serverplayer.dismountTo(this.getX(), this.getY(), this.getZ()); +- } else { +- entity.teleportTo(this.getX(), this.getY(), this.getZ()); +- } ++ if (entity.isPassenger()) { ++ entity.stopRiding(); ++ } + +- entity.resetFallDistance(); +- entity.hurt(this.damageSources().fall(), 5.0F); ++ entityplayer.connection.teleport(teleEvent.getTo()); ++ entity.resetFallDistance(); ++ CraftEventFactory.entityDamage = this; ++ entity.hurt(this.damageSources().fall(), 5.0F); ++ CraftEventFactory.entityDamage = null; ++ } ++ // CraftBukkit end + this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_TELEPORT, SoundSource.PLAYERS); + } + } else if (entity != null) { +@@ -87,7 +103,6 @@ + } + + @Override +- @Override + public void tick() { + Entity entity = this.getOwner(); + +@@ -101,14 +116,13 @@ + + @Nullable + @Override +- @Override +- public Entity changeDimension(ServerLevel serverlevel) { ++ public Entity changeDimension(ServerLevel server) { + Entity entity = this.getOwner(); + +- if (entity != null && entity.level().dimension() != serverlevel.dimension()) { ++ if (entity != null && server != null && entity.level().dimension() != server.dimension()) { // CraftBukkit - SPIGOT-6113 + this.setOwner((Entity) null); + } + +- return super.changeDimension(serverlevel); ++ return super.changeDimension(server); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java.patch new file mode 100644 index 0000000000..1768b5d3fa --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java.patch @@ -0,0 +1,59 @@ +--- a/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java ++++ b/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java +@@ -13,38 +13,44 @@ + + public class ThrownExperienceBottle extends ThrowableItemProjectile { + +- public ThrownExperienceBottle(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public ThrownExperienceBottle(EntityType entityType, Level level) { ++ super(entityType, level); + } + +- public ThrownExperienceBottle(Level level, LivingEntity livingentity) { +- super(EntityType.EXPERIENCE_BOTTLE, livingentity, level); ++ public ThrownExperienceBottle(Level level, LivingEntity shooter) { ++ super(EntityType.EXPERIENCE_BOTTLE, shooter, level); + } + +- public ThrownExperienceBottle(Level level, double d0, double d1, double d2) { +- super(EntityType.EXPERIENCE_BOTTLE, d0, d1, d2, level); ++ public ThrownExperienceBottle(Level level, double x, double d1, double y) { ++ super(EntityType.EXPERIENCE_BOTTLE, x, d1, y, level); + } + + @Override +- @Override + protected Item getDefaultItem() { + return Items.EXPERIENCE_BOTTLE; + } + + @Override +- @Override + protected float getGravity() { + return 0.07F; + } + + @Override +- @Override +- protected void onHit(HitResult hitresult) { +- super.onHit(hitresult); ++ protected void onHit(HitResult result) { ++ super.onHit(result); + if (this.level() instanceof ServerLevel) { +- this.level().levelEvent(2002, this.blockPosition(), PotionUtils.getColor(Potions.WATER)); ++ // CraftBukkit - moved to after event ++ // this.level().levelEvent(2002, this.blockPosition(), PotionUtil.getColor(Potions.WATER)); + int i = 3 + this.level().random.nextInt(5) + this.level().random.nextInt(5); + ++ // CraftBukkit start ++ org.bukkit.event.entity.ExpBottleEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExpBottleEvent(this, result, i); ++ i = event.getExperience(); ++ if (event.getShowEffect()) { ++ this.level().levelEvent(2002, this.blockPosition(), PotionUtils.getColor(Potions.WATER)); ++ } ++ // CraftBukkit end ++ + ExperienceOrb.award((ServerLevel) this.level(), this.position(), i); + this.discard(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrownPotion.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrownPotion.java.patch new file mode 100644 index 0000000000..f92606dd2d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrownPotion.java.patch @@ -0,0 +1,380 @@ +--- a/net/minecraft/world/entity/projectile/ThrownPotion.java ++++ b/net/minecraft/world/entity/projectile/ThrownPotion.java +@@ -7,13 +7,13 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.tags.BlockTags; + import net.minecraft.world.effect.MobEffect; + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.entity.AreaEffectCloud; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.animal.axolotl.Axolotl; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Item; +@@ -24,67 +24,73 @@ + import net.minecraft.world.item.alchemy.Potions; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.AbstractCandleBlock; +-import net.minecraft.world.level.block.CampfireBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++// CraftBukkit start ++import java.util.HashMap; ++import java.util.Map; ++import net.minecraft.world.effect.MobEffects; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.CampfireBlock; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.entity.LivingEntity; ++// CraftBukkit end + + public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplier { + + public static final double SPLASH_RANGE = 4.0D; + private static final double SPLASH_RANGE_SQ = 16.0D; +- public static final Predicate WATER_SENSITIVE_OR_ON_FIRE = (livingentity) -> { +- return livingentity.isSensitiveToWater() || livingentity.isOnFire(); ++ public static final Predicate WATER_SENSITIVE_OR_ON_FIRE = (entityliving) -> { ++ return entityliving.isSensitiveToWater() || entityliving.isOnFire(); + }; + +- public ThrownPotion(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public ThrownPotion(EntityType entityType, Level level) { ++ super(entityType, level); + } + +- public ThrownPotion(Level level, LivingEntity livingentity) { +- super(EntityType.POTION, livingentity, level); ++ public ThrownPotion(Level level, net.minecraft.world.entity.LivingEntity shooter) { ++ super(EntityType.POTION, shooter, level); + } + +- public ThrownPotion(Level level, double d0, double d1, double d2) { +- super(EntityType.POTION, d0, d1, d2, level); ++ public ThrownPotion(Level level, double x, double d1, double y) { ++ super(EntityType.POTION, x, d1, y, level); + } + + @Override +- @Override + protected Item getDefaultItem() { + return Items.SPLASH_POTION; + } + + @Override +- @Override + protected float getGravity() { + return 0.05F; + } + + @Override +- @Override +- protected void onHitBlock(BlockHitResult blockhitresult) { +- super.onHitBlock(blockhitresult); ++ protected void onHitBlock(BlockHitResult result) { ++ super.onHitBlock(result); + if (!this.level().isClientSide) { + ItemStack itemstack = this.getItem(); +- Potion potion = PotionUtils.getPotion(itemstack); ++ Potion potionregistry = PotionUtils.getPotion(itemstack); + List list = PotionUtils.getMobEffects(itemstack); +- boolean flag = potion == Potions.WATER && list.isEmpty(); +- Direction direction = blockhitresult.getDirection(); +- BlockPos blockpos = blockhitresult.getBlockPos(); +- BlockPos blockpos1 = blockpos.relative(direction); ++ boolean flag = potionregistry == Potions.WATER && list.isEmpty(); ++ Direction enumdirection = result.getDirection(); ++ BlockPos blockposition = result.getBlockPos(); ++ BlockPos blockposition1 = blockposition.relative(enumdirection); + + if (flag) { +- this.dowseFire(blockpos1); +- this.dowseFire(blockpos1.relative(direction.getOpposite())); ++ this.dowseFire(blockposition1); ++ this.dowseFire(blockposition1.relative(enumdirection.getOpposite())); + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction1 = (Direction) iterator.next(); ++ Direction enumdirection1 = (Direction) iterator.next(); + +- this.dowseFire(blockpos1.relative(direction1)); ++ this.dowseFire(blockposition1.relative(enumdirection1)); + } + } + +@@ -92,26 +98,25 @@ + } + + @Override +- @Override +- protected void onHit(HitResult hitresult) { +- super.onHit(hitresult); ++ protected void onHit(HitResult result) { ++ super.onHit(result); + if (!this.level().isClientSide) { + ItemStack itemstack = this.getItem(); +- Potion potion = PotionUtils.getPotion(itemstack); ++ Potion potionregistry = PotionUtils.getPotion(itemstack); + List list = PotionUtils.getMobEffects(itemstack); +- boolean flag = potion == Potions.WATER && list.isEmpty(); ++ boolean flag = potionregistry == Potions.WATER && list.isEmpty(); + + if (flag) { + this.applyWater(); +- } else if (!list.isEmpty()) { ++ } else if (true || !list.isEmpty()) { // CraftBukkit - Call event even if no effects to apply + if (this.isLingering()) { +- this.makeAreaOfEffectCloud(itemstack, potion); ++ this.makeAreaOfEffectCloud(itemstack, potionregistry, result); // CraftBukkit - Pass MovingObjectPosition + } else { +- this.applySplash(list, hitresult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitresult).getEntity() : null); ++ this.applySplash(list, result.getType() == HitResult.EnumMovingObjectType.ENTITY ? ((EntityHitResult) result).getEntity() : null, result); // CraftBukkit - Pass MovingObjectPosition + } + } + +- int i = potion.hasInstantEffects() ? 2007 : 2002; ++ int i = potionregistry.hasInstantEffects() ? 2007 : 2002; + + this.level().levelEvent(i, this.blockPosition(), PotionUtils.getColor(itemstack)); + this.discard(); +@@ -119,26 +124,26 @@ + } + + private void applyWater() { +- AABB aabb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D); +- List list = this.level().getEntitiesOfClass(LivingEntity.class, aabb, ThrownPotion.WATER_SENSITIVE_OR_ON_FIRE); ++ AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D); ++ List list = this.level().getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb, ThrownPotion.WATER_SENSITIVE_OR_ON_FIRE); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- LivingEntity livingentity = (LivingEntity) iterator.next(); +- double d0 = this.distanceToSqr((Entity) livingentity); ++ net.minecraft.world.entity.LivingEntity entityliving = (net.minecraft.world.entity.LivingEntity) iterator.next(); ++ double d0 = this.distanceToSqr((Entity) entityliving); + + if (d0 < 16.0D) { +- if (livingentity.isSensitiveToWater()) { +- livingentity.hurt(this.damageSources().indirectMagic(this, this.getOwner()), 1.0F); ++ if (entityliving.isSensitiveToWater()) { ++ entityliving.hurt(this.damageSources().indirectMagic(this, this.getOwner()), 1.0F); + } + +- if (livingentity.isOnFire() && livingentity.isAlive()) { +- livingentity.extinguishFire(); ++ if (entityliving.isOnFire() && entityliving.isAlive()) { ++ entityliving.extinguishFire(); + } + } + } + +- List list1 = this.level().getEntitiesOfClass(Axolotl.class, aabb); ++ List list1 = this.level().getEntitiesOfClass(Axolotl.class, axisalignedbb); + Iterator iterator1 = list1.iterator(); + + while (iterator1.hasNext()) { +@@ -149,100 +154,145 @@ + + } + +- private void applySplash(List list, @Nullable Entity entity) { +- AABB aabb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D); +- List list1 = this.level().getEntitiesOfClass(LivingEntity.class, aabb); ++ private void applySplash(List list, @Nullable Entity entity, HitResult position) { // CraftBukkit - Pass MovingObjectPosition ++ AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D); ++ List list1 = this.level().getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb); ++ Map affected = new HashMap(); // CraftBukkit + + if (!list1.isEmpty()) { + Entity entity1 = this.getEffectSource(); + Iterator iterator = list1.iterator(); + + while (iterator.hasNext()) { +- LivingEntity livingentity = (LivingEntity) iterator.next(); ++ net.minecraft.world.entity.LivingEntity entityliving = (net.minecraft.world.entity.LivingEntity) iterator.next(); + +- if (livingentity.isAffectedByPotions()) { +- double d0 = this.distanceToSqr((Entity) livingentity); ++ if (entityliving.isAffectedByPotions()) { ++ double d0 = this.distanceToSqr((Entity) entityliving); + + if (d0 < 16.0D) { + double d1; + +- if (livingentity == entity) { ++ if (entityliving == entity) { + d1 = 1.0D; + } else { + d1 = 1.0D - Math.sqrt(d0) / 4.0D; + } + +- Iterator iterator1 = list.iterator(); ++ // CraftBukkit start ++ affected.put((LivingEntity) entityliving.getBukkitEntity(), d1); ++ } ++ } ++ } ++ } + +- while (iterator1.hasNext()) { +- MobEffectInstance mobeffectinstance = (MobEffectInstance) iterator1.next(); +- MobEffect mobeffect = mobeffectinstance.getEffect(); ++ org.bukkit.event.entity.PotionSplashEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPotionSplashEvent(this, position, affected); ++ if (!event.isCancelled() && list != null && !list.isEmpty()) { // do not process effects if there are no effects to process ++ Entity entity1 = this.getEffectSource(); ++ for (LivingEntity victim : event.getAffectedEntities()) { ++ if (!(victim instanceof CraftLivingEntity)) { ++ continue; ++ } + +- if (mobeffect.isInstantenous()) { +- mobeffect.applyInstantenousEffect(this, this.getOwner(), livingentity, mobeffectinstance.getAmplifier(), d1); +- } else { +- int i = mobeffectinstance.mapDuration((j) -> { +- return (int) (d1 * (double) j + 0.5D); +- }); +- MobEffectInstance mobeffectinstance1 = new MobEffectInstance(mobeffect, i, mobeffectinstance.getAmplifier(), mobeffectinstance.isAmbient(), mobeffectinstance.isVisible()); ++ net.minecraft.world.entity.LivingEntity entityliving = ((CraftLivingEntity) victim).getHandle(); ++ double d1 = event.getIntensity(victim); ++ // CraftBukkit end + +- if (!mobeffectinstance1.endsWithin(20)) { +- livingentity.addEffect(mobeffectinstance1, entity1); +- } +- } ++ Iterator iterator1 = list.iterator(); ++ ++ while (iterator1.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator1.next(); ++ MobEffect mobeffectlist = mobeffect.getEffect(); ++ // CraftBukkit start - Abide by PVP settings - for players only! ++ if (!this.level().pvpMode && this.getOwner() instanceof ServerPlayer && entityliving instanceof ServerPlayer && entityliving != this.getOwner()) { ++ if (mobeffectlist == MobEffects.MOVEMENT_SLOWDOWN || mobeffectlist == MobEffects.DIG_SLOWDOWN || mobeffectlist == MobEffects.HARM || mobeffectlist == MobEffects.BLINDNESS ++ || mobeffectlist == MobEffects.HUNGER || mobeffectlist == MobEffects.WEAKNESS || mobeffectlist == MobEffects.POISON) { ++ continue; + } + } ++ // CraftBukkit end ++ ++ if (mobeffectlist.isInstantenous()) { ++ mobeffectlist.applyInstantenousEffect(this, this.getOwner(), entityliving, mobeffect.getAmplifier(), d1); ++ } else { ++ int i = mobeffect.mapDuration((j) -> { ++ return (int) (d1 * (double) j + 0.5D); ++ }); ++ MobEffectInstance mobeffect1 = new MobEffectInstance(mobeffectlist, i, mobeffect.getAmplifier(), mobeffect.isAmbient(), mobeffect.isVisible()); ++ ++ if (!mobeffect1.endsWithin(20)) { ++ entityliving.addEffect(mobeffect1, entity1, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_SPLASH); // CraftBukkit ++ } ++ } + } + } + } + + } + +- private void makeAreaOfEffectCloud(ItemStack itemstack, Potion potion) { +- AreaEffectCloud areaeffectcloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); ++ private void makeAreaOfEffectCloud(ItemStack itemstack, Potion potionregistry, HitResult position) { // CraftBukkit - Pass MovingObjectPosition ++ AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); + Entity entity = this.getOwner(); + +- if (entity instanceof LivingEntity) { +- areaeffectcloud.setOwner((LivingEntity) entity); ++ if (entity instanceof net.minecraft.world.entity.LivingEntity) { ++ entityareaeffectcloud.setOwner((net.minecraft.world.entity.LivingEntity) entity); + } + +- areaeffectcloud.setRadius(3.0F); +- areaeffectcloud.setRadiusOnUse(-0.5F); +- areaeffectcloud.setWaitTime(10); +- areaeffectcloud.setRadiusPerTick(-areaeffectcloud.getRadius() / (float) areaeffectcloud.getDuration()); +- areaeffectcloud.setPotion(potion); ++ entityareaeffectcloud.setRadius(3.0F); ++ entityareaeffectcloud.setRadiusOnUse(-0.5F); ++ entityareaeffectcloud.setWaitTime(10); ++ entityareaeffectcloud.setRadiusPerTick(-entityareaeffectcloud.getRadius() / (float) entityareaeffectcloud.getDuration()); ++ entityareaeffectcloud.setPotion(potionregistry); + Iterator iterator = PotionUtils.getCustomEffects(itemstack).iterator(); + + while (iterator.hasNext()) { +- MobEffectInstance mobeffectinstance = (MobEffectInstance) iterator.next(); ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); + +- areaeffectcloud.addEffect(new MobEffectInstance(mobeffectinstance)); ++ entityareaeffectcloud.addEffect(new MobEffectInstance(mobeffect)); + } + +- CompoundTag compoundtag = itemstack.getTag(); ++ CompoundTag nbttagcompound = itemstack.getTag(); + +- if (compoundtag != null && compoundtag.contains("CustomPotionColor", 99)) { +- areaeffectcloud.setFixedColor(compoundtag.getInt("CustomPotionColor")); ++ if (nbttagcompound != null && nbttagcompound.contains("CustomPotionColor", 99)) { ++ entityareaeffectcloud.setFixedColor(nbttagcompound.getInt("CustomPotionColor")); + } + +- this.level().addFreshEntity(areaeffectcloud); ++ // CraftBukkit start ++ org.bukkit.event.entity.LingeringPotionSplashEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callLingeringPotionSplashEvent(this, position, entityareaeffectcloud); ++ if (!(event.isCancelled() || entityareaeffectcloud.isRemoved())) { ++ this.level().addFreshEntity(entityareaeffectcloud); ++ } else { ++ entityareaeffectcloud.discard(); ++ } ++ // CraftBukkit end + } + +- private boolean isLingering() { ++ public boolean isLingering() { + return this.getItem().is(Items.LINGERING_POTION); + } + +- private void dowseFire(BlockPos blockpos) { +- BlockState blockstate = this.level().getBlockState(blockpos); ++ private void dowseFire(BlockPos pos) { ++ IBlockData iblockdata = this.level().getBlockState(pos); + +- if (blockstate.is(BlockTags.FIRE)) { +- this.level().destroyBlock(blockpos, false, this); +- } else if (AbstractCandleBlock.isLit(blockstate)) { +- AbstractCandleBlock.extinguish((Player) null, blockstate, this.level(), blockpos); +- } else if (CampfireBlock.isLitCampfire(blockstate)) { +- this.level().levelEvent((Player) null, 1009, blockpos, 0); +- CampfireBlock.dowse(this.getOwner(), this.level(), blockpos, blockstate); +- this.level().setBlockAndUpdate(blockpos, (BlockState) blockstate.setValue(CampfireBlock.LIT, false)); ++ if (iblockdata.is(BlockTags.FIRE)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityChangeBlockEvent(this, pos, Blocks.AIR.defaultBlockState())) { ++ this.level().destroyBlock(pos, false, this); ++ } ++ // CraftBukkit end ++ } else if (AbstractCandleBlock.isLit(iblockdata)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityChangeBlockEvent(this, pos, iblockdata.setValue(AbstractCandleBlock.LIT, false))) { ++ AbstractCandleBlock.extinguish((Player) null, iblockdata, this.level(), pos); ++ } ++ // CraftBukkit end ++ } else if (CampfireBlock.isLitCampfire(iblockdata)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityChangeBlockEvent(this, pos, iblockdata.setValue(CampfireBlock.LIT, false))) { ++ this.level().levelEvent((Player) null, 1009, pos, 0); ++ CampfireBlock.dowse(this.getOwner(), this.level(), pos, iblockdata); ++ this.level().setBlockAndUpdate(pos, (IBlockData) iblockdata.setValue(CampfireBlock.LIT, false)); ++ } ++ // CraftBukkit end + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrownTrident.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrownTrident.java.patch new file mode 100644 index 0000000000..d5898ab3fb --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/ThrownTrident.java.patch @@ -0,0 +1,211 @@ +--- a/net/minecraft/world/entity/projectile/ThrownTrident.java ++++ b/net/minecraft/world/entity/projectile/ThrownTrident.java +@@ -32,18 +32,17 @@ + private boolean dealtDamage; + public int clientSideReturnTridentTickCount; + +- public ThrownTrident(EntityType entitytype, Level level) { +- super(entitytype, level, ThrownTrident.DEFAULT_ARROW_STACK); ++ public ThrownTrident(EntityType entityType, Level level) { ++ super(entityType, level, ThrownTrident.DEFAULT_ARROW_STACK); + } + +- public ThrownTrident(Level level, LivingEntity livingentity, ItemStack itemstack) { +- super(EntityType.TRIDENT, livingentity, level, itemstack); +- this.entityData.set(ThrownTrident.ID_LOYALTY, (byte) EnchantmentHelper.getLoyalty(itemstack)); +- this.entityData.set(ThrownTrident.ID_FOIL, itemstack.hasFoil()); ++ public ThrownTrident(Level level, LivingEntity shooter, ItemStack stack) { ++ super(EntityType.TRIDENT, shooter, level, stack); ++ this.entityData.set(ThrownTrident.ID_LOYALTY, (byte) EnchantmentHelper.getLoyalty(stack)); ++ this.entityData.set(ThrownTrident.ID_FOIL, stack.hasFoil()); + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(ThrownTrident.ID_LOYALTY, (byte) 0); +@@ -51,7 +50,6 @@ + } + + @Override +- @Override + public void tick() { + if (this.inGroundTime > 4) { + this.dealtDamage = true; +@@ -69,16 +67,16 @@ + this.discard(); + } else { + this.setNoPhysics(true); +- Vec3 vec3 = entity.getEyePosition().subtract(this.position()); ++ Vec3 vec3d = entity.getEyePosition().subtract(this.position()); + +- this.setPosRaw(this.getX(), this.getY() + vec3.y * 0.015D * (double) b0, this.getZ()); ++ this.setPosRaw(this.getX(), this.getY() + vec3d.y * 0.015D * (double) b0, this.getZ()); + if (this.level().isClientSide) { + this.yOld = this.getY(); + } + + double d0 = 0.05D * (double) b0; + +- this.setDeltaMovement(this.getDeltaMovement().scale(0.95D).add(vec3.normalize().scale(d0))); ++ this.setDeltaMovement(this.getDeltaMovement().scale(0.95D).add(vec3d.normalize().scale(d0))); + if (this.clientSideReturnTridentTickCount == 0) { + this.playSound(SoundEvents.TRIDENT_RETURN, 10.0F, 1.0F); + } +@@ -102,28 +100,26 @@ + + @Nullable + @Override +- @Override +- protected EntityHitResult findHitEntity(Vec3 vec3, Vec3 vec31) { +- return this.dealtDamage ? null : super.findHitEntity(vec3, vec31); ++ protected EntityHitResult findHitEntity(Vec3 startVec, Vec3 endVec) { ++ return this.dealtDamage ? null : super.findHitEntity(startVec, endVec); + } + + @Override +- @Override +- protected void onHitEntity(EntityHitResult entityhitresult) { +- Entity entity = entityhitresult.getEntity(); ++ protected void onHitEntity(EntityHitResult result) { ++ Entity entity = result.getEntity(); + float f = 8.0F; + + if (entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; ++ LivingEntity entityliving = (LivingEntity) entity; + +- f += EnchantmentHelper.getDamageBonus(this.getPickupItemStackOrigin(), livingentity.getMobType()); ++ f += EnchantmentHelper.getDamageBonus(this.getPickupItemStackOrigin(), entityliving.getMobType()); + } + + Entity entity1 = this.getOwner(); + DamageSource damagesource = this.damageSources().trident(this, (Entity) (entity1 == null ? this : entity1)); + + this.dealtDamage = true; +- SoundEvent soundevent = SoundEvents.TRIDENT_HIT; ++ SoundEvent soundeffect = SoundEvents.TRIDENT_HIT; + + if (entity.hurt(damagesource, f)) { + if (entity.getType() == EntityType.ENDERMAN) { +@@ -131,14 +127,14 @@ + } + + if (entity instanceof LivingEntity) { +- LivingEntity livingentity1 = (LivingEntity) entity; ++ LivingEntity entityliving1 = (LivingEntity) entity; + + if (entity1 instanceof LivingEntity) { +- EnchantmentHelper.doPostHurtEffects(livingentity1, entity1); +- EnchantmentHelper.doPostDamageEffects((LivingEntity) entity1, livingentity1); ++ EnchantmentHelper.doPostHurtEffects(entityliving1, entity1); ++ EnchantmentHelper.doPostDamageEffects((LivingEntity) entity1, entityliving1); + } + +- this.doPostHurtEffects(livingentity1); ++ this.doPostHurtEffects(entityliving1); + } + } else if (entity.getType().is(EntityTypeTags.DEFLECTS_TRIDENTS)) { + this.deflect(); +@@ -149,22 +145,22 @@ + float f1 = 1.0F; + + if (this.level() instanceof ServerLevel && this.level().isThundering() && this.isChanneling()) { +- BlockPos blockpos = entity.blockPosition(); ++ BlockPos blockposition = entity.blockPosition(); + +- if (this.level().canSeeSky(blockpos)) { +- LightningBolt lightningbolt = (LightningBolt) EntityType.LIGHTNING_BOLT.create(this.level()); ++ if (this.level().canSeeSky(blockposition)) { ++ LightningBolt entitylightning = (LightningBolt) EntityType.LIGHTNING_BOLT.create(this.level()); + +- if (lightningbolt != null) { +- lightningbolt.moveTo(Vec3.atBottomCenterOf(blockpos)); +- lightningbolt.setCause(entity1 instanceof ServerPlayer ? (ServerPlayer) entity1 : null); +- this.level().addFreshEntity(lightningbolt); +- soundevent = SoundEvents.TRIDENT_THUNDER; ++ if (entitylightning != null) { ++ entitylightning.moveTo(Vec3.atBottomCenterOf(blockposition)); ++ entitylightning.setCause(entity1 instanceof ServerPlayer ? (ServerPlayer) entity1 : null); ++ ((ServerLevel) this.level()).strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.TRIDENT); // CraftBukkit ++ soundeffect = SoundEvents.TRIDENT_THUNDER; + f1 = 5.0F; + } + } + } + +- this.playSound(soundevent, f1, 1.0F); ++ this.playSound(soundeffect, f1, 1.0F); + } + + public boolean isChanneling() { +@@ -172,43 +168,37 @@ + } + + @Override +- @Override + protected boolean tryPickup(Player player) { + return super.tryPickup(player) || this.isNoPhysics() && this.ownedBy(player) && player.getInventory().add(this.getPickupItem()); + } + + @Override +- @Override + protected SoundEvent getDefaultHitGroundSoundEvent() { + return SoundEvents.TRIDENT_HIT_GROUND; + } + + @Override +- @Override +- public void playerTouch(Player player) { +- if (this.ownedBy(player) || this.getOwner() == null) { +- super.playerTouch(player); ++ public void playerTouch(Player entity) { ++ if (this.ownedBy(entity) || this.getOwner() == null) { ++ super.playerTouch(entity); + } + + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.dealtDamage = compoundtag.getBoolean("DealtDamage"); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.dealtDamage = compound.getBoolean("DealtDamage"); + this.entityData.set(ThrownTrident.ID_LOYALTY, (byte) EnchantmentHelper.getLoyalty(this.getPickupItemStackOrigin())); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putBoolean("DealtDamage", this.dealtDamage); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putBoolean("DealtDamage", this.dealtDamage); + } + + @Override +- @Override + public void tickDespawn() { + byte b0 = (Byte) this.entityData.get(ThrownTrident.ID_LOYALTY); + +@@ -219,14 +209,12 @@ + } + + @Override +- @Override + protected float getWaterInertia() { + return 0.99F; + } + + @Override +- @Override +- public boolean shouldRender(double d0, double d1, double d2) { ++ public boolean shouldRender(double x, double d1, double y) { + return true; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/WindCharge.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/WindCharge.java.patch new file mode 100644 index 0000000000..6fe717aedc --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/WindCharge.java.patch @@ -0,0 +1,169 @@ +--- a/net/minecraft/world/entity/projectile/WindCharge.java ++++ b/net/minecraft/world/entity/projectile/WindCharge.java +@@ -8,9 +8,9 @@ + import net.minecraft.world.damagesource.DamageSources; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.monster.breeze.Breeze; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.ClipContext; +@@ -24,19 +24,18 @@ + + public class WindCharge extends AbstractHurtingProjectile implements ItemSupplier { + +- public static final WindCharge.WindChargeExplosionDamageCalculator EXPLOSION_DAMAGE_CALCULATOR = new WindCharge.WindChargeExplosionDamageCalculator(); ++ public static final WindCharge.a EXPLOSION_DAMAGE_CALCULATOR = new WindCharge.a(); + +- public WindCharge(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public WindCharge(EntityType entityType, Level level) { ++ super(entityType, level); + } + +- public WindCharge(EntityType entitytype, Breeze breeze, Level level) { +- super(entitytype, breeze.getX(), breeze.getSnoutYPosition(), breeze.getZ(), level); ++ public WindCharge(EntityType entitytypes, Breeze breeze, Level world) { ++ super(entitytypes, breeze.getX(), breeze.getSnoutYPosition(), breeze.getZ(), world); + this.setOwner(breeze); + } + + @Override +- @Override + protected AABB makeBoundingBox() { + float f = this.getType().getDimensions().width / 2.0F; + float f1 = this.getType().getDimensions().height; +@@ -46,62 +45,56 @@ + } + + @Override +- @Override +- protected float getEyeHeight(Pose pose, EntityDimensions entitydimensions) { ++ protected float getEyeHeight(EntityPose pose, EntityDimensions dimensions) { + return 0.0F; + } + + @Override +- @Override + public boolean canCollideWith(Entity entity) { + return entity instanceof WindCharge ? false : super.canCollideWith(entity); + } + + @Override +- @Override +- protected boolean canHitEntity(Entity entity) { +- return entity instanceof WindCharge ? false : super.canHitEntity(entity); ++ protected boolean canHitEntity(Entity target) { ++ return target instanceof WindCharge ? false : super.canHitEntity(target); + } + + @Override +- @Override +- protected void onHitEntity(EntityHitResult entityhitresult) { +- super.onHitEntity(entityhitresult); ++ protected void onHitEntity(EntityHitResult result) { ++ super.onHitEntity(result); + if (!this.level().isClientSide) { +- Entity entity = entityhitresult.getEntity(); ++ Entity entity = result.getEntity(); + DamageSources damagesources = this.damageSources(); + Entity entity1 = this.getOwner(); +- LivingEntity livingentity; ++ LivingEntity entityliving; + + if (entity1 instanceof LivingEntity) { +- LivingEntity livingentity1 = (LivingEntity) entity1; ++ LivingEntity entityliving1 = (LivingEntity) entity1; + +- livingentity = livingentity1; ++ entityliving = entityliving1; + } else { +- livingentity = null; ++ entityliving = null; + } + +- entity.hurt(damagesources.mobProjectile(this, livingentity), 1.0F); ++ entity.hurt(damagesources.mobProjectile(this, entityliving), 1.0F); + this.explode(); + } + } + +- private void explode() { +- this.level().explode(this, (DamageSource) null, WindCharge.EXPLOSION_DAMAGE_CALCULATOR, this.getX(), this.getY(), this.getZ(), (float) (3.0D + this.random.nextDouble()), false, Level.ExplosionInteraction.BLOW, ParticleTypes.GUST, ParticleTypes.GUST_EMITTER, SoundEvents.WIND_BURST); ++ public void explode() { // PAIL private -> public ++ this.level().explode(this, (DamageSource) null, WindCharge.EXPLOSION_DAMAGE_CALCULATOR, this.getX(), this.getY(), this.getZ(), (float) (3.0D + this.random.nextDouble()), false, Level.a.BLOW, ParticleTypes.GUST, ParticleTypes.GUST_EMITTER, SoundEvents.WIND_BURST); + } + + @Override +- @Override +- protected void onHitBlock(BlockHitResult blockhitresult) { +- super.onHitBlock(blockhitresult); ++ protected void onHitBlock(BlockHitResult result) { ++ super.onHitBlock(result); + this.explode(); + this.discard(); + } + + @Override +- @Override +- protected void onHit(HitResult hitresult) { +- super.onHit(hitresult); ++ protected void onHit(HitResult result) { ++ super.onHit(result); + if (!this.level().isClientSide) { + this.discard(); + } +@@ -109,48 +102,41 @@ + } + + @Override +- @Override + protected boolean shouldBurn() { + return false; + } + + @Override +- @Override + public ItemStack getItem() { + return ItemStack.EMPTY; + } + + @Override +- @Override + protected float getInertia() { + return 1.0F; + } + + @Override +- @Override + protected float getLiquidInertia() { + return this.getInertia(); + } + + @Nullable + @Override +- @Override + protected ParticleOptions getTrailParticle() { + return null; + } + + @Override +- @Override + protected ClipContext.Block getClipType() { + return ClipContext.Block.OUTLINE; + } + +- public static final class WindChargeExplosionDamageCalculator extends ExplosionDamageCalculator { ++ public static final class a extends ExplosionDamageCalculator { + +- public WindChargeExplosionDamageCalculator() {} ++ public a() {} + + @Override +- @Override + public boolean shouldDamageEntity(Explosion explosion, Entity entity) { + return false; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/WitherSkull.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/WitherSkull.java.patch new file mode 100644 index 0000000000..35ebe55c75 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/projectile/WitherSkull.java.patch @@ -0,0 +1,177 @@ +--- a/net/minecraft/world/entity/projectile/WitherSkull.java ++++ b/net/minecraft/world/entity/projectile/WitherSkull.java +@@ -16,59 +16,58 @@ + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Explosion; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++// CraftBukkit start ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end + + public class WitherSkull extends AbstractHurtingProjectile { + + private static final EntityDataAccessor DATA_DANGEROUS = SynchedEntityData.defineId(WitherSkull.class, EntityDataSerializers.BOOLEAN); + +- public WitherSkull(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public WitherSkull(EntityType entityType, Level level) { ++ super(entityType, level); + } + +- public WitherSkull(Level level, LivingEntity livingentity, double d0, double d1, double d2) { +- super(EntityType.WITHER_SKULL, livingentity, d0, d1, d2, level); ++ public WitherSkull(Level level, LivingEntity shooter, double offsetX, double d1, double offsetY) { ++ super(EntityType.WITHER_SKULL, shooter, offsetX, d1, offsetY, level); + } + + @Override +- @Override + protected float getInertia() { + return this.isDangerous() ? 0.73F : super.getInertia(); + } + + @Override +- @Override + public boolean isOnFire() { + return false; + } + + @Override +- @Override +- public float getBlockExplosionResistance(Explosion explosion, BlockGetter blockgetter, BlockPos blockpos, BlockState blockstate, FluidState fluidstate, float f) { +- return this.isDangerous() && WitherBoss.canDestroy(blockstate) ? Math.min(0.8F, f) : f; ++ public float getBlockExplosionResistance(Explosion explosion, BlockGetter level, BlockPos pos, IBlockData blockState, FluidState fluidState, float explosionPower) { ++ return this.isDangerous() && WitherBoss.canDestroy(blockState) ? Math.min(0.8F, explosionPower) : explosionPower; + } + + @Override +- @Override +- protected void onHitEntity(EntityHitResult entityhitresult) { +- super.onHitEntity(entityhitresult); ++ protected void onHitEntity(EntityHitResult result) { ++ super.onHitEntity(result); + if (!this.level().isClientSide) { +- Entity entity = entityhitresult.getEntity(); ++ Entity entity = result.getEntity(); + Entity entity1 = this.getOwner(); +- LivingEntity livingentity; ++ LivingEntity entityliving; + boolean flag; + + if (entity1 instanceof LivingEntity) { +- livingentity = (LivingEntity) entity1; +- flag = entity.hurt(this.damageSources().witherSkull(this, livingentity), 8.0F); ++ entityliving = (LivingEntity) entity1; ++ flag = entity.hurt(this.damageSources().witherSkull(this, entityliving), 8.0F); + if (flag) { + if (entity.isAlive()) { +- this.doEnchantDamageEffects(livingentity, entity); ++ this.doEnchantDamageEffects(entityliving, entity); + } else { +- livingentity.heal(5.0F); ++ entityliving.heal(5.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.WITHER); // CraftBukkit + } + } + } else { +@@ -76,7 +75,7 @@ + } + + if (flag && entity instanceof LivingEntity) { +- livingentity = (LivingEntity) entity; ++ entityliving = (LivingEntity) entity; + byte b0 = 0; + + if (this.level().getDifficulty() == Difficulty.NORMAL) { +@@ -86,7 +85,7 @@ + } + + if (b0 > 0) { +- livingentity.addEffect(new MobEffectInstance(MobEffects.WITHER, 20 * b0, 1), this.getEffectSource()); ++ entityliving.addEffect(new MobEffectInstance(MobEffects.WITHER, 20 * b0, 1), this.getEffectSource(), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + +@@ -94,30 +93,34 @@ + } + + @Override +- @Override +- protected void onHit(HitResult hitresult) { +- super.onHit(hitresult); ++ protected void onHit(HitResult result) { ++ super.onHit(result); + if (!this.level().isClientSide) { +- this.level().explode(this, this.getX(), this.getY(), this.getZ(), 1.0F, false, Level.ExplosionInteraction.MOB); ++ // CraftBukkit start ++ // this.level().explode(this, this.getX(), this.getY(), this.getZ(), 1.0F, false, World.a.MOB); ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), 1.0F, false); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.MOB); ++ } ++ // CraftBukkit end + this.discard(); + } + + } + + @Override +- @Override + public boolean isPickable() { + return false; + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { ++ public boolean hurt(DamageSource source, float amount) { + return false; + } + + @Override +- @Override + protected void defineSynchedData() { + this.entityData.define(WitherSkull.DATA_DANGEROUS, false); + } +@@ -126,27 +129,24 @@ + return (Boolean) this.entityData.get(WitherSkull.DATA_DANGEROUS); + } + +- public void setDangerous(boolean flag) { +- this.entityData.set(WitherSkull.DATA_DANGEROUS, flag); ++ public void setDangerous(boolean invulnerable) { ++ this.entityData.set(WitherSkull.DATA_DANGEROUS, invulnerable); + } + + @Override +- @Override + protected boolean shouldBurn() { + return false; + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putBoolean("dangerous", this.isDangerous()); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putBoolean("dangerous", this.isDangerous()); + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.setDangerous(compoundtag.getBoolean("dangerous")); ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.setDangerous(compound.getBoolean("dangerous")); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/raid/Raid.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/raid/Raid.java.patch new file mode 100644 index 0000000000..a9036dbc86 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/raid/Raid.java.patch @@ -0,0 +1,805 @@ +--- a/net/minecraft/world/entity/raid/Raid.java ++++ b/net/minecraft/world/entity/raid/Raid.java +@@ -41,10 +41,10 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.SpawnPlacements; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.BlockItem; +@@ -88,65 +88,65 @@ + public static final int RAID_REMOVAL_THRESHOLD_SQR = 12544; + private final Map groupToLeaderMap = Maps.newHashMap(); + private final Map> groupRaiderMap = Maps.newHashMap(); +- private final Set heroesOfTheVillage = Sets.newHashSet(); +- private long ticksActive; ++ public final Set heroesOfTheVillage = Sets.newHashSet(); ++ public long ticksActive; + private BlockPos center; + private final ServerLevel level; + private boolean started; + private final int id; +- private float totalHealth; +- private int badOmenLevel; ++ public float totalHealth; ++ public int badOmenLevel; + private boolean active; + private int groupsSpawned; + private final ServerBossEvent raidEvent; + private int postRaidTicks; + private int raidCooldownTicks; + private final RandomSource random; +- private final int numGroups; ++ public final int numGroups; + private Raid.RaidStatus status; + private int celebrationTicks; + private Optional waveSpawnPos; + +- public Raid(int i, ServerLevel serverlevel, BlockPos blockpos) { ++ public Raid(int id, ServerLevel level, BlockPos center) { + this.raidEvent = new ServerBossEvent(Raid.RAID_NAME_COMPONENT, BossEvent.BossBarColor.RED, BossEvent.BossBarOverlay.NOTCHED_10); + this.random = RandomSource.create(); + this.waveSpawnPos = Optional.empty(); +- this.id = i; +- this.level = serverlevel; ++ this.id = id; ++ this.level = level; + this.active = true; + this.raidCooldownTicks = 300; + this.raidEvent.setProgress(0.0F); +- this.center = blockpos; +- this.numGroups = this.getNumGroups(serverlevel.getDifficulty()); ++ this.center = center; ++ this.numGroups = this.getNumGroups(level.getDifficulty()); + this.status = Raid.RaidStatus.ONGOING; + } + +- public Raid(ServerLevel serverlevel, CompoundTag compoundtag) { ++ public Raid(ServerLevel level, CompoundTag compound) { + this.raidEvent = new ServerBossEvent(Raid.RAID_NAME_COMPONENT, BossEvent.BossBarColor.RED, BossEvent.BossBarOverlay.NOTCHED_10); + this.random = RandomSource.create(); + this.waveSpawnPos = Optional.empty(); +- this.level = serverlevel; +- this.id = compoundtag.getInt("Id"); +- this.started = compoundtag.getBoolean("Started"); +- this.active = compoundtag.getBoolean("Active"); +- this.ticksActive = compoundtag.getLong("TicksActive"); +- this.badOmenLevel = compoundtag.getInt("BadOmenLevel"); +- this.groupsSpawned = compoundtag.getInt("GroupsSpawned"); +- this.raidCooldownTicks = compoundtag.getInt("PreRaidTicks"); +- this.postRaidTicks = compoundtag.getInt("PostRaidTicks"); +- this.totalHealth = compoundtag.getFloat("TotalHealth"); +- this.center = new BlockPos(compoundtag.getInt("CX"), compoundtag.getInt("CY"), compoundtag.getInt("CZ")); +- this.numGroups = compoundtag.getInt("NumGroups"); +- this.status = Raid.RaidStatus.getByName(compoundtag.getString("Status")); ++ this.level = level; ++ this.id = compound.getInt("Id"); ++ this.started = compound.getBoolean("Started"); ++ this.active = compound.getBoolean("Active"); ++ this.ticksActive = compound.getLong("TicksActive"); ++ this.badOmenLevel = compound.getInt("BadOmenLevel"); ++ this.groupsSpawned = compound.getInt("GroupsSpawned"); ++ this.raidCooldownTicks = compound.getInt("PreRaidTicks"); ++ this.postRaidTicks = compound.getInt("PostRaidTicks"); ++ this.totalHealth = compound.getFloat("TotalHealth"); ++ this.center = new BlockPos(compound.getInt("CX"), compound.getInt("CY"), compound.getInt("CZ")); ++ this.numGroups = compound.getInt("NumGroups"); ++ this.status = Raid.RaidStatus.getByName(compound.getString("Status")); + this.heroesOfTheVillage.clear(); +- if (compoundtag.contains("HeroesOfTheVillage", 9)) { +- ListTag listtag = compoundtag.getList("HeroesOfTheVillage", 11); +- Iterator iterator = listtag.iterator(); ++ if (compound.contains("HeroesOfTheVillage", 9)) { ++ ListTag nbttaglist = compound.getList("HeroesOfTheVillage", 11); ++ Iterator iterator = nbttaglist.iterator(); + + while (iterator.hasNext()) { +- Tag tag = (Tag) iterator.next(); ++ Tag nbtbase = (Tag) iterator.next(); + +- this.heroesOfTheVillage.add(NbtUtils.loadUUID(tag)); ++ this.heroesOfTheVillage.add(NbtUtils.loadUUID(nbtbase)); + } + } + +@@ -176,6 +176,12 @@ + return this.status == Raid.RaidStatus.LOSS; + } + ++ // CraftBukkit start ++ public boolean isInProgress() { ++ return this.status == RaidStatus.ONGOING; ++ } ++ // CraftBukkit end ++ + public float getTotalHealth() { + return this.totalHealth; + } +@@ -206,10 +212,10 @@ + } + + private Predicate validPlayer() { +- return (serverplayer) -> { +- BlockPos blockpos = serverplayer.blockPosition(); ++ return (entityplayer) -> { ++ BlockPos blockposition = entityplayer.blockPosition(); + +- return serverplayer.isAlive() && this.level.getRaidAt(blockpos) == this; ++ return entityplayer.isAlive() && this.level.getRaidAt(blockposition) == this; + }; + } + +@@ -218,21 +224,21 @@ + List list = this.level.getPlayers(this.validPlayer()); + Iterator iterator = list.iterator(); + +- ServerPlayer serverplayer; ++ ServerPlayer entityplayer; + + while (iterator.hasNext()) { +- serverplayer = (ServerPlayer) iterator.next(); +- if (!set.contains(serverplayer)) { +- this.raidEvent.addPlayer(serverplayer); ++ entityplayer = (ServerPlayer) iterator.next(); ++ if (!set.contains(entityplayer)) { ++ this.raidEvent.addPlayer(entityplayer); + } + } + + iterator = set.iterator(); + + while (iterator.hasNext()) { +- serverplayer = (ServerPlayer) iterator.next(); +- if (!list.contains(serverplayer)) { +- this.raidEvent.removePlayer(serverplayer); ++ entityplayer = (ServerPlayer) iterator.next(); ++ if (!list.contains(entityplayer)) { ++ this.raidEvent.removePlayer(entityplayer); + } + } + +@@ -246,8 +252,8 @@ + return this.badOmenLevel; + } + +- public void setBadOmenLevel(int i) { +- this.badOmenLevel = i; ++ public void setBadOmenLevel(int badOmenLevel) { ++ this.badOmenLevel = badOmenLevel; + } + + public void absorbBadOmen(Player player) { +@@ -272,6 +278,7 @@ + + this.active = this.level.hasChunkAt(this.center); + if (this.level.getDifficulty() == Difficulty.PEACEFUL) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.PEACE); // CraftBukkit + this.stop(); + return; + } +@@ -291,13 +298,16 @@ + if (!this.level.isVillage(this.center)) { + if (this.groupsSpawned > 0) { + this.status = Raid.RaidStatus.LOSS; ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidFinishEvent(this, new java.util.ArrayList<>()); // CraftBukkit + } else { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.NOT_IN_VILLAGE); // CraftBukkit + this.stop(); + } + } + + ++this.ticksActive; + if (this.ticksActive >= 48000L) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.TIMEOUT); // CraftBukkit + this.stop(); + return; + } +@@ -357,13 +367,13 @@ + int j = 0; + + while (this.shouldSpawnGroup()) { +- BlockPos blockpos = this.waveSpawnPos.isPresent() ? (BlockPos) this.waveSpawnPos.get() : this.findRandomSpawnPos(j, 20); ++ BlockPos blockposition = this.waveSpawnPos.isPresent() ? (BlockPos) this.waveSpawnPos.get() : this.findRandomSpawnPos(j, 20); + +- if (blockpos != null) { ++ if (blockposition != null) { + this.started = true; +- this.spawnGroup(blockpos); ++ this.spawnGroup(blockposition); + if (!flag1) { +- this.playSound(blockpos); ++ this.playSound(blockposition); + flag1 = true; + } + } else { +@@ -371,6 +381,7 @@ + } + + if (j > 3) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.UNSPAWNABLE); // CraftBukkit + this.stop(); + break; + } +@@ -383,24 +394,27 @@ + this.status = Raid.RaidStatus.VICTORY; + Iterator iterator = this.heroesOfTheVillage.iterator(); + ++ List winners = new java.util.ArrayList<>(); // CraftBukkit + while (iterator.hasNext()) { + UUID uuid = (UUID) iterator.next(); + Entity entity = this.level.getEntity(uuid); + + if (entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; ++ LivingEntity entityliving = (LivingEntity) entity; + + if (!entity.isSpectator()) { +- livingentity.addEffect(new MobEffectInstance(MobEffects.HERO_OF_THE_VILLAGE, 48000, this.badOmenLevel - 1, false, false, true)); +- if (livingentity instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) livingentity; ++ entityliving.addEffect(new MobEffectInstance(MobEffects.HERO_OF_THE_VILLAGE, 48000, this.badOmenLevel - 1, false, false, true)); ++ if (entityliving instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entityliving; + +- serverplayer.awardStat(Stats.RAID_WIN); +- CriteriaTriggers.RAID_WIN.trigger(serverplayer); ++ entityplayer.awardStat(Stats.RAID_WIN); ++ CriteriaTriggers.RAID_WIN.trigger(entityplayer); ++ winners.add(entityplayer.getBukkitEntity()); // CraftBukkit + } + } + } + } ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidFinishEvent(this, winners); // CraftBukkit + } + } + +@@ -408,6 +422,7 @@ + } else if (this.isOver()) { + ++this.celebrationTicks; + if (this.celebrationTicks >= 600) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.FINISHED); // CraftBukkit + this.stop(); + return; + } +@@ -429,20 +444,20 @@ + + private void moveRaidCenterToNearbyVillageSection() { + Stream stream = SectionPos.cube(SectionPos.of(this.center), 2); +- ServerLevel serverlevel = this.level; ++ ServerLevel worldserver = this.level; + + Objects.requireNonNull(this.level); +- stream.filter(serverlevel::isVillage).map(SectionPos::center).min(Comparator.comparingDouble((blockpos) -> { +- return blockpos.distSqr(this.center); ++ stream.filter(worldserver::isVillage).map(SectionPos::center).min(Comparator.comparingDouble((blockposition) -> { ++ return blockposition.distSqr(this.center); + })).ifPresent(this::setCenter); + } + +- private Optional getValidSpawnPos(int i) { ++ private Optional getValidSpawnPos(int offsetMultiplier) { + for (int j = 0; j < 3; ++j) { +- BlockPos blockpos = this.findRandomSpawnPos(i, 1); ++ BlockPos blockposition = this.findRandomSpawnPos(offsetMultiplier, 1); + +- if (blockpos != null) { +- return Optional.of(blockpos); ++ if (blockposition != null) { ++ return Optional.of(blockposition); + } + } + +@@ -478,25 +493,25 @@ + Iterator iterator1 = set.iterator(); + + while (iterator1.hasNext()) { +- Raider raider = (Raider) iterator1.next(); +- BlockPos blockpos = raider.blockPosition(); ++ Raider entityraider = (Raider) iterator1.next(); ++ BlockPos blockposition = entityraider.blockPosition(); + +- if (!raider.isRemoved() && raider.level().dimension() == this.level.dimension() && this.center.distSqr(blockpos) < 12544.0D) { +- if (raider.tickCount > 600) { +- if (this.level.getEntity(raider.getUUID()) == null) { +- hashset.add(raider); ++ if (!entityraider.isRemoved() && entityraider.level().dimension() == this.level.dimension() && this.center.distSqr(blockposition) < 12544.0D) { ++ if (entityraider.tickCount > 600) { ++ if (this.level.getEntity(entityraider.getUUID()) == null) { ++ hashset.add(entityraider); + } + +- if (!this.level.isVillage(blockpos) && raider.getNoActionTime() > 2400) { +- raider.setTicksOutsideRaid(raider.getTicksOutsideRaid() + 1); ++ if (!this.level.isVillage(blockposition) && entityraider.getNoActionTime() > 2400) { ++ entityraider.setTicksOutsideRaid(entityraider.getTicksOutsideRaid() + 1); + } + +- if (raider.getTicksOutsideRaid() >= 30) { +- hashset.add(raider); ++ if (entityraider.getTicksOutsideRaid() >= 30) { ++ hashset.add(entityraider); + } + } + } else { +- hashset.add(raider); ++ hashset.add(entityraider); + } + } + } +@@ -504,14 +519,14 @@ + Iterator iterator2 = hashset.iterator(); + + while (iterator2.hasNext()) { +- Raider raider1 = (Raider) iterator2.next(); ++ Raider entityraider1 = (Raider) iterator2.next(); + +- this.removeFromRaid(raider1, true); ++ this.removeFromRaid(entityraider1, true); + } + + } + +- private void playSound(BlockPos blockpos) { ++ private void playSound(BlockPos pos) { + float f = 13.0F; + boolean flag = true; + Collection collection = this.raidEvent.getPlayers(); +@@ -519,67 +534,74 @@ + Iterator iterator = this.level.players().iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); +- Vec3 vec3 = serverplayer.position(); +- Vec3 vec31 = Vec3.atCenterOf(blockpos); +- double d0 = Math.sqrt((vec31.x - vec3.x) * (vec31.x - vec3.x) + (vec31.z - vec3.z) * (vec31.z - vec3.z)); +- double d1 = vec3.x + 13.0D / d0 * (vec31.x - vec3.x); +- double d2 = vec3.z + 13.0D / d0 * (vec31.z - vec3.z); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ Vec3 vec3d = entityplayer.position(); ++ Vec3 vec3d1 = Vec3.atCenterOf(pos); ++ double d0 = Math.sqrt((vec3d1.x - vec3d.x) * (vec3d1.x - vec3d.x) + (vec3d1.z - vec3d.z) * (vec3d1.z - vec3d.z)); ++ double d1 = vec3d.x + 13.0D / d0 * (vec3d1.x - vec3d.x); ++ double d2 = vec3d.z + 13.0D / d0 * (vec3d1.z - vec3d.z); + +- if (d0 <= 64.0D || collection.contains(serverplayer)) { +- serverplayer.connection.send(new ClientboundSoundPacket(SoundEvents.RAID_HORN, SoundSource.NEUTRAL, d1, serverplayer.getY(), d2, 64.0F, 1.0F, i)); ++ if (d0 <= 64.0D || collection.contains(entityplayer)) { ++ entityplayer.connection.send(new ClientboundSoundPacket(SoundEvents.RAID_HORN, SoundSource.NEUTRAL, d1, entityplayer.getY(), d2, 64.0F, 1.0F, i)); + } + } + + } + +- private void spawnGroup(BlockPos blockpos) { ++ private void spawnGroup(BlockPos pos) { + boolean flag = false; + int i = this.groupsSpawned + 1; + + this.totalHealth = 0.0F; +- DifficultyInstance difficultyinstance = this.level.getCurrentDifficultyAt(blockpos); ++ DifficultyInstance difficultydamagescaler = this.level.getCurrentDifficultyAt(pos); + boolean flag1 = this.shouldSpawnBonusGroup(); +- Raid.RaiderType[] araid_raidertype = Raid.RaiderType.VALUES; +- int j = araid_raidertype.length; ++ Raid.RaiderType[] araid_wave = Raid.RaiderType.VALUES; ++ int j = araid_wave.length; + int k = 0; + ++ // CraftBukkit start ++ Raider leader = null; ++ List raiders = new java.util.ArrayList<>(); ++ // CraftBukkit end + while (k < j) { +- Raid.RaiderType raid_raidertype = araid_raidertype[k]; +- int l = this.getDefaultNumSpawns(raid_raidertype, i, flag1) + this.getPotentialBonusSpawns(raid_raidertype, this.random, i, difficultyinstance, flag1); ++ Raid.RaiderType raid_wave = araid_wave[k]; ++ int l = this.getDefaultNumSpawns(raid_wave, i, flag1) + this.getPotentialBonusSpawns(raid_wave, this.random, i, difficultydamagescaler, flag1); + int i1 = 0; + int j1 = 0; + + while (true) { + if (j1 < l) { +- Raider raider = (Raider) raid_raidertype.entityType.create(this.level); ++ Raider entityraider = (Raider) raid_wave.entityType.create(this.level); + +- if (raider != null) { +- if (!flag && raider.canBeLeader()) { +- raider.setPatrolLeader(true); +- this.setLeader(i, raider); ++ if (entityraider != null) { ++ if (!flag && entityraider.canBeLeader()) { ++ entityraider.setPatrolLeader(true); ++ this.setLeader(i, entityraider); + flag = true; ++ leader = entityraider; // CraftBukkit + } + +- this.joinRaid(i, raider, blockpos, false); +- if (raid_raidertype.entityType == EntityType.RAVAGER) { +- Raider raider1 = null; ++ this.joinRaid(i, entityraider, pos, false); ++ raiders.add(entityraider); // CraftBukkit ++ if (raid_wave.entityType == EntityType.RAVAGER) { ++ Raider entityraider1 = null; + + if (i == this.getNumGroups(Difficulty.NORMAL)) { +- raider1 = (Raider) EntityType.PILLAGER.create(this.level); ++ entityraider1 = (Raider) EntityType.PILLAGER.create(this.level); + } else if (i >= this.getNumGroups(Difficulty.HARD)) { + if (i1 == 0) { +- raider1 = (Raider) EntityType.EVOKER.create(this.level); ++ entityraider1 = (Raider) EntityType.EVOKER.create(this.level); + } else { +- raider1 = (Raider) EntityType.VINDICATOR.create(this.level); ++ entityraider1 = (Raider) EntityType.VINDICATOR.create(this.level); + } + } + + ++i1; +- if (raider1 != null) { +- this.joinRaid(i, raider1, blockpos, false); +- raider1.moveTo(blockpos, 0.0F, 0.0F); +- raider1.startRiding(raider); ++ if (entityraider1 != null) { ++ this.joinRaid(i, entityraider1, pos, false); ++ entityraider1.moveTo(pos, 0.0F, 0.0F); ++ entityraider1.startRiding(entityraider); ++ raiders.add(entityraider); // CraftBukkit + } + } + +@@ -597,22 +619,23 @@ + ++this.groupsSpawned; + this.updateBossbar(); + this.setDirty(); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidSpawnWaveEvent(this, leader, raiders); // CraftBukkit + } + +- public void joinRaid(int i, Raider raider, @Nullable BlockPos blockpos, boolean flag) { +- boolean flag1 = this.addWaveMob(i, raider); ++ public void joinRaid(int wave, Raider raider, @Nullable BlockPos pos, boolean isRecruited) { ++ boolean flag1 = this.addWaveMob(wave, raider); + + if (flag1) { + raider.setCurrentRaid(this); +- raider.setWave(i); ++ raider.setWave(wave); + raider.setCanJoinRaid(true); + raider.setTicksOutsideRaid(0); +- if (!flag && blockpos != null) { +- raider.setPos((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 1.0D, (double) blockpos.getZ() + 0.5D); +- raider.finalizeSpawn(this.level, this.level.getCurrentDifficultyAt(blockpos), MobSpawnType.EVENT, (SpawnGroupData) null, (CompoundTag) null); +- raider.applyRaidBuffs(i, false); ++ if (!isRecruited && pos != null) { ++ raider.setPos((double) pos.getX() + 0.5D, (double) pos.getY() + 1.0D, (double) pos.getZ() + 0.5D); ++ raider.finalizeSpawn(this.level, this.level.getCurrentDifficultyAt(pos), EnumMobSpawn.EVENT, (GroupDataEntity) null, (CompoundTag) null); ++ raider.applyRaidBuffs(wave, false); + raider.setOnGround(true); +- this.level.addFreshEntityWithPassengers(raider); ++ this.level.addFreshEntityWithPassengers(raider, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.RAID); // CraftBukkit + } + } + +@@ -629,10 +652,10 @@ + while (iterator.hasNext()) { + Set set = (Set) iterator.next(); + +- Raider raider; ++ Raider entityraider; + +- for (Iterator iterator1 = set.iterator(); iterator1.hasNext(); f += raider.getHealth()) { +- raider = (Raider) iterator1.next(); ++ for (Iterator iterator1 = set.iterator(); iterator1.hasNext(); f += entityraider.getHealth()) { ++ entityraider = (Raider) iterator1.next(); + } + } + +@@ -647,14 +670,14 @@ + return this.groupRaiderMap.values().stream().mapToInt(Set::size).sum(); + } + +- public void removeFromRaid(Raider raider, boolean flag) { ++ public void removeFromRaid(Raider raider, boolean wanderedOutOfRaid) { + Set set = (Set) this.groupRaiderMap.get(raider.getWave()); + + if (set != null) { + boolean flag1 = set.remove(raider); + + if (flag1) { +- if (flag) { ++ if (wanderedOutOfRaid) { + this.totalHealth -= raider.getHealth(); + } + +@@ -672,38 +695,38 @@ + + public static ItemStack getLeaderBannerInstance() { + ItemStack itemstack = new ItemStack(Items.WHITE_BANNER); +- CompoundTag compoundtag = new CompoundTag(); +- ListTag listtag = (new BannerPattern.Builder()).addPattern(BannerPatterns.RHOMBUS_MIDDLE, DyeColor.CYAN).addPattern(BannerPatterns.STRIPE_BOTTOM, DyeColor.LIGHT_GRAY).addPattern(BannerPatterns.STRIPE_CENTER, DyeColor.GRAY).addPattern(BannerPatterns.BORDER, DyeColor.LIGHT_GRAY).addPattern(BannerPatterns.STRIPE_MIDDLE, DyeColor.BLACK).addPattern(BannerPatterns.HALF_HORIZONTAL, DyeColor.LIGHT_GRAY).addPattern(BannerPatterns.CIRCLE_MIDDLE, DyeColor.LIGHT_GRAY).addPattern(BannerPatterns.BORDER, DyeColor.BLACK).toListTag(); ++ CompoundTag nbttagcompound = new CompoundTag(); ++ ListTag nbttaglist = (new BannerPattern.Builder()).addPattern(BannerPatterns.RHOMBUS_MIDDLE, DyeColor.CYAN).addPattern(BannerPatterns.STRIPE_BOTTOM, DyeColor.LIGHT_GRAY).addPattern(BannerPatterns.STRIPE_CENTER, DyeColor.GRAY).addPattern(BannerPatterns.BORDER, DyeColor.LIGHT_GRAY).addPattern(BannerPatterns.STRIPE_MIDDLE, DyeColor.BLACK).addPattern(BannerPatterns.HALF_HORIZONTAL, DyeColor.LIGHT_GRAY).addPattern(BannerPatterns.CIRCLE_MIDDLE, DyeColor.LIGHT_GRAY).addPattern(BannerPatterns.BORDER, DyeColor.BLACK).toListTag(); + +- compoundtag.put("Patterns", listtag); +- BlockItem.setBlockEntityData(itemstack, BlockEntityType.BANNER, compoundtag); +- itemstack.hideTooltipPart(ItemStack.TooltipPart.ADDITIONAL); ++ nbttagcompound.put("Patterns", nbttaglist); ++ BlockItem.setBlockEntityData(itemstack, BlockEntityType.BANNER, nbttagcompound); ++ itemstack.hideTooltipPart(ItemStack.HideFlags.ADDITIONAL); + itemstack.setHoverName(Component.translatable("block.minecraft.ominous_banner").withStyle(ChatFormatting.GOLD)); + return itemstack; + } + + @Nullable +- public Raider getLeader(int i) { +- return (Raider) this.groupToLeaderMap.get(i); ++ public Raider getLeader(int wave) { ++ return (Raider) this.groupToLeaderMap.get(wave); + } + + @Nullable +- private BlockPos findRandomSpawnPos(int i, int j) { +- int k = i == 0 ? 2 : 2 - i; +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ private BlockPos findRandomSpawnPos(int offsetMultiplier, int maxTry) { ++ int k = offsetMultiplier == 0 ? 2 : 2 - offsetMultiplier; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + +- for (int l = 0; l < j; ++l) { ++ for (int l = 0; l < maxTry; ++l) { + float f = this.level.random.nextFloat() * 6.2831855F; + int i1 = this.center.getX() + Mth.floor(Mth.cos(f) * 32.0F * (float) k) + this.level.random.nextInt(5); + int j1 = this.center.getZ() + Mth.floor(Mth.sin(f) * 32.0F * (float) k) + this.level.random.nextInt(5); + int k1 = this.level.getHeight(Heightmap.Types.WORLD_SURFACE, i1, j1); + +- blockpos_mutableblockpos.set(i1, k1, j1); +- if (!this.level.isVillage((BlockPos) blockpos_mutableblockpos) || i >= 2) { ++ blockposition_mutableblockposition.set(i1, k1, j1); ++ if (!this.level.isVillage((BlockPos) blockposition_mutableblockposition) || offsetMultiplier >= 2) { + boolean flag = true; + +- if (this.level.hasChunksAt(blockpos_mutableblockpos.getX() - 10, blockpos_mutableblockpos.getZ() - 10, blockpos_mutableblockpos.getX() + 10, blockpos_mutableblockpos.getZ() + 10) && this.level.isPositionEntityTicking(blockpos_mutableblockpos) && (NaturalSpawner.isSpawnPositionOk(SpawnPlacements.Type.ON_GROUND, this.level, blockpos_mutableblockpos, EntityType.RAVAGER) || this.level.getBlockState(blockpos_mutableblockpos.below()).is(Blocks.SNOW) && this.level.getBlockState(blockpos_mutableblockpos).isAir())) { +- return blockpos_mutableblockpos; ++ if (this.level.hasChunksAt(blockposition_mutableblockposition.getX() - 10, blockposition_mutableblockposition.getZ() - 10, blockposition_mutableblockposition.getX() + 10, blockposition_mutableblockposition.getZ() + 10) && this.level.isPositionEntityTicking(blockposition_mutableblockposition) && (NaturalSpawner.isSpawnPositionOk(SpawnPlacements.Surface.ON_GROUND, this.level, blockposition_mutableblockposition, EntityType.RAVAGER) || this.level.getBlockState(blockposition_mutableblockposition.below()).is(Blocks.SNOW) && this.level.getBlockState(blockposition_mutableblockposition).isAir())) { ++ return blockposition_mutableblockposition; + } + } + } +@@ -711,34 +734,34 @@ + return null; + } + +- private boolean addWaveMob(int i, Raider raider) { +- return this.addWaveMob(i, raider, true); ++ private boolean addWaveMob(int wave, Raider raider) { ++ return this.addWaveMob(wave, raider, true); + } + +- public boolean addWaveMob(int i, Raider raider, boolean flag) { +- this.groupRaiderMap.computeIfAbsent(i, (integer) -> { ++ public boolean addWaveMob(int wave, Raider raider, boolean isRecruited) { ++ this.groupRaiderMap.computeIfAbsent(wave, (integer) -> { + return Sets.newHashSet(); + }); +- Set set = (Set) this.groupRaiderMap.get(i); +- Raider raider1 = null; ++ Set set = (Set) this.groupRaiderMap.get(wave); ++ Raider entityraider1 = null; + Iterator iterator = set.iterator(); + + while (iterator.hasNext()) { +- Raider raider2 = (Raider) iterator.next(); ++ Raider entityraider2 = (Raider) iterator.next(); + +- if (raider2.getUUID().equals(raider.getUUID())) { +- raider1 = raider2; ++ if (entityraider2.getUUID().equals(raider.getUUID())) { ++ entityraider1 = entityraider2; + break; + } + } + +- if (raider1 != null) { +- set.remove(raider1); ++ if (entityraider1 != null) { ++ set.remove(entityraider1); + set.add(raider); + } + + set.add(raider); +- if (flag) { ++ if (isRecruited) { + this.totalHealth += raider.getHealth(); + } + +@@ -747,41 +770,41 @@ + return true; + } + +- public void setLeader(int i, Raider raider) { +- this.groupToLeaderMap.put(i, raider); ++ public void setLeader(int wave, Raider raider) { ++ this.groupToLeaderMap.put(wave, raider); + raider.setItemSlot(EquipmentSlot.HEAD, getLeaderBannerInstance()); + raider.setDropChance(EquipmentSlot.HEAD, 2.0F); + } + +- public void removeLeader(int i) { +- this.groupToLeaderMap.remove(i); ++ public void removeLeader(int wave) { ++ this.groupToLeaderMap.remove(wave); + } + + public BlockPos getCenter() { + return this.center; + } + +- private void setCenter(BlockPos blockpos) { +- this.center = blockpos; ++ private void setCenter(BlockPos center) { ++ this.center = center; + } + + public int getId() { + return this.id; + } + +- private int getDefaultNumSpawns(Raid.RaiderType raid_raidertype, int i, boolean flag) { +- return flag ? raid_raidertype.spawnsPerWaveBeforeBonus[this.numGroups] : raid_raidertype.spawnsPerWaveBeforeBonus[i]; ++ private int getDefaultNumSpawns(Raid.RaiderType raiderType, int wave, boolean shouldSpawnBonusGroup) { ++ return shouldSpawnBonusGroup ? raiderType.spawnsPerWaveBeforeBonus[this.numGroups] : raiderType.spawnsPerWaveBeforeBonus[wave]; + } + +- private int getPotentialBonusSpawns(Raid.RaiderType raid_raidertype, RandomSource randomsource, int i, DifficultyInstance difficultyinstance, boolean flag) { +- Difficulty difficulty = difficultyinstance.getDifficulty(); +- boolean flag1 = difficulty == Difficulty.EASY; +- boolean flag2 = difficulty == Difficulty.NORMAL; ++ private int getPotentialBonusSpawns(Raid.RaiderType raiderType, RandomSource random, int wave, DifficultyInstance difficulty, boolean shouldSpawnBonusGroup) { ++ Difficulty enumdifficulty = difficulty.getDifficulty(); ++ boolean flag1 = enumdifficulty == Difficulty.EASY; ++ boolean flag2 = enumdifficulty == Difficulty.NORMAL; + int j; + +- switch (raid_raidertype) { ++ switch (raiderType) { + case WITCH: +- if (flag1 || i <= 2 || i == 4) { ++ if (flag1 || wave <= 2 || wave == 4) { + return 0; + } + +@@ -790,7 +813,7 @@ + case PILLAGER: + case VINDICATOR: + if (flag1) { +- j = randomsource.nextInt(2); ++ j = random.nextInt(2); + } else if (flag2) { + j = 1; + } else { +@@ -798,45 +821,45 @@ + } + break; + case RAVAGER: +- j = !flag1 && flag ? 1 : 0; ++ j = !flag1 && shouldSpawnBonusGroup ? 1 : 0; + break; + default: + return 0; + } + +- return j > 0 ? randomsource.nextInt(j + 1) : 0; ++ return j > 0 ? random.nextInt(j + 1) : 0; + } + + public boolean isActive() { + return this.active; + } + +- public CompoundTag save(CompoundTag compoundtag) { +- compoundtag.putInt("Id", this.id); +- compoundtag.putBoolean("Started", this.started); +- compoundtag.putBoolean("Active", this.active); +- compoundtag.putLong("TicksActive", this.ticksActive); +- compoundtag.putInt("BadOmenLevel", this.badOmenLevel); +- compoundtag.putInt("GroupsSpawned", this.groupsSpawned); +- compoundtag.putInt("PreRaidTicks", this.raidCooldownTicks); +- compoundtag.putInt("PostRaidTicks", this.postRaidTicks); +- compoundtag.putFloat("TotalHealth", this.totalHealth); +- compoundtag.putInt("NumGroups", this.numGroups); +- compoundtag.putString("Status", this.status.getName()); +- compoundtag.putInt("CX", this.center.getX()); +- compoundtag.putInt("CY", this.center.getY()); +- compoundtag.putInt("CZ", this.center.getZ()); +- ListTag listtag = new ListTag(); ++ public CompoundTag save(CompoundTag compound) { ++ compound.putInt("Id", this.id); ++ compound.putBoolean("Started", this.started); ++ compound.putBoolean("Active", this.active); ++ compound.putLong("TicksActive", this.ticksActive); ++ compound.putInt("BadOmenLevel", this.badOmenLevel); ++ compound.putInt("GroupsSpawned", this.groupsSpawned); ++ compound.putInt("PreRaidTicks", this.raidCooldownTicks); ++ compound.putInt("PostRaidTicks", this.postRaidTicks); ++ compound.putFloat("TotalHealth", this.totalHealth); ++ compound.putInt("NumGroups", this.numGroups); ++ compound.putString("Status", this.status.getName()); ++ compound.putInt("CX", this.center.getX()); ++ compound.putInt("CY", this.center.getY()); ++ compound.putInt("CZ", this.center.getZ()); ++ ListTag nbttaglist = new ListTag(); + Iterator iterator = this.heroesOfTheVillage.iterator(); + + while (iterator.hasNext()) { + UUID uuid = (UUID) iterator.next(); + +- listtag.add(NbtUtils.createUUID(uuid)); ++ nbttaglist.add(NbtUtils.createUUID(uuid)); + } + +- compoundtag.put("HeroesOfTheVillage", listtag); +- return compoundtag; ++ compound.put("HeroesOfTheVillage", nbttaglist); ++ return compound; + } + + public int getNumGroups(Difficulty difficulty) { +@@ -858,10 +881,16 @@ + return i == 2 ? 0.1F : (i == 3 ? 0.25F : (i == 4 ? 0.5F : (i == 5 ? 0.75F : 0.0F))); + } + +- public void addHeroOfTheVillage(Entity entity) { +- this.heroesOfTheVillage.add(entity.getUUID()); ++ public void addHeroOfTheVillage(Entity player) { ++ this.heroesOfTheVillage.add(player.getUUID()); + } + ++ // CraftBukkit start - a method to get all raiders ++ public java.util.Collection getRaiders() { ++ return this.groupRaiderMap.values().stream().flatMap(Set::stream).collect(java.util.stream.Collectors.toSet()); ++ } ++ // CraftBukkit end ++ + private static enum RaidStatus { + + ONGOING, VICTORY, LOSS, STOPPED; +@@ -870,15 +899,15 @@ + + private RaidStatus() {} + +- static Raid.RaidStatus getByName(String s) { +- Raid.RaidStatus[] araid_raidstatus = Raid.RaidStatus.VALUES; +- int i = araid_raidstatus.length; ++ static Raid.RaidStatus getByName(String name) { ++ Raid.RaidStatus[] araid_status = Raid.RaidStatus.VALUES; ++ int i = araid_status.length; + + for (int j = 0; j < i; ++j) { +- Raid.RaidStatus raid_raidstatus = araid_raidstatus[j]; ++ Raid.RaidStatus raid_status = araid_status[j]; + +- if (s.equalsIgnoreCase(raid_raidstatus.name())) { +- return raid_raidstatus; ++ if (name.equalsIgnoreCase(raid_status.name())) { ++ return raid_status; + } + } + +@@ -898,8 +927,8 @@ + final EntityType entityType; + final int[] spawnsPerWaveBeforeBonus; + +- private RaiderType(EntityType entitytype, int[] aint) { +- this.entityType = entitytype; ++ private RaiderType(EntityType entitytypes, int[] aint) { ++ this.entityType = entitytypes; + this.spawnsPerWaveBeforeBonus = aint; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/raid/Raider.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/raid/Raider.java.patch new file mode 100644 index 0000000000..9d08e1beea --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/raid/Raider.java.patch @@ -0,0 +1,566 @@ +--- a/net/minecraft/world/entity/raid/Raider.java ++++ b/net/minecraft/world/entity/raid/Raider.java +@@ -22,10 +22,10 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.goal.Goal; + import net.minecraft.world.entity.ai.goal.PathfindToRaidGoal; + import net.minecraft.world.entity.ai.targeting.TargetingConditions; +@@ -46,8 +46,8 @@ + public abstract class Raider extends PatrollingMonster { + + protected static final EntityDataAccessor IS_CELEBRATING = SynchedEntityData.defineId(Raider.class, EntityDataSerializers.BOOLEAN); +- static final Predicate ALLOWED_ITEMS = (itementity) -> { +- return !itementity.hasPickUpDelay() && itementity.isAlive() && ItemStack.matches(itementity.getItem(), Raid.getLeaderBannerInstance()); ++ static final Predicate ALLOWED_ITEMS = (entityitem) -> { ++ return !entityitem.hasPickUpDelay() && entityitem.isAlive() && ItemStack.matches(entityitem.getItem(), Raid.getLeaderBannerInstance()); + }; + @Nullable + protected Raid raid; +@@ -55,12 +55,11 @@ + private boolean canJoinRaid; + private int ticksOutsideRaid; + +- protected Raider(EntityType entitytype, Level level) { +- super(entitytype, level); ++ protected Raider(EntityType entityType, Level level) { ++ super(entityType, level); + } + + @Override +- @Override + protected void registerGoals() { + super.registerGoals(); + this.goalSelector.addGoal(1, new Raider.ObtainRaidLeaderBannerGoal<>(this)); +@@ -70,7 +69,6 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Raider.IS_CELEBRATING, false); +@@ -82,12 +80,11 @@ + return this.canJoinRaid; + } + +- public void setCanJoinRaid(boolean flag) { +- this.canJoinRaid = flag; ++ public void setCanJoinRaid(boolean canJoinRaid) { ++ this.canJoinRaid = canJoinRaid; + } + + @Override +- @Override + public void aiStep() { + if (this.level() instanceof ServerLevel && this.isAlive()) { + Raid raid = this.getCurrentRaid(); +@@ -102,9 +99,9 @@ + } + } + } else { +- LivingEntity livingentity = this.getTarget(); ++ LivingEntity entityliving = this.getTarget(); + +- if (livingentity != null && (livingentity.getType() == EntityType.PLAYER || livingentity.getType() == EntityType.IRON_GOLEM)) { ++ if (entityliving != null && (entityliving.getType() == EntityType.PLAYER || entityliving.getType() == EntityType.IRON_GOLEM)) { + this.noActionTime = 0; + } + } +@@ -115,16 +112,14 @@ + } + + @Override +- @Override + protected void updateNoActionTime() { + this.noActionTime += 2; + } + + @Override +- @Override +- public void die(DamageSource damagesource) { ++ public void die(DamageSource cause) { + if (this.level() instanceof ServerLevel) { +- Entity entity = damagesource.getEntity(); ++ Entity entity = cause.getEntity(); + Raid raid = this.getCurrentRaid(); + + if (raid != null) { +@@ -141,46 +136,45 @@ + + if (this.isPatrolLeader() && raid == null && ((ServerLevel) this.level()).getRaidAt(this.blockPosition()) == null) { + ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); +- Player player = null; ++ Player entityhuman = null; + + if (entity instanceof Player) { +- player = (Player) entity; ++ entityhuman = (Player) entity; + } else if (entity instanceof Wolf) { +- Wolf wolf = (Wolf) entity; +- LivingEntity livingentity = wolf.getOwner(); ++ Wolf entitywolf = (Wolf) entity; ++ LivingEntity entityliving = entitywolf.getOwner(); + +- if (wolf.isTame() && livingentity instanceof Player) { +- player = (Player) livingentity; ++ if (entitywolf.isTame() && entityliving instanceof Player) { ++ entityhuman = (Player) entityliving; + } + } + +- if (!itemstack.isEmpty() && ItemStack.matches(itemstack, Raid.getLeaderBannerInstance()) && player != null) { +- MobEffectInstance mobeffectinstance = player.getEffect(MobEffects.BAD_OMEN); ++ if (!itemstack.isEmpty() && ItemStack.matches(itemstack, Raid.getLeaderBannerInstance()) && entityhuman != null) { ++ MobEffectInstance mobeffect = entityhuman.getEffect(MobEffects.BAD_OMEN); + byte b0 = 1; + int i; + +- if (mobeffectinstance != null) { +- i = b0 + mobeffectinstance.getAmplifier(); +- player.removeEffectNoUpdate(MobEffects.BAD_OMEN); ++ if (mobeffect != null) { ++ i = b0 + mobeffect.getAmplifier(); ++ entityhuman.removeEffectNoUpdate(MobEffects.BAD_OMEN); + } else { + i = b0 - 1; + } + + i = Mth.clamp(i, 0, 4); +- MobEffectInstance mobeffectinstance1 = new MobEffectInstance(MobEffects.BAD_OMEN, 120000, i, false, false, true); ++ MobEffectInstance mobeffect1 = new MobEffectInstance(MobEffects.BAD_OMEN, 120000, i, false, false, true); + + if (!this.level().getGameRules().getBoolean(GameRules.RULE_DISABLE_RAIDS)) { +- player.addEffect(mobeffectinstance1); ++ entityhuman.addEffect(mobeffect1, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN); // CraftBukkit + } + } + } + } + +- super.die(damagesource); ++ super.die(cause); + } + + @Override +- @Override + public boolean canJoinPatrol() { + return !this.hasActiveRaid(); + } +@@ -198,8 +192,8 @@ + return this.getCurrentRaid() != null && this.getCurrentRaid().isActive(); + } + +- public void setWave(int i) { +- this.wave = i; ++ public void setWave(int wave) { ++ this.wave = wave; + } + + public int getWave() { +@@ -210,31 +204,29 @@ + return (Boolean) this.entityData.get(Raider.IS_CELEBRATING); + } + +- public void setCelebrating(boolean flag) { +- this.entityData.set(Raider.IS_CELEBRATING, flag); ++ public void setCelebrating(boolean celebrating) { ++ this.entityData.set(Raider.IS_CELEBRATING, celebrating); + } + + @Override +- @Override +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("Wave", this.wave); +- compoundtag.putBoolean("CanJoinRaid", this.canJoinRaid); ++ public void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("Wave", this.wave); ++ compound.putBoolean("CanJoinRaid", this.canJoinRaid); + if (this.raid != null) { +- compoundtag.putInt("RaidId", this.raid.getId()); ++ compound.putInt("RaidId", this.raid.getId()); + } + + } + + @Override +- @Override +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.wave = compoundtag.getInt("Wave"); +- this.canJoinRaid = compoundtag.getBoolean("CanJoinRaid"); +- if (compoundtag.contains("RaidId", 3)) { ++ public void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.wave = compound.getInt("Wave"); ++ this.canJoinRaid = compound.getBoolean("CanJoinRaid"); ++ if (compound.contains("RaidId", 3)) { + if (this.level() instanceof ServerLevel) { +- this.raid = ((ServerLevel) this.level()).getRaids().get(compoundtag.getInt("RaidId")); ++ this.raid = ((ServerLevel) this.level()).getRaids().get(compound.getInt("RaidId")); + } + + if (this.raid != null) { +@@ -248,40 +240,37 @@ + } + + @Override +- @Override +- protected void pickUpItem(ItemEntity itementity) { +- ItemStack itemstack = itementity.getItem(); ++ protected void pickUpItem(ItemEntity itemEntity) { ++ ItemStack itemstack = itemEntity.getItem(); + boolean flag = this.hasActiveRaid() && this.getCurrentRaid().getLeader(this.getWave()) != null; + + if (this.hasActiveRaid() && !flag && ItemStack.matches(itemstack, Raid.getLeaderBannerInstance())) { +- EquipmentSlot equipmentslot = EquipmentSlot.HEAD; +- ItemStack itemstack1 = this.getItemBySlot(equipmentslot); +- double d0 = (double) this.getEquipmentDropChance(equipmentslot); ++ EquipmentSlot enumitemslot = EquipmentSlot.HEAD; ++ ItemStack itemstack1 = this.getItemBySlot(enumitemslot); ++ double d0 = (double) this.getEquipmentDropChance(enumitemslot); + + if (!itemstack1.isEmpty() && (double) Math.max(this.random.nextFloat() - 0.1F, 0.0F) < d0) { + this.spawnAtLocation(itemstack1); + } + +- this.onItemPickup(itementity); +- this.setItemSlot(equipmentslot, itemstack); +- this.take(itementity, itemstack.getCount()); +- itementity.discard(); ++ this.onItemPickup(itemEntity); ++ this.setItemSlot(enumitemslot, itemstack); ++ this.take(itemEntity, itemstack.getCount()); ++ itemEntity.discard(); + this.getCurrentRaid().setLeader(this.getWave(), this); + this.setPatrolLeader(true); + } else { +- super.pickUpItem(itementity); ++ super.pickUpItem(itemEntity); + } + + } + + @Override +- @Override +- public boolean removeWhenFarAway(double d0) { +- return this.getCurrentRaid() == null ? super.removeWhenFarAway(d0) : false; ++ public boolean removeWhenFarAway(double distanceToClosestPlayer) { ++ return this.getCurrentRaid() == null ? super.removeWhenFarAway(distanceToClosestPlayer) : false; + } + + @Override +- @Override + public boolean requiresCustomPersistence() { + return super.requiresCustomPersistence() || this.getCurrentRaid() != null; + } +@@ -290,26 +279,24 @@ + return this.ticksOutsideRaid; + } + +- public void setTicksOutsideRaid(int i) { +- this.ticksOutsideRaid = i; ++ public void setTicksOutsideRaid(int ticksOutsideRaid) { ++ this.ticksOutsideRaid = ticksOutsideRaid; + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { ++ public boolean hurt(DamageSource source, float amount) { + if (this.hasActiveRaid()) { + this.getCurrentRaid().updateBossbar(); + } + +- return super.hurt(damagesource, f); ++ return super.hurt(source, amount); + } + + @Nullable + @Override +- @Override +- public SpawnGroupData finalizeSpawn(ServerLevelAccessor serverlevelaccessor, DifficultyInstance difficultyinstance, MobSpawnType mobspawntype, @Nullable SpawnGroupData spawngroupdata, @Nullable CompoundTag compoundtag) { +- this.setCanJoinRaid(this.getType() != EntityType.WITCH || mobspawntype != MobSpawnType.NATURAL); +- return super.finalizeSpawn(serverlevelaccessor, difficultyinstance, mobspawntype, spawngroupdata, compoundtag); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ this.setCanJoinRaid(this.getType() != EntityType.WITCH || reason != EnumMobSpawn.NATURAL); ++ return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + + public abstract SoundEvent getCelebrateSound(); +@@ -318,20 +305,19 @@ + + private final T mob; + +- public ObtainRaidLeaderBannerGoal(T t0) { +- this.mob = t0; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ public ObtainRaidLeaderBannerGoal(T entityraider) { // CraftBukkit - decompile error ++ this.mob = entityraider; ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +- @Override + public boolean canUse() { + Raid raid = this.mob.getCurrentRaid(); + + if (this.mob.hasActiveRaid() && !this.mob.getCurrentRaid().isOver() && this.mob.canBeLeader() && !ItemStack.matches(this.mob.getItemBySlot(EquipmentSlot.HEAD), Raid.getLeaderBannerInstance())) { +- Raider raider = raid.getLeader(this.mob.getWave()); ++ Raider entityraider = raid.getLeader(this.mob.getWave()); + +- if (raider == null || !raider.isAlive()) { ++ if (entityraider == null || !entityraider.isAlive()) { + List list = this.mob.level().getEntitiesOfClass(ItemEntity.class, this.mob.getBoundingBox().inflate(16.0D, 8.0D, 16.0D), Raider.ALLOWED_ITEMS); + + if (!list.isEmpty()) { +@@ -346,7 +332,6 @@ + } + + @Override +- @Override + public void tick() { + if (this.mob.getNavigation().getTargetPos().closerToCenterThan(this.mob.position(), 1.414D)) { + List list = this.mob.level().getEntitiesOfClass(ItemEntity.class, this.mob.getBoundingBox().inflate(4.0D, 4.0D, 4.0D), Raider.ALLOWED_ITEMS); +@@ -368,15 +353,14 @@ + private final int distanceToPoi; + private boolean stuck; + +- public RaiderMoveThroughVillageGoal(Raider raider, double d0, int i) { ++ public RaiderMoveThroughVillageGoal(Raider raider, double speedModifier, int i) { + this.raider = raider; +- this.speedModifier = d0; ++ this.speedModifier = speedModifier; + this.distanceToPoi = i; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +- @Override + public boolean canUse() { + this.updateVisited(); + return this.isValidRaid() && this.hasSuitablePoi() && this.raider.getTarget() == null; +@@ -387,11 +371,11 @@ + } + + private boolean hasSuitablePoi() { +- ServerLevel serverlevel = (ServerLevel) this.raider.level(); +- BlockPos blockpos = this.raider.blockPosition(); +- Optional optional = serverlevel.getPoiManager().getRandom((holder) -> { ++ ServerLevel worldserver = (ServerLevel) this.raider.level(); ++ BlockPos blockposition = this.raider.blockPosition(); ++ Optional optional = worldserver.getPoiManager().getRandom((holder) -> { + return holder.is(PoiTypes.HOME); +- }, this::hasNotVisited, PoiManager.Occupancy.ANY, blockpos, 48, this.raider.random); ++ }, this::hasNotVisited, PoiManager.Occupancy.ANY, blockposition, 48, this.raider.random); + + if (optional.isEmpty()) { + return false; +@@ -402,13 +386,11 @@ + } + + @Override +- @Override + public boolean canContinueToUse() { + return this.raider.getNavigation().isDone() ? false : this.raider.getTarget() == null && !this.poiPos.closerToCenterThan(this.raider.position(), (double) (this.raider.getBbWidth() + (float) this.distanceToPoi)) && !this.stuck; + } + + @Override +- @Override + public void stop() { + if (this.poiPos.closerToCenterThan(this.raider.position(), (double) this.distanceToPoi)) { + this.visited.add(this.poiPos); +@@ -417,7 +399,6 @@ + } + + @Override +- @Override + public void start() { + super.start(); + this.raider.setNoActionTime(0); +@@ -426,38 +407,37 @@ + } + + @Override +- @Override + public void tick() { + if (this.raider.getNavigation().isDone()) { +- Vec3 vec3 = Vec3.atBottomCenterOf(this.poiPos); +- Vec3 vec31 = DefaultRandomPos.getPosTowards(this.raider, 16, 7, vec3, 0.3141592741012573D); ++ Vec3 vec3d = Vec3.atBottomCenterOf(this.poiPos); ++ Vec3 vec3d1 = DefaultRandomPos.getPosTowards(this.raider, 16, 7, vec3d, 0.3141592741012573D); + +- if (vec31 == null) { +- vec31 = DefaultRandomPos.getPosTowards(this.raider, 8, 7, vec3, 1.5707963705062866D); ++ if (vec3d1 == null) { ++ vec3d1 = DefaultRandomPos.getPosTowards(this.raider, 8, 7, vec3d, 1.5707963705062866D); + } + +- if (vec31 == null) { ++ if (vec3d1 == null) { + this.stuck = true; + return; + } + +- this.raider.getNavigation().moveTo(vec31.x, vec31.y, vec31.z, this.speedModifier); ++ this.raider.getNavigation().moveTo(vec3d1.x, vec3d1.y, vec3d1.z, this.speedModifier); + } + + } + +- private boolean hasNotVisited(BlockPos blockpos) { ++ private boolean hasNotVisited(BlockPos pos) { + Iterator iterator = this.visited.iterator(); + +- BlockPos blockpos1; ++ BlockPos blockposition1; + + do { + if (!iterator.hasNext()) { + return true; + } + +- blockpos1 = (BlockPos) iterator.next(); +- } while (!Objects.equals(blockpos, blockpos1)); ++ blockposition1 = (BlockPos) iterator.next(); ++ } while (!Objects.equals(pos, blockposition1)); + + return false; + } +@@ -474,13 +454,12 @@ + + private final Raider mob; + +- RaiderCelebration(Raider raider) { +- this.mob = raider; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ RaiderCelebration(Raider entityraider) { ++ this.mob = entityraider; ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +- @Override + public boolean canUse() { + Raid raid = this.mob.getCurrentRaid(); + +@@ -488,21 +467,18 @@ + } + + @Override +- @Override + public void start() { + this.mob.setCelebrating(true); + super.start(); + } + + @Override +- @Override + public void stop() { + this.mob.setCelebrating(false); + super.stop(); + } + + @Override +- @Override + public void tick() { + if (!this.mob.isSilent() && this.mob.random.nextInt(this.adjustedTickDelay(100)) == 0) { + Raider.this.playSound(Raider.this.getCelebrateSound(), Raider.this.getSoundVolume(), Raider.this.getVoicePitch()); +@@ -522,22 +498,20 @@ + private final float hostileRadiusSqr; + public final TargetingConditions shoutTargeting = TargetingConditions.forNonCombat().range(8.0D).ignoreLineOfSight().ignoreInvisibilityTesting(); + +- public HoldGroundAttackGoal(AbstractIllager abstractillager, float f) { +- this.mob = abstractillager; ++ public HoldGroundAttackGoal(AbstractIllager entityillagerabstract, float f) { ++ this.mob = entityillagerabstract; + this.hostileRadiusSqr = f * f; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + } + + @Override +- @Override + public boolean canUse() { +- LivingEntity livingentity = this.mob.getLastHurtByMob(); ++ LivingEntity entityliving = this.mob.getLastHurtByMob(); + +- return this.mob.getCurrentRaid() == null && this.mob.isPatrolling() && this.mob.getTarget() != null && !this.mob.isAggressive() && (livingentity == null || livingentity.getType() != EntityType.PLAYER); ++ return this.mob.getCurrentRaid() == null && this.mob.isPatrolling() && this.mob.getTarget() != null && !this.mob.isAggressive() && (entityliving == null || entityliving.getType() != EntityType.PLAYER); + } + + @Override +- @Override + public void start() { + super.start(); + this.mob.getNavigation().stop(); +@@ -545,28 +519,27 @@ + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- Raider raider = (Raider) iterator.next(); ++ Raider entityraider = (Raider) iterator.next(); + +- raider.setTarget(this.mob.getTarget()); ++ entityraider.setTarget(this.mob.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.FOLLOW_LEADER, true); // CraftBukkit + } + + } + + @Override +- @Override + public void stop() { + super.stop(); +- LivingEntity livingentity = this.mob.getTarget(); ++ LivingEntity entityliving = this.mob.getTarget(); + +- if (livingentity != null) { ++ if (entityliving != null) { + List list = this.mob.level().getNearbyEntities(Raider.class, this.shoutTargeting, this.mob, this.mob.getBoundingBox().inflate(8.0D, 8.0D, 8.0D)); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- Raider raider = (Raider) iterator.next(); ++ Raider entityraider = (Raider) iterator.next(); + +- raider.setTarget(livingentity); +- raider.setAggressive(true); ++ entityraider.setTarget(this.mob.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.FOLLOW_LEADER, true); // CraftBukkit ++ entityraider.setAggressive(true); + } + + this.mob.setAggressive(true); +@@ -575,19 +548,17 @@ + } + + @Override +- @Override + public boolean requiresUpdateEveryTick() { + return true; + } + + @Override +- @Override + public void tick() { +- LivingEntity livingentity = this.mob.getTarget(); ++ LivingEntity entityliving = this.mob.getTarget(); + +- if (livingentity != null) { +- if (this.mob.distanceToSqr((Entity) livingentity) > (double) this.hostileRadiusSqr) { +- this.mob.getLookControl().setLookAt(livingentity, 30.0F, 30.0F); ++ if (entityliving != null) { ++ if (this.mob.distanceToSqr((Entity) entityliving) > (double) this.hostileRadiusSqr) { ++ this.mob.getLookControl().setLookAt(entityliving, 30.0F, 30.0F); + if (this.mob.random.nextInt(50) == 0) { + this.mob.playAmbientSound(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/raid/Raids.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/raid/Raids.java.patch new file mode 100644 index 0000000000..37962d53b0 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/raid/Raids.java.patch @@ -0,0 +1,233 @@ +--- a/net/minecraft/world/entity/raid/Raids.java ++++ b/net/minecraft/world/entity/raid/Raids.java +@@ -29,27 +29,27 @@ + public class Raids extends SavedData { + + private static final String RAID_FILE_ID = "raids"; +- private final Map raidMap = Maps.newHashMap(); ++ public final Map raidMap = Maps.newHashMap(); + private final ServerLevel level; + private int nextAvailableID; + private int tick; + +- public static SavedData.Factory factory(ServerLevel serverlevel) { +- return new SavedData.Factory<>(() -> { +- return new Raids(serverlevel); +- }, (compoundtag) -> { +- return load(serverlevel, compoundtag); ++ public static SavedData.a factory(ServerLevel worldserver) { ++ return new SavedData.a<>(() -> { ++ return new Raids(worldserver); ++ }, (nbttagcompound) -> { ++ return load(worldserver, nbttagcompound); + }, DataFixTypes.SAVED_DATA_RAIDS); + } + +- public Raids(ServerLevel serverlevel) { +- this.level = serverlevel; ++ public Raids(ServerLevel level) { ++ this.level = level; + this.nextAvailableID = 1; + this.setDirty(); + } + +- public Raid get(int i) { +- return (Raid) this.raidMap.get(i); ++ public Raid get(int id) { ++ return (Raid) this.raidMap.get(id); + } + + public void tick() { +@@ -83,62 +83,76 @@ + } + + @Nullable +- public Raid createOrExtendRaid(ServerPlayer serverplayer) { +- if (serverplayer.isSpectator()) { ++ public Raid createOrExtendRaid(ServerPlayer serverPlayer) { ++ if (serverPlayer.isSpectator()) { + return null; + } else if (this.level.getGameRules().getBoolean(GameRules.RULE_DISABLE_RAIDS)) { + return null; + } else { +- DimensionType dimensiontype = serverplayer.level().dimensionType(); ++ DimensionType dimensionmanager = serverPlayer.level().dimensionType(); + +- if (!dimensiontype.hasRaids()) { ++ if (!dimensionmanager.hasRaids()) { + return null; + } else { +- BlockPos blockpos = serverplayer.blockPosition(); ++ BlockPos blockposition = serverPlayer.blockPosition(); + List list = this.level.getPoiManager().getInRange((holder) -> { + return holder.is(PoiTypeTags.VILLAGE); +- }, blockpos, 64, PoiManager.Occupancy.IS_OCCUPIED).toList(); ++ }, blockposition, 64, PoiManager.Occupancy.IS_OCCUPIED).toList(); + int i = 0; +- Vec3 vec3 = Vec3.ZERO; ++ Vec3 vec3d = Vec3.ZERO; + + for (Iterator iterator = list.iterator(); iterator.hasNext(); ++i) { +- PoiRecord poirecord = (PoiRecord) iterator.next(); +- BlockPos blockpos1 = poirecord.getPos(); ++ PoiRecord villageplacerecord = (PoiRecord) iterator.next(); ++ BlockPos blockposition1 = villageplacerecord.getPos(); + +- vec3 = vec3.add((double) blockpos1.getX(), (double) blockpos1.getY(), (double) blockpos1.getZ()); ++ vec3d = vec3d.add((double) blockposition1.getX(), (double) blockposition1.getY(), (double) blockposition1.getZ()); + } + +- BlockPos blockpos2; ++ BlockPos blockposition2; + + if (i > 0) { +- vec3 = vec3.scale(1.0D / (double) i); +- blockpos2 = BlockPos.containing(vec3); ++ vec3d = vec3d.scale(1.0D / (double) i); ++ blockposition2 = BlockPos.containing(vec3d); + } else { +- blockpos2 = blockpos; ++ blockposition2 = blockposition; + } + +- Raid raid = this.getOrCreateRaid(serverplayer.serverLevel(), blockpos2); ++ Raid raid = this.getOrCreateRaid(serverPlayer.serverLevel(), blockposition2); + boolean flag = false; + + if (!raid.isStarted()) { ++ /* CraftBukkit - moved down + if (!this.raidMap.containsKey(raid.getId())) { + this.raidMap.put(raid.getId(), raid); + } ++ */ + + flag = true; +- } else if (raid.getBadOmenLevel() < raid.getMaxBadOmenLevel()) { ++ // CraftBukkit start - fixed a bug with raid: players could add up Bad Omen level even when the raid had finished ++ } else if (raid.isInProgress() && raid.getBadOmenLevel() < raid.getMaxBadOmenLevel()) { + flag = true; ++ // CraftBukkit end + } else { +- serverplayer.removeEffect(MobEffects.BAD_OMEN); +- serverplayer.connection.send(new ClientboundEntityEventPacket(serverplayer, (byte) 43)); ++ serverPlayer.removeEffect(MobEffects.BAD_OMEN); ++ serverPlayer.connection.send(new ClientboundEntityEventPacket(serverPlayer, (byte) 43)); + } + + if (flag) { +- raid.absorbBadOmen(serverplayer); +- serverplayer.connection.send(new ClientboundEntityEventPacket(serverplayer, (byte) 43)); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callRaidTriggerEvent(raid, serverPlayer)) { ++ serverPlayer.removeEffect(MobEffects.BAD_OMEN); ++ return null; ++ } ++ ++ if (!this.raidMap.containsKey(raid.getId())) { ++ this.raidMap.put(raid.getId(), raid); ++ } ++ // CraftBukkit end ++ raid.absorbBadOmen(serverPlayer); ++ serverPlayer.connection.send(new ClientboundEntityEventPacket(serverPlayer, (byte) 43)); + if (!raid.hasFirstWaveSpawned()) { +- serverplayer.awardStat(Stats.RAID_TRIGGER); +- CriteriaTriggers.BAD_OMEN.trigger(serverplayer); ++ serverPlayer.awardStat(Stats.RAID_TRIGGER); ++ CriteriaTriggers.BAD_OMEN.trigger(serverPlayer); + } + } + +@@ -148,51 +162,50 @@ + } + } + +- private Raid getOrCreateRaid(ServerLevel serverlevel, BlockPos blockpos) { +- Raid raid = serverlevel.getRaidAt(blockpos); ++ private Raid getOrCreateRaid(ServerLevel serverLevel, BlockPos pos) { ++ Raid raid = serverLevel.getRaidAt(pos); + +- return raid != null ? raid : new Raid(this.getUniqueId(), serverlevel, blockpos); ++ return raid != null ? raid : new Raid(this.getUniqueId(), serverLevel, pos); + } + +- public static Raids load(ServerLevel serverlevel, CompoundTag compoundtag) { +- Raids raids = new Raids(serverlevel); ++ public static Raids load(ServerLevel level, CompoundTag tag) { ++ Raids persistentraid = new Raids(level); + +- raids.nextAvailableID = compoundtag.getInt("NextAvailableID"); +- raids.tick = compoundtag.getInt("Tick"); +- ListTag listtag = compoundtag.getList("Raids", 10); ++ persistentraid.nextAvailableID = tag.getInt("NextAvailableID"); ++ persistentraid.tick = tag.getInt("Tick"); ++ ListTag nbttaglist = tag.getList("Raids", 10); + +- for (int i = 0; i < listtag.size(); ++i) { +- CompoundTag compoundtag1 = listtag.getCompound(i); +- Raid raid = new Raid(serverlevel, compoundtag1); ++ for (int i = 0; i < nbttaglist.size(); ++i) { ++ CompoundTag nbttagcompound1 = nbttaglist.getCompound(i); ++ Raid raid = new Raid(level, nbttagcompound1); + +- raids.raidMap.put(raid.getId(), raid); ++ persistentraid.raidMap.put(raid.getId(), raid); + } + +- return raids; ++ return persistentraid; + } + + @Override +- @Override +- public CompoundTag save(CompoundTag compoundtag) { +- compoundtag.putInt("NextAvailableID", this.nextAvailableID); +- compoundtag.putInt("Tick", this.tick); +- ListTag listtag = new ListTag(); ++ public CompoundTag save(CompoundTag compound) { ++ compound.putInt("NextAvailableID", this.nextAvailableID); ++ compound.putInt("Tick", this.tick); ++ ListTag nbttaglist = new ListTag(); + Iterator iterator = this.raidMap.values().iterator(); + + while (iterator.hasNext()) { + Raid raid = (Raid) iterator.next(); +- CompoundTag compoundtag1 = new CompoundTag(); ++ CompoundTag nbttagcompound1 = new CompoundTag(); + +- raid.save(compoundtag1); +- listtag.add(compoundtag1); ++ raid.save(nbttagcompound1); ++ nbttaglist.add(nbttagcompound1); + } + +- compoundtag.put("Raids", listtag); +- return compoundtag; ++ compound.put("Raids", nbttaglist); ++ return compound; + } + +- public static String getFileId(Holder holder) { +- return holder.is(BuiltinDimensionTypes.END) ? "raids_end" : "raids"; ++ public static String getFileId(Holder dimensionTypeHolder) { ++ return dimensionTypeHolder.is(BuiltinDimensionTypes.END) ? "raids_end" : "raids"; + } + + private int getUniqueId() { +@@ -200,14 +213,14 @@ + } + + @Nullable +- public Raid getNearbyRaid(BlockPos blockpos, int i) { ++ public Raid getNearbyRaid(BlockPos pos, int distance) { + Raid raid = null; +- double d0 = (double) i; ++ double d0 = (double) distance; + Iterator iterator = this.raidMap.values().iterator(); + + while (iterator.hasNext()) { + Raid raid1 = (Raid) iterator.next(); +- double d1 = raid1.getCenter().distSqr(blockpos); ++ double d1 = raid1.getCenter().distSqr(pos); + + if (raid1.isActive() && d1 < d0) { + raid = raid1; diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/AbstractMinecart.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/AbstractMinecart.java.patch new file mode 100644 index 0000000000..8263cb526d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/AbstractMinecart.java.patch @@ -0,0 +1,1114 @@ +--- a/net/minecraft/world/entity/vehicle/AbstractMinecart.java ++++ b/net/minecraft/world/entity/vehicle/AbstractMinecart.java +@@ -25,11 +25,11 @@ + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.animal.IronGolem; + import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.entity.npc.WanderingTrader; +@@ -42,12 +42,20 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.PoweredRailBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.RailShape; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.Vehicle; ++import org.bukkit.event.vehicle.VehicleEntityCollisionEvent; ++import org.bukkit.util.Vector; ++// CraftBukkit end ++ + public abstract class AbstractMinecart extends VehicleEntity { + + private static final float LOWERED_PASSENGER_ATTACHMENT_Y = 0.0F; +@@ -55,7 +63,7 @@ + private static final EntityDataAccessor DATA_ID_DISPLAY_BLOCK = SynchedEntityData.defineId(AbstractMinecart.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_ID_DISPLAY_OFFSET = SynchedEntityData.defineId(AbstractMinecart.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_ID_CUSTOM_DISPLAY = SynchedEntityData.defineId(AbstractMinecart.class, EntityDataSerializers.BOOLEAN); +- private static final ImmutableMap> POSE_DISMOUNT_HEIGHTS = ImmutableMap.of(Pose.STANDING, ImmutableList.of(0, 1, -1), Pose.CROUCHING, ImmutableList.of(0, 1, -1), Pose.SWIMMING, ImmutableList.of(0, 1)); ++ private static final ImmutableMap> POSE_DISMOUNT_HEIGHTS = ImmutableMap.of(EntityPose.STANDING, ImmutableList.of(0, 1, -1), EntityPose.CROUCHING, ImmutableList.of(0, 1, -1), EntityPose.SWIMMING, ImmutableList.of(0, 1)); + protected static final float WATER_SLOWDOWN_FACTOR = 0.95F; + private boolean flipped; + private boolean onRails; +@@ -67,81 +75,90 @@ + private double lerpXRot; + private Vec3 targetDeltaMovement; + private static final Map> EXITS = (Map) Util.make(Maps.newEnumMap(RailShape.class), (enummap) -> { +- Vec3i vec3i = Direction.WEST.getNormal(); +- Vec3i vec3i1 = Direction.EAST.getNormal(); +- Vec3i vec3i2 = Direction.NORTH.getNormal(); +- Vec3i vec3i3 = Direction.SOUTH.getNormal(); +- Vec3i vec3i4 = vec3i.below(); +- Vec3i vec3i5 = vec3i1.below(); +- Vec3i vec3i6 = vec3i2.below(); +- Vec3i vec3i7 = vec3i3.below(); ++ Vec3i baseblockposition = Direction.WEST.getNormal(); ++ Vec3i baseblockposition1 = Direction.EAST.getNormal(); ++ Vec3i baseblockposition2 = Direction.NORTH.getNormal(); ++ Vec3i baseblockposition3 = Direction.SOUTH.getNormal(); ++ Vec3i baseblockposition4 = baseblockposition.below(); ++ Vec3i baseblockposition5 = baseblockposition1.below(); ++ Vec3i baseblockposition6 = baseblockposition2.below(); ++ Vec3i baseblockposition7 = baseblockposition3.below(); + +- enummap.put(RailShape.NORTH_SOUTH, Pair.of(vec3i2, vec3i3)); +- enummap.put(RailShape.EAST_WEST, Pair.of(vec3i, vec3i1)); +- enummap.put(RailShape.ASCENDING_EAST, Pair.of(vec3i4, vec3i1)); +- enummap.put(RailShape.ASCENDING_WEST, Pair.of(vec3i, vec3i5)); +- enummap.put(RailShape.ASCENDING_NORTH, Pair.of(vec3i2, vec3i7)); +- enummap.put(RailShape.ASCENDING_SOUTH, Pair.of(vec3i6, vec3i3)); +- enummap.put(RailShape.SOUTH_EAST, Pair.of(vec3i3, vec3i1)); +- enummap.put(RailShape.SOUTH_WEST, Pair.of(vec3i3, vec3i)); +- enummap.put(RailShape.NORTH_WEST, Pair.of(vec3i2, vec3i)); +- enummap.put(RailShape.NORTH_EAST, Pair.of(vec3i2, vec3i1)); ++ enummap.put(RailShape.NORTH_SOUTH, Pair.of(baseblockposition2, baseblockposition3)); ++ enummap.put(RailShape.EAST_WEST, Pair.of(baseblockposition, baseblockposition1)); ++ enummap.put(RailShape.ASCENDING_EAST, Pair.of(baseblockposition4, baseblockposition1)); ++ enummap.put(RailShape.ASCENDING_WEST, Pair.of(baseblockposition, baseblockposition5)); ++ enummap.put(RailShape.ASCENDING_NORTH, Pair.of(baseblockposition2, baseblockposition7)); ++ enummap.put(RailShape.ASCENDING_SOUTH, Pair.of(baseblockposition6, baseblockposition3)); ++ enummap.put(RailShape.SOUTH_EAST, Pair.of(baseblockposition3, baseblockposition1)); ++ enummap.put(RailShape.SOUTH_WEST, Pair.of(baseblockposition3, baseblockposition)); ++ enummap.put(RailShape.NORTH_WEST, Pair.of(baseblockposition2, baseblockposition)); ++ enummap.put(RailShape.NORTH_EAST, Pair.of(baseblockposition2, baseblockposition1)); + }); + +- protected AbstractMinecart(EntityType entitytype, Level level) { +- super(entitytype, level); ++ // CraftBukkit start ++ public boolean slowWhenEmpty = true; ++ private double derailedX = 0.5; ++ private double derailedY = 0.5; ++ private double derailedZ = 0.5; ++ private double flyingX = 0.95; ++ private double flyingY = 0.95; ++ private double flyingZ = 0.95; ++ public double maxSpeed = 0.4D; ++ // CraftBukkit end ++ ++ protected AbstractMinecart(EntityType entityType, Level level) { ++ super(entityType, level); + this.targetDeltaMovement = Vec3.ZERO; + this.blocksBuilding = true; + } + +- protected AbstractMinecart(EntityType entitytype, Level level, double d0, double d1, double d2) { +- this(entitytype, level); +- this.setPos(d0, d1, d2); +- this.xo = d0; ++ protected AbstractMinecart(EntityType entityType, Level level, double x, double d1, double y) { ++ this(entityType, level); ++ this.setPos(x, d1, y); ++ this.xo = x; + this.yo = d1; +- this.zo = d2; ++ this.zo = y; + } + +- public static AbstractMinecart createMinecart(ServerLevel serverlevel, double d0, double d1, double d2, AbstractMinecart.Type abstractminecart_type, ItemStack itemstack, @Nullable Player player) { ++ public static AbstractMinecart createMinecart(ServerLevel worldserver, double d0, double d1, double d2, AbstractMinecart.EnumMinecartType entityminecartabstract_enumminecarttype, ItemStack itemstack, @Nullable Player entityhuman) { + Object object; + +- switch (abstractminecart_type) { ++ switch (entityminecartabstract_enumminecarttype) { + case CHEST: +- object = new MinecartChest(serverlevel, d0, d1, d2); ++ object = new MinecartChest(worldserver, d0, d1, d2); + break; + case FURNACE: +- object = new MinecartFurnace(serverlevel, d0, d1, d2); ++ object = new MinecartFurnace(worldserver, d0, d1, d2); + break; + case TNT: +- object = new MinecartTNT(serverlevel, d0, d1, d2); ++ object = new MinecartTNT(worldserver, d0, d1, d2); + break; + case SPAWNER: +- object = new MinecartSpawner(serverlevel, d0, d1, d2); ++ object = new MinecartSpawner(worldserver, d0, d1, d2); + break; + case HOPPER: +- object = new MinecartHopper(serverlevel, d0, d1, d2); ++ object = new MinecartHopper(worldserver, d0, d1, d2); + break; + case COMMAND_BLOCK: +- object = new MinecartCommandBlock(serverlevel, d0, d1, d2); ++ object = new MinecartCommandBlock(worldserver, d0, d1, d2); + break; + default: +- object = new Minecart(serverlevel, d0, d1, d2); ++ object = new Minecart(worldserver, d0, d1, d2); + } + +- Object object1 = object; ++ AbstractMinecart object1 = (AbstractMinecart) object; // CraftBukkit- decompile error + +- EntityType.createDefaultStackConfig(serverlevel, itemstack, player).accept(object1); ++ EntityType.createDefaultStackConfig(worldserver, itemstack, entityhuman).accept(object1); + return (AbstractMinecart) object1; + } + + @Override +- @Override + protected Entity.MovementEmission getMovementEmission() { + return Entity.MovementEmission.EVENTS; + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(AbstractMinecart.DATA_ID_DISPLAY_BLOCK, Block.getId(Blocks.AIR.defaultBlockState())); +@@ -150,50 +167,45 @@ + } + + @Override +- @Override + public boolean canCollideWith(Entity entity) { + return Boat.canVehicleCollide(this, entity); + } + + @Override +- @Override + public boolean isPushable() { + return true; + } + + @Override +- @Override +- protected Vec3 getRelativePortalPosition(Direction.Axis direction_axis, BlockUtil.FoundRectangle blockutil_foundrectangle) { +- return LivingEntity.resetForwardDirectionOfRelativePortalPosition(super.getRelativePortalPosition(direction_axis, blockutil_foundrectangle)); ++ protected Vec3 getRelativePortalPosition(Direction.Axis axis, BlockUtil.FoundRectangle portal) { ++ return LivingEntity.resetForwardDirectionOfRelativePortalPosition(super.getRelativePortalPosition(axis, portal)); + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { + boolean flag = entity instanceof Villager || entity instanceof WanderingTrader; + + return new Vector3f(0.0F, flag ? 0.0F : 0.1875F, 0.0F); + } + + @Override +- @Override +- public Vec3 getDismountLocationForPassenger(LivingEntity livingentity) { +- Direction direction = this.getMotionDirection(); ++ public Vec3 getDismountLocationForPassenger(LivingEntity livingEntity) { ++ Direction enumdirection = this.getMotionDirection(); + +- if (direction.getAxis() == Direction.Axis.Y) { +- return super.getDismountLocationForPassenger(livingentity); ++ if (enumdirection.getAxis() == Direction.Axis.Y) { ++ return super.getDismountLocationForPassenger(livingEntity); + } else { +- int[][] aint = DismountHelper.offsetsForDirection(direction); +- BlockPos blockpos = this.blockPosition(); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); +- ImmutableList immutablelist = livingentity.getDismountPoses(); ++ int[][] aint = DismountHelper.offsetsForDirection(enumdirection); ++ BlockPos blockposition = this.blockPosition(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ ImmutableList immutablelist = livingEntity.getDismountPoses(); + UnmodifiableIterator unmodifiableiterator = immutablelist.iterator(); + + while (unmodifiableiterator.hasNext()) { +- Pose pose = (Pose) unmodifiableiterator.next(); +- EntityDimensions entitydimensions = livingentity.getDimensions(pose); +- float f = Math.min(entitydimensions.width, 1.0F) / 2.0F; +- UnmodifiableIterator unmodifiableiterator1 = ((ImmutableList) AbstractMinecart.POSE_DISMOUNT_HEIGHTS.get(pose)).iterator(); ++ EntityPose entitypose = (EntityPose) unmodifiableiterator.next(); ++ EntityDimensions entitysize = livingEntity.getDimensions(entitypose); ++ float f = Math.min(entitysize.width, 1.0F) / 2.0F; ++ UnmodifiableIterator unmodifiableiterator1 = ((ImmutableList) AbstractMinecart.POSE_DISMOUNT_HEIGHTS.get(entitypose)).iterator(); + + while (unmodifiableiterator1.hasNext()) { + int i = (Integer) unmodifiableiterator1.next(); +@@ -203,18 +215,18 @@ + for (int k = 0; k < j; ++k) { + int[] aint2 = aint1[k]; + +- blockpos_mutableblockpos.set(blockpos.getX() + aint2[0], blockpos.getY() + i, blockpos.getZ() + aint2[1]); +- double d0 = this.level().getBlockFloorHeight(DismountHelper.nonClimbableShape(this.level(), blockpos_mutableblockpos), () -> { +- return DismountHelper.nonClimbableShape(this.level(), blockpos_mutableblockpos.below()); ++ blockposition_mutableblockposition.set(blockposition.getX() + aint2[0], blockposition.getY() + i, blockposition.getZ() + aint2[1]); ++ double d0 = this.level().getBlockFloorHeight(DismountHelper.nonClimbableShape(this.level(), blockposition_mutableblockposition), () -> { ++ return DismountHelper.nonClimbableShape(this.level(), blockposition_mutableblockposition.below()); + }); + + if (DismountHelper.isBlockFloorValid(d0)) { +- AABB aabb = new AABB((double) (-f), 0.0D, (double) (-f), (double) f, (double) entitydimensions.height, (double) f); +- Vec3 vec3 = Vec3.upFromBottomCenterOf(blockpos_mutableblockpos, d0); ++ AABB axisalignedbb = new AABB((double) (-f), 0.0D, (double) (-f), (double) f, (double) entitysize.height, (double) f); ++ Vec3 vec3d = Vec3.upFromBottomCenterOf(blockposition_mutableblockposition, d0); + +- if (DismountHelper.canDismountTo(this.level(), livingentity, aabb.move(vec3))) { +- livingentity.setPose(pose); +- return vec3; ++ if (DismountHelper.canDismountTo(this.level(), livingEntity, axisalignedbb.move(vec3d))) { ++ livingEntity.setPose(entitypose); ++ return vec3d; + } + } + } +@@ -223,62 +235,65 @@ + + double d1 = this.getBoundingBox().maxY; + +- blockpos_mutableblockpos.set((double) blockpos.getX(), d1, (double) blockpos.getZ()); ++ blockposition_mutableblockposition.set((double) blockposition.getX(), d1, (double) blockposition.getZ()); + UnmodifiableIterator unmodifiableiterator2 = immutablelist.iterator(); + + while (unmodifiableiterator2.hasNext()) { +- Pose pose1 = (Pose) unmodifiableiterator2.next(); +- double d2 = (double) livingentity.getDimensions(pose1).height; +- int l = Mth.ceil(d1 - (double) blockpos_mutableblockpos.getY() + d2); +- double d3 = DismountHelper.findCeilingFrom(blockpos_mutableblockpos, l, (blockpos1) -> { +- return this.level().getBlockState(blockpos1).getCollisionShape(this.level(), blockpos1); ++ EntityPose entitypose1 = (EntityPose) unmodifiableiterator2.next(); ++ double d2 = (double) livingEntity.getDimensions(entitypose1).height; ++ int l = Mth.ceil(d1 - (double) blockposition_mutableblockposition.getY() + d2); ++ double d3 = DismountHelper.findCeilingFrom(blockposition_mutableblockposition, l, (blockposition1) -> { ++ return this.level().getBlockState(blockposition1).getCollisionShape(this.level(), blockposition1); + }); + + if (d1 + d2 <= d3) { +- livingentity.setPose(pose1); ++ livingEntity.setPose(entitypose1); + break; + } + } + +- return super.getDismountLocationForPassenger(livingentity); ++ return super.getDismountLocationForPassenger(livingEntity); + } + } + + @Override +- @Override + protected float getBlockSpeedFactor() { +- BlockState blockstate = this.level().getBlockState(this.blockPosition()); ++ IBlockData iblockdata = this.level().getBlockState(this.blockPosition()); + +- return blockstate.is(BlockTags.RAILS) ? 1.0F : super.getBlockSpeedFactor(); ++ return iblockdata.is(BlockTags.RAILS) ? 1.0F : super.getBlockSpeedFactor(); + } + + @Override +- @Override +- public void animateHurt(float f) { ++ public void animateHurt(float yaw) { + this.setHurtDir(-this.getHurtDir()); + this.setHurtTime(10); + this.setDamage(this.getDamage() + this.getDamage() * 10.0F); + } + + @Override +- @Override + public boolean isPickable() { + return !this.isRemoved(); + } + +- private static Pair exits(RailShape railshape) { +- return (Pair) AbstractMinecart.EXITS.get(railshape); ++ private static Pair exits(RailShape shape) { ++ return (Pair) AbstractMinecart.EXITS.get(shape); + } + + @Override +- @Override + public Direction getMotionDirection() { + return this.flipped ? this.getDirection().getOpposite().getClockWise() : this.getDirection().getClockWise(); + } + + @Override +- @Override + public void tick() { ++ // CraftBukkit start ++ double prevX = this.getX(); ++ double prevY = this.getY(); ++ double prevZ = this.getZ(); ++ float prevYaw = this.getYRot(); ++ float prevPitch = this.getXRot(); ++ // CraftBukkit end ++ + if (this.getHurtTime() > 0) { + this.setHurtTime(this.getHurtTime() - 1); + } +@@ -288,7 +303,7 @@ + } + + this.checkBelowWorld(); +- this.handleNetherPortal(); ++ // this.handleNetherPortal(); // CraftBukkit - handled in postTick + if (this.level().isClientSide) { + if (this.lerpSteps > 0) { + this.lerpPositionAndRotationStep(this.lerpSteps, this.lerpX, this.lerpY, this.lerpZ, this.lerpYRot, this.lerpXRot); +@@ -313,14 +328,14 @@ + --j; + } + +- BlockPos blockpos = new BlockPos(i, j, k); +- BlockState blockstate = this.level().getBlockState(blockpos); ++ BlockPos blockposition = new BlockPos(i, j, k); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); + +- this.onRails = BaseRailBlock.isRail(blockstate); ++ this.onRails = BaseRailBlock.isRail(iblockdata); + if (this.onRails) { +- this.moveAlongTrack(blockpos, blockstate); +- if (blockstate.is(Blocks.ACTIVATOR_RAIL)) { +- this.activateMinecart(i, j, k, (Boolean) blockstate.getValue(PoweredRailBlock.POWERED)); ++ this.moveAlongTrack(blockposition, iblockdata); ++ if (iblockdata.is(Blocks.ACTIVATOR_RAIL)) { ++ this.activateMinecart(i, j, k, (Boolean) iblockdata.getValue(PoweredRailBlock.POWERED)); + } + } else { + this.comeOffTrack(); +@@ -346,7 +361,19 @@ + } + + this.setRot(this.getYRot(), this.getXRot()); +- if (this.getMinecartType() == AbstractMinecart.Type.RIDEABLE && this.getDeltaMovement().horizontalDistanceSqr() > 0.01D) { ++ // CraftBukkit start ++ org.bukkit.World bworld = this.level().getWorld(); ++ Location from = new Location(bworld, prevX, prevY, prevZ, prevYaw, prevPitch); ++ Location to = CraftLocation.toBukkit(this.position(), bworld, this.getYRot(), this.getXRot()); ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ ++ this.level().getCraftServer().getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleUpdateEvent(vehicle)); ++ ++ if (!from.equals(to)) { ++ this.level().getCraftServer().getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleMoveEvent(vehicle, from, to)); ++ } ++ // CraftBukkit end ++ if (this.getMinecartType() == AbstractMinecart.EnumMinecartType.RIDEABLE && this.getDeltaMovement().horizontalDistanceSqr() > 0.01D) { + List list = this.level().getEntities((Entity) this, this.getBoundingBox().inflate(0.20000000298023224D, 0.0D, 0.20000000298023224D), EntitySelector.pushableBy(this)); + + if (!list.isEmpty()) { +@@ -356,8 +383,26 @@ + Entity entity = (Entity) iterator.next(); + + if (!(entity instanceof Player) && !(entity instanceof IronGolem) && !(entity instanceof AbstractMinecart) && !this.isVehicle() && !entity.isPassenger()) { ++ // CraftBukkit start ++ VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(collisionEvent); ++ ++ if (collisionEvent.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end + entity.startRiding(this); + } else { ++ // CraftBukkit start ++ if (!this.isPassengerOfSameVehicle(entity)) { ++ VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(collisionEvent); ++ ++ if (collisionEvent.isCancelled()) { ++ continue; ++ } ++ } ++ // CraftBukkit end + entity.push(this); + } + } +@@ -369,6 +414,14 @@ + Entity entity1 = (Entity) iterator1.next(); + + if (!this.hasPassenger(entity1) && entity1.isPushable() && entity1 instanceof AbstractMinecart) { ++ // CraftBukkit start ++ VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, entity1.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(collisionEvent); ++ ++ if (collisionEvent.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end + entity1.push(this); + } + } +@@ -385,40 +438,44 @@ + } + + protected double getMaxSpeed() { +- return (this.isInWater() ? 4.0D : 8.0D) / 20.0D; ++ return (this.isInWater() ? this.maxSpeed / 2.0D: this.maxSpeed); // CraftBukkit + } + +- public void activateMinecart(int i, int j, int k, boolean flag) {} ++ public void activateMinecart(int x, int y, int z, boolean powered) {} + + protected void comeOffTrack() { + double d0 = this.getMaxSpeed(); +- Vec3 vec3 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + +- this.setDeltaMovement(Mth.clamp(vec3.x, -d0, d0), vec3.y, Mth.clamp(vec3.z, -d0, d0)); ++ this.setDeltaMovement(Mth.clamp(vec3d.x, -d0, d0), vec3d.y, Mth.clamp(vec3d.z, -d0, d0)); + if (this.onGround()) { +- this.setDeltaMovement(this.getDeltaMovement().scale(0.5D)); ++ // CraftBukkit start - replace magic numbers with our variables ++ this.setDeltaMovement(new Vec3(this.getDeltaMovement().x * this.derailedX, this.getDeltaMovement().y * this.derailedY, this.getDeltaMovement().z * this.derailedZ)); ++ // CraftBukkit end + } + +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + if (!this.onGround()) { +- this.setDeltaMovement(this.getDeltaMovement().scale(0.95D)); ++ // CraftBukkit start - replace magic numbers with our variables ++ this.setDeltaMovement(new Vec3(this.getDeltaMovement().x * this.flyingX, this.getDeltaMovement().y * this.flyingY, this.getDeltaMovement().z * this.flyingZ)); ++ // CraftBukkit end + } + + } + +- protected void moveAlongTrack(BlockPos blockpos, BlockState blockstate) { ++ protected void moveAlongTrack(BlockPos pos, IBlockData state) { + this.resetFallDistance(); + double d0 = this.getX(); + double d1 = this.getY(); + double d2 = this.getZ(); +- Vec3 vec3 = this.getPos(d0, d1, d2); ++ Vec3 vec3d = this.getPos(d0, d1, d2); + +- d1 = (double) blockpos.getY(); ++ d1 = (double) pos.getY(); + boolean flag = false; + boolean flag1 = false; + +- if (blockstate.is(Blocks.POWERED_RAIL)) { +- flag = (Boolean) blockstate.getValue(PoweredRailBlock.POWERED); ++ if (state.is(Blocks.POWERED_RAIL)) { ++ flag = (Boolean) state.getValue(PoweredRailBlock.POWERED); + flag1 = !flag; + } + +@@ -428,54 +485,54 @@ + d3 *= 0.2D; + } + +- Vec3 vec31 = this.getDeltaMovement(); +- RailShape railshape = (RailShape) blockstate.getValue(((BaseRailBlock) blockstate.getBlock()).getShapeProperty()); ++ Vec3 vec3d1 = this.getDeltaMovement(); ++ RailShape blockpropertytrackposition = (RailShape) state.getValue(((BaseRailBlock) state.getBlock()).getShapeProperty()); + +- switch (railshape) { ++ switch (blockpropertytrackposition) { + case ASCENDING_EAST: +- this.setDeltaMovement(vec31.add(-d3, 0.0D, 0.0D)); ++ this.setDeltaMovement(vec3d1.add(-d3, 0.0D, 0.0D)); + ++d1; + break; + case ASCENDING_WEST: +- this.setDeltaMovement(vec31.add(d3, 0.0D, 0.0D)); ++ this.setDeltaMovement(vec3d1.add(d3, 0.0D, 0.0D)); + ++d1; + break; + case ASCENDING_NORTH: +- this.setDeltaMovement(vec31.add(0.0D, 0.0D, d3)); ++ this.setDeltaMovement(vec3d1.add(0.0D, 0.0D, d3)); + ++d1; + break; + case ASCENDING_SOUTH: +- this.setDeltaMovement(vec31.add(0.0D, 0.0D, -d3)); ++ this.setDeltaMovement(vec3d1.add(0.0D, 0.0D, -d3)); + ++d1; + } + +- vec31 = this.getDeltaMovement(); +- Pair pair = exits(railshape); +- Vec3i vec3i = (Vec3i) pair.getFirst(); +- Vec3i vec3i1 = (Vec3i) pair.getSecond(); +- double d4 = (double) (vec3i1.getX() - vec3i.getX()); +- double d5 = (double) (vec3i1.getZ() - vec3i.getZ()); ++ vec3d1 = this.getDeltaMovement(); ++ Pair pair = exits(blockpropertytrackposition); ++ Vec3i baseblockposition = (Vec3i) pair.getFirst(); ++ Vec3i baseblockposition1 = (Vec3i) pair.getSecond(); ++ double d4 = (double) (baseblockposition1.getX() - baseblockposition.getX()); ++ double d5 = (double) (baseblockposition1.getZ() - baseblockposition.getZ()); + double d6 = Math.sqrt(d4 * d4 + d5 * d5); +- double d7 = vec31.x * d4 + vec31.z * d5; ++ double d7 = vec3d1.x * d4 + vec3d1.z * d5; + + if (d7 < 0.0D) { + d4 = -d4; + d5 = -d5; + } + +- double d8 = Math.min(2.0D, vec31.horizontalDistance()); ++ double d8 = Math.min(2.0D, vec3d1.horizontalDistance()); + +- vec31 = new Vec3(d8 * d4 / d6, vec31.y, d8 * d5 / d6); +- this.setDeltaMovement(vec31); ++ vec3d1 = new Vec3(d8 * d4 / d6, vec3d1.y, d8 * d5 / d6); ++ this.setDeltaMovement(vec3d1); + Entity entity = this.getFirstPassenger(); + + if (entity instanceof Player) { +- Vec3 vec32 = entity.getDeltaMovement(); +- double d9 = vec32.horizontalDistanceSqr(); ++ Vec3 vec3d2 = entity.getDeltaMovement(); ++ double d9 = vec3d2.horizontalDistanceSqr(); + double d10 = this.getDeltaMovement().horizontalDistanceSqr(); + + if (d9 > 1.0E-4D && d10 < 0.01D) { +- this.setDeltaMovement(this.getDeltaMovement().add(vec32.x * 0.1D, 0.0D, vec32.z * 0.1D)); ++ this.setDeltaMovement(this.getDeltaMovement().add(vec3d2.x * 0.1D, 0.0D, vec3d2.z * 0.1D)); + flag1 = false; + } + } +@@ -491,10 +548,10 @@ + } + } + +- d11 = (double) blockpos.getX() + 0.5D + (double) vec3i.getX() * 0.5D; +- double d12 = (double) blockpos.getZ() + 0.5D + (double) vec3i.getZ() * 0.5D; +- double d13 = (double) blockpos.getX() + 0.5D + (double) vec3i1.getX() * 0.5D; +- double d14 = (double) blockpos.getZ() + 0.5D + (double) vec3i1.getZ() * 0.5D; ++ d11 = (double) pos.getX() + 0.5D + (double) baseblockposition.getX() * 0.5D; ++ double d12 = (double) pos.getZ() + 0.5D + (double) baseblockposition.getZ() * 0.5D; ++ double d13 = (double) pos.getX() + 0.5D + (double) baseblockposition1.getX() * 0.5D; ++ double d14 = (double) pos.getZ() + 0.5D + (double) baseblockposition1.getZ() * 0.5D; + + d4 = d13 - d11; + d5 = d14 - d12; +@@ -503,9 +560,9 @@ + double d17; + + if (d4 == 0.0D) { +- d15 = d2 - (double) blockpos.getZ(); ++ d15 = d2 - (double) pos.getZ(); + } else if (d5 == 0.0D) { +- d15 = d0 - (double) blockpos.getX(); ++ d15 = d0 - (double) pos.getX(); + } else { + d16 = d0 - d11; + d17 = d2 - d12; +@@ -517,230 +574,233 @@ + this.setPos(d0, d1, d2); + d16 = this.isVehicle() ? 0.75D : 1.0D; + d17 = this.getMaxSpeed(); +- vec31 = this.getDeltaMovement(); +- this.move(MoverType.SELF, new Vec3(Mth.clamp(d16 * vec31.x, -d17, d17), 0.0D, Mth.clamp(d16 * vec31.z, -d17, d17))); +- if (vec3i.getY() != 0 && Mth.floor(this.getX()) - blockpos.getX() == vec3i.getX() && Mth.floor(this.getZ()) - blockpos.getZ() == vec3i.getZ()) { +- this.setPos(this.getX(), this.getY() + (double) vec3i.getY(), this.getZ()); +- } else if (vec3i1.getY() != 0 && Mth.floor(this.getX()) - blockpos.getX() == vec3i1.getX() && Mth.floor(this.getZ()) - blockpos.getZ() == vec3i1.getZ()) { +- this.setPos(this.getX(), this.getY() + (double) vec3i1.getY(), this.getZ()); ++ vec3d1 = this.getDeltaMovement(); ++ this.move(EnumMoveType.SELF, new Vec3(Mth.clamp(d16 * vec3d1.x, -d17, d17), 0.0D, Mth.clamp(d16 * vec3d1.z, -d17, d17))); ++ if (baseblockposition.getY() != 0 && Mth.floor(this.getX()) - pos.getX() == baseblockposition.getX() && Mth.floor(this.getZ()) - pos.getZ() == baseblockposition.getZ()) { ++ this.setPos(this.getX(), this.getY() + (double) baseblockposition.getY(), this.getZ()); ++ } else if (baseblockposition1.getY() != 0 && Mth.floor(this.getX()) - pos.getX() == baseblockposition1.getX() && Mth.floor(this.getZ()) - pos.getZ() == baseblockposition1.getZ()) { ++ this.setPos(this.getX(), this.getY() + (double) baseblockposition1.getY(), this.getZ()); + } + + this.applyNaturalSlowdown(); +- Vec3 vec33 = this.getPos(this.getX(), this.getY(), this.getZ()); +- Vec3 vec34; ++ Vec3 vec3d3 = this.getPos(this.getX(), this.getY(), this.getZ()); ++ Vec3 vec3d4; + double d18; + +- if (vec33 != null && vec3 != null) { +- double d19 = (vec3.y - vec33.y) * 0.05D; ++ if (vec3d3 != null && vec3d != null) { ++ double d19 = (vec3d.y - vec3d3.y) * 0.05D; + +- vec34 = this.getDeltaMovement(); +- d18 = vec34.horizontalDistance(); ++ vec3d4 = this.getDeltaMovement(); ++ d18 = vec3d4.horizontalDistance(); + if (d18 > 0.0D) { +- this.setDeltaMovement(vec34.multiply((d18 + d19) / d18, 1.0D, (d18 + d19) / d18)); ++ this.setDeltaMovement(vec3d4.multiply((d18 + d19) / d18, 1.0D, (d18 + d19) / d18)); + } + +- this.setPos(this.getX(), vec33.y, this.getZ()); ++ this.setPos(this.getX(), vec3d3.y, this.getZ()); + } + + int i = Mth.floor(this.getX()); + int j = Mth.floor(this.getZ()); + +- if (i != blockpos.getX() || j != blockpos.getZ()) { +- vec34 = this.getDeltaMovement(); +- d18 = vec34.horizontalDistance(); +- this.setDeltaMovement(d18 * (double) (i - blockpos.getX()), vec34.y, d18 * (double) (j - blockpos.getZ())); ++ if (i != pos.getX() || j != pos.getZ()) { ++ vec3d4 = this.getDeltaMovement(); ++ d18 = vec3d4.horizontalDistance(); ++ this.setDeltaMovement(d18 * (double) (i - pos.getX()), vec3d4.y, d18 * (double) (j - pos.getZ())); + } + + if (flag) { +- vec34 = this.getDeltaMovement(); +- d18 = vec34.horizontalDistance(); ++ vec3d4 = this.getDeltaMovement(); ++ d18 = vec3d4.horizontalDistance(); + if (d18 > 0.01D) { + double d20 = 0.06D; + +- this.setDeltaMovement(vec34.add(vec34.x / d18 * 0.06D, 0.0D, vec34.z / d18 * 0.06D)); ++ this.setDeltaMovement(vec3d4.add(vec3d4.x / d18 * 0.06D, 0.0D, vec3d4.z / d18 * 0.06D)); + } else { +- Vec3 vec35 = this.getDeltaMovement(); +- double d21 = vec35.x; +- double d22 = vec35.z; ++ Vec3 vec3d5 = this.getDeltaMovement(); ++ double d21 = vec3d5.x; ++ double d22 = vec3d5.z; + +- if (railshape == RailShape.EAST_WEST) { +- if (this.isRedstoneConductor(blockpos.west())) { ++ if (blockpropertytrackposition == RailShape.EAST_WEST) { ++ if (this.isRedstoneConductor(pos.west())) { + d21 = 0.02D; +- } else if (this.isRedstoneConductor(blockpos.east())) { ++ } else if (this.isRedstoneConductor(pos.east())) { + d21 = -0.02D; + } + } else { +- if (railshape != RailShape.NORTH_SOUTH) { ++ if (blockpropertytrackposition != RailShape.NORTH_SOUTH) { + return; + } + +- if (this.isRedstoneConductor(blockpos.north())) { ++ if (this.isRedstoneConductor(pos.north())) { + d22 = 0.02D; +- } else if (this.isRedstoneConductor(blockpos.south())) { ++ } else if (this.isRedstoneConductor(pos.south())) { + d22 = -0.02D; + } + } + +- this.setDeltaMovement(d21, vec35.y, d22); ++ this.setDeltaMovement(d21, vec3d5.y, d22); + } + } + + } + + @Override +- @Override + public boolean isOnRails() { + return this.onRails; + } + +- private boolean isRedstoneConductor(BlockPos blockpos) { +- return this.level().getBlockState(blockpos).isRedstoneConductor(this.level(), blockpos); ++ private boolean isRedstoneConductor(BlockPos pos) { ++ return this.level().getBlockState(pos).isRedstoneConductor(this.level(), pos); + } + + protected void applyNaturalSlowdown() { +- double d0 = this.isVehicle() ? 0.997D : 0.96D; +- Vec3 vec3 = this.getDeltaMovement(); ++ double d0 = this.isVehicle() || !this.slowWhenEmpty ? 0.997D : 0.96D; // CraftBukkit - add !this.slowWhenEmpty ++ Vec3 vec3d = this.getDeltaMovement(); + +- vec3 = vec3.multiply(d0, 0.0D, d0); ++ vec3d = vec3d.multiply(d0, 0.0D, d0); + if (this.isInWater()) { +- vec3 = vec3.scale(0.949999988079071D); ++ vec3d = vec3d.scale(0.949999988079071D); + } + +- this.setDeltaMovement(vec3); ++ this.setDeltaMovement(vec3d); + } + + @Nullable +- public Vec3 getPosOffs(double d0, double d1, double d2, double d3) { +- int i = Mth.floor(d0); ++ public Vec3 getPosOffs(double x, double d1, double y, double d3) { ++ int i = Mth.floor(x); + int j = Mth.floor(d1); +- int k = Mth.floor(d2); ++ int k = Mth.floor(y); + + if (this.level().getBlockState(new BlockPos(i, j - 1, k)).is(BlockTags.RAILS)) { + --j; + } + +- BlockState blockstate = this.level().getBlockState(new BlockPos(i, j, k)); ++ IBlockData iblockdata = this.level().getBlockState(new BlockPos(i, j, k)); + +- if (BaseRailBlock.isRail(blockstate)) { +- RailShape railshape = (RailShape) blockstate.getValue(((BaseRailBlock) blockstate.getBlock()).getShapeProperty()); ++ if (BaseRailBlock.isRail(iblockdata)) { ++ RailShape blockpropertytrackposition = (RailShape) iblockdata.getValue(((BaseRailBlock) iblockdata.getBlock()).getShapeProperty()); + + d1 = (double) j; +- if (railshape.isAscending()) { ++ if (blockpropertytrackposition.isAscending()) { + d1 = (double) (j + 1); + } + +- Pair pair = exits(railshape); +- Vec3i vec3i = (Vec3i) pair.getFirst(); +- Vec3i vec3i1 = (Vec3i) pair.getSecond(); +- double d4 = (double) (vec3i1.getX() - vec3i.getX()); +- double d5 = (double) (vec3i1.getZ() - vec3i.getZ()); ++ Pair pair = exits(blockpropertytrackposition); ++ Vec3i baseblockposition = (Vec3i) pair.getFirst(); ++ Vec3i baseblockposition1 = (Vec3i) pair.getSecond(); ++ double d4 = (double) (baseblockposition1.getX() - baseblockposition.getX()); ++ double d5 = (double) (baseblockposition1.getZ() - baseblockposition.getZ()); + double d6 = Math.sqrt(d4 * d4 + d5 * d5); + + d4 /= d6; + d5 /= d6; +- d0 += d4 * d3; +- d2 += d5 * d3; +- if (vec3i.getY() != 0 && Mth.floor(d0) - i == vec3i.getX() && Mth.floor(d2) - k == vec3i.getZ()) { +- d1 += (double) vec3i.getY(); +- } else if (vec3i1.getY() != 0 && Mth.floor(d0) - i == vec3i1.getX() && Mth.floor(d2) - k == vec3i1.getZ()) { +- d1 += (double) vec3i1.getY(); ++ x += d4 * d3; ++ y += d5 * d3; ++ if (baseblockposition.getY() != 0 && Mth.floor(x) - i == baseblockposition.getX() && Mth.floor(y) - k == baseblockposition.getZ()) { ++ d1 += (double) baseblockposition.getY(); ++ } else if (baseblockposition1.getY() != 0 && Mth.floor(x) - i == baseblockposition1.getX() && Mth.floor(y) - k == baseblockposition1.getZ()) { ++ d1 += (double) baseblockposition1.getY(); + } + +- return this.getPos(d0, d1, d2); ++ return this.getPos(x, d1, y); + } else { + return null; + } + } + + @Nullable +- public Vec3 getPos(double d0, double d1, double d2) { +- int i = Mth.floor(d0); ++ public Vec3 getPos(double x, double d1, double y) { ++ int i = Mth.floor(x); + int j = Mth.floor(d1); +- int k = Mth.floor(d2); ++ int k = Mth.floor(y); + + if (this.level().getBlockState(new BlockPos(i, j - 1, k)).is(BlockTags.RAILS)) { + --j; + } + +- BlockState blockstate = this.level().getBlockState(new BlockPos(i, j, k)); ++ IBlockData iblockdata = this.level().getBlockState(new BlockPos(i, j, k)); + +- if (BaseRailBlock.isRail(blockstate)) { +- RailShape railshape = (RailShape) blockstate.getValue(((BaseRailBlock) blockstate.getBlock()).getShapeProperty()); +- Pair pair = exits(railshape); +- Vec3i vec3i = (Vec3i) pair.getFirst(); +- Vec3i vec3i1 = (Vec3i) pair.getSecond(); +- double d3 = (double) i + 0.5D + (double) vec3i.getX() * 0.5D; +- double d4 = (double) j + 0.0625D + (double) vec3i.getY() * 0.5D; +- double d5 = (double) k + 0.5D + (double) vec3i.getZ() * 0.5D; +- double d6 = (double) i + 0.5D + (double) vec3i1.getX() * 0.5D; +- double d7 = (double) j + 0.0625D + (double) vec3i1.getY() * 0.5D; +- double d8 = (double) k + 0.5D + (double) vec3i1.getZ() * 0.5D; ++ if (BaseRailBlock.isRail(iblockdata)) { ++ RailShape blockpropertytrackposition = (RailShape) iblockdata.getValue(((BaseRailBlock) iblockdata.getBlock()).getShapeProperty()); ++ Pair pair = exits(blockpropertytrackposition); ++ Vec3i baseblockposition = (Vec3i) pair.getFirst(); ++ Vec3i baseblockposition1 = (Vec3i) pair.getSecond(); ++ double d3 = (double) i + 0.5D + (double) baseblockposition.getX() * 0.5D; ++ double d4 = (double) j + 0.0625D + (double) baseblockposition.getY() * 0.5D; ++ double d5 = (double) k + 0.5D + (double) baseblockposition.getZ() * 0.5D; ++ double d6 = (double) i + 0.5D + (double) baseblockposition1.getX() * 0.5D; ++ double d7 = (double) j + 0.0625D + (double) baseblockposition1.getY() * 0.5D; ++ double d8 = (double) k + 0.5D + (double) baseblockposition1.getZ() * 0.5D; + double d9 = d6 - d3; + double d10 = (d7 - d4) * 2.0D; + double d11 = d8 - d5; + double d12; + + if (d9 == 0.0D) { +- d12 = d2 - (double) k; ++ d12 = y - (double) k; + } else if (d11 == 0.0D) { +- d12 = d0 - (double) i; ++ d12 = x - (double) i; + } else { +- double d13 = d0 - d3; +- double d14 = d2 - d5; ++ double d13 = x - d3; ++ double d14 = y - d5; + + d12 = (d13 * d9 + d14 * d11) * 2.0D; + } + +- d0 = d3 + d9 * d12; ++ x = d3 + d9 * d12; + d1 = d4 + d10 * d12; +- d2 = d5 + d11 * d12; ++ y = d5 + d11 * d12; + if (d10 < 0.0D) { + ++d1; + } else if (d10 > 0.0D) { + d1 += 0.5D; + } + +- return new Vec3(d0, d1, d2); ++ return new Vec3(x, d1, y); + } else { + return null; + } + } + + @Override +- @Override + public AABB getBoundingBoxForCulling() { +- AABB aabb = this.getBoundingBox(); ++ AABB axisalignedbb = this.getBoundingBox(); + +- return this.hasCustomDisplay() ? aabb.inflate((double) Math.abs(this.getDisplayOffset()) / 16.0D) : aabb; ++ return this.hasCustomDisplay() ? axisalignedbb.inflate((double) Math.abs(this.getDisplayOffset()) / 16.0D) : axisalignedbb; + } + + @Override +- @Override +- protected void readAdditionalSaveData(CompoundTag compoundtag) { +- if (compoundtag.getBoolean("CustomDisplayTile")) { +- this.setDisplayBlockState(NbtUtils.readBlockState(this.level().holderLookup(Registries.BLOCK), compoundtag.getCompound("DisplayState"))); +- this.setDisplayOffset(compoundtag.getInt("DisplayOffset")); ++ protected void readAdditionalSaveData(CompoundTag compound) { ++ if (compound.getBoolean("CustomDisplayTile")) { ++ this.setDisplayBlockState(NbtUtils.readBlockState(this.level().holderLookup(Registries.BLOCK), compound.getCompound("DisplayState"))); ++ this.setDisplayOffset(compound.getInt("DisplayOffset")); + } + + } + + @Override +- @Override +- protected void addAdditionalSaveData(CompoundTag compoundtag) { ++ protected void addAdditionalSaveData(CompoundTag compound) { + if (this.hasCustomDisplay()) { +- compoundtag.putBoolean("CustomDisplayTile", true); +- compoundtag.put("DisplayState", NbtUtils.writeBlockState(this.getDisplayBlockState())); +- compoundtag.putInt("DisplayOffset", this.getDisplayOffset()); ++ compound.putBoolean("CustomDisplayTile", true); ++ compound.put("DisplayState", NbtUtils.writeBlockState(this.getDisplayBlockState())); ++ compound.putInt("DisplayOffset", this.getDisplayOffset()); + } + + } + + @Override +- @Override + public void push(Entity entity) { + if (!this.level().isClientSide) { + if (!entity.noPhysics && !this.noPhysics) { + if (!this.hasPassenger(entity)) { ++ // CraftBukkit start ++ VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(collisionEvent); ++ ++ if (collisionEvent.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + double d0 = entity.getX() - this.getX(); + double d1 = entity.getZ() - this.getZ(); + double d2 = d0 * d0 + d1 * d1; +@@ -764,32 +824,32 @@ + if (entity instanceof AbstractMinecart) { + double d4 = entity.getX() - this.getX(); + double d5 = entity.getZ() - this.getZ(); +- Vec3 vec3 = (new Vec3(d4, 0.0D, d5)).normalize(); +- Vec3 vec31 = (new Vec3((double) Mth.cos(this.getYRot() * 0.017453292F), 0.0D, (double) Mth.sin(this.getYRot() * 0.017453292F))).normalize(); +- double d6 = Math.abs(vec3.dot(vec31)); ++ Vec3 vec3d = (new Vec3(d4, 0.0D, d5)).normalize(); ++ Vec3 vec3d1 = (new Vec3((double) Mth.cos(this.getYRot() * 0.017453292F), 0.0D, (double) Mth.sin(this.getYRot() * 0.017453292F))).normalize(); ++ double d6 = Math.abs(vec3d.dot(vec3d1)); + + if (d6 < 0.800000011920929D) { + return; + } + +- Vec3 vec32 = this.getDeltaMovement(); +- Vec3 vec33 = entity.getDeltaMovement(); ++ Vec3 vec3d2 = this.getDeltaMovement(); ++ Vec3 vec3d3 = entity.getDeltaMovement(); + +- if (((AbstractMinecart) entity).getMinecartType() == AbstractMinecart.Type.FURNACE && this.getMinecartType() != AbstractMinecart.Type.FURNACE) { +- this.setDeltaMovement(vec32.multiply(0.2D, 1.0D, 0.2D)); +- this.push(vec33.x - d0, 0.0D, vec33.z - d1); +- entity.setDeltaMovement(vec33.multiply(0.95D, 1.0D, 0.95D)); +- } else if (((AbstractMinecart) entity).getMinecartType() != AbstractMinecart.Type.FURNACE && this.getMinecartType() == AbstractMinecart.Type.FURNACE) { +- entity.setDeltaMovement(vec33.multiply(0.2D, 1.0D, 0.2D)); +- entity.push(vec32.x + d0, 0.0D, vec32.z + d1); +- this.setDeltaMovement(vec32.multiply(0.95D, 1.0D, 0.95D)); ++ if (((AbstractMinecart) entity).getMinecartType() == AbstractMinecart.EnumMinecartType.FURNACE && this.getMinecartType() != AbstractMinecart.EnumMinecartType.FURNACE) { ++ this.setDeltaMovement(vec3d2.multiply(0.2D, 1.0D, 0.2D)); ++ this.push(vec3d3.x - d0, 0.0D, vec3d3.z - d1); ++ entity.setDeltaMovement(vec3d3.multiply(0.95D, 1.0D, 0.95D)); ++ } else if (((AbstractMinecart) entity).getMinecartType() != AbstractMinecart.EnumMinecartType.FURNACE && this.getMinecartType() == AbstractMinecart.EnumMinecartType.FURNACE) { ++ entity.setDeltaMovement(vec3d3.multiply(0.2D, 1.0D, 0.2D)); ++ entity.push(vec3d2.x + d0, 0.0D, vec3d2.z + d1); ++ this.setDeltaMovement(vec3d2.multiply(0.95D, 1.0D, 0.95D)); + } else { +- double d7 = (vec33.x + vec32.x) / 2.0D; +- double d8 = (vec33.z + vec32.z) / 2.0D; ++ double d7 = (vec3d3.x + vec3d2.x) / 2.0D; ++ double d8 = (vec3d3.z + vec3d2.z) / 2.0D; + +- this.setDeltaMovement(vec32.multiply(0.2D, 1.0D, 0.2D)); ++ this.setDeltaMovement(vec3d2.multiply(0.2D, 1.0D, 0.2D)); + this.push(d7 - d0, 0.0D, d8 - d1); +- entity.setDeltaMovement(vec33.multiply(0.2D, 1.0D, 0.2D)); ++ entity.setDeltaMovement(vec3d3.multiply(0.2D, 1.0D, 0.2D)); + entity.push(d7 + d0, 0.0D, d8 + d1); + } + } else { +@@ -804,7 +864,6 @@ + } + + @Override +- @Override + public void lerpTo(double d0, double d1, double d2, float f, float f1, int i) { + this.lerpX = d0; + this.lerpY = d1; +@@ -816,49 +875,43 @@ + } + + @Override +- @Override + public double lerpTargetX() { + return this.lerpSteps > 0 ? this.lerpX : this.getX(); + } + + @Override +- @Override + public double lerpTargetY() { + return this.lerpSteps > 0 ? this.lerpY : this.getY(); + } + + @Override +- @Override + public double lerpTargetZ() { + return this.lerpSteps > 0 ? this.lerpZ : this.getZ(); + } + + @Override +- @Override + public float lerpTargetXRot() { + return this.lerpSteps > 0 ? (float) this.lerpXRot : this.getXRot(); + } + + @Override +- @Override + public float lerpTargetYRot() { + return this.lerpSteps > 0 ? (float) this.lerpYRot : this.getYRot(); + } + + @Override +- @Override +- public void lerpMotion(double d0, double d1, double d2) { +- this.targetDeltaMovement = new Vec3(d0, d1, d2); ++ public void lerpMotion(double x, double d1, double y) { ++ this.targetDeltaMovement = new Vec3(x, d1, y); + this.setDeltaMovement(this.targetDeltaMovement); + } + +- public abstract AbstractMinecart.Type getMinecartType(); ++ public abstract AbstractMinecart.EnumMinecartType getMinecartType(); + +- public BlockState getDisplayBlockState() { ++ public IBlockData getDisplayBlockState() { + return !this.hasCustomDisplay() ? this.getDefaultDisplayBlockState() : Block.stateById((Integer) this.getEntityData().get(AbstractMinecart.DATA_ID_DISPLAY_BLOCK)); + } + +- public BlockState getDefaultDisplayBlockState() { ++ public IBlockData getDefaultDisplayBlockState() { + return Blocks.AIR.defaultBlockState(); + } + +@@ -870,13 +923,13 @@ + return 6; + } + +- public void setDisplayBlockState(BlockState blockstate) { +- this.getEntityData().set(AbstractMinecart.DATA_ID_DISPLAY_BLOCK, Block.getId(blockstate)); ++ public void setDisplayBlockState(IBlockData displayState) { ++ this.getEntityData().set(AbstractMinecart.DATA_ID_DISPLAY_BLOCK, Block.getId(displayState)); + this.setCustomDisplay(true); + } + +- public void setDisplayOffset(int i) { +- this.getEntityData().set(AbstractMinecart.DATA_ID_DISPLAY_OFFSET, i); ++ public void setDisplayOffset(int displayOffset) { ++ this.getEntityData().set(AbstractMinecart.DATA_ID_DISPLAY_OFFSET, displayOffset); + this.setCustomDisplay(true); + } + +@@ -884,12 +937,11 @@ + return (Boolean) this.getEntityData().get(AbstractMinecart.DATA_ID_CUSTOM_DISPLAY); + } + +- public void setCustomDisplay(boolean flag) { +- this.getEntityData().set(AbstractMinecart.DATA_ID_CUSTOM_DISPLAY, flag); ++ public void setCustomDisplay(boolean customDisplay) { ++ this.getEntityData().set(AbstractMinecart.DATA_ID_CUSTOM_DISPLAY, customDisplay); + } + + @Override +- @Override + public ItemStack getPickResult() { + Item item; + +@@ -917,10 +969,32 @@ + return new ItemStack(item); + } + +- public static enum Type { ++ public static enum EnumMinecartType { + + RIDEABLE, CHEST, FURNACE, TNT, SPAWNER, HOPPER, COMMAND_BLOCK; + +- private Type() {} ++ private EnumMinecartType() {} + } ++ ++ // CraftBukkit start - Methods for getting and setting flying and derailed velocity modifiers ++ public Vector getFlyingVelocityMod() { ++ return new Vector(flyingX, flyingY, flyingZ); ++ } ++ ++ public void setFlyingVelocityMod(Vector flying) { ++ flyingX = flying.getX(); ++ flyingY = flying.getY(); ++ flyingZ = flying.getZ(); ++ } ++ ++ public Vector getDerailedVelocityMod() { ++ return new Vector(derailedX, derailedY, derailedZ); ++ } ++ ++ public void setDerailedVelocityMod(Vector derailed) { ++ derailedX = derailed.getX(); ++ derailedY = derailed.getY(); ++ derailedZ = derailed.getZ(); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java.patch new file mode 100644 index 0000000000..767c1d31d6 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java.patch @@ -0,0 +1,266 @@ +--- a/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java ++++ b/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java +@@ -6,7 +6,7 @@ + import net.minecraft.resources.ResourceLocation; + import net.minecraft.world.Container; + import net.minecraft.world.Containers; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; +@@ -17,103 +17,138 @@ + import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end + + public abstract class AbstractMinecartContainer extends AbstractMinecart implements ContainerEntity { + + private NonNullList itemStacks; + @Nullable +- private ResourceLocation lootTable; +- private long lootTableSeed; ++ public ResourceLocation lootTable; ++ public long lootTableSeed; + +- protected AbstractMinecartContainer(EntityType entitytype, Level level) { +- super(entitytype, level); +- this.itemStacks = NonNullList.withSize(36, ItemStack.EMPTY); ++ // CraftBukkit start ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.itemStacks; + } + +- protected AbstractMinecartContainer(EntityType entitytype, double d0, double d1, double d2, Level level) { +- super(entitytype, level, d0, d1, d2); +- this.itemStacks = NonNullList.withSize(36, ItemStack.EMPTY); ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); + } + ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public InventoryHolder getOwner() { ++ org.bukkit.entity.Entity cart = getBukkitEntity(); ++ if(cart instanceof InventoryHolder) return (InventoryHolder) cart; ++ return null; ++ } ++ + @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ + @Override +- public void destroy(DamageSource damagesource) { +- super.destroy(damagesource); +- this.chestVehicleDestroyed(damagesource, this.level(), this); ++ public Location getLocation() { ++ return getBukkitEntity().getLocation(); + } ++ // CraftBukkit end + ++ protected AbstractMinecartContainer(EntityType entityType, Level level) { ++ super(entityType, level); ++ this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); // CraftBukkit - SPIGOT-3513 ++ } ++ ++ protected AbstractMinecartContainer(EntityType entityType, double x, double d1, double y, Level world) { ++ super(entityType, world, x, d1, y); ++ this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); // CraftBukkit - SPIGOT-3513 ++ } ++ + @Override ++ public void destroy(DamageSource source) { ++ super.destroy(source); ++ this.chestVehicleDestroyed(source, this.level(), this); ++ } ++ + @Override +- public ItemStack getItem(int i) { +- return this.getChestVehicleItem(i); ++ public ItemStack getItem(int index) { ++ return this.getChestVehicleItem(index); + } + + @Override +- @Override +- public ItemStack removeItem(int i, int j) { +- return this.removeChestVehicleItem(i, j); ++ public ItemStack removeItem(int index, int count) { ++ return this.removeChestVehicleItem(index, count); + } + + @Override +- @Override +- public ItemStack removeItemNoUpdate(int i) { +- return this.removeChestVehicleItemNoUpdate(i); ++ public ItemStack removeItemNoUpdate(int index) { ++ return this.removeChestVehicleItemNoUpdate(index); + } + + @Override +- @Override +- public void setItem(int i, ItemStack itemstack) { +- this.setChestVehicleItem(i, itemstack); ++ public void setItem(int index, ItemStack stack) { ++ this.setChestVehicleItem(index, stack); + } + + @Override +- @Override +- public SlotAccess getSlot(int i) { +- return this.getChestVehicleSlot(i); ++ public SlotAccess getSlot(int slot) { ++ return this.getChestVehicleSlot(slot); + } + + @Override +- @Override + public void setChanged() {} + + @Override +- @Override + public boolean stillValid(Player player) { + return this.isChestVehicleStillValid(player); + } + + @Override +- @Override +- public void remove(Entity.RemovalReason entity_removalreason) { +- if (!this.level().isClientSide && entity_removalreason.shouldDestroy()) { ++ public void remove(Entity.RemovalReason reason) { ++ if (!this.level().isClientSide && reason.shouldDestroy()) { + Containers.dropContents(this.level(), (Entity) this, (Container) this); + } + +- super.remove(entity_removalreason); ++ super.remove(reason); + } + + @Override +- @Override +- protected void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- this.addChestVehicleSaveData(compoundtag); ++ protected void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ this.addChestVehicleSaveData(compound); + } + + @Override +- @Override +- protected void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.readChestVehicleSaveData(compoundtag); ++ protected void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.readChestVehicleSaveData(compound); + } + + @Override +- @Override +- public InteractionResult interact(Player player, InteractionHand interactionhand) { ++ public InteractionResult interact(Player player, EnumHand hand) { + return this.interactWithContainerVehicle(player); + } + + @Override +- @Override + protected void applyNaturalSlowdown() { + float f = 0.98F; + +@@ -131,25 +166,23 @@ + } + + @Override +- @Override + public void clearContent() { + this.clearChestVehicleContent(); + } + +- public void setLootTable(ResourceLocation resourcelocation, long i) { +- this.lootTable = resourcelocation; +- this.lootTableSeed = i; ++ public void setLootTable(ResourceLocation lootTable, long lootTableSeed) { ++ this.lootTable = lootTable; ++ this.lootTableSeed = lootTableSeed; + } + + @Nullable + @Override +- @Override +- public AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) { ++ public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { + if (this.lootTable != null && player.isSpectator()) { + return null; + } else { +- this.unpackChestVehicleLootTable(inventory.player); +- return this.createMenu(i, inventory); ++ this.unpackChestVehicleLootTable(playerInventory.player); ++ return this.createMenu(containerId, playerInventory); + } + } + +@@ -157,37 +190,31 @@ + + @Nullable + @Override +- @Override + public ResourceLocation getLootTable() { + return this.lootTable; + } + + @Override +- @Override +- public void setLootTable(@Nullable ResourceLocation resourcelocation) { +- this.lootTable = resourcelocation; ++ public void setLootTable(@Nullable ResourceLocation lootTable) { ++ this.lootTable = lootTable; + } + + @Override +- @Override + public long getLootTableSeed() { + return this.lootTableSeed; + } + + @Override +- @Override +- public void setLootTableSeed(long i) { +- this.lootTableSeed = i; ++ public void setLootTableSeed(long lootTableSeed) { ++ this.lootTableSeed = lootTableSeed; + } + + @Override +- @Override + public NonNullList getItemStacks() { + return this.itemStacks; + } + + @Override +- @Override + public void clearItemStacks() { + this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/Boat.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/Boat.java.patch new file mode 100644 index 0000000000..c5eee0a7aa --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/Boat.java.patch @@ -0,0 +1,974 @@ +--- a/net/minecraft/world/entity/vehicle/Boat.java ++++ b/net/minecraft/world/entity/vehicle/Boat.java +@@ -23,15 +23,15 @@ + import net.minecraft.util.ByIdMap; + import net.minecraft.util.Mth; + import net.minecraft.util.StringRepresentable; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.VariantHolder; + import net.minecraft.world.entity.animal.Animal; + import net.minecraft.world.entity.animal.WaterAnimal; +@@ -40,12 +40,12 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.GameRules; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.WaterlilyBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.phys.AABB; +@@ -55,6 +55,15 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.Vehicle; ++import org.bukkit.event.vehicle.VehicleDestroyEvent; ++import org.bukkit.event.vehicle.VehicleEntityCollisionEvent; ++import org.bukkit.event.vehicle.VehicleMoveEvent; ++// CraftBukkit end ++ + public class Boat extends VehicleEntity implements VariantHolder { + + private static final EntityDataAccessor DATA_ID_TYPE = SynchedEntityData.defineId(Boat.class, EntityDataSerializers.INT); +@@ -83,8 +92,8 @@ + private boolean inputDown; + private double waterLevel; + private float landFriction; +- private Boat.Status status; +- private Boat.Status oldStatus; ++ public Boat.EnumStatus status; ++ private Boat.EnumStatus oldStatus; + private double lastYd; + private boolean isAboveBubbleColumn; + private boolean bubbleColumnDirectionIsDown; +@@ -92,34 +101,39 @@ + private float bubbleAngle; + private float bubbleAngleO; + +- public Boat(EntityType entitytype, Level level) { +- super(entitytype, level); ++ // CraftBukkit start ++ // PAIL: Some of these haven't worked since a few updates, and since 1.9 they are less and less applicable. ++ public double maxSpeed = 0.4D; ++ public double occupiedDeceleration = 0.2D; ++ public double unoccupiedDeceleration = -1; ++ public boolean landBoats = false; ++ // CraftBukkit end ++ ++ public Boat(EntityType entityType, Level level) { ++ super(entityType, level); + this.paddlePositions = new float[2]; + this.blocksBuilding = true; + } + +- public Boat(Level level, double d0, double d1, double d2) { ++ public Boat(Level level, double x, double d1, double y) { + this(EntityType.BOAT, level); +- this.setPos(d0, d1, d2); +- this.xo = d0; ++ this.setPos(x, d1, y); ++ this.xo = x; + this.yo = d1; +- this.zo = d2; ++ this.zo = y; + } + + @Override +- @Override +- protected float getEyeHeight(Pose pose, EntityDimensions entitydimensions) { +- return entitydimensions.height; ++ protected float getEyeHeight(EntityPose pose, EntityDimensions size) { ++ return size.height; + } + + @Override +- @Override + protected Entity.MovementEmission getMovementEmission() { + return Entity.MovementEmission.EVENTS; + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(Boat.DATA_ID_TYPE, Boat.Type.OAK.ordinal()); +@@ -129,36 +143,31 @@ + } + + @Override +- @Override + public boolean canCollideWith(Entity entity) { + return canVehicleCollide(this, entity); + } + +- public static boolean canVehicleCollide(Entity entity, Entity entity1) { +- return (entity1.canBeCollidedWith() || entity1.isPushable()) && !entity.isPassengerOfSameVehicle(entity1); ++ public static boolean canVehicleCollide(Entity vehicle, Entity entity) { ++ return (entity.canBeCollidedWith() || entity.isPushable()) && !vehicle.isPassengerOfSameVehicle(entity); + } + + @Override +- @Override + public boolean canBeCollidedWith() { + return true; + } + + @Override +- @Override + public boolean isPushable() { + return true; + } + + @Override +- @Override +- protected Vec3 getRelativePortalPosition(Direction.Axis direction_axis, BlockUtil.FoundRectangle blockutil_foundrectangle) { +- return LivingEntity.resetForwardDirectionOfRelativePortalPosition(super.getRelativePortalPosition(direction_axis, blockutil_foundrectangle)); ++ protected Vec3 getRelativePortalPosition(Direction.Axis axis, BlockUtil.FoundRectangle portal) { ++ return LivingEntity.resetForwardDirectionOfRelativePortalPosition(super.getRelativePortalPosition(axis, portal)); + } + + @Override +- @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitydimensions, float f) { ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { + float f1 = this.getSinglePassengerXOffset(); + + if (this.getPassengers().size() > 1) { +@@ -175,15 +184,14 @@ + } + } + +- return new Vector3f(0.0F, this.getVariant() == Boat.Type.BAMBOO ? entitydimensions.height * 0.8888889F : entitydimensions.height / 3.0F, f1); ++ return new Vector3f(0.0F, this.getVariant() == Boat.Type.BAMBOO ? entitysize.height * 0.8888889F : entitysize.height / 3.0F, f1); + } + + @Override +- @Override +- public void onAboveBubbleCol(boolean flag) { ++ public void onAboveBubbleCol(boolean downwards) { + if (!this.level().isClientSide) { + this.isAboveBubbleColumn = true; +- this.bubbleColumnDirectionIsDown = flag; ++ this.bubbleColumnDirectionIsDown = downwards; + if (this.getBubbleTime() == 0) { + this.setBubbleTime(60); + } +@@ -198,20 +206,38 @@ + } + + @Override +- @Override + public void push(Entity entity) { + if (entity instanceof Boat) { + if (entity.getBoundingBox().minY < this.getBoundingBox().maxY) { ++ // CraftBukkit start ++ if (!this.isPassengerOfSameVehicle(entity)) { ++ VehicleEntityCollisionEvent event = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + super.push(entity); + } + } else if (entity.getBoundingBox().minY <= this.getBoundingBox().minY) { ++ // CraftBukkit start ++ if (!this.isPassengerOfSameVehicle(entity)) { ++ VehicleEntityCollisionEvent event = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + super.push(entity); + } + + } + + @Override +- @Override + public Item getDropItem() { + Item item; + +@@ -248,21 +274,18 @@ + } + + @Override +- @Override +- public void animateHurt(float f) { ++ public void animateHurt(float yaw) { + this.setHurtDir(-this.getHurtDir()); + this.setHurtTime(10); + this.setDamage(this.getDamage() * 11.0F); + } + + @Override +- @Override + public boolean isPickable() { + return !this.isRemoved(); + } + + @Override +- @Override + public void lerpTo(double d0, double d1, double d2, float f, float f1, int i) { + this.lerpX = d0; + this.lerpY = d1; +@@ -273,47 +296,41 @@ + } + + @Override +- @Override + public double lerpTargetX() { + return this.lerpSteps > 0 ? this.lerpX : this.getX(); + } + + @Override +- @Override + public double lerpTargetY() { + return this.lerpSteps > 0 ? this.lerpY : this.getY(); + } + + @Override +- @Override + public double lerpTargetZ() { + return this.lerpSteps > 0 ? this.lerpZ : this.getZ(); + } + + @Override +- @Override + public float lerpTargetXRot() { + return this.lerpSteps > 0 ? (float) this.lerpXRot : this.getXRot(); + } + + @Override +- @Override + public float lerpTargetYRot() { + return this.lerpSteps > 0 ? (float) this.lerpYRot : this.getYRot(); + } + + @Override +- @Override + public Direction getMotionDirection() { + return this.getDirection().getClockWise(); + } + ++ private Location lastLocation; // CraftBukkit + @Override +- @Override + public void tick() { + this.oldStatus = this.status; + this.status = this.getStatus(); +- if (this.status != Boat.Status.UNDER_WATER && this.status != Boat.Status.UNDER_FLOWING_WATER) { ++ if (this.status != Boat.EnumStatus.UNDER_WATER && this.status != Boat.EnumStatus.UNDER_FLOWING_WATER) { + this.outOfControlTicks = 0.0F; + } else { + ++this.outOfControlTicks; +@@ -344,24 +361,40 @@ + this.level().sendPacketToServer(new ServerboundPaddleBoatPacket(this.getPaddleState(0), this.getPaddleState(1))); + } + +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + } else { + this.setDeltaMovement(Vec3.ZERO); + } + ++ // CraftBukkit start ++ org.bukkit.Server server = this.level().getCraftServer(); ++ org.bukkit.World bworld = this.level().getWorld(); ++ ++ Location to = CraftLocation.toBukkit(this.position(), bworld, this.getYRot(), this.getXRot()); ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ ++ server.getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleUpdateEvent(vehicle)); ++ ++ if (lastLocation != null && !lastLocation.equals(to)) { ++ VehicleMoveEvent event = new VehicleMoveEvent(vehicle, lastLocation, to); ++ server.getPluginManager().callEvent(event); ++ } ++ lastLocation = vehicle.getLocation(); ++ // CraftBukkit end ++ + this.tickBubbleColumn(); + + for (int i = 0; i <= 1; ++i) { + if (this.getPaddleState(i)) { + if (!this.isSilent() && (double) (this.paddlePositions[i] % 6.2831855F) <= 0.7853981852531433D && (double) ((this.paddlePositions[i] + 0.3926991F) % 6.2831855F) >= 0.7853981852531433D) { +- SoundEvent soundevent = this.getPaddleSound(); ++ SoundEvent soundeffect = this.getPaddleSound(); + +- if (soundevent != null) { +- Vec3 vec3 = this.getViewVector(1.0F); +- double d0 = i == 1 ? -vec3.z : vec3.z; +- double d1 = i == 1 ? vec3.x : -vec3.x; ++ if (soundeffect != null) { ++ Vec3 vec3d = this.getViewVector(1.0F); ++ double d0 = i == 1 ? -vec3d.z : vec3d.z; ++ double d1 = i == 1 ? vec3d.x : -vec3d.x; + +- this.level().playSound((Player) null, this.getX() + d0, this.getY(), this.getZ() + d1, soundevent, this.getSoundSource(), 1.0F, 0.8F + 0.4F * this.random.nextFloat()); ++ this.level().playSound((Player) null, this.getX() + d0, this.getY(), this.getZ() + d1, soundeffect, this.getSoundSource(), 1.0F, 0.8F + 0.4F * this.random.nextFloat()); + } + } + +@@ -420,15 +453,15 @@ + + if (j > 0 && i == 0) { + this.setBubbleTime(0); +- Vec3 vec3 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + + if (this.bubbleColumnDirectionIsDown) { +- this.setDeltaMovement(vec3.add(0.0D, -0.7D, 0.0D)); ++ this.setDeltaMovement(vec3d.add(0.0D, -0.7D, 0.0D)); + this.ejectPassengers(); + } else { +- this.setDeltaMovement(vec3.x, this.hasPassenger((entity) -> { ++ this.setDeltaMovement(vec3d.x, this.hasPassenger((entity) -> { + return entity instanceof Player; +- }) ? 2.7D : 0.6D, vec3.z); ++ }) ? 2.7D : 0.6D, vec3d.z); + } + } + +@@ -465,44 +498,44 @@ + } + } + +- public void setPaddleState(boolean flag, boolean flag1) { +- this.entityData.set(Boat.DATA_ID_PADDLE_LEFT, flag); +- this.entityData.set(Boat.DATA_ID_PADDLE_RIGHT, flag1); ++ public void setPaddleState(boolean left, boolean right) { ++ this.entityData.set(Boat.DATA_ID_PADDLE_LEFT, left); ++ this.entityData.set(Boat.DATA_ID_PADDLE_RIGHT, right); + } + +- public float getRowingTime(int i, float f) { +- return this.getPaddleState(i) ? Mth.clampedLerp(this.paddlePositions[i] - 0.3926991F, this.paddlePositions[i], f) : 0.0F; ++ public float getRowingTime(int side, float limbSwing) { ++ return this.getPaddleState(side) ? Mth.clampedLerp(this.paddlePositions[side] - 0.3926991F, this.paddlePositions[side], limbSwing) : 0.0F; + } + +- private Boat.Status getStatus() { +- Boat.Status boat_status = this.isUnderwater(); ++ private Boat.EnumStatus getStatus() { ++ Boat.EnumStatus entityboat_enumstatus = this.isUnderwater(); + +- if (boat_status != null) { ++ if (entityboat_enumstatus != null) { + this.waterLevel = this.getBoundingBox().maxY; +- return boat_status; ++ return entityboat_enumstatus; + } else if (this.checkInWater()) { +- return Boat.Status.IN_WATER; ++ return Boat.EnumStatus.IN_WATER; + } else { + float f = this.getGroundFriction(); + + if (f > 0.0F) { + this.landFriction = f; +- return Boat.Status.ON_LAND; ++ return Boat.EnumStatus.ON_LAND; + } else { +- return Boat.Status.IN_AIR; ++ return Boat.EnumStatus.IN_AIR; + } + } + } + + public float getWaterLevelAbove() { +- AABB aabb = this.getBoundingBox(); +- int i = Mth.floor(aabb.minX); +- int j = Mth.ceil(aabb.maxX); +- int k = Mth.floor(aabb.maxY); +- int l = Mth.ceil(aabb.maxY - this.lastYd); +- int i1 = Mth.floor(aabb.minZ); +- int j1 = Mth.ceil(aabb.maxZ); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ AABB axisalignedbb = this.getBoundingBox(); ++ int i = Mth.floor(axisalignedbb.minX); ++ int j = Mth.ceil(axisalignedbb.maxX); ++ int k = Mth.floor(axisalignedbb.maxY); ++ int l = Mth.ceil(axisalignedbb.maxY - this.lastYd); ++ int i1 = Mth.floor(axisalignedbb.minZ); ++ int j1 = Mth.ceil(axisalignedbb.maxZ); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + int k1 = k; + + while (k1 < l) { +@@ -520,11 +553,11 @@ + continue label35; + } + +- blockpos_mutableblockpos.set(l1, k1, i2); +- FluidState fluidstate = this.level().getFluidState(blockpos_mutableblockpos); ++ blockposition_mutableblockposition.set(l1, k1, i2); ++ FluidState fluid = this.level().getFluidState(blockposition_mutableblockposition); + +- if (fluidstate.is(FluidTags.WATER)) { +- f = Math.max(f, fluidstate.getHeight(this.level(), blockpos_mutableblockpos)); ++ if (fluid.is(FluidTags.WATER)) { ++ f = Math.max(f, fluid.getHeight(this.level(), blockposition_mutableblockposition)); + } + + if (f >= 1.0F) { +@@ -534,7 +567,7 @@ + ++i2; + } + } else if (f < 1.0F) { +- return (float) blockpos_mutableblockpos.getY() + f; ++ return (float) blockposition_mutableblockposition.getY() + f; + } + + ++k1; +@@ -546,18 +579,18 @@ + } + + public float getGroundFriction() { +- AABB aabb = this.getBoundingBox(); +- AABB aabb1 = new AABB(aabb.minX, aabb.minY - 0.001D, aabb.minZ, aabb.maxX, aabb.minY, aabb.maxZ); +- int i = Mth.floor(aabb1.minX) - 1; +- int j = Mth.ceil(aabb1.maxX) + 1; +- int k = Mth.floor(aabb1.minY) - 1; +- int l = Mth.ceil(aabb1.maxY) + 1; +- int i1 = Mth.floor(aabb1.minZ) - 1; +- int j1 = Mth.ceil(aabb1.maxZ) + 1; +- VoxelShape voxelshape = Shapes.create(aabb1); ++ AABB axisalignedbb = this.getBoundingBox(); ++ AABB axisalignedbb1 = new AABB(axisalignedbb.minX, axisalignedbb.minY - 0.001D, axisalignedbb.minZ, axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.maxZ); ++ int i = Mth.floor(axisalignedbb1.minX) - 1; ++ int j = Mth.ceil(axisalignedbb1.maxX) + 1; ++ int k = Mth.floor(axisalignedbb1.minY) - 1; ++ int l = Mth.ceil(axisalignedbb1.maxY) + 1; ++ int i1 = Mth.floor(axisalignedbb1.minZ) - 1; ++ int j1 = Mth.ceil(axisalignedbb1.maxZ) + 1; ++ VoxelShape voxelshape = Shapes.create(axisalignedbb1); + float f = 0.0F; + int k1 = 0; +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + + for (int l1 = i; l1 < j; ++l1) { + for (int i2 = i1; i2 < j1; ++i2) { +@@ -566,11 +599,11 @@ + if (j2 != 2) { + for (int k2 = k; k2 < l; ++k2) { + if (j2 <= 0 || k2 != k && k2 != l - 1) { +- blockpos_mutableblockpos.set(l1, k2, i2); +- BlockState blockstate = this.level().getBlockState(blockpos_mutableblockpos); ++ blockposition_mutableblockposition.set(l1, k2, i2); ++ IBlockData iblockdata = this.level().getBlockState(blockposition_mutableblockposition); + +- if (!(blockstate.getBlock() instanceof WaterlilyBlock) && Shapes.joinIsNotEmpty(blockstate.getCollisionShape(this.level(), blockpos_mutableblockpos).move((double) l1, (double) k2, (double) i2), voxelshape, BooleanOp.AND)) { +- f += blockstate.getBlock().getFriction(); ++ if (!(iblockdata.getBlock() instanceof WaterlilyBlock) && Shapes.joinIsNotEmpty(iblockdata.getCollisionShape(this.level(), blockposition_mutableblockposition).move((double) l1, (double) k2, (double) i2), voxelshape, BooleanOp.AND)) { ++ f += iblockdata.getBlock().getFriction(); + ++k1; + } + } +@@ -583,29 +616,29 @@ + } + + private boolean checkInWater() { +- AABB aabb = this.getBoundingBox(); +- int i = Mth.floor(aabb.minX); +- int j = Mth.ceil(aabb.maxX); +- int k = Mth.floor(aabb.minY); +- int l = Mth.ceil(aabb.minY + 0.001D); +- int i1 = Mth.floor(aabb.minZ); +- int j1 = Mth.ceil(aabb.maxZ); ++ AABB axisalignedbb = this.getBoundingBox(); ++ int i = Mth.floor(axisalignedbb.minX); ++ int j = Mth.ceil(axisalignedbb.maxX); ++ int k = Mth.floor(axisalignedbb.minY); ++ int l = Mth.ceil(axisalignedbb.minY + 0.001D); ++ int i1 = Mth.floor(axisalignedbb.minZ); ++ int j1 = Mth.ceil(axisalignedbb.maxZ); + boolean flag = false; + + this.waterLevel = -1.7976931348623157E308D; +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + + for (int k1 = i; k1 < j; ++k1) { + for (int l1 = k; l1 < l; ++l1) { + for (int i2 = i1; i2 < j1; ++i2) { +- blockpos_mutableblockpos.set(k1, l1, i2); +- FluidState fluidstate = this.level().getFluidState(blockpos_mutableblockpos); ++ blockposition_mutableblockposition.set(k1, l1, i2); ++ FluidState fluid = this.level().getFluidState(blockposition_mutableblockposition); + +- if (fluidstate.is(FluidTags.WATER)) { +- float f = (float) l1 + fluidstate.getHeight(this.level(), blockpos_mutableblockpos); ++ if (fluid.is(FluidTags.WATER)) { ++ float f = (float) l1 + fluid.getHeight(this.level(), blockposition_mutableblockposition); + + this.waterLevel = Math.max((double) f, this.waterLevel); +- flag |= aabb.minY < (double) f; ++ flag |= axisalignedbb.minY < (double) f; + } + } + } +@@ -615,27 +648,27 @@ + } + + @Nullable +- private Boat.Status isUnderwater() { +- AABB aabb = this.getBoundingBox(); +- double d0 = aabb.maxY + 0.001D; +- int i = Mth.floor(aabb.minX); +- int j = Mth.ceil(aabb.maxX); +- int k = Mth.floor(aabb.maxY); ++ private Boat.EnumStatus isUnderwater() { ++ AABB axisalignedbb = this.getBoundingBox(); ++ double d0 = axisalignedbb.maxY + 0.001D; ++ int i = Mth.floor(axisalignedbb.minX); ++ int j = Mth.ceil(axisalignedbb.maxX); ++ int k = Mth.floor(axisalignedbb.maxY); + int l = Mth.ceil(d0); +- int i1 = Mth.floor(aabb.minZ); +- int j1 = Mth.ceil(aabb.maxZ); ++ int i1 = Mth.floor(axisalignedbb.minZ); ++ int j1 = Mth.ceil(axisalignedbb.maxZ); + boolean flag = false; +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + + for (int k1 = i; k1 < j; ++k1) { + for (int l1 = k; l1 < l; ++l1) { + for (int i2 = i1; i2 < j1; ++i2) { +- blockpos_mutableblockpos.set(k1, l1, i2); +- FluidState fluidstate = this.level().getFluidState(blockpos_mutableblockpos); ++ blockposition_mutableblockposition.set(k1, l1, i2); ++ FluidState fluid = this.level().getFluidState(blockposition_mutableblockposition); + +- if (fluidstate.is(FluidTags.WATER) && d0 < (double) ((float) blockpos_mutableblockpos.getY() + fluidstate.getHeight(this.level(), blockpos_mutableblockpos))) { +- if (!fluidstate.isSource()) { +- return Boat.Status.UNDER_FLOWING_WATER; ++ if (fluid.is(FluidTags.WATER) && d0 < (double) ((float) blockposition_mutableblockposition.getY() + fluid.getHeight(this.level(), blockposition_mutableblockposition))) { ++ if (!fluid.isSource()) { ++ return Boat.EnumStatus.UNDER_FLOWING_WATER; + } + + flag = true; +@@ -644,7 +677,7 @@ + } + } + +- return flag ? Boat.Status.UNDER_WATER : null; ++ return flag ? Boat.EnumStatus.UNDER_WATER : null; + } + + private void floatBoat() { +@@ -653,39 +686,39 @@ + double d2 = 0.0D; + + this.invFriction = 0.05F; +- if (this.oldStatus == Boat.Status.IN_AIR && this.status != Boat.Status.IN_AIR && this.status != Boat.Status.ON_LAND) { ++ if (this.oldStatus == Boat.EnumStatus.IN_AIR && this.status != Boat.EnumStatus.IN_AIR && this.status != Boat.EnumStatus.ON_LAND) { + this.waterLevel = this.getY(1.0D); + this.setPos(this.getX(), (double) (this.getWaterLevelAbove() - this.getBbHeight()) + 0.101D, this.getZ()); + this.setDeltaMovement(this.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D)); + this.lastYd = 0.0D; +- this.status = Boat.Status.IN_WATER; ++ this.status = Boat.EnumStatus.IN_WATER; + } else { +- if (this.status == Boat.Status.IN_WATER) { ++ if (this.status == Boat.EnumStatus.IN_WATER) { + d2 = (this.waterLevel - this.getY()) / (double) this.getBbHeight(); + this.invFriction = 0.9F; +- } else if (this.status == Boat.Status.UNDER_FLOWING_WATER) { ++ } else if (this.status == Boat.EnumStatus.UNDER_FLOWING_WATER) { + d1 = -7.0E-4D; + this.invFriction = 0.9F; +- } else if (this.status == Boat.Status.UNDER_WATER) { ++ } else if (this.status == Boat.EnumStatus.UNDER_WATER) { + d2 = 0.009999999776482582D; + this.invFriction = 0.45F; +- } else if (this.status == Boat.Status.IN_AIR) { ++ } else if (this.status == Boat.EnumStatus.IN_AIR) { + this.invFriction = 0.9F; +- } else if (this.status == Boat.Status.ON_LAND) { ++ } else if (this.status == Boat.EnumStatus.ON_LAND) { + this.invFriction = this.landFriction; + if (this.getControllingPassenger() instanceof Player) { + this.landFriction /= 2.0F; + } + } + +- Vec3 vec3 = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + +- this.setDeltaMovement(vec3.x * (double) this.invFriction, vec3.y + d1, vec3.z * (double) this.invFriction); ++ this.setDeltaMovement(vec3d.x * (double) this.invFriction, vec3d.y + d1, vec3d.z * (double) this.invFriction); + this.deltaRotation *= this.invFriction; + if (d2 > 0.0D) { +- Vec3 vec31 = this.getDeltaMovement(); ++ Vec3 vec3d1 = this.getDeltaMovement(); + +- this.setDeltaMovement(vec31.x, (vec31.y + d2 * 0.06153846016296973D) * 0.75D, vec31.z); ++ this.setDeltaMovement(vec3d1.x, (vec3d1.y + d2 * 0.06153846016296973D) * 0.75D, vec3d1.z); + } + } + +@@ -730,170 +763,166 @@ + } + + @Override +- @Override +- protected void positionRider(Entity entity, Entity.MoveFunction entity_movefunction) { +- super.positionRider(entity, entity_movefunction); +- if (!entity.getType().is(EntityTypeTags.CAN_TURN_IN_BOATS)) { +- entity.setYRot(entity.getYRot() + this.deltaRotation); +- entity.setYHeadRot(entity.getYHeadRot() + this.deltaRotation); +- this.clampRotation(entity); +- if (entity instanceof Animal && this.getPassengers().size() == this.getMaxPassengers()) { +- int i = entity.getId() % 2 == 0 ? 90 : 270; ++ protected void positionRider(Entity passenger, Entity.MoveFunction callback) { ++ super.positionRider(passenger, callback); ++ if (!passenger.getType().is(EntityTypeTags.CAN_TURN_IN_BOATS)) { ++ passenger.setYRot(passenger.getYRot() + this.deltaRotation); ++ passenger.setYHeadRot(passenger.getYHeadRot() + this.deltaRotation); ++ this.clampRotation(passenger); ++ if (passenger instanceof Animal && this.getPassengers().size() == this.getMaxPassengers()) { ++ int i = passenger.getId() % 2 == 0 ? 90 : 270; + +- entity.setYBodyRot(((Animal) entity).yBodyRot + (float) i); +- entity.setYHeadRot(entity.getYHeadRot() + (float) i); ++ passenger.setYBodyRot(((Animal) passenger).yBodyRot + (float) i); ++ passenger.setYHeadRot(passenger.getYHeadRot() + (float) i); + } + + } + } + + @Override +- @Override +- public Vec3 getDismountLocationForPassenger(LivingEntity livingentity) { +- Vec3 vec3 = getCollisionHorizontalEscapeVector((double) (this.getBbWidth() * Mth.SQRT_OF_TWO), (double) livingentity.getBbWidth(), livingentity.getYRot()); +- double d0 = this.getX() + vec3.x; +- double d1 = this.getZ() + vec3.z; +- BlockPos blockpos = BlockPos.containing(d0, this.getBoundingBox().maxY, d1); +- BlockPos blockpos1 = blockpos.below(); ++ public Vec3 getDismountLocationForPassenger(LivingEntity livingEntity) { ++ Vec3 vec3d = getCollisionHorizontalEscapeVector((double) (this.getBbWidth() * Mth.SQRT_OF_TWO), (double) livingEntity.getBbWidth(), livingEntity.getYRot()); ++ double d0 = this.getX() + vec3d.x; ++ double d1 = this.getZ() + vec3d.z; ++ BlockPos blockposition = BlockPos.containing(d0, this.getBoundingBox().maxY, d1); ++ BlockPos blockposition1 = blockposition.below(); + +- if (!this.level().isWaterAt(blockpos1)) { ++ if (!this.level().isWaterAt(blockposition1)) { + List list = Lists.newArrayList(); +- double d2 = this.level().getBlockFloorHeight(blockpos); ++ double d2 = this.level().getBlockFloorHeight(blockposition); + + if (DismountHelper.isBlockFloorValid(d2)) { +- list.add(new Vec3(d0, (double) blockpos.getY() + d2, d1)); ++ list.add(new Vec3(d0, (double) blockposition.getY() + d2, d1)); + } + +- double d3 = this.level().getBlockFloorHeight(blockpos1); ++ double d3 = this.level().getBlockFloorHeight(blockposition1); + + if (DismountHelper.isBlockFloorValid(d3)) { +- list.add(new Vec3(d0, (double) blockpos1.getY() + d3, d1)); ++ list.add(new Vec3(d0, (double) blockposition1.getY() + d3, d1)); + } + +- UnmodifiableIterator unmodifiableiterator = livingentity.getDismountPoses().iterator(); ++ UnmodifiableIterator unmodifiableiterator = livingEntity.getDismountPoses().iterator(); + + while (unmodifiableiterator.hasNext()) { +- Pose pose = (Pose) unmodifiableiterator.next(); ++ EntityPose entitypose = (EntityPose) unmodifiableiterator.next(); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- Vec3 vec31 = (Vec3) iterator.next(); ++ Vec3 vec3d1 = (Vec3) iterator.next(); + +- if (DismountHelper.canDismountTo(this.level(), vec31, livingentity, pose)) { +- livingentity.setPose(pose); +- return vec31; ++ if (DismountHelper.canDismountTo(this.level(), vec3d1, livingEntity, entitypose)) { ++ livingEntity.setPose(entitypose); ++ return vec3d1; + } + } + } + } + +- return super.getDismountLocationForPassenger(livingentity); ++ return super.getDismountLocationForPassenger(livingEntity); + } + +- protected void clampRotation(Entity entity) { +- entity.setYBodyRot(this.getYRot()); +- float f = Mth.wrapDegrees(entity.getYRot() - this.getYRot()); ++ protected void clampRotation(Entity entityToUpdate) { ++ entityToUpdate.setYBodyRot(this.getYRot()); ++ float f = Mth.wrapDegrees(entityToUpdate.getYRot() - this.getYRot()); + float f1 = Mth.clamp(f, -105.0F, 105.0F); + +- entity.yRotO += f1 - f; +- entity.setYRot(entity.getYRot() + f1 - f); +- entity.setYHeadRot(entity.getYRot()); ++ entityToUpdate.yRotO += f1 - f; ++ entityToUpdate.setYRot(entityToUpdate.getYRot() + f1 - f); ++ entityToUpdate.setYHeadRot(entityToUpdate.getYRot()); + } + + @Override +- @Override +- public void onPassengerTurned(Entity entity) { +- this.clampRotation(entity); ++ public void onPassengerTurned(Entity entityToUpdate) { ++ this.clampRotation(entityToUpdate); + } + + @Override +- @Override +- protected void addAdditionalSaveData(CompoundTag compoundtag) { +- compoundtag.putString("Type", this.getVariant().getSerializedName()); ++ protected void addAdditionalSaveData(CompoundTag compound) { ++ compound.putString("Type", this.getVariant().getSerializedName()); + } + + @Override +- @Override +- protected void readAdditionalSaveData(CompoundTag compoundtag) { +- if (compoundtag.contains("Type", 8)) { +- this.setVariant(Boat.Type.byName(compoundtag.getString("Type"))); ++ protected void readAdditionalSaveData(CompoundTag compound) { ++ if (compound.contains("Type", 8)) { ++ this.setVariant(Boat.Type.byName(compound.getString("Type"))); + } + + } + + @Override +- @Override +- public InteractionResult interact(Player player, InteractionHand interactionhand) { ++ public InteractionResult interact(Player player, EnumHand hand) { + return player.isSecondaryUseActive() ? InteractionResult.PASS : (this.outOfControlTicks < 60.0F ? (!this.level().isClientSide ? (player.startRiding(this) ? InteractionResult.CONSUME : InteractionResult.PASS) : InteractionResult.SUCCESS) : InteractionResult.PASS); + } + + @Override +- @Override +- protected void checkFallDamage(double d0, boolean flag, BlockState blockstate, BlockPos blockpos) { ++ protected void checkFallDamage(double y, boolean flag, IBlockData onGround, BlockPos state) { + this.lastYd = this.getDeltaMovement().y; + if (!this.isPassenger()) { + if (flag) { + if (this.fallDistance > 3.0F) { +- if (this.status != Boat.Status.ON_LAND) { ++ if (this.status != Boat.EnumStatus.ON_LAND) { + this.resetFallDistance(); + return; + } + + this.causeFallDamage(this.fallDistance, 1.0F, this.damageSources().fall()); + if (!this.level().isClientSide && !this.isRemoved()) { ++ // CraftBukkit start ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, null); ++ this.level().getCraftServer().getPluginManager().callEvent(destroyEvent); ++ if (!destroyEvent.isCancelled()) { + this.kill(); + if (this.level().getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { + int i; + + for (i = 0; i < 3; ++i) { +- this.spawnAtLocation((ItemLike) this.getVariant().getPlanks()); ++ this.spawnAtLocation((IMaterial) this.getVariant().getPlanks()); + } + + for (i = 0; i < 2; ++i) { +- this.spawnAtLocation((ItemLike) Items.STICK); ++ this.spawnAtLocation((IMaterial) Items.STICK); + } + } + } ++ } // CraftBukkit end + } + + this.resetFallDistance(); +- } else if (!this.level().getFluidState(this.blockPosition().below()).is(FluidTags.WATER) && d0 < 0.0D) { +- this.fallDistance -= (float) d0; ++ } else if (!this.level().getFluidState(this.blockPosition().below()).is(FluidTags.WATER) && y < 0.0D) { ++ this.fallDistance -= (float) y; + } + + } + } + +- public boolean getPaddleState(int i) { +- return (Boolean) this.entityData.get(i == 0 ? Boat.DATA_ID_PADDLE_LEFT : Boat.DATA_ID_PADDLE_RIGHT) && this.getControllingPassenger() != null; ++ public boolean getPaddleState(int side) { ++ return (Boolean) this.entityData.get(side == 0 ? Boat.DATA_ID_PADDLE_LEFT : Boat.DATA_ID_PADDLE_RIGHT) && this.getControllingPassenger() != null; + } + +- private void setBubbleTime(int i) { +- this.entityData.set(Boat.DATA_ID_BUBBLE_TIME, i); ++ private void setBubbleTime(int bubbleTime) { ++ this.entityData.set(Boat.DATA_ID_BUBBLE_TIME, bubbleTime); + } + + private int getBubbleTime() { + return (Integer) this.entityData.get(Boat.DATA_ID_BUBBLE_TIME); + } + +- public float getBubbleAngle(float f) { +- return Mth.lerp(f, this.bubbleAngleO, this.bubbleAngle); ++ public float getBubbleAngle(float partialTicks) { ++ return Mth.lerp(partialTicks, this.bubbleAngleO, this.bubbleAngle); + } + +- @Override +- public void setVariant(Boat.Type boat_type) { +- this.entityData.set(Boat.DATA_ID_TYPE, boat_type.ordinal()); ++ public void setVariant(Boat.Type variant) { ++ this.entityData.set(Boat.DATA_ID_TYPE, variant.ordinal()); + } + + @Override +- @Override + public Boat.Type getVariant() { + return Boat.Type.byId((Integer) this.entityData.get(Boat.DATA_ID_TYPE)); + } + + @Override +- @Override +- protected boolean canAddPassenger(Entity entity) { ++ protected boolean canAddPassenger(Entity passenger) { + return this.getPassengers().size() < this.getMaxPassengers() && !this.isEyeInFluid(FluidTags.WATER); + } + +@@ -903,43 +932,39 @@ + + @Nullable + @Override +- @Override + public LivingEntity getControllingPassenger() { + Entity entity = this.getFirstPassenger(); +- LivingEntity livingentity; ++ LivingEntity entityliving; + + if (entity instanceof LivingEntity) { +- LivingEntity livingentity1 = (LivingEntity) entity; ++ LivingEntity entityliving1 = (LivingEntity) entity; + +- livingentity = livingentity1; ++ entityliving = entityliving1; + } else { +- livingentity = super.getControllingPassenger(); ++ entityliving = super.getControllingPassenger(); + } + +- return livingentity; ++ return entityliving; + } + +- public void setInput(boolean flag, boolean flag1, boolean flag2, boolean flag3) { +- this.inputLeft = flag; +- this.inputRight = flag1; +- this.inputUp = flag2; +- this.inputDown = flag3; ++ public void setInput(boolean inputLeft, boolean inputRight, boolean inputUp, boolean inputDown) { ++ this.inputLeft = inputLeft; ++ this.inputRight = inputRight; ++ this.inputUp = inputUp; ++ this.inputDown = inputDown; + } + + @Override +- @Override + protected Component getTypeName() { + return Component.translatable(this.getDropItem().getDescriptionId()); + } + + @Override +- @Override + public boolean isUnderWater() { +- return this.status == Boat.Status.UNDER_WATER || this.status == Boat.Status.UNDER_FLOWING_WATER; ++ return this.status == Boat.EnumStatus.UNDER_WATER || this.status == Boat.EnumStatus.UNDER_FLOWING_WATER; + } + + @Override +- @Override + public ItemStack getPickResult() { + return new ItemStack(this.getDropItem()); + } +@@ -951,7 +976,7 @@ + private final String name; + private final Block planks; + public static final StringRepresentable.EnumCodec CODEC = StringRepresentable.fromEnum(Boat.Type::values); +- private static final IntFunction BY_ID = ByIdMap.continuous(Enum::ordinal, values(), ByIdMap.OutOfBoundsStrategy.ZERO); ++ private static final IntFunction BY_ID = ByIdMap.continuous(Enum::ordinal, values(), ByIdMap.a.ZERO); + + private Type(Block block, String s) { + this.name = s; +@@ -959,7 +984,6 @@ + } + + @Override +- @Override + public String getSerializedName() { + return this.name; + } +@@ -972,24 +996,23 @@ + return this.planks; + } + +- @Override + public String toString() { + return this.name; + } + +- public static Boat.Type byId(int i) { +- return (Boat.Type) Boat.Type.BY_ID.apply(i); ++ public static Boat.Type byId(int id) { ++ return (Boat.Type) Boat.Type.BY_ID.apply(id); + } + +- public static Boat.Type byName(String s) { +- return (Boat.Type) Boat.Type.CODEC.byName(s, Boat.Type.OAK); ++ public static Boat.Type byName(String name) { ++ return (Boat.Type) Boat.Type.CODEC.byName(name, Boat.Type.OAK); + } + } + +- public static enum Status { ++ public static enum EnumStatus { + + IN_WATER, UNDER_WATER, UNDER_FLOWING_WATER, ON_LAND, IN_AIR; + +- private Status() {} ++ private EnumStatus() {} + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/ChestBoat.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/ChestBoat.java.patch new file mode 100644 index 0000000000..ec272b5c4e --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/ChestBoat.java.patch @@ -0,0 +1,314 @@ +--- a/net/minecraft/world/entity/vehicle/ChestBoat.java ++++ b/net/minecraft/world/entity/vehicle/ChestBoat.java +@@ -6,7 +6,7 @@ + import net.minecraft.resources.ResourceLocation; + import net.minecraft.world.Container; + import net.minecraft.world.Containers; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; +@@ -23,6 +23,13 @@ + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end + + public class ChestBoat extends Boat implements HasCustomInventoryScreen, ContainerEntity { + +@@ -32,82 +39,74 @@ + private ResourceLocation lootTable; + private long lootTableSeed; + +- public ChestBoat(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public ChestBoat(EntityType entityType, Level level) { ++ super(entityType, level); + this.itemStacks = NonNullList.withSize(27, ItemStack.EMPTY); + } + +- public ChestBoat(Level level, double d0, double d1, double d2) { ++ public ChestBoat(Level level, double x, double d1, double y) { + super(EntityType.CHEST_BOAT, level); + this.itemStacks = NonNullList.withSize(27, ItemStack.EMPTY); +- this.setPos(d0, d1, d2); +- this.xo = d0; ++ this.setPos(x, d1, y); ++ this.xo = x; + this.yo = d1; +- this.zo = d2; ++ this.zo = y; + } + + @Override +- @Override + protected float getSinglePassengerXOffset() { + return 0.15F; + } + + @Override +- @Override + protected int getMaxPassengers() { + return 1; + } + + @Override +- @Override +- protected void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- this.addChestVehicleSaveData(compoundtag); ++ protected void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ this.addChestVehicleSaveData(compound); + } + + @Override +- @Override +- protected void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.readChestVehicleSaveData(compoundtag); ++ protected void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.readChestVehicleSaveData(compound); + } + + @Override +- @Override +- public void destroy(DamageSource damagesource) { ++ public void destroy(DamageSource damageSource) { + this.destroy(this.getDropItem()); +- this.chestVehicleDestroyed(damagesource, this.level(), this); ++ this.chestVehicleDestroyed(damageSource, this.level(), this); + } + + @Override +- @Override +- public void remove(Entity.RemovalReason entity_removalreason) { +- if (!this.level().isClientSide && entity_removalreason.shouldDestroy()) { ++ public void remove(Entity.RemovalReason reason) { ++ if (!this.level().isClientSide && reason.shouldDestroy()) { + Containers.dropContents(this.level(), (Entity) this, (Container) this); + } + +- super.remove(entity_removalreason); ++ super.remove(reason); + } + + @Override +- @Override +- public InteractionResult interact(Player player, InteractionHand interactionhand) { ++ public InteractionResult interact(Player player, EnumHand hand) { + if (this.canAddPassenger(player) && !player.isSecondaryUseActive()) { +- return super.interact(player, interactionhand); ++ return super.interact(player, hand); + } else { +- InteractionResult interactionresult = this.interactWithContainerVehicle(player); ++ InteractionResult enuminteractionresult = this.interactWithContainerVehicle(player); + +- if (interactionresult.consumesAction()) { ++ if (enuminteractionresult.consumesAction()) { + this.gameEvent(GameEvent.CONTAINER_OPEN, player); + PiglinAi.angerNearbyPiglins(player, true); + } + +- return interactionresult; ++ return enuminteractionresult; + } + } + + @Override +- @Override + public void openCustomInventoryScreen(Player player) { + player.openMenu(this); + if (!player.level().isClientSide) { +@@ -118,7 +117,6 @@ + } + + @Override +- @Override + public Item getDropItem() { + Item item; + +@@ -155,66 +153,56 @@ + } + + @Override +- @Override + public void clearContent() { + this.clearChestVehicleContent(); + } + + @Override +- @Override + public int getContainerSize() { + return 27; + } + + @Override +- @Override +- public ItemStack getItem(int i) { +- return this.getChestVehicleItem(i); ++ public ItemStack getItem(int slot) { ++ return this.getChestVehicleItem(slot); + } + + @Override +- @Override +- public ItemStack removeItem(int i, int j) { +- return this.removeChestVehicleItem(i, j); ++ public ItemStack removeItem(int slot, int amount) { ++ return this.removeChestVehicleItem(slot, amount); + } + + @Override +- @Override +- public ItemStack removeItemNoUpdate(int i) { +- return this.removeChestVehicleItemNoUpdate(i); ++ public ItemStack removeItemNoUpdate(int slot) { ++ return this.removeChestVehicleItemNoUpdate(slot); + } + + @Override +- @Override +- public void setItem(int i, ItemStack itemstack) { +- this.setChestVehicleItem(i, itemstack); ++ public void setItem(int slot, ItemStack stack) { ++ this.setChestVehicleItem(slot, stack); + } + + @Override +- @Override +- public SlotAccess getSlot(int i) { +- return this.getChestVehicleSlot(i); ++ public SlotAccess getSlot(int slot) { ++ return this.getChestVehicleSlot(slot); + } + + @Override +- @Override + public void setChanged() {} + + @Override +- @Override + public boolean stillValid(Player player) { + return this.isChestVehicleStillValid(player); + } + + @Nullable + @Override +- @Override +- public AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) { ++ public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { + if (this.lootTable != null && player.isSpectator()) { + return null; + } else { +- this.unpackLootTable(inventory.player); +- return ChestMenu.threeRows(i, inventory, this); ++ this.unpackLootTable(playerInventory.player); ++ return ChestMenu.threeRows(containerId, playerInventory, this); + } + } + +@@ -224,44 +212,84 @@ + + @Nullable + @Override +- @Override + public ResourceLocation getLootTable() { + return this.lootTable; + } + + @Override +- @Override +- public void setLootTable(@Nullable ResourceLocation resourcelocation) { +- this.lootTable = resourcelocation; ++ public void setLootTable(@Nullable ResourceLocation lootTable) { ++ this.lootTable = lootTable; + } + + @Override +- @Override + public long getLootTableSeed() { + return this.lootTableSeed; + } + + @Override +- @Override +- public void setLootTableSeed(long i) { +- this.lootTableSeed = i; ++ public void setLootTableSeed(long lootTableSeed) { ++ this.lootTableSeed = lootTableSeed; + } + + @Override +- @Override + public NonNullList getItemStacks() { + return this.itemStacks; + } + + @Override +- @Override + public void clearItemStacks() { + this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); + } + + @Override +- @Override + public void stopOpen(Player player) { + this.level().gameEvent(GameEvent.CONTAINER_CLOSE, this.position(), GameEvent.Context.of((Entity) player)); + } ++ ++ // CraftBukkit start ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ @Override ++ public List getContents() { ++ return this.itemStacks; ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public InventoryHolder getOwner() { ++ org.bukkit.entity.Entity entity = getBukkitEntity(); ++ if (entity instanceof InventoryHolder) return (InventoryHolder) entity; ++ return null; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ @Override ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return getBukkitEntity().getLocation(); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java.patch new file mode 100644 index 0000000000..9f3903592e --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java.patch @@ -0,0 +1,187 @@ +--- a/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java ++++ b/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java +@@ -8,7 +8,7 @@ + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; + import net.minecraft.server.level.ServerLevel; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.player.Player; +@@ -17,33 +17,31 @@ + import net.minecraft.world.level.BaseCommandBlock; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; + + public class MinecartCommandBlock extends AbstractMinecart { + +- static final EntityDataAccessor DATA_ID_COMMAND_NAME = SynchedEntityData.defineId(MinecartCommandBlock.class, EntityDataSerializers.STRING); ++ public static final EntityDataAccessor DATA_ID_COMMAND_NAME = SynchedEntityData.defineId(MinecartCommandBlock.class, EntityDataSerializers.STRING); + static final EntityDataAccessor DATA_ID_LAST_OUTPUT = SynchedEntityData.defineId(MinecartCommandBlock.class, EntityDataSerializers.COMPONENT); +- private final BaseCommandBlock commandBlock = new MinecartCommandBlock.MinecartCommandBase(); ++ private final BaseCommandBlock commandBlock = new MinecartCommandBlock.a(); + private static final int ACTIVATION_DELAY = 4; + private int lastActivated; + +- public MinecartCommandBlock(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public MinecartCommandBlock(EntityType entityType, Level level) { ++ super(entityType, level); + } + +- public MinecartCommandBlock(Level level, double d0, double d1, double d2) { +- super(EntityType.COMMAND_BLOCK_MINECART, level, d0, d1, d2); ++ public MinecartCommandBlock(Level level, double x, double d1, double y) { ++ super(EntityType.COMMAND_BLOCK_MINECART, level, x, d1, y); + } + + @Override +- @Override + protected Item getDropItem() { + return Items.MINECART; + } + + @Override +- @Override + protected void defineSynchedData() { + super.defineSynchedData(); + this.getEntityData().define(MinecartCommandBlock.DATA_ID_COMMAND_NAME, ""); +@@ -51,30 +49,26 @@ + } + + @Override +- @Override +- protected void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- this.commandBlock.load(compoundtag); ++ protected void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ this.commandBlock.load(compound); + this.getEntityData().set(MinecartCommandBlock.DATA_ID_COMMAND_NAME, this.getCommandBlock().getCommand()); + this.getEntityData().set(MinecartCommandBlock.DATA_ID_LAST_OUTPUT, this.getCommandBlock().getLastOutput()); + } + + @Override +- @Override +- protected void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- this.commandBlock.save(compoundtag); ++ protected void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ this.commandBlock.save(compound); + } + + @Override +- @Override +- public AbstractMinecart.Type getMinecartType() { +- return AbstractMinecart.Type.COMMAND_BLOCK; ++ public AbstractMinecart.EnumMinecartType getMinecartType() { ++ return AbstractMinecart.EnumMinecartType.COMMAND_BLOCK; + } + + @Override +- @Override +- public BlockState getDefaultDisplayBlockState() { ++ public IBlockData getDefaultDisplayBlockState() { + return Blocks.COMMAND_BLOCK.defaultBlockState(); + } + +@@ -83,9 +77,8 @@ + } + + @Override +- @Override +- public void activateMinecart(int i, int j, int k, boolean flag) { +- if (flag && this.tickCount - this.lastActivated >= 4) { ++ public void activateMinecart(int x, int y, int z, boolean receivingPower) { ++ if (receivingPower && this.tickCount - this.lastActivated >= 4) { + this.getCommandBlock().performCommand(this.level()); + this.lastActivated = this.tickCount; + } +@@ -93,52 +86,46 @@ + } + + @Override +- @Override +- public InteractionResult interact(Player player, InteractionHand interactionhand) { ++ public InteractionResult interact(Player player, EnumHand hand) { + return this.commandBlock.usedBy(player); + } + + @Override +- @Override +- public void onSyncedDataUpdated(EntityDataAccessor entitydataaccessor) { +- super.onSyncedDataUpdated(entitydataaccessor); +- if (MinecartCommandBlock.DATA_ID_LAST_OUTPUT.equals(entitydataaccessor)) { ++ public void onSyncedDataUpdated(EntityDataAccessor key) { ++ super.onSyncedDataUpdated(key); ++ if (MinecartCommandBlock.DATA_ID_LAST_OUTPUT.equals(key)) { + try { + this.commandBlock.setLastOutput((Component) this.getEntityData().get(MinecartCommandBlock.DATA_ID_LAST_OUTPUT)); + } catch (Throwable throwable) { + ; + } +- } else if (MinecartCommandBlock.DATA_ID_COMMAND_NAME.equals(entitydataaccessor)) { ++ } else if (MinecartCommandBlock.DATA_ID_COMMAND_NAME.equals(key)) { + this.commandBlock.setCommand((String) this.getEntityData().get(MinecartCommandBlock.DATA_ID_COMMAND_NAME)); + } + + } + + @Override +- @Override + public boolean onlyOpCanSetNbt() { + return true; + } + +- public class MinecartCommandBase extends BaseCommandBlock { ++ public class a extends BaseCommandBlock { + +- public MinecartCommandBase() {} ++ public a() {} + + @Override +- @Override + public ServerLevel getLevel() { + return (ServerLevel) MinecartCommandBlock.this.level(); + } + + @Override +- @Override + public void onUpdated() { + MinecartCommandBlock.this.getEntityData().set(MinecartCommandBlock.DATA_ID_COMMAND_NAME, this.getCommand()); + MinecartCommandBlock.this.getEntityData().set(MinecartCommandBlock.DATA_ID_LAST_OUTPUT, this.getLastOutput()); + } + + @Override +- @Override + public Vec3 getPosition() { + return MinecartCommandBlock.this.position(); + } +@@ -148,15 +135,20 @@ + } + + @Override +- @Override + public CommandSourceStack createCommandSourceStack() { + return new CommandSourceStack(this, MinecartCommandBlock.this.position(), MinecartCommandBlock.this.getRotationVector(), this.getLevel(), 2, this.getName().getString(), MinecartCommandBlock.this.getDisplayName(), this.getLevel().getServer(), MinecartCommandBlock.this); + } + + @Override +- @Override + public boolean isValid() { + return !MinecartCommandBlock.this.isRemoved(); + } ++ ++ // CraftBukkit start ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return (org.bukkit.craftbukkit.entity.CraftMinecartCommand) MinecartCommandBlock.this.getBukkitEntity(); ++ } ++ // CraftBukkit end + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/MinecartTNT.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/MinecartTNT.java.patch new file mode 100644 index 0000000000..2c6db68630 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/MinecartTNT.java.patch @@ -0,0 +1,218 @@ +--- a/net/minecraft/world/entity/vehicle/MinecartTNT.java ++++ b/net/minecraft/world/entity/vehicle/MinecartTNT.java +@@ -20,36 +20,36 @@ + import net.minecraft.world.level.ExplosionDamageCalculator; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; ++// CraftBukkit start ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end + + public class MinecartTNT extends AbstractMinecart { + + private static final byte EVENT_PRIME = 10; +- private int fuse = -1; ++ public int fuse = -1; + +- public MinecartTNT(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public MinecartTNT(EntityType entityType, Level level) { ++ super(entityType, level); + } + +- public MinecartTNT(Level level, double d0, double d1, double d2) { +- super(EntityType.TNT_MINECART, level, d0, d1, d2); ++ public MinecartTNT(Level level, double x, double d1, double y) { ++ super(EntityType.TNT_MINECART, level, x, d1, y); + } + + @Override +- @Override +- public AbstractMinecart.Type getMinecartType() { +- return AbstractMinecart.Type.TNT; ++ public AbstractMinecart.EnumMinecartType getMinecartType() { ++ return AbstractMinecart.EnumMinecartType.TNT; + } + + @Override +- @Override +- public BlockState getDefaultDisplayBlockState() { ++ public IBlockData getDefaultDisplayBlockState() { + return Blocks.TNT.defaultBlockState(); + } + + @Override +- @Override + public void tick() { + super.tick(); + if (this.fuse > 0) { +@@ -70,29 +70,27 @@ + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { +- Entity entity = damagesource.getDirectEntity(); ++ public boolean hurt(DamageSource source, float amount) { ++ Entity entity = source.getDirectEntity(); + + if (entity instanceof AbstractArrow) { +- AbstractArrow abstractarrow = (AbstractArrow) entity; ++ AbstractArrow entityarrow = (AbstractArrow) entity; + +- if (abstractarrow.isOnFire()) { +- DamageSource damagesource1 = this.damageSources().explosion(this, damagesource.getEntity()); ++ if (entityarrow.isOnFire()) { ++ DamageSource damagesource1 = this.damageSources().explosion(this, source.getEntity()); + +- this.explode(damagesource1, abstractarrow.getDeltaMovement().lengthSqr()); ++ this.explode(damagesource1, entityarrow.getDeltaMovement().lengthSqr()); + } + } + +- return super.hurt(damagesource, f); ++ return super.hurt(source, amount); + } + + @Override +- @Override +- public void destroy(DamageSource damagesource) { ++ public void destroy(DamageSource source) { + double d0 = this.getDeltaMovement().horizontalDistanceSqr(); + +- if (!damageSourceIgnitesTnt(damagesource) && d0 < 0.009999999776482582D) { ++ if (!damageSourceIgnitesTnt(source) && d0 < 0.009999999776482582D) { + this.destroy(this.getDropItem()); + } else { + if (this.fuse < 0) { +@@ -104,57 +102,61 @@ + } + + @Override +- @Override + protected Item getDropItem() { + return Items.TNT_MINECART; + } + +- protected void explode(double d0) { +- this.explode((DamageSource) null, d0); ++ public void explode(double radiusModifier) { ++ this.explode((DamageSource) null, radiusModifier); + } + +- protected void explode(@Nullable DamageSource damagesource, double d0) { ++ protected void explode(@Nullable DamageSource damageSource, double radiusModifier) { + if (!this.level().isClientSide) { +- double d1 = Math.sqrt(d0); ++ double d1 = Math.sqrt(radiusModifier); + + if (d1 > 5.0D) { + d1 = 5.0D; + } + +- this.level().explode(this, damagesource, (ExplosionDamageCalculator) null, this.getX(), this.getY(), this.getZ(), (float) (4.0D + this.random.nextDouble() * 1.5D * d1), false, Level.ExplosionInteraction.TNT); ++ // CraftBukkit start ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), (float) (4.0D + this.random.nextDouble() * 1.5D * d1), false); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ fuse = -1; ++ return; ++ } ++ this.level().explode(this, damageSource, (ExplosionDamageCalculator) null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.TNT); ++ // CraftBukkit end + this.discard(); + } + + } + + @Override +- @Override +- public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { +- if (f >= 3.0F) { +- float f2 = f / 10.0F; ++ public boolean causeFallDamage(float fallDistance, float multiplier, DamageSource source) { ++ if (fallDistance >= 3.0F) { ++ float f2 = fallDistance / 10.0F; + + this.explode((double) (f2 * f2)); + } + +- return super.causeFallDamage(f, f1, damagesource); ++ return super.causeFallDamage(fallDistance, multiplier, source); + } + + @Override +- @Override +- public void activateMinecart(int i, int j, int k, boolean flag) { +- if (flag && this.fuse < 0) { ++ public void activateMinecart(int x, int y, int z, boolean receivingPower) { ++ if (receivingPower && this.fuse < 0) { + this.primeFuse(); + } + + } + + @Override +- @Override +- public void handleEntityEvent(byte b0) { +- if (b0 == 10) { ++ public void handleEntityEvent(byte id) { ++ if (id == 10) { + this.primeFuse(); + } else { +- super.handleEntityEvent(b0); ++ super.handleEntityEvent(id); + } + + } +@@ -179,36 +181,31 @@ + } + + @Override +- @Override +- public float getBlockExplosionResistance(Explosion explosion, BlockGetter blockgetter, BlockPos blockpos, BlockState blockstate, FluidState fluidstate, float f) { +- return this.isPrimed() && (blockstate.is(BlockTags.RAILS) || blockgetter.getBlockState(blockpos.above()).is(BlockTags.RAILS)) ? 0.0F : super.getBlockExplosionResistance(explosion, blockgetter, blockpos, blockstate, fluidstate, f); ++ public float getBlockExplosionResistance(Explosion explosion, BlockGetter level, BlockPos pos, IBlockData blockState, FluidState fluidState, float explosionPower) { ++ return this.isPrimed() && (blockState.is(BlockTags.RAILS) || level.getBlockState(pos.above()).is(BlockTags.RAILS)) ? 0.0F : super.getBlockExplosionResistance(explosion, level, pos, blockState, fluidState, explosionPower); + } + + @Override +- @Override +- public boolean shouldBlockExplode(Explosion explosion, BlockGetter blockgetter, BlockPos blockpos, BlockState blockstate, float f) { +- return this.isPrimed() && (blockstate.is(BlockTags.RAILS) || blockgetter.getBlockState(blockpos.above()).is(BlockTags.RAILS)) ? false : super.shouldBlockExplode(explosion, blockgetter, blockpos, blockstate, f); ++ public boolean shouldBlockExplode(Explosion explosion, BlockGetter level, BlockPos pos, IBlockData blockState, float explosionPower) { ++ return this.isPrimed() && (blockState.is(BlockTags.RAILS) || level.getBlockState(pos.above()).is(BlockTags.RAILS)) ? false : super.shouldBlockExplode(explosion, level, pos, blockState, explosionPower); + } + + @Override +- @Override +- protected void readAdditionalSaveData(CompoundTag compoundtag) { +- super.readAdditionalSaveData(compoundtag); +- if (compoundtag.contains("TNTFuse", 99)) { +- this.fuse = compoundtag.getInt("TNTFuse"); ++ protected void readAdditionalSaveData(CompoundTag compound) { ++ super.readAdditionalSaveData(compound); ++ if (compound.contains("TNTFuse", 99)) { ++ this.fuse = compound.getInt("TNTFuse"); + } + + } + + @Override +- @Override +- protected void addAdditionalSaveData(CompoundTag compoundtag) { +- super.addAdditionalSaveData(compoundtag); +- compoundtag.putInt("TNTFuse", this.fuse); ++ protected void addAdditionalSaveData(CompoundTag compound) { ++ super.addAdditionalSaveData(compound); ++ compound.putInt("TNTFuse", this.fuse); + } + + @Override +- @Override + boolean shouldSourceDestroy(DamageSource damagesource) { + return damageSourceIgnitesTnt(damagesource); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/VehicleEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/VehicleEntity.java.patch new file mode 100644 index 0000000000..1e2645d350 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/entity/vehicle/VehicleEntity.java.patch @@ -0,0 +1,101 @@ +--- a/net/minecraft/world/entity/vehicle/VehicleEntity.java ++++ b/net/minecraft/world/entity/vehicle/VehicleEntity.java +@@ -13,36 +13,71 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.entity.Vehicle; ++import org.bukkit.event.vehicle.VehicleDamageEvent; ++import org.bukkit.event.vehicle.VehicleDestroyEvent; ++// CraftBukkit end ++ + public abstract class VehicleEntity extends Entity { + + protected static final EntityDataAccessor DATA_ID_HURT = SynchedEntityData.defineId(VehicleEntity.class, EntityDataSerializers.INT); + protected static final EntityDataAccessor DATA_ID_HURTDIR = SynchedEntityData.defineId(VehicleEntity.class, EntityDataSerializers.INT); + protected static final EntityDataAccessor DATA_ID_DAMAGE = SynchedEntityData.defineId(VehicleEntity.class, EntityDataSerializers.FLOAT); + +- public VehicleEntity(EntityType entitytype, Level level) { +- super(entitytype, level); ++ public VehicleEntity(EntityType entityType, Level level) { ++ super(entityType, level); + } + + @Override +- @Override +- public boolean hurt(DamageSource damagesource, float f) { ++ public boolean hurt(DamageSource source, float amount) { + if (!this.level().isClientSide && !this.isRemoved()) { +- if (this.isInvulnerableTo(damagesource)) { ++ if (this.isInvulnerableTo(source)) { + return false; + } else { ++ // CraftBukkit start ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ org.bukkit.entity.Entity attacker = (source.getEntity() == null) ? null : source.getEntity().getBukkitEntity(); ++ ++ VehicleDamageEvent event = new VehicleDamageEvent(vehicle, attacker, (double) amount); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ amount = (float) event.getDamage(); ++ // CraftBukkit end + this.setHurtDir(-this.getHurtDir()); + this.setHurtTime(10); + this.markHurt(); +- this.setDamage(this.getDamage() + f * 10.0F); +- this.gameEvent(GameEvent.ENTITY_DAMAGE, damagesource.getEntity()); +- boolean flag = damagesource.getEntity() instanceof Player && ((Player) damagesource.getEntity()).getAbilities().instabuild; ++ this.setDamage(this.getDamage() + amount * 10.0F); ++ this.gameEvent(GameEvent.ENTITY_DAMAGE, source.getEntity()); ++ boolean flag = source.getEntity() instanceof Player && ((Player) source.getEntity()).getAbilities().instabuild; + +- if ((flag || this.getDamage() <= 40.0F) && !this.shouldSourceDestroy(damagesource)) { ++ if ((flag || this.getDamage() <= 40.0F) && !this.shouldSourceDestroy(source)) { + if (flag) { ++ // CraftBukkit start ++ VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, attacker); ++ this.level().getCraftServer().getPluginManager().callEvent(destroyEvent); ++ ++ if (destroyEvent.isCancelled()) { ++ this.setDamage(40.0F); // Maximize damage so this doesn't get triggered again right away ++ return true; ++ } ++ // CraftBukkit end + this.discard(); + } + } else { +- this.destroy(damagesource); ++ // CraftBukkit start ++ VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, attacker); ++ this.level().getCraftServer().getPluginManager().callEvent(destroyEvent); ++ ++ if (destroyEvent.isCancelled()) { ++ this.setDamage(40.0F); // Maximize damage so this doesn't get triggered again right away ++ return true; ++ } ++ // CraftBukkit end ++ this.destroy(source); + } + + return true; +@@ -70,7 +105,6 @@ + } + + @Override +- @Override + protected void defineSynchedData() { + this.entityData.define(VehicleEntity.DATA_ID_HURT, 0); + this.entityData.define(VehicleEntity.DATA_ID_HURTDIR, 1); +@@ -101,7 +135,7 @@ + return (Integer) this.entityData.get(VehicleEntity.DATA_ID_HURTDIR); + } + +- protected void destroy(DamageSource damagesource) { ++ protected void destroy(DamageSource damageSource) { + this.destroy(this.getDropItem()); + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/food/FoodData.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/food/FoodData.java.patch new file mode 100644 index 0000000000..c9b63edfe3 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/food/FoodData.java.patch @@ -0,0 +1,194 @@ +--- a/net/minecraft/world/food/FoodData.java ++++ b/net/minecraft/world/food/FoodData.java +@@ -1,6 +1,8 @@ + package net.minecraft.world.food; + + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.network.protocol.game.ClientboundSetHealthPacket; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.Difficulty; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Item; +@@ -9,38 +11,68 @@ + + public class FoodData { + +- private int foodLevel = 20; +- private float saturationLevel = 5.0F; +- private float exhaustionLevel; ++ public int foodLevel = 20; ++ public float saturationLevel = 5.0F; ++ public float exhaustionLevel; + private int tickTimer; ++ // CraftBukkit start ++ private Player entityhuman; ++ public int saturatedRegenRate = 10; ++ public int unsaturatedRegenRate = 80; ++ public int starvationRate = 80; ++ // CraftBukkit end + private int lastFoodLevel = 20; + +- public FoodData() {} ++ public FoodData() { throw new AssertionError("Whoopsie, we missed the bukkit."); } // CraftBukkit start - throw an error + +- public void eat(int i, float f) { +- this.foodLevel = Math.min(i + this.foodLevel, 20); +- this.saturationLevel = Math.min(this.saturationLevel + (float) i * f * 2.0F, (float) this.foodLevel); ++ // CraftBukkit start - added EntityHuman constructor ++ public FoodData(Player entityhuman) { ++ org.apache.commons.lang.Validate.notNull(entityhuman); ++ this.entityhuman = entityhuman; + } ++ // CraftBukkit end + +- public void eat(Item item, ItemStack itemstack) { ++ public void eat(int foodLevelModifier, float saturationLevelModifier) { ++ this.foodLevel = Math.min(foodLevelModifier + this.foodLevel, 20); ++ this.saturationLevel = Math.min(this.saturationLevel + (float) foodLevelModifier * saturationLevelModifier * 2.0F, (float) this.foodLevel); ++ } ++ ++ public void eat(Item item, ItemStack stack) { + if (item.isEdible()) { +- FoodProperties foodproperties = item.getFoodProperties(); ++ FoodProperties foodinfo = item.getFoodProperties(); ++ // CraftBukkit start ++ int oldFoodLevel = foodLevel; + +- this.eat(foodproperties.getNutrition(), foodproperties.getSaturationModifier()); ++ org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(entityhuman, foodinfo.getNutrition() + oldFoodLevel, stack); ++ ++ if (!event.isCancelled()) { ++ this.eat(event.getFoodLevel() - oldFoodLevel, foodinfo.getSaturationModifier()); ++ } ++ ++ ((ServerPlayer) entityhuman).getBukkitEntity().sendHealthUpdate(); ++ // CraftBukkit end + } + + } + + public void tick(Player player) { +- Difficulty difficulty = player.level().getDifficulty(); ++ Difficulty enumdifficulty = player.level().getDifficulty(); + + this.lastFoodLevel = this.foodLevel; + if (this.exhaustionLevel > 4.0F) { + this.exhaustionLevel -= 4.0F; + if (this.saturationLevel > 0.0F) { + this.saturationLevel = Math.max(this.saturationLevel - 1.0F, 0.0F); +- } else if (difficulty != Difficulty.PEACEFUL) { +- this.foodLevel = Math.max(this.foodLevel - 1, 0); ++ } else if (enumdifficulty != Difficulty.PEACEFUL) { ++ // CraftBukkit start ++ org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(player, Math.max(this.foodLevel - 1, 0)); ++ ++ if (!event.isCancelled()) { ++ this.foodLevel = event.getFoodLevel(); ++ } ++ ++ ((ServerPlayer) player).connection.send(new ClientboundSetHealthPacket(((ServerPlayer) player).getBukkitEntity().getScaledHealth(), this.foodLevel, this.saturationLevel)); ++ // CraftBukkit end + } + } + +@@ -48,24 +80,26 @@ + + if (flag && this.saturationLevel > 0.0F && player.isHurt() && this.foodLevel >= 20) { + ++this.tickTimer; +- if (this.tickTimer >= 10) { ++ if (this.tickTimer >= this.saturatedRegenRate) { // CraftBukkit + float f = Math.min(this.saturationLevel, 6.0F); + +- player.heal(f / 6.0F); +- this.addExhaustion(f); ++ player.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED); // CraftBukkit - added RegainReason ++ // this.addExhaustion(f); CraftBukkit - EntityExhaustionEvent ++ player.causeFoodExhaustion(f, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.REGEN); // CraftBukkit - EntityExhaustionEvent + this.tickTimer = 0; + } + } else if (flag && this.foodLevel >= 18 && player.isHurt()) { + ++this.tickTimer; +- if (this.tickTimer >= 80) { +- player.heal(1.0F); +- this.addExhaustion(6.0F); ++ if (this.tickTimer >= this.unsaturatedRegenRate) { // CraftBukkit - add regen rate manipulation ++ player.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED); // CraftBukkit - added RegainReason ++ // this.a(6.0F); CraftBukkit - EntityExhaustionEvent ++ player.causeFoodExhaustion(6.0f, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.REGEN); // CraftBukkit - EntityExhaustionEvent + this.tickTimer = 0; + } + } else if (this.foodLevel <= 0) { + ++this.tickTimer; +- if (this.tickTimer >= 80) { +- if (player.getHealth() > 10.0F || difficulty == Difficulty.HARD || player.getHealth() > 1.0F && difficulty == Difficulty.NORMAL) { ++ if (this.tickTimer >= this.starvationRate) { // CraftBukkit - add regen rate manipulation ++ if (player.getHealth() > 10.0F || enumdifficulty == Difficulty.HARD || player.getHealth() > 1.0F && enumdifficulty == Difficulty.NORMAL) { + player.hurt(player.damageSources().starve(), 1.0F); + } + +@@ -77,21 +111,21 @@ + + } + +- public void readAdditionalSaveData(CompoundTag compoundtag) { +- if (compoundtag.contains("foodLevel", 99)) { +- this.foodLevel = compoundtag.getInt("foodLevel"); +- this.tickTimer = compoundtag.getInt("foodTickTimer"); +- this.saturationLevel = compoundtag.getFloat("foodSaturationLevel"); +- this.exhaustionLevel = compoundtag.getFloat("foodExhaustionLevel"); ++ public void readAdditionalSaveData(CompoundTag compoundTag) { ++ if (compoundTag.contains("foodLevel", 99)) { ++ this.foodLevel = compoundTag.getInt("foodLevel"); ++ this.tickTimer = compoundTag.getInt("foodTickTimer"); ++ this.saturationLevel = compoundTag.getFloat("foodSaturationLevel"); ++ this.exhaustionLevel = compoundTag.getFloat("foodExhaustionLevel"); + } + + } + +- public void addAdditionalSaveData(CompoundTag compoundtag) { +- compoundtag.putInt("foodLevel", this.foodLevel); +- compoundtag.putInt("foodTickTimer", this.tickTimer); +- compoundtag.putFloat("foodSaturationLevel", this.saturationLevel); +- compoundtag.putFloat("foodExhaustionLevel", this.exhaustionLevel); ++ public void addAdditionalSaveData(CompoundTag compoundTag) { ++ compoundTag.putInt("foodLevel", this.foodLevel); ++ compoundTag.putInt("foodTickTimer", this.tickTimer); ++ compoundTag.putFloat("foodSaturationLevel", this.saturationLevel); ++ compoundTag.putFloat("foodExhaustionLevel", this.exhaustionLevel); + } + + public int getFoodLevel() { +@@ -106,8 +140,8 @@ + return this.foodLevel < 20; + } + +- public void addExhaustion(float f) { +- this.exhaustionLevel = Math.min(this.exhaustionLevel + f, 40.0F); ++ public void addExhaustion(float exhaustion) { ++ this.exhaustionLevel = Math.min(this.exhaustionLevel + exhaustion, 40.0F); + } + + public float getExhaustionLevel() { +@@ -118,15 +152,15 @@ + return this.saturationLevel; + } + +- public void setFoodLevel(int i) { +- this.foodLevel = i; ++ public void setFoodLevel(int foodLevel) { ++ this.foodLevel = foodLevel; + } + +- public void setSaturation(float f) { +- this.saturationLevel = f; ++ public void setSaturation(float saturationLevel) { ++ this.saturationLevel = saturationLevel; + } + +- public void setExhaustion(float f) { +- this.exhaustionLevel = f; ++ public void setExhaustion(float exhaustionLevel) { ++ this.exhaustionLevel = exhaustionLevel; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/AbstractContainerMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/AbstractContainerMenu.java.patch new file mode 100644 index 0000000000..6a52b30551 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/AbstractContainerMenu.java.patch @@ -0,0 +1,959 @@ +--- a/net/minecraft/world/inventory/AbstractContainerMenu.java ++++ b/net/minecraft/world/inventory/AbstractContainerMenu.java +@@ -21,6 +21,8 @@ + import net.minecraft.ReportedException; + import net.minecraft.core.NonNullList; + import net.minecraft.core.registries.BuiltInRegistries; ++import net.minecraft.network.chat.Component; ++import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.Mth; + import net.minecraft.world.Container; +@@ -33,6 +35,18 @@ + import net.minecraft.world.level.block.entity.BlockEntity; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.google.common.base.Preconditions; ++import java.util.HashMap; ++import java.util.Map; ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.Event.Result; ++import org.bukkit.event.inventory.InventoryDragEvent; ++import org.bukkit.event.inventory.InventoryType; ++import org.bukkit.inventory.InventoryView; ++// CraftBukkit end ++ + public abstract class AbstractContainerMenu { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -44,11 +58,11 @@ + public static final int QUICKCRAFT_HEADER_CONTINUE = 1; + public static final int QUICKCRAFT_HEADER_END = 2; + public static final int CARRIED_SLOT_SIZE = Integer.MAX_VALUE; +- private final NonNullList lastSlots = NonNullList.create(); +- public final NonNullList slots = NonNullList.create(); ++ public NonNullList lastSlots = NonNullList.create(); ++ public NonNullList slots = NonNullList.create(); + private final List dataSlots = Lists.newArrayList(); + private ItemStack carried; +- private final NonNullList remoteSlots; ++ public NonNullList remoteSlots; + private final IntList remoteDataSlots; + private ItemStack remoteCarried; + private int stateId; +@@ -63,7 +77,28 @@ + private ContainerSynchronizer synchronizer; + private boolean suppressRemoteUpdates; + +- protected AbstractContainerMenu(@Nullable MenuType menutype, int i) { ++ // CraftBukkit start ++ public boolean checkReachable = true; ++ public abstract InventoryView getBukkitView(); ++ public void transferTo(AbstractContainerMenu other, org.bukkit.craftbukkit.entity.CraftHumanEntity player) { ++ InventoryView source = this.getBukkitView(), destination = other.getBukkitView(); ++ ((CraftInventory) source.getTopInventory()).getInventory().onClose(player); ++ ((CraftInventory) source.getBottomInventory()).getInventory().onClose(player); ++ ((CraftInventory) destination.getTopInventory()).getInventory().onOpen(player); ++ ((CraftInventory) destination.getBottomInventory()).getInventory().onOpen(player); ++ } ++ private Component title; ++ public final Component getTitle() { ++ Preconditions.checkState(this.title != null, "Title not set"); ++ return this.title; ++ } ++ public final void setTitle(Component title) { ++ Preconditions.checkState(this.title == null, "Title already set"); ++ this.title = title; ++ } ++ // CraftBukkit end ++ ++ protected AbstractContainerMenu(@Nullable MenuType menuType, int containerId) { + this.carried = ItemStack.EMPTY; + this.remoteSlots = NonNullList.create(); + this.remoteDataSlots = new IntArrayList(); +@@ -71,13 +106,13 @@ + this.quickcraftType = -1; + this.quickcraftSlots = Sets.newHashSet(); + this.containerListeners = Lists.newArrayList(); +- this.menuType = menutype; +- this.containerId = i; ++ this.menuType = menuType; ++ this.containerId = containerId; + } + +- protected static boolean stillValid(ContainerLevelAccess containerlevelaccess, Player player, Block block) { +- return (Boolean) containerlevelaccess.evaluate((level, blockpos) -> { +- return !level.getBlockState(blockpos).is(block) ? false : player.distanceToSqr((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D) <= 64.0D; ++ protected static boolean stillValid(ContainerLevelAccess access, Player player, Block targetBlock) { ++ return (Boolean) access.evaluate((world, blockposition) -> { ++ return !world.getBlockState(blockposition).is(targetBlock) ? false : player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) <= 64.0D; + }, true); + } + +@@ -89,24 +124,24 @@ + } + } + +- protected static void checkContainerSize(Container container, int i) { ++ protected static void checkContainerSize(Container container, int minSize) { + int j = container.getContainerSize(); + +- if (j < i) { +- throw new IllegalArgumentException("Container size " + j + " is smaller than expected " + i); ++ if (j < minSize) { ++ throw new IllegalArgumentException("Container size " + j + " is smaller than expected " + minSize); + } + } + +- protected static void checkContainerDataCount(ContainerData containerdata, int i) { +- int j = containerdata.getCount(); ++ protected static void checkContainerDataCount(ContainerData intArray, int minSize) { ++ int j = intArray.getCount(); + +- if (j < i) { +- throw new IllegalArgumentException("Container data count " + j + " is smaller than expected " + i); ++ if (j < minSize) { ++ throw new IllegalArgumentException("Container data count " + j + " is smaller than expected " + minSize); + } + } + +- public boolean isValidSlotIndex(int i) { +- return i == -1 || i == -999 || i < this.slots.size(); ++ public boolean isValidSlotIndex(int slotIndex) { ++ return slotIndex == -1 || slotIndex == -999 || slotIndex < this.slots.size(); + } + + protected Slot addSlot(Slot slot) { +@@ -117,28 +152,28 @@ + return slot; + } + +- protected DataSlot addDataSlot(DataSlot dataslot) { +- this.dataSlots.add(dataslot); ++ protected DataSlot addDataSlot(DataSlot intValue) { ++ this.dataSlots.add(intValue); + this.remoteDataSlots.add(0); +- return dataslot; ++ return intValue; + } + +- protected void addDataSlots(ContainerData containerdata) { +- for (int i = 0; i < containerdata.getCount(); ++i) { +- this.addDataSlot(DataSlot.forContainer(containerdata, i)); ++ protected void addDataSlots(ContainerData array) { ++ for (int i = 0; i < array.getCount(); ++i) { ++ this.addDataSlot(DataSlot.forContainer(array, i)); + } + + } + +- public void addSlotListener(ContainerListener containerlistener) { +- if (!this.containerListeners.contains(containerlistener)) { +- this.containerListeners.add(containerlistener); ++ public void addSlotListener(ContainerListener listener) { ++ if (!this.containerListeners.contains(listener)) { ++ this.containerListeners.add(listener); + this.broadcastChanges(); + } + } + +- public void setSynchronizer(ContainerSynchronizer containersynchronizer) { +- this.synchronizer = containersynchronizer; ++ public void setSynchronizer(ContainerSynchronizer synchronizer) { ++ this.synchronizer = synchronizer; + this.sendAllDataToRemote(); + } + +@@ -164,10 +199,19 @@ + + } + +- public void removeSlotListener(ContainerListener containerlistener) { +- this.containerListeners.remove(containerlistener); ++ // CraftBukkit start ++ public void broadcastCarriedItem() { ++ this.remoteCarried = this.getCarried().copy(); ++ if (this.synchronizer != null) { ++ this.synchronizer.sendCarriedChange(this, this.remoteCarried); ++ } + } ++ // CraftBukkit end + ++ public void removeSlotListener(ContainerListener listener) { ++ this.containerListeners.remove(listener); ++ } ++ + public NonNullList getItems() { + NonNullList nonnulllist = NonNullList.create(); + Iterator iterator = this.slots.iterator(); +@@ -197,10 +241,10 @@ + this.synchronizeCarriedToRemote(); + + for (i = 0; i < this.dataSlots.size(); ++i) { +- DataSlot dataslot = (DataSlot) this.dataSlots.get(i); +- int j = dataslot.get(); ++ DataSlot containerproperty = (DataSlot) this.dataSlots.get(i); ++ int j = containerproperty.get(); + +- if (dataslot.checkAndClearUpdateFlag()) { ++ if (containerproperty.checkAndClearUpdateFlag()) { + this.updateDataSlotListeners(i, j); + } + +@@ -220,69 +264,69 @@ + } + + for (i = 0; i < this.dataSlots.size(); ++i) { +- DataSlot dataslot = (DataSlot) this.dataSlots.get(i); ++ DataSlot containerproperty = (DataSlot) this.dataSlots.get(i); + +- if (dataslot.checkAndClearUpdateFlag()) { +- this.updateDataSlotListeners(i, dataslot.get()); ++ if (containerproperty.checkAndClearUpdateFlag()) { ++ this.updateDataSlotListeners(i, containerproperty.get()); + } + } + + this.sendAllDataToRemote(); + } + +- private void updateDataSlotListeners(int i, int j) { ++ private void updateDataSlotListeners(int slotIndex, int value) { + Iterator iterator = this.containerListeners.iterator(); + + while (iterator.hasNext()) { +- ContainerListener containerlistener = (ContainerListener) iterator.next(); ++ ContainerListener icrafting = (ContainerListener) iterator.next(); + +- containerlistener.dataChanged(this, i, j); ++ icrafting.dataChanged(this, slotIndex, value); + } + + } + +- private void triggerSlotListeners(int i, ItemStack itemstack, Supplier supplier) { +- ItemStack itemstack1 = (ItemStack) this.lastSlots.get(i); ++ private void triggerSlotListeners(int slotIndex, ItemStack stack, Supplier supplier) { ++ ItemStack itemstack1 = (ItemStack) this.lastSlots.get(slotIndex); + +- if (!ItemStack.matches(itemstack1, itemstack)) { ++ if (!ItemStack.matches(itemstack1, stack)) { + ItemStack itemstack2 = (ItemStack) supplier.get(); + +- this.lastSlots.set(i, itemstack2); ++ this.lastSlots.set(slotIndex, itemstack2); + Iterator iterator = this.containerListeners.iterator(); + + while (iterator.hasNext()) { +- ContainerListener containerlistener = (ContainerListener) iterator.next(); ++ ContainerListener icrafting = (ContainerListener) iterator.next(); + +- containerlistener.slotChanged(this, i, itemstack2); ++ icrafting.slotChanged(this, slotIndex, itemstack2); + } + } + + } + +- private void synchronizeSlotToRemote(int i, ItemStack itemstack, Supplier supplier) { ++ private void synchronizeSlotToRemote(int slotIndex, ItemStack stack, Supplier supplier) { + if (!this.suppressRemoteUpdates) { +- ItemStack itemstack1 = (ItemStack) this.remoteSlots.get(i); ++ ItemStack itemstack1 = (ItemStack) this.remoteSlots.get(slotIndex); + +- if (!ItemStack.matches(itemstack1, itemstack)) { ++ if (!ItemStack.matches(itemstack1, stack)) { + ItemStack itemstack2 = (ItemStack) supplier.get(); + +- this.remoteSlots.set(i, itemstack2); ++ this.remoteSlots.set(slotIndex, itemstack2); + if (this.synchronizer != null) { +- this.synchronizer.sendSlotChange(this, i, itemstack2); ++ this.synchronizer.sendSlotChange(this, slotIndex, itemstack2); + } + } + + } + } + +- private void synchronizeDataSlotToRemote(int i, int j) { ++ private void synchronizeDataSlotToRemote(int slotIndex, int value) { + if (!this.suppressRemoteUpdates) { +- int k = this.remoteDataSlots.getInt(i); ++ int k = this.remoteDataSlots.getInt(slotIndex); + +- if (k != j) { +- this.remoteDataSlots.set(i, j); ++ if (k != value) { ++ this.remoteDataSlots.set(slotIndex, value); + if (this.synchronizer != null) { +- this.synchronizer.sendDataChange(this, i, j); ++ this.synchronizer.sendDataChange(this, slotIndex, value); + } + } + +@@ -301,71 +345,71 @@ + } + } + +- public void setRemoteSlot(int i, ItemStack itemstack) { +- this.remoteSlots.set(i, itemstack.copy()); ++ public void setRemoteSlot(int slot, ItemStack stack) { ++ this.remoteSlots.set(slot, stack.copy()); + } + +- public void setRemoteSlotNoCopy(int i, ItemStack itemstack) { +- if (i >= 0 && i < this.remoteSlots.size()) { +- this.remoteSlots.set(i, itemstack); ++ public void setRemoteSlotNoCopy(int slot, ItemStack stack) { ++ if (slot >= 0 && slot < this.remoteSlots.size()) { ++ this.remoteSlots.set(slot, stack); + } else { +- AbstractContainerMenu.LOGGER.debug("Incorrect slot index: {} available slots: {}", i, this.remoteSlots.size()); ++ AbstractContainerMenu.LOGGER.debug("Incorrect slot index: {} available slots: {}", slot, this.remoteSlots.size()); + } + } + +- public void setRemoteCarried(ItemStack itemstack) { +- this.remoteCarried = itemstack.copy(); ++ public void setRemoteCarried(ItemStack remoteCarried) { ++ this.remoteCarried = remoteCarried.copy(); + } + +- public boolean clickMenuButton(Player player, int i) { ++ public boolean clickMenuButton(Player player, int id) { + return false; + } + +- public Slot getSlot(int i) { +- return (Slot) this.slots.get(i); ++ public Slot getSlot(int slotId) { ++ return (Slot) this.slots.get(slotId); + } + + public abstract ItemStack quickMoveStack(Player player, int index); + +- public void clicked(int i, int j, ClickType clicktype, Player player) { ++ public void clicked(int slotId, int button, InventoryClickType clickType, Player player) { + try { +- this.doClick(i, j, clicktype, player); ++ this.doClick(slotId, button, clickType, player); + } catch (Exception exception) { + CrashReport crashreport = CrashReport.forThrowable(exception, "Container click"); +- CrashReportCategory crashreportcategory = crashreport.addCategory("Click info"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Click info"); + +- crashreportcategory.setDetail("Menu Type", () -> { ++ crashreportsystemdetails.setDetail("Menu Type", () -> { + return this.menuType != null ? BuiltInRegistries.MENU.getKey(this.menuType).toString() : ""; + }); +- crashreportcategory.setDetail("Menu Class", () -> { ++ crashreportsystemdetails.setDetail("Menu Class", () -> { + return this.getClass().getCanonicalName(); + }); +- crashreportcategory.setDetail("Slot Count", (Object) this.slots.size()); +- crashreportcategory.setDetail("Slot", (Object) i); +- crashreportcategory.setDetail("Button", (Object) j); +- crashreportcategory.setDetail("Type", (Object) clicktype); ++ crashreportsystemdetails.setDetail("Slot Count", (Object) this.slots.size()); ++ crashreportsystemdetails.setDetail("Slot", (Object) slotId); ++ crashreportsystemdetails.setDetail("Button", (Object) button); ++ crashreportsystemdetails.setDetail("Type", (Object) clickType); + throw new ReportedException(crashreport); + } + } + +- private void doClick(int i, int j, ClickType clicktype, Player player) { +- Inventory inventory = player.getInventory(); ++ private void doClick(int slotId, int button, InventoryClickType clickType, Player player) { ++ Inventory playerinventory = player.getInventory(); + Slot slot; + ItemStack itemstack; + int k; + ItemStack itemstack1; + int l; + +- if (clicktype == ClickType.QUICK_CRAFT) { ++ if (clickType == InventoryClickType.QUICK_CRAFT) { + int i1 = this.quickcraftStatus; + +- this.quickcraftStatus = getQuickcraftHeader(j); ++ this.quickcraftStatus = getQuickcraftHeader(button); + if ((i1 != 1 || this.quickcraftStatus != 2) && i1 != this.quickcraftStatus) { + this.resetQuickCraft(); + } else if (this.getCarried().isEmpty()) { + this.resetQuickCraft(); + } else if (this.quickcraftStatus == 0) { +- this.quickcraftType = getQuickcraftType(j); ++ this.quickcraftType = getQuickcraftType(button); + if (isValidQuickcraftType(this.quickcraftType, player)) { + this.quickcraftStatus = 1; + this.quickcraftSlots.clear(); +@@ -373,17 +417,17 @@ + this.resetQuickCraft(); + } + } else if (this.quickcraftStatus == 1) { +- slot = (Slot) this.slots.get(i); ++ slot = (Slot) this.slots.get(slotId); + itemstack = this.getCarried(); + if (canItemQuickReplace(slot, itemstack, true) && slot.mayPlace(itemstack) && (this.quickcraftType == 2 || itemstack.getCount() > this.quickcraftSlots.size()) && this.canDragTo(slot)) { + this.quickcraftSlots.add(slot); + } + } else if (this.quickcraftStatus == 2) { + if (!this.quickcraftSlots.isEmpty()) { +- if (this.quickcraftSlots.size() == 1) { ++ if (false && this.quickcraftSlots.size() == 1) { // CraftBukkit - treat everything as a drag since we are unable to easily call InventoryClickEvent instead + k = ((Slot) this.quickcraftSlots.iterator().next()).index; + this.resetQuickCraft(); +- this.doClick(k, this.quickcraftType, ClickType.PICKUP, player); ++ this.doClick(k, this.quickcraftType, InventoryClickType.PICKUP, player); + return; + } + +@@ -396,6 +440,7 @@ + l = this.getCarried().getCount(); + Iterator iterator = this.quickcraftSlots.iterator(); + ++ Map draggedSlots = new HashMap(); // CraftBukkit - Store slots from drag in map (raw slot id -> new stack) + while (iterator.hasNext()) { + Slot slot1 = (Slot) iterator.next(); + ItemStack itemstack2 = this.getCarried(); +@@ -406,12 +451,48 @@ + int l1 = Math.min(getQuickCraftPlaceCount(this.quickcraftSlots, this.quickcraftType, itemstack1) + j1, k1); + + l -= l1 - j1; +- slot1.setByPlayer(itemstack1.copyWithCount(l1)); ++ // slot1.setByPlayer(itemstack1.copyWithCount(l1)); ++ draggedSlots.put(slot1.index, itemstack1.copyWithCount(l1)); // CraftBukkit - Put in map instead of setting + } + } + +- itemstack1.setCount(l); +- this.setCarried(itemstack1); ++ // CraftBukkit start - InventoryDragEvent ++ InventoryView view = getBukkitView(); ++ org.bukkit.inventory.ItemStack newcursor = CraftItemStack.asCraftMirror(itemstack1); ++ newcursor.setAmount(l); ++ Map eventmap = new HashMap(); ++ for (Map.Entry ditem : draggedSlots.entrySet()) { ++ eventmap.put(ditem.getKey(), CraftItemStack.asBukkitCopy(ditem.getValue())); ++ } ++ ++ // It's essential that we set the cursor to the new value here to prevent item duplication if a plugin closes the inventory. ++ ItemStack oldCursor = this.getCarried(); ++ this.setCarried(CraftItemStack.asNMSCopy(newcursor)); ++ ++ InventoryDragEvent event = new InventoryDragEvent(view, (newcursor.getType() != org.bukkit.Material.AIR ? newcursor : null), CraftItemStack.asBukkitCopy(oldCursor), this.quickcraftType == 1, eventmap); ++ player.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ // Whether or not a change was made to the inventory that requires an update. ++ boolean needsUpdate = event.getResult() != Result.DEFAULT; ++ ++ if (event.getResult() != Result.DENY) { ++ for (Map.Entry dslot : draggedSlots.entrySet()) { ++ view.setItem(dslot.getKey(), CraftItemStack.asBukkitCopy(dslot.getValue())); ++ } ++ // The only time the carried item will be set to null is if the inventory is closed by the server. ++ // If the inventory is closed by the server, then the cursor items are dropped. This is why we change the cursor early. ++ if (this.getCarried() != null) { ++ this.setCarried(CraftItemStack.asNMSCopy(event.getCursor())); ++ needsUpdate = true; ++ } ++ } else { ++ this.setCarried(oldCursor); ++ } ++ ++ if (needsUpdate && player instanceof ServerPlayer) { ++ this.sendAllDataToRemote(); ++ } ++ // CraftBukkit end + } + + this.resetQuickCraft(); +@@ -423,37 +504,40 @@ + } else { + int i2; + +- if ((clicktype == ClickType.PICKUP || clicktype == ClickType.QUICK_MOVE) && (j == 0 || j == 1)) { +- ClickAction clickaction = j == 0 ? ClickAction.PRIMARY : ClickAction.SECONDARY; ++ if ((clickType == InventoryClickType.PICKUP || clickType == InventoryClickType.QUICK_MOVE) && (button == 0 || button == 1)) { ++ ClickAction clickaction = button == 0 ? ClickAction.PRIMARY : ClickAction.SECONDARY; + +- if (i == -999) { ++ if (slotId == -999) { + if (!this.getCarried().isEmpty()) { + if (clickaction == ClickAction.PRIMARY) { +- player.drop(this.getCarried(), true); ++ // CraftBukkit start ++ ItemStack carried = this.getCarried(); + this.setCarried(ItemStack.EMPTY); ++ player.drop(carried, true); ++ // CraftBukkit start + } else { + player.drop(this.getCarried().split(1), true); + } + } +- } else if (clicktype == ClickType.QUICK_MOVE) { +- if (i < 0) { ++ } else if (clickType == InventoryClickType.QUICK_MOVE) { ++ if (slotId < 0) { + return; + } + +- slot = (Slot) this.slots.get(i); ++ slot = (Slot) this.slots.get(slotId); + if (!slot.mayPickup(player)) { + return; + } + +- for (itemstack = this.quickMoveStack(player, i); !itemstack.isEmpty() && ItemStack.isSameItem(slot.getItem(), itemstack); itemstack = this.quickMoveStack(player, i)) { ++ for (itemstack = this.quickMoveStack(player, slotId); !itemstack.isEmpty() && ItemStack.isSameItem(slot.getItem(), itemstack); itemstack = this.quickMoveStack(player, slotId)) { + ; + } + } else { +- if (i < 0) { ++ if (slotId < 0) { + return; + } + +- slot = (Slot) this.slots.get(i); ++ slot = (Slot) this.slots.get(slotId); + itemstack = slot.getItem(); + ItemStack itemstack3 = this.getCarried(); + +@@ -493,19 +577,28 @@ + } + + slot.setChanged(); ++ // CraftBukkit start - Make sure the client has the right slot contents ++ if (player instanceof ServerPlayer && slot.getMaxStackSize() != 64) { ++ ((ServerPlayer) player).connection.send(new ClientboundContainerSetSlotPacket(this.containerId, this.incrementStateId(), slot.index, slot.getItem())); ++ // Updating a crafting inventory makes the client reset the result slot, have to send it again ++ if (this.getBukkitView().getType() == InventoryType.WORKBENCH || this.getBukkitView().getType() == InventoryType.CRAFTING) { ++ ((ServerPlayer) player).connection.send(new ClientboundContainerSetSlotPacket(this.containerId, this.incrementStateId(), 0, this.getSlot(0).getItem())); ++ } ++ } ++ // CraftBukkit end + } + } else { + int j2; + +- if (clicktype == ClickType.SWAP && (j >= 0 && j < 9 || j == 40)) { +- ItemStack itemstack4 = inventory.getItem(j); ++ if (clickType == InventoryClickType.SWAP && (button >= 0 && button < 9 || button == 40)) { ++ ItemStack itemstack4 = playerinventory.getItem(button); + +- slot = (Slot) this.slots.get(i); ++ slot = (Slot) this.slots.get(slotId); + itemstack = slot.getItem(); + if (!itemstack4.isEmpty() || !itemstack.isEmpty()) { + if (itemstack4.isEmpty()) { + if (slot.mayPickup(player)) { +- inventory.setItem(j, itemstack); ++ playerinventory.setItem(button, itemstack); + slot.onSwapCraft(itemstack.getCount()); + slot.setByPlayer(ItemStack.EMPTY); + slot.onTake(player, itemstack); +@@ -516,7 +609,7 @@ + if (itemstack4.getCount() > j2) { + slot.setByPlayer(itemstack4.split(j2)); + } else { +- inventory.setItem(j, ItemStack.EMPTY); ++ playerinventory.setItem(button, ItemStack.EMPTY); + slot.setByPlayer(itemstack4); + } + } +@@ -525,11 +618,11 @@ + if (itemstack4.getCount() > j2) { + slot.setByPlayer(itemstack4.split(j2)); + slot.onTake(player, itemstack); +- if (!inventory.add(itemstack)) { ++ if (!playerinventory.add(itemstack)) { + player.drop(itemstack, true); + } + } else { +- inventory.setItem(j, itemstack); ++ playerinventory.setItem(button, itemstack); + slot.setByPlayer(itemstack4); + slot.onTake(player, itemstack); + } +@@ -538,23 +631,23 @@ + } else { + Slot slot2; + +- if (clicktype == ClickType.CLONE && player.getAbilities().instabuild && this.getCarried().isEmpty() && i >= 0) { +- slot2 = (Slot) this.slots.get(i); ++ if (clickType == InventoryClickType.CLONE && player.getAbilities().instabuild && this.getCarried().isEmpty() && slotId >= 0) { ++ slot2 = (Slot) this.slots.get(slotId); + if (slot2.hasItem()) { + itemstack1 = slot2.getItem(); + this.setCarried(itemstack1.copyWithCount(itemstack1.getMaxStackSize())); + } +- } else if (clicktype == ClickType.THROW && this.getCarried().isEmpty() && i >= 0) { +- slot2 = (Slot) this.slots.get(i); +- k = j == 0 ? 1 : slot2.getItem().getCount(); ++ } else if (clickType == InventoryClickType.THROW && this.getCarried().isEmpty() && slotId >= 0) { ++ slot2 = (Slot) this.slots.get(slotId); ++ k = button == 0 ? 1 : slot2.getItem().getCount(); + itemstack = slot2.safeTake(k, Integer.MAX_VALUE, player); + player.drop(itemstack, true); +- } else if (clicktype == ClickType.PICKUP_ALL && i >= 0) { +- slot2 = (Slot) this.slots.get(i); ++ } else if (clickType == InventoryClickType.PICKUP_ALL && slotId >= 0) { ++ slot2 = (Slot) this.slots.get(slotId); + itemstack1 = this.getCarried(); + if (!itemstack1.isEmpty() && (!slot2.hasItem() || !slot2.mayPickup(player))) { +- l = j == 0 ? 0 : this.slots.size() - 1; +- j2 = j == 0 ? 1 : -1; ++ l = button == 0 ? 0 : this.slots.size() - 1; ++ j2 = button == 0 ? 1 : -1; + + for (i2 = 0; i2 < 2; ++i2) { + for (int k2 = l; k2 >= 0 && k2 < this.slots.size() && itemstack1.getCount() < itemstack1.getMaxStackSize(); k2 += j2) { +@@ -579,30 +672,28 @@ + + } + +- private boolean tryItemClickBehaviourOverride(Player player, ClickAction clickaction, Slot slot, ItemStack itemstack, ItemStack itemstack1) { ++ private boolean tryItemClickBehaviourOverride(Player player, ClickAction action, Slot slot, ItemStack clickedItem, ItemStack carriedItem) { + FeatureFlagSet featureflagset = player.level().enabledFeatures(); + +- return itemstack1.isItemEnabled(featureflagset) && itemstack1.overrideStackedOnOther(slot, clickaction, player) ? true : itemstack.isItemEnabled(featureflagset) && itemstack.overrideOtherStackedOnMe(itemstack1, slot, clickaction, player, this.createCarriedSlotAccess()); ++ return carriedItem.isItemEnabled(featureflagset) && carriedItem.overrideStackedOnOther(slot, action, player) ? true : clickedItem.isItemEnabled(featureflagset) && clickedItem.overrideOtherStackedOnMe(carriedItem, slot, action, player, this.createCarriedSlotAccess()); + } + + private SlotAccess createCarriedSlotAccess() { + return new SlotAccess() { + @Override +- @Override + public ItemStack get() { + return AbstractContainerMenu.this.getCarried(); + } + + @Override +- @Override +- public boolean set(ItemStack itemstack) { +- AbstractContainerMenu.this.setCarried(itemstack); ++ public boolean set(ItemStack carried) { ++ AbstractContainerMenu.this.setCarried(carried); + return true; + } + }; + } + +- public boolean canTakeItemForPickAll(ItemStack itemstack, Slot slot) { ++ public boolean canTakeItemForPickAll(ItemStack stack, Slot slot) { + return true; + } + +@@ -611,13 +702,14 @@ + ItemStack itemstack = this.getCarried(); + + if (!itemstack.isEmpty()) { ++ this.setCarried(ItemStack.EMPTY); // CraftBukkit - SPIGOT-4556 - from below + if (player.isAlive() && !((ServerPlayer) player).hasDisconnected()) { + player.getInventory().placeItemBackInInventory(itemstack); + } else { + player.drop(itemstack, false); + } + +- this.setCarried(ItemStack.EMPTY); ++ // this.setCarried(ItemStack.EMPTY); // CraftBukkit - moved up + } + } + +@@ -628,10 +720,10 @@ + + if (player.isAlive() && (!(player instanceof ServerPlayer) || !((ServerPlayer) player).hasDisconnected())) { + for (i = 0; i < container.getContainerSize(); ++i) { +- Inventory inventory = player.getInventory(); ++ Inventory playerinventory = player.getInventory(); + +- if (inventory.player instanceof ServerPlayer) { +- inventory.placeItemBackInInventory(container.removeItemNoUpdate(i)); ++ if (playerinventory.player instanceof ServerPlayer) { ++ playerinventory.placeItemBackInInventory(container.removeItemNoUpdate(i)); + } + } + +@@ -647,66 +739,66 @@ + this.broadcastChanges(); + } + +- public void setItem(int i, int j, ItemStack itemstack) { +- this.getSlot(i).set(itemstack); +- this.stateId = j; ++ public void setItem(int slotId, int stateId, ItemStack stack) { ++ this.getSlot(slotId).set(stack); ++ this.stateId = stateId; + } + +- public void initializeContents(int i, List list, ItemStack itemstack) { +- for (int j = 0; j < list.size(); ++j) { +- this.getSlot(j).set((ItemStack) list.get(j)); ++ public void initializeContents(int stateId, List items, ItemStack carried) { ++ for (int j = 0; j < items.size(); ++j) { ++ this.getSlot(j).set((ItemStack) items.get(j)); + } + +- this.carried = itemstack; +- this.stateId = i; ++ this.carried = carried; ++ this.stateId = stateId; + } + +- public void setData(int i, int j) { +- ((DataSlot) this.dataSlots.get(i)).set(j); ++ public void setData(int id, int data) { ++ ((DataSlot) this.dataSlots.get(id)).set(data); + } + + public abstract boolean stillValid(Player player); + +- protected boolean moveItemStackTo(ItemStack itemstack, int i, int j, boolean flag) { ++ protected boolean moveItemStackTo(ItemStack stack, int startIndex, int endIndex, boolean reverseDirection) { + boolean flag1 = false; +- int k = i; ++ int k = startIndex; + +- if (flag) { +- k = j - 1; ++ if (reverseDirection) { ++ k = endIndex - 1; + } + + Slot slot; + ItemStack itemstack1; + +- if (itemstack.isStackable()) { +- while (!itemstack.isEmpty()) { +- if (flag) { +- if (k < i) { ++ if (stack.isStackable()) { ++ while (!stack.isEmpty()) { ++ if (reverseDirection) { ++ if (k < startIndex) { + break; + } +- } else if (k >= j) { ++ } else if (k >= endIndex) { + break; + } + + slot = (Slot) this.slots.get(k); + itemstack1 = slot.getItem(); +- if (!itemstack1.isEmpty() && ItemStack.isSameItemSameTags(itemstack, itemstack1)) { +- int l = itemstack1.getCount() + itemstack.getCount(); ++ if (!itemstack1.isEmpty() && ItemStack.isSameItemSameTags(stack, itemstack1)) { ++ int l = itemstack1.getCount() + stack.getCount(); + +- if (l <= itemstack.getMaxStackSize()) { +- itemstack.setCount(0); ++ if (l <= stack.getMaxStackSize()) { ++ stack.setCount(0); + itemstack1.setCount(l); + slot.setChanged(); + flag1 = true; +- } else if (itemstack1.getCount() < itemstack.getMaxStackSize()) { +- itemstack.shrink(itemstack.getMaxStackSize() - itemstack1.getCount()); +- itemstack1.setCount(itemstack.getMaxStackSize()); ++ } else if (itemstack1.getCount() < stack.getMaxStackSize()) { ++ stack.shrink(stack.getMaxStackSize() - itemstack1.getCount()); ++ itemstack1.setCount(stack.getMaxStackSize()); + slot.setChanged(); + flag1 = true; + } + } + +- if (flag) { ++ if (reverseDirection) { + --k; + } else { + ++k; +@@ -714,29 +806,29 @@ + } + } + +- if (!itemstack.isEmpty()) { +- if (flag) { +- k = j - 1; ++ if (!stack.isEmpty()) { ++ if (reverseDirection) { ++ k = endIndex - 1; + } else { +- k = i; ++ k = startIndex; + } + + while (true) { +- if (flag) { +- if (k < i) { ++ if (reverseDirection) { ++ if (k < startIndex) { + break; + } +- } else if (k >= j) { ++ } else if (k >= endIndex) { + break; + } + + slot = (Slot) this.slots.get(k); + itemstack1 = slot.getItem(); +- if (itemstack1.isEmpty() && slot.mayPlace(itemstack)) { +- if (itemstack.getCount() > slot.getMaxStackSize()) { +- slot.setByPlayer(itemstack.split(slot.getMaxStackSize())); ++ if (itemstack1.isEmpty() && slot.mayPlace(stack)) { ++ if (stack.getCount() > slot.getMaxStackSize()) { ++ slot.setByPlayer(stack.split(slot.getMaxStackSize())); + } else { +- slot.setByPlayer(itemstack.split(itemstack.getCount())); ++ slot.setByPlayer(stack.split(stack.getCount())); + } + + slot.setChanged(); +@@ -744,7 +836,7 @@ + break; + } + +- if (flag) { ++ if (reverseDirection) { + --k; + } else { + ++k; +@@ -755,20 +847,20 @@ + return flag1; + } + +- public static int getQuickcraftType(int i) { +- return i >> 2 & 3; ++ public static int getQuickcraftType(int eventButton) { ++ return eventButton >> 2 & 3; + } + +- public static int getQuickcraftHeader(int i) { +- return i & 3; ++ public static int getQuickcraftHeader(int clickedButton) { ++ return clickedButton & 3; + } + +- public static int getQuickcraftMask(int i, int j) { +- return i & 3 | (j & 3) << 2; ++ public static int getQuickcraftMask(int quickCraftingHeader, int quickCraftingType) { ++ return quickCraftingHeader & 3 | (quickCraftingType & 3) << 2; + } + +- public static boolean isValidQuickcraftType(int i, Player player) { +- return i == 0 ? true : (i == 1 ? true : i == 2 && player.getAbilities().instabuild); ++ public static boolean isValidQuickcraftType(int dragMode, Player player) { ++ return dragMode == 0 ? true : (dragMode == 1 ? true : dragMode == 2 && player.getAbilities().instabuild); + } + + protected void resetQuickCraft() { +@@ -776,27 +868,27 @@ + this.quickcraftSlots.clear(); + } + +- public static boolean canItemQuickReplace(@Nullable Slot slot, ItemStack itemstack, boolean flag) { ++ public static boolean canItemQuickReplace(@Nullable Slot slot, ItemStack stack, boolean stackSizeMatters) { + boolean flag1 = slot == null || !slot.hasItem(); + +- return !flag1 && ItemStack.isSameItemSameTags(itemstack, slot.getItem()) ? slot.getItem().getCount() + (flag ? 0 : itemstack.getCount()) <= itemstack.getMaxStackSize() : flag1; ++ return !flag1 && ItemStack.isSameItemSameTags(stack, slot.getItem()) ? slot.getItem().getCount() + (stackSizeMatters ? 0 : stack.getCount()) <= stack.getMaxStackSize() : flag1; + } + +- public static int getQuickCraftPlaceCount(Set set, int i, ItemStack itemstack) { ++ public static int getQuickCraftPlaceCount(Set slots, int type, ItemStack stack) { + int j; + +- switch (i) { ++ switch (type) { + case 0: +- j = Mth.floor((float) itemstack.getCount() / (float) set.size()); ++ j = Mth.floor((float) stack.getCount() / (float) slots.size()); + break; + case 1: + j = 1; + break; + case 2: +- j = itemstack.getItem().getMaxStackSize(); ++ j = stack.getItem().getMaxStackSize(); + break; + default: +- j = itemstack.getCount(); ++ j = stack.getCount(); + } + + return j; +@@ -806,8 +898,8 @@ + return true; + } + +- public static int getRedstoneSignalFromBlockEntity(@Nullable BlockEntity blockentity) { +- return blockentity instanceof Container ? getRedstoneSignalFromContainer((Container) blockentity) : 0; ++ public static int getRedstoneSignalFromBlockEntity(@Nullable BlockEntity blockEntity) { ++ return blockEntity instanceof Container ? getRedstoneSignalFromContainer((Container) blockEntity) : 0; + } + + public static int getRedstoneSignalFromContainer(@Nullable Container container) { +@@ -829,11 +921,16 @@ + } + } + +- public void setCarried(ItemStack itemstack) { +- this.carried = itemstack; ++ public void setCarried(ItemStack stack) { ++ this.carried = stack; + } + + public ItemStack getCarried() { ++ // CraftBukkit start ++ if (this.carried.isEmpty()) { ++ this.setCarried(ItemStack.EMPTY); ++ } ++ // CraftBukkit end + return this.carried; + } + +@@ -845,14 +942,14 @@ + this.suppressRemoteUpdates = false; + } + +- public void transferState(AbstractContainerMenu abstractcontainermenu) { ++ public void transferState(AbstractContainerMenu menu) { + Table table = HashBasedTable.create(); + + Slot slot; + int i; + +- for (i = 0; i < abstractcontainermenu.slots.size(); ++i) { +- slot = (Slot) abstractcontainermenu.slots.get(i); ++ for (i = 0; i < menu.slots.size(); ++i) { ++ slot = (Slot) menu.slots.get(i); + table.put(slot.container, slot.getContainerSlot(), i); + } + +@@ -861,18 +958,18 @@ + Integer integer = (Integer) table.get(slot.container, slot.getContainerSlot()); + + if (integer != null) { +- this.lastSlots.set(i, (ItemStack) abstractcontainermenu.lastSlots.get(integer)); +- this.remoteSlots.set(i, (ItemStack) abstractcontainermenu.remoteSlots.get(integer)); ++ this.lastSlots.set(i, (ItemStack) menu.lastSlots.get(integer)); ++ this.remoteSlots.set(i, (ItemStack) menu.remoteSlots.get(integer)); + } + } + + } + +- public OptionalInt findSlot(Container container, int i) { ++ public OptionalInt findSlot(Container container, int slotIndex) { + for (int j = 0; j < this.slots.size(); ++j) { + Slot slot = (Slot) this.slots.get(j); + +- if (slot.container == container && i == slot.getContainerSlot()) { ++ if (slot.container == container && slotIndex == slot.getContainerSlot()) { + return OptionalInt.of(j); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/AbstractFurnaceMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/AbstractFurnaceMenu.java.patch new file mode 100644 index 0000000000..79f9e2ab8e --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/AbstractFurnaceMenu.java.patch @@ -0,0 +1,206 @@ +--- a/net/minecraft/world/inventory/AbstractFurnaceMenu.java ++++ b/net/minecraft/world/inventory/AbstractFurnaceMenu.java +@@ -13,6 +13,10 @@ + import net.minecraft.world.item.crafting.RecipeType; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryFurnace; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + + public abstract class AbstractFurnaceMenu extends RecipeBookMenu { + +@@ -31,107 +35,116 @@ + private final RecipeType recipeType; + private final RecipeBookType recipeBookType; + +- protected AbstractFurnaceMenu(MenuType menutype, RecipeType recipetype, RecipeBookType recipebooktype, int i, Inventory inventory) { +- this(menutype, recipetype, recipebooktype, i, inventory, new SimpleContainer(3), new SimpleContainerData(4)); ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryFurnace inventory = new CraftInventoryFurnace((AbstractFurnaceBlockEntity) this.container); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; + } ++ // CraftBukkit end + +- protected AbstractFurnaceMenu(MenuType menutype, RecipeType recipetype, RecipeBookType recipebooktype, int i, Inventory inventory, Container container, ContainerData containerdata) { +- super(menutype, i); +- this.recipeType = recipetype; +- this.recipeBookType = recipebooktype; ++ protected AbstractFurnaceMenu(MenuType menuType, RecipeType recipeType, RecipeBookType recipeBookType, int containerId, Inventory playerInventory) { ++ this(menuType, recipeType, recipeBookType, containerId, playerInventory, new SimpleContainer(3), new SimpleContainerData(4)); ++ } ++ ++ protected AbstractFurnaceMenu(MenuType menuType, RecipeType recipeType, RecipeBookType recipeBookType, int containerId, Inventory playerInventory, Container container, ContainerData data) { ++ super(menuType, containerId); ++ this.recipeType = recipeType; ++ this.recipeBookType = recipeBookType; + checkContainerSize(container, 3); +- checkContainerDataCount(containerdata, 4); ++ checkContainerDataCount(data, 4); + this.container = container; +- this.data = containerdata; +- this.level = inventory.player.level(); ++ this.data = data; ++ this.level = playerInventory.player.level(); + this.addSlot(new Slot(container, 0, 56, 17)); + this.addSlot(new FurnaceFuelSlot(this, container, 1, 56, 53)); +- this.addSlot(new FurnaceResultSlot(inventory.player, container, 2, 116, 35)); ++ this.addSlot(new FurnaceResultSlot(playerInventory.player, container, 2, 116, 35)); ++ this.player = playerInventory; // CraftBukkit - save player + + int j; + + for (j = 0; j < 3; ++j) { + for (int k = 0; k < 9; ++k) { +- this.addSlot(new Slot(inventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); + } + } + + for (j = 0; j < 9; ++j) { +- this.addSlot(new Slot(inventory, j, 8 + j * 18, 142)); ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } + +- this.addDataSlots(containerdata); ++ this.addDataSlots(data); + } + + @Override +- @Override +- public void fillCraftSlotsStackedContents(StackedContents stackedcontents) { ++ public void fillCraftSlotsStackedContents(StackedContents itemHelper) { + if (this.container instanceof StackedContentsCompatible) { +- ((StackedContentsCompatible) this.container).fillStackedContents(stackedcontents); ++ ((StackedContentsCompatible) this.container).fillStackedContents(itemHelper); + } + + } + + @Override +- @Override + public void clearCraftingContent() { + this.getSlot(0).set(ItemStack.EMPTY); + this.getSlot(2).set(ItemStack.EMPTY); + } + + @Override +- @Override + public boolean recipeMatches(RecipeHolder> recipeholder) { + return recipeholder.value().matches(this.container, this.level); + } + + @Override +- @Override + public int getResultSlotIndex() { + return 2; + } + + @Override +- @Override + public int getGridWidth() { + return 1; + } + + @Override +- @Override + public int getGridHeight() { + return 1; + } + + @Override +- @Override + public int getSize() { + return 3; + } + + @Override +- @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(player); + } + + @Override +- @Override +- public ItemStack quickMoveStack(Player player, int i) { ++ public ItemStack quickMoveStack(Player player, int index) { + ItemStack itemstack = ItemStack.EMPTY; +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = (Slot) this.slots.get(index); + + if (slot != null && slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); + + itemstack = itemstack1.copy(); +- if (i == 2) { ++ if (index == 2) { + if (!this.moveItemStackTo(itemstack1, 3, 39, true)) { + return ItemStack.EMPTY; + } + + slot.onQuickCraft(itemstack1, itemstack); +- } else if (i != 1 && i != 0) { ++ } else if (index != 1 && index != 0) { + if (this.canSmelt(itemstack1)) { + if (!this.moveItemStackTo(itemstack1, 0, 1, false)) { + return ItemStack.EMPTY; +@@ -140,11 +153,11 @@ + if (!this.moveItemStackTo(itemstack1, 1, 2, false)) { + return ItemStack.EMPTY; + } +- } else if (i >= 3 && i < 30) { ++ } else if (index >= 3 && index < 30) { + if (!this.moveItemStackTo(itemstack1, 30, 39, false)) { + return ItemStack.EMPTY; + } +- } else if (i >= 30 && i < 39 && !this.moveItemStackTo(itemstack1, 3, 30, false)) { ++ } else if (index >= 30 && index < 39 && !this.moveItemStackTo(itemstack1, 3, 30, false)) { + return ItemStack.EMPTY; + } + } else if (!this.moveItemStackTo(itemstack1, 3, 39, false)) { +@@ -167,12 +180,12 @@ + return itemstack; + } + +- protected boolean canSmelt(ItemStack itemstack) { +- return this.level.getRecipeManager().getRecipeFor(this.recipeType, new SimpleContainer(new ItemStack[]{itemstack}), this.level).isPresent(); ++ protected boolean canSmelt(ItemStack stack) { ++ return this.level.getRecipeManager().getRecipeFor((RecipeType) this.recipeType, new SimpleContainer(new ItemStack[]{stack}), this.level).isPresent(); // Eclipse fail + } + +- protected boolean isFuel(ItemStack itemstack) { +- return AbstractFurnaceBlockEntity.isFuel(itemstack); ++ protected boolean isFuel(ItemStack stack) { ++ return AbstractFurnaceBlockEntity.isFuel(stack); + } + + public float getBurnProgress() { +@@ -197,14 +210,12 @@ + } + + @Override +- @Override + public RecipeBookType getRecipeBookType() { + return this.recipeBookType; + } + + @Override +- @Override +- public boolean shouldMoveToInventory(int i) { +- return i != 1; ++ public boolean shouldMoveToInventory(int slotIndex) { ++ return slotIndex != 1; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/AnvilMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/AnvilMenu.java.patch new file mode 100644 index 0000000000..32ada24941 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/AnvilMenu.java.patch @@ -0,0 +1,240 @@ +--- a/net/minecraft/world/inventory/AnvilMenu.java ++++ b/net/minecraft/world/inventory/AnvilMenu.java +@@ -16,9 +16,13 @@ + import net.minecraft.world.item.enchantment.Enchantment; + import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.level.block.AnvilBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class AnvilMenu extends ItemCombinerMenu { + + public static final int INPUT_SLOT = 0; +@@ -27,10 +31,10 @@ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final boolean DEBUG_COST = false; + public static final int MAX_NAME_LENGTH = 50; +- private int repairItemCountCost; ++ public int repairItemCountCost; + @Nullable +- private String itemName; +- private final DataSlot cost; ++ public String itemName; ++ public final DataSlot cost; + private static final int COST_FAIL = 0; + private static final int COST_BASE = 1; + private static final int COST_ADDED_BASE = 1; +@@ -42,19 +46,23 @@ + private static final int ADDITIONAL_SLOT_X_PLACEMENT = 76; + private static final int RESULT_SLOT_X_PLACEMENT = 134; + private static final int SLOT_Y_PLACEMENT = 47; ++ // CraftBukkit start ++ public static final int DEFAULT_DENIED_COST = -1; ++ public int maximumRepairCost = 40; ++ private CraftInventoryView bukkitEntity; ++ // CraftBukkit end + +- public AnvilMenu(int i, Inventory inventory) { +- this(i, inventory, ContainerLevelAccess.NULL); ++ public AnvilMenu(int containerId, Inventory playerInventory) { ++ this(containerId, playerInventory, ContainerLevelAccess.NULL); + } + +- public AnvilMenu(int i, Inventory inventory, ContainerLevelAccess containerlevelaccess) { +- super(MenuType.ANVIL, i, inventory, containerlevelaccess); ++ public AnvilMenu(int containerId, Inventory playerInventory, ContainerLevelAccess access) { ++ super(MenuType.ANVIL, containerId, playerInventory, access); + this.cost = DataSlot.standalone(); + this.addDataSlot(this.cost); + } + + @Override +- @Override + protected ItemCombinerMenuSlotDefinition createInputSlotDefinitions() { + return ItemCombinerMenuSlotDefinition.create().withSlot(0, 27, 47, (itemstack) -> { + return true; +@@ -64,20 +72,17 @@ + } + + @Override +- @Override +- protected boolean isValidBlock(BlockState blockstate) { +- return blockstate.is(BlockTags.ANVIL); ++ protected boolean isValidBlock(IBlockData state) { ++ return state.is(BlockTags.ANVIL); + } + + @Override +- @Override +- protected boolean mayPickup(Player player, boolean flag) { +- return (player.getAbilities().instabuild || player.experienceLevel >= this.cost.get()) && this.cost.get() > 0; ++ protected boolean mayPickup(Player player, boolean hasStack) { ++ return (player.getAbilities().instabuild || player.experienceLevel >= this.cost.get()) && this.cost.get() > AnvilMenu.DEFAULT_DENIED_COST && hasStack; // CraftBukkit - allow cost 0 like a free item + } + + @Override +- @Override +- protected void onTake(Player player, ItemStack itemstack) { ++ protected void onTake(Player player, ItemStack stack) { + if (!player.getAbilities().instabuild) { + player.giveExperienceLevels(-this.cost.get()); + } +@@ -96,29 +101,28 @@ + this.inputSlots.setItem(1, ItemStack.EMPTY); + } + +- this.cost.set(0); +- this.access.execute((level, blockpos) -> { +- BlockState blockstate = level.getBlockState(blockpos); ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item ++ this.access.execute((world, blockposition) -> { ++ IBlockData iblockdata = world.getBlockState(blockposition); + +- if (!player.getAbilities().instabuild && blockstate.is(BlockTags.ANVIL) && player.getRandom().nextFloat() < 0.12F) { +- BlockState blockstate1 = AnvilBlock.damage(blockstate); ++ if (!player.getAbilities().instabuild && iblockdata.is(BlockTags.ANVIL) && player.getRandom().nextFloat() < 0.12F) { ++ IBlockData iblockdata1 = AnvilBlock.damage(iblockdata); + +- if (blockstate1 == null) { +- level.removeBlock(blockpos, false); +- level.levelEvent(1029, blockpos, 0); ++ if (iblockdata1 == null) { ++ world.removeBlock(blockposition, false); ++ world.levelEvent(1029, blockposition, 0); + } else { +- level.setBlock(blockpos, blockstate1, 2); +- level.levelEvent(1030, blockpos, 0); ++ world.setBlock(blockposition, iblockdata1, 2); ++ world.levelEvent(1030, blockposition, 0); + } + } else { +- level.levelEvent(1030, blockpos, 0); ++ world.levelEvent(1030, blockposition, 0); + } + + }); + } + + @Override +- @Override + public void createResult() { + ItemStack itemstack = this.inputSlots.getItem(0); + +@@ -128,8 +132,8 @@ + byte b1 = 0; + + if (itemstack.isEmpty()) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- this.cost.set(0); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + } else { + ItemStack itemstack1 = itemstack.copy(); + ItemStack itemstack2 = this.inputSlots.getItem(1); +@@ -146,8 +150,8 @@ + if (itemstack1.isDamageableItem() && itemstack1.getItem().isValidRepairItem(itemstack, itemstack2)) { + k = Math.min(itemstack1.getDamageValue(), itemstack1.getMaxDamage() / 4); + if (k <= 0) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- this.cost.set(0); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + return; + } + +@@ -161,8 +165,8 @@ + this.repairItemCountCost = i1; + } else { + if (!flag && (!itemstack1.is(itemstack2.getItem()) || !itemstack1.isDamageableItem())) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- this.cost.set(0); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + return; + } + +@@ -251,8 +255,8 @@ + } + + if (flag2 && !flag1) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- this.cost.set(0); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + return; + } + } +@@ -275,11 +279,11 @@ + itemstack1 = ItemStack.EMPTY; + } + +- if (b1 == i && b1 > 0 && this.cost.get() >= 40) { +- this.cost.set(39); ++ if (b1 == i && b1 > 0 && this.cost.get() >= maximumRepairCost) { // CraftBukkit ++ this.cost.set(maximumRepairCost - 1); // CraftBukkit + } + +- if (this.cost.get() >= 40 && !this.player.getAbilities().instabuild) { ++ if (this.cost.get() >= maximumRepairCost && !this.player.getAbilities().instabuild) { // CraftBukkit + itemstack1 = ItemStack.EMPTY; + } + +@@ -298,17 +302,18 @@ + EnchantmentHelper.setEnchantments(map, itemstack1); + } + +- this.resultSlots.setItem(0, itemstack1); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), itemstack1); // CraftBukkit ++ sendAllDataToRemote(); // CraftBukkit - SPIGOT-6686: Always send completed inventory to stay in sync with client + this.broadcastChanges(); + } + } + +- public static int calculateIncreasedRepairCost(int i) { +- return i * 2 + 1; ++ public static int calculateIncreasedRepairCost(int oldRepairCost) { ++ return oldRepairCost * 2 + 1; + } + +- public boolean setItemName(String s) { +- String s1 = validateName(s); ++ public boolean setItemName(String itemName) { ++ String s1 = validateName(itemName); + + if (s1 != null && !s1.equals(this.itemName)) { + this.itemName = s1; +@@ -330,8 +335,8 @@ + } + + @Nullable +- private static String validateName(String s) { +- String s1 = SharedConstants.filterText(s); ++ private static String validateName(String itemName) { ++ String s1 = SharedConstants.filterText(itemName); + + return s1.length() <= 50 ? s1 : null; + } +@@ -339,4 +344,18 @@ + public int getCost() { + return this.cost.get(); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventory inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryAnvil( ++ access.getLocation(), this.inputSlots, this.resultSlots, this); ++ bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/BeaconMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/BeaconMenu.java.patch new file mode 100644 index 0000000000..75fbc4e670 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/BeaconMenu.java.patch @@ -0,0 +1,185 @@ +--- a/net/minecraft/world/inventory/BeaconMenu.java ++++ b/net/minecraft/world/inventory/BeaconMenu.java +@@ -7,10 +7,13 @@ + import net.minecraft.world.Container; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.effect.MobEffect; ++import net.minecraft.world.entity.player.Inventory; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + + public class BeaconMenu extends AbstractContainerMenu { + +@@ -26,32 +29,35 @@ + private final BeaconMenu.PaymentSlot paymentSlot; + private final ContainerLevelAccess access; + private final ContainerData beaconData; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ // CraftBukkit end + +- public BeaconMenu(int i, Container container) { +- this(i, container, new SimpleContainerData(3), ContainerLevelAccess.NULL); ++ public BeaconMenu(int containerId, Container container) { ++ this(containerId, container, new SimpleContainerData(3), ContainerLevelAccess.NULL); + } + +- public BeaconMenu(int i, Container container, ContainerData containerdata, ContainerLevelAccess containerlevelaccess) { +- super(MenuType.BEACON, i); ++ public BeaconMenu(int containerId, Container container, ContainerData beaconData, ContainerLevelAccess access) { ++ super(MenuType.BEACON, containerId); ++ player = (Inventory) container; // CraftBukkit - TODO: check this + this.beacon = new SimpleContainer(1) { + @Override +- @Override +- public boolean canPlaceItem(int j, ItemStack itemstack) { +- return itemstack.is(ItemTags.BEACON_PAYMENT_ITEMS); ++ public boolean canPlaceItem(int index, ItemStack stack) { ++ return stack.is(ItemTags.BEACON_PAYMENT_ITEMS); + } + + @Override +- @Override + public int getMaxStackSize() { + return 1; + } + }; +- checkContainerDataCount(containerdata, 3); +- this.beaconData = containerdata; +- this.access = containerlevelaccess; ++ checkContainerDataCount(beaconData, 3); ++ this.beaconData = beaconData; ++ this.access = access; + this.paymentSlot = new BeaconMenu.PaymentSlot(this.beacon, 0, 136, 110); + this.addSlot(this.paymentSlot); +- this.addDataSlots(containerdata); ++ this.addDataSlots(beaconData); + boolean flag = true; + boolean flag1 = true; + +@@ -70,7 +76,6 @@ + } + + @Override +- @Override + public void removed(Player player) { + super.removed(player); + if (!player.level().isClientSide) { +@@ -84,29 +89,27 @@ + } + + @Override +- @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.BEACON); + } + + @Override +- @Override +- public void setData(int i, int j) { +- super.setData(i, j); ++ public void setData(int id, int data) { ++ super.setData(id, data); + this.broadcastChanges(); + } + + @Override +- @Override +- public ItemStack quickMoveStack(Player player, int i) { ++ public ItemStack quickMoveStack(Player player, int index) { + ItemStack itemstack = ItemStack.EMPTY; +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = (Slot) this.slots.get(index); + + if (slot != null && slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); + + itemstack = itemstack1.copy(); +- if (i == 0) { ++ if (index == 0) { + if (!this.moveItemStackTo(itemstack1, 1, 37, true)) { + return ItemStack.EMPTY; + } +@@ -116,11 +119,11 @@ + if (!this.moveItemStackTo(itemstack1, 0, 1, false)) { + return ItemStack.EMPTY; + } +- } else if (i >= 1 && i < 28) { ++ } else if (index >= 1 && index < 28) { + if (!this.moveItemStackTo(itemstack1, 28, 37, false)) { + return ItemStack.EMPTY; + } +- } else if (i >= 28 && i < 37) { ++ } else if (index >= 28 && index < 37) { + if (!this.moveItemStackTo(itemstack1, 1, 28, false)) { + return ItemStack.EMPTY; + } +@@ -148,8 +151,8 @@ + return this.beaconData.get(0); + } + +- public static int encodeEffect(@Nullable MobEffect mobeffect) { +- return mobeffect == null ? 0 : BuiltInRegistries.MOB_EFFECT.getId(mobeffect) + 1; ++ public static int encodeEffect(@Nullable MobEffect mobeffectlist) { ++ return mobeffectlist == null ? 0 : BuiltInRegistries.MOB_EFFECT.getId(mobeffectlist) + 1; + } + + @Nullable +@@ -167,10 +170,10 @@ + return decodeEffect(this.beaconData.get(2)); + } + +- public void updateEffects(Optional optional, Optional optional1) { ++ public void updateEffects(Optional primaryEffect, Optional secondaryEffect) { + if (this.paymentSlot.hasItem()) { +- this.beaconData.set(1, encodeEffect((MobEffect) optional.orElse((Object) null))); +- this.beaconData.set(2, encodeEffect((MobEffect) optional1.orElse((Object) null))); ++ this.beaconData.set(1, encodeEffect((MobEffect) primaryEffect.orElse(null))); // CraftBukkit - decompile error ++ this.beaconData.set(2, encodeEffect((MobEffect) secondaryEffect.orElse(null))); // CraftBukkit - decompile error + this.paymentSlot.remove(1); + this.access.execute(Level::blockEntityChanged); + } +@@ -183,20 +186,31 @@ + + private class PaymentSlot extends Slot { + +- public PaymentSlot(Container container, int i, int j, int k) { +- super(container, i, j, k); ++ public PaymentSlot(Container container, int slot, int x, int y) { ++ super(container, slot, x, y); + } + + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { +- return itemstack.is(ItemTags.BEACON_PAYMENT_ITEMS); ++ public boolean mayPlace(ItemStack stack) { ++ return stack.is(ItemTags.BEACON_PAYMENT_ITEMS); + } + + @Override +- @Override + public int getMaxStackSize() { + return 1; + } + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventory inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryBeacon(this.beacon); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/BrewingStandMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/BrewingStandMenu.java.patch new file mode 100644 index 0000000000..9f079153d1 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/BrewingStandMenu.java.patch @@ -0,0 +1,220 @@ +--- a/net/minecraft/world/inventory/BrewingStandMenu.java ++++ b/net/minecraft/world/inventory/BrewingStandMenu.java +@@ -12,6 +12,10 @@ + import net.minecraft.world.item.alchemy.Potion; + import net.minecraft.world.item.alchemy.PotionBrewing; + import net.minecraft.world.item.alchemy.PotionUtils; ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryBrewer; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + + public class BrewingStandMenu extends AbstractContainerMenu { + +@@ -29,54 +33,59 @@ + private final ContainerData brewingStandData; + private final Slot ingredientSlot; + +- public BrewingStandMenu(int i, Inventory inventory) { +- this(i, inventory, new SimpleContainer(5), new SimpleContainerData(2)); ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ // CraftBukkit end ++ ++ public BrewingStandMenu(int containerId, Inventory playerInventory) { ++ this(containerId, playerInventory, new SimpleContainer(5), new SimpleContainerData(2)); + } + +- public BrewingStandMenu(int i, Inventory inventory, Container container, ContainerData containerdata) { +- super(MenuType.BREWING_STAND, i); +- checkContainerSize(container, 5); +- checkContainerDataCount(containerdata, 2); +- this.brewingStand = container; +- this.brewingStandData = containerdata; +- this.addSlot(new BrewingStandMenu.PotionSlot(container, 0, 56, 51)); +- this.addSlot(new BrewingStandMenu.PotionSlot(container, 1, 79, 58)); +- this.addSlot(new BrewingStandMenu.PotionSlot(container, 2, 102, 51)); +- this.ingredientSlot = this.addSlot(new BrewingStandMenu.IngredientsSlot(container, 3, 79, 17)); +- this.addSlot(new BrewingStandMenu.FuelSlot(container, 4, 17, 17)); +- this.addDataSlots(containerdata); ++ public BrewingStandMenu(int containerId, Inventory playerInventory, Container brewingStandContainer, ContainerData brewingStandData) { ++ super(MenuType.BREWING_STAND, containerId); ++ player = playerInventory; // CraftBukkit ++ checkContainerSize(brewingStandContainer, 5); ++ checkContainerDataCount(brewingStandData, 2); ++ this.brewingStand = brewingStandContainer; ++ this.brewingStandData = brewingStandData; ++ this.addSlot(new BrewingStandMenu.PotionSlot(brewingStandContainer, 0, 56, 51)); ++ this.addSlot(new BrewingStandMenu.PotionSlot(brewingStandContainer, 1, 79, 58)); ++ this.addSlot(new BrewingStandMenu.PotionSlot(brewingStandContainer, 2, 102, 51)); ++ this.ingredientSlot = this.addSlot(new BrewingStandMenu.IngredientsSlot(brewingStandContainer, 3, 79, 17)); ++ this.addSlot(new BrewingStandMenu.FuelSlot(brewingStandContainer, 4, 17, 17)); ++ this.addDataSlots(brewingStandData); + + int j; + + for (j = 0; j < 3; ++j) { + for (int k = 0; k < 9; ++k) { +- this.addSlot(new Slot(inventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); + } + } + + for (j = 0; j < 9; ++j) { +- this.addSlot(new Slot(inventory, j, 8 + j * 18, 142)); ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } + + } + + @Override +- @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.brewingStand.stillValid(player); + } + + @Override +- @Override +- public ItemStack quickMoveStack(Player player, int i) { ++ public ItemStack quickMoveStack(Player player, int index) { + ItemStack itemstack = ItemStack.EMPTY; +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = (Slot) this.slots.get(index); + + if (slot != null && slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); + + itemstack = itemstack1.copy(); +- if ((i < 0 || i > 2) && i != 3 && i != 4) { ++ if ((index < 0 || index > 2) && index != 3 && index != 4) { + if (BrewingStandMenu.FuelSlot.mayPlaceItem(itemstack)) { + if (this.moveItemStackTo(itemstack1, 4, 5, false) || this.ingredientSlot.mayPlace(itemstack1) && !this.moveItemStackTo(itemstack1, 3, 4, false)) { + return ItemStack.EMPTY; +@@ -89,11 +98,11 @@ + if (!this.moveItemStackTo(itemstack1, 0, 3, false)) { + return ItemStack.EMPTY; + } +- } else if (i >= 5 && i < 32) { ++ } else if (index >= 5 && index < 32) { + if (!this.moveItemStackTo(itemstack1, 32, 41, false)) { + return ItemStack.EMPTY; + } +- } else if (i >= 32 && i < 41) { ++ } else if (index >= 32 && index < 41) { + if (!this.moveItemStackTo(itemstack1, 5, 32, false)) { + return ItemStack.EMPTY; + } +@@ -134,53 +143,48 @@ + + private static class PotionSlot extends Slot { + +- public PotionSlot(Container container, int i, int j, int k) { +- super(container, i, j, k); ++ public PotionSlot(Container container, int slot, int x, int y) { ++ super(container, slot, x, y); + } + + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { +- return mayPlaceItem(itemstack); ++ public boolean mayPlace(ItemStack stack) { ++ return mayPlaceItem(stack); + } + + @Override +- @Override + public int getMaxStackSize() { + return 1; + } + + @Override +- @Override +- public void onTake(Player player, ItemStack itemstack) { +- Potion potion = PotionUtils.getPotion(itemstack); ++ public void onTake(Player player, ItemStack stack) { ++ Potion potionregistry = PotionUtils.getPotion(stack); + + if (player instanceof ServerPlayer) { +- CriteriaTriggers.BREWED_POTION.trigger((ServerPlayer) player, (Holder) potion.builtInRegistryHolder()); ++ CriteriaTriggers.BREWED_POTION.trigger((ServerPlayer) player, (Holder) potionregistry.builtInRegistryHolder()); + } + +- super.onTake(player, itemstack); ++ super.onTake(player, stack); + } + +- public static boolean mayPlaceItem(ItemStack itemstack) { +- return itemstack.is(Items.POTION) || itemstack.is(Items.SPLASH_POTION) || itemstack.is(Items.LINGERING_POTION) || itemstack.is(Items.GLASS_BOTTLE); ++ public static boolean mayPlaceItem(ItemStack stack) { ++ return stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE); + } + } + + private static class IngredientsSlot extends Slot { + +- public IngredientsSlot(Container container, int i, int j, int k) { +- super(container, i, j, k); ++ public IngredientsSlot(Container container, int slot, int x, int y) { ++ super(container, slot, x, y); + } + + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { +- return PotionBrewing.isIngredient(itemstack); ++ public boolean mayPlace(ItemStack stack) { ++ return PotionBrewing.isIngredient(stack); + } + + @Override +- @Override + public int getMaxStackSize() { + return 64; + } +@@ -188,24 +192,35 @@ + + private static class FuelSlot extends Slot { + +- public FuelSlot(Container container, int i, int j, int k) { +- super(container, i, j, k); ++ public FuelSlot(Container container, int slot, int x, int y) { ++ super(container, slot, x, y); + } + + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { +- return mayPlaceItem(itemstack); ++ public boolean mayPlace(ItemStack stack) { ++ return mayPlaceItem(stack); + } + +- public static boolean mayPlaceItem(ItemStack itemstack) { +- return itemstack.is(Items.BLAZE_POWDER); ++ public static boolean mayPlaceItem(ItemStack itemStack) { ++ return itemStack.is(Items.BLAZE_POWDER); + } + + @Override +- @Override + public int getMaxStackSize() { + return 64; + } + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryBrewer inventory = new CraftInventoryBrewer(this.brewingStand); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/CartographyTableMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/CartographyTableMenu.java.patch new file mode 100644 index 0000000000..aa95522d8f --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/CartographyTableMenu.java.patch @@ -0,0 +1,275 @@ +--- a/net/minecraft/world/inventory/CartographyTableMenu.java ++++ b/net/minecraft/world/inventory/CartographyTableMenu.java +@@ -5,15 +5,35 @@ + import net.minecraft.world.Container; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.entity.player.Inventory; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.item.MapItem; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.saveddata.maps.MapItemSavedData; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.inventory.CraftInventoryCartography; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class CartographyTableMenu extends AbstractContainerMenu { + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryCartography inventory = new CraftInventoryCartography(this.container, this.resultContainer); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + public static final int MAP_SLOT = 0; + public static final int ADDITIONAL_SLOT = 1; + public static final int RESULT_SLOT = 2; +@@ -26,66 +46,74 @@ + public final Container container; + private final ResultContainer resultContainer; + +- public CartographyTableMenu(int i, Inventory inventory) { +- this(i, inventory, ContainerLevelAccess.NULL); ++ public CartographyTableMenu(int containerId, Inventory playerInventory) { ++ this(containerId, playerInventory, ContainerLevelAccess.NULL); + } + +- public CartographyTableMenu(int i, Inventory inventory, final ContainerLevelAccess containerlevelaccess) { +- super(MenuType.CARTOGRAPHY_TABLE, i); ++ public CartographyTableMenu(int containerId, Inventory playerInventory, final ContainerLevelAccess access) { ++ super(MenuType.CARTOGRAPHY_TABLE, containerId); + this.container = new SimpleContainer(2) { + @Override +- @Override + public void setChanged() { + CartographyTableMenu.this.slotsChanged(this); + super.setChanged(); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end + }; + this.resultContainer = new ResultContainer() { + @Override +- @Override + public void setChanged() { + CartographyTableMenu.this.slotsChanged(this); + super.setChanged(); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end + }; +- this.access = containerlevelaccess; ++ this.access = access; + this.addSlot(new Slot(this.container, 0, 15, 15) { + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { +- return itemstack.is(Items.FILLED_MAP); ++ public boolean mayPlace(ItemStack stack) { ++ return stack.is(Items.FILLED_MAP); + } + }); + this.addSlot(new Slot(this.container, 1, 15, 52) { + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { +- return itemstack.is(Items.PAPER) || itemstack.is(Items.MAP) || itemstack.is(Items.GLASS_PANE); ++ public boolean mayPlace(ItemStack stack) { ++ return stack.is(Items.PAPER) || stack.is(Items.MAP) || stack.is(Items.GLASS_PANE); + } + }); + this.addSlot(new Slot(this.resultContainer, 2, 145, 39) { + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { ++ public boolean mayPlace(ItemStack stack) { + return false; + } + + @Override +- @Override +- public void onTake(Player player, ItemStack itemstack) { ++ public void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) { + ((Slot) CartographyTableMenu.this.slots.get(0)).remove(1); + ((Slot) CartographyTableMenu.this.slots.get(1)).remove(1); +- itemstack.getItem().onCraftedBy(itemstack, player.level(), player); +- containerlevelaccess.execute((level, blockpos) -> { +- long j = level.getGameTime(); ++ stack.getItem().onCraftedBy(stack, player.level(), player); ++ access.execute((world, blockposition) -> { ++ long j = world.getGameTime(); + + if (CartographyTableMenu.this.lastSoundTime != j) { +- level.playSound((Player) null, blockpos, SoundEvents.UI_CARTOGRAPHY_TABLE_TAKE_RESULT, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.playSound((net.minecraft.world.entity.player.Player) null, blockposition, SoundEvents.UI_CARTOGRAPHY_TABLE_TAKE_RESULT, SoundSource.BLOCKS, 1.0F, 1.0F); + CartographyTableMenu.this.lastSoundTime = j; + } + + }); +- super.onTake(player, itemstack); ++ super.onTake(player, stack); + } + }); + +@@ -93,25 +121,25 @@ + + for (j = 0; j < 3; ++j) { + for (int k = 0; k < 9; ++k) { +- this.addSlot(new Slot(inventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); + } + } + + for (j = 0; j < 9; ++j) { +- this.addSlot(new Slot(inventory, j, 8 + j * 18, 142)); ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } + ++ player = (Player) playerInventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override +- @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.CARTOGRAPHY_TABLE); + } + + @Override +- @Override +- public void slotsChanged(Container container) { ++ public void slotsChanged(Container inventory) { + ItemStack itemstack = this.container.getItem(0); + ItemStack itemstack1 = this.container.getItem(1); + ItemStack itemstack2 = this.resultContainer.getItem(2); +@@ -124,33 +152,33 @@ + + } + +- private void setupResultSlot(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2) { +- this.access.execute((level, blockpos) -> { +- MapItemSavedData mapitemsaveddata = MapItem.getSavedData(itemstack, level); ++ private void setupResultSlot(ItemStack map, ItemStack firstSlotStack, ItemStack resultOutput) { ++ this.access.execute((world, blockposition) -> { ++ MapItemSavedData worldmap = MapItem.getSavedData(map, world); + +- if (mapitemsaveddata != null) { ++ if (worldmap != null) { + ItemStack itemstack3; + +- if (itemstack1.is(Items.PAPER) && !mapitemsaveddata.locked && mapitemsaveddata.scale < 4) { +- itemstack3 = itemstack.copyWithCount(1); ++ if (firstSlotStack.is(Items.PAPER) && !worldmap.locked && worldmap.scale < 4) { ++ itemstack3 = map.copyWithCount(1); + itemstack3.getOrCreateTag().putInt("map_scale_direction", 1); + this.broadcastChanges(); +- } else if (itemstack1.is(Items.GLASS_PANE) && !mapitemsaveddata.locked) { +- itemstack3 = itemstack.copyWithCount(1); ++ } else if (firstSlotStack.is(Items.GLASS_PANE) && !worldmap.locked) { ++ itemstack3 = map.copyWithCount(1); + itemstack3.getOrCreateTag().putBoolean("map_to_lock", true); + this.broadcastChanges(); + } else { +- if (!itemstack1.is(Items.MAP)) { ++ if (!firstSlotStack.is(Items.MAP)) { + this.resultContainer.removeItemNoUpdate(2); + this.broadcastChanges(); + return; + } + +- itemstack3 = itemstack.copyWithCount(2); ++ itemstack3 = map.copyWithCount(2); + this.broadcastChanges(); + } + +- if (!ItemStack.matches(itemstack3, itemstack2)) { ++ if (!ItemStack.matches(itemstack3, resultOutput)) { + this.resultContainer.setItem(2, itemstack3); + this.broadcastChanges(); + } +@@ -160,39 +188,37 @@ + } + + @Override +- @Override +- public boolean canTakeItemForPickAll(ItemStack itemstack, Slot slot) { +- return slot.container != this.resultContainer && super.canTakeItemForPickAll(itemstack, slot); ++ public boolean canTakeItemForPickAll(ItemStack stack, Slot slot) { ++ return slot.container != this.resultContainer && super.canTakeItemForPickAll(stack, slot); + } + + @Override +- @Override +- public ItemStack quickMoveStack(Player player, int i) { ++ public ItemStack quickMoveStack(net.minecraft.world.entity.player.Player player, int index) { + ItemStack itemstack = ItemStack.EMPTY; +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = (Slot) this.slots.get(index); + + if (slot != null && slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); + + itemstack = itemstack1.copy(); +- if (i == 2) { ++ if (index == 2) { + itemstack1.getItem().onCraftedBy(itemstack1, player.level(), player); + if (!this.moveItemStackTo(itemstack1, 3, 39, true)) { + return ItemStack.EMPTY; + } + + slot.onQuickCraft(itemstack1, itemstack); +- } else if (i != 1 && i != 0) { ++ } else if (index != 1 && index != 0) { + if (itemstack1.is(Items.FILLED_MAP)) { + if (!this.moveItemStackTo(itemstack1, 0, 1, false)) { + return ItemStack.EMPTY; + } + } else if (!itemstack1.is(Items.PAPER) && !itemstack1.is(Items.MAP) && !itemstack1.is(Items.GLASS_PANE)) { +- if (i >= 3 && i < 30) { ++ if (index >= 3 && index < 30) { + if (!this.moveItemStackTo(itemstack1, 30, 39, false)) { + return ItemStack.EMPTY; + } +- } else if (i >= 30 && i < 39 && !this.moveItemStackTo(itemstack1, 3, 30, false)) { ++ } else if (index >= 30 && index < 39 && !this.moveItemStackTo(itemstack1, 3, 30, false)) { + return ItemStack.EMPTY; + } + } else if (!this.moveItemStackTo(itemstack1, 1, 2, false)) { +@@ -219,11 +245,10 @@ + } + + @Override +- @Override +- public void removed(Player player) { ++ public void removed(net.minecraft.world.entity.player.Player player) { + super.removed(player); + this.resultContainer.removeItemNoUpdate(2); +- this.access.execute((level, blockpos) -> { ++ this.access.execute((world, blockposition) -> { + this.clearContainer(player, this.container); + }); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/ChestMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/ChestMenu.java.patch new file mode 100644 index 0000000000..eeadcc9251 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/ChestMenu.java.patch @@ -0,0 +1,166 @@ +--- a/net/minecraft/world/inventory/ChestMenu.java ++++ b/net/minecraft/world/inventory/ChestMenu.java +@@ -1,61 +1,92 @@ + package net.minecraft.world.inventory; + ++import net.minecraft.world.CompoundContainer; + import net.minecraft.world.Container; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.entity.player.Inventory; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + + public class ChestMenu extends AbstractContainerMenu { + + private static final int SLOTS_PER_ROW = 9; + private final Container container; + private final int containerRows; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; + +- private ChestMenu(MenuType menutype, int i, Inventory inventory, int j) { +- this(menutype, i, inventory, new SimpleContainer(9 * j), j); ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventory inventory; ++ if (this.container instanceof Inventory) { ++ inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryPlayer((Inventory) this.container); ++ } else if (this.container instanceof CompoundContainer) { ++ inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) this.container); ++ } else { ++ inventory = new CraftInventory(this.container); ++ } ++ ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; + } ++ // CraftBukkit end + +- public static ChestMenu oneRow(int i, Inventory inventory) { +- return new ChestMenu(MenuType.GENERIC_9x1, i, inventory, 1); ++ private ChestMenu(MenuType type, int containerId, Inventory playerInventory, int rows) { ++ this(type, containerId, playerInventory, new SimpleContainer(9 * rows), rows); + } + +- public static ChestMenu twoRows(int i, Inventory inventory) { +- return new ChestMenu(MenuType.GENERIC_9x2, i, inventory, 2); ++ public static ChestMenu oneRow(int containerId, Inventory playerInventory) { ++ return new ChestMenu(MenuType.GENERIC_9x1, containerId, playerInventory, 1); + } + +- public static ChestMenu threeRows(int i, Inventory inventory) { +- return new ChestMenu(MenuType.GENERIC_9x3, i, inventory, 3); ++ public static ChestMenu twoRows(int containerId, Inventory playerInventory) { ++ return new ChestMenu(MenuType.GENERIC_9x2, containerId, playerInventory, 2); + } + +- public static ChestMenu fourRows(int i, Inventory inventory) { +- return new ChestMenu(MenuType.GENERIC_9x4, i, inventory, 4); ++ public static ChestMenu threeRows(int containerId, Inventory playerInventory) { ++ return new ChestMenu(MenuType.GENERIC_9x3, containerId, playerInventory, 3); + } + +- public static ChestMenu fiveRows(int i, Inventory inventory) { +- return new ChestMenu(MenuType.GENERIC_9x5, i, inventory, 5); ++ public static ChestMenu fourRows(int containerId, Inventory playerInventory) { ++ return new ChestMenu(MenuType.GENERIC_9x4, containerId, playerInventory, 4); + } + +- public static ChestMenu sixRows(int i, Inventory inventory) { +- return new ChestMenu(MenuType.GENERIC_9x6, i, inventory, 6); ++ public static ChestMenu fiveRows(int containerId, Inventory playerInventory) { ++ return new ChestMenu(MenuType.GENERIC_9x5, containerId, playerInventory, 5); + } + +- public static ChestMenu threeRows(int i, Inventory inventory, Container container) { +- return new ChestMenu(MenuType.GENERIC_9x3, i, inventory, container, 3); ++ public static ChestMenu sixRows(int containerId, Inventory playerInventory) { ++ return new ChestMenu(MenuType.GENERIC_9x6, containerId, playerInventory, 6); + } + +- public static ChestMenu sixRows(int i, Inventory inventory, Container container) { +- return new ChestMenu(MenuType.GENERIC_9x6, i, inventory, container, 6); ++ public static ChestMenu threeRows(int containerId, Inventory playerInventory, Container container) { ++ return new ChestMenu(MenuType.GENERIC_9x3, containerId, playerInventory, container, 3); + } + +- public ChestMenu(MenuType menutype, int i, Inventory inventory, Container container, int j) { +- super(menutype, i); +- checkContainerSize(container, j * 9); ++ public static ChestMenu sixRows(int containerId, Inventory playerInventory, Container container) { ++ return new ChestMenu(MenuType.GENERIC_9x6, containerId, playerInventory, container, 6); ++ } ++ ++ public ChestMenu(MenuType type, int containerId, Inventory playerInventory, Container container, int rows) { ++ super(type, containerId); ++ checkContainerSize(container, rows * 9); + this.container = container; +- this.containerRows = j; +- container.startOpen(inventory.player); ++ this.containerRows = rows; ++ container.startOpen(playerInventory.player); + int k = (this.containerRows - 4) * 18; + ++ // CraftBukkit start - Save player ++ this.player = playerInventory; ++ // CraftBukkit end ++ + int l; + int i1; + +@@ -67,33 +98,32 @@ + + for (l = 0; l < 3; ++l) { + for (i1 = 0; i1 < 9; ++i1) { +- this.addSlot(new Slot(inventory, i1 + l * 9 + 9, 8 + i1 * 18, 103 + l * 18 + k)); ++ this.addSlot(new Slot(playerInventory, i1 + l * 9 + 9, 8 + i1 * 18, 103 + l * 18 + k)); + } + } + + for (l = 0; l < 9; ++l) { +- this.addSlot(new Slot(inventory, l, 8 + l * 18, 161 + k)); ++ this.addSlot(new Slot(playerInventory, l, 8 + l * 18, 161 + k)); + } + + } + + @Override +- @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(player); + } + + @Override +- @Override +- public ItemStack quickMoveStack(Player player, int i) { ++ public ItemStack quickMoveStack(Player player, int index) { + ItemStack itemstack = ItemStack.EMPTY; +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = (Slot) this.slots.get(index); + + if (slot != null && slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); + + itemstack = itemstack1.copy(); +- if (i < this.containerRows * 9) { ++ if (index < this.containerRows * 9) { + if (!this.moveItemStackTo(itemstack1, this.containerRows * 9, this.slots.size(), true)) { + return ItemStack.EMPTY; + } +@@ -112,7 +142,6 @@ + } + + @Override +- @Override + public void removed(Player player) { + super.removed(player); + this.container.stopOpen(player); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/ContainerLevelAccess.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/ContainerLevelAccess.java.patch new file mode 100644 index 0000000000..4eee847433 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/ContainerLevelAccess.java.patch @@ -0,0 +1,70 @@ +--- a/net/minecraft/world/inventory/ContainerLevelAccess.java ++++ b/net/minecraft/world/inventory/ContainerLevelAccess.java +@@ -8,33 +8,57 @@ + + public interface ContainerLevelAccess { + ++ // CraftBukkit start ++ default Level getWorld() { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ ++ default BlockPos getPosition() { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ ++ default org.bukkit.Location getLocation() { ++ return new org.bukkit.Location(getWorld().getWorld(), getPosition().getX(), getPosition().getY(), getPosition().getZ()); ++ } ++ // CraftBukkit end ++ + ContainerLevelAccess NULL = new ContainerLevelAccess() { + @Override +- @Override +- public Optional evaluate(BiFunction bifunction) { ++ public Optional evaluate(BiFunction levelPosConsumer) { + return Optional.empty(); + } + }; + +- static ContainerLevelAccess create(final Level level, final BlockPos blockpos) { ++ static ContainerLevelAccess create(final Level level, final BlockPos pos) { + return new ContainerLevelAccess() { ++ // CraftBukkit start + @Override ++ public Level getWorld() { ++ return level; ++ } ++ + @Override +- public Optional evaluate(BiFunction bifunction) { +- return Optional.of(bifunction.apply(level, blockpos)); ++ public BlockPos getPosition() { ++ return pos; + } ++ // CraftBukkit end ++ ++ @Override ++ public Optional evaluate(BiFunction levelPosConsumer) { ++ return Optional.of(levelPosConsumer.apply(level, pos)); ++ } + }; + } + + Optional evaluate(BiFunction levelPosConsumer); + +- default T evaluate(BiFunction bifunction, T t0) { +- return this.evaluate(bifunction).orElse(t0); ++ default T evaluate(BiFunction levelPosConsumer, T defaultValue) { ++ return this.evaluate(levelPosConsumer).orElse(defaultValue); + } + +- default void execute(BiConsumer biconsumer) { +- this.evaluate((level, blockpos) -> { +- biconsumer.accept(level, blockpos); ++ default void execute(BiConsumer levelPosConsumer) { ++ this.evaluate((world, blockposition) -> { ++ levelPosConsumer.accept(world, blockposition); + return Optional.empty(); + }); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/CrafterMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/CrafterMenu.java.patch new file mode 100644 index 0000000000..79691c223d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/CrafterMenu.java.patch @@ -0,0 +1,148 @@ +--- a/net/minecraft/world/inventory/CrafterMenu.java ++++ b/net/minecraft/world/inventory/CrafterMenu.java +@@ -8,8 +8,27 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.CrafterBlock; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryCrafter; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class CrafterMenu extends AbstractContainerMenu implements ContainerListener { + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryCrafter inventory = new CraftInventoryCrafter(this.container, this.resultContainer); ++ bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + protected static final int SLOT_COUNT = 9; + private static final int INV_SLOT_START = 9; + private static final int INV_SLOT_END = 36; +@@ -18,28 +37,28 @@ + private final ResultContainer resultContainer = new ResultContainer(); + private final ContainerData containerData; + private final Player player; +- private final CraftingContainer container; ++ private final InventoryCrafting container; + +- public CrafterMenu(int i, Inventory inventory) { ++ public CrafterMenu(int i, Inventory playerinventory) { + super(MenuType.CRAFTER_3x3, i); +- this.player = inventory.player; ++ this.player = playerinventory.player; + this.containerData = new SimpleContainerData(10); + this.container = new TransientCraftingContainer(this, 3, 3); +- this.addSlots(inventory); ++ this.addSlots(playerinventory); + } + +- public CrafterMenu(int i, Inventory inventory, CraftingContainer craftingcontainer, ContainerData containerdata) { ++ public CrafterMenu(int i, Inventory playerinventory, InventoryCrafting inventorycrafting, ContainerData icontainerproperties) { + super(MenuType.CRAFTER_3x3, i); +- this.player = inventory.player; +- this.containerData = containerdata; +- this.container = craftingcontainer; +- checkContainerSize(craftingcontainer, 9); +- craftingcontainer.startOpen(inventory.player); +- this.addSlots(inventory); ++ this.player = playerinventory.player; ++ this.containerData = icontainerproperties; ++ this.container = inventorycrafting; ++ checkContainerSize(inventorycrafting, 9); ++ inventorycrafting.startOpen(playerinventory.player); ++ this.addSlots(playerinventory); + this.addSlotListener(this); + } + +- private void addSlots(Inventory inventory) { ++ private void addSlots(Inventory playerinventory) { + int i; + int j; + +@@ -53,12 +72,12 @@ + + for (j = 0; j < 3; ++j) { + for (i = 0; i < 9; ++i) { +- this.addSlot(new Slot(inventory, i + j * 9 + 9, 8 + i * 18, 84 + j * 18)); ++ this.addSlot(new Slot(playerinventory, i + j * 9 + 9, 8 + i * 18, 84 + j * 18)); + } + } + + for (j = 0; j < 9; ++j) { +- this.addSlot(new Slot(inventory, j, 8 + j * 18, 142)); ++ this.addSlot(new Slot(playerinventory, j, 8 + j * 18, 142)); + } + + this.addSlot(new NonInteractiveResultSlot(this.resultContainer, 0, 134, 35)); +@@ -82,16 +101,15 @@ + } + + @Override +- @Override +- public ItemStack quickMoveStack(Player player, int i) { ++ public ItemStack quickMoveStack(Player player, int index) { + ItemStack itemstack = ItemStack.EMPTY; +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = (Slot) this.slots.get(index); + + if (slot != null && slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); + + itemstack = itemstack1.copy(); +- if (i < 9) { ++ if (index < 9) { + if (!this.moveItemStackTo(itemstack1, 9, 45, true)) { + return ItemStack.EMPTY; + } +@@ -116,19 +134,19 @@ + } + + @Override +- @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(player); + } + + private void refreshRecipeResult() { +- Player player = this.player; ++ Player entityhuman = this.player; + +- if (player instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) player; +- Level level = serverplayer.level(); +- ItemStack itemstack = (ItemStack) CrafterBlock.getPotentialResults(level, this.container).map((craftingrecipe) -> { +- return craftingrecipe.assemble(this.container, level.registryAccess()); ++ if (entityhuman instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entityhuman; ++ Level world = entityplayer.level(); ++ ItemStack itemstack = (ItemStack) CrafterBlock.getPotentialResults(world, this.container).map((recipecrafting) -> { ++ return recipecrafting.assemble(this.container, world.registryAccess()); + }).orElse(ItemStack.EMPTY); + + this.resultContainer.setItem(0, itemstack); +@@ -141,12 +159,10 @@ + } + + @Override +- @Override +- public void slotChanged(AbstractContainerMenu abstractcontainermenu, int i, ItemStack itemstack) { ++ public void slotChanged(AbstractContainerMenu containerToSend, int dataSlotIndex, ItemStack stack) { + this.refreshRecipeResult(); + } + + @Override +- @Override +- public void dataChanged(AbstractContainerMenu abstractcontainermenu, int i, int j) {} ++ public void dataChanged(AbstractContainerMenu containerMenu, int dataSlotIndex, int value) {} + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/CraftingMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/CraftingMenu.java.patch new file mode 100644 index 0000000000..31876515ed --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/CraftingMenu.java.patch @@ -0,0 +1,267 @@ +--- a/net/minecraft/world/inventory/CraftingMenu.java ++++ b/net/minecraft/world/inventory/CraftingMenu.java +@@ -8,14 +8,18 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.player.StackedContents; + import net.minecraft.world.item.ItemStack; +-import net.minecraft.world.item.crafting.CraftingRecipe; + import net.minecraft.world.item.crafting.Recipe; ++import net.minecraft.world.item.crafting.RecipeCrafting; + import net.minecraft.world.item.crafting.RecipeHolder; + import net.minecraft.world.item.crafting.RecipeType; ++import net.minecraft.world.item.crafting.RepairItemRecipe; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; ++import org.bukkit.craftbukkit.inventory.CraftInventoryCrafting; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + +-public class CraftingMenu extends RecipeBookMenu { ++public class CraftingMenu extends RecipeBookMenu { + + public static final int RESULT_SLOT = 0; + private static final int CRAFT_SLOT_START = 1; +@@ -24,22 +28,28 @@ + private static final int INV_SLOT_END = 37; + private static final int USE_ROW_SLOT_START = 37; + private static final int USE_ROW_SLOT_END = 46; +- private final CraftingContainer craftSlots; +- private final ResultContainer resultSlots; +- private final ContainerLevelAccess access; ++ public final TransientCraftingContainer craftSlots; // CraftBukkit ++ public final ResultContainer resultSlots; ++ public final ContainerLevelAccess access; + private final Player player; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ // CraftBukkit end + +- public CraftingMenu(int i, Inventory inventory) { +- this(i, inventory, ContainerLevelAccess.NULL); ++ public CraftingMenu(int containerId, Inventory playerInventory) { ++ this(containerId, playerInventory, ContainerLevelAccess.NULL); + } + +- public CraftingMenu(int i, Inventory inventory, ContainerLevelAccess containerlevelaccess) { +- super(MenuType.CRAFTING, i); +- this.craftSlots = new TransientCraftingContainer(this, 3, 3); ++ public CraftingMenu(int containerId, Inventory playerInventory, ContainerLevelAccess access) { ++ super(MenuType.CRAFTING, containerId); ++ // CraftBukkit start - Switched order of IInventory construction and stored player + this.resultSlots = new ResultContainer(); +- this.access = containerlevelaccess; +- this.player = inventory.player; +- this.addSlot(new ResultSlot(inventory.player, this.craftSlots, this.resultSlots, 0, 124, 35)); ++ this.craftSlots = new TransientCraftingContainer(this, 3, 3, playerInventory.player); // CraftBukkit - pass player ++ this.craftSlots.resultInventory = this.resultSlots; ++ // CraftBukkit end ++ this.access = access; ++ this.player = playerInventory.player; ++ this.addSlot(new ResultSlot(playerInventory.player, this.craftSlots, this.resultSlots, 0, 124, 35)); + + int j; + int k; +@@ -52,105 +62,100 @@ + + for (j = 0; j < 3; ++j) { + for (k = 0; k < 9; ++k) { +- this.addSlot(new Slot(inventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); + } + } + + for (j = 0; j < 9; ++j) { +- this.addSlot(new Slot(inventory, j, 8 + j * 18, 142)); ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } + + } + +- protected static void slotChangedCraftingGrid(AbstractContainerMenu abstractcontainermenu, Level level, Player player, CraftingContainer craftingcontainer, ResultContainer resultcontainer) { ++ protected static void slotChangedCraftingGrid(AbstractContainerMenu menu, Level level, Player player, InventoryCrafting container, ResultContainer result) { + if (!level.isClientSide) { +- ServerPlayer serverplayer = (ServerPlayer) player; ++ ServerPlayer entityplayer = (ServerPlayer) player; + ItemStack itemstack = ItemStack.EMPTY; +- Optional> optional = level.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftingcontainer, level); ++ Optional> optional = level.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, container, level); + + if (optional.isPresent()) { +- RecipeHolder recipeholder = (RecipeHolder) optional.get(); +- CraftingRecipe craftingrecipe = (CraftingRecipe) recipeholder.value(); ++ RecipeHolder recipeholder = (RecipeHolder) optional.get(); ++ RecipeCrafting recipecrafting = (RecipeCrafting) recipeholder.value(); + +- if (resultcontainer.setRecipeUsed(level, serverplayer, recipeholder)) { +- ItemStack itemstack1 = craftingrecipe.assemble(craftingcontainer, level.registryAccess()); ++ if (result.setRecipeUsed(level, entityplayer, recipeholder)) { ++ ItemStack itemstack1 = recipecrafting.assemble(container, level.registryAccess()); + + if (itemstack1.isItemEnabled(level.enabledFeatures())) { + itemstack = itemstack1; + } + } + } ++ itemstack = org.bukkit.craftbukkit.event.CraftEventFactory.callPreCraftEvent(container, result, itemstack, menu.getBukkitView(), optional.map(RecipeHolder::toBukkitRecipe).orElse(null) instanceof RepairItemRecipe); // CraftBukkit + +- resultcontainer.setItem(0, itemstack); +- abstractcontainermenu.setRemoteSlot(0, itemstack); +- serverplayer.connection.send(new ClientboundContainerSetSlotPacket(abstractcontainermenu.containerId, abstractcontainermenu.incrementStateId(), 0, itemstack)); ++ result.setItem(0, itemstack); ++ menu.setRemoteSlot(0, itemstack); ++ entityplayer.connection.send(new ClientboundContainerSetSlotPacket(menu.containerId, menu.incrementStateId(), 0, itemstack)); + } + } + + @Override +- @Override +- public void slotsChanged(Container container) { +- this.access.execute((level, blockpos) -> { +- slotChangedCraftingGrid(this, level, this.player, this.craftSlots, this.resultSlots); ++ public void slotsChanged(Container inventory) { ++ this.access.execute((world, blockposition) -> { ++ slotChangedCraftingGrid(this, world, this.player, this.craftSlots, this.resultSlots); + }); + } + + @Override +- @Override +- public void fillCraftSlotsStackedContents(StackedContents stackedcontents) { +- this.craftSlots.fillStackedContents(stackedcontents); ++ public void fillCraftSlotsStackedContents(StackedContents itemHelper) { ++ this.craftSlots.fillStackedContents(itemHelper); + } + + @Override +- @Override + public void clearCraftingContent() { + this.craftSlots.clearContent(); + this.resultSlots.clearContent(); + } + + @Override +- @Override +- public boolean recipeMatches(RecipeHolder> recipeholder) { ++ public boolean recipeMatches(RecipeHolder> recipeholder) { + return recipeholder.value().matches(this.craftSlots, this.player.level()); + } + + @Override +- @Override + public void removed(Player player) { + super.removed(player); +- this.access.execute((level, blockpos) -> { ++ this.access.execute((world, blockposition) -> { + this.clearContainer(player, this.craftSlots); + }); + } + + @Override +- @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.CRAFTING_TABLE); + } + + @Override +- @Override +- public ItemStack quickMoveStack(Player player, int i) { ++ public ItemStack quickMoveStack(Player player, int index) { + ItemStack itemstack = ItemStack.EMPTY; +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = (Slot) this.slots.get(index); + + if (slot != null && slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); + + itemstack = itemstack1.copy(); +- if (i == 0) { +- this.access.execute((level, blockpos) -> { +- itemstack1.getItem().onCraftedBy(itemstack1, level, player); ++ if (index == 0) { ++ this.access.execute((world, blockposition) -> { ++ itemstack1.getItem().onCraftedBy(itemstack1, world, player); + }); + if (!this.moveItemStackTo(itemstack1, 10, 46, true)) { + return ItemStack.EMPTY; + } + + slot.onQuickCraft(itemstack1, itemstack); +- } else if (i >= 10 && i < 46) { ++ } else if (index >= 10 && index < 46) { + if (!this.moveItemStackTo(itemstack1, 1, 10, false)) { +- if (i < 37) { ++ if (index < 37) { + if (!this.moveItemStackTo(itemstack1, 37, 46, false)) { + return ItemStack.EMPTY; + } +@@ -173,7 +178,7 @@ + } + + slot.onTake(player, itemstack1); +- if (i == 0) { ++ if (index == 0) { + player.drop(itemstack1, false); + } + } +@@ -182,44 +187,50 @@ + } + + @Override +- @Override +- public boolean canTakeItemForPickAll(ItemStack itemstack, Slot slot) { +- return slot.container != this.resultSlots && super.canTakeItemForPickAll(itemstack, slot); ++ public boolean canTakeItemForPickAll(ItemStack stack, Slot slot) { ++ return slot.container != this.resultSlots && super.canTakeItemForPickAll(stack, slot); + } + + @Override +- @Override + public int getResultSlotIndex() { + return 0; + } + + @Override +- @Override + public int getGridWidth() { + return this.craftSlots.getWidth(); + } + + @Override +- @Override + public int getGridHeight() { + return this.craftSlots.getHeight(); + } + + @Override +- @Override + public int getSize() { + return 10; + } + + @Override +- @Override + public RecipeBookType getRecipeBookType() { + return RecipeBookType.CRAFTING; + } + + @Override ++ public boolean shouldMoveToInventory(int slotIndex) { ++ return slotIndex != this.getResultSlotIndex(); ++ } ++ ++ // CraftBukkit start + @Override +- public boolean shouldMoveToInventory(int i) { +- return i != this.getResultSlotIndex(); ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryCrafting inventory = new CraftInventoryCrafting(this.craftSlots, this.resultSlots); ++ bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; + } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/DispenserMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/DispenserMenu.java.patch new file mode 100644 index 0000000000..d502691d06 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/DispenserMenu.java.patch @@ -0,0 +1,109 @@ +--- a/net/minecraft/world/inventory/DispenserMenu.java ++++ b/net/minecraft/world/inventory/DispenserMenu.java +@@ -6,6 +6,11 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class DispenserMenu extends AbstractContainerMenu { + + private static final int SLOT_COUNT = 9; +@@ -13,17 +18,25 @@ + private static final int INV_SLOT_END = 36; + private static final int USE_ROW_SLOT_START = 36; + private static final int USE_ROW_SLOT_END = 45; +- private final Container dispenser; ++ public final Container dispenser; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ // CraftBukkit end + +- public DispenserMenu(int i, Inventory inventory) { +- this(i, inventory, new SimpleContainer(9)); ++ public DispenserMenu(int containerId, Inventory playerInventory) { ++ this(containerId, playerInventory, new SimpleContainer(9)); + } + +- public DispenserMenu(int i, Inventory inventory, Container container) { +- super(MenuType.GENERIC_3x3, i); ++ public DispenserMenu(int containerId, Inventory playerInventory, Container container) { ++ super(MenuType.GENERIC_3x3, containerId); ++ // CraftBukkit start - Save player ++ this.player = playerInventory; ++ // CraftBukkit end ++ + checkContainerSize(container, 9); + this.dispenser = container; +- container.startOpen(inventory.player); ++ container.startOpen(playerInventory.player); + + int j; + int k; +@@ -36,33 +49,32 @@ + + for (j = 0; j < 3; ++j) { + for (k = 0; k < 9; ++k) { +- this.addSlot(new Slot(inventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); + } + } + + for (j = 0; j < 9; ++j) { +- this.addSlot(new Slot(inventory, j, 8 + j * 18, 142)); ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } + + } + + @Override +- @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.dispenser.stillValid(player); + } + + @Override +- @Override +- public ItemStack quickMoveStack(Player player, int i) { ++ public ItemStack quickMoveStack(Player player, int index) { + ItemStack itemstack = ItemStack.EMPTY; +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = (Slot) this.slots.get(index); + + if (slot != null && slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); + + itemstack = itemstack1.copy(); +- if (i < 9) { ++ if (index < 9) { + if (!this.moveItemStackTo(itemstack1, 9, 45, true)) { + return ItemStack.EMPTY; + } +@@ -87,9 +99,21 @@ + } + + @Override +- @Override + public void removed(Player player) { + super.removed(player); + this.dispenser.stopOpen(player); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventory inventory = new CraftInventory(this.dispenser); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/EnchantmentMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/EnchantmentMenu.java.patch new file mode 100644 index 0000000000..71b40a29a1 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/EnchantmentMenu.java.patch @@ -0,0 +1,395 @@ +--- a/net/minecraft/world/inventory/EnchantmentMenu.java ++++ b/net/minecraft/world/inventory/EnchantmentMenu.java +@@ -18,14 +18,27 @@ + import net.minecraft.world.Container; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.entity.player.Inventory; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.EnchantedBookItem; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +-import net.minecraft.world.item.enchantment.EnchantmentHelper; +-import net.minecraft.world.item.enchantment.EnchantmentInstance; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.EnchantmentTableBlock; ++// CraftBukkit start ++import java.util.Map; ++import net.minecraft.world.item.enchantment.Enchantment; ++import net.minecraft.world.item.enchantment.EnchantmentHelper; ++import net.minecraft.world.item.enchantment.EnchantmentInstance; ++import org.bukkit.Location; ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftInventoryEnchanting; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.enchantments.EnchantmentOffer; ++import org.bukkit.event.enchantment.EnchantItemEvent; ++import org.bukkit.event.enchantment.PrepareItemEnchantEvent; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class EnchantmentMenu extends AbstractContainerMenu { + +@@ -37,43 +50,50 @@ + public final int[] costs; + public final int[] enchantClue; + public final int[] levelClue; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ // CraftBukkit end + +- public EnchantmentMenu(int i, Inventory inventory) { +- this(i, inventory, ContainerLevelAccess.NULL); ++ public EnchantmentMenu(int containerId, Inventory playerInventory) { ++ this(containerId, playerInventory, ContainerLevelAccess.NULL); + } + +- public EnchantmentMenu(int i, Inventory inventory, ContainerLevelAccess containerlevelaccess) { +- super(MenuType.ENCHANTMENT, i); ++ public EnchantmentMenu(int containerId, Inventory playerInventory, ContainerLevelAccess access) { ++ super(MenuType.ENCHANTMENT, containerId); + this.enchantSlots = new SimpleContainer(2) { + @Override +- @Override + public void setChanged() { + super.setChanged(); + EnchantmentMenu.this.slotsChanged(this); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end + }; + this.random = RandomSource.create(); + this.enchantmentSeed = DataSlot.standalone(); + this.costs = new int[3]; + this.enchantClue = new int[]{-1, -1, -1}; + this.levelClue = new int[]{-1, -1, -1}; +- this.access = containerlevelaccess; ++ this.access = access; + this.addSlot(new Slot(this.enchantSlots, 0, 15, 47) { + @Override +- @Override + public int getMaxStackSize() { + return 1; + } + }); + this.addSlot(new Slot(this.enchantSlots, 1, 35, 47) { + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { +- return itemstack.is(Items.LAPIS_LAZULI); ++ public boolean mayPlace(ItemStack stack) { ++ return stack.is(Items.LAPIS_LAZULI); + } + + @Override +- @Override + public Pair getNoItemIcon() { + return Pair.of(InventoryMenu.BLOCK_ATLAS, EnchantmentMenu.EMPTY_SLOT_LAPIS_LAZULI); + } +@@ -83,41 +103,43 @@ + + for (j = 0; j < 3; ++j) { + for (int k = 0; k < 9; ++k) { +- this.addSlot(new Slot(inventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); + } + } + + for (j = 0; j < 9; ++j) { +- this.addSlot(new Slot(inventory, j, 8 + j * 18, 142)); ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } + + this.addDataSlot(DataSlot.shared(this.costs, 0)); + this.addDataSlot(DataSlot.shared(this.costs, 1)); + this.addDataSlot(DataSlot.shared(this.costs, 2)); +- this.addDataSlot(this.enchantmentSeed).set(inventory.player.getEnchantmentSeed()); ++ this.addDataSlot(this.enchantmentSeed).set(playerInventory.player.getEnchantmentSeed()); + this.addDataSlot(DataSlot.shared(this.enchantClue, 0)); + this.addDataSlot(DataSlot.shared(this.enchantClue, 1)); + this.addDataSlot(DataSlot.shared(this.enchantClue, 2)); + this.addDataSlot(DataSlot.shared(this.levelClue, 0)); + this.addDataSlot(DataSlot.shared(this.levelClue, 1)); + this.addDataSlot(DataSlot.shared(this.levelClue, 2)); ++ // CraftBukkit start ++ player = (Player) playerInventory.player.getBukkitEntity(); ++ // CraftBukkit end + } + + @Override +- @Override +- public void slotsChanged(Container container) { +- if (container == this.enchantSlots) { +- ItemStack itemstack = container.getItem(0); ++ public void slotsChanged(Container inventory) { ++ if (inventory == this.enchantSlots) { ++ ItemStack itemstack = inventory.getItem(0); + +- if (!itemstack.isEmpty() && itemstack.isEnchantable()) { +- this.access.execute((level, blockpos) -> { ++ if (!itemstack.isEmpty()) { // CraftBukkit - relax condition ++ this.access.execute((world, blockposition) -> { + int i = 0; + Iterator iterator = EnchantmentTableBlock.BOOKSHELF_OFFSETS.iterator(); + + while (iterator.hasNext()) { +- BlockPos blockpos1 = (BlockPos) iterator.next(); ++ BlockPos blockposition1 = (BlockPos) iterator.next(); + +- if (EnchantmentTableBlock.isValidBookShelf(level, blockpos, blockpos1)) { ++ if (EnchantmentTableBlock.isValidBookShelf(world, blockposition, blockposition1)) { + ++i; + } + } +@@ -140,14 +162,49 @@ + List list = this.getEnchantmentList(itemstack, j, this.costs[j]); + + if (list != null && !list.isEmpty()) { +- EnchantmentInstance enchantmentinstance = (EnchantmentInstance) list.get(this.random.nextInt(list.size())); ++ EnchantmentInstance weightedrandomenchant = (EnchantmentInstance) list.get(this.random.nextInt(list.size())); + +- this.enchantClue[j] = BuiltInRegistries.ENCHANTMENT.getId(enchantmentinstance.enchantment); +- this.levelClue[j] = enchantmentinstance.level; ++ this.enchantClue[j] = BuiltInRegistries.ENCHANTMENT.getId(weightedrandomenchant.enchantment); ++ this.levelClue[j] = weightedrandomenchant.level; + } + } + } + ++ // CraftBukkit start ++ CraftItemStack item = CraftItemStack.asCraftMirror(itemstack); ++ org.bukkit.enchantments.EnchantmentOffer[] offers = new EnchantmentOffer[3]; ++ for (j = 0; j < 3; ++j) { ++ org.bukkit.enchantments.Enchantment enchantment = (this.enchantClue[j] >= 0) ? org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(BuiltInRegistries.ENCHANTMENT.byId(this.enchantClue[j])))) : null; ++ offers[j] = (enchantment != null) ? new EnchantmentOffer(enchantment, this.levelClue[j], this.costs[j]) : null; ++ } ++ ++ PrepareItemEnchantEvent event = new PrepareItemEnchantEvent(player, this.getBukkitView(), access.getLocation().getBlock(), item, offers, i); ++ event.setCancelled(!itemstack.isEnchantable()); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ for (j = 0; j < 3; ++j) { ++ this.costs[j] = 0; ++ this.enchantClue[j] = -1; ++ this.levelClue[j] = -1; ++ } ++ return; ++ } ++ ++ for (j = 0; j < 3; j++) { ++ EnchantmentOffer offer = event.getOffers()[j]; ++ if (offer != null) { ++ this.costs[j] = offer.getCost(); ++ this.enchantClue[j] = BuiltInRegistries.ENCHANTMENT.getId(BuiltInRegistries.ENCHANTMENT.get(CraftNamespacedKey.toMinecraft(offer.getEnchantment().getKey()))); ++ this.levelClue[j] = offer.getEnchantmentLevel(); ++ } else { ++ this.costs[j] = 0; ++ this.enchantClue[j] = -1; ++ this.levelClue[j] = -1; ++ } ++ } ++ // CraftBukkit end ++ + this.broadcastChanges(); + }); + } else { +@@ -162,47 +219,75 @@ + } + + @Override +- @Override +- public boolean clickMenuButton(Player player, int i) { +- if (i >= 0 && i < this.costs.length) { ++ public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { ++ if (id >= 0 && id < this.costs.length) { + ItemStack itemstack = this.enchantSlots.getItem(0); + ItemStack itemstack1 = this.enchantSlots.getItem(1); +- int j = i + 1; ++ int j = id + 1; + + if ((itemstack1.isEmpty() || itemstack1.getCount() < j) && !player.getAbilities().instabuild) { + return false; +- } else if (this.costs[i] > 0 && !itemstack.isEmpty() && (player.experienceLevel >= j && player.experienceLevel >= this.costs[i] || player.getAbilities().instabuild)) { +- this.access.execute((level, blockpos) -> { ++ } else if (this.costs[id] > 0 && !itemstack.isEmpty() && (player.experienceLevel >= j && player.experienceLevel >= this.costs[id] || player.getAbilities().instabuild)) { ++ this.access.execute((world, blockposition) -> { + ItemStack itemstack2 = itemstack; +- List list = this.getEnchantmentList(itemstack, i, this.costs[i]); ++ List list = this.getEnchantmentList(itemstack, id, this.costs[id]); + +- if (!list.isEmpty()) { +- player.onEnchantmentPerformed(itemstack, j); ++ // CraftBukkit start ++ if (true || !list.isEmpty()) { ++ // entityhuman.onEnchantmentPerformed(itemstack, j); // Moved down ++ Map enchants = new java.util.HashMap(); ++ for (EnchantmentInstance instance : list) { ++ enchants.put(org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(instance.enchantment))), instance.level); ++ } ++ CraftItemStack item = CraftItemStack.asCraftMirror(itemstack2); ++ ++ org.bukkit.enchantments.Enchantment hintedEnchantment = org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(Enchantment.byId(enchantClue[id])))); ++ int hintedEnchantmentLevel = levelClue[id]; ++ EnchantItemEvent event = new EnchantItemEvent((Player) player.getBukkitEntity(), this.getBukkitView(), access.getLocation().getBlock(), item, this.costs[id], enchants, hintedEnchantment, hintedEnchantmentLevel, id); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ int level = event.getExpLevelCost(); ++ if (event.isCancelled() || (level > player.experienceLevel && !player.getAbilities().instabuild) || event.getEnchantsToAdd().isEmpty()) { ++ return; ++ } ++ // CraftBukkit end + boolean flag = itemstack.is(Items.BOOK); + + if (flag) { + itemstack2 = new ItemStack(Items.ENCHANTED_BOOK); +- CompoundTag compoundtag = itemstack.getTag(); ++ CompoundTag nbttagcompound = itemstack.getTag(); + +- if (compoundtag != null) { +- itemstack2.setTag(compoundtag.copy()); ++ if (nbttagcompound != null) { ++ itemstack2.setTag(nbttagcompound.copy()); + } + + this.enchantSlots.setItem(0, itemstack2); + } + +- Iterator iterator = list.iterator(); ++ // CraftBukkit start ++ for (Map.Entry entry : event.getEnchantsToAdd().entrySet()) { ++ try { ++ if (flag) { ++ NamespacedKey enchantId = entry.getKey().getKey(); ++ Enchantment nms = BuiltInRegistries.ENCHANTMENT.get(CraftNamespacedKey.toMinecraft(enchantId)); ++ if (nms == null) { ++ continue; ++ } + +- while (iterator.hasNext()) { +- EnchantmentInstance enchantmentinstance = (EnchantmentInstance) iterator.next(); +- +- if (flag) { +- EnchantedBookItem.addEnchantment(itemstack2, enchantmentinstance); +- } else { +- itemstack2.enchant(enchantmentinstance.enchantment, enchantmentinstance.level); ++ EnchantmentInstance weightedrandomenchant = new EnchantmentInstance(nms, entry.getValue()); ++ EnchantedBookItem.addEnchantment(itemstack2, weightedrandomenchant); ++ } else { ++ item.addUnsafeEnchantment(entry.getKey(), entry.getValue()); ++ } ++ } catch (IllegalArgumentException e) { ++ /* Just swallow invalid enchantments */ + } + } + ++ player.onEnchantmentPerformed(itemstack, j); ++ // CraftBukkit end ++ ++ // CraftBukkit - TODO: let plugins change this + if (!player.getAbilities().instabuild) { + itemstack1.shrink(j); + if (itemstack1.isEmpty()) { +@@ -218,7 +303,7 @@ + this.enchantSlots.setChanged(); + this.enchantmentSeed.set(player.getEnchantmentSeed()); + this.slotsChanged(this.enchantSlots); +- level.playSound((Player) null, blockpos, SoundEvents.ENCHANTMENT_TABLE_USE, SoundSource.BLOCKS, 1.0F, level.random.nextFloat() * 0.1F + 0.9F); ++ world.playSound((net.minecraft.world.entity.player.Player) null, blockposition, SoundEvents.ENCHANTMENT_TABLE_USE, SoundSource.BLOCKS, 1.0F, world.random.nextFloat() * 0.1F + 0.9F); + } + + }); +@@ -227,18 +312,18 @@ + return false; + } + } else { +- Component component = player.getName(); ++ Component ichatbasecomponent = player.getName(); + +- Util.logAndPauseIfInIde(component + " pressed invalid button id: " + i); ++ Util.logAndPauseIfInIde(ichatbasecomponent + " pressed invalid button id: " + id); + return false; + } + } + +- private List getEnchantmentList(ItemStack itemstack, int i, int j) { +- this.random.setSeed((long) (this.enchantmentSeed.get() + i)); +- List list = EnchantmentHelper.selectEnchantment(this.random, itemstack, j, false); ++ private List getEnchantmentList(ItemStack stack, int enchantSlot, int level) { ++ this.random.setSeed((long) (this.enchantmentSeed.get() + enchantSlot)); ++ List list = EnchantmentHelper.selectEnchantment(this.random, stack, level, false); + +- if (itemstack.is(Items.BOOK) && list.size() > 1) { ++ if (stack.is(Items.BOOK) && list.size() > 1) { + list.remove(this.random.nextInt(list.size())); + } + +@@ -256,35 +341,33 @@ + } + + @Override +- @Override +- public void removed(Player player) { ++ public void removed(net.minecraft.world.entity.player.Player player) { + super.removed(player); +- this.access.execute((level, blockpos) -> { ++ this.access.execute((world, blockposition) -> { + this.clearContainer(player, this.enchantSlots); + }); + } + + @Override +- @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.ENCHANTING_TABLE); + } + + @Override +- @Override +- public ItemStack quickMoveStack(Player player, int i) { ++ public ItemStack quickMoveStack(net.minecraft.world.entity.player.Player player, int index) { + ItemStack itemstack = ItemStack.EMPTY; +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = (Slot) this.slots.get(index); + + if (slot != null && slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); + + itemstack = itemstack1.copy(); +- if (i == 0) { ++ if (index == 0) { + if (!this.moveItemStackTo(itemstack1, 2, 38, true)) { + return ItemStack.EMPTY; + } +- } else if (i == 1) { ++ } else if (index == 1) { + if (!this.moveItemStackTo(itemstack1, 2, 38, true)) { + return ItemStack.EMPTY; + } +@@ -318,4 +401,17 @@ + + return itemstack; + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryEnchanting inventory = new CraftInventoryEnchanting(this.enchantSlots); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/FurnaceResultSlot.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/FurnaceResultSlot.java.patch new file mode 100644 index 0000000000..101aa475e1 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/FurnaceResultSlot.java.patch @@ -0,0 +1,79 @@ +--- a/net/minecraft/world/inventory/FurnaceResultSlot.java ++++ b/net/minecraft/world/inventory/FurnaceResultSlot.java +@@ -11,55 +11,50 @@ + private final Player player; + private int removeCount; + +- public FurnaceResultSlot(Player player, Container container, int i, int j, int k) { +- super(container, i, j, k); ++ public FurnaceResultSlot(Player player, Container container, int slot, int xPosition, int yPosition) { ++ super(container, slot, xPosition, yPosition); + this.player = player; + } + + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { ++ public boolean mayPlace(ItemStack stack) { + return false; + } + + @Override +- @Override +- public ItemStack remove(int i) { ++ public ItemStack remove(int amount) { + if (this.hasItem()) { +- this.removeCount += Math.min(i, this.getItem().getCount()); ++ this.removeCount += Math.min(amount, this.getItem().getCount()); + } + +- return super.remove(i); ++ return super.remove(amount); + } + + @Override +- @Override +- public void onTake(Player player, ItemStack itemstack) { +- this.checkTakeAchievements(itemstack); +- super.onTake(player, itemstack); ++ public void onTake(Player player, ItemStack stack) { ++ this.checkTakeAchievements(stack); ++ super.onTake(player, stack); + } + + @Override +- @Override +- protected void onQuickCraft(ItemStack itemstack, int i) { +- this.removeCount += i; +- this.checkTakeAchievements(itemstack); ++ protected void onQuickCraft(ItemStack stack, int amount) { ++ this.removeCount += amount; ++ this.checkTakeAchievements(stack); + } + + @Override +- @Override +- protected void checkTakeAchievements(ItemStack itemstack) { +- itemstack.onCraftedBy(this.player.level(), this.player, this.removeCount); +- Player player = this.player; ++ protected void checkTakeAchievements(ItemStack stack) { ++ stack.onCraftedBy(this.player.level(), this.player, this.removeCount); ++ Player entityhuman = this.player; + +- if (player instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) player; +- Container container = this.container; ++ if (entityhuman instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entityhuman; ++ Container iinventory = this.container; + +- if (container instanceof AbstractFurnaceBlockEntity) { +- AbstractFurnaceBlockEntity abstractfurnaceblockentity = (AbstractFurnaceBlockEntity) container; ++ if (iinventory instanceof AbstractFurnaceBlockEntity) { ++ AbstractFurnaceBlockEntity tileentityfurnace = (AbstractFurnaceBlockEntity) iinventory; + +- abstractfurnaceblockentity.awardUsedRecipesAndPopExperience(serverplayer); ++ tileentityfurnace.awardUsedRecipesAndPopExperience(entityplayer, stack, this.removeCount); // CraftBukkit + } + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/GrindstoneMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/GrindstoneMenu.java.patch new file mode 100644 index 0000000000..54f2aafccf --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/GrindstoneMenu.java.patch @@ -0,0 +1,299 @@ +--- a/net/minecraft/world/inventory/GrindstoneMenu.java ++++ b/net/minecraft/world/inventory/GrindstoneMenu.java +@@ -9,7 +9,6 @@ + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.entity.ExperienceOrb; + import net.minecraft.world.entity.player.Inventory; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +@@ -18,9 +17,30 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.inventory.CraftInventoryGrindstone; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class GrindstoneMenu extends AbstractContainerMenu { + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryGrindstone inventory = new CraftInventoryGrindstone(this.repairSlots, this.resultSlots); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + public static final int MAX_NAME_LENGTH = 35; + public static final int INPUT_SLOT = 0; + public static final int ADDITIONAL_SLOT = 1; +@@ -33,52 +53,54 @@ + final Container repairSlots; + private final ContainerLevelAccess access; + +- public GrindstoneMenu(int i, Inventory inventory) { +- this(i, inventory, ContainerLevelAccess.NULL); ++ public GrindstoneMenu(int containerId, Inventory playerInventory) { ++ this(containerId, playerInventory, ContainerLevelAccess.NULL); + } + +- public GrindstoneMenu(int i, Inventory inventory, final ContainerLevelAccess containerlevelaccess) { +- super(MenuType.GRINDSTONE, i); ++ public GrindstoneMenu(int containerId, Inventory playerInventory, final ContainerLevelAccess access) { ++ super(MenuType.GRINDSTONE, containerId); + this.resultSlots = new ResultContainer(); + this.repairSlots = new SimpleContainer(2) { + @Override +- @Override + public void setChanged() { + super.setChanged(); + GrindstoneMenu.this.slotsChanged(this); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end + }; +- this.access = containerlevelaccess; ++ this.access = access; + this.addSlot(new Slot(this.repairSlots, 0, 49, 19) { + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { +- return itemstack.isDamageableItem() || itemstack.is(Items.ENCHANTED_BOOK) || itemstack.isEnchanted(); ++ public boolean mayPlace(ItemStack stack) { ++ return stack.isDamageableItem() || stack.is(Items.ENCHANTED_BOOK) || stack.isEnchanted(); + } + }); + this.addSlot(new Slot(this.repairSlots, 1, 49, 40) { + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { +- return itemstack.isDamageableItem() || itemstack.is(Items.ENCHANTED_BOOK) || itemstack.isEnchanted(); ++ public boolean mayPlace(ItemStack stack) { ++ return stack.isDamageableItem() || stack.is(Items.ENCHANTED_BOOK) || stack.isEnchanted(); + } + }); + this.addSlot(new Slot(this.resultSlots, 2, 129, 34) { + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { ++ public boolean mayPlace(ItemStack stack) { + return false; + } + + @Override +- @Override +- public void onTake(Player player, ItemStack itemstack) { +- containerlevelaccess.execute((level, blockpos) -> { +- if (level instanceof ServerLevel) { +- ExperienceOrb.award((ServerLevel) level, Vec3.atCenterOf(blockpos), this.getExperienceAmount(level)); ++ public void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) { ++ access.execute((world, blockposition) -> { ++ if (world instanceof ServerLevel) { ++ ExperienceOrb.award((ServerLevel) world, Vec3.atCenterOf(blockposition), this.getExperienceAmount(world)); + } + +- level.levelEvent(1042, blockpos, 0); ++ world.levelEvent(1042, blockposition, 0); + }); + GrindstoneMenu.this.repairSlots.setItem(0, ItemStack.EMPTY); + GrindstoneMenu.this.repairSlots.setItem(1, ItemStack.EMPTY); +@@ -98,9 +120,9 @@ + } + } + +- private int getExperienceFromItem(ItemStack itemstack) { ++ private int getExperienceFromItem(ItemStack stack) { + int j = 0; +- Map map = EnchantmentHelper.getEnchantments(itemstack); ++ Map map = EnchantmentHelper.getEnchantments(stack); + Iterator iterator = map.entrySet().iterator(); + + while (iterator.hasNext()) { +@@ -121,21 +143,21 @@ + + for (j = 0; j < 3; ++j) { + for (int k = 0; k < 9; ++k) { +- this.addSlot(new Slot(inventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); + } + } + + for (j = 0; j < 9; ++j) { +- this.addSlot(new Slot(inventory, j, 8 + j * 18, 142)); ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } + ++ player = (Player) playerInventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override +- @Override +- public void slotsChanged(Container container) { +- super.slotsChanged(container); +- if (container == this.repairSlots) { ++ public void slotsChanged(Container inventory) { ++ super.slotsChanged(inventory); ++ if (inventory == this.repairSlots) { + this.createResult(); + } + +@@ -151,7 +173,7 @@ + boolean flag2 = !itemstack.isEmpty() && !itemstack.is(Items.ENCHANTED_BOOK) && !itemstack.isEnchanted() || !itemstack1.isEmpty() && !itemstack1.is(Items.ENCHANTED_BOOK) && !itemstack1.isEnchanted(); + + if (itemstack.getCount() > 1 || itemstack1.getCount() > 1 || !flag1 && flag2) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + this.broadcastChanges(); + return; + } +@@ -162,7 +184,7 @@ + + if (flag1) { + if (!itemstack.is(itemstack1.getItem())) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + this.broadcastChanges(); + return; + } +@@ -176,7 +198,7 @@ + itemstack2 = this.mergeEnchants(itemstack, itemstack1); + if (!itemstack2.isDamageableItem()) { + if (!ItemStack.matches(itemstack, itemstack1)) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + this.broadcastChanges(); + return; + } +@@ -189,18 +211,18 @@ + i = flag3 ? itemstack.getDamageValue() : itemstack1.getDamageValue(); + itemstack2 = flag3 ? itemstack : itemstack1; + } +- +- this.resultSlots.setItem(0, this.removeNonCurses(itemstack2, i, b0)); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), this.removeNonCurses(itemstack2, i, b0)); // CraftBukkit + } else { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + } + ++ sendAllDataToRemote(); // CraftBukkit - SPIGOT-6686: Always send completed inventory to stay in sync with client + this.broadcastChanges(); + } + +- private ItemStack mergeEnchants(ItemStack itemstack, ItemStack itemstack1) { +- ItemStack itemstack2 = itemstack.copy(); +- Map map = EnchantmentHelper.getEnchantments(itemstack1); ++ private ItemStack mergeEnchants(ItemStack copyTo, ItemStack copyFrom) { ++ ItemStack itemstack2 = copyTo.copy(); ++ Map map = EnchantmentHelper.getEnchantments(copyFrom); + Iterator iterator = map.entrySet().iterator(); + + while (iterator.hasNext()) { +@@ -215,18 +237,18 @@ + return itemstack2; + } + +- private ItemStack removeNonCurses(ItemStack itemstack, int i, int j) { +- ItemStack itemstack1 = itemstack.copyWithCount(j); ++ private ItemStack removeNonCurses(ItemStack stack, int damage, int count) { ++ ItemStack itemstack1 = stack.copyWithCount(count); + + itemstack1.removeTagKey("Enchantments"); + itemstack1.removeTagKey("StoredEnchantments"); +- if (i > 0) { +- itemstack1.setDamageValue(i); ++ if (damage > 0) { ++ itemstack1.setDamageValue(damage); + } else { + itemstack1.removeTagKey("Damage"); + } + +- Map map = (Map) EnchantmentHelper.getEnchantments(itemstack).entrySet().stream().filter((entry) -> { ++ Map map = (Map) EnchantmentHelper.getEnchantments(stack).entrySet().stream().filter((entry) -> { + return ((Enchantment) entry.getKey()).isCurse(); + }).collect(Collectors.toMap(Entry::getKey, Entry::getValue)); + +@@ -234,8 +256,8 @@ + itemstack1.setRepairCost(0); + if (itemstack1.is(Items.ENCHANTED_BOOK) && map.size() == 0) { + itemstack1 = new ItemStack(Items.BOOK); +- if (itemstack.hasCustomHoverName()) { +- itemstack1.setHoverName(itemstack.getHoverName()); ++ if (stack.hasCustomHoverName()) { ++ itemstack1.setHoverName(stack.getHoverName()); + } + } + +@@ -247,25 +269,23 @@ + } + + @Override +- @Override +- public void removed(Player player) { ++ public void removed(net.minecraft.world.entity.player.Player player) { + super.removed(player); +- this.access.execute((level, blockpos) -> { ++ this.access.execute((world, blockposition) -> { + this.clearContainer(player, this.repairSlots); + }); + } + + @Override +- @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.GRINDSTONE); + } + + @Override +- @Override +- public ItemStack quickMoveStack(Player player, int i) { ++ public ItemStack quickMoveStack(net.minecraft.world.entity.player.Player player, int index) { + ItemStack itemstack = ItemStack.EMPTY; +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = (Slot) this.slots.get(index); + + if (slot != null && slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); +@@ -274,19 +294,19 @@ + ItemStack itemstack2 = this.repairSlots.getItem(0); + ItemStack itemstack3 = this.repairSlots.getItem(1); + +- if (i == 2) { ++ if (index == 2) { + if (!this.moveItemStackTo(itemstack1, 3, 39, true)) { + return ItemStack.EMPTY; + } + + slot.onQuickCraft(itemstack1, itemstack); +- } else if (i != 0 && i != 1) { ++ } else if (index != 0 && index != 1) { + if (!itemstack2.isEmpty() && !itemstack3.isEmpty()) { +- if (i >= 3 && i < 30) { ++ if (index >= 3 && index < 30) { + if (!this.moveItemStackTo(itemstack1, 30, 39, false)) { + return ItemStack.EMPTY; + } +- } else if (i >= 30 && i < 39 && !this.moveItemStackTo(itemstack1, 3, 30, false)) { ++ } else if (index >= 30 && index < 39 && !this.moveItemStackTo(itemstack1, 3, 30, false)) { + return ItemStack.EMPTY; + } + } else if (!this.moveItemStackTo(itemstack1, 0, 2, false)) { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/HopperMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/HopperMenu.java.patch new file mode 100644 index 0000000000..4ef856587f --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/HopperMenu.java.patch @@ -0,0 +1,98 @@ +--- a/net/minecraft/world/inventory/HopperMenu.java ++++ b/net/minecraft/world/inventory/HopperMenu.java +@@ -6,20 +6,42 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class HopperMenu extends AbstractContainerMenu { + + public static final int CONTAINER_SIZE = 5; + private final Container hopper; + +- public HopperMenu(int i, Inventory inventory) { +- this(i, inventory, new SimpleContainer(5)); ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventory inventory = new CraftInventory(this.hopper); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; + } ++ // CraftBukkit end + +- public HopperMenu(int i, Inventory inventory, Container container) { +- super(MenuType.HOPPER, i); ++ public HopperMenu(int containerId, Inventory playerInventory) { ++ this(containerId, playerInventory, new SimpleContainer(5)); ++ } ++ ++ public HopperMenu(int containerId, Inventory playerInventory, Container container) { ++ super(MenuType.HOPPER, containerId); + this.hopper = container; ++ this.player = playerInventory; // CraftBukkit - save player + checkContainerSize(container, 5); +- container.startOpen(inventory.player); ++ container.startOpen(playerInventory.player); + boolean flag = true; + + int j; +@@ -30,33 +52,32 @@ + + for (j = 0; j < 3; ++j) { + for (int k = 0; k < 9; ++k) { +- this.addSlot(new Slot(inventory, k + j * 9 + 9, 8 + k * 18, j * 18 + 51)); ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, j * 18 + 51)); + } + } + + for (j = 0; j < 9; ++j) { +- this.addSlot(new Slot(inventory, j, 8 + j * 18, 109)); ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 109)); + } + + } + + @Override +- @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.hopper.stillValid(player); + } + + @Override +- @Override +- public ItemStack quickMoveStack(Player player, int i) { ++ public ItemStack quickMoveStack(Player player, int index) { + ItemStack itemstack = ItemStack.EMPTY; +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = (Slot) this.slots.get(index); + + if (slot != null && slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); + + itemstack = itemstack1.copy(); +- if (i < this.hopper.getContainerSize()) { ++ if (index < this.hopper.getContainerSize()) { + if (!this.moveItemStackTo(itemstack1, this.hopper.getContainerSize(), this.slots.size(), true)) { + return ItemStack.EMPTY; + } +@@ -75,7 +96,6 @@ + } + + @Override +- @Override + public void removed(Player player) { + super.removed(player); + this.hopper.stopOpen(player); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/HorseInventoryMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/HorseInventoryMenu.java.patch new file mode 100644 index 0000000000..74e751cdf6 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/HorseInventoryMenu.java.patch @@ -0,0 +1,163 @@ +--- a/net/minecraft/world/inventory/HorseInventoryMenu.java ++++ b/net/minecraft/world/inventory/HorseInventoryMenu.java +@@ -8,48 +8,63 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.inventory.InventoryView; ++// CraftBukkit end ++ + public class HorseInventoryMenu extends AbstractContainerMenu { + + private final Container horseContainer; + private final AbstractHorse horse; + +- public HorseInventoryMenu(int i, Inventory inventory, Container container, final AbstractHorse abstracthorse) { +- super((MenuType) null, i); ++ // CraftBukkit start ++ org.bukkit.craftbukkit.inventory.CraftInventoryView bukkitEntity; ++ Inventory player; ++ ++ @Override ++ public InventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ return bukkitEntity = new CraftInventoryView(player.player.getBukkitEntity(), horseContainer.getOwner().getInventory(), this); ++ } ++ ++ public HorseInventoryMenu(int containerId, Inventory playerInventory, Container container, final AbstractHorse horse) { ++ super((MenuType) null, containerId); ++ player = playerInventory; ++ // CraftBukkit end + this.horseContainer = container; +- this.horse = abstracthorse; ++ this.horse = horse; + boolean flag = true; + +- container.startOpen(inventory.player); ++ container.startOpen(playerInventory.player); + boolean flag1 = true; + + this.addSlot(new Slot(container, 0, 8, 18) { + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { +- return itemstack.is(Items.SADDLE) && !this.hasItem() && abstracthorse.isSaddleable(); ++ public boolean mayPlace(ItemStack stack) { ++ return stack.is(Items.SADDLE) && !this.hasItem() && horse.isSaddleable(); + } + + @Override +- @Override + public boolean isActive() { +- return abstracthorse.isSaddleable(); ++ return horse.isSaddleable(); + } + }); + this.addSlot(new Slot(container, 1, 8, 36) { + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { +- return abstracthorse.isArmor(itemstack); ++ public boolean mayPlace(ItemStack stack) { ++ return horse.isArmor(stack); + } + + @Override +- @Override + public boolean isActive() { +- return abstracthorse.canWearArmor(); ++ return horse.canWearArmor(); + } + + @Override +- @Override + public int getMaxStackSize() { + return 1; + } +@@ -57,41 +72,39 @@ + int j; + int k; + +- if (this.hasChest(abstracthorse)) { ++ if (this.hasChest(horse)) { + for (j = 0; j < 3; ++j) { +- for (k = 0; k < ((AbstractChestedHorse) abstracthorse).getInventoryColumns(); ++k) { +- this.addSlot(new Slot(container, 2 + k + j * ((AbstractChestedHorse) abstracthorse).getInventoryColumns(), 80 + k * 18, 18 + j * 18)); ++ for (k = 0; k < ((AbstractChestedHorse) horse).getInventoryColumns(); ++k) { ++ this.addSlot(new Slot(container, 2 + k + j * ((AbstractChestedHorse) horse).getInventoryColumns(), 80 + k * 18, 18 + j * 18)); + } + } + } + + for (j = 0; j < 3; ++j) { + for (k = 0; k < 9; ++k) { +- this.addSlot(new Slot(inventory, k + j * 9 + 9, 8 + k * 18, 102 + j * 18 + -18)); ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 102 + j * 18 + -18)); + } + } + + for (j = 0; j < 9; ++j) { +- this.addSlot(new Slot(inventory, j, 8 + j * 18, 142)); ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } + + } + + @Override +- @Override + public boolean stillValid(Player player) { + return !this.horse.hasInventoryChanged(this.horseContainer) && this.horseContainer.stillValid(player) && this.horse.isAlive() && this.horse.distanceTo(player) < 8.0F; + } + +- private boolean hasChest(AbstractHorse abstracthorse) { +- return abstracthorse instanceof AbstractChestedHorse && ((AbstractChestedHorse) abstracthorse).hasChest(); ++ private boolean hasChest(AbstractHorse horse) { ++ return horse instanceof AbstractChestedHorse && ((AbstractChestedHorse) horse).hasChest(); + } + + @Override +- @Override +- public ItemStack quickMoveStack(Player player, int i) { ++ public ItemStack quickMoveStack(Player player, int index) { + ItemStack itemstack = ItemStack.EMPTY; +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = (Slot) this.slots.get(index); + + if (slot != null && slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); +@@ -99,7 +112,7 @@ + itemstack = itemstack1.copy(); + int j = this.horseContainer.getContainerSize(); + +- if (i < j) { ++ if (index < j) { + if (!this.moveItemStackTo(itemstack1, j, this.slots.size(), true)) { + return ItemStack.EMPTY; + } +@@ -115,11 +128,11 @@ + int k = j + 27; + int l = k + 9; + +- if (i >= k && i < l) { ++ if (index >= k && index < l) { + if (!this.moveItemStackTo(itemstack1, j, k, false)) { + return ItemStack.EMPTY; + } +- } else if (i >= j && i < k) { ++ } else if (index >= j && index < k) { + if (!this.moveItemStackTo(itemstack1, k, l, false)) { + return ItemStack.EMPTY; + } +@@ -141,7 +154,6 @@ + } + + @Override +- @Override + public void removed(Player player) { + super.removed(player); + this.horseContainer.stopOpen(player); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/InventoryMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/InventoryMenu.java.patch new file mode 100644 index 0000000000..cc70097523 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/InventoryMenu.java.patch @@ -0,0 +1,324 @@ +--- a/net/minecraft/world/inventory/InventoryMenu.java ++++ b/net/minecraft/world/inventory/InventoryMenu.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.inventory; + + import com.mojang.datafixers.util.Pair; ++import net.minecraft.network.chat.Component; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.world.Container; + import net.minecraft.world.entity.EquipmentSlot; +@@ -12,8 +13,11 @@ + import net.minecraft.world.item.crafting.Recipe; + import net.minecraft.world.item.crafting.RecipeHolder; + import net.minecraft.world.item.enchantment.EnchantmentHelper; ++import org.bukkit.craftbukkit.inventory.CraftInventoryCrafting; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + +-public class InventoryMenu extends RecipeBookMenu { ++public class InventoryMenu extends RecipeBookMenu { + + public static final int CONTAINER_ID = 0; + public static final int RESULT_SLOT = 0; +@@ -34,16 +38,29 @@ + public static final ResourceLocation EMPTY_ARMOR_SLOT_SHIELD = new ResourceLocation("item/empty_armor_slot_shield"); + static final ResourceLocation[] TEXTURE_EMPTY_SLOTS = new ResourceLocation[]{InventoryMenu.EMPTY_ARMOR_SLOT_BOOTS, InventoryMenu.EMPTY_ARMOR_SLOT_LEGGINGS, InventoryMenu.EMPTY_ARMOR_SLOT_CHESTPLATE, InventoryMenu.EMPTY_ARMOR_SLOT_HELMET}; + private static final EquipmentSlot[] SLOT_IDS = new EquipmentSlot[]{EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET}; +- private final CraftingContainer craftSlots = new TransientCraftingContainer(this, 2, 2); +- private final ResultContainer resultSlots = new ResultContainer(); ++ // CraftBukkit start ++ private final TransientCraftingContainer craftSlots; ++ private final ResultContainer resultSlots; ++ // CraftBukkit end + public final boolean active; + private final Player owner; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ // CraftBukkit end + +- public InventoryMenu(Inventory inventory, boolean flag, final Player player) { ++ public InventoryMenu(Inventory playerInventory, boolean active, final Player owner) { + super((MenuType) null, 0); +- this.active = flag; +- this.owner = player; +- this.addSlot(new ResultSlot(inventory.player, this.craftSlots, this.resultSlots, 0, 154, 28)); ++ this.active = active; ++ this.owner = owner; ++ // CraftBukkit start ++ this.resultSlots = new ResultContainer(); // CraftBukkit - moved to before InventoryCrafting construction ++ this.craftSlots = new TransientCraftingContainer(this, 2, 2, playerInventory.player); // CraftBukkit - pass player ++ this.craftSlots.resultInventory = this.resultSlots; // CraftBukkit - let InventoryCrafting know about its result slot ++ this.player = playerInventory; // CraftBukkit - save player ++ setTitle(Component.translatable("container.crafting")); // SPIGOT-4722: Allocate title for player inventory ++ // CraftBukkit end ++ this.addSlot(new ResultSlot(playerInventory.player, this.craftSlots, this.resultSlots, 0, 154, 28)); + + int i; + int j; +@@ -55,105 +72,93 @@ + } + + for (i = 0; i < 4; ++i) { +- final EquipmentSlot equipmentslot = InventoryMenu.SLOT_IDS[i]; ++ final EquipmentSlot enumitemslot = InventoryMenu.SLOT_IDS[i]; + +- this.addSlot(new Slot(inventory, 39 - i, 8, 8 + i * 18) { ++ this.addSlot(new Slot(playerInventory, 39 - i, 8, 8 + i * 18) { + @Override +- @Override + public void setByPlayer(ItemStack itemstack, ItemStack itemstack1) { +- InventoryMenu.onEquipItem(player, equipmentslot, itemstack, itemstack1); ++ InventoryMenu.onEquipItem(owner, enumitemslot, itemstack, itemstack1); + super.setByPlayer(itemstack, itemstack1); + } + + @Override +- @Override + public int getMaxStackSize() { + return 1; + } + + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { +- return equipmentslot == Mob.getEquipmentSlotForItem(itemstack); ++ public boolean mayPlace(ItemStack stack) { ++ return enumitemslot == Mob.getEquipmentSlotForItem(stack); + } + + @Override +- @Override +- public boolean mayPickup(Player player1) { ++ public boolean mayPickup(Player player) { + ItemStack itemstack = this.getItem(); + +- return !itemstack.isEmpty() && !player1.isCreative() && EnchantmentHelper.hasBindingCurse(itemstack) ? false : super.mayPickup(player1); ++ return !itemstack.isEmpty() && !player.isCreative() && EnchantmentHelper.hasBindingCurse(itemstack) ? false : super.mayPickup(player); + } + + @Override +- @Override + public Pair getNoItemIcon() { +- return Pair.of(InventoryMenu.BLOCK_ATLAS, InventoryMenu.TEXTURE_EMPTY_SLOTS[equipmentslot.getIndex()]); ++ return Pair.of(InventoryMenu.BLOCK_ATLAS, InventoryMenu.TEXTURE_EMPTY_SLOTS[enumitemslot.getIndex()]); + } + }); + } + + for (i = 0; i < 3; ++i) { + for (j = 0; j < 9; ++j) { +- this.addSlot(new Slot(inventory, j + (i + 1) * 9, 8 + j * 18, 84 + i * 18)); ++ this.addSlot(new Slot(playerInventory, j + (i + 1) * 9, 8 + j * 18, 84 + i * 18)); + } + } + + for (i = 0; i < 9; ++i) { +- this.addSlot(new Slot(inventory, i, 8 + i * 18, 142)); ++ this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142)); + } + +- this.addSlot(new Slot(inventory, 40, 77, 62) { ++ this.addSlot(new Slot(playerInventory, 40, 77, 62) { + @Override +- @Override + public void setByPlayer(ItemStack itemstack, ItemStack itemstack1) { +- InventoryMenu.onEquipItem(player, EquipmentSlot.OFFHAND, itemstack, itemstack1); ++ InventoryMenu.onEquipItem(owner, EquipmentSlot.OFFHAND, itemstack, itemstack1); + super.setByPlayer(itemstack, itemstack1); + } + + @Override +- @Override + public Pair getNoItemIcon() { + return Pair.of(InventoryMenu.BLOCK_ATLAS, InventoryMenu.EMPTY_ARMOR_SLOT_SHIELD); + } + }); + } + +- static void onEquipItem(Player player, EquipmentSlot equipmentslot, ItemStack itemstack, ItemStack itemstack1) { +- player.onEquipItem(equipmentslot, itemstack1, itemstack); ++ static void onEquipItem(Player player, EquipmentSlot slot, ItemStack newItem, ItemStack oldItem) { ++ player.onEquipItem(slot, oldItem, newItem); + } + +- public static boolean isHotbarSlot(int i) { +- return i >= 36 && i < 45 || i == 45; ++ public static boolean isHotbarSlot(int index) { ++ return index >= 36 && index < 45 || index == 45; + } + + @Override +- @Override +- public void fillCraftSlotsStackedContents(StackedContents stackedcontents) { +- this.craftSlots.fillStackedContents(stackedcontents); ++ public void fillCraftSlotsStackedContents(StackedContents itemHelper) { ++ this.craftSlots.fillStackedContents(itemHelper); + } + + @Override +- @Override + public void clearCraftingContent() { + this.resultSlots.clearContent(); + this.craftSlots.clearContent(); + } + + @Override +- @Override +- public boolean recipeMatches(RecipeHolder> recipeholder) { ++ public boolean recipeMatches(RecipeHolder> recipeholder) { + return recipeholder.value().matches(this.craftSlots, this.owner.level()); + } + + @Override +- @Override +- public void slotsChanged(Container container) { ++ public void slotsChanged(Container inventory) { + CraftingMenu.slotChangedCraftingGrid(this, this.owner.level(), this.owner, this.craftSlots, this.resultSlots); + } + + @Override +- @Override + public void removed(Player player) { + super.removed(player); + this.resultSlots.clearContent(); +@@ -163,52 +168,50 @@ + } + + @Override +- @Override + public boolean stillValid(Player player) { + return true; + } + + @Override +- @Override +- public ItemStack quickMoveStack(Player player, int i) { ++ public ItemStack quickMoveStack(Player player, int index) { + ItemStack itemstack = ItemStack.EMPTY; +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = (Slot) this.slots.get(index); + + if (slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); + + itemstack = itemstack1.copy(); +- EquipmentSlot equipmentslot = Mob.getEquipmentSlotForItem(itemstack); ++ EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(itemstack); + +- if (i == 0) { ++ if (index == 0) { + if (!this.moveItemStackTo(itemstack1, 9, 45, true)) { + return ItemStack.EMPTY; + } + + slot.onQuickCraft(itemstack1, itemstack); +- } else if (i >= 1 && i < 5) { ++ } else if (index >= 1 && index < 5) { + if (!this.moveItemStackTo(itemstack1, 9, 45, false)) { + return ItemStack.EMPTY; + } +- } else if (i >= 5 && i < 9) { ++ } else if (index >= 5 && index < 9) { + if (!this.moveItemStackTo(itemstack1, 9, 45, false)) { + return ItemStack.EMPTY; + } +- } else if (equipmentslot.getType() == EquipmentSlot.Type.ARMOR && !((Slot) this.slots.get(8 - equipmentslot.getIndex())).hasItem()) { +- int j = 8 - equipmentslot.getIndex(); ++ } else if (enumitemslot.getType() == EquipmentSlot.Function.ARMOR && !((Slot) this.slots.get(8 - enumitemslot.getIndex())).hasItem()) { ++ int j = 8 - enumitemslot.getIndex(); + + if (!this.moveItemStackTo(itemstack1, j, j + 1, false)) { + return ItemStack.EMPTY; + } +- } else if (equipmentslot == EquipmentSlot.OFFHAND && !((Slot) this.slots.get(45)).hasItem()) { ++ } else if (enumitemslot == EquipmentSlot.OFFHAND && !((Slot) this.slots.get(45)).hasItem()) { + if (!this.moveItemStackTo(itemstack1, 45, 46, false)) { + return ItemStack.EMPTY; + } +- } else if (i >= 9 && i < 36) { ++ } else if (index >= 9 && index < 36) { + if (!this.moveItemStackTo(itemstack1, 36, 45, false)) { + return ItemStack.EMPTY; + } +- } else if (i >= 36 && i < 45) { ++ } else if (index >= 36 && index < 45) { + if (!this.moveItemStackTo(itemstack1, 9, 36, false)) { + return ItemStack.EMPTY; + } +@@ -227,7 +230,7 @@ + } + + slot.onTake(player, itemstack1); +- if (i == 0) { ++ if (index == 0) { + player.drop(itemstack1, false); + } + } +@@ -236,48 +239,54 @@ + } + + @Override +- @Override +- public boolean canTakeItemForPickAll(ItemStack itemstack, Slot slot) { +- return slot.container != this.resultSlots && super.canTakeItemForPickAll(itemstack, slot); ++ public boolean canTakeItemForPickAll(ItemStack stack, Slot slot) { ++ return slot.container != this.resultSlots && super.canTakeItemForPickAll(stack, slot); + } + + @Override +- @Override + public int getResultSlotIndex() { + return 0; + } + + @Override +- @Override + public int getGridWidth() { + return this.craftSlots.getWidth(); + } + + @Override +- @Override + public int getGridHeight() { + return this.craftSlots.getHeight(); + } + + @Override +- @Override + public int getSize() { + return 5; + } + +- public CraftingContainer getCraftSlots() { ++ public InventoryCrafting getCraftSlots() { + return this.craftSlots; + } + + @Override +- @Override + public RecipeBookType getRecipeBookType() { + return RecipeBookType.CRAFTING; + } + + @Override ++ public boolean shouldMoveToInventory(int slotIndex) { ++ return slotIndex != this.getResultSlotIndex(); ++ } ++ ++ // CraftBukkit start + @Override +- public boolean shouldMoveToInventory(int i) { +- return i != this.getResultSlotIndex(); ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryCrafting inventory = new CraftInventoryCrafting(this.craftSlots, this.resultSlots); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; + } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/ItemCombinerMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/ItemCombinerMenu.java.patch new file mode 100644 index 0000000000..2d409a34ad --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/ItemCombinerMenu.java.patch @@ -0,0 +1,193 @@ +--- a/net/minecraft/world/inventory/ItemCombinerMenu.java ++++ b/net/minecraft/world/inventory/ItemCombinerMenu.java +@@ -8,7 +8,7 @@ + import net.minecraft.world.entity.player.Inventory; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public abstract class ItemCombinerMenu extends AbstractContainerMenu { + +@@ -25,12 +25,12 @@ + + protected abstract void onTake(Player player, ItemStack stack); + +- protected abstract boolean isValidBlock(BlockState state); ++ protected abstract boolean isValidBlock(IBlockData state); + +- public ItemCombinerMenu(@Nullable MenuType menutype, int i, Inventory inventory, ContainerLevelAccess containerlevelaccess) { +- super(menutype, i); +- this.access = containerlevelaccess; +- this.player = inventory.player; ++ public ItemCombinerMenu(@Nullable MenuType type, int containerId, Inventory playerInventory, ContainerLevelAccess access) { ++ super(type, containerId); ++ this.access = access; ++ this.player = playerInventory.player; + ItemCombinerMenuSlotDefinition itemcombinermenuslotdefinition = this.createInputSlotDefinitions(); + + this.inputSlots = this.createContainer(itemcombinermenuslotdefinition.getNumOfInputSlots()); +@@ -38,44 +38,40 @@ + this.resultSlotIndex = itemcombinermenuslotdefinition.getResultSlotIndex(); + this.createInputSlots(itemcombinermenuslotdefinition); + this.createResultSlot(itemcombinermenuslotdefinition); +- this.createInventorySlots(inventory); ++ this.createInventorySlots(playerInventory); + } + +- private void createInputSlots(ItemCombinerMenuSlotDefinition itemcombinermenuslotdefinition) { +- Iterator iterator = itemcombinermenuslotdefinition.getSlots().iterator(); ++ private void createInputSlots(ItemCombinerMenuSlotDefinition slotDefinition) { ++ Iterator iterator = slotDefinition.getSlots().iterator(); + + while (iterator.hasNext()) { +- final ItemCombinerMenuSlotDefinition.SlotDefinition itemcombinermenuslotdefinition_slotdefinition = (ItemCombinerMenuSlotDefinition.SlotDefinition) iterator.next(); ++ final ItemCombinerMenuSlotDefinition.b itemcombinermenuslotdefinition_b = (ItemCombinerMenuSlotDefinition.b) iterator.next(); + +- this.addSlot(new Slot(this.inputSlots, itemcombinermenuslotdefinition_slotdefinition.slotIndex(), itemcombinermenuslotdefinition_slotdefinition.x(), itemcombinermenuslotdefinition_slotdefinition.y()) { ++ this.addSlot(new Slot(this.inputSlots, itemcombinermenuslotdefinition_b.slotIndex(), itemcombinermenuslotdefinition_b.x(), itemcombinermenuslotdefinition_b.y()) { + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { +- return itemcombinermenuslotdefinition_slotdefinition.mayPlace().test(itemstack); ++ public boolean mayPlace(ItemStack stack) { ++ return itemcombinermenuslotdefinition_b.mayPlace().test(stack); + } + }); + } + + } + +- private void createResultSlot(ItemCombinerMenuSlotDefinition itemcombinermenuslotdefinition) { +- this.addSlot(new Slot(this.resultSlots, itemcombinermenuslotdefinition.getResultSlot().slotIndex(), itemcombinermenuslotdefinition.getResultSlot().x(), itemcombinermenuslotdefinition.getResultSlot().y()) { ++ private void createResultSlot(ItemCombinerMenuSlotDefinition slotDefinition) { ++ this.addSlot(new Slot(this.resultSlots, slotDefinition.getResultSlot().slotIndex(), slotDefinition.getResultSlot().x(), slotDefinition.getResultSlot().y()) { + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { ++ public boolean mayPlace(ItemStack stack) { + return false; + } + + @Override +- @Override + public boolean mayPickup(Player player) { + return ItemCombinerMenu.this.mayPickup(player, this.hasItem()); + } + + @Override +- @Override +- public void onTake(Player player, ItemStack itemstack) { +- ItemCombinerMenu.this.onTake(player, itemstack); ++ public void onTake(Player player, ItemStack stack) { ++ ItemCombinerMenu.this.onTake(player, stack); + } + }); + } +@@ -99,10 +95,9 @@ + + protected abstract ItemCombinerMenuSlotDefinition createInputSlotDefinitions(); + +- private SimpleContainer createContainer(int i) { +- return new SimpleContainer(i) { ++ private SimpleContainer createContainer(int size) { ++ return new SimpleContainer(size) { + @Override +- @Override + public void setChanged() { + super.setChanged(); + ItemCombinerMenu.this.slotsChanged(this); +@@ -111,37 +106,34 @@ + } + + @Override +- @Override +- public void slotsChanged(Container container) { +- super.slotsChanged(container); +- if (container == this.inputSlots) { ++ public void slotsChanged(Container inventory) { ++ super.slotsChanged(inventory); ++ if (inventory == this.inputSlots) { + this.createResult(); + } + + } + + @Override +- @Override + public void removed(Player player) { + super.removed(player); +- this.access.execute((level, blockpos) -> { ++ this.access.execute((world, blockposition) -> { + this.clearContainer(player, this.inputSlots); + }); + } + + @Override +- @Override + public boolean stillValid(Player player) { +- return (Boolean) this.access.evaluate((level, blockpos) -> { +- return !this.isValidBlock(level.getBlockState(blockpos)) ? false : player.distanceToSqr((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D) <= 64.0D; ++ if (!this.checkReachable) return true; // CraftBukkit ++ return (Boolean) this.access.evaluate((world, blockposition) -> { ++ return !this.isValidBlock(world.getBlockState(blockposition)) ? false : player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) <= 64.0D; + }, true); + } + + @Override +- @Override +- public ItemStack quickMoveStack(Player player, int i) { ++ public ItemStack quickMoveStack(Player player, int index) { + ItemStack itemstack = ItemStack.EMPTY; +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = (Slot) this.slots.get(index); + + if (slot != null && slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); +@@ -150,27 +142,27 @@ + int j = this.getInventorySlotStart(); + int k = this.getUseRowEnd(); + +- if (i == this.getResultSlot()) { ++ if (index == this.getResultSlot()) { + if (!this.moveItemStackTo(itemstack1, j, k, true)) { + return ItemStack.EMPTY; + } + + slot.onQuickCraft(itemstack1, itemstack); +- } else if (this.inputSlotIndexes.contains(i)) { ++ } else if (this.inputSlotIndexes.contains(index)) { + if (!this.moveItemStackTo(itemstack1, j, k, false)) { + return ItemStack.EMPTY; + } +- } else if (this.canMoveIntoInputSlots(itemstack1) && i >= this.getInventorySlotStart() && i < this.getUseRowEnd()) { ++ } else if (this.canMoveIntoInputSlots(itemstack1) && index >= this.getInventorySlotStart() && index < this.getUseRowEnd()) { + int l = this.getSlotToQuickMoveTo(itemstack); + + if (!this.moveItemStackTo(itemstack1, l, this.getResultSlot(), false)) { + return ItemStack.EMPTY; + } +- } else if (i >= this.getInventorySlotStart() && i < this.getInventorySlotEnd()) { ++ } else if (index >= this.getInventorySlotStart() && index < this.getInventorySlotEnd()) { + if (!this.moveItemStackTo(itemstack1, this.getUseRowStart(), this.getUseRowEnd(), false)) { + return ItemStack.EMPTY; + } +- } else if (i >= this.getUseRowStart() && i < this.getUseRowEnd() && !this.moveItemStackTo(itemstack1, this.getInventorySlotStart(), this.getInventorySlotEnd(), false)) { ++ } else if (index >= this.getUseRowStart() && index < this.getUseRowEnd() && !this.moveItemStackTo(itemstack1, this.getInventorySlotStart(), this.getInventorySlotEnd(), false)) { + return ItemStack.EMPTY; + } + +@@ -190,11 +182,11 @@ + return itemstack; + } + +- protected boolean canMoveIntoInputSlots(ItemStack itemstack) { ++ protected boolean canMoveIntoInputSlots(ItemStack stack) { + return true; + } + +- public int getSlotToQuickMoveTo(ItemStack itemstack) { ++ public int getSlotToQuickMoveTo(ItemStack stack) { + return this.inputSlots.isEmpty() ? 0 : (Integer) this.inputSlotIndexes.get(0); + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/LecternMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/LecternMenu.java.patch new file mode 100644 index 0000000000..be18e38036 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/LecternMenu.java.patch @@ -0,0 +1,134 @@ +--- a/net/minecraft/world/inventory/LecternMenu.java ++++ b/net/minecraft/world/inventory/LecternMenu.java +@@ -2,11 +2,33 @@ + + import net.minecraft.world.Container; + import net.minecraft.world.SimpleContainer; +-import net.minecraft.world.entity.player.Player; ++import net.minecraft.world.entity.player.Inventory; + import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.level.block.entity.LecternBlockEntity.LecternInventory; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.inventory.CraftInventoryLectern; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerTakeLecternBookEvent; ++// CraftBukkit end + + public class LecternMenu extends AbstractContainerMenu { + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryLectern inventory = new CraftInventoryLectern(this.lectern); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + private static final int DATA_COUNT = 1; + private static final int SLOT_COUNT = 1; + public static final int BUTTON_PREV_PAGE = 1; +@@ -16,38 +38,39 @@ + private final Container lectern; + private final ContainerData lecternData; + +- public LecternMenu(int i) { +- this(i, new SimpleContainer(1), new SimpleContainerData(1)); ++ // CraftBukkit start - add player ++ public LecternMenu(int i, Inventory playerinventory) { ++ this(i, new SimpleContainer(1), new SimpleContainerData(1), playerinventory); + } + +- public LecternMenu(int i, Container container, ContainerData containerdata) { ++ public LecternMenu(int i, Container iinventory, ContainerData icontainerproperties, Inventory playerinventory) { ++ // CraftBukkit end + super(MenuType.LECTERN, i); +- checkContainerSize(container, 1); +- checkContainerDataCount(containerdata, 1); +- this.lectern = container; +- this.lecternData = containerdata; +- this.addSlot(new Slot(container, 0, 0, 0) { ++ checkContainerSize(iinventory, 1); ++ checkContainerDataCount(icontainerproperties, 1); ++ this.lectern = iinventory; ++ this.lecternData = icontainerproperties; ++ this.addSlot(new Slot(iinventory, 0, 0, 0) { + @Override +- @Override + public void setChanged() { + super.setChanged(); + LecternMenu.this.slotsChanged(this.container); + } + }); +- this.addDataSlots(containerdata); ++ this.addDataSlots(icontainerproperties); ++ player = (Player) playerinventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override +- @Override +- public boolean clickMenuButton(Player player, int i) { ++ public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { + int j; + +- if (i >= 100) { +- j = i - 100; ++ if (id >= 100) { ++ j = id - 100; + this.setData(0, j); + return true; + } else { +- switch (i) { ++ switch (id) { + case 1: + j = this.lecternData.get(0); + this.setData(0, j - 1); +@@ -61,6 +84,13 @@ + return false; + } + ++ // CraftBukkit start - Event for taking the book ++ PlayerTakeLecternBookEvent event = new PlayerTakeLecternBookEvent(player, ((CraftInventoryLectern) getBukkitView().getTopInventory()).getHolder()); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end + ItemStack itemstack = this.lectern.removeItemNoUpdate(0); + + this.lectern.setChanged(); +@@ -76,21 +106,20 @@ + } + + @Override +- @Override +- public ItemStack quickMoveStack(Player player, int i) { ++ public ItemStack quickMoveStack(net.minecraft.world.entity.player.Player player, int index) { + return ItemStack.EMPTY; + } + + @Override +- @Override +- public void setData(int i, int j) { +- super.setData(i, j); ++ public void setData(int id, int data) { ++ super.setData(id, data); + this.broadcastChanges(); + } + + @Override +- @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (lectern instanceof LecternInventory && !((LecternInventory) lectern).getLectern().hasBook()) return false; // CraftBukkit ++ if (!this.checkReachable) return true; // CraftBukkit + return this.lectern.stillValid(player); + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/LoomMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/LoomMenu.java.patch new file mode 100644 index 0000000000..5e940721a3 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/LoomMenu.java.patch @@ -0,0 +1,354 @@ +--- a/net/minecraft/world/inventory/LoomMenu.java ++++ b/net/minecraft/world/inventory/LoomMenu.java +@@ -12,7 +12,6 @@ + import net.minecraft.world.Container; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.entity.player.Inventory; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.BannerItem; + import net.minecraft.world.item.BannerPatternItem; + import net.minecraft.world.item.BlockItem; +@@ -23,9 +22,30 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.BannerPattern; + import net.minecraft.world.level.block.entity.BlockEntityType; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.inventory.CraftInventoryLoom; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class LoomMenu extends AbstractContainerMenu { + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryLoom inventory = new CraftInventoryLoom(this.inputContainer, this.outputContainer); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + private static final int PATTERN_NOT_SET = -1; + private static final int INV_SLOT_START = 4; + private static final int INV_SLOT_END = 31; +@@ -43,81 +63,88 @@ + private final Container inputContainer; + private final Container outputContainer; + +- public LoomMenu(int i, Inventory inventory) { +- this(i, inventory, ContainerLevelAccess.NULL); ++ public LoomMenu(int containerId, Inventory playerInventory) { ++ this(containerId, playerInventory, ContainerLevelAccess.NULL); + } + +- public LoomMenu(int i, Inventory inventory, final ContainerLevelAccess containerlevelaccess) { +- super(MenuType.LOOM, i); ++ public LoomMenu(int containerId, Inventory playerInventory, final ContainerLevelAccess access) { ++ super(MenuType.LOOM, containerId); + this.selectedBannerPatternIndex = DataSlot.standalone(); + this.selectablePatterns = List.of(); + this.slotUpdateListener = () -> { + }; + this.inputContainer = new SimpleContainer(3) { + @Override +- @Override + public void setChanged() { + super.setChanged(); + LoomMenu.this.slotsChanged(this); + LoomMenu.this.slotUpdateListener.run(); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end + }; + this.outputContainer = new SimpleContainer(1) { + @Override +- @Override + public void setChanged() { + super.setChanged(); + LoomMenu.this.slotUpdateListener.run(); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end + }; +- this.access = containerlevelaccess; ++ this.access = access; + this.bannerSlot = this.addSlot(new Slot(this.inputContainer, 0, 13, 26) { + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { +- return itemstack.getItem() instanceof BannerItem; ++ public boolean mayPlace(ItemStack stack) { ++ return stack.getItem() instanceof BannerItem; + } + }); + this.dyeSlot = this.addSlot(new Slot(this.inputContainer, 1, 33, 26) { + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { +- return itemstack.getItem() instanceof DyeItem; ++ public boolean mayPlace(ItemStack stack) { ++ return stack.getItem() instanceof DyeItem; + } + }); + this.patternSlot = this.addSlot(new Slot(this.inputContainer, 2, 23, 45) { + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { +- return itemstack.getItem() instanceof BannerPatternItem; ++ public boolean mayPlace(ItemStack stack) { ++ return stack.getItem() instanceof BannerPatternItem; + } + }); + this.resultSlot = this.addSlot(new Slot(this.outputContainer, 0, 143, 57) { + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { ++ public boolean mayPlace(ItemStack stack) { + return false; + } + + @Override +- @Override +- public void onTake(Player player, ItemStack itemstack) { ++ public void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) { + LoomMenu.this.bannerSlot.remove(1); + LoomMenu.this.dyeSlot.remove(1); + if (!LoomMenu.this.bannerSlot.hasItem() || !LoomMenu.this.dyeSlot.hasItem()) { + LoomMenu.this.selectedBannerPatternIndex.set(-1); + } + +- containerlevelaccess.execute((level, blockpos) -> { +- long j = level.getGameTime(); ++ access.execute((world, blockposition) -> { ++ long j = world.getGameTime(); + + if (LoomMenu.this.lastSoundTime != j) { +- level.playSound((Player) null, blockpos, SoundEvents.UI_LOOM_TAKE_RESULT, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.playSound((net.minecraft.world.entity.player.Player) null, blockposition, SoundEvents.UI_LOOM_TAKE_RESULT, SoundSource.BLOCKS, 1.0F, 1.0F); + LoomMenu.this.lastSoundTime = j; + } + + }); +- super.onTake(player, itemstack); ++ super.onTake(player, stack); + } + }); + +@@ -125,58 +152,57 @@ + + for (j = 0; j < 3; ++j) { + for (int k = 0; k < 9; ++k) { +- this.addSlot(new Slot(inventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); + } + } + + for (j = 0; j < 9; ++j) { +- this.addSlot(new Slot(inventory, j, 8 + j * 18, 142)); ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } + + this.addDataSlot(this.selectedBannerPatternIndex); ++ player = (Player) playerInventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override +- @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.LOOM); + } + + @Override +- @Override +- public boolean clickMenuButton(Player player, int i) { +- if (i >= 0 && i < this.selectablePatterns.size()) { +- this.selectedBannerPatternIndex.set(i); +- this.setupResultSlot((Holder) this.selectablePatterns.get(i)); ++ public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { ++ if (id >= 0 && id < this.selectablePatterns.size()) { ++ this.selectedBannerPatternIndex.set(id); ++ this.setupResultSlot((Holder) this.selectablePatterns.get(id)); + return true; + } else { + return false; + } + } + +- private List> getSelectablePatterns(ItemStack itemstack) { +- if (itemstack.isEmpty()) { ++ private List> getSelectablePatterns(ItemStack stack) { ++ if (stack.isEmpty()) { + return (List) BuiltInRegistries.BANNER_PATTERN.getTag(BannerPatternTags.NO_ITEM_REQUIRED).map(ImmutableList::copyOf).orElse(ImmutableList.of()); + } else { +- Item item = itemstack.getItem(); ++ Item item = stack.getItem(); + + if (item instanceof BannerPatternItem) { +- BannerPatternItem bannerpatternitem = (BannerPatternItem) item; ++ BannerPatternItem itembannerpattern = (BannerPatternItem) item; + +- return (List) BuiltInRegistries.BANNER_PATTERN.getTag(bannerpatternitem.getBannerPattern()).map(ImmutableList::copyOf).orElse(ImmutableList.of()); ++ return (List) BuiltInRegistries.BANNER_PATTERN.getTag(itembannerpattern.getBannerPattern()).map(ImmutableList::copyOf).orElse(ImmutableList.of()); + } else { + return List.of(); + } + } + } + +- private boolean isValidPatternIndex(int i) { +- return i >= 0 && i < this.selectablePatterns.size(); ++ private boolean isValidPatternIndex(int index) { ++ return index >= 0 && index < this.selectablePatterns.size(); + } + + @Override +- @Override +- public void slotsChanged(Container container) { ++ public void slotsChanged(Container inventory) { + ItemStack itemstack = this.bannerSlot.getItem(); + ItemStack itemstack1 = this.dyeSlot.getItem(); + ItemStack itemstack2 = this.patternSlot.getItem(); +@@ -209,8 +235,8 @@ + } + + if (holder != null) { +- CompoundTag compoundtag = BlockItem.getBlockEntityData(itemstack); +- boolean flag1 = compoundtag != null && compoundtag.contains("Patterns", 9) && !itemstack.isEmpty() && compoundtag.getList("Patterns", 10).size() >= 6; ++ CompoundTag nbttagcompound = BlockItem.getBlockEntityData(itemstack); ++ boolean flag1 = nbttagcompound != null && nbttagcompound.contains("Patterns", 9) && !itemstack.isEmpty() && nbttagcompound.getList("Patterns", 10).size() >= 6; + + if (flag1) { + this.selectedBannerPatternIndex.set(-1); +@@ -238,27 +264,26 @@ + return this.selectedBannerPatternIndex.get(); + } + +- public void registerUpdateListener(Runnable runnable) { +- this.slotUpdateListener = runnable; ++ public void registerUpdateListener(Runnable listener) { ++ this.slotUpdateListener = listener; + } + + @Override +- @Override +- public ItemStack quickMoveStack(Player player, int i) { ++ public ItemStack quickMoveStack(net.minecraft.world.entity.player.Player player, int index) { + ItemStack itemstack = ItemStack.EMPTY; +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = (Slot) this.slots.get(index); + + if (slot != null && slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); + + itemstack = itemstack1.copy(); +- if (i == this.resultSlot.index) { ++ if (index == this.resultSlot.index) { + if (!this.moveItemStackTo(itemstack1, 4, 40, true)) { + return ItemStack.EMPTY; + } + + slot.onQuickCraft(itemstack1, itemstack); +- } else if (i != this.dyeSlot.index && i != this.bannerSlot.index && i != this.patternSlot.index) { ++ } else if (index != this.dyeSlot.index && index != this.bannerSlot.index && index != this.patternSlot.index) { + if (itemstack1.getItem() instanceof BannerItem) { + if (!this.moveItemStackTo(itemstack1, this.bannerSlot.index, this.bannerSlot.index + 1, false)) { + return ItemStack.EMPTY; +@@ -271,11 +296,11 @@ + if (!this.moveItemStackTo(itemstack1, this.patternSlot.index, this.patternSlot.index + 1, false)) { + return ItemStack.EMPTY; + } +- } else if (i >= 4 && i < 31) { ++ } else if (index >= 4 && index < 31) { + if (!this.moveItemStackTo(itemstack1, 31, 40, false)) { + return ItemStack.EMPTY; + } +- } else if (i >= 31 && i < 40 && !this.moveItemStackTo(itemstack1, 4, 31, false)) { ++ } else if (index >= 31 && index < 40 && !this.moveItemStackTo(itemstack1, 4, 31, false)) { + return ItemStack.EMPTY; + } + } else if (!this.moveItemStackTo(itemstack1, 4, 40, false)) { +@@ -299,42 +324,46 @@ + } + + @Override +- @Override +- public void removed(Player player) { ++ public void removed(net.minecraft.world.entity.player.Player player) { + super.removed(player); +- this.access.execute((level, blockpos) -> { ++ this.access.execute((world, blockposition) -> { + this.clearContainer(player, this.inputContainer); + }); + } + +- private void setupResultSlot(Holder holder) { ++ private void setupResultSlot(Holder pattern) { + ItemStack itemstack = this.bannerSlot.getItem(); + ItemStack itemstack1 = this.dyeSlot.getItem(); + ItemStack itemstack2 = ItemStack.EMPTY; + + if (!itemstack.isEmpty() && !itemstack1.isEmpty()) { + itemstack2 = itemstack.copyWithCount(1); +- DyeColor dyecolor = ((DyeItem) itemstack1.getItem()).getDyeColor(); +- CompoundTag compoundtag = BlockItem.getBlockEntityData(itemstack2); +- ListTag listtag; ++ DyeColor enumcolor = ((DyeItem) itemstack1.getItem()).getDyeColor(); ++ CompoundTag nbttagcompound = BlockItem.getBlockEntityData(itemstack2); ++ ListTag nbttaglist; + +- if (compoundtag != null && compoundtag.contains("Patterns", 9)) { +- listtag = compoundtag.getList("Patterns", 10); ++ if (nbttagcompound != null && nbttagcompound.contains("Patterns", 9)) { ++ nbttaglist = nbttagcompound.getList("Patterns", 10); ++ // CraftBukkit start ++ while (nbttaglist.size() > 20) { ++ nbttaglist.remove(20); ++ } ++ // CraftBukkit end + } else { +- listtag = new ListTag(); +- if (compoundtag == null) { +- compoundtag = new CompoundTag(); ++ nbttaglist = new ListTag(); ++ if (nbttagcompound == null) { ++ nbttagcompound = new CompoundTag(); + } + +- compoundtag.put("Patterns", listtag); ++ nbttagcompound.put("Patterns", nbttaglist); + } + +- CompoundTag compoundtag1 = new CompoundTag(); ++ CompoundTag nbttagcompound1 = new CompoundTag(); + +- compoundtag1.putString("Pattern", ((BannerPattern) holder.value()).getHashname()); +- compoundtag1.putInt("Color", dyecolor.getId()); +- listtag.add(compoundtag1); +- BlockItem.setBlockEntityData(itemstack2, BlockEntityType.BANNER, compoundtag); ++ nbttagcompound1.putString("Pattern", ((BannerPattern) pattern.value()).getHashname()); ++ nbttagcompound1.putInt("Color", enumcolor.getId()); ++ nbttaglist.add(nbttagcompound1); ++ BlockItem.setBlockEntityData(itemstack2, BlockEntityType.BANNER, nbttagcompound); + } + + if (!ItemStack.matches(itemstack2, this.resultSlot.getItem())) { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/MenuType.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/MenuType.java.patch new file mode 100644 index 0000000000..3be6e62017 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/MenuType.java.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/world/inventory/MenuType.java ++++ b/net/minecraft/world/inventory/MenuType.java +@@ -27,8 +27,8 @@ + public static final MenuType FURNACE = register("furnace", FurnaceMenu::new); + public static final MenuType GRINDSTONE = register("grindstone", GrindstoneMenu::new); + public static final MenuType HOPPER = register("hopper", HopperMenu::new); +- public static final MenuType LECTERN = register("lectern", (i, inventory) -> { +- return new LecternMenu(i); ++ public static final MenuType LECTERN = register("lectern", (i, playerinventory) -> { ++ return new LecternMenu(i, playerinventory); // CraftBukkit + }); + public static final MenuType LOOM = register("loom", LoomMenu::new); + public static final MenuType MERCHANT = register("merchant", MerchantMenu::new); +@@ -40,25 +40,24 @@ + private final FeatureFlagSet requiredFeatures; + private final MenuType.MenuSupplier constructor; + +- private static MenuType register(String s, MenuType.MenuSupplier menutype_menusupplier) { +- return (MenuType) Registry.register(BuiltInRegistries.MENU, s, new MenuType<>(menutype_menusupplier, FeatureFlags.VANILLA_SET)); ++ private static MenuType register(String key, MenuType.MenuSupplier factory) { ++ return (MenuType) Registry.register(BuiltInRegistries.MENU, key, new MenuType<>(factory, FeatureFlags.VANILLA_SET)); + } + +- private static MenuType register(String s, MenuType.MenuSupplier menutype_menusupplier, FeatureFlag... afeatureflag) { +- return (MenuType) Registry.register(BuiltInRegistries.MENU, s, new MenuType<>(menutype_menusupplier, FeatureFlags.REGISTRY.subset(afeatureflag))); ++ private static MenuType register(String key, MenuType.MenuSupplier factory, FeatureFlag... requiredFeatures) { ++ return (MenuType) Registry.register(BuiltInRegistries.MENU, key, new MenuType<>(factory, FeatureFlags.REGISTRY.subset(requiredFeatures))); + } + +- private MenuType(MenuType.MenuSupplier menutype_menusupplier, FeatureFlagSet featureflagset) { +- this.constructor = menutype_menusupplier; +- this.requiredFeatures = featureflagset; ++ private MenuType(MenuType.MenuSupplier constructor, FeatureFlagSet requiredFeatures) { ++ this.constructor = constructor; ++ this.requiredFeatures = requiredFeatures; + } + +- public T create(int i, Inventory inventory) { +- return this.constructor.create(i, inventory); ++ public T create(int containerId, Inventory playerInventory) { ++ return this.constructor.create(containerId, playerInventory); + } + + @Override +- @Override + public FeatureFlagSet requiredFeatures() { + return this.requiredFeatures; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/MerchantContainer.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/MerchantContainer.java.patch new file mode 100644 index 0000000000..d99120520f --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/MerchantContainer.java.patch @@ -0,0 +1,213 @@ +--- a/net/minecraft/world/inventory/MerchantContainer.java ++++ b/net/minecraft/world/inventory/MerchantContainer.java +@@ -5,11 +5,20 @@ + import net.minecraft.core.NonNullList; + import net.minecraft.world.Container; + import net.minecraft.world.ContainerHelper; ++import net.minecraft.world.entity.npc.AbstractVillager; ++import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.trading.Merchant; + import net.minecraft.world.item.trading.MerchantOffer; + import net.minecraft.world.item.trading.MerchantOffers; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.entity.CraftAbstractVillager; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end + + public class MerchantContainer implements Container { + +@@ -17,22 +26,60 @@ + private final NonNullList itemStacks; + @Nullable + private MerchantOffer activeOffer; +- private int selectionHint; ++ public int selectionHint; + private int futureXp; + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.itemStacks; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ merchant.setTradingPlayer((Player) null); // SPIGOT-4860 ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return (merchant instanceof AbstractVillager) ? (CraftAbstractVillager) ((AbstractVillager) this.merchant).getBukkitEntity() : null; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return (merchant instanceof Villager) ? ((Villager) this.merchant).getBukkitEntity().getLocation() : null; ++ } ++ // CraftBukkit end ++ + public MerchantContainer(Merchant merchant) { + this.itemStacks = NonNullList.withSize(3, ItemStack.EMPTY); + this.merchant = merchant; + } + + @Override +- @Override + public int getContainerSize() { + return this.itemStacks.size(); + } + + @Override +- @Override + public boolean isEmpty() { + Iterator iterator = this.itemStacks.iterator(); + +@@ -50,22 +97,20 @@ + } + + @Override +- @Override +- public ItemStack getItem(int i) { +- return (ItemStack) this.itemStacks.get(i); ++ public ItemStack getItem(int index) { ++ return (ItemStack) this.itemStacks.get(index); + } + + @Override +- @Override +- public ItemStack removeItem(int i, int j) { +- ItemStack itemstack = (ItemStack) this.itemStacks.get(i); ++ public ItemStack removeItem(int index, int count) { ++ ItemStack itemstack = (ItemStack) this.itemStacks.get(index); + +- if (i == 2 && !itemstack.isEmpty()) { +- return ContainerHelper.removeItem(this.itemStacks, i, itemstack.getCount()); ++ if (index == 2 && !itemstack.isEmpty()) { ++ return ContainerHelper.removeItem(this.itemStacks, index, itemstack.getCount()); + } else { +- ItemStack itemstack1 = ContainerHelper.removeItem(this.itemStacks, i, j); ++ ItemStack itemstack1 = ContainerHelper.removeItem(this.itemStacks, index, count); + +- if (!itemstack1.isEmpty() && this.isPaymentSlot(i)) { ++ if (!itemstack1.isEmpty() && this.isPaymentSlot(index)) { + this.updateSellItem(); + } + +@@ -73,38 +118,34 @@ + } + } + +- private boolean isPaymentSlot(int i) { +- return i == 0 || i == 1; ++ private boolean isPaymentSlot(int slot) { ++ return slot == 0 || slot == 1; + } + + @Override +- @Override +- public ItemStack removeItemNoUpdate(int i) { +- return ContainerHelper.takeItem(this.itemStacks, i); ++ public ItemStack removeItemNoUpdate(int index) { ++ return ContainerHelper.takeItem(this.itemStacks, index); + } + + @Override +- @Override +- public void setItem(int i, ItemStack itemstack) { +- this.itemStacks.set(i, itemstack); +- if (!itemstack.isEmpty() && itemstack.getCount() > this.getMaxStackSize()) { +- itemstack.setCount(this.getMaxStackSize()); ++ public void setItem(int index, ItemStack stack) { ++ this.itemStacks.set(index, stack); ++ if (!stack.isEmpty() && stack.getCount() > this.getMaxStackSize()) { ++ stack.setCount(this.getMaxStackSize()); + } + +- if (this.isPaymentSlot(i)) { ++ if (this.isPaymentSlot(index)) { + this.updateSellItem(); + } + + } + + @Override +- @Override + public boolean stillValid(Player player) { + return this.merchant.getTradingPlayer() == player; + } + + @Override +- @Override + public void setChanged() { + this.updateSellItem(); + } +@@ -126,20 +167,20 @@ + this.setItem(2, ItemStack.EMPTY); + this.futureXp = 0; + } else { +- MerchantOffers merchantoffers = this.merchant.getOffers(); ++ MerchantOffers merchantrecipelist = this.merchant.getOffers(); + +- if (!merchantoffers.isEmpty()) { +- MerchantOffer merchantoffer = merchantoffers.getRecipeFor(itemstack, itemstack1, this.selectionHint); ++ if (!merchantrecipelist.isEmpty()) { ++ MerchantOffer merchantrecipe = merchantrecipelist.getRecipeFor(itemstack, itemstack1, this.selectionHint); + +- if (merchantoffer == null || merchantoffer.isOutOfStock()) { +- this.activeOffer = merchantoffer; +- merchantoffer = merchantoffers.getRecipeFor(itemstack1, itemstack, this.selectionHint); ++ if (merchantrecipe == null || merchantrecipe.isOutOfStock()) { ++ this.activeOffer = merchantrecipe; ++ merchantrecipe = merchantrecipelist.getRecipeFor(itemstack1, itemstack, this.selectionHint); + } + +- if (merchantoffer != null && !merchantoffer.isOutOfStock()) { +- this.activeOffer = merchantoffer; +- this.setItem(2, merchantoffer.assemble()); +- this.futureXp = merchantoffer.getXp(); ++ if (merchantrecipe != null && !merchantrecipe.isOutOfStock()) { ++ this.activeOffer = merchantrecipe; ++ this.setItem(2, merchantrecipe.assemble()); ++ this.futureXp = merchantrecipe.getXp(); + } else { + this.setItem(2, ItemStack.EMPTY); + this.futureXp = 0; +@@ -155,13 +196,12 @@ + return this.activeOffer; + } + +- public void setSelectionHint(int i) { +- this.selectionHint = i; ++ public void setSelectionHint(int currentRecipeIndex) { ++ this.selectionHint = currentRecipeIndex; + this.updateSellItem(); + } + + @Override +- @Override + public void clearContent() { + this.itemStacks.clear(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/MerchantMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/MerchantMenu.java.patch new file mode 100644 index 0000000000..71fbb76739 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/MerchantMenu.java.patch @@ -0,0 +1,240 @@ +--- a/net/minecraft/world/inventory/MerchantMenu.java ++++ b/net/minecraft/world/inventory/MerchantMenu.java +@@ -11,6 +11,7 @@ + import net.minecraft.world.item.trading.Merchant; + import net.minecraft.world.item.trading.MerchantOffer; + import net.minecraft.world.item.trading.MerchantOffers; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; // CraftBukkit + + public class MerchantMenu extends AbstractContainerMenu { + +@@ -31,49 +32,61 @@ + private boolean showProgressBar; + private boolean canRestock; + +- public MerchantMenu(int i, Inventory inventory) { +- this(i, inventory, new ClientSideMerchant(inventory.player)); ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity == null) { ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), new org.bukkit.craftbukkit.inventory.CraftInventoryMerchant(trader, tradeContainer), this); ++ } ++ return bukkitEntity; + } ++ // CraftBukkit end + +- public MerchantMenu(int i, Inventory inventory, Merchant merchant) { +- super(MenuType.MERCHANT, i); +- this.trader = merchant; +- this.tradeContainer = new MerchantContainer(merchant); ++ public MerchantMenu(int containerId, Inventory playerInventory) { ++ this(containerId, playerInventory, new ClientSideMerchant(playerInventory.player)); ++ } ++ ++ public MerchantMenu(int containerId, Inventory playerInventory, Merchant trader) { ++ super(MenuType.MERCHANT, containerId); ++ this.trader = trader; ++ this.tradeContainer = new MerchantContainer(trader); + this.addSlot(new Slot(this.tradeContainer, 0, 136, 37)); + this.addSlot(new Slot(this.tradeContainer, 1, 162, 37)); +- this.addSlot(new MerchantResultSlot(inventory.player, merchant, this.tradeContainer, 2, 220, 37)); ++ this.addSlot(new MerchantResultSlot(playerInventory.player, trader, this.tradeContainer, 2, 220, 37)); ++ this.player = playerInventory; // CraftBukkit - save player + + int j; + + for (j = 0; j < 3; ++j) { + for (int k = 0; k < 9; ++k) { +- this.addSlot(new Slot(inventory, k + j * 9 + 9, 108 + k * 18, 84 + j * 18)); ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 108 + k * 18, 84 + j * 18)); + } + } + + for (j = 0; j < 9; ++j) { +- this.addSlot(new Slot(inventory, j, 108 + j * 18, 142)); ++ this.addSlot(new Slot(playerInventory, j, 108 + j * 18, 142)); + } + + } + +- public void setShowProgressBar(boolean flag) { +- this.showProgressBar = flag; ++ public void setShowProgressBar(boolean showProgressBar) { ++ this.showProgressBar = showProgressBar; + } + + @Override +- @Override +- public void slotsChanged(Container container) { ++ public void slotsChanged(Container inventory) { + this.tradeContainer.updateSellItem(); +- super.slotsChanged(container); ++ super.slotsChanged(inventory); + } + +- public void setSelectionHint(int i) { +- this.tradeContainer.setSelectionHint(i); ++ public void setSelectionHint(int currentRecipeIndex) { ++ this.tradeContainer.setSelectionHint(currentRecipeIndex); + } + + @Override +- @Override + public boolean stillValid(Player player) { + return this.trader.getTradingPlayer() == player; + } +@@ -86,20 +99,20 @@ + return this.tradeContainer.getFutureXp(); + } + +- public void setXp(int i) { +- this.trader.overrideXp(i); ++ public void setXp(int xp) { ++ this.trader.overrideXp(xp); + } + + public int getTraderLevel() { + return this.merchantLevel; + } + +- public void setMerchantLevel(int i) { +- this.merchantLevel = i; ++ public void setMerchantLevel(int level) { ++ this.merchantLevel = level; + } + +- public void setCanRestock(boolean flag) { +- this.canRestock = flag; ++ public void setCanRestock(boolean canRestock) { ++ this.canRestock = canRestock; + } + + public boolean canRestock() { +@@ -107,34 +120,32 @@ + } + + @Override +- @Override +- public boolean canTakeItemForPickAll(ItemStack itemstack, Slot slot) { ++ public boolean canTakeItemForPickAll(ItemStack stack, Slot slot) { + return false; + } + + @Override +- @Override +- public ItemStack quickMoveStack(Player player, int i) { ++ public ItemStack quickMoveStack(Player player, int index) { + ItemStack itemstack = ItemStack.EMPTY; +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = (Slot) this.slots.get(index); + + if (slot != null && slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); + + itemstack = itemstack1.copy(); +- if (i == 2) { ++ if (index == 2) { + if (!this.moveItemStackTo(itemstack1, 3, 39, true)) { + return ItemStack.EMPTY; + } + + slot.onQuickCraft(itemstack1, itemstack); + this.playTradeSound(); +- } else if (i != 0 && i != 1) { +- if (i >= 3 && i < 30) { ++ } else if (index != 0 && index != 1) { ++ if (index >= 3 && index < 30) { + if (!this.moveItemStackTo(itemstack1, 30, 39, false)) { + return ItemStack.EMPTY; + } +- } else if (i >= 30 && i < 39 && !this.moveItemStackTo(itemstack1, 3, 30, false)) { ++ } else if (index >= 30 && index < 39 && !this.moveItemStackTo(itemstack1, 3, 30, false)) { + return ItemStack.EMPTY; + } + } else if (!this.moveItemStackTo(itemstack1, 3, 39, false)) { +@@ -158,7 +169,7 @@ + } + + private void playTradeSound() { +- if (!this.trader.isClientSide()) { ++ if (!this.trader.isClientSide() && this.trader instanceof Entity) { // CraftBukkit - SPIGOT-5035 + Entity entity = (Entity) this.trader; + + entity.level().playLocalSound(entity.getX(), entity.getY(), entity.getZ(), this.trader.getNotifyTradeSound(), SoundSource.NEUTRAL, 1.0F, 1.0F, false); +@@ -167,7 +178,6 @@ + } + + @Override +- @Override + public void removed(Player player) { + super.removed(player); + this.trader.setTradingPlayer((Player) null); +@@ -193,8 +203,8 @@ + } + } + +- public void tryMoveItems(int i) { +- if (i >= 0 && this.getOffers().size() > i) { ++ public void tryMoveItems(int selectedMerchantRecipe) { ++ if (selectedMerchantRecipe >= 0 && this.getOffers().size() > selectedMerchantRecipe) { + ItemStack itemstack = this.tradeContainer.getItem(0); + + if (!itemstack.isEmpty()) { +@@ -216,10 +226,10 @@ + } + + if (this.tradeContainer.getItem(0).isEmpty() && this.tradeContainer.getItem(1).isEmpty()) { +- ItemStack itemstack2 = ((MerchantOffer) this.getOffers().get(i)).getCostA(); ++ ItemStack itemstack2 = ((MerchantOffer) this.getOffers().get(selectedMerchantRecipe)).getCostA(); + + this.moveFromInventoryToPaymentSlot(0, itemstack2); +- ItemStack itemstack3 = ((MerchantOffer) this.getOffers().get(i)).getCostB(); ++ ItemStack itemstack3 = ((MerchantOffer) this.getOffers().get(selectedMerchantRecipe)).getCostB(); + + this.moveFromInventoryToPaymentSlot(1, itemstack3); + } +@@ -227,22 +237,22 @@ + } + } + +- private void moveFromInventoryToPaymentSlot(int i, ItemStack itemstack) { +- if (!itemstack.isEmpty()) { ++ private void moveFromInventoryToPaymentSlot(int paymentSlotIndex, ItemStack paymentSlot) { ++ if (!paymentSlot.isEmpty()) { + for (int j = 3; j < 39; ++j) { + ItemStack itemstack1 = ((Slot) this.slots.get(j)).getItem(); + +- if (!itemstack1.isEmpty() && ItemStack.isSameItemSameTags(itemstack, itemstack1)) { +- ItemStack itemstack2 = this.tradeContainer.getItem(i); ++ if (!itemstack1.isEmpty() && ItemStack.isSameItemSameTags(paymentSlot, itemstack1)) { ++ ItemStack itemstack2 = this.tradeContainer.getItem(paymentSlotIndex); + int k = itemstack2.isEmpty() ? 0 : itemstack2.getCount(); +- int l = Math.min(itemstack.getMaxStackSize() - k, itemstack1.getCount()); ++ int l = Math.min(paymentSlot.getMaxStackSize() - k, itemstack1.getCount()); + ItemStack itemstack3 = itemstack1.copy(); + int i1 = k + l; + + itemstack1.shrink(l); + itemstack3.setCount(i1); +- this.tradeContainer.setItem(i, itemstack3); +- if (i1 >= itemstack.getMaxStackSize()) { ++ this.tradeContainer.setItem(paymentSlotIndex, itemstack3); ++ if (i1 >= paymentSlot.getMaxStackSize()) { + break; + } + } +@@ -251,8 +261,8 @@ + + } + +- public void setOffers(MerchantOffers merchantoffers) { +- this.trader.overrideOffers(merchantoffers); ++ public void setOffers(MerchantOffers offers) { ++ this.trader.overrideOffers(offers); + } + + public MerchantOffers getOffers() { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/PlayerEnderChestContainer.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/PlayerEnderChestContainer.java.patch new file mode 100644 index 0000000000..cd5e46f6f0 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/PlayerEnderChestContainer.java.patch @@ -0,0 +1,117 @@ +--- a/net/minecraft/world/inventory/PlayerEnderChestContainer.java ++++ b/net/minecraft/world/inventory/PlayerEnderChestContainer.java +@@ -7,72 +7,86 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.entity.EnderChestBlockEntity; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end + + public class PlayerEnderChestContainer extends SimpleContainer { + + @Nullable + private EnderChestBlockEntity activeChest; ++ // CraftBukkit start ++ private final Player owner; + +- public PlayerEnderChestContainer() { ++ public InventoryHolder getBukkitOwner() { ++ return owner.getBukkitEntity(); ++ } ++ ++ @Override ++ public Location getLocation() { ++ return this.activeChest != null ? CraftLocation.toBukkit(this.activeChest.getBlockPos(), this.activeChest.getLevel().getWorld()) : null; ++ } ++ ++ public PlayerEnderChestContainer(Player owner) { + super(27); ++ this.owner = owner; ++ // CraftBukkit end + } + +- public void setActiveChest(EnderChestBlockEntity enderchestblockentity) { +- this.activeChest = enderchestblockentity; ++ public void setActiveChest(EnderChestBlockEntity enderChestBlockEntity) { ++ this.activeChest = enderChestBlockEntity; + } + +- public boolean isActiveChest(EnderChestBlockEntity enderchestblockentity) { +- return this.activeChest == enderchestblockentity; ++ public boolean isActiveChest(EnderChestBlockEntity enderChest) { ++ return this.activeChest == enderChest; + } + + @Override +- @Override +- public void fromTag(ListTag listtag) { ++ public void fromTag(ListTag containerNbt) { + int i; + + for (i = 0; i < this.getContainerSize(); ++i) { + this.setItem(i, ItemStack.EMPTY); + } + +- for (i = 0; i < listtag.size(); ++i) { +- CompoundTag compoundtag = listtag.getCompound(i); +- int j = compoundtag.getByte("Slot") & 255; ++ for (i = 0; i < containerNbt.size(); ++i) { ++ CompoundTag nbttagcompound = containerNbt.getCompound(i); ++ int j = nbttagcompound.getByte("Slot") & 255; + + if (j >= 0 && j < this.getContainerSize()) { +- this.setItem(j, ItemStack.of(compoundtag)); ++ this.setItem(j, ItemStack.of(nbttagcompound)); + } + } + + } + + @Override +- @Override + public ListTag createTag() { +- ListTag listtag = new ListTag(); ++ ListTag nbttaglist = new ListTag(); + + for (int i = 0; i < this.getContainerSize(); ++i) { + ItemStack itemstack = this.getItem(i); + + if (!itemstack.isEmpty()) { +- CompoundTag compoundtag = new CompoundTag(); ++ CompoundTag nbttagcompound = new CompoundTag(); + +- compoundtag.putByte("Slot", (byte) i); +- itemstack.save(compoundtag); +- listtag.add(compoundtag); ++ nbttagcompound.putByte("Slot", (byte) i); ++ itemstack.save(nbttagcompound); ++ nbttaglist.add(nbttagcompound); + } + } + +- return listtag; ++ return nbttaglist; + } + + @Override +- @Override + public boolean stillValid(Player player) { + return this.activeChest != null && !this.activeChest.stillValid(player) ? false : super.stillValid(player); + } + + @Override +- @Override + public void startOpen(Player player) { + if (this.activeChest != null) { + this.activeChest.startOpen(player); +@@ -82,7 +96,6 @@ + } + + @Override +- @Override + public void stopOpen(Player player) { + if (this.activeChest != null) { + this.activeChest.stopOpen(player); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/ResultContainer.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/ResultContainer.java.patch new file mode 100644 index 0000000000..840880b2ea --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/ResultContainer.java.patch @@ -0,0 +1,126 @@ +--- a/net/minecraft/world/inventory/ResultContainer.java ++++ b/net/minecraft/world/inventory/ResultContainer.java +@@ -9,24 +9,61 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.crafting.RecipeHolder; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class ResultContainer implements Container, RecipeCraftingHolder { + + private final NonNullList itemStacks; + @Nullable + private RecipeHolder recipeUsed; + ++ // CraftBukkit start ++ private int maxStack = MAX_STACK; ++ ++ public java.util.List getContents() { ++ return this.itemStacks; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return null; // Result slots don't get an owner ++ } ++ ++ // Don't need a transaction; the InventoryCrafting keeps track of it for us ++ public void onOpen(CraftHumanEntity who) {} ++ public void onClose(CraftHumanEntity who) {} ++ public java.util.List getViewers() { ++ return new java.util.ArrayList(); ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return null; ++ } ++ // CraftBukkit end ++ + public ResultContainer() { + this.itemStacks = NonNullList.withSize(1, ItemStack.EMPTY); + } + + @Override +- @Override + public int getContainerSize() { + return 1; + } + + @Override +- @Override + public boolean isEmpty() { + Iterator iterator = this.itemStacks.iterator(); + +@@ -44,54 +81,45 @@ + } + + @Override +- @Override +- public ItemStack getItem(int i) { ++ public ItemStack getItem(int index) { + return (ItemStack) this.itemStacks.get(0); + } + + @Override +- @Override +- public ItemStack removeItem(int i, int j) { ++ public ItemStack removeItem(int index, int count) { + return ContainerHelper.takeItem(this.itemStacks, 0); + } + + @Override +- @Override +- public ItemStack removeItemNoUpdate(int i) { ++ public ItemStack removeItemNoUpdate(int index) { + return ContainerHelper.takeItem(this.itemStacks, 0); + } + + @Override +- @Override +- public void setItem(int i, ItemStack itemstack) { +- this.itemStacks.set(0, itemstack); ++ public void setItem(int index, ItemStack stack) { ++ this.itemStacks.set(0, stack); + } + + @Override +- @Override + public void setChanged() {} + + @Override +- @Override + public boolean stillValid(Player player) { + return true; + } + + @Override +- @Override + public void clearContent() { + this.itemStacks.clear(); + } + + @Override +- @Override + public void setRecipeUsed(@Nullable RecipeHolder recipeholder) { + this.recipeUsed = recipeholder; + } + + @Nullable + @Override +- @Override + public RecipeHolder getRecipeUsed() { + return this.recipeUsed; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/ShulkerBoxMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/ShulkerBoxMenu.java.patch new file mode 100644 index 0000000000..f1519aab85 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/ShulkerBoxMenu.java.patch @@ -0,0 +1,96 @@ +--- a/net/minecraft/world/inventory/ShulkerBoxMenu.java ++++ b/net/minecraft/world/inventory/ShulkerBoxMenu.java +@@ -6,20 +6,40 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class ShulkerBoxMenu extends AbstractContainerMenu { + + private static final int CONTAINER_SIZE = 27; + private final Container container; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity; ++ private Inventory player; + +- public ShulkerBoxMenu(int i, Inventory inventory) { +- this(i, inventory, new SimpleContainer(27)); ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), new CraftInventory(this.container), this); ++ return bukkitEntity; + } ++ // CraftBukkit end + +- public ShulkerBoxMenu(int i, Inventory inventory, Container container) { +- super(MenuType.SHULKER_BOX, i); ++ public ShulkerBoxMenu(int containerId, Inventory playerInventory) { ++ this(containerId, playerInventory, new SimpleContainer(27)); ++ } ++ ++ public ShulkerBoxMenu(int containerId, Inventory playerInventory, Container container) { ++ super(MenuType.SHULKER_BOX, containerId); + checkContainerSize(container, 27); + this.container = container; +- container.startOpen(inventory.player); ++ this.player = playerInventory; // CraftBukkit - save player ++ container.startOpen(playerInventory.player); + boolean flag = true; + boolean flag1 = true; + +@@ -34,33 +54,32 @@ + + for (j = 0; j < 3; ++j) { + for (k = 0; k < 9; ++k) { +- this.addSlot(new Slot(inventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); + } + } + + for (j = 0; j < 9; ++j) { +- this.addSlot(new Slot(inventory, j, 8 + j * 18, 142)); ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } + + } + + @Override +- @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(player); + } + + @Override +- @Override +- public ItemStack quickMoveStack(Player player, int i) { ++ public ItemStack quickMoveStack(Player player, int index) { + ItemStack itemstack = ItemStack.EMPTY; +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = (Slot) this.slots.get(index); + + if (slot != null && slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); + + itemstack = itemstack1.copy(); +- if (i < this.container.getContainerSize()) { ++ if (index < this.container.getContainerSize()) { + if (!this.moveItemStackTo(itemstack1, this.container.getContainerSize(), this.slots.size(), true)) { + return ItemStack.EMPTY; + } +@@ -79,7 +98,6 @@ + } + + @Override +- @Override + public void removed(Player player) { + super.removed(player); + this.container.stopOpen(player); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/SmithingMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/SmithingMenu.java.patch new file mode 100644 index 0000000000..bc5a86d4f9 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/SmithingMenu.java.patch @@ -0,0 +1,166 @@ +--- a/net/minecraft/world/inventory/SmithingMenu.java ++++ b/net/minecraft/world/inventory/SmithingMenu.java +@@ -11,8 +11,10 @@ + import net.minecraft.world.item.crafting.SmithingRecipe; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; // CraftBukkit ++ + public class SmithingMenu extends ItemCombinerMenu { + + public static final int TEMPLATE_SLOT = 0; +@@ -28,19 +30,21 @@ + @Nullable + private RecipeHolder selectedRecipe; + private final List> recipes; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity; ++ // CraftBukkit end + +- public SmithingMenu(int i, Inventory inventory) { +- this(i, inventory, ContainerLevelAccess.NULL); ++ public SmithingMenu(int containerId, Inventory playerInventory) { ++ this(containerId, playerInventory, ContainerLevelAccess.NULL); + } + +- public SmithingMenu(int i, Inventory inventory, ContainerLevelAccess containerlevelaccess) { +- super(MenuType.SMITHING, i, inventory, containerlevelaccess); +- this.level = inventory.player.level(); ++ public SmithingMenu(int containerId, Inventory playerInventory, ContainerLevelAccess access) { ++ super(MenuType.SMITHING, containerId, playerInventory, access); ++ this.level = playerInventory.player.level(); + this.recipes = this.level.getRecipeManager().getAllRecipesFor(RecipeType.SMITHING); + } + + @Override +- @Override + protected ItemCombinerMenuSlotDefinition createInputSlotDefinitions() { + return ItemCombinerMenuSlotDefinition.create().withSlot(0, 8, 48, (itemstack) -> { + return this.recipes.stream().anyMatch((recipeholder) -> { +@@ -58,27 +62,24 @@ + } + + @Override +- @Override +- protected boolean isValidBlock(BlockState blockstate) { +- return blockstate.is(Blocks.SMITHING_TABLE); ++ protected boolean isValidBlock(IBlockData state) { ++ return state.is(Blocks.SMITHING_TABLE); + } + + @Override +- @Override +- protected boolean mayPickup(Player player, boolean flag) { ++ protected boolean mayPickup(Player player, boolean hasStack) { + return this.selectedRecipe != null && ((SmithingRecipe) this.selectedRecipe.value()).matches(this.inputSlots, this.level); + } + + @Override +- @Override +- protected void onTake(Player player, ItemStack itemstack) { +- itemstack.onCraftedBy(player.level(), player, itemstack.getCount()); ++ protected void onTake(Player player, ItemStack stack) { ++ stack.onCraftedBy(player.level(), player, stack.getCount()); + this.resultSlots.awardUsedRecipes(player, this.getRelevantItems()); + this.shrinkStackInSlot(0); + this.shrinkStackInSlot(1); + this.shrinkStackInSlot(2); +- this.access.execute((level, blockpos) -> { +- level.levelEvent(1044, blockpos, 0); ++ this.access.execute((world, blockposition) -> { ++ world.levelEvent(1044, blockposition, 0); + }); + } + +@@ -86,23 +87,22 @@ + return List.of(this.inputSlots.getItem(0), this.inputSlots.getItem(1), this.inputSlots.getItem(2)); + } + +- private void shrinkStackInSlot(int i) { +- ItemStack itemstack = this.inputSlots.getItem(i); ++ private void shrinkStackInSlot(int index) { ++ ItemStack itemstack = this.inputSlots.getItem(index); + + if (!itemstack.isEmpty()) { + itemstack.shrink(1); +- this.inputSlots.setItem(i, itemstack); ++ this.inputSlots.setItem(index, itemstack); + } + + } + + @Override +- @Override + public void createResult() { + List> list = this.level.getRecipeManager().getRecipesFor(RecipeType.SMITHING, this.inputSlots, this.level); + + if (list.isEmpty()) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareSmithingEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + } else { + RecipeHolder recipeholder = (RecipeHolder) list.get(0); + ItemStack itemstack = ((SmithingRecipe) recipeholder.value()).assemble(this.inputSlots, this.level.registryAccess()); +@@ -110,16 +110,17 @@ + if (itemstack.isItemEnabled(this.level.enabledFeatures())) { + this.selectedRecipe = recipeholder; + this.resultSlots.setRecipeUsed(recipeholder); +- this.resultSlots.setItem(0, itemstack); ++ // CraftBukkit start ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareSmithingEvent(getBukkitView(), itemstack); ++ // CraftBukkit end + } + } + + } + + @Override +- @Override +- public int getSlotToQuickMoveTo(ItemStack itemstack) { +- return this.findSlotToQuickMoveTo(itemstack).orElse(0); ++ public int getSlotToQuickMoveTo(ItemStack stack) { ++ return this.findSlotToQuickMoveTo(stack).orElse(0); + } + + private static OptionalInt findSlotMatchingIngredient(SmithingRecipe smithingrecipe, ItemStack itemstack) { +@@ -127,15 +128,13 @@ + } + + @Override +- @Override +- public boolean canTakeItemForPickAll(ItemStack itemstack, Slot slot) { +- return slot.container != this.resultSlots && super.canTakeItemForPickAll(itemstack, slot); ++ public boolean canTakeItemForPickAll(ItemStack stack, Slot slot) { ++ return slot.container != this.resultSlots && super.canTakeItemForPickAll(stack, slot); + } + + @Override +- @Override +- public boolean canMoveIntoInputSlots(ItemStack itemstack) { +- return this.findSlotToQuickMoveTo(itemstack).isPresent(); ++ public boolean canMoveIntoInputSlots(ItemStack stack) { ++ return this.findSlotToQuickMoveTo(stack).isPresent(); + } + + private OptionalInt findSlotToQuickMoveTo(ItemStack itemstack) { +@@ -145,4 +144,18 @@ + return !this.getSlot(i).hasItem(); + }).findFirst(); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventory inventory = new org.bukkit.craftbukkit.inventory.CraftInventorySmithing( ++ access.getLocation(), this.inputSlots, this.resultSlots); ++ bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/StonecutterMenu.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/StonecutterMenu.java.patch new file mode 100644 index 0000000000..bc32a03c98 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/StonecutterMenu.java.patch @@ -0,0 +1,270 @@ +--- a/net/minecraft/world/inventory/StonecutterMenu.java ++++ b/net/minecraft/world/inventory/StonecutterMenu.java +@@ -7,7 +7,6 @@ + import net.minecraft.world.Container; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.entity.player.Inventory; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.crafting.RecipeHolder; +@@ -16,6 +15,13 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.inventory.CraftInventoryStonecutter; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++// CraftBukkit end ++ + public class StonecutterMenu extends AbstractContainerMenu { + + public static final int INPUT_SLOT = 0; +@@ -35,13 +41,28 @@ + Runnable slotUpdateListener; + public final Container container; + final ResultContainer resultContainer; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; + +- public StonecutterMenu(int i, Inventory inventory) { +- this(i, inventory, ContainerLevelAccess.NULL); ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryStonecutter inventory = new CraftInventoryStonecutter(this.container, this.resultContainer); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; + } ++ // CraftBukkit end + +- public StonecutterMenu(int i, Inventory inventory, final ContainerLevelAccess containerlevelaccess) { +- super(MenuType.STONECUTTER, i); ++ public StonecutterMenu(int containerId, Inventory playerInventory) { ++ this(containerId, playerInventory, ContainerLevelAccess.NULL); ++ } ++ ++ public StonecutterMenu(int containerId, Inventory playerInventory, final ContainerLevelAccess access) { ++ super(MenuType.STONECUTTER, containerId); + this.selectedRecipeIndex = DataSlot.standalone(); + this.recipes = Lists.newArrayList(); + this.input = ItemStack.EMPTY; +@@ -49,28 +70,32 @@ + }; + this.container = new SimpleContainer(1) { + @Override +- @Override + public void setChanged() { + super.setChanged(); + StonecutterMenu.this.slotsChanged(this); + StonecutterMenu.this.slotUpdateListener.run(); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end + }; + this.resultContainer = new ResultContainer(); +- this.access = containerlevelaccess; +- this.level = inventory.player.level(); ++ this.access = access; ++ this.level = playerInventory.player.level(); + this.inputSlot = this.addSlot(new Slot(this.container, 0, 20, 33)); + this.resultSlot = this.addSlot(new Slot(this.resultContainer, 1, 143, 33) { + @Override +- @Override +- public boolean mayPlace(ItemStack itemstack) { ++ public boolean mayPlace(ItemStack stack) { + return false; + } + + @Override +- @Override +- public void onTake(Player player, ItemStack itemstack) { +- itemstack.onCraftedBy(player.level(), player, itemstack.getCount()); ++ public void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) { ++ stack.onCraftedBy(player.level(), player, stack.getCount()); + StonecutterMenu.this.resultContainer.awardUsedRecipes(player, this.getRelevantItems()); + ItemStack itemstack1 = StonecutterMenu.this.inputSlot.remove(1); + +@@ -78,16 +103,16 @@ + StonecutterMenu.this.setupResultSlot(); + } + +- containerlevelaccess.execute((level, blockpos) -> { +- long j = level.getGameTime(); ++ access.execute((world, blockposition) -> { ++ long j = world.getGameTime(); + + if (StonecutterMenu.this.lastSoundTime != j) { +- level.playSound((Player) null, blockpos, SoundEvents.UI_STONECUTTER_TAKE_RESULT, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.playSound((net.minecraft.world.entity.player.Player) null, blockposition, SoundEvents.UI_STONECUTTER_TAKE_RESULT, SoundSource.BLOCKS, 1.0F, 1.0F); + StonecutterMenu.this.lastSoundTime = j; + } + + }); +- super.onTake(player, itemstack); ++ super.onTake(player, stack); + } + + private List getRelevantItems() { +@@ -99,15 +124,16 @@ + + for (j = 0; j < 3; ++j) { + for (int k = 0; k < 9; ++k) { +- this.addSlot(new Slot(inventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); + } + } + + for (j = 0; j < 9; ++j) { +- this.addSlot(new Slot(inventory, j, 8 + j * 18, 142)); ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } + + this.addDataSlot(this.selectedRecipeIndex); ++ player = (Player) playerInventory.player.getBukkitEntity(); // CraftBukkit + } + + public int getSelectedRecipeIndex() { +@@ -127,43 +153,41 @@ + } + + @Override +- @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.STONECUTTER); + } + + @Override +- @Override +- public boolean clickMenuButton(Player player, int i) { +- if (this.isValidRecipeIndex(i)) { +- this.selectedRecipeIndex.set(i); ++ public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { ++ if (this.isValidRecipeIndex(id)) { ++ this.selectedRecipeIndex.set(id); + this.setupResultSlot(); + } + + return true; + } + +- private boolean isValidRecipeIndex(int i) { +- return i >= 0 && i < this.recipes.size(); ++ private boolean isValidRecipeIndex(int recipeIndex) { ++ return recipeIndex >= 0 && recipeIndex < this.recipes.size(); + } + + @Override +- @Override +- public void slotsChanged(Container container) { ++ public void slotsChanged(Container inventory) { + ItemStack itemstack = this.inputSlot.getItem(); + + if (!itemstack.is(this.input.getItem())) { + this.input = itemstack.copy(); +- this.setupRecipeList(container, itemstack); ++ this.setupRecipeList(inventory, itemstack); + } + + } + +- private void setupRecipeList(Container container, ItemStack itemstack) { ++ private void setupRecipeList(Container container, ItemStack stack) { + this.recipes.clear(); + this.selectedRecipeIndex.set(-1); + this.resultSlot.set(ItemStack.EMPTY); +- if (!itemstack.isEmpty()) { ++ if (!stack.isEmpty()) { + this.recipes = this.level.getRecipeManager().getRecipesFor(RecipeType.STONECUTTING, container, this.level); + } + +@@ -188,40 +212,37 @@ + } + + @Override +- @Override + public MenuType getType() { + return MenuType.STONECUTTER; + } + +- public void registerUpdateListener(Runnable runnable) { +- this.slotUpdateListener = runnable; ++ public void registerUpdateListener(Runnable listener) { ++ this.slotUpdateListener = listener; + } + + @Override +- @Override +- public boolean canTakeItemForPickAll(ItemStack itemstack, Slot slot) { +- return slot.container != this.resultContainer && super.canTakeItemForPickAll(itemstack, slot); ++ public boolean canTakeItemForPickAll(ItemStack stack, Slot slot) { ++ return slot.container != this.resultContainer && super.canTakeItemForPickAll(stack, slot); + } + + @Override +- @Override +- public ItemStack quickMoveStack(Player player, int i) { ++ public ItemStack quickMoveStack(net.minecraft.world.entity.player.Player player, int index) { + ItemStack itemstack = ItemStack.EMPTY; +- Slot slot = (Slot) this.slots.get(i); ++ Slot slot = (Slot) this.slots.get(index); + + if (slot != null && slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); + Item item = itemstack1.getItem(); + + itemstack = itemstack1.copy(); +- if (i == 1) { ++ if (index == 1) { + item.onCraftedBy(itemstack1, player.level(), player); + if (!this.moveItemStackTo(itemstack1, 2, 38, true)) { + return ItemStack.EMPTY; + } + + slot.onQuickCraft(itemstack1, itemstack); +- } else if (i == 0) { ++ } else if (index == 0) { + if (!this.moveItemStackTo(itemstack1, 2, 38, false)) { + return ItemStack.EMPTY; + } +@@ -229,11 +250,11 @@ + if (!this.moveItemStackTo(itemstack1, 0, 1, false)) { + return ItemStack.EMPTY; + } +- } else if (i >= 2 && i < 29) { ++ } else if (index >= 2 && index < 29) { + if (!this.moveItemStackTo(itemstack1, 29, 38, false)) { + return ItemStack.EMPTY; + } +- } else if (i >= 29 && i < 38 && !this.moveItemStackTo(itemstack1, 2, 29, false)) { ++ } else if (index >= 29 && index < 38 && !this.moveItemStackTo(itemstack1, 2, 29, false)) { + return ItemStack.EMPTY; + } + +@@ -254,11 +275,10 @@ + } + + @Override +- @Override +- public void removed(Player player) { ++ public void removed(net.minecraft.world.entity.player.Player player) { + super.removed(player); + this.resultContainer.removeItemNoUpdate(1); +- this.access.execute((level, blockpos) -> { ++ this.access.execute((world, blockposition) -> { + this.clearContainer(player, this.container); + }); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/inventory/TransientCraftingContainer.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/TransientCraftingContainer.java.patch new file mode 100644 index 0000000000..d23f3abafa --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/inventory/TransientCraftingContainer.java.patch @@ -0,0 +1,207 @@ +--- a/net/minecraft/world/inventory/TransientCraftingContainer.java ++++ b/net/minecraft/world/inventory/TransientCraftingContainer.java +@@ -3,37 +3,107 @@ + import java.util.Iterator; + import java.util.List; + import net.minecraft.core.NonNullList; ++import net.minecraft.world.Container; + import net.minecraft.world.ContainerHelper; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.player.StackedContents; + import net.minecraft.world.item.ItemStack; + +-public class TransientCraftingContainer implements CraftingContainer { ++// CraftBukkit start ++import java.util.List; ++import net.minecraft.world.item.crafting.RecipeHolder; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.event.inventory.InventoryType; ++// CraftBukkit end + ++public class TransientCraftingContainer implements InventoryCrafting { ++ + private final NonNullList items; + private final int width; + private final int height; + private final AbstractContainerMenu menu; + +- public TransientCraftingContainer(AbstractContainerMenu abstractcontainermenu, int i, int j) { +- this(abstractcontainermenu, i, j, NonNullList.withSize(i * j, ItemStack.EMPTY)); ++ // CraftBukkit start - add fields ++ public List transaction = new java.util.ArrayList(); ++ private RecipeHolder currentRecipe; ++ public Container resultInventory; ++ private Player owner; ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.items; + } + +- public TransientCraftingContainer(AbstractContainerMenu abstractcontainermenu, int i, int j, NonNullList nonnulllist) { +- this.items = nonnulllist; +- this.menu = abstractcontainermenu; +- this.width = i; +- this.height = j; ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); + } + ++ public InventoryType getInvType() { ++ return items.size() == 4 ? InventoryType.CRAFTING : InventoryType.WORKBENCH; ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return (owner == null) ? null : owner.getBukkitEntity(); ++ } ++ + @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ resultInventory.setMaxStackSize(size); ++ } ++ + @Override ++ public Location getLocation() { ++ return menu instanceof CraftingMenu ? ((CraftingMenu) menu).access.getLocation() : owner.getBukkitEntity().getLocation(); ++ } ++ ++ @Override ++ public RecipeHolder getCurrentRecipe() { ++ return currentRecipe; ++ } ++ ++ @Override ++ public void setCurrentRecipe(RecipeHolder currentRecipe) { ++ this.currentRecipe = currentRecipe; ++ } ++ ++ public TransientCraftingContainer(AbstractContainerMenu container, int i, int j, Player player) { ++ this(container, i, j); ++ this.owner = player; ++ } ++ // CraftBukkit end ++ ++ public TransientCraftingContainer(AbstractContainerMenu menu, int width, int height) { ++ this(menu, width, height, NonNullList.withSize(width * height, ItemStack.EMPTY)); ++ } ++ ++ public TransientCraftingContainer(AbstractContainerMenu menu, int width, int height, NonNullList items) { ++ this.items = items; ++ this.menu = menu; ++ this.width = width; ++ this.height = height; ++ } ++ ++ @Override + public int getContainerSize() { + return this.items.size(); + } + + @Override +- @Override + public boolean isEmpty() { + Iterator iterator = this.items.iterator(); + +@@ -51,21 +121,18 @@ + } + + @Override +- @Override +- public ItemStack getItem(int i) { +- return i >= this.getContainerSize() ? ItemStack.EMPTY : (ItemStack) this.items.get(i); ++ public ItemStack getItem(int slot) { ++ return slot >= this.getContainerSize() ? ItemStack.EMPTY : (ItemStack) this.items.get(slot); + } + + @Override +- @Override +- public ItemStack removeItemNoUpdate(int i) { +- return ContainerHelper.takeItem(this.items, i); ++ public ItemStack removeItemNoUpdate(int slot) { ++ return ContainerHelper.takeItem(this.items, slot); + } + + @Override +- @Override +- public ItemStack removeItem(int i, int j) { +- ItemStack itemstack = ContainerHelper.removeItem(this.items, i, j); ++ public ItemStack removeItem(int slot, int amount) { ++ ItemStack itemstack = ContainerHelper.removeItem(this.items, slot, amount); + + if (!itemstack.isEmpty()) { + this.menu.slotsChanged(this); +@@ -75,55 +142,47 @@ + } + + @Override +- @Override +- public void setItem(int i, ItemStack itemstack) { +- this.items.set(i, itemstack); ++ public void setItem(int slot, ItemStack stack) { ++ this.items.set(slot, stack); + this.menu.slotsChanged(this); + } + + @Override +- @Override + public void setChanged() {} + + @Override +- @Override + public boolean stillValid(Player player) { + return true; + } + + @Override +- @Override + public void clearContent() { + this.items.clear(); + } + + @Override +- @Override + public int getHeight() { + return this.height; + } + + @Override +- @Override + public int getWidth() { + return this.width; + } + + @Override +- @Override + public List getItems() { + return List.copyOf(this.items); + } + + @Override +- @Override +- public void fillStackedContents(StackedContents stackedcontents) { ++ public void fillStackedContents(StackedContents contents) { + Iterator iterator = this.items.iterator(); + + while (iterator.hasNext()) { + ItemStack itemstack = (ItemStack) iterator.next(); + +- stackedcontents.accountSimpleStack(itemstack); ++ contents.accountSimpleStack(itemstack); + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/ArmorItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/ArmorItem.java.patch new file mode 100644 index 0000000000..5157e1a538 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/ArmorItem.java.patch @@ -0,0 +1,187 @@ +--- a/net/minecraft/world/item/ArmorItem.java ++++ b/net/minecraft/world/item/ArmorItem.java +@@ -9,11 +9,11 @@ + import net.minecraft.Util; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.dispenser.BlockSource; + import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; + import net.minecraft.core.dispenser.DispenseItemBehavior; ++import net.minecraft.core.dispenser.SourceBlock; + import net.minecraft.sounds.SoundEvent; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EquipmentSlot; +@@ -26,6 +26,11 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.DispenserBlock; + import net.minecraft.world.phys.AABB; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseArmorEvent; ++// CraftBukkit end + + public class ArmorItem extends Item implements Equipable { + +@@ -37,9 +42,8 @@ + }); + public static final DispenseItemBehavior DISPENSE_ITEM_BEHAVIOR = new DefaultDispenseItemBehavior() { + @Override +- @Override +- protected ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- return ArmorItem.dispenseArmor(blocksource, itemstack) ? itemstack : super.execute(blocksource, itemstack); ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ return ArmorItem.dispenseArmor(sourceblock, itemstack) ? itemstack : super.execute(sourceblock, itemstack); + } + }; + protected final ArmorItem.Type type; +@@ -49,41 +53,67 @@ + protected final ArmorMaterial material; + private final Multimap defaultModifiers; + +- public static boolean dispenseArmor(BlockSource blocksource, ItemStack itemstack) { +- BlockPos blockpos = blocksource.pos().relative((Direction) blocksource.state().getValue(DispenserBlock.FACING)); +- List list = blocksource.level().getEntitiesOfClass(LivingEntity.class, new AABB(blockpos), EntitySelector.NO_SPECTATORS.and(new EntitySelector.MobCanWearArmorEntitySelector(itemstack))); ++ public static boolean dispenseArmor(SourceBlock sourceblock, ItemStack itemstack) { ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ List list = sourceblock.level().getEntitiesOfClass(LivingEntity.class, new AABB(blockposition), EntitySelector.NO_SPECTATORS.and(new EntitySelector.MobCanWearArmorEntitySelector(itemstack))); + + if (list.isEmpty()) { + return false; + } else { +- LivingEntity livingentity = (LivingEntity) list.get(0); +- EquipmentSlot equipmentslot = Mob.getEquipmentSlotForItem(itemstack); ++ LivingEntity entityliving = (LivingEntity) list.get(0); ++ EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(itemstack); + ItemStack itemstack1 = itemstack.split(1); ++ // CraftBukkit start ++ Level world = sourceblock.level(); ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + +- livingentity.setItemSlot(equipmentslot, itemstack1); +- if (livingentity instanceof Mob) { +- ((Mob) livingentity).setDropChance(equipmentslot, 2.0F); +- ((Mob) livingentity).setPersistenceRequired(); ++ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityliving.getBukkitEntity()); ++ if (!DispenserBlock.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); + } + ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return false; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return true; ++ } ++ } ++ ++ entityliving.setItemSlot(enumitemslot, CraftItemStack.asNMSCopy(event.getItem())); ++ // CraftBukkit end ++ if (entityliving instanceof Mob) { ++ ((Mob) entityliving).setDropChance(enumitemslot, 2.0F); ++ ((Mob) entityliving).setPersistenceRequired(); ++ } ++ + return true; + } + } + +- public ArmorItem(ArmorMaterial armormaterial, ArmorItem.Type armoritem_type, Item.Properties item_properties) { +- super(item_properties.defaultDurability(armormaterial.getDurabilityForType(armoritem_type))); +- this.material = armormaterial; +- this.type = armoritem_type; +- this.defense = armormaterial.getDefenseForType(armoritem_type); +- this.toughness = armormaterial.getToughness(); +- this.knockbackResistance = armormaterial.getKnockbackResistance(); ++ public ArmorItem(ArmorMaterial material, ArmorItem.Type type, Item.Properties properties) { ++ super(properties.defaultDurability(material.getDurabilityForType(type))); ++ this.material = material; ++ this.type = type; ++ this.defense = material.getDefenseForType(type); ++ this.toughness = material.getToughness(); ++ this.knockbackResistance = material.getKnockbackResistance(); + DispenserBlock.registerBehavior(this, ArmorItem.DISPENSE_ITEM_BEHAVIOR); + Builder builder = ImmutableMultimap.builder(); +- UUID uuid = (UUID) ArmorItem.ARMOR_MODIFIER_UUID_PER_TYPE.get(armoritem_type); ++ UUID uuid = (UUID) ArmorItem.ARMOR_MODIFIER_UUID_PER_TYPE.get(type); + + builder.put(Attributes.ARMOR, new AttributeModifier(uuid, "Armor modifier", (double) this.defense, AttributeModifier.Operation.ADDITION)); + builder.put(Attributes.ARMOR_TOUGHNESS, new AttributeModifier(uuid, "Armor toughness", (double) this.toughness, AttributeModifier.Operation.ADDITION)); +- if (armormaterial == ArmorMaterials.NETHERITE) { ++ if (material == ArmorMaterials.NETHERITE) { + builder.put(Attributes.KNOCKBACK_RESISTANCE, new AttributeModifier(uuid, "Armor knockback resistance", (double) this.knockbackResistance, AttributeModifier.Operation.ADDITION)); + } + +@@ -95,7 +125,6 @@ + } + + @Override +- @Override + public int getEnchantmentValue() { + return this.material.getEnchantmentValue(); + } +@@ -105,21 +134,18 @@ + } + + @Override +- @Override +- public boolean isValidRepairItem(ItemStack itemstack, ItemStack itemstack1) { +- return this.material.getRepairIngredient().test(itemstack1) || super.isValidRepairItem(itemstack, itemstack1); ++ public boolean isValidRepairItem(ItemStack toRepair, ItemStack repair) { ++ return this.material.getRepairIngredient().test(repair) || super.isValidRepairItem(toRepair, repair); + } + + @Override +- @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand interactionhand) { +- return this.swapWithEquipmentSlot(this, level, player, interactionhand); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ return this.swapWithEquipmentSlot(this, level, player, hand); + } + + @Override +- @Override +- public Multimap getDefaultAttributeModifiers(EquipmentSlot equipmentslot) { +- return equipmentslot == this.type.getSlot() ? this.defaultModifiers : super.getDefaultAttributeModifiers(equipmentslot); ++ public Multimap getDefaultAttributeModifiers(EquipmentSlot equipmentSlot) { ++ return equipmentSlot == this.type.getSlot() ? this.defaultModifiers : super.getDefaultAttributeModifiers(equipmentSlot); + } + + public int getDefense() { +@@ -131,13 +157,11 @@ + } + + @Override +- @Override + public EquipmentSlot getEquipmentSlot() { + return this.type.getSlot(); + } + + @Override +- @Override + public SoundEvent getEquipSound() { + return this.getMaterial().getEquipSound(); + } +@@ -149,8 +173,8 @@ + private final EquipmentSlot slot; + private final String name; + +- private Type(EquipmentSlot equipmentslot, String s) { +- this.slot = equipmentslot; ++ private Type(EquipmentSlot enumitemslot, String s) { ++ this.slot = enumitemslot; + this.name = s; + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/ArmorStandItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/ArmorStandItem.java.patch new file mode 100644 index 0000000000..cb1b5174b4 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/ArmorStandItem.java.patch @@ -0,0 +1,85 @@ +--- a/net/minecraft/world/item/ArmorStandItem.java ++++ b/net/minecraft/world/item/ArmorStandItem.java +@@ -10,7 +10,7 @@ + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.decoration.ArmorStand; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.context.BlockPlaceContext; +@@ -22,45 +22,49 @@ + + public class ArmorStandItem extends Item { + +- public ArmorStandItem(Item.Properties item_properties) { +- super(item_properties); ++ public ArmorStandItem(Item.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public InteractionResult useOn(UseOnContext useoncontext) { +- Direction direction = useoncontext.getClickedFace(); ++ public InteractionResult useOn(UseOnContext context) { ++ Direction enumdirection = context.getClickedFace(); + +- if (direction == Direction.DOWN) { ++ if (enumdirection == Direction.DOWN) { + return InteractionResult.FAIL; + } else { +- Level level = useoncontext.getLevel(); +- BlockPlaceContext blockplacecontext = new BlockPlaceContext(useoncontext); +- BlockPos blockpos = blockplacecontext.getClickedPos(); +- ItemStack itemstack = useoncontext.getItemInHand(); +- Vec3 vec3 = Vec3.atBottomCenterOf(blockpos); +- AABB aabb = EntityType.ARMOR_STAND.getDimensions().makeBoundingBox(vec3.x(), vec3.y(), vec3.z()); ++ Level world = context.getLevel(); ++ BlockPlaceContext blockactioncontext = new BlockPlaceContext(context); ++ BlockPos blockposition = blockactioncontext.getClickedPos(); ++ ItemStack itemstack = context.getItemInHand(); ++ Vec3 vec3d = Vec3.atBottomCenterOf(blockposition); ++ AABB axisalignedbb = EntityType.ARMOR_STAND.getDimensions().makeBoundingBox(vec3d.x(), vec3d.y(), vec3d.z()); + +- if (level.noCollision((Entity) null, aabb) && level.getEntities((Entity) null, aabb).isEmpty()) { +- if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; +- Consumer consumer = EntityType.createDefaultStackConfig(serverlevel, itemstack, useoncontext.getPlayer()); +- ArmorStand armorstand = (ArmorStand) EntityType.ARMOR_STAND.create(serverlevel, itemstack.getTag(), consumer, blockpos, MobSpawnType.SPAWN_EGG, true, true); ++ if (world.noCollision((Entity) null, axisalignedbb) && world.getEntities((Entity) null, axisalignedbb).isEmpty()) { ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ Consumer consumer = EntityType.createDefaultStackConfig(worldserver, itemstack, context.getPlayer()); ++ ArmorStand entityarmorstand = (ArmorStand) EntityType.ARMOR_STAND.create(worldserver, itemstack.getTag(), consumer, blockposition, EnumMobSpawn.SPAWN_EGG, true, true); + +- if (armorstand == null) { ++ if (entityarmorstand == null) { + return InteractionResult.FAIL; + } + +- float f = (float) Mth.floor((Mth.wrapDegrees(useoncontext.getRotation() - 180.0F) + 22.5F) / 45.0F) * 45.0F; ++ float f = (float) Mth.floor((Mth.wrapDegrees(context.getRotation() - 180.0F) + 22.5F) / 45.0F) * 45.0F; + +- armorstand.moveTo(armorstand.getX(), armorstand.getY(), armorstand.getZ(), f, 0.0F); +- serverlevel.addFreshEntityWithPassengers(armorstand); +- level.playSound((Player) null, armorstand.getX(), armorstand.getY(), armorstand.getZ(), SoundEvents.ARMOR_STAND_PLACE, SoundSource.BLOCKS, 0.75F, 0.8F); +- armorstand.gameEvent(GameEvent.ENTITY_PLACE, useoncontext.getPlayer()); ++ entityarmorstand.moveTo(entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), f, 0.0F); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(context, entityarmorstand).isCancelled()) { ++ return InteractionResult.FAIL; ++ } ++ // CraftBukkit end ++ worldserver.addFreshEntityWithPassengers(entityarmorstand); ++ world.playSound((Player) null, entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), SoundEvents.ARMOR_STAND_PLACE, SoundSource.BLOCKS, 0.75F, 0.8F); ++ entityarmorstand.gameEvent(GameEvent.ENTITY_PLACE, context.getPlayer()); + } + + itemstack.shrink(1); +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } else { + return InteractionResult.FAIL; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/BlockItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/BlockItem.java.patch new file mode 100644 index 0000000000..fff559072b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/BlockItem.java.patch @@ -0,0 +1,398 @@ +--- a/net/minecraft/world/item/BlockItem.java ++++ b/net/minecraft/world/item/BlockItem.java +@@ -12,9 +12,9 @@ + import net.minecraft.nbt.ListTag; + import net.minecraft.network.chat.Component; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; +-import net.minecraft.sounds.SoundSource; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; +@@ -27,11 +27,15 @@ + import net.minecraft.world.level.block.SoundType; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BlockEntityType; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.Property; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.CollisionContext; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.event.block.BlockCanBuildEvent; ++// CraftBukkit end + + public class BlockItem extends Item { + +@@ -41,164 +45,199 @@ + @Deprecated + private final Block block; + +- public BlockItem(Block block, Item.Properties item_properties) { +- super(item_properties); ++ public BlockItem(Block block, Item.Properties properties) { ++ super(properties); + this.block = block; + } + + @Override +- @Override +- public InteractionResult useOn(UseOnContext useoncontext) { +- InteractionResult interactionresult = this.place(new BlockPlaceContext(useoncontext)); ++ public InteractionResult useOn(UseOnContext context) { ++ InteractionResult enuminteractionresult = this.place(new BlockPlaceContext(context)); + +- if (!interactionresult.consumesAction() && this.isEdible()) { +- InteractionResult interactionresult1 = this.use(useoncontext.getLevel(), useoncontext.getPlayer(), useoncontext.getHand()).getResult(); ++ if (!enuminteractionresult.consumesAction() && this.isEdible()) { ++ InteractionResult enuminteractionresult1 = this.use(context.getLevel(), context.getPlayer(), context.getHand()).getResult(); + +- return interactionresult1 == InteractionResult.CONSUME ? InteractionResult.CONSUME_PARTIAL : interactionresult1; ++ return enuminteractionresult1 == InteractionResult.CONSUME ? InteractionResult.CONSUME_PARTIAL : enuminteractionresult1; + } else { +- return interactionresult; ++ return enuminteractionresult; + } + } + +- public InteractionResult place(BlockPlaceContext blockplacecontext) { +- if (!this.getBlock().isEnabled(blockplacecontext.getLevel().enabledFeatures())) { ++ public InteractionResult place(BlockPlaceContext context) { ++ if (!this.getBlock().isEnabled(context.getLevel().enabledFeatures())) { + return InteractionResult.FAIL; +- } else if (!blockplacecontext.canPlace()) { ++ } else if (!context.canPlace()) { + return InteractionResult.FAIL; + } else { +- BlockPlaceContext blockplacecontext1 = this.updatePlacementContext(blockplacecontext); ++ BlockPlaceContext blockactioncontext1 = this.updatePlacementContext(context); + +- if (blockplacecontext1 == null) { ++ if (blockactioncontext1 == null) { + return InteractionResult.FAIL; + } else { +- BlockState blockstate = this.getPlacementState(blockplacecontext1); ++ IBlockData iblockdata = this.getPlacementState(blockactioncontext1); ++ // CraftBukkit start - special case for handling block placement with water lilies and snow buckets ++ org.bukkit.block.BlockState blockstate = null; ++ if (this instanceof PlaceOnWaterBlockItem || this instanceof SolidBucketItem) { ++ blockstate = org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockactioncontext1.getLevel(), blockactioncontext1.getClickedPos()); ++ } ++ // CraftBukkit end + +- if (blockstate == null) { ++ if (iblockdata == null) { + return InteractionResult.FAIL; +- } else if (!this.placeBlock(blockplacecontext1, blockstate)) { ++ } else if (!this.placeBlock(blockactioncontext1, iblockdata)) { + return InteractionResult.FAIL; + } else { +- BlockPos blockpos = blockplacecontext1.getClickedPos(); +- Level level = blockplacecontext1.getLevel(); +- Player player = blockplacecontext1.getPlayer(); +- ItemStack itemstack = blockplacecontext1.getItemInHand(); +- BlockState blockstate1 = level.getBlockState(blockpos); ++ BlockPos blockposition = blockactioncontext1.getClickedPos(); ++ Level world = blockactioncontext1.getLevel(); ++ Player entityhuman = blockactioncontext1.getPlayer(); ++ ItemStack itemstack = blockactioncontext1.getItemInHand(); ++ IBlockData iblockdata1 = world.getBlockState(blockposition); + +- if (blockstate1.is(blockstate.getBlock())) { +- blockstate1 = this.updateBlockStateFromTag(blockpos, level, itemstack, blockstate1); +- this.updateCustomBlockEntityTag(blockpos, level, player, itemstack, blockstate1); +- blockstate1.getBlock().setPlacedBy(level, blockpos, blockstate1, player, itemstack); +- if (player instanceof ServerPlayer) { +- CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) player, blockpos, itemstack); ++ if (iblockdata1.is(iblockdata.getBlock())) { ++ iblockdata1 = this.updateBlockStateFromTag(blockposition, world, itemstack, iblockdata1); ++ this.updateCustomBlockEntityTag(blockposition, world, entityhuman, itemstack, iblockdata1); ++ iblockdata1.getBlock().setPlacedBy(world, blockposition, iblockdata1, entityhuman, itemstack); ++ // CraftBukkit start ++ if (blockstate != null) { ++ org.bukkit.event.block.BlockPlaceEvent placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEvent((ServerLevel) world, entityhuman, blockactioncontext1.getHand(), blockstate, blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild())) { ++ blockstate.update(true, false); ++ ++ if (this instanceof SolidBucketItem) { ++ ((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 ++ } ++ return InteractionResult.FAIL; ++ } + } ++ // CraftBukkit end ++ if (entityhuman instanceof ServerPlayer) { ++ CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) entityhuman, blockposition, itemstack); ++ } + } + +- SoundType soundtype = blockstate1.getSoundType(); ++ SoundType soundeffecttype = iblockdata1.getSoundType(); + +- level.playSound(player, blockpos, this.getPlaceSound(blockstate1), SoundSource.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F); +- level.gameEvent(GameEvent.BLOCK_PLACE, blockpos, GameEvent.Context.of(player, blockstate1)); +- if (player == null || !player.getAbilities().instabuild) { ++ // world.playSound(entityhuman, blockposition, this.getPlaceSound(iblockdata1), SoundCategory.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F); ++ world.gameEvent(GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(entityhuman, iblockdata1)); ++ if ((entityhuman == null || !entityhuman.getAbilities().instabuild) && itemstack != ItemStack.EMPTY) { // CraftBukkit + itemstack.shrink(1); + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } + } + } + } + +- protected SoundEvent getPlaceSound(BlockState blockstate) { +- return blockstate.getSoundType().getPlaceSound(); ++ protected SoundEvent getPlaceSound(IBlockData state) { ++ return state.getSoundType().getPlaceSound(); + } + + @Nullable +- public BlockPlaceContext updatePlacementContext(BlockPlaceContext blockplacecontext) { +- return blockplacecontext; ++ public BlockPlaceContext updatePlacementContext(BlockPlaceContext context) { ++ return context; + } + +- protected boolean updateCustomBlockEntityTag(BlockPos blockpos, Level level, @Nullable Player player, ItemStack itemstack, BlockState blockstate) { +- return updateCustomBlockEntityTag(level, player, blockpos, itemstack); ++ protected boolean updateCustomBlockEntityTag(BlockPos pos, Level level, @Nullable Player player, ItemStack stack, IBlockData state) { ++ return updateCustomBlockEntityTag(level, player, pos, stack); + } + + @Nullable +- protected BlockState getPlacementState(BlockPlaceContext blockplacecontext) { +- BlockState blockstate = this.getBlock().getStateForPlacement(blockplacecontext); ++ protected IBlockData getPlacementState(BlockPlaceContext context) { ++ IBlockData iblockdata = this.getBlock().getStateForPlacement(context); + +- return blockstate != null && this.canPlace(blockplacecontext, blockstate) ? blockstate : null; ++ return iblockdata != null && this.canPlace(context, iblockdata) ? iblockdata : null; + } + +- private BlockState updateBlockStateFromTag(BlockPos blockpos, Level level, ItemStack itemstack, BlockState blockstate) { +- BlockState blockstate1 = blockstate; +- CompoundTag compoundtag = itemstack.getTag(); ++ private IBlockData updateBlockStateFromTag(BlockPos pos, Level level, ItemStack stack, IBlockData state) { ++ IBlockData iblockdata1 = state; ++ CompoundTag nbttagcompound = stack.getTag(); + +- if (compoundtag != null) { +- CompoundTag compoundtag1 = compoundtag.getCompound("BlockStateTag"); +- StateDefinition statedefinition = blockstate.getBlock().getStateDefinition(); +- Iterator iterator = compoundtag1.getAllKeys().iterator(); ++ if (nbttagcompound != null) { ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("BlockStateTag"); ++ // CraftBukkit start ++ iblockdata1 = getBlockState(iblockdata1, nbttagcompound1); ++ } + ++ if (iblockdata1 != state) { ++ level.setBlock(pos, iblockdata1, 2); ++ } ++ ++ return iblockdata1; ++ } ++ ++ public static IBlockData getBlockState(IBlockData iblockdata, CompoundTag nbttagcompound1) { ++ IBlockData iblockdata1 = iblockdata; ++ { ++ // CraftBukkit end ++ StateDefinition blockstatelist = iblockdata.getBlock().getStateDefinition(); ++ Iterator iterator = nbttagcompound1.getAllKeys().iterator(); ++ + while (iterator.hasNext()) { + String s = (String) iterator.next(); +- Property property = statedefinition.getProperty(s); ++ Property iblockstate = blockstatelist.getProperty(s); + +- if (property != null) { +- String s1 = compoundtag1.get(s).getAsString(); ++ if (iblockstate != null) { ++ String s1 = nbttagcompound1.get(s).getAsString(); + +- blockstate1 = updateState(blockstate1, property, s1); ++ iblockdata1 = updateState(iblockdata1, iblockstate, s1); + } + } + } +- +- if (blockstate1 != blockstate) { +- level.setBlock(blockpos, blockstate1, 2); +- } +- +- return blockstate1; ++ return iblockdata1; + } + +- private static > BlockState updateState(BlockState blockstate, Property property, String s) { +- return (BlockState) property.getValue(s).map((comparable) -> { +- return (BlockState) blockstate.setValue(property, comparable); +- }).orElse(blockstate); ++ private static > IBlockData updateState(IBlockData state, Property property, String valueIdentifier) { ++ return (IBlockData) property.getValue(valueIdentifier).map((comparable) -> { ++ return (IBlockData) state.setValue(property, comparable); ++ }).orElse(state); + } + +- protected boolean canPlace(BlockPlaceContext blockplacecontext, BlockState blockstate) { +- Player player = blockplacecontext.getPlayer(); +- CollisionContext collisioncontext = player == null ? CollisionContext.empty() : CollisionContext.of(player); ++ protected boolean canPlace(BlockPlaceContext context, IBlockData state) { ++ Player entityhuman = context.getPlayer(); ++ CollisionContext voxelshapecollision = entityhuman == null ? CollisionContext.empty() : CollisionContext.of(entityhuman); ++ // CraftBukkit start - store default return ++ boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && context.getLevel().isUnobstructed(state, context.getClickedPos(), voxelshapecollision); ++ org.bukkit.entity.Player player = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null; + +- return (!this.mustSurvive() || blockstate.canSurvive(blockplacecontext.getLevel(), blockplacecontext.getClickedPos())) && blockplacecontext.getLevel().isUnobstructed(blockstate, blockplacecontext.getClickedPos(), collisioncontext); ++ BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(context.getLevel(), context.getClickedPos()), player, CraftBlockData.fromData(state), defaultReturn); ++ context.getLevel().getCraftServer().getPluginManager().callEvent(event); ++ ++ return event.isBuildable(); ++ // CraftBukkit end + } + + protected boolean mustSurvive() { + return true; + } + +- protected boolean placeBlock(BlockPlaceContext blockplacecontext, BlockState blockstate) { +- return blockplacecontext.getLevel().setBlock(blockplacecontext.getClickedPos(), blockstate, 11); ++ protected boolean placeBlock(BlockPlaceContext context, IBlockData state) { ++ return context.getLevel().setBlock(context.getClickedPos(), state, 11); + } + +- public static boolean updateCustomBlockEntityTag(Level level, @Nullable Player player, BlockPos blockpos, ItemStack itemstack) { ++ public static boolean updateCustomBlockEntityTag(Level level, @Nullable Player player, BlockPos pos, ItemStack stack) { + MinecraftServer minecraftserver = level.getServer(); + + if (minecraftserver == null) { + return false; + } else { +- CompoundTag compoundtag = getBlockEntityData(itemstack); ++ CompoundTag nbttagcompound = getBlockEntityData(stack); + +- if (compoundtag != null) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ if (nbttagcompound != null) { ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity != null) { +- if (!level.isClientSide && blockentity.onlyOpCanSetNbt() && (player == null || !player.canUseGameMasterBlocks())) { ++ if (tileentity != null) { ++ if (!level.isClientSide && tileentity.onlyOpCanSetNbt() && (player == null || !player.canUseGameMasterBlocks())) { + return false; + } + +- CompoundTag compoundtag1 = blockentity.saveWithoutMetadata(); +- CompoundTag compoundtag2 = compoundtag1.copy(); ++ CompoundTag nbttagcompound1 = tileentity.saveWithoutMetadata(); ++ CompoundTag nbttagcompound2 = nbttagcompound1.copy(); + +- compoundtag1.merge(compoundtag); +- if (!compoundtag1.equals(compoundtag2)) { +- blockentity.load(compoundtag1); +- blockentity.setChanged(); ++ nbttagcompound1.merge(nbttagcompound); ++ if (!nbttagcompound1.equals(nbttagcompound2)) { ++ tileentity.load(nbttagcompound1); ++ tileentity.setChanged(); + return true; + } + } +@@ -209,67 +248,62 @@ + } + + @Override +- @Override + public String getDescriptionId() { + return this.getBlock().getDescriptionId(); + } + + @Override +- @Override +- public void appendHoverText(ItemStack itemstack, @Nullable Level level, List list, TooltipFlag tooltipflag) { +- super.appendHoverText(itemstack, level, list, tooltipflag); +- this.getBlock().appendHoverText(itemstack, level, list, tooltipflag); ++ public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { ++ super.appendHoverText(stack, level, tooltip, flag); ++ this.getBlock().appendHoverText(stack, level, tooltip, flag); + } + + public Block getBlock() { + return this.block; + } + +- public void registerBlocks(Map map, Item item) { +- map.put(this.getBlock(), item); ++ public void registerBlocks(Map blockToItemMap, Item item) { ++ blockToItemMap.put(this.getBlock(), item); + } + + @Override +- @Override + public boolean canFitInsideContainerItems() { + return !(this.block instanceof ShulkerBoxBlock); + } + + @Override +- @Override +- public void onDestroyed(ItemEntity itementity) { ++ public void onDestroyed(ItemEntity itemEntity) { + if (this.block instanceof ShulkerBoxBlock) { +- ItemStack itemstack = itementity.getItem(); +- CompoundTag compoundtag = getBlockEntityData(itemstack); ++ ItemStack itemstack = itemEntity.getItem(); ++ CompoundTag nbttagcompound = getBlockEntityData(itemstack); + +- if (compoundtag != null && compoundtag.contains("Items", 9)) { +- ListTag listtag = compoundtag.getList("Items", 10); +- Stream stream = listtag.stream(); ++ if (nbttagcompound != null && nbttagcompound.contains("Items", 9)) { ++ ListTag nbttaglist = nbttagcompound.getList("Items", 10); ++ Stream stream = nbttaglist.stream(); // CraftBukkit - decompile error + + Objects.requireNonNull(CompoundTag.class); +- ItemUtils.onContainerDestroyed(itementity, stream.map(CompoundTag.class::cast).map(ItemStack::of)); ++ ItemUtils.onContainerDestroyed(itemEntity, stream.map(CompoundTag.class::cast).map(ItemStack::of)); + } + } + + } + + @Nullable +- public static CompoundTag getBlockEntityData(ItemStack itemstack) { +- return itemstack.getTagElement("BlockEntityTag"); ++ public static CompoundTag getBlockEntityData(ItemStack stack) { ++ return stack.getTagElement("BlockEntityTag"); + } + +- public static void setBlockEntityData(ItemStack itemstack, BlockEntityType blockentitytype, CompoundTag compoundtag) { +- if (compoundtag.isEmpty()) { +- itemstack.removeTagKey("BlockEntityTag"); ++ public static void setBlockEntityData(ItemStack stack, BlockEntityType blockEntityType, CompoundTag blockEntityData) { ++ if (blockEntityData.isEmpty()) { ++ stack.removeTagKey("BlockEntityTag"); + } else { +- BlockEntity.addEntityType(compoundtag, blockentitytype); +- itemstack.addTagElement("BlockEntityTag", compoundtag); ++ BlockEntity.addEntityType(blockEntityData, blockEntityType); ++ stack.addTagElement("BlockEntityTag", blockEntityData); + } + + } + + @Override +- @Override + public FeatureFlagSet requiredFeatures() { + return this.getBlock().requiredFeatures(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/BoatItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/BoatItem.java.patch new file mode 100644 index 0000000000..e85cb14fde --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/BoatItem.java.patch @@ -0,0 +1,118 @@ +--- a/net/minecraft/world/item/BoatItem.java ++++ b/net/minecraft/world/item/BoatItem.java +@@ -5,7 +5,7 @@ + import java.util.function.Predicate; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntitySelector; +@@ -27,50 +27,64 @@ + private final Boat.Type type; + private final boolean hasChest; + +- public BoatItem(boolean flag, Boat.Type boat_type, Item.Properties item_properties) { +- super(item_properties); +- this.hasChest = flag; +- this.type = boat_type; ++ public BoatItem(boolean hasChest, Boat.Type type, Item.Properties properties) { ++ super(properties); ++ this.hasChest = hasChest; ++ this.type = type; + } + + @Override +- @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); +- BlockHitResult blockhitresult = getPlayerPOVHitResult(level, player, ClipContext.Fluid.ANY); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ BlockHitResult movingobjectpositionblock = getPlayerPOVHitResult(level, player, ClipContext.Fluid.ANY); + +- if (blockhitresult.getType() == HitResult.Type.MISS) { ++ if (movingobjectpositionblock.getType() == HitResult.EnumMovingObjectType.MISS) { + return InteractionResultHolder.pass(itemstack); + } else { +- Vec3 vec3 = player.getViewVector(1.0F); ++ Vec3 vec3d = player.getViewVector(1.0F); + double d0 = 5.0D; +- List list = level.getEntities((Entity) player, player.getBoundingBox().expandTowards(vec3.scale(5.0D)).inflate(1.0D), BoatItem.ENTITY_PREDICATE); ++ List list = level.getEntities((Entity) player, player.getBoundingBox().expandTowards(vec3d.scale(5.0D)).inflate(1.0D), BoatItem.ENTITY_PREDICATE); + + if (!list.isEmpty()) { +- Vec3 vec31 = player.getEyePosition(); ++ Vec3 vec3d1 = player.getEyePosition(); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); +- AABB aabb = entity.getBoundingBox().inflate((double) entity.getPickRadius()); ++ AABB axisalignedbb = entity.getBoundingBox().inflate((double) entity.getPickRadius()); + +- if (aabb.contains(vec31)) { ++ if (axisalignedbb.contains(vec3d1)) { + return InteractionResultHolder.pass(itemstack); + } + } + } + +- if (blockhitresult.getType() == HitResult.Type.BLOCK) { +- Boat boat = this.getBoat(level, blockhitresult, itemstack, player); ++ if (movingobjectpositionblock.getType() == HitResult.EnumMovingObjectType.BLOCK) { ++ // CraftBukkit start - Boat placement ++ org.bukkit.event.player.PlayerInteractEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(player, org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), itemstack, false, hand, movingobjectpositionblock.getLocation()); + +- boat.setVariant(this.type); +- boat.setYRot(player.getYRot()); +- if (!level.noCollision(boat, boat.getBoundingBox())) { ++ if (event.isCancelled()) { ++ return InteractionResultHolder.pass(itemstack); ++ } ++ // CraftBukkit end ++ Boat entityboat = this.getBoat(level, movingobjectpositionblock, itemstack, player); ++ ++ entityboat.setVariant(this.type); ++ entityboat.setYRot(player.getYRot()); ++ if (!level.noCollision(entityboat, entityboat.getBoundingBox())) { + return InteractionResultHolder.fail(itemstack); + } else { + if (!level.isClientSide) { +- level.addFreshEntity(boat); +- level.gameEvent((Entity) player, GameEvent.ENTITY_PLACE, blockhitresult.getLocation()); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(level, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), player, entityboat, hand).isCancelled()) { ++ return InteractionResultHolder.fail(itemstack); ++ } ++ ++ if (!level.addFreshEntity(entityboat)) { ++ return InteractionResultHolder.pass(itemstack); ++ } ++ // CraftBukkit end ++ level.gameEvent((Entity) player, GameEvent.ENTITY_PLACE, movingobjectpositionblock.getLocation()); + if (!player.getAbilities().instabuild) { + itemstack.shrink(1); + } +@@ -85,14 +99,14 @@ + } + } + +- private Boat getBoat(Level level, HitResult hitresult, ItemStack itemstack, Player player) { +- Vec3 vec3 = hitresult.getLocation(); +- Object object = this.hasChest ? new ChestBoat(level, vec3.x, vec3.y, vec3.z) : new Boat(level, vec3.x, vec3.y, vec3.z); ++ private Boat getBoat(Level world, HitResult movingobjectposition, ItemStack itemstack, Player entityhuman) { ++ Vec3 vec3d = movingobjectposition.getLocation(); ++ Boat object = this.hasChest ? new ChestBoat(world, vec3d.x, vec3d.y, vec3d.z) : new Boat(world, vec3d.x, vec3d.y, vec3d.z); // CraftBukkit - decompile error + +- if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; + +- EntityType.createDefaultStackConfig(serverlevel, itemstack, player).accept(object); ++ EntityType.createDefaultStackConfig(worldserver, itemstack, entityhuman).accept(object); + } + + return (Boat) object; diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/BoneMealItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/BoneMealItem.java.patch new file mode 100644 index 0000000000..850ee9f189 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/BoneMealItem.java.patch @@ -0,0 +1,260 @@ +--- a/net/minecraft/world/item/BoneMealItem.java ++++ b/net/minecraft/world/item/BoneMealItem.java +@@ -19,7 +19,7 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.BonemealableBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + + public class BoneMealItem extends Item { +@@ -28,55 +28,60 @@ + public static final int GRASS_SPREAD_HEIGHT = 1; + public static final int GRASS_COUNT_MULTIPLIER = 3; + +- public BoneMealItem(Item.Properties item_properties) { +- super(item_properties); ++ public BoneMealItem(Item.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public InteractionResult useOn(UseOnContext useoncontext) { +- Level level = useoncontext.getLevel(); +- BlockPos blockpos = useoncontext.getClickedPos(); +- BlockPos blockpos1 = blockpos.relative(useoncontext.getClickedFace()); ++ public InteractionResult useOn(UseOnContext context) { ++ // CraftBukkit start - extract bonemeal application logic to separate, static method ++ return applyBonemeal(context); ++ } + +- if (growCrop(useoncontext.getItemInHand(), level, blockpos)) { +- if (!level.isClientSide) { +- useoncontext.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); +- level.levelEvent(1505, blockpos, 0); ++ public static InteractionResult applyBonemeal(UseOnContext itemactioncontext) { ++ // CraftBukkit end ++ Level world = itemactioncontext.getLevel(); ++ BlockPos blockposition = itemactioncontext.getClickedPos(); ++ BlockPos blockposition1 = blockposition.relative(itemactioncontext.getClickedFace()); ++ ++ if (growCrop(itemactioncontext.getItemInHand(), world, blockposition)) { ++ if (!world.isClientSide) { ++ if (itemactioncontext.getPlayer() != null) itemactioncontext.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); // CraftBukkit - SPIGOT-7518 ++ world.levelEvent(1505, blockposition, 0); + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } else { +- BlockState blockstate = level.getBlockState(blockpos); +- boolean flag = blockstate.isFaceSturdy(level, blockpos, useoncontext.getClickedFace()); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ boolean flag = iblockdata.isFaceSturdy(world, blockposition, itemactioncontext.getClickedFace()); + +- if (flag && growWaterPlant(useoncontext.getItemInHand(), level, blockpos1, useoncontext.getClickedFace())) { +- if (!level.isClientSide) { +- useoncontext.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); +- level.levelEvent(1505, blockpos1, 0); ++ if (flag && growWaterPlant(itemactioncontext.getItemInHand(), world, blockposition1, itemactioncontext.getClickedFace())) { ++ if (!world.isClientSide) { ++ if (itemactioncontext.getPlayer() != null) itemactioncontext.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); // CraftBukkit - SPIGOT-7518 ++ world.levelEvent(1505, blockposition1, 0); + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } else { + return InteractionResult.PASS; + } + } + } + +- public static boolean growCrop(ItemStack itemstack, Level level, BlockPos blockpos) { +- BlockState blockstate = level.getBlockState(blockpos); +- Block block = blockstate.getBlock(); ++ public static boolean growCrop(ItemStack stack, Level level, BlockPos pos) { ++ IBlockData iblockdata = level.getBlockState(pos); ++ Block block = iblockdata.getBlock(); + + if (block instanceof BonemealableBlock) { +- BonemealableBlock bonemealableblock = (BonemealableBlock) block; ++ BonemealableBlock iblockfragileplantelement = (BonemealableBlock) block; + +- if (bonemealableblock.isValidBonemealTarget(level, blockpos, blockstate)) { ++ if (iblockfragileplantelement.isValidBonemealTarget(level, pos, iblockdata)) { + if (level instanceof ServerLevel) { +- if (bonemealableblock.isBonemealSuccess(level, level.random, blockpos, blockstate)) { +- bonemealableblock.performBonemeal((ServerLevel) level, level.random, blockpos, blockstate); ++ if (iblockfragileplantelement.isBonemealSuccess(level, level.random, pos, iblockdata)) { ++ iblockfragileplantelement.performBonemeal((ServerLevel) level, level.random, pos, iblockdata); + } + +- itemstack.shrink(1); ++ stack.shrink(1); + } + + return true; +@@ -86,8 +91,8 @@ + return false; + } + +- public static boolean growWaterPlant(ItemStack itemstack, Level level, BlockPos blockpos, @Nullable Direction direction) { +- if (level.getBlockState(blockpos).is(Blocks.WATER) && level.getFluidState(blockpos).getAmount() == 8) { ++ public static boolean growWaterPlant(ItemStack stack, Level level, BlockPos pos, @Nullable Direction clickedSide) { ++ if (level.getBlockState(pos).is(Blocks.WATER) && level.getFluidState(pos).getAmount() == 8) { + if (!(level instanceof ServerLevel)) { + return true; + } else { +@@ -95,54 +100,54 @@ + int i = 0; + + while (i < 128) { +- BlockPos blockpos1 = blockpos; +- BlockState blockstate = Blocks.SEAGRASS.defaultBlockState(); ++ BlockPos blockposition1 = pos; ++ IBlockData iblockdata = Blocks.SEAGRASS.defaultBlockState(); + int j = 0; + + while (true) { + if (j < i / 16) { +- blockpos1 = blockpos1.offset(randomsource.nextInt(3) - 1, (randomsource.nextInt(3) - 1) * randomsource.nextInt(3) / 2, randomsource.nextInt(3) - 1); +- if (!level.getBlockState(blockpos1).isCollisionShapeFullBlock(level, blockpos1)) { ++ blockposition1 = blockposition1.offset(randomsource.nextInt(3) - 1, (randomsource.nextInt(3) - 1) * randomsource.nextInt(3) / 2, randomsource.nextInt(3) - 1); ++ if (!level.getBlockState(blockposition1).isCollisionShapeFullBlock(level, blockposition1)) { + ++j; + continue; + } + } else { +- Holder holder = level.getBiome(blockpos1); ++ Holder holder = level.getBiome(blockposition1); + + if (holder.is(BiomeTags.PRODUCES_CORALS_FROM_BONEMEAL)) { +- if (i == 0 && direction != null && direction.getAxis().isHorizontal()) { +- blockstate = (BlockState) BuiltInRegistries.BLOCK.getTag(BlockTags.WALL_CORALS).flatMap((holderset_named) -> { ++ if (i == 0 && clickedSide != null && clickedSide.getAxis().isHorizontal()) { ++ iblockdata = (IBlockData) BuiltInRegistries.BLOCK.getTag(BlockTags.WALL_CORALS).flatMap((holderset_named) -> { + return holderset_named.getRandomElement(level.random); + }).map((holder1) -> { + return ((Block) holder1.value()).defaultBlockState(); +- }).orElse(blockstate); +- if (blockstate.hasProperty(BaseCoralWallFanBlock.FACING)) { +- blockstate = (BlockState) blockstate.setValue(BaseCoralWallFanBlock.FACING, direction); ++ }).orElse(iblockdata); ++ if (iblockdata.hasProperty(BaseCoralWallFanBlock.FACING)) { ++ iblockdata = (IBlockData) iblockdata.setValue(BaseCoralWallFanBlock.FACING, clickedSide); + } + } else if (randomsource.nextInt(4) == 0) { +- blockstate = (BlockState) BuiltInRegistries.BLOCK.getTag(BlockTags.UNDERWATER_BONEMEALS).flatMap((holderset_named) -> { ++ iblockdata = (IBlockData) BuiltInRegistries.BLOCK.getTag(BlockTags.UNDERWATER_BONEMEALS).flatMap((holderset_named) -> { + return holderset_named.getRandomElement(level.random); + }).map((holder1) -> { + return ((Block) holder1.value()).defaultBlockState(); +- }).orElse(blockstate); ++ }).orElse(iblockdata); + } + } + +- if (blockstate.is(BlockTags.WALL_CORALS, (blockbehaviour_blockstatebase) -> { +- return blockbehaviour_blockstatebase.hasProperty(BaseCoralWallFanBlock.FACING); ++ if (iblockdata.is(BlockTags.WALL_CORALS, (blockbase_blockdata) -> { ++ return blockbase_blockdata.hasProperty(BaseCoralWallFanBlock.FACING); + })) { +- for (int k = 0; !blockstate.canSurvive(level, blockpos1) && k < 4; ++k) { +- blockstate = (BlockState) blockstate.setValue(BaseCoralWallFanBlock.FACING, Direction.Plane.HORIZONTAL.getRandomDirection(randomsource)); ++ for (int k = 0; !iblockdata.canSurvive(level, blockposition1) && k < 4; ++k) { ++ iblockdata = (IBlockData) iblockdata.setValue(BaseCoralWallFanBlock.FACING, Direction.Plane.HORIZONTAL.getRandomDirection(randomsource)); + } + } + +- if (blockstate.canSurvive(level, blockpos1)) { +- BlockState blockstate1 = level.getBlockState(blockpos1); ++ if (iblockdata.canSurvive(level, blockposition1)) { ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + +- if (blockstate1.is(Blocks.WATER) && level.getFluidState(blockpos1).getAmount() == 8) { +- level.setBlock(blockpos1, blockstate, 3); +- } else if (blockstate1.is(Blocks.SEAGRASS) && randomsource.nextInt(10) == 0) { +- ((BonemealableBlock) Blocks.SEAGRASS).performBonemeal((ServerLevel) level, randomsource, blockpos1, blockstate1); ++ if (iblockdata1.is(Blocks.WATER) && level.getFluidState(blockposition1).getAmount() == 8) { ++ level.setBlock(blockposition1, iblockdata, 3); ++ } else if (iblockdata1.is(Blocks.SEAGRASS) && randomsource.nextInt(10) == 0) { ++ ((BonemealableBlock) Blocks.SEAGRASS).performBonemeal((ServerLevel) level, randomsource, blockposition1, iblockdata1); + } + } + } +@@ -152,7 +157,7 @@ + } + } + +- itemstack.shrink(1); ++ stack.shrink(1); + return true; + } + } else { +@@ -160,44 +165,44 @@ + } + } + +- public static void addGrowthParticles(LevelAccessor levelaccessor, BlockPos blockpos, int i) { +- if (i == 0) { +- i = 15; ++ public static void addGrowthParticles(LevelAccessor level, BlockPos pos, int data) { ++ if (data == 0) { ++ data = 15; + } + +- BlockState blockstate = levelaccessor.getBlockState(blockpos); ++ IBlockData iblockdata = level.getBlockState(pos); + +- if (!blockstate.isAir()) { ++ if (!iblockdata.isAir()) { + double d0 = 0.5D; + double d1; + +- if (blockstate.is(Blocks.WATER)) { +- i *= 3; ++ if (iblockdata.is(Blocks.WATER)) { ++ data *= 3; + d1 = 1.0D; + d0 = 3.0D; +- } else if (blockstate.isSolidRender(levelaccessor, blockpos)) { +- blockpos = blockpos.above(); +- i *= 3; ++ } else if (iblockdata.isSolidRender(level, pos)) { ++ pos = pos.above(); ++ data *= 3; + d0 = 3.0D; + d1 = 1.0D; + } else { +- d1 = blockstate.getShape(levelaccessor, blockpos).max(Direction.Axis.Y); ++ d1 = iblockdata.getShape(level, pos).max(Direction.Axis.Y); + } + +- levelaccessor.addParticle(ParticleTypes.HAPPY_VILLAGER, (double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D, 0.0D, 0.0D, 0.0D); +- RandomSource randomsource = levelaccessor.getRandom(); ++ level.addParticle(ParticleTypes.HAPPY_VILLAGER, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, 0.0D, 0.0D, 0.0D); ++ RandomSource randomsource = level.getRandom(); + +- for (int j = 0; j < i; ++j) { ++ for (int j = 0; j < data; ++j) { + double d2 = randomsource.nextGaussian() * 0.02D; + double d3 = randomsource.nextGaussian() * 0.02D; + double d4 = randomsource.nextGaussian() * 0.02D; + double d5 = 0.5D - d0; +- double d6 = (double) blockpos.getX() + d5 + randomsource.nextDouble() * d0 * 2.0D; +- double d7 = (double) blockpos.getY() + randomsource.nextDouble() * d1; +- double d8 = (double) blockpos.getZ() + d5 + randomsource.nextDouble() * d0 * 2.0D; ++ double d6 = (double) pos.getX() + d5 + randomsource.nextDouble() * d0 * 2.0D; ++ double d7 = (double) pos.getY() + randomsource.nextDouble() * d1; ++ double d8 = (double) pos.getZ() + d5 + randomsource.nextDouble() * d0 * 2.0D; + +- if (!levelaccessor.getBlockState(BlockPos.containing(d6, d7, d8).below()).isAir()) { +- levelaccessor.addParticle(ParticleTypes.HAPPY_VILLAGER, d6, d7, d8, d2, d3, d4); ++ if (!level.getBlockState(BlockPos.containing(d6, d7, d8).below()).isAir()) { ++ level.addParticle(ParticleTypes.HAPPY_VILLAGER, d6, d7, d8, d2, d3, d4); + } + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/BowItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/BowItem.java.patch new file mode 100644 index 0000000000..5b28a72dac --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/BowItem.java.patch @@ -0,0 +1,190 @@ +--- a/net/minecraft/world/item/BowItem.java ++++ b/net/minecraft/world/item/BowItem.java +@@ -4,7 +4,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.player.Player; +@@ -13,85 +13,101 @@ + import net.minecraft.world.item.enchantment.Enchantments; + import net.minecraft.world.level.Level; + +-public class BowItem extends ProjectileWeaponItem implements Vanishable { ++public class BowItem extends ProjectileWeaponItem implements ItemVanishable { + + public static final int MAX_DRAW_DURATION = 20; + public static final int DEFAULT_RANGE = 15; + +- public BowItem(Item.Properties item_properties) { +- super(item_properties); ++ public BowItem(Item.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public void releaseUsing(ItemStack itemstack, Level level, LivingEntity livingentity, int i) { +- if (livingentity instanceof Player) { +- Player player = (Player) livingentity; +- boolean flag = player.getAbilities().instabuild || EnchantmentHelper.getItemEnchantmentLevel(Enchantments.INFINITY_ARROWS, itemstack) > 0; +- ItemStack itemstack1 = player.getProjectile(itemstack); ++ public void releaseUsing(ItemStack stack, Level level, LivingEntity entityLiving, int timeLeft) { ++ if (entityLiving instanceof Player) { ++ Player entityhuman = (Player) entityLiving; ++ boolean flag = entityhuman.getAbilities().instabuild || EnchantmentHelper.getItemEnchantmentLevel(Enchantments.INFINITY_ARROWS, stack) > 0; ++ ItemStack itemstack1 = entityhuman.getProjectile(stack); + + if (!itemstack1.isEmpty() || flag) { + if (itemstack1.isEmpty()) { + itemstack1 = new ItemStack(Items.ARROW); + } + +- int j = this.getUseDuration(itemstack) - i; ++ int j = this.getUseDuration(stack) - timeLeft; + float f = getPowerForTime(j); + + if ((double) f >= 0.1D) { + boolean flag1 = flag && itemstack1.is(Items.ARROW); + + if (!level.isClientSide) { +- ArrowItem arrowitem = (ArrowItem) (itemstack1.getItem() instanceof ArrowItem ? itemstack1.getItem() : Items.ARROW); +- AbstractArrow abstractarrow = arrowitem.createArrow(level, itemstack1, player); ++ ArrowItem itemarrow = (ArrowItem) (itemstack1.getItem() instanceof ArrowItem ? itemstack1.getItem() : Items.ARROW); ++ AbstractArrow entityarrow = itemarrow.createArrow(level, itemstack1, entityhuman); + +- abstractarrow.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, f * 3.0F, 1.0F); ++ entityarrow.shootFromRotation(entityhuman, entityhuman.getXRot(), entityhuman.getYRot(), 0.0F, f * 3.0F, 1.0F); + if (f == 1.0F) { +- abstractarrow.setCritArrow(true); ++ entityarrow.setCritArrow(true); + } + +- int k = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.POWER_ARROWS, itemstack); ++ int k = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.POWER_ARROWS, stack); + + if (k > 0) { +- abstractarrow.setBaseDamage(abstractarrow.getBaseDamage() + (double) k * 0.5D + 0.5D); ++ entityarrow.setBaseDamage(entityarrow.getBaseDamage() + (double) k * 0.5D + 0.5D); + } + +- int l = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.PUNCH_ARROWS, itemstack); ++ int l = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.PUNCH_ARROWS, stack); + + if (l > 0) { +- abstractarrow.setKnockback(l); ++ entityarrow.setKnockback(l); + } + +- if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.FLAMING_ARROWS, itemstack) > 0) { +- abstractarrow.setSecondsOnFire(100); ++ if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.FLAMING_ARROWS, stack) > 0) { ++ entityarrow.setSecondsOnFire(100); + } ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(entityhuman, stack, itemstack1, entityarrow, entityhuman.getUsedItemHand(), f, !flag1); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ flag1 = !event.shouldConsumeItem(); ++ // CraftBukkit end + +- itemstack.hurtAndBreak(1, player, (player1) -> { +- player1.broadcastBreakEvent(player.getUsedItemHand()); ++ stack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(entityhuman.getUsedItemHand()); + }); +- if (flag1 || player.getAbilities().instabuild && (itemstack1.is(Items.SPECTRAL_ARROW) || itemstack1.is(Items.TIPPED_ARROW))) { +- abstractarrow.pickup = AbstractArrow.Pickup.CREATIVE_ONLY; ++ if (flag1 || entityhuman.getAbilities().instabuild && (itemstack1.is(Items.SPECTRAL_ARROW) || itemstack1.is(Items.TIPPED_ARROW))) { ++ entityarrow.pickup = AbstractArrow.Pickup.CREATIVE_ONLY; + } + +- level.addFreshEntity(abstractarrow); ++ // CraftBukkit start ++ if (event.getProjectile() == entityarrow.getBukkitEntity()) { ++ if (!level.addFreshEntity(entityarrow)) { ++ if (entityhuman instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } ++ return; ++ } ++ } ++ // CraftBukkit end + } + +- level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.ARROW_SHOOT, SoundSource.PLAYERS, 1.0F, 1.0F / (level.getRandom().nextFloat() * 0.4F + 1.2F) + f * 0.5F); +- if (!flag1 && !player.getAbilities().instabuild) { ++ level.playSound((Player) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEvents.ARROW_SHOOT, SoundSource.PLAYERS, 1.0F, 1.0F / (level.getRandom().nextFloat() * 0.4F + 1.2F) + f * 0.5F); ++ if (!flag1 && !entityhuman.getAbilities().instabuild) { + itemstack1.shrink(1); + if (itemstack1.isEmpty()) { +- player.getInventory().removeItem(itemstack1); ++ entityhuman.getInventory().removeItem(itemstack1); + } + } + +- player.awardStat(Stats.ITEM_USED.get(this)); ++ entityhuman.awardStat(Stats.ITEM_USED.get(this)); + } + } + } + } + +- public static float getPowerForTime(int i) { +- float f = (float) i / 20.0F; ++ public static float getPowerForTime(int charge) { ++ float f = (float) charge / 20.0F; + + f = (f * f + f * 2.0F) / 3.0F; + if (f > 1.0F) { +@@ -102,39 +118,34 @@ + } + + @Override +- @Override +- public int getUseDuration(ItemStack itemstack) { ++ public int getUseDuration(ItemStack stack) { + return 72000; + } + + @Override +- @Override +- public UseAnim getUseAnimation(ItemStack itemstack) { +- return UseAnim.BOW; ++ public EnumAnimation getUseAnimation(ItemStack stack) { ++ return EnumAnimation.BOW; + } + + @Override +- @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + boolean flag = !player.getProjectile(itemstack).isEmpty(); + + if (!player.getAbilities().instabuild && !flag) { + return InteractionResultHolder.fail(itemstack); + } else { +- player.startUsingItem(interactionhand); ++ player.startUsingItem(hand); + return InteractionResultHolder.consume(itemstack); + } + } + + @Override +- @Override + public Predicate getAllSupportedProjectiles() { + return BowItem.ARROW_ONLY; + } + + @Override +- @Override + public int getDefaultProjectileRange() { + return 15; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/BucketItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/BucketItem.java.patch new file mode 100644 index 0000000000..59d28174e7 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/BucketItem.java.patch @@ -0,0 +1,275 @@ +--- a/net/minecraft/world/item/BucketItem.java ++++ b/net/minecraft/world/item/BucketItem.java +@@ -5,13 +5,15 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.core.particles.ParticleTypes; ++import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; + import net.minecraft.tags.FluidTags; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; +@@ -21,56 +23,72 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.BucketPickup; + import net.minecraft.world.level.block.LiquidBlockContainer; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.FlowingFluid; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.HitResult; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.DummyGeneratorAccess; ++import org.bukkit.event.player.PlayerBucketEmptyEvent; ++import org.bukkit.event.player.PlayerBucketFillEvent; ++// CraftBukkit end + + public class BucketItem extends Item implements DispensibleContainerItem { + +- private final Fluid content; ++ public final Fluid content; + +- public BucketItem(Fluid fluid, Item.Properties item_properties) { +- super(item_properties); +- this.content = fluid; ++ public BucketItem(Fluid content, Item.Properties properties) { ++ super(properties); ++ this.content = content; + } + + @Override +- @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); +- BlockHitResult blockhitresult = getPlayerPOVHitResult(level, player, this.content == Fluids.EMPTY ? ClipContext.Fluid.SOURCE_ONLY : ClipContext.Fluid.NONE); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ BlockHitResult movingobjectpositionblock = getPlayerPOVHitResult(level, player, this.content == Fluids.EMPTY ? ClipContext.Fluid.SOURCE_ONLY : ClipContext.Fluid.NONE); + +- if (blockhitresult.getType() == HitResult.Type.MISS) { ++ if (movingobjectpositionblock.getType() == HitResult.EnumMovingObjectType.MISS) { + return InteractionResultHolder.pass(itemstack); +- } else if (blockhitresult.getType() != HitResult.Type.BLOCK) { ++ } else if (movingobjectpositionblock.getType() != HitResult.EnumMovingObjectType.BLOCK) { + return InteractionResultHolder.pass(itemstack); + } else { +- BlockPos blockpos = blockhitresult.getBlockPos(); +- Direction direction = blockhitresult.getDirection(); +- BlockPos blockpos1 = blockpos.relative(direction); ++ BlockPos blockposition = movingobjectpositionblock.getBlockPos(); ++ Direction enumdirection = movingobjectpositionblock.getDirection(); ++ BlockPos blockposition1 = blockposition.relative(enumdirection); + +- if (level.mayInteract(player, blockpos) && player.mayUseItemAt(blockpos1, direction, itemstack)) { +- BlockState blockstate; ++ if (level.mayInteract(player, blockposition) && player.mayUseItemAt(blockposition1, enumdirection, itemstack)) { ++ IBlockData iblockdata; + + if (this.content == Fluids.EMPTY) { +- blockstate = level.getBlockState(blockpos); +- Block block = blockstate.getBlock(); ++ iblockdata = level.getBlockState(blockposition); ++ Block block = iblockdata.getBlock(); + + if (block instanceof BucketPickup) { +- BucketPickup bucketpickup = (BucketPickup) block; +- ItemStack itemstack1 = bucketpickup.pickupBlock(player, level, blockpos, blockstate); ++ BucketPickup ifluidsource = (BucketPickup) block; ++ // CraftBukkit start ++ ItemStack dummyFluid = ifluidsource.pickupBlock(player, DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); ++ if (dummyFluid.isEmpty()) return InteractionResultHolder.fail(itemstack); // Don't fire event if the bucket won't be filled. ++ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) level, player, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.getItem(), hand); + ++ if (event.isCancelled()) { ++ ((ServerPlayer) player).connection.send(new ClientboundBlockUpdatePacket(level, blockposition)); // SPIGOT-5163 (see PlayerInteractManager) ++ ((ServerPlayer) player).getBukkitEntity().updateInventory(); // SPIGOT-4541 ++ return InteractionResultHolder.fail(itemstack); ++ } ++ // CraftBukkit end ++ ItemStack itemstack1 = ifluidsource.pickupBlock(player, level, blockposition, iblockdata); ++ + if (!itemstack1.isEmpty()) { + player.awardStat(Stats.ITEM_USED.get(this)); +- bucketpickup.getPickupSound().ifPresent((soundevent) -> { +- player.playSound(soundevent, 1.0F, 1.0F); ++ ifluidsource.getPickupSound().ifPresent((soundeffect) -> { ++ player.playSound(soundeffect, 1.0F, 1.0F); + }); +- level.gameEvent((Entity) player, GameEvent.FLUID_PICKUP, blockpos); +- ItemStack itemstack2 = ItemUtils.createFilledResult(itemstack, player, itemstack1); ++ level.gameEvent((Entity) player, GameEvent.FLUID_PICKUP, blockposition); ++ ItemStack itemstack2 = ItemUtils.createFilledResult(itemstack, player, CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit + + if (!level.isClientSide) { + CriteriaTriggers.FILLED_BUCKET.trigger((ServerPlayer) player, itemstack1); +@@ -82,13 +100,13 @@ + + return InteractionResultHolder.fail(itemstack); + } else { +- blockstate = level.getBlockState(blockpos); +- BlockPos blockpos2 = blockstate.getBlock() instanceof LiquidBlockContainer && this.content == Fluids.WATER ? blockpos : blockpos1; ++ iblockdata = level.getBlockState(blockposition); ++ BlockPos blockposition2 = iblockdata.getBlock() instanceof LiquidBlockContainer && this.content == Fluids.WATER ? blockposition : blockposition1; + +- if (this.emptyContents(player, level, blockpos2, blockhitresult)) { +- this.checkExtraContent(player, level, itemstack, blockpos2); ++ if (this.emptyContents(player, level, blockposition2, movingobjectpositionblock, movingobjectpositionblock.getDirection(), blockposition, itemstack, hand)) { // CraftBukkit ++ this.checkExtraContent(player, level, itemstack, blockposition2); + if (player instanceof ServerPlayer) { +- CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) player, blockpos2, itemstack); ++ CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) player, blockposition2, itemstack); + } + + player.awardStat(Stats.ITEM_USED.get(this)); +@@ -103,40 +121,44 @@ + } + } + +- public static ItemStack getEmptySuccessItem(ItemStack itemstack, Player player) { +- return !player.getAbilities().instabuild ? new ItemStack(Items.BUCKET) : itemstack; ++ public static ItemStack getEmptySuccessItem(ItemStack bucketStack, Player player) { ++ return !player.getAbilities().instabuild ? new ItemStack(Items.BUCKET) : bucketStack; + } + + @Override +- @Override +- public void checkExtraContent(@Nullable Player player, Level level, ItemStack itemstack, BlockPos blockpos) {} ++ public void checkExtraContent(@Nullable Player player, Level level, ItemStack containerStack, BlockPos pos) {} + + @Override +- @Override +- public boolean emptyContents(@Nullable Player player, Level level, BlockPos blockpos, @Nullable BlockHitResult blockhitresult) { +- Fluid fluid = this.content; ++ public boolean emptyContents(@Nullable Player player, Level level, BlockPos pos, @Nullable BlockHitResult result) { ++ // CraftBukkit start ++ return emptyContents(player, level, pos, result, null, null, null, EnumHand.MAIN_HAND); ++ } + +- if (!(fluid instanceof FlowingFluid)) { ++ public boolean emptyContents(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack, EnumHand enumhand) { ++ // CraftBukkit end ++ Fluid fluidtype = this.content; ++ ++ if (!(fluidtype instanceof FlowingFluid)) { + return false; + } else { +- FlowingFluid flowingfluid; +- BlockState blockstate; ++ FlowingFluid fluidtypeflowing; ++ IBlockData iblockdata; + Block block; + boolean flag; +- LiquidBlockContainer liquidblockcontainer; ++ LiquidBlockContainer ifluidcontainer; + boolean flag1; + label70: + { +- flowingfluid = (FlowingFluid) fluid; +- blockstate = level.getBlockState(blockpos); +- block = blockstate.getBlock(); +- flag = blockstate.canBeReplaced(this.content); +- if (!blockstate.isAir() && !flag) { ++ fluidtypeflowing = (FlowingFluid) fluidtype; ++ iblockdata = world.getBlockState(blockposition); ++ block = iblockdata.getBlock(); ++ flag = iblockdata.canBeReplaced(this.content); ++ if (!iblockdata.isAir() && !flag) { + label67: + { + if (block instanceof LiquidBlockContainer) { +- liquidblockcontainer = (LiquidBlockContainer) block; +- if (liquidblockcontainer.canPlaceLiquid(player, level, blockpos, blockstate, this.content)) { ++ ifluidcontainer = (LiquidBlockContainer) block; ++ if (ifluidcontainer.canPlaceLiquid(entityhuman, world, blockposition, iblockdata, this.content)) { + break label67; + } + } +@@ -151,48 +173,58 @@ + + boolean flag2 = flag1; + ++ // CraftBukkit start ++ if (flag2 && entityhuman != null) { ++ PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((ServerLevel) world, entityhuman, blockposition, clicked, enumdirection, itemstack, enumhand); ++ if (event.isCancelled()) { ++ ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-4238: needed when looking through entity ++ ((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 ++ return false; ++ } ++ } ++ // CraftBukkit end + if (!flag2) { +- return blockhitresult != null && this.emptyContents(player, level, blockhitresult.getBlockPos().relative(blockhitresult.getDirection()), (BlockHitResult) null); +- } else if (level.dimensionType().ultraWarm() && this.content.is(FluidTags.WATER)) { +- int i = blockpos.getX(); +- int j = blockpos.getY(); +- int k = blockpos.getZ(); ++ return movingobjectpositionblock != null && this.emptyContents(entityhuman, world, movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()), (BlockHitResult) null, enumdirection, clicked, itemstack, enumhand); // CraftBukkit ++ } else if (world.dimensionType().ultraWarm() && this.content.is(FluidTags.WATER)) { ++ int i = blockposition.getX(); ++ int j = blockposition.getY(); ++ int k = blockposition.getZ(); + +- level.playSound(player, blockpos, SoundEvents.FIRE_EXTINGUISH, SoundSource.BLOCKS, 0.5F, 2.6F + (level.random.nextFloat() - level.random.nextFloat()) * 0.8F); ++ world.playSound(entityhuman, blockposition, SoundEvents.FIRE_EXTINGUISH, SoundSource.BLOCKS, 0.5F, 2.6F + (world.random.nextFloat() - world.random.nextFloat()) * 0.8F); + + for (int l = 0; l < 8; ++l) { +- level.addParticle(ParticleTypes.LARGE_SMOKE, (double) i + Math.random(), (double) j + Math.random(), (double) k + Math.random(), 0.0D, 0.0D, 0.0D); ++ world.addParticle(ParticleTypes.LARGE_SMOKE, (double) i + Math.random(), (double) j + Math.random(), (double) k + Math.random(), 0.0D, 0.0D, 0.0D); + } + + return true; + } else { + if (block instanceof LiquidBlockContainer) { +- liquidblockcontainer = (LiquidBlockContainer) block; ++ ifluidcontainer = (LiquidBlockContainer) block; + if (this.content == Fluids.WATER) { +- liquidblockcontainer.placeLiquid(level, blockpos, blockstate, flowingfluid.getSource(false)); +- this.playEmptySound(player, level, blockpos); ++ ifluidcontainer.placeLiquid(world, blockposition, iblockdata, fluidtypeflowing.getSource(false)); ++ this.playEmptySound(entityhuman, world, blockposition); + return true; + } + } + +- if (!level.isClientSide && flag && !blockstate.liquid()) { +- level.destroyBlock(blockpos, true); ++ if (!world.isClientSide && flag && !iblockdata.liquid()) { ++ world.destroyBlock(blockposition, true); + } + +- if (!level.setBlock(blockpos, this.content.defaultFluidState().createLegacyBlock(), 11) && !blockstate.getFluidState().isSource()) { ++ if (!world.setBlock(blockposition, this.content.defaultFluidState().createLegacyBlock(), 11) && !iblockdata.getFluidState().isSource()) { + return false; + } else { +- this.playEmptySound(player, level, blockpos); ++ this.playEmptySound(entityhuman, world, blockposition); + return true; + } + } + } + } + +- protected void playEmptySound(@Nullable Player player, LevelAccessor levelaccessor, BlockPos blockpos) { +- SoundEvent soundevent = this.content.is(FluidTags.LAVA) ? SoundEvents.BUCKET_EMPTY_LAVA : SoundEvents.BUCKET_EMPTY; ++ protected void playEmptySound(@Nullable Player player, LevelAccessor level, BlockPos pos) { ++ SoundEvent soundeffect = this.content.is(FluidTags.LAVA) ? SoundEvents.BUCKET_EMPTY_LAVA : SoundEvents.BUCKET_EMPTY; + +- levelaccessor.playSound(player, blockpos, soundevent, SoundSource.BLOCKS, 1.0F, 1.0F); +- levelaccessor.gameEvent((Entity) player, GameEvent.FLUID_PLACE, blockpos); ++ level.playSound(player, pos, soundeffect, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.gameEvent((Entity) player, GameEvent.FLUID_PLACE, pos); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/ChorusFruitItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/ChorusFruitItem.java.patch new file mode 100644 index 0000000000..8a0e2affae --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/ChorusFruitItem.java.patch @@ -0,0 +1,86 @@ +--- a/net/minecraft/world/item/ChorusFruitItem.java ++++ b/net/minecraft/world/item/ChorusFruitItem.java +@@ -15,50 +15,58 @@ + + public class ChorusFruitItem extends Item { + +- public ChorusFruitItem(Item.Properties item_properties) { +- super(item_properties); ++ public ChorusFruitItem(Item.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public ItemStack finishUsingItem(ItemStack itemstack, Level level, LivingEntity livingentity) { +- ItemStack itemstack1 = super.finishUsingItem(itemstack, level, livingentity); ++ public ItemStack finishUsingItem(ItemStack stack, Level level, LivingEntity entityLiving) { ++ ItemStack itemstack1 = super.finishUsingItem(stack, level, entityLiving); + + if (!level.isClientSide) { + for (int i = 0; i < 16; ++i) { +- double d0 = livingentity.getX() + (livingentity.getRandom().nextDouble() - 0.5D) * 16.0D; +- double d1 = Mth.clamp(livingentity.getY() + (double) (livingentity.getRandom().nextInt(16) - 8), (double) level.getMinBuildHeight(), (double) (level.getMinBuildHeight() + ((ServerLevel) level).getLogicalHeight() - 1)); +- double d2 = livingentity.getZ() + (livingentity.getRandom().nextDouble() - 0.5D) * 16.0D; ++ double d0 = entityLiving.getX() + (entityLiving.getRandom().nextDouble() - 0.5D) * 16.0D; ++ double d1 = Mth.clamp(entityLiving.getY() + (double) (entityLiving.getRandom().nextInt(16) - 8), (double) level.getMinBuildHeight(), (double) (level.getMinBuildHeight() + ((ServerLevel) level).getLogicalHeight() - 1)); ++ double d2 = entityLiving.getZ() + (entityLiving.getRandom().nextDouble() - 0.5D) * 16.0D; + +- if (livingentity.isPassenger()) { +- livingentity.stopRiding(); ++ if (entityLiving.isPassenger()) { ++ entityLiving.stopRiding(); + } + +- Vec3 vec3 = livingentity.position(); ++ Vec3 vec3d = entityLiving.position(); + +- if (livingentity.randomTeleport(d0, d1, d2, true)) { +- level.gameEvent(GameEvent.TELEPORT, vec3, GameEvent.Context.of((Entity) livingentity)); +- SoundEvent soundevent; +- SoundSource soundsource; ++ // CraftBukkit start - handle canceled status of teleport event ++ java.util.Optional status = entityLiving.randomTeleport(d0, d1, d2, true, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.CHORUS_FRUIT); + +- if (livingentity instanceof Fox) { +- soundevent = SoundEvents.FOX_TELEPORT; +- soundsource = SoundSource.NEUTRAL; ++ if (!status.isPresent()) { ++ // teleport event was canceled, no more tries ++ break; ++ } ++ ++ if (status.get()) { ++ // CraftBukkit end ++ level.gameEvent(GameEvent.TELEPORT, vec3d, GameEvent.Context.of((Entity) entityLiving)); ++ SoundEvent soundeffect; ++ SoundSource soundcategory; ++ ++ if (entityLiving instanceof Fox) { ++ soundeffect = SoundEvents.FOX_TELEPORT; ++ soundcategory = SoundSource.NEUTRAL; + } else { +- soundevent = SoundEvents.CHORUS_FRUIT_TELEPORT; +- soundsource = SoundSource.PLAYERS; ++ soundeffect = SoundEvents.CHORUS_FRUIT_TELEPORT; ++ soundcategory = SoundSource.PLAYERS; + } + +- level.playSound((Player) null, livingentity.getX(), livingentity.getY(), livingentity.getZ(), soundevent, soundsource); +- livingentity.resetFallDistance(); ++ level.playSound((Player) null, entityLiving.getX(), entityLiving.getY(), entityLiving.getZ(), soundeffect, soundcategory); ++ entityLiving.resetFallDistance(); + break; + } + } + +- if (livingentity instanceof Player) { +- Player player = (Player) livingentity; ++ if (entityLiving instanceof Player) { ++ Player entityhuman = (Player) entityLiving; + +- player.getCooldowns().addCooldown(this, 20); ++ entityhuman.getCooldowns().addCooldown(this, 20); + } + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/CrossbowItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/CrossbowItem.java.patch new file mode 100644 index 0000000000..28a9e4be50 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/CrossbowItem.java.patch @@ -0,0 +1,538 @@ +--- a/net/minecraft/world/item/CrossbowItem.java ++++ b/net/minecraft/world/item/CrossbowItem.java +@@ -16,7 +16,7 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; +@@ -32,7 +32,7 @@ + import org.joml.Quaternionf; + import org.joml.Vector3f; + +-public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { ++public class CrossbowItem extends ProjectileWeaponItem implements ItemVanishable { + + private static final String TAG_CHARGED = "Charged"; + private static final String TAG_CHARGED_PROJECTILES = "ChargedProjectiles"; +@@ -45,36 +45,33 @@ + private static final float ARROW_POWER = 3.15F; + private static final float FIREWORK_POWER = 1.6F; + +- public CrossbowItem(Item.Properties item_properties) { +- super(item_properties); ++ public CrossbowItem(Item.Properties properties) { ++ super(properties); + } + + @Override +- @Override + public Predicate getSupportedHeldProjectiles() { + return CrossbowItem.ARROW_OR_FIREWORK; + } + + @Override +- @Override + public Predicate getAllSupportedProjectiles() { + return CrossbowItem.ARROW_ONLY; + } + + @Override +- @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (isCharged(itemstack)) { +- performShooting(level, player, interactionhand, itemstack, getShootingPower(itemstack), 1.0F); ++ performShooting(level, player, hand, itemstack, getShootingPower(itemstack), 1.0F); + setCharged(itemstack, false); + return InteractionResultHolder.consume(itemstack); + } else if (!player.getProjectile(itemstack).isEmpty()) { + if (!isCharged(itemstack)) { + this.startSoundPlayed = false; + this.midLoadSoundPlayed = false; +- player.startUsingItem(interactionhand); ++ player.startUsingItem(hand); + } + + return InteractionResultHolder.consume(itemstack); +@@ -83,30 +80,29 @@ + } + } + +- private static float getShootingPower(ItemStack itemstack) { +- return containsChargedProjectile(itemstack, Items.FIREWORK_ROCKET) ? 1.6F : 3.15F; ++ private static float getShootingPower(ItemStack crossbowStack) { ++ return containsChargedProjectile(crossbowStack, Items.FIREWORK_ROCKET) ? 1.6F : 3.15F; + } + + @Override +- @Override +- public void releaseUsing(ItemStack itemstack, Level level, LivingEntity livingentity, int i) { +- int j = this.getUseDuration(itemstack) - i; +- float f = getPowerForTime(j, itemstack); ++ public void releaseUsing(ItemStack stack, Level level, LivingEntity entityLiving, int timeLeft) { ++ int j = this.getUseDuration(stack) - timeLeft; ++ float f = getPowerForTime(j, stack); + +- if (f >= 1.0F && !isCharged(itemstack) && tryLoadProjectiles(livingentity, itemstack)) { +- setCharged(itemstack, true); +- SoundSource soundsource = livingentity instanceof Player ? SoundSource.PLAYERS : SoundSource.HOSTILE; ++ if (f >= 1.0F && !isCharged(stack) && tryLoadProjectiles(entityLiving, stack)) { ++ setCharged(stack, true); ++ SoundSource soundcategory = entityLiving instanceof Player ? SoundSource.PLAYERS : SoundSource.HOSTILE; + +- level.playSound((Player) null, livingentity.getX(), livingentity.getY(), livingentity.getZ(), SoundEvents.CROSSBOW_LOADING_END, soundsource, 1.0F, 1.0F / (level.getRandom().nextFloat() * 0.5F + 1.0F) + 0.2F); ++ level.playSound((Player) null, entityLiving.getX(), entityLiving.getY(), entityLiving.getZ(), SoundEvents.CROSSBOW_LOADING_END, soundcategory, 1.0F, 1.0F / (level.getRandom().nextFloat() * 0.5F + 1.0F) + 0.2F); + } + + } + +- private static boolean tryLoadProjectiles(LivingEntity livingentity, ItemStack itemstack) { +- int i = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.MULTISHOT, itemstack); ++ private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack crossbowStack) { ++ int i = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.MULTISHOT, crossbowStack); + int j = i == 0 ? 1 : 3; +- boolean flag = livingentity instanceof Player && ((Player) livingentity).getAbilities().instabuild; +- ItemStack itemstack1 = livingentity.getProjectile(itemstack); ++ boolean flag = shooter instanceof Player && ((Player) shooter).getAbilities().instabuild; ++ ItemStack itemstack1 = shooter.getProjectile(crossbowStack); + ItemStack itemstack2 = itemstack1.copy(); + + for (int k = 0; k < j; ++k) { +@@ -119,7 +115,7 @@ + itemstack2 = itemstack1.copy(); + } + +- if (!loadProjectile(livingentity, itemstack, itemstack1, k > 0, flag)) { ++ if (!loadProjectile(shooter, crossbowStack, itemstack1, k > 0, flag)) { + return false; + } + } +@@ -127,68 +123,68 @@ + return true; + } + +- private static boolean loadProjectile(LivingEntity livingentity, ItemStack itemstack, ItemStack itemstack1, boolean flag, boolean flag1) { +- if (itemstack1.isEmpty()) { ++ private static boolean loadProjectile(LivingEntity shooter, ItemStack crossbowStack, ItemStack ammoStack, boolean hasAmmo, boolean isCreative) { ++ if (ammoStack.isEmpty()) { + return false; + } else { +- boolean flag2 = flag1 && itemstack1.getItem() instanceof ArrowItem; ++ boolean flag2 = isCreative && ammoStack.getItem() instanceof ArrowItem; + ItemStack itemstack2; + +- if (!flag2 && !flag1 && !flag) { +- itemstack2 = itemstack1.split(1); +- if (itemstack1.isEmpty() && livingentity instanceof Player) { +- ((Player) livingentity).getInventory().removeItem(itemstack1); ++ if (!flag2 && !isCreative && !hasAmmo) { ++ itemstack2 = ammoStack.split(1); ++ if (ammoStack.isEmpty() && shooter instanceof Player) { ++ ((Player) shooter).getInventory().removeItem(ammoStack); + } + } else { +- itemstack2 = itemstack1.copy(); ++ itemstack2 = ammoStack.copy(); + } + +- addChargedProjectile(itemstack, itemstack2); ++ addChargedProjectile(crossbowStack, itemstack2); + return true; + } + } + +- public static boolean isCharged(ItemStack itemstack) { +- CompoundTag compoundtag = itemstack.getTag(); ++ public static boolean isCharged(ItemStack crossbowStack) { ++ CompoundTag nbttagcompound = crossbowStack.getTag(); + +- return compoundtag != null && compoundtag.getBoolean("Charged"); ++ return nbttagcompound != null && nbttagcompound.getBoolean("Charged"); + } + +- public static void setCharged(ItemStack itemstack, boolean flag) { +- CompoundTag compoundtag = itemstack.getOrCreateTag(); ++ public static void setCharged(ItemStack crossbowStack, boolean isCharged) { ++ CompoundTag nbttagcompound = crossbowStack.getOrCreateTag(); + +- compoundtag.putBoolean("Charged", flag); ++ nbttagcompound.putBoolean("Charged", isCharged); + } + +- private static void addChargedProjectile(ItemStack itemstack, ItemStack itemstack1) { +- CompoundTag compoundtag = itemstack.getOrCreateTag(); +- ListTag listtag; ++ private static void addChargedProjectile(ItemStack crossbowStack, ItemStack ammoStack) { ++ CompoundTag nbttagcompound = crossbowStack.getOrCreateTag(); ++ ListTag nbttaglist; + +- if (compoundtag.contains("ChargedProjectiles", 9)) { +- listtag = compoundtag.getList("ChargedProjectiles", 10); ++ if (nbttagcompound.contains("ChargedProjectiles", 9)) { ++ nbttaglist = nbttagcompound.getList("ChargedProjectiles", 10); + } else { +- listtag = new ListTag(); ++ nbttaglist = new ListTag(); + } + +- CompoundTag compoundtag1 = new CompoundTag(); ++ CompoundTag nbttagcompound1 = new CompoundTag(); + +- itemstack1.save(compoundtag1); +- listtag.add(compoundtag1); +- compoundtag.put("ChargedProjectiles", listtag); ++ ammoStack.save(nbttagcompound1); ++ nbttaglist.add(nbttagcompound1); ++ nbttagcompound.put("ChargedProjectiles", nbttaglist); + } + +- private static List getChargedProjectiles(ItemStack itemstack) { ++ private static List getChargedProjectiles(ItemStack crossbowStack) { + List list = Lists.newArrayList(); +- CompoundTag compoundtag = itemstack.getTag(); ++ CompoundTag nbttagcompound = crossbowStack.getTag(); + +- if (compoundtag != null && compoundtag.contains("ChargedProjectiles", 9)) { +- ListTag listtag = compoundtag.getList("ChargedProjectiles", 10); ++ if (nbttagcompound != null && nbttagcompound.contains("ChargedProjectiles", 9)) { ++ ListTag nbttaglist = nbttagcompound.getList("ChargedProjectiles", 10); + +- if (listtag != null) { +- for (int i = 0; i < listtag.size(); ++i) { +- CompoundTag compoundtag1 = listtag.getCompound(i); ++ if (nbttaglist != null) { ++ for (int i = 0; i < nbttaglist.size(); ++i) { ++ CompoundTag nbttagcompound1 = nbttaglist.getCompound(i); + +- list.add(ItemStack.of(compoundtag1)); ++ list.add(ItemStack.of(nbttagcompound1)); + } + } + } +@@ -196,134 +192,149 @@ + return list; + } + +- private static void clearChargedProjectiles(ItemStack itemstack) { +- CompoundTag compoundtag = itemstack.getTag(); ++ private static void clearChargedProjectiles(ItemStack crossbowStack) { ++ CompoundTag nbttagcompound = crossbowStack.getTag(); + +- if (compoundtag != null) { +- ListTag listtag = compoundtag.getList("ChargedProjectiles", 9); ++ if (nbttagcompound != null) { ++ ListTag nbttaglist = nbttagcompound.getList("ChargedProjectiles", 9); + +- listtag.clear(); +- compoundtag.put("ChargedProjectiles", listtag); ++ nbttaglist.clear(); ++ nbttagcompound.put("ChargedProjectiles", nbttaglist); + } + + } + +- public static boolean containsChargedProjectile(ItemStack itemstack, Item item) { +- return getChargedProjectiles(itemstack).stream().anyMatch((itemstack1) -> { +- return itemstack1.is(item); ++ public static boolean containsChargedProjectile(ItemStack crossbowStack, Item ammoItem) { ++ return getChargedProjectiles(crossbowStack).stream().anyMatch((itemstack1) -> { ++ return itemstack1.is(ammoItem); + }); + } + +- private static void shootProjectile(Level level, LivingEntity livingentity, InteractionHand interactionhand, ItemStack itemstack, ItemStack itemstack1, float f, boolean flag, float f1, float f2, float f3) { ++ private static void shootProjectile(Level level, LivingEntity shooter, EnumHand hand, ItemStack crossbowStack, ItemStack ammoStack, float soundPitch, boolean isCreativeMode, float velocity, float inaccuracy, float projectileAngle) { + if (!level.isClientSide) { +- boolean flag1 = itemstack1.is(Items.FIREWORK_ROCKET); ++ boolean flag1 = ammoStack.is(Items.FIREWORK_ROCKET); + Object object; + + if (flag1) { +- object = new FireworkRocketEntity(level, itemstack1, livingentity, livingentity.getX(), livingentity.getEyeY() - 0.15000000596046448D, livingentity.getZ(), true); ++ object = new FireworkRocketEntity(level, ammoStack, shooter, shooter.getX(), shooter.getEyeY() - 0.15000000596046448D, shooter.getZ(), true); + } else { +- object = getArrow(level, livingentity, itemstack, itemstack1); +- if (flag || f3 != 0.0F) { ++ object = getArrow(level, shooter, crossbowStack, ammoStack); ++ if (isCreativeMode || projectileAngle != 0.0F) { + ((AbstractArrow) object).pickup = AbstractArrow.Pickup.CREATIVE_ONLY; + } + } + +- if (livingentity instanceof CrossbowAttackMob) { +- CrossbowAttackMob crossbowattackmob = (CrossbowAttackMob) livingentity; ++ if (shooter instanceof CrossbowAttackMob) { ++ CrossbowAttackMob icrossbow = (CrossbowAttackMob) shooter; + +- crossbowattackmob.shootCrossbowProjectile(crossbowattackmob.getTarget(), itemstack, (Projectile) object, f3); ++ icrossbow.shootCrossbowProjectile(icrossbow.getTarget(), crossbowStack, (Projectile) object, projectileAngle); + } else { +- Vec3 vec3 = livingentity.getUpVector(1.0F); +- Quaternionf quaternionf = (new Quaternionf()).setAngleAxis((double) (f3 * 0.017453292F), vec3.x, vec3.y, vec3.z); +- Vec3 vec31 = livingentity.getViewVector(1.0F); +- Vector3f vector3f = vec31.toVector3f().rotate(quaternionf); ++ Vec3 vec3d = shooter.getUpVector(1.0F); ++ Quaternionf quaternionf = (new Quaternionf()).setAngleAxis((double) (projectileAngle * 0.017453292F), vec3d.x, vec3d.y, vec3d.z); ++ Vec3 vec3d1 = shooter.getViewVector(1.0F); ++ Vector3f vector3f = vec3d1.toVector3f().rotate(quaternionf); + +- ((Projectile) object).shoot((double) vector3f.x(), (double) vector3f.y(), (double) vector3f.z(), f1, f2); ++ ((Projectile) object).shoot((double) vector3f.x(), (double) vector3f.y(), (double) vector3f.z(), velocity, inaccuracy); + } ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(shooter, crossbowStack, ammoStack, (Entity) object, shooter.getUsedItemHand(), soundPitch, true); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ // CraftBukkit end + +- itemstack.hurtAndBreak(flag1 ? 3 : 1, livingentity, (livingentity1) -> { +- livingentity1.broadcastBreakEvent(interactionhand); ++ crossbowStack.hurtAndBreak(flag1 ? 3 : 1, shooter, (entityliving1) -> { ++ entityliving1.broadcastBreakEvent(hand); + }); +- level.addFreshEntity((Entity) object); +- level.playSound((Player) null, livingentity.getX(), livingentity.getY(), livingentity.getZ(), SoundEvents.CROSSBOW_SHOOT, SoundSource.PLAYERS, 1.0F, f); ++ // CraftBukkit start ++ if (event.getProjectile() == ((Entity) object).getBukkitEntity()) { ++ if (!level.addFreshEntity((Entity) object)) { ++ if (shooter instanceof ServerPlayer) { ++ ((ServerPlayer) shooter).getBukkitEntity().updateInventory(); ++ } ++ return; ++ } ++ } ++ // CraftBukkit end ++ level.playSound((Player) null, shooter.getX(), shooter.getY(), shooter.getZ(), SoundEvents.CROSSBOW_SHOOT, SoundSource.PLAYERS, 1.0F, soundPitch); + } + } + +- private static AbstractArrow getArrow(Level level, LivingEntity livingentity, ItemStack itemstack, ItemStack itemstack1) { +- ArrowItem arrowitem = (ArrowItem) (itemstack1.getItem() instanceof ArrowItem ? itemstack1.getItem() : Items.ARROW); +- AbstractArrow abstractarrow = arrowitem.createArrow(level, itemstack1, livingentity); ++ private static AbstractArrow getArrow(Level level, LivingEntity livingEntity, ItemStack crossbowStack, ItemStack ammoStack) { ++ ArrowItem itemarrow = (ArrowItem) (ammoStack.getItem() instanceof ArrowItem ? ammoStack.getItem() : Items.ARROW); ++ AbstractArrow entityarrow = itemarrow.createArrow(level, ammoStack, livingEntity); + +- if (livingentity instanceof Player) { +- abstractarrow.setCritArrow(true); ++ if (livingEntity instanceof Player) { ++ entityarrow.setCritArrow(true); + } + +- abstractarrow.setSoundEvent(SoundEvents.CROSSBOW_HIT); +- abstractarrow.setShotFromCrossbow(true); +- int i = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.PIERCING, itemstack); ++ entityarrow.setSoundEvent(SoundEvents.CROSSBOW_HIT); ++ entityarrow.setShotFromCrossbow(true); ++ int i = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.PIERCING, crossbowStack); + + if (i > 0) { +- abstractarrow.setPierceLevel((byte) i); ++ entityarrow.setPierceLevel((byte) i); + } + +- return abstractarrow; ++ return entityarrow; + } + +- public static void performShooting(Level level, LivingEntity livingentity, InteractionHand interactionhand, ItemStack itemstack, float f, float f1) { +- List list = getChargedProjectiles(itemstack); +- float[] afloat = getShotPitches(livingentity.getRandom()); ++ public static void performShooting(Level level, LivingEntity shooter, EnumHand usedHand, ItemStack crossbowStack, float velocity, float inaccuracy) { ++ List list = getChargedProjectiles(crossbowStack); ++ float[] afloat = getShotPitches(shooter.getRandom()); + + for (int i = 0; i < list.size(); ++i) { + ItemStack itemstack1 = (ItemStack) list.get(i); +- boolean flag = livingentity instanceof Player && ((Player) livingentity).getAbilities().instabuild; ++ boolean flag = shooter instanceof Player && ((Player) shooter).getAbilities().instabuild; + + if (!itemstack1.isEmpty()) { + if (i == 0) { +- shootProjectile(level, livingentity, interactionhand, itemstack, itemstack1, afloat[i], flag, f, f1, 0.0F); ++ shootProjectile(level, shooter, usedHand, crossbowStack, itemstack1, afloat[i], flag, velocity, inaccuracy, 0.0F); + } else if (i == 1) { +- shootProjectile(level, livingentity, interactionhand, itemstack, itemstack1, afloat[i], flag, f, f1, -10.0F); ++ shootProjectile(level, shooter, usedHand, crossbowStack, itemstack1, afloat[i], flag, velocity, inaccuracy, -10.0F); + } else if (i == 2) { +- shootProjectile(level, livingentity, interactionhand, itemstack, itemstack1, afloat[i], flag, f, f1, 10.0F); ++ shootProjectile(level, shooter, usedHand, crossbowStack, itemstack1, afloat[i], flag, velocity, inaccuracy, 10.0F); + } + } + } + +- onCrossbowShot(level, livingentity, itemstack); ++ onCrossbowShot(level, shooter, crossbowStack); + } + +- private static float[] getShotPitches(RandomSource randomsource) { +- boolean flag = randomsource.nextBoolean(); ++ private static float[] getShotPitches(RandomSource random) { ++ boolean flag = random.nextBoolean(); + +- return new float[]{1.0F, getRandomShotPitch(flag, randomsource), getRandomShotPitch(!flag, randomsource)}; ++ return new float[]{1.0F, getRandomShotPitch(flag, random), getRandomShotPitch(!flag, random)}; + } + +- private static float getRandomShotPitch(boolean flag, RandomSource randomsource) { +- float f = flag ? 0.63F : 0.43F; ++ private static float getRandomShotPitch(boolean isHighPitched, RandomSource random) { ++ float f = isHighPitched ? 0.63F : 0.43F; + +- return 1.0F / (randomsource.nextFloat() * 0.5F + 1.8F) + f; ++ return 1.0F / (random.nextFloat() * 0.5F + 1.8F) + f; + } + +- private static void onCrossbowShot(Level level, LivingEntity livingentity, ItemStack itemstack) { +- if (livingentity instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) livingentity; ++ private static void onCrossbowShot(Level level, LivingEntity shooter, ItemStack crossbowStack) { ++ if (shooter instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) shooter; + + if (!level.isClientSide) { +- CriteriaTriggers.SHOT_CROSSBOW.trigger(serverplayer, itemstack); ++ CriteriaTriggers.SHOT_CROSSBOW.trigger(entityplayer, crossbowStack); + } + +- serverplayer.awardStat(Stats.ITEM_USED.get(itemstack.getItem())); ++ entityplayer.awardStat(Stats.ITEM_USED.get(crossbowStack.getItem())); + } + +- clearChargedProjectiles(itemstack); ++ clearChargedProjectiles(crossbowStack); + } + + @Override +- @Override +- public void onUseTick(Level level, LivingEntity livingentity, ItemStack itemstack, int i) { ++ public void onUseTick(Level level, LivingEntity livingEntity, ItemStack stack, int count) { + if (!level.isClientSide) { +- int j = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.QUICK_CHARGE, itemstack); +- SoundEvent soundevent = this.getStartSound(j); +- SoundEvent soundevent1 = j == 0 ? SoundEvents.CROSSBOW_LOADING_MIDDLE : null; +- float f = (float) (itemstack.getUseDuration() - i) / (float) getChargeDuration(itemstack); ++ int j = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.QUICK_CHARGE, stack); ++ SoundEvent soundeffect = this.getStartSound(j); ++ SoundEvent soundeffect1 = j == 0 ? SoundEvents.CROSSBOW_LOADING_MIDDLE : null; ++ float f = (float) (stack.getUseDuration() - count) / (float) getChargeDuration(stack); + + if (f < 0.2F) { + this.startSoundPlayed = false; +@@ -332,37 +343,35 @@ + + if (f >= 0.2F && !this.startSoundPlayed) { + this.startSoundPlayed = true; +- level.playSound((Player) null, livingentity.getX(), livingentity.getY(), livingentity.getZ(), soundevent, SoundSource.PLAYERS, 0.5F, 1.0F); ++ level.playSound((Player) null, livingEntity.getX(), livingEntity.getY(), livingEntity.getZ(), soundeffect, SoundSource.PLAYERS, 0.5F, 1.0F); + } + +- if (f >= 0.5F && soundevent1 != null && !this.midLoadSoundPlayed) { ++ if (f >= 0.5F && soundeffect1 != null && !this.midLoadSoundPlayed) { + this.midLoadSoundPlayed = true; +- level.playSound((Player) null, livingentity.getX(), livingentity.getY(), livingentity.getZ(), soundevent1, SoundSource.PLAYERS, 0.5F, 1.0F); ++ level.playSound((Player) null, livingEntity.getX(), livingEntity.getY(), livingEntity.getZ(), soundeffect1, SoundSource.PLAYERS, 0.5F, 1.0F); + } + } + + } + + @Override +- @Override +- public int getUseDuration(ItemStack itemstack) { +- return getChargeDuration(itemstack) + 3; ++ public int getUseDuration(ItemStack stack) { ++ return getChargeDuration(stack) + 3; + } + +- public static int getChargeDuration(ItemStack itemstack) { +- int i = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.QUICK_CHARGE, itemstack); ++ public static int getChargeDuration(ItemStack crossbowStack) { ++ int i = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.QUICK_CHARGE, crossbowStack); + + return i == 0 ? 25 : 25 - 5 * i; + } + + @Override +- @Override +- public UseAnim getUseAnimation(ItemStack itemstack) { +- return UseAnim.CROSSBOW; ++ public EnumAnimation getUseAnimation(ItemStack stack) { ++ return EnumAnimation.CROSSBOW; + } + +- private SoundEvent getStartSound(int i) { +- switch (i) { ++ private SoundEvent getStartSound(int enchantmentLevel) { ++ switch (enchantmentLevel) { + case 1: + return SoundEvents.CROSSBOW_QUICK_CHARGE_1; + case 2: +@@ -374,8 +383,8 @@ + } + } + +- private static float getPowerForTime(int i, ItemStack itemstack) { +- float f = (float) i / (float) getChargeDuration(itemstack); ++ private static float getPowerForTime(int useTime, ItemStack crossbowStack) { ++ float f = (float) useTime / (float) getChargeDuration(crossbowStack); + + if (f > 1.0F) { + f = 1.0F; +@@ -385,24 +394,23 @@ + } + + @Override +- @Override +- public void appendHoverText(ItemStack itemstack, @Nullable Level level, List list, TooltipFlag tooltipflag) { +- List list1 = getChargedProjectiles(itemstack); ++ public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { ++ List list1 = getChargedProjectiles(stack); + +- if (isCharged(itemstack) && !list1.isEmpty()) { ++ if (isCharged(stack) && !list1.isEmpty()) { + ItemStack itemstack1 = (ItemStack) list1.get(0); + +- list.add(Component.translatable("item.minecraft.crossbow.projectile").append(CommonComponents.SPACE).append(itemstack1.getDisplayName())); +- if (tooltipflag.isAdvanced() && itemstack1.is(Items.FIREWORK_ROCKET)) { ++ tooltip.add(Component.translatable("item.minecraft.crossbow.projectile").append(CommonComponents.SPACE).append(itemstack1.getDisplayName())); ++ if (flag.isAdvanced() && itemstack1.is(Items.FIREWORK_ROCKET)) { + List list2 = Lists.newArrayList(); + +- Items.FIREWORK_ROCKET.appendHoverText(itemstack1, level, list2, tooltipflag); ++ Items.FIREWORK_ROCKET.appendHoverText(itemstack1, level, list2, flag); + if (!list2.isEmpty()) { + for (int i = 0; i < list2.size(); ++i) { + list2.set(i, Component.literal(" ").append((Component) list2.get(i)).withStyle(ChatFormatting.GRAY)); + } + +- list.addAll(list2); ++ tooltip.addAll(list2); + } + } + +@@ -410,13 +418,11 @@ + } + + @Override +- @Override +- public boolean useOnRelease(ItemStack itemstack) { +- return itemstack.is((Item) this); ++ public boolean useOnRelease(ItemStack stack) { ++ return stack.is((Item) this); + } + + @Override +- @Override + public int getDefaultProjectileRange() { + return 8; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/DebugStickItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/DebugStickItem.java.patch new file mode 100644 index 0000000000..665bad6233 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/DebugStickItem.java.patch @@ -0,0 +1,155 @@ +--- a/net/minecraft/world/item/DebugStickItem.java ++++ b/net/minecraft/world/item/DebugStickItem.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.world.item; + + import java.util.Collection; +@@ -8,88 +9,85 @@ + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; + import net.minecraft.server.level.ServerPlayer; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.Block; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.Property; + + public class DebugStickItem extends Item { + +- public DebugStickItem(Item.Properties item_properties) { +- super(item_properties); ++ public DebugStickItem(Item.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public boolean isFoil(ItemStack itemstack) { ++ public boolean isFoil(ItemStack stack) { + return true; + } + + @Override +- @Override +- public boolean canAttackBlock(BlockState blockstate, Level level, BlockPos blockpos, Player player) { ++ public boolean canAttackBlock(IBlockData state, Level level, BlockPos pos, Player player) { + if (!level.isClientSide) { +- this.handleInteraction(player, blockstate, level, blockpos, false, player.getItemInHand(InteractionHand.MAIN_HAND)); ++ this.handleInteraction(player, state, level, pos, false, player.getItemInHand(EnumHand.MAIN_HAND)); + } + + return false; + } + + @Override +- @Override +- public InteractionResult useOn(UseOnContext useoncontext) { +- Player player = useoncontext.getPlayer(); +- Level level = useoncontext.getLevel(); ++ public InteractionResult useOn(UseOnContext context) { ++ Player entityhuman = context.getPlayer(); ++ Level world = context.getLevel(); + +- if (!level.isClientSide && player != null) { +- BlockPos blockpos = useoncontext.getClickedPos(); ++ if (!world.isClientSide && entityhuman != null) { ++ BlockPos blockposition = context.getClickedPos(); + +- if (!this.handleInteraction(player, level.getBlockState(blockpos), level, blockpos, true, useoncontext.getItemInHand())) { ++ if (!this.handleInteraction(entityhuman, world.getBlockState(blockposition), world, blockposition, true, context.getItemInHand())) { + return InteractionResult.FAIL; + } + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } + +- private boolean handleInteraction(Player player, BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos, boolean flag, ItemStack itemstack) { ++ public boolean handleInteraction(Player player, IBlockData stateClicked, LevelAccessor accessor, BlockPos pos, boolean shouldCycleState, ItemStack debugStack) { + if (!player.canUseGameMasterBlocks()) { + return false; + } else { +- Block block = blockstate.getBlock(); +- StateDefinition statedefinition = block.getStateDefinition(); +- Collection> collection = statedefinition.getProperties(); ++ Block block = stateClicked.getBlock(); ++ StateDefinition blockstatelist = block.getStateDefinition(); ++ Collection> collection = blockstatelist.getProperties(); + String s = BuiltInRegistries.BLOCK.getKey(block).toString(); + + if (collection.isEmpty()) { + message(player, Component.translatable(this.getDescriptionId() + ".empty", s)); + return false; + } else { +- CompoundTag compoundtag = itemstack.getOrCreateTagElement("DebugProperty"); +- String s1 = compoundtag.getString(s); +- Property property = statedefinition.getProperty(s1); ++ CompoundTag nbttagcompound = debugStack.getOrCreateTagElement("DebugProperty"); ++ String s1 = nbttagcompound.getString(s); ++ Property iblockstate = blockstatelist.getProperty(s1); + +- if (flag) { +- if (property == null) { +- property = (Property) collection.iterator().next(); ++ if (shouldCycleState) { ++ if (iblockstate == null) { ++ iblockstate = (Property) collection.iterator().next(); + } + +- BlockState blockstate1 = cycleState(blockstate, property, player.isSecondaryUseActive()); ++ IBlockData iblockdata1 = cycleState(stateClicked, iblockstate, player.isSecondaryUseActive()); + +- levelaccessor.setBlock(blockpos, blockstate1, 18); +- message(player, Component.translatable(this.getDescriptionId() + ".update", property.getName(), getNameHelper(blockstate1, property))); ++ accessor.setBlock(pos, iblockdata1, 18); ++ message(player, Component.translatable(this.getDescriptionId() + ".update", iblockstate.getName(), getNameHelper(iblockdata1, iblockstate))); + } else { +- property = (Property) getRelative(collection, property, player.isSecondaryUseActive()); +- String s2 = property.getName(); ++ iblockstate = (Property) getRelative(collection, iblockstate, player.isSecondaryUseActive()); ++ String s2 = iblockstate.getName(); + +- compoundtag.putString(s, s2); +- message(player, Component.translatable(this.getDescriptionId() + ".select", s2, getNameHelper(blockstate, property))); ++ nbttagcompound.putString(s, s2); ++ message(player, Component.translatable(this.getDescriptionId() + ".select", s2, getNameHelper(stateClicked, iblockstate))); + } + + return true; +@@ -97,19 +95,19 @@ + } + } + +- private static > BlockState cycleState(BlockState blockstate, Property property, boolean flag) { +- return (BlockState) blockstate.setValue(property, (Comparable) getRelative(property.getPossibleValues(), blockstate.getValue(property), flag)); ++ private static > IBlockData cycleState(IBlockData state, Property property, boolean backwards) { ++ return (IBlockData) state.setValue(property, getRelative(property.getPossibleValues(), state.getValue(property), backwards)); // CraftBukkit - decompile error + } + +- private static T getRelative(Iterable iterable, @Nullable T t0, boolean flag) { +- return flag ? Util.findPreviousInIterable(iterable, t0) : Util.findNextInIterable(iterable, t0); ++ private static T getRelative(Iterable allowedValues, @Nullable T currentValue, boolean backwards) { ++ return backwards ? Util.findPreviousInIterable(allowedValues, currentValue) : Util.findNextInIterable(allowedValues, currentValue); + } + +- private static void message(Player player, Component component) { +- ((ServerPlayer) player).sendSystemMessage(component, true); ++ private static void message(Player player, Component messageComponent) { ++ ((ServerPlayer) player).sendSystemMessage(messageComponent, true); + } + +- private static > String getNameHelper(BlockState blockstate, Property property) { +- return property.getName(blockstate.getValue(property)); ++ private static > String getNameHelper(IBlockData state, Property property) { ++ return property.getName(state.getValue(property)); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/DyeItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/DyeItem.java.patch new file mode 100644 index 0000000000..ebdfdb2a0c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/DyeItem.java.patch @@ -0,0 +1,87 @@ +--- a/net/minecraft/world/item/DyeItem.java ++++ b/net/minecraft/world/item/DyeItem.java +@@ -4,7 +4,7 @@ + import java.util.Map; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; +@@ -12,29 +12,39 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.SignBlockEntity; ++import org.bukkit.event.entity.SheepDyeWoolEvent; // CraftBukkit + + public class DyeItem extends Item implements SignApplicator { + + private static final Map ITEM_BY_COLOR = Maps.newEnumMap(DyeColor.class); + private final DyeColor dyeColor; + +- public DyeItem(DyeColor dyecolor, Item.Properties item_properties) { +- super(item_properties); +- this.dyeColor = dyecolor; +- DyeItem.ITEM_BY_COLOR.put(dyecolor, this); ++ public DyeItem(DyeColor dyeColor, Item.Properties properties) { ++ super(properties); ++ this.dyeColor = dyeColor; ++ DyeItem.ITEM_BY_COLOR.put(dyeColor, this); + } + + @Override +- @Override +- public InteractionResult interactLivingEntity(ItemStack itemstack, Player player, LivingEntity livingentity, InteractionHand interactionhand) { +- if (livingentity instanceof Sheep) { +- Sheep sheep = (Sheep) livingentity; ++ public InteractionResult interactLivingEntity(ItemStack stack, Player player, LivingEntity target, EnumHand hand) { ++ if (target instanceof Sheep) { ++ Sheep entitysheep = (Sheep) target; + +- if (sheep.isAlive() && !sheep.isSheared() && sheep.getColor() != this.dyeColor) { +- sheep.level().playSound(player, (Entity) sheep, SoundEvents.DYE_USE, SoundSource.PLAYERS, 1.0F, 1.0F); ++ if (entitysheep.isAlive() && !entitysheep.isSheared() && entitysheep.getColor() != this.dyeColor) { ++ entitysheep.level().playSound(player, (Entity) entitysheep, SoundEvents.DYE_USE, SoundSource.PLAYERS, 1.0F, 1.0F); + if (!player.level().isClientSide) { +- sheep.setColor(this.dyeColor); +- itemstack.shrink(1); ++ // CraftBukkit start ++ byte bColor = (byte) this.dyeColor.getId(); ++ SheepDyeWoolEvent event = new SheepDyeWoolEvent((org.bukkit.entity.Sheep) entitysheep.getBukkitEntity(), org.bukkit.DyeColor.getByWoolData(bColor), (org.bukkit.entity.Player) player.getBukkitEntity()); ++ entitysheep.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return InteractionResult.PASS; ++ } ++ ++ entitysheep.setColor(DyeColor.byId((byte) event.getColor().getWoolData())); ++ // CraftBukkit end ++ stack.shrink(1); + } + + return InteractionResult.sidedSuccess(player.level().isClientSide); +@@ -48,17 +58,16 @@ + return this.dyeColor; + } + +- public static DyeItem byColor(DyeColor dyecolor) { +- return (DyeItem) DyeItem.ITEM_BY_COLOR.get(dyecolor); ++ public static DyeItem byColor(DyeColor color) { ++ return (DyeItem) DyeItem.ITEM_BY_COLOR.get(color); + } + + @Override +- @Override +- public boolean tryApplyToSign(Level level, SignBlockEntity signblockentity, boolean flag, Player player) { +- if (signblockentity.updateText((signtext) -> { ++ public boolean tryApplyToSign(Level level, SignBlockEntity sign, boolean isFront, Player player) { ++ if (sign.updateText((signtext) -> { + return signtext.setColor(this.getDyeColor()); +- }, flag)) { +- level.playSound((Player) null, signblockentity.getBlockPos(), SoundEvents.DYE_USE, SoundSource.BLOCKS, 1.0F, 1.0F); ++ }, isFront)) { ++ level.playSound((Player) null, sign.getBlockPos(), SoundEvents.DYE_USE, SoundSource.BLOCKS, 1.0F, 1.0F); + return true; + } else { + return false; diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/EggItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/EggItem.java.patch new file mode 100644 index 0000000000..6678bf5c4e --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/EggItem.java.patch @@ -0,0 +1,52 @@ +--- a/net/minecraft/world/item/EggItem.java ++++ b/net/minecraft/world/item/EggItem.java +@@ -3,7 +3,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.ThrownEgg; +@@ -11,23 +11,30 @@ + + public class EggItem extends Item { + +- public EggItem(Item.Properties item_properties) { +- super(item_properties); ++ public EggItem(Item.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + +- level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.EGG_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); ++ // world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); // CraftBukkit - moved down + if (!level.isClientSide) { +- ThrownEgg thrownegg = new ThrownEgg(level, player); ++ ThrownEgg entityegg = new ThrownEgg(level, player); + +- thrownegg.setItem(itemstack); +- thrownegg.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 1.5F, 1.0F); +- level.addFreshEntity(thrownegg); ++ entityegg.setItem(itemstack); ++ entityegg.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 1.5F, 1.0F); ++ // CraftBukkit start ++ if (!level.addFreshEntity(entityegg)) { ++ if (player instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().updateInventory(); ++ } ++ return InteractionResultHolder.fail(itemstack); ++ } ++ // CraftBukkit end + } ++ level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.EGG_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); + + player.awardStat(Stats.ITEM_USED.get(this)); + if (!player.getAbilities().instabuild) { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/EndCrystalItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/EndCrystalItem.java.patch new file mode 100644 index 0000000000..3253e9f5c4 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/EndCrystalItem.java.patch @@ -0,0 +1,96 @@ +--- a/net/minecraft/world/item/EndCrystalItem.java ++++ b/net/minecraft/world/item/EndCrystalItem.java +@@ -9,63 +9,66 @@ + import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.dimension.end.EndDragonFight; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; + + public class EndCrystalItem extends Item { + +- public EndCrystalItem(Item.Properties item_properties) { +- super(item_properties); ++ public EndCrystalItem(Item.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public InteractionResult useOn(UseOnContext useoncontext) { +- Level level = useoncontext.getLevel(); +- BlockPos blockpos = useoncontext.getClickedPos(); +- BlockState blockstate = level.getBlockState(blockpos); ++ public InteractionResult useOn(UseOnContext context) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ IBlockData iblockdata = world.getBlockState(blockposition); + +- if (!blockstate.is(Blocks.OBSIDIAN) && !blockstate.is(Blocks.BEDROCK)) { ++ if (!iblockdata.is(Blocks.OBSIDIAN) && !iblockdata.is(Blocks.BEDROCK)) { + return InteractionResult.FAIL; + } else { +- BlockPos blockpos1 = blockpos.above(); ++ BlockPos blockposition1 = blockposition.above(); + +- if (!level.isEmptyBlock(blockpos1)) { ++ if (!world.isEmptyBlock(blockposition1)) { + return InteractionResult.FAIL; + } else { +- double d0 = (double) blockpos1.getX(); +- double d1 = (double) blockpos1.getY(); +- double d2 = (double) blockpos1.getZ(); +- List list = level.getEntities((Entity) null, new AABB(d0, d1, d2, d0 + 1.0D, d1 + 2.0D, d2 + 1.0D)); ++ double d0 = (double) blockposition1.getX(); ++ double d1 = (double) blockposition1.getY(); ++ double d2 = (double) blockposition1.getZ(); ++ List list = world.getEntities((Entity) null, new AABB(d0, d1, d2, d0 + 1.0D, d1 + 2.0D, d2 + 1.0D)); + + if (!list.isEmpty()) { + return InteractionResult.FAIL; + } else { +- if (level instanceof ServerLevel) { +- EndCrystal endcrystal = new EndCrystal(level, d0 + 0.5D, d1, d2 + 0.5D); ++ if (world instanceof ServerLevel) { ++ EndCrystal entityendercrystal = new EndCrystal(world, d0 + 0.5D, d1, d2 + 0.5D); + +- endcrystal.setShowBottom(false); +- level.addFreshEntity(endcrystal); +- level.gameEvent((Entity) useoncontext.getPlayer(), GameEvent.ENTITY_PLACE, blockpos1); +- EndDragonFight enddragonfight = ((ServerLevel) level).getDragonFight(); ++ entityendercrystal.setShowBottom(false); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(context, entityendercrystal).isCancelled()) { ++ return InteractionResult.FAIL; ++ } ++ // CraftBukkit end ++ world.addFreshEntity(entityendercrystal); ++ world.gameEvent((Entity) context.getPlayer(), GameEvent.ENTITY_PLACE, blockposition1); ++ EndDragonFight enderdragonbattle = ((ServerLevel) world).getDragonFight(); + +- if (enddragonfight != null) { +- enddragonfight.tryRespawn(); ++ if (enderdragonbattle != null) { ++ enderdragonbattle.tryRespawn(); + } + } + +- useoncontext.getItemInHand().shrink(1); +- return InteractionResult.sidedSuccess(level.isClientSide); ++ context.getItemInHand().shrink(1); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } + } + } + } + + @Override +- @Override +- public boolean isFoil(ItemStack itemstack) { ++ public boolean isFoil(ItemStack stack) { + return true; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/EnderEyeItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/EnderEyeItem.java.patch new file mode 100644 index 0000000000..43ff750020 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/EnderEyeItem.java.patch @@ -0,0 +1,136 @@ +--- a/net/minecraft/world/item/EnderEyeItem.java ++++ b/net/minecraft/world/item/EnderEyeItem.java +@@ -8,7 +8,7 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; + import net.minecraft.tags.StructureTags; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.Entity; +@@ -20,7 +20,7 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.EndPortalFrameBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.pattern.BlockPattern; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.BlockHitResult; +@@ -28,40 +28,39 @@ + + public class EnderEyeItem extends Item { + +- public EnderEyeItem(Item.Properties item_properties) { +- super(item_properties); ++ public EnderEyeItem(Item.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public InteractionResult useOn(UseOnContext useoncontext) { +- Level level = useoncontext.getLevel(); +- BlockPos blockpos = useoncontext.getClickedPos(); +- BlockState blockstate = level.getBlockState(blockpos); ++ public InteractionResult useOn(UseOnContext context) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ IBlockData iblockdata = world.getBlockState(blockposition); + +- if (blockstate.is(Blocks.END_PORTAL_FRAME) && !(Boolean) blockstate.getValue(EndPortalFrameBlock.HAS_EYE)) { +- if (level.isClientSide) { ++ if (iblockdata.is(Blocks.END_PORTAL_FRAME) && !(Boolean) iblockdata.getValue(EndPortalFrameBlock.HAS_EYE)) { ++ if (world.isClientSide) { + return InteractionResult.SUCCESS; + } else { +- BlockState blockstate1 = (BlockState) blockstate.setValue(EndPortalFrameBlock.HAS_EYE, true); ++ IBlockData iblockdata1 = (IBlockData) iblockdata.setValue(EndPortalFrameBlock.HAS_EYE, true); + +- Block.pushEntitiesUp(blockstate, blockstate1, level, blockpos); +- level.setBlock(blockpos, blockstate1, 2); +- level.updateNeighbourForOutputSignal(blockpos, Blocks.END_PORTAL_FRAME); +- useoncontext.getItemInHand().shrink(1); +- level.levelEvent(1503, blockpos, 0); +- BlockPattern.BlockPatternMatch blockpattern_blockpatternmatch = EndPortalFrameBlock.getOrCreatePortalShape().find(level, blockpos); ++ Block.pushEntitiesUp(iblockdata, iblockdata1, world, blockposition); ++ world.setBlock(blockposition, iblockdata1, 2); ++ world.updateNeighbourForOutputSignal(blockposition, Blocks.END_PORTAL_FRAME); ++ context.getItemInHand().shrink(1); ++ world.levelEvent(1503, blockposition, 0); ++ BlockPattern.BlockPatternMatch shapedetector_shapedetectorcollection = EndPortalFrameBlock.getOrCreatePortalShape().find(world, blockposition); + +- if (blockpattern_blockpatternmatch != null) { +- BlockPos blockpos1 = blockpattern_blockpatternmatch.getFrontTopLeft().offset(-3, 0, -3); ++ if (shapedetector_shapedetectorcollection != null) { ++ BlockPos blockposition1 = shapedetector_shapedetectorcollection.getFrontTopLeft().offset(-3, 0, -3); + + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { +- level.setBlock(blockpos1.offset(i, 0, j), Blocks.END_PORTAL.defaultBlockState(), 2); ++ world.setBlock(blockposition1.offset(i, 0, j), Blocks.END_PORTAL.defaultBlockState(), 2); + } + } + +- level.globalLevelEvent(1038, blockpos1.offset(1, 0, 1), 0); ++ world.globalLevelEvent(1038, blockposition1.offset(1, 0, 1), 0); + } + + return InteractionResult.CONSUME; +@@ -72,28 +71,31 @@ + } + + @Override +- @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); +- BlockHitResult blockhitresult = getPlayerPOVHitResult(level, player, ClipContext.Fluid.NONE); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ BlockHitResult movingobjectpositionblock = getPlayerPOVHitResult(level, player, ClipContext.Fluid.NONE); + +- if (blockhitresult.getType() == HitResult.Type.BLOCK && level.getBlockState(blockhitresult.getBlockPos()).is(Blocks.END_PORTAL_FRAME)) { ++ if (movingobjectpositionblock.getType() == HitResult.EnumMovingObjectType.BLOCK && level.getBlockState(movingobjectpositionblock.getBlockPos()).is(Blocks.END_PORTAL_FRAME)) { + return InteractionResultHolder.pass(itemstack); + } else { +- player.startUsingItem(interactionhand); ++ player.startUsingItem(hand); + if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; +- BlockPos blockpos = serverlevel.findNearestMapStructure(StructureTags.EYE_OF_ENDER_LOCATED, player.blockPosition(), 100, false); ++ ServerLevel worldserver = (ServerLevel) level; ++ BlockPos blockposition = worldserver.findNearestMapStructure(StructureTags.EYE_OF_ENDER_LOCATED, player.blockPosition(), 100, false); + +- if (blockpos != null) { +- EyeOfEnder eyeofender = new EyeOfEnder(level, player.getX(), player.getY(0.5D), player.getZ()); ++ if (blockposition != null) { ++ EyeOfEnder entityendersignal = new EyeOfEnder(level, player.getX(), player.getY(0.5D), player.getZ()); + +- eyeofender.setItem(itemstack); +- eyeofender.signalTo(blockpos); +- level.gameEvent(GameEvent.PROJECTILE_SHOOT, eyeofender.position(), GameEvent.Context.of((Entity) player)); +- level.addFreshEntity(eyeofender); ++ entityendersignal.setItem(itemstack); ++ entityendersignal.signalTo(blockposition); ++ level.gameEvent(GameEvent.PROJECTILE_SHOOT, entityendersignal.position(), GameEvent.Context.of((Entity) player)); ++ // CraftBukkit start ++ if (!level.addFreshEntity(entityendersignal)) { ++ return new InteractionResultHolder(InteractionResult.FAIL, itemstack); ++ } ++ // CraftBukkit end + if (player instanceof ServerPlayer) { +- CriteriaTriggers.USED_ENDER_EYE.trigger((ServerPlayer) player, blockpos); ++ CriteriaTriggers.USED_ENDER_EYE.trigger((ServerPlayer) player, blockposition); + } + + level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.ENDER_EYE_LAUNCH, SoundSource.NEUTRAL, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); +@@ -103,7 +105,7 @@ + } + + player.awardStat(Stats.ITEM_USED.get(this)); +- player.swing(interactionhand, true); ++ player.swing(hand, true); + return InteractionResultHolder.success(itemstack); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/EnderpearlItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/EnderpearlItem.java.patch new file mode 100644 index 0000000000..2a4701dc4e --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/EnderpearlItem.java.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/item/EnderpearlItem.java ++++ b/net/minecraft/world/item/EnderpearlItem.java +@@ -3,7 +3,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.ThrownEnderpearl; +@@ -11,25 +11,32 @@ + + public class EnderpearlItem extends Item { + +- public EnderpearlItem(Item.Properties item_properties) { +- super(item_properties); ++ public EnderpearlItem(Item.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + +- level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); +- player.getCooldowns().addCooldown(this, 20); ++ // CraftBukkit start - change order + if (!level.isClientSide) { +- ThrownEnderpearl thrownenderpearl = new ThrownEnderpearl(level, player); ++ ThrownEnderpearl entityenderpearl = new ThrownEnderpearl(level, player); + +- thrownenderpearl.setItem(itemstack); +- thrownenderpearl.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 1.5F, 1.0F); +- level.addFreshEntity(thrownenderpearl); ++ entityenderpearl.setItem(itemstack); ++ entityenderpearl.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 1.5F, 1.0F); ++ if (!level.addFreshEntity(entityenderpearl)) { ++ if (player instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().updateInventory(); ++ } ++ return InteractionResultHolder.fail(itemstack); ++ } + } + ++ level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); ++ player.getCooldowns().addCooldown(this, 20); ++ // CraftBukkit end ++ + player.awardStat(Stats.ITEM_USED.get(this)); + if (!player.getAbilities().instabuild) { + itemstack.shrink(1); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/FireChargeItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/FireChargeItem.java.patch new file mode 100644 index 0000000000..fffc0310e0 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/FireChargeItem.java.patch @@ -0,0 +1,89 @@ +--- a/net/minecraft/world/item/FireChargeItem.java ++++ b/net/minecraft/world/item/FireChargeItem.java +@@ -13,50 +13,65 @@ + import net.minecraft.world.level.block.CampfireBlock; + import net.minecraft.world.level.block.CandleBlock; + import net.minecraft.world.level.block.CandleCakeBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.gameevent.GameEvent; + + public class FireChargeItem extends Item { + +- public FireChargeItem(Item.Properties item_properties) { +- super(item_properties); ++ public FireChargeItem(Item.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public InteractionResult useOn(UseOnContext useoncontext) { +- Level level = useoncontext.getLevel(); +- BlockPos blockpos = useoncontext.getClickedPos(); +- BlockState blockstate = level.getBlockState(blockpos); ++ public InteractionResult useOn(UseOnContext context) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ IBlockData iblockdata = world.getBlockState(blockposition); + boolean flag = false; + +- if (!CampfireBlock.canLight(blockstate) && !CandleBlock.canLight(blockstate) && !CandleCakeBlock.canLight(blockstate)) { +- blockpos = blockpos.relative(useoncontext.getClickedFace()); +- if (BaseFireBlock.canBePlacedAt(level, blockpos, useoncontext.getHorizontalDirection())) { +- this.playSound(level, blockpos); +- level.setBlockAndUpdate(blockpos, BaseFireBlock.getState(level, blockpos)); +- level.gameEvent((Entity) useoncontext.getPlayer(), GameEvent.BLOCK_PLACE, blockpos); ++ if (!CampfireBlock.canLight(iblockdata) && !CandleBlock.canLight(iblockdata) && !CandleCakeBlock.canLight(iblockdata)) { ++ blockposition = blockposition.relative(context.getClickedFace()); ++ if (BaseFireBlock.canBePlacedAt(world, blockposition, context.getHorizontalDirection())) { ++ // CraftBukkit start - fire BlockIgniteEvent ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FIREBALL, context.getPlayer()).isCancelled()) { ++ if (!context.getPlayer().getAbilities().instabuild) { ++ context.getItemInHand().shrink(1); ++ } ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end ++ this.playSound(world, blockposition); ++ world.setBlockAndUpdate(blockposition, BaseFireBlock.getState(world, blockposition)); ++ world.gameEvent((Entity) context.getPlayer(), GameEvent.BLOCK_PLACE, blockposition); + flag = true; + } + } else { +- this.playSound(level, blockpos); +- level.setBlockAndUpdate(blockpos, (BlockState) blockstate.setValue(BlockStateProperties.LIT, true)); +- level.gameEvent((Entity) useoncontext.getPlayer(), GameEvent.BLOCK_CHANGE, blockpos); ++ // CraftBukkit start - fire BlockIgniteEvent ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FIREBALL, context.getPlayer()).isCancelled()) { ++ if (!context.getPlayer().getAbilities().instabuild) { ++ context.getItemInHand().shrink(1); ++ } ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end ++ this.playSound(world, blockposition); ++ world.setBlockAndUpdate(blockposition, (IBlockData) iblockdata.setValue(BlockStateProperties.LIT, true)); ++ world.gameEvent((Entity) context.getPlayer(), GameEvent.BLOCK_CHANGE, blockposition); + flag = true; + } + + if (flag) { +- useoncontext.getItemInHand().shrink(1); +- return InteractionResult.sidedSuccess(level.isClientSide); ++ context.getItemInHand().shrink(1); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } else { + return InteractionResult.FAIL; + } + } + +- private void playSound(Level level, BlockPos blockpos) { ++ private void playSound(Level level, BlockPos pos) { + RandomSource randomsource = level.getRandom(); + +- level.playSound((Player) null, blockpos, SoundEvents.FIRECHARGE_USE, SoundSource.BLOCKS, 1.0F, (randomsource.nextFloat() - randomsource.nextFloat()) * 0.2F + 1.0F); ++ level.playSound((Player) null, pos, SoundEvents.FIRECHARGE_USE, SoundSource.BLOCKS, 1.0F, (randomsource.nextFloat() - randomsource.nextFloat()) * 0.2F + 1.0F); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/FishingRodItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/FishingRodItem.java.patch new file mode 100644 index 0000000000..f8e99a2b8f --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/FishingRodItem.java.patch @@ -0,0 +1,80 @@ +--- a/net/minecraft/world/item/FishingRodItem.java ++++ b/net/minecraft/world/item/FishingRodItem.java +@@ -3,7 +3,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.FishingHook; +@@ -11,35 +11,50 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + +-public class FishingRodItem extends Item implements Vanishable { ++// CraftBukkit start ++import org.bukkit.event.player.PlayerFishEvent; ++import org.bukkit.craftbukkit.CraftEquipmentSlot; ++// CraftBukkit end + +- public FishingRodItem(Item.Properties item_properties) { +- super(item_properties); ++public class FishingRodItem extends Item implements ItemVanishable { ++ ++ public FishingRodItem(Item.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + int i; + + if (player.fishing != null) { + if (!level.isClientSide) { + i = player.fishing.retrieve(itemstack); +- itemstack.hurtAndBreak(i, player, (player1) -> { +- player1.broadcastBreakEvent(interactionhand); ++ itemstack.hurtAndBreak(i, player, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(hand); + }); + } + + level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.FISHING_BOBBER_RETRIEVE, SoundSource.NEUTRAL, 1.0F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); + player.gameEvent(GameEvent.ITEM_INTERACT_FINISH); + } else { +- level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.FISHING_BOBBER_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); ++ // world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.FISHING_BOBBER_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); + if (!level.isClientSide) { + i = EnchantmentHelper.getFishingSpeedBonus(itemstack); + int j = EnchantmentHelper.getFishingLuckBonus(itemstack); + +- level.addFreshEntity(new FishingHook(player, level, j, i)); ++ // CraftBukkit start ++ FishingHook entityfishinghook = new FishingHook(player, level, j, i); ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((org.bukkit.entity.Player) player.getBukkitEntity(), null, (org.bukkit.entity.FishHook) entityfishinghook.getBukkitEntity(), CraftEquipmentSlot.getHand(hand), PlayerFishEvent.State.FISHING); ++ level.getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ player.fishing = null; ++ return InteractionResultHolder.pass(itemstack); ++ } ++ level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.FISHING_BOBBER_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); ++ level.addFreshEntity(entityfishinghook); ++ // CraftBukkit end + } + + player.awardStat(Stats.ITEM_USED.get(this)); +@@ -50,7 +65,6 @@ + } + + @Override +- @Override + public int getEnchantmentValue() { + return 1; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/FlintAndSteelItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/FlintAndSteelItem.java.patch new file mode 100644 index 0000000000..9cc0efceef --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/FlintAndSteelItem.java.patch @@ -0,0 +1,104 @@ +--- a/net/minecraft/world/item/FlintAndSteelItem.java ++++ b/net/minecraft/world/item/FlintAndSteelItem.java +@@ -14,57 +14,72 @@ + import net.minecraft.world.level.block.CampfireBlock; + import net.minecraft.world.level.block.CandleBlock; + import net.minecraft.world.level.block.CandleCakeBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.gameevent.GameEvent; + + public class FlintAndSteelItem extends Item { + +- public FlintAndSteelItem(Item.Properties item_properties) { +- super(item_properties); ++ public FlintAndSteelItem(Item.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public InteractionResult useOn(UseOnContext useoncontext) { +- Player player = useoncontext.getPlayer(); +- Level level = useoncontext.getLevel(); +- BlockPos blockpos = useoncontext.getClickedPos(); +- BlockState blockstate = level.getBlockState(blockpos); ++ public InteractionResult useOn(UseOnContext context) { ++ Player entityhuman = context.getPlayer(); ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ IBlockData iblockdata = world.getBlockState(blockposition); + +- if (!CampfireBlock.canLight(blockstate) && !CandleBlock.canLight(blockstate) && !CandleCakeBlock.canLight(blockstate)) { +- BlockPos blockpos1 = blockpos.relative(useoncontext.getClickedFace()); ++ if (!CampfireBlock.canLight(iblockdata) && !CandleBlock.canLight(iblockdata) && !CandleCakeBlock.canLight(iblockdata)) { ++ BlockPos blockposition1 = blockposition.relative(context.getClickedFace()); + +- if (BaseFireBlock.canBePlacedAt(level, blockpos1, useoncontext.getHorizontalDirection())) { +- level.playSound(player, blockpos1, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.4F + 0.8F); +- BlockState blockstate1 = BaseFireBlock.getState(level, blockpos1); ++ if (BaseFireBlock.canBePlacedAt(world, blockposition1, context.getHorizontalDirection())) { ++ // CraftBukkit start - Store the clicked block ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition1, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL, entityhuman).isCancelled()) { ++ context.getItemInHand().hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(context.getHand()); ++ }); ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end ++ world.playSound(entityhuman, blockposition1, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, world.getRandom().nextFloat() * 0.4F + 0.8F); ++ IBlockData iblockdata1 = BaseFireBlock.getState(world, blockposition1); + +- level.setBlock(blockpos1, blockstate1, 11); +- level.gameEvent((Entity) player, GameEvent.BLOCK_PLACE, blockpos); +- ItemStack itemstack = useoncontext.getItemInHand(); ++ world.setBlock(blockposition1, iblockdata1, 11); ++ world.gameEvent((Entity) entityhuman, GameEvent.BLOCK_PLACE, blockposition); ++ ItemStack itemstack = context.getItemInHand(); + +- if (player instanceof ServerPlayer) { +- CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) player, blockpos1, itemstack); +- itemstack.hurtAndBreak(1, player, (player1) -> { +- player1.broadcastBreakEvent(useoncontext.getHand()); ++ if (entityhuman instanceof ServerPlayer) { ++ CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) entityhuman, blockposition1, itemstack); ++ itemstack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(context.getHand()); + }); + } + +- return InteractionResult.sidedSuccess(level.isClientSide()); ++ return InteractionResult.sidedSuccess(world.isClientSide()); + } else { + return InteractionResult.FAIL; + } + } else { +- level.playSound(player, blockpos, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.4F + 0.8F); +- level.setBlock(blockpos, (BlockState) blockstate.setValue(BlockStateProperties.LIT, true), 11); +- level.gameEvent((Entity) player, GameEvent.BLOCK_CHANGE, blockpos); +- if (player != null) { +- useoncontext.getItemInHand().hurtAndBreak(1, player, (player1) -> { +- player1.broadcastBreakEvent(useoncontext.getHand()); ++ // CraftBukkit start - Store the clicked block ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL, entityhuman).isCancelled()) { ++ context.getItemInHand().hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(context.getHand()); + }); ++ return InteractionResult.PASS; + } ++ // CraftBukkit end ++ world.playSound(entityhuman, blockposition, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, world.getRandom().nextFloat() * 0.4F + 0.8F); ++ world.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockStateProperties.LIT, true), 11); ++ world.gameEvent((Entity) entityhuman, GameEvent.BLOCK_CHANGE, blockposition); ++ if (entityhuman != null) { ++ context.getItemInHand().hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(context.getHand()); ++ }); ++ } + +- return InteractionResult.sidedSuccess(level.isClientSide()); ++ return InteractionResult.sidedSuccess(world.isClientSide()); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/HangingEntityItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/HangingEntityItem.java.patch new file mode 100644 index 0000000000..a0a0dfeb0b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/HangingEntityItem.java.patch @@ -0,0 +1,157 @@ +--- a/net/minecraft/world/item/HangingEntityItem.java ++++ b/net/minecraft/world/item/HangingEntityItem.java +@@ -17,38 +17,41 @@ + import net.minecraft.world.entity.decoration.ItemFrame; + import net.minecraft.world.entity.decoration.Painting; + import net.minecraft.world.entity.decoration.PaintingVariant; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.entity.Player; ++import org.bukkit.event.hanging.HangingPlaceEvent; ++// CraftBukkit end ++ + public class HangingEntityItem extends Item { + + private static final Component TOOLTIP_RANDOM_VARIANT = Component.translatable("painting.random").withStyle(ChatFormatting.GRAY); + private final EntityType type; + +- public HangingEntityItem(EntityType entitytype, Item.Properties item_properties) { +- super(item_properties); +- this.type = entitytype; ++ public HangingEntityItem(EntityType type, Item.Properties properties) { ++ super(properties); ++ this.type = type; + } + + @Override +- @Override +- public InteractionResult useOn(UseOnContext useoncontext) { +- BlockPos blockpos = useoncontext.getClickedPos(); +- Direction direction = useoncontext.getClickedFace(); +- BlockPos blockpos1 = blockpos.relative(direction); +- Player player = useoncontext.getPlayer(); +- ItemStack itemstack = useoncontext.getItemInHand(); ++ public InteractionResult useOn(UseOnContext context) { ++ BlockPos blockposition = context.getClickedPos(); ++ Direction enumdirection = context.getClickedFace(); ++ BlockPos blockposition1 = blockposition.relative(enumdirection); ++ net.minecraft.world.entity.player.Player entityhuman = context.getPlayer(); ++ ItemStack itemstack = context.getItemInHand(); + +- if (player != null && !this.mayPlace(player, direction, itemstack, blockpos1)) { ++ if (entityhuman != null && !this.mayPlace(entityhuman, enumdirection, itemstack, blockposition1)) { + return InteractionResult.FAIL; + } else { +- Level level = useoncontext.getLevel(); ++ Level world = context.getLevel(); + Object object; + + if (this.type == EntityType.PAINTING) { +- Optional optional = Painting.create(level, blockpos1, direction); ++ Optional optional = Painting.create(world, blockposition1, enumdirection); + + if (optional.isEmpty()) { + return InteractionResult.CONSUME; +@@ -56,61 +59,73 @@ + + object = (HangingEntity) optional.get(); + } else if (this.type == EntityType.ITEM_FRAME) { +- object = new ItemFrame(level, blockpos1, direction); ++ object = new ItemFrame(world, blockposition1, enumdirection); + } else { + if (this.type != EntityType.GLOW_ITEM_FRAME) { +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } + +- object = new GlowItemFrame(level, blockpos1, direction); ++ object = new GlowItemFrame(world, blockposition1, enumdirection); + } + +- CompoundTag compoundtag = itemstack.getTag(); ++ CompoundTag nbttagcompound = itemstack.getTag(); + +- if (compoundtag != null) { +- EntityType.updateCustomEntityTag(level, player, (Entity) object, compoundtag); ++ if (nbttagcompound != null) { ++ EntityType.updateCustomEntityTag(world, entityhuman, (Entity) object, nbttagcompound); + } + + if (((HangingEntity) object).survives()) { +- if (!level.isClientSide) { ++ if (!world.isClientSide) { ++ // CraftBukkit start - fire HangingPlaceEvent ++ Player who = (context.getPlayer() == null) ? null : (Player) context.getPlayer().getBukkitEntity(); ++ org.bukkit.block.Block blockClicked = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(enumdirection); ++ org.bukkit.inventory.EquipmentSlot hand = org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand()); ++ ++ HangingPlaceEvent event = new HangingPlaceEvent((org.bukkit.entity.Hanging) ((HangingEntity) object).getBukkitEntity(), who, blockClicked, blockFace, hand, org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return InteractionResult.FAIL; ++ } ++ // CraftBukkit end + ((HangingEntity) object).playPlacementSound(); +- level.gameEvent((Entity) player, GameEvent.ENTITY_PLACE, ((HangingEntity) object).position()); +- level.addFreshEntity((Entity) object); ++ world.gameEvent((Entity) entityhuman, GameEvent.ENTITY_PLACE, ((HangingEntity) object).position()); ++ world.addFreshEntity((Entity) object); + } + + itemstack.shrink(1); +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } else { + return InteractionResult.CONSUME; + } + } + } + +- protected boolean mayPlace(Player player, Direction direction, ItemStack itemstack, BlockPos blockpos) { +- return !direction.getAxis().isVertical() && player.mayUseItemAt(blockpos, direction, itemstack); ++ protected boolean mayPlace(net.minecraft.world.entity.player.Player player, Direction direction, ItemStack hangingEntityStack, BlockPos pos) { ++ return !direction.getAxis().isVertical() && player.mayUseItemAt(pos, direction, hangingEntityStack); + } + + @Override +- @Override +- public void appendHoverText(ItemStack itemstack, @Nullable Level level, List list, TooltipFlag tooltipflag) { +- super.appendHoverText(itemstack, level, list, tooltipflag); ++ public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltipComponents, TooltipFlag isAdvanced) { ++ super.appendHoverText(stack, level, tooltipComponents, isAdvanced); + if (this.type == EntityType.PAINTING) { +- CompoundTag compoundtag = itemstack.getTag(); ++ CompoundTag nbttagcompound = stack.getTag(); + +- if (compoundtag != null && compoundtag.contains("EntityTag", 10)) { +- CompoundTag compoundtag1 = compoundtag.getCompound("EntityTag"); ++ if (nbttagcompound != null && nbttagcompound.contains("EntityTag", 10)) { ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("EntityTag"); + +- Painting.loadVariant(compoundtag1).ifPresentOrElse((holder) -> { ++ Painting.loadVariant(nbttagcompound1).ifPresentOrElse((holder) -> { + holder.unwrapKey().ifPresent((resourcekey) -> { +- list.add(Component.translatable(resourcekey.location().toLanguageKey("painting", "title")).withStyle(ChatFormatting.YELLOW)); +- list.add(Component.translatable(resourcekey.location().toLanguageKey("painting", "author")).withStyle(ChatFormatting.GRAY)); ++ tooltipComponents.add(Component.translatable(resourcekey.location().toLanguageKey("painting", "title")).withStyle(ChatFormatting.YELLOW)); ++ tooltipComponents.add(Component.translatable(resourcekey.location().toLanguageKey("painting", "author")).withStyle(ChatFormatting.GRAY)); + }); +- list.add(Component.translatable("painting.dimensions", Mth.positiveCeilDiv(((PaintingVariant) holder.value()).getWidth(), 16), Mth.positiveCeilDiv(((PaintingVariant) holder.value()).getHeight(), 16))); ++ tooltipComponents.add(Component.translatable("painting.dimensions", Mth.positiveCeilDiv(((PaintingVariant) holder.value()).getWidth(), 16), Mth.positiveCeilDiv(((PaintingVariant) holder.value()).getHeight(), 16))); + }, () -> { +- list.add(HangingEntityItem.TOOLTIP_RANDOM_VARIANT); ++ tooltipComponents.add(HangingEntityItem.TOOLTIP_RANDOM_VARIANT); + }); +- } else if (tooltipflag.isCreative()) { +- list.add(HangingEntityItem.TOOLTIP_RANDOM_VARIANT); ++ } else if (isAdvanced.isCreative()) { ++ tooltipComponents.add(HangingEntityItem.TOOLTIP_RANDOM_VARIANT); + } + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/ItemStack.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/ItemStack.java.patch new file mode 100644 index 0000000000..d4e2ce6fd3 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/ItemStack.java.patch @@ -0,0 +1,1314 @@ +--- a/net/minecraft/world/item/ItemStack.java ++++ b/net/minecraft/world/item/ItemStack.java +@@ -28,6 +28,7 @@ + import net.minecraft.advancements.CriteriaTriggers; + import net.minecraft.commands.arguments.blocks.BlockStateParser; + import net.minecraft.core.BlockPos; ++import net.minecraft.core.Direction; + import net.minecraft.core.Holder; + import net.minecraft.core.HolderSet; + import net.minecraft.core.Registry; +@@ -35,6 +36,7 @@ + import net.minecraft.core.registries.Registries; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; ++import net.minecraft.nbt.NbtOps; + import net.minecraft.nbt.Tag; + import net.minecraft.nbt.TagParser; + import net.minecraft.network.chat.CommonComponents; +@@ -43,27 +45,24 @@ + import net.minecraft.network.chat.HoverEvent; + import net.minecraft.network.chat.MutableComponent; + import net.minecraft.network.chat.Style; ++import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; + import net.minecraft.resources.ResourceLocation; +-import net.minecraft.server.level.ServerPlayer; +-import net.minecraft.sounds.SoundEvent; +-import net.minecraft.stats.Stats; + import net.minecraft.tags.TagKey; + import net.minecraft.util.ExtraCodecs; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobType; + import net.minecraft.world.entity.SlotAccess; + import net.minecraft.world.entity.ai.attributes.Attribute; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.decoration.ItemFrame; + import net.minecraft.world.entity.item.ItemEntity; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.flag.FeatureFlagSet; + import net.minecraft.world.inventory.ClickAction; + import net.minecraft.world.inventory.Slot; +@@ -74,13 +73,50 @@ + import net.minecraft.world.item.enchantment.Enchantment; + import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.item.enchantment.Enchantments; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; ++import net.minecraft.world.level.block.BaseEntityBlock; ++import net.minecraft.world.level.block.BedBlock; + import net.minecraft.world.level.block.Block; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.pattern.BlockInWorld; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.mojang.serialization.Dynamic; ++import java.util.Map; ++import java.util.Objects; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundSource; ++import net.minecraft.stats.Stats; ++import net.minecraft.util.datafix.fixes.DataConverterTypes; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.SaplingBlock; ++import net.minecraft.world.level.block.SignBlock; ++import net.minecraft.world.level.block.SoundType; ++import net.minecraft.world.level.block.WitherSkullBlock; ++import net.minecraft.world.level.block.entity.BlockEntity; ++import net.minecraft.world.level.block.entity.JukeboxBlockEntity; ++import net.minecraft.world.level.block.entity.SignBlockEntity; ++import net.minecraft.world.level.block.entity.SkullBlockEntity; ++import net.minecraft.world.level.gameevent.GameEvent; ++import org.bukkit.Location; ++import org.bukkit.TreeType; ++import org.bukkit.block.BlockState; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.entity.Player; ++import org.bukkit.event.block.BlockFertilizeEvent; ++import org.bukkit.event.player.PlayerItemDamageEvent; ++import org.bukkit.event.world.StructureGrowEvent; ++// CraftBukkit end ++ + public final class ItemStack { + + public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { +@@ -131,7 +167,7 @@ + /** @deprecated */ + @Deprecated + @Nullable +- private final Item item; ++ private Item item; + @Nullable + private CompoundTag tag; + @Nullable +@@ -145,26 +181,26 @@ + return this.getItem().getTooltipImage(this); + } + +- public ItemStack(ItemLike itemlike) { +- this(itemlike, 1); ++ public ItemStack(IMaterial item) { ++ this(item, 1); + } + +- public ItemStack(Holder holder) { +- this((ItemLike) holder.value(), 1); ++ public ItemStack(Holder tag) { ++ this((IMaterial) tag.value(), 1); + } + +- public ItemStack(Holder holder, int i, Optional optional) { +- this(holder, i); ++ public ItemStack(Holder item, int count, Optional optional) { ++ this(item, count); + optional.ifPresent(this::setTag); + } + +- public ItemStack(Holder holder, int i) { +- this((ItemLike) holder.value(), i); ++ public ItemStack(Holder item, int count) { ++ this((IMaterial) item.value(), count); + } + +- public ItemStack(ItemLike itemlike, int i) { +- this.item = itemlike.asItem(); +- this.count = i; ++ public ItemStack(IMaterial item, int count) { ++ this.item = item.asItem(); ++ this.count = count; + if (this.item.canBeDepleted()) { + this.setDamageValue(this.getDamageValue()); + } +@@ -175,11 +211,22 @@ + this.item = null; + } + +- private ItemStack(CompoundTag compoundtag) { +- this.item = (Item) BuiltInRegistries.ITEM.get(new ResourceLocation(compoundtag.getString("id"))); +- this.count = compoundtag.getByte("Count"); +- if (compoundtag.contains("tag", 10)) { +- this.tag = compoundtag.getCompound("tag").copy(); ++ // Called to run this stack through the data converter to handle older storage methods and serialized items ++ public void convertStack(int version) { ++ if (0 < version && version < CraftMagicNumbers.INSTANCE.getDataVersion()) { ++ CompoundTag savedStack = new CompoundTag(); ++ this.save(savedStack); ++ savedStack = (CompoundTag) MinecraftServer.getServer().fixerUpper.update(DataConverterTypes.ITEM_STACK, new Dynamic(NbtOps.INSTANCE, savedStack), version, CraftMagicNumbers.INSTANCE.getDataVersion()).getValue(); ++ this.load(savedStack); ++ } ++ } ++ ++ // CraftBukkit - break into own method ++ private void load(CompoundTag nbttagcompound) { ++ this.item = (Item) BuiltInRegistries.ITEM.get(new ResourceLocation(nbttagcompound.getString("id"))); ++ this.count = nbttagcompound.getByte("Count"); ++ if (nbttagcompound.contains("tag", 10)) { ++ this.tag = nbttagcompound.getCompound("tag").copy(); + this.getItem().verifyTagAfterLoad(this.tag); + } + +@@ -189,11 +236,16 @@ + + } + +- public static ItemStack of(CompoundTag compoundtag) { ++ private ItemStack(CompoundTag compoundTag) { ++ this.load(compoundTag); ++ // CraftBukkit end ++ } ++ ++ public static ItemStack of(CompoundTag compoundTag) { + try { +- return new ItemStack(compoundtag); ++ return new ItemStack(compoundTag); + } catch (RuntimeException runtimeexception) { +- ItemStack.LOGGER.debug("Tried to load invalid item: {}", compoundtag, runtimeexception); ++ ItemStack.LOGGER.debug("Tried to load invalid item: {}", compoundTag, runtimeexception); + return ItemStack.EMPTY; + } + } +@@ -202,12 +254,12 @@ + return this == ItemStack.EMPTY || this.item == Items.AIR || this.count <= 0; + } + +- public boolean isItemEnabled(FeatureFlagSet featureflagset) { +- return this.isEmpty() || this.getItem().isEnabled(featureflagset); ++ public boolean isItemEnabled(FeatureFlagSet enabledFlags) { ++ return this.isEmpty() || this.getItem().isEnabled(enabledFlags); + } + +- public ItemStack split(int i) { +- int j = Math.min(i, this.getCount()); ++ public ItemStack split(int amount) { ++ int j = Math.min(amount, this.getCount()); + ItemStack itemstack = this.copyWithCount(j); + + this.shrink(j); +@@ -233,20 +285,20 @@ + return this.getItem().builtInRegistryHolder(); + } + +- public boolean is(TagKey tagkey) { +- return this.getItem().builtInRegistryHolder().is(tagkey); ++ public boolean is(TagKey tag) { ++ return this.getItem().builtInRegistryHolder().is(tag); + } + + public boolean is(Item item) { + return this.getItem() == item; + } + +- public boolean is(Predicate> predicate) { +- return predicate.test(this.getItem().builtInRegistryHolder()); ++ public boolean is(Predicate> item) { ++ return item.test(this.getItem().builtInRegistryHolder()); + } + +- public boolean is(Holder holder) { +- return this.getItem().builtInRegistryHolder() == holder; ++ public boolean is(Holder item) { ++ return this.getItem().builtInRegistryHolder() == item; + } + + public boolean is(HolderSet holderset) { +@@ -257,47 +309,226 @@ + return this.getItem().builtInRegistryHolder().tags(); + } + +- public InteractionResult useOn(UseOnContext useoncontext) { +- Player player = useoncontext.getPlayer(); +- BlockPos blockpos = useoncontext.getClickedPos(); +- BlockInWorld blockinworld = new BlockInWorld(useoncontext.getLevel(), blockpos, false); ++ public InteractionResult useOn(UseOnContext context) { ++ net.minecraft.world.entity.player.Player entityhuman = context.getPlayer(); ++ BlockPos blockposition = context.getClickedPos(); ++ BlockInWorld shapedetectorblock = new BlockInWorld(context.getLevel(), blockposition, false); + +- if (player != null && !player.getAbilities().mayBuild && !this.hasAdventureModePlaceTagForBlock(useoncontext.getLevel().registryAccess().registryOrThrow(Registries.BLOCK), blockinworld)) { ++ if (entityhuman != null && !entityhuman.getAbilities().mayBuild && !this.hasAdventureModePlaceTagForBlock(context.getLevel().registryAccess().registryOrThrow(Registries.BLOCK), shapedetectorblock)) { + return InteractionResult.PASS; + } else { + Item item = this.getItem(); +- InteractionResult interactionresult = item.useOn(useoncontext); ++ // CraftBukkit start - handle all block place event logic here ++ CompoundTag oldData = this.getTagClone(); ++ int oldCount = this.getCount(); ++ ServerLevel world = (ServerLevel) context.getLevel(); + +- if (player != null && interactionresult.shouldAwardStats()) { +- player.awardStat(Stats.ITEM_USED.get(item)); ++ if (!(item instanceof BucketItem || item instanceof SolidBucketItem)) { // if not bucket ++ world.captureBlockStates = true; ++ // special case bonemeal ++ if (item == Items.BONE_MEAL) { ++ world.captureTreeGeneration = true; ++ } + } ++ InteractionResult enuminteractionresult; ++ try { ++ enuminteractionresult = item.useOn(context); ++ } finally { ++ world.captureBlockStates = false; ++ } ++ CompoundTag newData = this.getTagClone(); ++ int newCount = this.getCount(); ++ this.setCount(oldCount); ++ this.setTagClone(oldData); ++ if (enuminteractionresult.consumesAction() && world.captureTreeGeneration && world.capturedBlockStates.size() > 0) { ++ world.captureTreeGeneration = false; ++ Location location = CraftLocation.toBukkit(blockposition, world.getWorld()); ++ TreeType treeType = SaplingBlock.treeType; ++ SaplingBlock.treeType = null; ++ List blocks = new java.util.ArrayList<>(world.capturedBlockStates.values()); ++ world.capturedBlockStates.clear(); ++ StructureGrowEvent structureEvent = null; ++ if (treeType != null) { ++ boolean isBonemeal = getItem() == Items.BONE_MEAL; ++ structureEvent = new StructureGrowEvent(location, treeType, isBonemeal, (Player) entityhuman.getBukkitEntity(), (List< BlockState>) (List) blocks); ++ org.bukkit.Bukkit.getPluginManager().callEvent(structureEvent); ++ } + +- return interactionresult; ++ BlockFertilizeEvent fertilizeEvent = new BlockFertilizeEvent(CraftBlock.at(world, blockposition), (Player) entityhuman.getBukkitEntity(), (List< BlockState>) (List) blocks); ++ fertilizeEvent.setCancelled(structureEvent != null && structureEvent.isCancelled()); ++ org.bukkit.Bukkit.getPluginManager().callEvent(fertilizeEvent); ++ ++ if (!fertilizeEvent.isCancelled()) { ++ // Change the stack to its new contents if it hasn't been tampered with. ++ if (this.getCount() == oldCount && Objects.equals(this.tag, oldData)) { ++ this.setTag(newData); ++ this.setCount(newCount); ++ } ++ for (CraftBlockState blockstate : blocks) { ++ world.setBlock(blockstate.getPosition(),blockstate.getHandle(), blockstate.getFlag()); // SPIGOT-7248 - manual update to avoid physics where appropriate ++ } ++ entityhuman.awardStat(Stats.ITEM_USED.get(item)); // SPIGOT-7236 - award stat ++ } ++ ++ SignItem.openSign = null; // SPIGOT-6758 - Reset on early return ++ return enuminteractionresult; ++ } ++ world.captureTreeGeneration = false; ++ ++ if (entityhuman != null && enuminteractionresult.shouldAwardStats()) { ++ EnumHand enumhand = context.getHand(); ++ org.bukkit.event.block.BlockPlaceEvent placeEvent = null; ++ List blocks = new java.util.ArrayList<>(world.capturedBlockStates.values()); ++ world.capturedBlockStates.clear(); ++ if (blocks.size() > 1) { ++ placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockMultiPlaceEvent(world, entityhuman, enumhand, blocks, blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ } else if (blocks.size() == 1) { ++ placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEvent(world, entityhuman, enumhand, blocks.get(0), blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ } ++ ++ if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild())) { ++ enuminteractionresult = InteractionResult.FAIL; // cancel placement ++ // PAIL: Remove this when MC-99075 fixed ++ placeEvent.getPlayer().updateInventory(); ++ // revert back all captured blocks ++ world.preventPoiUpdated = true; // CraftBukkit - SPIGOT-5710 ++ for (BlockState blockstate : blocks) { ++ blockstate.update(true, false); ++ } ++ world.preventPoiUpdated = false; ++ ++ // Brute force all possible updates ++ BlockPos placedPos = ((CraftBlock) placeEvent.getBlock()).getPosition(); ++ for (Direction dir : Direction.values()) { ++ ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, placedPos.relative(dir))); ++ } ++ SignItem.openSign = null; // SPIGOT-6758 - Reset on early return ++ } else { ++ // Change the stack to its new contents if it hasn't been tampered with. ++ if (this.getCount() == oldCount && Objects.equals(this.tag, oldData)) { ++ this.setTag(newData); ++ this.setCount(newCount); ++ } ++ ++ for (Map.Entry e : world.capturedTileEntities.entrySet()) { ++ world.setBlockEntity(e.getValue()); ++ } ++ ++ for (BlockState blockstate : blocks) { ++ int updateFlag = ((CraftBlockState) blockstate).getFlag(); ++ IBlockData oldBlock = ((CraftBlockState) blockstate).getHandle(); ++ BlockPos newblockposition = ((CraftBlockState) blockstate).getPosition(); ++ IBlockData block = world.getBlockState(newblockposition); ++ ++ if (!(block.getBlock() instanceof BaseEntityBlock)) { // Containers get placed automatically ++ block.getBlock().onPlace(block, world, newblockposition, oldBlock, true); ++ } ++ ++ world.notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, world.getBlockState(newblockposition), updateFlag, 512); // send null chunk as chunk.k() returns false by this point ++ } ++ ++ // Special case juke boxes as they update their tile entity. Copied from ItemRecord. ++ // PAIL: checkme on updates. ++ if (this.item instanceof RecordItem) { ++ BlockEntity tileentity = world.getBlockEntity(blockposition); ++ ++ if (tileentity instanceof JukeboxBlockEntity) { ++ JukeboxBlockEntity tileentityjukebox = (JukeboxBlockEntity) tileentity; ++ ++ // There can only be one ++ ItemStack record = this.copy(); ++ if (!record.isEmpty()) { ++ record.setCount(1); ++ } ++ ++ tileentityjukebox.setTheItem(record); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entityhuman, world.getBlockState(blockposition))); ++ } ++ ++ this.shrink(1); ++ entityhuman.awardStat(Stats.PLAY_RECORD); ++ } ++ ++ if (this.item == Items.WITHER_SKELETON_SKULL) { // Special case skulls to allow wither spawns to be cancelled ++ BlockPos bp = blockposition; ++ if (!world.getBlockState(blockposition).canBeReplaced()) { ++ if (!world.getBlockState(blockposition).isSolid()) { ++ bp = null; ++ } else { ++ bp = bp.relative(context.getClickedFace()); ++ } ++ } ++ if (bp != null) { ++ BlockEntity te = world.getBlockEntity(bp); ++ if (te instanceof SkullBlockEntity) { ++ WitherSkullBlock.checkSpawn(world, bp, (SkullBlockEntity) te); ++ } ++ } ++ } ++ ++ // SPIGOT-4678 ++ if (this.item instanceof SignItem && SignItem.openSign != null) { ++ try { ++ if (world.getBlockEntity(SignItem.openSign) instanceof SignBlockEntity tileentitysign) { ++ if (world.getBlockState(SignItem.openSign).getBlock() instanceof SignBlock blocksign) { ++ blocksign.openTextEdit(entityhuman, tileentitysign, true, org.bukkit.event.player.PlayerSignOpenEvent.Cause.PLACE); // Craftbukkit ++ } ++ } ++ } finally { ++ SignItem.openSign = null; ++ } ++ } ++ ++ // SPIGOT-7315: Moved from BlockBed#setPlacedBy ++ if (placeEvent != null && this.item instanceof BedItem) { ++ BlockPos position = ((CraftBlock) placeEvent.getBlock()).getPosition(); ++ IBlockData blockData = world.getBlockState(position); ++ ++ if (blockData.getBlock() instanceof BedBlock) { ++ world.blockUpdated(position, Blocks.AIR); ++ blockData.updateNeighbourShapes(world, position, 3); ++ } ++ } ++ ++ // SPIGOT-1288 - play sound stripped from ItemBlock ++ if (this.item instanceof BlockItem) { ++ SoundType soundeffecttype = ((BlockItem) this.item).getBlock().defaultBlockState().getSoundType(); // TODO: not strictly correct, however currently only affects decorated pots ++ world.playSound(entityhuman, blockposition, soundeffecttype.getPlaceSound(), SoundSource.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F); ++ } ++ ++ entityhuman.awardStat(Stats.ITEM_USED.get(item)); ++ } ++ } ++ world.capturedTileEntities.clear(); ++ world.capturedBlockStates.clear(); ++ // CraftBukkit end ++ ++ return enuminteractionresult; + } + } + +- public float getDestroySpeed(BlockState blockstate) { +- return this.getItem().getDestroySpeed(this, blockstate); ++ public float getDestroySpeed(IBlockData state) { ++ return this.getItem().getDestroySpeed(this, state); + } + +- public InteractionResultHolder use(Level level, Player player, InteractionHand interactionhand) { +- return this.getItem().use(level, player, interactionhand); ++ public InteractionResultHolder use(Level level, net.minecraft.world.entity.player.Player player, EnumHand usedHand) { ++ return this.getItem().use(level, player, usedHand); + } + +- public ItemStack finishUsingItem(Level level, LivingEntity livingentity) { +- return this.getItem().finishUsingItem(this, level, livingentity); ++ public ItemStack finishUsingItem(Level level, LivingEntity livingEntity) { ++ return this.getItem().finishUsingItem(this, level, livingEntity); + } + +- public CompoundTag save(CompoundTag compoundtag) { +- ResourceLocation resourcelocation = BuiltInRegistries.ITEM.getKey(this.getItem()); ++ public CompoundTag save(CompoundTag compoundTag) { ++ ResourceLocation minecraftkey = BuiltInRegistries.ITEM.getKey(this.getItem()); + +- compoundtag.putString("id", resourcelocation == null ? "minecraft:air" : resourcelocation.toString()); +- compoundtag.putByte("Count", (byte) this.count); ++ compoundTag.putString("id", minecraftkey == null ? "minecraft:air" : minecraftkey.toString()); ++ compoundTag.putByte("Count", (byte) this.count); + if (this.tag != null) { +- compoundtag.put("tag", this.tag.copy()); ++ compoundTag.put("tag", this.tag.copy()); + } + +- return compoundtag; ++ return compoundTag; + } + + public int getMaxStackSize() { +@@ -310,9 +541,9 @@ + + public boolean isDamageableItem() { + if (!this.isEmpty() && this.getItem().getMaxDamage() > 0) { +- CompoundTag compoundtag = this.getTag(); ++ CompoundTag nbttagcompound = this.getTag(); + +- return compoundtag == null || !compoundtag.getBoolean("Unbreakable"); ++ return nbttagcompound == null || !nbttagcompound.getBoolean("Unbreakable"); + } else { + return false; + } +@@ -326,56 +557,76 @@ + return this.tag == null ? 0 : this.tag.getInt("Damage"); + } + +- public void setDamageValue(int i) { +- this.getOrCreateTag().putInt("Damage", Math.max(0, i)); ++ public void setDamageValue(int damage) { ++ this.getOrCreateTag().putInt("Damage", Math.max(0, damage)); + } + + public int getMaxDamage() { + return this.getItem().getMaxDamage(); + } + +- public boolean hurt(int i, RandomSource randomsource, @Nullable ServerPlayer serverplayer) { ++ public boolean hurt(int amount, RandomSource random, @Nullable ServerPlayer user) { + if (!this.isDamageableItem()) { + return false; + } else { + int j; + +- if (i > 0) { ++ if (amount > 0) { + j = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.UNBREAKING, this); + int k = 0; + +- for (int l = 0; j > 0 && l < i; ++l) { +- if (DigDurabilityEnchantment.shouldIgnoreDurabilityDrop(this, j, randomsource)) { ++ for (int l = 0; j > 0 && l < amount; ++l) { ++ if (DigDurabilityEnchantment.shouldIgnoreDurabilityDrop(this, j, random)) { + ++k; + } + } + +- i -= k; +- if (i <= 0) { ++ amount -= k; ++ // CraftBukkit start ++ if (user != null) { ++ PlayerItemDamageEvent event = new PlayerItemDamageEvent(user.getBukkitEntity(), CraftItemStack.asCraftMirror(this), amount); ++ event.getPlayer().getServer().getPluginManager().callEvent(event); ++ ++ if (amount != event.getDamage() || event.isCancelled()) { ++ event.getPlayer().updateInventory(); ++ } ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ amount = event.getDamage(); ++ } ++ // CraftBukkit end ++ if (amount <= 0) { + return false; + } + } + +- if (serverplayer != null && i != 0) { +- CriteriaTriggers.ITEM_DURABILITY_CHANGED.trigger(serverplayer, this, this.getDamageValue() + i); ++ if (user != null && amount != 0) { ++ CriteriaTriggers.ITEM_DURABILITY_CHANGED.trigger(user, this, this.getDamageValue() + amount); + } + +- j = this.getDamageValue() + i; ++ j = this.getDamageValue() + amount; + this.setDamageValue(j); + return j >= this.getMaxDamage(); + } + } + +- public void hurtAndBreak(int i, T t0, Consumer consumer) { +- if (!t0.level().isClientSide && (!(t0 instanceof Player) || !((Player) t0).getAbilities().instabuild)) { ++ public void hurtAndBreak(int amount, T entity, Consumer onBroken) { ++ if (!entity.level().isClientSide && (!(entity instanceof net.minecraft.world.entity.player.Player) || !((net.minecraft.world.entity.player.Player) entity).getAbilities().instabuild)) { + if (this.isDamageableItem()) { +- if (this.hurt(i, t0.getRandom(), t0 instanceof ServerPlayer ? (ServerPlayer) t0 : null)) { +- consumer.accept(t0); ++ if (this.hurt(amount, entity.getRandom(), entity instanceof ServerPlayer ? (ServerPlayer) entity : null)) { ++ onBroken.accept(entity); + Item item = this.getItem(); ++ // CraftBukkit start - Check for item breaking ++ if (this.count == 1 && entity instanceof net.minecraft.world.entity.player.Player) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemBreakEvent((net.minecraft.world.entity.player.Player) entity, this); ++ } ++ // CraftBukkit end + + this.shrink(1); +- if (t0 instanceof Player) { +- ((Player) t0).awardStat(Stats.ITEM_BROKEN.get(item)); ++ if (entity instanceof net.minecraft.world.entity.player.Player) { ++ ((net.minecraft.world.entity.player.Player) entity).awardStat(Stats.ITEM_BROKEN.get(item)); + } + + this.setDamageValue(0); +@@ -397,38 +648,38 @@ + return this.getItem().getBarColor(this); + } + +- public boolean overrideStackedOnOther(Slot slot, ClickAction clickaction, Player player) { +- return this.getItem().overrideStackedOnOther(this, slot, clickaction, player); ++ public boolean overrideStackedOnOther(Slot slot, ClickAction action, net.minecraft.world.entity.player.Player player) { ++ return this.getItem().overrideStackedOnOther(this, slot, action, player); + } + +- public boolean overrideOtherStackedOnMe(ItemStack itemstack, Slot slot, ClickAction clickaction, Player player, SlotAccess slotaccess) { +- return this.getItem().overrideOtherStackedOnMe(this, itemstack, slot, clickaction, player, slotaccess); ++ public boolean overrideOtherStackedOnMe(ItemStack stack, Slot slot, ClickAction action, net.minecraft.world.entity.player.Player player, SlotAccess access) { ++ return this.getItem().overrideOtherStackedOnMe(this, stack, slot, action, player, access); + } + +- public void hurtEnemy(LivingEntity livingentity, Player player) { ++ public void hurtEnemy(LivingEntity entity, net.minecraft.world.entity.player.Player player) { + Item item = this.getItem(); + +- if (item.hurtEnemy(this, livingentity, player)) { ++ if (item.hurtEnemy(this, entity, player)) { + player.awardStat(Stats.ITEM_USED.get(item)); + } + + } + +- public void mineBlock(Level level, BlockState blockstate, BlockPos blockpos, Player player) { ++ public void mineBlock(Level level, IBlockData state, BlockPos pos, net.minecraft.world.entity.player.Player player) { + Item item = this.getItem(); + +- if (item.mineBlock(this, level, blockstate, blockpos, player)) { ++ if (item.mineBlock(this, level, state, pos, player)) { + player.awardStat(Stats.ITEM_USED.get(item)); + } + + } + +- public boolean isCorrectToolForDrops(BlockState blockstate) { +- return this.getItem().isCorrectToolForDrops(blockstate); ++ public boolean isCorrectToolForDrops(IBlockData state) { ++ return this.getItem().isCorrectToolForDrops(state); + } + +- public InteractionResult interactLivingEntity(Player player, LivingEntity livingentity, InteractionHand interactionhand) { +- return this.getItem().interactLivingEntity(this, player, livingentity, interactionhand); ++ public InteractionResult interactLivingEntity(net.minecraft.world.entity.player.Player player, LivingEntity entity, EnumHand usedHand) { ++ return this.getItem().interactLivingEntity(this, player, entity, usedHand); + } + + public ItemStack copy() { +@@ -446,70 +697,69 @@ + } + } + +- public ItemStack copyWithCount(int i) { ++ public ItemStack copyWithCount(int count) { + if (this.isEmpty()) { + return ItemStack.EMPTY; + } else { + ItemStack itemstack = this.copy(); + +- itemstack.setCount(i); ++ itemstack.setCount(count); + return itemstack; + } + } + +- public static boolean matches(ItemStack itemstack, ItemStack itemstack1) { +- return itemstack == itemstack1 ? true : (itemstack.getCount() != itemstack1.getCount() ? false : isSameItemSameTags(itemstack, itemstack1)); ++ public static boolean matches(ItemStack stack, ItemStack other) { ++ return stack == other ? true : (stack.getCount() != other.getCount() ? false : isSameItemSameTags(stack, other)); + } + +- public static boolean isSameItem(ItemStack itemstack, ItemStack itemstack1) { +- return itemstack.is(itemstack1.getItem()); ++ public static boolean isSameItem(ItemStack stack, ItemStack other) { ++ return stack.is(other.getItem()); + } + +- public static boolean isSameItemSameTags(ItemStack itemstack, ItemStack itemstack1) { +- return !itemstack.is(itemstack1.getItem()) ? false : (itemstack.isEmpty() && itemstack1.isEmpty() ? true : Objects.equals(itemstack.tag, itemstack1.tag)); ++ public static boolean isSameItemSameTags(ItemStack stack, ItemStack other) { ++ return !stack.is(other.getItem()) ? false : (stack.isEmpty() && other.isEmpty() ? true : Objects.equals(stack.tag, other.tag)); + } + + public String getDescriptionId() { + return this.getItem().getDescriptionId(this); + } + +- @Override + public String toString() { + int i = this.getCount(); + + return i + " " + this.getItem(); + } + +- public void inventoryTick(Level level, Entity entity, int i, boolean flag) { ++ public void inventoryTick(Level level, Entity entity, int inventorySlot, boolean isCurrentItem) { + if (this.popTime > 0) { + --this.popTime; + } + + if (this.getItem() != null) { +- this.getItem().inventoryTick(this, level, entity, i, flag); ++ this.getItem().inventoryTick(this, level, entity, inventorySlot, isCurrentItem); + } + + } + +- public void onCraftedBy(Level level, Player player, int i) { +- player.awardStat(Stats.ITEM_CRAFTED.get(this.getItem()), i); ++ public void onCraftedBy(Level level, net.minecraft.world.entity.player.Player player, int amount) { ++ player.awardStat(Stats.ITEM_CRAFTED.get(this.getItem()), amount); + this.getItem().onCraftedBy(this, level, player); + } + +- public void onCraftedBySystem(Level level) { +- this.getItem().onCraftedPostProcess(this, level); ++ public void onCraftedBySystem(Level world) { ++ this.getItem().onCraftedPostProcess(this, world); + } + + public int getUseDuration() { + return this.getItem().getUseDuration(this); + } + +- public UseAnim getUseAnimation() { ++ public EnumAnimation getUseAnimation() { + return this.getItem().getUseAnimation(this); + } + +- public void releaseUsing(Level level, LivingEntity livingentity, int i) { +- this.getItem().releaseUsing(this, level, livingentity, i); ++ public void releaseUsing(Level level, LivingEntity livingEntity, int timeLeft) { ++ this.getItem().releaseUsing(this, level, livingEntity, timeLeft); + } + + public boolean useOnRelease() { +@@ -525,6 +775,17 @@ + return this.tag; + } + ++ // CraftBukkit start ++ @Nullable ++ private CompoundTag getTagClone() { ++ return this.tag == null ? null : this.tag.copy(); ++ } ++ ++ private void setTagClone(@Nullable CompoundTag nbtttagcompound) { ++ this.setTag(nbtttagcompound == null ? null : nbtttagcompound.copy()); ++ } ++ // CraftBukkit end ++ + public CompoundTag getOrCreateTag() { + if (this.tag == null) { + this.setTag(new CompoundTag()); +@@ -533,25 +794,25 @@ + return this.tag; + } + +- public CompoundTag getOrCreateTagElement(String s) { +- if (this.tag != null && this.tag.contains(s, 10)) { +- return this.tag.getCompound(s); ++ public CompoundTag getOrCreateTagElement(String key) { ++ if (this.tag != null && this.tag.contains(key, 10)) { ++ return this.tag.getCompound(key); + } else { +- CompoundTag compoundtag = new CompoundTag(); ++ CompoundTag nbttagcompound = new CompoundTag(); + +- this.addTagElement(s, compoundtag); +- return compoundtag; ++ this.addTagElement(key, nbttagcompound); ++ return nbttagcompound; + } + } + + @Nullable +- public CompoundTag getTagElement(String s) { +- return this.tag != null && this.tag.contains(s, 10) ? this.tag.getCompound(s) : null; ++ public CompoundTag getTagElement(String key) { ++ return this.tag != null && this.tag.contains(key, 10) ? this.tag.getCompound(key) : null; + } + +- public void removeTagKey(String s) { +- if (this.tag != null && this.tag.contains(s)) { +- this.tag.remove(s); ++ public void removeTagKey(String key) { ++ if (this.tag != null && this.tag.contains(key)) { ++ this.tag.remove(key); + if (this.tag.isEmpty()) { + this.tag = null; + } +@@ -563,56 +824,56 @@ + return this.tag != null ? this.tag.getList("Enchantments", 10) : new ListTag(); + } + +- public void setTag(@Nullable CompoundTag compoundtag) { +- this.tag = compoundtag; ++ public void setTag(@Nullable CompoundTag compoundTag) { ++ this.tag = compoundTag; + if (this.getItem().canBeDepleted()) { + this.setDamageValue(this.getDamageValue()); + } + +- if (compoundtag != null) { +- this.getItem().verifyTagAfterLoad(compoundtag); ++ if (compoundTag != null) { ++ this.getItem().verifyTagAfterLoad(compoundTag); + } + + } + + public Component getHoverName() { +- CompoundTag compoundtag = this.getTagElement("display"); ++ CompoundTag nbttagcompound = this.getTagElement("display"); + +- if (compoundtag != null && compoundtag.contains("Name", 8)) { ++ if (nbttagcompound != null && nbttagcompound.contains("Name", 8)) { + try { +- MutableComponent mutablecomponent = Component.Serializer.fromJson(compoundtag.getString("Name")); ++ MutableComponent ichatmutablecomponent = Component.Serializer.fromJson(nbttagcompound.getString("Name")); + +- if (mutablecomponent != null) { +- return mutablecomponent; ++ if (ichatmutablecomponent != null) { ++ return ichatmutablecomponent; + } + +- compoundtag.remove("Name"); ++ nbttagcompound.remove("Name"); + } catch (Exception exception) { +- compoundtag.remove("Name"); ++ nbttagcompound.remove("Name"); + } + } + + return this.getItem().getName(this); + } + +- public ItemStack setHoverName(@Nullable Component component) { +- CompoundTag compoundtag = this.getOrCreateTagElement("display"); ++ public ItemStack setHoverName(@Nullable Component nameComponent) { ++ CompoundTag nbttagcompound = this.getOrCreateTagElement("display"); + +- if (component != null) { +- compoundtag.putString("Name", Component.Serializer.toJson(component)); ++ if (nameComponent != null) { ++ nbttagcompound.putString("Name", Component.Serializer.toJson(nameComponent)); + } else { +- compoundtag.remove("Name"); ++ nbttagcompound.remove("Name"); + } + + return this; + } + + public void resetHoverName() { +- CompoundTag compoundtag = this.getTagElement("display"); ++ CompoundTag nbttagcompound = this.getTagElement("display"); + +- if (compoundtag != null) { +- compoundtag.remove("Name"); +- if (compoundtag.isEmpty()) { ++ if (nbttagcompound != null) { ++ nbttagcompound.remove("Name"); ++ if (nbttagcompound.isEmpty()) { + this.removeTagKey("display"); + } + } +@@ -624,21 +885,21 @@ + } + + public boolean hasCustomHoverName() { +- CompoundTag compoundtag = this.getTagElement("display"); ++ CompoundTag nbttagcompound = this.getTagElement("display"); + +- return compoundtag != null && compoundtag.contains("Name", 8); ++ return nbttagcompound != null && nbttagcompound.contains("Name", 8); + } + +- public List getTooltipLines(@Nullable Player player, TooltipFlag tooltipflag) { ++ public List getTooltipLines(@Nullable net.minecraft.world.entity.player.Player player, TooltipFlag isAdvanced) { + List list = Lists.newArrayList(); +- MutableComponent mutablecomponent = Component.empty().append(this.getHoverName()).withStyle(this.getRarity().color); ++ MutableComponent ichatmutablecomponent = Component.empty().append(this.getHoverName()).withStyle(this.getRarity().color); + + if (this.hasCustomHoverName()) { +- mutablecomponent.withStyle(ChatFormatting.ITALIC); ++ ichatmutablecomponent.withStyle(ChatFormatting.ITALIC); + } + +- list.add(mutablecomponent); +- if (!tooltipflag.isAdvanced() && !this.hasCustomHoverName() && this.is(Items.FILLED_MAP)) { ++ list.add(ichatmutablecomponent); ++ if (!isAdvanced.isAdvanced() && !this.hasCustomHoverName() && this.is(Items.FILLED_MAP)) { + Integer integer = MapItem.getMapId(this); + + if (integer != null) { +@@ -648,46 +909,46 @@ + + int i = this.getHideFlags(); + +- if (shouldShowInTooltip(i, ItemStack.TooltipPart.ADDITIONAL)) { +- this.getItem().appendHoverText(this, player == null ? null : player.level(), list, tooltipflag); ++ if (shouldShowInTooltip(i, ItemStack.HideFlags.ADDITIONAL)) { ++ this.getItem().appendHoverText(this, player == null ? null : player.level(), list, isAdvanced); + } + + int j; + + if (this.hasTag()) { +- if (shouldShowInTooltip(i, ItemStack.TooltipPart.UPGRADES) && player != null) { ++ if (shouldShowInTooltip(i, ItemStack.HideFlags.UPGRADES) && player != null) { + ArmorTrim.appendUpgradeHoverText(this, player.level().registryAccess(), list); + } + +- if (shouldShowInTooltip(i, ItemStack.TooltipPart.ENCHANTMENTS)) { ++ if (shouldShowInTooltip(i, ItemStack.HideFlags.ENCHANTMENTS)) { + appendEnchantmentNames(list, this.getEnchantmentTags()); + } + + if (this.tag.contains("display", 10)) { +- CompoundTag compoundtag = this.tag.getCompound("display"); ++ CompoundTag nbttagcompound = this.tag.getCompound("display"); + +- if (shouldShowInTooltip(i, ItemStack.TooltipPart.DYE) && compoundtag.contains("color", 99)) { +- if (tooltipflag.isAdvanced()) { +- list.add(Component.translatable("item.color", String.format(Locale.ROOT, "#%06X", compoundtag.getInt("color"))).withStyle(ChatFormatting.GRAY)); ++ if (shouldShowInTooltip(i, ItemStack.HideFlags.DYE) && nbttagcompound.contains("color", 99)) { ++ if (isAdvanced.isAdvanced()) { ++ list.add(Component.translatable("item.color", String.format(Locale.ROOT, "#%06X", nbttagcompound.getInt("color"))).withStyle(ChatFormatting.GRAY)); + } else { + list.add(Component.translatable("item.dyed").withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC)); + } + } + +- if (compoundtag.getTagType("Lore") == 9) { +- ListTag listtag = compoundtag.getList("Lore", 8); ++ if (nbttagcompound.getTagType("Lore") == 9) { ++ ListTag nbttaglist = nbttagcompound.getList("Lore", 8); + +- for (j = 0; j < listtag.size(); ++j) { +- String s = listtag.getString(j); ++ for (j = 0; j < nbttaglist.size(); ++j) { ++ String s = nbttaglist.getString(j); + + try { +- MutableComponent mutablecomponent1 = Component.Serializer.fromJson(s); ++ MutableComponent ichatmutablecomponent1 = Component.Serializer.fromJson(s); + +- if (mutablecomponent1 != null) { +- list.add(ComponentUtils.mergeStyles(mutablecomponent1, ItemStack.LORE_STYLE)); ++ if (ichatmutablecomponent1 != null) { ++ list.add(ComponentUtils.mergeStyles(ichatmutablecomponent1, ItemStack.LORE_STYLE)); + } + } catch (Exception exception) { +- compoundtag.remove("Lore"); ++ nbttagcompound.remove("Lore"); + } + } + } +@@ -696,18 +957,18 @@ + + int k; + +- if (shouldShowInTooltip(i, ItemStack.TooltipPart.MODIFIERS)) { +- EquipmentSlot[] aequipmentslot = EquipmentSlot.values(); ++ if (shouldShowInTooltip(i, ItemStack.HideFlags.MODIFIERS)) { ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); + +- k = aequipmentslot.length; ++ k = aenumitemslot.length; + + for (j = 0; j < k; ++j) { +- EquipmentSlot equipmentslot = aequipmentslot[j]; +- Multimap multimap = this.getAttributeModifiers(equipmentslot); ++ EquipmentSlot enumitemslot = aenumitemslot[j]; ++ Multimap multimap = this.getAttributeModifiers(enumitemslot); + + if (!multimap.isEmpty()) { + list.add(CommonComponents.EMPTY); +- list.add(Component.translatable("item.modifiers." + equipmentslot.getName()).withStyle(ChatFormatting.GRAY)); ++ list.add(Component.translatable("item.modifiers." + enumitemslot.getName()).withStyle(ChatFormatting.GRAY)); + Iterator iterator = multimap.entries().iterator(); + + while (iterator.hasNext()) { +@@ -719,7 +980,7 @@ + if (player != null) { + if (attributemodifier.getId() == Item.BASE_ATTACK_DAMAGE_UUID) { + d0 += player.getAttributeBaseValue(Attributes.ATTACK_DAMAGE); +- d0 += (double) EnchantmentHelper.getDamageBonus(this, MobType.UNDEFINED); ++ d0 += (double) EnchantmentHelper.getDamageBonus(this, EnumMonsterType.UNDEFINED); + flag = true; + } else if (attributemodifier.getId() == Item.BASE_ATTACK_SPEED_UUID) { + d0 += player.getAttributeBaseValue(Attributes.ATTACK_SPEED); +@@ -753,38 +1014,38 @@ + } + + if (this.hasTag()) { +- if (shouldShowInTooltip(i, ItemStack.TooltipPart.UNBREAKABLE) && this.tag.getBoolean("Unbreakable")) { ++ if (shouldShowInTooltip(i, ItemStack.HideFlags.UNBREAKABLE) && this.tag.getBoolean("Unbreakable")) { + list.add(Component.translatable("item.unbreakable").withStyle(ChatFormatting.BLUE)); + } + +- ListTag listtag1; ++ ListTag nbttaglist1; + +- if (shouldShowInTooltip(i, ItemStack.TooltipPart.CAN_DESTROY) && this.tag.contains("CanDestroy", 9)) { +- listtag1 = this.tag.getList("CanDestroy", 8); +- if (!listtag1.isEmpty()) { ++ if (shouldShowInTooltip(i, ItemStack.HideFlags.CAN_DESTROY) && this.tag.contains("CanDestroy", 9)) { ++ nbttaglist1 = this.tag.getList("CanDestroy", 8); ++ if (!nbttaglist1.isEmpty()) { + list.add(CommonComponents.EMPTY); + list.add(Component.translatable("item.canBreak").withStyle(ChatFormatting.GRAY)); + +- for (k = 0; k < listtag1.size(); ++k) { +- list.addAll(expandBlockState(listtag1.getString(k))); ++ for (k = 0; k < nbttaglist1.size(); ++k) { ++ list.addAll(expandBlockState(nbttaglist1.getString(k))); + } + } + } + +- if (shouldShowInTooltip(i, ItemStack.TooltipPart.CAN_PLACE) && this.tag.contains("CanPlaceOn", 9)) { +- listtag1 = this.tag.getList("CanPlaceOn", 8); +- if (!listtag1.isEmpty()) { ++ if (shouldShowInTooltip(i, ItemStack.HideFlags.CAN_PLACE) && this.tag.contains("CanPlaceOn", 9)) { ++ nbttaglist1 = this.tag.getList("CanPlaceOn", 8); ++ if (!nbttaglist1.isEmpty()) { + list.add(CommonComponents.EMPTY); + list.add(Component.translatable("item.canPlace").withStyle(ChatFormatting.GRAY)); + +- for (k = 0; k < listtag1.size(); ++k) { +- list.addAll(expandBlockState(listtag1.getString(k))); ++ for (k = 0; k < nbttaglist1.size(); ++k) { ++ list.addAll(expandBlockState(nbttaglist1.getString(k))); + } + } + } + } + +- if (tooltipflag.isAdvanced()) { ++ if (isAdvanced.isAdvanced()) { + if (this.isDamaged()) { + list.add(Component.translatable("item.durability", this.getMaxDamage() - this.getDamageValue(), this.getMaxDamage())); + } +@@ -802,37 +1063,37 @@ + return list; + } + +- private static boolean shouldShowInTooltip(int i, ItemStack.TooltipPart itemstack_tooltippart) { +- return (i & itemstack_tooltippart.getMask()) == 0; ++ private static boolean shouldShowInTooltip(int hideFlags, ItemStack.HideFlags part) { ++ return (hideFlags & part.getMask()) == 0; + } + + private int getHideFlags() { + return this.hasTag() && this.tag.contains("HideFlags", 99) ? this.tag.getInt("HideFlags") : 0; + } + +- public void hideTooltipPart(ItemStack.TooltipPart itemstack_tooltippart) { +- CompoundTag compoundtag = this.getOrCreateTag(); ++ public void hideTooltipPart(ItemStack.HideFlags part) { ++ CompoundTag nbttagcompound = this.getOrCreateTag(); + +- compoundtag.putInt("HideFlags", compoundtag.getInt("HideFlags") | itemstack_tooltippart.getMask()); ++ nbttagcompound.putInt("HideFlags", nbttagcompound.getInt("HideFlags") | part.getMask()); + } + +- public static void appendEnchantmentNames(List list, ListTag listtag) { +- for (int i = 0; i < listtag.size(); ++i) { +- CompoundTag compoundtag = listtag.getCompound(i); ++ public static void appendEnchantmentNames(List tooltipComponents, ListTag storedEnchantments) { ++ for (int i = 0; i < storedEnchantments.size(); ++i) { ++ CompoundTag nbttagcompound = storedEnchantments.getCompound(i); + +- BuiltInRegistries.ENCHANTMENT.getOptional(EnchantmentHelper.getEnchantmentId(compoundtag)).ifPresent((enchantment) -> { +- list.add(enchantment.getFullname(EnchantmentHelper.getEnchantmentLevel(compoundtag))); ++ BuiltInRegistries.ENCHANTMENT.getOptional(EnchantmentHelper.getEnchantmentId(nbttagcompound)).ifPresent((enchantment) -> { ++ tooltipComponents.add(enchantment.getFullname(EnchantmentHelper.getEnchantmentLevel(nbttagcompound))); + }); + } + + } + +- private static Collection expandBlockState(String s) { ++ private static Collection expandBlockState(String stateString) { + try { +- return (Collection) BlockStateParser.parseForTesting(BuiltInRegistries.BLOCK.asLookup(), s, true).map((blockstateparser_blockresult) -> { +- return Lists.newArrayList(new Component[]{blockstateparser_blockresult.blockState().getBlock().getName().withStyle(ChatFormatting.DARK_GRAY)}); +- }, (blockstateparser_tagresult) -> { +- return (List) blockstateparser_tagresult.tag().stream().map((holder) -> { ++ return (Collection) BlockStateParser.parseForTesting(BuiltInRegistries.BLOCK.asLookup(), stateString, true).map((argumentblock_a) -> { ++ return Lists.newArrayList(new Component[]{argumentblock_a.blockState().getBlock().getName().withStyle(ChatFormatting.DARK_GRAY)}); ++ }, (argumentblock_b) -> { ++ return (List) argumentblock_b.tag().stream().map((holder) -> { + return ((Block) holder.value()).getName().withStyle(ChatFormatting.DARK_GRAY); + }).collect(Collectors.toList()); + }); +@@ -853,23 +1114,23 @@ + return !this.getItem().isEnchantable(this) ? false : !this.isEnchanted(); + } + +- public void enchant(Enchantment enchantment, int i) { ++ public void enchant(Enchantment enchantment, int level) { + this.getOrCreateTag(); + if (!this.tag.contains("Enchantments", 9)) { + this.tag.put("Enchantments", new ListTag()); + } + +- ListTag listtag = this.tag.getList("Enchantments", 10); ++ ListTag nbttaglist = this.tag.getList("Enchantments", 10); + +- listtag.add(EnchantmentHelper.storeEnchantment(EnchantmentHelper.getEnchantmentId(enchantment), (byte) i)); ++ nbttaglist.add(EnchantmentHelper.storeEnchantment(EnchantmentHelper.getEnchantmentId(enchantment), (byte) level)); + } + + public boolean isEnchanted() { + return this.tag != null && this.tag.contains("Enchantments", 9) ? !this.tag.getList("Enchantments", 10).isEmpty() : false; + } + +- public void addTagElement(String s, Tag tag) { +- this.getOrCreateTag().put(s, tag); ++ public void addTagElement(String key, Tag tag) { ++ this.getOrCreateTag().put(key, tag); + } + + public boolean isFramed() { +@@ -894,30 +1155,30 @@ + return this.hasTag() && this.tag.contains("RepairCost", 3) ? this.tag.getInt("RepairCost") : 0; + } + +- public void setRepairCost(int i) { +- if (i > 0) { +- this.getOrCreateTag().putInt("RepairCost", i); ++ public void setRepairCost(int cost) { ++ if (cost > 0) { ++ this.getOrCreateTag().putInt("RepairCost", cost); + } else { + this.removeTagKey("RepairCost"); + } + + } + +- public Multimap getAttributeModifiers(EquipmentSlot equipmentslot) { ++ public Multimap getAttributeModifiers(EquipmentSlot slot) { + Object object; + + if (this.hasTag() && this.tag.contains("AttributeModifiers", 9)) { + object = HashMultimap.create(); +- ListTag listtag = this.tag.getList("AttributeModifiers", 10); ++ ListTag nbttaglist = this.tag.getList("AttributeModifiers", 10); + +- for (int i = 0; i < listtag.size(); ++i) { +- CompoundTag compoundtag = listtag.getCompound(i); ++ for (int i = 0; i < nbttaglist.size(); ++i) { ++ CompoundTag nbttagcompound = nbttaglist.getCompound(i); + +- if (!compoundtag.contains("Slot", 8) || compoundtag.getString("Slot").equals(equipmentslot.getName())) { +- Optional optional = BuiltInRegistries.ATTRIBUTE.getOptional(ResourceLocation.tryParse(compoundtag.getString("AttributeName"))); ++ if (!nbttagcompound.contains("Slot", 8) || nbttagcompound.getString("Slot").equals(slot.getName())) { ++ Optional optional = BuiltInRegistries.ATTRIBUTE.getOptional(ResourceLocation.tryParse(nbttagcompound.getString("AttributeName"))); + + if (!optional.isEmpty()) { +- AttributeModifier attributemodifier = AttributeModifier.load(compoundtag); ++ AttributeModifier attributemodifier = AttributeModifier.load(nbttagcompound); + + if (attributemodifier != null && attributemodifier.getId().getLeastSignificantBits() != 0L && attributemodifier.getId().getMostSignificantBits() != 0L) { + ((Multimap) object).put((Attribute) optional.get(), attributemodifier); +@@ -926,93 +1187,100 @@ + } + } + } else { +- object = this.getItem().getDefaultAttributeModifiers(equipmentslot); ++ object = this.getItem().getDefaultAttributeModifiers(slot); + } + + return (Multimap) object; + } + +- public void addAttributeModifier(Attribute attribute, AttributeModifier attributemodifier, @Nullable EquipmentSlot equipmentslot) { ++ public void addAttributeModifier(Attribute attribute, AttributeModifier modifier, @Nullable EquipmentSlot slot) { + this.getOrCreateTag(); + if (!this.tag.contains("AttributeModifiers", 9)) { + this.tag.put("AttributeModifiers", new ListTag()); + } + +- ListTag listtag = this.tag.getList("AttributeModifiers", 10); +- CompoundTag compoundtag = attributemodifier.save(); ++ ListTag nbttaglist = this.tag.getList("AttributeModifiers", 10); ++ CompoundTag nbttagcompound = modifier.save(); + +- compoundtag.putString("AttributeName", BuiltInRegistries.ATTRIBUTE.getKey(attribute).toString()); +- if (equipmentslot != null) { +- compoundtag.putString("Slot", equipmentslot.getName()); ++ nbttagcompound.putString("AttributeName", BuiltInRegistries.ATTRIBUTE.getKey(attribute).toString()); ++ if (slot != null) { ++ nbttagcompound.putString("Slot", slot.getName()); + } + +- listtag.add(compoundtag); ++ nbttaglist.add(nbttagcompound); + } + ++ // CraftBukkit start ++ @Deprecated ++ public void setItem(Item item) { ++ this.item = item; ++ } ++ // CraftBukkit end ++ + public Component getDisplayName() { +- MutableComponent mutablecomponent = Component.empty().append(this.getHoverName()); ++ MutableComponent ichatmutablecomponent = Component.empty().append(this.getHoverName()); + + if (this.hasCustomHoverName()) { +- mutablecomponent.withStyle(ChatFormatting.ITALIC); ++ ichatmutablecomponent.withStyle(ChatFormatting.ITALIC); + } + +- MutableComponent mutablecomponent1 = ComponentUtils.wrapInSquareBrackets(mutablecomponent); ++ MutableComponent ichatmutablecomponent1 = ComponentUtils.wrapInSquareBrackets(ichatmutablecomponent); + + if (!this.isEmpty()) { +- mutablecomponent1.withStyle(this.getRarity().color).withStyle((style) -> { +- return style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_ITEM, new HoverEvent.ItemStackInfo(this))); ++ ichatmutablecomponent1.withStyle(this.getRarity().color).withStyle((chatmodifier) -> { ++ return chatmodifier.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_ITEM, new HoverEvent.ItemStackInfo(this))); + }); + } + +- return mutablecomponent1; ++ return ichatmutablecomponent1; + } + +- public boolean hasAdventureModePlaceTagForBlock(Registry registry, BlockInWorld blockinworld) { ++ public boolean hasAdventureModePlaceTagForBlock(Registry blockRegistry, BlockInWorld block) { + if (this.adventurePlaceCheck == null) { + this.adventurePlaceCheck = new AdventureModeCheck("CanPlaceOn"); + } + +- return this.adventurePlaceCheck.test(this, registry, blockinworld); ++ return this.adventurePlaceCheck.test(this, blockRegistry, block); + } + +- public boolean hasAdventureModeBreakTagForBlock(Registry registry, BlockInWorld blockinworld) { ++ public boolean hasAdventureModeBreakTagForBlock(Registry blockRegistry, BlockInWorld block) { + if (this.adventureBreakCheck == null) { + this.adventureBreakCheck = new AdventureModeCheck("CanDestroy"); + } + +- return this.adventureBreakCheck.test(this, registry, blockinworld); ++ return this.adventureBreakCheck.test(this, blockRegistry, block); + } + + public int getPopTime() { + return this.popTime; + } + +- public void setPopTime(int i) { +- this.popTime = i; ++ public void setPopTime(int popTime) { ++ this.popTime = popTime; + } + + public int getCount() { + return this.isEmpty() ? 0 : this.count; + } + +- public void setCount(int i) { +- this.count = i; ++ public void setCount(int count) { ++ this.count = count; + } + +- public void grow(int i) { +- this.setCount(this.getCount() + i); ++ public void grow(int increment) { ++ this.setCount(this.getCount() + increment); + } + +- public void shrink(int i) { +- this.grow(-i); ++ public void shrink(int decrement) { ++ this.grow(-decrement); + } + +- public void onUseTick(Level level, LivingEntity livingentity, int i) { +- this.getItem().onUseTick(level, livingentity, this, i); ++ public void onUseTick(Level level, LivingEntity livingEntity, int count) { ++ this.getItem().onUseTick(level, livingEntity, this, count); + } + +- public void onDestroyed(ItemEntity itementity) { +- this.getItem().onDestroyed(itementity); ++ public void onDestroyed(ItemEntity itemEntity) { ++ this.getItem().onDestroyed(itemEntity); + } + + public boolean isEdible() { +@@ -1027,13 +1295,13 @@ + return this.getItem().getEatingSound(); + } + +- public static enum TooltipPart { ++ public static enum HideFlags { + + ENCHANTMENTS, MODIFIERS, UNBREAKABLE, CAN_DESTROY, CAN_PLACE, ADDITIONAL, DYE, UPGRADES; + + private final int mask = 1 << this.ordinal(); + +- private TooltipPart() {} ++ private HideFlags() {} + + public int getMask() { + return this.mask; diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/LeadItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/LeadItem.java.patch new file mode 100644 index 0000000000..3e499c1786 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/LeadItem.java.patch @@ -0,0 +1,119 @@ +--- a/net/minecraft/world/item/LeadItem.java ++++ b/net/minecraft/world/item/LeadItem.java +@@ -11,64 +11,90 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; ++// CraftBukkit start ++import org.bukkit.craftbukkit.CraftEquipmentSlot; ++import org.bukkit.event.hanging.HangingPlaceEvent; ++// CraftBukkit end + + public class LeadItem extends Item { + +- public LeadItem(Item.Properties item_properties) { +- super(item_properties); ++ public LeadItem(Item.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public InteractionResult useOn(UseOnContext useoncontext) { +- Level level = useoncontext.getLevel(); +- BlockPos blockpos = useoncontext.getClickedPos(); +- BlockState blockstate = level.getBlockState(blockpos); ++ public InteractionResult useOn(UseOnContext context) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ IBlockData iblockdata = world.getBlockState(blockposition); + +- if (blockstate.is(BlockTags.FENCES)) { +- Player player = useoncontext.getPlayer(); ++ if (iblockdata.is(BlockTags.FENCES)) { ++ Player entityhuman = context.getPlayer(); + +- if (!level.isClientSide && player != null) { +- bindPlayerMobs(player, level, blockpos); ++ if (!world.isClientSide && entityhuman != null) { ++ bindPlayerMobs(entityhuman, world, blockposition, context.getHand()); // CraftBukkit - Pass hand + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } else { + return InteractionResult.PASS; + } + } + +- public static InteractionResult bindPlayerMobs(Player player, Level level, BlockPos blockpos) { +- LeashFenceKnotEntity leashfenceknotentity = null; ++ public static InteractionResult bindPlayerMobs(Player entityhuman, Level world, BlockPos blockposition, net.minecraft.world.EnumHand enumhand) { // CraftBukkit - Add EnumHand ++ LeashFenceKnotEntity entityleash = null; + boolean flag = false; + double d0 = 7.0D; +- int i = blockpos.getX(); +- int j = blockpos.getY(); +- int k = blockpos.getZ(); +- List list = level.getEntitiesOfClass(Mob.class, new AABB((double) i - 7.0D, (double) j - 7.0D, (double) k - 7.0D, (double) i + 7.0D, (double) j + 7.0D, (double) k + 7.0D)); ++ int i = blockposition.getX(); ++ int j = blockposition.getY(); ++ int k = blockposition.getZ(); ++ List list = world.getEntitiesOfClass(Mob.class, new AABB((double) i - 7.0D, (double) j - 7.0D, (double) k - 7.0D, (double) i + 7.0D, (double) j + 7.0D, (double) k + 7.0D)); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- Mob mob = (Mob) iterator.next(); ++ Mob entityinsentient = (Mob) iterator.next(); + +- if (mob.getLeashHolder() == player) { +- if (leashfenceknotentity == null) { +- leashfenceknotentity = LeashFenceKnotEntity.getOrCreateKnot(level, blockpos); +- leashfenceknotentity.playPlacementSound(); ++ if (entityinsentient.getLeashHolder() == entityhuman) { ++ if (entityleash == null) { ++ entityleash = LeashFenceKnotEntity.getOrCreateKnot(world, blockposition); ++ ++ // CraftBukkit start - fire HangingPlaceEvent ++ org.bukkit.inventory.EquipmentSlot hand = CraftEquipmentSlot.getHand(enumhand); ++ HangingPlaceEvent event = new HangingPlaceEvent((org.bukkit.entity.Hanging) entityleash.getBukkitEntity(), entityhuman != null ? (org.bukkit.entity.Player) entityhuman.getBukkitEntity() : null, world.getWorld().getBlockAt(i, j, k), org.bukkit.block.BlockFace.SELF, hand); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ entityleash.discard(); ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end ++ entityleash.playPlacementSound(); + } + +- mob.setLeashedTo(leashfenceknotentity, true); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerLeashEntityEvent(entityinsentient, entityleash, entityhuman, enumhand).isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end ++ ++ entityinsentient.setLeashedTo(entityleash, true); + flag = true; + } + } + + if (flag) { +- level.gameEvent(GameEvent.BLOCK_ATTACH, blockpos, GameEvent.Context.of((Entity) player)); ++ world.gameEvent(GameEvent.BLOCK_ATTACH, blockposition, GameEvent.Context.of((Entity) entityhuman)); + } + + return flag ? InteractionResult.SUCCESS : InteractionResult.PASS; + } ++ ++ // CraftBukkit start ++ public static InteractionResult bindPlayerMobs(Player player, Level level, BlockPos pos) { ++ return bindPlayerMobs(player, level, pos, net.minecraft.world.EnumHand.MAIN_HAND); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/MapItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/MapItem.java.patch new file mode 100644 index 0000000000..393489499f --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/MapItem.java.patch @@ -0,0 +1,548 @@ +--- a/net/minecraft/world/item/MapItem.java ++++ b/net/minecraft/world/item/MapItem.java +@@ -26,7 +26,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.biome.Biome; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.level.levelgen.Heightmap; + import net.minecraft.world.level.material.FluidState; +@@ -42,80 +42,80 @@ + public static final String MAP_SCALE_TAG = "map_scale_direction"; + public static final String MAP_LOCK_TAG = "map_to_lock"; + +- public MapItem(Item.Properties item_properties) { +- super(item_properties); ++ public MapItem(Item.Properties properties) { ++ super(properties); + } + +- public static ItemStack create(Level level, int i, int j, byte b0, boolean flag, boolean flag1) { ++ public static ItemStack create(Level level, int levelX, int levelZ, byte scale, boolean trackingPosition, boolean unlimitedTracking) { + ItemStack itemstack = new ItemStack(Items.FILLED_MAP); + +- createAndStoreSavedData(itemstack, level, i, j, b0, flag, flag1, level.dimension()); ++ createAndStoreSavedData(itemstack, level, levelX, levelZ, scale, trackingPosition, unlimitedTracking, level.dimension()); + return itemstack; + } + + @Nullable +- public static MapItemSavedData getSavedData(@Nullable Integer integer, Level level) { +- return integer == null ? null : level.getMapData(makeKey(integer)); ++ public static MapItemSavedData getSavedData(@Nullable Integer mapId, Level level) { ++ return mapId == null ? null : level.getMapData(makeKey(mapId)); + } + + @Nullable +- public static MapItemSavedData getSavedData(ItemStack itemstack, Level level) { +- Integer integer = getMapId(itemstack); ++ public static MapItemSavedData getSavedData(ItemStack stack, Level level) { ++ Integer integer = getMapId(stack); + + return getSavedData(integer, level); + } + + @Nullable +- public static Integer getMapId(ItemStack itemstack) { +- CompoundTag compoundtag = itemstack.getTag(); ++ public static Integer getMapId(ItemStack stack) { ++ CompoundTag nbttagcompound = stack.getTag(); + +- return compoundtag != null && compoundtag.contains("map", 99) ? compoundtag.getInt("map") : null; ++ return nbttagcompound != null && nbttagcompound.contains("map", 99) ? nbttagcompound.getInt("map") : -1; // CraftBukkit - make new maps for no tag + } + +- private static int createNewSavedData(Level level, int i, int j, int k, boolean flag, boolean flag1, ResourceKey resourcekey) { +- MapItemSavedData mapitemsaveddata = MapItemSavedData.createFresh((double) i, (double) j, (byte) k, flag, flag1, resourcekey); ++ public static int createNewSavedData(Level level, int x, int z, int scale, boolean trackingPosition, boolean unlimitedTracking, ResourceKey dimension) { ++ MapItemSavedData worldmap = MapItemSavedData.createFresh((double) x, (double) z, (byte) scale, trackingPosition, unlimitedTracking, dimension); + int l = level.getFreeMapId(); + +- level.setMapData(makeKey(l), mapitemsaveddata); ++ level.setMapData(makeKey(l), worldmap); + return l; + } + +- private static void storeMapData(ItemStack itemstack, int i) { +- itemstack.getOrCreateTag().putInt("map", i); ++ private static void storeMapData(ItemStack stack, int mapId) { ++ stack.getOrCreateTag().putInt("map", mapId); + } + +- private static void createAndStoreSavedData(ItemStack itemstack, Level level, int i, int j, int k, boolean flag, boolean flag1, ResourceKey resourcekey) { +- int l = createNewSavedData(level, i, j, k, flag, flag1, resourcekey); ++ private static void createAndStoreSavedData(ItemStack stack, Level level, int x, int z, int scale, boolean trackingPosition, boolean unlimitedTracking, ResourceKey dimension) { ++ int l = createNewSavedData(level, x, z, scale, trackingPosition, unlimitedTracking, dimension); + +- storeMapData(itemstack, l); ++ storeMapData(stack, l); + } + +- public static String makeKey(int i) { +- return "map_" + i; ++ public static String makeKey(int mapId) { ++ return "map_" + mapId; + } + +- public void update(Level level, Entity entity, MapItemSavedData mapitemsaveddata) { +- if (level.dimension() == mapitemsaveddata.dimension && entity instanceof Player) { +- int i = 1 << mapitemsaveddata.scale; +- int j = mapitemsaveddata.centerX; +- int k = mapitemsaveddata.centerZ; +- int l = Mth.floor(entity.getX() - (double) j) / i + 64; +- int i1 = Mth.floor(entity.getZ() - (double) k) / i + 64; ++ public void update(Level level, Entity viewer, MapItemSavedData data) { ++ if (level.dimension() == data.dimension && viewer instanceof Player) { ++ int i = 1 << data.scale; ++ int j = data.centerX; ++ int k = data.centerZ; ++ int l = Mth.floor(viewer.getX() - (double) j) / i + 64; ++ int i1 = Mth.floor(viewer.getZ() - (double) k) / i + 64; + int j1 = 128 / i; + + if (level.dimensionType().hasCeiling()) { + j1 /= 2; + } + +- MapItemSavedData.HoldingPlayer mapitemsaveddata_holdingplayer = mapitemsaveddata.getHoldingPlayer((Player) entity); ++ MapItemSavedData.HoldingPlayer worldmap_worldmaphumantracker = data.getHoldingPlayer((Player) viewer); + +- ++mapitemsaveddata_holdingplayer.step; +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); +- BlockPos.MutableBlockPos blockpos_mutableblockpos1 = new BlockPos.MutableBlockPos(); ++ ++worldmap_worldmaphumantracker.step; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition1 = new BlockPos.MutableBlockPos(); + boolean flag = false; + + for (int k1 = l - j1 + 1; k1 < l + j1; ++k1) { +- if ((k1 & 15) == (mapitemsaveddata_holdingplayer.step & 15) || flag) { ++ if ((k1 & 15) == (worldmap_worldmaphumantracker.step & 15) || flag) { + flag = false; + double d0 = 0.0D; + +@@ -126,9 +126,9 @@ + int j2 = (j / i + k1 - 64) * i; + int k2 = (k / i + l1 - 64) * i; + Multiset multiset = LinkedHashMultiset.create(); +- LevelChunk levelchunk = level.getChunk(SectionPos.blockToSectionCoord(j2), SectionPos.blockToSectionCoord(k2)); ++ LevelChunk chunk = level.getChunk(SectionPos.blockToSectionCoord(j2), SectionPos.blockToSectionCoord(k2)); + +- if (!levelchunk.isEmpty()) { ++ if (!chunk.isEmpty()) { + int l2 = 0; + double d1 = 0.0D; + int i3; +@@ -146,71 +146,71 @@ + } else { + for (i3 = 0; i3 < i; ++i3) { + for (int j3 = 0; j3 < i; ++j3) { +- blockpos_mutableblockpos.set(j2 + i3, 0, k2 + j3); +- int k3 = levelchunk.getHeight(Heightmap.Types.WORLD_SURFACE, blockpos_mutableblockpos.getX(), blockpos_mutableblockpos.getZ()) + 1; +- BlockState blockstate; ++ blockposition_mutableblockposition.set(j2 + i3, 0, k2 + j3); ++ int k3 = chunk.getHeight(Heightmap.Types.WORLD_SURFACE, blockposition_mutableblockposition.getX(), blockposition_mutableblockposition.getZ()) + 1; ++ IBlockData iblockdata; + + if (k3 > level.getMinBuildHeight() + 1) { + do { + --k3; +- blockpos_mutableblockpos.setY(k3); +- blockstate = levelchunk.getBlockState(blockpos_mutableblockpos); +- } while (blockstate.getMapColor(level, blockpos_mutableblockpos) == MapColor.NONE && k3 > level.getMinBuildHeight()); ++ blockposition_mutableblockposition.setY(k3); ++ iblockdata = chunk.getBlockState(blockposition_mutableblockposition); ++ } while (iblockdata.getMapColor(level, blockposition_mutableblockposition) == MapColor.NONE && k3 > level.getMinBuildHeight()); + +- if (k3 > level.getMinBuildHeight() && !blockstate.getFluidState().isEmpty()) { ++ if (k3 > level.getMinBuildHeight() && !iblockdata.getFluidState().isEmpty()) { + int l3 = k3 - 1; + +- blockpos_mutableblockpos1.set(blockpos_mutableblockpos); ++ blockposition_mutableblockposition1.set(blockposition_mutableblockposition); + +- BlockState blockstate1; ++ IBlockData iblockdata1; + + do { +- blockpos_mutableblockpos1.setY(l3--); +- blockstate1 = levelchunk.getBlockState(blockpos_mutableblockpos1); ++ blockposition_mutableblockposition1.setY(l3--); ++ iblockdata1 = chunk.getBlockState(blockposition_mutableblockposition1); + ++l2; +- } while (l3 > level.getMinBuildHeight() && !blockstate1.getFluidState().isEmpty()); ++ } while (l3 > level.getMinBuildHeight() && !iblockdata1.getFluidState().isEmpty()); + +- blockstate = this.getCorrectStateForFluidBlock(level, blockstate, blockpos_mutableblockpos); ++ iblockdata = this.getCorrectStateForFluidBlock(level, iblockdata, blockposition_mutableblockposition); + } + } else { +- blockstate = Blocks.BEDROCK.defaultBlockState(); ++ iblockdata = Blocks.BEDROCK.defaultBlockState(); + } + +- mapitemsaveddata.checkBanners(level, blockpos_mutableblockpos.getX(), blockpos_mutableblockpos.getZ()); ++ data.checkBanners(level, blockposition_mutableblockposition.getX(), blockposition_mutableblockposition.getZ()); + d1 += (double) k3 / (double) (i * i); +- multiset.add(blockstate.getMapColor(level, blockpos_mutableblockpos)); ++ multiset.add(iblockdata.getMapColor(level, blockposition_mutableblockposition)); + } + } + } + + l2 /= i * i; +- MapColor mapcolor = (MapColor) Iterables.getFirst(Multisets.copyHighestCountFirst(multiset), MapColor.NONE); ++ MapColor materialmapcolor = (MapColor) Iterables.getFirst(Multisets.copyHighestCountFirst(multiset), MapColor.NONE); + double d2; +- MapColor.Brightness mapcolor_brightness; ++ MapColor.Brightness materialmapcolor_a; + +- if (mapcolor == MapColor.WATER) { ++ if (materialmapcolor == MapColor.WATER) { + d2 = (double) l2 * 0.1D + (double) (k1 + l1 & 1) * 0.2D; + if (d2 < 0.5D) { +- mapcolor_brightness = MapColor.Brightness.HIGH; ++ materialmapcolor_a = MapColor.Brightness.HIGH; + } else if (d2 > 0.9D) { +- mapcolor_brightness = MapColor.Brightness.LOW; ++ materialmapcolor_a = MapColor.Brightness.LOW; + } else { +- mapcolor_brightness = MapColor.Brightness.NORMAL; ++ materialmapcolor_a = MapColor.Brightness.NORMAL; + } + } else { + d2 = (d1 - d0) * 4.0D / (double) (i + 4) + ((double) (k1 + l1 & 1) - 0.5D) * 0.4D; + if (d2 > 0.6D) { +- mapcolor_brightness = MapColor.Brightness.HIGH; ++ materialmapcolor_a = MapColor.Brightness.HIGH; + } else if (d2 < -0.6D) { +- mapcolor_brightness = MapColor.Brightness.LOW; ++ materialmapcolor_a = MapColor.Brightness.LOW; + } else { +- mapcolor_brightness = MapColor.Brightness.NORMAL; ++ materialmapcolor_a = MapColor.Brightness.NORMAL; + } + } + + d0 = d1; + if (l1 >= 0 && i2 < j1 * j1 && (!flag1 || (k1 + l1 & 1) != 0)) { +- flag |= mapitemsaveddata.updateColor(k1, l1, mapcolor.getPackedId(mapcolor_brightness)); ++ flag |= data.updateColor(k1, l1, materialmapcolor.getPackedId(materialmapcolor_a)); + } + } + } +@@ -221,35 +221,35 @@ + } + } + +- private BlockState getCorrectStateForFluidBlock(Level level, BlockState blockstate, BlockPos blockpos) { +- FluidState fluidstate = blockstate.getFluidState(); ++ private IBlockData getCorrectStateForFluidBlock(Level level, IBlockData state, BlockPos pos) { ++ FluidState fluid = state.getFluidState(); + +- return !fluidstate.isEmpty() && !blockstate.isFaceSturdy(level, blockpos, Direction.UP) ? fluidstate.createLegacyBlock() : blockstate; ++ return !fluid.isEmpty() && !state.isFaceSturdy(level, pos, Direction.UP) ? fluid.createLegacyBlock() : state; + } + +- private static boolean isBiomeWatery(boolean[] aboolean, int i, int j) { +- return aboolean[j * 128 + i]; ++ private static boolean isBiomeWatery(boolean[] wateryMap, int xSample, int zSample) { ++ return wateryMap[zSample * 128 + xSample]; + } + +- public static void renderBiomePreviewMap(ServerLevel serverlevel, ItemStack itemstack) { +- MapItemSavedData mapitemsaveddata = getSavedData(itemstack, serverlevel); ++ public static void renderBiomePreviewMap(ServerLevel serverLevel, ItemStack stack) { ++ MapItemSavedData worldmap = getSavedData(stack, serverLevel); + +- if (mapitemsaveddata != null) { +- if (serverlevel.dimension() == mapitemsaveddata.dimension) { +- int i = 1 << mapitemsaveddata.scale; +- int j = mapitemsaveddata.centerX; +- int k = mapitemsaveddata.centerZ; ++ if (worldmap != null) { ++ if (serverLevel.dimension() == worldmap.dimension) { ++ int i = 1 << worldmap.scale; ++ int j = worldmap.centerX; ++ int k = worldmap.centerZ; + boolean[] aboolean = new boolean[16384]; + int l = j / i - 64; + int i1 = k / i - 64; +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + + int j1; + int k1; + + for (j1 = 0; j1 < 128; ++j1) { + for (k1 = 0; k1 < 128; ++k1) { +- Holder holder = serverlevel.getBiome(blockpos_mutableblockpos.set((l + k1) * i, 0, (i1 + j1) * i)); ++ Holder holder = serverLevel.getBiome(blockposition_mutableblockposition.set((l + k1) * i, 0, (i1 + j1) * i)); + + aboolean[j1 * 128 + k1] = holder.is(BiomeTags.WATER_ON_MAP_OUTLINES); + } +@@ -267,44 +267,44 @@ + } + } + +- MapColor.Brightness mapcolor_brightness = MapColor.Brightness.LOWEST; +- MapColor mapcolor = MapColor.NONE; ++ MapColor.Brightness materialmapcolor_a = MapColor.Brightness.LOWEST; ++ MapColor materialmapcolor = MapColor.NONE; + + if (isBiomeWatery(aboolean, j1, k1)) { +- mapcolor = MapColor.COLOR_ORANGE; ++ materialmapcolor = MapColor.COLOR_ORANGE; + if (l1 > 7 && k1 % 2 == 0) { + switch ((j1 + (int) (Mth.sin((float) k1 + 0.0F) * 7.0F)) / 8 % 5) { + case 0: + case 4: +- mapcolor_brightness = MapColor.Brightness.LOW; ++ materialmapcolor_a = MapColor.Brightness.LOW; + break; + case 1: + case 3: +- mapcolor_brightness = MapColor.Brightness.NORMAL; ++ materialmapcolor_a = MapColor.Brightness.NORMAL; + break; + case 2: +- mapcolor_brightness = MapColor.Brightness.HIGH; ++ materialmapcolor_a = MapColor.Brightness.HIGH; + } + } else if (l1 > 7) { +- mapcolor = MapColor.NONE; ++ materialmapcolor = MapColor.NONE; + } else if (l1 > 5) { +- mapcolor_brightness = MapColor.Brightness.NORMAL; ++ materialmapcolor_a = MapColor.Brightness.NORMAL; + } else if (l1 > 3) { +- mapcolor_brightness = MapColor.Brightness.LOW; ++ materialmapcolor_a = MapColor.Brightness.LOW; + } else if (l1 > 1) { +- mapcolor_brightness = MapColor.Brightness.LOW; ++ materialmapcolor_a = MapColor.Brightness.LOW; + } + } else if (l1 > 0) { +- mapcolor = MapColor.COLOR_BROWN; ++ materialmapcolor = MapColor.COLOR_BROWN; + if (l1 > 3) { +- mapcolor_brightness = MapColor.Brightness.NORMAL; ++ materialmapcolor_a = MapColor.Brightness.NORMAL; + } else { +- mapcolor_brightness = MapColor.Brightness.LOWEST; ++ materialmapcolor_a = MapColor.Brightness.LOWEST; + } + } + +- if (mapcolor != MapColor.NONE) { +- mapitemsaveddata.setColor(j1, k1, mapcolor.getPackedId(mapcolor_brightness)); ++ if (materialmapcolor != MapColor.NONE) { ++ worldmap.setColor(j1, k1, materialmapcolor.getPackedId(materialmapcolor_a)); + } + } + } +@@ -314,20 +314,19 @@ + } + + @Override +- @Override +- public void inventoryTick(ItemStack itemstack, Level level, Entity entity, int i, boolean flag) { ++ public void inventoryTick(ItemStack stack, Level level, Entity entity, int itemSlot, boolean isSelected) { + if (!level.isClientSide) { +- MapItemSavedData mapitemsaveddata = getSavedData(itemstack, level); ++ MapItemSavedData worldmap = getSavedData(stack, level); + +- if (mapitemsaveddata != null) { ++ if (worldmap != null) { + if (entity instanceof Player) { +- Player player = (Player) entity; ++ Player entityhuman = (Player) entity; + +- mapitemsaveddata.tickCarriedBy(player, itemstack); ++ worldmap.tickCarriedBy(entityhuman, stack); + } + +- if (!mapitemsaveddata.locked && (flag || entity instanceof Player && ((Player) entity).getOffhandItem() == itemstack)) { +- this.update(level, entity, mapitemsaveddata); ++ if (!worldmap.locked && (isSelected || entity instanceof Player && ((Player) entity).getOffhandItem() == stack)) { ++ this.update(level, entity, worldmap); + } + + } +@@ -336,88 +335,85 @@ + + @Nullable + @Override +- @Override +- public Packet getUpdatePacket(ItemStack itemstack, Level level, Player player) { +- Integer integer = getMapId(itemstack); +- MapItemSavedData mapitemsaveddata = getSavedData(integer, level); ++ public Packet getUpdatePacket(ItemStack stack, Level level, Player player) { ++ Integer integer = getMapId(stack); ++ MapItemSavedData worldmap = getSavedData(integer, level); + +- return mapitemsaveddata != null ? mapitemsaveddata.getUpdatePacket(integer, player) : null; ++ return worldmap != null ? worldmap.getUpdatePacket(integer, player) : null; + } + + @Override +- @Override +- public void onCraftedPostProcess(ItemStack itemstack, Level level) { +- CompoundTag compoundtag = itemstack.getTag(); ++ public void onCraftedPostProcess(ItemStack itemstack, Level world) { ++ CompoundTag nbttagcompound = itemstack.getTag(); + +- if (compoundtag != null && compoundtag.contains("map_scale_direction", 99)) { +- scaleMap(itemstack, level, compoundtag.getInt("map_scale_direction")); +- compoundtag.remove("map_scale_direction"); +- } else if (compoundtag != null && compoundtag.contains("map_to_lock", 1) && compoundtag.getBoolean("map_to_lock")) { +- lockMap(level, itemstack); +- compoundtag.remove("map_to_lock"); ++ if (nbttagcompound != null && nbttagcompound.contains("map_scale_direction", 99)) { ++ scaleMap(itemstack, world, nbttagcompound.getInt("map_scale_direction")); ++ nbttagcompound.remove("map_scale_direction"); ++ } else if (nbttagcompound != null && nbttagcompound.contains("map_to_lock", 1) && nbttagcompound.getBoolean("map_to_lock")) { ++ lockMap(world, itemstack); ++ nbttagcompound.remove("map_to_lock"); + } + + } + +- private static void scaleMap(ItemStack itemstack, Level level, int i) { +- MapItemSavedData mapitemsaveddata = getSavedData(itemstack, level); ++ private static void scaleMap(ItemStack stack, Level level, int scale) { ++ MapItemSavedData worldmap = getSavedData(stack, level); + +- if (mapitemsaveddata != null) { ++ if (worldmap != null) { + int j = level.getFreeMapId(); + +- level.setMapData(makeKey(j), mapitemsaveddata.scaled(i)); +- storeMapData(itemstack, j); ++ level.setMapData(makeKey(j), worldmap.scaled(scale)); ++ storeMapData(stack, j); + } + + } + +- public static void lockMap(Level level, ItemStack itemstack) { +- MapItemSavedData mapitemsaveddata = getSavedData(itemstack, level); ++ public static void lockMap(Level level, ItemStack stack) { ++ MapItemSavedData worldmap = getSavedData(stack, level); + +- if (mapitemsaveddata != null) { ++ if (worldmap != null) { + int i = level.getFreeMapId(); + String s = makeKey(i); +- MapItemSavedData mapitemsaveddata1 = mapitemsaveddata.locked(); ++ MapItemSavedData worldmap1 = worldmap.locked(); + +- level.setMapData(s, mapitemsaveddata1); +- storeMapData(itemstack, i); ++ level.setMapData(s, worldmap1); ++ storeMapData(stack, i); + } + + } + + @Override +- @Override +- public void appendHoverText(ItemStack itemstack, @Nullable Level level, List list, TooltipFlag tooltipflag) { +- Integer integer = getMapId(itemstack); +- MapItemSavedData mapitemsaveddata = level == null ? null : getSavedData(integer, level); +- CompoundTag compoundtag = itemstack.getTag(); ++ public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { ++ Integer integer = getMapId(stack); ++ MapItemSavedData worldmap = level == null ? null : getSavedData(integer, level); ++ CompoundTag nbttagcompound = stack.getTag(); + boolean flag; + byte b0; + +- if (compoundtag != null) { +- flag = compoundtag.getBoolean("map_to_lock"); +- b0 = compoundtag.getByte("map_scale_direction"); ++ if (nbttagcompound != null) { ++ flag = nbttagcompound.getBoolean("map_to_lock"); ++ b0 = nbttagcompound.getByte("map_scale_direction"); + } else { + flag = false; + b0 = 0; + } + +- if (mapitemsaveddata != null && (mapitemsaveddata.locked || flag)) { +- list.add(Component.translatable("filled_map.locked", integer).withStyle(ChatFormatting.GRAY)); ++ if (worldmap != null && (worldmap.locked || flag)) { ++ tooltip.add(Component.translatable("filled_map.locked", integer).withStyle(ChatFormatting.GRAY)); + } + +- if (tooltipflag.isAdvanced()) { +- if (mapitemsaveddata != null) { ++ if (flag.isAdvanced()) { ++ if (worldmap != null) { + if (!flag && b0 == 0) { +- list.add(getTooltipForId(integer)); ++ tooltip.add(getTooltipForId(integer)); + } + +- int i = Math.min(mapitemsaveddata.scale + b0, 4); ++ int i = Math.min(worldmap.scale + b0, 4); + +- list.add(Component.translatable("filled_map.scale", 1 << i).withStyle(ChatFormatting.GRAY)); +- list.add(Component.translatable("filled_map.level", i, 4).withStyle(ChatFormatting.GRAY)); ++ tooltip.add(Component.translatable("filled_map.scale", 1 << i).withStyle(ChatFormatting.GRAY)); ++ tooltip.add(Component.translatable("filled_map.level", i, 4).withStyle(ChatFormatting.GRAY)); + } else { +- list.add(Component.translatable("filled_map.unknown").withStyle(ChatFormatting.GRAY)); ++ tooltip.add(Component.translatable("filled_map.unknown").withStyle(ChatFormatting.GRAY)); + } + } + +@@ -431,11 +427,11 @@ + return getTooltipForId(getMapId(itemstack)); + } + +- public static int getColor(ItemStack itemstack) { +- CompoundTag compoundtag = itemstack.getTagElement("display"); ++ public static int getColor(ItemStack stack) { ++ CompoundTag nbttagcompound = stack.getTagElement("display"); + +- if (compoundtag != null && compoundtag.contains("MapColor", 99)) { +- int i = compoundtag.getInt("MapColor"); ++ if (nbttagcompound != null && nbttagcompound.contains("MapColor", 99)) { ++ int i = nbttagcompound.getInt("MapColor"); + + return -16777216 | i & 16777215; + } else { +@@ -444,22 +440,21 @@ + } + + @Override +- @Override +- public InteractionResult useOn(UseOnContext useoncontext) { +- BlockState blockstate = useoncontext.getLevel().getBlockState(useoncontext.getClickedPos()); ++ public InteractionResult useOn(UseOnContext context) { ++ IBlockData iblockdata = context.getLevel().getBlockState(context.getClickedPos()); + +- if (blockstate.is(BlockTags.BANNERS)) { +- if (!useoncontext.getLevel().isClientSide) { +- MapItemSavedData mapitemsaveddata = getSavedData(useoncontext.getItemInHand(), useoncontext.getLevel()); ++ if (iblockdata.is(BlockTags.BANNERS)) { ++ if (!context.getLevel().isClientSide) { ++ MapItemSavedData worldmap = getSavedData(context.getItemInHand(), context.getLevel()); + +- if (mapitemsaveddata != null && !mapitemsaveddata.toggleBanner(useoncontext.getLevel(), useoncontext.getClickedPos())) { ++ if (worldmap != null && !worldmap.toggleBanner(context.getLevel(), context.getClickedPos())) { + return InteractionResult.FAIL; + } + } + +- return InteractionResult.sidedSuccess(useoncontext.getLevel().isClientSide); ++ return InteractionResult.sidedSuccess(context.getLevel().isClientSide); + } else { +- return super.useOn(useoncontext); ++ return super.useOn(context); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/MilkBucketItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/MilkBucketItem.java.patch new file mode 100644 index 0000000000..f8e7e4b1eb --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/MilkBucketItem.java.patch @@ -0,0 +1,74 @@ +--- a/net/minecraft/world/item/MilkBucketItem.java ++++ b/net/minecraft/world/item/MilkBucketItem.java +@@ -3,7 +3,7 @@ + import net.minecraft.advancements.CriteriaTriggers; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.player.Player; +@@ -13,46 +13,42 @@ + + private static final int DRINK_DURATION = 32; + +- public MilkBucketItem(Item.Properties item_properties) { +- super(item_properties); ++ public MilkBucketItem(Item.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public ItemStack finishUsingItem(ItemStack itemstack, Level level, LivingEntity livingentity) { +- if (livingentity instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) livingentity; ++ public ItemStack finishUsingItem(ItemStack stack, Level level, LivingEntity entityLiving) { ++ if (entityLiving instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entityLiving; + +- CriteriaTriggers.CONSUME_ITEM.trigger(serverplayer, itemstack); +- serverplayer.awardStat(Stats.ITEM_USED.get(this)); ++ CriteriaTriggers.CONSUME_ITEM.trigger(entityplayer, stack); ++ entityplayer.awardStat(Stats.ITEM_USED.get(this)); + } + +- if (livingentity instanceof Player && !((Player) livingentity).getAbilities().instabuild) { +- itemstack.shrink(1); ++ if (entityLiving instanceof Player && !((Player) entityLiving).getAbilities().instabuild) { ++ stack.shrink(1); + } + + if (!level.isClientSide) { +- livingentity.removeAllEffects(); ++ entityLiving.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.MILK); // CraftBukkit + } + +- return itemstack.isEmpty() ? new ItemStack(Items.BUCKET) : itemstack; ++ return stack.isEmpty() ? new ItemStack(Items.BUCKET) : stack; + } + + @Override +- @Override +- public int getUseDuration(ItemStack itemstack) { ++ public int getUseDuration(ItemStack stack) { + return 32; + } + + @Override +- @Override +- public UseAnim getUseAnimation(ItemStack itemstack) { +- return UseAnim.DRINK; ++ public EnumAnimation getUseAnimation(ItemStack stack) { ++ return EnumAnimation.DRINK; + } + + @Override +- @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand interactionhand) { +- return ItemUtils.startUsingInstantly(level, player, interactionhand); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ return ItemUtils.startUsingInstantly(level, player, hand); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/MinecartItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/MinecartItem.java.patch new file mode 100644 index 0000000000..506e4c1f8e --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/MinecartItem.java.patch @@ -0,0 +1,195 @@ +--- a/net/minecraft/world/item/MinecartItem.java ++++ b/net/minecraft/world/item/MinecartItem.java +@@ -2,9 +2,9 @@ + + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.dispenser.BlockSource; + import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; + import net.minecraft.core.dispenser.DispenseItemBehavior; ++import net.minecraft.core.dispenser.SourceBlock; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.tags.BlockTags; + import net.minecraft.world.InteractionResult; +@@ -14,10 +14,15 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.BaseRailBlock; + import net.minecraft.world.level.block.DispenserBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.RailShape; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end + + public class MinecartItem extends Item { + +@@ -25,90 +30,121 @@ + private final DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior(); + + @Override +- @Override +- public ItemStack execute(BlockSource blocksource, ItemStack itemstack) { +- Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING); +- ServerLevel serverlevel = blocksource.level(); +- Vec3 vec3 = blocksource.center(); +- double d0 = vec3.x() + (double) direction.getStepX() * 1.125D; +- double d1 = Math.floor(vec3.y()) + (double) direction.getStepY(); +- double d2 = vec3.z() + (double) direction.getStepZ() * 1.125D; +- BlockPos blockpos = blocksource.pos().relative(direction); +- BlockState blockstate = serverlevel.getBlockState(blockpos); +- RailShape railshape = blockstate.getBlock() instanceof BaseRailBlock ? (RailShape) blockstate.getValue(((BaseRailBlock) blockstate.getBlock()).getShapeProperty()) : RailShape.NORTH_SOUTH; ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ ServerLevel worldserver = sourceblock.level(); ++ Vec3 vec3d = sourceblock.center(); ++ double d0 = vec3d.x() + (double) enumdirection.getStepX() * 1.125D; ++ double d1 = Math.floor(vec3d.y()) + (double) enumdirection.getStepY(); ++ double d2 = vec3d.z() + (double) enumdirection.getStepZ() * 1.125D; ++ BlockPos blockposition = sourceblock.pos().relative(enumdirection); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ RailShape blockpropertytrackposition = iblockdata.getBlock() instanceof BaseRailBlock ? (RailShape) iblockdata.getValue(((BaseRailBlock) iblockdata.getBlock()).getShapeProperty()) : RailShape.NORTH_SOUTH; + double d3; + +- if (blockstate.is(BlockTags.RAILS)) { +- if (railshape.isAscending()) { ++ if (iblockdata.is(BlockTags.RAILS)) { ++ if (blockpropertytrackposition.isAscending()) { + d3 = 0.6D; + } else { + d3 = 0.1D; + } + } else { +- if (!blockstate.isAir() || !serverlevel.getBlockState(blockpos.below()).is(BlockTags.RAILS)) { +- return this.defaultDispenseItemBehavior.dispense(blocksource, itemstack); ++ if (!iblockdata.isAir() || !worldserver.getBlockState(blockposition.below()).is(BlockTags.RAILS)) { ++ return this.defaultDispenseItemBehavior.dispense(sourceblock, itemstack); + } + +- BlockState blockstate1 = serverlevel.getBlockState(blockpos.below()); +- RailShape railshape1 = blockstate1.getBlock() instanceof BaseRailBlock ? (RailShape) blockstate1.getValue(((BaseRailBlock) blockstate1.getBlock()).getShapeProperty()) : RailShape.NORTH_SOUTH; ++ IBlockData iblockdata1 = worldserver.getBlockState(blockposition.below()); ++ RailShape blockpropertytrackposition1 = iblockdata1.getBlock() instanceof BaseRailBlock ? (RailShape) iblockdata1.getValue(((BaseRailBlock) iblockdata1.getBlock()).getShapeProperty()) : RailShape.NORTH_SOUTH; + +- if (direction != Direction.DOWN && railshape1.isAscending()) { ++ if (enumdirection != Direction.DOWN && blockpropertytrackposition1.isAscending()) { + d3 = -0.4D; + } else { + d3 = -0.9D; + } + } + +- AbstractMinecart abstractminecart = AbstractMinecart.createMinecart(serverlevel, d0, d1 + d3, d2, ((MinecartItem) itemstack.getItem()).type, itemstack, (Player) null); ++ // CraftBukkit start ++ // EntityMinecartAbstract entityminecartabstract = EntityMinecartAbstract.createMinecart(worldserver, d0, d1 + d3, d2, ((ItemMinecart) itemstack.getItem()).type); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block2 = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + +- serverlevel.addFreshEntity(abstractminecart); +- itemstack.shrink(1); ++ BlockDispenseEvent event = new BlockDispenseEvent(block2, craftItem.clone(), new org.bukkit.util.Vector(d0, d1 + d3, d2)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); ++ AbstractMinecart entityminecartabstract = AbstractMinecart.createMinecart(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), ((MinecartItem) itemstack1.getItem()).type, itemstack1, (Player) null); ++ ++ if (!worldserver.addFreshEntity(entityminecartabstract)) itemstack.grow(1); ++ // itemstack.shrink(1); // CraftBukkit - handled during event processing ++ // CraftBukkit end + return itemstack; + } + + @Override +- @Override +- protected void playSound(BlockSource blocksource) { +- blocksource.level().levelEvent(1000, blocksource.pos(), 0); ++ protected void playSound(SourceBlock sourceblock) { ++ sourceblock.level().levelEvent(1000, sourceblock.pos(), 0); + } + }; +- final AbstractMinecart.Type type; ++ final AbstractMinecart.EnumMinecartType type; + +- public MinecartItem(AbstractMinecart.Type abstractminecart_type, Item.Properties item_properties) { +- super(item_properties); +- this.type = abstractminecart_type; ++ public MinecartItem(AbstractMinecart.EnumMinecartType type, Item.Properties properties) { ++ super(properties); ++ this.type = type; + DispenserBlock.registerBehavior(this, MinecartItem.DISPENSE_ITEM_BEHAVIOR); + } + + @Override +- @Override +- public InteractionResult useOn(UseOnContext useoncontext) { +- Level level = useoncontext.getLevel(); +- BlockPos blockpos = useoncontext.getClickedPos(); +- BlockState blockstate = level.getBlockState(blockpos); ++ public InteractionResult useOn(UseOnContext context) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ IBlockData iblockdata = world.getBlockState(blockposition); + +- if (!blockstate.is(BlockTags.RAILS)) { ++ if (!iblockdata.is(BlockTags.RAILS)) { + return InteractionResult.FAIL; + } else { +- ItemStack itemstack = useoncontext.getItemInHand(); ++ ItemStack itemstack = context.getItemInHand(); + +- if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; +- RailShape railshape = blockstate.getBlock() instanceof BaseRailBlock ? (RailShape) blockstate.getValue(((BaseRailBlock) blockstate.getBlock()).getShapeProperty()) : RailShape.NORTH_SOUTH; ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ RailShape blockpropertytrackposition = iblockdata.getBlock() instanceof BaseRailBlock ? (RailShape) iblockdata.getValue(((BaseRailBlock) iblockdata.getBlock()).getShapeProperty()) : RailShape.NORTH_SOUTH; + double d0 = 0.0D; + +- if (railshape.isAscending()) { ++ if (blockpropertytrackposition.isAscending()) { + d0 = 0.5D; + } + +- AbstractMinecart abstractminecart = AbstractMinecart.createMinecart(serverlevel, (double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.0625D + d0, (double) blockpos.getZ() + 0.5D, this.type, itemstack, useoncontext.getPlayer()); ++ AbstractMinecart entityminecartabstract = AbstractMinecart.createMinecart(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.0625D + d0, (double) blockposition.getZ() + 0.5D, this.type, itemstack, context.getPlayer()); + +- serverlevel.addFreshEntity(abstractminecart); +- serverlevel.gameEvent(GameEvent.ENTITY_PLACE, blockpos, GameEvent.Context.of(useoncontext.getPlayer(), serverlevel.getBlockState(blockpos.below()))); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(context, entityminecartabstract).isCancelled()) { ++ return InteractionResult.FAIL; ++ } ++ // CraftBukkit end ++ if (!worldserver.addFreshEntity(entityminecartabstract)) return InteractionResult.PASS; // CraftBukkit ++ worldserver.gameEvent(GameEvent.ENTITY_PLACE, blockposition, GameEvent.Context.of(context.getPlayer(), worldserver.getBlockState(blockposition.below()))); + } + + itemstack.shrink(1); +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/PotionItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/PotionItem.java.patch new file mode 100644 index 0000000000..cdf203b6ae --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/PotionItem.java.patch @@ -0,0 +1,185 @@ +--- a/net/minecraft/world/item/PotionItem.java ++++ b/net/minecraft/world/item/PotionItem.java +@@ -14,7 +14,7 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; + import net.minecraft.tags.BlockTags; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.effect.MobEffectInstance; +@@ -26,125 +26,117 @@ + import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + + public class PotionItem extends Item { + + private static final int DRINK_DURATION = 32; + +- public PotionItem(Item.Properties item_properties) { +- super(item_properties); ++ public PotionItem(Item.Properties properties) { ++ super(properties); + } + + @Override +- @Override + public ItemStack getDefaultInstance() { + return PotionUtils.setPotion(super.getDefaultInstance(), Potions.WATER); + } + + @Override +- @Override +- public ItemStack finishUsingItem(ItemStack itemstack, Level level, LivingEntity livingentity) { +- Player player = livingentity instanceof Player ? (Player) livingentity : null; ++ public ItemStack finishUsingItem(ItemStack stack, Level level, LivingEntity entityLiving) { ++ Player entityhuman = entityLiving instanceof Player ? (Player) entityLiving : null; + +- if (player instanceof ServerPlayer) { +- CriteriaTriggers.CONSUME_ITEM.trigger((ServerPlayer) player, itemstack); ++ if (entityhuman instanceof ServerPlayer) { ++ CriteriaTriggers.CONSUME_ITEM.trigger((ServerPlayer) entityhuman, stack); + } + + if (!level.isClientSide) { +- List list = PotionUtils.getMobEffects(itemstack); ++ List list = PotionUtils.getMobEffects(stack); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- MobEffectInstance mobeffectinstance = (MobEffectInstance) iterator.next(); ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); + +- if (mobeffectinstance.getEffect().isInstantenous()) { +- mobeffectinstance.getEffect().applyInstantenousEffect(player, player, livingentity, mobeffectinstance.getAmplifier(), 1.0D); ++ if (mobeffect.getEffect().isInstantenous()) { ++ mobeffect.getEffect().applyInstantenousEffect(entityhuman, entityhuman, entityLiving, mobeffect.getAmplifier(), 1.0D); + } else { +- livingentity.addEffect(new MobEffectInstance(mobeffectinstance)); ++ entityLiving.addEffect(new MobEffectInstance(mobeffect), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_DRINK); // CraftBukkit + } + } + } + +- if (player != null) { +- player.awardStat(Stats.ITEM_USED.get(this)); +- if (!player.getAbilities().instabuild) { +- itemstack.shrink(1); ++ if (entityhuman != null) { ++ entityhuman.awardStat(Stats.ITEM_USED.get(this)); ++ if (!entityhuman.getAbilities().instabuild) { ++ stack.shrink(1); + } + } + +- if (player == null || !player.getAbilities().instabuild) { +- if (itemstack.isEmpty()) { ++ if (entityhuman == null || !entityhuman.getAbilities().instabuild) { ++ if (stack.isEmpty()) { + return new ItemStack(Items.GLASS_BOTTLE); + } + +- if (player != null) { +- player.getInventory().add(new ItemStack(Items.GLASS_BOTTLE)); ++ if (entityhuman != null) { ++ entityhuman.getInventory().add(new ItemStack(Items.GLASS_BOTTLE)); + } + } + +- livingentity.gameEvent(GameEvent.DRINK); +- return itemstack; ++ entityLiving.gameEvent(GameEvent.DRINK); ++ return stack; + } + + @Override +- @Override +- public InteractionResult useOn(UseOnContext useoncontext) { +- Level level = useoncontext.getLevel(); +- BlockPos blockpos = useoncontext.getClickedPos(); +- Player player = useoncontext.getPlayer(); +- ItemStack itemstack = useoncontext.getItemInHand(); +- BlockState blockstate = level.getBlockState(blockpos); ++ public InteractionResult useOn(UseOnContext context) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ Player entityhuman = context.getPlayer(); ++ ItemStack itemstack = context.getItemInHand(); ++ IBlockData iblockdata = world.getBlockState(blockposition); + +- if (useoncontext.getClickedFace() != Direction.DOWN && blockstate.is(BlockTags.CONVERTABLE_TO_MUD) && PotionUtils.getPotion(itemstack) == Potions.WATER) { +- level.playSound((Player) null, blockpos, SoundEvents.GENERIC_SPLASH, SoundSource.BLOCKS, 1.0F, 1.0F); +- player.setItemInHand(useoncontext.getHand(), ItemUtils.createFilledResult(itemstack, player, new ItemStack(Items.GLASS_BOTTLE))); +- player.awardStat(Stats.ITEM_USED.get(itemstack.getItem())); +- if (!level.isClientSide) { +- ServerLevel serverlevel = (ServerLevel) level; ++ if (context.getClickedFace() != Direction.DOWN && iblockdata.is(BlockTags.CONVERTABLE_TO_MUD) && PotionUtils.getPotion(itemstack) == Potions.WATER) { ++ world.playSound((Player) null, blockposition, SoundEvents.GENERIC_SPLASH, SoundSource.BLOCKS, 1.0F, 1.0F); ++ entityhuman.setItemInHand(context.getHand(), ItemUtils.createFilledResult(itemstack, entityhuman, new ItemStack(Items.GLASS_BOTTLE))); ++ entityhuman.awardStat(Stats.ITEM_USED.get(itemstack.getItem())); ++ if (!world.isClientSide) { ++ ServerLevel worldserver = (ServerLevel) world; + + for (int i = 0; i < 5; ++i) { +- serverlevel.sendParticles(ParticleTypes.SPLASH, (double) blockpos.getX() + level.random.nextDouble(), (double) (blockpos.getY() + 1), (double) blockpos.getZ() + level.random.nextDouble(), 1, 0.0D, 0.0D, 0.0D, 1.0D); ++ worldserver.sendParticles(ParticleTypes.SPLASH, (double) blockposition.getX() + world.random.nextDouble(), (double) (blockposition.getY() + 1), (double) blockposition.getZ() + world.random.nextDouble(), 1, 0.0D, 0.0D, 0.0D, 1.0D); + } + } + +- level.playSound((Player) null, blockpos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockpos); +- level.setBlockAndUpdate(blockpos, Blocks.MUD.defaultBlockState()); +- return InteractionResult.sidedSuccess(level.isClientSide); ++ world.playSound((Player) null, blockposition, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockposition); ++ world.setBlockAndUpdate(blockposition, Blocks.MUD.defaultBlockState()); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } else { + return InteractionResult.PASS; + } + } + + @Override +- @Override +- public int getUseDuration(ItemStack itemstack) { ++ public int getUseDuration(ItemStack stack) { + return 32; + } + + @Override +- @Override +- public UseAnim getUseAnimation(ItemStack itemstack) { +- return UseAnim.DRINK; ++ public EnumAnimation getUseAnimation(ItemStack stack) { ++ return EnumAnimation.DRINK; + } + + @Override +- @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand interactionhand) { +- return ItemUtils.startUsingInstantly(level, player, interactionhand); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ return ItemUtils.startUsingInstantly(level, player, hand); + } + + @Override +- @Override +- public String getDescriptionId(ItemStack itemstack) { +- return PotionUtils.getPotion(itemstack).getName(this.getDescriptionId() + ".effect."); ++ public String getDescriptionId(ItemStack stack) { ++ return PotionUtils.getPotion(stack).getName(this.getDescriptionId() + ".effect."); + } + + @Override +- @Override +- public void appendHoverText(ItemStack itemstack, @Nullable Level level, List list, TooltipFlag tooltipflag) { +- PotionUtils.addPotionTooltip(itemstack, list, 1.0F, level == null ? 20.0F : level.tickRateManager().tickrate()); ++ public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { ++ PotionUtils.addPotionTooltip(stack, tooltip, 1.0F, level == null ? 20.0F : level.tickRateManager().tickrate()); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/RecordItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/RecordItem.java.patch new file mode 100644 index 0000000000..fde55760c4 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/RecordItem.java.patch @@ -0,0 +1,99 @@ +--- a/net/minecraft/world/item/RecordItem.java ++++ b/net/minecraft/world/item/RecordItem.java +@@ -18,7 +18,7 @@ + import net.minecraft.world.level.block.JukeboxBlock; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.JukeboxBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + + public class RecordItem extends Item { +@@ -28,42 +28,42 @@ + private final SoundEvent sound; + private final int lengthInTicks; + +- protected RecordItem(int i, SoundEvent soundevent, Item.Properties item_properties, int j) { +- super(item_properties); +- this.analogOutput = i; +- this.sound = soundevent; +- this.lengthInTicks = j * 20; ++ protected RecordItem(int analogOutput, SoundEvent sound, Item.Properties properties, int lengthInSeconds) { ++ super(properties); ++ this.analogOutput = analogOutput; ++ this.sound = sound; ++ this.lengthInTicks = lengthInSeconds * 20; + RecordItem.BY_NAME.put(this.sound, this); + } + + @Override +- @Override +- public InteractionResult useOn(UseOnContext useoncontext) { +- Level level = useoncontext.getLevel(); +- BlockPos blockpos = useoncontext.getClickedPos(); +- BlockState blockstate = level.getBlockState(blockpos); ++ public InteractionResult useOn(UseOnContext context) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ IBlockData iblockdata = world.getBlockState(blockposition); + +- if (blockstate.is(Blocks.JUKEBOX) && !(Boolean) blockstate.getValue(JukeboxBlock.HAS_RECORD)) { +- ItemStack itemstack = useoncontext.getItemInHand(); ++ if (iblockdata.is(Blocks.JUKEBOX) && !(Boolean) iblockdata.getValue(JukeboxBlock.HAS_RECORD)) { ++ ItemStack itemstack = context.getItemInHand(); + +- if (!level.isClientSide) { +- Player player = useoncontext.getPlayer(); +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ if (!world.isClientSide) { ++ if (true) return InteractionResult.SUCCESS; // CraftBukkit - handled in ItemStack ++ Player entityhuman = context.getPlayer(); ++ BlockEntity tileentity = world.getBlockEntity(blockposition); + +- if (blockentity instanceof JukeboxBlockEntity) { +- JukeboxBlockEntity jukeboxblockentity = (JukeboxBlockEntity) blockentity; ++ if (tileentity instanceof JukeboxBlockEntity) { ++ JukeboxBlockEntity tileentityjukebox = (JukeboxBlockEntity) tileentity; + +- jukeboxblockentity.setTheItem(itemstack.copy()); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(player, blockstate)); ++ tileentityjukebox.setTheItem(itemstack.copy()); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entityhuman, iblockdata)); + } + + itemstack.shrink(1); +- if (player != null) { +- player.awardStat(Stats.PLAY_RECORD); ++ if (entityhuman != null) { ++ entityhuman.awardStat(Stats.PLAY_RECORD); + } + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } else { + return InteractionResult.PASS; + } +@@ -74,9 +74,8 @@ + } + + @Override +- @Override +- public void appendHoverText(ItemStack itemstack, @Nullable Level level, List list, TooltipFlag tooltipflag) { +- list.add(this.getDisplayName().withStyle(ChatFormatting.GRAY)); ++ public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { ++ tooltip.add(this.getDisplayName().withStyle(ChatFormatting.GRAY)); + } + + public MutableComponent getDisplayName() { +@@ -84,8 +83,8 @@ + } + + @Nullable +- public static RecordItem getBySound(SoundEvent soundevent) { +- return (RecordItem) RecordItem.BY_NAME.get(soundevent); ++ public static RecordItem getBySound(SoundEvent sound) { ++ return (RecordItem) RecordItem.BY_NAME.get(sound); + } + + public SoundEvent getSound() { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/SignItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/SignItem.java.patch new file mode 100644 index 0000000000..a7b04b1904 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/SignItem.java.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/item/SignItem.java ++++ b/net/minecraft/world/item/SignItem.java +@@ -9,34 +9,38 @@ + import net.minecraft.world.level.block.SignBlock; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.SignBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public class SignItem extends StandingAndWallBlockItem { + +- public SignItem(Item.Properties item_properties, Block block, Block block1) { +- super(block, block1, item_properties, Direction.DOWN); ++ public static BlockPos openSign; // CraftBukkit ++ ++ public SignItem(Item.Properties properties, Block standingBlock, Block wallBlock) { ++ super(standingBlock, wallBlock, properties, Direction.DOWN); + } + +- public SignItem(Item.Properties item_properties, Block block, Block block1, Direction direction) { +- super(block, block1, item_properties, direction); ++ public SignItem(Item.Properties properties, Block standingBlock, Block wallBlock, Direction attachmentDirection) { ++ super(standingBlock, wallBlock, properties, attachmentDirection); + } + + @Override +- @Override +- protected boolean updateCustomBlockEntityTag(BlockPos blockpos, Level level, @Nullable Player player, ItemStack itemstack, BlockState blockstate) { +- boolean flag = super.updateCustomBlockEntityTag(blockpos, level, player, itemstack, blockstate); ++ protected boolean updateCustomBlockEntityTag(BlockPos pos, Level level, @Nullable Player player, ItemStack stack, IBlockData state) { ++ boolean flag = super.updateCustomBlockEntityTag(pos, level, player, stack, state); + + if (!level.isClientSide && !flag && player != null) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof SignBlockEntity) { +- SignBlockEntity signblockentity = (SignBlockEntity) blockentity; +- Block block = level.getBlockState(blockpos).getBlock(); ++ if (tileentity instanceof SignBlockEntity) { ++ SignBlockEntity tileentitysign = (SignBlockEntity) tileentity; ++ Block block = level.getBlockState(pos).getBlock(); + + if (block instanceof SignBlock) { +- SignBlock signblock = (SignBlock) block; ++ SignBlock blocksign = (SignBlock) block; + +- signblock.openTextEdit(player, signblockentity, true); ++ // CraftBukkit start - SPIGOT-4678 ++ // blocksign.openTextEdit(entityhuman, tileentitysign, true); ++ SignItem.openSign = pos; ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/SnowballItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/SnowballItem.java.patch new file mode 100644 index 0000000000..07f92d46c9 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/SnowballItem.java.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/world/item/SnowballItem.java ++++ b/net/minecraft/world/item/SnowballItem.java +@@ -3,7 +3,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.Snowball; +@@ -11,28 +11,40 @@ + + public class SnowballItem extends Item { + +- public SnowballItem(Item.Properties item_properties) { +- super(item_properties); ++ public SnowballItem(Item.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + +- level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.SNOWBALL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); ++ // CraftBukkit - moved down ++ // world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.SNOWBALL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); + if (!level.isClientSide) { +- Snowball snowball = new Snowball(level, player); ++ Snowball entitysnowball = new Snowball(level, player); + +- snowball.setItem(itemstack); +- snowball.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 1.5F, 1.0F); +- level.addFreshEntity(snowball); ++ entitysnowball.setItem(itemstack); ++ entitysnowball.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 1.5F, 1.0F); ++ if (level.addFreshEntity(entitysnowball)) { ++ if (!player.getAbilities().instabuild) { ++ itemstack.shrink(1); ++ } ++ ++ level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.SNOWBALL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); ++ } else if (player instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().updateInventory(); ++ } + } ++ // CraftBukkit end + + player.awardStat(Stats.ITEM_USED.get(this)); +- if (!player.getAbilities().instabuild) { ++ // CraftBukkit start - moved up ++ /* ++ if (!entityhuman.getAbilities().instabuild) { + itemstack.shrink(1); + } ++ */ + + return InteractionResultHolder.sidedSuccess(itemstack, level.isClientSide()); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/SpawnEggItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/SpawnEggItem.java.patch new file mode 100644 index 0000000000..839b0598c2 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/SpawnEggItem.java.patch @@ -0,0 +1,232 @@ +--- a/net/minecraft/world/item/SpawnEggItem.java ++++ b/net/minecraft/world/item/SpawnEggItem.java +@@ -11,14 +11,14 @@ + import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.flag.FeatureFlagSet; + import net.minecraft.world.item.context.UseOnContext; +@@ -27,7 +27,7 @@ + import net.minecraft.world.level.Spawner; + import net.minecraft.world.level.block.LiquidBlock; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.HitResult; +@@ -40,51 +40,50 @@ + private final int highlightColor; + private final EntityType defaultType; + +- public SpawnEggItem(EntityType entitytype, int i, int j, Item.Properties item_properties) { +- super(item_properties); +- this.defaultType = entitytype; +- this.backgroundColor = i; +- this.highlightColor = j; +- SpawnEggItem.BY_ID.put(entitytype, this); ++ public SpawnEggItem(EntityType defaultType, int backgroundColor, int highlightColor, Item.Properties properties) { ++ super(properties); ++ this.defaultType = defaultType; ++ this.backgroundColor = backgroundColor; ++ this.highlightColor = highlightColor; ++ SpawnEggItem.BY_ID.put(defaultType, this); + } + + @Override +- @Override +- public InteractionResult useOn(UseOnContext useoncontext) { +- Level level = useoncontext.getLevel(); ++ public InteractionResult useOn(UseOnContext context) { ++ Level world = context.getLevel(); + +- if (!(level instanceof ServerLevel)) { ++ if (!(world instanceof ServerLevel)) { + return InteractionResult.SUCCESS; + } else { +- ItemStack itemstack = useoncontext.getItemInHand(); +- BlockPos blockpos = useoncontext.getClickedPos(); +- Direction direction = useoncontext.getClickedFace(); +- BlockState blockstate = level.getBlockState(blockpos); +- BlockEntity blockentity = level.getBlockEntity(blockpos); +- EntityType entitytype; ++ ItemStack itemstack = context.getItemInHand(); ++ BlockPos blockposition = context.getClickedPos(); ++ Direction enumdirection = context.getClickedFace(); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ BlockEntity tileentity = world.getBlockEntity(blockposition); ++ EntityType entitytypes; + +- if (blockentity instanceof Spawner) { +- Spawner spawner = (Spawner) blockentity; ++ if (tileentity instanceof Spawner) { ++ Spawner spawner = (Spawner) tileentity; + +- entitytype = this.getType(itemstack.getTag()); +- spawner.setEntityId(entitytype, level.getRandom()); +- level.sendBlockUpdated(blockpos, blockstate, blockstate, 3); +- level.gameEvent((Entity) useoncontext.getPlayer(), GameEvent.BLOCK_CHANGE, blockpos); ++ entitytypes = this.getType(itemstack.getTag()); ++ spawner.setEntityId(entitytypes, world.getRandom()); ++ world.sendBlockUpdated(blockposition, iblockdata, iblockdata, 3); ++ world.gameEvent((Entity) context.getPlayer(), GameEvent.BLOCK_CHANGE, blockposition); + itemstack.shrink(1); + return InteractionResult.CONSUME; + } else { +- BlockPos blockpos1; ++ BlockPos blockposition1; + +- if (blockstate.getCollisionShape(level, blockpos).isEmpty()) { +- blockpos1 = blockpos; ++ if (iblockdata.getCollisionShape(world, blockposition).isEmpty()) { ++ blockposition1 = blockposition; + } else { +- blockpos1 = blockpos.relative(direction); ++ blockposition1 = blockposition.relative(enumdirection); + } + +- entitytype = this.getType(itemstack.getTag()); +- if (entitytype.spawn((ServerLevel) level, itemstack, useoncontext.getPlayer(), blockpos1, MobSpawnType.SPAWN_EGG, true, !Objects.equals(blockpos, blockpos1) && direction == Direction.UP) != null) { ++ entitytypes = this.getType(itemstack.getTag()); ++ if (entitytypes.spawn((ServerLevel) world, itemstack, context.getPlayer(), blockposition1, EnumMobSpawn.SPAWN_EGG, true, !Objects.equals(blockposition, blockposition1) && enumdirection == Direction.UP) != null) { + itemstack.shrink(1); +- level.gameEvent((Entity) useoncontext.getPlayer(), GameEvent.ENTITY_PLACE, blockpos); ++ world.gameEvent((Entity) context.getPlayer(), GameEvent.ENTITY_PLACE, blockposition); + } + + return InteractionResult.CONSUME; +@@ -93,23 +92,22 @@ + } + + @Override +- @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); +- BlockHitResult blockhitresult = getPlayerPOVHitResult(level, player, ClipContext.Fluid.SOURCE_ONLY); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ BlockHitResult movingobjectpositionblock = getPlayerPOVHitResult(level, player, ClipContext.Fluid.SOURCE_ONLY); + +- if (blockhitresult.getType() != HitResult.Type.BLOCK) { ++ if (movingobjectpositionblock.getType() != HitResult.EnumMovingObjectType.BLOCK) { + return InteractionResultHolder.pass(itemstack); + } else if (!(level instanceof ServerLevel)) { + return InteractionResultHolder.success(itemstack); + } else { +- BlockPos blockpos = blockhitresult.getBlockPos(); ++ BlockPos blockposition = movingobjectpositionblock.getBlockPos(); + +- if (!(level.getBlockState(blockpos).getBlock() instanceof LiquidBlock)) { ++ if (!(level.getBlockState(blockposition).getBlock() instanceof LiquidBlock)) { + return InteractionResultHolder.pass(itemstack); +- } else if (level.mayInteract(player, blockpos) && player.mayUseItemAt(blockpos, blockhitresult.getDirection(), itemstack)) { +- EntityType entitytype = this.getType(itemstack.getTag()); +- Entity entity = entitytype.spawn((ServerLevel) level, itemstack, player, blockpos, MobSpawnType.SPAWN_EGG, false, false); ++ } else if (level.mayInteract(player, blockposition) && player.mayUseItemAt(blockposition, movingobjectpositionblock.getDirection(), itemstack)) { ++ EntityType entitytypes = this.getType(itemstack.getTag()); ++ Entity entity = entitytypes.spawn((ServerLevel) level, itemstack, player, blockposition, EnumMobSpawn.SPAWN_EGG, false, false); + + if (entity == null) { + return InteractionResultHolder.pass(itemstack); +@@ -128,29 +126,29 @@ + } + } + +- public boolean spawnsEntity(@Nullable CompoundTag compoundtag, EntityType entitytype) { +- return Objects.equals(this.getType(compoundtag), entitytype); ++ public boolean spawnsEntity(@Nullable CompoundTag nbt, EntityType type) { ++ return Objects.equals(this.getType(nbt), type); + } + +- public int getColor(int i) { +- return i == 0 ? this.backgroundColor : this.highlightColor; ++ public int getColor(int tintIndex) { ++ return tintIndex == 0 ? this.backgroundColor : this.highlightColor; + } + + @Nullable +- public static SpawnEggItem byId(@Nullable EntityType entitytype) { +- return (SpawnEggItem) SpawnEggItem.BY_ID.get(entitytype); ++ public static SpawnEggItem byId(@Nullable EntityType type) { ++ return (SpawnEggItem) SpawnEggItem.BY_ID.get(type); + } + + public static Iterable eggs() { + return Iterables.unmodifiableIterable(SpawnEggItem.BY_ID.values()); + } + +- public EntityType getType(@Nullable CompoundTag compoundtag) { +- if (compoundtag != null && compoundtag.contains("EntityTag", 10)) { +- CompoundTag compoundtag1 = compoundtag.getCompound("EntityTag"); ++ public EntityType getType(@Nullable CompoundTag nbt) { ++ if (nbt != null && nbt.contains("EntityTag", 10)) { ++ CompoundTag nbttagcompound1 = nbt.getCompound("EntityTag"); + +- if (compoundtag1.contains("id", 8)) { +- return (EntityType) EntityType.byString(compoundtag1.getString("id")).orElse(this.defaultType); ++ if (nbttagcompound1.contains("id", 8)) { ++ return (EntityType) EntityType.byString(nbttagcompound1.getString("id")).orElse(this.defaultType); + } + } + +@@ -158,21 +156,20 @@ + } + + @Override +- @Override + public FeatureFlagSet requiredFeatures() { + return this.defaultType.requiredFeatures(); + } + +- public Optional spawnOffspringFromSpawnEgg(Player player, Mob mob, EntityType entitytype, ServerLevel serverlevel, Vec3 vec3, ItemStack itemstack) { +- if (!this.spawnsEntity(itemstack.getTag(), entitytype)) { ++ public Optional spawnOffspringFromSpawnEgg(Player player, Mob mob, EntityType entityType, ServerLevel serverLevel, Vec3 pos, ItemStack stack) { ++ if (!this.spawnsEntity(stack.getTag(), entityType)) { + return Optional.empty(); + } else { + Object object; + + if (mob instanceof AgeableMob) { +- object = ((AgeableMob) mob).getBreedOffspring(serverlevel, (AgeableMob) mob); ++ object = ((AgeableMob) mob).getBreedOffspring(serverLevel, (AgeableMob) mob); + } else { +- object = (Mob) entitytype.create(serverlevel); ++ object = (Mob) entityType.create(serverLevel); + } + + if (object == null) { +@@ -182,17 +179,17 @@ + if (!((Mob) object).isBaby()) { + return Optional.empty(); + } else { +- ((Mob) object).moveTo(vec3.x(), vec3.y(), vec3.z(), 0.0F, 0.0F); +- serverlevel.addFreshEntityWithPassengers((Entity) object); +- if (itemstack.hasCustomHoverName()) { +- ((Mob) object).setCustomName(itemstack.getHoverName()); ++ ((Mob) object).moveTo(pos.x(), pos.y(), pos.z(), 0.0F, 0.0F); ++ serverLevel.addFreshEntityWithPassengers((Entity) object, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG); // CraftBukkit ++ if (stack.hasCustomHoverName()) { ++ ((Mob) object).setCustomName(stack.getHoverName()); + } + + if (!player.getAbilities().instabuild) { +- itemstack.shrink(1); ++ stack.shrink(1); + } + +- return Optional.of(object); ++ return Optional.of((Mob) object); // CraftBukkit - decompile error + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/StandingAndWallBlockItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/StandingAndWallBlockItem.java.patch new file mode 100644 index 0000000000..e6f2b4e97c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/StandingAndWallBlockItem.java.patch @@ -0,0 +1,103 @@ +--- a/net/minecraft/world/item/StandingAndWallBlockItem.java ++++ b/net/minecraft/world/item/StandingAndWallBlockItem.java +@@ -4,59 +4,74 @@ + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.item.context.BlockPlaceContext; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.Block; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.shapes.CollisionContext; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.event.block.BlockCanBuildEvent; ++// CraftBukkit end + + public class StandingAndWallBlockItem extends BlockItem { + +- protected final Block wallBlock; ++ public final Block wallBlock; + private final Direction attachmentDirection; + +- public StandingAndWallBlockItem(Block block, Block block1, Item.Properties item_properties, Direction direction) { +- super(block, item_properties); +- this.wallBlock = block1; +- this.attachmentDirection = direction; ++ public StandingAndWallBlockItem(Block block, Block wallBlock, Item.Properties properties, Direction attachmentDirection) { ++ super(block, properties); ++ this.wallBlock = wallBlock; ++ this.attachmentDirection = attachmentDirection; + } + +- protected boolean canPlace(LevelReader levelreader, BlockState blockstate, BlockPos blockpos) { +- return blockstate.canSurvive(levelreader, blockpos); ++ protected boolean canPlace(LevelReader level, IBlockData state, BlockPos pos) { ++ return state.canSurvive(level, pos); + } + + @Nullable + @Override +- @Override +- protected BlockState getPlacementState(BlockPlaceContext blockplacecontext) { +- BlockState blockstate = this.wallBlock.getStateForPlacement(blockplacecontext); +- BlockState blockstate1 = null; +- Level level = blockplacecontext.getLevel(); +- BlockPos blockpos = blockplacecontext.getClickedPos(); +- Direction[] adirection = blockplacecontext.getNearestLookingDirections(); +- int i = adirection.length; ++ protected IBlockData getPlacementState(BlockPlaceContext context) { ++ IBlockData iblockdata = this.wallBlock.getStateForPlacement(context); ++ IBlockData iblockdata1 = null; ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ Direction[] aenumdirection = context.getNearestLookingDirections(); ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; ++ Direction enumdirection = aenumdirection[j]; + +- if (direction != this.attachmentDirection.getOpposite()) { +- BlockState blockstate2 = direction == this.attachmentDirection ? this.getBlock().getStateForPlacement(blockplacecontext) : blockstate; ++ if (enumdirection != this.attachmentDirection.getOpposite()) { ++ IBlockData iblockdata2 = enumdirection == this.attachmentDirection ? this.getBlock().getStateForPlacement(context) : iblockdata; + +- if (blockstate2 != null && this.canPlace(level, blockstate2, blockpos)) { +- blockstate1 = blockstate2; ++ if (iblockdata2 != null && this.canPlace(world, iblockdata2, blockposition)) { ++ iblockdata1 = iblockdata2; + break; + } + } + } + +- return blockstate1 != null && level.isUnobstructed(blockstate1, blockpos, CollisionContext.empty()) ? blockstate1 : null; ++ // CraftBukkit start ++ if (iblockdata1 != null) { ++ boolean defaultReturn = world.isUnobstructed(iblockdata1, blockposition, CollisionContext.empty()); ++ org.bukkit.entity.Player player = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null; ++ ++ BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(world, blockposition), player, CraftBlockData.fromData(iblockdata1), defaultReturn); ++ context.getLevel().getCraftServer().getPluginManager().callEvent(event); ++ ++ return (event.isBuildable()) ? iblockdata1 : null; ++ } else { ++ return null; ++ } ++ // CraftBukkit end + } + + @Override +- @Override +- public void registerBlocks(Map map, Item item) { +- super.registerBlocks(map, item); +- map.put(this.wallBlock, item); ++ public void registerBlocks(Map blockToItemMap, Item item) { ++ super.registerBlocks(blockToItemMap, item); ++ blockToItemMap.put(this.wallBlock, item); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/TridentItem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/TridentItem.java.patch new file mode 100644 index 0000000000..65ea0af315 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/TridentItem.java.patch @@ -0,0 +1,245 @@ +--- a/net/minecraft/world/item/TridentItem.java ++++ b/net/minecraft/world/item/TridentItem.java +@@ -9,12 +9,12 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.ai.attributes.Attribute; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -23,18 +23,18 @@ + import net.minecraft.world.entity.projectile.ThrownTrident; + import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; + +-public class TridentItem extends Item implements Vanishable { ++public class TridentItem extends Item implements ItemVanishable { + + public static final int THROW_THRESHOLD_TIME = 10; + public static final float BASE_DAMAGE = 8.0F; + public static final float SHOOT_POWER = 2.5F; + private final Multimap defaultModifiers; + +- public TridentItem(Item.Properties item_properties) { +- super(item_properties); ++ public TridentItem(Item.Properties properties) { ++ super(properties); + Builder builder = ImmutableMultimap.builder(); + + builder.put(Attributes.ATTACK_DAMAGE, new AttributeModifier(TridentItem.BASE_ATTACK_DAMAGE_UUID, "Tool modifier", 8.0D, AttributeModifier.Operation.ADDITION)); +@@ -43,58 +43,80 @@ + } + + @Override +- @Override +- public boolean canAttackBlock(BlockState blockstate, Level level, BlockPos blockpos, Player player) { ++ public boolean canAttackBlock(IBlockData state, Level level, BlockPos pos, Player player) { + return !player.isCreative(); + } + + @Override +- @Override +- public UseAnim getUseAnimation(ItemStack itemstack) { +- return UseAnim.SPEAR; ++ public EnumAnimation getUseAnimation(ItemStack stack) { ++ return EnumAnimation.SPEAR; + } + + @Override +- @Override +- public int getUseDuration(ItemStack itemstack) { ++ public int getUseDuration(ItemStack stack) { + return 72000; + } + + @Override +- @Override +- public void releaseUsing(ItemStack itemstack, Level level, LivingEntity livingentity, int i) { +- if (livingentity instanceof Player) { +- Player player = (Player) livingentity; +- int j = this.getUseDuration(itemstack) - i; ++ public void releaseUsing(ItemStack stack, Level level, LivingEntity entityLiving, int timeLeft) { ++ if (entityLiving instanceof Player) { ++ Player entityhuman = (Player) entityLiving; ++ int j = this.getUseDuration(stack) - timeLeft; + + if (j >= 10) { +- int k = EnchantmentHelper.getRiptide(itemstack); ++ int k = EnchantmentHelper.getRiptide(stack); + +- if (k <= 0 || player.isInWaterOrRain()) { ++ if (k <= 0 || entityhuman.isInWaterOrRain()) { + if (!level.isClientSide) { +- itemstack.hurtAndBreak(1, player, (player1) -> { +- player1.broadcastBreakEvent(livingentity.getUsedItemHand()); ++ // CraftBukkit - moved down ++ /* ++ itemstack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(entityliving.getUsedItemHand()); + }); ++ */ + if (k == 0) { +- ThrownTrident throwntrident = new ThrownTrident(level, player, itemstack); ++ ThrownTrident entitythrowntrident = new ThrownTrident(level, entityhuman, stack); + +- throwntrident.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 2.5F + (float) k * 0.5F, 1.0F); +- if (player.getAbilities().instabuild) { +- throwntrident.pickup = AbstractArrow.Pickup.CREATIVE_ONLY; ++ entitythrowntrident.shootFromRotation(entityhuman, entityhuman.getXRot(), entityhuman.getYRot(), 0.0F, 2.5F + (float) k * 0.5F, 1.0F); ++ if (entityhuman.getAbilities().instabuild) { ++ entitythrowntrident.pickup = AbstractArrow.Pickup.CREATIVE_ONLY; + } + +- level.addFreshEntity(throwntrident); +- level.playSound((Player) null, (Entity) throwntrident, SoundEvents.TRIDENT_THROW, SoundSource.PLAYERS, 1.0F, 1.0F); +- if (!player.getAbilities().instabuild) { +- player.getInventory().removeItem(itemstack); ++ // CraftBukkit start ++ if (!level.addFreshEntity(entitythrowntrident)) { ++ if (entityhuman instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } ++ return; + } ++ ++ stack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(entityLiving.getUsedItemHand()); ++ }); ++ entitythrowntrident.pickupItemStack = stack.copy(); // SPIGOT-4511 update since damage call moved ++ // CraftBukkit end ++ ++ level.playSound((Player) null, (Entity) entitythrowntrident, SoundEvents.TRIDENT_THROW, SoundSource.PLAYERS, 1.0F, 1.0F); ++ if (!entityhuman.getAbilities().instabuild) { ++ entityhuman.getInventory().removeItem(stack); ++ } ++ // CraftBukkit start - SPIGOT-5458 also need in this branch :( ++ } else { ++ stack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(entityLiving.getUsedItemHand()); ++ }); ++ // CraftBukkkit end + } + } + +- player.awardStat(Stats.ITEM_USED.get(this)); ++ entityhuman.awardStat(Stats.ITEM_USED.get(this)); + if (k > 0) { +- float f = player.getYRot(); +- float f1 = player.getXRot(); ++ // CraftBukkit start ++ org.bukkit.event.player.PlayerRiptideEvent event = new org.bukkit.event.player.PlayerRiptideEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack)); ++ event.getPlayer().getServer().getPluginManager().callEvent(event); ++ // CraftBukkit end ++ float f = entityhuman.getYRot(); ++ float f1 = entityhuman.getXRot(); + float f2 = -Mth.sin(f * 0.017453292F) * Mth.cos(f1 * 0.017453292F); + float f3 = -Mth.sin(f1 * 0.017453292F); + float f4 = Mth.cos(f * 0.017453292F) * Mth.cos(f1 * 0.017453292F); +@@ -104,25 +126,25 @@ + f2 *= f6 / f5; + f3 *= f6 / f5; + f4 *= f6 / f5; +- player.push((double) f2, (double) f3, (double) f4); +- player.startAutoSpinAttack(20); +- if (player.onGround()) { ++ entityhuman.push((double) f2, (double) f3, (double) f4); ++ entityhuman.startAutoSpinAttack(20); ++ if (entityhuman.onGround()) { + float f7 = 1.1999999F; + +- player.move(MoverType.SELF, new Vec3(0.0D, 1.1999999284744263D, 0.0D)); ++ entityhuman.move(EnumMoveType.SELF, new Vec3(0.0D, 1.1999999284744263D, 0.0D)); + } + +- SoundEvent soundevent; ++ SoundEvent soundeffect; + + if (k >= 3) { +- soundevent = SoundEvents.TRIDENT_RIPTIDE_3; ++ soundeffect = SoundEvents.TRIDENT_RIPTIDE_3; + } else if (k == 2) { +- soundevent = SoundEvents.TRIDENT_RIPTIDE_2; ++ soundeffect = SoundEvents.TRIDENT_RIPTIDE_2; + } else { +- soundevent = SoundEvents.TRIDENT_RIPTIDE_1; ++ soundeffect = SoundEvents.TRIDENT_RIPTIDE_1; + } + +- level.playSound((Player) null, (Entity) player, soundevent, SoundSource.PLAYERS, 1.0F, 1.0F); ++ level.playSound((Player) null, (Entity) entityhuman, soundeffect, SoundSource.PLAYERS, 1.0F, 1.0F); + } + + } +@@ -131,35 +153,32 @@ + } + + @Override +- @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand interactionhand) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (itemstack.getDamageValue() >= itemstack.getMaxDamage() - 1) { + return InteractionResultHolder.fail(itemstack); + } else if (EnchantmentHelper.getRiptide(itemstack) > 0 && !player.isInWaterOrRain()) { + return InteractionResultHolder.fail(itemstack); + } else { +- player.startUsingItem(interactionhand); ++ player.startUsingItem(hand); + return InteractionResultHolder.consume(itemstack); + } + } + + @Override +- @Override +- public boolean hurtEnemy(ItemStack itemstack, LivingEntity livingentity, LivingEntity livingentity1) { +- itemstack.hurtAndBreak(1, livingentity1, (livingentity2) -> { +- livingentity2.broadcastBreakEvent(EquipmentSlot.MAINHAND); ++ public boolean hurtEnemy(ItemStack stack, LivingEntity target, LivingEntity attacker) { ++ stack.hurtAndBreak(1, attacker, (entityliving2) -> { ++ entityliving2.broadcastBreakEvent(EquipmentSlot.MAINHAND); + }); + return true; + } + + @Override +- @Override +- public boolean mineBlock(ItemStack itemstack, Level level, BlockState blockstate, BlockPos blockpos, LivingEntity livingentity) { +- if ((double) blockstate.getDestroySpeed(level, blockpos) != 0.0D) { +- itemstack.hurtAndBreak(2, livingentity, (livingentity1) -> { +- livingentity1.broadcastBreakEvent(EquipmentSlot.MAINHAND); ++ public boolean mineBlock(ItemStack stack, Level level, IBlockData state, BlockPos pos, LivingEntity entityLiving) { ++ if ((double) state.getDestroySpeed(level, pos) != 0.0D) { ++ stack.hurtAndBreak(2, entityLiving, (entityliving1) -> { ++ entityliving1.broadcastBreakEvent(EquipmentSlot.MAINHAND); + }); + } + +@@ -167,13 +186,11 @@ + } + + @Override +- @Override +- public Multimap getDefaultAttributeModifiers(EquipmentSlot equipmentslot) { +- return equipmentslot == EquipmentSlot.MAINHAND ? this.defaultModifiers : super.getDefaultAttributeModifiers(equipmentslot); ++ public Multimap getDefaultAttributeModifiers(EquipmentSlot equipmentSlot) { ++ return equipmentSlot == EquipmentSlot.MAINHAND ? this.defaultModifiers : super.getDefaultAttributeModifiers(equipmentSlot); + } + + @Override +- @Override + public int getEnchantmentValue() { + return 1; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/BlastingRecipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/BlastingRecipe.java.patch new file mode 100644 index 0000000000..e459ae58c7 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/BlastingRecipe.java.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/world/item/crafting/BlastingRecipe.java ++++ b/net/minecraft/world/item/crafting/BlastingRecipe.java +@@ -3,21 +3,40 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftBlastingRecipe; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class BlastingRecipe extends AbstractCookingRecipe { + +- public BlastingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient ingredient, ItemStack itemstack, float f, int i) { +- super(RecipeType.BLASTING, s, cookingbookcategory, ingredient, itemstack, f, i); ++ public BlastingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient recipeitemstack, ItemStack itemstack, float f, int i) { ++ super(RecipeType.BLASTING, s, cookingbookcategory, recipeitemstack, itemstack, f, i); + } + + @Override +- @Override + public ItemStack getToastSymbol() { + return new ItemStack(Blocks.BLAST_FURNACE); + } + + @Override +- @Override + public RecipeSerializer getSerializer() { + return RecipeSerializer.BLASTING_RECIPE; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftBlastingRecipe recipe = new CraftBlastingRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/CampfireCookingRecipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/CampfireCookingRecipe.java.patch new file mode 100644 index 0000000000..281bcf37fa --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/CampfireCookingRecipe.java.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/world/item/crafting/CampfireCookingRecipe.java ++++ b/net/minecraft/world/item/crafting/CampfireCookingRecipe.java +@@ -3,21 +3,40 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftCampfireRecipe; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class CampfireCookingRecipe extends AbstractCookingRecipe { + +- public CampfireCookingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient ingredient, ItemStack itemstack, float f, int i) { +- super(RecipeType.CAMPFIRE_COOKING, s, cookingbookcategory, ingredient, itemstack, f, i); ++ public CampfireCookingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient recipeitemstack, ItemStack itemstack, float f, int i) { ++ super(RecipeType.CAMPFIRE_COOKING, s, cookingbookcategory, recipeitemstack, itemstack, f, i); + } + + @Override +- @Override + public ItemStack getToastSymbol() { + return new ItemStack(Blocks.CAMPFIRE); + } + + @Override +- @Override + public RecipeSerializer getSerializer() { + return RecipeSerializer.CAMPFIRE_COOKING_RECIPE; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftCampfireRecipe recipe = new CraftCampfireRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/CustomRecipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/CustomRecipe.java.patch new file mode 100644 index 0000000000..6edc4b87a8 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/CustomRecipe.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/world/item/crafting/CustomRecipe.java ++++ b/net/minecraft/world/item/crafting/CustomRecipe.java +@@ -3,8 +3,13 @@ + import net.minecraft.core.RegistryAccess; + import net.minecraft.world.item.ItemStack; + +-public abstract class CustomRecipe implements CraftingRecipe { ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end + ++public abstract class CustomRecipe implements RecipeCrafting { ++ + private final CraftingBookCategory category; + + public CustomRecipe(CraftingBookCategory craftingbookcategory) { +@@ -12,20 +17,24 @@ + } + + @Override +- @Override + public boolean isSpecial() { + return true; + } + + @Override +- @Override +- public ItemStack getResultItem(RegistryAccess registryaccess) { ++ public ItemStack getResultItem(RegistryAccess registryAccess) { + return ItemStack.EMPTY; + } + + @Override +- @Override + public CraftingBookCategory category() { + return this.category; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ return new org.bukkit.craftbukkit.inventory.CraftComplexRecipe(id, this); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/Ingredient.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/Ingredient.java.patch new file mode 100644 index 0000000000..56822af3df --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/Ingredient.java.patch @@ -0,0 +1,278 @@ +--- a/net/minecraft/world/item/crafting/Ingredient.java ++++ b/net/minecraft/world/item/crafting/Ingredient.java +@@ -25,33 +25,34 @@ + import net.minecraft.world.entity.player.StackedContents; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + + public final class Ingredient implements Predicate { + + public static final Ingredient EMPTY = new Ingredient(Stream.empty()); +- private final Ingredient.Value[] values; ++ private final Ingredient.Provider[] values; + @Nullable +- private ItemStack[] itemStacks; ++ public ItemStack[] itemStacks; + @Nullable + private IntList stackingIds; ++ public boolean exact; // CraftBukkit + public static final Codec CODEC = codec(true); + public static final Codec CODEC_NONEMPTY = codec(false); + +- private Ingredient(Stream stream) { +- this.values = (Ingredient.Value[]) stream.toArray((i) -> { +- return new Ingredient.Value[i]; ++ public Ingredient(Stream values) { ++ this.values = (Ingredient.Provider[]) values.toArray((i) -> { ++ return new Ingredient.Provider[i]; + }); + } + +- private Ingredient(Ingredient.Value[] aingredient_value) { +- this.values = aingredient_value; ++ private Ingredient(Ingredient.Provider[] arecipeitemstack_provider) { ++ this.values = arecipeitemstack_provider; + } + + public ItemStack[] getItems() { + if (this.itemStacks == null) { +- this.itemStacks = (ItemStack[]) Arrays.stream(this.values).flatMap((ingredient_value) -> { +- return ingredient_value.getItems().stream(); ++ this.itemStacks = (ItemStack[]) Arrays.stream(this.values).flatMap((recipeitemstack_provider) -> { ++ return recipeitemstack_provider.getItems().stream(); + }).distinct().toArray((i) -> { + return new ItemStack[i]; + }); +@@ -60,12 +61,11 @@ + return this.itemStacks; + } + +- @Override +- public boolean test(@Nullable ItemStack itemstack) { +- if (itemstack == null) { ++ public boolean test(@Nullable ItemStack stack) { ++ if (stack == null) { + return false; + } else if (this.isEmpty()) { +- return itemstack.isEmpty(); ++ return stack.isEmpty(); + } else { + ItemStack[] aitemstack = this.getItems(); + int i = aitemstack.length; +@@ -73,7 +73,16 @@ + for (int j = 0; j < i; ++j) { + ItemStack itemstack1 = aitemstack[j]; + +- if (itemstack1.is(itemstack.getItem())) { ++ // CraftBukkit start ++ if (exact) { ++ if (itemstack1.getItem() == stack.getItem() && ItemStack.isSameItemSameTags(stack, itemstack1)) { ++ return true; ++ } ++ ++ continue; ++ } ++ // CraftBukkit end ++ if (itemstack1.is(stack.getItem())) { + return true; + } + } +@@ -102,92 +111,91 @@ + return this.stackingIds; + } + +- public void toNetwork(FriendlyByteBuf friendlybytebuf) { +- friendlybytebuf.writeCollection(Arrays.asList(this.getItems()), FriendlyByteBuf::writeItem); ++ public void toNetwork(FriendlyByteBuf buffer) { ++ buffer.writeCollection(Arrays.asList(this.getItems()), FriendlyByteBuf::writeItem); + } + + public boolean isEmpty() { + return this.values.length == 0; + } + +- @Override + public boolean equals(Object object) { + if (object instanceof Ingredient) { +- Ingredient ingredient = (Ingredient) object; ++ Ingredient recipeitemstack = (Ingredient) object; + +- return Arrays.equals(this.values, ingredient.values); ++ return Arrays.equals(this.values, recipeitemstack.values); + } else { + return false; + } + } + +- private static Ingredient fromValues(Stream stream) { +- Ingredient ingredient = new Ingredient(stream); ++ private static Ingredient fromValues(Stream stream) { ++ Ingredient recipeitemstack = new Ingredient(stream); + +- return ingredient.isEmpty() ? Ingredient.EMPTY : ingredient; ++ return recipeitemstack.isEmpty() ? Ingredient.EMPTY : recipeitemstack; + } + + public static Ingredient of() { + return Ingredient.EMPTY; + } + +- public static Ingredient of(ItemLike... aitemlike) { +- return of(Arrays.stream(aitemlike).map(ItemStack::new)); ++ public static Ingredient of(IMaterial... items) { ++ return of(Arrays.stream(items).map(ItemStack::new)); + } + +- public static Ingredient of(ItemStack... aitemstack) { +- return of(Arrays.stream(aitemstack)); ++ public static Ingredient of(ItemStack... stacks) { ++ return of(Arrays.stream(stacks)); + } + +- public static Ingredient of(Stream stream) { +- return fromValues(stream.filter((itemstack) -> { ++ public static Ingredient of(Stream stacks) { ++ return fromValues(stacks.filter((itemstack) -> { + return !itemstack.isEmpty(); + }).map(Ingredient.ItemValue::new)); + } + +- public static Ingredient of(TagKey tagkey) { +- return fromValues(Stream.of(new Ingredient.TagValue(tagkey))); ++ public static Ingredient of(TagKey tag) { ++ return fromValues(Stream.of(new Ingredient.TagValue(tag))); + } + +- public static Ingredient fromNetwork(FriendlyByteBuf friendlybytebuf) { +- return fromValues(friendlybytebuf.readList(FriendlyByteBuf::readItem).stream().map(Ingredient.ItemValue::new)); ++ public static Ingredient fromNetwork(FriendlyByteBuf buffer) { ++ return fromValues(buffer.readList(FriendlyByteBuf::readItem).stream().map(Ingredient.ItemValue::new)); + } + + private static Codec codec(boolean flag) { +- Codec codec = Codec.list(Ingredient.Value.CODEC).comapFlatMap((list) -> { ++ Codec codec = Codec.list(Ingredient.Provider.CODEC).comapFlatMap((list) -> { + return !flag && list.size() < 1 ? DataResult.error(() -> { + return "Item array cannot be empty, at least one item must be defined"; +- }) : DataResult.success((Ingredient.Value[]) list.toArray(new Ingredient.Value[0])); ++ }) : DataResult.success((Ingredient.Provider[]) list.toArray(new Ingredient.Provider[0])); + }, List::of); + +- return ExtraCodecs.either(codec, Ingredient.Value.CODEC).flatComapMap((either) -> { +- return (Ingredient) either.map(Ingredient::new, (ingredient_value) -> { +- return new Ingredient(new Ingredient.Value[]{ingredient_value}); ++ return ExtraCodecs.either(codec, Ingredient.Provider.CODEC).flatComapMap((either) -> { ++ return (Ingredient) either.map(Ingredient::new, (recipeitemstack_provider) -> { ++ return new Ingredient(new Ingredient.Provider[]{recipeitemstack_provider}); + }); +- }, (ingredient) -> { +- return ingredient.values.length == 1 ? DataResult.success(Either.right(ingredient.values[0])) : (ingredient.values.length == 0 && !flag ? DataResult.error(() -> { ++ }, (recipeitemstack) -> { ++ return recipeitemstack.values.length == 1 ? DataResult.success(Either.right(recipeitemstack.values[0])) : (recipeitemstack.values.length == 0 && !flag ? DataResult.error(() -> { + return "Item array cannot be empty, at least one item must be defined"; +- }) : DataResult.success(Either.left(ingredient.values))); ++ }) : DataResult.success(Either.left(recipeitemstack.values))); + }); + } + +- private interface Value { ++ public interface Provider { + +- Codec CODEC = ExtraCodecs.xor(Ingredient.ItemValue.CODEC, Ingredient.TagValue.CODEC).xmap((either) -> { +- return (Ingredient.Value) either.map((ingredient_itemvalue) -> { +- return ingredient_itemvalue; +- }, (ingredient_tagvalue) -> { +- return ingredient_tagvalue; ++ Codec CODEC = ExtraCodecs.xor(Ingredient.ItemValue.CODEC, Ingredient.TagValue.CODEC).xmap((either) -> { ++ return (Ingredient.Provider) either.map((recipeitemstack_stackprovider) -> { ++ return recipeitemstack_stackprovider; ++ }, (recipeitemstack_b) -> { ++ return recipeitemstack_b; + }); +- }, (ingredient_value) -> { +- if (ingredient_value instanceof Ingredient.TagValue) { +- Ingredient.TagValue ingredient_tagvalue = (Ingredient.TagValue) ingredient_value; ++ }, (recipeitemstack_provider) -> { ++ if (recipeitemstack_provider instanceof Ingredient.TagValue) { ++ Ingredient.TagValue recipeitemstack_b = (Ingredient.TagValue) recipeitemstack_provider; + +- return Either.right(ingredient_tagvalue); +- } else if (ingredient_value instanceof Ingredient.ItemValue) { +- Ingredient.ItemValue ingredient_itemvalue = (Ingredient.ItemValue) ingredient_value; ++ return Either.right(recipeitemstack_b); ++ } else if (recipeitemstack_provider instanceof Ingredient.ItemValue) { ++ Ingredient.ItemValue recipeitemstack_stackprovider = (Ingredient.ItemValue) recipeitemstack_provider; + +- return Either.left(ingredient_itemvalue); ++ return Either.left(recipeitemstack_stackprovider); + } else { + throw new UnsupportedOperationException("This is neither an item value nor a tag value."); + } +@@ -196,27 +204,25 @@ + Collection getItems(); + } + +- private static record TagValue(TagKey tag) implements Ingredient.Value { ++ private static record TagValue(TagKey tag) implements Ingredient.Provider { + + static final Codec CODEC = RecordCodecBuilder.create((instance) -> { +- return instance.group(TagKey.codec(Registries.ITEM).fieldOf("tag").forGetter((ingredient_tagvalue) -> { +- return ingredient_tagvalue.tag; ++ return instance.group(TagKey.codec(Registries.ITEM).fieldOf("tag").forGetter((recipeitemstack_b) -> { ++ return recipeitemstack_b.tag; + })).apply(instance, Ingredient.TagValue::new); + }); + +- @Override + public boolean equals(Object object) { + if (object instanceof Ingredient.TagValue) { +- Ingredient.TagValue ingredient_tagvalue = (Ingredient.TagValue) object; ++ Ingredient.TagValue recipeitemstack_b = (Ingredient.TagValue) object; + +- return ingredient_tagvalue.tag.location().equals(this.tag.location()); ++ return recipeitemstack_b.tag.location().equals(this.tag.location()); + } else { + return false; + } + } + + @Override +- @Override + public Collection getItems() { + List list = Lists.newArrayList(); + Iterator iterator = BuiltInRegistries.ITEM.getTagOrEmpty(this.tag).iterator(); +@@ -231,27 +237,25 @@ + } + } + +- private static record ItemValue(ItemStack item) implements Ingredient.Value { ++ public static record ItemValue(ItemStack item) implements Ingredient.Provider { + + static final Codec CODEC = RecordCodecBuilder.create((instance) -> { +- return instance.group(ItemStack.SINGLE_ITEM_CODEC.fieldOf("item").forGetter((ingredient_itemvalue) -> { +- return ingredient_itemvalue.item; ++ return instance.group(ItemStack.SINGLE_ITEM_CODEC.fieldOf("item").forGetter((recipeitemstack_stackprovider) -> { ++ return recipeitemstack_stackprovider.item; + })).apply(instance, Ingredient.ItemValue::new); + }); + +- @Override + public boolean equals(Object object) { + if (!(object instanceof Ingredient.ItemValue)) { + return false; + } else { +- Ingredient.ItemValue ingredient_itemvalue = (Ingredient.ItemValue) object; ++ Ingredient.ItemValue recipeitemstack_stackprovider = (Ingredient.ItemValue) object; + +- return ingredient_itemvalue.item.getItem().equals(this.item.getItem()) && ingredient_itemvalue.item.getCount() == this.item.getCount(); ++ return recipeitemstack_stackprovider.item.getItem().equals(this.item.getItem()) && recipeitemstack_stackprovider.item.getCount() == this.item.getCount(); + } + } + + @Override +- @Override + public Collection getItems() { + return Collections.singleton(this.item); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/Recipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/Recipe.java.patch new file mode 100644 index 0000000000..a1bd9ee38e --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/Recipe.java.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/item/crafting/Recipe.java ++++ b/net/minecraft/world/item/crafting/Recipe.java +@@ -22,11 +22,11 @@ + + ItemStack getResultItem(RegistryAccess registryAccess); + +- default NonNullList getRemainingItems(C c0) { +- NonNullList nonnulllist = NonNullList.withSize(c0.getContainerSize(), ItemStack.EMPTY); ++ default NonNullList getRemainingItems(C container) { ++ NonNullList nonnulllist = NonNullList.withSize(container.getContainerSize(), ItemStack.EMPTY); + + for (int i = 0; i < nonnulllist.size(); ++i) { +- Item item = c0.getItem(i).getItem(); ++ Item item = container.getItem(i).getItem(); + + if (item.hasCraftingRemainingItem()) { + nonnulllist.set(i, new ItemStack(item.getCraftingRemainingItem())); +@@ -63,8 +63,10 @@ + default boolean isIncomplete() { + NonNullList nonnulllist = this.getIngredients(); + +- return nonnulllist.isEmpty() || nonnulllist.stream().anyMatch((ingredient) -> { +- return ingredient.getItems().length == 0; ++ return nonnulllist.isEmpty() || nonnulllist.stream().anyMatch((recipeitemstack) -> { ++ return recipeitemstack.getItems().length == 0; + }); + } ++ ++ org.bukkit.inventory.Recipe toBukkitRecipe(org.bukkit.NamespacedKey id); // CraftBukkit + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/RecipeHolder.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/RecipeHolder.java.patch new file mode 100644 index 0000000000..16a1050265 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/RecipeHolder.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/item/crafting/RecipeHolder.java ++++ b/net/minecraft/world/item/crafting/RecipeHolder.java +@@ -1,10 +1,17 @@ + package net.minecraft.world.item.crafting; + + import net.minecraft.resources.ResourceLocation; ++// CraftBukkit start ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.inventory.Recipe; + +-public record RecipeHolder> (ResourceLocation id, T value) { ++public record RecipeHolder>(ResourceLocation id, T value) { + +- @Override ++ public final Recipe toBukkitRecipe() { ++ return this.value.toBukkitRecipe(CraftNamespacedKey.fromMinecraft(this.id)); ++ } ++ // CraftBukkit end ++ + public boolean equals(Object object) { + if (this == object) { + return true; +@@ -25,12 +32,10 @@ + } + } + +- @Override + public int hashCode() { + return this.id.hashCode(); + } + +- @Override + public String toString() { + return this.id.toString(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/RecipeManager.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/RecipeManager.java.patch new file mode 100644 index 0000000000..ae8c6942ab --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/RecipeManager.java.patch @@ -0,0 +1,274 @@ +--- a/net/minecraft/world/item/crafting/RecipeManager.java ++++ b/net/minecraft/world/item/crafting/RecipeManager.java +@@ -24,21 +24,26 @@ + import javax.annotation.Nullable; + import net.minecraft.Util; + import net.minecraft.core.NonNullList; ++import net.minecraft.world.Container; ++import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.level.Level; ++import org.slf4j.Logger; ++ ++// CraftBukkit start ++import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; ++import net.minecraft.core.registries.BuiltInRegistries; ++// CraftBukkit end + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.packs.resources.ResourceManager; + import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; + import net.minecraft.util.GsonHelper; + import net.minecraft.util.profiling.ProfilerFiller; +-import net.minecraft.world.Container; +-import net.minecraft.world.item.ItemStack; +-import net.minecraft.world.level.Level; +-import org.slf4j.Logger; + + public class RecipeManager extends SimpleJsonResourceReloadListener { + + private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().disableHtmlEscaping().create(); + private static final Logger LOGGER = LogUtils.getLogger(); +- private Map, Map>> recipes = ImmutableMap.of(); ++ public Map, Object2ObjectLinkedOpenHashMap>> recipes = ImmutableMap.of(); // CraftBukkit + private Map> byName = ImmutableMap.of(); + private boolean hasErrors; + +@@ -46,98 +51,121 @@ + super(RecipeManager.GSON, "recipes"); + } + +- @Override +- protected void apply(Map map, ResourceManager resourcemanager, ProfilerFiller profilerfiller) { ++ protected void apply(Map object, ResourceManager resourceManager, ProfilerFiller profiler) { + this.hasErrors = false; +- Map, Builder>> map1 = Maps.newHashMap(); ++ // CraftBukkit start - SPIGOT-5667 make sure all types are populated and mutable ++ Map, Object2ObjectLinkedOpenHashMap>> map1 = Maps.newHashMap(); ++ for (RecipeType recipeType : BuiltInRegistries.RECIPE_TYPE) { ++ map1.put(recipeType, new Object2ObjectLinkedOpenHashMap<>()); ++ } ++ // CraftBukkit end + Builder> builder = ImmutableMap.builder(); +- Iterator iterator = map.entrySet().iterator(); ++ Iterator iterator = object.entrySet().iterator(); + + while (iterator.hasNext()) { + Entry entry = (Entry) iterator.next(); +- ResourceLocation resourcelocation = (ResourceLocation) entry.getKey(); ++ ResourceLocation minecraftkey = (ResourceLocation) entry.getKey(); + + try { +- RecipeHolder recipeholder = fromJson(resourcelocation, GsonHelper.convertToJsonObject((JsonElement) entry.getValue(), "top element")); ++ RecipeHolder recipeholder = fromJson(minecraftkey, GsonHelper.convertToJsonObject((JsonElement) entry.getValue(), "top element")); + +- ((Builder) map1.computeIfAbsent(recipeholder.value().getType(), (recipetype) -> { +- return ImmutableMap.builder(); +- })).put(resourcelocation, recipeholder); +- builder.put(resourcelocation, recipeholder); ++ // CraftBukkit start ++ (map1.computeIfAbsent(recipeholder.value().getType(), (recipes) -> { ++ return new Object2ObjectLinkedOpenHashMap<>(); ++ // CraftBukkit end ++ })).put(minecraftkey, recipeholder); ++ builder.put(minecraftkey, recipeholder); + } catch (IllegalArgumentException | JsonParseException jsonparseexception) { +- RecipeManager.LOGGER.error("Parsing error loading recipe {}", resourcelocation, jsonparseexception); ++ RecipeManager.LOGGER.error("Parsing error loading recipe {}", minecraftkey, jsonparseexception); + } + } + + this.recipes = (Map) map1.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry1) -> { +- return ((Builder) entry1.getValue()).build(); ++ return (entry1.getValue()); // CraftBukkit + })); +- this.byName = builder.build(); ++ this.byName = Maps.newHashMap(builder.build()); // CraftBukkit + RecipeManager.LOGGER.info("Loaded {} recipes", map1.size()); + } + ++ // CraftBukkit start ++ public void addRecipe(RecipeHolder irecipe) { ++ Object2ObjectLinkedOpenHashMap> map = this.recipes.get(irecipe.value().getType()); // CraftBukkit ++ ++ if (byName.containsKey(irecipe.id()) || map.containsKey(irecipe.id())) { ++ throw new IllegalStateException("Duplicate recipe ignored with ID " + irecipe.id()); ++ } else { ++ map.putAndMoveToFirst(irecipe.id(), irecipe); // CraftBukkit - SPIGOT-4638: last recipe gets priority ++ byName.put(irecipe.id(), irecipe); ++ } ++ } ++ // CraftBukkit end ++ + public boolean hadErrorsLoading() { + return this.hasErrors; + } + +- public > Optional> getRecipeFor(RecipeType recipetype, C c0, Level level) { +- return this.byType(recipetype).values().stream().filter((recipeholder) -> { +- return recipeholder.value().matches(c0, level); ++ public > Optional> getRecipeFor(RecipeType recipeType, C inventory, Level level) { ++ // CraftBukkit start ++ Optional> recipe = this.byType(recipeType).values().stream().filter((recipeholder) -> { ++ return recipeholder.value().matches(inventory, level); + }).findFirst(); ++ inventory.setCurrentRecipe(recipe.orElse(null)); // CraftBukkit - Clear recipe when no recipe is found ++ return recipe; ++ // CraftBukkit end + } + +- public > Optional>> getRecipeFor(RecipeType recipetype, C c0, Level level, @Nullable ResourceLocation resourcelocation) { +- Map> map = this.byType(recipetype); ++ public > Optional>> getRecipeFor(RecipeType recipeType, C inventory, Level level, @Nullable ResourceLocation lastRecipe) { ++ Map> map = this.byType(recipeType); + +- if (resourcelocation != null) { +- RecipeHolder recipeholder = (RecipeHolder) map.get(resourcelocation); ++ if (lastRecipe != null) { ++ RecipeHolder recipeholder = (RecipeHolder) map.get(lastRecipe); + +- if (recipeholder != null && recipeholder.value().matches(c0, level)) { +- return Optional.of(Pair.of(resourcelocation, recipeholder)); ++ if (recipeholder != null && recipeholder.value().matches(inventory, level)) { ++ return Optional.of(Pair.of(lastRecipe, recipeholder)); + } + } + + return map.entrySet().stream().filter((entry) -> { +- return ((RecipeHolder) entry.getValue()).value().matches(c0, level); ++ return ((RecipeHolder) entry.getValue()).value().matches(inventory, level); + }).findFirst().map((entry) -> { + return Pair.of((ResourceLocation) entry.getKey(), (RecipeHolder) entry.getValue()); + }); + } + +- public > List> getAllRecipesFor(RecipeType recipetype) { +- return List.copyOf(this.byType(recipetype).values()); ++ public > List> getAllRecipesFor(RecipeType recipeType) { ++ return List.copyOf(this.byType(recipeType).values()); + } + +- public > List> getRecipesFor(RecipeType recipetype, C c0, Level level) { +- return (List) this.byType(recipetype).values().stream().filter((recipeholder) -> { +- return recipeholder.value().matches(c0, level); ++ public > List> getRecipesFor(RecipeType recipeType, C inventory, Level level) { ++ return (List) this.byType(recipeType).values().stream().filter((recipeholder) -> { ++ return recipeholder.value().matches(inventory, level); + }).sorted(Comparator.comparing((recipeholder) -> { + return recipeholder.value().getResultItem(level.registryAccess()).getDescriptionId(); + })).collect(Collectors.toList()); + } + +- private > Map> byType(RecipeType recipetype) { +- return (Map) this.recipes.getOrDefault(recipetype, Collections.emptyMap()); ++ private > Map> byType(RecipeType recipeType) { ++ return (Map) this.recipes.getOrDefault(recipeType, new Object2ObjectLinkedOpenHashMap<>()); // CraftBukkit + } + +- public > NonNullList getRemainingItemsFor(RecipeType recipetype, C c0, Level level) { +- Optional> optional = this.getRecipeFor(recipetype, c0, level); ++ public > NonNullList getRemainingItemsFor(RecipeType recipeType, C inventory, Level level) { ++ Optional> optional = this.getRecipeFor(recipeType, inventory, level); + + if (optional.isPresent()) { +- return ((RecipeHolder) optional.get()).value().getRemainingItems(c0); ++ return ((RecipeHolder) optional.get()).value().getRemainingItems(inventory); + } else { +- NonNullList nonnulllist = NonNullList.withSize(c0.getContainerSize(), ItemStack.EMPTY); ++ NonNullList nonnulllist = NonNullList.withSize(inventory.getContainerSize(), ItemStack.EMPTY); + + for (int i = 0; i < nonnulllist.size(); ++i) { +- nonnulllist.set(i, c0.getItem(i)); ++ nonnulllist.set(i, inventory.getItem(i)); + } + + return nonnulllist; + } + } + +- public Optional> byKey(ResourceLocation resourcelocation) { +- return Optional.ofNullable((RecipeHolder) this.byName.get(resourcelocation)); ++ public Optional> byKey(ResourceLocation recipeId) { ++ return Optional.ofNullable((RecipeHolder) this.byName.get(recipeId)); + } + + public Collection> getRecipes() { +@@ -152,43 +180,62 @@ + }); + } + +- protected static RecipeHolder fromJson(ResourceLocation resourcelocation, JsonObject jsonobject) { +- Recipe recipe = (Recipe) Util.getOrThrow(Recipe.CODEC.parse(JsonOps.INSTANCE, jsonobject), JsonParseException::new); ++ protected static RecipeHolder fromJson(ResourceLocation minecraftkey, JsonObject jsonobject) { ++ Recipe irecipe = (Recipe) Util.getOrThrow(Recipe.CODEC.parse(JsonOps.INSTANCE, jsonobject), JsonParseException::new); + +- return new RecipeHolder<>(resourcelocation, recipe); ++ return new RecipeHolder<>(minecraftkey, irecipe); + } + +- public void replaceRecipes(Iterable> iterable) { ++ public void replaceRecipes(Iterable> recipes) { + this.hasErrors = false; +- Map, Map>> map = Maps.newHashMap(); ++ Map, Object2ObjectLinkedOpenHashMap>> map = Maps.newHashMap(); // CraftBukkit + Builder> builder = ImmutableMap.builder(); + +- iterable.forEach((recipeholder) -> { +- Map> map1 = (Map) map.computeIfAbsent(recipeholder.value().getType(), (recipetype) -> { +- return Maps.newHashMap(); ++ recipes.forEach((recipeholder) -> { ++ Map> map1 = (Map) map.computeIfAbsent(recipeholder.value().getType(), (recipes) -> { ++ return new Object2ObjectLinkedOpenHashMap<>(); // CraftBukkit + }); +- ResourceLocation resourcelocation = recipeholder.id(); +- RecipeHolder recipeholder1 = (RecipeHolder) map1.put(resourcelocation, recipeholder); ++ ResourceLocation minecraftkey = recipeholder.id(); ++ RecipeHolder recipeholder1 = (RecipeHolder) map1.put(minecraftkey, recipeholder); + +- builder.put(resourcelocation, recipeholder); ++ builder.put(minecraftkey, recipeholder); + if (recipeholder1 != null) { +- throw new IllegalStateException("Duplicate recipe ignored with ID " + resourcelocation); ++ throw new IllegalStateException("Duplicate recipe ignored with ID " + minecraftkey); + } + }); + this.recipes = ImmutableMap.copyOf(map); +- this.byName = builder.build(); ++ this.byName = Maps.newHashMap(builder.build()); // CraftBukkit + } + +- public static > RecipeManager.CachedCheck createCheck(final RecipeType recipetype) { ++ // CraftBukkit start ++ public boolean removeRecipe(ResourceLocation mcKey) { ++ for (Object2ObjectLinkedOpenHashMap> recipes : recipes.values()) { ++ recipes.remove(mcKey); ++ } ++ ++ return byName.remove(mcKey) != null; ++ } ++ ++ public void clearRecipes() { ++ this.recipes = Maps.newHashMap(); ++ ++ for (RecipeType recipeType : BuiltInRegistries.RECIPE_TYPE) { ++ this.recipes.put(recipeType, new Object2ObjectLinkedOpenHashMap<>()); ++ } ++ ++ this.byName = Maps.newHashMap(); ++ } ++ // CraftBukkit end ++ ++ public static > RecipeManager.CachedCheck createCheck(final RecipeType recipeType) { + return new RecipeManager.CachedCheck() { + @Nullable + private ResourceLocation lastRecipe; + + @Override +- @Override +- public Optional> getRecipeFor(C c0, Level level) { +- RecipeManager recipemanager = level.getRecipeManager(); +- Optional>> optional = recipemanager.getRecipeFor(recipetype, c0, level, this.lastRecipe); ++ public Optional> getRecipeFor(C container, Level level) { ++ RecipeManager craftingmanager = level.getRecipeManager(); ++ Optional>> optional = craftingmanager.getRecipeFor(recipeType, container, level, this.lastRecipe); + + if (optional.isPresent()) { + Pair> pair = (Pair) optional.get(); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/ShapedRecipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/ShapedRecipe.java.patch new file mode 100644 index 0000000000..28bf8b2493 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/ShapedRecipe.java.patch @@ -0,0 +1,235 @@ +--- a/net/minecraft/world/item/crafting/ShapedRecipe.java ++++ b/net/minecraft/world/item/crafting/ShapedRecipe.java +@@ -6,11 +6,18 @@ + import net.minecraft.core.RegistryAccess; + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.util.ExtraCodecs; +-import net.minecraft.world.inventory.CraftingContainer; ++import net.minecraft.world.inventory.InventoryCrafting; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftShapedRecipe; ++import org.bukkit.inventory.RecipeChoice; ++// CraftBukkit end + +-public class ShapedRecipe implements CraftingRecipe { ++public class ShapedRecipe implements RecipeCrafting { + + final ShapedRecipePattern pattern; + final ItemStack result; +@@ -30,56 +37,109 @@ + this(s, craftingbookcategory, shapedrecipepattern, itemstack, true); + } + ++ // CraftBukkit start + @Override ++ public org.bukkit.inventory.ShapedRecipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ CraftShapedRecipe recipe = new CraftShapedRecipe(id, result, this); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ switch (this.pattern.height()) { ++ case 1: ++ switch (this.pattern.width()) { ++ case 1: ++ recipe.shape("a"); ++ break; ++ case 2: ++ recipe.shape("ab"); ++ break; ++ case 3: ++ recipe.shape("abc"); ++ break; ++ } ++ break; ++ case 2: ++ switch (this.pattern.width()) { ++ case 1: ++ recipe.shape("a","b"); ++ break; ++ case 2: ++ recipe.shape("ab","cd"); ++ break; ++ case 3: ++ recipe.shape("abc","def"); ++ break; ++ } ++ break; ++ case 3: ++ switch (this.pattern.width()) { ++ case 1: ++ recipe.shape("a","b","c"); ++ break; ++ case 2: ++ recipe.shape("ab","cd","ef"); ++ break; ++ case 3: ++ recipe.shape("abc","def","ghi"); ++ break; ++ } ++ break; ++ } ++ char c = 'a'; ++ for (Ingredient list : this.pattern.ingredients()) { ++ RecipeChoice choice = CraftRecipe.toBukkit(list); ++ if (choice != null) { ++ recipe.setIngredient(c, choice); ++ } ++ ++ c++; ++ } ++ return recipe; ++ } ++ // CraftBukkit end ++ + @Override + public RecipeSerializer getSerializer() { + return RecipeSerializer.SHAPED_RECIPE; + } + + @Override +- @Override + public String getGroup() { + return this.group; + } + + @Override +- @Override + public CraftingBookCategory category() { + return this.category; + } + + @Override +- @Override +- public ItemStack getResultItem(RegistryAccess registryaccess) { ++ public ItemStack getResultItem(RegistryAccess registryAccess) { + return this.result; + } + + @Override +- @Override + public NonNullList getIngredients() { + return this.pattern.ingredients(); + } + + @Override +- @Override + public boolean showNotification() { + return this.showNotification; + } + + @Override +- @Override +- public boolean canCraftInDimensions(int i, int j) { +- return i >= this.pattern.width() && j >= this.pattern.height(); ++ public boolean canCraftInDimensions(int width, int height) { ++ return width >= this.pattern.width() && height >= this.pattern.height(); + } + +- @Override +- public boolean matches(CraftingContainer craftingcontainer, Level level) { +- return this.pattern.matches(craftingcontainer); ++ public boolean matches(InventoryCrafting inv, Level level) { ++ return this.pattern.matches(inv); + } + +- @Override +- public ItemStack assemble(CraftingContainer craftingcontainer, RegistryAccess registryaccess) { +- return this.getResultItem(registryaccess).copy(); ++ public ItemStack assemble(InventoryCrafting container, RegistryAccess registryAccess) { ++ return this.getResultItem(registryAccess).copy(); + } + + public int getWidth() { +@@ -91,60 +151,56 @@ + } + + @Override +- @Override + public boolean isIncomplete() { + NonNullList nonnulllist = this.getIngredients(); + +- return nonnulllist.isEmpty() || nonnulllist.stream().filter((ingredient) -> { +- return !ingredient.isEmpty(); +- }).anyMatch((ingredient) -> { +- return ingredient.getItems().length == 0; ++ return nonnulllist.isEmpty() || nonnulllist.stream().filter((recipeitemstack) -> { ++ return !recipeitemstack.isEmpty(); ++ }).anyMatch((recipeitemstack) -> { ++ return recipeitemstack.getItems().length == 0; + }); + } + + public static class Serializer implements RecipeSerializer { + + public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { +- return instance.group(ExtraCodecs.strictOptionalField(Codec.STRING, "group", "").forGetter((shapedrecipe) -> { +- return shapedrecipe.group; +- }), CraftingBookCategory.CODEC.fieldOf("category").orElse(CraftingBookCategory.MISC).forGetter((shapedrecipe) -> { +- return shapedrecipe.category; +- }), ShapedRecipePattern.MAP_CODEC.forGetter((shapedrecipe) -> { +- return shapedrecipe.pattern; +- }), ItemStack.ITEM_WITH_COUNT_CODEC.fieldOf("result").forGetter((shapedrecipe) -> { +- return shapedrecipe.result; +- }), ExtraCodecs.strictOptionalField(Codec.BOOL, "show_notification", true).forGetter((shapedrecipe) -> { +- return shapedrecipe.showNotification; ++ return instance.group(ExtraCodecs.strictOptionalField(Codec.STRING, "group", "").forGetter((shapedrecipes) -> { ++ return shapedrecipes.group; ++ }), CraftingBookCategory.CODEC.fieldOf("category").orElse(CraftingBookCategory.MISC).forGetter((shapedrecipes) -> { ++ return shapedrecipes.category; ++ }), ShapedRecipePattern.MAP_CODEC.forGetter((shapedrecipes) -> { ++ return shapedrecipes.pattern; ++ }), ItemStack.ITEM_WITH_COUNT_CODEC.fieldOf("result").forGetter((shapedrecipes) -> { ++ return shapedrecipes.result; ++ }), ExtraCodecs.strictOptionalField(Codec.BOOL, "show_notification", true).forGetter((shapedrecipes) -> { ++ return shapedrecipes.showNotification; + })).apply(instance, ShapedRecipe::new); + }); + + public Serializer() {} + + @Override +- @Override + public Codec codec() { + return ShapedRecipe.Serializer.CODEC; + } + + @Override +- @Override +- public ShapedRecipe fromNetwork(FriendlyByteBuf friendlybytebuf) { +- String s = friendlybytebuf.readUtf(); +- CraftingBookCategory craftingbookcategory = (CraftingBookCategory) friendlybytebuf.readEnum(CraftingBookCategory.class); +- ShapedRecipePattern shapedrecipepattern = ShapedRecipePattern.fromNetwork(friendlybytebuf); +- ItemStack itemstack = friendlybytebuf.readItem(); +- boolean flag = friendlybytebuf.readBoolean(); ++ public ShapedRecipe fromNetwork(FriendlyByteBuf packetdataserializer) { ++ String s = packetdataserializer.readUtf(); ++ CraftingBookCategory craftingbookcategory = (CraftingBookCategory) packetdataserializer.readEnum(CraftingBookCategory.class); ++ ShapedRecipePattern shapedrecipepattern = ShapedRecipePattern.fromNetwork(packetdataserializer); ++ ItemStack itemstack = packetdataserializer.readItem(); ++ boolean flag = packetdataserializer.readBoolean(); + + return new ShapedRecipe(s, craftingbookcategory, shapedrecipepattern, itemstack, flag); + } + +- @Override +- public void toNetwork(FriendlyByteBuf friendlybytebuf, ShapedRecipe shapedrecipe) { +- friendlybytebuf.writeUtf(shapedrecipe.group); +- friendlybytebuf.writeEnum(shapedrecipe.category); +- shapedrecipe.pattern.toNetwork(friendlybytebuf); +- friendlybytebuf.writeItem(shapedrecipe.result); +- friendlybytebuf.writeBoolean(shapedrecipe.showNotification); ++ public void toNetwork(FriendlyByteBuf buffer, ShapedRecipe recipe) { ++ buffer.writeUtf(recipe.group); ++ buffer.writeEnum(recipe.category); ++ recipe.pattern.toNetwork(buffer); ++ buffer.writeItem(recipe.result); ++ buffer.writeBoolean(recipe.showNotification); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/ShapelessRecipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/ShapelessRecipe.java.patch new file mode 100644 index 0000000000..c3b7af75af --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/ShapelessRecipe.java.patch @@ -0,0 +1,204 @@ +--- a/net/minecraft/world/item/crafting/ShapelessRecipe.java ++++ b/net/minecraft/world/item/crafting/ShapelessRecipe.java +@@ -10,11 +10,17 @@ + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.util.ExtraCodecs; + import net.minecraft.world.entity.player.StackedContents; +-import net.minecraft.world.inventory.CraftingContainer; ++import net.minecraft.world.inventory.InventoryCrafting; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftShapelessRecipe; ++// CraftBukkit end + +-public class ShapelessRecipe implements CraftingRecipe { ++public class ShapelessRecipe implements RecipeCrafting { + + final String group; + final CraftingBookCategory category; +@@ -28,129 +34,134 @@ + this.ingredients = nonnulllist; + } + ++ // CraftBukkit start ++ @SuppressWarnings("unchecked") + @Override ++ public org.bukkit.inventory.ShapelessRecipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ CraftShapelessRecipe recipe = new CraftShapelessRecipe(id, result, this); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ for (Ingredient list : this.ingredients) { ++ recipe.addIngredient(CraftRecipe.toBukkit(list)); ++ } ++ return recipe; ++ } ++ // CraftBukkit end ++ + @Override + public RecipeSerializer getSerializer() { + return RecipeSerializer.SHAPELESS_RECIPE; + } + + @Override +- @Override + public String getGroup() { + return this.group; + } + + @Override +- @Override + public CraftingBookCategory category() { + return this.category; + } + + @Override +- @Override +- public ItemStack getResultItem(RegistryAccess registryaccess) { ++ public ItemStack getResultItem(RegistryAccess registryAccess) { + return this.result; + } + + @Override +- @Override + public NonNullList getIngredients() { + return this.ingredients; + } + +- @Override +- public boolean matches(CraftingContainer craftingcontainer, Level level) { +- StackedContents stackedcontents = new StackedContents(); ++ public boolean matches(InventoryCrafting inv, Level level) { ++ StackedContents autorecipestackmanager = new StackedContents(); + int i = 0; + +- for (int j = 0; j < craftingcontainer.getContainerSize(); ++j) { +- ItemStack itemstack = craftingcontainer.getItem(j); ++ for (int j = 0; j < inv.getContainerSize(); ++j) { ++ ItemStack itemstack = inv.getItem(j); + + if (!itemstack.isEmpty()) { + ++i; +- stackedcontents.accountStack(itemstack, 1); ++ autorecipestackmanager.accountStack(itemstack, 1); + } + } + +- return i == this.ingredients.size() && stackedcontents.canCraft(this, (IntList) null); ++ return i == this.ingredients.size() && autorecipestackmanager.canCraft(this, (IntList) null); + } + +- @Override +- public ItemStack assemble(CraftingContainer craftingcontainer, RegistryAccess registryaccess) { ++ public ItemStack assemble(InventoryCrafting container, RegistryAccess registryAccess) { + return this.result.copy(); + } + + @Override +- @Override +- public boolean canCraftInDimensions(int i, int j) { +- return i * j >= this.ingredients.size(); ++ public boolean canCraftInDimensions(int width, int height) { ++ return width * height >= this.ingredients.size(); + } + + public static class Serializer implements RecipeSerializer { + + private static final Codec CODEC = RecordCodecBuilder.create((instance) -> { +- return instance.group(ExtraCodecs.strictOptionalField(Codec.STRING, "group", "").forGetter((shapelessrecipe) -> { +- return shapelessrecipe.group; +- }), CraftingBookCategory.CODEC.fieldOf("category").orElse(CraftingBookCategory.MISC).forGetter((shapelessrecipe) -> { +- return shapelessrecipe.category; +- }), ItemStack.ITEM_WITH_COUNT_CODEC.fieldOf("result").forGetter((shapelessrecipe) -> { +- return shapelessrecipe.result; ++ return instance.group(ExtraCodecs.strictOptionalField(Codec.STRING, "group", "").forGetter((shapelessrecipes) -> { ++ return shapelessrecipes.group; ++ }), CraftingBookCategory.CODEC.fieldOf("category").orElse(CraftingBookCategory.MISC).forGetter((shapelessrecipes) -> { ++ return shapelessrecipes.category; ++ }), ItemStack.ITEM_WITH_COUNT_CODEC.fieldOf("result").forGetter((shapelessrecipes) -> { ++ return shapelessrecipes.result; + }), Ingredient.CODEC_NONEMPTY.listOf().fieldOf("ingredients").flatXmap((list) -> { +- Ingredient[] aingredient = (Ingredient[]) list.stream().filter((ingredient) -> { +- return !ingredient.isEmpty(); ++ Ingredient[] arecipeitemstack = (Ingredient[]) list.stream().filter((recipeitemstack) -> { ++ return !recipeitemstack.isEmpty(); + }).toArray((i) -> { + return new Ingredient[i]; + }); + +- return aingredient.length == 0 ? DataResult.error(() -> { ++ return arecipeitemstack.length == 0 ? DataResult.error(() -> { + return "No ingredients for shapeless recipe"; +- }) : (aingredient.length > 9 ? DataResult.error(() -> { ++ }) : (arecipeitemstack.length > 9 ? DataResult.error(() -> { + return "Too many ingredients for shapeless recipe"; +- }) : DataResult.success(NonNullList.of(Ingredient.EMPTY, aingredient))); +- }, DataResult::success).forGetter((shapelessrecipe) -> { +- return shapelessrecipe.ingredients; ++ }) : DataResult.success(NonNullList.of(Ingredient.EMPTY, arecipeitemstack))); ++ }, DataResult::success).forGetter((shapelessrecipes) -> { ++ return shapelessrecipes.ingredients; + })).apply(instance, ShapelessRecipe::new); + }); + + public Serializer() {} + + @Override +- @Override + public Codec codec() { + return ShapelessRecipe.Serializer.CODEC; + } + + @Override +- @Override +- public ShapelessRecipe fromNetwork(FriendlyByteBuf friendlybytebuf) { +- String s = friendlybytebuf.readUtf(); +- CraftingBookCategory craftingbookcategory = (CraftingBookCategory) friendlybytebuf.readEnum(CraftingBookCategory.class); +- int i = friendlybytebuf.readVarInt(); ++ public ShapelessRecipe fromNetwork(FriendlyByteBuf packetdataserializer) { ++ String s = packetdataserializer.readUtf(); ++ CraftingBookCategory craftingbookcategory = (CraftingBookCategory) packetdataserializer.readEnum(CraftingBookCategory.class); ++ int i = packetdataserializer.readVarInt(); + NonNullList nonnulllist = NonNullList.withSize(i, Ingredient.EMPTY); + + for (int j = 0; j < nonnulllist.size(); ++j) { +- nonnulllist.set(j, Ingredient.fromNetwork(friendlybytebuf)); ++ nonnulllist.set(j, Ingredient.fromNetwork(packetdataserializer)); + } + +- ItemStack itemstack = friendlybytebuf.readItem(); ++ ItemStack itemstack = packetdataserializer.readItem(); + + return new ShapelessRecipe(s, craftingbookcategory, itemstack, nonnulllist); + } + +- @Override +- public void toNetwork(FriendlyByteBuf friendlybytebuf, ShapelessRecipe shapelessrecipe) { +- friendlybytebuf.writeUtf(shapelessrecipe.group); +- friendlybytebuf.writeEnum(shapelessrecipe.category); +- friendlybytebuf.writeVarInt(shapelessrecipe.ingredients.size()); +- Iterator iterator = shapelessrecipe.ingredients.iterator(); ++ public void toNetwork(FriendlyByteBuf buffer, ShapelessRecipe recipe) { ++ buffer.writeUtf(recipe.group); ++ buffer.writeEnum(recipe.category); ++ buffer.writeVarInt(recipe.ingredients.size()); ++ Iterator iterator = recipe.ingredients.iterator(); + + while (iterator.hasNext()) { +- Ingredient ingredient = (Ingredient) iterator.next(); ++ Ingredient recipeitemstack = (Ingredient) iterator.next(); + +- ingredient.toNetwork(friendlybytebuf); ++ recipeitemstack.toNetwork(buffer); + } + +- friendlybytebuf.writeItem(shapelessrecipe.result); ++ buffer.writeItem(recipe.result); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmeltingRecipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmeltingRecipe.java.patch new file mode 100644 index 0000000000..6869ddcb4f --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmeltingRecipe.java.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/world/item/crafting/SmeltingRecipe.java ++++ b/net/minecraft/world/item/crafting/SmeltingRecipe.java +@@ -3,21 +3,40 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftFurnaceRecipe; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class SmeltingRecipe extends AbstractCookingRecipe { + +- public SmeltingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient ingredient, ItemStack itemstack, float f, int i) { +- super(RecipeType.SMELTING, s, cookingbookcategory, ingredient, itemstack, f, i); ++ public SmeltingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient recipeitemstack, ItemStack itemstack, float f, int i) { ++ super(RecipeType.SMELTING, s, cookingbookcategory, recipeitemstack, itemstack, f, i); + } + + @Override +- @Override + public ItemStack getToastSymbol() { + return new ItemStack(Blocks.FURNACE); + } + + @Override +- @Override + public RecipeSerializer getSerializer() { + return RecipeSerializer.SMELTING_RECIPE; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftFurnaceRecipe recipe = new CraftFurnaceRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmithingTransformRecipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmithingTransformRecipe.java.patch new file mode 100644 index 0000000000..d4f0b6a3ff --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmithingTransformRecipe.java.patch @@ -0,0 +1,159 @@ +--- a/net/minecraft/world/item/crafting/SmithingTransformRecipe.java ++++ b/net/minecraft/world/item/crafting/SmithingTransformRecipe.java +@@ -9,6 +9,13 @@ + import net.minecraft.world.Container; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftSmithingTransformRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end + + public class SmithingTransformRecipe implements SmithingRecipe { + +@@ -17,70 +24,73 @@ + final Ingredient addition; + final ItemStack result; + +- public SmithingTransformRecipe(Ingredient ingredient, Ingredient ingredient1, Ingredient ingredient2, ItemStack itemstack) { +- this.template = ingredient; +- this.base = ingredient1; +- this.addition = ingredient2; ++ public SmithingTransformRecipe(Ingredient recipeitemstack, Ingredient recipeitemstack1, Ingredient recipeitemstack2, ItemStack itemstack) { ++ this.template = recipeitemstack; ++ this.base = recipeitemstack1; ++ this.addition = recipeitemstack2; + this.result = itemstack; + } + + @Override +- @Override + public boolean matches(Container container, Level level) { + return this.template.test(container.getItem(0)) && this.base.test(container.getItem(1)) && this.addition.test(container.getItem(2)); + } + + @Override +- @Override +- public ItemStack assemble(Container container, RegistryAccess registryaccess) { ++ public ItemStack assemble(Container container, RegistryAccess registryAccess) { + ItemStack itemstack = this.result.copy(); +- CompoundTag compoundtag = container.getItem(1).getTag(); ++ CompoundTag nbttagcompound = container.getItem(1).getTag(); + +- if (compoundtag != null) { +- itemstack.setTag(compoundtag.copy()); ++ if (nbttagcompound != null) { ++ itemstack.setTag(nbttagcompound.copy()); + } + + return itemstack; + } + + @Override +- @Override +- public ItemStack getResultItem(RegistryAccess registryaccess) { ++ public ItemStack getResultItem(RegistryAccess registryAccess) { + return this.result; + } + + @Override +- @Override +- public boolean isTemplateIngredient(ItemStack itemstack) { +- return this.template.test(itemstack); ++ public boolean isTemplateIngredient(ItemStack stack) { ++ return this.template.test(stack); + } + + @Override +- @Override +- public boolean isBaseIngredient(ItemStack itemstack) { +- return this.base.test(itemstack); ++ public boolean isBaseIngredient(ItemStack stack) { ++ return this.base.test(stack); + } + + @Override +- @Override +- public boolean isAdditionIngredient(ItemStack itemstack) { +- return this.addition.test(itemstack); ++ public boolean isAdditionIngredient(ItemStack stack) { ++ return this.addition.test(stack); + } + + @Override +- @Override + public RecipeSerializer getSerializer() { + return RecipeSerializer.SMITHING_TRANSFORM; + } + + @Override +- @Override + public boolean isIncomplete() { + return Stream.of(this.template, this.base, this.addition).anyMatch(Ingredient::isEmpty); + } + +- public static class Serializer implements RecipeSerializer { ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); + ++ CraftSmithingTransformRecipe recipe = new CraftSmithingTransformRecipe(id, result, CraftRecipe.toBukkit(this.template), CraftRecipe.toBukkit(this.base), CraftRecipe.toBukkit(this.addition)); ++ ++ return recipe; ++ } ++ // CraftBukkit end ++ ++ public static class a implements RecipeSerializer { ++ + private static final Codec CODEC = RecordCodecBuilder.create((instance) -> { + return instance.group(Ingredient.CODEC.fieldOf("template").forGetter((smithingtransformrecipe) -> { + return smithingtransformrecipe.template; +@@ -93,31 +103,28 @@ + })).apply(instance, SmithingTransformRecipe::new); + }); + +- public Serializer() {} ++ public a() {} + + @Override +- @Override + public Codec codec() { +- return SmithingTransformRecipe.Serializer.CODEC; ++ return SmithingTransformRecipe.a.CODEC; + } + + @Override +- @Override +- public SmithingTransformRecipe fromNetwork(FriendlyByteBuf friendlybytebuf) { +- Ingredient ingredient = Ingredient.fromNetwork(friendlybytebuf); +- Ingredient ingredient1 = Ingredient.fromNetwork(friendlybytebuf); +- Ingredient ingredient2 = Ingredient.fromNetwork(friendlybytebuf); +- ItemStack itemstack = friendlybytebuf.readItem(); ++ public SmithingTransformRecipe fromNetwork(FriendlyByteBuf packetdataserializer) { ++ Ingredient recipeitemstack = Ingredient.fromNetwork(packetdataserializer); ++ Ingredient recipeitemstack1 = Ingredient.fromNetwork(packetdataserializer); ++ Ingredient recipeitemstack2 = Ingredient.fromNetwork(packetdataserializer); ++ ItemStack itemstack = packetdataserializer.readItem(); + +- return new SmithingTransformRecipe(ingredient, ingredient1, ingredient2, itemstack); ++ return new SmithingTransformRecipe(recipeitemstack, recipeitemstack1, recipeitemstack2, itemstack); + } + +- @Override +- public void toNetwork(FriendlyByteBuf friendlybytebuf, SmithingTransformRecipe smithingtransformrecipe) { +- smithingtransformrecipe.template.toNetwork(friendlybytebuf); +- smithingtransformrecipe.base.toNetwork(friendlybytebuf); +- smithingtransformrecipe.addition.toNetwork(friendlybytebuf); +- friendlybytebuf.writeItem(smithingtransformrecipe.result); ++ public void toNetwork(FriendlyByteBuf packetdataserializer, SmithingTransformRecipe smithingtransformrecipe) { ++ smithingtransformrecipe.template.toNetwork(packetdataserializer); ++ smithingtransformrecipe.base.toNetwork(packetdataserializer); ++ smithingtransformrecipe.addition.toNetwork(packetdataserializer); ++ packetdataserializer.writeItem(smithingtransformrecipe.result); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmithingTrimRecipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmithingTrimRecipe.java.patch new file mode 100644 index 0000000000..8e6da53406 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmithingTrimRecipe.java.patch @@ -0,0 +1,178 @@ +--- a/net/minecraft/world/item/crafting/SmithingTrimRecipe.java ++++ b/net/minecraft/world/item/crafting/SmithingTrimRecipe.java +@@ -17,6 +17,12 @@ + import net.minecraft.world.item.armortrim.TrimPattern; + import net.minecraft.world.item.armortrim.TrimPatterns; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftSmithingTrimRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end + + public class SmithingTrimRecipe implements SmithingRecipe { + +@@ -24,29 +30,27 @@ + final Ingredient base; + final Ingredient addition; + +- public SmithingTrimRecipe(Ingredient ingredient, Ingredient ingredient1, Ingredient ingredient2) { +- this.template = ingredient; +- this.base = ingredient1; +- this.addition = ingredient2; ++ public SmithingTrimRecipe(Ingredient recipeitemstack, Ingredient recipeitemstack1, Ingredient recipeitemstack2) { ++ this.template = recipeitemstack; ++ this.base = recipeitemstack1; ++ this.addition = recipeitemstack2; + } + + @Override +- @Override + public boolean matches(Container container, Level level) { + return this.template.test(container.getItem(0)) && this.base.test(container.getItem(1)) && this.addition.test(container.getItem(2)); + } + + @Override +- @Override +- public ItemStack assemble(Container container, RegistryAccess registryaccess) { ++ public ItemStack assemble(Container container, RegistryAccess registryAccess) { + ItemStack itemstack = container.getItem(1); + + if (this.base.test(itemstack)) { +- Optional> optional = TrimMaterials.getFromIngredient(registryaccess, container.getItem(2)); +- Optional> optional1 = TrimPatterns.getFromTemplate(registryaccess, container.getItem(0)); ++ Optional> optional = TrimMaterials.getFromIngredient(registryAccess, container.getItem(2)); ++ Optional> optional1 = TrimPatterns.getFromTemplate(registryAccess, container.getItem(0)); + + if (optional.isPresent() && optional1.isPresent()) { +- Optional optional2 = ArmorTrim.getTrim(registryaccess, itemstack, false); ++ Optional optional2 = ArmorTrim.getTrim(registryAccess, itemstack, false); + + if (optional2.isPresent() && ((ArmorTrim) optional2.get()).hasPatternAndMaterial((Holder) optional1.get(), (Holder) optional.get())) { + return ItemStack.EMPTY; +@@ -57,7 +61,7 @@ + itemstack1.setCount(1); + ArmorTrim armortrim = new ArmorTrim((Holder) optional.get(), (Holder) optional1.get()); + +- if (ArmorTrim.setTrim(registryaccess, itemstack1, armortrim)) { ++ if (ArmorTrim.setTrim(registryAccess, itemstack1, armortrim)) { + return itemstack1; + } + } +@@ -67,18 +71,17 @@ + } + + @Override +- @Override +- public ItemStack getResultItem(RegistryAccess registryaccess) { ++ public ItemStack getResultItem(RegistryAccess registryAccess) { + ItemStack itemstack = new ItemStack(Items.IRON_CHESTPLATE); +- Optional> optional = registryaccess.registryOrThrow(Registries.TRIM_PATTERN).holders().findFirst(); ++ Optional> optional = registryAccess.registryOrThrow(Registries.TRIM_PATTERN).holders().findFirst(); + + if (optional.isPresent()) { +- Optional> optional1 = registryaccess.registryOrThrow(Registries.TRIM_MATERIAL).getHolder(TrimMaterials.REDSTONE); ++ Optional> optional1 = registryAccess.registryOrThrow(Registries.TRIM_MATERIAL).getHolder(TrimMaterials.REDSTONE); + + if (optional1.isPresent()) { + ArmorTrim armortrim = new ArmorTrim((Holder) optional1.get(), (Holder) optional.get()); + +- ArmorTrim.setTrim(registryaccess, itemstack, armortrim); ++ ArmorTrim.setTrim(registryAccess, itemstack, armortrim); + } + } + +@@ -86,37 +89,39 @@ + } + + @Override +- @Override +- public boolean isTemplateIngredient(ItemStack itemstack) { +- return this.template.test(itemstack); ++ public boolean isTemplateIngredient(ItemStack stack) { ++ return this.template.test(stack); + } + + @Override +- @Override +- public boolean isBaseIngredient(ItemStack itemstack) { +- return this.base.test(itemstack); ++ public boolean isBaseIngredient(ItemStack stack) { ++ return this.base.test(stack); + } + + @Override +- @Override +- public boolean isAdditionIngredient(ItemStack itemstack) { +- return this.addition.test(itemstack); ++ public boolean isAdditionIngredient(ItemStack stack) { ++ return this.addition.test(stack); + } + + @Override +- @Override + public RecipeSerializer getSerializer() { + return RecipeSerializer.SMITHING_TRIM; + } + + @Override +- @Override + public boolean isIncomplete() { + return Stream.of(this.template, this.base, this.addition).anyMatch(Ingredient::isEmpty); + } + +- public static class Serializer implements RecipeSerializer { ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ return new CraftSmithingTrimRecipe(id, CraftRecipe.toBukkit(this.template), CraftRecipe.toBukkit(this.base), CraftRecipe.toBukkit(this.addition)); ++ } ++ // CraftBukkit end + ++ public static class a implements RecipeSerializer { ++ + private static final Codec CODEC = RecordCodecBuilder.create((instance) -> { + return instance.group(Ingredient.CODEC.fieldOf("template").forGetter((smithingtrimrecipe) -> { + return smithingtrimrecipe.template; +@@ -127,29 +132,26 @@ + })).apply(instance, SmithingTrimRecipe::new); + }); + +- public Serializer() {} ++ public a() {} + + @Override +- @Override + public Codec codec() { +- return SmithingTrimRecipe.Serializer.CODEC; ++ return SmithingTrimRecipe.a.CODEC; + } + + @Override +- @Override +- public SmithingTrimRecipe fromNetwork(FriendlyByteBuf friendlybytebuf) { +- Ingredient ingredient = Ingredient.fromNetwork(friendlybytebuf); +- Ingredient ingredient1 = Ingredient.fromNetwork(friendlybytebuf); +- Ingredient ingredient2 = Ingredient.fromNetwork(friendlybytebuf); ++ public SmithingTrimRecipe fromNetwork(FriendlyByteBuf packetdataserializer) { ++ Ingredient recipeitemstack = Ingredient.fromNetwork(packetdataserializer); ++ Ingredient recipeitemstack1 = Ingredient.fromNetwork(packetdataserializer); ++ Ingredient recipeitemstack2 = Ingredient.fromNetwork(packetdataserializer); + +- return new SmithingTrimRecipe(ingredient, ingredient1, ingredient2); ++ return new SmithingTrimRecipe(recipeitemstack, recipeitemstack1, recipeitemstack2); + } + +- @Override +- public void toNetwork(FriendlyByteBuf friendlybytebuf, SmithingTrimRecipe smithingtrimrecipe) { +- smithingtrimrecipe.template.toNetwork(friendlybytebuf); +- smithingtrimrecipe.base.toNetwork(friendlybytebuf); +- smithingtrimrecipe.addition.toNetwork(friendlybytebuf); ++ public void toNetwork(FriendlyByteBuf packetdataserializer, SmithingTrimRecipe smithingtrimrecipe) { ++ smithingtrimrecipe.template.toNetwork(packetdataserializer); ++ smithingtrimrecipe.base.toNetwork(packetdataserializer); ++ smithingtrimrecipe.addition.toNetwork(packetdataserializer); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmokingRecipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmokingRecipe.java.patch new file mode 100644 index 0000000000..d5799e7952 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/SmokingRecipe.java.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/world/item/crafting/SmokingRecipe.java ++++ b/net/minecraft/world/item/crafting/SmokingRecipe.java +@@ -3,21 +3,40 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftSmokingRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class SmokingRecipe extends AbstractCookingRecipe { + +- public SmokingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient ingredient, ItemStack itemstack, float f, int i) { +- super(RecipeType.SMOKING, s, cookingbookcategory, ingredient, itemstack, f, i); ++ public SmokingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient recipeitemstack, ItemStack itemstack, float f, int i) { ++ super(RecipeType.SMOKING, s, cookingbookcategory, recipeitemstack, itemstack, f, i); + } + + @Override +- @Override + public ItemStack getToastSymbol() { + return new ItemStack(Blocks.SMOKER); + } + + @Override +- @Override + public RecipeSerializer getSerializer() { + return RecipeSerializer.SMOKING_RECIPE; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftSmokingRecipe recipe = new CraftSmokingRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/StonecutterRecipe.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/StonecutterRecipe.java.patch new file mode 100644 index 0000000000..0b933cd748 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/crafting/StonecutterRecipe.java.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/world/item/crafting/StonecutterRecipe.java ++++ b/net/minecraft/world/item/crafting/StonecutterRecipe.java +@@ -5,21 +5,39 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftStonecuttingRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class StonecutterRecipe extends SingleItemRecipe { + +- public StonecutterRecipe(String s, Ingredient ingredient, ItemStack itemstack) { +- super(RecipeType.STONECUTTING, RecipeSerializer.STONECUTTER, s, ingredient, itemstack); ++ public StonecutterRecipe(String s, Ingredient recipeitemstack, ItemStack itemstack) { ++ super(RecipeType.STONECUTTING, RecipeSerializer.STONECUTTER, s, recipeitemstack, itemstack); + } + + @Override +- @Override +- public boolean matches(Container container, Level level) { +- return this.ingredient.test(container.getItem(0)); ++ public boolean matches(Container inv, Level level) { ++ return this.ingredient.test(inv.getItem(0)); + } + + @Override +- @Override + public ItemStack getToastSymbol() { + return new ItemStack(Blocks.STONECUTTER); + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftStonecuttingRecipe recipe = new CraftStonecuttingRecipe(id, result, CraftRecipe.toBukkit(this.ingredient)); ++ recipe.setGroup(this.group); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/enchantment/DamageEnchantment.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/enchantment/DamageEnchantment.java.patch new file mode 100644 index 0000000000..1a94a27b76 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/enchantment/DamageEnchantment.java.patch @@ -0,0 +1,90 @@ +--- a/net/minecraft/world/item/enchantment/DamageEnchantment.java ++++ b/net/minecraft/world/item/enchantment/DamageEnchantment.java +@@ -3,9 +3,9 @@ + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobType; + import net.minecraft.world.item.AxeItem; + import net.minecraft.world.item.ItemStack; + +@@ -20,57 +20,50 @@ + private static final int[] LEVEL_COST_SPAN = new int[]{20, 20, 20}; + public final int type; + +- public DamageEnchantment(Enchantment.Rarity enchantment_rarity, int i, EquipmentSlot... aequipmentslot) { +- super(enchantment_rarity, EnchantmentCategory.WEAPON, aequipmentslot); +- this.type = i; ++ public DamageEnchantment(Enchantment.Rarity rarity, int type, EquipmentSlot... applicableSlots) { ++ super(rarity, EnchantmentCategory.WEAPON, applicableSlots); ++ this.type = type; + } + + @Override +- @Override +- public int getMinCost(int i) { +- return DamageEnchantment.MIN_COST[this.type] + (i - 1) * DamageEnchantment.LEVEL_COST[this.type]; ++ public int getMinCost(int enchantmentLevel) { ++ return DamageEnchantment.MIN_COST[this.type] + (enchantmentLevel - 1) * DamageEnchantment.LEVEL_COST[this.type]; + } + + @Override +- @Override +- public int getMaxCost(int i) { +- return this.getMinCost(i) + DamageEnchantment.LEVEL_COST_SPAN[this.type]; ++ public int getMaxCost(int enchantmentLevel) { ++ return this.getMinCost(enchantmentLevel) + DamageEnchantment.LEVEL_COST_SPAN[this.type]; + } + + @Override +- @Override + public int getMaxLevel() { + return 5; + } + + @Override +- @Override +- public float getDamageBonus(int i, MobType mobtype) { +- return this.type == 0 ? 1.0F + (float) Math.max(0, i - 1) * 0.5F : (this.type == 1 && mobtype == MobType.UNDEAD ? (float) i * 2.5F : (this.type == 2 && mobtype == MobType.ARTHROPOD ? (float) i * 2.5F : 0.0F)); ++ public float getDamageBonus(int level, EnumMonsterType creatureType) { ++ return this.type == 0 ? 1.0F + (float) Math.max(0, level - 1) * 0.5F : (this.type == 1 && creatureType == EnumMonsterType.UNDEAD ? (float) level * 2.5F : (this.type == 2 && creatureType == EnumMonsterType.ARTHROPOD ? (float) level * 2.5F : 0.0F)); + } + + @Override +- @Override +- public boolean checkCompatibility(Enchantment enchantment) { +- return !(enchantment instanceof DamageEnchantment); ++ public boolean checkCompatibility(Enchantment ench) { ++ return !(ench instanceof DamageEnchantment); + } + + @Override +- @Override +- public boolean canEnchant(ItemStack itemstack) { +- return itemstack.getItem() instanceof AxeItem ? true : super.canEnchant(itemstack); ++ public boolean canEnchant(ItemStack stack) { ++ return stack.getItem() instanceof AxeItem ? true : super.canEnchant(stack); + } + + @Override +- @Override +- public void doPostAttack(LivingEntity livingentity, Entity entity, int i) { +- if (entity instanceof LivingEntity) { +- LivingEntity livingentity1 = (LivingEntity) entity; ++ public void doPostAttack(LivingEntity user, Entity target, int level) { ++ if (target instanceof LivingEntity) { ++ LivingEntity entityliving1 = (LivingEntity) target; + +- if (this.type == 2 && i > 0 && livingentity1.getMobType() == MobType.ARTHROPOD) { +- int j = 20 + livingentity.getRandom().nextInt(10 * i); ++ if (this.type == 2 && level > 0 && entityliving1.getMobType() == EnumMonsterType.ARTHROPOD) { ++ int j = 20 + user.getRandom().nextInt(10 * level); + +- livingentity1.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, j, 3)); ++ entityliving1.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, j, 3), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/enchantment/FrostWalkerEnchantment.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/enchantment/FrostWalkerEnchantment.java.patch new file mode 100644 index 0000000000..d6b70c75f8 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/enchantment/FrostWalkerEnchantment.java.patch @@ -0,0 +1,98 @@ +--- a/net/minecraft/world/item/enchantment/FrostWalkerEnchantment.java ++++ b/net/minecraft/world/item/enchantment/FrostWalkerEnchantment.java +@@ -8,59 +8,58 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.FrostedIceBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.shapes.CollisionContext; + + public class FrostWalkerEnchantment extends Enchantment { + +- public FrostWalkerEnchantment(Enchantment.Rarity enchantment_rarity, EquipmentSlot... aequipmentslot) { +- super(enchantment_rarity, EnchantmentCategory.ARMOR_FEET, aequipmentslot); ++ public FrostWalkerEnchantment(Enchantment.Rarity rarity, EquipmentSlot... applicableSlots) { ++ super(rarity, EnchantmentCategory.ARMOR_FEET, applicableSlots); + } + + @Override +- @Override +- public int getMinCost(int i) { +- return i * 10; ++ public int getMinCost(int enchantmentLevel) { ++ return enchantmentLevel * 10; + } + + @Override +- @Override +- public int getMaxCost(int i) { +- return this.getMinCost(i) + 15; ++ public int getMaxCost(int enchantmentLevel) { ++ return this.getMinCost(enchantmentLevel) + 15; + } + + @Override +- @Override + public boolean isTreasureOnly() { + return true; + } + + @Override +- @Override + public int getMaxLevel() { + return 2; + } + +- public static void onEntityMoved(LivingEntity livingentity, Level level, BlockPos blockpos, int i) { +- if (livingentity.onGround()) { +- BlockState blockstate = Blocks.FROSTED_ICE.defaultBlockState(); +- int j = Math.min(16, 2 + i); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); +- Iterator iterator = BlockPos.betweenClosed(blockpos.offset(-j, -1, -j), blockpos.offset(j, -1, j)).iterator(); ++ public static void onEntityMoved(LivingEntity living, Level level, BlockPos pos, int levelConflicting) { ++ if (living.onGround()) { ++ IBlockData iblockdata = Blocks.FROSTED_ICE.defaultBlockState(); ++ int j = Math.min(16, 2 + levelConflicting); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ Iterator iterator = BlockPos.betweenClosed(pos.offset(-j, -1, -j), pos.offset(j, -1, j)).iterator(); + + while (iterator.hasNext()) { +- BlockPos blockpos1 = (BlockPos) iterator.next(); ++ BlockPos blockposition1 = (BlockPos) iterator.next(); + +- if (blockpos1.closerToCenterThan(livingentity.position(), (double) j)) { +- blockpos_mutableblockpos.set(blockpos1.getX(), blockpos1.getY() + 1, blockpos1.getZ()); +- BlockState blockstate1 = level.getBlockState(blockpos_mutableblockpos); ++ if (blockposition1.closerToCenterThan(living.position(), (double) j)) { ++ blockposition_mutableblockposition.set(blockposition1.getX(), blockposition1.getY() + 1, blockposition1.getZ()); ++ IBlockData iblockdata1 = level.getBlockState(blockposition_mutableblockposition); + +- if (blockstate1.isAir()) { +- BlockState blockstate2 = level.getBlockState(blockpos1); ++ if (iblockdata1.isAir()) { ++ IBlockData iblockdata2 = level.getBlockState(blockposition1); + +- if (blockstate2 == FrostedIceBlock.meltsInto() && blockstate.canSurvive(level, blockpos1) && level.isUnobstructed(blockstate, blockpos1, CollisionContext.empty())) { +- level.setBlockAndUpdate(blockpos1, blockstate); +- level.scheduleTick(blockpos1, Blocks.FROSTED_ICE, Mth.nextInt(livingentity.getRandom(), 60, 120)); ++ if (iblockdata2 == FrostedIceBlock.meltsInto() && iblockdata.canSurvive(level, blockposition1) && level.isUnobstructed(iblockdata, blockposition1, CollisionContext.empty())) { ++ // CraftBukkit Start - Call EntityBlockFormEvent for Frost Walker ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, blockposition1, iblockdata, living)) { ++ level.scheduleTick(blockposition1, Blocks.FROSTED_ICE, Mth.nextInt(living.getRandom(), 60, 120)); ++ } ++ // CraftBukkit End + } + } + } +@@ -70,8 +69,7 @@ + } + + @Override +- @Override +- public boolean checkCompatibility(Enchantment enchantment) { +- return super.checkCompatibility(enchantment) && enchantment != Enchantments.DEPTH_STRIDER; ++ public boolean checkCompatibility(Enchantment ench) { ++ return super.checkCompatibility(ench) && ench != Enchantments.DEPTH_STRIDER; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/trading/Merchant.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/trading/Merchant.java.patch new file mode 100644 index 0000000000..e01c6979e5 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/trading/Merchant.java.patch @@ -0,0 +1,32 @@ +--- a/net/minecraft/world/item/trading/Merchant.java ++++ b/net/minecraft/world/item/trading/Merchant.java +@@ -36,20 +36,22 @@ + return false; + } + +- default void openTradingScreen(Player player, Component component, int i) { +- OptionalInt optionalint = player.openMenu(new SimpleMenuProvider((j, inventory, player1) -> { +- return new MerchantMenu(j, inventory, this); +- }, component)); ++ default void openTradingScreen(Player player, Component displayName, int level) { ++ OptionalInt optionalint = player.openMenu(new SimpleMenuProvider((j, playerinventory, entityhuman1) -> { ++ return new MerchantMenu(j, playerinventory, this); ++ }, displayName)); + + if (optionalint.isPresent()) { +- MerchantOffers merchantoffers = this.getOffers(); ++ MerchantOffers merchantrecipelist = this.getOffers(); + +- if (!merchantoffers.isEmpty()) { +- player.sendMerchantOffers(optionalint.getAsInt(), merchantoffers, i, this.getVillagerXp(), this.showProgressBar(), this.canRestock()); ++ if (!merchantrecipelist.isEmpty()) { ++ player.sendMerchantOffers(optionalint.getAsInt(), merchantrecipelist, level, this.getVillagerXp(), this.showProgressBar(), this.canRestock()); + } + } + + } + + boolean isClientSide(); ++ ++ org.bukkit.craftbukkit.inventory.CraftMerchant getCraftMerchant(); // CraftBukkit + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/item/trading/MerchantOffer.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/item/trading/MerchantOffer.java.patch new file mode 100644 index 0000000000..83b82b1693 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/item/trading/MerchantOffer.java.patch @@ -0,0 +1,261 @@ +--- a/net/minecraft/world/item/trading/MerchantOffer.java ++++ b/net/minecraft/world/item/trading/MerchantOffer.java +@@ -5,86 +5,104 @@ + import net.minecraft.util.Mth; + import net.minecraft.world.item.ItemStack; + ++import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; // CraftBukkit ++ + public class MerchantOffer { + +- private final ItemStack baseCostA; +- private final ItemStack costB; +- private final ItemStack result; +- private int uses; +- private final int maxUses; +- private boolean rewardExp; +- private int specialPriceDiff; +- private int demand; +- private float priceMultiplier; +- private int xp; ++ public ItemStack baseCostA; ++ public ItemStack costB; ++ public final ItemStack result; ++ public int uses; ++ public int maxUses; ++ public boolean rewardExp; ++ public int specialPriceDiff; ++ public int demand; ++ public float priceMultiplier; ++ public int xp; ++ // CraftBukkit start ++ private CraftMerchantRecipe bukkitHandle; + +- public MerchantOffer(CompoundTag compoundtag) { ++ public CraftMerchantRecipe asBukkit() { ++ return (bukkitHandle == null) ? bukkitHandle = new CraftMerchantRecipe(this) : bukkitHandle; ++ } ++ ++ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, CraftMerchantRecipe bukkit) { ++ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, 0, bukkit); ++ } ++ ++ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, int demand, CraftMerchantRecipe bukkit) { ++ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, demand); ++ this.bukkitHandle = bukkit; ++ } ++ // CraftBukkit end ++ ++ public MerchantOffer(CompoundTag compoundTag) { + this.rewardExp = true; + this.xp = 1; +- this.baseCostA = ItemStack.of(compoundtag.getCompound("buy")); +- this.costB = ItemStack.of(compoundtag.getCompound("buyB")); +- this.result = ItemStack.of(compoundtag.getCompound("sell")); +- this.uses = compoundtag.getInt("uses"); +- if (compoundtag.contains("maxUses", 99)) { +- this.maxUses = compoundtag.getInt("maxUses"); ++ this.baseCostA = ItemStack.of(compoundTag.getCompound("buy")); ++ this.costB = ItemStack.of(compoundTag.getCompound("buyB")); ++ this.result = ItemStack.of(compoundTag.getCompound("sell")); ++ this.uses = compoundTag.getInt("uses"); ++ if (compoundTag.contains("maxUses", 99)) { ++ this.maxUses = compoundTag.getInt("maxUses"); + } else { + this.maxUses = 4; + } + +- if (compoundtag.contains("rewardExp", 1)) { +- this.rewardExp = compoundtag.getBoolean("rewardExp"); ++ if (compoundTag.contains("rewardExp", 1)) { ++ this.rewardExp = compoundTag.getBoolean("rewardExp"); + } + +- if (compoundtag.contains("xp", 3)) { +- this.xp = compoundtag.getInt("xp"); ++ if (compoundTag.contains("xp", 3)) { ++ this.xp = compoundTag.getInt("xp"); + } + +- if (compoundtag.contains("priceMultiplier", 5)) { +- this.priceMultiplier = compoundtag.getFloat("priceMultiplier"); ++ if (compoundTag.contains("priceMultiplier", 5)) { ++ this.priceMultiplier = compoundTag.getFloat("priceMultiplier"); + } + +- this.specialPriceDiff = compoundtag.getInt("specialPrice"); +- this.demand = compoundtag.getInt("demand"); ++ this.specialPriceDiff = compoundTag.getInt("specialPrice"); ++ this.demand = compoundTag.getInt("demand"); + } + +- public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, int i, int j, float f) { +- this(itemstack, ItemStack.EMPTY, itemstack1, i, j, f); ++ public MerchantOffer(ItemStack baseCostA, ItemStack result, int maxUses, int xp, float priceMultiplier) { ++ this(baseCostA, ItemStack.EMPTY, result, maxUses, xp, priceMultiplier); + } + +- public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, float f) { +- this(itemstack, itemstack1, itemstack2, 0, i, j, f); ++ public MerchantOffer(ItemStack baseCostA, ItemStack costB, ItemStack result, int maxUses, int xp, float priceMultiplier) { ++ this(baseCostA, costB, result, 0, maxUses, xp, priceMultiplier); + } + +- public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f) { +- this(itemstack, itemstack1, itemstack2, i, j, k, f, 0); ++ public MerchantOffer(ItemStack baseCostA, ItemStack costB, ItemStack result, int uses, int maxUses, int xp, float priceMultiplier) { ++ this(baseCostA, costB, result, uses, maxUses, xp, priceMultiplier, 0); + } + +- public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, int l) { ++ public MerchantOffer(ItemStack baseCostA, ItemStack costB, ItemStack result, int uses, int maxUses, int xp, float priceMultiplier, int demand) { + this.rewardExp = true; + this.xp = 1; +- this.baseCostA = itemstack; +- this.costB = itemstack1; +- this.result = itemstack2; +- this.uses = i; +- this.maxUses = j; +- this.xp = k; +- this.priceMultiplier = f; +- this.demand = l; ++ this.baseCostA = baseCostA; ++ this.costB = costB; ++ this.result = result; ++ this.uses = uses; ++ this.maxUses = maxUses; ++ this.xp = xp; ++ this.priceMultiplier = priceMultiplier; ++ this.demand = demand; + } + +- private MerchantOffer(MerchantOffer merchantoffer) { ++ private MerchantOffer(MerchantOffer merchantrecipe) { + this.rewardExp = true; + this.xp = 1; +- this.baseCostA = merchantoffer.baseCostA.copy(); +- this.costB = merchantoffer.costB.copy(); +- this.result = merchantoffer.result.copy(); +- this.uses = merchantoffer.uses; +- this.maxUses = merchantoffer.maxUses; +- this.rewardExp = merchantoffer.rewardExp; +- this.specialPriceDiff = merchantoffer.specialPriceDiff; +- this.demand = merchantoffer.demand; +- this.priceMultiplier = merchantoffer.priceMultiplier; +- this.xp = merchantoffer.xp; ++ this.baseCostA = merchantrecipe.baseCostA.copy(); ++ this.costB = merchantrecipe.costB.copy(); ++ this.result = merchantrecipe.result.copy(); ++ this.uses = merchantrecipe.uses; ++ this.maxUses = merchantrecipe.maxUses; ++ this.rewardExp = merchantrecipe.rewardExp; ++ this.specialPriceDiff = merchantrecipe.specialPriceDiff; ++ this.demand = merchantrecipe.demand; ++ this.priceMultiplier = merchantrecipe.priceMultiplier; ++ this.xp = merchantrecipe.xp; + } + + public ItemStack getBaseCostA() { +@@ -96,6 +114,7 @@ + return ItemStack.EMPTY; + } else { + int i = this.baseCostA.getCount(); ++ if (i <= 0) return ItemStack.EMPTY; // CraftBukkit - SPIGOT-5476 + int j = Math.max(0, Mth.floor((float) (i * this.demand) * this.priceMultiplier)); + + return this.baseCostA.copyWithCount(Mth.clamp(i + j + this.specialPriceDiff, 1, this.baseCostA.getItem().getMaxStackSize())); +@@ -138,8 +157,8 @@ + return this.demand; + } + +- public void addToSpecialPriceDiff(int i) { +- this.specialPriceDiff += i; ++ public void addToSpecialPriceDiff(int add) { ++ this.specialPriceDiff += add; + } + + public void resetSpecialPriceDiff() { +@@ -150,8 +169,8 @@ + return this.specialPriceDiff; + } + +- public void setSpecialPriceDiff(int i) { +- this.specialPriceDiff = i; ++ public void setSpecialPriceDiff(int price) { ++ this.specialPriceDiff = price; + } + + public float getPriceMultiplier() { +@@ -179,46 +198,50 @@ + } + + public CompoundTag createTag() { +- CompoundTag compoundtag = new CompoundTag(); ++ CompoundTag nbttagcompound = new CompoundTag(); + +- compoundtag.put("buy", this.baseCostA.save(new CompoundTag())); +- compoundtag.put("sell", this.result.save(new CompoundTag())); +- compoundtag.put("buyB", this.costB.save(new CompoundTag())); +- compoundtag.putInt("uses", this.uses); +- compoundtag.putInt("maxUses", this.maxUses); +- compoundtag.putBoolean("rewardExp", this.rewardExp); +- compoundtag.putInt("xp", this.xp); +- compoundtag.putFloat("priceMultiplier", this.priceMultiplier); +- compoundtag.putInt("specialPrice", this.specialPriceDiff); +- compoundtag.putInt("demand", this.demand); +- return compoundtag; ++ nbttagcompound.put("buy", this.baseCostA.save(new CompoundTag())); ++ nbttagcompound.put("sell", this.result.save(new CompoundTag())); ++ nbttagcompound.put("buyB", this.costB.save(new CompoundTag())); ++ nbttagcompound.putInt("uses", this.uses); ++ nbttagcompound.putInt("maxUses", this.maxUses); ++ nbttagcompound.putBoolean("rewardExp", this.rewardExp); ++ nbttagcompound.putInt("xp", this.xp); ++ nbttagcompound.putFloat("priceMultiplier", this.priceMultiplier); ++ nbttagcompound.putInt("specialPrice", this.specialPriceDiff); ++ nbttagcompound.putInt("demand", this.demand); ++ return nbttagcompound; + } + +- public boolean satisfiedBy(ItemStack itemstack, ItemStack itemstack1) { +- return this.isRequiredItem(itemstack, this.getCostA()) && itemstack.getCount() >= this.getCostA().getCount() && this.isRequiredItem(itemstack1, this.costB) && itemstack1.getCount() >= this.costB.getCount(); ++ public boolean satisfiedBy(ItemStack playerOfferA, ItemStack playerOfferB) { ++ return this.isRequiredItem(playerOfferA, this.getCostA()) && playerOfferA.getCount() >= this.getCostA().getCount() && this.isRequiredItem(playerOfferB, this.costB) && playerOfferB.getCount() >= this.costB.getCount(); + } + +- private boolean isRequiredItem(ItemStack itemstack, ItemStack itemstack1) { +- if (itemstack1.isEmpty() && itemstack.isEmpty()) { ++ private boolean isRequiredItem(ItemStack offer, ItemStack cost) { ++ if (cost.isEmpty() && offer.isEmpty()) { + return true; + } else { +- ItemStack itemstack2 = itemstack.copy(); ++ ItemStack itemstack2 = offer.copy(); + + if (itemstack2.getItem().canBeDepleted()) { + itemstack2.setDamageValue(itemstack2.getDamageValue()); + } + +- return ItemStack.isSameItem(itemstack2, itemstack1) && (!itemstack1.hasTag() || itemstack2.hasTag() && NbtUtils.compareNbt(itemstack1.getTag(), itemstack2.getTag(), false)); ++ return ItemStack.isSameItem(itemstack2, cost) && (!cost.hasTag() || itemstack2.hasTag() && NbtUtils.compareNbt(cost.getTag(), itemstack2.getTag(), false)); + } + } + +- public boolean take(ItemStack itemstack, ItemStack itemstack1) { +- if (!this.satisfiedBy(itemstack, itemstack1)) { ++ public boolean take(ItemStack playerOfferA, ItemStack playerOfferB) { ++ if (!this.satisfiedBy(playerOfferA, playerOfferB)) { + return false; + } else { +- itemstack.shrink(this.getCostA().getCount()); ++ // CraftBukkit start ++ if (!this.getCostA().isEmpty()) { ++ playerOfferA.shrink(this.getCostA().getCount()); ++ } ++ // CraftBukkit end + if (!this.getCostB().isEmpty()) { +- itemstack1.shrink(this.getCostB().getCount()); ++ playerOfferB.shrink(this.getCostB().getCount()); + } + + return true; diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/BaseCommandBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/BaseCommandBlock.java.patch new file mode 100644 index 0000000000..db78f62f28 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/BaseCommandBlock.java.patch @@ -0,0 +1,190 @@ +--- a/net/minecraft/world/level/BaseCommandBlock.java ++++ b/net/minecraft/world/level/BaseCommandBlock.java +@@ -30,6 +30,10 @@ + private Component lastOutput; + private String command = ""; + private Component name; ++ // CraftBukkit start ++ @Override ++ public abstract org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper); ++ // CraftBukkit end + + public BaseCommandBlock() { + this.name = BaseCommandBlock.DEFAULT_NAME; +@@ -39,45 +43,45 @@ + return this.successCount; + } + +- public void setSuccessCount(int i) { +- this.successCount = i; ++ public void setSuccessCount(int successCount) { ++ this.successCount = successCount; + } + + public Component getLastOutput() { + return this.lastOutput == null ? CommonComponents.EMPTY : this.lastOutput; + } + +- public CompoundTag save(CompoundTag compoundtag) { +- compoundtag.putString("Command", this.command); +- compoundtag.putInt("SuccessCount", this.successCount); +- compoundtag.putString("CustomName", Component.Serializer.toJson(this.name)); +- compoundtag.putBoolean("TrackOutput", this.trackOutput); ++ public CompoundTag save(CompoundTag compound) { ++ compound.putString("Command", this.command); ++ compound.putInt("SuccessCount", this.successCount); ++ compound.putString("CustomName", Component.Serializer.toJson(this.name)); ++ compound.putBoolean("TrackOutput", this.trackOutput); + if (this.lastOutput != null && this.trackOutput) { +- compoundtag.putString("LastOutput", Component.Serializer.toJson(this.lastOutput)); ++ compound.putString("LastOutput", Component.Serializer.toJson(this.lastOutput)); + } + +- compoundtag.putBoolean("UpdateLastExecution", this.updateLastExecution); ++ compound.putBoolean("UpdateLastExecution", this.updateLastExecution); + if (this.updateLastExecution && this.lastExecution > 0L) { +- compoundtag.putLong("LastExecution", this.lastExecution); ++ compound.putLong("LastExecution", this.lastExecution); + } + +- return compoundtag; ++ return compound; + } + +- public void load(CompoundTag compoundtag) { +- this.command = compoundtag.getString("Command"); +- this.successCount = compoundtag.getInt("SuccessCount"); +- if (compoundtag.contains("CustomName", 8)) { +- this.setName(Component.Serializer.fromJson(compoundtag.getString("CustomName"))); ++ public void load(CompoundTag nbt) { ++ this.command = nbt.getString("Command"); ++ this.successCount = nbt.getInt("SuccessCount"); ++ if (nbt.contains("CustomName", 8)) { ++ this.setName(Component.Serializer.fromJson(nbt.getString("CustomName"))); + } + +- if (compoundtag.contains("TrackOutput", 1)) { +- this.trackOutput = compoundtag.getBoolean("TrackOutput"); ++ if (nbt.contains("TrackOutput", 1)) { ++ this.trackOutput = nbt.getBoolean("TrackOutput"); + } + +- if (compoundtag.contains("LastOutput", 8) && this.trackOutput) { ++ if (nbt.contains("LastOutput", 8) && this.trackOutput) { + try { +- this.lastOutput = Component.Serializer.fromJson(compoundtag.getString("LastOutput")); ++ this.lastOutput = Component.Serializer.fromJson(nbt.getString("LastOutput")); + } catch (Throwable throwable) { + this.lastOutput = Component.literal(throwable.getMessage()); + } +@@ -85,20 +89,20 @@ + this.lastOutput = null; + } + +- if (compoundtag.contains("UpdateLastExecution")) { +- this.updateLastExecution = compoundtag.getBoolean("UpdateLastExecution"); ++ if (nbt.contains("UpdateLastExecution")) { ++ this.updateLastExecution = nbt.getBoolean("UpdateLastExecution"); + } + +- if (this.updateLastExecution && compoundtag.contains("LastExecution")) { +- this.lastExecution = compoundtag.getLong("LastExecution"); ++ if (this.updateLastExecution && nbt.contains("LastExecution")) { ++ this.lastExecution = nbt.getLong("LastExecution"); + } else { + this.lastExecution = -1L; + } + + } + +- public void setCommand(String s) { +- this.command = s; ++ public void setCommand(String command) { ++ this.command = command; + this.successCount = 0; + } + +@@ -119,20 +123,20 @@ + if (minecraftserver.isCommandBlockEnabled() && !StringUtil.isNullOrEmpty(this.command)) { + try { + this.lastOutput = null; +- CommandSourceStack commandsourcestack = this.createCommandSourceStack().withCallback((flag, i) -> { ++ CommandSourceStack commandlistenerwrapper = this.createCommandSourceStack().withCallback((flag, i) -> { + if (flag) { + ++this.successCount; + } + + }); + +- minecraftserver.getCommands().performPrefixedCommand(commandsourcestack, this.command); ++ minecraftserver.getCommands().dispatchServerCommand(commandlistenerwrapper, this.command); // CraftBukkit + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Executing command block"); +- CrashReportCategory crashreportcategory = crashreport.addCategory("Command to be executed"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Command to be executed"); + +- crashreportcategory.setDetail("Command", this::getCommand); +- crashreportcategory.setDetail("Name", () -> { ++ crashreportsystemdetails.setDetail("Command", this::getCommand); ++ crashreportsystemdetails.setDetail("Name", () -> { + return this.getName().getString(); + }); + throw new ReportedException(crashreport); +@@ -156,9 +160,9 @@ + return this.name; + } + +- public void setName(@Nullable Component component) { +- if (component != null) { +- this.name = component; ++ public void setName(@Nullable Component name) { ++ if (name != null) { ++ this.name = name; + } else { + this.name = BaseCommandBlock.DEFAULT_NAME; + } +@@ -166,7 +170,6 @@ + } + + @Override +- @Override + public void sendSystemMessage(Component component) { + if (this.trackOutput) { + SimpleDateFormat simpledateformat = BaseCommandBlock.TIME_FORMAT; +@@ -182,12 +185,12 @@ + + public abstract void onUpdated(); + +- public void setLastOutput(@Nullable Component component) { +- this.lastOutput = component; ++ public void setLastOutput(@Nullable Component lastOutputMessage) { ++ this.lastOutput = lastOutputMessage; + } + +- public void setTrackOutput(boolean flag) { +- this.trackOutput = flag; ++ public void setTrackOutput(boolean shouldTrackOutput) { ++ this.trackOutput = shouldTrackOutput; + } + + public boolean isTrackOutput() { +@@ -211,19 +214,16 @@ + public abstract CommandSourceStack createCommandSourceStack(); + + @Override +- @Override + public boolean acceptsSuccess() { + return this.getLevel().getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK) && this.trackOutput; + } + + @Override +- @Override + public boolean acceptsFailure() { + return this.trackOutput; + } + + @Override +- @Override + public boolean shouldInformAdmins() { + return this.getLevel().getGameRules().getBoolean(GameRules.RULE_COMMANDBLOCKOUTPUT); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/BaseSpawner.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/BaseSpawner.java.patch new file mode 100644 index 0000000000..d948068a10 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/BaseSpawner.java.patch @@ -0,0 +1,367 @@ +--- a/net/minecraft/world/level/BaseSpawner.java ++++ b/net/minecraft/world/level/BaseSpawner.java +@@ -19,9 +19,9 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.SpawnPlacements; + import net.minecraft.world.level.entity.EntityTypeTest; + import net.minecraft.world.level.gameevent.GameEvent; +@@ -33,39 +33,40 @@ + public static final String SPAWN_DATA_TAG = "SpawnData"; + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int EVENT_SPAWN = 1; +- private int spawnDelay = 20; +- private SimpleWeightedRandomList spawnPotentials = SimpleWeightedRandomList.empty(); ++ public int spawnDelay = 20; ++ public SimpleWeightedRandomList spawnPotentials = SimpleWeightedRandomList.empty(); + @Nullable +- private SpawnData nextSpawnData; ++ public SpawnData nextSpawnData; + private double spin; + private double oSpin; +- private int minSpawnDelay = 200; +- private int maxSpawnDelay = 800; +- private int spawnCount = 4; ++ public int minSpawnDelay = 200; ++ public int maxSpawnDelay = 800; ++ public int spawnCount = 4; + @Nullable + private Entity displayEntity; +- private int maxNearbyEntities = 6; +- private int requiredPlayerRange = 16; +- private int spawnRange = 4; ++ public int maxNearbyEntities = 6; ++ public int requiredPlayerRange = 16; ++ public int spawnRange = 4; + + public BaseSpawner() {} + +- public void setEntityId(EntityType entitytype, @Nullable Level level, RandomSource randomsource, BlockPos blockpos) { +- this.getOrCreateNextSpawnData(level, randomsource, blockpos).getEntityToSpawn().putString("id", BuiltInRegistries.ENTITY_TYPE.getKey(entitytype).toString()); ++ public void setEntityId(EntityType type, @Nullable Level level, RandomSource random, BlockPos pos) { ++ this.getOrCreateNextSpawnData(level, random, pos).getEntityToSpawn().putString("id", BuiltInRegistries.ENTITY_TYPE.getKey(type).toString()); ++ this.spawnPotentials = SimpleWeightedRandomList.empty(); // CraftBukkit - SPIGOT-3496, MC-92282 + } + +- private boolean isNearPlayer(Level level, BlockPos blockpos) { +- return level.hasNearbyAlivePlayer((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D, (double) this.requiredPlayerRange); ++ private boolean isNearPlayer(Level level, BlockPos pos) { ++ return level.hasNearbyAlivePlayer((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (double) this.requiredPlayerRange); + } + +- public void clientTick(Level level, BlockPos blockpos) { +- if (!this.isNearPlayer(level, blockpos)) { ++ public void clientTick(Level level, BlockPos pos) { ++ if (!this.isNearPlayer(level, pos)) { + this.oSpin = this.spin; + } else if (this.displayEntity != null) { + RandomSource randomsource = level.getRandom(); +- double d0 = (double) blockpos.getX() + randomsource.nextDouble(); +- double d1 = (double) blockpos.getY() + randomsource.nextDouble(); +- double d2 = (double) blockpos.getZ() + randomsource.nextDouble(); ++ double d0 = (double) pos.getX() + randomsource.nextDouble(); ++ double d1 = (double) pos.getY() + randomsource.nextDouble(); ++ double d2 = (double) pos.getZ() + randomsource.nextDouble(); + + level.addParticle(ParticleTypes.SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); + level.addParticle(ParticleTypes.FLAME, d0, d1, d2, 0.0D, 0.0D, 0.0D); +@@ -79,88 +80,93 @@ + + } + +- public void serverTick(ServerLevel serverlevel, BlockPos blockpos) { +- if (this.isNearPlayer(serverlevel, blockpos)) { ++ public void serverTick(ServerLevel serverLevel, BlockPos pos) { ++ if (this.isNearPlayer(serverLevel, pos)) { + if (this.spawnDelay == -1) { +- this.delay(serverlevel, blockpos); ++ this.delay(serverLevel, pos); + } + + if (this.spawnDelay > 0) { + --this.spawnDelay; + } else { + boolean flag = false; +- RandomSource randomsource = serverlevel.getRandom(); +- SpawnData spawndata = this.getOrCreateNextSpawnData(serverlevel, randomsource, blockpos); ++ RandomSource randomsource = serverLevel.getRandom(); ++ SpawnData mobspawnerdata = this.getOrCreateNextSpawnData(serverLevel, randomsource, pos); + + for (int i = 0; i < this.spawnCount; ++i) { +- CompoundTag compoundtag = spawndata.getEntityToSpawn(); +- Optional> optional = EntityType.by(compoundtag); ++ CompoundTag nbttagcompound = mobspawnerdata.getEntityToSpawn(); ++ Optional> optional = EntityType.by(nbttagcompound); + + if (optional.isEmpty()) { +- this.delay(serverlevel, blockpos); ++ this.delay(serverLevel, pos); + return; + } + +- ListTag listtag = compoundtag.getList("Pos", 6); +- int j = listtag.size(); +- double d0 = j >= 1 ? listtag.getDouble(0) : (double) blockpos.getX() + (randomsource.nextDouble() - randomsource.nextDouble()) * (double) this.spawnRange + 0.5D; +- double d1 = j >= 2 ? listtag.getDouble(1) : (double) (blockpos.getY() + randomsource.nextInt(3) - 1); +- double d2 = j >= 3 ? listtag.getDouble(2) : (double) blockpos.getZ() + (randomsource.nextDouble() - randomsource.nextDouble()) * (double) this.spawnRange + 0.5D; ++ ListTag nbttaglist = nbttagcompound.getList("Pos", 6); ++ int j = nbttaglist.size(); ++ double d0 = j >= 1 ? nbttaglist.getDouble(0) : (double) pos.getX() + (randomsource.nextDouble() - randomsource.nextDouble()) * (double) this.spawnRange + 0.5D; ++ double d1 = j >= 2 ? nbttaglist.getDouble(1) : (double) (pos.getY() + randomsource.nextInt(3) - 1); ++ double d2 = j >= 3 ? nbttaglist.getDouble(2) : (double) pos.getZ() + (randomsource.nextDouble() - randomsource.nextDouble()) * (double) this.spawnRange + 0.5D; + +- if (serverlevel.noCollision(((EntityType) optional.get()).getAABB(d0, d1, d2))) { +- BlockPos blockpos1 = BlockPos.containing(d0, d1, d2); ++ if (serverLevel.noCollision(((EntityType) optional.get()).getAABB(d0, d1, d2))) { ++ BlockPos blockposition1 = BlockPos.containing(d0, d1, d2); + +- if (spawndata.getCustomSpawnRules().isPresent()) { +- if (!((EntityType) optional.get()).getCategory().isFriendly() && serverlevel.getDifficulty() == Difficulty.PEACEFUL) { ++ if (mobspawnerdata.getCustomSpawnRules().isPresent()) { ++ if (!((EntityType) optional.get()).getCategory().isFriendly() && serverLevel.getDifficulty() == Difficulty.PEACEFUL) { + continue; + } + +- SpawnData.CustomSpawnRules spawndata_customspawnrules = (SpawnData.CustomSpawnRules) spawndata.getCustomSpawnRules().get(); ++ SpawnData.CustomSpawnRules mobspawnerdata_a = (SpawnData.CustomSpawnRules) mobspawnerdata.getCustomSpawnRules().get(); + +- if (!spawndata_customspawnrules.blockLightLimit().isValueInRange(serverlevel.getBrightness(LightLayer.BLOCK, blockpos1)) || !spawndata_customspawnrules.skyLightLimit().isValueInRange(serverlevel.getBrightness(LightLayer.SKY, blockpos1))) { ++ if (!mobspawnerdata_a.blockLightLimit().isValueInRange(serverLevel.getBrightness(EnumSkyBlock.BLOCK, blockposition1)) || !mobspawnerdata_a.skyLightLimit().isValueInRange(serverLevel.getBrightness(EnumSkyBlock.SKY, blockposition1))) { + continue; + } +- } else if (!SpawnPlacements.checkSpawnRules((EntityType) optional.get(), serverlevel, MobSpawnType.SPAWNER, blockpos1, serverlevel.getRandom())) { ++ } else if (!SpawnPlacements.checkSpawnRules((EntityType) optional.get(), serverLevel, EnumMobSpawn.SPAWNER, blockposition1, serverLevel.getRandom())) { + continue; + } + +- Entity entity = EntityType.loadEntityRecursive(compoundtag, serverlevel, (entity1) -> { ++ Entity entity = EntityType.loadEntityRecursive(nbttagcompound, serverLevel, (entity1) -> { + entity1.moveTo(d0, d1, d2, entity1.getYRot(), entity1.getXRot()); + return entity1; + }); + + if (entity == null) { +- this.delay(serverlevel, blockpos); ++ this.delay(serverLevel, pos); + return; + } + +- int k = serverlevel.getEntities(EntityTypeTest.forExactClass(entity.getClass()), (new AABB((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), (double) (blockpos.getX() + 1), (double) (blockpos.getY() + 1), (double) (blockpos.getZ() + 1))).inflate((double) this.spawnRange), EntitySelector.NO_SPECTATORS).size(); ++ int k = serverLevel.getEntities(EntityTypeTest.forExactClass(entity.getClass()), (new AABB((double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), (double) (pos.getX() + 1), (double) (pos.getY() + 1), (double) (pos.getZ() + 1))).inflate((double) this.spawnRange), EntitySelector.NO_SPECTATORS).size(); + + if (k >= this.maxNearbyEntities) { +- this.delay(serverlevel, blockpos); ++ this.delay(serverLevel, pos); + return; + } + + entity.moveTo(entity.getX(), entity.getY(), entity.getZ(), randomsource.nextFloat() * 360.0F, 0.0F); + if (entity instanceof Mob) { +- Mob mob = (Mob) entity; ++ Mob entityinsentient = (Mob) entity; + +- if (spawndata.getCustomSpawnRules().isEmpty() && !mob.checkSpawnRules(serverlevel, MobSpawnType.SPAWNER) || !mob.checkSpawnObstruction(serverlevel)) { ++ if (mobspawnerdata.getCustomSpawnRules().isEmpty() && !entityinsentient.checkSpawnRules(serverLevel, EnumMobSpawn.SPAWNER) || !entityinsentient.checkSpawnObstruction(serverLevel)) { + continue; + } + +- if (spawndata.getEntityToSpawn().size() == 1 && spawndata.getEntityToSpawn().contains("id", 8)) { +- ((Mob) entity).finalizeSpawn(serverlevel, serverlevel.getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.SPAWNER, (SpawnGroupData) null, (CompoundTag) null); ++ if (mobspawnerdata.getEntityToSpawn().size() == 1 && mobspawnerdata.getEntityToSpawn().contains("id", 8)) { ++ ((Mob) entity).finalizeSpawn(serverLevel, serverLevel.getCurrentDifficultyAt(entity.blockPosition()), EnumMobSpawn.SPAWNER, (GroupDataEntity) null, (CompoundTag) null); + } + } + +- if (!serverlevel.tryAddFreshEntityWithPassengers(entity)) { +- this.delay(serverlevel, blockpos); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) { ++ continue; ++ } ++ if (!serverLevel.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER)) { ++ // CraftBukkit end ++ this.delay(serverLevel, pos); + return; + } + +- serverlevel.levelEvent(2004, blockpos, 0); +- serverlevel.gameEvent(entity, GameEvent.ENTITY_PLACE, blockpos1); ++ serverLevel.levelEvent(2004, pos, 0); ++ serverLevel.gameEvent(entity, GameEvent.ENTITY_PLACE, blockposition1); + if (entity instanceof Mob) { + ((Mob) entity).spawnAnim(); + } +@@ -170,14 +176,14 @@ + } + + if (flag) { +- this.delay(serverlevel, blockpos); ++ this.delay(serverLevel, pos); + } + + } + } + } + +- private void delay(Level level, BlockPos blockpos) { ++ private void delay(Level level, BlockPos pos) { + RandomSource randomsource = level.random; + + if (this.maxSpawnDelay <= this.minSpawnDelay) { +@@ -186,83 +192,83 @@ + this.spawnDelay = this.minSpawnDelay + randomsource.nextInt(this.maxSpawnDelay - this.minSpawnDelay); + } + +- this.spawnPotentials.getRandom(randomsource).ifPresent((weightedentry_wrapper) -> { +- this.setNextSpawnData(level, blockpos, (SpawnData) weightedentry_wrapper.getData()); ++ this.spawnPotentials.getRandom(randomsource).ifPresent((weightedentry_b) -> { ++ this.setNextSpawnData(level, pos, (SpawnData) weightedentry_b.getData()); + }); +- this.broadcastEvent(level, blockpos, 1); ++ this.broadcastEvent(level, pos, 1); + } + +- public void load(@Nullable Level level, BlockPos blockpos, CompoundTag compoundtag) { +- this.spawnDelay = compoundtag.getShort("Delay"); +- boolean flag = compoundtag.contains("SpawnData", 10); ++ public void load(@Nullable Level level, BlockPos pos, CompoundTag tag) { ++ this.spawnDelay = tag.getShort("Delay"); ++ boolean flag = tag.contains("SpawnData", 10); + + if (flag) { +- SpawnData spawndata = (SpawnData) SpawnData.CODEC.parse(NbtOps.INSTANCE, compoundtag.getCompound("SpawnData")).resultOrPartial((s) -> { ++ SpawnData mobspawnerdata = (SpawnData) SpawnData.CODEC.parse(NbtOps.INSTANCE, tag.getCompound("SpawnData")).resultOrPartial((s) -> { + BaseSpawner.LOGGER.warn("Invalid SpawnData: {}", s); + }).orElseGet(SpawnData::new); + +- this.setNextSpawnData(level, blockpos, spawndata); ++ this.setNextSpawnData(level, pos, mobspawnerdata); + } + +- boolean flag1 = compoundtag.contains("SpawnPotentials", 9); ++ boolean flag1 = tag.contains("SpawnPotentials", 9); + + if (flag1) { +- ListTag listtag = compoundtag.getList("SpawnPotentials", 10); ++ ListTag nbttaglist = tag.getList("SpawnPotentials", 10); + +- this.spawnPotentials = (SimpleWeightedRandomList) SpawnData.LIST_CODEC.parse(NbtOps.INSTANCE, listtag).resultOrPartial((s) -> { ++ this.spawnPotentials = (SimpleWeightedRandomList) SpawnData.LIST_CODEC.parse(NbtOps.INSTANCE, nbttaglist).resultOrPartial((s) -> { + BaseSpawner.LOGGER.warn("Invalid SpawnPotentials list: {}", s); + }).orElseGet(SimpleWeightedRandomList::empty); + } else { + this.spawnPotentials = SimpleWeightedRandomList.single(this.nextSpawnData != null ? this.nextSpawnData : new SpawnData()); + } + +- if (compoundtag.contains("MinSpawnDelay", 99)) { +- this.minSpawnDelay = compoundtag.getShort("MinSpawnDelay"); +- this.maxSpawnDelay = compoundtag.getShort("MaxSpawnDelay"); +- this.spawnCount = compoundtag.getShort("SpawnCount"); ++ if (tag.contains("MinSpawnDelay", 99)) { ++ this.minSpawnDelay = tag.getShort("MinSpawnDelay"); ++ this.maxSpawnDelay = tag.getShort("MaxSpawnDelay"); ++ this.spawnCount = tag.getShort("SpawnCount"); + } + +- if (compoundtag.contains("MaxNearbyEntities", 99)) { +- this.maxNearbyEntities = compoundtag.getShort("MaxNearbyEntities"); +- this.requiredPlayerRange = compoundtag.getShort("RequiredPlayerRange"); ++ if (tag.contains("MaxNearbyEntities", 99)) { ++ this.maxNearbyEntities = tag.getShort("MaxNearbyEntities"); ++ this.requiredPlayerRange = tag.getShort("RequiredPlayerRange"); + } + +- if (compoundtag.contains("SpawnRange", 99)) { +- this.spawnRange = compoundtag.getShort("SpawnRange"); ++ if (tag.contains("SpawnRange", 99)) { ++ this.spawnRange = tag.getShort("SpawnRange"); + } + + this.displayEntity = null; + } + +- public CompoundTag save(CompoundTag compoundtag) { +- compoundtag.putShort("Delay", (short) this.spawnDelay); +- compoundtag.putShort("MinSpawnDelay", (short) this.minSpawnDelay); +- compoundtag.putShort("MaxSpawnDelay", (short) this.maxSpawnDelay); +- compoundtag.putShort("SpawnCount", (short) this.spawnCount); +- compoundtag.putShort("MaxNearbyEntities", (short) this.maxNearbyEntities); +- compoundtag.putShort("RequiredPlayerRange", (short) this.requiredPlayerRange); +- compoundtag.putShort("SpawnRange", (short) this.spawnRange); ++ public CompoundTag save(CompoundTag tag) { ++ tag.putShort("Delay", (short) this.spawnDelay); ++ tag.putShort("MinSpawnDelay", (short) this.minSpawnDelay); ++ tag.putShort("MaxSpawnDelay", (short) this.maxSpawnDelay); ++ tag.putShort("SpawnCount", (short) this.spawnCount); ++ tag.putShort("MaxNearbyEntities", (short) this.maxNearbyEntities); ++ tag.putShort("RequiredPlayerRange", (short) this.requiredPlayerRange); ++ tag.putShort("SpawnRange", (short) this.spawnRange); + if (this.nextSpawnData != null) { +- compoundtag.put("SpawnData", (Tag) SpawnData.CODEC.encodeStart(NbtOps.INSTANCE, this.nextSpawnData).result().orElseThrow(() -> { ++ tag.put("SpawnData", (Tag) SpawnData.CODEC.encodeStart(NbtOps.INSTANCE, this.nextSpawnData).result().orElseThrow(() -> { + return new IllegalStateException("Invalid SpawnData"); + })); + } + +- compoundtag.put("SpawnPotentials", (Tag) SpawnData.LIST_CODEC.encodeStart(NbtOps.INSTANCE, this.spawnPotentials).result().orElseThrow()); +- return compoundtag; ++ tag.put("SpawnPotentials", (Tag) SpawnData.LIST_CODEC.encodeStart(NbtOps.INSTANCE, this.spawnPotentials).result().orElseThrow()); ++ return tag; + } + + @Nullable +- public Entity getOrCreateDisplayEntity(Level level, BlockPos blockpos) { ++ public Entity getOrCreateDisplayEntity(Level world, BlockPos blockposition) { + if (this.displayEntity == null) { +- CompoundTag compoundtag = this.getOrCreateNextSpawnData(level, level.getRandom(), blockpos).getEntityToSpawn(); ++ CompoundTag nbttagcompound = this.getOrCreateNextSpawnData(world, world.getRandom(), blockposition).getEntityToSpawn(); + +- if (!compoundtag.contains("id", 8)) { ++ if (!nbttagcompound.contains("id", 8)) { + return null; + } + +- this.displayEntity = EntityType.loadEntityRecursive(compoundtag, level, Function.identity()); +- if (compoundtag.size() == 1 && this.displayEntity instanceof Mob) { ++ this.displayEntity = EntityType.loadEntityRecursive(nbttagcompound, world, Function.identity()); ++ if (nbttagcompound.size() == 1 && this.displayEntity instanceof Mob) { + ; + } + } +@@ -270,8 +276,8 @@ + return this.displayEntity; + } + +- public boolean onEventTriggered(Level level, int i) { +- if (i == 1) { ++ public boolean onEventTriggered(Level level, int id) { ++ if (id == 1) { + if (level.isClientSide) { + this.spawnDelay = this.minSpawnDelay; + } +@@ -282,15 +288,15 @@ + } + } + +- protected void setNextSpawnData(@Nullable Level level, BlockPos blockpos, SpawnData spawndata) { +- this.nextSpawnData = spawndata; ++ protected void setNextSpawnData(@Nullable Level level, BlockPos pos, SpawnData nextSpawnData) { ++ this.nextSpawnData = nextSpawnData; + } + +- private SpawnData getOrCreateNextSpawnData(@Nullable Level level, RandomSource randomsource, BlockPos blockpos) { ++ private SpawnData getOrCreateNextSpawnData(@Nullable Level level, RandomSource random, BlockPos pos) { + if (this.nextSpawnData != null) { + return this.nextSpawnData; + } else { +- this.setNextSpawnData(level, blockpos, (SpawnData) this.spawnPotentials.getRandom(randomsource).map(WeightedEntry.Wrapper::getData).orElseGet(SpawnData::new)); ++ this.setNextSpawnData(level, pos, (SpawnData) this.spawnPotentials.getRandom(random).map(WeightedEntry.Wrapper::getData).orElseGet(SpawnData::new)); + return this.nextSpawnData; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/BlockGetter.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/BlockGetter.java.patch new file mode 100644 index 0000000000..ffc0fc8e85 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/BlockGetter.java.patch @@ -0,0 +1,208 @@ +--- a/net/minecraft/world/level/BlockGetter.java ++++ b/net/minecraft/world/level/BlockGetter.java +@@ -11,7 +11,7 @@ + import net.minecraft.util.Mth; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BlockEntityType; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.BlockHitResult; +@@ -23,110 +23,116 @@ + @Nullable + BlockEntity getBlockEntity(BlockPos pos); + +- default Optional getBlockEntity(BlockPos blockpos, BlockEntityType blockentitytype) { +- BlockEntity blockentity = this.getBlockEntity(blockpos); ++ default Optional getBlockEntity(BlockPos pos, BlockEntityType blockEntityType) { ++ BlockEntity tileentity = this.getBlockEntity(pos); + +- return blockentity != null && blockentity.getType() == blockentitytype ? Optional.of(blockentity) : Optional.empty(); ++ return tileentity != null && tileentity.getType() == blockEntityType ? (Optional) Optional.of(tileentity) : Optional.empty(); // CraftBukkit - decompile error + } + +- BlockState getBlockState(BlockPos pos); ++ IBlockData getBlockState(BlockPos pos); + + FluidState getFluidState(BlockPos pos); + +- default int getLightEmission(BlockPos blockpos) { +- return this.getBlockState(blockpos).getLightEmission(); ++ default int getLightEmission(BlockPos pos) { ++ return this.getBlockState(pos).getLightEmission(); + } + + default int getMaxLightLevel() { + return 15; + } + +- default Stream getBlockStates(AABB aabb) { +- return BlockPos.betweenClosedStream(aabb).map(this::getBlockState); ++ default Stream getBlockStates(AABB area) { ++ return BlockPos.betweenClosedStream(area).map(this::getBlockState); + } + +- default BlockHitResult isBlockInLine(ClipBlockStateContext clipblockstatecontext) { +- return (BlockHitResult) traverseBlocks(clipblockstatecontext.getFrom(), clipblockstatecontext.getTo(), clipblockstatecontext, (clipblockstatecontext1, blockpos) -> { +- BlockState blockstate = this.getBlockState(blockpos); +- Vec3 vec3 = clipblockstatecontext1.getFrom().subtract(clipblockstatecontext1.getTo()); ++ default BlockHitResult isBlockInLine(ClipBlockStateContext context) { ++ return (BlockHitResult) traverseBlocks(context.getFrom(), context.getTo(), context, (clipblockstatecontext1, blockposition) -> { ++ IBlockData iblockdata = this.getBlockState(blockposition); ++ Vec3 vec3d = clipblockstatecontext1.getFrom().subtract(clipblockstatecontext1.getTo()); + +- return clipblockstatecontext1.isTargetBlock().test(blockstate) ? new BlockHitResult(clipblockstatecontext1.getTo(), Direction.getNearest(vec3.x, vec3.y, vec3.z), BlockPos.containing(clipblockstatecontext1.getTo()), false) : null; ++ return clipblockstatecontext1.isTargetBlock().test(iblockdata) ? new BlockHitResult(clipblockstatecontext1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(clipblockstatecontext1.getTo()), false) : null; + }, (clipblockstatecontext1) -> { +- Vec3 vec3 = clipblockstatecontext1.getFrom().subtract(clipblockstatecontext1.getTo()); ++ Vec3 vec3d = clipblockstatecontext1.getFrom().subtract(clipblockstatecontext1.getTo()); + +- return BlockHitResult.miss(clipblockstatecontext1.getTo(), Direction.getNearest(vec3.x, vec3.y, vec3.z), BlockPos.containing(clipblockstatecontext1.getTo())); ++ return BlockHitResult.miss(clipblockstatecontext1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(clipblockstatecontext1.getTo())); + }); + } + +- default BlockHitResult clip(ClipContext clipcontext) { +- return (BlockHitResult) traverseBlocks(clipcontext.getFrom(), clipcontext.getTo(), clipcontext, (clipcontext1, blockpos) -> { +- BlockState blockstate = this.getBlockState(blockpos); +- FluidState fluidstate = this.getFluidState(blockpos); +- Vec3 vec3 = clipcontext1.getFrom(); +- Vec3 vec31 = clipcontext1.getTo(); +- VoxelShape voxelshape = clipcontext1.getBlockShape(blockstate, this, blockpos); +- BlockHitResult blockhitresult = this.clipWithInteractionOverride(vec3, vec31, blockpos, voxelshape, blockstate); +- VoxelShape voxelshape1 = clipcontext1.getFluidShape(fluidstate, this, blockpos); +- BlockHitResult blockhitresult1 = voxelshape1.clip(vec3, vec31, blockpos); +- double d0 = blockhitresult == null ? Double.MAX_VALUE : clipcontext1.getFrom().distanceToSqr(blockhitresult.getLocation()); +- double d1 = blockhitresult1 == null ? Double.MAX_VALUE : clipcontext1.getFrom().distanceToSqr(blockhitresult1.getLocation()); ++ // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace ++ default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition) { ++ IBlockData iblockdata = this.getBlockState(blockposition); ++ FluidState fluid = this.getFluidState(blockposition); ++ Vec3 vec3d = raytrace1.getFrom(); ++ Vec3 vec3d1 = raytrace1.getTo(); ++ VoxelShape voxelshape = raytrace1.getBlockShape(iblockdata, this, blockposition); ++ BlockHitResult movingobjectpositionblock = this.clipWithInteractionOverride(vec3d, vec3d1, blockposition, voxelshape, iblockdata); ++ VoxelShape voxelshape1 = raytrace1.getFluidShape(fluid, this, blockposition); ++ BlockHitResult movingobjectpositionblock1 = voxelshape1.clip(vec3d, vec3d1, blockposition); ++ double d0 = movingobjectpositionblock == null ? Double.MAX_VALUE : raytrace1.getFrom().distanceToSqr(movingobjectpositionblock.getLocation()); ++ double d1 = movingobjectpositionblock1 == null ? Double.MAX_VALUE : raytrace1.getFrom().distanceToSqr(movingobjectpositionblock1.getLocation()); + +- return d0 <= d1 ? blockhitresult : blockhitresult1; +- }, (clipcontext1) -> { +- Vec3 vec3 = clipcontext1.getFrom().subtract(clipcontext1.getTo()); ++ return d0 <= d1 ? movingobjectpositionblock : movingobjectpositionblock1; ++ } ++ // CraftBukkit end + +- return BlockHitResult.miss(clipcontext1.getTo(), Direction.getNearest(vec3.x, vec3.y, vec3.z), BlockPos.containing(clipcontext1.getTo())); ++ default BlockHitResult clip(ClipContext context) { ++ return (BlockHitResult) traverseBlocks(context.getFrom(), context.getTo(), context, (raytrace1, blockposition) -> { ++ return this.clip(raytrace1, blockposition); // CraftBukkit - moved into separate method ++ }, (raytrace1) -> { ++ Vec3 vec3d = raytrace1.getFrom().subtract(raytrace1.getTo()); ++ ++ return BlockHitResult.miss(raytrace1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(raytrace1.getTo())); + }); + } + + @Nullable +- default BlockHitResult clipWithInteractionOverride(Vec3 vec3, Vec3 vec31, BlockPos blockpos, VoxelShape voxelshape, BlockState blockstate) { +- BlockHitResult blockhitresult = voxelshape.clip(vec3, vec31, blockpos); ++ default BlockHitResult clipWithInteractionOverride(Vec3 startVec, Vec3 endVec, BlockPos pos, VoxelShape shape, IBlockData state) { ++ BlockHitResult movingobjectpositionblock = shape.clip(startVec, endVec, pos); + +- if (blockhitresult != null) { +- BlockHitResult blockhitresult1 = blockstate.getInteractionShape(this, blockpos).clip(vec3, vec31, blockpos); ++ if (movingobjectpositionblock != null) { ++ BlockHitResult movingobjectpositionblock1 = state.getInteractionShape(this, pos).clip(startVec, endVec, pos); + +- if (blockhitresult1 != null && blockhitresult1.getLocation().subtract(vec3).lengthSqr() < blockhitresult.getLocation().subtract(vec3).lengthSqr()) { +- return blockhitresult.withDirection(blockhitresult1.getDirection()); ++ if (movingobjectpositionblock1 != null && movingobjectpositionblock1.getLocation().subtract(startVec).lengthSqr() < movingobjectpositionblock.getLocation().subtract(startVec).lengthSqr()) { ++ return movingobjectpositionblock.withDirection(movingobjectpositionblock1.getDirection()); + } + } + +- return blockhitresult; ++ return movingobjectpositionblock; + } + +- default double getBlockFloorHeight(VoxelShape voxelshape, Supplier supplier) { +- if (!voxelshape.isEmpty()) { +- return voxelshape.max(Direction.Axis.Y); ++ default double getBlockFloorHeight(VoxelShape shape, Supplier belowShapeSupplier) { ++ if (!shape.isEmpty()) { ++ return shape.max(Direction.Axis.Y); + } else { +- double d0 = ((VoxelShape) supplier.get()).max(Direction.Axis.Y); ++ double d0 = ((VoxelShape) belowShapeSupplier.get()).max(Direction.Axis.Y); + + return d0 >= 1.0D ? d0 - 1.0D : Double.NEGATIVE_INFINITY; + } + } + +- default double getBlockFloorHeight(BlockPos blockpos) { +- return this.getBlockFloorHeight(this.getBlockState(blockpos).getCollisionShape(this, blockpos), () -> { +- BlockPos blockpos1 = blockpos.below(); ++ default double getBlockFloorHeight(BlockPos pos) { ++ return this.getBlockFloorHeight(this.getBlockState(pos).getCollisionShape(this, pos), () -> { ++ BlockPos blockposition1 = pos.below(); + +- return this.getBlockState(blockpos1).getCollisionShape(this, blockpos1); ++ return this.getBlockState(blockposition1).getCollisionShape(this, blockposition1); + }); + } + +- static T traverseBlocks(Vec3 vec3, Vec3 vec31, C c0, BiFunction bifunction, Function function) { +- if (vec3.equals(vec31)) { +- return function.apply(c0); ++ static T traverseBlocks(Vec3 from, Vec3 to, C context, BiFunction tester, Function onFail) { ++ if (from.equals(to)) { ++ return onFail.apply(context); + } else { +- double d0 = Mth.lerp(-1.0E-7D, vec31.x, vec3.x); +- double d1 = Mth.lerp(-1.0E-7D, vec31.y, vec3.y); +- double d2 = Mth.lerp(-1.0E-7D, vec31.z, vec3.z); +- double d3 = Mth.lerp(-1.0E-7D, vec3.x, vec31.x); +- double d4 = Mth.lerp(-1.0E-7D, vec3.y, vec31.y); +- double d5 = Mth.lerp(-1.0E-7D, vec3.z, vec31.z); ++ double d0 = Mth.lerp(-1.0E-7D, to.x, from.x); ++ double d1 = Mth.lerp(-1.0E-7D, to.y, from.y); ++ double d2 = Mth.lerp(-1.0E-7D, to.z, from.z); ++ double d3 = Mth.lerp(-1.0E-7D, from.x, to.x); ++ double d4 = Mth.lerp(-1.0E-7D, from.y, to.y); ++ double d5 = Mth.lerp(-1.0E-7D, from.z, to.z); + int i = Mth.floor(d3); + int j = Mth.floor(d4); + int k = Mth.floor(d5); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(i, j, k); +- T t0 = bifunction.apply(c0, blockpos_mutableblockpos); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(i, j, k); ++ T t0 = tester.apply(context, blockposition_mutableblockposition); + + if (t0 != null) { + return t0; +@@ -144,11 +150,11 @@ + double d13 = d10 * (i1 > 0 ? 1.0D - Mth.frac(d4) : Mth.frac(d4)); + double d14 = d11 * (j1 > 0 ? 1.0D - Mth.frac(d5) : Mth.frac(d5)); + +- Object object; ++ T object; // CraftBukkit - decompile error + + do { + if (d12 > 1.0D && d13 > 1.0D && d14 > 1.0D) { +- return function.apply(c0); ++ return onFail.apply(context); + } + + if (d12 < d13) { +@@ -167,7 +173,7 @@ + d14 += d11; + } + +- object = bifunction.apply(c0, blockpos_mutableblockpos.set(i, j, k)); ++ object = tester.apply(context, blockposition_mutableblockposition.set(i, j, k)); + } while (object == null); + + return object; diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/ClipContext.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/ClipContext.java.patch new file mode 100644 index 0000000000..335c2f59f4 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/ClipContext.java.patch @@ -0,0 +1,112 @@ +--- a/net/minecraft/world/level/ClipContext.java ++++ b/net/minecraft/world/level/ClipContext.java +@@ -6,7 +6,7 @@ + import net.minecraft.tags.FluidTags; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; +@@ -21,16 +21,16 @@ + private final ClipContext.Fluid fluid; + private final CollisionContext collisionContext; + +- public ClipContext(Vec3 vec3, Vec3 vec31, ClipContext.Block clipcontext_block, ClipContext.Fluid clipcontext_fluid, Entity entity) { +- this(vec3, vec31, clipcontext_block, clipcontext_fluid, CollisionContext.of(entity)); ++ public ClipContext(Vec3 from, Vec3 to, ClipContext.Block block, ClipContext.Fluid fluid, Entity entity) { ++ this(from, to, block, fluid, (entity == null) ? CollisionContext.empty() : CollisionContext.of(entity)); // CraftBukkit + } + +- public ClipContext(Vec3 vec3, Vec3 vec31, ClipContext.Block clipcontext_block, ClipContext.Fluid clipcontext_fluid, CollisionContext collisioncontext) { +- this.from = vec3; +- this.to = vec31; +- this.block = clipcontext_block; +- this.fluid = clipcontext_fluid; +- this.collisionContext = collisioncontext; ++ public ClipContext(Vec3 vec3d, Vec3 vec3d1, ClipContext.Block raytrace_blockcollisionoption, ClipContext.Fluid raytrace_fluidcollisionoption, CollisionContext voxelshapecollision) { ++ this.from = vec3d; ++ this.to = vec3d1; ++ this.block = raytrace_blockcollisionoption; ++ this.fluid = raytrace_fluidcollisionoption; ++ this.collisionContext = voxelshapecollision; + } + + public Vec3 getTo() { +@@ -41,56 +41,55 @@ + return this.from; + } + +- public VoxelShape getBlockShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return this.block.get(blockstate, blockgetter, blockpos, this.collisionContext); ++ public VoxelShape getBlockShape(IBlockData blockState, BlockGetter level, BlockPos pos) { ++ return this.block.get(blockState, level, pos, this.collisionContext); + } + +- public VoxelShape getFluidShape(FluidState fluidstate, BlockGetter blockgetter, BlockPos blockpos) { +- return this.fluid.canPick(fluidstate) ? fluidstate.getShape(blockgetter, blockpos) : Shapes.empty(); ++ public VoxelShape getFluidShape(FluidState state, BlockGetter level, BlockPos pos) { ++ return this.fluid.canPick(state) ? state.getShape(level, pos) : Shapes.empty(); + } + + public static enum Block implements ClipContext.ShapeGetter { + +- COLLIDER(BlockBehaviour.BlockStateBase::getCollisionShape), OUTLINE(BlockBehaviour.BlockStateBase::getShape), VISUAL(BlockBehaviour.BlockStateBase::getVisualShape), FALLDAMAGE_RESETTING((blockstate, blockgetter, blockpos, collisioncontext) -> { +- return blockstate.is(BlockTags.FALL_DAMAGE_RESETTING) ? Shapes.block() : Shapes.empty(); ++ COLLIDER(BlockBehaviour.BlockStateBase::getCollisionShape), OUTLINE(BlockBehaviour.BlockStateBase::getShape), VISUAL(BlockBehaviour.BlockStateBase::getVisualShape), FALLDAMAGE_RESETTING((iblockdata, iblockaccess, blockposition, voxelshapecollision) -> { ++ return iblockdata.is(BlockTags.FALL_DAMAGE_RESETTING) ? Shapes.block() : Shapes.empty(); + }); + + private final ClipContext.ShapeGetter shapeGetter; + +- private Block(ClipContext.ShapeGetter clipcontext_shapegetter) { +- this.shapeGetter = clipcontext_shapegetter; ++ private Block(ClipContext.ShapeGetter raytrace_c) { ++ this.shapeGetter = raytrace_c; + } + + @Override +- @Override +- public VoxelShape get(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return this.shapeGetter.get(blockstate, blockgetter, blockpos, collisioncontext); ++ public VoxelShape get(IBlockData state, BlockGetter block, BlockPos pos, CollisionContext collisionContext) { ++ return this.shapeGetter.get(state, block, pos, collisionContext); + } + } + + public static enum Fluid { + +- NONE((fluidstate) -> { ++ NONE((fluid) -> { + return false; +- }), SOURCE_ONLY(FluidState::isSource), ANY((fluidstate) -> { +- return !fluidstate.isEmpty(); +- }), WATER((fluidstate) -> { +- return fluidstate.is(FluidTags.WATER); ++ }), SOURCE_ONLY(FluidState::isSource), ANY((fluid) -> { ++ return !fluid.isEmpty(); ++ }), WATER((fluid) -> { ++ return fluid.is(FluidTags.WATER); + }); + + private final Predicate canPick; + +- private Fluid(Predicate predicate) { ++ private Fluid(Predicate predicate) { // CraftBukkit - decompile error + this.canPick = predicate; + } + +- public boolean canPick(FluidState fluidstate) { +- return this.canPick.test(fluidstate); ++ public boolean canPick(FluidState state) { ++ return this.canPick.test(state); + } + } + + public interface ShapeGetter { + +- VoxelShape get(BlockState state, BlockGetter block, BlockPos pos, CollisionContext collisionContext); ++ VoxelShape get(IBlockData state, BlockGetter block, BlockPos pos, CollisionContext collisionContext); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/Explosion.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/Explosion.java.patch new file mode 100644 index 0000000000..1e6eb4a118 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/Explosion.java.patch @@ -0,0 +1,470 @@ +--- a/net/minecraft/world/level/Explosion.java ++++ b/net/minecraft/world/level/Explosion.java +@@ -24,6 +24,8 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; ++import net.minecraft.world.entity.boss.EnderDragonPart; ++import net.minecraft.world.entity.boss.enderdragon.EnderDragon; + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.item.PrimedTnt; + import net.minecraft.world.entity.player.Player; +@@ -32,26 +34,32 @@ + import net.minecraft.world.item.enchantment.ProtectionEnchantment; + import net.minecraft.world.level.block.BaseFireBlock; + import net.minecraft.world.level.block.Block; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++import net.minecraft.world.level.block.Blocks; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityExplodeEvent; ++import org.bukkit.Location; ++import org.bukkit.event.block.BlockExplodeEvent; ++// CraftBukkit end + + public class Explosion { + + private static final ExplosionDamageCalculator EXPLOSION_DAMAGE_CALCULATOR = new ExplosionDamageCalculator(); + private static final int MAX_DROPS_PER_COMBINED_STACK = 16; + private final boolean fire; +- private final Explosion.BlockInteraction blockInteraction; ++ private final Explosion.Effect blockInteraction; + private final RandomSource random; + private final Level level; + private final double x; + private final double y; + private final double z; + @Nullable +- private final Entity source; ++ public final Entity source; + private final float radius; + private final DamageSource damageSource; + private final ExplosionDamageCalculator damageCalculator; +@@ -60,53 +68,58 @@ + private final SoundEvent explosionSound; + private final ObjectArrayList toBlow; + private final Map hitPlayers; ++ // CraftBukkit - add field ++ public boolean wasCanceled = false; ++ public float yield; ++ // CraftBukkit end + +- public static DamageSource getDefaultDamageSource(Level level, @Nullable Entity entity) { +- return level.damageSources().explosion(entity, getIndirectSourceEntityInternal(entity)); ++ public static DamageSource getDefaultDamageSource(Level world, @Nullable Entity entity) { ++ return world.damageSources().explosion(entity, getIndirectSourceEntityInternal(entity)); + } + +- public Explosion(Level level, @Nullable Entity entity, double d0, double d1, double d2, float f, List list, Explosion.BlockInteraction explosion_blockinteraction, ParticleOptions particleoptions, ParticleOptions particleoptions1, SoundEvent soundevent) { +- this(level, entity, getDefaultDamageSource(level, entity), (ExplosionDamageCalculator) null, d0, d1, d2, f, false, explosion_blockinteraction, particleoptions, particleoptions1, soundevent); ++ public Explosion(Level world, @Nullable Entity entity, double d0, double d1, double d2, float f, List list, Explosion.Effect explosion_effect, ParticleOptions particleparam, ParticleOptions particleparam1, SoundEvent soundeffect) { ++ this(world, entity, getDefaultDamageSource(world, entity), (ExplosionDamageCalculator) null, d0, d1, d2, f, false, explosion_effect, particleparam, particleparam1, soundeffect); + this.toBlow.addAll(list); + } + +- public Explosion(Level level, @Nullable Entity entity, double d0, double d1, double d2, float f, boolean flag, Explosion.BlockInteraction explosion_blockinteraction, List list) { +- this(level, entity, d0, d1, d2, f, flag, explosion_blockinteraction); +- this.toBlow.addAll(list); ++ public Explosion(Level level, @Nullable Entity source, double toBlowX, double d1, double toBlowY, float f, boolean toBlowZ, Explosion.Effect explosion_effect, List radius) { ++ this(level, source, toBlowX, d1, toBlowY, f, toBlowZ, explosion_effect); ++ this.toBlow.addAll(radius); + } + +- public Explosion(Level level, @Nullable Entity entity, double d0, double d1, double d2, float f, boolean flag, Explosion.BlockInteraction explosion_blockinteraction) { +- this(level, entity, getDefaultDamageSource(level, entity), (ExplosionDamageCalculator) null, d0, d1, d2, f, flag, explosion_blockinteraction, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); ++ public Explosion(Level level, @Nullable Entity source, double toBlowX, double d1, double toBlowY, float f, boolean toBlowZ, Explosion.Effect explosion_effect) { ++ this(level, source, getDefaultDamageSource(level, source), (ExplosionDamageCalculator) null, toBlowX, d1, toBlowY, f, toBlowZ, explosion_effect, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); + } + +- public Explosion(Level level, @Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Explosion.BlockInteraction explosion_blockinteraction, ParticleOptions particleoptions, ParticleOptions particleoptions1, SoundEvent soundevent) { ++ public Explosion(Level world, @Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Explosion.Effect explosion_effect, ParticleOptions particleparam, ParticleOptions particleparam1, SoundEvent soundeffect) { + this.random = RandomSource.create(); + this.toBlow = new ObjectArrayList(); + this.hitPlayers = Maps.newHashMap(); +- this.level = level; ++ this.level = world; + this.source = entity; +- this.radius = f; ++ this.radius = (float) Math.max(f, 0.0); // CraftBukkit - clamp bad values + this.x = d0; + this.y = d1; + this.z = d2; + this.fire = flag; +- this.blockInteraction = explosion_blockinteraction; +- this.damageSource = damagesource == null ? level.damageSources().explosion(this) : damagesource; ++ this.blockInteraction = explosion_effect; ++ this.damageSource = damagesource == null ? world.damageSources().explosion(this) : damagesource; + this.damageCalculator = explosiondamagecalculator == null ? this.makeDamageCalculator(entity) : explosiondamagecalculator; +- this.smallExplosionParticles = particleoptions; +- this.largeExplosionParticles = particleoptions1; +- this.explosionSound = soundevent; ++ this.smallExplosionParticles = particleparam; ++ this.largeExplosionParticles = particleparam1; ++ this.explosionSound = soundeffect; ++ this.yield = this.blockInteraction == Explosion.Effect.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F; // CraftBukkit + } + + private ExplosionDamageCalculator makeDamageCalculator(@Nullable Entity entity) { + return (ExplosionDamageCalculator) (entity == null ? Explosion.EXPLOSION_DAMAGE_CALCULATOR : new EntityBasedExplosionDamageCalculator(entity)); + } + +- public static float getSeenPercent(Vec3 vec3, Entity entity) { +- AABB aabb = entity.getBoundingBox(); +- double d0 = 1.0D / ((aabb.maxX - aabb.minX) * 2.0D + 1.0D); +- double d1 = 1.0D / ((aabb.maxY - aabb.minY) * 2.0D + 1.0D); +- double d2 = 1.0D / ((aabb.maxZ - aabb.minZ) * 2.0D + 1.0D); ++ public static float getSeenPercent(Vec3 explosionVector, Entity entity) { ++ AABB axisalignedbb = entity.getBoundingBox(); ++ double d0 = 1.0D / ((axisalignedbb.maxX - axisalignedbb.minX) * 2.0D + 1.0D); ++ double d1 = 1.0D / ((axisalignedbb.maxY - axisalignedbb.minY) * 2.0D + 1.0D); ++ double d2 = 1.0D / ((axisalignedbb.maxZ - axisalignedbb.minZ) * 2.0D + 1.0D); + double d3 = (1.0D - Math.floor(1.0D / d0) * d0) / 2.0D; + double d4 = (1.0D - Math.floor(1.0D / d2) * d2) / 2.0D; + +@@ -117,12 +130,12 @@ + for (double d5 = 0.0D; d5 <= 1.0D; d5 += d0) { + for (double d6 = 0.0D; d6 <= 1.0D; d6 += d1) { + for (double d7 = 0.0D; d7 <= 1.0D; d7 += d2) { +- double d8 = Mth.lerp(d5, aabb.minX, aabb.maxX); +- double d9 = Mth.lerp(d6, aabb.minY, aabb.maxY); +- double d10 = Mth.lerp(d7, aabb.minZ, aabb.maxZ); +- Vec3 vec31 = new Vec3(d8 + d3, d9, d10 + d4); ++ double d8 = Mth.lerp(d5, axisalignedbb.minX, axisalignedbb.maxX); ++ double d9 = Mth.lerp(d6, axisalignedbb.minY, axisalignedbb.maxY); ++ double d10 = Mth.lerp(d7, axisalignedbb.minZ, axisalignedbb.maxZ); ++ Vec3 vec3d1 = new Vec3(d8 + d3, d9, d10 + d4); + +- if (entity.level().clip(new ClipContext(vec31, vec3, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, entity)).getType() == HitResult.Type.MISS) { ++ if (entity.level().clip(new ClipContext(vec3d1, explosionVector, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, entity)).getType() == HitResult.EnumMovingObjectType.MISS) { + ++i; + } + +@@ -146,6 +159,11 @@ + } + + public void explode() { ++ // CraftBukkit start ++ if (this.radius < 0.1F) { ++ return; ++ } ++ // CraftBukkit end + this.level.gameEvent(this.source, GameEvent.EXPLODE, new Vec3(this.x, this.y, this.z)); + Set set = Sets.newHashSet(); + boolean flag = true; +@@ -171,22 +189,22 @@ + double d6 = this.z; + + for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { +- BlockPos blockpos = BlockPos.containing(d4, d5, d6); +- BlockState blockstate = this.level.getBlockState(blockpos); +- FluidState fluidstate = this.level.getFluidState(blockpos); ++ BlockPos blockposition = BlockPos.containing(d4, d5, d6); ++ IBlockData iblockdata = this.level.getBlockState(blockposition); ++ FluidState fluid = this.level.getFluidState(blockposition); + +- if (!this.level.isInWorldBounds(blockpos)) { ++ if (!this.level.isInWorldBounds(blockposition)) { + break; + } + +- Optional optional = this.damageCalculator.getBlockExplosionResistance(this, this.level, blockpos, blockstate, fluidstate); ++ Optional optional = this.damageCalculator.getBlockExplosionResistance(this, this.level, blockposition, iblockdata, fluid); + + if (optional.isPresent()) { + f -= ((Float) optional.get() + 0.3F) * 0.3F; + } + +- if (f > 0.0F && this.damageCalculator.shouldBlockExplode(this, this.level, blockpos, blockstate, f)) { +- set.add(blockpos); ++ if (f > 0.0F && this.damageCalculator.shouldBlockExplode(this, this.level, blockposition, iblockdata, f)) { ++ set.add(blockposition); + } + + d4 += d0 * 0.30000001192092896D; +@@ -208,14 +226,14 @@ + int j1 = Mth.floor(this.z - (double) f2 - 1.0D); + int k1 = Mth.floor(this.z + (double) f2 + 1.0D); + List list = this.level.getEntities(this.source, new AABB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1)); +- Vec3 vec3 = new Vec3(this.x, this.y, this.z); ++ Vec3 vec3d = new Vec3(this.x, this.y, this.z); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); + + if (!entity.ignoreExplosion(this)) { +- double d7 = Math.sqrt(entity.distanceToSqr(vec3)) / (double) f2; ++ double d7 = Math.sqrt(entity.distanceToSqr(vec3d)) / (double) f2; + + if (d7 <= 1.0D) { + double d8 = entity.getX() - this.x; +@@ -228,16 +246,46 @@ + d9 /= d11; + d10 /= d11; + if (this.damageCalculator.shouldDamageEntity(this, entity)) { +- entity.hurt(this.damageSource, this.damageCalculator.getEntityDamageAmount(this, entity)); ++ // CraftBukkit start ++ ++ // Special case ender dragon only give knockback if no damage is cancelled ++ // Thinks to note: ++ // - Setting a velocity to a ComplexEntityPart is ignored (and therefore not needed) ++ // - Damaging ComplexEntityPart while forward the damage to EntityEnderDragon ++ // - Damaging EntityEnderDragon does nothing ++ // - EntityEnderDragon hitbock always covers the other parts and is therefore always present ++ if (entity instanceof EnderDragonPart) { ++ continue; ++ } ++ ++ CraftEventFactory.entityDamage = source; ++ entity.lastDamageCancelled = false; ++ ++ if (entity instanceof EnderDragon) { ++ for (EnderDragonPart entityComplexPart : ((EnderDragon) entity).subEntities) { ++ // Calculate damage separately for each EntityComplexPart ++ if (list.contains(entityComplexPart)) { ++ entityComplexPart.hurt(this.damageSource, this.damageCalculator.getEntityDamageAmount(this, entity)); ++ } ++ } ++ } else { ++ entity.hurt(this.damageSource, this.damageCalculator.getEntityDamageAmount(this, entity)); ++ } ++ ++ CraftEventFactory.entityDamage = null; ++ if (entity.lastDamageCancelled) { // SPIGOT-5339, SPIGOT-6252, SPIGOT-6777: Skip entity if damage event was cancelled ++ continue; ++ } ++ // CraftBukkit end + } + +- double d12 = (1.0D - d7) * (double) getSeenPercent(vec3, entity); ++ double d12 = (1.0D - d7) * (double) getSeenPercent(vec3d, entity); + double d13; + + if (entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; ++ LivingEntity entityliving = (LivingEntity) entity; + +- d13 = ProtectionEnchantment.getExplosionKnockbackAfterDampener(livingentity, d12); ++ d13 = ProtectionEnchantment.getExplosionKnockbackAfterDampener(entityliving, d12); + } else { + d13 = d12; + } +@@ -245,14 +293,14 @@ + d8 *= d13; + d9 *= d13; + d10 *= d13; +- Vec3 vec31 = new Vec3(d8, d9, d10); ++ Vec3 vec3d1 = new Vec3(d8, d9, d10); + +- entity.setDeltaMovement(entity.getDeltaMovement().add(vec31)); ++ entity.setDeltaMovement(entity.getDeltaMovement().add(vec3d1)); + if (entity instanceof Player) { +- Player player = (Player) entity; ++ Player entityhuman = (Player) entity; + +- if (!player.isSpectator() && (!player.isCreative() || !player.getAbilities().flying)) { +- this.hitPlayers.put(player, vec31); ++ if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.getAbilities().flying)) { ++ this.hitPlayers.put(entityhuman, vec3d1); + } + } + } +@@ -262,23 +310,23 @@ + + } + +- public void finalizeExplosion(boolean flag) { ++ public void finalizeExplosion(boolean spawnParticles) { + if (this.level.isClientSide) { + this.level.playLocalSound(this.x, this.y, this.z, this.explosionSound, SoundSource.BLOCKS, 4.0F, (1.0F + (this.level.random.nextFloat() - this.level.random.nextFloat()) * 0.2F) * 0.7F, false); + } + + boolean flag1 = this.interactsWithBlocks(); + +- if (flag) { +- ParticleOptions particleoptions; ++ if (spawnParticles) { ++ ParticleOptions particleparam; + + if (this.radius >= 2.0F && flag1) { +- particleoptions = this.largeExplosionParticles; ++ particleparam = this.largeExplosionParticles; + } else { +- particleoptions = this.smallExplosionParticles; ++ particleparam = this.smallExplosionParticles; + } + +- this.level.addParticle(particleoptions, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D); ++ this.level.addParticle(particleparam, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D); + } + + if (flag1) { +@@ -287,12 +335,66 @@ + + Util.shuffle(this.toBlow, this.level.random); + ObjectListIterator objectlistiterator = this.toBlow.iterator(); ++ // CraftBukkit start ++ org.bukkit.World bworld = this.level.getWorld(); ++ org.bukkit.entity.Entity explode = this.source == null ? null : this.source.getBukkitEntity(); ++ Location location = new Location(bworld, this.x, this.y, this.z); + ++ List blockList = new ObjectArrayList<>(); ++ for (int i1 = this.toBlow.size() - 1; i1 >= 0; i1--) { ++ BlockPos cpos = this.toBlow.get(i1); ++ org.bukkit.block.Block bblock = bworld.getBlockAt(cpos.getX(), cpos.getY(), cpos.getZ()); ++ if (!bblock.getType().isAir()) { ++ blockList.add(bblock); ++ } ++ } ++ ++ List bukkitBlocks; ++ ++ if (explode != null) { ++ EntityExplodeEvent event = new EntityExplodeEvent(explode, location, blockList, this.yield); ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ this.wasCanceled = event.isCancelled(); ++ bukkitBlocks = event.blockList(); ++ this.yield = event.getYield(); ++ } else { ++ BlockExplodeEvent event = new BlockExplodeEvent(location.getBlock(), blockList, this.yield); ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ this.wasCanceled = event.isCancelled(); ++ bukkitBlocks = event.blockList(); ++ this.yield = event.getYield(); ++ } ++ ++ this.toBlow.clear(); ++ ++ for (org.bukkit.block.Block bblock : bukkitBlocks) { ++ BlockPos coords = new BlockPos(bblock.getX(), bblock.getY(), bblock.getZ()); ++ toBlow.add(coords); ++ } ++ ++ if (this.wasCanceled) { ++ return; ++ } ++ // CraftBukkit end ++ objectlistiterator = this.toBlow.iterator(); ++ + while (objectlistiterator.hasNext()) { +- BlockPos blockpos = (BlockPos) objectlistiterator.next(); ++ BlockPos blockposition = (BlockPos) objectlistiterator.next(); ++ // CraftBukkit start - TNTPrimeEvent ++ IBlockData iblockdata = this.level.getBlockState(blockposition); ++ Block block = iblockdata.getBlock(); ++ if (block instanceof net.minecraft.world.level.block.TntBlock) { ++ Entity sourceEntity = source == null ? null : source; ++ BlockPos sourceBlock = sourceEntity == null ? BlockPos.containing(this.x, this.y, this.z) : null; ++ if (!CraftEventFactory.callTNTPrimeEvent(this.level, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.EXPLOSION, sourceEntity, sourceBlock)) { ++ this.level.sendBlockUpdated(blockposition, Blocks.AIR.defaultBlockState(), iblockdata, 3); // Update the block on the client ++ continue; ++ } ++ } ++ // CraftBukkit end + +- this.level.getBlockState(blockpos).onExplosionHit(this.level, blockpos, this, (itemstack, blockpos1) -> { +- addOrAppendStack(list, itemstack, blockpos1); ++ this.level.getBlockState(blockposition).onExplosionHit(this.level, blockposition, this, (itemstack, blockposition1) -> { ++ addOrAppendStack(list, itemstack, blockposition1); + }); + } + +@@ -311,17 +413,22 @@ + ObjectListIterator objectlistiterator1 = this.toBlow.iterator(); + + while (objectlistiterator1.hasNext()) { +- BlockPos blockpos1 = (BlockPos) objectlistiterator1.next(); ++ BlockPos blockposition1 = (BlockPos) objectlistiterator1.next(); + +- if (this.random.nextInt(3) == 0 && this.level.getBlockState(blockpos1).isAir() && this.level.getBlockState(blockpos1.below()).isSolidRender(this.level, blockpos1.below())) { +- this.level.setBlockAndUpdate(blockpos1, BaseFireBlock.getState(this.level, blockpos1)); ++ if (this.random.nextInt(3) == 0 && this.level.getBlockState(blockposition1).isAir() && this.level.getBlockState(blockposition1.below()).isSolidRender(this.level, blockposition1.below())) { ++ // CraftBukkit start - Ignition by explosion ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(this.level, blockposition1, this).isCancelled()) { ++ this.level.setBlockAndUpdate(blockposition1, BaseFireBlock.getState(this.level, blockposition1)); ++ } ++ // CraftBukkit end + } + } + } + + } + +- private static void addOrAppendStack(List> list, ItemStack itemstack, BlockPos blockpos) { ++ private static void addOrAppendStack(List> list, ItemStack itemstack, BlockPos blockposition) { ++ if (itemstack.isEmpty()) return; // CraftBukkit - SPIGOT-5425 + for (int i = 0; i < list.size(); ++i) { + Pair pair = (Pair) list.get(i); + ItemStack itemstack1 = (ItemStack) pair.getFirst(); +@@ -334,11 +441,11 @@ + } + } + +- list.add(Pair.of(itemstack, blockpos)); ++ list.add(Pair.of(itemstack, blockposition)); + } + + public boolean interactsWithBlocks() { +- return this.blockInteraction != Explosion.BlockInteraction.KEEP; ++ return this.blockInteraction != Explosion.Effect.KEEP; + } + + public Map getHitPlayers() { +@@ -350,22 +457,22 @@ + if (entity == null) { + return null; + } else if (entity instanceof PrimedTnt) { +- PrimedTnt primedtnt = (PrimedTnt) entity; ++ PrimedTnt entitytntprimed = (PrimedTnt) entity; + +- return primedtnt.getOwner(); ++ return entitytntprimed.getOwner(); + } else if (entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; ++ LivingEntity entityliving = (LivingEntity) entity; + +- return livingentity; ++ return entityliving; + } else { + if (entity instanceof Projectile) { +- Projectile projectile = (Projectile) entity; +- Entity entity1 = projectile.getOwner(); ++ Projectile iprojectile = (Projectile) entity; ++ Entity entity1 = iprojectile.getOwner(); + + if (entity1 instanceof LivingEntity) { +- LivingEntity livingentity1 = (LivingEntity) entity1; ++ LivingEntity entityliving1 = (LivingEntity) entity1; + +- return livingentity1; ++ return entityliving1; + } + } + +@@ -391,7 +498,7 @@ + return this.toBlow; + } + +- public Explosion.BlockInteraction getBlockInteraction() { ++ public Explosion.Effect getBlockInteraction() { + return this.blockInteraction; + } + +@@ -407,10 +514,10 @@ + return this.explosionSound; + } + +- public static enum BlockInteraction { ++ public static enum Effect { + + KEEP, DESTROY, DESTROY_WITH_DECAY, TRIGGER_BLOCK; + +- private BlockInteraction() {} ++ private Effect() {} + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/GameRules.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/GameRules.java.patch new file mode 100644 index 0000000000..ea1edeab1f --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/GameRules.java.patch @@ -0,0 +1,512 @@ +--- a/net/minecraft/world/level/GameRules.java ++++ b/net/minecraft/world/level/GameRules.java +@@ -32,8 +32,8 @@ + + public static final int DEFAULT_RANDOM_TICK_SPEED = 3; + static final Logger LOGGER = LogUtils.getLogger(); +- private static final Map, GameRules.Type> GAME_RULE_TYPES = Maps.newTreeMap(Comparator.comparing((gamerules_key) -> { +- return gamerules_key.id; ++ private static final Map, GameRules.Type> GAME_RULE_TYPES = Maps.newTreeMap(Comparator.comparing((gamerules_gamerulekey) -> { ++ return gamerules_gamerulekey.id; + })); + public static final GameRules.Key RULE_DOFIRETICK = register("doFireTick", GameRules.Category.UPDATES, GameRules.BooleanValue.create(true)); + public static final GameRules.Key RULE_MOBGRIEFING = register("mobGriefing", GameRules.Category.MOBS, GameRules.BooleanValue.create(true)); +@@ -50,14 +50,14 @@ + public static final GameRules.Key RULE_SHOWDEATHMESSAGES = register("showDeathMessages", GameRules.Category.CHAT, GameRules.BooleanValue.create(true)); + public static final GameRules.Key RULE_RANDOMTICKING = register("randomTickSpeed", GameRules.Category.UPDATES, GameRules.IntegerValue.create(3)); + public static final GameRules.Key RULE_SENDCOMMANDFEEDBACK = register("sendCommandFeedback", GameRules.Category.CHAT, GameRules.BooleanValue.create(true)); +- public static final GameRules.Key RULE_REDUCEDDEBUGINFO = register("reducedDebugInfo", GameRules.Category.MISC, GameRules.BooleanValue.create(false, (minecraftserver, gamerules_booleanvalue) -> { +- int i = gamerules_booleanvalue.get() ? 22 : 23; ++ public static final GameRules.Key RULE_REDUCEDDEBUGINFO = register("reducedDebugInfo", GameRules.Category.MISC, GameRules.BooleanValue.create(false, (minecraftserver, gamerules_gameruleboolean) -> { ++ int i = gamerules_gameruleboolean.get() ? 22 : 23; + Iterator iterator = minecraftserver.getPlayerList().getPlayers().iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- serverplayer.connection.send(new ClientboundEntityEventPacket(serverplayer, (byte) i)); ++ entityplayer.connection.send(new ClientboundEntityEventPacket(entityplayer, (byte) i)); + } + + })); +@@ -66,13 +66,13 @@ + public static final GameRules.Key RULE_DISABLE_ELYTRA_MOVEMENT_CHECK = register("disableElytraMovementCheck", GameRules.Category.PLAYER, GameRules.BooleanValue.create(false)); + public static final GameRules.Key RULE_MAX_ENTITY_CRAMMING = register("maxEntityCramming", GameRules.Category.MOBS, GameRules.IntegerValue.create(24)); + public static final GameRules.Key RULE_WEATHER_CYCLE = register("doWeatherCycle", GameRules.Category.UPDATES, GameRules.BooleanValue.create(true)); +- public static final GameRules.Key RULE_LIMITED_CRAFTING = register("doLimitedCrafting", GameRules.Category.PLAYER, GameRules.BooleanValue.create(false, (minecraftserver, gamerules_booleanvalue) -> { ++ public static final GameRules.Key RULE_LIMITED_CRAFTING = register("doLimitedCrafting", GameRules.Category.PLAYER, GameRules.BooleanValue.create(false, (minecraftserver, gamerules_gameruleboolean) -> { + Iterator iterator = minecraftserver.getPlayerList().getPlayers().iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- serverplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LIMITED_CRAFTING, gamerules_booleanvalue.get() ? 1.0F : 0.0F)); ++ entityplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LIMITED_CRAFTING, gamerules_gameruleboolean.get() ? 1.0F : 0.0F)); + } + + })); +@@ -82,13 +82,13 @@ + public static final GameRules.Key RULE_ANNOUNCE_ADVANCEMENTS = register("announceAdvancements", GameRules.Category.CHAT, GameRules.BooleanValue.create(true)); + public static final GameRules.Key RULE_DISABLE_RAIDS = register("disableRaids", GameRules.Category.MOBS, GameRules.BooleanValue.create(false)); + public static final GameRules.Key RULE_DOINSOMNIA = register("doInsomnia", GameRules.Category.SPAWNING, GameRules.BooleanValue.create(true)); +- public static final GameRules.Key RULE_DO_IMMEDIATE_RESPAWN = register("doImmediateRespawn", GameRules.Category.PLAYER, GameRules.BooleanValue.create(false, (minecraftserver, gamerules_booleanvalue) -> { ++ public static final GameRules.Key RULE_DO_IMMEDIATE_RESPAWN = register("doImmediateRespawn", GameRules.Category.PLAYER, GameRules.BooleanValue.create(false, (minecraftserver, gamerules_gameruleboolean) -> { + Iterator iterator = minecraftserver.getPlayerList().getPlayers().iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- serverplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.IMMEDIATE_RESPAWN, gamerules_booleanvalue.get() ? 1.0F : 0.0F)); ++ entityplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.IMMEDIATE_RESPAWN, gamerules_gameruleboolean.get() ? 1.0F : 0.0F)); + } + + })); +@@ -115,20 +115,20 @@ + public static final GameRules.Key RULE_ENDER_PEARLS_VANISH_ON_DEATH = register("enderPearlsVanishOnDeath", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true)); + private final Map, GameRules.Value> rules; + +- private static > GameRules.Key register(String s, GameRules.Category gamerules_category, GameRules.Type gamerules_type) { +- GameRules.Key gamerules_key = new GameRules.Key<>(s, gamerules_category); +- GameRules.Type gamerules_type1 = (GameRules.Type) GameRules.GAME_RULE_TYPES.put(gamerules_key, gamerules_type); ++ private static > GameRules.Key register(String name, GameRules.Category category, GameRules.Type type) { ++ GameRules.Key gamerules_gamerulekey = new GameRules.Key<>(name, category); ++ GameRules.Type gamerules_gameruledefinition1 = (GameRules.Type) GameRules.GAME_RULE_TYPES.put(gamerules_gamerulekey, type); + +- if (gamerules_type1 != null) { +- throw new IllegalStateException("Duplicate game rule registration for " + s); ++ if (gamerules_gameruledefinition1 != null) { ++ throw new IllegalStateException("Duplicate game rule registration for " + name); + } else { +- return gamerules_key; ++ return gamerules_gamerulekey; + } + } + +- public GameRules(DynamicLike dynamiclike) { ++ public GameRules(DynamicLike tag) { + this(); +- this.loadFromTag(dynamiclike); ++ this.loadFromTag(tag); + } + + public GameRules() { +@@ -137,29 +137,29 @@ + })); + } + +- private GameRules(Map, GameRules.Value> map) { +- this.rules = map; ++ private GameRules(Map, GameRules.Value> rules) { ++ this.rules = rules; + } + +- public > T getRule(GameRules.Key gamerules_key) { +- return (GameRules.Value) this.rules.get(gamerules_key); ++ public > T getRule(GameRules.Key key) { ++ return (T) this.rules.get(key); // CraftBukkit - decompile error + } + + public CompoundTag createTag() { +- CompoundTag compoundtag = new CompoundTag(); ++ CompoundTag nbttagcompound = new CompoundTag(); + +- this.rules.forEach((gamerules_key, gamerules_value) -> { +- compoundtag.putString(gamerules_key.id, gamerules_value.serialize()); ++ this.rules.forEach((gamerules_gamerulekey, gamerules_gamerulevalue) -> { ++ nbttagcompound.putString(gamerules_gamerulekey.id, gamerules_gamerulevalue.serialize()); + }); +- return compoundtag; ++ return nbttagcompound; + } + +- private void loadFromTag(DynamicLike dynamiclike) { +- this.rules.forEach((gamerules_key, gamerules_value) -> { +- Optional optional = dynamiclike.get(gamerules_key.id).asString().result(); ++ private void loadFromTag(DynamicLike dynamic) { ++ this.rules.forEach((gamerules_gamerulekey, gamerules_gamerulevalue) -> { ++ Optional optional = dynamic.get(gamerules_gamerulekey.id).asString().result(); // CraftBukkit - decompile error + +- Objects.requireNonNull(gamerules_value); +- optional.ifPresent(gamerules_value::deserialize); ++ Objects.requireNonNull(gamerules_gamerulevalue); ++ optional.ifPresent(gamerules_gamerulevalue::deserialize); + }); + } + +@@ -169,35 +169,35 @@ + }))); + } + +- public static void visitGameRuleTypes(GameRules.GameRuleTypeVisitor gamerules_gameruletypevisitor) { +- GameRules.GAME_RULE_TYPES.forEach((gamerules_key, gamerules_type) -> { +- callVisitorCap(gamerules_gameruletypevisitor, gamerules_key, gamerules_type); ++ public static void visitGameRuleTypes(GameRules.GameRuleTypeVisitor visitor) { ++ GameRules.GAME_RULE_TYPES.forEach((gamerules_gamerulekey, gamerules_gameruledefinition) -> { ++ callVisitorCap(visitor, gamerules_gamerulekey, gamerules_gameruledefinition); + }); + } + +- private static > void callVisitorCap(GameRules.GameRuleTypeVisitor gamerules_gameruletypevisitor, GameRules.Key gamerules_key, GameRules.Type gamerules_type) { +- gamerules_gameruletypevisitor.visit(gamerules_key, gamerules_type); +- gamerules_type.callVisitor(gamerules_gameruletypevisitor, gamerules_key); ++ private static > void callVisitorCap(GameRules.GameRuleTypeVisitor visitor, GameRules.Key key, GameRules.Type type) { ++ visitor.visit((GameRules.Key) key, (GameRules.Type) type); // CraftBukkit - decompile error ++ ((GameRules.Type) type).callVisitor(visitor, (GameRules.Key) key); // CraftBukkit - decompile error + } + +- public void assignFrom(GameRules gamerules, @Nullable MinecraftServer minecraftserver) { +- gamerules.rules.keySet().forEach((gamerules_key) -> { +- this.assignCap(gamerules_key, gamerules, minecraftserver); ++ public void assignFrom(GameRules rules, @Nullable MinecraftServer server) { ++ rules.rules.keySet().forEach((gamerules_gamerulekey) -> { ++ this.assignCap(gamerules_gamerulekey, rules, server); + }); + } + +- private > void assignCap(GameRules.Key gamerules_key, GameRules gamerules, @Nullable MinecraftServer minecraftserver) { +- T t0 = gamerules.getRule(gamerules_key); ++ private > void assignCap(GameRules.Key key, GameRules rules, @Nullable MinecraftServer server) { ++ T t0 = rules.getRule(key); + +- this.getRule(gamerules_key).setFrom(t0, minecraftserver); ++ this.getRule(key).setFrom(t0, server); + } + +- public boolean getBoolean(GameRules.Key gamerules_key) { +- return ((GameRules.BooleanValue) this.getRule(gamerules_key)).get(); ++ public boolean getBoolean(GameRules.Key key) { ++ return ((GameRules.BooleanValue) this.getRule(key)).get(); + } + +- public int getInt(GameRules.Key gamerules_key) { +- return ((GameRules.IntegerValue) this.getRule(gamerules_key)).get(); ++ public int getInt(GameRules.Key key) { ++ return ((GameRules.IntegerValue) this.getRule(key)).get(); + } + + public static final class Key> { +@@ -205,22 +205,19 @@ + final String id; + private final GameRules.Category category; + +- public Key(String s, GameRules.Category gamerules_category) { +- this.id = s; +- this.category = gamerules_category; ++ public Key(String id, GameRules.Category category) { ++ this.id = id; ++ this.category = category; + } + +- @Override + public String toString() { + return this.id; + } + +- @Override + public boolean equals(Object object) { + return this == object ? true : object instanceof GameRules.Key && ((GameRules.Key) object).id.equals(this.id); + } + +- @Override + public int hashCode() { + return this.id.hashCode(); + } +@@ -260,23 +257,23 @@ + final BiConsumer callback; + private final GameRules.VisitorCaller visitorCaller; + +- Type(Supplier> supplier, Function, T> function, BiConsumer biconsumer, GameRules.VisitorCaller gamerules_visitorcaller) { +- this.argument = supplier; +- this.constructor = function; +- this.callback = biconsumer; +- this.visitorCaller = gamerules_visitorcaller; ++ Type(Supplier> argument, Function, T> constructor, BiConsumer callback, GameRules.VisitorCaller visitorCaller) { ++ this.argument = argument; ++ this.constructor = constructor; ++ this.callback = callback; ++ this.visitorCaller = visitorCaller; + } + +- public RequiredArgumentBuilder createArgument(String s) { +- return Commands.argument(s, (ArgumentType) this.argument.get()); ++ public RequiredArgumentBuilder createArgument(String name) { ++ return Commands.argument(name, (ArgumentType) this.argument.get()); + } + + public T createRule() { +- return (GameRules.Value) this.constructor.apply(this); ++ return this.constructor.apply(this); // CraftBukkit - decompile error + } + +- public void callVisitor(GameRules.GameRuleTypeVisitor gamerules_gameruletypevisitor, GameRules.Key gamerules_key) { +- this.visitorCaller.call(gamerules_gameruletypevisitor, gamerules_key, this); ++ public void callVisitor(GameRules.GameRuleTypeVisitor visitor, GameRules.Key key) { ++ this.visitorCaller.call(visitor, key, this); + } + } + +@@ -284,29 +281,28 @@ + + protected final GameRules.Type type; + +- public Value(GameRules.Type gamerules_type) { +- this.type = gamerules_type; ++ public Value(GameRules.Type type) { ++ this.type = type; + } + + protected abstract void updateFromArgument(CommandContext context, String paramName); + +- public void setFromArgument(CommandContext commandcontext, String s) { +- this.updateFromArgument(commandcontext, s); +- this.onChanged(((CommandSourceStack) commandcontext.getSource()).getServer()); ++ public void setFromArgument(CommandContext context, String paramName) { ++ this.updateFromArgument(context, paramName); ++ this.onChanged(((CommandSourceStack) context.getSource()).getServer()); + } + +- protected void onChanged(@Nullable MinecraftServer minecraftserver) { +- if (minecraftserver != null) { +- this.type.callback.accept(minecraftserver, this.getSelf()); ++ public void onChanged(@Nullable MinecraftServer server) { ++ if (server != null) { ++ this.type.callback.accept(server, this.getSelf()); + } + + } + +- protected abstract void deserialize(String value); ++ public abstract void deserialize(String value); // PAIL - private->public + + public abstract String serialize(); + +- @Override + public String toString() { + return this.serialize(); + } +@@ -322,82 +318,75 @@ + + public interface GameRuleTypeVisitor { + +- default > void visit(GameRules.Key gamerules_key, GameRules.Type gamerules_type) {} ++ default > void visit(GameRules.Key key, GameRules.Type type) {} + +- default void visitBoolean(GameRules.Key gamerules_key, GameRules.Type gamerules_type) {} ++ default void visitBoolean(GameRules.Key key, GameRules.Type type) {} + +- default void visitInteger(GameRules.Key gamerules_key, GameRules.Type gamerules_type) {} ++ default void visitInteger(GameRules.Key key, GameRules.Type type) {} + } + + public static class BooleanValue extends GameRules.Value { + + private boolean value; + +- static GameRules.Type create(boolean flag, BiConsumer biconsumer) { +- return new GameRules.Type<>(BoolArgumentType::bool, (gamerules_type) -> { +- return new GameRules.BooleanValue(gamerules_type, flag); +- }, biconsumer, GameRules.GameRuleTypeVisitor::visitBoolean); ++ static GameRules.Type create(boolean defaultValue, BiConsumer changeListener) { ++ return new GameRules.Type<>(BoolArgumentType::bool, (gamerules_gameruledefinition) -> { ++ return new GameRules.BooleanValue(gamerules_gameruledefinition, defaultValue); ++ }, changeListener, GameRules.GameRuleTypeVisitor::visitBoolean); + } + +- static GameRules.Type create(boolean flag) { +- return create(flag, (minecraftserver, gamerules_booleanvalue) -> { ++ static GameRules.Type create(boolean defaultValue) { ++ return create(defaultValue, (minecraftserver, gamerules_gameruleboolean) -> { + }); + } + +- public BooleanValue(GameRules.Type gamerules_type, boolean flag) { +- super(gamerules_type); +- this.value = flag; ++ public BooleanValue(GameRules.Type type, boolean value) { ++ super(type); ++ this.value = value; + } + + @Override +- @Override +- protected void updateFromArgument(CommandContext commandcontext, String s) { +- this.value = BoolArgumentType.getBool(commandcontext, s); ++ protected void updateFromArgument(CommandContext context, String paramName) { ++ this.value = BoolArgumentType.getBool(context, paramName); + } + + public boolean get() { + return this.value; + } + +- public void set(boolean flag, @Nullable MinecraftServer minecraftserver) { +- this.value = flag; +- this.onChanged(minecraftserver); ++ public void set(boolean value, @Nullable MinecraftServer server) { ++ this.value = value; ++ this.onChanged(server); + } + + @Override +- @Override + public String serialize() { + return Boolean.toString(this.value); + } + + @Override +- @Override +- protected void deserialize(String s) { +- this.value = Boolean.parseBoolean(s); ++ public void deserialize(String value) { // PAIL - protected->public ++ this.value = Boolean.parseBoolean(value); + } + + @Override +- @Override + public int getCommandResult() { + return this.value ? 1 : 0; + } + + @Override +- @Override + protected GameRules.BooleanValue getSelf() { + return this; + } + + @Override +- @Override + protected GameRules.BooleanValue copy() { + return new GameRules.BooleanValue(this.type, this.value); + } + +- @Override +- public void setFrom(GameRules.BooleanValue gamerules_booleanvalue, @Nullable MinecraftServer minecraftserver) { +- this.value = gamerules_booleanvalue.value; +- this.onChanged(minecraftserver); ++ public void setFrom(GameRules.BooleanValue value, @Nullable MinecraftServer server) { ++ this.value = value.value; ++ this.onChanged(server); + } + } + +@@ -405,64 +394,61 @@ + + private int value; + +- private static GameRules.Type create(int i, BiConsumer biconsumer) { +- return new GameRules.Type<>(IntegerArgumentType::integer, (gamerules_type) -> { +- return new GameRules.IntegerValue(gamerules_type, i); +- }, biconsumer, GameRules.GameRuleTypeVisitor::visitInteger); ++ private static GameRules.Type create(int defaultValue, BiConsumer changeListener) { ++ return new GameRules.Type<>(IntegerArgumentType::integer, (gamerules_gameruledefinition) -> { ++ return new GameRules.IntegerValue(gamerules_gameruledefinition, defaultValue); ++ }, changeListener, GameRules.GameRuleTypeVisitor::visitInteger); + } + +- static GameRules.Type create(int i) { +- return create(i, (minecraftserver, gamerules_integervalue) -> { ++ static GameRules.Type create(int defaultValue) { ++ return create(defaultValue, (minecraftserver, gamerules_gameruleint) -> { + }); + } + +- public IntegerValue(GameRules.Type gamerules_type, int i) { +- super(gamerules_type); +- this.value = i; ++ public IntegerValue(GameRules.Type type, int value) { ++ super(type); ++ this.value = value; + } + + @Override +- @Override +- protected void updateFromArgument(CommandContext commandcontext, String s) { +- this.value = IntegerArgumentType.getInteger(commandcontext, s); ++ protected void updateFromArgument(CommandContext context, String paramName) { ++ this.value = IntegerArgumentType.getInteger(context, paramName); + } + + public int get() { + return this.value; + } + +- public void set(int i, @Nullable MinecraftServer minecraftserver) { +- this.value = i; +- this.onChanged(minecraftserver); ++ public void set(int value, @Nullable MinecraftServer server) { ++ this.value = value; ++ this.onChanged(server); + } + + @Override +- @Override + public String serialize() { + return Integer.toString(this.value); + } + + @Override +- @Override +- protected void deserialize(String s) { +- this.value = safeParse(s); ++ public void deserialize(String value) { // PAIL - protected->public ++ this.value = safeParse(value); + } + +- public boolean tryDeserialize(String s) { ++ public boolean tryDeserialize(String name) { + try { +- this.value = Integer.parseInt(s); ++ this.value = Integer.parseInt(name); + return true; + } catch (NumberFormatException numberformatexception) { + return false; + } + } + +- private static int safeParse(String s) { +- if (!s.isEmpty()) { ++ private static int safeParse(String strValue) { ++ if (!strValue.isEmpty()) { + try { +- return Integer.parseInt(s); ++ return Integer.parseInt(strValue); + } catch (NumberFormatException numberformatexception) { +- GameRules.LOGGER.warn("Failed to parse integer {}", s); ++ GameRules.LOGGER.warn("Failed to parse integer {}", strValue); + } + } + +@@ -470,27 +456,23 @@ + } + + @Override +- @Override + public int getCommandResult() { + return this.value; + } + + @Override +- @Override + protected GameRules.IntegerValue getSelf() { + return this; + } + + @Override +- @Override + protected GameRules.IntegerValue copy() { + return new GameRules.IntegerValue(this.type, this.value); + } + +- @Override +- public void setFrom(GameRules.IntegerValue gamerules_integervalue, @Nullable MinecraftServer minecraftserver) { +- this.value = gamerules_integervalue.value; +- this.onChanged(minecraftserver); ++ public void setFrom(GameRules.IntegerValue value, @Nullable MinecraftServer server) { ++ this.value = value.value; ++ this.onChanged(server); + } + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/Level.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/Level.java.patch new file mode 100644 index 0000000000..247952ce1c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/Level.java.patch @@ -0,0 +1,1327 @@ +--- a/net/minecraft/world/level/Level.java ++++ b/net/minecraft/world/level/Level.java +@@ -28,6 +28,7 @@ + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.FullChunkStatus; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; +@@ -42,6 +43,7 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.boss.EnderDragonPart; + import net.minecraft.world.entity.boss.enderdragon.EnderDragon; ++import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.crafting.RecipeManager; +@@ -52,13 +54,15 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.TickingBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.border.BorderChangeListener; + import net.minecraft.world.level.border.WorldBorder; + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkSource; + import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.level.dimension.DimensionType; ++import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.entity.EntityTypeTest; + import net.minecraft.world.level.entity.LevelEntityGetter; + import net.minecraft.world.level.gameevent.GameEvent; +@@ -75,6 +79,27 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.scores.Scoreboard; + ++// CraftBukkit start ++import java.util.HashMap; ++import java.util.Map; ++import net.minecraft.network.protocol.game.ClientboundSetBorderCenterPacket; ++import net.minecraft.network.protocol.game.ClientboundSetBorderLerpSizePacket; ++import net.minecraft.network.protocol.game.ClientboundSetBorderSizePacket; ++import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDelayPacket; ++import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDistancePacket; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.block.CapturedBlockState; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.craftbukkit.util.CraftSpawnCategory; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.entity.SpawnCategory; ++import org.bukkit.event.block.BlockPhysicsEvent; ++import org.bukkit.event.world.GenericGameEvent; ++// CraftBukkit end ++ + public abstract class Level implements LevelAccessor, AutoCloseable { + + public static final Codec> RESOURCE_KEY_CODEC = ResourceKey.codec(Registries.DIMENSION); +@@ -92,22 +117,22 @@ + protected final NeighborUpdater neighborUpdater; + private final List pendingBlockEntityTickers = Lists.newArrayList(); + private boolean tickingBlockEntities; +- private final Thread thread; ++ public final Thread thread; + private final boolean isDebug; + private int skyDarken; + protected int randValue = RandomSource.create().nextInt(); + protected final int addend = 1013904223; + protected float oRainLevel; +- protected float rainLevel; ++ public float rainLevel; + protected float oThunderLevel; +- protected float thunderLevel; ++ public float thunderLevel; + public final RandomSource random = RandomSource.create(); + /** @deprecated */ + @Deprecated + private final RandomSource threadSafeRandom = RandomSource.createThreadSafe(); + private final ResourceKey dimensionTypeId; + private final Holder dimensionTypeRegistration; +- protected final WritableLevelData levelData; ++ public final WritableLevelData levelData; + private final Supplier profiler; + public final boolean isClientSide; + private final WorldBorder worldBorder; +@@ -117,29 +142,63 @@ + private final DamageSources damageSources; + private long subTickCount; + +- protected Level(WritableLevelData writableleveldata, ResourceKey resourcekey, RegistryAccess registryaccess, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j) { ++ // CraftBukkit start Added the following ++ private final CraftWorld world; ++ public boolean pvpMode; ++ public boolean keepSpawnInMemory = true; ++ public org.bukkit.generator.ChunkGenerator generator; ++ ++ public boolean preventPoiUpdated = false; // CraftBukkit - SPIGOT-5710 ++ public boolean captureBlockStates = false; ++ public boolean captureTreeGeneration = false; ++ public Map capturedBlockStates = new java.util.LinkedHashMap<>(); ++ public Map capturedTileEntities = new HashMap<>(); ++ public List captureDrops; ++ public final it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap ticksPerSpawnCategory = new it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<>(); ++ public boolean populating; ++ ++ public CraftWorld getWorld() { ++ return this.world; ++ } ++ ++ public CraftServer getCraftServer() { ++ return (CraftServer) Bukkit.getServer(); ++ } ++ ++ public abstract ResourceKey getTypeKey(); ++ ++ protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env) { ++ this.generator = gen; ++ this.world = new CraftWorld((ServerLevel) this, gen, biomeProvider, env); ++ ++ // CraftBukkit Ticks things ++ for (SpawnCategory spawnCategory : SpawnCategory.values()) { ++ if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { ++ this.ticksPerSpawnCategory.put(spawnCategory, (long) this.getCraftServer().getTicksPerSpawns(spawnCategory)); ++ } ++ } ++ ++ // CraftBukkit end + this.profiler = supplier; +- this.levelData = writableleveldata; ++ this.levelData = worlddatamutable; + this.dimensionTypeRegistration = holder; + this.dimensionTypeId = (ResourceKey) holder.unwrapKey().orElseThrow(() -> { + return new IllegalArgumentException("Dimension must be registered, got " + holder); + }); +- final DimensionType dimensiontype = (DimensionType) holder.value(); ++ final DimensionType dimensionmanager = (DimensionType) holder.value(); + + this.dimension = resourcekey; + this.isClientSide = flag; +- if (dimensiontype.coordinateScale() != 1.0D) { ++ if (dimensionmanager.coordinateScale() != 1.0D) { + this.worldBorder = new WorldBorder() { + @Override +- @Override + public double getCenterX() { +- return super.getCenterX() / dimensiontype.coordinateScale(); ++ return super.getCenterX(); // CraftBukkit + } + + @Override +- @Override + public double getCenterZ() { +- return super.getCenterZ() / dimensiontype.coordinateScale(); ++ return super.getCenterZ(); // CraftBukkit + } + }; + } else { +@@ -150,189 +209,299 @@ + this.biomeManager = new BiomeManager(this, i); + this.isDebug = flag1; + this.neighborUpdater = new CollectingNeighborUpdater(this, j); +- this.registryAccess = registryaccess; +- this.damageSources = new DamageSources(registryaccess); ++ this.registryAccess = iregistrycustom; ++ this.damageSources = new DamageSources(iregistrycustom); ++ // CraftBukkit start ++ getWorldBorder().world = (ServerLevel) this; ++ // From PlayerList.setPlayerFileData ++ getWorldBorder().addListener(new BorderChangeListener() { ++ @Override ++ public void onBorderSizeSet(WorldBorder border, double size) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderSizePacket(border), border.world); ++ } ++ ++ @Override ++ public void onBorderSizeLerping(WorldBorder border, double oldSize, double d1, long newSize) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderLerpSizePacket(border), border.world); ++ } ++ ++ @Override ++ public void onBorderCenterSet(WorldBorder border, double x, double d1) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderCenterPacket(border), border.world); ++ } ++ ++ @Override ++ public void onBorderSetWarningTime(WorldBorder border, int warningTime) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderWarningDelayPacket(border), border.world); ++ } ++ ++ @Override ++ public void onBorderSetWarningBlocks(WorldBorder border, int warningBlocks) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderWarningDistancePacket(border), border.world); ++ } ++ ++ @Override ++ public void onBorderSetDamagePerBlock(WorldBorder border, double damagePerBlock) {} ++ ++ @Override ++ public void onBorderSetDamageSafeZOne(WorldBorder border, double damageSafeZone) {} ++ }); ++ // CraftBukkit end + } + + @Override +- @Override + public boolean isClientSide() { + return this.isClientSide; + } + + @Nullable + @Override +- @Override + public MinecraftServer getServer() { + return null; + } + +- public boolean isInWorldBounds(BlockPos blockpos) { +- return !this.isOutsideBuildHeight(blockpos) && isInWorldBoundsHorizontal(blockpos); ++ public boolean isInWorldBounds(BlockPos pos) { ++ return !this.isOutsideBuildHeight(pos) && isInWorldBoundsHorizontal(pos); + } + +- public static boolean isInSpawnableBounds(BlockPos blockpos) { +- return !isOutsideSpawnableHeight(blockpos.getY()) && isInWorldBoundsHorizontal(blockpos); ++ public static boolean isInSpawnableBounds(BlockPos pos) { ++ return !isOutsideSpawnableHeight(pos.getY()) && isInWorldBoundsHorizontal(pos); + } + +- private static boolean isInWorldBoundsHorizontal(BlockPos blockpos) { +- return blockpos.getX() >= -30000000 && blockpos.getZ() >= -30000000 && blockpos.getX() < 30000000 && blockpos.getZ() < 30000000; ++ private static boolean isInWorldBoundsHorizontal(BlockPos pos) { ++ return pos.getX() >= -30000000 && pos.getZ() >= -30000000 && pos.getX() < 30000000 && pos.getZ() < 30000000; + } + +- private static boolean isOutsideSpawnableHeight(int i) { +- return i < -20000000 || i >= 20000000; ++ private static boolean isOutsideSpawnableHeight(int y) { ++ return y < -20000000 || y >= 20000000; + } + +- public LevelChunk getChunkAt(BlockPos blockpos) { +- return this.getChunk(SectionPos.blockToSectionCoord(blockpos.getX()), SectionPos.blockToSectionCoord(blockpos.getZ())); ++ public LevelChunk getChunkAt(BlockPos pos) { ++ return this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())); + } + + @Override +- @Override +- public LevelChunk getChunk(int i, int j) { +- return (LevelChunk) this.getChunk(i, j, ChunkStatus.FULL); ++ public LevelChunk getChunk(int chunkX, int chunkZ) { ++ return (LevelChunk) this.getChunk(chunkX, chunkZ, ChunkStatus.FULL); + } + + @Nullable + @Override +- @Override +- public ChunkAccess getChunk(int i, int j, ChunkStatus chunkstatus, boolean flag) { +- ChunkAccess chunkaccess = this.getChunkSource().getChunk(i, j, chunkstatus, flag); ++ public ChunkAccess getChunk(int x, int z, ChunkStatus requiredStatus, boolean nonnull) { ++ ChunkAccess ichunkaccess = this.getChunkSource().getChunk(x, z, requiredStatus, nonnull); + +- if (chunkaccess == null && flag) { ++ if (ichunkaccess == null && nonnull) { + throw new IllegalStateException("Should always be able to create a chunk!"); + } else { +- return chunkaccess; ++ return ichunkaccess; + } + } + + @Override +- @Override +- public boolean setBlock(BlockPos blockpos, BlockState blockstate, int i) { +- return this.setBlock(blockpos, blockstate, i, 512); ++ public boolean setBlock(BlockPos pos, IBlockData newState, int flags) { ++ return this.setBlock(pos, newState, flags, 512); + } + + @Override +- @Override +- public boolean setBlock(BlockPos blockpos, BlockState blockstate, int i, int j) { +- if (this.isOutsideBuildHeight(blockpos)) { ++ public boolean setBlock(BlockPos pos, IBlockData state, int flags, int recursionLeft) { ++ // CraftBukkit start - tree generation ++ if (this.captureTreeGeneration) { ++ CapturedBlockState blockstate = capturedBlockStates.get(pos); ++ if (blockstate == null) { ++ blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags); ++ this.capturedBlockStates.put(pos.immutable(), blockstate); ++ } ++ blockstate.setData(state); ++ return true; ++ } ++ // CraftBukkit end ++ if (this.isOutsideBuildHeight(pos)) { + return false; + } else if (!this.isClientSide && this.isDebug()) { + return false; + } else { +- LevelChunk levelchunk = this.getChunkAt(blockpos); +- Block block = blockstate.getBlock(); +- BlockState blockstate1 = levelchunk.setBlockState(blockpos, blockstate, (i & 64) != 0); ++ LevelChunk chunk = this.getChunkAt(pos); ++ Block block = state.getBlock(); + +- if (blockstate1 == null) { ++ // CraftBukkit start - capture blockstates ++ boolean captured = false; ++ if (this.captureBlockStates && !this.capturedBlockStates.containsKey(pos)) { ++ CapturedBlockState blockstate = CapturedBlockState.getBlockState(this, pos, flags); ++ this.capturedBlockStates.put(pos.immutable(), blockstate); ++ captured = true; ++ } ++ // CraftBukkit end ++ ++ IBlockData iblockdata1 = chunk.setBlockState(pos, state, (flags & 64) != 0, (flags & 1024) == 0); // CraftBukkit custom NO_PLACE flag ++ ++ if (iblockdata1 == null) { ++ // CraftBukkit start - remove blockstate if failed (or the same) ++ if (this.captureBlockStates && captured) { ++ this.capturedBlockStates.remove(pos); ++ } ++ // CraftBukkit end + return false; + } else { +- BlockState blockstate2 = this.getBlockState(blockpos); ++ IBlockData iblockdata2 = this.getBlockState(pos); + +- if (blockstate2 == blockstate) { +- if (blockstate1 != blockstate2) { +- this.setBlocksDirty(blockpos, blockstate1, blockstate2); ++ /* ++ if (iblockdata2 == iblockdata) { ++ if (iblockdata1 != iblockdata2) { ++ this.setBlocksDirty(blockposition, iblockdata1, iblockdata2); + } + +- if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || levelchunk.getFullStatus() != null && levelchunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING))) { +- this.sendBlockUpdated(blockpos, blockstate1, blockstate, i); ++ if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk.getFullStatus() != null && chunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING))) { ++ this.sendBlockUpdated(blockposition, iblockdata1, iblockdata, i); + } + + if ((i & 1) != 0) { +- this.blockUpdated(blockpos, blockstate1.getBlock()); +- if (!this.isClientSide && blockstate.hasAnalogOutputSignal()) { +- this.updateNeighbourForOutputSignal(blockpos, block); ++ this.blockUpdated(blockposition, iblockdata1.getBlock()); ++ if (!this.isClientSide && iblockdata.hasAnalogOutputSignal()) { ++ this.updateNeighbourForOutputSignal(blockposition, block); + } + } + + if ((i & 16) == 0 && j > 0) { + int k = i & -34; + +- blockstate1.updateIndirectNeighbourShapes(this, blockpos, k, j - 1); +- blockstate.updateNeighbourShapes(this, blockpos, k, j - 1); +- blockstate.updateIndirectNeighbourShapes(this, blockpos, k, j - 1); ++ iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); ++ iblockdata.updateNeighbourShapes(this, blockposition, k, j - 1); ++ iblockdata.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); + } + +- this.onBlockStateChange(blockpos, blockstate1, blockstate2); ++ this.onBlockStateChange(blockposition, iblockdata1, iblockdata2); + } ++ */ + ++ // CraftBukkit start ++ if (!this.captureBlockStates) { // Don't notify clients or update physics while capturing blockstates ++ // Modularize client and physic updates ++ notifyAndUpdatePhysics(pos, chunk, iblockdata1, state, iblockdata2, flags, recursionLeft); ++ } ++ // CraftBukkit end ++ + return true; + } + } + } + +- public void onBlockStateChange(BlockPos blockpos, BlockState blockstate, BlockState blockstate1) {} ++ // CraftBukkit start - Split off from above in order to directly send client and physic updates ++ public void notifyAndUpdatePhysics(BlockPos blockposition, LevelChunk chunk, IBlockData oldBlock, IBlockData newBlock, IBlockData actualBlock, int i, int j) { ++ IBlockData iblockdata = newBlock; ++ IBlockData iblockdata1 = oldBlock; ++ IBlockData iblockdata2 = actualBlock; ++ if (iblockdata2 == iblockdata) { ++ if (iblockdata1 != iblockdata2) { ++ this.setBlocksDirty(blockposition, iblockdata1, iblockdata2); ++ } + ++ if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getFullStatus() != null && chunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement ++ this.sendBlockUpdated(blockposition, iblockdata1, iblockdata, i); ++ } ++ ++ if ((i & 1) != 0) { ++ this.blockUpdated(blockposition, iblockdata1.getBlock()); ++ if (!this.isClientSide && iblockdata.hasAnalogOutputSignal()) { ++ this.updateNeighbourForOutputSignal(blockposition, newBlock.getBlock()); ++ } ++ } ++ ++ if ((i & 16) == 0 && j > 0) { ++ int k = i & -34; ++ ++ // CraftBukkit start ++ iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam ++ CraftWorld world = ((ServerLevel) this).getWorld(); ++ if (world != null) { ++ BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata)); ++ this.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ iblockdata.updateNeighbourShapes(this, blockposition, k, j - 1); ++ iblockdata.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); ++ } ++ ++ // CraftBukkit start - SPIGOT-5710 ++ if (!preventPoiUpdated) { ++ this.onBlockStateChange(blockposition, iblockdata1, iblockdata2); ++ } ++ // CraftBukkit end ++ } ++ } ++ // CraftBukkit end ++ ++ public void onBlockStateChange(BlockPos pos, IBlockData blockState, IBlockData newState) {} ++ + @Override +- @Override +- public boolean removeBlock(BlockPos blockpos, boolean flag) { +- FluidState fluidstate = this.getFluidState(blockpos); ++ public boolean removeBlock(BlockPos pos, boolean isMoving) { ++ FluidState fluid = this.getFluidState(pos); + +- return this.setBlock(blockpos, fluidstate.createLegacyBlock(), 3 | (flag ? 64 : 0)); ++ return this.setBlock(pos, fluid.createLegacyBlock(), 3 | (isMoving ? 64 : 0)); + } + + @Override +- @Override +- public boolean destroyBlock(BlockPos blockpos, boolean flag, @Nullable Entity entity, int i) { +- BlockState blockstate = this.getBlockState(blockpos); ++ public boolean destroyBlock(BlockPos pos, boolean dropBlock, @Nullable Entity entity, int recursionLeft) { ++ IBlockData iblockdata = this.getBlockState(pos); + +- if (blockstate.isAir()) { ++ if (iblockdata.isAir()) { + return false; + } else { +- FluidState fluidstate = this.getFluidState(blockpos); ++ FluidState fluid = this.getFluidState(pos); + +- if (!(blockstate.getBlock() instanceof BaseFireBlock)) { +- this.levelEvent(2001, blockpos, Block.getId(blockstate)); ++ if (!(iblockdata.getBlock() instanceof BaseFireBlock)) { ++ this.levelEvent(2001, pos, Block.getId(iblockdata)); + } + +- if (flag) { +- BlockEntity blockentity = blockstate.hasBlockEntity() ? this.getBlockEntity(blockpos) : null; ++ if (dropBlock) { ++ BlockEntity tileentity = iblockdata.hasBlockEntity() ? this.getBlockEntity(pos) : null; + +- Block.dropResources(blockstate, this, blockpos, blockentity, entity, ItemStack.EMPTY); ++ Block.dropResources(iblockdata, this, pos, tileentity, entity, ItemStack.EMPTY); + } + +- boolean flag1 = this.setBlock(blockpos, fluidstate.createLegacyBlock(), 3, i); ++ boolean flag1 = this.setBlock(pos, fluid.createLegacyBlock(), 3, recursionLeft); + + if (flag1) { +- this.gameEvent(GameEvent.BLOCK_DESTROY, blockpos, GameEvent.Context.of(entity, blockstate)); ++ this.gameEvent(GameEvent.BLOCK_DESTROY, pos, GameEvent.Context.of(entity, iblockdata)); + } + + return flag1; + } + } + +- public void addDestroyBlockEffect(BlockPos blockpos, BlockState blockstate) {} ++ public void addDestroyBlockEffect(BlockPos pos, IBlockData state) {} + +- public boolean setBlockAndUpdate(BlockPos blockpos, BlockState blockstate) { +- return this.setBlock(blockpos, blockstate, 3); ++ public boolean setBlockAndUpdate(BlockPos pos, IBlockData state) { ++ return this.setBlock(pos, state, 3); + } + +- public abstract void sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags); ++ public abstract void sendBlockUpdated(BlockPos pos, IBlockData oldState, IBlockData newState, int flags); + +- public void setBlocksDirty(BlockPos blockpos, BlockState blockstate, BlockState blockstate1) {} ++ public void setBlocksDirty(BlockPos blockPos, IBlockData oldState, IBlockData newState) {} + +- public void updateNeighborsAt(BlockPos blockpos, Block block) {} ++ public void updateNeighborsAt(BlockPos pos, Block block) {} + +- public void updateNeighborsAtExceptFromFacing(BlockPos blockpos, Block block, Direction direction) {} ++ public void updateNeighborsAtExceptFromFacing(BlockPos pos, Block blockType, Direction skipSide) {} + +- public void neighborChanged(BlockPos blockpos, Block block, BlockPos blockpos1) {} ++ public void neighborChanged(BlockPos pos, Block block, BlockPos fromPos) {} + +- public void neighborChanged(BlockState blockstate, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) {} ++ public void neighborChanged(IBlockData state, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) {} + + @Override +- @Override +- public void neighborShapeChanged(Direction direction, BlockState blockstate, BlockPos blockpos, BlockPos blockpos1, int i, int j) { +- this.neighborUpdater.shapeUpdate(direction, blockstate, blockpos, blockpos1, i, j); ++ public void neighborShapeChanged(Direction direction, IBlockData queried, BlockPos pos, BlockPos offsetPos, int flags, int recursionLevel) { ++ this.neighborUpdater.shapeUpdate(direction, queried, pos, offsetPos, flags, recursionLevel); + } + + @Override +- @Override +- public int getHeight(Heightmap.Types heightmap_types, int i, int j) { ++ public int getHeight(Heightmap.Types heightmapType, int x, int z) { + int k; + +- if (i >= -30000000 && j >= -30000000 && i < 30000000 && j < 30000000) { +- if (this.hasChunk(SectionPos.blockToSectionCoord(i), SectionPos.blockToSectionCoord(j))) { +- k = this.getChunk(SectionPos.blockToSectionCoord(i), SectionPos.blockToSectionCoord(j)).getHeight(heightmap_types, i & 15, j & 15) + 1; ++ if (x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000) { ++ if (this.hasChunk(SectionPos.blockToSectionCoord(x), SectionPos.blockToSectionCoord(z))) { ++ k = this.getChunk(SectionPos.blockToSectionCoord(x), SectionPos.blockToSectionCoord(z)).getHeight(heightmapType, x & 15, z & 15) + 1; + } else { + k = this.getMinBuildHeight(); + } +@@ -344,32 +513,37 @@ + } + + @Override +- @Override + public LevelLightEngine getLightEngine() { + return this.getChunkSource().getLightEngine(); + } + + @Override +- @Override +- public BlockState getBlockState(BlockPos blockpos) { +- if (this.isOutsideBuildHeight(blockpos)) { ++ public IBlockData getBlockState(BlockPos pos) { ++ // CraftBukkit start - tree generation ++ if (captureTreeGeneration) { ++ CapturedBlockState previous = capturedBlockStates.get(pos); ++ if (previous != null) { ++ return previous.getHandle(); ++ } ++ } ++ // CraftBukkit end ++ if (this.isOutsideBuildHeight(pos)) { + return Blocks.VOID_AIR.defaultBlockState(); + } else { +- LevelChunk levelchunk = this.getChunk(SectionPos.blockToSectionCoord(blockpos.getX()), SectionPos.blockToSectionCoord(blockpos.getZ())); ++ LevelChunk chunk = this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())); + +- return levelchunk.getBlockState(blockpos); ++ return chunk.getBlockState(pos); + } + } + + @Override +- @Override +- public FluidState getFluidState(BlockPos blockpos) { +- if (this.isOutsideBuildHeight(blockpos)) { ++ public FluidState getFluidState(BlockPos pos) { ++ if (this.isOutsideBuildHeight(pos)) { + return Fluids.EMPTY.defaultFluidState(); + } else { +- LevelChunk levelchunk = this.getChunkAt(blockpos); ++ LevelChunk chunk = this.getChunkAt(pos); + +- return levelchunk.getFluidState(blockpos); ++ return chunk.getFluidState(pos); + } + } + +@@ -381,78 +555,76 @@ + return !this.dimensionType().hasFixedTime() && !this.isDay(); + } + +- public void playSound(@Nullable Entity entity, BlockPos blockpos, SoundEvent soundevent, SoundSource soundsource, float f, float f1) { +- Player player; ++ public void playSound(@Nullable Entity entity, BlockPos pos, SoundEvent sound, SoundSource category, float volume, float pitch) { ++ Player entityhuman; + + if (entity instanceof Player) { +- Player player1 = (Player) entity; ++ Player entityhuman1 = (Player) entity; + +- player = player1; ++ entityhuman = entityhuman1; + } else { +- player = null; ++ entityhuman = null; + } + +- this.playSound(player, blockpos, soundevent, soundsource, f, f1); ++ this.playSound(entityhuman, pos, sound, category, volume, pitch); + } + + @Override +- @Override +- public void playSound(@Nullable Player player, BlockPos blockpos, SoundEvent soundevent, SoundSource soundsource, float f, float f1) { +- this.playSound(player, (double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D, soundevent, soundsource, f, f1); ++ public void playSound(@Nullable Player player, BlockPos pos, SoundEvent sound, SoundSource category, float volume, float pitch) { ++ this.playSound(player, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, sound, category, volume, pitch); + } + +- public abstract void playSeededSound(@Nullable Player player, double x, double d, double y, Holder holder, SoundSource z, float f, float sound, long source); ++ public abstract void playSeededSound(@Nullable Player player, double x, double d1, double y, Holder holder, SoundSource z, float f, float sound, long source); + +- public void playSeededSound(@Nullable Player player, double d0, double d1, double d2, SoundEvent soundevent, SoundSource soundsource, float f, float f1, long i) { +- this.playSeededSound(player, d0, d1, d2, BuiltInRegistries.SOUND_EVENT.wrapAsHolder(soundevent), soundsource, f, f1, i); ++ public void playSeededSound(@Nullable Player player, double x, double d1, double y, SoundEvent soundeffect, SoundSource z, float f, float sound, long source) { ++ this.playSeededSound(player, x, d1, y, BuiltInRegistries.SOUND_EVENT.wrapAsHolder(soundeffect), z, f, sound, source); + } + + public abstract void playSeededSound(@Nullable Player player, Entity entity, Holder sound, SoundSource category, float volume, float pitch, long seed); + +- public void playSound(@Nullable Player player, double d0, double d1, double d2, SoundEvent soundevent, SoundSource soundsource) { +- this.playSound(player, d0, d1, d2, soundevent, soundsource, 1.0F, 1.0F); ++ public void playSound(@Nullable Player entityhuman, double d0, double d1, double d2, SoundEvent soundeffect, SoundSource soundcategory) { ++ this.playSound(entityhuman, d0, d1, d2, soundeffect, soundcategory, 1.0F, 1.0F); + } + +- public void playSound(@Nullable Player player, double d0, double d1, double d2, SoundEvent soundevent, SoundSource soundsource, float f, float f1) { +- this.playSeededSound(player, d0, d1, d2, soundevent, soundsource, f, f1, this.threadSafeRandom.nextLong()); ++ public void playSound(@Nullable Player player, double x, double d1, double y, SoundEvent soundeffect, SoundSource z, float f, float sound) { ++ this.playSeededSound(player, x, d1, y, soundeffect, z, f, sound, this.threadSafeRandom.nextLong()); + } + +- public void playSound(@Nullable Player player, Entity entity, SoundEvent soundevent, SoundSource soundsource, float f, float f1) { +- this.playSeededSound(player, entity, BuiltInRegistries.SOUND_EVENT.wrapAsHolder(soundevent), soundsource, f, f1, this.threadSafeRandom.nextLong()); ++ public void playSound(@Nullable Player player, Entity entity, SoundEvent event, SoundSource category, float volume, float pitch) { ++ this.playSeededSound(player, entity, BuiltInRegistries.SOUND_EVENT.wrapAsHolder(event), category, volume, pitch, this.threadSafeRandom.nextLong()); + } + +- public void playLocalSound(BlockPos blockpos, SoundEvent soundevent, SoundSource soundsource, float f, float f1, boolean flag) { +- this.playLocalSound((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D, soundevent, soundsource, f, f1, flag); ++ public void playLocalSound(BlockPos pos, SoundEvent sound, SoundSource category, float volume, float pitch, boolean distanceDelay) { ++ this.playLocalSound((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, sound, category, volume, pitch, distanceDelay); + } + +- public void playLocalSound(Entity entity, SoundEvent soundevent, SoundSource soundsource, float f, float f1) {} ++ public void playLocalSound(Entity entity, SoundEvent soundeffect, SoundSource soundcategory, float f, float f1) {} + +- public void playLocalSound(double d0, double d1, double d2, SoundEvent soundevent, SoundSource soundsource, float f, float f1, boolean flag) {} ++ public void playLocalSound(double x, double d1, double y, SoundEvent soundeffect, SoundSource z, float f, float sound, boolean category) {} + + @Override +- @Override +- public void addParticle(ParticleOptions particleoptions, double d0, double d1, double d2, double d3, double d4, double d5) {} ++ public void addParticle(ParticleOptions particleData, double x, double d1, double y, double d3, double z, double d5) {} + +- public void addParticle(ParticleOptions particleoptions, boolean flag, double d0, double d1, double d2, double d3, double d4, double d5) {} ++ public void addParticle(ParticleOptions particleData, boolean forceAlwaysRender, double x, double d1, double y, double d3, double z, double d5) {} + +- public void addAlwaysVisibleParticle(ParticleOptions particleoptions, double d0, double d1, double d2, double d3, double d4, double d5) {} ++ public void addAlwaysVisibleParticle(ParticleOptions particleData, double x, double d1, double y, double d3, double z, double d5) {} + +- public void addAlwaysVisibleParticle(ParticleOptions particleoptions, boolean flag, double d0, double d1, double d2, double d3, double d4, double d5) {} ++ public void addAlwaysVisibleParticle(ParticleOptions particleData, boolean ignoreRange, double x, double d1, double y, double d3, double z, double d5) {} + +- public float getSunAngle(float f) { +- float f1 = this.getTimeOfDay(f); ++ public float getSunAngle(float partialTicks) { ++ float f1 = this.getTimeOfDay(partialTicks); + + return f1 * 6.2831855F; + } + +- public void addBlockEntityTicker(TickingBlockEntity tickingblockentity) { +- (this.tickingBlockEntities ? this.pendingBlockEntityTickers : this.blockEntityTickers).add(tickingblockentity); ++ public void addBlockEntityTicker(TickingBlockEntity ticker) { ++ (this.tickingBlockEntities ? this.pendingBlockEntityTickers : this.blockEntityTickers).add(ticker); + } + + protected void tickBlockEntities() { +- ProfilerFiller profilerfiller = this.getProfiler(); ++ ProfilerFiller gameprofilerfiller = this.getProfiler(); + +- profilerfiller.push("blockEntities"); ++ gameprofilerfiller.push("blockEntities"); + this.tickingBlockEntities = true; + if (!this.pendingBlockEntityTickers.isEmpty()) { + this.blockEntityTickers.addAll(this.pendingBlockEntityTickers); +@@ -473,17 +645,17 @@ + } + + this.tickingBlockEntities = false; +- profilerfiller.pop(); ++ gameprofilerfiller.pop(); + } + +- public void guardEntityTick(Consumer consumer, T t0) { ++ public void guardEntityTick(Consumer consumerEntity, T entity) { + try { +- consumer.accept(t0); ++ consumerEntity.accept(entity); + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking entity"); +- CrashReportCategory crashreportcategory = crashreport.addCategory("Entity being ticked"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being ticked"); + +- t0.fillCrashReportCategory(crashreportcategory); ++ entity.fillCrashReportCategory(crashreportsystemdetails); + throw new ReportedException(crashreport); + } + } +@@ -492,108 +664,123 @@ + return true; + } + +- public boolean shouldTickBlocksAt(long i) { ++ public boolean shouldTickBlocksAt(long chunkPos) { + return true; + } + +- public boolean shouldTickBlocksAt(BlockPos blockpos) { +- return this.shouldTickBlocksAt(ChunkPos.asLong(blockpos)); ++ public boolean shouldTickBlocksAt(BlockPos pos) { ++ return this.shouldTickBlocksAt(ChunkPos.asLong(pos)); + } + +- public Explosion explode(@Nullable Entity entity, double d0, double d1, double d2, float f, Level.ExplosionInteraction level_explosioninteraction) { +- return this.explode(entity, Explosion.getDefaultDamageSource(this, entity), (ExplosionDamageCalculator) null, d0, d1, d2, f, false, level_explosioninteraction, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); ++ public Explosion explode(@Nullable Entity source, double x, double d1, double y, float f, Level.a z) { ++ return this.explode(source, Explosion.getDefaultDamageSource(this, source), (ExplosionDamageCalculator) null, x, d1, y, f, false, z, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); + } + +- public Explosion explode(@Nullable Entity entity, double d0, double d1, double d2, float f, boolean flag, Level.ExplosionInteraction level_explosioninteraction) { +- return this.explode(entity, Explosion.getDefaultDamageSource(this, entity), (ExplosionDamageCalculator) null, d0, d1, d2, f, flag, level_explosioninteraction, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); ++ public Explosion explode(@Nullable Entity source, double x, double d1, double y, float f, boolean z, Level.a world_a) { ++ return this.explode(source, Explosion.getDefaultDamageSource(this, source), (ExplosionDamageCalculator) null, x, d1, y, f, z, world_a, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); + } + +- public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, Vec3 vec3, float f, boolean flag, Level.ExplosionInteraction level_explosioninteraction) { +- return this.explode(entity, damagesource, explosiondamagecalculator, vec3.x(), vec3.y(), vec3.z(), f, flag, level_explosioninteraction, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); ++ public Explosion explode(@Nullable Entity source, @Nullable DamageSource damageSource, @Nullable ExplosionDamageCalculator damageCalculator, Vec3 pos, float radius, boolean fire, Level.a explosionInteraction) { ++ return this.explode(source, damageSource, damageCalculator, pos.x(), pos.y(), pos.z(), radius, fire, explosionInteraction, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); + } + +- public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.ExplosionInteraction level_explosioninteraction) { +- return this.explode(entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, level_explosioninteraction, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); ++ public Explosion explode(@Nullable Entity source, @Nullable DamageSource damageSource, @Nullable ExplosionDamageCalculator damageCalculator, double x, double d1, double y, float f, boolean z, Level.a world_a) { ++ return this.explode(source, damageSource, damageCalculator, x, d1, y, f, z, world_a, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); + } + +- public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.ExplosionInteraction level_explosioninteraction, ParticleOptions particleoptions, ParticleOptions particleoptions1, SoundEvent soundevent) { +- return this.explode(entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, level_explosioninteraction, true, particleoptions, particleoptions1, soundevent); ++ public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.a world_a, ParticleOptions particleparam, ParticleOptions particleparam1, SoundEvent soundeffect) { ++ return this.explode(entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, world_a, true, particleparam, particleparam1, soundeffect); + } + +- public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.ExplosionInteraction level_explosioninteraction, boolean flag1, ParticleOptions particleoptions, ParticleOptions particleoptions1, SoundEvent soundevent) { +- Explosion.BlockInteraction explosion_blockinteraction; ++ public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.a world_a, boolean flag1, ParticleOptions particleparam, ParticleOptions particleparam1, SoundEvent soundeffect) { ++ Explosion.Effect explosion_effect; + +- switch (level_explosioninteraction) { ++ switch (world_a) { + case NONE: +- explosion_blockinteraction = Explosion.BlockInteraction.KEEP; ++ explosion_effect = Explosion.Effect.KEEP; + break; + case BLOCK: +- explosion_blockinteraction = this.getDestroyType(GameRules.RULE_BLOCK_EXPLOSION_DROP_DECAY); ++ explosion_effect = this.getDestroyType(GameRules.RULE_BLOCK_EXPLOSION_DROP_DECAY); + break; + case MOB: +- explosion_blockinteraction = this.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? this.getDestroyType(GameRules.RULE_MOB_EXPLOSION_DROP_DECAY) : Explosion.BlockInteraction.KEEP; ++ explosion_effect = this.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? this.getDestroyType(GameRules.RULE_MOB_EXPLOSION_DROP_DECAY) : Explosion.Effect.KEEP; + break; + case TNT: +- explosion_blockinteraction = this.getDestroyType(GameRules.RULE_TNT_EXPLOSION_DROP_DECAY); ++ explosion_effect = this.getDestroyType(GameRules.RULE_TNT_EXPLOSION_DROP_DECAY); + break; + case BLOW: +- explosion_blockinteraction = Explosion.BlockInteraction.TRIGGER_BLOCK; ++ explosion_effect = Explosion.Effect.TRIGGER_BLOCK; + break; + default: + throw new IncompatibleClassChangeError(); + } + +- Explosion.BlockInteraction explosion_blockinteraction1 = explosion_blockinteraction; +- Explosion explosion = new Explosion(this, entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, explosion_blockinteraction1, particleoptions, particleoptions1, soundevent); ++ Explosion.Effect explosion_effect1 = explosion_effect; ++ Explosion explosion = new Explosion(this, entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, explosion_effect1, particleparam, particleparam1, soundeffect); + + explosion.explode(); + explosion.finalizeExplosion(flag1); + return explosion; + } + +- private Explosion.BlockInteraction getDestroyType(GameRules.Key gamerules_key) { +- return this.getGameRules().getBoolean(gamerules_key) ? Explosion.BlockInteraction.DESTROY_WITH_DECAY : Explosion.BlockInteraction.DESTROY; ++ private Explosion.Effect getDestroyType(GameRules.Key gameRule) { ++ return this.getGameRules().getBoolean(gameRule) ? Explosion.Effect.DESTROY_WITH_DECAY : Explosion.Effect.DESTROY; + } + + public abstract String gatherChunkSourceStats(); + + @Nullable + @Override +- @Override +- public BlockEntity getBlockEntity(BlockPos blockpos) { +- return this.isOutsideBuildHeight(blockpos) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(blockpos).getBlockEntity(blockpos, LevelChunk.EntityCreationType.IMMEDIATE)); ++ public BlockEntity getBlockEntity(BlockPos pos) { ++ // CraftBukkit start ++ return getBlockEntity(pos, true); + } + +- public void setBlockEntity(BlockEntity blockentity) { +- BlockPos blockpos = blockentity.getBlockPos(); ++ @Nullable ++ public BlockEntity getBlockEntity(BlockPos blockposition, boolean validate) { ++ if (capturedTileEntities.containsKey(blockposition)) { ++ return capturedTileEntities.get(blockposition); ++ } ++ // CraftBukkit end ++ return this.isOutsideBuildHeight(blockposition) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(blockposition).getBlockEntity(blockposition, LevelChunk.EnumTileEntityState.IMMEDIATE)); ++ } + +- if (!this.isOutsideBuildHeight(blockpos)) { +- this.getChunkAt(blockpos).addAndRegisterBlockEntity(blockentity); ++ public void setBlockEntity(BlockEntity blockEntity) { ++ BlockPos blockposition = blockEntity.getBlockPos(); ++ ++ if (!this.isOutsideBuildHeight(blockposition)) { ++ // CraftBukkit start ++ if (captureBlockStates) { ++ capturedTileEntities.put(blockposition.immutable(), blockEntity); ++ return; ++ } ++ // CraftBukkit end ++ this.getChunkAt(blockposition).addAndRegisterBlockEntity(blockEntity); + } + } + +- public void removeBlockEntity(BlockPos blockpos) { +- if (!this.isOutsideBuildHeight(blockpos)) { +- this.getChunkAt(blockpos).removeBlockEntity(blockpos); ++ public void removeBlockEntity(BlockPos pos) { ++ if (!this.isOutsideBuildHeight(pos)) { ++ this.getChunkAt(pos).removeBlockEntity(pos); + } + } + +- public boolean isLoaded(BlockPos blockpos) { +- return this.isOutsideBuildHeight(blockpos) ? false : this.getChunkSource().hasChunk(SectionPos.blockToSectionCoord(blockpos.getX()), SectionPos.blockToSectionCoord(blockpos.getZ())); ++ public boolean isLoaded(BlockPos pos) { ++ return this.isOutsideBuildHeight(pos) ? false : this.getChunkSource().hasChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())); + } + +- public boolean loadedAndEntityCanStandOnFace(BlockPos blockpos, Entity entity, Direction direction) { +- if (this.isOutsideBuildHeight(blockpos)) { ++ public boolean loadedAndEntityCanStandOnFace(BlockPos pos, Entity entity, Direction direction) { ++ if (this.isOutsideBuildHeight(pos)) { + return false; + } else { +- ChunkAccess chunkaccess = this.getChunk(SectionPos.blockToSectionCoord(blockpos.getX()), SectionPos.blockToSectionCoord(blockpos.getZ()), ChunkStatus.FULL, false); ++ ChunkAccess ichunkaccess = this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()), ChunkStatus.FULL, false); + +- return chunkaccess == null ? false : chunkaccess.getBlockState(blockpos).entityCanStandOnFace(this, blockpos, entity, direction); ++ return ichunkaccess == null ? false : ichunkaccess.getBlockState(pos).entityCanStandOnFace(this, pos, entity, direction); + } + } + +- public boolean loadedAndEntityCanStandOn(BlockPos blockpos, Entity entity) { +- return this.loadedAndEntityCanStandOnFace(blockpos, entity, Direction.UP); ++ public boolean loadedAndEntityCanStandOn(BlockPos pos, Entity entity) { ++ return this.loadedAndEntityCanStandOnFace(pos, entity, Direction.UP); + } + + public void updateSkyBrightness() { +@@ -604,18 +791,18 @@ + this.skyDarken = (int) ((1.0D - d2 * d0 * d1) * 11.0D); + } + +- public void setSpawnSettings(boolean flag, boolean flag1) { +- this.getChunkSource().setSpawnSettings(flag, flag1); ++ public void setSpawnSettings(boolean hostile, boolean peaceful) { ++ this.getChunkSource().setSpawnSettings(hostile, peaceful); + } + + public BlockPos getSharedSpawnPos() { +- BlockPos blockpos = new BlockPos(this.levelData.getXSpawn(), this.levelData.getYSpawn(), this.levelData.getZSpawn()); ++ BlockPos blockposition = new BlockPos(this.levelData.getXSpawn(), this.levelData.getYSpawn(), this.levelData.getZSpawn()); + +- if (!this.getWorldBorder().isWithinBounds(blockpos)) { +- blockpos = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, BlockPos.containing(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); ++ if (!this.getWorldBorder().isWithinBounds(blockposition)) { ++ blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, BlockPos.containing(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); + } + +- return blockpos; ++ return blockposition; + } + + public float getSharedSpawnAngle() { +@@ -632,38 +819,35 @@ + + } + +- @Override + public void close() throws IOException { + this.getChunkSource().close(); + } + + @Nullable + @Override +- @Override +- public BlockGetter getChunkForCollisions(int i, int j) { +- return this.getChunk(i, j, ChunkStatus.FULL, false); ++ public BlockGetter getChunkForCollisions(int chunkX, int chunkZ) { ++ return this.getChunk(chunkX, chunkZ, ChunkStatus.FULL, false); + } + + @Override +- @Override +- public List getEntities(@Nullable Entity entity, AABB aabb, Predicate predicate) { ++ public List getEntities(@Nullable Entity entity, AABB boundingBox, Predicate predicate) { + this.getProfiler().incrementCounter("getEntities"); + List list = Lists.newArrayList(); + +- this.getEntities().get(aabb, (entity1) -> { ++ this.getEntities().get(boundingBox, (entity1) -> { + if (entity1 != entity && predicate.test(entity1)) { + list.add(entity1); + } + + if (entity1 instanceof EnderDragon) { +- EnderDragonPart[] aenderdragonpart = ((EnderDragon) entity1).getSubEntities(); +- int i = aenderdragonpart.length; ++ EnderDragonPart[] aentitycomplexpart = ((EnderDragon) entity1).getSubEntities(); ++ int i = aentitycomplexpart.length; + + for (int j = 0; j < i; ++j) { +- EnderDragonPart enderdragonpart = aenderdragonpart[j]; ++ EnderDragonPart entitycomplexpart = aentitycomplexpart[j]; + +- if (entity1 != entity && predicate.test(enderdragonpart)) { +- list.add(enderdragonpart); ++ if (entity1 != entity && predicate.test(entitycomplexpart)) { ++ list.add(entitycomplexpart); + } + } + } +@@ -673,62 +857,60 @@ + } + + @Override +- @Override +- public List getEntities(EntityTypeTest entitytypetest, AABB aabb, Predicate predicate) { ++ public List getEntities(EntityTypeTest entityTypeTest, AABB bounds, Predicate predicate) { + List list = Lists.newArrayList(); + +- this.getEntities(entitytypetest, aabb, predicate, list); ++ this.getEntities(entityTypeTest, bounds, predicate, list); + return list; + } + +- public void getEntities(EntityTypeTest entitytypetest, AABB aabb, Predicate predicate, List list) { +- this.getEntities(entitytypetest, aabb, predicate, list, Integer.MAX_VALUE); ++ public void getEntities(EntityTypeTest entityTypeTest, AABB bounds, Predicate predicate, List output) { ++ this.getEntities(entityTypeTest, bounds, predicate, output, Integer.MAX_VALUE); + } + +- public void getEntities(EntityTypeTest entitytypetest, AABB aabb, Predicate predicate, List list, int i) { ++ public void getEntities(EntityTypeTest entityTypeTest, AABB bounds, Predicate predicate, List output, int maxResults) { + this.getProfiler().incrementCounter("getEntities"); +- this.getEntities().get(entitytypetest, aabb, (entity) -> { ++ this.getEntities().get(entityTypeTest, bounds, (entity) -> { + if (predicate.test(entity)) { +- list.add(entity); +- if (list.size() >= i) { +- return AbortableIterationConsumer.Continuation.ABORT; ++ output.add(entity); ++ if (output.size() >= maxResults) { ++ return AbortableIterationConsumer.a.ABORT; + } + } + + if (entity instanceof EnderDragon) { +- EnderDragon enderdragon = (EnderDragon) entity; +- EnderDragonPart[] aenderdragonpart = enderdragon.getSubEntities(); +- int j = aenderdragonpart.length; ++ EnderDragon entityenderdragon = (EnderDragon) entity; ++ EnderDragonPart[] aentitycomplexpart = entityenderdragon.getSubEntities(); ++ int j = aentitycomplexpart.length; + + for (int k = 0; k < j; ++k) { +- EnderDragonPart enderdragonpart = aenderdragonpart[k]; +- T t0 = (Entity) entitytypetest.tryCast(enderdragonpart); ++ EnderDragonPart entitycomplexpart = aentitycomplexpart[k]; ++ T t0 = entityTypeTest.tryCast(entitycomplexpart); // CraftBukkit - decompile error + + if (t0 != null && predicate.test(t0)) { +- list.add(t0); +- if (list.size() >= i) { +- return AbortableIterationConsumer.Continuation.ABORT; ++ output.add(t0); ++ if (output.size() >= maxResults) { ++ return AbortableIterationConsumer.a.ABORT; + } + } + } + } + +- return AbortableIterationConsumer.Continuation.CONTINUE; ++ return AbortableIterationConsumer.a.CONTINUE; + }); + } + + @Nullable + public abstract Entity getEntity(int id); + +- public void blockEntityChanged(BlockPos blockpos) { +- if (this.hasChunkAt(blockpos)) { +- this.getChunkAt(blockpos).setUnsaved(true); ++ public void blockEntityChanged(BlockPos pos) { ++ if (this.hasChunkAt(pos)) { ++ this.getChunkAt(pos).setUnsaved(true); + } + + } + + @Override +- @Override + public int getSeaLevel() { + return 63; + } +@@ -743,20 +925,19 @@ + return this.levelData.getDayTime(); + } + +- public boolean mayInteract(Player player, BlockPos blockpos) { ++ public boolean mayInteract(Player player, BlockPos pos) { + return true; + } + +- public void broadcastEntityEvent(Entity entity, byte b0) {} ++ public void broadcastEntityEvent(Entity entity, byte state) {} + +- public void broadcastDamageEvent(Entity entity, DamageSource damagesource) {} ++ public void broadcastDamageEvent(Entity entity, DamageSource damageSource) {} + +- public void blockEvent(BlockPos blockpos, Block block, int i, int j) { +- this.getBlockState(blockpos).triggerEvent(this, blockpos, i, j); ++ public void blockEvent(BlockPos pos, Block block, int eventID, int eventParam) { ++ this.getBlockState(pos).triggerEvent(this, pos, eventID, eventParam); + } + + @Override +- @Override + public LevelData getLevelData() { + return this.levelData; + } +@@ -767,23 +948,23 @@ + + public abstract TickRateManager tickRateManager(); + +- public float getThunderLevel(float f) { +- return Mth.lerp(f, this.oThunderLevel, this.thunderLevel) * this.getRainLevel(f); ++ public float getThunderLevel(float delta) { ++ return Mth.lerp(delta, this.oThunderLevel, this.thunderLevel) * this.getRainLevel(delta); + } + +- public void setThunderLevel(float f) { +- float f1 = Mth.clamp(f, 0.0F, 1.0F); ++ public void setThunderLevel(float strength) { ++ float f1 = Mth.clamp(strength, 0.0F, 1.0F); + + this.oThunderLevel = f1; + this.thunderLevel = f1; + } + +- public float getRainLevel(float f) { +- return Mth.lerp(f, this.oRainLevel, this.rainLevel); ++ public float getRainLevel(float delta) { ++ return Mth.lerp(delta, this.oRainLevel, this.rainLevel); + } + +- public void setRainLevel(float f) { +- float f1 = Mth.clamp(f, 0.0F, 1.0F); ++ public void setRainLevel(float strength) { ++ float f1 = Mth.clamp(strength, 0.0F, 1.0F); + + this.oRainLevel = f1; + this.rainLevel = f1; +@@ -797,17 +978,17 @@ + return (double) this.getRainLevel(1.0F) > 0.2D; + } + +- public boolean isRainingAt(BlockPos blockpos) { ++ public boolean isRainingAt(BlockPos pos) { + if (!this.isRaining()) { + return false; +- } else if (!this.canSeeSky(blockpos)) { ++ } else if (!this.canSeeSky(pos)) { + return false; +- } else if (this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, blockpos).getY() > blockpos.getY()) { ++ } else if (this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, pos).getY() > pos.getY()) { + return false; + } else { +- Biome biome = (Biome) this.getBiome(blockpos).value(); ++ Biome biomebase = (Biome) this.getBiome(pos).value(); + +- return biome.getPrecipitationAt(blockpos) == Biome.Precipitation.RAIN; ++ return biomebase.getPrecipitationAt(pos) == Biome.Precipitation.RAIN; + } + } + +@@ -818,56 +999,56 @@ + + public abstract int getFreeMapId(); + +- public void globalLevelEvent(int i, BlockPos blockpos, int j) {} ++ public void globalLevelEvent(int id, BlockPos pos, int data) {} + +- public CrashReportCategory fillReportDetails(CrashReport crashreport) { +- CrashReportCategory crashreportcategory = crashreport.addCategory("Affected level", 1); ++ public CrashReportCategory fillReportDetails(CrashReport report) { ++ CrashReportCategory crashreportsystemdetails = report.addCategory("Affected level", 1); + +- crashreportcategory.setDetail("All players", () -> { ++ crashreportsystemdetails.setDetail("All players", () -> { + int i = this.players().size(); + + return i + " total; " + this.players(); + }); +- ChunkSource chunksource = this.getChunkSource(); ++ ChunkSource ichunkprovider = this.getChunkSource(); + +- Objects.requireNonNull(chunksource); +- crashreportcategory.setDetail("Chunk stats", chunksource::gatherStats); +- crashreportcategory.setDetail("Level dimension", () -> { ++ Objects.requireNonNull(ichunkprovider); ++ crashreportsystemdetails.setDetail("Chunk stats", ichunkprovider::gatherStats); ++ crashreportsystemdetails.setDetail("Level dimension", () -> { + return this.dimension().location().toString(); + }); + + try { +- this.levelData.fillCrashReportCategory(crashreportcategory, this); ++ this.levelData.fillCrashReportCategory(crashreportsystemdetails, this); + } catch (Throwable throwable) { +- crashreportcategory.setDetailError("Level Data Unobtainable", throwable); ++ crashreportsystemdetails.setDetailError("Level Data Unobtainable", throwable); + } + +- return crashreportcategory; ++ return crashreportsystemdetails; + } + + public abstract void destroyBlockProgress(int breakerId, BlockPos pos, int progress); + +- public void createFireworks(double d0, double d1, double d2, double d3, double d4, double d5, @Nullable CompoundTag compoundtag) {} ++ public void createFireworks(double x, double d1, double y, double d3, double z, double d5, @Nullable CompoundTag motionX) {} + + public abstract Scoreboard getScoreboard(); + +- public void updateNeighbourForOutputSignal(BlockPos blockpos, Block block) { ++ public void updateNeighbourForOutputSignal(BlockPos pos, Block block) { + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); +- BlockPos blockpos1 = blockpos.relative(direction); ++ Direction enumdirection = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection); + +- if (this.hasChunkAt(blockpos1)) { +- BlockState blockstate = this.getBlockState(blockpos1); ++ if (this.hasChunkAt(blockposition1)) { ++ IBlockData iblockdata = this.getBlockState(blockposition1); + +- if (blockstate.is(Blocks.COMPARATOR)) { +- this.neighborChanged(blockstate, blockpos1, block, blockpos, false); +- } else if (blockstate.isRedstoneConductor(this, blockpos1)) { +- blockpos1 = blockpos1.relative(direction); +- blockstate = this.getBlockState(blockpos1); +- if (blockstate.is(Blocks.COMPARATOR)) { +- this.neighborChanged(blockstate, blockpos1, block, blockpos, false); ++ if (iblockdata.is(Blocks.COMPARATOR)) { ++ this.neighborChanged(iblockdata, blockposition1, block, pos, false); ++ } else if (iblockdata.isRedstoneConductor(this, blockposition1)) { ++ blockposition1 = blockposition1.relative(enumdirection); ++ iblockdata = this.getBlockState(blockposition1); ++ if (iblockdata.is(Blocks.COMPARATOR)) { ++ this.neighborChanged(iblockdata, blockposition1, block, pos, false); + } + } + } +@@ -876,29 +1057,26 @@ + } + + @Override +- @Override +- public DifficultyInstance getCurrentDifficultyAt(BlockPos blockpos) { ++ public DifficultyInstance getCurrentDifficultyAt(BlockPos pos) { + long i = 0L; + float f = 0.0F; + +- if (this.hasChunkAt(blockpos)) { ++ if (this.hasChunkAt(pos)) { + f = this.getMoonBrightness(); +- i = this.getChunkAt(blockpos).getInhabitedTime(); ++ i = this.getChunkAt(pos).getInhabitedTime(); + } + + return new DifficultyInstance(this.getDifficulty(), this.getDayTime(), i, f); + } + + @Override +- @Override + public int getSkyDarken() { + return this.skyDarken; + } + +- public void setSkyFlashTime(int i) {} ++ public void setSkyFlashTime(int timeFlash) {} + + @Override +- @Override + public WorldBorder getWorldBorder() { + return this.worldBorder; + } +@@ -908,7 +1086,6 @@ + } + + @Override +- @Override + public DimensionType dimensionType() { + return (DimensionType) this.dimensionTypeRegistration.value(); + } +@@ -926,30 +1103,27 @@ + } + + @Override +- @Override + public RandomSource getRandom() { + return this.random; + } + + @Override +- @Override +- public boolean isStateAtPosition(BlockPos blockpos, Predicate predicate) { +- return predicate.test(this.getBlockState(blockpos)); ++ public boolean isStateAtPosition(BlockPos pos, Predicate state) { ++ return state.test(this.getBlockState(pos)); + } + + @Override +- @Override +- public boolean isFluidAtPosition(BlockPos blockpos, Predicate predicate) { +- return predicate.test(this.getFluidState(blockpos)); ++ public boolean isFluidAtPosition(BlockPos pos, Predicate predicate) { ++ return predicate.test(this.getFluidState(pos)); + } + + public abstract RecipeManager getRecipeManager(); + +- public BlockPos getBlockRandomPos(int i, int j, int k, int l) { ++ public BlockPos getBlockRandomPos(int x, int y, int z, int yMask) { + this.randValue = this.randValue * 3 + 1013904223; + int i1 = this.randValue >> 2; + +- return new BlockPos(i + (i1 & 15), j + (i1 >> 16 & l), k + (i1 >> 8 & 15)); ++ return new BlockPos(x + (i1 & 15), y + (i1 >> 16 & yMask), z + (i1 >> 8 & 15)); + } + + public boolean noSave() { +@@ -965,7 +1139,6 @@ + } + + @Override +- @Override + public BiomeManager getBiomeManager() { + return this.biomeManager; + } +@@ -974,16 +1147,14 @@ + return this.isDebug; + } + +- protected abstract LevelEntityGetter getEntities(); ++ public abstract LevelEntityGetter getEntities(); + + @Override +- @Override + public long nextSubTickCount() { + return (long) (this.subTickCount++); + } + + @Override +- @Override + public RegistryAccess registryAccess() { + return this.registryAccess; + } +@@ -992,10 +1163,10 @@ + return this.damageSources; + } + +- public static enum ExplosionInteraction { ++ public static enum a { + + NONE, BLOCK, MOB, TNT, BLOW; + +- private ExplosionInteraction() {} ++ private a() {} + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/LevelAccessor.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/LevelAccessor.java.patch new file mode 100644 index 0000000000..b27ddcd716 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/LevelAccessor.java.patch @@ -0,0 +1,125 @@ +--- a/net/minecraft/world/level/LevelAccessor.java ++++ b/net/minecraft/world/level/LevelAccessor.java +@@ -13,7 +13,7 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.block.Block; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ChunkSource; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.Fluid; +@@ -27,7 +27,6 @@ + public interface LevelAccessor extends CommonLevelAccessor, LevelTimeAccess { + + @Override +- @Override + default long dayTime() { + return this.getLevelData().getDayTime(); + } +@@ -36,30 +35,30 @@ + + LevelTickAccess getBlockTicks(); + +- private default ScheduledTick createTick(BlockPos blockpos, T t0, int i, TickPriority tickpriority) { +- return new ScheduledTick<>(t0, blockpos, this.getLevelData().getGameTime() + (long) i, tickpriority, this.nextSubTickCount()); ++ default ScheduledTick createTick(BlockPos pos, T type, int delay, TickPriority priority) { // CraftBukkit - decompile error ++ return new ScheduledTick<>(type, pos, this.getLevelData().getGameTime() + (long) delay, priority, this.nextSubTickCount()); + } + +- private default ScheduledTick createTick(BlockPos blockpos, T t0, int i) { +- return new ScheduledTick<>(t0, blockpos, this.getLevelData().getGameTime() + (long) i, this.nextSubTickCount()); ++ default ScheduledTick createTick(BlockPos pos, T type, int delay) { // CraftBukkit - decompile error ++ return new ScheduledTick<>(type, pos, this.getLevelData().getGameTime() + (long) delay, this.nextSubTickCount()); + } + +- default void scheduleTick(BlockPos blockpos, Block block, int i, TickPriority tickpriority) { +- this.getBlockTicks().schedule(this.createTick(blockpos, block, i, tickpriority)); ++ default void scheduleTick(BlockPos pos, Block block, int delay, TickPriority priority) { ++ this.getBlockTicks().schedule(this.createTick(pos, block, delay, priority)); + } + +- default void scheduleTick(BlockPos blockpos, Block block, int i) { +- this.getBlockTicks().schedule(this.createTick(blockpos, block, i)); ++ default void scheduleTick(BlockPos pos, Block block, int delay) { ++ this.getBlockTicks().schedule(this.createTick(pos, block, delay)); + } + + LevelTickAccess getFluidTicks(); + +- default void scheduleTick(BlockPos blockpos, Fluid fluid, int i, TickPriority tickpriority) { +- this.getFluidTicks().schedule(this.createTick(blockpos, fluid, i, tickpriority)); ++ default void scheduleTick(BlockPos pos, Fluid fluid, int delay, TickPriority priority) { ++ this.getFluidTicks().schedule(this.createTick(pos, fluid, delay, priority)); + } + +- default void scheduleTick(BlockPos blockpos, Fluid fluid, int i) { +- this.getFluidTicks().schedule(this.createTick(blockpos, fluid, i)); ++ default void scheduleTick(BlockPos pos, Fluid fluid, int delay) { ++ this.getFluidTicks().schedule(this.createTick(pos, fluid, delay)); + } + + LevelData getLevelData(); +@@ -76,44 +75,45 @@ + ChunkSource getChunkSource(); + + @Override +- @Override +- default boolean hasChunk(int i, int j) { +- return this.getChunkSource().hasChunk(i, j); ++ default boolean hasChunk(int chunkX, int chunkZ) { ++ return this.getChunkSource().hasChunk(chunkX, chunkZ); + } + + RandomSource getRandom(); + +- default void blockUpdated(BlockPos blockpos, Block block) {} ++ default void blockUpdated(BlockPos pos, Block block) {} + +- default void neighborShapeChanged(Direction direction, BlockState blockstate, BlockPos blockpos, BlockPos blockpos1, int i, int j) { +- NeighborUpdater.executeShapeUpdate(this, direction, blockstate, blockpos, blockpos1, i, j - 1); ++ default void neighborShapeChanged(Direction direction, IBlockData queried, BlockPos pos, BlockPos offsetPos, int flags, int recursionLevel) { ++ NeighborUpdater.executeShapeUpdate(this, direction, queried, pos, offsetPos, flags, recursionLevel - 1); + } + +- default void playSound(@Nullable Player player, BlockPos blockpos, SoundEvent soundevent, SoundSource soundsource) { +- this.playSound(player, blockpos, soundevent, soundsource, 1.0F, 1.0F); ++ default void playSound(@Nullable Player player, BlockPos pos, SoundEvent sound, SoundSource source) { ++ this.playSound(player, pos, sound, source, 1.0F, 1.0F); + } + + void playSound(@Nullable Player player, BlockPos pos, SoundEvent sound, SoundSource source, float volume, float pitch); + +- void addParticle(ParticleOptions particleData, double x, double d, double y, double d1, double z, double d2); ++ void addParticle(ParticleOptions particleData, double x, double d1, double y, double d3, double z, double d5); + + void levelEvent(@Nullable Player player, int type, BlockPos pos, int data); + +- default void levelEvent(int i, BlockPos blockpos, int j) { +- this.levelEvent((Player) null, i, blockpos, j); ++ default void levelEvent(int type, BlockPos pos, int data) { ++ this.levelEvent((Player) null, type, pos, data); + } + + void gameEvent(GameEvent event, Vec3 position, GameEvent.Context context); + +- default void gameEvent(@Nullable Entity entity, GameEvent gameevent, Vec3 vec3) { +- this.gameEvent(gameevent, vec3, new GameEvent.Context(entity, (BlockState) null)); ++ default void gameEvent(@Nullable Entity entity, GameEvent event, Vec3 position) { ++ this.gameEvent(event, position, new GameEvent.Context(entity, (IBlockData) null)); + } + +- default void gameEvent(@Nullable Entity entity, GameEvent gameevent, BlockPos blockpos) { +- this.gameEvent(gameevent, blockpos, new GameEvent.Context(entity, (BlockState) null)); ++ default void gameEvent(@Nullable Entity entity, GameEvent event, BlockPos pos) { ++ this.gameEvent(event, pos, new GameEvent.Context(entity, (IBlockData) null)); + } + +- default void gameEvent(GameEvent gameevent, BlockPos blockpos, GameEvent.Context gameevent_context) { +- this.gameEvent(gameevent, Vec3.atCenterOf(blockpos), gameevent_context); ++ default void gameEvent(GameEvent event, BlockPos pos, GameEvent.Context context) { ++ this.gameEvent(event, Vec3.atCenterOf(pos), context); + } ++ ++ net.minecraft.server.level.ServerLevel getMinecraftWorld(); // CraftBukkit + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/LevelWriter.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/LevelWriter.java.patch new file mode 100644 index 0000000000..d645bc2bef --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/LevelWriter.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/world/level/LevelWriter.java ++++ b/net/minecraft/world/level/LevelWriter.java +@@ -3,24 +3,24 @@ + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.world.entity.Entity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public interface LevelWriter { + +- boolean setBlock(BlockPos pos, BlockState state, int flags, int recursionLeft); ++ boolean setBlock(BlockPos pos, IBlockData state, int flags, int recursionLeft); + +- default boolean setBlock(BlockPos blockpos, BlockState blockstate, int i) { +- return this.setBlock(blockpos, blockstate, i, 512); ++ default boolean setBlock(BlockPos pos, IBlockData newState, int flags) { ++ return this.setBlock(pos, newState, flags, 512); + } + + boolean removeBlock(BlockPos pos, boolean isMoving); + +- default boolean destroyBlock(BlockPos blockpos, boolean flag) { +- return this.destroyBlock(blockpos, flag, (Entity) null); ++ default boolean destroyBlock(BlockPos pos, boolean dropBlock) { ++ return this.destroyBlock(pos, dropBlock, (Entity) null); + } + +- default boolean destroyBlock(BlockPos blockpos, boolean flag, @Nullable Entity entity) { +- return this.destroyBlock(blockpos, flag, entity, 512); ++ default boolean destroyBlock(BlockPos pos, boolean dropBlock, @Nullable Entity entity) { ++ return this.destroyBlock(pos, dropBlock, entity, 512); + } + + boolean destroyBlock(BlockPos pos, boolean dropBlock, @Nullable Entity entity, int recursionLeft); +@@ -28,4 +28,10 @@ + default boolean addFreshEntity(Entity entity) { + return false; + } ++ ++ // CraftBukkit start ++ default boolean addFreshEntity(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ return false; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/NaturalSpawner.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/NaturalSpawner.java.patch new file mode 100644 index 0000000000..ef00c13ded --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/NaturalSpawner.java.patch @@ -0,0 +1,676 @@ +--- a/net/minecraft/world/level/NaturalSpawner.java ++++ b/net/minecraft/world/level/NaturalSpawner.java +@@ -27,16 +27,16 @@ + import net.minecraft.util.random.WeightedRandomList; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.Mob; + import net.minecraft.world.entity.MobCategory; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.SpawnPlacements; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.biome.Biome; + import net.minecraft.world.level.biome.MobSpawnSettings; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.chunk.LevelChunk; +@@ -45,9 +45,14 @@ + import net.minecraft.world.level.levelgen.structure.Structure; + import net.minecraft.world.level.levelgen.structure.structures.NetherFortressStructure; + import net.minecraft.world.level.material.FluidState; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; ++import net.minecraft.world.level.storage.LevelData; + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.util.CraftSpawnCategory; ++import org.bukkit.entity.SpawnCategory; ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; ++// CraftBukkit end + + public final class NaturalSpawner { + +@@ -56,112 +61,127 @@ + public static final int SPAWN_DISTANCE_CHUNK = 8; + public static final int SPAWN_DISTANCE_BLOCK = 128; + static final int MAGIC_NUMBER = (int) Math.pow(17.0D, 2.0D); +- private static final MobCategory[] SPAWNING_CATEGORIES = (MobCategory[]) Stream.of(MobCategory.values()).filter((mobcategory) -> { +- return mobcategory != MobCategory.MISC; ++ private static final MobCategory[] SPAWNING_CATEGORIES = (MobCategory[]) Stream.of(MobCategory.values()).filter((enumcreaturetype) -> { ++ return enumcreaturetype != MobCategory.MISC; + }).toArray((i) -> { + return new MobCategory[i]; + }); + + private NaturalSpawner() {} + +- public static NaturalSpawner.SpawnState createState(int i, Iterable iterable, NaturalSpawner.ChunkGetter naturalspawner_chunkgetter, LocalMobCapCalculator localmobcapcalculator) { +- PotentialCalculator potentialcalculator = new PotentialCalculator(); ++ public static NaturalSpawner.SpawnState createState(int spawnableChunkCount, Iterable entities, NaturalSpawner.ChunkGetter chunkGetter, LocalMobCapCalculator calculator) { ++ PotentialCalculator spawnercreatureprobabilities = new PotentialCalculator(); + Object2IntOpenHashMap object2intopenhashmap = new Object2IntOpenHashMap(); +- Iterator iterator = iterable.iterator(); ++ Iterator iterator = entities.iterator(); + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); + + if (entity instanceof Mob) { +- Mob mob = (Mob) entity; ++ Mob entityinsentient = (Mob) entity; + +- if (mob.isPersistenceRequired() || mob.requiresCustomPersistence()) { ++ if (entityinsentient.isPersistenceRequired() || entityinsentient.requiresCustomPersistence()) { + continue; + } + } + +- MobCategory mobcategory = entity.getType().getCategory(); ++ MobCategory enumcreaturetype = entity.getType().getCategory(); + +- if (mobcategory != MobCategory.MISC) { +- BlockPos blockpos = entity.blockPosition(); ++ if (enumcreaturetype != MobCategory.MISC) { ++ BlockPos blockposition = entity.blockPosition(); + +- naturalspawner_chunkgetter.query(ChunkPos.asLong(blockpos), (levelchunk) -> { +- MobSpawnSettings.MobSpawnCost mobspawnsettings_mobspawncost = getRoughBiome(blockpos, levelchunk).getMobSettings().getMobSpawnCost(entity.getType()); ++ chunkGetter.query(ChunkPos.asLong(blockposition), (chunk) -> { ++ MobSpawnSettings.MobSpawnCost biomesettingsmobs_b = getRoughBiome(blockposition, chunk).getMobSettings().getMobSpawnCost(entity.getType()); + +- if (mobspawnsettings_mobspawncost != null) { +- potentialcalculator.addCharge(entity.blockPosition(), mobspawnsettings_mobspawncost.charge()); ++ if (biomesettingsmobs_b != null) { ++ spawnercreatureprobabilities.addCharge(entity.blockPosition(), biomesettingsmobs_b.charge()); + } + + if (entity instanceof Mob) { +- localmobcapcalculator.addMob(levelchunk.getPos(), mobcategory); ++ calculator.addMob(chunk.getPos(), enumcreaturetype); + } + +- object2intopenhashmap.addTo(mobcategory, 1); ++ object2intopenhashmap.addTo(enumcreaturetype, 1); + }); + } + } + +- return new NaturalSpawner.SpawnState(i, object2intopenhashmap, potentialcalculator, localmobcapcalculator); ++ return new NaturalSpawner.SpawnState(spawnableChunkCount, object2intopenhashmap, spawnercreatureprobabilities, calculator); + } + +- static Biome getRoughBiome(BlockPos blockpos, ChunkAccess chunkaccess) { +- return (Biome) chunkaccess.getNoiseBiome(QuartPos.fromBlock(blockpos.getX()), QuartPos.fromBlock(blockpos.getY()), QuartPos.fromBlock(blockpos.getZ())).value(); ++ static Biome getRoughBiome(BlockPos pos, ChunkAccess chunk) { ++ return (Biome) chunk.getNoiseBiome(QuartPos.fromBlock(pos.getX()), QuartPos.fromBlock(pos.getY()), QuartPos.fromBlock(pos.getZ())).value(); + } + +- public static void spawnForChunk(ServerLevel serverlevel, LevelChunk levelchunk, NaturalSpawner.SpawnState naturalspawner_spawnstate, boolean flag, boolean flag1, boolean flag2) { +- serverlevel.getProfiler().push("spawner"); +- MobCategory[] amobcategory = NaturalSpawner.SPAWNING_CATEGORIES; +- int i = amobcategory.length; ++ public static void spawnForChunk(ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnState spawnState, boolean spawnFriendlies, boolean spawnMonsters, boolean forcedDespawn) { ++ level.getProfiler().push("spawner"); ++ MobCategory[] aenumcreaturetype = NaturalSpawner.SPAWNING_CATEGORIES; ++ int i = aenumcreaturetype.length; + ++ LevelData worlddata = level.getLevelData(); // CraftBukkit - Other mob type spawn tick rate ++ + for (int j = 0; j < i; ++j) { +- MobCategory mobcategory = amobcategory[j]; ++ MobCategory enumcreaturetype = aenumcreaturetype[j]; ++ // CraftBukkit start - Use per-world spawn limits ++ boolean spawnThisTick = true; ++ int limit = enumcreaturetype.getMaxInstancesPerChunk(); ++ SpawnCategory spawnCategory = CraftSpawnCategory.toBukkit(enumcreaturetype); ++ if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { ++ spawnThisTick = level.ticksPerSpawnCategory.getLong(spawnCategory) != 0 && worlddata.getGameTime() % level.ticksPerSpawnCategory.getLong(spawnCategory) == 0; ++ limit = level.getWorld().getSpawnLimit(spawnCategory); ++ } + +- if ((flag || !mobcategory.isFriendly()) && (flag1 || mobcategory.isFriendly()) && (flag2 || !mobcategory.isPersistent()) && naturalspawner_spawnstate.canSpawnForCategory(mobcategory, levelchunk.getPos())) { +- Objects.requireNonNull(naturalspawner_spawnstate); +- NaturalSpawner.SpawnPredicate naturalspawner_spawnpredicate = naturalspawner_spawnstate::canSpawn; ++ if (!spawnThisTick || limit == 0) { ++ continue; ++ } + +- Objects.requireNonNull(naturalspawner_spawnstate); +- spawnCategoryForChunk(mobcategory, serverlevel, levelchunk, naturalspawner_spawnpredicate, naturalspawner_spawnstate::afterSpawn); ++ if ((spawnFriendlies || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (forcedDespawn || !enumcreaturetype.isPersistent()) && spawnState.canSpawnForCategory(enumcreaturetype, chunk.getPos(), limit)) { ++ // CraftBukkit end ++ Objects.requireNonNull(spawnState); ++ NaturalSpawner.SpawnPredicate spawnercreature_c = spawnState::canSpawn; ++ ++ Objects.requireNonNull(spawnState); ++ spawnCategoryForChunk(enumcreaturetype, level, chunk, spawnercreature_c, spawnState::afterSpawn); + } + } + +- serverlevel.getProfiler().pop(); ++ level.getProfiler().pop(); + } + +- public static void spawnCategoryForChunk(MobCategory mobcategory, ServerLevel serverlevel, LevelChunk levelchunk, NaturalSpawner.SpawnPredicate naturalspawner_spawnpredicate, NaturalSpawner.AfterSpawnCallback naturalspawner_afterspawncallback) { +- BlockPos blockpos = getRandomPosWithin(serverlevel, levelchunk); ++ public static void spawnCategoryForChunk(MobCategory category, ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback) { ++ BlockPos blockposition = getRandomPosWithin(level, chunk); + +- if (blockpos.getY() >= serverlevel.getMinBuildHeight() + 1) { +- spawnCategoryForPosition(mobcategory, serverlevel, levelchunk, blockpos, naturalspawner_spawnpredicate, naturalspawner_afterspawncallback); ++ if (blockposition.getY() >= level.getMinBuildHeight() + 1) { ++ spawnCategoryForPosition(category, level, chunk, blockposition, filter, callback); + } + } + + @VisibleForDebug +- public static void spawnCategoryForPosition(MobCategory mobcategory, ServerLevel serverlevel, BlockPos blockpos) { +- spawnCategoryForPosition(mobcategory, serverlevel, serverlevel.getChunk(blockpos), blockpos, (entitytype, blockpos1, chunkaccess) -> { ++ public static void spawnCategoryForPosition(MobCategory category, ServerLevel level, BlockPos pos) { ++ spawnCategoryForPosition(category, level, level.getChunk(pos), pos, (entitytypes, blockposition1, ichunkaccess) -> { + return true; +- }, (mob, chunkaccess) -> { ++ }, (entityinsentient, ichunkaccess) -> { + }); + } + +- public static void spawnCategoryForPosition(MobCategory mobcategory, ServerLevel serverlevel, ChunkAccess chunkaccess, BlockPos blockpos, NaturalSpawner.SpawnPredicate naturalspawner_spawnpredicate, NaturalSpawner.AfterSpawnCallback naturalspawner_afterspawncallback) { +- StructureManager structuremanager = serverlevel.structureManager(); +- ChunkGenerator chunkgenerator = serverlevel.getChunkSource().getGenerator(); +- int i = blockpos.getY(); +- BlockState blockstate = chunkaccess.getBlockState(blockpos); ++ public static void spawnCategoryForPosition(MobCategory category, ServerLevel level, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback) { ++ StructureManager structuremanager = level.structureManager(); ++ ChunkGenerator chunkgenerator = level.getChunkSource().getGenerator(); ++ int i = pos.getY(); ++ IBlockData iblockdata = chunk.getBlockState(pos); + +- if (!blockstate.isRedstoneConductor(chunkaccess, blockpos)) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ if (!iblockdata.isRedstoneConductor(chunk, pos)) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + int j = 0; + int k = 0; + + while (k < 3) { +- int l = blockpos.getX(); +- int i1 = blockpos.getZ(); ++ int l = pos.getX(); ++ int i1 = pos.getZ(); + boolean flag = true; +- MobSpawnSettings.SpawnerData mobspawnsettings_spawnerdata = null; +- SpawnGroupData spawngroupdata = null; +- int j1 = Mth.ceil(serverlevel.random.nextFloat() * 4.0F); ++ MobSpawnSettings.SpawnerData biomesettingsmobs_c = null; ++ GroupDataEntity groupdataentity = null; ++ int j1 = Mth.ceil(level.random.nextFloat() * 4.0F); + int k1 = 0; + int l1 = 0; + +@@ -169,47 +189,52 @@ + if (l1 < j1) { + label53: + { +- l += serverlevel.random.nextInt(6) - serverlevel.random.nextInt(6); +- i1 += serverlevel.random.nextInt(6) - serverlevel.random.nextInt(6); +- blockpos_mutableblockpos.set(l, i, i1); ++ l += level.random.nextInt(6) - level.random.nextInt(6); ++ i1 += level.random.nextInt(6) - level.random.nextInt(6); ++ blockposition_mutableblockposition.set(l, i, i1); + double d0 = (double) l + 0.5D; + double d1 = (double) i1 + 0.5D; +- Player player = serverlevel.getNearestPlayer(d0, (double) i, d1, -1.0D, false); ++ Player entityhuman = level.getNearestPlayer(d0, (double) i, d1, -1.0D, false); + +- if (player != null) { +- double d2 = player.distanceToSqr(d0, (double) i, d1); ++ if (entityhuman != null) { ++ double d2 = entityhuman.distanceToSqr(d0, (double) i, d1); + +- if (isRightDistanceToPlayerAndSpawnPoint(serverlevel, chunkaccess, blockpos_mutableblockpos, d2)) { +- if (mobspawnsettings_spawnerdata == null) { +- Optional optional = getRandomSpawnMobAt(serverlevel, structuremanager, chunkgenerator, mobcategory, serverlevel.random, blockpos_mutableblockpos); ++ if (isRightDistanceToPlayerAndSpawnPoint(level, chunk, blockposition_mutableblockposition, d2)) { ++ if (biomesettingsmobs_c == null) { ++ Optional optional = getRandomSpawnMobAt(level, structuremanager, chunkgenerator, category, level.random, blockposition_mutableblockposition); + + if (optional.isEmpty()) { + break label53; + } + +- mobspawnsettings_spawnerdata = (MobSpawnSettings.SpawnerData) optional.get(); +- j1 = mobspawnsettings_spawnerdata.minCount + serverlevel.random.nextInt(1 + mobspawnsettings_spawnerdata.maxCount - mobspawnsettings_spawnerdata.minCount); ++ biomesettingsmobs_c = (MobSpawnSettings.SpawnerData) optional.get(); ++ j1 = biomesettingsmobs_c.minCount + level.random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount); + } + +- if (isValidSpawnPostitionForType(serverlevel, mobcategory, structuremanager, chunkgenerator, mobspawnsettings_spawnerdata, blockpos_mutableblockpos, d2) && naturalspawner_spawnpredicate.test(mobspawnsettings_spawnerdata.type, blockpos_mutableblockpos, chunkaccess)) { +- Mob mob = getMobForSpawn(serverlevel, mobspawnsettings_spawnerdata.type); ++ if (isValidSpawnPostitionForType(level, category, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2) && filter.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { ++ Mob entityinsentient = getMobForSpawn(level, biomesettingsmobs_c.type); + +- if (mob == null) { ++ if (entityinsentient == null) { + return; + } + +- mob.moveTo(d0, (double) i, d1, serverlevel.random.nextFloat() * 360.0F, 0.0F); +- if (isValidPositionForMob(serverlevel, mob, d2)) { +- spawngroupdata = mob.finalizeSpawn(serverlevel, serverlevel.getCurrentDifficultyAt(mob.blockPosition()), MobSpawnType.NATURAL, spawngroupdata, (CompoundTag) null); +- ++j; +- ++k1; +- serverlevel.addFreshEntityWithPassengers(mob); +- naturalspawner_afterspawncallback.run(mob, chunkaccess); +- if (j >= mob.getMaxSpawnClusterSize()) { ++ entityinsentient.moveTo(d0, (double) i, d1, level.random.nextFloat() * 360.0F, 0.0F); ++ if (isValidPositionForMob(level, entityinsentient, d2)) { ++ groupdataentity = entityinsentient.finalizeSpawn(level, level.getCurrentDifficultyAt(entityinsentient.blockPosition()), EnumMobSpawn.NATURAL, groupdataentity, (CompoundTag) null); ++ // CraftBukkit start ++ // SPIGOT-7045: Give ocelot babies back their special spawn reason. Note: This is the only modification required as ocelots count as monsters which means they only spawn during normal chunk ticking and do not spawn during chunk generation as starter mobs. ++ level.addFreshEntityWithPassengers(entityinsentient, (entityinsentient instanceof net.minecraft.world.entity.animal.Ocelot && !((org.bukkit.entity.Ageable) entityinsentient.getBukkitEntity()).isAdult()) ? SpawnReason.OCELOT_BABY : SpawnReason.NATURAL); ++ if (!entityinsentient.isRemoved()) { ++ ++j; ++ ++k1; ++ callback.run(entityinsentient, chunk); ++ } ++ // CraftBukkit end ++ if (j >= entityinsentient.getMaxSpawnClusterSize()) { + return; + } + +- if (mob.isMaxGroupSizeReached(k1)) { ++ if (entityinsentient.isMaxGroupSizeReached(k1)) { + break label53; + } + } +@@ -230,38 +255,38 @@ + } + } + +- private static boolean isRightDistanceToPlayerAndSpawnPoint(ServerLevel serverlevel, ChunkAccess chunkaccess, BlockPos.MutableBlockPos blockpos_mutableblockpos, double d0) { +- return d0 <= 576.0D ? false : (serverlevel.getSharedSpawnPos().closerToCenterThan(new Vec3((double) blockpos_mutableblockpos.getX() + 0.5D, (double) blockpos_mutableblockpos.getY(), (double) blockpos_mutableblockpos.getZ() + 0.5D), 24.0D) ? false : Objects.equals(new ChunkPos(blockpos_mutableblockpos), chunkaccess.getPos()) || serverlevel.isNaturalSpawningAllowed((BlockPos) blockpos_mutableblockpos)); ++ private static boolean isRightDistanceToPlayerAndSpawnPoint(ServerLevel level, ChunkAccess chunk, BlockPos.MutableBlockPos pos, double distance) { ++ return distance <= 576.0D ? false : (level.getSharedSpawnPos().closerToCenterThan(new Vec3((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D), 24.0D) ? false : Objects.equals(new ChunkPos(pos), chunk.getPos()) || level.isNaturalSpawningAllowed((BlockPos) pos)); + } + +- private static boolean isValidSpawnPostitionForType(ServerLevel serverlevel, MobCategory mobcategory, StructureManager structuremanager, ChunkGenerator chunkgenerator, MobSpawnSettings.SpawnerData mobspawnsettings_spawnerdata, BlockPos.MutableBlockPos blockpos_mutableblockpos, double d0) { +- EntityType entitytype = mobspawnsettings_spawnerdata.type; ++ private static boolean isValidSpawnPostitionForType(ServerLevel level, MobCategory category, StructureManager structureManager, ChunkGenerator generator, MobSpawnSettings.SpawnerData data, BlockPos.MutableBlockPos pos, double distance) { ++ EntityType entitytypes = data.type; + +- if (entitytype.getCategory() == MobCategory.MISC) { ++ if (entitytypes.getCategory() == MobCategory.MISC) { + return false; +- } else if (!entitytype.canSpawnFarFromPlayer() && d0 > (double) (entitytype.getCategory().getDespawnDistance() * entitytype.getCategory().getDespawnDistance())) { ++ } else if (!entitytypes.canSpawnFarFromPlayer() && distance > (double) (entitytypes.getCategory().getDespawnDistance() * entitytypes.getCategory().getDespawnDistance())) { + return false; +- } else if (entitytype.canSummon() && canSpawnMobAt(serverlevel, structuremanager, chunkgenerator, mobcategory, mobspawnsettings_spawnerdata, blockpos_mutableblockpos)) { +- SpawnPlacements.Type spawnplacements_type = SpawnPlacements.getPlacementType(entitytype); ++ } else if (entitytypes.canSummon() && canSpawnMobAt(level, structureManager, generator, category, data, pos)) { ++ SpawnPlacements.Surface entitypositiontypes_surface = SpawnPlacements.getPlacementType(entitytypes); + +- return !isSpawnPositionOk(spawnplacements_type, serverlevel, blockpos_mutableblockpos, entitytype) ? false : (!SpawnPlacements.checkSpawnRules(entitytype, serverlevel, MobSpawnType.NATURAL, blockpos_mutableblockpos, serverlevel.random) ? false : serverlevel.noCollision(entitytype.getAABB((double) blockpos_mutableblockpos.getX() + 0.5D, (double) blockpos_mutableblockpos.getY(), (double) blockpos_mutableblockpos.getZ() + 0.5D))); ++ return !isSpawnPositionOk(entitypositiontypes_surface, level, pos, entitytypes) ? false : (!SpawnPlacements.checkSpawnRules(entitytypes, level, EnumMobSpawn.NATURAL, pos, level.random) ? false : level.noCollision(entitytypes.getAABB((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D))); + } else { + return false; + } + } + + @Nullable +- private static Mob getMobForSpawn(ServerLevel serverlevel, EntityType entitytype) { ++ private static Mob getMobForSpawn(ServerLevel level, EntityType entityType) { + try { +- Entity entity = entitytype.create(serverlevel); ++ Entity entity = entityType.create(level); + + if (entity instanceof Mob) { +- Mob mob = (Mob) entity; ++ Mob entityinsentient = (Mob) entity; + +- return mob; ++ return entityinsentient; + } + +- NaturalSpawner.LOGGER.warn("Can't spawn entity of type: {}", BuiltInRegistries.ENTITY_TYPE.getKey(entitytype)); ++ NaturalSpawner.LOGGER.warn("Can't spawn entity of type: {}", BuiltInRegistries.ENTITY_TYPE.getKey(entityType)); + } catch (Exception exception) { + NaturalSpawner.LOGGER.warn("Failed to create mob", exception); + } +@@ -269,90 +294,90 @@ + return null; + } + +- private static boolean isValidPositionForMob(ServerLevel serverlevel, Mob mob, double d0) { +- return d0 > (double) (mob.getType().getCategory().getDespawnDistance() * mob.getType().getCategory().getDespawnDistance()) && mob.removeWhenFarAway(d0) ? false : mob.checkSpawnRules(serverlevel, MobSpawnType.NATURAL) && mob.checkSpawnObstruction(serverlevel); ++ private static boolean isValidPositionForMob(ServerLevel level, Mob mob, double distance) { ++ return distance > (double) (mob.getType().getCategory().getDespawnDistance() * mob.getType().getCategory().getDespawnDistance()) && mob.removeWhenFarAway(distance) ? false : mob.checkSpawnRules(level, EnumMobSpawn.NATURAL) && mob.checkSpawnObstruction(level); + } + +- private static Optional getRandomSpawnMobAt(ServerLevel serverlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, MobCategory mobcategory, RandomSource randomsource, BlockPos blockpos) { +- Holder holder = serverlevel.getBiome(blockpos); ++ private static Optional getRandomSpawnMobAt(ServerLevel level, StructureManager structureManager, ChunkGenerator generator, MobCategory category, RandomSource random, BlockPos pos) { ++ Holder holder = level.getBiome(pos); + +- return mobcategory == MobCategory.WATER_AMBIENT && holder.is(BiomeTags.REDUCED_WATER_AMBIENT_SPAWNS) && randomsource.nextFloat() < 0.98F ? Optional.empty() : mobsAt(serverlevel, structuremanager, chunkgenerator, mobcategory, blockpos, holder).getRandom(randomsource); ++ return category == MobCategory.WATER_AMBIENT && holder.is(BiomeTags.REDUCED_WATER_AMBIENT_SPAWNS) && random.nextFloat() < 0.98F ? Optional.empty() : mobsAt(level, structureManager, generator, category, pos, holder).getRandom(random); + } + +- private static boolean canSpawnMobAt(ServerLevel serverlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, MobCategory mobcategory, MobSpawnSettings.SpawnerData mobspawnsettings_spawnerdata, BlockPos blockpos) { +- return mobsAt(serverlevel, structuremanager, chunkgenerator, mobcategory, blockpos, (Holder) null).unwrap().contains(mobspawnsettings_spawnerdata); ++ private static boolean canSpawnMobAt(ServerLevel level, StructureManager structureManager, ChunkGenerator generator, MobCategory category, MobSpawnSettings.SpawnerData data, BlockPos pos) { ++ return mobsAt(level, structureManager, generator, category, pos, (Holder) null).unwrap().contains(data); + } + +- private static WeightedRandomList mobsAt(ServerLevel serverlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, MobCategory mobcategory, BlockPos blockpos, @Nullable Holder holder) { +- return isInNetherFortressBounds(blockpos, serverlevel, mobcategory, structuremanager) ? NetherFortressStructure.FORTRESS_ENEMIES : chunkgenerator.getMobsAt(holder != null ? holder : serverlevel.getBiome(blockpos), structuremanager, mobcategory, blockpos); ++ private static WeightedRandomList mobsAt(ServerLevel level, StructureManager structureManager, ChunkGenerator generator, MobCategory category, BlockPos pos, @Nullable Holder biome) { ++ return isInNetherFortressBounds(pos, level, category, structureManager) ? NetherFortressStructure.FORTRESS_ENEMIES : generator.getMobsAt(biome != null ? biome : level.getBiome(pos), structureManager, category, pos); + } + +- public static boolean isInNetherFortressBounds(BlockPos blockpos, ServerLevel serverlevel, MobCategory mobcategory, StructureManager structuremanager) { +- if (mobcategory == MobCategory.MONSTER && serverlevel.getBlockState(blockpos.below()).is(Blocks.NETHER_BRICKS)) { +- Structure structure = (Structure) structuremanager.registryAccess().registryOrThrow(Registries.STRUCTURE).get(BuiltinStructures.FORTRESS); ++ public static boolean isInNetherFortressBounds(BlockPos pos, ServerLevel level, MobCategory category, StructureManager structureManager) { ++ if (category == MobCategory.MONSTER && level.getBlockState(pos.below()).is(Blocks.NETHER_BRICKS)) { ++ Structure structure = (Structure) structureManager.registryAccess().registryOrThrow(Registries.STRUCTURE).get(BuiltinStructures.FORTRESS); + +- return structure == null ? false : structuremanager.getStructureAt(blockpos, structure).isValid(); ++ return structure == null ? false : structureManager.getStructureAt(pos, structure).isValid(); + } else { + return false; + } + } + +- private static BlockPos getRandomPosWithin(Level level, LevelChunk levelchunk) { +- ChunkPos chunkpos = levelchunk.getPos(); +- int i = chunkpos.getMinBlockX() + level.random.nextInt(16); +- int j = chunkpos.getMinBlockZ() + level.random.nextInt(16); +- int k = levelchunk.getHeight(Heightmap.Types.WORLD_SURFACE, i, j) + 1; ++ private static BlockPos getRandomPosWithin(Level level, LevelChunk chunk) { ++ ChunkPos chunkcoordintpair = chunk.getPos(); ++ int i = chunkcoordintpair.getMinBlockX() + level.random.nextInt(16); ++ int j = chunkcoordintpair.getMinBlockZ() + level.random.nextInt(16); ++ int k = chunk.getHeight(Heightmap.Types.WORLD_SURFACE, i, j) + 1; + int l = Mth.randomBetweenInclusive(level.random, level.getMinBuildHeight(), k); + + return new BlockPos(i, l, j); + } + +- public static boolean isValidEmptySpawnBlock(BlockGetter blockgetter, BlockPos blockpos, BlockState blockstate, FluidState fluidstate, EntityType entitytype) { +- return blockstate.isCollisionShapeFullBlock(blockgetter, blockpos) ? false : (blockstate.isSignalSource() ? false : (!fluidstate.isEmpty() ? false : (blockstate.is(BlockTags.PREVENT_MOB_SPAWNING_INSIDE) ? false : !entitytype.isBlockDangerous(blockstate)))); ++ public static boolean isValidEmptySpawnBlock(BlockGetter block, BlockPos pos, IBlockData blockState, FluidState fluidState, EntityType entityType) { ++ return blockState.isCollisionShapeFullBlock(block, pos) ? false : (blockState.isSignalSource() ? false : (!fluidState.isEmpty() ? false : (blockState.is(BlockTags.PREVENT_MOB_SPAWNING_INSIDE) ? false : !entityType.isBlockDangerous(blockState)))); + } + +- public static boolean isSpawnPositionOk(SpawnPlacements.Type spawnplacements_type, LevelReader levelreader, BlockPos blockpos, @Nullable EntityType entitytype) { +- if (spawnplacements_type == SpawnPlacements.Type.NO_RESTRICTIONS) { ++ public static boolean isSpawnPositionOk(SpawnPlacements.Surface placeType, LevelReader level, BlockPos pos, @Nullable EntityType entityType) { ++ if (placeType == SpawnPlacements.Surface.NO_RESTRICTIONS) { + return true; +- } else if (entitytype != null && levelreader.getWorldBorder().isWithinBounds(blockpos)) { +- BlockState blockstate = levelreader.getBlockState(blockpos); +- FluidState fluidstate = levelreader.getFluidState(blockpos); +- BlockPos blockpos1 = blockpos.above(); +- BlockPos blockpos2 = blockpos.below(); ++ } else if (entityType != null && level.getWorldBorder().isWithinBounds(pos)) { ++ IBlockData iblockdata = level.getBlockState(pos); ++ FluidState fluid = level.getFluidState(pos); ++ BlockPos blockposition1 = pos.above(); ++ BlockPos blockposition2 = pos.below(); + +- switch (spawnplacements_type) { ++ switch (placeType) { + case IN_WATER: +- return fluidstate.is(FluidTags.WATER) && !levelreader.getBlockState(blockpos1).isRedstoneConductor(levelreader, blockpos1); ++ return fluid.is(FluidTags.WATER) && !level.getBlockState(blockposition1).isRedstoneConductor(level, blockposition1); + case IN_LAVA: +- return fluidstate.is(FluidTags.LAVA); ++ return fluid.is(FluidTags.LAVA); + case ON_GROUND: + default: +- BlockState blockstate1 = levelreader.getBlockState(blockpos2); ++ IBlockData iblockdata1 = level.getBlockState(blockposition2); + +- return !blockstate1.isValidSpawn(levelreader, blockpos2, entitytype) ? false : isValidEmptySpawnBlock(levelreader, blockpos, blockstate, fluidstate, entitytype) && isValidEmptySpawnBlock(levelreader, blockpos1, levelreader.getBlockState(blockpos1), levelreader.getFluidState(blockpos1), entitytype); ++ return !iblockdata1.isValidSpawn(level, blockposition2, entityType) ? false : isValidEmptySpawnBlock(level, pos, iblockdata, fluid, entityType) && isValidEmptySpawnBlock(level, blockposition1, level.getBlockState(blockposition1), level.getFluidState(blockposition1), entityType); + } + } else { + return false; + } + } + +- public static void spawnMobsForChunkGeneration(ServerLevelAccessor serverlevelaccessor, Holder holder, ChunkPos chunkpos, RandomSource randomsource) { +- MobSpawnSettings mobspawnsettings = ((Biome) holder.value()).getMobSettings(); +- WeightedRandomList weightedrandomlist = mobspawnsettings.getMobs(MobCategory.CREATURE); ++ public static void spawnMobsForChunkGeneration(ServerLevelAccessor levelAccessor, Holder biome, ChunkPos chunkPos, RandomSource random) { ++ MobSpawnSettings biomesettingsmobs = ((Biome) biome.value()).getMobSettings(); ++ WeightedRandomList weightedrandomlist = biomesettingsmobs.getMobs(MobCategory.CREATURE); + + if (!weightedrandomlist.isEmpty()) { +- int i = chunkpos.getMinBlockX(); +- int j = chunkpos.getMinBlockZ(); ++ int i = chunkPos.getMinBlockX(); ++ int j = chunkPos.getMinBlockZ(); + +- while (randomsource.nextFloat() < mobspawnsettings.getCreatureProbability()) { +- Optional optional = weightedrandomlist.getRandom(randomsource); ++ while (random.nextFloat() < biomesettingsmobs.getCreatureProbability()) { ++ Optional optional = weightedrandomlist.getRandom(random); + + if (!optional.isEmpty()) { +- MobSpawnSettings.SpawnerData mobspawnsettings_spawnerdata = (MobSpawnSettings.SpawnerData) optional.get(); +- int k = mobspawnsettings_spawnerdata.minCount + randomsource.nextInt(1 + mobspawnsettings_spawnerdata.maxCount - mobspawnsettings_spawnerdata.minCount); +- SpawnGroupData spawngroupdata = null; +- int l = i + randomsource.nextInt(16); +- int i1 = j + randomsource.nextInt(16); ++ MobSpawnSettings.SpawnerData biomesettingsmobs_c = (MobSpawnSettings.SpawnerData) optional.get(); ++ int k = biomesettingsmobs_c.minCount + random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount); ++ GroupDataEntity groupdataentity = null; ++ int l = i + random.nextInt(16); ++ int i1 = j + random.nextInt(16); + int j1 = l; + int k1 = i1; + +@@ -360,21 +385,21 @@ + boolean flag = false; + + for (int i2 = 0; !flag && i2 < 4; ++i2) { +- BlockPos blockpos = getTopNonCollidingPos(serverlevelaccessor, mobspawnsettings_spawnerdata.type, l, i1); ++ BlockPos blockposition = getTopNonCollidingPos(levelAccessor, biomesettingsmobs_c.type, l, i1); + +- if (mobspawnsettings_spawnerdata.type.canSummon() && isSpawnPositionOk(SpawnPlacements.getPlacementType(mobspawnsettings_spawnerdata.type), serverlevelaccessor, blockpos, mobspawnsettings_spawnerdata.type)) { +- float f = mobspawnsettings_spawnerdata.type.getWidth(); ++ if (biomesettingsmobs_c.type.canSummon() && isSpawnPositionOk(SpawnPlacements.getPlacementType(biomesettingsmobs_c.type), levelAccessor, blockposition, biomesettingsmobs_c.type)) { ++ float f = biomesettingsmobs_c.type.getWidth(); + double d0 = Mth.clamp((double) l, (double) i + (double) f, (double) i + 16.0D - (double) f); + double d1 = Mth.clamp((double) i1, (double) j + (double) f, (double) j + 16.0D - (double) f); + +- if (!serverlevelaccessor.noCollision(mobspawnsettings_spawnerdata.type.getAABB(d0, (double) blockpos.getY(), d1)) || !SpawnPlacements.checkSpawnRules(mobspawnsettings_spawnerdata.type, serverlevelaccessor, MobSpawnType.CHUNK_GENERATION, BlockPos.containing(d0, (double) blockpos.getY(), d1), serverlevelaccessor.getRandom())) { ++ if (!levelAccessor.noCollision(biomesettingsmobs_c.type.getAABB(d0, (double) blockposition.getY(), d1)) || !SpawnPlacements.checkSpawnRules(biomesettingsmobs_c.type, levelAccessor, EnumMobSpawn.CHUNK_GENERATION, BlockPos.containing(d0, (double) blockposition.getY(), d1), levelAccessor.getRandom())) { + continue; + } + + Entity entity; + + try { +- entity = mobspawnsettings_spawnerdata.type.create(serverlevelaccessor.getLevel()); ++ entity = biomesettingsmobs_c.type.create(levelAccessor.getLevel()); + } catch (Exception exception) { + NaturalSpawner.LOGGER.warn("Failed to create mob", exception); + continue; +@@ -384,22 +409,22 @@ + continue; + } + +- entity.moveTo(d0, (double) blockpos.getY(), d1, randomsource.nextFloat() * 360.0F, 0.0F); ++ entity.moveTo(d0, (double) blockposition.getY(), d1, random.nextFloat() * 360.0F, 0.0F); + if (entity instanceof Mob) { +- Mob mob = (Mob) entity; ++ Mob entityinsentient = (Mob) entity; + +- if (mob.checkSpawnRules(serverlevelaccessor, MobSpawnType.CHUNK_GENERATION) && mob.checkSpawnObstruction(serverlevelaccessor)) { +- spawngroupdata = mob.finalizeSpawn(serverlevelaccessor, serverlevelaccessor.getCurrentDifficultyAt(mob.blockPosition()), MobSpawnType.CHUNK_GENERATION, spawngroupdata, (CompoundTag) null); +- serverlevelaccessor.addFreshEntityWithPassengers(mob); ++ if (entityinsentient.checkSpawnRules(levelAccessor, EnumMobSpawn.CHUNK_GENERATION) && entityinsentient.checkSpawnObstruction(levelAccessor)) { ++ groupdataentity = entityinsentient.finalizeSpawn(levelAccessor, levelAccessor.getCurrentDifficultyAt(entityinsentient.blockPosition()), EnumMobSpawn.CHUNK_GENERATION, groupdataentity, (CompoundTag) null); ++ levelAccessor.addFreshEntityWithPassengers(entityinsentient, SpawnReason.CHUNK_GEN); // CraftBukkit + flag = true; + } + } + } + +- l += randomsource.nextInt(5) - randomsource.nextInt(5); ++ l += random.nextInt(5) - random.nextInt(5); + +- for (i1 += randomsource.nextInt(5) - randomsource.nextInt(5); l < i || l >= i + 16 || i1 < j || i1 >= j + 16; i1 = k1 + randomsource.nextInt(5) - randomsource.nextInt(5)) { +- l = j1 + randomsource.nextInt(5) - randomsource.nextInt(5); ++ for (i1 += random.nextInt(5) - random.nextInt(5); l < i || l >= i + 16 || i1 < j || i1 >= j + 16; i1 = k1 + random.nextInt(5) - random.nextInt(5)) { ++ l = j1 + random.nextInt(5) - random.nextInt(5); + } + } + } +@@ -409,29 +434,29 @@ + } + } + +- private static BlockPos getTopNonCollidingPos(LevelReader levelreader, EntityType entitytype, int i, int j) { +- int k = levelreader.getHeight(SpawnPlacements.getHeightmapType(entitytype), i, j); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(i, k, j); ++ private static BlockPos getTopNonCollidingPos(LevelReader level, EntityType entityType, int x, int z) { ++ int k = level.getHeight(SpawnPlacements.getHeightmapType(entityType), x, z); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(x, k, z); + +- if (levelreader.dimensionType().hasCeiling()) { ++ if (level.dimensionType().hasCeiling()) { + do { +- blockpos_mutableblockpos.move(Direction.DOWN); +- } while (!levelreader.getBlockState(blockpos_mutableblockpos).isAir()); ++ blockposition_mutableblockposition.move(Direction.DOWN); ++ } while (!level.getBlockState(blockposition_mutableblockposition).isAir()); + + do { +- blockpos_mutableblockpos.move(Direction.DOWN); +- } while (levelreader.getBlockState(blockpos_mutableblockpos).isAir() && blockpos_mutableblockpos.getY() > levelreader.getMinBuildHeight()); ++ blockposition_mutableblockposition.move(Direction.DOWN); ++ } while (level.getBlockState(blockposition_mutableblockposition).isAir() && blockposition_mutableblockposition.getY() > level.getMinBuildHeight()); + } + +- if (SpawnPlacements.getPlacementType(entitytype) == SpawnPlacements.Type.ON_GROUND) { +- BlockPos blockpos = blockpos_mutableblockpos.below(); ++ if (SpawnPlacements.getPlacementType(entityType) == SpawnPlacements.Surface.ON_GROUND) { ++ BlockPos blockposition = blockposition_mutableblockposition.below(); + +- if (levelreader.getBlockState(blockpos).isPathfindable(levelreader, blockpos, PathComputationType.LAND)) { +- return blockpos; ++ if (level.getBlockState(blockposition).isPathfindable(level, blockposition, PathMode.LAND)) { ++ return blockposition; + } + } + +- return blockpos_mutableblockpos.immutable(); ++ return blockposition_mutableblockposition.immutable(); + } + + @FunctionalInterface +@@ -453,54 +478,54 @@ + private EntityType lastCheckedType; + private double lastCharge; + +- SpawnState(int i, Object2IntOpenHashMap object2intopenhashmap, PotentialCalculator potentialcalculator, LocalMobCapCalculator localmobcapcalculator) { +- this.spawnableChunkCount = i; +- this.mobCategoryCounts = object2intopenhashmap; +- this.spawnPotential = potentialcalculator; +- this.localMobCapCalculator = localmobcapcalculator; +- this.unmodifiableMobCategoryCounts = Object2IntMaps.unmodifiable(object2intopenhashmap); ++ SpawnState(int spawnableChunkCount, Object2IntOpenHashMap mobCategoryCounts, PotentialCalculator spawnPotential, LocalMobCapCalculator localMobCapCalculator) { ++ this.spawnableChunkCount = spawnableChunkCount; ++ this.mobCategoryCounts = mobCategoryCounts; ++ this.spawnPotential = spawnPotential; ++ this.localMobCapCalculator = localMobCapCalculator; ++ this.unmodifiableMobCategoryCounts = Object2IntMaps.unmodifiable(mobCategoryCounts); + } + +- private boolean canSpawn(EntityType entitytype, BlockPos blockpos, ChunkAccess chunkaccess) { +- this.lastCheckedPos = blockpos; +- this.lastCheckedType = entitytype; +- MobSpawnSettings.MobSpawnCost mobspawnsettings_mobspawncost = NaturalSpawner.getRoughBiome(blockpos, chunkaccess).getMobSettings().getMobSpawnCost(entitytype); ++ private boolean canSpawn(EntityType entityType, BlockPos pos, ChunkAccess chunk) { ++ this.lastCheckedPos = pos; ++ this.lastCheckedType = entityType; ++ MobSpawnSettings.MobSpawnCost biomesettingsmobs_b = NaturalSpawner.getRoughBiome(pos, chunk).getMobSettings().getMobSpawnCost(entityType); + +- if (mobspawnsettings_mobspawncost == null) { ++ if (biomesettingsmobs_b == null) { + this.lastCharge = 0.0D; + return true; + } else { +- double d0 = mobspawnsettings_mobspawncost.charge(); ++ double d0 = biomesettingsmobs_b.charge(); + + this.lastCharge = d0; +- double d1 = this.spawnPotential.getPotentialEnergyChange(blockpos, d0); ++ double d1 = this.spawnPotential.getPotentialEnergyChange(pos, d0); + +- return d1 <= mobspawnsettings_mobspawncost.energyBudget(); ++ return d1 <= biomesettingsmobs_b.energyBudget(); + } + } + +- private void afterSpawn(Mob mob, ChunkAccess chunkaccess) { +- EntityType entitytype = mob.getType(); +- BlockPos blockpos = mob.blockPosition(); ++ private void afterSpawn(Mob mob, ChunkAccess chunk) { ++ EntityType entitytypes = mob.getType(); ++ BlockPos blockposition = mob.blockPosition(); + double d0; + +- if (blockpos.equals(this.lastCheckedPos) && entitytype == this.lastCheckedType) { ++ if (blockposition.equals(this.lastCheckedPos) && entitytypes == this.lastCheckedType) { + d0 = this.lastCharge; + } else { +- MobSpawnSettings.MobSpawnCost mobspawnsettings_mobspawncost = NaturalSpawner.getRoughBiome(blockpos, chunkaccess).getMobSettings().getMobSpawnCost(entitytype); ++ MobSpawnSettings.MobSpawnCost biomesettingsmobs_b = NaturalSpawner.getRoughBiome(blockposition, chunk).getMobSettings().getMobSpawnCost(entitytypes); + +- if (mobspawnsettings_mobspawncost != null) { +- d0 = mobspawnsettings_mobspawncost.charge(); ++ if (biomesettingsmobs_b != null) { ++ d0 = biomesettingsmobs_b.charge(); + } else { + d0 = 0.0D; + } + } + +- this.spawnPotential.addCharge(blockpos, d0); +- MobCategory mobcategory = entitytype.getCategory(); ++ this.spawnPotential.addCharge(blockposition, d0); ++ MobCategory enumcreaturetype = entitytypes.getCategory(); + +- this.mobCategoryCounts.addTo(mobcategory, 1); +- this.localMobCapCalculator.addMob(new ChunkPos(blockpos), mobcategory); ++ this.mobCategoryCounts.addTo(enumcreaturetype, 1); ++ this.localMobCapCalculator.addMob(new ChunkPos(blockposition), enumcreaturetype); + } + + public int getSpawnableChunkCount() { +@@ -511,10 +536,12 @@ + return this.unmodifiableMobCategoryCounts; + } + +- boolean canSpawnForCategory(MobCategory mobcategory, ChunkPos chunkpos) { +- int i = mobcategory.getMaxInstancesPerChunk() * this.spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER; ++ // CraftBukkit start ++ boolean canSpawnForCategory(MobCategory enumcreaturetype, ChunkPos chunkcoordintpair, int limit) { ++ int i = limit * this.spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER; ++ // CraftBukkit end + +- return this.mobCategoryCounts.getInt(mobcategory) >= i ? false : this.localMobCapCalculator.canSpawn(mobcategory, chunkpos); ++ return this.mobCategoryCounts.getInt(enumcreaturetype) >= i ? false : this.localMobCapCalculator.canSpawn(enumcreaturetype, chunkcoordintpair); + } + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/ServerLevelAccessor.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/ServerLevelAccessor.java.patch new file mode 100644 index 0000000000..5318edb2bd --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/ServerLevelAccessor.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/level/ServerLevelAccessor.java ++++ b/net/minecraft/world/level/ServerLevelAccessor.java +@@ -8,6 +8,17 @@ + ServerLevel getLevel(); + + default void addFreshEntityWithPassengers(Entity entity) { +- entity.getSelfAndPassengers().forEach(this::addFreshEntity); ++ // CraftBukkit start ++ this.addFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); + } ++ ++ default void addFreshEntityWithPassengers(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ entity.getSelfAndPassengers().forEach((e) -> this.addFreshEntity(e, reason)); ++ } ++ ++ @Override ++ default ServerLevel getMinecraftWorld() { ++ return getLevel(); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/AbstractCandleBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/AbstractCandleBlock.java.patch new file mode 100644 index 0000000000..0c5e53e45a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/AbstractCandleBlock.java.patch @@ -0,0 +1,127 @@ +--- a/net/minecraft/world/level/block/AbstractCandleBlock.java ++++ b/net/minecraft/world/level/block/AbstractCandleBlock.java +@@ -17,7 +17,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.gameevent.GameEvent; +@@ -30,78 +30,79 @@ + public static final BooleanProperty LIT = BlockStateProperties.LIT; + + @Override +- @Override + protected abstract MapCodec codec(); + +- protected AbstractCandleBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ protected AbstractCandleBlock(BlockBehaviour.Properties properties) { ++ super(properties); + } + +- protected abstract Iterable getParticleOffsets(BlockState state); ++ protected abstract Iterable getParticleOffsets(IBlockData state); + +- public static boolean isLit(BlockState blockstate) { +- return blockstate.hasProperty(AbstractCandleBlock.LIT) && (blockstate.is(BlockTags.CANDLES) || blockstate.is(BlockTags.CANDLE_CAKES)) && (Boolean) blockstate.getValue(AbstractCandleBlock.LIT); ++ public static boolean isLit(IBlockData state) { ++ return state.hasProperty(AbstractCandleBlock.LIT) && (state.is(BlockTags.CANDLES) || state.is(BlockTags.CANDLE_CAKES)) && (Boolean) state.getValue(AbstractCandleBlock.LIT); + } + + @Override +- @Override +- public void onProjectileHit(Level level, BlockState blockstate, BlockHitResult blockhitresult, Projectile projectile) { +- if (!level.isClientSide && projectile.isOnFire() && this.canBeLit(blockstate)) { +- setLit(level, blockstate, blockhitresult.getBlockPos(), true); ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { ++ if (!level.isClientSide && projectile.isOnFire() && this.canBeLit(state)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, hit.getBlockPos(), projectile).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ setLit(level, state, hit.getBlockPos(), true); + } + + } + +- protected boolean canBeLit(BlockState blockstate) { +- return !(Boolean) blockstate.getValue(AbstractCandleBlock.LIT); ++ protected boolean canBeLit(IBlockData state) { ++ return !(Boolean) state.getValue(AbstractCandleBlock.LIT); + } + + @Override +- @Override +- public void animateTick(BlockState blockstate, Level level, BlockPos blockpos, RandomSource randomsource) { +- if ((Boolean) blockstate.getValue(AbstractCandleBlock.LIT)) { +- this.getParticleOffsets(blockstate).forEach((vec3) -> { +- addParticlesAndSound(level, vec3.add((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ()), randomsource); ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(AbstractCandleBlock.LIT)) { ++ this.getParticleOffsets(state).forEach((vec3d) -> { ++ addParticlesAndSound(level, vec3d.add((double) pos.getX(), (double) pos.getY(), (double) pos.getZ()), random); + }); + } + } + +- private static void addParticlesAndSound(Level level, Vec3 vec3, RandomSource randomsource) { +- float f = randomsource.nextFloat(); ++ private static void addParticlesAndSound(Level level, Vec3 offset, RandomSource random) { ++ float f = random.nextFloat(); + + if (f < 0.3F) { +- level.addParticle(ParticleTypes.SMOKE, vec3.x, vec3.y, vec3.z, 0.0D, 0.0D, 0.0D); ++ level.addParticle(ParticleTypes.SMOKE, offset.x, offset.y, offset.z, 0.0D, 0.0D, 0.0D); + if (f < 0.17F) { +- level.playLocalSound(vec3.x + 0.5D, vec3.y + 0.5D, vec3.z + 0.5D, SoundEvents.CANDLE_AMBIENT, SoundSource.BLOCKS, 1.0F + randomsource.nextFloat(), randomsource.nextFloat() * 0.7F + 0.3F, false); ++ level.playLocalSound(offset.x + 0.5D, offset.y + 0.5D, offset.z + 0.5D, SoundEvents.CANDLE_AMBIENT, SoundSource.BLOCKS, 1.0F + random.nextFloat(), random.nextFloat() * 0.7F + 0.3F, false); + } + } + +- level.addParticle(ParticleTypes.SMALL_FLAME, vec3.x, vec3.y, vec3.z, 0.0D, 0.0D, 0.0D); ++ level.addParticle(ParticleTypes.SMALL_FLAME, offset.x, offset.y, offset.z, 0.0D, 0.0D, 0.0D); + } + +- public static void extinguish(@Nullable Player player, BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos) { +- setLit(levelaccessor, blockstate, blockpos, false); +- if (blockstate.getBlock() instanceof AbstractCandleBlock) { +- ((AbstractCandleBlock) blockstate.getBlock()).getParticleOffsets(blockstate).forEach((vec3) -> { +- levelaccessor.addParticle(ParticleTypes.SMOKE, (double) blockpos.getX() + vec3.x(), (double) blockpos.getY() + vec3.y(), (double) blockpos.getZ() + vec3.z(), 0.0D, 0.10000000149011612D, 0.0D); ++ public static void extinguish(@Nullable Player player, IBlockData state, LevelAccessor level, BlockPos pos) { ++ setLit(level, state, pos, false); ++ if (state.getBlock() instanceof AbstractCandleBlock) { ++ ((AbstractCandleBlock) state.getBlock()).getParticleOffsets(state).forEach((vec3d) -> { ++ level.addParticle(ParticleTypes.SMOKE, (double) pos.getX() + vec3d.x(), (double) pos.getY() + vec3d.y(), (double) pos.getZ() + vec3d.z(), 0.0D, 0.10000000149011612D, 0.0D); + }); + } + +- levelaccessor.playSound((Player) null, blockpos, SoundEvents.CANDLE_EXTINGUISH, SoundSource.BLOCKS, 1.0F, 1.0F); +- levelaccessor.gameEvent((Entity) player, GameEvent.BLOCK_CHANGE, blockpos); ++ level.playSound((Player) null, pos, SoundEvents.CANDLE_EXTINGUISH, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.gameEvent((Entity) player, GameEvent.BLOCK_CHANGE, pos); + } + +- private static void setLit(LevelAccessor levelaccessor, BlockState blockstate, BlockPos blockpos, boolean flag) { +- levelaccessor.setBlock(blockpos, (BlockState) blockstate.setValue(AbstractCandleBlock.LIT, flag), 11); ++ private static void setLit(LevelAccessor level, IBlockData state, BlockPos pos, boolean lit) { ++ level.setBlock(pos, (IBlockData) state.setValue(AbstractCandleBlock.LIT, lit), 11); + } + + @Override +- @Override +- public void onExplosionHit(BlockState blockstate, Level level, BlockPos blockpos, Explosion explosion, BiConsumer biconsumer) { +- if (explosion.getBlockInteraction() == Explosion.BlockInteraction.TRIGGER_BLOCK && !level.isClientSide() && (Boolean) blockstate.getValue(AbstractCandleBlock.LIT)) { +- extinguish((Player) null, blockstate, level, blockpos); ++ public void onExplosionHit(IBlockData iblockdata, Level world, BlockPos blockposition, Explosion explosion, BiConsumer biconsumer) { ++ if (explosion.getBlockInteraction() == Explosion.Effect.TRIGGER_BLOCK && !world.isClientSide() && (Boolean) iblockdata.getValue(AbstractCandleBlock.LIT)) { ++ extinguish((Player) null, iblockdata, world, blockposition); + } + +- super.onExplosionHit(blockstate, level, blockpos, explosion, biconsumer); ++ super.onExplosionHit(iblockdata, world, blockposition, explosion, biconsumer); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BambooSaplingBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BambooSaplingBlock.java.patch new file mode 100644 index 0000000000..d4101bd137 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BambooSaplingBlock.java.patch @@ -0,0 +1,120 @@ +--- a/net/minecraft/world/level/block/BambooSaplingBlock.java ++++ b/net/minecraft/world/level/block/BambooSaplingBlock.java +@@ -15,7 +15,7 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BambooLeaves; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; +@@ -28,83 +28,73 @@ + protected static final VoxelShape SAPLING_SHAPE = Block.box(4.0D, 0.0D, 4.0D, 12.0D, 12.0D, 12.0D); + + @Override +- @Override + public MapCodec codec() { + return BambooSaplingBlock.CODEC; + } + +- public BambooSaplingBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ public BambooSaplingBlock(BlockBehaviour.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- Vec3 vec3 = blockstate.getOffset(blockgetter, blockpos); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ Vec3 vec3d = state.getOffset(level, pos); + +- return BambooSaplingBlock.SAPLING_SHAPE.move(vec3.x, vec3.y, vec3.z); ++ return BambooSaplingBlock.SAPLING_SHAPE.move(vec3d.x, vec3d.y, vec3d.z); + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (randomsource.nextInt(3) == 0 && serverlevel.isEmptyBlock(blockpos.above()) && serverlevel.getRawBrightness(blockpos.above(), 0) >= 9) { +- this.growBamboo(serverlevel, blockpos); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (random.nextInt(3) == 0 && level.isEmptyBlock(pos.above()) && level.getRawBrightness(pos.above(), 0) >= 9) { ++ this.growBamboo(level, pos); + } + + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- return levelreader.getBlockState(blockpos.below()).is(BlockTags.BAMBOO_PLANTABLE_ON); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ return level.getBlockState(pos.below()).is(BlockTags.BAMBOO_PLANTABLE_ON); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if (!blockstate.canSurvive(levelaccessor, blockpos)) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if (!state.canSurvive(level, currentPos)) { + return Blocks.AIR.defaultBlockState(); + } else { +- if (direction == Direction.UP && blockstate1.is(Blocks.BAMBOO)) { +- levelaccessor.setBlock(blockpos, Blocks.BAMBOO.defaultBlockState(), 2); ++ if (facing == Direction.UP && facingState.is(Blocks.BAMBOO)) { ++ level.setBlock(currentPos, Blocks.BAMBOO.defaultBlockState(), 2); + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + } + + @Override +- @Override +- public ItemStack getCloneItemStack(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { ++ public ItemStack getCloneItemStack(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { + return new ItemStack(Items.BAMBOO); + } + + @Override +- @Override +- public boolean isValidBonemealTarget(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { +- return levelreader.getBlockState(blockpos.above()).isAir(); ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ return iworldreader.getBlockState(blockposition.above()).isAir(); + } + + @Override +- @Override +- public boolean isBonemealSuccess(Level level, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return true; + } + + @Override +- @Override +- public void performBonemeal(ServerLevel serverlevel, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { +- this.growBamboo(serverlevel, blockpos); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ this.growBamboo(level, pos); + } + + @Override +- @Override +- public float getDestroyProgress(BlockState blockstate, Player player, BlockGetter blockgetter, BlockPos blockpos) { +- return player.getMainHandItem().getItem() instanceof SwordItem ? 1.0F : super.getDestroyProgress(blockstate, player, blockgetter, blockpos); ++ public float getDestroyProgress(IBlockData state, Player player, BlockGetter level, BlockPos pos) { ++ return player.getMainHandItem().getItem() instanceof SwordItem ? 1.0F : super.getDestroyProgress(state, player, level, pos); + } + +- protected void growBamboo(Level level, BlockPos blockpos) { +- level.setBlock(blockpos.above(), (BlockState) Blocks.BAMBOO.defaultBlockState().setValue(BambooStalkBlock.LEAVES, BambooLeaves.SMALL), 3); ++ protected void growBamboo(Level level, BlockPos state) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, state, state.above(), (IBlockData) Blocks.BAMBOO.defaultBlockState().setValue(BambooStalkBlock.LEAVES, BambooLeaves.SMALL), 3); // CraftBukkit - BlockSpreadEvent + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BambooStalkBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BambooStalkBlock.java.patch new file mode 100644 index 0000000000..af738d0119 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BambooStalkBlock.java.patch @@ -0,0 +1,330 @@ +--- a/net/minecraft/world/level/block/BambooStalkBlock.java ++++ b/net/minecraft/world/level/block/BambooStalkBlock.java +@@ -15,14 +15,14 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BambooLeaves; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.EnumProperty; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.level.material.FluidState; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; +@@ -46,79 +46,71 @@ + public static final int AGE_THICK_BAMBOO = 1; + + @Override +- @Override + public MapCodec codec() { + return BambooStalkBlock.CODEC; + } + +- public BambooStalkBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(BambooStalkBlock.AGE, 0)).setValue(BambooStalkBlock.LEAVES, BambooLeaves.NONE)).setValue(BambooStalkBlock.STAGE, 0)); ++ public BambooStalkBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(BambooStalkBlock.AGE, 0)).setValue(BambooStalkBlock.LEAVES, BambooLeaves.NONE)).setValue(BambooStalkBlock.STAGE, 0)); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(BambooStalkBlock.AGE, BambooStalkBlock.LEAVES, BambooStalkBlock.STAGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(BambooStalkBlock.AGE, BambooStalkBlock.LEAVES, BambooStalkBlock.STAGE); + } + + @Override +- @Override +- public boolean propagatesSkylightDown(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { ++ public boolean propagatesSkylightDown(IBlockData state, BlockGetter level, BlockPos pos) { + return true; + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- VoxelShape voxelshape = blockstate.getValue(BambooStalkBlock.LEAVES) == BambooLeaves.LARGE ? BambooStalkBlock.LARGE_SHAPE : BambooStalkBlock.SMALL_SHAPE; +- Vec3 vec3 = blockstate.getOffset(blockgetter, blockpos); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ VoxelShape voxelshape = state.getValue(BambooStalkBlock.LEAVES) == BambooLeaves.LARGE ? BambooStalkBlock.LARGE_SHAPE : BambooStalkBlock.SMALL_SHAPE; ++ Vec3 vec3d = state.getOffset(level, pos); + +- return voxelshape.move(vec3.x, vec3.y, vec3.z); ++ return voxelshape.move(vec3d.x, vec3d.y, vec3d.z); + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + + @Override +- @Override +- public VoxelShape getCollisionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- Vec3 vec3 = blockstate.getOffset(blockgetter, blockpos); ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ Vec3 vec3d = state.getOffset(level, pos); + +- return BambooStalkBlock.COLLISION_SHAPE.move(vec3.x, vec3.y, vec3.z); ++ return BambooStalkBlock.COLLISION_SHAPE.move(vec3d.x, vec3d.y, vec3d.z); + } + + @Override +- @Override +- public boolean isCollisionShapeFullBlock(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { ++ public boolean isCollisionShapeFullBlock(IBlockData state, BlockGetter level, BlockPos pos) { + return false; + } + + @Nullable + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- FluidState fluidstate = blockplacecontext.getLevel().getFluidState(blockplacecontext.getClickedPos()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ FluidState fluid = context.getLevel().getFluidState(context.getClickedPos()); + +- if (!fluidstate.isEmpty()) { ++ if (!fluid.isEmpty()) { + return null; + } else { +- BlockState blockstate = blockplacecontext.getLevel().getBlockState(blockplacecontext.getClickedPos().below()); ++ IBlockData iblockdata = context.getLevel().getBlockState(context.getClickedPos().below()); + +- if (blockstate.is(BlockTags.BAMBOO_PLANTABLE_ON)) { +- if (blockstate.is(Blocks.BAMBOO_SAPLING)) { +- return (BlockState) this.defaultBlockState().setValue(BambooStalkBlock.AGE, 0); +- } else if (blockstate.is(Blocks.BAMBOO)) { +- int i = (Integer) blockstate.getValue(BambooStalkBlock.AGE) > 0 ? 1 : 0; ++ if (iblockdata.is(BlockTags.BAMBOO_PLANTABLE_ON)) { ++ if (iblockdata.is(Blocks.BAMBOO_SAPLING)) { ++ return (IBlockData) this.defaultBlockState().setValue(BambooStalkBlock.AGE, 0); ++ } else if (iblockdata.is(Blocks.BAMBOO)) { ++ int i = (Integer) iblockdata.getValue(BambooStalkBlock.AGE) > 0 ? 1 : 0; + +- return (BlockState) this.defaultBlockState().setValue(BambooStalkBlock.AGE, i); ++ return (IBlockData) this.defaultBlockState().setValue(BambooStalkBlock.AGE, i); + } else { +- BlockState blockstate1 = blockplacecontext.getLevel().getBlockState(blockplacecontext.getClickedPos().above()); ++ IBlockData iblockdata1 = context.getLevel().getBlockState(context.getClickedPos().above()); + +- return blockstate1.is(Blocks.BAMBOO) ? (BlockState) this.defaultBlockState().setValue(BambooStalkBlock.AGE, (Integer) blockstate1.getValue(BambooStalkBlock.AGE)) : Blocks.BAMBOO_SAPLING.defaultBlockState(); ++ return iblockdata1.is(Blocks.BAMBOO) ? (IBlockData) this.defaultBlockState().setValue(BambooStalkBlock.AGE, (Integer) iblockdata1.getValue(BambooStalkBlock.AGE)) : Blocks.BAMBOO_SAPLING.defaultBlockState(); + } + } else { + return null; +@@ -127,29 +119,26 @@ + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (!blockstate.canSurvive(serverlevel, blockpos)) { +- serverlevel.destroyBlock(blockpos, true); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (!state.canSurvive(level, pos)) { ++ level.destroyBlock(pos, true); + } + + } + + @Override +- @Override +- public boolean isRandomlyTicking(BlockState blockstate) { +- return (Integer) blockstate.getValue(BambooStalkBlock.STAGE) == 0; ++ public boolean isRandomlyTicking(IBlockData state) { ++ return (Integer) state.getValue(BambooStalkBlock.STAGE) == 0; + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if ((Integer) blockstate.getValue(BambooStalkBlock.STAGE) == 0) { +- if (randomsource.nextInt(3) == 0 && serverlevel.isEmptyBlock(blockpos.above()) && serverlevel.getRawBrightness(blockpos.above(), 0) >= 9) { +- int i = this.getHeightBelowUpToMax(serverlevel, blockpos) + 1; ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Integer) state.getValue(BambooStalkBlock.STAGE) == 0) { ++ if (random.nextInt(3) == 0 && level.isEmptyBlock(pos.above()) && level.getRawBrightness(pos.above(), 0) >= 9) { ++ int i = this.getHeightBelowUpToMax(level, pos) + 1; + + if (i < 16) { +- this.growBamboo(blockstate, serverlevel, blockpos, randomsource, i); ++ this.growBamboo(state, level, pos, random, i); + } + } + +@@ -157,57 +146,52 @@ + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- return levelreader.getBlockState(blockpos.below()).is(BlockTags.BAMBOO_PLANTABLE_ON); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ return level.getBlockState(pos.below()).is(BlockTags.BAMBOO_PLANTABLE_ON); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if (!blockstate.canSurvive(levelaccessor, blockpos)) { +- levelaccessor.scheduleTick(blockpos, (Block) this, 1); ++ public IBlockData updateShape(IBlockData state, Direction direction, IBlockData neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { ++ if (!state.canSurvive(level, pos)) { ++ level.scheduleTick(pos, (Block) this, 1); + } + +- if (direction == Direction.UP && blockstate1.is(Blocks.BAMBOO) && (Integer) blockstate1.getValue(BambooStalkBlock.AGE) > (Integer) blockstate.getValue(BambooStalkBlock.AGE)) { +- levelaccessor.setBlock(blockpos, (BlockState) blockstate.cycle(BambooStalkBlock.AGE), 2); ++ if (direction == Direction.UP && neighborState.is(Blocks.BAMBOO) && (Integer) neighborState.getValue(BambooStalkBlock.AGE) > (Integer) state.getValue(BambooStalkBlock.AGE)) { ++ level.setBlock(pos, (IBlockData) state.cycle(BambooStalkBlock.AGE), 2); + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, direction, neighborState, level, pos, neighborPos); + } + + @Override +- @Override +- public boolean isValidBonemealTarget(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { +- int i = this.getHeightAboveUpToMax(levelreader, blockpos); +- int j = this.getHeightBelowUpToMax(levelreader, blockpos); ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ int i = this.getHeightAboveUpToMax(iworldreader, blockposition); ++ int j = this.getHeightBelowUpToMax(iworldreader, blockposition); + +- return i + j + 1 < 16 && (Integer) levelreader.getBlockState(blockpos.above(i)).getValue(BambooStalkBlock.STAGE) != 1; ++ return i + j + 1 < 16 && (Integer) iworldreader.getBlockState(blockposition.above(i)).getValue(BambooStalkBlock.STAGE) != 1; + } + + @Override +- @Override +- public boolean isBonemealSuccess(Level level, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return true; + } + + @Override +- @Override +- public void performBonemeal(ServerLevel serverlevel, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { +- int i = this.getHeightAboveUpToMax(serverlevel, blockpos); +- int j = this.getHeightBelowUpToMax(serverlevel, blockpos); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ int i = this.getHeightAboveUpToMax(level, pos); ++ int j = this.getHeightBelowUpToMax(level, pos); + int k = i + j + 1; +- int l = 1 + randomsource.nextInt(2); ++ int l = 1 + random.nextInt(2); + + for (int i1 = 0; i1 < l; ++i1) { +- BlockPos blockpos1 = blockpos.above(i); +- BlockState blockstate1 = serverlevel.getBlockState(blockpos1); ++ BlockPos blockposition1 = pos.above(i); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + +- if (k >= 16 || (Integer) blockstate1.getValue(BambooStalkBlock.STAGE) == 1 || !serverlevel.isEmptyBlock(blockpos1.above())) { ++ if (k >= 16 || !iblockdata1.is(Blocks.BAMBOO) || (Integer) iblockdata1.getValue(BambooStalkBlock.STAGE) == 1 || !level.isEmptyBlock(blockposition1.above())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here + return; + } + +- this.growBamboo(blockstate1, serverlevel, blockpos1, randomsource, k); ++ this.growBamboo(iblockdata1, level, blockposition1, random, k); + ++i; + ++k; + } +@@ -215,51 +199,61 @@ + } + + @Override +- @Override +- public float getDestroyProgress(BlockState blockstate, Player player, BlockGetter blockgetter, BlockPos blockpos) { +- return player.getMainHandItem().getItem() instanceof SwordItem ? 1.0F : super.getDestroyProgress(blockstate, player, blockgetter, blockpos); ++ public float getDestroyProgress(IBlockData state, Player player, BlockGetter level, BlockPos pos) { ++ return player.getMainHandItem().getItem() instanceof SwordItem ? 1.0F : super.getDestroyProgress(state, player, level, pos); + } + +- protected void growBamboo(BlockState blockstate, Level level, BlockPos blockpos, RandomSource randomsource, int i) { +- BlockState blockstate1 = level.getBlockState(blockpos.below()); +- BlockPos blockpos1 = blockpos.below(2); +- BlockState blockstate2 = level.getBlockState(blockpos1); +- BambooLeaves bambooleaves = BambooLeaves.NONE; ++ protected void growBamboo(IBlockData state, Level level, BlockPos pos, RandomSource random, int age) { ++ IBlockData iblockdata1 = level.getBlockState(pos.below()); ++ BlockPos blockposition1 = pos.below(2); ++ IBlockData iblockdata2 = level.getBlockState(blockposition1); ++ BambooLeaves blockpropertybamboosize = BambooLeaves.NONE; ++ boolean shouldUpdateOthers = false; // CraftBukkit + +- if (i >= 1) { +- if (blockstate1.is(Blocks.BAMBOO) && blockstate1.getValue(BambooStalkBlock.LEAVES) != BambooLeaves.NONE) { +- if (blockstate1.is(Blocks.BAMBOO) && blockstate1.getValue(BambooStalkBlock.LEAVES) != BambooLeaves.NONE) { +- bambooleaves = BambooLeaves.LARGE; +- if (blockstate2.is(Blocks.BAMBOO)) { +- level.setBlock(blockpos.below(), (BlockState) blockstate1.setValue(BambooStalkBlock.LEAVES, BambooLeaves.SMALL), 3); +- level.setBlock(blockpos1, (BlockState) blockstate2.setValue(BambooStalkBlock.LEAVES, BambooLeaves.NONE), 3); ++ if (age >= 1) { ++ if (iblockdata1.is(Blocks.BAMBOO) && iblockdata1.getValue(BambooStalkBlock.LEAVES) != BambooLeaves.NONE) { ++ if (iblockdata1.is(Blocks.BAMBOO) && iblockdata1.getValue(BambooStalkBlock.LEAVES) != BambooLeaves.NONE) { ++ blockpropertybamboosize = BambooLeaves.LARGE; ++ if (iblockdata2.is(Blocks.BAMBOO)) { ++ // CraftBukkit start - moved down ++ // world.setBlock(blockposition.below(), (IBlockData) iblockdata1.setValue(BlockBamboo.LEAVES, BlockPropertyBambooSize.SMALL), 3); ++ // world.setBlock(blockposition1, (IBlockData) iblockdata2.setValue(BlockBamboo.LEAVES, BlockPropertyBambooSize.NONE), 3); ++ shouldUpdateOthers = true; ++ // CraftBukkit end + } + } + } else { +- bambooleaves = BambooLeaves.SMALL; ++ blockpropertybamboosize = BambooLeaves.SMALL; + } + } + +- int j = (Integer) blockstate.getValue(BambooStalkBlock.AGE) != 1 && !blockstate2.is(Blocks.BAMBOO) ? 0 : 1; +- int k = (i < 11 || randomsource.nextFloat() >= 0.25F) && i != 15 ? 0 : 1; ++ int j = (Integer) state.getValue(BambooStalkBlock.AGE) != 1 && !iblockdata2.is(Blocks.BAMBOO) ? 0 : 1; ++ int k = (age < 11 || random.nextFloat() >= 0.25F) && age != 15 ? 0 : 1; + +- level.setBlock(blockpos.above(), (BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(BambooStalkBlock.AGE, j)).setValue(BambooStalkBlock.LEAVES, bambooleaves)).setValue(BambooStalkBlock.STAGE, k), 3); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, pos.above(), (IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(BambooStalkBlock.AGE, j)).setValue(BambooStalkBlock.LEAVES, blockpropertybamboosize)).setValue(BambooStalkBlock.STAGE, k), 3)) { ++ if (shouldUpdateOthers) { ++ level.setBlock(pos.below(), (IBlockData) iblockdata1.setValue(BambooStalkBlock.LEAVES, BambooLeaves.SMALL), 3); ++ level.setBlock(blockposition1, (IBlockData) iblockdata2.setValue(BambooStalkBlock.LEAVES, BambooLeaves.NONE), 3); ++ } ++ } ++ // CraftBukkit end + } + +- protected int getHeightAboveUpToMax(BlockGetter blockgetter, BlockPos blockpos) { ++ protected int getHeightAboveUpToMax(BlockGetter level, BlockPos pos) { + int i; + +- for (i = 0; i < 16 && blockgetter.getBlockState(blockpos.above(i + 1)).is(Blocks.BAMBOO); ++i) { ++ for (i = 0; i < 16 && level.getBlockState(pos.above(i + 1)).is(Blocks.BAMBOO); ++i) { + ; + } + + return i; + } + +- protected int getHeightBelowUpToMax(BlockGetter blockgetter, BlockPos blockpos) { ++ protected int getHeightBelowUpToMax(BlockGetter level, BlockPos pos) { + int i; + +- for (i = 0; i < 16 && blockgetter.getBlockState(blockpos.below(i + 1)).is(Blocks.BAMBOO); ++i) { ++ for (i = 0; i < 16 && level.getBlockState(pos.below(i + 1)).is(Blocks.BAMBOO); ++i) { + ; + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BaseFireBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BaseFireBlock.java.patch new file mode 100644 index 0000000000..ec81b5847a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BaseFireBlock.java.patch @@ -0,0 +1,280 @@ +--- a/net/minecraft/world/level/block/BaseFireBlock.java ++++ b/net/minecraft/world/level/block/BaseFireBlock.java +@@ -14,7 +14,7 @@ + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.portal.PortalShape; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; +@@ -26,126 +26,127 @@ + protected static final float AABB_OFFSET = 1.0F; + protected static final VoxelShape DOWN_AABB = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 1.0D, 16.0D); + +- public BaseFireBlock(BlockBehaviour.Properties blockbehaviour_properties, float f) { +- super(blockbehaviour_properties); +- this.fireDamage = f; ++ public BaseFireBlock(BlockBehaviour.Properties properties, float fireDamage) { ++ super(properties); ++ this.fireDamage = fireDamage; + } + + @Override +- @Override + protected abstract MapCodec codec(); + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- return getState(blockplacecontext.getLevel(), blockplacecontext.getClickedPos()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return getState(context.getLevel(), context.getClickedPos()); + } + +- public static BlockState getState(BlockGetter blockgetter, BlockPos blockpos) { +- BlockPos blockpos1 = blockpos.below(); +- BlockState blockstate = blockgetter.getBlockState(blockpos1); ++ public static IBlockData getState(BlockGetter reader, BlockPos pos) { ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata = reader.getBlockState(blockposition1); + +- return SoulFireBlock.canSurviveOnBlock(blockstate) ? Blocks.SOUL_FIRE.defaultBlockState() : ((FireBlock) Blocks.FIRE).getStateForPlacement(blockgetter, blockpos); ++ return SoulFireBlock.canSurviveOnBlock(iblockdata) ? Blocks.SOUL_FIRE.defaultBlockState() : ((FireBlock) Blocks.FIRE).getStateForPlacement(reader, pos); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return BaseFireBlock.DOWN_AABB; + } + + @Override +- @Override +- public void animateTick(BlockState blockstate, Level level, BlockPos blockpos, RandomSource randomsource) { +- if (randomsource.nextInt(24) == 0) { +- level.playLocalSound((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D, SoundEvents.FIRE_AMBIENT, SoundSource.BLOCKS, 1.0F + randomsource.nextFloat(), randomsource.nextFloat() * 0.7F + 0.3F, false); ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if (random.nextInt(24) == 0) { ++ level.playLocalSound((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.FIRE_AMBIENT, SoundSource.BLOCKS, 1.0F + random.nextFloat(), random.nextFloat() * 0.7F + 0.3F, false); + } + +- BlockPos blockpos1 = blockpos.below(); +- BlockState blockstate1 = level.getBlockState(blockpos1); ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + double d0; + double d1; + double d2; + int i; + +- if (!this.canBurn(blockstate1) && !blockstate1.isFaceSturdy(level, blockpos1, Direction.UP)) { +- if (this.canBurn(level.getBlockState(blockpos.west()))) { ++ if (!this.canBurn(iblockdata1) && !iblockdata1.isFaceSturdy(level, blockposition1, Direction.UP)) { ++ if (this.canBurn(level.getBlockState(pos.west()))) { + for (i = 0; i < 2; ++i) { +- d0 = (double) blockpos.getX() + randomsource.nextDouble() * 0.10000000149011612D; +- d1 = (double) blockpos.getY() + randomsource.nextDouble(); +- d2 = (double) blockpos.getZ() + randomsource.nextDouble(); ++ d0 = (double) pos.getX() + random.nextDouble() * 0.10000000149011612D; ++ d1 = (double) pos.getY() + random.nextDouble(); ++ d2 = (double) pos.getZ() + random.nextDouble(); + level.addParticle(ParticleTypes.LARGE_SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + } + +- if (this.canBurn(level.getBlockState(blockpos.east()))) { ++ if (this.canBurn(level.getBlockState(pos.east()))) { + for (i = 0; i < 2; ++i) { +- d0 = (double) (blockpos.getX() + 1) - randomsource.nextDouble() * 0.10000000149011612D; +- d1 = (double) blockpos.getY() + randomsource.nextDouble(); +- d2 = (double) blockpos.getZ() + randomsource.nextDouble(); ++ d0 = (double) (pos.getX() + 1) - random.nextDouble() * 0.10000000149011612D; ++ d1 = (double) pos.getY() + random.nextDouble(); ++ d2 = (double) pos.getZ() + random.nextDouble(); + level.addParticle(ParticleTypes.LARGE_SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + } + +- if (this.canBurn(level.getBlockState(blockpos.north()))) { ++ if (this.canBurn(level.getBlockState(pos.north()))) { + for (i = 0; i < 2; ++i) { +- d0 = (double) blockpos.getX() + randomsource.nextDouble(); +- d1 = (double) blockpos.getY() + randomsource.nextDouble(); +- d2 = (double) blockpos.getZ() + randomsource.nextDouble() * 0.10000000149011612D; ++ d0 = (double) pos.getX() + random.nextDouble(); ++ d1 = (double) pos.getY() + random.nextDouble(); ++ d2 = (double) pos.getZ() + random.nextDouble() * 0.10000000149011612D; + level.addParticle(ParticleTypes.LARGE_SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + } + +- if (this.canBurn(level.getBlockState(blockpos.south()))) { ++ if (this.canBurn(level.getBlockState(pos.south()))) { + for (i = 0; i < 2; ++i) { +- d0 = (double) blockpos.getX() + randomsource.nextDouble(); +- d1 = (double) blockpos.getY() + randomsource.nextDouble(); +- d2 = (double) (blockpos.getZ() + 1) - randomsource.nextDouble() * 0.10000000149011612D; ++ d0 = (double) pos.getX() + random.nextDouble(); ++ d1 = (double) pos.getY() + random.nextDouble(); ++ d2 = (double) (pos.getZ() + 1) - random.nextDouble() * 0.10000000149011612D; + level.addParticle(ParticleTypes.LARGE_SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + } + +- if (this.canBurn(level.getBlockState(blockpos.above()))) { ++ if (this.canBurn(level.getBlockState(pos.above()))) { + for (i = 0; i < 2; ++i) { +- d0 = (double) blockpos.getX() + randomsource.nextDouble(); +- d1 = (double) (blockpos.getY() + 1) - randomsource.nextDouble() * 0.10000000149011612D; +- d2 = (double) blockpos.getZ() + randomsource.nextDouble(); ++ d0 = (double) pos.getX() + random.nextDouble(); ++ d1 = (double) (pos.getY() + 1) - random.nextDouble() * 0.10000000149011612D; ++ d2 = (double) pos.getZ() + random.nextDouble(); + level.addParticle(ParticleTypes.LARGE_SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + } + } else { + for (i = 0; i < 3; ++i) { +- d0 = (double) blockpos.getX() + randomsource.nextDouble(); +- d1 = (double) blockpos.getY() + randomsource.nextDouble() * 0.5D + 0.5D; +- d2 = (double) blockpos.getZ() + randomsource.nextDouble(); ++ d0 = (double) pos.getX() + random.nextDouble(); ++ d1 = (double) pos.getY() + random.nextDouble() * 0.5D + 0.5D; ++ d2 = (double) pos.getZ() + random.nextDouble(); + level.addParticle(ParticleTypes.LARGE_SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + } + + } + +- protected abstract boolean canBurn(BlockState state); ++ protected abstract boolean canBurn(IBlockData state); + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { + if (!entity.fireImmune()) { + entity.setRemainingFireTicks(entity.getRemainingFireTicks() + 1); + if (entity.getRemainingFireTicks() == 0) { +- entity.setSecondsOnFire(8); ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityCombustEvent event = new org.bukkit.event.entity.EntityCombustByBlockEvent(org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), entity.getBukkitEntity(), 8); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ entity.setSecondsOnFire(event.getDuration(), false); ++ } ++ // CraftBukkit end + } + } + + entity.hurt(level.damageSources().inFire(), this.fireDamage); +- super.entityInside(blockstate, level, blockpos, entity); ++ super.entityInside(state, level, pos, entity); + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!blockstate1.is(blockstate.getBlock())) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ if (!oldState.is(state.getBlock())) { + if (inPortalDimension(level)) { +- Optional optional = PortalShape.findEmptyPortalShape(level, blockpos, Direction.Axis.X); ++ Optional optional = PortalShape.findEmptyPortalShape(level, pos, Direction.Axis.X); + + if (optional.isPresent()) { + ((PortalShape) optional.get()).createPortalBlocks(); +@@ -153,50 +154,48 @@ + } + } + +- if (!blockstate.canSurvive(level, blockpos)) { +- level.removeBlock(blockpos, false); ++ if (!state.canSurvive(level, pos)) { ++ fireExtinguished(level, pos); // CraftBukkit - fuel block broke + } + + } + } + + private static boolean inPortalDimension(Level level) { +- return level.dimension() == Level.OVERWORLD || level.dimension() == Level.NETHER; ++ return level.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.OVERWORLD || level.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.NETHER; // CraftBukkit - getTypeKey() + } + + @Override +- @Override +- protected void spawnDestroyParticles(Level level, Player player, BlockPos blockpos, BlockState blockstate) {} ++ protected void spawnDestroyParticles(Level level, Player player, BlockPos pos, IBlockData state) {} + + @Override +- @Override +- public BlockState playerWillDestroy(Level level, BlockPos blockpos, BlockState blockstate, Player player) { +- if (!level.isClientSide()) { +- level.levelEvent((Player) null, 1009, blockpos, 0); ++ public IBlockData playerWillDestroy(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ if (!world.isClientSide()) { ++ world.levelEvent((Player) null, 1009, blockposition, 0); + } + +- return super.playerWillDestroy(level, blockpos, blockstate, player); ++ return super.playerWillDestroy(world, blockposition, iblockdata, entityhuman); + } + +- public static boolean canBePlacedAt(Level level, BlockPos blockpos, Direction direction) { +- BlockState blockstate = level.getBlockState(blockpos); ++ public static boolean canBePlacedAt(Level level, BlockPos pos, Direction direction) { ++ IBlockData iblockdata = level.getBlockState(pos); + +- return !blockstate.isAir() ? false : getState(level, blockpos).canSurvive(level, blockpos) || isPortal(level, blockpos, direction); ++ return !iblockdata.isAir() ? false : getState(level, pos).canSurvive(level, pos) || isPortal(level, pos, direction); + } + +- private static boolean isPortal(Level level, BlockPos blockpos, Direction direction) { ++ private static boolean isPortal(Level level, BlockPos pos, Direction direction) { + if (!inPortalDimension(level)) { + return false; + } else { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = blockpos.mutable(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); + boolean flag = false; +- Direction[] adirection = Direction.values(); +- int i = adirection.length; ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction1 = adirection[j]; ++ Direction enumdirection1 = aenumdirection[j]; + +- if (level.getBlockState(blockpos_mutableblockpos.set(blockpos).move(direction1)).is(Blocks.OBSIDIAN)) { ++ if (level.getBlockState(blockposition_mutableblockposition.set(pos).move(enumdirection1)).is(Blocks.OBSIDIAN)) { + flag = true; + break; + } +@@ -205,10 +204,18 @@ + if (!flag) { + return false; + } else { +- Direction.Axis direction_axis = direction.getAxis().isHorizontal() ? direction.getCounterClockWise().getAxis() : Direction.Plane.HORIZONTAL.getRandomAxis(level.random); ++ Direction.Axis enumdirection_enumaxis = direction.getAxis().isHorizontal() ? direction.getCounterClockWise().getAxis() : Direction.Plane.HORIZONTAL.getRandomAxis(level.random); + +- return PortalShape.findEmptyPortalShape(level, blockpos, direction_axis).isPresent(); ++ return PortalShape.findEmptyPortalShape(level, pos, enumdirection_enumaxis).isPresent(); + } + } + } ++ ++ // CraftBukkit start ++ protected void fireExtinguished(net.minecraft.world.level.LevelAccessor world, BlockPos position) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, position, Blocks.AIR.defaultBlockState()).isCancelled()) { ++ world.removeBlock(position, false); ++ } ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BasePressurePlateBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BasePressurePlateBlock.java.patch new file mode 100644 index 0000000000..771b25481b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BasePressurePlateBlock.java.patch @@ -0,0 +1,225 @@ +--- a/net/minecraft/world/level/block/BasePressurePlateBlock.java ++++ b/net/minecraft/world/level/block/BasePressurePlateBlock.java +@@ -15,12 +15,13 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockSetType; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public abstract class BasePressurePlateBlock extends Block { + +@@ -29,19 +30,17 @@ + protected static final AABB TOUCH_AABB = new AABB(0.0625D, 0.0D, 0.0625D, 0.9375D, 0.25D, 0.9375D); + protected final BlockSetType type; + +- protected BasePressurePlateBlock(BlockBehaviour.Properties blockbehaviour_properties, BlockSetType blocksettype) { +- super(blockbehaviour_properties.sound(blocksettype.soundType())); +- this.type = blocksettype; ++ protected BasePressurePlateBlock(BlockBehaviour.Properties properties, BlockSetType type) { ++ super(properties.sound(type.soundType())); ++ this.type = type; + } + + @Override +- @Override + protected abstract MapCodec codec(); + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return this.getSignalForState(blockstate) > 0 ? BasePressurePlateBlock.PRESSED_AABB : BasePressurePlateBlock.AABB; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return this.getSignalForState(state) > 0 ? BasePressurePlateBlock.PRESSED_AABB : BasePressurePlateBlock.AABB; + } + + protected int getPressedTime() { +@@ -49,120 +48,130 @@ + } + + @Override +- @Override +- public boolean isPossibleToRespawnInThis(BlockState blockstate) { ++ public boolean isPossibleToRespawnInThis(IBlockData state) { + return true; + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- return direction == Direction.DOWN && !blockstate.canSurvive(levelaccessor, blockpos) ? Blocks.AIR.defaultBlockState() : super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ return facing == Direction.DOWN && !state.canSurvive(level, currentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- BlockPos blockpos1 = blockpos.below(); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.below(); + +- return canSupportRigidBlock(levelreader, blockpos1) || canSupportCenter(levelreader, blockpos1, Direction.UP); ++ return canSupportRigidBlock(level, blockposition1) || canSupportCenter(level, blockposition1, Direction.UP); + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- int i = this.getSignalForState(blockstate); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ int i = this.getSignalForState(state); + + if (i > 0) { +- this.checkPressed((Entity) null, serverlevel, blockpos, blockstate, i); ++ this.checkPressed((Entity) null, level, pos, state, i); + } + + } + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { + if (!level.isClientSide) { +- int i = this.getSignalForState(blockstate); ++ int i = this.getSignalForState(state); + + if (i == 0) { +- this.checkPressed(entity, level, blockpos, blockstate, i); ++ this.checkPressed(entity, level, pos, state, i); + } + + } + } + +- private void checkPressed(@Nullable Entity entity, Level level, BlockPos blockpos, BlockState blockstate, int i) { +- int j = this.getSignalStrength(level, blockpos); +- boolean flag = i > 0; ++ private void checkPressed(@Nullable Entity entity, Level level, BlockPos pos, IBlockData state, int currentSignal) { ++ int j = this.getSignalStrength(level, pos); ++ boolean flag = currentSignal > 0; + boolean flag1 = j > 0; + +- if (i != j) { +- BlockState blockstate1 = this.setSignalForState(blockstate, j); ++ // CraftBukkit start - Interact Pressure Plate ++ org.bukkit.World bworld = level.getWorld(); ++ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager(); + +- level.setBlock(blockpos, blockstate1, 2); +- this.updateNeighbours(level, blockpos); +- level.setBlocksDirty(blockpos, blockstate, blockstate1); ++ if (flag != flag1) { ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), currentSignal, j); ++ manager.callEvent(eventRedstone); ++ ++ flag1 = eventRedstone.getNewCurrent() > 0; ++ j = eventRedstone.getNewCurrent(); + } ++ // CraftBukkit end + ++ if (currentSignal != j) { ++ IBlockData iblockdata1 = this.setSignalForState(state, j); ++ ++ level.setBlock(pos, iblockdata1, 2); ++ this.updateNeighbours(level, pos); ++ level.setBlocksDirty(pos, state, iblockdata1); ++ } ++ + if (!flag1 && flag) { +- level.playSound((Player) null, blockpos, this.type.pressurePlateClickOff(), SoundSource.BLOCKS); +- level.gameEvent(entity, GameEvent.BLOCK_DEACTIVATE, blockpos); ++ level.playSound((Player) null, pos, this.type.pressurePlateClickOff(), SoundSource.BLOCKS); ++ level.gameEvent(entity, GameEvent.BLOCK_DEACTIVATE, pos); + } else if (flag1 && !flag) { +- level.playSound((Player) null, blockpos, this.type.pressurePlateClickOn(), SoundSource.BLOCKS); +- level.gameEvent(entity, GameEvent.BLOCK_ACTIVATE, blockpos); ++ level.playSound((Player) null, pos, this.type.pressurePlateClickOn(), SoundSource.BLOCKS); ++ level.gameEvent(entity, GameEvent.BLOCK_ACTIVATE, pos); + } + + if (flag1) { +- level.scheduleTick(new BlockPos(blockpos), (Block) this, this.getPressedTime()); ++ level.scheduleTick(new BlockPos(pos), (Block) this, this.getPressedTime()); + } + + } + + @Override +- @Override +- public void onRemove(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!flag && !blockstate.is(blockstate1.getBlock())) { +- if (this.getSignalForState(blockstate) > 0) { +- this.updateNeighbours(level, blockpos); ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { ++ if (!isMoving && !state.is(newState.getBlock())) { ++ if (this.getSignalForState(state) > 0) { ++ this.updateNeighbours(level, pos); + } + +- super.onRemove(blockstate, level, blockpos, blockstate1, flag); ++ super.onRemove(state, level, pos, newState, isMoving); + } + } + +- protected void updateNeighbours(Level level, BlockPos blockpos) { +- level.updateNeighborsAt(blockpos, this); +- level.updateNeighborsAt(blockpos.below(), this); ++ protected void updateNeighbours(Level level, BlockPos pos) { ++ level.updateNeighborsAt(pos, this); ++ level.updateNeighborsAt(pos.below(), this); + } + + @Override +- @Override +- public int getSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return this.getSignalForState(blockstate); ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return this.getSignalForState(blockState); + } + + @Override +- @Override +- public int getDirectSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return direction == Direction.UP ? this.getSignalForState(blockstate) : 0; ++ public int getDirectSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return side == Direction.UP ? this.getSignalForState(blockState) : 0; + } + + @Override +- @Override +- public boolean isSignalSource(BlockState blockstate) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + +- protected static int getEntityCount(Level level, AABB aabb, Class oclass) { +- return level.getEntitiesOfClass(oclass, aabb, EntitySelector.NO_SPECTATORS.and((entity) -> { ++ protected static int getEntityCount(Level level, AABB box, Class entityClass) { ++ // CraftBukkit start ++ return getEntities(level, box, entityClass).size(); ++ } ++ ++ protected static java.util.List getEntities(Level world, AABB axisalignedbb, Class oclass) { ++ // CraftBukkit end ++ return world.getEntitiesOfClass(oclass, axisalignedbb, EntitySelector.NO_SPECTATORS.and((entity) -> { + return !entity.isIgnoringBlockTriggers(); +- })).size(); ++ })); // CraftBukkit + } + + protected abstract int getSignalStrength(Level level, BlockPos pos); + +- protected abstract int getSignalForState(BlockState state); ++ protected abstract int getSignalForState(IBlockData state); + +- protected abstract BlockState setSignalForState(BlockState state, int signal); ++ protected abstract IBlockData setSignalForState(IBlockData state, int signal); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BedBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BedBlock.java.patch new file mode 100644 index 0000000000..409184cf75 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BedBlock.java.patch @@ -0,0 +1,478 @@ +--- a/net/minecraft/world/level/block/BedBlock.java ++++ b/net/minecraft/world/level/block/BedBlock.java +@@ -9,7 +9,7 @@ + import net.minecraft.core.Direction; + import net.minecraft.network.chat.Component; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +@@ -28,13 +28,13 @@ + import net.minecraft.world.level.block.entity.BedBlockEntity; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BedPart; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.block.state.properties.EnumProperty; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; +@@ -64,60 +64,68 @@ + private final DyeColor color; + + @Override +- @Override + public MapCodec codec() { + return BedBlock.CODEC; + } + +- public BedBlock(DyeColor dyecolor, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.color = dyecolor; +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(BedBlock.PART, BedPart.FOOT)).setValue(BedBlock.OCCUPIED, false)); ++ public BedBlock(DyeColor color, BlockBehaviour.Properties properties) { ++ super(properties); ++ this.color = color; ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(BedBlock.PART, BedPart.FOOT)).setValue(BedBlock.OCCUPIED, false)); + } + + @Nullable +- public static Direction getBedOrientation(BlockGetter blockgetter, BlockPos blockpos) { +- BlockState blockstate = blockgetter.getBlockState(blockpos); ++ public static Direction getBedOrientation(BlockGetter level, BlockPos pos) { ++ IBlockData iblockdata = level.getBlockState(pos); + +- return blockstate.getBlock() instanceof BedBlock ? (Direction) blockstate.getValue(BedBlock.FACING) : null; ++ return iblockdata.getBlock() instanceof BedBlock ? (Direction) iblockdata.getValue(BedBlock.FACING) : null; + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + if (level.isClientSide) { + return InteractionResult.CONSUME; + } else { +- if (blockstate.getValue(BedBlock.PART) != BedPart.HEAD) { +- blockpos = blockpos.relative((Direction) blockstate.getValue(BedBlock.FACING)); +- blockstate = level.getBlockState(blockpos); +- if (!blockstate.is((Block) this)) { ++ if (state.getValue(BedBlock.PART) != BedPart.HEAD) { ++ pos = pos.relative((Direction) state.getValue(BedBlock.FACING)); ++ state = level.getBlockState(pos); ++ if (!state.is((Block) this)) { + return InteractionResult.CONSUME; + } + } + +- if (!canSetSpawn(level)) { +- level.removeBlock(blockpos, false); +- BlockPos blockpos1 = blockpos.relative(((Direction) blockstate.getValue(BedBlock.FACING)).getOpposite()); ++ // CraftBukkit - moved world and biome check into EntityHuman ++ if (false && !canSetSpawn(level)) { ++ level.removeBlock(pos, false); ++ BlockPos blockposition1 = pos.relative(((Direction) state.getValue(BedBlock.FACING)).getOpposite()); + +- if (level.getBlockState(blockpos1).is((Block) this)) { +- level.removeBlock(blockpos1, false); ++ if (level.getBlockState(blockposition1).is((Block) this)) { ++ level.removeBlock(blockposition1, false); + } + +- Vec3 vec3 = blockpos.getCenter(); ++ Vec3 vec3d = pos.getCenter(); + +- level.explode((Entity) null, level.damageSources().badRespawnPointExplosion(vec3), (ExplosionDamageCalculator) null, vec3, 5.0F, true, Level.ExplosionInteraction.BLOCK); ++ level.explode((Entity) null, level.damageSources().badRespawnPointExplosion(vec3d), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.a.BLOCK); + return InteractionResult.SUCCESS; +- } else if ((Boolean) blockstate.getValue(BedBlock.OCCUPIED)) { +- if (!this.kickVillagerOutOfBed(level, blockpos)) { ++ } else if ((Boolean) state.getValue(BedBlock.OCCUPIED)) { ++ if (!this.kickVillagerOutOfBed(level, pos)) { + player.displayClientMessage(Component.translatable("block.minecraft.bed.occupied"), true); + } + + return InteractionResult.SUCCESS; + } else { +- player.startSleepInBed(blockpos).ifLeft((player_bedsleepingproblem) -> { +- if (player_bedsleepingproblem.getMessage() != null) { +- player.displayClientMessage(player_bedsleepingproblem.getMessage(), true); ++ // CraftBukkit start ++ IBlockData finaliblockdata = state; ++ BlockPos finalblockposition = pos; ++ // CraftBukkit end ++ player.startSleepInBed(pos).ifLeft((entityhuman_enumbedresult) -> { ++ // CraftBukkit start - handling bed explosion from below here ++ if (!level.dimensionType().bedWorks()) { ++ this.explodeBed(finaliblockdata, level, finalblockposition); ++ } else ++ // CraftBukkit end ++ if (entityhuman_enumbedresult.getMessage() != null) { ++ player.displayClientMessage(entityhuman_enumbedresult.getMessage(), true); + } + + }); +@@ -126,12 +134,33 @@ + } + } + ++ // CraftBukkit start ++ private InteractionResult explodeBed(IBlockData iblockdata, Level world, BlockPos blockposition) { ++ { ++ { ++ world.removeBlock(blockposition, false); ++ BlockPos blockposition1 = blockposition.relative(((Direction) iblockdata.getValue(BedBlock.FACING)).getOpposite()); ++ ++ if (world.getBlockState(blockposition1).getBlock() == this) { ++ world.removeBlock(blockposition1, false); ++ } ++ ++ Vec3 vec3d = blockposition.getCenter(); ++ ++ world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.a.BLOCK); ++ return InteractionResult.SUCCESS; ++ } ++ } ++ } ++ // CraftBukkit end ++ + public static boolean canSetSpawn(Level level) { +- return level.dimensionType().bedWorks(); ++ // CraftBukkit - moved world and biome check into EntityHuman ++ return true || level.dimensionType().bedWorks(); + } + +- private boolean kickVillagerOutOfBed(Level level, BlockPos blockpos) { +- List list = level.getEntitiesOfClass(Villager.class, new AABB(blockpos), LivingEntity::isSleeping); ++ private boolean kickVillagerOutOfBed(Level level, BlockPos pos) { ++ List list = level.getEntitiesOfClass(Villager.class, new AABB(pos), LivingEntity::isSleeping); + + if (list.isEmpty()) { + return false; +@@ -142,16 +171,14 @@ + } + + @Override +- @Override +- public void fallOn(Level level, BlockState blockstate, BlockPos blockpos, Entity entity, float f) { +- super.fallOn(level, blockstate, blockpos, entity, f * 0.5F); ++ public void fallOn(Level level, IBlockData state, BlockPos pos, Entity entity, float fallDistance) { ++ super.fallOn(level, state, pos, entity, fallDistance * 0.5F); + } + + @Override +- @Override +- public void updateEntityAfterFallOn(BlockGetter blockgetter, Entity entity) { ++ public void updateEntityAfterFallOn(BlockGetter level, Entity entity) { + if (entity.isSuppressingBounce()) { +- super.updateEntityAfterFallOn(blockgetter, entity); ++ super.updateEntityAfterFallOn(level, entity); + } else { + this.bounceUp(entity); + } +@@ -159,64 +186,60 @@ + } + + private void bounceUp(Entity entity) { +- Vec3 vec3 = entity.getDeltaMovement(); ++ Vec3 vec3d = entity.getDeltaMovement(); + +- if (vec3.y < 0.0D) { ++ if (vec3d.y < 0.0D) { + double d0 = entity instanceof LivingEntity ? 1.0D : 0.8D; + +- entity.setDeltaMovement(vec3.x, -vec3.y * 0.6600000262260437D * d0, vec3.z); ++ entity.setDeltaMovement(vec3d.x, -vec3d.y * 0.6600000262260437D * d0, vec3d.z); + } + + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- return direction == getNeighbourDirection((BedPart) blockstate.getValue(BedBlock.PART), (Direction) blockstate.getValue(BedBlock.FACING)) ? (blockstate1.is((Block) this) && blockstate1.getValue(BedBlock.PART) != blockstate.getValue(BedBlock.PART) ? (BlockState) blockstate.setValue(BedBlock.OCCUPIED, (Boolean) blockstate1.getValue(BedBlock.OCCUPIED)) : Blocks.AIR.defaultBlockState()) : super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ return facing == getNeighbourDirection((BedPart) state.getValue(BedBlock.PART), (Direction) state.getValue(BedBlock.FACING)) ? (facingState.is((Block) this) && facingState.getValue(BedBlock.PART) != state.getValue(BedBlock.PART) ? (IBlockData) state.setValue(BedBlock.OCCUPIED, (Boolean) facingState.getValue(BedBlock.OCCUPIED)) : Blocks.AIR.defaultBlockState()) : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + +- private static Direction getNeighbourDirection(BedPart bedpart, Direction direction) { +- return bedpart == BedPart.FOOT ? direction : direction.getOpposite(); ++ private static Direction getNeighbourDirection(BedPart part, Direction direction) { ++ return part == BedPart.FOOT ? direction : direction.getOpposite(); + } + + @Override +- @Override +- public BlockState playerWillDestroy(Level level, BlockPos blockpos, BlockState blockstate, Player player) { +- if (!level.isClientSide && player.isCreative()) { +- BedPart bedpart = (BedPart) blockstate.getValue(BedBlock.PART); ++ public IBlockData playerWillDestroy(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ if (!world.isClientSide && entityhuman.isCreative()) { ++ BedPart blockpropertybedpart = (BedPart) iblockdata.getValue(BedBlock.PART); + +- if (bedpart == BedPart.FOOT) { +- BlockPos blockpos1 = blockpos.relative(getNeighbourDirection(bedpart, (Direction) blockstate.getValue(BedBlock.FACING))); +- BlockState blockstate1 = level.getBlockState(blockpos1); ++ if (blockpropertybedpart == BedPart.FOOT) { ++ BlockPos blockposition1 = blockposition.relative(getNeighbourDirection(blockpropertybedpart, (Direction) iblockdata.getValue(BedBlock.FACING))); ++ IBlockData iblockdata1 = world.getBlockState(blockposition1); + +- if (blockstate1.is((Block) this) && blockstate1.getValue(BedBlock.PART) == BedPart.HEAD) { +- level.setBlock(blockpos1, Blocks.AIR.defaultBlockState(), 35); +- level.levelEvent(player, 2001, blockpos1, Block.getId(blockstate1)); ++ if (iblockdata1.is((Block) this) && iblockdata1.getValue(BedBlock.PART) == BedPart.HEAD) { ++ world.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 35); ++ world.levelEvent(entityhuman, 2001, blockposition1, Block.getId(iblockdata1)); + } + } + } + +- return super.playerWillDestroy(level, blockpos, blockstate, player); ++ return super.playerWillDestroy(world, blockposition, iblockdata, entityhuman); + } + + @Nullable + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- Direction direction = blockplacecontext.getHorizontalDirection(); +- BlockPos blockpos = blockplacecontext.getClickedPos(); +- BlockPos blockpos1 = blockpos.relative(direction); +- Level level = blockplacecontext.getLevel(); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ Direction enumdirection = context.getHorizontalDirection(); ++ BlockPos blockposition = context.getClickedPos(); ++ BlockPos blockposition1 = blockposition.relative(enumdirection); ++ Level world = context.getLevel(); + +- return level.getBlockState(blockpos1).canBeReplaced(blockplacecontext) && level.getWorldBorder().isWithinBounds(blockpos1) ? (BlockState) this.defaultBlockState().setValue(BedBlock.FACING, direction) : null; ++ return world.getBlockState(blockposition1).canBeReplaced(context) && world.getWorldBorder().isWithinBounds(blockposition1) ? (IBlockData) this.defaultBlockState().setValue(BedBlock.FACING, enumdirection) : null; + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- Direction direction = getConnectedDirection(blockstate).getOpposite(); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ Direction enumdirection = getConnectedDirection(state).getOpposite(); + +- switch (direction) { ++ switch (enumdirection) { + case NORTH: + return BedBlock.NORTH_SHAPE; + case SOUTH: +@@ -228,82 +251,82 @@ + } + } + +- public static Direction getConnectedDirection(BlockState blockstate) { +- Direction direction = (Direction) blockstate.getValue(BedBlock.FACING); ++ public static Direction getConnectedDirection(IBlockData state) { ++ Direction enumdirection = (Direction) state.getValue(BedBlock.FACING); + +- return blockstate.getValue(BedBlock.PART) == BedPart.HEAD ? direction.getOpposite() : direction; ++ return state.getValue(BedBlock.PART) == BedPart.HEAD ? enumdirection.getOpposite() : enumdirection; + } + +- public static DoubleBlockCombiner.BlockType getBlockType(BlockState blockstate) { +- BedPart bedpart = (BedPart) blockstate.getValue(BedBlock.PART); ++ public static DoubleBlockCombiner.BlockType getBlockType(IBlockData state) { ++ BedPart blockpropertybedpart = (BedPart) state.getValue(BedBlock.PART); + +- return bedpart == BedPart.HEAD ? DoubleBlockCombiner.BlockType.FIRST : DoubleBlockCombiner.BlockType.SECOND; ++ return blockpropertybedpart == BedPart.HEAD ? DoubleBlockCombiner.BlockType.FIRST : DoubleBlockCombiner.BlockType.SECOND; + } + +- private static boolean isBunkBed(BlockGetter blockgetter, BlockPos blockpos) { +- return blockgetter.getBlockState(blockpos.below()).getBlock() instanceof BedBlock; ++ private static boolean isBunkBed(BlockGetter level, BlockPos pos) { ++ return level.getBlockState(pos.below()).getBlock() instanceof BedBlock; + } + +- public static Optional findStandUpPosition(EntityType entitytype, CollisionGetter collisiongetter, BlockPos blockpos, Direction direction, float f) { +- Direction direction1 = direction.getClockWise(); +- Direction direction2 = direction1.isFacingAngle(f) ? direction1.getOpposite() : direction1; ++ public static Optional findStandUpPosition(EntityType entityType, CollisionGetter collisionGetter, BlockPos pos, Direction direction, float yRot) { ++ Direction enumdirection1 = direction.getClockWise(); ++ Direction enumdirection2 = enumdirection1.isFacingAngle(yRot) ? enumdirection1.getOpposite() : enumdirection1; + +- if (isBunkBed(collisiongetter, blockpos)) { +- return findBunkBedStandUpPosition(entitytype, collisiongetter, blockpos, direction, direction2); ++ if (isBunkBed(collisionGetter, pos)) { ++ return findBunkBedStandUpPosition(entityType, collisionGetter, pos, direction, enumdirection2); + } else { +- int[][] aint = bedStandUpOffsets(direction, direction2); +- Optional optional = findStandUpPositionAtOffset(entitytype, collisiongetter, blockpos, aint, true); ++ int[][] aint = bedStandUpOffsets(direction, enumdirection2); ++ Optional optional = findStandUpPositionAtOffset(entityType, collisionGetter, pos, aint, true); + +- return optional.isPresent() ? optional : findStandUpPositionAtOffset(entitytype, collisiongetter, blockpos, aint, false); ++ return optional.isPresent() ? optional : findStandUpPositionAtOffset(entityType, collisionGetter, pos, aint, false); + } + } + +- private static Optional findBunkBedStandUpPosition(EntityType entitytype, CollisionGetter collisiongetter, BlockPos blockpos, Direction direction, Direction direction1) { +- int[][] aint = bedSurroundStandUpOffsets(direction, direction1); +- Optional optional = findStandUpPositionAtOffset(entitytype, collisiongetter, blockpos, aint, true); ++ private static Optional findBunkBedStandUpPosition(EntityType entityType, CollisionGetter collisionGetter, BlockPos pos, Direction stateFacing, Direction entityFacing) { ++ int[][] aint = bedSurroundStandUpOffsets(stateFacing, entityFacing); ++ Optional optional = findStandUpPositionAtOffset(entityType, collisionGetter, pos, aint, true); + + if (optional.isPresent()) { + return optional; + } else { +- BlockPos blockpos1 = blockpos.below(); +- Optional optional1 = findStandUpPositionAtOffset(entitytype, collisiongetter, blockpos1, aint, true); ++ BlockPos blockposition1 = pos.below(); ++ Optional optional1 = findStandUpPositionAtOffset(entityType, collisionGetter, blockposition1, aint, true); + + if (optional1.isPresent()) { + return optional1; + } else { +- int[][] aint1 = bedAboveStandUpOffsets(direction); +- Optional optional2 = findStandUpPositionAtOffset(entitytype, collisiongetter, blockpos, aint1, true); ++ int[][] aint1 = bedAboveStandUpOffsets(stateFacing); ++ Optional optional2 = findStandUpPositionAtOffset(entityType, collisionGetter, pos, aint1, true); + + if (optional2.isPresent()) { + return optional2; + } else { +- Optional optional3 = findStandUpPositionAtOffset(entitytype, collisiongetter, blockpos, aint, false); ++ Optional optional3 = findStandUpPositionAtOffset(entityType, collisionGetter, pos, aint, false); + + if (optional3.isPresent()) { + return optional3; + } else { +- Optional optional4 = findStandUpPositionAtOffset(entitytype, collisiongetter, blockpos1, aint, false); ++ Optional optional4 = findStandUpPositionAtOffset(entityType, collisionGetter, blockposition1, aint, false); + +- return optional4.isPresent() ? optional4 : findStandUpPositionAtOffset(entitytype, collisiongetter, blockpos, aint1, false); ++ return optional4.isPresent() ? optional4 : findStandUpPositionAtOffset(entityType, collisionGetter, pos, aint1, false); + } + } + } + } + } + +- private static Optional findStandUpPositionAtOffset(EntityType entitytype, CollisionGetter collisiongetter, BlockPos blockpos, int[][] aint, boolean flag) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); +- int[][] aint1 = aint; +- int i = aint.length; ++ private static Optional findStandUpPositionAtOffset(EntityType entityType, CollisionGetter collisionGetter, BlockPos pos, int[][] offsets, boolean simulate) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ int[][] aint1 = offsets; ++ int i = offsets.length; + + for (int j = 0; j < i; ++j) { + int[] aint2 = aint1[j]; + +- blockpos_mutableblockpos.set(blockpos.getX() + aint2[0], blockpos.getY(), blockpos.getZ() + aint2[1]); +- Vec3 vec3 = DismountHelper.findSafeDismountLocation(entitytype, collisiongetter, blockpos_mutableblockpos, flag); ++ blockposition_mutableblockposition.set(pos.getX() + aint2[0], pos.getY(), pos.getZ() + aint2[1]); ++ Vec3 vec3d = DismountHelper.findSafeDismountLocation(entityType, collisionGetter, blockposition_mutableblockposition, simulate); + +- if (vec3 != null) { +- return Optional.of(vec3); ++ if (vec3d != null) { ++ return Optional.of(vec3d); + } + } + +@@ -311,33 +334,34 @@ + } + + @Override +- @Override +- public RenderShape getRenderShape(BlockState blockstate) { +- return RenderShape.ENTITYBLOCK_ANIMATED; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.ENTITYBLOCK_ANIMATED; + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(BedBlock.FACING, BedBlock.PART, BedBlock.OCCUPIED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(BedBlock.FACING, BedBlock.PART, BedBlock.OCCUPIED); + } + + @Override +- @Override +- public BlockEntity newBlockEntity(BlockPos blockpos, BlockState blockstate) { +- return new BedBlockEntity(blockpos, blockstate, this.color); ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ return new BedBlockEntity(pos, state, this.color); + } + + @Override +- @Override +- public void setPlacedBy(Level level, BlockPos blockpos, BlockState blockstate, @Nullable LivingEntity livingentity, ItemStack itemstack) { +- super.setPlacedBy(level, blockpos, blockstate, livingentity, itemstack); ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, @Nullable LivingEntity placer, ItemStack stack) { ++ super.setPlacedBy(level, pos, state, placer, stack); + if (!level.isClientSide) { +- BlockPos blockpos1 = blockpos.relative((Direction) blockstate.getValue(BedBlock.FACING)); ++ BlockPos blockposition1 = pos.relative((Direction) state.getValue(BedBlock.FACING)); + +- level.setBlock(blockpos1, (BlockState) blockstate.setValue(BedBlock.PART, BedPart.HEAD), 3); +- level.blockUpdated(blockpos, Blocks.AIR); +- blockstate.updateNeighbourShapes(level, blockpos, 3); ++ level.setBlock(blockposition1, (IBlockData) state.setValue(BedBlock.PART, BedPart.HEAD), 3); ++ // CraftBukkit start - SPIGOT-7315: Don't updated if we capture block states ++ if (level.captureBlockStates) { ++ return; ++ } ++ // CraftBukkit end ++ level.blockUpdated(pos, Blocks.AIR); ++ state.updateNeighbourShapes(level, pos, 3); + } + + } +@@ -347,28 +371,26 @@ + } + + @Override +- @Override +- public long getSeed(BlockState blockstate, BlockPos blockpos) { +- BlockPos blockpos1 = blockpos.relative((Direction) blockstate.getValue(BedBlock.FACING), blockstate.getValue(BedBlock.PART) == BedPart.HEAD ? 0 : 1); ++ public long getSeed(IBlockData state, BlockPos pos) { ++ BlockPos blockposition1 = pos.relative((Direction) state.getValue(BedBlock.FACING), state.getValue(BedBlock.PART) == BedPart.HEAD ? 0 : 1); + +- return Mth.getSeed(blockpos1.getX(), blockpos.getY(), blockpos1.getZ()); ++ return Mth.getSeed(blockposition1.getX(), pos.getY(), blockposition1.getZ()); + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + +- private static int[][] bedStandUpOffsets(Direction direction, Direction direction1) { +- return (int[][]) ArrayUtils.addAll(bedSurroundStandUpOffsets(direction, direction1), bedAboveStandUpOffsets(direction)); ++ private static int[][] bedStandUpOffsets(Direction firstDir, Direction secondDir) { ++ return (int[][]) ArrayUtils.addAll(bedSurroundStandUpOffsets(firstDir, secondDir), bedAboveStandUpOffsets(firstDir)); + } + +- private static int[][] bedSurroundStandUpOffsets(Direction direction, Direction direction1) { +- return new int[][]{{direction1.getStepX(), direction1.getStepZ()}, {direction1.getStepX() - direction.getStepX(), direction1.getStepZ() - direction.getStepZ()}, {direction1.getStepX() - direction.getStepX() * 2, direction1.getStepZ() - direction.getStepZ() * 2}, {-direction.getStepX() * 2, -direction.getStepZ() * 2}, {-direction1.getStepX() - direction.getStepX() * 2, -direction1.getStepZ() - direction.getStepZ() * 2}, {-direction1.getStepX() - direction.getStepX(), -direction1.getStepZ() - direction.getStepZ()}, {-direction1.getStepX(), -direction1.getStepZ()}, {-direction1.getStepX() + direction.getStepX(), -direction1.getStepZ() + direction.getStepZ()}, {direction.getStepX(), direction.getStepZ()}, {direction1.getStepX() + direction.getStepX(), direction1.getStepZ() + direction.getStepZ()}}; ++ private static int[][] bedSurroundStandUpOffsets(Direction firstDir, Direction secondDir) { ++ return new int[][]{{secondDir.getStepX(), secondDir.getStepZ()}, {secondDir.getStepX() - firstDir.getStepX(), secondDir.getStepZ() - firstDir.getStepZ()}, {secondDir.getStepX() - firstDir.getStepX() * 2, secondDir.getStepZ() - firstDir.getStepZ() * 2}, {-firstDir.getStepX() * 2, -firstDir.getStepZ() * 2}, {-secondDir.getStepX() - firstDir.getStepX() * 2, -secondDir.getStepZ() - firstDir.getStepZ() * 2}, {-secondDir.getStepX() - firstDir.getStepX(), -secondDir.getStepZ() - firstDir.getStepZ()}, {-secondDir.getStepX(), -secondDir.getStepZ()}, {-secondDir.getStepX() + firstDir.getStepX(), -secondDir.getStepZ() + firstDir.getStepZ()}, {firstDir.getStepX(), firstDir.getStepZ()}, {secondDir.getStepX() + firstDir.getStepX(), secondDir.getStepZ() + firstDir.getStepZ()}}; + } + +- private static int[][] bedAboveStandUpOffsets(Direction direction) { +- return new int[][]{{0, 0}, {-direction.getStepX(), -direction.getStepZ()}}; ++ private static int[][] bedAboveStandUpOffsets(Direction dir) { ++ return new int[][]{{0, 0}, {-dir.getStepX(), -dir.getStepZ()}}; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BeehiveBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BeehiveBlock.java.patch new file mode 100644 index 0000000000..e81fd11f29 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BeehiveBlock.java.patch @@ -0,0 +1,447 @@ +--- a/net/minecraft/world/level/block/BeehiveBlock.java ++++ b/net/minecraft/world/level/block/BeehiveBlock.java +@@ -17,7 +17,7 @@ + import net.minecraft.tags.BlockTags; + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.animal.Bee; +@@ -43,7 +43,7 @@ + import net.minecraft.world.level.block.entity.BlockEntityTicker; + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.DirectionProperty; +@@ -64,52 +64,48 @@ + private static final int SHEARED_HONEYCOMB_COUNT = 3; + + @Override +- @Override + public MapCodec codec() { + return BeehiveBlock.CODEC; + } + +- public BeehiveBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(BeehiveBlock.HONEY_LEVEL, 0)).setValue(BeehiveBlock.FACING, Direction.NORTH)); ++ public BeehiveBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(BeehiveBlock.HONEY_LEVEL, 0)).setValue(BeehiveBlock.FACING, Direction.NORTH)); + } + + @Override +- @Override +- public boolean hasAnalogOutputSignal(BlockState blockstate) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return true; + } + + @Override +- @Override +- public int getAnalogOutputSignal(BlockState blockstate, Level level, BlockPos blockpos) { +- return (Integer) blockstate.getValue(BeehiveBlock.HONEY_LEVEL); ++ public int getAnalogOutputSignal(IBlockData blockState, Level level, BlockPos pos) { ++ return (Integer) blockState.getValue(BeehiveBlock.HONEY_LEVEL); + } + + @Override +- @Override +- public void playerDestroy(Level level, Player player, BlockPos blockpos, BlockState blockstate, @Nullable BlockEntity blockentity, ItemStack itemstack) { +- super.playerDestroy(level, player, blockpos, blockstate, blockentity, itemstack); +- if (!level.isClientSide && blockentity instanceof BeehiveBlockEntity) { +- BeehiveBlockEntity beehiveblockentity = (BeehiveBlockEntity) blockentity; ++ public void playerDestroy(Level level, Player player, BlockPos pos, IBlockData state, @Nullable BlockEntity te, ItemStack stack) { ++ super.playerDestroy(level, player, pos, state, te, stack); ++ if (!level.isClientSide && te instanceof BeehiveBlockEntity) { ++ BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) te; + +- if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, itemstack) == 0) { +- beehiveblockentity.emptyAllLivingFromHive(player, blockstate, BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY); +- level.updateNeighbourForOutputSignal(blockpos, this); +- this.angerNearbyBees(level, blockpos); ++ if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack) == 0) { ++ tileentitybeehive.emptyAllLivingFromHive(player, state, BeehiveBlockEntity.ReleaseStatus.EMERGENCY); ++ level.updateNeighbourForOutputSignal(pos, this); ++ this.angerNearbyBees(level, pos); + } + +- CriteriaTriggers.BEE_NEST_DESTROYED.trigger((ServerPlayer) player, blockstate, itemstack, beehiveblockentity.getOccupantCount()); ++ CriteriaTriggers.BEE_NEST_DESTROYED.trigger((ServerPlayer) player, state, stack, tileentitybeehive.getOccupantCount()); + } + + } + +- private void angerNearbyBees(Level level, BlockPos blockpos) { +- AABB aabb = (new AABB(blockpos)).inflate(8.0D, 6.0D, 8.0D); +- List list = level.getEntitiesOfClass(Bee.class, aabb); ++ private void angerNearbyBees(Level level, BlockPos pos) { ++ AABB axisalignedbb = (new AABB(pos)).inflate(8.0D, 6.0D, 8.0D); ++ List list = level.getEntitiesOfClass(Bee.class, axisalignedbb); + + if (!list.isEmpty()) { +- List list1 = level.getEntitiesOfClass(Player.class, aabb); ++ List list1 = level.getEntitiesOfClass(Player.class, axisalignedbb); + + if (list1.isEmpty()) { + return; +@@ -118,27 +114,26 @@ + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- Bee bee = (Bee) iterator.next(); ++ Bee entitybee = (Bee) iterator.next(); + +- if (bee.getTarget() == null) { +- Player player = (Player) Util.getRandom(list1, level.random); ++ if (entitybee.getTarget() == null) { ++ Player entityhuman = (Player) Util.getRandom(list1, level.random); + +- bee.setTarget(player); ++ entitybee.setTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit + } + } + } + + } + +- public static void dropHoneycomb(Level level, BlockPos blockpos) { +- popResource(level, blockpos, new ItemStack(Items.HONEYCOMB, 3)); ++ public static void dropHoneycomb(Level level, BlockPos pos) { ++ popResource(level, pos, new ItemStack(Items.HONEYCOMB, 3)); + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- ItemStack itemstack = player.getItemInHand(interactionhand); +- int i = (Integer) blockstate.getValue(BeehiveBlock.HONEY_LEVEL); ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ int i = (Integer) state.getValue(BeehiveBlock.HONEY_LEVEL); + boolean flag = false; + + if (i >= 5) { +@@ -146,23 +141,23 @@ + + if (itemstack.is(Items.SHEARS)) { + level.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BEEHIVE_SHEAR, SoundSource.BLOCKS, 1.0F, 1.0F); +- dropHoneycomb(level, blockpos); +- itemstack.hurtAndBreak(1, player, (player1) -> { +- player1.broadcastBreakEvent(interactionhand); ++ dropHoneycomb(level, pos); ++ itemstack.hurtAndBreak(1, player, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(hand); + }); + flag = true; +- level.gameEvent((Entity) player, GameEvent.SHEAR, blockpos); ++ level.gameEvent((Entity) player, GameEvent.SHEAR, pos); + } else if (itemstack.is(Items.GLASS_BOTTLE)) { + itemstack.shrink(1); + level.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.BLOCKS, 1.0F, 1.0F); + if (itemstack.isEmpty()) { +- player.setItemInHand(interactionhand, new ItemStack(Items.HONEY_BOTTLE)); ++ player.setItemInHand(hand, new ItemStack(Items.HONEY_BOTTLE)); + } else if (!player.getInventory().add(new ItemStack(Items.HONEY_BOTTLE))) { + player.drop(new ItemStack(Items.HONEY_BOTTLE), false); + } + + flag = true; +- level.gameEvent((Entity) player, GameEvent.FLUID_PICKUP, blockpos); ++ level.gameEvent((Entity) player, GameEvent.FLUID_PICKUP, pos); + } + + if (!level.isClientSide() && flag) { +@@ -171,79 +166,78 @@ + } + + if (flag) { +- if (!CampfireBlock.isSmokeyPos(level, blockpos)) { +- if (this.hiveContainsBees(level, blockpos)) { +- this.angerNearbyBees(level, blockpos); ++ if (!CampfireBlock.isSmokeyPos(level, pos)) { ++ if (this.hiveContainsBees(level, pos)) { ++ this.angerNearbyBees(level, pos); + } + +- this.releaseBeesAndResetHoneyLevel(level, blockstate, blockpos, player, BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY); ++ this.releaseBeesAndResetHoneyLevel(level, state, pos, player, BeehiveBlockEntity.ReleaseStatus.EMERGENCY); + } else { +- this.resetHoneyLevel(level, blockstate, blockpos); ++ this.resetHoneyLevel(level, state, pos); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + } else { +- return super.use(blockstate, level, blockpos, player, interactionhand, blockhitresult); ++ return super.use(state, level, pos, player, hand, hit); + } + } + +- private boolean hiveContainsBees(Level level, BlockPos blockpos) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ private boolean hiveContainsBees(Level level, BlockPos pos) { ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof BeehiveBlockEntity) { +- BeehiveBlockEntity beehiveblockentity = (BeehiveBlockEntity) blockentity; ++ if (tileentity instanceof BeehiveBlockEntity) { ++ BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) tileentity; + +- return !beehiveblockentity.isEmpty(); ++ return !tileentitybeehive.isEmpty(); + } else { + return false; + } + } + +- public void releaseBeesAndResetHoneyLevel(Level level, BlockState blockstate, BlockPos blockpos, @Nullable Player player, BeehiveBlockEntity.BeeReleaseStatus beehiveblockentity_beereleasestatus) { +- this.resetHoneyLevel(level, blockstate, blockpos); +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ public void releaseBeesAndResetHoneyLevel(Level level, IBlockData state, BlockPos pos, @Nullable Player player, BeehiveBlockEntity.ReleaseStatus beeReleaseStatus) { ++ this.resetHoneyLevel(level, state, pos); ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof BeehiveBlockEntity) { +- BeehiveBlockEntity beehiveblockentity = (BeehiveBlockEntity) blockentity; ++ if (tileentity instanceof BeehiveBlockEntity) { ++ BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) tileentity; + +- beehiveblockentity.emptyAllLivingFromHive(player, blockstate, beehiveblockentity_beereleasestatus); ++ tileentitybeehive.emptyAllLivingFromHive(player, state, beeReleaseStatus); + } + + } + +- public void resetHoneyLevel(Level level, BlockState blockstate, BlockPos blockpos) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(BeehiveBlock.HONEY_LEVEL, 0), 3); ++ public void resetHoneyLevel(Level level, IBlockData state, BlockPos pos) { ++ level.setBlock(pos, (IBlockData) state.setValue(BeehiveBlock.HONEY_LEVEL, 0), 3); + } + + @Override +- @Override +- public void animateTick(BlockState blockstate, Level level, BlockPos blockpos, RandomSource randomsource) { +- if ((Integer) blockstate.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) { +- for (int i = 0; i < randomsource.nextInt(1) + 1; ++i) { +- this.trySpawnDripParticles(level, blockpos, blockstate); ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if ((Integer) state.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) { ++ for (int i = 0; i < random.nextInt(1) + 1; ++i) { ++ this.trySpawnDripParticles(level, pos, state); + } + } + + } + +- private void trySpawnDripParticles(Level level, BlockPos blockpos, BlockState blockstate) { +- if (blockstate.getFluidState().isEmpty() && level.random.nextFloat() >= 0.3F) { +- VoxelShape voxelshape = blockstate.getCollisionShape(level, blockpos); ++ private void trySpawnDripParticles(Level level, BlockPos pos, IBlockData state) { ++ if (state.getFluidState().isEmpty() && level.random.nextFloat() >= 0.3F) { ++ VoxelShape voxelshape = state.getCollisionShape(level, pos); + double d0 = voxelshape.max(Direction.Axis.Y); + +- if (d0 >= 1.0D && !blockstate.is(BlockTags.IMPERMEABLE)) { ++ if (d0 >= 1.0D && !state.is(BlockTags.IMPERMEABLE)) { + double d1 = voxelshape.min(Direction.Axis.Y); + + if (d1 > 0.0D) { +- this.spawnParticle(level, blockpos, voxelshape, (double) blockpos.getY() + d1 - 0.05D); ++ this.spawnParticle(level, pos, voxelshape, (double) pos.getY() + d1 - 0.05D); + } else { +- BlockPos blockpos1 = blockpos.below(); +- BlockState blockstate1 = level.getBlockState(blockpos1); +- VoxelShape voxelshape1 = blockstate1.getCollisionShape(level, blockpos1); ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ VoxelShape voxelshape1 = iblockdata1.getCollisionShape(level, blockposition1); + double d2 = voxelshape1.max(Direction.Axis.Y); + +- if ((d2 < 1.0D || !blockstate1.isCollisionShapeFullBlock(level, blockpos1)) && blockstate1.getFluidState().isEmpty()) { +- this.spawnParticle(level, blockpos, voxelshape, (double) blockpos.getY() - 0.05D); ++ if ((d2 < 1.0D || !iblockdata1.isCollisionShapeFullBlock(level, blockposition1)) && iblockdata1.getFluidState().isEmpty()) { ++ this.spawnParticle(level, pos, voxelshape, (double) pos.getY() - 0.05D); + } + } + } +@@ -251,124 +245,114 @@ + } + } + +- private void spawnParticle(Level level, BlockPos blockpos, VoxelShape voxelshape, double d0) { +- this.spawnFluidParticle(level, (double) blockpos.getX() + voxelshape.min(Direction.Axis.X), (double) blockpos.getX() + voxelshape.max(Direction.Axis.X), (double) blockpos.getZ() + voxelshape.min(Direction.Axis.Z), (double) blockpos.getZ() + voxelshape.max(Direction.Axis.Z), d0); ++ private void spawnParticle(Level level, BlockPos pos, VoxelShape shape, double y) { ++ this.spawnFluidParticle(level, (double) pos.getX() + shape.min(Direction.Axis.X), (double) pos.getX() + shape.max(Direction.Axis.X), (double) pos.getZ() + shape.min(Direction.Axis.Z), (double) pos.getZ() + shape.max(Direction.Axis.Z), y); + } + +- private void spawnFluidParticle(Level level, double d0, double d1, double d2, double d3, double d4) { +- level.addParticle(ParticleTypes.DRIPPING_HONEY, Mth.lerp(level.random.nextDouble(), d0, d1), d4, Mth.lerp(level.random.nextDouble(), d2, d3), 0.0D, 0.0D, 0.0D); ++ private void spawnFluidParticle(Level particleData, double x1, double d1, double x2, double d3, double z1) { ++ particleData.addParticle(ParticleTypes.DRIPPING_HONEY, Mth.lerp(particleData.random.nextDouble(), x1, d1), z1, Mth.lerp(particleData.random.nextDouble(), x2, d3), 0.0D, 0.0D, 0.0D); + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- return (BlockState) this.defaultBlockState().setValue(BeehiveBlock.FACING, blockplacecontext.getHorizontalDirection().getOpposite()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return (IBlockData) this.defaultBlockState().setValue(BeehiveBlock.FACING, context.getHorizontalDirection().getOpposite()); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(BeehiveBlock.HONEY_LEVEL, BeehiveBlock.FACING); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(BeehiveBlock.HONEY_LEVEL, BeehiveBlock.FACING); + } + + @Override +- @Override +- public RenderShape getRenderShape(BlockState blockstate) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Nullable + @Override +- @Override +- public BlockEntity newBlockEntity(BlockPos blockpos, BlockState blockstate) { +- return new BeehiveBlockEntity(blockpos, blockstate); ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ return new BeehiveBlockEntity(pos, state); + } + + @Nullable + @Override +- @Override +- public BlockEntityTicker getTicker(Level level, BlockState blockstate, BlockEntityType blockentitytype) { +- return level.isClientSide ? null : createTickerHelper(blockentitytype, BlockEntityType.BEEHIVE, BeehiveBlockEntity::serverTick); ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { ++ return level.isClientSide ? null : createTickerHelper(blockEntityType, BlockEntityType.BEEHIVE, BeehiveBlockEntity::serverTick); + } + + @Override +- @Override +- public BlockState playerWillDestroy(Level level, BlockPos blockpos, BlockState blockstate, Player player) { +- if (!level.isClientSide && player.isCreative() && level.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ public IBlockData playerWillDestroy(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ if (!world.isClientSide && entityhuman.isCreative() && world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { ++ BlockEntity tileentity = world.getBlockEntity(blockposition); + +- if (blockentity instanceof BeehiveBlockEntity) { +- BeehiveBlockEntity beehiveblockentity = (BeehiveBlockEntity) blockentity; ++ if (tileentity instanceof BeehiveBlockEntity) { ++ BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) tileentity; + ItemStack itemstack = new ItemStack(this); +- int i = (Integer) blockstate.getValue(BeehiveBlock.HONEY_LEVEL); +- boolean flag = !beehiveblockentity.isEmpty(); ++ int i = (Integer) iblockdata.getValue(BeehiveBlock.HONEY_LEVEL); ++ boolean flag = !tileentitybeehive.isEmpty(); + + if (flag || i > 0) { +- CompoundTag compoundtag; ++ CompoundTag nbttagcompound; + + if (flag) { +- compoundtag = new CompoundTag(); +- compoundtag.put("Bees", beehiveblockentity.writeBees()); +- BlockItem.setBlockEntityData(itemstack, BlockEntityType.BEEHIVE, compoundtag); ++ nbttagcompound = new CompoundTag(); ++ nbttagcompound.put("Bees", tileentitybeehive.writeBees()); ++ BlockItem.setBlockEntityData(itemstack, BlockEntityType.BEEHIVE, nbttagcompound); + } + +- compoundtag = new CompoundTag(); +- compoundtag.putInt("honey_level", i); +- itemstack.addTagElement("BlockStateTag", compoundtag); +- ItemEntity itementity = new ItemEntity(level, (double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), itemstack); ++ nbttagcompound = new CompoundTag(); ++ nbttagcompound.putInt("honey_level", i); ++ itemstack.addTagElement("BlockStateTag", nbttagcompound); ++ ItemEntity entityitem = new ItemEntity(world, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), itemstack); + +- itementity.setDefaultPickUpDelay(); +- level.addFreshEntity(itementity); ++ entityitem.setDefaultPickUpDelay(); ++ world.addFreshEntity(entityitem); + } + } + } + +- return super.playerWillDestroy(level, blockpos, blockstate, player); ++ return super.playerWillDestroy(world, blockposition, iblockdata, entityhuman); + } + + @Override +- @Override +- public List getDrops(BlockState blockstate, LootParams.Builder lootparams_builder) { +- Entity entity = (Entity) lootparams_builder.getOptionalParameter(LootContextParams.THIS_ENTITY); ++ public List getDrops(IBlockData state, LootParams.Builder params) { ++ Entity entity = (Entity) params.getOptionalParameter(LootContextParams.THIS_ENTITY); + + if (entity instanceof PrimedTnt || entity instanceof Creeper || entity instanceof WitherSkull || entity instanceof WitherBoss || entity instanceof MinecartTNT) { +- BlockEntity blockentity = (BlockEntity) lootparams_builder.getOptionalParameter(LootContextParams.BLOCK_ENTITY); ++ BlockEntity tileentity = (BlockEntity) params.getOptionalParameter(LootContextParams.BLOCK_ENTITY); + +- if (blockentity instanceof BeehiveBlockEntity) { +- BeehiveBlockEntity beehiveblockentity = (BeehiveBlockEntity) blockentity; ++ if (tileentity instanceof BeehiveBlockEntity) { ++ BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) tileentity; + +- beehiveblockentity.emptyAllLivingFromHive((Player) null, blockstate, BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY); ++ tileentitybeehive.emptyAllLivingFromHive((Player) null, state, BeehiveBlockEntity.ReleaseStatus.EMERGENCY); + } + } + +- return super.getDrops(blockstate, lootparams_builder); ++ return super.getDrops(state, params); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if (levelaccessor.getBlockState(blockpos1).getBlock() instanceof FireBlock) { +- BlockEntity blockentity = levelaccessor.getBlockEntity(blockpos); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if (level.getBlockState(facingPos).getBlock() instanceof FireBlock) { ++ BlockEntity tileentity = level.getBlockEntity(currentPos); + +- if (blockentity instanceof BeehiveBlockEntity) { +- BeehiveBlockEntity beehiveblockentity = (BeehiveBlockEntity) blockentity; ++ if (tileentity instanceof BeehiveBlockEntity) { ++ BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) tileentity; + +- beehiveblockentity.emptyAllLivingFromHive((Player) null, blockstate, BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY); ++ tileentitybeehive.emptyAllLivingFromHive((Player) null, state, BeehiveBlockEntity.ReleaseStatus.EMERGENCY); + } + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- @Override +- public BlockState rotate(BlockState blockstate, Rotation rotation) { +- return (BlockState) blockstate.setValue(BeehiveBlock.FACING, rotation.rotate((Direction) blockstate.getValue(BeehiveBlock.FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return (IBlockData) state.setValue(BeehiveBlock.FACING, rotation.rotate((Direction) state.getValue(BeehiveBlock.FACING))); + } + + @Override +- @Override +- public BlockState mirror(BlockState blockstate, Mirror mirror) { +- return blockstate.rotate(mirror.getRotation((Direction) blockstate.getValue(BeehiveBlock.FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(BeehiveBlock.FACING))); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BellBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BellBlock.java.patch new file mode 100644 index 0000000000..8f9aeb26d2 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BellBlock.java.patch @@ -0,0 +1,373 @@ +--- a/net/minecraft/world/level/block/BellBlock.java ++++ b/net/minecraft/world/level/block/BellBlock.java +@@ -8,7 +8,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; +@@ -25,7 +25,7 @@ + import net.minecraft.world.level.block.entity.BlockEntityTicker; + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BellAttachType; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; +@@ -33,7 +33,7 @@ + import net.minecraft.world.level.block.state.properties.DirectionProperty; + import net.minecraft.world.level.block.state.properties.EnumProperty; + import net.minecraft.world.level.gameevent.GameEvent; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; +@@ -60,53 +60,49 @@ + public static final int EVENT_BELL_RING = 1; + + @Override +- @Override + public MapCodec codec() { + return BellBlock.CODEC; + } + +- public BellBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(BellBlock.FACING, Direction.NORTH)).setValue(BellBlock.ATTACHMENT, BellAttachType.FLOOR)).setValue(BellBlock.POWERED, false)); ++ public BellBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(BellBlock.FACING, Direction.NORTH)).setValue(BellBlock.ATTACHMENT, BellAttachType.FLOOR)).setValue(BellBlock.POWERED, false)); + } + + @Override +- @Override +- public void neighborChanged(BlockState blockstate, Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { +- boolean flag1 = level.hasNeighborSignal(blockpos); ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ boolean flag1 = level.hasNeighborSignal(pos); + +- if (flag1 != (Boolean) blockstate.getValue(BellBlock.POWERED)) { ++ if (flag1 != (Boolean) state.getValue(BellBlock.POWERED)) { + if (flag1) { +- this.attemptToRing(level, blockpos, (Direction) null); ++ this.attemptToRing(level, pos, (Direction) null); + } + +- level.setBlock(blockpos, (BlockState) blockstate.setValue(BellBlock.POWERED, flag1), 3); ++ level.setBlock(pos, (IBlockData) state.setValue(BellBlock.POWERED, flag1), 3); + } + + } + + @Override +- @Override +- public void onProjectileHit(Level level, BlockState blockstate, BlockHitResult blockhitresult, Projectile projectile) { ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { + Entity entity = projectile.getOwner(); +- Player player = entity instanceof Player ? (Player) entity : null; ++ Player entityhuman = entity instanceof Player ? (Player) entity : null; + +- this.onHit(level, blockstate, blockhitresult, player, true); ++ this.onHit(level, state, hit, entityhuman, true); + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- return this.onHit(level, blockstate, blockhitresult, player, true) ? InteractionResult.sidedSuccess(level.isClientSide) : InteractionResult.PASS; ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ return this.onHit(level, state, hit, player, true) ? InteractionResult.sidedSuccess(level.isClientSide) : InteractionResult.PASS; + } + +- public boolean onHit(Level level, BlockState blockstate, BlockHitResult blockhitresult, @Nullable Player player, boolean flag) { +- Direction direction = blockhitresult.getDirection(); +- BlockPos blockpos = blockhitresult.getBlockPos(); +- boolean flag1 = !flag || this.isProperHit(blockstate, direction, blockhitresult.getLocation().y - (double) blockpos.getY()); ++ public boolean onHit(Level level, IBlockData state, BlockHitResult result, @Nullable Player player, boolean canRingBell) { ++ Direction enumdirection = result.getDirection(); ++ BlockPos blockposition = result.getBlockPos(); ++ boolean flag1 = !canRingBell || this.isProperHit(state, enumdirection, result.getLocation().y - (double) blockposition.getY()); + + if (flag1) { +- boolean flag2 = this.attemptToRing(player, level, blockpos, direction); ++ boolean flag2 = this.attemptToRing(player, level, blockposition, enumdirection); + + if (flag2 && player != null) { + player.awardStat(Stats.BELL_RING); +@@ -118,17 +114,17 @@ + } + } + +- private boolean isProperHit(BlockState blockstate, Direction direction, double d0) { +- if (direction.getAxis() != Direction.Axis.Y && d0 <= 0.8123999834060669D) { +- Direction direction1 = (Direction) blockstate.getValue(BellBlock.FACING); +- BellAttachType bellattachtype = (BellAttachType) blockstate.getValue(BellBlock.ATTACHMENT); ++ private boolean isProperHit(IBlockData pos, Direction direction, double distanceY) { ++ if (direction.getAxis() != Direction.Axis.Y && distanceY <= 0.8123999834060669D) { ++ Direction enumdirection1 = (Direction) pos.getValue(BellBlock.FACING); ++ BellAttachType blockpropertybellattach = (BellAttachType) pos.getValue(BellBlock.ATTACHMENT); + +- switch (bellattachtype) { ++ switch (blockpropertybellattach) { + case FLOOR: +- return direction1.getAxis() == direction.getAxis(); ++ return enumdirection1.getAxis() == direction.getAxis(); + case SINGLE_WALL: + case DOUBLE_WALL: +- return direction1.getAxis() != direction.getAxis(); ++ return enumdirection1.getAxis() != direction.getAxis(); + case CEILING: + return true; + default: +@@ -139,80 +135,81 @@ + } + } + +- public boolean attemptToRing(Level level, BlockPos blockpos, @Nullable Direction direction) { +- return this.attemptToRing((Entity) null, level, blockpos, direction); ++ public boolean attemptToRing(Level level, BlockPos pos, @Nullable Direction direction) { ++ return this.attemptToRing((Entity) null, level, pos, direction); + } + +- public boolean attemptToRing(@Nullable Entity entity, Level level, BlockPos blockpos, @Nullable Direction direction) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ public boolean attemptToRing(@Nullable Entity entity, Level level, BlockPos pos, @Nullable Direction direction) { ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (!level.isClientSide && blockentity instanceof BellBlockEntity) { ++ if (!level.isClientSide && tileentity instanceof BellBlockEntity) { + if (direction == null) { +- direction = (Direction) level.getBlockState(blockpos).getValue(BellBlock.FACING); ++ direction = (Direction) level.getBlockState(pos).getValue(BellBlock.FACING); + } ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBellRingEvent(level, pos, direction, entity)) { ++ return false; ++ } ++ // CraftBukkit end + +- ((BellBlockEntity) blockentity).onHit(direction); +- level.playSound((Player) null, blockpos, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2.0F, 1.0F); +- level.gameEvent(entity, GameEvent.BLOCK_CHANGE, blockpos); ++ ((BellBlockEntity) tileentity).onHit(direction); ++ level.playSound((Player) null, pos, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2.0F, 1.0F); ++ level.gameEvent(entity, GameEvent.BLOCK_CHANGE, pos); + return true; + } else { + return false; + } + } + +- private VoxelShape getVoxelShape(BlockState blockstate) { +- Direction direction = (Direction) blockstate.getValue(BellBlock.FACING); +- BellAttachType bellattachtype = (BellAttachType) blockstate.getValue(BellBlock.ATTACHMENT); ++ private VoxelShape getVoxelShape(IBlockData state) { ++ Direction enumdirection = (Direction) state.getValue(BellBlock.FACING); ++ BellAttachType blockpropertybellattach = (BellAttachType) state.getValue(BellBlock.ATTACHMENT); + +- return bellattachtype == BellAttachType.FLOOR ? (direction != Direction.NORTH && direction != Direction.SOUTH ? BellBlock.EAST_WEST_FLOOR_SHAPE : BellBlock.NORTH_SOUTH_FLOOR_SHAPE) : (bellattachtype == BellAttachType.CEILING ? BellBlock.CEILING_SHAPE : (bellattachtype == BellAttachType.DOUBLE_WALL ? (direction != Direction.NORTH && direction != Direction.SOUTH ? BellBlock.EAST_WEST_BETWEEN : BellBlock.NORTH_SOUTH_BETWEEN) : (direction == Direction.NORTH ? BellBlock.TO_NORTH : (direction == Direction.SOUTH ? BellBlock.TO_SOUTH : (direction == Direction.EAST ? BellBlock.TO_EAST : BellBlock.TO_WEST))))); ++ return blockpropertybellattach == BellAttachType.FLOOR ? (enumdirection != Direction.NORTH && enumdirection != Direction.SOUTH ? BellBlock.EAST_WEST_FLOOR_SHAPE : BellBlock.NORTH_SOUTH_FLOOR_SHAPE) : (blockpropertybellattach == BellAttachType.CEILING ? BellBlock.CEILING_SHAPE : (blockpropertybellattach == BellAttachType.DOUBLE_WALL ? (enumdirection != Direction.NORTH && enumdirection != Direction.SOUTH ? BellBlock.EAST_WEST_BETWEEN : BellBlock.NORTH_SOUTH_BETWEEN) : (enumdirection == Direction.NORTH ? BellBlock.TO_NORTH : (enumdirection == Direction.SOUTH ? BellBlock.TO_SOUTH : (enumdirection == Direction.EAST ? BellBlock.TO_EAST : BellBlock.TO_WEST))))); + } + + @Override +- @Override +- public VoxelShape getCollisionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return this.getVoxelShape(blockstate); ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return this.getVoxelShape(state); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return this.getVoxelShape(blockstate); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return this.getVoxelShape(state); + } + + @Override +- @Override +- public RenderShape getRenderShape(BlockState blockstate) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Nullable + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- Direction direction = blockplacecontext.getClickedFace(); +- BlockPos blockpos = blockplacecontext.getClickedPos(); +- Level level = blockplacecontext.getLevel(); +- Direction.Axis direction_axis = direction.getAxis(); +- BlockState blockstate; ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ Direction enumdirection = context.getClickedFace(); ++ BlockPos blockposition = context.getClickedPos(); ++ Level world = context.getLevel(); ++ Direction.Axis enumdirection_enumaxis = enumdirection.getAxis(); ++ IBlockData iblockdata; + +- if (direction_axis == Direction.Axis.Y) { +- blockstate = (BlockState) ((BlockState) this.defaultBlockState().setValue(BellBlock.ATTACHMENT, direction == Direction.DOWN ? BellAttachType.CEILING : BellAttachType.FLOOR)).setValue(BellBlock.FACING, blockplacecontext.getHorizontalDirection()); +- if (blockstate.canSurvive(blockplacecontext.getLevel(), blockpos)) { +- return blockstate; ++ if (enumdirection_enumaxis == Direction.Axis.Y) { ++ iblockdata = (IBlockData) ((IBlockData) this.defaultBlockState().setValue(BellBlock.ATTACHMENT, enumdirection == Direction.DOWN ? BellAttachType.CEILING : BellAttachType.FLOOR)).setValue(BellBlock.FACING, context.getHorizontalDirection()); ++ if (iblockdata.canSurvive(context.getLevel(), blockposition)) { ++ return iblockdata; + } + } else { +- boolean flag = direction_axis == Direction.Axis.X && level.getBlockState(blockpos.west()).isFaceSturdy(level, blockpos.west(), Direction.EAST) && level.getBlockState(blockpos.east()).isFaceSturdy(level, blockpos.east(), Direction.WEST) || direction_axis == Direction.Axis.Z && level.getBlockState(blockpos.north()).isFaceSturdy(level, blockpos.north(), Direction.SOUTH) && level.getBlockState(blockpos.south()).isFaceSturdy(level, blockpos.south(), Direction.NORTH); ++ boolean flag = enumdirection_enumaxis == Direction.Axis.X && world.getBlockState(blockposition.west()).isFaceSturdy(world, blockposition.west(), Direction.EAST) && world.getBlockState(blockposition.east()).isFaceSturdy(world, blockposition.east(), Direction.WEST) || enumdirection_enumaxis == Direction.Axis.Z && world.getBlockState(blockposition.north()).isFaceSturdy(world, blockposition.north(), Direction.SOUTH) && world.getBlockState(blockposition.south()).isFaceSturdy(world, blockposition.south(), Direction.NORTH); + +- blockstate = (BlockState) ((BlockState) this.defaultBlockState().setValue(BellBlock.FACING, direction.getOpposite())).setValue(BellBlock.ATTACHMENT, flag ? BellAttachType.DOUBLE_WALL : BellAttachType.SINGLE_WALL); +- if (blockstate.canSurvive(blockplacecontext.getLevel(), blockplacecontext.getClickedPos())) { +- return blockstate; ++ iblockdata = (IBlockData) ((IBlockData) this.defaultBlockState().setValue(BellBlock.FACING, enumdirection.getOpposite())).setValue(BellBlock.ATTACHMENT, flag ? BellAttachType.DOUBLE_WALL : BellAttachType.SINGLE_WALL); ++ if (iblockdata.canSurvive(context.getLevel(), context.getClickedPos())) { ++ return iblockdata; + } + +- boolean flag1 = level.getBlockState(blockpos.below()).isFaceSturdy(level, blockpos.below(), Direction.UP); ++ boolean flag1 = world.getBlockState(blockposition.below()).isFaceSturdy(world, blockposition.below(), Direction.UP); + +- blockstate = (BlockState) blockstate.setValue(BellBlock.ATTACHMENT, flag1 ? BellAttachType.FLOOR : BellAttachType.CEILING); +- if (blockstate.canSurvive(blockplacecontext.getLevel(), blockplacecontext.getClickedPos())) { +- return blockstate; ++ iblockdata = (IBlockData) iblockdata.setValue(BellBlock.ATTACHMENT, flag1 ? BellAttachType.FLOOR : BellAttachType.CEILING); ++ if (iblockdata.canSurvive(context.getLevel(), context.getClickedPos())) { ++ return iblockdata; + } + } + +@@ -220,92 +217,83 @@ + } + + @Override +- @Override +- public void onExplosionHit(BlockState blockstate, Level level, BlockPos blockpos, Explosion explosion, BiConsumer biconsumer) { +- if (explosion.getBlockInteraction() == Explosion.BlockInteraction.TRIGGER_BLOCK && !level.isClientSide()) { +- this.attemptToRing(level, blockpos, (Direction) null); ++ public void onExplosionHit(IBlockData iblockdata, Level world, BlockPos blockposition, Explosion explosion, BiConsumer biconsumer) { ++ if (explosion.getBlockInteraction() == Explosion.Effect.TRIGGER_BLOCK && !world.isClientSide()) { ++ this.attemptToRing(world, blockposition, (Direction) null); + } + +- super.onExplosionHit(blockstate, level, blockpos, explosion, biconsumer); ++ super.onExplosionHit(iblockdata, world, blockposition, explosion, biconsumer); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- BellAttachType bellattachtype = (BellAttachType) blockstate.getValue(BellBlock.ATTACHMENT); +- Direction direction1 = getConnectedDirection(blockstate).getOpposite(); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ BellAttachType blockpropertybellattach = (BellAttachType) state.getValue(BellBlock.ATTACHMENT); ++ Direction enumdirection1 = getConnectedDirection(state).getOpposite(); + +- if (direction1 == direction && !blockstate.canSurvive(levelaccessor, blockpos) && bellattachtype != BellAttachType.DOUBLE_WALL) { ++ if (enumdirection1 == facing && !state.canSurvive(level, currentPos) && blockpropertybellattach != BellAttachType.DOUBLE_WALL) { + return Blocks.AIR.defaultBlockState(); + } else { +- if (direction.getAxis() == ((Direction) blockstate.getValue(BellBlock.FACING)).getAxis()) { +- if (bellattachtype == BellAttachType.DOUBLE_WALL && !blockstate1.isFaceSturdy(levelaccessor, blockpos1, direction)) { +- return (BlockState) ((BlockState) blockstate.setValue(BellBlock.ATTACHMENT, BellAttachType.SINGLE_WALL)).setValue(BellBlock.FACING, direction.getOpposite()); ++ if (facing.getAxis() == ((Direction) state.getValue(BellBlock.FACING)).getAxis()) { ++ if (blockpropertybellattach == BellAttachType.DOUBLE_WALL && !facingState.isFaceSturdy(level, facingPos, facing)) { ++ return (IBlockData) ((IBlockData) state.setValue(BellBlock.ATTACHMENT, BellAttachType.SINGLE_WALL)).setValue(BellBlock.FACING, facing.getOpposite()); + } + +- if (bellattachtype == BellAttachType.SINGLE_WALL && direction1.getOpposite() == direction && blockstate1.isFaceSturdy(levelaccessor, blockpos1, (Direction) blockstate.getValue(BellBlock.FACING))) { +- return (BlockState) blockstate.setValue(BellBlock.ATTACHMENT, BellAttachType.DOUBLE_WALL); ++ if (blockpropertybellattach == BellAttachType.SINGLE_WALL && enumdirection1.getOpposite() == facing && facingState.isFaceSturdy(level, facingPos, (Direction) state.getValue(BellBlock.FACING))) { ++ return (IBlockData) state.setValue(BellBlock.ATTACHMENT, BellAttachType.DOUBLE_WALL); + } + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- Direction direction = getConnectedDirection(blockstate).getOpposite(); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ Direction enumdirection = getConnectedDirection(state).getOpposite(); + +- return direction == Direction.UP ? Block.canSupportCenter(levelreader, blockpos.above(), Direction.DOWN) : FaceAttachedHorizontalDirectionalBlock.canAttach(levelreader, blockpos, direction); ++ return enumdirection == Direction.UP ? Block.canSupportCenter(level, pos.above(), Direction.DOWN) : FaceAttachedHorizontalDirectionalBlock.canAttach(level, pos, enumdirection); + } + +- private static Direction getConnectedDirection(BlockState blockstate) { +- switch ((BellAttachType) blockstate.getValue(BellBlock.ATTACHMENT)) { ++ private static Direction getConnectedDirection(IBlockData state) { ++ switch ((BellAttachType) state.getValue(BellBlock.ATTACHMENT)) { + case FLOOR: + return Direction.UP; + case CEILING: + return Direction.DOWN; + default: +- return ((Direction) blockstate.getValue(BellBlock.FACING)).getOpposite(); ++ return ((Direction) state.getValue(BellBlock.FACING)).getOpposite(); + } + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(BellBlock.FACING, BellBlock.ATTACHMENT, BellBlock.POWERED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(BellBlock.FACING, BellBlock.ATTACHMENT, BellBlock.POWERED); + } + + @Nullable + @Override +- @Override +- public BlockEntity newBlockEntity(BlockPos blockpos, BlockState blockstate) { +- return new BellBlockEntity(blockpos, blockstate); ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ return new BellBlockEntity(pos, state); + } + + @Nullable + @Override +- @Override +- public BlockEntityTicker getTicker(Level level, BlockState blockstate, BlockEntityType blockentitytype) { +- return createTickerHelper(blockentitytype, BlockEntityType.BELL, level.isClientSide ? BellBlockEntity::clientTick : BellBlockEntity::serverTick); ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { ++ return createTickerHelper(blockEntityType, BlockEntityType.BELL, level.isClientSide ? BellBlockEntity::clientTick : BellBlockEntity::serverTick); + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + + @Override +- @Override +- public BlockState rotate(BlockState blockstate, Rotation rotation) { +- return (BlockState) blockstate.setValue(BellBlock.FACING, rotation.rotate((Direction) blockstate.getValue(BellBlock.FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return (IBlockData) state.setValue(BellBlock.FACING, rotation.rotate((Direction) state.getValue(BellBlock.FACING))); + } + + @Override +- @Override +- public BlockState mirror(BlockState blockstate, Mirror mirror) { +- return blockstate.rotate(mirror.getRotation((Direction) blockstate.getValue(BellBlock.FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(BellBlock.FACING))); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BigDripleafBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BigDripleafBlock.java.patch new file mode 100644 index 0000000000..4264a46a6d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BigDripleafBlock.java.patch @@ -0,0 +1,365 @@ +--- a/net/minecraft/world/level/block/BigDripleafBlock.java ++++ b/net/minecraft/world/level/block/BigDripleafBlock.java +@@ -26,7 +26,7 @@ + import net.minecraft.world.level.LevelHeightAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -41,6 +41,10 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end + + public class BigDripleafBlock extends HorizontalDirectionalBlock implements BonemealableBlock, SimpleWaterloggedBlock { + +@@ -61,230 +65,238 @@ + private static final Map LEAF_SHAPES = ImmutableMap.of(Tilt.NONE, Block.box(0.0D, 11.0D, 0.0D, 16.0D, 15.0D, 16.0D), Tilt.UNSTABLE, Block.box(0.0D, 11.0D, 0.0D, 16.0D, 15.0D, 16.0D), Tilt.PARTIAL, Block.box(0.0D, 11.0D, 0.0D, 16.0D, 13.0D, 16.0D), Tilt.FULL, Shapes.empty()); + private static final VoxelShape STEM_SLICER = Block.box(0.0D, 13.0D, 0.0D, 16.0D, 16.0D, 16.0D); + private static final Map STEM_SHAPES = ImmutableMap.of(Direction.NORTH, Shapes.joinUnoptimized(BigDripleafStemBlock.NORTH_SHAPE, BigDripleafBlock.STEM_SLICER, BooleanOp.ONLY_FIRST), Direction.SOUTH, Shapes.joinUnoptimized(BigDripleafStemBlock.SOUTH_SHAPE, BigDripleafBlock.STEM_SLICER, BooleanOp.ONLY_FIRST), Direction.EAST, Shapes.joinUnoptimized(BigDripleafStemBlock.EAST_SHAPE, BigDripleafBlock.STEM_SLICER, BooleanOp.ONLY_FIRST), Direction.WEST, Shapes.joinUnoptimized(BigDripleafStemBlock.WEST_SHAPE, BigDripleafBlock.STEM_SLICER, BooleanOp.ONLY_FIRST)); +- private final Map shapesCache; ++ private final Map shapesCache; + + @Override +- @Override + public MapCodec codec() { + return BigDripleafBlock.CODEC; + } + +- protected BigDripleafBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(BigDripleafBlock.WATERLOGGED, false)).setValue(BigDripleafBlock.FACING, Direction.NORTH)).setValue(BigDripleafBlock.TILT, Tilt.NONE)); ++ protected BigDripleafBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(BigDripleafBlock.WATERLOGGED, false)).setValue(BigDripleafBlock.FACING, Direction.NORTH)).setValue(BigDripleafBlock.TILT, Tilt.NONE)); + this.shapesCache = this.getShapeForEachState(BigDripleafBlock::calculateShape); + } + +- private static VoxelShape calculateShape(BlockState blockstate) { +- return Shapes.or((VoxelShape) BigDripleafBlock.LEAF_SHAPES.get(blockstate.getValue(BigDripleafBlock.TILT)), (VoxelShape) BigDripleafBlock.STEM_SHAPES.get(blockstate.getValue(BigDripleafBlock.FACING))); ++ private static VoxelShape calculateShape(IBlockData state) { ++ return Shapes.or((VoxelShape) BigDripleafBlock.LEAF_SHAPES.get(state.getValue(BigDripleafBlock.TILT)), (VoxelShape) BigDripleafBlock.STEM_SHAPES.get(state.getValue(BigDripleafBlock.FACING))); + } + +- public static void placeWithRandomHeight(LevelAccessor levelaccessor, RandomSource randomsource, BlockPos blockpos, Direction direction) { +- int i = Mth.nextInt(randomsource, 2, 5); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = blockpos.mutable(); ++ public static void placeWithRandomHeight(LevelAccessor level, RandomSource random, BlockPos pos, Direction direction) { ++ int i = Mth.nextInt(random, 2, 5); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); + int j = 0; + +- while (j < i && canPlaceAt(levelaccessor, blockpos_mutableblockpos, levelaccessor.getBlockState(blockpos_mutableblockpos))) { ++ while (j < i && canPlaceAt(level, blockposition_mutableblockposition, level.getBlockState(blockposition_mutableblockposition))) { + ++j; +- blockpos_mutableblockpos.move(Direction.UP); ++ blockposition_mutableblockposition.move(Direction.UP); + } + +- int k = blockpos.getY() + j - 1; ++ int k = pos.getY() + j - 1; + +- blockpos_mutableblockpos.setY(blockpos.getY()); ++ blockposition_mutableblockposition.setY(pos.getY()); + +- while (blockpos_mutableblockpos.getY() < k) { +- BigDripleafStemBlock.place(levelaccessor, blockpos_mutableblockpos, levelaccessor.getFluidState(blockpos_mutableblockpos), direction); +- blockpos_mutableblockpos.move(Direction.UP); ++ while (blockposition_mutableblockposition.getY() < k) { ++ BigDripleafStemBlock.place(level, blockposition_mutableblockposition, level.getFluidState(blockposition_mutableblockposition), direction); ++ blockposition_mutableblockposition.move(Direction.UP); + } + +- place(levelaccessor, blockpos_mutableblockpos, levelaccessor.getFluidState(blockpos_mutableblockpos), direction); ++ place(level, blockposition_mutableblockposition, level.getFluidState(blockposition_mutableblockposition), direction); + } + +- private static boolean canReplace(BlockState blockstate) { +- return blockstate.isAir() || blockstate.is(Blocks.WATER) || blockstate.is(Blocks.SMALL_DRIPLEAF); ++ private static boolean canReplace(IBlockData state) { ++ return state.isAir() || state.is(Blocks.WATER) || state.is(Blocks.SMALL_DRIPLEAF); + } + +- protected static boolean canPlaceAt(LevelHeightAccessor levelheightaccessor, BlockPos blockpos, BlockState blockstate) { +- return !levelheightaccessor.isOutsideBuildHeight(blockpos) && canReplace(blockstate); ++ protected static boolean canPlaceAt(LevelHeightAccessor level, BlockPos pos, IBlockData state) { ++ return !level.isOutsideBuildHeight(pos) && canReplace(state); + } + +- protected static boolean place(LevelAccessor levelaccessor, BlockPos blockpos, FluidState fluidstate, Direction direction) { +- BlockState blockstate = (BlockState) ((BlockState) Blocks.BIG_DRIPLEAF.defaultBlockState().setValue(BigDripleafBlock.WATERLOGGED, fluidstate.isSourceOfType(Fluids.WATER))).setValue(BigDripleafBlock.FACING, direction); ++ protected static boolean place(LevelAccessor level, BlockPos pos, FluidState fluidState, Direction direction) { ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.BIG_DRIPLEAF.defaultBlockState().setValue(BigDripleafBlock.WATERLOGGED, fluidState.isSourceOfType(Fluids.WATER))).setValue(BigDripleafBlock.FACING, direction); + +- return levelaccessor.setBlock(blockpos, blockstate, 3); ++ return level.setBlock(pos, iblockdata, 3); + } + + @Override +- @Override +- public void onProjectileHit(Level level, BlockState blockstate, BlockHitResult blockhitresult, Projectile projectile) { +- this.setTiltAndScheduleTick(blockstate, level, blockhitresult.getBlockPos(), Tilt.FULL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN); ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { ++ this.setTiltAndScheduleTick(state, level, hit.getBlockPos(), Tilt.FULL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN, projectile); // CraftBukkit + } + + @Override +- @Override +- public FluidState getFluidState(BlockState blockstate) { +- return (Boolean) blockstate.getValue(BigDripleafBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(blockstate); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(BigDripleafBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- BlockPos blockpos1 = blockpos.below(); +- BlockState blockstate1 = levelreader.getBlockState(blockpos1); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + +- return blockstate1.is((Block) this) || blockstate1.is(Blocks.BIG_DRIPLEAF_STEM) || blockstate1.is(BlockTags.BIG_DRIPLEAF_PLACEABLE); ++ return iblockdata1.is((Block) this) || iblockdata1.is(Blocks.BIG_DRIPLEAF_STEM) || iblockdata1.is(BlockTags.BIG_DRIPLEAF_PLACEABLE); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if (direction == Direction.DOWN && !blockstate.canSurvive(levelaccessor, blockpos)) { ++ public IBlockData updateShape(IBlockData state, Direction direction, IBlockData neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { ++ if (direction == Direction.DOWN && !state.canSurvive(level, pos)) { + return Blocks.AIR.defaultBlockState(); + } else { +- if ((Boolean) blockstate.getValue(BigDripleafBlock.WATERLOGGED)) { +- levelaccessor.scheduleTick(blockpos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(levelaccessor)); ++ if ((Boolean) state.getValue(BigDripleafBlock.WATERLOGGED)) { ++ level.scheduleTick(pos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + +- return direction == Direction.UP && blockstate1.is((Block) this) ? Blocks.BIG_DRIPLEAF_STEM.withPropertiesOf(blockstate) : super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return direction == Direction.UP && neighborState.is((Block) this) ? Blocks.BIG_DRIPLEAF_STEM.withPropertiesOf(state) : super.updateShape(state, direction, neighborState, level, pos, neighborPos); + } + } + + @Override +- @Override +- public boolean isValidBonemealTarget(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { +- BlockState blockstate1 = levelreader.getBlockState(blockpos.above()); ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ IBlockData iblockdata1 = iworldreader.getBlockState(blockposition.above()); + +- return canReplace(blockstate1); ++ return canReplace(iblockdata1); + } + + @Override +- @Override +- public boolean isBonemealSuccess(Level level, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return true; + } + + @Override +- @Override +- public void performBonemeal(ServerLevel serverlevel, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { +- BlockPos blockpos1 = blockpos.above(); +- BlockState blockstate1 = serverlevel.getBlockState(blockpos1); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ BlockPos blockposition1 = pos.above(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + +- if (canPlaceAt(serverlevel, blockpos1, blockstate1)) { +- Direction direction = (Direction) blockstate.getValue(BigDripleafBlock.FACING); ++ if (canPlaceAt(level, blockposition1, iblockdata1)) { ++ Direction enumdirection = (Direction) state.getValue(BigDripleafBlock.FACING); + +- BigDripleafStemBlock.place(serverlevel, blockpos, blockstate.getFluidState(), direction); +- place(serverlevel, blockpos1, blockstate1.getFluidState(), direction); ++ BigDripleafStemBlock.place(level, pos, state.getFluidState(), enumdirection); ++ place(level, blockposition1, iblockdata1.getFluidState(), enumdirection); + } + + } + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { + if (!level.isClientSide) { +- if (blockstate.getValue(BigDripleafBlock.TILT) == Tilt.NONE && canEntityTilt(blockpos, entity) && !level.hasNeighborSignal(blockpos)) { +- this.setTiltAndScheduleTick(blockstate, level, blockpos, Tilt.UNSTABLE, (SoundEvent) null); ++ if (state.getValue(BigDripleafBlock.TILT) == Tilt.NONE && canEntityTilt(pos, entity) && !level.hasNeighborSignal(pos)) { ++ // CraftBukkit start - tilt dripleaf ++ org.bukkit.event.Cancellable cancellable; ++ if (entity instanceof Player) { ++ cancellable = CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ if (cancellable.isCancelled()) { ++ return; ++ } ++ this.setTiltAndScheduleTick(state, level, pos, Tilt.UNSTABLE, (SoundEvent) null, entity); ++ // CraftBukkit end + } + + } + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (serverlevel.hasNeighborSignal(blockpos)) { +- resetTilt(blockstate, serverlevel, blockpos); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (level.hasNeighborSignal(pos)) { ++ resetTilt(state, level, pos); + } else { +- Tilt tilt = (Tilt) blockstate.getValue(BigDripleafBlock.TILT); ++ Tilt tilt = (Tilt) state.getValue(BigDripleafBlock.TILT); + + if (tilt == Tilt.UNSTABLE) { +- this.setTiltAndScheduleTick(blockstate, serverlevel, blockpos, Tilt.PARTIAL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN); ++ this.setTiltAndScheduleTick(state, level, pos, Tilt.PARTIAL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN, null); // CraftBukkit + } else if (tilt == Tilt.PARTIAL) { +- this.setTiltAndScheduleTick(blockstate, serverlevel, blockpos, Tilt.FULL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN); ++ this.setTiltAndScheduleTick(state, level, pos, Tilt.FULL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN, null); // CraftBukkit + } else if (tilt == Tilt.FULL) { +- resetTilt(blockstate, serverlevel, blockpos); ++ resetTilt(state, level, pos); + } + + } + } + + @Override +- @Override +- public void neighborChanged(BlockState blockstate, Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { +- if (level.hasNeighborSignal(blockpos)) { +- resetTilt(blockstate, level, blockpos); ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston) { ++ if (level.hasNeighborSignal(pos)) { ++ resetTilt(state, level, pos); + } + + } + +- private static void playTiltSound(Level level, BlockPos blockpos, SoundEvent soundevent) { ++ private static void playTiltSound(Level level, BlockPos pos, SoundEvent sound) { + float f = Mth.randomBetween(level.random, 0.8F, 1.2F); + +- level.playSound((Player) null, blockpos, soundevent, SoundSource.BLOCKS, 1.0F, f); ++ level.playSound((Player) null, pos, sound, SoundSource.BLOCKS, 1.0F, f); + } + +- private static boolean canEntityTilt(BlockPos blockpos, Entity entity) { +- return entity.onGround() && entity.position().y > (double) ((float) blockpos.getY() + 0.6875F); ++ private static boolean canEntityTilt(BlockPos pos, Entity entity) { ++ return entity.onGround() && entity.position().y > (double) ((float) pos.getY() + 0.6875F); + } + +- private void setTiltAndScheduleTick(BlockState blockstate, Level level, BlockPos blockpos, Tilt tilt, @Nullable SoundEvent soundevent) { +- setTilt(blockstate, level, blockpos, tilt); +- if (soundevent != null) { +- playTiltSound(level, blockpos, soundevent); ++ // CraftBukkit start ++ private void setTiltAndScheduleTick(IBlockData iblockdata, Level world, BlockPos blockposition, Tilt tilt, @Nullable SoundEvent soundeffect, @Nullable Entity entity) { ++ if (!setTilt(iblockdata, world, blockposition, tilt, entity)) return; ++ // CraftBukkit end ++ if (soundeffect != null) { ++ playTiltSound(world, blockposition, soundeffect); + } + + int i = BigDripleafBlock.DELAY_UNTIL_NEXT_TILT_STATE.getInt(tilt); + + if (i != -1) { +- level.scheduleTick(blockpos, (Block) this, i); ++ world.scheduleTick(blockposition, (Block) this, i); + } + + } + +- private static void resetTilt(BlockState blockstate, Level level, BlockPos blockpos) { +- setTilt(blockstate, level, blockpos, Tilt.NONE); +- if (blockstate.getValue(BigDripleafBlock.TILT) != Tilt.NONE) { +- playTiltSound(level, blockpos, SoundEvents.BIG_DRIPLEAF_TILT_UP); ++ private static void resetTilt(IBlockData state, Level level, BlockPos pos) { ++ setTilt(state, level, pos, Tilt.NONE, null); // CraftBukkit ++ if (state.getValue(BigDripleafBlock.TILT) != Tilt.NONE) { ++ playTiltSound(level, pos, SoundEvents.BIG_DRIPLEAF_TILT_UP); + } + + } + +- private static void setTilt(BlockState blockstate, Level level, BlockPos blockpos, Tilt tilt) { +- Tilt tilt1 = (Tilt) blockstate.getValue(BigDripleafBlock.TILT); ++ // CraftBukkit start ++ private static boolean setTilt(IBlockData iblockdata, Level world, BlockPos blockposition, Tilt tilt, @Nullable Entity entity) { ++ if (entity != null) { ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, iblockdata.setValue(BigDripleafBlock.TILT, tilt))) { ++ return false; ++ } ++ } ++ // CraftBukkit end ++ Tilt tilt1 = (Tilt) iblockdata.getValue(BigDripleafBlock.TILT); + +- level.setBlock(blockpos, (BlockState) blockstate.setValue(BigDripleafBlock.TILT, tilt), 2); ++ world.setBlock(blockposition, (IBlockData) iblockdata.setValue(BigDripleafBlock.TILT, tilt), 2); + if (tilt.causesVibration() && tilt != tilt1) { +- level.gameEvent((Entity) null, GameEvent.BLOCK_CHANGE, blockpos); ++ world.gameEvent((Entity) null, GameEvent.BLOCK_CHANGE, blockposition); + } + ++ return true; // CraftBukkit + } + + @Override +- @Override +- public VoxelShape getCollisionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return (VoxelShape) BigDripleafBlock.LEAF_SHAPES.get(blockstate.getValue(BigDripleafBlock.TILT)); ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (VoxelShape) BigDripleafBlock.LEAF_SHAPES.get(state.getValue(BigDripleafBlock.TILT)); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return (VoxelShape) this.shapesCache.get(blockstate); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (VoxelShape) this.shapesCache.get(state); + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- BlockState blockstate = blockplacecontext.getLevel().getBlockState(blockplacecontext.getClickedPos().below()); +- FluidState fluidstate = blockplacecontext.getLevel().getFluidState(blockplacecontext.getClickedPos()); +- boolean flag = blockstate.is(Blocks.BIG_DRIPLEAF) || blockstate.is(Blocks.BIG_DRIPLEAF_STEM); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ IBlockData iblockdata = context.getLevel().getBlockState(context.getClickedPos().below()); ++ FluidState fluid = context.getLevel().getFluidState(context.getClickedPos()); ++ boolean flag = iblockdata.is(Blocks.BIG_DRIPLEAF) || iblockdata.is(Blocks.BIG_DRIPLEAF_STEM); + +- return (BlockState) ((BlockState) this.defaultBlockState().setValue(BigDripleafBlock.WATERLOGGED, fluidstate.isSourceOfType(Fluids.WATER))).setValue(BigDripleafBlock.FACING, flag ? (Direction) blockstate.getValue(BigDripleafBlock.FACING) : blockplacecontext.getHorizontalDirection().getOpposite()); ++ return (IBlockData) ((IBlockData) this.defaultBlockState().setValue(BigDripleafBlock.WATERLOGGED, fluid.isSourceOfType(Fluids.WATER))).setValue(BigDripleafBlock.FACING, flag ? (Direction) iblockdata.getValue(BigDripleafBlock.FACING) : context.getHorizontalDirection().getOpposite()); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(BigDripleafBlock.WATERLOGGED, BigDripleafBlock.FACING, BigDripleafBlock.TILT); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(BigDripleafBlock.WATERLOGGED, BigDripleafBlock.FACING, BigDripleafBlock.TILT); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/Block.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/Block.java.patch new file mode 100644 index 0000000000..3fcc5a3846 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/Block.java.patch @@ -0,0 +1,647 @@ +--- a/net/minecraft/world/level/block/Block.java ++++ b/net/minecraft/world/level/block/Block.java +@@ -44,14 +44,14 @@ + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Explosion; + import net.minecraft.world.level.GameRules; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.biome.Biome; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.Property; + import net.minecraft.world.level.gameevent.GameEvent; +@@ -63,14 +63,13 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import org.slf4j.Logger; + +-public class Block extends BlockBehaviour implements ItemLike { ++public class Block extends BlockBehaviour implements IMaterial { + + public static final MapCodec CODEC = simpleCodec(Block::new); + private static final Logger LOGGER = LogUtils.getLogger(); + private final Holder.Reference builtInRegistryHolder; +- public static final IdMapper BLOCK_STATE_REGISTRY = new IdMapper<>(); ++ public static final IdMapper BLOCK_STATE_REGISTRY = new IdMapper<>(); + private static final LoadingCache SHAPE_FULL_BLOCK_CACHE = CacheBuilder.newBuilder().maximumSize(512L).weakKeys().build(new CacheLoader() { +- @Override + public Boolean load(VoxelShape voxelshape) { + return !Shapes.joinIsNotEmpty(Shapes.block(), voxelshape, BooleanOp.NOT_SAME); + } +@@ -88,8 +87,8 @@ + public static final float INDESTRUCTIBLE = -1.0F; + public static final float INSTANT = 0.0F; + public static final int UPDATE_LIMIT = 512; +- protected final StateDefinition stateDefinition; +- private BlockState defaultBlockState; ++ protected final StateDefinition stateDefinition; ++ private IBlockData defaultBlockState; + @Nullable + private String descriptionId; + @Nullable +@@ -97,7 +96,6 @@ + private static final int CACHE_SIZE = 2048; + private static final ThreadLocal> OCCLUSION_CACHE = ThreadLocal.withInitial(() -> { + Object2ByteLinkedOpenHashMap object2bytelinkedopenhashmap = new Object2ByteLinkedOpenHashMap(2048, 0.25F) { +- @Override + protected void rehash(int i) {} + }; + +@@ -106,38 +104,37 @@ + }); + + @Override +- @Override + protected MapCodec codec() { + return Block.CODEC; + } + +- public static int getId(@Nullable BlockState blockstate) { +- if (blockstate == null) { ++ public static int getId(@Nullable IBlockData state) { ++ if (state == null) { + return 0; + } else { +- int i = Block.BLOCK_STATE_REGISTRY.getId(blockstate); ++ int i = Block.BLOCK_STATE_REGISTRY.getId(state); + + return i == -1 ? 0 : i; + } + } + +- public static BlockState stateById(int i) { +- BlockState blockstate = (BlockState) Block.BLOCK_STATE_REGISTRY.byId(i); ++ public static IBlockData stateById(int id) { ++ IBlockData iblockdata = (IBlockData) Block.BLOCK_STATE_REGISTRY.byId(id); + +- return blockstate == null ? Blocks.AIR.defaultBlockState() : blockstate; ++ return iblockdata == null ? Blocks.AIR.defaultBlockState() : iblockdata; + } + + public static Block byItem(@Nullable Item item) { + return item instanceof BlockItem ? ((BlockItem) item).getBlock() : Blocks.AIR; + } + +- public static BlockState pushEntitiesUp(BlockState blockstate, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos) { +- VoxelShape voxelshape = Shapes.joinUnoptimized(blockstate.getCollisionShape(levelaccessor, blockpos), blockstate1.getCollisionShape(levelaccessor, blockpos), BooleanOp.ONLY_SECOND).move((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ()); ++ public static IBlockData pushEntitiesUp(IBlockData oldState, IBlockData newState, LevelAccessor level, BlockPos pos) { ++ VoxelShape voxelshape = Shapes.joinUnoptimized(oldState.getCollisionShape(level, pos), newState.getCollisionShape(level, pos), BooleanOp.ONLY_SECOND).move((double) pos.getX(), (double) pos.getY(), (double) pos.getZ()); + + if (voxelshape.isEmpty()) { +- return blockstate1; ++ return newState; + } else { +- List list = levelaccessor.getEntities((Entity) null, voxelshape.bounds()); ++ List list = level.getEntities((Entity) null, voxelshape.bounds()); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +@@ -147,55 +144,55 @@ + entity.teleportRelative(0.0D, 1.0D + d0, 0.0D); + } + +- return blockstate1; ++ return newState; + } + } + +- public static VoxelShape box(double d0, double d1, double d2, double d3, double d4, double d5) { +- return Shapes.box(d0 / 16.0D, d1 / 16.0D, d2 / 16.0D, d3 / 16.0D, d4 / 16.0D, d5 / 16.0D); ++ public static VoxelShape box(double x1, double d1, double y1, double d3, double z1, double d5) { ++ return Shapes.box(x1 / 16.0D, d1 / 16.0D, y1 / 16.0D, d3 / 16.0D, z1 / 16.0D, d5 / 16.0D); + } + +- public static BlockState updateFromNeighbourShapes(BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos) { +- BlockState blockstate1 = blockstate; +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); +- Direction[] adirection = Block.UPDATE_SHAPE_ORDER; +- int i = adirection.length; ++ public static IBlockData updateFromNeighbourShapes(IBlockData currentState, LevelAccessor level, BlockPos pos) { ++ IBlockData iblockdata1 = currentState; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ Direction[] aenumdirection = Block.UPDATE_SHAPE_ORDER; ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; ++ Direction enumdirection = aenumdirection[j]; + +- blockpos_mutableblockpos.setWithOffset(blockpos, direction); +- blockstate1 = blockstate1.updateShape(direction, levelaccessor.getBlockState(blockpos_mutableblockpos), levelaccessor, blockpos, blockpos_mutableblockpos); ++ blockposition_mutableblockposition.setWithOffset(pos, enumdirection); ++ iblockdata1 = iblockdata1.updateShape(enumdirection, level.getBlockState(blockposition_mutableblockposition), level, pos, blockposition_mutableblockposition); + } + +- return blockstate1; ++ return iblockdata1; + } + +- public static void updateOrDestroy(BlockState blockstate, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, int i) { +- updateOrDestroy(blockstate, blockstate1, levelaccessor, blockpos, i, 512); ++ public static void updateOrDestroy(IBlockData oldState, IBlockData newState, LevelAccessor level, BlockPos pos, int flags) { ++ updateOrDestroy(oldState, newState, level, pos, flags, 512); + } + +- public static void updateOrDestroy(BlockState blockstate, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, int i, int j) { +- if (blockstate1 != blockstate) { +- if (blockstate1.isAir()) { +- if (!levelaccessor.isClientSide()) { +- levelaccessor.destroyBlock(blockpos, (i & 32) == 0, (Entity) null, j); ++ public static void updateOrDestroy(IBlockData oldState, IBlockData newState, LevelAccessor level, BlockPos pos, int flags, int recursionLeft) { ++ if (newState != oldState) { ++ if (newState.isAir()) { ++ if (!level.isClientSide()) { ++ level.destroyBlock(pos, (flags & 32) == 0, (Entity) null, recursionLeft); + } + } else { +- levelaccessor.setBlock(blockpos, blockstate1, i & -33, j); ++ level.setBlock(pos, newState, flags & -33, recursionLeft); + } + } + + } + +- public Block(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ public Block(BlockBehaviour.Properties properties) { ++ super(properties); + this.builtInRegistryHolder = BuiltInRegistries.BLOCK.createIntrusiveHolder(this); +- StateDefinition.Builder statedefinition_builder = new StateDefinition.Builder<>(this); ++ StateDefinition.Builder blockstatelist_a = new StateDefinition.Builder<>(this); + +- this.createBlockStateDefinition(statedefinition_builder); +- this.stateDefinition = statedefinition_builder.create(Block::defaultBlockState, BlockState::new); +- this.registerDefaultState((BlockState) this.stateDefinition.any()); ++ this.createBlockStateDefinition(blockstatelist_a); ++ this.stateDefinition = blockstatelist_a.create(Block::defaultBlockState, IBlockData::new); ++ this.registerDefaultState((IBlockData) this.stateDefinition.any()); + if (SharedConstants.IS_RUNNING_IN_IDE) { + String s = this.getClass().getSimpleName(); + +@@ -206,40 +203,40 @@ + + } + +- public static boolean isExceptionForConnection(BlockState blockstate) { +- return blockstate.getBlock() instanceof LeavesBlock || blockstate.is(Blocks.BARRIER) || blockstate.is(Blocks.CARVED_PUMPKIN) || blockstate.is(Blocks.JACK_O_LANTERN) || blockstate.is(Blocks.MELON) || blockstate.is(Blocks.PUMPKIN) || blockstate.is(BlockTags.SHULKER_BOXES); ++ public static boolean isExceptionForConnection(IBlockData state) { ++ return state.getBlock() instanceof LeavesBlock || state.is(Blocks.BARRIER) || state.is(Blocks.CARVED_PUMPKIN) || state.is(Blocks.JACK_O_LANTERN) || state.is(Blocks.MELON) || state.is(Blocks.PUMPKIN) || state.is(BlockTags.SHULKER_BOXES); + } + +- public boolean isRandomlyTicking(BlockState blockstate) { ++ public boolean isRandomlyTicking(IBlockData state) { + return this.isRandomlyTicking; + } + +- public static boolean shouldRenderFace(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction, BlockPos blockpos1) { +- BlockState blockstate1 = blockgetter.getBlockState(blockpos1); ++ public static boolean shouldRenderFace(IBlockData state, BlockGetter level, BlockPos offset, Direction face, BlockPos pos) { ++ IBlockData iblockdata1 = level.getBlockState(pos); + +- if (blockstate.skipRendering(blockstate1, direction)) { ++ if (state.skipRendering(iblockdata1, face)) { + return false; +- } else if (blockstate1.canOcclude()) { +- Block.BlockStatePairKey block_blockstatepairkey = new Block.BlockStatePairKey(blockstate, blockstate1, direction); ++ } else if (iblockdata1.canOcclude()) { ++ Block.BlockStatePairKey block_a = new Block.BlockStatePairKey(state, iblockdata1, face); + Object2ByteLinkedOpenHashMap object2bytelinkedopenhashmap = (Object2ByteLinkedOpenHashMap) Block.OCCLUSION_CACHE.get(); +- byte b0 = object2bytelinkedopenhashmap.getAndMoveToFirst(block_blockstatepairkey); ++ byte b0 = object2bytelinkedopenhashmap.getAndMoveToFirst(block_a); + + if (b0 != 127) { + return b0 != 0; + } else { +- VoxelShape voxelshape = blockstate.getFaceOcclusionShape(blockgetter, blockpos, direction); ++ VoxelShape voxelshape = state.getFaceOcclusionShape(level, offset, face); + + if (voxelshape.isEmpty()) { + return true; + } else { +- VoxelShape voxelshape1 = blockstate1.getFaceOcclusionShape(blockgetter, blockpos1, direction.getOpposite()); ++ VoxelShape voxelshape1 = iblockdata1.getFaceOcclusionShape(level, pos, face.getOpposite()); + boolean flag = Shapes.joinIsNotEmpty(voxelshape, voxelshape1, BooleanOp.ONLY_FIRST); + + if (object2bytelinkedopenhashmap.size() == 2048) { + object2bytelinkedopenhashmap.removeLastByte(); + } + +- object2bytelinkedopenhashmap.putAndMoveToFirst(block_blockstatepairkey, (byte) (flag ? 1 : 0)); ++ object2bytelinkedopenhashmap.putAndMoveToFirst(block_a, (byte) (flag ? 1 : 0)); + return flag; + } + } +@@ -248,117 +245,123 @@ + } + } + +- public static boolean canSupportRigidBlock(BlockGetter blockgetter, BlockPos blockpos) { +- return blockgetter.getBlockState(blockpos).isFaceSturdy(blockgetter, blockpos, Direction.UP, SupportType.RIGID); ++ public static boolean canSupportRigidBlock(BlockGetter level, BlockPos pos) { ++ return level.getBlockState(pos).isFaceSturdy(level, pos, Direction.UP, SupportType.RIGID); + } + +- public static boolean canSupportCenter(LevelReader levelreader, BlockPos blockpos, Direction direction) { +- BlockState blockstate = levelreader.getBlockState(blockpos); ++ public static boolean canSupportCenter(LevelReader level, BlockPos pos, Direction direction) { ++ IBlockData iblockdata = level.getBlockState(pos); + +- return direction == Direction.DOWN && blockstate.is(BlockTags.UNSTABLE_BOTTOM_CENTER) ? false : blockstate.isFaceSturdy(levelreader, blockpos, direction, SupportType.CENTER); ++ return direction == Direction.DOWN && iblockdata.is(BlockTags.UNSTABLE_BOTTOM_CENTER) ? false : iblockdata.isFaceSturdy(level, pos, direction, SupportType.CENTER); + } + +- public static boolean isFaceFull(VoxelShape voxelshape, Direction direction) { +- VoxelShape voxelshape1 = voxelshape.getFaceShape(direction); ++ public static boolean isFaceFull(VoxelShape shape, Direction face) { ++ VoxelShape voxelshape1 = shape.getFaceShape(face); + + return isShapeFullBlock(voxelshape1); + } + +- public static boolean isShapeFullBlock(VoxelShape voxelshape) { +- return (Boolean) Block.SHAPE_FULL_BLOCK_CACHE.getUnchecked(voxelshape); ++ public static boolean isShapeFullBlock(VoxelShape shape) { ++ return (Boolean) Block.SHAPE_FULL_BLOCK_CACHE.getUnchecked(shape); + } + +- public boolean propagatesSkylightDown(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return !isShapeFullBlock(blockstate.getShape(blockgetter, blockpos)) && blockstate.getFluidState().isEmpty(); ++ public boolean propagatesSkylightDown(IBlockData state, BlockGetter level, BlockPos pos) { ++ return !isShapeFullBlock(state.getShape(level, pos)) && state.getFluidState().isEmpty(); + } + +- public void animateTick(BlockState blockstate, Level level, BlockPos blockpos, RandomSource randomsource) {} ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) {} + +- public void destroy(LevelAccessor levelaccessor, BlockPos blockpos, BlockState blockstate) {} ++ public void destroy(LevelAccessor level, BlockPos pos, IBlockData state) {} + +- public static List getDrops(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, @Nullable BlockEntity blockentity) { +- LootParams.Builder lootparams_builder = (new LootParams.Builder(serverlevel)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockpos)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withOptionalParameter(LootContextParams.BLOCK_ENTITY, blockentity); ++ public static List getDrops(IBlockData state, ServerLevel level, BlockPos pos, @Nullable BlockEntity blockEntity) { ++ LootParams.Builder lootparams_a = (new LootParams.Builder(level)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withOptionalParameter(LootContextParams.BLOCK_ENTITY, blockEntity); + +- return blockstate.getDrops(lootparams_builder); ++ return state.getDrops(lootparams_a); + } + +- public static List getDrops(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, @Nullable BlockEntity blockentity, @Nullable Entity entity, ItemStack itemstack) { +- LootParams.Builder lootparams_builder = (new LootParams.Builder(serverlevel)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockpos)).withParameter(LootContextParams.TOOL, itemstack).withOptionalParameter(LootContextParams.THIS_ENTITY, entity).withOptionalParameter(LootContextParams.BLOCK_ENTITY, blockentity); ++ public static List getDrops(IBlockData state, ServerLevel level, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool) { ++ LootParams.Builder lootparams_a = (new LootParams.Builder(level)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos)).withParameter(LootContextParams.TOOL, tool).withOptionalParameter(LootContextParams.THIS_ENTITY, entity).withOptionalParameter(LootContextParams.BLOCK_ENTITY, blockEntity); + +- return blockstate.getDrops(lootparams_builder); ++ return state.getDrops(lootparams_a); + } + +- public static void dropResources(BlockState blockstate, Level level, BlockPos blockpos) { ++ public static void dropResources(IBlockData state, Level level, BlockPos pos) { + if (level instanceof ServerLevel) { +- getDrops(blockstate, (ServerLevel) level, blockpos, (BlockEntity) null).forEach((itemstack) -> { +- popResource(level, blockpos, itemstack); ++ getDrops(state, (ServerLevel) level, pos, (BlockEntity) null).forEach((itemstack) -> { ++ popResource(level, pos, itemstack); + }); +- blockstate.spawnAfterBreak((ServerLevel) level, blockpos, ItemStack.EMPTY, true); ++ state.spawnAfterBreak((ServerLevel) level, pos, ItemStack.EMPTY, true); + } + + } + +- public static void dropResources(BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos, @Nullable BlockEntity blockentity) { +- if (levelaccessor instanceof ServerLevel) { +- getDrops(blockstate, (ServerLevel) levelaccessor, blockpos, blockentity).forEach((itemstack) -> { +- popResource((ServerLevel) levelaccessor, blockpos, itemstack); ++ public static void dropResources(IBlockData state, LevelAccessor level, BlockPos pos, @Nullable BlockEntity blockEntity) { ++ if (level instanceof ServerLevel) { ++ getDrops(state, (ServerLevel) level, pos, blockEntity).forEach((itemstack) -> { ++ popResource((ServerLevel) level, pos, itemstack); + }); +- blockstate.spawnAfterBreak((ServerLevel) levelaccessor, blockpos, ItemStack.EMPTY, true); ++ state.spawnAfterBreak((ServerLevel) level, pos, ItemStack.EMPTY, true); + } + + } + +- public static void dropResources(BlockState blockstate, Level level, BlockPos blockpos, @Nullable BlockEntity blockentity, @Nullable Entity entity, ItemStack itemstack) { ++ public static void dropResources(IBlockData state, Level level, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool) { + if (level instanceof ServerLevel) { +- getDrops(blockstate, (ServerLevel) level, blockpos, blockentity, entity, itemstack).forEach((itemstack1) -> { +- popResource(level, blockpos, itemstack1); ++ getDrops(state, (ServerLevel) level, pos, blockEntity, entity, tool).forEach((itemstack1) -> { ++ popResource(level, pos, itemstack1); + }); +- blockstate.spawnAfterBreak((ServerLevel) level, blockpos, itemstack, true); ++ state.spawnAfterBreak((ServerLevel) level, pos, tool, true); + } + + } + +- public static void popResource(Level level, BlockPos blockpos, ItemStack itemstack) { ++ public static void popResource(Level level, BlockPos pos, ItemStack stack) { + double d0 = (double) EntityType.ITEM.getHeight() / 2.0D; +- double d1 = (double) blockpos.getX() + 0.5D + Mth.nextDouble(level.random, -0.25D, 0.25D); +- double d2 = (double) blockpos.getY() + 0.5D + Mth.nextDouble(level.random, -0.25D, 0.25D) - d0; +- double d3 = (double) blockpos.getZ() + 0.5D + Mth.nextDouble(level.random, -0.25D, 0.25D); ++ double d1 = (double) pos.getX() + 0.5D + Mth.nextDouble(level.random, -0.25D, 0.25D); ++ double d2 = (double) pos.getY() + 0.5D + Mth.nextDouble(level.random, -0.25D, 0.25D) - d0; ++ double d3 = (double) pos.getZ() + 0.5D + Mth.nextDouble(level.random, -0.25D, 0.25D); + + popResource(level, () -> { +- return new ItemEntity(level, d1, d2, d3, itemstack); +- }, itemstack); ++ return new ItemEntity(level, d1, d2, d3, stack); ++ }, stack); + } + +- public static void popResourceFromFace(Level level, BlockPos blockpos, Direction direction, ItemStack itemstack) { ++ public static void popResourceFromFace(Level level, BlockPos pos, Direction direction, ItemStack stack) { + int i = direction.getStepX(); + int j = direction.getStepY(); + int k = direction.getStepZ(); + double d0 = (double) EntityType.ITEM.getWidth() / 2.0D; + double d1 = (double) EntityType.ITEM.getHeight() / 2.0D; +- double d2 = (double) blockpos.getX() + 0.5D + (i == 0 ? Mth.nextDouble(level.random, -0.25D, 0.25D) : (double) i * (0.5D + d0)); +- double d3 = (double) blockpos.getY() + 0.5D + (j == 0 ? Mth.nextDouble(level.random, -0.25D, 0.25D) : (double) j * (0.5D + d1)) - d1; +- double d4 = (double) blockpos.getZ() + 0.5D + (k == 0 ? Mth.nextDouble(level.random, -0.25D, 0.25D) : (double) k * (0.5D + d0)); ++ double d2 = (double) pos.getX() + 0.5D + (i == 0 ? Mth.nextDouble(level.random, -0.25D, 0.25D) : (double) i * (0.5D + d0)); ++ double d3 = (double) pos.getY() + 0.5D + (j == 0 ? Mth.nextDouble(level.random, -0.25D, 0.25D) : (double) j * (0.5D + d1)) - d1; ++ double d4 = (double) pos.getZ() + 0.5D + (k == 0 ? Mth.nextDouble(level.random, -0.25D, 0.25D) : (double) k * (0.5D + d0)); + double d5 = i == 0 ? Mth.nextDouble(level.random, -0.1D, 0.1D) : (double) i * 0.1D; + double d6 = j == 0 ? Mth.nextDouble(level.random, 0.0D, 0.1D) : (double) j * 0.1D + 0.1D; + double d7 = k == 0 ? Mth.nextDouble(level.random, -0.1D, 0.1D) : (double) k * 0.1D; + + popResource(level, () -> { +- return new ItemEntity(level, d2, d3, d4, itemstack, d5, d6, d7); +- }, itemstack); ++ return new ItemEntity(level, d2, d3, d4, stack, d5, d6, d7); ++ }, stack); + } + +- private static void popResource(Level level, Supplier supplier, ItemStack itemstack) { +- if (!level.isClientSide && !itemstack.isEmpty() && level.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { +- ItemEntity itementity = (ItemEntity) supplier.get(); ++ private static void popResource(Level level, Supplier itemEntitySupplier, ItemStack stack) { ++ if (!level.isClientSide && !stack.isEmpty() && level.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { ++ ItemEntity entityitem = (ItemEntity) itemEntitySupplier.get(); + +- itementity.setDefaultPickUpDelay(); +- level.addFreshEntity(itementity); ++ entityitem.setDefaultPickUpDelay(); ++ // CraftBukkit start ++ if (level.captureDrops != null) { ++ level.captureDrops.add(entityitem); ++ } else { ++ level.addFreshEntity(entityitem); ++ } ++ // CraftBukkit end + } + } + +- protected void popExperience(ServerLevel serverlevel, BlockPos blockpos, int i) { +- if (serverlevel.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { +- ExperienceOrb.award(serverlevel, Vec3.atCenterOf(blockpos), i); ++ public void popExperience(ServerLevel level, BlockPos pos, int amount) { ++ if (level.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { ++ ExperienceOrb.award(level, Vec3.atCenterOf(pos), amount); + } + + } +@@ -367,25 +370,25 @@ + return this.explosionResistance; + } + +- public void wasExploded(Level level, BlockPos blockpos, Explosion explosion) {} ++ public void wasExploded(Level level, BlockPos pos, Explosion explosion) {} + +- public void stepOn(Level level, BlockPos blockpos, BlockState blockstate, Entity entity) {} ++ public void stepOn(Level level, BlockPos pos, IBlockData state, Entity entity) {} + + @Nullable +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { + return this.defaultBlockState(); + } + +- public void playerDestroy(Level level, Player player, BlockPos blockpos, BlockState blockstate, @Nullable BlockEntity blockentity, ItemStack itemstack) { ++ public void playerDestroy(Level level, Player player, BlockPos pos, IBlockData state, @Nullable BlockEntity blockEntity, ItemStack tool) { + player.awardStat(Stats.BLOCK_MINED.get(this)); +- player.causeFoodExhaustion(0.005F); +- dropResources(blockstate, level, blockpos, blockentity, player, itemstack); ++ player.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED); // CraftBukkit - EntityExhaustionEvent ++ dropResources(state, level, pos, blockEntity, player, tool); + } + +- public void setPlacedBy(Level level, BlockPos blockpos, BlockState blockstate, @Nullable LivingEntity livingentity, ItemStack itemstack) {} ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, @Nullable LivingEntity placer, ItemStack stack) {} + +- public boolean isPossibleToRespawnInThis(BlockState blockstate) { +- return !blockstate.isSolid() && !blockstate.liquid(); ++ public boolean isPossibleToRespawnInThis(IBlockData state) { ++ return !state.isSolid() && !state.liquid(); + } + + public MutableComponent getName() { +@@ -400,15 +403,15 @@ + return this.descriptionId; + } + +- public void fallOn(Level level, BlockState blockstate, BlockPos blockpos, Entity entity, float f) { +- entity.causeFallDamage(f, 1.0F, entity.damageSources().fall()); ++ public void fallOn(Level level, IBlockData state, BlockPos pos, Entity entity, float fallDistance) { ++ entity.causeFallDamage(fallDistance, 1.0F, entity.damageSources().fall()); + } + +- public void updateEntityAfterFallOn(BlockGetter blockgetter, Entity entity) { ++ public void updateEntityAfterFallOn(BlockGetter level, Entity entity) { + entity.setDeltaMovement(entity.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D)); + } + +- public ItemStack getCloneItemStack(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { ++ public ItemStack getCloneItemStack(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { + return new ItemStack(this); + } + +@@ -424,65 +427,64 @@ + return this.jumpFactor; + } + +- protected void spawnDestroyParticles(Level level, Player player, BlockPos blockpos, BlockState blockstate) { +- level.levelEvent(player, 2001, blockpos, getId(blockstate)); ++ protected void spawnDestroyParticles(Level level, Player player, BlockPos pos, IBlockData state) { ++ level.levelEvent(player, 2001, pos, getId(state)); + } + +- public BlockState playerWillDestroy(Level level, BlockPos blockpos, BlockState blockstate, Player player) { +- this.spawnDestroyParticles(level, player, blockpos, blockstate); +- if (blockstate.is(BlockTags.GUARDED_BY_PIGLINS)) { +- PiglinAi.angerNearbyPiglins(player, false); ++ public IBlockData playerWillDestroy(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ this.spawnDestroyParticles(world, entityhuman, blockposition, iblockdata); ++ if (iblockdata.is(BlockTags.GUARDED_BY_PIGLINS)) { ++ PiglinAi.angerNearbyPiglins(entityhuman, false); + } + +- level.gameEvent(GameEvent.BLOCK_DESTROY, blockpos, GameEvent.Context.of(player, blockstate)); +- return blockstate; ++ world.gameEvent(GameEvent.BLOCK_DESTROY, blockposition, GameEvent.Context.of(entityhuman, iblockdata)); ++ return iblockdata; + } + +- public void handlePrecipitation(BlockState blockstate, Level level, BlockPos blockpos, Biome.Precipitation biome_precipitation) {} ++ public void handlePrecipitation(IBlockData state, Level level, BlockPos pos, Biome.Precipitation precipitation) {} + + public boolean dropFromExplosion(Explosion explosion) { + return true; + } + +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) {} ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) {} + +- public StateDefinition getStateDefinition() { ++ public StateDefinition getStateDefinition() { + return this.stateDefinition; + } + +- protected final void registerDefaultState(BlockState blockstate) { +- this.defaultBlockState = blockstate; ++ protected final void registerDefaultState(IBlockData state) { ++ this.defaultBlockState = state; + } + +- public final BlockState defaultBlockState() { ++ public final IBlockData defaultBlockState() { + return this.defaultBlockState; + } + +- public final BlockState withPropertiesOf(BlockState blockstate) { +- BlockState blockstate1 = this.defaultBlockState(); +- Iterator iterator = blockstate.getBlock().getStateDefinition().getProperties().iterator(); ++ public final IBlockData withPropertiesOf(IBlockData state) { ++ IBlockData iblockdata1 = this.defaultBlockState(); ++ Iterator iterator = state.getBlock().getStateDefinition().getProperties().iterator(); + + while (iterator.hasNext()) { +- Property property = (Property) iterator.next(); ++ Property iblockstate = (Property) iterator.next(); + +- if (blockstate1.hasProperty(property)) { +- blockstate1 = copyProperty(blockstate, blockstate1, property); ++ if (iblockdata1.hasProperty(iblockstate)) { ++ iblockdata1 = copyProperty(state, iblockdata1, iblockstate); + } + } + +- return blockstate1; ++ return iblockdata1; + } + +- private static > BlockState copyProperty(BlockState blockstate, BlockState blockstate1, Property property) { +- return (BlockState) blockstate1.setValue(property, blockstate.getValue(property)); ++ private static > IBlockData copyProperty(IBlockData sourceState, IBlockData targetState, Property property) { ++ return (IBlockData) targetState.setValue(property, sourceState.getValue(property)); + } + +- public SoundType getSoundType(BlockState blockstate) { ++ public SoundType getSoundType(IBlockData state) { + return this.soundType; + } + + @Override +- @Override + public Item asItem() { + if (this.item == null) { + this.item = Item.byBlock(this); +@@ -495,21 +497,19 @@ + return this.dynamicShape; + } + +- @Override + public String toString() { + return "Block{" + BuiltInRegistries.BLOCK.getKey(this) + "}"; + } + +- public void appendHoverText(ItemStack itemstack, @Nullable BlockGetter blockgetter, List list, TooltipFlag tooltipflag) {} ++ public void appendHoverText(ItemStack stack, @Nullable BlockGetter level, List tooltip, TooltipFlag flag) {} + + @Override +- @Override + protected Block asBlock() { + return this; + } + +- protected ImmutableMap getShapeForEachState(Function function) { +- return (ImmutableMap) this.stateDefinition.getPossibleStates().stream().collect(ImmutableMap.toImmutableMap(Function.identity(), function)); ++ protected ImmutableMap getShapeForEachState(Function shapeGetter) { ++ return (ImmutableMap) this.stateDefinition.getPossibleStates().stream().collect(ImmutableMap.toImmutableMap(Function.identity(), shapeGetter)); + } + + /** @deprecated */ +@@ -518,43 +518,49 @@ + return this.builtInRegistryHolder; + } + +- protected void tryDropExperience(ServerLevel serverlevel, BlockPos blockpos, ItemStack itemstack, IntProvider intprovider) { ++ // CraftBukkit start ++ protected int tryDropExperience(ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, IntProvider intprovider) { + if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, itemstack) == 0) { +- int i = intprovider.sample(serverlevel.random); ++ int i = intprovider.sample(worldserver.random); + + if (i > 0) { +- this.popExperience(serverlevel, blockpos, i); ++ // this.popExperience(worldserver, blockposition, i); ++ return i; + } + } + ++ return 0; + } + ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { ++ return 0; ++ } ++ // CraftBukkit end ++ + public static final class BlockStatePairKey { + +- private final BlockState first; +- private final BlockState second; ++ private final IBlockData first; ++ private final IBlockData second; + private final Direction direction; + +- public BlockStatePairKey(BlockState blockstate, BlockState blockstate1, Direction direction) { +- this.first = blockstate; +- this.second = blockstate1; ++ public BlockStatePairKey(IBlockData first, IBlockData second, Direction direction) { ++ this.first = first; ++ this.second = second; + this.direction = direction; + } + +- @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } else if (!(object instanceof Block.BlockStatePairKey)) { + return false; + } else { +- Block.BlockStatePairKey block_blockstatepairkey = (Block.BlockStatePairKey) object; ++ Block.BlockStatePairKey block_a = (Block.BlockStatePairKey) object; + +- return this.first == block_blockstatepairkey.first && this.second == block_blockstatepairkey.second && this.direction == block_blockstatepairkey.direction; ++ return this.first == block_a.first && this.second == block_a.second && this.direction == block_a.direction; + } + } + +- @Override + public int hashCode() { + int i = this.first.hashCode(); + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BuddingAmethystBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BuddingAmethystBlock.java.patch new file mode 100644 index 0000000000..1f93242eb5 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BuddingAmethystBlock.java.patch @@ -0,0 +1,71 @@ +--- a/net/minecraft/world/level/block/BuddingAmethystBlock.java ++++ b/net/minecraft/world/level/block/BuddingAmethystBlock.java +@@ -6,7 +6,7 @@ + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.RandomSource; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.Fluids; + + public class BuddingAmethystBlock extends AmethystBlock { +@@ -16,44 +16,42 @@ + private static final Direction[] DIRECTIONS = Direction.values(); + + @Override +- @Override + public MapCodec codec() { + return BuddingAmethystBlock.CODEC; + } + +- public BuddingAmethystBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ public BuddingAmethystBlock(BlockBehaviour.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (randomsource.nextInt(5) == 0) { +- Direction direction = BuddingAmethystBlock.DIRECTIONS[randomsource.nextInt(BuddingAmethystBlock.DIRECTIONS.length)]; +- BlockPos blockpos1 = blockpos.relative(direction); +- BlockState blockstate1 = serverlevel.getBlockState(blockpos1); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (random.nextInt(5) == 0) { ++ Direction enumdirection = BuddingAmethystBlock.DIRECTIONS[random.nextInt(BuddingAmethystBlock.DIRECTIONS.length)]; ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + Block block = null; + +- if (canClusterGrowAtState(blockstate1)) { ++ if (canClusterGrowAtState(iblockdata1)) { + block = Blocks.SMALL_AMETHYST_BUD; +- } else if (blockstate1.is(Blocks.SMALL_AMETHYST_BUD) && blockstate1.getValue(AmethystClusterBlock.FACING) == direction) { ++ } else if (iblockdata1.is(Blocks.SMALL_AMETHYST_BUD) && iblockdata1.getValue(AmethystClusterBlock.FACING) == enumdirection) { + block = Blocks.MEDIUM_AMETHYST_BUD; +- } else if (blockstate1.is(Blocks.MEDIUM_AMETHYST_BUD) && blockstate1.getValue(AmethystClusterBlock.FACING) == direction) { ++ } else if (iblockdata1.is(Blocks.MEDIUM_AMETHYST_BUD) && iblockdata1.getValue(AmethystClusterBlock.FACING) == enumdirection) { + block = Blocks.LARGE_AMETHYST_BUD; +- } else if (blockstate1.is(Blocks.LARGE_AMETHYST_BUD) && blockstate1.getValue(AmethystClusterBlock.FACING) == direction) { ++ } else if (iblockdata1.is(Blocks.LARGE_AMETHYST_BUD) && iblockdata1.getValue(AmethystClusterBlock.FACING) == enumdirection) { + block = Blocks.AMETHYST_CLUSTER; + } + + if (block != null) { +- BlockState blockstate2 = (BlockState) ((BlockState) block.defaultBlockState().setValue(AmethystClusterBlock.FACING, direction)).setValue(AmethystClusterBlock.WATERLOGGED, blockstate1.getFluidState().getType() == Fluids.WATER); ++ IBlockData iblockdata2 = (IBlockData) ((IBlockData) block.defaultBlockState().setValue(AmethystClusterBlock.FACING, enumdirection)).setValue(AmethystClusterBlock.WATERLOGGED, iblockdata1.getFluidState().getType() == Fluids.WATER); + +- serverlevel.setBlockAndUpdate(blockpos1, blockstate2); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition1, iblockdata2); // CraftBukkit + } + + } + } + +- public static boolean canClusterGrowAtState(BlockState blockstate) { +- return blockstate.isAir() || blockstate.is(Blocks.WATER) && blockstate.getFluidState().getAmount() == 8; ++ public static boolean canClusterGrowAtState(IBlockData state) { ++ return state.isAir() || state.is(Blocks.WATER) && state.getFluidState().getAmount() == 8; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BushBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BushBlock.java.patch new file mode 100644 index 0000000000..cf8a82d88c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/BushBlock.java.patch @@ -0,0 +1,71 @@ +--- a/net/minecraft/world/level/block/BushBlock.java ++++ b/net/minecraft/world/level/block/BushBlock.java +@@ -8,46 +8,48 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.pathfinder.PathMode; + + public abstract class BushBlock extends Block { + +- protected BushBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ protected BushBlock(BlockBehaviour.Properties properties) { ++ super(properties); + } + + @Override +- @Override + protected abstract MapCodec codec(); + +- protected boolean mayPlaceOn(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return blockstate.is(BlockTags.DIRT) || blockstate.is(Blocks.FARMLAND); ++ protected boolean mayPlaceOn(IBlockData state, BlockGetter level, BlockPos pos) { ++ return state.is(BlockTags.DIRT) || state.is(Blocks.FARMLAND); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- return !blockstate.canSurvive(levelaccessor, blockpos) ? Blocks.AIR.defaultBlockState() : super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ // CraftBukkit start ++ if (!state.canSurvive(level, currentPos)) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(level, currentPos).isCancelled()) { ++ return Blocks.AIR.defaultBlockState(); ++ } ++ } ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ // CraftBukkit end + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- BlockPos blockpos1 = blockpos.below(); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.below(); + +- return this.mayPlaceOn(levelreader.getBlockState(blockpos1), levelreader, blockpos1); ++ return this.mayPlaceOn(level.getBlockState(blockposition1), level, blockposition1); + } + + @Override +- @Override +- public boolean propagatesSkylightDown(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return blockstate.getFluidState().isEmpty(); ++ public boolean propagatesSkylightDown(IBlockData state, BlockGetter reader, BlockPos pos) { ++ return state.getFluidState().isEmpty(); + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { +- return pathcomputationtype == PathComputationType.AIR && !this.hasCollision ? true : super.isPathfindable(blockstate, blockgetter, blockpos, pathcomputationtype); ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { ++ return type == PathMode.AIR && !this.hasCollision ? true : super.isPathfindable(state, level, pos, type); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ButtonBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ButtonBlock.java.patch new file mode 100644 index 0000000000..601cd179d8 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ButtonBlock.java.patch @@ -0,0 +1,294 @@ +--- a/net/minecraft/world/level/block/ButtonBlock.java ++++ b/net/minecraft/world/level/block/ButtonBlock.java +@@ -11,7 +11,7 @@ + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundSource; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; +@@ -22,7 +22,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.AttachFace; + import net.minecraft.world.level.block.state.properties.BlockSetType; +@@ -32,14 +32,18 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.event.block.BlockRedstoneEvent; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end + + public class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- return instance.group(BlockSetType.CODEC.fieldOf("block_set_type").forGetter((buttonblock) -> { +- return buttonblock.type; +- }), Codec.intRange(1, 1024).fieldOf("ticks_to_stay_pressed").forGetter((buttonblock) -> { +- return buttonblock.ticksToStayPressed; ++ return instance.group(BlockSetType.CODEC.fieldOf("block_set_type").forGetter((blockbuttonabstract) -> { ++ return blockbuttonabstract.type; ++ }), Codec.intRange(1, 1024).fieldOf("ticks_to_stay_pressed").forGetter((blockbuttonabstract) -> { ++ return blockbuttonabstract.ticksToStayPressed; + }), propertiesCodec()).apply(instance, ButtonBlock::new); + }); + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; +@@ -67,27 +71,25 @@ + private final int ticksToStayPressed; + + @Override +- @Override + public MapCodec codec() { + return ButtonBlock.CODEC; + } + +- protected ButtonBlock(BlockSetType blocksettype, int i, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties.sound(blocksettype.soundType())); ++ protected ButtonBlock(BlockSetType blocksettype, int i, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info.sound(blocksettype.soundType())); + this.type = blocksettype; +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(ButtonBlock.FACING, Direction.NORTH)).setValue(ButtonBlock.POWERED, false)).setValue(ButtonBlock.FACE, AttachFace.WALL)); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(ButtonBlock.FACING, Direction.NORTH)).setValue(ButtonBlock.POWERED, false)).setValue(ButtonBlock.FACE, AttachFace.WALL)); + this.ticksToStayPressed = i; + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- Direction direction = (Direction) blockstate.getValue(ButtonBlock.FACING); +- boolean flag = (Boolean) blockstate.getValue(ButtonBlock.POWERED); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ Direction enumdirection = (Direction) state.getValue(ButtonBlock.FACING); ++ boolean flag = (Boolean) state.getValue(ButtonBlock.POWERED); + +- switch ((AttachFace) blockstate.getValue(ButtonBlock.FACE)) { ++ switch ((AttachFace) state.getValue(ButtonBlock.FACE)) { + case FLOOR: +- if (direction.getAxis() == Direction.Axis.X) { ++ if (enumdirection.getAxis() == Direction.Axis.X) { + return flag ? ButtonBlock.PRESSED_FLOOR_AABB_X : ButtonBlock.FLOOR_AABB_X; + } + +@@ -95,7 +97,7 @@ + case WALL: + VoxelShape voxelshape; + +- switch (direction) { ++ switch (enumdirection) { + case EAST: + voxelshape = flag ? ButtonBlock.PRESSED_EAST_AABB : ButtonBlock.EAST_AABB; + break; +@@ -117,119 +119,148 @@ + return voxelshape; + case CEILING: + default: +- return direction.getAxis() == Direction.Axis.X ? (flag ? ButtonBlock.PRESSED_CEILING_AABB_X : ButtonBlock.CEILING_AABB_X) : (flag ? ButtonBlock.PRESSED_CEILING_AABB_Z : ButtonBlock.CEILING_AABB_Z); ++ return enumdirection.getAxis() == Direction.Axis.X ? (flag ? ButtonBlock.PRESSED_CEILING_AABB_X : ButtonBlock.CEILING_AABB_X) : (flag ? ButtonBlock.PRESSED_CEILING_AABB_Z : ButtonBlock.CEILING_AABB_Z); + } + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- if ((Boolean) blockstate.getValue(ButtonBlock.POWERED)) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ if ((Boolean) state.getValue(ButtonBlock.POWERED)) { + return InteractionResult.CONSUME; + } else { +- this.press(blockstate, level, blockpos); +- this.playSound(player, level, blockpos, true); +- level.gameEvent((Entity) player, GameEvent.BLOCK_ACTIVATE, blockpos); ++ // CraftBukkit start ++ boolean powered = ((Boolean) state.getValue(POWERED)); ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ int old = (powered) ? 15 : 0; ++ int current = (!powered) ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if ((eventRedstone.getNewCurrent() > 0) != (!powered)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ this.press(state, level, pos); ++ this.playSound(player, level, pos, true); ++ level.gameEvent((Entity) player, GameEvent.BLOCK_ACTIVATE, pos); + return InteractionResult.sidedSuccess(level.isClientSide); + } + } + + @Override +- @Override +- public void onExplosionHit(BlockState blockstate, Level level, BlockPos blockpos, Explosion explosion, BiConsumer biconsumer) { +- if (explosion.getBlockInteraction() == Explosion.BlockInteraction.TRIGGER_BLOCK && !level.isClientSide() && !(Boolean) blockstate.getValue(ButtonBlock.POWERED)) { +- this.press(blockstate, level, blockpos); ++ public void onExplosionHit(IBlockData iblockdata, Level world, BlockPos blockposition, Explosion explosion, BiConsumer biconsumer) { ++ if (explosion.getBlockInteraction() == Explosion.Effect.TRIGGER_BLOCK && !world.isClientSide() && !(Boolean) iblockdata.getValue(ButtonBlock.POWERED)) { ++ this.press(iblockdata, world, blockposition); + } + +- super.onExplosionHit(blockstate, level, blockpos, explosion, biconsumer); ++ super.onExplosionHit(iblockdata, world, blockposition, explosion, biconsumer); + } + +- public void press(BlockState blockstate, Level level, BlockPos blockpos) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(ButtonBlock.POWERED, true), 3); +- this.updateNeighbours(blockstate, level, blockpos); +- level.scheduleTick(blockpos, (Block) this, this.ticksToStayPressed); ++ public void press(IBlockData state, Level level, BlockPos pos) { ++ level.setBlock(pos, (IBlockData) state.setValue(ButtonBlock.POWERED, true), 3); ++ this.updateNeighbours(state, level, pos); ++ level.scheduleTick(pos, (Block) this, this.ticksToStayPressed); + } + +- protected void playSound(@Nullable Player player, LevelAccessor levelaccessor, BlockPos blockpos, boolean flag) { +- levelaccessor.playSound(flag ? player : null, blockpos, this.getSound(flag), SoundSource.BLOCKS); ++ protected void playSound(@Nullable Player player, LevelAccessor level, BlockPos pos, boolean hitByArrow) { ++ level.playSound(hitByArrow ? player : null, pos, this.getSound(hitByArrow), SoundSource.BLOCKS); + } + +- protected SoundEvent getSound(boolean flag) { +- return flag ? this.type.buttonClickOn() : this.type.buttonClickOff(); ++ protected SoundEvent getSound(boolean isOn) { ++ return isOn ? this.type.buttonClickOn() : this.type.buttonClickOff(); + } + + @Override +- @Override +- public void onRemove(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!flag && !blockstate.is(blockstate1.getBlock())) { +- if ((Boolean) blockstate.getValue(ButtonBlock.POWERED)) { +- this.updateNeighbours(blockstate, level, blockpos); ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { ++ if (!isMoving && !state.is(newState.getBlock())) { ++ if ((Boolean) state.getValue(ButtonBlock.POWERED)) { ++ this.updateNeighbours(state, level, pos); + } + +- super.onRemove(blockstate, level, blockpos, blockstate1, flag); ++ super.onRemove(state, level, pos, newState, isMoving); + } + } + + @Override +- @Override +- public int getSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return (Boolean) blockstate.getValue(ButtonBlock.POWERED) ? 15 : 0; ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return (Boolean) blockState.getValue(ButtonBlock.POWERED) ? 15 : 0; + } + + @Override +- @Override +- public int getDirectSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return (Boolean) blockstate.getValue(ButtonBlock.POWERED) && getConnectedDirection(blockstate) == direction ? 15 : 0; ++ public int getDirectSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return (Boolean) blockState.getValue(ButtonBlock.POWERED) && getConnectedDirection(blockState) == side ? 15 : 0; + } + + @Override +- @Override +- public boolean isSignalSource(BlockState blockstate) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if ((Boolean) blockstate.getValue(ButtonBlock.POWERED)) { +- this.checkPressed(blockstate, serverlevel, blockpos); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(ButtonBlock.POWERED)) { ++ this.checkPressed(state, level, pos); + } + } + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { +- if (!level.isClientSide && this.type.canButtonBeActivatedByArrows() && !(Boolean) blockstate.getValue(ButtonBlock.POWERED)) { +- this.checkPressed(blockstate, level, blockpos); ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ if (!level.isClientSide && this.type.canButtonBeActivatedByArrows() && !(Boolean) state.getValue(ButtonBlock.POWERED)) { ++ this.checkPressed(state, level, pos); + } + } + +- protected void checkPressed(BlockState blockstate, Level level, BlockPos blockpos) { +- AbstractArrow abstractarrow = this.type.canButtonBeActivatedByArrows() ? (AbstractArrow) level.getEntitiesOfClass(AbstractArrow.class, blockstate.getShape(level, blockpos).bounds().move(blockpos)).stream().findFirst().orElse((Object) null) : null; +- boolean flag = abstractarrow != null; +- boolean flag1 = (Boolean) blockstate.getValue(ButtonBlock.POWERED); ++ protected void checkPressed(IBlockData state, Level level, BlockPos pos) { ++ AbstractArrow entityarrow = this.type.canButtonBeActivatedByArrows() ? (AbstractArrow) level.getEntitiesOfClass(AbstractArrow.class, state.getShape(level, pos).bounds().move(pos)).stream().findFirst().orElse(null) : null; // CraftBukkit - decompile error ++ boolean flag = entityarrow != null; ++ boolean flag1 = (Boolean) state.getValue(ButtonBlock.POWERED); + ++ // CraftBukkit start - Call interact event when arrows turn on wooden buttons ++ if (flag1 != flag && flag) { ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ EntityInteractEvent event = new EntityInteractEvent(entityarrow.getBukkitEntity(), block); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ + if (flag != flag1) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(ButtonBlock.POWERED, flag), 3); +- this.updateNeighbours(blockstate, level, blockpos); +- this.playSound((Player) null, level, blockpos, flag); +- level.gameEvent((Entity) abstractarrow, flag ? GameEvent.BLOCK_ACTIVATE : GameEvent.BLOCK_DEACTIVATE, blockpos); ++ // CraftBukkit start ++ boolean powered = flag1; ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ int old = (powered) ? 15 : 0; ++ int current = (!powered) ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if ((flag && eventRedstone.getNewCurrent() <= 0) || (!flag && eventRedstone.getNewCurrent() > 0)) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(ButtonBlock.POWERED, flag), 3); ++ this.updateNeighbours(state, level, pos); ++ this.playSound((Player) null, level, pos, flag); ++ level.gameEvent((Entity) entityarrow, flag ? GameEvent.BLOCK_ACTIVATE : GameEvent.BLOCK_DEACTIVATE, pos); + } + + if (flag) { +- level.scheduleTick(new BlockPos(blockpos), (Block) this, this.ticksToStayPressed); ++ level.scheduleTick(new BlockPos(pos), (Block) this, this.ticksToStayPressed); + } + + } + +- private void updateNeighbours(BlockState blockstate, Level level, BlockPos blockpos) { +- level.updateNeighborsAt(blockpos, this); +- level.updateNeighborsAt(blockpos.relative(getConnectedDirection(blockstate).getOpposite()), this); ++ private void updateNeighbours(IBlockData state, Level level, BlockPos pos) { ++ level.updateNeighborsAt(pos, this); ++ level.updateNeighborsAt(pos.relative(getConnectedDirection(state).getOpposite()), this); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(ButtonBlock.FACING, ButtonBlock.POWERED, ButtonBlock.FACE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(ButtonBlock.FACING, ButtonBlock.POWERED, ButtonBlock.FACE); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CactusBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CactusBlock.java.patch new file mode 100644 index 0000000000..8ba6ac85b2 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CactusBlock.java.patch @@ -0,0 +1,169 @@ +--- a/net/minecraft/world/level/block/CactusBlock.java ++++ b/net/minecraft/world/level/block/CactusBlock.java +@@ -14,13 +14,14 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class CactusBlock extends Block { + +@@ -32,48 +33,45 @@ + protected static final VoxelShape OUTLINE_SHAPE = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 16.0D, 15.0D); + + @Override +- @Override + public MapCodec codec() { + return CactusBlock.CODEC; + } + +- protected CactusBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(CactusBlock.AGE, 0)); ++ protected CactusBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(CactusBlock.AGE, 0)); + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (!blockstate.canSurvive(serverlevel, blockpos)) { +- serverlevel.destroyBlock(blockpos, true); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (!state.canSurvive(level, pos)) { ++ level.destroyBlock(pos, true); + } + + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- BlockPos blockpos1 = blockpos.above(); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ BlockPos blockposition1 = pos.above(); + +- if (serverlevel.isEmptyBlock(blockpos1)) { ++ if (level.isEmptyBlock(blockposition1)) { + int i; + +- for (i = 1; serverlevel.getBlockState(blockpos.below(i)).is((Block) this); ++i) { ++ for (i = 1; level.getBlockState(pos.below(i)).is((Block) this); ++i) { + ; + } + + if (i < 3) { +- int j = (Integer) blockstate.getValue(CactusBlock.AGE); ++ int j = (Integer) state.getValue(CactusBlock.AGE); + + if (j == 15) { +- serverlevel.setBlockAndUpdate(blockpos1, this.defaultBlockState()); +- BlockState blockstate1 = (BlockState) blockstate.setValue(CactusBlock.AGE, 0); ++ CraftEventFactory.handleBlockGrowEvent(level, blockposition1, this.defaultBlockState()); // CraftBukkit ++ IBlockData iblockdata1 = (IBlockData) state.setValue(CactusBlock.AGE, 0); + +- serverlevel.setBlock(blockpos, blockstate1, 4); +- serverlevel.neighborChanged(blockstate1, blockpos1, this, blockpos, false); ++ level.setBlock(pos, iblockdata1, 4); ++ level.neighborChanged(iblockdata1, blockposition1, this, pos, false); + } else { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(CactusBlock.AGE, j + 1), 4); ++ level.setBlock(pos, (IBlockData) state.setValue(CactusBlock.AGE, j + 1), 4); + } + + } +@@ -81,64 +79,59 @@ + } + + @Override +- @Override +- public VoxelShape getCollisionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return CactusBlock.COLLISION_SHAPE; + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return CactusBlock.OUTLINE_SHAPE; + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if (!blockstate.canSurvive(levelaccessor, blockpos)) { +- levelaccessor.scheduleTick(blockpos, (Block) this, 1); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if (!state.canSurvive(level, currentPos)) { ++ level.scheduleTick(currentPos, (Block) this, 1); + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- Direction direction; +- BlockState blockstate1; ++ Direction enumdirection; ++ IBlockData iblockdata1; + + do { + if (!iterator.hasNext()) { +- BlockState blockstate2 = levelreader.getBlockState(blockpos.below()); ++ IBlockData iblockdata2 = level.getBlockState(pos.below()); + +- return (blockstate2.is(Blocks.CACTUS) || blockstate2.is(BlockTags.SAND)) && !levelreader.getBlockState(blockpos.above()).liquid(); ++ return (iblockdata2.is(Blocks.CACTUS) || iblockdata2.is(BlockTags.SAND)) && !level.getBlockState(pos.above()).liquid(); + } + +- direction = (Direction) iterator.next(); +- blockstate1 = levelreader.getBlockState(blockpos.relative(direction)); +- } while (!blockstate1.isSolid() && !levelreader.getFluidState(blockpos.relative(direction)).is(FluidTags.LAVA)); ++ enumdirection = (Direction) iterator.next(); ++ iblockdata1 = level.getBlockState(pos.relative(enumdirection)); ++ } while (!iblockdata1.isSolid() && !level.getFluidState(pos.relative(enumdirection)).is(FluidTags.LAVA)); + + return false; + } + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ CraftEventFactory.blockDamage = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); // CraftBukkit + entity.hurt(level.damageSources().cactus(), 1.0F); ++ CraftEventFactory.blockDamage = null; // CraftBukkit + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(CactusBlock.AGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(CactusBlock.AGE); + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CakeBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CakeBlock.java.patch new file mode 100644 index 0000000000..99b7c77da0 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CakeBlock.java.patch @@ -0,0 +1,183 @@ +--- a/net/minecraft/world/level/block/CakeBlock.java ++++ b/net/minecraft/world/level/block/CakeBlock.java +@@ -7,7 +7,7 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; + import net.minecraft.tags.ItemTags; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; +@@ -18,12 +18,12 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.level.gameevent.GameEvent; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; +@@ -39,29 +39,26 @@ + protected static final VoxelShape[] SHAPE_BY_BITE = new VoxelShape[]{Block.box(1.0D, 0.0D, 1.0D, 15.0D, 8.0D, 15.0D), Block.box(3.0D, 0.0D, 1.0D, 15.0D, 8.0D, 15.0D), Block.box(5.0D, 0.0D, 1.0D, 15.0D, 8.0D, 15.0D), Block.box(7.0D, 0.0D, 1.0D, 15.0D, 8.0D, 15.0D), Block.box(9.0D, 0.0D, 1.0D, 15.0D, 8.0D, 15.0D), Block.box(11.0D, 0.0D, 1.0D, 15.0D, 8.0D, 15.0D), Block.box(13.0D, 0.0D, 1.0D, 15.0D, 8.0D, 15.0D)}; + + @Override +- @Override + public MapCodec codec() { + return CakeBlock.CODEC; + } + +- protected CakeBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(CakeBlock.BITES, 0)); ++ protected CakeBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(CakeBlock.BITES, 0)); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return CakeBlock.SHAPE_BY_BITE[(Integer) blockstate.getValue(CakeBlock.BITES)]; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return CakeBlock.SHAPE_BY_BITE[(Integer) state.getValue(CakeBlock.BITES)]; + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ ItemStack itemstack = player.getItemInHand(hand); + Item item = itemstack.getItem(); + +- if (itemstack.is(ItemTags.CANDLES) && (Integer) blockstate.getValue(CakeBlock.BITES) == 0) { ++ if (itemstack.is(ItemTags.CANDLES) && (Integer) state.getValue(CakeBlock.BITES) == 0) { + Block block = Block.byItem(item); + + if (block instanceof CandleBlock) { +@@ -69,16 +66,16 @@ + itemstack.shrink(1); + } + +- level.playSound((Player) null, blockpos, SoundEvents.CAKE_ADD_CANDLE, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.setBlockAndUpdate(blockpos, CandleCakeBlock.byCandle(block)); +- level.gameEvent((Entity) player, GameEvent.BLOCK_CHANGE, blockpos); ++ level.playSound((Player) null, pos, SoundEvents.CAKE_ADD_CANDLE, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.setBlockAndUpdate(pos, CandleCakeBlock.byCandle(block)); ++ level.gameEvent((Entity) player, GameEvent.BLOCK_CHANGE, pos); + player.awardStat(Stats.ITEM_USED.get(item)); + return InteractionResult.SUCCESS; + } + } + + if (level.isClientSide) { +- if (eat(level, blockpos, blockstate, player).consumesAction()) { ++ if (eat(level, pos, state, player).consumesAction()) { + return InteractionResult.SUCCESS; + } + +@@ -87,23 +84,34 @@ + } + } + +- return eat(level, blockpos, blockstate, player); ++ return eat(level, pos, state, player); + } + +- protected static InteractionResult eat(LevelAccessor levelaccessor, BlockPos blockpos, BlockState blockstate, Player player) { ++ protected static InteractionResult eat(LevelAccessor level, BlockPos pos, IBlockData state, Player player) { + if (!player.canEat(false)) { + return InteractionResult.PASS; + } else { + player.awardStat(Stats.EAT_CAKE_SLICE); +- player.getFoodData().eat(2, 0.1F); +- int i = (Integer) blockstate.getValue(CakeBlock.BITES); ++ // CraftBukkit start ++ // entityhuman.getFoodData().eat(2, 0.1F); ++ int oldFoodLevel = player.getFoodData().foodLevel; + +- levelaccessor.gameEvent((Entity) player, GameEvent.EAT, blockpos); ++ org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(player, 2 + oldFoodLevel); ++ ++ if (!event.isCancelled()) { ++ player.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, 0.1F); ++ } ++ ++ ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().sendHealthUpdate(); ++ // CraftBukkit end ++ int i = (Integer) state.getValue(CakeBlock.BITES); ++ ++ level.gameEvent((Entity) player, GameEvent.EAT, pos); + if (i < 6) { +- levelaccessor.setBlock(blockpos, (BlockState) blockstate.setValue(CakeBlock.BITES, i + 1), 3); ++ level.setBlock(pos, (IBlockData) state.setValue(CakeBlock.BITES, i + 1), 3); + } else { +- levelaccessor.removeBlock(blockpos, false); +- levelaccessor.gameEvent((Entity) player, GameEvent.BLOCK_DESTROY, blockpos); ++ level.removeBlock(pos, false); ++ level.gameEvent((Entity) player, GameEvent.BLOCK_DESTROY, pos); + } + + return InteractionResult.SUCCESS; +@@ -111,42 +119,36 @@ + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- return direction == Direction.DOWN && !blockstate.canSurvive(levelaccessor, blockpos) ? Blocks.AIR.defaultBlockState() : super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ return facing == Direction.DOWN && !state.canSurvive(level, currentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- return levelreader.getBlockState(blockpos.below()).isSolid(); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ return level.getBlockState(pos.below()).isSolid(); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(CakeBlock.BITES); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(CakeBlock.BITES); + } + + @Override +- @Override +- public int getAnalogOutputSignal(BlockState blockstate, Level level, BlockPos blockpos) { +- return getOutputSignal((Integer) blockstate.getValue(CakeBlock.BITES)); ++ public int getAnalogOutputSignal(IBlockData blockState, Level level, BlockPos pos) { ++ return getOutputSignal((Integer) blockState.getValue(CakeBlock.BITES)); + } + +- public static int getOutputSignal(int i) { +- return (7 - i) * 2; ++ public static int getOutputSignal(int eaten) { ++ return (7 - eaten) * 2; + } + + @Override +- @Override +- public boolean hasAnalogOutputSignal(BlockState blockstate) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return true; + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CampfireBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CampfireBlock.java.patch new file mode 100644 index 0000000000..229afee996 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CampfireBlock.java.patch @@ -0,0 +1,394 @@ +--- a/net/minecraft/world/level/block/CampfireBlock.java ++++ b/net/minecraft/world/level/block/CampfireBlock.java +@@ -15,7 +15,7 @@ + import net.minecraft.tags.BlockTags; + import net.minecraft.util.RandomSource; + import net.minecraft.world.Containers; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; +@@ -34,7 +34,7 @@ + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.CampfireBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -43,20 +43,23 @@ + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++// CraftBukkit end + + public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedBlock { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- return instance.group(Codec.BOOL.fieldOf("spawn_particles").forGetter((campfireblock) -> { +- return campfireblock.spawnParticles; +- }), Codec.intRange(0, 1000).fieldOf("fire_damage").forGetter((campfireblock) -> { +- return campfireblock.fireDamage; ++ return instance.group(Codec.BOOL.fieldOf("spawn_particles").forGetter((blockcampfire) -> { ++ return blockcampfire.spawnParticles; ++ }), Codec.intRange(0, 1000).fieldOf("fire_damage").forGetter((blockcampfire) -> { ++ return blockcampfire.fireDamage; + }), propertiesCodec()).apply(instance, CampfireBlock::new); + }); + protected static final VoxelShape SHAPE = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 7.0D, 16.0D); +@@ -70,30 +73,28 @@ + private final int fireDamage; + + @Override +- @Override + public MapCodec codec() { + return CampfireBlock.CODEC; + } + +- public CampfireBlock(boolean flag, int i, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.spawnParticles = flag; +- this.fireDamage = i; +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(CampfireBlock.LIT, true)).setValue(CampfireBlock.SIGNAL_FIRE, false)).setValue(CampfireBlock.WATERLOGGED, false)).setValue(CampfireBlock.FACING, Direction.NORTH)); ++ public CampfireBlock(boolean spawnParticles, int fireDamage, BlockBehaviour.Properties properties) { ++ super(properties); ++ this.spawnParticles = spawnParticles; ++ this.fireDamage = fireDamage; ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(CampfireBlock.LIT, true)).setValue(CampfireBlock.SIGNAL_FIRE, false)).setValue(CampfireBlock.WATERLOGGED, false)).setValue(CampfireBlock.FACING, Direction.NORTH)); + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof CampfireBlockEntity) { +- CampfireBlockEntity campfireblockentity = (CampfireBlockEntity) blockentity; +- ItemStack itemstack = player.getItemInHand(interactionhand); +- Optional> optional = campfireblockentity.getCookableRecipe(itemstack); ++ if (tileentity instanceof CampfireBlockEntity) { ++ CampfireBlockEntity tileentitycampfire = (CampfireBlockEntity) tileentity; ++ ItemStack itemstack = player.getItemInHand(hand); ++ Optional> optional = tileentitycampfire.getCookableRecipe(itemstack); + + if (optional.isPresent()) { +- if (!level.isClientSide && campfireblockentity.placeFood(player, player.getAbilities().instabuild ? itemstack.copy() : itemstack, ((CampfireCookingRecipe) ((RecipeHolder) optional.get()).value()).getCookingTime())) { ++ if (!level.isClientSide && tileentitycampfire.placeFood(player, player.getAbilities().instabuild ? itemstack.copy() : itemstack, ((CampfireCookingRecipe) ((RecipeHolder) optional.get()).value()).getCookingTime())) { + player.awardStat(Stats.INTERACT_WITH_CAMPFIRE); + return InteractionResult.SUCCESS; + } +@@ -106,115 +107,109 @@ + } + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { +- if ((Boolean) blockstate.getValue(CampfireBlock.LIT) && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity) entity)) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ if ((Boolean) state.getValue(CampfireBlock.LIT) && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity) entity)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = CraftBlock.at(level, pos); // CraftBukkit + entity.hurt(level.damageSources().inFire(), (float) this.fireDamage); ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = null; // CraftBukkit + } + +- super.entityInside(blockstate, level, blockpos, entity); ++ super.entityInside(state, level, pos, entity); + } + + @Override +- @Override +- public void onRemove(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!blockstate.is(blockstate1.getBlock())) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { ++ if (!state.is(newState.getBlock())) { ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof CampfireBlockEntity) { +- Containers.dropContents(level, blockpos, ((CampfireBlockEntity) blockentity).getItems()); ++ if (tileentity instanceof CampfireBlockEntity) { ++ Containers.dropContents(level, pos, ((CampfireBlockEntity) tileentity).getItems()); + } + +- super.onRemove(blockstate, level, blockpos, blockstate1, flag); ++ super.onRemove(state, level, pos, newState, isMoving); + } + } + + @Nullable + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- Level level = blockplacecontext.getLevel(); +- BlockPos blockpos = blockplacecontext.getClickedPos(); +- boolean flag = level.getFluidState(blockpos).getType() == Fluids.WATER; ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ boolean flag = world.getFluidState(blockposition).getType() == Fluids.WATER; + +- return (BlockState) ((BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(CampfireBlock.WATERLOGGED, flag)).setValue(CampfireBlock.SIGNAL_FIRE, this.isSmokeSource(level.getBlockState(blockpos.below())))).setValue(CampfireBlock.LIT, !flag)).setValue(CampfireBlock.FACING, blockplacecontext.getHorizontalDirection()); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(CampfireBlock.WATERLOGGED, flag)).setValue(CampfireBlock.SIGNAL_FIRE, this.isSmokeSource(world.getBlockState(blockposition.below())))).setValue(CampfireBlock.LIT, !flag)).setValue(CampfireBlock.FACING, context.getHorizontalDirection()); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if ((Boolean) blockstate.getValue(CampfireBlock.WATERLOGGED)) { +- levelaccessor.scheduleTick(blockpos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(levelaccessor)); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if ((Boolean) state.getValue(CampfireBlock.WATERLOGGED)) { ++ level.scheduleTick(currentPos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + +- return direction == Direction.DOWN ? (BlockState) blockstate.setValue(CampfireBlock.SIGNAL_FIRE, this.isSmokeSource(blockstate1)) : super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return facing == Direction.DOWN ? (IBlockData) state.setValue(CampfireBlock.SIGNAL_FIRE, this.isSmokeSource(facingState)) : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + +- private boolean isSmokeSource(BlockState blockstate) { +- return blockstate.is(Blocks.HAY_BLOCK); ++ private boolean isSmokeSource(IBlockData state) { ++ return state.is(Blocks.HAY_BLOCK); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return CampfireBlock.SHAPE; + } + + @Override +- @Override +- public RenderShape getRenderShape(BlockState blockstate) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Override +- @Override +- public void animateTick(BlockState blockstate, Level level, BlockPos blockpos, RandomSource randomsource) { +- if ((Boolean) blockstate.getValue(CampfireBlock.LIT)) { +- if (randomsource.nextInt(10) == 0) { +- level.playLocalSound((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D, SoundEvents.CAMPFIRE_CRACKLE, SoundSource.BLOCKS, 0.5F + randomsource.nextFloat(), randomsource.nextFloat() * 0.7F + 0.6F, false); ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(CampfireBlock.LIT)) { ++ if (random.nextInt(10) == 0) { ++ level.playLocalSound((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.CAMPFIRE_CRACKLE, SoundSource.BLOCKS, 0.5F + random.nextFloat(), random.nextFloat() * 0.7F + 0.6F, false); + } + +- if (this.spawnParticles && randomsource.nextInt(5) == 0) { +- for (int i = 0; i < randomsource.nextInt(1) + 1; ++i) { +- level.addParticle(ParticleTypes.LAVA, (double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D, (double) (randomsource.nextFloat() / 2.0F), 5.0E-5D, (double) (randomsource.nextFloat() / 2.0F)); ++ if (this.spawnParticles && random.nextInt(5) == 0) { ++ for (int i = 0; i < random.nextInt(1) + 1; ++i) { ++ level.addParticle(ParticleTypes.LAVA, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (double) (random.nextFloat() / 2.0F), 5.0E-5D, (double) (random.nextFloat() / 2.0F)); + } + } + + } + } + +- public static void dowse(@Nullable Entity entity, LevelAccessor levelaccessor, BlockPos blockpos, BlockState blockstate) { +- if (levelaccessor.isClientSide()) { ++ public static void dowse(@Nullable Entity entity, LevelAccessor level, BlockPos pos, IBlockData state) { ++ if (level.isClientSide()) { + for (int i = 0; i < 20; ++i) { +- makeParticles((Level) levelaccessor, blockpos, (Boolean) blockstate.getValue(CampfireBlock.SIGNAL_FIRE), true); ++ makeParticles((Level) level, pos, (Boolean) state.getValue(CampfireBlock.SIGNAL_FIRE), true); + } + } + +- BlockEntity blockentity = levelaccessor.getBlockEntity(blockpos); ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof CampfireBlockEntity) { +- ((CampfireBlockEntity) blockentity).dowse(); ++ if (tileentity instanceof CampfireBlockEntity) { ++ ((CampfireBlockEntity) tileentity).dowse(); + } + +- levelaccessor.gameEvent(entity, GameEvent.BLOCK_CHANGE, blockpos); ++ level.gameEvent(entity, GameEvent.BLOCK_CHANGE, pos); + } + + @Override +- @Override +- public boolean placeLiquid(LevelAccessor levelaccessor, BlockPos blockpos, BlockState blockstate, FluidState fluidstate) { +- if (!(Boolean) blockstate.getValue(BlockStateProperties.WATERLOGGED) && fluidstate.getType() == Fluids.WATER) { +- boolean flag = (Boolean) blockstate.getValue(CampfireBlock.LIT); ++ public boolean placeLiquid(LevelAccessor level, BlockPos pos, IBlockData state, FluidState fluidState) { ++ if (!(Boolean) state.getValue(BlockStateProperties.WATERLOGGED) && fluidState.getType() == Fluids.WATER) { ++ boolean flag = (Boolean) state.getValue(CampfireBlock.LIT); + + if (flag) { +- if (!levelaccessor.isClientSide()) { +- levelaccessor.playSound((Player) null, blockpos, SoundEvents.GENERIC_EXTINGUISH_FIRE, SoundSource.BLOCKS, 1.0F, 1.0F); ++ if (!level.isClientSide()) { ++ level.playSound((Player) null, pos, SoundEvents.GENERIC_EXTINGUISH_FIRE, SoundSource.BLOCKS, 1.0F, 1.0F); + } + +- dowse((Entity) null, levelaccessor, blockpos, blockstate); ++ dowse((Entity) null, level, pos, state); + } + +- levelaccessor.setBlock(blockpos, (BlockState) ((BlockState) blockstate.setValue(CampfireBlock.WATERLOGGED, true)).setValue(CampfireBlock.LIT, false), 3); +- levelaccessor.scheduleTick(blockpos, fluidstate.getType(), fluidstate.getType().getTickDelay(levelaccessor)); ++ level.setBlock(pos, (IBlockData) ((IBlockData) state.setValue(CampfireBlock.WATERLOGGED, true)).setValue(CampfireBlock.LIT, false), 3); ++ level.scheduleTick(pos, fluidState.getType(), fluidState.getType().getTickDelay(level)); + return true; + } else { + return false; +@@ -222,98 +217,95 @@ + } + + @Override +- @Override +- public void onProjectileHit(Level level, BlockState blockstate, BlockHitResult blockhitresult, Projectile projectile) { +- BlockPos blockpos = blockhitresult.getBlockPos(); ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { ++ BlockPos blockposition = hit.getBlockPos(); + +- if (!level.isClientSide && projectile.isOnFire() && projectile.mayInteract(level, blockpos) && !(Boolean) blockstate.getValue(CampfireBlock.LIT) && !(Boolean) blockstate.getValue(CampfireBlock.WATERLOGGED)) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(BlockStateProperties.LIT, true), 11); ++ if (!level.isClientSide && projectile.isOnFire() && projectile.mayInteract(level, blockposition) && !(Boolean) state.getValue(CampfireBlock.LIT) && !(Boolean) state.getValue(CampfireBlock.WATERLOGGED)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, blockposition, projectile).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(blockposition, (IBlockData) state.setValue(BlockStateProperties.LIT, true), 11); + } + + } + +- public static void makeParticles(Level level, BlockPos blockpos, boolean flag, boolean flag1) { ++ public static void makeParticles(Level level, BlockPos pos, boolean isSignalFire, boolean spawnExtraSmoke) { + RandomSource randomsource = level.getRandom(); +- SimpleParticleType simpleparticletype = flag ? ParticleTypes.CAMPFIRE_SIGNAL_SMOKE : ParticleTypes.CAMPFIRE_COSY_SMOKE; ++ SimpleParticleType particletype = isSignalFire ? ParticleTypes.CAMPFIRE_SIGNAL_SMOKE : ParticleTypes.CAMPFIRE_COSY_SMOKE; + +- level.addAlwaysVisibleParticle(simpleparticletype, true, (double) blockpos.getX() + 0.5D + randomsource.nextDouble() / 3.0D * (double) (randomsource.nextBoolean() ? 1 : -1), (double) blockpos.getY() + randomsource.nextDouble() + randomsource.nextDouble(), (double) blockpos.getZ() + 0.5D + randomsource.nextDouble() / 3.0D * (double) (randomsource.nextBoolean() ? 1 : -1), 0.0D, 0.07D, 0.0D); +- if (flag1) { +- level.addParticle(ParticleTypes.SMOKE, (double) blockpos.getX() + 0.5D + randomsource.nextDouble() / 4.0D * (double) (randomsource.nextBoolean() ? 1 : -1), (double) blockpos.getY() + 0.4D, (double) blockpos.getZ() + 0.5D + randomsource.nextDouble() / 4.0D * (double) (randomsource.nextBoolean() ? 1 : -1), 0.0D, 0.005D, 0.0D); ++ level.addAlwaysVisibleParticle(particletype, true, (double) pos.getX() + 0.5D + randomsource.nextDouble() / 3.0D * (double) (randomsource.nextBoolean() ? 1 : -1), (double) pos.getY() + randomsource.nextDouble() + randomsource.nextDouble(), (double) pos.getZ() + 0.5D + randomsource.nextDouble() / 3.0D * (double) (randomsource.nextBoolean() ? 1 : -1), 0.0D, 0.07D, 0.0D); ++ if (spawnExtraSmoke) { ++ level.addParticle(ParticleTypes.SMOKE, (double) pos.getX() + 0.5D + randomsource.nextDouble() / 4.0D * (double) (randomsource.nextBoolean() ? 1 : -1), (double) pos.getY() + 0.4D, (double) pos.getZ() + 0.5D + randomsource.nextDouble() / 4.0D * (double) (randomsource.nextBoolean() ? 1 : -1), 0.0D, 0.005D, 0.0D); + } + + } + +- public static boolean isSmokeyPos(Level level, BlockPos blockpos) { ++ public static boolean isSmokeyPos(Level level, BlockPos pos) { + for (int i = 1; i <= 5; ++i) { +- BlockPos blockpos1 = blockpos.below(i); +- BlockState blockstate = level.getBlockState(blockpos1); ++ BlockPos blockposition1 = pos.below(i); ++ IBlockData iblockdata = level.getBlockState(blockposition1); + +- if (isLitCampfire(blockstate)) { ++ if (isLitCampfire(iblockdata)) { + return true; + } + +- boolean flag = Shapes.joinIsNotEmpty(CampfireBlock.VIRTUAL_FENCE_POST, blockstate.getCollisionShape(level, blockpos, CollisionContext.empty()), BooleanOp.AND); ++ boolean flag = Shapes.joinIsNotEmpty(CampfireBlock.VIRTUAL_FENCE_POST, iblockdata.getCollisionShape(level, pos, CollisionContext.empty()), BooleanOp.AND); + + if (flag) { +- BlockState blockstate1 = level.getBlockState(blockpos1.below()); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1.below()); + +- return isLitCampfire(blockstate1); ++ return isLitCampfire(iblockdata1); + } + } + + return false; + } + +- public static boolean isLitCampfire(BlockState blockstate) { +- return blockstate.hasProperty(CampfireBlock.LIT) && blockstate.is(BlockTags.CAMPFIRES) && (Boolean) blockstate.getValue(CampfireBlock.LIT); ++ public static boolean isLitCampfire(IBlockData state) { ++ return state.hasProperty(CampfireBlock.LIT) && state.is(BlockTags.CAMPFIRES) && (Boolean) state.getValue(CampfireBlock.LIT); + } + + @Override +- @Override +- public FluidState getFluidState(BlockState blockstate) { +- return (Boolean) blockstate.getValue(CampfireBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(blockstate); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(CampfireBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override +- @Override +- public BlockState rotate(BlockState blockstate, Rotation rotation) { +- return (BlockState) blockstate.setValue(CampfireBlock.FACING, rotation.rotate((Direction) blockstate.getValue(CampfireBlock.FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rot) { ++ return (IBlockData) state.setValue(CampfireBlock.FACING, rot.rotate((Direction) state.getValue(CampfireBlock.FACING))); + } + + @Override +- @Override +- public BlockState mirror(BlockState blockstate, Mirror mirror) { +- return blockstate.rotate(mirror.getRotation((Direction) blockstate.getValue(CampfireBlock.FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(CampfireBlock.FACING))); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(CampfireBlock.LIT, CampfireBlock.SIGNAL_FIRE, CampfireBlock.WATERLOGGED, CampfireBlock.FACING); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(CampfireBlock.LIT, CampfireBlock.SIGNAL_FIRE, CampfireBlock.WATERLOGGED, CampfireBlock.FACING); + } + + @Override +- @Override +- public BlockEntity newBlockEntity(BlockPos blockpos, BlockState blockstate) { +- return new CampfireBlockEntity(blockpos, blockstate); ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ return new CampfireBlockEntity(pos, state); + } + + @Nullable + @Override +- @Override +- public BlockEntityTicker getTicker(Level level, BlockState blockstate, BlockEntityType blockentitytype) { +- return level.isClientSide ? ((Boolean) blockstate.getValue(CampfireBlock.LIT) ? createTickerHelper(blockentitytype, BlockEntityType.CAMPFIRE, CampfireBlockEntity::particleTick) : null) : ((Boolean) blockstate.getValue(CampfireBlock.LIT) ? createTickerHelper(blockentitytype, BlockEntityType.CAMPFIRE, CampfireBlockEntity::cookTick) : createTickerHelper(blockentitytype, BlockEntityType.CAMPFIRE, CampfireBlockEntity::cooldownTick)); ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { ++ return level.isClientSide ? ((Boolean) state.getValue(CampfireBlock.LIT) ? createTickerHelper(blockEntityType, BlockEntityType.CAMPFIRE, CampfireBlockEntity::particleTick) : null) : ((Boolean) state.getValue(CampfireBlock.LIT) ? createTickerHelper(blockEntityType, BlockEntityType.CAMPFIRE, CampfireBlockEntity::cookTick) : createTickerHelper(blockEntityType, BlockEntityType.CAMPFIRE, CampfireBlockEntity::cooldownTick)); + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + +- public static boolean canLight(BlockState blockstate) { +- return blockstate.is(BlockTags.CAMPFIRES, (blockbehaviour_blockstatebase) -> { +- return blockbehaviour_blockstatebase.hasProperty(CampfireBlock.WATERLOGGED) && blockbehaviour_blockstatebase.hasProperty(CampfireBlock.LIT); +- }) && !(Boolean) blockstate.getValue(CampfireBlock.WATERLOGGED) && !(Boolean) blockstate.getValue(CampfireBlock.LIT); ++ public static boolean canLight(IBlockData state) { ++ return state.is(BlockTags.CAMPFIRES, (blockbase_blockdata) -> { ++ return blockbase_blockdata.hasProperty(CampfireBlock.WATERLOGGED) && blockbase_blockdata.hasProperty(CampfireBlock.LIT); ++ }) && !(Boolean) state.getValue(CampfireBlock.WATERLOGGED) && !(Boolean) state.getValue(CampfireBlock.LIT); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CarvedPumpkinBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CarvedPumpkinBlock.java.patch new file mode 100644 index 0000000000..ff34a14490 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CarvedPumpkinBlock.java.patch @@ -0,0 +1,198 @@ +--- a/net/minecraft/world/level/block/CarvedPumpkinBlock.java ++++ b/net/minecraft/world/level/block/CarvedPumpkinBlock.java +@@ -16,13 +16,16 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.pattern.BlockInWorld; + import net.minecraft.world.level.block.state.pattern.BlockPattern; + import net.minecraft.world.level.block.state.pattern.BlockPatternBuilder; + import net.minecraft.world.level.block.state.predicate.BlockStatePredicate; + import net.minecraft.world.level.block.state.properties.DirectionProperty; ++// CraftBukkit start ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; ++// CraftBukkit end + + public class CarvedPumpkinBlock extends HorizontalDirectionalBlock { + +@@ -36,105 +39,106 @@ + private BlockPattern ironGolemBase; + @Nullable + private BlockPattern ironGolemFull; +- private static final Predicate PUMPKINS_PREDICATE = (blockstate) -> { +- return blockstate != null && (blockstate.is(Blocks.CARVED_PUMPKIN) || blockstate.is(Blocks.JACK_O_LANTERN)); ++ private static final Predicate PUMPKINS_PREDICATE = (iblockdata) -> { ++ return iblockdata != null && (iblockdata.is(Blocks.CARVED_PUMPKIN) || iblockdata.is(Blocks.JACK_O_LANTERN)); + }; + + @Override +- @Override + public MapCodec codec() { + return CarvedPumpkinBlock.CODEC; + } + +- protected CarvedPumpkinBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(CarvedPumpkinBlock.FACING, Direction.NORTH)); ++ protected CarvedPumpkinBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(CarvedPumpkinBlock.FACING, Direction.NORTH)); + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!blockstate1.is(blockstate.getBlock())) { +- this.trySpawnGolem(level, blockpos); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ if (!oldState.is(state.getBlock())) { ++ this.trySpawnGolem(level, pos); + } + } + +- public boolean canSpawnGolem(LevelReader levelreader, BlockPos blockpos) { +- return this.getOrCreateSnowGolemBase().find(levelreader, blockpos) != null || this.getOrCreateIronGolemBase().find(levelreader, blockpos) != null; ++ public boolean canSpawnGolem(LevelReader level, BlockPos pos) { ++ return this.getOrCreateSnowGolemBase().find(level, pos) != null || this.getOrCreateIronGolemBase().find(level, pos) != null; + } + +- private void trySpawnGolem(Level level, BlockPos blockpos) { +- BlockPattern.BlockPatternMatch blockpattern_blockpatternmatch = this.getOrCreateSnowGolemFull().find(level, blockpos); ++ private void trySpawnGolem(Level level, BlockPos pos) { ++ BlockPattern.BlockPatternMatch shapedetector_shapedetectorcollection = this.getOrCreateSnowGolemFull().find(level, pos); + +- if (blockpattern_blockpatternmatch != null) { +- SnowGolem snowgolem = (SnowGolem) EntityType.SNOW_GOLEM.create(level); ++ if (shapedetector_shapedetectorcollection != null) { ++ SnowGolem entitysnowman = (SnowGolem) EntityType.SNOW_GOLEM.create(level); + +- if (snowgolem != null) { +- spawnGolemInWorld(level, blockpattern_blockpatternmatch, snowgolem, blockpattern_blockpatternmatch.getBlock(0, 2, 0).getPos()); ++ if (entitysnowman != null) { ++ spawnGolemInWorld(level, shapedetector_shapedetectorcollection, entitysnowman, shapedetector_shapedetectorcollection.getBlock(0, 2, 0).getPos()); + } + } else { +- BlockPattern.BlockPatternMatch blockpattern_blockpatternmatch1 = this.getOrCreateIronGolemFull().find(level, blockpos); ++ BlockPattern.BlockPatternMatch shapedetector_shapedetectorcollection1 = this.getOrCreateIronGolemFull().find(level, pos); + +- if (blockpattern_blockpatternmatch1 != null) { +- IronGolem irongolem = (IronGolem) EntityType.IRON_GOLEM.create(level); ++ if (shapedetector_shapedetectorcollection1 != null) { ++ IronGolem entityirongolem = (IronGolem) EntityType.IRON_GOLEM.create(level); + +- if (irongolem != null) { +- irongolem.setPlayerCreated(true); +- spawnGolemInWorld(level, blockpattern_blockpatternmatch1, irongolem, blockpattern_blockpatternmatch1.getBlock(1, 2, 0).getPos()); ++ if (entityirongolem != null) { ++ entityirongolem.setPlayerCreated(true); ++ spawnGolemInWorld(level, shapedetector_shapedetectorcollection1, entityirongolem, shapedetector_shapedetectorcollection1.getBlock(1, 2, 0).getPos()); + } + } + } + + } + +- private static void spawnGolemInWorld(Level level, BlockPattern.BlockPatternMatch blockpattern_blockpatternmatch, Entity entity, BlockPos blockpos) { +- clearPatternBlocks(level, blockpattern_blockpatternmatch); +- entity.moveTo((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.05D, (double) blockpos.getZ() + 0.5D, 0.0F, 0.0F); +- level.addFreshEntity(entity); +- Iterator iterator = level.getEntitiesOfClass(ServerPlayer.class, entity.getBoundingBox().inflate(5.0D)).iterator(); ++ private static void spawnGolemInWorld(Level level, BlockPattern.BlockPatternMatch patternMatch, Entity golem, BlockPos pos) { ++ // clearPatternBlocks(world, shapedetector_shapedetectorcollection); // CraftBukkit - moved down ++ golem.moveTo((double) pos.getX() + 0.5D, (double) pos.getY() + 0.05D, (double) pos.getZ() + 0.5D, 0.0F, 0.0F); ++ // CraftBukkit start ++ if (!level.addFreshEntity(golem, SpawnReason.BUILD_IRONGOLEM)) { ++ return; ++ } ++ clearPatternBlocks(level, patternMatch); // CraftBukkit - from above ++ // CraftBukkit end ++ Iterator iterator = level.getEntitiesOfClass(ServerPlayer.class, golem.getBoundingBox().inflate(5.0D)).iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- CriteriaTriggers.SUMMONED_ENTITY.trigger(serverplayer, entity); ++ CriteriaTriggers.SUMMONED_ENTITY.trigger(entityplayer, golem); + } + +- updatePatternBlocks(level, blockpattern_blockpatternmatch); ++ updatePatternBlocks(level, patternMatch); + } + +- public static void clearPatternBlocks(Level level, BlockPattern.BlockPatternMatch blockpattern_blockpatternmatch) { +- for (int i = 0; i < blockpattern_blockpatternmatch.getWidth(); ++i) { +- for (int j = 0; j < blockpattern_blockpatternmatch.getHeight(); ++j) { +- BlockInWorld blockinworld = blockpattern_blockpatternmatch.getBlock(i, j, 0); ++ public static void clearPatternBlocks(Level level, BlockPattern.BlockPatternMatch patternMatch) { ++ for (int i = 0; i < patternMatch.getWidth(); ++i) { ++ for (int j = 0; j < patternMatch.getHeight(); ++j) { ++ BlockInWorld shapedetectorblock = patternMatch.getBlock(i, j, 0); + +- level.setBlock(blockinworld.getPos(), Blocks.AIR.defaultBlockState(), 2); +- level.levelEvent(2001, blockinworld.getPos(), Block.getId(blockinworld.getState())); ++ level.setBlock(shapedetectorblock.getPos(), Blocks.AIR.defaultBlockState(), 2); ++ level.levelEvent(2001, shapedetectorblock.getPos(), Block.getId(shapedetectorblock.getState())); + } + } + + } + +- public static void updatePatternBlocks(Level level, BlockPattern.BlockPatternMatch blockpattern_blockpatternmatch) { +- for (int i = 0; i < blockpattern_blockpatternmatch.getWidth(); ++i) { +- for (int j = 0; j < blockpattern_blockpatternmatch.getHeight(); ++j) { +- BlockInWorld blockinworld = blockpattern_blockpatternmatch.getBlock(i, j, 0); ++ public static void updatePatternBlocks(Level level, BlockPattern.BlockPatternMatch patternMatch) { ++ for (int i = 0; i < patternMatch.getWidth(); ++i) { ++ for (int j = 0; j < patternMatch.getHeight(); ++j) { ++ BlockInWorld shapedetectorblock = patternMatch.getBlock(i, j, 0); + +- level.blockUpdated(blockinworld.getPos(), Blocks.AIR); ++ level.blockUpdated(shapedetectorblock.getPos(), Blocks.AIR); + } + } + + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- return (BlockState) this.defaultBlockState().setValue(CarvedPumpkinBlock.FACING, blockplacecontext.getHorizontalDirection().getOpposite()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return (IBlockData) this.defaultBlockState().setValue(CarvedPumpkinBlock.FACING, context.getHorizontalDirection().getOpposite()); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(CarvedPumpkinBlock.FACING); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(CarvedPumpkinBlock.FACING); + } + + private BlockPattern getOrCreateSnowGolemBase() { +@@ -155,8 +159,8 @@ + + private BlockPattern getOrCreateIronGolemBase() { + if (this.ironGolemBase == null) { +- this.ironGolemBase = BlockPatternBuilder.start().aisle("~ ~", "###", "~#~").where('#', BlockInWorld.hasState(BlockStatePredicate.forBlock(Blocks.IRON_BLOCK))).where('~', (blockinworld) -> { +- return blockinworld.getState().isAir(); ++ this.ironGolemBase = BlockPatternBuilder.start().aisle("~ ~", "###", "~#~").where('#', BlockInWorld.hasState(BlockStatePredicate.forBlock(Blocks.IRON_BLOCK))).where('~', (shapedetectorblock) -> { ++ return shapedetectorblock.getState().isAir(); + }).build(); + } + +@@ -165,8 +169,8 @@ + + private BlockPattern getOrCreateIronGolemFull() { + if (this.ironGolemFull == null) { +- this.ironGolemFull = BlockPatternBuilder.start().aisle("~^~", "###", "~#~").where('^', BlockInWorld.hasState(CarvedPumpkinBlock.PUMPKINS_PREDICATE)).where('#', BlockInWorld.hasState(BlockStatePredicate.forBlock(Blocks.IRON_BLOCK))).where('~', (blockinworld) -> { +- return blockinworld.getState().isAir(); ++ this.ironGolemFull = BlockPatternBuilder.start().aisle("~^~", "###", "~#~").where('^', BlockInWorld.hasState(CarvedPumpkinBlock.PUMPKINS_PREDICATE)).where('#', BlockInWorld.hasState(BlockStatePredicate.forBlock(Blocks.IRON_BLOCK))).where('~', (shapedetectorblock) -> { ++ return shapedetectorblock.getState().isAir(); + }).build(); + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CauldronBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CauldronBlock.java.patch new file mode 100644 index 0000000000..e1a9e019c4 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CauldronBlock.java.patch @@ -0,0 +1,100 @@ +--- a/net/minecraft/world/level/block/CauldronBlock.java ++++ b/net/minecraft/world/level/block/CauldronBlock.java +@@ -7,10 +7,13 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.biome.Biome; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; ++// CraftBukkit start ++import org.bukkit.event.block.CauldronLevelChangeEvent; ++// CraftBukkit end + + public class CauldronBlock extends AbstractCauldronBlock { + +@@ -19,61 +22,54 @@ + private static final float POWDER_SNOW_FILL_CHANCE = 0.1F; + + @Override +- @Override + public MapCodec codec() { + return CauldronBlock.CODEC; + } + +- public CauldronBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties, CauldronInteraction.EMPTY); ++ public CauldronBlock(BlockBehaviour.Properties properties) { ++ super(properties, CauldronInteraction.EMPTY); + } + + @Override +- @Override +- public boolean isFull(BlockState blockstate) { ++ public boolean isFull(IBlockData state) { + return false; + } + +- protected static boolean shouldHandlePrecipitation(Level level, Biome.Precipitation biome_precipitation) { +- return biome_precipitation == Biome.Precipitation.RAIN ? level.getRandom().nextFloat() < 0.05F : (biome_precipitation == Biome.Precipitation.SNOW ? level.getRandom().nextFloat() < 0.1F : false); ++ protected static boolean shouldHandlePrecipitation(Level level, Biome.Precipitation precipitation) { ++ return precipitation == Biome.Precipitation.RAIN ? level.getRandom().nextFloat() < 0.05F : (precipitation == Biome.Precipitation.SNOW ? level.getRandom().nextFloat() < 0.1F : false); + } + + @Override +- @Override +- public void handlePrecipitation(BlockState blockstate, Level level, BlockPos blockpos, Biome.Precipitation biome_precipitation) { +- if (shouldHandlePrecipitation(level, biome_precipitation)) { +- if (biome_precipitation == Biome.Precipitation.RAIN) { +- level.setBlockAndUpdate(blockpos, Blocks.WATER_CAULDRON.defaultBlockState()); +- level.gameEvent((Entity) null, GameEvent.BLOCK_CHANGE, blockpos); +- } else if (biome_precipitation == Biome.Precipitation.SNOW) { +- level.setBlockAndUpdate(blockpos, Blocks.POWDER_SNOW_CAULDRON.defaultBlockState()); +- level.gameEvent((Entity) null, GameEvent.BLOCK_CHANGE, blockpos); ++ public void handlePrecipitation(IBlockData state, Level level, BlockPos pos, Biome.Precipitation precipitation) { ++ if (shouldHandlePrecipitation(level, precipitation)) { ++ if (precipitation == Biome.Precipitation.RAIN) { ++ level.setBlockAndUpdate(pos, Blocks.WATER_CAULDRON.defaultBlockState()); ++ level.gameEvent((Entity) null, GameEvent.BLOCK_CHANGE, pos); ++ } else if (precipitation == Biome.Precipitation.SNOW) { ++ level.setBlockAndUpdate(pos, Blocks.POWDER_SNOW_CAULDRON.defaultBlockState()); ++ level.gameEvent((Entity) null, GameEvent.BLOCK_CHANGE, pos); + } + + } + } + + @Override +- @Override + protected boolean canReceiveStalactiteDrip(Fluid fluid) { + return true; + } + + @Override +- @Override +- protected void receiveStalactiteDrip(BlockState blockstate, Level level, BlockPos blockpos, Fluid fluid) { +- BlockState blockstate1; ++ protected void receiveStalactiteDrip(IBlockData state, Level level, BlockPos pos, Fluid fluid) { ++ IBlockData iblockdata1; + + if (fluid == Fluids.WATER) { +- blockstate1 = Blocks.WATER_CAULDRON.defaultBlockState(); +- level.setBlockAndUpdate(blockpos, blockstate1); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(blockstate1)); +- level.levelEvent(1047, blockpos, 0); ++ iblockdata1 = Blocks.WATER_CAULDRON.defaultBlockState(); ++ LayeredCauldronBlock.changeLevel(state, level, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL); // CraftBukkit ++ level.levelEvent(1047, pos, 0); + } else if (fluid == Fluids.LAVA) { +- blockstate1 = Blocks.LAVA_CAULDRON.defaultBlockState(); +- level.setBlockAndUpdate(blockpos, blockstate1); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(blockstate1)); +- level.levelEvent(1046, blockpos, 0); ++ iblockdata1 = Blocks.LAVA_CAULDRON.defaultBlockState(); ++ LayeredCauldronBlock.changeLevel(state, level, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL); // CraftBukkit ++ level.levelEvent(1046, pos, 0); + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CaveVines.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CaveVines.java.patch new file mode 100644 index 0000000000..b1687f0e9d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CaveVines.java.patch @@ -0,0 +1,80 @@ +--- a/net/minecraft/world/level/block/CaveVines.java ++++ b/net/minecraft/world/level/block/CaveVines.java +@@ -12,40 +12,64 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.VoxelShape; + ++// CraftBukkit start ++import java.util.Collections; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerHarvestBlockEvent; ++// CraftBukkit end ++ + public interface CaveVines { + + VoxelShape SHAPE = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 16.0D, 15.0D); + BooleanProperty BERRIES = BlockStateProperties.BERRIES; + +- static InteractionResult use(@Nullable Entity entity, BlockState blockstate, Level level, BlockPos blockpos) { +- if ((Boolean) blockstate.getValue(CaveVines.BERRIES)) { +- Block.popResource(level, blockpos, new ItemStack(Items.GLOW_BERRIES, 1)); ++ static InteractionResult use(@Nullable Entity entity, IBlockData state, Level level, BlockPos pos) { ++ if ((Boolean) state.getValue(CaveVines.BERRIES)) { ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, (IBlockData) state.setValue(CaveVines.BERRIES, false))) { ++ return InteractionResult.SUCCESS; ++ } ++ ++ if (entity instanceof Player) { ++ PlayerHarvestBlockEvent event = CraftEventFactory.callPlayerHarvestBlockEvent(level, pos, (Player) entity, net.minecraft.world.EnumHand.MAIN_HAND, Collections.singletonList(new ItemStack(Items.GLOW_BERRIES, 1))); ++ if (event.isCancelled()) { ++ return InteractionResult.SUCCESS; // We need to return a success either way, because making it PASS or FAIL will result in a bug where cancelling while harvesting w/ block in hand places block ++ } ++ for (org.bukkit.inventory.ItemStack itemStack : event.getItemsHarvested()) { ++ Block.popResource(level, pos, CraftItemStack.asNMSCopy(itemStack)); ++ } ++ } else { ++ Block.popResource(level, pos, new ItemStack(Items.GLOW_BERRIES, 1)); ++ } ++ // CraftBukkit end ++ + float f = Mth.randomBetween(level.random, 0.8F, 1.2F); + +- level.playSound((Player) null, blockpos, SoundEvents.CAVE_VINES_PICK_BERRIES, SoundSource.BLOCKS, 1.0F, f); +- BlockState blockstate1 = (BlockState) blockstate.setValue(CaveVines.BERRIES, false); ++ level.playSound((Player) null, pos, SoundEvents.CAVE_VINES_PICK_BERRIES, SoundSource.BLOCKS, 1.0F, f); ++ IBlockData iblockdata1 = (IBlockData) state.setValue(CaveVines.BERRIES, false); + +- level.setBlock(blockpos, blockstate1, 2); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(entity, blockstate1)); ++ level.setBlock(pos, iblockdata1, 2); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, iblockdata1)); + return InteractionResult.sidedSuccess(level.isClientSide); + } else { + return InteractionResult.PASS; + } + } + +- static boolean hasGlowBerries(BlockState blockstate) { +- return blockstate.hasProperty(CaveVines.BERRIES) && (Boolean) blockstate.getValue(CaveVines.BERRIES); ++ static boolean hasGlowBerries(IBlockData state) { ++ return state.hasProperty(CaveVines.BERRIES) && (Boolean) state.getValue(CaveVines.BERRIES); + } + +- static ToIntFunction emission(int i) { +- return (blockstate) -> { +- return (Boolean) blockstate.getValue(BlockStateProperties.BERRIES) ? i : 0; ++ static ToIntFunction emission(int berries) { ++ return (iblockdata) -> { ++ return (Boolean) iblockdata.getValue(BlockStateProperties.BERRIES) ? berries : 0; + }; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CeilingHangingSignBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CeilingHangingSignBlock.java.patch new file mode 100644 index 0000000000..8a3e53f3fd --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CeilingHangingSignBlock.java.patch @@ -0,0 +1,199 @@ +--- a/net/minecraft/world/level/block/CeilingHangingSignBlock.java ++++ b/net/minecraft/world/level/block/CeilingHangingSignBlock.java +@@ -10,7 +10,7 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.tags.BlockTags; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.HangingSignItem; +@@ -26,7 +26,7 @@ + import net.minecraft.world.level.block.entity.HangingSignBlockEntity; + import net.minecraft.world.level.block.entity.SignBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -51,129 +51,116 @@ + private static final Map AABBS = Maps.newHashMap(ImmutableMap.of(0, Block.box(1.0D, 0.0D, 7.0D, 15.0D, 10.0D, 9.0D), 4, Block.box(7.0D, 0.0D, 1.0D, 9.0D, 10.0D, 15.0D), 8, Block.box(1.0D, 0.0D, 7.0D, 15.0D, 10.0D, 9.0D), 12, Block.box(7.0D, 0.0D, 1.0D, 9.0D, 10.0D, 15.0D))); + + @Override +- @Override + public MapCodec codec() { + return CeilingHangingSignBlock.CODEC; + } + +- public CeilingHangingSignBlock(WoodType woodtype, BlockBehaviour.Properties blockbehaviour_properties) { +- super(woodtype, blockbehaviour_properties.sound(woodtype.hangingSignSoundType())); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(CeilingHangingSignBlock.ROTATION, 0)).setValue(CeilingHangingSignBlock.ATTACHED, false)).setValue(CeilingHangingSignBlock.WATERLOGGED, false)); ++ public CeilingHangingSignBlock(WoodType blockpropertywood, BlockBehaviour.Properties blockbase_info) { ++ super(blockpropertywood, blockbase_info.sound(blockpropertywood.hangingSignSoundType())); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(CeilingHangingSignBlock.ROTATION, 0)).setValue(CeilingHangingSignBlock.ATTACHED, false)).setValue(CeilingHangingSignBlock.WATERLOGGED, false)); + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof SignBlockEntity) { +- SignBlockEntity signblockentity = (SignBlockEntity) blockentity; +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ if (tileentity instanceof SignBlockEntity) { ++ SignBlockEntity tileentitysign = (SignBlockEntity) tileentity; ++ ItemStack itemstack = player.getItemInHand(hand); + +- if (this.shouldTryToChainAnotherHangingSign(player, blockhitresult, signblockentity, itemstack)) { ++ if (this.shouldTryToChainAnotherHangingSign(player, hit, tileentitysign, itemstack)) { + return InteractionResult.PASS; + } + } + +- return super.use(blockstate, level, blockpos, player, interactionhand, blockhitresult); ++ return super.use(state, level, pos, player, hand, hit); + } + +- private boolean shouldTryToChainAnotherHangingSign(Player player, BlockHitResult blockhitresult, SignBlockEntity signblockentity, ItemStack itemstack) { +- return !signblockentity.canExecuteClickCommands(signblockentity.isFacingFrontText(player), player) && itemstack.getItem() instanceof HangingSignItem && blockhitresult.getDirection().equals(Direction.DOWN); ++ private boolean shouldTryToChainAnotherHangingSign(Player player, BlockHitResult hitResult, SignBlockEntity sign, ItemStack stack) { ++ return !sign.canExecuteClickCommands(sign.isFacingFrontText(player), player) && stack.getItem() instanceof HangingSignItem && hitResult.getDirection().equals(Direction.DOWN); + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- return levelreader.getBlockState(blockpos.above()).isFaceSturdy(levelreader, blockpos.above(), Direction.DOWN, SupportType.CENTER); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ return level.getBlockState(pos.above()).isFaceSturdy(level, pos.above(), Direction.DOWN, SupportType.CENTER); + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- Level level = blockplacecontext.getLevel(); +- FluidState fluidstate = level.getFluidState(blockplacecontext.getClickedPos()); +- BlockPos blockpos = blockplacecontext.getClickedPos().above(); +- BlockState blockstate = level.getBlockState(blockpos); +- boolean flag = blockstate.is(BlockTags.ALL_HANGING_SIGNS); +- Direction direction = Direction.fromYRot((double) blockplacecontext.getRotation()); +- boolean flag1 = !Block.isFaceFull(blockstate.getCollisionShape(level, blockpos), Direction.DOWN) || blockplacecontext.isSecondaryUseActive(); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ Level world = context.getLevel(); ++ FluidState fluid = world.getFluidState(context.getClickedPos()); ++ BlockPos blockposition = context.getClickedPos().above(); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ boolean flag = iblockdata.is(BlockTags.ALL_HANGING_SIGNS); ++ Direction enumdirection = Direction.fromYRot((double) context.getRotation()); ++ boolean flag1 = !Block.isFaceFull(iblockdata.getCollisionShape(world, blockposition), Direction.DOWN) || context.isSecondaryUseActive(); + +- if (flag && !blockplacecontext.isSecondaryUseActive()) { +- if (blockstate.hasProperty(WallHangingSignBlock.FACING)) { +- Direction direction1 = (Direction) blockstate.getValue(WallHangingSignBlock.FACING); ++ if (flag && !context.isSecondaryUseActive()) { ++ if (iblockdata.hasProperty(WallHangingSignBlock.FACING)) { ++ Direction enumdirection1 = (Direction) iblockdata.getValue(WallHangingSignBlock.FACING); + +- if (direction1.getAxis().test(direction)) { ++ if (enumdirection1.getAxis().test(enumdirection)) { + flag1 = false; + } +- } else if (blockstate.hasProperty(CeilingHangingSignBlock.ROTATION)) { +- Optional optional = RotationSegment.convertToDirection((Integer) blockstate.getValue(CeilingHangingSignBlock.ROTATION)); ++ } else if (iblockdata.hasProperty(CeilingHangingSignBlock.ROTATION)) { ++ Optional optional = RotationSegment.convertToDirection((Integer) iblockdata.getValue(CeilingHangingSignBlock.ROTATION)); + +- if (optional.isPresent() && ((Direction) optional.get()).getAxis().test(direction)) { ++ if (optional.isPresent() && ((Direction) optional.get()).getAxis().test(enumdirection)) { + flag1 = false; + } + } + } + +- int i = !flag1 ? RotationSegment.convertToSegment(direction.getOpposite()) : RotationSegment.convertToSegment(blockplacecontext.getRotation() + 180.0F); ++ int i = !flag1 ? RotationSegment.convertToSegment(enumdirection.getOpposite()) : RotationSegment.convertToSegment(context.getRotation() + 180.0F); + +- return (BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(CeilingHangingSignBlock.ATTACHED, flag1)).setValue(CeilingHangingSignBlock.ROTATION, i)).setValue(CeilingHangingSignBlock.WATERLOGGED, fluidstate.getType() == Fluids.WATER); ++ return (IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(CeilingHangingSignBlock.ATTACHED, flag1)).setValue(CeilingHangingSignBlock.ROTATION, i)).setValue(CeilingHangingSignBlock.WATERLOGGED, fluid.getType() == Fluids.WATER); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- VoxelShape voxelshape = (VoxelShape) CeilingHangingSignBlock.AABBS.get(blockstate.getValue(CeilingHangingSignBlock.ROTATION)); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ VoxelShape voxelshape = (VoxelShape) CeilingHangingSignBlock.AABBS.get(state.getValue(CeilingHangingSignBlock.ROTATION)); + + return voxelshape == null ? CeilingHangingSignBlock.SHAPE : voxelshape; + } + + @Override +- @Override +- public VoxelShape getBlockSupportShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return this.getShape(blockstate, blockgetter, blockpos, CollisionContext.empty()); ++ public VoxelShape getBlockSupportShape(IBlockData state, BlockGetter level, BlockPos pos) { ++ return this.getShape(state, level, pos, CollisionContext.empty()); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- return direction == Direction.UP && !this.canSurvive(blockstate, levelaccessor, blockpos) ? Blocks.AIR.defaultBlockState() : super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ return facing == Direction.UP && !this.canSurvive(state, level, currentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- @Override +- public float getYRotationDegrees(BlockState blockstate) { +- return RotationSegment.convertToDegrees((Integer) blockstate.getValue(CeilingHangingSignBlock.ROTATION)); ++ public float getYRotationDegrees(IBlockData state) { ++ return RotationSegment.convertToDegrees((Integer) state.getValue(CeilingHangingSignBlock.ROTATION)); + } + + @Override +- @Override +- public BlockState rotate(BlockState blockstate, Rotation rotation) { +- return (BlockState) blockstate.setValue(CeilingHangingSignBlock.ROTATION, rotation.rotate((Integer) blockstate.getValue(CeilingHangingSignBlock.ROTATION), 16)); ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return (IBlockData) state.setValue(CeilingHangingSignBlock.ROTATION, rotation.rotate((Integer) state.getValue(CeilingHangingSignBlock.ROTATION), 16)); + } + + @Override +- @Override +- public BlockState mirror(BlockState blockstate, Mirror mirror) { +- return (BlockState) blockstate.setValue(CeilingHangingSignBlock.ROTATION, mirror.mirror((Integer) blockstate.getValue(CeilingHangingSignBlock.ROTATION), 16)); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return (IBlockData) state.setValue(CeilingHangingSignBlock.ROTATION, mirror.mirror((Integer) state.getValue(CeilingHangingSignBlock.ROTATION), 16)); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(CeilingHangingSignBlock.ROTATION, CeilingHangingSignBlock.ATTACHED, CeilingHangingSignBlock.WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(CeilingHangingSignBlock.ROTATION, CeilingHangingSignBlock.ATTACHED, CeilingHangingSignBlock.WATERLOGGED); + } + + @Override +- @Override +- public BlockEntity newBlockEntity(BlockPos blockpos, BlockState blockstate) { +- return new HangingSignBlockEntity(blockpos, blockstate); ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ return new HangingSignBlockEntity(pos, state); + } + + @Nullable + @Override +- @Override +- public BlockEntityTicker getTicker(Level level, BlockState blockstate, BlockEntityType blockentitytype) { +- return createTickerHelper(blockentitytype, BlockEntityType.HANGING_SIGN, SignBlockEntity::tick); ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { ++ return null; // Craftbukkit - remove unnecessary sign ticking + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ChangeOverTimeBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ChangeOverTimeBlock.java.patch new file mode 100644 index 0000000000..7d8bf33b51 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ChangeOverTimeBlock.java.patch @@ -0,0 +1,67 @@ +--- a/net/minecraft/world/level/block/ChangeOverTimeBlock.java ++++ b/net/minecraft/world/level/block/ChangeOverTimeBlock.java +@@ -5,22 +5,22 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public interface ChangeOverTimeBlock> { + + int SCAN_DISTANCE = 4; + +- Optional getNext(BlockState state); ++ Optional getNext(IBlockData state); + + float getChanceModifier(); + +- default void changeOverTime(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { ++ default void changeOverTime(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, RandomSource randomsource) { + float f = 0.05688889F; + + if (randomsource.nextFloat() < 0.05688889F) { +- this.getNextState(blockstate, serverlevel, blockpos, randomsource).ifPresent((blockstate1) -> { +- serverlevel.setBlockAndUpdate(blockpos, blockstate1); ++ this.getNextState(iblockdata, worldserver, blockposition, randomsource).ifPresent((iblockdata1) -> { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(worldserver, blockposition, iblockdata1); // CraftBukkit + }); + } + +@@ -28,22 +28,22 @@ + + T getAge(); + +- default Optional getNextState(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { ++ default Optional getNextState(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, RandomSource randomsource) { + int i = this.getAge().ordinal(); + int j = 0; + int k = 0; +- Iterator iterator = BlockPos.withinManhattan(blockpos, 4, 4, 4).iterator(); ++ Iterator iterator = BlockPos.withinManhattan(blockposition, 4, 4, 4).iterator(); + + while (iterator.hasNext()) { +- BlockPos blockpos1 = (BlockPos) iterator.next(); +- int l = blockpos1.distManhattan(blockpos); ++ BlockPos blockposition1 = (BlockPos) iterator.next(); ++ int l = blockposition1.distManhattan(blockposition); + + if (l > 4) { + break; + } + +- if (!blockpos1.equals(blockpos)) { +- Block block = serverlevel.getBlockState(blockpos1).getBlock(); ++ if (!blockposition1.equals(blockposition)) { ++ Block block = worldserver.getBlockState(blockposition1).getBlock(); + + if (block instanceof ChangeOverTimeBlock) { + ChangeOverTimeBlock changeovertimeblock = (ChangeOverTimeBlock) block; +@@ -69,6 +69,6 @@ + float f = (float) (k + 1) / (float) (k + j + 1); + float f1 = f * f * this.getChanceModifier(); + +- return randomsource.nextFloat() < f1 ? this.getNext(blockstate) : Optional.empty(); ++ return randomsource.nextFloat() < f1 ? this.getNext(iblockdata) : Optional.empty(); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ChestBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ChestBlock.java.patch new file mode 100644 index 0000000000..1741eccf2f --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ChestBlock.java.patch @@ -0,0 +1,532 @@ +--- a/net/minecraft/world/level/block/ChestBlock.java ++++ b/net/minecraft/world/level/block/ChestBlock.java +@@ -20,9 +20,9 @@ + import net.minecraft.world.CompoundContainer; + import net.minecraft.world.Container; + import net.minecraft.world.Containers; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; ++import net.minecraft.world.ITileInventory; + import net.minecraft.world.InteractionResult; +-import net.minecraft.world.MenuProvider; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.animal.Cat; + import net.minecraft.world.entity.monster.piglin.PiglinAi; +@@ -41,7 +41,7 @@ + import net.minecraft.world.level.block.entity.ChestBlockEntity; + import net.minecraft.world.level.block.entity.LidBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -51,7 +51,7 @@ + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; +@@ -59,8 +59,8 @@ + + public class ChestBlock extends AbstractChestBlock implements SimpleWaterloggedBlock { + +- public static final MapCodec CODEC = simpleCodec((blockbehaviour_properties) -> { +- return new ChestBlock(blockbehaviour_properties, () -> { ++ public static final MapCodec CODEC = simpleCodec((blockbase_info) -> { ++ return new ChestBlock(blockbase_info, () -> { + return BlockEntityType.CHEST; + }); + }); +@@ -76,111 +76,114 @@ + protected static final VoxelShape EAST_AABB = Block.box(1.0D, 0.0D, 1.0D, 16.0D, 14.0D, 15.0D); + protected static final VoxelShape AABB = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 14.0D, 15.0D); + private static final DoubleBlockCombiner.Combiner> CHEST_COMBINER = new DoubleBlockCombiner.Combiner>() { +- @Override +- public Optional acceptDouble(ChestBlockEntity chestblockentity, ChestBlockEntity chestblockentity1) { +- return Optional.of(new CompoundContainer(chestblockentity, chestblockentity1)); ++ public Optional acceptDouble(ChestBlockEntity tileentitychest, ChestBlockEntity tileentitychest1) { ++ return Optional.of(new CompoundContainer(tileentitychest, tileentitychest1)); + } + +- @Override +- public Optional acceptSingle(ChestBlockEntity chestblockentity) { +- return Optional.of(chestblockentity); ++ public Optional acceptSingle(ChestBlockEntity tileentitychest) { ++ return Optional.of(tileentitychest); + } + + @Override +- @Override + public Optional acceptNone() { + return Optional.empty(); + } + }; +- private static final DoubleBlockCombiner.Combiner> MENU_PROVIDER_COMBINER = new DoubleBlockCombiner.Combiner>() { ++ private static final DoubleBlockCombiner.Combiner> MENU_PROVIDER_COMBINER = new DoubleBlockCombiner.Combiner>() { ++ public Optional acceptDouble(final ChestBlockEntity tileentitychest, final ChestBlockEntity tileentitychest1) { ++ final CompoundContainer inventorylargechest = new CompoundContainer(tileentitychest, tileentitychest1); ++ ++ return Optional.of(new DoubleInventory(tileentitychest, tileentitychest1, inventorylargechest)); // CraftBukkit ++ } ++ ++ public Optional acceptSingle(ChestBlockEntity tileentitychest) { ++ return Optional.of(tileentitychest); ++ } ++ + @Override +- public Optional acceptDouble(final ChestBlockEntity chestblockentity, final ChestBlockEntity chestblockentity1) { +- final CompoundContainer compoundcontainer = new CompoundContainer(chestblockentity, chestblockentity1); ++ public Optional acceptNone() { ++ return Optional.empty(); ++ } ++ }; + +- return Optional.of(new MenuProvider() { +- @Nullable +- @Override +- @Override +- public AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) { +- if (chestblockentity.canOpen(player) && chestblockentity1.canOpen(player)) { +- chestblockentity.unpackLootTable(inventory.player); +- chestblockentity1.unpackLootTable(inventory.player); +- return ChestMenu.sixRows(i, inventory, compoundcontainer); +- } else { +- return null; +- } +- } ++ // CraftBukkit start ++ public static class DoubleInventory implements ITileInventory { + +- @Override +- @Override +- public Component getDisplayName() { +- return (Component) (chestblockentity.hasCustomName() ? chestblockentity.getDisplayName() : (chestblockentity1.hasCustomName() ? chestblockentity1.getDisplayName() : Component.translatable("container.chestDouble"))); +- } +- }); ++ private final ChestBlockEntity tileentitychest; ++ private final ChestBlockEntity tileentitychest1; ++ public final CompoundContainer inventorylargechest; ++ ++ public DoubleInventory(ChestBlockEntity tileentitychest, ChestBlockEntity tileentitychest1, CompoundContainer inventorylargechest) { ++ this.tileentitychest = tileentitychest; ++ this.tileentitychest1 = tileentitychest1; ++ this.inventorylargechest = inventorylargechest; + } + ++ @Nullable + @Override +- public Optional acceptSingle(ChestBlockEntity chestblockentity) { +- return Optional.of(chestblockentity); ++ public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { ++ if (tileentitychest.canOpen(player) && tileentitychest1.canOpen(player)) { ++ tileentitychest.unpackLootTable(playerInventory.player); ++ tileentitychest1.unpackLootTable(playerInventory.player); ++ return ChestMenu.sixRows(containerId, playerInventory, inventorylargechest); ++ } else { ++ return null; ++ } + } + + @Override +- @Override +- public Optional acceptNone() { +- return Optional.empty(); ++ public Component getDisplayName() { ++ return (Component) (tileentitychest.hasCustomName() ? tileentitychest.getDisplayName() : (tileentitychest1.hasCustomName() ? tileentitychest1.getDisplayName() : Component.translatable("container.chestDouble"))); + } + }; ++ // CraftBukkit end + + @Override +- @Override + public MapCodec codec() { + return ChestBlock.CODEC; + } + +- protected ChestBlock(BlockBehaviour.Properties blockbehaviour_properties, Supplier> supplier) { +- super(blockbehaviour_properties, supplier); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(ChestBlock.FACING, Direction.NORTH)).setValue(ChestBlock.TYPE, ChestType.SINGLE)).setValue(ChestBlock.WATERLOGGED, false)); ++ protected ChestBlock(BlockBehaviour.Properties properties, Supplier> blockEntityType) { ++ super(properties, blockEntityType); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(ChestBlock.FACING, Direction.NORTH)).setValue(ChestBlock.TYPE, ChestType.SINGLE)).setValue(ChestBlock.WATERLOGGED, false)); + } + +- public static DoubleBlockCombiner.BlockType getBlockType(BlockState blockstate) { +- ChestType chesttype = (ChestType) blockstate.getValue(ChestBlock.TYPE); ++ public static DoubleBlockCombiner.BlockType getBlockType(IBlockData state) { ++ ChestType blockpropertychesttype = (ChestType) state.getValue(ChestBlock.TYPE); + +- return chesttype == ChestType.SINGLE ? DoubleBlockCombiner.BlockType.SINGLE : (chesttype == ChestType.RIGHT ? DoubleBlockCombiner.BlockType.FIRST : DoubleBlockCombiner.BlockType.SECOND); ++ return blockpropertychesttype == ChestType.SINGLE ? DoubleBlockCombiner.BlockType.SINGLE : (blockpropertychesttype == ChestType.RIGHT ? DoubleBlockCombiner.BlockType.FIRST : DoubleBlockCombiner.BlockType.SECOND); + } + + @Override +- @Override +- public RenderShape getRenderShape(BlockState blockstate) { +- return RenderShape.ENTITYBLOCK_ANIMATED; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.ENTITYBLOCK_ANIMATED; + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if ((Boolean) blockstate.getValue(ChestBlock.WATERLOGGED)) { +- levelaccessor.scheduleTick(blockpos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(levelaccessor)); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if ((Boolean) state.getValue(ChestBlock.WATERLOGGED)) { ++ level.scheduleTick(currentPos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + +- if (blockstate1.is((Block) this) && direction.getAxis().isHorizontal()) { +- ChestType chesttype = (ChestType) blockstate1.getValue(ChestBlock.TYPE); ++ if (facingState.is((Block) this) && facing.getAxis().isHorizontal()) { ++ ChestType blockpropertychesttype = (ChestType) facingState.getValue(ChestBlock.TYPE); + +- if (blockstate.getValue(ChestBlock.TYPE) == ChestType.SINGLE && chesttype != ChestType.SINGLE && blockstate.getValue(ChestBlock.FACING) == blockstate1.getValue(ChestBlock.FACING) && getConnectedDirection(blockstate1) == direction.getOpposite()) { +- return (BlockState) blockstate.setValue(ChestBlock.TYPE, chesttype.getOpposite()); ++ if (state.getValue(ChestBlock.TYPE) == ChestType.SINGLE && blockpropertychesttype != ChestType.SINGLE && state.getValue(ChestBlock.FACING) == facingState.getValue(ChestBlock.FACING) && getConnectedDirection(facingState) == facing.getOpposite()) { ++ return (IBlockData) state.setValue(ChestBlock.TYPE, blockpropertychesttype.getOpposite()); + } +- } else if (getConnectedDirection(blockstate) == direction) { +- return (BlockState) blockstate.setValue(ChestBlock.TYPE, ChestType.SINGLE); ++ } else if (getConnectedDirection(state) == facing) { ++ return (IBlockData) state.setValue(ChestBlock.TYPE, ChestType.SINGLE); + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- if (blockstate.getValue(ChestBlock.TYPE) == ChestType.SINGLE) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ if (state.getValue(ChestBlock.TYPE) == ChestType.SINGLE) { + return ChestBlock.AABB; + } else { +- switch (getConnectedDirection(blockstate)) { ++ switch (getConnectedDirection(state)) { + case NORTH: + default: + return ChestBlock.NORTH_AABB; +@@ -194,84 +197,79 @@ + } + } + +- public static Direction getConnectedDirection(BlockState blockstate) { +- Direction direction = (Direction) blockstate.getValue(ChestBlock.FACING); ++ public static Direction getConnectedDirection(IBlockData state) { ++ Direction enumdirection = (Direction) state.getValue(ChestBlock.FACING); + +- return blockstate.getValue(ChestBlock.TYPE) == ChestType.LEFT ? direction.getClockWise() : direction.getCounterClockWise(); ++ return state.getValue(ChestBlock.TYPE) == ChestType.LEFT ? enumdirection.getClockWise() : enumdirection.getCounterClockWise(); + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- ChestType chesttype = ChestType.SINGLE; +- Direction direction = blockplacecontext.getHorizontalDirection().getOpposite(); +- FluidState fluidstate = blockplacecontext.getLevel().getFluidState(blockplacecontext.getClickedPos()); +- boolean flag = blockplacecontext.isSecondaryUseActive(); +- Direction direction1 = blockplacecontext.getClickedFace(); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ ChestType blockpropertychesttype = ChestType.SINGLE; ++ Direction enumdirection = context.getHorizontalDirection().getOpposite(); ++ FluidState fluid = context.getLevel().getFluidState(context.getClickedPos()); ++ boolean flag = context.isSecondaryUseActive(); ++ Direction enumdirection1 = context.getClickedFace(); + +- if (direction1.getAxis().isHorizontal() && flag) { +- Direction direction2 = this.candidatePartnerFacing(blockplacecontext, direction1.getOpposite()); ++ if (enumdirection1.getAxis().isHorizontal() && flag) { ++ Direction enumdirection2 = this.candidatePartnerFacing(context, enumdirection1.getOpposite()); + +- if (direction2 != null && direction2.getAxis() != direction1.getAxis()) { +- direction = direction2; +- chesttype = direction2.getCounterClockWise() == direction1.getOpposite() ? ChestType.RIGHT : ChestType.LEFT; ++ if (enumdirection2 != null && enumdirection2.getAxis() != enumdirection1.getAxis()) { ++ enumdirection = enumdirection2; ++ blockpropertychesttype = enumdirection2.getCounterClockWise() == enumdirection1.getOpposite() ? ChestType.RIGHT : ChestType.LEFT; + } + } + +- if (chesttype == ChestType.SINGLE && !flag) { +- if (direction == this.candidatePartnerFacing(blockplacecontext, direction.getClockWise())) { +- chesttype = ChestType.LEFT; +- } else if (direction == this.candidatePartnerFacing(blockplacecontext, direction.getCounterClockWise())) { +- chesttype = ChestType.RIGHT; ++ if (blockpropertychesttype == ChestType.SINGLE && !flag) { ++ if (enumdirection == this.candidatePartnerFacing(context, enumdirection.getClockWise())) { ++ blockpropertychesttype = ChestType.LEFT; ++ } else if (enumdirection == this.candidatePartnerFacing(context, enumdirection.getCounterClockWise())) { ++ blockpropertychesttype = ChestType.RIGHT; + } + } + +- return (BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(ChestBlock.FACING, direction)).setValue(ChestBlock.TYPE, chesttype)).setValue(ChestBlock.WATERLOGGED, fluidstate.getType() == Fluids.WATER); ++ return (IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(ChestBlock.FACING, enumdirection)).setValue(ChestBlock.TYPE, blockpropertychesttype)).setValue(ChestBlock.WATERLOGGED, fluid.getType() == Fluids.WATER); + } + + @Override +- @Override +- public FluidState getFluidState(BlockState blockstate) { +- return (Boolean) blockstate.getValue(ChestBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(blockstate); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(ChestBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Nullable +- private Direction candidatePartnerFacing(BlockPlaceContext blockplacecontext, Direction direction) { +- BlockState blockstate = blockplacecontext.getLevel().getBlockState(blockplacecontext.getClickedPos().relative(direction)); ++ private Direction candidatePartnerFacing(BlockPlaceContext context, Direction direction) { ++ IBlockData iblockdata = context.getLevel().getBlockState(context.getClickedPos().relative(direction)); + +- return blockstate.is((Block) this) && blockstate.getValue(ChestBlock.TYPE) == ChestType.SINGLE ? (Direction) blockstate.getValue(ChestBlock.FACING) : null; ++ return iblockdata.is((Block) this) && iblockdata.getValue(ChestBlock.TYPE) == ChestType.SINGLE ? (Direction) iblockdata.getValue(ChestBlock.FACING) : null; + } + + @Override +- @Override +- public void setPlacedBy(Level level, BlockPos blockpos, BlockState blockstate, LivingEntity livingentity, ItemStack itemstack) { +- if (itemstack.hasCustomHoverName()) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, LivingEntity placer, ItemStack stack) { ++ if (stack.hasCustomHoverName()) { ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof ChestBlockEntity) { +- ((ChestBlockEntity) blockentity).setCustomName(itemstack.getHoverName()); ++ if (tileentity instanceof ChestBlockEntity) { ++ ((ChestBlockEntity) tileentity).setCustomName(stack.getHoverName()); + } + } + + } + + @Override +- @Override +- public void onRemove(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- Containers.dropContentsOnDestroy(blockstate, blockstate1, level, blockpos); +- super.onRemove(blockstate, level, blockpos, blockstate1, flag); ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { ++ Containers.dropContentsOnDestroy(state, newState, level, pos); ++ super.onRemove(state, level, pos, newState, isMoving); + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + if (level.isClientSide) { + return InteractionResult.SUCCESS; + } else { +- MenuProvider menuprovider = this.getMenuProvider(blockstate, level, blockpos); ++ ITileInventory itileinventory = this.getMenuProvider(state, level, pos); + +- if (menuprovider != null) { +- player.openMenu(menuprovider); ++ if (itileinventory != null) { ++ player.openMenu(itileinventory); + player.awardStat(this.getOpenChestStat()); + PiglinAi.angerNearbyPiglins(player, true); + } +@@ -289,92 +287,92 @@ + } + + @Nullable +- public static Container getContainer(ChestBlock chestblock, BlockState blockstate, Level level, BlockPos blockpos, boolean flag) { +- return (Container) ((Optional) chestblock.combine(blockstate, level, blockpos, flag).apply(ChestBlock.CHEST_COMBINER)).orElse((Object) null); ++ public static Container getContainer(ChestBlock chest, IBlockData state, Level level, BlockPos pos, boolean override) { ++ return (Container) ((Optional) chest.combine(state, level, pos, override).apply(ChestBlock.CHEST_COMBINER)).orElse((Object) null); + } + + @Override +- @Override +- public DoubleBlockCombiner.NeighborCombineResult combine(BlockState blockstate, Level level, BlockPos blockpos, boolean flag) { +- BiPredicate bipredicate; ++ public DoubleBlockCombiner.NeighborCombineResult combine(IBlockData state, Level level, BlockPos pos, boolean override) { ++ BiPredicate bipredicate; // CraftBukkit - decompile error + +- if (flag) { +- bipredicate = (levelaccessor, blockpos1) -> { ++ if (override) { ++ bipredicate = (generatoraccess, blockposition1) -> { + return false; + }; + } else { + bipredicate = ChestBlock::isChestBlockedAt; + } + +- return DoubleBlockCombiner.combineWithNeigbour((BlockEntityType) this.blockEntityType.get(), ChestBlock::getBlockType, ChestBlock::getConnectedDirection, ChestBlock.FACING, blockstate, level, blockpos, bipredicate); ++ return DoubleBlockCombiner.combineWithNeigbour((BlockEntityType) this.blockEntityType.get(), ChestBlock::getBlockType, ChestBlock::getConnectedDirection, ChestBlock.FACING, state, level, pos, bipredicate); + } + + @Nullable + @Override +- @Override +- public MenuProvider getMenuProvider(BlockState blockstate, Level level, BlockPos blockpos) { +- return (MenuProvider) ((Optional) this.combine(blockstate, level, blockpos, false).apply(ChestBlock.MENU_PROVIDER_COMBINER)).orElse((Object) null); ++ public ITileInventory getMenuProvider(IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ return getMenuProvider(state, level, pos, false); + } + +- public static DoubleBlockCombiner.Combiner opennessCombiner(final LidBlockEntity lidblockentity) { ++ @Nullable ++ public ITileInventory getMenuProvider(IBlockData iblockdata, Level world, BlockPos blockposition, boolean ignoreObstructions) { ++ return (ITileInventory) ((Optional) this.combine(iblockdata, world, blockposition, ignoreObstructions).apply(ChestBlock.MENU_PROVIDER_COMBINER)).orElse((Object) null); ++ // CraftBukkit end ++ } ++ ++ public static DoubleBlockCombiner.Combiner opennessCombiner(final LidBlockEntity lid) { + return new DoubleBlockCombiner.Combiner() { +- @Override +- public Float2FloatFunction acceptDouble(ChestBlockEntity chestblockentity, ChestBlockEntity chestblockentity1) { ++ public Float2FloatFunction acceptDouble(ChestBlockEntity first, ChestBlockEntity second) { + return (f) -> { +- return Math.max(chestblockentity.getOpenNess(f), chestblockentity1.getOpenNess(f)); ++ return Math.max(first.getOpenNess(f), second.getOpenNess(f)); + }; + } + +- @Override +- public Float2FloatFunction acceptSingle(ChestBlockEntity chestblockentity) { +- Objects.requireNonNull(chestblockentity); +- return chestblockentity::getOpenNess; ++ public Float2FloatFunction acceptSingle(ChestBlockEntity single) { ++ Objects.requireNonNull(single); ++ return single::getOpenNess; + } + + @Override +- @Override + public Float2FloatFunction acceptNone() { +- LidBlockEntity lidblockentity1 = lidblockentity; ++ LidBlockEntity lidblockentity1 = lid; + +- Objects.requireNonNull(lidblockentity); ++ Objects.requireNonNull(lid); + return lidblockentity1::getOpenNess; + } + }; + } + + @Override +- @Override +- public BlockEntity newBlockEntity(BlockPos blockpos, BlockState blockstate) { +- return new ChestBlockEntity(blockpos, blockstate); ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ return new ChestBlockEntity(pos, state); + } + + @Nullable + @Override +- @Override +- public BlockEntityTicker getTicker(Level level, BlockState blockstate, BlockEntityType blockentitytype) { +- return level.isClientSide ? createTickerHelper(blockentitytype, this.blockEntityType(), ChestBlockEntity::lidAnimateTick) : null; ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { ++ return level.isClientSide ? createTickerHelper(blockEntityType, this.blockEntityType(), ChestBlockEntity::lidAnimateTick) : null; + } + +- public static boolean isChestBlockedAt(LevelAccessor levelaccessor, BlockPos blockpos) { +- return isBlockedChestByBlock(levelaccessor, blockpos) || isCatSittingOnChest(levelaccessor, blockpos); ++ public static boolean isChestBlockedAt(LevelAccessor level, BlockPos pos) { ++ return isBlockedChestByBlock(level, pos) || isCatSittingOnChest(level, pos); + } + +- private static boolean isBlockedChestByBlock(BlockGetter blockgetter, BlockPos blockpos) { +- BlockPos blockpos1 = blockpos.above(); ++ private static boolean isBlockedChestByBlock(BlockGetter level, BlockPos pos) { ++ BlockPos blockposition1 = pos.above(); + +- return blockgetter.getBlockState(blockpos1).isRedstoneConductor(blockgetter, blockpos1); ++ return level.getBlockState(blockposition1).isRedstoneConductor(level, blockposition1); + } + +- private static boolean isCatSittingOnChest(LevelAccessor levelaccessor, BlockPos blockpos) { +- List list = levelaccessor.getEntitiesOfClass(Cat.class, new AABB((double) blockpos.getX(), (double) (blockpos.getY() + 1), (double) blockpos.getZ(), (double) (blockpos.getX() + 1), (double) (blockpos.getY() + 2), (double) (blockpos.getZ() + 1))); ++ private static boolean isCatSittingOnChest(LevelAccessor level, BlockPos pos) { ++ List list = level.getEntitiesOfClass(Cat.class, new AABB((double) pos.getX(), (double) (pos.getY() + 1), (double) pos.getZ(), (double) (pos.getX() + 1), (double) (pos.getY() + 2), (double) (pos.getZ() + 1))); + + if (!list.isEmpty()) { + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- Cat cat = (Cat) iterator.next(); ++ Cat entitycat = (Cat) iterator.next(); + +- if (cat.isInSittingPose()) { ++ if (entitycat.isInSittingPose()) { + return true; + } + } +@@ -384,48 +382,41 @@ + } + + @Override +- @Override +- public boolean hasAnalogOutputSignal(BlockState blockstate) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return true; + } + + @Override +- @Override +- public int getAnalogOutputSignal(BlockState blockstate, Level level, BlockPos blockpos) { +- return AbstractContainerMenu.getRedstoneSignalFromContainer(getContainer(this, blockstate, level, blockpos, false)); ++ public int getAnalogOutputSignal(IBlockData blockState, Level level, BlockPos pos) { ++ return AbstractContainerMenu.getRedstoneSignalFromContainer(getContainer(this, blockState, level, pos, false)); + } + + @Override +- @Override +- public BlockState rotate(BlockState blockstate, Rotation rotation) { +- return (BlockState) blockstate.setValue(ChestBlock.FACING, rotation.rotate((Direction) blockstate.getValue(ChestBlock.FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return (IBlockData) state.setValue(ChestBlock.FACING, rotation.rotate((Direction) state.getValue(ChestBlock.FACING))); + } + + @Override +- @Override +- public BlockState mirror(BlockState blockstate, Mirror mirror) { +- return blockstate.rotate(mirror.getRotation((Direction) blockstate.getValue(ChestBlock.FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(ChestBlock.FACING))); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(ChestBlock.FACING, ChestBlock.TYPE, ChestBlock.WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(ChestBlock.FACING, ChestBlock.TYPE, ChestBlock.WATERLOGGED); + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- BlockEntity blockentity = serverlevel.getBlockEntity(blockpos); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof ChestBlockEntity) { +- ((ChestBlockEntity) blockentity).recheckOpen(); ++ if (tileentity instanceof ChestBlockEntity) { ++ ((ChestBlockEntity) tileentity).recheckOpen(); + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ChorusFlowerBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ChorusFlowerBlock.java.patch new file mode 100644 index 0000000000..e83dd06795 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ChorusFlowerBlock.java.patch @@ -0,0 +1,369 @@ +--- a/net/minecraft/world/level/block/ChorusFlowerBlock.java ++++ b/net/minecraft/world/level/block/ChorusFlowerBlock.java +@@ -15,18 +15,20 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.VoxelShape; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public class ChorusFlowerBlock extends Block { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- return instance.group(BuiltInRegistries.BLOCK.byNameCodec().fieldOf("plant").forGetter((chorusflowerblock) -> { +- return chorusflowerblock.plant; ++ return instance.group(BuiltInRegistries.BLOCK.byNameCodec().fieldOf("plant").forGetter((blockchorusflower) -> { ++ return blockchorusflower.plant; + }), propertiesCodec()).apply(instance, ChorusFlowerBlock::new); + }); + public static final int DEAD_AGE = 5; +@@ -35,62 +37,57 @@ + private final Block plant; + + @Override +- @Override + public MapCodec codec() { + return ChorusFlowerBlock.CODEC; + } + +- protected ChorusFlowerBlock(Block block, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ protected ChorusFlowerBlock(Block block, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info); + this.plant = block; +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(ChorusFlowerBlock.AGE, 0)); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(ChorusFlowerBlock.AGE, 0)); + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (!blockstate.canSurvive(serverlevel, blockpos)) { +- serverlevel.destroyBlock(blockpos, true); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (!state.canSurvive(level, pos)) { ++ level.destroyBlock(pos, true); + } + + } + + @Override +- @Override +- public boolean isRandomlyTicking(BlockState blockstate) { +- return (Integer) blockstate.getValue(ChorusFlowerBlock.AGE) < 5; ++ public boolean isRandomlyTicking(IBlockData state) { ++ return (Integer) state.getValue(ChorusFlowerBlock.AGE) < 5; + } + + @Override +- @Override +- public VoxelShape getBlockSupportShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { ++ public VoxelShape getBlockSupportShape(IBlockData state, BlockGetter level, BlockPos pos) { + return ChorusFlowerBlock.BLOCK_SUPPORT_SHAPE; + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- BlockPos blockpos1 = blockpos.above(); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ BlockPos blockposition1 = pos.above(); + +- if (serverlevel.isEmptyBlock(blockpos1) && blockpos1.getY() < serverlevel.getMaxBuildHeight()) { +- int i = (Integer) blockstate.getValue(ChorusFlowerBlock.AGE); ++ if (level.isEmptyBlock(blockposition1) && blockposition1.getY() < level.getMaxBuildHeight()) { ++ int i = (Integer) state.getValue(ChorusFlowerBlock.AGE); + + if (i < 5) { + boolean flag = false; + boolean flag1 = false; +- BlockState blockstate1 = serverlevel.getBlockState(blockpos.below()); ++ IBlockData iblockdata1 = level.getBlockState(pos.below()); + int j; + +- if (blockstate1.is(Blocks.END_STONE)) { ++ if (iblockdata1.is(Blocks.END_STONE)) { + flag = true; +- } else if (blockstate1.is(this.plant)) { ++ } else if (iblockdata1.is(this.plant)) { + j = 1; + + for (int k = 0; k < 4; ++k) { +- BlockState blockstate2 = serverlevel.getBlockState(blockpos.below(j + 1)); ++ IBlockData iblockdata2 = level.getBlockState(pos.below(j + 1)); + +- if (!blockstate2.is(this.plant)) { +- if (blockstate2.is(Blocks.END_STONE)) { ++ if (!iblockdata2.is(this.plant)) { ++ if (iblockdata2.is(Blocks.END_STONE)) { + flag1 = true; + } + break; +@@ -99,18 +96,22 @@ + ++j; + } + +- if (j < 2 || j <= randomsource.nextInt(flag1 ? 5 : 4)) { ++ if (j < 2 || j <= random.nextInt(flag1 ? 5 : 4)) { + flag = true; + } +- } else if (blockstate1.isAir()) { ++ } else if (iblockdata1.isAir()) { + flag = true; + } + +- if (flag && allNeighborsEmpty(serverlevel, blockpos1, (Direction) null) && serverlevel.isEmptyBlock(blockpos.above(2))) { +- serverlevel.setBlock(blockpos, ChorusPlantBlock.getStateWithConnections(serverlevel, blockpos, this.plant.defaultBlockState()), 2); +- this.placeGrownFlower(serverlevel, blockpos1, i); ++ if (flag && allNeighborsEmpty(level, blockposition1, (Direction) null) && level.isEmptyBlock(pos.above(2))) { ++ // CraftBukkit start - add event ++ if (CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition1, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(i)), 2)) { ++ level.setBlock(pos, ChorusPlantBlock.getStateWithConnections(level, pos, this.plant.defaultBlockState()), 2); ++ this.placeGrownFlower(level, blockposition1, i); ++ } ++ // CraftBukkit end + } else if (i < 4) { +- j = randomsource.nextInt(4); ++ j = random.nextInt(4); + if (flag1) { + ++j; + } +@@ -118,87 +119,97 @@ + boolean flag2 = false; + + for (int l = 0; l < j; ++l) { +- Direction direction = Direction.Plane.HORIZONTAL.getRandomDirection(randomsource); +- BlockPos blockpos2 = blockpos.relative(direction); ++ Direction enumdirection = Direction.Plane.HORIZONTAL.getRandomDirection(random); ++ BlockPos blockposition2 = pos.relative(enumdirection); + +- if (serverlevel.isEmptyBlock(blockpos2) && serverlevel.isEmptyBlock(blockpos2.below()) && allNeighborsEmpty(serverlevel, blockpos2, direction.getOpposite())) { +- this.placeGrownFlower(serverlevel, blockpos2, i + 1); +- flag2 = true; ++ if (level.isEmptyBlock(blockposition2) && level.isEmptyBlock(blockposition2.below()) && allNeighborsEmpty(level, blockposition2, enumdirection.getOpposite())) { ++ // CraftBukkit start - add event ++ if (CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition2, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(i + 1)), 2)) { ++ this.placeGrownFlower(level, blockposition2, i + 1); ++ flag2 = true; ++ } ++ // CraftBukkit end + } + } + + if (flag2) { +- serverlevel.setBlock(blockpos, ChorusPlantBlock.getStateWithConnections(serverlevel, blockpos, this.plant.defaultBlockState()), 2); ++ level.setBlock(pos, ChorusPlantBlock.getStateWithConnections(level, pos, this.plant.defaultBlockState()), 2); + } else { +- this.placeDeadFlower(serverlevel, blockpos); ++ // CraftBukkit start - add event ++ if (CraftEventFactory.handleBlockGrowEvent(level, pos, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(5)), 2)) { ++ this.placeDeadFlower(level, pos); ++ } ++ // CraftBukkit end + } + } else { +- this.placeDeadFlower(serverlevel, blockpos); ++ // CraftBukkit start - add event ++ if (CraftEventFactory.handleBlockGrowEvent(level, pos, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(5)), 2)) { ++ this.placeDeadFlower(level, pos); ++ } ++ // CraftBukkit end + } + + } + } + } + +- private void placeGrownFlower(Level level, BlockPos blockpos, int i) { +- level.setBlock(blockpos, (BlockState) this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, i), 2); +- level.levelEvent(1033, blockpos, 0); ++ private void placeGrownFlower(Level level, BlockPos pos, int age) { ++ level.setBlock(pos, (IBlockData) this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, age), 2); ++ level.levelEvent(1033, pos, 0); + } + +- private void placeDeadFlower(Level level, BlockPos blockpos) { +- level.setBlock(blockpos, (BlockState) this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, 5), 2); +- level.levelEvent(1034, blockpos, 0); ++ private void placeDeadFlower(Level level, BlockPos pos) { ++ level.setBlock(pos, (IBlockData) this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, 5), 2); ++ level.levelEvent(1034, pos, 0); + } + +- private static boolean allNeighborsEmpty(LevelReader levelreader, BlockPos blockpos, @Nullable Direction direction) { ++ private static boolean allNeighborsEmpty(LevelReader level, BlockPos pos, @Nullable Direction excludingSide) { + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- Direction direction1; ++ Direction enumdirection1; + + do { + if (!iterator.hasNext()) { + return true; + } + +- direction1 = (Direction) iterator.next(); +- } while (direction1 == direction || levelreader.isEmptyBlock(blockpos.relative(direction1))); ++ enumdirection1 = (Direction) iterator.next(); ++ } while (enumdirection1 == excludingSide || level.isEmptyBlock(pos.relative(enumdirection1))); + + return false; + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if (direction != Direction.UP && !blockstate.canSurvive(levelaccessor, blockpos)) { +- levelaccessor.scheduleTick(blockpos, (Block) this, 1); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if (facing != Direction.UP && !state.canSurvive(level, currentPos)) { ++ level.scheduleTick(currentPos, (Block) this, 1); + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- BlockState blockstate1 = levelreader.getBlockState(blockpos.below()); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ IBlockData iblockdata1 = level.getBlockState(pos.below()); + +- if (!blockstate1.is(this.plant) && !blockstate1.is(Blocks.END_STONE)) { +- if (!blockstate1.isAir()) { ++ if (!iblockdata1.is(this.plant) && !iblockdata1.is(Blocks.END_STONE)) { ++ if (!iblockdata1.isAir()) { + return false; + } else { + boolean flag = false; + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); +- BlockState blockstate2 = levelreader.getBlockState(blockpos.relative(direction)); ++ Direction enumdirection = (Direction) iterator.next(); ++ IBlockData iblockdata2 = level.getBlockState(pos.relative(enumdirection)); + +- if (blockstate2.is(this.plant)) { ++ if (iblockdata2.is(this.plant)) { + if (flag) { + return false; + } + + flag = true; +- } else if (!blockstate2.isAir()) { ++ } else if (!iblockdata2.isAir()) { + return false; + } + } +@@ -211,70 +222,73 @@ + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(ChorusFlowerBlock.AGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(ChorusFlowerBlock.AGE); + } + +- public static void generatePlant(LevelAccessor levelaccessor, BlockPos blockpos, RandomSource randomsource, int i) { +- levelaccessor.setBlock(blockpos, ChorusPlantBlock.getStateWithConnections(levelaccessor, blockpos, Blocks.CHORUS_PLANT.defaultBlockState()), 2); +- growTreeRecursive(levelaccessor, blockpos, randomsource, blockpos, i, 0); ++ public static void generatePlant(LevelAccessor level, BlockPos pos, RandomSource random, int maxHorizontalDistance) { ++ level.setBlock(pos, ChorusPlantBlock.getStateWithConnections(level, pos, Blocks.CHORUS_PLANT.defaultBlockState()), 2); ++ growTreeRecursive(level, pos, random, pos, maxHorizontalDistance, 0); + } + +- private static void growTreeRecursive(LevelAccessor levelaccessor, BlockPos blockpos, RandomSource randomsource, BlockPos blockpos1, int i, int j) { ++ private static void growTreeRecursive(LevelAccessor level, BlockPos branchPos, RandomSource random, BlockPos originalBranchPos, int maxHorizontalDistance, int iterations) { + Block block = Blocks.CHORUS_PLANT; +- int k = randomsource.nextInt(4) + 1; ++ int k = random.nextInt(4) + 1; + +- if (j == 0) { ++ if (iterations == 0) { + ++k; + } + + for (int l = 0; l < k; ++l) { +- BlockPos blockpos2 = blockpos.above(l + 1); ++ BlockPos blockposition2 = branchPos.above(l + 1); + +- if (!allNeighborsEmpty(levelaccessor, blockpos2, (Direction) null)) { ++ if (!allNeighborsEmpty(level, blockposition2, (Direction) null)) { + return; + } + +- levelaccessor.setBlock(blockpos2, ChorusPlantBlock.getStateWithConnections(levelaccessor, blockpos2, block.defaultBlockState()), 2); +- levelaccessor.setBlock(blockpos2.below(), ChorusPlantBlock.getStateWithConnections(levelaccessor, blockpos2.below(), block.defaultBlockState()), 2); ++ level.setBlock(blockposition2, ChorusPlantBlock.getStateWithConnections(level, blockposition2, block.defaultBlockState()), 2); ++ level.setBlock(blockposition2.below(), ChorusPlantBlock.getStateWithConnections(level, blockposition2.below(), block.defaultBlockState()), 2); + } + + boolean flag = false; + +- if (j < 4) { +- int i1 = randomsource.nextInt(4); ++ if (iterations < 4) { ++ int i1 = random.nextInt(4); + +- if (j == 0) { ++ if (iterations == 0) { + ++i1; + } + + for (int j1 = 0; j1 < i1; ++j1) { +- Direction direction = Direction.Plane.HORIZONTAL.getRandomDirection(randomsource); +- BlockPos blockpos3 = blockpos.above(k).relative(direction); ++ Direction enumdirection = Direction.Plane.HORIZONTAL.getRandomDirection(random); ++ BlockPos blockposition3 = branchPos.above(k).relative(enumdirection); + +- if (Math.abs(blockpos3.getX() - blockpos1.getX()) < i && Math.abs(blockpos3.getZ() - blockpos1.getZ()) < i && levelaccessor.isEmptyBlock(blockpos3) && levelaccessor.isEmptyBlock(blockpos3.below()) && allNeighborsEmpty(levelaccessor, blockpos3, direction.getOpposite())) { ++ if (Math.abs(blockposition3.getX() - originalBranchPos.getX()) < maxHorizontalDistance && Math.abs(blockposition3.getZ() - originalBranchPos.getZ()) < maxHorizontalDistance && level.isEmptyBlock(blockposition3) && level.isEmptyBlock(blockposition3.below()) && allNeighborsEmpty(level, blockposition3, enumdirection.getOpposite())) { + flag = true; +- levelaccessor.setBlock(blockpos3, ChorusPlantBlock.getStateWithConnections(levelaccessor, blockpos3, block.defaultBlockState()), 2); +- levelaccessor.setBlock(blockpos3.relative(direction.getOpposite()), ChorusPlantBlock.getStateWithConnections(levelaccessor, blockpos3.relative(direction.getOpposite()), block.defaultBlockState()), 2); +- growTreeRecursive(levelaccessor, blockpos3, randomsource, blockpos1, i, j + 1); ++ level.setBlock(blockposition3, ChorusPlantBlock.getStateWithConnections(level, blockposition3, block.defaultBlockState()), 2); ++ level.setBlock(blockposition3.relative(enumdirection.getOpposite()), ChorusPlantBlock.getStateWithConnections(level, blockposition3.relative(enumdirection.getOpposite()), block.defaultBlockState()), 2); ++ growTreeRecursive(level, blockposition3, random, originalBranchPos, maxHorizontalDistance, iterations + 1); + } + } + } + + if (!flag) { +- levelaccessor.setBlock(blockpos.above(k), (BlockState) Blocks.CHORUS_FLOWER.defaultBlockState().setValue(ChorusFlowerBlock.AGE, 5), 2); ++ level.setBlock(branchPos.above(k), (IBlockData) Blocks.CHORUS_FLOWER.defaultBlockState().setValue(ChorusFlowerBlock.AGE, 5), 2); + } + + } + + @Override +- @Override +- public void onProjectileHit(Level level, BlockState blockstate, BlockHitResult blockhitresult, Projectile projectile) { +- BlockPos blockpos = blockhitresult.getBlockPos(); ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { ++ BlockPos blockposition = hit.getBlockPos(); + +- if (!level.isClientSide && projectile.mayInteract(level, blockpos) && projectile.mayBreak(level)) { +- level.destroyBlock(blockpos, true, projectile); ++ if (!level.isClientSide && projectile.mayInteract(level, blockposition) && projectile.mayBreak(level)) { ++ // CraftBukkit ++ if (!CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, Blocks.AIR.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end ++ level.destroyBlock(blockposition, true, projectile); + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CocoaBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CocoaBlock.java.patch new file mode 100644 index 0000000000..03365b03d7 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CocoaBlock.java.patch @@ -0,0 +1,166 @@ +--- a/net/minecraft/world/level/block/CocoaBlock.java ++++ b/net/minecraft/world/level/block/CocoaBlock.java +@@ -13,13 +13,14 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class CocoaBlock extends HorizontalDirectionalBlock implements BonemealableBlock { + +@@ -41,49 +42,44 @@ + protected static final VoxelShape[] SOUTH_AABB = new VoxelShape[]{Block.box(6.0D, 7.0D, 11.0D, 10.0D, 12.0D, 15.0D), Block.box(5.0D, 5.0D, 9.0D, 11.0D, 12.0D, 15.0D), Block.box(4.0D, 3.0D, 7.0D, 12.0D, 12.0D, 15.0D)}; + + @Override +- @Override + public MapCodec codec() { + return CocoaBlock.CODEC; + } + +- public CocoaBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(CocoaBlock.FACING, Direction.NORTH)).setValue(CocoaBlock.AGE, 0)); ++ public CocoaBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(CocoaBlock.FACING, Direction.NORTH)).setValue(CocoaBlock.AGE, 0)); + } + + @Override +- @Override +- public boolean isRandomlyTicking(BlockState blockstate) { +- return (Integer) blockstate.getValue(CocoaBlock.AGE) < 2; ++ public boolean isRandomlyTicking(IBlockData state) { ++ return (Integer) state.getValue(CocoaBlock.AGE) < 2; + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (serverlevel.random.nextInt(5) == 0) { +- int i = (Integer) blockstate.getValue(CocoaBlock.AGE); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (level.random.nextInt(5) == 0) { ++ int i = (Integer) state.getValue(CocoaBlock.AGE); + + if (i < 2) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(CocoaBlock.AGE, i + 1), 2); ++ CraftEventFactory.handleBlockGrowEvent(level, pos, (IBlockData) state.setValue(CocoaBlock.AGE, i + 1), 2); // CraftBukkkit + } + } + + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- BlockState blockstate1 = levelreader.getBlockState(blockpos.relative((Direction) blockstate.getValue(CocoaBlock.FACING))); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ IBlockData iblockdata1 = level.getBlockState(pos.relative((Direction) state.getValue(CocoaBlock.FACING))); + +- return blockstate1.is(BlockTags.JUNGLE_LOGS); ++ return iblockdata1.is(BlockTags.JUNGLE_LOGS); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- int i = (Integer) blockstate.getValue(CocoaBlock.AGE); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ int i = (Integer) state.getValue(CocoaBlock.AGE); + +- switch ((Direction) blockstate.getValue(CocoaBlock.FACING)) { ++ switch ((Direction) state.getValue(CocoaBlock.FACING)) { + case SOUTH: + return CocoaBlock.SOUTH_AABB[i]; + case NORTH: +@@ -98,21 +94,20 @@ + + @Nullable + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- BlockState blockstate = this.defaultBlockState(); +- Level level = blockplacecontext.getLevel(); +- BlockPos blockpos = blockplacecontext.getClickedPos(); +- Direction[] adirection = blockplacecontext.getNearestLookingDirections(); +- int i = adirection.length; ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ IBlockData iblockdata = this.defaultBlockState(); ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ Direction[] aenumdirection = context.getNearestLookingDirections(); ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; ++ Direction enumdirection = aenumdirection[j]; + +- if (direction.getAxis().isHorizontal()) { +- blockstate = (BlockState) blockstate.setValue(CocoaBlock.FACING, direction); +- if (blockstate.canSurvive(level, blockpos)) { +- return blockstate; ++ if (enumdirection.getAxis().isHorizontal()) { ++ iblockdata = (IBlockData) iblockdata.setValue(CocoaBlock.FACING, enumdirection); ++ if (iblockdata.canSurvive(world, blockposition)) { ++ return iblockdata; + } + } + } +@@ -121,38 +116,32 @@ + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- return direction == blockstate.getValue(CocoaBlock.FACING) && !blockstate.canSurvive(levelaccessor, blockpos) ? Blocks.AIR.defaultBlockState() : super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ return facing == state.getValue(CocoaBlock.FACING) && !state.canSurvive(level, currentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- @Override +- public boolean isValidBonemealTarget(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { +- return (Integer) blockstate.getValue(CocoaBlock.AGE) < 2; ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ return (Integer) iblockdata.getValue(CocoaBlock.AGE) < 2; + } + + @Override +- @Override +- public boolean isBonemealSuccess(Level level, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return true; + } + + @Override +- @Override +- public void performBonemeal(ServerLevel serverlevel, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(CocoaBlock.AGE, (Integer) blockstate.getValue(CocoaBlock.AGE) + 1), 2); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ CraftEventFactory.handleBlockGrowEvent(level, pos, (IBlockData) state.setValue(CocoaBlock.AGE, (Integer) state.getValue(CocoaBlock.AGE) + 1), 2); // CraftBukkit + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(CocoaBlock.FACING, CocoaBlock.AGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(CocoaBlock.FACING, CocoaBlock.AGE); + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CommandBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CommandBlock.java.patch new file mode 100644 index 0000000000..9074b40b42 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CommandBlock.java.patch @@ -0,0 +1,359 @@ +--- a/net/minecraft/world/level/block/CommandBlock.java ++++ b/net/minecraft/world/level/block/CommandBlock.java +@@ -9,7 +9,7 @@ + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.RandomSource; + import net.minecraft.util.StringUtil; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.player.Player; +@@ -22,7 +22,7 @@ + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.CommandBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -30,55 +30,63 @@ + import net.minecraft.world.phys.BlockHitResult; + import org.slf4j.Logger; + ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit ++ + public class CommandBlock extends BaseEntityBlock implements GameMasterBlock { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- return instance.group(Codec.BOOL.fieldOf("automatic").forGetter((commandblock) -> { +- return commandblock.automatic; ++ return instance.group(Codec.BOOL.fieldOf("automatic").forGetter((blockcommand) -> { ++ return blockcommand.automatic; + }), propertiesCodec()).apply(instance, CommandBlock::new); + }); + private static final Logger LOGGER = LogUtils.getLogger(); +- public static final DirectionProperty FACING = DirectionalBlock.FACING; ++ public static final DirectionProperty FACING = BlockDirectional.FACING; + public static final BooleanProperty CONDITIONAL = BlockStateProperties.CONDITIONAL; + private final boolean automatic; + + @Override +- @Override + public MapCodec codec() { + return CommandBlock.CODEC; + } + +- public CommandBlock(boolean flag, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(CommandBlock.FACING, Direction.NORTH)).setValue(CommandBlock.CONDITIONAL, false)); ++ public CommandBlock(boolean flag, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(CommandBlock.FACING, Direction.NORTH)).setValue(CommandBlock.CONDITIONAL, false)); + this.automatic = flag; + } + + @Override +- @Override +- public BlockEntity newBlockEntity(BlockPos blockpos, BlockState blockstate) { +- CommandBlockEntity commandblockentity = new CommandBlockEntity(blockpos, blockstate); ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ CommandBlockEntity tileentitycommand = new CommandBlockEntity(pos, state); + +- commandblockentity.setAutomatic(this.automatic); +- return commandblockentity; ++ tileentitycommand.setAutomatic(this.automatic); ++ return tileentitycommand; + } + + @Override +- @Override +- public void neighborChanged(BlockState blockstate, Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { + if (!level.isClientSide) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof CommandBlockEntity) { +- CommandBlockEntity commandblockentity = (CommandBlockEntity) blockentity; +- boolean flag1 = level.hasNeighborSignal(blockpos); +- boolean flag2 = commandblockentity.isPowered(); ++ if (tileentity instanceof CommandBlockEntity) { ++ CommandBlockEntity tileentitycommand = (CommandBlockEntity) tileentity; ++ boolean flag1 = level.hasNeighborSignal(pos); ++ boolean flag2 = tileentitycommand.isPowered(); ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ int old = flag2 ? 15 : 0; ++ int current = flag1 ? 15 : 0; + +- commandblockentity.setPowered(flag1); +- if (!flag2 && !commandblockentity.isAutomatic() && commandblockentity.getMode() != CommandBlockEntity.Mode.SEQUENCE) { ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bukkitBlock, old, current); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ flag1 = eventRedstone.getNewCurrent() > 0; ++ // CraftBukkit end ++ ++ tileentitycommand.setPowered(flag1); ++ if (!flag2 && !tileentitycommand.isAutomatic() && tileentitycommand.getMode() != CommandBlockEntity.Type.SEQUENCE) { + if (flag1) { +- commandblockentity.markConditionMet(); +- level.scheduleTick(blockpos, (Block) this, 1); ++ tileentitycommand.markConditionMet(); ++ level.scheduleTick(pos, (Block) this, 1); + } + + } +@@ -87,58 +95,56 @@ + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- BlockEntity blockentity = serverlevel.getBlockEntity(blockpos); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof CommandBlockEntity) { +- CommandBlockEntity commandblockentity = (CommandBlockEntity) blockentity; +- BaseCommandBlock basecommandblock = commandblockentity.getCommandBlock(); +- boolean flag = !StringUtil.isNullOrEmpty(basecommandblock.getCommand()); +- CommandBlockEntity.Mode commandblockentity_mode = commandblockentity.getMode(); +- boolean flag1 = commandblockentity.wasConditionMet(); ++ if (tileentity instanceof CommandBlockEntity) { ++ CommandBlockEntity tileentitycommand = (CommandBlockEntity) tileentity; ++ BaseCommandBlock commandblocklistenerabstract = tileentitycommand.getCommandBlock(); ++ boolean flag = !StringUtil.isNullOrEmpty(commandblocklistenerabstract.getCommand()); ++ CommandBlockEntity.Type tileentitycommand_type = tileentitycommand.getMode(); ++ boolean flag1 = tileentitycommand.wasConditionMet(); + +- if (commandblockentity_mode == CommandBlockEntity.Mode.AUTO) { +- commandblockentity.markConditionMet(); ++ if (tileentitycommand_type == CommandBlockEntity.Type.AUTO) { ++ tileentitycommand.markConditionMet(); + if (flag1) { +- this.execute(blockstate, serverlevel, blockpos, basecommandblock, flag); +- } else if (commandblockentity.isConditional()) { +- basecommandblock.setSuccessCount(0); ++ this.execute(state, level, pos, commandblocklistenerabstract, flag); ++ } else if (tileentitycommand.isConditional()) { ++ commandblocklistenerabstract.setSuccessCount(0); + } + +- if (commandblockentity.isPowered() || commandblockentity.isAutomatic()) { +- serverlevel.scheduleTick(blockpos, (Block) this, 1); ++ if (tileentitycommand.isPowered() || tileentitycommand.isAutomatic()) { ++ level.scheduleTick(pos, (Block) this, 1); + } +- } else if (commandblockentity_mode == CommandBlockEntity.Mode.REDSTONE) { ++ } else if (tileentitycommand_type == CommandBlockEntity.Type.REDSTONE) { + if (flag1) { +- this.execute(blockstate, serverlevel, blockpos, basecommandblock, flag); +- } else if (commandblockentity.isConditional()) { +- basecommandblock.setSuccessCount(0); ++ this.execute(state, level, pos, commandblocklistenerabstract, flag); ++ } else if (tileentitycommand.isConditional()) { ++ commandblocklistenerabstract.setSuccessCount(0); + } + } + +- serverlevel.updateNeighbourForOutputSignal(blockpos, this); ++ level.updateNeighbourForOutputSignal(pos, this); + } + + } + +- private void execute(BlockState blockstate, Level level, BlockPos blockpos, BaseCommandBlock basecommandblock, boolean flag) { +- if (flag) { +- basecommandblock.performCommand(level); ++ private void execute(IBlockData state, Level level, BlockPos pos, BaseCommandBlock logic, boolean canTrigger) { ++ if (canTrigger) { ++ logic.performCommand(level); + } else { +- basecommandblock.setSuccessCount(0); ++ logic.setSuccessCount(0); + } + +- executeChain(level, blockpos, (Direction) blockstate.getValue(CommandBlock.FACING)); ++ executeChain(level, pos, (Direction) state.getValue(CommandBlock.FACING)); + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof CommandBlockEntity && player.canUseGameMasterBlocks()) { +- player.openCommandBlock((CommandBlockEntity) blockentity); ++ if (tileentity instanceof CommandBlockEntity && player.canUseGameMasterBlocks()) { ++ player.openCommandBlock((CommandBlockEntity) tileentity); + return InteractionResult.sidedSuccess(level.isClientSide); + } else { + return InteractionResult.PASS; +@@ -146,42 +152,39 @@ + } + + @Override +- @Override +- public boolean hasAnalogOutputSignal(BlockState blockstate) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return true; + } + + @Override +- @Override +- public int getAnalogOutputSignal(BlockState blockstate, Level level, BlockPos blockpos) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ public int getAnalogOutputSignal(IBlockData blockState, Level level, BlockPos pos) { ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- return blockentity instanceof CommandBlockEntity ? ((CommandBlockEntity) blockentity).getCommandBlock().getSuccessCount() : 0; ++ return tileentity instanceof CommandBlockEntity ? ((CommandBlockEntity) tileentity).getCommandBlock().getSuccessCount() : 0; + } + + @Override +- @Override +- public void setPlacedBy(Level level, BlockPos blockpos, BlockState blockstate, LivingEntity livingentity, ItemStack itemstack) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, LivingEntity placer, ItemStack stack) { ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof CommandBlockEntity) { +- CommandBlockEntity commandblockentity = (CommandBlockEntity) blockentity; +- BaseCommandBlock basecommandblock = commandblockentity.getCommandBlock(); ++ if (tileentity instanceof CommandBlockEntity) { ++ CommandBlockEntity tileentitycommand = (CommandBlockEntity) tileentity; ++ BaseCommandBlock commandblocklistenerabstract = tileentitycommand.getCommandBlock(); + +- if (itemstack.hasCustomHoverName()) { +- basecommandblock.setName(itemstack.getHoverName()); ++ if (stack.hasCustomHoverName()) { ++ commandblocklistenerabstract.setName(stack.getHoverName()); + } + + if (!level.isClientSide) { +- if (BlockItem.getBlockEntityData(itemstack) == null) { +- basecommandblock.setTrackOutput(level.getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK)); +- commandblockentity.setAutomatic(this.automatic); ++ if (BlockItem.getBlockEntityData(stack) == null) { ++ commandblocklistenerabstract.setTrackOutput(level.getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK)); ++ tileentitycommand.setAutomatic(this.automatic); + } + +- if (commandblockentity.getMode() == CommandBlockEntity.Mode.SEQUENCE) { +- boolean flag = level.hasNeighborSignal(blockpos); ++ if (tileentitycommand.getMode() == CommandBlockEntity.Type.SEQUENCE) { ++ boolean flag = level.hasNeighborSignal(pos); + +- commandblockentity.setPowered(flag); ++ tileentitycommand.setPowered(flag); + } + } + +@@ -189,74 +192,69 @@ + } + + @Override +- @Override +- public RenderShape getRenderShape(BlockState blockstate) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Override +- @Override +- public BlockState rotate(BlockState blockstate, Rotation rotation) { +- return (BlockState) blockstate.setValue(CommandBlock.FACING, rotation.rotate((Direction) blockstate.getValue(CommandBlock.FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return (IBlockData) state.setValue(CommandBlock.FACING, rotation.rotate((Direction) state.getValue(CommandBlock.FACING))); + } + + @Override +- @Override +- public BlockState mirror(BlockState blockstate, Mirror mirror) { +- return blockstate.rotate(mirror.getRotation((Direction) blockstate.getValue(CommandBlock.FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(CommandBlock.FACING))); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(CommandBlock.FACING, CommandBlock.CONDITIONAL); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(CommandBlock.FACING, CommandBlock.CONDITIONAL); + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- return (BlockState) this.defaultBlockState().setValue(CommandBlock.FACING, blockplacecontext.getNearestLookingDirection().getOpposite()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return (IBlockData) this.defaultBlockState().setValue(CommandBlock.FACING, context.getNearestLookingDirection().getOpposite()); + } + +- private static void executeChain(Level level, BlockPos blockpos, Direction direction) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = blockpos.mutable(); ++ private static void executeChain(Level level, BlockPos pos, Direction direction) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); + GameRules gamerules = level.getGameRules(); + +- BlockState blockstate; ++ IBlockData iblockdata; + int i; + +- for (i = gamerules.getInt(GameRules.RULE_MAX_COMMAND_CHAIN_LENGTH); i-- > 0; direction = (Direction) blockstate.getValue(CommandBlock.FACING)) { +- blockpos_mutableblockpos.move(direction); +- blockstate = level.getBlockState(blockpos_mutableblockpos); +- Block block = blockstate.getBlock(); ++ for (i = gamerules.getInt(GameRules.RULE_MAX_COMMAND_CHAIN_LENGTH); i-- > 0; direction = (Direction) iblockdata.getValue(CommandBlock.FACING)) { ++ blockposition_mutableblockposition.move(direction); ++ iblockdata = level.getBlockState(blockposition_mutableblockposition); ++ Block block = iblockdata.getBlock(); + +- if (!blockstate.is(Blocks.CHAIN_COMMAND_BLOCK)) { ++ if (!iblockdata.is(Blocks.CHAIN_COMMAND_BLOCK)) { + break; + } + +- BlockEntity blockentity = level.getBlockEntity(blockpos_mutableblockpos); ++ BlockEntity tileentity = level.getBlockEntity(blockposition_mutableblockposition); + +- if (!(blockentity instanceof CommandBlockEntity)) { ++ if (!(tileentity instanceof CommandBlockEntity)) { + break; + } + +- CommandBlockEntity commandblockentity = (CommandBlockEntity) blockentity; ++ CommandBlockEntity tileentitycommand = (CommandBlockEntity) tileentity; + +- if (commandblockentity.getMode() != CommandBlockEntity.Mode.SEQUENCE) { ++ if (tileentitycommand.getMode() != CommandBlockEntity.Type.SEQUENCE) { + break; + } + +- if (commandblockentity.isPowered() || commandblockentity.isAutomatic()) { +- BaseCommandBlock basecommandblock = commandblockentity.getCommandBlock(); ++ if (tileentitycommand.isPowered() || tileentitycommand.isAutomatic()) { ++ BaseCommandBlock commandblocklistenerabstract = tileentitycommand.getCommandBlock(); + +- if (commandblockentity.markConditionMet()) { +- if (!basecommandblock.performCommand(level)) { ++ if (tileentitycommand.markConditionMet()) { ++ if (!commandblocklistenerabstract.performCommand(level)) { + break; + } + +- level.updateNeighbourForOutputSignal(blockpos_mutableblockpos, block); +- } else if (commandblockentity.isConditional()) { +- basecommandblock.setSuccessCount(0); ++ level.updateNeighbourForOutputSignal(blockposition_mutableblockposition, block); ++ } else if (tileentitycommand.isConditional()) { ++ commandblocklistenerabstract.setSuccessCount(0); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ComparatorBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ComparatorBlock.java.patch new file mode 100644 index 0000000000..80dfa7faa8 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ComparatorBlock.java.patch @@ -0,0 +1,285 @@ +--- a/net/minecraft/world/level/block/ComparatorBlock.java ++++ b/net/minecraft/world/level/block/ComparatorBlock.java +@@ -9,7 +9,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.decoration.ItemFrame; + import net.minecraft.world.entity.player.Player; +@@ -19,7 +19,7 @@ + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.ComparatorBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.ComparatorMode; +@@ -27,6 +27,7 @@ + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.ticks.TickPriority; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class ComparatorBlock extends DiodeBlock implements EntityBlock { + +@@ -34,77 +35,71 @@ + public static final EnumProperty MODE = BlockStateProperties.MODE_COMPARATOR; + + @Override +- @Override + public MapCodec codec() { + return ComparatorBlock.CODEC; + } + +- public ComparatorBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(ComparatorBlock.FACING, Direction.NORTH)).setValue(ComparatorBlock.POWERED, false)).setValue(ComparatorBlock.MODE, ComparatorMode.COMPARE)); ++ public ComparatorBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(ComparatorBlock.FACING, Direction.NORTH)).setValue(ComparatorBlock.POWERED, false)).setValue(ComparatorBlock.MODE, ComparatorMode.COMPARE)); + } + + @Override +- @Override +- protected int getDelay(BlockState blockstate) { ++ protected int getDelay(IBlockData state) { + return 2; + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- return direction == Direction.DOWN && !this.canSurviveOn(levelaccessor, blockpos1, blockstate1) ? Blocks.AIR.defaultBlockState() : super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ public IBlockData updateShape(IBlockData state, Direction direction, IBlockData neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { ++ return direction == Direction.DOWN && !this.canSurviveOn(level, neighborPos, neighborState) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, direction, neighborState, level, pos, neighborPos); + } + + @Override +- @Override +- protected int getOutputSignal(BlockGetter blockgetter, BlockPos blockpos, BlockState blockstate) { +- BlockEntity blockentity = blockgetter.getBlockEntity(blockpos); ++ protected int getOutputSignal(BlockGetter level, BlockPos pos, IBlockData state) { ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- return blockentity instanceof ComparatorBlockEntity ? ((ComparatorBlockEntity) blockentity).getOutputSignal() : 0; ++ return tileentity instanceof ComparatorBlockEntity ? ((ComparatorBlockEntity) tileentity).getOutputSignal() : 0; + } + +- private int calculateOutputSignal(Level level, BlockPos blockpos, BlockState blockstate) { +- int i = this.getInputSignal(level, blockpos, blockstate); ++ private int calculateOutputSignal(Level level, BlockPos pos, IBlockData state) { ++ int i = this.getInputSignal(level, pos, state); + + if (i == 0) { + return 0; + } else { +- int j = this.getAlternateSignal(level, blockpos, blockstate); ++ int j = this.getAlternateSignal(level, pos, state); + +- return j > i ? 0 : (blockstate.getValue(ComparatorBlock.MODE) == ComparatorMode.SUBTRACT ? i - j : i); ++ return j > i ? 0 : (state.getValue(ComparatorBlock.MODE) == ComparatorMode.SUBTRACT ? i - j : i); + } + } + + @Override +- @Override +- protected boolean shouldTurnOn(Level level, BlockPos blockpos, BlockState blockstate) { +- int i = this.getInputSignal(level, blockpos, blockstate); ++ protected boolean shouldTurnOn(Level level, BlockPos pos, IBlockData state) { ++ int i = this.getInputSignal(level, pos, state); + + if (i == 0) { + return false; + } else { +- int j = this.getAlternateSignal(level, blockpos, blockstate); ++ int j = this.getAlternateSignal(level, pos, state); + +- return i > j ? true : i == j && blockstate.getValue(ComparatorBlock.MODE) == ComparatorMode.COMPARE; ++ return i > j ? true : i == j && state.getValue(ComparatorBlock.MODE) == ComparatorMode.COMPARE; + } + } + + @Override +- @Override +- protected int getInputSignal(Level level, BlockPos blockpos, BlockState blockstate) { +- int i = super.getInputSignal(level, blockpos, blockstate); +- Direction direction = (Direction) blockstate.getValue(ComparatorBlock.FACING); +- BlockPos blockpos1 = blockpos.relative(direction); +- BlockState blockstate1 = level.getBlockState(blockpos1); ++ protected int getInputSignal(Level level, BlockPos pos, IBlockData state) { ++ int i = super.getInputSignal(level, pos, state); ++ Direction enumdirection = (Direction) state.getValue(ComparatorBlock.FACING); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + +- if (blockstate1.hasAnalogOutputSignal()) { +- i = blockstate1.getAnalogOutputSignal(level, blockpos1); +- } else if (i < 15 && blockstate1.isRedstoneConductor(level, blockpos1)) { +- blockpos1 = blockpos1.relative(direction); +- blockstate1 = level.getBlockState(blockpos1); +- ItemFrame itemframe = this.getItemFrame(level, direction, blockpos1); +- int j = Math.max(itemframe == null ? Integer.MIN_VALUE : itemframe.getAnalogOutput(), blockstate1.hasAnalogOutputSignal() ? blockstate1.getAnalogOutputSignal(level, blockpos1) : Integer.MIN_VALUE); ++ if (iblockdata1.hasAnalogOutputSignal()) { ++ i = iblockdata1.getAnalogOutputSignal(level, blockposition1); ++ } else if (i < 15 && iblockdata1.isRedstoneConductor(level, blockposition1)) { ++ blockposition1 = blockposition1.relative(enumdirection); ++ iblockdata1 = level.getBlockState(blockposition1); ++ ItemFrame entityitemframe = this.getItemFrame(level, enumdirection, blockposition1); ++ int j = Math.max(entityitemframe == null ? Integer.MIN_VALUE : entityitemframe.getAnalogOutput(), iblockdata1.hasAnalogOutputSignal() ? iblockdata1.getAnalogOutputSignal(level, blockposition1) : Integer.MIN_VALUE); + + if (j != Integer.MIN_VALUE) { + i = j; +@@ -115,98 +110,103 @@ + } + + @Nullable +- private ItemFrame getItemFrame(Level level, Direction direction, BlockPos blockpos) { +- List list = level.getEntitiesOfClass(ItemFrame.class, new AABB((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), (double) (blockpos.getX() + 1), (double) (blockpos.getY() + 1), (double) (blockpos.getZ() + 1)), (itemframe) -> { +- return itemframe != null && itemframe.getDirection() == direction; ++ private ItemFrame getItemFrame(Level level, Direction facing, BlockPos pos) { ++ // CraftBukkit - decompile error ++ List list = level.getEntitiesOfClass(ItemFrame.class, new AABB((double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), (double) (pos.getX() + 1), (double) (pos.getY() + 1), (double) (pos.getZ() + 1)), (java.util.function.Predicate) (entityitemframe) -> { ++ return entityitemframe != null && entityitemframe.getDirection() == facing; + }); + + return list.size() == 1 ? (ItemFrame) list.get(0) : null; + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + if (!player.getAbilities().mayBuild) { + return InteractionResult.PASS; + } else { +- blockstate = (BlockState) blockstate.cycle(ComparatorBlock.MODE); +- float f = blockstate.getValue(ComparatorBlock.MODE) == ComparatorMode.SUBTRACT ? 0.55F : 0.5F; ++ state = (IBlockData) state.cycle(ComparatorBlock.MODE); ++ float f = state.getValue(ComparatorBlock.MODE) == ComparatorMode.SUBTRACT ? 0.55F : 0.5F; + +- level.playSound(player, blockpos, SoundEvents.COMPARATOR_CLICK, SoundSource.BLOCKS, 0.3F, f); +- level.setBlock(blockpos, blockstate, 2); +- this.refreshOutputState(level, blockpos, blockstate); ++ level.playSound(player, pos, SoundEvents.COMPARATOR_CLICK, SoundSource.BLOCKS, 0.3F, f); ++ level.setBlock(pos, state, 2); ++ this.refreshOutputState(level, pos, state); + return InteractionResult.sidedSuccess(level.isClientSide); + } + } + + @Override +- @Override +- protected void checkTickOnNeighbor(Level level, BlockPos blockpos, BlockState blockstate) { +- if (!level.getBlockTicks().willTickThisTick(blockpos, this)) { +- int i = this.calculateOutputSignal(level, blockpos, blockstate); +- BlockEntity blockentity = level.getBlockEntity(blockpos); +- int j = blockentity instanceof ComparatorBlockEntity ? ((ComparatorBlockEntity) blockentity).getOutputSignal() : 0; ++ protected void checkTickOnNeighbor(Level level, BlockPos pos, IBlockData state) { ++ if (!level.getBlockTicks().willTickThisTick(pos, this)) { ++ int i = this.calculateOutputSignal(level, pos, state); ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ int j = tileentity instanceof ComparatorBlockEntity ? ((ComparatorBlockEntity) tileentity).getOutputSignal() : 0; + +- if (i != j || (Boolean) blockstate.getValue(ComparatorBlock.POWERED) != this.shouldTurnOn(level, blockpos, blockstate)) { +- TickPriority tickpriority = this.shouldPrioritize(level, blockpos, blockstate) ? TickPriority.HIGH : TickPriority.NORMAL; ++ if (i != j || (Boolean) state.getValue(ComparatorBlock.POWERED) != this.shouldTurnOn(level, pos, state)) { ++ TickPriority ticklistpriority = this.shouldPrioritize(level, pos, state) ? TickPriority.HIGH : TickPriority.NORMAL; + +- level.scheduleTick(blockpos, (Block) this, 2, tickpriority); ++ level.scheduleTick(pos, (Block) this, 2, ticklistpriority); + } + + } + } + +- private void refreshOutputState(Level level, BlockPos blockpos, BlockState blockstate) { +- int i = this.calculateOutputSignal(level, blockpos, blockstate); +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ private void refreshOutputState(Level level, BlockPos pos, IBlockData state) { ++ int i = this.calculateOutputSignal(level, pos, state); ++ BlockEntity tileentity = level.getBlockEntity(pos); + int j = 0; + +- if (blockentity instanceof ComparatorBlockEntity) { +- ComparatorBlockEntity comparatorblockentity = (ComparatorBlockEntity) blockentity; ++ if (tileentity instanceof ComparatorBlockEntity) { ++ ComparatorBlockEntity tileentitycomparator = (ComparatorBlockEntity) tileentity; + +- j = comparatorblockentity.getOutputSignal(); +- comparatorblockentity.setOutputSignal(i); ++ j = tileentitycomparator.getOutputSignal(); ++ tileentitycomparator.setOutputSignal(i); + } + +- if (j != i || blockstate.getValue(ComparatorBlock.MODE) == ComparatorMode.COMPARE) { +- boolean flag = this.shouldTurnOn(level, blockpos, blockstate); +- boolean flag1 = (Boolean) blockstate.getValue(ComparatorBlock.POWERED); ++ if (j != i || state.getValue(ComparatorBlock.MODE) == ComparatorMode.COMPARE) { ++ boolean flag = this.shouldTurnOn(level, pos, state); ++ boolean flag1 = (Boolean) state.getValue(ComparatorBlock.POWERED); + + if (flag1 && !flag) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(ComparatorBlock.POWERED, false), 2); ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 15, 0).getNewCurrent() != 0) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(ComparatorBlock.POWERED, false), 2); + } else if (!flag1 && flag) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(ComparatorBlock.POWERED, true), 2); ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 0, 15).getNewCurrent() != 15) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(ComparatorBlock.POWERED, true), 2); + } + +- this.updateNeighborsInFront(level, blockpos, blockstate); ++ this.updateNeighborsInFront(level, pos, state); + } + + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- this.refreshOutputState(serverlevel, blockpos, blockstate); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ this.refreshOutputState(level, pos, state); + } + + @Override +- @Override +- public boolean triggerEvent(BlockState blockstate, Level level, BlockPos blockpos, int i, int j) { +- super.triggerEvent(blockstate, level, blockpos, i, j); +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ public boolean triggerEvent(IBlockData state, Level level, BlockPos pos, int id, int param) { ++ super.triggerEvent(state, level, pos, id, param); ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- return blockentity != null && blockentity.triggerEvent(i, j); ++ return tileentity != null && tileentity.triggerEvent(id, param); + } + + @Override +- @Override +- public BlockEntity newBlockEntity(BlockPos blockpos, BlockState blockstate) { +- return new ComparatorBlockEntity(blockpos, blockstate); ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ return new ComparatorBlockEntity(pos, state); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(ComparatorBlock.FACING, ComparatorBlock.MODE, ComparatorBlock.POWERED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(ComparatorBlock.FACING, ComparatorBlock.MODE, ComparatorBlock.POWERED); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ComposterBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ComposterBlock.java.patch new file mode 100644 index 0000000000..a2cf07f89a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ComposterBlock.java.patch @@ -0,0 +1,489 @@ +--- a/net/minecraft/world/level/block/ComposterBlock.java ++++ b/net/minecraft/world/level/block/ComposterBlock.java +@@ -13,7 +13,7 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.WorldlyContainer; +@@ -24,22 +24,26 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.BlockGetter; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.level.gameevent.GameEvent; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftBlockInventoryHolder; ++import org.bukkit.craftbukkit.util.DummyGeneratorAccess; ++// CraftBukkit end + + public class ComposterBlock extends Block implements WorldlyContainerHolder { + +@@ -48,7 +52,7 @@ + public static final int MIN_LEVEL = 0; + public static final int MAX_LEVEL = 7; + public static final IntegerProperty LEVEL = BlockStateProperties.LEVEL_COMPOSTER; +- public static final Object2FloatMap COMPOSTABLES = new Object2FloatOpenHashMap(); ++ public static final Object2FloatMap COMPOSTABLES = new Object2FloatOpenHashMap(); + private static final int AABB_SIDE_THICKNESS = 2; + private static final VoxelShape OUTER_SHAPE = Shapes.block(); + private static final VoxelShape[] SHAPES = (VoxelShape[]) Util.make(new VoxelShape[9], (avoxelshape) -> { +@@ -60,7 +64,6 @@ + }); + + @Override +- @Override + public MapCodec codec() { + return ComposterBlock.CODEC; + } +@@ -176,20 +179,20 @@ + add(1.0F, Items.PUMPKIN_PIE); + } + +- private static void add(float f, ItemLike itemlike) { +- ComposterBlock.COMPOSTABLES.put(itemlike.asItem(), f); ++ private static void add(float chance, IMaterial item) { ++ ComposterBlock.COMPOSTABLES.put(item.asItem(), chance); + } + +- public ComposterBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(ComposterBlock.LEVEL, 0)); ++ public ComposterBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(ComposterBlock.LEVEL, 0)); + } + +- public static void handleFill(Level level, BlockPos blockpos, boolean flag) { +- BlockState blockstate = level.getBlockState(blockpos); ++ public static void handleFill(Level level, BlockPos pos, boolean success) { ++ IBlockData iblockdata = level.getBlockState(pos); + +- level.playLocalSound(blockpos, flag ? SoundEvents.COMPOSTER_FILL_SUCCESS : SoundEvents.COMPOSTER_FILL, SoundSource.BLOCKS, 1.0F, 1.0F, false); +- double d0 = blockstate.getShape(level, blockpos).max(Direction.Axis.Y, 0.5D, 0.5D) + 0.03125D; ++ level.playLocalSound(pos, success ? SoundEvents.COMPOSTER_FILL_SUCCESS : SoundEvents.COMPOSTER_FILL, SoundSource.BLOCKS, 1.0F, 1.0F, false); ++ double d0 = iblockdata.getShape(level, pos).max(Direction.Axis.Y, 0.5D, 0.5D) + 0.03125D; + double d1 = 0.13124999403953552D; + double d2 = 0.737500011920929D; + RandomSource randomsource = level.getRandom(); +@@ -199,49 +202,44 @@ + double d4 = randomsource.nextGaussian() * 0.02D; + double d5 = randomsource.nextGaussian() * 0.02D; + +- level.addParticle(ParticleTypes.COMPOSTER, (double) blockpos.getX() + 0.13124999403953552D + 0.737500011920929D * (double) randomsource.nextFloat(), (double) blockpos.getY() + d0 + (double) randomsource.nextFloat() * (1.0D - d0), (double) blockpos.getZ() + 0.13124999403953552D + 0.737500011920929D * (double) randomsource.nextFloat(), d3, d4, d5); ++ level.addParticle(ParticleTypes.COMPOSTER, (double) pos.getX() + 0.13124999403953552D + 0.737500011920929D * (double) randomsource.nextFloat(), (double) pos.getY() + d0 + (double) randomsource.nextFloat() * (1.0D - d0), (double) pos.getZ() + 0.13124999403953552D + 0.737500011920929D * (double) randomsource.nextFloat(), d3, d4, d5); + } + + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return ComposterBlock.SHAPES[(Integer) blockstate.getValue(ComposterBlock.LEVEL)]; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return ComposterBlock.SHAPES[(Integer) state.getValue(ComposterBlock.LEVEL)]; + } + + @Override +- @Override +- public VoxelShape getInteractionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { ++ public VoxelShape getInteractionShape(IBlockData state, BlockGetter level, BlockPos pos) { + return ComposterBlock.OUTER_SHAPE; + } + + @Override +- @Override +- public VoxelShape getCollisionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return ComposterBlock.SHAPES[0]; + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if ((Integer) blockstate.getValue(ComposterBlock.LEVEL) == 7) { +- level.scheduleTick(blockpos, blockstate.getBlock(), 20); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ if ((Integer) state.getValue(ComposterBlock.LEVEL) == 7) { ++ level.scheduleTick(pos, state.getBlock(), 20); + } + + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- int i = (Integer) blockstate.getValue(ComposterBlock.LEVEL); +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ int i = (Integer) state.getValue(ComposterBlock.LEVEL); ++ ItemStack itemstack = player.getItemInHand(hand); + + if (i < 8 && ComposterBlock.COMPOSTABLES.containsKey(itemstack.getItem())) { + if (i < 7 && !level.isClientSide) { +- BlockState blockstate1 = addItem(player, blockstate, level, blockpos, itemstack); ++ IBlockData iblockdata1 = addItem(player, state, level, pos, itemstack); + +- level.levelEvent(1500, blockpos, blockstate != blockstate1 ? 1 : 0); ++ level.levelEvent(1500, pos, state != iblockdata1 ? 1 : 0); + player.awardStat(Stats.ITEM_USED.get(itemstack.getItem())); + if (!player.getAbilities().instabuild) { + itemstack.shrink(1); +@@ -250,232 +248,245 @@ + + return InteractionResult.sidedSuccess(level.isClientSide); + } else if (i == 8) { +- extractProduce(player, blockstate, level, blockpos); ++ extractProduce(player, state, level, pos); + return InteractionResult.sidedSuccess(level.isClientSide); + } else { + return InteractionResult.PASS; + } + } + +- public static BlockState insertItem(Entity entity, BlockState blockstate, ServerLevel serverlevel, ItemStack itemstack, BlockPos blockpos) { +- int i = (Integer) blockstate.getValue(ComposterBlock.LEVEL); ++ public static IBlockData insertItem(Entity entity, IBlockData state, ServerLevel level, ItemStack stack, BlockPos pos) { ++ int i = (Integer) state.getValue(ComposterBlock.LEVEL); + +- if (i < 7 && ComposterBlock.COMPOSTABLES.containsKey(itemstack.getItem())) { +- BlockState blockstate1 = addItem(entity, blockstate, serverlevel, blockpos, itemstack); ++ if (i < 7 && ComposterBlock.COMPOSTABLES.containsKey(stack.getItem())) { ++ // CraftBukkit start ++ double rand = level.getRandom().nextDouble(); ++ IBlockData iblockdata1 = addItem(entity, state, DummyGeneratorAccess.INSTANCE, pos, stack, rand); ++ if (state == iblockdata1 || !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, iblockdata1)) { ++ return state; ++ } ++ iblockdata1 = addItem(entity, state, level, pos, stack, rand); ++ // CraftBukkit end + +- itemstack.shrink(1); +- return blockstate1; ++ stack.shrink(1); ++ return iblockdata1; + } else { +- return blockstate; ++ return state; + } + } + +- public static BlockState extractProduce(Entity entity, BlockState blockstate, Level level, BlockPos blockpos) { ++ public static IBlockData extractProduce(Entity entity, IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ if (entity != null && !(entity instanceof Player)) { ++ IBlockData iblockdata1 = empty(entity, state, DummyGeneratorAccess.INSTANCE, pos); ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, iblockdata1)) { ++ return state; ++ } ++ } ++ // CraftBukkit end + if (!level.isClientSide) { +- Vec3 vec3 = Vec3.atLowerCornerWithOffset(blockpos, 0.5D, 1.01D, 0.5D).offsetRandom(level.random, 0.7F); +- ItemEntity itementity = new ItemEntity(level, vec3.x(), vec3.y(), vec3.z(), new ItemStack(Items.BONE_MEAL)); ++ Vec3 vec3d = Vec3.atLowerCornerWithOffset(pos, 0.5D, 1.01D, 0.5D).offsetRandom(level.random, 0.7F); ++ ItemEntity entityitem = new ItemEntity(level, vec3d.x(), vec3d.y(), vec3d.z(), new ItemStack(Items.BONE_MEAL)); + +- itementity.setDefaultPickUpDelay(); +- level.addFreshEntity(itementity); ++ entityitem.setDefaultPickUpDelay(); ++ level.addFreshEntity(entityitem); + } + +- BlockState blockstate1 = empty(entity, blockstate, level, blockpos); ++ IBlockData iblockdata1 = empty(entity, state, level, pos); + +- level.playSound((Player) null, blockpos, SoundEvents.COMPOSTER_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); +- return blockstate1; ++ level.playSound((Player) null, pos, SoundEvents.COMPOSTER_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); ++ return iblockdata1; + } + +- static BlockState empty(@Nullable Entity entity, BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos) { +- BlockState blockstate1 = (BlockState) blockstate.setValue(ComposterBlock.LEVEL, 0); ++ static IBlockData empty(@Nullable Entity entity, IBlockData state, LevelAccessor level, BlockPos pos) { ++ IBlockData iblockdata1 = (IBlockData) state.setValue(ComposterBlock.LEVEL, 0); + +- levelaccessor.setBlock(blockpos, blockstate1, 3); +- levelaccessor.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(entity, blockstate1)); +- return blockstate1; ++ level.setBlock(pos, iblockdata1, 3); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, iblockdata1)); ++ return iblockdata1; + } + +- static BlockState addItem(@Nullable Entity entity, BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos, ItemStack itemstack) { +- int i = (Integer) blockstate.getValue(ComposterBlock.LEVEL); ++ static IBlockData addItem(@Nullable Entity entity, IBlockData state, LevelAccessor level, BlockPos pos, ItemStack stack) { ++ // CraftBukkit start ++ return addItem(entity, state, level, pos, stack, level.getRandom().nextDouble()); ++ } ++ ++ static IBlockData addItem(@Nullable Entity entity, IBlockData iblockdata, LevelAccessor generatoraccess, BlockPos blockposition, ItemStack itemstack, double rand) { ++ // CraftBukkit end ++ int i = (Integer) iblockdata.getValue(ComposterBlock.LEVEL); + float f = ComposterBlock.COMPOSTABLES.getFloat(itemstack.getItem()); + +- if ((i != 0 || f <= 0.0F) && levelaccessor.getRandom().nextDouble() >= (double) f) { +- return blockstate; ++ if ((i != 0 || f <= 0.0F) && rand >= (double) f) { ++ return iblockdata; + } else { + int j = i + 1; +- BlockState blockstate1 = (BlockState) blockstate.setValue(ComposterBlock.LEVEL, j); ++ IBlockData iblockdata1 = (IBlockData) iblockdata.setValue(ComposterBlock.LEVEL, j); + +- levelaccessor.setBlock(blockpos, blockstate1, 3); +- levelaccessor.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(entity, blockstate1)); ++ generatoraccess.setBlock(blockposition, iblockdata1, 3); ++ generatoraccess.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entity, iblockdata1)); + if (j == 7) { +- levelaccessor.scheduleTick(blockpos, blockstate.getBlock(), 20); ++ generatoraccess.scheduleTick(blockposition, iblockdata.getBlock(), 20); + } + +- return blockstate1; ++ return iblockdata1; + } + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if ((Integer) blockstate.getValue(ComposterBlock.LEVEL) == 7) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.cycle(ComposterBlock.LEVEL), 3); +- serverlevel.playSound((Player) null, blockpos, SoundEvents.COMPOSTER_READY, SoundSource.BLOCKS, 1.0F, 1.0F); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Integer) state.getValue(ComposterBlock.LEVEL) == 7) { ++ level.setBlock(pos, (IBlockData) state.cycle(ComposterBlock.LEVEL), 3); ++ level.playSound((Player) null, pos, SoundEvents.COMPOSTER_READY, SoundSource.BLOCKS, 1.0F, 1.0F); + } + + } + + @Override +- @Override +- public boolean hasAnalogOutputSignal(BlockState blockstate) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return true; + } + + @Override +- @Override +- public int getAnalogOutputSignal(BlockState blockstate, Level level, BlockPos blockpos) { +- return (Integer) blockstate.getValue(ComposterBlock.LEVEL); ++ public int getAnalogOutputSignal(IBlockData blockState, Level level, BlockPos pos) { ++ return (Integer) blockState.getValue(ComposterBlock.LEVEL); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(ComposterBlock.LEVEL); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(ComposterBlock.LEVEL); + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + + @Override +- @Override +- public WorldlyContainer getContainer(BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos) { +- int i = (Integer) blockstate.getValue(ComposterBlock.LEVEL); ++ public WorldlyContainer getContainer(IBlockData state, LevelAccessor level, BlockPos pos) { ++ int i = (Integer) state.getValue(ComposterBlock.LEVEL); + +- return (WorldlyContainer) (i == 8 ? new ComposterBlock.OutputContainer(blockstate, levelaccessor, blockpos, new ItemStack(Items.BONE_MEAL)) : (i < 7 ? new ComposterBlock.InputContainer(blockstate, levelaccessor, blockpos) : new ComposterBlock.EmptyContainer())); ++ // CraftBukkit - empty generatoraccess, blockposition ++ return (WorldlyContainer) (i == 8 ? new ComposterBlock.OutputContainer(state, level, pos, new ItemStack(Items.BONE_MEAL)) : (i < 7 ? new ComposterBlock.InputContainer(state, level, pos) : new ComposterBlock.EmptyContainer(level, pos))); + } + +- private static class OutputContainer extends SimpleContainer implements WorldlyContainer { ++ public static class OutputContainer extends SimpleContainer implements WorldlyContainer { + +- private final BlockState state; ++ private final IBlockData state; + private final LevelAccessor level; + private final BlockPos pos; + private boolean changed; + +- public OutputContainer(BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos, ItemStack itemstack) { +- super(itemstack); +- this.state = blockstate; +- this.level = levelaccessor; +- this.pos = blockpos; ++ public OutputContainer(IBlockData state, LevelAccessor level, BlockPos pos, ItemStack stack) { ++ super(stack); ++ this.state = state; ++ this.level = level; ++ this.pos = pos; ++ this.bukkitOwner = new CraftBlockInventoryHolder(level, pos, this); // CraftBukkit + } + + @Override +- @Override + public int getMaxStackSize() { + return 1; + } + + @Override +- @Override +- public int[] getSlotsForFace(Direction direction) { +- return direction == Direction.DOWN ? new int[]{0} : new int[0]; ++ public int[] getSlotsForFace(Direction side) { ++ return side == Direction.DOWN ? new int[]{0} : new int[0]; + } + + @Override +- @Override +- public boolean canPlaceItemThroughFace(int i, ItemStack itemstack, @Nullable Direction direction) { ++ public boolean canPlaceItemThroughFace(int index, ItemStack itemStack, @Nullable Direction direction) { + return false; + } + + @Override +- @Override +- public boolean canTakeItemThroughFace(int i, ItemStack itemstack, Direction direction) { +- return !this.changed && direction == Direction.DOWN && itemstack.is(Items.BONE_MEAL); ++ public boolean canTakeItemThroughFace(int index, ItemStack stack, Direction direction) { ++ return !this.changed && direction == Direction.DOWN && stack.is(Items.BONE_MEAL); + } + + @Override +- @Override + public void setChanged() { ++ // CraftBukkit start - allow putting items back (eg cancelled InventoryMoveItemEvent) ++ if (this.isEmpty()) { + ComposterBlock.empty((Entity) null, this.state, this.level, this.pos); + this.changed = true; ++ } else { ++ this.level.setBlock(this.pos, this.state, 3); ++ this.changed = false; ++ } ++ // CraftBukkit end + } + } + +- private static class InputContainer extends SimpleContainer implements WorldlyContainer { ++ public static class InputContainer extends SimpleContainer implements WorldlyContainer { + +- private final BlockState state; ++ private final IBlockData state; + private final LevelAccessor level; + private final BlockPos pos; + private boolean changed; + +- public InputContainer(BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos) { ++ public InputContainer(IBlockData state, LevelAccessor level, BlockPos pos) { + super(1); +- this.state = blockstate; +- this.level = levelaccessor; +- this.pos = blockpos; ++ this.bukkitOwner = new CraftBlockInventoryHolder(level, pos, this); // CraftBukkit ++ this.state = state; ++ this.level = level; ++ this.pos = pos; + } + + @Override +- @Override + public int getMaxStackSize() { + return 1; + } + + @Override +- @Override +- public int[] getSlotsForFace(Direction direction) { +- return direction == Direction.UP ? new int[]{0} : new int[0]; ++ public int[] getSlotsForFace(Direction side) { ++ return side == Direction.UP ? new int[]{0} : new int[0]; + } + + @Override +- @Override +- public boolean canPlaceItemThroughFace(int i, ItemStack itemstack, @Nullable Direction direction) { +- return !this.changed && direction == Direction.UP && ComposterBlock.COMPOSTABLES.containsKey(itemstack.getItem()); ++ public boolean canPlaceItemThroughFace(int index, ItemStack itemStack, @Nullable Direction direction) { ++ return !this.changed && direction == Direction.UP && ComposterBlock.COMPOSTABLES.containsKey(itemStack.getItem()); + } + + @Override +- @Override +- public boolean canTakeItemThroughFace(int i, ItemStack itemstack, Direction direction) { ++ public boolean canTakeItemThroughFace(int index, ItemStack stack, Direction direction) { + return false; + } + + @Override +- @Override + public void setChanged() { + ItemStack itemstack = this.getItem(0); + + if (!itemstack.isEmpty()) { + this.changed = true; +- BlockState blockstate = ComposterBlock.addItem((Entity) null, this.state, this.level, this.pos, itemstack); ++ IBlockData iblockdata = ComposterBlock.addItem((Entity) null, this.state, this.level, this.pos, itemstack); + +- this.level.levelEvent(1500, this.pos, blockstate != this.state ? 1 : 0); ++ this.level.levelEvent(1500, this.pos, iblockdata != this.state ? 1 : 0); + this.removeItemNoUpdate(0); + } + + } + } + +- private static class EmptyContainer extends SimpleContainer implements WorldlyContainer { ++ public static class EmptyContainer extends SimpleContainer implements WorldlyContainer { + +- public EmptyContainer() { ++ public EmptyContainer(LevelAccessor generatoraccess, BlockPos blockposition) { // CraftBukkit + super(0); ++ this.bukkitOwner = new CraftBlockInventoryHolder(generatoraccess, blockposition, this); // CraftBukkit + } + + @Override +- @Override +- public int[] getSlotsForFace(Direction direction) { ++ public int[] getSlotsForFace(Direction side) { + return new int[0]; + } + + @Override +- @Override +- public boolean canPlaceItemThroughFace(int i, ItemStack itemstack, @Nullable Direction direction) { ++ public boolean canPlaceItemThroughFace(int index, ItemStack itemStack, @Nullable Direction direction) { + return false; + } + + @Override +- @Override +- public boolean canTakeItemThroughFace(int i, ItemStack itemstack, Direction direction) { ++ public boolean canTakeItemThroughFace(int index, ItemStack stack, Direction direction) { + return false; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ConcretePowderBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ConcretePowderBlock.java.patch new file mode 100644 index 0000000000..1c2d36e14a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ConcretePowderBlock.java.patch @@ -0,0 +1,161 @@ +--- a/net/minecraft/world/level/block/ConcretePowderBlock.java ++++ b/net/minecraft/world/level/block/ConcretePowderBlock.java +@@ -12,65 +12,85 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.block.CraftBlockStates; ++import org.bukkit.event.block.BlockFormEvent; ++// CraftBukkit end ++ + public class ConcretePowderBlock extends FallingBlock { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- return instance.group(BuiltInRegistries.BLOCK.byNameCodec().fieldOf("concrete").forGetter((concretepowderblock) -> { +- return concretepowderblock.concrete; ++ return instance.group(BuiltInRegistries.BLOCK.byNameCodec().fieldOf("concrete").forGetter((blockconcretepowder) -> { ++ return blockconcretepowder.concrete; + }), propertiesCodec()).apply(instance, ConcretePowderBlock::new); + }); + private final Block concrete; + + @Override +- @Override + public MapCodec codec() { + return ConcretePowderBlock.CODEC; + } + +- public ConcretePowderBlock(Block block, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.concrete = block; ++ public ConcretePowderBlock(Block concrete, BlockBehaviour.Properties properties) { ++ super(properties); ++ this.concrete = concrete; + } + + @Override +- @Override +- public void onLand(Level level, BlockPos blockpos, BlockState blockstate, BlockState blockstate1, FallingBlockEntity fallingblockentity) { +- if (shouldSolidify(level, blockpos, blockstate1)) { +- level.setBlock(blockpos, this.concrete.defaultBlockState(), 3); ++ public void onLand(Level level, BlockPos pos, IBlockData state, IBlockData replaceableState, FallingBlockEntity fallingBlock) { ++ if (shouldSolidify(level, pos, replaceableState)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, this.concrete.defaultBlockState(), 3); // CraftBukkit + } + + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- Level level = blockplacecontext.getLevel(); +- BlockPos blockpos = blockplacecontext.getClickedPos(); +- BlockState blockstate = level.getBlockState(blockpos); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ IBlockData iblockdata = world.getBlockState(blockposition); + +- return shouldSolidify(level, blockpos, blockstate) ? this.concrete.defaultBlockState() : super.getStateForPlacement(blockplacecontext); ++ // CraftBukkit start ++ if (!shouldSolidify(world, blockposition, iblockdata)) { ++ return super.getStateForPlacement(context); ++ } ++ ++ // TODO: An event factory call for methods like this ++ CraftBlockState blockState = CraftBlockStates.getBlockState(world, blockposition); ++ blockState.setData(this.concrete.defaultBlockState()); ++ ++ BlockFormEvent event = new BlockFormEvent(blockState.getBlock(), blockState); ++ world.getServer().server.getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ return blockState.getHandle(); ++ } ++ ++ return super.getStateForPlacement(context); ++ // CraftBukkit end + } + +- private static boolean shouldSolidify(BlockGetter blockgetter, BlockPos blockpos, BlockState blockstate) { +- return canSolidify(blockstate) || touchesLiquid(blockgetter, blockpos); ++ private static boolean shouldSolidify(BlockGetter level, BlockPos pos, IBlockData state) { ++ return canSolidify(state) || touchesLiquid(level, pos); + } + +- private static boolean touchesLiquid(BlockGetter blockgetter, BlockPos blockpos) { ++ private static boolean touchesLiquid(BlockGetter level, BlockPos pos) { + boolean flag = false; +- BlockPos.MutableBlockPos blockpos_mutableblockpos = blockpos.mutable(); +- Direction[] adirection = Direction.values(); +- int i = adirection.length; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; +- BlockState blockstate = blockgetter.getBlockState(blockpos_mutableblockpos); ++ Direction enumdirection = aenumdirection[j]; ++ IBlockData iblockdata = level.getBlockState(blockposition_mutableblockposition); + +- if (direction != Direction.DOWN || canSolidify(blockstate)) { +- blockpos_mutableblockpos.setWithOffset(blockpos, direction); +- blockstate = blockgetter.getBlockState(blockpos_mutableblockpos); +- if (canSolidify(blockstate) && !blockstate.isFaceSturdy(blockgetter, blockpos, direction.getOpposite())) { ++ if (enumdirection != Direction.DOWN || canSolidify(iblockdata)) { ++ blockposition_mutableblockposition.setWithOffset(pos, enumdirection); ++ iblockdata = level.getBlockState(blockposition_mutableblockposition); ++ if (canSolidify(iblockdata) && !iblockdata.isFaceSturdy(level, pos, enumdirection.getOpposite())) { + flag = true; + break; + } +@@ -80,19 +100,35 @@ + return flag; + } + +- private static boolean canSolidify(BlockState blockstate) { +- return blockstate.getFluidState().is(FluidTags.WATER); ++ private static boolean canSolidify(IBlockData state) { ++ return state.getFluidState().is(FluidTags.WATER); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- return touchesLiquid(levelaccessor, blockpos) ? this.concrete.defaultBlockState() : super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ // CraftBukkit start ++ if (touchesLiquid(level, currentPos)) { ++ // Suppress during worldgen ++ if (!(level instanceof Level)) { ++ return this.concrete.defaultBlockState(); ++ } ++ CraftBlockState blockState = CraftBlockStates.getBlockState(level, currentPos); ++ blockState.setData(this.concrete.defaultBlockState()); ++ ++ BlockFormEvent event = new BlockFormEvent(blockState.getBlock(), blockState); ++ ((Level) level).getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ return blockState.getHandle(); ++ } ++ } ++ ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ // CraftBukkit end + } + + @Override +- @Override +- public int getDustColor(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return blockstate.getMapColor(blockgetter, blockpos).col; ++ public int getDustColor(IBlockData state, BlockGetter reader, BlockPos pos) { ++ return state.getMapColor(reader, pos).col; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CoralBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CoralBlock.java.patch new file mode 100644 index 0000000000..14759a9278 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CoralBlock.java.patch @@ -0,0 +1,99 @@ +--- a/net/minecraft/world/level/block/CoralBlock.java ++++ b/net/minecraft/world/level/block/CoralBlock.java +@@ -13,58 +13,60 @@ + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; + + public class CoralBlock extends Block { + + public static final MapCodec DEAD_CORAL_FIELD = BuiltInRegistries.BLOCK.byNameCodec().fieldOf("dead"); + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- return instance.group(CoralBlock.DEAD_CORAL_FIELD.forGetter((coralblock) -> { +- return coralblock.deadBlock; ++ return instance.group(CoralBlock.DEAD_CORAL_FIELD.forGetter((blockcoral) -> { ++ return blockcoral.deadBlock; + }), propertiesCodec()).apply(instance, CoralBlock::new); + }); + private final Block deadBlock; + +- public CoralBlock(Block block, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.deadBlock = block; ++ public CoralBlock(Block deadBlock, BlockBehaviour.Properties properties) { ++ super(properties); ++ this.deadBlock = deadBlock; + } + + @Override +- @Override + public MapCodec codec() { + return CoralBlock.CODEC; + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (!this.scanForWater(serverlevel, blockpos)) { +- serverlevel.setBlock(blockpos, this.deadBlock.defaultBlockState(), 2); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (!this.scanForWater(level, pos)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, this.deadBlock.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, this.deadBlock.defaultBlockState(), 2); + } + + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if (!this.scanForWater(levelaccessor, blockpos)) { +- levelaccessor.scheduleTick(blockpos, (Block) this, 60 + levelaccessor.getRandom().nextInt(40)); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if (!this.scanForWater(level, currentPos)) { ++ level.scheduleTick(currentPos, (Block) this, 60 + level.getRandom().nextInt(40)); + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + +- protected boolean scanForWater(BlockGetter blockgetter, BlockPos blockpos) { +- Direction[] adirection = Direction.values(); +- int i = adirection.length; ++ protected boolean scanForWater(BlockGetter level, BlockPos pos) { ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; +- FluidState fluidstate = blockgetter.getFluidState(blockpos.relative(direction)); ++ Direction enumdirection = aenumdirection[j]; ++ FluidState fluid = level.getFluidState(pos.relative(enumdirection)); + +- if (fluidstate.is(FluidTags.WATER)) { ++ if (fluid.is(FluidTags.WATER)) { + return true; + } + } +@@ -74,10 +76,9 @@ + + @Nullable + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- if (!this.scanForWater(blockplacecontext.getLevel(), blockplacecontext.getClickedPos())) { +- blockplacecontext.getLevel().scheduleTick(blockplacecontext.getClickedPos(), (Block) this, 60 + blockplacecontext.getLevel().getRandom().nextInt(40)); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ if (!this.scanForWater(context.getLevel(), context.getClickedPos())) { ++ context.getLevel().scheduleTick(context.getClickedPos(), (Block) this, 60 + context.getLevel().getRandom().nextInt(40)); + } + + return this.defaultBlockState(); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CoralFanBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CoralFanBlock.java.patch new file mode 100644 index 0000000000..cf73df727d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CoralFanBlock.java.patch @@ -0,0 +1,82 @@ +--- a/net/minecraft/world/level/block/CoralFanBlock.java ++++ b/net/minecraft/world/level/block/CoralFanBlock.java +@@ -9,57 +9,58 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; + + public class CoralFanBlock extends BaseCoralFanBlock { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- return instance.group(CoralBlock.DEAD_CORAL_FIELD.forGetter((coralfanblock) -> { +- return coralfanblock.deadBlock; ++ return instance.group(CoralBlock.DEAD_CORAL_FIELD.forGetter((blockcoralfan) -> { ++ return blockcoralfan.deadBlock; + }), propertiesCodec()).apply(instance, CoralFanBlock::new); + }); + private final Block deadBlock; + + @Override +- @Override + public MapCodec codec() { + return CoralFanBlock.CODEC; + } + +- protected CoralFanBlock(Block block, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.deadBlock = block; ++ protected CoralFanBlock(Block deadBlock, BlockBehaviour.Properties properties) { ++ super(properties); ++ this.deadBlock = deadBlock; + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- this.tryScheduleDieTick(blockstate, level, blockpos); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ this.tryScheduleDieTick(state, level, pos); + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (!scanForWater(blockstate, serverlevel, blockpos)) { +- serverlevel.setBlock(blockpos, (BlockState) this.deadBlock.defaultBlockState().setValue(CoralFanBlock.WATERLOGGED, false), 2); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (!scanForWater(state, level, pos)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, this.deadBlock.defaultBlockState().setValue(CoralFanBlock.WATERLOGGED, false)).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) this.deadBlock.defaultBlockState().setValue(CoralFanBlock.WATERLOGGED, false), 2); + } + + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if (direction == Direction.DOWN && !blockstate.canSurvive(levelaccessor, blockpos)) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if (facing == Direction.DOWN && !state.canSurvive(level, currentPos)) { + return Blocks.AIR.defaultBlockState(); + } else { +- this.tryScheduleDieTick(blockstate, levelaccessor, blockpos); +- if ((Boolean) blockstate.getValue(CoralFanBlock.WATERLOGGED)) { +- levelaccessor.scheduleTick(blockpos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(levelaccessor)); ++ this.tryScheduleDieTick(state, level, currentPos); ++ if ((Boolean) state.getValue(CoralFanBlock.WATERLOGGED)) { ++ level.scheduleTick(currentPos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CoralPlantBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CoralPlantBlock.java.patch new file mode 100644 index 0000000000..f42c6279ab --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CoralPlantBlock.java.patch @@ -0,0 +1,92 @@ +--- a/net/minecraft/world/level/block/CoralPlantBlock.java ++++ b/net/minecraft/world/level/block/CoralPlantBlock.java +@@ -10,7 +10,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.shapes.CollisionContext; +@@ -19,8 +19,8 @@ + public class CoralPlantBlock extends BaseCoralPlantTypeBlock { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- return instance.group(CoralBlock.DEAD_CORAL_FIELD.forGetter((coralplantblock) -> { +- return coralplantblock.deadBlock; ++ return instance.group(CoralBlock.DEAD_CORAL_FIELD.forGetter((blockcoralplant) -> { ++ return blockcoralplant.deadBlock; + }), propertiesCodec()).apply(instance, CoralPlantBlock::new); + }); + private final Block deadBlock; +@@ -28,49 +28,49 @@ + protected static final VoxelShape SHAPE = Block.box(2.0D, 0.0D, 2.0D, 14.0D, 15.0D, 14.0D); + + @Override +- @Override + public MapCodec codec() { + return CoralPlantBlock.CODEC; + } + +- protected CoralPlantBlock(Block block, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.deadBlock = block; ++ protected CoralPlantBlock(Block deadBlock, BlockBehaviour.Properties properties) { ++ super(properties); ++ this.deadBlock = deadBlock; + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- this.tryScheduleDieTick(blockstate, level, blockpos); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ this.tryScheduleDieTick(state, level, pos); + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (!scanForWater(blockstate, serverlevel, blockpos)) { +- serverlevel.setBlock(blockpos, (BlockState) this.deadBlock.defaultBlockState().setValue(CoralPlantBlock.WATERLOGGED, false), 2); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (!scanForWater(state, level, pos)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, this.deadBlock.defaultBlockState().setValue(CoralPlantBlock.WATERLOGGED, false)).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) this.deadBlock.defaultBlockState().setValue(CoralPlantBlock.WATERLOGGED, false), 2); + } + + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if (direction == Direction.DOWN && !blockstate.canSurvive(levelaccessor, blockpos)) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if (facing == Direction.DOWN && !state.canSurvive(level, currentPos)) { + return Blocks.AIR.defaultBlockState(); + } else { +- this.tryScheduleDieTick(blockstate, levelaccessor, blockpos); +- if ((Boolean) blockstate.getValue(CoralPlantBlock.WATERLOGGED)) { +- levelaccessor.scheduleTick(blockpos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(levelaccessor)); ++ this.tryScheduleDieTick(state, level, currentPos); ++ if ((Boolean) state.getValue(CoralPlantBlock.WATERLOGGED)) { ++ level.scheduleTick(currentPos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return CoralPlantBlock.SHAPE; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CoralWallFanBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CoralWallFanBlock.java.patch new file mode 100644 index 0000000000..8cc6df029f --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CoralWallFanBlock.java.patch @@ -0,0 +1,82 @@ +--- a/net/minecraft/world/level/block/CoralWallFanBlock.java ++++ b/net/minecraft/world/level/block/CoralWallFanBlock.java +@@ -9,57 +9,58 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; + + public class CoralWallFanBlock extends BaseCoralWallFanBlock { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- return instance.group(CoralBlock.DEAD_CORAL_FIELD.forGetter((coralwallfanblock) -> { +- return coralwallfanblock.deadBlock; ++ return instance.group(CoralBlock.DEAD_CORAL_FIELD.forGetter((blockcoralfanwall) -> { ++ return blockcoralfanwall.deadBlock; + }), propertiesCodec()).apply(instance, CoralWallFanBlock::new); + }); + private final Block deadBlock; + + @Override +- @Override + public MapCodec codec() { + return CoralWallFanBlock.CODEC; + } + +- protected CoralWallFanBlock(Block block, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.deadBlock = block; ++ protected CoralWallFanBlock(Block deadBlock, BlockBehaviour.Properties properties) { ++ super(properties); ++ this.deadBlock = deadBlock; + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- this.tryScheduleDieTick(blockstate, level, blockpos); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ this.tryScheduleDieTick(state, level, pos); + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (!scanForWater(blockstate, serverlevel, blockpos)) { +- serverlevel.setBlock(blockpos, (BlockState) ((BlockState) this.deadBlock.defaultBlockState().setValue(CoralWallFanBlock.WATERLOGGED, false)).setValue(CoralWallFanBlock.FACING, (Direction) blockstate.getValue(CoralWallFanBlock.FACING)), 2); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (!scanForWater(state, level, pos)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, this.deadBlock.defaultBlockState().setValue(CoralWallFanBlock.WATERLOGGED, false).setValue(CoralWallFanBlock.FACING, state.getValue(CoralWallFanBlock.FACING))).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) ((IBlockData) this.deadBlock.defaultBlockState().setValue(CoralWallFanBlock.WATERLOGGED, false)).setValue(CoralWallFanBlock.FACING, (Direction) state.getValue(CoralWallFanBlock.FACING)), 2); + } + + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if (direction.getOpposite() == blockstate.getValue(CoralWallFanBlock.FACING) && !blockstate.canSurvive(levelaccessor, blockpos)) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if (facing.getOpposite() == state.getValue(CoralWallFanBlock.FACING) && !state.canSurvive(level, currentPos)) { + return Blocks.AIR.defaultBlockState(); + } else { +- if ((Boolean) blockstate.getValue(CoralWallFanBlock.WATERLOGGED)) { +- levelaccessor.scheduleTick(blockpos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(levelaccessor)); ++ if ((Boolean) state.getValue(CoralWallFanBlock.WATERLOGGED)) { ++ level.scheduleTick(currentPos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + +- this.tryScheduleDieTick(blockstate, levelaccessor, blockpos); +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ this.tryScheduleDieTick(state, level, currentPos); ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CropBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CropBlock.java.patch new file mode 100644 index 0000000000..d8354c373e --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/CropBlock.java.patch @@ -0,0 +1,246 @@ +--- a/net/minecraft/world/level/block/CropBlock.java ++++ b/net/minecraft/world/level/block/CropBlock.java +@@ -11,16 +11,17 @@ + import net.minecraft.world.item.Items; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.GameRules; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class CropBlock extends BushBlock implements BonemealableBlock { + +@@ -30,26 +31,23 @@ + private static final VoxelShape[] SHAPE_BY_AGE = new VoxelShape[]{Block.box(0.0D, 0.0D, 0.0D, 16.0D, 2.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 4.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 6.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 8.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 10.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 12.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 14.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 16.0D, 16.0D)}; + + @Override +- @Override + public MapCodec codec() { + return CropBlock.CODEC; + } + +- protected CropBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(this.getAgeProperty(), 0)); ++ protected CropBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(this.getAgeProperty(), 0)); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return CropBlock.SHAPE_BY_AGE[this.getAge(blockstate)]; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return CropBlock.SHAPE_BY_AGE[this.getAge(state)]; + } + + @Override +- @Override +- protected boolean mayPlaceOn(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return blockstate.is(Blocks.FARMLAND); ++ protected boolean mayPlaceOn(IBlockData state, BlockGetter level, BlockPos pos) { ++ return state.is(Blocks.FARMLAND); + } + + protected IntegerProperty getAgeProperty() { +@@ -60,68 +58,66 @@ + return 7; + } + +- public int getAge(BlockState blockstate) { +- return (Integer) blockstate.getValue(this.getAgeProperty()); ++ public int getAge(IBlockData state) { ++ return (Integer) state.getValue(this.getAgeProperty()); + } + +- public BlockState getStateForAge(int i) { +- return (BlockState) this.defaultBlockState().setValue(this.getAgeProperty(), i); ++ public IBlockData getStateForAge(int age) { ++ return (IBlockData) this.defaultBlockState().setValue(this.getAgeProperty(), age); + } + +- public final boolean isMaxAge(BlockState blockstate) { +- return this.getAge(blockstate) >= this.getMaxAge(); ++ public final boolean isMaxAge(IBlockData state) { ++ return this.getAge(state) >= this.getMaxAge(); + } + + @Override +- @Override +- public boolean isRandomlyTicking(BlockState blockstate) { +- return !this.isMaxAge(blockstate); ++ public boolean isRandomlyTicking(IBlockData state) { ++ return !this.isMaxAge(state); + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (serverlevel.getRawBrightness(blockpos, 0) >= 9) { +- int i = this.getAge(blockstate); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (level.getRawBrightness(pos, 0) >= 9) { ++ int i = this.getAge(state); + + if (i < this.getMaxAge()) { +- float f = getGrowthSpeed(this, serverlevel, blockpos); ++ float f = getGrowthSpeed(this, level, pos); + +- if (randomsource.nextInt((int) (25.0F / f) + 1) == 0) { +- serverlevel.setBlock(blockpos, this.getStateForAge(i + 1), 2); ++ if (random.nextInt((int) (25.0F / f) + 1) == 0) { ++ CraftEventFactory.handleBlockGrowEvent(level, pos, this.getStateForAge(i + 1), 2); // CraftBukkit + } + } + } + + } + +- public void growCrops(Level level, BlockPos blockpos, BlockState blockstate) { +- int i = this.getAge(blockstate) + this.getBonemealAgeIncrease(level); ++ public void growCrops(Level level, BlockPos pos, IBlockData state) { ++ int i = this.getAge(state) + this.getBonemealAgeIncrease(level); + int j = this.getMaxAge(); + + if (i > j) { + i = j; + } + +- level.setBlock(blockpos, this.getStateForAge(i), 2); ++ CraftEventFactory.handleBlockGrowEvent(level, pos, this.getStateForAge(i), 2); // CraftBukkit + } + + protected int getBonemealAgeIncrease(Level level) { + return Mth.nextInt(level.random, 2, 5); + } + +- protected static float getGrowthSpeed(Block block, BlockGetter blockgetter, BlockPos blockpos) { ++ protected static float getGrowthSpeed(Block block, BlockGetter level, BlockPos pos) { + float f = 1.0F; +- BlockPos blockpos1 = blockpos.below(); ++ BlockPos blockposition1 = pos.below(); + + for (int i = -1; i <= 1; ++i) { + for (int j = -1; j <= 1; ++j) { + float f1 = 0.0F; +- BlockState blockstate = blockgetter.getBlockState(blockpos1.offset(i, 0, j)); ++ IBlockData iblockdata = level.getBlockState(blockposition1.offset(i, 0, j)); + +- if (blockstate.is(Blocks.FARMLAND)) { ++ if (iblockdata.is(Blocks.FARMLAND)) { + f1 = 1.0F; +- if ((Integer) blockstate.getValue(FarmBlock.MOISTURE) > 0) { ++ if ((Integer) iblockdata.getValue(FarmBlock.MOISTURE) > 0) { + f1 = 3.0F; + } + } +@@ -134,17 +130,17 @@ + } + } + +- BlockPos blockpos2 = blockpos.north(); +- BlockPos blockpos3 = blockpos.south(); +- BlockPos blockpos4 = blockpos.west(); +- BlockPos blockpos5 = blockpos.east(); +- boolean flag = blockgetter.getBlockState(blockpos4).is(block) || blockgetter.getBlockState(blockpos5).is(block); +- boolean flag1 = blockgetter.getBlockState(blockpos2).is(block) || blockgetter.getBlockState(blockpos3).is(block); ++ BlockPos blockposition2 = pos.north(); ++ BlockPos blockposition3 = pos.south(); ++ BlockPos blockposition4 = pos.west(); ++ BlockPos blockposition5 = pos.east(); ++ boolean flag = level.getBlockState(blockposition4).is(block) || level.getBlockState(blockposition5).is(block); ++ boolean flag1 = level.getBlockState(blockposition2).is(block) || level.getBlockState(blockposition3).is(block); + + if (flag && flag1) { + f /= 2.0F; + } else { +- boolean flag2 = blockgetter.getBlockState(blockpos4.north()).is(block) || blockgetter.getBlockState(blockpos5.north()).is(block) || blockgetter.getBlockState(blockpos5.south()).is(block) || blockgetter.getBlockState(blockpos4.south()).is(block); ++ boolean flag2 = level.getBlockState(blockposition4.north()).is(block) || level.getBlockState(blockposition5.north()).is(block) || level.getBlockState(blockposition5.south()).is(block) || level.getBlockState(blockposition4.south()).is(block); + + if (flag2) { + f /= 2.0F; +@@ -155,56 +151,49 @@ + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- return hasSufficientLight(levelreader, blockpos) && super.canSurvive(blockstate, levelreader, blockpos); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ return hasSufficientLight(level, pos) && super.canSurvive(state, level, pos); + } + +- protected static boolean hasSufficientLight(LevelReader levelreader, BlockPos blockpos) { +- return levelreader.getRawBrightness(blockpos, 0) >= 8; ++ protected static boolean hasSufficientLight(LevelReader iworldreader, BlockPos blockposition) { ++ return iworldreader.getRawBrightness(blockposition, 0) >= 8; + } + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { +- if (entity instanceof Ravager && level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- level.destroyBlock(blockpos, true, entity); ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ if (entity instanceof Ravager && CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit ++ level.destroyBlock(pos, true, entity); + } + +- super.entityInside(blockstate, level, blockpos, entity); ++ super.entityInside(state, level, pos, entity); + } + +- protected ItemLike getBaseSeedId() { ++ protected IMaterial getBaseSeedId() { + return Items.WHEAT_SEEDS; + } + + @Override +- @Override +- public ItemStack getCloneItemStack(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { ++ public ItemStack getCloneItemStack(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { + return new ItemStack(this.getBaseSeedId()); + } + + @Override +- @Override +- public boolean isValidBonemealTarget(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { +- return !this.isMaxAge(blockstate); ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ return !this.isMaxAge(iblockdata); + } + + @Override +- @Override +- public boolean isBonemealSuccess(Level level, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return true; + } + + @Override +- @Override +- public void performBonemeal(ServerLevel serverlevel, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { +- this.growCrops(serverlevel, blockpos, blockstate); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ this.growCrops(level, pos, state); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(CropBlock.AGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(CropBlock.AGE); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DaylightDetectorBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DaylightDetectorBlock.java.patch new file mode 100644 index 0000000000..73183bccbd --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DaylightDetectorBlock.java.patch @@ -0,0 +1,160 @@ +--- a/net/minecraft/world/level/block/DaylightDetectorBlock.java ++++ b/net/minecraft/world/level/block/DaylightDetectorBlock.java +@@ -5,18 +5,18 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.BlockGetter; ++import net.minecraft.world.level.EnumSkyBlock; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BlockEntityTicker; + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.DaylightDetectorBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -34,38 +34,34 @@ + protected static final VoxelShape SHAPE = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 6.0D, 16.0D); + + @Override +- @Override + public MapCodec codec() { + return DaylightDetectorBlock.CODEC; + } + +- public DaylightDetectorBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(DaylightDetectorBlock.POWER, 0)).setValue(DaylightDetectorBlock.INVERTED, false)); ++ public DaylightDetectorBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(DaylightDetectorBlock.POWER, 0)).setValue(DaylightDetectorBlock.INVERTED, false)); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return DaylightDetectorBlock.SHAPE; + } + + @Override +- @Override +- public boolean useShapeForLightOcclusion(BlockState blockstate) { ++ public boolean useShapeForLightOcclusion(IBlockData state) { + return true; + } + + @Override +- @Override +- public int getSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return (Integer) blockstate.getValue(DaylightDetectorBlock.POWER); ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return (Integer) blockState.getValue(DaylightDetectorBlock.POWER); + } + +- private static void updateSignalStrength(BlockState blockstate, Level level, BlockPos blockpos) { +- int i = level.getBrightness(LightLayer.SKY, blockpos) - level.getSkyDarken(); ++ private static void updateSignalStrength(IBlockData state, Level level, BlockPos pos) { ++ int i = level.getBrightness(EnumSkyBlock.SKY, pos) - level.getSkyDarken(); + float f = level.getSunAngle(1.0F); +- boolean flag = (Boolean) blockstate.getValue(DaylightDetectorBlock.INVERTED); ++ boolean flag = (Boolean) state.getValue(DaylightDetectorBlock.INVERTED); + + if (flag) { + i = 15 - i; +@@ -77,66 +73,61 @@ + } + + i = Mth.clamp(i, 0, 15); +- if ((Integer) blockstate.getValue(DaylightDetectorBlock.POWER) != i) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(DaylightDetectorBlock.POWER, i), 3); ++ if ((Integer) state.getValue(DaylightDetectorBlock.POWER) != i) { ++ i = org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(level, pos, ((Integer) state.getValue(POWER)), i).getNewCurrent(); // CraftBukkit - Call BlockRedstoneEvent ++ level.setBlock(pos, (IBlockData) state.setValue(DaylightDetectorBlock.POWER, i), 3); + } + + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + if (player.mayBuild()) { + if (level.isClientSide) { + return InteractionResult.SUCCESS; + } else { +- BlockState blockstate1 = (BlockState) blockstate.cycle(DaylightDetectorBlock.INVERTED); ++ IBlockData iblockdata1 = (IBlockData) state.cycle(DaylightDetectorBlock.INVERTED); + +- level.setBlock(blockpos, blockstate1, 2); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(player, blockstate1)); +- updateSignalStrength(blockstate1, level, blockpos); ++ level.setBlock(pos, iblockdata1, 2); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(player, iblockdata1)); ++ updateSignalStrength(iblockdata1, level, pos); + return InteractionResult.CONSUME; + } + } else { +- return super.use(blockstate, level, blockpos, player, interactionhand, blockhitresult); ++ return super.use(state, level, pos, player, hand, hit); + } + } + + @Override +- @Override +- public RenderShape getRenderShape(BlockState blockstate) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Override +- @Override +- public boolean isSignalSource(BlockState blockstate) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + + @Override +- @Override +- public BlockEntity newBlockEntity(BlockPos blockpos, BlockState blockstate) { +- return new DaylightDetectorBlockEntity(blockpos, blockstate); ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ return new DaylightDetectorBlockEntity(pos, state); + } + + @Nullable + @Override +- @Override +- public BlockEntityTicker getTicker(Level level, BlockState blockstate, BlockEntityType blockentitytype) { +- return !level.isClientSide && level.dimensionType().hasSkyLight() ? createTickerHelper(blockentitytype, BlockEntityType.DAYLIGHT_DETECTOR, DaylightDetectorBlock::tickEntity) : null; ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { ++ return !level.isClientSide && level.dimensionType().hasSkyLight() ? createTickerHelper(blockEntityType, BlockEntityType.DAYLIGHT_DETECTOR, DaylightDetectorBlock::tickEntity) : null; + } + +- private static void tickEntity(Level level, BlockPos blockpos, BlockState blockstate, DaylightDetectorBlockEntity daylightdetectorblockentity) { ++ private static void tickEntity(Level level, BlockPos pos, IBlockData state, DaylightDetectorBlockEntity blockEntity) { + if (level.getGameTime() % 20L == 0L) { +- updateSignalStrength(blockstate, level, blockpos); ++ updateSignalStrength(state, level, pos); + } + + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(DaylightDetectorBlock.POWER, DaylightDetectorBlock.INVERTED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(DaylightDetectorBlock.POWER, DaylightDetectorBlock.INVERTED); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DetectorRailBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DetectorRailBlock.java.patch new file mode 100644 index 0000000000..51585efb91 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DetectorRailBlock.java.patch @@ -0,0 +1,417 @@ +--- a/net/minecraft/world/level/block/DetectorRailBlock.java ++++ b/net/minecraft/world/level/block/DetectorRailBlock.java +@@ -17,7 +17,7 @@ + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -25,6 +25,7 @@ + import net.minecraft.world.level.block.state.properties.Property; + import net.minecraft.world.level.block.state.properties.RailShape; + import net.minecraft.world.phys.AABB; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class DetectorRailBlock extends BaseRailBlock { + +@@ -34,57 +35,51 @@ + private static final int PRESSED_CHECK_PERIOD = 20; + + @Override +- @Override + public MapCodec codec() { + return DetectorRailBlock.CODEC; + } + +- public DetectorRailBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(true, blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(DetectorRailBlock.POWERED, false)).setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_SOUTH)).setValue(DetectorRailBlock.WATERLOGGED, false)); ++ public DetectorRailBlock(BlockBehaviour.Properties properties) { ++ super(true, properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(DetectorRailBlock.POWERED, false)).setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_SOUTH)).setValue(DetectorRailBlock.WATERLOGGED, false)); + } + + @Override +- @Override +- public boolean isSignalSource(BlockState blockstate) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { + if (!level.isClientSide) { +- if (!(Boolean) blockstate.getValue(DetectorRailBlock.POWERED)) { +- this.checkPressed(level, blockpos, blockstate); ++ if (!(Boolean) state.getValue(DetectorRailBlock.POWERED)) { ++ this.checkPressed(level, pos, state); + } + } + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if ((Boolean) blockstate.getValue(DetectorRailBlock.POWERED)) { +- this.checkPressed(serverlevel, blockpos, blockstate); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(DetectorRailBlock.POWERED)) { ++ this.checkPressed(level, pos, state); + } + } + + @Override +- @Override +- public int getSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return (Boolean) blockstate.getValue(DetectorRailBlock.POWERED) ? 15 : 0; ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return (Boolean) blockState.getValue(DetectorRailBlock.POWERED) ? 15 : 0; + } + + @Override +- @Override +- public int getDirectSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return !(Boolean) blockstate.getValue(DetectorRailBlock.POWERED) ? 0 : (direction == Direction.UP ? 15 : 0); ++ public int getDirectSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return !(Boolean) blockState.getValue(DetectorRailBlock.POWERED) ? 0 : (side == Direction.UP ? 15 : 0); + } + +- private void checkPressed(Level level, BlockPos blockpos, BlockState blockstate) { +- if (this.canSurvive(blockstate, level, blockpos)) { +- boolean flag = (Boolean) blockstate.getValue(DetectorRailBlock.POWERED); ++ private void checkPressed(Level level, BlockPos pos, IBlockData state) { ++ if (this.canSurvive(state, level, pos)) { ++ boolean flag = (Boolean) state.getValue(DetectorRailBlock.POWERED); + boolean flag1 = false; +- List list = this.getInteractingMinecartOfType(level, blockpos, AbstractMinecart.class, (entity) -> { ++ List list = this.getInteractingMinecartOfType(level, pos, AbstractMinecart.class, (entity) -> { + return true; + }); + +@@ -92,75 +87,81 @@ + flag1 = true; + } + +- BlockState blockstate1; ++ IBlockData iblockdata1; ++ // CraftBukkit start ++ if (flag != flag1) { ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); + ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, flag ? 15 : 0, flag1 ? 15 : 0); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ flag1 = eventRedstone.getNewCurrent() > 0; ++ } ++ // CraftBukkit end ++ + if (flag1 && !flag) { +- blockstate1 = (BlockState) blockstate.setValue(DetectorRailBlock.POWERED, true); +- level.setBlock(blockpos, blockstate1, 3); +- this.updatePowerToConnected(level, blockpos, blockstate1, true); +- level.updateNeighborsAt(blockpos, this); +- level.updateNeighborsAt(blockpos.below(), this); +- level.setBlocksDirty(blockpos, blockstate, blockstate1); ++ iblockdata1 = (IBlockData) state.setValue(DetectorRailBlock.POWERED, true); ++ level.setBlock(pos, iblockdata1, 3); ++ this.updatePowerToConnected(level, pos, iblockdata1, true); ++ level.updateNeighborsAt(pos, this); ++ level.updateNeighborsAt(pos.below(), this); ++ level.setBlocksDirty(pos, state, iblockdata1); + } + + if (!flag1 && flag) { +- blockstate1 = (BlockState) blockstate.setValue(DetectorRailBlock.POWERED, false); +- level.setBlock(blockpos, blockstate1, 3); +- this.updatePowerToConnected(level, blockpos, blockstate1, false); +- level.updateNeighborsAt(blockpos, this); +- level.updateNeighborsAt(blockpos.below(), this); +- level.setBlocksDirty(blockpos, blockstate, blockstate1); ++ iblockdata1 = (IBlockData) state.setValue(DetectorRailBlock.POWERED, false); ++ level.setBlock(pos, iblockdata1, 3); ++ this.updatePowerToConnected(level, pos, iblockdata1, false); ++ level.updateNeighborsAt(pos, this); ++ level.updateNeighborsAt(pos.below(), this); ++ level.setBlocksDirty(pos, state, iblockdata1); + } + + if (flag1) { +- level.scheduleTick(blockpos, (Block) this, 20); ++ level.scheduleTick(pos, (Block) this, 20); + } + +- level.updateNeighbourForOutputSignal(blockpos, this); ++ level.updateNeighbourForOutputSignal(pos, this); + } + } + +- protected void updatePowerToConnected(Level level, BlockPos blockpos, BlockState blockstate, boolean flag) { +- RailState railstate = new RailState(level, blockpos, blockstate); +- List list = railstate.getConnections(); ++ protected void updatePowerToConnected(Level level, BlockPos pos, IBlockData state, boolean powered) { ++ RailState minecarttracklogic = new RailState(level, pos, state); ++ List list = minecarttracklogic.getConnections(); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- BlockPos blockpos1 = (BlockPos) iterator.next(); +- BlockState blockstate1 = level.getBlockState(blockpos1); ++ BlockPos blockposition1 = (BlockPos) iterator.next(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + +- level.neighborChanged(blockstate1, blockpos1, blockstate1.getBlock(), blockpos, false); ++ level.neighborChanged(iblockdata1, blockposition1, iblockdata1.getBlock(), pos, false); + } + + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!blockstate1.is(blockstate.getBlock())) { +- BlockState blockstate2 = this.updateState(blockstate, level, blockpos, flag); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ if (!oldState.is(state.getBlock())) { ++ IBlockData iblockdata2 = this.updateState(state, level, pos, isMoving); + +- this.checkPressed(level, blockpos, blockstate2); ++ this.checkPressed(level, pos, iblockdata2); + } + } + + @Override +- @Override + public Property getShapeProperty() { + return DetectorRailBlock.SHAPE; + } + + @Override +- @Override +- public boolean hasAnalogOutputSignal(BlockState blockstate) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return true; + } + + @Override +- @Override +- public int getAnalogOutputSignal(BlockState blockstate, Level level, BlockPos blockpos) { +- if ((Boolean) blockstate.getValue(DetectorRailBlock.POWERED)) { +- List list = this.getInteractingMinecartOfType(level, blockpos, MinecartCommandBlock.class, (entity) -> { ++ public int getAnalogOutputSignal(IBlockData blockState, Level level, BlockPos pos) { ++ if ((Boolean) blockState.getValue(DetectorRailBlock.POWERED)) { ++ List list = this.getInteractingMinecartOfType(level, pos, MinecartCommandBlock.class, (entity) -> { + return true; + }); + +@@ -168,7 +169,7 @@ + return ((MinecartCommandBlock) list.get(0)).getCommandBlock().getSuccessCount(); + } + +- List list1 = this.getInteractingMinecartOfType(level, blockpos, AbstractMinecart.class, EntitySelector.CONTAINER_ENTITY_SELECTOR); ++ List list1 = this.getInteractingMinecartOfType(level, pos, AbstractMinecart.class, EntitySelector.CONTAINER_ENTITY_SELECTOR); + + if (!list1.isEmpty()) { + return AbstractContainerMenu.getRedstoneSignalFromContainer((Container) list1.get(0)); +@@ -178,140 +179,137 @@ + return 0; + } + +- private List getInteractingMinecartOfType(Level level, BlockPos blockpos, Class oclass, Predicate predicate) { +- return level.getEntitiesOfClass(oclass, this.getSearchBB(blockpos), predicate); ++ private List getInteractingMinecartOfType(Level level, BlockPos pos, Class cartType, Predicate filter) { ++ return level.getEntitiesOfClass(cartType, this.getSearchBB(pos), filter); + } + +- private AABB getSearchBB(BlockPos blockpos) { ++ private AABB getSearchBB(BlockPos pos) { + double d0 = 0.2D; + +- return new AABB((double) blockpos.getX() + 0.2D, (double) blockpos.getY(), (double) blockpos.getZ() + 0.2D, (double) (blockpos.getX() + 1) - 0.2D, (double) (blockpos.getY() + 1) - 0.2D, (double) (blockpos.getZ() + 1) - 0.2D); ++ return new AABB((double) pos.getX() + 0.2D, (double) pos.getY(), (double) pos.getZ() + 0.2D, (double) (pos.getX() + 1) - 0.2D, (double) (pos.getY() + 1) - 0.2D, (double) (pos.getZ() + 1) - 0.2D); + } + + @Override +- @Override +- public BlockState rotate(BlockState blockstate, Rotation rotation) { ++ public IBlockData rotate(IBlockData state, Rotation rotation) { + switch (rotation) { + case CLOCKWISE_180: +- switch ((RailShape) blockstate.getValue(DetectorRailBlock.SHAPE)) { ++ switch ((RailShape) state.getValue(DetectorRailBlock.SHAPE)) { + case ASCENDING_EAST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_WEST); + case ASCENDING_WEST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_EAST); + case ASCENDING_NORTH: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); + case ASCENDING_SOUTH: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_NORTH); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_NORTH); + case SOUTH_EAST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_WEST); + case SOUTH_WEST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_EAST); + case NORTH_WEST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_EAST); + case NORTH_EAST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_WEST); + } + case COUNTERCLOCKWISE_90: +- switch ((RailShape) blockstate.getValue(DetectorRailBlock.SHAPE)) { ++ switch ((RailShape) state.getValue(DetectorRailBlock.SHAPE)) { + case ASCENDING_EAST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_NORTH); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_NORTH); + case ASCENDING_WEST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); + case ASCENDING_NORTH: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_WEST); + case ASCENDING_SOUTH: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_EAST); + case SOUTH_EAST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_EAST); + case SOUTH_WEST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_EAST); + case NORTH_WEST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_WEST); + case NORTH_EAST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_WEST); + case NORTH_SOUTH: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.EAST_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.EAST_WEST); + case EAST_WEST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_SOUTH); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_SOUTH); + } + case CLOCKWISE_90: +- switch ((RailShape) blockstate.getValue(DetectorRailBlock.SHAPE)) { ++ switch ((RailShape) state.getValue(DetectorRailBlock.SHAPE)) { + case ASCENDING_EAST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); + case ASCENDING_WEST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_NORTH); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_NORTH); + case ASCENDING_NORTH: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_EAST); + case ASCENDING_SOUTH: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_WEST); + case SOUTH_EAST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_WEST); + case SOUTH_WEST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_WEST); + case NORTH_WEST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_EAST); + case NORTH_EAST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_EAST); + case NORTH_SOUTH: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.EAST_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.EAST_WEST); + case EAST_WEST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_SOUTH); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_SOUTH); + } + default: +- return blockstate; ++ return state; + } + } + + @Override +- @Override +- public BlockState mirror(BlockState blockstate, Mirror mirror) { +- RailShape railshape = (RailShape) blockstate.getValue(DetectorRailBlock.SHAPE); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ RailShape blockpropertytrackposition = (RailShape) state.getValue(DetectorRailBlock.SHAPE); + + switch (mirror) { + case LEFT_RIGHT: +- switch (railshape) { ++ switch (blockpropertytrackposition) { + case ASCENDING_NORTH: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); + case ASCENDING_SOUTH: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_NORTH); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_NORTH); + case SOUTH_EAST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_EAST); + case SOUTH_WEST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_WEST); + case NORTH_WEST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_WEST); + case NORTH_EAST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_EAST); + default: +- return super.mirror(blockstate, mirror); ++ return super.mirror(state, mirror); + } + case FRONT_BACK: +- switch (railshape) { ++ switch (blockpropertytrackposition) { + case ASCENDING_EAST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_WEST); + case ASCENDING_WEST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_EAST); + case ASCENDING_NORTH: + case ASCENDING_SOUTH: + default: + break; + case SOUTH_EAST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_WEST); + case SOUTH_WEST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_EAST); + case NORTH_WEST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_EAST); + case NORTH_EAST: +- return (BlockState) blockstate.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_WEST); + } + } + +- return super.mirror(blockstate, mirror); ++ return super.mirror(state, mirror); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(DetectorRailBlock.SHAPE, DetectorRailBlock.POWERED, DetectorRailBlock.WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(DetectorRailBlock.SHAPE, DetectorRailBlock.POWERED, DetectorRailBlock.WATERLOGGED); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DiodeBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DiodeBlock.java.patch new file mode 100644 index 0000000000..0008db28b8 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DiodeBlock.java.patch @@ -0,0 +1,303 @@ +--- a/net/minecraft/world/level/block/DiodeBlock.java ++++ b/net/minecraft/world/level/block/DiodeBlock.java +@@ -14,57 +14,64 @@ + import net.minecraft.world.level.SignalGetter; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.ticks.TickPriority; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public abstract class DiodeBlock extends HorizontalDirectionalBlock { + + protected static final VoxelShape SHAPE = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 2.0D, 16.0D); + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + +- protected DiodeBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ protected DiodeBlock(BlockBehaviour.Properties properties) { ++ super(properties); + } + + @Override +- @Override + protected abstract MapCodec codec(); + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return DiodeBlock.SHAPE; + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- BlockPos blockpos1 = blockpos.below(); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.below(); + +- return this.canSurviveOn(levelreader, blockpos1, levelreader.getBlockState(blockpos1)); ++ return this.canSurviveOn(level, blockposition1, level.getBlockState(blockposition1)); + } + +- protected boolean canSurviveOn(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { +- return blockstate.isFaceSturdy(levelreader, blockpos, Direction.UP, SupportType.RIGID); ++ protected boolean canSurviveOn(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ return iblockdata.isFaceSturdy(iworldreader, blockposition, Direction.UP, SupportType.RIGID); + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (!this.isLocked(serverlevel, blockpos, blockstate)) { +- boolean flag = (Boolean) blockstate.getValue(DiodeBlock.POWERED); +- boolean flag1 = this.shouldTurnOn(serverlevel, blockpos, blockstate); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (!this.isLocked(level, pos, state)) { ++ boolean flag = (Boolean) state.getValue(DiodeBlock.POWERED); ++ boolean flag1 = this.shouldTurnOn(level, pos, state); + + if (flag && !flag1) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(DiodeBlock.POWERED, false), 2); ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 15, 0).getNewCurrent() != 0) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(DiodeBlock.POWERED, false), 2); + } else if (!flag) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(DiodeBlock.POWERED, true), 2); ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 0, 15).getNewCurrent() != 15) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(DiodeBlock.POWERED, true), 2); + if (!flag1) { +- serverlevel.scheduleTick(blockpos, (Block) this, this.getDelay(blockstate), TickPriority.VERY_HIGH); ++ level.scheduleTick(pos, (Block) this, this.getDelay(state), TickPriority.VERY_HIGH); + } + } + +@@ -72,152 +79,144 @@ + } + + @Override +- @Override +- public int getDirectSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return blockstate.getSignal(blockgetter, blockpos, direction); ++ public int getDirectSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return blockState.getSignal(blockAccess, pos, side); + } + + @Override +- @Override +- public int getSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return !(Boolean) blockstate.getValue(DiodeBlock.POWERED) ? 0 : (blockstate.getValue(DiodeBlock.FACING) == direction ? this.getOutputSignal(blockgetter, blockpos, blockstate) : 0); ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return !(Boolean) blockState.getValue(DiodeBlock.POWERED) ? 0 : (blockState.getValue(DiodeBlock.FACING) == side ? this.getOutputSignal(blockAccess, pos, blockState) : 0); + } + + @Override +- @Override +- public void neighborChanged(BlockState blockstate, Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { +- if (blockstate.canSurvive(level, blockpos)) { +- this.checkTickOnNeighbor(level, blockpos, blockstate); ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ if (state.canSurvive(level, pos)) { ++ this.checkTickOnNeighbor(level, pos, state); + } else { +- BlockEntity blockentity = blockstate.hasBlockEntity() ? level.getBlockEntity(blockpos) : null; ++ BlockEntity tileentity = state.hasBlockEntity() ? level.getBlockEntity(pos) : null; + +- dropResources(blockstate, level, blockpos, blockentity); +- level.removeBlock(blockpos, false); +- Direction[] adirection = Direction.values(); +- int i = adirection.length; ++ dropResources(state, level, pos, tileentity); ++ level.removeBlock(pos, false); ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; ++ Direction enumdirection = aenumdirection[j]; + +- level.updateNeighborsAt(blockpos.relative(direction), this); ++ level.updateNeighborsAt(pos.relative(enumdirection), this); + } + + } + } + +- protected void checkTickOnNeighbor(Level level, BlockPos blockpos, BlockState blockstate) { +- if (!this.isLocked(level, blockpos, blockstate)) { +- boolean flag = (Boolean) blockstate.getValue(DiodeBlock.POWERED); +- boolean flag1 = this.shouldTurnOn(level, blockpos, blockstate); ++ protected void checkTickOnNeighbor(Level level, BlockPos pos, IBlockData state) { ++ if (!this.isLocked(level, pos, state)) { ++ boolean flag = (Boolean) state.getValue(DiodeBlock.POWERED); ++ boolean flag1 = this.shouldTurnOn(level, pos, state); + +- if (flag != flag1 && !level.getBlockTicks().willTickThisTick(blockpos, this)) { +- TickPriority tickpriority = TickPriority.HIGH; ++ if (flag != flag1 && !level.getBlockTicks().willTickThisTick(pos, this)) { ++ TickPriority ticklistpriority = TickPriority.HIGH; + +- if (this.shouldPrioritize(level, blockpos, blockstate)) { +- tickpriority = TickPriority.EXTREMELY_HIGH; ++ if (this.shouldPrioritize(level, pos, state)) { ++ ticklistpriority = TickPriority.EXTREMELY_HIGH; + } else if (flag) { +- tickpriority = TickPriority.VERY_HIGH; ++ ticklistpriority = TickPriority.VERY_HIGH; + } + +- level.scheduleTick(blockpos, (Block) this, this.getDelay(blockstate), tickpriority); ++ level.scheduleTick(pos, (Block) this, this.getDelay(state), ticklistpriority); + } + + } + } + +- public boolean isLocked(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { ++ public boolean isLocked(LevelReader level, BlockPos pos, IBlockData state) { + return false; + } + +- protected boolean shouldTurnOn(Level level, BlockPos blockpos, BlockState blockstate) { +- return this.getInputSignal(level, blockpos, blockstate) > 0; ++ protected boolean shouldTurnOn(Level level, BlockPos pos, IBlockData state) { ++ return this.getInputSignal(level, pos, state) > 0; + } + +- protected int getInputSignal(Level level, BlockPos blockpos, BlockState blockstate) { +- Direction direction = (Direction) blockstate.getValue(DiodeBlock.FACING); +- BlockPos blockpos1 = blockpos.relative(direction); +- int i = level.getSignal(blockpos1, direction); ++ protected int getInputSignal(Level level, BlockPos pos, IBlockData state) { ++ Direction enumdirection = (Direction) state.getValue(DiodeBlock.FACING); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ int i = level.getSignal(blockposition1, enumdirection); + + if (i >= 15) { + return i; + } else { +- BlockState blockstate1 = level.getBlockState(blockpos1); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + +- return Math.max(i, blockstate1.is(Blocks.REDSTONE_WIRE) ? (Integer) blockstate1.getValue(RedStoneWireBlock.POWER) : 0); ++ return Math.max(i, iblockdata1.is(Blocks.REDSTONE_WIRE) ? (Integer) iblockdata1.getValue(RedStoneWireBlock.POWER) : 0); + } + } + +- protected int getAlternateSignal(SignalGetter signalgetter, BlockPos blockpos, BlockState blockstate) { +- Direction direction = (Direction) blockstate.getValue(DiodeBlock.FACING); +- Direction direction1 = direction.getClockWise(); +- Direction direction2 = direction.getCounterClockWise(); ++ protected int getAlternateSignal(SignalGetter level, BlockPos pos, IBlockData state) { ++ Direction enumdirection = (Direction) state.getValue(DiodeBlock.FACING); ++ Direction enumdirection1 = enumdirection.getClockWise(); ++ Direction enumdirection2 = enumdirection.getCounterClockWise(); + boolean flag = this.sideInputDiodesOnly(); + +- return Math.max(signalgetter.getControlInputSignal(blockpos.relative(direction1), direction1, flag), signalgetter.getControlInputSignal(blockpos.relative(direction2), direction2, flag)); ++ return Math.max(level.getControlInputSignal(pos.relative(enumdirection1), enumdirection1, flag), level.getControlInputSignal(pos.relative(enumdirection2), enumdirection2, flag)); + } + + @Override +- @Override +- public boolean isSignalSource(BlockState blockstate) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- return (BlockState) this.defaultBlockState().setValue(DiodeBlock.FACING, blockplacecontext.getHorizontalDirection().getOpposite()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return (IBlockData) this.defaultBlockState().setValue(DiodeBlock.FACING, context.getHorizontalDirection().getOpposite()); + } + + @Override +- @Override +- public void setPlacedBy(Level level, BlockPos blockpos, BlockState blockstate, LivingEntity livingentity, ItemStack itemstack) { +- if (this.shouldTurnOn(level, blockpos, blockstate)) { +- level.scheduleTick(blockpos, (Block) this, 1); ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, LivingEntity placer, ItemStack stack) { ++ if (this.shouldTurnOn(level, pos, state)) { ++ level.scheduleTick(pos, (Block) this, 1); + } + + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- this.updateNeighborsInFront(level, blockpos, blockstate); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ this.updateNeighborsInFront(level, pos, state); + } + + @Override +- @Override +- public void onRemove(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!flag && !blockstate.is(blockstate1.getBlock())) { +- super.onRemove(blockstate, level, blockpos, blockstate1, flag); +- this.updateNeighborsInFront(level, blockpos, blockstate); ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { ++ if (!isMoving && !state.is(newState.getBlock())) { ++ super.onRemove(state, level, pos, newState, isMoving); ++ this.updateNeighborsInFront(level, pos, state); + } + } + +- protected void updateNeighborsInFront(Level level, BlockPos blockpos, BlockState blockstate) { +- Direction direction = (Direction) blockstate.getValue(DiodeBlock.FACING); +- BlockPos blockpos1 = blockpos.relative(direction.getOpposite()); ++ protected void updateNeighborsInFront(Level level, BlockPos pos, IBlockData state) { ++ Direction enumdirection = (Direction) state.getValue(DiodeBlock.FACING); ++ BlockPos blockposition1 = pos.relative(enumdirection.getOpposite()); + +- level.neighborChanged(blockpos1, this, blockpos); +- level.updateNeighborsAtExceptFromFacing(blockpos1, this, direction); ++ level.neighborChanged(blockposition1, this, pos); ++ level.updateNeighborsAtExceptFromFacing(blockposition1, this, enumdirection); + } + + protected boolean sideInputDiodesOnly() { + return false; + } + +- protected int getOutputSignal(BlockGetter blockgetter, BlockPos blockpos, BlockState blockstate) { ++ protected int getOutputSignal(BlockGetter level, BlockPos pos, IBlockData state) { + return 15; + } + +- public static boolean isDiode(BlockState blockstate) { +- return blockstate.getBlock() instanceof DiodeBlock; ++ public static boolean isDiode(IBlockData state) { ++ return state.getBlock() instanceof DiodeBlock; + } + +- public boolean shouldPrioritize(BlockGetter blockgetter, BlockPos blockpos, BlockState blockstate) { +- Direction direction = ((Direction) blockstate.getValue(DiodeBlock.FACING)).getOpposite(); +- BlockState blockstate1 = blockgetter.getBlockState(blockpos.relative(direction)); ++ public boolean shouldPrioritize(BlockGetter level, BlockPos pos, IBlockData state) { ++ Direction enumdirection = ((Direction) state.getValue(DiodeBlock.FACING)).getOpposite(); ++ IBlockData iblockdata1 = level.getBlockState(pos.relative(enumdirection)); + +- return isDiode(blockstate1) && blockstate1.getValue(DiodeBlock.FACING) != direction; ++ return isDiode(iblockdata1) && iblockdata1.getValue(DiodeBlock.FACING) != enumdirection; + } + +- protected abstract int getDelay(BlockState state); ++ protected abstract int getDelay(IBlockData state); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DispenserBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DispenserBlock.java.patch new file mode 100644 index 0000000000..5deb28528d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DispenserBlock.java.patch @@ -0,0 +1,268 @@ +--- a/net/minecraft/world/level/block/DispenserBlock.java ++++ b/net/minecraft/world/level/block/DispenserBlock.java +@@ -7,15 +7,15 @@ + import net.minecraft.Util; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.Position; +-import net.minecraft.core.dispenser.BlockSource; ++import net.minecraft.core.IPosition; + import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; + import net.minecraft.core.dispenser.DispenseItemBehavior; ++import net.minecraft.core.dispenser.SourceBlock; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.stats.Stats; + import net.minecraft.util.RandomSource; + import net.minecraft.world.Containers; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.player.Player; +@@ -23,14 +23,14 @@ + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.context.BlockPlaceContext; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.DispenserBlockEntity; +-import net.minecraft.world.level.block.entity.DropperBlockEntity; ++import net.minecraft.world.level.block.entity.TileEntityDropper; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -43,39 +43,38 @@ + + private static final Logger LOGGER = LogUtils.getLogger(); + public static final MapCodec CODEC = simpleCodec(DispenserBlock::new); +- public static final DirectionProperty FACING = DirectionalBlock.FACING; ++ public static final DirectionProperty FACING = BlockDirectional.FACING; + public static final BooleanProperty TRIGGERED = BlockStateProperties.TRIGGERED; +- private static final Map DISPENSER_REGISTRY = (Map) Util.make(new Object2ObjectOpenHashMap(), (object2objectopenhashmap) -> { ++ public static final Map DISPENSER_REGISTRY = (Map) Util.make(new Object2ObjectOpenHashMap(), (object2objectopenhashmap) -> { + object2objectopenhashmap.defaultReturnValue(new DefaultDispenseItemBehavior()); + }); + private static final int TRIGGER_DURATION = 4; ++ public static boolean eventFired = false; // CraftBukkit + + @Override +- @Override + public MapCodec codec() { + return DispenserBlock.CODEC; + } + +- public static void registerBehavior(ItemLike itemlike, DispenseItemBehavior dispenseitembehavior) { +- DispenserBlock.DISPENSER_REGISTRY.put(itemlike.asItem(), dispenseitembehavior); ++ public static void registerBehavior(IMaterial item, DispenseItemBehavior behavior) { ++ DispenserBlock.DISPENSER_REGISTRY.put(item.asItem(), behavior); + } + +- protected DispenserBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(DispenserBlock.FACING, Direction.NORTH)).setValue(DispenserBlock.TRIGGERED, false)); ++ protected DispenserBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(DispenserBlock.FACING, Direction.NORTH)).setValue(DispenserBlock.TRIGGERED, false)); + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + if (level.isClientSide) { + return InteractionResult.SUCCESS; + } else { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof DispenserBlockEntity) { +- player.openMenu((DispenserBlockEntity) blockentity); +- if (blockentity instanceof DropperBlockEntity) { ++ if (tileentity instanceof DispenserBlockEntity) { ++ player.openMenu((DispenserBlockEntity) tileentity); ++ if (tileentity instanceof TileEntityDropper) { + player.awardStat(Stats.INSPECT_DROPPER); + } else { + player.awardStat(Stats.INSPECT_DISPENSER); +@@ -86,126 +85,115 @@ + } + } + +- protected void dispenseFrom(ServerLevel serverlevel, BlockState blockstate, BlockPos blockpos) { +- DispenserBlockEntity dispenserblockentity = (DispenserBlockEntity) serverlevel.getBlockEntity(blockpos, BlockEntityType.DISPENSER).orElse((Object) null); ++ public void dispenseFrom(ServerLevel worldserver, IBlockData iblockdata, BlockPos blockposition) { ++ DispenserBlockEntity tileentitydispenser = (DispenserBlockEntity) worldserver.getBlockEntity(blockposition, BlockEntityType.DISPENSER).orElse(null); // CraftBukkit - decompile error + +- if (dispenserblockentity == null) { +- DispenserBlock.LOGGER.warn("Ignoring dispensing attempt for Dispenser without matching block entity at {}", blockpos); ++ if (tileentitydispenser == null) { ++ DispenserBlock.LOGGER.warn("Ignoring dispensing attempt for Dispenser without matching block entity at {}", blockposition); + } else { +- BlockSource blocksource = new BlockSource(serverlevel, blockpos, blockstate, dispenserblockentity); +- int i = dispenserblockentity.getRandomSlot(serverlevel.random); ++ SourceBlock sourceblock = new SourceBlock(worldserver, blockposition, iblockdata, tileentitydispenser); ++ int i = tileentitydispenser.getRandomSlot(worldserver.random); + + if (i < 0) { +- serverlevel.levelEvent(1001, blockpos, 0); +- serverlevel.gameEvent(GameEvent.BLOCK_ACTIVATE, blockpos, GameEvent.Context.of(dispenserblockentity.getBlockState())); ++ worldserver.levelEvent(1001, blockposition, 0); ++ worldserver.gameEvent(GameEvent.BLOCK_ACTIVATE, blockposition, GameEvent.Context.of(tileentitydispenser.getBlockState())); + } else { +- ItemStack itemstack = dispenserblockentity.getItem(i); +- DispenseItemBehavior dispenseitembehavior = this.getDispenseMethod(itemstack); ++ ItemStack itemstack = tileentitydispenser.getItem(i); ++ DispenseItemBehavior idispensebehavior = this.getDispenseMethod(itemstack); + +- if (dispenseitembehavior != DispenseItemBehavior.NOOP) { +- dispenserblockentity.setItem(i, dispenseitembehavior.dispense(blocksource, itemstack)); ++ if (idispensebehavior != DispenseItemBehavior.NOOP) { ++ eventFired = false; // CraftBukkit - reset event status ++ tileentitydispenser.setItem(i, idispensebehavior.dispense(sourceblock, itemstack)); + } + + } + } + } + +- protected DispenseItemBehavior getDispenseMethod(ItemStack itemstack) { +- return (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(itemstack.getItem()); ++ protected DispenseItemBehavior getDispenseMethod(ItemStack stack) { ++ return (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(stack.getItem()); + } + + @Override +- @Override +- public void neighborChanged(BlockState blockstate, Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { +- boolean flag1 = level.hasNeighborSignal(blockpos) || level.hasNeighborSignal(blockpos.above()); +- boolean flag2 = (Boolean) blockstate.getValue(DispenserBlock.TRIGGERED); ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ boolean flag1 = level.hasNeighborSignal(pos) || level.hasNeighborSignal(pos.above()); ++ boolean flag2 = (Boolean) state.getValue(DispenserBlock.TRIGGERED); + + if (flag1 && !flag2) { +- level.scheduleTick(blockpos, (Block) this, 4); +- level.setBlock(blockpos, (BlockState) blockstate.setValue(DispenserBlock.TRIGGERED, true), 2); ++ level.scheduleTick(pos, (Block) this, 4); ++ level.setBlock(pos, (IBlockData) state.setValue(DispenserBlock.TRIGGERED, true), 2); + } else if (!flag1 && flag2) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(DispenserBlock.TRIGGERED, false), 2); ++ level.setBlock(pos, (IBlockData) state.setValue(DispenserBlock.TRIGGERED, false), 2); + } + + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- this.dispenseFrom(serverlevel, blockstate, blockpos); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ this.dispenseFrom(level, state, pos); + } + + @Override +- @Override +- public BlockEntity newBlockEntity(BlockPos blockpos, BlockState blockstate) { +- return new DispenserBlockEntity(blockpos, blockstate); ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ return new DispenserBlockEntity(pos, state); + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- return (BlockState) this.defaultBlockState().setValue(DispenserBlock.FACING, blockplacecontext.getNearestLookingDirection().getOpposite()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return (IBlockData) this.defaultBlockState().setValue(DispenserBlock.FACING, context.getNearestLookingDirection().getOpposite()); + } + + @Override +- @Override +- public void setPlacedBy(Level level, BlockPos blockpos, BlockState blockstate, LivingEntity livingentity, ItemStack itemstack) { +- if (itemstack.hasCustomHoverName()) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, LivingEntity placer, ItemStack stack) { ++ if (stack.hasCustomHoverName()) { ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof DispenserBlockEntity) { +- ((DispenserBlockEntity) blockentity).setCustomName(itemstack.getHoverName()); ++ if (tileentity instanceof DispenserBlockEntity) { ++ ((DispenserBlockEntity) tileentity).setCustomName(stack.getHoverName()); + } + } + + } + + @Override +- @Override +- public void onRemove(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- Containers.dropContentsOnDestroy(blockstate, blockstate1, level, blockpos); +- super.onRemove(blockstate, level, blockpos, blockstate1, flag); ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { ++ Containers.dropContentsOnDestroy(state, newState, level, pos); ++ super.onRemove(state, level, pos, newState, isMoving); + } + +- public static Position getDispensePosition(BlockSource blocksource) { +- Direction direction = (Direction) blocksource.state().getValue(DispenserBlock.FACING); ++ public static IPosition getDispensePosition(SourceBlock sourceblock) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); + +- return blocksource.center().add(0.7D * (double) direction.getStepX(), 0.7D * (double) direction.getStepY(), 0.7D * (double) direction.getStepZ()); ++ return sourceblock.center().add(0.7D * (double) enumdirection.getStepX(), 0.7D * (double) enumdirection.getStepY(), 0.7D * (double) enumdirection.getStepZ()); + } + + @Override +- @Override +- public boolean hasAnalogOutputSignal(BlockState blockstate) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return true; + } + + @Override +- @Override +- public int getAnalogOutputSignal(BlockState blockstate, Level level, BlockPos blockpos) { +- return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(blockpos)); ++ public int getAnalogOutputSignal(IBlockData blockState, Level level, BlockPos pos) { ++ return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos)); + } + + @Override +- @Override +- public RenderShape getRenderShape(BlockState blockstate) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Override +- @Override +- public BlockState rotate(BlockState blockstate, Rotation rotation) { +- return (BlockState) blockstate.setValue(DispenserBlock.FACING, rotation.rotate((Direction) blockstate.getValue(DispenserBlock.FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return (IBlockData) state.setValue(DispenserBlock.FACING, rotation.rotate((Direction) state.getValue(DispenserBlock.FACING))); + } + + @Override +- @Override +- public BlockState mirror(BlockState blockstate, Mirror mirror) { +- return blockstate.rotate(mirror.getRotation((Direction) blockstate.getValue(DispenserBlock.FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(DispenserBlock.FACING))); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(DispenserBlock.FACING, DispenserBlock.TRIGGERED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(DispenserBlock.FACING, DispenserBlock.TRIGGERED); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DoorBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DoorBlock.java.patch new file mode 100644 index 0000000000..383ce67a8d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DoorBlock.java.patch @@ -0,0 +1,388 @@ +--- a/net/minecraft/world/level/block/DoorBlock.java ++++ b/net/minecraft/world/level/block/DoorBlock.java +@@ -8,7 +8,7 @@ + import net.minecraft.core.Direction; + import net.minecraft.sounds.SoundSource; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; +@@ -21,21 +21,22 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; ++import net.minecraft.world.level.block.state.properties.BlockPropertyDoorHinge; ++import net.minecraft.world.level.block.state.properties.BlockPropertyDoubleBlockHalf; + import net.minecraft.world.level.block.state.properties.BlockSetType; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.block.state.properties.DirectionProperty; +-import net.minecraft.world.level.block.state.properties.DoorHingeSide; +-import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; + import net.minecraft.world.level.block.state.properties.EnumProperty; + import net.minecraft.world.level.gameevent.GameEvent; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class DoorBlock extends Block { + +@@ -44,9 +45,9 @@ + }); + public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING; + public static final BooleanProperty OPEN = BlockStateProperties.OPEN; +- public static final EnumProperty HINGE = BlockStateProperties.DOOR_HINGE; ++ public static final EnumProperty HINGE = BlockStateProperties.DOOR_HINGE; + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; +- public static final EnumProperty HALF = BlockStateProperties.DOUBLE_BLOCK_HALF; ++ public static final EnumProperty HALF = BlockStateProperties.DOUBLE_BLOCK_HALF; + protected static final float AABB_DOOR_THICKNESS = 3.0F; + protected static final VoxelShape SOUTH_AABB = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 16.0D, 3.0D); + protected static final VoxelShape NORTH_AABB = Block.box(0.0D, 0.0D, 13.0D, 16.0D, 16.0D, 16.0D); +@@ -55,15 +56,14 @@ + private final BlockSetType type; + + @Override +- @Override + public MapCodec codec() { + return DoorBlock.CODEC; + } + +- protected DoorBlock(BlockSetType blocksettype, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties.sound(blocksettype.soundType())); ++ protected DoorBlock(BlockSetType blocksettype, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info.sound(blocksettype.soundType())); + this.type = blocksettype; +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(DoorBlock.FACING, Direction.NORTH)).setValue(DoorBlock.OPEN, false)).setValue(DoorBlock.HINGE, DoorHingeSide.LEFT)).setValue(DoorBlock.POWERED, false)).setValue(DoorBlock.HALF, DoubleBlockHalf.LOWER)); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(DoorBlock.FACING, Direction.NORTH)).setValue(DoorBlock.OPEN, false)).setValue(DoorBlock.HINGE, BlockPropertyDoorHinge.LEFT)).setValue(DoorBlock.POWERED, false)).setValue(DoorBlock.HALF, BlockPropertyDoubleBlockHalf.LOWER)); + } + + public BlockSetType type() { +@@ -71,14 +71,13 @@ + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- Direction direction = (Direction) blockstate.getValue(DoorBlock.FACING); +- boolean flag = !(Boolean) blockstate.getValue(DoorBlock.OPEN); +- boolean flag1 = blockstate.getValue(DoorBlock.HINGE) == DoorHingeSide.RIGHT; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ Direction enumdirection = (Direction) state.getValue(DoorBlock.FACING); ++ boolean flag = !(Boolean) state.getValue(DoorBlock.OPEN); ++ boolean flag1 = state.getValue(DoorBlock.HINGE) == BlockPropertyDoorHinge.RIGHT; + VoxelShape voxelshape; + +- switch (direction) { ++ switch (enumdirection) { + case SOUTH: + voxelshape = flag ? DoorBlock.SOUTH_AABB : (flag1 ? DoorBlock.EAST_AABB : DoorBlock.WEST_AABB); + break; +@@ -96,42 +95,38 @@ + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- DoubleBlockHalf doubleblockhalf = (DoubleBlockHalf) blockstate.getValue(DoorBlock.HALF); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ BlockPropertyDoubleBlockHalf blockpropertydoubleblockhalf = (BlockPropertyDoubleBlockHalf) state.getValue(DoorBlock.HALF); + +- return direction.getAxis() == Direction.Axis.Y && doubleblockhalf == DoubleBlockHalf.LOWER == (direction == Direction.UP) ? (blockstate1.getBlock() instanceof DoorBlock && blockstate1.getValue(DoorBlock.HALF) != doubleblockhalf ? (BlockState) blockstate1.setValue(DoorBlock.HALF, doubleblockhalf) : Blocks.AIR.defaultBlockState()) : (doubleblockhalf == DoubleBlockHalf.LOWER && direction == Direction.DOWN && !blockstate.canSurvive(levelaccessor, blockpos) ? Blocks.AIR.defaultBlockState() : super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1)); ++ return facing.getAxis() == Direction.Axis.Y && blockpropertydoubleblockhalf == BlockPropertyDoubleBlockHalf.LOWER == (facing == Direction.UP) ? (facingState.getBlock() instanceof DoorBlock && facingState.getValue(DoorBlock.HALF) != blockpropertydoubleblockhalf ? (IBlockData) facingState.setValue(DoorBlock.HALF, blockpropertydoubleblockhalf) : Blocks.AIR.defaultBlockState()) : (blockpropertydoubleblockhalf == BlockPropertyDoubleBlockHalf.LOWER && facing == Direction.DOWN && !state.canSurvive(level, currentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, level, currentPos, facingPos)); + } + + @Override +- @Override +- public void onExplosionHit(BlockState blockstate, Level level, BlockPos blockpos, Explosion explosion, BiConsumer biconsumer) { +- if (explosion.getBlockInteraction() == Explosion.BlockInteraction.TRIGGER_BLOCK && blockstate.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER && !level.isClientSide() && this.type.canOpenByWindCharge() && !(Boolean) blockstate.getValue(DoorBlock.POWERED)) { +- this.setOpen((Entity) null, level, blockstate, blockpos, !this.isOpen(blockstate)); ++ public void onExplosionHit(IBlockData iblockdata, Level world, BlockPos blockposition, Explosion explosion, BiConsumer biconsumer) { ++ if (explosion.getBlockInteraction() == Explosion.Effect.TRIGGER_BLOCK && iblockdata.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER && !world.isClientSide() && this.type.canOpenByWindCharge() && !(Boolean) iblockdata.getValue(DoorBlock.POWERED)) { ++ this.setOpen((Entity) null, world, iblockdata, blockposition, !this.isOpen(iblockdata)); + } + +- super.onExplosionHit(blockstate, level, blockpos, explosion, biconsumer); ++ super.onExplosionHit(iblockdata, world, blockposition, explosion, biconsumer); + } + + @Override +- @Override +- public BlockState playerWillDestroy(Level level, BlockPos blockpos, BlockState blockstate, Player player) { +- if (!level.isClientSide && (player.isCreative() || !player.hasCorrectToolForDrops(blockstate))) { +- DoublePlantBlock.preventDropFromBottomPart(level, blockpos, blockstate, player); ++ public IBlockData playerWillDestroy(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ if (!world.isClientSide && (entityhuman.isCreative() || !entityhuman.hasCorrectToolForDrops(iblockdata))) { ++ DoublePlantBlock.preventDropFromBottomPart(world, blockposition, iblockdata, entityhuman); + } + +- return super.playerWillDestroy(level, blockpos, blockstate, player); ++ return super.playerWillDestroy(world, blockposition, iblockdata, entityhuman); + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + boolean flag; + +- switch (pathcomputationtype) { ++ switch (type) { + case LAND: + case AIR: +- flag = (Boolean) blockstate.getValue(DoorBlock.OPEN); ++ flag = (Boolean) state.getValue(DoorBlock.OPEN); + break; + case WATER: + flag = false; +@@ -145,153 +140,159 @@ + + @Nullable + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- BlockPos blockpos = blockplacecontext.getClickedPos(); +- Level level = blockplacecontext.getLevel(); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ BlockPos blockposition = context.getClickedPos(); ++ Level world = context.getLevel(); + +- if (blockpos.getY() < level.getMaxBuildHeight() - 1 && level.getBlockState(blockpos.above()).canBeReplaced(blockplacecontext)) { +- boolean flag = level.hasNeighborSignal(blockpos) || level.hasNeighborSignal(blockpos.above()); ++ if (blockposition.getY() < world.getMaxBuildHeight() - 1 && world.getBlockState(blockposition.above()).canBeReplaced(context)) { ++ boolean flag = world.hasNeighborSignal(blockposition) || world.hasNeighborSignal(blockposition.above()); + +- return (BlockState) ((BlockState) ((BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(DoorBlock.FACING, blockplacecontext.getHorizontalDirection())).setValue(DoorBlock.HINGE, this.getHinge(blockplacecontext))).setValue(DoorBlock.POWERED, flag)).setValue(DoorBlock.OPEN, flag)).setValue(DoorBlock.HALF, DoubleBlockHalf.LOWER); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(DoorBlock.FACING, context.getHorizontalDirection())).setValue(DoorBlock.HINGE, this.getHinge(context))).setValue(DoorBlock.POWERED, flag)).setValue(DoorBlock.OPEN, flag)).setValue(DoorBlock.HALF, BlockPropertyDoubleBlockHalf.LOWER); + } else { + return null; + } + } + + @Override +- @Override +- public void setPlacedBy(Level level, BlockPos blockpos, BlockState blockstate, LivingEntity livingentity, ItemStack itemstack) { +- level.setBlock(blockpos.above(), (BlockState) blockstate.setValue(DoorBlock.HALF, DoubleBlockHalf.UPPER), 3); ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, LivingEntity placer, ItemStack stack) { ++ level.setBlock(pos.above(), (IBlockData) state.setValue(DoorBlock.HALF, BlockPropertyDoubleBlockHalf.UPPER), 3); + } + +- private DoorHingeSide getHinge(BlockPlaceContext blockplacecontext) { +- Level level = blockplacecontext.getLevel(); +- BlockPos blockpos = blockplacecontext.getClickedPos(); +- Direction direction = blockplacecontext.getHorizontalDirection(); +- BlockPos blockpos1 = blockpos.above(); +- Direction direction1 = direction.getCounterClockWise(); +- BlockPos blockpos2 = blockpos.relative(direction1); +- BlockState blockstate = level.getBlockState(blockpos2); +- BlockPos blockpos3 = blockpos1.relative(direction1); +- BlockState blockstate1 = level.getBlockState(blockpos3); +- Direction direction2 = direction.getClockWise(); +- BlockPos blockpos4 = blockpos.relative(direction2); +- BlockState blockstate2 = level.getBlockState(blockpos4); +- BlockPos blockpos5 = blockpos1.relative(direction2); +- BlockState blockstate3 = level.getBlockState(blockpos5); +- int i = (blockstate.isCollisionShapeFullBlock(level, blockpos2) ? -1 : 0) + (blockstate1.isCollisionShapeFullBlock(level, blockpos3) ? -1 : 0) + (blockstate2.isCollisionShapeFullBlock(level, blockpos4) ? 1 : 0) + (blockstate3.isCollisionShapeFullBlock(level, blockpos5) ? 1 : 0); +- boolean flag = blockstate.is((Block) this) && blockstate.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER; +- boolean flag1 = blockstate2.is((Block) this) && blockstate2.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER; ++ private BlockPropertyDoorHinge getHinge(BlockPlaceContext context) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ Direction enumdirection = context.getHorizontalDirection(); ++ BlockPos blockposition1 = blockposition.above(); ++ Direction enumdirection1 = enumdirection.getCounterClockWise(); ++ BlockPos blockposition2 = blockposition.relative(enumdirection1); ++ IBlockData iblockdata = world.getBlockState(blockposition2); ++ BlockPos blockposition3 = blockposition1.relative(enumdirection1); ++ IBlockData iblockdata1 = world.getBlockState(blockposition3); ++ Direction enumdirection2 = enumdirection.getClockWise(); ++ BlockPos blockposition4 = blockposition.relative(enumdirection2); ++ IBlockData iblockdata2 = world.getBlockState(blockposition4); ++ BlockPos blockposition5 = blockposition1.relative(enumdirection2); ++ IBlockData iblockdata3 = world.getBlockState(blockposition5); ++ int i = (iblockdata.isCollisionShapeFullBlock(world, blockposition2) ? -1 : 0) + (iblockdata1.isCollisionShapeFullBlock(world, blockposition3) ? -1 : 0) + (iblockdata2.isCollisionShapeFullBlock(world, blockposition4) ? 1 : 0) + (iblockdata3.isCollisionShapeFullBlock(world, blockposition5) ? 1 : 0); ++ boolean flag = iblockdata.is((Block) this) && iblockdata.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER; ++ boolean flag1 = iblockdata2.is((Block) this) && iblockdata2.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER; + + if ((!flag || flag1) && i <= 0) { + if ((!flag1 || flag) && i >= 0) { +- int j = direction.getStepX(); +- int k = direction.getStepZ(); +- Vec3 vec3 = blockplacecontext.getClickLocation(); +- double d0 = vec3.x - (double) blockpos.getX(); +- double d1 = vec3.z - (double) blockpos.getZ(); ++ int j = enumdirection.getStepX(); ++ int k = enumdirection.getStepZ(); ++ Vec3 vec3d = context.getClickLocation(); ++ double d0 = vec3d.x - (double) blockposition.getX(); ++ double d1 = vec3d.z - (double) blockposition.getZ(); + +- return (j >= 0 || d1 >= 0.5D) && (j <= 0 || d1 <= 0.5D) && (k >= 0 || d0 <= 0.5D) && (k <= 0 || d0 >= 0.5D) ? DoorHingeSide.LEFT : DoorHingeSide.RIGHT; ++ return (j >= 0 || d1 >= 0.5D) && (j <= 0 || d1 <= 0.5D) && (k >= 0 || d0 <= 0.5D) && (k <= 0 || d0 >= 0.5D) ? BlockPropertyDoorHinge.LEFT : BlockPropertyDoorHinge.RIGHT; + } else { +- return DoorHingeSide.LEFT; ++ return BlockPropertyDoorHinge.LEFT; + } + } else { +- return DoorHingeSide.RIGHT; ++ return BlockPropertyDoorHinge.RIGHT; + } + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + if (!this.type.canOpenByHand()) { + return InteractionResult.PASS; + } else { +- blockstate = (BlockState) blockstate.cycle(DoorBlock.OPEN); +- level.setBlock(blockpos, blockstate, 10); +- this.playSound(player, level, blockpos, (Boolean) blockstate.getValue(DoorBlock.OPEN)); +- level.gameEvent((Entity) player, this.isOpen(blockstate) ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, blockpos); ++ state = (IBlockData) state.cycle(DoorBlock.OPEN); ++ level.setBlock(pos, state, 10); ++ this.playSound(player, level, pos, (Boolean) state.getValue(DoorBlock.OPEN)); ++ level.gameEvent((Entity) player, this.isOpen(state) ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); + return InteractionResult.sidedSuccess(level.isClientSide); + } + } + +- public boolean isOpen(BlockState blockstate) { +- return (Boolean) blockstate.getValue(DoorBlock.OPEN); ++ public boolean isOpen(IBlockData state) { ++ return (Boolean) state.getValue(DoorBlock.OPEN); + } + +- public void setOpen(@Nullable Entity entity, Level level, BlockState blockstate, BlockPos blockpos, boolean flag) { +- if (blockstate.is((Block) this) && (Boolean) blockstate.getValue(DoorBlock.OPEN) != flag) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(DoorBlock.OPEN, flag), 10); +- this.playSound(entity, level, blockpos, flag); +- level.gameEvent(entity, flag ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, blockpos); ++ public void setOpen(@Nullable Entity entity, Level level, IBlockData state, BlockPos pos, boolean open) { ++ if (state.is((Block) this) && (Boolean) state.getValue(DoorBlock.OPEN) != open) { ++ level.setBlock(pos, (IBlockData) state.setValue(DoorBlock.OPEN, open), 10); ++ this.playSound(entity, level, pos, open); ++ level.gameEvent(entity, open ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); + } + } + + @Override +- @Override +- public void neighborChanged(BlockState blockstate, Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { +- boolean flag1 = level.hasNeighborSignal(blockpos) || level.hasNeighborSignal(blockpos.relative(blockstate.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER ? Direction.UP : Direction.DOWN)); ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ // CraftBukkit start ++ BlockPos otherHalf = pos.relative(state.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER ? Direction.UP : Direction.DOWN); + +- if (!this.defaultBlockState().is(block) && flag1 != (Boolean) blockstate.getValue(DoorBlock.POWERED)) { +- if (flag1 != (Boolean) blockstate.getValue(DoorBlock.OPEN)) { +- this.playSound((Entity) null, level, blockpos, flag1); +- level.gameEvent((Entity) null, flag1 ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, blockpos); ++ org.bukkit.World bworld = level.getWorld(); ++ org.bukkit.block.Block bukkitBlock = bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ org.bukkit.block.Block blockTop = bworld.getBlockAt(otherHalf.getX(), otherHalf.getY(), otherHalf.getZ()); ++ ++ int power = bukkitBlock.getBlockPower(); ++ int powerTop = blockTop.getBlockPower(); ++ if (powerTop > power) power = powerTop; ++ int oldPower = (Boolean) state.getValue(DoorBlock.POWERED) ? 15 : 0; ++ ++ if (oldPower == 0 ^ power == 0) { ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bukkitBlock, oldPower, power); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ boolean flag1 = eventRedstone.getNewCurrent() > 0; ++ // CraftBukkit end ++ if (flag1 != (Boolean) state.getValue(DoorBlock.OPEN)) { ++ this.playSound((Entity) null, level, pos, flag1); ++ level.gameEvent((Entity) null, flag1 ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); + } + +- level.setBlock(blockpos, (BlockState) ((BlockState) blockstate.setValue(DoorBlock.POWERED, flag1)).setValue(DoorBlock.OPEN, flag1), 2); ++ level.setBlock(pos, (IBlockData) ((IBlockData) state.setValue(DoorBlock.POWERED, flag1)).setValue(DoorBlock.OPEN, flag1), 2); + } + + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- BlockPos blockpos1 = blockpos.below(); +- BlockState blockstate1 = levelreader.getBlockState(blockpos1); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + +- return blockstate.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER ? blockstate1.isFaceSturdy(levelreader, blockpos1, Direction.UP) : blockstate1.is((Block) this); ++ return state.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER ? iblockdata1.isFaceSturdy(level, blockposition1, Direction.UP) : iblockdata1.is((Block) this); + } + +- private void playSound(@Nullable Entity entity, Level level, BlockPos blockpos, boolean flag) { +- level.playSound(entity, blockpos, flag ? this.type.doorOpen() : this.type.doorClose(), SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.1F + 0.9F); ++ private void playSound(@Nullable Entity source, Level level, BlockPos pos, boolean isOpening) { ++ level.playSound(source, pos, isOpening ? this.type.doorOpen() : this.type.doorClose(), SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.1F + 0.9F); + } + + @Override +- @Override +- public BlockState rotate(BlockState blockstate, Rotation rotation) { +- return (BlockState) blockstate.setValue(DoorBlock.FACING, rotation.rotate((Direction) blockstate.getValue(DoorBlock.FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return (IBlockData) state.setValue(DoorBlock.FACING, rotation.rotate((Direction) state.getValue(DoorBlock.FACING))); + } + + @Override +- @Override +- public BlockState mirror(BlockState blockstate, Mirror mirror) { +- return mirror == Mirror.NONE ? blockstate : (BlockState) blockstate.rotate(mirror.getRotation((Direction) blockstate.getValue(DoorBlock.FACING))).cycle(DoorBlock.HINGE); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return mirror == Mirror.NONE ? state : (IBlockData) state.rotate(mirror.getRotation((Direction) state.getValue(DoorBlock.FACING))).cycle(DoorBlock.HINGE); + } + + @Override +- @Override +- public long getSeed(BlockState blockstate, BlockPos blockpos) { +- return Mth.getSeed(blockpos.getX(), blockpos.below(blockstate.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER ? 0 : 1).getY(), blockpos.getZ()); ++ public long getSeed(IBlockData state, BlockPos pos) { ++ return Mth.getSeed(pos.getX(), pos.below(state.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER ? 0 : 1).getY(), pos.getZ()); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(DoorBlock.HALF, DoorBlock.FACING, DoorBlock.OPEN, DoorBlock.HINGE, DoorBlock.POWERED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(DoorBlock.HALF, DoorBlock.FACING, DoorBlock.OPEN, DoorBlock.HINGE, DoorBlock.POWERED); + } + +- public static boolean isWoodenDoor(Level level, BlockPos blockpos) { +- return isWoodenDoor(level.getBlockState(blockpos)); ++ public static boolean isWoodenDoor(Level level, BlockPos pos) { ++ return isWoodenDoor(level.getBlockState(pos)); + } + +- public static boolean isWoodenDoor(BlockState blockstate) { +- Block block = blockstate.getBlock(); ++ public static boolean isWoodenDoor(IBlockData state) { ++ Block block = state.getBlock(); + boolean flag; + + if (block instanceof DoorBlock) { +- DoorBlock doorblock = (DoorBlock) block; ++ DoorBlock blockdoor = (DoorBlock) block; + +- if (doorblock.type().canOpenByHand()) { ++ if (blockdoor.type().canOpenByHand()) { + flag = true; + return flag; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DoublePlantBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DoublePlantBlock.java.patch new file mode 100644 index 0000000000..4321cd8ff5 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DoublePlantBlock.java.patch @@ -0,0 +1,181 @@ +--- a/net/minecraft/world/level/block/DoublePlantBlock.java ++++ b/net/minecraft/world/level/block/DoublePlantBlock.java +@@ -14,10 +14,10 @@ + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; ++import net.minecraft.world.level.block.state.properties.BlockPropertyDoubleBlockHalf; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; +-import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; + import net.minecraft.world.level.block.state.properties.EnumProperty; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; +@@ -25,114 +25,110 @@ + public class DoublePlantBlock extends BushBlock { + + public static final MapCodec CODEC = simpleCodec(DoublePlantBlock::new); +- public static final EnumProperty HALF = BlockStateProperties.DOUBLE_BLOCK_HALF; ++ public static final EnumProperty HALF = BlockStateProperties.DOUBLE_BLOCK_HALF; + + @Override +- @Override + public MapCodec codec() { + return DoublePlantBlock.CODEC; + } + +- public DoublePlantBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(DoublePlantBlock.HALF, DoubleBlockHalf.LOWER)); ++ public DoublePlantBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(DoublePlantBlock.HALF, BlockPropertyDoubleBlockHalf.LOWER)); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- DoubleBlockHalf doubleblockhalf = (DoubleBlockHalf) blockstate.getValue(DoublePlantBlock.HALF); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ BlockPropertyDoubleBlockHalf blockpropertydoubleblockhalf = (BlockPropertyDoubleBlockHalf) state.getValue(DoublePlantBlock.HALF); + +- return direction.getAxis() == Direction.Axis.Y && doubleblockhalf == DoubleBlockHalf.LOWER == (direction == Direction.UP) && (!blockstate1.is((Block) this) || blockstate1.getValue(DoublePlantBlock.HALF) == doubleblockhalf) ? Blocks.AIR.defaultBlockState() : (doubleblockhalf == DoubleBlockHalf.LOWER && direction == Direction.DOWN && !blockstate.canSurvive(levelaccessor, blockpos) ? Blocks.AIR.defaultBlockState() : super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1)); ++ return facing.getAxis() == Direction.Axis.Y && blockpropertydoubleblockhalf == BlockPropertyDoubleBlockHalf.LOWER == (facing == Direction.UP) && (!facingState.is((Block) this) || facingState.getValue(DoublePlantBlock.HALF) == blockpropertydoubleblockhalf) ? Blocks.AIR.defaultBlockState() : (blockpropertydoubleblockhalf == BlockPropertyDoubleBlockHalf.LOWER && facing == Direction.DOWN && !state.canSurvive(level, currentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, level, currentPos, facingPos)); + } + + @Nullable + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- BlockPos blockpos = blockplacecontext.getClickedPos(); +- Level level = blockplacecontext.getLevel(); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ BlockPos blockposition = context.getClickedPos(); ++ Level world = context.getLevel(); + +- return blockpos.getY() < level.getMaxBuildHeight() - 1 && level.getBlockState(blockpos.above()).canBeReplaced(blockplacecontext) ? super.getStateForPlacement(blockplacecontext) : null; ++ return blockposition.getY() < world.getMaxBuildHeight() - 1 && world.getBlockState(blockposition.above()).canBeReplaced(context) ? super.getStateForPlacement(context) : null; + } + + @Override +- @Override +- public void setPlacedBy(Level level, BlockPos blockpos, BlockState blockstate, LivingEntity livingentity, ItemStack itemstack) { +- BlockPos blockpos1 = blockpos.above(); ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, LivingEntity placer, ItemStack stack) { ++ BlockPos blockposition1 = pos.above(); + +- level.setBlock(blockpos1, copyWaterloggedFrom(level, blockpos1, (BlockState) this.defaultBlockState().setValue(DoublePlantBlock.HALF, DoubleBlockHalf.UPPER)), 3); ++ level.setBlock(blockposition1, copyWaterloggedFrom(level, blockposition1, (IBlockData) this.defaultBlockState().setValue(DoublePlantBlock.HALF, BlockPropertyDoubleBlockHalf.UPPER)), 3); + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- if (blockstate.getValue(DoublePlantBlock.HALF) != DoubleBlockHalf.UPPER) { +- return super.canSurvive(blockstate, levelreader, blockpos); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ if (state.getValue(DoublePlantBlock.HALF) != BlockPropertyDoubleBlockHalf.UPPER) { ++ return super.canSurvive(state, level, pos); + } else { +- BlockState blockstate1 = levelreader.getBlockState(blockpos.below()); ++ IBlockData iblockdata1 = level.getBlockState(pos.below()); + +- return blockstate1.is((Block) this) && blockstate1.getValue(DoublePlantBlock.HALF) == DoubleBlockHalf.LOWER; ++ return iblockdata1.is((Block) this) && iblockdata1.getValue(DoublePlantBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER; + } + } + +- public static void placeAt(LevelAccessor levelaccessor, BlockState blockstate, BlockPos blockpos, int i) { +- BlockPos blockpos1 = blockpos.above(); ++ public static void placeAt(LevelAccessor level, IBlockData state, BlockPos pos, int flags) { ++ BlockPos blockposition1 = pos.above(); + +- levelaccessor.setBlock(blockpos, copyWaterloggedFrom(levelaccessor, blockpos, (BlockState) blockstate.setValue(DoublePlantBlock.HALF, DoubleBlockHalf.LOWER)), i); +- levelaccessor.setBlock(blockpos1, copyWaterloggedFrom(levelaccessor, blockpos1, (BlockState) blockstate.setValue(DoublePlantBlock.HALF, DoubleBlockHalf.UPPER)), i); ++ level.setBlock(pos, copyWaterloggedFrom(level, pos, (IBlockData) state.setValue(DoublePlantBlock.HALF, BlockPropertyDoubleBlockHalf.LOWER)), flags); ++ level.setBlock(blockposition1, copyWaterloggedFrom(level, blockposition1, (IBlockData) state.setValue(DoublePlantBlock.HALF, BlockPropertyDoubleBlockHalf.UPPER)), flags); + } + +- public static BlockState copyWaterloggedFrom(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { +- return blockstate.hasProperty(BlockStateProperties.WATERLOGGED) ? (BlockState) blockstate.setValue(BlockStateProperties.WATERLOGGED, levelreader.isWaterAt(blockpos)) : blockstate; ++ public static IBlockData copyWaterloggedFrom(LevelReader level, BlockPos pos, IBlockData state) { ++ return state.hasProperty(BlockStateProperties.WATERLOGGED) ? (IBlockData) state.setValue(BlockStateProperties.WATERLOGGED, level.isWaterAt(pos)) : state; + } + + @Override +- @Override +- public BlockState playerWillDestroy(Level level, BlockPos blockpos, BlockState blockstate, Player player) { +- if (!level.isClientSide) { +- if (player.isCreative()) { +- preventDropFromBottomPart(level, blockpos, blockstate, player); ++ public IBlockData playerWillDestroy(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ if (!world.isClientSide) { ++ if (entityhuman.isCreative()) { ++ preventDropFromBottomPart(world, blockposition, iblockdata, entityhuman); + } else { +- dropResources(blockstate, level, blockpos, (BlockEntity) null, player, player.getMainHandItem()); ++ dropResources(iblockdata, world, blockposition, (BlockEntity) null, entityhuman, entityhuman.getMainHandItem()); + } + } + +- return super.playerWillDestroy(level, blockpos, blockstate, player); ++ return super.playerWillDestroy(world, blockposition, iblockdata, entityhuman); + } + + @Override +- @Override +- public void playerDestroy(Level level, Player player, BlockPos blockpos, BlockState blockstate, @Nullable BlockEntity blockentity, ItemStack itemstack) { +- super.playerDestroy(level, player, blockpos, Blocks.AIR.defaultBlockState(), blockentity, itemstack); ++ public void playerDestroy(Level level, Player player, BlockPos pos, IBlockData state, @Nullable BlockEntity te, ItemStack stack) { ++ super.playerDestroy(level, player, pos, Blocks.AIR.defaultBlockState(), te, stack); + } + +- protected static void preventDropFromBottomPart(Level level, BlockPos blockpos, BlockState blockstate, Player player) { +- DoubleBlockHalf doubleblockhalf = (DoubleBlockHalf) blockstate.getValue(DoublePlantBlock.HALF); ++ protected static void preventDropFromBottomPart(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, blockposition).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ BlockPropertyDoubleBlockHalf blockpropertydoubleblockhalf = (BlockPropertyDoubleBlockHalf) iblockdata.getValue(DoublePlantBlock.HALF); + +- if (doubleblockhalf == DoubleBlockHalf.UPPER) { +- BlockPos blockpos1 = blockpos.below(); +- BlockState blockstate1 = level.getBlockState(blockpos1); ++ if (blockpropertydoubleblockhalf == BlockPropertyDoubleBlockHalf.UPPER) { ++ BlockPos blockposition1 = blockposition.below(); ++ IBlockData iblockdata1 = world.getBlockState(blockposition1); + +- if (blockstate1.is(blockstate.getBlock()) && blockstate1.getValue(DoublePlantBlock.HALF) == DoubleBlockHalf.LOWER) { +- BlockState blockstate2 = blockstate1.getFluidState().is((Fluid) Fluids.WATER) ? Blocks.WATER.defaultBlockState() : Blocks.AIR.defaultBlockState(); ++ if (iblockdata1.is(iblockdata.getBlock()) && iblockdata1.getValue(DoublePlantBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER) { ++ IBlockData iblockdata2 = iblockdata1.getFluidState().is((Fluid) Fluids.WATER) ? Blocks.WATER.defaultBlockState() : Blocks.AIR.defaultBlockState(); + +- level.setBlock(blockpos1, blockstate2, 35); +- level.levelEvent(player, 2001, blockpos1, Block.getId(blockstate1)); ++ world.setBlock(blockposition1, iblockdata2, 35); ++ world.levelEvent(entityhuman, 2001, blockposition1, Block.getId(iblockdata1)); + } + } + + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(DoublePlantBlock.HALF); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(DoublePlantBlock.HALF); + } + + @Override +- @Override +- public long getSeed(BlockState blockstate, BlockPos blockpos) { +- return Mth.getSeed(blockpos.getX(), blockpos.below(blockstate.getValue(DoublePlantBlock.HALF) == DoubleBlockHalf.LOWER ? 0 : 1).getY(), blockpos.getZ()); ++ public long getSeed(IBlockData state, BlockPos pos) { ++ return Mth.getSeed(pos.getX(), pos.below(state.getValue(DoublePlantBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER ? 0 : 1).getY(), pos.getZ()); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DragonEggBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DragonEggBlock.java.patch new file mode 100644 index 0000000000..5aae14af92 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DragonEggBlock.java.patch @@ -0,0 +1,125 @@ +--- a/net/minecraft/world/level/block/DragonEggBlock.java ++++ b/net/minecraft/world/level/block/DragonEggBlock.java +@@ -4,18 +4,19 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.border.WorldBorder; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockFromToEvent; // CraftBukkit + + public class DragonEggBlock extends FallingBlock { + +@@ -23,56 +24,64 @@ + protected static final VoxelShape SHAPE = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 16.0D, 15.0D); + + @Override +- @Override + public MapCodec codec() { + return DragonEggBlock.CODEC; + } + +- public DragonEggBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ public DragonEggBlock(BlockBehaviour.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return DragonEggBlock.SHAPE; + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- this.teleport(blockstate, level, blockpos); ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ this.teleport(state, level, pos); + return InteractionResult.sidedSuccess(level.isClientSide); + } + + @Override +- @Override +- public void attack(BlockState blockstate, Level level, BlockPos blockpos, Player player) { +- this.teleport(blockstate, level, blockpos); ++ public void attack(IBlockData state, Level level, BlockPos pos, Player player) { ++ this.teleport(state, level, pos); + } + +- private void teleport(BlockState blockstate, Level level, BlockPos blockpos) { ++ private void teleport(IBlockData state, Level level, BlockPos pos) { + WorldBorder worldborder = level.getWorldBorder(); + + for (int i = 0; i < 1000; ++i) { +- BlockPos blockpos1 = blockpos.offset(level.random.nextInt(16) - level.random.nextInt(16), level.random.nextInt(8) - level.random.nextInt(8), level.random.nextInt(16) - level.random.nextInt(16)); ++ BlockPos blockposition1 = pos.offset(level.random.nextInt(16) - level.random.nextInt(16), level.random.nextInt(8) - level.random.nextInt(8), level.random.nextInt(16) - level.random.nextInt(16)); + +- if (level.getBlockState(blockpos1).isAir() && worldborder.isWithinBounds(blockpos1)) { ++ if (level.getBlockState(blockposition1).isAir() && worldborder.isWithinBounds(blockposition1)) { ++ // CraftBukkit start ++ org.bukkit.block.Block from = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ org.bukkit.block.Block to = level.getWorld().getBlockAt(blockposition1.getX(), blockposition1.getY(), blockposition1.getZ()); ++ BlockFromToEvent event = new BlockFromToEvent(from, to); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ blockposition1 = new BlockPos(event.getToBlock().getX(), event.getToBlock().getY(), event.getToBlock().getZ()); ++ // CraftBukkit end + if (level.isClientSide) { + for (int j = 0; j < 128; ++j) { + double d0 = level.random.nextDouble(); + float f = (level.random.nextFloat() - 0.5F) * 0.2F; + float f1 = (level.random.nextFloat() - 0.5F) * 0.2F; + float f2 = (level.random.nextFloat() - 0.5F) * 0.2F; +- double d1 = Mth.lerp(d0, (double) blockpos1.getX(), (double) blockpos.getX()) + (level.random.nextDouble() - 0.5D) + 0.5D; +- double d2 = Mth.lerp(d0, (double) blockpos1.getY(), (double) blockpos.getY()) + level.random.nextDouble() - 0.5D; +- double d3 = Mth.lerp(d0, (double) blockpos1.getZ(), (double) blockpos.getZ()) + (level.random.nextDouble() - 0.5D) + 0.5D; ++ double d1 = Mth.lerp(d0, (double) blockposition1.getX(), (double) pos.getX()) + (level.random.nextDouble() - 0.5D) + 0.5D; ++ double d2 = Mth.lerp(d0, (double) blockposition1.getY(), (double) pos.getY()) + level.random.nextDouble() - 0.5D; ++ double d3 = Mth.lerp(d0, (double) blockposition1.getZ(), (double) pos.getZ()) + (level.random.nextDouble() - 0.5D) + 0.5D; + + level.addParticle(ParticleTypes.PORTAL, d1, d2, d3, (double) f, (double) f1, (double) f2); + } + } else { +- level.setBlock(blockpos1, blockstate, 2); +- level.removeBlock(blockpos, false); ++ level.setBlock(blockposition1, state, 2); ++ level.removeBlock(pos, false); + } + + return; +@@ -82,14 +91,12 @@ + } + + @Override +- @Override + protected int getDelayAfterPlace() { + return 5; + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DropExperienceBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DropExperienceBlock.java.patch new file mode 100644 index 0000000000..85e299f3ef --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DropExperienceBlock.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/world/level/block/DropExperienceBlock.java ++++ b/net/minecraft/world/level/block/DropExperienceBlock.java +@@ -7,7 +7,7 @@ + import net.minecraft.util.valueproviders.IntProvider; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public class DropExperienceBlock extends Block { + +@@ -19,23 +19,28 @@ + private final IntProvider xpRange; + + @Override +- @Override + public MapCodec codec() { + return DropExperienceBlock.CODEC; + } + +- public DropExperienceBlock(IntProvider intprovider, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ public DropExperienceBlock(IntProvider intprovider, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info); + this.xpRange = intprovider; + } + + @Override ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ super.spawnAfterBreak(state, level, pos, stack, dropExperience); ++ // CraftBukkit start - Delegate to getExpDrop ++ } ++ + @Override +- public void spawnAfterBreak(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, ItemStack itemstack, boolean flag) { +- super.spawnAfterBreak(blockstate, serverlevel, blockpos, itemstack, flag); ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { + if (flag) { +- this.tryDropExperience(serverlevel, blockpos, itemstack, this.xpRange); ++ return this.tryDropExperience(worldserver, blockposition, itemstack, this.xpRange); + } + ++ return 0; ++ // CraftBukkit end + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DropperBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DropperBlock.java.patch new file mode 100644 index 0000000000..792829fede --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/DropperBlock.java.patch @@ -0,0 +1,131 @@ +--- a/net/minecraft/world/level/block/DropperBlock.java ++++ b/net/minecraft/world/level/block/DropperBlock.java +@@ -4,75 +4,92 @@ + import com.mojang.serialization.MapCodec; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.dispenser.BlockSource; + import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; + import net.minecraft.core.dispenser.DispenseItemBehavior; ++import net.minecraft.core.dispenser.SourceBlock; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.CompoundContainer; + import net.minecraft.world.Container; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.DispenserBlockEntity; +-import net.minecraft.world.level.block.entity.DropperBlockEntity; + import net.minecraft.world.level.block.entity.HopperBlockEntity; ++import net.minecraft.world.level.block.entity.TileEntityDropper; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.inventory.InventoryMoveItemEvent; ++// CraftBukkit end + + public class DropperBlock extends DispenserBlock { + + private static final Logger LOGGER = LogUtils.getLogger(); + public static final MapCodec CODEC = simpleCodec(DropperBlock::new); +- private static final DispenseItemBehavior DISPENSE_BEHAVIOUR = new DefaultDispenseItemBehavior(); ++ private static final DispenseItemBehavior DISPENSE_BEHAVIOUR = new DefaultDispenseItemBehavior(true); // CraftBukkit + + @Override +- @Override + public MapCodec codec() { + return DropperBlock.CODEC; + } + +- public DropperBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ public DropperBlock(BlockBehaviour.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- protected DispenseItemBehavior getDispenseMethod(ItemStack itemstack) { ++ protected DispenseItemBehavior getDispenseMethod(ItemStack stack) { + return DropperBlock.DISPENSE_BEHAVIOUR; + } + + @Override +- @Override +- public BlockEntity newBlockEntity(BlockPos blockpos, BlockState blockstate) { +- return new DropperBlockEntity(blockpos, blockstate); ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ return new TileEntityDropper(pos, state); + } + + @Override +- @Override +- protected void dispenseFrom(ServerLevel serverlevel, BlockState blockstate, BlockPos blockpos) { +- DispenserBlockEntity dispenserblockentity = (DispenserBlockEntity) serverlevel.getBlockEntity(blockpos, BlockEntityType.DROPPER).orElse((Object) null); ++ public void dispenseFrom(ServerLevel worldserver, IBlockData iblockdata, BlockPos blockposition) { ++ DispenserBlockEntity tileentitydispenser = (DispenserBlockEntity) worldserver.getBlockEntity(blockposition, BlockEntityType.DROPPER).orElse(null); // CraftBukkit - decompile error + +- if (dispenserblockentity == null) { +- DropperBlock.LOGGER.warn("Ignoring dispensing attempt for Dropper without matching block entity at {}", blockpos); ++ if (tileentitydispenser == null) { ++ DropperBlock.LOGGER.warn("Ignoring dispensing attempt for Dropper without matching block entity at {}", blockposition); + } else { +- BlockSource blocksource = new BlockSource(serverlevel, blockpos, blockstate, dispenserblockentity); +- int i = dispenserblockentity.getRandomSlot(serverlevel.random); ++ SourceBlock sourceblock = new SourceBlock(worldserver, blockposition, iblockdata, tileentitydispenser); ++ int i = tileentitydispenser.getRandomSlot(worldserver.random); + + if (i < 0) { +- serverlevel.levelEvent(1001, blockpos, 0); ++ worldserver.levelEvent(1001, blockposition, 0); + } else { +- ItemStack itemstack = dispenserblockentity.getItem(i); ++ ItemStack itemstack = tileentitydispenser.getItem(i); + + if (!itemstack.isEmpty()) { +- Direction direction = (Direction) serverlevel.getBlockState(blockpos).getValue(DropperBlock.FACING); +- Container container = HopperBlockEntity.getContainerAt(serverlevel, blockpos.relative(direction)); ++ Direction enumdirection = (Direction) worldserver.getBlockState(blockposition).getValue(DropperBlock.FACING); ++ Container iinventory = HopperBlockEntity.getContainerAt(worldserver, blockposition.relative(enumdirection)); + ItemStack itemstack1; + +- if (container == null) { +- itemstack1 = DropperBlock.DISPENSE_BEHAVIOUR.dispense(blocksource, itemstack); ++ if (iinventory == null) { ++ itemstack1 = DropperBlock.DISPENSE_BEHAVIOUR.dispense(sourceblock, itemstack); + } else { +- itemstack1 = HopperBlockEntity.addItem(dispenserblockentity, container, itemstack.copy().split(1), direction.getOpposite()); +- if (itemstack1.isEmpty()) { ++ // CraftBukkit start - Fire event when pushing items into other inventories ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(itemstack.copy().split(1)); ++ ++ org.bukkit.inventory.Inventory destinationInventory; ++ // Have to special case large chests as they work oddly ++ if (iinventory instanceof CompoundContainer) { ++ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory); ++ } else { ++ destinationInventory = iinventory.getOwner().getInventory(); ++ } ++ ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(tileentitydispenser.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true); ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ itemstack1 = HopperBlockEntity.addItem(tileentitydispenser, iinventory, CraftItemStack.asNMSCopy(event.getItem()), enumdirection.getOpposite()); ++ if (event.getItem().equals(oitemstack) && itemstack1.isEmpty()) { ++ // CraftBukkit end + itemstack1 = itemstack.copy(); + itemstack1.shrink(1); + } else { +@@ -80,7 +97,7 @@ + } + } + +- dispenserblockentity.setItem(i, itemstack1); ++ tileentitydispenser.setItem(i, itemstack1); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/EndPortalBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/EndPortalBlock.java.patch new file mode 100644 index 0000000000..2d1e1ee6e7 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/EndPortalBlock.java.patch @@ -0,0 +1,118 @@ +--- a/net/minecraft/world/level/block/EndPortalBlock.java ++++ b/net/minecraft/world/level/block/EndPortalBlock.java +@@ -5,6 +5,7 @@ + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.resources.ResourceKey; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.RandomSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.item.ItemStack; +@@ -14,12 +15,16 @@ + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.TheEndPortalBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.entity.EntityPortalEnterEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++// CraftBukkit end + + public class EndPortalBlock extends BaseEntityBlock { + +@@ -27,62 +32,64 @@ + protected static final VoxelShape SHAPE = Block.box(0.0D, 6.0D, 0.0D, 16.0D, 12.0D, 16.0D); + + @Override +- @Override + public MapCodec codec() { + return EndPortalBlock.CODEC; + } + +- protected EndPortalBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ protected EndPortalBlock(BlockBehaviour.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public BlockEntity newBlockEntity(BlockPos blockpos, BlockState blockstate) { +- return new TheEndPortalBlockEntity(blockpos, blockstate); ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ return new TheEndPortalBlockEntity(pos, state); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return EndPortalBlock.SHAPE; + } + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { +- if (level instanceof ServerLevel && entity.canChangeDimensions() && Shapes.joinIsNotEmpty(Shapes.create(entity.getBoundingBox().move((double) (-blockpos.getX()), (double) (-blockpos.getY()), (double) (-blockpos.getZ()))), blockstate.getShape(level, blockpos), BooleanOp.AND)) { +- ResourceKey resourcekey = level.dimension() == Level.END ? Level.OVERWORLD : Level.END; +- ServerLevel serverlevel = ((ServerLevel) level).getServer().getLevel(resourcekey); ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ if (level instanceof ServerLevel && entity.canChangeDimensions() && Shapes.joinIsNotEmpty(Shapes.create(entity.getBoundingBox().move((double) (-pos.getX()), (double) (-pos.getY()), (double) (-pos.getZ()))), state.getShape(level, pos), BooleanOp.AND)) { ++ ResourceKey resourcekey = level.getTypeKey() == LevelStem.END ? Level.OVERWORLD : Level.END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends ++ ServerLevel worldserver = ((ServerLevel) level).getServer().getLevel(resourcekey); + +- if (serverlevel == null) { +- return; ++ if (worldserver == null) { ++ // return; // CraftBukkit - always fire event in case plugins wish to change it + } + +- entity.changeDimension(serverlevel); ++ // CraftBukkit start - Entity in portal ++ EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(level.getWorld(), pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (entity instanceof ServerPlayer) { ++ ((ServerPlayer) entity).changeDimension(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); ++ return; ++ } ++ // CraftBukkit end ++ entity.changeDimension(worldserver); + } + + } + + @Override +- @Override +- public void animateTick(BlockState blockstate, Level level, BlockPos blockpos, RandomSource randomsource) { +- double d0 = (double) blockpos.getX() + randomsource.nextDouble(); +- double d1 = (double) blockpos.getY() + 0.8D; +- double d2 = (double) blockpos.getZ() + randomsource.nextDouble(); ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ double d0 = (double) pos.getX() + random.nextDouble(); ++ double d1 = (double) pos.getY() + 0.8D; ++ double d2 = (double) pos.getZ() + random.nextDouble(); + + level.addParticle(ParticleTypes.SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + + @Override +- @Override +- public ItemStack getCloneItemStack(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { ++ public ItemStack getCloneItemStack(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { + return ItemStack.EMPTY; + } + + @Override +- @Override +- public boolean canBeReplaced(BlockState blockstate, Fluid fluid) { ++ public boolean canBeReplaced(IBlockData state, Fluid fluid) { + return false; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/FarmBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/FarmBlock.java.patch new file mode 100644 index 0000000000..22094a8a3d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/FarmBlock.java.patch @@ -0,0 +1,213 @@ +--- a/net/minecraft/world/level/block/FarmBlock.java ++++ b/net/minecraft/world/level/block/FarmBlock.java +@@ -20,14 +20,18 @@ + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.piston.MovingPistonBlock; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.level.gameevent.GameEvent; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.event.entity.EntityInteractEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class FarmBlock extends Block { + +@@ -37,124 +41,136 @@ + public static final int MAX_MOISTURE = 7; + + @Override +- @Override + public MapCodec codec() { + return FarmBlock.CODEC; + } + +- protected FarmBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(FarmBlock.MOISTURE, 0)); ++ protected FarmBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(FarmBlock.MOISTURE, 0)); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if (direction == Direction.UP && !blockstate.canSurvive(levelaccessor, blockpos)) { +- levelaccessor.scheduleTick(blockpos, (Block) this, 1); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if (facing == Direction.UP && !state.canSurvive(level, currentPos)) { ++ level.scheduleTick(currentPos, (Block) this, 1); + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- BlockState blockstate1 = levelreader.getBlockState(blockpos.above()); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ IBlockData iblockdata1 = level.getBlockState(pos.above()); + +- return !blockstate1.isSolid() || blockstate1.getBlock() instanceof FenceGateBlock || blockstate1.getBlock() instanceof MovingPistonBlock; ++ return !iblockdata1.isSolid() || iblockdata1.getBlock() instanceof FenceGateBlock || iblockdata1.getBlock() instanceof MovingPistonBlock; + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- return !this.defaultBlockState().canSurvive(blockplacecontext.getLevel(), blockplacecontext.getClickedPos()) ? Blocks.DIRT.defaultBlockState() : super.getStateForPlacement(blockplacecontext); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return !this.defaultBlockState().canSurvive(context.getLevel(), context.getClickedPos()) ? Blocks.DIRT.defaultBlockState() : super.getStateForPlacement(context); + } + + @Override +- @Override +- public boolean useShapeForLightOcclusion(BlockState blockstate) { ++ public boolean useShapeForLightOcclusion(IBlockData state) { + return true; + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return FarmBlock.SHAPE; + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (!blockstate.canSurvive(serverlevel, blockpos)) { +- turnToDirt((Entity) null, blockstate, serverlevel, blockpos); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (!state.canSurvive(level, pos)) { ++ turnToDirt((Entity) null, state, level, pos); + } + + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- int i = (Integer) blockstate.getValue(FarmBlock.MOISTURE); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ int i = (Integer) state.getValue(FarmBlock.MOISTURE); + +- if (!isNearWater(serverlevel, blockpos) && !serverlevel.isRainingAt(blockpos.above())) { ++ if (!isNearWater(level, pos) && !level.isRainingAt(pos.above())) { + if (i > 0) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(FarmBlock.MOISTURE, i - 1), 2); +- } else if (!shouldMaintainFarmland(serverlevel, blockpos)) { +- turnToDirt((Entity) null, blockstate, serverlevel, blockpos); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleMoistureChangeEvent(level, pos, (IBlockData) state.setValue(FarmBlock.MOISTURE, i - 1), 2); // CraftBukkit ++ } else if (!shouldMaintainFarmland(level, pos)) { ++ turnToDirt((Entity) null, state, level, pos); + } + } else if (i < 7) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(FarmBlock.MOISTURE, 7), 2); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleMoistureChangeEvent(level, pos, (IBlockData) state.setValue(FarmBlock.MOISTURE, 7), 2); // CraftBukkit + } + + } + + @Override +- @Override +- public void fallOn(Level level, BlockState blockstate, BlockPos blockpos, Entity entity, float f) { +- if (!level.isClientSide && level.random.nextFloat() < f - 0.5F && entity instanceof LivingEntity && (entity instanceof Player || level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && entity.getBbWidth() * entity.getBbWidth() * entity.getBbHeight() > 0.512F) { +- turnToDirt(entity, blockstate, level, blockpos); ++ public void fallOn(Level level, IBlockData state, BlockPos pos, Entity entity, float fallDistance) { ++ super.fallOn(level, state, pos, entity, fallDistance); // CraftBukkit - moved here as game rules / events shouldn't affect fall damage. ++ if (!level.isClientSide && level.random.nextFloat() < fallDistance - 0.5F && entity instanceof LivingEntity && (entity instanceof Player || level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && entity.getBbWidth() * entity.getBbWidth() * entity.getBbHeight() > 0.512F) { ++ // CraftBukkit start - Interact soil ++ org.bukkit.event.Cancellable cancellable; ++ if (entity instanceof Player) { ++ cancellable = CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ if (cancellable.isCancelled()) { ++ return; ++ } ++ ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.DIRT.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end ++ turnToDirt(entity, state, level, pos); + } + +- super.fallOn(level, blockstate, blockpos, entity, f); ++ // super.fallOn(world, iblockdata, blockposition, entity, f); // CraftBukkit - moved up + } + +- public static void turnToDirt(@Nullable Entity entity, BlockState blockstate, Level level, BlockPos blockpos) { +- BlockState blockstate1 = pushEntitiesUp(blockstate, Blocks.DIRT.defaultBlockState(), level, blockpos); ++ public static void turnToDirt(@Nullable Entity entity, IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ if (CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ IBlockData iblockdata1 = pushEntitiesUp(state, Blocks.DIRT.defaultBlockState(), level, pos); + +- level.setBlockAndUpdate(blockpos, blockstate1); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(entity, blockstate1)); ++ level.setBlockAndUpdate(pos, iblockdata1); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, iblockdata1)); + } + +- private static boolean shouldMaintainFarmland(BlockGetter blockgetter, BlockPos blockpos) { +- return blockgetter.getBlockState(blockpos.above()).is(BlockTags.MAINTAINS_FARMLAND); ++ private static boolean shouldMaintainFarmland(BlockGetter level, BlockPos pos) { ++ return level.getBlockState(pos.above()).is(BlockTags.MAINTAINS_FARMLAND); + } + +- private static boolean isNearWater(LevelReader levelreader, BlockPos blockpos) { +- Iterator iterator = BlockPos.betweenClosed(blockpos.offset(-4, 0, -4), blockpos.offset(4, 1, 4)).iterator(); ++ private static boolean isNearWater(LevelReader level, BlockPos pos) { ++ Iterator iterator = BlockPos.betweenClosed(pos.offset(-4, 0, -4), pos.offset(4, 1, 4)).iterator(); + +- BlockPos blockpos1; ++ BlockPos blockposition1; + + do { + if (!iterator.hasNext()) { + return false; + } + +- blockpos1 = (BlockPos) iterator.next(); +- } while (!levelreader.getFluidState(blockpos1).is(FluidTags.WATER)); ++ blockposition1 = (BlockPos) iterator.next(); ++ } while (!level.getFluidState(blockposition1).is(FluidTags.WATER)); + + return true; + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(FarmBlock.MOISTURE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(FarmBlock.MOISTURE); + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/FenceGateBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/FenceGateBlock.java.patch new file mode 100644 index 0000000000..59ad7260a5 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/FenceGateBlock.java.patch @@ -0,0 +1,261 @@ +--- a/net/minecraft/world/level/block/FenceGateBlock.java ++++ b/net/minecraft/world/level/block/FenceGateBlock.java +@@ -7,7 +7,7 @@ + import net.minecraft.core.Direction; + import net.minecraft.sounds.SoundSource; + import net.minecraft.tags.BlockTags; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; +@@ -18,13 +18,13 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.block.state.properties.WoodType; + import net.minecraft.world.level.gameevent.GameEvent; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; +@@ -33,8 +33,8 @@ + public class FenceGateBlock extends HorizontalDirectionalBlock { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- return instance.group(WoodType.CODEC.fieldOf("wood_type").forGetter((fencegateblock) -> { +- return fencegateblock.type; ++ return instance.group(WoodType.CODEC.fieldOf("wood_type").forGetter((blockfencegate) -> { ++ return blockfencegate.type; + }), propertiesCodec()).apply(instance, FenceGateBlock::new); + }); + public static final BooleanProperty OPEN = BlockStateProperties.OPEN; +@@ -55,136 +55,136 @@ + private final WoodType type; + + @Override +- @Override + public MapCodec codec() { + return FenceGateBlock.CODEC; + } + +- public FenceGateBlock(WoodType woodtype, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties.sound(woodtype.soundType())); +- this.type = woodtype; +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(FenceGateBlock.OPEN, false)).setValue(FenceGateBlock.POWERED, false)).setValue(FenceGateBlock.IN_WALL, false)); ++ public FenceGateBlock(WoodType blockpropertywood, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info.sound(blockpropertywood.soundType())); ++ this.type = blockpropertywood; ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(FenceGateBlock.OPEN, false)).setValue(FenceGateBlock.POWERED, false)).setValue(FenceGateBlock.IN_WALL, false)); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return (Boolean) blockstate.getValue(FenceGateBlock.IN_WALL) ? (((Direction) blockstate.getValue(FenceGateBlock.FACING)).getAxis() == Direction.Axis.X ? FenceGateBlock.X_SHAPE_LOW : FenceGateBlock.Z_SHAPE_LOW) : (((Direction) blockstate.getValue(FenceGateBlock.FACING)).getAxis() == Direction.Axis.X ? FenceGateBlock.X_SHAPE : FenceGateBlock.Z_SHAPE); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (Boolean) state.getValue(FenceGateBlock.IN_WALL) ? (((Direction) state.getValue(FenceGateBlock.FACING)).getAxis() == Direction.Axis.X ? FenceGateBlock.X_SHAPE_LOW : FenceGateBlock.Z_SHAPE_LOW) : (((Direction) state.getValue(FenceGateBlock.FACING)).getAxis() == Direction.Axis.X ? FenceGateBlock.X_SHAPE : FenceGateBlock.Z_SHAPE); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- Direction.Axis direction_axis = direction.getAxis(); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ Direction.Axis enumdirection_enumaxis = facing.getAxis(); + +- if (((Direction) blockstate.getValue(FenceGateBlock.FACING)).getClockWise().getAxis() != direction_axis) { +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ if (((Direction) state.getValue(FenceGateBlock.FACING)).getClockWise().getAxis() != enumdirection_enumaxis) { ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } else { +- boolean flag = this.isWall(blockstate1) || this.isWall(levelaccessor.getBlockState(blockpos.relative(direction.getOpposite()))); ++ boolean flag = this.isWall(facingState) || this.isWall(level.getBlockState(currentPos.relative(facing.getOpposite()))); + +- return (BlockState) blockstate.setValue(FenceGateBlock.IN_WALL, flag); ++ return (IBlockData) state.setValue(FenceGateBlock.IN_WALL, flag); + } + } + + @Override +- @Override +- public VoxelShape getBlockSupportShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return (Boolean) blockstate.getValue(FenceGateBlock.OPEN) ? Shapes.empty() : (((Direction) blockstate.getValue(FenceGateBlock.FACING)).getAxis() == Direction.Axis.Z ? FenceGateBlock.Z_SUPPORT_SHAPE : FenceGateBlock.X_SUPPORT_SHAPE); ++ public VoxelShape getBlockSupportShape(IBlockData state, BlockGetter level, BlockPos pos) { ++ return (Boolean) state.getValue(FenceGateBlock.OPEN) ? Shapes.empty() : (((Direction) state.getValue(FenceGateBlock.FACING)).getAxis() == Direction.Axis.Z ? FenceGateBlock.Z_SUPPORT_SHAPE : FenceGateBlock.X_SUPPORT_SHAPE); + } + + @Override +- @Override +- public VoxelShape getCollisionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return (Boolean) blockstate.getValue(FenceGateBlock.OPEN) ? Shapes.empty() : (((Direction) blockstate.getValue(FenceGateBlock.FACING)).getAxis() == Direction.Axis.Z ? FenceGateBlock.Z_COLLISION_SHAPE : FenceGateBlock.X_COLLISION_SHAPE); ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (Boolean) state.getValue(FenceGateBlock.OPEN) ? Shapes.empty() : (((Direction) state.getValue(FenceGateBlock.FACING)).getAxis() == Direction.Axis.Z ? FenceGateBlock.Z_COLLISION_SHAPE : FenceGateBlock.X_COLLISION_SHAPE); + } + + @Override +- @Override +- public VoxelShape getOcclusionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return (Boolean) blockstate.getValue(FenceGateBlock.IN_WALL) ? (((Direction) blockstate.getValue(FenceGateBlock.FACING)).getAxis() == Direction.Axis.X ? FenceGateBlock.X_OCCLUSION_SHAPE_LOW : FenceGateBlock.Z_OCCLUSION_SHAPE_LOW) : (((Direction) blockstate.getValue(FenceGateBlock.FACING)).getAxis() == Direction.Axis.X ? FenceGateBlock.X_OCCLUSION_SHAPE : FenceGateBlock.Z_OCCLUSION_SHAPE); ++ public VoxelShape getOcclusionShape(IBlockData state, BlockGetter level, BlockPos pos) { ++ return (Boolean) state.getValue(FenceGateBlock.IN_WALL) ? (((Direction) state.getValue(FenceGateBlock.FACING)).getAxis() == Direction.Axis.X ? FenceGateBlock.X_OCCLUSION_SHAPE_LOW : FenceGateBlock.Z_OCCLUSION_SHAPE_LOW) : (((Direction) state.getValue(FenceGateBlock.FACING)).getAxis() == Direction.Axis.X ? FenceGateBlock.X_OCCLUSION_SHAPE : FenceGateBlock.Z_OCCLUSION_SHAPE); + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { +- switch (pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { ++ switch (type) { + case LAND: +- return (Boolean) blockstate.getValue(FenceGateBlock.OPEN); ++ return (Boolean) state.getValue(FenceGateBlock.OPEN); + case WATER: + return false; + case AIR: +- return (Boolean) blockstate.getValue(FenceGateBlock.OPEN); ++ return (Boolean) state.getValue(FenceGateBlock.OPEN); + default: + return false; + } + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- Level level = blockplacecontext.getLevel(); +- BlockPos blockpos = blockplacecontext.getClickedPos(); +- boolean flag = level.hasNeighborSignal(blockpos); +- Direction direction = blockplacecontext.getHorizontalDirection(); +- Direction.Axis direction_axis = direction.getAxis(); +- boolean flag1 = direction_axis == Direction.Axis.Z && (this.isWall(level.getBlockState(blockpos.west())) || this.isWall(level.getBlockState(blockpos.east()))) || direction_axis == Direction.Axis.X && (this.isWall(level.getBlockState(blockpos.north())) || this.isWall(level.getBlockState(blockpos.south()))); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ boolean flag = world.hasNeighborSignal(blockposition); ++ Direction enumdirection = context.getHorizontalDirection(); ++ Direction.Axis enumdirection_enumaxis = enumdirection.getAxis(); ++ boolean flag1 = enumdirection_enumaxis == Direction.Axis.Z && (this.isWall(world.getBlockState(blockposition.west())) || this.isWall(world.getBlockState(blockposition.east()))) || enumdirection_enumaxis == Direction.Axis.X && (this.isWall(world.getBlockState(blockposition.north())) || this.isWall(world.getBlockState(blockposition.south()))); + +- return (BlockState) ((BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(FenceGateBlock.FACING, direction)).setValue(FenceGateBlock.OPEN, flag)).setValue(FenceGateBlock.POWERED, flag)).setValue(FenceGateBlock.IN_WALL, flag1); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(FenceGateBlock.FACING, enumdirection)).setValue(FenceGateBlock.OPEN, flag)).setValue(FenceGateBlock.POWERED, flag)).setValue(FenceGateBlock.IN_WALL, flag1); + } + +- private boolean isWall(BlockState blockstate) { +- return blockstate.is(BlockTags.WALLS); ++ private boolean isWall(IBlockData state) { ++ return state.is(BlockTags.WALLS); + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- if ((Boolean) blockstate.getValue(FenceGateBlock.OPEN)) { +- blockstate = (BlockState) blockstate.setValue(FenceGateBlock.OPEN, false); +- level.setBlock(blockpos, blockstate, 10); ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ if ((Boolean) state.getValue(FenceGateBlock.OPEN)) { ++ state = (IBlockData) state.setValue(FenceGateBlock.OPEN, false); ++ level.setBlock(pos, state, 10); + } else { +- Direction direction = player.getDirection(); ++ Direction enumdirection = player.getDirection(); + +- if (blockstate.getValue(FenceGateBlock.FACING) == direction.getOpposite()) { +- blockstate = (BlockState) blockstate.setValue(FenceGateBlock.FACING, direction); ++ if (state.getValue(FenceGateBlock.FACING) == enumdirection.getOpposite()) { ++ state = (IBlockData) state.setValue(FenceGateBlock.FACING, enumdirection); + } + +- blockstate = (BlockState) blockstate.setValue(FenceGateBlock.OPEN, true); +- level.setBlock(blockpos, blockstate, 10); ++ state = (IBlockData) state.setValue(FenceGateBlock.OPEN, true); ++ level.setBlock(pos, state, 10); + } + +- boolean flag = (Boolean) blockstate.getValue(FenceGateBlock.OPEN); ++ boolean flag = (Boolean) state.getValue(FenceGateBlock.OPEN); + +- level.playSound(player, blockpos, flag ? this.type.fenceGateOpen() : this.type.fenceGateClose(), SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.1F + 0.9F); +- level.gameEvent((Entity) player, flag ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, blockpos); ++ level.playSound(player, pos, flag ? this.type.fenceGateOpen() : this.type.fenceGateClose(), SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.1F + 0.9F); ++ level.gameEvent((Entity) player, flag ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); + return InteractionResult.sidedSuccess(level.isClientSide); + } + + @Override +- @Override +- public void onExplosionHit(BlockState blockstate, Level level, BlockPos blockpos, Explosion explosion, BiConsumer biconsumer) { +- if (explosion.getBlockInteraction() == Explosion.BlockInteraction.TRIGGER_BLOCK && !level.isClientSide() && !(Boolean) blockstate.getValue(FenceGateBlock.POWERED)) { +- boolean flag = (Boolean) blockstate.getValue(FenceGateBlock.OPEN); ++ public void onExplosionHit(IBlockData iblockdata, Level world, BlockPos blockposition, Explosion explosion, BiConsumer biconsumer) { ++ if (explosion.getBlockInteraction() == Explosion.Effect.TRIGGER_BLOCK && !world.isClientSide() && !(Boolean) iblockdata.getValue(FenceGateBlock.POWERED)) { ++ boolean flag = (Boolean) iblockdata.getValue(FenceGateBlock.OPEN); + +- level.setBlockAndUpdate(blockpos, (BlockState) blockstate.setValue(FenceGateBlock.OPEN, !flag)); +- level.playSound((Player) null, blockpos, flag ? this.type.fenceGateClose() : this.type.fenceGateOpen(), SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.1F + 0.9F); +- level.gameEvent(flag ? GameEvent.BLOCK_CLOSE : GameEvent.BLOCK_OPEN, blockpos, GameEvent.Context.of(blockstate)); ++ world.setBlockAndUpdate(blockposition, (IBlockData) iblockdata.setValue(FenceGateBlock.OPEN, !flag)); ++ world.playSound((Player) null, blockposition, flag ? this.type.fenceGateClose() : this.type.fenceGateOpen(), SoundSource.BLOCKS, 1.0F, world.getRandom().nextFloat() * 0.1F + 0.9F); ++ world.gameEvent(flag ? GameEvent.BLOCK_CLOSE : GameEvent.BLOCK_OPEN, blockposition, GameEvent.Context.of(iblockdata)); + } + +- super.onExplosionHit(blockstate, level, blockpos, explosion, biconsumer); ++ super.onExplosionHit(iblockdata, world, blockposition, explosion, biconsumer); + } + + @Override +- @Override +- public void neighborChanged(BlockState blockstate, Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { + if (!level.isClientSide) { +- boolean flag1 = level.hasNeighborSignal(blockpos); ++ boolean flag1 = level.hasNeighborSignal(pos); ++ // CraftBukkit start ++ boolean oldPowered = state.getValue(FenceGateBlock.POWERED); ++ if (oldPowered != flag1) { ++ int newPower = flag1 ? 15 : 0; ++ int oldPower = oldPowered ? 15 : 0; ++ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos); ++ org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(bukkitBlock, oldPower, newPower); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ flag1 = eventRedstone.getNewCurrent() > 0; ++ } ++ // CraftBukkit end + +- if ((Boolean) blockstate.getValue(FenceGateBlock.POWERED) != flag1) { +- level.setBlock(blockpos, (BlockState) ((BlockState) blockstate.setValue(FenceGateBlock.POWERED, flag1)).setValue(FenceGateBlock.OPEN, flag1), 2); +- if ((Boolean) blockstate.getValue(FenceGateBlock.OPEN) != flag1) { +- level.playSound((Player) null, blockpos, flag1 ? this.type.fenceGateOpen() : this.type.fenceGateClose(), SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.1F + 0.9F); +- level.gameEvent((Entity) null, flag1 ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, blockpos); ++ if ((Boolean) state.getValue(FenceGateBlock.POWERED) != flag1) { ++ level.setBlock(pos, (IBlockData) ((IBlockData) state.setValue(FenceGateBlock.POWERED, flag1)).setValue(FenceGateBlock.OPEN, flag1), 2); ++ if ((Boolean) state.getValue(FenceGateBlock.OPEN) != flag1) { ++ level.playSound((Player) null, pos, flag1 ? this.type.fenceGateOpen() : this.type.fenceGateClose(), SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.1F + 0.9F); ++ level.gameEvent((Entity) null, flag1 ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); + } + } + +@@ -192,12 +192,11 @@ + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(FenceGateBlock.FACING, FenceGateBlock.OPEN, FenceGateBlock.POWERED, FenceGateBlock.IN_WALL); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(FenceGateBlock.FACING, FenceGateBlock.OPEN, FenceGateBlock.POWERED, FenceGateBlock.IN_WALL); + } + +- public static boolean connectsToDirection(BlockState blockstate, Direction direction) { +- return ((Direction) blockstate.getValue(FenceGateBlock.FACING)).getAxis() == direction.getClockWise().getAxis(); ++ public static boolean connectsToDirection(IBlockData state, Direction direction) { ++ return ((Direction) state.getValue(FenceGateBlock.FACING)).getAxis() == direction.getClockWise().getAxis(); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/FireBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/FireBlock.java.patch new file mode 100644 index 0000000000..978638ad35 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/FireBlock.java.patch @@ -0,0 +1,816 @@ +--- a/net/minecraft/world/level/block/FireBlock.java ++++ b/net/minecraft/world/level/block/FireBlock.java +@@ -20,7 +20,7 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -28,6 +28,13 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.block.CraftBlockStates; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.block.BlockBurnEvent; ++import org.bukkit.event.block.BlockFadeEvent; ++// CraftBukkit end + + public class FireBlock extends BaseFireBlock { + +@@ -47,7 +54,7 @@ + private static final VoxelShape EAST_AABB = Block.box(15.0D, 0.0D, 0.0D, 16.0D, 16.0D, 16.0D); + private static final VoxelShape NORTH_AABB = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 16.0D, 1.0D); + private static final VoxelShape SOUTH_AABB = Block.box(0.0D, 0.0D, 15.0D, 16.0D, 16.0D, 16.0D); +- private final Map shapesCache; ++ private final Map shapesCache; + private static final int IGNITE_INSTANT = 60; + private static final int IGNITE_EASY = 30; + private static final int IGNITE_MEDIUM = 15; +@@ -56,43 +63,42 @@ + private static final int BURN_EASY = 60; + private static final int BURN_MEDIUM = 20; + private static final int BURN_HARD = 5; +- private final Object2IntMap igniteOdds = new Object2IntOpenHashMap(); ++ public final Object2IntMap igniteOdds = new Object2IntOpenHashMap(); + private final Object2IntMap burnOdds = new Object2IntOpenHashMap(); + + @Override +- @Override + public MapCodec codec() { + return FireBlock.CODEC; + } + +- public FireBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties, 1.0F); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(FireBlock.AGE, 0)).setValue(FireBlock.NORTH, false)).setValue(FireBlock.EAST, false)).setValue(FireBlock.SOUTH, false)).setValue(FireBlock.WEST, false)).setValue(FireBlock.UP, false)); +- this.shapesCache = ImmutableMap.copyOf((Map) this.stateDefinition.getPossibleStates().stream().filter((blockstate) -> { +- return (Integer) blockstate.getValue(FireBlock.AGE) == 0; ++ public FireBlock(BlockBehaviour.Properties properties) { ++ super(properties, 1.0F); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(FireBlock.AGE, 0)).setValue(FireBlock.NORTH, false)).setValue(FireBlock.EAST, false)).setValue(FireBlock.SOUTH, false)).setValue(FireBlock.WEST, false)).setValue(FireBlock.UP, false)); ++ this.shapesCache = ImmutableMap.copyOf((Map) this.stateDefinition.getPossibleStates().stream().filter((iblockdata) -> { ++ return (Integer) iblockdata.getValue(FireBlock.AGE) == 0; + }).collect(Collectors.toMap(Function.identity(), FireBlock::calculateShape))); + } + +- private static VoxelShape calculateShape(BlockState blockstate) { ++ private static VoxelShape calculateShape(IBlockData state) { + VoxelShape voxelshape = Shapes.empty(); + +- if ((Boolean) blockstate.getValue(FireBlock.UP)) { ++ if ((Boolean) state.getValue(FireBlock.UP)) { + voxelshape = FireBlock.UP_AABB; + } + +- if ((Boolean) blockstate.getValue(FireBlock.NORTH)) { ++ if ((Boolean) state.getValue(FireBlock.NORTH)) { + voxelshape = Shapes.or(voxelshape, FireBlock.NORTH_AABB); + } + +- if ((Boolean) blockstate.getValue(FireBlock.SOUTH)) { ++ if ((Boolean) state.getValue(FireBlock.SOUTH)) { + voxelshape = Shapes.or(voxelshape, FireBlock.SOUTH_AABB); + } + +- if ((Boolean) blockstate.getValue(FireBlock.EAST)) { ++ if ((Boolean) state.getValue(FireBlock.EAST)) { + voxelshape = Shapes.or(voxelshape, FireBlock.EAST_AABB); + } + +- if ((Boolean) blockstate.getValue(FireBlock.WEST)) { ++ if ((Boolean) state.getValue(FireBlock.WEST)) { + voxelshape = Shapes.or(voxelshape, FireBlock.WEST_AABB); + } + +@@ -100,105 +106,119 @@ + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- return this.canSurvive(blockstate, levelaccessor, blockpos) ? this.getStateWithAge(levelaccessor, blockpos, (Integer) blockstate.getValue(FireBlock.AGE)) : Blocks.AIR.defaultBlockState(); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ // CraftBukkit start ++ if (!this.canSurvive(state, level, currentPos)) { ++ // Suppress during worldgen ++ if (!(level instanceof Level)) { ++ return Blocks.AIR.defaultBlockState(); ++ } ++ CraftBlockState blockState = CraftBlockStates.getBlockState(level, currentPos); ++ blockState.setData(Blocks.AIR.defaultBlockState()); ++ ++ BlockFadeEvent event = new BlockFadeEvent(blockState.getBlock(), blockState); ++ ((Level) level).getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ return blockState.getHandle(); ++ } ++ } ++ return this.getStateWithAge(level, currentPos, (Integer) state.getValue(FireBlock.AGE)); ++ // CraftBukkit end + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return (VoxelShape) this.shapesCache.get(blockstate.setValue(FireBlock.AGE, 0)); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (VoxelShape) this.shapesCache.get(state.setValue(FireBlock.AGE, 0)); + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- return this.getStateForPlacement(blockplacecontext.getLevel(), blockplacecontext.getClickedPos()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return this.getStateForPlacement(context.getLevel(), context.getClickedPos()); + } + +- protected BlockState getStateForPlacement(BlockGetter blockgetter, BlockPos blockpos) { +- BlockPos blockpos1 = blockpos.below(); +- BlockState blockstate = blockgetter.getBlockState(blockpos1); ++ protected IBlockData getStateForPlacement(BlockGetter level, BlockPos pos) { ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata = level.getBlockState(blockposition1); + +- if (!this.canBurn(blockstate) && !blockstate.isFaceSturdy(blockgetter, blockpos1, Direction.UP)) { +- BlockState blockstate1 = this.defaultBlockState(); +- Direction[] adirection = Direction.values(); +- int i = adirection.length; ++ if (!this.canBurn(iblockdata) && !iblockdata.isFaceSturdy(level, blockposition1, Direction.UP)) { ++ IBlockData iblockdata1 = this.defaultBlockState(); ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; +- BooleanProperty booleanproperty = (BooleanProperty) FireBlock.PROPERTY_BY_DIRECTION.get(direction); ++ Direction enumdirection = aenumdirection[j]; ++ BooleanProperty blockstateboolean = (BooleanProperty) FireBlock.PROPERTY_BY_DIRECTION.get(enumdirection); + +- if (booleanproperty != null) { +- blockstate1 = (BlockState) blockstate1.setValue(booleanproperty, this.canBurn(blockgetter.getBlockState(blockpos.relative(direction)))); ++ if (blockstateboolean != null) { ++ iblockdata1 = (IBlockData) iblockdata1.setValue(blockstateboolean, this.canBurn(level.getBlockState(pos.relative(enumdirection)))); + } + } + +- return blockstate1; ++ return iblockdata1; + } else { + return this.defaultBlockState(); + } + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- BlockPos blockpos1 = blockpos.below(); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.below(); + +- return levelreader.getBlockState(blockpos1).isFaceSturdy(levelreader, blockpos1, Direction.UP) || this.isValidFireLocation(levelreader, blockpos); ++ return level.getBlockState(blockposition1).isFaceSturdy(level, blockposition1, Direction.UP) || this.isValidFireLocation(level, pos); + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- serverlevel.scheduleTick(blockpos, (Block) this, getFireTickDelay(serverlevel.random)); +- if (serverlevel.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) { +- if (!blockstate.canSurvive(serverlevel, blockpos)) { +- serverlevel.removeBlock(blockpos, false); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ level.scheduleTick(pos, (Block) this, getFireTickDelay(level.random)); ++ if (level.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) { ++ if (!state.canSurvive(level, pos)) { ++ fireExtinguished(level, pos); // CraftBukkit - invalid place location + } + +- BlockState blockstate1 = serverlevel.getBlockState(blockpos.below()); +- boolean flag = blockstate1.is(serverlevel.dimensionType().infiniburn()); +- int i = (Integer) blockstate.getValue(FireBlock.AGE); ++ IBlockData iblockdata1 = level.getBlockState(pos.below()); ++ boolean flag = iblockdata1.is(level.dimensionType().infiniburn()); ++ int i = (Integer) state.getValue(FireBlock.AGE); + +- if (!flag && serverlevel.isRaining() && this.isNearRain(serverlevel, blockpos) && randomsource.nextFloat() < 0.2F + (float) i * 0.03F) { +- serverlevel.removeBlock(blockpos, false); ++ if (!flag && level.isRaining() && this.isNearRain(level, pos) && random.nextFloat() < 0.2F + (float) i * 0.03F) { ++ fireExtinguished(level, pos); // CraftBukkit - extinguished by rain + } else { +- int j = Math.min(15, i + randomsource.nextInt(3) / 2); ++ int j = Math.min(15, i + random.nextInt(3) / 2); + + if (i != j) { +- blockstate = (BlockState) blockstate.setValue(FireBlock.AGE, j); +- serverlevel.setBlock(blockpos, blockstate, 4); ++ state = (IBlockData) state.setValue(FireBlock.AGE, j); ++ level.setBlock(pos, state, 4); + } + + if (!flag) { +- if (!this.isValidFireLocation(serverlevel, blockpos)) { +- BlockPos blockpos1 = blockpos.below(); ++ if (!this.isValidFireLocation(level, pos)) { ++ BlockPos blockposition1 = pos.below(); + +- if (!serverlevel.getBlockState(blockpos1).isFaceSturdy(serverlevel, blockpos1, Direction.UP) || i > 3) { +- serverlevel.removeBlock(blockpos, false); ++ if (!level.getBlockState(blockposition1).isFaceSturdy(level, blockposition1, Direction.UP) || i > 3) { ++ fireExtinguished(level, pos); // CraftBukkit + } + + return; + } + +- if (i == 15 && randomsource.nextInt(4) == 0 && !this.canBurn(serverlevel.getBlockState(blockpos.below()))) { +- serverlevel.removeBlock(blockpos, false); ++ if (i == 15 && random.nextInt(4) == 0 && !this.canBurn(level.getBlockState(pos.below()))) { ++ fireExtinguished(level, pos); // CraftBukkit + return; + } + } + +- boolean flag1 = serverlevel.getBiome(blockpos).is(BiomeTags.INCREASED_FIRE_BURNOUT); ++ boolean flag1 = level.getBiome(pos).is(BiomeTags.INCREASED_FIRE_BURNOUT); + int k = flag1 ? -50 : 0; + +- this.checkBurnOut(serverlevel, blockpos.east(), 300 + k, randomsource, i); +- this.checkBurnOut(serverlevel, blockpos.west(), 300 + k, randomsource, i); +- this.checkBurnOut(serverlevel, blockpos.below(), 250 + k, randomsource, i); +- this.checkBurnOut(serverlevel, blockpos.above(), 250 + k, randomsource, i); +- this.checkBurnOut(serverlevel, blockpos.north(), 300 + k, randomsource, i); +- this.checkBurnOut(serverlevel, blockpos.south(), 300 + k, randomsource, i); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ // CraftBukkit start - add source blockposition to burn calls ++ this.trySpread(level, pos.east(), 300 + k, random, i, pos); ++ this.trySpread(level, pos.west(), 300 + k, random, i, pos); ++ this.trySpread(level, pos.below(), 250 + k, random, i, pos); ++ this.trySpread(level, pos.above(), 250 + k, random, i, pos); ++ this.trySpread(level, pos.north(), 300 + k, random, i, pos); ++ this.trySpread(level, pos.south(), 300 + k, random, i, pos); ++ // CraftBukkit end ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + + for (int l = -1; l <= 1; ++l) { + for (int i1 = -1; i1 <= 1; ++i1) { +@@ -210,20 +230,28 @@ + k1 += (j1 - 1) * 100; + } + +- blockpos_mutableblockpos.setWithOffset(blockpos, l, j1, i1); +- int l1 = this.getIgniteOdds(serverlevel, blockpos_mutableblockpos); ++ blockposition_mutableblockposition.setWithOffset(pos, l, j1, i1); ++ int l1 = this.getIgniteOdds(level, blockposition_mutableblockposition); + + if (l1 > 0) { +- int i2 = (l1 + 40 + serverlevel.getDifficulty().getId() * 7) / (i + 30); ++ int i2 = (l1 + 40 + level.getDifficulty().getId() * 7) / (i + 30); + + if (flag1) { + i2 /= 2; + } + +- if (i2 > 0 && randomsource.nextInt(k1) <= i2 && (!serverlevel.isRaining() || !this.isNearRain(serverlevel, blockpos_mutableblockpos))) { +- int j2 = Math.min(15, i + randomsource.nextInt(5) / 4); ++ if (i2 > 0 && random.nextInt(k1) <= i2 && (!level.isRaining() || !this.isNearRain(level, blockposition_mutableblockposition))) { ++ int j2 = Math.min(15, i + random.nextInt(5) / 4); + +- serverlevel.setBlock(blockpos_mutableblockpos, this.getStateWithAge(serverlevel, blockpos_mutableblockpos, j2), 3); ++ // CraftBukkit start - Call to stop spread of fire ++ if (level.getBlockState(blockposition_mutableblockposition).getBlock() != Blocks.FIRE) { ++ if (CraftEventFactory.callBlockIgniteEvent(level, blockposition_mutableblockposition, pos).isCancelled()) { ++ continue; ++ } ++ ++ CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition_mutableblockposition, this.getStateWithAge(level, blockposition_mutableblockposition, j2), 3); // CraftBukkit ++ } ++ // CraftBukkit end + } + } + } +@@ -235,55 +263,71 @@ + } + } + +- protected boolean isNearRain(Level level, BlockPos blockpos) { +- return level.isRainingAt(blockpos) || level.isRainingAt(blockpos.west()) || level.isRainingAt(blockpos.east()) || level.isRainingAt(blockpos.north()) || level.isRainingAt(blockpos.south()); ++ protected boolean isNearRain(Level level, BlockPos pos) { ++ return level.isRainingAt(pos) || level.isRainingAt(pos.west()) || level.isRainingAt(pos.east()) || level.isRainingAt(pos.north()) || level.isRainingAt(pos.south()); + } + +- private int getBurnOdds(BlockState blockstate) { +- return blockstate.hasProperty(BlockStateProperties.WATERLOGGED) && (Boolean) blockstate.getValue(BlockStateProperties.WATERLOGGED) ? 0 : this.burnOdds.getInt(blockstate.getBlock()); ++ private int getBurnOdds(IBlockData state) { ++ return state.hasProperty(BlockStateProperties.WATERLOGGED) && (Boolean) state.getValue(BlockStateProperties.WATERLOGGED) ? 0 : this.burnOdds.getInt(state.getBlock()); + } + +- private int getIgniteOdds(BlockState blockstate) { +- return blockstate.hasProperty(BlockStateProperties.WATERLOGGED) && (Boolean) blockstate.getValue(BlockStateProperties.WATERLOGGED) ? 0 : this.igniteOdds.getInt(blockstate.getBlock()); ++ private int getIgniteOdds(IBlockData state) { ++ return state.hasProperty(BlockStateProperties.WATERLOGGED) && (Boolean) state.getValue(BlockStateProperties.WATERLOGGED) ? 0 : this.igniteOdds.getInt(state.getBlock()); + } + +- private void checkBurnOut(Level level, BlockPos blockpos, int i, RandomSource randomsource, int j) { +- int k = this.getBurnOdds(level.getBlockState(blockpos)); ++ private void trySpread(Level world, BlockPos blockposition, int i, RandomSource randomsource, int j, BlockPos sourceposition) { // CraftBukkit add sourceposition ++ int k = this.getBurnOdds(world.getBlockState(blockposition)); + + if (randomsource.nextInt(i) < k) { +- BlockState blockstate = level.getBlockState(blockpos); ++ IBlockData iblockdata = world.getBlockState(blockposition); + +- if (randomsource.nextInt(j + 10) < 5 && !level.isRainingAt(blockpos)) { ++ // CraftBukkit start ++ org.bukkit.block.Block theBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ org.bukkit.block.Block sourceBlock = world.getWorld().getBlockAt(sourceposition.getX(), sourceposition.getY(), sourceposition.getZ()); ++ ++ BlockBurnEvent event = new BlockBurnEvent(theBlock, sourceBlock); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ if (iblockdata.getBlock() instanceof TntBlock && !CraftEventFactory.callTNTPrimeEvent(world, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.FIRE, null, sourceposition)) { ++ return; ++ } ++ // CraftBukkit end ++ ++ if (randomsource.nextInt(j + 10) < 5 && !world.isRainingAt(blockposition)) { + int l = Math.min(j + randomsource.nextInt(5) / 4, 15); + +- level.setBlock(blockpos, this.getStateWithAge(level, blockpos, l), 3); ++ world.setBlock(blockposition, this.getStateWithAge(world, blockposition, l), 3); + } else { +- level.removeBlock(blockpos, false); ++ world.removeBlock(blockposition, false); + } + +- Block block = blockstate.getBlock(); ++ Block block = iblockdata.getBlock(); + + if (block instanceof TntBlock) { +- TntBlock.explode(level, blockpos); ++ TntBlock.explode(world, blockposition); + } + } + + } + +- private BlockState getStateWithAge(LevelAccessor levelaccessor, BlockPos blockpos, int i) { +- BlockState blockstate = getState(levelaccessor, blockpos); ++ private IBlockData getStateWithAge(LevelAccessor level, BlockPos pos, int age) { ++ IBlockData iblockdata = getState(level, pos); + +- return blockstate.is(Blocks.FIRE) ? (BlockState) blockstate.setValue(FireBlock.AGE, i) : blockstate; ++ return iblockdata.is(Blocks.FIRE) ? (IBlockData) iblockdata.setValue(FireBlock.AGE, age) : iblockdata; + } + +- private boolean isValidFireLocation(BlockGetter blockgetter, BlockPos blockpos) { +- Direction[] adirection = Direction.values(); +- int i = adirection.length; ++ private boolean isValidFireLocation(BlockGetter level, BlockPos pos) { ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; ++ Direction enumdirection = aenumdirection[j]; + +- if (this.canBurn(blockgetter.getBlockState(blockpos.relative(direction)))) { ++ if (this.canBurn(level.getBlockState(pos.relative(enumdirection)))) { + return true; + } + } +@@ -291,19 +335,19 @@ + return false; + } + +- private int getIgniteOdds(LevelReader levelreader, BlockPos blockpos) { +- if (!levelreader.isEmptyBlock(blockpos)) { ++ private int getIgniteOdds(LevelReader level, BlockPos pos) { ++ if (!level.isEmptyBlock(pos)) { + return 0; + } else { + int i = 0; +- Direction[] adirection = Direction.values(); +- int j = adirection.length; ++ Direction[] aenumdirection = Direction.values(); ++ int j = aenumdirection.length; + + for (int k = 0; k < j; ++k) { +- Direction direction = adirection[k]; +- BlockState blockstate = levelreader.getBlockState(blockpos.relative(direction)); ++ Direction enumdirection = aenumdirection[k]; ++ IBlockData iblockdata = level.getBlockState(pos.relative(enumdirection)); + +- i = Math.max(this.getIgniteOdds(blockstate), i); ++ i = Math.max(this.getIgniteOdds(iblockdata), i); + } + + return i; +@@ -311,209 +355,206 @@ + } + + @Override +- @Override +- protected boolean canBurn(BlockState blockstate) { +- return this.getIgniteOdds(blockstate) > 0; ++ protected boolean canBurn(IBlockData state) { ++ return this.getIgniteOdds(state) > 0; + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- super.onPlace(blockstate, level, blockpos, blockstate1, flag); +- level.scheduleTick(blockpos, (Block) this, getFireTickDelay(level.random)); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ super.onPlace(state, level, pos, oldState, isMoving); ++ level.scheduleTick(pos, (Block) this, getFireTickDelay(level.random)); + } + +- private static int getFireTickDelay(RandomSource randomsource) { +- return 30 + randomsource.nextInt(10); ++ private static int getFireTickDelay(RandomSource random) { ++ return 30 + random.nextInt(10); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(FireBlock.AGE, FireBlock.NORTH, FireBlock.EAST, FireBlock.SOUTH, FireBlock.WEST, FireBlock.UP); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(FireBlock.AGE, FireBlock.NORTH, FireBlock.EAST, FireBlock.SOUTH, FireBlock.WEST, FireBlock.UP); + } + +- public void setFlammable(Block block, int i, int j) { +- this.igniteOdds.put(block, i); +- this.burnOdds.put(block, j); ++ public void setFlammable(Block block, int encouragement, int flammability) { ++ this.igniteOdds.put(block, encouragement); ++ this.burnOdds.put(block, flammability); + } + + public static void bootStrap() { +- FireBlock fireblock = (FireBlock) Blocks.FIRE; ++ FireBlock blockfire = (FireBlock) Blocks.FIRE; + +- fireblock.setFlammable(Blocks.OAK_PLANKS, 5, 20); +- fireblock.setFlammable(Blocks.SPRUCE_PLANKS, 5, 20); +- fireblock.setFlammable(Blocks.BIRCH_PLANKS, 5, 20); +- fireblock.setFlammable(Blocks.JUNGLE_PLANKS, 5, 20); +- fireblock.setFlammable(Blocks.ACACIA_PLANKS, 5, 20); +- fireblock.setFlammable(Blocks.CHERRY_PLANKS, 5, 20); +- fireblock.setFlammable(Blocks.DARK_OAK_PLANKS, 5, 20); +- fireblock.setFlammable(Blocks.MANGROVE_PLANKS, 5, 20); +- fireblock.setFlammable(Blocks.BAMBOO_PLANKS, 5, 20); +- fireblock.setFlammable(Blocks.BAMBOO_MOSAIC, 5, 20); +- fireblock.setFlammable(Blocks.OAK_SLAB, 5, 20); +- fireblock.setFlammable(Blocks.SPRUCE_SLAB, 5, 20); +- fireblock.setFlammable(Blocks.BIRCH_SLAB, 5, 20); +- fireblock.setFlammable(Blocks.JUNGLE_SLAB, 5, 20); +- fireblock.setFlammable(Blocks.ACACIA_SLAB, 5, 20); +- fireblock.setFlammable(Blocks.CHERRY_SLAB, 5, 20); +- fireblock.setFlammable(Blocks.DARK_OAK_SLAB, 5, 20); +- fireblock.setFlammable(Blocks.MANGROVE_SLAB, 5, 20); +- fireblock.setFlammable(Blocks.BAMBOO_SLAB, 5, 20); +- fireblock.setFlammable(Blocks.BAMBOO_MOSAIC_SLAB, 5, 20); +- fireblock.setFlammable(Blocks.OAK_FENCE_GATE, 5, 20); +- fireblock.setFlammable(Blocks.SPRUCE_FENCE_GATE, 5, 20); +- fireblock.setFlammable(Blocks.BIRCH_FENCE_GATE, 5, 20); +- fireblock.setFlammable(Blocks.JUNGLE_FENCE_GATE, 5, 20); +- fireblock.setFlammable(Blocks.ACACIA_FENCE_GATE, 5, 20); +- fireblock.setFlammable(Blocks.CHERRY_FENCE_GATE, 5, 20); +- fireblock.setFlammable(Blocks.DARK_OAK_FENCE_GATE, 5, 20); +- fireblock.setFlammable(Blocks.MANGROVE_FENCE_GATE, 5, 20); +- fireblock.setFlammable(Blocks.BAMBOO_FENCE_GATE, 5, 20); +- fireblock.setFlammable(Blocks.OAK_FENCE, 5, 20); +- fireblock.setFlammable(Blocks.SPRUCE_FENCE, 5, 20); +- fireblock.setFlammable(Blocks.BIRCH_FENCE, 5, 20); +- fireblock.setFlammable(Blocks.JUNGLE_FENCE, 5, 20); +- fireblock.setFlammable(Blocks.ACACIA_FENCE, 5, 20); +- fireblock.setFlammable(Blocks.CHERRY_FENCE, 5, 20); +- fireblock.setFlammable(Blocks.DARK_OAK_FENCE, 5, 20); +- fireblock.setFlammable(Blocks.MANGROVE_FENCE, 5, 20); +- fireblock.setFlammable(Blocks.BAMBOO_FENCE, 5, 20); +- fireblock.setFlammable(Blocks.OAK_STAIRS, 5, 20); +- fireblock.setFlammable(Blocks.BIRCH_STAIRS, 5, 20); +- fireblock.setFlammable(Blocks.SPRUCE_STAIRS, 5, 20); +- fireblock.setFlammable(Blocks.JUNGLE_STAIRS, 5, 20); +- fireblock.setFlammable(Blocks.ACACIA_STAIRS, 5, 20); +- fireblock.setFlammable(Blocks.CHERRY_STAIRS, 5, 20); +- fireblock.setFlammable(Blocks.DARK_OAK_STAIRS, 5, 20); +- fireblock.setFlammable(Blocks.MANGROVE_STAIRS, 5, 20); +- fireblock.setFlammable(Blocks.BAMBOO_STAIRS, 5, 20); +- fireblock.setFlammable(Blocks.BAMBOO_MOSAIC_STAIRS, 5, 20); +- fireblock.setFlammable(Blocks.OAK_LOG, 5, 5); +- fireblock.setFlammable(Blocks.SPRUCE_LOG, 5, 5); +- fireblock.setFlammable(Blocks.BIRCH_LOG, 5, 5); +- fireblock.setFlammable(Blocks.JUNGLE_LOG, 5, 5); +- fireblock.setFlammable(Blocks.ACACIA_LOG, 5, 5); +- fireblock.setFlammable(Blocks.CHERRY_LOG, 5, 5); +- fireblock.setFlammable(Blocks.DARK_OAK_LOG, 5, 5); +- fireblock.setFlammable(Blocks.MANGROVE_LOG, 5, 5); +- fireblock.setFlammable(Blocks.BAMBOO_BLOCK, 5, 5); +- fireblock.setFlammable(Blocks.STRIPPED_OAK_LOG, 5, 5); +- fireblock.setFlammable(Blocks.STRIPPED_SPRUCE_LOG, 5, 5); +- fireblock.setFlammable(Blocks.STRIPPED_BIRCH_LOG, 5, 5); +- fireblock.setFlammable(Blocks.STRIPPED_JUNGLE_LOG, 5, 5); +- fireblock.setFlammable(Blocks.STRIPPED_ACACIA_LOG, 5, 5); +- fireblock.setFlammable(Blocks.STRIPPED_CHERRY_LOG, 5, 5); +- fireblock.setFlammable(Blocks.STRIPPED_DARK_OAK_LOG, 5, 5); +- fireblock.setFlammable(Blocks.STRIPPED_MANGROVE_LOG, 5, 5); +- fireblock.setFlammable(Blocks.STRIPPED_BAMBOO_BLOCK, 5, 5); +- fireblock.setFlammable(Blocks.STRIPPED_OAK_WOOD, 5, 5); +- fireblock.setFlammable(Blocks.STRIPPED_SPRUCE_WOOD, 5, 5); +- fireblock.setFlammable(Blocks.STRIPPED_BIRCH_WOOD, 5, 5); +- fireblock.setFlammable(Blocks.STRIPPED_JUNGLE_WOOD, 5, 5); +- fireblock.setFlammable(Blocks.STRIPPED_ACACIA_WOOD, 5, 5); +- fireblock.setFlammable(Blocks.STRIPPED_CHERRY_WOOD, 5, 5); +- fireblock.setFlammable(Blocks.STRIPPED_DARK_OAK_WOOD, 5, 5); +- fireblock.setFlammable(Blocks.STRIPPED_MANGROVE_WOOD, 5, 5); +- fireblock.setFlammable(Blocks.OAK_WOOD, 5, 5); +- fireblock.setFlammable(Blocks.SPRUCE_WOOD, 5, 5); +- fireblock.setFlammable(Blocks.BIRCH_WOOD, 5, 5); +- fireblock.setFlammable(Blocks.JUNGLE_WOOD, 5, 5); +- fireblock.setFlammable(Blocks.ACACIA_WOOD, 5, 5); +- fireblock.setFlammable(Blocks.CHERRY_WOOD, 5, 5); +- fireblock.setFlammable(Blocks.DARK_OAK_WOOD, 5, 5); +- fireblock.setFlammable(Blocks.MANGROVE_WOOD, 5, 5); +- fireblock.setFlammable(Blocks.MANGROVE_ROOTS, 5, 20); +- fireblock.setFlammable(Blocks.OAK_LEAVES, 30, 60); +- fireblock.setFlammable(Blocks.SPRUCE_LEAVES, 30, 60); +- fireblock.setFlammable(Blocks.BIRCH_LEAVES, 30, 60); +- fireblock.setFlammable(Blocks.JUNGLE_LEAVES, 30, 60); +- fireblock.setFlammable(Blocks.ACACIA_LEAVES, 30, 60); +- fireblock.setFlammable(Blocks.CHERRY_LEAVES, 30, 60); +- fireblock.setFlammable(Blocks.DARK_OAK_LEAVES, 30, 60); +- fireblock.setFlammable(Blocks.MANGROVE_LEAVES, 30, 60); +- fireblock.setFlammable(Blocks.BOOKSHELF, 30, 20); +- fireblock.setFlammable(Blocks.TNT, 15, 100); +- fireblock.setFlammable(Blocks.SHORT_GRASS, 60, 100); +- fireblock.setFlammable(Blocks.FERN, 60, 100); +- fireblock.setFlammable(Blocks.DEAD_BUSH, 60, 100); +- fireblock.setFlammable(Blocks.SUNFLOWER, 60, 100); +- fireblock.setFlammable(Blocks.LILAC, 60, 100); +- fireblock.setFlammable(Blocks.ROSE_BUSH, 60, 100); +- fireblock.setFlammable(Blocks.PEONY, 60, 100); +- fireblock.setFlammable(Blocks.TALL_GRASS, 60, 100); +- fireblock.setFlammable(Blocks.LARGE_FERN, 60, 100); +- fireblock.setFlammable(Blocks.DANDELION, 60, 100); +- fireblock.setFlammable(Blocks.POPPY, 60, 100); +- fireblock.setFlammable(Blocks.BLUE_ORCHID, 60, 100); +- fireblock.setFlammable(Blocks.ALLIUM, 60, 100); +- fireblock.setFlammable(Blocks.AZURE_BLUET, 60, 100); +- fireblock.setFlammable(Blocks.RED_TULIP, 60, 100); +- fireblock.setFlammable(Blocks.ORANGE_TULIP, 60, 100); +- fireblock.setFlammable(Blocks.WHITE_TULIP, 60, 100); +- fireblock.setFlammable(Blocks.PINK_TULIP, 60, 100); +- fireblock.setFlammable(Blocks.OXEYE_DAISY, 60, 100); +- fireblock.setFlammable(Blocks.CORNFLOWER, 60, 100); +- fireblock.setFlammable(Blocks.LILY_OF_THE_VALLEY, 60, 100); +- fireblock.setFlammable(Blocks.TORCHFLOWER, 60, 100); +- fireblock.setFlammable(Blocks.PITCHER_PLANT, 60, 100); +- fireblock.setFlammable(Blocks.WITHER_ROSE, 60, 100); +- fireblock.setFlammable(Blocks.PINK_PETALS, 60, 100); +- fireblock.setFlammable(Blocks.WHITE_WOOL, 30, 60); +- fireblock.setFlammable(Blocks.ORANGE_WOOL, 30, 60); +- fireblock.setFlammable(Blocks.MAGENTA_WOOL, 30, 60); +- fireblock.setFlammable(Blocks.LIGHT_BLUE_WOOL, 30, 60); +- fireblock.setFlammable(Blocks.YELLOW_WOOL, 30, 60); +- fireblock.setFlammable(Blocks.LIME_WOOL, 30, 60); +- fireblock.setFlammable(Blocks.PINK_WOOL, 30, 60); +- fireblock.setFlammable(Blocks.GRAY_WOOL, 30, 60); +- fireblock.setFlammable(Blocks.LIGHT_GRAY_WOOL, 30, 60); +- fireblock.setFlammable(Blocks.CYAN_WOOL, 30, 60); +- fireblock.setFlammable(Blocks.PURPLE_WOOL, 30, 60); +- fireblock.setFlammable(Blocks.BLUE_WOOL, 30, 60); +- fireblock.setFlammable(Blocks.BROWN_WOOL, 30, 60); +- fireblock.setFlammable(Blocks.GREEN_WOOL, 30, 60); +- fireblock.setFlammable(Blocks.RED_WOOL, 30, 60); +- fireblock.setFlammable(Blocks.BLACK_WOOL, 30, 60); +- fireblock.setFlammable(Blocks.VINE, 15, 100); +- fireblock.setFlammable(Blocks.COAL_BLOCK, 5, 5); +- fireblock.setFlammable(Blocks.HAY_BLOCK, 60, 20); +- fireblock.setFlammable(Blocks.TARGET, 15, 20); +- fireblock.setFlammable(Blocks.WHITE_CARPET, 60, 20); +- fireblock.setFlammable(Blocks.ORANGE_CARPET, 60, 20); +- fireblock.setFlammable(Blocks.MAGENTA_CARPET, 60, 20); +- fireblock.setFlammable(Blocks.LIGHT_BLUE_CARPET, 60, 20); +- fireblock.setFlammable(Blocks.YELLOW_CARPET, 60, 20); +- fireblock.setFlammable(Blocks.LIME_CARPET, 60, 20); +- fireblock.setFlammable(Blocks.PINK_CARPET, 60, 20); +- fireblock.setFlammable(Blocks.GRAY_CARPET, 60, 20); +- fireblock.setFlammable(Blocks.LIGHT_GRAY_CARPET, 60, 20); +- fireblock.setFlammable(Blocks.CYAN_CARPET, 60, 20); +- fireblock.setFlammable(Blocks.PURPLE_CARPET, 60, 20); +- fireblock.setFlammable(Blocks.BLUE_CARPET, 60, 20); +- fireblock.setFlammable(Blocks.BROWN_CARPET, 60, 20); +- fireblock.setFlammable(Blocks.GREEN_CARPET, 60, 20); +- fireblock.setFlammable(Blocks.RED_CARPET, 60, 20); +- fireblock.setFlammable(Blocks.BLACK_CARPET, 60, 20); +- fireblock.setFlammable(Blocks.DRIED_KELP_BLOCK, 30, 60); +- fireblock.setFlammable(Blocks.BAMBOO, 60, 60); +- fireblock.setFlammable(Blocks.SCAFFOLDING, 60, 60); +- fireblock.setFlammable(Blocks.LECTERN, 30, 20); +- fireblock.setFlammable(Blocks.COMPOSTER, 5, 20); +- fireblock.setFlammable(Blocks.SWEET_BERRY_BUSH, 60, 100); +- fireblock.setFlammable(Blocks.BEEHIVE, 5, 20); +- fireblock.setFlammable(Blocks.BEE_NEST, 30, 20); +- fireblock.setFlammable(Blocks.AZALEA_LEAVES, 30, 60); +- fireblock.setFlammable(Blocks.FLOWERING_AZALEA_LEAVES, 30, 60); +- fireblock.setFlammable(Blocks.CAVE_VINES, 15, 60); +- fireblock.setFlammable(Blocks.CAVE_VINES_PLANT, 15, 60); +- fireblock.setFlammable(Blocks.SPORE_BLOSSOM, 60, 100); +- fireblock.setFlammable(Blocks.AZALEA, 30, 60); +- fireblock.setFlammable(Blocks.FLOWERING_AZALEA, 30, 60); +- fireblock.setFlammable(Blocks.BIG_DRIPLEAF, 60, 100); +- fireblock.setFlammable(Blocks.BIG_DRIPLEAF_STEM, 60, 100); +- fireblock.setFlammable(Blocks.SMALL_DRIPLEAF, 60, 100); +- fireblock.setFlammable(Blocks.HANGING_ROOTS, 30, 60); +- fireblock.setFlammable(Blocks.GLOW_LICHEN, 15, 100); ++ blockfire.setFlammable(Blocks.OAK_PLANKS, 5, 20); ++ blockfire.setFlammable(Blocks.SPRUCE_PLANKS, 5, 20); ++ blockfire.setFlammable(Blocks.BIRCH_PLANKS, 5, 20); ++ blockfire.setFlammable(Blocks.JUNGLE_PLANKS, 5, 20); ++ blockfire.setFlammable(Blocks.ACACIA_PLANKS, 5, 20); ++ blockfire.setFlammable(Blocks.CHERRY_PLANKS, 5, 20); ++ blockfire.setFlammable(Blocks.DARK_OAK_PLANKS, 5, 20); ++ blockfire.setFlammable(Blocks.MANGROVE_PLANKS, 5, 20); ++ blockfire.setFlammable(Blocks.BAMBOO_PLANKS, 5, 20); ++ blockfire.setFlammable(Blocks.BAMBOO_MOSAIC, 5, 20); ++ blockfire.setFlammable(Blocks.OAK_SLAB, 5, 20); ++ blockfire.setFlammable(Blocks.SPRUCE_SLAB, 5, 20); ++ blockfire.setFlammable(Blocks.BIRCH_SLAB, 5, 20); ++ blockfire.setFlammable(Blocks.JUNGLE_SLAB, 5, 20); ++ blockfire.setFlammable(Blocks.ACACIA_SLAB, 5, 20); ++ blockfire.setFlammable(Blocks.CHERRY_SLAB, 5, 20); ++ blockfire.setFlammable(Blocks.DARK_OAK_SLAB, 5, 20); ++ blockfire.setFlammable(Blocks.MANGROVE_SLAB, 5, 20); ++ blockfire.setFlammable(Blocks.BAMBOO_SLAB, 5, 20); ++ blockfire.setFlammable(Blocks.BAMBOO_MOSAIC_SLAB, 5, 20); ++ blockfire.setFlammable(Blocks.OAK_FENCE_GATE, 5, 20); ++ blockfire.setFlammable(Blocks.SPRUCE_FENCE_GATE, 5, 20); ++ blockfire.setFlammable(Blocks.BIRCH_FENCE_GATE, 5, 20); ++ blockfire.setFlammable(Blocks.JUNGLE_FENCE_GATE, 5, 20); ++ blockfire.setFlammable(Blocks.ACACIA_FENCE_GATE, 5, 20); ++ blockfire.setFlammable(Blocks.CHERRY_FENCE_GATE, 5, 20); ++ blockfire.setFlammable(Blocks.DARK_OAK_FENCE_GATE, 5, 20); ++ blockfire.setFlammable(Blocks.MANGROVE_FENCE_GATE, 5, 20); ++ blockfire.setFlammable(Blocks.BAMBOO_FENCE_GATE, 5, 20); ++ blockfire.setFlammable(Blocks.OAK_FENCE, 5, 20); ++ blockfire.setFlammable(Blocks.SPRUCE_FENCE, 5, 20); ++ blockfire.setFlammable(Blocks.BIRCH_FENCE, 5, 20); ++ blockfire.setFlammable(Blocks.JUNGLE_FENCE, 5, 20); ++ blockfire.setFlammable(Blocks.ACACIA_FENCE, 5, 20); ++ blockfire.setFlammable(Blocks.CHERRY_FENCE, 5, 20); ++ blockfire.setFlammable(Blocks.DARK_OAK_FENCE, 5, 20); ++ blockfire.setFlammable(Blocks.MANGROVE_FENCE, 5, 20); ++ blockfire.setFlammable(Blocks.BAMBOO_FENCE, 5, 20); ++ blockfire.setFlammable(Blocks.OAK_STAIRS, 5, 20); ++ blockfire.setFlammable(Blocks.BIRCH_STAIRS, 5, 20); ++ blockfire.setFlammable(Blocks.SPRUCE_STAIRS, 5, 20); ++ blockfire.setFlammable(Blocks.JUNGLE_STAIRS, 5, 20); ++ blockfire.setFlammable(Blocks.ACACIA_STAIRS, 5, 20); ++ blockfire.setFlammable(Blocks.CHERRY_STAIRS, 5, 20); ++ blockfire.setFlammable(Blocks.DARK_OAK_STAIRS, 5, 20); ++ blockfire.setFlammable(Blocks.MANGROVE_STAIRS, 5, 20); ++ blockfire.setFlammable(Blocks.BAMBOO_STAIRS, 5, 20); ++ blockfire.setFlammable(Blocks.BAMBOO_MOSAIC_STAIRS, 5, 20); ++ blockfire.setFlammable(Blocks.OAK_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.SPRUCE_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.BIRCH_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.JUNGLE_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.ACACIA_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.CHERRY_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.DARK_OAK_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.MANGROVE_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.BAMBOO_BLOCK, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_OAK_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_SPRUCE_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_BIRCH_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_JUNGLE_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_ACACIA_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_CHERRY_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_DARK_OAK_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_MANGROVE_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_BAMBOO_BLOCK, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_OAK_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_SPRUCE_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_BIRCH_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_JUNGLE_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_ACACIA_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_CHERRY_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_DARK_OAK_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_MANGROVE_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.OAK_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.SPRUCE_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.BIRCH_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.JUNGLE_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.ACACIA_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.CHERRY_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.DARK_OAK_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.MANGROVE_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.MANGROVE_ROOTS, 5, 20); ++ blockfire.setFlammable(Blocks.OAK_LEAVES, 30, 60); ++ blockfire.setFlammable(Blocks.SPRUCE_LEAVES, 30, 60); ++ blockfire.setFlammable(Blocks.BIRCH_LEAVES, 30, 60); ++ blockfire.setFlammable(Blocks.JUNGLE_LEAVES, 30, 60); ++ blockfire.setFlammable(Blocks.ACACIA_LEAVES, 30, 60); ++ blockfire.setFlammable(Blocks.CHERRY_LEAVES, 30, 60); ++ blockfire.setFlammable(Blocks.DARK_OAK_LEAVES, 30, 60); ++ blockfire.setFlammable(Blocks.MANGROVE_LEAVES, 30, 60); ++ blockfire.setFlammable(Blocks.BOOKSHELF, 30, 20); ++ blockfire.setFlammable(Blocks.TNT, 15, 100); ++ blockfire.setFlammable(Blocks.SHORT_GRASS, 60, 100); ++ blockfire.setFlammable(Blocks.FERN, 60, 100); ++ blockfire.setFlammable(Blocks.DEAD_BUSH, 60, 100); ++ blockfire.setFlammable(Blocks.SUNFLOWER, 60, 100); ++ blockfire.setFlammable(Blocks.LILAC, 60, 100); ++ blockfire.setFlammable(Blocks.ROSE_BUSH, 60, 100); ++ blockfire.setFlammable(Blocks.PEONY, 60, 100); ++ blockfire.setFlammable(Blocks.TALL_GRASS, 60, 100); ++ blockfire.setFlammable(Blocks.LARGE_FERN, 60, 100); ++ blockfire.setFlammable(Blocks.DANDELION, 60, 100); ++ blockfire.setFlammable(Blocks.POPPY, 60, 100); ++ blockfire.setFlammable(Blocks.BLUE_ORCHID, 60, 100); ++ blockfire.setFlammable(Blocks.ALLIUM, 60, 100); ++ blockfire.setFlammable(Blocks.AZURE_BLUET, 60, 100); ++ blockfire.setFlammable(Blocks.RED_TULIP, 60, 100); ++ blockfire.setFlammable(Blocks.ORANGE_TULIP, 60, 100); ++ blockfire.setFlammable(Blocks.WHITE_TULIP, 60, 100); ++ blockfire.setFlammable(Blocks.PINK_TULIP, 60, 100); ++ blockfire.setFlammable(Blocks.OXEYE_DAISY, 60, 100); ++ blockfire.setFlammable(Blocks.CORNFLOWER, 60, 100); ++ blockfire.setFlammable(Blocks.LILY_OF_THE_VALLEY, 60, 100); ++ blockfire.setFlammable(Blocks.TORCHFLOWER, 60, 100); ++ blockfire.setFlammable(Blocks.PITCHER_PLANT, 60, 100); ++ blockfire.setFlammable(Blocks.WITHER_ROSE, 60, 100); ++ blockfire.setFlammable(Blocks.PINK_PETALS, 60, 100); ++ blockfire.setFlammable(Blocks.WHITE_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.ORANGE_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.MAGENTA_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.LIGHT_BLUE_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.YELLOW_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.LIME_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.PINK_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.GRAY_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.LIGHT_GRAY_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.CYAN_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.PURPLE_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.BLUE_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.BROWN_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.GREEN_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.RED_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.BLACK_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.VINE, 15, 100); ++ blockfire.setFlammable(Blocks.COAL_BLOCK, 5, 5); ++ blockfire.setFlammable(Blocks.HAY_BLOCK, 60, 20); ++ blockfire.setFlammable(Blocks.TARGET, 15, 20); ++ blockfire.setFlammable(Blocks.WHITE_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.ORANGE_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.MAGENTA_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.LIGHT_BLUE_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.YELLOW_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.LIME_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.PINK_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.GRAY_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.LIGHT_GRAY_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.CYAN_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.PURPLE_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.BLUE_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.BROWN_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.GREEN_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.RED_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.BLACK_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.DRIED_KELP_BLOCK, 30, 60); ++ blockfire.setFlammable(Blocks.BAMBOO, 60, 60); ++ blockfire.setFlammable(Blocks.SCAFFOLDING, 60, 60); ++ blockfire.setFlammable(Blocks.LECTERN, 30, 20); ++ blockfire.setFlammable(Blocks.COMPOSTER, 5, 20); ++ blockfire.setFlammable(Blocks.SWEET_BERRY_BUSH, 60, 100); ++ blockfire.setFlammable(Blocks.BEEHIVE, 5, 20); ++ blockfire.setFlammable(Blocks.BEE_NEST, 30, 20); ++ blockfire.setFlammable(Blocks.AZALEA_LEAVES, 30, 60); ++ blockfire.setFlammable(Blocks.FLOWERING_AZALEA_LEAVES, 30, 60); ++ blockfire.setFlammable(Blocks.CAVE_VINES, 15, 60); ++ blockfire.setFlammable(Blocks.CAVE_VINES_PLANT, 15, 60); ++ blockfire.setFlammable(Blocks.SPORE_BLOSSOM, 60, 100); ++ blockfire.setFlammable(Blocks.AZALEA, 30, 60); ++ blockfire.setFlammable(Blocks.FLOWERING_AZALEA, 30, 60); ++ blockfire.setFlammable(Blocks.BIG_DRIPLEAF, 60, 100); ++ blockfire.setFlammable(Blocks.BIG_DRIPLEAF_STEM, 60, 100); ++ blockfire.setFlammable(Blocks.SMALL_DRIPLEAF, 60, 100); ++ blockfire.setFlammable(Blocks.HANGING_ROOTS, 30, 60); ++ blockfire.setFlammable(Blocks.GLOW_LICHEN, 15, 100); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/FungusBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/FungusBlock.java.patch new file mode 100644 index 0000000000..ca895468af --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/FungusBlock.java.patch @@ -0,0 +1,101 @@ +--- a/net/minecraft/world/level/block/FungusBlock.java ++++ b/net/minecraft/world/level/block/FungusBlock.java +@@ -15,7 +15,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; +@@ -23,10 +23,10 @@ + public class FungusBlock extends BushBlock implements BonemealableBlock { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- return instance.group(ResourceKey.codec(Registries.CONFIGURED_FEATURE).fieldOf("feature").forGetter((fungusblock) -> { +- return fungusblock.feature; +- }), BuiltInRegistries.BLOCK.byNameCodec().fieldOf("grows_on").forGetter((fungusblock) -> { +- return fungusblock.requiredBlock; ++ return instance.group(ResourceKey.codec(Registries.CONFIGURED_FEATURE).fieldOf("feature").forGetter((blockfungi) -> { ++ return blockfungi.feature; ++ }), BuiltInRegistries.BLOCK.byNameCodec().fieldOf("grows_on").forGetter((blockfungi) -> { ++ return blockfungi.requiredBlock; + }), propertiesCodec()).apply(instance, FungusBlock::new); + }); + protected static final VoxelShape SHAPE = Block.box(4.0D, 0.0D, 4.0D, 12.0D, 9.0D, 12.0D); +@@ -35,52 +35,53 @@ + private final ResourceKey> feature; + + @Override +- @Override + public MapCodec codec() { + return FungusBlock.CODEC; + } + +- protected FungusBlock(ResourceKey> resourcekey, Block block, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ protected FungusBlock(ResourceKey> resourcekey, Block block, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info); + this.feature = resourcekey; + this.requiredBlock = block; + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return FungusBlock.SHAPE; + } + + @Override +- @Override +- protected boolean mayPlaceOn(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return blockstate.is(BlockTags.NYLIUM) || blockstate.is(Blocks.MYCELIUM) || blockstate.is(Blocks.SOUL_SOIL) || super.mayPlaceOn(blockstate, blockgetter, blockpos); ++ protected boolean mayPlaceOn(IBlockData state, BlockGetter level, BlockPos pos) { ++ return state.is(BlockTags.NYLIUM) || state.is(Blocks.MYCELIUM) || state.is(Blocks.SOUL_SOIL) || super.mayPlaceOn(state, level, pos); + } + +- private Optional>> getFeature(LevelReader levelreader) { +- return levelreader.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE).getHolder(this.feature); ++ private Optional>> getFeature(LevelReader level) { ++ return level.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE).getHolder(this.feature); + } + + @Override +- @Override +- public boolean isValidBonemealTarget(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { +- BlockState blockstate1 = levelreader.getBlockState(blockpos.below()); ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ IBlockData iblockdata1 = iworldreader.getBlockState(blockposition.below()); + +- return blockstate1.is(this.requiredBlock); ++ return iblockdata1.is(this.requiredBlock); + } + + @Override +- @Override +- public boolean isBonemealSuccess(Level level, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { +- return (double) randomsource.nextFloat() < 0.4D; ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { ++ return (double) random.nextFloat() < 0.4D; + } + + @Override +- @Override +- public void performBonemeal(ServerLevel serverlevel, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { +- this.getFeature(serverlevel).ifPresent((holder) -> { +- ((ConfiguredFeature) holder.value()).place(serverlevel, serverlevel.getChunkSource().getGenerator(), randomsource, blockpos); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ this.getFeature(level).ifPresent((holder) -> { ++ // CraftBukkit start ++ if (this == Blocks.WARPED_FUNGUS) { ++ SaplingBlock.treeType = org.bukkit.TreeType.WARPED_FUNGUS; ++ } else if (this == Blocks.CRIMSON_FUNGUS) { ++ SaplingBlock.treeType = org.bukkit.TreeType.CRIMSON_FUNGUS; ++ } ++ // CraftBukkit end ++ ((ConfiguredFeature) holder.value()).place(level, level.getChunkSource().getGenerator(), random, pos); + }); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/GrowingPlantHeadBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/GrowingPlantHeadBlock.java.patch new file mode 100644 index 0000000000..15101aa821 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/GrowingPlantHeadBlock.java.patch @@ -0,0 +1,167 @@ +--- a/net/minecraft/world/level/block/GrowingPlantHeadBlock.java ++++ b/net/minecraft/world/level/block/GrowingPlantHeadBlock.java +@@ -9,7 +9,7 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; +@@ -23,103 +23,94 @@ + public static final int MAX_AGE = 25; + private final double growPerTickProbability; + +- protected GrowingPlantHeadBlock(BlockBehaviour.Properties blockbehaviour_properties, Direction direction, VoxelShape voxelshape, boolean flag, double d0) { +- super(blockbehaviour_properties, direction, voxelshape, flag); +- this.growPerTickProbability = d0; +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(GrowingPlantHeadBlock.AGE, 0)); ++ protected GrowingPlantHeadBlock(BlockBehaviour.Properties properties, Direction growthDirection, VoxelShape shape, boolean scheduleFluidTicks, double growPerTickProbability) { ++ super(properties, growthDirection, shape, scheduleFluidTicks); ++ this.growPerTickProbability = growPerTickProbability; ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(GrowingPlantHeadBlock.AGE, 0)); + } + + @Override +- @Override + protected abstract MapCodec codec(); + + @Override +- @Override +- public BlockState getStateForPlacement(LevelAccessor levelaccessor) { +- return (BlockState) this.defaultBlockState().setValue(GrowingPlantHeadBlock.AGE, levelaccessor.getRandom().nextInt(25)); ++ public IBlockData getStateForPlacement(LevelAccessor level) { ++ return (IBlockData) this.defaultBlockState().setValue(GrowingPlantHeadBlock.AGE, level.getRandom().nextInt(25)); + } + + @Override +- @Override +- public boolean isRandomlyTicking(BlockState blockstate) { +- return (Integer) blockstate.getValue(GrowingPlantHeadBlock.AGE) < 25; ++ public boolean isRandomlyTicking(IBlockData state) { ++ return (Integer) state.getValue(GrowingPlantHeadBlock.AGE) < 25; + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if ((Integer) blockstate.getValue(GrowingPlantHeadBlock.AGE) < 25 && randomsource.nextDouble() < this.growPerTickProbability) { +- BlockPos blockpos1 = blockpos.relative(this.growthDirection); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Integer) state.getValue(GrowingPlantHeadBlock.AGE) < 25 && random.nextDouble() < this.growPerTickProbability) { ++ BlockPos blockposition1 = pos.relative(this.growthDirection); + +- if (this.canGrowInto(serverlevel.getBlockState(blockpos1))) { +- serverlevel.setBlockAndUpdate(blockpos1, this.getGrowIntoState(blockstate, serverlevel.random)); ++ if (this.canGrowInto(level.getBlockState(blockposition1))) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition1, this.getGrowIntoState(state, level.random)); // CraftBukkit + } + } + + } + +- protected BlockState getGrowIntoState(BlockState blockstate, RandomSource randomsource) { +- return (BlockState) blockstate.cycle(GrowingPlantHeadBlock.AGE); ++ protected IBlockData getGrowIntoState(IBlockData state, RandomSource random) { ++ return (IBlockData) state.cycle(GrowingPlantHeadBlock.AGE); + } + +- public BlockState getMaxAgeState(BlockState blockstate) { +- return (BlockState) blockstate.setValue(GrowingPlantHeadBlock.AGE, 25); ++ public IBlockData getMaxAgeState(IBlockData state) { ++ return (IBlockData) state.setValue(GrowingPlantHeadBlock.AGE, 25); + } + +- public boolean isMaxAge(BlockState blockstate) { +- return (Integer) blockstate.getValue(GrowingPlantHeadBlock.AGE) == 25; ++ public boolean isMaxAge(IBlockData state) { ++ return (Integer) state.getValue(GrowingPlantHeadBlock.AGE) == 25; + } + +- protected BlockState updateBodyAfterConvertedFromHead(BlockState blockstate, BlockState blockstate1) { +- return blockstate1; ++ protected IBlockData updateBodyAfterConvertedFromHead(IBlockData head, IBlockData body) { ++ return body; + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if (direction == this.growthDirection.getOpposite() && !blockstate.canSurvive(levelaccessor, blockpos)) { +- levelaccessor.scheduleTick(blockpos, (Block) this, 1); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if (facing == this.growthDirection.getOpposite() && !state.canSurvive(level, currentPos)) { ++ level.scheduleTick(currentPos, (Block) this, 1); + } + +- if (direction == this.growthDirection && (blockstate1.is((Block) this) || blockstate1.is(this.getBodyBlock()))) { +- return this.updateBodyAfterConvertedFromHead(blockstate, this.getBodyBlock().defaultBlockState()); ++ if (facing == this.growthDirection && (facingState.is((Block) this) || facingState.is(this.getBodyBlock()))) { ++ return this.updateBodyAfterConvertedFromHead(state, this.getBodyBlock().defaultBlockState()); + } else { + if (this.scheduleFluidTicks) { +- levelaccessor.scheduleTick(blockpos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(levelaccessor)); ++ level.scheduleTick(currentPos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(GrowingPlantHeadBlock.AGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(GrowingPlantHeadBlock.AGE); + } + + @Override +- @Override +- public boolean isValidBonemealTarget(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { +- return this.canGrowInto(levelreader.getBlockState(blockpos.relative(this.growthDirection))); ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ return this.canGrowInto(iworldreader.getBlockState(blockposition.relative(this.growthDirection))); + } + + @Override +- @Override +- public boolean isBonemealSuccess(Level level, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return true; + } + + @Override +- @Override +- public void performBonemeal(ServerLevel serverlevel, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { +- BlockPos blockpos1 = blockpos.relative(this.growthDirection); +- int i = Math.min((Integer) blockstate.getValue(GrowingPlantHeadBlock.AGE) + 1, 25); +- int j = this.getBlocksToGrowWhenBonemealed(randomsource); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ BlockPos blockposition1 = pos.relative(this.growthDirection); ++ int i = Math.min((Integer) state.getValue(GrowingPlantHeadBlock.AGE) + 1, 25); ++ int j = this.getBlocksToGrowWhenBonemealed(random); + +- for (int k = 0; k < j && this.canGrowInto(serverlevel.getBlockState(blockpos1)); ++k) { +- serverlevel.setBlockAndUpdate(blockpos1, (BlockState) blockstate.setValue(GrowingPlantHeadBlock.AGE, i)); +- blockpos1 = blockpos1.relative(this.growthDirection); ++ for (int k = 0; k < j && this.canGrowInto(level.getBlockState(blockposition1)); ++k) { ++ level.setBlockAndUpdate(blockposition1, (IBlockData) state.setValue(GrowingPlantHeadBlock.AGE, i)); ++ blockposition1 = blockposition1.relative(this.growthDirection); + i = Math.min(i + 1, 25); + } + +@@ -127,10 +118,9 @@ + + protected abstract int getBlocksToGrowWhenBonemealed(RandomSource random); + +- protected abstract boolean canGrowInto(BlockState state); ++ protected abstract boolean canGrowInto(IBlockData state); + + @Override +- @Override + protected GrowingPlantHeadBlock getHeadBlock() { + return this; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/IceBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/IceBlock.java.patch new file mode 100644 index 0000000000..82382fe39c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/IceBlock.java.patch @@ -0,0 +1,91 @@ +--- a/net/minecraft/world/level/block/IceBlock.java ++++ b/net/minecraft/world/level/block/IceBlock.java +@@ -9,64 +9,66 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.item.enchantment.Enchantments; ++import net.minecraft.world.level.EnumSkyBlock; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public class IceBlock extends HalfTransparentBlock { + + public static final MapCodec CODEC = simpleCodec(IceBlock::new); + + @Override +- @Override + public MapCodec codec() { + return IceBlock.CODEC; + } + +- public IceBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ public IceBlock(BlockBehaviour.Properties properties) { ++ super(properties); + } + +- public static BlockState meltsInto() { ++ public static IBlockData meltsInto() { + return Blocks.WATER.defaultBlockState(); + } + + @Override +- @Override +- public void playerDestroy(Level level, Player player, BlockPos blockpos, BlockState blockstate, @Nullable BlockEntity blockentity, ItemStack itemstack) { +- super.playerDestroy(level, player, blockpos, blockstate, blockentity, itemstack); +- if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, itemstack) == 0) { ++ public void playerDestroy(Level level, Player player, BlockPos pos, IBlockData state, @Nullable BlockEntity te, ItemStack stack) { ++ super.playerDestroy(level, player, pos, state, te, stack); ++ if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack) == 0) { + if (level.dimensionType().ultraWarm()) { +- level.removeBlock(blockpos, false); ++ level.removeBlock(pos, false); + return; + } + +- BlockState blockstate1 = level.getBlockState(blockpos.below()); ++ IBlockData iblockdata1 = level.getBlockState(pos.below()); + +- if (blockstate1.blocksMotion() || blockstate1.liquid()) { +- level.setBlockAndUpdate(blockpos, meltsInto()); ++ if (iblockdata1.blocksMotion() || iblockdata1.liquid()) { ++ level.setBlockAndUpdate(pos, meltsInto()); + } + } + + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (serverlevel.getBrightness(LightLayer.BLOCK, blockpos) > 11 - blockstate.getLightBlock(serverlevel, blockpos)) { +- this.melt(blockstate, serverlevel, blockpos); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (level.getBrightness(EnumSkyBlock.BLOCK, pos) > 11 - state.getLightBlock(level, pos)) { ++ this.melt(state, level, pos); + } + + } + +- protected void melt(BlockState blockstate, Level level, BlockPos blockpos) { ++ protected void melt(IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, level.dimensionType().ultraWarm() ? Blocks.AIR.defaultBlockState() : Blocks.WATER.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + if (level.dimensionType().ultraWarm()) { +- level.removeBlock(blockpos, false); ++ level.removeBlock(pos, false); + } else { +- level.setBlockAndUpdate(blockpos, meltsInto()); +- level.neighborChanged(blockpos, meltsInto().getBlock(), blockpos); ++ level.setBlockAndUpdate(pos, meltsInto()); ++ level.neighborChanged(pos, meltsInto().getBlock(), pos); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/InfestedBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/InfestedBlock.java.patch new file mode 100644 index 0000000000..e55610e754 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/InfestedBlock.java.patch @@ -0,0 +1,117 @@ +--- a/net/minecraft/world/level/block/InfestedBlock.java ++++ b/net/minecraft/world/level/block/InfestedBlock.java +@@ -16,8 +16,9 @@ + import net.minecraft.world.item.enchantment.Enchantments; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.Property; ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; // CraftBukkit + + public class InfestedBlock extends Block { + +@@ -26,73 +27,71 @@ + }); + private final Block hostBlock; + private static final Map BLOCK_BY_HOST_BLOCK = Maps.newIdentityHashMap(); +- private static final Map HOST_TO_INFESTED_STATES = Maps.newIdentityHashMap(); +- private static final Map INFESTED_TO_HOST_STATES = Maps.newIdentityHashMap(); ++ private static final Map HOST_TO_INFESTED_STATES = Maps.newIdentityHashMap(); ++ private static final Map INFESTED_TO_HOST_STATES = Maps.newIdentityHashMap(); + + @Override +- @Override + public MapCodec codec() { + return InfestedBlock.CODEC; + } + +- public InfestedBlock(Block block, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties.destroyTime(block.defaultDestroyTime() / 2.0F).explosionResistance(0.75F)); +- this.hostBlock = block; +- InfestedBlock.BLOCK_BY_HOST_BLOCK.put(block, this); ++ public InfestedBlock(Block hostBlock, BlockBehaviour.Properties properties) { ++ super(properties.destroyTime(hostBlock.defaultDestroyTime() / 2.0F).explosionResistance(0.75F)); ++ this.hostBlock = hostBlock; ++ InfestedBlock.BLOCK_BY_HOST_BLOCK.put(hostBlock, this); + } + + public Block getHostBlock() { + return this.hostBlock; + } + +- public static boolean isCompatibleHostBlock(BlockState blockstate) { +- return InfestedBlock.BLOCK_BY_HOST_BLOCK.containsKey(blockstate.getBlock()); ++ public static boolean isCompatibleHostBlock(IBlockData state) { ++ return InfestedBlock.BLOCK_BY_HOST_BLOCK.containsKey(state.getBlock()); + } + +- private void spawnInfestation(ServerLevel serverlevel, BlockPos blockpos) { +- Silverfish silverfish = (Silverfish) EntityType.SILVERFISH.create(serverlevel); ++ private void spawnInfestation(ServerLevel level, BlockPos pos) { ++ Silverfish entitysilverfish = (Silverfish) EntityType.SILVERFISH.create(level); + +- if (silverfish != null) { +- silverfish.moveTo((double) blockpos.getX() + 0.5D, (double) blockpos.getY(), (double) blockpos.getZ() + 0.5D, 0.0F, 0.0F); +- serverlevel.addFreshEntity(silverfish); +- silverfish.spawnAnim(); ++ if (entitysilverfish != null) { ++ entitysilverfish.moveTo((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, 0.0F, 0.0F); ++ level.addFreshEntity(entitysilverfish, SpawnReason.SILVERFISH_BLOCK); // CraftBukkit - add SpawnReason ++ entitysilverfish.spawnAnim(); + } + + } + + @Override +- @Override +- public void spawnAfterBreak(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, ItemStack itemstack, boolean flag) { +- super.spawnAfterBreak(blockstate, serverlevel, blockpos, itemstack, flag); +- if (serverlevel.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS) && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, itemstack) == 0) { +- this.spawnInfestation(serverlevel, blockpos); ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ super.spawnAfterBreak(state, level, pos, stack, dropExperience); ++ if (level.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS) && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack) == 0) { ++ this.spawnInfestation(level, pos); + } + + } + +- public static BlockState infestedStateByHost(BlockState blockstate) { +- return getNewStateWithProperties(InfestedBlock.HOST_TO_INFESTED_STATES, blockstate, () -> { +- return ((Block) InfestedBlock.BLOCK_BY_HOST_BLOCK.get(blockstate.getBlock())).defaultBlockState(); ++ public static IBlockData infestedStateByHost(IBlockData host) { ++ return getNewStateWithProperties(InfestedBlock.HOST_TO_INFESTED_STATES, host, () -> { ++ return ((Block) InfestedBlock.BLOCK_BY_HOST_BLOCK.get(host.getBlock())).defaultBlockState(); + }); + } + +- public BlockState hostStateByInfested(BlockState blockstate) { +- return getNewStateWithProperties(InfestedBlock.INFESTED_TO_HOST_STATES, blockstate, () -> { ++ public IBlockData hostStateByInfested(IBlockData infested) { ++ return getNewStateWithProperties(InfestedBlock.INFESTED_TO_HOST_STATES, infested, () -> { + return this.getHostBlock().defaultBlockState(); + }); + } + +- private static BlockState getNewStateWithProperties(Map map, BlockState blockstate, Supplier supplier) { +- return (BlockState) map.computeIfAbsent(blockstate, (blockstate1) -> { +- BlockState blockstate2 = (BlockState) supplier.get(); ++ private static IBlockData getNewStateWithProperties(Map stateMap, IBlockData state, Supplier supplier) { ++ return (IBlockData) stateMap.computeIfAbsent(state, (iblockdata1) -> { ++ IBlockData iblockdata2 = (IBlockData) supplier.get(); + +- Property property; ++ Property iblockstate; + +- for (Iterator iterator = blockstate1.getProperties().iterator(); iterator.hasNext(); blockstate2 = blockstate2.hasProperty(property) ? (BlockState) blockstate2.setValue(property, blockstate1.getValue(property)) : blockstate2) { +- property = (Property) iterator.next(); ++ for (Iterator iterator = iblockdata1.getProperties().iterator(); iterator.hasNext(); iblockdata2 = iblockdata2.hasProperty(iblockstate) ? (IBlockData) iblockdata2.setValue(iblockstate, iblockdata1.getValue(iblockstate)) : iblockdata2) { ++ iblockstate = (Property) iterator.next(); + } + +- return blockstate2; ++ return iblockdata2; + }); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/LayeredCauldronBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/LayeredCauldronBlock.java.patch new file mode 100644 index 0000000000..eabce09974 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/LayeredCauldronBlock.java.patch @@ -0,0 +1,184 @@ +--- a/net/minecraft/world/level/block/LayeredCauldronBlock.java ++++ b/net/minecraft/world/level/block/LayeredCauldronBlock.java +@@ -8,13 +8,18 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.biome.Biome; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.block.CraftBlockStates; ++import org.bukkit.event.block.CauldronLevelChangeEvent; ++// CraftBukkit end + + public class LayeredCauldronBlock extends AbstractCauldronBlock { + +@@ -33,96 +38,116 @@ + private final Biome.Precipitation precipitationType; + + @Override +- @Override + public MapCodec codec() { + return LayeredCauldronBlock.CODEC; + } + +- public LayeredCauldronBlock(Biome.Precipitation biome_precipitation, CauldronInteraction.InteractionMap cauldroninteraction_interactionmap, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties, cauldroninteraction_interactionmap); +- this.precipitationType = biome_precipitation; +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(LayeredCauldronBlock.LEVEL, 1)); ++ public LayeredCauldronBlock(Biome.Precipitation biomebase_precipitation, CauldronInteraction.a cauldroninteraction_a, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info, cauldroninteraction_a); ++ this.precipitationType = biomebase_precipitation; ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(LayeredCauldronBlock.LEVEL, 1)); + } + + @Override +- @Override +- public boolean isFull(BlockState blockstate) { +- return (Integer) blockstate.getValue(LayeredCauldronBlock.LEVEL) == 3; ++ public boolean isFull(IBlockData state) { ++ return (Integer) state.getValue(LayeredCauldronBlock.LEVEL) == 3; + } + + @Override +- @Override + protected boolean canReceiveStalactiteDrip(Fluid fluid) { + return fluid == Fluids.WATER && this.precipitationType == Biome.Precipitation.RAIN; + } + + @Override +- @Override +- protected double getContentHeight(BlockState blockstate) { +- return (6.0D + (double) (Integer) blockstate.getValue(LayeredCauldronBlock.LEVEL) * 3.0D) / 16.0D; ++ protected double getContentHeight(IBlockData state) { ++ return (6.0D + (double) (Integer) state.getValue(LayeredCauldronBlock.LEVEL) * 3.0D) / 16.0D; + } + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { +- if (!level.isClientSide && entity.isOnFire() && this.isEntityInsideContent(blockstate, blockpos, entity)) { +- entity.clearFire(); +- if (entity.mayInteract(level, blockpos)) { +- this.handleEntityOnFireInside(blockstate, level, blockpos); ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ if (!level.isClientSide && entity.isOnFire() && this.isEntityInsideContent(state, pos, entity)) { ++ // CraftBukkit start ++ if (entity.mayInteract(level, pos)) { ++ if (!lowerFillLevel(state, level, pos, entity, CauldronLevelChangeEvent.ChangeReason.EXTINGUISH)) { ++ return; ++ } + } ++ entity.clearFire(); ++ // CraftBukkit end + } + + } + +- private void handleEntityOnFireInside(BlockState blockstate, Level level, BlockPos blockpos) { ++ private void handleEntityOnFireInside(IBlockData state, Level level, BlockPos pos) { + if (this.precipitationType == Biome.Precipitation.SNOW) { +- lowerFillLevel((BlockState) Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, (Integer) blockstate.getValue(LayeredCauldronBlock.LEVEL)), level, blockpos); ++ lowerFillLevel((IBlockData) Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, (Integer) state.getValue(LayeredCauldronBlock.LEVEL)), level, pos); + } else { +- lowerFillLevel(blockstate, level, blockpos); ++ lowerFillLevel(state, level, pos); + } + + } + +- public static void lowerFillLevel(BlockState blockstate, Level level, BlockPos blockpos) { +- int i = (Integer) blockstate.getValue(LayeredCauldronBlock.LEVEL) - 1; +- BlockState blockstate1 = i == 0 ? Blocks.CAULDRON.defaultBlockState() : (BlockState) blockstate.setValue(LayeredCauldronBlock.LEVEL, i); ++ public static void lowerFillLevel(IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ lowerFillLevel(state, level, pos, null, CauldronLevelChangeEvent.ChangeReason.UNKNOWN); ++ } + +- level.setBlockAndUpdate(blockpos, blockstate1); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(blockstate1)); ++ public static boolean lowerFillLevel(IBlockData iblockdata, Level world, BlockPos blockposition, Entity entity, CauldronLevelChangeEvent.ChangeReason reason) { ++ int i = (Integer) iblockdata.getValue(LayeredCauldronBlock.LEVEL) - 1; ++ IBlockData iblockdata1 = i == 0 ? Blocks.CAULDRON.defaultBlockState() : (IBlockData) iblockdata.setValue(LayeredCauldronBlock.LEVEL, i); ++ ++ return changeLevel(iblockdata, world, blockposition, iblockdata1, entity, reason); + } + ++ // CraftBukkit start ++ public static boolean changeLevel(IBlockData iblockdata, Level world, BlockPos blockposition, IBlockData newBlock, Entity entity, CauldronLevelChangeEvent.ChangeReason reason) { ++ CraftBlockState newState = CraftBlockStates.getBlockState(world, blockposition); ++ newState.setData(newBlock); ++ ++ CauldronLevelChangeEvent event = new CauldronLevelChangeEvent( ++ world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), ++ (entity == null) ? null : entity.getBukkitEntity(), reason, newState ++ ); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ newState.update(true); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(newBlock)); ++ return true; ++ } ++ // CraftBukkit end ++ + @Override +- @Override +- public void handlePrecipitation(BlockState blockstate, Level level, BlockPos blockpos, Biome.Precipitation biome_precipitation) { +- if (CauldronBlock.shouldHandlePrecipitation(level, biome_precipitation) && (Integer) blockstate.getValue(LayeredCauldronBlock.LEVEL) != 3 && biome_precipitation == this.precipitationType) { +- BlockState blockstate1 = (BlockState) blockstate.cycle(LayeredCauldronBlock.LEVEL); ++ public void handlePrecipitation(IBlockData state, Level level, BlockPos pos, Biome.Precipitation precipitation) { ++ if (CauldronBlock.shouldHandlePrecipitation(level, precipitation) && (Integer) state.getValue(LayeredCauldronBlock.LEVEL) != 3 && precipitation == this.precipitationType) { ++ IBlockData iblockdata1 = (IBlockData) state.cycle(LayeredCauldronBlock.LEVEL); + +- level.setBlockAndUpdate(blockpos, blockstate1); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(blockstate1)); ++ changeLevel(state, level, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL); // CraftBukkit + } + } + + @Override +- @Override +- public int getAnalogOutputSignal(BlockState blockstate, Level level, BlockPos blockpos) { +- return (Integer) blockstate.getValue(LayeredCauldronBlock.LEVEL); ++ public int getAnalogOutputSignal(IBlockData state, Level level, BlockPos pos) { ++ return (Integer) state.getValue(LayeredCauldronBlock.LEVEL); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(LayeredCauldronBlock.LEVEL); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(LayeredCauldronBlock.LEVEL); + } + + @Override +- @Override +- protected void receiveStalactiteDrip(BlockState blockstate, Level level, BlockPos blockpos, Fluid fluid) { +- if (!this.isFull(blockstate)) { +- BlockState blockstate1 = (BlockState) blockstate.setValue(LayeredCauldronBlock.LEVEL, (Integer) blockstate.getValue(LayeredCauldronBlock.LEVEL) + 1); ++ protected void receiveStalactiteDrip(IBlockData state, Level level, BlockPos pos, Fluid fluid) { ++ if (!this.isFull(state)) { ++ IBlockData iblockdata1 = (IBlockData) state.setValue(LayeredCauldronBlock.LEVEL, (Integer) state.getValue(LayeredCauldronBlock.LEVEL) + 1); + +- level.setBlockAndUpdate(blockpos, blockstate1); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(blockstate1)); +- level.levelEvent(1047, blockpos, 0); ++ // CraftBukkit start ++ if (!changeLevel(state, level, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL)) { ++ return; ++ } ++ // CraftBukkit end ++ level.levelEvent(1047, pos, 0); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/LeavesBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/LeavesBlock.java.patch new file mode 100644 index 0000000000..e0918cec94 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/LeavesBlock.java.patch @@ -0,0 +1,207 @@ +--- a/net/minecraft/world/level/block/LeavesBlock.java ++++ b/net/minecraft/world/level/block/LeavesBlock.java +@@ -14,7 +14,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -24,6 +24,7 @@ + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.LeavesDecayEvent; // CraftBukkit + + public class LeavesBlock extends Block implements SimpleWaterloggedBlock { + +@@ -35,130 +36,127 @@ + private static final int TICK_DELAY = 1; + + @Override +- @Override + public MapCodec codec() { + return LeavesBlock.CODEC; + } + +- public LeavesBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(LeavesBlock.DISTANCE, 7)).setValue(LeavesBlock.PERSISTENT, false)).setValue(LeavesBlock.WATERLOGGED, false)); ++ public LeavesBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(LeavesBlock.DISTANCE, 7)).setValue(LeavesBlock.PERSISTENT, false)).setValue(LeavesBlock.WATERLOGGED, false)); + } + + @Override +- @Override +- public VoxelShape getBlockSupportShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { ++ public VoxelShape getBlockSupportShape(IBlockData state, BlockGetter reader, BlockPos pos) { + return Shapes.empty(); + } + + @Override +- @Override +- public boolean isRandomlyTicking(BlockState blockstate) { +- return (Integer) blockstate.getValue(LeavesBlock.DISTANCE) == 7 && !(Boolean) blockstate.getValue(LeavesBlock.PERSISTENT); ++ public boolean isRandomlyTicking(IBlockData state) { ++ return (Integer) state.getValue(LeavesBlock.DISTANCE) == 7 && !(Boolean) state.getValue(LeavesBlock.PERSISTENT); + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (this.decaying(blockstate)) { +- dropResources(blockstate, serverlevel, blockpos); +- serverlevel.removeBlock(blockpos, false); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (this.decaying(state)) { ++ // CraftBukkit start ++ LeavesDecayEvent event = new LeavesDecayEvent(level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled() || level.getBlockState(pos).getBlock() != this) { ++ return; ++ } ++ // CraftBukkit end ++ dropResources(state, level, pos); ++ level.removeBlock(pos, false); + } + + } + +- protected boolean decaying(BlockState blockstate) { +- return !(Boolean) blockstate.getValue(LeavesBlock.PERSISTENT) && (Integer) blockstate.getValue(LeavesBlock.DISTANCE) == 7; ++ protected boolean decaying(IBlockData state) { ++ return !(Boolean) state.getValue(LeavesBlock.PERSISTENT) && (Integer) state.getValue(LeavesBlock.DISTANCE) == 7; + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- serverlevel.setBlock(blockpos, updateDistance(blockstate, serverlevel, blockpos), 3); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ level.setBlock(pos, updateDistance(state, level, pos), 3); + } + + @Override +- @Override +- public int getLightBlock(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { ++ public int getLightBlock(IBlockData state, BlockGetter level, BlockPos pos) { + return 1; + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if ((Boolean) blockstate.getValue(LeavesBlock.WATERLOGGED)) { +- levelaccessor.scheduleTick(blockpos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(levelaccessor)); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if ((Boolean) state.getValue(LeavesBlock.WATERLOGGED)) { ++ level.scheduleTick(currentPos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + +- int i = getDistanceAt(blockstate1) + 1; ++ int i = getDistanceAt(facingState) + 1; + +- if (i != 1 || (Integer) blockstate.getValue(LeavesBlock.DISTANCE) != i) { +- levelaccessor.scheduleTick(blockpos, (Block) this, 1); ++ if (i != 1 || (Integer) state.getValue(LeavesBlock.DISTANCE) != i) { ++ level.scheduleTick(currentPos, (Block) this, 1); + } + +- return blockstate; ++ return state; + } + +- private static BlockState updateDistance(BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos) { ++ private static IBlockData updateDistance(IBlockData state, LevelAccessor level, BlockPos pos) { + int i = 7; +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); +- Direction[] adirection = Direction.values(); +- int j = adirection.length; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ Direction[] aenumdirection = Direction.values(); ++ int j = aenumdirection.length; + + for (int k = 0; k < j; ++k) { +- Direction direction = adirection[k]; ++ Direction enumdirection = aenumdirection[k]; + +- blockpos_mutableblockpos.setWithOffset(blockpos, direction); +- i = Math.min(i, getDistanceAt(levelaccessor.getBlockState(blockpos_mutableblockpos)) + 1); ++ blockposition_mutableblockposition.setWithOffset(pos, enumdirection); ++ i = Math.min(i, getDistanceAt(level.getBlockState(blockposition_mutableblockposition)) + 1); + if (i == 1) { + break; + } + } + +- return (BlockState) blockstate.setValue(LeavesBlock.DISTANCE, i); ++ return (IBlockData) state.setValue(LeavesBlock.DISTANCE, i); + } + +- private static int getDistanceAt(BlockState blockstate) { +- return getOptionalDistanceAt(blockstate).orElse(7); ++ private static int getDistanceAt(IBlockData neighbor) { ++ return getOptionalDistanceAt(neighbor).orElse(7); + } + +- public static OptionalInt getOptionalDistanceAt(BlockState blockstate) { +- return blockstate.is(BlockTags.LOGS) ? OptionalInt.of(0) : (blockstate.hasProperty(LeavesBlock.DISTANCE) ? OptionalInt.of((Integer) blockstate.getValue(LeavesBlock.DISTANCE)) : OptionalInt.empty()); ++ public static OptionalInt getOptionalDistanceAt(IBlockData state) { ++ return state.is(BlockTags.LOGS) ? OptionalInt.of(0) : (state.hasProperty(LeavesBlock.DISTANCE) ? OptionalInt.of((Integer) state.getValue(LeavesBlock.DISTANCE)) : OptionalInt.empty()); + } + + @Override +- @Override +- public FluidState getFluidState(BlockState blockstate) { +- return (Boolean) blockstate.getValue(LeavesBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(blockstate); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(LeavesBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override +- @Override +- public void animateTick(BlockState blockstate, Level level, BlockPos blockpos, RandomSource randomsource) { +- if (level.isRainingAt(blockpos.above())) { +- if (randomsource.nextInt(15) == 1) { +- BlockPos blockpos1 = blockpos.below(); +- BlockState blockstate1 = level.getBlockState(blockpos1); ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if (level.isRainingAt(pos.above())) { ++ if (random.nextInt(15) == 1) { ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + +- if (!blockstate1.canOcclude() || !blockstate1.isFaceSturdy(level, blockpos1, Direction.UP)) { +- ParticleUtils.spawnParticleBelow(level, blockpos, randomsource, ParticleTypes.DRIPPING_WATER); ++ if (!iblockdata1.canOcclude() || !iblockdata1.isFaceSturdy(level, blockposition1, Direction.UP)) { ++ ParticleUtils.spawnParticleBelow(level, pos, random, ParticleTypes.DRIPPING_WATER); + } + } + } + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(LeavesBlock.DISTANCE, LeavesBlock.PERSISTENT, LeavesBlock.WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(LeavesBlock.DISTANCE, LeavesBlock.PERSISTENT, LeavesBlock.WATERLOGGED); + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- FluidState fluidstate = blockplacecontext.getLevel().getFluidState(blockplacecontext.getClickedPos()); +- BlockState blockstate = (BlockState) ((BlockState) this.defaultBlockState().setValue(LeavesBlock.PERSISTENT, true)).setValue(LeavesBlock.WATERLOGGED, fluidstate.getType() == Fluids.WATER); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ FluidState fluid = context.getLevel().getFluidState(context.getClickedPos()); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) this.defaultBlockState().setValue(LeavesBlock.PERSISTENT, true)).setValue(LeavesBlock.WATERLOGGED, fluid.getType() == Fluids.WATER); + +- return updateDistance(blockstate, blockplacecontext.getLevel(), blockplacecontext.getClickedPos()); ++ return updateDistance(iblockdata, context.getLevel(), context.getClickedPos()); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/LecternBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/LecternBlock.java.patch new file mode 100644 index 0000000000..20097f8fde --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/LecternBlock.java.patch @@ -0,0 +1,379 @@ +--- a/net/minecraft/world/level/block/LecternBlock.java ++++ b/net/minecraft/world/level/block/LecternBlock.java +@@ -11,9 +11,9 @@ + import net.minecraft.stats.Stats; + import net.minecraft.tags.ItemTags; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; ++import net.minecraft.world.ITileInventory; + import net.minecraft.world.InteractionResult; +-import net.minecraft.world.MenuProvider; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; +@@ -25,13 +25,13 @@ + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.LecternBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.block.state.properties.DirectionProperty; + import net.minecraft.world.level.gameevent.GameEvent; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; +@@ -55,63 +55,56 @@ + private static final int PAGE_CHANGE_IMPULSE_TICKS = 2; + + @Override +- @Override + public MapCodec codec() { + return LecternBlock.CODEC; + } + +- protected LecternBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(LecternBlock.FACING, Direction.NORTH)).setValue(LecternBlock.POWERED, false)).setValue(LecternBlock.HAS_BOOK, false)); ++ protected LecternBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(LecternBlock.FACING, Direction.NORTH)).setValue(LecternBlock.POWERED, false)).setValue(LecternBlock.HAS_BOOK, false)); + } + + @Override +- @Override +- public RenderShape getRenderShape(BlockState blockstate) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Override +- @Override +- public VoxelShape getOcclusionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { ++ public VoxelShape getOcclusionShape(IBlockData state, BlockGetter level, BlockPos pos) { + return LecternBlock.SHAPE_COMMON; + } + + @Override +- @Override +- public boolean useShapeForLightOcclusion(BlockState blockstate) { ++ public boolean useShapeForLightOcclusion(IBlockData state) { + return true; + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- Level level = blockplacecontext.getLevel(); +- ItemStack itemstack = blockplacecontext.getItemInHand(); +- Player player = blockplacecontext.getPlayer(); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ Level world = context.getLevel(); ++ ItemStack itemstack = context.getItemInHand(); ++ Player entityhuman = context.getPlayer(); + boolean flag = false; + +- if (!level.isClientSide && player != null && player.canUseGameMasterBlocks()) { +- CompoundTag compoundtag = BlockItem.getBlockEntityData(itemstack); ++ if (!world.isClientSide && entityhuman != null && entityhuman.canUseGameMasterBlocks()) { ++ CompoundTag nbttagcompound = BlockItem.getBlockEntityData(itemstack); + +- if (compoundtag != null && compoundtag.contains("Book")) { ++ if (nbttagcompound != null && nbttagcompound.contains("Book")) { + flag = true; + } + } + +- return (BlockState) ((BlockState) this.defaultBlockState().setValue(LecternBlock.FACING, blockplacecontext.getHorizontalDirection().getOpposite())).setValue(LecternBlock.HAS_BOOK, flag); ++ return (IBlockData) ((IBlockData) this.defaultBlockState().setValue(LecternBlock.FACING, context.getHorizontalDirection().getOpposite())).setValue(LecternBlock.HAS_BOOK, flag); + } + + @Override +- @Override +- public VoxelShape getCollisionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return LecternBlock.SHAPE_COLLISION; + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- switch ((Direction) blockstate.getValue(LecternBlock.FACING)) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ switch ((Direction) state.getValue(LecternBlock.FACING)) { + case NORTH: + return LecternBlock.SHAPE_NORTH; + case SOUTH: +@@ -126,33 +119,29 @@ + } + + @Override +- @Override +- public BlockState rotate(BlockState blockstate, Rotation rotation) { +- return (BlockState) blockstate.setValue(LecternBlock.FACING, rotation.rotate((Direction) blockstate.getValue(LecternBlock.FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return (IBlockData) state.setValue(LecternBlock.FACING, rotation.rotate((Direction) state.getValue(LecternBlock.FACING))); + } + + @Override +- @Override +- public BlockState mirror(BlockState blockstate, Mirror mirror) { +- return blockstate.rotate(mirror.getRotation((Direction) blockstate.getValue(LecternBlock.FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(LecternBlock.FACING))); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(LecternBlock.FACING, LecternBlock.POWERED, LecternBlock.HAS_BOOK); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(LecternBlock.FACING, LecternBlock.POWERED, LecternBlock.HAS_BOOK); + } + + @Override +- @Override +- public BlockEntity newBlockEntity(BlockPos blockpos, BlockState blockstate) { +- return new LecternBlockEntity(blockpos, blockstate); ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ return new LecternBlockEntity(pos, state); + } + +- public static boolean tryPlaceBook(@Nullable Entity entity, Level level, BlockPos blockpos, BlockState blockstate, ItemStack itemstack) { +- if (!(Boolean) blockstate.getValue(LecternBlock.HAS_BOOK)) { ++ public static boolean tryPlaceBook(@Nullable Entity entity, Level level, BlockPos pos, IBlockData state, ItemStack stack) { ++ if (!(Boolean) state.getValue(LecternBlock.HAS_BOOK)) { + if (!level.isClientSide) { +- placeBook(entity, level, blockpos, blockstate, itemstack); ++ placeBook(entity, level, pos, state, stack); + } + + return true; +@@ -161,114 +150,108 @@ + } + } + +- private static void placeBook(@Nullable Entity entity, Level level, BlockPos blockpos, BlockState blockstate, ItemStack itemstack) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ private static void placeBook(@Nullable Entity entity, Level level, BlockPos pos, IBlockData state, ItemStack stack) { ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof LecternBlockEntity) { +- LecternBlockEntity lecternblockentity = (LecternBlockEntity) blockentity; ++ if (tileentity instanceof LecternBlockEntity) { ++ LecternBlockEntity tileentitylectern = (LecternBlockEntity) tileentity; + +- lecternblockentity.setBook(itemstack.split(1)); +- resetBookState(entity, level, blockpos, blockstate, true); +- level.playSound((Player) null, blockpos, SoundEvents.BOOK_PUT, SoundSource.BLOCKS, 1.0F, 1.0F); ++ tileentitylectern.setBook(stack.split(1)); ++ resetBookState(entity, level, pos, state, true); ++ level.playSound((Player) null, pos, SoundEvents.BOOK_PUT, SoundSource.BLOCKS, 1.0F, 1.0F); + } + + } + +- public static void resetBookState(@Nullable Entity entity, Level level, BlockPos blockpos, BlockState blockstate, boolean flag) { +- BlockState blockstate1 = (BlockState) ((BlockState) blockstate.setValue(LecternBlock.POWERED, false)).setValue(LecternBlock.HAS_BOOK, flag); ++ public static void resetBookState(@Nullable Entity entity, Level level, BlockPos pos, IBlockData state, boolean hasBook) { ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) state.setValue(LecternBlock.POWERED, false)).setValue(LecternBlock.HAS_BOOK, hasBook); + +- level.setBlock(blockpos, blockstate1, 3); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(entity, blockstate1)); +- updateBelow(level, blockpos, blockstate); ++ level.setBlock(pos, iblockdata1, 3); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, iblockdata1)); ++ updateBelow(level, pos, state); + } + +- public static void signalPageChange(Level level, BlockPos blockpos, BlockState blockstate) { +- changePowered(level, blockpos, blockstate, true); +- level.scheduleTick(blockpos, blockstate.getBlock(), 2); +- level.levelEvent(1043, blockpos, 0); ++ public static void signalPageChange(Level level, BlockPos pos, IBlockData state) { ++ changePowered(level, pos, state, true); ++ level.scheduleTick(pos, state.getBlock(), 2); ++ level.levelEvent(1043, pos, 0); + } + +- private static void changePowered(Level level, BlockPos blockpos, BlockState blockstate, boolean flag) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(LecternBlock.POWERED, flag), 3); +- updateBelow(level, blockpos, blockstate); ++ private static void changePowered(Level level, BlockPos pos, IBlockData state, boolean powered) { ++ level.setBlock(pos, (IBlockData) state.setValue(LecternBlock.POWERED, powered), 3); ++ updateBelow(level, pos, state); + } + +- private static void updateBelow(Level level, BlockPos blockpos, BlockState blockstate) { +- level.updateNeighborsAt(blockpos.below(), blockstate.getBlock()); ++ private static void updateBelow(Level level, BlockPos pos, IBlockData state) { ++ level.updateNeighborsAt(pos.below(), state.getBlock()); + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- changePowered(serverlevel, blockpos, blockstate, false); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ changePowered(level, pos, state, false); + } + + @Override +- @Override +- public void onRemove(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!blockstate.is(blockstate1.getBlock())) { +- if ((Boolean) blockstate.getValue(LecternBlock.HAS_BOOK)) { +- this.popBook(blockstate, level, blockpos); ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { ++ if (!state.is(newState.getBlock())) { ++ if ((Boolean) state.getValue(LecternBlock.HAS_BOOK)) { ++ this.popBook(state, level, pos); + } + +- if ((Boolean) blockstate.getValue(LecternBlock.POWERED)) { +- level.updateNeighborsAt(blockpos.below(), this); ++ if ((Boolean) state.getValue(LecternBlock.POWERED)) { ++ level.updateNeighborsAt(pos.below(), this); + } + +- super.onRemove(blockstate, level, blockpos, blockstate1, flag); ++ super.onRemove(state, level, pos, newState, isMoving); + } + } + +- private void popBook(BlockState blockstate, Level level, BlockPos blockpos) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ private void popBook(IBlockData state, Level level, BlockPos pos) { ++ BlockEntity tileentity = level.getBlockEntity(pos, false); // CraftBukkit - don't validate, type may be changed already + +- if (blockentity instanceof LecternBlockEntity) { +- LecternBlockEntity lecternblockentity = (LecternBlockEntity) blockentity; +- Direction direction = (Direction) blockstate.getValue(LecternBlock.FACING); +- ItemStack itemstack = lecternblockentity.getBook().copy(); +- float f = 0.25F * (float) direction.getStepX(); +- float f1 = 0.25F * (float) direction.getStepZ(); +- ItemEntity itementity = new ItemEntity(level, (double) blockpos.getX() + 0.5D + (double) f, (double) (blockpos.getY() + 1), (double) blockpos.getZ() + 0.5D + (double) f1, itemstack); ++ if (tileentity instanceof LecternBlockEntity) { ++ LecternBlockEntity tileentitylectern = (LecternBlockEntity) tileentity; ++ Direction enumdirection = (Direction) state.getValue(LecternBlock.FACING); ++ ItemStack itemstack = tileentitylectern.getBook().copy(); ++ if (itemstack.isEmpty()) return; // CraftBukkit - SPIGOT-5500 ++ float f = 0.25F * (float) enumdirection.getStepX(); ++ float f1 = 0.25F * (float) enumdirection.getStepZ(); ++ ItemEntity entityitem = new ItemEntity(level, (double) pos.getX() + 0.5D + (double) f, (double) (pos.getY() + 1), (double) pos.getZ() + 0.5D + (double) f1, itemstack); + +- itementity.setDefaultPickUpDelay(); +- level.addFreshEntity(itementity); +- lecternblockentity.clearContent(); ++ entityitem.setDefaultPickUpDelay(); ++ level.addFreshEntity(entityitem); ++ tileentitylectern.clearContent(); + } + + } + + @Override +- @Override +- public boolean isSignalSource(BlockState blockstate) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + + @Override +- @Override +- public int getSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return (Boolean) blockstate.getValue(LecternBlock.POWERED) ? 15 : 0; ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return (Boolean) blockState.getValue(LecternBlock.POWERED) ? 15 : 0; + } + + @Override +- @Override +- public int getDirectSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return direction == Direction.UP && (Boolean) blockstate.getValue(LecternBlock.POWERED) ? 15 : 0; ++ public int getDirectSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return side == Direction.UP && (Boolean) blockState.getValue(LecternBlock.POWERED) ? 15 : 0; + } + + @Override +- @Override +- public boolean hasAnalogOutputSignal(BlockState blockstate) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return true; + } + + @Override +- @Override +- public int getAnalogOutputSignal(BlockState blockstate, Level level, BlockPos blockpos) { +- if ((Boolean) blockstate.getValue(LecternBlock.HAS_BOOK)) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ public int getAnalogOutputSignal(IBlockData blockState, Level level, BlockPos pos) { ++ if ((Boolean) blockState.getValue(LecternBlock.HAS_BOOK)) { ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof LecternBlockEntity) { +- return ((LecternBlockEntity) blockentity).getRedstoneSignal(); ++ if (tileentity instanceof LecternBlockEntity) { ++ return ((LecternBlockEntity) tileentity).getRedstoneSignal(); + } + } + +@@ -276,16 +259,15 @@ + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- if ((Boolean) blockstate.getValue(LecternBlock.HAS_BOOK)) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ if ((Boolean) state.getValue(LecternBlock.HAS_BOOK)) { + if (!level.isClientSide) { +- this.openScreen(level, blockpos, player); ++ this.openScreen(level, pos, player); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + } else { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ ItemStack itemstack = player.getItemInHand(hand); + + return !itemstack.isEmpty() && !itemstack.is(ItemTags.LECTERN_BOOKS) ? InteractionResult.CONSUME : InteractionResult.PASS; + } +@@ -293,24 +275,22 @@ + + @Nullable + @Override +- @Override +- public MenuProvider getMenuProvider(BlockState blockstate, Level level, BlockPos blockpos) { +- return !(Boolean) blockstate.getValue(LecternBlock.HAS_BOOK) ? null : super.getMenuProvider(blockstate, level, blockpos); ++ public ITileInventory getMenuProvider(IBlockData state, Level level, BlockPos pos) { ++ return !(Boolean) state.getValue(LecternBlock.HAS_BOOK) ? null : super.getMenuProvider(state, level, pos); + } + +- private void openScreen(Level level, BlockPos blockpos, Player player) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ private void openScreen(Level level, BlockPos pos, Player player) { ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof LecternBlockEntity) { +- player.openMenu((LecternBlockEntity) blockentity); ++ if (tileentity instanceof LecternBlockEntity) { ++ player.openMenu((LecternBlockEntity) tileentity); + player.awardStat(Stats.INTERACT_WITH_LECTERN); + } + + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/LeverBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/LeverBlock.java.patch new file mode 100644 index 0000000000..227b0b7ccd --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/LeverBlock.java.patch @@ -0,0 +1,239 @@ +--- a/net/minecraft/world/level/block/LeverBlock.java ++++ b/net/minecraft/world/level/block/LeverBlock.java +@@ -4,11 +4,11 @@ + import java.util.function.BiConsumer; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.particles.DustParticleOptions; ++import net.minecraft.core.particles.ParticleParamRedstone; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; +@@ -18,7 +18,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.AttachFace; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; +@@ -27,6 +27,7 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class LeverBlock extends FaceAttachedHorizontalDirectionalBlock { + +@@ -45,22 +46,20 @@ + protected static final VoxelShape DOWN_AABB_X = Block.box(4.0D, 10.0D, 5.0D, 12.0D, 16.0D, 11.0D); + + @Override +- @Override + public MapCodec codec() { + return LeverBlock.CODEC; + } + +- protected LeverBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(LeverBlock.FACING, Direction.NORTH)).setValue(LeverBlock.POWERED, false)).setValue(LeverBlock.FACE, AttachFace.WALL)); ++ protected LeverBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(LeverBlock.FACING, Direction.NORTH)).setValue(LeverBlock.POWERED, false)).setValue(LeverBlock.FACE, AttachFace.WALL)); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- switch ((AttachFace) blockstate.getValue(LeverBlock.FACE)) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ switch ((AttachFace) state.getValue(LeverBlock.FACE)) { + case FLOOR: +- switch (((Direction) blockstate.getValue(LeverBlock.FACING)).getAxis()) { ++ switch (((Direction) state.getValue(LeverBlock.FACING)).getAxis()) { + case X: + return LeverBlock.UP_AABB_X; + case Z: +@@ -68,7 +67,7 @@ + return LeverBlock.UP_AABB_Z; + } + case WALL: +- switch ((Direction) blockstate.getValue(LeverBlock.FACING)) { ++ switch ((Direction) state.getValue(LeverBlock.FACING)) { + case EAST: + return LeverBlock.EAST_AABB; + case WEST: +@@ -81,7 +80,7 @@ + } + case CEILING: + default: +- switch (((Direction) blockstate.getValue(LeverBlock.FACING)).getAxis()) { ++ switch (((Direction) state.getValue(LeverBlock.FACING)).getAxis()) { + case X: + return LeverBlock.DOWN_AABB_X; + case Z: +@@ -92,101 +91,107 @@ + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- BlockState blockstate1; ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ IBlockData iblockdata1; + + if (level.isClientSide) { +- blockstate1 = (BlockState) blockstate.cycle(LeverBlock.POWERED); +- if ((Boolean) blockstate1.getValue(LeverBlock.POWERED)) { +- makeParticle(blockstate1, level, blockpos, 1.0F); ++ iblockdata1 = (IBlockData) state.cycle(LeverBlock.POWERED); ++ if ((Boolean) iblockdata1.getValue(LeverBlock.POWERED)) { ++ makeParticle(iblockdata1, level, pos, 1.0F); + } + + return InteractionResult.SUCCESS; + } else { +- blockstate1 = this.pull(blockstate, level, blockpos); +- float f = (Boolean) blockstate1.getValue(LeverBlock.POWERED) ? 0.6F : 0.5F; ++ // CraftBukkit start - Interact Lever ++ boolean powered = state.getValue(LeverBlock.POWERED); // Old powered state ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ int old = (powered) ? 15 : 0; ++ int current = (!powered) ? 15 : 0; + +- level.playSound((Player) null, blockpos, SoundEvents.LEVER_CLICK, SoundSource.BLOCKS, 0.3F, f); +- level.gameEvent((Entity) player, (Boolean) blockstate1.getValue(LeverBlock.POWERED) ? GameEvent.BLOCK_ACTIVATE : GameEvent.BLOCK_DEACTIVATE, blockpos); ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if ((eventRedstone.getNewCurrent() > 0) != (!powered)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ ++ iblockdata1 = this.pull(state, level, pos); ++ float f = (Boolean) iblockdata1.getValue(LeverBlock.POWERED) ? 0.6F : 0.5F; ++ ++ level.playSound((Player) null, pos, SoundEvents.LEVER_CLICK, SoundSource.BLOCKS, 0.3F, f); ++ level.gameEvent((Entity) player, (Boolean) iblockdata1.getValue(LeverBlock.POWERED) ? GameEvent.BLOCK_ACTIVATE : GameEvent.BLOCK_DEACTIVATE, pos); + return InteractionResult.CONSUME; + } + } + + @Override +- @Override +- public void onExplosionHit(BlockState blockstate, Level level, BlockPos blockpos, Explosion explosion, BiConsumer biconsumer) { +- if (explosion.getBlockInteraction() == Explosion.BlockInteraction.TRIGGER_BLOCK && !level.isClientSide()) { +- this.pull(blockstate, level, blockpos); ++ public void onExplosionHit(IBlockData iblockdata, Level world, BlockPos blockposition, Explosion explosion, BiConsumer biconsumer) { ++ if (explosion.getBlockInteraction() == Explosion.Effect.TRIGGER_BLOCK && !world.isClientSide()) { ++ this.pull(iblockdata, world, blockposition); + } + +- super.onExplosionHit(blockstate, level, blockpos, explosion, biconsumer); ++ super.onExplosionHit(iblockdata, world, blockposition, explosion, biconsumer); + } + +- public BlockState pull(BlockState blockstate, Level level, BlockPos blockpos) { +- blockstate = (BlockState) blockstate.cycle(LeverBlock.POWERED); +- level.setBlock(blockpos, blockstate, 3); +- this.updateNeighbours(blockstate, level, blockpos); +- return blockstate; ++ public IBlockData pull(IBlockData state, Level level, BlockPos pos) { ++ state = (IBlockData) state.cycle(LeverBlock.POWERED); ++ level.setBlock(pos, state, 3); ++ this.updateNeighbours(state, level, pos); ++ return state; + } + +- private static void makeParticle(BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos, float f) { +- Direction direction = ((Direction) blockstate.getValue(LeverBlock.FACING)).getOpposite(); +- Direction direction1 = getConnectedDirection(blockstate).getOpposite(); +- double d0 = (double) blockpos.getX() + 0.5D + 0.1D * (double) direction.getStepX() + 0.2D * (double) direction1.getStepX(); +- double d1 = (double) blockpos.getY() + 0.5D + 0.1D * (double) direction.getStepY() + 0.2D * (double) direction1.getStepY(); +- double d2 = (double) blockpos.getZ() + 0.5D + 0.1D * (double) direction.getStepZ() + 0.2D * (double) direction1.getStepZ(); ++ private static void makeParticle(IBlockData state, LevelAccessor level, BlockPos pos, float alpha) { ++ Direction enumdirection = ((Direction) state.getValue(LeverBlock.FACING)).getOpposite(); ++ Direction enumdirection1 = getConnectedDirection(state).getOpposite(); ++ double d0 = (double) pos.getX() + 0.5D + 0.1D * (double) enumdirection.getStepX() + 0.2D * (double) enumdirection1.getStepX(); ++ double d1 = (double) pos.getY() + 0.5D + 0.1D * (double) enumdirection.getStepY() + 0.2D * (double) enumdirection1.getStepY(); ++ double d2 = (double) pos.getZ() + 0.5D + 0.1D * (double) enumdirection.getStepZ() + 0.2D * (double) enumdirection1.getStepZ(); + +- levelaccessor.addParticle(new DustParticleOptions(DustParticleOptions.REDSTONE_PARTICLE_COLOR, f), d0, d1, d2, 0.0D, 0.0D, 0.0D); ++ level.addParticle(new ParticleParamRedstone(ParticleParamRedstone.REDSTONE_PARTICLE_COLOR, alpha), d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + + @Override +- @Override +- public void animateTick(BlockState blockstate, Level level, BlockPos blockpos, RandomSource randomsource) { +- if ((Boolean) blockstate.getValue(LeverBlock.POWERED) && randomsource.nextFloat() < 0.25F) { +- makeParticle(blockstate, level, blockpos, 0.5F); ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(LeverBlock.POWERED) && random.nextFloat() < 0.25F) { ++ makeParticle(state, level, pos, 0.5F); + } + + } + + @Override +- @Override +- public void onRemove(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!flag && !blockstate.is(blockstate1.getBlock())) { +- if ((Boolean) blockstate.getValue(LeverBlock.POWERED)) { +- this.updateNeighbours(blockstate, level, blockpos); ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { ++ if (!isMoving && !state.is(newState.getBlock())) { ++ if ((Boolean) state.getValue(LeverBlock.POWERED)) { ++ this.updateNeighbours(state, level, pos); + } + +- super.onRemove(blockstate, level, blockpos, blockstate1, flag); ++ super.onRemove(state, level, pos, newState, isMoving); + } + } + + @Override +- @Override +- public int getSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return (Boolean) blockstate.getValue(LeverBlock.POWERED) ? 15 : 0; ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return (Boolean) blockState.getValue(LeverBlock.POWERED) ? 15 : 0; + } + + @Override +- @Override +- public int getDirectSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return (Boolean) blockstate.getValue(LeverBlock.POWERED) && getConnectedDirection(blockstate) == direction ? 15 : 0; ++ public int getDirectSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return (Boolean) blockState.getValue(LeverBlock.POWERED) && getConnectedDirection(blockState) == side ? 15 : 0; + } + + @Override +- @Override +- public boolean isSignalSource(BlockState blockstate) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + +- private void updateNeighbours(BlockState blockstate, Level level, BlockPos blockpos) { +- level.updateNeighborsAt(blockpos, this); +- level.updateNeighborsAt(blockpos.relative(getConnectedDirection(blockstate).getOpposite()), this); ++ private void updateNeighbours(IBlockData state, Level level, BlockPos pos) { ++ level.updateNeighborsAt(pos, this); ++ level.updateNeighborsAt(pos.relative(getConnectedDirection(state).getOpposite()), this); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(LeverBlock.FACE, LeverBlock.FACING, LeverBlock.POWERED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(LeverBlock.FACE, LeverBlock.FACING, LeverBlock.POWERED); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/LightningRodBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/LightningRodBlock.java.patch new file mode 100644 index 0000000000..dae930f7d5 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/LightningRodBlock.java.patch @@ -0,0 +1,220 @@ +--- a/net/minecraft/world/level/block/LightningRodBlock.java ++++ b/net/minecraft/world/level/block/LightningRodBlock.java +@@ -22,7 +22,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -32,6 +32,10 @@ + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockRedstoneEvent; ++// CraftBukkit end + + public class LightningRodBlock extends RodBlock implements SimpleWaterloggedBlock { + +@@ -43,134 +47,133 @@ + private static final int SPARK_CYCLE = 200; + + @Override +- @Override + public MapCodec codec() { + return LightningRodBlock.CODEC; + } + +- public LightningRodBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(LightningRodBlock.FACING, Direction.UP)).setValue(LightningRodBlock.WATERLOGGED, false)).setValue(LightningRodBlock.POWERED, false)); ++ public LightningRodBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(LightningRodBlock.FACING, Direction.UP)).setValue(LightningRodBlock.WATERLOGGED, false)).setValue(LightningRodBlock.POWERED, false)); + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- FluidState fluidstate = blockplacecontext.getLevel().getFluidState(blockplacecontext.getClickedPos()); +- boolean flag = fluidstate.getType() == Fluids.WATER; ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ FluidState fluid = context.getLevel().getFluidState(context.getClickedPos()); ++ boolean flag = fluid.getType() == Fluids.WATER; + +- return (BlockState) ((BlockState) this.defaultBlockState().setValue(LightningRodBlock.FACING, blockplacecontext.getClickedFace())).setValue(LightningRodBlock.WATERLOGGED, flag); ++ return (IBlockData) ((IBlockData) this.defaultBlockState().setValue(LightningRodBlock.FACING, context.getClickedFace())).setValue(LightningRodBlock.WATERLOGGED, flag); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if ((Boolean) blockstate.getValue(LightningRodBlock.WATERLOGGED)) { +- levelaccessor.scheduleTick(blockpos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(levelaccessor)); ++ public IBlockData updateShape(IBlockData state, Direction direction, IBlockData neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { ++ if ((Boolean) state.getValue(LightningRodBlock.WATERLOGGED)) { ++ level.scheduleTick(pos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, direction, neighborState, level, pos, neighborPos); + } + + @Override +- @Override +- public FluidState getFluidState(BlockState blockstate) { +- return (Boolean) blockstate.getValue(LightningRodBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(blockstate); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(LightningRodBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override +- @Override +- public int getSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return (Boolean) blockstate.getValue(LightningRodBlock.POWERED) ? 15 : 0; ++ public int getSignal(IBlockData state, BlockGetter level, BlockPos pos, Direction direction) { ++ return (Boolean) state.getValue(LightningRodBlock.POWERED) ? 15 : 0; + } + + @Override +- @Override +- public int getDirectSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return (Boolean) blockstate.getValue(LightningRodBlock.POWERED) && blockstate.getValue(LightningRodBlock.FACING) == direction ? 15 : 0; ++ public int getDirectSignal(IBlockData state, BlockGetter level, BlockPos pos, Direction direction) { ++ return (Boolean) state.getValue(LightningRodBlock.POWERED) && state.getValue(LightningRodBlock.FACING) == direction ? 15 : 0; + } + +- public void onLightningStrike(BlockState blockstate, Level level, BlockPos blockpos) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(LightningRodBlock.POWERED, true), 3); +- this.updateNeighbours(blockstate, level, blockpos); +- level.scheduleTick(blockpos, (Block) this, 8); +- level.levelEvent(3002, blockpos, ((Direction) blockstate.getValue(LightningRodBlock.FACING)).getAxis().ordinal()); ++ public void onLightningStrike(IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ boolean powered = state.getValue(LightningRodBlock.POWERED); ++ int old = (powered) ? 15 : 0; ++ int current = (!powered) ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(level, pos), old, current); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if (eventRedstone.getNewCurrent() <= 0) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(LightningRodBlock.POWERED, true), 3); ++ this.updateNeighbours(state, level, pos); ++ level.scheduleTick(pos, (Block) this, 8); ++ level.levelEvent(3002, pos, ((Direction) state.getValue(LightningRodBlock.FACING)).getAxis().ordinal()); + } + +- private void updateNeighbours(BlockState blockstate, Level level, BlockPos blockpos) { +- level.updateNeighborsAt(blockpos.relative(((Direction) blockstate.getValue(LightningRodBlock.FACING)).getOpposite()), this); ++ private void updateNeighbours(IBlockData state, Level level, BlockPos pos) { ++ level.updateNeighborsAt(pos.relative(((Direction) state.getValue(LightningRodBlock.FACING)).getOpposite()), this); + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(LightningRodBlock.POWERED, false), 3); +- this.updateNeighbours(blockstate, serverlevel, blockpos); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ level.setBlock(pos, (IBlockData) state.setValue(LightningRodBlock.POWERED, false), 3); ++ this.updateNeighbours(state, level, pos); + } + + @Override +- @Override +- public void animateTick(BlockState blockstate, Level level, BlockPos blockpos, RandomSource randomsource) { +- if (level.isThundering() && (long) level.random.nextInt(200) <= level.getGameTime() % 200L && blockpos.getY() == level.getHeight(Heightmap.Types.WORLD_SURFACE, blockpos.getX(), blockpos.getZ()) - 1) { +- ParticleUtils.spawnParticlesAlongAxis(((Direction) blockstate.getValue(LightningRodBlock.FACING)).getAxis(), level, blockpos, 0.125D, ParticleTypes.ELECTRIC_SPARK, UniformInt.of(1, 2)); ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if (level.isThundering() && (long) level.random.nextInt(200) <= level.getGameTime() % 200L && pos.getY() == level.getHeight(Heightmap.Types.WORLD_SURFACE, pos.getX(), pos.getZ()) - 1) { ++ ParticleUtils.spawnParticlesAlongAxis(((Direction) state.getValue(LightningRodBlock.FACING)).getAxis(), level, pos, 0.125D, ParticleTypes.ELECTRIC_SPARK, UniformInt.of(1, 2)); + } + } + + @Override +- @Override +- public void onRemove(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!blockstate.is(blockstate1.getBlock())) { +- if ((Boolean) blockstate.getValue(LightningRodBlock.POWERED)) { +- this.updateNeighbours(blockstate, level, blockpos); ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean movedByPiston) { ++ if (!state.is(newState.getBlock())) { ++ if ((Boolean) state.getValue(LightningRodBlock.POWERED)) { ++ this.updateNeighbours(state, level, pos); + } + +- super.onRemove(blockstate, level, blockpos, blockstate1, flag); ++ super.onRemove(state, level, pos, newState, movedByPiston); + } + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!blockstate.is(blockstate1.getBlock())) { +- if ((Boolean) blockstate.getValue(LightningRodBlock.POWERED) && !level.getBlockTicks().hasScheduledTick(blockpos, this)) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(LightningRodBlock.POWERED, false), 18); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean movedByPiston) { ++ if (!state.is(oldState.getBlock())) { ++ if ((Boolean) state.getValue(LightningRodBlock.POWERED) && !level.getBlockTicks().hasScheduledTick(pos, this)) { ++ level.setBlock(pos, (IBlockData) state.setValue(LightningRodBlock.POWERED, false), 18); + } + + } + } + + @Override +- @Override +- public void onProjectileHit(Level level, BlockState blockstate, BlockHitResult blockhitresult, Projectile projectile) { ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { + if (level.isThundering() && projectile instanceof ThrownTrident && ((ThrownTrident) projectile).isChanneling()) { +- BlockPos blockpos = blockhitresult.getBlockPos(); ++ BlockPos blockposition = hit.getBlockPos(); + +- if (level.canSeeSky(blockpos)) { +- LightningBolt lightningbolt = (LightningBolt) EntityType.LIGHTNING_BOLT.create(level); ++ if (level.canSeeSky(blockposition)) { ++ LightningBolt entitylightning = (LightningBolt) EntityType.LIGHTNING_BOLT.create(level); + +- if (lightningbolt != null) { +- lightningbolt.moveTo(Vec3.atBottomCenterOf(blockpos.above())); ++ if (entitylightning != null) { ++ entitylightning.moveTo(Vec3.atBottomCenterOf(blockposition.above())); + Entity entity = projectile.getOwner(); + +- lightningbolt.setCause(entity instanceof ServerPlayer ? (ServerPlayer) entity : null); +- level.addFreshEntity(lightningbolt); ++ entitylightning.setCause(entity instanceof ServerPlayer ? (ServerPlayer) entity : null); ++ ((ServerLevel) level).strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.TRIDENT); // CraftBukkit + } + +- level.playSound((Player) null, blockpos, SoundEvents.TRIDENT_THUNDER, SoundSource.WEATHER, 5.0F, 1.0F); ++ level.playSound((Player) null, blockposition, SoundEvents.TRIDENT_THUNDER, SoundSource.WEATHER, 5.0F, 1.0F); + } + } + + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(LightningRodBlock.FACING, LightningRodBlock.POWERED, LightningRodBlock.WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(LightningRodBlock.FACING, LightningRodBlock.POWERED, LightningRodBlock.WATERLOGGED); + } + + @Override +- @Override +- public boolean isSignalSource(BlockState blockstate) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/LiquidBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/LiquidBlock.java.patch new file mode 100644 index 0000000000..a655696951 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/LiquidBlock.java.patch @@ -0,0 +1,278 @@ +--- a/net/minecraft/world/level/block/LiquidBlock.java ++++ b/net/minecraft/world/level/block/LiquidBlock.java +@@ -24,13 +24,13 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.level.material.FlowingFluid; + import net.minecraft.world.level.material.FluidState; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.level.storage.loot.LootParams; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; +@@ -38,26 +38,26 @@ + + public class LiquidBlock extends Block implements BucketPickup { + +- private static final Codec FLOWING_FLUID = BuiltInRegistries.FLUID.byNameCodec().comapFlatMap((fluid) -> { +- DataResult dataresult; ++ private static final Codec FLOWING_FLUID = BuiltInRegistries.FLUID.byNameCodec().comapFlatMap((fluidtype) -> { ++ DataResult dataresult; // CraftBukkit - decompile error + +- if (fluid instanceof FlowingFluid) { +- FlowingFluid flowingfluid = (FlowingFluid) fluid; ++ if (fluidtype instanceof FlowingFluid) { ++ FlowingFluid fluidtypeflowing = (FlowingFluid) fluidtype; + +- dataresult = DataResult.success(flowingfluid); ++ dataresult = DataResult.success(fluidtypeflowing); + } else { + dataresult = DataResult.error(() -> { +- return "Not a flowing fluid: " + fluid; ++ return "Not a flowing fluid: " + fluidtype; + }); + } + + return dataresult; +- }, (flowingfluid) -> { +- return flowingfluid; ++ }, (fluidtypeflowing) -> { ++ return fluidtypeflowing; + }); + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- return instance.group(LiquidBlock.FLOWING_FLUID.fieldOf("fluid").forGetter((liquidblock) -> { +- return liquidblock.fluid; ++ return instance.group(LiquidBlock.FLOWING_FLUID.fieldOf("fluid").forGetter((blockfluids) -> { ++ return blockfluids.fluid; + }), propertiesCodec()).apply(instance, LiquidBlock::new); + }); + public static final IntegerProperty LEVEL = BlockStateProperties.LEVEL; +@@ -67,135 +67,127 @@ + public static final ImmutableList POSSIBLE_FLOW_DIRECTIONS = ImmutableList.of(Direction.DOWN, Direction.SOUTH, Direction.NORTH, Direction.EAST, Direction.WEST); + + @Override +- @Override + public MapCodec codec() { + return LiquidBlock.CODEC; + } + +- protected LiquidBlock(FlowingFluid flowingfluid, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.fluid = flowingfluid; ++ protected LiquidBlock(FlowingFluid fluid, BlockBehaviour.Properties properties) { ++ super(properties); ++ this.fluid = fluid; + this.stateCache = Lists.newArrayList(); +- this.stateCache.add(flowingfluid.getSource(false)); ++ this.stateCache.add(fluid.getSource(false)); + + for (int i = 1; i < 8; ++i) { +- this.stateCache.add(flowingfluid.getFlowing(8 - i, false)); ++ this.stateCache.add(fluid.getFlowing(8 - i, false)); + } + +- this.stateCache.add(flowingfluid.getFlowing(8, true)); +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(LiquidBlock.LEVEL, 0)); ++ this.stateCache.add(fluid.getFlowing(8, true)); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(LiquidBlock.LEVEL, 0)); + } + + @Override +- @Override +- public VoxelShape getCollisionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return collisioncontext.isAbove(LiquidBlock.STABLE_SHAPE, blockpos, true) && (Integer) blockstate.getValue(LiquidBlock.LEVEL) == 0 && collisioncontext.canStandOnFluid(blockgetter.getFluidState(blockpos.above()), blockstate.getFluidState()) ? LiquidBlock.STABLE_SHAPE : Shapes.empty(); ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return context.isAbove(LiquidBlock.STABLE_SHAPE, pos, true) && (Integer) state.getValue(LiquidBlock.LEVEL) == 0 && context.canStandOnFluid(level.getFluidState(pos.above()), state.getFluidState()) ? LiquidBlock.STABLE_SHAPE : Shapes.empty(); + } + + @Override +- @Override +- public boolean isRandomlyTicking(BlockState blockstate) { +- return blockstate.getFluidState().isRandomlyTicking(); ++ public boolean isRandomlyTicking(IBlockData state) { ++ return state.getFluidState().isRandomlyTicking(); + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- blockstate.getFluidState().randomTick(serverlevel, blockpos, randomsource); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ state.getFluidState().randomTick(level, pos, random); + } + + @Override +- @Override +- public boolean propagatesSkylightDown(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { ++ public boolean propagatesSkylightDown(IBlockData state, BlockGetter reader, BlockPos pos) { + return false; + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return !this.fluid.is(FluidTags.LAVA); + } + + @Override +- @Override +- public FluidState getFluidState(BlockState blockstate) { +- int i = (Integer) blockstate.getValue(LiquidBlock.LEVEL); ++ public FluidState getFluidState(IBlockData state) { ++ int i = (Integer) state.getValue(LiquidBlock.LEVEL); + + return (FluidState) this.stateCache.get(Math.min(i, 8)); + } + + @Override +- @Override +- public boolean skipRendering(BlockState blockstate, BlockState blockstate1, Direction direction) { +- return blockstate1.getFluidState().getType().isSame(this.fluid); ++ public boolean skipRendering(IBlockData state, IBlockData adjacentBlockState, Direction side) { ++ return adjacentBlockState.getFluidState().getType().isSame(this.fluid); + } + + @Override +- @Override +- public RenderShape getRenderShape(BlockState blockstate) { +- return RenderShape.INVISIBLE; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.INVISIBLE; + } + + @Override +- @Override +- public List getDrops(BlockState blockstate, LootParams.Builder lootparams_builder) { ++ public List getDrops(IBlockData state, LootParams.Builder params) { + return Collections.emptyList(); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return Shapes.empty(); + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (this.shouldSpreadLiquid(level, blockpos, blockstate)) { +- level.scheduleTick(blockpos, blockstate.getFluidState().getType(), this.fluid.getTickDelay(level)); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ if (this.shouldSpreadLiquid(level, pos, state)) { ++ level.scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay(level)); + } + + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if (blockstate.getFluidState().isSource() || blockstate1.getFluidState().isSource()) { +- levelaccessor.scheduleTick(blockpos, blockstate.getFluidState().getType(), this.fluid.getTickDelay(levelaccessor)); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if (state.getFluidState().isSource() || facingState.getFluidState().isSource()) { ++ level.scheduleTick(currentPos, state.getFluidState().getType(), this.fluid.getTickDelay(level)); + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- @Override +- public void neighborChanged(BlockState blockstate, Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { +- if (this.shouldSpreadLiquid(level, blockpos, blockstate)) { +- level.scheduleTick(blockpos, blockstate.getFluidState().getType(), this.fluid.getTickDelay(level)); ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ if (this.shouldSpreadLiquid(level, pos, state)) { ++ level.scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay(level)); + } + + } + +- private boolean shouldSpreadLiquid(Level level, BlockPos blockpos, BlockState blockstate) { ++ private boolean shouldSpreadLiquid(Level level, BlockPos pos, IBlockData state) { + if (this.fluid.is(FluidTags.LAVA)) { +- boolean flag = level.getBlockState(blockpos.below()).is(Blocks.SOUL_SOIL); ++ boolean flag = level.getBlockState(pos.below()).is(Blocks.SOUL_SOIL); + UnmodifiableIterator unmodifiableiterator = LiquidBlock.POSSIBLE_FLOW_DIRECTIONS.iterator(); + + while (unmodifiableiterator.hasNext()) { +- Direction direction = (Direction) unmodifiableiterator.next(); +- BlockPos blockpos1 = blockpos.relative(direction.getOpposite()); ++ Direction enumdirection = (Direction) unmodifiableiterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection.getOpposite()); + +- if (level.getFluidState(blockpos1).is(FluidTags.WATER)) { +- Block block = level.getFluidState(blockpos).isSource() ? Blocks.OBSIDIAN : Blocks.COBBLESTONE; ++ if (level.getFluidState(blockposition1).is(FluidTags.WATER)) { ++ Block block = level.getFluidState(pos).isSource() ? Blocks.OBSIDIAN : Blocks.COBBLESTONE; + +- level.setBlockAndUpdate(blockpos, block.defaultBlockState()); +- this.fizz(level, blockpos); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, block.defaultBlockState())) { ++ this.fizz(level, pos); ++ } ++ // CraftBukkit end + return false; + } + +- if (flag && level.getBlockState(blockpos1).is(Blocks.BLUE_ICE)) { +- level.setBlockAndUpdate(blockpos, Blocks.BASALT.defaultBlockState()); +- this.fizz(level, blockpos); ++ if (flag && level.getBlockState(blockposition1).is(Blocks.BLUE_ICE)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, Blocks.BASALT.defaultBlockState())) { ++ this.fizz(level, pos); ++ } ++ // CraftBukkit end + return false; + } + } +@@ -204,21 +196,19 @@ + return true; + } + +- private void fizz(LevelAccessor levelaccessor, BlockPos blockpos) { +- levelaccessor.levelEvent(1501, blockpos, 0); ++ private void fizz(LevelAccessor level, BlockPos pos) { ++ level.levelEvent(1501, pos, 0); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(LiquidBlock.LEVEL); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(LiquidBlock.LEVEL); + } + + @Override +- @Override +- public ItemStack pickupBlock(@Nullable Player player, LevelAccessor levelaccessor, BlockPos blockpos, BlockState blockstate) { +- if ((Integer) blockstate.getValue(LiquidBlock.LEVEL) == 0) { +- levelaccessor.setBlock(blockpos, Blocks.AIR.defaultBlockState(), 11); ++ public ItemStack pickupBlock(@Nullable Player entityhuman, LevelAccessor generatoraccess, BlockPos blockposition, IBlockData iblockdata) { ++ if ((Integer) iblockdata.getValue(LiquidBlock.LEVEL) == 0) { ++ generatoraccess.setBlock(blockposition, Blocks.AIR.defaultBlockState(), 11); + return new ItemStack(this.fluid.getBucket()); + } else { + return ItemStack.EMPTY; +@@ -226,7 +216,6 @@ + } + + @Override +- @Override + public Optional getPickupSound() { + return this.fluid.getPickupSound(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/MagmaBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/MagmaBlock.java.patch new file mode 100644 index 0000000000..57e8fee85d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/MagmaBlock.java.patch @@ -0,0 +1,70 @@ +--- a/net/minecraft/world/level/block/MagmaBlock.java ++++ b/net/minecraft/world/level/block/MagmaBlock.java +@@ -11,7 +11,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public class MagmaBlock extends Block { + +@@ -19,44 +19,41 @@ + private static final int BUBBLE_COLUMN_CHECK_DELAY = 20; + + @Override +- @Override + public MapCodec codec() { + return MagmaBlock.CODEC; + } + +- public MagmaBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ public MagmaBlock(BlockBehaviour.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public void stepOn(Level level, BlockPos blockpos, BlockState blockstate, Entity entity) { ++ public void stepOn(Level level, BlockPos pos, IBlockData state, Entity entity) { + if (!entity.isSteppingCarefully() && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity) entity)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); // CraftBukkit + entity.hurt(level.damageSources().hotFloor(), 1.0F); ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = null; // CraftBukkit + } + +- super.stepOn(level, blockpos, blockstate, entity); ++ super.stepOn(level, pos, state, entity); + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- BubbleColumnBlock.updateColumn(serverlevel, blockpos.above(), blockstate); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ BubbleColumnBlock.updateColumn(level, pos.above(), state); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if (direction == Direction.UP && blockstate1.is(Blocks.WATER)) { +- levelaccessor.scheduleTick(blockpos, (Block) this, 20); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if (facing == Direction.UP && facingState.is(Blocks.WATER)) { ++ level.scheduleTick(currentPos, (Block) this, 20); + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- level.scheduleTick(blockpos, (Block) this, 20); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ level.scheduleTick(pos, (Block) this, 20); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/MultifaceSpreader.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/MultifaceSpreader.java.patch new file mode 100644 index 0000000000..af9a84273d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/MultifaceSpreader.java.patch @@ -0,0 +1,271 @@ +--- a/net/minecraft/world/level/block/MultifaceSpreader.java ++++ b/net/minecraft/world/level/block/MultifaceSpreader.java +@@ -9,83 +9,83 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.LevelAccessor; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public class MultifaceSpreader { + + public static final MultifaceSpreader.SpreadType[] DEFAULT_SPREAD_ORDER = new MultifaceSpreader.SpreadType[]{MultifaceSpreader.SpreadType.SAME_POSITION, MultifaceSpreader.SpreadType.SAME_PLANE, MultifaceSpreader.SpreadType.WRAP_AROUND}; + private final MultifaceSpreader.SpreadConfig config; + +- public MultifaceSpreader(MultifaceBlock multifaceblock) { +- this((MultifaceSpreader.SpreadConfig) (new MultifaceSpreader.DefaultSpreaderConfig(multifaceblock))); ++ public MultifaceSpreader(MultifaceBlock block) { ++ this((MultifaceSpreader.SpreadConfig) (new MultifaceSpreader.DefaultSpreaderConfig(block))); + } + +- public MultifaceSpreader(MultifaceSpreader.SpreadConfig multifacespreader_spreadconfig) { +- this.config = multifacespreader_spreadconfig; ++ public MultifaceSpreader(MultifaceSpreader.SpreadConfig config) { ++ this.config = config; + } + +- public boolean canSpreadInAnyDirection(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return Direction.stream().anyMatch((direction1) -> { +- MultifaceSpreader.SpreadConfig multifacespreader_spreadconfig = this.config; ++ public boolean canSpreadInAnyDirection(IBlockData state, BlockGetter level, BlockPos pos, Direction spreadDirection) { ++ return Direction.stream().anyMatch((enumdirection1) -> { ++ MultifaceSpreader.SpreadConfig multifacespreader_b = this.config; + + Objects.requireNonNull(this.config); +- return this.getSpreadFromFaceTowardDirection(blockstate, blockgetter, blockpos, direction, direction1, multifacespreader_spreadconfig::canSpreadInto).isPresent(); ++ return this.getSpreadFromFaceTowardDirection(state, level, pos, spreadDirection, enumdirection1, multifacespreader_b::canSpreadInto).isPresent(); + }); + } + +- public Optional spreadFromRandomFaceTowardRandomDirection(BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos, RandomSource randomsource) { +- return (Optional) Direction.allShuffled(randomsource).stream().filter((direction) -> { +- return this.config.canSpreadFrom(blockstate, direction); +- }).map((direction) -> { +- return this.spreadFromFaceTowardRandomDirection(blockstate, levelaccessor, blockpos, direction, randomsource, false); ++ public Optional spreadFromRandomFaceTowardRandomDirection(IBlockData state, LevelAccessor level, BlockPos pos, RandomSource random) { ++ return (Optional) Direction.allShuffled(random).stream().filter((enumdirection) -> { ++ return this.config.canSpreadFrom(state, enumdirection); ++ }).map((enumdirection) -> { ++ return this.spreadFromFaceTowardRandomDirection(state, level, pos, enumdirection, random, false); + }).filter(Optional::isPresent).findFirst().orElse(Optional.empty()); + } + +- public long spreadAll(BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos, boolean flag) { +- return (Long) Direction.stream().filter((direction) -> { +- return this.config.canSpreadFrom(blockstate, direction); +- }).map((direction) -> { +- return this.spreadFromFaceTowardAllDirections(blockstate, levelaccessor, blockpos, direction, flag); ++ public long spreadAll(IBlockData state, LevelAccessor level, BlockPos pos, boolean markForPostprocessing) { ++ return (Long) Direction.stream().filter((enumdirection) -> { ++ return this.config.canSpreadFrom(state, enumdirection); ++ }).map((enumdirection) -> { ++ return this.spreadFromFaceTowardAllDirections(state, level, pos, enumdirection, markForPostprocessing); + }).reduce(0L, Long::sum); + } + +- public Optional spreadFromFaceTowardRandomDirection(BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos, Direction direction, RandomSource randomsource, boolean flag) { +- return (Optional) Direction.allShuffled(randomsource).stream().map((direction1) -> { +- return this.spreadFromFaceTowardDirection(blockstate, levelaccessor, blockpos, direction, direction1, flag); ++ public Optional spreadFromFaceTowardRandomDirection(IBlockData state, LevelAccessor level, BlockPos pos, Direction spreadDirection, RandomSource random, boolean markForPostprocessing) { ++ return (Optional) Direction.allShuffled(random).stream().map((enumdirection1) -> { ++ return this.spreadFromFaceTowardDirection(state, level, pos, spreadDirection, enumdirection1, markForPostprocessing); + }).filter(Optional::isPresent).findFirst().orElse(Optional.empty()); + } + +- private long spreadFromFaceTowardAllDirections(BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos, Direction direction, boolean flag) { +- return Direction.stream().map((direction1) -> { +- return this.spreadFromFaceTowardDirection(blockstate, levelaccessor, blockpos, direction, direction1, flag); ++ private long spreadFromFaceTowardAllDirections(IBlockData state, LevelAccessor level, BlockPos pos, Direction spreadDirection, boolean markForPostprocessing) { ++ return Direction.stream().map((enumdirection1) -> { ++ return this.spreadFromFaceTowardDirection(state, level, pos, spreadDirection, enumdirection1, markForPostprocessing); + }).filter(Optional::isPresent).count(); + } + + @VisibleForTesting +- public Optional spreadFromFaceTowardDirection(BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos, Direction direction, Direction direction1, boolean flag) { +- MultifaceSpreader.SpreadConfig multifacespreader_spreadconfig = this.config; ++ public Optional spreadFromFaceTowardDirection(IBlockData state, LevelAccessor level, BlockPos pos, Direction spreadDirection, Direction face, boolean markForPostprocessing) { ++ MultifaceSpreader.SpreadConfig multifacespreader_b = this.config; + + Objects.requireNonNull(this.config); +- return this.getSpreadFromFaceTowardDirection(blockstate, levelaccessor, blockpos, direction, direction1, multifacespreader_spreadconfig::canSpreadInto).flatMap((multifacespreader_spreadpos) -> { +- return this.spreadToFace(levelaccessor, multifacespreader_spreadpos, flag); ++ return this.getSpreadFromFaceTowardDirection(state, level, pos, spreadDirection, face, multifacespreader_b::canSpreadInto).flatMap((multifacespreader_c) -> { ++ return this.spreadToFace(level, multifacespreader_c, markForPostprocessing); + }); + } + +- public Optional getSpreadFromFaceTowardDirection(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction, Direction direction1, MultifaceSpreader.SpreadPredicate multifacespreader_spreadpredicate) { +- if (direction1.getAxis() == direction.getAxis()) { ++ public Optional getSpreadFromFaceTowardDirection(IBlockData state, BlockGetter level, BlockPos pos, Direction spreadDirection, Direction face, MultifaceSpreader.SpreadPredicate predicate) { ++ if (face.getAxis() == spreadDirection.getAxis()) { + return Optional.empty(); +- } else if (!this.config.isOtherBlockValidAsSource(blockstate) && (!this.config.hasFace(blockstate, direction) || this.config.hasFace(blockstate, direction1))) { ++ } else if (!this.config.isOtherBlockValidAsSource(state) && (!this.config.hasFace(state, spreadDirection) || this.config.hasFace(state, face))) { + return Optional.empty(); + } else { +- MultifaceSpreader.SpreadType[] amultifacespreader_spreadtype = this.config.getSpreadTypes(); +- int i = amultifacespreader_spreadtype.length; ++ MultifaceSpreader.SpreadType[] amultifacespreader_e = this.config.getSpreadTypes(); ++ int i = amultifacespreader_e.length; + + for (int j = 0; j < i; ++j) { +- MultifaceSpreader.SpreadType multifacespreader_spreadtype = amultifacespreader_spreadtype[j]; +- MultifaceSpreader.SpreadPos multifacespreader_spreadpos = multifacespreader_spreadtype.getSpreadPos(blockpos, direction1, direction); ++ MultifaceSpreader.SpreadType multifacespreader_e = amultifacespreader_e[j]; ++ MultifaceSpreader.c multifacespreader_c = multifacespreader_e.getSpreadPos(pos, face, spreadDirection); + +- if (multifacespreader_spreadpredicate.test(blockgetter, blockpos, multifacespreader_spreadpos)) { +- return Optional.of(multifacespreader_spreadpos); ++ if (predicate.test(level, pos, multifacespreader_c)) { ++ return Optional.of(multifacespreader_c); + } + } + +@@ -93,72 +93,70 @@ + } + } + +- public Optional spreadToFace(LevelAccessor levelaccessor, MultifaceSpreader.SpreadPos multifacespreader_spreadpos, boolean flag) { +- BlockState blockstate = levelaccessor.getBlockState(multifacespreader_spreadpos.pos()); ++ public Optional spreadToFace(LevelAccessor level, MultifaceSpreader.c pos, boolean markForPostprocessing) { ++ IBlockData iblockdata = level.getBlockState(pos.pos()); + +- return this.config.placeBlock(levelaccessor, multifacespreader_spreadpos, blockstate, flag) ? Optional.of(multifacespreader_spreadpos) : Optional.empty(); ++ return this.config.placeBlock(level, pos, iblockdata, markForPostprocessing) ? Optional.of(pos) : Optional.empty(); + } + + public static class DefaultSpreaderConfig implements MultifaceSpreader.SpreadConfig { + + protected MultifaceBlock block; + +- public DefaultSpreaderConfig(MultifaceBlock multifaceblock) { +- this.block = multifaceblock; ++ public DefaultSpreaderConfig(MultifaceBlock block) { ++ this.block = block; + } + + @Nullable + @Override +- @Override +- public BlockState getStateForPlacement(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return this.block.getStateForPlacement(blockstate, blockgetter, blockpos, direction); ++ public IBlockData getStateForPlacement(IBlockData currentState, BlockGetter level, BlockPos pos, Direction lookingDirection) { ++ return this.block.getStateForPlacement(currentState, level, pos, lookingDirection); + } + +- protected boolean stateCanBeReplaced(BlockGetter blockgetter, BlockPos blockpos, BlockPos blockpos1, Direction direction, BlockState blockstate) { +- return blockstate.isAir() || blockstate.is((Block) this.block) || blockstate.is(Blocks.WATER) && blockstate.getFluidState().isSource(); ++ protected boolean stateCanBeReplaced(BlockGetter level, BlockPos pos, BlockPos spreadPos, Direction direction, IBlockData state) { ++ return state.isAir() || state.is((Block) this.block) || state.is(Blocks.WATER) && state.getFluidState().isSource(); + } + + @Override +- @Override +- public boolean canSpreadInto(BlockGetter blockgetter, BlockPos blockpos, MultifaceSpreader.SpreadPos multifacespreader_spreadpos) { +- BlockState blockstate = blockgetter.getBlockState(multifacespreader_spreadpos.pos()); ++ public boolean canSpreadInto(BlockGetter level, BlockPos pos, MultifaceSpreader.c spreadPos) { ++ IBlockData iblockdata = level.getBlockState(spreadPos.pos()); + +- return this.stateCanBeReplaced(blockgetter, blockpos, multifacespreader_spreadpos.pos(), multifacespreader_spreadpos.face(), blockstate) && this.block.isValidStateForPlacement(blockgetter, blockstate, multifacespreader_spreadpos.pos(), multifacespreader_spreadpos.face()); ++ return this.stateCanBeReplaced(level, pos, spreadPos.pos(), spreadPos.face(), iblockdata) && this.block.isValidStateForPlacement(level, iblockdata, spreadPos.pos(), spreadPos.face()); + } + } + + public interface SpreadConfig { + + @Nullable +- BlockState getStateForPlacement(BlockState currentState, BlockGetter level, BlockPos pos, Direction lookingDirection); ++ IBlockData getStateForPlacement(IBlockData currentState, BlockGetter level, BlockPos pos, Direction lookingDirection); + +- boolean canSpreadInto(BlockGetter level, BlockPos pos, MultifaceSpreader.SpreadPos spreadPos); ++ boolean canSpreadInto(BlockGetter level, BlockPos pos, MultifaceSpreader.c spreadPos); + + default MultifaceSpreader.SpreadType[] getSpreadTypes() { + return MultifaceSpreader.DEFAULT_SPREAD_ORDER; + } + +- default boolean hasFace(BlockState blockstate, Direction direction) { +- return MultifaceBlock.hasFace(blockstate, direction); ++ default boolean hasFace(IBlockData state, Direction direction) { ++ return MultifaceBlock.hasFace(state, direction); + } + +- default boolean isOtherBlockValidAsSource(BlockState blockstate) { ++ default boolean isOtherBlockValidAsSource(IBlockData otherBlock) { + return false; + } + +- default boolean canSpreadFrom(BlockState blockstate, Direction direction) { +- return this.isOtherBlockValidAsSource(blockstate) || this.hasFace(blockstate, direction); ++ default boolean canSpreadFrom(IBlockData state, Direction direction) { ++ return this.isOtherBlockValidAsSource(state) || this.hasFace(state, direction); + } + +- default boolean placeBlock(LevelAccessor levelaccessor, MultifaceSpreader.SpreadPos multifacespreader_spreadpos, BlockState blockstate, boolean flag) { +- BlockState blockstate1 = this.getStateForPlacement(blockstate, levelaccessor, multifacespreader_spreadpos.pos(), multifacespreader_spreadpos.face()); ++ default boolean placeBlock(LevelAccessor level, MultifaceSpreader.c pos, IBlockData state, boolean markForPostprocessing) { ++ IBlockData iblockdata1 = this.getStateForPlacement(state, level, pos.pos(), pos.face()); + +- if (blockstate1 != null) { +- if (flag) { +- levelaccessor.getChunk(multifacespreader_spreadpos.pos()).markPosForPostprocessing(multifacespreader_spreadpos.pos()); ++ if (iblockdata1 != null) { ++ if (markForPostprocessing) { ++ level.getChunk(pos.pos()).markPosForPostprocessing(pos.pos()); + } + +- return levelaccessor.setBlock(multifacespreader_spreadpos.pos(), blockstate1, 2); ++ return org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos.source(), pos.pos(), iblockdata1, 2); // CraftBukkit + } else { + return false; + } +@@ -168,39 +166,36 @@ + @FunctionalInterface + public interface SpreadPredicate { + +- boolean test(BlockGetter level, BlockPos pos, MultifaceSpreader.SpreadPos spreadPos); ++ boolean test(BlockGetter level, BlockPos pos, MultifaceSpreader.c spreadPos); + } + + public static enum SpreadType { + + SAME_POSITION { + @Override +- @Override +- public MultifaceSpreader.SpreadPos getSpreadPos(BlockPos blockpos, Direction direction, Direction direction1) { +- return new MultifaceSpreader.SpreadPos(blockpos, direction); ++ public MultifaceSpreader.c getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection) { ++ return new MultifaceSpreader.c(pos, face, pos); // CraftBukkit + } + }, + SAME_PLANE { + @Override +- @Override +- public MultifaceSpreader.SpreadPos getSpreadPos(BlockPos blockpos, Direction direction, Direction direction1) { +- return new MultifaceSpreader.SpreadPos(blockpos.relative(direction), direction1); ++ public MultifaceSpreader.c getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection) { ++ return new MultifaceSpreader.c(pos.relative(face), spreadDirection, pos); // CraftBukkit + } + }, + WRAP_AROUND { + @Override +- @Override +- public MultifaceSpreader.SpreadPos getSpreadPos(BlockPos blockpos, Direction direction, Direction direction1) { +- return new MultifaceSpreader.SpreadPos(blockpos.relative(direction).relative(direction1), direction.getOpposite()); ++ public MultifaceSpreader.c getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection) { ++ return new MultifaceSpreader.c(pos.relative(face).relative(spreadDirection), face.getOpposite(), pos); // CraftBukkit + } + }; + + SpreadType() {} + +- public abstract MultifaceSpreader.SpreadPos getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection); ++ public abstract MultifaceSpreader.c getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection); + } + +- public static record SpreadPos(BlockPos pos, Direction face) { ++ public static record c(BlockPos pos, Direction face, BlockPos source) { // CraftBukkit + + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/MushroomBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/MushroomBlock.java.patch new file mode 100644 index 0000000000..604218a399 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/MushroomBlock.java.patch @@ -0,0 +1,161 @@ +--- a/net/minecraft/world/level/block/MushroomBlock.java ++++ b/net/minecraft/world/level/block/MushroomBlock.java +@@ -15,16 +15,19 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.TreeType; ++// CraftBukkit end + + public class MushroomBlock extends BushBlock implements BonemealableBlock { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- return instance.group(ResourceKey.codec(Registries.CONFIGURED_FEATURE).fieldOf("feature").forGetter((mushroomblock) -> { +- return mushroomblock.feature; ++ return instance.group(ResourceKey.codec(Registries.CONFIGURED_FEATURE).fieldOf("feature").forGetter((blockmushroom) -> { ++ return blockmushroom.feature; + }), propertiesCodec()).apply(instance, MushroomBlock::new); + }); + protected static final float AABB_OFFSET = 3.0F; +@@ -32,34 +35,31 @@ + private final ResourceKey> feature; + + @Override +- @Override + public MapCodec codec() { + return MushroomBlock.CODEC; + } + +- public MushroomBlock(ResourceKey> resourcekey, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ public MushroomBlock(ResourceKey> resourcekey, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info); + this.feature = resourcekey; + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return MushroomBlock.SHAPE; + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (randomsource.nextInt(25) == 0) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (random.nextInt(25) == 0) { + int i = 5; + boolean flag = true; +- Iterator iterator = BlockPos.betweenClosed(blockpos.offset(-4, -1, -4), blockpos.offset(4, 1, 4)).iterator(); ++ Iterator iterator = BlockPos.betweenClosed(pos.offset(-4, -1, -4), pos.offset(4, 1, 4)).iterator(); + + while (iterator.hasNext()) { +- BlockPos blockpos1 = (BlockPos) iterator.next(); ++ BlockPos blockposition1 = (BlockPos) iterator.next(); + +- if (serverlevel.getBlockState(blockpos1).is((Block) this)) { ++ if (level.getBlockState(blockposition1).is((Block) this)) { + --i; + if (i <= 0) { + return; +@@ -67,69 +67,65 @@ + } + } + +- BlockPos blockpos2 = blockpos.offset(randomsource.nextInt(3) - 1, randomsource.nextInt(2) - randomsource.nextInt(2), randomsource.nextInt(3) - 1); ++ BlockPos blockposition2 = pos.offset(random.nextInt(3) - 1, random.nextInt(2) - random.nextInt(2), random.nextInt(3) - 1); + + for (int j = 0; j < 4; ++j) { +- if (serverlevel.isEmptyBlock(blockpos2) && blockstate.canSurvive(serverlevel, blockpos2)) { +- blockpos = blockpos2; ++ if (level.isEmptyBlock(blockposition2) && state.canSurvive(level, blockposition2)) { ++ pos = blockposition2; + } + +- blockpos2 = blockpos.offset(randomsource.nextInt(3) - 1, randomsource.nextInt(2) - randomsource.nextInt(2), randomsource.nextInt(3) - 1); ++ blockposition2 = pos.offset(random.nextInt(3) - 1, random.nextInt(2) - random.nextInt(2), random.nextInt(3) - 1); + } + +- if (serverlevel.isEmptyBlock(blockpos2) && blockstate.canSurvive(serverlevel, blockpos2)) { +- serverlevel.setBlock(blockpos2, blockstate, 2); ++ if (level.isEmptyBlock(blockposition2) && state.canSurvive(level, blockposition2)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition2, state, 2); // CraftBukkit + } + } + + } + + @Override +- @Override +- protected boolean mayPlaceOn(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return blockstate.isSolidRender(blockgetter, blockpos); ++ protected boolean mayPlaceOn(IBlockData state, BlockGetter level, BlockPos pos) { ++ return state.isSolidRender(level, pos); + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- BlockPos blockpos1 = blockpos.below(); +- BlockState blockstate1 = levelreader.getBlockState(blockpos1); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + +- return blockstate1.is(BlockTags.MUSHROOM_GROW_BLOCK) ? true : levelreader.getRawBrightness(blockpos, 0) < 13 && this.mayPlaceOn(blockstate1, levelreader, blockpos1); ++ return iblockdata1.is(BlockTags.MUSHROOM_GROW_BLOCK) ? true : level.getRawBrightness(pos, 0) < 13 && this.mayPlaceOn(iblockdata1, level, blockposition1); + } + +- public boolean growMushroom(ServerLevel serverlevel, BlockPos blockpos, BlockState blockstate, RandomSource randomsource) { +- Optional>> optional = serverlevel.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE).getHolder(this.feature); ++ public boolean growMushroom(ServerLevel level, BlockPos pos, IBlockData state, RandomSource random) { ++ Optional>> optional = level.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE).getHolder(this.feature); + + if (optional.isEmpty()) { + return false; + } else { +- serverlevel.removeBlock(blockpos, false); +- if (((ConfiguredFeature) ((Holder) optional.get()).value()).place(serverlevel, serverlevel.getChunkSource().getGenerator(), randomsource, blockpos)) { ++ level.removeBlock(pos, false); ++ SaplingBlock.treeType = (this == Blocks.BROWN_MUSHROOM) ? TreeType.BROWN_MUSHROOM : TreeType.BROWN_MUSHROOM; // CraftBukkit ++ if (((ConfiguredFeature) ((Holder) optional.get()).value()).place(level, level.getChunkSource().getGenerator(), random, pos)) { + return true; + } else { +- serverlevel.setBlock(blockpos, blockstate, 3); ++ level.setBlock(pos, state, 3); + return false; + } + } + } + + @Override +- @Override +- public boolean isValidBonemealTarget(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { + return true; + } + + @Override +- @Override +- public boolean isBonemealSuccess(Level level, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { +- return (double) randomsource.nextFloat() < 0.4D; ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { ++ return (double) random.nextFloat() < 0.4D; + } + + @Override +- @Override +- public void performBonemeal(ServerLevel serverlevel, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { +- this.growMushroom(serverlevel, blockpos, blockstate, randomsource); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ this.growMushroom(level, pos, state, random); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/NetherPortalBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/NetherPortalBlock.java.patch new file mode 100644 index 0000000000..af49a6be37 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/NetherPortalBlock.java.patch @@ -0,0 +1,195 @@ +--- a/net/minecraft/world/level/block/NetherPortalBlock.java ++++ b/net/minecraft/world/level/block/NetherPortalBlock.java +@@ -10,7 +10,7 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.GameRules; +@@ -18,13 +18,16 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.EnumProperty; + import net.minecraft.world.level.portal.PortalShape; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.event.entity.EntityPortalEnterEvent; ++// CraftBukkit end + + public class NetherPortalBlock extends Block { + +@@ -35,20 +38,18 @@ + protected static final VoxelShape Z_AXIS_AABB = Block.box(6.0D, 0.0D, 0.0D, 10.0D, 16.0D, 16.0D); + + @Override +- @Override + public MapCodec codec() { + return NetherPortalBlock.CODEC; + } + +- public NetherPortalBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(NetherPortalBlock.AXIS, Direction.Axis.X)); ++ public NetherPortalBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(NetherPortalBlock.AXIS, Direction.Axis.X)); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- switch ((Direction.Axis) blockstate.getValue(NetherPortalBlock.AXIS)) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ switch ((Direction.Axis) state.getValue(NetherPortalBlock.AXIS)) { + case Z: + return NetherPortalBlock.Z_AXIS_AABB; + case X: +@@ -58,15 +59,15 @@ + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (serverlevel.dimensionType().natural() && serverlevel.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && randomsource.nextInt(2000) < serverlevel.getDifficulty().getId()) { +- while (serverlevel.getBlockState(blockpos).is((Block) this)) { +- blockpos = blockpos.below(); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (level.dimensionType().natural() && level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && random.nextInt(2000) < level.getDifficulty().getId()) { ++ while (level.getBlockState(pos).is((Block) this)) { ++ pos = pos.below(); + } + +- if (serverlevel.getBlockState(blockpos).isValidSpawn(serverlevel, blockpos, EntityType.ZOMBIFIED_PIGLIN)) { +- Entity entity = EntityType.ZOMBIFIED_PIGLIN.spawn(serverlevel, blockpos.above(), MobSpawnType.STRUCTURE); ++ if (level.getBlockState(pos).isValidSpawn(level, pos, EntityType.ZOMBIFIED_PIGLIN)) { ++ // CraftBukkit - set spawn reason to NETHER_PORTAL ++ Entity entity = EntityType.ZOMBIFIED_PIGLIN.spawn(level, pos.above(), EnumMobSpawn.STRUCTURE, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NETHER_PORTAL); + + if (entity != null) { + entity.setPortalCooldown(); +@@ -77,46 +78,47 @@ + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- Direction.Axis direction_axis = direction.getAxis(); +- Direction.Axis direction_axis1 = (Direction.Axis) blockstate.getValue(NetherPortalBlock.AXIS); +- boolean flag = direction_axis1 != direction_axis && direction_axis.isHorizontal(); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ Direction.Axis enumdirection_enumaxis = facing.getAxis(); ++ Direction.Axis enumdirection_enumaxis1 = (Direction.Axis) state.getValue(NetherPortalBlock.AXIS); ++ boolean flag = enumdirection_enumaxis1 != enumdirection_enumaxis && enumdirection_enumaxis.isHorizontal(); + +- return !flag && !blockstate1.is((Block) this) && !(new PortalShape(levelaccessor, blockpos, direction_axis1)).isComplete() ? Blocks.AIR.defaultBlockState() : super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return !flag && !facingState.is((Block) this) && !(new PortalShape(level, currentPos, enumdirection_enumaxis1)).isComplete() ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { + if (entity.canChangeDimensions()) { +- entity.handleInsidePortal(blockpos); ++ // CraftBukkit start - Entity in portal ++ EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(level.getWorld(), pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ // CraftBukkit end ++ entity.handleInsidePortal(pos); + } + + } + + @Override +- @Override +- public void animateTick(BlockState blockstate, Level level, BlockPos blockpos, RandomSource randomsource) { +- if (randomsource.nextInt(100) == 0) { +- level.playLocalSound((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D, SoundEvents.PORTAL_AMBIENT, SoundSource.BLOCKS, 0.5F, randomsource.nextFloat() * 0.4F + 0.8F, false); ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if (random.nextInt(100) == 0) { ++ level.playLocalSound((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.PORTAL_AMBIENT, SoundSource.BLOCKS, 0.5F, random.nextFloat() * 0.4F + 0.8F, false); + } + + for (int i = 0; i < 4; ++i) { +- double d0 = (double) blockpos.getX() + randomsource.nextDouble(); +- double d1 = (double) blockpos.getY() + randomsource.nextDouble(); +- double d2 = (double) blockpos.getZ() + randomsource.nextDouble(); +- double d3 = ((double) randomsource.nextFloat() - 0.5D) * 0.5D; +- double d4 = ((double) randomsource.nextFloat() - 0.5D) * 0.5D; +- double d5 = ((double) randomsource.nextFloat() - 0.5D) * 0.5D; +- int j = randomsource.nextInt(2) * 2 - 1; ++ double d0 = (double) pos.getX() + random.nextDouble(); ++ double d1 = (double) pos.getY() + random.nextDouble(); ++ double d2 = (double) pos.getZ() + random.nextDouble(); ++ double d3 = ((double) random.nextFloat() - 0.5D) * 0.5D; ++ double d4 = ((double) random.nextFloat() - 0.5D) * 0.5D; ++ double d5 = ((double) random.nextFloat() - 0.5D) * 0.5D; ++ int j = random.nextInt(2) * 2 - 1; + +- if (!level.getBlockState(blockpos.west()).is((Block) this) && !level.getBlockState(blockpos.east()).is((Block) this)) { +- d0 = (double) blockpos.getX() + 0.5D + 0.25D * (double) j; +- d3 = (double) (randomsource.nextFloat() * 2.0F * (float) j); ++ if (!level.getBlockState(pos.west()).is((Block) this) && !level.getBlockState(pos.east()).is((Block) this)) { ++ d0 = (double) pos.getX() + 0.5D + 0.25D * (double) j; ++ d3 = (double) (random.nextFloat() * 2.0F * (float) j); + } else { +- d2 = (double) blockpos.getZ() + 0.5D + 0.25D * (double) j; +- d5 = (double) (randomsource.nextFloat() * 2.0F * (float) j); ++ d2 = (double) pos.getZ() + 0.5D + 0.25D * (double) j; ++ d5 = (double) (random.nextFloat() * 2.0F * (float) j); + } + + level.addParticle(ParticleTypes.PORTAL, d0, d1, d2, d3, d4, d5); +@@ -125,33 +127,30 @@ + } + + @Override +- @Override +- public ItemStack getCloneItemStack(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { ++ public ItemStack getCloneItemStack(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { + return ItemStack.EMPTY; + } + + @Override +- @Override +- public BlockState rotate(BlockState blockstate, Rotation rotation) { +- switch (rotation) { ++ public IBlockData rotate(IBlockData state, Rotation rot) { ++ switch (rot) { + case COUNTERCLOCKWISE_90: + case CLOCKWISE_90: +- switch ((Direction.Axis) blockstate.getValue(NetherPortalBlock.AXIS)) { ++ switch ((Direction.Axis) state.getValue(NetherPortalBlock.AXIS)) { + case Z: +- return (BlockState) blockstate.setValue(NetherPortalBlock.AXIS, Direction.Axis.X); ++ return (IBlockData) state.setValue(NetherPortalBlock.AXIS, Direction.Axis.X); + case X: +- return (BlockState) blockstate.setValue(NetherPortalBlock.AXIS, Direction.Axis.Z); ++ return (IBlockData) state.setValue(NetherPortalBlock.AXIS, Direction.Axis.Z); + default: +- return blockstate; ++ return state; + } + default: +- return blockstate; ++ return state; + } + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(NetherPortalBlock.AXIS); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(NetherPortalBlock.AXIS); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/NetherWartBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/NetherWartBlock.java.patch new file mode 100644 index 0000000000..b1b431ef39 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/NetherWartBlock.java.patch @@ -0,0 +1,84 @@ +--- a/net/minecraft/world/level/block/NetherWartBlock.java ++++ b/net/minecraft/world/level/block/NetherWartBlock.java +@@ -9,7 +9,7 @@ + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; +@@ -24,55 +24,48 @@ + private static final VoxelShape[] SHAPE_BY_AGE = new VoxelShape[]{Block.box(0.0D, 0.0D, 0.0D, 16.0D, 5.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 8.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 11.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 14.0D, 16.0D)}; + + @Override +- @Override + public MapCodec codec() { + return NetherWartBlock.CODEC; + } + +- protected NetherWartBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(NetherWartBlock.AGE, 0)); ++ protected NetherWartBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(NetherWartBlock.AGE, 0)); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return NetherWartBlock.SHAPE_BY_AGE[(Integer) blockstate.getValue(NetherWartBlock.AGE)]; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return NetherWartBlock.SHAPE_BY_AGE[(Integer) state.getValue(NetherWartBlock.AGE)]; + } + + @Override +- @Override +- protected boolean mayPlaceOn(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return blockstate.is(Blocks.SOUL_SAND); ++ protected boolean mayPlaceOn(IBlockData state, BlockGetter level, BlockPos pos) { ++ return state.is(Blocks.SOUL_SAND); + } + + @Override +- @Override +- public boolean isRandomlyTicking(BlockState blockstate) { +- return (Integer) blockstate.getValue(NetherWartBlock.AGE) < 3; ++ public boolean isRandomlyTicking(IBlockData state) { ++ return (Integer) state.getValue(NetherWartBlock.AGE) < 3; + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- int i = (Integer) blockstate.getValue(NetherWartBlock.AGE); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ int i = (Integer) state.getValue(NetherWartBlock.AGE); + +- if (i < 3 && randomsource.nextInt(10) == 0) { +- blockstate = (BlockState) blockstate.setValue(NetherWartBlock.AGE, i + 1); +- serverlevel.setBlock(blockpos, blockstate, 2); ++ if (i < 3 && random.nextInt(10) == 0) { ++ state = (IBlockData) state.setValue(NetherWartBlock.AGE, i + 1); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, state, 2); // CraftBukkit + } + + } + + @Override +- @Override +- public ItemStack getCloneItemStack(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { ++ public ItemStack getCloneItemStack(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { + return new ItemStack(Items.NETHER_WART); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(NetherWartBlock.AGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(NetherWartBlock.AGE); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/NoteBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/NoteBlock.java.patch new file mode 100644 index 0000000000..527baf7acd --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/NoteBlock.java.patch @@ -0,0 +1,226 @@ +--- a/net/minecraft/world/level/block/NoteBlock.java ++++ b/net/minecraft/world/level/block/NoteBlock.java +@@ -11,7 +11,7 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; + import net.minecraft.tags.ItemTags; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; +@@ -22,7 +22,7 @@ + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.SkullBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -41,146 +41,145 @@ + public static final int NOTE_VOLUME = 3; + + @Override +- @Override + public MapCodec codec() { + return NoteBlock.CODEC; + } + +- public NoteBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(NoteBlock.INSTRUMENT, NoteBlockInstrument.HARP)).setValue(NoteBlock.NOTE, 0)).setValue(NoteBlock.POWERED, false)); ++ public NoteBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(NoteBlock.INSTRUMENT, NoteBlockInstrument.HARP)).setValue(NoteBlock.NOTE, 0)).setValue(NoteBlock.POWERED, false)); + } + +- private BlockState setInstrument(LevelAccessor levelaccessor, BlockPos blockpos, BlockState blockstate) { +- NoteBlockInstrument noteblockinstrument = levelaccessor.getBlockState(blockpos.above()).instrument(); ++ private IBlockData setInstrument(LevelAccessor level, BlockPos pos, IBlockData state) { ++ NoteBlockInstrument blockpropertyinstrument = level.getBlockState(pos.above()).instrument(); + +- if (noteblockinstrument.worksAboveNoteBlock()) { +- return (BlockState) blockstate.setValue(NoteBlock.INSTRUMENT, noteblockinstrument); ++ if (blockpropertyinstrument.worksAboveNoteBlock()) { ++ return (IBlockData) state.setValue(NoteBlock.INSTRUMENT, blockpropertyinstrument); + } else { +- NoteBlockInstrument noteblockinstrument1 = levelaccessor.getBlockState(blockpos.below()).instrument(); +- NoteBlockInstrument noteblockinstrument2 = noteblockinstrument1.worksAboveNoteBlock() ? NoteBlockInstrument.HARP : noteblockinstrument1; ++ NoteBlockInstrument blockpropertyinstrument1 = level.getBlockState(pos.below()).instrument(); ++ NoteBlockInstrument blockpropertyinstrument2 = blockpropertyinstrument1.worksAboveNoteBlock() ? NoteBlockInstrument.HARP : blockpropertyinstrument1; + +- return (BlockState) blockstate.setValue(NoteBlock.INSTRUMENT, noteblockinstrument2); ++ return (IBlockData) state.setValue(NoteBlock.INSTRUMENT, blockpropertyinstrument2); + } + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- return this.setInstrument(blockplacecontext.getLevel(), blockplacecontext.getClickedPos(), this.defaultBlockState()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return this.setInstrument(context.getLevel(), context.getClickedPos(), this.defaultBlockState()); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- boolean flag = direction.getAxis() == Direction.Axis.Y; ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ boolean flag = facing.getAxis() == Direction.Axis.Y; + +- return flag ? this.setInstrument(levelaccessor, blockpos, blockstate) : super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return flag ? this.setInstrument(level, currentPos, state) : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- @Override +- public void neighborChanged(BlockState blockstate, Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { +- boolean flag1 = level.hasNeighborSignal(blockpos); ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ boolean flag1 = level.hasNeighborSignal(pos); + +- if (flag1 != (Boolean) blockstate.getValue(NoteBlock.POWERED)) { ++ if (flag1 != (Boolean) state.getValue(NoteBlock.POWERED)) { + if (flag1) { +- this.playNote((Entity) null, blockstate, level, blockpos); ++ this.playNote((Entity) null, state, level, pos); ++ state = level.getBlockState(pos); // CraftBukkit - SPIGOT-5617: update in case changed in event + } + +- level.setBlock(blockpos, (BlockState) blockstate.setValue(NoteBlock.POWERED, flag1), 3); ++ level.setBlock(pos, (IBlockData) state.setValue(NoteBlock.POWERED, flag1), 3); + } + + } + +- private void playNote(@Nullable Entity entity, BlockState blockstate, Level level, BlockPos blockpos) { +- if (((NoteBlockInstrument) blockstate.getValue(NoteBlock.INSTRUMENT)).worksAboveNoteBlock() || level.getBlockState(blockpos.above()).isAir()) { +- level.blockEvent(blockpos, this, 0, 0); +- level.gameEvent(entity, GameEvent.NOTE_BLOCK_PLAY, blockpos); ++ private void playNote(@Nullable Entity entity, IBlockData state, Level level, BlockPos pos) { ++ if (((NoteBlockInstrument) state.getValue(NoteBlock.INSTRUMENT)).worksAboveNoteBlock() || level.getBlockState(pos.above()).isAir()) { ++ // CraftBukkit start ++ org.bukkit.event.block.NotePlayEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callNotePlayEvent(level, pos, state.getValue(NoteBlock.INSTRUMENT), state.getValue(NoteBlock.NOTE)); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.blockEvent(pos, this, 0, 0); ++ level.gameEvent(entity, GameEvent.NOTE_BLOCK_PLAY, pos); + } + + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ ItemStack itemstack = player.getItemInHand(hand); + +- if (itemstack.is(ItemTags.NOTE_BLOCK_TOP_INSTRUMENTS) && blockhitresult.getDirection() == Direction.UP) { ++ if (itemstack.is(ItemTags.NOTE_BLOCK_TOP_INSTRUMENTS) && hit.getDirection() == Direction.UP) { + return InteractionResult.PASS; + } else if (level.isClientSide) { + return InteractionResult.SUCCESS; + } else { +- blockstate = (BlockState) blockstate.cycle(NoteBlock.NOTE); +- level.setBlock(blockpos, blockstate, 3); +- this.playNote(player, blockstate, level, blockpos); ++ state = (IBlockData) state.cycle(NoteBlock.NOTE); ++ level.setBlock(pos, state, 3); ++ this.playNote(player, state, level, pos); + player.awardStat(Stats.TUNE_NOTEBLOCK); + return InteractionResult.CONSUME; + } + } + + @Override +- @Override +- public void attack(BlockState blockstate, Level level, BlockPos blockpos, Player player) { ++ public void attack(IBlockData state, Level level, BlockPos pos, Player player) { + if (!level.isClientSide) { +- this.playNote(player, blockstate, level, blockpos); ++ this.playNote(player, state, level, pos); + player.awardStat(Stats.PLAY_NOTEBLOCK); + } + } + +- public static float getPitchFromNote(int i) { +- return (float) Math.pow(2.0D, (double) (i - 12) / 12.0D); ++ public static float getPitchFromNote(int note) { ++ return (float) Math.pow(2.0D, (double) (note - 12) / 12.0D); + } + + @Override +- @Override +- public boolean triggerEvent(BlockState blockstate, Level level, BlockPos blockpos, int i, int j) { +- NoteBlockInstrument noteblockinstrument = (NoteBlockInstrument) blockstate.getValue(NoteBlock.INSTRUMENT); ++ public boolean triggerEvent(IBlockData state, Level level, BlockPos pos, int id, int param) { ++ NoteBlockInstrument blockpropertyinstrument = (NoteBlockInstrument) state.getValue(NoteBlock.INSTRUMENT); + float f; + +- if (noteblockinstrument.isTunable()) { +- int k = (Integer) blockstate.getValue(NoteBlock.NOTE); ++ if (blockpropertyinstrument.isTunable()) { ++ int k = (Integer) state.getValue(NoteBlock.NOTE); + + f = getPitchFromNote(k); +- level.addParticle(ParticleTypes.NOTE, (double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 1.2D, (double) blockpos.getZ() + 0.5D, (double) k / 24.0D, 0.0D, 0.0D); ++ level.addParticle(ParticleTypes.NOTE, (double) pos.getX() + 0.5D, (double) pos.getY() + 1.2D, (double) pos.getZ() + 0.5D, (double) k / 24.0D, 0.0D, 0.0D); + } else { + f = 1.0F; + } + + Holder holder; + +- if (noteblockinstrument.hasCustomSound()) { +- ResourceLocation resourcelocation = this.getCustomSoundId(level, blockpos); ++ if (blockpropertyinstrument.hasCustomSound()) { ++ ResourceLocation minecraftkey = this.getCustomSoundId(level, pos); + +- if (resourcelocation == null) { ++ if (minecraftkey == null) { + return false; + } + +- holder = Holder.direct(SoundEvent.createVariableRangeEvent(resourcelocation)); ++ holder = Holder.direct(SoundEvent.createVariableRangeEvent(minecraftkey)); + } else { +- holder = noteblockinstrument.getSoundEvent(); ++ holder = blockpropertyinstrument.getSoundEvent(); + } + +- level.playSeededSound((Player) null, (double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D, holder, SoundSource.RECORDS, 3.0F, f, level.random.nextLong()); ++ level.playSeededSound((Player) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, holder, SoundSource.RECORDS, 3.0F, f, level.random.nextLong()); + return true; + } + + @Nullable +- private ResourceLocation getCustomSoundId(Level level, BlockPos blockpos) { +- BlockEntity blockentity = level.getBlockEntity(blockpos.above()); ++ private ResourceLocation getCustomSoundId(Level level, BlockPos pos) { ++ BlockEntity tileentity = level.getBlockEntity(pos.above()); + +- if (blockentity instanceof SkullBlockEntity) { +- SkullBlockEntity skullblockentity = (SkullBlockEntity) blockentity; ++ if (tileentity instanceof SkullBlockEntity) { ++ SkullBlockEntity tileentityskull = (SkullBlockEntity) tileentity; + +- return skullblockentity.getNoteBlockSound(); ++ return tileentityskull.getNoteBlockSound(); + } else { + return null; + } + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(NoteBlock.INSTRUMENT, NoteBlock.POWERED, NoteBlock.NOTE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(NoteBlock.INSTRUMENT, NoteBlock.POWERED, NoteBlock.NOTE); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/NyliumBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/NyliumBlock.java.patch new file mode 100644 index 0000000000..61709a2c8a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/NyliumBlock.java.patch @@ -0,0 +1,112 @@ +--- a/net/minecraft/world/level/block/NyliumBlock.java ++++ b/net/minecraft/world/level/block/NyliumBlock.java +@@ -12,7 +12,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; + import net.minecraft.world.level.lighting.LightEngine; +@@ -22,67 +22,67 @@ + public static final MapCodec CODEC = simpleCodec(NyliumBlock::new); + + @Override +- @Override + public MapCodec codec() { + return NyliumBlock.CODEC; + } + +- protected NyliumBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ protected NyliumBlock(BlockBehaviour.Properties properties) { ++ super(properties); + } + +- private static boolean canBeNylium(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- BlockPos blockpos1 = blockpos.above(); +- BlockState blockstate1 = levelreader.getBlockState(blockpos1); +- int i = LightEngine.getLightBlockInto(levelreader, blockstate, blockpos, blockstate1, blockpos1, Direction.UP, blockstate1.getLightBlock(levelreader, blockpos1)); ++ private static boolean canBeNylium(IBlockData state, LevelReader reader, BlockPos pos) { ++ BlockPos blockposition1 = pos.above(); ++ IBlockData iblockdata1 = reader.getBlockState(blockposition1); ++ int i = LightEngine.getLightBlockInto(reader, state, pos, iblockdata1, blockposition1, Direction.UP, iblockdata1.getLightBlock(reader, blockposition1)); + +- return i < levelreader.getMaxLightLevel(); ++ return i < reader.getMaxLightLevel(); + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (!canBeNylium(blockstate, serverlevel, blockpos)) { +- serverlevel.setBlockAndUpdate(blockpos, Blocks.NETHERRACK.defaultBlockState()); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (!canBeNylium(state, level, pos)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.NETHERRACK.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlockAndUpdate(pos, Blocks.NETHERRACK.defaultBlockState()); + } + + } + + @Override +- @Override +- public boolean isValidBonemealTarget(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { +- return levelreader.getBlockState(blockpos.above()).isAir(); ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ return iworldreader.getBlockState(blockposition.above()).isAir(); + } + + @Override +- @Override +- public boolean isBonemealSuccess(Level level, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return true; + } + + @Override +- @Override +- public void performBonemeal(ServerLevel serverlevel, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { +- BlockState blockstate1 = serverlevel.getBlockState(blockpos); +- BlockPos blockpos1 = blockpos.above(); +- ChunkGenerator chunkgenerator = serverlevel.getChunkSource().getGenerator(); +- Registry> registry = serverlevel.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ IBlockData iblockdata1 = level.getBlockState(pos); ++ BlockPos blockposition1 = pos.above(); ++ ChunkGenerator chunkgenerator = level.getChunkSource().getGenerator(); ++ Registry> iregistry = level.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE); + +- if (blockstate1.is(Blocks.CRIMSON_NYLIUM)) { +- this.place(registry, NetherFeatures.CRIMSON_FOREST_VEGETATION_BONEMEAL, serverlevel, chunkgenerator, randomsource, blockpos1); +- } else if (blockstate1.is(Blocks.WARPED_NYLIUM)) { +- this.place(registry, NetherFeatures.WARPED_FOREST_VEGETATION_BONEMEAL, serverlevel, chunkgenerator, randomsource, blockpos1); +- this.place(registry, NetherFeatures.NETHER_SPROUTS_BONEMEAL, serverlevel, chunkgenerator, randomsource, blockpos1); +- if (randomsource.nextInt(8) == 0) { +- this.place(registry, NetherFeatures.TWISTING_VINES_BONEMEAL, serverlevel, chunkgenerator, randomsource, blockpos1); ++ if (iblockdata1.is(Blocks.CRIMSON_NYLIUM)) { ++ this.place(iregistry, NetherFeatures.CRIMSON_FOREST_VEGETATION_BONEMEAL, level, chunkgenerator, random, blockposition1); ++ } else if (iblockdata1.is(Blocks.WARPED_NYLIUM)) { ++ this.place(iregistry, NetherFeatures.WARPED_FOREST_VEGETATION_BONEMEAL, level, chunkgenerator, random, blockposition1); ++ this.place(iregistry, NetherFeatures.NETHER_SPROUTS_BONEMEAL, level, chunkgenerator, random, blockposition1); ++ if (random.nextInt(8) == 0) { ++ this.place(iregistry, NetherFeatures.TWISTING_VINES_BONEMEAL, level, chunkgenerator, random, blockposition1); + } + } + + } + +- private void place(Registry> registry, ResourceKey> resourcekey, ServerLevel serverlevel, ChunkGenerator chunkgenerator, RandomSource randomsource, BlockPos blockpos) { +- registry.getHolder(resourcekey).ifPresent((holder_reference) -> { +- ((ConfiguredFeature) holder_reference.value()).place(serverlevel, chunkgenerator, randomsource, blockpos); ++ private void place(Registry> featureRegistry, ResourceKey> featureKey, ServerLevel level, ChunkGenerator chunkGenerator, RandomSource random, BlockPos pos) { ++ featureRegistry.getHolder(featureKey).ifPresent((holder_c) -> { ++ ((ConfiguredFeature) holder_c.value()).place(level, chunkGenerator, random, pos); + }); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ObserverBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ObserverBlock.java.patch new file mode 100644 index 0000000000..25266b57d5 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ObserverBlock.java.patch @@ -0,0 +1,189 @@ +--- a/net/minecraft/world/level/block/ObserverBlock.java ++++ b/net/minecraft/world/level/block/ObserverBlock.java +@@ -10,129 +10,128 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + +-public class ObserverBlock extends DirectionalBlock { ++public class ObserverBlock extends BlockDirectional { + + public static final MapCodec CODEC = simpleCodec(ObserverBlock::new); + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + + @Override +- @Override + public MapCodec codec() { + return ObserverBlock.CODEC; + } + +- public ObserverBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(ObserverBlock.FACING, Direction.SOUTH)).setValue(ObserverBlock.POWERED, false)); ++ public ObserverBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(ObserverBlock.FACING, Direction.SOUTH)).setValue(ObserverBlock.POWERED, false)); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(ObserverBlock.FACING, ObserverBlock.POWERED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(ObserverBlock.FACING, ObserverBlock.POWERED); + } + + @Override +- @Override +- public BlockState rotate(BlockState blockstate, Rotation rotation) { +- return (BlockState) blockstate.setValue(ObserverBlock.FACING, rotation.rotate((Direction) blockstate.getValue(ObserverBlock.FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rot) { ++ return (IBlockData) state.setValue(ObserverBlock.FACING, rot.rotate((Direction) state.getValue(ObserverBlock.FACING))); + } + + @Override +- @Override +- public BlockState mirror(BlockState blockstate, Mirror mirror) { +- return blockstate.rotate(mirror.getRotation((Direction) blockstate.getValue(ObserverBlock.FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(ObserverBlock.FACING))); + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if ((Boolean) blockstate.getValue(ObserverBlock.POWERED)) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(ObserverBlock.POWERED, false), 2); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(ObserverBlock.POWERED)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 15, 0).getNewCurrent() != 0) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(ObserverBlock.POWERED, false), 2); + } else { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(ObserverBlock.POWERED, true), 2); +- serverlevel.scheduleTick(blockpos, (Block) this, 2); ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 0, 15).getNewCurrent() != 15) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(ObserverBlock.POWERED, true), 2); ++ level.scheduleTick(pos, (Block) this, 2); + } + +- this.updateNeighborsInFront(serverlevel, blockpos, blockstate); ++ this.updateNeighborsInFront(level, pos, state); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if (blockstate.getValue(ObserverBlock.FACING) == direction && !(Boolean) blockstate.getValue(ObserverBlock.POWERED)) { +- this.startSignal(levelaccessor, blockpos); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if (state.getValue(ObserverBlock.FACING) == facing && !(Boolean) state.getValue(ObserverBlock.POWERED)) { ++ this.startSignal(level, currentPos); + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + +- private void startSignal(LevelAccessor levelaccessor, BlockPos blockpos) { +- if (!levelaccessor.isClientSide() && !levelaccessor.getBlockTicks().hasScheduledTick(blockpos, this)) { +- levelaccessor.scheduleTick(blockpos, (Block) this, 2); ++ private void startSignal(LevelAccessor level, BlockPos pos) { ++ if (!level.isClientSide() && !level.getBlockTicks().hasScheduledTick(pos, this)) { ++ level.scheduleTick(pos, (Block) this, 2); + } + + } + +- protected void updateNeighborsInFront(Level level, BlockPos blockpos, BlockState blockstate) { +- Direction direction = (Direction) blockstate.getValue(ObserverBlock.FACING); +- BlockPos blockpos1 = blockpos.relative(direction.getOpposite()); ++ protected void updateNeighborsInFront(Level level, BlockPos pos, IBlockData state) { ++ Direction enumdirection = (Direction) state.getValue(ObserverBlock.FACING); ++ BlockPos blockposition1 = pos.relative(enumdirection.getOpposite()); + +- level.neighborChanged(blockpos1, this, blockpos); +- level.updateNeighborsAtExceptFromFacing(blockpos1, this, direction); ++ level.neighborChanged(blockposition1, this, pos); ++ level.updateNeighborsAtExceptFromFacing(blockposition1, this, enumdirection); + } + + @Override +- @Override +- public boolean isSignalSource(BlockState blockstate) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + + @Override +- @Override +- public int getDirectSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return blockstate.getSignal(blockgetter, blockpos, direction); ++ public int getDirectSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return blockState.getSignal(blockAccess, pos, side); + } + + @Override +- @Override +- public int getSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return (Boolean) blockstate.getValue(ObserverBlock.POWERED) && blockstate.getValue(ObserverBlock.FACING) == direction ? 15 : 0; ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return (Boolean) blockState.getValue(ObserverBlock.POWERED) && blockState.getValue(ObserverBlock.FACING) == side ? 15 : 0; + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!blockstate.is(blockstate1.getBlock())) { +- if (!level.isClientSide() && (Boolean) blockstate.getValue(ObserverBlock.POWERED) && !level.getBlockTicks().hasScheduledTick(blockpos, this)) { +- BlockState blockstate2 = (BlockState) blockstate.setValue(ObserverBlock.POWERED, false); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ if (!state.is(oldState.getBlock())) { ++ if (!level.isClientSide() && (Boolean) state.getValue(ObserverBlock.POWERED) && !level.getBlockTicks().hasScheduledTick(pos, this)) { ++ IBlockData iblockdata2 = (IBlockData) state.setValue(ObserverBlock.POWERED, false); + +- level.setBlock(blockpos, blockstate2, 18); +- this.updateNeighborsInFront(level, blockpos, blockstate2); ++ level.setBlock(pos, iblockdata2, 18); ++ this.updateNeighborsInFront(level, pos, iblockdata2); + } + + } + } + + @Override +- @Override +- public void onRemove(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!blockstate.is(blockstate1.getBlock())) { +- if (!level.isClientSide && (Boolean) blockstate.getValue(ObserverBlock.POWERED) && level.getBlockTicks().hasScheduledTick(blockpos, this)) { +- this.updateNeighborsInFront(level, blockpos, (BlockState) blockstate.setValue(ObserverBlock.POWERED, false)); ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { ++ if (!state.is(newState.getBlock())) { ++ if (!level.isClientSide && (Boolean) state.getValue(ObserverBlock.POWERED) && level.getBlockTicks().hasScheduledTick(pos, this)) { ++ this.updateNeighborsInFront(level, pos, (IBlockData) state.setValue(ObserverBlock.POWERED, false)); + } + + } + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- return (BlockState) this.defaultBlockState().setValue(ObserverBlock.FACING, blockplacecontext.getNearestLookingDirection().getOpposite().getOpposite()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return (IBlockData) this.defaultBlockState().setValue(ObserverBlock.FACING, context.getNearestLookingDirection().getOpposite().getOpposite()); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/PointedDripstoneBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/PointedDripstoneBlock.java.patch new file mode 100644 index 0000000000..d0945a39e9 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/PointedDripstoneBlock.java.patch @@ -0,0 +1,859 @@ +--- a/net/minecraft/world/level/block/PointedDripstoneBlock.java ++++ b/net/minecraft/world/level/block/PointedDripstoneBlock.java +@@ -24,7 +24,7 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -35,13 +35,17 @@ + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class PointedDripstoneBlock extends Block implements Fallable, SimpleWaterloggedBlock { + +@@ -77,161 +81,159 @@ + private static final VoxelShape REQUIRED_SPACE_TO_DRIP_THROUGH_NON_SOLID_BLOCK = Block.box(6.0D, 0.0D, 6.0D, 10.0D, 16.0D, 10.0D); + + @Override +- @Override + public MapCodec codec() { + return PointedDripstoneBlock.CODEC; + } + +- public PointedDripstoneBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(PointedDripstoneBlock.TIP_DIRECTION, Direction.UP)).setValue(PointedDripstoneBlock.THICKNESS, DripstoneThickness.TIP)).setValue(PointedDripstoneBlock.WATERLOGGED, false)); ++ public PointedDripstoneBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(PointedDripstoneBlock.TIP_DIRECTION, Direction.UP)).setValue(PointedDripstoneBlock.THICKNESS, DripstoneThickness.TIP)).setValue(PointedDripstoneBlock.WATERLOGGED, false)); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(PointedDripstoneBlock.TIP_DIRECTION, PointedDripstoneBlock.THICKNESS, PointedDripstoneBlock.WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(PointedDripstoneBlock.TIP_DIRECTION, PointedDripstoneBlock.THICKNESS, PointedDripstoneBlock.WATERLOGGED); + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- return isValidPointedDripstonePlacement(levelreader, blockpos, (Direction) blockstate.getValue(PointedDripstoneBlock.TIP_DIRECTION)); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ return isValidPointedDripstonePlacement(level, pos, (Direction) state.getValue(PointedDripstoneBlock.TIP_DIRECTION)); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if ((Boolean) blockstate.getValue(PointedDripstoneBlock.WATERLOGGED)) { +- levelaccessor.scheduleTick(blockpos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(levelaccessor)); ++ public IBlockData updateShape(IBlockData state, Direction direction, IBlockData neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { ++ if ((Boolean) state.getValue(PointedDripstoneBlock.WATERLOGGED)) { ++ level.scheduleTick(pos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + + if (direction != Direction.UP && direction != Direction.DOWN) { +- return blockstate; ++ return state; + } else { +- Direction direction1 = (Direction) blockstate.getValue(PointedDripstoneBlock.TIP_DIRECTION); ++ Direction enumdirection1 = (Direction) state.getValue(PointedDripstoneBlock.TIP_DIRECTION); + +- if (direction1 == Direction.DOWN && levelaccessor.getBlockTicks().hasScheduledTick(blockpos, this)) { +- return blockstate; +- } else if (direction == direction1.getOpposite() && !this.canSurvive(blockstate, levelaccessor, blockpos)) { +- if (direction1 == Direction.DOWN) { +- levelaccessor.scheduleTick(blockpos, (Block) this, 2); ++ if (enumdirection1 == Direction.DOWN && level.getBlockTicks().hasScheduledTick(pos, this)) { ++ return state; ++ } else if (direction == enumdirection1.getOpposite() && !this.canSurvive(state, level, pos)) { ++ if (enumdirection1 == Direction.DOWN) { ++ level.scheduleTick(pos, (Block) this, 2); + } else { +- levelaccessor.scheduleTick(blockpos, (Block) this, 1); ++ level.scheduleTick(pos, (Block) this, 1); + } + +- return blockstate; ++ return state; + } else { +- boolean flag = blockstate.getValue(PointedDripstoneBlock.THICKNESS) == DripstoneThickness.TIP_MERGE; +- DripstoneThickness dripstonethickness = calculateDripstoneThickness(levelaccessor, blockpos, direction1, flag); ++ boolean flag = state.getValue(PointedDripstoneBlock.THICKNESS) == DripstoneThickness.TIP_MERGE; ++ DripstoneThickness dripstonethickness = calculateDripstoneThickness(level, pos, enumdirection1, flag); + +- return (BlockState) blockstate.setValue(PointedDripstoneBlock.THICKNESS, dripstonethickness); ++ return (IBlockData) state.setValue(PointedDripstoneBlock.THICKNESS, dripstonethickness); + } + } + } + + @Override +- @Override +- public void onProjectileHit(Level level, BlockState blockstate, BlockHitResult blockhitresult, Projectile projectile) { ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { + if (!level.isClientSide) { +- BlockPos blockpos = blockhitresult.getBlockPos(); ++ BlockPos blockposition = hit.getBlockPos(); + +- if (projectile.mayInteract(level, blockpos) && projectile.mayBreak(level) && projectile instanceof ThrownTrident && projectile.getDeltaMovement().length() > 0.6D) { +- level.destroyBlock(blockpos, true); ++ if (projectile.mayInteract(level, blockposition) && projectile.mayBreak(level) && projectile instanceof ThrownTrident && projectile.getDeltaMovement().length() > 0.6D) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, Blocks.AIR.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end ++ level.destroyBlock(blockposition, true); + } + + } + } + + @Override +- @Override +- public void fallOn(Level level, BlockState blockstate, BlockPos blockpos, Entity entity, float f) { +- if (blockstate.getValue(PointedDripstoneBlock.TIP_DIRECTION) == Direction.UP && blockstate.getValue(PointedDripstoneBlock.THICKNESS) == DripstoneThickness.TIP) { +- entity.causeFallDamage(f + 2.0F, 2.0F, level.damageSources().stalagmite()); ++ public void fallOn(Level level, IBlockData state, BlockPos pos, Entity entity, float fallDistance) { ++ if (state.getValue(PointedDripstoneBlock.TIP_DIRECTION) == Direction.UP && state.getValue(PointedDripstoneBlock.THICKNESS) == DripstoneThickness.TIP) { ++ CraftEventFactory.blockDamage = CraftBlock.at(level, pos); // CraftBukkit ++ entity.causeFallDamage(fallDistance + 2.0F, 2.0F, level.damageSources().stalagmite()); ++ CraftEventFactory.blockDamage = null; // CraftBukkit + } else { +- super.fallOn(level, blockstate, blockpos, entity, f); ++ super.fallOn(level, state, pos, entity, fallDistance); + } + + } + + @Override +- @Override +- public void animateTick(BlockState blockstate, Level level, BlockPos blockpos, RandomSource randomsource) { +- if (canDrip(blockstate)) { +- float f = randomsource.nextFloat(); ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if (canDrip(state)) { ++ float f = random.nextFloat(); + + if (f <= 0.12F) { +- getFluidAboveStalactite(level, blockpos, blockstate).filter((pointeddripstoneblock_fluidinfo) -> { +- return f < 0.02F || canFillCauldron(pointeddripstoneblock_fluidinfo.fluid); +- }).ifPresent((pointeddripstoneblock_fluidinfo) -> { +- spawnDripParticle(level, blockpos, blockstate, pointeddripstoneblock_fluidinfo.fluid); ++ getFluidAboveStalactite(level, pos, state).filter((pointeddripstoneblock_a) -> { ++ return f < 0.02F || canFillCauldron(pointeddripstoneblock_a.fluid); ++ }).ifPresent((pointeddripstoneblock_a) -> { ++ spawnDripParticle(level, pos, state, pointeddripstoneblock_a.fluid); + }); + } + } + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (isStalagmite(blockstate) && !this.canSurvive(blockstate, serverlevel, blockpos)) { +- serverlevel.destroyBlock(blockpos, true); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (isStalagmite(state) && !this.canSurvive(state, level, pos)) { ++ level.destroyBlock(pos, true); + } else { +- spawnFallingStalactite(blockstate, serverlevel, blockpos); ++ spawnFallingStalactite(state, level, pos); + } + + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- maybeTransferFluid(blockstate, serverlevel, blockpos, randomsource.nextFloat()); +- if (randomsource.nextFloat() < 0.011377778F && isStalactiteStartPos(blockstate, serverlevel, blockpos)) { +- growStalactiteOrStalagmiteIfPossible(blockstate, serverlevel, blockpos, randomsource); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ maybeTransferFluid(state, level, pos, random.nextFloat()); ++ if (random.nextFloat() < 0.011377778F && isStalactiteStartPos(state, level, pos)) { ++ growStalactiteOrStalagmiteIfPossible(state, level, pos, random); + } + + } + + @VisibleForTesting +- public static void maybeTransferFluid(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, float f) { +- if (f <= 0.17578125F || f <= 0.05859375F) { +- if (isStalactiteStartPos(blockstate, serverlevel, blockpos)) { +- Optional optional = getFluidAboveStalactite(serverlevel, blockpos, blockstate); ++ public static void maybeTransferFluid(IBlockData state, ServerLevel level, BlockPos pos, float randChance) { ++ if (randChance <= 0.17578125F || randChance <= 0.05859375F) { ++ if (isStalactiteStartPos(state, level, pos)) { ++ Optional optional = getFluidAboveStalactite(level, pos, state); + + if (!optional.isEmpty()) { +- Fluid fluid = ((PointedDripstoneBlock.FluidInfo) optional.get()).fluid; ++ Fluid fluidtype = ((PointedDripstoneBlock.a) optional.get()).fluid; + float f1; + +- if (fluid == Fluids.WATER) { ++ if (fluidtype == Fluids.WATER) { + f1 = 0.17578125F; + } else { +- if (fluid != Fluids.LAVA) { ++ if (fluidtype != Fluids.LAVA) { + return; + } + + f1 = 0.05859375F; + } + +- if (f < f1) { +- BlockPos blockpos1 = findTip(blockstate, serverlevel, blockpos, 11, false); ++ if (randChance < f1) { ++ BlockPos blockposition1 = findTip(state, level, pos, 11, false); + +- if (blockpos1 != null) { +- if (((PointedDripstoneBlock.FluidInfo) optional.get()).sourceState.is(Blocks.MUD) && fluid == Fluids.WATER) { +- BlockState blockstate1 = Blocks.CLAY.defaultBlockState(); ++ if (blockposition1 != null) { ++ if (((PointedDripstoneBlock.a) optional.get()).sourceState.is(Blocks.MUD) && fluidtype == Fluids.WATER) { ++ IBlockData iblockdata1 = Blocks.CLAY.defaultBlockState(); + +- serverlevel.setBlockAndUpdate(((PointedDripstoneBlock.FluidInfo) optional.get()).pos, blockstate1); +- Block.pushEntitiesUp(((PointedDripstoneBlock.FluidInfo) optional.get()).sourceState, blockstate1, serverlevel, ((PointedDripstoneBlock.FluidInfo) optional.get()).pos); +- serverlevel.gameEvent(GameEvent.BLOCK_CHANGE, ((PointedDripstoneBlock.FluidInfo) optional.get()).pos, GameEvent.Context.of(blockstate1)); +- serverlevel.levelEvent(1504, blockpos1, 0); ++ level.setBlockAndUpdate(((PointedDripstoneBlock.a) optional.get()).pos, iblockdata1); ++ Block.pushEntitiesUp(((PointedDripstoneBlock.a) optional.get()).sourceState, iblockdata1, level, ((PointedDripstoneBlock.a) optional.get()).pos); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, ((PointedDripstoneBlock.a) optional.get()).pos, GameEvent.Context.of(iblockdata1)); ++ level.levelEvent(1504, blockposition1, 0); + } else { +- BlockPos blockpos2 = findFillableCauldronBelowStalactiteTip(serverlevel, blockpos1, fluid); ++ BlockPos blockposition2 = findFillableCauldronBelowStalactiteTip(level, blockposition1, fluidtype); + +- if (blockpos2 != null) { +- serverlevel.levelEvent(1504, blockpos1, 0); +- int i = blockpos1.getY() - blockpos2.getY(); ++ if (blockposition2 != null) { ++ level.levelEvent(1504, blockposition1, 0); ++ int i = blockposition1.getY() - blockposition2.getY(); + int j = 50 + i; +- BlockState blockstate2 = serverlevel.getBlockState(blockpos2); ++ IBlockData iblockdata2 = level.getBlockState(blockposition2); + +- serverlevel.scheduleTick(blockpos2, blockstate2.getBlock(), j); ++ level.scheduleTick(blockposition2, iblockdata2.getBlock(), j); + } + } + } +@@ -243,45 +245,41 @@ + + @Nullable + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- Level level = blockplacecontext.getLevel(); +- BlockPos blockpos = blockplacecontext.getClickedPos(); +- Direction direction = blockplacecontext.getNearestLookingVerticalDirection().getOpposite(); +- Direction direction1 = calculateTipDirection(level, blockpos, direction); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ Direction enumdirection = context.getNearestLookingVerticalDirection().getOpposite(); ++ Direction enumdirection1 = calculateTipDirection(world, blockposition, enumdirection); + +- if (direction1 == null) { ++ if (enumdirection1 == null) { + return null; + } else { +- boolean flag = !blockplacecontext.isSecondaryUseActive(); +- DripstoneThickness dripstonethickness = calculateDripstoneThickness(level, blockpos, direction1, flag); ++ boolean flag = !context.isSecondaryUseActive(); ++ DripstoneThickness dripstonethickness = calculateDripstoneThickness(world, blockposition, enumdirection1, flag); + +- return dripstonethickness == null ? null : (BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(PointedDripstoneBlock.TIP_DIRECTION, direction1)).setValue(PointedDripstoneBlock.THICKNESS, dripstonethickness)).setValue(PointedDripstoneBlock.WATERLOGGED, level.getFluidState(blockpos).getType() == Fluids.WATER); ++ return dripstonethickness == null ? null : (IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(PointedDripstoneBlock.TIP_DIRECTION, enumdirection1)).setValue(PointedDripstoneBlock.THICKNESS, dripstonethickness)).setValue(PointedDripstoneBlock.WATERLOGGED, world.getFluidState(blockposition).getType() == Fluids.WATER); + } + } + + @Override +- @Override +- public FluidState getFluidState(BlockState blockstate) { +- return (Boolean) blockstate.getValue(PointedDripstoneBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(blockstate); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(PointedDripstoneBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override +- @Override +- public VoxelShape getOcclusionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { ++ public VoxelShape getOcclusionShape(IBlockData state, BlockGetter level, BlockPos pos) { + return Shapes.empty(); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- DripstoneThickness dripstonethickness = (DripstoneThickness) blockstate.getValue(PointedDripstoneBlock.THICKNESS); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ DripstoneThickness dripstonethickness = (DripstoneThickness) state.getValue(PointedDripstoneBlock.THICKNESS); + VoxelShape voxelshape; + + if (dripstonethickness == DripstoneThickness.TIP_MERGE) { + voxelshape = PointedDripstoneBlock.TIP_MERGE_SHAPE; + } else if (dripstonethickness == DripstoneThickness.TIP) { +- if (blockstate.getValue(PointedDripstoneBlock.TIP_DIRECTION) == Direction.DOWN) { ++ if (state.getValue(PointedDripstoneBlock.TIP_DIRECTION) == Direction.DOWN) { + voxelshape = PointedDripstoneBlock.TIP_SHAPE_DOWN; + } else { + voxelshape = PointedDripstoneBlock.TIP_SHAPE_UP; +@@ -294,73 +292,69 @@ + voxelshape = PointedDripstoneBlock.BASE_SHAPE; + } + +- Vec3 vec3 = blockstate.getOffset(blockgetter, blockpos); ++ Vec3 vec3d = state.getOffset(level, pos); + +- return voxelshape.move(vec3.x, 0.0D, vec3.z); ++ return voxelshape.move(vec3d.x, 0.0D, vec3d.z); + } + + @Override +- @Override +- public boolean isCollisionShapeFullBlock(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { ++ public boolean isCollisionShapeFullBlock(IBlockData state, BlockGetter level, BlockPos pos) { + return false; + } + + @Override +- @Override + public float getMaxHorizontalOffset() { + return 0.125F; + } + + @Override +- @Override +- public void onBrokenAfterFall(Level level, BlockPos blockpos, FallingBlockEntity fallingblockentity) { +- if (!fallingblockentity.isSilent()) { +- level.levelEvent(1045, blockpos, 0); ++ public void onBrokenAfterFall(Level level, BlockPos pos, FallingBlockEntity fallingBlock) { ++ if (!fallingBlock.isSilent()) { ++ level.levelEvent(1045, pos, 0); + } + + } + + @Override +- @Override + public DamageSource getFallDamageSource(Entity entity) { + return entity.damageSources().fallingStalactite(entity); + } + +- private static void spawnFallingStalactite(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = blockpos.mutable(); ++ private static void spawnFallingStalactite(IBlockData state, ServerLevel level, BlockPos pos) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); + +- for (BlockState blockstate1 = blockstate; isStalactite(blockstate1); blockstate1 = serverlevel.getBlockState(blockpos_mutableblockpos)) { +- FallingBlockEntity fallingblockentity = FallingBlockEntity.fall(serverlevel, blockpos_mutableblockpos, blockstate1); ++ for (IBlockData iblockdata1 = state; isStalactite(iblockdata1); iblockdata1 = level.getBlockState(blockposition_mutableblockposition)) { ++ FallingBlockEntity entityfallingblock = FallingBlockEntity.fall(level, blockposition_mutableblockposition, iblockdata1); + +- if (isTip(blockstate1, true)) { +- int i = Math.max(1 + blockpos.getY() - blockpos_mutableblockpos.getY(), 6); ++ if (isTip(iblockdata1, true)) { ++ int i = Math.max(1 + pos.getY() - blockposition_mutableblockposition.getY(), 6); + float f = 1.0F * (float) i; + +- fallingblockentity.setHurtsEntities(f, 40); ++ entityfallingblock.setHurtsEntities(f, 40); + break; + } + +- blockpos_mutableblockpos.move(Direction.DOWN); ++ blockposition_mutableblockposition.move(Direction.DOWN); + } + + } + + @VisibleForTesting +- public static void growStalactiteOrStalagmiteIfPossible(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- BlockState blockstate1 = serverlevel.getBlockState(blockpos.above(1)); +- BlockState blockstate2 = serverlevel.getBlockState(blockpos.above(2)); ++ public static void growStalactiteOrStalagmiteIfPossible(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ IBlockData iblockdata1 = level.getBlockState(pos.above(1)); ++ IBlockData iblockdata2 = level.getBlockState(pos.above(2)); + +- if (canGrow(blockstate1, blockstate2)) { +- BlockPos blockpos1 = findTip(blockstate, serverlevel, blockpos, 7, false); ++ if (canGrow(iblockdata1, iblockdata2)) { ++ BlockPos blockposition1 = findTip(state, level, pos, 7, false); + +- if (blockpos1 != null) { +- BlockState blockstate3 = serverlevel.getBlockState(blockpos1); ++ if (blockposition1 != null) { ++ IBlockData iblockdata3 = level.getBlockState(blockposition1); + +- if (canDrip(blockstate3) && canTipGrow(blockstate3, serverlevel, blockpos1)) { +- if (randomsource.nextBoolean()) { +- grow(serverlevel, blockpos1, Direction.DOWN); ++ if (canDrip(iblockdata3) && canTipGrow(iblockdata3, level, blockposition1)) { ++ if (random.nextBoolean()) { ++ grow(level, blockposition1, Direction.DOWN); + } else { +- growStalagmiteBelow(serverlevel, blockpos1); ++ growStalagmiteBelow(level, blockposition1); + } + + } +@@ -368,246 +362,245 @@ + } + } + +- private static void growStalagmiteBelow(ServerLevel serverlevel, BlockPos blockpos) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = blockpos.mutable(); ++ private static void growStalagmiteBelow(ServerLevel level, BlockPos pos) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); + + for (int i = 0; i < 10; ++i) { +- blockpos_mutableblockpos.move(Direction.DOWN); +- BlockState blockstate = serverlevel.getBlockState(blockpos_mutableblockpos); ++ blockposition_mutableblockposition.move(Direction.DOWN); ++ IBlockData iblockdata = level.getBlockState(blockposition_mutableblockposition); + +- if (!blockstate.getFluidState().isEmpty()) { ++ if (!iblockdata.getFluidState().isEmpty()) { + return; + } + +- if (isUnmergedTipWithDirection(blockstate, Direction.UP) && canTipGrow(blockstate, serverlevel, blockpos_mutableblockpos)) { +- grow(serverlevel, blockpos_mutableblockpos, Direction.UP); ++ if (isUnmergedTipWithDirection(iblockdata, Direction.UP) && canTipGrow(iblockdata, level, blockposition_mutableblockposition)) { ++ grow(level, blockposition_mutableblockposition, Direction.UP); + return; + } + +- if (isValidPointedDripstonePlacement(serverlevel, blockpos_mutableblockpos, Direction.UP) && !serverlevel.isWaterAt(blockpos_mutableblockpos.below())) { +- grow(serverlevel, blockpos_mutableblockpos.below(), Direction.UP); ++ if (isValidPointedDripstonePlacement(level, blockposition_mutableblockposition, Direction.UP) && !level.isWaterAt(blockposition_mutableblockposition.below())) { ++ grow(level, blockposition_mutableblockposition.below(), Direction.UP); + return; + } + +- if (!canDripThrough(serverlevel, blockpos_mutableblockpos, blockstate)) { ++ if (!canDripThrough(level, blockposition_mutableblockposition, iblockdata)) { + return; + } + } + + } + +- private static void grow(ServerLevel serverlevel, BlockPos blockpos, Direction direction) { +- BlockPos blockpos1 = blockpos.relative(direction); +- BlockState blockstate = serverlevel.getBlockState(blockpos1); ++ private static void grow(ServerLevel server, BlockPos pos, Direction direction) { ++ BlockPos blockposition1 = pos.relative(direction); ++ IBlockData iblockdata = server.getBlockState(blockposition1); + +- if (isUnmergedTipWithDirection(blockstate, direction.getOpposite())) { +- createMergedTips(blockstate, serverlevel, blockpos1); +- } else if (blockstate.isAir() || blockstate.is(Blocks.WATER)) { +- createDripstone(serverlevel, blockpos1, direction, DripstoneThickness.TIP); ++ if (isUnmergedTipWithDirection(iblockdata, direction.getOpposite())) { ++ createMergedTips(iblockdata, server, blockposition1); ++ } else if (iblockdata.isAir() || iblockdata.is(Blocks.WATER)) { ++ createDripstone(server, blockposition1, direction, DripstoneThickness.TIP, pos); // CraftBukkit + } + + } + +- private static void createDripstone(LevelAccessor levelaccessor, BlockPos blockpos, Direction direction, DripstoneThickness dripstonethickness) { +- BlockState blockstate = (BlockState) ((BlockState) ((BlockState) Blocks.POINTED_DRIPSTONE.defaultBlockState().setValue(PointedDripstoneBlock.TIP_DIRECTION, direction)).setValue(PointedDripstoneBlock.THICKNESS, dripstonethickness)).setValue(PointedDripstoneBlock.WATERLOGGED, levelaccessor.getFluidState(blockpos).getType() == Fluids.WATER); ++ private static void createDripstone(LevelAccessor generatoraccess, BlockPos blockposition, Direction enumdirection, DripstoneThickness dripstonethickness, BlockPos source) { // CraftBukkit ++ IBlockData iblockdata = (IBlockData) ((IBlockData) ((IBlockData) Blocks.POINTED_DRIPSTONE.defaultBlockState().setValue(PointedDripstoneBlock.TIP_DIRECTION, enumdirection)).setValue(PointedDripstoneBlock.THICKNESS, dripstonethickness)).setValue(PointedDripstoneBlock.WATERLOGGED, generatoraccess.getFluidState(blockposition).getType() == Fluids.WATER); + +- levelaccessor.setBlock(blockpos, blockstate, 3); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(generatoraccess, source, blockposition, iblockdata, 3); // CraftBukkit + } + +- private static void createMergedTips(BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos) { +- BlockPos blockpos1; +- BlockPos blockpos2; ++ private static void createMergedTips(IBlockData state, LevelAccessor level, BlockPos pos) { ++ BlockPos blockposition1; ++ BlockPos blockposition2; + +- if (blockstate.getValue(PointedDripstoneBlock.TIP_DIRECTION) == Direction.UP) { +- blockpos1 = blockpos; +- blockpos2 = blockpos.above(); ++ if (state.getValue(PointedDripstoneBlock.TIP_DIRECTION) == Direction.UP) { ++ blockposition1 = pos; ++ blockposition2 = pos.above(); + } else { +- blockpos2 = blockpos; +- blockpos1 = blockpos.below(); ++ blockposition2 = pos; ++ blockposition1 = pos.below(); + } + +- createDripstone(levelaccessor, blockpos2, Direction.DOWN, DripstoneThickness.TIP_MERGE); +- createDripstone(levelaccessor, blockpos1, Direction.UP, DripstoneThickness.TIP_MERGE); ++ createDripstone(level, blockposition2, Direction.DOWN, DripstoneThickness.TIP_MERGE, pos); // CraftBukkit ++ createDripstone(level, blockposition1, Direction.UP, DripstoneThickness.TIP_MERGE, pos); // CraftBukkit + } + +- public static void spawnDripParticle(Level level, BlockPos blockpos, BlockState blockstate) { +- getFluidAboveStalactite(level, blockpos, blockstate).ifPresent((pointeddripstoneblock_fluidinfo) -> { +- spawnDripParticle(level, blockpos, blockstate, pointeddripstoneblock_fluidinfo.fluid); ++ public static void spawnDripParticle(Level level, BlockPos pos, IBlockData state) { ++ getFluidAboveStalactite(level, pos, state).ifPresent((pointeddripstoneblock_a) -> { ++ spawnDripParticle(level, pos, state, pointeddripstoneblock_a.fluid); + }); + } + +- private static void spawnDripParticle(Level level, BlockPos blockpos, BlockState blockstate, Fluid fluid) { +- Vec3 vec3 = blockstate.getOffset(level, blockpos); ++ private static void spawnDripParticle(Level level, BlockPos pos, IBlockData state, Fluid fluid) { ++ Vec3 vec3d = state.getOffset(level, pos); + double d0 = 0.0625D; +- double d1 = (double) blockpos.getX() + 0.5D + vec3.x; +- double d2 = (double) ((float) (blockpos.getY() + 1) - 0.6875F) - 0.0625D; +- double d3 = (double) blockpos.getZ() + 0.5D + vec3.z; +- Fluid fluid1 = getDripFluid(level, fluid); +- SimpleParticleType simpleparticletype = fluid1.is(FluidTags.LAVA) ? ParticleTypes.DRIPPING_DRIPSTONE_LAVA : ParticleTypes.DRIPPING_DRIPSTONE_WATER; ++ double d1 = (double) pos.getX() + 0.5D + vec3d.x; ++ double d2 = (double) ((float) (pos.getY() + 1) - 0.6875F) - 0.0625D; ++ double d3 = (double) pos.getZ() + 0.5D + vec3d.z; ++ Fluid fluidtype1 = getDripFluid(level, fluid); ++ SimpleParticleType particletype = fluidtype1.is(FluidTags.LAVA) ? ParticleTypes.DRIPPING_DRIPSTONE_LAVA : ParticleTypes.DRIPPING_DRIPSTONE_WATER; + +- level.addParticle(simpleparticletype, d1, d2, d3, 0.0D, 0.0D, 0.0D); ++ level.addParticle(particletype, d1, d2, d3, 0.0D, 0.0D, 0.0D); + } + + @Nullable +- private static BlockPos findTip(BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos, int i, boolean flag) { +- if (isTip(blockstate, flag)) { +- return blockpos; ++ private static BlockPos findTip(IBlockData state, LevelAccessor level, BlockPos pos, int maxIterations, boolean isTipMerge) { ++ if (isTip(state, isTipMerge)) { ++ return pos; + } else { +- Direction direction = (Direction) blockstate.getValue(PointedDripstoneBlock.TIP_DIRECTION); +- BiPredicate bipredicate = (blockpos1, blockstate1) -> { +- return blockstate1.is(Blocks.POINTED_DRIPSTONE) && blockstate1.getValue(PointedDripstoneBlock.TIP_DIRECTION) == direction; ++ Direction enumdirection = (Direction) state.getValue(PointedDripstoneBlock.TIP_DIRECTION); ++ BiPredicate bipredicate = (blockposition1, iblockdata1) -> { ++ return iblockdata1.is(Blocks.POINTED_DRIPSTONE) && iblockdata1.getValue(PointedDripstoneBlock.TIP_DIRECTION) == enumdirection; + }; + +- return (BlockPos) findBlockVertical(levelaccessor, blockpos, direction.getAxisDirection(), bipredicate, (blockstate1) -> { +- return isTip(blockstate1, flag); +- }, i).orElse((Object) null); ++ return (BlockPos) findBlockVertical(level, pos, enumdirection.getAxisDirection(), bipredicate, (iblockdata1) -> { ++ return isTip(iblockdata1, isTipMerge); ++ }, maxIterations).orElse(null); // CraftBukkit - decompile error + } + } + + @Nullable +- private static Direction calculateTipDirection(LevelReader levelreader, BlockPos blockpos, Direction direction) { +- Direction direction1; ++ private static Direction calculateTipDirection(LevelReader level, BlockPos pos, Direction dir) { ++ Direction enumdirection1; + +- if (isValidPointedDripstonePlacement(levelreader, blockpos, direction)) { +- direction1 = direction; ++ if (isValidPointedDripstonePlacement(level, pos, dir)) { ++ enumdirection1 = dir; + } else { +- if (!isValidPointedDripstonePlacement(levelreader, blockpos, direction.getOpposite())) { ++ if (!isValidPointedDripstonePlacement(level, pos, dir.getOpposite())) { + return null; + } + +- direction1 = direction.getOpposite(); ++ enumdirection1 = dir.getOpposite(); + } + +- return direction1; ++ return enumdirection1; + } + +- private static DripstoneThickness calculateDripstoneThickness(LevelReader levelreader, BlockPos blockpos, Direction direction, boolean flag) { +- Direction direction1 = direction.getOpposite(); +- BlockState blockstate = levelreader.getBlockState(blockpos.relative(direction)); ++ private static DripstoneThickness calculateDripstoneThickness(LevelReader level, BlockPos pos, Direction dir, boolean isTipMerge) { ++ Direction enumdirection1 = dir.getOpposite(); ++ IBlockData iblockdata = level.getBlockState(pos.relative(dir)); + +- if (isPointedDripstoneWithDirection(blockstate, direction1)) { +- return !flag && blockstate.getValue(PointedDripstoneBlock.THICKNESS) != DripstoneThickness.TIP_MERGE ? DripstoneThickness.TIP : DripstoneThickness.TIP_MERGE; +- } else if (!isPointedDripstoneWithDirection(blockstate, direction)) { ++ if (isPointedDripstoneWithDirection(iblockdata, enumdirection1)) { ++ return !isTipMerge && iblockdata.getValue(PointedDripstoneBlock.THICKNESS) != DripstoneThickness.TIP_MERGE ? DripstoneThickness.TIP : DripstoneThickness.TIP_MERGE; ++ } else if (!isPointedDripstoneWithDirection(iblockdata, dir)) { + return DripstoneThickness.TIP; + } else { +- DripstoneThickness dripstonethickness = (DripstoneThickness) blockstate.getValue(PointedDripstoneBlock.THICKNESS); ++ DripstoneThickness dripstonethickness = (DripstoneThickness) iblockdata.getValue(PointedDripstoneBlock.THICKNESS); + + if (dripstonethickness != DripstoneThickness.TIP && dripstonethickness != DripstoneThickness.TIP_MERGE) { +- BlockState blockstate1 = levelreader.getBlockState(blockpos.relative(direction1)); ++ IBlockData iblockdata1 = level.getBlockState(pos.relative(enumdirection1)); + +- return !isPointedDripstoneWithDirection(blockstate1, direction) ? DripstoneThickness.BASE : DripstoneThickness.MIDDLE; ++ return !isPointedDripstoneWithDirection(iblockdata1, dir) ? DripstoneThickness.BASE : DripstoneThickness.MIDDLE; + } else { + return DripstoneThickness.FRUSTUM; + } + } + } + +- public static boolean canDrip(BlockState blockstate) { +- return isStalactite(blockstate) && blockstate.getValue(PointedDripstoneBlock.THICKNESS) == DripstoneThickness.TIP && !(Boolean) blockstate.getValue(PointedDripstoneBlock.WATERLOGGED); ++ public static boolean canDrip(IBlockData state) { ++ return isStalactite(state) && state.getValue(PointedDripstoneBlock.THICKNESS) == DripstoneThickness.TIP && !(Boolean) state.getValue(PointedDripstoneBlock.WATERLOGGED); + } + +- private static boolean canTipGrow(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos) { +- Direction direction = (Direction) blockstate.getValue(PointedDripstoneBlock.TIP_DIRECTION); +- BlockPos blockpos1 = blockpos.relative(direction); +- BlockState blockstate1 = serverlevel.getBlockState(blockpos1); ++ private static boolean canTipGrow(IBlockData state, ServerLevel level, BlockPos pos) { ++ Direction enumdirection = (Direction) state.getValue(PointedDripstoneBlock.TIP_DIRECTION); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + +- return !blockstate1.getFluidState().isEmpty() ? false : (blockstate1.isAir() ? true : isUnmergedTipWithDirection(blockstate1, direction.getOpposite())); ++ return !iblockdata1.getFluidState().isEmpty() ? false : (iblockdata1.isAir() ? true : isUnmergedTipWithDirection(iblockdata1, enumdirection.getOpposite())); + } + +- private static Optional findRootBlock(Level level, BlockPos blockpos, BlockState blockstate, int i) { +- Direction direction = (Direction) blockstate.getValue(PointedDripstoneBlock.TIP_DIRECTION); +- BiPredicate bipredicate = (blockpos1, blockstate1) -> { +- return blockstate1.is(Blocks.POINTED_DRIPSTONE) && blockstate1.getValue(PointedDripstoneBlock.TIP_DIRECTION) == direction; ++ private static Optional findRootBlock(Level level, BlockPos pos, IBlockData state, int maxIterations) { ++ Direction enumdirection = (Direction) state.getValue(PointedDripstoneBlock.TIP_DIRECTION); ++ BiPredicate bipredicate = (blockposition1, iblockdata1) -> { ++ return iblockdata1.is(Blocks.POINTED_DRIPSTONE) && iblockdata1.getValue(PointedDripstoneBlock.TIP_DIRECTION) == enumdirection; + }; + +- return findBlockVertical(level, blockpos, direction.getOpposite().getAxisDirection(), bipredicate, (blockstate1) -> { +- return !blockstate1.is(Blocks.POINTED_DRIPSTONE); +- }, i); ++ return findBlockVertical(level, pos, enumdirection.getOpposite().getAxisDirection(), bipredicate, (iblockdata1) -> { ++ return !iblockdata1.is(Blocks.POINTED_DRIPSTONE); ++ }, maxIterations); + } + +- private static boolean isValidPointedDripstonePlacement(LevelReader levelreader, BlockPos blockpos, Direction direction) { +- BlockPos blockpos1 = blockpos.relative(direction.getOpposite()); +- BlockState blockstate = levelreader.getBlockState(blockpos1); ++ private static boolean isValidPointedDripstonePlacement(LevelReader level, BlockPos pos, Direction dir) { ++ BlockPos blockposition1 = pos.relative(dir.getOpposite()); ++ IBlockData iblockdata = level.getBlockState(blockposition1); + +- return blockstate.isFaceSturdy(levelreader, blockpos1, direction) || isPointedDripstoneWithDirection(blockstate, direction); ++ return iblockdata.isFaceSturdy(level, blockposition1, dir) || isPointedDripstoneWithDirection(iblockdata, dir); + } + +- private static boolean isTip(BlockState blockstate, boolean flag) { +- if (!blockstate.is(Blocks.POINTED_DRIPSTONE)) { ++ private static boolean isTip(IBlockData state, boolean isTipMerge) { ++ if (!state.is(Blocks.POINTED_DRIPSTONE)) { + return false; + } else { +- DripstoneThickness dripstonethickness = (DripstoneThickness) blockstate.getValue(PointedDripstoneBlock.THICKNESS); ++ DripstoneThickness dripstonethickness = (DripstoneThickness) state.getValue(PointedDripstoneBlock.THICKNESS); + +- return dripstonethickness == DripstoneThickness.TIP || flag && dripstonethickness == DripstoneThickness.TIP_MERGE; ++ return dripstonethickness == DripstoneThickness.TIP || isTipMerge && dripstonethickness == DripstoneThickness.TIP_MERGE; + } + } + +- private static boolean isUnmergedTipWithDirection(BlockState blockstate, Direction direction) { +- return isTip(blockstate, false) && blockstate.getValue(PointedDripstoneBlock.TIP_DIRECTION) == direction; ++ private static boolean isUnmergedTipWithDirection(IBlockData state, Direction dir) { ++ return isTip(state, false) && state.getValue(PointedDripstoneBlock.TIP_DIRECTION) == dir; + } + +- private static boolean isStalactite(BlockState blockstate) { +- return isPointedDripstoneWithDirection(blockstate, Direction.DOWN); ++ private static boolean isStalactite(IBlockData state) { ++ return isPointedDripstoneWithDirection(state, Direction.DOWN); + } + +- private static boolean isStalagmite(BlockState blockstate) { +- return isPointedDripstoneWithDirection(blockstate, Direction.UP); ++ private static boolean isStalagmite(IBlockData state) { ++ return isPointedDripstoneWithDirection(state, Direction.UP); + } + +- private static boolean isStalactiteStartPos(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- return isStalactite(blockstate) && !levelreader.getBlockState(blockpos.above()).is(Blocks.POINTED_DRIPSTONE); ++ private static boolean isStalactiteStartPos(IBlockData state, LevelReader level, BlockPos pos) { ++ return isStalactite(state) && !level.getBlockState(pos.above()).is(Blocks.POINTED_DRIPSTONE); + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + +- private static boolean isPointedDripstoneWithDirection(BlockState blockstate, Direction direction) { +- return blockstate.is(Blocks.POINTED_DRIPSTONE) && blockstate.getValue(PointedDripstoneBlock.TIP_DIRECTION) == direction; ++ private static boolean isPointedDripstoneWithDirection(IBlockData state, Direction dir) { ++ return state.is(Blocks.POINTED_DRIPSTONE) && state.getValue(PointedDripstoneBlock.TIP_DIRECTION) == dir; + } + + @Nullable +- private static BlockPos findFillableCauldronBelowStalactiteTip(Level level, BlockPos blockpos, Fluid fluid) { +- Predicate predicate = (blockstate) -> { +- return blockstate.getBlock() instanceof AbstractCauldronBlock && ((AbstractCauldronBlock) blockstate.getBlock()).canReceiveStalactiteDrip(fluid); ++ private static BlockPos findFillableCauldronBelowStalactiteTip(Level level, BlockPos pos, Fluid fluid) { ++ Predicate predicate = (iblockdata) -> { ++ return iblockdata.getBlock() instanceof AbstractCauldronBlock && ((AbstractCauldronBlock) iblockdata.getBlock()).canReceiveStalactiteDrip(fluid); + }; +- BiPredicate bipredicate = (blockpos1, blockstate) -> { +- return canDripThrough(level, blockpos1, blockstate); ++ BiPredicate bipredicate = (blockposition1, iblockdata) -> { ++ return canDripThrough(level, blockposition1, iblockdata); + }; + +- return (BlockPos) findBlockVertical(level, blockpos, Direction.DOWN.getAxisDirection(), bipredicate, predicate, 11).orElse((Object) null); ++ return (BlockPos) findBlockVertical(level, pos, Direction.DOWN.getAxisDirection(), bipredicate, predicate, 11).orElse(null); // CraftBukkit - decompile error + } + + @Nullable +- public static BlockPos findStalactiteTipAboveCauldron(Level level, BlockPos blockpos) { +- BiPredicate bipredicate = (blockpos1, blockstate) -> { +- return canDripThrough(level, blockpos1, blockstate); ++ public static BlockPos findStalactiteTipAboveCauldron(Level level, BlockPos pos) { ++ BiPredicate bipredicate = (blockposition1, iblockdata) -> { ++ return canDripThrough(level, blockposition1, iblockdata); + }; + +- return (BlockPos) findBlockVertical(level, blockpos, Direction.UP.getAxisDirection(), bipredicate, PointedDripstoneBlock::canDrip, 11).orElse((Object) null); ++ return (BlockPos) findBlockVertical(level, pos, Direction.UP.getAxisDirection(), bipredicate, PointedDripstoneBlock::canDrip, 11).orElse(null); // CraftBukkit - decompile error + } + +- public static Fluid getCauldronFillFluidType(ServerLevel serverlevel, BlockPos blockpos) { +- return (Fluid) getFluidAboveStalactite(serverlevel, blockpos, serverlevel.getBlockState(blockpos)).map((pointeddripstoneblock_fluidinfo) -> { +- return pointeddripstoneblock_fluidinfo.fluid; ++ public static Fluid getCauldronFillFluidType(ServerLevel level, BlockPos pos) { ++ return (Fluid) getFluidAboveStalactite(level, pos, level.getBlockState(pos)).map((pointeddripstoneblock_a) -> { ++ return pointeddripstoneblock_a.fluid; + }).filter(PointedDripstoneBlock::canFillCauldron).orElse(Fluids.EMPTY); + } + +- private static Optional getFluidAboveStalactite(Level level, BlockPos blockpos, BlockState blockstate) { +- return !isStalactite(blockstate) ? Optional.empty() : findRootBlock(level, blockpos, blockstate, 11).map((blockpos1) -> { +- BlockPos blockpos2 = blockpos1.above(); +- BlockState blockstate1 = level.getBlockState(blockpos2); ++ private static Optional getFluidAboveStalactite(Level level, BlockPos pos, IBlockData state) { ++ return !isStalactite(state) ? Optional.empty() : findRootBlock(level, pos, state, 11).map((blockposition1) -> { ++ BlockPos blockposition2 = blockposition1.above(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition2); + Object object; + +- if (blockstate1.is(Blocks.MUD) && !level.dimensionType().ultraWarm()) { ++ if (iblockdata1.is(Blocks.MUD) && !level.dimensionType().ultraWarm()) { + object = Fluids.WATER; + } else { +- object = level.getFluidState(blockpos2).getType(); ++ object = level.getFluidState(blockposition2).getType(); + } + +- return new PointedDripstoneBlock.FluidInfo(blockpos2, (Fluid) object, blockstate1); ++ return new PointedDripstoneBlock.a(blockposition2, (Fluid) object, iblockdata1); + }); + } + +@@ -615,27 +608,27 @@ + return fluid == Fluids.LAVA || fluid == Fluids.WATER; + } + +- private static boolean canGrow(BlockState blockstate, BlockState blockstate1) { +- return blockstate.is(Blocks.DRIPSTONE_BLOCK) && blockstate1.is(Blocks.WATER) && blockstate1.getFluidState().isSource(); ++ private static boolean canGrow(IBlockData dripstoneState, IBlockData state) { ++ return dripstoneState.is(Blocks.DRIPSTONE_BLOCK) && state.is(Blocks.WATER) && state.getFluidState().isSource(); + } + + private static Fluid getDripFluid(Level level, Fluid fluid) { + return (Fluid) (fluid.isSame(Fluids.EMPTY) ? (level.dimensionType().ultraWarm() ? Fluids.LAVA : Fluids.WATER) : fluid); + } + +- private static Optional findBlockVertical(LevelAccessor levelaccessor, BlockPos blockpos, Direction.AxisDirection direction_axisdirection, BiPredicate bipredicate, Predicate predicate, int i) { +- Direction direction = Direction.get(direction_axisdirection, Direction.Axis.Y); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = blockpos.mutable(); ++ private static Optional findBlockVertical(LevelAccessor level, BlockPos pos, Direction.AxisDirection axis, BiPredicate positionalStatePredicate, Predicate statePredicate, int maxIterations) { ++ Direction enumdirection = Direction.get(axis, Direction.Axis.Y); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); + +- for (int j = 1; j < i; ++j) { +- blockpos_mutableblockpos.move(direction); +- BlockState blockstate = levelaccessor.getBlockState(blockpos_mutableblockpos); ++ for (int j = 1; j < maxIterations; ++j) { ++ blockposition_mutableblockposition.move(enumdirection); ++ IBlockData iblockdata = level.getBlockState(blockposition_mutableblockposition); + +- if (predicate.test(blockstate)) { +- return Optional.of(blockpos_mutableblockpos.immutable()); ++ if (statePredicate.test(iblockdata)) { ++ return Optional.of(blockposition_mutableblockposition.immutable()); + } + +- if (levelaccessor.isOutsideBuildHeight(blockpos_mutableblockpos.getY()) || !bipredicate.test(blockpos_mutableblockpos, blockstate)) { ++ if (level.isOutsideBuildHeight(blockposition_mutableblockposition.getY()) || !positionalStatePredicate.test(blockposition_mutableblockposition, iblockdata)) { + return Optional.empty(); + } + } +@@ -643,21 +636,21 @@ + return Optional.empty(); + } + +- private static boolean canDripThrough(BlockGetter blockgetter, BlockPos blockpos, BlockState blockstate) { +- if (blockstate.isAir()) { ++ private static boolean canDripThrough(BlockGetter level, BlockPos pos, IBlockData state) { ++ if (state.isAir()) { + return true; +- } else if (blockstate.isSolidRender(blockgetter, blockpos)) { ++ } else if (state.isSolidRender(level, pos)) { + return false; +- } else if (!blockstate.getFluidState().isEmpty()) { ++ } else if (!state.getFluidState().isEmpty()) { + return false; + } else { +- VoxelShape voxelshape = blockstate.getCollisionShape(blockgetter, blockpos); ++ VoxelShape voxelshape = state.getCollisionShape(level, pos); + + return !Shapes.joinIsNotEmpty(PointedDripstoneBlock.REQUIRED_SPACE_TO_DRIP_THROUGH_NON_SOLID_BLOCK, voxelshape, BooleanOp.AND); + } + } + +- static record FluidInfo(BlockPos pos, Fluid fluid, BlockState sourceState) { ++ static record a(BlockPos pos, Fluid fluid, IBlockData sourceState) { + + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/PowderSnowBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/PowderSnowBlock.java.patch new file mode 100644 index 0000000000..1ae7a05d80 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/PowderSnowBlock.java.patch @@ -0,0 +1,161 @@ +--- a/net/minecraft/world/level/block/PowderSnowBlock.java ++++ b/net/minecraft/world/level/block/PowderSnowBlock.java +@@ -23,8 +23,8 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.EntityCollisionContext; +@@ -43,46 +43,47 @@ + private static final double MINIMUM_FALL_DISTANCE_FOR_BIG_SOUND = 7.0D; + + @Override +- @Override + public MapCodec codec() { + return PowderSnowBlock.CODEC; + } + +- public PowderSnowBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ public PowderSnowBlock(BlockBehaviour.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public boolean skipRendering(BlockState blockstate, BlockState blockstate1, Direction direction) { +- return blockstate1.is((Block) this) ? true : super.skipRendering(blockstate, blockstate1, direction); ++ public boolean skipRendering(IBlockData state, IBlockData adjacentState, Direction direction) { ++ return adjacentState.is((Block) this) ? true : super.skipRendering(state, adjacentState, direction); + } + + @Override +- @Override +- public VoxelShape getOcclusionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { ++ public VoxelShape getOcclusionShape(IBlockData state, BlockGetter level, BlockPos pos) { + return Shapes.empty(); + } + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { + if (!(entity instanceof LivingEntity) || entity.getFeetBlockState().is((Block) this)) { +- entity.makeStuckInBlock(blockstate, new Vec3(0.8999999761581421D, 1.5D, 0.8999999761581421D)); ++ entity.makeStuckInBlock(state, new Vec3(0.8999999761581421D, 1.5D, 0.8999999761581421D)); + if (level.isClientSide) { + RandomSource randomsource = level.getRandom(); + boolean flag = entity.xOld != entity.getX() || entity.zOld != entity.getZ(); + + if (flag && randomsource.nextBoolean()) { +- level.addParticle(ParticleTypes.SNOWFLAKE, entity.getX(), (double) (blockpos.getY() + 1), entity.getZ(), (double) (Mth.randomBetween(randomsource, -1.0F, 1.0F) * 0.083333336F), 0.05000000074505806D, (double) (Mth.randomBetween(randomsource, -1.0F, 1.0F) * 0.083333336F)); ++ level.addParticle(ParticleTypes.SNOWFLAKE, entity.getX(), (double) (pos.getY() + 1), entity.getZ(), (double) (Mth.randomBetween(randomsource, -1.0F, 1.0F) * 0.083333336F), 0.05000000074505806D, (double) (Mth.randomBetween(randomsource, -1.0F, 1.0F) * 0.083333336F)); + } + } + } + + entity.setIsInPowderSnow(true); + if (!level.isClientSide) { +- if (entity.isOnFire() && (level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity instanceof Player) && entity.mayInteract(level, blockpos)) { +- level.destroyBlock(blockpos, false); ++ // CraftBukkit start ++ if (entity.isOnFire() && entity.mayInteract(level, pos)) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !(level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity instanceof Player))) { ++ return; ++ } ++ // CraftBukkit end ++ level.destroyBlock(pos, false); + } + + entity.setSharedFlagOnFire(false); +@@ -91,23 +92,21 @@ + } + + @Override +- @Override +- public void fallOn(Level level, BlockState blockstate, BlockPos blockpos, Entity entity, float f) { +- if ((double) f >= 4.0D && entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; +- LivingEntity.Fallsounds livingentity_fallsounds = livingentity.getFallSounds(); +- SoundEvent soundevent = (double) f < 7.0D ? livingentity_fallsounds.small() : livingentity_fallsounds.big(); ++ public void fallOn(Level level, IBlockData state, BlockPos pos, Entity entity, float fallDistance) { ++ if ((double) fallDistance >= 4.0D && entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ LivingEntity.a entityliving_a = entityliving.getFallSounds(); ++ SoundEvent soundeffect = (double) fallDistance < 7.0D ? entityliving_a.small() : entityliving_a.big(); + +- entity.playSound(soundevent, 1.0F, 1.0F); ++ entity.playSound(soundeffect, 1.0F, 1.0F); + } + } + + @Override +- @Override +- public VoxelShape getCollisionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- if (collisioncontext instanceof EntityCollisionContext) { +- EntityCollisionContext entitycollisioncontext = (EntityCollisionContext) collisioncontext; +- Entity entity = entitycollisioncontext.getEntity(); ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ if (context instanceof EntityCollisionContext) { ++ EntityCollisionContext voxelshapecollisionentity = (EntityCollisionContext) context; ++ Entity entity = voxelshapecollisionentity.getEntity(); + + if (entity != null) { + if (entity.fallDistance > 2.5F) { +@@ -116,8 +115,8 @@ + + boolean flag = entity instanceof FallingBlockEntity; + +- if (flag || canEntityWalkOnPowderSnow(entity) && collisioncontext.isAbove(Shapes.block(), blockpos, false) && !collisioncontext.isDescending()) { +- return super.getCollisionShape(blockstate, blockgetter, blockpos, collisioncontext); ++ if (flag || canEntityWalkOnPowderSnow(entity) && context.isAbove(Shapes.block(), pos, false) && !context.isDescending()) { ++ return super.getCollisionShape(state, level, pos, context); + } + } + } +@@ -126,8 +125,7 @@ + } + + @Override +- @Override +- public VoxelShape getVisualShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getVisualShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return Shapes.empty(); + } + +@@ -136,25 +134,22 @@ + } + + @Override +- @Override +- public ItemStack pickupBlock(@Nullable Player player, LevelAccessor levelaccessor, BlockPos blockpos, BlockState blockstate) { +- levelaccessor.setBlock(blockpos, Blocks.AIR.defaultBlockState(), 11); +- if (!levelaccessor.isClientSide()) { +- levelaccessor.levelEvent(2001, blockpos, Block.getId(blockstate)); ++ public ItemStack pickupBlock(@Nullable Player entityhuman, LevelAccessor generatoraccess, BlockPos blockposition, IBlockData iblockdata) { ++ generatoraccess.setBlock(blockposition, Blocks.AIR.defaultBlockState(), 11); ++ if (!generatoraccess.isClientSide()) { ++ generatoraccess.levelEvent(2001, blockposition, Block.getId(iblockdata)); + } + + return new ItemStack(Items.POWDER_SNOW_BUCKET); + } + + @Override +- @Override + public Optional getPickupSound() { + return Optional.of(SoundEvents.BUCKET_FILL_POWDER_SNOW); + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return true; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/PoweredRailBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/PoweredRailBlock.java.patch new file mode 100644 index 0000000000..4311b185ab --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/PoweredRailBlock.java.patch @@ -0,0 +1,361 @@ +--- a/net/minecraft/world/level/block/PoweredRailBlock.java ++++ b/net/minecraft/world/level/block/PoweredRailBlock.java +@@ -4,13 +4,14 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.block.state.properties.EnumProperty; + import net.minecraft.world.level.block.state.properties.Property; + import net.minecraft.world.level.block.state.properties.RailShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class PoweredRailBlock extends BaseRailBlock { + +@@ -19,43 +20,42 @@ + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + + @Override +- @Override + public MapCodec codec() { + return PoweredRailBlock.CODEC; + } + +- protected PoweredRailBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(true, blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_SOUTH)).setValue(PoweredRailBlock.POWERED, false)).setValue(PoweredRailBlock.WATERLOGGED, false)); ++ protected PoweredRailBlock(BlockBehaviour.Properties properties) { ++ super(true, properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_SOUTH)).setValue(PoweredRailBlock.POWERED, false)).setValue(PoweredRailBlock.WATERLOGGED, false)); + } + +- protected boolean findPoweredRailSignal(Level level, BlockPos blockpos, BlockState blockstate, boolean flag, int i) { +- if (i >= 8) { ++ protected boolean findPoweredRailSignal(Level level, BlockPos pos, IBlockData state, boolean searchForward, int recursionCount) { ++ if (recursionCount >= 8) { + return false; + } else { +- int j = blockpos.getX(); +- int k = blockpos.getY(); +- int l = blockpos.getZ(); ++ int j = pos.getX(); ++ int k = pos.getY(); ++ int l = pos.getZ(); + boolean flag1 = true; +- RailShape railshape = (RailShape) blockstate.getValue(PoweredRailBlock.SHAPE); ++ RailShape blockpropertytrackposition = (RailShape) state.getValue(PoweredRailBlock.SHAPE); + +- switch (railshape) { ++ switch (blockpropertytrackposition) { + case NORTH_SOUTH: +- if (flag) { ++ if (searchForward) { + ++l; + } else { + --l; + } + break; + case EAST_WEST: +- if (flag) { ++ if (searchForward) { + --j; + } else { + ++j; + } + break; + case ASCENDING_EAST: +- if (flag) { ++ if (searchForward) { + --j; + } else { + ++j; +@@ -63,10 +63,10 @@ + flag1 = false; + } + +- railshape = RailShape.EAST_WEST; ++ blockpropertytrackposition = RailShape.EAST_WEST; + break; + case ASCENDING_WEST: +- if (flag) { ++ if (searchForward) { + --j; + ++k; + flag1 = false; +@@ -74,10 +74,10 @@ + ++j; + } + +- railshape = RailShape.EAST_WEST; ++ blockpropertytrackposition = RailShape.EAST_WEST; + break; + case ASCENDING_NORTH: +- if (flag) { ++ if (searchForward) { + ++l; + } else { + --l; +@@ -85,10 +85,10 @@ + flag1 = false; + } + +- railshape = RailShape.NORTH_SOUTH; ++ blockpropertytrackposition = RailShape.NORTH_SOUTH; + break; + case ASCENDING_SOUTH: +- if (flag) { ++ if (searchForward) { + ++l; + ++k; + flag1 = false; +@@ -96,171 +96,173 @@ + --l; + } + +- railshape = RailShape.NORTH_SOUTH; ++ blockpropertytrackposition = RailShape.NORTH_SOUTH; + } + +- return this.isSameRailWithPower(level, new BlockPos(j, k, l), flag, i, railshape) ? true : flag1 && this.isSameRailWithPower(level, new BlockPos(j, k - 1, l), flag, i, railshape); ++ return this.isSameRailWithPower(level, new BlockPos(j, k, l), searchForward, recursionCount, blockpropertytrackposition) ? true : flag1 && this.isSameRailWithPower(level, new BlockPos(j, k - 1, l), searchForward, recursionCount, blockpropertytrackposition); + } + } + +- protected boolean isSameRailWithPower(Level level, BlockPos blockpos, boolean flag, int i, RailShape railshape) { +- BlockState blockstate = level.getBlockState(blockpos); ++ protected boolean isSameRailWithPower(Level level, BlockPos state, boolean searchForward, int recursionCount, RailShape shape) { ++ IBlockData iblockdata = level.getBlockState(state); + +- if (!blockstate.is((Block) this)) { ++ if (!iblockdata.is((Block) this)) { + return false; + } else { +- RailShape railshape1 = (RailShape) blockstate.getValue(PoweredRailBlock.SHAPE); ++ RailShape blockpropertytrackposition1 = (RailShape) iblockdata.getValue(PoweredRailBlock.SHAPE); + +- return railshape == RailShape.EAST_WEST && (railshape1 == RailShape.NORTH_SOUTH || railshape1 == RailShape.ASCENDING_NORTH || railshape1 == RailShape.ASCENDING_SOUTH) ? false : (railshape == RailShape.NORTH_SOUTH && (railshape1 == RailShape.EAST_WEST || railshape1 == RailShape.ASCENDING_EAST || railshape1 == RailShape.ASCENDING_WEST) ? false : ((Boolean) blockstate.getValue(PoweredRailBlock.POWERED) ? (level.hasNeighborSignal(blockpos) ? true : this.findPoweredRailSignal(level, blockpos, blockstate, flag, i + 1)) : false)); ++ return shape == RailShape.EAST_WEST && (blockpropertytrackposition1 == RailShape.NORTH_SOUTH || blockpropertytrackposition1 == RailShape.ASCENDING_NORTH || blockpropertytrackposition1 == RailShape.ASCENDING_SOUTH) ? false : (shape == RailShape.NORTH_SOUTH && (blockpropertytrackposition1 == RailShape.EAST_WEST || blockpropertytrackposition1 == RailShape.ASCENDING_EAST || blockpropertytrackposition1 == RailShape.ASCENDING_WEST) ? false : ((Boolean) iblockdata.getValue(PoweredRailBlock.POWERED) ? (level.hasNeighborSignal(state) ? true : this.findPoweredRailSignal(level, state, iblockdata, searchForward, recursionCount + 1)) : false)); + } + } + + @Override +- @Override +- protected void updateState(BlockState blockstate, Level level, BlockPos blockpos, Block block) { +- boolean flag = (Boolean) blockstate.getValue(PoweredRailBlock.POWERED); +- boolean flag1 = level.hasNeighborSignal(blockpos) || this.findPoweredRailSignal(level, blockpos, blockstate, true, 0) || this.findPoweredRailSignal(level, blockpos, blockstate, false, 0); ++ protected void updateState(IBlockData state, Level level, BlockPos pos, Block block) { ++ boolean flag = (Boolean) state.getValue(PoweredRailBlock.POWERED); ++ boolean flag1 = level.hasNeighborSignal(pos) || this.findPoweredRailSignal(level, pos, state, true, 0) || this.findPoweredRailSignal(level, pos, state, false, 0); + + if (flag1 != flag) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(PoweredRailBlock.POWERED, flag1), 3); +- level.updateNeighborsAt(blockpos.below(), this); +- if (((RailShape) blockstate.getValue(PoweredRailBlock.SHAPE)).isAscending()) { +- level.updateNeighborsAt(blockpos.above(), this); ++ // CraftBukkit start ++ int power = flag ? 15 : 0; ++ int newPower = CraftEventFactory.callRedstoneChange(level, pos, power, 15 - power).getNewCurrent(); ++ if (newPower == power) { ++ return; + } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(PoweredRailBlock.POWERED, flag1), 3); ++ level.updateNeighborsAt(pos.below(), this); ++ if (((RailShape) state.getValue(PoweredRailBlock.SHAPE)).isAscending()) { ++ level.updateNeighborsAt(pos.above(), this); ++ } + } + + } + + @Override +- @Override + public Property getShapeProperty() { + return PoweredRailBlock.SHAPE; + } + + @Override +- @Override +- public BlockState rotate(BlockState blockstate, Rotation rotation) { +- switch (rotation) { ++ public IBlockData rotate(IBlockData state, Rotation rot) { ++ switch (rot) { + case CLOCKWISE_180: +- switch ((RailShape) blockstate.getValue(PoweredRailBlock.SHAPE)) { ++ switch ((RailShape) state.getValue(PoweredRailBlock.SHAPE)) { + case ASCENDING_EAST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_WEST); + case ASCENDING_WEST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_EAST); + case ASCENDING_NORTH: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); + case ASCENDING_SOUTH: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_NORTH); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_NORTH); + case SOUTH_EAST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_WEST); + case SOUTH_WEST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_EAST); + case NORTH_WEST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_EAST); + case NORTH_EAST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_WEST); + } + case COUNTERCLOCKWISE_90: +- switch ((RailShape) blockstate.getValue(PoweredRailBlock.SHAPE)) { ++ switch ((RailShape) state.getValue(PoweredRailBlock.SHAPE)) { + case NORTH_SOUTH: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.EAST_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.EAST_WEST); + case EAST_WEST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_SOUTH); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_SOUTH); + case ASCENDING_EAST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_NORTH); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_NORTH); + case ASCENDING_WEST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); + case ASCENDING_NORTH: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_WEST); + case ASCENDING_SOUTH: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_EAST); + case SOUTH_EAST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_EAST); + case SOUTH_WEST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_EAST); + case NORTH_WEST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_WEST); + case NORTH_EAST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_WEST); + } + case CLOCKWISE_90: +- switch ((RailShape) blockstate.getValue(PoweredRailBlock.SHAPE)) { ++ switch ((RailShape) state.getValue(PoweredRailBlock.SHAPE)) { + case NORTH_SOUTH: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.EAST_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.EAST_WEST); + case EAST_WEST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_SOUTH); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_SOUTH); + case ASCENDING_EAST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); + case ASCENDING_WEST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_NORTH); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_NORTH); + case ASCENDING_NORTH: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_EAST); + case ASCENDING_SOUTH: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_WEST); + case SOUTH_EAST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_WEST); + case SOUTH_WEST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_WEST); + case NORTH_WEST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_EAST); + case NORTH_EAST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_EAST); + } + default: +- return blockstate; ++ return state; + } + } + + @Override +- @Override +- public BlockState mirror(BlockState blockstate, Mirror mirror) { +- RailShape railshape = (RailShape) blockstate.getValue(PoweredRailBlock.SHAPE); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ RailShape blockpropertytrackposition = (RailShape) state.getValue(PoweredRailBlock.SHAPE); + + switch (mirror) { + case LEFT_RIGHT: +- switch (railshape) { ++ switch (blockpropertytrackposition) { + case ASCENDING_NORTH: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); + case ASCENDING_SOUTH: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_NORTH); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_NORTH); + case SOUTH_EAST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_EAST); + case SOUTH_WEST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_WEST); + case NORTH_WEST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_WEST); + case NORTH_EAST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_EAST); + default: +- return super.mirror(blockstate, mirror); ++ return super.mirror(state, mirror); + } + case FRONT_BACK: +- switch (railshape) { ++ switch (blockpropertytrackposition) { + case ASCENDING_EAST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_WEST); + case ASCENDING_WEST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_EAST); + case ASCENDING_NORTH: + case ASCENDING_SOUTH: + default: + break; + case SOUTH_EAST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_WEST); + case SOUTH_WEST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_EAST); + case NORTH_WEST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_EAST); + case NORTH_EAST: +- return (BlockState) blockstate.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_WEST); + } + } + +- return super.mirror(blockstate, mirror); ++ return super.mirror(state, mirror); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(PoweredRailBlock.SHAPE, PoweredRailBlock.POWERED, PoweredRailBlock.WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(PoweredRailBlock.SHAPE, PoweredRailBlock.POWERED, PoweredRailBlock.WATERLOGGED); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/PressurePlateBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/PressurePlateBlock.java.patch new file mode 100644 index 0000000000..ee792e88af --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/PressurePlateBlock.java.patch @@ -0,0 +1,108 @@ +--- a/net/minecraft/world/level/block/PressurePlateBlock.java ++++ b/net/minecraft/world/level/block/PressurePlateBlock.java +@@ -5,50 +5,49 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockSetType; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end + + public class PressurePlateBlock extends BasePressurePlateBlock { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- return instance.group(BlockSetType.CODEC.fieldOf("block_set_type").forGetter((pressureplateblock) -> { +- return pressureplateblock.type; ++ return instance.group(BlockSetType.CODEC.fieldOf("block_set_type").forGetter((blockpressureplatebinary) -> { ++ return blockpressureplatebinary.type; + }), propertiesCodec()).apply(instance, PressurePlateBlock::new); + }); + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + + @Override +- @Override + public MapCodec codec() { + return PressurePlateBlock.CODEC; + } + +- protected PressurePlateBlock(BlockSetType blocksettype, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties, blocksettype); +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(PressurePlateBlock.POWERED, false)); ++ protected PressurePlateBlock(BlockSetType blocksettype, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info, blocksettype); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(PressurePlateBlock.POWERED, false)); + } + + @Override +- @Override +- protected int getSignalForState(BlockState blockstate) { +- return (Boolean) blockstate.getValue(PressurePlateBlock.POWERED) ? 15 : 0; ++ protected int getSignalForState(IBlockData state) { ++ return (Boolean) state.getValue(PressurePlateBlock.POWERED) ? 15 : 0; + } + + @Override +- @Override +- protected BlockState setSignalForState(BlockState blockstate, int i) { +- return (BlockState) blockstate.setValue(PressurePlateBlock.POWERED, i > 0); ++ protected IBlockData setSignalForState(IBlockData state, int strength) { ++ return (IBlockData) state.setValue(PressurePlateBlock.POWERED, strength > 0); + } + + @Override +- @Override +- protected int getSignalStrength(Level level, BlockPos blockpos) { +- Class oclass; ++ protected int getSignalStrength(Level level, BlockPos pos) { ++ Class oclass; // CraftBukkit + + switch (this.type.pressurePlateSensitivity()) { + case EVERYTHING: +@@ -63,12 +62,35 @@ + + Class oclass1 = oclass; + +- return getEntityCount(level, PressurePlateBlock.TOUCH_AABB.move(blockpos), oclass1) > 0 ? 15 : 0; ++ // CraftBukkit start - Call interact event when turning on a pressure plate ++ for (Entity entity : getEntities(level, PressurePlateBlock.TOUCH_AABB.move(pos), oclass)) { ++ if (this.getSignalForState(level.getBlockState(pos)) == 0) { ++ org.bukkit.World bworld = level.getWorld(); ++ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager(); ++ org.bukkit.event.Cancellable cancellable; ++ ++ if (entity instanceof Player) { ++ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ manager.callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ // We only want to block turning the plate on if all events are cancelled ++ if (cancellable.isCancelled()) { ++ continue; ++ } ++ } ++ ++ return 15; ++ } ++ ++ return 0; ++ // CraftBukkit end + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(PressurePlateBlock.POWERED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(PressurePlateBlock.POWERED); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/RedStoneOreBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/RedStoneOreBlock.java.patch new file mode 100644 index 0000000000..5972cc7587 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/RedStoneOreBlock.java.patch @@ -0,0 +1,221 @@ +--- a/net/minecraft/world/level/block/RedStoneOreBlock.java ++++ b/net/minecraft/world/level/block/RedStoneOreBlock.java +@@ -3,10 +3,10 @@ + import com.mojang.serialization.MapCodec; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.particles.DustParticleOptions; ++import net.minecraft.core.particles.ParticleParamRedstone; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; +@@ -17,10 +17,14 @@ + import net.minecraft.world.item.enchantment.Enchantments; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.phys.BlockHitResult; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end + + public class RedStoneOreBlock extends Block { + +@@ -28,116 +32,138 @@ + public static final BooleanProperty LIT = RedstoneTorchBlock.LIT; + + @Override +- @Override + public MapCodec codec() { + return RedStoneOreBlock.CODEC; + } + +- public RedStoneOreBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) this.defaultBlockState().setValue(RedStoneOreBlock.LIT, false)); ++ public RedStoneOreBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) this.defaultBlockState().setValue(RedStoneOreBlock.LIT, false)); + } + + @Override +- @Override +- public void attack(BlockState blockstate, Level level, BlockPos blockpos, Player player) { +- interact(blockstate, level, blockpos); +- super.attack(blockstate, level, blockpos, player); ++ public void attack(IBlockData state, Level level, BlockPos pos, Player player) { ++ interact(state, level, pos, player); // CraftBukkit - add entityhuman ++ super.attack(state, level, pos, player); + } + + @Override +- @Override +- public void stepOn(Level level, BlockPos blockpos, BlockState blockstate, Entity entity) { ++ public void stepOn(Level level, BlockPos pos, IBlockData state, Entity entity) { + if (!entity.isSteppingCarefully()) { +- interact(blockstate, level, blockpos); ++ // CraftBukkit start ++ if (entity instanceof Player) { ++ org.bukkit.event.player.PlayerInteractEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ if (!event.isCancelled()) { ++ interact(level.getBlockState(pos), level, pos, entity); // add entity ++ } ++ } else { ++ EntityInteractEvent event = new EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ interact(level.getBlockState(pos), level, pos, entity); // add entity ++ } ++ } ++ // CraftBukkit end + } + +- super.stepOn(level, blockpos, blockstate, entity); ++ super.stepOn(level, pos, state, entity); + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + if (level.isClientSide) { +- spawnParticles(level, blockpos); ++ spawnParticles(level, pos); + } else { +- interact(blockstate, level, blockpos); ++ interact(state, level, pos, player); // CraftBukkit - add entityhuman + } + +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ ItemStack itemstack = player.getItemInHand(hand); + +- return itemstack.getItem() instanceof BlockItem && (new BlockPlaceContext(player, interactionhand, itemstack, blockhitresult)).canPlace() ? InteractionResult.PASS : InteractionResult.SUCCESS; ++ return itemstack.getItem() instanceof BlockItem && (new BlockPlaceContext(player, hand, itemstack, hit)).canPlace() ? InteractionResult.PASS : InteractionResult.SUCCESS; + } + +- private static void interact(BlockState blockstate, Level level, BlockPos blockpos) { +- spawnParticles(level, blockpos); +- if (!(Boolean) blockstate.getValue(RedStoneOreBlock.LIT)) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(RedStoneOreBlock.LIT, true), 3); ++ private static void interact(IBlockData iblockdata, Level world, BlockPos blockposition, Entity entity) { // CraftBukkit - add Entity ++ spawnParticles(world, blockposition); ++ if (!(Boolean) iblockdata.getValue(RedStoneOreBlock.LIT)) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, iblockdata.setValue(RedStoneOreBlock.LIT, true))) { ++ return; ++ } ++ // CraftBukkit end ++ world.setBlock(blockposition, (IBlockData) iblockdata.setValue(RedStoneOreBlock.LIT, true), 3); + } + + } + + @Override +- @Override +- public boolean isRandomlyTicking(BlockState blockstate) { +- return (Boolean) blockstate.getValue(RedStoneOreBlock.LIT); ++ public boolean isRandomlyTicking(IBlockData state) { ++ return (Boolean) state.getValue(RedStoneOreBlock.LIT); + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if ((Boolean) blockstate.getValue(RedStoneOreBlock.LIT)) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(RedStoneOreBlock.LIT, false), 3); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(RedStoneOreBlock.LIT)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callBlockFadeEvent(level, pos, state.setValue(RedStoneOreBlock.LIT, false)).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(RedStoneOreBlock.LIT, false), 3); + } + + } + + @Override ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ super.spawnAfterBreak(state, level, pos, stack, dropExperience); ++ // CraftBukkit start - Delegated to getExpDrop ++ } ++ + @Override +- public void spawnAfterBreak(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, ItemStack itemstack, boolean flag) { +- super.spawnAfterBreak(blockstate, serverlevel, blockpos, itemstack, flag); ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { + if (flag && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, itemstack) == 0) { +- int i = 1 + serverlevel.random.nextInt(5); ++ int i = 1 + worldserver.random.nextInt(5); + +- this.popExperience(serverlevel, blockpos, i); ++ // this.popExperience(worldserver, blockposition, i); ++ return i; + } + ++ return 0; ++ // CraftBukkit end + } + + @Override +- @Override +- public void animateTick(BlockState blockstate, Level level, BlockPos blockpos, RandomSource randomsource) { +- if ((Boolean) blockstate.getValue(RedStoneOreBlock.LIT)) { +- spawnParticles(level, blockpos); ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(RedStoneOreBlock.LIT)) { ++ spawnParticles(level, pos); + } + + } + +- private static void spawnParticles(Level level, BlockPos blockpos) { ++ private static void spawnParticles(Level level, BlockPos pos) { + double d0 = 0.5625D; + RandomSource randomsource = level.random; +- Direction[] adirection = Direction.values(); +- int i = adirection.length; ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; +- BlockPos blockpos1 = blockpos.relative(direction); ++ Direction enumdirection = aenumdirection[j]; ++ BlockPos blockposition1 = pos.relative(enumdirection); + +- if (!level.getBlockState(blockpos1).isSolidRender(level, blockpos1)) { +- Direction.Axis direction_axis = direction.getAxis(); +- double d1 = direction_axis == Direction.Axis.X ? 0.5D + 0.5625D * (double) direction.getStepX() : (double) randomsource.nextFloat(); +- double d2 = direction_axis == Direction.Axis.Y ? 0.5D + 0.5625D * (double) direction.getStepY() : (double) randomsource.nextFloat(); +- double d3 = direction_axis == Direction.Axis.Z ? 0.5D + 0.5625D * (double) direction.getStepZ() : (double) randomsource.nextFloat(); ++ if (!level.getBlockState(blockposition1).isSolidRender(level, blockposition1)) { ++ Direction.Axis enumdirection_enumaxis = enumdirection.getAxis(); ++ double d1 = enumdirection_enumaxis == Direction.Axis.X ? 0.5D + 0.5625D * (double) enumdirection.getStepX() : (double) randomsource.nextFloat(); ++ double d2 = enumdirection_enumaxis == Direction.Axis.Y ? 0.5D + 0.5625D * (double) enumdirection.getStepY() : (double) randomsource.nextFloat(); ++ double d3 = enumdirection_enumaxis == Direction.Axis.Z ? 0.5D + 0.5625D * (double) enumdirection.getStepZ() : (double) randomsource.nextFloat(); + +- level.addParticle(DustParticleOptions.REDSTONE, (double) blockpos.getX() + d1, (double) blockpos.getY() + d2, (double) blockpos.getZ() + d3, 0.0D, 0.0D, 0.0D); ++ level.addParticle(ParticleParamRedstone.REDSTONE, (double) pos.getX() + d1, (double) pos.getY() + d2, (double) pos.getZ() + d3, 0.0D, 0.0D, 0.0D); + } + } + + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(RedStoneOreBlock.LIT); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(RedStoneOreBlock.LIT); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/RedStoneWireBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/RedStoneWireBlock.java.patch new file mode 100644 index 0000000000..3305feaec2 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/RedStoneWireBlock.java.patch @@ -0,0 +1,768 @@ +--- a/net/minecraft/world/level/block/RedStoneWireBlock.java ++++ b/net/minecraft/world/level/block/RedStoneWireBlock.java +@@ -12,10 +12,10 @@ + import net.minecraft.Util; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.particles.DustParticleOptions; ++import net.minecraft.core.particles.ParticleParamRedstone; + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.context.BlockPlaceContext; +@@ -24,7 +24,7 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.EnumProperty; +@@ -36,6 +36,7 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class RedStoneWireBlock extends Block { + +@@ -54,56 +55,55 @@ + private static final VoxelShape SHAPE_DOT = Block.box(3.0D, 0.0D, 3.0D, 13.0D, 1.0D, 13.0D); + private static final Map SHAPES_FLOOR = Maps.newEnumMap(ImmutableMap.of(Direction.NORTH, Block.box(3.0D, 0.0D, 0.0D, 13.0D, 1.0D, 13.0D), Direction.SOUTH, Block.box(3.0D, 0.0D, 3.0D, 13.0D, 1.0D, 16.0D), Direction.EAST, Block.box(3.0D, 0.0D, 3.0D, 16.0D, 1.0D, 13.0D), Direction.WEST, Block.box(0.0D, 0.0D, 3.0D, 13.0D, 1.0D, 13.0D))); + private static final Map SHAPES_UP = Maps.newEnumMap(ImmutableMap.of(Direction.NORTH, Shapes.or((VoxelShape) RedStoneWireBlock.SHAPES_FLOOR.get(Direction.NORTH), Block.box(3.0D, 0.0D, 0.0D, 13.0D, 16.0D, 1.0D)), Direction.SOUTH, Shapes.or((VoxelShape) RedStoneWireBlock.SHAPES_FLOOR.get(Direction.SOUTH), Block.box(3.0D, 0.0D, 15.0D, 13.0D, 16.0D, 16.0D)), Direction.EAST, Shapes.or((VoxelShape) RedStoneWireBlock.SHAPES_FLOOR.get(Direction.EAST), Block.box(15.0D, 0.0D, 3.0D, 16.0D, 16.0D, 13.0D)), Direction.WEST, Shapes.or((VoxelShape) RedStoneWireBlock.SHAPES_FLOOR.get(Direction.WEST), Block.box(0.0D, 0.0D, 3.0D, 1.0D, 16.0D, 13.0D)))); +- private static final Map SHAPES_CACHE = Maps.newHashMap(); +- private static final Vec3[] COLORS = (Vec3[]) Util.make(new Vec3[16], (avec3) -> { ++ private static final Map SHAPES_CACHE = Maps.newHashMap(); ++ private static final Vec3[] COLORS = (Vec3[]) Util.make(new Vec3[16], (avec3d) -> { + for (int i = 0; i <= 15; ++i) { + float f = (float) i / 15.0F; + float f1 = f * 0.6F + (f > 0.0F ? 0.4F : 0.3F); + float f2 = Mth.clamp(f * f * 0.7F - 0.5F, 0.0F, 1.0F); + float f3 = Mth.clamp(f * f * 0.6F - 0.7F, 0.0F, 1.0F); + +- avec3[i] = new Vec3((double) f1, (double) f2, (double) f3); ++ avec3d[i] = new Vec3((double) f1, (double) f2, (double) f3); + } + + }); + private static final float PARTICLE_DENSITY = 0.2F; +- private final BlockState crossState; ++ private final IBlockData crossState; + private boolean shouldSignal = true; + + @Override +- @Override + public MapCodec codec() { + return RedStoneWireBlock.CODEC; + } + +- public RedStoneWireBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(RedStoneWireBlock.NORTH, RedstoneSide.NONE)).setValue(RedStoneWireBlock.EAST, RedstoneSide.NONE)).setValue(RedStoneWireBlock.SOUTH, RedstoneSide.NONE)).setValue(RedStoneWireBlock.WEST, RedstoneSide.NONE)).setValue(RedStoneWireBlock.POWER, 0)); +- this.crossState = (BlockState) ((BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(RedStoneWireBlock.NORTH, RedstoneSide.SIDE)).setValue(RedStoneWireBlock.EAST, RedstoneSide.SIDE)).setValue(RedStoneWireBlock.SOUTH, RedstoneSide.SIDE)).setValue(RedStoneWireBlock.WEST, RedstoneSide.SIDE); ++ public RedStoneWireBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(RedStoneWireBlock.NORTH, RedstoneSide.NONE)).setValue(RedStoneWireBlock.EAST, RedstoneSide.NONE)).setValue(RedStoneWireBlock.SOUTH, RedstoneSide.NONE)).setValue(RedStoneWireBlock.WEST, RedstoneSide.NONE)).setValue(RedStoneWireBlock.POWER, 0)); ++ this.crossState = (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(RedStoneWireBlock.NORTH, RedstoneSide.SIDE)).setValue(RedStoneWireBlock.EAST, RedstoneSide.SIDE)).setValue(RedStoneWireBlock.SOUTH, RedstoneSide.SIDE)).setValue(RedStoneWireBlock.WEST, RedstoneSide.SIDE); + UnmodifiableIterator unmodifiableiterator = this.getStateDefinition().getPossibleStates().iterator(); + + while (unmodifiableiterator.hasNext()) { +- BlockState blockstate = (BlockState) unmodifiableiterator.next(); ++ IBlockData iblockdata = (IBlockData) unmodifiableiterator.next(); + +- if ((Integer) blockstate.getValue(RedStoneWireBlock.POWER) == 0) { +- RedStoneWireBlock.SHAPES_CACHE.put(blockstate, this.calculateShape(blockstate)); ++ if ((Integer) iblockdata.getValue(RedStoneWireBlock.POWER) == 0) { ++ RedStoneWireBlock.SHAPES_CACHE.put(iblockdata, this.calculateShape(iblockdata)); + } + } + + } + +- private VoxelShape calculateShape(BlockState blockstate) { ++ private VoxelShape calculateShape(IBlockData state) { + VoxelShape voxelshape = RedStoneWireBlock.SHAPE_DOT; + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); +- RedstoneSide redstoneside = (RedstoneSide) blockstate.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(direction)); ++ Direction enumdirection = (Direction) iterator.next(); ++ RedstoneSide blockpropertyredstoneside = (RedstoneSide) state.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(enumdirection)); + +- if (redstoneside == RedstoneSide.SIDE) { +- voxelshape = Shapes.or(voxelshape, (VoxelShape) RedStoneWireBlock.SHAPES_FLOOR.get(direction)); +- } else if (redstoneside == RedstoneSide.UP) { +- voxelshape = Shapes.or(voxelshape, (VoxelShape) RedStoneWireBlock.SHAPES_UP.get(direction)); ++ if (blockpropertyredstoneside == RedstoneSide.SIDE) { ++ voxelshape = Shapes.or(voxelshape, (VoxelShape) RedStoneWireBlock.SHAPES_FLOOR.get(enumdirection)); ++ } else if (blockpropertyredstoneside == RedstoneSide.UP) { ++ voxelshape = Shapes.or(voxelshape, (VoxelShape) RedStoneWireBlock.SHAPES_UP.get(enumdirection)); + } + } + +@@ -111,136 +111,132 @@ + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return (VoxelShape) RedStoneWireBlock.SHAPES_CACHE.get(blockstate.setValue(RedStoneWireBlock.POWER, 0)); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (VoxelShape) RedStoneWireBlock.SHAPES_CACHE.get(state.setValue(RedStoneWireBlock.POWER, 0)); + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- return this.getConnectionState(blockplacecontext.getLevel(), this.crossState, blockplacecontext.getClickedPos()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return this.getConnectionState(context.getLevel(), this.crossState, context.getClickedPos()); + } + +- private BlockState getConnectionState(BlockGetter blockgetter, BlockState blockstate, BlockPos blockpos) { +- boolean flag = isDot(blockstate); ++ private IBlockData getConnectionState(BlockGetter level, IBlockData state, BlockPos pos) { ++ boolean flag = isDot(state); + +- blockstate = this.getMissingConnections(blockgetter, (BlockState) this.defaultBlockState().setValue(RedStoneWireBlock.POWER, (Integer) blockstate.getValue(RedStoneWireBlock.POWER)), blockpos); +- if (flag && isDot(blockstate)) { +- return blockstate; ++ state = this.getMissingConnections(level, (IBlockData) this.defaultBlockState().setValue(RedStoneWireBlock.POWER, (Integer) state.getValue(RedStoneWireBlock.POWER)), pos); ++ if (flag && isDot(state)) { ++ return state; + } else { +- boolean flag1 = ((RedstoneSide) blockstate.getValue(RedStoneWireBlock.NORTH)).isConnected(); +- boolean flag2 = ((RedstoneSide) blockstate.getValue(RedStoneWireBlock.SOUTH)).isConnected(); +- boolean flag3 = ((RedstoneSide) blockstate.getValue(RedStoneWireBlock.EAST)).isConnected(); +- boolean flag4 = ((RedstoneSide) blockstate.getValue(RedStoneWireBlock.WEST)).isConnected(); ++ boolean flag1 = ((RedstoneSide) state.getValue(RedStoneWireBlock.NORTH)).isConnected(); ++ boolean flag2 = ((RedstoneSide) state.getValue(RedStoneWireBlock.SOUTH)).isConnected(); ++ boolean flag3 = ((RedstoneSide) state.getValue(RedStoneWireBlock.EAST)).isConnected(); ++ boolean flag4 = ((RedstoneSide) state.getValue(RedStoneWireBlock.WEST)).isConnected(); + boolean flag5 = !flag1 && !flag2; + boolean flag6 = !flag3 && !flag4; + + if (!flag4 && flag5) { +- blockstate = (BlockState) blockstate.setValue(RedStoneWireBlock.WEST, RedstoneSide.SIDE); ++ state = (IBlockData) state.setValue(RedStoneWireBlock.WEST, RedstoneSide.SIDE); + } + + if (!flag3 && flag5) { +- blockstate = (BlockState) blockstate.setValue(RedStoneWireBlock.EAST, RedstoneSide.SIDE); ++ state = (IBlockData) state.setValue(RedStoneWireBlock.EAST, RedstoneSide.SIDE); + } + + if (!flag1 && flag6) { +- blockstate = (BlockState) blockstate.setValue(RedStoneWireBlock.NORTH, RedstoneSide.SIDE); ++ state = (IBlockData) state.setValue(RedStoneWireBlock.NORTH, RedstoneSide.SIDE); + } + + if (!flag2 && flag6) { +- blockstate = (BlockState) blockstate.setValue(RedStoneWireBlock.SOUTH, RedstoneSide.SIDE); ++ state = (IBlockData) state.setValue(RedStoneWireBlock.SOUTH, RedstoneSide.SIDE); + } + +- return blockstate; ++ return state; + } + } + +- private BlockState getMissingConnections(BlockGetter blockgetter, BlockState blockstate, BlockPos blockpos) { +- boolean flag = !blockgetter.getBlockState(blockpos.above()).isRedstoneConductor(blockgetter, blockpos); ++ private IBlockData getMissingConnections(BlockGetter level, IBlockData state, BlockPos pos) { ++ boolean flag = !level.getBlockState(pos.above()).isRedstoneConductor(level, pos); + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); ++ Direction enumdirection = (Direction) iterator.next(); + +- if (!((RedstoneSide) blockstate.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(direction))).isConnected()) { +- RedstoneSide redstoneside = this.getConnectingSide(blockgetter, blockpos, direction, flag); ++ if (!((RedstoneSide) state.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(enumdirection))).isConnected()) { ++ RedstoneSide blockpropertyredstoneside = this.getConnectingSide(level, pos, enumdirection, flag); + +- blockstate = (BlockState) blockstate.setValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(direction), redstoneside); ++ state = (IBlockData) state.setValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(enumdirection), blockpropertyredstoneside); + } + } + +- return blockstate; ++ return state; + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if (direction == Direction.DOWN) { +- return !this.canSurviveOn(levelaccessor, blockpos1, blockstate1) ? Blocks.AIR.defaultBlockState() : blockstate; +- } else if (direction == Direction.UP) { +- return this.getConnectionState(levelaccessor, blockstate, blockpos); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if (facing == Direction.DOWN) { ++ return !this.canSurviveOn(level, facingPos, facingState) ? Blocks.AIR.defaultBlockState() : state; ++ } else if (facing == Direction.UP) { ++ return this.getConnectionState(level, state, currentPos); + } else { +- RedstoneSide redstoneside = this.getConnectingSide(levelaccessor, blockpos, direction); ++ RedstoneSide blockpropertyredstoneside = this.getConnectingSide(level, currentPos, facing); + +- return redstoneside.isConnected() == ((RedstoneSide) blockstate.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(direction))).isConnected() && !isCross(blockstate) ? (BlockState) blockstate.setValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(direction), redstoneside) : this.getConnectionState(levelaccessor, (BlockState) ((BlockState) this.crossState.setValue(RedStoneWireBlock.POWER, (Integer) blockstate.getValue(RedStoneWireBlock.POWER))).setValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(direction), redstoneside), blockpos); ++ return blockpropertyredstoneside.isConnected() == ((RedstoneSide) state.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(facing))).isConnected() && !isCross(state) ? (IBlockData) state.setValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(facing), blockpropertyredstoneside) : this.getConnectionState(level, (IBlockData) ((IBlockData) this.crossState.setValue(RedStoneWireBlock.POWER, (Integer) state.getValue(RedStoneWireBlock.POWER))).setValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(facing), blockpropertyredstoneside), currentPos); + } + } + +- private static boolean isCross(BlockState blockstate) { +- return ((RedstoneSide) blockstate.getValue(RedStoneWireBlock.NORTH)).isConnected() && ((RedstoneSide) blockstate.getValue(RedStoneWireBlock.SOUTH)).isConnected() && ((RedstoneSide) blockstate.getValue(RedStoneWireBlock.EAST)).isConnected() && ((RedstoneSide) blockstate.getValue(RedStoneWireBlock.WEST)).isConnected(); ++ private static boolean isCross(IBlockData state) { ++ return ((RedstoneSide) state.getValue(RedStoneWireBlock.NORTH)).isConnected() && ((RedstoneSide) state.getValue(RedStoneWireBlock.SOUTH)).isConnected() && ((RedstoneSide) state.getValue(RedStoneWireBlock.EAST)).isConnected() && ((RedstoneSide) state.getValue(RedStoneWireBlock.WEST)).isConnected(); + } + +- private static boolean isDot(BlockState blockstate) { +- return !((RedstoneSide) blockstate.getValue(RedStoneWireBlock.NORTH)).isConnected() && !((RedstoneSide) blockstate.getValue(RedStoneWireBlock.SOUTH)).isConnected() && !((RedstoneSide) blockstate.getValue(RedStoneWireBlock.EAST)).isConnected() && !((RedstoneSide) blockstate.getValue(RedStoneWireBlock.WEST)).isConnected(); ++ private static boolean isDot(IBlockData state) { ++ return !((RedstoneSide) state.getValue(RedStoneWireBlock.NORTH)).isConnected() && !((RedstoneSide) state.getValue(RedStoneWireBlock.SOUTH)).isConnected() && !((RedstoneSide) state.getValue(RedStoneWireBlock.EAST)).isConnected() && !((RedstoneSide) state.getValue(RedStoneWireBlock.WEST)).isConnected(); + } + + @Override +- @Override +- public void updateIndirectNeighbourShapes(BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos, int i, int j) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ public void updateIndirectNeighbourShapes(IBlockData state, LevelAccessor level, BlockPos pos, int flags, int recursionLeft) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); +- RedstoneSide redstoneside = (RedstoneSide) blockstate.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(direction)); ++ Direction enumdirection = (Direction) iterator.next(); ++ RedstoneSide blockpropertyredstoneside = (RedstoneSide) state.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(enumdirection)); + +- if (redstoneside != RedstoneSide.NONE && !levelaccessor.getBlockState(blockpos_mutableblockpos.setWithOffset(blockpos, direction)).is((Block) this)) { +- blockpos_mutableblockpos.move(Direction.DOWN); +- BlockState blockstate1 = levelaccessor.getBlockState(blockpos_mutableblockpos); ++ if (blockpropertyredstoneside != RedstoneSide.NONE && !level.getBlockState(blockposition_mutableblockposition.setWithOffset(pos, enumdirection)).is((Block) this)) { ++ blockposition_mutableblockposition.move(Direction.DOWN); ++ IBlockData iblockdata1 = level.getBlockState(blockposition_mutableblockposition); + +- if (blockstate1.is((Block) this)) { +- BlockPos blockpos1 = blockpos_mutableblockpos.relative(direction.getOpposite()); ++ if (iblockdata1.is((Block) this)) { ++ BlockPos blockposition1 = blockposition_mutableblockposition.relative(enumdirection.getOpposite()); + +- levelaccessor.neighborShapeChanged(direction.getOpposite(), levelaccessor.getBlockState(blockpos1), blockpos_mutableblockpos, blockpos1, i, j); ++ level.neighborShapeChanged(enumdirection.getOpposite(), level.getBlockState(blockposition1), blockposition_mutableblockposition, blockposition1, flags, recursionLeft); + } + +- blockpos_mutableblockpos.setWithOffset(blockpos, direction).move(Direction.UP); +- BlockState blockstate2 = levelaccessor.getBlockState(blockpos_mutableblockpos); ++ blockposition_mutableblockposition.setWithOffset(pos, enumdirection).move(Direction.UP); ++ IBlockData iblockdata2 = level.getBlockState(blockposition_mutableblockposition); + +- if (blockstate2.is((Block) this)) { +- BlockPos blockpos2 = blockpos_mutableblockpos.relative(direction.getOpposite()); ++ if (iblockdata2.is((Block) this)) { ++ BlockPos blockposition2 = blockposition_mutableblockposition.relative(enumdirection.getOpposite()); + +- levelaccessor.neighborShapeChanged(direction.getOpposite(), levelaccessor.getBlockState(blockpos2), blockpos_mutableblockpos, blockpos2, i, j); ++ level.neighborShapeChanged(enumdirection.getOpposite(), level.getBlockState(blockposition2), blockposition_mutableblockposition, blockposition2, flags, recursionLeft); + } + } + } + + } + +- private RedstoneSide getConnectingSide(BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return this.getConnectingSide(blockgetter, blockpos, direction, !blockgetter.getBlockState(blockpos.above()).isRedstoneConductor(blockgetter, blockpos)); ++ private RedstoneSide getConnectingSide(BlockGetter level, BlockPos pos, Direction face) { ++ return this.getConnectingSide(level, pos, face, !level.getBlockState(pos.above()).isRedstoneConductor(level, pos)); + } + +- private RedstoneSide getConnectingSide(BlockGetter blockgetter, BlockPos blockpos, Direction direction, boolean flag) { +- BlockPos blockpos1 = blockpos.relative(direction); +- BlockState blockstate = blockgetter.getBlockState(blockpos1); ++ private RedstoneSide getConnectingSide(BlockGetter level, BlockPos pos, Direction direction, boolean nonNormalCubeAbove) { ++ BlockPos blockposition1 = pos.relative(direction); ++ IBlockData iblockdata = level.getBlockState(blockposition1); + +- if (flag) { +- boolean flag1 = blockstate.getBlock() instanceof TrapDoorBlock || this.canSurviveOn(blockgetter, blockpos1, blockstate); ++ if (nonNormalCubeAbove) { ++ boolean flag1 = iblockdata.getBlock() instanceof TrapDoorBlock || this.canSurviveOn(level, blockposition1, iblockdata); + +- if (flag1 && shouldConnectTo(blockgetter.getBlockState(blockpos1.above()))) { +- if (blockstate.isFaceSturdy(blockgetter, blockpos1, direction.getOpposite())) { ++ if (flag1 && shouldConnectTo(level.getBlockState(blockposition1.above()))) { ++ if (iblockdata.isFaceSturdy(level, blockposition1, direction.getOpposite())) { + return RedstoneSide.UP; + } + +@@ -248,56 +244,64 @@ + } + } + +- return !shouldConnectTo(blockstate, direction) && (blockstate.isRedstoneConductor(blockgetter, blockpos1) || !shouldConnectTo(blockgetter.getBlockState(blockpos1.below()))) ? RedstoneSide.NONE : RedstoneSide.SIDE; ++ return !shouldConnectTo(iblockdata, direction) && (iblockdata.isRedstoneConductor(level, blockposition1) || !shouldConnectTo(level.getBlockState(blockposition1.below()))) ? RedstoneSide.NONE : RedstoneSide.SIDE; + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- BlockPos blockpos1 = blockpos.below(); +- BlockState blockstate1 = levelreader.getBlockState(blockpos1); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + +- return this.canSurviveOn(levelreader, blockpos1, blockstate1); ++ return this.canSurviveOn(level, blockposition1, iblockdata1); + } + +- private boolean canSurviveOn(BlockGetter blockgetter, BlockPos blockpos, BlockState blockstate) { +- return blockstate.isFaceSturdy(blockgetter, blockpos, Direction.UP) || blockstate.is(Blocks.HOPPER); ++ private boolean canSurviveOn(BlockGetter level, BlockPos pos, IBlockData state) { ++ return state.isFaceSturdy(level, pos, Direction.UP) || state.is(Blocks.HOPPER); + } + +- private void updatePowerStrength(Level level, BlockPos blockpos, BlockState blockstate) { +- int i = this.calculateTargetStrength(level, blockpos); ++ private void updatePowerStrength(Level level, BlockPos pos, IBlockData state) { ++ int i = this.calculateTargetStrength(level, pos); + +- if ((Integer) blockstate.getValue(RedStoneWireBlock.POWER) != i) { +- if (level.getBlockState(blockpos) == blockstate) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(RedStoneWireBlock.POWER, i), 2); ++ // CraftBukkit start ++ int oldPower = (Integer) state.getValue(RedStoneWireBlock.POWER); ++ if (oldPower != i) { ++ BlockRedstoneEvent event = new BlockRedstoneEvent(level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()), oldPower, i); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ i = event.getNewCurrent(); ++ } ++ if (oldPower != i) { ++ // CraftBukkit end ++ if (level.getBlockState(pos) == state) { ++ level.setBlock(pos, (IBlockData) state.setValue(RedStoneWireBlock.POWER, i), 2); + } + + Set set = Sets.newHashSet(); + +- set.add(blockpos); +- Direction[] adirection = Direction.values(); +- int j = adirection.length; ++ set.add(pos); ++ Direction[] aenumdirection = Direction.values(); ++ int j = aenumdirection.length; + + for (int k = 0; k < j; ++k) { +- Direction direction = adirection[k]; ++ Direction enumdirection = aenumdirection[k]; + +- set.add(blockpos.relative(direction)); ++ set.add(pos.relative(enumdirection)); + } + + Iterator iterator = set.iterator(); + + while (iterator.hasNext()) { +- BlockPos blockpos1 = (BlockPos) iterator.next(); ++ BlockPos blockposition1 = (BlockPos) iterator.next(); + +- level.updateNeighborsAt(blockpos1, this); ++ level.updateNeighborsAt(blockposition1, this); + } + } + + } + +- private int calculateTargetStrength(Level level, BlockPos blockpos) { ++ private int calculateTargetStrength(Level level, BlockPos pos) { + this.shouldSignal = false; +- int i = level.getBestNeighborSignal(blockpos); ++ int i = level.getBestNeighborSignal(pos); + + this.shouldSignal = true; + int j = 0; +@@ -306,17 +310,17 @@ + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); +- BlockPos blockpos1 = blockpos.relative(direction); +- BlockState blockstate = level.getBlockState(blockpos1); ++ Direction enumdirection = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ IBlockData iblockdata = level.getBlockState(blockposition1); + +- j = Math.max(j, this.getWireSignal(blockstate)); +- BlockPos blockpos2 = blockpos.above(); ++ j = Math.max(j, this.getWireSignal(iblockdata)); ++ BlockPos blockposition2 = pos.above(); + +- if (blockstate.isRedstoneConductor(level, blockpos1) && !level.getBlockState(blockpos2).isRedstoneConductor(level, blockpos2)) { +- j = Math.max(j, this.getWireSignal(level.getBlockState(blockpos1.above()))); +- } else if (!blockstate.isRedstoneConductor(level, blockpos1)) { +- j = Math.max(j, this.getWireSignal(level.getBlockState(blockpos1.below()))); ++ if (iblockdata.isRedstoneConductor(level, blockposition1) && !level.getBlockState(blockposition2).isRedstoneConductor(level, blockposition2)) { ++ j = Math.max(j, this.getWireSignal(level.getBlockState(blockposition1.above()))); ++ } else if (!iblockdata.isRedstoneConductor(level, blockposition1)) { ++ j = Math.max(j, this.getWireSignal(level.getBlockState(blockposition1.below()))); + } + } + } +@@ -324,183 +328,176 @@ + return Math.max(i, j - 1); + } + +- private int getWireSignal(BlockState blockstate) { +- return blockstate.is((Block) this) ? (Integer) blockstate.getValue(RedStoneWireBlock.POWER) : 0; ++ private int getWireSignal(IBlockData state) { ++ return state.is((Block) this) ? (Integer) state.getValue(RedStoneWireBlock.POWER) : 0; + } + +- private void checkCornerChangeAt(Level level, BlockPos blockpos) { +- if (level.getBlockState(blockpos).is((Block) this)) { +- level.updateNeighborsAt(blockpos, this); +- Direction[] adirection = Direction.values(); +- int i = adirection.length; ++ private void checkCornerChangeAt(Level level, BlockPos pos) { ++ if (level.getBlockState(pos).is((Block) this)) { ++ level.updateNeighborsAt(pos, this); ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; ++ Direction enumdirection = aenumdirection[j]; + +- level.updateNeighborsAt(blockpos.relative(direction), this); ++ level.updateNeighborsAt(pos.relative(enumdirection), this); + } + + } + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!blockstate1.is(blockstate.getBlock()) && !level.isClientSide) { +- this.updatePowerStrength(level, blockpos, blockstate); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ if (!oldState.is(state.getBlock()) && !level.isClientSide) { ++ this.updatePowerStrength(level, pos, state); + Iterator iterator = Direction.Plane.VERTICAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); ++ Direction enumdirection = (Direction) iterator.next(); + +- level.updateNeighborsAt(blockpos.relative(direction), this); ++ level.updateNeighborsAt(pos.relative(enumdirection), this); + } + +- this.updateNeighborsOfNeighboringWires(level, blockpos); ++ this.updateNeighborsOfNeighboringWires(level, pos); + } + } + + @Override +- @Override +- public void onRemove(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!flag && !blockstate.is(blockstate1.getBlock())) { +- super.onRemove(blockstate, level, blockpos, blockstate1, flag); ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { ++ if (!isMoving && !state.is(newState.getBlock())) { ++ super.onRemove(state, level, pos, newState, isMoving); + if (!level.isClientSide) { +- Direction[] adirection = Direction.values(); +- int i = adirection.length; ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; ++ Direction enumdirection = aenumdirection[j]; + +- level.updateNeighborsAt(blockpos.relative(direction), this); ++ level.updateNeighborsAt(pos.relative(enumdirection), this); + } + +- this.updatePowerStrength(level, blockpos, blockstate); +- this.updateNeighborsOfNeighboringWires(level, blockpos); ++ this.updatePowerStrength(level, pos, state); ++ this.updateNeighborsOfNeighboringWires(level, pos); + } + } + } + +- private void updateNeighborsOfNeighboringWires(Level level, BlockPos blockpos) { ++ private void updateNeighborsOfNeighboringWires(Level level, BlockPos pos) { + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- Direction direction; ++ Direction enumdirection; + + while (iterator.hasNext()) { +- direction = (Direction) iterator.next(); +- this.checkCornerChangeAt(level, blockpos.relative(direction)); ++ enumdirection = (Direction) iterator.next(); ++ this.checkCornerChangeAt(level, pos.relative(enumdirection)); + } + + iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- direction = (Direction) iterator.next(); +- BlockPos blockpos1 = blockpos.relative(direction); ++ enumdirection = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection); + +- if (level.getBlockState(blockpos1).isRedstoneConductor(level, blockpos1)) { +- this.checkCornerChangeAt(level, blockpos1.above()); ++ if (level.getBlockState(blockposition1).isRedstoneConductor(level, blockposition1)) { ++ this.checkCornerChangeAt(level, blockposition1.above()); + } else { +- this.checkCornerChangeAt(level, blockpos1.below()); ++ this.checkCornerChangeAt(level, blockposition1.below()); + } + } + + } + + @Override +- @Override +- public void neighborChanged(BlockState blockstate, Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { + if (!level.isClientSide) { +- if (blockstate.canSurvive(level, blockpos)) { +- this.updatePowerStrength(level, blockpos, blockstate); ++ if (state.canSurvive(level, pos)) { ++ this.updatePowerStrength(level, pos, state); + } else { +- dropResources(blockstate, level, blockpos); +- level.removeBlock(blockpos, false); ++ dropResources(state, level, pos); ++ level.removeBlock(pos, false); + } + + } + } + + @Override +- @Override +- public int getDirectSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return !this.shouldSignal ? 0 : blockstate.getSignal(blockgetter, blockpos, direction); ++ public int getDirectSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return !this.shouldSignal ? 0 : blockState.getSignal(blockAccess, pos, side); + } + + @Override +- @Override +- public int getSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- if (this.shouldSignal && direction != Direction.DOWN) { +- int i = (Integer) blockstate.getValue(RedStoneWireBlock.POWER); ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ if (this.shouldSignal && side != Direction.DOWN) { ++ int i = (Integer) blockState.getValue(RedStoneWireBlock.POWER); + +- return i == 0 ? 0 : (direction != Direction.UP && !((RedstoneSide) this.getConnectionState(blockgetter, blockstate, blockpos).getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(direction.getOpposite()))).isConnected() ? 0 : i); ++ return i == 0 ? 0 : (side != Direction.UP && !((RedstoneSide) this.getConnectionState(blockAccess, blockState, pos).getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(side.getOpposite()))).isConnected() ? 0 : i); + } else { + return 0; + } + } + +- protected static boolean shouldConnectTo(BlockState blockstate) { +- return shouldConnectTo(blockstate, (Direction) null); ++ protected static boolean shouldConnectTo(IBlockData state) { ++ return shouldConnectTo(state, (Direction) null); + } + +- protected static boolean shouldConnectTo(BlockState blockstate, @Nullable Direction direction) { +- if (blockstate.is(Blocks.REDSTONE_WIRE)) { ++ protected static boolean shouldConnectTo(IBlockData state, @Nullable Direction direction) { ++ if (state.is(Blocks.REDSTONE_WIRE)) { + return true; +- } else if (blockstate.is(Blocks.REPEATER)) { +- Direction direction1 = (Direction) blockstate.getValue(RepeaterBlock.FACING); ++ } else if (state.is(Blocks.REPEATER)) { ++ Direction enumdirection1 = (Direction) state.getValue(RepeaterBlock.FACING); + +- return direction1 == direction || direction1.getOpposite() == direction; ++ return enumdirection1 == direction || enumdirection1.getOpposite() == direction; + } else { +- return blockstate.is(Blocks.OBSERVER) ? direction == blockstate.getValue(ObserverBlock.FACING) : blockstate.isSignalSource() && direction != null; ++ return state.is(Blocks.OBSERVER) ? direction == state.getValue(ObserverBlock.FACING) : state.isSignalSource() && direction != null; + } + } + + @Override +- @Override +- public boolean isSignalSource(BlockState blockstate) { ++ public boolean isSignalSource(IBlockData state) { + return this.shouldSignal; + } + +- public static int getColorForPower(int i) { +- Vec3 vec3 = RedStoneWireBlock.COLORS[i]; ++ public static int getColorForPower(int power) { ++ Vec3 vec3d = RedStoneWireBlock.COLORS[power]; + +- return Mth.color((float) vec3.x(), (float) vec3.y(), (float) vec3.z()); ++ return Mth.color((float) vec3d.x(), (float) vec3d.y(), (float) vec3d.z()); + } + +- private void spawnParticlesAlongLine(Level level, RandomSource randomsource, BlockPos blockpos, Vec3 vec3, Direction direction, Direction direction1, float f, float f1) { +- float f2 = f1 - f; ++ private void spawnParticlesAlongLine(Level level, RandomSource random, BlockPos pos, Vec3 particleVec, Direction xDirection, Direction zDirection, float min, float max) { ++ float f2 = max - min; + +- if (randomsource.nextFloat() < 0.2F * f2) { ++ if (random.nextFloat() < 0.2F * f2) { + float f3 = 0.4375F; +- float f4 = f + f2 * randomsource.nextFloat(); +- double d0 = 0.5D + (double) (0.4375F * (float) direction.getStepX()) + (double) (f4 * (float) direction1.getStepX()); +- double d1 = 0.5D + (double) (0.4375F * (float) direction.getStepY()) + (double) (f4 * (float) direction1.getStepY()); +- double d2 = 0.5D + (double) (0.4375F * (float) direction.getStepZ()) + (double) (f4 * (float) direction1.getStepZ()); ++ float f4 = min + f2 * random.nextFloat(); ++ double d0 = 0.5D + (double) (0.4375F * (float) xDirection.getStepX()) + (double) (f4 * (float) zDirection.getStepX()); ++ double d1 = 0.5D + (double) (0.4375F * (float) xDirection.getStepY()) + (double) (f4 * (float) zDirection.getStepY()); ++ double d2 = 0.5D + (double) (0.4375F * (float) xDirection.getStepZ()) + (double) (f4 * (float) zDirection.getStepZ()); + +- level.addParticle(new DustParticleOptions(vec3.toVector3f(), 1.0F), (double) blockpos.getX() + d0, (double) blockpos.getY() + d1, (double) blockpos.getZ() + d2, 0.0D, 0.0D, 0.0D); ++ level.addParticle(new ParticleParamRedstone(particleVec.toVector3f(), 1.0F), (double) pos.getX() + d0, (double) pos.getY() + d1, (double) pos.getZ() + d2, 0.0D, 0.0D, 0.0D); + } + } + + @Override +- @Override +- public void animateTick(BlockState blockstate, Level level, BlockPos blockpos, RandomSource randomsource) { +- int i = (Integer) blockstate.getValue(RedStoneWireBlock.POWER); ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ int i = (Integer) state.getValue(RedStoneWireBlock.POWER); + + if (i != 0) { + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); +- RedstoneSide redstoneside = (RedstoneSide) blockstate.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(direction)); ++ Direction enumdirection = (Direction) iterator.next(); ++ RedstoneSide blockpropertyredstoneside = (RedstoneSide) state.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(enumdirection)); + +- switch (redstoneside) { ++ switch (blockpropertyredstoneside) { + case UP: +- this.spawnParticlesAlongLine(level, randomsource, blockpos, RedStoneWireBlock.COLORS[i], direction, Direction.UP, -0.5F, 0.5F); ++ this.spawnParticlesAlongLine(level, random, pos, RedStoneWireBlock.COLORS[i], enumdirection, Direction.UP, -0.5F, 0.5F); + case SIDE: +- this.spawnParticlesAlongLine(level, randomsource, blockpos, RedStoneWireBlock.COLORS[i], Direction.DOWN, direction, 0.0F, 0.5F); ++ this.spawnParticlesAlongLine(level, random, pos, RedStoneWireBlock.COLORS[i], Direction.DOWN, enumdirection, 0.0F, 0.5F); + break; + case NONE: + default: +- this.spawnParticlesAlongLine(level, randomsource, blockpos, RedStoneWireBlock.COLORS[i], Direction.DOWN, direction, 0.0F, 0.3F); ++ this.spawnParticlesAlongLine(level, random, pos, RedStoneWireBlock.COLORS[i], Direction.DOWN, enumdirection, 0.0F, 0.3F); + } + } + +@@ -508,53 +505,49 @@ + } + + @Override +- @Override +- public BlockState rotate(BlockState blockstate, Rotation rotation) { ++ public IBlockData rotate(IBlockData state, Rotation rotation) { + switch (rotation) { + case CLOCKWISE_180: +- return (BlockState) ((BlockState) ((BlockState) ((BlockState) blockstate.setValue(RedStoneWireBlock.NORTH, (RedstoneSide) blockstate.getValue(RedStoneWireBlock.SOUTH))).setValue(RedStoneWireBlock.EAST, (RedstoneSide) blockstate.getValue(RedStoneWireBlock.WEST))).setValue(RedStoneWireBlock.SOUTH, (RedstoneSide) blockstate.getValue(RedStoneWireBlock.NORTH))).setValue(RedStoneWireBlock.WEST, (RedstoneSide) blockstate.getValue(RedStoneWireBlock.EAST)); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) state.setValue(RedStoneWireBlock.NORTH, (RedstoneSide) state.getValue(RedStoneWireBlock.SOUTH))).setValue(RedStoneWireBlock.EAST, (RedstoneSide) state.getValue(RedStoneWireBlock.WEST))).setValue(RedStoneWireBlock.SOUTH, (RedstoneSide) state.getValue(RedStoneWireBlock.NORTH))).setValue(RedStoneWireBlock.WEST, (RedstoneSide) state.getValue(RedStoneWireBlock.EAST)); + case COUNTERCLOCKWISE_90: +- return (BlockState) ((BlockState) ((BlockState) ((BlockState) blockstate.setValue(RedStoneWireBlock.NORTH, (RedstoneSide) blockstate.getValue(RedStoneWireBlock.EAST))).setValue(RedStoneWireBlock.EAST, (RedstoneSide) blockstate.getValue(RedStoneWireBlock.SOUTH))).setValue(RedStoneWireBlock.SOUTH, (RedstoneSide) blockstate.getValue(RedStoneWireBlock.WEST))).setValue(RedStoneWireBlock.WEST, (RedstoneSide) blockstate.getValue(RedStoneWireBlock.NORTH)); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) state.setValue(RedStoneWireBlock.NORTH, (RedstoneSide) state.getValue(RedStoneWireBlock.EAST))).setValue(RedStoneWireBlock.EAST, (RedstoneSide) state.getValue(RedStoneWireBlock.SOUTH))).setValue(RedStoneWireBlock.SOUTH, (RedstoneSide) state.getValue(RedStoneWireBlock.WEST))).setValue(RedStoneWireBlock.WEST, (RedstoneSide) state.getValue(RedStoneWireBlock.NORTH)); + case CLOCKWISE_90: +- return (BlockState) ((BlockState) ((BlockState) ((BlockState) blockstate.setValue(RedStoneWireBlock.NORTH, (RedstoneSide) blockstate.getValue(RedStoneWireBlock.WEST))).setValue(RedStoneWireBlock.EAST, (RedstoneSide) blockstate.getValue(RedStoneWireBlock.NORTH))).setValue(RedStoneWireBlock.SOUTH, (RedstoneSide) blockstate.getValue(RedStoneWireBlock.EAST))).setValue(RedStoneWireBlock.WEST, (RedstoneSide) blockstate.getValue(RedStoneWireBlock.SOUTH)); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) state.setValue(RedStoneWireBlock.NORTH, (RedstoneSide) state.getValue(RedStoneWireBlock.WEST))).setValue(RedStoneWireBlock.EAST, (RedstoneSide) state.getValue(RedStoneWireBlock.NORTH))).setValue(RedStoneWireBlock.SOUTH, (RedstoneSide) state.getValue(RedStoneWireBlock.EAST))).setValue(RedStoneWireBlock.WEST, (RedstoneSide) state.getValue(RedStoneWireBlock.SOUTH)); + default: +- return blockstate; ++ return state; + } + } + + @Override +- @Override +- public BlockState mirror(BlockState blockstate, Mirror mirror) { ++ public IBlockData mirror(IBlockData state, Mirror mirror) { + switch (mirror) { + case LEFT_RIGHT: +- return (BlockState) ((BlockState) blockstate.setValue(RedStoneWireBlock.NORTH, (RedstoneSide) blockstate.getValue(RedStoneWireBlock.SOUTH))).setValue(RedStoneWireBlock.SOUTH, (RedstoneSide) blockstate.getValue(RedStoneWireBlock.NORTH)); ++ return (IBlockData) ((IBlockData) state.setValue(RedStoneWireBlock.NORTH, (RedstoneSide) state.getValue(RedStoneWireBlock.SOUTH))).setValue(RedStoneWireBlock.SOUTH, (RedstoneSide) state.getValue(RedStoneWireBlock.NORTH)); + case FRONT_BACK: +- return (BlockState) ((BlockState) blockstate.setValue(RedStoneWireBlock.EAST, (RedstoneSide) blockstate.getValue(RedStoneWireBlock.WEST))).setValue(RedStoneWireBlock.WEST, (RedstoneSide) blockstate.getValue(RedStoneWireBlock.EAST)); ++ return (IBlockData) ((IBlockData) state.setValue(RedStoneWireBlock.EAST, (RedstoneSide) state.getValue(RedStoneWireBlock.WEST))).setValue(RedStoneWireBlock.WEST, (RedstoneSide) state.getValue(RedStoneWireBlock.EAST)); + default: +- return super.mirror(blockstate, mirror); ++ return super.mirror(state, mirror); + } + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(RedStoneWireBlock.NORTH, RedStoneWireBlock.EAST, RedStoneWireBlock.SOUTH, RedStoneWireBlock.WEST, RedStoneWireBlock.POWER); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(RedStoneWireBlock.NORTH, RedStoneWireBlock.EAST, RedStoneWireBlock.SOUTH, RedStoneWireBlock.WEST, RedStoneWireBlock.POWER); + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + if (!player.getAbilities().mayBuild) { + return InteractionResult.PASS; + } else { +- if (isCross(blockstate) || isDot(blockstate)) { +- BlockState blockstate1 = isCross(blockstate) ? this.defaultBlockState() : this.crossState; ++ if (isCross(state) || isDot(state)) { ++ IBlockData iblockdata1 = isCross(state) ? this.defaultBlockState() : this.crossState; + +- blockstate1 = (BlockState) blockstate1.setValue(RedStoneWireBlock.POWER, (Integer) blockstate.getValue(RedStoneWireBlock.POWER)); +- blockstate1 = this.getConnectionState(level, blockstate1, blockpos); +- if (blockstate1 != blockstate) { +- level.setBlock(blockpos, blockstate1, 3); +- this.updatesOnShapeChange(level, blockpos, blockstate, blockstate1); ++ iblockdata1 = (IBlockData) iblockdata1.setValue(RedStoneWireBlock.POWER, (Integer) state.getValue(RedStoneWireBlock.POWER)); ++ iblockdata1 = this.getConnectionState(level, iblockdata1, pos); ++ if (iblockdata1 != state) { ++ level.setBlock(pos, iblockdata1, 3); ++ this.updatesOnShapeChange(level, pos, state, iblockdata1); + return InteractionResult.SUCCESS; + } + } +@@ -563,15 +556,15 @@ + } + } + +- private void updatesOnShapeChange(Level level, BlockPos blockpos, BlockState blockstate, BlockState blockstate1) { ++ private void updatesOnShapeChange(Level level, BlockPos pos, IBlockData oldState, IBlockData newState) { + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); +- BlockPos blockpos1 = blockpos.relative(direction); ++ Direction enumdirection = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection); + +- if (((RedstoneSide) blockstate.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(direction))).isConnected() != ((RedstoneSide) blockstate1.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(direction))).isConnected() && level.getBlockState(blockpos1).isRedstoneConductor(level, blockpos1)) { +- level.updateNeighborsAtExceptFromFacing(blockpos1, blockstate1.getBlock(), direction.getOpposite()); ++ if (((RedstoneSide) oldState.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(enumdirection))).isConnected() != ((RedstoneSide) newState.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(enumdirection))).isConnected() && level.getBlockState(blockposition1).isRedstoneConductor(level, blockposition1)) { ++ level.updateNeighborsAtExceptFromFacing(blockposition1, newState.getBlock(), enumdirection.getOpposite()); + } + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/RedstoneLampBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/RedstoneLampBlock.java.patch new file mode 100644 index 0000000000..16becdc751 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/RedstoneLampBlock.java.patch @@ -0,0 +1,92 @@ +--- a/net/minecraft/world/level/block/RedstoneLampBlock.java ++++ b/net/minecraft/world/level/block/RedstoneLampBlock.java +@@ -8,9 +8,10 @@ + import net.minecraft.world.item.context.BlockPlaceContext; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BooleanProperty; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class RedstoneLampBlock extends Block { + +@@ -18,34 +19,36 @@ + public static final BooleanProperty LIT = RedstoneTorchBlock.LIT; + + @Override +- @Override + public MapCodec codec() { + return RedstoneLampBlock.CODEC; + } + +- public RedstoneLampBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) this.defaultBlockState().setValue(RedstoneLampBlock.LIT, false)); ++ public RedstoneLampBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) this.defaultBlockState().setValue(RedstoneLampBlock.LIT, false)); + } + + @Nullable + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- return (BlockState) this.defaultBlockState().setValue(RedstoneLampBlock.LIT, blockplacecontext.getLevel().hasNeighborSignal(blockplacecontext.getClickedPos())); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return (IBlockData) this.defaultBlockState().setValue(RedstoneLampBlock.LIT, context.getLevel().hasNeighborSignal(context.getClickedPos())); + } + + @Override +- @Override +- public void neighborChanged(BlockState blockstate, Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { + if (!level.isClientSide) { +- boolean flag1 = (Boolean) blockstate.getValue(RedstoneLampBlock.LIT); ++ boolean flag1 = (Boolean) state.getValue(RedstoneLampBlock.LIT); + +- if (flag1 != level.hasNeighborSignal(blockpos)) { ++ if (flag1 != level.hasNeighborSignal(pos)) { + if (flag1) { +- level.scheduleTick(blockpos, (Block) this, 4); ++ level.scheduleTick(pos, (Block) this, 4); + } else { +- level.setBlock(blockpos, (BlockState) blockstate.cycle(RedstoneLampBlock.LIT), 2); ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 0, 15).getNewCurrent() != 15) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.cycle(RedstoneLampBlock.LIT), 2); + } + } + +@@ -53,17 +56,20 @@ + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if ((Boolean) blockstate.getValue(RedstoneLampBlock.LIT) && !serverlevel.hasNeighborSignal(blockpos)) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.cycle(RedstoneLampBlock.LIT), 2); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(RedstoneLampBlock.LIT) && !level.hasNeighborSignal(pos)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 15, 0).getNewCurrent() != 0) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.cycle(RedstoneLampBlock.LIT), 2); + } + + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(RedstoneLampBlock.LIT); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(RedstoneLampBlock.LIT); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/RedstoneTorchBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/RedstoneTorchBlock.java.patch new file mode 100644 index 0000000000..9c07a20f1a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/RedstoneTorchBlock.java.patch @@ -0,0 +1,245 @@ +--- a/net/minecraft/world/level/block/RedstoneTorchBlock.java ++++ b/net/minecraft/world/level/block/RedstoneTorchBlock.java +@@ -8,16 +8,17 @@ + import java.util.WeakHashMap; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.particles.DustParticleOptions; ++import net.minecraft.core.particles.ParticleParamRedstone; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.RandomSource; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class RedstoneTorchBlock extends BaseTorchBlock { + +@@ -30,135 +31,150 @@ + private static final int TOGGLE_DELAY = 2; + + @Override +- @Override + public MapCodec codec() { + return RedstoneTorchBlock.CODEC; + } + +- protected RedstoneTorchBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(RedstoneTorchBlock.LIT, true)); ++ protected RedstoneTorchBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(RedstoneTorchBlock.LIT, true)); + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- Direction[] adirection = Direction.values(); +- int i = adirection.length; ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; ++ Direction enumdirection = aenumdirection[j]; + +- level.updateNeighborsAt(blockpos.relative(direction), this); ++ level.updateNeighborsAt(pos.relative(enumdirection), this); + } + + } + + @Override +- @Override +- public void onRemove(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!flag) { +- Direction[] adirection = Direction.values(); +- int i = adirection.length; ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { ++ if (!isMoving) { ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; ++ Direction enumdirection = aenumdirection[j]; + +- level.updateNeighborsAt(blockpos.relative(direction), this); ++ level.updateNeighborsAt(pos.relative(enumdirection), this); + } + + } + } + + @Override +- @Override +- public int getSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return (Boolean) blockstate.getValue(RedstoneTorchBlock.LIT) && Direction.UP != direction ? 15 : 0; ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return (Boolean) blockState.getValue(RedstoneTorchBlock.LIT) && Direction.UP != side ? 15 : 0; + } + +- protected boolean hasNeighborSignal(Level level, BlockPos blockpos, BlockState blockstate) { +- return level.hasSignal(blockpos.below(), Direction.DOWN); ++ protected boolean hasNeighborSignal(Level level, BlockPos pos, IBlockData state) { ++ return level.hasSignal(pos.below(), Direction.DOWN); + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- boolean flag = this.hasNeighborSignal(serverlevel, blockpos, blockstate); +- List list = (List) RedstoneTorchBlock.RECENT_TOGGLES.get(serverlevel); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ boolean flag = this.hasNeighborSignal(level, pos, state); ++ List list = (List) RedstoneTorchBlock.RECENT_TOGGLES.get(level); + +- while (list != null && !list.isEmpty() && serverlevel.getGameTime() - ((RedstoneTorchBlock.Toggle) list.get(0)).when > 60L) { ++ while (list != null && !list.isEmpty() && level.getGameTime() - ((RedstoneTorchBlock.Toggle) list.get(0)).when > 60L) { + list.remove(0); + } + +- if ((Boolean) blockstate.getValue(RedstoneTorchBlock.LIT)) { ++ // CraftBukkit start ++ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager(); ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ int oldCurrent = ((Boolean) state.getValue(RedstoneTorchBlock.LIT)).booleanValue() ? 15 : 0; ++ ++ BlockRedstoneEvent event = new BlockRedstoneEvent(block, oldCurrent, oldCurrent); ++ // CraftBukkit end ++ if ((Boolean) state.getValue(RedstoneTorchBlock.LIT)) { + if (flag) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(RedstoneTorchBlock.LIT, false), 3); +- if (isToggledTooFrequently(serverlevel, blockpos, true)) { +- serverlevel.levelEvent(1502, blockpos, 0); +- serverlevel.scheduleTick(blockpos, serverlevel.getBlockState(blockpos).getBlock(), 160); ++ // CraftBukkit start ++ if (oldCurrent != 0) { ++ event.setNewCurrent(0); ++ manager.callEvent(event); ++ if (event.getNewCurrent() != 0) { ++ return; ++ } + } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(RedstoneTorchBlock.LIT, false), 3); ++ if (isToggledTooFrequently(level, pos, true)) { ++ level.levelEvent(1502, pos, 0); ++ level.scheduleTick(pos, level.getBlockState(pos).getBlock(), 160); ++ } + } +- } else if (!flag && !isToggledTooFrequently(serverlevel, blockpos, false)) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(RedstoneTorchBlock.LIT, true), 3); ++ } else if (!flag && !isToggledTooFrequently(level, pos, false)) { ++ // CraftBukkit start ++ if (oldCurrent != 15) { ++ event.setNewCurrent(15); ++ manager.callEvent(event); ++ if (event.getNewCurrent() != 15) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(RedstoneTorchBlock.LIT, true), 3); + } + + } + + @Override +- @Override +- public void neighborChanged(BlockState blockstate, Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { +- if ((Boolean) blockstate.getValue(RedstoneTorchBlock.LIT) == this.hasNeighborSignal(level, blockpos, blockstate) && !level.getBlockTicks().willTickThisTick(blockpos, this)) { +- level.scheduleTick(blockpos, (Block) this, 2); ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ if ((Boolean) state.getValue(RedstoneTorchBlock.LIT) == this.hasNeighborSignal(level, pos, state) && !level.getBlockTicks().willTickThisTick(pos, this)) { ++ level.scheduleTick(pos, (Block) this, 2); + } + + } + + @Override +- @Override +- public int getDirectSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return direction == Direction.DOWN ? blockstate.getSignal(blockgetter, blockpos, direction) : 0; ++ public int getDirectSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return side == Direction.DOWN ? blockState.getSignal(blockAccess, pos, side) : 0; + } + + @Override +- @Override +- public boolean isSignalSource(BlockState blockstate) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + + @Override +- @Override +- public void animateTick(BlockState blockstate, Level level, BlockPos blockpos, RandomSource randomsource) { +- if ((Boolean) blockstate.getValue(RedstoneTorchBlock.LIT)) { +- double d0 = (double) blockpos.getX() + 0.5D + (randomsource.nextDouble() - 0.5D) * 0.2D; +- double d1 = (double) blockpos.getY() + 0.7D + (randomsource.nextDouble() - 0.5D) * 0.2D; +- double d2 = (double) blockpos.getZ() + 0.5D + (randomsource.nextDouble() - 0.5D) * 0.2D; ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(RedstoneTorchBlock.LIT)) { ++ double d0 = (double) pos.getX() + 0.5D + (random.nextDouble() - 0.5D) * 0.2D; ++ double d1 = (double) pos.getY() + 0.7D + (random.nextDouble() - 0.5D) * 0.2D; ++ double d2 = (double) pos.getZ() + 0.5D + (random.nextDouble() - 0.5D) * 0.2D; + +- level.addParticle(DustParticleOptions.REDSTONE, d0, d1, d2, 0.0D, 0.0D, 0.0D); ++ level.addParticle(ParticleParamRedstone.REDSTONE, d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(RedstoneTorchBlock.LIT); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(RedstoneTorchBlock.LIT); + } + +- private static boolean isToggledTooFrequently(Level level, BlockPos blockpos, boolean flag) { +- List list = (List) RedstoneTorchBlock.RECENT_TOGGLES.computeIfAbsent(level, (blockgetter) -> { ++ private static boolean isToggledTooFrequently(Level level, BlockPos pos, boolean logToggle) { ++ List list = (List) RedstoneTorchBlock.RECENT_TOGGLES.computeIfAbsent(level, (iblockaccess) -> { + return Lists.newArrayList(); + }); + +- if (flag) { +- list.add(new RedstoneTorchBlock.Toggle(blockpos.immutable(), level.getGameTime())); ++ if (logToggle) { ++ list.add(new RedstoneTorchBlock.Toggle(pos.immutable(), level.getGameTime())); + } + + int i = 0; + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- RedstoneTorchBlock.Toggle redstonetorchblock_toggle = (RedstoneTorchBlock.Toggle) iterator.next(); ++ RedstoneTorchBlock.Toggle blockredstonetorch_redstoneupdateinfo = (RedstoneTorchBlock.Toggle) iterator.next(); + +- if (redstonetorchblock_toggle.pos.equals(blockpos)) { ++ if (blockredstonetorch_redstoneupdateinfo.pos.equals(pos)) { + ++i; + if (i >= 8) { + return true; +@@ -174,9 +190,9 @@ + final BlockPos pos; + final long when; + +- public Toggle(BlockPos blockpos, long i) { +- this.pos = blockpos; +- this.when = i; ++ public Toggle(BlockPos pos, long when) { ++ this.pos = pos; ++ this.when = when; + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/RespawnAnchorBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/RespawnAnchorBlock.java.patch new file mode 100644 index 0000000000..62e33e09e5 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/RespawnAnchorBlock.java.patch @@ -0,0 +1,277 @@ +--- a/net/minecraft/world/level/block/RespawnAnchorBlock.java ++++ b/net/minecraft/world/level/block/RespawnAnchorBlock.java +@@ -18,7 +18,7 @@ + import net.minecraft.tags.FluidTags; + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +@@ -32,13 +32,13 @@ + import net.minecraft.world.level.ExplosionDamageCalculator; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.FluidState; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; + +@@ -52,45 +52,43 @@ + private static final ImmutableList RESPAWN_OFFSETS = (new Builder()).addAll(RespawnAnchorBlock.RESPAWN_HORIZONTAL_OFFSETS).addAll(RespawnAnchorBlock.RESPAWN_HORIZONTAL_OFFSETS.stream().map(Vec3i::below).iterator()).addAll(RespawnAnchorBlock.RESPAWN_HORIZONTAL_OFFSETS.stream().map(Vec3i::above).iterator()).add(new Vec3i(0, 1, 0)).build(); + + @Override +- @Override + public MapCodec codec() { + return RespawnAnchorBlock.CODEC; + } + +- public RespawnAnchorBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(RespawnAnchorBlock.CHARGE, 0)); ++ public RespawnAnchorBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(RespawnAnchorBlock.CHARGE, 0)); + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ ItemStack itemstack = player.getItemInHand(hand); + +- if (interactionhand == InteractionHand.MAIN_HAND && !isRespawnFuel(itemstack) && isRespawnFuel(player.getItemInHand(InteractionHand.OFF_HAND))) { ++ if (hand == EnumHand.MAIN_HAND && !isRespawnFuel(itemstack) && isRespawnFuel(player.getItemInHand(EnumHand.OFF_HAND))) { + return InteractionResult.PASS; +- } else if (isRespawnFuel(itemstack) && canBeCharged(blockstate)) { +- charge(player, level, blockpos, blockstate); ++ } else if (isRespawnFuel(itemstack) && canBeCharged(state)) { ++ charge(player, level, pos, state); + if (!player.getAbilities().instabuild) { + itemstack.shrink(1); + } + + return InteractionResult.sidedSuccess(level.isClientSide); +- } else if ((Integer) blockstate.getValue(RespawnAnchorBlock.CHARGE) == 0) { ++ } else if ((Integer) state.getValue(RespawnAnchorBlock.CHARGE) == 0) { + return InteractionResult.PASS; + } else if (!canSetSpawn(level)) { + if (!level.isClientSide) { +- this.explode(blockstate, level, blockpos); ++ this.explode(state, level, pos); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + } else { + if (!level.isClientSide) { +- ServerPlayer serverplayer = (ServerPlayer) player; ++ ServerPlayer entityplayer = (ServerPlayer) player; + +- if (serverplayer.getRespawnDimension() != level.dimension() || !blockpos.equals(serverplayer.getRespawnPosition())) { +- serverplayer.setRespawnPosition(level.dimension(), blockpos, 0.0F, false, true); +- level.playSound((Player) null, (double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D, SoundEvents.RESPAWN_ANCHOR_SET_SPAWN, SoundSource.BLOCKS, 1.0F, 1.0F); ++ if (entityplayer.getRespawnDimension() != level.dimension() || !pos.equals(entityplayer.getRespawnPosition())) { ++ entityplayer.setRespawnPosition(level.dimension(), pos, 0.0F, false, true, org.bukkit.event.player.PlayerSpawnChangeEvent.Cause.RESPAWN_ANCHOR); // CraftBukkit ++ level.playSound((Player) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.RESPAWN_ANCHOR_SET_SPAWN, SoundSource.BLOCKS, 1.0F, 1.0F); + return InteractionResult.SUCCESS; + } + } +@@ -99,135 +97,129 @@ + } + } + +- private static boolean isRespawnFuel(ItemStack itemstack) { +- return itemstack.is(Items.GLOWSTONE); ++ private static boolean isRespawnFuel(ItemStack stack) { ++ return stack.is(Items.GLOWSTONE); + } + +- private static boolean canBeCharged(BlockState blockstate) { +- return (Integer) blockstate.getValue(RespawnAnchorBlock.CHARGE) < 4; ++ private static boolean canBeCharged(IBlockData state) { ++ return (Integer) state.getValue(RespawnAnchorBlock.CHARGE) < 4; + } + +- private static boolean isWaterThatWouldFlow(BlockPos blockpos, Level level) { +- FluidState fluidstate = level.getFluidState(blockpos); ++ private static boolean isWaterThatWouldFlow(BlockPos pos, Level level) { ++ FluidState fluid = level.getFluidState(pos); + +- if (!fluidstate.is(FluidTags.WATER)) { ++ if (!fluid.is(FluidTags.WATER)) { + return false; +- } else if (fluidstate.isSource()) { ++ } else if (fluid.isSource()) { + return true; + } else { +- float f = (float) fluidstate.getAmount(); ++ float f = (float) fluid.getAmount(); + + if (f < 2.0F) { + return false; + } else { +- FluidState fluidstate1 = level.getFluidState(blockpos.below()); ++ FluidState fluid1 = level.getFluidState(pos.below()); + +- return !fluidstate1.is(FluidTags.WATER); ++ return !fluid1.is(FluidTags.WATER); + } + } + } + +- private void explode(BlockState blockstate, Level level, final BlockPos blockpos) { +- level.removeBlock(blockpos, false); +- Stream stream = Direction.Plane.HORIZONTAL.stream(); ++ private void explode(IBlockData state, Level level, final BlockPos pos2) { ++ level.removeBlock(pos2, false); ++ Stream stream = Direction.Plane.HORIZONTAL.stream(); // CraftBukkit - decompile error + +- Objects.requireNonNull(blockpos); +- boolean flag = stream.map(blockpos::relative).anyMatch((blockpos1) -> { +- return isWaterThatWouldFlow(blockpos1, level); ++ Objects.requireNonNull(pos2); ++ boolean flag = stream.map(pos2::relative).anyMatch((blockposition1) -> { ++ return isWaterThatWouldFlow(blockposition1, level); + }); +- final boolean flag1 = flag || level.getFluidState(blockpos.above()).is(FluidTags.WATER); ++ final boolean flag1 = flag || level.getFluidState(pos2.above()).is(FluidTags.WATER); + ExplosionDamageCalculator explosiondamagecalculator = new ExplosionDamageCalculator() { + @Override +- @Override +- public Optional getBlockExplosionResistance(Explosion explosion, BlockGetter blockgetter, BlockPos blockpos1, BlockState blockstate1, FluidState fluidstate) { +- return blockpos1.equals(blockpos) && flag1 ? Optional.of(Blocks.WATER.getExplosionResistance()) : super.getBlockExplosionResistance(explosion, blockgetter, blockpos1, blockstate1, fluidstate); ++ public Optional getBlockExplosionResistance(Explosion explosion, BlockGetter reader, BlockPos pos, IBlockData state, FluidState fluid) { ++ return pos.equals(pos2) && flag1 ? Optional.of(Blocks.WATER.getExplosionResistance()) : super.getBlockExplosionResistance(explosion, reader, pos, state, fluid); + } + }; +- Vec3 vec3 = blockpos.getCenter(); ++ Vec3 vec3d = pos2.getCenter(); + +- level.explode((Entity) null, level.damageSources().badRespawnPointExplosion(vec3), explosiondamagecalculator, vec3, 5.0F, true, Level.ExplosionInteraction.BLOCK); ++ level.explode((Entity) null, level.damageSources().badRespawnPointExplosion(vec3d), explosiondamagecalculator, vec3d, 5.0F, true, Level.a.BLOCK); + } + + public static boolean canSetSpawn(Level level) { + return level.dimensionType().respawnAnchorWorks(); + } + +- public static void charge(@Nullable Entity entity, Level level, BlockPos blockpos, BlockState blockstate) { +- BlockState blockstate1 = (BlockState) blockstate.setValue(RespawnAnchorBlock.CHARGE, (Integer) blockstate.getValue(RespawnAnchorBlock.CHARGE) + 1); ++ public static void charge(@Nullable Entity entity, Level level, BlockPos pos, IBlockData state) { ++ IBlockData iblockdata1 = (IBlockData) state.setValue(RespawnAnchorBlock.CHARGE, (Integer) state.getValue(RespawnAnchorBlock.CHARGE) + 1); + +- level.setBlock(blockpos, blockstate1, 3); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(entity, blockstate1)); +- level.playSound((Player) null, (double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D, SoundEvents.RESPAWN_ANCHOR_CHARGE, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.setBlock(pos, iblockdata1, 3); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, iblockdata1)); ++ level.playSound((Player) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.RESPAWN_ANCHOR_CHARGE, SoundSource.BLOCKS, 1.0F, 1.0F); + } + + @Override +- @Override +- public void animateTick(BlockState blockstate, Level level, BlockPos blockpos, RandomSource randomsource) { +- if ((Integer) blockstate.getValue(RespawnAnchorBlock.CHARGE) != 0) { +- if (randomsource.nextInt(100) == 0) { +- level.playSound((Player) null, (double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D, SoundEvents.RESPAWN_ANCHOR_AMBIENT, SoundSource.BLOCKS, 1.0F, 1.0F); ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if ((Integer) state.getValue(RespawnAnchorBlock.CHARGE) != 0) { ++ if (random.nextInt(100) == 0) { ++ level.playSound((Player) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.RESPAWN_ANCHOR_AMBIENT, SoundSource.BLOCKS, 1.0F, 1.0F); + } + +- double d0 = (double) blockpos.getX() + 0.5D + (0.5D - randomsource.nextDouble()); +- double d1 = (double) blockpos.getY() + 1.0D; +- double d2 = (double) blockpos.getZ() + 0.5D + (0.5D - randomsource.nextDouble()); +- double d3 = (double) randomsource.nextFloat() * 0.04D; ++ double d0 = (double) pos.getX() + 0.5D + (0.5D - random.nextDouble()); ++ double d1 = (double) pos.getY() + 1.0D; ++ double d2 = (double) pos.getZ() + 0.5D + (0.5D - random.nextDouble()); ++ double d3 = (double) random.nextFloat() * 0.04D; + + level.addParticle(ParticleTypes.REVERSE_PORTAL, d0, d1, d2, 0.0D, d3, 0.0D); + } + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(RespawnAnchorBlock.CHARGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(RespawnAnchorBlock.CHARGE); + } + + @Override +- @Override +- public boolean hasAnalogOutputSignal(BlockState blockstate) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return true; + } + +- public static int getScaledChargeLevel(BlockState blockstate, int i) { +- return Mth.floor((float) ((Integer) blockstate.getValue(RespawnAnchorBlock.CHARGE) - 0) / 4.0F * (float) i); ++ public static int getScaledChargeLevel(IBlockData state, int scale) { ++ return Mth.floor((float) ((Integer) state.getValue(RespawnAnchorBlock.CHARGE) - 0) / 4.0F * (float) scale); + } + + @Override +- @Override +- public int getAnalogOutputSignal(BlockState blockstate, Level level, BlockPos blockpos) { +- return getScaledChargeLevel(blockstate, 15); ++ public int getAnalogOutputSignal(IBlockData blockState, Level level, BlockPos pos) { ++ return getScaledChargeLevel(blockState, 15); + } + +- public static Optional findStandUpPosition(EntityType entitytype, CollisionGetter collisiongetter, BlockPos blockpos) { +- Optional optional = findStandUpPosition(entitytype, collisiongetter, blockpos, true); ++ public static Optional findStandUpPosition(EntityType entityType, CollisionGetter level, BlockPos pos) { ++ Optional optional = findStandUpPosition(entityType, level, pos, true); + +- return optional.isPresent() ? optional : findStandUpPosition(entitytype, collisiongetter, blockpos, false); ++ return optional.isPresent() ? optional : findStandUpPosition(entityType, level, pos, false); + } + +- private static Optional findStandUpPosition(EntityType entitytype, CollisionGetter collisiongetter, BlockPos blockpos, boolean flag) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ private static Optional findStandUpPosition(EntityType entityType, CollisionGetter level, BlockPos pos, boolean simulate) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + UnmodifiableIterator unmodifiableiterator = RespawnAnchorBlock.RESPAWN_OFFSETS.iterator(); + +- Vec3 vec3; ++ Vec3 vec3d; + + do { + if (!unmodifiableiterator.hasNext()) { + return Optional.empty(); + } + +- Vec3i vec3i = (Vec3i) unmodifiableiterator.next(); ++ Vec3i baseblockposition = (Vec3i) unmodifiableiterator.next(); + +- blockpos_mutableblockpos.set(blockpos).move(vec3i); +- vec3 = DismountHelper.findSafeDismountLocation(entitytype, collisiongetter, blockpos_mutableblockpos, flag); +- } while (vec3 == null); ++ blockposition_mutableblockposition.set(pos).move(baseblockposition); ++ vec3d = DismountHelper.findSafeDismountLocation(entityType, level, blockposition_mutableblockposition, simulate); ++ } while (vec3d == null); + +- return Optional.of(vec3); ++ return Optional.of(vec3d); + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/RootedDirtBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/RootedDirtBlock.java.patch new file mode 100644 index 0000000000..7d189c56f8 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/RootedDirtBlock.java.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/world/level/block/RootedDirtBlock.java ++++ b/net/minecraft/world/level/block/RootedDirtBlock.java +@@ -7,37 +7,33 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public class RootedDirtBlock extends Block implements BonemealableBlock { + + public static final MapCodec CODEC = simpleCodec(RootedDirtBlock::new); + + @Override +- @Override + public MapCodec codec() { + return RootedDirtBlock.CODEC; + } + +- public RootedDirtBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ public RootedDirtBlock(BlockBehaviour.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public boolean isValidBonemealTarget(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { +- return levelreader.getBlockState(blockpos.below()).isAir(); ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ return iworldreader.getBlockState(blockposition.below()).isAir(); + } + + @Override +- @Override +- public boolean isBonemealSuccess(Level level, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return true; + } + + @Override +- @Override +- public void performBonemeal(ServerLevel serverlevel, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { +- serverlevel.setBlockAndUpdate(blockpos.below(), Blocks.HANGING_ROOTS.defaultBlockState()); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, pos.below(), Blocks.HANGING_ROOTS.defaultBlockState()); // CraftBukkit + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SaplingBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SaplingBlock.java.patch new file mode 100644 index 0000000000..b10fdeb23b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SaplingBlock.java.patch @@ -0,0 +1,143 @@ +--- a/net/minecraft/world/level/block/SaplingBlock.java ++++ b/net/minecraft/world/level/block/SaplingBlock.java +@@ -8,84 +8,110 @@ + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; +-import net.minecraft.world.level.block.grower.TreeGrower; ++import net.minecraft.world.level.block.grower.WorldGenTreeProvider; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.TreeType; ++import org.bukkit.block.BlockState; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.world.StructureGrowEvent; ++// CraftBukkit end + + public class SaplingBlock extends BushBlock implements BonemealableBlock { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- return instance.group(TreeGrower.CODEC.fieldOf("tree").forGetter((saplingblock) -> { +- return saplingblock.treeGrower; ++ return instance.group(WorldGenTreeProvider.CODEC.fieldOf("tree").forGetter((blocksapling) -> { ++ return blocksapling.treeGrower; + }), propertiesCodec()).apply(instance, SaplingBlock::new); + }); + public static final IntegerProperty STAGE = BlockStateProperties.STAGE; + protected static final float AABB_OFFSET = 6.0F; + protected static final VoxelShape SHAPE = Block.box(2.0D, 0.0D, 2.0D, 14.0D, 12.0D, 14.0D); +- protected final TreeGrower treeGrower; ++ protected final WorldGenTreeProvider treeGrower; ++ public static TreeType treeType; // CraftBukkit + + @Override +- @Override + public MapCodec codec() { + return SaplingBlock.CODEC; + } + +- protected SaplingBlock(TreeGrower treegrower, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.treeGrower = treegrower; +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(SaplingBlock.STAGE, 0)); ++ protected SaplingBlock(WorldGenTreeProvider worldgentreeprovider, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info); ++ this.treeGrower = worldgentreeprovider; ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(SaplingBlock.STAGE, 0)); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return SaplingBlock.SHAPE; + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (serverlevel.getMaxLocalRawBrightness(blockpos.above()) >= 9 && randomsource.nextInt(7) == 0) { +- this.advanceTree(serverlevel, blockpos, blockstate, randomsource); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (level.getMaxLocalRawBrightness(pos.above()) >= 9 && random.nextInt(7) == 0) { ++ this.advanceTree(level, pos, state, random); + } + + } + +- public void advanceTree(ServerLevel serverlevel, BlockPos blockpos, BlockState blockstate, RandomSource randomsource) { +- if ((Integer) blockstate.getValue(SaplingBlock.STAGE) == 0) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.cycle(SaplingBlock.STAGE), 4); ++ public void advanceTree(ServerLevel level, BlockPos pos, IBlockData state, RandomSource random) { ++ if ((Integer) state.getValue(SaplingBlock.STAGE) == 0) { ++ level.setBlock(pos, (IBlockData) state.cycle(SaplingBlock.STAGE), 4); + } else { +- this.treeGrower.growTree(serverlevel, serverlevel.getChunkSource().getGenerator(), blockpos, blockstate, randomsource); ++ // CraftBukkit start ++ if (level.captureTreeGeneration) { ++ this.treeGrower.growTree(level, level.getChunkSource().getGenerator(), pos, state, random); ++ } else { ++ level.captureTreeGeneration = true; ++ this.treeGrower.growTree(level, level.getChunkSource().getGenerator(), pos, state, random); ++ level.captureTreeGeneration = false; ++ if (level.capturedBlockStates.size() > 0) { ++ TreeType treeType = SaplingBlock.treeType; ++ SaplingBlock.treeType = null; ++ Location location = CraftLocation.toBukkit(pos, level.getWorld()); ++ java.util.List blocks = new java.util.ArrayList<>(level.capturedBlockStates.values()); ++ level.capturedBlockStates.clear(); ++ StructureGrowEvent event = null; ++ if (treeType != null) { ++ event = new StructureGrowEvent(location, treeType, false, null, blocks); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ } ++ if (event == null || !event.isCancelled()) { ++ for (BlockState blockstate : blocks) { ++ blockstate.update(true); ++ } ++ } ++ } ++ } ++ // CraftBukkit end + } + + } + + @Override +- @Override +- public boolean isValidBonemealTarget(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { + return true; + } + + @Override +- @Override +- public boolean isBonemealSuccess(Level level, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return (double) level.random.nextFloat() < 0.45D; + } + + @Override +- @Override +- public void performBonemeal(ServerLevel serverlevel, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { +- this.advanceTree(serverlevel, blockpos, blockstate, randomsource); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ this.advanceTree(level, pos, state, random); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(SaplingBlock.STAGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(SaplingBlock.STAGE); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ScaffoldingBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ScaffoldingBlock.java.patch new file mode 100644 index 0000000000..322e8173f0 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/ScaffoldingBlock.java.patch @@ -0,0 +1,194 @@ +--- a/net/minecraft/world/level/block/ScaffoldingBlock.java ++++ b/net/minecraft/world/level/block/ScaffoldingBlock.java +@@ -13,7 +13,7 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -39,132 +39,120 @@ + public static final BooleanProperty BOTTOM = BlockStateProperties.BOTTOM; + + @Override +- @Override + public MapCodec codec() { + return ScaffoldingBlock.CODEC; + } + +- protected ScaffoldingBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(ScaffoldingBlock.DISTANCE, 7)).setValue(ScaffoldingBlock.WATERLOGGED, false)).setValue(ScaffoldingBlock.BOTTOM, false)); ++ protected ScaffoldingBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(ScaffoldingBlock.DISTANCE, 7)).setValue(ScaffoldingBlock.WATERLOGGED, false)).setValue(ScaffoldingBlock.BOTTOM, false)); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(ScaffoldingBlock.DISTANCE, ScaffoldingBlock.WATERLOGGED, ScaffoldingBlock.BOTTOM); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(ScaffoldingBlock.DISTANCE, ScaffoldingBlock.WATERLOGGED, ScaffoldingBlock.BOTTOM); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return !collisioncontext.isHoldingItem(blockstate.getBlock().asItem()) ? ((Boolean) blockstate.getValue(ScaffoldingBlock.BOTTOM) ? ScaffoldingBlock.UNSTABLE_SHAPE : ScaffoldingBlock.STABLE_SHAPE) : Shapes.block(); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return !context.isHoldingItem(state.getBlock().asItem()) ? ((Boolean) state.getValue(ScaffoldingBlock.BOTTOM) ? ScaffoldingBlock.UNSTABLE_SHAPE : ScaffoldingBlock.STABLE_SHAPE) : Shapes.block(); + } + + @Override +- @Override +- public VoxelShape getInteractionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { ++ public VoxelShape getInteractionShape(IBlockData state, BlockGetter level, BlockPos pos) { + return Shapes.block(); + } + + @Override +- @Override +- public boolean canBeReplaced(BlockState blockstate, BlockPlaceContext blockplacecontext) { +- return blockplacecontext.getItemInHand().is(this.asItem()); ++ public boolean canBeReplaced(IBlockData state, BlockPlaceContext useContext) { ++ return useContext.getItemInHand().is(this.asItem()); + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- BlockPos blockpos = blockplacecontext.getClickedPos(); +- Level level = blockplacecontext.getLevel(); +- int i = getDistance(level, blockpos); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ BlockPos blockposition = context.getClickedPos(); ++ Level world = context.getLevel(); ++ int i = getDistance(world, blockposition); + +- return (BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(ScaffoldingBlock.WATERLOGGED, level.getFluidState(blockpos).getType() == Fluids.WATER)).setValue(ScaffoldingBlock.DISTANCE, i)).setValue(ScaffoldingBlock.BOTTOM, this.isBottom(level, blockpos, i)); ++ return (IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(ScaffoldingBlock.WATERLOGGED, world.getFluidState(blockposition).getType() == Fluids.WATER)).setValue(ScaffoldingBlock.DISTANCE, i)).setValue(ScaffoldingBlock.BOTTOM, this.isBottom(world, blockposition, i)); + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { + if (!level.isClientSide) { +- level.scheduleTick(blockpos, (Block) this, 1); ++ level.scheduleTick(pos, (Block) this, 1); + } + + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if ((Boolean) blockstate.getValue(ScaffoldingBlock.WATERLOGGED)) { +- levelaccessor.scheduleTick(blockpos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(levelaccessor)); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if ((Boolean) state.getValue(ScaffoldingBlock.WATERLOGGED)) { ++ level.scheduleTick(currentPos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + +- if (!levelaccessor.isClientSide()) { +- levelaccessor.scheduleTick(blockpos, (Block) this, 1); ++ if (!level.isClientSide()) { ++ level.scheduleTick(currentPos, (Block) this, 1); + } + +- return blockstate; ++ return state; + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- int i = getDistance(serverlevel, blockpos); +- BlockState blockstate1 = (BlockState) ((BlockState) blockstate.setValue(ScaffoldingBlock.DISTANCE, i)).setValue(ScaffoldingBlock.BOTTOM, this.isBottom(serverlevel, blockpos, i)); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ int i = getDistance(level, pos); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) state.setValue(ScaffoldingBlock.DISTANCE, i)).setValue(ScaffoldingBlock.BOTTOM, this.isBottom(level, pos, i)); + +- if ((Integer) blockstate1.getValue(ScaffoldingBlock.DISTANCE) == 7) { +- if ((Integer) blockstate.getValue(ScaffoldingBlock.DISTANCE) == 7) { +- FallingBlockEntity.fall(serverlevel, blockpos, blockstate1); ++ if ((Integer) iblockdata1.getValue(ScaffoldingBlock.DISTANCE) == 7 && !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.AIR.defaultBlockState()).isCancelled()) { // CraftBukkit - BlockFadeEvent ++ if ((Integer) state.getValue(ScaffoldingBlock.DISTANCE) == 7) { ++ FallingBlockEntity.fall(level, pos, iblockdata1); + } else { +- serverlevel.destroyBlock(blockpos, true); ++ level.destroyBlock(pos, true); + } +- } else if (blockstate != blockstate1) { +- serverlevel.setBlock(blockpos, blockstate1, 3); ++ } else if (state != iblockdata1) { ++ level.setBlock(pos, iblockdata1, 3); + } + + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- return getDistance(levelreader, blockpos) < 7; ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ return getDistance(level, pos) < 7; + } + + @Override +- @Override +- public VoxelShape getCollisionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return collisioncontext.isAbove(Shapes.block(), blockpos, true) && !collisioncontext.isDescending() ? ScaffoldingBlock.STABLE_SHAPE : ((Integer) blockstate.getValue(ScaffoldingBlock.DISTANCE) != 0 && (Boolean) blockstate.getValue(ScaffoldingBlock.BOTTOM) && collisioncontext.isAbove(ScaffoldingBlock.BELOW_BLOCK, blockpos, true) ? ScaffoldingBlock.UNSTABLE_SHAPE_BOTTOM : Shapes.empty()); ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return context.isAbove(Shapes.block(), pos, true) && !context.isDescending() ? ScaffoldingBlock.STABLE_SHAPE : ((Integer) state.getValue(ScaffoldingBlock.DISTANCE) != 0 && (Boolean) state.getValue(ScaffoldingBlock.BOTTOM) && context.isAbove(ScaffoldingBlock.BELOW_BLOCK, pos, true) ? ScaffoldingBlock.UNSTABLE_SHAPE_BOTTOM : Shapes.empty()); + } + + @Override +- @Override +- public FluidState getFluidState(BlockState blockstate) { +- return (Boolean) blockstate.getValue(ScaffoldingBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(blockstate); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(ScaffoldingBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + +- private boolean isBottom(BlockGetter blockgetter, BlockPos blockpos, int i) { +- return i > 0 && !blockgetter.getBlockState(blockpos.below()).is((Block) this); ++ private boolean isBottom(BlockGetter level, BlockPos pos, int distance) { ++ return distance > 0 && !level.getBlockState(pos.below()).is((Block) this); + } + +- public static int getDistance(BlockGetter blockgetter, BlockPos blockpos) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = blockpos.mutable().move(Direction.DOWN); +- BlockState blockstate = blockgetter.getBlockState(blockpos_mutableblockpos); ++ public static int getDistance(BlockGetter level, BlockPos pos) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable().move(Direction.DOWN); ++ IBlockData iblockdata = level.getBlockState(blockposition_mutableblockposition); + int i = 7; + +- if (blockstate.is(Blocks.SCAFFOLDING)) { +- i = (Integer) blockstate.getValue(ScaffoldingBlock.DISTANCE); +- } else if (blockstate.isFaceSturdy(blockgetter, blockpos_mutableblockpos, Direction.UP)) { ++ if (iblockdata.is(Blocks.SCAFFOLDING)) { ++ i = (Integer) iblockdata.getValue(ScaffoldingBlock.DISTANCE); ++ } else if (iblockdata.isFaceSturdy(level, blockposition_mutableblockposition, Direction.UP)) { + return 0; + } + + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); +- BlockState blockstate1 = blockgetter.getBlockState(blockpos_mutableblockpos.setWithOffset(blockpos, direction)); ++ Direction enumdirection = (Direction) iterator.next(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition_mutableblockposition.setWithOffset(pos, enumdirection)); + +- if (blockstate1.is(Blocks.SCAFFOLDING)) { +- i = Math.min(i, (Integer) blockstate1.getValue(ScaffoldingBlock.DISTANCE) + 1); ++ if (iblockdata1.is(Blocks.SCAFFOLDING)) { ++ i = Math.min(i, (Integer) iblockdata1.getValue(ScaffoldingBlock.DISTANCE) + 1); + if (i == 1) { + break; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SculkBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SculkBlock.java.patch new file mode 100644 index 0000000000..b277c76353 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SculkBlock.java.patch @@ -0,0 +1,138 @@ +--- a/net/minecraft/world/level/block/SculkBlock.java ++++ b/net/minecraft/world/level/block/SculkBlock.java +@@ -10,7 +10,7 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; +@@ -20,83 +20,84 @@ + public static final MapCodec CODEC = simpleCodec(SculkBlock::new); + + @Override +- @Override + public MapCodec codec() { + return SculkBlock.CODEC; + } + +- public SculkBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(ConstantInt.of(1), blockbehaviour_properties); ++ public SculkBlock(BlockBehaviour.Properties properties) { ++ super(ConstantInt.of(1), properties); + } + + @Override +- @Override +- public int attemptUseCharge(SculkSpreader.ChargeCursor sculkspreader_chargecursor, LevelAccessor levelaccessor, BlockPos blockpos, RandomSource randomsource, SculkSpreader sculkspreader, boolean flag) { +- int i = sculkspreader_chargecursor.getCharge(); ++ public int attemptUseCharge(SculkSpreader.ChargeCursor cursor, LevelAccessor level, BlockPos pos, RandomSource random, SculkSpreader spreader, boolean shouldConvertBlocks) { ++ int i = cursor.getCharge(); + +- if (i != 0 && randomsource.nextInt(sculkspreader.chargeDecayRate()) == 0) { +- BlockPos blockpos1 = sculkspreader_chargecursor.getPos(); +- boolean flag1 = blockpos1.closerThan(blockpos, (double) sculkspreader.noGrowthRadius()); ++ if (i != 0 && random.nextInt(spreader.chargeDecayRate()) == 0) { ++ BlockPos blockposition1 = cursor.getPos(); ++ boolean flag1 = blockposition1.closerThan(pos, (double) spreader.noGrowthRadius()); + +- if (!flag1 && canPlaceGrowth(levelaccessor, blockpos1)) { +- int j = sculkspreader.growthSpawnCost(); ++ if (!flag1 && canPlaceGrowth(level, blockposition1)) { ++ int j = spreader.growthSpawnCost(); + +- if (randomsource.nextInt(j) < i) { +- BlockPos blockpos2 = blockpos1.above(); +- BlockState blockstate = this.getRandomGrowthState(levelaccessor, blockpos2, randomsource, sculkspreader.isWorldGeneration()); ++ if (random.nextInt(j) < i) { ++ BlockPos blockposition2 = blockposition1.above(); ++ IBlockData iblockdata = this.getRandomGrowthState(level, blockposition2, random, spreader.isWorldGeneration()); + +- levelaccessor.setBlock(blockpos2, blockstate, 3); +- levelaccessor.playSound((Player) null, blockpos1, blockstate.getSoundType().getPlaceSound(), SoundSource.BLOCKS, 1.0F, 1.0F); ++ // CraftBukkit start - Call BlockSpreadEvent ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition2, iblockdata, 3)) { ++ level.playSound((Player) null, blockposition1, iblockdata.getSoundType().getPlaceSound(), SoundSource.BLOCKS, 1.0F, 1.0F); ++ } ++ // CraftBukkit end + } + + return Math.max(0, i - j); + } else { +- return randomsource.nextInt(sculkspreader.additionalDecayRate()) != 0 ? i : i - (flag1 ? 1 : getDecayPenalty(sculkspreader, blockpos1, blockpos, i)); ++ return random.nextInt(spreader.additionalDecayRate()) != 0 ? i : i - (flag1 ? 1 : getDecayPenalty(spreader, blockposition1, pos, i)); + } + } else { + return i; + } + } + +- private static int getDecayPenalty(SculkSpreader sculkspreader, BlockPos blockpos, BlockPos blockpos1, int i) { +- int j = sculkspreader.noGrowthRadius(); +- float f = Mth.square((float) Math.sqrt(blockpos.distSqr(blockpos1)) - (float) j); ++ private static int getDecayPenalty(SculkSpreader spreader, BlockPos cursorPos, BlockPos rootPos, int charge) { ++ int j = spreader.noGrowthRadius(); ++ float f = Mth.square((float) Math.sqrt(cursorPos.distSqr(rootPos)) - (float) j); + int k = Mth.square(24 - j); + float f1 = Math.min(1.0F, f / (float) k); + +- return Math.max(1, (int) ((float) i * f1 * 0.5F)); ++ return Math.max(1, (int) ((float) charge * f1 * 0.5F)); + } + +- private BlockState getRandomGrowthState(LevelAccessor levelaccessor, BlockPos blockpos, RandomSource randomsource, boolean flag) { +- BlockState blockstate; ++ private IBlockData getRandomGrowthState(LevelAccessor level, BlockPos pos, RandomSource random, boolean isWorldGeneration) { ++ IBlockData iblockdata; + +- if (randomsource.nextInt(11) == 0) { +- blockstate = (BlockState) Blocks.SCULK_SHRIEKER.defaultBlockState().setValue(SculkShriekerBlock.CAN_SUMMON, flag); ++ if (random.nextInt(11) == 0) { ++ iblockdata = (IBlockData) Blocks.SCULK_SHRIEKER.defaultBlockState().setValue(SculkShriekerBlock.CAN_SUMMON, isWorldGeneration); + } else { +- blockstate = Blocks.SCULK_SENSOR.defaultBlockState(); ++ iblockdata = Blocks.SCULK_SENSOR.defaultBlockState(); + } + +- return blockstate.hasProperty(BlockStateProperties.WATERLOGGED) && !levelaccessor.getFluidState(blockpos).isEmpty() ? (BlockState) blockstate.setValue(BlockStateProperties.WATERLOGGED, true) : blockstate; ++ return iblockdata.hasProperty(BlockStateProperties.WATERLOGGED) && !level.getFluidState(pos).isEmpty() ? (IBlockData) iblockdata.setValue(BlockStateProperties.WATERLOGGED, true) : iblockdata; + } + +- private static boolean canPlaceGrowth(LevelAccessor levelaccessor, BlockPos blockpos) { +- BlockState blockstate = levelaccessor.getBlockState(blockpos.above()); ++ private static boolean canPlaceGrowth(LevelAccessor level, BlockPos pos) { ++ IBlockData iblockdata = level.getBlockState(pos.above()); + +- if (!blockstate.isAir() && (!blockstate.is(Blocks.WATER) || !blockstate.getFluidState().is((Fluid) Fluids.WATER))) { ++ if (!iblockdata.isAir() && (!iblockdata.is(Blocks.WATER) || !iblockdata.getFluidState().is((Fluid) Fluids.WATER))) { + return false; + } else { + int i = 0; +- Iterator iterator = BlockPos.betweenClosed(blockpos.offset(-4, 0, -4), blockpos.offset(4, 2, 4)).iterator(); ++ Iterator iterator = BlockPos.betweenClosed(pos.offset(-4, 0, -4), pos.offset(4, 2, 4)).iterator(); + + do { + if (!iterator.hasNext()) { + return true; + } + +- BlockPos blockpos1 = (BlockPos) iterator.next(); +- BlockState blockstate1 = levelaccessor.getBlockState(blockpos1); ++ BlockPos blockposition1 = (BlockPos) iterator.next(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + +- if (blockstate1.is(Blocks.SCULK_SENSOR) || blockstate1.is(Blocks.SCULK_SHRIEKER)) { ++ if (iblockdata1.is(Blocks.SCULK_SENSOR) || iblockdata1.is(Blocks.SCULK_SHRIEKER)) { + ++i; + } + } while (i <= 2); +@@ -106,7 +107,6 @@ + } + + @Override +- @Override + public boolean canChangeBlockStateOnSpread() { + return false; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SculkCatalystBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SculkCatalystBlock.java.patch new file mode 100644 index 0000000000..839690d392 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SculkCatalystBlock.java.patch @@ -0,0 +1,93 @@ +--- a/net/minecraft/world/level/block/SculkCatalystBlock.java ++++ b/net/minecraft/world/level/block/SculkCatalystBlock.java +@@ -14,7 +14,7 @@ + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.SculkCatalystBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -26,58 +26,58 @@ + private final IntProvider xpRange = ConstantInt.of(5); + + @Override +- @Override + public MapCodec codec() { + return SculkCatalystBlock.CODEC; + } + +- public SculkCatalystBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(SculkCatalystBlock.PULSE, false)); ++ public SculkCatalystBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(SculkCatalystBlock.PULSE, false)); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(SculkCatalystBlock.PULSE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(SculkCatalystBlock.PULSE); + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if ((Boolean) blockstate.getValue(SculkCatalystBlock.PULSE)) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(SculkCatalystBlock.PULSE, false), 3); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(SculkCatalystBlock.PULSE)) { ++ level.setBlock(pos, (IBlockData) state.setValue(SculkCatalystBlock.PULSE, false), 3); + } + + } + + @Nullable + @Override +- @Override +- public BlockEntity newBlockEntity(BlockPos blockpos, BlockState blockstate) { +- return new SculkCatalystBlockEntity(blockpos, blockstate); ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ return new SculkCatalystBlockEntity(pos, state); + } + + @Nullable + @Override ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { ++ return level.isClientSide ? null : createTickerHelper(blockEntityType, BlockEntityType.SCULK_CATALYST, SculkCatalystBlockEntity::serverTick); ++ } ++ + @Override +- public BlockEntityTicker getTicker(Level level, BlockState blockstate, BlockEntityType blockentitytype) { +- return level.isClientSide ? null : createTickerHelper(blockentitytype, BlockEntityType.SCULK_CATALYST, SculkCatalystBlockEntity::serverTick); ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Override +- @Override +- public RenderShape getRenderShape(BlockState blockstate) { +- return RenderShape.MODEL; ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ super.spawnAfterBreak(state, level, pos, stack, dropExperience); ++ // CraftBukkit start - Delegate to getExpDrop + } + + @Override +- @Override +- public void spawnAfterBreak(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, ItemStack itemstack, boolean flag) { +- super.spawnAfterBreak(blockstate, serverlevel, blockpos, itemstack, flag); ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { + if (flag) { +- this.tryDropExperience(serverlevel, blockpos, itemstack, this.xpRange); ++ return this.tryDropExperience(worldserver, blockposition, itemstack, this.xpRange); + } + ++ return 0; ++ // CraftBukkit end + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SculkSensorBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SculkSensorBlock.java.patch new file mode 100644 index 0000000000..46c929fc8a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SculkSensorBlock.java.patch @@ -0,0 +1,433 @@ +--- a/net/minecraft/world/level/block/SculkSensorBlock.java ++++ b/net/minecraft/world/level/block/SculkSensorBlock.java +@@ -26,7 +26,7 @@ + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.SculkSensorBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -38,9 +38,13 @@ + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockRedstoneEvent; ++// CraftBukkit end + + public class SculkSensorBlock extends BaseEntityBlock implements SimpleWaterloggedBlock { + +@@ -61,168 +65,174 @@ + }); + + @Override +- @Override + public MapCodec codec() { + return SculkSensorBlock.CODEC; + } + +- public SculkSensorBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(SculkSensorBlock.PHASE, SculkSensorPhase.INACTIVE)).setValue(SculkSensorBlock.POWER, 0)).setValue(SculkSensorBlock.WATERLOGGED, false)); ++ public SculkSensorBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(SculkSensorBlock.PHASE, SculkSensorPhase.INACTIVE)).setValue(SculkSensorBlock.POWER, 0)).setValue(SculkSensorBlock.WATERLOGGED, false)); + } + + @Nullable + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- BlockPos blockpos = blockplacecontext.getClickedPos(); +- FluidState fluidstate = blockplacecontext.getLevel().getFluidState(blockpos); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ BlockPos blockposition = context.getClickedPos(); ++ FluidState fluid = context.getLevel().getFluidState(blockposition); + +- return (BlockState) this.defaultBlockState().setValue(SculkSensorBlock.WATERLOGGED, fluidstate.getType() == Fluids.WATER); ++ return (IBlockData) this.defaultBlockState().setValue(SculkSensorBlock.WATERLOGGED, fluid.getType() == Fluids.WATER); + } + + @Override +- @Override +- public FluidState getFluidState(BlockState blockstate) { +- return (Boolean) blockstate.getValue(SculkSensorBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(blockstate); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(SculkSensorBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (getPhase(blockstate) != SculkSensorPhase.ACTIVE) { +- if (getPhase(blockstate) == SculkSensorPhase.COOLDOWN) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.INACTIVE), 3); +- if (!(Boolean) blockstate.getValue(SculkSensorBlock.WATERLOGGED)) { +- serverlevel.playSound((Player) null, blockpos, SoundEvents.SCULK_CLICKING_STOP, SoundSource.BLOCKS, 1.0F, serverlevel.random.nextFloat() * 0.2F + 0.8F); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (getPhase(state) != SculkSensorPhase.ACTIVE) { ++ if (getPhase(state) == SculkSensorPhase.COOLDOWN) { ++ level.setBlock(pos, (IBlockData) state.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.INACTIVE), 3); ++ if (!(Boolean) state.getValue(SculkSensorBlock.WATERLOGGED)) { ++ level.playSound((Player) null, pos, SoundEvents.SCULK_CLICKING_STOP, SoundSource.BLOCKS, 1.0F, level.random.nextFloat() * 0.2F + 0.8F); + } + } + + } else { +- deactivate(serverlevel, blockpos, blockstate); ++ deactivate(level, pos, state); + } + } + + @Override +- @Override +- public void stepOn(Level level, BlockPos blockpos, BlockState blockstate, Entity entity) { +- if (!level.isClientSide() && canActivate(blockstate) && entity.getType() != EntityType.WARDEN) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ public void stepOn(Level level, BlockPos pos, IBlockData state, Entity entity) { ++ if (!level.isClientSide() && canActivate(state) && entity.getType() != EntityType.WARDEN) { ++ // CraftBukkit start ++ org.bukkit.event.Cancellable cancellable; ++ if (entity instanceof Player) { ++ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new org.bukkit.event.entity.EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent((org.bukkit.event.entity.EntityInteractEvent) cancellable); ++ } ++ if (cancellable.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof SculkSensorBlockEntity) { +- SculkSensorBlockEntity sculksensorblockentity = (SculkSensorBlockEntity) blockentity; ++ if (tileentity instanceof SculkSensorBlockEntity) { ++ SculkSensorBlockEntity sculksensorblockentity = (SculkSensorBlockEntity) tileentity; + + if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; ++ ServerLevel worldserver = (ServerLevel) level; + +- if (sculksensorblockentity.getVibrationUser().canReceiveVibration(serverlevel, blockpos, GameEvent.STEP, GameEvent.Context.of(blockstate))) { +- sculksensorblockentity.getListener().forceScheduleVibration(serverlevel, GameEvent.STEP, GameEvent.Context.of(entity), entity.position()); ++ if (sculksensorblockentity.getVibrationUser().canReceiveVibration(worldserver, pos, GameEvent.STEP, GameEvent.Context.of(state))) { ++ sculksensorblockentity.getListener().forceScheduleVibration(worldserver, GameEvent.STEP, GameEvent.Context.of(entity), entity.position()); + } + } + } + } + +- super.stepOn(level, blockpos, blockstate, entity); ++ super.stepOn(level, pos, state, entity); + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!level.isClientSide() && !blockstate.is(blockstate1.getBlock())) { +- if ((Integer) blockstate.getValue(SculkSensorBlock.POWER) > 0 && !level.getBlockTicks().hasScheduledTick(blockpos, this)) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(SculkSensorBlock.POWER, 0), 18); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean movedByPiston) { ++ if (!level.isClientSide() && !state.is(oldState.getBlock())) { ++ if ((Integer) state.getValue(SculkSensorBlock.POWER) > 0 && !level.getBlockTicks().hasScheduledTick(pos, this)) { ++ level.setBlock(pos, (IBlockData) state.setValue(SculkSensorBlock.POWER, 0), 18); + } + + } + } + + @Override +- @Override +- public void onRemove(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!blockstate.is(blockstate1.getBlock())) { +- if (getPhase(blockstate) == SculkSensorPhase.ACTIVE) { +- updateNeighbours(level, blockpos, blockstate); ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean movedByPiston) { ++ if (!state.is(newState.getBlock())) { ++ if (getPhase(state) == SculkSensorPhase.ACTIVE) { ++ updateNeighbours(level, pos, state); + } + +- super.onRemove(blockstate, level, blockpos, blockstate1, flag); ++ super.onRemove(state, level, pos, newState, movedByPiston); + } + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if ((Boolean) blockstate.getValue(SculkSensorBlock.WATERLOGGED)) { +- levelaccessor.scheduleTick(blockpos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(levelaccessor)); ++ public IBlockData updateShape(IBlockData state, Direction direction, IBlockData neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { ++ if ((Boolean) state.getValue(SculkSensorBlock.WATERLOGGED)) { ++ level.scheduleTick(pos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, direction, neighborState, level, pos, neighborPos); + } + +- private static void updateNeighbours(Level level, BlockPos blockpos, BlockState blockstate) { +- Block block = blockstate.getBlock(); ++ private static void updateNeighbours(Level level, BlockPos pos, IBlockData state) { ++ Block block = state.getBlock(); + +- level.updateNeighborsAt(blockpos, block); +- level.updateNeighborsAt(blockpos.below(), block); ++ level.updateNeighborsAt(pos, block); ++ level.updateNeighborsAt(pos.below(), block); + } + + @Nullable + @Override +- @Override +- public BlockEntity newBlockEntity(BlockPos blockpos, BlockState blockstate) { +- return new SculkSensorBlockEntity(blockpos, blockstate); ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ return new SculkSensorBlockEntity(pos, state); + } + + @Nullable + @Override +- @Override +- public BlockEntityTicker getTicker(Level level, BlockState blockstate, BlockEntityType blockentitytype) { +- return !level.isClientSide ? createTickerHelper(blockentitytype, BlockEntityType.SCULK_SENSOR, (level1, blockpos, blockstate1, sculksensorblockentity) -> { +- VibrationSystem.Ticker.tick(level1, sculksensorblockentity.getVibrationData(), sculksensorblockentity.getVibrationUser()); ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { ++ return !level.isClientSide ? createTickerHelper(blockEntityType, BlockEntityType.SCULK_SENSOR, (world1, blockposition, iblockdata1, sculksensorblockentity) -> { ++ VibrationSystem.Ticker.tick(world1, sculksensorblockentity.getVibrationData(), sculksensorblockentity.getVibrationUser()); + }) : null; + } + + @Override +- @Override +- public RenderShape getRenderShape(BlockState blockstate) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return SculkSensorBlock.SHAPE; + } + + @Override +- @Override +- public boolean isSignalSource(BlockState blockstate) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + + @Override +- @Override +- public int getSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return (Integer) blockstate.getValue(SculkSensorBlock.POWER); ++ public int getSignal(IBlockData state, BlockGetter level, BlockPos pos, Direction direction) { ++ return (Integer) state.getValue(SculkSensorBlock.POWER); + } + + @Override +- @Override +- public int getDirectSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return direction == Direction.UP ? blockstate.getSignal(blockgetter, blockpos, direction) : 0; ++ public int getDirectSignal(IBlockData state, BlockGetter level, BlockPos pos, Direction direction) { ++ return direction == Direction.UP ? state.getSignal(level, pos, direction) : 0; + } + +- public static SculkSensorPhase getPhase(BlockState blockstate) { +- return (SculkSensorPhase) blockstate.getValue(SculkSensorBlock.PHASE); ++ public static SculkSensorPhase getPhase(IBlockData state) { ++ return (SculkSensorPhase) state.getValue(SculkSensorBlock.PHASE); + } + +- public static boolean canActivate(BlockState blockstate) { +- return getPhase(blockstate) == SculkSensorPhase.INACTIVE; ++ public static boolean canActivate(IBlockData state) { ++ return getPhase(state) == SculkSensorPhase.INACTIVE; + } + +- public static void deactivate(Level level, BlockPos blockpos, BlockState blockstate) { +- level.setBlock(blockpos, (BlockState) ((BlockState) blockstate.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.COOLDOWN)).setValue(SculkSensorBlock.POWER, 0), 3); +- level.scheduleTick(blockpos, blockstate.getBlock(), 10); +- updateNeighbours(level, blockpos, blockstate); ++ public static void deactivate(Level level, BlockPos pos, IBlockData state) { ++ // CraftBukkit start ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(level, pos), state.getValue(SculkSensorBlock.POWER), 0); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if (eventRedstone.getNewCurrent() > 0) { ++ level.setBlock(pos, state.setValue(SculkSensorBlock.POWER, eventRedstone.getNewCurrent()), 3); ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) ((IBlockData) state.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.COOLDOWN)).setValue(SculkSensorBlock.POWER, 0), 3); ++ level.scheduleTick(pos, state.getBlock(), 10); ++ updateNeighbours(level, pos, state); + } + + @VisibleForTesting +@@ -230,48 +240,56 @@ + return 30; + } + +- public void activate(@Nullable Entity entity, Level level, BlockPos blockpos, BlockState blockstate, int i, int j) { +- level.setBlock(blockpos, (BlockState) ((BlockState) blockstate.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.ACTIVE)).setValue(SculkSensorBlock.POWER, i), 3); +- level.scheduleTick(blockpos, blockstate.getBlock(), this.getActiveTicks()); +- updateNeighbours(level, blockpos, blockstate); +- tryResonateVibration(entity, level, blockpos, j); +- level.gameEvent(entity, GameEvent.SCULK_SENSOR_TENDRILS_CLICKING, blockpos); +- if (!(Boolean) blockstate.getValue(SculkSensorBlock.WATERLOGGED)) { +- level.playSound((Player) null, (double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D, SoundEvents.SCULK_CLICKING, SoundSource.BLOCKS, 1.0F, level.random.nextFloat() * 0.2F + 0.8F); ++ public void activate(@Nullable Entity entity, Level level, BlockPos pos, IBlockData state, int power, int frequency) { ++ // CraftBukkit start ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(level, pos), state.getValue(SculkSensorBlock.POWER), power); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if (eventRedstone.getNewCurrent() <= 0) { ++ return; + } ++ power = eventRedstone.getNewCurrent(); ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) ((IBlockData) state.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.ACTIVE)).setValue(SculkSensorBlock.POWER, power), 3); ++ level.scheduleTick(pos, state.getBlock(), this.getActiveTicks()); ++ updateNeighbours(level, pos, state); ++ tryResonateVibration(entity, level, pos, frequency); ++ level.gameEvent(entity, GameEvent.SCULK_SENSOR_TENDRILS_CLICKING, pos); ++ if (!(Boolean) state.getValue(SculkSensorBlock.WATERLOGGED)) { ++ level.playSound((Player) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.SCULK_CLICKING, SoundSource.BLOCKS, 1.0F, level.random.nextFloat() * 0.2F + 0.8F); ++ } + + } + +- public static void tryResonateVibration(@Nullable Entity entity, Level level, BlockPos blockpos, int i) { +- Direction[] adirection = Direction.values(); +- int j = adirection.length; ++ public static void tryResonateVibration(@Nullable Entity entity, Level level, BlockPos pos, int frequency) { ++ Direction[] aenumdirection = Direction.values(); ++ int j = aenumdirection.length; + + for (int k = 0; k < j; ++k) { +- Direction direction = adirection[k]; +- BlockPos blockpos1 = blockpos.relative(direction); +- BlockState blockstate = level.getBlockState(blockpos1); ++ Direction enumdirection = aenumdirection[k]; ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ IBlockData iblockdata = level.getBlockState(blockposition1); + +- if (blockstate.is(BlockTags.VIBRATION_RESONATORS)) { +- level.gameEvent(VibrationSystem.getResonanceEventByFrequency(i), blockpos1, GameEvent.Context.of(entity, blockstate)); +- float f = SculkSensorBlock.RESONANCE_PITCH_BEND[i]; ++ if (iblockdata.is(BlockTags.VIBRATION_RESONATORS)) { ++ level.gameEvent(VibrationSystem.getResonanceEventByFrequency(frequency), blockposition1, GameEvent.Context.of(entity, iblockdata)); ++ float f = SculkSensorBlock.RESONANCE_PITCH_BEND[frequency]; + +- level.playSound((Player) null, blockpos1, SoundEvents.AMETHYST_BLOCK_RESONATE, SoundSource.BLOCKS, 1.0F, f); ++ level.playSound((Player) null, blockposition1, SoundEvents.AMETHYST_BLOCK_RESONATE, SoundSource.BLOCKS, 1.0F, f); + } + } + + } + + @Override +- @Override +- public void animateTick(BlockState blockstate, Level level, BlockPos blockpos, RandomSource randomsource) { +- if (getPhase(blockstate) == SculkSensorPhase.ACTIVE) { +- Direction direction = Direction.getRandom(randomsource); ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if (getPhase(state) == SculkSensorPhase.ACTIVE) { ++ Direction enumdirection = Direction.getRandom(random); + +- if (direction != Direction.UP && direction != Direction.DOWN) { +- double d0 = (double) blockpos.getX() + 0.5D + (direction.getStepX() == 0 ? 0.5D - randomsource.nextDouble() : (double) direction.getStepX() * 0.6D); +- double d1 = (double) blockpos.getY() + 0.25D; +- double d2 = (double) blockpos.getZ() + 0.5D + (direction.getStepZ() == 0 ? 0.5D - randomsource.nextDouble() : (double) direction.getStepZ() * 0.6D); +- double d3 = (double) randomsource.nextFloat() * 0.04D; ++ if (enumdirection != Direction.UP && enumdirection != Direction.DOWN) { ++ double d0 = (double) pos.getX() + 0.5D + (enumdirection.getStepX() == 0 ? 0.5D - random.nextDouble() : (double) enumdirection.getStepX() * 0.6D); ++ double d1 = (double) pos.getY() + 0.25D; ++ double d2 = (double) pos.getZ() + 0.5D + (enumdirection.getStepZ() == 0 ? 0.5D - random.nextDouble() : (double) enumdirection.getStepZ() * 0.6D); ++ double d3 = (double) random.nextFloat() * 0.04D; + + level.addParticle(DustColorTransitionOptions.SCULK_TO_REDSTONE, d0, d1, d2, 0.0D, d3, 0.0D); + } +@@ -279,50 +297,51 @@ + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(SculkSensorBlock.PHASE, SculkSensorBlock.POWER, SculkSensorBlock.WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(SculkSensorBlock.PHASE, SculkSensorBlock.POWER, SculkSensorBlock.WATERLOGGED); + } + + @Override +- @Override +- public boolean hasAnalogOutputSignal(BlockState blockstate) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return true; + } + + @Override +- @Override +- public int getAnalogOutputSignal(BlockState blockstate, Level level, BlockPos blockpos) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ public int getAnalogOutputSignal(IBlockData state, Level level, BlockPos pos) { ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof SculkSensorBlockEntity) { +- SculkSensorBlockEntity sculksensorblockentity = (SculkSensorBlockEntity) blockentity; ++ if (tileentity instanceof SculkSensorBlockEntity) { ++ SculkSensorBlockEntity sculksensorblockentity = (SculkSensorBlockEntity) tileentity; + +- return getPhase(blockstate) == SculkSensorPhase.ACTIVE ? sculksensorblockentity.getLastVibrationFrequency() : 0; ++ return getPhase(state) == SculkSensorPhase.ACTIVE ? sculksensorblockentity.getLastVibrationFrequency() : 0; + } else { + return 0; + } + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + + @Override +- @Override +- public boolean useShapeForLightOcclusion(BlockState blockstate) { ++ public boolean useShapeForLightOcclusion(IBlockData state) { + return true; + } + + @Override ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ super.spawnAfterBreak(state, level, pos, stack, dropExperience); ++ // CraftBukkit start - Delegate to getExpDrop ++ } ++ + @Override +- public void spawnAfterBreak(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, ItemStack itemstack, boolean flag) { +- super.spawnAfterBreak(blockstate, serverlevel, blockpos, itemstack, flag); ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { + if (flag) { +- this.tryDropExperience(serverlevel, blockpos, itemstack, ConstantInt.of(5)); ++ return this.tryDropExperience(worldserver, blockposition, itemstack, ConstantInt.of(5)); + } + ++ return 0; ++ // CraftBukkit end + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SculkShriekerBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SculkShriekerBlock.java.patch new file mode 100644 index 0000000000..585a60f135 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SculkShriekerBlock.java.patch @@ -0,0 +1,204 @@ +--- a/net/minecraft/world/level/block/SculkShriekerBlock.java ++++ b/net/minecraft/world/level/block/SculkShriekerBlock.java +@@ -19,7 +19,7 @@ + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.SculkShriekerBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -40,139 +40,132 @@ + public static final double TOP_Y = SculkShriekerBlock.COLLIDER.max(Direction.Axis.Y); + + @Override +- @Override + public MapCodec codec() { + return SculkShriekerBlock.CODEC; + } + +- public SculkShriekerBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(SculkShriekerBlock.SHRIEKING, false)).setValue(SculkShriekerBlock.WATERLOGGED, false)).setValue(SculkShriekerBlock.CAN_SUMMON, false)); ++ public SculkShriekerBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(SculkShriekerBlock.SHRIEKING, false)).setValue(SculkShriekerBlock.WATERLOGGED, false)).setValue(SculkShriekerBlock.CAN_SUMMON, false)); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(SculkShriekerBlock.SHRIEKING); +- statedefinition_builder.add(SculkShriekerBlock.WATERLOGGED); +- statedefinition_builder.add(SculkShriekerBlock.CAN_SUMMON); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(SculkShriekerBlock.SHRIEKING); ++ builder.add(SculkShriekerBlock.WATERLOGGED); ++ builder.add(SculkShriekerBlock.CAN_SUMMON); + } + + @Override +- @Override +- public void stepOn(Level level, BlockPos blockpos, BlockState blockstate, Entity entity) { ++ public void stepOn(Level level, BlockPos pos, IBlockData state, Entity entity) { + if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; +- ServerPlayer serverplayer = SculkShriekerBlockEntity.tryGetPlayer(entity); ++ ServerLevel worldserver = (ServerLevel) level; ++ ServerPlayer entityplayer = SculkShriekerBlockEntity.tryGetPlayer(entity); + +- if (serverplayer != null) { +- serverlevel.getBlockEntity(blockpos, BlockEntityType.SCULK_SHRIEKER).ifPresent((sculkshriekerblockentity) -> { +- sculkshriekerblockentity.tryShriek(serverlevel, serverplayer); ++ if (entityplayer != null) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(entityplayer, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null).isCancelled()) return; // CraftBukkit ++ worldserver.getBlockEntity(pos, BlockEntityType.SCULK_SHRIEKER).ifPresent((sculkshriekerblockentity) -> { ++ sculkshriekerblockentity.tryShriek(worldserver, entityplayer); + }); + } + } + +- super.stepOn(level, blockpos, blockstate, entity); ++ super.stepOn(level, pos, state, entity); + } + + @Override +- @Override +- public void onRemove(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean movedByPiston) { + if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; ++ ServerLevel worldserver = (ServerLevel) level; + +- if ((Boolean) blockstate.getValue(SculkShriekerBlock.SHRIEKING) && !blockstate.is(blockstate1.getBlock())) { +- serverlevel.getBlockEntity(blockpos, BlockEntityType.SCULK_SHRIEKER).ifPresent((sculkshriekerblockentity) -> { +- sculkshriekerblockentity.tryRespond(serverlevel); ++ if ((Boolean) state.getValue(SculkShriekerBlock.SHRIEKING) && !state.is(newState.getBlock())) { ++ worldserver.getBlockEntity(pos, BlockEntityType.SCULK_SHRIEKER).ifPresent((sculkshriekerblockentity) -> { ++ sculkshriekerblockentity.tryRespond(worldserver); + }); + } + } + +- super.onRemove(blockstate, level, blockpos, blockstate1, flag); ++ super.onRemove(state, level, pos, newState, movedByPiston); + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if ((Boolean) blockstate.getValue(SculkShriekerBlock.SHRIEKING)) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(SculkShriekerBlock.SHRIEKING, false), 3); +- serverlevel.getBlockEntity(blockpos, BlockEntityType.SCULK_SHRIEKER).ifPresent((sculkshriekerblockentity) -> { +- sculkshriekerblockentity.tryRespond(serverlevel); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(SculkShriekerBlock.SHRIEKING)) { ++ level.setBlock(pos, (IBlockData) state.setValue(SculkShriekerBlock.SHRIEKING, false), 3); ++ level.getBlockEntity(pos, BlockEntityType.SCULK_SHRIEKER).ifPresent((sculkshriekerblockentity) -> { ++ sculkshriekerblockentity.tryRespond(level); + }); + } + + } + + @Override +- @Override +- public RenderShape getRenderShape(BlockState blockstate) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Override +- @Override +- public VoxelShape getCollisionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return SculkShriekerBlock.COLLIDER; + } + + @Override +- @Override +- public VoxelShape getOcclusionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { ++ public VoxelShape getOcclusionShape(IBlockData state, BlockGetter level, BlockPos pos) { + return SculkShriekerBlock.COLLIDER; + } + + @Override +- @Override +- public boolean useShapeForLightOcclusion(BlockState blockstate) { ++ public boolean useShapeForLightOcclusion(IBlockData state) { + return true; + } + + @Nullable + @Override +- @Override +- public BlockEntity newBlockEntity(BlockPos blockpos, BlockState blockstate) { +- return new SculkShriekerBlockEntity(blockpos, blockstate); ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ return new SculkShriekerBlockEntity(pos, state); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if ((Boolean) blockstate.getValue(SculkShriekerBlock.WATERLOGGED)) { +- levelaccessor.scheduleTick(blockpos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(levelaccessor)); ++ public IBlockData updateShape(IBlockData state, Direction direction, IBlockData neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { ++ if ((Boolean) state.getValue(SculkShriekerBlock.WATERLOGGED)) { ++ level.scheduleTick(pos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, direction, neighborState, level, pos, neighborPos); + } + + @Nullable + @Override ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return (IBlockData) this.defaultBlockState().setValue(SculkShriekerBlock.WATERLOGGED, context.getLevel().getFluidState(context.getClickedPos()).getType() == Fluids.WATER); ++ } ++ + @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- return (BlockState) this.defaultBlockState().setValue(SculkShriekerBlock.WATERLOGGED, blockplacecontext.getLevel().getFluidState(blockplacecontext.getClickedPos()).getType() == Fluids.WATER); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(SculkShriekerBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override +- @Override +- public FluidState getFluidState(BlockState blockstate) { +- return (Boolean) blockstate.getValue(SculkShriekerBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(blockstate); ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ super.spawnAfterBreak(state, level, pos, stack, dropExperience); ++ // CraftBukkit start - Delegate to getExpDrop + } + + @Override +- @Override +- public void spawnAfterBreak(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, ItemStack itemstack, boolean flag) { +- super.spawnAfterBreak(blockstate, serverlevel, blockpos, itemstack, flag); ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { + if (flag) { +- this.tryDropExperience(serverlevel, blockpos, itemstack, ConstantInt.of(5)); ++ return this.tryDropExperience(worldserver, blockposition, itemstack, ConstantInt.of(5)); + } + ++ return 0; ++ // CraftBukkit end + } + + @Nullable + @Override +- @Override +- public BlockEntityTicker getTicker(Level level, BlockState blockstate, BlockEntityType blockentitytype) { +- return !level.isClientSide ? BaseEntityBlock.createTickerHelper(blockentitytype, BlockEntityType.SCULK_SHRIEKER, (level1, blockpos, blockstate1, sculkshriekerblockentity) -> { +- VibrationSystem.Ticker.tick(level1, sculkshriekerblockentity.getVibrationData(), sculkshriekerblockentity.getVibrationUser()); ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { ++ return !level.isClientSide ? BaseEntityBlock.createTickerHelper(blockEntityType, BlockEntityType.SCULK_SHRIEKER, (world1, blockposition, iblockdata1, sculkshriekerblockentity) -> { ++ VibrationSystem.Ticker.tick(world1, sculkshriekerblockentity.getVibrationData(), sculkshriekerblockentity.getVibrationUser()); + }) : null; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SculkSpreader.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SculkSpreader.java.patch new file mode 100644 index 0000000000..e415f99b26 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SculkSpreader.java.patch @@ -0,0 +1,412 @@ +--- a/net/minecraft/world/level/block/SculkSpreader.java ++++ b/net/minecraft/world/level/block/SculkSpreader.java +@@ -30,6 +30,7 @@ + import net.minecraft.core.Vec3i; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.Tag; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; +@@ -37,9 +38,14 @@ + import net.minecraft.tags.TagKey; + import net.minecraft.util.RandomSource; + import net.minecraft.world.entity.player.Player; ++import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.SculkBloomEvent; ++// CraftBukkit end + + public class SculkSpreader { + +@@ -56,14 +62,15 @@ + private final int additionalDecayRate; + private List cursors = new ArrayList(); + private static final Logger LOGGER = LogUtils.getLogger(); ++ public Level level; // CraftBukkit + +- public SculkSpreader(boolean flag, TagKey tagkey, int i, int j, int k, int l) { +- this.isWorldGeneration = flag; +- this.replaceableBlocks = tagkey; +- this.growthSpawnCost = i; +- this.noGrowthRadius = j; +- this.chargeDecayRate = k; +- this.additionalDecayRate = l; ++ public SculkSpreader(boolean isWorldGeneration, TagKey replaceableBlocks, int growthSpawnCoat, int noGrowthRadius, int chargeDecayRate, int additionalDecayRate) { ++ this.isWorldGeneration = isWorldGeneration; ++ this.replaceableBlocks = replaceableBlocks; ++ this.growthSpawnCost = growthSpawnCoat; ++ this.noGrowthRadius = noGrowthRadius; ++ this.chargeDecayRate = chargeDecayRate; ++ this.additionalDecayRate = additionalDecayRate; + } + + public static SculkSpreader createLevelSpreader() { +@@ -107,10 +114,10 @@ + this.cursors.clear(); + } + +- public void load(CompoundTag compoundtag) { +- if (compoundtag.contains("cursors", 9)) { ++ public void load(CompoundTag tag) { ++ if (tag.contains("cursors", 9)) { + this.cursors.clear(); +- DataResult dataresult = SculkSpreader.ChargeCursor.CODEC.listOf().parse(new Dynamic(NbtOps.INSTANCE, compoundtag.getList("cursors", 10))); ++ DataResult> dataresult = SculkSpreader.ChargeCursor.CODEC.listOf().parse(new Dynamic<>(NbtOps.INSTANCE, tag.getList("cursors", 10))); // CraftBukkit - decompile error + Logger logger = SculkSpreader.LOGGER; + + Objects.requireNonNull(logger); +@@ -124,63 +131,76 @@ + + } + +- public void save(CompoundTag compoundtag) { +- DataResult dataresult = SculkSpreader.ChargeCursor.CODEC.listOf().encodeStart(NbtOps.INSTANCE, this.cursors); ++ public void save(CompoundTag tag) { ++ DataResult dataresult = SculkSpreader.ChargeCursor.CODEC.listOf().encodeStart(NbtOps.INSTANCE, this.cursors); // CraftBukkit - decompile error + Logger logger = SculkSpreader.LOGGER; + + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((tag) -> { +- compoundtag.put("cursors", tag); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ tag.put("cursors", nbtbase); + }); + } + +- public void addCursors(BlockPos blockpos, int i) { +- while (i > 0) { +- int j = Math.min(i, 1000); ++ public void addCursors(BlockPos pos, int charge) { ++ while (charge > 0) { ++ int j = Math.min(charge, 1000); + +- this.addCursor(new SculkSpreader.ChargeCursor(blockpos, j)); +- i -= j; ++ this.addCursor(new SculkSpreader.ChargeCursor(pos, j)); ++ charge -= j; + } + + } + +- private void addCursor(SculkSpreader.ChargeCursor sculkspreader_chargecursor) { ++ private void addCursor(SculkSpreader.ChargeCursor cursor) { + if (this.cursors.size() < 32) { +- this.cursors.add(sculkspreader_chargecursor); ++ // CraftBukkit start ++ if (!isWorldGeneration()) { // CraftBukkit - SPIGOT-7475: Don't call event during world generation ++ CraftBlock bukkitBlock = CraftBlock.at(level, cursor.pos); ++ SculkBloomEvent event = new SculkBloomEvent(bukkitBlock, cursor.getCharge()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ cursor.charge = event.getCharge(); ++ } ++ // CraftBukkit end ++ ++ this.cursors.add(cursor); + } + } + +- public void updateCursors(LevelAccessor levelaccessor, BlockPos blockpos, RandomSource randomsource, boolean flag) { ++ public void updateCursors(LevelAccessor level, BlockPos pos, RandomSource random, boolean shouldConvertBlocks) { + if (!this.cursors.isEmpty()) { + List list = new ArrayList(); + Map map = new HashMap(); + Object2IntMap object2intmap = new Object2IntOpenHashMap(); + Iterator iterator = this.cursors.iterator(); + +- BlockPos blockpos1; ++ BlockPos blockposition1; + + while (iterator.hasNext()) { +- SculkSpreader.ChargeCursor sculkspreader_chargecursor = (SculkSpreader.ChargeCursor) iterator.next(); ++ SculkSpreader.ChargeCursor sculkspreader_a = (SculkSpreader.ChargeCursor) iterator.next(); + +- sculkspreader_chargecursor.update(levelaccessor, blockpos, randomsource, this, flag); +- if (sculkspreader_chargecursor.charge <= 0) { +- levelaccessor.levelEvent(3006, sculkspreader_chargecursor.getPos(), 0); ++ sculkspreader_a.update(level, pos, random, this, shouldConvertBlocks); ++ if (sculkspreader_a.charge <= 0) { ++ level.levelEvent(3006, sculkspreader_a.getPos(), 0); + } else { +- blockpos1 = sculkspreader_chargecursor.getPos(); +- object2intmap.computeInt(blockpos1, (blockpos2, integer) -> { +- return (integer == null ? 0 : integer) + sculkspreader_chargecursor.charge; ++ blockposition1 = sculkspreader_a.getPos(); ++ object2intmap.computeInt(blockposition1, (blockposition2, integer) -> { ++ return (integer == null ? 0 : integer) + sculkspreader_a.charge; + }); +- SculkSpreader.ChargeCursor sculkspreader_chargecursor1 = (SculkSpreader.ChargeCursor) map.get(blockpos1); ++ SculkSpreader.ChargeCursor sculkspreader_a1 = (SculkSpreader.ChargeCursor) map.get(blockposition1); + +- if (sculkspreader_chargecursor1 == null) { +- map.put(blockpos1, sculkspreader_chargecursor); +- list.add(sculkspreader_chargecursor); +- } else if (!this.isWorldGeneration() && sculkspreader_chargecursor.charge + sculkspreader_chargecursor1.charge <= 1000) { +- sculkspreader_chargecursor1.mergeWith(sculkspreader_chargecursor); ++ if (sculkspreader_a1 == null) { ++ map.put(blockposition1, sculkspreader_a); ++ list.add(sculkspreader_a); ++ } else if (!this.isWorldGeneration() && sculkspreader_a.charge + sculkspreader_a1.charge <= 1000) { ++ sculkspreader_a1.mergeWith(sculkspreader_a); + } else { +- list.add(sculkspreader_chargecursor); +- if (sculkspreader_chargecursor.charge < sculkspreader_chargecursor1.charge) { +- map.put(blockpos1, sculkspreader_chargecursor); ++ list.add(sculkspreader_a); ++ if (sculkspreader_a.charge < sculkspreader_a1.charge) { ++ map.put(blockposition1, sculkspreader_a); + } + } + } +@@ -191,16 +211,16 @@ + while (objectiterator.hasNext()) { + Entry entry = (Entry) objectiterator.next(); + +- blockpos1 = (BlockPos) entry.getKey(); ++ blockposition1 = (BlockPos) entry.getKey(); + int i = entry.getIntValue(); +- SculkSpreader.ChargeCursor sculkspreader_chargecursor2 = (SculkSpreader.ChargeCursor) map.get(blockpos1); +- Collection collection = sculkspreader_chargecursor2 == null ? null : sculkspreader_chargecursor2.getFacingData(); ++ SculkSpreader.ChargeCursor sculkspreader_a2 = (SculkSpreader.ChargeCursor) map.get(blockposition1); ++ Collection collection = sculkspreader_a2 == null ? null : sculkspreader_a2.getFacingData(); + + if (i > 0 && collection != null) { + int j = (int) (Math.log1p((double) i) / 2.299999952316284D) + 1; + int k = (j << 6) + MultifaceBlock.pack(collection); + +- levelaccessor.levelEvent(3006, blockpos1, k); ++ level.levelEvent(3006, blockposition1, k); + } + } + +@@ -211,8 +231,8 @@ + public static class ChargeCursor { + + private static final ObjectArrayList NON_CORNER_NEIGHBOURS = (ObjectArrayList) Util.make(new ObjectArrayList(18), (objectarraylist) -> { +- Stream stream = BlockPos.betweenClosedStream(new BlockPos(-1, -1, -1), new BlockPos(1, 1, 1)).filter((blockpos) -> { +- return (blockpos.getX() == 0 || blockpos.getY() == 0 || blockpos.getZ() == 0) && !blockpos.equals(BlockPos.ZERO); ++ Stream stream = BlockPos.betweenClosedStream(new BlockPos(-1, -1, -1), new BlockPos(1, 1, 1)).filter((blockposition) -> { ++ return (blockposition.getX() == 0 || blockposition.getY() == 0 || blockposition.getZ() == 0) && !blockposition.equals(BlockPos.ZERO); + }).map(BlockPos::immutable); + + Objects.requireNonNull(objectarraylist); +@@ -229,23 +249,23 @@ + return Sets.newEnumSet(list, Direction.class); + }, Lists::newArrayList); + public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { +- return instance.group(BlockPos.CODEC.fieldOf("pos").forGetter(SculkSpreader.ChargeCursor::getPos), Codec.intRange(0, 1000).fieldOf("charge").orElse(0).forGetter(SculkSpreader.ChargeCursor::getCharge), Codec.intRange(0, 1).fieldOf("decay_delay").orElse(1).forGetter(SculkSpreader.ChargeCursor::getDecayDelay), Codec.intRange(0, Integer.MAX_VALUE).fieldOf("update_delay").orElse(0).forGetter((sculkspreader_chargecursor) -> { +- return sculkspreader_chargecursor.updateDelay; +- }), SculkSpreader.ChargeCursor.DIRECTION_SET.optionalFieldOf("facings").forGetter((sculkspreader_chargecursor) -> { +- return Optional.ofNullable(sculkspreader_chargecursor.getFacingData()); ++ return instance.group(BlockPos.CODEC.fieldOf("pos").forGetter(SculkSpreader.ChargeCursor::getPos), Codec.intRange(0, 1000).fieldOf("charge").orElse(0).forGetter(SculkSpreader.ChargeCursor::getCharge), Codec.intRange(0, 1).fieldOf("decay_delay").orElse(1).forGetter(SculkSpreader.ChargeCursor::getDecayDelay), Codec.intRange(0, Integer.MAX_VALUE).fieldOf("update_delay").orElse(0).forGetter((sculkspreader_a) -> { ++ return sculkspreader_a.updateDelay; ++ }), SculkSpreader.ChargeCursor.DIRECTION_SET.optionalFieldOf("facings").forGetter((sculkspreader_a) -> { ++ return Optional.ofNullable(sculkspreader_a.getFacingData()); + })).apply(instance, SculkSpreader.ChargeCursor::new); + }); + +- private ChargeCursor(BlockPos blockpos, int i, int j, int k, Optional> optional) { +- this.pos = blockpos; +- this.charge = i; +- this.decayDelay = j; +- this.updateDelay = k; +- this.facings = (Set) optional.orElse((Object) null); ++ private ChargeCursor(BlockPos pos, int charge, int decayDelay, int updateDelay, Optional> facings) { ++ this.pos = pos; ++ this.charge = charge; ++ this.decayDelay = decayDelay; ++ this.updateDelay = updateDelay; ++ this.facings = (Set) facings.orElse(null); // CraftBukkit - decompile error + } + +- public ChargeCursor(BlockPos blockpos, int i) { +- this(blockpos, i, 1, 0, Optional.empty()); ++ public ChargeCursor(BlockPos pos, int charge) { ++ this(pos, charge, 1, 0, Optional.empty()); + } + + public BlockPos getPos() { +@@ -265,56 +285,56 @@ + return this.facings; + } + +- private boolean shouldUpdate(LevelAccessor levelaccessor, BlockPos blockpos, boolean flag) { ++ private boolean shouldUpdate(LevelAccessor level, BlockPos pos, boolean isWorldGeneration) { + if (this.charge <= 0) { + return false; +- } else if (flag) { ++ } else if (isWorldGeneration) { + return true; +- } else if (levelaccessor instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) levelaccessor; ++ } else if (level instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) level; + +- return serverlevel.shouldTickBlocksAt(blockpos); ++ return worldserver.shouldTickBlocksAt(pos); + } else { + return false; + } + } + +- public void update(LevelAccessor levelaccessor, BlockPos blockpos, RandomSource randomsource, SculkSpreader sculkspreader, boolean flag) { +- if (this.shouldUpdate(levelaccessor, blockpos, sculkspreader.isWorldGeneration)) { ++ public void update(LevelAccessor level, BlockPos pos, RandomSource random, SculkSpreader spreader, boolean shouldConvertBlocks) { ++ if (this.shouldUpdate(level, pos, spreader.isWorldGeneration)) { + if (this.updateDelay > 0) { + --this.updateDelay; + } else { +- BlockState blockstate = levelaccessor.getBlockState(this.pos); +- SculkBehaviour sculkbehaviour = getBlockBehaviour(blockstate); ++ IBlockData iblockdata = level.getBlockState(this.pos); ++ SculkBehaviour sculkbehaviour = getBlockBehaviour(iblockdata); + +- if (flag && sculkbehaviour.attemptSpreadVein(levelaccessor, this.pos, blockstate, this.facings, sculkspreader.isWorldGeneration())) { ++ if (shouldConvertBlocks && sculkbehaviour.attemptSpreadVein(level, this.pos, iblockdata, this.facings, spreader.isWorldGeneration())) { + if (sculkbehaviour.canChangeBlockStateOnSpread()) { +- blockstate = levelaccessor.getBlockState(this.pos); +- sculkbehaviour = getBlockBehaviour(blockstate); ++ iblockdata = level.getBlockState(this.pos); ++ sculkbehaviour = getBlockBehaviour(iblockdata); + } + +- levelaccessor.playSound((Player) null, this.pos, SoundEvents.SCULK_BLOCK_SPREAD, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.playSound((Player) null, this.pos, SoundEvents.SCULK_BLOCK_SPREAD, SoundSource.BLOCKS, 1.0F, 1.0F); + } + +- this.charge = sculkbehaviour.attemptUseCharge(this, levelaccessor, blockpos, randomsource, sculkspreader, flag); ++ this.charge = sculkbehaviour.attemptUseCharge(this, level, pos, random, spreader, shouldConvertBlocks); + if (this.charge <= 0) { +- sculkbehaviour.onDischarged(levelaccessor, blockstate, this.pos, randomsource); ++ sculkbehaviour.onDischarged(level, iblockdata, this.pos, random); + } else { +- BlockPos blockpos1 = getValidMovementPos(levelaccessor, this.pos, randomsource); ++ BlockPos blockposition1 = getValidMovementPos(level, this.pos, random); + +- if (blockpos1 != null) { +- sculkbehaviour.onDischarged(levelaccessor, blockstate, this.pos, randomsource); +- this.pos = blockpos1.immutable(); +- if (sculkspreader.isWorldGeneration() && !this.pos.closerThan(new Vec3i(blockpos.getX(), this.pos.getY(), blockpos.getZ()), 15.0D)) { ++ if (blockposition1 != null) { ++ sculkbehaviour.onDischarged(level, iblockdata, this.pos, random); ++ this.pos = blockposition1.immutable(); ++ if (spreader.isWorldGeneration() && !this.pos.closerThan(new Vec3i(pos.getX(), this.pos.getY(), pos.getZ()), 15.0D)) { + this.charge = 0; + return; + } + +- blockstate = levelaccessor.getBlockState(blockpos1); ++ iblockdata = level.getBlockState(blockposition1); + } + +- if (blockstate.getBlock() instanceof SculkBehaviour) { +- this.facings = MultifaceBlock.availableFaces(blockstate); ++ if (iblockdata.getBlock() instanceof SculkBehaviour) { ++ this.facings = MultifaceBlock.availableFaces(iblockdata); + } + + this.decayDelay = sculkbehaviour.updateDecayDelay(this.decayDelay); +@@ -324,14 +344,14 @@ + } + } + +- void mergeWith(SculkSpreader.ChargeCursor sculkspreader_chargecursor) { +- this.charge += sculkspreader_chargecursor.charge; +- sculkspreader_chargecursor.charge = 0; +- this.updateDelay = Math.min(this.updateDelay, sculkspreader_chargecursor.updateDelay); ++ void mergeWith(SculkSpreader.ChargeCursor cursor) { ++ this.charge += cursor.charge; ++ cursor.charge = 0; ++ this.updateDelay = Math.min(this.updateDelay, cursor.updateDelay); + } + +- private static SculkBehaviour getBlockBehaviour(BlockState blockstate) { +- Block block = blockstate.getBlock(); ++ private static SculkBehaviour getBlockBehaviour(IBlockData state) { ++ Block block = state.getBlock(); + SculkBehaviour sculkbehaviour; + + if (block instanceof SculkBehaviour) { +@@ -345,50 +365,50 @@ + return sculkbehaviour; + } + +- private static List getRandomizedNonCornerNeighbourOffsets(RandomSource randomsource) { +- return Util.shuffledCopy(SculkSpreader.ChargeCursor.NON_CORNER_NEIGHBOURS, randomsource); ++ private static List getRandomizedNonCornerNeighbourOffsets(RandomSource random) { ++ return Util.shuffledCopy(SculkSpreader.ChargeCursor.NON_CORNER_NEIGHBOURS, random); + } + + @Nullable +- private static BlockPos getValidMovementPos(LevelAccessor levelaccessor, BlockPos blockpos, RandomSource randomsource) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = blockpos.mutable(); +- BlockPos.MutableBlockPos blockpos_mutableblockpos1 = blockpos.mutable(); +- Iterator iterator = getRandomizedNonCornerNeighbourOffsets(randomsource).iterator(); ++ private static BlockPos getValidMovementPos(LevelAccessor level, BlockPos pos, RandomSource random) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition1 = pos.mutable(); ++ Iterator iterator = getRandomizedNonCornerNeighbourOffsets(random).iterator(); + + while (iterator.hasNext()) { +- Vec3i vec3i = (Vec3i) iterator.next(); ++ Vec3i baseblockposition = (Vec3i) iterator.next(); + +- blockpos_mutableblockpos1.setWithOffset(blockpos, vec3i); +- BlockState blockstate = levelaccessor.getBlockState(blockpos_mutableblockpos1); ++ blockposition_mutableblockposition1.setWithOffset(pos, baseblockposition); ++ IBlockData iblockdata = level.getBlockState(blockposition_mutableblockposition1); + +- if (blockstate.getBlock() instanceof SculkBehaviour && isMovementUnobstructed(levelaccessor, blockpos, blockpos_mutableblockpos1)) { +- blockpos_mutableblockpos.set(blockpos_mutableblockpos1); +- if (SculkVeinBlock.hasSubstrateAccess(levelaccessor, blockstate, blockpos_mutableblockpos1)) { ++ if (iblockdata.getBlock() instanceof SculkBehaviour && isMovementUnobstructed(level, pos, blockposition_mutableblockposition1)) { ++ blockposition_mutableblockposition.set(blockposition_mutableblockposition1); ++ if (SculkVeinBlock.hasSubstrateAccess(level, iblockdata, blockposition_mutableblockposition1)) { + break; + } + } + } + +- return blockpos_mutableblockpos.equals(blockpos) ? null : blockpos_mutableblockpos; ++ return blockposition_mutableblockposition.equals(pos) ? null : blockposition_mutableblockposition; + } + +- private static boolean isMovementUnobstructed(LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if (blockpos.distManhattan(blockpos1) == 1) { ++ private static boolean isMovementUnobstructed(LevelAccessor level, BlockPos fromPos, BlockPos toPos) { ++ if (fromPos.distManhattan(toPos) == 1) { + return true; + } else { +- BlockPos blockpos2 = blockpos1.subtract(blockpos); +- Direction direction = Direction.fromAxisAndDirection(Direction.Axis.X, blockpos2.getX() < 0 ? Direction.AxisDirection.NEGATIVE : Direction.AxisDirection.POSITIVE); +- Direction direction1 = Direction.fromAxisAndDirection(Direction.Axis.Y, blockpos2.getY() < 0 ? Direction.AxisDirection.NEGATIVE : Direction.AxisDirection.POSITIVE); +- Direction direction2 = Direction.fromAxisAndDirection(Direction.Axis.Z, blockpos2.getZ() < 0 ? Direction.AxisDirection.NEGATIVE : Direction.AxisDirection.POSITIVE); ++ BlockPos blockposition2 = toPos.subtract(fromPos); ++ Direction enumdirection = Direction.fromAxisAndDirection(Direction.Axis.X, blockposition2.getX() < 0 ? Direction.AxisDirection.NEGATIVE : Direction.AxisDirection.POSITIVE); ++ Direction enumdirection1 = Direction.fromAxisAndDirection(Direction.Axis.Y, blockposition2.getY() < 0 ? Direction.AxisDirection.NEGATIVE : Direction.AxisDirection.POSITIVE); ++ Direction enumdirection2 = Direction.fromAxisAndDirection(Direction.Axis.Z, blockposition2.getZ() < 0 ? Direction.AxisDirection.NEGATIVE : Direction.AxisDirection.POSITIVE); + +- return blockpos2.getX() == 0 ? isUnobstructed(levelaccessor, blockpos, direction1) || isUnobstructed(levelaccessor, blockpos, direction2) : (blockpos2.getY() == 0 ? isUnobstructed(levelaccessor, blockpos, direction) || isUnobstructed(levelaccessor, blockpos, direction2) : isUnobstructed(levelaccessor, blockpos, direction) || isUnobstructed(levelaccessor, blockpos, direction1)); ++ return blockposition2.getX() == 0 ? isUnobstructed(level, fromPos, enumdirection1) || isUnobstructed(level, fromPos, enumdirection2) : (blockposition2.getY() == 0 ? isUnobstructed(level, fromPos, enumdirection) || isUnobstructed(level, fromPos, enumdirection2) : isUnobstructed(level, fromPos, enumdirection) || isUnobstructed(level, fromPos, enumdirection1)); + } + } + +- private static boolean isUnobstructed(LevelAccessor levelaccessor, BlockPos blockpos, Direction direction) { +- BlockPos blockpos1 = blockpos.relative(direction); ++ private static boolean isUnobstructed(LevelAccessor level, BlockPos pos, Direction direction) { ++ BlockPos blockposition1 = pos.relative(direction); + +- return !levelaccessor.getBlockState(blockpos1).isFaceSturdy(levelaccessor, blockpos1, direction.getOpposite()); ++ return !level.getBlockState(blockposition1).isFaceSturdy(level, blockposition1, direction.getOpposite()); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SculkVeinBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SculkVeinBlock.java.patch new file mode 100644 index 0000000000..dfd949b40c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SculkVeinBlock.java.patch @@ -0,0 +1,308 @@ +--- a/net/minecraft/world/level/block/SculkVeinBlock.java ++++ b/net/minecraft/world/level/block/SculkVeinBlock.java +@@ -17,7 +17,7 @@ + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -33,20 +33,18 @@ + private final MultifaceSpreader sameSpaceSpreader; + + @Override +- @Override + public MapCodec codec() { + return SculkVeinBlock.CODEC; + } + +- public SculkVeinBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ public SculkVeinBlock(BlockBehaviour.Properties properties) { ++ super(properties); + this.veinSpreader = new MultifaceSpreader(new SculkVeinBlock.SculkVeinSpreaderConfig(MultifaceSpreader.DEFAULT_SPREAD_ORDER)); + this.sameSpaceSpreader = new MultifaceSpreader(new SculkVeinBlock.SculkVeinSpreaderConfig(new MultifaceSpreader.SpreadType[]{MultifaceSpreader.SpreadType.SAME_POSITION})); +- this.registerDefaultState((BlockState) this.defaultBlockState().setValue(SculkVeinBlock.WATERLOGGED, false)); ++ this.registerDefaultState((IBlockData) this.defaultBlockState().setValue(SculkVeinBlock.WATERLOGGED, false)); + } + + @Override +- @Override + public MultifaceSpreader getSpreader() { + return this.veinSpreader; + } +@@ -55,17 +53,17 @@ + return this.sameSpaceSpreader; + } + +- public static boolean regrow(LevelAccessor levelaccessor, BlockPos blockpos, BlockState blockstate, Collection collection) { ++ public static boolean regrow(LevelAccessor level, BlockPos pos, IBlockData state, Collection directions) { + boolean flag = false; +- BlockState blockstate1 = Blocks.SCULK_VEIN.defaultBlockState(); +- Iterator iterator = collection.iterator(); ++ IBlockData iblockdata1 = Blocks.SCULK_VEIN.defaultBlockState(); ++ Iterator iterator = directions.iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); +- BlockPos blockpos1 = blockpos.relative(direction); ++ Direction enumdirection = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection); + +- if (canAttachTo(levelaccessor, direction, blockpos1, levelaccessor.getBlockState(blockpos1))) { +- blockstate1 = (BlockState) blockstate1.setValue(getFaceProperty(direction), true); ++ if (canAttachTo(level, enumdirection, blockposition1, level.getBlockState(blockposition1))) { ++ iblockdata1 = (IBlockData) iblockdata1.setValue(getFaceProperty(enumdirection), true); + flag = true; + } + } +@@ -73,80 +71,83 @@ + if (!flag) { + return false; + } else { +- if (!blockstate.getFluidState().isEmpty()) { +- blockstate1 = (BlockState) blockstate1.setValue(SculkVeinBlock.WATERLOGGED, true); ++ if (!state.getFluidState().isEmpty()) { ++ iblockdata1 = (IBlockData) iblockdata1.setValue(SculkVeinBlock.WATERLOGGED, true); + } + +- levelaccessor.setBlock(blockpos, blockstate1, 3); ++ level.setBlock(pos, iblockdata1, 3); + return true; + } + } + + @Override +- @Override +- public void onDischarged(LevelAccessor levelaccessor, BlockState blockstate, BlockPos blockpos, RandomSource randomsource) { +- if (blockstate.is((Block) this)) { +- Direction[] adirection = SculkVeinBlock.DIRECTIONS; +- int i = adirection.length; ++ public void onDischarged(LevelAccessor level, IBlockData state, BlockPos pos, RandomSource random) { ++ if (state.is((Block) this)) { ++ Direction[] aenumdirection = SculkVeinBlock.DIRECTIONS; ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; +- BooleanProperty booleanproperty = getFaceProperty(direction); ++ Direction enumdirection = aenumdirection[j]; ++ BooleanProperty blockstateboolean = getFaceProperty(enumdirection); + +- if ((Boolean) blockstate.getValue(booleanproperty) && levelaccessor.getBlockState(blockpos.relative(direction)).is(Blocks.SCULK)) { +- blockstate = (BlockState) blockstate.setValue(booleanproperty, false); ++ if ((Boolean) state.getValue(blockstateboolean) && level.getBlockState(pos.relative(enumdirection)).is(Blocks.SCULK)) { ++ state = (IBlockData) state.setValue(blockstateboolean, false); + } + } + +- if (!hasAnyFace(blockstate)) { +- FluidState fluidstate = levelaccessor.getFluidState(blockpos); ++ if (!hasAnyFace(state)) { ++ FluidState fluid = level.getFluidState(pos); + +- blockstate = (fluidstate.isEmpty() ? Blocks.AIR : Blocks.WATER).defaultBlockState(); ++ state = (fluid.isEmpty() ? Blocks.AIR : Blocks.WATER).defaultBlockState(); + } + +- levelaccessor.setBlock(blockpos, blockstate, 3); +- SculkBehaviour.super.onDischarged(levelaccessor, blockstate, blockpos, randomsource); ++ level.setBlock(pos, state, 3); ++ SculkBehaviour.super.onDischarged(level, state, pos, random); + } + } + + @Override +- @Override +- public int attemptUseCharge(SculkSpreader.ChargeCursor sculkspreader_chargecursor, LevelAccessor levelaccessor, BlockPos blockpos, RandomSource randomsource, SculkSpreader sculkspreader, boolean flag) { +- return flag && this.attemptPlaceSculk(sculkspreader, levelaccessor, sculkspreader_chargecursor.getPos(), randomsource) ? sculkspreader_chargecursor.getCharge() - 1 : (randomsource.nextInt(sculkspreader.chargeDecayRate()) == 0 ? Mth.floor((float) sculkspreader_chargecursor.getCharge() * 0.5F) : sculkspreader_chargecursor.getCharge()); ++ public int attemptUseCharge(SculkSpreader.ChargeCursor cursor, LevelAccessor level, BlockPos pos, RandomSource random, SculkSpreader spreader, boolean shouldConvertBlocks) { ++ // CraftBukkit - add source block ++ return shouldConvertBlocks && this.attemptPlaceSculk(spreader, level, cursor.getPos(), random, pos) ? cursor.getCharge() - 1 : (random.nextInt(spreader.chargeDecayRate()) == 0 ? Mth.floor((float) cursor.getCharge() * 0.5F) : cursor.getCharge()); + } + +- private boolean attemptPlaceSculk(SculkSpreader sculkspreader, LevelAccessor levelaccessor, BlockPos blockpos, RandomSource randomsource) { +- BlockState blockstate = levelaccessor.getBlockState(blockpos); ++ private boolean attemptPlaceSculk(SculkSpreader sculkspreader, LevelAccessor generatoraccess, BlockPos blockposition, RandomSource randomsource, BlockPos sourceBlock) { // CraftBukkit ++ IBlockData iblockdata = generatoraccess.getBlockState(blockposition); + TagKey tagkey = sculkspreader.replaceableBlocks(); + Iterator iterator = Direction.allShuffled(randomsource).iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); ++ Direction enumdirection = (Direction) iterator.next(); + +- if (hasFace(blockstate, direction)) { +- BlockPos blockpos1 = blockpos.relative(direction); +- BlockState blockstate1 = levelaccessor.getBlockState(blockpos1); ++ if (hasFace(iblockdata, enumdirection)) { ++ BlockPos blockposition1 = blockposition.relative(enumdirection); ++ IBlockData iblockdata1 = generatoraccess.getBlockState(blockposition1); + +- if (blockstate1.is(tagkey)) { +- BlockState blockstate2 = Blocks.SCULK.defaultBlockState(); ++ if (iblockdata1.is(tagkey)) { ++ IBlockData iblockdata2 = Blocks.SCULK.defaultBlockState(); + +- levelaccessor.setBlock(blockpos1, blockstate2, 3); +- Block.pushEntitiesUp(blockstate1, blockstate2, levelaccessor, blockpos1); +- levelaccessor.playSound((Player) null, blockpos1, SoundEvents.SCULK_BLOCK_SPREAD, SoundSource.BLOCKS, 1.0F, 1.0F); +- this.veinSpreader.spreadAll(blockstate2, levelaccessor, blockpos1, sculkspreader.isWorldGeneration()); +- Direction direction1 = direction.getOpposite(); +- Direction[] adirection = SculkVeinBlock.DIRECTIONS; +- int i = adirection.length; ++ // CraftBukkit start - Call BlockSpreadEvent ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(generatoraccess, sourceBlock, blockposition1, iblockdata2, 3)) { ++ return false; ++ } ++ // CraftBukkit end ++ Block.pushEntitiesUp(iblockdata1, iblockdata2, generatoraccess, blockposition1); ++ generatoraccess.playSound((Player) null, blockposition1, SoundEvents.SCULK_BLOCK_SPREAD, SoundSource.BLOCKS, 1.0F, 1.0F); ++ this.veinSpreader.spreadAll(iblockdata2, generatoraccess, blockposition1, sculkspreader.isWorldGeneration()); ++ Direction enumdirection1 = enumdirection.getOpposite(); ++ Direction[] aenumdirection = SculkVeinBlock.DIRECTIONS; ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction2 = adirection[j]; ++ Direction enumdirection2 = aenumdirection[j]; + +- if (direction2 != direction1) { +- BlockPos blockpos2 = blockpos1.relative(direction2); +- BlockState blockstate3 = levelaccessor.getBlockState(blockpos2); ++ if (enumdirection2 != enumdirection1) { ++ BlockPos blockposition2 = blockposition1.relative(enumdirection2); ++ IBlockData iblockdata3 = generatoraccess.getBlockState(blockposition2); + +- if (blockstate3.is((Block) this)) { +- this.onDischarged(levelaccessor, blockstate3, blockpos2, randomsource); ++ if (iblockdata3.is((Block) this)) { ++ this.onDischarged(generatoraccess, iblockdata3, blockposition2, randomsource); + } + } + } +@@ -159,17 +160,17 @@ + return false; + } + +- public static boolean hasSubstrateAccess(LevelAccessor levelaccessor, BlockState blockstate, BlockPos blockpos) { +- if (!blockstate.is(Blocks.SCULK_VEIN)) { ++ public static boolean hasSubstrateAccess(LevelAccessor level, IBlockData state, BlockPos pos) { ++ if (!state.is(Blocks.SCULK_VEIN)) { + return false; + } else { +- Direction[] adirection = SculkVeinBlock.DIRECTIONS; +- int i = adirection.length; ++ Direction[] aenumdirection = SculkVeinBlock.DIRECTIONS; ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; ++ Direction enumdirection = aenumdirection[j]; + +- if (hasFace(blockstate, direction) && levelaccessor.getBlockState(blockpos.relative(direction)).is(BlockTags.SCULK_REPLACEABLE)) { ++ if (hasFace(state, enumdirection) && level.getBlockState(pos.relative(enumdirection)).is(BlockTags.SCULK_REPLACEABLE)) { + return true; + } + } +@@ -179,75 +180,68 @@ + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if ((Boolean) blockstate.getValue(SculkVeinBlock.WATERLOGGED)) { +- levelaccessor.scheduleTick(blockpos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(levelaccessor)); ++ public IBlockData updateShape(IBlockData state, Direction direction, IBlockData neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { ++ if ((Boolean) state.getValue(SculkVeinBlock.WATERLOGGED)) { ++ level.scheduleTick(pos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, direction, neighborState, level, pos, neighborPos); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- super.createBlockStateDefinition(statedefinition_builder); +- statedefinition_builder.add(SculkVeinBlock.WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ super.createBlockStateDefinition(builder); ++ builder.add(SculkVeinBlock.WATERLOGGED); + } + + @Override +- @Override +- public boolean canBeReplaced(BlockState blockstate, BlockPlaceContext blockplacecontext) { +- return !blockplacecontext.getItemInHand().is(Items.SCULK_VEIN) || super.canBeReplaced(blockstate, blockplacecontext); ++ public boolean canBeReplaced(IBlockData state, BlockPlaceContext useContext) { ++ return !useContext.getItemInHand().is(Items.SCULK_VEIN) || super.canBeReplaced(state, useContext); + } + + @Override +- @Override +- public FluidState getFluidState(BlockState blockstate) { +- return (Boolean) blockstate.getValue(SculkVeinBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(blockstate); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(SculkVeinBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + private class SculkVeinSpreaderConfig extends MultifaceSpreader.DefaultSpreaderConfig { + + private final MultifaceSpreader.SpreadType[] spreadTypes; + +- public SculkVeinSpreaderConfig(MultifaceSpreader.SpreadType... amultifacespreader_spreadtype) { ++ public SculkVeinSpreaderConfig(MultifaceSpreader.SpreadType... amultifacespreader_e) { + super(SculkVeinBlock.this); +- this.spreadTypes = amultifacespreader_spreadtype; ++ this.spreadTypes = amultifacespreader_e; + } + + @Override +- @Override +- public boolean stateCanBeReplaced(BlockGetter blockgetter, BlockPos blockpos, BlockPos blockpos1, Direction direction, BlockState blockstate) { +- BlockState blockstate1 = blockgetter.getBlockState(blockpos1.relative(direction)); ++ public boolean stateCanBeReplaced(BlockGetter level, BlockPos pos, BlockPos spreadPos, Direction direction, IBlockData state) { ++ IBlockData iblockdata1 = level.getBlockState(spreadPos.relative(direction)); + +- if (!blockstate1.is(Blocks.SCULK) && !blockstate1.is(Blocks.SCULK_CATALYST) && !blockstate1.is(Blocks.MOVING_PISTON)) { +- if (blockpos.distManhattan(blockpos1) == 2) { +- BlockPos blockpos2 = blockpos.relative(direction.getOpposite()); ++ if (!iblockdata1.is(Blocks.SCULK) && !iblockdata1.is(Blocks.SCULK_CATALYST) && !iblockdata1.is(Blocks.MOVING_PISTON)) { ++ if (pos.distManhattan(spreadPos) == 2) { ++ BlockPos blockposition2 = pos.relative(direction.getOpposite()); + +- if (blockgetter.getBlockState(blockpos2).isFaceSturdy(blockgetter, blockpos2, direction)) { ++ if (level.getBlockState(blockposition2).isFaceSturdy(level, blockposition2, direction)) { + return false; + } + } + +- FluidState fluidstate = blockstate.getFluidState(); ++ FluidState fluid = state.getFluidState(); + +- return !fluidstate.isEmpty() && !fluidstate.is((Fluid) Fluids.WATER) ? false : (blockstate.is(BlockTags.FIRE) ? false : blockstate.canBeReplaced() || super.stateCanBeReplaced(blockgetter, blockpos, blockpos1, direction, blockstate)); ++ return !fluid.isEmpty() && !fluid.is((Fluid) Fluids.WATER) ? false : (state.is(BlockTags.FIRE) ? false : state.canBeReplaced() || super.stateCanBeReplaced(level, pos, spreadPos, direction, state)); + } else { + return false; + } + } + + @Override +- @Override + public MultifaceSpreader.SpreadType[] getSpreadTypes() { + return this.spreadTypes; + } + + @Override +- @Override +- public boolean isOtherBlockValidAsSource(BlockState blockstate) { +- return !blockstate.is(Blocks.SCULK_VEIN); ++ public boolean isOtherBlockValidAsSource(IBlockData otherBlock) { ++ return !otherBlock.is(Blocks.SCULK_VEIN); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SignBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SignBlock.java.patch new file mode 100644 index 0000000000..3f47c78fa0 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SignBlock.java.patch @@ -0,0 +1,222 @@ +--- a/net/minecraft/world/level/block/SignBlock.java ++++ b/net/minecraft/world/level/block/SignBlock.java +@@ -7,10 +7,10 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.network.chat.CommonComponents; +-import net.minecraft.network.chat.contents.PlainTextContents; ++import net.minecraft.network.chat.contents.LiteralContents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Item; +@@ -25,7 +25,7 @@ + import net.minecraft.world.level.block.entity.SignBlockEntity; + import net.minecraft.world.level.block.entity.SignText; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.block.state.properties.WoodType; +@@ -45,47 +45,41 @@ + protected static final VoxelShape SHAPE = Block.box(4.0D, 0.0D, 4.0D, 12.0D, 16.0D, 12.0D); + private final WoodType type; + +- protected SignBlock(WoodType woodtype, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.type = woodtype; ++ protected SignBlock(WoodType blockpropertywood, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info); ++ this.type = blockpropertywood; + } + + @Override +- @Override + protected abstract MapCodec codec(); + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if ((Boolean) blockstate.getValue(SignBlock.WATERLOGGED)) { +- levelaccessor.scheduleTick(blockpos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(levelaccessor)); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if ((Boolean) state.getValue(SignBlock.WATERLOGGED)) { ++ level.scheduleTick(currentPos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return SignBlock.SHAPE; + } + + @Override +- @Override +- public boolean isPossibleToRespawnInThis(BlockState blockstate) { ++ public boolean isPossibleToRespawnInThis(IBlockData state) { + return true; + } + + @Override +- @Override +- public BlockEntity newBlockEntity(BlockPos blockpos, BlockState blockstate) { +- return new SignBlockEntity(blockpos, blockstate); ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ return new SignBlockEntity(pos, state); + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ ItemStack itemstack = player.getItemInHand(hand); + Item item = itemstack.getItem(); + Item item1 = itemstack.getItem(); + SignApplicator signapplicator; +@@ -100,37 +94,37 @@ + + SignApplicator signapplicator2 = signapplicator; + boolean flag = signapplicator2 != null && player.mayBuild(); +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof SignBlockEntity) { +- SignBlockEntity signblockentity = (SignBlockEntity) blockentity; ++ if (tileentity instanceof SignBlockEntity) { ++ SignBlockEntity tileentitysign = (SignBlockEntity) tileentity; + + if (!level.isClientSide) { +- boolean flag1 = signblockentity.isFacingFrontText(player); +- SignText signtext = signblockentity.getText(flag1); +- boolean flag2 = signblockentity.executeClickCommandsIfPresent(player, level, blockpos, flag1); ++ boolean flag1 = tileentitysign.isFacingFrontText(player); ++ SignText signtext = tileentitysign.getText(flag1); ++ boolean flag2 = tileentitysign.executeClickCommandsIfPresent(player, level, pos, flag1); + +- if (signblockentity.isWaxed()) { +- level.playSound((Player) null, signblockentity.getBlockPos(), signblockentity.getSignInteractionFailedSoundEvent(), SoundSource.BLOCKS); ++ if (tileentitysign.isWaxed()) { ++ level.playSound((Player) null, tileentitysign.getBlockPos(), tileentitysign.getSignInteractionFailedSoundEvent(), SoundSource.BLOCKS); + return this.getInteractionResult(flag); +- } else if (flag && !this.otherPlayerIsEditingSign(player, signblockentity) && signapplicator2.canApplyToSign(signtext, player) && signapplicator2.tryApplyToSign(level, signblockentity, flag1, player)) { ++ } else if (flag && !this.otherPlayerIsEditingSign(player, tileentitysign) && signapplicator2.canApplyToSign(signtext, player) && signapplicator2.tryApplyToSign(level, tileentitysign, flag1, player)) { + if (!player.isCreative()) { + itemstack.shrink(1); + } + +- level.gameEvent(GameEvent.BLOCK_CHANGE, signblockentity.getBlockPos(), GameEvent.Context.of(player, signblockentity.getBlockState())); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, tileentitysign.getBlockPos(), GameEvent.Context.of(player, tileentitysign.getBlockState())); + player.awardStat(Stats.ITEM_USED.get(item)); + return InteractionResult.SUCCESS; + } else if (flag2) { + return InteractionResult.SUCCESS; +- } else if (!this.otherPlayerIsEditingSign(player, signblockentity) && player.mayBuild() && this.hasEditableText(player, signblockentity, flag1)) { +- this.openTextEdit(player, signblockentity, flag1); ++ } else if (!this.otherPlayerIsEditingSign(player, tileentitysign) && player.mayBuild() && this.hasEditableText(player, tileentitysign, flag1)) { ++ this.openTextEdit(player, tileentitysign, flag1, org.bukkit.event.player.PlayerSignOpenEvent.Cause.INTERACT); // CraftBukkit + return this.getInteractionResult(flag); + } else { + return InteractionResult.PASS; + } + } else { +- return !flag && !signblockentity.isWaxed() ? InteractionResult.CONSUME : InteractionResult.SUCCESS; ++ return !flag && !tileentitysign.isWaxed() ? InteractionResult.CONSUME : InteractionResult.SUCCESS; + } + } else { + return InteractionResult.PASS; +@@ -141,24 +135,23 @@ + return flag ? InteractionResult.PASS : InteractionResult.SUCCESS; + } + +- private boolean hasEditableText(Player player, SignBlockEntity signblockentity, boolean flag) { +- SignText signtext = signblockentity.getText(flag); ++ private boolean hasEditableText(Player player, SignBlockEntity signEntity, boolean isFrontText) { ++ SignText signtext = signEntity.getText(isFrontText); + +- return Arrays.stream(signtext.getMessages(player.isTextFilteringEnabled())).allMatch((component) -> { +- return component.equals(CommonComponents.EMPTY) || component.getContents() instanceof PlainTextContents; ++ return Arrays.stream(signtext.getMessages(player.isTextFilteringEnabled())).allMatch((ichatbasecomponent) -> { ++ return ichatbasecomponent.equals(CommonComponents.EMPTY) || ichatbasecomponent.getContents() instanceof LiteralContents; + }); + } + +- public abstract float getYRotationDegrees(BlockState state); ++ public abstract float getYRotationDegrees(IBlockData state); + +- public Vec3 getSignHitboxCenterPosition(BlockState blockstate) { ++ public Vec3 getSignHitboxCenterPosition(IBlockData state) { + return new Vec3(0.5D, 0.5D, 0.5D); + } + + @Override +- @Override +- public FluidState getFluidState(BlockState blockstate) { +- return (Boolean) blockstate.getValue(SignBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(blockstate); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(SignBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + public WoodType type() { +@@ -166,32 +159,40 @@ + } + + public static WoodType getWoodType(Block block) { +- WoodType woodtype; ++ WoodType blockpropertywood; + + if (block instanceof SignBlock) { +- woodtype = ((SignBlock) block).type(); ++ blockpropertywood = ((SignBlock) block).type(); + } else { +- woodtype = WoodType.OAK; ++ blockpropertywood = WoodType.OAK; + } + +- return woodtype; ++ return blockpropertywood; + } + +- public void openTextEdit(Player player, SignBlockEntity signblockentity, boolean flag) { +- signblockentity.setAllowedPlayerEditor(player.getUUID()); +- player.openTextEdit(signblockentity, flag); ++ public void openTextEdit(Player player, SignBlockEntity signEntity, boolean isFrontText) { ++ // Craftbukkit start ++ openTextEdit(player, signEntity, isFrontText, org.bukkit.event.player.PlayerSignOpenEvent.Cause.UNKNOWN); + } + +- private boolean otherPlayerIsEditingSign(Player player, SignBlockEntity signblockentity) { +- UUID uuid = signblockentity.getPlayerWhoMayEdit(); ++ public void openTextEdit(Player entityhuman, SignBlockEntity tileentitysign, boolean flag, org.bukkit.event.player.PlayerSignOpenEvent.Cause cause) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerSignOpenEvent(entityhuman, tileentitysign, flag, cause)) { ++ return; ++ } ++ // Craftbukkit end ++ tileentitysign.setAllowedPlayerEditor(entityhuman.getUUID()); ++ entityhuman.openTextEdit(tileentitysign, flag); ++ } + ++ private boolean otherPlayerIsEditingSign(Player player, SignBlockEntity signEntity) { ++ UUID uuid = signEntity.getPlayerWhoMayEdit(); ++ + return uuid != null && !uuid.equals(player.getUUID()); + } + + @Nullable + @Override +- @Override +- public BlockEntityTicker getTicker(Level level, BlockState blockstate, BlockEntityType blockentitytype) { +- return createTickerHelper(blockentitytype, BlockEntityType.SIGN, SignBlockEntity::tick); ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { ++ return null; // Craftbukkit - remove unnecessary sign ticking + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SnowLayerBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SnowLayerBlock.java.patch new file mode 100644 index 0000000000..56ffa70460 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SnowLayerBlock.java.patch @@ -0,0 +1,178 @@ +--- a/net/minecraft/world/level/block/SnowLayerBlock.java ++++ b/net/minecraft/world/level/block/SnowLayerBlock.java +@@ -9,15 +9,15 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.world.item.context.BlockPlaceContext; + import net.minecraft.world.level.BlockGetter; ++import net.minecraft.world.level.EnumSkyBlock; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; +-import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; +@@ -31,22 +31,20 @@ + public static final int HEIGHT_IMPASSABLE = 5; + + @Override +- @Override + public MapCodec codec() { + return SnowLayerBlock.CODEC; + } + +- protected SnowLayerBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(SnowLayerBlock.LAYERS, 1)); ++ protected SnowLayerBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(SnowLayerBlock.LAYERS, 1)); + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { +- switch (pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { ++ switch (type) { + case LAND: +- return (Integer) blockstate.getValue(SnowLayerBlock.LAYERS) < 5; ++ return (Integer) state.getValue(SnowLayerBlock.LAYERS) < 5; + case WATER: + return false; + case AIR: +@@ -57,91 +55,84 @@ + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return SnowLayerBlock.SHAPE_BY_LAYER[(Integer) blockstate.getValue(SnowLayerBlock.LAYERS)]; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return SnowLayerBlock.SHAPE_BY_LAYER[(Integer) state.getValue(SnowLayerBlock.LAYERS)]; + } + + @Override +- @Override +- public VoxelShape getCollisionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return SnowLayerBlock.SHAPE_BY_LAYER[(Integer) blockstate.getValue(SnowLayerBlock.LAYERS) - 1]; ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return SnowLayerBlock.SHAPE_BY_LAYER[(Integer) state.getValue(SnowLayerBlock.LAYERS) - 1]; + } + + @Override +- @Override +- public VoxelShape getBlockSupportShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return SnowLayerBlock.SHAPE_BY_LAYER[(Integer) blockstate.getValue(SnowLayerBlock.LAYERS)]; ++ public VoxelShape getBlockSupportShape(IBlockData state, BlockGetter reader, BlockPos pos) { ++ return SnowLayerBlock.SHAPE_BY_LAYER[(Integer) state.getValue(SnowLayerBlock.LAYERS)]; + } + + @Override +- @Override +- public VoxelShape getVisualShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return SnowLayerBlock.SHAPE_BY_LAYER[(Integer) blockstate.getValue(SnowLayerBlock.LAYERS)]; ++ public VoxelShape getVisualShape(IBlockData state, BlockGetter reader, BlockPos pos, CollisionContext context) { ++ return SnowLayerBlock.SHAPE_BY_LAYER[(Integer) state.getValue(SnowLayerBlock.LAYERS)]; + } + + @Override +- @Override +- public boolean useShapeForLightOcclusion(BlockState blockstate) { ++ public boolean useShapeForLightOcclusion(IBlockData state) { + return true; + } + + @Override +- @Override +- public float getShadeBrightness(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return (Integer) blockstate.getValue(SnowLayerBlock.LAYERS) == 8 ? 0.2F : 1.0F; ++ public float getShadeBrightness(IBlockData state, BlockGetter level, BlockPos pos) { ++ return (Integer) state.getValue(SnowLayerBlock.LAYERS) == 8 ? 0.2F : 1.0F; + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- BlockState blockstate1 = levelreader.getBlockState(blockpos.below()); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ IBlockData iblockdata1 = level.getBlockState(pos.below()); + +- return blockstate1.is(BlockTags.SNOW_LAYER_CANNOT_SURVIVE_ON) ? false : (blockstate1.is(BlockTags.SNOW_LAYER_CAN_SURVIVE_ON) ? true : Block.isFaceFull(blockstate1.getCollisionShape(levelreader, blockpos.below()), Direction.UP) || blockstate1.is((Block) this) && (Integer) blockstate1.getValue(SnowLayerBlock.LAYERS) == 8); ++ return iblockdata1.is(BlockTags.SNOW_LAYER_CANNOT_SURVIVE_ON) ? false : (iblockdata1.is(BlockTags.SNOW_LAYER_CAN_SURVIVE_ON) ? true : Block.isFaceFull(iblockdata1.getCollisionShape(level, pos.below()), Direction.UP) || iblockdata1.is((Block) this) && (Integer) iblockdata1.getValue(SnowLayerBlock.LAYERS) == 8); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- return !blockstate.canSurvive(levelaccessor, blockpos) ? Blocks.AIR.defaultBlockState() : super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ return !state.canSurvive(level, currentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (serverlevel.getBrightness(LightLayer.BLOCK, blockpos) > 11) { +- dropResources(blockstate, serverlevel, blockpos); +- serverlevel.removeBlock(blockpos, false); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (level.getBrightness(EnumSkyBlock.BLOCK, pos) > 11) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.AIR.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ dropResources(state, level, pos); ++ level.removeBlock(pos, false); + } + + } + + @Override +- @Override +- public boolean canBeReplaced(BlockState blockstate, BlockPlaceContext blockplacecontext) { +- int i = (Integer) blockstate.getValue(SnowLayerBlock.LAYERS); ++ public boolean canBeReplaced(IBlockData state, BlockPlaceContext useContext) { ++ int i = (Integer) state.getValue(SnowLayerBlock.LAYERS); + +- return blockplacecontext.getItemInHand().is(this.asItem()) && i < 8 ? (blockplacecontext.replacingClickedOnBlock() ? blockplacecontext.getClickedFace() == Direction.UP : true) : i == 1; ++ return useContext.getItemInHand().is(this.asItem()) && i < 8 ? (useContext.replacingClickedOnBlock() ? useContext.getClickedFace() == Direction.UP : true) : i == 1; + } + + @Nullable + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- BlockState blockstate = blockplacecontext.getLevel().getBlockState(blockplacecontext.getClickedPos()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ IBlockData iblockdata = context.getLevel().getBlockState(context.getClickedPos()); + +- if (blockstate.is((Block) this)) { +- int i = (Integer) blockstate.getValue(SnowLayerBlock.LAYERS); ++ if (iblockdata.is((Block) this)) { ++ int i = (Integer) iblockdata.getValue(SnowLayerBlock.LAYERS); + +- return (BlockState) blockstate.setValue(SnowLayerBlock.LAYERS, Math.min(8, i + 1)); ++ return (IBlockData) iblockdata.setValue(SnowLayerBlock.LAYERS, Math.min(8, i + 1)); + } else { +- return super.getStateForPlacement(blockplacecontext); ++ return super.getStateForPlacement(context); + } + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(SnowLayerBlock.LAYERS); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(SnowLayerBlock.LAYERS); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SpawnerBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SpawnerBlock.java.patch new file mode 100644 index 0000000000..e27a18b7d9 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SpawnerBlock.java.patch @@ -0,0 +1,83 @@ +--- a/net/minecraft/world/level/block/SpawnerBlock.java ++++ b/net/minecraft/world/level/block/SpawnerBlock.java +@@ -16,57 +16,59 @@ + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.SpawnerBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public class SpawnerBlock extends BaseEntityBlock { + + public static final MapCodec CODEC = simpleCodec(SpawnerBlock::new); + + @Override +- @Override + public MapCodec codec() { + return SpawnerBlock.CODEC; + } + +- protected SpawnerBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ protected SpawnerBlock(BlockBehaviour.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public BlockEntity newBlockEntity(BlockPos blockpos, BlockState blockstate) { +- return new SpawnerBlockEntity(blockpos, blockstate); ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ return new SpawnerBlockEntity(pos, state); + } + + @Nullable + @Override ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { ++ return createTickerHelper(blockEntityType, BlockEntityType.MOB_SPAWNER, level.isClientSide ? SpawnerBlockEntity::clientTick : SpawnerBlockEntity::serverTick); ++ } ++ + @Override +- public BlockEntityTicker getTicker(Level level, BlockState blockstate, BlockEntityType blockentitytype) { +- return createTickerHelper(blockentitytype, BlockEntityType.MOB_SPAWNER, level.isClientSide ? SpawnerBlockEntity::clientTick : SpawnerBlockEntity::serverTick); ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ super.spawnAfterBreak(state, level, pos, stack, dropExperience); ++ // CraftBukkit start - Delegate to getExpDrop + } + + @Override +- @Override +- public void spawnAfterBreak(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, ItemStack itemstack, boolean flag) { +- super.spawnAfterBreak(blockstate, serverlevel, blockpos, itemstack, flag); ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { + if (flag) { +- int i = 15 + serverlevel.random.nextInt(15) + serverlevel.random.nextInt(15); ++ int i = 15 + worldserver.random.nextInt(15) + worldserver.random.nextInt(15); + +- this.popExperience(serverlevel, blockpos, i); ++ // this.popExperience(worldserver, blockposition, i); ++ return i; + } + ++ return 0; ++ // CraftBukkit end + } + + @Override +- @Override +- public RenderShape getRenderShape(BlockState blockstate) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Override +- @Override +- public void appendHoverText(ItemStack itemstack, @Nullable BlockGetter blockgetter, List list, TooltipFlag tooltipflag) { +- super.appendHoverText(itemstack, blockgetter, list, tooltipflag); +- Spawner.appendHoverText(itemstack, list, "SpawnData"); ++ public void appendHoverText(ItemStack stack, @Nullable BlockGetter level, List tooltip, TooltipFlag flag) { ++ super.appendHoverText(stack, level, tooltip, flag); ++ Spawner.appendHoverText(stack, tooltip, "SpawnData"); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SpongeBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SpongeBlock.java.patch new file mode 100644 index 0000000000..4dc39bd7b6 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SpongeBlock.java.patch @@ -0,0 +1,177 @@ +--- a/net/minecraft/world/level/block/SpongeBlock.java ++++ b/net/minecraft/world/level/block/SpongeBlock.java +@@ -10,8 +10,14 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.util.BlockStateListPopulator; ++import org.bukkit.event.block.SpongeAbsorbEvent; ++// CraftBukkit end + + public class SpongeBlock extends Block { + +@@ -21,85 +27,122 @@ + private static final Direction[] ALL_DIRECTIONS = Direction.values(); + + @Override +- @Override + public MapCodec codec() { + return SpongeBlock.CODEC; + } + +- protected SpongeBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ protected SpongeBlock(BlockBehaviour.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!blockstate1.is(blockstate.getBlock())) { +- this.tryAbsorbWater(level, blockpos); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ if (!oldState.is(state.getBlock())) { ++ this.tryAbsorbWater(level, pos); + } + } + + @Override +- @Override +- public void neighborChanged(BlockState blockstate, Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { +- this.tryAbsorbWater(level, blockpos); +- super.neighborChanged(blockstate, level, blockpos, block, blockpos1, flag); ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ this.tryAbsorbWater(level, pos); ++ super.neighborChanged(state, level, pos, block, fromPos, isMoving); + } + +- protected void tryAbsorbWater(Level level, BlockPos blockpos) { +- if (this.removeWaterBreadthFirstSearch(level, blockpos)) { +- level.setBlock(blockpos, Blocks.WET_SPONGE.defaultBlockState(), 2); +- level.playSound((Player) null, blockpos, SoundEvents.SPONGE_ABSORB, SoundSource.BLOCKS, 1.0F, 1.0F); ++ protected void tryAbsorbWater(Level level, BlockPos pos) { ++ if (this.removeWaterBreadthFirstSearch(level, pos)) { ++ level.setBlock(pos, Blocks.WET_SPONGE.defaultBlockState(), 2); ++ level.playSound((Player) null, pos, SoundEvents.SPONGE_ABSORB, SoundSource.BLOCKS, 1.0F, 1.0F); + } + + } + +- private boolean removeWaterBreadthFirstSearch(Level level, BlockPos blockpos) { +- return BlockPos.breadthFirstTraversal(blockpos, 6, 65, (blockpos1, consumer) -> { +- Direction[] adirection = SpongeBlock.ALL_DIRECTIONS; +- int i = adirection.length; ++ private boolean removeWaterBreadthFirstSearch(Level level, BlockPos pos) { ++ BlockStateListPopulator blockList = new BlockStateListPopulator(level); // CraftBukkit - Use BlockStateListPopulator ++ BlockPos.breadthFirstTraversal(pos, 6, 65, (blockposition1, consumer) -> { ++ Direction[] aenumdirection = SpongeBlock.ALL_DIRECTIONS; ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; ++ Direction enumdirection = aenumdirection[j]; + +- consumer.accept(blockpos1.relative(direction)); ++ consumer.accept(blockposition1.relative(enumdirection)); + } + +- }, (blockpos1) -> { +- if (blockpos1.equals(blockpos)) { ++ }, (blockposition1) -> { ++ if (blockposition1.equals(pos)) { + return true; + } else { +- BlockState blockstate = level.getBlockState(blockpos1); +- FluidState fluidstate = level.getFluidState(blockpos1); ++ // CraftBukkit start ++ IBlockData iblockdata = blockList.getBlockState(blockposition1); ++ FluidState fluid = blockList.getFluidState(blockposition1); ++ // CraftBukkit end + +- if (!fluidstate.is(FluidTags.WATER)) { ++ if (!fluid.is(FluidTags.WATER)) { + return false; + } else { +- Block block = blockstate.getBlock(); ++ Block block = iblockdata.getBlock(); + + if (block instanceof BucketPickup) { +- BucketPickup bucketpickup = (BucketPickup) block; ++ BucketPickup ifluidsource = (BucketPickup) block; + +- if (!bucketpickup.pickupBlock((Player) null, level, blockpos1, blockstate).isEmpty()) { ++ if (!ifluidsource.pickupBlock((Player) null, blockList, blockposition1, iblockdata).isEmpty()) { // CraftBukkit + return true; + } + } + +- if (blockstate.getBlock() instanceof LiquidBlock) { +- level.setBlock(blockpos1, Blocks.AIR.defaultBlockState(), 3); ++ if (iblockdata.getBlock() instanceof LiquidBlock) { ++ blockList.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3); // CraftBukkit + } else { +- if (!blockstate.is(Blocks.KELP) && !blockstate.is(Blocks.KELP_PLANT) && !blockstate.is(Blocks.SEAGRASS) && !blockstate.is(Blocks.TALL_SEAGRASS)) { ++ if (!iblockdata.is(Blocks.KELP) && !iblockdata.is(Blocks.KELP_PLANT) && !iblockdata.is(Blocks.SEAGRASS) && !iblockdata.is(Blocks.TALL_SEAGRASS)) { + return false; + } + +- BlockEntity blockentity = blockstate.hasBlockEntity() ? level.getBlockEntity(blockpos1) : null; ++ // CraftBukkit start ++ // TileEntity tileentity = iblockdata.hasBlockEntity() ? world.getBlockEntity(blockposition1) : null; + +- dropResources(blockstate, level, blockpos1, blockentity); +- level.setBlock(blockpos1, Blocks.AIR.defaultBlockState(), 3); ++ // dropResources(iblockdata, world, blockposition1, tileentity); ++ blockList.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3); ++ // CraftBukkit end + } + + return true; + } + } +- }) > 1; ++ }); ++ // CraftBukkit start ++ List blocks = blockList.getList(); // Is a clone ++ if (!blocks.isEmpty()) { ++ final org.bukkit.block.Block bblock = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ ++ SpongeAbsorbEvent event = new SpongeAbsorbEvent(bblock, (List) (List) blocks); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ for (CraftBlockState block : blocks) { ++ BlockPos blockposition1 = block.getPosition(); ++ IBlockData iblockdata = level.getBlockState(blockposition1); ++ FluidState fluid = level.getFluidState(blockposition1); ++ ++ if (fluid.is(FluidTags.WATER)) { ++ if (iblockdata.getBlock() instanceof BucketPickup && !((BucketPickup) iblockdata.getBlock()).pickupBlock((Player) null, blockList, blockposition1, iblockdata).isEmpty()) { ++ // NOP ++ } else if (iblockdata.getBlock() instanceof LiquidBlock) { ++ // NOP ++ } else if (iblockdata.is(Blocks.KELP) || iblockdata.is(Blocks.KELP_PLANT) || iblockdata.is(Blocks.SEAGRASS) || iblockdata.is(Blocks.TALL_SEAGRASS)) { ++ BlockEntity tileentity = iblockdata.hasBlockEntity() ? level.getBlockEntity(blockposition1) : null; ++ ++ dropResources(iblockdata, level, blockposition1, tileentity); ++ } ++ } ++ level.setBlock(blockposition1, block.getHandle(), block.getFlag()); ++ } ++ ++ return true; ++ } ++ return false; ++ // CraftBukkit end + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java.patch new file mode 100644 index 0000000000..9d46150c7a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java.patch @@ -0,0 +1,83 @@ +--- a/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java ++++ b/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java +@@ -8,54 +8,57 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.lighting.LightEngine; + + public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock { + +- protected SpreadingSnowyDirtBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ protected SpreadingSnowyDirtBlock(BlockBehaviour.Properties properties) { ++ super(properties); + } + +- private static boolean canBeGrass(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- BlockPos blockpos1 = blockpos.above(); +- BlockState blockstate1 = levelreader.getBlockState(blockpos1); ++ private static boolean canBeGrass(IBlockData state, LevelReader levelReader, BlockPos pos) { ++ BlockPos blockposition1 = pos.above(); ++ IBlockData iblockdata1 = levelReader.getBlockState(blockposition1); + +- if (blockstate1.is(Blocks.SNOW) && (Integer) blockstate1.getValue(SnowLayerBlock.LAYERS) == 1) { ++ if (iblockdata1.is(Blocks.SNOW) && (Integer) iblockdata1.getValue(SnowLayerBlock.LAYERS) == 1) { + return true; +- } else if (blockstate1.getFluidState().getAmount() == 8) { ++ } else if (iblockdata1.getFluidState().getAmount() == 8) { + return false; + } else { +- int i = LightEngine.getLightBlockInto(levelreader, blockstate, blockpos, blockstate1, blockpos1, Direction.UP, blockstate1.getLightBlock(levelreader, blockpos1)); ++ int i = LightEngine.getLightBlockInto(levelReader, state, pos, iblockdata1, blockposition1, Direction.UP, iblockdata1.getLightBlock(levelReader, blockposition1)); + +- return i < levelreader.getMaxLightLevel(); ++ return i < levelReader.getMaxLightLevel(); + } + } + + @Override +- @Override + protected abstract MapCodec codec(); + +- private static boolean canPropagate(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- BlockPos blockpos1 = blockpos.above(); ++ private static boolean canPropagate(IBlockData state, LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.above(); + +- return canBeGrass(blockstate, levelreader, blockpos) && !levelreader.getFluidState(blockpos1).is(FluidTags.WATER); ++ return canBeGrass(state, level, pos) && !level.getFluidState(blockposition1).is(FluidTags.WATER); + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (!canBeGrass(blockstate, serverlevel, blockpos)) { +- serverlevel.setBlockAndUpdate(blockpos, Blocks.DIRT.defaultBlockState()); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (!canBeGrass(state, level, pos)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlockAndUpdate(pos, Blocks.DIRT.defaultBlockState()); + } else { +- if (serverlevel.getMaxLocalRawBrightness(blockpos.above()) >= 9) { +- BlockState blockstate1 = this.defaultBlockState(); ++ if (level.getMaxLocalRawBrightness(pos.above()) >= 9) { ++ IBlockData iblockdata1 = this.defaultBlockState(); + + for (int i = 0; i < 4; ++i) { +- BlockPos blockpos1 = blockpos.offset(randomsource.nextInt(3) - 1, randomsource.nextInt(5) - 3, randomsource.nextInt(3) - 1); ++ BlockPos blockposition1 = pos.offset(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1); + +- if (serverlevel.getBlockState(blockpos1).is(Blocks.DIRT) && canPropagate(blockstate1, serverlevel, blockpos1)) { +- serverlevel.setBlockAndUpdate(blockpos1, (BlockState) blockstate1.setValue(SpreadingSnowyDirtBlock.SNOWY, serverlevel.getBlockState(blockpos1.above()).is(Blocks.SNOW))); ++ if (level.getBlockState(blockposition1).is(Blocks.DIRT) && canPropagate(iblockdata1, level, blockposition1)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition1, (IBlockData) iblockdata1.setValue(SpreadingSnowyDirtBlock.SNOWY, level.getBlockState(blockposition1.above()).is(Blocks.SNOW))); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/StemBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/StemBlock.java.patch new file mode 100644 index 0000000000..02f9b900e7 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/StemBlock.java.patch @@ -0,0 +1,174 @@ +--- a/net/minecraft/world/level/block/StemBlock.java ++++ b/net/minecraft/world/level/block/StemBlock.java +@@ -16,26 +16,27 @@ + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.BlockGetter; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class StemBlock extends BushBlock implements BonemealableBlock { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- return instance.group(ResourceKey.codec(Registries.BLOCK).fieldOf("fruit").forGetter((stemblock) -> { +- return stemblock.fruit; +- }), ResourceKey.codec(Registries.BLOCK).fieldOf("attached_stem").forGetter((stemblock) -> { +- return stemblock.attachedStem; +- }), ResourceKey.codec(Registries.ITEM).fieldOf("seed").forGetter((stemblock) -> { +- return stemblock.seed; ++ return instance.group(ResourceKey.codec(Registries.BLOCK).fieldOf("fruit").forGetter((blockstem) -> { ++ return blockstem.fruit; ++ }), ResourceKey.codec(Registries.BLOCK).fieldOf("attached_stem").forGetter((blockstem) -> { ++ return blockstem.attachedStem; ++ }), ResourceKey.codec(Registries.ITEM).fieldOf("seed").forGetter((blockstem) -> { ++ return blockstem.seed; + }), propertiesCodec()).apply(instance, StemBlock::new); + }); + public static final int MAX_AGE = 7; +@@ -47,56 +48,56 @@ + private final ResourceKey seed; + + @Override +- @Override + public MapCodec codec() { + return StemBlock.CODEC; + } + +- protected StemBlock(ResourceKey resourcekey, ResourceKey resourcekey1, ResourceKey resourcekey2, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ protected StemBlock(ResourceKey resourcekey, ResourceKey resourcekey1, ResourceKey resourcekey2, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info); + this.fruit = resourcekey; + this.attachedStem = resourcekey1; + this.seed = resourcekey2; +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(StemBlock.AGE, 0)); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(StemBlock.AGE, 0)); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return StemBlock.SHAPE_BY_AGE[(Integer) blockstate.getValue(StemBlock.AGE)]; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return StemBlock.SHAPE_BY_AGE[(Integer) state.getValue(StemBlock.AGE)]; + } + + @Override +- @Override +- protected boolean mayPlaceOn(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return blockstate.is(Blocks.FARMLAND); ++ protected boolean mayPlaceOn(IBlockData state, BlockGetter level, BlockPos pos) { ++ return state.is(Blocks.FARMLAND); + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (serverlevel.getRawBrightness(blockpos, 0) >= 9) { +- float f = CropBlock.getGrowthSpeed(this, serverlevel, blockpos); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (level.getRawBrightness(pos, 0) >= 9) { ++ float f = CropBlock.getGrowthSpeed(this, level, pos); + +- if (randomsource.nextInt((int) (25.0F / f) + 1) == 0) { +- int i = (Integer) blockstate.getValue(StemBlock.AGE); ++ if (random.nextInt((int) (25.0F / f) + 1) == 0) { ++ int i = (Integer) state.getValue(StemBlock.AGE); + + if (i < 7) { +- blockstate = (BlockState) blockstate.setValue(StemBlock.AGE, i + 1); +- serverlevel.setBlock(blockpos, blockstate, 2); ++ state = (IBlockData) state.setValue(StemBlock.AGE, i + 1); ++ CraftEventFactory.handleBlockGrowEvent(level, pos, state, 2); // CraftBukkit + } else { +- Direction direction = Direction.Plane.HORIZONTAL.getRandomDirection(randomsource); +- BlockPos blockpos1 = blockpos.relative(direction); +- BlockState blockstate1 = serverlevel.getBlockState(blockpos1.below()); ++ Direction enumdirection = Direction.Plane.HORIZONTAL.getRandomDirection(random); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1.below()); + +- if (serverlevel.getBlockState(blockpos1).isAir() && (blockstate1.is(Blocks.FARMLAND) || blockstate1.is(BlockTags.DIRT))) { +- Registry registry = serverlevel.registryAccess().registryOrThrow(Registries.BLOCK); +- Optional optional = registry.getOptional(this.fruit); +- Optional optional1 = registry.getOptional(this.attachedStem); ++ if (level.getBlockState(blockposition1).isAir() && (iblockdata1.is(Blocks.FARMLAND) || iblockdata1.is(BlockTags.DIRT))) { ++ Registry iregistry = level.registryAccess().registryOrThrow(Registries.BLOCK); ++ Optional optional = iregistry.getOptional(this.fruit); ++ Optional optional1 = iregistry.getOptional(this.attachedStem); + + if (optional.isPresent() && optional1.isPresent()) { +- serverlevel.setBlockAndUpdate(blockpos1, ((Block) optional.get()).defaultBlockState()); +- serverlevel.setBlockAndUpdate(blockpos, (BlockState) ((Block) optional1.get()).defaultBlockState().setValue(HorizontalDirectionalBlock.FACING, direction)); ++ // CraftBukkit start ++ if (!CraftEventFactory.handleBlockGrowEvent(level, blockposition1, ((Block) optional.get()).defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlockAndUpdate(pos, (IBlockData) ((Block) optional1.get()).defaultBlockState().setValue(HorizontalDirectionalBlock.FACING, enumdirection)); + } + } + } +@@ -106,39 +107,34 @@ + } + + @Override +- @Override +- public ItemStack getCloneItemStack(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { +- return new ItemStack((ItemLike) DataFixUtils.orElse(levelreader.registryAccess().registryOrThrow(Registries.ITEM).getOptional(this.seed), this)); ++ public ItemStack getCloneItemStack(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ return new ItemStack((IMaterial) DataFixUtils.orElse(iworldreader.registryAccess().registryOrThrow(Registries.ITEM).getOptional(this.seed), this)); + } + + @Override +- @Override +- public boolean isValidBonemealTarget(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { +- return (Integer) blockstate.getValue(StemBlock.AGE) != 7; ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ return (Integer) iblockdata.getValue(StemBlock.AGE) != 7; + } + + @Override +- @Override +- public boolean isBonemealSuccess(Level level, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return true; + } + + @Override +- @Override +- public void performBonemeal(ServerLevel serverlevel, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { +- int i = Math.min(7, (Integer) blockstate.getValue(StemBlock.AGE) + Mth.nextInt(serverlevel.random, 2, 5)); +- BlockState blockstate1 = (BlockState) blockstate.setValue(StemBlock.AGE, i); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ int i = Math.min(7, (Integer) state.getValue(StemBlock.AGE) + Mth.nextInt(level.random, 2, 5)); ++ IBlockData iblockdata1 = (IBlockData) state.setValue(StemBlock.AGE, i); + +- serverlevel.setBlock(blockpos, blockstate1, 2); ++ CraftEventFactory.handleBlockGrowEvent(level, pos, iblockdata1, 2); // CraftBukkit + if (i == 7) { +- blockstate1.randomTick(serverlevel, blockpos, serverlevel.random); ++ iblockdata1.randomTick(level, pos, level.random); + } + + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(StemBlock.AGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(StemBlock.AGE); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SugarCaneBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SugarCaneBlock.java.patch new file mode 100644 index 0000000000..b69f05039b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SugarCaneBlock.java.patch @@ -0,0 +1,133 @@ +--- a/net/minecraft/world/level/block/SugarCaneBlock.java ++++ b/net/minecraft/world/level/block/SugarCaneBlock.java +@@ -12,7 +12,7 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; +@@ -28,49 +28,45 @@ + protected static final VoxelShape SHAPE = Block.box(2.0D, 0.0D, 2.0D, 14.0D, 16.0D, 14.0D); + + @Override +- @Override + public MapCodec codec() { + return SugarCaneBlock.CODEC; + } + +- protected SugarCaneBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(SugarCaneBlock.AGE, 0)); ++ protected SugarCaneBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(SugarCaneBlock.AGE, 0)); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return SugarCaneBlock.SHAPE; + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (!blockstate.canSurvive(serverlevel, blockpos)) { +- serverlevel.destroyBlock(blockpos, true); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (!state.canSurvive(level, pos)) { ++ level.destroyBlock(pos, true); + } + + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (serverlevel.isEmptyBlock(blockpos.above())) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (level.isEmptyBlock(pos.above())) { + int i; + +- for (i = 1; serverlevel.getBlockState(blockpos.below(i)).is((Block) this); ++i) { ++ for (i = 1; level.getBlockState(pos.below(i)).is((Block) this); ++i) { + ; + } + + if (i < 3) { +- int j = (Integer) blockstate.getValue(SugarCaneBlock.AGE); ++ int j = (Integer) state.getValue(SugarCaneBlock.AGE); + + if (j == 15) { +- serverlevel.setBlockAndUpdate(blockpos.above(), this.defaultBlockState()); +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(SugarCaneBlock.AGE, 0), 4); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos.above(), this.defaultBlockState()); // CraftBukkit ++ level.setBlock(pos, (IBlockData) state.setValue(SugarCaneBlock.AGE, 0), 4); + } else { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(SugarCaneBlock.AGE, j + 1), 4); ++ level.setBlock(pos, (IBlockData) state.setValue(SugarCaneBlock.AGE, j + 1), 4); + } + } + } +@@ -78,33 +74,31 @@ + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if (!blockstate.canSurvive(levelaccessor, blockpos)) { +- levelaccessor.scheduleTick(blockpos, (Block) this, 1); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if (!state.canSurvive(level, currentPos)) { ++ level.scheduleTick(currentPos, (Block) this, 1); + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- BlockState blockstate1 = levelreader.getBlockState(blockpos.below()); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ IBlockData iblockdata1 = level.getBlockState(pos.below()); + +- if (blockstate1.is((Block) this)) { ++ if (iblockdata1.is((Block) this)) { + return true; + } else { +- if (blockstate1.is(BlockTags.DIRT) || blockstate1.is(BlockTags.SAND)) { +- BlockPos blockpos1 = blockpos.below(); ++ if (iblockdata1.is(BlockTags.DIRT) || iblockdata1.is(BlockTags.SAND)) { ++ BlockPos blockposition1 = pos.below(); + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); +- BlockState blockstate2 = levelreader.getBlockState(blockpos1.relative(direction)); +- FluidState fluidstate = levelreader.getFluidState(blockpos1.relative(direction)); ++ Direction enumdirection = (Direction) iterator.next(); ++ IBlockData iblockdata2 = level.getBlockState(blockposition1.relative(enumdirection)); ++ FluidState fluid = level.getFluidState(blockposition1.relative(enumdirection)); + +- if (fluidstate.is(FluidTags.WATER) || blockstate2.is(Blocks.FROSTED_ICE)) { ++ if (fluid.is(FluidTags.WATER) || iblockdata2.is(Blocks.FROSTED_ICE)) { + return true; + } + } +@@ -115,8 +109,7 @@ + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(SugarCaneBlock.AGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(SugarCaneBlock.AGE); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SweetBerryBushBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SweetBerryBushBlock.java.patch new file mode 100644 index 0000000000..7b43ea8786 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/SweetBerryBushBlock.java.patch @@ -0,0 +1,190 @@ +--- a/net/minecraft/world/level/block/SweetBerryBushBlock.java ++++ b/net/minecraft/world/level/block/SweetBerryBushBlock.java +@@ -6,7 +6,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +@@ -18,7 +18,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; +@@ -27,6 +27,13 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import java.util.Collections; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerHarvestBlockEvent; ++// CraftBukkit end + + public class SweetBerryBushBlock extends BushBlock implements BonemealableBlock { + +@@ -38,59 +45,55 @@ + private static final VoxelShape MID_GROWTH_SHAPE = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 16.0D, 15.0D); + + @Override +- @Override + public MapCodec codec() { + return SweetBerryBushBlock.CODEC; + } + +- public SweetBerryBushBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(SweetBerryBushBlock.AGE, 0)); ++ public SweetBerryBushBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(SweetBerryBushBlock.AGE, 0)); + } + + @Override +- @Override +- public ItemStack getCloneItemStack(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { ++ public ItemStack getCloneItemStack(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { + return new ItemStack(Items.SWEET_BERRIES); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return (Integer) blockstate.getValue(SweetBerryBushBlock.AGE) == 0 ? SweetBerryBushBlock.SAPLING_SHAPE : ((Integer) blockstate.getValue(SweetBerryBushBlock.AGE) < 3 ? SweetBerryBushBlock.MID_GROWTH_SHAPE : super.getShape(blockstate, blockgetter, blockpos, collisioncontext)); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (Integer) state.getValue(SweetBerryBushBlock.AGE) == 0 ? SweetBerryBushBlock.SAPLING_SHAPE : ((Integer) state.getValue(SweetBerryBushBlock.AGE) < 3 ? SweetBerryBushBlock.MID_GROWTH_SHAPE : super.getShape(state, level, pos, context)); + } + + @Override +- @Override +- public boolean isRandomlyTicking(BlockState blockstate) { +- return (Integer) blockstate.getValue(SweetBerryBushBlock.AGE) < 3; ++ public boolean isRandomlyTicking(IBlockData state) { ++ return (Integer) state.getValue(SweetBerryBushBlock.AGE) < 3; + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- int i = (Integer) blockstate.getValue(SweetBerryBushBlock.AGE); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ int i = (Integer) state.getValue(SweetBerryBushBlock.AGE); + +- if (i < 3 && randomsource.nextInt(5) == 0 && serverlevel.getRawBrightness(blockpos.above(), 0) >= 9) { +- BlockState blockstate1 = (BlockState) blockstate.setValue(SweetBerryBushBlock.AGE, i + 1); ++ if (i < 3 && random.nextInt(5) == 0 && level.getRawBrightness(pos.above(), 0) >= 9) { ++ IBlockData iblockdata1 = (IBlockData) state.setValue(SweetBerryBushBlock.AGE, i + 1); + +- serverlevel.setBlock(blockpos, blockstate1, 2); +- serverlevel.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(blockstate1)); ++ if (!CraftEventFactory.handleBlockGrowEvent(level, pos, iblockdata1, 2)) return; // CraftBukkit ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(iblockdata1)); + } + + } + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { + if (entity instanceof LivingEntity && entity.getType() != EntityType.FOX && entity.getType() != EntityType.BEE) { +- entity.makeStuckInBlock(blockstate, new Vec3(0.800000011920929D, 0.75D, 0.800000011920929D)); +- if (!level.isClientSide && (Integer) blockstate.getValue(SweetBerryBushBlock.AGE) > 0 && (entity.xOld != entity.getX() || entity.zOld != entity.getZ())) { ++ entity.makeStuckInBlock(state, new Vec3(0.800000011920929D, 0.75D, 0.800000011920929D)); ++ if (!level.isClientSide && (Integer) state.getValue(SweetBerryBushBlock.AGE) > 0 && (entity.xOld != entity.getX() || entity.zOld != entity.getZ())) { + double d0 = Math.abs(entity.getX() - entity.xOld); + double d1 = Math.abs(entity.getZ() - entity.zOld); + + if (d0 >= 0.003000000026077032D || d1 >= 0.003000000026077032D) { ++ CraftEventFactory.blockDamage = CraftBlock.at(level, pos); // CraftBukkit + entity.hurt(level.damageSources().sweetBerryBush(), 1.0F); ++ CraftEventFactory.blockDamage = null; // CraftBukkit + } + } + +@@ -98,51 +101,54 @@ + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- int i = (Integer) blockstate.getValue(SweetBerryBushBlock.AGE); ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ int i = (Integer) state.getValue(SweetBerryBushBlock.AGE); + boolean flag = i == 3; + +- if (!flag && player.getItemInHand(interactionhand).is(Items.BONE_MEAL)) { ++ if (!flag && player.getItemInHand(hand).is(Items.BONE_MEAL)) { + return InteractionResult.PASS; + } else if (i > 1) { + int j = 1 + level.random.nextInt(2); + +- popResource(level, blockpos, new ItemStack(Items.SWEET_BERRIES, j + (flag ? 1 : 0))); +- level.playSound((Player) null, blockpos, SoundEvents.SWEET_BERRY_BUSH_PICK_BERRIES, SoundSource.BLOCKS, 1.0F, 0.8F + level.random.nextFloat() * 0.4F); +- BlockState blockstate1 = (BlockState) blockstate.setValue(SweetBerryBushBlock.AGE, 1); ++ // CraftBukkit start ++ PlayerHarvestBlockEvent event = CraftEventFactory.callPlayerHarvestBlockEvent(level, pos, player, hand, Collections.singletonList(new ItemStack(Items.SWEET_BERRIES, j + (flag ? 1 : 0)))); ++ if (event.isCancelled()) { ++ return InteractionResult.SUCCESS; // We need to return a success either way, because making it PASS or FAIL will result in a bug where cancelling while harvesting w/ block in hand places block ++ } ++ for (org.bukkit.inventory.ItemStack itemStack : event.getItemsHarvested()) { ++ popResource(level, pos, CraftItemStack.asNMSCopy(itemStack)); ++ } ++ // CraftBukkit end ++ level.playSound((Player) null, pos, SoundEvents.SWEET_BERRY_BUSH_PICK_BERRIES, SoundSource.BLOCKS, 1.0F, 0.8F + level.random.nextFloat() * 0.4F); ++ IBlockData iblockdata1 = (IBlockData) state.setValue(SweetBerryBushBlock.AGE, 1); + +- level.setBlock(blockpos, blockstate1, 2); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(player, blockstate1)); ++ level.setBlock(pos, iblockdata1, 2); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(player, iblockdata1)); + return InteractionResult.sidedSuccess(level.isClientSide); + } else { +- return super.use(blockstate, level, blockpos, player, interactionhand, blockhitresult); ++ return super.use(state, level, pos, player, hand, hit); + } + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(SweetBerryBushBlock.AGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(SweetBerryBushBlock.AGE); + } + + @Override +- @Override +- public boolean isValidBonemealTarget(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { +- return (Integer) blockstate.getValue(SweetBerryBushBlock.AGE) < 3; ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ return (Integer) iblockdata.getValue(SweetBerryBushBlock.AGE) < 3; + } + + @Override +- @Override +- public boolean isBonemealSuccess(Level level, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return true; + } + + @Override +- @Override +- public void performBonemeal(ServerLevel serverlevel, RandomSource randomsource, BlockPos blockpos, BlockState blockstate) { +- int i = Math.min(3, (Integer) blockstate.getValue(SweetBerryBushBlock.AGE) + 1); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ int i = Math.min(3, (Integer) state.getValue(SweetBerryBushBlock.AGE) + 1); + +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(SweetBerryBushBlock.AGE, i), 2); ++ level.setBlock(pos, (IBlockData) state.setValue(SweetBerryBushBlock.AGE, i), 2); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/TntBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/TntBlock.java.patch new file mode 100644 index 0000000000..4605d24159 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/TntBlock.java.patch @@ -0,0 +1,202 @@ +--- a/net/minecraft/world/level/block/TntBlock.java ++++ b/net/minecraft/world/level/block/TntBlock.java +@@ -6,7 +6,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; +@@ -19,12 +19,16 @@ + import net.minecraft.world.level.Explosion; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.BlockHitResult; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.block.TNTPrimeEvent.PrimeCause; ++// CraftBukkit end + + public class TntBlock extends Block { + +@@ -32,90 +36,89 @@ + public static final BooleanProperty UNSTABLE = BlockStateProperties.UNSTABLE; + + @Override +- @Override + public MapCodec codec() { + return TntBlock.CODEC; + } + +- public TntBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) this.defaultBlockState().setValue(TntBlock.UNSTABLE, false)); ++ public TntBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) this.defaultBlockState().setValue(TntBlock.UNSTABLE, false)); + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!blockstate1.is(blockstate.getBlock())) { +- if (level.hasNeighborSignal(blockpos)) { +- explode(level, blockpos); +- level.removeBlock(blockpos, false); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ if (!oldState.is(state.getBlock())) { ++ if (level.hasNeighborSignal(pos) && CraftEventFactory.callTNTPrimeEvent(level, pos, PrimeCause.REDSTONE, null, null)) { // CraftBukkit - TNTPrimeEvent ++ explode(level, pos); ++ level.removeBlock(pos, false); + } + + } + } + + @Override +- @Override +- public void neighborChanged(BlockState blockstate, Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { +- if (level.hasNeighborSignal(blockpos)) { +- explode(level, blockpos); +- level.removeBlock(blockpos, false); ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ if (level.hasNeighborSignal(pos) && CraftEventFactory.callTNTPrimeEvent(level, pos, PrimeCause.REDSTONE, null, fromPos)) { // CraftBukkit - TNTPrimeEvent ++ explode(level, pos); ++ level.removeBlock(pos, false); + } + + } + + @Override +- @Override +- public BlockState playerWillDestroy(Level level, BlockPos blockpos, BlockState blockstate, Player player) { +- if (!level.isClientSide() && !player.isCreative() && (Boolean) blockstate.getValue(TntBlock.UNSTABLE)) { +- explode(level, blockpos); ++ public IBlockData playerWillDestroy(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ if (!world.isClientSide() && !entityhuman.isCreative() && (Boolean) iblockdata.getValue(TntBlock.UNSTABLE) && CraftEventFactory.callTNTPrimeEvent(world, blockposition, PrimeCause.BLOCK_BREAK, entityhuman, null)) { // CraftBukkit - TNTPrimeEvent ++ explode(world, blockposition); + } + +- return super.playerWillDestroy(level, blockpos, blockstate, player); ++ return super.playerWillDestroy(world, blockposition, iblockdata, entityhuman); + } + + @Override +- @Override +- public void wasExploded(Level level, BlockPos blockpos, Explosion explosion) { ++ public void wasExploded(Level level, BlockPos pos, Explosion explosion) { + if (!level.isClientSide) { +- PrimedTnt primedtnt = new PrimedTnt(level, (double) blockpos.getX() + 0.5D, (double) blockpos.getY(), (double) blockpos.getZ() + 0.5D, explosion.getIndirectSourceEntity()); +- int i = primedtnt.getFuse(); ++ PrimedTnt entitytntprimed = new PrimedTnt(level, (double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, explosion.getIndirectSourceEntity()); ++ int i = entitytntprimed.getFuse(); + +- primedtnt.setFuse((short) (level.random.nextInt(i / 4) + i / 8)); +- level.addFreshEntity(primedtnt); ++ entitytntprimed.setFuse((short) (level.random.nextInt(i / 4) + i / 8)); ++ level.addFreshEntity(entitytntprimed); + } + } + +- public static void explode(Level level, BlockPos blockpos) { +- explode(level, blockpos, (LivingEntity) null); ++ public static void explode(Level level, BlockPos pos) { ++ explode(level, pos, (LivingEntity) null); + } + +- private static void explode(Level level, BlockPos blockpos, @Nullable LivingEntity livingentity) { ++ private static void explode(Level level, BlockPos pos, @Nullable LivingEntity entity) { + if (!level.isClientSide) { +- PrimedTnt primedtnt = new PrimedTnt(level, (double) blockpos.getX() + 0.5D, (double) blockpos.getY(), (double) blockpos.getZ() + 0.5D, livingentity); ++ PrimedTnt entitytntprimed = new PrimedTnt(level, (double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, entity); + +- level.addFreshEntity(primedtnt); +- level.playSound((Player) null, primedtnt.getX(), primedtnt.getY(), primedtnt.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent((Entity) livingentity, GameEvent.PRIME_FUSE, blockpos); ++ level.addFreshEntity(entitytntprimed); ++ level.playSound((Player) null, entitytntprimed.getX(), entitytntprimed.getY(), entitytntprimed.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.gameEvent((Entity) entity, GameEvent.PRIME_FUSE, pos); + } + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ ItemStack itemstack = player.getItemInHand(hand); + + if (!itemstack.is(Items.FLINT_AND_STEEL) && !itemstack.is(Items.FIRE_CHARGE)) { +- return super.use(blockstate, level, blockpos, player, interactionhand, blockhitresult); ++ return super.use(state, level, pos, player, hand, hit); + } else { +- explode(level, blockpos, player); +- level.setBlock(blockpos, Blocks.AIR.defaultBlockState(), 11); ++ // CraftBukkit start - TNTPrimeEvent ++ if (!CraftEventFactory.callTNTPrimeEvent(level, pos, PrimeCause.PLAYER, player, null)) { ++ return InteractionResult.CONSUME; ++ } ++ // CraftBukkit end ++ explode(level, pos, player); ++ level.setBlock(pos, Blocks.AIR.defaultBlockState(), 11); + Item item = itemstack.getItem(); + + if (!player.isCreative()) { + if (itemstack.is(Items.FLINT_AND_STEEL)) { +- itemstack.hurtAndBreak(1, player, (player1) -> { +- player1.broadcastBreakEvent(interactionhand); ++ itemstack.hurtAndBreak(1, player, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(hand); + }); + } else { + itemstack.shrink(1); +@@ -128,29 +131,31 @@ + } + + @Override +- @Override +- public void onProjectileHit(Level level, BlockState blockstate, BlockHitResult blockhitresult, Projectile projectile) { ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { + if (!level.isClientSide) { +- BlockPos blockpos = blockhitresult.getBlockPos(); ++ BlockPos blockposition = hit.getBlockPos(); + Entity entity = projectile.getOwner(); + +- if (projectile.isOnFire() && projectile.mayInteract(level, blockpos)) { +- explode(level, blockpos, entity instanceof LivingEntity ? (LivingEntity) entity : null); +- level.removeBlock(blockpos, false); ++ if (projectile.isOnFire() && projectile.mayInteract(level, blockposition)) { ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, Blocks.AIR.defaultBlockState()) || !CraftEventFactory.callTNTPrimeEvent(level, blockposition, PrimeCause.PROJECTILE, projectile, null)) { ++ return; ++ } ++ // CraftBukkit end ++ explode(level, blockposition, entity instanceof LivingEntity ? (LivingEntity) entity : null); ++ level.removeBlock(blockposition, false); + } + } + + } + + @Override +- @Override + public boolean dropFromExplosion(Explosion explosion) { + return false; + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(TntBlock.UNSTABLE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(TntBlock.UNSTABLE); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/TrapDoorBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/TrapDoorBlock.java.patch new file mode 100644 index 0000000000..b165c1f2ea --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/TrapDoorBlock.java.patch @@ -0,0 +1,252 @@ +--- a/net/minecraft/world/level/block/TrapDoorBlock.java ++++ b/net/minecraft/world/level/block/TrapDoorBlock.java +@@ -7,7 +7,7 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.sounds.SoundSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; +@@ -18,7 +18,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockSetType; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; +@@ -29,16 +29,17 @@ + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class TrapDoorBlock extends HorizontalDirectionalBlock implements SimpleWaterloggedBlock { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- return instance.group(BlockSetType.CODEC.fieldOf("block_set_type").forGetter((trapdoorblock) -> { +- return trapdoorblock.type; ++ return instance.group(BlockSetType.CODEC.fieldOf("block_set_type").forGetter((blocktrapdoor) -> { ++ return blocktrapdoor.type; + }), propertiesCodec()).apply(instance, TrapDoorBlock::new); + }); + public static final BooleanProperty OPEN = BlockStateProperties.OPEN; +@@ -55,24 +56,22 @@ + private final BlockSetType type; + + @Override +- @Override + public MapCodec codec() { + return TrapDoorBlock.CODEC; + } + +- protected TrapDoorBlock(BlockSetType blocksettype, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties.sound(blocksettype.soundType())); ++ protected TrapDoorBlock(BlockSetType blocksettype, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info.sound(blocksettype.soundType())); + this.type = blocksettype; +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(TrapDoorBlock.FACING, Direction.NORTH)).setValue(TrapDoorBlock.OPEN, false)).setValue(TrapDoorBlock.HALF, Half.BOTTOM)).setValue(TrapDoorBlock.POWERED, false)).setValue(TrapDoorBlock.WATERLOGGED, false)); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(TrapDoorBlock.FACING, Direction.NORTH)).setValue(TrapDoorBlock.OPEN, false)).setValue(TrapDoorBlock.HALF, Half.BOTTOM)).setValue(TrapDoorBlock.POWERED, false)).setValue(TrapDoorBlock.WATERLOGGED, false)); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- if (!(Boolean) blockstate.getValue(TrapDoorBlock.OPEN)) { +- return blockstate.getValue(TrapDoorBlock.HALF) == Half.TOP ? TrapDoorBlock.TOP_AABB : TrapDoorBlock.BOTTOM_AABB; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ if (!(Boolean) state.getValue(TrapDoorBlock.OPEN)) { ++ return state.getValue(TrapDoorBlock.HALF) == Half.TOP ? TrapDoorBlock.TOP_AABB : TrapDoorBlock.BOTTOM_AABB; + } else { +- switch ((Direction) blockstate.getValue(TrapDoorBlock.FACING)) { ++ switch ((Direction) state.getValue(TrapDoorBlock.FACING)) { + case NORTH: + default: + return TrapDoorBlock.NORTH_OPEN_AABB; +@@ -87,72 +86,81 @@ + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { +- switch (pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { ++ switch (type) { + case LAND: +- return (Boolean) blockstate.getValue(TrapDoorBlock.OPEN); ++ return (Boolean) state.getValue(TrapDoorBlock.OPEN); + case WATER: +- return (Boolean) blockstate.getValue(TrapDoorBlock.WATERLOGGED); ++ return (Boolean) state.getValue(TrapDoorBlock.WATERLOGGED); + case AIR: +- return (Boolean) blockstate.getValue(TrapDoorBlock.OPEN); ++ return (Boolean) state.getValue(TrapDoorBlock.OPEN); + default: + return false; + } + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + if (!this.type.canOpenByHand()) { + return InteractionResult.PASS; + } else { +- this.toggle(blockstate, level, blockpos, player); ++ this.toggle(state, level, pos, player); + return InteractionResult.sidedSuccess(level.isClientSide); + } + } + + @Override +- @Override +- public void onExplosionHit(BlockState blockstate, Level level, BlockPos blockpos, Explosion explosion, BiConsumer biconsumer) { +- if (explosion.getBlockInteraction() == Explosion.BlockInteraction.TRIGGER_BLOCK && !level.isClientSide() && this.type.canOpenByWindCharge() && !(Boolean) blockstate.getValue(TrapDoorBlock.POWERED)) { +- this.toggle(blockstate, level, blockpos, (Player) null); ++ public void onExplosionHit(IBlockData iblockdata, Level world, BlockPos blockposition, Explosion explosion, BiConsumer biconsumer) { ++ if (explosion.getBlockInteraction() == Explosion.Effect.TRIGGER_BLOCK && !world.isClientSide() && this.type.canOpenByWindCharge() && !(Boolean) iblockdata.getValue(TrapDoorBlock.POWERED)) { ++ this.toggle(iblockdata, world, blockposition, (Player) null); + } + +- super.onExplosionHit(blockstate, level, blockpos, explosion, biconsumer); ++ super.onExplosionHit(iblockdata, world, blockposition, explosion, biconsumer); + } + +- private void toggle(BlockState blockstate, Level level, BlockPos blockpos, @Nullable Player player) { +- BlockState blockstate1 = (BlockState) blockstate.cycle(TrapDoorBlock.OPEN); ++ private void toggle(IBlockData iblockdata, Level world, BlockPos blockposition, @Nullable Player entityhuman) { ++ IBlockData iblockdata1 = (IBlockData) iblockdata.cycle(TrapDoorBlock.OPEN); + +- level.setBlock(blockpos, blockstate1, 2); +- if ((Boolean) blockstate1.getValue(TrapDoorBlock.WATERLOGGED)) { +- level.scheduleTick(blockpos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); ++ world.setBlock(blockposition, iblockdata1, 2); ++ if ((Boolean) iblockdata1.getValue(TrapDoorBlock.WATERLOGGED)) { ++ world.scheduleTick(blockposition, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(world)); + } + +- this.playSound(player, level, blockpos, (Boolean) blockstate1.getValue(TrapDoorBlock.OPEN)); ++ this.playSound(entityhuman, world, blockposition, (Boolean) iblockdata1.getValue(TrapDoorBlock.OPEN)); + } + +- protected void playSound(@Nullable Player player, Level level, BlockPos blockpos, boolean flag) { +- level.playSound(player, blockpos, flag ? this.type.trapdoorOpen() : this.type.trapdoorClose(), SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.1F + 0.9F); +- level.gameEvent((Entity) player, flag ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, blockpos); ++ protected void playSound(@Nullable Player player, Level level, BlockPos pos, boolean isOpened) { ++ level.playSound(player, pos, isOpened ? this.type.trapdoorOpen() : this.type.trapdoorClose(), SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.1F + 0.9F); ++ level.gameEvent((Entity) player, isOpened ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); + } + + @Override +- @Override +- public void neighborChanged(BlockState blockstate, Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { + if (!level.isClientSide) { +- boolean flag1 = level.hasNeighborSignal(blockpos); ++ boolean flag1 = level.hasNeighborSignal(pos); + +- if (flag1 != (Boolean) blockstate.getValue(TrapDoorBlock.POWERED)) { +- if ((Boolean) blockstate.getValue(TrapDoorBlock.OPEN) != flag1) { +- blockstate = (BlockState) blockstate.setValue(TrapDoorBlock.OPEN, flag1); +- this.playSound((Player) null, level, blockpos, flag1); ++ if (flag1 != (Boolean) state.getValue(TrapDoorBlock.POWERED)) { ++ // CraftBukkit start ++ org.bukkit.World bworld = level.getWorld(); ++ org.bukkit.block.Block bblock = bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ ++ int power = bblock.getBlockPower(); ++ int oldPower = (Boolean) state.getValue(OPEN) ? 15 : 0; ++ ++ if (oldPower == 0 ^ power == 0 || block.defaultBlockState().isSignalSource()) { ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bblock, oldPower, power); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ flag1 = eventRedstone.getNewCurrent() > 0; + } ++ // CraftBukkit end ++ if ((Boolean) state.getValue(TrapDoorBlock.OPEN) != flag1) { ++ state = (IBlockData) state.setValue(TrapDoorBlock.OPEN, flag1); ++ this.playSound((Player) null, level, pos, flag1); ++ } + +- level.setBlock(blockpos, (BlockState) blockstate.setValue(TrapDoorBlock.POWERED, flag1), 2); +- if ((Boolean) blockstate.getValue(TrapDoorBlock.WATERLOGGED)) { +- level.scheduleTick(blockpos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); ++ level.setBlock(pos, (IBlockData) state.setValue(TrapDoorBlock.POWERED, flag1), 2); ++ if ((Boolean) state.getValue(TrapDoorBlock.WATERLOGGED)) { ++ level.scheduleTick(pos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + } + +@@ -160,45 +168,41 @@ + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- BlockState blockstate = this.defaultBlockState(); +- FluidState fluidstate = blockplacecontext.getLevel().getFluidState(blockplacecontext.getClickedPos()); +- Direction direction = blockplacecontext.getClickedFace(); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ IBlockData iblockdata = this.defaultBlockState(); ++ FluidState fluid = context.getLevel().getFluidState(context.getClickedPos()); ++ Direction enumdirection = context.getClickedFace(); + +- if (!blockplacecontext.replacingClickedOnBlock() && direction.getAxis().isHorizontal()) { +- blockstate = (BlockState) ((BlockState) blockstate.setValue(TrapDoorBlock.FACING, direction)).setValue(TrapDoorBlock.HALF, blockplacecontext.getClickLocation().y - (double) blockplacecontext.getClickedPos().getY() > 0.5D ? Half.TOP : Half.BOTTOM); ++ if (!context.replacingClickedOnBlock() && enumdirection.getAxis().isHorizontal()) { ++ iblockdata = (IBlockData) ((IBlockData) iblockdata.setValue(TrapDoorBlock.FACING, enumdirection)).setValue(TrapDoorBlock.HALF, context.getClickLocation().y - (double) context.getClickedPos().getY() > 0.5D ? Half.TOP : Half.BOTTOM); + } else { +- blockstate = (BlockState) ((BlockState) blockstate.setValue(TrapDoorBlock.FACING, blockplacecontext.getHorizontalDirection().getOpposite())).setValue(TrapDoorBlock.HALF, direction == Direction.UP ? Half.BOTTOM : Half.TOP); ++ iblockdata = (IBlockData) ((IBlockData) iblockdata.setValue(TrapDoorBlock.FACING, context.getHorizontalDirection().getOpposite())).setValue(TrapDoorBlock.HALF, enumdirection == Direction.UP ? Half.BOTTOM : Half.TOP); + } + +- if (blockplacecontext.getLevel().hasNeighborSignal(blockplacecontext.getClickedPos())) { +- blockstate = (BlockState) ((BlockState) blockstate.setValue(TrapDoorBlock.OPEN, true)).setValue(TrapDoorBlock.POWERED, true); ++ if (context.getLevel().hasNeighborSignal(context.getClickedPos())) { ++ iblockdata = (IBlockData) ((IBlockData) iblockdata.setValue(TrapDoorBlock.OPEN, true)).setValue(TrapDoorBlock.POWERED, true); + } + +- return (BlockState) blockstate.setValue(TrapDoorBlock.WATERLOGGED, fluidstate.getType() == Fluids.WATER); ++ return (IBlockData) iblockdata.setValue(TrapDoorBlock.WATERLOGGED, fluid.getType() == Fluids.WATER); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(TrapDoorBlock.FACING, TrapDoorBlock.OPEN, TrapDoorBlock.HALF, TrapDoorBlock.POWERED, TrapDoorBlock.WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(TrapDoorBlock.FACING, TrapDoorBlock.OPEN, TrapDoorBlock.HALF, TrapDoorBlock.POWERED, TrapDoorBlock.WATERLOGGED); + } + + @Override +- @Override +- public FluidState getFluidState(BlockState blockstate) { +- return (Boolean) blockstate.getValue(TrapDoorBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(blockstate); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(TrapDoorBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if ((Boolean) blockstate.getValue(TrapDoorBlock.WATERLOGGED)) { +- levelaccessor.scheduleTick(blockpos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(levelaccessor)); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if ((Boolean) state.getValue(TrapDoorBlock.WATERLOGGED)) { ++ level.scheduleTick(currentPos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + protected BlockSetType getType() { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/TripWireBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/TripWireBlock.java.patch new file mode 100644 index 0000000000..73e4c2de2c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/TripWireBlock.java.patch @@ -0,0 +1,289 @@ +--- a/net/minecraft/world/level/block/TripWireBlock.java ++++ b/net/minecraft/world/level/block/TripWireBlock.java +@@ -18,7 +18,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -26,12 +26,13 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.entity.EntityInteractEvent; // CraftBukkit + + public class TripWireBlock extends Block { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- return instance.group(BuiltInRegistries.BLOCK.byNameCodec().fieldOf("hook").forGetter((tripwireblock) -> { +- return tripwireblock.hook; ++ return instance.group(BuiltInRegistries.BLOCK.byNameCodec().fieldOf("hook").forGetter((blocktripwire) -> { ++ return blocktripwire.hook; + }), propertiesCodec()).apply(instance, TripWireBlock::new); + }); + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; +@@ -48,84 +49,77 @@ + private final Block hook; + + @Override +- @Override + public MapCodec codec() { + return TripWireBlock.CODEC; + } + +- public TripWireBlock(Block block, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) ((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(TripWireBlock.POWERED, false)).setValue(TripWireBlock.ATTACHED, false)).setValue(TripWireBlock.DISARMED, false)).setValue(TripWireBlock.NORTH, false)).setValue(TripWireBlock.EAST, false)).setValue(TripWireBlock.SOUTH, false)).setValue(TripWireBlock.WEST, false)); ++ public TripWireBlock(Block block, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(TripWireBlock.POWERED, false)).setValue(TripWireBlock.ATTACHED, false)).setValue(TripWireBlock.DISARMED, false)).setValue(TripWireBlock.NORTH, false)).setValue(TripWireBlock.EAST, false)).setValue(TripWireBlock.SOUTH, false)).setValue(TripWireBlock.WEST, false)); + this.hook = block; + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return (Boolean) blockstate.getValue(TripWireBlock.ATTACHED) ? TripWireBlock.AABB : TripWireBlock.NOT_ATTACHED_AABB; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (Boolean) state.getValue(TripWireBlock.ATTACHED) ? TripWireBlock.AABB : TripWireBlock.NOT_ATTACHED_AABB; + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- Level level = blockplacecontext.getLevel(); +- BlockPos blockpos = blockplacecontext.getClickedPos(); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); + +- return (BlockState) ((BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(TripWireBlock.NORTH, this.shouldConnectTo(level.getBlockState(blockpos.north()), Direction.NORTH))).setValue(TripWireBlock.EAST, this.shouldConnectTo(level.getBlockState(blockpos.east()), Direction.EAST))).setValue(TripWireBlock.SOUTH, this.shouldConnectTo(level.getBlockState(blockpos.south()), Direction.SOUTH))).setValue(TripWireBlock.WEST, this.shouldConnectTo(level.getBlockState(blockpos.west()), Direction.WEST)); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(TripWireBlock.NORTH, this.shouldConnectTo(world.getBlockState(blockposition.north()), Direction.NORTH))).setValue(TripWireBlock.EAST, this.shouldConnectTo(world.getBlockState(blockposition.east()), Direction.EAST))).setValue(TripWireBlock.SOUTH, this.shouldConnectTo(world.getBlockState(blockposition.south()), Direction.SOUTH))).setValue(TripWireBlock.WEST, this.shouldConnectTo(world.getBlockState(blockposition.west()), Direction.WEST)); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- return direction.getAxis().isHorizontal() ? (BlockState) blockstate.setValue((Property) TripWireBlock.PROPERTY_BY_DIRECTION.get(direction), this.shouldConnectTo(blockstate1, direction)) : super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ return facing.getAxis().isHorizontal() ? (IBlockData) state.setValue((Property) TripWireBlock.PROPERTY_BY_DIRECTION.get(facing), this.shouldConnectTo(facingState, facing)) : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!blockstate1.is(blockstate.getBlock())) { +- this.updateSource(level, blockpos, blockstate); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ if (!oldState.is(state.getBlock())) { ++ this.updateSource(level, pos, state); + } + } + + @Override +- @Override +- public void onRemove(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!flag && !blockstate.is(blockstate1.getBlock())) { +- this.updateSource(level, blockpos, (BlockState) blockstate.setValue(TripWireBlock.POWERED, true)); ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { ++ if (!isMoving && !state.is(newState.getBlock())) { ++ this.updateSource(level, pos, (IBlockData) state.setValue(TripWireBlock.POWERED, true)); + } + } + + @Override +- @Override +- public BlockState playerWillDestroy(Level level, BlockPos blockpos, BlockState blockstate, Player player) { +- if (!level.isClientSide && !player.getMainHandItem().isEmpty() && player.getMainHandItem().is(Items.SHEARS)) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(TripWireBlock.DISARMED, true), 4); +- level.gameEvent((Entity) player, GameEvent.SHEAR, blockpos); ++ public IBlockData playerWillDestroy(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ if (!world.isClientSide && !entityhuman.getMainHandItem().isEmpty() && entityhuman.getMainHandItem().is(Items.SHEARS)) { ++ world.setBlock(blockposition, (IBlockData) iblockdata.setValue(TripWireBlock.DISARMED, true), 4); ++ world.gameEvent((Entity) entityhuman, GameEvent.SHEAR, blockposition); + } + +- return super.playerWillDestroy(level, blockpos, blockstate, player); ++ return super.playerWillDestroy(world, blockposition, iblockdata, entityhuman); + } + +- private void updateSource(Level level, BlockPos blockpos, BlockState blockstate) { +- Direction[] adirection = new Direction[]{Direction.SOUTH, Direction.WEST}; +- int i = adirection.length; ++ private void updateSource(Level level, BlockPos pos, IBlockData state) { ++ Direction[] aenumdirection = new Direction[]{Direction.SOUTH, Direction.WEST}; ++ int i = aenumdirection.length; + int j = 0; + + while (j < i) { +- Direction direction = adirection[j]; ++ Direction enumdirection = aenumdirection[j]; + int k = 1; + + while (true) { + if (k < 42) { +- BlockPos blockpos1 = blockpos.relative(direction, k); +- BlockState blockstate1 = level.getBlockState(blockpos1); ++ BlockPos blockposition1 = pos.relative(enumdirection, k); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + +- if (blockstate1.is(this.hook)) { +- if (blockstate1.getValue(TripWireHookBlock.FACING) == direction.getOpposite()) { +- TripWireHookBlock.calculateState(level, blockpos1, blockstate1, false, true, k, blockstate); ++ if (iblockdata1.is(this.hook)) { ++ if (iblockdata1.getValue(TripWireHookBlock.FACING) == enumdirection.getOpposite()) { ++ TripWireHookBlock.calculateState(level, blockposition1, iblockdata1, false, true, k, state); + } +- } else if (blockstate1.is((Block) this)) { ++ } else if (iblockdata1.is((Block) this)) { + ++k; + continue; + } +@@ -139,28 +133,26 @@ + } + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { + if (!level.isClientSide) { +- if (!(Boolean) blockstate.getValue(TripWireBlock.POWERED)) { +- this.checkPressed(level, blockpos); ++ if (!(Boolean) state.getValue(TripWireBlock.POWERED)) { ++ this.checkPressed(level, pos); + } + } + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if ((Boolean) serverlevel.getBlockState(blockpos).getValue(TripWireBlock.POWERED)) { +- this.checkPressed(serverlevel, blockpos); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) level.getBlockState(pos).getValue(TripWireBlock.POWERED)) { ++ this.checkPressed(level, pos); + } + } + +- private void checkPressed(Level level, BlockPos blockpos) { +- BlockState blockstate = level.getBlockState(blockpos); +- boolean flag = (Boolean) blockstate.getValue(TripWireBlock.POWERED); ++ private void checkPressed(Level level, BlockPos pos) { ++ IBlockData iblockdata = level.getBlockState(pos); ++ boolean flag = (Boolean) iblockdata.getValue(TripWireBlock.POWERED); + boolean flag1 = false; +- List list = level.getEntities((Entity) null, blockstate.getShape(level, blockpos).bounds().move(blockpos)); ++ List list = level.getEntities((Entity) null, iblockdata.getShape(level, pos).bounds().move(pos)); + + if (!list.isEmpty()) { + Iterator iterator = list.iterator(); +@@ -175,53 +167,84 @@ + } + } + ++ // CraftBukkit start - Call interact even when triggering connected tripwire ++ if (flag != flag1 && flag1 && (Boolean)iblockdata.getValue(ATTACHED)) { ++ org.bukkit.World bworld = level.getWorld(); ++ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager(); ++ org.bukkit.block.Block block = bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ boolean allowed = false; ++ ++ // If all of the events are cancelled block the tripwire trigger, else allow ++ for (Object object : list) { ++ if (object != null) { ++ org.bukkit.event.Cancellable cancellable; ++ ++ if (object instanceof Player) { ++ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) object, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else if (object instanceof Entity) { ++ cancellable = new EntityInteractEvent(((Entity) object).getBukkitEntity(), block); ++ manager.callEvent((EntityInteractEvent) cancellable); ++ } else { ++ continue; ++ } ++ ++ if (!cancellable.isCancelled()) { ++ allowed = true; ++ break; ++ } ++ } ++ } ++ ++ if (!allowed) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ + if (flag1 != flag) { +- blockstate = (BlockState) blockstate.setValue(TripWireBlock.POWERED, flag1); +- level.setBlock(blockpos, blockstate, 3); +- this.updateSource(level, blockpos, blockstate); ++ iblockdata = (IBlockData) iblockdata.setValue(TripWireBlock.POWERED, flag1); ++ level.setBlock(pos, iblockdata, 3); ++ this.updateSource(level, pos, iblockdata); + } + + if (flag1) { +- level.scheduleTick(new BlockPos(blockpos), (Block) this, 10); ++ level.scheduleTick(new BlockPos(pos), (Block) this, 10); + } + + } + +- public boolean shouldConnectTo(BlockState blockstate, Direction direction) { +- return blockstate.is(this.hook) ? blockstate.getValue(TripWireHookBlock.FACING) == direction.getOpposite() : blockstate.is((Block) this); ++ public boolean shouldConnectTo(IBlockData state, Direction direction) { ++ return state.is(this.hook) ? state.getValue(TripWireHookBlock.FACING) == direction.getOpposite() : state.is((Block) this); + } + + @Override +- @Override +- public BlockState rotate(BlockState blockstate, Rotation rotation) { +- switch (rotation) { ++ public IBlockData rotate(IBlockData state, Rotation rot) { ++ switch (rot) { + case CLOCKWISE_180: +- return (BlockState) ((BlockState) ((BlockState) ((BlockState) blockstate.setValue(TripWireBlock.NORTH, (Boolean) blockstate.getValue(TripWireBlock.SOUTH))).setValue(TripWireBlock.EAST, (Boolean) blockstate.getValue(TripWireBlock.WEST))).setValue(TripWireBlock.SOUTH, (Boolean) blockstate.getValue(TripWireBlock.NORTH))).setValue(TripWireBlock.WEST, (Boolean) blockstate.getValue(TripWireBlock.EAST)); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) state.setValue(TripWireBlock.NORTH, (Boolean) state.getValue(TripWireBlock.SOUTH))).setValue(TripWireBlock.EAST, (Boolean) state.getValue(TripWireBlock.WEST))).setValue(TripWireBlock.SOUTH, (Boolean) state.getValue(TripWireBlock.NORTH))).setValue(TripWireBlock.WEST, (Boolean) state.getValue(TripWireBlock.EAST)); + case COUNTERCLOCKWISE_90: +- return (BlockState) ((BlockState) ((BlockState) ((BlockState) blockstate.setValue(TripWireBlock.NORTH, (Boolean) blockstate.getValue(TripWireBlock.EAST))).setValue(TripWireBlock.EAST, (Boolean) blockstate.getValue(TripWireBlock.SOUTH))).setValue(TripWireBlock.SOUTH, (Boolean) blockstate.getValue(TripWireBlock.WEST))).setValue(TripWireBlock.WEST, (Boolean) blockstate.getValue(TripWireBlock.NORTH)); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) state.setValue(TripWireBlock.NORTH, (Boolean) state.getValue(TripWireBlock.EAST))).setValue(TripWireBlock.EAST, (Boolean) state.getValue(TripWireBlock.SOUTH))).setValue(TripWireBlock.SOUTH, (Boolean) state.getValue(TripWireBlock.WEST))).setValue(TripWireBlock.WEST, (Boolean) state.getValue(TripWireBlock.NORTH)); + case CLOCKWISE_90: +- return (BlockState) ((BlockState) ((BlockState) ((BlockState) blockstate.setValue(TripWireBlock.NORTH, (Boolean) blockstate.getValue(TripWireBlock.WEST))).setValue(TripWireBlock.EAST, (Boolean) blockstate.getValue(TripWireBlock.NORTH))).setValue(TripWireBlock.SOUTH, (Boolean) blockstate.getValue(TripWireBlock.EAST))).setValue(TripWireBlock.WEST, (Boolean) blockstate.getValue(TripWireBlock.SOUTH)); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) state.setValue(TripWireBlock.NORTH, (Boolean) state.getValue(TripWireBlock.WEST))).setValue(TripWireBlock.EAST, (Boolean) state.getValue(TripWireBlock.NORTH))).setValue(TripWireBlock.SOUTH, (Boolean) state.getValue(TripWireBlock.EAST))).setValue(TripWireBlock.WEST, (Boolean) state.getValue(TripWireBlock.SOUTH)); + default: +- return blockstate; ++ return state; + } + } + + @Override +- @Override +- public BlockState mirror(BlockState blockstate, Mirror mirror) { ++ public IBlockData mirror(IBlockData state, Mirror mirror) { + switch (mirror) { + case LEFT_RIGHT: +- return (BlockState) ((BlockState) blockstate.setValue(TripWireBlock.NORTH, (Boolean) blockstate.getValue(TripWireBlock.SOUTH))).setValue(TripWireBlock.SOUTH, (Boolean) blockstate.getValue(TripWireBlock.NORTH)); ++ return (IBlockData) ((IBlockData) state.setValue(TripWireBlock.NORTH, (Boolean) state.getValue(TripWireBlock.SOUTH))).setValue(TripWireBlock.SOUTH, (Boolean) state.getValue(TripWireBlock.NORTH)); + case FRONT_BACK: +- return (BlockState) ((BlockState) blockstate.setValue(TripWireBlock.EAST, (Boolean) blockstate.getValue(TripWireBlock.WEST))).setValue(TripWireBlock.WEST, (Boolean) blockstate.getValue(TripWireBlock.EAST)); ++ return (IBlockData) ((IBlockData) state.setValue(TripWireBlock.EAST, (Boolean) state.getValue(TripWireBlock.WEST))).setValue(TripWireBlock.WEST, (Boolean) state.getValue(TripWireBlock.EAST)); + default: +- return super.mirror(blockstate, mirror); ++ return super.mirror(state, mirror); + } + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(TripWireBlock.POWERED, TripWireBlock.ATTACHED, TripWireBlock.DISARMED, TripWireBlock.NORTH, TripWireBlock.EAST, TripWireBlock.WEST, TripWireBlock.SOUTH); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(TripWireBlock.POWERED, TripWireBlock.ATTACHED, TripWireBlock.DISARMED, TripWireBlock.NORTH, TripWireBlock.EAST, TripWireBlock.WEST, TripWireBlock.SOUTH); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/TripWireHookBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/TripWireHookBlock.java.patch new file mode 100644 index 0000000000..d2d0babfe9 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/TripWireHookBlock.java.patch @@ -0,0 +1,370 @@ +--- a/net/minecraft/world/level/block/TripWireHookBlock.java ++++ b/net/minecraft/world/level/block/TripWireHookBlock.java +@@ -20,7 +20,7 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -28,6 +28,10 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockRedstoneEvent; ++// CraftBukkit end + + public class TripWireHookBlock extends Block { + +@@ -45,20 +49,18 @@ + protected static final VoxelShape EAST_AABB = Block.box(0.0D, 0.0D, 5.0D, 6.0D, 10.0D, 11.0D); + + @Override +- @Override + public MapCodec codec() { + return TripWireHookBlock.CODEC; + } + +- public TripWireHookBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(TripWireHookBlock.FACING, Direction.NORTH)).setValue(TripWireHookBlock.POWERED, false)).setValue(TripWireHookBlock.ATTACHED, false)); ++ public TripWireHookBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(TripWireHookBlock.FACING, Direction.NORTH)).setValue(TripWireHookBlock.POWERED, false)).setValue(TripWireHookBlock.ATTACHED, false)); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- switch ((Direction) blockstate.getValue(TripWireHookBlock.FACING)) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ switch ((Direction) state.getValue(TripWireHookBlock.FACING)) { + case EAST: + default: + return TripWireHookBlock.EAST_AABB; +@@ -72,41 +74,38 @@ + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- Direction direction = (Direction) blockstate.getValue(TripWireHookBlock.FACING); +- BlockPos blockpos1 = blockpos.relative(direction.getOpposite()); +- BlockState blockstate1 = levelreader.getBlockState(blockpos1); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ Direction enumdirection = (Direction) state.getValue(TripWireHookBlock.FACING); ++ BlockPos blockposition1 = pos.relative(enumdirection.getOpposite()); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + +- return direction.getAxis().isHorizontal() && blockstate1.isFaceSturdy(levelreader, blockpos1, direction); ++ return enumdirection.getAxis().isHorizontal() && iblockdata1.isFaceSturdy(level, blockposition1, enumdirection); + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- return direction.getOpposite() == blockstate.getValue(TripWireHookBlock.FACING) && !blockstate.canSurvive(levelaccessor, blockpos) ? Blocks.AIR.defaultBlockState() : super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ return facing.getOpposite() == state.getValue(TripWireHookBlock.FACING) && !state.canSurvive(level, currentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Nullable + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- BlockState blockstate = (BlockState) ((BlockState) this.defaultBlockState().setValue(TripWireHookBlock.POWERED, false)).setValue(TripWireHookBlock.ATTACHED, false); +- Level level = blockplacecontext.getLevel(); +- BlockPos blockpos = blockplacecontext.getClickedPos(); +- Direction[] adirection = blockplacecontext.getNearestLookingDirections(); +- Direction[] adirection1 = adirection; +- int i = adirection.length; ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ IBlockData iblockdata = (IBlockData) ((IBlockData) this.defaultBlockState().setValue(TripWireHookBlock.POWERED, false)).setValue(TripWireHookBlock.ATTACHED, false); ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ Direction[] aenumdirection = context.getNearestLookingDirections(); ++ Direction[] aenumdirection1 = aenumdirection; ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection1[j]; ++ Direction enumdirection = aenumdirection1[j]; + +- if (direction.getAxis().isHorizontal()) { +- Direction direction1 = direction.getOpposite(); ++ if (enumdirection.getAxis().isHorizontal()) { ++ Direction enumdirection1 = enumdirection.getOpposite(); + +- blockstate = (BlockState) blockstate.setValue(TripWireHookBlock.FACING, direction1); +- if (blockstate.canSurvive(level, blockpos)) { +- return blockstate; ++ iblockdata = (IBlockData) iblockdata.setValue(TripWireHookBlock.FACING, enumdirection1); ++ if (iblockdata.canSurvive(world, blockposition)) { ++ return iblockdata; + } + } + } +@@ -115,52 +114,51 @@ + } + + @Override +- @Override +- public void setPlacedBy(Level level, BlockPos blockpos, BlockState blockstate, LivingEntity livingentity, ItemStack itemstack) { +- calculateState(level, blockpos, blockstate, false, false, -1, (BlockState) null); ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, LivingEntity placer, ItemStack stack) { ++ calculateState(level, pos, state, false, false, -1, (IBlockData) null); + } + +- public static void calculateState(Level level, BlockPos blockpos, BlockState blockstate, boolean flag, boolean flag1, int i, @Nullable BlockState blockstate1) { +- Optional optional = blockstate.getOptionalValue(TripWireHookBlock.FACING); ++ public static void calculateState(Level world, BlockPos level, IBlockData pos, boolean hookState, boolean attaching, int shouldNotifyNeighbours, @Nullable IBlockData searchRange) { ++ Optional optional = pos.getOptionalValue(TripWireHookBlock.FACING); + + if (optional.isPresent()) { +- Direction direction = (Direction) optional.get(); +- boolean flag2 = (Boolean) blockstate.getOptionalValue(TripWireHookBlock.ATTACHED).orElse(false); +- boolean flag3 = (Boolean) blockstate.getOptionalValue(TripWireHookBlock.POWERED).orElse(false); +- Block block = blockstate.getBlock(); +- boolean flag4 = !flag; ++ Direction enumdirection = (Direction) optional.get(); ++ boolean flag2 = (Boolean) pos.getOptionalValue(TripWireHookBlock.ATTACHED).orElse(false); ++ boolean flag3 = (Boolean) pos.getOptionalValue(TripWireHookBlock.POWERED).orElse(false); ++ Block block = pos.getBlock(); ++ boolean flag4 = !hookState; + boolean flag5 = false; + int j = 0; +- BlockState[] ablockstate = new BlockState[42]; ++ IBlockData[] aiblockdata = new IBlockData[42]; + +- BlockPos blockpos1; ++ BlockPos blockposition1; + + for (int k = 1; k < 42; ++k) { +- blockpos1 = blockpos.relative(direction, k); +- BlockState blockstate2 = level.getBlockState(blockpos1); ++ blockposition1 = level.relative(enumdirection, k); ++ IBlockData iblockdata2 = world.getBlockState(blockposition1); + +- if (blockstate2.is(Blocks.TRIPWIRE_HOOK)) { +- if (blockstate2.getValue(TripWireHookBlock.FACING) == direction.getOpposite()) { ++ if (iblockdata2.is(Blocks.TRIPWIRE_HOOK)) { ++ if (iblockdata2.getValue(TripWireHookBlock.FACING) == enumdirection.getOpposite()) { + j = k; + } + break; + } + +- if (!blockstate2.is(Blocks.TRIPWIRE) && k != i) { +- ablockstate[k] = null; ++ if (!iblockdata2.is(Blocks.TRIPWIRE) && k != shouldNotifyNeighbours) { ++ aiblockdata[k] = null; + flag4 = false; + } else { +- if (k == i) { +- blockstate2 = (BlockState) MoreObjects.firstNonNull(blockstate1, blockstate2); ++ if (k == shouldNotifyNeighbours) { ++ iblockdata2 = (IBlockData) MoreObjects.firstNonNull(searchRange, iblockdata2); + } + +- boolean flag6 = !(Boolean) blockstate2.getValue(TripWireBlock.DISARMED); +- boolean flag7 = (Boolean) blockstate2.getValue(TripWireBlock.POWERED); ++ boolean flag6 = !(Boolean) iblockdata2.getValue(TripWireBlock.DISARMED); ++ boolean flag7 = (Boolean) iblockdata2.getValue(TripWireBlock.POWERED); + + flag5 |= flag6 && flag7; +- ablockstate[k] = blockstate2; +- if (k == i) { +- level.scheduleTick(blockpos, block, 10); ++ aiblockdata[k] = iblockdata2; ++ if (k == shouldNotifyNeighbours) { ++ world.scheduleTick(level, block, 10); + flag4 &= flag6; + } + } +@@ -168,33 +166,42 @@ + + flag4 &= j > 1; + flag5 &= flag4; +- BlockState blockstate3 = (BlockState) ((BlockState) block.defaultBlockState().trySetValue(TripWireHookBlock.ATTACHED, flag4)).trySetValue(TripWireHookBlock.POWERED, flag5); ++ IBlockData iblockdata3 = (IBlockData) ((IBlockData) block.defaultBlockState().trySetValue(TripWireHookBlock.ATTACHED, flag4)).trySetValue(TripWireHookBlock.POWERED, flag5); + + if (j > 0) { +- blockpos1 = blockpos.relative(direction, j); +- Direction direction1 = direction.getOpposite(); ++ blockposition1 = level.relative(enumdirection, j); ++ Direction enumdirection1 = enumdirection.getOpposite(); + +- level.setBlock(blockpos1, (BlockState) blockstate3.setValue(TripWireHookBlock.FACING, direction1), 3); +- notifyNeighbors(block, level, blockpos1, direction1); +- emitState(level, blockpos1, flag4, flag5, flag2, flag3); ++ world.setBlock(blockposition1, (IBlockData) iblockdata3.setValue(TripWireHookBlock.FACING, enumdirection1), 3); ++ notifyNeighbors(block, world, blockposition1, enumdirection1); ++ emitState(world, blockposition1, flag4, flag5, flag2, flag3); + } + +- emitState(level, blockpos, flag4, flag5, flag2, flag3); +- if (!flag) { +- level.setBlock(blockpos, (BlockState) blockstate3.setValue(TripWireHookBlock.FACING, direction), 3); +- if (flag1) { +- notifyNeighbors(block, level, blockpos, direction); ++ // CraftBukkit start ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(world, level), 15, 0); ++ world.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if (eventRedstone.getNewCurrent() > 0) { ++ return; ++ } ++ // CraftBukkit end ++ ++ emitState(world, level, flag4, flag5, flag2, flag3); ++ if (!hookState) { ++ world.setBlock(level, (IBlockData) iblockdata3.setValue(TripWireHookBlock.FACING, enumdirection), 3); ++ if (attaching) { ++ notifyNeighbors(block, world, level, enumdirection); + } + } + + if (flag2 != flag4) { + for (int l = 1; l < j; ++l) { +- BlockPos blockpos2 = blockpos.relative(direction, l); +- BlockState blockstate4 = ablockstate[l]; ++ BlockPos blockposition2 = level.relative(enumdirection, l); ++ IBlockData iblockdata4 = aiblockdata[l]; + +- if (blockstate4 != null) { +- level.setBlock(blockpos2, (BlockState) blockstate4.trySetValue(TripWireHookBlock.ATTACHED, flag4), 3); +- if (!level.getBlockState(blockpos2).isAir()) { ++ if (iblockdata4 != null) { ++ world.setBlock(blockposition2, (IBlockData) iblockdata4.trySetValue(TripWireHookBlock.ATTACHED, flag4), 3); ++ if (!world.getBlockState(blockposition2).isAir()) { + ; + } + } +@@ -205,86 +212,78 @@ + } + + @Override +- @Override +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- calculateState(serverlevel, blockpos, blockstate, false, true, -1, (BlockState) null); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ calculateState(level, pos, state, false, true, -1, (IBlockData) null); + } + +- private static void emitState(Level level, BlockPos blockpos, boolean flag, boolean flag1, boolean flag2, boolean flag3) { +- if (flag1 && !flag3) { +- level.playSound((Player) null, blockpos, SoundEvents.TRIPWIRE_CLICK_ON, SoundSource.BLOCKS, 0.4F, 0.6F); +- level.gameEvent((Entity) null, GameEvent.BLOCK_ACTIVATE, blockpos); +- } else if (!flag1 && flag3) { +- level.playSound((Player) null, blockpos, SoundEvents.TRIPWIRE_CLICK_OFF, SoundSource.BLOCKS, 0.4F, 0.5F); +- level.gameEvent((Entity) null, GameEvent.BLOCK_DEACTIVATE, blockpos); +- } else if (flag && !flag2) { +- level.playSound((Player) null, blockpos, SoundEvents.TRIPWIRE_ATTACH, SoundSource.BLOCKS, 0.4F, 0.7F); +- level.gameEvent((Entity) null, GameEvent.BLOCK_ATTACH, blockpos); +- } else if (!flag && flag2) { +- level.playSound((Player) null, blockpos, SoundEvents.TRIPWIRE_DETACH, SoundSource.BLOCKS, 0.4F, 1.2F / (level.random.nextFloat() * 0.2F + 0.9F)); +- level.gameEvent((Entity) null, GameEvent.BLOCK_DETACH, blockpos); ++ private static void emitState(Level world, BlockPos level, boolean pos, boolean attached, boolean powered, boolean wasAttached) { ++ if (attached && !wasAttached) { ++ world.playSound((Player) null, level, SoundEvents.TRIPWIRE_CLICK_ON, SoundSource.BLOCKS, 0.4F, 0.6F); ++ world.gameEvent((Entity) null, GameEvent.BLOCK_ACTIVATE, level); ++ } else if (!attached && wasAttached) { ++ world.playSound((Player) null, level, SoundEvents.TRIPWIRE_CLICK_OFF, SoundSource.BLOCKS, 0.4F, 0.5F); ++ world.gameEvent((Entity) null, GameEvent.BLOCK_DEACTIVATE, level); ++ } else if (pos && !powered) { ++ world.playSound((Player) null, level, SoundEvents.TRIPWIRE_ATTACH, SoundSource.BLOCKS, 0.4F, 0.7F); ++ world.gameEvent((Entity) null, GameEvent.BLOCK_ATTACH, level); ++ } else if (!pos && powered) { ++ world.playSound((Player) null, level, SoundEvents.TRIPWIRE_DETACH, SoundSource.BLOCKS, 0.4F, 1.2F / (world.random.nextFloat() * 0.2F + 0.9F)); ++ world.gameEvent((Entity) null, GameEvent.BLOCK_DETACH, level); + } + + } + +- private static void notifyNeighbors(Block block, Level level, BlockPos blockpos, Direction direction) { +- level.updateNeighborsAt(blockpos, block); +- level.updateNeighborsAt(blockpos.relative(direction.getOpposite()), block); ++ private static void notifyNeighbors(Block block, Level world, BlockPos blockposition, Direction enumdirection) { ++ world.updateNeighborsAt(blockposition, block); ++ world.updateNeighborsAt(blockposition.relative(enumdirection.getOpposite()), block); + } + + @Override +- @Override +- public void onRemove(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!flag && !blockstate.is(blockstate1.getBlock())) { +- boolean flag1 = (Boolean) blockstate.getValue(TripWireHookBlock.ATTACHED); +- boolean flag2 = (Boolean) blockstate.getValue(TripWireHookBlock.POWERED); ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { ++ if (!isMoving && !state.is(newState.getBlock())) { ++ boolean flag1 = (Boolean) state.getValue(TripWireHookBlock.ATTACHED); ++ boolean flag2 = (Boolean) state.getValue(TripWireHookBlock.POWERED); + + if (flag1 || flag2) { +- calculateState(level, blockpos, blockstate, true, false, -1, (BlockState) null); ++ calculateState(level, pos, state, true, false, -1, (IBlockData) null); + } + + if (flag2) { +- level.updateNeighborsAt(blockpos, this); +- level.updateNeighborsAt(blockpos.relative(((Direction) blockstate.getValue(TripWireHookBlock.FACING)).getOpposite()), this); ++ level.updateNeighborsAt(pos, this); ++ level.updateNeighborsAt(pos.relative(((Direction) state.getValue(TripWireHookBlock.FACING)).getOpposite()), this); + } + +- super.onRemove(blockstate, level, blockpos, blockstate1, flag); ++ super.onRemove(state, level, pos, newState, isMoving); + } + } + + @Override +- @Override +- public int getSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return (Boolean) blockstate.getValue(TripWireHookBlock.POWERED) ? 15 : 0; ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return (Boolean) blockState.getValue(TripWireHookBlock.POWERED) ? 15 : 0; + } + + @Override +- @Override +- public int getDirectSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return !(Boolean) blockstate.getValue(TripWireHookBlock.POWERED) ? 0 : (blockstate.getValue(TripWireHookBlock.FACING) == direction ? 15 : 0); ++ public int getDirectSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return !(Boolean) blockState.getValue(TripWireHookBlock.POWERED) ? 0 : (blockState.getValue(TripWireHookBlock.FACING) == side ? 15 : 0); + } + + @Override +- @Override +- public boolean isSignalSource(BlockState blockstate) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + + @Override +- @Override +- public BlockState rotate(BlockState blockstate, Rotation rotation) { +- return (BlockState) blockstate.setValue(TripWireHookBlock.FACING, rotation.rotate((Direction) blockstate.getValue(TripWireHookBlock.FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return (IBlockData) state.setValue(TripWireHookBlock.FACING, rotation.rotate((Direction) state.getValue(TripWireHookBlock.FACING))); + } + + @Override +- @Override +- public BlockState mirror(BlockState blockstate, Mirror mirror) { +- return blockstate.rotate(mirror.getRotation((Direction) blockstate.getValue(TripWireHookBlock.FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(TripWireHookBlock.FACING))); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(TripWireHookBlock.FACING, TripWireHookBlock.POWERED, TripWireHookBlock.ATTACHED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(TripWireHookBlock.FACING, TripWireHookBlock.POWERED, TripWireHookBlock.ATTACHED); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/TurtleEggBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/TurtleEggBlock.java.patch new file mode 100644 index 0000000000..0fe855926f --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/TurtleEggBlock.java.patch @@ -0,0 +1,242 @@ +--- a/net/minecraft/world/level/block/TurtleEggBlock.java ++++ b/net/minecraft/world/level/block/TurtleEggBlock.java +@@ -22,13 +22,18 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.event.entity.EntityInteractEvent; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class TurtleEggBlock extends Block { + +@@ -42,83 +47,102 @@ + public static final IntegerProperty EGGS = BlockStateProperties.EGGS; + + @Override +- @Override + public MapCodec codec() { + return TurtleEggBlock.CODEC; + } + +- public TurtleEggBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(TurtleEggBlock.HATCH, 0)).setValue(TurtleEggBlock.EGGS, 1)); ++ public TurtleEggBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(TurtleEggBlock.HATCH, 0)).setValue(TurtleEggBlock.EGGS, 1)); + } + + @Override +- @Override +- public void stepOn(Level level, BlockPos blockpos, BlockState blockstate, Entity entity) { ++ public void stepOn(Level level, BlockPos pos, IBlockData state, Entity entity) { + if (!entity.isSteppingCarefully()) { +- this.destroyEgg(level, blockstate, blockpos, entity, 100); ++ this.destroyEgg(level, state, pos, entity, 100); + } + +- super.stepOn(level, blockpos, blockstate, entity); ++ super.stepOn(level, pos, state, entity); + } + + @Override +- @Override +- public void fallOn(Level level, BlockState blockstate, BlockPos blockpos, Entity entity, float f) { ++ public void fallOn(Level level, IBlockData state, BlockPos pos, Entity entity, float fallDistance) { + if (!(entity instanceof Zombie)) { +- this.destroyEgg(level, blockstate, blockpos, entity, 3); ++ this.destroyEgg(level, state, pos, entity, 3); + } + +- super.fallOn(level, blockstate, blockpos, entity, f); ++ super.fallOn(level, state, pos, entity, fallDistance); + } + +- private void destroyEgg(Level level, BlockState blockstate, BlockPos blockpos, Entity entity, int i) { ++ private void destroyEgg(Level level, IBlockData state, BlockPos pos, Entity entity, int chance) { + if (this.canDestroyEgg(level, entity)) { +- if (!level.isClientSide && level.random.nextInt(i) == 0 && blockstate.is(Blocks.TURTLE_EGG)) { +- this.decreaseEggs(level, blockpos, blockstate); ++ if (!level.isClientSide && level.random.nextInt(chance) == 0 && state.is(Blocks.TURTLE_EGG)) { ++ // CraftBukkit start - Step on eggs ++ org.bukkit.event.Cancellable cancellable; ++ if (entity instanceof Player) { ++ cancellable = CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), CraftBlock.at(level, pos)); ++ level.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ if (cancellable.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ this.decreaseEggs(level, pos, state); + } + + } + } + +- private void decreaseEggs(Level level, BlockPos blockpos, BlockState blockstate) { +- level.playSound((Player) null, blockpos, SoundEvents.TURTLE_EGG_BREAK, SoundSource.BLOCKS, 0.7F, 0.9F + level.random.nextFloat() * 0.2F); +- int i = (Integer) blockstate.getValue(TurtleEggBlock.EGGS); ++ private void decreaseEggs(Level level, BlockPos pos, IBlockData state) { ++ level.playSound((Player) null, pos, SoundEvents.TURTLE_EGG_BREAK, SoundSource.BLOCKS, 0.7F, 0.9F + level.random.nextFloat() * 0.2F); ++ int i = (Integer) state.getValue(TurtleEggBlock.EGGS); + + if (i <= 1) { +- level.destroyBlock(blockpos, false); ++ level.destroyBlock(pos, false); + } else { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(TurtleEggBlock.EGGS, i - 1), 2); +- level.gameEvent(GameEvent.BLOCK_DESTROY, blockpos, GameEvent.Context.of(blockstate)); +- level.levelEvent(2001, blockpos, Block.getId(blockstate)); ++ level.setBlock(pos, (IBlockData) state.setValue(TurtleEggBlock.EGGS, i - 1), 2); ++ level.gameEvent(GameEvent.BLOCK_DESTROY, pos, GameEvent.Context.of(state)); ++ level.levelEvent(2001, pos, Block.getId(state)); + } + + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (this.shouldUpdateHatchLevel(serverlevel) && onSand(serverlevel, blockpos)) { +- int i = (Integer) blockstate.getValue(TurtleEggBlock.HATCH); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (this.shouldUpdateHatchLevel(level) && onSand(level, pos)) { ++ int i = (Integer) state.getValue(TurtleEggBlock.HATCH); + + if (i < 2) { +- serverlevel.playSound((Player) null, blockpos, SoundEvents.TURTLE_EGG_CRACK, SoundSource.BLOCKS, 0.7F, 0.9F + randomsource.nextFloat() * 0.2F); +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(TurtleEggBlock.HATCH, i + 1), 2); +- serverlevel.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(blockstate)); ++ // CraftBukkit start - Call BlockGrowEvent ++ if (!CraftEventFactory.handleBlockGrowEvent(level, pos, state.setValue(TurtleEggBlock.HATCH, i + 1), 2)) { ++ return; ++ } ++ // CraftBukkit end ++ level.playSound((Player) null, pos, SoundEvents.TURTLE_EGG_CRACK, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F); ++ // worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockTurtleEgg.HATCH, i + 1), 2); // CraftBukkit - handled above ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(state)); + } else { +- serverlevel.playSound((Player) null, blockpos, SoundEvents.TURTLE_EGG_HATCH, SoundSource.BLOCKS, 0.7F, 0.9F + randomsource.nextFloat() * 0.2F); +- serverlevel.removeBlock(blockpos, false); +- serverlevel.gameEvent(GameEvent.BLOCK_DESTROY, blockpos, GameEvent.Context.of(blockstate)); ++ // CraftBukkit start - Call BlockFadeEvent ++ if (CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.AIR.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.playSound((Player) null, pos, SoundEvents.TURTLE_EGG_HATCH, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F); ++ level.removeBlock(pos, false); ++ level.gameEvent(GameEvent.BLOCK_DESTROY, pos, GameEvent.Context.of(state)); + +- for (int j = 0; j < (Integer) blockstate.getValue(TurtleEggBlock.EGGS); ++j) { +- serverlevel.levelEvent(2001, blockpos, Block.getId(blockstate)); +- Turtle turtle = (Turtle) EntityType.TURTLE.create(serverlevel); ++ for (int j = 0; j < (Integer) state.getValue(TurtleEggBlock.EGGS); ++j) { ++ level.levelEvent(2001, pos, Block.getId(state)); ++ Turtle entityturtle = (Turtle) EntityType.TURTLE.create(level); + +- if (turtle != null) { +- turtle.setAge(-24000); +- turtle.setHomePos(blockpos); +- turtle.moveTo((double) blockpos.getX() + 0.3D + (double) j * 0.2D, (double) blockpos.getY(), (double) blockpos.getZ() + 0.3D, 0.0F, 0.0F); +- serverlevel.addFreshEntity(turtle); ++ if (entityturtle != null) { ++ entityturtle.setAge(-24000); ++ entityturtle.setHomePos(pos); ++ entityturtle.moveTo((double) pos.getX() + 0.3D + (double) j * 0.2D, (double) pos.getY(), (double) pos.getZ() + 0.3D, 0.0F, 0.0F); ++ level.addFreshEntity(entityturtle, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); // CraftBukkit + } + } + } +@@ -126,19 +150,18 @@ + + } + +- public static boolean onSand(BlockGetter blockgetter, BlockPos blockpos) { +- return isSand(blockgetter, blockpos.below()); ++ public static boolean onSand(BlockGetter level, BlockPos pos) { ++ return isSand(level, pos.below()); + } + +- public static boolean isSand(BlockGetter blockgetter, BlockPos blockpos) { +- return blockgetter.getBlockState(blockpos).is(BlockTags.SAND); ++ public static boolean isSand(BlockGetter reader, BlockPos pos) { ++ return reader.getBlockState(pos).is(BlockTags.SAND); + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (onSand(level, blockpos) && !level.isClientSide) { +- level.levelEvent(2005, blockpos, 0); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ if (onSand(level, pos) && !level.isClientSide) { ++ level.levelEvent(2005, pos, 0); + } + + } +@@ -150,37 +173,32 @@ + } + + @Override +- @Override +- public void playerDestroy(Level level, Player player, BlockPos blockpos, BlockState blockstate, @Nullable BlockEntity blockentity, ItemStack itemstack) { +- super.playerDestroy(level, player, blockpos, blockstate, blockentity, itemstack); +- this.decreaseEggs(level, blockpos, blockstate); ++ public void playerDestroy(Level level, Player player, BlockPos pos, IBlockData state, @Nullable BlockEntity te, ItemStack stack) { ++ super.playerDestroy(level, player, pos, state, te, stack); ++ this.decreaseEggs(level, pos, state); + } + + @Override +- @Override +- public boolean canBeReplaced(BlockState blockstate, BlockPlaceContext blockplacecontext) { +- return !blockplacecontext.isSecondaryUseActive() && blockplacecontext.getItemInHand().is(this.asItem()) && (Integer) blockstate.getValue(TurtleEggBlock.EGGS) < 4 ? true : super.canBeReplaced(blockstate, blockplacecontext); ++ public boolean canBeReplaced(IBlockData state, BlockPlaceContext useContext) { ++ return !useContext.isSecondaryUseActive() && useContext.getItemInHand().is(this.asItem()) && (Integer) state.getValue(TurtleEggBlock.EGGS) < 4 ? true : super.canBeReplaced(state, useContext); + } + + @Nullable + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- BlockState blockstate = blockplacecontext.getLevel().getBlockState(blockplacecontext.getClickedPos()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ IBlockData iblockdata = context.getLevel().getBlockState(context.getClickedPos()); + +- return blockstate.is((Block) this) ? (BlockState) blockstate.setValue(TurtleEggBlock.EGGS, Math.min(4, (Integer) blockstate.getValue(TurtleEggBlock.EGGS) + 1)) : super.getStateForPlacement(blockplacecontext); ++ return iblockdata.is((Block) this) ? (IBlockData) iblockdata.setValue(TurtleEggBlock.EGGS, Math.min(4, (Integer) iblockdata.getValue(TurtleEggBlock.EGGS) + 1)) : super.getStateForPlacement(context); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return (Integer) blockstate.getValue(TurtleEggBlock.EGGS) > 1 ? TurtleEggBlock.MULTIPLE_EGGS_AABB : TurtleEggBlock.ONE_EGG_AABB; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (Integer) state.getValue(TurtleEggBlock.EGGS) > 1 ? TurtleEggBlock.MULTIPLE_EGGS_AABB : TurtleEggBlock.ONE_EGG_AABB; + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(TurtleEggBlock.HATCH, TurtleEggBlock.EGGS); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(TurtleEggBlock.HATCH, TurtleEggBlock.EGGS); + } + + private boolean canDestroyEgg(Level level, Entity entity) { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/VineBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/VineBlock.java.patch new file mode 100644 index 0000000000..540c1a87a3 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/VineBlock.java.patch @@ -0,0 +1,509 @@ +--- a/net/minecraft/world/level/block/VineBlock.java ++++ b/net/minecraft/world/level/block/VineBlock.java +@@ -18,12 +18,13 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class VineBlock extends Block { + +@@ -42,40 +43,39 @@ + private static final VoxelShape EAST_AABB = Block.box(15.0D, 0.0D, 0.0D, 16.0D, 16.0D, 16.0D); + private static final VoxelShape NORTH_AABB = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 16.0D, 1.0D); + private static final VoxelShape SOUTH_AABB = Block.box(0.0D, 0.0D, 15.0D, 16.0D, 16.0D, 16.0D); +- private final Map shapesCache; ++ private final Map shapesCache; + + @Override +- @Override + public MapCodec codec() { + return VineBlock.CODEC; + } + +- public VineBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(VineBlock.UP, false)).setValue(VineBlock.NORTH, false)).setValue(VineBlock.EAST, false)).setValue(VineBlock.SOUTH, false)).setValue(VineBlock.WEST, false)); ++ public VineBlock(BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(VineBlock.UP, false)).setValue(VineBlock.NORTH, false)).setValue(VineBlock.EAST, false)).setValue(VineBlock.SOUTH, false)).setValue(VineBlock.WEST, false)); + this.shapesCache = ImmutableMap.copyOf((Map) this.stateDefinition.getPossibleStates().stream().collect(Collectors.toMap(Function.identity(), VineBlock::calculateShape))); + } + +- private static VoxelShape calculateShape(BlockState blockstate) { ++ private static VoxelShape calculateShape(IBlockData state) { + VoxelShape voxelshape = Shapes.empty(); + +- if ((Boolean) blockstate.getValue(VineBlock.UP)) { ++ if ((Boolean) state.getValue(VineBlock.UP)) { + voxelshape = VineBlock.UP_AABB; + } + +- if ((Boolean) blockstate.getValue(VineBlock.NORTH)) { ++ if ((Boolean) state.getValue(VineBlock.NORTH)) { + voxelshape = Shapes.or(voxelshape, VineBlock.NORTH_AABB); + } + +- if ((Boolean) blockstate.getValue(VineBlock.SOUTH)) { ++ if ((Boolean) state.getValue(VineBlock.SOUTH)) { + voxelshape = Shapes.or(voxelshape, VineBlock.SOUTH_AABB); + } + +- if ((Boolean) blockstate.getValue(VineBlock.EAST)) { ++ if ((Boolean) state.getValue(VineBlock.EAST)) { + voxelshape = Shapes.or(voxelshape, VineBlock.EAST_AABB); + } + +- if ((Boolean) blockstate.getValue(VineBlock.WEST)) { ++ if ((Boolean) state.getValue(VineBlock.WEST)) { + voxelshape = Shapes.or(voxelshape, VineBlock.WEST_AABB); + } + +@@ -83,35 +83,32 @@ + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return (VoxelShape) this.shapesCache.get(blockstate); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (VoxelShape) this.shapesCache.get(state); + } + + @Override +- @Override +- public boolean propagatesSkylightDown(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { ++ public boolean propagatesSkylightDown(IBlockData state, BlockGetter level, BlockPos pos) { + return true; + } + + @Override +- @Override +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- return this.hasFaces(this.getUpdatedState(blockstate, levelreader, blockpos)); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ return this.hasFaces(this.getUpdatedState(state, level, pos)); + } + +- private boolean hasFaces(BlockState blockstate) { +- return this.countFaces(blockstate) > 0; ++ private boolean hasFaces(IBlockData state) { ++ return this.countFaces(state) > 0; + } + +- private int countFaces(BlockState blockstate) { ++ private int countFaces(IBlockData state) { + int i = 0; + Iterator iterator = VineBlock.PROPERTY_BY_DIRECTION.values().iterator(); + + while (iterator.hasNext()) { +- BooleanProperty booleanproperty = (BooleanProperty) iterator.next(); ++ BooleanProperty blockstateboolean = (BooleanProperty) iterator.next(); + +- if ((Boolean) blockstate.getValue(booleanproperty)) { ++ if ((Boolean) state.getValue(blockstateboolean)) { + ++i; + } + } +@@ -119,155 +116,157 @@ + return i; + } + +- private boolean canSupportAtFace(BlockGetter blockgetter, BlockPos blockpos, Direction direction) { ++ private boolean canSupportAtFace(BlockGetter level, BlockPos pos, Direction direction) { + if (direction == Direction.DOWN) { + return false; + } else { +- BlockPos blockpos1 = blockpos.relative(direction); ++ BlockPos blockposition1 = pos.relative(direction); + +- if (isAcceptableNeighbour(blockgetter, blockpos1, direction)) { ++ if (isAcceptableNeighbour(level, blockposition1, direction)) { + return true; + } else if (direction.getAxis() == Direction.Axis.Y) { + return false; + } else { +- BooleanProperty booleanproperty = (BooleanProperty) VineBlock.PROPERTY_BY_DIRECTION.get(direction); +- BlockState blockstate = blockgetter.getBlockState(blockpos.above()); ++ BooleanProperty blockstateboolean = (BooleanProperty) VineBlock.PROPERTY_BY_DIRECTION.get(direction); ++ IBlockData iblockdata = level.getBlockState(pos.above()); + +- return blockstate.is((Block) this) && (Boolean) blockstate.getValue(booleanproperty); ++ return iblockdata.is((Block) this) && (Boolean) iblockdata.getValue(blockstateboolean); + } + } + } + +- public static boolean isAcceptableNeighbour(BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return MultifaceBlock.canAttachTo(blockgetter, direction, blockpos, blockgetter.getBlockState(blockpos)); ++ public static boolean isAcceptableNeighbour(BlockGetter blockReader, BlockPos neighborPos, Direction attachedFace) { ++ return MultifaceBlock.canAttachTo(blockReader, attachedFace, neighborPos, blockReader.getBlockState(neighborPos)); + } + +- private BlockState getUpdatedState(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- BlockPos blockpos1 = blockpos.above(); ++ private IBlockData getUpdatedState(IBlockData state, BlockGetter level, BlockPos pos) { ++ BlockPos blockposition1 = pos.above(); + +- if ((Boolean) blockstate.getValue(VineBlock.UP)) { +- blockstate = (BlockState) blockstate.setValue(VineBlock.UP, isAcceptableNeighbour(blockgetter, blockpos1, Direction.DOWN)); ++ if ((Boolean) state.getValue(VineBlock.UP)) { ++ state = (IBlockData) state.setValue(VineBlock.UP, isAcceptableNeighbour(level, blockposition1, Direction.DOWN)); + } + +- BlockState blockstate1 = null; ++ IBlockData iblockdata1 = null; + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); +- BooleanProperty booleanproperty = getPropertyForFace(direction); ++ Direction enumdirection = (Direction) iterator.next(); ++ BooleanProperty blockstateboolean = getPropertyForFace(enumdirection); + +- if ((Boolean) blockstate.getValue(booleanproperty)) { +- boolean flag = this.canSupportAtFace(blockgetter, blockpos, direction); ++ if ((Boolean) state.getValue(blockstateboolean)) { ++ boolean flag = this.canSupportAtFace(level, pos, enumdirection); + + if (!flag) { +- if (blockstate1 == null) { +- blockstate1 = blockgetter.getBlockState(blockpos1); ++ if (iblockdata1 == null) { ++ iblockdata1 = level.getBlockState(blockposition1); + } + +- flag = blockstate1.is((Block) this) && (Boolean) blockstate1.getValue(booleanproperty); ++ flag = iblockdata1.is((Block) this) && (Boolean) iblockdata1.getValue(blockstateboolean); + } + +- blockstate = (BlockState) blockstate.setValue(booleanproperty, flag); ++ state = (IBlockData) state.setValue(blockstateboolean, flag); + } + } + +- return blockstate; ++ return state; + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- if (direction == Direction.DOWN) { +- return super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if (facing == Direction.DOWN) { ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } else { +- BlockState blockstate2 = this.getUpdatedState(blockstate, levelaccessor, blockpos); ++ IBlockData iblockdata2 = this.getUpdatedState(state, level, currentPos); + +- return !this.hasFaces(blockstate2) ? Blocks.AIR.defaultBlockState() : blockstate2; ++ return !this.hasFaces(iblockdata2) ? Blocks.AIR.defaultBlockState() : iblockdata2; + } + } + + @Override +- @Override +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- if (serverlevel.getGameRules().getBoolean(GameRules.RULE_DO_VINES_SPREAD)) { +- if (randomsource.nextInt(4) == 0) { +- Direction direction = Direction.getRandom(randomsource); +- BlockPos blockpos1 = blockpos.above(); +- BlockPos blockpos2; +- BlockState blockstate1; +- Direction direction1; ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (level.getGameRules().getBoolean(GameRules.RULE_DO_VINES_SPREAD)) { ++ if (random.nextInt(4) == 0) { ++ Direction enumdirection = Direction.getRandom(random); ++ BlockPos blockposition1 = pos.above(); ++ BlockPos blockposition2; ++ IBlockData iblockdata1; ++ Direction enumdirection1; + +- if (direction.getAxis().isHorizontal() && !(Boolean) blockstate.getValue(getPropertyForFace(direction))) { +- if (this.canSpread(serverlevel, blockpos)) { +- blockpos2 = blockpos.relative(direction); +- blockstate1 = serverlevel.getBlockState(blockpos2); +- if (blockstate1.isAir()) { +- direction1 = direction.getClockWise(); +- Direction direction2 = direction.getCounterClockWise(); +- boolean flag = (Boolean) blockstate.getValue(getPropertyForFace(direction1)); +- boolean flag1 = (Boolean) blockstate.getValue(getPropertyForFace(direction2)); +- BlockPos blockpos3 = blockpos2.relative(direction1); +- BlockPos blockpos4 = blockpos2.relative(direction2); ++ if (enumdirection.getAxis().isHorizontal() && !(Boolean) state.getValue(getPropertyForFace(enumdirection))) { ++ if (this.canSpread(level, pos)) { ++ blockposition2 = pos.relative(enumdirection); ++ iblockdata1 = level.getBlockState(blockposition2); ++ if (iblockdata1.isAir()) { ++ enumdirection1 = enumdirection.getClockWise(); ++ Direction enumdirection2 = enumdirection.getCounterClockWise(); ++ boolean flag = (Boolean) state.getValue(getPropertyForFace(enumdirection1)); ++ boolean flag1 = (Boolean) state.getValue(getPropertyForFace(enumdirection2)); ++ BlockPos blockposition3 = blockposition2.relative(enumdirection1); ++ BlockPos blockposition4 = blockposition2.relative(enumdirection2); + +- if (flag && isAcceptableNeighbour(serverlevel, blockpos3, direction1)) { +- serverlevel.setBlock(blockpos2, (BlockState) this.defaultBlockState().setValue(getPropertyForFace(direction1), true), 2); +- } else if (flag1 && isAcceptableNeighbour(serverlevel, blockpos4, direction2)) { +- serverlevel.setBlock(blockpos2, (BlockState) this.defaultBlockState().setValue(getPropertyForFace(direction2), true), 2); ++ // CraftBukkit start - Call BlockSpreadEvent ++ BlockPos source = pos; ++ ++ if (flag && isAcceptableNeighbour(level, blockposition3, enumdirection1)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, source, blockposition2, (IBlockData) this.defaultBlockState().setValue(getPropertyForFace(enumdirection1), true), 2); ++ } else if (flag1 && isAcceptableNeighbour(level, blockposition4, enumdirection2)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, source, blockposition2, (IBlockData) this.defaultBlockState().setValue(getPropertyForFace(enumdirection2), true), 2); + } else { +- Direction direction3 = direction.getOpposite(); ++ Direction enumdirection3 = enumdirection.getOpposite(); + +- if (flag && serverlevel.isEmptyBlock(blockpos3) && isAcceptableNeighbour(serverlevel, blockpos.relative(direction1), direction3)) { +- serverlevel.setBlock(blockpos3, (BlockState) this.defaultBlockState().setValue(getPropertyForFace(direction3), true), 2); +- } else if (flag1 && serverlevel.isEmptyBlock(blockpos4) && isAcceptableNeighbour(serverlevel, blockpos.relative(direction2), direction3)) { +- serverlevel.setBlock(blockpos4, (BlockState) this.defaultBlockState().setValue(getPropertyForFace(direction3), true), 2); +- } else if ((double) randomsource.nextFloat() < 0.05D && isAcceptableNeighbour(serverlevel, blockpos2.above(), Direction.UP)) { +- serverlevel.setBlock(blockpos2, (BlockState) this.defaultBlockState().setValue(VineBlock.UP, true), 2); ++ if (flag && level.isEmptyBlock(blockposition3) && isAcceptableNeighbour(level, pos.relative(enumdirection1), enumdirection3)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, source, blockposition3, (IBlockData) this.defaultBlockState().setValue(getPropertyForFace(enumdirection3), true), 2); ++ } else if (flag1 && level.isEmptyBlock(blockposition4) && isAcceptableNeighbour(level, pos.relative(enumdirection2), enumdirection3)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, source, blockposition4, (IBlockData) this.defaultBlockState().setValue(getPropertyForFace(enumdirection3), true), 2); ++ } else if ((double) random.nextFloat() < 0.05D && isAcceptableNeighbour(level, blockposition2.above(), Direction.UP)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, source, blockposition2, (IBlockData) this.defaultBlockState().setValue(VineBlock.UP, true), 2); + } ++ // CraftBukkit end + } +- } else if (isAcceptableNeighbour(serverlevel, blockpos2, direction)) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(getPropertyForFace(direction), true), 2); ++ } else if (isAcceptableNeighbour(level, blockposition2, enumdirection)) { ++ CraftEventFactory.handleBlockGrowEvent(level, pos, (IBlockData) state.setValue(getPropertyForFace(enumdirection), true), 2); // CraftBukkit + } + + } + } else { +- if (direction == Direction.UP && blockpos.getY() < serverlevel.getMaxBuildHeight() - 1) { +- if (this.canSupportAtFace(serverlevel, blockpos, direction)) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(VineBlock.UP, true), 2); ++ if (enumdirection == Direction.UP && pos.getY() < level.getMaxBuildHeight() - 1) { ++ if (this.canSupportAtFace(level, pos, enumdirection)) { ++ CraftEventFactory.handleBlockGrowEvent(level, pos, (IBlockData) state.setValue(VineBlock.UP, true), 2); // CraftBukkit + return; + } + +- if (serverlevel.isEmptyBlock(blockpos1)) { +- if (!this.canSpread(serverlevel, blockpos)) { ++ if (level.isEmptyBlock(blockposition1)) { ++ if (!this.canSpread(level, pos)) { + return; + } + +- BlockState blockstate2 = blockstate; ++ IBlockData iblockdata2 = state; + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- direction1 = (Direction) iterator.next(); +- if (randomsource.nextBoolean() || !isAcceptableNeighbour(serverlevel, blockpos1.relative(direction1), direction1)) { +- blockstate2 = (BlockState) blockstate2.setValue(getPropertyForFace(direction1), false); ++ enumdirection1 = (Direction) iterator.next(); ++ if (random.nextBoolean() || !isAcceptableNeighbour(level, blockposition1.relative(enumdirection1), enumdirection1)) { ++ iblockdata2 = (IBlockData) iblockdata2.setValue(getPropertyForFace(enumdirection1), false); + } + } + +- if (this.hasHorizontalConnection(blockstate2)) { +- serverlevel.setBlock(blockpos1, blockstate2, 2); ++ if (this.hasHorizontalConnection(iblockdata2)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition1, iblockdata2, 2); // CraftBukkit + } + + return; + } + } + +- if (blockpos.getY() > serverlevel.getMinBuildHeight()) { +- blockpos2 = blockpos.below(); +- blockstate1 = serverlevel.getBlockState(blockpos2); +- if (blockstate1.isAir() || blockstate1.is((Block) this)) { +- BlockState blockstate3 = blockstate1.isAir() ? this.defaultBlockState() : blockstate1; +- BlockState blockstate4 = this.copyRandomFaces(blockstate, blockstate3, randomsource); ++ if (pos.getY() > level.getMinBuildHeight()) { ++ blockposition2 = pos.below(); ++ iblockdata1 = level.getBlockState(blockposition2); ++ if (iblockdata1.isAir() || iblockdata1.is((Block) this)) { ++ IBlockData iblockdata3 = iblockdata1.isAir() ? this.defaultBlockState() : iblockdata1; ++ IBlockData iblockdata4 = this.copyRandomFaces(state, iblockdata3, random); + +- if (blockstate3 != blockstate4 && this.hasHorizontalConnection(blockstate4)) { +- serverlevel.setBlock(blockpos2, blockstate4, 2); ++ if (iblockdata3 != iblockdata4 && this.hasHorizontalConnection(iblockdata4)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition2, iblockdata4, 2); // CraftBukkit + } + } + } +@@ -277,38 +276,38 @@ + } + } + +- private BlockState copyRandomFaces(BlockState blockstate, BlockState blockstate1, RandomSource randomsource) { ++ private IBlockData copyRandomFaces(IBlockData sourceState, IBlockData spreadState, RandomSource random) { + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); ++ Direction enumdirection = (Direction) iterator.next(); + +- if (randomsource.nextBoolean()) { +- BooleanProperty booleanproperty = getPropertyForFace(direction); ++ if (random.nextBoolean()) { ++ BooleanProperty blockstateboolean = getPropertyForFace(enumdirection); + +- if ((Boolean) blockstate.getValue(booleanproperty)) { +- blockstate1 = (BlockState) blockstate1.setValue(booleanproperty, true); ++ if ((Boolean) sourceState.getValue(blockstateboolean)) { ++ spreadState = (IBlockData) spreadState.setValue(blockstateboolean, true); + } + } + } + +- return blockstate1; ++ return spreadState; + } + +- private boolean hasHorizontalConnection(BlockState blockstate) { +- return (Boolean) blockstate.getValue(VineBlock.NORTH) || (Boolean) blockstate.getValue(VineBlock.EAST) || (Boolean) blockstate.getValue(VineBlock.SOUTH) || (Boolean) blockstate.getValue(VineBlock.WEST); ++ private boolean hasHorizontalConnection(IBlockData state) { ++ return (Boolean) state.getValue(VineBlock.NORTH) || (Boolean) state.getValue(VineBlock.EAST) || (Boolean) state.getValue(VineBlock.SOUTH) || (Boolean) state.getValue(VineBlock.WEST); + } + +- private boolean canSpread(BlockGetter blockgetter, BlockPos blockpos) { ++ private boolean canSpread(BlockGetter blockReader, BlockPos pos) { + boolean flag = true; +- Iterable iterable = BlockPos.betweenClosed(blockpos.getX() - 4, blockpos.getY() - 1, blockpos.getZ() - 4, blockpos.getX() + 4, blockpos.getY() + 1, blockpos.getZ() + 4); ++ Iterable iterable = BlockPos.betweenClosed(pos.getX() - 4, pos.getY() - 1, pos.getZ() - 4, pos.getX() + 4, pos.getY() + 1, pos.getZ() + 4); + int i = 5; + Iterator iterator = iterable.iterator(); + + while (iterator.hasNext()) { +- BlockPos blockpos1 = (BlockPos) iterator.next(); ++ BlockPos blockposition1 = (BlockPos) iterator.next(); + +- if (blockgetter.getBlockState(blockpos1).is((Block) this)) { ++ if (blockReader.getBlockState(blockposition1).is((Block) this)) { + --i; + if (i <= 0) { + return false; +@@ -320,74 +319,69 @@ + } + + @Override +- @Override +- public boolean canBeReplaced(BlockState blockstate, BlockPlaceContext blockplacecontext) { +- BlockState blockstate1 = blockplacecontext.getLevel().getBlockState(blockplacecontext.getClickedPos()); ++ public boolean canBeReplaced(IBlockData state, BlockPlaceContext useContext) { ++ IBlockData iblockdata1 = useContext.getLevel().getBlockState(useContext.getClickedPos()); + +- return blockstate1.is((Block) this) ? this.countFaces(blockstate1) < VineBlock.PROPERTY_BY_DIRECTION.size() : super.canBeReplaced(blockstate, blockplacecontext); ++ return iblockdata1.is((Block) this) ? this.countFaces(iblockdata1) < VineBlock.PROPERTY_BY_DIRECTION.size() : super.canBeReplaced(state, useContext); + } + + @Nullable + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- BlockState blockstate = blockplacecontext.getLevel().getBlockState(blockplacecontext.getClickedPos()); +- boolean flag = blockstate.is((Block) this); +- BlockState blockstate1 = flag ? blockstate : this.defaultBlockState(); +- Direction[] adirection = blockplacecontext.getNearestLookingDirections(); +- int i = adirection.length; ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ IBlockData iblockdata = context.getLevel().getBlockState(context.getClickedPos()); ++ boolean flag = iblockdata.is((Block) this); ++ IBlockData iblockdata1 = flag ? iblockdata : this.defaultBlockState(); ++ Direction[] aenumdirection = context.getNearestLookingDirections(); ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; ++ Direction enumdirection = aenumdirection[j]; + +- if (direction != Direction.DOWN) { +- BooleanProperty booleanproperty = getPropertyForFace(direction); +- boolean flag1 = flag && (Boolean) blockstate.getValue(booleanproperty); ++ if (enumdirection != Direction.DOWN) { ++ BooleanProperty blockstateboolean = getPropertyForFace(enumdirection); ++ boolean flag1 = flag && (Boolean) iblockdata.getValue(blockstateboolean); + +- if (!flag1 && this.canSupportAtFace(blockplacecontext.getLevel(), blockplacecontext.getClickedPos(), direction)) { +- return (BlockState) blockstate1.setValue(booleanproperty, true); ++ if (!flag1 && this.canSupportAtFace(context.getLevel(), context.getClickedPos(), enumdirection)) { ++ return (IBlockData) iblockdata1.setValue(blockstateboolean, true); + } + } + } + +- return flag ? blockstate1 : null; ++ return flag ? iblockdata1 : null; + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(VineBlock.UP, VineBlock.NORTH, VineBlock.EAST, VineBlock.SOUTH, VineBlock.WEST); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(VineBlock.UP, VineBlock.NORTH, VineBlock.EAST, VineBlock.SOUTH, VineBlock.WEST); + } + + @Override +- @Override +- public BlockState rotate(BlockState blockstate, Rotation rotation) { +- switch (rotation) { ++ public IBlockData rotate(IBlockData state, Rotation rotate) { ++ switch (rotate) { + case CLOCKWISE_180: +- return (BlockState) ((BlockState) ((BlockState) ((BlockState) blockstate.setValue(VineBlock.NORTH, (Boolean) blockstate.getValue(VineBlock.SOUTH))).setValue(VineBlock.EAST, (Boolean) blockstate.getValue(VineBlock.WEST))).setValue(VineBlock.SOUTH, (Boolean) blockstate.getValue(VineBlock.NORTH))).setValue(VineBlock.WEST, (Boolean) blockstate.getValue(VineBlock.EAST)); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) state.setValue(VineBlock.NORTH, (Boolean) state.getValue(VineBlock.SOUTH))).setValue(VineBlock.EAST, (Boolean) state.getValue(VineBlock.WEST))).setValue(VineBlock.SOUTH, (Boolean) state.getValue(VineBlock.NORTH))).setValue(VineBlock.WEST, (Boolean) state.getValue(VineBlock.EAST)); + case COUNTERCLOCKWISE_90: +- return (BlockState) ((BlockState) ((BlockState) ((BlockState) blockstate.setValue(VineBlock.NORTH, (Boolean) blockstate.getValue(VineBlock.EAST))).setValue(VineBlock.EAST, (Boolean) blockstate.getValue(VineBlock.SOUTH))).setValue(VineBlock.SOUTH, (Boolean) blockstate.getValue(VineBlock.WEST))).setValue(VineBlock.WEST, (Boolean) blockstate.getValue(VineBlock.NORTH)); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) state.setValue(VineBlock.NORTH, (Boolean) state.getValue(VineBlock.EAST))).setValue(VineBlock.EAST, (Boolean) state.getValue(VineBlock.SOUTH))).setValue(VineBlock.SOUTH, (Boolean) state.getValue(VineBlock.WEST))).setValue(VineBlock.WEST, (Boolean) state.getValue(VineBlock.NORTH)); + case CLOCKWISE_90: +- return (BlockState) ((BlockState) ((BlockState) ((BlockState) blockstate.setValue(VineBlock.NORTH, (Boolean) blockstate.getValue(VineBlock.WEST))).setValue(VineBlock.EAST, (Boolean) blockstate.getValue(VineBlock.NORTH))).setValue(VineBlock.SOUTH, (Boolean) blockstate.getValue(VineBlock.EAST))).setValue(VineBlock.WEST, (Boolean) blockstate.getValue(VineBlock.SOUTH)); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) state.setValue(VineBlock.NORTH, (Boolean) state.getValue(VineBlock.WEST))).setValue(VineBlock.EAST, (Boolean) state.getValue(VineBlock.NORTH))).setValue(VineBlock.SOUTH, (Boolean) state.getValue(VineBlock.EAST))).setValue(VineBlock.WEST, (Boolean) state.getValue(VineBlock.SOUTH)); + default: +- return blockstate; ++ return state; + } + } + + @Override +- @Override +- public BlockState mirror(BlockState blockstate, Mirror mirror) { ++ public IBlockData mirror(IBlockData state, Mirror mirror) { + switch (mirror) { + case LEFT_RIGHT: +- return (BlockState) ((BlockState) blockstate.setValue(VineBlock.NORTH, (Boolean) blockstate.getValue(VineBlock.SOUTH))).setValue(VineBlock.SOUTH, (Boolean) blockstate.getValue(VineBlock.NORTH)); ++ return (IBlockData) ((IBlockData) state.setValue(VineBlock.NORTH, (Boolean) state.getValue(VineBlock.SOUTH))).setValue(VineBlock.SOUTH, (Boolean) state.getValue(VineBlock.NORTH)); + case FRONT_BACK: +- return (BlockState) ((BlockState) blockstate.setValue(VineBlock.EAST, (Boolean) blockstate.getValue(VineBlock.WEST))).setValue(VineBlock.WEST, (Boolean) blockstate.getValue(VineBlock.EAST)); ++ return (IBlockData) ((IBlockData) state.setValue(VineBlock.EAST, (Boolean) state.getValue(VineBlock.WEST))).setValue(VineBlock.WEST, (Boolean) state.getValue(VineBlock.EAST)); + default: +- return super.mirror(blockstate, mirror); ++ return super.mirror(state, mirror); + } + } + +- public static BooleanProperty getPropertyForFace(Direction direction) { +- return (BooleanProperty) VineBlock.PROPERTY_BY_DIRECTION.get(direction); ++ public static BooleanProperty getPropertyForFace(Direction face) { ++ return (BooleanProperty) VineBlock.PROPERTY_BY_DIRECTION.get(face); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/WallHangingSignBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/WallHangingSignBlock.java.patch new file mode 100644 index 0000000000..741dfd0b1c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/WallHangingSignBlock.java.patch @@ -0,0 +1,238 @@ +--- a/net/minecraft/world/level/block/WallHangingSignBlock.java ++++ b/net/minecraft/world/level/block/WallHangingSignBlock.java +@@ -9,7 +9,7 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.tags.BlockTags; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.HangingSignItem; +@@ -25,13 +25,13 @@ + import net.minecraft.world.level.block.entity.HangingSignBlockEntity; + import net.minecraft.world.level.block.entity.SignBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.DirectionProperty; + import net.minecraft.world.level.block.state.properties.WoodType; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; +@@ -50,63 +50,57 @@ + private static final Map AABBS = Maps.newEnumMap(ImmutableMap.of(Direction.NORTH, WallHangingSignBlock.SHAPE_NORTHSOUTH, Direction.SOUTH, WallHangingSignBlock.SHAPE_NORTHSOUTH, Direction.EAST, WallHangingSignBlock.SHAPE_EASTWEST, Direction.WEST, WallHangingSignBlock.SHAPE_EASTWEST)); + + @Override +- @Override + public MapCodec codec() { + return WallHangingSignBlock.CODEC; + } + +- public WallHangingSignBlock(WoodType woodtype, BlockBehaviour.Properties blockbehaviour_properties) { +- super(woodtype, blockbehaviour_properties.sound(woodtype.hangingSignSoundType())); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(WallHangingSignBlock.FACING, Direction.NORTH)).setValue(WallHangingSignBlock.WATERLOGGED, false)); ++ public WallHangingSignBlock(WoodType blockpropertywood, BlockBehaviour.Properties blockbase_info) { ++ super(blockpropertywood, blockbase_info.sound(blockpropertywood.hangingSignSoundType())); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(WallHangingSignBlock.FACING, Direction.NORTH)).setValue(WallHangingSignBlock.WATERLOGGED, false)); + } + + @Override +- @Override +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof SignBlockEntity) { +- SignBlockEntity signblockentity = (SignBlockEntity) blockentity; +- ItemStack itemstack = player.getItemInHand(interactionhand); ++ if (tileentity instanceof SignBlockEntity) { ++ SignBlockEntity tileentitysign = (SignBlockEntity) tileentity; ++ ItemStack itemstack = player.getItemInHand(hand); + +- if (this.shouldTryToChainAnotherHangingSign(blockstate, player, blockhitresult, signblockentity, itemstack)) { ++ if (this.shouldTryToChainAnotherHangingSign(state, player, hit, tileentitysign, itemstack)) { + return InteractionResult.PASS; + } + } + +- return super.use(blockstate, level, blockpos, player, interactionhand, blockhitresult); ++ return super.use(state, level, pos, player, hand, hit); + } + +- private boolean shouldTryToChainAnotherHangingSign(BlockState blockstate, Player player, BlockHitResult blockhitresult, SignBlockEntity signblockentity, ItemStack itemstack) { +- return !signblockentity.canExecuteClickCommands(signblockentity.isFacingFrontText(player), player) && itemstack.getItem() instanceof HangingSignItem && !this.isHittingEditableSide(blockhitresult, blockstate); ++ private boolean shouldTryToChainAnotherHangingSign(IBlockData state, Player player, BlockHitResult hitResult, SignBlockEntity sign, ItemStack stack) { ++ return !sign.canExecuteClickCommands(sign.isFacingFrontText(player), player) && stack.getItem() instanceof HangingSignItem && !this.isHittingEditableSide(hitResult, state); + } + +- private boolean isHittingEditableSide(BlockHitResult blockhitresult, BlockState blockstate) { +- return blockhitresult.getDirection().getAxis() == ((Direction) blockstate.getValue(WallHangingSignBlock.FACING)).getAxis(); ++ private boolean isHittingEditableSide(BlockHitResult hitResult, IBlockData state) { ++ return hitResult.getDirection().getAxis() == ((Direction) state.getValue(WallHangingSignBlock.FACING)).getAxis(); + } + + @Override +- @Override + public String getDescriptionId() { + return this.asItem().getDescriptionId(); + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return (VoxelShape) WallHangingSignBlock.AABBS.get(blockstate.getValue(WallHangingSignBlock.FACING)); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (VoxelShape) WallHangingSignBlock.AABBS.get(state.getValue(WallHangingSignBlock.FACING)); + } + + @Override +- @Override +- public VoxelShape getBlockSupportShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return this.getShape(blockstate, blockgetter, blockpos, CollisionContext.empty()); ++ public VoxelShape getBlockSupportShape(IBlockData state, BlockGetter level, BlockPos pos) { ++ return this.getShape(state, level, pos, CollisionContext.empty()); + } + + @Override +- @Override +- public VoxelShape getCollisionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- switch ((Direction) blockstate.getValue(WallHangingSignBlock.FACING)) { ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ switch ((Direction) state.getValue(WallHangingSignBlock.FACING)) { + case EAST: + case WEST: + return WallHangingSignBlock.PLANK_EASTWEST; +@@ -115,39 +109,38 @@ + } + } + +- public boolean canPlace(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { +- Direction direction = ((Direction) blockstate.getValue(WallHangingSignBlock.FACING)).getClockWise(); +- Direction direction1 = ((Direction) blockstate.getValue(WallHangingSignBlock.FACING)).getCounterClockWise(); ++ public boolean canPlace(IBlockData state, LevelReader level, BlockPos pos) { ++ Direction enumdirection = ((Direction) state.getValue(WallHangingSignBlock.FACING)).getClockWise(); ++ Direction enumdirection1 = ((Direction) state.getValue(WallHangingSignBlock.FACING)).getCounterClockWise(); + +- return this.canAttachTo(levelreader, blockstate, blockpos.relative(direction), direction1) || this.canAttachTo(levelreader, blockstate, blockpos.relative(direction1), direction); ++ return this.canAttachTo(level, state, pos.relative(enumdirection), enumdirection1) || this.canAttachTo(level, state, pos.relative(enumdirection1), enumdirection); + } + +- public boolean canAttachTo(LevelReader levelreader, BlockState blockstate, BlockPos blockpos, Direction direction) { +- BlockState blockstate1 = levelreader.getBlockState(blockpos); ++ public boolean canAttachTo(LevelReader level, IBlockData state, BlockPos pos, Direction direction) { ++ IBlockData iblockdata1 = level.getBlockState(pos); + +- return blockstate1.is(BlockTags.WALL_HANGING_SIGNS) ? ((Direction) blockstate1.getValue(WallHangingSignBlock.FACING)).getAxis().test((Direction) blockstate.getValue(WallHangingSignBlock.FACING)) : blockstate1.isFaceSturdy(levelreader, blockpos, direction, SupportType.FULL); ++ return iblockdata1.is(BlockTags.WALL_HANGING_SIGNS) ? ((Direction) iblockdata1.getValue(WallHangingSignBlock.FACING)).getAxis().test((Direction) state.getValue(WallHangingSignBlock.FACING)) : iblockdata1.isFaceSturdy(level, pos, direction, SupportType.FULL); + } + + @Nullable + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- BlockState blockstate = this.defaultBlockState(); +- FluidState fluidstate = blockplacecontext.getLevel().getFluidState(blockplacecontext.getClickedPos()); +- Level level = blockplacecontext.getLevel(); +- BlockPos blockpos = blockplacecontext.getClickedPos(); +- Direction[] adirection = blockplacecontext.getNearestLookingDirections(); +- int i = adirection.length; ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ IBlockData iblockdata = this.defaultBlockState(); ++ FluidState fluid = context.getLevel().getFluidState(context.getClickedPos()); ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ Direction[] aenumdirection = context.getNearestLookingDirections(); ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; ++ Direction enumdirection = aenumdirection[j]; + +- if (direction.getAxis().isHorizontal() && !direction.getAxis().test(blockplacecontext.getClickedFace())) { +- Direction direction1 = direction.getOpposite(); ++ if (enumdirection.getAxis().isHorizontal() && !enumdirection.getAxis().test(context.getClickedFace())) { ++ Direction enumdirection1 = enumdirection.getOpposite(); + +- blockstate = (BlockState) blockstate.setValue(WallHangingSignBlock.FACING, direction1); +- if (blockstate.canSurvive(level, blockpos) && this.canPlace(blockstate, level, blockpos)) { +- return (BlockState) blockstate.setValue(WallHangingSignBlock.WATERLOGGED, fluidstate.getType() == Fluids.WATER); ++ iblockdata = (IBlockData) iblockdata.setValue(WallHangingSignBlock.FACING, enumdirection1); ++ if (iblockdata.canSurvive(world, blockposition) && this.canPlace(iblockdata, world, blockposition)) { ++ return (IBlockData) iblockdata.setValue(WallHangingSignBlock.WATERLOGGED, fluid.getType() == Fluids.WATER); + } + } + } +@@ -156,51 +149,43 @@ + } + + @Override +- @Override +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- return direction.getAxis() == ((Direction) blockstate.getValue(WallHangingSignBlock.FACING)).getClockWise().getAxis() && !blockstate.canSurvive(levelaccessor, blockpos) ? Blocks.AIR.defaultBlockState() : super.updateShape(blockstate, direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ return facing.getAxis() == ((Direction) state.getValue(WallHangingSignBlock.FACING)).getClockWise().getAxis() && !state.canSurvive(level, currentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- @Override +- public float getYRotationDegrees(BlockState blockstate) { +- return ((Direction) blockstate.getValue(WallHangingSignBlock.FACING)).toYRot(); ++ public float getYRotationDegrees(IBlockData state) { ++ return ((Direction) state.getValue(WallHangingSignBlock.FACING)).toYRot(); + } + + @Override +- @Override +- public BlockState rotate(BlockState blockstate, Rotation rotation) { +- return (BlockState) blockstate.setValue(WallHangingSignBlock.FACING, rotation.rotate((Direction) blockstate.getValue(WallHangingSignBlock.FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return (IBlockData) state.setValue(WallHangingSignBlock.FACING, rotation.rotate((Direction) state.getValue(WallHangingSignBlock.FACING))); + } + + @Override +- @Override +- public BlockState mirror(BlockState blockstate, Mirror mirror) { +- return blockstate.rotate(mirror.getRotation((Direction) blockstate.getValue(WallHangingSignBlock.FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(WallHangingSignBlock.FACING))); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(WallHangingSignBlock.FACING, WallHangingSignBlock.WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(WallHangingSignBlock.FACING, WallHangingSignBlock.WATERLOGGED); + } + + @Override +- @Override +- public BlockEntity newBlockEntity(BlockPos blockpos, BlockState blockstate) { +- return new HangingSignBlockEntity(blockpos, blockstate); ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ return new HangingSignBlockEntity(pos, state); + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + + @Nullable + @Override +- @Override +- public BlockEntityTicker getTicker(Level level, BlockState blockstate, BlockEntityType blockentitytype) { +- return createTickerHelper(blockentitytype, BlockEntityType.HANGING_SIGN, SignBlockEntity::tick); ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { ++ return null; // Craftbukkit - remove unnecessary sign ticking + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/WaterlilyBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/WaterlilyBlock.java.patch new file mode 100644 index 0000000000..fd16d2e1d9 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/WaterlilyBlock.java.patch @@ -0,0 +1,71 @@ +--- a/net/minecraft/world/level/block/WaterlilyBlock.java ++++ b/net/minecraft/world/level/block/WaterlilyBlock.java +@@ -8,11 +8,14 @@ + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class WaterlilyBlock extends BushBlock { + +@@ -20,37 +23,38 @@ + protected static final VoxelShape AABB = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 1.5D, 15.0D); + + @Override +- @Override + public MapCodec codec() { + return WaterlilyBlock.CODEC; + } + +- protected WaterlilyBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); ++ protected WaterlilyBlock(BlockBehaviour.Properties properties) { ++ super(properties); + } + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { +- super.entityInside(blockstate, level, blockpos, entity); ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ super.entityInside(state, level, pos, entity); + if (level instanceof ServerLevel && entity instanceof Boat) { +- level.destroyBlock(new BlockPos(blockpos), true, entity); ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end ++ level.destroyBlock(new BlockPos(pos), true, entity); + } + + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return WaterlilyBlock.AABB; + } + + @Override +- @Override +- protected boolean mayPlaceOn(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- FluidState fluidstate = blockgetter.getFluidState(blockpos); +- FluidState fluidstate1 = blockgetter.getFluidState(blockpos.above()); ++ protected boolean mayPlaceOn(IBlockData state, BlockGetter level, BlockPos pos) { ++ FluidState fluid = level.getFluidState(pos); ++ FluidState fluid1 = level.getFluidState(pos.above()); + +- return (fluidstate.getType() == Fluids.WATER || blockstate.getBlock() instanceof IceBlock) && fluidstate1.getType() == Fluids.EMPTY; ++ return (fluid.getType() == Fluids.WATER || state.getBlock() instanceof IceBlock) && fluid1.getType() == Fluids.EMPTY; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/WeightedPressurePlateBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/WeightedPressurePlateBlock.java.patch new file mode 100644 index 0000000000..735972bb47 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/WeightedPressurePlateBlock.java.patch @@ -0,0 +1,112 @@ +--- a/net/minecraft/world/level/block/WeightedPressurePlateBlock.java ++++ b/net/minecraft/world/level/block/WeightedPressurePlateBlock.java +@@ -6,43 +6,64 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockSetType; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end + + public class WeightedPressurePlateBlock extends BasePressurePlateBlock { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- return instance.group(Codec.intRange(1, 1024).fieldOf("max_weight").forGetter((weightedpressureplateblock) -> { +- return weightedpressureplateblock.maxWeight; +- }), BlockSetType.CODEC.fieldOf("block_set_type").forGetter((weightedpressureplateblock) -> { +- return weightedpressureplateblock.type; ++ return instance.group(Codec.intRange(1, 1024).fieldOf("max_weight").forGetter((blockpressureplateweighted) -> { ++ return blockpressureplateweighted.maxWeight; ++ }), BlockSetType.CODEC.fieldOf("block_set_type").forGetter((blockpressureplateweighted) -> { ++ return blockpressureplateweighted.type; + }), propertiesCodec()).apply(instance, WeightedPressurePlateBlock::new); + }); + public static final IntegerProperty POWER = BlockStateProperties.POWER; + private final int maxWeight; + + @Override +- @Override + public MapCodec codec() { + return WeightedPressurePlateBlock.CODEC; + } + +- protected WeightedPressurePlateBlock(int i, BlockSetType blocksettype, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties, blocksettype); +- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(WeightedPressurePlateBlock.POWER, 0)); ++ protected WeightedPressurePlateBlock(int i, BlockSetType blocksettype, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info, blocksettype); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(WeightedPressurePlateBlock.POWER, 0)); + this.maxWeight = i; + } + + @Override +- @Override +- protected int getSignalStrength(Level level, BlockPos blockpos) { +- int i = Math.min(getEntityCount(level, WeightedPressurePlateBlock.TOUCH_AABB.move(blockpos), Entity.class), this.maxWeight); ++ protected int getSignalStrength(Level level, BlockPos pos) { ++ // CraftBukkit start ++ // int i = Math.min(getEntityCount(world, BlockPressurePlateWeighted.TOUCH_AABB.move(blockposition), Entity.class), this.maxWeight); ++ int i = 0; ++ for (Entity entity : getEntities(level, WeightedPressurePlateBlock.TOUCH_AABB.move(pos), Entity.class)) { ++ org.bukkit.event.Cancellable cancellable; + ++ if (entity instanceof Player) { ++ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ // We only want to block turning the plate on if all events are cancelled ++ if (!cancellable.isCancelled()) { ++ i++; ++ } ++ } ++ ++ i = Math.min(i, this.maxWeight); ++ // CraftBukkit end ++ + if (i > 0) { + float f = (float) Math.min(this.maxWeight, i) / (float) this.maxWeight; + +@@ -53,26 +74,22 @@ + } + + @Override +- @Override +- protected int getSignalForState(BlockState blockstate) { +- return (Integer) blockstate.getValue(WeightedPressurePlateBlock.POWER); ++ protected int getSignalForState(IBlockData state) { ++ return (Integer) state.getValue(WeightedPressurePlateBlock.POWER); + } + + @Override +- @Override +- protected BlockState setSignalForState(BlockState blockstate, int i) { +- return (BlockState) blockstate.setValue(WeightedPressurePlateBlock.POWER, i); ++ protected IBlockData setSignalForState(IBlockData state, int strength) { ++ return (IBlockData) state.setValue(WeightedPressurePlateBlock.POWER, strength); + } + + @Override +- @Override + protected int getPressedTime() { + return 10; + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(WeightedPressurePlateBlock.POWER); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(WeightedPressurePlateBlock.POWER); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/WitherRoseBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/WitherRoseBlock.java.patch new file mode 100644 index 0000000000..1f467e7104 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/WitherRoseBlock.java.patch @@ -0,0 +1,79 @@ +--- a/net/minecraft/world/level/block/WitherRoseBlock.java ++++ b/net/minecraft/world/level/block/WitherRoseBlock.java +@@ -15,7 +15,7 @@ + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; +@@ -27,50 +27,46 @@ + }); + + @Override +- @Override + public MapCodec codec() { + return WitherRoseBlock.CODEC; + } + +- public WitherRoseBlock(MobEffect mobeffect, int i, BlockBehaviour.Properties blockbehaviour_properties) { +- this(makeEffectList(mobeffect, i), blockbehaviour_properties); ++ public WitherRoseBlock(MobEffect suspiciousStewEffect, int effectDuration, BlockBehaviour.Properties properties) { ++ this(makeEffectList(suspiciousStewEffect, effectDuration), properties); + } + +- public WitherRoseBlock(List list, BlockBehaviour.Properties blockbehaviour_properties) { +- super(list, blockbehaviour_properties); ++ public WitherRoseBlock(List list, BlockBehaviour.Properties blockbase_info) { ++ super(list, blockbase_info); + } + + @Override +- @Override +- protected boolean mayPlaceOn(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return super.mayPlaceOn(blockstate, blockgetter, blockpos) || blockstate.is(Blocks.NETHERRACK) || blockstate.is(Blocks.SOUL_SAND) || blockstate.is(Blocks.SOUL_SOIL); ++ protected boolean mayPlaceOn(IBlockData state, BlockGetter level, BlockPos pos) { ++ return super.mayPlaceOn(state, level, pos) || state.is(Blocks.NETHERRACK) || state.is(Blocks.SOUL_SAND) || state.is(Blocks.SOUL_SOIL); + } + + @Override +- @Override +- public void animateTick(BlockState blockstate, Level level, BlockPos blockpos, RandomSource randomsource) { +- VoxelShape voxelshape = this.getShape(blockstate, level, blockpos, CollisionContext.empty()); +- Vec3 vec3 = voxelshape.bounds().getCenter(); +- double d0 = (double) blockpos.getX() + vec3.x; +- double d1 = (double) blockpos.getZ() + vec3.z; ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ VoxelShape voxelshape = this.getShape(state, level, pos, CollisionContext.empty()); ++ Vec3 vec3d = voxelshape.bounds().getCenter(); ++ double d0 = (double) pos.getX() + vec3d.x; ++ double d1 = (double) pos.getZ() + vec3d.z; + + for (int i = 0; i < 3; ++i) { +- if (randomsource.nextBoolean()) { +- level.addParticle(ParticleTypes.SMOKE, d0 + randomsource.nextDouble() / 5.0D, (double) blockpos.getY() + (0.5D - randomsource.nextDouble()), d1 + randomsource.nextDouble() / 5.0D, 0.0D, 0.0D, 0.0D); ++ if (random.nextBoolean()) { ++ level.addParticle(ParticleTypes.SMOKE, d0 + random.nextDouble() / 5.0D, (double) pos.getY() + (0.5D - random.nextDouble()), d1 + random.nextDouble() / 5.0D, 0.0D, 0.0D, 0.0D); + } + } + + } + + @Override +- @Override +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { + if (!level.isClientSide && level.getDifficulty() != Difficulty.PEACEFUL) { + if (entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; ++ LivingEntity entityliving = (LivingEntity) entity; + +- if (!livingentity.isInvulnerableTo(level.damageSources().wither())) { +- livingentity.addEffect(new MobEffectInstance(MobEffects.WITHER, 40)); ++ if (!entityliving.isInvulnerableTo(level.damageSources().wither())) { ++ entityliving.addEffect(new MobEffectInstance(MobEffects.WITHER, 40), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.WITHER_ROSE); // CraftBukkit + } + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/WitherSkullBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/WitherSkullBlock.java.patch new file mode 100644 index 0000000000..9679161a58 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/WitherSkullBlock.java.patch @@ -0,0 +1,146 @@ +--- a/net/minecraft/world/level/block/WitherSkullBlock.java ++++ b/net/minecraft/world/level/block/WitherSkullBlock.java +@@ -19,12 +19,16 @@ + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.SkullBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.pattern.BlockInWorld; + import net.minecraft.world.level.block.state.pattern.BlockPattern; + import net.minecraft.world.level.block.state.pattern.BlockPatternBuilder; + import net.minecraft.world.level.block.state.predicate.BlockStatePredicate; + ++// CraftBukkit start ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; ++// CraftBukkit end ++ + public class WitherSkullBlock extends SkullBlock { + + public static final MapCodec CODEC = simpleCodec(WitherSkullBlock::new); +@@ -34,55 +38,60 @@ + private static BlockPattern witherPatternBase; + + @Override +- @Override + public MapCodec codec() { + return WitherSkullBlock.CODEC; + } + +- protected WitherSkullBlock(BlockBehaviour.Properties blockbehaviour_properties) { +- super(SkullBlock.Types.WITHER_SKELETON, blockbehaviour_properties); ++ protected WitherSkullBlock(BlockBehaviour.Properties properties) { ++ super(SkullBlock.Type.WITHER_SKELETON, properties); + } + + @Override +- @Override +- public void setPlacedBy(Level level, BlockPos blockpos, BlockState blockstate, @Nullable LivingEntity livingentity, ItemStack itemstack) { +- super.setPlacedBy(level, blockpos, blockstate, livingentity, itemstack); +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, @Nullable LivingEntity placer, ItemStack stack) { ++ super.setPlacedBy(level, pos, state, placer, stack); ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof SkullBlockEntity) { +- checkSpawn(level, blockpos, (SkullBlockEntity) blockentity); ++ if (tileentity instanceof SkullBlockEntity) { ++ checkSpawn(level, pos, (SkullBlockEntity) tileentity); + } + + } + +- public static void checkSpawn(Level level, BlockPos blockpos, SkullBlockEntity skullblockentity) { ++ public static void checkSpawn(Level level, BlockPos pos, SkullBlockEntity blockEntity) { ++ if (level.captureBlockStates) return; // CraftBukkit + if (!level.isClientSide) { +- BlockState blockstate = skullblockentity.getBlockState(); +- boolean flag = blockstate.is(Blocks.WITHER_SKELETON_SKULL) || blockstate.is(Blocks.WITHER_SKELETON_WALL_SKULL); ++ IBlockData iblockdata = blockEntity.getBlockState(); ++ boolean flag = iblockdata.is(Blocks.WITHER_SKELETON_SKULL) || iblockdata.is(Blocks.WITHER_SKELETON_WALL_SKULL); + +- if (flag && blockpos.getY() >= level.getMinBuildHeight() && level.getDifficulty() != Difficulty.PEACEFUL) { +- BlockPattern.BlockPatternMatch blockpattern_blockpatternmatch = getOrCreateWitherFull().find(level, blockpos); ++ if (flag && pos.getY() >= level.getMinBuildHeight() && level.getDifficulty() != Difficulty.PEACEFUL) { ++ BlockPattern.BlockPatternMatch shapedetector_shapedetectorcollection = getOrCreateWitherFull().find(level, pos); + +- if (blockpattern_blockpatternmatch != null) { +- WitherBoss witherboss = (WitherBoss) EntityType.WITHER.create(level); ++ if (shapedetector_shapedetectorcollection != null) { ++ WitherBoss entitywither = (WitherBoss) EntityType.WITHER.create(level); + +- if (witherboss != null) { +- CarvedPumpkinBlock.clearPatternBlocks(level, blockpattern_blockpatternmatch); +- BlockPos blockpos1 = blockpattern_blockpatternmatch.getBlock(1, 2, 0).getPos(); ++ if (entitywither != null) { ++ // BlockPumpkinCarved.clearPatternBlocks(world, shapedetector_shapedetectorcollection); // CraftBukkit - move down ++ BlockPos blockposition1 = shapedetector_shapedetectorcollection.getBlock(1, 2, 0).getPos(); + +- witherboss.moveTo((double) blockpos1.getX() + 0.5D, (double) blockpos1.getY() + 0.55D, (double) blockpos1.getZ() + 0.5D, blockpattern_blockpatternmatch.getForwards().getAxis() == Direction.Axis.X ? 0.0F : 90.0F, 0.0F); +- witherboss.yBodyRot = blockpattern_blockpatternmatch.getForwards().getAxis() == Direction.Axis.X ? 0.0F : 90.0F; +- witherboss.makeInvulnerable(); +- Iterator iterator = level.getEntitiesOfClass(ServerPlayer.class, witherboss.getBoundingBox().inflate(50.0D)).iterator(); ++ entitywither.moveTo((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.55D, (double) blockposition1.getZ() + 0.5D, shapedetector_shapedetectorcollection.getForwards().getAxis() == Direction.Axis.X ? 0.0F : 90.0F, 0.0F); ++ entitywither.yBodyRot = shapedetector_shapedetectorcollection.getForwards().getAxis() == Direction.Axis.X ? 0.0F : 90.0F; ++ entitywither.makeInvulnerable(); ++ // CraftBukkit start ++ if (!level.addFreshEntity(entitywither, SpawnReason.BUILD_WITHER)) { ++ return; ++ } ++ CarvedPumpkinBlock.clearPatternBlocks(level, shapedetector_shapedetectorcollection); // CraftBukkit - from above ++ // CraftBukkit end ++ Iterator iterator = level.getEntitiesOfClass(ServerPlayer.class, entitywither.getBoundingBox().inflate(50.0D)).iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- CriteriaTriggers.SUMMONED_ENTITY.trigger(serverplayer, (Entity) witherboss); ++ CriteriaTriggers.SUMMONED_ENTITY.trigger(entityplayer, (Entity) entitywither); + } + +- level.addFreshEntity(witherboss); +- CarvedPumpkinBlock.updatePatternBlocks(level, blockpattern_blockpatternmatch); ++ // world.addFreshEntity(entitywither); // CraftBukkit - moved up ++ CarvedPumpkinBlock.updatePatternBlocks(level, shapedetector_shapedetectorcollection); + } + + } +@@ -90,16 +99,16 @@ + } + } + +- public static boolean canSpawnMob(Level level, BlockPos blockpos, ItemStack itemstack) { +- return itemstack.is(Items.WITHER_SKELETON_SKULL) && blockpos.getY() >= level.getMinBuildHeight() + 2 && level.getDifficulty() != Difficulty.PEACEFUL && !level.isClientSide ? getOrCreateWitherBase().find(level, blockpos) != null : false; ++ public static boolean canSpawnMob(Level level, BlockPos pos, ItemStack stack) { ++ return stack.is(Items.WITHER_SKELETON_SKULL) && pos.getY() >= level.getMinBuildHeight() + 2 && level.getDifficulty() != Difficulty.PEACEFUL && !level.isClientSide ? getOrCreateWitherBase().find(level, pos) != null : false; + } + + private static BlockPattern getOrCreateWitherFull() { + if (WitherSkullBlock.witherPatternFull == null) { +- WitherSkullBlock.witherPatternFull = BlockPatternBuilder.start().aisle("^^^", "###", "~#~").where('#', (blockinworld) -> { +- return blockinworld.getState().is(BlockTags.WITHER_SUMMON_BASE_BLOCKS); +- }).where('^', BlockInWorld.hasState(BlockStatePredicate.forBlock(Blocks.WITHER_SKELETON_SKULL).or(BlockStatePredicate.forBlock(Blocks.WITHER_SKELETON_WALL_SKULL)))).where('~', (blockinworld) -> { +- return blockinworld.getState().isAir(); ++ WitherSkullBlock.witherPatternFull = BlockPatternBuilder.start().aisle("^^^", "###", "~#~").where('#', (shapedetectorblock) -> { ++ return shapedetectorblock.getState().is(BlockTags.WITHER_SUMMON_BASE_BLOCKS); ++ }).where('^', BlockInWorld.hasState(BlockStatePredicate.forBlock(Blocks.WITHER_SKELETON_SKULL).or(BlockStatePredicate.forBlock(Blocks.WITHER_SKELETON_WALL_SKULL)))).where('~', (shapedetectorblock) -> { ++ return shapedetectorblock.getState().isAir(); + }).build(); + } + +@@ -108,10 +117,10 @@ + + private static BlockPattern getOrCreateWitherBase() { + if (WitherSkullBlock.witherPatternBase == null) { +- WitherSkullBlock.witherPatternBase = BlockPatternBuilder.start().aisle(" ", "###", "~#~").where('#', (blockinworld) -> { +- return blockinworld.getState().is(BlockTags.WITHER_SUMMON_BASE_BLOCKS); +- }).where('~', (blockinworld) -> { +- return blockinworld.getState().isAir(); ++ WitherSkullBlock.witherPatternBase = BlockPatternBuilder.start().aisle(" ", "###", "~#~").where('#', (shapedetectorblock) -> { ++ return shapedetectorblock.getState().is(BlockTags.WITHER_SUMMON_BASE_BLOCKS); ++ }).where('~', (shapedetectorblock) -> { ++ return shapedetectorblock.getState().isAir(); + }).build(); + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java.patch new file mode 100644 index 0000000000..57ca7373fc --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java.patch @@ -0,0 +1,782 @@ +--- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -28,7 +28,6 @@ + import net.minecraft.world.ContainerHelper; + import net.minecraft.world.WorldlyContainer; + import net.minecraft.world.entity.ExperienceOrb; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.player.StackedContents; + import net.minecraft.world.inventory.ContainerData; + import net.minecraft.world.inventory.RecipeCraftingHolder; +@@ -40,12 +39,25 @@ + import net.minecraft.world.item.crafting.RecipeHolder; + import net.minecraft.world.item.crafting.RecipeManager; + import net.minecraft.world.item.crafting.RecipeType; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.AbstractFurnaceBlock; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.block.BlockExpEvent; ++import org.bukkit.event.inventory.FurnaceBurnEvent; ++import org.bukkit.event.inventory.FurnaceExtractEvent; ++import org.bukkit.event.inventory.FurnaceSmeltEvent; ++import org.bukkit.event.inventory.FurnaceStartSmeltEvent; ++import org.bukkit.inventory.CookingRecipe; ++// CraftBukkit end + + public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntity implements WorldlyContainer, RecipeCraftingHolder, StackedContentsCompatible { + +@@ -63,22 +75,21 @@ + public static final int BURN_TIME_STANDARD = 200; + public static final int BURN_COOL_SPEED = 2; + protected NonNullList items; +- int litTime; ++ public int litTime; + int litDuration; +- int cookingProgress; +- int cookingTotalTime; ++ public int cookingProgress; ++ public int cookingTotalTime; + protected final ContainerData dataAccess; +- private final Object2IntOpenHashMap recipesUsed; ++ public final Object2IntOpenHashMap recipesUsed; + private final RecipeManager.CachedCheck quickCheck; + +- protected AbstractFurnaceBlockEntity(BlockEntityType blockentitytype, BlockPos blockpos, BlockState blockstate, RecipeType recipetype) { +- super(blockentitytype, blockpos, blockstate); ++ protected AbstractFurnaceBlockEntity(BlockEntityType type, BlockPos pos, IBlockData blockState, RecipeType recipeType) { ++ super(type, pos, blockState); + this.items = NonNullList.withSize(3, ItemStack.EMPTY); + this.dataAccess = new ContainerData() { + @Override +- @Override +- public int get(int i) { +- switch (i) { ++ public int get(int index) { ++ switch (index) { + case 0: + return AbstractFurnaceBlockEntity.this.litTime; + case 1: +@@ -93,125 +104,157 @@ + } + + @Override +- @Override +- public void set(int i, int j) { +- switch (i) { ++ public void set(int index, int value) { ++ switch (index) { + case 0: +- AbstractFurnaceBlockEntity.this.litTime = j; ++ AbstractFurnaceBlockEntity.this.litTime = value; + break; + case 1: +- AbstractFurnaceBlockEntity.this.litDuration = j; ++ AbstractFurnaceBlockEntity.this.litDuration = value; + break; + case 2: +- AbstractFurnaceBlockEntity.this.cookingProgress = j; ++ AbstractFurnaceBlockEntity.this.cookingProgress = value; + break; + case 3: +- AbstractFurnaceBlockEntity.this.cookingTotalTime = j; ++ AbstractFurnaceBlockEntity.this.cookingTotalTime = value; + } + + } + + @Override +- @Override + public int getCount() { + return 4; + } + }; + this.recipesUsed = new Object2IntOpenHashMap(); +- this.quickCheck = RecipeManager.createCheck(recipetype); ++ this.quickCheck = RecipeManager.createCheck((RecipeType) recipeType); // CraftBukkit - decompile error // Eclipse fail + } + + public static Map getFuel() { + Map map = Maps.newLinkedHashMap(); + +- add(map, (ItemLike) Items.LAVA_BUCKET, 20000); +- add(map, (ItemLike) Blocks.COAL_BLOCK, 16000); +- add(map, (ItemLike) Items.BLAZE_ROD, 2400); +- add(map, (ItemLike) Items.COAL, 1600); +- add(map, (ItemLike) Items.CHARCOAL, 1600); ++ add(map, (IMaterial) Items.LAVA_BUCKET, 20000); ++ add(map, (IMaterial) Blocks.COAL_BLOCK, 16000); ++ add(map, (IMaterial) Items.BLAZE_ROD, 2400); ++ add(map, (IMaterial) Items.COAL, 1600); ++ add(map, (IMaterial) Items.CHARCOAL, 1600); + add(map, ItemTags.LOGS, 300); + add(map, ItemTags.BAMBOO_BLOCKS, 300); + add(map, ItemTags.PLANKS, 300); +- add(map, (ItemLike) Blocks.BAMBOO_MOSAIC, 300); ++ add(map, (IMaterial) Blocks.BAMBOO_MOSAIC, 300); + add(map, ItemTags.WOODEN_STAIRS, 300); +- add(map, (ItemLike) Blocks.BAMBOO_MOSAIC_STAIRS, 300); ++ add(map, (IMaterial) Blocks.BAMBOO_MOSAIC_STAIRS, 300); + add(map, ItemTags.WOODEN_SLABS, 150); +- add(map, (ItemLike) Blocks.BAMBOO_MOSAIC_SLAB, 150); ++ add(map, (IMaterial) Blocks.BAMBOO_MOSAIC_SLAB, 150); + add(map, ItemTags.WOODEN_TRAPDOORS, 300); + add(map, ItemTags.WOODEN_PRESSURE_PLATES, 300); + add(map, ItemTags.WOODEN_FENCES, 300); + add(map, ItemTags.FENCE_GATES, 300); +- add(map, (ItemLike) Blocks.NOTE_BLOCK, 300); +- add(map, (ItemLike) Blocks.BOOKSHELF, 300); +- add(map, (ItemLike) Blocks.CHISELED_BOOKSHELF, 300); +- add(map, (ItemLike) Blocks.LECTERN, 300); +- add(map, (ItemLike) Blocks.JUKEBOX, 300); +- add(map, (ItemLike) Blocks.CHEST, 300); +- add(map, (ItemLike) Blocks.TRAPPED_CHEST, 300); +- add(map, (ItemLike) Blocks.CRAFTING_TABLE, 300); +- add(map, (ItemLike) Blocks.DAYLIGHT_DETECTOR, 300); ++ add(map, (IMaterial) Blocks.NOTE_BLOCK, 300); ++ add(map, (IMaterial) Blocks.BOOKSHELF, 300); ++ add(map, (IMaterial) Blocks.CHISELED_BOOKSHELF, 300); ++ add(map, (IMaterial) Blocks.LECTERN, 300); ++ add(map, (IMaterial) Blocks.JUKEBOX, 300); ++ add(map, (IMaterial) Blocks.CHEST, 300); ++ add(map, (IMaterial) Blocks.TRAPPED_CHEST, 300); ++ add(map, (IMaterial) Blocks.CRAFTING_TABLE, 300); ++ add(map, (IMaterial) Blocks.DAYLIGHT_DETECTOR, 300); + add(map, ItemTags.BANNERS, 300); +- add(map, (ItemLike) Items.BOW, 300); +- add(map, (ItemLike) Items.FISHING_ROD, 300); +- add(map, (ItemLike) Blocks.LADDER, 300); ++ add(map, (IMaterial) Items.BOW, 300); ++ add(map, (IMaterial) Items.FISHING_ROD, 300); ++ add(map, (IMaterial) Blocks.LADDER, 300); + add(map, ItemTags.SIGNS, 200); + add(map, ItemTags.HANGING_SIGNS, 800); +- add(map, (ItemLike) Items.WOODEN_SHOVEL, 200); +- add(map, (ItemLike) Items.WOODEN_SWORD, 200); +- add(map, (ItemLike) Items.WOODEN_HOE, 200); +- add(map, (ItemLike) Items.WOODEN_AXE, 200); +- add(map, (ItemLike) Items.WOODEN_PICKAXE, 200); ++ add(map, (IMaterial) Items.WOODEN_SHOVEL, 200); ++ add(map, (IMaterial) Items.WOODEN_SWORD, 200); ++ add(map, (IMaterial) Items.WOODEN_HOE, 200); ++ add(map, (IMaterial) Items.WOODEN_AXE, 200); ++ add(map, (IMaterial) Items.WOODEN_PICKAXE, 200); + add(map, ItemTags.WOODEN_DOORS, 200); + add(map, ItemTags.BOATS, 1200); + add(map, ItemTags.WOOL, 100); + add(map, ItemTags.WOODEN_BUTTONS, 100); +- add(map, (ItemLike) Items.STICK, 100); ++ add(map, (IMaterial) Items.STICK, 100); + add(map, ItemTags.SAPLINGS, 100); +- add(map, (ItemLike) Items.BOWL, 100); ++ add(map, (IMaterial) Items.BOWL, 100); + add(map, ItemTags.WOOL_CARPETS, 67); +- add(map, (ItemLike) Blocks.DRIED_KELP_BLOCK, 4001); +- add(map, (ItemLike) Items.CROSSBOW, 300); +- add(map, (ItemLike) Blocks.BAMBOO, 50); +- add(map, (ItemLike) Blocks.DEAD_BUSH, 100); +- add(map, (ItemLike) Blocks.SCAFFOLDING, 50); +- add(map, (ItemLike) Blocks.LOOM, 300); +- add(map, (ItemLike) Blocks.BARREL, 300); +- add(map, (ItemLike) Blocks.CARTOGRAPHY_TABLE, 300); +- add(map, (ItemLike) Blocks.FLETCHING_TABLE, 300); +- add(map, (ItemLike) Blocks.SMITHING_TABLE, 300); +- add(map, (ItemLike) Blocks.COMPOSTER, 300); +- add(map, (ItemLike) Blocks.AZALEA, 100); +- add(map, (ItemLike) Blocks.FLOWERING_AZALEA, 100); +- add(map, (ItemLike) Blocks.MANGROVE_ROOTS, 300); ++ add(map, (IMaterial) Blocks.DRIED_KELP_BLOCK, 4001); ++ add(map, (IMaterial) Items.CROSSBOW, 300); ++ add(map, (IMaterial) Blocks.BAMBOO, 50); ++ add(map, (IMaterial) Blocks.DEAD_BUSH, 100); ++ add(map, (IMaterial) Blocks.SCAFFOLDING, 50); ++ add(map, (IMaterial) Blocks.LOOM, 300); ++ add(map, (IMaterial) Blocks.BARREL, 300); ++ add(map, (IMaterial) Blocks.CARTOGRAPHY_TABLE, 300); ++ add(map, (IMaterial) Blocks.FLETCHING_TABLE, 300); ++ add(map, (IMaterial) Blocks.SMITHING_TABLE, 300); ++ add(map, (IMaterial) Blocks.COMPOSTER, 300); ++ add(map, (IMaterial) Blocks.AZALEA, 100); ++ add(map, (IMaterial) Blocks.FLOWERING_AZALEA, 100); ++ add(map, (IMaterial) Blocks.MANGROVE_ROOTS, 300); + return map; + } + ++ // CraftBukkit start - add fields and methods ++ private int maxStack = MAX_STACK; ++ public List transaction = new java.util.ArrayList(); ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ public Object2IntOpenHashMap getRecipesUsed() { ++ return this.recipesUsed; // PAIL private -> public ++ } ++ // CraftBukkit end ++ + private static boolean isNeverAFurnaceFuel(Item item) { + return item.builtInRegistryHolder().is(ItemTags.NON_FLAMMABLE_WOOD); + } + +- private static void add(Map map, TagKey tagkey, int i) { +- Iterator iterator = BuiltInRegistries.ITEM.getTagOrEmpty(tagkey).iterator(); ++ private static void add(Map map, TagKey itemTag, int burnTime) { ++ Iterator iterator = BuiltInRegistries.ITEM.getTagOrEmpty(itemTag).iterator(); + + while (iterator.hasNext()) { + Holder holder = (Holder) iterator.next(); + + if (!isNeverAFurnaceFuel((Item) holder.value())) { +- map.put((Item) holder.value(), i); ++ map.put((Item) holder.value(), burnTime); + } + } + + } + +- private static void add(Map map, ItemLike itemlike, int i) { +- Item item = itemlike.asItem(); ++ private static void add(Map map, IMaterial item, int burnTime) { ++ Item item1 = item.asItem(); + +- if (isNeverAFurnaceFuel(item)) { ++ if (isNeverAFurnaceFuel(item1)) { + if (SharedConstants.IS_RUNNING_IN_IDE) { +- throw (IllegalStateException) Util.pauseInIde(new IllegalStateException("A developer tried to explicitly make fire resistant item " + item.getName((ItemStack) null).getString() + " a furnace fuel. That will not work!")); ++ throw (IllegalStateException) Util.pauseInIde(new IllegalStateException("A developer tried to explicitly make fire resistant item " + item1.getName((ItemStack) null).getString() + " a furnace fuel. That will not work!")); + } + } else { +- map.put(item, i); ++ map.put(item1, burnTime); + } + } + +@@ -220,73 +263,82 @@ + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); ++ public void load(CompoundTag tag) { ++ super.load(tag); + this.items = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); +- ContainerHelper.loadAllItems(compoundtag, this.items); +- this.litTime = compoundtag.getShort("BurnTime"); +- this.cookingProgress = compoundtag.getShort("CookTime"); +- this.cookingTotalTime = compoundtag.getShort("CookTimeTotal"); ++ ContainerHelper.loadAllItems(tag, this.items); ++ this.litTime = tag.getShort("BurnTime"); ++ this.cookingProgress = tag.getShort("CookTime"); ++ this.cookingTotalTime = tag.getShort("CookTimeTotal"); + this.litDuration = this.getBurnDuration((ItemStack) this.items.get(1)); +- CompoundTag compoundtag1 = compoundtag.getCompound("RecipesUsed"); +- Iterator iterator = compoundtag1.getAllKeys().iterator(); ++ CompoundTag nbttagcompound1 = tag.getCompound("RecipesUsed"); ++ Iterator iterator = nbttagcompound1.getAllKeys().iterator(); + + while (iterator.hasNext()) { + String s = (String) iterator.next(); + +- this.recipesUsed.put(new ResourceLocation(s), compoundtag1.getInt(s)); ++ this.recipesUsed.put(new ResourceLocation(s), nbttagcompound1.getInt(s)); + } + + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); +- compoundtag.putShort("BurnTime", (short) this.litTime); +- compoundtag.putShort("CookTime", (short) this.cookingProgress); +- compoundtag.putShort("CookTimeTotal", (short) this.cookingTotalTime); +- ContainerHelper.saveAllItems(compoundtag, this.items); +- CompoundTag compoundtag1 = new CompoundTag(); ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); ++ tag.putShort("BurnTime", (short) this.litTime); ++ tag.putShort("CookTime", (short) this.cookingProgress); ++ tag.putShort("CookTimeTotal", (short) this.cookingTotalTime); ++ ContainerHelper.saveAllItems(tag, this.items); ++ CompoundTag nbttagcompound1 = new CompoundTag(); + +- this.recipesUsed.forEach((resourcelocation, integer) -> { +- compoundtag1.putInt(resourcelocation.toString(), integer); ++ this.recipesUsed.forEach((minecraftkey, integer) -> { ++ nbttagcompound1.putInt(minecraftkey.toString(), integer); + }); +- compoundtag.put("RecipesUsed", compoundtag1); ++ tag.put("RecipesUsed", nbttagcompound1); + } + +- public static void serverTick(Level level, BlockPos blockpos, BlockState blockstate, AbstractFurnaceBlockEntity abstractfurnaceblockentity) { +- boolean flag = abstractfurnaceblockentity.isLit(); ++ public static void serverTick(Level level, BlockPos pos, IBlockData state, AbstractFurnaceBlockEntity blockEntity) { ++ boolean flag = blockEntity.isLit(); + boolean flag1 = false; + +- if (abstractfurnaceblockentity.isLit()) { +- --abstractfurnaceblockentity.litTime; ++ if (blockEntity.isLit()) { ++ --blockEntity.litTime; + } + +- ItemStack itemstack = (ItemStack) abstractfurnaceblockentity.items.get(1); +- boolean flag2 = !((ItemStack) abstractfurnaceblockentity.items.get(0)).isEmpty(); ++ ItemStack itemstack = (ItemStack) blockEntity.items.get(1); ++ boolean flag2 = !((ItemStack) blockEntity.items.get(0)).isEmpty(); + boolean flag3 = !itemstack.isEmpty(); + +- if (!abstractfurnaceblockentity.isLit() && (!flag3 || !flag2)) { +- if (!abstractfurnaceblockentity.isLit() && abstractfurnaceblockentity.cookingProgress > 0) { +- abstractfurnaceblockentity.cookingProgress = Mth.clamp(abstractfurnaceblockentity.cookingProgress - 2, 0, abstractfurnaceblockentity.cookingTotalTime); ++ if (!blockEntity.isLit() && (!flag3 || !flag2)) { ++ if (!blockEntity.isLit() && blockEntity.cookingProgress > 0) { ++ blockEntity.cookingProgress = Mth.clamp(blockEntity.cookingProgress - 2, 0, blockEntity.cookingTotalTime); + } + } else { + RecipeHolder recipeholder; + + if (flag2) { +- recipeholder = (RecipeHolder) abstractfurnaceblockentity.quickCheck.getRecipeFor(abstractfurnaceblockentity, level).orElse((Object) null); ++ recipeholder = (RecipeHolder) blockEntity.quickCheck.getRecipeFor(blockEntity, level).orElse(null); // CraftBukkit - decompile error + } else { + recipeholder = null; + } + +- int i = abstractfurnaceblockentity.getMaxStackSize(); ++ int i = blockEntity.getMaxStackSize(); + +- if (!abstractfurnaceblockentity.isLit() && canBurn(level.registryAccess(), recipeholder, abstractfurnaceblockentity.items, i)) { +- abstractfurnaceblockentity.litTime = abstractfurnaceblockentity.getBurnDuration(itemstack); +- abstractfurnaceblockentity.litDuration = abstractfurnaceblockentity.litTime; +- if (abstractfurnaceblockentity.isLit()) { ++ if (!blockEntity.isLit() && canBurn(level.registryAccess(), recipeholder, blockEntity.items, i)) { ++ // CraftBukkit start ++ CraftItemStack fuel = CraftItemStack.asCraftMirror(itemstack); ++ ++ FurnaceBurnEvent furnaceBurnEvent = new FurnaceBurnEvent(CraftBlock.at(level, pos), fuel, blockEntity.getBurnDuration(itemstack)); ++ level.getCraftServer().getPluginManager().callEvent(furnaceBurnEvent); ++ ++ if (furnaceBurnEvent.isCancelled()) { ++ return; ++ } ++ ++ blockEntity.litTime = furnaceBurnEvent.getBurnTime(); ++ blockEntity.litDuration = blockEntity.litTime; ++ if (blockEntity.isLit() && furnaceBurnEvent.isBurning()) { ++ // CraftBukkit end + flag1 = true; + if (flag3) { + Item item = itemstack.getItem(); +@@ -295,43 +347,55 @@ + if (itemstack.isEmpty()) { + Item item1 = item.getCraftingRemainingItem(); + +- abstractfurnaceblockentity.items.set(1, item1 == null ? ItemStack.EMPTY : new ItemStack(item1)); ++ blockEntity.items.set(1, item1 == null ? ItemStack.EMPTY : new ItemStack(item1)); + } + } + } + } + +- if (abstractfurnaceblockentity.isLit() && canBurn(level.registryAccess(), recipeholder, abstractfurnaceblockentity.items, i)) { +- ++abstractfurnaceblockentity.cookingProgress; +- if (abstractfurnaceblockentity.cookingProgress == abstractfurnaceblockentity.cookingTotalTime) { +- abstractfurnaceblockentity.cookingProgress = 0; +- abstractfurnaceblockentity.cookingTotalTime = getTotalCookTime(level, abstractfurnaceblockentity); +- if (burn(level.registryAccess(), recipeholder, abstractfurnaceblockentity.items, i)) { +- abstractfurnaceblockentity.setRecipeUsed(recipeholder); ++ if (blockEntity.isLit() && canBurn(level.registryAccess(), recipeholder, blockEntity.items, i)) { ++ // CraftBukkit start ++ if (recipeholder != null && blockEntity.cookingProgress == 0) { ++ CraftItemStack source = CraftItemStack.asCraftMirror(blockEntity.items.get(0)); ++ CookingRecipe recipe = (CookingRecipe) recipeholder.toBukkitRecipe(); ++ ++ FurnaceStartSmeltEvent event = new FurnaceStartSmeltEvent(CraftBlock.at(level, pos), source, recipe); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ blockEntity.cookingTotalTime = event.getTotalCookTime(); ++ } ++ // CraftBukkit end ++ ++ ++blockEntity.cookingProgress; ++ if (blockEntity.cookingProgress == blockEntity.cookingTotalTime) { ++ blockEntity.cookingProgress = 0; ++ blockEntity.cookingTotalTime = getTotalCookTime(level, blockEntity); ++ if (burn(blockEntity.level, blockEntity.worldPosition, level.registryAccess(), recipeholder, blockEntity.items, i)) { // CraftBukkit ++ blockEntity.setRecipeUsed(recipeholder); + } + + flag1 = true; + } + } else { +- abstractfurnaceblockentity.cookingProgress = 0; ++ blockEntity.cookingProgress = 0; + } + } + +- if (flag != abstractfurnaceblockentity.isLit()) { ++ if (flag != blockEntity.isLit()) { + flag1 = true; +- blockstate = (BlockState) blockstate.setValue(AbstractFurnaceBlock.LIT, abstractfurnaceblockentity.isLit()); +- level.setBlock(blockpos, blockstate, 3); ++ state = (IBlockData) state.setValue(AbstractFurnaceBlock.LIT, blockEntity.isLit()); ++ level.setBlock(pos, state, 3); + } + + if (flag1) { +- setChanged(level, blockpos, blockstate); ++ setChanged(level, pos, state); + } + + } + +- private static boolean canBurn(RegistryAccess registryaccess, @Nullable RecipeHolder recipeholder, NonNullList nonnulllist, int i) { ++ private static boolean canBurn(RegistryAccess iregistrycustom, @Nullable RecipeHolder recipeholder, NonNullList nonnulllist, int i) { + if (!((ItemStack) nonnulllist.get(0)).isEmpty() && recipeholder != null) { +- ItemStack itemstack = recipeholder.value().getResultItem(registryaccess); ++ ItemStack itemstack = recipeholder.value().getResultItem(iregistrycustom); + + if (itemstack.isEmpty()) { + return false; +@@ -345,17 +409,44 @@ + } + } + +- private static boolean burn(RegistryAccess registryaccess, @Nullable RecipeHolder recipeholder, NonNullList nonnulllist, int i) { +- if (recipeholder != null && canBurn(registryaccess, recipeholder, nonnulllist, i)) { ++ private static boolean burn(Level world, BlockPos blockposition, RegistryAccess iregistrycustom, @Nullable RecipeHolder recipeholder, NonNullList nonnulllist, int i) { // CraftBukkit ++ if (recipeholder != null && canBurn(iregistrycustom, recipeholder, nonnulllist, i)) { + ItemStack itemstack = (ItemStack) nonnulllist.get(0); +- ItemStack itemstack1 = recipeholder.value().getResultItem(registryaccess); ++ ItemStack itemstack1 = recipeholder.value().getResultItem(iregistrycustom); + ItemStack itemstack2 = (ItemStack) nonnulllist.get(2); + ++ // CraftBukkit start - fire FurnaceSmeltEvent ++ CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); ++ org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); ++ ++ FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(CraftBlock.at(world, blockposition), source, result); ++ world.getCraftServer().getPluginManager().callEvent(furnaceSmeltEvent); ++ ++ if (furnaceSmeltEvent.isCancelled()) { ++ return false; ++ } ++ ++ result = furnaceSmeltEvent.getResult(); ++ itemstack1 = CraftItemStack.asNMSCopy(result); ++ ++ if (!itemstack1.isEmpty()) { ++ if (itemstack2.isEmpty()) { ++ nonnulllist.set(2, itemstack1.copy()); ++ } else if (CraftItemStack.asCraftMirror(itemstack2).isSimilar(result)) { ++ itemstack2.grow(itemstack1.getCount()); ++ } else { ++ return false; ++ } ++ } ++ ++ /* + if (itemstack2.isEmpty()) { + nonnulllist.set(2, itemstack1.copy()); + } else if (itemstack2.is(itemstack1.getItem())) { + itemstack2.grow(1); + } ++ */ ++ // CraftBukkit end + + if (itemstack.is(Blocks.WET_SPONGE.asItem()) && !((ItemStack) nonnulllist.get(1)).isEmpty() && ((ItemStack) nonnulllist.get(1)).is(Items.BUCKET)) { + nonnulllist.set(1, new ItemStack(Items.WATER_BUCKET)); +@@ -368,52 +459,48 @@ + } + } + +- protected int getBurnDuration(ItemStack itemstack) { +- if (itemstack.isEmpty()) { ++ protected int getBurnDuration(ItemStack fuel) { ++ if (fuel.isEmpty()) { + return 0; + } else { +- Item item = itemstack.getItem(); ++ Item item = fuel.getItem(); + + return (Integer) getFuel().getOrDefault(item, 0); + } + } + +- private static int getTotalCookTime(Level level, AbstractFurnaceBlockEntity abstractfurnaceblockentity) { +- return (Integer) abstractfurnaceblockentity.quickCheck.getRecipeFor(abstractfurnaceblockentity, level).map((recipeholder) -> { ++ private static int getTotalCookTime(Level level, AbstractFurnaceBlockEntity blockEntity) { ++ if (level == null) return 200; // CraftBukkit - SPIGOT-4302 ++ return (Integer) blockEntity.quickCheck.getRecipeFor(blockEntity, level).map((recipeholder) -> { + return ((AbstractCookingRecipe) recipeholder.value()).getCookingTime(); + }).orElse(200); + } + +- public static boolean isFuel(ItemStack itemstack) { +- return getFuel().containsKey(itemstack.getItem()); ++ public static boolean isFuel(ItemStack stack) { ++ return getFuel().containsKey(stack.getItem()); + } + + @Override +- @Override +- public int[] getSlotsForFace(Direction direction) { +- return direction == Direction.DOWN ? AbstractFurnaceBlockEntity.SLOTS_FOR_DOWN : (direction == Direction.UP ? AbstractFurnaceBlockEntity.SLOTS_FOR_UP : AbstractFurnaceBlockEntity.SLOTS_FOR_SIDES); ++ public int[] getSlotsForFace(Direction side) { ++ return side == Direction.DOWN ? AbstractFurnaceBlockEntity.SLOTS_FOR_DOWN : (side == Direction.UP ? AbstractFurnaceBlockEntity.SLOTS_FOR_UP : AbstractFurnaceBlockEntity.SLOTS_FOR_SIDES); + } + + @Override +- @Override +- public boolean canPlaceItemThroughFace(int i, ItemStack itemstack, @Nullable Direction direction) { +- return this.canPlaceItem(i, itemstack); ++ public boolean canPlaceItemThroughFace(int index, ItemStack itemStack, @Nullable Direction direction) { ++ return this.canPlaceItem(index, itemStack); + } + + @Override +- @Override +- public boolean canTakeItemThroughFace(int i, ItemStack itemstack, Direction direction) { +- return direction == Direction.DOWN && i == 1 ? itemstack.is(Items.WATER_BUCKET) || itemstack.is(Items.BUCKET) : true; ++ public boolean canTakeItemThroughFace(int index, ItemStack stack, Direction direction) { ++ return direction == Direction.DOWN && index == 1 ? stack.is(Items.WATER_BUCKET) || stack.is(Items.BUCKET) : true; + } + + @Override +- @Override + public int getContainerSize() { + return this.items.size(); + } + + @Override +- @Override + public boolean isEmpty() { + Iterator iterator = this.items.iterator(); + +@@ -431,35 +518,31 @@ + } + + @Override +- @Override +- public ItemStack getItem(int i) { +- return (ItemStack) this.items.get(i); ++ public ItemStack getItem(int index) { ++ return (ItemStack) this.items.get(index); + } + + @Override +- @Override +- public ItemStack removeItem(int i, int j) { +- return ContainerHelper.removeItem(this.items, i, j); ++ public ItemStack removeItem(int index, int count) { ++ return ContainerHelper.removeItem(this.items, index, count); + } + + @Override +- @Override +- public ItemStack removeItemNoUpdate(int i) { +- return ContainerHelper.takeItem(this.items, i); ++ public ItemStack removeItemNoUpdate(int index) { ++ return ContainerHelper.takeItem(this.items, index); + } + + @Override +- @Override +- public void setItem(int i, ItemStack itemstack) { +- ItemStack itemstack1 = (ItemStack) this.items.get(i); +- boolean flag = !itemstack.isEmpty() && ItemStack.isSameItemSameTags(itemstack1, itemstack); ++ public void setItem(int index, ItemStack stack) { ++ ItemStack itemstack1 = (ItemStack) this.items.get(index); ++ boolean flag = !stack.isEmpty() && ItemStack.isSameItemSameTags(itemstack1, stack); + +- this.items.set(i, itemstack); +- if (itemstack.getCount() > this.getMaxStackSize()) { +- itemstack.setCount(this.getMaxStackSize()); ++ this.items.set(index, stack); ++ if (stack.getCount() > this.getMaxStackSize()) { ++ stack.setCount(this.getMaxStackSize()); + } + +- if (i == 0 && !flag) { ++ if (index == 0 && !flag) { + this.cookingTotalTime = getTotalCookTime(this.level, this); + this.cookingProgress = 0; + this.setChanged(); +@@ -468,87 +551,87 @@ + } + + @Override +- @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { + return Container.stillValidBlockEntity(this, player); + } + + @Override +- @Override +- public boolean canPlaceItem(int i, ItemStack itemstack) { +- if (i == 2) { ++ public boolean canPlaceItem(int index, ItemStack stack) { ++ if (index == 2) { + return false; +- } else if (i != 1) { ++ } else if (index != 1) { + return true; + } else { + ItemStack itemstack1 = (ItemStack) this.items.get(1); + +- return isFuel(itemstack) || itemstack.is(Items.BUCKET) && !itemstack1.is(Items.BUCKET); ++ return isFuel(stack) || stack.is(Items.BUCKET) && !itemstack1.is(Items.BUCKET); + } + } + + @Override +- @Override + public void clearContent() { + this.items.clear(); + } + + @Override +- @Override + public void setRecipeUsed(@Nullable RecipeHolder recipeholder) { + if (recipeholder != null) { +- ResourceLocation resourcelocation = recipeholder.id(); ++ ResourceLocation minecraftkey = recipeholder.id(); + +- this.recipesUsed.addTo(resourcelocation, 1); ++ this.recipesUsed.addTo(minecraftkey, 1); + } + + } + + @Nullable + @Override +- @Override + public RecipeHolder getRecipeUsed() { + return null; + } + + @Override +- @Override +- public void awardUsedRecipes(Player player, List list) {} ++ public void awardUsedRecipes(net.minecraft.world.entity.player.Player player, List items) {} + +- public void awardUsedRecipesAndPopExperience(ServerPlayer serverplayer) { +- List> list = this.getRecipesToAwardAndPopExperience(serverplayer.serverLevel(), serverplayer.position()); ++ public void awardUsedRecipesAndPopExperience(ServerPlayer entityplayer, ItemStack itemstack, int amount) { // CraftBukkit ++ List> list = this.getRecipesToAwardAndPopExperience(entityplayer.serverLevel(), entityplayer.position(), this.worldPosition, entityplayer, itemstack, amount); // CraftBukkit + +- serverplayer.awardRecipes(list); ++ entityplayer.awardRecipes(list); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { + RecipeHolder recipeholder = (RecipeHolder) iterator.next(); + + if (recipeholder != null) { +- serverplayer.triggerRecipeCrafted(recipeholder, this.items); ++ entityplayer.triggerRecipeCrafted(recipeholder, this.items); + } + } + + this.recipesUsed.clear(); + } + +- public List> getRecipesToAwardAndPopExperience(ServerLevel serverlevel, Vec3 vec3) { ++ public List> getRecipesToAwardAndPopExperience(ServerLevel level, Vec3 popVec) { ++ // CraftBukkit start ++ return this.getRecipesToAwardAndPopExperience(level, popVec, this.worldPosition, null, null, 0); ++ } ++ ++ public List> getRecipesToAwardAndPopExperience(ServerLevel worldserver, Vec3 vec3d, BlockPos blockposition, ServerPlayer entityplayer, ItemStack itemstack, int amount) { ++ // CraftBukkit end + List> list = Lists.newArrayList(); + ObjectIterator objectiterator = this.recipesUsed.object2IntEntrySet().iterator(); + + while (objectiterator.hasNext()) { + Entry entry = (Entry) objectiterator.next(); + +- serverlevel.getRecipeManager().byKey((ResourceLocation) entry.getKey()).ifPresent((recipeholder) -> { ++ worldserver.getRecipeManager().byKey((ResourceLocation) entry.getKey()).ifPresent((recipeholder) -> { + list.add(recipeholder); +- createExperience(serverlevel, vec3, entry.getIntValue(), ((AbstractCookingRecipe) recipeholder.value()).getExperience()); ++ createExperience(worldserver, vec3d, entry.getIntValue(), ((AbstractCookingRecipe) recipeholder.value()).getExperience(), blockposition, entityplayer, itemstack, amount); // CraftBukkit + }); + } + + return list; + } + +- private static void createExperience(ServerLevel serverlevel, Vec3 vec3, int i, float f) { ++ private static void createExperience(ServerLevel worldserver, Vec3 vec3d, int i, float f, BlockPos blockposition, net.minecraft.world.entity.player.Player entityhuman, ItemStack itemstack, int amount) { // CraftBukkit + int j = Mth.floor((float) i * f); + float f1 = Mth.frac((float) i * f); + +@@ -556,18 +639,28 @@ + ++j; + } + +- ExperienceOrb.award(serverlevel, vec3, j); ++ // CraftBukkit start - fire FurnaceExtractEvent / BlockExpEvent ++ BlockExpEvent event; ++ if (amount != 0) { ++ event = new FurnaceExtractEvent((Player) entityhuman.getBukkitEntity(), CraftBlock.at(worldserver, blockposition), org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(itemstack.getItem()), amount, j); ++ } else { ++ event = new BlockExpEvent(CraftBlock.at(worldserver, blockposition), j); ++ } ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ j = event.getExpToDrop(); ++ // CraftBukkit end ++ ++ ExperienceOrb.award(worldserver, vec3d, j); + } + + @Override +- @Override +- public void fillStackedContents(StackedContents stackedcontents) { ++ public void fillStackedContents(StackedContents helper) { + Iterator iterator = this.items.iterator(); + + while (iterator.hasNext()) { + ItemStack itemstack = (ItemStack) iterator.next(); + +- stackedcontents.accountStack(itemstack); ++ helper.accountStack(itemstack); + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BannerBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BannerBlockEntity.java.patch new file mode 100644 index 0000000000..a6185e09b1 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BannerBlockEntity.java.patch @@ -0,0 +1,236 @@ +--- a/net/minecraft/world/level/block/entity/BannerBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BannerBlockEntity.java +@@ -11,15 +11,15 @@ + import net.minecraft.nbt.ListTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +-import net.minecraft.world.Nameable; ++import net.minecraft.world.INamableTileEntity; + import net.minecraft.world.item.BlockItem; + import net.minecraft.world.item.DyeColor; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.AbstractBannerBlock; + import net.minecraft.world.level.block.BannerBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + +-public class BannerBlockEntity extends BlockEntity implements Nameable { ++public class BannerBlockEntity extends BlockEntity implements INamableTileEntity { + + public static final int MAX_PATTERNS = 6; + public static final String TAG_PATTERNS = "Patterns"; +@@ -27,104 +27,103 @@ + public static final String TAG_COLOR = "Color"; + @Nullable + private Component name; +- private DyeColor baseColor; ++ public DyeColor baseColor; + @Nullable +- private ListTag itemPatterns; ++ public ListTag itemPatterns; + @Nullable + private List, DyeColor>> patterns; + +- public BannerBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.BANNER, blockpos, blockstate); +- this.baseColor = ((AbstractBannerBlock) blockstate.getBlock()).getColor(); ++ public BannerBlockEntity(BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.BANNER, pos, blockState); ++ this.baseColor = ((AbstractBannerBlock) blockState.getBlock()).getColor(); + } + +- public BannerBlockEntity(BlockPos blockpos, BlockState blockstate, DyeColor dyecolor) { +- this(blockpos, blockstate); +- this.baseColor = dyecolor; ++ public BannerBlockEntity(BlockPos pos, IBlockData blockState, DyeColor baseColor) { ++ this(pos, blockState); ++ this.baseColor = baseColor; + } + + @Nullable +- public static ListTag getItemPatterns(ItemStack itemstack) { +- ListTag listtag = null; +- CompoundTag compoundtag = BlockItem.getBlockEntityData(itemstack); ++ public static ListTag getItemPatterns(ItemStack stack) { ++ ListTag nbttaglist = null; ++ CompoundTag nbttagcompound = BlockItem.getBlockEntityData(stack); + +- if (compoundtag != null && compoundtag.contains("Patterns", 9)) { +- listtag = compoundtag.getList("Patterns", 10).copy(); ++ if (nbttagcompound != null && nbttagcompound.contains("Patterns", 9)) { ++ nbttaglist = nbttagcompound.getList("Patterns", 10).copy(); + } + +- return listtag; ++ return nbttaglist; + } + +- public void fromItem(ItemStack itemstack, DyeColor dyecolor) { +- this.baseColor = dyecolor; +- this.fromItem(itemstack); ++ public void fromItem(ItemStack stack, DyeColor color) { ++ this.baseColor = color; ++ this.fromItem(stack); + } + +- public void fromItem(ItemStack itemstack) { +- this.itemPatterns = getItemPatterns(itemstack); ++ public void fromItem(ItemStack item) { ++ this.itemPatterns = getItemPatterns(item); + this.patterns = null; +- this.name = itemstack.hasCustomHoverName() ? itemstack.getHoverName() : null; ++ this.name = item.hasCustomHoverName() ? item.getHoverName() : null; + } + + @Override +- @Override + public Component getName() { + return (Component) (this.name != null ? this.name : Component.translatable("block.minecraft.banner")); + } + + @Nullable + @Override +- @Override + public Component getCustomName() { + return this.name; + } + +- public void setCustomName(Component component) { +- this.name = component; ++ public void setCustomName(Component name) { ++ this.name = name; + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); + if (this.itemPatterns != null) { +- compoundtag.put("Patterns", this.itemPatterns); ++ tag.put("Patterns", this.itemPatterns); + } + + if (this.name != null) { +- compoundtag.putString("CustomName", Component.Serializer.toJson(this.name)); ++ tag.putString("CustomName", Component.Serializer.toJson(this.name)); + } + + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); +- if (compoundtag.contains("CustomName", 8)) { +- this.name = Component.Serializer.fromJson(compoundtag.getString("CustomName")); ++ public void load(CompoundTag tag) { ++ super.load(tag); ++ if (tag.contains("CustomName", 8)) { ++ this.name = Component.Serializer.fromJson(tag.getString("CustomName")); + } + +- this.itemPatterns = compoundtag.getList("Patterns", 10); ++ this.itemPatterns = tag.getList("Patterns", 10); ++ // CraftBukkit start ++ while (this.itemPatterns.size() > 20) { ++ this.itemPatterns.remove(20); ++ } ++ // CraftBukkit end + this.patterns = null; + } + + @Override +- @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + @Override +- @Override + public CompoundTag getUpdateTag() { + return this.saveWithoutMetadata(); + } + +- public static int getPatternCount(ItemStack itemstack) { +- CompoundTag compoundtag = BlockItem.getBlockEntityData(itemstack); ++ public static int getPatternCount(ItemStack stack) { ++ CompoundTag nbttagcompound = BlockItem.getBlockEntityData(stack); + +- return compoundtag != null && compoundtag.contains("Patterns") ? compoundtag.getList("Patterns", 10).size() : 0; ++ return nbttagcompound != null && nbttagcompound.contains("Patterns") ? nbttagcompound.getList("Patterns", 10).size() : 0; + } + + public List, DyeColor>> getPatterns() { +@@ -135,17 +134,17 @@ + return this.patterns; + } + +- public static List, DyeColor>> createPatterns(DyeColor dyecolor, @Nullable ListTag listtag) { ++ public static List, DyeColor>> createPatterns(DyeColor color, @Nullable ListTag listTag) { + List, DyeColor>> list = Lists.newArrayList(); + +- list.add(Pair.of(BuiltInRegistries.BANNER_PATTERN.getHolderOrThrow(BannerPatterns.BASE), dyecolor)); +- if (listtag != null) { +- for (int i = 0; i < listtag.size(); ++i) { +- CompoundTag compoundtag = listtag.getCompound(i); +- Holder holder = BannerPattern.byHash(compoundtag.getString("Pattern")); ++ list.add(Pair.of(BuiltInRegistries.BANNER_PATTERN.getHolderOrThrow(BannerPatterns.BASE), color)); ++ if (listTag != null) { ++ for (int i = 0; i < listTag.size(); ++i) { ++ CompoundTag nbttagcompound = listTag.getCompound(i); ++ Holder holder = BannerPattern.byHash(nbttagcompound.getString("Pattern")); + + if (holder != null) { +- int j = compoundtag.getInt("Color"); ++ int j = nbttagcompound.getInt("Color"); + + list.add(Pair.of(holder, DyeColor.byId(j))); + } +@@ -155,21 +154,21 @@ + return list; + } + +- public static void removeLastPattern(ItemStack itemstack) { +- CompoundTag compoundtag = BlockItem.getBlockEntityData(itemstack); ++ public static void removeLastPattern(ItemStack stack) { ++ CompoundTag nbttagcompound = BlockItem.getBlockEntityData(stack); + +- if (compoundtag != null && compoundtag.contains("Patterns", 9)) { +- ListTag listtag = compoundtag.getList("Patterns", 10); ++ if (nbttagcompound != null && nbttagcompound.contains("Patterns", 9)) { ++ ListTag nbttaglist = nbttagcompound.getList("Patterns", 10); + +- if (!listtag.isEmpty()) { +- listtag.remove(listtag.size() - 1); +- if (listtag.isEmpty()) { +- compoundtag.remove("Patterns"); ++ if (!nbttaglist.isEmpty()) { ++ nbttaglist.remove(nbttaglist.size() - 1); ++ if (nbttaglist.isEmpty()) { ++ nbttagcompound.remove("Patterns"); + } + } + +- compoundtag.remove("id"); +- BlockItem.setBlockEntityData(itemstack, BlockEntityType.BANNER, compoundtag); ++ nbttagcompound.remove("id"); ++ BlockItem.setBlockEntityData(stack, BlockEntityType.BANNER, nbttagcompound); + } + } + +@@ -177,10 +176,10 @@ + ItemStack itemstack = new ItemStack(BannerBlock.byColor(this.baseColor)); + + if (this.itemPatterns != null && !this.itemPatterns.isEmpty()) { +- CompoundTag compoundtag = new CompoundTag(); ++ CompoundTag nbttagcompound = new CompoundTag(); + +- compoundtag.put("Patterns", this.itemPatterns.copy()); +- BlockItem.setBlockEntityData(itemstack, this.getType(), compoundtag); ++ nbttagcompound.put("Patterns", this.itemPatterns.copy()); ++ BlockItem.setBlockEntityData(itemstack, this.getType(), nbttagcompound); + } + + if (this.name != null) { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BarrelBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BarrelBlockEntity.java.patch new file mode 100644 index 0000000000..de8d0c6d24 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BarrelBlockEntity.java.patch @@ -0,0 +1,203 @@ +--- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java +@@ -18,42 +18,79 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.BarrelBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class BarrelBlockEntity extends RandomizableContainerBlockEntity { + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new ArrayList<>(); ++ private int maxStack = MAX_STACK; ++ ++ @Override ++ public List getContents() { ++ return this.items; ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ @Override ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ // CraftBukkit end + private NonNullList items; +- private final ContainerOpenersCounter openersCounter; ++ public final ContainerOpenersCounter openersCounter; + +- public BarrelBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.BARREL, blockpos, blockstate); ++ public BarrelBlockEntity(BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.BARREL, pos, blockState); + this.items = NonNullList.withSize(27, ItemStack.EMPTY); + this.openersCounter = new ContainerOpenersCounter() { + @Override +- @Override +- protected void onOpen(Level level, BlockPos blockpos1, BlockState blockstate1) { +- BarrelBlockEntity.this.playSound(blockstate1, SoundEvents.BARREL_OPEN); +- BarrelBlockEntity.this.updateBlockState(blockstate1, true); ++ protected void onOpen(Level level, BlockPos pos, IBlockData state) { ++ BarrelBlockEntity.this.playSound(state, SoundEvents.BARREL_OPEN); ++ BarrelBlockEntity.this.updateBlockState(state, true); + } + + @Override +- @Override +- protected void onClose(Level level, BlockPos blockpos1, BlockState blockstate1) { +- BarrelBlockEntity.this.playSound(blockstate1, SoundEvents.BARREL_CLOSE); +- BarrelBlockEntity.this.updateBlockState(blockstate1, false); ++ protected void onClose(Level level, BlockPos pos, IBlockData state) { ++ BarrelBlockEntity.this.playSound(state, SoundEvents.BARREL_CLOSE); ++ BarrelBlockEntity.this.updateBlockState(state, false); + } + + @Override +- @Override +- protected void openerCountChanged(Level level, BlockPos blockpos1, BlockState blockstate1, int i, int j) {} ++ protected void openerCountChanged(Level level, BlockPos pos, IBlockData state, int count, int openCount) {} + + @Override +- @Override + protected boolean isOwnContainer(Player player) { + if (player.containerMenu instanceof ChestMenu) { +- Container container = ((ChestMenu) player.containerMenu).getContainer(); ++ Container iinventory = ((ChestMenu) player.containerMenu).getContainer(); + +- return container == BarrelBlockEntity.this; ++ return iinventory == BarrelBlockEntity.this; + } else { + return false; + } +@@ -62,58 +99,50 @@ + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); +- if (!this.trySaveLootTable(compoundtag)) { +- ContainerHelper.saveAllItems(compoundtag, this.items); ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); ++ if (!this.trySaveLootTable(tag)) { ++ ContainerHelper.saveAllItems(tag, this.items); + } + + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); ++ public void load(CompoundTag tag) { ++ super.load(tag); + this.items = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); +- if (!this.tryLoadLootTable(compoundtag)) { +- ContainerHelper.loadAllItems(compoundtag, this.items); ++ if (!this.tryLoadLootTable(tag)) { ++ ContainerHelper.loadAllItems(tag, this.items); + } + + } + + @Override +- @Override + public int getContainerSize() { + return 27; + } + + @Override +- @Override + protected NonNullList getItems() { + return this.items; + } + + @Override +- @Override +- protected void setItems(NonNullList nonnulllist) { +- this.items = nonnulllist; ++ protected void setItems(NonNullList items) { ++ this.items = items; + } + + @Override +- @Override + protected Component getDefaultName() { + return Component.translatable("container.barrel"); + } + + @Override +- @Override +- protected AbstractContainerMenu createMenu(int i, Inventory inventory) { +- return ChestMenu.threeRows(i, inventory, this); ++ protected AbstractContainerMenu createMenu(int id, Inventory player) { ++ return ChestMenu.threeRows(id, player, this); + } + + @Override +- @Override + public void startOpen(Player player) { + if (!this.remove && !player.isSpectator()) { + this.openersCounter.incrementOpeners(player, this.getLevel(), this.getBlockPos(), this.getBlockState()); +@@ -122,7 +151,6 @@ + } + + @Override +- @Override + public void stopOpen(Player player) { + if (!this.remove && !player.isSpectator()) { + this.openersCounter.decrementOpeners(player, this.getLevel(), this.getBlockPos(), this.getBlockState()); +@@ -137,16 +165,16 @@ + + } + +- void updateBlockState(BlockState blockstate, boolean flag) { +- this.level.setBlock(this.getBlockPos(), (BlockState) blockstate.setValue(BarrelBlock.OPEN, flag), 3); ++ public void updateBlockState(IBlockData state, boolean open) { ++ this.level.setBlock(this.getBlockPos(), (IBlockData) state.setValue(BarrelBlock.OPEN, open), 3); + } + +- void playSound(BlockState blockstate, SoundEvent soundevent) { +- Vec3i vec3i = ((Direction) blockstate.getValue(BarrelBlock.FACING)).getNormal(); +- double d0 = (double) this.worldPosition.getX() + 0.5D + (double) vec3i.getX() / 2.0D; +- double d1 = (double) this.worldPosition.getY() + 0.5D + (double) vec3i.getY() / 2.0D; +- double d2 = (double) this.worldPosition.getZ() + 0.5D + (double) vec3i.getZ() / 2.0D; ++ public void playSound(IBlockData state, SoundEvent sound) { ++ Vec3i baseblockposition = ((Direction) state.getValue(BarrelBlock.FACING)).getNormal(); ++ double d0 = (double) this.worldPosition.getX() + 0.5D + (double) baseblockposition.getX() / 2.0D; ++ double d1 = (double) this.worldPosition.getY() + 0.5D + (double) baseblockposition.getY() / 2.0D; ++ double d2 = (double) this.worldPosition.getZ() + 0.5D + (double) baseblockposition.getZ() / 2.0D; + +- this.level.playSound((Player) null, d0, d1, d2, soundevent, SoundSource.BLOCKS, 0.5F, this.level.random.nextFloat() * 0.1F + 0.9F); ++ this.level.playSound((Player) null, d0, d1, d2, sound, SoundSource.BLOCKS, 0.5F, this.level.random.nextFloat() * 0.1F + 0.9F); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java.patch new file mode 100644 index 0000000000..726e674739 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java.patch @@ -0,0 +1,122 @@ +--- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java +@@ -7,66 +7,61 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.Container; ++import net.minecraft.world.INamableTileEntity; ++import net.minecraft.world.ITileInventory; + import net.minecraft.world.LockCode; +-import net.minecraft.world.MenuProvider; +-import net.minecraft.world.Nameable; + import net.minecraft.world.entity.player.Inventory; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.inventory.AbstractContainerMenu; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + +-public abstract class BaseContainerBlockEntity extends BlockEntity implements Container, MenuProvider, Nameable { ++public abstract class BaseContainerBlockEntity extends BlockEntity implements Container, ITileInventory, INamableTileEntity { + +- private LockCode lockKey; ++ public LockCode lockKey; + @Nullable +- private Component name; ++ public Component name; + +- protected BaseContainerBlockEntity(BlockEntityType blockentitytype, BlockPos blockpos, BlockState blockstate) { +- super(blockentitytype, blockpos, blockstate); ++ protected BaseContainerBlockEntity(BlockEntityType type, BlockPos pos, IBlockData blockState) { ++ super(type, pos, blockState); + this.lockKey = LockCode.NO_LOCK; + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); +- this.lockKey = LockCode.fromTag(compoundtag); +- if (compoundtag.contains("CustomName", 8)) { +- this.name = Component.Serializer.fromJson(compoundtag.getString("CustomName")); ++ public void load(CompoundTag tag) { ++ super.load(tag); ++ this.lockKey = LockCode.fromTag(tag); ++ if (tag.contains("CustomName", 8)) { ++ this.name = Component.Serializer.fromJson(tag.getString("CustomName")); + } + + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); +- this.lockKey.addToTag(compoundtag); ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); ++ this.lockKey.addToTag(tag); + if (this.name != null) { +- compoundtag.putString("CustomName", Component.Serializer.toJson(this.name)); ++ tag.putString("CustomName", Component.Serializer.toJson(this.name)); + } + + } + +- public void setCustomName(Component component) { +- this.name = component; ++ public void setCustomName(Component name) { ++ this.name = name; + } + + @Override +- @Override + public Component getName() { + return this.name != null ? this.name : this.getDefaultName(); + } + + @Override +- @Override + public Component getDisplayName() { + return this.getName(); + } + + @Nullable + @Override +- @Override + public Component getCustomName() { + return this.name; + } +@@ -77,9 +72,9 @@ + return canUnlock(player, this.lockKey, this.getDisplayName()); + } + +- public static boolean canUnlock(Player player, LockCode lockcode, Component component) { +- if (!player.isSpectator() && !lockcode.unlocksWith(player.getMainHandItem())) { +- player.displayClientMessage(Component.translatable("container.isLocked", component), true); ++ public static boolean canUnlock(Player player, LockCode code, Component displayName) { ++ if (!player.isSpectator() && !code.unlocksWith(player.getMainHandItem())) { ++ player.displayClientMessage(Component.translatable("container.isLocked", displayName), true); + player.playNotifySound(SoundEvents.CHEST_LOCKED, SoundSource.BLOCKS, 1.0F, 1.0F); + return false; + } else { +@@ -89,10 +84,17 @@ + + @Nullable + @Override +- @Override +- public AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) { +- return this.canOpen(player) ? this.createMenu(i, inventory) : null; ++ public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { ++ return this.canOpen(player) ? this.createMenu(containerId, playerInventory) : null; + } + + protected abstract AbstractContainerMenu createMenu(int containerId, Inventory inventory); ++ ++ // CraftBukkit start ++ @Override ++ public org.bukkit.Location getLocation() { ++ if (level == null) return null; ++ return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BeaconBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BeaconBlockEntity.java.patch new file mode 100644 index 0000000000..a8399a1e35 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BeaconBlockEntity.java.patch @@ -0,0 +1,521 @@ +--- a/net/minecraft/world/level/block/entity/BeaconBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +@@ -20,9 +20,9 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.tags.BlockTags; ++import net.minecraft.world.INamableTileEntity; ++import net.minecraft.world.ITileInventory; + import net.minecraft.world.LockCode; +-import net.minecraft.world.MenuProvider; +-import net.minecraft.world.Nameable; + import net.minecraft.world.effect.MobEffect; + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.effect.MobEffects; +@@ -33,14 +33,18 @@ + import net.minecraft.world.inventory.ContainerData; + import net.minecraft.world.inventory.ContainerLevelAccess; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.BeaconBeamBlock; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.IBeaconBeam; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.levelgen.Heightmap; + import net.minecraft.world.phys.AABB; ++// CraftBukkit start ++import org.bukkit.craftbukkit.potion.CraftPotionUtil; ++import org.bukkit.potion.PotionEffect; ++// CraftBukkit end + +-public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Nameable { ++public class BeaconBlockEntity extends BlockEntity implements ITileInventory, INamableTileEntity { + + private static final int MAX_LEVELS = 4; + public static final MobEffect[][] BEACON_EFFECTS = new MobEffect[][]{{MobEffects.MOVEMENT_SPEED, MobEffects.DIG_SPEED}, {MobEffects.DAMAGE_RESISTANCE, MobEffects.JUMP}, {MobEffects.DAMAGE_BOOST}, {MobEffects.REGENERATION}}; +@@ -55,32 +59,40 @@ + private static final String TAG_SECONDARY = "secondary_effect"; + List beamSections = Lists.newArrayList(); + private List checkingBeamSections = Lists.newArrayList(); +- int levels; ++ public int levels; + private int lastCheckY; + @Nullable +- MobEffect primaryPower; ++ public MobEffect primaryPower; + @Nullable +- MobEffect secondaryPower; ++ public MobEffect secondaryPower; + @Nullable +- private Component name; +- private LockCode lockKey; ++ public Component name; ++ public LockCode lockKey; + private final ContainerData dataAccess; ++ // CraftBukkit start - add fields and methods ++ public PotionEffect getPrimaryEffect() { ++ return (this.primaryPower != null) ? CraftPotionUtil.toBukkit(new MobEffectInstance(this.primaryPower, getLevel(this.levels), getAmplification(levels, primaryPower, secondaryPower), true, true)) : null; ++ } + ++ public PotionEffect getSecondaryEffect() { ++ return (hasSecondaryEffect(levels, primaryPower, secondaryPower)) ? CraftPotionUtil.toBukkit(new MobEffectInstance(this.secondaryPower, getLevel(this.levels), getAmplification(levels, primaryPower, secondaryPower), true, true)) : null; ++ } ++ // CraftBukkit end ++ + @Nullable +- static MobEffect filterEffect(@Nullable MobEffect mobeffect) { +- return BeaconBlockEntity.VALID_EFFECTS.contains(mobeffect) ? mobeffect : null; ++ static MobEffect filterEffect(@Nullable MobEffect mobeffectlist) { ++ return BeaconBlockEntity.VALID_EFFECTS.contains(mobeffectlist) ? mobeffectlist : null; + } + +- public BeaconBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.BEACON, blockpos, blockstate); ++ public BeaconBlockEntity(BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.BEACON, pos, blockState); + this.lockKey = LockCode.NO_LOCK; + this.dataAccess = new ContainerData() { + @Override +- @Override +- public int get(int i) { ++ public int get(int index) { + int j; + +- switch (i) { ++ switch (index) { + case 0: + j = BeaconBlockEntity.this.levels; + break; +@@ -98,126 +110,124 @@ + } + + @Override +- @Override +- public void set(int i, int j) { +- switch (i) { ++ public void set(int index, int value) { ++ switch (index) { + case 0: +- BeaconBlockEntity.this.levels = j; ++ BeaconBlockEntity.this.levels = value; + break; + case 1: + if (!BeaconBlockEntity.this.level.isClientSide && !BeaconBlockEntity.this.beamSections.isEmpty()) { + BeaconBlockEntity.playSound(BeaconBlockEntity.this.level, BeaconBlockEntity.this.worldPosition, SoundEvents.BEACON_POWER_SELECT); + } + +- BeaconBlockEntity.this.primaryPower = BeaconBlockEntity.filterEffect(BeaconMenu.decodeEffect(j)); ++ BeaconBlockEntity.this.primaryPower = BeaconBlockEntity.filterEffect(BeaconMenu.decodeEffect(value)); + break; + case 2: +- BeaconBlockEntity.this.secondaryPower = BeaconBlockEntity.filterEffect(BeaconMenu.decodeEffect(j)); ++ BeaconBlockEntity.this.secondaryPower = BeaconBlockEntity.filterEffect(BeaconMenu.decodeEffect(value)); + } + + } + + @Override +- @Override + public int getCount() { + return 3; + } + }; + } + +- public static void tick(Level level, BlockPos blockpos, BlockState blockstate, BeaconBlockEntity beaconblockentity) { +- int i = blockpos.getX(); +- int j = blockpos.getY(); +- int k = blockpos.getZ(); +- BlockPos blockpos1; ++ public static void tick(Level level, BlockPos pos, IBlockData state, BeaconBlockEntity blockEntity) { ++ int i = pos.getX(); ++ int j = pos.getY(); ++ int k = pos.getZ(); ++ BlockPos blockposition1; + +- if (beaconblockentity.lastCheckY < j) { +- blockpos1 = blockpos; +- beaconblockentity.checkingBeamSections = Lists.newArrayList(); +- beaconblockentity.lastCheckY = blockpos.getY() - 1; ++ if (blockEntity.lastCheckY < j) { ++ blockposition1 = pos; ++ blockEntity.checkingBeamSections = Lists.newArrayList(); ++ blockEntity.lastCheckY = pos.getY() - 1; + } else { +- blockpos1 = new BlockPos(i, beaconblockentity.lastCheckY + 1, k); ++ blockposition1 = new BlockPos(i, blockEntity.lastCheckY + 1, k); + } + +- BeaconBlockEntity.BeaconBeamSection beaconblockentity_beaconbeamsection = beaconblockentity.checkingBeamSections.isEmpty() ? null : (BeaconBlockEntity.BeaconBeamSection) beaconblockentity.checkingBeamSections.get(beaconblockentity.checkingBeamSections.size() - 1); ++ BeaconBlockEntity.BeaconBeamSection tileentitybeacon_beaconcolortracker = blockEntity.checkingBeamSections.isEmpty() ? null : (BeaconBlockEntity.BeaconBeamSection) blockEntity.checkingBeamSections.get(blockEntity.checkingBeamSections.size() - 1); + int l = level.getHeight(Heightmap.Types.WORLD_SURFACE, i, k); + + int i1; + +- for (i1 = 0; i1 < 10 && blockpos1.getY() <= l; ++i1) { +- BlockState blockstate1 = level.getBlockState(blockpos1); +- Block block = blockstate1.getBlock(); ++ for (i1 = 0; i1 < 10 && blockposition1.getY() <= l; ++i1) { ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ Block block = iblockdata1.getBlock(); + +- if (block instanceof BeaconBeamBlock) { +- float[] afloat = ((BeaconBeamBlock) block).getColor().getTextureDiffuseColors(); ++ if (block instanceof IBeaconBeam) { ++ float[] afloat = ((IBeaconBeam) block).getColor().getTextureDiffuseColors(); + +- if (beaconblockentity.checkingBeamSections.size() <= 1) { +- beaconblockentity_beaconbeamsection = new BeaconBlockEntity.BeaconBeamSection(afloat); +- beaconblockentity.checkingBeamSections.add(beaconblockentity_beaconbeamsection); +- } else if (beaconblockentity_beaconbeamsection != null) { +- if (Arrays.equals(afloat, beaconblockentity_beaconbeamsection.color)) { +- beaconblockentity_beaconbeamsection.increaseHeight(); ++ if (blockEntity.checkingBeamSections.size() <= 1) { ++ tileentitybeacon_beaconcolortracker = new BeaconBlockEntity.BeaconBeamSection(afloat); ++ blockEntity.checkingBeamSections.add(tileentitybeacon_beaconcolortracker); ++ } else if (tileentitybeacon_beaconcolortracker != null) { ++ if (Arrays.equals(afloat, tileentitybeacon_beaconcolortracker.color)) { ++ tileentitybeacon_beaconcolortracker.increaseHeight(); + } else { +- beaconblockentity_beaconbeamsection = new BeaconBlockEntity.BeaconBeamSection(new float[]{(beaconblockentity_beaconbeamsection.color[0] + afloat[0]) / 2.0F, (beaconblockentity_beaconbeamsection.color[1] + afloat[1]) / 2.0F, (beaconblockentity_beaconbeamsection.color[2] + afloat[2]) / 2.0F}); +- beaconblockentity.checkingBeamSections.add(beaconblockentity_beaconbeamsection); ++ tileentitybeacon_beaconcolortracker = new BeaconBlockEntity.BeaconBeamSection(new float[]{(tileentitybeacon_beaconcolortracker.color[0] + afloat[0]) / 2.0F, (tileentitybeacon_beaconcolortracker.color[1] + afloat[1]) / 2.0F, (tileentitybeacon_beaconcolortracker.color[2] + afloat[2]) / 2.0F}); ++ blockEntity.checkingBeamSections.add(tileentitybeacon_beaconcolortracker); + } + } + } else { +- if (beaconblockentity_beaconbeamsection == null || blockstate1.getLightBlock(level, blockpos1) >= 15 && !blockstate1.is(Blocks.BEDROCK)) { +- beaconblockentity.checkingBeamSections.clear(); +- beaconblockentity.lastCheckY = l; ++ if (tileentitybeacon_beaconcolortracker == null || iblockdata1.getLightBlock(level, blockposition1) >= 15 && !iblockdata1.is(Blocks.BEDROCK)) { ++ blockEntity.checkingBeamSections.clear(); ++ blockEntity.lastCheckY = l; + break; + } + +- beaconblockentity_beaconbeamsection.increaseHeight(); ++ tileentitybeacon_beaconcolortracker.increaseHeight(); + } + +- blockpos1 = blockpos1.above(); +- ++beaconblockentity.lastCheckY; ++ blockposition1 = blockposition1.above(); ++ ++blockEntity.lastCheckY; + } + +- i1 = beaconblockentity.levels; ++ i1 = blockEntity.levels; + if (level.getGameTime() % 80L == 0L) { +- if (!beaconblockentity.beamSections.isEmpty()) { +- beaconblockentity.levels = updateBase(level, i, j, k); ++ if (!blockEntity.beamSections.isEmpty()) { ++ blockEntity.levels = updateBase(level, i, j, k); + } + +- if (beaconblockentity.levels > 0 && !beaconblockentity.beamSections.isEmpty()) { +- applyEffects(level, blockpos, beaconblockentity.levels, beaconblockentity.primaryPower, beaconblockentity.secondaryPower); +- playSound(level, blockpos, SoundEvents.BEACON_AMBIENT); ++ if (blockEntity.levels > 0 && !blockEntity.beamSections.isEmpty()) { ++ applyEffects(level, pos, blockEntity.levels, blockEntity.primaryPower, blockEntity.secondaryPower); ++ playSound(level, pos, SoundEvents.BEACON_AMBIENT); + } + } + +- if (beaconblockentity.lastCheckY >= l) { +- beaconblockentity.lastCheckY = level.getMinBuildHeight() - 1; ++ if (blockEntity.lastCheckY >= l) { ++ blockEntity.lastCheckY = level.getMinBuildHeight() - 1; + boolean flag = i1 > 0; + +- beaconblockentity.beamSections = beaconblockentity.checkingBeamSections; ++ blockEntity.beamSections = blockEntity.checkingBeamSections; + if (!level.isClientSide) { +- boolean flag1 = beaconblockentity.levels > 0; ++ boolean flag1 = blockEntity.levels > 0; + + if (!flag && flag1) { +- playSound(level, blockpos, SoundEvents.BEACON_ACTIVATE); ++ playSound(level, pos, SoundEvents.BEACON_ACTIVATE); + Iterator iterator = level.getEntitiesOfClass(ServerPlayer.class, (new AABB((double) i, (double) j, (double) k, (double) i, (double) (j - 4), (double) k)).inflate(10.0D, 5.0D, 10.0D)).iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- CriteriaTriggers.CONSTRUCT_BEACON.trigger(serverplayer, beaconblockentity.levels); ++ CriteriaTriggers.CONSTRUCT_BEACON.trigger(entityplayer, blockEntity.levels); + } + } else if (flag && !flag1) { +- playSound(level, blockpos, SoundEvents.BEACON_DEACTIVATE); ++ playSound(level, pos, SoundEvents.BEACON_DEACTIVATE); + } + } + } + + } + +- private static int updateBase(Level level, int i, int j, int k) { ++ private static int updateBase(Level level, int x, int y, int z) { + int l = 0; + + for (int i1 = 1; i1 <= 4; l = i1++) { +- int j1 = j - i1; ++ int j1 = y - i1; + + if (j1 < level.getMinBuildHeight()) { + break; +@@ -225,8 +235,8 @@ + + boolean flag = true; + +- for (int k1 = i - i1; k1 <= i + i1 && flag; ++k1) { +- for (int l1 = k - i1; l1 <= k + i1; ++l1) { ++ for (int k1 = x - i1; k1 <= x + i1 && flag; ++k1) { ++ for (int l1 = z - i1; l1 <= z + i1; ++l1) { + if (!level.getBlockState(new BlockPos(k1, j1, l1)).is(BlockTags.BEACON_BASE_BLOCKS)) { + flag = false; + break; +@@ -243,146 +253,176 @@ + } + + @Override +- @Override + public void setRemoved() { + playSound(this.level, this.worldPosition, SoundEvents.BEACON_DEACTIVATE); + super.setRemoved(); + } + +- private static void applyEffects(Level level, BlockPos blockpos, int i, @Nullable MobEffect mobeffect, @Nullable MobEffect mobeffect1) { +- if (!level.isClientSide && mobeffect != null) { +- double d0 = (double) (i * 10 + 10); ++ // CraftBukkit start - split into components ++ private static byte getAmplification(int i, @Nullable MobEffect mobeffectlist, @Nullable MobEffect mobeffectlist1) { ++ { + byte b0 = 0; + +- if (i >= 4 && mobeffect == mobeffect1) { ++ if (i >= 4 && mobeffectlist == mobeffectlist1) { + b0 = 1; + } + ++ return b0; ++ } ++ } ++ ++ private static int getLevel(int i) { ++ { + int j = (9 + i * 2) * 20; +- AABB aabb = (new AABB(blockpos)).inflate(d0).expandTowards(0.0D, (double) level.getHeight(), 0.0D); +- List list = level.getEntitiesOfClass(Player.class, aabb); ++ return j; ++ } ++ } ++ ++ public static List getHumansInRange(Level world, BlockPos blockposition, int i) { ++ { ++ double d0 = (double) (i * 10 + 10); ++ ++ AABB axisalignedbb = (new AABB(blockposition)).inflate(d0).expandTowards(0.0D, (double) world.getHeight(), 0.0D); ++ List list = world.getEntitiesOfClass(Player.class, axisalignedbb); ++ ++ return list; ++ } ++ } ++ ++ private static void applyEffect(List list, MobEffect mobeffectlist, int j, int b0) { ++ { + Iterator iterator = list.iterator(); + +- Player player; ++ Player entityhuman; + + while (iterator.hasNext()) { +- player = (Player) iterator.next(); +- player.addEffect(new MobEffectInstance(mobeffect, j, b0, true, true)); ++ entityhuman = (Player) iterator.next(); ++ entityhuman.addEffect(new MobEffectInstance(mobeffectlist, j, b0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); + } ++ } ++ } + +- if (i >= 4 && mobeffect != mobeffect1 && mobeffect1 != null) { +- iterator = list.iterator(); +- +- while (iterator.hasNext()) { +- player = (Player) iterator.next(); +- player.addEffect(new MobEffectInstance(mobeffect1, j, 0, true, true)); +- } ++ private static boolean hasSecondaryEffect(int i, @Nullable MobEffect mobeffectlist, @Nullable MobEffect mobeffectlist1) { ++ { ++ if (i >= 4 && mobeffectlist != mobeffectlist1 && mobeffectlist1 != null) { ++ return true; + } + ++ return false; + } + } + +- public static void playSound(Level level, BlockPos blockpos, SoundEvent soundevent) { +- level.playSound((Player) null, blockpos, soundevent, SoundSource.BLOCKS, 1.0F, 1.0F); ++ private static void applyEffects(Level level, BlockPos pos, int levels, @Nullable MobEffect primary, @Nullable MobEffect secondary) { ++ if (!level.isClientSide && primary != null) { ++ double d0 = (double) (levels * 10 + 10); ++ byte b0 = getAmplification(levels, primary, secondary); ++ ++ int j = getLevel(levels); ++ List list = getHumansInRange(level, pos, levels); ++ ++ applyEffect(list, primary, j, b0); ++ ++ if (hasSecondaryEffect(levels, primary, secondary)) { ++ applyEffect(list, secondary, j, 0); ++ } ++ } ++ + } ++ // CraftBukkit end + ++ public static void playSound(Level level, BlockPos pos, SoundEvent sound) { ++ level.playSound((Player) null, pos, sound, SoundSource.BLOCKS, 1.0F, 1.0F); ++ } ++ + public List getBeamSections() { + return (List) (this.levels == 0 ? ImmutableList.of() : this.beamSections); + } + + @Override +- @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + @Override +- @Override + public CompoundTag getUpdateTag() { + return this.saveWithoutMetadata(); + } + +- private static void storeEffect(CompoundTag compoundtag, String s, @Nullable MobEffect mobeffect) { +- if (mobeffect != null) { +- ResourceLocation resourcelocation = BuiltInRegistries.MOB_EFFECT.getKey(mobeffect); ++ private static void storeEffect(CompoundTag nbttagcompound, String s, @Nullable MobEffect mobeffectlist) { ++ if (mobeffectlist != null) { ++ ResourceLocation minecraftkey = BuiltInRegistries.MOB_EFFECT.getKey(mobeffectlist); + +- if (resourcelocation != null) { +- compoundtag.putString(s, resourcelocation.toString()); ++ if (minecraftkey != null) { ++ nbttagcompound.putString(s, minecraftkey.toString()); + } + } + + } + + @Nullable +- private static MobEffect loadEffect(CompoundTag compoundtag, String s) { +- if (compoundtag.contains(s, 8)) { +- ResourceLocation resourcelocation = ResourceLocation.tryParse(compoundtag.getString(s)); ++ private static MobEffect loadEffect(CompoundTag nbttagcompound, String s) { ++ if (nbttagcompound.contains(s, 8)) { ++ ResourceLocation minecraftkey = ResourceLocation.tryParse(nbttagcompound.getString(s)); + +- return filterEffect((MobEffect) BuiltInRegistries.MOB_EFFECT.get(resourcelocation)); ++ return (MobEffect) BuiltInRegistries.MOB_EFFECT.get(minecraftkey); // CraftBukkit - persist manually set non-default beacon effects (SPIGOT-3598) + } else { + return null; + } + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); +- this.primaryPower = loadEffect(compoundtag, "primary_effect"); +- this.secondaryPower = loadEffect(compoundtag, "secondary_effect"); +- if (compoundtag.contains("CustomName", 8)) { +- this.name = Component.Serializer.fromJson(compoundtag.getString("CustomName")); ++ public void load(CompoundTag tag) { ++ super.load(tag); ++ this.primaryPower = loadEffect(tag, "primary_effect"); ++ this.secondaryPower = loadEffect(tag, "secondary_effect"); ++ this.levels = tag.getInt("Levels"); // CraftBukkit - SPIGOT-5053, use where available ++ if (tag.contains("CustomName", 8)) { ++ this.name = Component.Serializer.fromJson(tag.getString("CustomName")); + } + +- this.lockKey = LockCode.fromTag(compoundtag); ++ this.lockKey = LockCode.fromTag(tag); + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); +- storeEffect(compoundtag, "primary_effect", this.primaryPower); +- storeEffect(compoundtag, "secondary_effect", this.secondaryPower); +- compoundtag.putInt("Levels", this.levels); ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); ++ storeEffect(tag, "primary_effect", this.primaryPower); ++ storeEffect(tag, "secondary_effect", this.secondaryPower); ++ tag.putInt("Levels", this.levels); + if (this.name != null) { +- compoundtag.putString("CustomName", Component.Serializer.toJson(this.name)); ++ tag.putString("CustomName", Component.Serializer.toJson(this.name)); + } + +- this.lockKey.addToTag(compoundtag); ++ this.lockKey.addToTag(tag); + } + +- public void setCustomName(@Nullable Component component) { +- this.name = component; ++ public void setCustomName(@Nullable Component name) { ++ this.name = name; + } + + @Nullable + @Override +- @Override + public Component getCustomName() { + return this.name; + } + + @Nullable + @Override +- @Override +- public AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) { +- return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName()) ? new BeaconMenu(i, inventory, this.dataAccess, ContainerLevelAccess.create(this.level, this.getBlockPos())) : null; ++ public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { ++ return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName()) ? new BeaconMenu(containerId, playerInventory, this.dataAccess, ContainerLevelAccess.create(this.level, this.getBlockPos())) : null; + } + + @Override +- @Override + public Component getDisplayName() { + return this.getName(); + } + + @Override +- @Override + public Component getName() { + return this.name != null ? this.name : BeaconBlockEntity.DEFAULT_NAME; + } + + @Override +- @Override + public void setLevel(Level level) { + super.setLevel(level); + this.lastCheckY = level.getMinBuildHeight() - 1; +@@ -393,8 +433,8 @@ + final float[] color; + private int height; + +- public BeaconBeamSection(float[] afloat) { +- this.color = afloat; ++ public BeaconBeamSection(float[] color) { ++ this.color = color; + this.height = 1; + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java.patch new file mode 100644 index 0000000000..7f5f382071 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java.patch @@ -0,0 +1,512 @@ +--- a/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java +@@ -24,7 +24,7 @@ + import net.minecraft.world.level.block.BeehiveBlock; + import net.minecraft.world.level.block.CampfireBlock; + import net.minecraft.world.level.block.FireBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + + public class BeehiveBlockEntity extends BlockEntity { +@@ -42,17 +42,17 @@ + public static final int MIN_OCCUPATION_TICKS_NECTARLESS = 600; + private final List stored = Lists.newArrayList(); + @Nullable +- private BlockPos savedFlowerPos; ++ public BlockPos savedFlowerPos; ++ public int maxBees = 3; // CraftBukkit - allow setting max amount of bees a hive can hold + +- public BeehiveBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.BEEHIVE, blockpos, blockstate); ++ public BeehiveBlockEntity(BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.BEEHIVE, pos, blockState); + } + + @Override +- @Override + public void setChanged() { + if (this.isFireNearby()) { +- this.emptyAllLivingFromHive((Player) null, this.level.getBlockState(this.getBlockPos()), BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY); ++ this.emptyAllLivingFromHive((Player) null, this.level.getBlockState(this.getBlockPos()), BeehiveBlockEntity.ReleaseStatus.EMERGENCY); + } + + super.setChanged(); +@@ -64,15 +64,15 @@ + } else { + Iterator iterator = BlockPos.betweenClosed(this.worldPosition.offset(-1, -1, -1), this.worldPosition.offset(1, 1, 1)).iterator(); + +- BlockPos blockpos; ++ BlockPos blockposition; + + do { + if (!iterator.hasNext()) { + return false; + } + +- blockpos = (BlockPos) iterator.next(); +- } while (!(this.level.getBlockState(blockpos).getBlock() instanceof FireBlock)); ++ blockposition = (BlockPos) iterator.next(); ++ } while (!(this.level.getBlockState(blockposition).getBlock() instanceof FireBlock)); + + return true; + } +@@ -83,11 +83,11 @@ + } + + public boolean isFull() { +- return this.stored.size() == 3; ++ return this.stored.size() == this.maxBees; // CraftBukkit + } + +- public void emptyAllLivingFromHive(@Nullable Player player, BlockState blockstate, BeehiveBlockEntity.BeeReleaseStatus beehiveblockentity_beereleasestatus) { +- List list = this.releaseAllOccupants(blockstate, beehiveblockentity_beereleasestatus); ++ public void emptyAllLivingFromHive(@Nullable Player player, IBlockData state, BeehiveBlockEntity.ReleaseStatus releaseStatus) { ++ List list = this.releaseAllOccupants(state, releaseStatus); + + if (player != null) { + Iterator iterator = list.iterator(); +@@ -96,13 +96,13 @@ + Entity entity = (Entity) iterator.next(); + + if (entity instanceof Bee) { +- Bee bee = (Bee) entity; ++ Bee entitybee = (Bee) entity; + + if (player.position().distanceToSqr(entity.position()) <= 16.0D) { + if (!this.isSedated()) { +- bee.setTarget(player); ++ entitybee.setTarget(player, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit + } else { +- bee.setStayOutOfHiveCountdown(400); ++ entitybee.setStayOutOfHiveCountdown(400); + } + } + } +@@ -111,11 +111,17 @@ + + } + +- private List releaseAllOccupants(BlockState blockstate, BeehiveBlockEntity.BeeReleaseStatus beehiveblockentity_beereleasestatus) { ++ private List releaseAllOccupants(IBlockData state, BeehiveBlockEntity.ReleaseStatus releaseStatus) { ++ // CraftBukkit start - This allows us to bypass the night/rain/emergency check ++ return releaseBees(state, releaseStatus, false); ++ } ++ ++ public List releaseBees(IBlockData iblockdata, BeehiveBlockEntity.ReleaseStatus tileentitybeehive_releasestatus, boolean force) { + List list = Lists.newArrayList(); + +- this.stored.removeIf((beehiveblockentity_beedata) -> { +- return releaseOccupant(this.level, this.worldPosition, blockstate, beehiveblockentity_beedata, list, beehiveblockentity_beereleasestatus, this.savedFlowerPos); ++ this.stored.removeIf((tileentitybeehive_hivebee) -> { ++ return releaseBee(this.level, this.worldPosition, iblockdata, tileentitybeehive_hivebee, list, tileentitybeehive_releasestatus, this.savedFlowerPos, force); ++ // CraftBukkit end + }); + if (!list.isEmpty()) { + super.setChanged(); +@@ -124,8 +130,8 @@ + return list; + } + +- public void addOccupant(Entity entity, boolean flag) { +- this.addOccupantWithPresetTicks(entity, flag, 0); ++ public void addOccupant(Entity occupant, boolean hasNectar) { ++ this.addOccupantWithPresetTicks(occupant, hasNectar, 0); + } + + @VisibleForDebug +@@ -133,8 +139,8 @@ + return this.stored.size(); + } + +- public static int getHoneyLevel(BlockState blockstate) { +- return (Integer) blockstate.getValue(BeehiveBlock.HONEY_LEVEL); ++ public static int getHoneyLevel(IBlockData state) { ++ return (Integer) state.getValue(BeehiveBlock.HONEY_LEVEL); + } + + @VisibleForDebug +@@ -142,55 +148,73 @@ + return CampfireBlock.isSmokeyPos(this.level, this.getBlockPos()); + } + +- public void addOccupantWithPresetTicks(Entity entity, boolean flag, int i) { +- if (this.stored.size() < 3) { +- entity.stopRiding(); +- entity.ejectPassengers(); +- CompoundTag compoundtag = new CompoundTag(); ++ public void addOccupantWithPresetTicks(Entity occupant, boolean hasNectar, int ticksInHive) { ++ if (this.stored.size() < this.maxBees) { // CraftBukkit ++ // CraftBukkit start ++ if (this.level != null) { ++ org.bukkit.event.entity.EntityEnterBlockEvent event = new org.bukkit.event.entity.EntityEnterBlockEvent(occupant.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, getBlockPos())); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ if (occupant instanceof Bee) { ++ ((Bee) occupant).setStayOutOfHiveCountdown(400); ++ } ++ return; ++ } ++ } ++ // CraftBukkit end ++ occupant.stopRiding(); ++ occupant.ejectPassengers(); ++ CompoundTag nbttagcompound = new CompoundTag(); + +- entity.save(compoundtag); +- this.storeBee(compoundtag, i, flag); ++ occupant.save(nbttagcompound); ++ this.storeBee(nbttagcompound, ticksInHive, hasNectar); + if (this.level != null) { +- if (entity instanceof Bee) { +- Bee bee = (Bee) entity; ++ if (occupant instanceof Bee) { ++ Bee entitybee = (Bee) occupant; + +- if (bee.hasSavedFlowerPos() && (!this.hasSavedFlowerPos() || this.level.random.nextBoolean())) { +- this.savedFlowerPos = bee.getSavedFlowerPos(); ++ if (entitybee.hasSavedFlowerPos() && (!this.hasSavedFlowerPos() || this.level.random.nextBoolean())) { ++ this.savedFlowerPos = entitybee.getSavedFlowerPos(); + } + } + +- BlockPos blockpos = this.getBlockPos(); ++ BlockPos blockposition = this.getBlockPos(); + +- this.level.playSound((Player) null, (double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), SoundEvents.BEEHIVE_ENTER, SoundSource.BLOCKS, 1.0F, 1.0F); +- this.level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(entity, this.getBlockState())); ++ this.level.playSound((Player) null, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), SoundEvents.BEEHIVE_ENTER, SoundSource.BLOCKS, 1.0F, 1.0F); ++ this.level.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(occupant, this.getBlockState())); + } + +- entity.discard(); ++ occupant.discard(); + super.setChanged(); + } + } + +- public void storeBee(CompoundTag compoundtag, int i, boolean flag) { +- this.stored.add(new BeehiveBlockEntity.BeeData(compoundtag, i, flag ? 2400 : 600)); ++ public void storeBee(CompoundTag entityData, int ticksInHive, boolean hasNectar) { ++ this.stored.add(new BeehiveBlockEntity.BeeData(entityData, ticksInHive, hasNectar ? 2400 : 600)); + } + +- private static boolean releaseOccupant(Level level, BlockPos blockpos, BlockState blockstate, BeehiveBlockEntity.BeeData beehiveblockentity_beedata, @Nullable List list, BeehiveBlockEntity.BeeReleaseStatus beehiveblockentity_beereleasestatus, @Nullable BlockPos blockpos1) { +- if ((level.isNight() || level.isRaining()) && beehiveblockentity_beereleasestatus != BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY) { ++ private static boolean releaseOccupant(Level level, BlockPos pos, IBlockData state, BeehiveBlockEntity.BeeData data, @Nullable List storedInHives, BeehiveBlockEntity.ReleaseStatus releaseStatus, @Nullable BlockPos savedFlowerPos) { ++ // CraftBukkit start - This allows us to bypass the night/rain/emergency check ++ return releaseBee(level, pos, state, data, storedInHives, releaseStatus, savedFlowerPos, false); ++ } ++ ++ private static boolean releaseBee(Level world, BlockPos blockposition, IBlockData iblockdata, BeehiveBlockEntity.BeeData tileentitybeehive_hivebee, @Nullable List list, BeehiveBlockEntity.ReleaseStatus tileentitybeehive_releasestatus, @Nullable BlockPos blockposition1, boolean force) { ++ if (!force && (world.isNight() || world.isRaining()) && tileentitybeehive_releasestatus != BeehiveBlockEntity.ReleaseStatus.EMERGENCY) { ++ // CraftBukkit end + return false; + } else { +- CompoundTag compoundtag = beehiveblockentity_beedata.entityData.copy(); ++ CompoundTag nbttagcompound = tileentitybeehive_hivebee.entityData.copy(); + +- removeIgnoredBeeTags(compoundtag); +- compoundtag.put("HivePos", NbtUtils.writeBlockPos(blockpos)); +- compoundtag.putBoolean("NoGravity", true); +- Direction direction = (Direction) blockstate.getValue(BeehiveBlock.FACING); +- BlockPos blockpos2 = blockpos.relative(direction); +- boolean flag = !level.getBlockState(blockpos2).getCollisionShape(level, blockpos2).isEmpty(); ++ removeIgnoredBeeTags(nbttagcompound); ++ nbttagcompound.put("HivePos", NbtUtils.writeBlockPos(blockposition)); ++ nbttagcompound.putBoolean("NoGravity", true); ++ Direction enumdirection = (Direction) iblockdata.getValue(BeehiveBlock.FACING); ++ BlockPos blockposition2 = blockposition.relative(enumdirection); ++ boolean flag = !world.getBlockState(blockposition2).getCollisionShape(world, blockposition2).isEmpty(); + +- if (flag && beehiveblockentity_beereleasestatus != BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY) { ++ if (flag && tileentitybeehive_releasestatus != BeehiveBlockEntity.ReleaseStatus.EMERGENCY) { + return false; + } else { +- Entity entity = EntityType.loadEntityRecursive(compoundtag, level, (entity1) -> { ++ Entity entity = EntityType.loadEntityRecursive(nbttagcompound, world, (entity1) -> { + return entity1; + }); + +@@ -198,49 +222,63 @@ + if (!entity.getType().is(EntityTypeTags.BEEHIVE_INHABITORS)) { + return false; + } else { ++ // CraftBukkit start + if (entity instanceof Bee) { +- Bee bee = (Bee) entity; ++ float f = entity.getBbWidth(); ++ double d0 = flag ? 0.0D : 0.55D + (double) (f / 2.0F); ++ double d1 = (double) blockposition.getX() + 0.5D + d0 * (double) enumdirection.getStepX(); ++ double d2 = (double) blockposition.getY() + 0.5D - (double) (entity.getBbHeight() / 2.0F); ++ double d3 = (double) blockposition.getZ() + 0.5D + d0 * (double) enumdirection.getStepZ(); + +- if (blockpos1 != null && !bee.hasSavedFlowerPos() && level.random.nextFloat() < 0.9F) { +- bee.setSavedFlowerPos(blockpos1); ++ entity.moveTo(d1, d2, d3, entity.getYRot(), entity.getXRot()); ++ } ++ if (!world.addFreshEntity(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BEEHIVE)) return false; // CraftBukkit - SpawnReason, moved from below ++ // CraftBukkit end ++ if (entity instanceof Bee) { ++ Bee entitybee = (Bee) entity; ++ ++ if (blockposition1 != null && !entitybee.hasSavedFlowerPos() && world.random.nextFloat() < 0.9F) { ++ entitybee.setSavedFlowerPos(blockposition1); + } + +- if (beehiveblockentity_beereleasestatus == BeehiveBlockEntity.BeeReleaseStatus.HONEY_DELIVERED) { +- bee.dropOffNectar(); +- if (blockstate.is(BlockTags.BEEHIVES, (blockbehaviour_blockstatebase) -> { +- return blockbehaviour_blockstatebase.hasProperty(BeehiveBlock.HONEY_LEVEL); ++ if (tileentitybeehive_releasestatus == BeehiveBlockEntity.ReleaseStatus.HONEY_DELIVERED) { ++ entitybee.dropOffNectar(); ++ if (iblockdata.is(BlockTags.BEEHIVES, (blockbase_blockdata) -> { ++ return blockbase_blockdata.hasProperty(BeehiveBlock.HONEY_LEVEL); + })) { +- int i = getHoneyLevel(blockstate); ++ int i = getHoneyLevel(iblockdata); + + if (i < 5) { +- int j = level.random.nextInt(100) == 0 ? 2 : 1; ++ int j = world.random.nextInt(100) == 0 ? 2 : 1; + + if (i + j > 5) { + --j; + } + +- level.setBlockAndUpdate(blockpos, (BlockState) blockstate.setValue(BeehiveBlock.HONEY_LEVEL, i + j)); ++ world.setBlockAndUpdate(blockposition, (IBlockData) iblockdata.setValue(BeehiveBlock.HONEY_LEVEL, i + j)); + } + } + } + +- setBeeReleaseData(beehiveblockentity_beedata.ticksInHive, bee); ++ setBeeReleaseData(tileentitybeehive_hivebee.ticksInHive, entitybee); + if (list != null) { +- list.add(bee); ++ list.add(entitybee); + } + ++ /* // CraftBukkit start + float f = entity.getBbWidth(); + double d0 = flag ? 0.0D : 0.55D + (double) (f / 2.0F); +- double d1 = (double) blockpos.getX() + 0.5D + d0 * (double) direction.getStepX(); +- double d2 = (double) blockpos.getY() + 0.5D - (double) (entity.getBbHeight() / 2.0F); +- double d3 = (double) blockpos.getZ() + 0.5D + d0 * (double) direction.getStepZ(); ++ double d1 = (double) blockposition.getX() + 0.5D + d0 * (double) enumdirection.getStepX(); ++ double d2 = (double) blockposition.getY() + 0.5D - (double) (entity.getBbHeight() / 2.0F); ++ double d3 = (double) blockposition.getZ() + 0.5D + d0 * (double) enumdirection.getStepZ(); + + entity.moveTo(d1, d2, d3, entity.getYRot(), entity.getXRot()); ++ */ // CraftBukkit end + } + +- level.playSound((Player) null, blockpos, SoundEvents.BEEHIVE_EXIT, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(entity, level.getBlockState(blockpos))); +- return level.addFreshEntity(entity); ++ world.playSound((Player) null, blockposition, SoundEvents.BEEHIVE_EXIT, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entity, world.getBlockState(blockposition))); ++ return true; // return this.world.addFreshEntity(entity); // CraftBukkit - moved up + } + } else { + return false; +@@ -249,126 +287,134 @@ + } + } + +- static void removeIgnoredBeeTags(CompoundTag compoundtag) { ++ static void removeIgnoredBeeTags(CompoundTag tag) { + Iterator iterator = BeehiveBlockEntity.IGNORED_BEE_TAGS.iterator(); + + while (iterator.hasNext()) { + String s = (String) iterator.next(); + +- compoundtag.remove(s); ++ tag.remove(s); + } + + } + +- private static void setBeeReleaseData(int i, Bee bee) { ++ private static void setBeeReleaseData(int timeInHive, Bee bee) { + int j = bee.getAge(); + + if (j < 0) { +- bee.setAge(Math.min(0, j + i)); ++ bee.setAge(Math.min(0, j + timeInHive)); + } else if (j > 0) { +- bee.setAge(Math.max(0, j - i)); ++ bee.setAge(Math.max(0, j - timeInHive)); + } + +- bee.setInLoveTime(Math.max(0, bee.getInLoveTime() - i)); ++ bee.setInLoveTime(Math.max(0, bee.getInLoveTime() - timeInHive)); + } + + private boolean hasSavedFlowerPos() { + return this.savedFlowerPos != null; + } + +- private static void tickOccupants(Level level, BlockPos blockpos, BlockState blockstate, List list, @Nullable BlockPos blockpos1) { ++ private static void tickOccupants(Level level, BlockPos pos, IBlockData state, List data, @Nullable BlockPos savedFlowerPos) { + boolean flag = false; + +- BeehiveBlockEntity.BeeData beehiveblockentity_beedata; ++ BeehiveBlockEntity.BeeData tileentitybeehive_hivebee; + +- for (Iterator iterator = list.iterator(); iterator.hasNext(); ++beehiveblockentity_beedata.ticksInHive) { +- beehiveblockentity_beedata = (BeehiveBlockEntity.BeeData) iterator.next(); +- if (beehiveblockentity_beedata.ticksInHive > beehiveblockentity_beedata.minOccupationTicks) { +- BeehiveBlockEntity.BeeReleaseStatus beehiveblockentity_beereleasestatus = beehiveblockentity_beedata.entityData.getBoolean("HasNectar") ? BeehiveBlockEntity.BeeReleaseStatus.HONEY_DELIVERED : BeehiveBlockEntity.BeeReleaseStatus.BEE_RELEASED; ++ for (Iterator iterator = data.iterator(); iterator.hasNext(); ++tileentitybeehive_hivebee.ticksInHive) { ++ tileentitybeehive_hivebee = (BeehiveBlockEntity.BeeData) iterator.next(); ++ if (tileentitybeehive_hivebee.ticksInHive > tileentitybeehive_hivebee.minOccupationTicks) { ++ BeehiveBlockEntity.ReleaseStatus tileentitybeehive_releasestatus = tileentitybeehive_hivebee.entityData.getBoolean("HasNectar") ? BeehiveBlockEntity.ReleaseStatus.HONEY_DELIVERED : BeehiveBlockEntity.ReleaseStatus.BEE_RELEASED; + +- if (releaseOccupant(level, blockpos, blockstate, beehiveblockentity_beedata, (List) null, beehiveblockentity_beereleasestatus, blockpos1)) { ++ if (releaseOccupant(level, pos, state, tileentitybeehive_hivebee, (List) null, tileentitybeehive_releasestatus, savedFlowerPos)) { + flag = true; + iterator.remove(); ++ // CraftBukkit start ++ } else { ++ tileentitybeehive_hivebee.ticksInHive = tileentitybeehive_hivebee.minOccupationTicks / 2; // Not strictly Vanilla behaviour in cases where bees cannot spawn but still reasonable ++ // CraftBukkit end + } + } + } + + if (flag) { +- setChanged(level, blockpos, blockstate); ++ setChanged(level, pos, state); + } + + } + +- public static void serverTick(Level level, BlockPos blockpos, BlockState blockstate, BeehiveBlockEntity beehiveblockentity) { +- tickOccupants(level, blockpos, blockstate, beehiveblockentity.stored, beehiveblockentity.savedFlowerPos); +- if (!beehiveblockentity.stored.isEmpty() && level.getRandom().nextDouble() < 0.005D) { +- double d0 = (double) blockpos.getX() + 0.5D; +- double d1 = (double) blockpos.getY(); +- double d2 = (double) blockpos.getZ() + 0.5D; ++ public static void serverTick(Level level, BlockPos pos, IBlockData state, BeehiveBlockEntity beehive) { ++ tickOccupants(level, pos, state, beehive.stored, beehive.savedFlowerPos); ++ if (!beehive.stored.isEmpty() && level.getRandom().nextDouble() < 0.005D) { ++ double d0 = (double) pos.getX() + 0.5D; ++ double d1 = (double) pos.getY(); ++ double d2 = (double) pos.getZ() + 0.5D; + + level.playSound((Player) null, d0, d1, d2, SoundEvents.BEEHIVE_WORK, SoundSource.BLOCKS, 1.0F, 1.0F); + } + +- DebugPackets.sendHiveInfo(level, blockpos, blockstate, beehiveblockentity); ++ DebugPackets.sendHiveInfo(level, pos, state, beehive); + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); ++ public void load(CompoundTag tag) { ++ super.load(tag); + this.stored.clear(); +- ListTag listtag = compoundtag.getList("Bees", 10); ++ ListTag nbttaglist = tag.getList("Bees", 10); + +- for (int i = 0; i < listtag.size(); ++i) { +- CompoundTag compoundtag1 = listtag.getCompound(i); +- BeehiveBlockEntity.BeeData beehiveblockentity_beedata = new BeehiveBlockEntity.BeeData(compoundtag1.getCompound("EntityData").copy(), compoundtag1.getInt("TicksInHive"), compoundtag1.getInt("MinOccupationTicks")); ++ for (int i = 0; i < nbttaglist.size(); ++i) { ++ CompoundTag nbttagcompound1 = nbttaglist.getCompound(i); ++ BeehiveBlockEntity.BeeData tileentitybeehive_hivebee = new BeehiveBlockEntity.BeeData(nbttagcompound1.getCompound("EntityData").copy(), nbttagcompound1.getInt("TicksInHive"), nbttagcompound1.getInt("MinOccupationTicks")); + +- this.stored.add(beehiveblockentity_beedata); ++ this.stored.add(tileentitybeehive_hivebee); + } + + this.savedFlowerPos = null; +- if (compoundtag.contains("FlowerPos")) { +- this.savedFlowerPos = NbtUtils.readBlockPos(compoundtag.getCompound("FlowerPos")); ++ if (tag.contains("FlowerPos")) { ++ this.savedFlowerPos = NbtUtils.readBlockPos(tag.getCompound("FlowerPos")); + } + ++ // CraftBukkit start ++ if (tag.contains("Bukkit.MaxEntities")) { ++ this.maxBees = tag.getInt("Bukkit.MaxEntities"); ++ } ++ // CraftBukkit end + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); +- compoundtag.put("Bees", this.writeBees()); ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); ++ tag.put("Bees", this.writeBees()); + if (this.hasSavedFlowerPos()) { +- compoundtag.put("FlowerPos", NbtUtils.writeBlockPos(this.savedFlowerPos)); ++ tag.put("FlowerPos", NbtUtils.writeBlockPos(this.savedFlowerPos)); + } ++ tag.putInt("Bukkit.MaxEntities", this.maxBees); // CraftBukkit + + } + + public ListTag writeBees() { +- ListTag listtag = new ListTag(); ++ ListTag nbttaglist = new ListTag(); + Iterator iterator = this.stored.iterator(); + + while (iterator.hasNext()) { +- BeehiveBlockEntity.BeeData beehiveblockentity_beedata = (BeehiveBlockEntity.BeeData) iterator.next(); +- CompoundTag compoundtag = beehiveblockentity_beedata.entityData.copy(); ++ BeehiveBlockEntity.BeeData tileentitybeehive_hivebee = (BeehiveBlockEntity.BeeData) iterator.next(); ++ CompoundTag nbttagcompound = tileentitybeehive_hivebee.entityData.copy(); + +- compoundtag.remove("UUID"); +- CompoundTag compoundtag1 = new CompoundTag(); ++ nbttagcompound.remove("UUID"); ++ CompoundTag nbttagcompound1 = new CompoundTag(); + +- compoundtag1.put("EntityData", compoundtag); +- compoundtag1.putInt("TicksInHive", beehiveblockentity_beedata.ticksInHive); +- compoundtag1.putInt("MinOccupationTicks", beehiveblockentity_beedata.minOccupationTicks); +- listtag.add(compoundtag1); ++ nbttagcompound1.put("EntityData", nbttagcompound); ++ nbttagcompound1.putInt("TicksInHive", tileentitybeehive_hivebee.ticksInHive); ++ nbttagcompound1.putInt("MinOccupationTicks", tileentitybeehive_hivebee.minOccupationTicks); ++ nbttaglist.add(nbttagcompound1); + } + +- return listtag; ++ return nbttaglist; + } + +- public static enum BeeReleaseStatus { ++ public static enum ReleaseStatus { + + HONEY_DELIVERED, BEE_RELEASED, EMERGENCY; + +- private BeeReleaseStatus() {} ++ private ReleaseStatus() {} + } + + private static class BeeData { +@@ -377,11 +423,11 @@ + int ticksInHive; + final int minOccupationTicks; + +- BeeData(CompoundTag compoundtag, int i, int j) { +- BeehiveBlockEntity.removeIgnoredBeeTags(compoundtag); +- this.entityData = compoundtag; +- this.ticksInHive = i; +- this.minOccupationTicks = j; ++ BeeData(CompoundTag entityData, int ticksInHive, int minOccupationTicks) { ++ BeehiveBlockEntity.removeIgnoredBeeTags(entityData); ++ this.entityData = entityData; ++ this.ticksInHive = ticksInHive; ++ this.minOccupationTicks = minOccupationTicks; + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BellBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BellBlockEntity.java.patch new file mode 100644 index 0000000000..0352cc9b1a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BellBlockEntity.java.patch @@ -0,0 +1,225 @@ +--- a/net/minecraft/world/level/block/entity/BellBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BellBlockEntity.java +@@ -16,7 +16,7 @@ + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.AABB; + import org.apache.commons.lang3.mutable.MutableInt; + +@@ -35,64 +35,63 @@ + public boolean shaking; + public Direction clickDirection; + private List nearbyEntities; +- private boolean resonating; +- private int resonationTicks; ++ public boolean resonating; ++ public int resonationTicks; + +- public BellBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.BELL, blockpos, blockstate); ++ public BellBlockEntity(BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.BELL, pos, blockState); + } + + @Override +- @Override +- public boolean triggerEvent(int i, int j) { +- if (i == 1) { ++ public boolean triggerEvent(int id, int type) { ++ if (id == 1) { + this.updateEntities(); + this.resonationTicks = 0; +- this.clickDirection = Direction.from3DDataValue(j); ++ this.clickDirection = Direction.from3DDataValue(type); + this.ticks = 0; + this.shaking = true; + return true; + } else { +- return super.triggerEvent(i, j); ++ return super.triggerEvent(id, type); + } + } + +- private static void tick(Level level, BlockPos blockpos, BlockState blockstate, BellBlockEntity bellblockentity, BellBlockEntity.ResonationEndAction bellblockentity_resonationendaction) { +- if (bellblockentity.shaking) { +- ++bellblockentity.ticks; ++ private static void tick(Level level, BlockPos pos, IBlockData state, BellBlockEntity blockEntity, BellBlockEntity.ResonationEndAction resonationEndAction) { ++ if (blockEntity.shaking) { ++ ++blockEntity.ticks; + } + +- if (bellblockentity.ticks >= 50) { +- bellblockentity.shaking = false; +- bellblockentity.ticks = 0; ++ if (blockEntity.ticks >= 50) { ++ blockEntity.shaking = false; ++ blockEntity.ticks = 0; + } + +- if (bellblockentity.ticks >= 5 && bellblockentity.resonationTicks == 0 && areRaidersNearby(blockpos, bellblockentity.nearbyEntities)) { +- bellblockentity.resonating = true; +- level.playSound((Player) null, blockpos, SoundEvents.BELL_RESONATE, SoundSource.BLOCKS, 1.0F, 1.0F); ++ if (blockEntity.ticks >= 5 && blockEntity.resonationTicks == 0 && areRaidersNearby(pos, blockEntity.nearbyEntities)) { ++ blockEntity.resonating = true; ++ level.playSound((Player) null, pos, SoundEvents.BELL_RESONATE, SoundSource.BLOCKS, 1.0F, 1.0F); + } + +- if (bellblockentity.resonating) { +- if (bellblockentity.resonationTicks < 40) { +- ++bellblockentity.resonationTicks; ++ if (blockEntity.resonating) { ++ if (blockEntity.resonationTicks < 40) { ++ ++blockEntity.resonationTicks; + } else { +- bellblockentity_resonationendaction.run(level, blockpos, bellblockentity.nearbyEntities); +- bellblockentity.resonating = false; ++ resonationEndAction.run(level, pos, blockEntity.nearbyEntities); ++ blockEntity.resonating = false; + } + } + + } + +- public static void clientTick(Level level, BlockPos blockpos, BlockState blockstate, BellBlockEntity bellblockentity) { +- tick(level, blockpos, blockstate, bellblockentity, BellBlockEntity::showBellParticles); ++ public static void clientTick(Level level, BlockPos pos, IBlockData state, BellBlockEntity blockEntity) { ++ tick(level, pos, state, blockEntity, BellBlockEntity::showBellParticles); + } + +- public static void serverTick(Level level, BlockPos blockpos, BlockState blockstate, BellBlockEntity bellblockentity) { +- tick(level, blockpos, blockstate, bellblockentity, BellBlockEntity::makeRaidersGlow); ++ public static void serverTick(Level level, BlockPos pos, IBlockData state, BellBlockEntity blockEntity) { ++ tick(level, pos, state, blockEntity, BellBlockEntity::makeRaidersGlow); + } + + public void onHit(Direction direction) { +- BlockPos blockpos = this.getBlockPos(); ++ BlockPos blockposition = this.getBlockPos(); + + this.clickDirection = direction; + if (this.shaking) { +@@ -101,68 +100,72 @@ + this.shaking = true; + } + +- this.level.blockEvent(blockpos, this.getBlockState().getBlock(), 1, direction.get3DDataValue()); ++ this.level.blockEvent(blockposition, this.getBlockState().getBlock(), 1, direction.get3DDataValue()); + } + + private void updateEntities() { +- BlockPos blockpos = this.getBlockPos(); ++ BlockPos blockposition = this.getBlockPos(); + + if (this.level.getGameTime() > this.lastRingTimestamp + 60L || this.nearbyEntities == null) { + this.lastRingTimestamp = this.level.getGameTime(); +- AABB aabb = (new AABB(blockpos)).inflate(48.0D); ++ AABB axisalignedbb = (new AABB(blockposition)).inflate(48.0D); + +- this.nearbyEntities = this.level.getEntitiesOfClass(LivingEntity.class, aabb); ++ this.nearbyEntities = this.level.getEntitiesOfClass(LivingEntity.class, axisalignedbb); + } + + if (!this.level.isClientSide) { + Iterator iterator = this.nearbyEntities.iterator(); + + while (iterator.hasNext()) { +- LivingEntity livingentity = (LivingEntity) iterator.next(); ++ LivingEntity entityliving = (LivingEntity) iterator.next(); + +- if (livingentity.isAlive() && !livingentity.isRemoved() && blockpos.closerToCenterThan(livingentity.position(), 32.0D)) { +- livingentity.getBrain().setMemory(MemoryModuleType.HEARD_BELL_TIME, (Object) this.level.getGameTime()); ++ if (entityliving.isAlive() && !entityliving.isRemoved() && blockposition.closerToCenterThan(entityliving.position(), 32.0D)) { ++ entityliving.getBrain().setMemory(MemoryModuleType.HEARD_BELL_TIME, this.level.getGameTime()); // CraftBukkit - decompile error + } + } + } + + } + +- private static boolean areRaidersNearby(BlockPos blockpos, List list) { +- Iterator iterator = list.iterator(); ++ private static boolean areRaidersNearby(BlockPos pos, List raiders) { ++ Iterator iterator = raiders.iterator(); + +- LivingEntity livingentity; ++ LivingEntity entityliving; + + do { + if (!iterator.hasNext()) { + return false; + } + +- livingentity = (LivingEntity) iterator.next(); +- } while (!livingentity.isAlive() || livingentity.isRemoved() || !blockpos.closerToCenterThan(livingentity.position(), 32.0D) || !livingentity.getType().is(EntityTypeTags.RAIDERS)); ++ entityliving = (LivingEntity) iterator.next(); ++ } while (!entityliving.isAlive() || entityliving.isRemoved() || !pos.closerToCenterThan(entityliving.position(), 32.0D) || !entityliving.getType().is(EntityTypeTags.RAIDERS)); + + return true; + } + +- private static void makeRaidersGlow(Level level, BlockPos blockpos, List list) { +- list.stream().filter((livingentity) -> { +- return isRaiderWithinRange(blockpos, livingentity); +- }).forEach(BellBlockEntity::glow); ++ private static void makeRaidersGlow(Level level, BlockPos pos, List raiders) { ++ List entities = // CraftBukkit ++ raiders.stream().filter((entityliving) -> { ++ return isRaiderWithinRange(pos, entityliving); ++ }).map((entity) -> (org.bukkit.entity.LivingEntity) entity.getBukkitEntity()).collect(java.util.stream.Collectors.toCollection(java.util.ArrayList::new)); // CraftBukkit ++ ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBellResonateEvent(level, pos, entities).forEach(BellBlockEntity::glow); ++ // CraftBukkit end + } + +- private static void showBellParticles(Level level, BlockPos blockpos, List list) { ++ private static void showBellParticles(Level level, BlockPos pos, List raiders) { + MutableInt mutableint = new MutableInt(16700985); +- int i = (int) list.stream().filter((livingentity) -> { +- return blockpos.closerToCenterThan(livingentity.position(), 48.0D); ++ int i = (int) raiders.stream().filter((entityliving) -> { ++ return pos.closerToCenterThan(entityliving.position(), 48.0D); + }).count(); + +- list.stream().filter((livingentity) -> { +- return isRaiderWithinRange(blockpos, livingentity); +- }).forEach((livingentity) -> { ++ raiders.stream().filter((entityliving) -> { ++ return isRaiderWithinRange(pos, entityliving); ++ }).forEach((entityliving) -> { + float f = 1.0F; +- double d0 = Math.sqrt((livingentity.getX() - (double) blockpos.getX()) * (livingentity.getX() - (double) blockpos.getX()) + (livingentity.getZ() - (double) blockpos.getZ()) * (livingentity.getZ() - (double) blockpos.getZ())); +- double d1 = (double) ((float) blockpos.getX() + 0.5F) + 1.0D / d0 * (livingentity.getX() - (double) blockpos.getX()); +- double d2 = (double) ((float) blockpos.getZ() + 0.5F) + 1.0D / d0 * (livingentity.getZ() - (double) blockpos.getZ()); ++ double d0 = Math.sqrt((entityliving.getX() - (double) pos.getX()) * (entityliving.getX() - (double) pos.getX()) + (entityliving.getZ() - (double) pos.getZ()) * (entityliving.getZ() - (double) pos.getZ())); ++ double d1 = (double) ((float) pos.getX() + 0.5F) + 1.0D / d0 * (entityliving.getX() - (double) pos.getX()); ++ double d2 = (double) ((float) pos.getZ() + 0.5F) + 1.0D / d0 * (entityliving.getZ() - (double) pos.getZ()); + int j = Mth.clamp((i - 21) / -2, 3, 15); + + for (int k = 0; k < j; ++k) { +@@ -171,18 +174,18 @@ + double d4 = (double) FastColor.ARGB32.green(l) / 255.0D; + double d5 = (double) FastColor.ARGB32.blue(l) / 255.0D; + +- level.addParticle(ParticleTypes.ENTITY_EFFECT, d1, (double) ((float) blockpos.getY() + 0.5F), d2, d3, d4, d5); ++ level.addParticle(ParticleTypes.ENTITY_EFFECT, d1, (double) ((float) pos.getY() + 0.5F), d2, d3, d4, d5); + } + + }); + } + +- private static boolean isRaiderWithinRange(BlockPos blockpos, LivingEntity livingentity) { +- return livingentity.isAlive() && !livingentity.isRemoved() && blockpos.closerToCenterThan(livingentity.position(), 48.0D) && livingentity.getType().is(EntityTypeTags.RAIDERS); ++ private static boolean isRaiderWithinRange(BlockPos pos, LivingEntity raider) { ++ return raider.isAlive() && !raider.isRemoved() && pos.closerToCenterThan(raider.position(), 48.0D) && raider.getType().is(EntityTypeTags.RAIDERS); + } + +- private static void glow(LivingEntity livingentity) { +- livingentity.addEffect(new MobEffectInstance(MobEffects.GLOWING, 60)); ++ private static void glow(LivingEntity entity) { ++ entity.addEffect(new MobEffectInstance(MobEffects.GLOWING, 60)); + } + + @FunctionalInterface diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BlockEntity.java.patch new file mode 100644 index 0000000000..263ca1e097 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BlockEntity.java.patch @@ -0,0 +1,242 @@ +--- a/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -12,27 +12,37 @@ + import net.minecraft.world.item.BlockItem; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer; ++import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end ++ + public abstract class BlockEntity { + ++ // CraftBukkit start - data containers ++ private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); ++ public CraftPersistentDataContainer persistentDataContainer; ++ // CraftBukkit end + private static final Logger LOGGER = LogUtils.getLogger(); + private final BlockEntityType type; + @Nullable + protected Level level; + protected final BlockPos worldPosition; + protected boolean remove; +- private BlockState blockState; ++ private IBlockData blockState; + +- public BlockEntity(BlockEntityType blockentitytype, BlockPos blockpos, BlockState blockstate) { +- this.type = blockentitytype; +- this.worldPosition = blockpos.immutable(); +- this.blockState = blockstate; ++ public BlockEntity(BlockEntityType type, BlockPos pos, IBlockData blockState) { ++ this.type = type; ++ this.worldPosition = pos.immutable(); ++ this.blockState = blockState; + } + +- public static BlockPos getPosFromTag(CompoundTag compoundtag) { +- return new BlockPos(compoundtag.getInt("x"), compoundtag.getInt("y"), compoundtag.getInt("z")); ++ public static BlockPos getPosFromTag(CompoundTag tag) { ++ return new BlockPos(tag.getInt("x"), tag.getInt("y"), tag.getInt("z")); + } + + @Nullable +@@ -48,76 +58,90 @@ + return this.level != null; + } + +- public void load(CompoundTag compoundtag) {} ++ // CraftBukkit start - read container ++ public void load(CompoundTag tag) { ++ this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); + +- protected void saveAdditional(CompoundTag compoundtag) {} ++ net.minecraft.nbt.Tag persistentDataTag = tag.get("PublicBukkitValues"); ++ if (persistentDataTag instanceof CompoundTag) { ++ this.persistentDataContainer.putAll((CompoundTag) persistentDataTag); ++ } ++ } ++ // CraftBukkit end + ++ protected void saveAdditional(CompoundTag tag) {} ++ + public final CompoundTag saveWithFullMetadata() { +- CompoundTag compoundtag = this.saveWithoutMetadata(); ++ CompoundTag nbttagcompound = this.saveWithoutMetadata(); + +- this.saveMetadata(compoundtag); +- return compoundtag; ++ this.saveMetadata(nbttagcompound); ++ return nbttagcompound; + } + + public final CompoundTag saveWithId() { +- CompoundTag compoundtag = this.saveWithoutMetadata(); ++ CompoundTag nbttagcompound = this.saveWithoutMetadata(); + +- this.saveId(compoundtag); +- return compoundtag; ++ this.saveId(nbttagcompound); ++ return nbttagcompound; + } + + public final CompoundTag saveWithoutMetadata() { +- CompoundTag compoundtag = new CompoundTag(); ++ CompoundTag nbttagcompound = new CompoundTag(); + +- this.saveAdditional(compoundtag); +- return compoundtag; ++ this.saveAdditional(nbttagcompound); ++ // CraftBukkit start - store container ++ if (this.persistentDataContainer != null && !this.persistentDataContainer.isEmpty()) { ++ nbttagcompound.put("PublicBukkitValues", this.persistentDataContainer.toTagCompound()); ++ } ++ // CraftBukkit end ++ return nbttagcompound; + } + +- private void saveId(CompoundTag compoundtag) { +- ResourceLocation resourcelocation = BlockEntityType.getKey(this.getType()); ++ private void saveId(CompoundTag tag) { ++ ResourceLocation minecraftkey = BlockEntityType.getKey(this.getType()); + +- if (resourcelocation == null) { ++ if (minecraftkey == null) { + throw new RuntimeException(this.getClass() + " is missing a mapping! This is a bug!"); + } else { +- compoundtag.putString("id", resourcelocation.toString()); ++ tag.putString("id", minecraftkey.toString()); + } + } + +- public static void addEntityType(CompoundTag compoundtag, BlockEntityType blockentitytype) { +- compoundtag.putString("id", BlockEntityType.getKey(blockentitytype).toString()); ++ public static void addEntityType(CompoundTag tag, BlockEntityType entityType) { ++ tag.putString("id", BlockEntityType.getKey(entityType).toString()); + } + +- public void saveToItem(ItemStack itemstack) { +- BlockItem.setBlockEntityData(itemstack, this.getType(), this.saveWithoutMetadata()); ++ public void saveToItem(ItemStack stack) { ++ BlockItem.setBlockEntityData(stack, this.getType(), this.saveWithoutMetadata()); + } + +- private void saveMetadata(CompoundTag compoundtag) { +- this.saveId(compoundtag); +- compoundtag.putInt("x", this.worldPosition.getX()); +- compoundtag.putInt("y", this.worldPosition.getY()); +- compoundtag.putInt("z", this.worldPosition.getZ()); ++ private void saveMetadata(CompoundTag tag) { ++ this.saveId(tag); ++ tag.putInt("x", this.worldPosition.getX()); ++ tag.putInt("y", this.worldPosition.getY()); ++ tag.putInt("z", this.worldPosition.getZ()); + } + + @Nullable +- public static BlockEntity loadStatic(BlockPos blockpos, BlockState blockstate, CompoundTag compoundtag) { +- String s = compoundtag.getString("id"); +- ResourceLocation resourcelocation = ResourceLocation.tryParse(s); ++ public static BlockEntity loadStatic(BlockPos pos, IBlockData state, CompoundTag tag) { ++ String s = tag.getString("id"); ++ ResourceLocation minecraftkey = ResourceLocation.tryParse(s); + +- if (resourcelocation == null) { ++ if (minecraftkey == null) { + BlockEntity.LOGGER.error("Block entity has invalid type: {}", s); + return null; + } else { +- return (BlockEntity) BuiltInRegistries.BLOCK_ENTITY_TYPE.getOptional(resourcelocation).map((blockentitytype) -> { ++ return (BlockEntity) BuiltInRegistries.BLOCK_ENTITY_TYPE.getOptional(minecraftkey).map((tileentitytypes) -> { + try { +- return blockentitytype.create(blockpos, blockstate); ++ return tileentitytypes.create(pos, state); + } catch (Throwable throwable) { + BlockEntity.LOGGER.error("Failed to create block entity {}", s, throwable); + return null; + } +- }).map((blockentity) -> { ++ }).map((tileentity) -> { + try { +- blockentity.load(compoundtag); +- return blockentity; ++ tileentity.load(tag); ++ return tileentity; + } catch (Throwable throwable) { + BlockEntity.LOGGER.error("Failed to load data for block entity {}", s, throwable); + return null; +@@ -136,10 +160,10 @@ + + } + +- protected static void setChanged(Level level, BlockPos blockpos, BlockState blockstate) { +- level.blockEntityChanged(blockpos); +- if (!blockstate.isAir()) { +- level.updateNeighbourForOutputSignal(blockpos, blockstate.getBlock()); ++ protected static void setChanged(Level level, BlockPos pos, IBlockData state) { ++ level.blockEntityChanged(pos); ++ if (!state.isAir()) { ++ level.updateNeighbourForOutputSignal(pos, state.getBlock()); + } + + } +@@ -148,7 +172,7 @@ + return this.worldPosition; + } + +- public BlockState getBlockState() { ++ public IBlockData getBlockState() { + return this.blockState; + } + +@@ -173,19 +197,19 @@ + this.remove = false; + } + +- public boolean triggerEvent(int i, int j) { ++ public boolean triggerEvent(int id, int type) { + return false; + } + +- public void fillCrashReportCategory(CrashReportCategory crashreportcategory) { +- crashreportcategory.setDetail("Name", () -> { +- ResourceLocation resourcelocation = BuiltInRegistries.BLOCK_ENTITY_TYPE.getKey(this.getType()); ++ public void fillCrashReportCategory(CrashReportCategory reportCategory) { ++ reportCategory.setDetail("Name", () -> { ++ ResourceLocation minecraftkey = BuiltInRegistries.BLOCK_ENTITY_TYPE.getKey(this.getType()); + +- return resourcelocation + " // " + this.getClass().getCanonicalName(); ++ return minecraftkey + " // " + this.getClass().getCanonicalName(); + }); + if (this.level != null) { +- CrashReportCategory.populateBlockDetails(crashreportcategory, this.level, this.worldPosition, this.getBlockState()); +- CrashReportCategory.populateBlockDetails(crashreportcategory, this.level, this.worldPosition, this.level.getBlockState(this.worldPosition)); ++ CrashReportCategory.populateBlockDetails(reportCategory, this.level, this.worldPosition, this.getBlockState()); ++ CrashReportCategory.populateBlockDetails(reportCategory, this.level, this.worldPosition, this.level.getBlockState(this.worldPosition)); + } + } + +@@ -199,7 +223,16 @@ + + /** @deprecated */ + @Deprecated +- public void setBlockState(BlockState blockstate) { +- this.blockState = blockstate; ++ public void setBlockState(IBlockData blockState) { ++ this.blockState = blockState; + } ++ ++ // CraftBukkit start - add method ++ public InventoryHolder getOwner() { ++ if (level == null) return null; ++ org.bukkit.block.BlockState state = level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()).getState(); ++ if (state instanceof InventoryHolder) return (InventoryHolder) state; ++ return null; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java.patch new file mode 100644 index 0000000000..c0def2da40 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java.patch @@ -0,0 +1,418 @@ +--- a/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java +@@ -23,8 +23,22 @@ + import net.minecraft.world.item.alchemy.PotionBrewing; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.BrewingStandBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.event.block.BrewingStartEvent; ++import org.bukkit.event.inventory.BrewEvent; ++import org.bukkit.event.inventory.BrewingStandFuelEvent; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end ++ + public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements WorldlyContainer { + + private static final int INGREDIENT_SLOT = 3; +@@ -37,20 +51,49 @@ + public static final int DATA_FUEL_USES = 1; + public static final int NUM_DATA_VALUES = 2; + private NonNullList items; +- int brewTime; ++ public int brewTime; + private boolean[] lastPotionCount; + private Item ingredient; +- int fuel; ++ public int fuel; + protected final ContainerData dataAccess; ++ // CraftBukkit start - add fields and methods ++ private int lastTick = MinecraftServer.currentTick; ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = 64; + +- public BrewingStandBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.BREWING_STAND, blockpos, blockstate); ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ ++ public BrewingStandBlockEntity(BlockPos pos, IBlockData state) { ++ super(BlockEntityType.BREWING_STAND, pos, state); + this.items = NonNullList.withSize(5, ItemStack.EMPTY); + this.dataAccess = new ContainerData() { + @Override +- @Override +- public int get(int i) { +- switch (i) { ++ public int get(int index) { ++ switch (index) { + case 0: + return BrewingStandBlockEntity.this.brewTime; + case 1: +@@ -61,20 +104,18 @@ + } + + @Override +- @Override +- public void set(int i, int j) { +- switch (i) { ++ public void set(int index, int value) { ++ switch (index) { + case 0: +- BrewingStandBlockEntity.this.brewTime = j; ++ BrewingStandBlockEntity.this.brewTime = value; + break; + case 1: +- BrewingStandBlockEntity.this.fuel = j; ++ BrewingStandBlockEntity.this.fuel = value; + } + + } + + @Override +- @Override + public int getCount() { + return 2; + } +@@ -82,19 +123,16 @@ + } + + @Override +- @Override + protected Component getDefaultName() { + return Component.translatable("container.brewing"); + } + + @Override +- @Override + public int getContainerSize() { + return this.items.size(); + } + + @Override +- @Override + public boolean isEmpty() { + Iterator iterator = this.items.iterator(); + +@@ -111,52 +149,72 @@ + return false; + } + +- public static void serverTick(Level level, BlockPos blockpos, BlockState blockstate, BrewingStandBlockEntity brewingstandblockentity) { +- ItemStack itemstack = (ItemStack) brewingstandblockentity.items.get(4); ++ public static void serverTick(Level level, BlockPos pos, IBlockData state, BrewingStandBlockEntity blockEntity) { ++ ItemStack itemstack = (ItemStack) blockEntity.items.get(4); + +- if (brewingstandblockentity.fuel <= 0 && itemstack.is(Items.BLAZE_POWDER)) { +- brewingstandblockentity.fuel = 20; +- itemstack.shrink(1); +- setChanged(level, blockpos, blockstate); ++ if (blockEntity.fuel <= 0 && itemstack.is(Items.BLAZE_POWDER)) { ++ // CraftBukkit start ++ BrewingStandFuelEvent event = new BrewingStandFuelEvent(CraftBlock.at(level, pos), CraftItemStack.asCraftMirror(itemstack), 20); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ blockEntity.fuel = event.getFuelPower(); ++ if (blockEntity.fuel > 0 && event.isConsuming()) { ++ itemstack.shrink(1); ++ } ++ // CraftBukkit end ++ setChanged(level, pos, state); + } + +- boolean flag = isBrewable(brewingstandblockentity.items); +- boolean flag1 = brewingstandblockentity.brewTime > 0; +- ItemStack itemstack1 = (ItemStack) brewingstandblockentity.items.get(3); ++ boolean flag = isBrewable(blockEntity.items); ++ boolean flag1 = blockEntity.brewTime > 0; ++ ItemStack itemstack1 = (ItemStack) blockEntity.items.get(3); + ++ // CraftBukkit start - Use wall time instead of ticks for brewing ++ int elapsedTicks = MinecraftServer.currentTick - blockEntity.lastTick; ++ blockEntity.lastTick = MinecraftServer.currentTick; ++ + if (flag1) { +- --brewingstandblockentity.brewTime; +- boolean flag2 = brewingstandblockentity.brewTime == 0; ++ blockEntity.brewTime -= elapsedTicks; ++ boolean flag2 = blockEntity.brewTime <= 0; // == -> <= ++ // CraftBukkit end + + if (flag2 && flag) { +- doBrew(level, blockpos, brewingstandblockentity.items); +- setChanged(level, blockpos, blockstate); +- } else if (!flag || !itemstack1.is(brewingstandblockentity.ingredient)) { +- brewingstandblockentity.brewTime = 0; +- setChanged(level, blockpos, blockstate); ++ doBrew(level, pos, blockEntity.items, blockEntity); // CraftBukkit ++ setChanged(level, pos, state); ++ } else if (!flag || !itemstack1.is(blockEntity.ingredient)) { ++ blockEntity.brewTime = 0; ++ setChanged(level, pos, state); + } +- } else if (flag && brewingstandblockentity.fuel > 0) { +- --brewingstandblockentity.fuel; +- brewingstandblockentity.brewTime = 400; +- brewingstandblockentity.ingredient = itemstack1.getItem(); +- setChanged(level, blockpos, blockstate); ++ } else if (flag && blockEntity.fuel > 0) { ++ --blockEntity.fuel; ++ // CraftBukkit start ++ BrewingStartEvent event = new BrewingStartEvent(CraftBlock.at(level, pos), CraftItemStack.asCraftMirror(itemstack1), 400); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ blockEntity.brewTime = event.getTotalBrewTime(); // 400 -> event.getTotalBrewTime() ++ // CraftBukkit end ++ blockEntity.ingredient = itemstack1.getItem(); ++ setChanged(level, pos, state); + } + +- boolean[] aboolean = brewingstandblockentity.getPotionBits(); ++ boolean[] aboolean = blockEntity.getPotionBits(); + +- if (!Arrays.equals(aboolean, brewingstandblockentity.lastPotionCount)) { +- brewingstandblockentity.lastPotionCount = aboolean; +- BlockState blockstate1 = blockstate; ++ if (!Arrays.equals(aboolean, blockEntity.lastPotionCount)) { ++ blockEntity.lastPotionCount = aboolean; ++ IBlockData iblockdata1 = state; + +- if (!(blockstate.getBlock() instanceof BrewingStandBlock)) { ++ if (!(state.getBlock() instanceof BrewingStandBlock)) { + return; + } + + for (int i = 0; i < BrewingStandBlock.HAS_BOTTLE.length; ++i) { +- blockstate1 = (BlockState) blockstate1.setValue(BrewingStandBlock.HAS_BOTTLE[i], aboolean[i]); ++ iblockdata1 = (IBlockData) iblockdata1.setValue(BrewingStandBlock.HAS_BOTTLE[i], aboolean[i]); + } + +- level.setBlock(blockpos, blockstate1, 2); ++ level.setBlock(pos, iblockdata1, 2); + } + + } +@@ -173,8 +231,8 @@ + return aboolean; + } + +- private static boolean isBrewable(NonNullList nonnulllist) { +- ItemStack itemstack = (ItemStack) nonnulllist.get(3); ++ private static boolean isBrewable(NonNullList items) { ++ ItemStack itemstack = (ItemStack) items.get(3); + + if (itemstack.isEmpty()) { + return false; +@@ -182,7 +240,7 @@ + return false; + } else { + for (int i = 0; i < 3; ++i) { +- ItemStack itemstack1 = (ItemStack) nonnulllist.get(i); ++ ItemStack itemstack1 = (ItemStack) items.get(i); + + if (!itemstack1.isEmpty() && PotionBrewing.hasMix(itemstack1, itemstack)) { + return true; +@@ -193,13 +251,35 @@ + } + } + +- private static void doBrew(Level level, BlockPos blockpos, NonNullList nonnulllist) { ++ // CraftBukkit start ++ private static void doBrew(Level world, BlockPos blockposition, NonNullList nonnulllist, BrewingStandBlockEntity tileentitybrewingstand) { + ItemStack itemstack = (ItemStack) nonnulllist.get(3); ++ InventoryHolder owner = tileentitybrewingstand.getOwner(); ++ List brewResults = new ArrayList<>(3); + + for (int i = 0; i < 3; ++i) { +- nonnulllist.set(i, PotionBrewing.mix(itemstack, (ItemStack) nonnulllist.get(i))); ++ brewResults.add(i, CraftItemStack.asCraftMirror(PotionBrewing.mix(itemstack, (ItemStack) nonnulllist.get(i)))); + } + ++ if (owner != null) { ++ BrewEvent event = new BrewEvent(CraftBlock.at(world, blockposition), (org.bukkit.inventory.BrewerInventory) owner.getInventory(), brewResults, tileentitybrewingstand.fuel); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ ++ for (int i = 0; i < 3; ++i) { ++ // CraftBukkit start - validate index in case it is cleared by plugins ++ if (i < brewResults.size()) { ++ nonnulllist.set(i, CraftItemStack.asNMSCopy(brewResults.get(i))); ++ } else { ++ nonnulllist.set(i, ItemStack.EMPTY); ++ } ++ // CraftBukkit end ++ } ++ + itemstack.shrink(1); + if (itemstack.getItem().hasCraftingRemainingItem()) { + ItemStack itemstack1 = new ItemStack(itemstack.getItem().getCraftingRemainingItem()); +@@ -207,99 +287,86 @@ + if (itemstack.isEmpty()) { + itemstack = itemstack1; + } else { +- Containers.dropItemStack(level, (double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), itemstack1); ++ Containers.dropItemStack(world, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), itemstack1); + } + } + + nonnulllist.set(3, itemstack); +- level.levelEvent(1035, blockpos, 0); ++ world.levelEvent(1035, blockposition, 0); + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); ++ public void load(CompoundTag tag) { ++ super.load(tag); + this.items = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); +- ContainerHelper.loadAllItems(compoundtag, this.items); +- this.brewTime = compoundtag.getShort("BrewTime"); +- this.fuel = compoundtag.getByte("Fuel"); ++ ContainerHelper.loadAllItems(tag, this.items); ++ this.brewTime = tag.getShort("BrewTime"); ++ this.fuel = tag.getByte("Fuel"); + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); +- compoundtag.putShort("BrewTime", (short) this.brewTime); +- ContainerHelper.saveAllItems(compoundtag, this.items); +- compoundtag.putByte("Fuel", (byte) this.fuel); ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); ++ tag.putShort("BrewTime", (short) this.brewTime); ++ ContainerHelper.saveAllItems(tag, this.items); ++ tag.putByte("Fuel", (byte) this.fuel); + } + + @Override +- @Override +- public ItemStack getItem(int i) { +- return i >= 0 && i < this.items.size() ? (ItemStack) this.items.get(i) : ItemStack.EMPTY; ++ public ItemStack getItem(int index) { ++ return index >= 0 && index < this.items.size() ? (ItemStack) this.items.get(index) : ItemStack.EMPTY; + } + + @Override +- @Override +- public ItemStack removeItem(int i, int j) { +- return ContainerHelper.removeItem(this.items, i, j); ++ public ItemStack removeItem(int index, int count) { ++ return ContainerHelper.removeItem(this.items, index, count); + } + + @Override +- @Override +- public ItemStack removeItemNoUpdate(int i) { +- return ContainerHelper.takeItem(this.items, i); ++ public ItemStack removeItemNoUpdate(int index) { ++ return ContainerHelper.takeItem(this.items, index); + } + + @Override +- @Override +- public void setItem(int i, ItemStack itemstack) { +- if (i >= 0 && i < this.items.size()) { +- this.items.set(i, itemstack); ++ public void setItem(int index, ItemStack stack) { ++ if (index >= 0 && index < this.items.size()) { ++ this.items.set(index, stack); + } + + } + + @Override +- @Override + public boolean stillValid(Player player) { + return Container.stillValidBlockEntity(this, player); + } + + @Override +- @Override +- public boolean canPlaceItem(int i, ItemStack itemstack) { +- return i == 3 ? PotionBrewing.isIngredient(itemstack) : (i == 4 ? itemstack.is(Items.BLAZE_POWDER) : (itemstack.is(Items.POTION) || itemstack.is(Items.SPLASH_POTION) || itemstack.is(Items.LINGERING_POTION) || itemstack.is(Items.GLASS_BOTTLE)) && this.getItem(i).isEmpty()); ++ public boolean canPlaceItem(int index, ItemStack stack) { ++ return index == 3 ? PotionBrewing.isIngredient(stack) : (index == 4 ? stack.is(Items.BLAZE_POWDER) : (stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE)) && this.getItem(index).isEmpty()); + } + + @Override +- @Override +- public int[] getSlotsForFace(Direction direction) { +- return direction == Direction.UP ? BrewingStandBlockEntity.SLOTS_FOR_UP : (direction == Direction.DOWN ? BrewingStandBlockEntity.SLOTS_FOR_DOWN : BrewingStandBlockEntity.SLOTS_FOR_SIDES); ++ public int[] getSlotsForFace(Direction side) { ++ return side == Direction.UP ? BrewingStandBlockEntity.SLOTS_FOR_UP : (side == Direction.DOWN ? BrewingStandBlockEntity.SLOTS_FOR_DOWN : BrewingStandBlockEntity.SLOTS_FOR_SIDES); + } + + @Override +- @Override +- public boolean canPlaceItemThroughFace(int i, ItemStack itemstack, @Nullable Direction direction) { +- return this.canPlaceItem(i, itemstack); ++ public boolean canPlaceItemThroughFace(int index, ItemStack itemStack, @Nullable Direction direction) { ++ return this.canPlaceItem(index, itemStack); + } + + @Override +- @Override +- public boolean canTakeItemThroughFace(int i, ItemStack itemstack, Direction direction) { +- return i == 3 ? itemstack.is(Items.GLASS_BOTTLE) : true; ++ public boolean canTakeItemThroughFace(int index, ItemStack stack, Direction direction) { ++ return index == 3 ? stack.is(Items.GLASS_BOTTLE) : true; + } + + @Override +- @Override + public void clearContent() { + this.items.clear(); + } + + @Override +- @Override +- protected AbstractContainerMenu createMenu(int i, Inventory inventory) { +- return new BrewingStandMenu(i, inventory, this, this.dataAccess); ++ protected AbstractContainerMenu createMenu(int id, Inventory player) { ++ return new BrewingStandMenu(id, player, this, this.dataAccess); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BrushableBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BrushableBlockEntity.java.patch new file mode 100644 index 0000000000..71a1b4e27f --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/BrushableBlockEntity.java.patch @@ -0,0 +1,238 @@ +--- a/net/minecraft/world/level/block/entity/BrushableBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BrushableBlockEntity.java +@@ -19,7 +19,7 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.BrushableBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.storage.loot.LootParams; + import net.minecraft.world.level.storage.loot.LootTable; +@@ -28,6 +28,12 @@ + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.Arrays; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class BrushableBlockEntity extends BlockEntity { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -41,41 +47,41 @@ + private int brushCount; + private long brushCountResetsAtTick; + private long coolDownEndsAtTick; +- private ItemStack item; ++ public ItemStack item; + @Nullable + private Direction hitDirection; + @Nullable +- private ResourceLocation lootTable; +- private long lootTableSeed; ++ public ResourceLocation lootTable; ++ public long lootTableSeed; + +- public BrushableBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.BRUSHABLE_BLOCK, blockpos, blockstate); ++ public BrushableBlockEntity(BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.BRUSHABLE_BLOCK, pos, blockState); + this.item = ItemStack.EMPTY; + } + +- public boolean brush(long i, Player player, Direction direction) { ++ public boolean brush(long startTick, Player entityhuman, Direction player) { + if (this.hitDirection == null) { +- this.hitDirection = direction; ++ this.hitDirection = player; + } + +- this.brushCountResetsAtTick = i + 40L; +- if (i >= this.coolDownEndsAtTick && this.level instanceof ServerLevel) { +- this.coolDownEndsAtTick = i + 10L; +- this.unpackLootTable(player); ++ this.brushCountResetsAtTick = startTick + 40L; ++ if (startTick >= this.coolDownEndsAtTick && this.level instanceof ServerLevel) { ++ this.coolDownEndsAtTick = startTick + 10L; ++ this.unpackLootTable(entityhuman); + int j = this.getCompletionState(); + + if (++this.brushCount >= 10) { +- this.brushingCompleted(player); ++ this.brushingCompleted(entityhuman); + return true; + } else { + this.level.scheduleTick(this.getBlockPos(), this.getBlockState().getBlock(), 2); + int k = this.getCompletionState(); + + if (j != k) { +- BlockState blockstate = this.getBlockState(); +- BlockState blockstate1 = (BlockState) blockstate.setValue(BlockStateProperties.DUSTED, k); ++ IBlockData iblockdata = this.getBlockState(); ++ IBlockData iblockdata1 = (IBlockData) iblockdata.setValue(BlockStateProperties.DUSTED, k); + +- this.level.setBlock(this.getBlockPos(), blockstate1, 3); ++ this.level.setBlock(this.getBlockPos(), iblockdata1, 3); + } + + return false; +@@ -90,9 +96,9 @@ + LootTable loottable = this.level.getServer().getLootData().getLootTable(this.lootTable); + + if (player instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) player; ++ ServerPlayer entityplayer = (ServerPlayer) player; + +- CriteriaTriggers.GENERATE_LOOT.trigger(serverplayer, this.lootTable); ++ CriteriaTriggers.GENERATE_LOOT.trigger(entityplayer, this.lootTable); + } + + LootParams lootparams = (new LootParams.Builder((ServerLevel) this.level)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(this.worldPosition)).withLuck(player.getLuck()).withParameter(LootContextParams.THIS_ENTITY, player).create(LootContextParamSets.CHEST); +@@ -120,9 +126,9 @@ + private void brushingCompleted(Player player) { + if (this.level != null && this.level.getServer() != null) { + this.dropContent(player); +- BlockState blockstate = this.getBlockState(); ++ IBlockData iblockdata = this.getBlockState(); + +- this.level.levelEvent(3008, this.getBlockPos(), Block.getId(blockstate)); ++ this.level.levelEvent(3008, this.getBlockPos(), Block.getId(iblockdata)); + Block block = this.getBlockState().getBlock(); + Block block1; + +@@ -145,15 +151,18 @@ + double d0 = (double) EntityType.ITEM.getWidth(); + double d1 = 1.0D - d0; + double d2 = d0 / 2.0D; +- Direction direction = (Direction) Objects.requireNonNullElse(this.hitDirection, Direction.UP); +- BlockPos blockpos = this.worldPosition.relative(direction, 1); +- double d3 = (double) blockpos.getX() + 0.5D * d1 + d2; +- double d4 = (double) blockpos.getY() + 0.5D + (double) (EntityType.ITEM.getHeight() / 2.0F); +- double d5 = (double) blockpos.getZ() + 0.5D * d1 + d2; +- ItemEntity itementity = new ItemEntity(this.level, d3, d4, d5, this.item.split(this.level.random.nextInt(21) + 10)); ++ Direction enumdirection = (Direction) Objects.requireNonNullElse(this.hitDirection, Direction.UP); ++ BlockPos blockposition = this.worldPosition.relative(enumdirection, 1); ++ double d3 = (double) blockposition.getX() + 0.5D * d1 + d2; ++ double d4 = (double) blockposition.getY() + 0.5D + (double) (EntityType.ITEM.getHeight() / 2.0F); ++ double d5 = (double) blockposition.getZ() + 0.5D * d1 + d2; ++ ItemEntity entityitem = new ItemEntity(this.level, d3, d4, d5, this.item.split(this.level.random.nextInt(21) + 10)); + +- itementity.setDeltaMovement(Vec3.ZERO); +- this.level.addFreshEntity(itementity); ++ entityitem.setDeltaMovement(Vec3.ZERO); ++ // CraftBukkit start ++ org.bukkit.block.Block bblock = CraftBlock.at(this.level, this.worldPosition); ++ CraftEventFactory.handleBlockDropItemEvent(bblock, bblock.getState(), (ServerPlayer) player, Arrays.asList(entityitem)); ++ // CraftBukkit end + this.item = ItemStack.EMPTY; + } + +@@ -169,7 +178,7 @@ + int j = this.getCompletionState(); + + if (i != j) { +- this.level.setBlock(this.getBlockPos(), (BlockState) this.getBlockState().setValue(BlockStateProperties.DUSTED, j), 3); ++ this.level.setBlock(this.getBlockPos(), (IBlockData) this.getBlockState().setValue(BlockStateProperties.DUSTED, j), 3); + } + + boolean flag = true; +@@ -188,23 +197,23 @@ + } + } + +- private boolean tryLoadLootTable(CompoundTag compoundtag) { +- if (compoundtag.contains("LootTable", 8)) { +- this.lootTable = new ResourceLocation(compoundtag.getString("LootTable")); +- this.lootTableSeed = compoundtag.getLong("LootTableSeed"); ++ private boolean tryLoadLootTable(CompoundTag tag) { ++ if (tag.contains("LootTable", 8)) { ++ this.lootTable = new ResourceLocation(tag.getString("LootTable")); ++ this.lootTableSeed = tag.getLong("LootTableSeed"); + return true; + } else { + return false; + } + } + +- private boolean trySaveLootTable(CompoundTag compoundtag) { ++ private boolean trySaveLootTable(CompoundTag tag) { + if (this.lootTable == null) { + return false; + } else { +- compoundtag.putString("LootTable", this.lootTable.toString()); ++ tag.putString("LootTable", this.lootTable.toString()); + if (this.lootTableSeed != 0L) { +- compoundtag.putLong("LootTableSeed", this.lootTableSeed); ++ tag.putLong("LootTableSeed", this.lootTableSeed); + } + + return true; +@@ -212,49 +221,46 @@ + } + + @Override +- @Override + public CompoundTag getUpdateTag() { +- CompoundTag compoundtag = super.getUpdateTag(); ++ CompoundTag nbttagcompound = super.getUpdateTag(); + + if (this.hitDirection != null) { +- compoundtag.putInt("hit_direction", this.hitDirection.ordinal()); ++ nbttagcompound.putInt("hit_direction", this.hitDirection.ordinal()); + } + +- compoundtag.put("item", this.item.save(new CompoundTag())); +- return compoundtag; ++ nbttagcompound.put("item", this.item.save(new CompoundTag())); ++ return nbttagcompound; + } + + @Override +- @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- if (!this.tryLoadLootTable(compoundtag) && compoundtag.contains("item")) { +- this.item = ItemStack.of(compoundtag.getCompound("item")); ++ public void load(CompoundTag tag) { ++ super.load(tag); // CraftBukkit - SPIGOT-7393: Load super Bukkit data ++ if (!this.tryLoadLootTable(tag) && tag.contains("item")) { ++ this.item = ItemStack.of(tag.getCompound("item")); + } + +- if (compoundtag.contains("hit_direction")) { +- this.hitDirection = Direction.values()[compoundtag.getInt("hit_direction")]; ++ if (tag.contains("hit_direction")) { ++ this.hitDirection = Direction.values()[tag.getInt("hit_direction")]; + } + + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- if (!this.trySaveLootTable(compoundtag)) { +- compoundtag.put("item", this.item.save(new CompoundTag())); ++ protected void saveAdditional(CompoundTag tag) { ++ if (!this.trySaveLootTable(tag)) { ++ tag.put("item", this.item.save(new CompoundTag())); + } + + } + +- public void setLootTable(ResourceLocation resourcelocation, long i) { +- this.lootTable = resourcelocation; +- this.lootTableSeed = i; ++ public void setLootTable(ResourceLocation lootTable, long lootTableSeed) { ++ this.lootTable = lootTable; ++ this.lootTableSeed = lootTableSeed; + } + + private int getCompletionState() { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/CampfireBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/CampfireBlockEntity.java.patch new file mode 100644 index 0000000000..af9953ad3a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/CampfireBlockEntity.java.patch @@ -0,0 +1,244 @@ +--- a/net/minecraft/world/level/block/entity/CampfireBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/CampfireBlockEntity.java +@@ -23,93 +23,115 @@ + import net.minecraft.world.item.crafting.RecipeType; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.CampfireBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockCookEvent; ++import org.bukkit.event.block.CampfireStartEvent; ++import org.bukkit.inventory.CampfireRecipe; ++// CraftBukkit end ++ + public class CampfireBlockEntity extends BlockEntity implements Clearable { + + private static final int BURN_COOL_SPEED = 2; + private static final int NUM_SLOTS = 4; + private final NonNullList items; +- private final int[] cookingProgress; +- private final int[] cookingTime; ++ public final int[] cookingProgress; ++ public final int[] cookingTime; + private final RecipeManager.CachedCheck quickCheck; + +- public CampfireBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.CAMPFIRE, blockpos, blockstate); ++ public CampfireBlockEntity(BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.CAMPFIRE, pos, blockState); + this.items = NonNullList.withSize(4, ItemStack.EMPTY); + this.cookingProgress = new int[4]; + this.cookingTime = new int[4]; + this.quickCheck = RecipeManager.createCheck(RecipeType.CAMPFIRE_COOKING); + } + +- public static void cookTick(Level level, BlockPos blockpos, BlockState blockstate, CampfireBlockEntity campfireblockentity) { ++ public static void cookTick(Level level, BlockPos pos, IBlockData state, CampfireBlockEntity blockEntity) { + boolean flag = false; + +- for (int i = 0; i < campfireblockentity.items.size(); ++i) { +- ItemStack itemstack = (ItemStack) campfireblockentity.items.get(i); ++ for (int i = 0; i < blockEntity.items.size(); ++i) { ++ ItemStack itemstack = (ItemStack) blockEntity.items.get(i); + + if (!itemstack.isEmpty()) { + flag = true; +- int j = campfireblockentity.cookingProgress[i]++; ++ int j = blockEntity.cookingProgress[i]++; + +- if (campfireblockentity.cookingProgress[i] >= campfireblockentity.cookingTime[i]) { +- SimpleContainer simplecontainer = new SimpleContainer(new ItemStack[]{itemstack}); +- ItemStack itemstack1 = (ItemStack) campfireblockentity.quickCheck.getRecipeFor(simplecontainer, level).map((recipeholder) -> { +- return ((CampfireCookingRecipe) recipeholder.value()).assemble(simplecontainer, level.registryAccess()); ++ if (blockEntity.cookingProgress[i] >= blockEntity.cookingTime[i]) { ++ SimpleContainer inventorysubcontainer = new SimpleContainer(new ItemStack[]{itemstack}); ++ ItemStack itemstack1 = (ItemStack) blockEntity.quickCheck.getRecipeFor(inventorysubcontainer, level).map((recipeholder) -> { ++ return ((CampfireCookingRecipe) recipeholder.value()).assemble(inventorysubcontainer, level.registryAccess()); + }).orElse(itemstack); + + if (itemstack1.isItemEnabled(level.enabledFeatures())) { +- Containers.dropItemStack(level, (double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), itemstack1); +- campfireblockentity.items.set(i, ItemStack.EMPTY); +- level.sendBlockUpdated(blockpos, blockstate, blockstate, 3); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockpos, GameEvent.Context.of(blockstate)); ++ // CraftBukkit start - fire BlockCookEvent ++ CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); ++ org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); ++ ++ BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(level, pos), source, result); ++ level.getCraftServer().getPluginManager().callEvent(blockCookEvent); ++ ++ if (blockCookEvent.isCancelled()) { ++ return; ++ } ++ ++ result = blockCookEvent.getResult(); ++ itemstack1 = CraftItemStack.asNMSCopy(result); ++ // CraftBukkit end ++ Containers.dropItemStack(level, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), itemstack1); ++ blockEntity.items.set(i, ItemStack.EMPTY); ++ level.sendBlockUpdated(pos, state, state, 3); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(state)); + } + } + } + } + + if (flag) { +- setChanged(level, blockpos, blockstate); ++ setChanged(level, pos, state); + } + + } + +- public static void cooldownTick(Level level, BlockPos blockpos, BlockState blockstate, CampfireBlockEntity campfireblockentity) { ++ public static void cooldownTick(Level level, BlockPos pos, IBlockData state, CampfireBlockEntity blockEntity) { + boolean flag = false; + +- for (int i = 0; i < campfireblockentity.items.size(); ++i) { +- if (campfireblockentity.cookingProgress[i] > 0) { ++ for (int i = 0; i < blockEntity.items.size(); ++i) { ++ if (blockEntity.cookingProgress[i] > 0) { + flag = true; +- campfireblockentity.cookingProgress[i] = Mth.clamp(campfireblockentity.cookingProgress[i] - 2, 0, campfireblockentity.cookingTime[i]); ++ blockEntity.cookingProgress[i] = Mth.clamp(blockEntity.cookingProgress[i] - 2, 0, blockEntity.cookingTime[i]); + } + } + + if (flag) { +- setChanged(level, blockpos, blockstate); ++ setChanged(level, pos, state); + } + + } + +- public static void particleTick(Level level, BlockPos blockpos, BlockState blockstate, CampfireBlockEntity campfireblockentity) { ++ public static void particleTick(Level level, BlockPos pos, IBlockData state, CampfireBlockEntity blockEntity) { + RandomSource randomsource = level.random; + int i; + + if (randomsource.nextFloat() < 0.11F) { + for (i = 0; i < randomsource.nextInt(2) + 2; ++i) { +- CampfireBlock.makeParticles(level, blockpos, (Boolean) blockstate.getValue(CampfireBlock.SIGNAL_FIRE), false); ++ CampfireBlock.makeParticles(level, pos, (Boolean) state.getValue(CampfireBlock.SIGNAL_FIRE), false); + } + } + +- i = ((Direction) blockstate.getValue(CampfireBlock.FACING)).get2DDataValue(); ++ i = ((Direction) state.getValue(CampfireBlock.FACING)).get2DDataValue(); + +- for (int j = 0; j < campfireblockentity.items.size(); ++j) { +- if (!((ItemStack) campfireblockentity.items.get(j)).isEmpty() && randomsource.nextFloat() < 0.2F) { +- Direction direction = Direction.from2DDataValue(Math.floorMod(j + i, 4)); ++ for (int j = 0; j < blockEntity.items.size(); ++j) { ++ if (!((ItemStack) blockEntity.items.get(j)).isEmpty() && randomsource.nextFloat() < 0.2F) { ++ Direction enumdirection = Direction.from2DDataValue(Math.floorMod(j + i, 4)); + float f = 0.3125F; +- double d0 = (double) blockpos.getX() + 0.5D - (double) ((float) direction.getStepX() * 0.3125F) + (double) ((float) direction.getClockWise().getStepX() * 0.3125F); +- double d1 = (double) blockpos.getY() + 0.5D; +- double d2 = (double) blockpos.getZ() + 0.5D - (double) ((float) direction.getStepZ() * 0.3125F) + (double) ((float) direction.getClockWise().getStepZ() * 0.3125F); ++ double d0 = (double) pos.getX() + 0.5D - (double) ((float) enumdirection.getStepX() * 0.3125F) + (double) ((float) enumdirection.getClockWise().getStepX() * 0.3125F); ++ double d1 = (double) pos.getY() + 0.5D; ++ double d2 = (double) pos.getZ() + 0.5D - (double) ((float) enumdirection.getStepZ() * 0.3125F) + (double) ((float) enumdirection.getClockWise().getStepZ() * 0.3125F); + + for (int k = 0; k < 4; ++k) { + level.addParticle(ParticleTypes.SMOKE, d0, d1, d2, 0.0D, 5.0E-4D, 0.0D); +@@ -124,61 +146,61 @@ + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); ++ public void load(CompoundTag tag) { ++ super.load(tag); + this.items.clear(); +- ContainerHelper.loadAllItems(compoundtag, this.items); ++ ContainerHelper.loadAllItems(tag, this.items); + int[] aint; + +- if (compoundtag.contains("CookingTimes", 11)) { +- aint = compoundtag.getIntArray("CookingTimes"); ++ if (tag.contains("CookingTimes", 11)) { ++ aint = tag.getIntArray("CookingTimes"); + System.arraycopy(aint, 0, this.cookingProgress, 0, Math.min(this.cookingTime.length, aint.length)); + } + +- if (compoundtag.contains("CookingTotalTimes", 11)) { +- aint = compoundtag.getIntArray("CookingTotalTimes"); ++ if (tag.contains("CookingTotalTimes", 11)) { ++ aint = tag.getIntArray("CookingTotalTimes"); + System.arraycopy(aint, 0, this.cookingTime, 0, Math.min(this.cookingTime.length, aint.length)); + } + + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); +- ContainerHelper.saveAllItems(compoundtag, this.items, true); +- compoundtag.putIntArray("CookingTimes", this.cookingProgress); +- compoundtag.putIntArray("CookingTotalTimes", this.cookingTime); ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); ++ ContainerHelper.saveAllItems(tag, this.items, true); ++ tag.putIntArray("CookingTimes", this.cookingProgress); ++ tag.putIntArray("CookingTotalTimes", this.cookingTime); + } + + @Override +- @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + @Override +- @Override + public CompoundTag getUpdateTag() { +- CompoundTag compoundtag = new CompoundTag(); ++ CompoundTag nbttagcompound = new CompoundTag(); + +- ContainerHelper.saveAllItems(compoundtag, this.items, true); +- return compoundtag; ++ ContainerHelper.saveAllItems(nbttagcompound, this.items, true); ++ return nbttagcompound; + } + +- public Optional> getCookableRecipe(ItemStack itemstack) { +- return this.items.stream().noneMatch(ItemStack::isEmpty) ? Optional.empty() : this.quickCheck.getRecipeFor(new SimpleContainer(new ItemStack[]{itemstack}), this.level); ++ public Optional> getCookableRecipe(ItemStack stack) { ++ return this.items.stream().noneMatch(ItemStack::isEmpty) ? Optional.empty() : this.quickCheck.getRecipeFor(new SimpleContainer(new ItemStack[]{stack}), this.level); + } + +- public boolean placeFood(@Nullable Entity entity, ItemStack itemstack, int i) { ++ public boolean placeFood(@Nullable Entity entity, ItemStack stack, int cookTime) { + for (int j = 0; j < this.items.size(); ++j) { + ItemStack itemstack1 = (ItemStack) this.items.get(j); + + if (itemstack1.isEmpty()) { +- this.cookingTime[j] = i; ++ // CraftBukkit start ++ CampfireStartEvent event = new CampfireStartEvent(CraftBlock.at(this.level,this.worldPosition), CraftItemStack.asCraftMirror(stack), (CampfireRecipe) getCookableRecipe(stack).get().toBukkitRecipe()); ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ this.cookingTime[j] = event.getTotalCookTime(); // i -> event.getTotalCookTime() ++ // CraftBukkit end + this.cookingProgress[j] = 0; +- this.items.set(j, itemstack.split(1)); ++ this.items.set(j, stack.split(1)); + this.level.gameEvent(GameEvent.BLOCK_CHANGE, this.getBlockPos(), GameEvent.Context.of(entity, this.getBlockState())); + this.markUpdated(); + return true; +@@ -194,7 +216,6 @@ + } + + @Override +- @Override + public void clearContent() { + this.items.clear(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/ChestBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/ChestBlockEntity.java.patch new file mode 100644 index 0000000000..95913eeb89 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/ChestBlockEntity.java.patch @@ -0,0 +1,296 @@ +--- a/net/minecraft/world/level/block/entity/ChestBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/ChestBlockEntity.java +@@ -20,126 +20,151 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.ChestBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.ChestType; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end + + public class ChestBlockEntity extends RandomizableContainerBlockEntity implements LidBlockEntity { + + private static final int EVENT_SET_OPEN_COUNT = 1; + private NonNullList items; +- private final ContainerOpenersCounter openersCounter; ++ public final ContainerOpenersCounter openersCounter; + private final ChestLidController chestLidController; + +- protected ChestBlockEntity(BlockEntityType blockentitytype, BlockPos blockpos, BlockState blockstate) { +- super(blockentitytype, blockpos, blockstate); ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ ++ protected ChestBlockEntity(BlockEntityType type, BlockPos pos, IBlockData blockState) { ++ super(type, pos, blockState); + this.items = NonNullList.withSize(27, ItemStack.EMPTY); + this.openersCounter = new ContainerOpenersCounter() { + @Override +- @Override +- protected void onOpen(Level level, BlockPos blockpos1, BlockState blockstate1) { +- ChestBlockEntity.playSound(level, blockpos1, blockstate1, SoundEvents.CHEST_OPEN); ++ protected void onOpen(Level level, BlockPos pos, IBlockData state) { ++ ChestBlockEntity.playSound(level, pos, state, SoundEvents.CHEST_OPEN); + } + + @Override +- @Override +- protected void onClose(Level level, BlockPos blockpos1, BlockState blockstate1) { +- ChestBlockEntity.playSound(level, blockpos1, blockstate1, SoundEvents.CHEST_CLOSE); ++ protected void onClose(Level level, BlockPos pos, IBlockData state) { ++ ChestBlockEntity.playSound(level, pos, state, SoundEvents.CHEST_CLOSE); + } + + @Override +- @Override +- protected void openerCountChanged(Level level, BlockPos blockpos1, BlockState blockstate1, int i, int j) { +- ChestBlockEntity.this.signalOpenCount(level, blockpos1, blockstate1, i, j); ++ protected void openerCountChanged(Level level, BlockPos pos, IBlockData state, int count, int openCount) { ++ ChestBlockEntity.this.signalOpenCount(level, pos, state, count, openCount); + } + + @Override +- @Override + protected boolean isOwnContainer(Player player) { + if (!(player.containerMenu instanceof ChestMenu)) { + return false; + } else { +- Container container = ((ChestMenu) player.containerMenu).getContainer(); ++ Container iinventory = ((ChestMenu) player.containerMenu).getContainer(); + +- return container == ChestBlockEntity.this || container instanceof CompoundContainer && ((CompoundContainer) container).contains(ChestBlockEntity.this); ++ return iinventory == ChestBlockEntity.this || iinventory instanceof CompoundContainer && ((CompoundContainer) iinventory).contains(ChestBlockEntity.this); + } + } + }; + this.chestLidController = new ChestLidController(); + } + +- public ChestBlockEntity(BlockPos blockpos, BlockState blockstate) { +- this(BlockEntityType.CHEST, blockpos, blockstate); ++ public ChestBlockEntity(BlockPos pos, IBlockData blockState) { ++ this(BlockEntityType.CHEST, pos, blockState); + } + + @Override +- @Override + public int getContainerSize() { + return 27; + } + + @Override +- @Override + protected Component getDefaultName() { + return Component.translatable("container.chest"); + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); ++ public void load(CompoundTag tag) { ++ super.load(tag); + this.items = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); +- if (!this.tryLoadLootTable(compoundtag)) { +- ContainerHelper.loadAllItems(compoundtag, this.items); ++ if (!this.tryLoadLootTable(tag)) { ++ ContainerHelper.loadAllItems(tag, this.items); + } + + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); +- if (!this.trySaveLootTable(compoundtag)) { +- ContainerHelper.saveAllItems(compoundtag, this.items); ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); ++ if (!this.trySaveLootTable(tag)) { ++ ContainerHelper.saveAllItems(tag, this.items); + } + + } + +- public static void lidAnimateTick(Level level, BlockPos blockpos, BlockState blockstate, ChestBlockEntity chestblockentity) { +- chestblockentity.chestLidController.tickLid(); ++ public static void lidAnimateTick(Level level, BlockPos pos, IBlockData state, ChestBlockEntity blockEntity) { ++ blockEntity.chestLidController.tickLid(); + } + +- static void playSound(Level level, BlockPos blockpos, BlockState blockstate, SoundEvent soundevent) { +- ChestType chesttype = (ChestType) blockstate.getValue(ChestBlock.TYPE); ++ public static void playSound(Level level, BlockPos pos, IBlockData state, SoundEvent sound) { ++ ChestType blockpropertychesttype = (ChestType) state.getValue(ChestBlock.TYPE); + +- if (chesttype != ChestType.LEFT) { +- double d0 = (double) blockpos.getX() + 0.5D; +- double d1 = (double) blockpos.getY() + 0.5D; +- double d2 = (double) blockpos.getZ() + 0.5D; ++ if (blockpropertychesttype != ChestType.LEFT) { ++ double d0 = (double) pos.getX() + 0.5D; ++ double d1 = (double) pos.getY() + 0.5D; ++ double d2 = (double) pos.getZ() + 0.5D; + +- if (chesttype == ChestType.RIGHT) { +- Direction direction = ChestBlock.getConnectedDirection(blockstate); ++ if (blockpropertychesttype == ChestType.RIGHT) { ++ Direction enumdirection = ChestBlock.getConnectedDirection(state); + +- d0 += (double) direction.getStepX() * 0.5D; +- d2 += (double) direction.getStepZ() * 0.5D; ++ d0 += (double) enumdirection.getStepX() * 0.5D; ++ d2 += (double) enumdirection.getStepZ() * 0.5D; + } + +- level.playSound((Player) null, d0, d1, d2, soundevent, SoundSource.BLOCKS, 0.5F, level.random.nextFloat() * 0.1F + 0.9F); ++ level.playSound((Player) null, d0, d1, d2, sound, SoundSource.BLOCKS, 0.5F, level.random.nextFloat() * 0.1F + 0.9F); + } + } + + @Override +- @Override +- public boolean triggerEvent(int i, int j) { +- if (i == 1) { +- this.chestLidController.shouldBeOpen(j > 0); ++ public boolean triggerEvent(int id, int type) { ++ if (id == 1) { ++ this.chestLidController.shouldBeOpen(type > 0); + return true; + } else { +- return super.triggerEvent(i, j); ++ return super.triggerEvent(id, type); + } + } + + @Override +- @Override + public void startOpen(Player player) { + if (!this.remove && !player.isSpectator()) { + this.openersCounter.incrementOpeners(player, this.getLevel(), this.getBlockPos(), this.getBlockState()); +@@ -148,7 +173,6 @@ + } + + @Override +- @Override + public void stopOpen(Player player) { + if (!this.remove && !player.isSpectator()) { + this.openersCounter.decrementOpeners(player, this.getLevel(), this.getBlockPos(), this.getBlockState()); +@@ -157,48 +181,44 @@ + } + + @Override +- @Override + protected NonNullList getItems() { + return this.items; + } + + @Override +- @Override +- protected void setItems(NonNullList nonnulllist) { +- this.items = nonnulllist; ++ protected void setItems(NonNullList items) { ++ this.items = items; + } + + @Override +- @Override +- public float getOpenNess(float f) { +- return this.chestLidController.getOpenness(f); ++ public float getOpenNess(float partialTicks) { ++ return this.chestLidController.getOpenness(partialTicks); + } + +- public static int getOpenCount(BlockGetter blockgetter, BlockPos blockpos) { +- BlockState blockstate = blockgetter.getBlockState(blockpos); ++ public static int getOpenCount(BlockGetter level, BlockPos pos) { ++ IBlockData iblockdata = level.getBlockState(pos); + +- if (blockstate.hasBlockEntity()) { +- BlockEntity blockentity = blockgetter.getBlockEntity(blockpos); ++ if (iblockdata.hasBlockEntity()) { ++ BlockEntity tileentity = level.getBlockEntity(pos); + +- if (blockentity instanceof ChestBlockEntity) { +- return ((ChestBlockEntity) blockentity).openersCounter.getOpenerCount(); ++ if (tileentity instanceof ChestBlockEntity) { ++ return ((ChestBlockEntity) tileentity).openersCounter.getOpenerCount(); + } + } + + return 0; + } + +- public static void swapContents(ChestBlockEntity chestblockentity, ChestBlockEntity chestblockentity1) { +- NonNullList nonnulllist = chestblockentity.getItems(); ++ public static void swapContents(ChestBlockEntity chest, ChestBlockEntity otherChest) { ++ NonNullList nonnulllist = chest.getItems(); + +- chestblockentity.setItems(chestblockentity1.getItems()); +- chestblockentity1.setItems(nonnulllist); ++ chest.setItems(otherChest.getItems()); ++ otherChest.setItems(nonnulllist); + } + + @Override +- @Override +- protected AbstractContainerMenu createMenu(int i, Inventory inventory) { +- return ChestMenu.threeRows(i, inventory, this); ++ protected AbstractContainerMenu createMenu(int id, Inventory player) { ++ return ChestMenu.threeRows(id, player, this); + } + + public void recheckOpen() { +@@ -208,9 +228,16 @@ + + } + +- protected void signalOpenCount(Level level, BlockPos blockpos, BlockState blockstate, int i, int j) { +- Block block = blockstate.getBlock(); ++ protected void signalOpenCount(Level level, BlockPos pos, IBlockData state, int eventId, int eventParam) { ++ Block block = state.getBlock(); + +- level.blockEvent(blockpos, block, 1, j); ++ level.blockEvent(pos, block, 1, eventParam); + } ++ ++ // CraftBukkit start ++ @Override ++ public boolean onlyOpCanSetNbt() { ++ return true; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java.patch new file mode 100644 index 0000000000..5fcfc2ef82 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java.patch @@ -0,0 +1,226 @@ +--- a/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java +@@ -13,56 +13,97 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.ChiseledBookShelfBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.gameevent.GameEvent; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class ChiseledBookShelfBlockEntity extends BlockEntity implements Container { + + public static final int MAX_BOOKS_IN_STORAGE = 6; + private static final Logger LOGGER = LogUtils.getLogger(); + private final NonNullList items; +- private int lastInteractedSlot; ++ public int lastInteractedSlot; ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList<>(); ++ private int maxStack = 1; + +- public ChiseledBookShelfBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.CHISELED_BOOKSHELF, blockpos, blockstate); ++ @Override ++ public List getContents() { ++ return this.items; ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ } ++ // CraftBukkit end ++ ++ public ChiseledBookShelfBlockEntity(BlockPos pos, IBlockData state) { ++ super(BlockEntityType.CHISELED_BOOKSHELF, pos, state); + this.items = NonNullList.withSize(6, ItemStack.EMPTY); + this.lastInteractedSlot = -1; + } + +- private void updateState(int i) { +- if (i >= 0 && i < 6) { +- this.lastInteractedSlot = i; +- BlockState blockstate = this.getBlockState(); ++ private void updateState(int slot) { ++ if (slot >= 0 && slot < 6) { ++ this.lastInteractedSlot = slot; ++ IBlockData iblockdata = this.getBlockState(); + + for (int j = 0; j < ChiseledBookShelfBlock.SLOT_OCCUPIED_PROPERTIES.size(); ++j) { + boolean flag = !this.getItem(j).isEmpty(); +- BooleanProperty booleanproperty = (BooleanProperty) ChiseledBookShelfBlock.SLOT_OCCUPIED_PROPERTIES.get(j); ++ BooleanProperty blockstateboolean = (BooleanProperty) ChiseledBookShelfBlock.SLOT_OCCUPIED_PROPERTIES.get(j); + +- blockstate = (BlockState) blockstate.setValue(booleanproperty, flag); ++ iblockdata = (IBlockData) iblockdata.setValue(blockstateboolean, flag); + } + +- ((Level) Objects.requireNonNull(this.level)).setBlock(this.worldPosition, blockstate, 3); +- this.level.gameEvent(GameEvent.BLOCK_CHANGE, this.worldPosition, GameEvent.Context.of(blockstate)); ++ ((Level) Objects.requireNonNull(this.level)).setBlock(this.worldPosition, iblockdata, 3); ++ this.level.gameEvent(GameEvent.BLOCK_CHANGE, this.worldPosition, GameEvent.Context.of(iblockdata)); + } else { +- ChiseledBookShelfBlockEntity.LOGGER.error("Expected slot 0-5, got {}", i); ++ ChiseledBookShelfBlockEntity.LOGGER.error("Expected slot 0-5, got {}", slot); + } + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { ++ public void load(CompoundTag tag) { ++ super.load(tag); // CraftBukkit - SPIGOT-7393: Load super Bukkit data + this.items.clear(); +- ContainerHelper.loadAllItems(compoundtag, this.items); +- this.lastInteractedSlot = compoundtag.getInt("last_interacted_slot"); ++ ContainerHelper.loadAllItems(tag, this.items); ++ this.lastInteractedSlot = tag.getInt("last_interacted_slot"); + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- ContainerHelper.saveAllItems(compoundtag, this.items, true); +- compoundtag.putInt("last_interacted_slot", this.lastInteractedSlot); ++ protected void saveAdditional(CompoundTag tag) { ++ ContainerHelper.saveAllItems(tag, this.items, true); ++ tag.putInt("last_interacted_slot", this.lastInteractedSlot); + } + + public int count() { +@@ -70,84 +111,73 @@ + } + + @Override +- @Override + public void clearContent() { + this.items.clear(); + } + + @Override +- @Override + public int getContainerSize() { + return 6; + } + + @Override +- @Override + public boolean isEmpty() { + return this.items.stream().allMatch(ItemStack::isEmpty); + } + + @Override +- @Override +- public ItemStack getItem(int i) { +- return (ItemStack) this.items.get(i); ++ public ItemStack getItem(int slot) { ++ return (ItemStack) this.items.get(slot); + } + + @Override +- @Override +- public ItemStack removeItem(int i, int j) { +- ItemStack itemstack = (ItemStack) Objects.requireNonNullElse((ItemStack) this.items.get(i), ItemStack.EMPTY); ++ public ItemStack removeItem(int slot, int amount) { ++ ItemStack itemstack = (ItemStack) Objects.requireNonNullElse((ItemStack) this.items.get(slot), ItemStack.EMPTY); + +- this.items.set(i, ItemStack.EMPTY); ++ this.items.set(slot, ItemStack.EMPTY); + if (!itemstack.isEmpty()) { +- this.updateState(i); ++ if (level != null) this.updateState(slot); // CraftBukkit - SPIGOT-7381: check for null world + } + + return itemstack; + } + + @Override +- @Override +- public ItemStack removeItemNoUpdate(int i) { +- return this.removeItem(i, 1); ++ public ItemStack removeItemNoUpdate(int slot) { ++ return this.removeItem(slot, 1); + } + + @Override +- @Override +- public void setItem(int i, ItemStack itemstack) { +- if (itemstack.is(ItemTags.BOOKSHELF_BOOKS)) { +- this.items.set(i, itemstack); +- this.updateState(i); +- } else if (itemstack.isEmpty()) { +- this.removeItem(i, 1); ++ public void setItem(int slot, ItemStack stack) { ++ if (stack.is(ItemTags.BOOKSHELF_BOOKS)) { ++ this.items.set(slot, stack); ++ if (level != null) this.updateState(slot); // CraftBukkit - SPIGOT-7381: check for null world ++ } else if (stack.isEmpty()) { ++ this.removeItem(slot, 1); + } + + } + + @Override +- @Override +- public boolean canTakeItem(Container container, int i, ItemStack itemstack) { +- return container.hasAnyMatching((itemstack1) -> { +- return itemstack1.isEmpty() ? true : ItemStack.isSameItemSameTags(itemstack, itemstack1) && itemstack1.getCount() + itemstack.getCount() <= Math.min(itemstack1.getMaxStackSize(), container.getMaxStackSize()); ++ public boolean canTakeItem(Container target, int index, ItemStack stack) { ++ return target.hasAnyMatching((itemstack1) -> { ++ return itemstack1.isEmpty() ? true : ItemStack.isSameItemSameTags(stack, itemstack1) && itemstack1.getCount() + stack.getCount() <= Math.min(itemstack1.getMaxStackSize(), target.getMaxStackSize()); + }); + } + + @Override +- @Override + public int getMaxStackSize() { +- return 1; ++ return maxStack; // CraftBukkit + } + + @Override +- @Override + public boolean stillValid(Player player) { + return Container.stillValidBlockEntity(this, player); + } + + @Override +- @Override +- public boolean canPlaceItem(int i, ItemStack itemstack) { +- return itemstack.is(ItemTags.BOOKSHELF_BOOKS) && this.getItem(i).isEmpty() && itemstack.getCount() == this.getMaxStackSize(); ++ public boolean canPlaceItem(int index, ItemStack stack) { ++ return stack.is(ItemTags.BOOKSHELF_BOOKS) && this.getItem(index).isEmpty() && stack.getCount() == this.getMaxStackSize(); + } + + public int getLastInteractedSlot() { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/CommandBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/CommandBlockEntity.java.patch new file mode 100644 index 0000000000..551f8d0fe2 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/CommandBlockEntity.java.patch @@ -0,0 +1,196 @@ +--- a/net/minecraft/world/level/block/entity/CommandBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/CommandBlockEntity.java +@@ -10,7 +10,7 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.CommandBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; + +@@ -20,74 +20,72 @@ + private boolean auto; + private boolean conditionMet; + private final BaseCommandBlock commandBlock = new BaseCommandBlock() { ++ // CraftBukkit start + @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return new org.bukkit.craftbukkit.command.CraftBlockCommandSender(wrapper, CommandBlockEntity.this); ++ } ++ // CraftBukkit end ++ + @Override +- public void setCommand(String s) { +- super.setCommand(s); ++ public void setCommand(String command) { ++ super.setCommand(command); + CommandBlockEntity.this.setChanged(); + } + + @Override +- @Override + public ServerLevel getLevel() { + return (ServerLevel) CommandBlockEntity.this.level; + } + + @Override +- @Override + public void onUpdated() { +- BlockState blockstate = CommandBlockEntity.this.level.getBlockState(CommandBlockEntity.this.worldPosition); ++ IBlockData iblockdata = CommandBlockEntity.this.level.getBlockState(CommandBlockEntity.this.worldPosition); + +- this.getLevel().sendBlockUpdated(CommandBlockEntity.this.worldPosition, blockstate, blockstate, 3); ++ this.getLevel().sendBlockUpdated(CommandBlockEntity.this.worldPosition, iblockdata, iblockdata, 3); + } + + @Override +- @Override + public Vec3 getPosition() { + return Vec3.atCenterOf(CommandBlockEntity.this.worldPosition); + } + + @Override +- @Override + public CommandSourceStack createCommandSourceStack() { +- Direction direction = (Direction) CommandBlockEntity.this.getBlockState().getValue(CommandBlock.FACING); ++ Direction enumdirection = (Direction) CommandBlockEntity.this.getBlockState().getValue(CommandBlock.FACING); + +- return new CommandSourceStack(this, Vec3.atCenterOf(CommandBlockEntity.this.worldPosition), new Vec2(0.0F, direction.toYRot()), this.getLevel(), 2, this.getName().getString(), this.getName(), this.getLevel().getServer(), (Entity) null); ++ return new CommandSourceStack(this, Vec3.atCenterOf(CommandBlockEntity.this.worldPosition), new Vec2(0.0F, enumdirection.toYRot()), this.getLevel(), 2, this.getName().getString(), this.getName(), this.getLevel().getServer(), (Entity) null); + } + + @Override +- @Override + public boolean isValid() { + return !CommandBlockEntity.this.isRemoved(); + } + }; + +- public CommandBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.COMMAND_BLOCK, blockpos, blockstate); ++ public CommandBlockEntity(BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.COMMAND_BLOCK, pos, blockState); + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); +- this.commandBlock.save(compoundtag); +- compoundtag.putBoolean("powered", this.isPowered()); +- compoundtag.putBoolean("conditionMet", this.wasConditionMet()); +- compoundtag.putBoolean("auto", this.isAutomatic()); ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); ++ this.commandBlock.save(tag); ++ tag.putBoolean("powered", this.isPowered()); ++ tag.putBoolean("conditionMet", this.wasConditionMet()); ++ tag.putBoolean("auto", this.isAutomatic()); + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); +- this.commandBlock.load(compoundtag); +- this.powered = compoundtag.getBoolean("powered"); +- this.conditionMet = compoundtag.getBoolean("conditionMet"); +- this.setAutomatic(compoundtag.getBoolean("auto")); ++ public void load(CompoundTag tag) { ++ super.load(tag); ++ this.commandBlock.load(tag); ++ this.powered = tag.getBoolean("powered"); ++ this.conditionMet = tag.getBoolean("conditionMet"); ++ this.setAutomatic(tag.getBoolean("auto")); + } + + @Override +- @Override + public boolean onlyOpCanSetNbt() { + return true; + } +@@ -96,8 +94,8 @@ + return this.commandBlock; + } + +- public void setPowered(boolean flag) { +- this.powered = flag; ++ public void setPowered(boolean powered) { ++ this.powered = powered; + } + + public boolean isPowered() { +@@ -108,20 +106,20 @@ + return this.auto; + } + +- public void setAutomatic(boolean flag) { ++ public void setAutomatic(boolean auto) { + boolean flag1 = this.auto; + +- this.auto = flag; +- if (!flag1 && flag && !this.powered && this.level != null && this.getMode() != CommandBlockEntity.Mode.SEQUENCE) { ++ this.auto = auto; ++ if (!flag1 && auto && !this.powered && this.level != null && this.getMode() != CommandBlockEntity.Type.SEQUENCE) { + this.scheduleTick(); + } + + } + + public void onModeSwitch() { +- CommandBlockEntity.Mode commandblockentity_mode = this.getMode(); ++ CommandBlockEntity.Type tileentitycommand_type = this.getMode(); + +- if (commandblockentity_mode == CommandBlockEntity.Mode.AUTO && (this.powered || this.auto) && this.level != null) { ++ if (tileentitycommand_type == CommandBlockEntity.Type.AUTO && (this.powered || this.auto) && this.level != null) { + this.scheduleTick(); + } + +@@ -144,12 +142,12 @@ + public boolean markConditionMet() { + this.conditionMet = true; + if (this.isConditional()) { +- BlockPos blockpos = this.worldPosition.relative(((Direction) this.level.getBlockState(this.worldPosition).getValue(CommandBlock.FACING)).getOpposite()); ++ BlockPos blockposition = this.worldPosition.relative(((Direction) this.level.getBlockState(this.worldPosition).getValue(CommandBlock.FACING)).getOpposite()); + +- if (this.level.getBlockState(blockpos).getBlock() instanceof CommandBlock) { +- BlockEntity blockentity = this.level.getBlockEntity(blockpos); ++ if (this.level.getBlockState(blockposition).getBlock() instanceof CommandBlock) { ++ BlockEntity tileentity = this.level.getBlockEntity(blockposition); + +- this.conditionMet = blockentity instanceof CommandBlockEntity && ((CommandBlockEntity) blockentity).getCommandBlock().getSuccessCount() > 0; ++ this.conditionMet = tileentity instanceof CommandBlockEntity && ((CommandBlockEntity) tileentity).getCommandBlock().getSuccessCount() > 0; + } else { + this.conditionMet = false; + } +@@ -158,22 +156,22 @@ + return this.conditionMet; + } + +- public CommandBlockEntity.Mode getMode() { +- BlockState blockstate = this.getBlockState(); ++ public CommandBlockEntity.Type getMode() { ++ IBlockData iblockdata = this.getBlockState(); + +- return blockstate.is(Blocks.COMMAND_BLOCK) ? CommandBlockEntity.Mode.REDSTONE : (blockstate.is(Blocks.REPEATING_COMMAND_BLOCK) ? CommandBlockEntity.Mode.AUTO : (blockstate.is(Blocks.CHAIN_COMMAND_BLOCK) ? CommandBlockEntity.Mode.SEQUENCE : CommandBlockEntity.Mode.REDSTONE)); ++ return iblockdata.is(Blocks.COMMAND_BLOCK) ? CommandBlockEntity.Type.REDSTONE : (iblockdata.is(Blocks.REPEATING_COMMAND_BLOCK) ? CommandBlockEntity.Type.AUTO : (iblockdata.is(Blocks.CHAIN_COMMAND_BLOCK) ? CommandBlockEntity.Type.SEQUENCE : CommandBlockEntity.Type.REDSTONE)); + } + + public boolean isConditional() { +- BlockState blockstate = this.level.getBlockState(this.getBlockPos()); ++ IBlockData iblockdata = this.level.getBlockState(this.getBlockPos()); + +- return blockstate.getBlock() instanceof CommandBlock ? (Boolean) blockstate.getValue(CommandBlock.CONDITIONAL) : false; ++ return iblockdata.getBlock() instanceof CommandBlock ? (Boolean) iblockdata.getValue(CommandBlock.CONDITIONAL) : false; + } + +- public static enum Mode { ++ public static enum Type { + + SEQUENCE, AUTO, REDSTONE; + +- private Mode() {} ++ private Type() {} + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/ConduitBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/ConduitBlockEntity.java.patch new file mode 100644 index 0000000000..659edbd9c6 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/ConduitBlockEntity.java.patch @@ -0,0 +1,402 @@ +--- a/net/minecraft/world/level/block/entity/ConduitBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/ConduitBlockEntity.java +@@ -18,14 +18,18 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.monster.Enemy; ++import net.minecraft.world.entity.monster.IMonster; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class ConduitBlockEntity extends BlockEntity { + +@@ -47,16 +51,15 @@ + private UUID destroyTargetUUID; + private long nextAmbientSoundActivation; + +- public ConduitBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.CONDUIT, blockpos, blockstate); ++ public ConduitBlockEntity(BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.CONDUIT, pos, blockState); + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); +- if (compoundtag.hasUUID("Target")) { +- this.destroyTargetUUID = compoundtag.getUUID("Target"); ++ public void load(CompoundTag tag) { ++ super.load(tag); ++ if (tag.hasUUID("Target")) { ++ this.destroyTargetUUID = tag.getUUID("Target"); + } else { + this.destroyTargetUUID = null; + } +@@ -64,86 +67,83 @@ + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); + if (this.destroyTarget != null) { +- compoundtag.putUUID("Target", this.destroyTarget.getUUID()); ++ tag.putUUID("Target", this.destroyTarget.getUUID()); + } + + } + + @Override +- @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + @Override +- @Override + public CompoundTag getUpdateTag() { + return this.saveWithoutMetadata(); + } + +- public static void clientTick(Level level, BlockPos blockpos, BlockState blockstate, ConduitBlockEntity conduitblockentity) { +- ++conduitblockentity.tickCount; ++ public static void clientTick(Level level, BlockPos pos, IBlockData state, ConduitBlockEntity blockEntity) { ++ ++blockEntity.tickCount; + long i = level.getGameTime(); +- List list = conduitblockentity.effectBlocks; ++ List list = blockEntity.effectBlocks; + + if (i % 40L == 0L) { +- conduitblockentity.isActive = updateShape(level, blockpos, list); +- updateHunting(conduitblockentity, list); ++ blockEntity.isActive = updateShape(level, pos, list); ++ updateHunting(blockEntity, list); + } + +- updateClientTarget(level, blockpos, conduitblockentity); +- animationTick(level, blockpos, list, conduitblockentity.destroyTarget, conduitblockentity.tickCount); +- if (conduitblockentity.isActive()) { +- ++conduitblockentity.activeRotation; ++ updateClientTarget(level, pos, blockEntity); ++ animationTick(level, pos, list, blockEntity.destroyTarget, blockEntity.tickCount); ++ if (blockEntity.isActive()) { ++ ++blockEntity.activeRotation; + } + + } + +- public static void serverTick(Level level, BlockPos blockpos, BlockState blockstate, ConduitBlockEntity conduitblockentity) { +- ++conduitblockentity.tickCount; ++ public static void serverTick(Level level, BlockPos pos, IBlockData state, ConduitBlockEntity blockEntity) { ++ ++blockEntity.tickCount; + long i = level.getGameTime(); +- List list = conduitblockentity.effectBlocks; ++ List list = blockEntity.effectBlocks; + + if (i % 40L == 0L) { +- boolean flag = updateShape(level, blockpos, list); ++ boolean flag = updateShape(level, pos, list); + +- if (flag != conduitblockentity.isActive) { +- SoundEvent soundevent = flag ? SoundEvents.CONDUIT_ACTIVATE : SoundEvents.CONDUIT_DEACTIVATE; ++ if (flag != blockEntity.isActive) { ++ SoundEvent soundeffect = flag ? SoundEvents.CONDUIT_ACTIVATE : SoundEvents.CONDUIT_DEACTIVATE; + +- level.playSound((Player) null, blockpos, soundevent, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.playSound((Player) null, pos, soundeffect, SoundSource.BLOCKS, 1.0F, 1.0F); + } + +- conduitblockentity.isActive = flag; +- updateHunting(conduitblockentity, list); ++ blockEntity.isActive = flag; ++ updateHunting(blockEntity, list); + if (flag) { +- applyEffects(level, blockpos, list); +- updateDestroyTarget(level, blockpos, blockstate, list, conduitblockentity); ++ applyEffects(level, pos, list); ++ updateDestroyTarget(level, pos, state, list, blockEntity); + } + } + +- if (conduitblockentity.isActive()) { ++ if (blockEntity.isActive()) { + if (i % 80L == 0L) { +- level.playSound((Player) null, blockpos, SoundEvents.CONDUIT_AMBIENT, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.playSound((Player) null, pos, SoundEvents.CONDUIT_AMBIENT, SoundSource.BLOCKS, 1.0F, 1.0F); + } + +- if (i > conduitblockentity.nextAmbientSoundActivation) { +- conduitblockentity.nextAmbientSoundActivation = i + 60L + (long) level.getRandom().nextInt(40); +- level.playSound((Player) null, blockpos, SoundEvents.CONDUIT_AMBIENT_SHORT, SoundSource.BLOCKS, 1.0F, 1.0F); ++ if (i > blockEntity.nextAmbientSoundActivation) { ++ blockEntity.nextAmbientSoundActivation = i + 60L + (long) level.getRandom().nextInt(40); ++ level.playSound((Player) null, pos, SoundEvents.CONDUIT_AMBIENT_SHORT, SoundSource.BLOCKS, 1.0F, 1.0F); + } + } + + } + +- private static void updateHunting(ConduitBlockEntity conduitblockentity, List list) { +- conduitblockentity.setHunting(list.size() >= 42); ++ private static void updateHunting(ConduitBlockEntity blockEntity, List positions) { ++ blockEntity.setHunting(positions.size() >= 42); + } + +- private static boolean updateShape(Level level, BlockPos blockpos, List list) { +- list.clear(); ++ private static boolean updateShape(Level level, BlockPos pos, List positions) { ++ positions.clear(); + + int i; + int j; +@@ -152,9 +152,9 @@ + for (i = -1; i <= 1; ++i) { + for (j = -1; j <= 1; ++j) { + for (k = -1; k <= 1; ++k) { +- BlockPos blockpos1 = blockpos.offset(i, j, k); ++ BlockPos blockposition1 = pos.offset(i, j, k); + +- if (!level.isWaterAt(blockpos1)) { ++ if (!level.isWaterAt(blockposition1)) { + return false; + } + } +@@ -169,16 +169,16 @@ + int j1 = Math.abs(k); + + if ((l > 1 || i1 > 1 || j1 > 1) && (i == 0 && (i1 == 2 || j1 == 2) || j == 0 && (l == 2 || j1 == 2) || k == 0 && (l == 2 || i1 == 2))) { +- BlockPos blockpos2 = blockpos.offset(i, j, k); +- BlockState blockstate = level.getBlockState(blockpos2); ++ BlockPos blockposition2 = pos.offset(i, j, k); ++ IBlockData iblockdata = level.getBlockState(blockposition2); + Block[] ablock = ConduitBlockEntity.VALID_BLOCKS; + int k1 = ablock.length; + + for (int l1 = 0; l1 < k1; ++l1) { + Block block = ablock[l1]; + +- if (blockstate.is(block)) { +- list.add(blockpos2); ++ if (iblockdata.is(block)) { ++ positions.add(blockposition2); + } + } + } +@@ -186,126 +186,131 @@ + } + } + +- return list.size() >= 16; ++ return positions.size() >= 16; + } + +- private static void applyEffects(Level level, BlockPos blockpos, List list) { +- int i = list.size(); ++ private static void applyEffects(Level level, BlockPos pos, List positions) { ++ int i = positions.size(); + int j = i / 7 * 16; +- int k = blockpos.getX(); +- int l = blockpos.getY(); +- int i1 = blockpos.getZ(); +- AABB aabb = (new AABB((double) k, (double) l, (double) i1, (double) (k + 1), (double) (l + 1), (double) (i1 + 1))).inflate((double) j).expandTowards(0.0D, (double) level.getHeight(), 0.0D); +- List list1 = level.getEntitiesOfClass(Player.class, aabb); ++ int k = pos.getX(); ++ int l = pos.getY(); ++ int i1 = pos.getZ(); ++ AABB axisalignedbb = (new AABB((double) k, (double) l, (double) i1, (double) (k + 1), (double) (l + 1), (double) (i1 + 1))).inflate((double) j).expandTowards(0.0D, (double) level.getHeight(), 0.0D); ++ List list1 = level.getEntitiesOfClass(Player.class, axisalignedbb); + + if (!list1.isEmpty()) { + Iterator iterator = list1.iterator(); + + while (iterator.hasNext()) { +- Player player = (Player) iterator.next(); ++ Player entityhuman = (Player) iterator.next(); + +- if (blockpos.closerThan(player.blockPosition(), (double) j) && player.isInWaterOrRain()) { +- player.addEffect(new MobEffectInstance(MobEffects.CONDUIT_POWER, 260, 0, true, true)); ++ if (pos.closerThan(entityhuman.blockPosition(), (double) j) && entityhuman.isInWaterOrRain()) { ++ entityhuman.addEffect(new MobEffectInstance(MobEffects.CONDUIT_POWER, 260, 0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONDUIT); // CraftBukkit + } + } + + } + } + +- private static void updateDestroyTarget(Level level, BlockPos blockpos, BlockState blockstate, List list, ConduitBlockEntity conduitblockentity) { +- LivingEntity livingentity = conduitblockentity.destroyTarget; +- int i = list.size(); ++ private static void updateDestroyTarget(Level level, BlockPos pos, IBlockData state, List positions, ConduitBlockEntity blockEntity) { ++ LivingEntity entityliving = blockEntity.destroyTarget; ++ int i = positions.size(); + + if (i < 42) { +- conduitblockentity.destroyTarget = null; +- } else if (conduitblockentity.destroyTarget == null && conduitblockentity.destroyTargetUUID != null) { +- conduitblockentity.destroyTarget = findDestroyTarget(level, blockpos, conduitblockentity.destroyTargetUUID); +- conduitblockentity.destroyTargetUUID = null; +- } else if (conduitblockentity.destroyTarget == null) { +- List list1 = level.getEntitiesOfClass(LivingEntity.class, getDestroyRangeAABB(blockpos), (livingentity1) -> { +- return livingentity1 instanceof Enemy && livingentity1.isInWaterOrRain(); ++ blockEntity.destroyTarget = null; ++ } else if (blockEntity.destroyTarget == null && blockEntity.destroyTargetUUID != null) { ++ blockEntity.destroyTarget = findDestroyTarget(level, pos, blockEntity.destroyTargetUUID); ++ blockEntity.destroyTargetUUID = null; ++ } else if (blockEntity.destroyTarget == null) { ++ List list1 = level.getEntitiesOfClass(LivingEntity.class, getDestroyRangeAABB(pos), (entityliving1) -> { ++ return entityliving1 instanceof IMonster && entityliving1.isInWaterOrRain(); + }); + + if (!list1.isEmpty()) { +- conduitblockentity.destroyTarget = (LivingEntity) list1.get(level.random.nextInt(list1.size())); ++ blockEntity.destroyTarget = (LivingEntity) list1.get(level.random.nextInt(list1.size())); + } +- } else if (!conduitblockentity.destroyTarget.isAlive() || !blockpos.closerThan(conduitblockentity.destroyTarget.blockPosition(), 8.0D)) { +- conduitblockentity.destroyTarget = null; ++ } else if (!blockEntity.destroyTarget.isAlive() || !pos.closerThan(blockEntity.destroyTarget.blockPosition(), 8.0D)) { ++ blockEntity.destroyTarget = null; + } + +- if (conduitblockentity.destroyTarget != null) { +- level.playSound((Player) null, conduitblockentity.destroyTarget.getX(), conduitblockentity.destroyTarget.getY(), conduitblockentity.destroyTarget.getZ(), SoundEvents.CONDUIT_ATTACK_TARGET, SoundSource.BLOCKS, 1.0F, 1.0F); +- conduitblockentity.destroyTarget.hurt(level.damageSources().magic(), 4.0F); ++ if (blockEntity.destroyTarget != null) { ++ // CraftBukkit start ++ CraftEventFactory.blockDamage = CraftBlock.at(level, pos); ++ if (blockEntity.destroyTarget.hurt(level.damageSources().magic(), 4.0F)) { ++ level.playSound((Player) null, blockEntity.destroyTarget.getX(), blockEntity.destroyTarget.getY(), blockEntity.destroyTarget.getZ(), SoundEvents.CONDUIT_ATTACK_TARGET, SoundSource.BLOCKS, 1.0F, 1.0F); ++ } ++ CraftEventFactory.blockDamage = null; ++ // CraftBukkit end + } + +- if (livingentity != conduitblockentity.destroyTarget) { +- level.sendBlockUpdated(blockpos, blockstate, blockstate, 2); ++ if (entityliving != blockEntity.destroyTarget) { ++ level.sendBlockUpdated(pos, state, state, 2); + } + + } + +- private static void updateClientTarget(Level level, BlockPos blockpos, ConduitBlockEntity conduitblockentity) { +- if (conduitblockentity.destroyTargetUUID == null) { +- conduitblockentity.destroyTarget = null; +- } else if (conduitblockentity.destroyTarget == null || !conduitblockentity.destroyTarget.getUUID().equals(conduitblockentity.destroyTargetUUID)) { +- conduitblockentity.destroyTarget = findDestroyTarget(level, blockpos, conduitblockentity.destroyTargetUUID); +- if (conduitblockentity.destroyTarget == null) { +- conduitblockentity.destroyTargetUUID = null; ++ private static void updateClientTarget(Level level, BlockPos pos, ConduitBlockEntity blockEntity) { ++ if (blockEntity.destroyTargetUUID == null) { ++ blockEntity.destroyTarget = null; ++ } else if (blockEntity.destroyTarget == null || !blockEntity.destroyTarget.getUUID().equals(blockEntity.destroyTargetUUID)) { ++ blockEntity.destroyTarget = findDestroyTarget(level, pos, blockEntity.destroyTargetUUID); ++ if (blockEntity.destroyTarget == null) { ++ blockEntity.destroyTargetUUID = null; + } + } + + } + +- private static AABB getDestroyRangeAABB(BlockPos blockpos) { +- int i = blockpos.getX(); +- int j = blockpos.getY(); +- int k = blockpos.getZ(); ++ private static AABB getDestroyRangeAABB(BlockPos pos) { ++ int i = pos.getX(); ++ int j = pos.getY(); ++ int k = pos.getZ(); + + return (new AABB((double) i, (double) j, (double) k, (double) (i + 1), (double) (j + 1), (double) (k + 1))).inflate(8.0D); + } + + @Nullable +- private static LivingEntity findDestroyTarget(Level level, BlockPos blockpos, UUID uuid) { +- List list = level.getEntitiesOfClass(LivingEntity.class, getDestroyRangeAABB(blockpos), (livingentity) -> { +- return livingentity.getUUID().equals(uuid); ++ private static LivingEntity findDestroyTarget(Level level, BlockPos pos, UUID targetId) { ++ List list = level.getEntitiesOfClass(LivingEntity.class, getDestroyRangeAABB(pos), (entityliving) -> { ++ return entityliving.getUUID().equals(targetId); + }); + + return list.size() == 1 ? (LivingEntity) list.get(0) : null; + } + +- private static void animationTick(Level level, BlockPos blockpos, List list, @Nullable Entity entity, int i) { ++ private static void animationTick(Level level, BlockPos pos, List positions, @Nullable Entity entity, int tickCount) { + RandomSource randomsource = level.random; +- double d0 = (double) (Mth.sin((float) (i + 35) * 0.1F) / 2.0F + 0.5F); ++ double d0 = (double) (Mth.sin((float) (tickCount + 35) * 0.1F) / 2.0F + 0.5F); + + d0 = (d0 * d0 + d0) * 0.30000001192092896D; +- Vec3 vec3 = new Vec3((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 1.5D + d0, (double) blockpos.getZ() + 0.5D); +- Iterator iterator = list.iterator(); ++ Vec3 vec3d = new Vec3((double) pos.getX() + 0.5D, (double) pos.getY() + 1.5D + d0, (double) pos.getZ() + 0.5D); ++ Iterator iterator = positions.iterator(); + + float f; + + while (iterator.hasNext()) { +- BlockPos blockpos1 = (BlockPos) iterator.next(); ++ BlockPos blockposition1 = (BlockPos) iterator.next(); + + if (randomsource.nextInt(50) == 0) { +- BlockPos blockpos2 = blockpos1.subtract(blockpos); ++ BlockPos blockposition2 = blockposition1.subtract(pos); + +- f = -0.5F + randomsource.nextFloat() + (float) blockpos2.getX(); +- float f1 = -2.0F + randomsource.nextFloat() + (float) blockpos2.getY(); +- float f2 = -0.5F + randomsource.nextFloat() + (float) blockpos2.getZ(); ++ f = -0.5F + randomsource.nextFloat() + (float) blockposition2.getX(); ++ float f1 = -2.0F + randomsource.nextFloat() + (float) blockposition2.getY(); ++ float f2 = -0.5F + randomsource.nextFloat() + (float) blockposition2.getZ(); + +- level.addParticle(ParticleTypes.NAUTILUS, vec3.x, vec3.y, vec3.z, (double) f, (double) f1, (double) f2); ++ level.addParticle(ParticleTypes.NAUTILUS, vec3d.x, vec3d.y, vec3d.z, (double) f, (double) f1, (double) f2); + } + } + + if (entity != null) { +- Vec3 vec31 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); ++ Vec3 vec3d1 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); + float f3 = (-0.5F + randomsource.nextFloat()) * (3.0F + entity.getBbWidth()); + float f4 = -1.0F + randomsource.nextFloat() * entity.getBbHeight(); + + f = (-0.5F + randomsource.nextFloat()) * (3.0F + entity.getBbWidth()); +- Vec3 vec32 = new Vec3((double) f3, (double) f4, (double) f); ++ Vec3 vec3d2 = new Vec3((double) f3, (double) f4, (double) f); + +- level.addParticle(ParticleTypes.NAUTILUS, vec31.x, vec31.y, vec31.z, vec32.x, vec32.y, vec32.z); ++ level.addParticle(ParticleTypes.NAUTILUS, vec3d1.x, vec3d1.y, vec3d1.z, vec3d2.x, vec3d2.y, vec3d2.z); + } + + } +@@ -318,11 +323,11 @@ + return this.isHunting; + } + +- private void setHunting(boolean flag) { +- this.isHunting = flag; ++ private void setHunting(boolean isHunting) { ++ this.isHunting = isHunting; + } + +- public float getActiveRotation(float f) { +- return (this.activeRotation + f) * -0.0375F; ++ public float getActiveRotation(float partialTick) { ++ return (this.activeRotation + partialTick) * -0.0375F; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java.patch new file mode 100644 index 0000000000..f82f58315d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java.patch @@ -0,0 +1,158 @@ +--- a/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java ++++ b/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java +@@ -4,7 +4,7 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.entity.EntityTypeTest; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; +@@ -13,52 +13,90 @@ + + private static final int CHECK_TICK_DELAY = 5; + private int openCount; ++ public boolean opened; // CraftBukkit + + public ContainerOpenersCounter() {} + +- protected abstract void onOpen(Level level, BlockPos pos, BlockState state); ++ protected abstract void onOpen(Level level, BlockPos pos, IBlockData state); + +- protected abstract void onClose(Level level, BlockPos pos, BlockState state); ++ protected abstract void onClose(Level level, BlockPos pos, IBlockData state); + +- protected abstract void openerCountChanged(Level level, BlockPos pos, BlockState state, int count, int openCount); ++ protected abstract void openerCountChanged(Level level, BlockPos pos, IBlockData state, int count, int openCount); + ++ // CraftBukkit start ++ public void onAPIOpen(Level world, BlockPos blockposition, IBlockData iblockdata) { ++ onOpen(world, blockposition, iblockdata); ++ } ++ ++ public void onAPIClose(Level world, BlockPos blockposition, IBlockData iblockdata) { ++ onClose(world, blockposition, iblockdata); ++ } ++ ++ public void openerAPICountChanged(Level world, BlockPos blockposition, IBlockData iblockdata, int i, int j) { ++ openerCountChanged(world, blockposition, iblockdata, i, j); ++ } ++ // CraftBukkit end ++ + protected abstract boolean isOwnContainer(Player player); + +- public void incrementOpeners(Player player, Level level, BlockPos blockpos, BlockState blockstate) { ++ public void incrementOpeners(Player player, Level level, BlockPos pos, IBlockData state) { ++ int oldPower = Math.max(0, Math.min(15, this.openCount)); // CraftBukkit - Get power before new viewer is added + int i = this.openCount++; + ++ // CraftBukkit start - Call redstone event ++ if (level.getBlockState(pos).is(net.minecraft.world.level.block.Blocks.TRAPPED_CHEST)) { ++ int newPower = Math.max(0, Math.min(15, this.openCount)); ++ ++ if (oldPower != newPower) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(level, pos, oldPower, newPower); ++ } ++ } ++ // CraftBukkit end ++ + if (i == 0) { +- this.onOpen(level, blockpos, blockstate); +- level.gameEvent((Entity) player, GameEvent.CONTAINER_OPEN, blockpos); +- scheduleRecheck(level, blockpos, blockstate); ++ this.onOpen(level, pos, state); ++ level.gameEvent((Entity) player, GameEvent.CONTAINER_OPEN, pos); ++ scheduleRecheck(level, pos, state); + } + +- this.openerCountChanged(level, blockpos, blockstate, i, this.openCount); ++ this.openerCountChanged(level, pos, state, i, this.openCount); + } + +- public void decrementOpeners(Player player, Level level, BlockPos blockpos, BlockState blockstate) { ++ public void decrementOpeners(Player player, Level level, BlockPos pos, IBlockData state) { ++ int oldPower = Math.max(0, Math.min(15, this.openCount)); // CraftBukkit - Get power before new viewer is added + int i = this.openCount--; + ++ // CraftBukkit start - Call redstone event ++ if (level.getBlockState(pos).is(net.minecraft.world.level.block.Blocks.TRAPPED_CHEST)) { ++ int newPower = Math.max(0, Math.min(15, this.openCount)); ++ ++ if (oldPower != newPower) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(level, pos, oldPower, newPower); ++ } ++ } ++ // CraftBukkit end ++ + if (this.openCount == 0) { +- this.onClose(level, blockpos, blockstate); +- level.gameEvent((Entity) player, GameEvent.CONTAINER_CLOSE, blockpos); ++ this.onClose(level, pos, state); ++ level.gameEvent((Entity) player, GameEvent.CONTAINER_CLOSE, pos); + } + +- this.openerCountChanged(level, blockpos, blockstate, i, this.openCount); ++ this.openerCountChanged(level, pos, state, i, this.openCount); + } + +- private int getOpenCount(Level level, BlockPos blockpos) { +- int i = blockpos.getX(); +- int j = blockpos.getY(); +- int k = blockpos.getZ(); ++ private int getOpenCount(Level level, BlockPos pos) { ++ int i = pos.getX(); ++ int j = pos.getY(); ++ int k = pos.getZ(); + float f = 5.0F; +- AABB aabb = new AABB((double) ((float) i - 5.0F), (double) ((float) j - 5.0F), (double) ((float) k - 5.0F), (double) ((float) (i + 1) + 5.0F), (double) ((float) (j + 1) + 5.0F), (double) ((float) (k + 1) + 5.0F)); ++ AABB axisalignedbb = new AABB((double) ((float) i - 5.0F), (double) ((float) j - 5.0F), (double) ((float) k - 5.0F), (double) ((float) (i + 1) + 5.0F), (double) ((float) (j + 1) + 5.0F), (double) ((float) (k + 1) + 5.0F)); + +- return level.getEntities(EntityTypeTest.forClass(Player.class), aabb, this::isOwnContainer).size(); ++ return level.getEntities(EntityTypeTest.forClass(Player.class), axisalignedbb, this::isOwnContainer).size(); + } + +- public void recheckOpeners(Level level, BlockPos blockpos, BlockState blockstate) { +- int i = this.getOpenCount(level, blockpos); ++ public void recheckOpeners(Level level, BlockPos pos, IBlockData state) { ++ int i = this.getOpenCount(level, pos); ++ if (opened) i++; // CraftBukkit - add dummy count from API + int j = this.openCount; + + if (j != i) { +@@ -66,19 +104,19 @@ + boolean flag1 = j != 0; + + if (flag && !flag1) { +- this.onOpen(level, blockpos, blockstate); +- level.gameEvent((Entity) null, GameEvent.CONTAINER_OPEN, blockpos); ++ this.onOpen(level, pos, state); ++ level.gameEvent((Entity) null, GameEvent.CONTAINER_OPEN, pos); + } else if (!flag) { +- this.onClose(level, blockpos, blockstate); +- level.gameEvent((Entity) null, GameEvent.CONTAINER_CLOSE, blockpos); ++ this.onClose(level, pos, state); ++ level.gameEvent((Entity) null, GameEvent.CONTAINER_CLOSE, pos); + } + + this.openCount = i; + } + +- this.openerCountChanged(level, blockpos, blockstate, j, i); ++ this.openerCountChanged(level, pos, state, j, i); + if (i > 0) { +- scheduleRecheck(level, blockpos, blockstate); ++ scheduleRecheck(level, pos, state); + } + + } +@@ -87,7 +125,7 @@ + return this.openCount; + } + +- private static void scheduleRecheck(Level level, BlockPos blockpos, BlockState blockstate) { +- level.scheduleTick(blockpos, blockstate.getBlock(), 5); ++ private static void scheduleRecheck(Level level, BlockPos pos, IBlockData state) { ++ level.scheduleTick(pos, state.getBlock(), 5); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/CrafterBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/CrafterBlockEntity.java.patch new file mode 100644 index 0000000000..032cf69b77 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/CrafterBlockEntity.java.patch @@ -0,0 +1,320 @@ +--- a/net/minecraft/world/level/block/entity/CrafterBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/CrafterBlockEntity.java +@@ -15,14 +15,20 @@ + import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.inventory.ContainerData; + import net.minecraft.world.inventory.CrafterMenu; +-import net.minecraft.world.inventory.CraftingContainer; ++import net.minecraft.world.inventory.InventoryCrafting; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.CrafterBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + +-public class CrafterBlockEntity extends RandomizableContainerBlockEntity implements CraftingContainer { ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end + ++public class CrafterBlockEntity extends RandomizableContainerBlockEntity implements InventoryCrafting { ++ + public static final int CONTAINER_WIDTH = 3; + public static final int CONTAINER_HEIGHT = 3; + public static final int CONTAINER_SIZE = 9; +@@ -31,11 +37,51 @@ + public static final int DATA_TRIGGERED = 9; + public static final int NUM_DATA = 10; + private NonNullList items; +- private int craftingTicksRemaining; ++ public int craftingTicksRemaining; + protected final ContainerData containerData; ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList<>(); ++ private int maxStack = 1; + +- public CrafterBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.CRAFTER, blockpos, blockstate); ++ @Override ++ public List getContents() { ++ return this.items; ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ @Override ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ } ++ // CraftBukkit end ++ ++ public CrafterBlockEntity(BlockPos blockposition, IBlockData iblockdata) { ++ super(BlockEntityType.CRAFTER, blockposition, iblockdata); + this.items = NonNullList.withSize(9, ItemStack.EMPTY); + this.craftingTicksRemaining = 0; + this.containerData = new ContainerData() { +@@ -43,24 +89,21 @@ + private int triggered = 0; + + @Override +- @Override +- public int get(int i) { +- return i == 9 ? this.triggered : this.slotStates[i]; ++ public int get(int index) { ++ return index == 9 ? this.triggered : this.slotStates[index]; + } + + @Override +- @Override +- public void set(int i, int j) { +- if (i == 9) { +- this.triggered = j; ++ public void set(int index, int value) { ++ if (index == 9) { ++ this.triggered = value; + } else { +- this.slotStates[i] = j; ++ this.slotStates[index] = value; + } + + } + + @Override +- @Override + public int getCount() { + return 10; + } +@@ -68,15 +111,13 @@ + } + + @Override +- @Override + protected Component getDefaultName() { + return Component.translatable("container.crafter"); + } + + @Override +- @Override +- protected AbstractContainerMenu createMenu(int i, Inventory inventory) { +- return new CrafterMenu(i, inventory, this, this.containerData); ++ protected AbstractContainerMenu createMenu(int containerId, Inventory inventory) { ++ return new CrafterMenu(containerId, inventory, this, this.containerData); + } + + public void setSlotState(int i, boolean flag) { +@@ -91,15 +132,14 @@ + } + + @Override +- @Override +- public boolean canPlaceItem(int i, ItemStack itemstack) { +- if (this.containerData.get(i) == 1) { ++ public boolean canPlaceItem(int index, ItemStack stack) { ++ if (this.containerData.get(index) == 1) { + return false; + } else { +- ItemStack itemstack1 = (ItemStack) this.items.get(i); ++ ItemStack itemstack1 = (ItemStack) this.items.get(index); + int j = itemstack1.getCount(); + +- return j >= itemstack1.getMaxStackSize() ? false : (itemstack1.isEmpty() ? true : !this.smallerStackExist(j, itemstack1, i)); ++ return j >= itemstack1.getMaxStackSize() ? false : (itemstack1.isEmpty() ? true : !this.smallerStackExist(j, itemstack1, index)); + } + } + +@@ -118,16 +158,15 @@ + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); +- this.craftingTicksRemaining = compoundtag.getInt("crafting_ticks_remaining"); ++ public void load(CompoundTag tag) { ++ super.load(tag); ++ this.craftingTicksRemaining = tag.getInt("crafting_ticks_remaining"); + this.items = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); +- if (!this.tryLoadLootTable(compoundtag)) { +- ContainerHelper.loadAllItems(compoundtag, this.items); ++ if (!this.tryLoadLootTable(tag)) { ++ ContainerHelper.loadAllItems(tag, this.items); + } + +- int[] aint = compoundtag.getIntArray("disabled_slots"); ++ int[] aint = tag.getIntArray("disabled_slots"); + + for (int i = 0; i < 9; ++i) { + this.containerData.set(i, 0); +@@ -144,30 +183,27 @@ + } + } + +- this.containerData.set(9, compoundtag.getInt("triggered")); ++ this.containerData.set(9, tag.getInt("triggered")); + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); +- compoundtag.putInt("crafting_ticks_remaining", this.craftingTicksRemaining); +- if (!this.trySaveLootTable(compoundtag)) { +- ContainerHelper.saveAllItems(compoundtag, this.items); ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); ++ tag.putInt("crafting_ticks_remaining", this.craftingTicksRemaining); ++ if (!this.trySaveLootTable(tag)) { ++ ContainerHelper.saveAllItems(tag, this.items); + } + +- this.addDisabledSlots(compoundtag); +- this.addTriggered(compoundtag); ++ this.addDisabledSlots(tag); ++ this.addTriggered(tag); + } + + @Override +- @Override + public int getContainerSize() { + return 9; + } + + @Override +- @Override + public boolean isEmpty() { + Iterator iterator = this.items.iterator(); + +@@ -185,65 +221,57 @@ + } + + @Override +- @Override +- public ItemStack getItem(int i) { +- return (ItemStack) this.items.get(i); ++ public ItemStack getItem(int slot) { ++ return (ItemStack) this.items.get(slot); + } + + @Override +- @Override +- public void setItem(int i, ItemStack itemstack) { +- if (this.isSlotDisabled(i)) { +- this.setSlotState(i, true); ++ public void setItem(int slot, ItemStack stack) { ++ if (this.isSlotDisabled(slot)) { ++ this.setSlotState(slot, true); + } + +- super.setItem(i, itemstack); ++ super.setItem(slot, stack); + } + + @Override +- @Override + public boolean stillValid(Player player) { + return this.level != null && this.level.getBlockEntity(this.worldPosition) == this ? player.distanceToSqr((double) this.worldPosition.getX() + 0.5D, (double) this.worldPosition.getY() + 0.5D, (double) this.worldPosition.getZ() + 0.5D) <= 64.0D : false; + } + + @Override +- @Override + public NonNullList getItems() { + return this.items; + } + + @Override +- @Override +- protected void setItems(NonNullList nonnulllist) { +- this.items = nonnulllist; ++ protected void setItems(NonNullList itemStacks) { ++ this.items = itemStacks; + } + + @Override +- @Override + public int getWidth() { + return 3; + } + + @Override +- @Override + public int getHeight() { + return 3; + } + + @Override +- @Override +- public void fillStackedContents(StackedContents stackedcontents) { ++ public void fillStackedContents(StackedContents contents) { + Iterator iterator = this.items.iterator(); + + while (iterator.hasNext()) { + ItemStack itemstack = (ItemStack) iterator.next(); + +- stackedcontents.accountSimpleStack(itemstack); ++ contents.accountSimpleStack(itemstack); + } + + } + +- private void addDisabledSlots(CompoundTag compoundtag) { ++ private void addDisabledSlots(CompoundTag nbttagcompound) { + IntArrayList intarraylist = new IntArrayList(); + + for (int i = 0; i < 9; ++i) { +@@ -252,11 +280,11 @@ + } + } + +- compoundtag.putIntArray("disabled_slots", (List) intarraylist); ++ nbttagcompound.putIntArray("disabled_slots", (List) intarraylist); + } + +- private void addTriggered(CompoundTag compoundtag) { +- compoundtag.putInt("triggered", this.containerData.get(9)); ++ private void addTriggered(CompoundTag nbttagcompound) { ++ nbttagcompound.putInt("triggered", this.containerData.get(9)); + } + + public void setTriggered(boolean flag) { +@@ -268,13 +296,13 @@ + return this.containerData.get(9) == 1; + } + +- public static void serverTick(Level level, BlockPos blockpos, BlockState blockstate, CrafterBlockEntity crafterblockentity) { ++ public static void serverTick(Level world, BlockPos blockposition, IBlockData iblockdata, CrafterBlockEntity crafterblockentity) { + int i = crafterblockentity.craftingTicksRemaining - 1; + + if (i >= 0) { + crafterblockentity.craftingTicksRemaining = i; + if (i == 0) { +- level.setBlock(blockpos, (BlockState) blockstate.setValue(CrafterBlock.CRAFTING, false), 3); ++ world.setBlock(blockposition, (IBlockData) iblockdata.setValue(CrafterBlock.CRAFTING, false), 3); + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java.patch new file mode 100644 index 0000000000..94b743e74c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java.patch @@ -0,0 +1,306 @@ +--- a/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java +@@ -17,49 +17,98 @@ + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.ticks.ContainerSingleItem; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class DecoratedPotBlockEntity extends BlockEntity implements RandomizableContainer, ContainerSingleItem { + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new ArrayList<>(); ++ private int maxStack = MAX_STACK; ++ ++ @Override ++ public List getContents() { ++ return Arrays.asList(this.item); ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ @Override ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return CraftLocation.toBukkit(worldPosition, level.getWorld()); ++ } ++ // CraftBukkit end ++ + public static final String TAG_SHERDS = "sherds"; + public static final String TAG_ITEM = "item"; + public static final int EVENT_POT_WOBBLES = 1; + public long wobbleStartedAtTick; + @Nullable +- public DecoratedPotBlockEntity.WobbleStyle lastWobbleStyle; +- private DecoratedPotBlockEntity.Decorations decorations; ++ public DecoratedPotBlockEntity.b lastWobbleStyle; ++ public DecoratedPotBlockEntity.Decorations decorations; + private ItemStack item; + @Nullable + protected ResourceLocation lootTable; + protected long lootTableSeed; + +- public DecoratedPotBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.DECORATED_POT, blockpos, blockstate); ++ public DecoratedPotBlockEntity(BlockPos pos, IBlockData state) { ++ super(BlockEntityType.DECORATED_POT, pos, state); + this.item = ItemStack.EMPTY; + this.decorations = DecoratedPotBlockEntity.Decorations.EMPTY; + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); +- this.decorations.save(compoundtag); +- if (!this.trySaveLootTable(compoundtag) && !this.item.isEmpty()) { +- compoundtag.put("item", this.item.save(new CompoundTag())); ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); ++ this.decorations.save(tag); ++ if (!this.trySaveLootTable(tag) && !this.item.isEmpty()) { ++ tag.put("item", this.item.save(new CompoundTag())); + } + + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); +- this.decorations = DecoratedPotBlockEntity.Decorations.load(compoundtag); +- if (!this.tryLoadLootTable(compoundtag)) { +- if (compoundtag.contains("item", 10)) { +- this.item = ItemStack.of(compoundtag.getCompound("item")); ++ public void load(CompoundTag tag) { ++ super.load(tag); ++ this.decorations = DecoratedPotBlockEntity.Decorations.load(tag); ++ if (!this.tryLoadLootTable(tag)) { ++ if (tag.contains("item", 10)) { ++ this.item = ItemStack.of(tag.getCompound("item")); + } else { + this.item = ItemStack.EMPTY; + } +@@ -68,13 +117,11 @@ + } + + @Override +- @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + @Override +- @Override + public CompoundTag getUpdateTag() { + return this.saveWithoutMetadata(); + } +@@ -87,56 +134,50 @@ + return this.decorations; + } + +- public void setFromItem(ItemStack itemstack) { +- this.decorations = DecoratedPotBlockEntity.Decorations.load(BlockItem.getBlockEntityData(itemstack)); ++ public void setFromItem(ItemStack item) { ++ this.decorations = DecoratedPotBlockEntity.Decorations.load(BlockItem.getBlockEntityData(item)); + } + + public ItemStack getPotAsItem() { + return createDecoratedPotItem(this.decorations); + } + +- public static ItemStack createDecoratedPotItem(DecoratedPotBlockEntity.Decorations decoratedpotblockentity_decorations) { ++ public static ItemStack createDecoratedPotItem(DecoratedPotBlockEntity.Decorations decoratedpotblockentity_decoration) { + ItemStack itemstack = Items.DECORATED_POT.getDefaultInstance(); +- CompoundTag compoundtag = decoratedpotblockentity_decorations.save(new CompoundTag()); ++ CompoundTag nbttagcompound = decoratedpotblockentity_decoration.save(new CompoundTag()); + +- BlockItem.setBlockEntityData(itemstack, BlockEntityType.DECORATED_POT, compoundtag); ++ BlockItem.setBlockEntityData(itemstack, BlockEntityType.DECORATED_POT, nbttagcompound); + return itemstack; + } + + @Nullable + @Override +- @Override + public ResourceLocation getLootTable() { + return this.lootTable; + } + + @Override +- @Override +- public void setLootTable(@Nullable ResourceLocation resourcelocation) { +- this.lootTable = resourcelocation; ++ public void setLootTable(@Nullable ResourceLocation minecraftkey) { ++ this.lootTable = minecraftkey; + } + + @Override +- @Override + public long getLootTableSeed() { + return this.lootTableSeed; + } + + @Override +- @Override + public void setLootTableSeed(long i) { + this.lootTableSeed = i; + } + + @Override +- @Override + public ItemStack getTheItem() { + this.unpackLootTable((Player) null); + return this.item; + } + + @Override +- @Override + public ItemStack splitTheItem(int i) { + this.unpackLootTable((Player) null); + ItemStack itemstack = this.item.split(i); +@@ -149,33 +190,30 @@ + } + + @Override +- @Override + public void setTheItem(ItemStack itemstack) { + this.unpackLootTable((Player) null); + this.item = itemstack; + } + + @Override +- @Override + public BlockEntity getContainerBlockEntity() { + return this; + } + +- public void wobble(DecoratedPotBlockEntity.WobbleStyle decoratedpotblockentity_wobblestyle) { ++ public void wobble(DecoratedPotBlockEntity.b decoratedpotblockentity_b) { + if (this.level != null && !this.level.isClientSide()) { +- this.level.blockEvent(this.getBlockPos(), this.getBlockState().getBlock(), 1, decoratedpotblockentity_wobblestyle.ordinal()); ++ this.level.blockEvent(this.getBlockPos(), this.getBlockState().getBlock(), 1, decoratedpotblockentity_b.ordinal()); + } + } + + @Override +- @Override +- public boolean triggerEvent(int i, int j) { +- if (this.level != null && i == 1 && j >= 0 && j < DecoratedPotBlockEntity.WobbleStyle.values().length) { ++ public boolean triggerEvent(int id, int type) { ++ if (this.level != null && id == 1 && type >= 0 && type < DecoratedPotBlockEntity.b.values().length) { + this.wobbleStartedAtTick = this.level.getGameTime(); +- this.lastWobbleStyle = DecoratedPotBlockEntity.WobbleStyle.values()[j]; ++ this.lastWobbleStyle = DecoratedPotBlockEntity.b.values()[type]; + return true; + } else { +- return super.triggerEvent(i, j); ++ return super.triggerEvent(id, type); + } + } + +@@ -183,17 +221,17 @@ + + public static final DecoratedPotBlockEntity.Decorations EMPTY = new DecoratedPotBlockEntity.Decorations(Items.BRICK, Items.BRICK, Items.BRICK, Items.BRICK); + +- public CompoundTag save(CompoundTag compoundtag) { ++ public CompoundTag save(CompoundTag tag) { + if (this.equals(DecoratedPotBlockEntity.Decorations.EMPTY)) { +- return compoundtag; ++ return tag; + } else { +- ListTag listtag = new ListTag(); ++ ListTag nbttaglist = new ListTag(); + + this.sorted().forEach((item) -> { +- listtag.add(StringTag.valueOf(BuiltInRegistries.ITEM.getKey(item).toString())); ++ nbttaglist.add(StringTag.valueOf(BuiltInRegistries.ITEM.getKey(item).toString())); + }); +- compoundtag.put("sherds", listtag); +- return compoundtag; ++ tag.put("sherds", nbttaglist); ++ return tag; + } + } + +@@ -201,34 +239,34 @@ + return Stream.of(this.back, this.left, this.right, this.front); + } + +- public static DecoratedPotBlockEntity.Decorations load(@Nullable CompoundTag compoundtag) { +- if (compoundtag != null && compoundtag.contains("sherds", 9)) { +- ListTag listtag = compoundtag.getList("sherds", 8); ++ public static DecoratedPotBlockEntity.Decorations load(@Nullable CompoundTag tag) { ++ if (tag != null && tag.contains("sherds", 9)) { ++ ListTag nbttaglist = tag.getList("sherds", 8); + +- return new DecoratedPotBlockEntity.Decorations(itemFromTag(listtag, 0), itemFromTag(listtag, 1), itemFromTag(listtag, 2), itemFromTag(listtag, 3)); ++ return new DecoratedPotBlockEntity.Decorations(itemFromTag(nbttaglist, 0), itemFromTag(nbttaglist, 1), itemFromTag(nbttaglist, 2), itemFromTag(nbttaglist, 3)); + } else { + return DecoratedPotBlockEntity.Decorations.EMPTY; + } + } + +- private static Item itemFromTag(ListTag listtag, int i) { +- if (i >= listtag.size()) { ++ private static Item itemFromTag(ListTag tag, int index) { ++ if (index >= tag.size()) { + return Items.BRICK; + } else { +- Tag tag = listtag.get(i); ++ Tag nbtbase = tag.get(index); + +- return (Item) BuiltInRegistries.ITEM.get(ResourceLocation.tryParse(tag.getAsString())); ++ return (Item) BuiltInRegistries.ITEM.get(ResourceLocation.tryParse(nbtbase.getAsString())); + } + } + } + +- public static enum WobbleStyle { ++ public static enum b { + + POSITIVE(7), NEGATIVE(10); + + public final int duration; + +- private WobbleStyle(int i) { ++ private b(int i) { + this.duration = i; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/DispenserBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/DispenserBlockEntity.java.patch new file mode 100644 index 0000000000..5ea499ed37 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/DispenserBlockEntity.java.patch @@ -0,0 +1,154 @@ +--- a/net/minecraft/world/level/block/entity/DispenserBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/DispenserBlockEntity.java +@@ -11,35 +11,70 @@ + import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.inventory.DispenserMenu; + import net.minecraft.world.item.ItemStack; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class DispenserBlockEntity extends RandomizableContainerBlockEntity { + + public static final int CONTAINER_SIZE = 9; + private NonNullList items; + +- protected DispenserBlockEntity(BlockEntityType blockentitytype, BlockPos blockpos, BlockState blockstate) { +- super(blockentitytype, blockpos, blockstate); ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ ++ protected DispenserBlockEntity(BlockEntityType type, BlockPos pos, IBlockData blockState) { ++ super(type, pos, blockState); + this.items = NonNullList.withSize(9, ItemStack.EMPTY); + } + +- public DispenserBlockEntity(BlockPos blockpos, BlockState blockstate) { +- this(BlockEntityType.DISPENSER, blockpos, blockstate); ++ public DispenserBlockEntity(BlockPos pos, IBlockData blockState) { ++ this(BlockEntityType.DISPENSER, pos, blockState); + } + + @Override +- @Override + public int getContainerSize() { + return 9; + } + +- public int getRandomSlot(RandomSource randomsource) { ++ public int getRandomSlot(RandomSource random) { + this.unpackLootTable((Player) null); + int i = -1; + int j = 1; + + for (int k = 0; k < this.items.size(); ++k) { +- if (!((ItemStack) this.items.get(k)).isEmpty() && randomsource.nextInt(j++) == 0) { ++ if (!((ItemStack) this.items.get(k)).isEmpty() && random.nextInt(j++) == 0) { + i = k; + } + } +@@ -47,10 +82,10 @@ + return i; + } + +- public int addItem(ItemStack itemstack) { ++ public int addItem(ItemStack stack) { + for (int i = 0; i < this.items.size(); ++i) { + if (((ItemStack) this.items.get(i)).isEmpty()) { +- this.setItem(i, itemstack); ++ this.setItem(i, stack); + return i; + } + } +@@ -59,47 +94,41 @@ + } + + @Override +- @Override + protected Component getDefaultName() { + return Component.translatable("container.dispenser"); + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); ++ public void load(CompoundTag tag) { ++ super.load(tag); + this.items = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); +- if (!this.tryLoadLootTable(compoundtag)) { +- ContainerHelper.loadAllItems(compoundtag, this.items); ++ if (!this.tryLoadLootTable(tag)) { ++ ContainerHelper.loadAllItems(tag, this.items); + } + + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); +- if (!this.trySaveLootTable(compoundtag)) { +- ContainerHelper.saveAllItems(compoundtag, this.items); ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); ++ if (!this.trySaveLootTable(tag)) { ++ ContainerHelper.saveAllItems(tag, this.items); + } + + } + + @Override +- @Override + protected NonNullList getItems() { + return this.items; + } + + @Override +- @Override +- protected void setItems(NonNullList nonnulllist) { +- this.items = nonnulllist; ++ protected void setItems(NonNullList items) { ++ this.items = items; + } + + @Override +- @Override +- protected AbstractContainerMenu createMenu(int i, Inventory inventory) { +- return new DispenserMenu(i, inventory, this); ++ protected AbstractContainerMenu createMenu(int id, Inventory player) { ++ return new DispenserMenu(id, player, this); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/HopperBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/HopperBlockEntity.java.patch new file mode 100644 index 0000000000..27ac2c8b81 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/HopperBlockEntity.java.patch @@ -0,0 +1,692 @@ +--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java +@@ -11,6 +11,7 @@ + import net.minecraft.core.NonNullList; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; ++import net.minecraft.world.CompoundContainer; + import net.minecraft.world.Container; + import net.minecraft.world.ContainerHelper; + import net.minecraft.world.WorldlyContainer; +@@ -18,7 +19,6 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.item.ItemEntity; +-import net.minecraft.world.entity.player.Inventory; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.inventory.HopperMenu; +@@ -27,10 +27,21 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.ChestBlock; + import net.minecraft.world.level.block.HopperBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.Shapes; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.event.inventory.HopperInventorySearchEvent; ++import org.bukkit.event.inventory.InventoryMoveItemEvent; ++import org.bukkit.event.inventory.InventoryPickupItemEvent; ++import org.bukkit.inventory.Inventory; ++// CraftBukkit end + + public class HopperBlockEntity extends RandomizableContainerBlockEntity implements Hopper { + +@@ -40,95 +51,119 @@ + private int cooldownTime; + private long tickedGameTime; + +- public HopperBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.HOPPER, blockpos, blockstate); ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ ++ public HopperBlockEntity(BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.HOPPER, pos, blockState); + this.items = NonNullList.withSize(5, ItemStack.EMPTY); + this.cooldownTime = -1; + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); ++ public void load(CompoundTag tag) { ++ super.load(tag); + this.items = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); +- if (!this.tryLoadLootTable(compoundtag)) { +- ContainerHelper.loadAllItems(compoundtag, this.items); ++ if (!this.tryLoadLootTable(tag)) { ++ ContainerHelper.loadAllItems(tag, this.items); + } + +- this.cooldownTime = compoundtag.getInt("TransferCooldown"); ++ this.cooldownTime = tag.getInt("TransferCooldown"); + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); +- if (!this.trySaveLootTable(compoundtag)) { +- ContainerHelper.saveAllItems(compoundtag, this.items); ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); ++ if (!this.trySaveLootTable(tag)) { ++ ContainerHelper.saveAllItems(tag, this.items); + } + +- compoundtag.putInt("TransferCooldown", this.cooldownTime); ++ tag.putInt("TransferCooldown", this.cooldownTime); + } + + @Override +- @Override + public int getContainerSize() { + return this.items.size(); + } + + @Override +- @Override +- public ItemStack removeItem(int i, int j) { ++ public ItemStack removeItem(int index, int count) { + this.unpackLootTable((Player) null); +- return ContainerHelper.removeItem(this.getItems(), i, j); ++ return ContainerHelper.removeItem(this.getItems(), index, count); + } + + @Override +- @Override +- public void setItem(int i, ItemStack itemstack) { ++ public void setItem(int index, ItemStack stack) { + this.unpackLootTable((Player) null); +- this.getItems().set(i, itemstack); +- if (itemstack.getCount() > this.getMaxStackSize()) { +- itemstack.setCount(this.getMaxStackSize()); ++ this.getItems().set(index, stack); ++ if (stack.getCount() > this.getMaxStackSize()) { ++ stack.setCount(this.getMaxStackSize()); + } + + } + + @Override +- @Override + protected Component getDefaultName() { + return Component.translatable("container.hopper"); + } + +- public static void pushItemsTick(Level level, BlockPos blockpos, BlockState blockstate, HopperBlockEntity hopperblockentity) { +- --hopperblockentity.cooldownTime; +- hopperblockentity.tickedGameTime = level.getGameTime(); +- if (!hopperblockentity.isOnCooldown()) { +- hopperblockentity.setCooldown(0); +- tryMoveItems(level, blockpos, blockstate, hopperblockentity, () -> { +- return suckInItems(level, hopperblockentity); ++ public static void pushItemsTick(Level level, BlockPos pos, IBlockData state, HopperBlockEntity blockEntity) { ++ --blockEntity.cooldownTime; ++ blockEntity.tickedGameTime = level.getGameTime(); ++ if (!blockEntity.isOnCooldown()) { ++ blockEntity.setCooldown(0); ++ tryMoveItems(level, pos, state, blockEntity, () -> { ++ return suckInItems(level, blockEntity); + }); + } + + } + +- private static boolean tryMoveItems(Level level, BlockPos blockpos, BlockState blockstate, HopperBlockEntity hopperblockentity, BooleanSupplier booleansupplier) { ++ private static boolean tryMoveItems(Level level, BlockPos pos, IBlockData state, HopperBlockEntity blockEntity, BooleanSupplier validator) { + if (level.isClientSide) { + return false; + } else { +- if (!hopperblockentity.isOnCooldown() && (Boolean) blockstate.getValue(HopperBlock.ENABLED)) { ++ if (!blockEntity.isOnCooldown() && (Boolean) state.getValue(HopperBlock.ENABLED)) { + boolean flag = false; + +- if (!hopperblockentity.isEmpty()) { +- flag = ejectItems(level, blockpos, blockstate, hopperblockentity); ++ if (!blockEntity.isEmpty()) { ++ flag = ejectItems(level, pos, state, (Container) blockEntity, blockEntity); // CraftBukkit + } + +- if (!hopperblockentity.inventoryFull()) { +- flag |= booleansupplier.getAsBoolean(); ++ if (!blockEntity.inventoryFull()) { ++ flag |= validator.getAsBoolean(); + } + + if (flag) { +- hopperblockentity.setCooldown(8); +- setChanged(level, blockpos, blockstate); ++ blockEntity.setCooldown(8); ++ setChanged(level, pos, state); + return true; + } + } +@@ -153,28 +188,51 @@ + return false; + } + +- private static boolean ejectItems(Level level, BlockPos blockpos, BlockState blockstate, Container container) { +- Container container1 = getAttachedContainer(level, blockpos, blockstate); ++ private static boolean ejectItems(Level world, BlockPos blockposition, IBlockData iblockdata, Container iinventory, HopperBlockEntity hopper) { // CraftBukkit ++ Container iinventory1 = getAttachedContainer(world, blockposition, iblockdata); + +- if (container1 == null) { ++ if (iinventory1 == null) { + return false; + } else { +- Direction direction = ((Direction) blockstate.getValue(HopperBlock.FACING)).getOpposite(); ++ Direction enumdirection = ((Direction) iblockdata.getValue(HopperBlock.FACING)).getOpposite(); + +- if (isFullContainer(container1, direction)) { ++ if (isFullContainer(iinventory1, enumdirection)) { + return false; + } else { +- for (int i = 0; i < container.getContainerSize(); ++i) { +- if (!container.getItem(i).isEmpty()) { +- ItemStack itemstack = container.getItem(i).copy(); +- ItemStack itemstack1 = addItem(container, container1, container.removeItem(i, 1), direction); ++ for (int i = 0; i < iinventory.getContainerSize(); ++i) { ++ if (!iinventory.getItem(i).isEmpty()) { ++ ItemStack itemstack = iinventory.getItem(i).copy(); ++ // ItemStack itemstack1 = addItem(iinventory, iinventory1, iinventory.removeItem(i, 1), enumdirection); + ++ // CraftBukkit start - Call event when pushing items into other inventories ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.removeItem(i, 1)); ++ ++ Inventory destinationInventory; ++ // Have to special case large chests as they work oddly ++ if (iinventory1 instanceof CompoundContainer) { ++ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory1); ++ } else if (iinventory1.getOwner() != null) { ++ destinationInventory = iinventory1.getOwner().getInventory(); ++ } else { ++ destinationInventory = new CraftInventory(iinventory); ++ } ++ ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(iinventory.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ hopper.setItem(i, itemstack); ++ hopper.setCooldown(8); // Delay hopper checks ++ return false; ++ } ++ ItemStack itemstack1 = addItem(iinventory, iinventory1, CraftItemStack.asNMSCopy(event.getItem()), enumdirection); ++ // CraftBukkit end ++ + if (itemstack1.isEmpty()) { +- container1.setChanged(); ++ iinventory1.setChanged(); + return true; + } + +- container.setItem(i, itemstack); ++ iinventory.setItem(i, itemstack); + } + } + +@@ -202,101 +260,135 @@ + } + + public static boolean suckInItems(Level level, Hopper hopper) { +- Container container = getSourceContainer(level, hopper); ++ Container iinventory = getSourceContainer(level, hopper); + +- if (container != null) { +- Direction direction = Direction.DOWN; ++ if (iinventory != null) { ++ Direction enumdirection = Direction.DOWN; + +- return isEmptyContainer(container, direction) ? false : getSlots(container, direction).anyMatch((i) -> { +- return tryTakeInItemFromSlot(hopper, container, i, direction); ++ return isEmptyContainer(iinventory, enumdirection) ? false : getSlots(iinventory, enumdirection).anyMatch((i) -> { ++ return tryTakeInItemFromSlot(hopper, iinventory, i, enumdirection); + }); + } else { + Iterator iterator = getItemsAtAndAbove(level, hopper).iterator(); + +- ItemEntity itementity; ++ ItemEntity entityitem; + + do { + if (!iterator.hasNext()) { + return false; + } + +- itementity = (ItemEntity) iterator.next(); +- } while (!addItem(hopper, itementity)); ++ entityitem = (ItemEntity) iterator.next(); ++ } while (!addItem(hopper, entityitem)); + + return true; + } + } + +- private static boolean tryTakeInItemFromSlot(Hopper hopper, Container container, int i, Direction direction) { +- ItemStack itemstack = container.getItem(i); ++ private static boolean tryTakeInItemFromSlot(Hopper hopper, Container container, int slot, Direction direction) { ++ ItemStack itemstack = container.getItem(slot); + +- if (!itemstack.isEmpty() && canTakeItemFromContainer(hopper, container, itemstack, i, direction)) { ++ if (!itemstack.isEmpty() && canTakeItemFromContainer(hopper, container, itemstack, slot, direction)) { + ItemStack itemstack1 = itemstack.copy(); +- ItemStack itemstack2 = addItem(container, hopper, container.removeItem(i, 1), (Direction) null); ++ // ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.removeItem(i, 1), (EnumDirection) null); ++ // CraftBukkit start - Call event on collection of items from inventories into the hopper ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(container.removeItem(slot, 1)); + ++ Inventory sourceInventory; ++ // Have to special case large chests as they work oddly ++ if (container instanceof CompoundContainer) { ++ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) container); ++ } else if (container.getOwner() != null) { ++ sourceInventory = container.getOwner().getInventory(); ++ } else { ++ sourceInventory = new CraftInventory(container); ++ } ++ ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack.clone(), hopper.getOwner().getInventory(), false); ++ ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ container.setItem(slot, itemstack1); ++ ++ if (hopper instanceof HopperBlockEntity) { ++ ((HopperBlockEntity) hopper).setCooldown(8); // Delay hopper checks ++ } ++ ++ return false; ++ } ++ ItemStack itemstack2 = addItem(container, hopper, CraftItemStack.asNMSCopy(event.getItem()), null); ++ // CraftBukkit end ++ + if (itemstack2.isEmpty()) { + container.setChanged(); + return true; + } + +- container.setItem(i, itemstack1); ++ container.setItem(slot, itemstack1); + } + + return false; + } + +- public static boolean addItem(Container container, ItemEntity itementity) { ++ public static boolean addItem(Container container, ItemEntity item) { + boolean flag = false; +- ItemStack itemstack = itementity.getItem().copy(); ++ // CraftBukkit start ++ InventoryPickupItemEvent event = new InventoryPickupItemEvent(container.getOwner().getInventory(), (org.bukkit.entity.Item) item.getBukkitEntity()); ++ item.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ ItemStack itemstack = item.getItem().copy(); + ItemStack itemstack1 = addItem((Container) null, container, itemstack, (Direction) null); + + if (itemstack1.isEmpty()) { + flag = true; +- itementity.setItem(ItemStack.EMPTY); +- itementity.discard(); ++ item.setItem(ItemStack.EMPTY); ++ item.discard(); + } else { +- itementity.setItem(itemstack1); ++ item.setItem(itemstack1); + } + + return flag; + } + +- public static ItemStack addItem(@Nullable Container container, Container container1, ItemStack itemstack, @Nullable Direction direction) { ++ public static ItemStack addItem(@Nullable Container source, Container destination, ItemStack stack, @Nullable Direction direction) { + int i; + +- if (container1 instanceof WorldlyContainer) { +- WorldlyContainer worldlycontainer = (WorldlyContainer) container1; ++ if (destination instanceof WorldlyContainer) { ++ WorldlyContainer iworldinventory = (WorldlyContainer) destination; + + if (direction != null) { +- int[] aint = worldlycontainer.getSlotsForFace(direction); ++ int[] aint = iworldinventory.getSlotsForFace(direction); + +- for (i = 0; i < aint.length && !itemstack.isEmpty(); ++i) { +- itemstack = tryMoveInItem(container, container1, itemstack, aint[i], direction); ++ for (i = 0; i < aint.length && !stack.isEmpty(); ++i) { ++ stack = tryMoveInItem(source, destination, stack, aint[i], direction); + } + +- return itemstack; ++ return stack; + } + } + +- int j = container1.getContainerSize(); ++ int j = destination.getContainerSize(); + +- for (i = 0; i < j && !itemstack.isEmpty(); ++i) { +- itemstack = tryMoveInItem(container, container1, itemstack, i, direction); ++ for (i = 0; i < j && !stack.isEmpty(); ++i) { ++ stack = tryMoveInItem(source, destination, stack, i, direction); + } + +- return itemstack; ++ return stack; + } + +- private static boolean canPlaceItemInContainer(Container container, ItemStack itemstack, int i, @Nullable Direction direction) { +- if (!container.canPlaceItem(i, itemstack)) { ++ private static boolean canPlaceItemInContainer(Container container, ItemStack stack, int slot, @Nullable Direction direction) { ++ if (!container.canPlaceItem(slot, stack)) { + return false; + } else { + boolean flag; + + if (container instanceof WorldlyContainer) { +- WorldlyContainer worldlycontainer = (WorldlyContainer) container; ++ WorldlyContainer iworldinventory = (WorldlyContainer) container; + +- if (!worldlycontainer.canPlaceItemThroughFace(i, itemstack, direction)) { ++ if (!iworldinventory.canPlaceItemThroughFace(slot, stack, direction)) { + flag = false; + return flag; + } +@@ -307,16 +399,16 @@ + } + } + +- private static boolean canTakeItemFromContainer(Container container, Container container1, ItemStack itemstack, int i, Direction direction) { +- if (!container1.canTakeItem(container, i, itemstack)) { ++ private static boolean canTakeItemFromContainer(Container source, Container destination, ItemStack stack, int slot, Direction direction) { ++ if (!destination.canTakeItem(source, slot, stack)) { + return false; + } else { + boolean flag; + +- if (container1 instanceof WorldlyContainer) { +- WorldlyContainer worldlycontainer = (WorldlyContainer) container1; ++ if (destination instanceof WorldlyContainer) { ++ WorldlyContainer iworldinventory = (WorldlyContainer) destination; + +- if (!worldlycontainer.canTakeItemThroughFace(i, itemstack, direction)) { ++ if (!iworldinventory.canTakeItemThroughFace(slot, stack, direction)) { + flag = false; + return flag; + } +@@ -327,97 +419,121 @@ + } + } + +- private static ItemStack tryMoveInItem(@Nullable Container container, Container container1, ItemStack itemstack, int i, @Nullable Direction direction) { +- ItemStack itemstack1 = container1.getItem(i); ++ private static ItemStack tryMoveInItem(@Nullable Container source, Container destination, ItemStack stack, int slot, @Nullable Direction direction) { ++ ItemStack itemstack1 = destination.getItem(slot); + +- if (canPlaceItemInContainer(container1, itemstack, i, direction)) { ++ if (canPlaceItemInContainer(destination, stack, slot, direction)) { + boolean flag = false; +- boolean flag1 = container1.isEmpty(); ++ boolean flag1 = destination.isEmpty(); + + if (itemstack1.isEmpty()) { +- container1.setItem(i, itemstack); +- itemstack = ItemStack.EMPTY; ++ destination.setItem(slot, stack); ++ stack = ItemStack.EMPTY; + flag = true; +- } else if (canMergeItems(itemstack1, itemstack)) { +- int j = itemstack.getMaxStackSize() - itemstack1.getCount(); +- int k = Math.min(itemstack.getCount(), j); ++ } else if (canMergeItems(itemstack1, stack)) { ++ int j = stack.getMaxStackSize() - itemstack1.getCount(); ++ int k = Math.min(stack.getCount(), j); + +- itemstack.shrink(k); ++ stack.shrink(k); + itemstack1.grow(k); + flag = k > 0; + } + + if (flag) { +- if (flag1 && container1 instanceof HopperBlockEntity) { +- HopperBlockEntity hopperblockentity = (HopperBlockEntity) container1; ++ if (flag1 && destination instanceof HopperBlockEntity) { ++ HopperBlockEntity tileentityhopper = (HopperBlockEntity) destination; + +- if (!hopperblockentity.isOnCustomCooldown()) { ++ if (!tileentityhopper.isOnCustomCooldown()) { + byte b0 = 0; + +- if (container instanceof HopperBlockEntity) { +- HopperBlockEntity hopperblockentity1 = (HopperBlockEntity) container; ++ if (source instanceof HopperBlockEntity) { ++ HopperBlockEntity tileentityhopper1 = (HopperBlockEntity) source; + +- if (hopperblockentity.tickedGameTime >= hopperblockentity1.tickedGameTime) { ++ if (tileentityhopper.tickedGameTime >= tileentityhopper1.tickedGameTime) { + b0 = 1; + } + } + +- hopperblockentity.setCooldown(8 - b0); ++ tileentityhopper.setCooldown(8 - b0); + } + } + +- container1.setChanged(); ++ destination.setChanged(); + } + } + +- return itemstack; ++ return stack; + } + ++ // CraftBukkit start + @Nullable +- private static Container getAttachedContainer(Level level, BlockPos blockpos, BlockState blockstate) { +- Direction direction = (Direction) blockstate.getValue(HopperBlock.FACING); ++ private static Container runHopperInventorySearchEvent(Container inventory, CraftBlock hopper, CraftBlock searchLocation, HopperInventorySearchEvent.ContainerType containerType) { ++ HopperInventorySearchEvent event = new HopperInventorySearchEvent((inventory != null) ? new CraftInventory(inventory) : null, containerType, hopper, searchLocation); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ CraftInventory craftInventory = (CraftInventory) event.getInventory(); ++ return (craftInventory != null) ? craftInventory.getInventory() : null; ++ } ++ // CraftBukkit end + +- return getContainerAt(level, blockpos.relative(direction)); ++ @Nullable ++ private static Container getAttachedContainer(Level level, BlockPos pos, IBlockData state) { ++ Direction enumdirection = (Direction) state.getValue(HopperBlock.FACING); ++ ++ // CraftBukkit start ++ BlockPos searchPosition = pos.relative(enumdirection); ++ Container inventory = getContainerAt(level, pos.relative(enumdirection)); ++ ++ CraftBlock hopper = CraftBlock.at(level, pos); ++ CraftBlock searchBlock = CraftBlock.at(level, searchPosition); ++ return runHopperInventorySearchEvent(inventory, hopper, searchBlock, HopperInventorySearchEvent.ContainerType.DESTINATION); ++ // CraftBukkit end + } + + @Nullable + private static Container getSourceContainer(Level level, Hopper hopper) { +- return getContainerAt(level, hopper.getLevelX(), hopper.getLevelY() + 1.0D, hopper.getLevelZ()); ++ // CraftBukkit start ++ Container inventory = getContainerAt(level, hopper.getLevelX(), hopper.getLevelY() + 1.0D, hopper.getLevelZ()); ++ ++ BlockPos blockPosition = BlockPos.containing(hopper.getLevelX(), hopper.getLevelY(), hopper.getLevelZ()); ++ CraftBlock hopper1 = CraftBlock.at(level, blockPosition); ++ CraftBlock container = CraftBlock.at(level, blockPosition.above()); ++ return runHopperInventorySearchEvent(inventory, hopper1, container, HopperInventorySearchEvent.ContainerType.SOURCE); ++ // CraftBukkit end + } + + public static List getItemsAtAndAbove(Level level, Hopper hopper) { +- return (List) hopper.getSuckShape().toAabbs().stream().flatMap((aabb) -> { +- return level.getEntitiesOfClass(ItemEntity.class, aabb.move(hopper.getLevelX() - 0.5D, hopper.getLevelY() - 0.5D, hopper.getLevelZ() - 0.5D), EntitySelector.ENTITY_STILL_ALIVE).stream(); ++ return (List) hopper.getSuckShape().toAabbs().stream().flatMap((axisalignedbb) -> { ++ return level.getEntitiesOfClass(ItemEntity.class, axisalignedbb.move(hopper.getLevelX() - 0.5D, hopper.getLevelY() - 0.5D, hopper.getLevelZ() - 0.5D), EntitySelector.ENTITY_STILL_ALIVE).stream(); + }).collect(Collectors.toList()); + } + + @Nullable +- public static Container getContainerAt(Level level, BlockPos blockpos) { +- return getContainerAt(level, (double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D); ++ public static Container getContainerAt(Level level, BlockPos pos) { ++ return getContainerAt(level, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D); + } + + @Nullable +- private static Container getContainerAt(Level level, double d0, double d1, double d2) { ++ private static Container getContainerAt(Level level, double x, double d1, double y) { + Object object = null; +- BlockPos blockpos = BlockPos.containing(d0, d1, d2); +- BlockState blockstate = level.getBlockState(blockpos); +- Block block = blockstate.getBlock(); ++ BlockPos blockposition = BlockPos.containing(x, d1, y); ++ IBlockData iblockdata = level.getBlockState(blockposition); ++ Block block = iblockdata.getBlock(); + + if (block instanceof WorldlyContainerHolder) { +- object = ((WorldlyContainerHolder) block).getContainer(blockstate, level, blockpos); +- } else if (blockstate.hasBlockEntity()) { +- BlockEntity blockentity = level.getBlockEntity(blockpos); ++ object = ((WorldlyContainerHolder) block).getContainer(iblockdata, level, blockposition); ++ } else if (iblockdata.hasBlockEntity()) { ++ BlockEntity tileentity = level.getBlockEntity(blockposition); + +- if (blockentity instanceof Container) { +- object = (Container) blockentity; ++ if (tileentity instanceof Container) { ++ object = (Container) tileentity; + if (object instanceof ChestBlockEntity && block instanceof ChestBlock) { +- object = ChestBlock.getContainer((ChestBlock) block, blockstate, level, blockpos, true); ++ object = ChestBlock.getContainer((ChestBlock) block, iblockdata, level, blockposition, true); + } + } + } + + if (object == null) { +- List list = level.getEntities((Entity) null, new AABB(d0 - 0.5D, d1 - 0.5D, d2 - 0.5D, d0 + 0.5D, d1 + 0.5D, d2 + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); ++ List list = level.getEntities((Entity) null, new AABB(x - 0.5D, d1 - 0.5D, y - 0.5D, x + 0.5D, d1 + 0.5D, y + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); + + if (!list.isEmpty()) { + object = (Container) list.get(level.random.nextInt(list.size())); +@@ -427,30 +543,27 @@ + return (Container) object; + } + +- private static boolean canMergeItems(ItemStack itemstack, ItemStack itemstack1) { +- return itemstack.getCount() <= itemstack.getMaxStackSize() && ItemStack.isSameItemSameTags(itemstack, itemstack1); ++ private static boolean canMergeItems(ItemStack stack1, ItemStack stack2) { ++ return stack1.getCount() <= stack1.getMaxStackSize() && ItemStack.isSameItemSameTags(stack1, stack2); + } + + @Override +- @Override + public double getLevelX() { + return (double) this.worldPosition.getX() + 0.5D; + } + + @Override +- @Override + public double getLevelY() { + return (double) this.worldPosition.getY() + 0.5D; + } + + @Override +- @Override + public double getLevelZ() { + return (double) this.worldPosition.getZ() + 0.5D; + } + +- private void setCooldown(int i) { +- this.cooldownTime = i; ++ private void setCooldown(int cooldownTime) { ++ this.cooldownTime = cooldownTime; + } + + private boolean isOnCooldown() { +@@ -462,24 +575,22 @@ + } + + @Override +- @Override + protected NonNullList getItems() { + return this.items; + } + + @Override +- @Override +- protected void setItems(NonNullList nonnulllist) { +- this.items = nonnulllist; ++ protected void setItems(NonNullList items) { ++ this.items = items; + } + +- public static void entityInside(Level level, BlockPos blockpos, BlockState blockstate, Entity entity, HopperBlockEntity hopperblockentity) { ++ public static void entityInside(Level level, BlockPos pos, IBlockData state, Entity entity, HopperBlockEntity blockEntity) { + if (entity instanceof ItemEntity) { +- ItemEntity itementity = (ItemEntity) entity; ++ ItemEntity entityitem = (ItemEntity) entity; + +- if (!itementity.getItem().isEmpty() && Shapes.joinIsNotEmpty(Shapes.create(entity.getBoundingBox().move((double) (-blockpos.getX()), (double) (-blockpos.getY()), (double) (-blockpos.getZ()))), hopperblockentity.getSuckShape(), BooleanOp.AND)) { +- tryMoveItems(level, blockpos, blockstate, hopperblockentity, () -> { +- return addItem(hopperblockentity, itementity); ++ if (!entityitem.getItem().isEmpty() && Shapes.joinIsNotEmpty(Shapes.create(entity.getBoundingBox().move((double) (-pos.getX()), (double) (-pos.getY()), (double) (-pos.getZ()))), blockEntity.getSuckShape(), BooleanOp.AND)) { ++ tryMoveItems(level, pos, state, blockEntity, () -> { ++ return addItem(blockEntity, entityitem); + }); + } + } +@@ -487,8 +598,7 @@ + } + + @Override +- @Override +- protected AbstractContainerMenu createMenu(int i, Inventory inventory) { +- return new HopperMenu(i, inventory, this); ++ protected AbstractContainerMenu createMenu(int id, net.minecraft.world.entity.player.Inventory player) { ++ return new HopperMenu(id, player, this); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java.patch new file mode 100644 index 0000000000..eff93903d1 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java.patch @@ -0,0 +1,274 @@ +--- a/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java +@@ -17,58 +17,100 @@ + import net.minecraft.world.item.RecordItem; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.JukeboxBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.ticks.ContainerSingleItem; + ++// CraftBukkit start ++import java.util.Collections; ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class JukeboxBlockEntity extends BlockEntity implements Clearable, ContainerSingleItem { + + private static final int SONG_END_PADDING = 20; + private ItemStack item; + private int ticksSinceLastEvent; +- private long tickCount; +- private long recordStartedTick; +- private boolean isPlaying; ++ public long tickCount; ++ public long recordStartedTick; ++ public boolean isPlaying; ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ public boolean opened; + +- public JukeboxBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.JUKEBOX, blockpos, blockstate); +- this.item = ItemStack.EMPTY; ++ @Override ++ public List getContents() { ++ return Collections.singletonList(item); + } + + @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ + @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); +- if (compoundtag.contains("RecordItem", 10)) { +- this.item = ItemStack.of(compoundtag.getCompound("RecordItem")); +- } ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } + +- this.isPlaying = compoundtag.getBoolean("IsPlaying"); +- this.recordStartedTick = compoundtag.getLong("RecordStartTick"); +- this.tickCount = compoundtag.getLong("TickCount"); ++ @Override ++ public List getViewers() { ++ return transaction; + } + + @Override ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ + @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); ++ public Location getLocation() { ++ if (level == null) return null; ++ return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ } ++ // CraftBukkit end ++ ++ public JukeboxBlockEntity(BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.JUKEBOX, pos, blockState); ++ this.item = ItemStack.EMPTY; ++ } ++ ++ @Override ++ public void load(CompoundTag tag) { ++ super.load(tag); ++ if (tag.contains("RecordItem", 10)) { ++ this.item = ItemStack.of(tag.getCompound("RecordItem")); ++ } ++ ++ this.isPlaying = tag.getBoolean("IsPlaying"); ++ this.recordStartedTick = tag.getLong("RecordStartTick"); ++ this.tickCount = tag.getLong("TickCount"); ++ } ++ ++ @Override ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); + if (!this.getTheItem().isEmpty()) { +- compoundtag.put("RecordItem", this.getTheItem().save(new CompoundTag())); ++ tag.put("RecordItem", this.getTheItem().save(new CompoundTag())); + } + +- compoundtag.putBoolean("IsPlaying", this.isPlaying); +- compoundtag.putLong("RecordStartTick", this.recordStartedTick); +- compoundtag.putLong("TickCount", this.tickCount); ++ tag.putBoolean("IsPlaying", this.isPlaying); ++ tag.putLong("RecordStartTick", this.recordStartedTick); ++ tag.putLong("TickCount", this.tickCount); + } + + public boolean isRecordPlaying() { + return !this.getTheItem().isEmpty() && this.isPlaying; + } + +- private void setHasRecordBlockState(@Nullable Entity entity, boolean flag) { ++ private void setHasRecordBlockState(@Nullable Entity entity, boolean hasRecord) { + if (this.level.getBlockState(this.getBlockPos()) == this.getBlockState()) { +- this.level.setBlock(this.getBlockPos(), (BlockState) this.getBlockState().setValue(JukeboxBlock.HAS_RECORD, flag), 2); ++ this.level.setBlock(this.getBlockPos(), (IBlockData) this.getBlockState().setValue(JukeboxBlock.HAS_RECORD, hasRecord), 2); + this.level.gameEvent(GameEvent.BLOCK_CHANGE, this.getBlockPos(), GameEvent.Context.of(entity, this.getBlockState())); + } + +@@ -91,20 +133,20 @@ + this.setChanged(); + } + +- private void tick(Level level, BlockPos blockpos, BlockState blockstate) { ++ private void tick(Level level, BlockPos pos, IBlockData state) { + ++this.ticksSinceLastEvent; + if (this.isRecordPlaying()) { + Item item = this.getTheItem().getItem(); + + if (item instanceof RecordItem) { +- RecordItem recorditem = (RecordItem) item; ++ RecordItem itemrecord = (RecordItem) item; + +- if (this.shouldRecordStopPlaying(recorditem)) { ++ if (this.shouldRecordStopPlaying(itemrecord)) { + this.stopPlaying(); + } else if (this.shouldSendJukeboxPlayingEvent()) { + this.ticksSinceLastEvent = 0; +- level.gameEvent(GameEvent.JUKEBOX_PLAY, blockpos, GameEvent.Context.of(blockstate)); +- this.spawnMusicParticles(level, blockpos); ++ level.gameEvent(GameEvent.JUKEBOX_PLAY, pos, GameEvent.Context.of(state)); ++ this.spawnMusicParticles(level, pos); + } + } + } +@@ -112,8 +154,8 @@ + ++this.tickCount; + } + +- private boolean shouldRecordStopPlaying(RecordItem recorditem) { +- return this.tickCount >= this.recordStartedTick + (long) recorditem.getLengthInTicks() + 20L; ++ private boolean shouldRecordStopPlaying(RecordItem record) { ++ return this.tickCount >= this.recordStartedTick + (long) record.getLengthInTicks() + 20L; + } + + private boolean shouldSendJukeboxPlayingEvent() { +@@ -121,13 +163,11 @@ + } + + @Override +- @Override + public ItemStack getTheItem() { + return this.item; + } + + @Override +- @Override + public ItemStack splitTheItem(int i) { + ItemStack itemstack = this.item; + +@@ -141,7 +181,6 @@ + } + + @Override +- @Override + public void setTheItem(ItemStack itemstack) { + if (itemstack.is(ItemTags.MUSIC_DISCS) && this.level != null) { + this.item = itemstack; +@@ -154,65 +193,65 @@ + } + + @Override +- @Override + public int getMaxStackSize() { +- return 1; ++ return maxStack; // CraftBukkit + } + + @Override +- @Override + public BlockEntity getContainerBlockEntity() { + return this; + } + + @Override +- @Override +- public boolean canPlaceItem(int i, ItemStack itemstack) { +- return itemstack.is(ItemTags.MUSIC_DISCS) && this.getItem(i).isEmpty(); ++ public boolean canPlaceItem(int index, ItemStack stack) { ++ return stack.is(ItemTags.MUSIC_DISCS) && this.getItem(index).isEmpty(); + } + + @Override +- @Override +- public boolean canTakeItem(Container container, int i, ItemStack itemstack) { +- return container.hasAnyMatching(ItemStack::isEmpty); ++ public boolean canTakeItem(Container target, int index, ItemStack stack) { ++ return target.hasAnyMatching(ItemStack::isEmpty); + } + +- private void spawnMusicParticles(Level level, BlockPos blockpos) { ++ private void spawnMusicParticles(Level level, BlockPos pos) { + if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; +- Vec3 vec3 = Vec3.atBottomCenterOf(blockpos).add(0.0D, 1.2000000476837158D, 0.0D); ++ ServerLevel worldserver = (ServerLevel) level; ++ Vec3 vec3d = Vec3.atBottomCenterOf(pos).add(0.0D, 1.2000000476837158D, 0.0D); + float f = (float) level.getRandom().nextInt(4) / 24.0F; + +- serverlevel.sendParticles(ParticleTypes.NOTE, vec3.x(), vec3.y(), vec3.z(), 0, (double) f, 0.0D, 0.0D, 1.0D); ++ worldserver.sendParticles(ParticleTypes.NOTE, vec3d.x(), vec3d.y(), vec3d.z(), 0, (double) f, 0.0D, 0.0D, 1.0D); + } + + } + + public void popOutRecord() { + if (this.level != null && !this.level.isClientSide) { +- BlockPos blockpos = this.getBlockPos(); ++ BlockPos blockposition = this.getBlockPos(); + ItemStack itemstack = this.getTheItem(); + + if (!itemstack.isEmpty()) { + this.removeTheItem(); +- Vec3 vec3 = Vec3.atLowerCornerWithOffset(blockpos, 0.5D, 1.01D, 0.5D).offsetRandom(this.level.random, 0.7F); ++ Vec3 vec3d = Vec3.atLowerCornerWithOffset(blockposition, 0.5D, 1.01D, 0.5D).offsetRandom(this.level.random, 0.7F); + ItemStack itemstack1 = itemstack.copy(); +- ItemEntity itementity = new ItemEntity(this.level, vec3.x(), vec3.y(), vec3.z(), itemstack1); ++ ItemEntity entityitem = new ItemEntity(this.level, vec3d.x(), vec3d.y(), vec3d.z(), itemstack1); + +- itementity.setDefaultPickUpDelay(); +- this.level.addFreshEntity(itementity); ++ entityitem.setDefaultPickUpDelay(); ++ this.level.addFreshEntity(entityitem); + } + } + } + +- public static void playRecordTick(Level level, BlockPos blockpos, BlockState blockstate, JukeboxBlockEntity jukeboxblockentity) { +- jukeboxblockentity.tick(level, blockpos, blockstate); ++ public static void playRecordTick(Level level, BlockPos pos, IBlockData state, JukeboxBlockEntity jukebox) { ++ jukebox.tick(level, pos, state); + } + + @VisibleForTesting +- public void setRecordWithoutPlaying(ItemStack itemstack) { +- this.item = itemstack; +- this.level.updateNeighborsAt(this.getBlockPos(), this.getBlockState().getBlock()); ++ public void setRecordWithoutPlaying(ItemStack stack) { ++ this.item = stack; ++ // CraftBukkit start - add null check for level ++ if (level != null) { ++ this.level.updateNeighborsAt(this.getBlockPos(), this.getBlockState().getBlock()); ++ } ++ // CraftBukkit end + this.setChanged(); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/LecternBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/LecternBlockEntity.java.patch new file mode 100644 index 0000000000..263922d16c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/LecternBlockEntity.java.patch @@ -0,0 +1,366 @@ +--- a/net/minecraft/world/level/block/entity/LecternBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/LecternBlockEntity.java +@@ -10,7 +10,7 @@ + import net.minecraft.util.Mth; + import net.minecraft.world.Clearable; + import net.minecraft.world.Container; +-import net.minecraft.world.MenuProvider; ++import net.minecraft.world.ITileInventory; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Inventory; + import net.minecraft.world.entity.player.Player; +@@ -21,40 +21,94 @@ + import net.minecraft.world.item.Items; + import net.minecraft.world.item.WrittenBookItem; + import net.minecraft.world.level.block.LecternBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.block.Lectern; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end + +-public class LecternBlockEntity extends BlockEntity implements Clearable, MenuProvider { ++public class LecternBlockEntity extends BlockEntity implements Clearable, ITileInventory, CommandSource { // CraftBukkit - ICommandListener + + public static final int DATA_PAGE = 0; + public static final int NUM_DATA = 1; + public static final int SLOT_BOOK = 0; + public static final int NUM_SLOTS = 1; +- private final Container bookAccess = new Container() { ++ // CraftBukkit start - add fields and methods ++ public final Container bookAccess = new LecternInventory(); ++ public class LecternInventory implements Container { ++ ++ public List transaction = new ArrayList<>(); ++ private int maxStack = 1; ++ + @Override ++ public List getContents() { ++ return Arrays.asList(book); ++ } ++ + @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return CraftLocation.toBukkit(worldPosition, level.getWorld()); ++ } ++ ++ @Override ++ public InventoryHolder getOwner() { ++ return (Lectern) LecternBlockEntity.this.getOwner(); ++ } ++ ++ public LecternBlockEntity getLectern() { ++ return LecternBlockEntity.this; ++ } ++ // CraftBukkit end ++ ++ @Override + public int getContainerSize() { + return 1; + } + + @Override +- @Override + public boolean isEmpty() { + return LecternBlockEntity.this.book.isEmpty(); + } + + @Override +- @Override +- public ItemStack getItem(int i) { +- return i == 0 ? LecternBlockEntity.this.book : ItemStack.EMPTY; ++ public ItemStack getItem(int slot) { ++ return slot == 0 ? LecternBlockEntity.this.book : ItemStack.EMPTY; + } + + @Override +- @Override +- public ItemStack removeItem(int i, int j) { +- if (i == 0) { +- ItemStack itemstack = LecternBlockEntity.this.book.split(j); ++ public ItemStack removeItem(int slot, int amount) { ++ if (slot == 0) { ++ ItemStack itemstack = LecternBlockEntity.this.book.split(amount); + + if (LecternBlockEntity.this.book.isEmpty()) { + LecternBlockEntity.this.onBookItemRemove(); +@@ -67,9 +121,8 @@ + } + + @Override +- @Override +- public ItemStack removeItemNoUpdate(int i) { +- if (i == 0) { ++ public ItemStack removeItemNoUpdate(int slot) { ++ if (slot == 0) { + ItemStack itemstack = LecternBlockEntity.this.book; + + LecternBlockEntity.this.book = ItemStack.EMPTY; +@@ -81,55 +134,55 @@ + } + + @Override +- @Override +- public void setItem(int i, ItemStack itemstack) {} ++ // CraftBukkit start ++ public void setItem(int slot, ItemStack stack) { ++ if (slot == 0) { ++ LecternBlockEntity.this.setBook(stack); ++ if (LecternBlockEntity.this.getLevel() != null) { ++ LecternBlock.resetBookState(null, LecternBlockEntity.this.getLevel(), LecternBlockEntity.this.getBlockPos(), LecternBlockEntity.this.getBlockState(), LecternBlockEntity.this.hasBook()); ++ } ++ } ++ } ++ // CraftBukkit end + + @Override +- @Override + public int getMaxStackSize() { +- return 1; ++ return maxStack; // CraftBukkit + } + + @Override +- @Override + public void setChanged() { + LecternBlockEntity.this.setChanged(); + } + + @Override +- @Override + public boolean stillValid(Player player) { + return Container.stillValidBlockEntity(LecternBlockEntity.this, player) && LecternBlockEntity.this.hasBook(); + } + + @Override +- @Override +- public boolean canPlaceItem(int i, ItemStack itemstack) { ++ public boolean canPlaceItem(int index, ItemStack stack) { + return false; + } + + @Override +- @Override + public void clearContent() {} + }; + private final ContainerData dataAccess = new ContainerData() { + @Override +- @Override +- public int get(int i) { +- return i == 0 ? LecternBlockEntity.this.page : 0; ++ public int get(int index) { ++ return index == 0 ? LecternBlockEntity.this.page : 0; + } + + @Override +- @Override +- public void set(int i, int j) { +- if (i == 0) { +- LecternBlockEntity.this.setPage(j); ++ public void set(int index, int value) { ++ if (index == 0) { ++ LecternBlockEntity.this.setPage(value); + } + + } + + @Override +- @Override + public int getCount() { + return 1; + } +@@ -138,8 +191,8 @@ + int page; + private int pageCount; + +- public LecternBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.LECTERN, blockpos, blockstate); ++ public LecternBlockEntity(BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.LECTERN, pos, blockState); + this.book = ItemStack.EMPTY; + } + +@@ -151,8 +204,8 @@ + return this.book.is(Items.WRITABLE_BOOK) || this.book.is(Items.WRITTEN_BOOK); + } + +- public void setBook(ItemStack itemstack) { +- this.setBook(itemstack, (Player) null); ++ public void setBook(ItemStack stack) { ++ this.setBook(stack, (Player) null); + } + + void onBookItemRemove() { +@@ -161,20 +214,20 @@ + LecternBlock.resetBookState((Entity) null, this.getLevel(), this.getBlockPos(), this.getBlockState(), false); + } + +- public void setBook(ItemStack itemstack, @Nullable Player player) { +- this.book = this.resolveBook(itemstack, player); ++ public void setBook(ItemStack stack, @Nullable Player player) { ++ this.book = this.resolveBook(stack, player); + this.page = 0; + this.pageCount = WrittenBookItem.getPageCount(this.book); + this.setChanged(); + } + +- void setPage(int i) { +- int j = Mth.clamp(i, 0, this.pageCount - 1); ++ public void setPage(int page) { ++ int j = Mth.clamp(page, 0, this.pageCount - 1); + + if (j != this.page) { + this.page = j; + this.setChanged(); +- LecternBlock.signalPageChange(this.getLevel(), this.getBlockPos(), this.getBlockState()); ++ if (this.level != null) LecternBlock.signalPageChange(this.getLevel(), this.getBlockPos(), this.getBlockState()); // CraftBukkit + } + + } +@@ -189,14 +242,40 @@ + return Mth.floor(f * 14.0F) + (this.hasBook() ? 1 : 0); + } + +- private ItemStack resolveBook(ItemStack itemstack, @Nullable Player player) { +- if (this.level instanceof ServerLevel && itemstack.is(Items.WRITTEN_BOOK)) { +- WrittenBookItem.resolveBookComponents(itemstack, this.createCommandSourceStack(player), player); ++ private ItemStack resolveBook(ItemStack stack, @Nullable Player player) { ++ if (this.level instanceof ServerLevel && stack.is(Items.WRITTEN_BOOK)) { ++ WrittenBookItem.resolveBookComponents(stack, this.createCommandSourceStack(player), player); + } + +- return itemstack; ++ return stack; + } + ++ // CraftBukkit start ++ @Override ++ public void sendSystemMessage(Component component) { ++ } ++ ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return wrapper.getEntity() != null ? wrapper.getEntity().getBukkitSender(wrapper) : new org.bukkit.craftbukkit.command.CraftBlockCommandSender(wrapper, this); ++ } ++ ++ @Override ++ public boolean acceptsSuccess() { ++ return false; ++ } ++ ++ @Override ++ public boolean acceptsFailure() { ++ return false; ++ } ++ ++ @Override ++ public boolean shouldInformAdmins() { ++ return false; ++ } ++ ++ // CraftBukkit end + private CommandSourceStack createCommandSourceStack(@Nullable Player player) { + String s; + Object object; +@@ -209,56 +288,51 @@ + object = player.getDisplayName(); + } + +- Vec3 vec3 = Vec3.atCenterOf(this.worldPosition); ++ Vec3 vec3d = Vec3.atCenterOf(this.worldPosition); + +- return new CommandSourceStack(CommandSource.NULL, vec3, Vec2.ZERO, (ServerLevel) this.level, 2, s, (Component) object, this.level.getServer(), player); ++ // CraftBukkit - this ++ return new CommandSourceStack(this, vec3d, Vec2.ZERO, (ServerLevel) this.level, 2, s, (Component) object, this.level.getServer(), player); + } + + @Override +- @Override + public boolean onlyOpCanSetNbt() { + return true; + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); +- if (compoundtag.contains("Book", 10)) { +- this.book = this.resolveBook(ItemStack.of(compoundtag.getCompound("Book")), (Player) null); ++ public void load(CompoundTag tag) { ++ super.load(tag); ++ if (tag.contains("Book", 10)) { ++ this.book = this.resolveBook(ItemStack.of(tag.getCompound("Book")), (Player) null); + } else { + this.book = ItemStack.EMPTY; + } + + this.pageCount = WrittenBookItem.getPageCount(this.book); +- this.page = Mth.clamp(compoundtag.getInt("Page"), 0, this.pageCount - 1); ++ this.page = Mth.clamp(tag.getInt("Page"), 0, this.pageCount - 1); + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); + if (!this.getBook().isEmpty()) { +- compoundtag.put("Book", this.getBook().save(new CompoundTag())); +- compoundtag.putInt("Page", this.page); ++ tag.put("Book", this.getBook().save(new CompoundTag())); ++ tag.putInt("Page", this.page); + } + + } + + @Override +- @Override + public void clearContent() { + this.setBook(ItemStack.EMPTY); + } + + @Override +- @Override +- public AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) { +- return new LecternMenu(i, this.bookAccess, this.dataAccess); ++ public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { ++ return new LecternMenu(containerId, this.bookAccess, this.dataAccess, playerInventory); // CraftBukkit + } + + @Override +- @Override + public Component getDisplayName() { + return Component.translatable("container.lectern"); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java.patch new file mode 100644 index 0000000000..0ce3834ee9 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java.patch @@ -0,0 +1,167 @@ +--- a/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java +@@ -18,41 +18,42 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.SculkCatalystBlock; + import net.minecraft.world.level.block.SculkSpreader; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.BlockPositionSource; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.gameevent.GameEventListener; + import net.minecraft.world.level.gameevent.PositionSource; + import net.minecraft.world.phys.Vec3; + +-public class SculkCatalystBlockEntity extends BlockEntity implements GameEventListener.Holder { ++public class SculkCatalystBlockEntity extends BlockEntity implements GameEventListener.b { + + private final SculkCatalystBlockEntity.CatalystListener catalystListener; + +- public SculkCatalystBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.SCULK_CATALYST, blockpos, blockstate); +- this.catalystListener = new SculkCatalystBlockEntity.CatalystListener(blockstate, new BlockPositionSource(blockpos)); ++ public SculkCatalystBlockEntity(BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.SCULK_CATALYST, pos, blockState); ++ this.catalystListener = new SculkCatalystBlockEntity.CatalystListener(blockState, new BlockPositionSource(pos)); ++ catalystListener.level = level; // CraftBukkit + } + +- public static void serverTick(Level level, BlockPos blockpos, BlockState blockstate, SculkCatalystBlockEntity sculkcatalystblockentity) { +- sculkcatalystblockentity.catalystListener.getSculkSpreader().updateCursors(level, blockpos, level.getRandom(), true); ++ public static void serverTick(Level level, BlockPos pos, IBlockData state, SculkCatalystBlockEntity sculkCatalyst) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = sculkCatalyst.getBlockPos(); // CraftBukkit - SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep. ++ sculkCatalyst.catalystListener.getSculkSpreader().updateCursors(level, pos, level.getRandom(), true); ++ org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = null; // CraftBukkit + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- this.catalystListener.sculkSpreader.load(compoundtag); ++ public void load(CompoundTag tag) { ++ super.load(tag); // CraftBukkit - SPIGOT-7393: Load super Bukkit data ++ this.catalystListener.sculkSpreader.load(tag); + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- this.catalystListener.sculkSpreader.save(compoundtag); +- super.saveAdditional(compoundtag); ++ protected void saveAdditional(CompoundTag tag) { ++ this.catalystListener.sculkSpreader.save(tag); ++ super.saveAdditional(tag); + } + + @Override +- @Override + public SculkCatalystBlockEntity.CatalystListener getListener() { + return this.catalystListener; + } +@@ -61,53 +62,51 @@ + + public static final int PULSE_TICKS = 8; + final SculkSpreader sculkSpreader; +- private final BlockState blockState; ++ private final IBlockData blockState; + private final PositionSource positionSource; ++ private Level level; // CraftBukkit + +- public CatalystListener(BlockState blockstate, PositionSource positionsource) { +- this.blockState = blockstate; +- this.positionSource = positionsource; ++ public CatalystListener(IBlockData blockState, PositionSource positionSource) { ++ this.blockState = blockState; ++ this.positionSource = positionSource; + this.sculkSpreader = SculkSpreader.createLevelSpreader(); ++ this.sculkSpreader.level = level; // CraftBukkit + } + + @Override +- @Override + public PositionSource getListenerSource() { + return this.positionSource; + } + + @Override +- @Override + public int getListenerRadius() { + return 8; + } + + @Override +- @Override +- public GameEventListener.DeliveryMode getDeliveryMode() { +- return GameEventListener.DeliveryMode.BY_DISTANCE; ++ public GameEventListener.a getDeliveryMode() { ++ return GameEventListener.a.BY_DISTANCE; + } + + @Override +- @Override +- public boolean handleGameEvent(ServerLevel serverlevel, GameEvent gameevent, GameEvent.Context gameevent_context, Vec3 vec3) { +- if (gameevent == GameEvent.ENTITY_DIE) { +- Entity entity = gameevent_context.sourceEntity(); ++ public boolean handleGameEvent(ServerLevel level, GameEvent gameEvent, GameEvent.Context context, Vec3 pos) { ++ if (gameEvent == GameEvent.ENTITY_DIE) { ++ Entity entity = context.sourceEntity(); + + if (entity instanceof LivingEntity) { +- LivingEntity livingentity = (LivingEntity) entity; ++ LivingEntity entityliving = (LivingEntity) entity; + +- if (!livingentity.wasExperienceConsumed()) { +- int i = livingentity.getExperienceReward(); ++ if (!entityliving.wasExperienceConsumed()) { ++ int i = entityliving.getExperienceReward(); + +- if (livingentity.shouldDropExperience() && i > 0) { +- this.sculkSpreader.addCursors(BlockPos.containing(vec3.relative(Direction.UP, 0.5D)), i); +- this.tryAwardItSpreadsAdvancement(serverlevel, livingentity); ++ if (entityliving.shouldDropExperience() && i > 0) { ++ this.sculkSpreader.addCursors(BlockPos.containing(pos.relative(Direction.UP, 0.5D)), i); ++ this.tryAwardItSpreadsAdvancement(level, entityliving); + } + +- livingentity.skipDropExperience(); +- this.positionSource.getPosition(serverlevel).ifPresent((vec31) -> { +- this.bloom(serverlevel, BlockPos.containing(vec31), this.blockState, serverlevel.getRandom()); ++ entityliving.skipDropExperience(); ++ this.positionSource.getPosition(level).ifPresent((vec3d1) -> { ++ this.bloom(level, BlockPos.containing(vec3d1), this.blockState, level.getRandom()); + }); + } + +@@ -123,21 +122,21 @@ + return this.sculkSpreader; + } + +- private void bloom(ServerLevel serverlevel, BlockPos blockpos, BlockState blockstate, RandomSource randomsource) { +- serverlevel.setBlock(blockpos, (BlockState) blockstate.setValue(SculkCatalystBlock.PULSE, true), 3); +- serverlevel.scheduleTick(blockpos, blockstate.getBlock(), 8); +- serverlevel.sendParticles(ParticleTypes.SCULK_SOUL, (double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 1.15D, (double) blockpos.getZ() + 0.5D, 2, 0.2D, 0.0D, 0.2D, 0.0D); +- serverlevel.playSound((Player) null, blockpos, SoundEvents.SCULK_CATALYST_BLOOM, SoundSource.BLOCKS, 2.0F, 0.6F + randomsource.nextFloat() * 0.4F); ++ public void bloom(ServerLevel level, BlockPos pos, IBlockData state, RandomSource random) { ++ level.setBlock(pos, (IBlockData) state.setValue(SculkCatalystBlock.PULSE, true), 3); ++ level.scheduleTick(pos, state.getBlock(), 8); ++ level.sendParticles(ParticleTypes.SCULK_SOUL, (double) pos.getX() + 0.5D, (double) pos.getY() + 1.15D, (double) pos.getZ() + 0.5D, 2, 0.2D, 0.0D, 0.2D, 0.0D); ++ level.playSound((Player) null, pos, SoundEvents.SCULK_CATALYST_BLOOM, SoundSource.BLOCKS, 2.0F, 0.6F + random.nextFloat() * 0.4F); + } + +- private void tryAwardItSpreadsAdvancement(Level level, LivingEntity livingentity) { +- LivingEntity livingentity1 = livingentity.getLastHurtByMob(); ++ private void tryAwardItSpreadsAdvancement(Level level, LivingEntity entity) { ++ LivingEntity entityliving1 = entity.getLastHurtByMob(); + +- if (livingentity1 instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) livingentity1; +- DamageSource damagesource = livingentity.getLastDamageSource() == null ? level.damageSources().playerAttack(serverplayer) : livingentity.getLastDamageSource(); ++ if (entityliving1 instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entityliving1; ++ DamageSource damagesource = entity.getLastDamageSource() == null ? level.damageSources().playerAttack(entityplayer) : entity.getLastDamageSource(); + +- CriteriaTriggers.KILL_MOB_NEAR_SCULK_CATALYST.trigger(serverplayer, livingentity, damagesource); ++ CriteriaTriggers.KILL_MOB_NEAR_SCULK_CATALYST.trigger(entityplayer, entity, damagesource); + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java.patch new file mode 100644 index 0000000000..dc23b35b07 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java.patch @@ -0,0 +1,361 @@ +--- a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java +@@ -15,7 +15,7 @@ + import net.minecraft.world.ContainerHelper; + import net.minecraft.world.WorldlyContainer; + import net.minecraft.world.entity.Entity; +-import net.minecraft.world.entity.MoverType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.monster.Shulker; + import net.minecraft.world.entity.player.Inventory; + import net.minecraft.world.entity.player.Player; +@@ -26,11 +26,15 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.ShulkerBoxBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; +-import net.minecraft.world.level.material.PushReaction; ++import net.minecraft.world.level.material.EnumPistonReaction; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end + + public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity implements WorldlyContainer { + +@@ -44,32 +48,63 @@ + public static final String ITEMS_TAG = "Items"; + private static final int[] SLOTS = IntStream.range(0, 27).toArray(); + private NonNullList itemStacks; +- private int openCount; +- private ShulkerBoxBlockEntity.AnimationStatus animationStatus; ++ public int openCount; ++ private ShulkerBoxBlockEntity.AnimationPhase animationStatus; + private float progress; + private float progressOld; + @Nullable + private final DyeColor color; + +- public ShulkerBoxBlockEntity(@Nullable DyeColor dyecolor, BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.SHULKER_BOX, blockpos, blockstate); ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ public boolean opened; ++ ++ public List getContents() { ++ return this.itemStacks; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ ++ public ShulkerBoxBlockEntity(@Nullable DyeColor color, BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.SHULKER_BOX, pos, blockState); + this.itemStacks = NonNullList.withSize(27, ItemStack.EMPTY); +- this.animationStatus = ShulkerBoxBlockEntity.AnimationStatus.CLOSED; +- this.color = dyecolor; ++ this.animationStatus = ShulkerBoxBlockEntity.AnimationPhase.CLOSED; ++ this.color = color; + } + +- public ShulkerBoxBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.SHULKER_BOX, blockpos, blockstate); ++ public ShulkerBoxBlockEntity(BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.SHULKER_BOX, pos, blockState); + this.itemStacks = NonNullList.withSize(27, ItemStack.EMPTY); +- this.animationStatus = ShulkerBoxBlockEntity.AnimationStatus.CLOSED; +- this.color = ShulkerBoxBlock.getColorFromBlock(blockstate.getBlock()); ++ this.animationStatus = ShulkerBoxBlockEntity.AnimationPhase.CLOSED; ++ this.color = ShulkerBoxBlock.getColorFromBlock(blockState.getBlock()); + } + +- public static void tick(Level level, BlockPos blockpos, BlockState blockstate, ShulkerBoxBlockEntity shulkerboxblockentity) { +- shulkerboxblockentity.updateAnimation(level, blockpos, blockstate); ++ public static void tick(Level level, BlockPos pos, IBlockData state, ShulkerBoxBlockEntity blockEntity) { ++ blockEntity.updateAnimation(level, pos, state); + } + +- private void updateAnimation(Level level, BlockPos blockpos, BlockState blockstate) { ++ private void updateAnimation(Level level, BlockPos pos, IBlockData state) { + this.progressOld = this.progress; + switch (this.animationStatus) { + case CLOSED: +@@ -78,27 +113,27 @@ + case OPENING: + this.progress += 0.1F; + if (this.progressOld == 0.0F) { +- doNeighborUpdates(level, blockpos, blockstate); ++ doNeighborUpdates(level, pos, state); + } + + if (this.progress >= 1.0F) { +- this.animationStatus = ShulkerBoxBlockEntity.AnimationStatus.OPENED; ++ this.animationStatus = ShulkerBoxBlockEntity.AnimationPhase.OPENED; + this.progress = 1.0F; +- doNeighborUpdates(level, blockpos, blockstate); ++ doNeighborUpdates(level, pos, state); + } + +- this.moveCollidedEntities(level, blockpos, blockstate); ++ this.moveCollidedEntities(level, pos, state); + break; + case CLOSING: + this.progress -= 0.1F; + if (this.progressOld == 1.0F) { +- doNeighborUpdates(level, blockpos, blockstate); ++ doNeighborUpdates(level, pos, state); + } + + if (this.progress <= 0.0F) { +- this.animationStatus = ShulkerBoxBlockEntity.AnimationStatus.CLOSED; ++ this.animationStatus = ShulkerBoxBlockEntity.AnimationPhase.CLOSED; + this.progress = 0.0F; +- doNeighborUpdates(level, blockpos, blockstate); ++ doNeighborUpdates(level, pos, state); + } + break; + case OPENED: +@@ -107,19 +142,19 @@ + + } + +- public ShulkerBoxBlockEntity.AnimationStatus getAnimationStatus() { ++ public ShulkerBoxBlockEntity.AnimationPhase getAnimationStatus() { + return this.animationStatus; + } + +- public AABB getBoundingBox(BlockState blockstate) { +- return Shulker.getProgressAabb((Direction) blockstate.getValue(ShulkerBoxBlock.FACING), 0.5F * this.getProgress(1.0F)); ++ public AABB getBoundingBox(IBlockData state) { ++ return Shulker.getProgressAabb((Direction) state.getValue(ShulkerBoxBlock.FACING), 0.5F * this.getProgress(1.0F)); + } + +- private void moveCollidedEntities(Level level, BlockPos blockpos, BlockState blockstate) { +- if (blockstate.getBlock() instanceof ShulkerBoxBlock) { +- Direction direction = (Direction) blockstate.getValue(ShulkerBoxBlock.FACING); +- AABB aabb = Shulker.getProgressDeltaAabb(direction, this.progressOld, this.progress).move(blockpos); +- List list = level.getEntities((Entity) null, aabb); ++ private void moveCollidedEntities(Level level, BlockPos pos, IBlockData state) { ++ if (state.getBlock() instanceof ShulkerBoxBlock) { ++ Direction enumdirection = (Direction) state.getValue(ShulkerBoxBlock.FACING); ++ AABB axisalignedbb = Shulker.getProgressDeltaAabb(enumdirection, this.progressOld, this.progress).move(pos); ++ List list = level.getEntities((Entity) null, axisalignedbb); + + if (!list.isEmpty()) { + Iterator iterator = list.iterator(); +@@ -127,8 +162,8 @@ + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); + +- if (entity.getPistonPushReaction() != PushReaction.IGNORE) { +- entity.move(MoverType.SHULKER_BOX, new Vec3((aabb.getXsize() + 0.01D) * (double) direction.getStepX(), (aabb.getYsize() + 0.01D) * (double) direction.getStepY(), (aabb.getZsize() + 0.01D) * (double) direction.getStepZ())); ++ if (entity.getPistonPushReaction() != EnumPistonReaction.IGNORE) { ++ entity.move(EnumMoveType.SHULKER_BOX, new Vec3((axisalignedbb.getXsize() + 0.01D) * (double) enumdirection.getStepX(), (axisalignedbb.getYsize() + 0.01D) * (double) enumdirection.getStepY(), (axisalignedbb.getZsize() + 0.01D) * (double) enumdirection.getStepZ())); + } + } + +@@ -137,37 +172,34 @@ + } + + @Override +- @Override + public int getContainerSize() { + return this.itemStacks.size(); + } + + @Override +- @Override +- public boolean triggerEvent(int i, int j) { +- if (i == 1) { +- this.openCount = j; +- if (j == 0) { +- this.animationStatus = ShulkerBoxBlockEntity.AnimationStatus.CLOSING; ++ public boolean triggerEvent(int id, int type) { ++ if (id == 1) { ++ this.openCount = type; ++ if (type == 0) { ++ this.animationStatus = ShulkerBoxBlockEntity.AnimationPhase.CLOSING; + } + +- if (j == 1) { +- this.animationStatus = ShulkerBoxBlockEntity.AnimationStatus.OPENING; ++ if (type == 1) { ++ this.animationStatus = ShulkerBoxBlockEntity.AnimationPhase.OPENING; + } + + return true; + } else { +- return super.triggerEvent(i, j); ++ return super.triggerEvent(id, type); + } + } + +- private static void doNeighborUpdates(Level level, BlockPos blockpos, BlockState blockstate) { +- blockstate.updateNeighbourShapes(level, blockpos, 3); +- level.updateNeighborsAt(blockpos, blockstate.getBlock()); ++ private static void doNeighborUpdates(Level level, BlockPos pos, IBlockData state) { ++ state.updateNeighbourShapes(level, pos, 3); ++ level.updateNeighborsAt(pos, state.getBlock()); + } + + @Override +- @Override + public void startOpen(Player player) { + if (!this.remove && !player.isSpectator()) { + if (this.openCount < 0) { +@@ -175,6 +207,7 @@ + } + + ++this.openCount; ++ if (opened) return; // CraftBukkit - only animate if the ShulkerBox hasn't been forced open already by an API call. + this.level.blockEvent(this.worldPosition, this.getBlockState().getBlock(), 1, this.openCount); + if (this.openCount == 1) { + this.level.gameEvent((Entity) player, GameEvent.CONTAINER_OPEN, this.worldPosition); +@@ -185,10 +218,10 @@ + } + + @Override +- @Override + public void stopOpen(Player player) { + if (!this.remove && !player.isSpectator()) { + --this.openCount; ++ if (opened) return; // CraftBukkit - only animate if the ShulkerBox hasn't been forced open already by an API call. + this.level.blockEvent(this.worldPosition, this.getBlockState().getBlock(), 1, this.openCount); + if (this.openCount <= 0) { + this.level.gameEvent((Entity) player, GameEvent.CONTAINER_CLOSE, this.worldPosition); +@@ -199,68 +232,60 @@ + } + + @Override +- @Override + protected Component getDefaultName() { + return Component.translatable("container.shulkerBox"); + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); +- this.loadFromTag(compoundtag); ++ public void load(CompoundTag tag) { ++ super.load(tag); ++ this.loadFromTag(tag); + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); +- if (!this.trySaveLootTable(compoundtag)) { +- ContainerHelper.saveAllItems(compoundtag, this.itemStacks, false); ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); ++ if (!this.trySaveLootTable(tag)) { ++ ContainerHelper.saveAllItems(tag, this.itemStacks, false); + } + + } + +- public void loadFromTag(CompoundTag compoundtag) { ++ public void loadFromTag(CompoundTag tag) { + this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); +- if (!this.tryLoadLootTable(compoundtag) && compoundtag.contains("Items", 9)) { +- ContainerHelper.loadAllItems(compoundtag, this.itemStacks); ++ if (!this.tryLoadLootTable(tag) && tag.contains("Items", 9)) { ++ ContainerHelper.loadAllItems(tag, this.itemStacks); + } + + } + + @Override +- @Override + protected NonNullList getItems() { + return this.itemStacks; + } + + @Override +- @Override +- protected void setItems(NonNullList nonnulllist) { +- this.itemStacks = nonnulllist; ++ protected void setItems(NonNullList items) { ++ this.itemStacks = items; + } + + @Override +- @Override +- public int[] getSlotsForFace(Direction direction) { ++ public int[] getSlotsForFace(Direction side) { + return ShulkerBoxBlockEntity.SLOTS; + } + + @Override +- @Override +- public boolean canPlaceItemThroughFace(int i, ItemStack itemstack, @Nullable Direction direction) { +- return !(Block.byItem(itemstack.getItem()) instanceof ShulkerBoxBlock); ++ public boolean canPlaceItemThroughFace(int index, ItemStack itemStack, @Nullable Direction direction) { ++ return !(Block.byItem(itemStack.getItem()) instanceof ShulkerBoxBlock); + } + + @Override +- @Override +- public boolean canTakeItemThroughFace(int i, ItemStack itemstack, Direction direction) { ++ public boolean canTakeItemThroughFace(int index, ItemStack stack, Direction direction) { + return true; + } + +- public float getProgress(float f) { +- return Mth.lerp(f, this.progressOld, this.progress); ++ public float getProgress(float partialTicks) { ++ return Mth.lerp(partialTicks, this.progressOld, this.progress); + } + + @Nullable +@@ -269,19 +294,18 @@ + } + + @Override +- @Override +- protected AbstractContainerMenu createMenu(int i, Inventory inventory) { +- return new ShulkerBoxMenu(i, inventory, this); ++ protected AbstractContainerMenu createMenu(int id, Inventory player) { ++ return new ShulkerBoxMenu(id, player, this); + } + + public boolean isClosed() { +- return this.animationStatus == ShulkerBoxBlockEntity.AnimationStatus.CLOSED; ++ return this.animationStatus == ShulkerBoxBlockEntity.AnimationPhase.CLOSED; + } + +- public static enum AnimationStatus { ++ public static enum AnimationPhase { + + CLOSED, OPENING, OPENED, CLOSING; + +- private AnimationStatus() {} ++ private AnimationPhase() {} + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/SignBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/SignBlockEntity.java.patch new file mode 100644 index 0000000000..e8cb80dc90 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/SignBlockEntity.java.patch @@ -0,0 +1,454 @@ +--- a/net/minecraft/world/level/block/entity/SignBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/SignBlockEntity.java +@@ -13,43 +13,50 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.Tag; + import net.minecraft.network.chat.ClickEvent; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.ComponentUtils; + import net.minecraft.network.chat.Style; + import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.network.FilteredText; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.SignBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; ++import org.bukkit.block.sign.Side; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.entity.Player; ++import org.bukkit.event.block.SignChangeEvent; ++// CraftBukkit end + +-public class SignBlockEntity extends BlockEntity { ++public class SignBlockEntity extends BlockEntity implements CommandSource { // CraftBukkit - implements + + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int MAX_TEXT_LINE_WIDTH = 90; + private static final int TEXT_LINE_HEIGHT = 10; + @Nullable +- private UUID playerWhoMayEdit; ++ public UUID playerWhoMayEdit; + private SignText frontText; + private SignText backText; + private boolean isWaxed; + +- public SignBlockEntity(BlockPos blockpos, BlockState blockstate) { +- this(BlockEntityType.SIGN, blockpos, blockstate); ++ public SignBlockEntity(BlockPos pos, IBlockData blockState) { ++ this(BlockEntityType.SIGN, pos, blockState); + } + +- public SignBlockEntity(BlockEntityType blockentitytype, BlockPos blockpos, BlockState blockstate) { +- super(blockentitytype, blockpos, blockstate); ++ public SignBlockEntity(BlockEntityType type, BlockPos pos, IBlockData blockState) { ++ super(type, pos, blockState); + this.frontText = this.createDefaultSignText(); + this.backText = this.createDefaultSignText(); + } +@@ -58,15 +65,15 @@ + return new SignText(); + } + +- public boolean isFacingFrontText(Player player) { ++ public boolean isFacingFrontText(net.minecraft.world.entity.player.Player player) { + Block block = this.getBlockState().getBlock(); + + if (block instanceof SignBlock) { +- SignBlock signblock = (SignBlock) block; +- Vec3 vec3 = signblock.getSignHitboxCenterPosition(this.getBlockState()); +- double d0 = player.getX() - ((double) this.getBlockPos().getX() + vec3.x); +- double d1 = player.getZ() - ((double) this.getBlockPos().getZ() + vec3.z); +- float f = signblock.getYRotationDegrees(this.getBlockState()); ++ SignBlock blocksign = (SignBlock) block; ++ Vec3 vec3d = blocksign.getSignHitboxCenterPosition(this.getBlockState()); ++ double d0 = player.getX() - ((double) this.getBlockPos().getX() + vec3d.x); ++ double d1 = player.getZ() - ((double) this.getBlockPos().getZ() + vec3d.z); ++ float f = blocksign.getYRotationDegrees(this.getBlockState()); + float f1 = (float) (Mth.atan2(d1, d0) * 57.2957763671875D) - 90.0F; + + return Mth.degreesDifferenceAbs(f, f1) <= 90.0F; +@@ -75,8 +82,8 @@ + } + } + +- public SignText getText(boolean flag) { +- return flag ? this.frontText : this.backText; ++ public SignText getText(boolean isFrontText) { ++ return isFrontText ? this.frontText : this.backText; + } + + public SignText getFrontText() { +@@ -96,34 +103,32 @@ + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); +- DataResult dataresult = SignText.DIRECT_CODEC.encodeStart(NbtOps.INSTANCE, this.frontText); ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); ++ DataResult dataresult = SignText.DIRECT_CODEC.encodeStart(NbtOps.INSTANCE, this.frontText); // CraftBukkit - decompile error + Logger logger = SignBlockEntity.LOGGER; + + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((tag) -> { +- compoundtag.put("front_text", tag); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ tag.put("front_text", nbtbase); + }); + dataresult = SignText.DIRECT_CODEC.encodeStart(NbtOps.INSTANCE, this.backText); + logger = SignBlockEntity.LOGGER; + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((tag) -> { +- compoundtag.put("back_text", tag); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ tag.put("back_text", nbtbase); + }); +- compoundtag.putBoolean("is_waxed", this.isWaxed); ++ tag.putBoolean("is_waxed", this.isWaxed); + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); +- DataResult dataresult; ++ public void load(CompoundTag tag) { ++ super.load(tag); ++ DataResult dataresult; // CraftBukkit - decompile error + Logger logger; + +- if (compoundtag.contains("front_text")) { +- dataresult = SignText.DIRECT_CODEC.parse(NbtOps.INSTANCE, compoundtag.getCompound("front_text")); ++ if (tag.contains("front_text")) { ++ dataresult = SignText.DIRECT_CODEC.parse(NbtOps.INSTANCE, tag.getCompound("front_text")); + logger = SignBlockEntity.LOGGER; + Objects.requireNonNull(logger); + dataresult.resultOrPartial(logger::error).ifPresent((signtext) -> { +@@ -131,8 +136,8 @@ + }); + } + +- if (compoundtag.contains("back_text")) { +- dataresult = SignText.DIRECT_CODEC.parse(NbtOps.INSTANCE, compoundtag.getCompound("back_text")); ++ if (tag.contains("back_text")) { ++ dataresult = SignText.DIRECT_CODEC.parse(NbtOps.INSTANCE, tag.getCompound("back_text")); + logger = SignBlockEntity.LOGGER; + Objects.requireNonNull(logger); + dataresult.resultOrPartial(logger::error).ifPresent((signtext) -> { +@@ -140,76 +145,101 @@ + }); + } + +- this.isWaxed = compoundtag.getBoolean("is_waxed"); ++ this.isWaxed = tag.getBoolean("is_waxed"); + } + +- private SignText loadLines(SignText signtext) { ++ private SignText loadLines(SignText text) { + for (int i = 0; i < 4; ++i) { +- Component component = this.loadLine(signtext.getMessage(i, false)); +- Component component1 = this.loadLine(signtext.getMessage(i, true)); ++ Component ichatbasecomponent = this.loadLine(text.getMessage(i, false)); ++ Component ichatbasecomponent1 = this.loadLine(text.getMessage(i, true)); + +- signtext = signtext.setMessage(i, component, component1); ++ text = text.setMessage(i, ichatbasecomponent, ichatbasecomponent1); + } + +- return signtext; ++ return text; + } + +- private Component loadLine(Component component) { +- Level level = this.level; ++ private Component loadLine(Component lineText) { ++ Level world = this.level; + +- if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; + + try { +- return ComponentUtils.updateForEntity(createCommandSourceStack((Player) null, serverlevel, this.worldPosition), component, (Entity) null, 0); ++ return ComponentUtils.updateForEntity(createCommandSourceStack((net.minecraft.world.entity.player.Player) null, worldserver, this.worldPosition), lineText, (Entity) null, 0); + } catch (CommandSyntaxException commandsyntaxexception) { + ; + } + } + +- return component; ++ return lineText; + } + +- public void updateSignText(Player player, boolean flag, List list) { ++ public void updateSignText(net.minecraft.world.entity.player.Player player, boolean isFrontText, List filteredText) { + if (!this.isWaxed() && player.getUUID().equals(this.getPlayerWhoMayEdit()) && this.level != null) { + this.updateText((signtext) -> { +- return this.setMessages(player, list, signtext); +- }, flag); ++ return this.setMessages(player, filteredText, signtext, isFrontText); // CraftBukkit ++ }, isFrontText); + this.setAllowedPlayerEditor((UUID) null); + this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3); + } else { + SignBlockEntity.LOGGER.warn("Player {} just tried to change non-editable sign", player.getName().getString()); ++ ((ServerPlayer) player).connection.send(this.getUpdatePacket()); // CraftBukkit + } + } + +- public boolean updateText(UnaryOperator unaryoperator, boolean flag) { +- SignText signtext = this.getText(flag); ++ public boolean updateText(UnaryOperator updater, boolean isFrontText) { ++ SignText signtext = this.getText(isFrontText); + +- return this.setText((SignText) unaryoperator.apply(signtext), flag); ++ return this.setText((SignText) updater.apply(signtext), isFrontText); + } + +- private SignText setMessages(Player player, List list, SignText signtext) { ++ private SignText setMessages(net.minecraft.world.entity.player.Player entityhuman, List list, SignText signtext, boolean front) { // CraftBukkit ++ SignText originalText = signtext; // CraftBukkit + for (int i = 0; i < list.size(); ++i) { + FilteredText filteredtext = (FilteredText) list.get(i); +- Style style = signtext.getMessage(i, player.isTextFilteringEnabled()).getStyle(); ++ Style chatmodifier = signtext.getMessage(i, entityhuman.isTextFilteringEnabled()).getStyle(); + +- if (player.isTextFilteringEnabled()) { +- signtext = signtext.setMessage(i, Component.literal(filteredtext.filteredOrEmpty()).setStyle(style)); ++ if (entityhuman.isTextFilteringEnabled()) { ++ signtext = signtext.setMessage(i, Component.literal(filteredtext.filteredOrEmpty()).setStyle(chatmodifier)); + } else { +- signtext = signtext.setMessage(i, Component.literal(filteredtext.raw()).setStyle(style), Component.literal(filteredtext.filteredOrEmpty()).setStyle(style)); ++ signtext = signtext.setMessage(i, Component.literal(filteredtext.raw()).setStyle(chatmodifier), Component.literal(filteredtext.filteredOrEmpty()).setStyle(chatmodifier)); + } + } + ++ // CraftBukkit start ++ Player player = ((ServerPlayer) entityhuman).getBukkitEntity(); ++ String[] lines = new String[4]; ++ ++ for (int i = 0; i < list.size(); ++i) { ++ lines[i] = CraftChatMessage.fromComponent(signtext.getMessage(i, entityhuman.isTextFilteringEnabled())); ++ } ++ ++ SignChangeEvent event = new SignChangeEvent(CraftBlock.at(this.level, this.worldPosition), player, lines.clone(), (front) ? Side.FRONT : Side.BACK); ++ entityhuman.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return originalText; ++ } ++ ++ Component[] components = org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()); ++ for (int i = 0; i < components.length; i++) { ++ if (!Objects.equals(lines[i], event.getLine(i))) { ++ signtext = signtext.setMessage(i, components[i]); ++ } ++ } ++ // CraftBukkit end ++ + return signtext; + } + +- public boolean setText(SignText signtext, boolean flag) { +- return flag ? this.setFrontText(signtext) : this.setBackText(signtext); ++ public boolean setText(SignText text, boolean isFrontText) { ++ return isFrontText ? this.setFrontText(text) : this.setBackText(text); + } + +- private boolean setBackText(SignText signtext) { +- if (signtext != this.backText) { +- this.backText = signtext; ++ private boolean setBackText(SignText text) { ++ if (text != this.backText) { ++ this.backText = text; + this.markUpdated(); + return true; + } else { +@@ -217,9 +247,9 @@ + } + } + +- private boolean setFrontText(SignText signtext) { +- if (signtext != this.frontText) { +- this.frontText = signtext; ++ private boolean setFrontText(SignText text) { ++ if (text != this.frontText) { ++ this.frontText = text; + this.markUpdated(); + return true; + } else { +@@ -227,22 +257,22 @@ + } + } + +- public boolean canExecuteClickCommands(boolean flag, Player player) { +- return this.isWaxed() && this.getText(flag).hasAnyClickCommands(player); ++ public boolean canExecuteClickCommands(boolean isFrontText, net.minecraft.world.entity.player.Player player) { ++ return this.isWaxed() && this.getText(isFrontText).hasAnyClickCommands(player); + } + +- public boolean executeClickCommandsIfPresent(Player player, Level level, BlockPos blockpos, boolean flag) { ++ public boolean executeClickCommandsIfPresent(net.minecraft.world.entity.player.Player player, Level level, BlockPos pos, boolean frontText) { + boolean flag1 = false; +- Component[] acomponent = this.getText(flag).getMessages(player.isTextFilteringEnabled()); +- int i = acomponent.length; ++ Component[] aichatbasecomponent = this.getText(frontText).getMessages(player.isTextFilteringEnabled()); ++ int i = aichatbasecomponent.length; + + for (int j = 0; j < i; ++j) { +- Component component = acomponent[j]; +- Style style = component.getStyle(); +- ClickEvent clickevent = style.getClickEvent(); ++ Component ichatbasecomponent = aichatbasecomponent[j]; ++ Style chatmodifier = ichatbasecomponent.getStyle(); ++ ClickEvent chatclickable = chatmodifier.getClickEvent(); + +- if (clickevent != null && clickevent.getAction() == ClickEvent.Action.RUN_COMMAND) { +- player.getServer().getCommands().performPrefixedCommand(createCommandSourceStack(player, level, blockpos), clickevent.getValue()); ++ if (chatclickable != null && chatclickable.getAction() == ClickEvent.Action.RUN_COMMAND) { ++ player.getServer().getCommands().performPrefixedCommand(createCommandSourceStack(player, level, pos), chatclickable.getValue()); + flag1 = true; + } + } +@@ -250,52 +280,80 @@ + return flag1; + } + +- private static CommandSourceStack createCommandSourceStack(@Nullable Player player, Level level, BlockPos blockpos) { +- String s = player == null ? "Sign" : player.getName().getString(); +- Object object = player == null ? Component.literal("Sign") : player.getDisplayName(); ++ // CraftBukkit start ++ @Override ++ public void sendSystemMessage(Component component) {} + +- return new CommandSourceStack(CommandSource.NULL, Vec3.atCenterOf(blockpos), Vec2.ZERO, (ServerLevel) level, 2, s, (Component) object, level.getServer(), player); ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return wrapper.getEntity() != null ? wrapper.getEntity().getBukkitSender(wrapper) : new org.bukkit.craftbukkit.command.CraftBlockCommandSender(wrapper, this); + } + + @Override ++ public boolean acceptsSuccess() { ++ return false; ++ } ++ + @Override ++ public boolean acceptsFailure() { ++ return false; ++ } ++ ++ @Override ++ public boolean shouldInformAdmins() { ++ return false; ++ } ++ ++ private CommandSourceStack createCommandSourceStack(@Nullable net.minecraft.world.entity.player.Player level, Level pos, BlockPos blockposition) { ++ // CraftBukkit end ++ String s = level == null ? "Sign" : level.getName().getString(); ++ Object object = level == null ? Component.literal("Sign") : level.getDisplayName(); ++ ++ // CraftBukkit - this ++ return new CommandSourceStack(this, Vec3.atCenterOf(blockposition), Vec2.ZERO, (ServerLevel) pos, 2, s, (Component) object, pos.getServer(), level); ++ } ++ ++ @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + @Override +- @Override + public CompoundTag getUpdateTag() { + return this.saveWithoutMetadata(); + } + + @Override +- @Override + public boolean onlyOpCanSetNbt() { + return true; + } + +- public void setAllowedPlayerEditor(@Nullable UUID uuid) { +- this.playerWhoMayEdit = uuid; ++ public void setAllowedPlayerEditor(@Nullable UUID playWhoMayEdit) { ++ this.playerWhoMayEdit = playWhoMayEdit; + } + + @Nullable + public UUID getPlayerWhoMayEdit() { ++ // CraftBukkit start - unnecessary sign ticking removed, so do this lazily ++ if (this.level != null && this.playerWhoMayEdit != null) { ++ clearInvalidPlayerWhoMayEdit(this, this.level, this.playerWhoMayEdit); ++ } ++ // CraftBukkit end + return this.playerWhoMayEdit; + } + + private void markUpdated() { + this.setChanged(); +- this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3); ++ if (this.level != null) this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3); // CraftBukkit - skip notify if world is null (SPIGOT-5122) + } + + public boolean isWaxed() { + return this.isWaxed; + } + +- public boolean setWaxed(boolean flag) { +- if (this.isWaxed != flag) { +- this.isWaxed = flag; ++ public boolean setWaxed(boolean isWaxed) { ++ if (this.isWaxed != isWaxed) { ++ this.isWaxed = isWaxed; + this.markUpdated(); + return true; + } else { +@@ -304,23 +362,23 @@ + } + + public boolean playerIsTooFarAwayToEdit(UUID uuid) { +- Player player = this.level.getPlayerByUUID(uuid); ++ net.minecraft.world.entity.player.Player entityhuman = this.level.getPlayerByUUID(uuid); + +- return player == null || player.distanceToSqr((double) this.getBlockPos().getX(), (double) this.getBlockPos().getY(), (double) this.getBlockPos().getZ()) > 64.0D; ++ return entityhuman == null || entityhuman.distanceToSqr((double) this.getBlockPos().getX(), (double) this.getBlockPos().getY(), (double) this.getBlockPos().getZ()) > 64.0D; + } + +- public static void tick(Level level, BlockPos blockpos, BlockState blockstate, SignBlockEntity signblockentity) { +- UUID uuid = signblockentity.getPlayerWhoMayEdit(); ++ public static void tick(Level level, BlockPos pos, IBlockData state, SignBlockEntity sign) { ++ UUID uuid = sign.getPlayerWhoMayEdit(); + + if (uuid != null) { +- signblockentity.clearInvalidPlayerWhoMayEdit(signblockentity, level, uuid); ++ sign.clearInvalidPlayerWhoMayEdit(sign, level, uuid); + } + + } + +- private void clearInvalidPlayerWhoMayEdit(SignBlockEntity signblockentity, Level level, UUID uuid) { +- if (signblockentity.playerIsTooFarAwayToEdit(uuid)) { +- signblockentity.setAllowedPlayerEditor((UUID) null); ++ private void clearInvalidPlayerWhoMayEdit(SignBlockEntity sign, Level level, UUID uuid) { ++ if (sign.playerIsTooFarAwayToEdit(uuid)) { ++ sign.setAllowedPlayerEditor((UUID) null); + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/SkullBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/SkullBlockEntity.java.patch new file mode 100644 index 0000000000..3dfdcb5b2c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/SkullBlockEntity.java.patch @@ -0,0 +1,199 @@ +--- a/net/minecraft/world/level/block/entity/SkullBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/SkullBlockEntity.java +@@ -23,7 +23,7 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.SkullBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public class SkullBlockEntity extends BlockEntity { + +@@ -42,24 +42,23 @@ + + }; + @Nullable +- private GameProfile owner; ++ public GameProfile owner; + @Nullable +- private ResourceLocation noteBlockSound; ++ public ResourceLocation noteBlockSound; + private int animationTickCount; + private boolean isAnimating; + +- public SkullBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.SKULL, blockpos, blockstate); ++ public SkullBlockEntity(BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.SKULL, pos, blockState); + } + +- public static void setup(final Services services, Executor executor) { +- SkullBlockEntity.mainThreadExecutor = executor; ++ public static void setup(final Services services, Executor mainThreadExecutor) { ++ SkullBlockEntity.mainThreadExecutor = mainThreadExecutor; + final BooleanSupplier booleansupplier = () -> { + return SkullBlockEntity.profileCache == null; + }; + + SkullBlockEntity.profileCache = CacheBuilder.newBuilder().expireAfterAccess(Duration.ofMinutes(10L)).maximumSize(256L).build(new CacheLoader>>() { +- @Override + public CompletableFuture> load(String s) { + return booleansupplier.getAsBoolean() ? CompletableFuture.completedFuture(Optional.empty()) : SkullBlockEntity.loadProfile(s, services, booleansupplier); + } +@@ -85,54 +84,52 @@ + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); + if (this.owner != null) { +- CompoundTag compoundtag1 = new CompoundTag(); ++ CompoundTag nbttagcompound1 = new CompoundTag(); + +- NbtUtils.writeGameProfile(compoundtag1, this.owner); +- compoundtag.put("SkullOwner", compoundtag1); ++ NbtUtils.writeGameProfile(nbttagcompound1, this.owner); ++ tag.put("SkullOwner", nbttagcompound1); + } + + if (this.noteBlockSound != null) { +- compoundtag.putString("note_block_sound", this.noteBlockSound.toString()); ++ tag.putString("note_block_sound", this.noteBlockSound.toString()); + } + + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); +- if (compoundtag.contains("SkullOwner", 10)) { +- this.setOwner(NbtUtils.readGameProfile(compoundtag.getCompound("SkullOwner"))); +- } else if (compoundtag.contains("ExtraType", 8)) { +- String s = compoundtag.getString("ExtraType"); ++ public void load(CompoundTag tag) { ++ super.load(tag); ++ if (tag.contains("SkullOwner", 10)) { ++ this.setOwner(NbtUtils.readGameProfile(tag.getCompound("SkullOwner"))); ++ } else if (tag.contains("ExtraType", 8)) { ++ String s = tag.getString("ExtraType"); + + if (!StringUtil.isNullOrEmpty(s)) { + this.setOwner(new GameProfile(Util.NIL_UUID, s)); + } + } + +- if (compoundtag.contains("note_block_sound", 8)) { +- this.noteBlockSound = ResourceLocation.tryParse(compoundtag.getString("note_block_sound")); ++ if (tag.contains("note_block_sound", 8)) { ++ this.noteBlockSound = ResourceLocation.tryParse(tag.getString("note_block_sound")); + } + + } + +- public static void animation(Level level, BlockPos blockpos, BlockState blockstate, SkullBlockEntity skullblockentity) { +- if (blockstate.hasProperty(SkullBlock.POWERED) && (Boolean) blockstate.getValue(SkullBlock.POWERED)) { +- skullblockentity.isAnimating = true; +- ++skullblockentity.animationTickCount; ++ public static void animation(Level level, BlockPos pos, IBlockData state, SkullBlockEntity blockEntity) { ++ if (state.hasProperty(SkullBlock.POWERED) && (Boolean) state.getValue(SkullBlock.POWERED)) { ++ blockEntity.isAnimating = true; ++ ++blockEntity.animationTickCount; + } else { +- skullblockentity.isAnimating = false; ++ blockEntity.isAnimating = false; + } + + } + +- public float getAnimation(float f) { +- return this.isAnimating ? (float) this.animationTickCount + f : (float) this.animationTickCount; ++ public float getAnimation(float partialTick) { ++ return this.isAnimating ? (float) this.animationTickCount + partialTick : (float) this.animationTickCount; + } + + @Nullable +@@ -146,20 +143,18 @@ + } + + @Override +- @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + @Override +- @Override + public CompoundTag getUpdateTag() { + return this.saveWithoutMetadata(); + } + +- public void setOwner(@Nullable GameProfile gameprofile) { ++ public void setOwner(@Nullable GameProfile owner) { + synchronized (this) { +- this.owner = gameprofile; ++ this.owner = owner; + } + + this.updateOwnerProfile(); +@@ -177,16 +172,16 @@ + } + + @Nullable +- public static GameProfile getOrResolveGameProfile(CompoundTag compoundtag) { +- if (compoundtag.contains("SkullOwner", 10)) { +- return NbtUtils.readGameProfile(compoundtag.getCompound("SkullOwner")); ++ public static GameProfile getOrResolveGameProfile(CompoundTag nbttagcompound) { ++ if (nbttagcompound.contains("SkullOwner", 10)) { ++ return NbtUtils.readGameProfile(nbttagcompound.getCompound("SkullOwner")); + } else { +- if (compoundtag.contains("SkullOwner", 8)) { +- String s = compoundtag.getString("SkullOwner"); ++ if (nbttagcompound.contains("SkullOwner", 8)) { ++ String s = nbttagcompound.getString("SkullOwner"); + + if (!Util.isBlank(s)) { +- compoundtag.remove("SkullOwner"); +- resolveGameProfile(compoundtag, s); ++ nbttagcompound.remove("SkullOwner"); ++ resolveGameProfile(nbttagcompound, s); + } + } + +@@ -194,18 +189,28 @@ + } + } + +- public static void resolveGameProfile(CompoundTag compoundtag) { +- String s = compoundtag.getString("SkullOwner"); ++ public static void resolveGameProfile(CompoundTag nbttagcompound) { ++ String s = nbttagcompound.getString("SkullOwner"); + + if (!Util.isBlank(s)) { +- resolveGameProfile(compoundtag, s); ++ resolveGameProfile(nbttagcompound, s); ++ // CraftBukkit start ++ } else { ++ net.minecraft.nbt.ListTag textures = nbttagcompound.getCompound("SkullOwner").getCompound("Properties").getList("textures", 10); // Safe due to method contracts ++ for (int i = 0; i < textures.size(); i++) { ++ if (textures.get(i) instanceof CompoundTag && !((CompoundTag) textures.get(i)).contains("Signature", 8) && ((CompoundTag) textures.get(i)).getString("Value").trim().isEmpty()) { ++ nbttagcompound.remove("SkullOwner"); ++ break; ++ } ++ } ++ // CraftBukkit end + } + + } + +- private static void resolveGameProfile(CompoundTag compoundtag, String s) { ++ private static void resolveGameProfile(CompoundTag nbttagcompound, String s) { + fetchGameProfile(s).thenAccept((optional) -> { +- compoundtag.put("SkullOwner", NbtUtils.writeGameProfile(new CompoundTag(), (GameProfile) optional.orElse(new GameProfile(Util.NIL_UUID, s)))); ++ nbttagcompound.put("SkullOwner", NbtUtils.writeGameProfile(new CompoundTag(), (GameProfile) optional.orElse(new GameProfile(Util.NIL_UUID, s)))); + }); + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java.patch new file mode 100644 index 0000000000..655c780eec --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java.patch @@ -0,0 +1,475 @@ +--- a/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +@@ -24,14 +24,20 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.LevelChunk; ++import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; + import net.minecraft.world.level.levelgen.feature.Feature; + import net.minecraft.world.level.levelgen.feature.configurations.EndGatewayConfiguration; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.player.PlayerTeleportEvent; ++// CraftBukkit end + + public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { + +@@ -41,76 +47,74 @@ + private static final int ATTENTION_INTERVAL = 2400; + private static final int EVENT_COOLDOWN = 1; + private static final int GATEWAY_HEIGHT_ABOVE_SURFACE = 10; +- private long age; ++ public long age; + private int teleportCooldown; + @Nullable +- private BlockPos exitPortal; +- private boolean exactTeleport; ++ public BlockPos exitPortal; ++ public boolean exactTeleport; + +- public TheEndGatewayBlockEntity(BlockPos blockpos, BlockState blockstate) { +- super(BlockEntityType.END_GATEWAY, blockpos, blockstate); ++ public TheEndGatewayBlockEntity(BlockPos pos, IBlockData blockState) { ++ super(BlockEntityType.END_GATEWAY, pos, blockState); + } + + @Override +- @Override +- protected void saveAdditional(CompoundTag compoundtag) { +- super.saveAdditional(compoundtag); +- compoundtag.putLong("Age", this.age); ++ protected void saveAdditional(CompoundTag tag) { ++ super.saveAdditional(tag); ++ tag.putLong("Age", this.age); + if (this.exitPortal != null) { +- compoundtag.put("ExitPortal", NbtUtils.writeBlockPos(this.exitPortal)); ++ tag.put("ExitPortal", NbtUtils.writeBlockPos(this.exitPortal)); + } + + if (this.exactTeleport) { +- compoundtag.putBoolean("ExactTeleport", true); ++ tag.putBoolean("ExactTeleport", true); + } + + } + + @Override +- @Override +- public void load(CompoundTag compoundtag) { +- super.load(compoundtag); +- this.age = compoundtag.getLong("Age"); +- if (compoundtag.contains("ExitPortal", 10)) { +- BlockPos blockpos = NbtUtils.readBlockPos(compoundtag.getCompound("ExitPortal")); ++ public void load(CompoundTag tag) { ++ super.load(tag); ++ this.age = tag.getLong("Age"); ++ if (tag.contains("ExitPortal", 10)) { ++ BlockPos blockposition = NbtUtils.readBlockPos(tag.getCompound("ExitPortal")); + +- if (Level.isInSpawnableBounds(blockpos)) { +- this.exitPortal = blockpos; ++ if (Level.isInSpawnableBounds(blockposition)) { ++ this.exitPortal = blockposition; + } + } + +- this.exactTeleport = compoundtag.getBoolean("ExactTeleport"); ++ this.exactTeleport = tag.getBoolean("ExactTeleport"); + } + +- public static void beamAnimationTick(Level level, BlockPos blockpos, BlockState blockstate, TheEndGatewayBlockEntity theendgatewayblockentity) { +- ++theendgatewayblockentity.age; +- if (theendgatewayblockentity.isCoolingDown()) { +- --theendgatewayblockentity.teleportCooldown; ++ public static void beamAnimationTick(Level level, BlockPos pos, IBlockData state, TheEndGatewayBlockEntity blockEntity) { ++ ++blockEntity.age; ++ if (blockEntity.isCoolingDown()) { ++ --blockEntity.teleportCooldown; + } + + } + +- public static void teleportTick(Level level, BlockPos blockpos, BlockState blockstate, TheEndGatewayBlockEntity theendgatewayblockentity) { +- boolean flag = theendgatewayblockentity.isSpawning(); +- boolean flag1 = theendgatewayblockentity.isCoolingDown(); ++ public static void teleportTick(Level level, BlockPos pos, IBlockData state, TheEndGatewayBlockEntity blockEntity) { ++ boolean flag = blockEntity.isSpawning(); ++ boolean flag1 = blockEntity.isCoolingDown(); + +- ++theendgatewayblockentity.age; ++ ++blockEntity.age; + if (flag1) { +- --theendgatewayblockentity.teleportCooldown; ++ --blockEntity.teleportCooldown; + } else { +- List list = level.getEntitiesOfClass(Entity.class, new AABB(blockpos), TheEndGatewayBlockEntity::canEntityTeleport); ++ List list = level.getEntitiesOfClass(Entity.class, new AABB(pos), TheEndGatewayBlockEntity::canEntityTeleport); + + if (!list.isEmpty()) { +- teleportEntity(level, blockpos, blockstate, (Entity) list.get(level.random.nextInt(list.size())), theendgatewayblockentity); ++ teleportEntity(level, pos, state, (Entity) list.get(level.random.nextInt(list.size())), blockEntity); + } + +- if (theendgatewayblockentity.age % 2400L == 0L) { +- triggerCooldown(level, blockpos, blockstate, theendgatewayblockentity); ++ if (blockEntity.age % 2400L == 0L) { ++ triggerCooldown(level, pos, state, blockEntity); + } + } + +- if (flag != theendgatewayblockentity.isSpawning() || flag1 != theendgatewayblockentity.isCoolingDown()) { +- setChanged(level, blockpos, blockstate); ++ if (flag != blockEntity.isSpawning() || flag1 != blockEntity.isCoolingDown()) { ++ setChanged(level, pos, state); + } + + } +@@ -127,70 +131,67 @@ + return this.teleportCooldown > 0; + } + +- public float getSpawnPercent(float f) { +- return Mth.clamp(((float) this.age + f) / 200.0F, 0.0F, 1.0F); ++ public float getSpawnPercent(float partialTicks) { ++ return Mth.clamp(((float) this.age + partialTicks) / 200.0F, 0.0F, 1.0F); + } + +- public float getCooldownPercent(float f) { +- return 1.0F - Mth.clamp(((float) this.teleportCooldown - f) / 40.0F, 0.0F, 1.0F); ++ public float getCooldownPercent(float partialTicks) { ++ return 1.0F - Mth.clamp(((float) this.teleportCooldown - partialTicks) / 40.0F, 0.0F, 1.0F); + } + + @Override +- @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + @Override +- @Override + public CompoundTag getUpdateTag() { + return this.saveWithoutMetadata(); + } + +- private static void triggerCooldown(Level level, BlockPos blockpos, BlockState blockstate, TheEndGatewayBlockEntity theendgatewayblockentity) { ++ private static void triggerCooldown(Level level, BlockPos pos, IBlockData state, TheEndGatewayBlockEntity blockEntity) { + if (!level.isClientSide) { +- theendgatewayblockentity.teleportCooldown = 40; +- level.blockEvent(blockpos, blockstate.getBlock(), 1, 0); +- setChanged(level, blockpos, blockstate); ++ blockEntity.teleportCooldown = 40; ++ level.blockEvent(pos, state.getBlock(), 1, 0); ++ setChanged(level, pos, state); + } + + } + + @Override +- @Override +- public boolean triggerEvent(int i, int j) { +- if (i == 1) { ++ public boolean triggerEvent(int id, int type) { ++ if (id == 1) { + this.teleportCooldown = 40; + return true; + } else { +- return super.triggerEvent(i, j); ++ return super.triggerEvent(id, type); + } + } + +- public static void teleportEntity(Level level, BlockPos blockpos, BlockState blockstate, Entity entity, TheEndGatewayBlockEntity theendgatewayblockentity) { +- if (level instanceof ServerLevel && !theendgatewayblockentity.isCoolingDown()) { +- ServerLevel serverlevel = (ServerLevel) level; ++ public static void teleportEntity(Level level, BlockPos pos, IBlockData state, Entity entity, TheEndGatewayBlockEntity blockEntity) { ++ if (level instanceof ServerLevel && !blockEntity.isCoolingDown()) { ++ ServerLevel worldserver = (ServerLevel) level; + +- theendgatewayblockentity.teleportCooldown = 100; +- BlockPos blockpos1; ++ blockEntity.teleportCooldown = 100; ++ BlockPos blockposition1; + +- if (theendgatewayblockentity.exitPortal == null && level.dimension() == Level.END) { +- blockpos1 = findOrCreateValidTeleportPos(serverlevel, blockpos); +- blockpos1 = blockpos1.above(10); +- TheEndGatewayBlockEntity.LOGGER.debug("Creating portal at {}", blockpos1); +- spawnGatewayPortal(serverlevel, blockpos1, EndGatewayConfiguration.knownExit(blockpos, false)); +- theendgatewayblockentity.exitPortal = blockpos1; ++ if (blockEntity.exitPortal == null && level.getTypeKey() == LevelStem.END) { // CraftBukkit - work in alternate worlds ++ blockposition1 = findOrCreateValidTeleportPos(worldserver, pos); ++ blockposition1 = blockposition1.above(10); ++ TheEndGatewayBlockEntity.LOGGER.debug("Creating portal at {}", blockposition1); ++ spawnGatewayPortal(worldserver, blockposition1, EndGatewayConfiguration.knownExit(pos, false)); ++ blockEntity.exitPortal = blockposition1; + } + +- if (theendgatewayblockentity.exitPortal != null) { +- blockpos1 = theendgatewayblockentity.exactTeleport ? theendgatewayblockentity.exitPortal : findExitPosition(level, theendgatewayblockentity.exitPortal); ++ if (blockEntity.exitPortal != null) { ++ blockposition1 = blockEntity.exactTeleport ? blockEntity.exitPortal : findExitPosition(level, blockEntity.exitPortal); + Entity entity1; + + if (entity instanceof ThrownEnderpearl) { + Entity entity2 = ((ThrownEnderpearl) entity).getOwner(); + + if (entity2 instanceof ServerPlayer) { +- CriteriaTriggers.ENTER_BLOCK.trigger((ServerPlayer) entity2, blockstate); ++ CriteriaTriggers.ENTER_BLOCK.trigger((ServerPlayer) entity2, state); + } + + if (entity2 != null) { +@@ -203,78 +204,104 @@ + entity1 = entity.getRootVehicle(); + } + ++ // CraftBukkit start - Fire PlayerTeleportEvent/EntityTeleportEvent ++ if (entity1 instanceof ServerPlayer) { ++ org.bukkit.craftbukkit.entity.CraftPlayer player = (CraftPlayer) entity1.getBukkitEntity(); ++ org.bukkit.Location location = CraftLocation.toBukkit(blockposition1, level.getWorld()).add(0.5D, 0.5D, 0.5D); ++ location.setPitch(player.getLocation().getPitch()); ++ location.setYaw(player.getLocation().getYaw()); ++ ++ PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.END_GATEWAY); ++ Bukkit.getPluginManager().callEvent(teleEvent); ++ if (teleEvent.isCancelled()) { ++ return; ++ } ++ ++ entity1.setPortalCooldown(); ++ ((ServerPlayer) entity1).connection.teleport(teleEvent.getTo()); ++ triggerCooldown(level, pos, state, blockEntity); // CraftBukkit - call at end of method ++ return; ++ ++ } ++ ++ org.bukkit.event.entity.EntityTeleportEvent teleEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTeleportEvent(entity1, blockposition1.getX() + 0.5, blockposition1.getY() + 0.5, blockposition1.getZ() + 0.5); ++ if (teleEvent.isCancelled()) { ++ return; ++ } ++ + entity1.setPortalCooldown(); +- entity1.teleportToWithTicket((double) blockpos1.getX() + 0.5D, (double) blockpos1.getY(), (double) blockpos1.getZ() + 0.5D); ++ entity1.teleportToWithTicket(teleEvent.getTo().getX(), teleEvent.getTo().getY(), teleEvent.getTo().getZ()); ++ // CraftBukkit end + } + +- triggerCooldown(level, blockpos, blockstate, theendgatewayblockentity); ++ triggerCooldown(level, pos, state, blockEntity); + } + } + +- private static BlockPos findExitPosition(Level level, BlockPos blockpos) { +- BlockPos blockpos1 = findTallestBlock(level, blockpos.offset(0, 2, 0), 5, false); ++ private static BlockPos findExitPosition(Level level, BlockPos pos) { ++ BlockPos blockposition1 = findTallestBlock(level, pos.offset(0, 2, 0), 5, false); + +- TheEndGatewayBlockEntity.LOGGER.debug("Best exit position for portal at {} is {}", blockpos, blockpos1); +- return blockpos1.above(); ++ TheEndGatewayBlockEntity.LOGGER.debug("Best exit position for portal at {} is {}", pos, blockposition1); ++ return blockposition1.above(); + } + +- private static BlockPos findOrCreateValidTeleportPos(ServerLevel serverlevel, BlockPos blockpos) { +- Vec3 vec3 = findExitPortalXZPosTentative(serverlevel, blockpos); +- LevelChunk levelchunk = getChunk(serverlevel, vec3); +- BlockPos blockpos1 = findValidSpawnInChunk(levelchunk); ++ private static BlockPos findOrCreateValidTeleportPos(ServerLevel level, BlockPos pos) { ++ Vec3 vec3d = findExitPortalXZPosTentative(level, pos); ++ LevelChunk chunk = getChunk(level, vec3d); ++ BlockPos blockposition1 = findValidSpawnInChunk(chunk); + +- if (blockpos1 == null) { +- BlockPos blockpos2 = BlockPos.containing(vec3.x + 0.5D, 75.0D, vec3.z + 0.5D); ++ if (blockposition1 == null) { ++ BlockPos blockposition2 = BlockPos.containing(vec3d.x + 0.5D, 75.0D, vec3d.z + 0.5D); + +- TheEndGatewayBlockEntity.LOGGER.debug("Failed to find a suitable block to teleport to, spawning an island on {}", blockpos2); +- serverlevel.registryAccess().registry(Registries.CONFIGURED_FEATURE).flatMap((registry) -> { +- return registry.getHolder(EndFeatures.END_ISLAND); +- }).ifPresent((holder_reference) -> { +- ((ConfiguredFeature) holder_reference.value()).place(serverlevel, serverlevel.getChunkSource().getGenerator(), RandomSource.create(blockpos2.asLong()), blockpos2); ++ TheEndGatewayBlockEntity.LOGGER.debug("Failed to find a suitable block to teleport to, spawning an island on {}", blockposition2); ++ level.registryAccess().registry(Registries.CONFIGURED_FEATURE).flatMap((iregistry) -> { ++ return iregistry.getHolder(EndFeatures.END_ISLAND); ++ }).ifPresent((holder_c) -> { ++ ((ConfiguredFeature) holder_c.value()).place(level, level.getChunkSource().getGenerator(), RandomSource.create(blockposition2.asLong()), blockposition2); + }); +- blockpos1 = blockpos2; ++ blockposition1 = blockposition2; + } else { +- TheEndGatewayBlockEntity.LOGGER.debug("Found suitable block to teleport to: {}", blockpos1); ++ TheEndGatewayBlockEntity.LOGGER.debug("Found suitable block to teleport to: {}", blockposition1); + } + +- return findTallestBlock(serverlevel, blockpos1, 16, true); ++ return findTallestBlock(level, blockposition1, 16, true); + } + +- private static Vec3 findExitPortalXZPosTentative(ServerLevel serverlevel, BlockPos blockpos) { +- Vec3 vec3 = (new Vec3((double) blockpos.getX(), 0.0D, (double) blockpos.getZ())).normalize(); ++ private static Vec3 findExitPortalXZPosTentative(ServerLevel level, BlockPos pos) { ++ Vec3 vec3d = (new Vec3((double) pos.getX(), 0.0D, (double) pos.getZ())).normalize(); + boolean flag = true; +- Vec3 vec31 = vec3.scale(1024.0D); ++ Vec3 vec3d1 = vec3d.scale(1024.0D); + + int i; + +- for (i = 16; !isChunkEmpty(serverlevel, vec31) && i-- > 0; vec31 = vec31.add(vec3.scale(-16.0D))) { +- TheEndGatewayBlockEntity.LOGGER.debug("Skipping backwards past nonempty chunk at {}", vec31); ++ for (i = 16; !isChunkEmpty(level, vec3d1) && i-- > 0; vec3d1 = vec3d1.add(vec3d.scale(-16.0D))) { ++ TheEndGatewayBlockEntity.LOGGER.debug("Skipping backwards past nonempty chunk at {}", vec3d1); + } + +- for (i = 16; isChunkEmpty(serverlevel, vec31) && i-- > 0; vec31 = vec31.add(vec3.scale(16.0D))) { +- TheEndGatewayBlockEntity.LOGGER.debug("Skipping forward past empty chunk at {}", vec31); ++ for (i = 16; isChunkEmpty(level, vec3d1) && i-- > 0; vec3d1 = vec3d1.add(vec3d.scale(16.0D))) { ++ TheEndGatewayBlockEntity.LOGGER.debug("Skipping forward past empty chunk at {}", vec3d1); + } + +- TheEndGatewayBlockEntity.LOGGER.debug("Found chunk at {}", vec31); +- return vec31; ++ TheEndGatewayBlockEntity.LOGGER.debug("Found chunk at {}", vec3d1); ++ return vec3d1; + } + +- private static boolean isChunkEmpty(ServerLevel serverlevel, Vec3 vec3) { +- return getChunk(serverlevel, vec3).getHighestFilledSectionIndex() == -1; ++ private static boolean isChunkEmpty(ServerLevel level, Vec3 pos) { ++ return getChunk(level, pos).getHighestFilledSectionIndex() == -1; + } + +- private static BlockPos findTallestBlock(BlockGetter blockgetter, BlockPos blockpos, int i, boolean flag) { +- BlockPos blockpos1 = null; ++ private static BlockPos findTallestBlock(BlockGetter level, BlockPos pos, int radius, boolean allowBedrock) { ++ BlockPos blockposition1 = null; + +- for (int j = -i; j <= i; ++j) { +- for (int k = -i; k <= i; ++k) { +- if (j != 0 || k != 0 || flag) { +- for (int l = blockgetter.getMaxBuildHeight() - 1; l > (blockpos1 == null ? blockgetter.getMinBuildHeight() : blockpos1.getY()); --l) { +- BlockPos blockpos2 = new BlockPos(blockpos.getX() + j, l, blockpos.getZ() + k); +- BlockState blockstate = blockgetter.getBlockState(blockpos2); ++ for (int j = -radius; j <= radius; ++j) { ++ for (int k = -radius; k <= radius; ++k) { ++ if (j != 0 || k != 0 || allowBedrock) { ++ for (int l = level.getMaxBuildHeight() - 1; l > (blockposition1 == null ? level.getMinBuildHeight() : blockposition1.getY()); --l) { ++ BlockPos blockposition2 = new BlockPos(pos.getX() + j, l, pos.getZ() + k); ++ IBlockData iblockdata = level.getBlockState(blockposition2); + +- if (blockstate.isCollisionShapeFullBlock(blockgetter, blockpos2) && (flag || !blockstate.is(Blocks.BEDROCK))) { +- blockpos1 = blockpos2; ++ if (iblockdata.isCollisionShapeFullBlock(level, blockposition2) && (allowBedrock || !iblockdata.is(Blocks.BEDROCK))) { ++ blockposition1 = blockposition2; + break; + } + } +@@ -282,68 +309,67 @@ + } + } + +- return blockpos1 == null ? blockpos : blockpos1; ++ return blockposition1 == null ? pos : blockposition1; + } + +- private static LevelChunk getChunk(Level level, Vec3 vec3) { +- return level.getChunk(Mth.floor(vec3.x / 16.0D), Mth.floor(vec3.z / 16.0D)); ++ private static LevelChunk getChunk(Level level, Vec3 pos) { ++ return level.getChunk(Mth.floor(pos.x / 16.0D), Mth.floor(pos.z / 16.0D)); + } + + @Nullable +- private static BlockPos findValidSpawnInChunk(LevelChunk levelchunk) { +- ChunkPos chunkpos = levelchunk.getPos(); +- BlockPos blockpos = new BlockPos(chunkpos.getMinBlockX(), 30, chunkpos.getMinBlockZ()); +- int i = levelchunk.getHighestSectionPosition() + 16 - 1; +- BlockPos blockpos1 = new BlockPos(chunkpos.getMaxBlockX(), i, chunkpos.getMaxBlockZ()); +- BlockPos blockpos2 = null; ++ private static BlockPos findValidSpawnInChunk(LevelChunk chunk) { ++ ChunkPos chunkcoordintpair = chunk.getPos(); ++ BlockPos blockposition = new BlockPos(chunkcoordintpair.getMinBlockX(), 30, chunkcoordintpair.getMinBlockZ()); ++ int i = chunk.getHighestSectionPosition() + 16 - 1; ++ BlockPos blockposition1 = new BlockPos(chunkcoordintpair.getMaxBlockX(), i, chunkcoordintpair.getMaxBlockZ()); ++ BlockPos blockposition2 = null; + double d0 = 0.0D; +- Iterator iterator = BlockPos.betweenClosed(blockpos, blockpos1).iterator(); ++ Iterator iterator = BlockPos.betweenClosed(blockposition, blockposition1).iterator(); + + while (iterator.hasNext()) { +- BlockPos blockpos3 = (BlockPos) iterator.next(); +- BlockState blockstate = levelchunk.getBlockState(blockpos3); +- BlockPos blockpos4 = blockpos3.above(); +- BlockPos blockpos5 = blockpos3.above(2); ++ BlockPos blockposition3 = (BlockPos) iterator.next(); ++ IBlockData iblockdata = chunk.getBlockState(blockposition3); ++ BlockPos blockposition4 = blockposition3.above(); ++ BlockPos blockposition5 = blockposition3.above(2); + +- if (blockstate.is(Blocks.END_STONE) && !levelchunk.getBlockState(blockpos4).isCollisionShapeFullBlock(levelchunk, blockpos4) && !levelchunk.getBlockState(blockpos5).isCollisionShapeFullBlock(levelchunk, blockpos5)) { +- double d1 = blockpos3.distToCenterSqr(0.0D, 0.0D, 0.0D); ++ if (iblockdata.is(Blocks.END_STONE) && !chunk.getBlockState(blockposition4).isCollisionShapeFullBlock(chunk, blockposition4) && !chunk.getBlockState(blockposition5).isCollisionShapeFullBlock(chunk, blockposition5)) { ++ double d1 = blockposition3.distToCenterSqr(0.0D, 0.0D, 0.0D); + +- if (blockpos2 == null || d1 < d0) { +- blockpos2 = blockpos3; ++ if (blockposition2 == null || d1 < d0) { ++ blockposition2 = blockposition3; + d0 = d1; + } + } + } + +- return blockpos2; ++ return blockposition2; + } + +- private static void spawnGatewayPortal(ServerLevel serverlevel, BlockPos blockpos, EndGatewayConfiguration endgatewayconfiguration) { +- Feature.END_GATEWAY.place(endgatewayconfiguration, serverlevel, serverlevel.getChunkSource().getGenerator(), RandomSource.create(), blockpos); ++ private static void spawnGatewayPortal(ServerLevel level, BlockPos pos, EndGatewayConfiguration config) { ++ Feature.END_GATEWAY.place(config, level, level.getChunkSource().getGenerator(), RandomSource.create(), pos); + } + + @Override +- @Override +- public boolean shouldRenderFace(Direction direction) { +- return Block.shouldRenderFace(this.getBlockState(), this.level, this.getBlockPos(), direction, this.getBlockPos().relative(direction)); ++ public boolean shouldRenderFace(Direction face) { ++ return Block.shouldRenderFace(this.getBlockState(), this.level, this.getBlockPos(), face, this.getBlockPos().relative(face)); + } + + public int getParticleAmount() { + int i = 0; +- Direction[] adirection = Direction.values(); +- int j = adirection.length; ++ Direction[] aenumdirection = Direction.values(); ++ int j = aenumdirection.length; + + for (int k = 0; k < j; ++k) { +- Direction direction = adirection[k]; ++ Direction enumdirection = aenumdirection[k]; + +- i += this.shouldRenderFace(direction) ? 1 : 0; ++ i += this.shouldRenderFace(enumdirection) ? 1 : 0; + } + + return i; + } + +- public void setExitPosition(BlockPos blockpos, boolean flag) { +- this.exactTeleport = flag; +- this.exitPortal = blockpos; ++ public void setExitPosition(BlockPos exitPortal, boolean exactTeleport) { ++ this.exactTeleport = exactTeleport; ++ this.exitPortal = exitPortal; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/piston/PistonBaseBlock.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/piston/PistonBaseBlock.java.patch new file mode 100644 index 0000000000..ea98c9bebe --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/piston/PistonBaseBlock.java.patch @@ -0,0 +1,641 @@ +--- a/net/minecraft/world/level/block/piston/PistonBaseBlock.java ++++ b/net/minecraft/world/level/block/piston/PistonBaseBlock.java +@@ -23,29 +23,36 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.SignalGetter; + import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.BlockDirectional; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.DirectionalBlock; + import net.minecraft.world.level.block.Mirror; + import net.minecraft.world.level.block.Rotation; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.block.state.properties.PistonType; + import net.minecraft.world.level.gameevent.GameEvent; +-import net.minecraft.world.level.material.PushReaction; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.material.EnumPistonReaction; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import com.google.common.collect.ImmutableList; ++import java.util.AbstractList; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockPistonRetractEvent; ++import org.bukkit.event.block.BlockPistonExtendEvent; ++// CraftBukkit end + +-public class PistonBaseBlock extends DirectionalBlock { ++public class PistonBaseBlock extends BlockDirectional { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +- return instance.group(Codec.BOOL.fieldOf("sticky").forGetter((pistonbaseblock) -> { +- return pistonbaseblock.isSticky; ++ return instance.group(Codec.BOOL.fieldOf("sticky").forGetter((blockpiston) -> { ++ return blockpiston.isSticky; + }), propertiesCodec()).apply(instance, PistonBaseBlock::new); + }); + public static final BooleanProperty EXTENDED = BlockStateProperties.EXTENDED; +@@ -62,22 +69,20 @@ + private final boolean isSticky; + + @Override +- @Override + public MapCodec codec() { + return PistonBaseBlock.CODEC; + } + +- public PistonBaseBlock(boolean flag, BlockBehaviour.Properties blockbehaviour_properties) { +- super(blockbehaviour_properties); +- this.registerDefaultState((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(PistonBaseBlock.FACING, Direction.NORTH)).setValue(PistonBaseBlock.EXTENDED, false)); +- this.isSticky = flag; ++ public PistonBaseBlock(boolean isSticky, BlockBehaviour.Properties properties) { ++ super(properties); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(PistonBaseBlock.FACING, Direction.NORTH)).setValue(PistonBaseBlock.EXTENDED, false)); ++ this.isSticky = isSticky; + } + + @Override +- @Override +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- if ((Boolean) blockstate.getValue(PistonBaseBlock.EXTENDED)) { +- switch ((Direction) blockstate.getValue(PistonBaseBlock.FACING)) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ if ((Boolean) state.getValue(PistonBaseBlock.EXTENDED)) { ++ switch ((Direction) state.getValue(PistonBaseBlock.FACING)) { + case DOWN: + return PistonBaseBlock.DOWN_AABB; + case UP: +@@ -98,96 +103,104 @@ + } + + @Override +- @Override +- public void setPlacedBy(Level level, BlockPos blockpos, BlockState blockstate, LivingEntity livingentity, ItemStack itemstack) { ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, LivingEntity placer, ItemStack stack) { + if (!level.isClientSide) { +- this.checkIfExtend(level, blockpos, blockstate); ++ this.checkIfExtend(level, pos, state); + } + + } + + @Override +- @Override +- public void neighborChanged(BlockState blockstate, Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { + if (!level.isClientSide) { +- this.checkIfExtend(level, blockpos, blockstate); ++ this.checkIfExtend(level, pos, state); + } + + } + + @Override +- @Override +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (!blockstate1.is(blockstate.getBlock())) { +- if (!level.isClientSide && level.getBlockEntity(blockpos) == null) { +- this.checkIfExtend(level, blockpos, blockstate); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ if (!oldState.is(state.getBlock())) { ++ if (!level.isClientSide && level.getBlockEntity(pos) == null) { ++ this.checkIfExtend(level, pos, state); + } + + } + } + + @Override +- @Override +- public BlockState getStateForPlacement(BlockPlaceContext blockplacecontext) { +- return (BlockState) ((BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, blockplacecontext.getNearestLookingDirection().getOpposite())).setValue(PistonBaseBlock.EXTENDED, false); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return (IBlockData) ((IBlockData) this.defaultBlockState().setValue(PistonBaseBlock.FACING, context.getNearestLookingDirection().getOpposite())).setValue(PistonBaseBlock.EXTENDED, false); + } + +- private void checkIfExtend(Level level, BlockPos blockpos, BlockState blockstate) { +- Direction direction = (Direction) blockstate.getValue(PistonBaseBlock.FACING); +- boolean flag = this.getNeighborSignal(level, blockpos, direction); ++ private void checkIfExtend(Level level, BlockPos pos, IBlockData state) { ++ Direction enumdirection = (Direction) state.getValue(PistonBaseBlock.FACING); ++ boolean flag = this.getNeighborSignal(level, pos, enumdirection); + +- if (flag && !(Boolean) blockstate.getValue(PistonBaseBlock.EXTENDED)) { +- if ((new PistonStructureResolver(level, blockpos, direction, true)).resolve()) { +- level.blockEvent(blockpos, this, 0, direction.get3DDataValue()); ++ if (flag && !(Boolean) state.getValue(PistonBaseBlock.EXTENDED)) { ++ if ((new PistonStructureResolver(level, pos, enumdirection, true)).resolve()) { ++ level.blockEvent(pos, this, 0, enumdirection.get3DDataValue()); + } +- } else if (!flag && (Boolean) blockstate.getValue(PistonBaseBlock.EXTENDED)) { +- BlockPos blockpos1 = blockpos.relative(direction, 2); +- BlockState blockstate1 = level.getBlockState(blockpos1); ++ } else if (!flag && (Boolean) state.getValue(PistonBaseBlock.EXTENDED)) { ++ BlockPos blockposition1 = pos.relative(enumdirection, 2); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + byte b0 = 1; + +- if (blockstate1.is(Blocks.MOVING_PISTON) && blockstate1.getValue(PistonBaseBlock.FACING) == direction) { +- BlockEntity blockentity = level.getBlockEntity(blockpos1); ++ if (iblockdata1.is(Blocks.MOVING_PISTON) && iblockdata1.getValue(PistonBaseBlock.FACING) == enumdirection) { ++ BlockEntity tileentity = level.getBlockEntity(blockposition1); + +- if (blockentity instanceof PistonMovingBlockEntity) { +- PistonMovingBlockEntity pistonmovingblockentity = (PistonMovingBlockEntity) blockentity; ++ if (tileentity instanceof PistonMovingBlockEntity) { ++ PistonMovingBlockEntity tileentitypiston = (PistonMovingBlockEntity) tileentity; + +- if (pistonmovingblockentity.isExtending() && (pistonmovingblockentity.getProgress(0.0F) < 0.5F || level.getGameTime() == pistonmovingblockentity.getLastTicked() || ((ServerLevel) level).isHandlingTick())) { ++ if (tileentitypiston.isExtending() && (tileentitypiston.getProgress(0.0F) < 0.5F || level.getGameTime() == tileentitypiston.getLastTicked() || ((ServerLevel) level).isHandlingTick())) { + b0 = 2; + } + } + } + +- level.blockEvent(blockpos, this, b0, direction.get3DDataValue()); ++ // CraftBukkit start ++ if (!this.isSticky) { ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ BlockPistonRetractEvent event = new BlockPistonRetractEvent(block, ImmutableList.of(), CraftBlock.notchToBlockFace(enumdirection)); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // PAIL: checkME - what happened to setTypeAndData? ++ // CraftBukkit end ++ level.blockEvent(pos, this, b0, enumdirection.get3DDataValue()); + } + + } + +- private boolean getNeighborSignal(SignalGetter signalgetter, BlockPos blockpos, Direction direction) { +- Direction[] adirection = Direction.values(); +- int i = adirection.length; ++ private boolean getNeighborSignal(SignalGetter signalGetter, BlockPos pos, Direction direction) { ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; + + int j; + + for (j = 0; j < i; ++j) { +- Direction direction1 = adirection[j]; ++ Direction enumdirection1 = aenumdirection[j]; + +- if (direction1 != direction && signalgetter.hasSignal(blockpos.relative(direction1), direction1)) { ++ if (enumdirection1 != direction && signalGetter.hasSignal(pos.relative(enumdirection1), enumdirection1)) { + return true; + } + } + +- if (signalgetter.hasSignal(blockpos, Direction.DOWN)) { ++ if (signalGetter.hasSignal(pos, Direction.DOWN)) { + return true; + } else { +- BlockPos blockpos1 = blockpos.above(); +- Direction[] adirection1 = Direction.values(); ++ BlockPos blockposition1 = pos.above(); ++ Direction[] aenumdirection1 = Direction.values(); + +- j = adirection1.length; ++ j = aenumdirection1.length; + + for (int k = 0; k < j; ++k) { +- Direction direction2 = adirection1[k]; ++ Direction enumdirection2 = aenumdirection1[k]; + +- if (direction2 != Direction.DOWN && signalgetter.hasSignal(blockpos1.relative(direction2), direction2)) { ++ if (enumdirection2 != Direction.DOWN && signalGetter.hasSignal(blockposition1.relative(enumdirection2), enumdirection2)) { + return true; + } + } +@@ -197,109 +210,108 @@ + } + + @Override +- @Override +- public boolean triggerEvent(BlockState blockstate, Level level, BlockPos blockpos, int i, int j) { +- Direction direction = (Direction) blockstate.getValue(PistonBaseBlock.FACING); +- BlockState blockstate1 = (BlockState) blockstate.setValue(PistonBaseBlock.EXTENDED, true); ++ public boolean triggerEvent(IBlockData state, Level level, BlockPos pos, int id, int param) { ++ Direction enumdirection = (Direction) state.getValue(PistonBaseBlock.FACING); ++ IBlockData iblockdata1 = (IBlockData) state.setValue(PistonBaseBlock.EXTENDED, true); + + if (!level.isClientSide) { +- boolean flag = this.getNeighborSignal(level, blockpos, direction); ++ boolean flag = this.getNeighborSignal(level, pos, enumdirection); + +- if (flag && (i == 1 || i == 2)) { +- level.setBlock(blockpos, blockstate1, 2); ++ if (flag && (id == 1 || id == 2)) { ++ level.setBlock(pos, iblockdata1, 2); + return false; + } + +- if (!flag && i == 0) { ++ if (!flag && id == 0) { + return false; + } + } + +- if (i == 0) { +- if (!this.moveBlocks(level, blockpos, direction, true)) { ++ if (id == 0) { ++ if (!this.moveBlocks(level, pos, enumdirection, true)) { + return false; + } + +- level.setBlock(blockpos, blockstate1, 67); +- level.playSound((Player) null, blockpos, SoundEvents.PISTON_EXTEND, SoundSource.BLOCKS, 0.5F, level.random.nextFloat() * 0.25F + 0.6F); +- level.gameEvent(GameEvent.BLOCK_ACTIVATE, blockpos, GameEvent.Context.of(blockstate1)); +- } else if (i == 1 || i == 2) { +- BlockEntity blockentity = level.getBlockEntity(blockpos.relative(direction)); ++ level.setBlock(pos, iblockdata1, 67); ++ level.playSound((Player) null, pos, SoundEvents.PISTON_EXTEND, SoundSource.BLOCKS, 0.5F, level.random.nextFloat() * 0.25F + 0.6F); ++ level.gameEvent(GameEvent.BLOCK_ACTIVATE, pos, GameEvent.Context.of(iblockdata1)); ++ } else if (id == 1 || id == 2) { ++ BlockEntity tileentity = level.getBlockEntity(pos.relative(enumdirection)); + +- if (blockentity instanceof PistonMovingBlockEntity) { +- ((PistonMovingBlockEntity) blockentity).finalTick(); ++ if (tileentity instanceof PistonMovingBlockEntity) { ++ ((PistonMovingBlockEntity) tileentity).finalTick(); + } + +- BlockState blockstate2 = (BlockState) ((BlockState) Blocks.MOVING_PISTON.defaultBlockState().setValue(MovingPistonBlock.FACING, direction)).setValue(MovingPistonBlock.TYPE, this.isSticky ? PistonType.STICKY : PistonType.DEFAULT); ++ IBlockData iblockdata2 = (IBlockData) ((IBlockData) Blocks.MOVING_PISTON.defaultBlockState().setValue(MovingPistonBlock.FACING, enumdirection)).setValue(MovingPistonBlock.TYPE, this.isSticky ? PistonType.STICKY : PistonType.DEFAULT); + +- level.setBlock(blockpos, blockstate2, 20); +- level.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(blockpos, blockstate2, (BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(j & 7)), direction, false, true)); +- level.blockUpdated(blockpos, blockstate2.getBlock()); +- blockstate2.updateNeighbourShapes(level, blockpos, 2); ++ level.setBlock(pos, iblockdata2, 20); ++ level.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(pos, iblockdata2, (IBlockData) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(param & 7)), enumdirection, false, true)); ++ level.blockUpdated(pos, iblockdata2.getBlock()); ++ iblockdata2.updateNeighbourShapes(level, pos, 2); + if (this.isSticky) { +- BlockPos blockpos1 = blockpos.offset(direction.getStepX() * 2, direction.getStepY() * 2, direction.getStepZ() * 2); +- BlockState blockstate3 = level.getBlockState(blockpos1); ++ BlockPos blockposition1 = pos.offset(enumdirection.getStepX() * 2, enumdirection.getStepY() * 2, enumdirection.getStepZ() * 2); ++ IBlockData iblockdata3 = level.getBlockState(blockposition1); + boolean flag1 = false; + +- if (blockstate3.is(Blocks.MOVING_PISTON)) { +- BlockEntity blockentity1 = level.getBlockEntity(blockpos1); ++ if (iblockdata3.is(Blocks.MOVING_PISTON)) { ++ BlockEntity tileentity1 = level.getBlockEntity(blockposition1); + +- if (blockentity1 instanceof PistonMovingBlockEntity) { +- PistonMovingBlockEntity pistonmovingblockentity = (PistonMovingBlockEntity) blockentity1; ++ if (tileentity1 instanceof PistonMovingBlockEntity) { ++ PistonMovingBlockEntity tileentitypiston = (PistonMovingBlockEntity) tileentity1; + +- if (pistonmovingblockentity.getDirection() == direction && pistonmovingblockentity.isExtending()) { +- pistonmovingblockentity.finalTick(); ++ if (tileentitypiston.getDirection() == enumdirection && tileentitypiston.isExtending()) { ++ tileentitypiston.finalTick(); + flag1 = true; + } + } + } + + if (!flag1) { +- if (i == 1 && !blockstate3.isAir() && isPushable(blockstate3, level, blockpos1, direction.getOpposite(), false, direction) && (blockstate3.getPistonPushReaction() == PushReaction.NORMAL || blockstate3.is(Blocks.PISTON) || blockstate3.is(Blocks.STICKY_PISTON))) { +- this.moveBlocks(level, blockpos, direction, false); ++ if (id == 1 && !iblockdata3.isAir() && isPushable(iblockdata3, level, blockposition1, enumdirection.getOpposite(), false, enumdirection) && (iblockdata3.getPistonPushReaction() == EnumPistonReaction.NORMAL || iblockdata3.is(Blocks.PISTON) || iblockdata3.is(Blocks.STICKY_PISTON))) { ++ this.moveBlocks(level, pos, enumdirection, false); + } else { +- level.removeBlock(blockpos.relative(direction), false); ++ level.removeBlock(pos.relative(enumdirection), false); + } + } + } else { +- level.removeBlock(blockpos.relative(direction), false); ++ level.removeBlock(pos.relative(enumdirection), false); + } + +- level.playSound((Player) null, blockpos, SoundEvents.PISTON_CONTRACT, SoundSource.BLOCKS, 0.5F, level.random.nextFloat() * 0.15F + 0.6F); +- level.gameEvent(GameEvent.BLOCK_DEACTIVATE, blockpos, GameEvent.Context.of(blockstate2)); ++ level.playSound((Player) null, pos, SoundEvents.PISTON_CONTRACT, SoundSource.BLOCKS, 0.5F, level.random.nextFloat() * 0.15F + 0.6F); ++ level.gameEvent(GameEvent.BLOCK_DEACTIVATE, pos, GameEvent.Context.of(iblockdata2)); + } + + return true; + } + +- public static boolean isPushable(BlockState blockstate, Level level, BlockPos blockpos, Direction direction, boolean flag, Direction direction1) { +- if (blockpos.getY() >= level.getMinBuildHeight() && blockpos.getY() <= level.getMaxBuildHeight() - 1 && level.getWorldBorder().isWithinBounds(blockpos)) { +- if (blockstate.isAir()) { ++ public static boolean isPushable(IBlockData state, Level level, BlockPos pos, Direction movementDirection, boolean allowDestroy, Direction pistonFacing) { ++ if (pos.getY() >= level.getMinBuildHeight() && pos.getY() <= level.getMaxBuildHeight() - 1 && level.getWorldBorder().isWithinBounds(pos)) { ++ if (state.isAir()) { + return true; +- } else if (!blockstate.is(Blocks.OBSIDIAN) && !blockstate.is(Blocks.CRYING_OBSIDIAN) && !blockstate.is(Blocks.RESPAWN_ANCHOR) && !blockstate.is(Blocks.REINFORCED_DEEPSLATE)) { +- if (direction == Direction.DOWN && blockpos.getY() == level.getMinBuildHeight()) { ++ } else if (!state.is(Blocks.OBSIDIAN) && !state.is(Blocks.CRYING_OBSIDIAN) && !state.is(Blocks.RESPAWN_ANCHOR) && !state.is(Blocks.REINFORCED_DEEPSLATE)) { ++ if (movementDirection == Direction.DOWN && pos.getY() == level.getMinBuildHeight()) { + return false; +- } else if (direction == Direction.UP && blockpos.getY() == level.getMaxBuildHeight() - 1) { ++ } else if (movementDirection == Direction.UP && pos.getY() == level.getMaxBuildHeight() - 1) { + return false; + } else { +- if (!blockstate.is(Blocks.PISTON) && !blockstate.is(Blocks.STICKY_PISTON)) { +- if (blockstate.getDestroySpeed(level, blockpos) == -1.0F) { ++ if (!state.is(Blocks.PISTON) && !state.is(Blocks.STICKY_PISTON)) { ++ if (state.getDestroySpeed(level, pos) == -1.0F) { + return false; + } + +- switch (blockstate.getPistonPushReaction()) { ++ switch (state.getPistonPushReaction()) { + case BLOCK: + return false; + case DESTROY: +- return flag; ++ return allowDestroy; + case PUSH_ONLY: +- return direction == direction1; ++ return movementDirection == pistonFacing; + } +- } else if ((Boolean) blockstate.getValue(PistonBaseBlock.EXTENDED)) { ++ } else if ((Boolean) state.getValue(PistonBaseBlock.EXTENDED)) { + return false; + } + +- return !blockstate.hasBlockEntity(); ++ return !state.hasBlockEntity(); + } + } else { + return false; +@@ -309,99 +321,141 @@ + } + } + +- private boolean moveBlocks(Level level, BlockPos blockpos, Direction direction, boolean flag) { +- BlockPos blockpos1 = blockpos.relative(direction); ++ private boolean moveBlocks(Level level, BlockPos pos, Direction facing, boolean extending) { ++ BlockPos blockposition1 = pos.relative(facing); + +- if (!flag && level.getBlockState(blockpos1).is(Blocks.PISTON_HEAD)) { +- level.setBlock(blockpos1, Blocks.AIR.defaultBlockState(), 20); ++ if (!extending && level.getBlockState(blockposition1).is(Blocks.PISTON_HEAD)) { ++ level.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 20); + } + +- PistonStructureResolver pistonstructureresolver = new PistonStructureResolver(level, blockpos, direction, flag); ++ PistonStructureResolver pistonextendschecker = new PistonStructureResolver(level, pos, facing, extending); + +- if (!pistonstructureresolver.resolve()) { ++ if (!pistonextendschecker.resolve()) { + return false; + } else { +- Map map = Maps.newHashMap(); +- List list = pistonstructureresolver.getToPush(); +- List list1 = Lists.newArrayList(); ++ Map map = Maps.newHashMap(); ++ List list = pistonextendschecker.getToPush(); ++ List list1 = Lists.newArrayList(); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- BlockPos blockpos2 = (BlockPos) iterator.next(); +- BlockState blockstate = level.getBlockState(blockpos2); ++ BlockPos blockposition2 = (BlockPos) iterator.next(); ++ IBlockData iblockdata = level.getBlockState(blockposition2); + +- list1.add(blockstate); +- map.put(blockpos2, blockstate); ++ list1.add(iblockdata); ++ map.put(blockposition2, iblockdata); + } + +- List list2 = pistonstructureresolver.getToDestroy(); +- BlockState[] ablockstate = new BlockState[list.size() + list2.size()]; +- Direction direction1 = flag ? direction : direction.getOpposite(); ++ List list2 = pistonextendschecker.getToDestroy(); ++ IBlockData[] aiblockdata = new IBlockData[list.size() + list2.size()]; ++ Direction enumdirection1 = extending ? facing : facing.getOpposite(); + int i = 0; ++ // CraftBukkit start ++ final org.bukkit.block.Block bblock = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); + +- BlockPos blockpos3; ++ final List moved = pistonextendschecker.getToPush(); ++ final List broken = pistonextendschecker.getToDestroy(); ++ ++ List blocks = new AbstractList() { ++ ++ @Override ++ public int size() { ++ return moved.size() + broken.size(); ++ } ++ ++ @Override ++ public org.bukkit.block.Block get(int index) { ++ if (index >= size() || index < 0) { ++ throw new ArrayIndexOutOfBoundsException(index); ++ } ++ BlockPos pos = (BlockPos) (index < moved.size() ? moved.get(index) : broken.get(index - moved.size())); ++ return bblock.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ } ++ }; ++ org.bukkit.event.block.BlockPistonEvent event; ++ if (extending) { ++ event = new BlockPistonExtendEvent(bblock, blocks, CraftBlock.notchToBlockFace(enumdirection1)); ++ } else { ++ event = new BlockPistonRetractEvent(bblock, blocks, CraftBlock.notchToBlockFace(enumdirection1)); ++ } ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ for (BlockPos b : broken) { ++ level.sendBlockUpdated(b, Blocks.AIR.defaultBlockState(), level.getBlockState(b), 3); ++ } ++ for (BlockPos b : moved) { ++ level.sendBlockUpdated(b, Blocks.AIR.defaultBlockState(), level.getBlockState(b), 3); ++ b = b.relative(enumdirection1); ++ level.sendBlockUpdated(b, Blocks.AIR.defaultBlockState(), level.getBlockState(b), 3); ++ } ++ return false; ++ } ++ // CraftBukkit end ++ ++ BlockPos blockposition3; + int j; +- BlockState blockstate1; ++ IBlockData iblockdata1; + + for (j = list2.size() - 1; j >= 0; --j) { +- blockpos3 = (BlockPos) list2.get(j); +- blockstate1 = level.getBlockState(blockpos3); +- BlockEntity blockentity = blockstate1.hasBlockEntity() ? level.getBlockEntity(blockpos3) : null; ++ blockposition3 = (BlockPos) list2.get(j); ++ iblockdata1 = level.getBlockState(blockposition3); ++ BlockEntity tileentity = iblockdata1.hasBlockEntity() ? level.getBlockEntity(blockposition3) : null; + +- dropResources(blockstate1, level, blockpos3, blockentity); +- level.setBlock(blockpos3, Blocks.AIR.defaultBlockState(), 18); +- level.gameEvent(GameEvent.BLOCK_DESTROY, blockpos3, GameEvent.Context.of(blockstate1)); +- if (!blockstate1.is(BlockTags.FIRE)) { +- level.addDestroyBlockEffect(blockpos3, blockstate1); ++ dropResources(iblockdata1, level, blockposition3, tileentity); ++ level.setBlock(blockposition3, Blocks.AIR.defaultBlockState(), 18); ++ level.gameEvent(GameEvent.BLOCK_DESTROY, blockposition3, GameEvent.Context.of(iblockdata1)); ++ if (!iblockdata1.is(BlockTags.FIRE)) { ++ level.addDestroyBlockEffect(blockposition3, iblockdata1); + } + +- ablockstate[i++] = blockstate1; ++ aiblockdata[i++] = iblockdata1; + } + + for (j = list.size() - 1; j >= 0; --j) { +- blockpos3 = (BlockPos) list.get(j); +- blockstate1 = level.getBlockState(blockpos3); +- blockpos3 = blockpos3.relative(direction1); +- map.remove(blockpos3); +- BlockState blockstate2 = (BlockState) Blocks.MOVING_PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, direction); ++ blockposition3 = (BlockPos) list.get(j); ++ iblockdata1 = level.getBlockState(blockposition3); ++ blockposition3 = blockposition3.relative(enumdirection1); ++ map.remove(blockposition3); ++ IBlockData iblockdata2 = (IBlockData) Blocks.MOVING_PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, facing); + +- level.setBlock(blockpos3, blockstate2, 68); +- level.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(blockpos3, blockstate2, (BlockState) list1.get(j), direction, flag, false)); +- ablockstate[i++] = blockstate1; ++ level.setBlock(blockposition3, iblockdata2, 68); ++ level.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(blockposition3, iblockdata2, (IBlockData) list1.get(j), facing, extending, false)); ++ aiblockdata[i++] = iblockdata1; + } + +- if (flag) { +- PistonType pistontype = this.isSticky ? PistonType.STICKY : PistonType.DEFAULT; +- BlockState blockstate3 = (BlockState) ((BlockState) Blocks.PISTON_HEAD.defaultBlockState().setValue(PistonHeadBlock.FACING, direction)).setValue(PistonHeadBlock.TYPE, pistontype); ++ if (extending) { ++ PistonType blockpropertypistontype = this.isSticky ? PistonType.STICKY : PistonType.DEFAULT; ++ IBlockData iblockdata3 = (IBlockData) ((IBlockData) Blocks.PISTON_HEAD.defaultBlockState().setValue(PistonHeadBlock.FACING, facing)).setValue(PistonHeadBlock.TYPE, blockpropertypistontype); + +- blockstate1 = (BlockState) ((BlockState) Blocks.MOVING_PISTON.defaultBlockState().setValue(MovingPistonBlock.FACING, direction)).setValue(MovingPistonBlock.TYPE, this.isSticky ? PistonType.STICKY : PistonType.DEFAULT); +- map.remove(blockpos1); +- level.setBlock(blockpos1, blockstate1, 68); +- level.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(blockpos1, blockstate1, blockstate3, direction, true, true)); ++ iblockdata1 = (IBlockData) ((IBlockData) Blocks.MOVING_PISTON.defaultBlockState().setValue(MovingPistonBlock.FACING, facing)).setValue(MovingPistonBlock.TYPE, this.isSticky ? PistonType.STICKY : PistonType.DEFAULT); ++ map.remove(blockposition1); ++ level.setBlock(blockposition1, iblockdata1, 68); ++ level.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(blockposition1, iblockdata1, iblockdata3, facing, true, true)); + } + +- BlockState blockstate4 = Blocks.AIR.defaultBlockState(); ++ IBlockData iblockdata4 = Blocks.AIR.defaultBlockState(); + Iterator iterator1 = map.keySet().iterator(); + + while (iterator1.hasNext()) { +- BlockPos blockpos4 = (BlockPos) iterator1.next(); ++ BlockPos blockposition4 = (BlockPos) iterator1.next(); + +- level.setBlock(blockpos4, blockstate4, 82); ++ level.setBlock(blockposition4, iblockdata4, 82); + } + + iterator1 = map.entrySet().iterator(); + +- BlockPos blockpos5; ++ BlockPos blockposition5; + + while (iterator1.hasNext()) { +- Entry entry = (Entry) iterator1.next(); ++ Entry entry = (Entry) iterator1.next(); + +- blockpos5 = (BlockPos) entry.getKey(); +- BlockState blockstate5 = (BlockState) entry.getValue(); ++ blockposition5 = (BlockPos) entry.getKey(); ++ IBlockData iblockdata5 = (IBlockData) entry.getValue(); + +- blockstate5.updateIndirectNeighbourShapes(level, blockpos5, 2); +- blockstate4.updateNeighbourShapes(level, blockpos5, 2); +- blockstate4.updateIndirectNeighbourShapes(level, blockpos5, 2); ++ iblockdata5.updateIndirectNeighbourShapes(level, blockposition5, 2); ++ iblockdata4.updateNeighbourShapes(level, blockposition5, 2); ++ iblockdata4.updateIndirectNeighbourShapes(level, blockposition5, 2); + } + + i = 0; +@@ -409,18 +463,18 @@ + int k; + + for (k = list2.size() - 1; k >= 0; --k) { +- blockstate1 = ablockstate[i++]; +- blockpos5 = (BlockPos) list2.get(k); +- blockstate1.updateIndirectNeighbourShapes(level, blockpos5, 2); +- level.updateNeighborsAt(blockpos5, blockstate1.getBlock()); ++ iblockdata1 = aiblockdata[i++]; ++ blockposition5 = (BlockPos) list2.get(k); ++ iblockdata1.updateIndirectNeighbourShapes(level, blockposition5, 2); ++ level.updateNeighborsAt(blockposition5, iblockdata1.getBlock()); + } + + for (k = list.size() - 1; k >= 0; --k) { +- level.updateNeighborsAt((BlockPos) list.get(k), ablockstate[i++].getBlock()); ++ level.updateNeighborsAt((BlockPos) list.get(k), aiblockdata[i++].getBlock()); + } + +- if (flag) { +- level.updateNeighborsAt(blockpos1, Blocks.PISTON_HEAD); ++ if (extending) { ++ level.updateNeighborsAt(blockposition1, Blocks.PISTON_HEAD); + } + + return true; +@@ -428,32 +482,27 @@ + } + + @Override +- @Override +- public BlockState rotate(BlockState blockstate, Rotation rotation) { +- return (BlockState) blockstate.setValue(PistonBaseBlock.FACING, rotation.rotate((Direction) blockstate.getValue(PistonBaseBlock.FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rot) { ++ return (IBlockData) state.setValue(PistonBaseBlock.FACING, rot.rotate((Direction) state.getValue(PistonBaseBlock.FACING))); + } + + @Override +- @Override +- public BlockState mirror(BlockState blockstate, Mirror mirror) { +- return blockstate.rotate(mirror.getRotation((Direction) blockstate.getValue(PistonBaseBlock.FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(PistonBaseBlock.FACING))); + } + + @Override +- @Override +- protected void createBlockStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(PistonBaseBlock.FACING, PistonBaseBlock.EXTENDED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(PistonBaseBlock.FACING, PistonBaseBlock.EXTENDED); + } + + @Override +- @Override +- public boolean useShapeForLightOcclusion(BlockState blockstate) { +- return (Boolean) blockstate.getValue(PistonBaseBlock.EXTENDED); ++ public boolean useShapeForLightOcclusion(IBlockData state) { ++ return (Boolean) state.getValue(PistonBaseBlock.EXTENDED); + } + + @Override +- @Override +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/block/state/BlockBehaviour.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/state/BlockBehaviour.java.patch new file mode 100644 index 0000000000..828c825a36 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/block/state/BlockBehaviour.java.patch @@ -0,0 +1,1487 @@ +--- a/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -28,9 +28,9 @@ + import net.minecraft.tags.TagKey; + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; ++import net.minecraft.world.ITileInventory; + import net.minecraft.world.InteractionResult; +-import net.minecraft.world.MenuProvider; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.player.Player; +@@ -52,8 +52,8 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.EntityBlock; ++import net.minecraft.world.level.block.EnumRenderType; + import net.minecraft.world.level.block.Mirror; +-import net.minecraft.world.level.block.RenderShape; + import net.minecraft.world.level.block.Rotation; + import net.minecraft.world.level.block.SoundType; + import net.minecraft.world.level.block.SupportType; +@@ -62,12 +62,12 @@ + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.state.properties.NoteBlockInstrument; + import net.minecraft.world.level.block.state.properties.Property; ++import net.minecraft.world.level.material.EnumPistonReaction; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.level.material.MapColor; +-import net.minecraft.world.level.material.PushReaction; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.level.storage.loot.BuiltInLootTables; + import net.minecraft.world.level.storage.loot.LootParams; + import net.minecraft.world.level.storage.loot.LootTable; +@@ -96,18 +96,18 @@ + @Nullable + protected ResourceLocation drops; + +- public BlockBehaviour(BlockBehaviour.Properties blockbehaviour_properties) { +- this.hasCollision = blockbehaviour_properties.hasCollision; +- this.drops = blockbehaviour_properties.drops; +- this.explosionResistance = blockbehaviour_properties.explosionResistance; +- this.isRandomlyTicking = blockbehaviour_properties.isRandomlyTicking; +- this.soundType = blockbehaviour_properties.soundType; +- this.friction = blockbehaviour_properties.friction; +- this.speedFactor = blockbehaviour_properties.speedFactor; +- this.jumpFactor = blockbehaviour_properties.jumpFactor; +- this.dynamicShape = blockbehaviour_properties.dynamicShape; +- this.requiredFeatures = blockbehaviour_properties.requiredFeatures; +- this.properties = blockbehaviour_properties; ++ public BlockBehaviour(BlockBehaviour.Properties properties) { ++ this.hasCollision = properties.hasCollision; ++ this.drops = properties.drops; ++ this.explosionResistance = properties.explosionResistance; ++ this.isRandomlyTicking = properties.isRandomlyTicking; ++ this.soundType = properties.soundType; ++ this.friction = properties.friction; ++ this.speedFactor = properties.speedFactor; ++ this.jumpFactor = properties.jumpFactor; ++ this.dynamicShape = properties.dynamicShape; ++ this.requiredFeatures = properties.requiredFeatures; ++ this.properties = properties; + } + + public BlockBehaviour.Properties properties() { +@@ -128,18 +128,18 @@ + + /** @deprecated */ + @Deprecated +- public void updateIndirectNeighbourShapes(BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos, int i, int j) {} ++ public void updateIndirectNeighbourShapes(IBlockData state, LevelAccessor level, BlockPos pos, int flags, int recursionLeft) {} + + /** @deprecated */ + @Deprecated +- public boolean isPathfindable(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { +- switch (pathcomputationtype) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { ++ switch (type) { + case LAND: +- return !blockstate.isCollisionShapeFullBlock(blockgetter, blockpos); ++ return !state.isCollisionShapeFullBlock(level, pos); + case WATER: +- return blockgetter.getFluidState(blockpos).is(FluidTags.WATER); ++ return level.getFluidState(pos).is(FluidTags.WATER); + case AIR: +- return !blockstate.isCollisionShapeFullBlock(blockgetter, blockpos); ++ return !state.isCollisionShapeFullBlock(level, pos); + default: + return false; + } +@@ -147,101 +147,103 @@ + + /** @deprecated */ + @Deprecated +- public BlockState updateShape(BlockState blockstate, Direction direction, BlockState blockstate1, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- return blockstate; ++ public IBlockData updateShape(IBlockData state, Direction direction, IBlockData neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { ++ return state; + } + + /** @deprecated */ + @Deprecated +- public boolean skipRendering(BlockState blockstate, BlockState blockstate1, Direction direction) { ++ public boolean skipRendering(IBlockData state, IBlockData adjacentState, Direction direction) { + return false; + } + + /** @deprecated */ + @Deprecated +- public void neighborChanged(BlockState blockstate, Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { +- DebugPackets.sendNeighborsUpdatePacket(level, blockpos); ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston) { ++ DebugPackets.sendNeighborsUpdatePacket(level, pos); + } + + /** @deprecated */ + @Deprecated +- public void onPlace(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) {} ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean movedByPiston) {} + + /** @deprecated */ + @Deprecated +- public void onRemove(BlockState blockstate, Level level, BlockPos blockpos, BlockState blockstate1, boolean flag) { +- if (blockstate.hasBlockEntity() && !blockstate.is(blockstate1.getBlock())) { +- level.removeBlockEntity(blockpos); ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean movedByPiston) { ++ if (state.hasBlockEntity() && !state.is(newState.getBlock())) { ++ level.removeBlockEntity(pos); + } + + } + + /** @deprecated */ + @Deprecated +- public void onExplosionHit(BlockState blockstate, Level level, BlockPos blockpos, Explosion explosion, BiConsumer biconsumer) { +- if (!blockstate.isAir() && explosion.getBlockInteraction() != Explosion.BlockInteraction.TRIGGER_BLOCK) { +- Block block = blockstate.getBlock(); ++ public void onExplosionHit(IBlockData iblockdata, Level world, BlockPos blockposition, Explosion explosion, BiConsumer biconsumer) { ++ if (!iblockdata.isAir() && explosion.getBlockInteraction() != Explosion.Effect.TRIGGER_BLOCK) { ++ Block block = iblockdata.getBlock(); + boolean flag = explosion.getIndirectSourceEntity() instanceof Player; + +- if (block.dropFromExplosion(explosion) && level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; +- BlockEntity blockentity = blockstate.hasBlockEntity() ? level.getBlockEntity(blockpos) : null; +- LootParams.Builder lootparams_builder = (new LootParams.Builder(serverlevel)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockpos)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withOptionalParameter(LootContextParams.BLOCK_ENTITY, blockentity).withOptionalParameter(LootContextParams.THIS_ENTITY, explosion.getDirectSourceEntity()); ++ if (block.dropFromExplosion(explosion) && world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ BlockEntity tileentity = iblockdata.hasBlockEntity() ? world.getBlockEntity(blockposition) : null; ++ LootParams.Builder lootparams_a = (new LootParams.Builder(worldserver)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockposition)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withOptionalParameter(LootContextParams.BLOCK_ENTITY, tileentity).withOptionalParameter(LootContextParams.THIS_ENTITY, explosion.getDirectSourceEntity()); + +- if (explosion.getBlockInteraction() == Explosion.BlockInteraction.DESTROY_WITH_DECAY) { +- lootparams_builder.withParameter(LootContextParams.EXPLOSION_RADIUS, explosion.radius()); ++ // CraftBukkit start - add yield ++ if (explosion.yield < 1.0F) { ++ lootparams_a.withParameter(LootContextParams.EXPLOSION_RADIUS, 1.0F / explosion.yield); ++ // CraftBukkit end + } + +- blockstate.spawnAfterBreak(serverlevel, blockpos, ItemStack.EMPTY, flag); +- blockstate.getDrops(lootparams_builder).forEach((itemstack) -> { +- biconsumer.accept(itemstack, blockpos); ++ iblockdata.spawnAfterBreak(worldserver, blockposition, ItemStack.EMPTY, flag); ++ iblockdata.getDrops(lootparams_a).forEach((itemstack) -> { ++ biconsumer.accept(itemstack, blockposition); + }); + } + +- level.setBlock(blockpos, Blocks.AIR.defaultBlockState(), 3); +- block.wasExploded(level, blockpos, explosion); ++ world.setBlock(blockposition, Blocks.AIR.defaultBlockState(), 3); ++ block.wasExploded(world, blockposition, explosion); + } + } + + /** @deprecated */ + @Deprecated +- public InteractionResult use(BlockState blockstate, Level level, BlockPos blockpos, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + return InteractionResult.PASS; + } + + /** @deprecated */ + @Deprecated +- public boolean triggerEvent(BlockState blockstate, Level level, BlockPos blockpos, int i, int j) { ++ public boolean triggerEvent(IBlockData state, Level level, BlockPos pos, int id, int param) { + return false; + } + + /** @deprecated */ + @Deprecated +- public RenderShape getRenderShape(BlockState blockstate) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + /** @deprecated */ + @Deprecated +- public boolean useShapeForLightOcclusion(BlockState blockstate) { ++ public boolean useShapeForLightOcclusion(IBlockData state) { + return false; + } + + /** @deprecated */ + @Deprecated +- public boolean isSignalSource(BlockState blockstate) { ++ public boolean isSignalSource(IBlockData state) { + return false; + } + + /** @deprecated */ + @Deprecated +- public FluidState getFluidState(BlockState blockstate) { ++ public FluidState getFluidState(IBlockData state) { + return Fluids.EMPTY.defaultFluidState(); + } + + /** @deprecated */ + @Deprecated +- public boolean hasAnalogOutputSignal(BlockState blockstate) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return false; + } + +@@ -254,46 +256,45 @@ + } + + @Override +- @Override + public FeatureFlagSet requiredFeatures() { + return this.requiredFeatures; + } + + /** @deprecated */ + @Deprecated +- public BlockState rotate(BlockState blockstate, Rotation rotation) { +- return blockstate; ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return state; + } + + /** @deprecated */ + @Deprecated +- public BlockState mirror(BlockState blockstate, Mirror mirror) { +- return blockstate; ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state; + } + + /** @deprecated */ + @Deprecated +- public boolean canBeReplaced(BlockState blockstate, BlockPlaceContext blockplacecontext) { +- return blockstate.canBeReplaced() && (blockplacecontext.getItemInHand().isEmpty() || !blockplacecontext.getItemInHand().is(this.asItem())); ++ public boolean canBeReplaced(IBlockData state, BlockPlaceContext useContext) { ++ return state.canBeReplaced() && (useContext.getItemInHand().isEmpty() || !useContext.getItemInHand().is(this.asItem())); + } + + /** @deprecated */ + @Deprecated +- public boolean canBeReplaced(BlockState blockstate, Fluid fluid) { +- return blockstate.canBeReplaced() || !blockstate.isSolid(); ++ public boolean canBeReplaced(IBlockData state, Fluid fluid) { ++ return state.canBeReplaced() || !state.isSolid(); + } + + /** @deprecated */ + @Deprecated +- public List getDrops(BlockState blockstate, LootParams.Builder lootparams_builder) { +- ResourceLocation resourcelocation = this.getLootTable(); ++ public List getDrops(IBlockData state, LootParams.Builder params) { ++ ResourceLocation minecraftkey = this.getLootTable(); + +- if (resourcelocation == BuiltInLootTables.EMPTY) { ++ if (minecraftkey == BuiltInLootTables.EMPTY) { + return Collections.emptyList(); + } else { +- LootParams lootparams = lootparams_builder.withParameter(LootContextParams.BLOCK_STATE, blockstate).create(LootContextParamSets.BLOCK); +- ServerLevel serverlevel = lootparams.getLevel(); +- LootTable loottable = serverlevel.getServer().getLootData().getLootTable(resourcelocation); ++ LootParams lootparams = params.withParameter(LootContextParams.BLOCK_STATE, state).create(LootContextParamSets.BLOCK); ++ ServerLevel worldserver = lootparams.getLevel(); ++ LootTable loottable = worldserver.getServer().getLootData().getLootTable(minecraftkey); + + return loottable.getRandomItems(lootparams); + } +@@ -301,140 +302,140 @@ + + /** @deprecated */ + @Deprecated +- public long getSeed(BlockState blockstate, BlockPos blockpos) { +- return Mth.getSeed(blockpos); ++ public long getSeed(IBlockData state, BlockPos pos) { ++ return Mth.getSeed(pos); + } + + /** @deprecated */ + @Deprecated +- public VoxelShape getOcclusionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return blockstate.getShape(blockgetter, blockpos); ++ public VoxelShape getOcclusionShape(IBlockData state, BlockGetter level, BlockPos pos) { ++ return state.getShape(level, pos); + } + + /** @deprecated */ + @Deprecated +- public VoxelShape getBlockSupportShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return this.getCollisionShape(blockstate, blockgetter, blockpos, CollisionContext.empty()); ++ public VoxelShape getBlockSupportShape(IBlockData state, BlockGetter level, BlockPos pos) { ++ return this.getCollisionShape(state, level, pos, CollisionContext.empty()); + } + + /** @deprecated */ + @Deprecated +- public VoxelShape getInteractionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { ++ public VoxelShape getInteractionShape(IBlockData state, BlockGetter level, BlockPos pos) { + return Shapes.empty(); + } + + /** @deprecated */ + @Deprecated +- public int getLightBlock(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return blockstate.isSolidRender(blockgetter, blockpos) ? blockgetter.getMaxLightLevel() : (blockstate.propagatesSkylightDown(blockgetter, blockpos) ? 0 : 1); ++ public int getLightBlock(IBlockData state, BlockGetter level, BlockPos pos) { ++ return state.isSolidRender(level, pos) ? level.getMaxLightLevel() : (state.propagatesSkylightDown(level, pos) ? 0 : 1); + } + + /** @deprecated */ + @Nullable + @Deprecated +- public MenuProvider getMenuProvider(BlockState blockstate, Level level, BlockPos blockpos) { ++ public ITileInventory getMenuProvider(IBlockData state, Level level, BlockPos pos) { + return null; + } + + /** @deprecated */ + @Deprecated +- public boolean canSurvive(BlockState blockstate, LevelReader levelreader, BlockPos blockpos) { ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { + return true; + } + + /** @deprecated */ + @Deprecated +- public float getShadeBrightness(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return blockstate.isCollisionShapeFullBlock(blockgetter, blockpos) ? 0.2F : 1.0F; ++ public float getShadeBrightness(IBlockData state, BlockGetter level, BlockPos pos) { ++ return state.isCollisionShapeFullBlock(level, pos) ? 0.2F : 1.0F; + } + + /** @deprecated */ + @Deprecated +- public int getAnalogOutputSignal(BlockState blockstate, Level level, BlockPos blockpos) { ++ public int getAnalogOutputSignal(IBlockData state, Level level, BlockPos pos) { + return 0; + } + + /** @deprecated */ + @Deprecated +- public VoxelShape getShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return Shapes.block(); + } + + /** @deprecated */ + @Deprecated +- public VoxelShape getCollisionShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return this.hasCollision ? blockstate.getShape(blockgetter, blockpos) : Shapes.empty(); ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return this.hasCollision ? state.getShape(level, pos) : Shapes.empty(); + } + + /** @deprecated */ + @Deprecated +- public boolean isCollisionShapeFullBlock(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return Block.isShapeFullBlock(blockstate.getCollisionShape(blockgetter, blockpos)); ++ public boolean isCollisionShapeFullBlock(IBlockData state, BlockGetter level, BlockPos pos) { ++ return Block.isShapeFullBlock(state.getCollisionShape(level, pos)); + } + + /** @deprecated */ + @Deprecated +- public boolean isOcclusionShapeFullBlock(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos) { +- return Block.isShapeFullBlock(blockstate.getOcclusionShape(blockgetter, blockpos)); ++ public boolean isOcclusionShapeFullBlock(IBlockData state, BlockGetter level, BlockPos pos) { ++ return Block.isShapeFullBlock(state.getOcclusionShape(level, pos)); + } + + /** @deprecated */ + @Deprecated +- public VoxelShape getVisualShape(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return this.getCollisionShape(blockstate, blockgetter, blockpos, collisioncontext); ++ public VoxelShape getVisualShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return this.getCollisionShape(state, level, pos, context); + } + + /** @deprecated */ + @Deprecated +- public void randomTick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) {} ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) {} + + /** @deprecated */ + @Deprecated +- public void tick(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) {} ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) {} + + /** @deprecated */ + @Deprecated +- public float getDestroyProgress(BlockState blockstate, Player player, BlockGetter blockgetter, BlockPos blockpos) { +- float f = blockstate.getDestroySpeed(blockgetter, blockpos); ++ public float getDestroyProgress(IBlockData state, Player player, BlockGetter level, BlockPos pos) { ++ float f = state.getDestroySpeed(level, pos); + + if (f == -1.0F) { + return 0.0F; + } else { +- int i = player.hasCorrectToolForDrops(blockstate) ? 30 : 100; ++ int i = player.hasCorrectToolForDrops(state) ? 30 : 100; + +- return player.getDestroySpeed(blockstate) / f / (float) i; ++ return player.getDestroySpeed(state) / f / (float) i; + } + } + + /** @deprecated */ + @Deprecated +- public void spawnAfterBreak(BlockState blockstate, ServerLevel serverlevel, BlockPos blockpos, ItemStack itemstack, boolean flag) {} ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {} + + /** @deprecated */ + @Deprecated +- public void attack(BlockState blockstate, Level level, BlockPos blockpos, Player player) {} ++ public void attack(IBlockData state, Level level, BlockPos pos, Player player) {} + + /** @deprecated */ + @Deprecated +- public int getSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { ++ public int getSignal(IBlockData state, BlockGetter level, BlockPos pos, Direction direction) { + return 0; + } + + /** @deprecated */ + @Deprecated +- public void entityInside(BlockState blockstate, Level level, BlockPos blockpos, Entity entity) {} ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) {} + + /** @deprecated */ + @Deprecated +- public int getDirectSignal(BlockState blockstate, BlockGetter blockgetter, BlockPos blockpos, Direction direction) { ++ public int getDirectSignal(IBlockData state, BlockGetter level, BlockPos pos, Direction direction) { + return 0; + } + + public final ResourceLocation getLootTable() { + if (this.drops == null) { +- ResourceLocation resourcelocation = BuiltInRegistries.BLOCK.getKey(this.asBlock()); ++ ResourceLocation minecraftkey = BuiltInRegistries.BLOCK.getKey(this.asBlock()); + +- this.drops = resourcelocation.withPrefix("blocks/"); ++ this.drops = minecraftkey.withPrefix("blocks/"); + } + + return this.drops; +@@ -442,7 +443,7 @@ + + /** @deprecated */ + @Deprecated +- public void onProjectileHit(Level level, BlockState blockstate, BlockHitResult blockhitresult, Projectile projectile) {} ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) {} + + public abstract Item asItem(); + +@@ -461,12 +462,12 @@ + public static final Codec CODEC = Codec.unit(() -> { + return of(); + }); +- Function mapColor = (blockstate) -> { ++ Function mapColor = (iblockdata) -> { + return MapColor.NONE; + }; + boolean hasCollision = true; + SoundType soundType; +- ToIntFunction lightEmission; ++ ToIntFunction lightEmission; + float explosionResistance; + float destroyTime; + boolean requiresCorrectToolForDrops; +@@ -485,7 +486,7 @@ + @Deprecated + boolean forceSolidOff; + boolean forceSolidOn; +- PushReaction pushReaction; ++ EnumPistonReaction pushReaction; + boolean spawnTerrainParticles; + NoteBlockInstrument instrument; + boolean replaceable; +@@ -501,30 +502,30 @@ + + private Properties() { + this.soundType = SoundType.STONE; +- this.lightEmission = (blockstate) -> { ++ this.lightEmission = (iblockdata) -> { + return 0; + }; + this.friction = 0.6F; + this.speedFactor = 1.0F; + this.jumpFactor = 1.0F; + this.canOcclude = true; +- this.pushReaction = PushReaction.NORMAL; ++ this.pushReaction = EnumPistonReaction.NORMAL; + this.spawnTerrainParticles = true; + this.instrument = NoteBlockInstrument.HARP; +- this.isValidSpawn = (blockstate, blockgetter, blockpos, entitytype) -> { +- return blockstate.isFaceSturdy(blockgetter, blockpos, Direction.UP) && blockstate.getLightEmission() < 14; ++ this.isValidSpawn = (iblockdata, iblockaccess, blockposition, entitytypes) -> { ++ return iblockdata.isFaceSturdy(iblockaccess, blockposition, Direction.UP) && iblockdata.getLightEmission() < 14; + }; +- this.isRedstoneConductor = (blockstate, blockgetter, blockpos) -> { +- return blockstate.isCollisionShapeFullBlock(blockgetter, blockpos); ++ this.isRedstoneConductor = (iblockdata, iblockaccess, blockposition) -> { ++ return iblockdata.isCollisionShapeFullBlock(iblockaccess, blockposition); + }; +- this.isSuffocating = (blockstate, blockgetter, blockpos) -> { +- return blockstate.blocksMotion() && blockstate.isCollisionShapeFullBlock(blockgetter, blockpos); ++ this.isSuffocating = (iblockdata, iblockaccess, blockposition) -> { ++ return iblockdata.blocksMotion() && iblockdata.isCollisionShapeFullBlock(iblockaccess, blockposition); + }; + this.isViewBlocking = this.isSuffocating; +- this.hasPostProcess = (blockstate, blockgetter, blockpos) -> { ++ this.hasPostProcess = (iblockdata, iblockaccess, blockposition) -> { + return false; + }; +- this.emissiveRendering = (blockstate, blockgetter, blockpos) -> { ++ this.emissiveRendering = (iblockdata, iblockaccess, blockposition) -> { + return false; + }; + this.requiredFeatures = FeatureFlags.VANILLA_SET; +@@ -535,69 +536,69 @@ + return new BlockBehaviour.Properties(); + } + +- public static BlockBehaviour.Properties ofFullCopy(BlockBehaviour blockbehaviour) { +- BlockBehaviour.Properties blockbehaviour_properties = ofLegacyCopy(blockbehaviour); +- BlockBehaviour.Properties blockbehaviour_properties1 = blockbehaviour.properties; ++ public static BlockBehaviour.Properties ofFullCopy(BlockBehaviour blockbase) { ++ BlockBehaviour.Properties blockbase_info = ofLegacyCopy(blockbase); ++ BlockBehaviour.Properties blockbase_info1 = blockbase.properties; + +- blockbehaviour_properties.jumpFactor = blockbehaviour_properties1.jumpFactor; +- blockbehaviour_properties.isRedstoneConductor = blockbehaviour_properties1.isRedstoneConductor; +- blockbehaviour_properties.isValidSpawn = blockbehaviour_properties1.isValidSpawn; +- blockbehaviour_properties.hasPostProcess = blockbehaviour_properties1.hasPostProcess; +- blockbehaviour_properties.isSuffocating = blockbehaviour_properties1.isSuffocating; +- blockbehaviour_properties.isViewBlocking = blockbehaviour_properties1.isViewBlocking; +- blockbehaviour_properties.drops = blockbehaviour_properties1.drops; +- return blockbehaviour_properties; ++ blockbase_info.jumpFactor = blockbase_info1.jumpFactor; ++ blockbase_info.isRedstoneConductor = blockbase_info1.isRedstoneConductor; ++ blockbase_info.isValidSpawn = blockbase_info1.isValidSpawn; ++ blockbase_info.hasPostProcess = blockbase_info1.hasPostProcess; ++ blockbase_info.isSuffocating = blockbase_info1.isSuffocating; ++ blockbase_info.isViewBlocking = blockbase_info1.isViewBlocking; ++ blockbase_info.drops = blockbase_info1.drops; ++ return blockbase_info; + } + + /** @deprecated */ + @Deprecated +- public static BlockBehaviour.Properties ofLegacyCopy(BlockBehaviour blockbehaviour) { +- BlockBehaviour.Properties blockbehaviour_properties = new BlockBehaviour.Properties(); +- BlockBehaviour.Properties blockbehaviour_properties1 = blockbehaviour.properties; ++ public static BlockBehaviour.Properties ofLegacyCopy(BlockBehaviour blockbase) { ++ BlockBehaviour.Properties blockbase_info = new BlockBehaviour.Properties(); ++ BlockBehaviour.Properties blockbase_info1 = blockbase.properties; + +- blockbehaviour_properties.destroyTime = blockbehaviour_properties1.destroyTime; +- blockbehaviour_properties.explosionResistance = blockbehaviour_properties1.explosionResistance; +- blockbehaviour_properties.hasCollision = blockbehaviour_properties1.hasCollision; +- blockbehaviour_properties.isRandomlyTicking = blockbehaviour_properties1.isRandomlyTicking; +- blockbehaviour_properties.lightEmission = blockbehaviour_properties1.lightEmission; +- blockbehaviour_properties.mapColor = blockbehaviour_properties1.mapColor; +- blockbehaviour_properties.soundType = blockbehaviour_properties1.soundType; +- blockbehaviour_properties.friction = blockbehaviour_properties1.friction; +- blockbehaviour_properties.speedFactor = blockbehaviour_properties1.speedFactor; +- blockbehaviour_properties.dynamicShape = blockbehaviour_properties1.dynamicShape; +- blockbehaviour_properties.canOcclude = blockbehaviour_properties1.canOcclude; +- blockbehaviour_properties.isAir = blockbehaviour_properties1.isAir; +- blockbehaviour_properties.ignitedByLava = blockbehaviour_properties1.ignitedByLava; +- blockbehaviour_properties.liquid = blockbehaviour_properties1.liquid; +- blockbehaviour_properties.forceSolidOff = blockbehaviour_properties1.forceSolidOff; +- blockbehaviour_properties.forceSolidOn = blockbehaviour_properties1.forceSolidOn; +- blockbehaviour_properties.pushReaction = blockbehaviour_properties1.pushReaction; +- blockbehaviour_properties.requiresCorrectToolForDrops = blockbehaviour_properties1.requiresCorrectToolForDrops; +- blockbehaviour_properties.offsetFunction = blockbehaviour_properties1.offsetFunction; +- blockbehaviour_properties.spawnTerrainParticles = blockbehaviour_properties1.spawnTerrainParticles; +- blockbehaviour_properties.requiredFeatures = blockbehaviour_properties1.requiredFeatures; +- blockbehaviour_properties.emissiveRendering = blockbehaviour_properties1.emissiveRendering; +- blockbehaviour_properties.instrument = blockbehaviour_properties1.instrument; +- blockbehaviour_properties.replaceable = blockbehaviour_properties1.replaceable; +- return blockbehaviour_properties; ++ blockbase_info.destroyTime = blockbase_info1.destroyTime; ++ blockbase_info.explosionResistance = blockbase_info1.explosionResistance; ++ blockbase_info.hasCollision = blockbase_info1.hasCollision; ++ blockbase_info.isRandomlyTicking = blockbase_info1.isRandomlyTicking; ++ blockbase_info.lightEmission = blockbase_info1.lightEmission; ++ blockbase_info.mapColor = blockbase_info1.mapColor; ++ blockbase_info.soundType = blockbase_info1.soundType; ++ blockbase_info.friction = blockbase_info1.friction; ++ blockbase_info.speedFactor = blockbase_info1.speedFactor; ++ blockbase_info.dynamicShape = blockbase_info1.dynamicShape; ++ blockbase_info.canOcclude = blockbase_info1.canOcclude; ++ blockbase_info.isAir = blockbase_info1.isAir; ++ blockbase_info.ignitedByLava = blockbase_info1.ignitedByLava; ++ blockbase_info.liquid = blockbase_info1.liquid; ++ blockbase_info.forceSolidOff = blockbase_info1.forceSolidOff; ++ blockbase_info.forceSolidOn = blockbase_info1.forceSolidOn; ++ blockbase_info.pushReaction = blockbase_info1.pushReaction; ++ blockbase_info.requiresCorrectToolForDrops = blockbase_info1.requiresCorrectToolForDrops; ++ blockbase_info.offsetFunction = blockbase_info1.offsetFunction; ++ blockbase_info.spawnTerrainParticles = blockbase_info1.spawnTerrainParticles; ++ blockbase_info.requiredFeatures = blockbase_info1.requiredFeatures; ++ blockbase_info.emissiveRendering = blockbase_info1.emissiveRendering; ++ blockbase_info.instrument = blockbase_info1.instrument; ++ blockbase_info.replaceable = blockbase_info1.replaceable; ++ return blockbase_info; + } + +- public BlockBehaviour.Properties mapColor(DyeColor dyecolor) { +- this.mapColor = (blockstate) -> { +- return dyecolor.getMapColor(); ++ public BlockBehaviour.Properties mapColor(DyeColor mapColor) { ++ this.mapColor = (iblockdata) -> { ++ return mapColor.getMapColor(); + }; + return this; + } + +- public BlockBehaviour.Properties mapColor(MapColor mapcolor) { +- this.mapColor = (blockstate) -> { +- return mapcolor; ++ public BlockBehaviour.Properties mapColor(MapColor mapColor) { ++ this.mapColor = (iblockdata) -> { ++ return mapColor; + }; + return this; + } + +- public BlockBehaviour.Properties mapColor(Function function) { +- this.mapColor = function; ++ public BlockBehaviour.Properties mapColor(Function mapColor) { ++ this.mapColor = mapColor; + return this; + } + +@@ -612,41 +613,41 @@ + return this; + } + +- public BlockBehaviour.Properties friction(float f) { +- this.friction = f; ++ public BlockBehaviour.Properties friction(float friction) { ++ this.friction = friction; + return this; + } + +- public BlockBehaviour.Properties speedFactor(float f) { +- this.speedFactor = f; ++ public BlockBehaviour.Properties speedFactor(float speedFactor) { ++ this.speedFactor = speedFactor; + return this; + } + +- public BlockBehaviour.Properties jumpFactor(float f) { +- this.jumpFactor = f; ++ public BlockBehaviour.Properties jumpFactor(float jumpFactor) { ++ this.jumpFactor = jumpFactor; + return this; + } + +- public BlockBehaviour.Properties sound(SoundType soundtype) { +- this.soundType = soundtype; ++ public BlockBehaviour.Properties sound(SoundType soundType) { ++ this.soundType = soundType; + return this; + } + +- public BlockBehaviour.Properties lightLevel(ToIntFunction tointfunction) { +- this.lightEmission = tointfunction; ++ public BlockBehaviour.Properties lightLevel(ToIntFunction lightEmission) { ++ this.lightEmission = lightEmission; + return this; + } + +- public BlockBehaviour.Properties strength(float f, float f1) { +- return this.destroyTime(f).explosionResistance(f1); ++ public BlockBehaviour.Properties strength(float destroyTime, float explosionResistance) { ++ return this.destroyTime(destroyTime).explosionResistance(explosionResistance); + } + + public BlockBehaviour.Properties instabreak() { + return this.strength(0.0F); + } + +- public BlockBehaviour.Properties strength(float f) { +- this.strength(f, f); ++ public BlockBehaviour.Properties strength(float strength) { ++ this.strength(strength, strength); + return this; + } + +@@ -692,8 +693,8 @@ + return this; + } + +- public BlockBehaviour.Properties pushReaction(PushReaction pushreaction) { +- this.pushReaction = pushreaction; ++ public BlockBehaviour.Properties pushReaction(EnumPistonReaction pushReaction) { ++ this.pushReaction = pushReaction; + return this; + } + +@@ -702,33 +703,33 @@ + return this; + } + +- public BlockBehaviour.Properties isValidSpawn(BlockBehaviour.StateArgumentPredicate> blockbehaviour_stateargumentpredicate) { +- this.isValidSpawn = blockbehaviour_stateargumentpredicate; ++ public BlockBehaviour.Properties isValidSpawn(BlockBehaviour.StateArgumentPredicate> isValidSpawn) { ++ this.isValidSpawn = isValidSpawn; + return this; + } + +- public BlockBehaviour.Properties isRedstoneConductor(BlockBehaviour.StatePredicate blockbehaviour_statepredicate) { +- this.isRedstoneConductor = blockbehaviour_statepredicate; ++ public BlockBehaviour.Properties isRedstoneConductor(BlockBehaviour.StatePredicate isRedstoneConductor) { ++ this.isRedstoneConductor = isRedstoneConductor; + return this; + } + +- public BlockBehaviour.Properties isSuffocating(BlockBehaviour.StatePredicate blockbehaviour_statepredicate) { +- this.isSuffocating = blockbehaviour_statepredicate; ++ public BlockBehaviour.Properties isSuffocating(BlockBehaviour.StatePredicate isSuffocating) { ++ this.isSuffocating = isSuffocating; + return this; + } + +- public BlockBehaviour.Properties isViewBlocking(BlockBehaviour.StatePredicate blockbehaviour_statepredicate) { +- this.isViewBlocking = blockbehaviour_statepredicate; ++ public BlockBehaviour.Properties isViewBlocking(BlockBehaviour.StatePredicate isViewBlocking) { ++ this.isViewBlocking = isViewBlocking; + return this; + } + +- public BlockBehaviour.Properties hasPostProcess(BlockBehaviour.StatePredicate blockbehaviour_statepredicate) { +- this.hasPostProcess = blockbehaviour_statepredicate; ++ public BlockBehaviour.Properties hasPostProcess(BlockBehaviour.StatePredicate hasPostProcess) { ++ this.hasPostProcess = hasPostProcess; + return this; + } + +- public BlockBehaviour.Properties emissiveRendering(BlockBehaviour.StatePredicate blockbehaviour_statepredicate) { +- this.emissiveRendering = blockbehaviour_statepredicate; ++ public BlockBehaviour.Properties emissiveRendering(BlockBehaviour.StatePredicate emissiveRendering) { ++ this.emissiveRendering = emissiveRendering; + return this; + } + +@@ -737,22 +738,22 @@ + return this; + } + +- public BlockBehaviour.Properties destroyTime(float f) { +- this.destroyTime = f; ++ public BlockBehaviour.Properties destroyTime(float destroyTime) { ++ this.destroyTime = destroyTime; + return this; + } + +- public BlockBehaviour.Properties explosionResistance(float f) { +- this.explosionResistance = Math.max(0.0F, f); ++ public BlockBehaviour.Properties explosionResistance(float explosionResistance) { ++ this.explosionResistance = Math.max(0.0F, explosionResistance); + return this; + } + +- public BlockBehaviour.Properties offsetType(BlockBehaviour.OffsetType blockbehaviour_offsettype) { +- switch (blockbehaviour_offsettype) { ++ public BlockBehaviour.Properties offsetType(BlockBehaviour.EnumRandomOffset offsetType) { ++ switch (offsetType) { + case XYZ: +- this.offsetFunction = Optional.of((blockstate, blockgetter, blockpos) -> { +- Block block = blockstate.getBlock(); +- long i = Mth.getSeed(blockpos.getX(), 0, blockpos.getZ()); ++ this.offsetFunction = Optional.of((iblockdata, iblockaccess, blockposition) -> { ++ Block block = iblockdata.getBlock(); ++ long i = Mth.getSeed(blockposition.getX(), 0, blockposition.getZ()); + double d0 = ((double) ((float) (i >> 4 & 15L) / 15.0F) - 1.0D) * (double) block.getMaxVerticalOffset(); + float f = block.getMaxHorizontalOffset(); + double d1 = Mth.clamp(((double) ((float) (i & 15L) / 15.0F) - 0.5D) * 0.5D, (double) (-f), (double) f); +@@ -762,9 +763,9 @@ + }); + break; + case XZ: +- this.offsetFunction = Optional.of((blockstate, blockgetter, blockpos) -> { +- Block block = blockstate.getBlock(); +- long i = Mth.getSeed(blockpos.getX(), 0, blockpos.getZ()); ++ this.offsetFunction = Optional.of((iblockdata, iblockaccess, blockposition) -> { ++ Block block = iblockdata.getBlock(); ++ long i = Mth.getSeed(blockposition.getX(), 0, blockposition.getZ()); + float f = block.getMaxHorizontalOffset(); + double d0 = Mth.clamp(((double) ((float) (i & 15L) / 15.0F) - 0.5D) * 0.5D, (double) (-f), (double) f); + double d1 = Mth.clamp(((double) ((float) (i >> 8 & 15L) / 15.0F) - 0.5D) * 0.5D, (double) (-f), (double) f); +@@ -784,13 +785,13 @@ + return this; + } + +- public BlockBehaviour.Properties requiredFeatures(FeatureFlag... afeatureflag) { +- this.requiredFeatures = FeatureFlags.REGISTRY.subset(afeatureflag); ++ public BlockBehaviour.Properties requiredFeatures(FeatureFlag... requiredFeatures) { ++ this.requiredFeatures = FeatureFlags.REGISTRY.subset(requiredFeatures); + return this; + } + +- public BlockBehaviour.Properties instrument(NoteBlockInstrument noteblockinstrument) { +- this.instrument = noteblockinstrument; ++ public BlockBehaviour.Properties instrument(NoteBlockInstrument instrument) { ++ this.instrument = instrument; + return this; + } + +@@ -802,20 +803,20 @@ + + public interface StateArgumentPredicate { + +- boolean test(BlockState state, BlockGetter level, BlockPos pos, A value); ++ boolean test(IBlockData state, BlockGetter level, BlockPos pos, A value); + } + + public interface OffsetFunction { + +- Vec3 evaluate(BlockState state, BlockGetter level, BlockPos pos); ++ Vec3 evaluate(IBlockData state, BlockGetter level, BlockPos pos); + } + + public interface StatePredicate { + +- boolean test(BlockState state, BlockGetter level, BlockPos pos); ++ boolean test(IBlockData state, BlockGetter level, BlockPos pos); + } + +- public abstract static class BlockStateBase extends StateHolder { ++ public abstract static class BlockStateBase extends StateHolder { + + private final int lightEmission; + private final boolean useShapeForLightOcclusion; +@@ -827,9 +828,9 @@ + /** @deprecated */ + @Deprecated + private boolean legacySolid; +- private final PushReaction pushReaction; ++ private final EnumPistonReaction pushReaction; + private final MapColor mapColor; +- private final float destroySpeed; ++ public final float destroySpeed; + private final boolean requiresCorrectToolForDrops; + private final boolean canOcclude; + private final BlockBehaviour.StatePredicate isRedstoneConductor; +@@ -846,30 +847,30 @@ + private FluidState fluidState; + private boolean isRandomlyTicking; + +- protected BlockStateBase(Block block, ImmutableMap, Comparable> immutablemap, MapCodec mapcodec) { +- super(block, immutablemap, mapcodec); ++ protected BlockStateBase(Block owner, ImmutableMap, Comparable> values, MapCodec propertiesCodec) { ++ super(owner, values, propertiesCodec); + this.fluidState = Fluids.EMPTY.defaultFluidState(); +- BlockBehaviour.Properties blockbehaviour_properties = block.properties; ++ BlockBehaviour.Properties blockbase_info = owner.properties; + +- this.lightEmission = blockbehaviour_properties.lightEmission.applyAsInt(this.asState()); +- this.useShapeForLightOcclusion = block.useShapeForLightOcclusion(this.asState()); +- this.isAir = blockbehaviour_properties.isAir; +- this.ignitedByLava = blockbehaviour_properties.ignitedByLava; +- this.liquid = blockbehaviour_properties.liquid; +- this.pushReaction = blockbehaviour_properties.pushReaction; +- this.mapColor = (MapColor) blockbehaviour_properties.mapColor.apply(this.asState()); +- this.destroySpeed = blockbehaviour_properties.destroyTime; +- this.requiresCorrectToolForDrops = blockbehaviour_properties.requiresCorrectToolForDrops; +- this.canOcclude = blockbehaviour_properties.canOcclude; +- this.isRedstoneConductor = blockbehaviour_properties.isRedstoneConductor; +- this.isSuffocating = blockbehaviour_properties.isSuffocating; +- this.isViewBlocking = blockbehaviour_properties.isViewBlocking; +- this.hasPostProcess = blockbehaviour_properties.hasPostProcess; +- this.emissiveRendering = blockbehaviour_properties.emissiveRendering; +- this.offsetFunction = blockbehaviour_properties.offsetFunction; +- this.spawnTerrainParticles = blockbehaviour_properties.spawnTerrainParticles; +- this.instrument = blockbehaviour_properties.instrument; +- this.replaceable = blockbehaviour_properties.replaceable; ++ this.lightEmission = blockbase_info.lightEmission.applyAsInt(this.asState()); ++ this.useShapeForLightOcclusion = owner.useShapeForLightOcclusion(this.asState()); ++ this.isAir = blockbase_info.isAir; ++ this.ignitedByLava = blockbase_info.ignitedByLava; ++ this.liquid = blockbase_info.liquid; ++ this.pushReaction = blockbase_info.pushReaction; ++ this.mapColor = (MapColor) blockbase_info.mapColor.apply(this.asState()); ++ this.destroySpeed = blockbase_info.destroyTime; ++ this.requiresCorrectToolForDrops = blockbase_info.requiresCorrectToolForDrops; ++ this.canOcclude = blockbase_info.canOcclude; ++ this.isRedstoneConductor = blockbase_info.isRedstoneConductor; ++ this.isSuffocating = blockbase_info.isSuffocating; ++ this.isViewBlocking = blockbase_info.isViewBlocking; ++ this.hasPostProcess = blockbase_info.hasPostProcess; ++ this.emissiveRendering = blockbase_info.emissiveRendering; ++ this.offsetFunction = blockbase_info.offsetFunction; ++ this.spawnTerrainParticles = blockbase_info.spawnTerrainParticles; ++ this.instrument = blockbase_info.instrument; ++ this.replaceable = blockbase_info.replaceable; + } + + private boolean calculateSolid() { +@@ -885,9 +886,9 @@ + if (voxelshape.isEmpty()) { + return false; + } else { +- AABB aabb = voxelshape.bounds(); ++ AABB axisalignedbb = voxelshape.bounds(); + +- return aabb.getSize() >= 0.7291666666666666D ? true : aabb.getYsize() >= 1.0D; ++ return axisalignedbb.getSize() >= 0.7291666666666666D ? true : axisalignedbb.getYsize() >= 1.0D; + } + } + } +@@ -924,24 +925,24 @@ + return this.legacySolid; + } + +- public boolean isValidSpawn(BlockGetter blockgetter, BlockPos blockpos, EntityType entitytype) { +- return this.getBlock().properties.isValidSpawn.test(this.asState(), blockgetter, blockpos, entitytype); ++ public boolean isValidSpawn(BlockGetter level, BlockPos pos, EntityType entityType) { ++ return this.getBlock().properties.isValidSpawn.test(this.asState(), level, pos, entityType); + } + +- public boolean propagatesSkylightDown(BlockGetter blockgetter, BlockPos blockpos) { +- return this.cache != null ? this.cache.propagatesSkylightDown : this.getBlock().propagatesSkylightDown(this.asState(), blockgetter, blockpos); ++ public boolean propagatesSkylightDown(BlockGetter level, BlockPos pos) { ++ return this.cache != null ? this.cache.propagatesSkylightDown : this.getBlock().propagatesSkylightDown(this.asState(), level, pos); + } + +- public int getLightBlock(BlockGetter blockgetter, BlockPos blockpos) { +- return this.cache != null ? this.cache.lightBlock : this.getBlock().getLightBlock(this.asState(), blockgetter, blockpos); ++ public int getLightBlock(BlockGetter level, BlockPos pos) { ++ return this.cache != null ? this.cache.lightBlock : this.getBlock().getLightBlock(this.asState(), level, pos); + } + +- public VoxelShape getFaceOcclusionShape(BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return this.cache != null && this.cache.occlusionShapes != null ? this.cache.occlusionShapes[direction.ordinal()] : Shapes.getFaceShape(this.getOcclusionShape(blockgetter, blockpos), direction); ++ public VoxelShape getFaceOcclusionShape(BlockGetter level, BlockPos pos, Direction direction) { ++ return this.cache != null && this.cache.occlusionShapes != null ? this.cache.occlusionShapes[direction.ordinal()] : Shapes.getFaceShape(this.getOcclusionShape(level, pos), direction); + } + +- public VoxelShape getOcclusionShape(BlockGetter blockgetter, BlockPos blockpos) { +- return this.getBlock().getOcclusionShape(this.asState(), blockgetter, blockpos); ++ public VoxelShape getOcclusionShape(BlockGetter level, BlockPos pos) { ++ return this.getBlock().getOcclusionShape(this.asState(), level, pos); + } + + public boolean hasLargeCollisionShape() { +@@ -970,73 +971,73 @@ + return this.liquid; + } + +- public MapColor getMapColor(BlockGetter blockgetter, BlockPos blockpos) { ++ public MapColor getMapColor(BlockGetter level, BlockPos pos) { + return this.mapColor; + } + +- public BlockState rotate(Rotation rotation) { ++ public IBlockData rotate(Rotation rotation) { + return this.getBlock().rotate(this.asState(), rotation); + } + +- public BlockState mirror(Mirror mirror) { ++ public IBlockData mirror(Mirror mirror) { + return this.getBlock().mirror(this.asState(), mirror); + } + +- public RenderShape getRenderShape() { ++ public EnumRenderType getRenderShape() { + return this.getBlock().getRenderShape(this.asState()); + } + +- public boolean emissiveRendering(BlockGetter blockgetter, BlockPos blockpos) { +- return this.emissiveRendering.test(this.asState(), blockgetter, blockpos); ++ public boolean emissiveRendering(BlockGetter level, BlockPos pos) { ++ return this.emissiveRendering.test(this.asState(), level, pos); + } + +- public float getShadeBrightness(BlockGetter blockgetter, BlockPos blockpos) { +- return this.getBlock().getShadeBrightness(this.asState(), blockgetter, blockpos); ++ public float getShadeBrightness(BlockGetter level, BlockPos pos) { ++ return this.getBlock().getShadeBrightness(this.asState(), level, pos); + } + +- public boolean isRedstoneConductor(BlockGetter blockgetter, BlockPos blockpos) { +- return this.isRedstoneConductor.test(this.asState(), blockgetter, blockpos); ++ public boolean isRedstoneConductor(BlockGetter level, BlockPos pos) { ++ return this.isRedstoneConductor.test(this.asState(), level, pos); + } + + public boolean isSignalSource() { + return this.getBlock().isSignalSource(this.asState()); + } + +- public int getSignal(BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return this.getBlock().getSignal(this.asState(), blockgetter, blockpos, direction); ++ public int getSignal(BlockGetter level, BlockPos pos, Direction direction) { ++ return this.getBlock().getSignal(this.asState(), level, pos, direction); + } + + public boolean hasAnalogOutputSignal() { + return this.getBlock().hasAnalogOutputSignal(this.asState()); + } + +- public int getAnalogOutputSignal(Level level, BlockPos blockpos) { +- return this.getBlock().getAnalogOutputSignal(this.asState(), level, blockpos); ++ public int getAnalogOutputSignal(Level level, BlockPos pos) { ++ return this.getBlock().getAnalogOutputSignal(this.asState(), level, pos); + } + +- public float getDestroySpeed(BlockGetter blockgetter, BlockPos blockpos) { ++ public float getDestroySpeed(BlockGetter level, BlockPos pos) { + return this.destroySpeed; + } + +- public float getDestroyProgress(Player player, BlockGetter blockgetter, BlockPos blockpos) { +- return this.getBlock().getDestroyProgress(this.asState(), player, blockgetter, blockpos); ++ public float getDestroyProgress(Player player, BlockGetter level, BlockPos pos) { ++ return this.getBlock().getDestroyProgress(this.asState(), player, level, pos); + } + +- public int getDirectSignal(BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return this.getBlock().getDirectSignal(this.asState(), blockgetter, blockpos, direction); ++ public int getDirectSignal(BlockGetter level, BlockPos pos, Direction direction) { ++ return this.getBlock().getDirectSignal(this.asState(), level, pos, direction); + } + +- public PushReaction getPistonPushReaction() { ++ public EnumPistonReaction getPistonPushReaction() { + return this.pushReaction; + } + +- public boolean isSolidRender(BlockGetter blockgetter, BlockPos blockpos) { ++ public boolean isSolidRender(BlockGetter level, BlockPos pos) { + if (this.cache != null) { + return this.cache.solidRender; + } else { +- BlockState blockstate = this.asState(); ++ IBlockData iblockdata = this.asState(); + +- return blockstate.canOcclude() ? Block.isShapeFullBlock(blockstate.getOcclusionShape(blockgetter, blockpos)) : false; ++ return iblockdata.canOcclude() ? Block.isShapeFullBlock(iblockdata.getOcclusionShape(level, pos)) : false; + } + } + +@@ -1044,49 +1045,49 @@ + return this.canOcclude; + } + +- public boolean skipRendering(BlockState blockstate, Direction direction) { +- return this.getBlock().skipRendering(this.asState(), blockstate, direction); ++ public boolean skipRendering(IBlockData state, Direction face) { ++ return this.getBlock().skipRendering(this.asState(), state, face); + } + +- public VoxelShape getShape(BlockGetter blockgetter, BlockPos blockpos) { +- return this.getShape(blockgetter, blockpos, CollisionContext.empty()); ++ public VoxelShape getShape(BlockGetter level, BlockPos pos) { ++ return this.getShape(level, pos, CollisionContext.empty()); + } + +- public VoxelShape getShape(BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return this.getBlock().getShape(this.asState(), blockgetter, blockpos, collisioncontext); ++ public VoxelShape getShape(BlockGetter level, BlockPos pos, CollisionContext context) { ++ return this.getBlock().getShape(this.asState(), level, pos, context); + } + +- public VoxelShape getCollisionShape(BlockGetter blockgetter, BlockPos blockpos) { +- return this.cache != null ? this.cache.collisionShape : this.getCollisionShape(blockgetter, blockpos, CollisionContext.empty()); ++ public VoxelShape getCollisionShape(BlockGetter level, BlockPos pos) { ++ return this.cache != null ? this.cache.collisionShape : this.getCollisionShape(level, pos, CollisionContext.empty()); + } + +- public VoxelShape getCollisionShape(BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return this.getBlock().getCollisionShape(this.asState(), blockgetter, blockpos, collisioncontext); ++ public VoxelShape getCollisionShape(BlockGetter level, BlockPos pos, CollisionContext context) { ++ return this.getBlock().getCollisionShape(this.asState(), level, pos, context); + } + +- public VoxelShape getBlockSupportShape(BlockGetter blockgetter, BlockPos blockpos) { +- return this.getBlock().getBlockSupportShape(this.asState(), blockgetter, blockpos); ++ public VoxelShape getBlockSupportShape(BlockGetter level, BlockPos pos) { ++ return this.getBlock().getBlockSupportShape(this.asState(), level, pos); + } + +- public VoxelShape getVisualShape(BlockGetter blockgetter, BlockPos blockpos, CollisionContext collisioncontext) { +- return this.getBlock().getVisualShape(this.asState(), blockgetter, blockpos, collisioncontext); ++ public VoxelShape getVisualShape(BlockGetter level, BlockPos pos, CollisionContext context) { ++ return this.getBlock().getVisualShape(this.asState(), level, pos, context); + } + +- public VoxelShape getInteractionShape(BlockGetter blockgetter, BlockPos blockpos) { +- return this.getBlock().getInteractionShape(this.asState(), blockgetter, blockpos); ++ public VoxelShape getInteractionShape(BlockGetter level, BlockPos pos) { ++ return this.getBlock().getInteractionShape(this.asState(), level, pos); + } + +- public final boolean entityCanStandOn(BlockGetter blockgetter, BlockPos blockpos, Entity entity) { +- return this.entityCanStandOnFace(blockgetter, blockpos, entity, Direction.UP); ++ public final boolean entityCanStandOn(BlockGetter level, BlockPos pos, Entity entity) { ++ return this.entityCanStandOnFace(level, pos, entity, Direction.UP); + } + +- public final boolean entityCanStandOnFace(BlockGetter blockgetter, BlockPos blockpos, Entity entity, Direction direction) { +- return Block.isFaceFull(this.getCollisionShape(blockgetter, blockpos, CollisionContext.of(entity)), direction); ++ public final boolean entityCanStandOnFace(BlockGetter level, BlockPos pos, Entity entity, Direction face) { ++ return Block.isFaceFull(this.getCollisionShape(level, pos, CollisionContext.of(entity)), face); + } + +- public Vec3 getOffset(BlockGetter blockgetter, BlockPos blockpos) { +- return (Vec3) this.offsetFunction.map((blockbehaviour_offsetfunction) -> { +- return blockbehaviour_offsetfunction.evaluate(this.asState(), blockgetter, blockpos); ++ public Vec3 getOffset(BlockGetter level, BlockPos pos) { ++ return (Vec3) this.offsetFunction.map((blockbase_b) -> { ++ return blockbase_b.evaluate(this.asState(), level, pos); + }).orElse(Vec3.ZERO); + } + +@@ -1094,100 +1095,100 @@ + return this.offsetFunction.isPresent(); + } + +- public boolean triggerEvent(Level level, BlockPos blockpos, int i, int j) { +- return this.getBlock().triggerEvent(this.asState(), level, blockpos, i, j); ++ public boolean triggerEvent(Level level, BlockPos pos, int id, int param) { ++ return this.getBlock().triggerEvent(this.asState(), level, pos, id, param); + } + + /** @deprecated */ + @Deprecated +- public void neighborChanged(Level level, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { +- this.getBlock().neighborChanged(this.asState(), level, blockpos, block, blockpos1, flag); ++ public void neighborChanged(Level level, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston) { ++ this.getBlock().neighborChanged(this.asState(), level, pos, neighborBlock, neighborPos, movedByPiston); + } + +- public final void updateNeighbourShapes(LevelAccessor levelaccessor, BlockPos blockpos, int i) { +- this.updateNeighbourShapes(levelaccessor, blockpos, i, 512); ++ public final void updateNeighbourShapes(LevelAccessor level, BlockPos pos, int flags) { ++ this.updateNeighbourShapes(level, pos, flags, 512); + } + +- public final void updateNeighbourShapes(LevelAccessor levelaccessor, BlockPos blockpos, int i, int j) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); +- Direction[] adirection = BlockBehaviour.UPDATE_SHAPE_ORDER; +- int k = adirection.length; ++ public final void updateNeighbourShapes(LevelAccessor level, BlockPos pos, int flags, int recursionLeft) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ Direction[] aenumdirection = BlockBehaviour.UPDATE_SHAPE_ORDER; ++ int k = aenumdirection.length; + + for (int l = 0; l < k; ++l) { +- Direction direction = adirection[l]; ++ Direction enumdirection = aenumdirection[l]; + +- blockpos_mutableblockpos.setWithOffset(blockpos, direction); +- levelaccessor.neighborShapeChanged(direction.getOpposite(), this.asState(), blockpos_mutableblockpos, blockpos, i, j); ++ blockposition_mutableblockposition.setWithOffset(pos, enumdirection); ++ level.neighborShapeChanged(enumdirection.getOpposite(), this.asState(), blockposition_mutableblockposition, pos, flags, recursionLeft); + } + + } + +- public final void updateIndirectNeighbourShapes(LevelAccessor levelaccessor, BlockPos blockpos, int i) { +- this.updateIndirectNeighbourShapes(levelaccessor, blockpos, i, 512); ++ public final void updateIndirectNeighbourShapes(LevelAccessor level, BlockPos pos, int flags) { ++ this.updateIndirectNeighbourShapes(level, pos, flags, 512); + } + +- public void updateIndirectNeighbourShapes(LevelAccessor levelaccessor, BlockPos blockpos, int i, int j) { +- this.getBlock().updateIndirectNeighbourShapes(this.asState(), levelaccessor, blockpos, i, j); ++ public void updateIndirectNeighbourShapes(LevelAccessor level, BlockPos pos, int flags, int recursionLeft) { ++ this.getBlock().updateIndirectNeighbourShapes(this.asState(), level, pos, flags, recursionLeft); + } + +- public void onPlace(Level level, BlockPos blockpos, BlockState blockstate, boolean flag) { +- this.getBlock().onPlace(this.asState(), level, blockpos, blockstate, flag); ++ public void onPlace(Level level, BlockPos pos, IBlockData oldState, boolean movedByPiston) { ++ this.getBlock().onPlace(this.asState(), level, pos, oldState, movedByPiston); + } + +- public void onRemove(Level level, BlockPos blockpos, BlockState blockstate, boolean flag) { +- this.getBlock().onRemove(this.asState(), level, blockpos, blockstate, flag); ++ public void onRemove(Level level, BlockPos pos, IBlockData newState, boolean movedByPiston) { ++ this.getBlock().onRemove(this.asState(), level, pos, newState, movedByPiston); + } + +- public void onExplosionHit(Level level, BlockPos blockpos, Explosion explosion, BiConsumer biconsumer) { +- this.getBlock().onExplosionHit(this.asState(), level, blockpos, explosion, biconsumer); ++ public void onExplosionHit(Level world, BlockPos blockposition, Explosion explosion, BiConsumer biconsumer) { ++ this.getBlock().onExplosionHit(this.asState(), world, blockposition, explosion, biconsumer); + } + +- public void tick(ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- this.getBlock().tick(this.asState(), serverlevel, blockpos, randomsource); ++ public void tick(ServerLevel level, BlockPos pos, RandomSource random) { ++ this.getBlock().tick(this.asState(), level, pos, random); + } + +- public void randomTick(ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource) { +- this.getBlock().randomTick(this.asState(), serverlevel, blockpos, randomsource); ++ public void randomTick(ServerLevel level, BlockPos pos, RandomSource random) { ++ this.getBlock().randomTick(this.asState(), level, pos, random); + } + +- public void entityInside(Level level, BlockPos blockpos, Entity entity) { +- this.getBlock().entityInside(this.asState(), level, blockpos, entity); ++ public void entityInside(Level level, BlockPos pos, Entity entity) { ++ this.getBlock().entityInside(this.asState(), level, pos, entity); + } + +- public void spawnAfterBreak(ServerLevel serverlevel, BlockPos blockpos, ItemStack itemstack, boolean flag) { +- this.getBlock().spawnAfterBreak(this.asState(), serverlevel, blockpos, itemstack, flag); ++ public void spawnAfterBreak(ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ this.getBlock().spawnAfterBreak(this.asState(), level, pos, stack, dropExperience); + } + +- public List getDrops(LootParams.Builder lootparams_builder) { +- return this.getBlock().getDrops(this.asState(), lootparams_builder); ++ public List getDrops(LootParams.Builder lootParams) { ++ return this.getBlock().getDrops(this.asState(), lootParams); + } + +- public InteractionResult use(Level level, Player player, InteractionHand interactionhand, BlockHitResult blockhitresult) { +- return this.getBlock().use(this.asState(), level, blockhitresult.getBlockPos(), player, interactionhand, blockhitresult); ++ public InteractionResult use(Level level, Player player, EnumHand hand, BlockHitResult result) { ++ return this.getBlock().use(this.asState(), level, result.getBlockPos(), player, hand, result); + } + +- public void attack(Level level, BlockPos blockpos, Player player) { +- this.getBlock().attack(this.asState(), level, blockpos, player); ++ public void attack(Level level, BlockPos pos, Player player) { ++ this.getBlock().attack(this.asState(), level, pos, player); + } + +- public boolean isSuffocating(BlockGetter blockgetter, BlockPos blockpos) { +- return this.isSuffocating.test(this.asState(), blockgetter, blockpos); ++ public boolean isSuffocating(BlockGetter level, BlockPos pos) { ++ return this.isSuffocating.test(this.asState(), level, pos); + } + +- public boolean isViewBlocking(BlockGetter blockgetter, BlockPos blockpos) { +- return this.isViewBlocking.test(this.asState(), blockgetter, blockpos); ++ public boolean isViewBlocking(BlockGetter level, BlockPos pos) { ++ return this.isViewBlocking.test(this.asState(), level, pos); + } + +- public BlockState updateShape(Direction direction, BlockState blockstate, LevelAccessor levelaccessor, BlockPos blockpos, BlockPos blockpos1) { +- return this.getBlock().updateShape(this.asState(), direction, blockstate, levelaccessor, blockpos, blockpos1); ++ public IBlockData updateShape(Direction direction, IBlockData neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { ++ return this.getBlock().updateShape(this.asState(), direction, neighborState, level, pos, neighborPos); + } + +- public boolean isPathfindable(BlockGetter blockgetter, BlockPos blockpos, PathComputationType pathcomputationtype) { +- return this.getBlock().isPathfindable(this.asState(), blockgetter, blockpos, pathcomputationtype); ++ public boolean isPathfindable(BlockGetter level, BlockPos pos, PathMode type) { ++ return this.getBlock().isPathfindable(this.asState(), level, pos, type); + } + +- public boolean canBeReplaced(BlockPlaceContext blockplacecontext) { +- return this.getBlock().canBeReplaced(this.asState(), blockplacecontext); ++ public boolean canBeReplaced(BlockPlaceContext useContext) { ++ return this.getBlock().canBeReplaced(this.asState(), useContext); + } + + public boolean canBeReplaced(Fluid fluid) { +@@ -1198,29 +1199,29 @@ + return this.replaceable; + } + +- public boolean canSurvive(LevelReader levelreader, BlockPos blockpos) { +- return this.getBlock().canSurvive(this.asState(), levelreader, blockpos); ++ public boolean canSurvive(LevelReader level, BlockPos pos) { ++ return this.getBlock().canSurvive(this.asState(), level, pos); + } + +- public boolean hasPostProcess(BlockGetter blockgetter, BlockPos blockpos) { +- return this.hasPostProcess.test(this.asState(), blockgetter, blockpos); ++ public boolean hasPostProcess(BlockGetter level, BlockPos pos) { ++ return this.hasPostProcess.test(this.asState(), level, pos); + } + + @Nullable +- public MenuProvider getMenuProvider(Level level, BlockPos blockpos) { +- return this.getBlock().getMenuProvider(this.asState(), level, blockpos); ++ public ITileInventory getMenuProvider(Level level, BlockPos pos) { ++ return this.getBlock().getMenuProvider(this.asState(), level, pos); + } + +- public boolean is(TagKey tagkey) { +- return this.getBlock().builtInRegistryHolder().is(tagkey); ++ public boolean is(TagKey tag) { ++ return this.getBlock().builtInRegistryHolder().is(tag); + } + +- public boolean is(TagKey tagkey, Predicate predicate) { +- return this.is(tagkey) && predicate.test(this); ++ public boolean is(TagKey tag, Predicate predicate) { ++ return this.is(tag) && predicate.test(this); + } + +- public boolean is(HolderSet holderset) { +- return holderset.contains(this.getBlock().builtInRegistryHolder()); ++ public boolean is(HolderSet holder) { ++ return holder.contains(this.getBlock().builtInRegistryHolder()); + } + + public boolean is(Holder holder) { +@@ -1236,8 +1237,8 @@ + } + + @Nullable +- public BlockEntityTicker getTicker(Level level, BlockEntityType blockentitytype) { +- return this.getBlock() instanceof EntityBlock ? ((EntityBlock) this.getBlock()).getTicker(level, this.asState(), blockentitytype) : null; ++ public BlockEntityTicker getTicker(Level level, BlockEntityType blockEntityType) { ++ return this.getBlock() instanceof EntityBlock ? ((EntityBlock) this.getBlock()).getTicker(level, this.asState(), blockEntityType) : null; + } + + public boolean is(Block block) { +@@ -1256,31 +1257,31 @@ + return this.isRandomlyTicking; + } + +- public long getSeed(BlockPos blockpos) { +- return this.getBlock().getSeed(this.asState(), blockpos); ++ public long getSeed(BlockPos pos) { ++ return this.getBlock().getSeed(this.asState(), pos); + } + + public SoundType getSoundType() { + return this.getBlock().getSoundType(this.asState()); + } + +- public void onProjectileHit(Level level, BlockState blockstate, BlockHitResult blockhitresult, Projectile projectile) { +- this.getBlock().onProjectileHit(level, blockstate, blockhitresult, projectile); ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { ++ this.getBlock().onProjectileHit(level, state, hit, projectile); + } + +- public boolean isFaceSturdy(BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- return this.isFaceSturdy(blockgetter, blockpos, direction, SupportType.FULL); ++ public boolean isFaceSturdy(BlockGetter level, BlockPos pos, Direction direction) { ++ return this.isFaceSturdy(level, pos, direction, SupportType.FULL); + } + +- public boolean isFaceSturdy(BlockGetter blockgetter, BlockPos blockpos, Direction direction, SupportType supporttype) { +- return this.cache != null ? this.cache.isFaceSturdy(direction, supporttype) : supporttype.isSupporting(this.asState(), blockgetter, blockpos, direction); ++ public boolean isFaceSturdy(BlockGetter level, BlockPos pos, Direction face, SupportType supportType) { ++ return this.cache != null ? this.cache.isFaceSturdy(face, supportType) : supportType.isSupporting(this.asState(), level, pos, face); + } + +- public boolean isCollisionShapeFullBlock(BlockGetter blockgetter, BlockPos blockpos) { +- return this.cache != null ? this.cache.isCollisionShapeFullBlock : this.getBlock().isCollisionShapeFullBlock(this.asState(), blockgetter, blockpos); ++ public boolean isCollisionShapeFullBlock(BlockGetter level, BlockPos pos) { ++ return this.cache != null ? this.cache.isCollisionShapeFullBlock : this.getBlock().isCollisionShapeFullBlock(this.asState(), level, pos); + } + +- protected abstract BlockState asState(); ++ protected abstract IBlockData asState(); + + public boolean requiresCorrectToolForDrops() { + return this.requiresCorrectToolForDrops; +@@ -1308,71 +1309,71 @@ + private final boolean[] faceSturdy; + protected final boolean isCollisionShapeFullBlock; + +- Cache(BlockState blockstate) { +- Block block = blockstate.getBlock(); ++ Cache(IBlockData iblockdata) { ++ Block block = iblockdata.getBlock(); + +- this.solidRender = blockstate.isSolidRender(EmptyBlockGetter.INSTANCE, BlockPos.ZERO); +- this.propagatesSkylightDown = block.propagatesSkylightDown(blockstate, EmptyBlockGetter.INSTANCE, BlockPos.ZERO); +- this.lightBlock = block.getLightBlock(blockstate, EmptyBlockGetter.INSTANCE, BlockPos.ZERO); ++ this.solidRender = iblockdata.isSolidRender(EmptyBlockGetter.INSTANCE, BlockPos.ZERO); ++ this.propagatesSkylightDown = block.propagatesSkylightDown(iblockdata, EmptyBlockGetter.INSTANCE, BlockPos.ZERO); ++ this.lightBlock = block.getLightBlock(iblockdata, EmptyBlockGetter.INSTANCE, BlockPos.ZERO); + int i; + +- if (!blockstate.canOcclude()) { ++ if (!iblockdata.canOcclude()) { + this.occlusionShapes = null; + } else { + this.occlusionShapes = new VoxelShape[BlockBehaviour.BlockStateBase.Cache.DIRECTIONS.length]; +- VoxelShape voxelshape = block.getOcclusionShape(blockstate, EmptyBlockGetter.INSTANCE, BlockPos.ZERO); +- Direction[] adirection = BlockBehaviour.BlockStateBase.Cache.DIRECTIONS; ++ VoxelShape voxelshape = block.getOcclusionShape(iblockdata, EmptyBlockGetter.INSTANCE, BlockPos.ZERO); ++ Direction[] aenumdirection = BlockBehaviour.BlockStateBase.Cache.DIRECTIONS; + +- i = adirection.length; ++ i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; ++ Direction enumdirection = aenumdirection[j]; + +- this.occlusionShapes[direction.ordinal()] = Shapes.getFaceShape(voxelshape, direction); ++ this.occlusionShapes[enumdirection.ordinal()] = Shapes.getFaceShape(voxelshape, enumdirection); + } + } + +- this.collisionShape = block.getCollisionShape(blockstate, EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()); +- if (!this.collisionShape.isEmpty() && blockstate.hasOffsetFunction()) { ++ this.collisionShape = block.getCollisionShape(iblockdata, EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()); ++ if (!this.collisionShape.isEmpty() && iblockdata.hasOffsetFunction()) { + throw new IllegalStateException(String.format(Locale.ROOT, "%s has a collision shape and an offset type, but is not marked as dynamicShape in its properties.", BuiltInRegistries.BLOCK.getKey(block))); + } else { +- this.largeCollisionShape = Arrays.stream(Direction.Axis.values()).anyMatch((direction_axis) -> { +- return this.collisionShape.min(direction_axis) < 0.0D || this.collisionShape.max(direction_axis) > 1.0D; ++ this.largeCollisionShape = Arrays.stream(Direction.Axis.values()).anyMatch((enumdirection_enumaxis) -> { ++ return this.collisionShape.min(enumdirection_enumaxis) < 0.0D || this.collisionShape.max(enumdirection_enumaxis) > 1.0D; + }); + this.faceSturdy = new boolean[BlockBehaviour.BlockStateBase.Cache.DIRECTIONS.length * BlockBehaviour.BlockStateBase.Cache.SUPPORT_TYPE_COUNT]; +- Direction[] adirection1 = BlockBehaviour.BlockStateBase.Cache.DIRECTIONS; +- int k = adirection1.length; ++ Direction[] aenumdirection1 = BlockBehaviour.BlockStateBase.Cache.DIRECTIONS; ++ int k = aenumdirection1.length; + + for (i = 0; i < k; ++i) { +- Direction direction1 = adirection1[i]; +- SupportType[] asupporttype = SupportType.values(); +- int l = asupporttype.length; ++ Direction enumdirection1 = aenumdirection1[i]; ++ SupportType[] aenumblocksupport = SupportType.values(); ++ int l = aenumblocksupport.length; + + for (int i1 = 0; i1 < l; ++i1) { +- SupportType supporttype = asupporttype[i1]; ++ SupportType enumblocksupport = aenumblocksupport[i1]; + +- this.faceSturdy[getFaceSupportIndex(direction1, supporttype)] = supporttype.isSupporting(blockstate, EmptyBlockGetter.INSTANCE, BlockPos.ZERO, direction1); ++ this.faceSturdy[getFaceSupportIndex(enumdirection1, enumblocksupport)] = enumblocksupport.isSupporting(iblockdata, EmptyBlockGetter.INSTANCE, BlockPos.ZERO, enumdirection1); + } + } + +- this.isCollisionShapeFullBlock = Block.isShapeFullBlock(blockstate.getCollisionShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)); ++ this.isCollisionShapeFullBlock = Block.isShapeFullBlock(iblockdata.getCollisionShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)); + } + } + +- public boolean isFaceSturdy(Direction direction, SupportType supporttype) { +- return this.faceSturdy[getFaceSupportIndex(direction, supporttype)]; ++ public boolean isFaceSturdy(Direction enumdirection, SupportType enumblocksupport) { ++ return this.faceSturdy[getFaceSupportIndex(enumdirection, enumblocksupport)]; + } + +- private static int getFaceSupportIndex(Direction direction, SupportType supporttype) { +- return direction.ordinal() * BlockBehaviour.BlockStateBase.Cache.SUPPORT_TYPE_COUNT + supporttype.ordinal(); ++ private static int getFaceSupportIndex(Direction enumdirection, SupportType enumblocksupport) { ++ return enumdirection.ordinal() * BlockBehaviour.BlockStateBase.Cache.SUPPORT_TYPE_COUNT + enumblocksupport.ordinal(); + } + } + } + +- public static enum OffsetType { ++ public static enum EnumRandomOffset { + + NONE, XZ, XYZ; + +- private OffsetType() {} ++ private EnumRandomOffset() {} + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/border/WorldBorder.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/border/WorldBorder.java.patch new file mode 100644 index 0000000000..9ac2001a84 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/border/WorldBorder.java.patch @@ -0,0 +1,544 @@ +--- a/net/minecraft/world/level/border/WorldBorder.java ++++ b/net/minecraft/world/level/border/WorldBorder.java +@@ -27,33 +27,34 @@ + private double centerX; + private double centerZ; + int absoluteMaxSize = 29999984; +- private WorldBorder.BorderExtent extent = new WorldBorder.StaticBorderExtent(5.9999968E7D); ++ private WorldBorder.a extent = new WorldBorder.StaticBorderExtent(5.9999968E7D); + public static final WorldBorder.Settings DEFAULT_SETTINGS = new WorldBorder.Settings(0.0D, 0.0D, 0.2D, 5.0D, 5, 15, 5.9999968E7D, 0L, 0.0D); ++ public net.minecraft.server.level.ServerLevel world; // CraftBukkit + + public WorldBorder() {} + +- public boolean isWithinBounds(BlockPos blockpos) { +- return (double) (blockpos.getX() + 1) > this.getMinX() && (double) blockpos.getX() < this.getMaxX() && (double) (blockpos.getZ() + 1) > this.getMinZ() && (double) blockpos.getZ() < this.getMaxZ(); ++ public boolean isWithinBounds(BlockPos pos) { ++ return (double) (pos.getX() + 1) > this.getMinX() && (double) pos.getX() < this.getMaxX() && (double) (pos.getZ() + 1) > this.getMinZ() && (double) pos.getZ() < this.getMaxZ(); + } + +- public boolean isWithinBounds(ChunkPos chunkpos) { +- return (double) chunkpos.getMaxBlockX() > this.getMinX() && (double) chunkpos.getMinBlockX() < this.getMaxX() && (double) chunkpos.getMaxBlockZ() > this.getMinZ() && (double) chunkpos.getMinBlockZ() < this.getMaxZ(); ++ public boolean isWithinBounds(ChunkPos chunkPos) { ++ return (double) chunkPos.getMaxBlockX() > this.getMinX() && (double) chunkPos.getMinBlockX() < this.getMaxX() && (double) chunkPos.getMaxBlockZ() > this.getMinZ() && (double) chunkPos.getMinBlockZ() < this.getMaxZ(); + } + +- public boolean isWithinBounds(double d0, double d1) { +- return d0 > this.getMinX() && d0 < this.getMaxX() && d1 > this.getMinZ() && d1 < this.getMaxZ(); ++ public boolean isWithinBounds(double x, double d1) { ++ return x > this.getMinX() && x < this.getMaxX() && d1 > this.getMinZ() && d1 < this.getMaxZ(); + } + +- public boolean isWithinBounds(double d0, double d1, double d2) { +- return d0 > this.getMinX() - d2 && d0 < this.getMaxX() + d2 && d1 > this.getMinZ() - d2 && d1 < this.getMaxZ() + d2; ++ public boolean isWithinBounds(double x, double d1, double z) { ++ return x > this.getMinX() - z && x < this.getMaxX() + z && d1 > this.getMinZ() - z && d1 < this.getMaxZ() + z; + } + +- public boolean isWithinBounds(AABB aabb) { +- return aabb.maxX > this.getMinX() && aabb.minX < this.getMaxX() && aabb.maxZ > this.getMinZ() && aabb.minZ < this.getMaxZ(); ++ public boolean isWithinBounds(AABB box) { ++ return box.maxX > this.getMinX() && box.minX < this.getMaxX() && box.maxZ > this.getMinZ() && box.minZ < this.getMaxZ(); + } + +- public BlockPos clampToBounds(double d0, double d1, double d2) { +- return BlockPos.containing(Mth.clamp(d0, this.getMinX(), this.getMaxX()), d1, Mth.clamp(d2, this.getMinZ(), this.getMaxZ())); ++ public BlockPos clampToBounds(double x, double d1, double y) { ++ return BlockPos.containing(Mth.clamp(x, this.getMinX(), this.getMaxX()), d1, Mth.clamp(y, this.getMinZ(), this.getMaxZ())); + } + + public double getDistanceToBorder(Entity entity) { +@@ -64,19 +65,19 @@ + return this.extent.getCollisionShape(); + } + +- public double getDistanceToBorder(double d0, double d1) { ++ public double getDistanceToBorder(double x, double d1) { + double d2 = d1 - this.getMinZ(); + double d3 = this.getMaxZ() - d1; +- double d4 = d0 - this.getMinX(); +- double d5 = this.getMaxX() - d0; ++ double d4 = x - this.getMinX(); ++ double d5 = this.getMaxX() - x; + double d6 = Math.min(d4, d5); + + d6 = Math.min(d6, d2); + return Math.min(d6, d3); + } + +- public boolean isInsideCloseToBorder(Entity entity, AABB aabb) { +- double d0 = Math.max(Mth.absMax(aabb.getXsize(), aabb.getZsize()), 1.0D); ++ public boolean isInsideCloseToBorder(Entity entity, AABB bounds) { ++ double d0 = Math.max(Mth.absMax(bounds.getXsize(), bounds.getZsize()), 1.0D); + + return this.getDistanceToBorder(entity) < d0 * 2.0D && this.isWithinBounds(entity.getX(), entity.getZ(), d0); + } +@@ -109,16 +110,16 @@ + return this.centerZ; + } + +- public void setCenter(double d0, double d1) { +- this.centerX = d0; ++ public void setCenter(double x, double d1) { ++ this.centerX = x; + this.centerZ = d1; + this.extent.onCenterChange(); + Iterator iterator = this.getListeners().iterator(); + + while (iterator.hasNext()) { +- BorderChangeListener borderchangelistener = (BorderChangeListener) iterator.next(); ++ BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); + +- borderchangelistener.onBorderCenterSet(this, d0, d1); ++ iworldborderlistener.onBorderCenterSet(this, x, d1); + } + + } +@@ -135,26 +136,26 @@ + return this.extent.getLerpTarget(); + } + +- public void setSize(double d0) { +- this.extent = new WorldBorder.StaticBorderExtent(d0); ++ public void setSize(double size) { ++ this.extent = new WorldBorder.StaticBorderExtent(size); + Iterator iterator = this.getListeners().iterator(); + + while (iterator.hasNext()) { +- BorderChangeListener borderchangelistener = (BorderChangeListener) iterator.next(); ++ BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); + +- borderchangelistener.onBorderSizeSet(this, d0); ++ iworldborderlistener.onBorderSizeSet(this, size); + } + + } + +- public void lerpSizeBetween(double d0, double d1, long i) { +- this.extent = (WorldBorder.BorderExtent) (d0 == d1 ? new WorldBorder.StaticBorderExtent(d1) : new WorldBorder.MovingBorderExtent(d0, d1, i)); ++ public void lerpSizeBetween(double oldSize, double d1, long newSize) { ++ this.extent = (WorldBorder.a) (oldSize == d1 ? new WorldBorder.StaticBorderExtent(d1) : new WorldBorder.MovingBorderExtent(oldSize, d1, newSize)); + Iterator iterator = this.getListeners().iterator(); + + while (iterator.hasNext()) { +- BorderChangeListener borderchangelistener = (BorderChangeListener) iterator.next(); ++ BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); + +- borderchangelistener.onBorderSizeLerping(this, d0, d1, i); ++ iworldborderlistener.onBorderSizeLerping(this, oldSize, d1, newSize); + } + + } +@@ -163,16 +164,17 @@ + return Lists.newArrayList(this.listeners); + } + +- public void addListener(BorderChangeListener borderchangelistener) { +- this.listeners.add(borderchangelistener); ++ public void addListener(BorderChangeListener listener) { ++ if (listeners.contains(listener)) return; // CraftBukkit ++ this.listeners.add(listener); + } + +- public void removeListener(BorderChangeListener borderchangelistener) { +- this.listeners.remove(borderchangelistener); ++ public void removeListener(BorderChangeListener listener) { ++ this.listeners.remove(listener); + } + +- public void setAbsoluteMaxSize(int i) { +- this.absoluteMaxSize = i; ++ public void setAbsoluteMaxSize(int size) { ++ this.absoluteMaxSize = size; + this.extent.onAbsoluteMaxSizeChange(); + } + +@@ -184,14 +186,14 @@ + return this.damageSafeZone; + } + +- public void setDamageSafeZone(double d0) { +- this.damageSafeZone = d0; ++ public void setDamageSafeZone(double damageSafeZone) { ++ this.damageSafeZone = damageSafeZone; + Iterator iterator = this.getListeners().iterator(); + + while (iterator.hasNext()) { +- BorderChangeListener borderchangelistener = (BorderChangeListener) iterator.next(); ++ BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); + +- borderchangelistener.onBorderSetDamageSafeZOne(this, d0); ++ iworldborderlistener.onBorderSetDamageSafeZOne(this, damageSafeZone); + } + + } +@@ -200,14 +202,14 @@ + return this.damagePerBlock; + } + +- public void setDamagePerBlock(double d0) { +- this.damagePerBlock = d0; ++ public void setDamagePerBlock(double damagePerBlock) { ++ this.damagePerBlock = damagePerBlock; + Iterator iterator = this.getListeners().iterator(); + + while (iterator.hasNext()) { +- BorderChangeListener borderchangelistener = (BorderChangeListener) iterator.next(); ++ BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); + +- borderchangelistener.onBorderSetDamagePerBlock(this, d0); ++ iworldborderlistener.onBorderSetDamagePerBlock(this, damagePerBlock); + } + + } +@@ -220,14 +222,14 @@ + return this.warningTime; + } + +- public void setWarningTime(int i) { +- this.warningTime = i; ++ public void setWarningTime(int warningTime) { ++ this.warningTime = warningTime; + Iterator iterator = this.getListeners().iterator(); + + while (iterator.hasNext()) { +- BorderChangeListener borderchangelistener = (BorderChangeListener) iterator.next(); ++ BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); + +- borderchangelistener.onBorderSetWarningTime(this, i); ++ iworldborderlistener.onBorderSetWarningTime(this, warningTime); + } + + } +@@ -236,14 +238,14 @@ + return this.warningBlocks; + } + +- public void setWarningBlocks(int i) { +- this.warningBlocks = i; ++ public void setWarningBlocks(int warningDistance) { ++ this.warningBlocks = warningDistance; + Iterator iterator = this.getListeners().iterator(); + + while (iterator.hasNext()) { +- BorderChangeListener borderchangelistener = (BorderChangeListener) iterator.next(); ++ BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); + +- borderchangelistener.onBorderSetWarningBlocks(this, i); ++ iworldborderlistener.onBorderSetWarningBlocks(this, warningDistance); + } + + } +@@ -256,21 +258,21 @@ + return new WorldBorder.Settings(this); + } + +- public void applySettings(WorldBorder.Settings worldborder_settings) { +- this.setCenter(worldborder_settings.getCenterX(), worldborder_settings.getCenterZ()); +- this.setDamagePerBlock(worldborder_settings.getDamagePerBlock()); +- this.setDamageSafeZone(worldborder_settings.getSafeZone()); +- this.setWarningBlocks(worldborder_settings.getWarningBlocks()); +- this.setWarningTime(worldborder_settings.getWarningTime()); +- if (worldborder_settings.getSizeLerpTime() > 0L) { +- this.lerpSizeBetween(worldborder_settings.getSize(), worldborder_settings.getSizeLerpTarget(), worldborder_settings.getSizeLerpTime()); ++ public void applySettings(WorldBorder.Settings serializer) { ++ this.setCenter(serializer.getCenterX(), serializer.getCenterZ()); ++ this.setDamagePerBlock(serializer.getDamagePerBlock()); ++ this.setDamageSafeZone(serializer.getSafeZone()); ++ this.setWarningBlocks(serializer.getWarningBlocks()); ++ this.setWarningTime(serializer.getWarningTime()); ++ if (serializer.getSizeLerpTime() > 0L) { ++ this.lerpSizeBetween(serializer.getSize(), serializer.getSizeLerpTarget(), serializer.getSizeLerpTime()); + } else { +- this.setSize(worldborder_settings.getSize()); ++ this.setSize(serializer.getSize()); + } + + } + +- private class StaticBorderExtent implements WorldBorder.BorderExtent { ++ private class StaticBorderExtent implements WorldBorder.a { + + private final double size; + private double minX; +@@ -285,55 +287,46 @@ + } + + @Override +- @Override + public double getMinX() { + return this.minX; + } + + @Override +- @Override + public double getMaxX() { + return this.maxX; + } + + @Override +- @Override + public double getMinZ() { + return this.minZ; + } + + @Override +- @Override + public double getMaxZ() { + return this.maxZ; + } + + @Override +- @Override + public double getSize() { + return this.size; + } + + @Override +- @Override + public BorderStatus getStatus() { + return BorderStatus.STATIONARY; + } + + @Override +- @Override + public double getLerpSpeed() { + return 0.0D; + } + + @Override +- @Override + public long getLerpRemainingTime() { + return 0L; + } + + @Override +- @Override + public double getLerpTarget() { + return this.size; + } +@@ -347,31 +340,27 @@ + } + + @Override +- @Override + public void onAbsoluteMaxSizeChange() { + this.updateBox(); + } + + @Override +- @Override + public void onCenterChange() { + this.updateBox(); + } + + @Override +- @Override +- public WorldBorder.BorderExtent update() { ++ public WorldBorder.a update() { + return this; + } + + @Override +- @Override + public VoxelShape getCollisionShape() { + return this.shape; + } + } + +- private interface BorderExtent { ++ private interface a { + + double getMinX(); + +@@ -395,12 +384,12 @@ + + void onCenterChange(); + +- WorldBorder.BorderExtent update(); ++ WorldBorder.a update(); + + VoxelShape getCollisionShape(); + } + +- private class MovingBorderExtent implements WorldBorder.BorderExtent { ++ private class MovingBorderExtent implements WorldBorder.a { + + private final double from; + private final double to; +@@ -417,31 +406,26 @@ + } + + @Override +- @Override + public double getMinX() { + return Mth.clamp(WorldBorder.this.getCenterX() - this.getSize() / 2.0D, (double) (-WorldBorder.this.absoluteMaxSize), (double) WorldBorder.this.absoluteMaxSize); + } + + @Override +- @Override + public double getMinZ() { + return Mth.clamp(WorldBorder.this.getCenterZ() - this.getSize() / 2.0D, (double) (-WorldBorder.this.absoluteMaxSize), (double) WorldBorder.this.absoluteMaxSize); + } + + @Override +- @Override + public double getMaxX() { + return Mth.clamp(WorldBorder.this.getCenterX() + this.getSize() / 2.0D, (double) (-WorldBorder.this.absoluteMaxSize), (double) WorldBorder.this.absoluteMaxSize); + } + + @Override +- @Override + public double getMaxZ() { + return Mth.clamp(WorldBorder.this.getCenterZ() + this.getSize() / 2.0D, (double) (-WorldBorder.this.absoluteMaxSize), (double) WorldBorder.this.absoluteMaxSize); + } + + @Override +- @Override + public double getSize() { + double d0 = (double) (Util.getMillis() - this.lerpBegin) / this.lerpDuration; + +@@ -449,45 +433,37 @@ + } + + @Override +- @Override + public double getLerpSpeed() { + return Math.abs(this.from - this.to) / (double) (this.lerpEnd - this.lerpBegin); + } + + @Override +- @Override + public long getLerpRemainingTime() { + return this.lerpEnd - Util.getMillis(); + } + + @Override +- @Override + public double getLerpTarget() { + return this.to; + } + + @Override +- @Override + public BorderStatus getStatus() { + return this.to < this.from ? BorderStatus.SHRINKING : BorderStatus.GROWING; + } + + @Override +- @Override + public void onCenterChange() {} + + @Override +- @Override + public void onAbsoluteMaxSizeChange() {} + + @Override +- @Override +- public WorldBorder.BorderExtent update() { +- return (WorldBorder.BorderExtent) (this.getLerpRemainingTime() <= 0L ? WorldBorder.this.new StaticBorderExtent(this.to) : this); ++ public WorldBorder.a update() { ++ return (WorldBorder.a) (this.getLerpRemainingTime() <= 0L ? WorldBorder.this.new StaticBorderExtent(this.to) : this); + } + + @Override +- @Override + public VoxelShape getCollisionShape() { + return Shapes.join(Shapes.INFINITY, Shapes.box(Math.floor(this.getMinX()), Double.NEGATIVE_INFINITY, Math.floor(this.getMinZ()), Math.ceil(this.getMaxX()), Double.POSITIVE_INFINITY, Math.ceil(this.getMaxZ())), BooleanOp.ONLY_FIRST); + } +@@ -505,28 +481,28 @@ + private final long sizeLerpTime; + private final double sizeLerpTarget; + +- Settings(double d0, double d1, double d2, double d3, int i, int j, double d4, long k, double d5) { +- this.centerX = d0; ++ Settings(double centerX, double d1, double centerZ, double d3, int damagePerBlock, int j, double safeZone, long k, double warningBlocks) { ++ this.centerX = centerX; + this.centerZ = d1; +- this.damagePerBlock = d2; ++ this.damagePerBlock = centerZ; + this.safeZone = d3; +- this.warningBlocks = i; ++ this.warningBlocks = damagePerBlock; + this.warningTime = j; +- this.size = d4; ++ this.size = safeZone; + this.sizeLerpTime = k; +- this.sizeLerpTarget = d5; ++ this.sizeLerpTarget = warningBlocks; + } + +- Settings(WorldBorder worldborder) { +- this.centerX = worldborder.getCenterX(); +- this.centerZ = worldborder.getCenterZ(); +- this.damagePerBlock = worldborder.getDamagePerBlock(); +- this.safeZone = worldborder.getDamageSafeZone(); +- this.warningBlocks = worldborder.getWarningBlocks(); +- this.warningTime = worldborder.getWarningTime(); +- this.size = worldborder.getSize(); +- this.sizeLerpTime = worldborder.getLerpRemainingTime(); +- this.sizeLerpTarget = worldborder.getLerpTarget(); ++ Settings(WorldBorder border) { ++ this.centerX = border.getCenterX(); ++ this.centerZ = border.getCenterZ(); ++ this.damagePerBlock = border.getDamagePerBlock(); ++ this.safeZone = border.getDamageSafeZone(); ++ this.warningBlocks = border.getWarningBlocks(); ++ this.warningTime = border.getWarningTime(); ++ this.size = border.getSize(); ++ this.sizeLerpTime = border.getLerpRemainingTime(); ++ this.sizeLerpTarget = border.getLerpTarget(); + } + + public double getCenterX() { +@@ -565,30 +541,30 @@ + return this.sizeLerpTarget; + } + +- public static WorldBorder.Settings read(DynamicLike dynamiclike, WorldBorder.Settings worldborder_settings) { +- double d0 = Mth.clamp(dynamiclike.get("BorderCenterX").asDouble(worldborder_settings.centerX), -2.9999984E7D, 2.9999984E7D); +- double d1 = Mth.clamp(dynamiclike.get("BorderCenterZ").asDouble(worldborder_settings.centerZ), -2.9999984E7D, 2.9999984E7D); +- double d2 = dynamiclike.get("BorderSize").asDouble(worldborder_settings.size); +- long i = dynamiclike.get("BorderSizeLerpTime").asLong(worldborder_settings.sizeLerpTime); +- double d3 = dynamiclike.get("BorderSizeLerpTarget").asDouble(worldborder_settings.sizeLerpTarget); +- double d4 = dynamiclike.get("BorderSafeZone").asDouble(worldborder_settings.safeZone); +- double d5 = dynamiclike.get("BorderDamagePerBlock").asDouble(worldborder_settings.damagePerBlock); +- int j = dynamiclike.get("BorderWarningBlocks").asInt(worldborder_settings.warningBlocks); +- int k = dynamiclike.get("BorderWarningTime").asInt(worldborder_settings.warningTime); ++ public static WorldBorder.Settings read(DynamicLike dynamic, WorldBorder.Settings defaultValue) { ++ double d0 = Mth.clamp(dynamic.get("BorderCenterX").asDouble(defaultValue.centerX), -2.9999984E7D, 2.9999984E7D); ++ double d1 = Mth.clamp(dynamic.get("BorderCenterZ").asDouble(defaultValue.centerZ), -2.9999984E7D, 2.9999984E7D); ++ double d2 = dynamic.get("BorderSize").asDouble(defaultValue.size); ++ long i = dynamic.get("BorderSizeLerpTime").asLong(defaultValue.sizeLerpTime); ++ double d3 = dynamic.get("BorderSizeLerpTarget").asDouble(defaultValue.sizeLerpTarget); ++ double d4 = dynamic.get("BorderSafeZone").asDouble(defaultValue.safeZone); ++ double d5 = dynamic.get("BorderDamagePerBlock").asDouble(defaultValue.damagePerBlock); ++ int j = dynamic.get("BorderWarningBlocks").asInt(defaultValue.warningBlocks); ++ int k = dynamic.get("BorderWarningTime").asInt(defaultValue.warningTime); + + return new WorldBorder.Settings(d0, d1, d5, d4, j, k, d2, i, d3); + } + +- public void write(CompoundTag compoundtag) { +- compoundtag.putDouble("BorderCenterX", this.centerX); +- compoundtag.putDouble("BorderCenterZ", this.centerZ); +- compoundtag.putDouble("BorderSize", this.size); +- compoundtag.putLong("BorderSizeLerpTime", this.sizeLerpTime); +- compoundtag.putDouble("BorderSafeZone", this.safeZone); +- compoundtag.putDouble("BorderDamagePerBlock", this.damagePerBlock); +- compoundtag.putDouble("BorderSizeLerpTarget", this.sizeLerpTarget); +- compoundtag.putDouble("BorderWarningBlocks", (double) this.warningBlocks); +- compoundtag.putDouble("BorderWarningTime", (double) this.warningTime); ++ public void write(CompoundTag nbt) { ++ nbt.putDouble("BorderCenterX", this.centerX); ++ nbt.putDouble("BorderCenterZ", this.centerZ); ++ nbt.putDouble("BorderSize", this.size); ++ nbt.putLong("BorderSizeLerpTime", this.sizeLerpTime); ++ nbt.putDouble("BorderSafeZone", this.safeZone); ++ nbt.putDouble("BorderDamagePerBlock", this.damagePerBlock); ++ nbt.putDouble("BorderSizeLerpTarget", this.sizeLerpTarget); ++ nbt.putDouble("BorderWarningBlocks", (double) this.warningBlocks); ++ nbt.putDouble("BorderWarningTime", (double) this.warningTime); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/ChunkAccess.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/ChunkAccess.java.patch new file mode 100644 index 0000000000..b580a0cbda --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/ChunkAccess.java.patch @@ -0,0 +1,513 @@ +--- a/net/minecraft/world/level/chunk/ChunkAccess.java ++++ b/net/minecraft/world/level/chunk/ChunkAccess.java +@@ -40,7 +40,7 @@ + import net.minecraft.world.level.biome.Climate; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEventListenerRegistry; + import net.minecraft.world.level.levelgen.BelowZeroRetrogen; + import net.minecraft.world.level.levelgen.Heightmap; +@@ -73,62 +73,71 @@ + protected final UpgradeData upgradeData; + @Nullable + protected BlendingData blendingData; +- protected final Map heightmaps = Maps.newEnumMap(Heightmap.Types.class); ++ public final Map heightmaps = Maps.newEnumMap(Heightmap.Types.class); + protected ChunkSkyLightSources skyLightSources; + private final Map structureStarts = Maps.newHashMap(); + private final Map structuresRefences = Maps.newHashMap(); + protected final Map pendingBlockEntities = Maps.newHashMap(); +- protected final Map blockEntities = Maps.newHashMap(); ++ public final Map blockEntities = Maps.newHashMap(); + protected final LevelHeightAccessor levelHeightAccessor; + protected final LevelChunkSection[] sections; + +- public ChunkAccess(ChunkPos chunkpos, UpgradeData upgradedata, LevelHeightAccessor levelheightaccessor, Registry registry, long i, @Nullable LevelChunkSection[] alevelchunksection, @Nullable BlendingData blendingdata) { +- this.chunkPos = chunkpos; +- this.upgradeData = upgradedata; +- this.levelHeightAccessor = levelheightaccessor; +- this.sections = new LevelChunkSection[levelheightaccessor.getSectionsCount()]; +- this.inhabitedTime = i; +- this.postProcessing = new ShortList[levelheightaccessor.getSectionsCount()]; +- this.blendingData = blendingdata; +- this.skyLightSources = new ChunkSkyLightSources(levelheightaccessor); +- if (alevelchunksection != null) { +- if (this.sections.length == alevelchunksection.length) { +- System.arraycopy(alevelchunksection, 0, this.sections, 0, this.sections.length); ++ // CraftBukkit start - SPIGOT-6814: move to IChunkAccess to account for 1.17 to 1.18 chunk upgrading. ++ private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry(); ++ public org.bukkit.craftbukkit.persistence.DirtyCraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.DirtyCraftPersistentDataContainer(DATA_TYPE_REGISTRY); ++ // CraftBukkit end ++ ++ public ChunkAccess(ChunkPos chunkPos, UpgradeData upgradeData, LevelHeightAccessor levelHeightAccessor, Registry biomeRegistry, long inhabitedTime, @Nullable LevelChunkSection[] achunksection, @Nullable BlendingData sections) { ++ this.chunkPos = chunkPos; ++ this.upgradeData = upgradeData; ++ this.levelHeightAccessor = levelHeightAccessor; ++ this.sections = new LevelChunkSection[levelHeightAccessor.getSectionsCount()]; ++ this.inhabitedTime = inhabitedTime; ++ this.postProcessing = new ShortList[levelHeightAccessor.getSectionsCount()]; ++ this.blendingData = sections; ++ this.skyLightSources = new ChunkSkyLightSources(levelHeightAccessor); ++ if (achunksection != null) { ++ if (this.sections.length == achunksection.length) { ++ System.arraycopy(achunksection, 0, this.sections, 0, this.sections.length); + } else { +- ChunkAccess.LOGGER.warn("Could not set level chunk sections, array length is {} instead of {}", alevelchunksection.length, this.sections.length); ++ ChunkAccess.LOGGER.warn("Could not set level chunk sections, array length is {} instead of {}", achunksection.length, this.sections.length); + } + } + +- replaceMissingSections(registry, this.sections); ++ replaceMissingSections(biomeRegistry, this.sections); ++ // CraftBukkit start ++ this.biomeRegistry = biomeRegistry; + } ++ public final Registry biomeRegistry; ++ // CraftBukkit end + +- private static void replaceMissingSections(Registry registry, LevelChunkSection[] alevelchunksection) { +- for (int i = 0; i < alevelchunksection.length; ++i) { +- if (alevelchunksection[i] == null) { +- alevelchunksection[i] = new LevelChunkSection(registry); ++ private static void replaceMissingSections(Registry biomeRegistry, LevelChunkSection[] sections) { ++ for (int i = 0; i < sections.length; ++i) { ++ if (sections[i] == null) { ++ sections[i] = new LevelChunkSection(biomeRegistry); + } + } + + } + +- public GameEventListenerRegistry getListenerRegistry(int i) { ++ public GameEventListenerRegistry getListenerRegistry(int sectionY) { + return GameEventListenerRegistry.NOOP; + } + + @Nullable +- public abstract BlockState setBlockState(BlockPos pos, BlockState state, boolean isMoving); ++ public abstract IBlockData setBlockState(BlockPos pos, IBlockData state, boolean isMoving); + + public abstract void setBlockEntity(BlockEntity blockEntity); + + public abstract void addEntity(Entity entity); + + public int getHighestFilledSectionIndex() { +- LevelChunkSection[] alevelchunksection = this.getSections(); ++ LevelChunkSection[] achunksection = this.getSections(); + +- for (int i = alevelchunksection.length - 1; i >= 0; --i) { +- LevelChunkSection levelchunksection = alevelchunksection[i]; ++ for (int i = achunksection.length - 1; i >= 0; --i) { ++ LevelChunkSection chunksection = achunksection[i]; + +- if (!levelchunksection.hasOnlyAir()) { ++ if (!chunksection.hasOnlyAir()) { + return i; + } + } +@@ -155,41 +164,41 @@ + return this.sections; + } + +- public LevelChunkSection getSection(int i) { +- return this.getSections()[i]; ++ public LevelChunkSection getSection(int index) { ++ return this.getSections()[index]; + } + + public Collection> getHeightmaps() { + return Collections.unmodifiableSet(this.heightmaps.entrySet()); + } + +- public void setHeightmap(Heightmap.Types heightmap_types, long[] along) { +- this.getOrCreateHeightmapUnprimed(heightmap_types).setRawData(this, heightmap_types, along); ++ public void setHeightmap(Heightmap.Types type, long[] data) { ++ this.getOrCreateHeightmapUnprimed(type).setRawData(this, type, data); + } + +- public Heightmap getOrCreateHeightmapUnprimed(Heightmap.Types heightmap_types) { +- return (Heightmap) this.heightmaps.computeIfAbsent(heightmap_types, (heightmap_types1) -> { +- return new Heightmap(this, heightmap_types1); ++ public Heightmap getOrCreateHeightmapUnprimed(Heightmap.Types type) { ++ return (Heightmap) this.heightmaps.computeIfAbsent(type, (heightmap_type1) -> { ++ return new Heightmap(this, heightmap_type1); + }); + } + +- public boolean hasPrimedHeightmap(Heightmap.Types heightmap_types) { +- return this.heightmaps.get(heightmap_types) != null; ++ public boolean hasPrimedHeightmap(Heightmap.Types type) { ++ return this.heightmaps.get(type) != null; + } + +- public int getHeight(Heightmap.Types heightmap_types, int i, int j) { +- Heightmap heightmap = (Heightmap) this.heightmaps.get(heightmap_types); ++ public int getHeight(Heightmap.Types type, int x, int z) { ++ Heightmap heightmap = (Heightmap) this.heightmaps.get(type); + + if (heightmap == null) { + if (SharedConstants.IS_RUNNING_IN_IDE && this instanceof LevelChunk) { +- ChunkAccess.LOGGER.error("Unprimed heightmap: " + heightmap_types + " " + i + " " + j); ++ ChunkAccess.LOGGER.error("Unprimed heightmap: " + type + " " + x + " " + z); + } + +- Heightmap.primeHeightmaps(this, EnumSet.of(heightmap_types)); +- heightmap = (Heightmap) this.heightmaps.get(heightmap_types); ++ Heightmap.primeHeightmaps(this, EnumSet.of(type)); ++ heightmap = (Heightmap) this.heightmaps.get(type); + } + +- return heightmap.getFirstAvailable(i & 15, j & 15) - 1; ++ return heightmap.getFirstAvailable(x & 15, z & 15) - 1; + } + + public ChunkPos getPos() { +@@ -198,15 +207,13 @@ + + @Nullable + @Override +- @Override + public StructureStart getStartForStructure(Structure structure) { + return (StructureStart) this.structureStarts.get(structure); + } + + @Override +- @Override +- public void setStartForStructure(Structure structure, StructureStart structurestart) { +- this.structureStarts.put(structure, structurestart); ++ public void setStartForStructure(Structure structure, StructureStart structureStart) { ++ this.structureStarts.put(structure, structureStart); + this.unsaved = true; + } + +@@ -214,51 +221,47 @@ + return Collections.unmodifiableMap(this.structureStarts); + } + +- public void setAllStarts(Map map) { ++ public void setAllStarts(Map structureStarts) { + this.structureStarts.clear(); +- this.structureStarts.putAll(map); ++ this.structureStarts.putAll(structureStarts); + this.unsaved = true; + } + + @Override +- @Override + public LongSet getReferencesForStructure(Structure structure) { + return (LongSet) this.structuresRefences.getOrDefault(structure, ChunkAccess.EMPTY_REFERENCE_SET); + } + + @Override +- @Override +- public void addReferenceForStructure(Structure structure, long i) { ++ public void addReferenceForStructure(Structure structure, long reference) { + ((LongSet) this.structuresRefences.computeIfAbsent(structure, (structure1) -> { + return new LongOpenHashSet(); +- })).add(i); ++ })).add(reference); + this.unsaved = true; + } + + @Override +- @Override + public Map getAllReferences() { + return Collections.unmodifiableMap(this.structuresRefences); + } + + @Override +- @Override +- public void setAllReferences(Map map) { ++ public void setAllReferences(Map structureReferencesMap) { + this.structuresRefences.clear(); +- this.structuresRefences.putAll(map); ++ this.structuresRefences.putAll(structureReferencesMap); + this.unsaved = true; + } + +- public boolean isYSpaceEmpty(int i, int j) { +- if (i < this.getMinBuildHeight()) { +- i = this.getMinBuildHeight(); ++ public boolean isYSpaceEmpty(int startY, int endY) { ++ if (startY < this.getMinBuildHeight()) { ++ startY = this.getMinBuildHeight(); + } + +- if (j >= this.getMaxBuildHeight()) { +- j = this.getMaxBuildHeight() - 1; ++ if (endY >= this.getMaxBuildHeight()) { ++ endY = this.getMaxBuildHeight() - 1; + } + +- for (int k = i; k <= j; k += 16) { ++ for (int k = startY; k <= endY; k += 16) { + if (!this.getSection(this.getSectionIndex(k)).hasOnlyAir()) { + return false; + } +@@ -267,12 +270,13 @@ + return true; + } + +- public void setUnsaved(boolean flag) { +- this.unsaved = flag; ++ public void setUnsaved(boolean unsaved) { ++ this.unsaved = unsaved; ++ if (!unsaved) this.persistentDataContainer.dirty(false); // CraftBukkit - SPIGOT-6814: chunk was saved, pdc is no longer dirty + } + + public boolean isUnsaved() { +- return this.unsaved; ++ return this.unsaved || this.persistentDataContainer.dirty(); // CraftBukkit - SPIGOT-6814: chunk is unsaved if pdc was mutated + } + + public abstract ChunkStatus getStatus(); +@@ -292,54 +296,53 @@ + + public abstract void removeBlockEntity(BlockPos pos); + +- public void markPosForPostprocessing(BlockPos blockpos) { +- ChunkAccess.LOGGER.warn("Trying to mark a block for PostProcessing @ {}, but this operation is not supported.", blockpos); ++ public void markPosForPostprocessing(BlockPos pos) { ++ ChunkAccess.LOGGER.warn("Trying to mark a block for PostProcessing @ {}, but this operation is not supported.", pos); + } + + public ShortList[] getPostProcessing() { + return this.postProcessing; + } + +- public void addPackedPostProcess(short short0, int i) { +- getOrCreateOffsetList(this.getPostProcessing(), i).add(short0); ++ public void addPackedPostProcess(short packedPosition, int index) { ++ getOrCreateOffsetList(this.getPostProcessing(), index).add(packedPosition); + } + +- public void setBlockEntityNbt(CompoundTag compoundtag) { +- this.pendingBlockEntities.put(BlockEntity.getPosFromTag(compoundtag), compoundtag); ++ public void setBlockEntityNbt(CompoundTag tag) { ++ this.pendingBlockEntities.put(BlockEntity.getPosFromTag(tag), tag); + } + + @Nullable +- public CompoundTag getBlockEntityNbt(BlockPos blockpos) { +- return (CompoundTag) this.pendingBlockEntities.get(blockpos); ++ public CompoundTag getBlockEntityNbt(BlockPos pos) { ++ return (CompoundTag) this.pendingBlockEntities.get(pos); + } + + @Nullable + public abstract CompoundTag getBlockEntityNbtForSaving(BlockPos pos); + + @Override +- @Override +- public final void findBlockLightSources(BiConsumer biconsumer) { +- this.findBlocks((blockstate) -> { +- return blockstate.getLightEmission() != 0; +- }, biconsumer); ++ public final void findBlockLightSources(BiConsumer output) { ++ this.findBlocks((iblockdata) -> { ++ return iblockdata.getLightEmission() != 0; ++ }, output); + } + +- public void findBlocks(Predicate predicate, BiConsumer biconsumer) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ public void findBlocks(Predicate predicate, BiConsumer output) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + + for (int i = this.getMinSection(); i < this.getMaxSection(); ++i) { +- LevelChunkSection levelchunksection = this.getSection(this.getSectionIndexFromSectionY(i)); ++ LevelChunkSection chunksection = this.getSection(this.getSectionIndexFromSectionY(i)); + +- if (levelchunksection.maybeHas(predicate)) { +- BlockPos blockpos = SectionPos.of(this.chunkPos, i).origin(); ++ if (chunksection.maybeHas(predicate)) { ++ BlockPos blockposition = SectionPos.of(this.chunkPos, i).origin(); + + for (int j = 0; j < 16; ++j) { + for (int k = 0; k < 16; ++k) { + for (int l = 0; l < 16; ++l) { +- BlockState blockstate = levelchunksection.getBlockState(l, j, k); ++ IBlockData iblockdata = chunksection.getBlockState(l, j, k); + +- if (predicate.test(blockstate)) { +- biconsumer.accept(blockpos_mutableblockpos.setWithOffset(blockpos, l, j, k), blockstate); ++ if (predicate.test(iblockdata)) { ++ output.accept(blockposition_mutableblockposition.setWithOffset(blockposition, l, j, k), iblockdata); + } + } + } +@@ -353,7 +356,7 @@ + + public abstract TickContainerAccess getFluidTicks(); + +- public abstract ChunkAccess.TicksToSave getTicksForSerialization(); ++ public abstract ChunkAccess.a getTicksForSerialization(); + + public UpgradeData getUpgradeData() { + return this.upgradeData; +@@ -368,54 +371,52 @@ + return this.blendingData; + } + +- public void setBlendingData(BlendingData blendingdata) { +- this.blendingData = blendingdata; ++ public void setBlendingData(BlendingData blendingData) { ++ this.blendingData = blendingData; + } + + public long getInhabitedTime() { + return this.inhabitedTime; + } + +- public void incrementInhabitedTime(long i) { +- this.inhabitedTime += i; ++ public void incrementInhabitedTime(long amount) { ++ this.inhabitedTime += amount; + } + +- public void setInhabitedTime(long i) { +- this.inhabitedTime = i; ++ public void setInhabitedTime(long inhabitedTime) { ++ this.inhabitedTime = inhabitedTime; + } + +- public static ShortList getOrCreateOffsetList(ShortList[] ashortlist, int i) { +- if (ashortlist[i] == null) { +- ashortlist[i] = new ShortArrayList(); ++ public static ShortList getOrCreateOffsetList(ShortList[] packedPositions, int index) { ++ if (packedPositions[index] == null) { ++ packedPositions[index] = new ShortArrayList(); + } + +- return ashortlist[i]; ++ return packedPositions[index]; + } + + public boolean isLightCorrect() { + return this.isLightCorrect; + } + +- public void setLightCorrect(boolean flag) { +- this.isLightCorrect = flag; ++ public void setLightCorrect(boolean lightCorrect) { ++ this.isLightCorrect = lightCorrect; + this.setUnsaved(true); + } + + @Override +- @Override + public int getMinBuildHeight() { + return this.levelHeightAccessor.getMinBuildHeight(); + } + + @Override +- @Override + public int getHeight() { + return this.levelHeightAccessor.getHeight(); + } + +- public NoiseChunk getOrCreateNoiseChunk(Function function) { ++ public NoiseChunk getOrCreateNoiseChunk(Function noiseChunkCreator) { + if (this.noiseChunk == null) { +- this.noiseChunk = (NoiseChunk) function.apply(this); ++ this.noiseChunk = (NoiseChunk) noiseChunkCreator.apply(this); + } + + return this.noiseChunk; +@@ -423,46 +424,66 @@ + + /** @deprecated */ + @Deprecated +- public BiomeGenerationSettings carverBiome(Supplier supplier) { ++ public BiomeGenerationSettings carverBiome(Supplier caverBiomeSettingsSupplier) { + if (this.carverBiomeSettings == null) { +- this.carverBiomeSettings = (BiomeGenerationSettings) supplier.get(); ++ this.carverBiomeSettings = (BiomeGenerationSettings) caverBiomeSettingsSupplier.get(); + } + + return this.carverBiomeSettings; + } + + @Override +- @Override +- public Holder getNoiseBiome(int i, int j, int k) { ++ public Holder getNoiseBiome(int x, int y, int z) { + try { + int l = QuartPos.fromBlock(this.getMinBuildHeight()); + int i1 = l + QuartPos.fromBlock(this.getHeight()) - 1; +- int j1 = Mth.clamp(j, l, i1); ++ int j1 = Mth.clamp(y, l, i1); + int k1 = this.getSectionIndex(QuartPos.toBlock(j1)); + +- return this.sections[k1].getNoiseBiome(i & 3, j1 & 3, k & 3); ++ return this.sections[k1].getNoiseBiome(x & 3, j1 & 3, z & 3); + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting biome"); +- CrashReportCategory crashreportcategory = crashreport.addCategory("Biome being got"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Biome being got"); + +- crashreportcategory.setDetail("Location", () -> { ++ crashreportsystemdetails.setDetail("Location", () -> { ++ return CrashReportCategory.formatLocation(this, x, y, z); ++ }); ++ throw new ReportedException(crashreport); ++ } ++ } ++ ++ // CraftBukkit start ++ public void setBiome(int i, int j, int k, Holder biome) { ++ try { ++ int l = QuartPos.fromBlock(this.getMinBuildHeight()); ++ int i1 = l + QuartPos.fromBlock(this.getHeight()) - 1; ++ int j1 = Mth.clamp(j, l, i1); ++ int k1 = this.getSectionIndex(QuartPos.toBlock(j1)); ++ ++ this.sections[k1].setBiome(i & 3, j1 & 3, k & 3, biome); ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Setting biome"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Biome being set"); ++ ++ crashreportsystemdetails.setDetail("Location", () -> { + return CrashReportCategory.formatLocation(this, i, j, k); + }); + throw new ReportedException(crashreport); + } + } ++ // CraftBukkit end + +- public void fillBiomesFromNoise(BiomeResolver biomeresolver, Climate.Sampler climate_sampler) { +- ChunkPos chunkpos = this.getPos(); +- int i = QuartPos.fromBlock(chunkpos.getMinBlockX()); +- int j = QuartPos.fromBlock(chunkpos.getMinBlockZ()); ++ public void fillBiomesFromNoise(BiomeResolver resolver, Climate.Sampler sampler) { ++ ChunkPos chunkcoordintpair = this.getPos(); ++ int i = QuartPos.fromBlock(chunkcoordintpair.getMinBlockX()); ++ int j = QuartPos.fromBlock(chunkcoordintpair.getMinBlockZ()); + LevelHeightAccessor levelheightaccessor = this.getHeightAccessorForGeneration(); + + for (int k = levelheightaccessor.getMinSection(); k < levelheightaccessor.getMaxSection(); ++k) { +- LevelChunkSection levelchunksection = this.getSection(this.getSectionIndexFromSectionY(k)); ++ LevelChunkSection chunksection = this.getSection(this.getSectionIndexFromSectionY(k)); + int l = QuartPos.fromSection(k); + +- levelchunksection.fillBiomesFromNoise(biomeresolver, climate_sampler, i, l, j); ++ chunksection.fillBiomesFromNoise(resolver, sampler, i, l, j); + } + + } +@@ -489,12 +510,11 @@ + } + + @Override +- @Override + public ChunkSkyLightSources getSkyLightSources() { + return this.skyLightSources; + } + +- public static record TicksToSave(SerializableTickContainer blocks, SerializableTickContainer fluids) { ++ public static record a(SerializableTickContainer blocks, SerializableTickContainer fluids) { + + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/ChunkGenerator.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/ChunkGenerator.java.patch new file mode 100644 index 0000000000..9fe7894467 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/ChunkGenerator.java.patch @@ -0,0 +1,700 @@ +--- a/net/minecraft/world/level/chunk/ChunkGenerator.java ++++ b/net/minecraft/world/level/chunk/ChunkGenerator.java +@@ -48,7 +48,6 @@ + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.LevelHeightAccessor; + import net.minecraft.world.level.LevelReader; +-import net.minecraft.world.level.NoiseColumn; + import net.minecraft.world.level.StructureManager; + import net.minecraft.world.level.WorldGenLevel; + import net.minecraft.world.level.biome.Biome; +@@ -83,48 +82,48 @@ + public static final Codec CODEC = BuiltInRegistries.CHUNK_GENERATOR.byNameCodec().dispatchStable(ChunkGenerator::codec, Function.identity()); + protected final BiomeSource biomeSource; + private final Supplier> featuresPerStep; +- private final Function, BiomeGenerationSettings> generationSettingsGetter; ++ public final Function, BiomeGenerationSettings> generationSettingsGetter; + +- public ChunkGenerator(BiomeSource biomesource) { +- this(biomesource, (holder) -> { ++ public ChunkGenerator(BiomeSource biomeSource) { ++ this(biomeSource, (holder) -> { + return ((Biome) holder.value()).getGenerationSettings(); + }); + } + +- public ChunkGenerator(BiomeSource biomesource, Function, BiomeGenerationSettings> function) { +- this.biomeSource = biomesource; +- this.generationSettingsGetter = function; ++ public ChunkGenerator(BiomeSource biomeSource, Function, BiomeGenerationSettings> generationSettingsGetter) { ++ this.biomeSource = biomeSource; ++ this.generationSettingsGetter = generationSettingsGetter; + this.featuresPerStep = Suppliers.memoize(() -> { +- return FeatureSorter.buildFeaturesPerStep(List.copyOf(biomesource.possibleBiomes()), (holder) -> { +- return ((BiomeGenerationSettings) function.apply(holder)).features(); ++ return FeatureSorter.buildFeaturesPerStep(List.copyOf(biomeSource.possibleBiomes()), (holder) -> { ++ return ((BiomeGenerationSettings) generationSettingsGetter.apply(holder)).features(); + }, true); + }); + } + + protected abstract Codec codec(); + +- public ChunkGeneratorStructureState createState(HolderLookup holderlookup, RandomState randomstate, long i) { +- return ChunkGeneratorStructureState.createForNormal(randomstate, i, this.biomeSource, holderlookup); ++ public ChunkGeneratorStructureState createState(HolderLookup structureSetLookup, RandomState randomState, long seed) { ++ return ChunkGeneratorStructureState.createForNormal(randomState, seed, this.biomeSource, structureSetLookup); + } + + public Optional>> getTypeNameForDataFixer() { + return BuiltInRegistries.CHUNK_GENERATOR.getResourceKey(this.codec()); + } + +- public CompletableFuture createBiomes(Executor executor, RandomState randomstate, Blender blender, StructureManager structuremanager, ChunkAccess chunkaccess) { ++ public CompletableFuture createBiomes(Executor executor, RandomState randomState, Blender blender, StructureManager structureManager, ChunkAccess chunk) { + return CompletableFuture.supplyAsync(Util.wrapThreadWithTaskName("init_biomes", () -> { +- chunkaccess.fillBiomesFromNoise(this.biomeSource, randomstate.sampler()); +- return chunkaccess; ++ chunk.fillBiomesFromNoise(this.biomeSource, randomState.sampler()); ++ return chunk; + }), Util.backgroundExecutor()); + } + +- public abstract void applyCarvers(WorldGenRegion level, long seed, RandomState randomState, BiomeManager random, StructureManager biomeManager, ChunkAccess structureManager, GenerationStep.Carving chunk); ++ public abstract void applyCarvers(WorldGenRegion level, long seed, RandomState randomstate, BiomeManager random, StructureManager biomeManager, ChunkAccess structureManager, GenerationStep.Carving chunk); + + @Nullable +- public Pair> findNearestMapStructure(ServerLevel serverlevel, HolderSet holderset, BlockPos blockpos, int i, boolean flag) { +- ChunkGeneratorStructureState chunkgeneratorstructurestate = serverlevel.getChunkSource().getGeneratorState(); ++ public Pair> findNearestMapStructure(ServerLevel level, HolderSet structure, BlockPos pos, int searchRadius, boolean skipKnownStructures) { ++ ChunkGeneratorStructureState chunkgeneratorstructurestate = level.getChunkSource().getGeneratorState(); + Map>> map = new Object2ObjectArrayMap(); +- Iterator iterator = holderset.iterator(); ++ Iterator iterator = structure.iterator(); + + while (iterator.hasNext()) { + Holder holder = (Holder) iterator.next(); +@@ -144,7 +143,7 @@ + } else { + Pair> pair = null; + double d0 = Double.MAX_VALUE; +- StructureManager structuremanager = serverlevel.structureManager(); ++ StructureManager structuremanager = level.structureManager(); + List>>> list = new ArrayList(map.size()); + Iterator iterator2 = map.entrySet().iterator(); + +@@ -154,11 +153,11 @@ + + if (structureplacement1 instanceof ConcentricRingsStructurePlacement) { + ConcentricRingsStructurePlacement concentricringsstructureplacement = (ConcentricRingsStructurePlacement) structureplacement1; +- Pair> pair1 = this.getNearestGeneratedStructure((Set) entry.getValue(), serverlevel, structuremanager, blockpos, flag, concentricringsstructureplacement); ++ Pair> pair1 = this.getNearestGeneratedStructure((Set) entry.getValue(), level, structuremanager, pos, skipKnownStructures, concentricringsstructureplacement); + + if (pair1 != null) { +- BlockPos blockpos1 = (BlockPos) pair1.getFirst(); +- double d1 = blockpos.distSqr(blockpos1); ++ BlockPos blockposition1 = (BlockPos) pair1.getFirst(); ++ double d1 = pos.distSqr(blockposition1); + + if (d1 < d0) { + d0 = d1; +@@ -171,21 +170,21 @@ + } + + if (!list.isEmpty()) { +- int j = SectionPos.blockToSectionCoord(blockpos.getX()); +- int k = SectionPos.blockToSectionCoord(blockpos.getZ()); ++ int j = SectionPos.blockToSectionCoord(pos.getX()); ++ int k = SectionPos.blockToSectionCoord(pos.getZ()); + +- for (int l = 0; l <= i; ++l) { ++ for (int l = 0; l <= searchRadius; ++l) { + boolean flag1 = false; + Iterator iterator3 = list.iterator(); + + while (iterator3.hasNext()) { + Entry>> entry1 = (Entry) iterator3.next(); + RandomSpreadStructurePlacement randomspreadstructureplacement = (RandomSpreadStructurePlacement) entry1.getKey(); +- Pair> pair2 = getNearestGeneratedStructure((Set) entry1.getValue(), serverlevel, structuremanager, j, k, l, flag, chunkgeneratorstructurestate.getLevelSeed(), randomspreadstructureplacement); ++ Pair> pair2 = getNearestGeneratedStructure((Set) entry1.getValue(), level, structuremanager, j, k, l, skipKnownStructures, chunkgeneratorstructurestate.getLevelSeed(), randomspreadstructureplacement); + + if (pair2 != null) { + flag1 = true; +- double d2 = blockpos.distSqr((Vec3i) pair2.getFirst()); ++ double d2 = pos.distSqr((Vec3i) pair2.getFirst()); + + if (d2 < d0) { + d0 = d2; +@@ -205,26 +204,26 @@ + } + + @Nullable +- private Pair> getNearestGeneratedStructure(Set> set, ServerLevel serverlevel, StructureManager structuremanager, BlockPos blockpos, boolean flag, ConcentricRingsStructurePlacement concentricringsstructureplacement) { +- List list = serverlevel.getChunkSource().getGeneratorState().getRingPositionsFor(concentricringsstructureplacement); ++ private Pair> getNearestGeneratedStructure(Set> structureHoldersSet, ServerLevel level, StructureManager structureManager, BlockPos pos, boolean skipKnownStructures, ConcentricRingsStructurePlacement placement) { ++ List list = level.getChunkSource().getGeneratorState().getRingPositionsFor(placement); + + if (list == null) { + throw new IllegalStateException("Somehow tried to find structures for a placement that doesn't exist"); + } else { + Pair> pair = null; + double d0 = Double.MAX_VALUE; +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- ChunkPos chunkpos = (ChunkPos) iterator.next(); ++ ChunkPos chunkcoordintpair = (ChunkPos) iterator.next(); + +- blockpos_mutableblockpos.set(SectionPos.sectionToBlockCoord(chunkpos.x, 8), 32, SectionPos.sectionToBlockCoord(chunkpos.z, 8)); +- double d1 = blockpos_mutableblockpos.distSqr(blockpos); ++ blockposition_mutableblockposition.set(SectionPos.sectionToBlockCoord(chunkcoordintpair.x, 8), 32, SectionPos.sectionToBlockCoord(chunkcoordintpair.z, 8)); ++ double d1 = blockposition_mutableblockposition.distSqr(pos); + boolean flag1 = pair == null || d1 < d0; + + if (flag1) { +- Pair> pair1 = getStructureGeneratingAt(set, serverlevel, structuremanager, flag, concentricringsstructureplacement, chunkpos); ++ Pair> pair1 = getStructureGeneratingAt(structureHoldersSet, level, structureManager, skipKnownStructures, placement, chunkcoordintpair); + + if (pair1 != null) { + pair = pair1; +@@ -238,20 +237,20 @@ + } + + @Nullable +- private static Pair> getNearestGeneratedStructure(Set> set, LevelReader levelreader, StructureManager structuremanager, int i, int j, int k, boolean flag, long l, RandomSpreadStructurePlacement randomspreadstructureplacement) { ++ private static Pair> getNearestGeneratedStructure(Set> structureHoldersSet, LevelReader level, StructureManager structureManager, int x, int y, int z, boolean skipKnownStructures, long seed, RandomSpreadStructurePlacement randomspreadstructureplacement) { + int i1 = randomspreadstructureplacement.spacing(); + +- for (int j1 = -k; j1 <= k; ++j1) { +- boolean flag1 = j1 == -k || j1 == k; ++ for (int j1 = -z; j1 <= z; ++j1) { ++ boolean flag1 = j1 == -z || j1 == z; + +- for (int k1 = -k; k1 <= k; ++k1) { +- boolean flag2 = k1 == -k || k1 == k; ++ for (int k1 = -z; k1 <= z; ++k1) { ++ boolean flag2 = k1 == -z || k1 == z; + + if (flag1 || flag2) { +- int l1 = i + i1 * j1; +- int i2 = j + i1 * k1; +- ChunkPos chunkpos = randomspreadstructureplacement.getPotentialStructureChunk(l, l1, i2); +- Pair> pair = getStructureGeneratingAt(set, levelreader, structuremanager, flag, randomspreadstructureplacement, chunkpos); ++ int l1 = x + i1 * j1; ++ int i2 = y + i1 * k1; ++ ChunkPos chunkcoordintpair = randomspreadstructureplacement.getPotentialStructureChunk(seed, l1, i2); ++ Pair> pair = getStructureGeneratingAt(structureHoldersSet, level, structureManager, skipKnownStructures, randomspreadstructureplacement, chunkcoordintpair); + + if (pair != null) { + return pair; +@@ -264,8 +263,8 @@ + } + + @Nullable +- private static Pair> getStructureGeneratingAt(Set> set, LevelReader levelreader, StructureManager structuremanager, boolean flag, StructurePlacement structureplacement, ChunkPos chunkpos) { +- Iterator iterator = set.iterator(); ++ private static Pair> getStructureGeneratingAt(Set> structureHoldersSet, LevelReader level, StructureManager structureManager, boolean skipKnownStructures, StructurePlacement placement, ChunkPos chunkPos) { ++ Iterator iterator = structureHoldersSet.iterator(); + + Holder holder; + StructureStart structurestart; +@@ -281,55 +280,55 @@ + } + + holder = (Holder) iterator.next(); +- structurecheckresult = structuremanager.checkStructurePresence(chunkpos, (Structure) holder.value(), flag); ++ structurecheckresult = structureManager.checkStructurePresence(chunkPos, (Structure) holder.value(), skipKnownStructures); + } while (structurecheckresult == StructureCheckResult.START_NOT_PRESENT); + +- if (!flag && structurecheckresult == StructureCheckResult.START_PRESENT) { +- return Pair.of(structureplacement.getLocatePos(chunkpos), holder); ++ if (!skipKnownStructures && structurecheckresult == StructureCheckResult.START_PRESENT) { ++ return Pair.of(placement.getLocatePos(chunkPos), holder); + } + +- ChunkAccess chunkaccess = levelreader.getChunk(chunkpos.x, chunkpos.z, ChunkStatus.STRUCTURE_STARTS); ++ ChunkAccess ichunkaccess = level.getChunk(chunkPos.x, chunkPos.z, ChunkStatus.STRUCTURE_STARTS); + +- structurestart = structuremanager.getStartForStructure(SectionPos.bottomOf(chunkaccess), (Structure) holder.value(), chunkaccess); ++ structurestart = structureManager.getStartForStructure(SectionPos.bottomOf(ichunkaccess), (Structure) holder.value(), ichunkaccess); + } while (structurestart == null); + } while (!structurestart.isValid()); +- } while (flag && !tryAddReference(structuremanager, structurestart)); ++ } while (skipKnownStructures && !tryAddReference(structureManager, structurestart)); + +- return Pair.of(structureplacement.getLocatePos(structurestart.getChunkPos()), holder); ++ return Pair.of(placement.getLocatePos(structurestart.getChunkPos()), holder); + } + +- private static boolean tryAddReference(StructureManager structuremanager, StructureStart structurestart) { +- if (structurestart.canBeReferenced()) { +- structuremanager.addReference(structurestart); ++ private static boolean tryAddReference(StructureManager structureManager, StructureStart structureStart) { ++ if (structureStart.canBeReferenced()) { ++ structureManager.addReference(structureStart); + return true; + } else { + return false; + } + } + +- public void applyBiomeDecoration(WorldGenLevel worldgenlevel, ChunkAccess chunkaccess, StructureManager structuremanager) { +- ChunkPos chunkpos = chunkaccess.getPos(); ++ public void addVanillaDecorations(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager) { // CraftBukkit ++ ChunkPos chunkcoordintpair = ichunkaccess.getPos(); + +- if (!SharedConstants.debugVoidTerrain(chunkpos)) { +- SectionPos sectionpos = SectionPos.of(chunkpos, worldgenlevel.getMinSection()); +- BlockPos blockpos = sectionpos.origin(); +- Registry registry = worldgenlevel.registryAccess().registryOrThrow(Registries.STRUCTURE); +- Map> map = (Map) registry.stream().collect(Collectors.groupingBy((structure) -> { ++ if (!SharedConstants.debugVoidTerrain(chunkcoordintpair)) { ++ SectionPos sectionposition = SectionPos.of(chunkcoordintpair, generatoraccessseed.getMinSection()); ++ BlockPos blockposition = sectionposition.origin(); ++ Registry iregistry = generatoraccessseed.registryAccess().registryOrThrow(Registries.STRUCTURE); ++ Map> map = (Map) iregistry.stream().collect(Collectors.groupingBy((structure) -> { + return structure.step().ordinal(); + })); + List list = (List) this.featuresPerStep.get(); +- WorldgenRandom worldgenrandom = new WorldgenRandom(new XoroshiroRandomSource(RandomSupport.generateUniqueSeed())); +- long i = worldgenrandom.setDecorationSeed(worldgenlevel.getSeed(), blockpos.getX(), blockpos.getZ()); ++ WorldgenRandom seededrandom = new WorldgenRandom(new XoroshiroRandomSource(RandomSupport.generateUniqueSeed())); ++ long i = seededrandom.setDecorationSeed(generatoraccessseed.getSeed(), blockposition.getX(), blockposition.getZ()); + Set> set = new ObjectArraySet(); + +- ChunkPos.rangeClosed(sectionpos.chunk(), 1).forEach((chunkpos1) -> { +- ChunkAccess chunkaccess1 = worldgenlevel.getChunk(chunkpos1.x, chunkpos1.z); +- LevelChunkSection[] alevelchunksection = chunkaccess1.getSections(); +- int j = alevelchunksection.length; ++ ChunkPos.rangeClosed(sectionposition.chunk(), 1).forEach((chunkcoordintpair1) -> { ++ ChunkAccess ichunkaccess1 = generatoraccessseed.getChunk(chunkcoordintpair1.x, chunkcoordintpair1.z); ++ LevelChunkSection[] achunksection = ichunkaccess1.getSections(); ++ int j = achunksection.length; + + for (int k = 0; k < j; ++k) { +- LevelChunkSection levelchunksection = alevelchunksection[k]; +- PalettedContainerRO palettedcontainerro = levelchunksection.getBiomes(); ++ LevelChunkSection chunksection = achunksection[k]; ++ PalettedContainerRO> palettedcontainerro = chunksection.getBiomes(); // CraftBukkit - decompile error + + Objects.requireNonNull(set); + palettedcontainerro.getAll(set::add); +@@ -340,13 +339,13 @@ + int j = list.size(); + + try { +- Registry registry1 = worldgenlevel.registryAccess().registryOrThrow(Registries.PLACED_FEATURE); ++ Registry iregistry1 = generatoraccessseed.registryAccess().registryOrThrow(Registries.PLACED_FEATURE); + int k = Math.max(GenerationStep.Decoration.values().length, j); + + for (int l = 0; l < k; ++l) { + int i1 = 0; + Iterator iterator; +- CrashReportCategory crashreportcategory; ++ CrashReportCategory crashreportsystemdetails; + + if (structuremanager.shouldGenerateStructures()) { + List list1 = (List) map.getOrDefault(l, Collections.emptyList()); +@@ -354,25 +353,25 @@ + for (iterator = list1.iterator(); iterator.hasNext(); ++i1) { + Structure structure = (Structure) iterator.next(); + +- worldgenrandom.setFeatureSeed(i, i1, l); +- Supplier supplier = () -> { +- Optional optional = registry.getResourceKey(structure).map(Object::toString); ++ seededrandom.setFeatureSeed(i, i1, l); ++ Supplier supplier = () -> { // CraftBukkit - decompile error ++ Optional optional = iregistry.getResourceKey(structure).map(Object::toString); + + Objects.requireNonNull(structure); + return (String) optional.orElseGet(structure::toString); + }; + + try { +- worldgenlevel.setCurrentlyGenerating(supplier); +- structuremanager.startsForStructure(sectionpos, structure).forEach((structurestart) -> { +- structurestart.placeInChunk(worldgenlevel, structuremanager, this, worldgenrandom, getWritableArea(chunkaccess), chunkpos); ++ generatoraccessseed.setCurrentlyGenerating(supplier); ++ structuremanager.startsForStructure(sectionposition, structure).forEach((structurestart) -> { ++ structurestart.placeInChunk(generatoraccessseed, structuremanager, this, seededrandom, getWritableArea(ichunkaccess), chunkcoordintpair); + }); + } catch (Exception exception) { + CrashReport crashreport = CrashReport.forThrowable(exception, "Feature placement"); + +- crashreportcategory = crashreport.addCategory("Feature"); ++ crashreportsystemdetails = crashreport.addCategory("Feature"); + Objects.requireNonNull(supplier); +- crashreportcategory.setDetail("Description", supplier::get); ++ crashreportsystemdetails.setDetail("Description", supplier::get); + throw new ReportedException(crashreport); + } + } +@@ -389,10 +388,10 @@ + + if (l < list2.size()) { + HolderSet holderset = (HolderSet) list2.get(l); +- FeatureSorter.StepFeatureData featuresorter_stepfeaturedata = (FeatureSorter.StepFeatureData) list.get(l); ++ FeatureSorter.StepFeatureData featuresorter_b = (FeatureSorter.StepFeatureData) list.get(l); + + holderset.stream().map(Holder::value).forEach((placedfeature) -> { +- intarrayset.add(featuresorter_stepfeaturedata.indexMapping().applyAsInt(placedfeature)); ++ intarrayset.add(featuresorter_b.indexMapping().applyAsInt(placedfeature)); + }); + } + } +@@ -401,50 +400,77 @@ + int[] aint = intarrayset.toIntArray(); + + Arrays.sort(aint); +- FeatureSorter.StepFeatureData featuresorter_stepfeaturedata1 = (FeatureSorter.StepFeatureData) list.get(l); ++ FeatureSorter.StepFeatureData featuresorter_b1 = (FeatureSorter.StepFeatureData) list.get(l); + + for (int k1 = 0; k1 < j1; ++k1) { + int l1 = aint[k1]; +- PlacedFeature placedfeature = (PlacedFeature) featuresorter_stepfeaturedata1.features().get(l1); ++ PlacedFeature placedfeature = (PlacedFeature) featuresorter_b1.features().get(l1); + Supplier supplier1 = () -> { +- Optional optional = registry1.getResourceKey(placedfeature).map(Object::toString); ++ Optional optional = iregistry1.getResourceKey(placedfeature).map(Object::toString); + + Objects.requireNonNull(placedfeature); + return (String) optional.orElseGet(placedfeature::toString); + }; + +- worldgenrandom.setFeatureSeed(i, l1, l); ++ seededrandom.setFeatureSeed(i, l1, l); + + try { +- worldgenlevel.setCurrentlyGenerating(supplier1); +- placedfeature.placeWithBiomeCheck(worldgenlevel, this, worldgenrandom, blockpos); ++ generatoraccessseed.setCurrentlyGenerating(supplier1); ++ placedfeature.placeWithBiomeCheck(generatoraccessseed, this, seededrandom, blockposition); + } catch (Exception exception1) { + CrashReport crashreport1 = CrashReport.forThrowable(exception1, "Feature placement"); + +- crashreportcategory = crashreport1.addCategory("Feature"); ++ crashreportsystemdetails = crashreport1.addCategory("Feature"); + Objects.requireNonNull(supplier1); +- crashreportcategory.setDetail("Description", supplier1::get); ++ crashreportsystemdetails.setDetail("Description", supplier1::get); + throw new ReportedException(crashreport1); + } + } + } + } + +- worldgenlevel.setCurrentlyGenerating((Supplier) null); ++ generatoraccessseed.setCurrentlyGenerating((Supplier) null); + } catch (Exception exception2) { + CrashReport crashreport2 = CrashReport.forThrowable(exception2, "Biome decoration"); + +- crashreport2.addCategory("Generation").setDetail("CenterX", (Object) chunkpos.x).setDetail("CenterZ", (Object) chunkpos.z).setDetail("Seed", (Object) i); ++ crashreport2.addCategory("Generation").setDetail("CenterX", (Object) chunkcoordintpair.x).setDetail("CenterZ", (Object) chunkcoordintpair.z).setDetail("Seed", (Object) i); + throw new ReportedException(crashreport2); + } + } + } + +- private static BoundingBox getWritableArea(ChunkAccess chunkaccess) { +- ChunkPos chunkpos = chunkaccess.getPos(); +- int i = chunkpos.getMinBlockX(); +- int j = chunkpos.getMinBlockZ(); +- LevelHeightAccessor levelheightaccessor = chunkaccess.getHeightAccessorForGeneration(); ++ // CraftBukkit start ++ public void applyBiomeDecoration(WorldGenLevel level, ChunkAccess chunk, StructureManager structureManager) { ++ applyBiomeDecoration(level, chunk, structureManager, true); ++ } ++ ++ public void applyBiomeDecoration(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager, boolean vanilla) { ++ if (vanilla) { ++ addVanillaDecorations(generatoraccessseed, ichunkaccess, structuremanager); ++ } ++ ++ org.bukkit.World world = generatoraccessseed.getMinecraftWorld().getWorld(); ++ // only call when a populator is present (prevents unnecessary entity conversion) ++ if (!world.getPopulators().isEmpty()) { ++ org.bukkit.craftbukkit.generator.CraftLimitedRegion limitedRegion = new org.bukkit.craftbukkit.generator.CraftLimitedRegion(generatoraccessseed, ichunkaccess.getPos()); ++ int x = ichunkaccess.getPos().x; ++ int z = ichunkaccess.getPos().z; ++ for (org.bukkit.generator.BlockPopulator populator : world.getPopulators()) { ++ WorldgenRandom seededrandom = new WorldgenRandom(new net.minecraft.world.level.levelgen.LegacyRandomSource(generatoraccessseed.getSeed())); ++ seededrandom.setDecorationSeed(generatoraccessseed.getSeed(), x, z); ++ populator.populate(world, new org.bukkit.craftbukkit.util.RandomSourceWrapper.RandomWrapper(seededrandom), x, z, limitedRegion); ++ } ++ limitedRegion.saveEntities(); ++ limitedRegion.breakLink(); ++ } ++ } ++ // CraftBukkit end ++ ++ private static BoundingBox getWritableArea(ChunkAccess chunk) { ++ ChunkPos chunkcoordintpair = chunk.getPos(); ++ int i = chunkcoordintpair.getMinBlockX(); ++ int j = chunkcoordintpair.getMinBlockZ(); ++ LevelHeightAccessor levelheightaccessor = chunk.getHeightAccessorForGeneration(); + int k = levelheightaccessor.getMinBuildHeight() + 1; + int l = levelheightaccessor.getMaxBuildHeight() - 1; + +@@ -455,7 +481,7 @@ + + public abstract void spawnOriginalMobs(WorldGenRegion level); + +- public int getSpawnHeight(LevelHeightAccessor levelheightaccessor) { ++ public int getSpawnHeight(LevelHeightAccessor level) { + return 64; + } + +@@ -465,24 +491,24 @@ + + public abstract int getGenDepth(); + +- public WeightedRandomList getMobsAt(Holder holder, StructureManager structuremanager, MobCategory mobcategory, BlockPos blockpos) { +- Map map = structuremanager.getAllStructuresAt(blockpos); ++ public WeightedRandomList getMobsAt(Holder biome, StructureManager structureManager, MobCategory category, BlockPos pos) { ++ Map map = structureManager.getAllStructuresAt(pos); + Iterator iterator = map.entrySet().iterator(); + + while (iterator.hasNext()) { + Entry entry = (Entry) iterator.next(); + Structure structure = (Structure) entry.getKey(); +- StructureSpawnOverride structurespawnoverride = (StructureSpawnOverride) structure.spawnOverrides().get(mobcategory); ++ StructureSpawnOverride structurespawnoverride = (StructureSpawnOverride) structure.spawnOverrides().get(category); + + if (structurespawnoverride != null) { + MutableBoolean mutableboolean = new MutableBoolean(false); + Predicate predicate = structurespawnoverride.boundingBox() == StructureSpawnOverride.BoundingBoxType.PIECE ? (structurestart) -> { +- return structuremanager.structureHasPieceAt(blockpos, structurestart); ++ return structureManager.structureHasPieceAt(pos, structurestart); + } : (structurestart) -> { +- return structurestart.getBoundingBox().isInside(blockpos); ++ return structurestart.getBoundingBox().isInside(pos); + }; + +- structuremanager.fillStartsForStructure(structure, (LongSet) entry.getValue(), (structurestart) -> { ++ structureManager.fillStartsForStructure(structure, (LongSet) entry.getValue(), (structurestart) -> { + if (mutableboolean.isFalse() && predicate.test(structurestart)) { + mutableboolean.setTrue(); + } +@@ -494,70 +520,70 @@ + } + } + +- return ((Biome) holder.value()).getMobSettings().getMobs(mobcategory); ++ return ((Biome) biome.value()).getMobSettings().getMobs(category); + } + +- public void createStructures(RegistryAccess registryaccess, ChunkGeneratorStructureState chunkgeneratorstructurestate, StructureManager structuremanager, ChunkAccess chunkaccess, StructureTemplateManager structuretemplatemanager) { +- ChunkPos chunkpos = chunkaccess.getPos(); +- SectionPos sectionpos = SectionPos.bottomOf(chunkaccess); +- RandomState randomstate = chunkgeneratorstructurestate.randomState(); ++ public void createStructures(RegistryAccess registryAccess, ChunkGeneratorStructureState structureState, StructureManager structureManager, ChunkAccess chunk, StructureTemplateManager structureTemplateManager) { ++ ChunkPos chunkcoordintpair = chunk.getPos(); ++ SectionPos sectionposition = SectionPos.bottomOf(chunk); ++ RandomState randomstate = structureState.randomState(); + +- chunkgeneratorstructurestate.possibleStructureSets().forEach((holder) -> { ++ structureState.possibleStructureSets().forEach((holder) -> { + StructurePlacement structureplacement = ((StructureSet) holder.value()).placement(); +- List list = ((StructureSet) holder.value()).structures(); ++ List list = ((StructureSet) holder.value()).structures(); + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +- StructureSet.StructureSelectionEntry structureset_structureselectionentry = (StructureSet.StructureSelectionEntry) iterator.next(); +- StructureStart structurestart = structuremanager.getStartForStructure(sectionpos, (Structure) structureset_structureselectionentry.structure().value(), chunkaccess); ++ StructureSet.a structureset_a = (StructureSet.a) iterator.next(); ++ StructureStart structurestart = structureManager.getStartForStructure(sectionposition, (Structure) structureset_a.structure().value(), chunk); + + if (structurestart != null && structurestart.isValid()) { + return; + } + } + +- if (structureplacement.isStructureChunk(chunkgeneratorstructurestate, chunkpos.x, chunkpos.z)) { ++ if (structureplacement.isStructureChunk(structureState, chunkcoordintpair.x, chunkcoordintpair.z)) { + if (list.size() == 1) { +- this.tryGenerateStructure((StructureSet.StructureSelectionEntry) list.get(0), structuremanager, registryaccess, randomstate, structuretemplatemanager, chunkgeneratorstructurestate.getLevelSeed(), chunkaccess, chunkpos, sectionpos); ++ this.tryGenerateStructure((StructureSet.a) list.get(0), structureManager, registryAccess, randomstate, structureTemplateManager, structureState.getLevelSeed(), chunk, chunkcoordintpair, sectionposition); + } else { +- ArrayList arraylist = new ArrayList(list.size()); ++ ArrayList arraylist = new ArrayList(list.size()); + + arraylist.addAll(list); +- WorldgenRandom worldgenrandom = new WorldgenRandom(new LegacyRandomSource(0L)); ++ WorldgenRandom seededrandom = new WorldgenRandom(new LegacyRandomSource(0L)); + +- worldgenrandom.setLargeFeatureSeed(chunkgeneratorstructurestate.getLevelSeed(), chunkpos.x, chunkpos.z); ++ seededrandom.setLargeFeatureSeed(structureState.getLevelSeed(), chunkcoordintpair.x, chunkcoordintpair.z); + int i = 0; + +- StructureSet.StructureSelectionEntry structureset_structureselectionentry1; ++ StructureSet.a structureset_a1; + +- for (Iterator iterator1 = arraylist.iterator(); iterator1.hasNext(); i += structureset_structureselectionentry1.weight()) { +- structureset_structureselectionentry1 = (StructureSet.StructureSelectionEntry) iterator1.next(); ++ for (Iterator iterator1 = arraylist.iterator(); iterator1.hasNext(); i += structureset_a1.weight()) { ++ structureset_a1 = (StructureSet.a) iterator1.next(); + } + + while (!arraylist.isEmpty()) { +- int j = worldgenrandom.nextInt(i); ++ int j = seededrandom.nextInt(i); + int k = 0; + Iterator iterator2 = arraylist.iterator(); + + while (true) { + if (iterator2.hasNext()) { +- StructureSet.StructureSelectionEntry structureset_structureselectionentry2 = (StructureSet.StructureSelectionEntry) iterator2.next(); ++ StructureSet.a structureset_a2 = (StructureSet.a) iterator2.next(); + +- j -= structureset_structureselectionentry2.weight(); ++ j -= structureset_a2.weight(); + if (j >= 0) { + ++k; + continue; + } + } + +- StructureSet.StructureSelectionEntry structureset_structureselectionentry3 = (StructureSet.StructureSelectionEntry) arraylist.get(k); ++ StructureSet.a structureset_a3 = (StructureSet.a) arraylist.get(k); + +- if (this.tryGenerateStructure(structureset_structureselectionentry3, structuremanager, registryaccess, randomstate, structuretemplatemanager, chunkgeneratorstructurestate.getLevelSeed(), chunkaccess, chunkpos, sectionpos)) { ++ if (this.tryGenerateStructure(structureset_a3, structureManager, registryAccess, randomstate, structureTemplateManager, structureState.getLevelSeed(), chunk, chunkcoordintpair, sectionposition)) { + return; + } + + arraylist.remove(k); +- i -= structureset_structureselectionentry3.weight(); ++ i -= structureset_a3.weight(); + break; + } + } +@@ -567,65 +593,73 @@ + }); + } + +- private boolean tryGenerateStructure(StructureSet.StructureSelectionEntry structureset_structureselectionentry, StructureManager structuremanager, RegistryAccess registryaccess, RandomState randomstate, StructureTemplateManager structuretemplatemanager, long i, ChunkAccess chunkaccess, ChunkPos chunkpos, SectionPos sectionpos) { +- Structure structure = (Structure) structureset_structureselectionentry.structure().value(); +- int j = fetchReferences(structuremanager, chunkaccess, sectionpos, structure); ++ private boolean tryGenerateStructure(StructureSet.a structureSelectionEntry, StructureManager structureManager, RegistryAccess registryAccess, RandomState random, StructureTemplateManager structureTemplateManager, long seed, ChunkAccess ichunkaccess, ChunkPos chunk, SectionPos chunkPos) { ++ Structure structure = (Structure) structureSelectionEntry.structure().value(); ++ int j = fetchReferences(structureManager, ichunkaccess, chunkPos, structure); + HolderSet holderset = structure.biomes(); + + Objects.requireNonNull(holderset); + Predicate> predicate = holderset::contains; +- StructureStart structurestart = structure.generate(registryaccess, this, this.biomeSource, randomstate, structuretemplatemanager, i, chunkpos, j, chunkaccess, predicate); ++ StructureStart structurestart = structure.generate(registryAccess, this, this.biomeSource, random, structureTemplateManager, seed, chunk, j, ichunkaccess, predicate); + + if (structurestart.isValid()) { +- structuremanager.setStartForStructure(sectionpos, structure, structurestart, chunkaccess); ++ // CraftBukkit start ++ BoundingBox box = structurestart.getBoundingBox(); ++ org.bukkit.event.world.AsyncStructureSpawnEvent event = new org.bukkit.event.world.AsyncStructureSpawnEvent(structureManager.level.getMinecraftWorld().getWorld(), org.bukkit.craftbukkit.generator.structure.CraftStructure.minecraftToBukkit(structure, registryAccess), new org.bukkit.util.BoundingBox(box.minX(), box.minY(), box.minZ(), box.maxX(), box.maxY(), box.maxZ()), chunk.x, chunk.z); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return true; ++ } ++ // CraftBukkit end ++ structureManager.setStartForStructure(chunkPos, structure, structurestart, ichunkaccess); + return true; + } else { + return false; + } + } + +- private static int fetchReferences(StructureManager structuremanager, ChunkAccess chunkaccess, SectionPos sectionpos, Structure structure) { +- StructureStart structurestart = structuremanager.getStartForStructure(sectionpos, structure, chunkaccess); ++ private static int fetchReferences(StructureManager structureManager, ChunkAccess chunk, SectionPos sectionPos, Structure structure) { ++ StructureStart structurestart = structureManager.getStartForStructure(sectionPos, structure, chunk); + + return structurestart != null ? structurestart.getReferences() : 0; + } + +- public void createReferences(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkAccess chunkaccess) { ++ public void createReferences(WorldGenLevel level, StructureManager structureManager, ChunkAccess chunk) { + boolean flag = true; +- ChunkPos chunkpos = chunkaccess.getPos(); +- int i = chunkpos.x; +- int j = chunkpos.z; +- int k = chunkpos.getMinBlockX(); +- int l = chunkpos.getMinBlockZ(); +- SectionPos sectionpos = SectionPos.bottomOf(chunkaccess); ++ ChunkPos chunkcoordintpair = chunk.getPos(); ++ int i = chunkcoordintpair.x; ++ int j = chunkcoordintpair.z; ++ int k = chunkcoordintpair.getMinBlockX(); ++ int l = chunkcoordintpair.getMinBlockZ(); ++ SectionPos sectionposition = SectionPos.bottomOf(chunk); + + for (int i1 = i - 8; i1 <= i + 8; ++i1) { + for (int j1 = j - 8; j1 <= j + 8; ++j1) { + long k1 = ChunkPos.asLong(i1, j1); +- Iterator iterator = worldgenlevel.getChunk(i1, j1).getAllStarts().values().iterator(); ++ Iterator iterator = level.getChunk(i1, j1).getAllStarts().values().iterator(); + + while (iterator.hasNext()) { + StructureStart structurestart = (StructureStart) iterator.next(); + + try { + if (structurestart.isValid() && structurestart.getBoundingBox().intersects(k, l, k + 15, l + 15)) { +- structuremanager.addReferenceForStructure(sectionpos, structurestart.getStructure(), k1, chunkaccess); +- DebugPackets.sendStructurePacket(worldgenlevel, structurestart); ++ structureManager.addReferenceForStructure(sectionposition, structurestart.getStructure(), k1, chunk); ++ DebugPackets.sendStructurePacket(level, structurestart); + } + } catch (Exception exception) { + CrashReport crashreport = CrashReport.forThrowable(exception, "Generating structure reference"); +- CrashReportCategory crashreportcategory = crashreport.addCategory("Structure"); +- Optional> optional = worldgenlevel.registryAccess().registry(Registries.STRUCTURE); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Structure"); ++ Optional> optional = level.registryAccess().registry(Registries.STRUCTURE); + +- crashreportcategory.setDetail("Id", () -> { +- return (String) optional.map((registry) -> { +- return registry.getKey(structurestart.getStructure()).toString(); ++ crashreportsystemdetails.setDetail("Id", () -> { ++ return (String) optional.map((iregistry) -> { ++ return iregistry.getKey(structurestart.getStructure()).toString(); + }).orElse("UNKNOWN"); + }); +- crashreportcategory.setDetail("Name", () -> { ++ crashreportsystemdetails.setDetail("Name", () -> { + return BuiltInRegistries.STRUCTURE_TYPE.getKey(structurestart.getStructure().type()).toString(); + }); +- crashreportcategory.setDetail("Class", () -> { ++ crashreportsystemdetails.setDetail("Class", () -> { + return structurestart.getStructure().getClass().getCanonicalName(); + }); + throw new ReportedException(crashreport); +@@ -644,21 +678,21 @@ + + public abstract int getBaseHeight(int x, int z, Heightmap.Types type, LevelHeightAccessor level, RandomState random); + +- public abstract NoiseColumn getBaseColumn(int x, int z, LevelHeightAccessor height, RandomState random); ++ public abstract net.minecraft.world.level.NoiseColumn getBaseColumn(int x, int z, LevelHeightAccessor height, RandomState random); + +- public int getFirstFreeHeight(int i, int j, Heightmap.Types heightmap_types, LevelHeightAccessor levelheightaccessor, RandomState randomstate) { +- return this.getBaseHeight(i, j, heightmap_types, levelheightaccessor, randomstate); ++ public int getFirstFreeHeight(int x, int z, Heightmap.Types type, LevelHeightAccessor level, RandomState random) { ++ return this.getBaseHeight(x, z, type, level, random); + } + +- public int getFirstOccupiedHeight(int i, int j, Heightmap.Types heightmap_types, LevelHeightAccessor levelheightaccessor, RandomState randomstate) { +- return this.getBaseHeight(i, j, heightmap_types, levelheightaccessor, randomstate) - 1; ++ public int getFirstOccupiedHeight(int x, int z, Heightmap.Types types, LevelHeightAccessor level, RandomState random) { ++ return this.getBaseHeight(x, z, types, level, random) - 1; + } + + public abstract void addDebugScreenInfo(List info, RandomState random, BlockPos pos); + + /** @deprecated */ + @Deprecated +- public BiomeGenerationSettings getBiomeGenerationSettings(Holder holder) { +- return (BiomeGenerationSettings) this.generationSettingsGetter.apply(holder); ++ public BiomeGenerationSettings getBiomeGenerationSettings(Holder biome) { ++ return (BiomeGenerationSettings) this.generationSettingsGetter.apply(biome); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java.patch new file mode 100644 index 0000000000..70be79b403 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java.patch @@ -0,0 +1,166 @@ +--- a/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java ++++ b/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.world.level.chunk; + + import com.google.common.base.Stopwatch; +@@ -45,40 +46,40 @@ + private boolean hasGeneratedPositions; + private final List> possibleStructureSets; + +- public static ChunkGeneratorStructureState createForFlat(RandomState randomstate, long i, BiomeSource biomesource, Stream> stream) { +- List> list = stream.filter((holder) -> { +- return hasBiomesForStructureSet((StructureSet) holder.value(), biomesource); ++ public static ChunkGeneratorStructureState createForFlat(RandomState randomState, long levelSeed, BiomeSource worldchunkmanager, Stream> biomeSource) { ++ List> list = biomeSource.filter((holder) -> { ++ return hasBiomesForStructureSet((StructureSet) holder.value(), worldchunkmanager); + }).toList(); + +- return new ChunkGeneratorStructureState(randomstate, biomesource, i, 0L, list); ++ return new ChunkGeneratorStructureState(randomState, worldchunkmanager, levelSeed, 0L, list); + } + +- public static ChunkGeneratorStructureState createForNormal(RandomState randomstate, long i, BiomeSource biomesource, HolderLookup holderlookup) { +- List> list = (List) holderlookup.listElements().filter((holder_reference) -> { +- return hasBiomesForStructureSet((StructureSet) holder_reference.value(), biomesource); ++ public static ChunkGeneratorStructureState createForNormal(RandomState randomState, long seed, BiomeSource worldchunkmanager, HolderLookup biomeSource) { ++ List> list = (List) biomeSource.listElements().filter((holder_c) -> { ++ return hasBiomesForStructureSet((StructureSet) holder_c.value(), worldchunkmanager); + }).collect(Collectors.toUnmodifiableList()); + +- return new ChunkGeneratorStructureState(randomstate, biomesource, i, i, list); ++ return new ChunkGeneratorStructureState(randomState, worldchunkmanager, seed, seed, list); + } + +- private static boolean hasBiomesForStructureSet(StructureSet structureset, BiomeSource biomesource) { +- Stream> stream = structureset.structures().stream().flatMap((structureset_structureselectionentry) -> { +- Structure structure = (Structure) structureset_structureselectionentry.structure().value(); ++ private static boolean hasBiomesForStructureSet(StructureSet structureSet, BiomeSource biomeSource) { ++ Stream> stream = structureSet.structures().stream().flatMap((structureset_a) -> { ++ Structure structure = (Structure) structureset_a.structure().value(); + + return structure.biomes().stream(); + }); +- Set set = biomesource.possibleBiomes(); ++ Set set = biomeSource.possibleBiomes(); + + Objects.requireNonNull(set); + return stream.anyMatch(set::contains); + } + +- private ChunkGeneratorStructureState(RandomState randomstate, BiomeSource biomesource, long i, long j, List> list) { +- this.randomState = randomstate; +- this.levelSeed = i; +- this.biomeSource = biomesource; ++ private ChunkGeneratorStructureState(RandomState randomState, BiomeSource biomeSource, long levelSeed, long j, List> cocentricRingsSeed) { ++ this.randomState = randomState; ++ this.levelSeed = levelSeed; ++ this.biomeSource = biomeSource; + this.concentricRingsSeed = j; +- this.possibleStructureSets = list; ++ this.possibleStructureSets = cocentricRingsSeed; + } + + public List> possibleStructureSets() { +@@ -94,8 +95,8 @@ + Iterator iterator = structureset.structures().iterator(); + + while (iterator.hasNext()) { +- StructureSet.StructureSelectionEntry structureset_structureselectionentry = (StructureSet.StructureSelectionEntry) iterator.next(); +- Structure structure = (Structure) structureset_structureselectionentry.structure().value(); ++ StructureSet.a structureset_a = (StructureSet.a) iterator.next(); ++ Structure structure = (Structure) structureset_a.structure().value(); + Stream stream = structure.biomes().stream(); + + Objects.requireNonNull(set); +@@ -120,16 +121,16 @@ + }); + } + +- private CompletableFuture> generateRingPositions(Holder holder, ConcentricRingsStructurePlacement concentricringsstructureplacement) { +- if (concentricringsstructureplacement.count() == 0) { ++ private CompletableFuture> generateRingPositions(Holder structureSet, ConcentricRingsStructurePlacement placement) { ++ if (placement.count() == 0) { + return CompletableFuture.completedFuture(List.of()); + } else { + Stopwatch stopwatch = Stopwatch.createStarted(Util.TICKER); +- int i = concentricringsstructureplacement.distance(); +- int j = concentricringsstructureplacement.count(); ++ int i = placement.distance(); ++ int j = placement.count(); + List> list = new ArrayList(j); +- int k = concentricringsstructureplacement.spread(); +- HolderSet holderset = concentricringsstructureplacement.preferredBiomes(); ++ int k = placement.spread(); ++ HolderSet holderset = placement.preferredBiomes(); + RandomSource randomsource = RandomSource.create(); + + randomsource.setSeed(this.concentricRingsSeed); +@@ -144,17 +145,17 @@ + RandomSource randomsource1 = randomsource.fork(); + + list.add(CompletableFuture.supplyAsync(() -> { +- BiomeSource biomesource = this.biomeSource; ++ BiomeSource worldchunkmanager = this.biomeSource; + int i2 = SectionPos.sectionToBlockCoord(k1, 8); + int j2 = SectionPos.sectionToBlockCoord(l1, 8); + + Objects.requireNonNull(holderset); +- Pair> pair = biomesource.findBiomeHorizontal(i2, 0, j2, 112, holderset::contains, randomsource1, this.randomState.sampler()); ++ Pair> pair = worldchunkmanager.findBiomeHorizontal(i2, 0, j2, 112, holderset::contains, randomsource1, this.randomState.sampler()); + + if (pair != null) { +- BlockPos blockpos = (BlockPos) pair.getFirst(); ++ BlockPos blockposition = (BlockPos) pair.getFirst(); + +- return new ChunkPos(SectionPos.blockToSectionCoord(blockpos.getX()), SectionPos.blockToSectionCoord(blockpos.getZ())); ++ return new ChunkPos(SectionPos.blockToSectionCoord(blockposition.getX()), SectionPos.blockToSectionCoord(blockposition.getZ())); + } else { + return new ChunkPos(k1, l1); + } +@@ -173,7 +174,7 @@ + return Util.sequence(list).thenApply((list1) -> { + double d2 = (double) stopwatch.stop().elapsed(TimeUnit.MILLISECONDS) / 1000.0D; + +- ChunkGeneratorStructureState.LOGGER.debug("Calculation for {} took {}s", holder, d2); ++ ChunkGeneratorStructureState.LOGGER.debug("Calculation for {} took {}s", structureSet, d2); + return list1; + }); + } +@@ -188,27 +189,27 @@ + } + + @Nullable +- public List getRingPositionsFor(ConcentricRingsStructurePlacement concentricringsstructureplacement) { ++ public List getRingPositionsFor(ConcentricRingsStructurePlacement placement) { + this.ensureStructuresGenerated(); +- CompletableFuture> completablefuture = (CompletableFuture) this.ringPositions.get(concentricringsstructureplacement); ++ CompletableFuture> completablefuture = (CompletableFuture) this.ringPositions.get(placement); + + return completablefuture != null ? (List) completablefuture.join() : null; + } + +- public List getPlacementsForStructure(Holder holder) { ++ public List getPlacementsForStructure(Holder structure) { + this.ensureStructuresGenerated(); +- return (List) this.placementsForStructure.getOrDefault(holder.value(), List.of()); ++ return (List) this.placementsForStructure.getOrDefault(structure.value(), List.of()); + } + + public RandomState randomState() { + return this.randomState; + } + +- public boolean hasStructureChunkInRange(Holder holder, int i, int j, int k) { +- StructurePlacement structureplacement = ((StructureSet) holder.value()).placement(); ++ public boolean hasStructureChunkInRange(Holder structureSet, int x, int z, int range) { ++ StructurePlacement structureplacement = ((StructureSet) structureSet.value()).placement(); + +- for (int l = i - k; l <= i + k; ++l) { +- for (int i1 = j - k; i1 <= j + k; ++i1) { ++ for (int l = x - range; l <= x + range; ++l) { ++ for (int i1 = z - range; i1 <= z + range; ++i1) { + if (structureplacement.isStructureChunk(this, l, i1)) { + return true; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/ChunkStatus.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/ChunkStatus.java.patch new file mode 100644 index 0000000000..60051765ba --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/ChunkStatus.java.patch @@ -0,0 +1,342 @@ +--- a/net/minecraft/world/level/chunk/ChunkStatus.java ++++ b/net/minecraft/world/level/chunk/ChunkStatus.java +@@ -33,40 +33,40 @@ + public static final int MAX_STRUCTURE_DISTANCE = 8; + private static final EnumSet PRE_FEATURES = EnumSet.of(Heightmap.Types.OCEAN_FLOOR_WG, Heightmap.Types.WORLD_SURFACE_WG); + public static final EnumSet POST_FEATURES = EnumSet.of(Heightmap.Types.OCEAN_FLOOR, Heightmap.Types.WORLD_SURFACE, Heightmap.Types.MOTION_BLOCKING, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES); +- private static final ChunkStatus.LoadingTask PASSTHROUGH_LOAD_TASK = (chunkstatus, serverlevel, structuretemplatemanager, threadedlevellightengine, function, chunkaccess) -> { +- return CompletableFuture.completedFuture(Either.left(chunkaccess)); ++ private static final ChunkStatus.LoadingTask PASSTHROUGH_LOAD_TASK = (chunkstatus, worldserver, structuretemplatemanager, lightenginethreaded, function, ichunkaccess) -> { ++ return CompletableFuture.completedFuture(Either.left(ichunkaccess)); + }; +- public static final ChunkStatus EMPTY = registerSimple("empty", (ChunkStatus) null, -1, ChunkStatus.PRE_FEATURES, ChunkStatus.ChunkType.PROTOCHUNK, (chunkstatus, serverlevel, chunkgenerator, list, chunkaccess) -> { ++ public static final ChunkStatus EMPTY = registerSimple("empty", (ChunkStatus) null, -1, ChunkStatus.PRE_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, list, ichunkaccess) -> { + }); +- public static final ChunkStatus STRUCTURE_STARTS = register("structure_starts", ChunkStatus.EMPTY, 0, false, ChunkStatus.PRE_FEATURES, ChunkStatus.ChunkType.PROTOCHUNK, (chunkstatus, executor, serverlevel, chunkgenerator, structuretemplatemanager, threadedlevellightengine, function, list, chunkaccess) -> { +- if (serverlevel.getServer().getWorldData().worldGenOptions().generateStructures()) { +- chunkgenerator.createStructures(serverlevel.registryAccess(), serverlevel.getChunkSource().getGeneratorState(), serverlevel.structureManager(), chunkaccess, structuretemplatemanager); ++ public static final ChunkStatus STRUCTURE_STARTS = register("structure_starts", ChunkStatus.EMPTY, 0, false, ChunkStatus.PRE_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, executor, worldserver, chunkgenerator, structuretemplatemanager, lightenginethreaded, function, list, ichunkaccess) -> { ++ if (worldserver.serverLevelData.worldGenOptions().generateStructures()) { // CraftBukkit ++ chunkgenerator.createStructures(worldserver.registryAccess(), worldserver.getChunkSource().getGeneratorState(), worldserver.structureManager(), ichunkaccess, structuretemplatemanager); + } + +- serverlevel.onStructureStartsAvailable(chunkaccess); +- return CompletableFuture.completedFuture(Either.left(chunkaccess)); +- }, (chunkstatus, serverlevel, structuretemplatemanager, threadedlevellightengine, function, chunkaccess) -> { +- serverlevel.onStructureStartsAvailable(chunkaccess); +- return CompletableFuture.completedFuture(Either.left(chunkaccess)); ++ worldserver.onStructureStartsAvailable(ichunkaccess); ++ return CompletableFuture.completedFuture(Either.left(ichunkaccess)); ++ }, (chunkstatus, worldserver, structuretemplatemanager, lightenginethreaded, function, ichunkaccess) -> { ++ worldserver.onStructureStartsAvailable(ichunkaccess); ++ return CompletableFuture.completedFuture(Either.left(ichunkaccess)); + }); +- public static final ChunkStatus STRUCTURE_REFERENCES = registerSimple("structure_references", ChunkStatus.STRUCTURE_STARTS, 8, ChunkStatus.PRE_FEATURES, ChunkStatus.ChunkType.PROTOCHUNK, (chunkstatus, serverlevel, chunkgenerator, list, chunkaccess) -> { +- WorldGenRegion worldgenregion = new WorldGenRegion(serverlevel, list, chunkstatus, -1); ++ public static final ChunkStatus STRUCTURE_REFERENCES = registerSimple("structure_references", ChunkStatus.STRUCTURE_STARTS, 8, ChunkStatus.PRE_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, list, ichunkaccess) -> { ++ WorldGenRegion regionlimitedworldaccess = new WorldGenRegion(worldserver, list, chunkstatus, -1); + +- chunkgenerator.createReferences(worldgenregion, serverlevel.structureManager().forWorldGenRegion(worldgenregion), chunkaccess); ++ chunkgenerator.createReferences(regionlimitedworldaccess, worldserver.structureManager().forWorldGenRegion(regionlimitedworldaccess), ichunkaccess); + }); +- public static final ChunkStatus BIOMES = register("biomes", ChunkStatus.STRUCTURE_REFERENCES, 8, ChunkStatus.PRE_FEATURES, ChunkStatus.ChunkType.PROTOCHUNK, (chunkstatus, executor, serverlevel, chunkgenerator, structuretemplatemanager, threadedlevellightengine, function, list, chunkaccess) -> { +- WorldGenRegion worldgenregion = new WorldGenRegion(serverlevel, list, chunkstatus, -1); ++ public static final ChunkStatus BIOMES = register("biomes", ChunkStatus.STRUCTURE_REFERENCES, 8, ChunkStatus.PRE_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, executor, worldserver, chunkgenerator, structuretemplatemanager, lightenginethreaded, function, list, ichunkaccess) -> { ++ WorldGenRegion regionlimitedworldaccess = new WorldGenRegion(worldserver, list, chunkstatus, -1); + +- return chunkgenerator.createBiomes(executor, serverlevel.getChunkSource().randomState(), Blender.of(worldgenregion), serverlevel.structureManager().forWorldGenRegion(worldgenregion), chunkaccess).thenApply((chunkaccess1) -> { +- return Either.left(chunkaccess1); ++ return chunkgenerator.createBiomes(executor, worldserver.getChunkSource().randomState(), Blender.of(regionlimitedworldaccess), worldserver.structureManager().forWorldGenRegion(regionlimitedworldaccess), ichunkaccess).thenApply((ichunkaccess1) -> { ++ return Either.left(ichunkaccess1); + }); + }); +- public static final ChunkStatus NOISE = register("noise", ChunkStatus.BIOMES, 8, ChunkStatus.PRE_FEATURES, ChunkStatus.ChunkType.PROTOCHUNK, (chunkstatus, executor, serverlevel, chunkgenerator, structuretemplatemanager, threadedlevellightengine, function, list, chunkaccess) -> { +- WorldGenRegion worldgenregion = new WorldGenRegion(serverlevel, list, chunkstatus, 0); ++ public static final ChunkStatus NOISE = register("noise", ChunkStatus.BIOMES, 8, ChunkStatus.PRE_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, executor, worldserver, chunkgenerator, structuretemplatemanager, lightenginethreaded, function, list, ichunkaccess) -> { ++ WorldGenRegion regionlimitedworldaccess = new WorldGenRegion(worldserver, list, chunkstatus, 0); + +- return chunkgenerator.fillFromNoise(executor, Blender.of(worldgenregion), serverlevel.getChunkSource().randomState(), serverlevel.structureManager().forWorldGenRegion(worldgenregion), chunkaccess).thenApply((chunkaccess1) -> { +- if (chunkaccess1 instanceof ProtoChunk) { +- ProtoChunk protochunk = (ProtoChunk) chunkaccess1; ++ return chunkgenerator.fillFromNoise(executor, Blender.of(regionlimitedworldaccess), worldserver.getChunkSource().randomState(), worldserver.structureManager().forWorldGenRegion(regionlimitedworldaccess), ichunkaccess).thenApply((ichunkaccess1) -> { ++ if (ichunkaccess1 instanceof ProtoChunk) { ++ ProtoChunk protochunk = (ProtoChunk) ichunkaccess1; + BelowZeroRetrogen belowzeroretrogen = protochunk.getBelowZeroRetrogen(); + + if (belowzeroretrogen != null) { +@@ -77,52 +77,52 @@ + } + } + +- return Either.left(chunkaccess1); ++ return Either.left(ichunkaccess1); + }); + }); +- public static final ChunkStatus SURFACE = registerSimple("surface", ChunkStatus.NOISE, 8, ChunkStatus.PRE_FEATURES, ChunkStatus.ChunkType.PROTOCHUNK, (chunkstatus, serverlevel, chunkgenerator, list, chunkaccess) -> { +- WorldGenRegion worldgenregion = new WorldGenRegion(serverlevel, list, chunkstatus, 0); ++ public static final ChunkStatus SURFACE = registerSimple("surface", ChunkStatus.NOISE, 8, ChunkStatus.PRE_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, list, ichunkaccess) -> { ++ WorldGenRegion regionlimitedworldaccess = new WorldGenRegion(worldserver, list, chunkstatus, 0); + +- chunkgenerator.buildSurface(worldgenregion, serverlevel.structureManager().forWorldGenRegion(worldgenregion), serverlevel.getChunkSource().randomState(), chunkaccess); ++ chunkgenerator.buildSurface(regionlimitedworldaccess, worldserver.structureManager().forWorldGenRegion(regionlimitedworldaccess), worldserver.getChunkSource().randomState(), ichunkaccess); + }); +- public static final ChunkStatus CARVERS = registerSimple("carvers", ChunkStatus.SURFACE, 8, ChunkStatus.POST_FEATURES, ChunkStatus.ChunkType.PROTOCHUNK, (chunkstatus, serverlevel, chunkgenerator, list, chunkaccess) -> { +- WorldGenRegion worldgenregion = new WorldGenRegion(serverlevel, list, chunkstatus, 0); ++ public static final ChunkStatus CARVERS = registerSimple("carvers", ChunkStatus.SURFACE, 8, ChunkStatus.POST_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, list, ichunkaccess) -> { ++ WorldGenRegion regionlimitedworldaccess = new WorldGenRegion(worldserver, list, chunkstatus, 0); + +- if (chunkaccess instanceof ProtoChunk) { +- ProtoChunk protochunk = (ProtoChunk) chunkaccess; ++ if (ichunkaccess instanceof ProtoChunk) { ++ ProtoChunk protochunk = (ProtoChunk) ichunkaccess; + +- Blender.addAroundOldChunksCarvingMaskFilter(worldgenregion, protochunk); ++ Blender.addAroundOldChunksCarvingMaskFilter(regionlimitedworldaccess, protochunk); + } + +- chunkgenerator.applyCarvers(worldgenregion, serverlevel.getSeed(), serverlevel.getChunkSource().randomState(), serverlevel.getBiomeManager(), serverlevel.structureManager().forWorldGenRegion(worldgenregion), chunkaccess, GenerationStep.Carving.AIR); ++ chunkgenerator.applyCarvers(regionlimitedworldaccess, worldserver.getSeed(), worldserver.getChunkSource().randomState(), worldserver.getBiomeManager(), worldserver.structureManager().forWorldGenRegion(regionlimitedworldaccess), ichunkaccess, GenerationStep.Carving.AIR); + }); +- public static final ChunkStatus FEATURES = registerSimple("features", ChunkStatus.CARVERS, 8, ChunkStatus.POST_FEATURES, ChunkStatus.ChunkType.PROTOCHUNK, (chunkstatus, serverlevel, chunkgenerator, list, chunkaccess) -> { +- Heightmap.primeHeightmaps(chunkaccess, EnumSet.of(Heightmap.Types.MOTION_BLOCKING, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, Heightmap.Types.OCEAN_FLOOR, Heightmap.Types.WORLD_SURFACE)); +- WorldGenRegion worldgenregion = new WorldGenRegion(serverlevel, list, chunkstatus, 1); ++ public static final ChunkStatus FEATURES = registerSimple("features", ChunkStatus.CARVERS, 8, ChunkStatus.POST_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, list, ichunkaccess) -> { ++ Heightmap.primeHeightmaps(ichunkaccess, EnumSet.of(Heightmap.Types.MOTION_BLOCKING, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, Heightmap.Types.OCEAN_FLOOR, Heightmap.Types.WORLD_SURFACE)); ++ WorldGenRegion regionlimitedworldaccess = new WorldGenRegion(worldserver, list, chunkstatus, 1); + +- chunkgenerator.applyBiomeDecoration(worldgenregion, chunkaccess, serverlevel.structureManager().forWorldGenRegion(worldgenregion)); +- Blender.generateBorderTicks(worldgenregion, chunkaccess); ++ chunkgenerator.applyBiomeDecoration(regionlimitedworldaccess, ichunkaccess, worldserver.structureManager().forWorldGenRegion(regionlimitedworldaccess)); ++ Blender.generateBorderTicks(regionlimitedworldaccess, ichunkaccess); + }); +- public static final ChunkStatus INITIALIZE_LIGHT = register("initialize_light", ChunkStatus.FEATURES, 0, false, ChunkStatus.POST_FEATURES, ChunkStatus.ChunkType.PROTOCHUNK, (chunkstatus, executor, serverlevel, chunkgenerator, structuretemplatemanager, threadedlevellightengine, function, list, chunkaccess) -> { +- return initializeLight(threadedlevellightengine, chunkaccess); +- }, (chunkstatus, serverlevel, structuretemplatemanager, threadedlevellightengine, function, chunkaccess) -> { +- return initializeLight(threadedlevellightengine, chunkaccess); ++ public static final ChunkStatus INITIALIZE_LIGHT = register("initialize_light", ChunkStatus.FEATURES, 0, false, ChunkStatus.POST_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, executor, worldserver, chunkgenerator, structuretemplatemanager, lightenginethreaded, function, list, ichunkaccess) -> { ++ return initializeLight(lightenginethreaded, ichunkaccess); ++ }, (chunkstatus, worldserver, structuretemplatemanager, lightenginethreaded, function, ichunkaccess) -> { ++ return initializeLight(lightenginethreaded, ichunkaccess); + }); +- public static final ChunkStatus LIGHT = register("light", ChunkStatus.INITIALIZE_LIGHT, 1, true, ChunkStatus.POST_FEATURES, ChunkStatus.ChunkType.PROTOCHUNK, (chunkstatus, executor, serverlevel, chunkgenerator, structuretemplatemanager, threadedlevellightengine, function, list, chunkaccess) -> { +- return lightChunk(threadedlevellightengine, chunkaccess); +- }, (chunkstatus, serverlevel, structuretemplatemanager, threadedlevellightengine, function, chunkaccess) -> { +- return lightChunk(threadedlevellightengine, chunkaccess); ++ public static final ChunkStatus LIGHT = register("light", ChunkStatus.INITIALIZE_LIGHT, 1, true, ChunkStatus.POST_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, executor, worldserver, chunkgenerator, structuretemplatemanager, lightenginethreaded, function, list, ichunkaccess) -> { ++ return lightChunk(lightenginethreaded, ichunkaccess); ++ }, (chunkstatus, worldserver, structuretemplatemanager, lightenginethreaded, function, ichunkaccess) -> { ++ return lightChunk(lightenginethreaded, ichunkaccess); + }); +- public static final ChunkStatus SPAWN = registerSimple("spawn", ChunkStatus.LIGHT, 0, ChunkStatus.POST_FEATURES, ChunkStatus.ChunkType.PROTOCHUNK, (chunkstatus, serverlevel, chunkgenerator, list, chunkaccess) -> { +- if (!chunkaccess.isUpgrading()) { +- chunkgenerator.spawnOriginalMobs(new WorldGenRegion(serverlevel, list, chunkstatus, -1)); ++ public static final ChunkStatus SPAWN = registerSimple("spawn", ChunkStatus.LIGHT, 0, ChunkStatus.POST_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, list, ichunkaccess) -> { ++ if (!ichunkaccess.isUpgrading()) { ++ chunkgenerator.spawnOriginalMobs(new WorldGenRegion(worldserver, list, chunkstatus, -1)); + } + + }); +- public static final ChunkStatus FULL = register("full", ChunkStatus.SPAWN, 0, false, ChunkStatus.POST_FEATURES, ChunkStatus.ChunkType.LEVELCHUNK, (chunkstatus, executor, serverlevel, chunkgenerator, structuretemplatemanager, threadedlevellightengine, function, list, chunkaccess) -> { +- return (CompletableFuture) function.apply(chunkaccess); +- }, (chunkstatus, serverlevel, structuretemplatemanager, threadedlevellightengine, function, chunkaccess) -> { +- return (CompletableFuture) function.apply(chunkaccess); ++ public static final ChunkStatus FULL = register("full", ChunkStatus.SPAWN, 0, false, ChunkStatus.POST_FEATURES, ChunkStatus.Type.LEVELCHUNK, (chunkstatus, executor, worldserver, chunkgenerator, structuretemplatemanager, lightenginethreaded, function, list, ichunkaccess) -> { ++ return (CompletableFuture) function.apply(ichunkaccess); ++ }, (chunkstatus, worldserver, structuretemplatemanager, lightenginethreaded, function, ichunkaccess) -> { ++ return (CompletableFuture) function.apply(ichunkaccess); + }); + private static final List STATUS_BY_RANGE = ImmutableList.of(ChunkStatus.FULL, ChunkStatus.INITIALIZE_LIGHT, ChunkStatus.CARVERS, ChunkStatus.BIOMES, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, new ChunkStatus[0]); + private static final IntList RANGE_BY_STATUS = (IntList) Util.make(new IntArrayList(getStatusList().size()), (intarraylist) -> { +@@ -143,33 +143,33 @@ + private final ChunkStatus.LoadingTask loadingTask; + private final int range; + private final boolean hasLoadDependencies; +- private final ChunkStatus.ChunkType chunkType; ++ private final ChunkStatus.Type chunkType; + private final EnumSet heightmapsAfter; + +- private static CompletableFuture> initializeLight(ThreadedLevelLightEngine threadedlevellightengine, ChunkAccess chunkaccess) { +- chunkaccess.initializeLightSources(); +- ((ProtoChunk) chunkaccess).setLightEngine(threadedlevellightengine); +- boolean flag = isLighted(chunkaccess); ++ private static CompletableFuture> initializeLight(ThreadedLevelLightEngine lightEngine, ChunkAccess chunk) { ++ chunk.initializeLightSources(); ++ ((ProtoChunk) chunk).setLightEngine(lightEngine); ++ boolean flag = isLighted(chunk); + +- return threadedlevellightengine.initializeLight(chunkaccess, flag).thenApply(Either::left); ++ return lightEngine.initializeLight(chunk, flag).thenApply(Either::left); + } + +- private static CompletableFuture> lightChunk(ThreadedLevelLightEngine threadedlevellightengine, ChunkAccess chunkaccess) { +- boolean flag = isLighted(chunkaccess); ++ private static CompletableFuture> lightChunk(ThreadedLevelLightEngine lightEngine, ChunkAccess chunk) { ++ boolean flag = isLighted(chunk); + +- return threadedlevellightengine.lightChunk(chunkaccess, flag).thenApply(Either::left); ++ return lightEngine.lightChunk(chunk, flag).thenApply(Either::left); + } + +- private static ChunkStatus registerSimple(String s, @Nullable ChunkStatus chunkstatus, int i, EnumSet enumset, ChunkStatus.ChunkType chunkstatus_chunktype, ChunkStatus.SimpleGenerationTask chunkstatus_simplegenerationtask) { +- return register(s, chunkstatus, i, enumset, chunkstatus_chunktype, chunkstatus_simplegenerationtask); ++ private static ChunkStatus registerSimple(String key, @Nullable ChunkStatus parent, int taskRange, EnumSet heightmaps, ChunkStatus.Type type, ChunkStatus.SimpleGenerationTask generationTask) { ++ return register(key, parent, taskRange, heightmaps, type, generationTask); + } + +- private static ChunkStatus register(String s, @Nullable ChunkStatus chunkstatus, int i, EnumSet enumset, ChunkStatus.ChunkType chunkstatus_chunktype, ChunkStatus.GenerationTask chunkstatus_generationtask) { +- return register(s, chunkstatus, i, false, enumset, chunkstatus_chunktype, chunkstatus_generationtask, ChunkStatus.PASSTHROUGH_LOAD_TASK); ++ private static ChunkStatus register(String key, @Nullable ChunkStatus parent, int taskRange, EnumSet heightmaps, ChunkStatus.Type type, ChunkStatus.GenerationTask generationTask) { ++ return register(key, parent, taskRange, false, heightmaps, type, generationTask, ChunkStatus.PASSTHROUGH_LOAD_TASK); + } + +- private static ChunkStatus register(String s, @Nullable ChunkStatus chunkstatus, int i, boolean flag, EnumSet enumset, ChunkStatus.ChunkType chunkstatus_chunktype, ChunkStatus.GenerationTask chunkstatus_generationtask, ChunkStatus.LoadingTask chunkstatus_loadingtask) { +- return (ChunkStatus) Registry.register(BuiltInRegistries.CHUNK_STATUS, s, new ChunkStatus(chunkstatus, i, flag, enumset, chunkstatus_chunktype, chunkstatus_generationtask, chunkstatus_loadingtask)); ++ private static ChunkStatus register(String key, @Nullable ChunkStatus parent, int taskRange, boolean hasLoadDependencies, EnumSet heightmaps, ChunkStatus.Type type, ChunkStatus.GenerationTask generationTask, ChunkStatus.LoadingTask loadingTask) { ++ return (ChunkStatus) Registry.register(BuiltInRegistries.CHUNK_STATUS, key, new ChunkStatus(parent, taskRange, hasLoadDependencies, heightmaps, type, generationTask, loadingTask)); + } + + public static List getStatusList() { +@@ -186,31 +186,31 @@ + return list; + } + +- private static boolean isLighted(ChunkAccess chunkaccess) { +- return chunkaccess.getStatus().isOrAfter(ChunkStatus.LIGHT) && chunkaccess.isLightCorrect(); ++ private static boolean isLighted(ChunkAccess chunk) { ++ return chunk.getStatus().isOrAfter(ChunkStatus.LIGHT) && chunk.isLightCorrect(); + } + +- public static ChunkStatus getStatusAroundFullChunk(int i) { +- return i >= ChunkStatus.STATUS_BY_RANGE.size() ? ChunkStatus.EMPTY : (i < 0 ? ChunkStatus.FULL : (ChunkStatus) ChunkStatus.STATUS_BY_RANGE.get(i)); ++ public static ChunkStatus getStatusAroundFullChunk(int radius) { ++ return radius >= ChunkStatus.STATUS_BY_RANGE.size() ? ChunkStatus.EMPTY : (radius < 0 ? ChunkStatus.FULL : (ChunkStatus) ChunkStatus.STATUS_BY_RANGE.get(radius)); + } + + public static int maxDistance() { + return ChunkStatus.STATUS_BY_RANGE.size(); + } + +- public static int getDistance(ChunkStatus chunkstatus) { +- return ChunkStatus.RANGE_BY_STATUS.getInt(chunkstatus.getIndex()); ++ public static int getDistance(ChunkStatus status) { ++ return ChunkStatus.RANGE_BY_STATUS.getInt(status.getIndex()); + } + +- ChunkStatus(@Nullable ChunkStatus chunkstatus, int i, boolean flag, EnumSet enumset, ChunkStatus.ChunkType chunkstatus_chunktype, ChunkStatus.GenerationTask chunkstatus_generationtask, ChunkStatus.LoadingTask chunkstatus_loadingtask) { +- this.parent = chunkstatus == null ? this : chunkstatus; +- this.generationTask = chunkstatus_generationtask; +- this.loadingTask = chunkstatus_loadingtask; +- this.range = i; +- this.hasLoadDependencies = flag; +- this.chunkType = chunkstatus_chunktype; +- this.heightmapsAfter = enumset; +- this.index = chunkstatus == null ? 0 : chunkstatus.getIndex() + 1; ++ ChunkStatus(@Nullable ChunkStatus parent, int range, boolean hasLoadDependencies, EnumSet heightmapsAfter, ChunkStatus.Type chunkType, ChunkStatus.GenerationTask generationTask, ChunkStatus.LoadingTask loadingTask) { ++ this.parent = parent == null ? this : parent; ++ this.generationTask = generationTask; ++ this.loadingTask = loadingTask; ++ this.range = range; ++ this.hasLoadDependencies = hasLoadDependencies; ++ this.chunkType = chunkType; ++ this.heightmapsAfter = heightmapsAfter; ++ this.index = parent == null ? 0 : parent.getIndex() + 1; + } + + public int getIndex() { +@@ -221,14 +221,14 @@ + return this.parent; + } + +- public CompletableFuture> generate(Executor executor, ServerLevel serverlevel, ChunkGenerator chunkgenerator, StructureTemplateManager structuretemplatemanager, ThreadedLevelLightEngine threadedlevellightengine, Function>> function, List list) { +- ChunkAccess chunkaccess = (ChunkAccess) list.get(list.size() / 2); +- ProfiledDuration profiledduration = JvmProfiler.INSTANCE.onChunkGenerate(chunkaccess.getPos(), serverlevel.dimension(), this.toString()); ++ public CompletableFuture> generate(Executor exectutor, ServerLevel level, ChunkGenerator chunkGenerator, StructureTemplateManager structureTemplateManager, ThreadedLevelLightEngine lightEngine, Function>> task, List cache) { ++ ChunkAccess ichunkaccess = (ChunkAccess) cache.get(cache.size() / 2); ++ ProfiledDuration profiledduration = JvmProfiler.INSTANCE.onChunkGenerate(ichunkaccess.getPos(), level.dimension(), this.toString()); + +- return this.generationTask.doWork(this, executor, serverlevel, chunkgenerator, structuretemplatemanager, threadedlevellightengine, function, list, chunkaccess).thenApply((either) -> { +- either.ifLeft((chunkaccess1) -> { +- if (chunkaccess1 instanceof ProtoChunk) { +- ProtoChunk protochunk = (ProtoChunk) chunkaccess1; ++ return this.generationTask.doWork(this, exectutor, level, chunkGenerator, structureTemplateManager, lightEngine, task, cache, ichunkaccess).thenApply((either) -> { ++ either.ifLeft((ichunkaccess1) -> { ++ if (ichunkaccess1 instanceof ProtoChunk) { ++ ProtoChunk protochunk = (ProtoChunk) ichunkaccess1; + + if (!protochunk.getStatus().isOrAfter(this)) { + protochunk.setStatus(this); +@@ -244,8 +244,8 @@ + }); + } + +- public CompletableFuture> load(ServerLevel serverlevel, StructureTemplateManager structuretemplatemanager, ThreadedLevelLightEngine threadedlevellightengine, Function>> function, ChunkAccess chunkaccess) { +- return this.loadingTask.doWork(this, serverlevel, structuretemplatemanager, threadedlevellightengine, function, chunkaccess); ++ public CompletableFuture> load(ServerLevel level, StructureTemplateManager structureTemplateManager, ThreadedLevelLightEngine lightEngine, Function>> task, ChunkAccess loadingChunk) { ++ return this.loadingTask.doWork(this, level, structureTemplateManager, lightEngine, task, loadingChunk); + } + + public int getRange() { +@@ -256,51 +256,49 @@ + return this.hasLoadDependencies; + } + +- public ChunkStatus.ChunkType getChunkType() { ++ public ChunkStatus.Type getChunkType() { + return this.chunkType; + } + +- public static ChunkStatus byName(String s) { +- return (ChunkStatus) BuiltInRegistries.CHUNK_STATUS.get(ResourceLocation.tryParse(s)); ++ public static ChunkStatus byName(String key) { ++ return (ChunkStatus) BuiltInRegistries.CHUNK_STATUS.get(ResourceLocation.tryParse(key)); + } + + public EnumSet heightmapsAfter() { + return this.heightmapsAfter; + } + +- public boolean isOrAfter(ChunkStatus chunkstatus) { +- return this.getIndex() >= chunkstatus.getIndex(); ++ public boolean isOrAfter(ChunkStatus status) { ++ return this.getIndex() >= status.getIndex(); + } + +- @Override + public String toString() { + return BuiltInRegistries.CHUNK_STATUS.getKey(this).toString(); + } + +- public static enum ChunkType { ++ public static enum Type { + + PROTOCHUNK, LEVELCHUNK; + +- private ChunkType() {} ++ private Type() {} + } + + private interface GenerationTask { + +- CompletableFuture> doWork(ChunkStatus status, Executor executor, ServerLevel level, ChunkGenerator chunkGenerator, StructureTemplateManager structureTemplateManager, ThreadedLevelLightEngine lightEngine, Function>> task, List cache, ChunkAccess loadingChunk); ++ CompletableFuture> doWork(ChunkStatus status, Executor executor, ServerLevel level, ChunkGenerator chunkGenerator, StructureTemplateManager structureTemplateManager, ThreadedLevelLightEngine lightEngine, Function>> task, List cache, ChunkAccess loadingChunk); + } + + private interface LoadingTask { + +- CompletableFuture> doWork(ChunkStatus status, ServerLevel level, StructureTemplateManager structureTemplateManager, ThreadedLevelLightEngine lightEngine, Function>> task, ChunkAccess chunk); ++ CompletableFuture> doWork(ChunkStatus status, ServerLevel level, StructureTemplateManager structureTemplateManager, ThreadedLevelLightEngine lightEngine, Function>> task, ChunkAccess chunk); + } + + private interface SimpleGenerationTask extends ChunkStatus.GenerationTask { + + @Override +- @Override +- default CompletableFuture> doWork(ChunkStatus chunkstatus, Executor executor, ServerLevel serverlevel, ChunkGenerator chunkgenerator, StructureTemplateManager structuretemplatemanager, ThreadedLevelLightEngine threadedlevellightengine, Function>> function, List list, ChunkAccess chunkaccess) { +- this.doWork(chunkstatus, serverlevel, chunkgenerator, list, chunkaccess); +- return CompletableFuture.completedFuture(Either.left(chunkaccess)); ++ default CompletableFuture> doWork(ChunkStatus status, Executor executor, ServerLevel level, ChunkGenerator chunkGenerator, StructureTemplateManager structureTemplateManager, ThreadedLevelLightEngine lightEngine, Function>> task, List cache, ChunkAccess loadingChunk) { ++ this.doWork(status, level, chunkGenerator, cache, loadingChunk); ++ return CompletableFuture.completedFuture(Either.left(loadingChunk)); + } + + void doWork(ChunkStatus status, ServerLevel level, ChunkGenerator generator, List cache, ChunkAccess loadingChunk); diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/DataLayer.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/DataLayer.java.patch new file mode 100644 index 0000000000..03b569a1c4 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/DataLayer.java.patch @@ -0,0 +1,133 @@ +--- a/net/minecraft/world/level/chunk/DataLayer.java ++++ b/net/minecraft/world/level/chunk/DataLayer.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.world.level.chunk; + + import java.util.Arrays; +@@ -19,69 +20,69 @@ + this(0); + } + +- public DataLayer(int i) { +- this.defaultValue = i; ++ public DataLayer(int size) { ++ this.defaultValue = size; + } + +- public DataLayer(byte[] abyte) { +- this.data = abyte; ++ public DataLayer(byte[] data) { ++ this.data = data; + this.defaultValue = 0; +- if (abyte.length != 2048) { +- throw (IllegalArgumentException) Util.pauseInIde(new IllegalArgumentException("DataLayer should be 2048 bytes not: " + abyte.length)); ++ if (data.length != 2048) { ++ throw (IllegalArgumentException) Util.pauseInIde(new IllegalArgumentException("DataLayer should be 2048 bytes not: " + data.length)); + } + } + +- public int get(int i, int j, int k) { +- return this.get(getIndex(i, j, k)); ++ public int get(int x, int y, int z) { ++ return this.get(getIndex(x, y, z)); + } + +- public void set(int i, int j, int k, int l) { +- this.set(getIndex(i, j, k), l); ++ public void set(int x, int y, int z, int value) { ++ this.set(getIndex(x, y, z), value); + } + +- private static int getIndex(int i, int j, int k) { +- return j << 8 | k << 4 | i; ++ private static int getIndex(int x, int y, int z) { ++ return y << 8 | z << 4 | x; + } + +- private int get(int i) { ++ private int get(int index) { + if (this.data == null) { + return this.defaultValue; + } else { +- int j = getByteIndex(i); +- int k = getNibbleIndex(i); ++ int j = getByteIndex(index); ++ int k = getNibbleIndex(index); + + return this.data[j] >> 4 * k & 15; + } + } + +- private void set(int i, int j) { ++ private void set(int index, int value) { + byte[] abyte = this.getData(); +- int k = getByteIndex(i); +- int l = getNibbleIndex(i); ++ int k = getByteIndex(index); ++ int l = getNibbleIndex(index); + int i1 = ~(15 << 4 * l); +- int j1 = (j & 15) << 4 * l; ++ int j1 = (value & 15) << 4 * l; + + abyte[k] = (byte) (abyte[k] & i1 | j1); + } + +- private static int getNibbleIndex(int i) { +- return i & 1; ++ private static int getNibbleIndex(int index) { ++ return index & 1; + } + +- private static int getByteIndex(int i) { +- return i >> 1; ++ private static int getByteIndex(int index) { ++ return index >> 1; + } + +- public void fill(int i) { +- this.defaultValue = i; ++ public void fill(int defaultValue) { ++ this.defaultValue = defaultValue; + this.data = null; + } + +- private static byte packFilled(int i) { +- byte b0 = (byte) i; ++ private static byte packFilled(int value) { ++ byte b0 = (byte) value; + + for (int j = 4; j < 8; j += 4) { +- b0 = (byte) (b0 | i << j); ++ b0 = (byte) (b0 | value << j); + } + + return b0; +@@ -102,7 +103,6 @@ + return this.data == null ? new DataLayer(this.defaultValue) : new DataLayer((byte[]) this.data.clone()); + } + +- @Override + public String toString() { + StringBuilder stringbuilder = new StringBuilder(); + +@@ -121,7 +121,7 @@ + } + + @VisibleForDebug +- public String layerToString(int i) { ++ public String layerToString(int unused) { + StringBuilder stringbuilder = new StringBuilder(); + + for (int j = 0; j < 256; ++j) { +@@ -138,8 +138,8 @@ + return this.data == null; + } + +- public boolean isDefinitelyFilledWith(int i) { +- return this.data == null && this.defaultValue == i; ++ public boolean isDefinitelyFilledWith(int value) { ++ return this.data == null && this.defaultValue == value; + } + + public boolean isEmpty() { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/LevelChunk.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/LevelChunk.java.patch new file mode 100644 index 0000000000..10593a78a2 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/LevelChunk.java.patch @@ -0,0 +1,1151 @@ +--- a/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/net/minecraft/world/level/chunk/LevelChunk.java +@@ -36,7 +36,7 @@ + import net.minecraft.world.level.block.entity.BlockEntityTicker; + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.TickingBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.EuclideanGameEventListenerRegistry; + import net.minecraft.world.level.gameevent.GameEventListener; + import net.minecraft.world.level.gameevent.GameEventListenerRegistry; +@@ -56,30 +56,26 @@ + static final Logger LOGGER = LogUtils.getLogger(); + private static final TickingBlockEntity NULL_TICKER = new TickingBlockEntity() { + @Override +- @Override + public void tick() {} + + @Override +- @Override + public boolean isRemoved() { + return true; + } + + @Override +- @Override + public BlockPos getPos() { + return BlockPos.ZERO; + } + + @Override +- @Override + public String getType() { + return ""; + } + }; + private final Map tickersInLevel; +- private boolean loaded; +- final Level level; ++ public boolean loaded; ++ public final ServerLevel level; // CraftBukkit - type + @Nullable + private Supplier fullStatus; + @Nullable +@@ -88,50 +84,55 @@ + private final LevelChunkTicks blockTicks; + private final LevelChunkTicks fluidTicks; + +- public LevelChunk(Level level, ChunkPos chunkpos) { +- this(level, chunkpos, UpgradeData.EMPTY, new LevelChunkTicks<>(), new LevelChunkTicks<>(), 0L, (LevelChunkSection[]) null, (LevelChunk.PostLoadProcessor) null, (BlendingData) null); ++ public LevelChunk(Level level, ChunkPos pos) { ++ this(level, pos, UpgradeData.EMPTY, new LevelChunkTicks<>(), new LevelChunkTicks<>(), 0L, (LevelChunkSection[]) null, (LevelChunk.PostLoadProcessor) null, (BlendingData) null); + } + +- public LevelChunk(Level level, ChunkPos chunkpos, UpgradeData upgradedata, LevelChunkTicks levelchunkticks, LevelChunkTicks levelchunkticks1, long i, @Nullable LevelChunkSection[] alevelchunksection, @Nullable LevelChunk.PostLoadProcessor levelchunk_postloadprocessor, @Nullable BlendingData blendingdata) { +- super(chunkpos, upgradedata, level, level.registryAccess().registryOrThrow(Registries.BIOME), i, alevelchunksection, blendingdata); ++ public LevelChunk(Level level, ChunkPos pos, UpgradeData data, LevelChunkTicks blockTicks, LevelChunkTicks fluidTicks, long inhabitedTime, @Nullable LevelChunkSection[] achunksection, @Nullable LevelChunk.PostLoadProcessor sections, @Nullable BlendingData postLoad) { ++ super(pos, data, level, level.registryAccess().registryOrThrow(Registries.BIOME), inhabitedTime, achunksection, postLoad); + this.tickersInLevel = Maps.newHashMap(); +- this.level = level; ++ this.level = (ServerLevel) level; // CraftBukkit - type + this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap(); +- Heightmap.Types[] aheightmap_types = Heightmap.Types.values(); +- int j = aheightmap_types.length; ++ Heightmap.Types[] aheightmap_type = Heightmap.Types.values(); ++ int j = aheightmap_type.length; + + for (int k = 0; k < j; ++k) { +- Heightmap.Types heightmap_types = aheightmap_types[k]; ++ Heightmap.Types heightmap_type = aheightmap_type[k]; + +- if (ChunkStatus.FULL.heightmapsAfter().contains(heightmap_types)) { +- this.heightmaps.put(heightmap_types, new Heightmap(this, heightmap_types)); ++ if (ChunkStatus.FULL.heightmapsAfter().contains(heightmap_type)) { ++ this.heightmaps.put(heightmap_type, new Heightmap(this, heightmap_type)); + } + } + +- this.postLoad = levelchunk_postloadprocessor; +- this.blockTicks = levelchunkticks; +- this.fluidTicks = levelchunkticks1; ++ this.postLoad = sections; ++ this.blockTicks = blockTicks; ++ this.fluidTicks = fluidTicks; + } + +- public LevelChunk(ServerLevel serverlevel, ProtoChunk protochunk, @Nullable LevelChunk.PostLoadProcessor levelchunk_postloadprocessor) { +- this(serverlevel, protochunk.getPos(), protochunk.getUpgradeData(), protochunk.unpackBlockTicks(), protochunk.unpackFluidTicks(), protochunk.getInhabitedTime(), protochunk.getSections(), levelchunk_postloadprocessor, protochunk.getBlendingData()); +- Iterator iterator = protochunk.getBlockEntities().values().iterator(); ++ // CraftBukkit start ++ public boolean mustNotSave; ++ public boolean needsDecoration; ++ // CraftBukkit end + ++ public LevelChunk(ServerLevel level, ProtoChunk chunk, @Nullable LevelChunk.PostLoadProcessor postLoad) { ++ this(level, chunk.getPos(), chunk.getUpgradeData(), chunk.unpackBlockTicks(), chunk.unpackFluidTicks(), chunk.getInhabitedTime(), chunk.getSections(), postLoad, chunk.getBlendingData()); ++ Iterator iterator = chunk.getBlockEntities().values().iterator(); ++ + while (iterator.hasNext()) { +- BlockEntity blockentity = (BlockEntity) iterator.next(); ++ BlockEntity tileentity = (BlockEntity) iterator.next(); + +- this.setBlockEntity(blockentity); ++ this.setBlockEntity(tileentity); + } + +- this.pendingBlockEntities.putAll(protochunk.getBlockEntityNbts()); ++ this.pendingBlockEntities.putAll(chunk.getBlockEntityNbts()); + +- for (int i = 0; i < protochunk.getPostProcessing().length; ++i) { +- this.postProcessing[i] = protochunk.getPostProcessing()[i]; ++ for (int i = 0; i < chunk.getPostProcessing().length; ++i) { ++ this.postProcessing[i] = chunk.getPostProcessing()[i]; + } + +- this.setAllStarts(protochunk.getAllStarts()); +- this.setAllReferences(protochunk.getAllReferences()); +- iterator = protochunk.getHeightmaps().iterator(); ++ this.setAllStarts(chunk.getAllStarts()); ++ this.setAllReferences(chunk.getAllReferences()); ++ iterator = chunk.getHeightmaps().iterator(); + + while (iterator.hasNext()) { + Entry entry = (Entry) iterator.next(); +@@ -141,82 +142,81 @@ + } + } + +- this.skyLightSources = protochunk.skyLightSources; +- this.setLightCorrect(protochunk.isLightCorrect()); ++ this.skyLightSources = chunk.skyLightSources; ++ this.setLightCorrect(chunk.isLightCorrect()); + this.unsaved = true; ++ this.needsDecoration = true; // CraftBukkit ++ // CraftBukkit start ++ this.persistentDataContainer = chunk.persistentDataContainer; // SPIGOT-6814: copy PDC to account for 1.17 to 1.18 chunk upgrading. ++ // CraftBukkit end + } + + @Override +- @Override + public TickContainerAccess getBlockTicks() { + return this.blockTicks; + } + + @Override +- @Override + public TickContainerAccess getFluidTicks() { + return this.fluidTicks; + } + + @Override +- @Override +- public ChunkAccess.TicksToSave getTicksForSerialization() { +- return new ChunkAccess.TicksToSave(this.blockTicks, this.fluidTicks); ++ public ChunkAccess.a getTicksForSerialization() { ++ return new ChunkAccess.a(this.blockTicks, this.fluidTicks); + } + + @Override +- @Override +- public GameEventListenerRegistry getListenerRegistry(int i) { +- Level level = this.level; ++ public GameEventListenerRegistry getListenerRegistry(int sectionY) { ++ Level world = this.level; + +- if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; + +- return (GameEventListenerRegistry) this.gameEventListenerRegistrySections.computeIfAbsent(i, (j) -> { +- return new EuclideanGameEventListenerRegistry(serverlevel, i, this::removeGameEventListenerRegistry); ++ return (GameEventListenerRegistry) this.gameEventListenerRegistrySections.computeIfAbsent(sectionY, (j) -> { ++ return new EuclideanGameEventListenerRegistry(worldserver, sectionY, this::removeGameEventListenerRegistry); + }); + } else { +- return super.getListenerRegistry(i); ++ return super.getListenerRegistry(sectionY); + } + } + + @Override +- @Override +- public BlockState getBlockState(BlockPos blockpos) { +- int i = blockpos.getX(); +- int j = blockpos.getY(); +- int k = blockpos.getZ(); ++ public IBlockData getBlockState(BlockPos pos) { ++ int i = pos.getX(); ++ int j = pos.getY(); ++ int k = pos.getZ(); + + if (this.level.isDebug()) { +- BlockState blockstate = null; ++ IBlockData iblockdata = null; + + if (j == 60) { +- blockstate = Blocks.BARRIER.defaultBlockState(); ++ iblockdata = Blocks.BARRIER.defaultBlockState(); + } + + if (j == 70) { +- blockstate = DebugLevelSource.getBlockStateFor(i, k); ++ iblockdata = DebugLevelSource.getBlockStateFor(i, k); + } + +- return blockstate == null ? Blocks.AIR.defaultBlockState() : blockstate; ++ return iblockdata == null ? Blocks.AIR.defaultBlockState() : iblockdata; + } else { + try { + int l = this.getSectionIndex(j); + + if (l >= 0 && l < this.sections.length) { +- LevelChunkSection levelchunksection = this.sections[l]; ++ LevelChunkSection chunksection = this.sections[l]; + +- if (!levelchunksection.hasOnlyAir()) { +- return levelchunksection.getBlockState(i & 15, j & 15, k & 15); ++ if (!chunksection.hasOnlyAir()) { ++ return chunksection.getBlockState(i & 15, j & 15, k & 15); + } + } + + return Blocks.AIR.defaultBlockState(); + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting block state"); +- CrashReportCategory crashreportcategory = crashreport.addCategory("Block being got"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being got"); + +- crashreportcategory.setDetail("Location", () -> { ++ crashreportsystemdetails.setDetail("Location", () -> { + return CrashReportCategory.formatLocation(this, i, j, k); + }); + throw new ReportedException(crashreport); +@@ -225,107 +225,113 @@ + } + + @Override +- @Override +- public FluidState getFluidState(BlockPos blockpos) { +- return this.getFluidState(blockpos.getX(), blockpos.getY(), blockpos.getZ()); ++ public FluidState getFluidState(BlockPos pos) { ++ return this.getFluidState(pos.getX(), pos.getY(), pos.getZ()); + } + +- public FluidState getFluidState(int i, int j, int k) { ++ public FluidState getFluidState(int x, int y, int z) { + try { +- int l = this.getSectionIndex(j); ++ int l = this.getSectionIndex(y); + + if (l >= 0 && l < this.sections.length) { +- LevelChunkSection levelchunksection = this.sections[l]; ++ LevelChunkSection chunksection = this.sections[l]; + +- if (!levelchunksection.hasOnlyAir()) { +- return levelchunksection.getFluidState(i & 15, j & 15, k & 15); ++ if (!chunksection.hasOnlyAir()) { ++ return chunksection.getFluidState(x & 15, y & 15, z & 15); + } + } + + return Fluids.EMPTY.defaultFluidState(); + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting fluid state"); +- CrashReportCategory crashreportcategory = crashreport.addCategory("Block being got"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being got"); + +- crashreportcategory.setDetail("Location", () -> { +- return CrashReportCategory.formatLocation(this, i, j, k); ++ crashreportsystemdetails.setDetail("Location", () -> { ++ return CrashReportCategory.formatLocation(this, x, y, z); + }); + throw new ReportedException(crashreport); + } + } + ++ // CraftBukkit start + @Nullable + @Override +- @Override +- public BlockState setBlockState(BlockPos blockpos, BlockState blockstate, boolean flag) { +- int i = blockpos.getY(); +- LevelChunkSection levelchunksection = this.getSection(this.getSectionIndex(i)); +- boolean flag1 = levelchunksection.hasOnlyAir(); ++ public IBlockData setBlockState(BlockPos pos, IBlockData state, boolean isMoving) { ++ return this.setBlockState(pos, state, isMoving, true); ++ } + +- if (flag1 && blockstate.isAir()) { ++ @Nullable ++ public IBlockData setBlockState(BlockPos blockposition, IBlockData iblockdata, boolean flag, boolean doPlace) { ++ // CraftBukkit end ++ int i = blockposition.getY(); ++ LevelChunkSection chunksection = this.getSection(this.getSectionIndex(i)); ++ boolean flag1 = chunksection.hasOnlyAir(); ++ ++ if (flag1 && iblockdata.isAir()) { + return null; + } else { +- int j = blockpos.getX() & 15; ++ int j = blockposition.getX() & 15; + int k = i & 15; +- int l = blockpos.getZ() & 15; +- BlockState blockstate1 = levelchunksection.setBlockState(j, k, l, blockstate); ++ int l = blockposition.getZ() & 15; ++ IBlockData iblockdata1 = chunksection.setBlockState(j, k, l, iblockdata); + +- if (blockstate1 == blockstate) { ++ if (iblockdata1 == iblockdata) { + return null; + } else { +- Block block = blockstate.getBlock(); ++ Block block = iblockdata.getBlock(); + +- ((Heightmap) this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING)).update(j, i, l, blockstate); +- ((Heightmap) this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES)).update(j, i, l, blockstate); +- ((Heightmap) this.heightmaps.get(Heightmap.Types.OCEAN_FLOOR)).update(j, i, l, blockstate); +- ((Heightmap) this.heightmaps.get(Heightmap.Types.WORLD_SURFACE)).update(j, i, l, blockstate); +- boolean flag2 = levelchunksection.hasOnlyAir(); ++ ((Heightmap) this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING)).update(j, i, l, iblockdata); ++ ((Heightmap) this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES)).update(j, i, l, iblockdata); ++ ((Heightmap) this.heightmaps.get(Heightmap.Types.OCEAN_FLOOR)).update(j, i, l, iblockdata); ++ ((Heightmap) this.heightmaps.get(Heightmap.Types.WORLD_SURFACE)).update(j, i, l, iblockdata); ++ boolean flag2 = chunksection.hasOnlyAir(); + + if (flag1 != flag2) { +- this.level.getChunkSource().getLightEngine().updateSectionStatus(blockpos, flag2); ++ this.level.getChunkSource().getLightEngine().updateSectionStatus(blockposition, flag2); + } + +- if (LightEngine.hasDifferentLightProperties(this, blockpos, blockstate1, blockstate)) { +- ProfilerFiller profilerfiller = this.level.getProfiler(); ++ if (LightEngine.hasDifferentLightProperties(this, blockposition, iblockdata1, iblockdata)) { ++ ProfilerFiller gameprofilerfiller = this.level.getProfiler(); + +- profilerfiller.push("updateSkyLightSources"); ++ gameprofilerfiller.push("updateSkyLightSources"); + this.skyLightSources.update(this, j, i, l); +- profilerfiller.popPush("queueCheckLight"); +- this.level.getChunkSource().getLightEngine().checkBlock(blockpos); +- profilerfiller.pop(); ++ gameprofilerfiller.popPush("queueCheckLight"); ++ this.level.getChunkSource().getLightEngine().checkBlock(blockposition); ++ gameprofilerfiller.pop(); + } + +- boolean flag3 = blockstate1.hasBlockEntity(); ++ boolean flag3 = iblockdata1.hasBlockEntity(); + + if (!this.level.isClientSide) { +- blockstate1.onRemove(this.level, blockpos, blockstate, flag); +- } else if (!blockstate1.is(block) && flag3) { +- this.removeBlockEntity(blockpos); ++ iblockdata1.onRemove(this.level, blockposition, iblockdata, flag); ++ } else if (!iblockdata1.is(block) && flag3) { ++ this.removeBlockEntity(blockposition); + } + +- if (!levelchunksection.getBlockState(j, k, l).is(block)) { ++ if (!chunksection.getBlockState(j, k, l).is(block)) { + return null; + } else { +- if (!this.level.isClientSide) { +- blockstate.onPlace(this.level, blockpos, blockstate1, flag); ++ // CraftBukkit - Don't place while processing the BlockPlaceEvent, unless it's a BlockContainer. Prevents blocks such as TNT from activating when cancelled. ++ if (!this.level.isClientSide && doPlace && (!this.level.captureBlockStates || block instanceof net.minecraft.world.level.block.BaseEntityBlock)) { ++ iblockdata.onPlace(this.level, blockposition, iblockdata1, flag); + } + +- if (blockstate.hasBlockEntity()) { +- BlockEntity blockentity = this.getBlockEntity(blockpos, LevelChunk.EntityCreationType.CHECK); ++ if (iblockdata.hasBlockEntity()) { ++ BlockEntity tileentity = this.getBlockEntity(blockposition, LevelChunk.EnumTileEntityState.CHECK); + +- if (blockentity == null) { +- blockentity = ((EntityBlock) block).newBlockEntity(blockpos, blockstate); +- if (blockentity != null) { +- this.addAndRegisterBlockEntity(blockentity); ++ if (tileentity == null) { ++ tileentity = ((EntityBlock) block).newBlockEntity(blockposition, iblockdata); ++ if (tileentity != null) { ++ this.addAndRegisterBlockEntity(tileentity); + } + } else { +- blockentity.setBlockState(blockstate); +- this.updateBlockEntityTicker(blockentity); ++ tileentity.setBlockState(iblockdata); ++ this.updateBlockEntityTicker(tileentity); + } + } + + this.unsaved = true; +- return blockstate1; ++ return iblockdata1; + } + } + } +@@ -334,66 +340,69 @@ + /** @deprecated */ + @Deprecated + @Override +- @Override + public void addEntity(Entity entity) {} + + @Nullable +- private BlockEntity createBlockEntity(BlockPos blockpos) { +- BlockState blockstate = this.getBlockState(blockpos); ++ private BlockEntity createBlockEntity(BlockPos pos) { ++ IBlockData iblockdata = this.getBlockState(pos); + +- return !blockstate.hasBlockEntity() ? null : ((EntityBlock) blockstate.getBlock()).newBlockEntity(blockpos, blockstate); ++ return !iblockdata.hasBlockEntity() ? null : ((EntityBlock) iblockdata.getBlock()).newBlockEntity(pos, iblockdata); + } + + @Nullable + @Override +- @Override +- public BlockEntity getBlockEntity(BlockPos blockpos) { +- return this.getBlockEntity(blockpos, LevelChunk.EntityCreationType.CHECK); ++ public BlockEntity getBlockEntity(BlockPos pos) { ++ return this.getBlockEntity(pos, LevelChunk.EnumTileEntityState.CHECK); + } + + @Nullable +- public BlockEntity getBlockEntity(BlockPos blockpos, LevelChunk.EntityCreationType levelchunk_entitycreationtype) { +- BlockEntity blockentity = (BlockEntity) this.blockEntities.get(blockpos); ++ public BlockEntity getBlockEntity(BlockPos pos, LevelChunk.EnumTileEntityState creationType) { ++ // CraftBukkit start ++ BlockEntity tileentity = level.capturedTileEntities.get(pos); ++ if (tileentity == null) { ++ tileentity = (BlockEntity) this.blockEntities.get(pos); ++ } ++ // CraftBukkit end + +- if (blockentity == null) { +- CompoundTag compoundtag = (CompoundTag) this.pendingBlockEntities.remove(blockpos); ++ if (tileentity == null) { ++ CompoundTag nbttagcompound = (CompoundTag) this.pendingBlockEntities.remove(pos); + +- if (compoundtag != null) { +- BlockEntity blockentity1 = this.promotePendingBlockEntity(blockpos, compoundtag); ++ if (nbttagcompound != null) { ++ BlockEntity tileentity1 = this.promotePendingBlockEntity(pos, nbttagcompound); + +- if (blockentity1 != null) { +- return blockentity1; ++ if (tileentity1 != null) { ++ return tileentity1; + } + } + } + +- if (blockentity == null) { +- if (levelchunk_entitycreationtype == LevelChunk.EntityCreationType.IMMEDIATE) { +- blockentity = this.createBlockEntity(blockpos); +- if (blockentity != null) { +- this.addAndRegisterBlockEntity(blockentity); ++ if (tileentity == null) { ++ if (creationType == LevelChunk.EnumTileEntityState.IMMEDIATE) { ++ tileentity = this.createBlockEntity(pos); ++ if (tileentity != null) { ++ this.addAndRegisterBlockEntity(tileentity); + } + } +- } else if (blockentity.isRemoved()) { +- this.blockEntities.remove(blockpos); ++ } else if (tileentity.isRemoved()) { ++ this.blockEntities.remove(pos); + return null; + } + +- return blockentity; ++ return tileentity; + } + +- public void addAndRegisterBlockEntity(BlockEntity blockentity) { +- this.setBlockEntity(blockentity); ++ public void addAndRegisterBlockEntity(BlockEntity blockEntity) { ++ this.setBlockEntity(blockEntity); + if (this.isInLevel()) { +- Level level = this.level; ++ Level world = this.level; + +- if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; + +- this.addGameEventListener(blockentity, serverlevel); ++ this.addGameEventListener(blockEntity, worldserver); + } + +- this.updateBlockEntityTicker(blockentity); ++ this.updateBlockEntityTicker(blockEntity); + } + + } +@@ -402,91 +411,101 @@ + return this.loaded || this.level.isClientSide(); + } + +- boolean isTicking(BlockPos blockpos) { +- if (!this.level.getWorldBorder().isWithinBounds(blockpos)) { ++ boolean isTicking(BlockPos pos) { ++ if (!this.level.getWorldBorder().isWithinBounds(pos)) { + return false; + } else { +- Level level = this.level; ++ Level world = this.level; + +- if (!(level instanceof ServerLevel)) { ++ if (!(world instanceof ServerLevel)) { + return true; + } else { +- ServerLevel serverlevel = (ServerLevel) level; ++ ServerLevel worldserver = (ServerLevel) world; + +- return this.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING) && serverlevel.areEntitiesLoaded(ChunkPos.asLong(blockpos)); ++ return this.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING) && worldserver.areEntitiesLoaded(ChunkPos.asLong(pos)); + } + } + } + + @Override +- @Override +- public void setBlockEntity(BlockEntity blockentity) { +- BlockPos blockpos = blockentity.getBlockPos(); ++ public void setBlockEntity(BlockEntity blockEntity) { ++ BlockPos blockposition = blockEntity.getBlockPos(); + +- if (this.getBlockState(blockpos).hasBlockEntity()) { +- blockentity.setLevel(this.level); +- blockentity.clearRemoved(); +- BlockEntity blockentity1 = (BlockEntity) this.blockEntities.put(blockpos.immutable(), blockentity); ++ if (this.getBlockState(blockposition).hasBlockEntity()) { ++ blockEntity.setLevel(this.level); ++ blockEntity.clearRemoved(); ++ BlockEntity tileentity1 = (BlockEntity) this.blockEntities.put(blockposition.immutable(), blockEntity); + +- if (blockentity1 != null && blockentity1 != blockentity) { +- blockentity1.setRemoved(); ++ if (tileentity1 != null && tileentity1 != blockEntity) { ++ tileentity1.setRemoved(); + } + ++ // CraftBukkit start ++ } else { ++ System.out.println("Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() ++ + " (" + getBlockState(blockposition) + ") where there was no entity tile!"); ++ System.out.println("Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); ++ new Exception().printStackTrace(); ++ // CraftBukkit end + } + } + + @Nullable + @Override +- @Override +- public CompoundTag getBlockEntityNbtForSaving(BlockPos blockpos) { +- BlockEntity blockentity = this.getBlockEntity(blockpos); +- CompoundTag compoundtag; ++ public CompoundTag getBlockEntityNbtForSaving(BlockPos pos) { ++ BlockEntity tileentity = this.getBlockEntity(pos); ++ CompoundTag nbttagcompound; + +- if (blockentity != null && !blockentity.isRemoved()) { +- compoundtag = blockentity.saveWithFullMetadata(); +- compoundtag.putBoolean("keepPacked", false); +- return compoundtag; ++ if (tileentity != null && !tileentity.isRemoved()) { ++ nbttagcompound = tileentity.saveWithFullMetadata(); ++ nbttagcompound.putBoolean("keepPacked", false); ++ return nbttagcompound; + } else { +- compoundtag = (CompoundTag) this.pendingBlockEntities.get(blockpos); +- if (compoundtag != null) { +- compoundtag = compoundtag.copy(); +- compoundtag.putBoolean("keepPacked", true); ++ nbttagcompound = (CompoundTag) this.pendingBlockEntities.get(pos); ++ if (nbttagcompound != null) { ++ nbttagcompound = nbttagcompound.copy(); ++ nbttagcompound.putBoolean("keepPacked", true); + } + +- return compoundtag; ++ return nbttagcompound; + } + } + + @Override +- @Override +- public void removeBlockEntity(BlockPos blockpos) { ++ public void removeBlockEntity(BlockPos pos) { + if (this.isInLevel()) { +- BlockEntity blockentity = (BlockEntity) this.blockEntities.remove(blockpos); ++ BlockEntity tileentity = (BlockEntity) this.blockEntities.remove(pos); + +- if (blockentity != null) { +- Level level = this.level; ++ // CraftBukkit start - SPIGOT-5561: Also remove from pending map ++ if (!pendingBlockEntities.isEmpty()) { ++ pendingBlockEntities.remove(pos); ++ } ++ // CraftBukkit end + +- if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; ++ if (tileentity != null) { ++ Level world = this.level; + +- this.removeGameEventListener(blockentity, serverlevel); ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ ++ this.removeGameEventListener(tileentity, worldserver); + } + +- blockentity.setRemoved(); ++ tileentity.setRemoved(); + } + } + +- this.removeBlockEntityTicker(blockpos); ++ this.removeBlockEntityTicker(pos); + } + +- private void removeGameEventListener(T t0, ServerLevel serverlevel) { +- Block block = t0.getBlockState().getBlock(); ++ private void removeGameEventListener(T blockEntity, ServerLevel level) { ++ Block block = blockEntity.getBlockState().getBlock(); + + if (block instanceof EntityBlock) { +- GameEventListener gameeventlistener = ((EntityBlock) block).getListener(serverlevel, t0); ++ GameEventListener gameeventlistener = ((EntityBlock) block).getListener(level, blockEntity); + + if (gameeventlistener != null) { +- int i = SectionPos.blockToSectionCoord(t0.getBlockPos().getY()); ++ int i = SectionPos.blockToSectionCoord(blockEntity.getBlockPos().getY()); + GameEventListenerRegistry gameeventlistenerregistry = this.getListenerRegistry(i); + + gameeventlistenerregistry.unregister(gameeventlistener); +@@ -495,15 +514,15 @@ + + } + +- private void removeGameEventListenerRegistry(int i) { +- this.gameEventListenerRegistrySections.remove(i); ++ private void removeGameEventListenerRegistry(int sectionY) { ++ this.gameEventListenerRegistrySections.remove(sectionY); + } + +- private void removeBlockEntityTicker(BlockPos blockpos) { +- LevelChunk.RebindableTickingBlockEntityWrapper levelchunk_rebindabletickingblockentitywrapper = (LevelChunk.RebindableTickingBlockEntityWrapper) this.tickersInLevel.remove(blockpos); ++ private void removeBlockEntityTicker(BlockPos pos) { ++ LevelChunk.RebindableTickingBlockEntityWrapper chunk_d = (LevelChunk.RebindableTickingBlockEntityWrapper) this.tickersInLevel.remove(pos); + +- if (levelchunk_rebindabletickingblockentitywrapper != null) { +- levelchunk_rebindabletickingblockentitywrapper.rebind(LevelChunk.NULL_TICKER); ++ if (chunk_d != null) { ++ chunk_d.rebind(LevelChunk.NULL_TICKER); + } + + } +@@ -516,61 +535,112 @@ + + } + ++ // CraftBukkit start ++ public void loadCallback() { ++ org.bukkit.Server server = this.level.getCraftServer(); ++ if (server != null) { ++ /* ++ * If it's a new world, the first few chunks are generated inside ++ * the World constructor. We can't reliably alter that, so we have ++ * no way of creating a CraftWorld/CraftServer at that point. ++ */ ++ org.bukkit.Chunk bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this); ++ server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(bukkitChunk, this.needsDecoration)); ++ ++ if (this.needsDecoration) { ++ this.needsDecoration = false; ++ java.util.Random random = new java.util.Random(); ++ random.setSeed(level.getSeed()); ++ long xRand = random.nextLong() / 2L * 2L + 1L; ++ long zRand = random.nextLong() / 2L * 2L + 1L; ++ random.setSeed((long) this.chunkPos.x * xRand + (long) this.chunkPos.z * zRand ^ level.getSeed()); ++ ++ org.bukkit.World world = this.level.getWorld(); ++ if (world != null) { ++ this.level.populating = true; ++ try { ++ for (org.bukkit.generator.BlockPopulator populator : world.getPopulators()) { ++ populator.populate(world, random, bukkitChunk); ++ } ++ } finally { ++ this.level.populating = false; ++ } ++ } ++ server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk)); ++ } ++ } ++ } ++ ++ public void unloadCallback() { ++ org.bukkit.Server server = this.level.getCraftServer(); ++ org.bukkit.Chunk bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this); ++ org.bukkit.event.world.ChunkUnloadEvent unloadEvent = new org.bukkit.event.world.ChunkUnloadEvent(bukkitChunk, this.isUnsaved()); ++ server.getPluginManager().callEvent(unloadEvent); ++ // note: saving can be prevented, but not forced if no saving is actually required ++ this.mustNotSave = !unloadEvent.isSaveChunk(); ++ } ++ ++ @Override ++ public boolean isUnsaved() { ++ return super.isUnsaved() && !this.mustNotSave; ++ } ++ // CraftBukkit end ++ + public boolean isEmpty() { + return false; + } + +- public void replaceWithPacketData(FriendlyByteBuf friendlybytebuf, CompoundTag compoundtag, Consumer consumer) { ++ public void replaceWithPacketData(FriendlyByteBuf buffer, CompoundTag tag, Consumer outputTagConsumer) { + this.clearAllBlockEntities(); +- LevelChunkSection[] alevelchunksection = this.sections; +- int i = alevelchunksection.length; ++ LevelChunkSection[] achunksection = this.sections; ++ int i = achunksection.length; + + int j; + + for (j = 0; j < i; ++j) { +- LevelChunkSection levelchunksection = alevelchunksection[j]; ++ LevelChunkSection chunksection = achunksection[j]; + +- levelchunksection.read(friendlybytebuf); ++ chunksection.read(buffer); + } + +- Heightmap.Types[] aheightmap_types = Heightmap.Types.values(); ++ Heightmap.Types[] aheightmap_type = Heightmap.Types.values(); + +- i = aheightmap_types.length; ++ i = aheightmap_type.length; + + for (j = 0; j < i; ++j) { +- Heightmap.Types heightmap_types = aheightmap_types[j]; +- String s = heightmap_types.getSerializationKey(); ++ Heightmap.Types heightmap_type = aheightmap_type[j]; ++ String s = heightmap_type.getSerializationKey(); + +- if (compoundtag.contains(s, 12)) { +- this.setHeightmap(heightmap_types, compoundtag.getLongArray(s)); ++ if (tag.contains(s, 12)) { ++ this.setHeightmap(heightmap_type, tag.getLongArray(s)); + } + } + + this.initializeLightSources(); +- consumer.accept((blockpos, blockentitytype, compoundtag1) -> { +- BlockEntity blockentity = this.getBlockEntity(blockpos, LevelChunk.EntityCreationType.IMMEDIATE); ++ outputTagConsumer.accept((blockposition, tileentitytypes, nbttagcompound1) -> { ++ BlockEntity tileentity = this.getBlockEntity(blockposition, LevelChunk.EnumTileEntityState.IMMEDIATE); + +- if (blockentity != null && compoundtag1 != null && blockentity.getType() == blockentitytype) { +- blockentity.load(compoundtag1); ++ if (tileentity != null && nbttagcompound1 != null && tileentity.getType() == tileentitytypes) { ++ tileentity.load(nbttagcompound1); + } + + }); + } + +- public void replaceBiomes(FriendlyByteBuf friendlybytebuf) { +- LevelChunkSection[] alevelchunksection = this.sections; +- int i = alevelchunksection.length; ++ public void replaceBiomes(FriendlyByteBuf buffer) { ++ LevelChunkSection[] achunksection = this.sections; ++ int i = achunksection.length; + + for (int j = 0; j < i; ++j) { +- LevelChunkSection levelchunksection = alevelchunksection[j]; ++ LevelChunkSection chunksection = achunksection[j]; + +- levelchunksection.readBiomes(friendlybytebuf); ++ chunksection.readBiomes(buffer); + } + + } + +- public void setLoaded(boolean flag) { +- this.loaded = flag; ++ public void setLoaded(boolean loaded) { ++ this.loaded = loaded; + } + + public Level getLevel() { +@@ -582,7 +652,7 @@ + } + + public void postProcessGeneration() { +- ChunkPos chunkpos = this.getPos(); ++ ChunkPos chunkcoordintpair = this.getPos(); + + for (int i = 0; i < this.postProcessing.length; ++i) { + if (this.postProcessing[i] != null) { +@@ -590,18 +660,18 @@ + + while (shortlistiterator.hasNext()) { + Short oshort = (Short) shortlistiterator.next(); +- BlockPos blockpos = ProtoChunk.unpackOffsetCoordinates(oshort, this.getSectionYFromSectionIndex(i), chunkpos); +- BlockState blockstate = this.getBlockState(blockpos); +- FluidState fluidstate = blockstate.getFluidState(); ++ BlockPos blockposition = ProtoChunk.unpackOffsetCoordinates(oshort, this.getSectionYFromSectionIndex(i), chunkcoordintpair); ++ IBlockData iblockdata = this.getBlockState(blockposition); ++ FluidState fluid = iblockdata.getFluidState(); + +- if (!fluidstate.isEmpty()) { +- fluidstate.tick(this.level, blockpos); ++ if (!fluid.isEmpty()) { ++ fluid.tick(this.level, blockposition); + } + +- if (!(blockstate.getBlock() instanceof LiquidBlock)) { +- BlockState blockstate1 = Block.updateFromNeighbourShapes(blockstate, this.level, blockpos); ++ if (!(iblockdata.getBlock() instanceof LiquidBlock)) { ++ IBlockData iblockdata1 = Block.updateFromNeighbourShapes(iblockdata, this.level, blockposition); + +- this.level.setBlock(blockpos, blockstate1, 20); ++ this.level.setBlock(blockposition, iblockdata1, 20); + } + } + +@@ -612,9 +682,9 @@ + UnmodifiableIterator unmodifiableiterator = ImmutableList.copyOf(this.pendingBlockEntities.keySet()).iterator(); + + while (unmodifiableiterator.hasNext()) { +- BlockPos blockpos1 = (BlockPos) unmodifiableiterator.next(); ++ BlockPos blockposition1 = (BlockPos) unmodifiableiterator.next(); + +- this.getBlockEntity(blockpos1); ++ this.getBlockEntity(blockposition1); + } + + this.pendingBlockEntities.clear(); +@@ -622,48 +692,47 @@ + } + + @Nullable +- private BlockEntity promotePendingBlockEntity(BlockPos blockpos, CompoundTag compoundtag) { +- BlockState blockstate = this.getBlockState(blockpos); +- BlockEntity blockentity; ++ private BlockEntity promotePendingBlockEntity(BlockPos pos, CompoundTag tag) { ++ IBlockData iblockdata = this.getBlockState(pos); ++ BlockEntity tileentity; + +- if ("DUMMY".equals(compoundtag.getString("id"))) { +- if (blockstate.hasBlockEntity()) { +- blockentity = ((EntityBlock) blockstate.getBlock()).newBlockEntity(blockpos, blockstate); ++ if ("DUMMY".equals(tag.getString("id"))) { ++ if (iblockdata.hasBlockEntity()) { ++ tileentity = ((EntityBlock) iblockdata.getBlock()).newBlockEntity(pos, iblockdata); + } else { +- blockentity = null; +- LevelChunk.LOGGER.warn("Tried to load a DUMMY block entity @ {} but found not block entity block {} at location", blockpos, blockstate); ++ tileentity = null; ++ LevelChunk.LOGGER.warn("Tried to load a DUMMY block entity @ {} but found not block entity block {} at location", pos, iblockdata); + } + } else { +- blockentity = BlockEntity.loadStatic(blockpos, blockstate, compoundtag); ++ tileentity = BlockEntity.loadStatic(pos, iblockdata, tag); + } + +- if (blockentity != null) { +- blockentity.setLevel(this.level); +- this.addAndRegisterBlockEntity(blockentity); ++ if (tileentity != null) { ++ tileentity.setLevel(this.level); ++ this.addAndRegisterBlockEntity(tileentity); + } else { +- LevelChunk.LOGGER.warn("Tried to load a block entity for block {} but failed at location {}", blockstate, blockpos); ++ LevelChunk.LOGGER.warn("Tried to load a block entity for block {} but failed at location {}", iblockdata, pos); + } + +- return blockentity; ++ return tileentity; + } + +- public void unpackTicks(long i) { +- this.blockTicks.unpack(i); +- this.fluidTicks.unpack(i); ++ public void unpackTicks(long pos) { ++ this.blockTicks.unpack(pos); ++ this.fluidTicks.unpack(pos); + } + +- public void registerTickContainerInLevel(ServerLevel serverlevel) { +- serverlevel.getBlockTicks().addContainer(this.chunkPos, this.blockTicks); +- serverlevel.getFluidTicks().addContainer(this.chunkPos, this.fluidTicks); ++ public void registerTickContainerInLevel(ServerLevel level) { ++ level.getBlockTicks().addContainer(this.chunkPos, this.blockTicks); ++ level.getFluidTicks().addContainer(this.chunkPos, this.fluidTicks); + } + +- public void unregisterTickContainerFromLevel(ServerLevel serverlevel) { +- serverlevel.getBlockTicks().removeContainer(this.chunkPos); +- serverlevel.getFluidTicks().removeContainer(this.chunkPos); ++ public void unregisterTickContainerFromLevel(ServerLevel level) { ++ level.getBlockTicks().removeContainer(this.chunkPos); ++ level.getFluidTicks().removeContainer(this.chunkPos); + } + + @Override +- @Override + public ChunkStatus getStatus() { + return ChunkStatus.FULL; + } +@@ -672,64 +741,64 @@ + return this.fullStatus == null ? FullChunkStatus.FULL : (FullChunkStatus) this.fullStatus.get(); + } + +- public void setFullStatus(Supplier supplier) { +- this.fullStatus = supplier; ++ public void setFullStatus(Supplier fullStatus) { ++ this.fullStatus = fullStatus; + } + + public void clearAllBlockEntities() { + this.blockEntities.values().forEach(BlockEntity::setRemoved); + this.blockEntities.clear(); +- this.tickersInLevel.values().forEach((levelchunk_rebindabletickingblockentitywrapper) -> { +- levelchunk_rebindabletickingblockentitywrapper.rebind(LevelChunk.NULL_TICKER); ++ this.tickersInLevel.values().forEach((chunk_d) -> { ++ chunk_d.rebind(LevelChunk.NULL_TICKER); + }); + this.tickersInLevel.clear(); + } + + public void registerAllBlockEntitiesAfterLevelLoad() { +- this.blockEntities.values().forEach((blockentity) -> { +- Level level = this.level; ++ this.blockEntities.values().forEach((tileentity) -> { ++ Level world = this.level; + +- if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; + +- this.addGameEventListener(blockentity, serverlevel); ++ this.addGameEventListener(tileentity, worldserver); + } + +- this.updateBlockEntityTicker(blockentity); ++ this.updateBlockEntityTicker(tileentity); + }); + } + +- private void addGameEventListener(T t0, ServerLevel serverlevel) { +- Block block = t0.getBlockState().getBlock(); ++ private void addGameEventListener(T blockEntity, ServerLevel level) { ++ Block block = blockEntity.getBlockState().getBlock(); + + if (block instanceof EntityBlock) { +- GameEventListener gameeventlistener = ((EntityBlock) block).getListener(serverlevel, t0); ++ GameEventListener gameeventlistener = ((EntityBlock) block).getListener(level, blockEntity); + + if (gameeventlistener != null) { +- this.getListenerRegistry(SectionPos.blockToSectionCoord(t0.getBlockPos().getY())).register(gameeventlistener); ++ this.getListenerRegistry(SectionPos.blockToSectionCoord(blockEntity.getBlockPos().getY())).register(gameeventlistener); + } + } + + } + +- private void updateBlockEntityTicker(T t0) { +- BlockState blockstate = t0.getBlockState(); +- BlockEntityTicker blockentityticker = blockstate.getTicker(this.level, t0.getType()); ++ private void updateBlockEntityTicker(T blockEntity) { ++ IBlockData iblockdata = blockEntity.getBlockState(); ++ BlockEntityTicker blockentityticker = iblockdata.getTicker(this.level, (BlockEntityType) blockEntity.getType()); // CraftBukkit - decompile error + + if (blockentityticker == null) { +- this.removeBlockEntityTicker(t0.getBlockPos()); ++ this.removeBlockEntityTicker(blockEntity.getBlockPos()); + } else { +- this.tickersInLevel.compute(t0.getBlockPos(), (blockpos, levelchunk_rebindabletickingblockentitywrapper) -> { +- TickingBlockEntity tickingblockentity = this.createTicker(t0, blockentityticker); ++ this.tickersInLevel.compute(blockEntity.getBlockPos(), (blockposition, chunk_d) -> { ++ TickingBlockEntity tickingblockentity = this.createTicker(blockEntity, blockentityticker); + +- if (levelchunk_rebindabletickingblockentitywrapper != null) { +- levelchunk_rebindabletickingblockentitywrapper.rebind(tickingblockentity); +- return levelchunk_rebindabletickingblockentitywrapper; ++ if (chunk_d != null) { ++ chunk_d.rebind(tickingblockentity); ++ return chunk_d; + } else if (this.isInLevel()) { +- LevelChunk.RebindableTickingBlockEntityWrapper levelchunk_rebindabletickingblockentitywrapper1 = new LevelChunk.RebindableTickingBlockEntityWrapper(tickingblockentity); ++ LevelChunk.RebindableTickingBlockEntityWrapper chunk_d1 = new LevelChunk.RebindableTickingBlockEntityWrapper(tickingblockentity); + +- this.level.addBlockEntityTicker(levelchunk_rebindabletickingblockentitywrapper1); +- return levelchunk_rebindabletickingblockentitywrapper1; ++ this.level.addBlockEntityTicker(chunk_d1); ++ return chunk_d1; + } else { + return null; + } +@@ -738,8 +807,8 @@ + + } + +- private TickingBlockEntity createTicker(T t0, BlockEntityTicker blockentityticker) { +- return new LevelChunk.BoundTickingBlockEntity<>(t0, blockentityticker); ++ private TickingBlockEntity createTicker(T blockEntity, BlockEntityTicker ticker) { ++ return new LevelChunk.BoundTickingBlockEntity<>(blockEntity, ticker); + } + + @FunctionalInterface +@@ -748,11 +817,11 @@ + void run(LevelChunk chunk); + } + +- public static enum EntityCreationType { ++ public static enum EnumTileEntityState { + + IMMEDIATE, QUEUED, CHECK; + +- private EntityCreationType() {} ++ private EnumTileEntityState() {} + } + + private class RebindableTickingBlockEntityWrapper implements TickingBlockEntity { +@@ -763,35 +832,30 @@ + this.ticker = tickingblockentity; + } + +- void rebind(TickingBlockEntity tickingblockentity) { +- this.ticker = tickingblockentity; ++ void rebind(TickingBlockEntity ticker) { ++ this.ticker = ticker; + } + + @Override +- @Override + public void tick() { + this.ticker.tick(); + } + + @Override +- @Override + public boolean isRemoved() { + return this.ticker.isRemoved(); + } + + @Override +- @Override + public BlockPos getPos() { + return this.ticker.getPos(); + } + + @Override +- @Override + public String getType() { + return this.ticker.getType(); + } + +- @Override + public String toString() { + return this.ticker + " "; + } +@@ -803,38 +867,37 @@ + private final BlockEntityTicker ticker; + private boolean loggedInvalidBlockState; + +- BoundTickingBlockEntity(T t0, BlockEntityTicker blockentityticker) { +- this.blockEntity = t0; ++ BoundTickingBlockEntity(BlockEntity tileentity, BlockEntityTicker blockentityticker) { ++ this.blockEntity = (T) tileentity; // CraftBukkit - decompile error + this.ticker = blockentityticker; + } + + @Override +- @Override + public void tick() { + if (!this.blockEntity.isRemoved() && this.blockEntity.hasLevel()) { +- BlockPos blockpos = this.blockEntity.getBlockPos(); ++ BlockPos blockposition = this.blockEntity.getBlockPos(); + +- if (LevelChunk.this.isTicking(blockpos)) { ++ if (LevelChunk.this.isTicking(blockposition)) { + try { +- ProfilerFiller profilerfiller = LevelChunk.this.level.getProfiler(); ++ ProfilerFiller gameprofilerfiller = LevelChunk.this.level.getProfiler(); + +- profilerfiller.push(this::getType); +- BlockState blockstate = LevelChunk.this.getBlockState(blockpos); ++ gameprofilerfiller.push(this::getType); ++ IBlockData iblockdata = LevelChunk.this.getBlockState(blockposition); + +- if (this.blockEntity.getType().isValid(blockstate)) { +- this.ticker.tick(LevelChunk.this.level, this.blockEntity.getBlockPos(), blockstate, this.blockEntity); ++ if (this.blockEntity.getType().isValid(iblockdata)) { ++ this.ticker.tick(LevelChunk.this.level, this.blockEntity.getBlockPos(), iblockdata, this.blockEntity); + this.loggedInvalidBlockState = false; + } else if (!this.loggedInvalidBlockState) { + this.loggedInvalidBlockState = true; +- LevelChunk.LOGGER.warn("Block entity {} @ {} state {} invalid for ticking:", new Object[]{LogUtils.defer(this::getType), LogUtils.defer(this::getPos), blockstate}); ++ LevelChunk.LOGGER.warn("Block entity {} @ {} state {} invalid for ticking:", new Object[]{LogUtils.defer(this::getType), LogUtils.defer(this::getPos), iblockdata}); + } + +- profilerfiller.pop(); ++ gameprofilerfiller.pop(); + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking block entity"); +- CrashReportCategory crashreportcategory = crashreport.addCategory("Block entity being ticked"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block entity being ticked"); + +- this.blockEntity.fillCrashReportCategory(crashreportcategory); ++ this.blockEntity.fillCrashReportCategory(crashreportsystemdetails); + throw new ReportedException(crashreport); + } + } +@@ -843,24 +906,20 @@ + } + + @Override +- @Override + public boolean isRemoved() { + return this.blockEntity.isRemoved(); + } + + @Override +- @Override + public BlockPos getPos() { + return this.blockEntity.getBlockPos(); + } + + @Override +- @Override + public String getType() { + return BlockEntityType.getKey(this.blockEntity.getType()).toString(); + } + +- @Override + public String toString() { + String s = this.getType(); + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/LevelChunkSection.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/LevelChunkSection.java.patch new file mode 100644 index 0000000000..62c90f4b18 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/LevelChunkSection.java.patch @@ -0,0 +1,251 @@ +--- a/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -10,7 +10,7 @@ + import net.minecraft.world.level.biome.Climate; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; + + public class LevelChunkSection { +@@ -22,26 +22,28 @@ + private short nonEmptyBlockCount; + private short tickingBlockCount; + private short tickingFluidCount; +- private final PalettedContainer states; +- private PalettedContainerRO> biomes; ++ private final PalettedContainer states; ++ // CraftBukkit start - read/write ++ private PalettedContainer> biomes; + +- public LevelChunkSection(PalettedContainer palettedcontainer, PalettedContainerRO> palettedcontainerro) { +- this.states = palettedcontainer; ++ public LevelChunkSection(PalettedContainer datapaletteblock, PalettedContainer> palettedcontainerro) { ++ // CraftBukkit end ++ this.states = datapaletteblock; + this.biomes = palettedcontainerro; + this.recalcBlockCounts(); + } + +- public LevelChunkSection(Registry registry) { ++ public LevelChunkSection(Registry biomeRegistry) { + this.states = new PalettedContainer<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES); +- this.biomes = new PalettedContainer<>(registry.asHolderIdMap(), registry.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES); ++ this.biomes = new PalettedContainer<>(biomeRegistry.asHolderIdMap(), biomeRegistry.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES); + } + +- public BlockState getBlockState(int i, int j, int k) { +- return (BlockState) this.states.get(i, j, k); ++ public IBlockData getBlockState(int x, int y, int z) { ++ return (IBlockData) this.states.get(x, y, z); + } + +- public FluidState getFluidState(int i, int j, int k) { +- return ((BlockState) this.states.get(i, j, k)).getFluidState(); ++ public FluidState getFluidState(int x, int y, int z) { ++ return ((IBlockData) this.states.get(x, y, z)).getFluidState(); + } + + public void acquire() { +@@ -52,45 +54,45 @@ + this.states.release(); + } + +- public BlockState setBlockState(int i, int j, int k, BlockState blockstate) { +- return this.setBlockState(i, j, k, blockstate, true); ++ public IBlockData setBlockState(int x, int y, int z, IBlockData state) { ++ return this.setBlockState(x, y, z, state, true); + } + +- public BlockState setBlockState(int i, int j, int k, BlockState blockstate, boolean flag) { +- BlockState blockstate1; ++ public IBlockData setBlockState(int x, int y, int z, IBlockData state, boolean useLocks) { ++ IBlockData iblockdata1; + +- if (flag) { +- blockstate1 = (BlockState) this.states.getAndSet(i, j, k, blockstate); ++ if (useLocks) { ++ iblockdata1 = (IBlockData) this.states.getAndSet(x, y, z, state); + } else { +- blockstate1 = (BlockState) this.states.getAndSetUnchecked(i, j, k, blockstate); ++ iblockdata1 = (IBlockData) this.states.getAndSetUnchecked(x, y, z, state); + } + +- FluidState fluidstate = blockstate1.getFluidState(); +- FluidState fluidstate1 = blockstate.getFluidState(); ++ FluidState fluid = iblockdata1.getFluidState(); ++ FluidState fluid1 = state.getFluidState(); + +- if (!blockstate1.isAir()) { ++ if (!iblockdata1.isAir()) { + --this.nonEmptyBlockCount; +- if (blockstate1.isRandomlyTicking()) { ++ if (iblockdata1.isRandomlyTicking()) { + --this.tickingBlockCount; + } + } + +- if (!fluidstate.isEmpty()) { ++ if (!fluid.isEmpty()) { + --this.tickingFluidCount; + } + +- if (!blockstate.isAir()) { ++ if (!state.isAir()) { + ++this.nonEmptyBlockCount; +- if (blockstate.isRandomlyTicking()) { ++ if (state.isRandomlyTicking()) { + ++this.tickingBlockCount; + } + } + +- if (!fluidstate1.isEmpty()) { ++ if (!fluid1.isEmpty()) { + ++this.tickingFluidCount; + } + +- return blockstate1; ++ return iblockdata1; + } + + public boolean hasOnlyAir() { +@@ -110,28 +112,27 @@ + } + + public void recalcBlockCounts() { +- class BlockCounter implements PalettedContainer.CountConsumer { ++ class a implements PalettedContainer.CountConsumer { + + public int nonEmptyBlockCount; + public int tickingBlockCount; + public int tickingFluidCount; + +- BlockCounter() {} ++ a() {} + +- @Override +- public void accept(BlockState blockstate, int i) { +- FluidState fluidstate = blockstate.getFluidState(); ++ public void accept(IBlockData iblockdata, int i) { ++ FluidState fluid = iblockdata.getFluidState(); + +- if (!blockstate.isAir()) { ++ if (!iblockdata.isAir()) { + this.nonEmptyBlockCount += i; +- if (blockstate.isRandomlyTicking()) { ++ if (iblockdata.isRandomlyTicking()) { + this.tickingBlockCount += i; + } + } + +- if (!fluidstate.isEmpty()) { ++ if (!fluid.isEmpty()) { + this.nonEmptyBlockCount += i; +- if (fluidstate.isRandomlyTicking()) { ++ if (fluid.isRandomlyTicking()) { + this.tickingFluidCount += i; + } + } +@@ -139,15 +140,15 @@ + } + } + +- BlockCounter blockcounter = new BlockCounter(); ++ a a0 = new a(); + +- this.states.count(blockcounter); +- this.nonEmptyBlockCount = (short) blockcounter.nonEmptyBlockCount; +- this.tickingBlockCount = (short) blockcounter.tickingBlockCount; +- this.tickingFluidCount = (short) blockcounter.tickingFluidCount; ++ this.states.count(a0); ++ this.nonEmptyBlockCount = (short) a0.nonEmptyBlockCount; ++ this.tickingBlockCount = (short) a0.tickingBlockCount; ++ this.tickingFluidCount = (short) a0.tickingFluidCount; + } + +- public PalettedContainer getStates() { ++ public PalettedContainer getStates() { + return this.states; + } + +@@ -155,52 +156,58 @@ + return this.biomes; + } + +- public void read(FriendlyByteBuf friendlybytebuf) { +- this.nonEmptyBlockCount = friendlybytebuf.readShort(); +- this.states.read(friendlybytebuf); +- PalettedContainer> palettedcontainer = this.biomes.recreate(); ++ public void read(FriendlyByteBuf buffer) { ++ this.nonEmptyBlockCount = buffer.readShort(); ++ this.states.read(buffer); ++ PalettedContainer> datapaletteblock = this.biomes.recreate(); + +- palettedcontainer.read(friendlybytebuf); +- this.biomes = palettedcontainer; ++ datapaletteblock.read(buffer); ++ this.biomes = datapaletteblock; + } + +- public void readBiomes(FriendlyByteBuf friendlybytebuf) { +- PalettedContainer> palettedcontainer = this.biomes.recreate(); ++ public void readBiomes(FriendlyByteBuf buffer) { ++ PalettedContainer> datapaletteblock = this.biomes.recreate(); + +- palettedcontainer.read(friendlybytebuf); +- this.biomes = palettedcontainer; ++ datapaletteblock.read(buffer); ++ this.biomes = datapaletteblock; + } + +- public void write(FriendlyByteBuf friendlybytebuf) { +- friendlybytebuf.writeShort(this.nonEmptyBlockCount); +- this.states.write(friendlybytebuf); +- this.biomes.write(friendlybytebuf); ++ public void write(FriendlyByteBuf buffer) { ++ buffer.writeShort(this.nonEmptyBlockCount); ++ this.states.write(buffer); ++ this.biomes.write(buffer); + } + + public int getSerializedSize() { + return 2 + this.states.getSerializedSize() + this.biomes.getSerializedSize(); + } + +- public boolean maybeHas(Predicate predicate) { ++ public boolean maybeHas(Predicate predicate) { + return this.states.maybeHas(predicate); + } + +- public Holder getNoiseBiome(int i, int j, int k) { +- return (Holder) this.biomes.get(i, j, k); ++ public Holder getNoiseBiome(int x, int y, int z) { ++ return (Holder) this.biomes.get(x, y, z); + } + +- public void fillBiomesFromNoise(BiomeResolver biomeresolver, Climate.Sampler climate_sampler, int i, int j, int k) { +- PalettedContainer> palettedcontainer = this.biomes.recreate(); ++ // CraftBukkit start ++ public void setBiome(int i, int j, int k, Holder biome) { ++ this.biomes.set(i, j, k, biome); ++ } ++ // CraftBukkit end ++ ++ public void fillBiomesFromNoise(BiomeResolver biomeResolver, Climate.Sampler climateSampler, int x, int y, int z) { ++ PalettedContainer> datapaletteblock = this.biomes.recreate(); + boolean flag = true; + + for (int l = 0; l < 4; ++l) { + for (int i1 = 0; i1 < 4; ++i1) { + for (int j1 = 0; j1 < 4; ++j1) { +- palettedcontainer.getAndSetUnchecked(l, i1, j1, biomeresolver.getNoiseBiome(i + l, j + i1, k + j1, climate_sampler)); ++ datapaletteblock.getAndSetUnchecked(l, i1, j1, biomeResolver.getNoiseBiome(x + l, y + i1, z + j1, climateSampler)); + } + } + } + +- this.biomes = palettedcontainer; ++ this.biomes = datapaletteblock; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/storage/ChunkSerializer.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/storage/ChunkSerializer.java.patch new file mode 100644 index 0000000000..03b395a949 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/storage/ChunkSerializer.java.patch @@ -0,0 +1,798 @@ +--- a/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -38,13 +38,13 @@ + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.ai.village.poi.PoiManager; + import net.minecraft.world.level.ChunkPos; +-import net.minecraft.world.level.LightLayer; ++import net.minecraft.world.level.EnumSkyBlock; + import net.minecraft.world.level.biome.Biome; + import net.minecraft.world.level.biome.Biomes; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.CarvingMask; + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkStatus; +@@ -71,7 +71,7 @@ + + public class ChunkSerializer { + +- private static final Codec> BLOCK_STATE_CODEC = PalettedContainer.codecRW(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState()); ++ public static final Codec> BLOCK_STATE_CODEC = PalettedContainer.codecRW(Block.BLOCK_STATE_REGISTRY, IBlockData.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState()); + private static final Logger LOGGER = LogUtils.getLogger(); + private static final String TAG_UPGRADE_DATA = "UpgradeData"; + private static final String BLOCK_TICKS_TAG = "block_ticks"; +@@ -86,134 +86,134 @@ + + public ChunkSerializer() {} + +- public static ProtoChunk read(ServerLevel serverlevel, PoiManager poimanager, ChunkPos chunkpos, CompoundTag compoundtag) { +- ChunkPos chunkpos1 = new ChunkPos(compoundtag.getInt("xPos"), compoundtag.getInt("zPos")); ++ public static ProtoChunk read(ServerLevel level, PoiManager poiManager, ChunkPos pos, CompoundTag tag) { ++ ChunkPos chunkcoordintpair1 = new ChunkPos(tag.getInt("xPos"), tag.getInt("zPos")); + +- if (!Objects.equals(chunkpos, chunkpos1)) { +- ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", new Object[]{chunkpos, chunkpos, chunkpos1}); ++ if (!Objects.equals(pos, chunkcoordintpair1)) { ++ ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", new Object[]{pos, pos, chunkcoordintpair1}); + } + +- UpgradeData upgradedata = compoundtag.contains("UpgradeData", 10) ? new UpgradeData(compoundtag.getCompound("UpgradeData"), serverlevel) : UpgradeData.EMPTY; +- boolean flag = compoundtag.getBoolean("isLightOn"); +- ListTag listtag = compoundtag.getList("sections", 10); +- int i = serverlevel.getSectionsCount(); +- LevelChunkSection[] alevelchunksection = new LevelChunkSection[i]; +- boolean flag1 = serverlevel.dimensionType().hasSkyLight(); +- ServerChunkCache serverchunkcache = serverlevel.getChunkSource(); +- LevelLightEngine levellightengine = serverchunkcache.getLightEngine(); +- Registry registry = serverlevel.registryAccess().registryOrThrow(Registries.BIOME); +- Codec>> codec = makeBiomeCodec(registry); ++ UpgradeData chunkconverter = tag.contains("UpgradeData", 10) ? new UpgradeData(tag.getCompound("UpgradeData"), level) : UpgradeData.EMPTY; ++ boolean flag = tag.getBoolean("isLightOn"); ++ ListTag nbttaglist = tag.getList("sections", 10); ++ int i = level.getSectionsCount(); ++ LevelChunkSection[] achunksection = new LevelChunkSection[i]; ++ boolean flag1 = level.dimensionType().hasSkyLight(); ++ ServerChunkCache chunkproviderserver = level.getChunkSource(); ++ LevelLightEngine levellightengine = chunkproviderserver.getLightEngine(); ++ Registry iregistry = level.registryAccess().registryOrThrow(Registries.BIOME); ++ Codec>> codec = makeBiomeCodecRW(iregistry); // CraftBukkit - read/write + boolean flag2 = false; + + DataResult dataresult; + +- for (int j = 0; j < listtag.size(); ++j) { +- CompoundTag compoundtag1 = listtag.getCompound(j); +- byte b0 = compoundtag1.getByte("Y"); +- int k = serverlevel.getSectionIndexFromSectionY(b0); ++ for (int j = 0; j < nbttaglist.size(); ++j) { ++ CompoundTag nbttagcompound1 = nbttaglist.getCompound(j); ++ byte b0 = nbttagcompound1.getByte("Y"); ++ int k = level.getSectionIndexFromSectionY(b0); + +- if (k >= 0 && k < alevelchunksection.length) { ++ if (k >= 0 && k < achunksection.length) { + Logger logger; +- PalettedContainer palettedcontainer; ++ PalettedContainer datapaletteblock; + +- if (compoundtag1.contains("block_states", 10)) { +- dataresult = ChunkSerializer.BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, compoundtag1.getCompound("block_states")).promotePartial((s) -> { +- logErrors(chunkpos, b0, s); ++ if (nbttagcompound1.contains("block_states", 10)) { ++ dataresult = ChunkSerializer.BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, nbttagcompound1.getCompound("block_states")).promotePartial((s) -> { ++ logErrors(pos, b0, s); + }); + logger = ChunkSerializer.LOGGER; + Objects.requireNonNull(logger); +- palettedcontainer = (PalettedContainer) dataresult.getOrThrow(false, logger::error); ++ datapaletteblock = (PalettedContainer) ((DataResult>) dataresult).getOrThrow(false, logger::error); // CraftBukkit - decompile error + } else { +- palettedcontainer = new PalettedContainer<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES); ++ datapaletteblock = new PalettedContainer<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES); + } + +- Object object; ++ PalettedContainer object; // CraftBukkit - read/write + +- if (compoundtag1.contains("biomes", 10)) { +- dataresult = codec.parse(NbtOps.INSTANCE, compoundtag1.getCompound("biomes")).promotePartial((s) -> { +- logErrors(chunkpos, b0, s); ++ if (nbttagcompound1.contains("biomes", 10)) { ++ dataresult = codec.parse(NbtOps.INSTANCE, nbttagcompound1.getCompound("biomes")).promotePartial((s) -> { ++ logErrors(pos, b0, s); + }); + logger = ChunkSerializer.LOGGER; + Objects.requireNonNull(logger); +- object = (PalettedContainerRO) dataresult.getOrThrow(false, logger::error); ++ object = ((DataResult>>) dataresult).getOrThrow(false, logger::error); // CraftBukkit - decompile error + } else { +- object = new PalettedContainer<>(registry.asHolderIdMap(), registry.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES); ++ object = new PalettedContainer<>(iregistry.asHolderIdMap(), iregistry.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES); + } + +- LevelChunkSection levelchunksection = new LevelChunkSection(palettedcontainer, (PalettedContainerRO) object); ++ LevelChunkSection chunksection = new LevelChunkSection(datapaletteblock, (PalettedContainer) object); // CraftBukkit - read/write + +- alevelchunksection[k] = levelchunksection; +- SectionPos sectionpos = SectionPos.of(chunkpos, b0); ++ achunksection[k] = chunksection; ++ SectionPos sectionposition = SectionPos.of(pos, b0); + +- poimanager.checkConsistencyWithBlocks(sectionpos, levelchunksection); ++ poiManager.checkConsistencyWithBlocks(sectionposition, chunksection); + } + +- boolean flag3 = compoundtag1.contains("BlockLight", 7); +- boolean flag4 = flag1 && compoundtag1.contains("SkyLight", 7); ++ boolean flag3 = nbttagcompound1.contains("BlockLight", 7); ++ boolean flag4 = flag1 && nbttagcompound1.contains("SkyLight", 7); + + if (flag3 || flag4) { + if (!flag2) { +- levellightengine.retainData(chunkpos, true); ++ levellightengine.retainData(pos, true); + flag2 = true; + } + + if (flag3) { +- levellightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkpos, b0), new DataLayer(compoundtag1.getByteArray("BlockLight"))); ++ levellightengine.queueSectionData(EnumSkyBlock.BLOCK, SectionPos.of(pos, b0), new DataLayer(nbttagcompound1.getByteArray("BlockLight"))); + } + + if (flag4) { +- levellightengine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkpos, b0), new DataLayer(compoundtag1.getByteArray("SkyLight"))); ++ levellightengine.queueSectionData(EnumSkyBlock.SKY, SectionPos.of(pos, b0), new DataLayer(nbttagcompound1.getByteArray("SkyLight"))); + } + } + } + +- long l = compoundtag.getLong("InhabitedTime"); +- ChunkStatus.ChunkType chunkstatus_chunktype = getChunkTypeFromTag(compoundtag); ++ long l = tag.getLong("InhabitedTime"); ++ ChunkStatus.Type chunkstatus_type = getChunkTypeFromTag(tag); + Logger logger1; + BlendingData blendingdata; + +- if (compoundtag.contains("blending_data", 10)) { +- dataresult = BlendingData.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compoundtag.getCompound("blending_data"))); ++ if (tag.contains("blending_data", 10)) { ++ dataresult = BlendingData.CODEC.parse(new Dynamic(NbtOps.INSTANCE, tag.getCompound("blending_data"))); + logger1 = ChunkSerializer.LOGGER; + Objects.requireNonNull(logger1); +- blendingdata = (BlendingData) dataresult.resultOrPartial(logger1::error).orElse((Object) null); ++ blendingdata = (BlendingData) ((DataResult) dataresult).resultOrPartial(logger1::error).orElse(null); // CraftBukkit - decompile error + } else { + blendingdata = null; + } + + Object object1; + +- if (chunkstatus_chunktype == ChunkStatus.ChunkType.LEVELCHUNK) { +- LevelChunkTicks levelchunkticks = LevelChunkTicks.load(compoundtag.getList("block_ticks", 10), (s) -> { ++ if (chunkstatus_type == ChunkStatus.Type.LEVELCHUNK) { ++ LevelChunkTicks levelchunkticks = LevelChunkTicks.load(tag.getList("block_ticks", 10), (s) -> { + return BuiltInRegistries.BLOCK.getOptional(ResourceLocation.tryParse(s)); +- }, chunkpos); +- LevelChunkTicks levelchunkticks1 = LevelChunkTicks.load(compoundtag.getList("fluid_ticks", 10), (s) -> { ++ }, pos); ++ LevelChunkTicks levelchunkticks1 = LevelChunkTicks.load(tag.getList("fluid_ticks", 10), (s) -> { + return BuiltInRegistries.FLUID.getOptional(ResourceLocation.tryParse(s)); +- }, chunkpos); ++ }, pos); + +- object1 = new LevelChunk(serverlevel.getLevel(), chunkpos, upgradedata, levelchunkticks, levelchunkticks1, l, alevelchunksection, postLoadChunk(serverlevel, compoundtag), blendingdata); ++ object1 = new LevelChunk(level.getLevel(), pos, chunkconverter, levelchunkticks, levelchunkticks1, l, achunksection, postLoadChunk(level, tag), blendingdata); + } else { +- ProtoChunkTicks protochunkticks = ProtoChunkTicks.load(compoundtag.getList("block_ticks", 10), (s) -> { ++ ProtoChunkTicks protochunkticklist = ProtoChunkTicks.load(tag.getList("block_ticks", 10), (s) -> { + return BuiltInRegistries.BLOCK.getOptional(ResourceLocation.tryParse(s)); +- }, chunkpos); +- ProtoChunkTicks protochunkticks1 = ProtoChunkTicks.load(compoundtag.getList("fluid_ticks", 10), (s) -> { ++ }, pos); ++ ProtoChunkTicks protochunkticklist1 = ProtoChunkTicks.load(tag.getList("fluid_ticks", 10), (s) -> { + return BuiltInRegistries.FLUID.getOptional(ResourceLocation.tryParse(s)); +- }, chunkpos); +- ProtoChunk protochunk = new ProtoChunk(chunkpos, upgradedata, alevelchunksection, protochunkticks, protochunkticks1, serverlevel, registry, blendingdata); ++ }, pos); ++ ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, level, iregistry, blendingdata); + + object1 = protochunk; + protochunk.setInhabitedTime(l); +- if (compoundtag.contains("below_zero_retrogen", 10)) { +- dataresult = BelowZeroRetrogen.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compoundtag.getCompound("below_zero_retrogen"))); ++ if (tag.contains("below_zero_retrogen", 10)) { ++ dataresult = BelowZeroRetrogen.CODEC.parse(new Dynamic(NbtOps.INSTANCE, tag.getCompound("below_zero_retrogen"))); + logger1 = ChunkSerializer.LOGGER; + Objects.requireNonNull(logger1); +- Optional optional = dataresult.resultOrPartial(logger1::error); ++ Optional optional = ((DataResult) dataresult).resultOrPartial(logger1::error); // CraftBukkit - decompile error + + Objects.requireNonNull(protochunk); + optional.ifPresent(protochunk::setBelowZeroRetrogen); + } + +- ChunkStatus chunkstatus = ChunkStatus.byName(compoundtag.getString("Status")); ++ ChunkStatus chunkstatus = ChunkStatus.byName(tag.getString("Status")); + + protochunk.setStatus(chunkstatus); + if (chunkstatus.isOrAfter(ChunkStatus.INITIALIZE_LIGHT)) { +@@ -221,267 +221,285 @@ + } + } + ++ // CraftBukkit start - load chunk persistent data from nbt - SPIGOT-6814: Already load PDC here to account for 1.17 to 1.18 chunk upgrading. ++ net.minecraft.nbt.Tag persistentBase = tag.get("ChunkBukkitValues"); ++ if (persistentBase instanceof CompoundTag) { ++ ((ChunkAccess) object1).persistentDataContainer.putAll((CompoundTag) persistentBase); ++ } ++ // CraftBukkit end ++ + ((ChunkAccess) object1).setLightCorrect(flag); +- CompoundTag compoundtag2 = compoundtag.getCompound("Heightmaps"); ++ CompoundTag nbttagcompound2 = tag.getCompound("Heightmaps"); + EnumSet enumset = EnumSet.noneOf(Heightmap.Types.class); + Iterator iterator = ((ChunkAccess) object1).getStatus().heightmapsAfter().iterator(); + + while (iterator.hasNext()) { +- Heightmap.Types heightmap_types = (Heightmap.Types) iterator.next(); +- String s = heightmap_types.getSerializationKey(); ++ Heightmap.Types heightmap_type = (Heightmap.Types) iterator.next(); ++ String s = heightmap_type.getSerializationKey(); + +- if (compoundtag2.contains(s, 12)) { +- ((ChunkAccess) object1).setHeightmap(heightmap_types, compoundtag2.getLongArray(s)); ++ if (nbttagcompound2.contains(s, 12)) { ++ ((ChunkAccess) object1).setHeightmap(heightmap_type, nbttagcompound2.getLongArray(s)); + } else { +- enumset.add(heightmap_types); ++ enumset.add(heightmap_type); + } + } + + Heightmap.primeHeightmaps((ChunkAccess) object1, enumset); +- CompoundTag compoundtag3 = compoundtag.getCompound("structures"); ++ CompoundTag nbttagcompound3 = tag.getCompound("structures"); + +- ((ChunkAccess) object1).setAllStarts(unpackStructureStart(StructurePieceSerializationContext.fromLevel(serverlevel), compoundtag3, serverlevel.getSeed())); +- ((ChunkAccess) object1).setAllReferences(unpackStructureReferences(serverlevel.registryAccess(), chunkpos, compoundtag3)); +- if (compoundtag.getBoolean("shouldSave")) { ++ ((ChunkAccess) object1).setAllStarts(unpackStructureStart(StructurePieceSerializationContext.fromLevel(level), nbttagcompound3, level.getSeed())); ++ ((ChunkAccess) object1).setAllReferences(unpackStructureReferences(level.registryAccess(), pos, nbttagcompound3)); ++ if (tag.getBoolean("shouldSave")) { + ((ChunkAccess) object1).setUnsaved(true); + } + +- ListTag listtag1 = compoundtag.getList("PostProcessing", 9); ++ ListTag nbttaglist1 = tag.getList("PostProcessing", 9); + +- ListTag listtag2; ++ ListTag nbttaglist2; + int i1; + +- for (int j1 = 0; j1 < listtag1.size(); ++j1) { +- listtag2 = listtag1.getList(j1); ++ for (int j1 = 0; j1 < nbttaglist1.size(); ++j1) { ++ nbttaglist2 = nbttaglist1.getList(j1); + +- for (i1 = 0; i1 < listtag2.size(); ++i1) { +- ((ChunkAccess) object1).addPackedPostProcess(listtag2.getShort(i1), j1); ++ for (i1 = 0; i1 < nbttaglist2.size(); ++i1) { ++ ((ChunkAccess) object1).addPackedPostProcess(nbttaglist2.getShort(i1), j1); + } + } + +- if (chunkstatus_chunktype == ChunkStatus.ChunkType.LEVELCHUNK) { ++ if (chunkstatus_type == ChunkStatus.Type.LEVELCHUNK) { + return new ImposterProtoChunk((LevelChunk) object1, false); + } else { + ProtoChunk protochunk1 = (ProtoChunk) object1; + +- listtag2 = compoundtag.getList("entities", 10); ++ nbttaglist2 = tag.getList("entities", 10); + +- for (i1 = 0; i1 < listtag2.size(); ++i1) { +- protochunk1.addEntity(listtag2.getCompound(i1)); ++ for (i1 = 0; i1 < nbttaglist2.size(); ++i1) { ++ protochunk1.addEntity(nbttaglist2.getCompound(i1)); + } + +- ListTag listtag3 = compoundtag.getList("block_entities", 10); ++ ListTag nbttaglist3 = tag.getList("block_entities", 10); + +- for (int k1 = 0; k1 < listtag3.size(); ++k1) { +- CompoundTag compoundtag4 = listtag3.getCompound(k1); ++ for (int k1 = 0; k1 < nbttaglist3.size(); ++k1) { ++ CompoundTag nbttagcompound4 = nbttaglist3.getCompound(k1); + +- ((ChunkAccess) object1).setBlockEntityNbt(compoundtag4); ++ ((ChunkAccess) object1).setBlockEntityNbt(nbttagcompound4); + } + +- CompoundTag compoundtag5 = compoundtag.getCompound("CarvingMasks"); +- Iterator iterator1 = compoundtag5.getAllKeys().iterator(); ++ CompoundTag nbttagcompound5 = tag.getCompound("CarvingMasks"); ++ Iterator iterator1 = nbttagcompound5.getAllKeys().iterator(); + + while (iterator1.hasNext()) { + String s1 = (String) iterator1.next(); +- GenerationStep.Carving generationstep_carving = GenerationStep.Carving.valueOf(s1); ++ GenerationStep.Carving worldgenstage_features = GenerationStep.Carving.valueOf(s1); + +- protochunk1.setCarvingMask(generationstep_carving, new CarvingMask(compoundtag5.getLongArray(s1), ((ChunkAccess) object1).getMinBuildHeight())); ++ protochunk1.setCarvingMask(worldgenstage_features, new CarvingMask(nbttagcompound5.getLongArray(s1), ((ChunkAccess) object1).getMinBuildHeight())); + } + + return protochunk1; + } + } + +- private static void logErrors(ChunkPos chunkpos, int i, String s) { +- ChunkSerializer.LOGGER.error("Recoverable errors when loading section [" + chunkpos.x + ", " + i + ", " + chunkpos.z + "]: " + s); ++ private static void logErrors(ChunkPos chunkPos, int chunkSectionY, String errorMessage) { ++ ChunkSerializer.LOGGER.error("Recoverable errors when loading section [" + chunkPos.x + ", " + chunkSectionY + ", " + chunkPos.z + "]: " + errorMessage); + } + +- private static Codec>> makeBiomeCodec(Registry registry) { +- return PalettedContainer.codecRO(registry.asHolderIdMap(), registry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, registry.getHolderOrThrow(Biomes.PLAINS)); ++ private static Codec>> makeBiomeCodec(Registry biomeRegistry) { ++ return PalettedContainer.codecRO(biomeRegistry.asHolderIdMap(), biomeRegistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomeRegistry.getHolderOrThrow(Biomes.PLAINS)); + } + +- public static CompoundTag write(ServerLevel serverlevel, ChunkAccess chunkaccess) { +- ChunkPos chunkpos = chunkaccess.getPos(); +- CompoundTag compoundtag = NbtUtils.addCurrentDataVersion(new CompoundTag()); ++ // CraftBukkit start - read/write ++ private static Codec>> makeBiomeCodecRW(Registry iregistry) { ++ return PalettedContainer.codecRW(iregistry.asHolderIdMap(), iregistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, iregistry.getHolderOrThrow(Biomes.PLAINS)); ++ } ++ // CraftBukkit end + +- compoundtag.putInt("xPos", chunkpos.x); +- compoundtag.putInt("yPos", chunkaccess.getMinSection()); +- compoundtag.putInt("zPos", chunkpos.z); +- compoundtag.putLong("LastUpdate", serverlevel.getGameTime()); +- compoundtag.putLong("InhabitedTime", chunkaccess.getInhabitedTime()); +- compoundtag.putString("Status", BuiltInRegistries.CHUNK_STATUS.getKey(chunkaccess.getStatus()).toString()); +- BlendingData blendingdata = chunkaccess.getBlendingData(); +- DataResult dataresult; ++ public static CompoundTag write(ServerLevel level, ChunkAccess chunk) { ++ ChunkPos chunkcoordintpair = chunk.getPos(); ++ CompoundTag nbttagcompound = NbtUtils.addCurrentDataVersion(new CompoundTag()); ++ ++ nbttagcompound.putInt("xPos", chunkcoordintpair.x); ++ nbttagcompound.putInt("yPos", chunk.getMinSection()); ++ nbttagcompound.putInt("zPos", chunkcoordintpair.z); ++ nbttagcompound.putLong("LastUpdate", level.getGameTime()); ++ nbttagcompound.putLong("InhabitedTime", chunk.getInhabitedTime()); ++ nbttagcompound.putString("Status", BuiltInRegistries.CHUNK_STATUS.getKey(chunk.getStatus()).toString()); ++ BlendingData blendingdata = chunk.getBlendingData(); ++ DataResult dataresult; // CraftBukkit - decompile error + Logger logger; + + if (blendingdata != null) { + dataresult = BlendingData.CODEC.encodeStart(NbtOps.INSTANCE, blendingdata); + logger = ChunkSerializer.LOGGER; + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((tag) -> { +- compoundtag.put("blending_data", tag); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ nbttagcompound.put("blending_data", nbtbase); + }); + } + +- BelowZeroRetrogen belowzeroretrogen = chunkaccess.getBelowZeroRetrogen(); ++ BelowZeroRetrogen belowzeroretrogen = chunk.getBelowZeroRetrogen(); + + if (belowzeroretrogen != null) { + dataresult = BelowZeroRetrogen.CODEC.encodeStart(NbtOps.INSTANCE, belowzeroretrogen); + logger = ChunkSerializer.LOGGER; + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((tag) -> { +- compoundtag.put("below_zero_retrogen", tag); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ nbttagcompound.put("below_zero_retrogen", nbtbase); + }); + } + +- UpgradeData upgradedata = chunkaccess.getUpgradeData(); ++ UpgradeData chunkconverter = chunk.getUpgradeData(); + +- if (!upgradedata.isEmpty()) { +- compoundtag.put("UpgradeData", upgradedata.write()); ++ if (!chunkconverter.isEmpty()) { ++ nbttagcompound.put("UpgradeData", chunkconverter.write()); + } + +- LevelChunkSection[] alevelchunksection = chunkaccess.getSections(); +- ListTag listtag = new ListTag(); +- ThreadedLevelLightEngine threadedlevellightengine = serverlevel.getChunkSource().getLightEngine(); +- Registry registry = serverlevel.registryAccess().registryOrThrow(Registries.BIOME); +- Codec>> codec = makeBiomeCodec(registry); +- boolean flag = chunkaccess.isLightCorrect(); ++ LevelChunkSection[] achunksection = chunk.getSections(); ++ ListTag nbttaglist = new ListTag(); ++ ThreadedLevelLightEngine lightenginethreaded = level.getChunkSource().getLightEngine(); ++ Registry iregistry = level.registryAccess().registryOrThrow(Registries.BIOME); ++ Codec>> codec = makeBiomeCodec(iregistry); ++ boolean flag = chunk.isLightCorrect(); + +- for (int i = threadedlevellightengine.getMinLightSection(); i < threadedlevellightengine.getMaxLightSection(); ++i) { +- int j = chunkaccess.getSectionIndexFromSectionY(i); +- boolean flag1 = j >= 0 && j < alevelchunksection.length; +- DataLayer datalayer = threadedlevellightengine.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkpos, i)); +- DataLayer datalayer1 = threadedlevellightengine.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkpos, i)); ++ for (int i = lightenginethreaded.getMinLightSection(); i < lightenginethreaded.getMaxLightSection(); ++i) { ++ int j = chunk.getSectionIndexFromSectionY(i); ++ boolean flag1 = j >= 0 && j < achunksection.length; ++ DataLayer nibblearray = lightenginethreaded.getLayerListener(EnumSkyBlock.BLOCK).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); ++ DataLayer nibblearray1 = lightenginethreaded.getLayerListener(EnumSkyBlock.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); + +- if (flag1 || datalayer != null || datalayer1 != null) { +- CompoundTag compoundtag1 = new CompoundTag(); ++ if (flag1 || nibblearray != null || nibblearray1 != null) { ++ CompoundTag nbttagcompound1 = new CompoundTag(); + + if (flag1) { +- LevelChunkSection levelchunksection = alevelchunksection[j]; +- DataResult dataresult1 = ChunkSerializer.BLOCK_STATE_CODEC.encodeStart(NbtOps.INSTANCE, levelchunksection.getStates()); ++ LevelChunkSection chunksection = achunksection[j]; ++ DataResult dataresult1 = ChunkSerializer.BLOCK_STATE_CODEC.encodeStart(NbtOps.INSTANCE, chunksection.getStates()); // CraftBukkit - decompile error + Logger logger1 = ChunkSerializer.LOGGER; + + Objects.requireNonNull(logger1); +- compoundtag1.put("block_states", (Tag) dataresult1.getOrThrow(false, logger1::error)); +- dataresult1 = codec.encodeStart(NbtOps.INSTANCE, levelchunksection.getBiomes()); ++ nbttagcompound1.put("block_states", (Tag) dataresult1.getOrThrow(false, logger1::error)); ++ dataresult1 = codec.encodeStart(NbtOps.INSTANCE, chunksection.getBiomes()); + logger1 = ChunkSerializer.LOGGER; + Objects.requireNonNull(logger1); +- compoundtag1.put("biomes", (Tag) dataresult1.getOrThrow(false, logger1::error)); ++ nbttagcompound1.put("biomes", (Tag) dataresult1.getOrThrow(false, logger1::error)); + } + +- if (datalayer != null && !datalayer.isEmpty()) { +- compoundtag1.putByteArray("BlockLight", datalayer.getData()); ++ if (nibblearray != null && !nibblearray.isEmpty()) { ++ nbttagcompound1.putByteArray("BlockLight", nibblearray.getData()); + } + +- if (datalayer1 != null && !datalayer1.isEmpty()) { +- compoundtag1.putByteArray("SkyLight", datalayer1.getData()); ++ if (nibblearray1 != null && !nibblearray1.isEmpty()) { ++ nbttagcompound1.putByteArray("SkyLight", nibblearray1.getData()); + } + +- if (!compoundtag1.isEmpty()) { +- compoundtag1.putByte("Y", (byte) i); +- listtag.add(compoundtag1); ++ if (!nbttagcompound1.isEmpty()) { ++ nbttagcompound1.putByte("Y", (byte) i); ++ nbttaglist.add(nbttagcompound1); + } + } + } + +- compoundtag.put("sections", listtag); ++ nbttagcompound.put("sections", nbttaglist); + if (flag) { +- compoundtag.putBoolean("isLightOn", true); ++ nbttagcompound.putBoolean("isLightOn", true); + } + +- ListTag listtag1 = new ListTag(); +- Iterator iterator = chunkaccess.getBlockEntitiesPos().iterator(); ++ ListTag nbttaglist1 = new ListTag(); ++ Iterator iterator = chunk.getBlockEntitiesPos().iterator(); + +- CompoundTag compoundtag2; ++ CompoundTag nbttagcompound2; + + while (iterator.hasNext()) { +- BlockPos blockpos = (BlockPos) iterator.next(); ++ BlockPos blockposition = (BlockPos) iterator.next(); + +- compoundtag2 = chunkaccess.getBlockEntityNbtForSaving(blockpos); +- if (compoundtag2 != null) { +- listtag1.add(compoundtag2); ++ nbttagcompound2 = chunk.getBlockEntityNbtForSaving(blockposition); ++ if (nbttagcompound2 != null) { ++ nbttaglist1.add(nbttagcompound2); + } + } + +- compoundtag.put("block_entities", listtag1); +- if (chunkaccess.getStatus().getChunkType() == ChunkStatus.ChunkType.PROTOCHUNK) { +- ProtoChunk protochunk = (ProtoChunk) chunkaccess; +- ListTag listtag2 = new ListTag(); ++ nbttagcompound.put("block_entities", nbttaglist1); ++ if (chunk.getStatus().getChunkType() == ChunkStatus.Type.PROTOCHUNK) { ++ ProtoChunk protochunk = (ProtoChunk) chunk; ++ ListTag nbttaglist2 = new ListTag(); + +- listtag2.addAll(protochunk.getEntities()); +- compoundtag.put("entities", listtag2); +- compoundtag2 = new CompoundTag(); +- GenerationStep.Carving[] agenerationstep_carving = GenerationStep.Carving.values(); +- int k = agenerationstep_carving.length; ++ nbttaglist2.addAll(protochunk.getEntities()); ++ nbttagcompound.put("entities", nbttaglist2); ++ nbttagcompound2 = new CompoundTag(); ++ GenerationStep.Carving[] aworldgenstage_features = GenerationStep.Carving.values(); ++ int k = aworldgenstage_features.length; + + for (int l = 0; l < k; ++l) { +- GenerationStep.Carving generationstep_carving = agenerationstep_carving[l]; +- CarvingMask carvingmask = protochunk.getCarvingMask(generationstep_carving); ++ GenerationStep.Carving worldgenstage_features = aworldgenstage_features[l]; ++ CarvingMask carvingmask = protochunk.getCarvingMask(worldgenstage_features); + + if (carvingmask != null) { +- compoundtag2.putLongArray(generationstep_carving.toString(), carvingmask.toArray()); ++ nbttagcompound2.putLongArray(worldgenstage_features.toString(), carvingmask.toArray()); + } + } + +- compoundtag.put("CarvingMasks", compoundtag2); ++ nbttagcompound.put("CarvingMasks", nbttagcompound2); + } + +- saveTicks(serverlevel, compoundtag, chunkaccess.getTicksForSerialization()); +- compoundtag.put("PostProcessing", packOffsets(chunkaccess.getPostProcessing())); +- CompoundTag compoundtag3 = new CompoundTag(); +- Iterator iterator1 = chunkaccess.getHeightmaps().iterator(); ++ saveTicks(level, nbttagcompound, chunk.getTicksForSerialization()); ++ nbttagcompound.put("PostProcessing", packOffsets(chunk.getPostProcessing())); ++ CompoundTag nbttagcompound3 = new CompoundTag(); ++ Iterator iterator1 = chunk.getHeightmaps().iterator(); + + while (iterator1.hasNext()) { + Entry entry = (Entry) iterator1.next(); + +- if (chunkaccess.getStatus().heightmapsAfter().contains(entry.getKey())) { +- compoundtag3.put(((Heightmap.Types) entry.getKey()).getSerializationKey(), new LongArrayTag(((Heightmap) entry.getValue()).getRawData())); ++ if (chunk.getStatus().heightmapsAfter().contains(entry.getKey())) { ++ nbttagcompound3.put(((Heightmap.Types) entry.getKey()).getSerializationKey(), new LongArrayTag(((Heightmap) entry.getValue()).getRawData())); + } + } + +- compoundtag.put("Heightmaps", compoundtag3); +- compoundtag.put("structures", packStructureData(StructurePieceSerializationContext.fromLevel(serverlevel), chunkpos, chunkaccess.getAllStarts(), chunkaccess.getAllReferences())); +- return compoundtag; ++ nbttagcompound.put("Heightmaps", nbttagcompound3); ++ nbttagcompound.put("structures", packStructureData(StructurePieceSerializationContext.fromLevel(level), chunkcoordintpair, chunk.getAllStarts(), chunk.getAllReferences())); ++ // CraftBukkit start - store chunk persistent data in nbt ++ if (!chunk.persistentDataContainer.isEmpty()) { // SPIGOT-6814: Always save PDC to account for 1.17 to 1.18 chunk upgrading. ++ nbttagcompound.put("ChunkBukkitValues", chunk.persistentDataContainer.toTagCompound()); ++ } ++ // CraftBukkit end ++ return nbttagcompound; + } + +- private static void saveTicks(ServerLevel serverlevel, CompoundTag compoundtag, ChunkAccess.TicksToSave chunkaccess_tickstosave) { +- long i = serverlevel.getLevelData().getGameTime(); ++ private static void saveTicks(ServerLevel level, CompoundTag tag, ChunkAccess.a ticksToSave) { ++ long i = level.getLevelData().getGameTime(); + +- compoundtag.put("block_ticks", chunkaccess_tickstosave.blocks().save(i, (block) -> { ++ tag.put("block_ticks", ticksToSave.blocks().save(i, (block) -> { + return BuiltInRegistries.BLOCK.getKey(block).toString(); + })); +- compoundtag.put("fluid_ticks", chunkaccess_tickstosave.fluids().save(i, (fluid) -> { +- return BuiltInRegistries.FLUID.getKey(fluid).toString(); ++ tag.put("fluid_ticks", ticksToSave.fluids().save(i, (fluidtype) -> { ++ return BuiltInRegistries.FLUID.getKey(fluidtype).toString(); + })); + } + +- public static ChunkStatus.ChunkType getChunkTypeFromTag(@Nullable CompoundTag compoundtag) { +- return compoundtag != null ? ChunkStatus.byName(compoundtag.getString("Status")).getChunkType() : ChunkStatus.ChunkType.PROTOCHUNK; ++ public static ChunkStatus.Type getChunkTypeFromTag(@Nullable CompoundTag chunkNBT) { ++ return chunkNBT != null ? ChunkStatus.byName(chunkNBT.getString("Status")).getChunkType() : ChunkStatus.Type.PROTOCHUNK; + } + + @Nullable +- private static LevelChunk.PostLoadProcessor postLoadChunk(ServerLevel serverlevel, CompoundTag compoundtag) { +- ListTag listtag = getListOfCompoundsOrNull(compoundtag, "entities"); +- ListTag listtag1 = getListOfCompoundsOrNull(compoundtag, "block_entities"); ++ private static LevelChunk.PostLoadProcessor postLoadChunk(ServerLevel level, CompoundTag tag) { ++ ListTag nbttaglist = getListOfCompoundsOrNull(tag, "entities"); ++ ListTag nbttaglist1 = getListOfCompoundsOrNull(tag, "block_entities"); + +- return listtag == null && listtag1 == null ? null : (levelchunk) -> { +- if (listtag != null) { +- serverlevel.addLegacyChunkEntities(EntityType.loadEntitiesRecursive(listtag, serverlevel)); ++ return nbttaglist == null && nbttaglist1 == null ? null : (chunk) -> { ++ if (nbttaglist != null) { ++ level.addLegacyChunkEntities(EntityType.loadEntitiesRecursive(nbttaglist, level)); + } + +- if (listtag1 != null) { +- for (int i = 0; i < listtag1.size(); ++i) { +- CompoundTag compoundtag1 = listtag1.getCompound(i); +- boolean flag = compoundtag1.getBoolean("keepPacked"); ++ if (nbttaglist1 != null) { ++ for (int i = 0; i < nbttaglist1.size(); ++i) { ++ CompoundTag nbttagcompound1 = nbttaglist1.getCompound(i); ++ boolean flag = nbttagcompound1.getBoolean("keepPacked"); + + if (flag) { +- levelchunk.setBlockEntityNbt(compoundtag1); ++ chunk.setBlockEntityNbt(nbttagcompound1); + } else { +- BlockPos blockpos = BlockEntity.getPosFromTag(compoundtag1); +- BlockEntity blockentity = BlockEntity.loadStatic(blockpos, levelchunk.getBlockState(blockpos), compoundtag1); ++ BlockPos blockposition = BlockEntity.getPosFromTag(nbttagcompound1); ++ BlockEntity tileentity = BlockEntity.loadStatic(blockposition, chunk.getBlockState(blockposition), nbttagcompound1); + +- if (blockentity != null) { +- levelchunk.setBlockEntity(blockentity); ++ if (tileentity != null) { ++ chunk.setBlockEntity(tileentity); + } + } + } +@@ -491,58 +509,58 @@ + } + + @Nullable +- private static ListTag getListOfCompoundsOrNull(CompoundTag compoundtag, String s) { +- ListTag listtag = compoundtag.getList(s, 10); ++ private static ListTag getListOfCompoundsOrNull(CompoundTag tag, String key) { ++ ListTag nbttaglist = tag.getList(key, 10); + +- return listtag.isEmpty() ? null : listtag; ++ return nbttaglist.isEmpty() ? null : nbttaglist; + } + +- private static CompoundTag packStructureData(StructurePieceSerializationContext structurepieceserializationcontext, ChunkPos chunkpos, Map map, Map map1) { +- CompoundTag compoundtag = new CompoundTag(); +- CompoundTag compoundtag1 = new CompoundTag(); +- Registry registry = structurepieceserializationcontext.registryAccess().registryOrThrow(Registries.STRUCTURE); +- Iterator iterator = map.entrySet().iterator(); ++ private static CompoundTag packStructureData(StructurePieceSerializationContext context, ChunkPos pos, Map structureMap, Map referenceMap) { ++ CompoundTag nbttagcompound = new CompoundTag(); ++ CompoundTag nbttagcompound1 = new CompoundTag(); ++ Registry iregistry = context.registryAccess().registryOrThrow(Registries.STRUCTURE); ++ Iterator iterator = structureMap.entrySet().iterator(); + + while (iterator.hasNext()) { + Entry entry = (Entry) iterator.next(); +- ResourceLocation resourcelocation = registry.getKey((Structure) entry.getKey()); ++ ResourceLocation minecraftkey = iregistry.getKey((Structure) entry.getKey()); + +- compoundtag1.put(resourcelocation.toString(), ((StructureStart) entry.getValue()).createTag(structurepieceserializationcontext, chunkpos)); ++ nbttagcompound1.put(minecraftkey.toString(), ((StructureStart) entry.getValue()).createTag(context, pos)); + } + +- compoundtag.put("starts", compoundtag1); +- CompoundTag compoundtag2 = new CompoundTag(); +- Iterator iterator1 = map1.entrySet().iterator(); ++ nbttagcompound.put("starts", nbttagcompound1); ++ CompoundTag nbttagcompound2 = new CompoundTag(); ++ Iterator iterator1 = referenceMap.entrySet().iterator(); + + while (iterator1.hasNext()) { + Entry entry1 = (Entry) iterator1.next(); + + if (!((LongSet) entry1.getValue()).isEmpty()) { +- ResourceLocation resourcelocation1 = registry.getKey((Structure) entry1.getKey()); ++ ResourceLocation minecraftkey1 = iregistry.getKey((Structure) entry1.getKey()); + +- compoundtag2.put(resourcelocation1.toString(), new LongArrayTag((LongSet) entry1.getValue())); ++ nbttagcompound2.put(minecraftkey1.toString(), new LongArrayTag((LongSet) entry1.getValue())); + } + } + +- compoundtag.put("References", compoundtag2); +- return compoundtag; ++ nbttagcompound.put("References", nbttagcompound2); ++ return nbttagcompound; + } + +- private static Map unpackStructureStart(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag, long i) { ++ private static Map unpackStructureStart(StructurePieceSerializationContext context, CompoundTag tag, long seed) { + Map map = Maps.newHashMap(); +- Registry registry = structurepieceserializationcontext.registryAccess().registryOrThrow(Registries.STRUCTURE); +- CompoundTag compoundtag1 = compoundtag.getCompound("starts"); +- Iterator iterator = compoundtag1.getAllKeys().iterator(); ++ Registry iregistry = context.registryAccess().registryOrThrow(Registries.STRUCTURE); ++ CompoundTag nbttagcompound1 = tag.getCompound("starts"); ++ Iterator iterator = nbttagcompound1.getAllKeys().iterator(); + + while (iterator.hasNext()) { + String s = (String) iterator.next(); +- ResourceLocation resourcelocation = ResourceLocation.tryParse(s); +- Structure structure = (Structure) registry.get(resourcelocation); ++ ResourceLocation minecraftkey = ResourceLocation.tryParse(s); ++ Structure structure = (Structure) iregistry.get(minecraftkey); + + if (structure == null) { +- ChunkSerializer.LOGGER.error("Unknown structure start: {}", resourcelocation); ++ ChunkSerializer.LOGGER.error("Unknown structure start: {}", minecraftkey); + } else { +- StructureStart structurestart = StructureStart.loadStaticStart(structurepieceserializationcontext, compoundtag1.getCompound(s), i); ++ StructureStart structurestart = StructureStart.loadStaticStart(context, nbttagcompound1.getCompound(s), seed); + + if (structurestart != null) { + map.put(structure, structurestart); +@@ -553,28 +571,28 @@ + return map; + } + +- private static Map unpackStructureReferences(RegistryAccess registryaccess, ChunkPos chunkpos, CompoundTag compoundtag) { ++ private static Map unpackStructureReferences(RegistryAccess registryAccess, ChunkPos pos, CompoundTag tag) { + Map map = Maps.newHashMap(); +- Registry registry = registryaccess.registryOrThrow(Registries.STRUCTURE); +- CompoundTag compoundtag1 = compoundtag.getCompound("References"); +- Iterator iterator = compoundtag1.getAllKeys().iterator(); ++ Registry iregistry = registryAccess.registryOrThrow(Registries.STRUCTURE); ++ CompoundTag nbttagcompound1 = tag.getCompound("References"); ++ Iterator iterator = nbttagcompound1.getAllKeys().iterator(); + + while (iterator.hasNext()) { + String s = (String) iterator.next(); +- ResourceLocation resourcelocation = ResourceLocation.tryParse(s); +- Structure structure = (Structure) registry.get(resourcelocation); ++ ResourceLocation minecraftkey = ResourceLocation.tryParse(s); ++ Structure structure = (Structure) iregistry.get(minecraftkey); + + if (structure == null) { +- ChunkSerializer.LOGGER.warn("Found reference to unknown structure '{}' in chunk {}, discarding", resourcelocation, chunkpos); ++ ChunkSerializer.LOGGER.warn("Found reference to unknown structure '{}' in chunk {}, discarding", minecraftkey, pos); + } else { +- long[] along = compoundtag1.getLongArray(s); ++ long[] along = nbttagcompound1.getLongArray(s); + + if (along.length != 0) { + map.put(structure, new LongOpenHashSet(Arrays.stream(along).filter((i) -> { +- ChunkPos chunkpos1 = new ChunkPos(i); ++ ChunkPos chunkcoordintpair1 = new ChunkPos(i); + +- if (chunkpos1.getChessboardDistance(chunkpos) > 8) { +- ChunkSerializer.LOGGER.warn("Found invalid structure reference [ {} @ {} ] for chunk {}.", new Object[]{resourcelocation, chunkpos1, chunkpos}); ++ if (chunkcoordintpair1.getChessboardDistance(pos) > 8) { ++ ChunkSerializer.LOGGER.warn("Found invalid structure reference [ {} @ {} ] for chunk {}.", new Object[]{minecraftkey, chunkcoordintpair1, pos}); + return false; + } else { + return true; +@@ -587,14 +605,14 @@ + return map; + } + +- public static ListTag packOffsets(ShortList[] ashortlist) { +- ListTag listtag = new ListTag(); +- ShortList[] ashortlist1 = ashortlist; +- int i = ashortlist.length; ++ public static ListTag packOffsets(ShortList[] list) { ++ ListTag nbttaglist = new ListTag(); ++ ShortList[] ashortlist1 = list; ++ int i = list.length; + + for (int j = 0; j < i; ++j) { + ShortList shortlist = ashortlist1[j]; +- ListTag listtag1 = new ListTag(); ++ ListTag nbttaglist1 = new ListTag(); + + if (shortlist != null) { + ShortListIterator shortlistiterator = shortlist.iterator(); +@@ -602,13 +620,13 @@ + while (shortlistiterator.hasNext()) { + Short oshort = (Short) shortlistiterator.next(); + +- listtag1.add(ShortTag.valueOf(oshort)); ++ nbttaglist1.add(ShortTag.valueOf(oshort)); + } + } + +- listtag.add(listtag1); ++ nbttaglist.add(nbttaglist1); + } + +- return listtag; ++ return nbttaglist; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/storage/ChunkStorage.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/storage/ChunkStorage.java.patch new file mode 100644 index 0000000000..af7601d2ab --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/storage/ChunkStorage.java.patch @@ -0,0 +1,183 @@ +--- a/net/minecraft/world/level/chunk/storage/ChunkStorage.java ++++ b/net/minecraft/world/level/chunk/storage/ChunkStorage.java +@@ -12,10 +12,16 @@ + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtUtils; + import net.minecraft.resources.ResourceKey; ++import net.minecraft.server.level.ServerChunkCache; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.datafix.DataFixTypes; + import net.minecraft.world.level.ChunkPos; +-import net.minecraft.world.level.Level; ++import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.chunk.ChunkGenerator; ++// CraftBukkit start ++import java.util.concurrent.ExecutionException; ++import net.minecraft.world.level.chunk.ChunkStatus; ++import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.levelgen.structure.LegacyStructureDataHandler; + import net.minecraft.world.level.storage.DimensionDataStorage; + +@@ -27,74 +33,118 @@ + @Nullable + private volatile LegacyStructureDataHandler legacyStructureHandler; + +- public ChunkStorage(Path path, DataFixer datafixer, boolean flag) { +- this.fixerUpper = datafixer; +- this.worker = new IOWorker(path, flag, "chunk"); ++ public ChunkStorage(Path regionFolder, DataFixer fixerUpper, boolean sync) { ++ this.fixerUpper = fixerUpper; ++ this.worker = new IOWorker(regionFolder, sync, "chunk"); + } + +- public boolean isOldChunkAround(ChunkPos chunkpos, int i) { +- return this.worker.isOldChunkAround(chunkpos, i); ++ public boolean isOldChunkAround(ChunkPos pos, int radius) { ++ return this.worker.isOldChunkAround(pos, radius); + } + +- public CompoundTag upgradeChunkTag(ResourceKey resourcekey, Supplier supplier, CompoundTag compoundtag, Optional>> optional) { +- int i = getVersion(compoundtag); ++ // CraftBukkit start ++ private boolean check(ServerChunkCache cps, int x, int z) { ++ ChunkPos pos = new ChunkPos(x, z); ++ if (cps != null) { ++ com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); ++ if (cps.hasChunk(x, z)) { ++ return true; ++ } ++ } + ++ CompoundTag nbt; ++ try { ++ nbt = read(pos).get().orElse(null); ++ } catch (InterruptedException | ExecutionException ex) { ++ throw new RuntimeException(ex); ++ } ++ if (nbt != null) { ++ CompoundTag level = nbt.getCompound("Level"); ++ if (level.getBoolean("TerrainPopulated")) { ++ return true; ++ } ++ ++ ChunkStatus status = ChunkStatus.byName(level.getString("Status")); ++ if (status != null && status.isOrAfter(ChunkStatus.FEATURES)) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ public CompoundTag upgradeChunkTag(ResourceKey resourcekey, Supplier supplier, CompoundTag nbttagcompound, Optional>> optional, ChunkPos pos, @Nullable LevelAccessor generatoraccess) { ++ // CraftBukkit end ++ int i = getVersion(nbttagcompound); ++ ++ // CraftBukkit start ++ if (i < 1466) { ++ CompoundTag level = nbttagcompound.getCompound("Level"); ++ if (level.getBoolean("TerrainPopulated") && !level.getBoolean("LightPopulated")) { ++ ServerChunkCache cps = (generatoraccess == null) ? null : ((ServerLevel) generatoraccess).getChunkSource(); ++ if (check(cps, pos.x - 1, pos.z) && check(cps, pos.x - 1, pos.z - 1) && check(cps, pos.x, pos.z - 1)) { ++ level.putBoolean("LightPopulated", true); ++ } ++ } ++ } ++ // CraftBukkit end ++ + if (i < 1493) { +- compoundtag = DataFixTypes.CHUNK.update(this.fixerUpper, compoundtag, i, 1493); +- if (compoundtag.getCompound("Level").getBoolean("hasLegacyStructureData")) { +- LegacyStructureDataHandler legacystructuredatahandler = this.getLegacyStructureHandler(resourcekey, supplier); ++ nbttagcompound = DataFixTypes.CHUNK.update(this.fixerUpper, nbttagcompound, i, 1493); ++ if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) { ++ LegacyStructureDataHandler persistentstructurelegacy = this.getLegacyStructureHandler(resourcekey, supplier); + +- compoundtag = legacystructuredatahandler.updateFromLegacy(compoundtag); ++ nbttagcompound = persistentstructurelegacy.updateFromLegacy(nbttagcompound); + } + } + +- injectDatafixingContext(compoundtag, resourcekey, optional); +- compoundtag = DataFixTypes.CHUNK.updateToCurrentVersion(this.fixerUpper, compoundtag, Math.max(1493, i)); ++ injectDatafixingContext(nbttagcompound, resourcekey, optional); ++ nbttagcompound = DataFixTypes.CHUNK.updateToCurrentVersion(this.fixerUpper, nbttagcompound, Math.max(1493, i)); + if (i < SharedConstants.getCurrentVersion().getDataVersion().getVersion()) { +- NbtUtils.addCurrentDataVersion(compoundtag); ++ NbtUtils.addCurrentDataVersion(nbttagcompound); + } + +- compoundtag.remove("__context"); +- return compoundtag; ++ nbttagcompound.remove("__context"); ++ return nbttagcompound; + } + +- private LegacyStructureDataHandler getLegacyStructureHandler(ResourceKey resourcekey, Supplier supplier) { +- LegacyStructureDataHandler legacystructuredatahandler = this.legacyStructureHandler; ++ private LegacyStructureDataHandler getLegacyStructureHandler(ResourceKey level, Supplier storage) { // CraftBukkit ++ LegacyStructureDataHandler persistentstructurelegacy = this.legacyStructureHandler; + +- if (legacystructuredatahandler == null) { ++ if (persistentstructurelegacy == null) { + synchronized (this) { +- legacystructuredatahandler = this.legacyStructureHandler; +- if (legacystructuredatahandler == null) { +- this.legacyStructureHandler = legacystructuredatahandler = LegacyStructureDataHandler.getLegacyStructureHandler(resourcekey, (DimensionDataStorage) supplier.get()); ++ persistentstructurelegacy = this.legacyStructureHandler; ++ if (persistentstructurelegacy == null) { ++ this.legacyStructureHandler = persistentstructurelegacy = LegacyStructureDataHandler.getLegacyStructureHandler(level, (DimensionDataStorage) storage.get()); + } + } + } + +- return legacystructuredatahandler; ++ return persistentstructurelegacy; + } + +- public static void injectDatafixingContext(CompoundTag compoundtag, ResourceKey resourcekey, Optional>> optional) { +- CompoundTag compoundtag1 = new CompoundTag(); ++ public static void injectDatafixingContext(CompoundTag chunkData, ResourceKey levelKey, Optional>> chunkGeneratorKey) { // CraftBukkit ++ CompoundTag nbttagcompound1 = new CompoundTag(); + +- compoundtag1.putString("dimension", resourcekey.location().toString()); +- optional.ifPresent((resourcekey1) -> { +- compoundtag1.putString("generator", resourcekey1.location().toString()); ++ nbttagcompound1.putString("dimension", levelKey.location().toString()); ++ chunkGeneratorKey.ifPresent((resourcekey1) -> { ++ nbttagcompound1.putString("generator", resourcekey1.location().toString()); + }); +- compoundtag.put("__context", compoundtag1); ++ chunkData.put("__context", nbttagcompound1); + } + +- public static int getVersion(CompoundTag compoundtag) { +- return NbtUtils.getDataVersion(compoundtag, -1); ++ public static int getVersion(CompoundTag chunkData) { ++ return NbtUtils.getDataVersion(chunkData, -1); + } + +- public CompletableFuture> read(ChunkPos chunkpos) { +- return this.worker.loadAsync(chunkpos); ++ public CompletableFuture> read(ChunkPos chunkPos) { ++ return this.worker.loadAsync(chunkPos); + } + +- public void write(ChunkPos chunkpos, CompoundTag compoundtag) { +- this.worker.store(chunkpos, compoundtag); ++ public void write(ChunkPos chunkPos, CompoundTag chunkData) { ++ this.worker.store(chunkPos, chunkData); + if (this.legacyStructureHandler != null) { +- this.legacyStructureHandler.removeIndex(chunkpos.toLong()); ++ this.legacyStructureHandler.removeIndex(chunkPos.toLong()); + } + + } +@@ -103,7 +153,6 @@ + this.worker.synchronize(true).join(); + } + +- @Override + public void close() throws IOException { + this.worker.close(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/storage/RegionFile.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/storage/RegionFile.java.patch new file mode 100644 index 0000000000..b7280e4f64 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/storage/RegionFile.java.patch @@ -0,0 +1,414 @@ +--- a/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.world.level.chunk.storage; + + import com.google.common.annotations.VisibleForTesting; +@@ -44,38 +45,38 @@ + @VisibleForTesting + protected final RegionBitmap usedSectors; + +- public RegionFile(Path path, Path path1, boolean flag) throws IOException { +- this(path, path1, RegionFileVersion.VERSION_DEFLATE, flag); ++ public RegionFile(Path regionFile, Path containingFolder, boolean sync) throws IOException { ++ this(regionFile, containingFolder, RegionFileVersion.VERSION_DEFLATE, sync); + } + +- public RegionFile(Path path, Path path1, RegionFileVersion regionfileversion, boolean flag) throws IOException { ++ public RegionFile(Path regionFile, Path containingFolder, RegionFileVersion version, boolean sync) throws IOException { + this.header = ByteBuffer.allocateDirect(8192); + this.usedSectors = new RegionBitmap(); +- this.version = regionfileversion; +- if (!Files.isDirectory(path1, new LinkOption[0])) { +- throw new IllegalArgumentException("Expected directory, got " + path1.toAbsolutePath()); ++ this.version = version; ++ if (!Files.isDirectory(containingFolder, new LinkOption[0])) { ++ throw new IllegalArgumentException("Expected directory, got " + containingFolder.toAbsolutePath()); + } else { +- this.externalFileDir = path1; ++ this.externalFileDir = containingFolder; + this.offsets = this.header.asIntBuffer(); +- this.offsets.limit(1024); +- this.header.position(4096); ++ ((java.nio.Buffer) this.offsets).limit(1024); // CraftBukkit - decompile error ++ ((java.nio.Buffer) this.header).position(4096); // CraftBukkit - decompile error + this.timestamps = this.header.asIntBuffer(); +- if (flag) { +- this.file = FileChannel.open(path, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.DSYNC); ++ if (sync) { ++ this.file = FileChannel.open(regionFile, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.DSYNC); + } else { +- this.file = FileChannel.open(path, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE); ++ this.file = FileChannel.open(regionFile, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE); + } + + this.usedSectors.force(0, 2); +- this.header.position(0); ++ ((java.nio.Buffer) this.header).position(0); // CraftBukkit - decompile error + int i = this.file.read(this.header, 0L); + + if (i != -1) { + if (i != 8192) { +- RegionFile.LOGGER.warn("Region file {} has truncated header: {}", path, i); ++ RegionFile.LOGGER.warn("Region file {} has truncated header: {}", regionFile, i); + } + +- long j = Files.size(path); ++ long j = Files.size(regionFile); + + for (int k = 0; k < 1024; ++k) { + int l = this.offsets.get(k); +@@ -85,13 +86,13 @@ + int j1 = getNumSectors(l); + + if (i1 < 2) { +- RegionFile.LOGGER.warn("Region file {} has invalid sector at index: {}; sector {} overlaps with header", new Object[]{path, k, i1}); ++ RegionFile.LOGGER.warn("Region file {} has invalid sector at index: {}; sector {} overlaps with header", new Object[]{regionFile, k, i1}); + this.offsets.put(k, 0); + } else if (j1 == 0) { +- RegionFile.LOGGER.warn("Region file {} has an invalid sector at index: {}; size has to be > 0", path, k); ++ RegionFile.LOGGER.warn("Region file {} has an invalid sector at index: {}; size has to be > 0", regionFile, k); + this.offsets.put(k, 0); + } else if ((long) i1 * 4096L > j) { +- RegionFile.LOGGER.warn("Region file {} has an invalid sector at index: {}; sector {} is out of bounds", new Object[]{path, k, i1}); ++ RegionFile.LOGGER.warn("Region file {} has an invalid sector at index: {}; sector {} is out of bounds", new Object[]{regionFile, k, i1}); + this.offsets.put(k, 0); + } else { + this.usedSectors.force(i1, j1); +@@ -103,15 +104,15 @@ + } + } + +- private Path getExternalChunkPath(ChunkPos chunkpos) { +- String s = "c." + chunkpos.x + "." + chunkpos.z + ".mcc"; ++ private Path getExternalChunkPath(ChunkPos chunkPos) { ++ String s = "c." + chunkPos.x + "." + chunkPos.z + ".mcc"; + + return this.externalFileDir.resolve(s); + } + + @Nullable +- public synchronized DataInputStream getChunkDataInputStream(ChunkPos chunkpos) throws IOException { +- int i = this.getOffset(chunkpos); ++ public synchronized DataInputStream getChunkDataInputStream(ChunkPos chunkPos) throws IOException { ++ int i = this.getOffset(chunkPos); + + if (i == 0) { + return null; +@@ -122,16 +123,16 @@ + ByteBuffer bytebuffer = ByteBuffer.allocate(l); + + this.file.read(bytebuffer, (long) (j * 4096)); +- bytebuffer.flip(); ++ ((java.nio.Buffer) bytebuffer).flip(); // CraftBukkit - decompile error + if (bytebuffer.remaining() < 5) { +- RegionFile.LOGGER.error("Chunk {} header is truncated: expected {} but read {}", new Object[]{chunkpos, l, bytebuffer.remaining()}); ++ RegionFile.LOGGER.error("Chunk {} header is truncated: expected {} but read {}", new Object[]{chunkPos, l, bytebuffer.remaining()}); + return null; + } else { + int i1 = bytebuffer.getInt(); + byte b0 = bytebuffer.get(); + + if (i1 == 0) { +- RegionFile.LOGGER.warn("Chunk {} is allocated, but stream is missing", chunkpos); ++ RegionFile.LOGGER.warn("Chunk {} is allocated, but stream is missing", chunkPos); + return null; + } else { + int j1 = i1 - 1; +@@ -141,15 +142,15 @@ + RegionFile.LOGGER.warn("Chunk has both internal and external streams"); + } + +- return this.createExternalChunkInputStream(chunkpos, getExternalChunkVersion(b0)); ++ return this.createExternalChunkInputStream(chunkPos, getExternalChunkVersion(b0)); + } else if (j1 > bytebuffer.remaining()) { +- RegionFile.LOGGER.error("Chunk {} stream is truncated: expected {} but read {}", new Object[]{chunkpos, j1, bytebuffer.remaining()}); ++ RegionFile.LOGGER.error("Chunk {} stream is truncated: expected {} but read {}", new Object[]{chunkPos, j1, bytebuffer.remaining()}); + return null; + } else if (j1 < 0) { +- RegionFile.LOGGER.error("Declared size {} of chunk {} is negative", i1, chunkpos); ++ RegionFile.LOGGER.error("Declared size {} of chunk {} is negative", i1, chunkPos); + return null; + } else { +- return this.createChunkInputStream(chunkpos, b0, createStream(bytebuffer, j1)); ++ return this.createChunkInputStream(chunkPos, b0, createStream(bytebuffer, j1)); + } + } + } +@@ -160,60 +161,60 @@ + return (int) (Util.getEpochMillis() / 1000L); + } + +- private static boolean isExternalStreamChunk(byte b0) { +- return (b0 & 128) != 0; ++ private static boolean isExternalStreamChunk(byte versionByte) { ++ return (versionByte & 128) != 0; + } + +- private static byte getExternalChunkVersion(byte b0) { +- return (byte) (b0 & -129); ++ private static byte getExternalChunkVersion(byte versionByte) { ++ return (byte) (versionByte & -129); + } + + @Nullable +- private DataInputStream createChunkInputStream(ChunkPos chunkpos, byte b0, InputStream inputstream) throws IOException { +- RegionFileVersion regionfileversion = RegionFileVersion.fromId(b0); ++ private DataInputStream createChunkInputStream(ChunkPos chunkPos, byte versionByte, InputStream inputStream) throws IOException { ++ RegionFileVersion regionfilecompression = RegionFileVersion.fromId(versionByte); + +- if (regionfileversion == null) { +- RegionFile.LOGGER.error("Chunk {} has invalid chunk stream version {}", chunkpos, b0); ++ if (regionfilecompression == null) { ++ RegionFile.LOGGER.error("Chunk {} has invalid chunk stream version {}", chunkPos, versionByte); + return null; + } else { +- return new DataInputStream(regionfileversion.wrap(inputstream)); ++ return new DataInputStream(regionfilecompression.wrap(inputStream)); + } + } + + @Nullable +- private DataInputStream createExternalChunkInputStream(ChunkPos chunkpos, byte b0) throws IOException { +- Path path = this.getExternalChunkPath(chunkpos); ++ private DataInputStream createExternalChunkInputStream(ChunkPos chunkPos, byte versionByte) throws IOException { ++ Path path = this.getExternalChunkPath(chunkPos); + + if (!Files.isRegularFile(path, new LinkOption[0])) { + RegionFile.LOGGER.error("External chunk path {} is not file", path); + return null; + } else { +- return this.createChunkInputStream(chunkpos, b0, Files.newInputStream(path)); ++ return this.createChunkInputStream(chunkPos, versionByte, Files.newInputStream(path)); + } + } + +- private static ByteArrayInputStream createStream(ByteBuffer bytebuffer, int i) { +- return new ByteArrayInputStream(bytebuffer.array(), bytebuffer.position(), i); ++ private static ByteArrayInputStream createStream(ByteBuffer sourceBuffer, int length) { ++ return new ByteArrayInputStream(sourceBuffer.array(), sourceBuffer.position(), length); + } + +- private int packSectorOffset(int i, int j) { +- return i << 8 | j; ++ private int packSectorOffset(int sectorOffset, int sectorCount) { ++ return sectorOffset << 8 | sectorCount; + } + +- private static int getNumSectors(int i) { +- return i & 255; ++ private static int getNumSectors(int packedSectorOffset) { ++ return packedSectorOffset & 255; + } + +- private static int getSectorNumber(int i) { +- return i >> 8 & 16777215; ++ private static int getSectorNumber(int packedSectorOffset) { ++ return packedSectorOffset >> 8 & 16777215; + } + +- private static int sizeToSectors(int i) { +- return (i + 4096 - 1) / 4096; ++ private static int sizeToSectors(int size) { ++ return (size + 4096 - 1) / 4096; + } + +- public boolean doesChunkExist(ChunkPos chunkpos) { +- int i = this.getOffset(chunkpos); ++ public boolean doesChunkExist(ChunkPos chunkPos) { ++ int i = this.getOffset(chunkPos); + + if (i == 0) { + return false; +@@ -224,7 +225,7 @@ + + try { + this.file.read(bytebuffer, (long) (j * 4096)); +- bytebuffer.flip(); ++ ((java.nio.Buffer) bytebuffer).flip(); // CraftBukkit - decompile error + if (bytebuffer.remaining() != 5) { + return false; + } else { +@@ -236,7 +237,7 @@ + return false; + } + +- if (!Files.isRegularFile(this.getExternalChunkPath(chunkpos), new LinkOption[0])) { ++ if (!Files.isRegularFile(this.getExternalChunkPath(chunkPos), new LinkOption[0])) { + return false; + } + } else { +@@ -263,59 +264,59 @@ + } + } + +- public DataOutputStream getChunkDataOutputStream(ChunkPos chunkpos) throws IOException { +- return new DataOutputStream(this.version.wrap((OutputStream) (new RegionFile.ChunkBuffer(chunkpos)))); ++ public DataOutputStream getChunkDataOutputStream(ChunkPos chunkPos) throws IOException { ++ return new DataOutputStream(this.version.wrap((OutputStream) (new RegionFile.ChunkBuffer(chunkPos)))); + } + + public void flush() throws IOException { + this.file.force(true); + } + +- public void clear(ChunkPos chunkpos) throws IOException { +- int i = getOffsetIndex(chunkpos); ++ public void clear(ChunkPos chunkPos) throws IOException { ++ int i = getOffsetIndex(chunkPos); + int j = this.offsets.get(i); + + if (j != 0) { + this.offsets.put(i, 0); + this.timestamps.put(i, getTimestamp()); + this.writeHeader(); +- Files.deleteIfExists(this.getExternalChunkPath(chunkpos)); ++ Files.deleteIfExists(this.getExternalChunkPath(chunkPos)); + this.usedSectors.free(getSectorNumber(j), getNumSectors(j)); + } + } + +- protected synchronized void write(ChunkPos chunkpos, ByteBuffer bytebuffer) throws IOException { +- int i = getOffsetIndex(chunkpos); ++ protected synchronized void write(ChunkPos chunkPos, ByteBuffer chunkData) throws IOException { ++ int i = getOffsetIndex(chunkPos); + int j = this.offsets.get(i); + int k = getSectorNumber(j); + int l = getNumSectors(j); +- int i1 = bytebuffer.remaining(); ++ int i1 = chunkData.remaining(); + int j1 = sizeToSectors(i1); + int k1; +- RegionFile.CommitOp regionfile_commitop; ++ RegionFile.b regionfile_b; + + if (j1 >= 256) { +- Path path = this.getExternalChunkPath(chunkpos); ++ Path path = this.getExternalChunkPath(chunkPos); + +- RegionFile.LOGGER.warn("Saving oversized chunk {} ({} bytes} to external file {}", new Object[]{chunkpos, i1, path}); ++ RegionFile.LOGGER.warn("Saving oversized chunk {} ({} bytes} to external file {}", new Object[]{chunkPos, i1, path}); + j1 = 1; + k1 = this.usedSectors.allocate(j1); +- regionfile_commitop = this.writeToExternalFile(path, bytebuffer); ++ regionfile_b = this.writeToExternalFile(path, chunkData); + ByteBuffer bytebuffer1 = this.createExternalStub(); + + this.file.write(bytebuffer1, (long) (k1 * 4096)); + } else { + k1 = this.usedSectors.allocate(j1); +- regionfile_commitop = () -> { +- Files.deleteIfExists(this.getExternalChunkPath(chunkpos)); ++ regionfile_b = () -> { ++ Files.deleteIfExists(this.getExternalChunkPath(chunkPos)); + }; +- this.file.write(bytebuffer, (long) (k1 * 4096)); ++ this.file.write(chunkData, (long) (k1 * 4096)); + } + + this.offsets.put(i, this.packSectorOffset(k1, j1)); + this.timestamps.put(i, getTimestamp()); + this.writeHeader(); +- regionfile_commitop.run(); ++ regionfile_b.run(); + if (k != 0) { + this.usedSectors.free(k, l); + } +@@ -327,17 +328,17 @@ + + bytebuffer.putInt(1); + bytebuffer.put((byte) (this.version.getId() | 128)); +- bytebuffer.flip(); ++ ((java.nio.Buffer) bytebuffer).flip(); // CraftBukkit - decompile error + return bytebuffer; + } + +- private RegionFile.CommitOp writeToExternalFile(Path path, ByteBuffer bytebuffer) throws IOException { ++ private RegionFile.b writeToExternalFile(Path externalChunkFile, ByteBuffer chunkData) throws IOException { + Path path1 = Files.createTempFile(this.externalFileDir, "tmp", (String) null); + FileChannel filechannel = FileChannel.open(path1, StandardOpenOption.CREATE, StandardOpenOption.WRITE); + + try { +- bytebuffer.position(5); +- filechannel.write(bytebuffer); ++ ((java.nio.Buffer) chunkData).position(5); // CraftBukkit - decompile error ++ filechannel.write(chunkData); + } catch (Throwable throwable) { + if (filechannel != null) { + try { +@@ -355,28 +356,27 @@ + } + + return () -> { +- Files.move(path1, path, StandardCopyOption.REPLACE_EXISTING); ++ Files.move(path1, externalChunkFile, StandardCopyOption.REPLACE_EXISTING); + }; + } + + private void writeHeader() throws IOException { +- this.header.position(0); ++ ((java.nio.Buffer) this.header).position(0); // CraftBukkit - decompile error + this.file.write(this.header, 0L); + } + +- private int getOffset(ChunkPos chunkpos) { +- return this.offsets.get(getOffsetIndex(chunkpos)); ++ private int getOffset(ChunkPos chunkPos) { ++ return this.offsets.get(getOffsetIndex(chunkPos)); + } + +- public boolean hasChunk(ChunkPos chunkpos) { +- return this.getOffset(chunkpos) != 0; ++ public boolean hasChunk(ChunkPos chunkPos) { ++ return this.getOffset(chunkPos) != 0; + } + +- private static int getOffsetIndex(ChunkPos chunkpos) { +- return chunkpos.getRegionLocalX() + chunkpos.getRegionLocalZ() * 32; ++ private static int getOffsetIndex(ChunkPos chunkPos) { ++ return chunkPos.getRegionLocalX() + chunkPos.getRegionLocalZ() * 32; + } + +- @Override + public void close() throws IOException { + try { + this.padToFullSector(); +@@ -397,7 +397,7 @@ + if (i != j) { + ByteBuffer bytebuffer = RegionFile.PADDING_BUFFER.duplicate(); + +- bytebuffer.position(0); ++ ((java.nio.Buffer) bytebuffer).position(0); // CraftBukkit - decompile error + this.file.write(bytebuffer, (long) (j - 1)); + } + +@@ -407,17 +407,16 @@ + + private final ChunkPos pos; + +- public ChunkBuffer(ChunkPos chunkpos) { ++ public ChunkBuffer(ChunkPos chunkcoordintpair) { + super(8096); + super.write(0); + super.write(0); + super.write(0); + super.write(0); + super.write(RegionFile.this.version.getId()); +- this.pos = chunkpos; ++ this.pos = chunkcoordintpair; + } + +- @Override + public void close() throws IOException { + ByteBuffer bytebuffer = ByteBuffer.wrap(this.buf, 0, this.count); + +@@ -426,7 +425,7 @@ + } + } + +- private interface CommitOp { ++ private interface b { + + void run() throws IOException; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch new file mode 100644 index 0000000000..1ce22f83cc --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch @@ -0,0 +1,153 @@ +--- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -21,17 +21,17 @@ + + public static final String ANVIL_EXTENSION = ".mca"; + private static final int MAX_CACHE_SIZE = 256; +- private final Long2ObjectLinkedOpenHashMap regionCache = new Long2ObjectLinkedOpenHashMap(); ++ public final Long2ObjectLinkedOpenHashMap regionCache = new Long2ObjectLinkedOpenHashMap(); + private final Path folder; + private final boolean sync; + +- RegionFileStorage(Path path, boolean flag) { +- this.folder = path; +- this.sync = flag; ++ RegionFileStorage(Path folder, boolean sync) { ++ this.folder = folder; ++ this.sync = sync; + } + +- private RegionFile getRegionFile(ChunkPos chunkpos) throws IOException { +- long i = ChunkPos.asLong(chunkpos.getRegionX(), chunkpos.getRegionZ()); ++ private RegionFile getRegionFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit ++ long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); + RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i); + + if (regionfile != null) { +@@ -43,8 +43,9 @@ + + FileUtil.createDirectoriesSafe(this.folder); + Path path = this.folder; +- int j = chunkpos.getRegionX(); +- Path path1 = path.resolve("r." + j + "." + chunkpos.getRegionZ() + ".mca"); ++ int j = chunkcoordintpair.getRegionX(); ++ Path path1 = path.resolve("r." + j + "." + chunkcoordintpair.getRegionZ() + ".mca"); ++ if (existingOnly && !java.nio.file.Files.exists(path1)) return null; // CraftBukkit + RegionFile regionfile1 = new RegionFile(path1, this.folder, this.sync); + + this.regionCache.putAndMoveToFirst(i, regionfile1); +@@ -53,20 +54,25 @@ + } + + @Nullable +- public CompoundTag read(ChunkPos chunkpos) throws IOException { +- RegionFile regionfile = this.getRegionFile(chunkpos); +- DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkpos); ++ public CompoundTag read(ChunkPos chunkPos) throws IOException { ++ // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing ++ RegionFile regionfile = this.getRegionFile(chunkPos, true); ++ if (regionfile == null) { ++ return null; ++ } ++ // CraftBukkit end ++ DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkPos); + +- CompoundTag compoundtag; ++ CompoundTag nbttagcompound; + label43: + { + try { + if (datainputstream != null) { +- compoundtag = NbtIo.read((DataInput) datainputstream); ++ nbttagcompound = NbtIo.read((DataInput) datainputstream); + break label43; + } + +- compoundtag = null; ++ nbttagcompound = null; + } catch (Throwable throwable) { + if (datainputstream != null) { + try { +@@ -83,23 +89,28 @@ + datainputstream.close(); + } + +- return compoundtag; ++ return nbttagcompound; + } + + if (datainputstream != null) { + datainputstream.close(); + } + +- return compoundtag; ++ return nbttagcompound; + } + +- public void scanChunk(ChunkPos chunkpos, StreamTagVisitor streamtagvisitor) throws IOException { +- RegionFile regionfile = this.getRegionFile(chunkpos); +- DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkpos); ++ public void scanChunk(ChunkPos chunkPos, StreamTagVisitor visitor) throws IOException { ++ // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing ++ RegionFile regionfile = this.getRegionFile(chunkPos, true); ++ if (regionfile == null) { ++ return; ++ } ++ // CraftBukkit end ++ DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkPos); + + try { + if (datainputstream != null) { +- NbtIo.parse(datainputstream, streamtagvisitor, NbtAccounter.unlimitedHeap()); ++ NbtIo.parse(datainputstream, visitor, NbtAccounter.unlimitedHeap()); + } + } catch (Throwable throwable) { + if (datainputstream != null) { +@@ -119,16 +130,16 @@ + + } + +- protected void write(ChunkPos chunkpos, @Nullable CompoundTag compoundtag) throws IOException { +- RegionFile regionfile = this.getRegionFile(chunkpos); ++ protected void write(ChunkPos chunkPos, @Nullable CompoundTag chunkData) throws IOException { ++ RegionFile regionfile = this.getRegionFile(chunkPos, false); // CraftBukkit + +- if (compoundtag == null) { +- regionfile.clear(chunkpos); ++ if (chunkData == null) { ++ regionfile.clear(chunkPos); + } else { +- DataOutputStream dataoutputstream = regionfile.getChunkDataOutputStream(chunkpos); ++ DataOutputStream dataoutputstream = regionfile.getChunkDataOutputStream(chunkPos); + + try { +- NbtIo.write(compoundtag, (DataOutput) dataoutputstream); ++ NbtIo.write(chunkData, (DataOutput) dataoutputstream); + } catch (Throwable throwable) { + if (dataoutputstream != null) { + try { +@@ -148,9 +159,8 @@ + + } + +- @Override + public void close() throws IOException { +- ExceptionCollector exceptioncollector = new ExceptionCollector<>(); ++ ExceptionCollector exceptionsuppressor = new ExceptionCollector<>(); + ObjectIterator objectiterator = this.regionCache.values().iterator(); + + while (objectiterator.hasNext()) { +@@ -159,11 +169,11 @@ + try { + regionfile.close(); + } catch (IOException ioexception) { +- exceptioncollector.add(ioexception); ++ exceptionsuppressor.add(ioexception); + } + } + +- exceptioncollector.throwIfPresent(); ++ exceptionsuppressor.throwIfPresent(); + } + + public void flush() throws IOException { diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/dimension/end/EndDragonFight.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/dimension/end/EndDragonFight.java.patch new file mode 100644 index 0000000000..8849445398 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/dimension/end/EndDragonFight.java.patch @@ -0,0 +1,503 @@ +--- a/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -57,7 +57,7 @@ + import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; + import net.minecraft.world.level.levelgen.feature.EndPodiumFeature; + import net.minecraft.world.level.levelgen.feature.SpikeFeature; +-import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; ++import net.minecraft.world.level.levelgen.feature.configurations.WorldGenFeatureConfiguration; + import net.minecraft.world.phys.AABB; + import org.slf4j.Logger; + +@@ -73,8 +73,8 @@ + private static final int GATEWAY_DISTANCE = 96; + public static final int DRAGON_SPAWN_Y = 128; + private final Predicate validPlayer; +- private final ServerBossEvent dragonEvent; +- private final ServerLevel level; ++ public final ServerBossEvent dragonEvent; ++ public final ServerLevel level; + private final BlockPos origin; + private final ObjectArrayList gateways; + private final BlockPattern exitPortalPattern; +@@ -86,42 +86,42 @@ + private boolean previouslyKilled; + private boolean skipArenaLoadedCheck; + @Nullable +- private UUID dragonUUID; ++ public UUID dragonUUID; + private boolean needsStateScanning; + @Nullable +- private BlockPos portalLocation; ++ public BlockPos portalLocation; + @Nullable +- private DragonRespawnAnimation respawnStage; ++ public DragonRespawnAnimation respawnStage; + private int respawnTime; + @Nullable + private List respawnCrystals; + +- public EndDragonFight(ServerLevel serverlevel, long i, EndDragonFight.Data enddragonfight_data) { +- this(serverlevel, i, enddragonfight_data, BlockPos.ZERO); ++ public EndDragonFight(ServerLevel level, long seed, EndDragonFight.Data enderdragonbattle_a) { ++ this(level, seed, enderdragonbattle_a, BlockPos.ZERO); + } + +- public EndDragonFight(ServerLevel serverlevel, long i, EndDragonFight.Data enddragonfight_data, BlockPos blockpos) { ++ public EndDragonFight(ServerLevel level, long seed, EndDragonFight.Data enderdragonbattle_a, BlockPos data) { + this.dragonEvent = (ServerBossEvent) (new ServerBossEvent(Component.translatable("entity.minecraft.ender_dragon"), BossEvent.BossBarColor.PINK, BossEvent.BossBarOverlay.PROGRESS)).setPlayBossMusic(true).setCreateWorldFog(true); + this.gateways = new ObjectArrayList(); + this.ticksSinceLastPlayerScan = 21; + this.skipArenaLoadedCheck = false; + this.needsStateScanning = true; +- this.level = serverlevel; +- this.origin = blockpos; +- this.validPlayer = EntitySelector.ENTITY_STILL_ALIVE.and(EntitySelector.withinDistance((double) blockpos.getX(), (double) (128 + blockpos.getY()), (double) blockpos.getZ(), 192.0D)); +- this.needsStateScanning = enddragonfight_data.needsStateScanning; +- this.dragonUUID = (UUID) enddragonfight_data.dragonUUID.orElse((Object) null); +- this.dragonKilled = enddragonfight_data.dragonKilled; +- this.previouslyKilled = enddragonfight_data.previouslyKilled; +- if (enddragonfight_data.isRespawning) { ++ this.level = level; ++ this.origin = data; ++ this.validPlayer = EntitySelector.ENTITY_STILL_ALIVE.and(EntitySelector.withinDistance((double) data.getX(), (double) (128 + data.getY()), (double) data.getZ(), 192.0D)); ++ this.needsStateScanning = enderdragonbattle_a.needsStateScanning; ++ this.dragonUUID = (UUID) enderdragonbattle_a.dragonUUID.orElse(null); // CraftBukkit - decompile error ++ this.dragonKilled = enderdragonbattle_a.dragonKilled; ++ this.previouslyKilled = enderdragonbattle_a.previouslyKilled; ++ if (enderdragonbattle_a.isRespawning) { + this.respawnStage = DragonRespawnAnimation.START; + } + +- this.portalLocation = (BlockPos) enddragonfight_data.exitPortalLocation.orElse((Object) null); +- this.gateways.addAll((Collection) enddragonfight_data.gateways.orElseGet(() -> { ++ this.portalLocation = (BlockPos) enderdragonbattle_a.exitPortalLocation.orElse(null); // CraftBukkit - decompile error ++ this.gateways.addAll((Collection) enderdragonbattle_a.gateways.orElseGet(() -> { + ObjectArrayList objectarraylist = new ObjectArrayList(ContiguousSet.create(Range.closedOpen(0, 20), DiscreteDomain.integers())); + +- Util.shuffle(objectarraylist, RandomSource.create(i)); ++ Util.shuffle(objectarraylist, RandomSource.create(seed)); + return objectarraylist; + })); + this.exitPortalPattern = BlockPatternBuilder.start().aisle(" ", " ", " ", " # ", " ", " ", " ").aisle(" ", " ", " ", " # ", " ", " ", " ").aisle(" ", " ", " ", " # ", " ", " ", " ").aisle(" ### ", " # # ", "# #", "# # #", "# #", " # # ", " ### ").aisle(" ", " ### ", " ##### ", " ##### ", " ##### ", " ### ", " ").where('#', BlockInWorld.hasState(BlockPredicate.forBlock(Blocks.BEDROCK))).build(); +@@ -200,14 +200,14 @@ + if (list.isEmpty()) { + this.dragonKilled = true; + } else { +- EnderDragon enderdragon = (EnderDragon) list.get(0); ++ EnderDragon entityenderdragon = (EnderDragon) list.get(0); + +- this.dragonUUID = enderdragon.getUUID(); +- EndDragonFight.LOGGER.info("Found that there's a dragon still alive ({})", enderdragon); ++ this.dragonUUID = entityenderdragon.getUUID(); ++ EndDragonFight.LOGGER.info("Found that there's a dragon still alive ({})", entityenderdragon); + this.dragonKilled = false; + if (!flag) { + EndDragonFight.LOGGER.info("But we didn't have a portal, let's remove it."); +- enderdragon.discard(); ++ entityenderdragon.discard(); + this.dragonUUID = null; + } + } +@@ -231,27 +231,27 @@ + + } + +- protected void setRespawnStage(DragonRespawnAnimation dragonrespawnanimation) { ++ public void setRespawnStage(DragonRespawnAnimation state) { + if (this.respawnStage == null) { + throw new IllegalStateException("Dragon respawn isn't in progress, can't skip ahead in the animation."); + } else { + this.respawnTime = 0; +- if (dragonrespawnanimation == DragonRespawnAnimation.END) { ++ if (state == DragonRespawnAnimation.END) { + this.respawnStage = null; + this.dragonKilled = false; +- EnderDragon enderdragon = this.createNewDragon(); ++ EnderDragon entityenderdragon = this.createNewDragon(); + +- if (enderdragon != null) { ++ if (entityenderdragon != null) { + Iterator iterator = this.dragonEvent.getPlayers().iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- CriteriaTriggers.SUMMONED_ENTITY.trigger(serverplayer, (Entity) enderdragon); ++ CriteriaTriggers.SUMMONED_ENTITY.trigger(entityplayer, (Entity) entityenderdragon); + } + } + } else { +- this.respawnStage = dragonrespawnanimation; ++ this.respawnStage = state; + } + + } +@@ -263,10 +263,10 @@ + + label27: + while (j <= 8) { +- LevelChunk levelchunk = this.level.getChunk(i, j); +- Iterator iterator = levelchunk.getBlockEntities().values().iterator(); ++ LevelChunk chunk = this.level.getChunk(i, j); ++ Iterator iterator = chunk.getBlockEntities().values().iterator(); + +- BlockEntity blockentity; ++ BlockEntity tileentity; + + do { + if (!iterator.hasNext()) { +@@ -274,8 +274,8 @@ + continue label27; + } + +- blockentity = (BlockEntity) iterator.next(); +- } while (!(blockentity instanceof TheEndPortalBlockEntity)); ++ tileentity = (BlockEntity) iterator.next(); ++ } while (!(tileentity instanceof TheEndPortalBlockEntity)); + + return true; + } +@@ -285,49 +285,49 @@ + } + + @Nullable +- private BlockPattern.BlockPatternMatch findExitPortal() { +- ChunkPos chunkpos = new ChunkPos(this.origin); ++ public BlockPattern.BlockPatternMatch findExitPortal() { ++ ChunkPos chunkcoordintpair = new ChunkPos(this.origin); + + int i; + +- for (int j = -8 + chunkpos.x; j <= 8 + chunkpos.x; ++j) { +- for (i = -8 + chunkpos.z; i <= 8 + chunkpos.z; ++i) { +- LevelChunk levelchunk = this.level.getChunk(j, i); +- Iterator iterator = levelchunk.getBlockEntities().values().iterator(); ++ for (int j = -8 + chunkcoordintpair.x; j <= 8 + chunkcoordintpair.x; ++j) { ++ for (i = -8 + chunkcoordintpair.z; i <= 8 + chunkcoordintpair.z; ++i) { ++ LevelChunk chunk = this.level.getChunk(j, i); ++ Iterator iterator = chunk.getBlockEntities().values().iterator(); + + while (iterator.hasNext()) { +- BlockEntity blockentity = (BlockEntity) iterator.next(); ++ BlockEntity tileentity = (BlockEntity) iterator.next(); + +- if (blockentity instanceof TheEndPortalBlockEntity) { +- BlockPattern.BlockPatternMatch blockpattern_blockpatternmatch = this.exitPortalPattern.find(this.level, blockentity.getBlockPos()); ++ if (tileentity instanceof TheEndPortalBlockEntity) { ++ BlockPattern.BlockPatternMatch shapedetector_shapedetectorcollection = this.exitPortalPattern.find(this.level, tileentity.getBlockPos()); + +- if (blockpattern_blockpatternmatch != null) { +- BlockPos blockpos = blockpattern_blockpatternmatch.getBlock(3, 3, 3).getPos(); ++ if (shapedetector_shapedetectorcollection != null) { ++ BlockPos blockposition = shapedetector_shapedetectorcollection.getBlock(3, 3, 3).getPos(); + + if (this.portalLocation == null) { +- this.portalLocation = blockpos; ++ this.portalLocation = blockposition; + } + +- return blockpattern_blockpatternmatch; ++ return shapedetector_shapedetectorcollection; + } + } + } + } + } + +- BlockPos blockpos1 = EndPodiumFeature.getLocation(this.origin); ++ BlockPos blockposition1 = EndPodiumFeature.getLocation(this.origin); + +- i = this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, blockpos1).getY(); ++ i = this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, blockposition1).getY(); + + for (int k = i; k >= this.level.getMinBuildHeight(); --k) { +- BlockPattern.BlockPatternMatch blockpattern_blockpatternmatch1 = this.exitPortalPattern.find(this.level, new BlockPos(blockpos1.getX(), k, blockpos1.getZ())); ++ BlockPattern.BlockPatternMatch shapedetector_shapedetectorcollection1 = this.exitPortalPattern.find(this.level, new BlockPos(blockposition1.getX(), k, blockposition1.getZ())); + +- if (blockpattern_blockpatternmatch1 != null) { ++ if (shapedetector_shapedetectorcollection1 != null) { + if (this.portalLocation == null) { +- this.portalLocation = blockpattern_blockpatternmatch1.getBlock(3, 3, 3).getPos(); ++ this.portalLocation = shapedetector_shapedetectorcollection1.getBlock(3, 3, 3).getPos(); + } + +- return blockpattern_blockpatternmatch1; ++ return shapedetector_shapedetectorcollection1; + } + } + +@@ -338,17 +338,17 @@ + if (this.skipArenaLoadedCheck) { + return true; + } else { +- ChunkPos chunkpos = new ChunkPos(this.origin); ++ ChunkPos chunkcoordintpair = new ChunkPos(this.origin); + +- for (int i = -8 + chunkpos.x; i <= 8 + chunkpos.x; ++i) { +- for (int j = 8 + chunkpos.z; j <= 8 + chunkpos.z; ++j) { +- ChunkAccess chunkaccess = this.level.getChunk(i, j, ChunkStatus.FULL, false); ++ for (int i = -8 + chunkcoordintpair.x; i <= 8 + chunkcoordintpair.x; ++i) { ++ for (int j = 8 + chunkcoordintpair.z; j <= 8 + chunkcoordintpair.z; ++j) { ++ ChunkAccess ichunkaccess = this.level.getChunk(i, j, ChunkStatus.FULL, false); + +- if (!(chunkaccess instanceof LevelChunk)) { ++ if (!(ichunkaccess instanceof LevelChunk)) { + return false; + } + +- FullChunkStatus fullchunkstatus = ((LevelChunk) chunkaccess).getFullStatus(); ++ FullChunkStatus fullchunkstatus = ((LevelChunk) ichunkaccess).getFullStatus(); + + if (!fullchunkstatus.isOrAfter(FullChunkStatus.BLOCK_TICKING)) { + return false; +@@ -365,10 +365,10 @@ + Iterator iterator = this.level.getPlayers(this.validPlayer).iterator(); + + while (iterator.hasNext()) { +- ServerPlayer serverplayer = (ServerPlayer) iterator.next(); ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); + +- this.dragonEvent.addPlayer(serverplayer); +- set.add(serverplayer); ++ this.dragonEvent.addPlayer(entityplayer); ++ set.add(entityplayer); + } + + Set set1 = Sets.newHashSet(this.dragonEvent.getPlayers()); +@@ -377,9 +377,9 @@ + Iterator iterator1 = set1.iterator(); + + while (iterator1.hasNext()) { +- ServerPlayer serverplayer1 = (ServerPlayer) iterator1.next(); ++ ServerPlayer entityplayer1 = (ServerPlayer) iterator1.next(); + +- this.dragonEvent.removePlayer(serverplayer1); ++ this.dragonEvent.removePlayer(entityplayer1); + } + + } +@@ -388,17 +388,17 @@ + this.ticksSinceCrystalsScanned = 0; + this.crystalsAlive = 0; + +- SpikeFeature.EndSpike spikefeature_endspike; ++ SpikeFeature.EndSpike worldgenender_spike; + +- for (Iterator iterator = SpikeFeature.getSpikesForLevel(this.level).iterator(); iterator.hasNext(); this.crystalsAlive += this.level.getEntitiesOfClass(EndCrystal.class, spikefeature_endspike.getTopBoundingBox()).size()) { +- spikefeature_endspike = (SpikeFeature.EndSpike) iterator.next(); ++ for (Iterator iterator = SpikeFeature.getSpikesForLevel(this.level).iterator(); iterator.hasNext(); this.crystalsAlive += this.level.getEntitiesOfClass(EndCrystal.class, worldgenender_spike.getTopBoundingBox()).size()) { ++ worldgenender_spike = (SpikeFeature.EndSpike) iterator.next(); + } + + EndDragonFight.LOGGER.debug("Found {} end crystals still alive", this.crystalsAlive); + } + +- public void setDragonKilled(EnderDragon enderdragon) { +- if (enderdragon.getUUID().equals(this.dragonUUID)) { ++ public void setDragonKilled(EnderDragon dragon) { ++ if (dragon.getUUID().equals(this.dragonUUID)) { + this.dragonEvent.setProgress(0.0F); + this.dragonEvent.setVisible(false); + this.spawnExitPortal(true); +@@ -430,17 +430,17 @@ + } + } + +- private void spawnNewGateway(BlockPos blockpos) { +- this.level.levelEvent(3000, blockpos, 0); +- this.level.registryAccess().registry(Registries.CONFIGURED_FEATURE).flatMap((registry) -> { +- return registry.getHolder(EndFeatures.END_GATEWAY_DELAYED); +- }).ifPresent((holder_reference) -> { +- ((ConfiguredFeature) holder_reference.value()).place(this.level, this.level.getChunkSource().getGenerator(), RandomSource.create(), blockpos); ++ private void spawnNewGateway(BlockPos pos) { ++ this.level.levelEvent(3000, pos, 0); ++ this.level.registryAccess().registry(Registries.CONFIGURED_FEATURE).flatMap((iregistry) -> { ++ return iregistry.getHolder(EndFeatures.END_GATEWAY_DELAYED); ++ }).ifPresent((holder_c) -> { ++ ((ConfiguredFeature) holder_c.value()).place(this.level, this.level.getChunkSource().getGenerator(), RandomSource.create(), pos); + }); + } + +- private void spawnExitPortal(boolean flag) { +- EndPodiumFeature endpodiumfeature = new EndPodiumFeature(flag); ++ public void spawnExitPortal(boolean active) { ++ EndPodiumFeature worldgenendtrophy = new EndPodiumFeature(active); + + if (this.portalLocation == null) { + for (this.portalLocation = this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.origin)).below(); this.level.getBlockState(this.portalLocation).is(Blocks.BEDROCK) && this.portalLocation.getY() > this.level.getSeaLevel(); this.portalLocation = this.portalLocation.below()) { +@@ -448,7 +448,7 @@ + } + } + +- if (endpodiumfeature.place(FeatureConfiguration.NONE, this.level, this.level.getChunkSource().getGenerator(), RandomSource.create(), this.portalLocation)) { ++ if (worldgenendtrophy.place(WorldGenFeatureConfiguration.NONE, this.level, this.level.getChunkSource().getGenerator(), RandomSource.create(), this.portalLocation)) { + int i = Mth.positiveCeilDiv(4, 16); + + this.level.getChunkSource().chunkMap.waitForLightBeforeSending(new ChunkPos(this.portalLocation), i); +@@ -459,26 +459,26 @@ + @Nullable + private EnderDragon createNewDragon() { + this.level.getChunkAt(new BlockPos(this.origin.getX(), 128 + this.origin.getY(), this.origin.getZ())); +- EnderDragon enderdragon = (EnderDragon) EntityType.ENDER_DRAGON.create(this.level); ++ EnderDragon entityenderdragon = (EnderDragon) EntityType.ENDER_DRAGON.create(this.level); + +- if (enderdragon != null) { +- enderdragon.setDragonFight(this); +- enderdragon.setFightOrigin(this.origin); +- enderdragon.getPhaseManager().setPhase(EnderDragonPhase.HOLDING_PATTERN); +- enderdragon.moveTo((double) this.origin.getX(), (double) (128 + this.origin.getY()), (double) this.origin.getZ(), this.level.random.nextFloat() * 360.0F, 0.0F); +- this.level.addFreshEntity(enderdragon); +- this.dragonUUID = enderdragon.getUUID(); ++ if (entityenderdragon != null) { ++ entityenderdragon.setDragonFight(this); ++ entityenderdragon.setFightOrigin(this.origin); ++ entityenderdragon.getPhaseManager().setPhase(EnderDragonPhase.HOLDING_PATTERN); ++ entityenderdragon.moveTo((double) this.origin.getX(), (double) (128 + this.origin.getY()), (double) this.origin.getZ(), this.level.random.nextFloat() * 360.0F, 0.0F); ++ this.level.addFreshEntity(entityenderdragon); ++ this.dragonUUID = entityenderdragon.getUUID(); + } + +- return enderdragon; ++ return entityenderdragon; + } + +- public void updateDragon(EnderDragon enderdragon) { +- if (enderdragon.getUUID().equals(this.dragonUUID)) { +- this.dragonEvent.setProgress(enderdragon.getHealth() / enderdragon.getMaxHealth()); ++ public void updateDragon(EnderDragon dragon) { ++ if (dragon.getUUID().equals(this.dragonUUID)) { ++ this.dragonEvent.setProgress(dragon.getHealth() / dragon.getMaxHealth()); + this.ticksSinceDragonSeen = 0; +- if (enderdragon.hasCustomName()) { +- this.dragonEvent.setName(enderdragon.getDisplayName()); ++ if (dragon.hasCustomName()) { ++ this.dragonEvent.setName(dragon.getDisplayName()); + } + } + +@@ -488,8 +488,8 @@ + return this.crystalsAlive; + } + +- public void onCrystalDestroyed(EndCrystal endcrystal, DamageSource damagesource) { +- if (this.respawnStage != null && this.respawnCrystals.contains(endcrystal)) { ++ public void onCrystalDestroyed(EndCrystal crystal, DamageSource dmgSrc) { ++ if (this.respawnStage != null && this.respawnCrystals.contains(crystal)) { + EndDragonFight.LOGGER.debug("Aborting respawn sequence"); + this.respawnStage = null; + this.respawnTime = 0; +@@ -500,7 +500,7 @@ + Entity entity = this.level.getEntity(this.dragonUUID); + + if (entity instanceof EnderDragon) { +- ((EnderDragon) entity).onCrystalDestroyed(endcrystal, endcrystal.blockPosition(), damagesource); ++ ((EnderDragon) entity).onCrystalDestroyed(crystal, crystal.blockPosition(), dmgSrc); + } + } + +@@ -510,55 +510,55 @@ + return this.previouslyKilled; + } + +- public void tryRespawn() { ++ public boolean tryRespawn() { // CraftBukkit - return boolean + if (this.dragonKilled && this.respawnStage == null) { +- BlockPos blockpos = this.portalLocation; ++ BlockPos blockposition = this.portalLocation; + +- if (blockpos == null) { ++ if (blockposition == null) { + EndDragonFight.LOGGER.debug("Tried to respawn, but need to find the portal first."); +- BlockPattern.BlockPatternMatch blockpattern_blockpatternmatch = this.findExitPortal(); ++ BlockPattern.BlockPatternMatch shapedetector_shapedetectorcollection = this.findExitPortal(); + +- if (blockpattern_blockpatternmatch == null) { ++ if (shapedetector_shapedetectorcollection == null) { + EndDragonFight.LOGGER.debug("Couldn't find a portal, so we made one."); + this.spawnExitPortal(true); + } else { + EndDragonFight.LOGGER.debug("Found the exit portal & saved its location for next time."); + } + +- blockpos = this.portalLocation; ++ blockposition = this.portalLocation; + } + + List list = Lists.newArrayList(); +- BlockPos blockpos1 = blockpos.above(1); ++ BlockPos blockposition1 = blockposition.above(1); + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); +- List list1 = this.level.getEntitiesOfClass(EndCrystal.class, new AABB(blockpos1.relative(direction, 2))); ++ Direction enumdirection = (Direction) iterator.next(); ++ List list1 = this.level.getEntitiesOfClass(EndCrystal.class, new AABB(blockposition1.relative(enumdirection, 2))); + + if (list1.isEmpty()) { +- return; ++ return false; // CraftBukkit - return value + } + + list.addAll(list1); + } + + EndDragonFight.LOGGER.debug("Found all crystals, respawning dragon."); +- this.respawnDragon(list); ++ return this.respawnDragon(list); // CraftBukkit - return value + } +- ++ return false; // CraftBukkit - return value + } + +- private void respawnDragon(List list) { ++ public boolean respawnDragon(List list) { // CraftBukkit - return boolean + if (this.dragonKilled && this.respawnStage == null) { +- for (BlockPattern.BlockPatternMatch blockpattern_blockpatternmatch = this.findExitPortal(); blockpattern_blockpatternmatch != null; blockpattern_blockpatternmatch = this.findExitPortal()) { ++ for (BlockPattern.BlockPatternMatch shapedetector_shapedetectorcollection = this.findExitPortal(); shapedetector_shapedetectorcollection != null; shapedetector_shapedetectorcollection = this.findExitPortal()) { + for (int i = 0; i < this.exitPortalPattern.getWidth(); ++i) { + for (int j = 0; j < this.exitPortalPattern.getHeight(); ++j) { + for (int k = 0; k < this.exitPortalPattern.getDepth(); ++k) { +- BlockInWorld blockinworld = blockpattern_blockpatternmatch.getBlock(i, j, k); ++ BlockInWorld shapedetectorblock = shapedetector_shapedetectorcollection.getBlock(i, j, k); + +- if (blockinworld.getState().is(Blocks.BEDROCK) || blockinworld.getState().is(Blocks.END_PORTAL)) { +- this.level.setBlockAndUpdate(blockinworld.getPos(), Blocks.END_STONE.defaultBlockState()); ++ if (shapedetectorblock.getState().is(Blocks.BEDROCK) || shapedetectorblock.getState().is(Blocks.END_PORTAL)) { ++ this.level.setBlockAndUpdate(shapedetectorblock.getPos(), Blocks.END_STONE.defaultBlockState()); + } + } + } +@@ -569,23 +569,24 @@ + this.respawnTime = 0; + this.spawnExitPortal(false); + this.respawnCrystals = list; ++ return true; // CraftBukkit - return value + } +- ++ return false; // CraftBukkit - return value + } + + public void resetSpikeCrystals() { + Iterator iterator = SpikeFeature.getSpikesForLevel(this.level).iterator(); + + while (iterator.hasNext()) { +- SpikeFeature.EndSpike spikefeature_endspike = (SpikeFeature.EndSpike) iterator.next(); +- List list = this.level.getEntitiesOfClass(EndCrystal.class, spikefeature_endspike.getTopBoundingBox()); ++ SpikeFeature.EndSpike worldgenender_spike = (SpikeFeature.EndSpike) iterator.next(); ++ List list = this.level.getEntitiesOfClass(EndCrystal.class, worldgenender_spike.getTopBoundingBox()); + Iterator iterator1 = list.iterator(); + + while (iterator1.hasNext()) { +- EndCrystal endcrystal = (EndCrystal) iterator1.next(); ++ EndCrystal entityendercrystal = (EndCrystal) iterator1.next(); + +- endcrystal.setInvulnerable(false); +- endcrystal.setBeamTarget((BlockPos) null); ++ entityendercrystal.setInvulnerable(false); ++ entityendercrystal.setBeamTarget((BlockPos) null); + } + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/entity/PersistentEntitySectionManager.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/entity/PersistentEntitySectionManager.java.patch new file mode 100644 index 0000000000..6472285dee --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/entity/PersistentEntitySectionManager.java.patch @@ -0,0 +1,469 @@ +--- a/net/minecraft/world/level/entity/PersistentEntitySectionManager.java ++++ b/net/minecraft/world/level/entity/PersistentEntitySectionManager.java +@@ -29,121 +29,135 @@ + import net.minecraft.util.CsvOutput; + import net.minecraft.util.VisibleForDebug; + import net.minecraft.world.entity.Entity; +-import net.minecraft.world.level.ChunkPos; + import org.slf4j.Logger; ++import net.minecraft.world.level.ChunkPos; ++// CraftBukkit start ++import net.minecraft.world.level.chunk.storage.EntityStorage; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class PersistentEntitySectionManager implements AutoCloseable { + + static final Logger LOGGER = LogUtils.getLogger(); + final Set knownUuids = Sets.newHashSet(); + final LevelCallback callbacks; +- private final EntityPersistentStorage permanentStorage; ++ public final EntityPersistentStorage permanentStorage; + private final EntityLookup visibleEntityStorage = new EntityLookup<>(); + final EntitySectionStorage sectionStorage; + private final LevelEntityGetter entityGetter; + private final Long2ObjectMap chunkVisibility = new Long2ObjectOpenHashMap(); +- private final Long2ObjectMap chunkLoadStatuses = new Long2ObjectOpenHashMap(); ++ private final Long2ObjectMap chunkLoadStatuses = new Long2ObjectOpenHashMap(); + private final LongSet chunksToUnload = new LongOpenHashSet(); + private final Queue> loadingInbox = Queues.newConcurrentLinkedQueue(); + +- public PersistentEntitySectionManager(Class oclass, LevelCallback levelcallback, EntityPersistentStorage entitypersistentstorage) { +- this.sectionStorage = new EntitySectionStorage<>(oclass, this.chunkVisibility); ++ public PersistentEntitySectionManager(Class entityClass, LevelCallback callbacks, EntityPersistentStorage permanentStorage) { ++ this.sectionStorage = new EntitySectionStorage<>(entityClass, this.chunkVisibility); + this.chunkVisibility.defaultReturnValue(Visibility.HIDDEN); +- this.chunkLoadStatuses.defaultReturnValue(PersistentEntitySectionManager.ChunkLoadStatus.FRESH); +- this.callbacks = levelcallback; +- this.permanentStorage = entitypersistentstorage; ++ this.chunkLoadStatuses.defaultReturnValue(PersistentEntitySectionManager.b.FRESH); ++ this.callbacks = callbacks; ++ this.permanentStorage = permanentStorage; + this.entityGetter = new LevelEntityGetterAdapter<>(this.visibleEntityStorage, this.sectionStorage); + } + +- void removeSectionIfEmpty(long i, EntitySection entitysection) { ++ // CraftBukkit start - add method to get all entities in chunk ++ public List getEntities(ChunkPos chunkCoordIntPair) { ++ return sectionStorage.getExistingSectionsInChunk(chunkCoordIntPair.toLong()).flatMap(EntitySection::getEntities).map(entity -> (Entity) entity).collect(Collectors.toList()); ++ } ++ ++ public boolean isPending(long pair) { ++ return chunkLoadStatuses.get(pair) == b.PENDING; ++ } ++ // CraftBukkit end ++ ++ void removeSectionIfEmpty(long sectionKey, EntitySection entitysection) { + if (entitysection.isEmpty()) { +- this.sectionStorage.remove(i); ++ this.sectionStorage.remove(sectionKey); + } + + } + +- private boolean addEntityUuid(T t0) { +- if (!this.knownUuids.add(t0.getUUID())) { +- PersistentEntitySectionManager.LOGGER.warn("UUID of added entity already exists: {}", t0); ++ private boolean addEntityUuid(T entity) { ++ if (!this.knownUuids.add(entity.getUUID())) { ++ PersistentEntitySectionManager.LOGGER.warn("UUID of added entity already exists: {}", entity); + return false; + } else { + return true; + } + } + +- public boolean addNewEntity(T t0) { +- return this.addEntity(t0, false); ++ public boolean addNewEntity(T entity) { ++ return this.addEntity(entity, false); + } + +- private boolean addEntity(T t0, boolean flag) { +- if (!this.addEntityUuid(t0)) { ++ private boolean addEntity(T entity, boolean worldGenSpawned) { ++ if (!this.addEntityUuid(entity)) { + return false; + } else { +- long i = SectionPos.asLong(t0.blockPosition()); ++ long i = SectionPos.asLong(entity.blockPosition()); + EntitySection entitysection = this.sectionStorage.getOrCreateSection(i); + +- entitysection.add(t0); +- t0.setLevelCallback(new PersistentEntitySectionManager.Callback(t0, i, entitysection)); +- if (!flag) { +- this.callbacks.onCreated(t0); ++ entitysection.add(entity); ++ entity.setLevelCallback(new PersistentEntitySectionManager.Callback(entity, i, entitysection)); ++ if (!worldGenSpawned) { ++ this.callbacks.onCreated(entity); + } + +- Visibility visibility = getEffectiveStatus(t0, entitysection.getStatus()); ++ Visibility visibility = getEffectiveStatus(entity, entitysection.getStatus()); + + if (visibility.isAccessible()) { +- this.startTracking(t0); ++ this.startTracking(entity); + } + + if (visibility.isTicking()) { +- this.startTicking(t0); ++ this.startTicking(entity); + } + + return true; + } + } + +- static Visibility getEffectiveStatus(T t0, Visibility visibility) { +- return t0.isAlwaysTicking() ? Visibility.TICKING : visibility; ++ static Visibility getEffectiveStatus(T entity, Visibility visibility) { ++ return entity.isAlwaysTicking() ? Visibility.TICKING : visibility; + } + +- public void addLegacyChunkEntities(Stream stream) { +- stream.forEach((entityaccess) -> { ++ public void addLegacyChunkEntities(Stream entities) { ++ entities.forEach((entityaccess) -> { + this.addEntity(entityaccess, true); + }); + } + +- public void addWorldGenChunkEntities(Stream stream) { +- stream.forEach((entityaccess) -> { ++ public void addWorldGenChunkEntities(Stream entities) { ++ entities.forEach((entityaccess) -> { + this.addEntity(entityaccess, false); + }); + } + +- void startTicking(T t0) { +- this.callbacks.onTickingStart(t0); ++ void startTicking(T entity) { ++ this.callbacks.onTickingStart(entity); + } + +- void stopTicking(T t0) { +- this.callbacks.onTickingEnd(t0); ++ void stopTicking(T entity) { ++ this.callbacks.onTickingEnd(entity); + } + +- void startTracking(T t0) { +- this.visibleEntityStorage.add(t0); +- this.callbacks.onTrackingStart(t0); ++ void startTracking(T entity) { ++ this.visibleEntityStorage.add(entity); ++ this.callbacks.onTrackingStart(entity); + } + +- void stopTracking(T t0) { +- this.callbacks.onTrackingEnd(t0); +- this.visibleEntityStorage.remove(t0); ++ void stopTracking(T entity) { ++ this.callbacks.onTrackingEnd(entity); ++ this.visibleEntityStorage.remove(entity); + } + +- public void updateChunkStatus(ChunkPos chunkpos, FullChunkStatus fullchunkstatus) { +- Visibility visibility = Visibility.fromFullChunkStatus(fullchunkstatus); ++ public void updateChunkStatus(ChunkPos chunkPos, FullChunkStatus fullChunkStatus) { ++ Visibility visibility = Visibility.fromFullChunkStatus(fullChunkStatus); + +- this.updateChunkStatus(chunkpos, visibility); ++ this.updateChunkStatus(chunkPos, visibility); + } + +- public void updateChunkStatus(ChunkPos chunkpos, Visibility visibility) { +- long i = chunkpos.toLong(); ++ public void updateChunkStatus(ChunkPos pos, Visibility visibility) { ++ long i = pos.toLong(); + + if (visibility == Visibility.HIDDEN) { + this.chunkVisibility.remove(i); +@@ -186,19 +200,25 @@ + }); + } + +- private void ensureChunkQueuedForLoad(long i) { +- PersistentEntitySectionManager.ChunkLoadStatus persistententitysectionmanager_chunkloadstatus = (PersistentEntitySectionManager.ChunkLoadStatus) this.chunkLoadStatuses.get(i); ++ public void ensureChunkQueuedForLoad(long chunkPosValue) { ++ PersistentEntitySectionManager.b persistententitysectionmanager_b = (PersistentEntitySectionManager.b) this.chunkLoadStatuses.get(chunkPosValue); + +- if (persistententitysectionmanager_chunkloadstatus == PersistentEntitySectionManager.ChunkLoadStatus.FRESH) { +- this.requestChunkLoad(i); ++ if (persistententitysectionmanager_b == PersistentEntitySectionManager.b.FRESH) { ++ this.requestChunkLoad(chunkPosValue); + } + + } + +- private boolean storeChunkSections(long i, Consumer consumer) { +- PersistentEntitySectionManager.ChunkLoadStatus persistententitysectionmanager_chunkloadstatus = (PersistentEntitySectionManager.ChunkLoadStatus) this.chunkLoadStatuses.get(i); ++ private boolean storeChunkSections(long chunkPosValue, Consumer consumer) { ++ // CraftBukkit start - add boolean for event call ++ return storeChunkSections(chunkPosValue, consumer, false); ++ } + +- if (persistententitysectionmanager_chunkloadstatus == PersistentEntitySectionManager.ChunkLoadStatus.PENDING) { ++ private boolean storeChunkSections(long i, Consumer consumer, boolean callEvent) { ++ // CraftBukkit end ++ PersistentEntitySectionManager.b persistententitysectionmanager_b = (PersistentEntitySectionManager.b) this.chunkLoadStatuses.get(i); ++ ++ if (persistententitysectionmanager_b == PersistentEntitySectionManager.b.PENDING) { + return false; + } else { + List list = (List) this.sectionStorage.getExistingSectionsInChunk(i).flatMap((entitysection) -> { +@@ -206,15 +226,17 @@ + }).collect(Collectors.toList()); + + if (list.isEmpty()) { +- if (persistententitysectionmanager_chunkloadstatus == PersistentEntitySectionManager.ChunkLoadStatus.LOADED) { ++ if (persistententitysectionmanager_b == PersistentEntitySectionManager.b.LOADED) { ++ if (callEvent) CraftEventFactory.callEntitiesUnloadEvent(((EntityStorage) permanentStorage).level, new ChunkPos(i), ImmutableList.of()); // CraftBukkit + this.permanentStorage.storeEntities(new ChunkEntities<>(new ChunkPos(i), ImmutableList.of())); + } + + return true; +- } else if (persistententitysectionmanager_chunkloadstatus == PersistentEntitySectionManager.ChunkLoadStatus.FRESH) { ++ } else if (persistententitysectionmanager_b == PersistentEntitySectionManager.b.FRESH) { + this.requestChunkLoad(i); + return false; + } else { ++ if (callEvent) CraftEventFactory.callEntitiesUnloadEvent(((EntityStorage) permanentStorage).level, new ChunkPos(i), list.stream().map(entity -> (Entity) entity).collect(Collectors.toList())); // CraftBukkit + this.permanentStorage.storeEntities(new ChunkEntities<>(new ChunkPos(i), list)); + list.forEach(consumer); + return true; +@@ -222,51 +244,55 @@ + } + } + +- private void requestChunkLoad(long i) { +- this.chunkLoadStatuses.put(i, PersistentEntitySectionManager.ChunkLoadStatus.PENDING); +- ChunkPos chunkpos = new ChunkPos(i); +- CompletableFuture completablefuture = this.permanentStorage.loadEntities(chunkpos); ++ private void requestChunkLoad(long chunkPosValue) { ++ this.chunkLoadStatuses.put(chunkPosValue, PersistentEntitySectionManager.b.PENDING); ++ ChunkPos chunkcoordintpair = new ChunkPos(chunkPosValue); ++ CompletableFuture completablefuture = this.permanentStorage.loadEntities(chunkcoordintpair); + Queue queue = this.loadingInbox; + + Objects.requireNonNull(this.loadingInbox); + completablefuture.thenAccept(queue::add).exceptionally((throwable) -> { +- PersistentEntitySectionManager.LOGGER.error("Failed to read chunk {}", chunkpos, throwable); ++ PersistentEntitySectionManager.LOGGER.error("Failed to read chunk {}", chunkcoordintpair, throwable); + return null; + }); + } + +- private boolean processChunkUnload(long i) { +- boolean flag = this.storeChunkSections(i, (entityaccess) -> { ++ private boolean processChunkUnload(long chunkPosValue) { ++ boolean flag = this.storeChunkSections(chunkPosValue, (entityaccess) -> { + entityaccess.getPassengersAndSelf().forEach(this::unloadEntity); +- }); ++ }, true); // CraftBukkit - add boolean for event call + + if (!flag) { + return false; + } else { +- this.chunkLoadStatuses.remove(i); ++ this.chunkLoadStatuses.remove(chunkPosValue); + return true; + } + } + +- private void unloadEntity(EntityAccess entityaccess) { +- entityaccess.setRemoved(Entity.RemovalReason.UNLOADED_TO_CHUNK); +- entityaccess.setLevelCallback(EntityInLevelCallback.NULL); ++ private void unloadEntity(EntityAccess entity) { ++ entity.setRemoved(Entity.RemovalReason.UNLOADED_TO_CHUNK); ++ entity.setLevelCallback(EntityInLevelCallback.NULL); + } + + private void processUnloads() { +- this.chunksToUnload.removeIf((i) -> { ++ this.chunksToUnload.removeIf((java.util.function.LongPredicate) (i) -> { // CraftBukkit - decompile error + return this.chunkVisibility.get(i) != Visibility.HIDDEN ? true : this.processChunkUnload(i); + }); + } + + private void processPendingLoads() { +- ChunkEntities chunkentities; ++ ChunkEntities chunkentities; // CraftBukkit - decompile error + + while ((chunkentities = (ChunkEntities) this.loadingInbox.poll()) != null) { + chunkentities.getEntities().forEach((entityaccess) -> { + this.addEntity(entityaccess, true); + }); +- this.chunkLoadStatuses.put(chunkentities.getPos().toLong(), PersistentEntitySectionManager.ChunkLoadStatus.LOADED); ++ this.chunkLoadStatuses.put(chunkentities.getPos().toLong(), PersistentEntitySectionManager.b.LOADED); ++ // CraftBukkit start - call entity load event ++ List entities = getEntities(chunkentities.getPos()); ++ CraftEventFactory.callEntitiesLoadEvent(((EntityStorage) permanentStorage).level, chunkentities.getPos(), entities); ++ // CraftBukkit end + } + + } +@@ -281,9 +307,9 @@ + ObjectIterator objectiterator = Long2ObjectMaps.fastIterable(this.chunkLoadStatuses).iterator(); + + while (objectiterator.hasNext()) { +- Entry entry = (Entry) objectiterator.next(); ++ Entry entry = (Entry) objectiterator.next(); + +- if (entry.getValue() == PersistentEntitySectionManager.ChunkLoadStatus.LOADED) { ++ if (entry.getValue() == PersistentEntitySectionManager.b.LOADED) { + longset.add(entry.getLongKey()); + } + } +@@ -292,7 +318,7 @@ + } + + public void autoSave() { +- this.getAllChunksToSave().forEach((i) -> { ++ this.getAllChunksToSave().forEach((java.util.function.LongConsumer) (i) -> { // CraftBukkit - decompile error + boolean flag = this.chunkVisibility.get(i) == Visibility.HIDDEN; + + if (flag) { +@@ -311,7 +337,7 @@ + while (!longset.isEmpty()) { + this.permanentStorage.flush(false); + this.processPendingLoads(); +- longset.removeIf((i) -> { ++ longset.removeIf((java.util.function.LongPredicate) (i) -> { // CraftBukkit - decompile error + boolean flag = this.chunkVisibility.get(i) == Visibility.HIDDEN; + + return flag ? this.processChunkUnload(i) : this.storeChunkSections(i, (entityaccess) -> { +@@ -322,9 +348,16 @@ + this.permanentStorage.flush(true); + } + +- @Override + public void close() throws IOException { +- this.saveAll(); ++ // CraftBukkit start - add save boolean ++ close(true); ++ } ++ ++ public void close(boolean save) throws IOException { ++ if (save) { ++ this.saveAll(); ++ } ++ // CraftBukkit end + this.permanentStorage.close(); + } + +@@ -336,30 +369,30 @@ + return this.entityGetter; + } + +- public boolean canPositionTick(BlockPos blockpos) { +- return ((Visibility) this.chunkVisibility.get(ChunkPos.asLong(blockpos))).isTicking(); ++ public boolean canPositionTick(BlockPos pos) { ++ return ((Visibility) this.chunkVisibility.get(ChunkPos.asLong(pos))).isTicking(); + } + +- public boolean canPositionTick(ChunkPos chunkpos) { +- return ((Visibility) this.chunkVisibility.get(chunkpos.toLong())).isTicking(); ++ public boolean canPositionTick(ChunkPos chunkPos) { ++ return ((Visibility) this.chunkVisibility.get(chunkPos.toLong())).isTicking(); + } + +- public boolean areEntitiesLoaded(long i) { +- return this.chunkLoadStatuses.get(i) == PersistentEntitySectionManager.ChunkLoadStatus.LOADED; ++ public boolean areEntitiesLoaded(long chunkPos) { ++ return this.chunkLoadStatuses.get(chunkPos) == PersistentEntitySectionManager.b.LOADED; + } + + public void dumpSections(Writer writer) throws IOException { +- CsvOutput csvoutput = CsvOutput.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("visibility").addColumn("load_status").addColumn("entity_count").build(writer); ++ CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("visibility").addColumn("load_status").addColumn("entity_count").build(writer); + +- this.sectionStorage.getAllChunksWithExistingSections().forEach((i) -> { +- PersistentEntitySectionManager.ChunkLoadStatus persistententitysectionmanager_chunkloadstatus = (PersistentEntitySectionManager.ChunkLoadStatus) this.chunkLoadStatuses.get(i); ++ this.sectionStorage.getAllChunksWithExistingSections().forEach((java.util.function.LongConsumer) (i) -> { // CraftBukkit - decompile error ++ PersistentEntitySectionManager.b persistententitysectionmanager_b = (PersistentEntitySectionManager.b) this.chunkLoadStatuses.get(i); + + this.sectionStorage.getExistingSectionPositionsInChunk(i).forEach((j) -> { + EntitySection entitysection = this.sectionStorage.getSection(j); + + if (entitysection != null) { + try { +- csvoutput.writeRow(SectionPos.x(j), SectionPos.y(j), SectionPos.z(j), entitysection.getStatus(), persistententitysectionmanager_chunkloadstatus, entitysection.size()); ++ csvwriter.writeRow(SectionPos.x(j), SectionPos.y(j), SectionPos.z(j), entitysection.getStatus(), persistententitysectionmanager_b, entitysection.size()); + } catch (IOException ioexception) { + throw new UncheckedIOException(ioexception); + } +@@ -381,11 +414,11 @@ + return this.visibleEntityStorage.count(); + } + +- private static enum ChunkLoadStatus { ++ private static enum b { + + FRESH, PENDING, LOADED; + +- private ChunkLoadStatus() {} ++ private b() {} + } + + private class Callback implements EntityInLevelCallback { +@@ -394,17 +427,16 @@ + private long currentSectionKey; + private EntitySection currentSection; + +- Callback(T t0, long i, EntitySection entitysection) { +- this.entity = t0; ++ Callback(EntityAccess entityaccess, long i, EntitySection entitysection) { ++ this.entity = (T) entityaccess; // CraftBukkit - decompile error + this.currentSectionKey = i; + this.currentSection = entitysection; + } + + @Override +- @Override + public void onMove() { +- BlockPos blockpos = this.entity.blockPosition(); +- long i = SectionPos.asLong(blockpos); ++ BlockPos blockposition = this.entity.blockPosition(); ++ long i = SectionPos.asLong(blockposition); + + if (i != this.currentSectionKey) { + Visibility visibility = this.currentSection.getStatus(); +@@ -424,9 +456,9 @@ + + } + +- private void updateStatus(Visibility visibility, Visibility visibility1) { +- Visibility visibility2 = PersistentEntitySectionManager.getEffectiveStatus(this.entity, visibility); +- Visibility visibility3 = PersistentEntitySectionManager.getEffectiveStatus(this.entity, visibility1); ++ private void updateStatus(Visibility oldVisibility, Visibility newVisibility) { ++ Visibility visibility2 = PersistentEntitySectionManager.getEffectiveStatus(this.entity, oldVisibility); ++ Visibility visibility3 = PersistentEntitySectionManager.getEffectiveStatus(this.entity, newVisibility); + + if (visibility2 == visibility3) { + if (visibility3.isAccessible()) { +@@ -460,10 +492,9 @@ + } + + @Override +- @Override +- public void onRemove(Entity.RemovalReason entity_removalreason) { ++ public void onRemove(Entity.RemovalReason reason) { + if (!this.currentSection.remove(this.entity)) { +- PersistentEntitySectionManager.LOGGER.warn("Entity {} wasn't found in section {} (destroying due to {})", new Object[]{this.entity, SectionPos.of(this.currentSectionKey), entity_removalreason}); ++ PersistentEntitySectionManager.LOGGER.warn("Entity {} wasn't found in section {} (destroying due to {})", new Object[]{this.entity, SectionPos.of(this.currentSectionKey), reason}); + } + + Visibility visibility = PersistentEntitySectionManager.getEffectiveStatus(this.entity, this.currentSection.getStatus()); +@@ -476,7 +507,7 @@ + PersistentEntitySectionManager.this.stopTracking(this.entity); + } + +- if (entity_removalreason.shouldDestroy()) { ++ if (reason.shouldDestroy()) { + PersistentEntitySectionManager.this.callbacks.onDestroyed(this.entity); + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/gameevent/GameEventDispatcher.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/gameevent/GameEventDispatcher.java.patch new file mode 100644 index 0000000000..ee5071204e --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/gameevent/GameEventDispatcher.java.patch @@ -0,0 +1,105 @@ +--- a/net/minecraft/world/level/gameevent/GameEventDispatcher.java ++++ b/net/minecraft/world/level/gameevent/GameEventDispatcher.java +@@ -10,30 +10,44 @@ + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.CraftGameEvent; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.world.GenericGameEvent; ++// CraftBukkit end + + public class GameEventDispatcher { + + private final ServerLevel level; + +- public GameEventDispatcher(ServerLevel serverlevel) { +- this.level = serverlevel; ++ public GameEventDispatcher(ServerLevel level) { ++ this.level = level; + } + +- public void post(GameEvent gameevent, Vec3 vec3, GameEvent.Context gameevent_context) { +- int i = gameevent.getNotificationRadius(); +- BlockPos blockpos = BlockPos.containing(vec3); +- int j = SectionPos.blockToSectionCoord(blockpos.getX() - i); +- int k = SectionPos.blockToSectionCoord(blockpos.getY() - i); +- int l = SectionPos.blockToSectionCoord(blockpos.getZ() - i); +- int i1 = SectionPos.blockToSectionCoord(blockpos.getX() + i); +- int j1 = SectionPos.blockToSectionCoord(blockpos.getY() + i); +- int k1 = SectionPos.blockToSectionCoord(blockpos.getZ() + i); ++ public void post(GameEvent event, Vec3 pos, GameEvent.Context context) { ++ int i = event.getNotificationRadius(); ++ BlockPos blockposition = BlockPos.containing(pos); ++ // CraftBukkit start ++ GenericGameEvent event1 = new GenericGameEvent(CraftGameEvent.minecraftToBukkit(event), CraftLocation.toBukkit(blockposition, level.getWorld()), (context.sourceEntity() == null) ? null : context.sourceEntity().getBukkitEntity(), i, !Bukkit.isPrimaryThread()); ++ level.getCraftServer().getPluginManager().callEvent(event1); ++ if (event1.isCancelled()) { ++ return; ++ } ++ i = event1.getRadius(); ++ // CraftBukkit end ++ int j = SectionPos.blockToSectionCoord(blockposition.getX() - i); ++ int k = SectionPos.blockToSectionCoord(blockposition.getY() - i); ++ int l = SectionPos.blockToSectionCoord(blockposition.getZ() - i); ++ int i1 = SectionPos.blockToSectionCoord(blockposition.getX() + i); ++ int j1 = SectionPos.blockToSectionCoord(blockposition.getY() + i); ++ int k1 = SectionPos.blockToSectionCoord(blockposition.getZ() + i); + List list = new ArrayList(); +- GameEventListenerRegistry.ListenerVisitor gameeventlistenerregistry_listenervisitor = (gameeventlistener, vec31) -> { +- if (gameeventlistener.getDeliveryMode() == GameEventListener.DeliveryMode.BY_DISTANCE) { +- list.add(new GameEvent.ListenerInfo(gameevent, vec3, gameevent_context, gameeventlistener, vec31)); ++ GameEventListenerRegistry.ListenerVisitor gameeventlistenerregistry_a = (gameeventlistener, vec3d1) -> { ++ if (gameeventlistener.getDeliveryMode() == GameEventListener.a.BY_DISTANCE) { ++ list.add(new GameEvent.ListenerInfo(event, pos, context, gameeventlistener, vec3d1)); + } else { +- gameeventlistener.handleGameEvent(this.level, gameevent, gameevent_context, vec3); ++ gameeventlistener.handleGameEvent(this.level, event, context, pos); + } + + }; +@@ -41,11 +55,11 @@ + + for (int l1 = j; l1 <= i1; ++l1) { + for (int i2 = l; i2 <= k1; ++i2) { +- LevelChunk levelchunk = this.level.getChunkSource().getChunkNow(l1, i2); ++ LevelChunk chunk = this.level.getChunkSource().getChunkNow(l1, i2); + +- if (levelchunk != null) { ++ if (chunk != null) { + for (int j2 = k; j2 <= j1; ++j2) { +- flag |= levelchunk.getListenerRegistry(j2).visitInRangeListeners(gameevent, vec3, gameevent_context, gameeventlistenerregistry_listenervisitor); ++ flag |= chunk.getListenerRegistry(j2).visitInRangeListeners(event, pos, context, gameeventlistenerregistry_a); + } + } + } +@@ -56,20 +70,20 @@ + } + + if (flag) { +- DebugPackets.sendGameEventInfo(this.level, gameevent, vec3); ++ DebugPackets.sendGameEventInfo(this.level, event, pos); + } + + } + +- private void handleGameEventMessagesInQueue(List list) { +- Collections.sort(list); +- Iterator iterator = list.iterator(); ++ private void handleGameEventMessagesInQueue(List listenerInfos) { ++ Collections.sort(listenerInfos); ++ Iterator iterator = listenerInfos.iterator(); + + while (iterator.hasNext()) { +- GameEvent.ListenerInfo gameevent_listenerinfo = (GameEvent.ListenerInfo) iterator.next(); +- GameEventListener gameeventlistener = gameevent_listenerinfo.recipient(); ++ GameEvent.ListenerInfo gameevent_b = (GameEvent.ListenerInfo) iterator.next(); ++ GameEventListener gameeventlistener = gameevent_b.recipient(); + +- gameeventlistener.handleGameEvent(this.level, gameevent_listenerinfo.gameEvent(), gameevent_listenerinfo.context(), gameevent_listenerinfo.source()); ++ gameeventlistener.handleGameEvent(this.level, gameevent_b.gameEvent(), gameevent_b.context(), gameevent_b.source()); + } + + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java.patch new file mode 100644 index 0000000000..dae021e0fe --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java.patch @@ -0,0 +1,393 @@ +--- a/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java ++++ b/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java +@@ -27,6 +27,11 @@ + import net.minecraft.world.level.gameevent.PositionSource; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.CraftGameEvent; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockReceiveGameEvent; ++// CraftBukkit end + + public interface VibrationSystem { + +@@ -84,18 +89,18 @@ + + VibrationSystem.User getVibrationUser(); + +- static int getGameEventFrequency(GameEvent gameevent) { +- return VibrationSystem.VIBRATION_FREQUENCY_FOR_EVENT.applyAsInt(gameevent); ++ static int getGameEventFrequency(GameEvent gameEvent) { ++ return VibrationSystem.VIBRATION_FREQUENCY_FOR_EVENT.applyAsInt(gameEvent); + } + +- static GameEvent getResonanceEventByFrequency(int i) { +- return VibrationSystem.RESONANCE_EVENTS[i - 1]; ++ static GameEvent getResonanceEventByFrequency(int frequency) { ++ return VibrationSystem.RESONANCE_EVENTS[frequency - 1]; + } + +- static int getRedstoneStrengthForDistance(float f, int i) { +- double d0 = 15.0D / (double) i; ++ static int getRedstoneStrengthForDistance(float distance, int maxDistance) { ++ double d0 = 15.0D / (double) maxDistance; + +- return Math.max(1, 15 - Mth.floor(d0 * (double) f)); ++ return Math.max(1, 15 - Mth.floor(d0 * (double) distance)); + } + + public interface User { +@@ -120,26 +125,26 @@ + return false; + } + +- default int calculateTravelTimeInTicks(float f) { +- return Mth.floor(f); ++ default int calculateTravelTimeInTicks(float distance) { ++ return Mth.floor(distance); + } + +- default boolean isValidVibration(GameEvent gameevent, GameEvent.Context gameevent_context) { +- if (!gameevent.is(this.getListenableEvents())) { ++ default boolean isValidVibration(GameEvent gameEvent, GameEvent.Context context) { ++ if (!gameEvent.is(this.getListenableEvents())) { + return false; + } else { +- Entity entity = gameevent_context.sourceEntity(); ++ Entity entity = context.sourceEntity(); + + if (entity != null) { + if (entity.isSpectator()) { + return false; + } + +- if (entity.isSteppingCarefully() && gameevent.is(GameEventTags.IGNORE_VIBRATIONS_SNEAKING)) { ++ if (entity.isSteppingCarefully() && gameEvent.is(GameEventTags.IGNORE_VIBRATIONS_SNEAKING)) { + if (this.canTriggerAvoidVibration() && entity instanceof ServerPlayer) { +- ServerPlayer serverplayer = (ServerPlayer) entity; ++ ServerPlayer entityplayer = (ServerPlayer) entity; + +- CriteriaTriggers.AVOID_VIBRATION.trigger(serverplayer); ++ CriteriaTriggers.AVOID_VIBRATION.trigger(entityplayer); + } + + return false; +@@ -150,7 +155,7 @@ + } + } + +- return gameevent_context.affectedState() != null ? !gameevent_context.affectedState().is(BlockTags.DAMPENS_VIBRATIONS) : true; ++ return context.affectedState() != null ? !context.affectedState().is(BlockTags.DAMPENS_VIBRATIONS) : true; + } + } + +@@ -159,85 +164,86 @@ + + public interface Ticker { + +- static void tick(Level level, VibrationSystem.Data vibrationsystem_data, VibrationSystem.User vibrationsystem_user) { ++ static void tick(Level level, VibrationSystem.Data data, VibrationSystem.User user) { + if (level instanceof ServerLevel) { +- ServerLevel serverlevel = (ServerLevel) level; ++ ServerLevel worldserver = (ServerLevel) level; + +- if (vibrationsystem_data.currentVibration == null) { +- trySelectAndScheduleVibration(serverlevel, vibrationsystem_data, vibrationsystem_user); ++ if (data.currentVibration == null) { ++ trySelectAndScheduleVibration(worldserver, data, user); + } + +- if (vibrationsystem_data.currentVibration != null) { +- boolean flag = vibrationsystem_data.getTravelTimeInTicks() > 0; ++ if (data.currentVibration != null) { ++ boolean flag = data.getTravelTimeInTicks() > 0; + +- tryReloadVibrationParticle(serverlevel, vibrationsystem_data, vibrationsystem_user); +- vibrationsystem_data.decrementTravelTime(); +- if (vibrationsystem_data.getTravelTimeInTicks() <= 0) { +- flag = receiveVibration(serverlevel, vibrationsystem_data, vibrationsystem_user, vibrationsystem_data.currentVibration); ++ tryReloadVibrationParticle(worldserver, data, user); ++ data.decrementTravelTime(); ++ if (data.getTravelTimeInTicks() <= 0) { ++ flag = receiveVibration(worldserver, data, user, data.currentVibration); + } + + if (flag) { +- vibrationsystem_user.onDataChanged(); ++ user.onDataChanged(); + } + + } + } + } + +- private static void trySelectAndScheduleVibration(ServerLevel serverlevel, VibrationSystem.Data vibrationsystem_data, VibrationSystem.User vibrationsystem_user) { +- vibrationsystem_data.getSelectionStrategy().chosenCandidate(serverlevel.getGameTime()).ifPresent((vibrationinfo) -> { +- vibrationsystem_data.setCurrentVibration(vibrationinfo); +- Vec3 vec3 = vibrationinfo.pos(); ++ private static void trySelectAndScheduleVibration(ServerLevel level, VibrationSystem.Data data, VibrationSystem.User user) { ++ data.getSelectionStrategy().chosenCandidate(level.getGameTime()).ifPresent((vibrationinfo) -> { ++ data.setCurrentVibration(vibrationinfo); ++ Vec3 vec3d = vibrationinfo.pos(); + +- vibrationsystem_data.setTravelTimeInTicks(vibrationsystem_user.calculateTravelTimeInTicks(vibrationinfo.distance())); +- serverlevel.sendParticles(new VibrationParticleOption(vibrationsystem_user.getPositionSource(), vibrationsystem_data.getTravelTimeInTicks()), vec3.x, vec3.y, vec3.z, 1, 0.0D, 0.0D, 0.0D, 0.0D); +- vibrationsystem_user.onDataChanged(); +- vibrationsystem_data.getSelectionStrategy().startOver(); ++ data.setTravelTimeInTicks(user.calculateTravelTimeInTicks(vibrationinfo.distance())); ++ level.sendParticles(new VibrationParticleOption(user.getPositionSource(), data.getTravelTimeInTicks()), vec3d.x, vec3d.y, vec3d.z, 1, 0.0D, 0.0D, 0.0D, 0.0D); ++ user.onDataChanged(); ++ data.getSelectionStrategy().startOver(); + }); + } + +- private static void tryReloadVibrationParticle(ServerLevel serverlevel, VibrationSystem.Data vibrationsystem_data, VibrationSystem.User vibrationsystem_user) { +- if (vibrationsystem_data.shouldReloadVibrationParticle()) { +- if (vibrationsystem_data.currentVibration == null) { +- vibrationsystem_data.setReloadVibrationParticle(false); ++ private static void tryReloadVibrationParticle(ServerLevel level, VibrationSystem.Data data, VibrationSystem.User user) { ++ if (data.shouldReloadVibrationParticle()) { ++ if (data.currentVibration == null) { ++ data.setReloadVibrationParticle(false); + } else { +- Vec3 vec3 = vibrationsystem_data.currentVibration.pos(); +- PositionSource positionsource = vibrationsystem_user.getPositionSource(); +- Vec3 vec31 = (Vec3) positionsource.getPosition(serverlevel).orElse(vec3); +- int i = vibrationsystem_data.getTravelTimeInTicks(); +- int j = vibrationsystem_user.calculateTravelTimeInTicks(vibrationsystem_data.currentVibration.distance()); ++ Vec3 vec3d = data.currentVibration.pos(); ++ PositionSource positionsource = user.getPositionSource(); ++ Vec3 vec3d1 = (Vec3) positionsource.getPosition(level).orElse(vec3d); ++ int i = data.getTravelTimeInTicks(); ++ int j = user.calculateTravelTimeInTicks(data.currentVibration.distance()); + double d0 = 1.0D - (double) i / (double) j; +- double d1 = Mth.lerp(d0, vec3.x, vec31.x); +- double d2 = Mth.lerp(d0, vec3.y, vec31.y); +- double d3 = Mth.lerp(d0, vec3.z, vec31.z); +- boolean flag = serverlevel.sendParticles(new VibrationParticleOption(positionsource, i), d1, d2, d3, 1, 0.0D, 0.0D, 0.0D, 0.0D) > 0; ++ double d1 = Mth.lerp(d0, vec3d.x, vec3d1.x); ++ double d2 = Mth.lerp(d0, vec3d.y, vec3d1.y); ++ double d3 = Mth.lerp(d0, vec3d.z, vec3d1.z); ++ boolean flag = level.sendParticles(new VibrationParticleOption(positionsource, i), d1, d2, d3, 1, 0.0D, 0.0D, 0.0D, 0.0D) > 0; + + if (flag) { +- vibrationsystem_data.setReloadVibrationParticle(false); ++ data.setReloadVibrationParticle(false); + } + + } + } + } + +- private static boolean receiveVibration(ServerLevel serverlevel, VibrationSystem.Data vibrationsystem_data, VibrationSystem.User vibrationsystem_user, VibrationInfo vibrationinfo) { +- BlockPos blockpos = BlockPos.containing(vibrationinfo.pos()); +- BlockPos blockpos1 = (BlockPos) vibrationsystem_user.getPositionSource().getPosition(serverlevel).map(BlockPos::containing).orElse(blockpos); ++ private static boolean receiveVibration(ServerLevel level, VibrationSystem.Data data, VibrationSystem.User user, VibrationInfo vibrationInfo) { ++ BlockPos blockposition = BlockPos.containing(vibrationInfo.pos()); ++ BlockPos blockposition1 = (BlockPos) user.getPositionSource().getPosition(level).map(BlockPos::containing).orElse(blockposition); + +- if (vibrationsystem_user.requiresAdjacentChunksToBeTicking() && !areAdjacentChunksTicking(serverlevel, blockpos1)) { ++ if (user.requiresAdjacentChunksToBeTicking() && !areAdjacentChunksTicking(level, blockposition1)) { + return false; + } else { +- vibrationsystem_user.onReceiveVibration(serverlevel, blockpos, vibrationinfo.gameEvent(), (Entity) vibrationinfo.getEntity(serverlevel).orElse((Object) null), (Entity) vibrationinfo.getProjectileOwner(serverlevel).orElse((Object) null), VibrationSystem.Listener.distanceBetweenInBlocks(blockpos, blockpos1)); +- vibrationsystem_data.setCurrentVibration((VibrationInfo) null); ++ // CraftBukkit - decompile error ++ user.onReceiveVibration(level, blockposition, vibrationInfo.gameEvent(), (Entity) vibrationInfo.getEntity(level).orElse(null), (Entity) vibrationInfo.getProjectileOwner(level).orElse(null), VibrationSystem.Listener.distanceBetweenInBlocks(blockposition, blockposition1)); ++ data.setCurrentVibration((VibrationInfo) null); + return true; + } + } + +- private static boolean areAdjacentChunksTicking(Level level, BlockPos blockpos) { +- ChunkPos chunkpos = new ChunkPos(blockpos); ++ private static boolean areAdjacentChunksTicking(Level level, BlockPos pos) { ++ ChunkPos chunkcoordintpair = new ChunkPos(pos); + +- for (int i = chunkpos.x - 1; i <= chunkpos.x + 1; ++i) { +- for (int j = chunkpos.z - 1; j <= chunkpos.z + 1; ++j) { ++ for (int i = chunkcoordintpair.x - 1; i <= chunkcoordintpair.x + 1; ++i) { ++ for (int j = chunkcoordintpair.z - 1; j <= chunkcoordintpair.z + 1; ++j) { + if (!level.shouldTickBlocksAt(ChunkPos.asLong(i, j)) || level.getChunkSource().getChunkNow(i, j) == null) { + return false; + } +@@ -252,79 +258,82 @@ + + private final VibrationSystem system; + +- public Listener(VibrationSystem vibrationsystem) { +- this.system = vibrationsystem; ++ public Listener(VibrationSystem system) { ++ this.system = system; + } + + @Override +- @Override + public PositionSource getListenerSource() { + return this.system.getVibrationUser().getPositionSource(); + } + + @Override +- @Override + public int getListenerRadius() { + return this.system.getVibrationUser().getListenerRadius(); + } + + @Override +- @Override +- public boolean handleGameEvent(ServerLevel serverlevel, GameEvent gameevent, GameEvent.Context gameevent_context, Vec3 vec3) { +- VibrationSystem.Data vibrationsystem_data = this.system.getVibrationData(); +- VibrationSystem.User vibrationsystem_user = this.system.getVibrationUser(); ++ public boolean handleGameEvent(ServerLevel level, GameEvent gameEvent, GameEvent.Context context, Vec3 pos) { ++ VibrationSystem.Data vibrationsystem_a = this.system.getVibrationData(); ++ VibrationSystem.User vibrationsystem_d = this.system.getVibrationUser(); + +- if (vibrationsystem_data.getCurrentVibration() != null) { ++ if (vibrationsystem_a.getCurrentVibration() != null) { + return false; +- } else if (!vibrationsystem_user.isValidVibration(gameevent, gameevent_context)) { ++ } else if (!vibrationsystem_d.isValidVibration(gameEvent, context)) { + return false; + } else { +- Optional optional = vibrationsystem_user.getPositionSource().getPosition(serverlevel); ++ Optional optional = vibrationsystem_d.getPositionSource().getPosition(level); + + if (optional.isEmpty()) { + return false; + } else { +- Vec3 vec31 = (Vec3) optional.get(); +- +- if (!vibrationsystem_user.canReceiveVibration(serverlevel, BlockPos.containing(vec3), gameevent, gameevent_context)) { ++ Vec3 vec3d1 = (Vec3) optional.get(); ++ // CraftBukkit start ++ boolean defaultCancel = !vibrationsystem_d.canReceiveVibration(level, BlockPos.containing(pos), gameEvent, context); ++ Entity entity = context.sourceEntity(); ++ BlockReceiveGameEvent event = new BlockReceiveGameEvent(CraftGameEvent.minecraftToBukkit(gameEvent), CraftBlock.at(level, BlockPos.containing(vec3d1)), (entity == null) ? null : entity.getBukkitEntity()); ++ event.setCancelled(defaultCancel); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ // CraftBukkit end + return false; +- } else if (isOccluded(serverlevel, vec3, vec31)) { ++ } else if (isOccluded(level, pos, vec3d1)) { + return false; + } else { +- this.scheduleVibration(serverlevel, vibrationsystem_data, gameevent, gameevent_context, vec3, vec31); ++ this.scheduleVibration(level, vibrationsystem_a, gameEvent, context, pos, vec3d1); + return true; + } + } + } + } + +- public void forceScheduleVibration(ServerLevel serverlevel, GameEvent gameevent, GameEvent.Context gameevent_context, Vec3 vec3) { +- this.system.getVibrationUser().getPositionSource().getPosition(serverlevel).ifPresent((vec31) -> { +- this.scheduleVibration(serverlevel, this.system.getVibrationData(), gameevent, gameevent_context, vec3, vec31); ++ public void forceScheduleVibration(ServerLevel level, GameEvent gameEvent, GameEvent.Context context, Vec3 eventPos) { ++ this.system.getVibrationUser().getPositionSource().getPosition(level).ifPresent((vec3d1) -> { ++ this.scheduleVibration(level, this.system.getVibrationData(), gameEvent, context, eventPos, vec3d1); + }); + } + +- private void scheduleVibration(ServerLevel serverlevel, VibrationSystem.Data vibrationsystem_data, GameEvent gameevent, GameEvent.Context gameevent_context, Vec3 vec3, Vec3 vec31) { +- vibrationsystem_data.selectionStrategy.addCandidate(new VibrationInfo(gameevent, (float) vec3.distanceTo(vec31), vec3, gameevent_context.sourceEntity()), serverlevel.getGameTime()); ++ private void scheduleVibration(ServerLevel level, VibrationSystem.Data data, GameEvent gameEvent, GameEvent.Context context, Vec3 pos, Vec3 vibrationUserPos) { ++ data.selectionStrategy.addCandidate(new VibrationInfo(gameEvent, (float) pos.distanceTo(vibrationUserPos), pos, context.sourceEntity()), level.getGameTime()); + } + +- public static float distanceBetweenInBlocks(BlockPos blockpos, BlockPos blockpos1) { +- return (float) Math.sqrt(blockpos.distSqr(blockpos1)); ++ public static float distanceBetweenInBlocks(BlockPos pos1, BlockPos pos2) { ++ return (float) Math.sqrt(pos1.distSqr(pos2)); + } + +- private static boolean isOccluded(Level level, Vec3 vec3, Vec3 vec31) { +- Vec3 vec32 = new Vec3((double) Mth.floor(vec3.x) + 0.5D, (double) Mth.floor(vec3.y) + 0.5D, (double) Mth.floor(vec3.z) + 0.5D); +- Vec3 vec33 = new Vec3((double) Mth.floor(vec31.x) + 0.5D, (double) Mth.floor(vec31.y) + 0.5D, (double) Mth.floor(vec31.z) + 0.5D); +- Direction[] adirection = Direction.values(); +- int i = adirection.length; ++ private static boolean isOccluded(Level level, Vec3 eventPos, Vec3 vibrationUserPos) { ++ Vec3 vec3d2 = new Vec3((double) Mth.floor(eventPos.x) + 0.5D, (double) Mth.floor(eventPos.y) + 0.5D, (double) Mth.floor(eventPos.z) + 0.5D); ++ Vec3 vec3d3 = new Vec3((double) Mth.floor(vibrationUserPos.x) + 0.5D, (double) Mth.floor(vibrationUserPos.y) + 0.5D, (double) Mth.floor(vibrationUserPos.z) + 0.5D); ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; +- Vec3 vec34 = vec32.relative(direction, 9.999999747378752E-6D); ++ Direction enumdirection = aenumdirection[j]; ++ Vec3 vec3d4 = vec3d2.relative(enumdirection, 9.999999747378752E-6D); + +- if (level.isBlockInLine(new ClipBlockStateContext(vec34, vec33, (blockstate) -> { +- return blockstate.is(BlockTags.OCCLUDES_VIBRATION_SIGNALS); +- })).getType() != HitResult.Type.BLOCK) { ++ if (level.isBlockInLine(new ClipBlockStateContext(vec3d4, vec3d3, (iblockdata) -> { ++ return iblockdata.is(BlockTags.OCCLUDES_VIBRATION_SIGNALS); ++ })).getType() != HitResult.EnumMovingObjectType.BLOCK) { + return false; + } + } +@@ -336,10 +345,10 @@ + public static final class Data { + + public static Codec CODEC = RecordCodecBuilder.create((instance) -> { +- return instance.group(VibrationInfo.CODEC.optionalFieldOf("event").forGetter((vibrationsystem_data) -> { +- return Optional.ofNullable(vibrationsystem_data.currentVibration); ++ return instance.group(VibrationInfo.CODEC.optionalFieldOf("event").forGetter((vibrationsystem_a) -> { ++ return Optional.ofNullable(vibrationsystem_a.currentVibration); + }), VibrationSelector.CODEC.fieldOf("selector").forGetter(VibrationSystem.Data::getSelectionStrategy), ExtraCodecs.NON_NEGATIVE_INT.fieldOf("event_delay").orElse(0).forGetter(VibrationSystem.Data::getTravelTimeInTicks)).apply(instance, (optional, vibrationselector, integer) -> { +- return new VibrationSystem.Data((VibrationInfo) optional.orElse((Object) null), vibrationselector, integer, true); ++ return new VibrationSystem.Data((VibrationInfo) optional.orElse(null), vibrationselector, integer, true); // CraftBukkit - decompile error + }); + }); + public static final String NBT_TAG_KEY = "listener"; +@@ -349,11 +358,11 @@ + final VibrationSelector selectionStrategy; + private boolean reloadVibrationParticle; + +- private Data(@Nullable VibrationInfo vibrationinfo, VibrationSelector vibrationselector, int i, boolean flag) { +- this.currentVibration = vibrationinfo; +- this.travelTimeInTicks = i; +- this.selectionStrategy = vibrationselector; +- this.reloadVibrationParticle = flag; ++ private Data(@Nullable VibrationInfo currentVibration, VibrationSelector selectionStrategy, int travelTimeInTicks, boolean reloadVibrationParticle) { ++ this.currentVibration = currentVibration; ++ this.travelTimeInTicks = travelTimeInTicks; ++ this.selectionStrategy = selectionStrategy; ++ this.reloadVibrationParticle = reloadVibrationParticle; + } + + public Data() { +@@ -369,16 +378,16 @@ + return this.currentVibration; + } + +- public void setCurrentVibration(@Nullable VibrationInfo vibrationinfo) { +- this.currentVibration = vibrationinfo; ++ public void setCurrentVibration(@Nullable VibrationInfo currentVibration) { ++ this.currentVibration = currentVibration; + } + + public int getTravelTimeInTicks() { + return this.travelTimeInTicks; + } + +- public void setTravelTimeInTicks(int i) { +- this.travelTimeInTicks = i; ++ public void setTravelTimeInTicks(int travelTimeInTicks) { ++ this.travelTimeInTicks = travelTimeInTicks; + } + + public void decrementTravelTime() { +@@ -389,8 +398,8 @@ + return this.reloadVibrationParticle; + } + +- public void setReloadVibrationParticle(boolean flag) { +- this.reloadVibrationParticle = flag; ++ public void setReloadVibrationParticle(boolean reloadVibrationParticle) { ++ this.reloadVibrationParticle = reloadVibrationParticle; + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/FlatLevelSource.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/FlatLevelSource.java.patch new file mode 100644 index 0000000000..5dc931ea62 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/FlatLevelSource.java.patch @@ -0,0 +1,180 @@ +--- a/net/minecraft/world/level/levelgen/FlatLevelSource.java ++++ b/net/minecraft/world/level/levelgen/FlatLevelSource.java +@@ -19,7 +19,7 @@ + import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.biome.FixedBiomeSource; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.chunk.ChunkGeneratorStructureState; +@@ -34,28 +34,32 @@ + }); + private final FlatLevelGeneratorSettings settings; + +- public FlatLevelSource(FlatLevelGeneratorSettings flatlevelgeneratorsettings) { +- FixedBiomeSource fixedbiomesource = new FixedBiomeSource(flatlevelgeneratorsettings.getBiome()); ++ public FlatLevelSource(FlatLevelGeneratorSettings settings) { ++ // CraftBukkit start ++ // WorldChunkManagerHell worldchunkmanagerhell = new WorldChunkManagerHell(generatorsettingsflat.getBiome()); + +- Objects.requireNonNull(flatlevelgeneratorsettings); +- super(fixedbiomesource, Util.memoize(flatlevelgeneratorsettings::adjustGenerationSettings)); +- this.settings = flatlevelgeneratorsettings; ++ // Objects.requireNonNull(generatorsettingsflat); ++ this(settings, new FixedBiomeSource(settings.getBiome())); + } + ++ public FlatLevelSource(FlatLevelGeneratorSettings generatorsettingsflat, net.minecraft.world.level.biome.BiomeSource worldchunkmanager) { ++ super(worldchunkmanager, Util.memoize(generatorsettingsflat::adjustGenerationSettings)); ++ // CraftBukkit end ++ this.settings = generatorsettingsflat; ++ } ++ + @Override +- @Override +- public ChunkGeneratorStructureState createState(HolderLookup holderlookup, RandomState randomstate, long i) { ++ public ChunkGeneratorStructureState createState(HolderLookup structureSetLookup, RandomState randomState, long seed) { + Stream> stream = (Stream) this.settings.structureOverrides().map(HolderSet::stream).orElseGet(() -> { +- return holderlookup.listElements().map((holder_reference) -> { +- return holder_reference; ++ return structureSetLookup.listElements().map((holder_c) -> { ++ return holder_c; + }); + }); + +- return ChunkGeneratorStructureState.createForFlat(randomstate, i, this.biomeSource, stream); ++ return ChunkGeneratorStructureState.createForFlat(randomState, seed, this.biomeSource, stream); + } + + @Override +- @Override + protected Codec codec() { + return FlatLevelSource.CODEC; + } +@@ -65,94 +69,83 @@ + } + + @Override +- @Override +- public void buildSurface(WorldGenRegion worldgenregion, StructureManager structuremanager, RandomState randomstate, ChunkAccess chunkaccess) {} ++ public void buildSurface(WorldGenRegion level, StructureManager structureManager, RandomState random, ChunkAccess chunk) {} + + @Override +- @Override +- public int getSpawnHeight(LevelHeightAccessor levelheightaccessor) { +- return levelheightaccessor.getMinBuildHeight() + Math.min(levelheightaccessor.getHeight(), this.settings.getLayers().size()); ++ public int getSpawnHeight(LevelHeightAccessor level) { ++ return level.getMinBuildHeight() + Math.min(level.getHeight(), this.settings.getLayers().size()); + } + + @Override +- @Override +- public CompletableFuture fillFromNoise(Executor executor, Blender blender, RandomState randomstate, StructureManager structuremanager, ChunkAccess chunkaccess) { +- List list = this.settings.getLayers(); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); +- Heightmap heightmap = chunkaccess.getOrCreateHeightmapUnprimed(Heightmap.Types.OCEAN_FLOOR_WG); +- Heightmap heightmap1 = chunkaccess.getOrCreateHeightmapUnprimed(Heightmap.Types.WORLD_SURFACE_WG); ++ public CompletableFuture fillFromNoise(Executor executor, Blender blender, RandomState random, StructureManager structureManager, ChunkAccess chunk) { ++ List list = this.settings.getLayers(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ Heightmap heightmap = chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.OCEAN_FLOOR_WG); ++ Heightmap heightmap1 = chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.WORLD_SURFACE_WG); + +- for (int i = 0; i < Math.min(chunkaccess.getHeight(), list.size()); ++i) { +- BlockState blockstate = (BlockState) list.get(i); ++ for (int i = 0; i < Math.min(chunk.getHeight(), list.size()); ++i) { ++ IBlockData iblockdata = (IBlockData) list.get(i); + +- if (blockstate != null) { +- int j = chunkaccess.getMinBuildHeight() + i; ++ if (iblockdata != null) { ++ int j = chunk.getMinBuildHeight() + i; + + for (int k = 0; k < 16; ++k) { + for (int l = 0; l < 16; ++l) { +- chunkaccess.setBlockState(blockpos_mutableblockpos.set(k, j, l), blockstate, false); +- heightmap.update(k, j, l, blockstate); +- heightmap1.update(k, j, l, blockstate); ++ chunk.setBlockState(blockposition_mutableblockposition.set(k, j, l), iblockdata, false); ++ heightmap.update(k, j, l, iblockdata); ++ heightmap1.update(k, j, l, iblockdata); + } + } + } + } + +- return CompletableFuture.completedFuture(chunkaccess); ++ return CompletableFuture.completedFuture(chunk); + } + + @Override +- @Override +- public int getBaseHeight(int i, int j, Heightmap.Types heightmap_types, LevelHeightAccessor levelheightaccessor, RandomState randomstate) { +- List list = this.settings.getLayers(); ++ public int getBaseHeight(int x, int z, Heightmap.Types type, LevelHeightAccessor level, RandomState random) { ++ List list = this.settings.getLayers(); + +- for (int k = Math.min(list.size(), levelheightaccessor.getMaxBuildHeight()) - 1; k >= 0; --k) { +- BlockState blockstate = (BlockState) list.get(k); ++ for (int k = Math.min(list.size(), level.getMaxBuildHeight()) - 1; k >= 0; --k) { ++ IBlockData iblockdata = (IBlockData) list.get(k); + +- if (blockstate != null && heightmap_types.isOpaque().test(blockstate)) { +- return levelheightaccessor.getMinBuildHeight() + k + 1; ++ if (iblockdata != null && type.isOpaque().test(iblockdata)) { ++ return level.getMinBuildHeight() + k + 1; + } + } + +- return levelheightaccessor.getMinBuildHeight(); ++ return level.getMinBuildHeight(); + } + + @Override +- @Override +- public NoiseColumn getBaseColumn(int i, int j, LevelHeightAccessor levelheightaccessor, RandomState randomstate) { +- return new NoiseColumn(levelheightaccessor.getMinBuildHeight(), (BlockState[]) this.settings.getLayers().stream().limit((long) levelheightaccessor.getHeight()).map((blockstate) -> { +- return blockstate == null ? Blocks.AIR.defaultBlockState() : blockstate; ++ public NoiseColumn getBaseColumn(int x, int z, LevelHeightAccessor height, RandomState random) { ++ return new NoiseColumn(height.getMinBuildHeight(), (IBlockData[]) this.settings.getLayers().stream().limit((long) height.getHeight()).map((iblockdata) -> { ++ return iblockdata == null ? Blocks.AIR.defaultBlockState() : iblockdata; + }).toArray((k) -> { +- return new BlockState[k]; ++ return new IBlockData[k]; + })); + } + + @Override +- @Override +- public void addDebugScreenInfo(List list, RandomState randomstate, BlockPos blockpos) {} ++ public void addDebugScreenInfo(List info, RandomState random, BlockPos pos) {} + + @Override +- @Override +- public void applyCarvers(WorldGenRegion worldgenregion, long i, RandomState randomstate, BiomeManager biomemanager, StructureManager structuremanager, ChunkAccess chunkaccess, GenerationStep.Carving generationstep_carving) {} ++ public void applyCarvers(WorldGenRegion level, long seed, RandomState randomstate, BiomeManager random, StructureManager biomeManager, ChunkAccess structureManager, GenerationStep.Carving chunk) {} + + @Override +- @Override +- public void spawnOriginalMobs(WorldGenRegion worldgenregion) {} ++ public void spawnOriginalMobs(WorldGenRegion level) {} + + @Override +- @Override + public int getMinY() { + return 0; + } + + @Override +- @Override + public int getGenDepth() { + return 384; + } + + @Override +- @Override + public int getSeaLevel() { + return -63; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java.patch new file mode 100644 index 0000000000..f5b8641e81 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java.patch @@ -0,0 +1,491 @@ +--- a/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java ++++ b/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +@@ -1,3 +1,4 @@ ++// keep + package net.minecraft.world.level.levelgen; + + import com.google.common.annotations.VisibleForTesting; +@@ -37,7 +38,7 @@ + import net.minecraft.world.level.biome.BiomeResolver; + import net.minecraft.world.level.biome.BiomeSource; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.CarvingMask; + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkGenerator; +@@ -52,59 +53,57 @@ + public final class NoiseBasedChunkGenerator extends ChunkGenerator { + + public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { +- return instance.group(BiomeSource.CODEC.fieldOf("biome_source").forGetter((noisebasedchunkgenerator) -> { +- return noisebasedchunkgenerator.biomeSource; +- }), NoiseGeneratorSettings.CODEC.fieldOf("settings").forGetter((noisebasedchunkgenerator) -> { +- return noisebasedchunkgenerator.settings; ++ return instance.group(BiomeSource.CODEC.fieldOf("biome_source").forGetter((chunkgeneratorabstract) -> { ++ return chunkgeneratorabstract.biomeSource; ++ }), NoiseGeneratorSettings.CODEC.fieldOf("settings").forGetter((chunkgeneratorabstract) -> { ++ return chunkgeneratorabstract.settings; + })).apply(instance, instance.stable(NoiseBasedChunkGenerator::new)); + }); +- private static final BlockState AIR = Blocks.AIR.defaultBlockState(); +- private final Holder settings; ++ private static final IBlockData AIR = Blocks.AIR.defaultBlockState(); ++ public final Holder settings; + private final Supplier globalFluidPicker; + +- public NoiseBasedChunkGenerator(BiomeSource biomesource, Holder holder) { +- super(biomesource); +- this.settings = holder; ++ public NoiseBasedChunkGenerator(BiomeSource biomeSource, Holder settings) { ++ super(biomeSource); ++ this.settings = settings; + this.globalFluidPicker = Suppliers.memoize(() -> { +- return createFluidPicker((NoiseGeneratorSettings) holder.value()); ++ return createFluidPicker((NoiseGeneratorSettings) settings.value()); + }); + } + +- private static Aquifer.FluidPicker createFluidPicker(NoiseGeneratorSettings noisegeneratorsettings) { +- Aquifer.FluidStatus aquifer_fluidstatus = new Aquifer.FluidStatus(-54, Blocks.LAVA.defaultBlockState()); +- int i = noisegeneratorsettings.seaLevel(); +- Aquifer.FluidStatus aquifer_fluidstatus1 = new Aquifer.FluidStatus(i, noisegeneratorsettings.defaultFluid()); +- Aquifer.FluidStatus aquifer_fluidstatus2 = new Aquifer.FluidStatus(DimensionType.MIN_Y * 2, Blocks.AIR.defaultBlockState()); ++ private static Aquifer.FluidPicker createFluidPicker(NoiseGeneratorSettings settings) { ++ Aquifer.FluidStatus aquifer_b = new Aquifer.FluidStatus(-54, Blocks.LAVA.defaultBlockState()); ++ int i = settings.seaLevel(); ++ Aquifer.FluidStatus aquifer_b1 = new Aquifer.FluidStatus(i, settings.defaultFluid()); ++ Aquifer.FluidStatus aquifer_b2 = new Aquifer.FluidStatus(DimensionType.MIN_Y * 2, Blocks.AIR.defaultBlockState()); + + return (j, k, l) -> { +- return k < Math.min(-54, i) ? aquifer_fluidstatus : aquifer_fluidstatus1; ++ return k < Math.min(-54, i) ? aquifer_b : aquifer_b1; + }; + } + + @Override +- @Override +- public CompletableFuture createBiomes(Executor executor, RandomState randomstate, Blender blender, StructureManager structuremanager, ChunkAccess chunkaccess) { ++ public CompletableFuture createBiomes(Executor executor, RandomState randomState, Blender blender, StructureManager structureManager, ChunkAccess chunk) { + return CompletableFuture.supplyAsync(Util.wrapThreadWithTaskName("init_biomes", () -> { +- this.doCreateBiomes(blender, randomstate, structuremanager, chunkaccess); +- return chunkaccess; ++ this.doCreateBiomes(blender, randomState, structureManager, chunk); ++ return chunk; + }), Util.backgroundExecutor()); + } + +- private void doCreateBiomes(Blender blender, RandomState randomstate, StructureManager structuremanager, ChunkAccess chunkaccess) { +- NoiseChunk noisechunk = chunkaccess.getOrCreateNoiseChunk((chunkaccess1) -> { +- return this.createNoiseChunk(chunkaccess1, structuremanager, blender, randomstate); ++ private void doCreateBiomes(Blender blender, RandomState random, StructureManager structureManager, ChunkAccess chunk) { ++ NoiseChunk noisechunk = chunk.getOrCreateNoiseChunk((ichunkaccess1) -> { ++ return this.createNoiseChunk(ichunkaccess1, structureManager, blender, random); + }); +- BiomeResolver biomeresolver = BelowZeroRetrogen.getBiomeResolver(blender.getBiomeResolver(this.biomeSource), chunkaccess); ++ BiomeResolver biomeresolver = BelowZeroRetrogen.getBiomeResolver(blender.getBiomeResolver(this.biomeSource), chunk); + +- chunkaccess.fillBiomesFromNoise(biomeresolver, noisechunk.cachedClimateSampler(randomstate.router(), ((NoiseGeneratorSettings) this.settings.value()).spawnTarget())); ++ chunk.fillBiomesFromNoise(biomeresolver, noisechunk.cachedClimateSampler(random.router(), ((NoiseGeneratorSettings) this.settings.value()).spawnTarget())); + } + +- private NoiseChunk createNoiseChunk(ChunkAccess chunkaccess, StructureManager structuremanager, Blender blender, RandomState randomstate) { +- return NoiseChunk.forChunk(chunkaccess, randomstate, Beardifier.forStructuresInChunk(structuremanager, chunkaccess.getPos()), (NoiseGeneratorSettings) this.settings.value(), (Aquifer.FluidPicker) this.globalFluidPicker.get(), blender); ++ private NoiseChunk createNoiseChunk(ChunkAccess chunk, StructureManager structureManager, Blender blender, RandomState random) { ++ return NoiseChunk.forChunk(chunk, random, Beardifier.forStructuresInChunk(structureManager, chunk.getPos()), (NoiseGeneratorSettings) this.settings.value(), (Aquifer.FluidPicker) this.globalFluidPicker.get(), blender); + } + + @Override +- @Override + protected Codec codec() { + return NoiseBasedChunkGenerator.CODEC; + } +@@ -113,39 +112,36 @@ + return this.settings; + } + +- public boolean stable(ResourceKey resourcekey) { +- return this.settings.is(resourcekey); ++ public boolean stable(ResourceKey settings) { ++ return this.settings.is(settings); + } + + @Override +- @Override +- public int getBaseHeight(int i, int j, Heightmap.Types heightmap_types, LevelHeightAccessor levelheightaccessor, RandomState randomstate) { +- return this.iterateNoiseColumn(levelheightaccessor, randomstate, i, j, (MutableObject) null, heightmap_types.isOpaque()).orElse(levelheightaccessor.getMinBuildHeight()); ++ public int getBaseHeight(int x, int z, Heightmap.Types type, LevelHeightAccessor level, RandomState random) { ++ return this.iterateNoiseColumn(level, random, x, z, (MutableObject) null, type.isOpaque()).orElse(level.getMinBuildHeight()); + } + + @Override +- @Override +- public NoiseColumn getBaseColumn(int i, int j, LevelHeightAccessor levelheightaccessor, RandomState randomstate) { ++ public NoiseColumn getBaseColumn(int x, int z, LevelHeightAccessor height, RandomState random) { + MutableObject mutableobject = new MutableObject(); + +- this.iterateNoiseColumn(levelheightaccessor, randomstate, i, j, mutableobject, (Predicate) null); ++ this.iterateNoiseColumn(height, random, x, z, mutableobject, (Predicate) null); + return (NoiseColumn) mutableobject.getValue(); + } + + @Override +- @Override +- public void addDebugScreenInfo(List list, RandomState randomstate, BlockPos blockpos) { ++ public void addDebugScreenInfo(List info, RandomState random, BlockPos pos) { + DecimalFormat decimalformat = new DecimalFormat("0.000"); +- NoiseRouter noiserouter = randomstate.router(); +- DensityFunction.SinglePointContext densityfunction_singlepointcontext = new DensityFunction.SinglePointContext(blockpos.getX(), blockpos.getY(), blockpos.getZ()); +- double d0 = noiserouter.ridges().compute(densityfunction_singlepointcontext); +- String s = decimalformat.format(noiserouter.temperature().compute(densityfunction_singlepointcontext)); ++ NoiseRouter noiserouter = random.router(); ++ DensityFunction.e densityfunction_e = new DensityFunction.e(pos.getX(), pos.getY(), pos.getZ()); ++ double d0 = noiserouter.ridges().compute(densityfunction_e); ++ String s = decimalformat.format(noiserouter.temperature().compute(densityfunction_e)); + +- list.add("NoiseRouter T: " + s + " V: " + decimalformat.format(noiserouter.vegetation().compute(densityfunction_singlepointcontext)) + " C: " + decimalformat.format(noiserouter.continents().compute(densityfunction_singlepointcontext)) + " E: " + decimalformat.format(noiserouter.erosion().compute(densityfunction_singlepointcontext)) + " D: " + decimalformat.format(noiserouter.depth().compute(densityfunction_singlepointcontext)) + " W: " + decimalformat.format(d0) + " PV: " + decimalformat.format((double) NoiseRouterData.peaksAndValleys((float) d0)) + " AS: " + decimalformat.format(noiserouter.initialDensityWithoutJaggedness().compute(densityfunction_singlepointcontext)) + " N: " + decimalformat.format(noiserouter.finalDensity().compute(densityfunction_singlepointcontext))); ++ info.add("NoiseRouter T: " + s + " V: " + decimalformat.format(noiserouter.vegetation().compute(densityfunction_e)) + " C: " + decimalformat.format(noiserouter.continents().compute(densityfunction_e)) + " E: " + decimalformat.format(noiserouter.erosion().compute(densityfunction_e)) + " D: " + decimalformat.format(noiserouter.depth().compute(densityfunction_e)) + " W: " + decimalformat.format(d0) + " PV: " + decimalformat.format((double) NoiseRouterData.peaksAndValleys((float) d0)) + " AS: " + decimalformat.format(noiserouter.initialDensityWithoutJaggedness().compute(densityfunction_e)) + " N: " + decimalformat.format(noiserouter.finalDensity().compute(densityfunction_e))); + } + +- private OptionalInt iterateNoiseColumn(LevelHeightAccessor levelheightaccessor, RandomState randomstate, int i, int j, @Nullable MutableObject mutableobject, @Nullable Predicate predicate) { +- NoiseSettings noisesettings = ((NoiseGeneratorSettings) this.settings.value()).noiseSettings().clampToHeightAccessor(levelheightaccessor); ++ private OptionalInt iterateNoiseColumn(LevelHeightAccessor level, RandomState random, int x, int z, @Nullable MutableObject column, @Nullable Predicate stoppingState) { ++ NoiseSettings noisesettings = ((NoiseGeneratorSettings) this.settings.value()).noiseSettings().clampToHeightAccessor(level); + int k = noisesettings.getCellHeight(); + int l = noisesettings.minY(); + int i1 = Mth.floorDiv(l, k); +@@ -154,25 +150,25 @@ + if (j1 <= 0) { + return OptionalInt.empty(); + } else { +- BlockState[] ablockstate; ++ IBlockData[] aiblockdata; + +- if (mutableobject == null) { +- ablockstate = null; ++ if (column == null) { ++ aiblockdata = null; + } else { +- ablockstate = new BlockState[noisesettings.height()]; +- mutableobject.setValue(new NoiseColumn(l, ablockstate)); ++ aiblockdata = new IBlockData[noisesettings.height()]; ++ column.setValue(new NoiseColumn(l, aiblockdata)); + } + + int k1 = noisesettings.getCellWidth(); +- int l1 = Math.floorDiv(i, k1); +- int i2 = Math.floorDiv(j, k1); +- int j2 = Math.floorMod(i, k1); +- int k2 = Math.floorMod(j, k1); ++ int l1 = Math.floorDiv(x, k1); ++ int i2 = Math.floorDiv(z, k1); ++ int j2 = Math.floorMod(x, k1); ++ int k2 = Math.floorMod(z, k1); + int l2 = l1 * k1; + int i3 = i2 * k1; + double d0 = (double) j2 / (double) k1; + double d1 = (double) k2 / (double) k1; +- NoiseChunk noisechunk = new NoiseChunk(1, randomstate, l2, i3, noisesettings, DensityFunctions.BeardifierMarker.INSTANCE, (NoiseGeneratorSettings) this.settings.value(), (Aquifer.FluidPicker) this.globalFluidPicker.get(), Blender.empty()); ++ NoiseChunk noisechunk = new NoiseChunk(1, random, l2, i3, noisesettings, DensityFunctions.b.INSTANCE, (NoiseGeneratorSettings) this.settings.value(), (Aquifer.FluidPicker) this.globalFluidPicker.get(), Blender.empty()); + + noisechunk.initializeForFirstCellX(); + noisechunk.advanceCellX(0); +@@ -185,18 +181,18 @@ + double d2 = (double) k3 / (double) k; + + noisechunk.updateForY(l3, d2); +- noisechunk.updateForX(i, d0); +- noisechunk.updateForZ(j, d1); +- BlockState blockstate = noisechunk.getInterpolatedState(); +- BlockState blockstate1 = blockstate == null ? ((NoiseGeneratorSettings) this.settings.value()).defaultBlock() : blockstate; ++ noisechunk.updateForX(x, d0); ++ noisechunk.updateForZ(z, d1); ++ IBlockData iblockdata = noisechunk.getInterpolatedState(); ++ IBlockData iblockdata1 = iblockdata == null ? ((NoiseGeneratorSettings) this.settings.value()).defaultBlock() : iblockdata; + +- if (ablockstate != null) { ++ if (aiblockdata != null) { + int i4 = j3 * k + k3; + +- ablockstate[i4] = blockstate1; ++ aiblockdata[i4] = iblockdata1; + } + +- if (predicate != null && predicate.test(blockstate1)) { ++ if (stoppingState != null && stoppingState.test(iblockdata1)) { + noisechunk.stopInterpolation(); + return OptionalInt.of(l3 + 1); + } +@@ -209,59 +205,57 @@ + } + + @Override +- @Override +- public void buildSurface(WorldGenRegion worldgenregion, StructureManager structuremanager, RandomState randomstate, ChunkAccess chunkaccess) { +- if (!SharedConstants.debugVoidTerrain(chunkaccess.getPos())) { +- WorldGenerationContext worldgenerationcontext = new WorldGenerationContext(this, worldgenregion); ++ public void buildSurface(WorldGenRegion level, StructureManager structureManager, RandomState random, ChunkAccess chunk) { ++ if (!SharedConstants.debugVoidTerrain(chunk.getPos())) { ++ WorldGenerationContext worldgenerationcontext = new WorldGenerationContext(this, level); + +- this.buildSurface(chunkaccess, worldgenerationcontext, randomstate, structuremanager, worldgenregion.getBiomeManager(), worldgenregion.registryAccess().registryOrThrow(Registries.BIOME), Blender.of(worldgenregion)); ++ this.buildSurface(chunk, worldgenerationcontext, random, structureManager, level.getBiomeManager(), level.registryAccess().registryOrThrow(Registries.BIOME), Blender.of(level)); + } + } + + @VisibleForTesting +- public void buildSurface(ChunkAccess chunkaccess, WorldGenerationContext worldgenerationcontext, RandomState randomstate, StructureManager structuremanager, BiomeManager biomemanager, Registry registry, Blender blender) { +- NoiseChunk noisechunk = chunkaccess.getOrCreateNoiseChunk((chunkaccess1) -> { +- return this.createNoiseChunk(chunkaccess1, structuremanager, blender, randomstate); ++ public void buildSurface(ChunkAccess chunk, WorldGenerationContext context, RandomState random, StructureManager structureManager, BiomeManager biomeManager, Registry biomes, Blender blender) { ++ NoiseChunk noisechunk = chunk.getOrCreateNoiseChunk((ichunkaccess1) -> { ++ return this.createNoiseChunk(ichunkaccess1, structureManager, blender, random); + }); +- NoiseGeneratorSettings noisegeneratorsettings = (NoiseGeneratorSettings) this.settings.value(); ++ NoiseGeneratorSettings generatorsettingbase = (NoiseGeneratorSettings) this.settings.value(); + +- randomstate.surfaceSystem().buildSurface(randomstate, biomemanager, registry, noisegeneratorsettings.useLegacyRandomSource(), worldgenerationcontext, chunkaccess, noisechunk, noisegeneratorsettings.surfaceRule()); ++ random.surfaceSystem().buildSurface(random, biomeManager, biomes, generatorsettingbase.useLegacyRandomSource(), context, chunk, noisechunk, generatorsettingbase.surfaceRule()); + } + + @Override +- @Override +- public void applyCarvers(WorldGenRegion worldgenregion, long i, RandomState randomstate, BiomeManager biomemanager, StructureManager structuremanager, ChunkAccess chunkaccess, GenerationStep.Carving generationstep_carving) { +- BiomeManager biomemanager1 = biomemanager.withDifferentSource((j, k, l) -> { ++ public void applyCarvers(WorldGenRegion level, long seed, RandomState randomstate, BiomeManager random, StructureManager biomeManager, ChunkAccess structureManager, GenerationStep.Carving chunk) { ++ BiomeManager biomemanager1 = random.withDifferentSource((j, k, l) -> { + return this.biomeSource.getNoiseBiome(j, k, l, randomstate.sampler()); + }); +- WorldgenRandom worldgenrandom = new WorldgenRandom(new LegacyRandomSource(RandomSupport.generateUniqueSeed())); ++ WorldgenRandom seededrandom = new WorldgenRandom(new LegacyRandomSource(RandomSupport.generateUniqueSeed())); + boolean flag = true; +- ChunkPos chunkpos = chunkaccess.getPos(); +- NoiseChunk noisechunk = chunkaccess.getOrCreateNoiseChunk((chunkaccess1) -> { +- return this.createNoiseChunk(chunkaccess1, structuremanager, Blender.of(worldgenregion), randomstate); ++ ChunkPos chunkcoordintpair = structureManager.getPos(); ++ NoiseChunk noisechunk = structureManager.getOrCreateNoiseChunk((ichunkaccess1) -> { ++ return this.createNoiseChunk(ichunkaccess1, biomeManager, Blender.of(level), randomstate); + }); + Aquifer aquifer = noisechunk.aquifer(); +- CarvingContext carvingcontext = new CarvingContext(this, worldgenregion.registryAccess(), chunkaccess.getHeightAccessorForGeneration(), noisechunk, randomstate, ((NoiseGeneratorSettings) this.settings.value()).surfaceRule()); +- CarvingMask carvingmask = ((ProtoChunk) chunkaccess).getOrCreateCarvingMask(generationstep_carving); ++ CarvingContext carvingcontext = new CarvingContext(this, level.registryAccess(), structureManager.getHeightAccessorForGeneration(), noisechunk, randomstate, ((NoiseGeneratorSettings) this.settings.value()).surfaceRule()); ++ CarvingMask carvingmask = ((ProtoChunk) structureManager).getOrCreateCarvingMask(chunk); + + for (int j = -8; j <= 8; ++j) { + for (int k = -8; k <= 8; ++k) { +- ChunkPos chunkpos1 = new ChunkPos(chunkpos.x + j, chunkpos.z + k); +- ChunkAccess chunkaccess1 = worldgenregion.getChunk(chunkpos1.x, chunkpos1.z); +- BiomeGenerationSettings biomegenerationsettings = chunkaccess1.carverBiome(() -> { +- return this.getBiomeGenerationSettings(this.biomeSource.getNoiseBiome(QuartPos.fromBlock(chunkpos1.getMinBlockX()), 0, QuartPos.fromBlock(chunkpos1.getMinBlockZ()), randomstate.sampler())); ++ ChunkPos chunkcoordintpair1 = new ChunkPos(chunkcoordintpair.x + j, chunkcoordintpair.z + k); ++ ChunkAccess ichunkaccess1 = level.getChunk(chunkcoordintpair1.x, chunkcoordintpair1.z); ++ BiomeGenerationSettings biomesettingsgeneration = ichunkaccess1.carverBiome(() -> { ++ return this.getBiomeGenerationSettings(this.biomeSource.getNoiseBiome(QuartPos.fromBlock(chunkcoordintpair1.getMinBlockX()), 0, QuartPos.fromBlock(chunkcoordintpair1.getMinBlockZ()), randomstate.sampler())); + }); +- Iterable>> iterable = biomegenerationsettings.getCarvers(generationstep_carving); ++ Iterable>> iterable = biomesettingsgeneration.getCarvers(chunk); + int l = 0; + + for (Iterator iterator = iterable.iterator(); iterator.hasNext(); ++l) { + Holder> holder = (Holder) iterator.next(); +- ConfiguredWorldCarver configuredworldcarver = (ConfiguredWorldCarver) holder.value(); ++ ConfiguredWorldCarver worldgencarverwrapper = (ConfiguredWorldCarver) holder.value(); + +- worldgenrandom.setLargeFeatureSeed(i + (long) l, chunkpos1.x, chunkpos1.z); +- if (configuredworldcarver.isStartChunk(worldgenrandom)) { ++ seededrandom.setLargeFeatureSeed(seed + (long) l, chunkcoordintpair1.x, chunkcoordintpair1.z); ++ if (worldgencarverwrapper.isStartChunk(seededrandom)) { + Objects.requireNonNull(biomemanager1); +- configuredworldcarver.carve(carvingcontext, chunkaccess, biomemanager1::getBiome, worldgenrandom, aquifer, chunkpos1, carvingmask); ++ worldgencarverwrapper.carve(carvingcontext, structureManager, biomemanager1::getBiome, seededrandom, aquifer, chunkcoordintpair1, carvingmask); + } + } + } +@@ -270,55 +264,54 @@ + } + + @Override +- @Override +- public CompletableFuture fillFromNoise(Executor executor, Blender blender, RandomState randomstate, StructureManager structuremanager, ChunkAccess chunkaccess) { +- NoiseSettings noisesettings = ((NoiseGeneratorSettings) this.settings.value()).noiseSettings().clampToHeightAccessor(chunkaccess.getHeightAccessorForGeneration()); ++ public CompletableFuture fillFromNoise(Executor executor, Blender blender, RandomState random, StructureManager structureManager, ChunkAccess chunk) { ++ NoiseSettings noisesettings = ((NoiseGeneratorSettings) this.settings.value()).noiseSettings().clampToHeightAccessor(chunk.getHeightAccessorForGeneration()); + int i = noisesettings.minY(); + int j = Mth.floorDiv(i, noisesettings.getCellHeight()); + int k = Mth.floorDiv(noisesettings.height(), noisesettings.getCellHeight()); + + if (k <= 0) { +- return CompletableFuture.completedFuture(chunkaccess); ++ return CompletableFuture.completedFuture(chunk); + } else { +- int l = chunkaccess.getSectionIndex(k * noisesettings.getCellHeight() - 1 + i); +- int i1 = chunkaccess.getSectionIndex(i); ++ int l = chunk.getSectionIndex(k * noisesettings.getCellHeight() - 1 + i); ++ int i1 = chunk.getSectionIndex(i); + Set set = Sets.newHashSet(); + + for (int j1 = l; j1 >= i1; --j1) { +- LevelChunkSection levelchunksection = chunkaccess.getSection(j1); ++ LevelChunkSection chunksection = chunk.getSection(j1); + +- levelchunksection.acquire(); +- set.add(levelchunksection); ++ chunksection.acquire(); ++ set.add(chunksection); + } + + return CompletableFuture.supplyAsync(Util.wrapThreadWithTaskName("wgen_fill_noise", () -> { +- return this.doFill(blender, structuremanager, randomstate, chunkaccess, j, k); +- }), Util.backgroundExecutor()).whenCompleteAsync((chunkaccess1, throwable) -> { ++ return this.doFill(blender, structureManager, random, chunk, j, k); ++ }), Util.backgroundExecutor()).whenCompleteAsync((ichunkaccess1, throwable) -> { + Iterator iterator = set.iterator(); + + while (iterator.hasNext()) { +- LevelChunkSection levelchunksection1 = (LevelChunkSection) iterator.next(); ++ LevelChunkSection chunksection1 = (LevelChunkSection) iterator.next(); + +- levelchunksection1.release(); ++ chunksection1.release(); + } + + }, executor); + } + } + +- private ChunkAccess doFill(Blender blender, StructureManager structuremanager, RandomState randomstate, ChunkAccess chunkaccess, int i, int j) { +- NoiseChunk noisechunk = chunkaccess.getOrCreateNoiseChunk((chunkaccess1) -> { +- return this.createNoiseChunk(chunkaccess1, structuremanager, blender, randomstate); ++ private ChunkAccess doFill(Blender blender, StructureManager structureManager, RandomState random, ChunkAccess chunk, int minCellY, int cellCountY) { ++ NoiseChunk noisechunk = chunk.getOrCreateNoiseChunk((ichunkaccess1) -> { ++ return this.createNoiseChunk(ichunkaccess1, structureManager, blender, random); + }); +- Heightmap heightmap = chunkaccess.getOrCreateHeightmapUnprimed(Heightmap.Types.OCEAN_FLOOR_WG); +- Heightmap heightmap1 = chunkaccess.getOrCreateHeightmapUnprimed(Heightmap.Types.WORLD_SURFACE_WG); +- ChunkPos chunkpos = chunkaccess.getPos(); +- int k = chunkpos.getMinBlockX(); +- int l = chunkpos.getMinBlockZ(); ++ Heightmap heightmap = chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.OCEAN_FLOOR_WG); ++ Heightmap heightmap1 = chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.WORLD_SURFACE_WG); ++ ChunkPos chunkcoordintpair = chunk.getPos(); ++ int k = chunkcoordintpair.getMinBlockX(); ++ int l = chunkcoordintpair.getMinBlockZ(); + Aquifer aquifer = noisechunk.aquifer(); + + noisechunk.initializeForFirstCellX(); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + int i1 = noisechunk.cellWidth(); + int j1 = noisechunk.cellHeight(); + int k1 = 16 / i1; +@@ -328,20 +321,20 @@ + noisechunk.advanceCellX(i2); + + for (int j2 = 0; j2 < l1; ++j2) { +- int k2 = chunkaccess.getSectionsCount() - 1; +- LevelChunkSection levelchunksection = chunkaccess.getSection(k2); ++ int k2 = chunk.getSectionsCount() - 1; ++ LevelChunkSection chunksection = chunk.getSection(k2); + +- for (int l2 = j - 1; l2 >= 0; --l2) { ++ for (int l2 = cellCountY - 1; l2 >= 0; --l2) { + noisechunk.selectCellYZ(l2, j2); + + for (int i3 = j1 - 1; i3 >= 0; --i3) { +- int j3 = (i + l2) * j1 + i3; ++ int j3 = (minCellY + l2) * j1 + i3; + int k3 = j3 & 15; +- int l3 = chunkaccess.getSectionIndex(j3); ++ int l3 = chunk.getSectionIndex(j3); + + if (k2 != l3) { + k2 = l3; +- levelchunksection = chunkaccess.getSection(l3); ++ chunksection = chunk.getSection(l3); + } + + double d0 = (double) i3 / (double) j1; +@@ -361,20 +354,20 @@ + double d2 = (double) l4 / (double) i1; + + noisechunk.updateForZ(i5, d2); +- BlockState blockstate = noisechunk.getInterpolatedState(); ++ IBlockData iblockdata = noisechunk.getInterpolatedState(); + +- if (blockstate == null) { +- blockstate = ((NoiseGeneratorSettings) this.settings.value()).defaultBlock(); ++ if (iblockdata == null) { ++ iblockdata = ((NoiseGeneratorSettings) this.settings.value()).defaultBlock(); + } + +- blockstate = this.debugPreliminarySurfaceLevel(noisechunk, j4, j3, i5, blockstate); +- if (blockstate != NoiseBasedChunkGenerator.AIR && !SharedConstants.debugVoidTerrain(chunkaccess.getPos())) { +- levelchunksection.setBlockState(k4, k3, j5, blockstate, false); +- heightmap.update(k4, j3, j5, blockstate); +- heightmap1.update(k4, j3, j5, blockstate); +- if (aquifer.shouldScheduleFluidUpdate() && !blockstate.getFluidState().isEmpty()) { +- blockpos_mutableblockpos.set(j4, j3, i5); +- chunkaccess.markPosForPostprocessing(blockpos_mutableblockpos); ++ iblockdata = this.debugPreliminarySurfaceLevel(noisechunk, j4, j3, i5, iblockdata); ++ if (iblockdata != NoiseBasedChunkGenerator.AIR && !SharedConstants.debugVoidTerrain(chunk.getPos())) { ++ chunksection.setBlockState(k4, k3, j5, iblockdata, false); ++ heightmap.update(k4, j3, j5, iblockdata); ++ heightmap1.update(k4, j3, j5, iblockdata); ++ if (aquifer.shouldScheduleFluidUpdate() && !iblockdata.getFluidState().isEmpty()) { ++ blockposition_mutableblockposition.set(j4, j3, i5); ++ chunk.markPosForPostprocessing(blockposition_mutableblockposition); + } + } + } +@@ -387,41 +380,37 @@ + } + + noisechunk.stopInterpolation(); +- return chunkaccess; ++ return chunk; + } + +- private BlockState debugPreliminarySurfaceLevel(NoiseChunk noisechunk, int i, int j, int k, BlockState blockstate) { +- return blockstate; ++ private IBlockData debugPreliminarySurfaceLevel(NoiseChunk chunk, int x, int y, int z, IBlockData state) { ++ return state; + } + + @Override +- @Override + public int getGenDepth() { + return ((NoiseGeneratorSettings) this.settings.value()).noiseSettings().height(); + } + + @Override +- @Override + public int getSeaLevel() { + return ((NoiseGeneratorSettings) this.settings.value()).seaLevel(); + } + + @Override +- @Override + public int getMinY() { + return ((NoiseGeneratorSettings) this.settings.value()).noiseSettings().minY(); + } + + @Override +- @Override +- public void spawnOriginalMobs(WorldGenRegion worldgenregion) { ++ public void spawnOriginalMobs(WorldGenRegion level) { + if (!((NoiseGeneratorSettings) this.settings.value()).disableMobGeneration()) { +- ChunkPos chunkpos = worldgenregion.getCenter(); +- Holder holder = worldgenregion.getBiome(chunkpos.getWorldPosition().atY(worldgenregion.getMaxBuildHeight() - 1)); +- WorldgenRandom worldgenrandom = new WorldgenRandom(new LegacyRandomSource(RandomSupport.generateUniqueSeed())); ++ ChunkPos chunkcoordintpair = level.getCenter(); ++ Holder holder = level.getBiome(chunkcoordintpair.getWorldPosition().atY(level.getMaxBuildHeight() - 1)); ++ WorldgenRandom seededrandom = new WorldgenRandom(new LegacyRandomSource(RandomSupport.generateUniqueSeed())); + +- worldgenrandom.setDecorationSeed(worldgenregion.getSeed(), chunkpos.getMinBlockX(), chunkpos.getMinBlockZ()); +- NaturalSpawner.spawnMobsForChunkGeneration(worldgenregion, holder, chunkpos, worldgenrandom); ++ seededrandom.setDecorationSeed(level.getSeed(), chunkcoordintpair.getMinBlockX(), chunkcoordintpair.getMinBlockZ()); ++ NaturalSpawner.spawnMobsForChunkGeneration(level, holder, chunkcoordintpair, seededrandom); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/PatrolSpawner.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/PatrolSpawner.java.patch new file mode 100644 index 0000000000..21311a74b2 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/PatrolSpawner.java.patch @@ -0,0 +1,146 @@ +--- a/net/minecraft/world/level/levelgen/PatrolSpawner.java ++++ b/net/minecraft/world/level/levelgen/PatrolSpawner.java +@@ -7,15 +7,15 @@ + import net.minecraft.tags.BiomeTags; + import net.minecraft.util.RandomSource; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.monster.PatrollingMonster; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.CustomSpawner; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.NaturalSpawner; + import net.minecraft.world.level.biome.Biome; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public class PatrolSpawner implements CustomSpawner { + +@@ -24,67 +24,66 @@ + public PatrolSpawner() {} + + @Override +- @Override +- public int tick(ServerLevel serverlevel, boolean flag, boolean flag1) { +- if (!flag) { ++ public int tick(ServerLevel level, boolean spawnEnemies, boolean spawnFriendlies) { ++ if (!spawnEnemies) { + return 0; +- } else if (!serverlevel.getGameRules().getBoolean(GameRules.RULE_DO_PATROL_SPAWNING)) { ++ } else if (!level.getGameRules().getBoolean(GameRules.RULE_DO_PATROL_SPAWNING)) { + return 0; + } else { +- RandomSource randomsource = serverlevel.random; ++ RandomSource randomsource = level.random; + + --this.nextTick; + if (this.nextTick > 0) { + return 0; + } else { + this.nextTick += 12000 + randomsource.nextInt(1200); +- long i = serverlevel.getDayTime() / 24000L; ++ long i = level.getDayTime() / 24000L; + +- if (i >= 5L && serverlevel.isDay()) { ++ if (i >= 5L && level.isDay()) { + if (randomsource.nextInt(5) != 0) { + return 0; + } else { +- int j = serverlevel.players().size(); ++ int j = level.players().size(); + + if (j < 1) { + return 0; + } else { +- Player player = (Player) serverlevel.players().get(randomsource.nextInt(j)); ++ Player entityhuman = (Player) level.players().get(randomsource.nextInt(j)); + +- if (player.isSpectator()) { ++ if (entityhuman.isSpectator()) { + return 0; +- } else if (serverlevel.isCloseToVillage(player.blockPosition(), 2)) { ++ } else if (level.isCloseToVillage(entityhuman.blockPosition(), 2)) { + return 0; + } else { + int k = (24 + randomsource.nextInt(24)) * (randomsource.nextBoolean() ? -1 : 1); + int l = (24 + randomsource.nextInt(24)) * (randomsource.nextBoolean() ? -1 : 1); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = player.blockPosition().mutable().move(k, 0, l); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = entityhuman.blockPosition().mutable().move(k, 0, l); + boolean flag2 = true; + +- if (!serverlevel.hasChunksAt(blockpos_mutableblockpos.getX() - 10, blockpos_mutableblockpos.getZ() - 10, blockpos_mutableblockpos.getX() + 10, blockpos_mutableblockpos.getZ() + 10)) { ++ if (!level.hasChunksAt(blockposition_mutableblockposition.getX() - 10, blockposition_mutableblockposition.getZ() - 10, blockposition_mutableblockposition.getX() + 10, blockposition_mutableblockposition.getZ() + 10)) { + return 0; + } else { +- Holder holder = serverlevel.getBiome(blockpos_mutableblockpos); ++ Holder holder = level.getBiome(blockposition_mutableblockposition); + + if (holder.is(BiomeTags.WITHOUT_PATROL_SPAWNS)) { + return 0; + } else { + int i1 = 0; +- int j1 = (int) Math.ceil((double) serverlevel.getCurrentDifficultyAt(blockpos_mutableblockpos).getEffectiveDifficulty()) + 1; ++ int j1 = (int) Math.ceil((double) level.getCurrentDifficultyAt(blockposition_mutableblockposition).getEffectiveDifficulty()) + 1; + + for (int k1 = 0; k1 < j1; ++k1) { + ++i1; +- blockpos_mutableblockpos.setY(serverlevel.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, blockpos_mutableblockpos).getY()); ++ blockposition_mutableblockposition.setY(level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, blockposition_mutableblockposition).getY()); + if (k1 == 0) { +- if (!this.spawnPatrolMember(serverlevel, blockpos_mutableblockpos, randomsource, true)) { ++ if (!this.spawnPatrolMember(level, blockposition_mutableblockposition, randomsource, true)) { + break; + } + } else { +- this.spawnPatrolMember(serverlevel, blockpos_mutableblockpos, randomsource, false); ++ this.spawnPatrolMember(level, blockposition_mutableblockposition, randomsource, false); + } + +- blockpos_mutableblockpos.setX(blockpos_mutableblockpos.getX() + randomsource.nextInt(5) - randomsource.nextInt(5)); +- blockpos_mutableblockpos.setZ(blockpos_mutableblockpos.getZ() + randomsource.nextInt(5) - randomsource.nextInt(5)); ++ blockposition_mutableblockposition.setX(blockposition_mutableblockposition.getX() + randomsource.nextInt(5) - randomsource.nextInt(5)); ++ blockposition_mutableblockposition.setZ(blockposition_mutableblockposition.getZ() + randomsource.nextInt(5) - randomsource.nextInt(5)); + } + + return i1; +@@ -100,25 +99,25 @@ + } + } + +- private boolean spawnPatrolMember(ServerLevel serverlevel, BlockPos blockpos, RandomSource randomsource, boolean flag) { +- BlockState blockstate = serverlevel.getBlockState(blockpos); ++ private boolean spawnPatrolMember(ServerLevel level, BlockPos pos, RandomSource random, boolean leader) { ++ IBlockData iblockdata = level.getBlockState(pos); + +- if (!NaturalSpawner.isValidEmptySpawnBlock(serverlevel, blockpos, blockstate, blockstate.getFluidState(), EntityType.PILLAGER)) { ++ if (!NaturalSpawner.isValidEmptySpawnBlock(level, pos, iblockdata, iblockdata.getFluidState(), EntityType.PILLAGER)) { + return false; +- } else if (!PatrollingMonster.checkPatrollingMonsterSpawnRules(EntityType.PILLAGER, serverlevel, MobSpawnType.PATROL, blockpos, randomsource)) { ++ } else if (!PatrollingMonster.checkPatrollingMonsterSpawnRules(EntityType.PILLAGER, level, EnumMobSpawn.PATROL, pos, random)) { + return false; + } else { +- PatrollingMonster patrollingmonster = (PatrollingMonster) EntityType.PILLAGER.create(serverlevel); ++ PatrollingMonster entitymonsterpatrolling = (PatrollingMonster) EntityType.PILLAGER.create(level); + +- if (patrollingmonster != null) { +- if (flag) { +- patrollingmonster.setPatrolLeader(true); +- patrollingmonster.findPatrolTarget(); ++ if (entitymonsterpatrolling != null) { ++ if (leader) { ++ entitymonsterpatrolling.setPatrolLeader(true); ++ entitymonsterpatrolling.findPatrolTarget(); + } + +- patrollingmonster.setPos((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ()); +- patrollingmonster.finalizeSpawn(serverlevel, serverlevel.getCurrentDifficultyAt(blockpos), MobSpawnType.PATROL, (SpawnGroupData) null, (CompoundTag) null); +- serverlevel.addFreshEntityWithPassengers(patrollingmonster); ++ entitymonsterpatrolling.setPos((double) pos.getX(), (double) pos.getY(), (double) pos.getZ()); ++ entitymonsterpatrolling.finalizeSpawn(level, level.getCurrentDifficultyAt(pos), EnumMobSpawn.PATROL, (GroupDataEntity) null, (CompoundTag) null); ++ level.addFreshEntityWithPassengers(entitymonsterpatrolling, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.PATROL); // CraftBukkit + return true; + } else { + return false; diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java.patch new file mode 100644 index 0000000000..fc3a43a4e6 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java.patch @@ -0,0 +1,280 @@ +--- a/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java ++++ b/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java +@@ -18,7 +18,7 @@ + import net.minecraft.resources.ResourceKey; + import net.minecraft.util.datafix.DataFixTypes; + import net.minecraft.world.level.ChunkPos; +-import net.minecraft.world.level.Level; ++import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.storage.DimensionDataStorage; + + public class LegacyStructureDataHandler { +@@ -49,10 +49,10 @@ + private final List legacyKeys; + private final List currentKeys; + +- public LegacyStructureDataHandler(@Nullable DimensionDataStorage dimensiondatastorage, List list, List list1) { +- this.legacyKeys = list; +- this.currentKeys = list1; +- this.populateCaches(dimensiondatastorage); ++ public LegacyStructureDataHandler(@Nullable DimensionDataStorage storage, List legacyKeys, List currentKeys) { ++ this.legacyKeys = legacyKeys; ++ this.currentKeys = currentKeys; ++ this.populateCaches(storage); + boolean flag = false; + + String s; +@@ -64,64 +64,64 @@ + this.hasLegacyData = flag; + } + +- public void removeIndex(long i) { ++ public void removeIndex(long packedChunkPos) { + Iterator iterator = this.legacyKeys.iterator(); + + while (iterator.hasNext()) { + String s = (String) iterator.next(); +- StructureFeatureIndexSavedData structurefeatureindexsaveddata = (StructureFeatureIndexSavedData) this.indexMap.get(s); ++ StructureFeatureIndexSavedData persistentindexed = (StructureFeatureIndexSavedData) this.indexMap.get(s); + +- if (structurefeatureindexsaveddata != null && structurefeatureindexsaveddata.hasUnhandledIndex(i)) { +- structurefeatureindexsaveddata.removeIndex(i); +- structurefeatureindexsaveddata.setDirty(); ++ if (persistentindexed != null && persistentindexed.hasUnhandledIndex(packedChunkPos)) { ++ persistentindexed.removeIndex(packedChunkPos); ++ persistentindexed.setDirty(); + } + } + + } + +- public CompoundTag updateFromLegacy(CompoundTag compoundtag) { +- CompoundTag compoundtag1 = compoundtag.getCompound("Level"); +- ChunkPos chunkpos = new ChunkPos(compoundtag1.getInt("xPos"), compoundtag1.getInt("zPos")); ++ public CompoundTag updateFromLegacy(CompoundTag tag) { ++ CompoundTag nbttagcompound1 = tag.getCompound("Level"); ++ ChunkPos chunkcoordintpair = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); + +- if (this.isUnhandledStructureStart(chunkpos.x, chunkpos.z)) { +- compoundtag = this.updateStructureStart(compoundtag, chunkpos); ++ if (this.isUnhandledStructureStart(chunkcoordintpair.x, chunkcoordintpair.z)) { ++ tag = this.updateStructureStart(tag, chunkcoordintpair); + } + +- CompoundTag compoundtag2 = compoundtag1.getCompound("Structures"); +- CompoundTag compoundtag3 = compoundtag2.getCompound("References"); ++ CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("Structures"); ++ CompoundTag nbttagcompound3 = nbttagcompound2.getCompound("References"); + Iterator iterator = this.currentKeys.iterator(); + + while (iterator.hasNext()) { + String s = (String) iterator.next(); + boolean flag = LegacyStructureDataHandler.OLD_STRUCTURE_REGISTRY_KEYS.contains(s.toLowerCase(Locale.ROOT)); + +- if (!compoundtag3.contains(s, 12) && flag) { ++ if (!nbttagcompound3.contains(s, 12) && flag) { + boolean flag1 = true; + LongArrayList longarraylist = new LongArrayList(); + +- for (int i = chunkpos.x - 8; i <= chunkpos.x + 8; ++i) { +- for (int j = chunkpos.z - 8; j <= chunkpos.z + 8; ++j) { ++ for (int i = chunkcoordintpair.x - 8; i <= chunkcoordintpair.x + 8; ++i) { ++ for (int j = chunkcoordintpair.z - 8; j <= chunkcoordintpair.z + 8; ++j) { + if (this.hasLegacyStart(i, j, s)) { + longarraylist.add(ChunkPos.asLong(i, j)); + } + } + } + +- compoundtag3.putLongArray(s, (List) longarraylist); ++ nbttagcompound3.putLongArray(s, (List) longarraylist); + } + } + +- compoundtag2.put("References", compoundtag3); +- compoundtag1.put("Structures", compoundtag2); +- compoundtag.put("Level", compoundtag1); +- return compoundtag; ++ nbttagcompound2.put("References", nbttagcompound3); ++ nbttagcompound1.put("Structures", nbttagcompound2); ++ tag.put("Level", nbttagcompound1); ++ return tag; + } + +- private boolean hasLegacyStart(int i, int j, String s) { +- return !this.hasLegacyData ? false : this.dataMap.get(s) != null && ((StructureFeatureIndexSavedData) this.indexMap.get(LegacyStructureDataHandler.CURRENT_TO_LEGACY_MAP.get(s))).hasStartIndex(ChunkPos.asLong(i, j)); ++ private boolean hasLegacyStart(int chunkX, int chunkZ, String key) { ++ return !this.hasLegacyData ? false : this.dataMap.get(key) != null && ((StructureFeatureIndexSavedData) this.indexMap.get(LegacyStructureDataHandler.CURRENT_TO_LEGACY_MAP.get(key))).hasStartIndex(ChunkPos.asLong(chunkX, chunkZ)); + } + +- private boolean isUnhandledStructureStart(int i, int j) { ++ private boolean isUnhandledStructureStart(int chunkX, int chunkZ) { + if (!this.hasLegacyData) { + return false; + } else { +@@ -135,16 +135,16 @@ + } + + s = (String) iterator.next(); +- } while (this.dataMap.get(s) == null || !((StructureFeatureIndexSavedData) this.indexMap.get(LegacyStructureDataHandler.CURRENT_TO_LEGACY_MAP.get(s))).hasUnhandledIndex(ChunkPos.asLong(i, j))); ++ } while (this.dataMap.get(s) == null || !((StructureFeatureIndexSavedData) this.indexMap.get(LegacyStructureDataHandler.CURRENT_TO_LEGACY_MAP.get(s))).hasUnhandledIndex(ChunkPos.asLong(chunkX, chunkZ))); + + return true; + } + } + +- private CompoundTag updateStructureStart(CompoundTag compoundtag, ChunkPos chunkpos) { +- CompoundTag compoundtag1 = compoundtag.getCompound("Level"); +- CompoundTag compoundtag2 = compoundtag1.getCompound("Structures"); +- CompoundTag compoundtag3 = compoundtag2.getCompound("Starts"); ++ private CompoundTag updateStructureStart(CompoundTag tag, ChunkPos chunkPos) { ++ CompoundTag nbttagcompound1 = tag.getCompound("Level"); ++ CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("Structures"); ++ CompoundTag nbttagcompound3 = nbttagcompound2.getCompound("Starts"); + Iterator iterator = this.currentKeys.iterator(); + + while (iterator.hasNext()) { +@@ -152,104 +152,104 @@ + Long2ObjectMap long2objectmap = (Long2ObjectMap) this.dataMap.get(s); + + if (long2objectmap != null) { +- long i = chunkpos.toLong(); ++ long i = chunkPos.toLong(); + + if (((StructureFeatureIndexSavedData) this.indexMap.get(LegacyStructureDataHandler.CURRENT_TO_LEGACY_MAP.get(s))).hasUnhandledIndex(i)) { +- CompoundTag compoundtag4 = (CompoundTag) long2objectmap.get(i); ++ CompoundTag nbttagcompound4 = (CompoundTag) long2objectmap.get(i); + +- if (compoundtag4 != null) { +- compoundtag3.put(s, compoundtag4); ++ if (nbttagcompound4 != null) { ++ nbttagcompound3.put(s, nbttagcompound4); + } + } + } + } + +- compoundtag2.put("Starts", compoundtag3); +- compoundtag1.put("Structures", compoundtag2); +- compoundtag.put("Level", compoundtag1); +- return compoundtag; ++ nbttagcompound2.put("Starts", nbttagcompound3); ++ nbttagcompound1.put("Structures", nbttagcompound2); ++ tag.put("Level", nbttagcompound1); ++ return tag; + } + +- private void populateCaches(@Nullable DimensionDataStorage dimensiondatastorage) { +- if (dimensiondatastorage != null) { ++ private void populateCaches(@Nullable DimensionDataStorage storage) { ++ if (storage != null) { + Iterator iterator = this.legacyKeys.iterator(); + + while (iterator.hasNext()) { + String s = (String) iterator.next(); +- CompoundTag compoundtag = new CompoundTag(); ++ CompoundTag nbttagcompound = new CompoundTag(); + + try { +- compoundtag = dimensiondatastorage.readTagFromDisk(s, DataFixTypes.SAVED_DATA_STRUCTURE_FEATURE_INDICES, 1493).getCompound("data").getCompound("Features"); +- if (compoundtag.isEmpty()) { ++ nbttagcompound = storage.readTagFromDisk(s, DataFixTypes.SAVED_DATA_STRUCTURE_FEATURE_INDICES, 1493).getCompound("data").getCompound("Features"); ++ if (nbttagcompound.isEmpty()) { + continue; + } + } catch (IOException ioexception) { + ; + } + +- Iterator iterator1 = compoundtag.getAllKeys().iterator(); ++ Iterator iterator1 = nbttagcompound.getAllKeys().iterator(); + + while (iterator1.hasNext()) { + String s1 = (String) iterator1.next(); +- CompoundTag compoundtag1 = compoundtag.getCompound(s1); +- long i = ChunkPos.asLong(compoundtag1.getInt("ChunkX"), compoundtag1.getInt("ChunkZ")); +- ListTag listtag = compoundtag1.getList("Children", 10); ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound(s1); ++ long i = ChunkPos.asLong(nbttagcompound1.getInt("ChunkX"), nbttagcompound1.getInt("ChunkZ")); ++ ListTag nbttaglist = nbttagcompound1.getList("Children", 10); + String s2; + +- if (!listtag.isEmpty()) { +- s2 = listtag.getCompound(0).getString("id"); ++ if (!nbttaglist.isEmpty()) { ++ s2 = nbttaglist.getCompound(0).getString("id"); + String s3 = (String) LegacyStructureDataHandler.LEGACY_TO_CURRENT_MAP.get(s2); + + if (s3 != null) { +- compoundtag1.putString("id", s3); ++ nbttagcompound1.putString("id", s3); + } + } + +- s2 = compoundtag1.getString("id"); ++ s2 = nbttagcompound1.getString("id"); + ((Long2ObjectMap) this.dataMap.computeIfAbsent(s2, (s4) -> { + return new Long2ObjectOpenHashMap(); +- })).put(i, compoundtag1); ++ })).put(i, nbttagcompound1); + } + + String s4 = s + "_index"; +- StructureFeatureIndexSavedData structurefeatureindexsaveddata = (StructureFeatureIndexSavedData) dimensiondatastorage.computeIfAbsent(StructureFeatureIndexSavedData.factory(), s4); ++ StructureFeatureIndexSavedData persistentindexed = (StructureFeatureIndexSavedData) storage.computeIfAbsent(StructureFeatureIndexSavedData.factory(), s4); + +- if (!structurefeatureindexsaveddata.getAll().isEmpty()) { +- this.indexMap.put(s, structurefeatureindexsaveddata); ++ if (!persistentindexed.getAll().isEmpty()) { ++ this.indexMap.put(s, persistentindexed); + } else { +- StructureFeatureIndexSavedData structurefeatureindexsaveddata1 = new StructureFeatureIndexSavedData(); ++ StructureFeatureIndexSavedData persistentindexed1 = new StructureFeatureIndexSavedData(); + +- this.indexMap.put(s, structurefeatureindexsaveddata1); +- Iterator iterator2 = compoundtag.getAllKeys().iterator(); ++ this.indexMap.put(s, persistentindexed1); ++ Iterator iterator2 = nbttagcompound.getAllKeys().iterator(); + + while (iterator2.hasNext()) { + String s5 = (String) iterator2.next(); +- CompoundTag compoundtag2 = compoundtag.getCompound(s5); ++ CompoundTag nbttagcompound2 = nbttagcompound.getCompound(s5); + +- structurefeatureindexsaveddata1.addIndex(ChunkPos.asLong(compoundtag2.getInt("ChunkX"), compoundtag2.getInt("ChunkZ"))); ++ persistentindexed1.addIndex(ChunkPos.asLong(nbttagcompound2.getInt("ChunkX"), nbttagcompound2.getInt("ChunkZ"))); + } + +- structurefeatureindexsaveddata1.setDirty(); ++ persistentindexed1.setDirty(); + } + } + + } + } + +- public static LegacyStructureDataHandler getLegacyStructureHandler(ResourceKey resourcekey, @Nullable DimensionDataStorage dimensiondatastorage) { +- if (resourcekey == Level.OVERWORLD) { +- return new LegacyStructureDataHandler(dimensiondatastorage, ImmutableList.of("Monument", "Stronghold", "Village", "Mineshaft", "Temple", "Mansion"), ImmutableList.of("Village", "Mineshaft", "Mansion", "Igloo", "Desert_Pyramid", "Jungle_Pyramid", "Swamp_Hut", "Stronghold", "Monument")); ++ public static LegacyStructureDataHandler getLegacyStructureHandler(ResourceKey level, @Nullable DimensionDataStorage storage) { // CraftBukkit ++ if (level == LevelStem.OVERWORLD) { // CraftBukkit ++ return new LegacyStructureDataHandler(storage, ImmutableList.of("Monument", "Stronghold", "Village", "Mineshaft", "Temple", "Mansion"), ImmutableList.of("Village", "Mineshaft", "Mansion", "Igloo", "Desert_Pyramid", "Jungle_Pyramid", "Swamp_Hut", "Stronghold", "Monument")); + } else { + ImmutableList immutablelist; + +- if (resourcekey == Level.NETHER) { ++ if (level == LevelStem.NETHER) { // CraftBukkit + immutablelist = ImmutableList.of("Fortress"); +- return new LegacyStructureDataHandler(dimensiondatastorage, immutablelist, immutablelist); +- } else if (resourcekey == Level.END) { ++ return new LegacyStructureDataHandler(storage, immutablelist, immutablelist); ++ } else if (level == LevelStem.END) { // CraftBukkit + immutablelist = ImmutableList.of("EndCity"); +- return new LegacyStructureDataHandler(dimensiondatastorage, immutablelist, immutablelist); ++ return new LegacyStructureDataHandler(storage, immutablelist, immutablelist); + } else { +- throw new RuntimeException(String.format(Locale.ROOT, "Unknown dimension type : %s", resourcekey)); ++ throw new RuntimeException(String.format(Locale.ROOT, "Unknown dimension type : %s", level)); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/StructurePiece.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/StructurePiece.java.patch new file mode 100644 index 0000000000..cc96842ea7 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/StructurePiece.java.patch @@ -0,0 +1,696 @@ +--- a/net/minecraft/world/level/levelgen/structure/StructurePiece.java ++++ b/net/minecraft/world/level/levelgen/structure/StructurePiece.java +@@ -29,9 +29,7 @@ + import net.minecraft.world.level.block.Mirror; + import net.minecraft.world.level.block.Rotation; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.entity.ChestBlockEntity; +-import net.minecraft.world.level.block.entity.DispenserBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.levelgen.Heightmap; + import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; +@@ -42,7 +40,7 @@ + public abstract class StructurePiece { + + private static final Logger LOGGER = LogUtils.getLogger(); +- protected static final BlockState CAVE_AIR = Blocks.CAVE_AIR.defaultBlockState(); ++ protected static final IBlockData CAVE_AIR = Blocks.CAVE_AIR.defaultBlockState(); + protected BoundingBox boundingBox; + @Nullable + private Direction orientation; +@@ -50,58 +48,53 @@ + private Rotation rotation; + protected int genDepth; + private final StructurePieceType type; +- private static final Set SHAPE_CHECK_BLOCKS = ImmutableSet.builder().add(Blocks.NETHER_BRICK_FENCE).add(Blocks.TORCH).add(Blocks.WALL_TORCH).add(Blocks.OAK_FENCE).add(Blocks.SPRUCE_FENCE).add(Blocks.DARK_OAK_FENCE).add(Blocks.ACACIA_FENCE).add(Blocks.BIRCH_FENCE).add(Blocks.JUNGLE_FENCE).add(Blocks.LADDER).add(Blocks.IRON_BARS).build(); ++ public static final Set SHAPE_CHECK_BLOCKS = ImmutableSet.builder().add(Blocks.NETHER_BRICK_FENCE).add(Blocks.TORCH).add(Blocks.WALL_TORCH).add(Blocks.OAK_FENCE).add(Blocks.SPRUCE_FENCE).add(Blocks.DARK_OAK_FENCE).add(Blocks.ACACIA_FENCE).add(Blocks.BIRCH_FENCE).add(Blocks.JUNGLE_FENCE).add(Blocks.LADDER).add(Blocks.IRON_BARS).build(); // CraftBukkit - decompile error / PAIL private -> public + +- protected StructurePiece(StructurePieceType structurepiecetype, int i, BoundingBox boundingbox) { +- this.type = structurepiecetype; +- this.genDepth = i; +- this.boundingBox = boundingbox; ++ protected StructurePiece(StructurePieceType type, int genDepth, BoundingBox boundingBox) { ++ this.type = type; ++ this.genDepth = genDepth; ++ this.boundingBox = boundingBox; + } + +- public StructurePiece(StructurePieceType structurepiecetype, CompoundTag compoundtag) { +- int i = compoundtag.getInt("GD"); +- DataResult dataresult = BoundingBox.CODEC.parse(NbtOps.INSTANCE, compoundtag.get("BB")); +- Logger logger = StructurePiece.LOGGER; +- +- Objects.requireNonNull(logger); +- this(structurepiecetype, i, (BoundingBox) dataresult.resultOrPartial(logger::error).orElseThrow(() -> { ++ public StructurePiece(StructurePieceType type, CompoundTag tag) { ++ // CraftBukkit start - decompile error ++ this(type, tag.getInt("GD"), (BoundingBox) BoundingBox.CODEC.parse(NbtOps.INSTANCE, tag.get("BB")).resultOrPartial(Objects.requireNonNull(StructurePiece.LOGGER)::error).orElseThrow(() -> { + return new IllegalArgumentException("Invalid boundingbox"); + })); +- int j = compoundtag.getInt("O"); ++ // CraftBukkit end ++ int j = tag.getInt("O"); + + this.setOrientation(j == -1 ? null : Direction.from2DDataValue(j)); + } + +- protected static BoundingBox makeBoundingBox(int i, int j, int k, Direction direction, int l, int i1, int j1) { +- return direction.getAxis() == Direction.Axis.Z ? new BoundingBox(i, j, k, i + l - 1, j + i1 - 1, k + j1 - 1) : new BoundingBox(i, j, k, i + j1 - 1, j + i1 - 1, k + l - 1); ++ protected static BoundingBox makeBoundingBox(int x, int y, int z, Direction direction, int offsetX, int offsetY, int offsetZ) { ++ return direction.getAxis() == Direction.Axis.Z ? new BoundingBox(x, y, z, x + offsetX - 1, y + offsetY - 1, z + offsetZ - 1) : new BoundingBox(x, y, z, x + offsetZ - 1, y + offsetY - 1, z + offsetX - 1); + } + +- protected static Direction getRandomHorizontalDirection(RandomSource randomsource) { +- return Direction.Plane.HORIZONTAL.getRandomDirection(randomsource); ++ protected static Direction getRandomHorizontalDirection(RandomSource random) { ++ return Direction.Plane.HORIZONTAL.getRandomDirection(random); + } + +- public final CompoundTag createTag(StructurePieceSerializationContext structurepieceserializationcontext) { +- CompoundTag compoundtag = new CompoundTag(); ++ public final CompoundTag createTag(StructurePieceSerializationContext context) { ++ CompoundTag nbttagcompound = new CompoundTag(); + +- compoundtag.putString("id", BuiltInRegistries.STRUCTURE_PIECE.getKey(this.getType()).toString()); +- DataResult dataresult = BoundingBox.CODEC.encodeStart(NbtOps.INSTANCE, this.boundingBox); +- Logger logger = StructurePiece.LOGGER; +- +- Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((tag) -> { +- compoundtag.put("BB", tag); ++ nbttagcompound.putString("id", BuiltInRegistries.STRUCTURE_PIECE.getKey(this.getType()).toString()); ++ // CraftBukkit start - decompile error ++ BoundingBox.CODEC.encodeStart(NbtOps.INSTANCE, this.boundingBox).resultOrPartial(Objects.requireNonNull(StructurePiece.LOGGER)::error).ifPresent((nbtbase) -> { ++ nbttagcompound.put("BB", nbtbase); + }); +- Direction direction = this.getOrientation(); ++ // CraftBukkit end ++ Direction enumdirection = this.getOrientation(); + +- compoundtag.putInt("O", direction == null ? -1 : direction.get2DDataValue()); +- compoundtag.putInt("GD", this.genDepth); +- this.addAdditionalSaveData(structurepieceserializationcontext, compoundtag); +- return compoundtag; ++ nbttagcompound.putInt("O", enumdirection == null ? -1 : enumdirection.get2DDataValue()); ++ nbttagcompound.putInt("GD", this.genDepth); ++ this.addAdditionalSaveData(context, nbttagcompound); ++ return nbttagcompound; + } + + protected abstract void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag); + +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) {} ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) {} + + public abstract void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos); + +@@ -113,74 +106,74 @@ + return this.genDepth; + } + +- public void setGenDepth(int i) { +- this.genDepth = i; ++ public void setGenDepth(int genDepth) { ++ this.genDepth = genDepth; + } + +- public boolean isCloseToChunk(ChunkPos chunkpos, int i) { +- int j = chunkpos.getMinBlockX(); +- int k = chunkpos.getMinBlockZ(); ++ public boolean isCloseToChunk(ChunkPos chunkPos, int distance) { ++ int j = chunkPos.getMinBlockX(); ++ int k = chunkPos.getMinBlockZ(); + +- return this.boundingBox.intersects(j - i, k - i, j + 15 + i, k + 15 + i); ++ return this.boundingBox.intersects(j - distance, k - distance, j + 15 + distance, k + 15 + distance); + } + + public BlockPos getLocatorPosition() { + return new BlockPos(this.boundingBox.getCenter()); + } + +- protected BlockPos.MutableBlockPos getWorldPos(int i, int j, int k) { +- return new BlockPos.MutableBlockPos(this.getWorldX(i, k), this.getWorldY(j), this.getWorldZ(i, k)); ++ protected BlockPos.MutableBlockPos getWorldPos(int x, int y, int z) { ++ return new BlockPos.MutableBlockPos(this.getWorldX(x, z), this.getWorldY(y), this.getWorldZ(x, z)); + } + +- protected int getWorldX(int i, int j) { +- Direction direction = this.getOrientation(); ++ protected int getWorldX(int x, int z) { ++ Direction enumdirection = this.getOrientation(); + +- if (direction == null) { +- return i; ++ if (enumdirection == null) { ++ return x; + } else { +- switch (direction) { ++ switch (enumdirection) { + case NORTH: + case SOUTH: +- return this.boundingBox.minX() + i; ++ return this.boundingBox.minX() + x; + case WEST: +- return this.boundingBox.maxX() - j; ++ return this.boundingBox.maxX() - z; + case EAST: +- return this.boundingBox.minX() + j; ++ return this.boundingBox.minX() + z; + default: +- return i; ++ return x; + } + } + } + +- protected int getWorldY(int i) { +- return this.getOrientation() == null ? i : i + this.boundingBox.minY(); ++ protected int getWorldY(int y) { ++ return this.getOrientation() == null ? y : y + this.boundingBox.minY(); + } + +- protected int getWorldZ(int i, int j) { +- Direction direction = this.getOrientation(); ++ protected int getWorldZ(int x, int z) { ++ Direction enumdirection = this.getOrientation(); + +- if (direction == null) { +- return j; ++ if (enumdirection == null) { ++ return z; + } else { +- switch (direction) { ++ switch (enumdirection) { + case NORTH: +- return this.boundingBox.maxZ() - j; ++ return this.boundingBox.maxZ() - z; + case SOUTH: +- return this.boundingBox.minZ() + j; ++ return this.boundingBox.minZ() + z; + case WEST: + case EAST: +- return this.boundingBox.minZ() + i; ++ return this.boundingBox.minZ() + x; + default: +- return j; ++ return z; + } + } + } + +- protected void placeBlock(WorldGenLevel worldgenlevel, BlockState blockstate, int i, int j, int k, BoundingBox boundingbox) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = this.getWorldPos(i, j, k); ++ protected void placeBlock(WorldGenLevel level, IBlockData blockstate, int x, int y, int z, BoundingBox boundingbox) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y, z); + +- if (boundingbox.isInside(blockpos_mutableblockpos)) { +- if (this.canBeReplaced(worldgenlevel, i, j, k, boundingbox)) { ++ if (boundingbox.isInside(blockposition_mutableblockposition)) { ++ if (this.canBeReplaced(level, x, y, z, boundingbox)) { + if (this.mirror != Mirror.NONE) { + blockstate = blockstate.mirror(this.mirror); + } +@@ -189,57 +182,94 @@ + blockstate = blockstate.rotate(this.rotation); + } + +- worldgenlevel.setBlock(blockpos_mutableblockpos, blockstate, 2); +- FluidState fluidstate = worldgenlevel.getFluidState(blockpos_mutableblockpos); ++ level.setBlock(blockposition_mutableblockposition, blockstate, 2); ++ // CraftBukkit start - fluid handling is already done if we have a transformer generator access ++ if (level instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess) { ++ return; ++ } ++ // CraftBukkit end ++ FluidState fluid = level.getFluidState(blockposition_mutableblockposition); + +- if (!fluidstate.isEmpty()) { +- worldgenlevel.scheduleTick(blockpos_mutableblockpos, fluidstate.getType(), 0); ++ if (!fluid.isEmpty()) { ++ level.scheduleTick(blockposition_mutableblockposition, fluid.getType(), 0); + } + + if (StructurePiece.SHAPE_CHECK_BLOCKS.contains(blockstate.getBlock())) { +- worldgenlevel.getChunk(blockpos_mutableblockpos).markPosForPostprocessing(blockpos_mutableblockpos); ++ level.getChunk(blockposition_mutableblockposition).markPosForPostprocessing(blockposition_mutableblockposition); + } + + } + } + } + +- protected boolean canBeReplaced(LevelReader levelreader, int i, int j, int k, BoundingBox boundingbox) { ++ // CraftBukkit start ++ protected boolean placeCraftBlockEntity(ServerLevelAccessor worldAccess, BlockPos position, org.bukkit.craftbukkit.block.CraftBlockEntityState craftBlockEntityState, int i) { ++ if (worldAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ return transformerAccess.setCraftBlock(position, craftBlockEntityState, i); ++ } ++ boolean result = worldAccess.setBlock(position, craftBlockEntityState.getHandle(), i); ++ BlockEntity tileEntity = worldAccess.getBlockEntity(position); ++ if (tileEntity != null) { ++ tileEntity.load(craftBlockEntityState.getSnapshotNBT()); ++ } ++ return result; ++ } ++ ++ protected void placeCraftSpawner(ServerLevelAccessor worldAccess, BlockPos position, org.bukkit.entity.EntityType entityType, int i) { ++ // This method is used in structures that are generated by code and place spawners as they set the entity after the block was placed making it impossible for plugins to access that information ++ org.bukkit.craftbukkit.block.CraftCreatureSpawner spawner = (org.bukkit.craftbukkit.block.CraftCreatureSpawner) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(position, Blocks.SPAWNER.defaultBlockState(), null); ++ spawner.setSpawnedType(entityType); ++ placeCraftBlockEntity(worldAccess, position, spawner, i); ++ } ++ ++ protected void setCraftLootTable(ServerLevelAccessor worldAccess, BlockPos position, RandomSource randomSource, net.minecraft.resources.ResourceLocation loottableKey) { ++ // This method is used in structures that use data markers to a loot table to loot containers as otherwise plugins won't have access to that information. ++ net.minecraft.world.level.block.entity.BlockEntity tileEntity = worldAccess.getBlockEntity(position); ++ if (tileEntity instanceof net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity tileEntityLootable) { ++ tileEntityLootable.setLootTable(loottableKey, randomSource.nextLong()); ++ if (worldAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ transformerAccess.setCraftBlock(position, (org.bukkit.craftbukkit.block.CraftBlockState) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(position, tileEntity.getBlockState(), tileEntityLootable.saveWithFullMetadata()), 3); ++ } ++ } ++ } ++ // CraftBukkit end ++ ++ protected boolean canBeReplaced(LevelReader level, int x, int y, int z, BoundingBox box) { + return true; + } + +- protected BlockState getBlock(BlockGetter blockgetter, int i, int j, int k, BoundingBox boundingbox) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = this.getWorldPos(i, j, k); ++ protected IBlockData getBlock(BlockGetter level, int x, int y, int z, BoundingBox box) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y, z); + +- return !boundingbox.isInside(blockpos_mutableblockpos) ? Blocks.AIR.defaultBlockState() : blockgetter.getBlockState(blockpos_mutableblockpos); ++ return !box.isInside(blockposition_mutableblockposition) ? Blocks.AIR.defaultBlockState() : level.getBlockState(blockposition_mutableblockposition); + } + +- protected boolean isInterior(LevelReader levelreader, int i, int j, int k, BoundingBox boundingbox) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = this.getWorldPos(i, j + 1, k); ++ protected boolean isInterior(LevelReader level, int x, int y, int z, BoundingBox box) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y + 1, z); + +- return !boundingbox.isInside(blockpos_mutableblockpos) ? false : blockpos_mutableblockpos.getY() < levelreader.getHeight(Heightmap.Types.OCEAN_FLOOR_WG, blockpos_mutableblockpos.getX(), blockpos_mutableblockpos.getZ()); ++ return !box.isInside(blockposition_mutableblockposition) ? false : blockposition_mutableblockposition.getY() < level.getHeight(Heightmap.Types.OCEAN_FLOOR_WG, blockposition_mutableblockposition.getX(), blockposition_mutableblockposition.getZ()); + } + +- protected void generateAirBox(WorldGenLevel worldgenlevel, BoundingBox boundingbox, int i, int j, int k, int l, int i1, int j1) { +- for (int k1 = j; k1 <= i1; ++k1) { +- for (int l1 = i; l1 <= l; ++l1) { +- for (int i2 = k; i2 <= j1; ++i2) { +- this.placeBlock(worldgenlevel, Blocks.AIR.defaultBlockState(), l1, k1, i2, boundingbox); ++ protected void generateAirBox(WorldGenLevel level, BoundingBox box, int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { ++ for (int k1 = minY; k1 <= maxY; ++k1) { ++ for (int l1 = minX; l1 <= maxX; ++l1) { ++ for (int i2 = minZ; i2 <= maxZ; ++i2) { ++ this.placeBlock(level, Blocks.AIR.defaultBlockState(), l1, k1, i2, box); + } + } + } + + } + +- protected void generateBox(WorldGenLevel worldgenlevel, BoundingBox boundingbox, int i, int j, int k, int l, int i1, int j1, BlockState blockstate, BlockState blockstate1, boolean flag) { +- for (int k1 = j; k1 <= i1; ++k1) { +- for (int l1 = i; l1 <= l; ++l1) { +- for (int i2 = k; i2 <= j1; ++i2) { +- if (!flag || !this.getBlock(worldgenlevel, l1, k1, i2, boundingbox).isAir()) { +- if (k1 != j && k1 != i1 && l1 != i && l1 != l && i2 != k && i2 != j1) { +- this.placeBlock(worldgenlevel, blockstate1, l1, k1, i2, boundingbox); ++ protected void generateBox(WorldGenLevel level, BoundingBox box, int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, IBlockData boundaryBlockState, IBlockData insideBlockState, boolean existingOnly) { ++ for (int k1 = yMin; k1 <= yMax; ++k1) { ++ for (int l1 = xMin; l1 <= xMax; ++l1) { ++ for (int i2 = zMin; i2 <= zMax; ++i2) { ++ if (!existingOnly || !this.getBlock(level, l1, k1, i2, box).isAir()) { ++ if (k1 != yMin && k1 != yMax && l1 != xMin && l1 != xMax && i2 != zMin && i2 != zMax) { ++ this.placeBlock(level, insideBlockState, l1, k1, i2, box); + } else { +- this.placeBlock(worldgenlevel, blockstate, l1, k1, i2, boundingbox); ++ this.placeBlock(level, boundaryBlockState, l1, k1, i2, box); + } + } + } +@@ -248,17 +278,17 @@ + + } + +- protected void generateBox(WorldGenLevel worldgenlevel, BoundingBox boundingbox, BoundingBox boundingbox1, BlockState blockstate, BlockState blockstate1, boolean flag) { +- this.generateBox(worldgenlevel, boundingbox, boundingbox1.minX(), boundingbox1.minY(), boundingbox1.minZ(), boundingbox1.maxX(), boundingbox1.maxY(), boundingbox1.maxZ(), blockstate, blockstate1, flag); ++ protected void generateBox(WorldGenLevel level, BoundingBox boundingBox, BoundingBox box, IBlockData boundaryBlockState, IBlockData insideBlockState, boolean existingOnly) { ++ this.generateBox(level, boundingBox, box.minX(), box.minY(), box.minZ(), box.maxX(), box.maxY(), box.maxZ(), boundaryBlockState, insideBlockState, existingOnly); + } + +- protected void generateBox(WorldGenLevel worldgenlevel, BoundingBox boundingbox, int i, int j, int k, int l, int i1, int j1, boolean flag, RandomSource randomsource, StructurePiece.BlockSelector structurepiece_blockselector) { +- for (int k1 = j; k1 <= i1; ++k1) { +- for (int l1 = i; l1 <= l; ++l1) { +- for (int i2 = k; i2 <= j1; ++i2) { +- if (!flag || !this.getBlock(worldgenlevel, l1, k1, i2, boundingbox).isAir()) { +- structurepiece_blockselector.next(randomsource, l1, k1, i2, k1 == j || k1 == i1 || l1 == i || l1 == l || i2 == k || i2 == j1); +- this.placeBlock(worldgenlevel, structurepiece_blockselector.getNext(), l1, k1, i2, boundingbox); ++ protected void generateBox(WorldGenLevel level, BoundingBox box, int minX, int minY, int minZ, int maxX, int maxY, int maxZ, boolean alwaysReplace, RandomSource random, StructurePiece.BlockSelector blockSelector) { ++ for (int k1 = minY; k1 <= maxY; ++k1) { ++ for (int l1 = minX; l1 <= maxX; ++l1) { ++ for (int i2 = minZ; i2 <= maxZ; ++i2) { ++ if (!alwaysReplace || !this.getBlock(level, l1, k1, i2, box).isAir()) { ++ blockSelector.next(random, l1, k1, i2, k1 == minY || k1 == maxY || l1 == minX || l1 == maxX || i2 == minZ || i2 == maxZ); ++ this.placeBlock(level, blockSelector.getNext(), l1, k1, i2, box); + } + } + } +@@ -266,19 +296,19 @@ + + } + +- protected void generateBox(WorldGenLevel worldgenlevel, BoundingBox boundingbox, BoundingBox boundingbox1, boolean flag, RandomSource randomsource, StructurePiece.BlockSelector structurepiece_blockselector) { +- this.generateBox(worldgenlevel, boundingbox, boundingbox1.minX(), boundingbox1.minY(), boundingbox1.minZ(), boundingbox1.maxX(), boundingbox1.maxY(), boundingbox1.maxZ(), flag, randomsource, structurepiece_blockselector); ++ protected void generateBox(WorldGenLevel level, BoundingBox boundingBox, BoundingBox box, boolean alwaysReplace, RandomSource random, StructurePiece.BlockSelector blockSelector) { ++ this.generateBox(level, boundingBox, box.minX(), box.minY(), box.minZ(), box.maxX(), box.maxY(), box.maxZ(), alwaysReplace, random, blockSelector); + } + +- protected void generateMaybeBox(WorldGenLevel worldgenlevel, BoundingBox boundingbox, RandomSource randomsource, float f, int i, int j, int k, int l, int i1, int j1, BlockState blockstate, BlockState blockstate1, boolean flag, boolean flag1) { +- for (int k1 = j; k1 <= i1; ++k1) { +- for (int l1 = i; l1 <= l; ++l1) { +- for (int i2 = k; i2 <= j1; ++i2) { +- if (randomsource.nextFloat() <= f && (!flag || !this.getBlock(worldgenlevel, l1, k1, i2, boundingbox).isAir()) && (!flag1 || this.isInterior(worldgenlevel, l1, k1, i2, boundingbox))) { +- if (k1 != j && k1 != i1 && l1 != i && l1 != l && i2 != k && i2 != j1) { +- this.placeBlock(worldgenlevel, blockstate1, l1, k1, i2, boundingbox); ++ protected void generateMaybeBox(WorldGenLevel level, BoundingBox box, RandomSource random, float chance, int x1, int y1, int z1, int x2, int y2, int z2, IBlockData edgeState, IBlockData state, boolean requireNonAir, boolean requireSkylight) { ++ for (int k1 = y1; k1 <= y2; ++k1) { ++ for (int l1 = x1; l1 <= x2; ++l1) { ++ for (int i2 = z1; i2 <= z2; ++i2) { ++ if (random.nextFloat() <= chance && (!requireNonAir || !this.getBlock(level, l1, k1, i2, box).isAir()) && (!requireSkylight || this.isInterior(level, l1, k1, i2, box))) { ++ if (k1 != y1 && k1 != y2 && l1 != x1 && l1 != x2 && i2 != z1 && i2 != z2) { ++ this.placeBlock(level, state, l1, k1, i2, box); + } else { +- this.placeBlock(worldgenlevel, blockstate, l1, k1, i2, boundingbox); ++ this.placeBlock(level, edgeState, l1, k1, i2, box); + } + } + } +@@ -287,34 +317,34 @@ + + } + +- protected void maybeGenerateBlock(WorldGenLevel worldgenlevel, BoundingBox boundingbox, RandomSource randomsource, float f, int i, int j, int k, BlockState blockstate) { +- if (randomsource.nextFloat() < f) { +- this.placeBlock(worldgenlevel, blockstate, i, j, k, boundingbox); ++ protected void maybeGenerateBlock(WorldGenLevel level, BoundingBox box, RandomSource random, float chance, int x, int y, int z, IBlockData state) { ++ if (random.nextFloat() < chance) { ++ this.placeBlock(level, state, x, y, z, box); + } + + } + +- protected void generateUpperHalfSphere(WorldGenLevel worldgenlevel, BoundingBox boundingbox, int i, int j, int k, int l, int i1, int j1, BlockState blockstate, boolean flag) { +- float f = (float) (l - i + 1); +- float f1 = (float) (i1 - j + 1); +- float f2 = (float) (j1 - k + 1); +- float f3 = (float) i + f / 2.0F; +- float f4 = (float) k + f2 / 2.0F; ++ protected void generateUpperHalfSphere(WorldGenLevel level, BoundingBox box, int minX, int minY, int minZ, int maxX, int maxY, int maxZ, IBlockData state, boolean excludeAir) { ++ float f = (float) (maxX - minX + 1); ++ float f1 = (float) (maxY - minY + 1); ++ float f2 = (float) (maxZ - minZ + 1); ++ float f3 = (float) minX + f / 2.0F; ++ float f4 = (float) minZ + f2 / 2.0F; + +- for (int k1 = j; k1 <= i1; ++k1) { +- float f5 = (float) (k1 - j) / f1; ++ for (int k1 = minY; k1 <= maxY; ++k1) { ++ float f5 = (float) (k1 - minY) / f1; + +- for (int l1 = i; l1 <= l; ++l1) { ++ for (int l1 = minX; l1 <= maxX; ++l1) { + float f6 = ((float) l1 - f3) / (f * 0.5F); + +- for (int i2 = k; i2 <= j1; ++i2) { ++ for (int i2 = minZ; i2 <= maxZ; ++i2) { + float f7 = ((float) i2 - f4) / (f2 * 0.5F); + +- if (!flag || !this.getBlock(worldgenlevel, l1, k1, i2, boundingbox).isAir()) { ++ if (!excludeAir || !this.getBlock(level, l1, k1, i2, box).isAir()) { + float f8 = f6 * f6 + f5 * f5 + f7 * f7; + + if (f8 <= 1.05F) { +- this.placeBlock(worldgenlevel, blockstate, l1, k1, i2, boundingbox); ++ this.placeBlock(level, state, l1, k1, i2, box); + } + } + } +@@ -323,86 +353,94 @@ + + } + +- protected void fillColumnDown(WorldGenLevel worldgenlevel, BlockState blockstate, int i, int j, int k, BoundingBox boundingbox) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = this.getWorldPos(i, j, k); ++ protected void fillColumnDown(WorldGenLevel level, IBlockData state, int x, int y, int z, BoundingBox box) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y, z); + +- if (boundingbox.isInside(blockpos_mutableblockpos)) { +- while (this.isReplaceableByStructures(worldgenlevel.getBlockState(blockpos_mutableblockpos)) && blockpos_mutableblockpos.getY() > worldgenlevel.getMinBuildHeight() + 1) { +- worldgenlevel.setBlock(blockpos_mutableblockpos, blockstate, 2); +- blockpos_mutableblockpos.move(Direction.DOWN); ++ if (box.isInside(blockposition_mutableblockposition)) { ++ while (this.isReplaceableByStructures(level.getBlockState(blockposition_mutableblockposition)) && blockposition_mutableblockposition.getY() > level.getMinBuildHeight() + 1) { ++ level.setBlock(blockposition_mutableblockposition, state, 2); ++ blockposition_mutableblockposition.move(Direction.DOWN); + } + + } + } + +- protected boolean isReplaceableByStructures(BlockState blockstate) { +- return blockstate.isAir() || blockstate.liquid() || blockstate.is(Blocks.GLOW_LICHEN) || blockstate.is(Blocks.SEAGRASS) || blockstate.is(Blocks.TALL_SEAGRASS); ++ protected boolean isReplaceableByStructures(IBlockData state) { ++ return state.isAir() || state.liquid() || state.is(Blocks.GLOW_LICHEN) || state.is(Blocks.SEAGRASS) || state.is(Blocks.TALL_SEAGRASS); + } + +- protected boolean createChest(WorldGenLevel worldgenlevel, BoundingBox boundingbox, RandomSource randomsource, int i, int j, int k, ResourceLocation resourcelocation) { +- return this.createChest(worldgenlevel, boundingbox, randomsource, this.getWorldPos(i, j, k), resourcelocation, (BlockState) null); ++ protected boolean createChest(WorldGenLevel level, BoundingBox box, RandomSource random, int x, int y, int z, ResourceLocation lootTable) { ++ return this.createChest(level, box, random, this.getWorldPos(x, y, z), lootTable, (IBlockData) null); + } + +- public static BlockState reorient(BlockGetter blockgetter, BlockPos blockpos, BlockState blockstate) { +- Direction direction = null; ++ public static IBlockData reorient(BlockGetter level, BlockPos pos, IBlockData state) { ++ Direction enumdirection = null; + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction1 = (Direction) iterator.next(); +- BlockPos blockpos1 = blockpos.relative(direction1); +- BlockState blockstate1 = blockgetter.getBlockState(blockpos1); ++ Direction enumdirection1 = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection1); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + +- if (blockstate1.is(Blocks.CHEST)) { +- return blockstate; ++ if (iblockdata1.is(Blocks.CHEST)) { ++ return state; + } + +- if (blockstate1.isSolidRender(blockgetter, blockpos1)) { +- if (direction != null) { +- direction = null; ++ if (iblockdata1.isSolidRender(level, blockposition1)) { ++ if (enumdirection != null) { ++ enumdirection = null; + break; + } + +- direction = direction1; ++ enumdirection = enumdirection1; + } + } + +- if (direction != null) { +- return (BlockState) blockstate.setValue(HorizontalDirectionalBlock.FACING, direction.getOpposite()); ++ if (enumdirection != null) { ++ return (IBlockData) state.setValue(HorizontalDirectionalBlock.FACING, enumdirection.getOpposite()); + } else { +- Direction direction2 = (Direction) blockstate.getValue(HorizontalDirectionalBlock.FACING); +- BlockPos blockpos2 = blockpos.relative(direction2); ++ Direction enumdirection2 = (Direction) state.getValue(HorizontalDirectionalBlock.FACING); ++ BlockPos blockposition2 = pos.relative(enumdirection2); + +- if (blockgetter.getBlockState(blockpos2).isSolidRender(blockgetter, blockpos2)) { +- direction2 = direction2.getOpposite(); +- blockpos2 = blockpos.relative(direction2); ++ if (level.getBlockState(blockposition2).isSolidRender(level, blockposition2)) { ++ enumdirection2 = enumdirection2.getOpposite(); ++ blockposition2 = pos.relative(enumdirection2); + } + +- if (blockgetter.getBlockState(blockpos2).isSolidRender(blockgetter, blockpos2)) { +- direction2 = direction2.getClockWise(); +- blockpos2 = blockpos.relative(direction2); ++ if (level.getBlockState(blockposition2).isSolidRender(level, blockposition2)) { ++ enumdirection2 = enumdirection2.getClockWise(); ++ blockposition2 = pos.relative(enumdirection2); + } + +- if (blockgetter.getBlockState(blockpos2).isSolidRender(blockgetter, blockpos2)) { +- direction2 = direction2.getOpposite(); +- blockpos.relative(direction2); ++ if (level.getBlockState(blockposition2).isSolidRender(level, blockposition2)) { ++ enumdirection2 = enumdirection2.getOpposite(); ++ pos.relative(enumdirection2); + } + +- return (BlockState) blockstate.setValue(HorizontalDirectionalBlock.FACING, direction2); ++ return (IBlockData) state.setValue(HorizontalDirectionalBlock.FACING, enumdirection2); + } + } + +- protected boolean createChest(ServerLevelAccessor serverlevelaccessor, BoundingBox boundingbox, RandomSource randomsource, BlockPos blockpos, ResourceLocation resourcelocation, @Nullable BlockState blockstate) { +- if (boundingbox.isInside(blockpos) && !serverlevelaccessor.getBlockState(blockpos).is(Blocks.CHEST)) { +- if (blockstate == null) { +- blockstate = reorient(serverlevelaccessor, blockpos, Blocks.CHEST.defaultBlockState()); ++ protected boolean createChest(ServerLevelAccessor level, BoundingBox box, RandomSource random, BlockPos pos, ResourceLocation lootTable, @Nullable IBlockData state) { ++ if (box.isInside(pos) && !level.getBlockState(pos).is(Blocks.CHEST)) { ++ if (state == null) { ++ state = reorient(level, pos, Blocks.CHEST.defaultBlockState()); + } + +- serverlevelaccessor.setBlock(blockpos, blockstate, 2); +- BlockEntity blockentity = serverlevelaccessor.getBlockEntity(blockpos); ++ // CraftBukkit start ++ /* ++ worldaccess.setBlock(blockposition, iblockdata, 2); ++ TileEntity tileentity = worldaccess.getBlockEntity(blockposition); + +- if (blockentity instanceof ChestBlockEntity) { +- ((ChestBlockEntity) blockentity).setLootTable(resourcelocation, randomsource.nextLong()); ++ if (tileentity instanceof TileEntityChest) { ++ ((TileEntityChest) tileentity).setLootTable(minecraftkey, randomsource.nextLong()); + } ++ */ ++ org.bukkit.craftbukkit.block.CraftChest chestState = (org.bukkit.craftbukkit.block.CraftChest) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(pos, state, null); ++ chestState.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(lootTable))); ++ chestState.setSeed(random.nextLong()); ++ placeCraftBlockEntity(level, pos, chestState, 2); ++ // CraftBukkit end + + return true; + } else { +@@ -410,29 +448,48 @@ + } + } + +- protected boolean createDispenser(WorldGenLevel worldgenlevel, BoundingBox boundingbox, RandomSource randomsource, int i, int j, int k, Direction direction, ResourceLocation resourcelocation) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = this.getWorldPos(i, j, k); ++ protected boolean createDispenser(WorldGenLevel level, BoundingBox box, RandomSource random, int x, int y, int z, Direction facing, ResourceLocation lootTable) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y, z); + +- if (boundingbox.isInside(blockpos_mutableblockpos) && !worldgenlevel.getBlockState(blockpos_mutableblockpos).is(Blocks.DISPENSER)) { +- this.placeBlock(worldgenlevel, (BlockState) Blocks.DISPENSER.defaultBlockState().setValue(DispenserBlock.FACING, direction), i, j, k, boundingbox); +- BlockEntity blockentity = worldgenlevel.getBlockEntity(blockpos_mutableblockpos); ++ if (box.isInside(blockposition_mutableblockposition) && !level.getBlockState(blockposition_mutableblockposition).is(Blocks.DISPENSER)) { ++ // CraftBukkit start ++ /* ++ this.placeBlock(generatoraccessseed, (IBlockData) Blocks.DISPENSER.defaultBlockState().setValue(BlockDispenser.FACING, enumdirection), i, j, k, structureboundingbox); ++ TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); + +- if (blockentity instanceof DispenserBlockEntity) { +- ((DispenserBlockEntity) blockentity).setLootTable(resourcelocation, randomsource.nextLong()); ++ if (tileentity instanceof TileEntityDispenser) { ++ ((TileEntityDispenser) tileentity).setLootTable(minecraftkey, randomsource.nextLong()); + } ++ */ ++ if (!this.canBeReplaced(level, x, y, z, box)) { ++ return true; ++ } ++ IBlockData iblockdata = Blocks.DISPENSER.defaultBlockState().setValue(DispenserBlock.FACING, facing); ++ if (this.mirror != Mirror.NONE) { ++ iblockdata = iblockdata.mirror(this.mirror); ++ } ++ if (this.rotation != Rotation.NONE) { ++ iblockdata = iblockdata.rotate(this.rotation); ++ } + ++ org.bukkit.craftbukkit.block.CraftDispenser dispenserState = (org.bukkit.craftbukkit.block.CraftDispenser) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockposition_mutableblockposition, iblockdata, null); ++ dispenserState.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(lootTable))); ++ dispenserState.setSeed(random.nextLong()); ++ placeCraftBlockEntity(level, blockposition_mutableblockposition, dispenserState, 2); ++ // CraftBukkit end ++ + return true; + } else { + return false; + } + } + +- public void move(int i, int j, int k) { +- this.boundingBox.move(i, j, k); ++ public void move(int x, int y, int z) { ++ this.boundingBox.move(x, y, z); + } + +- public static BoundingBox createBoundingBox(Stream stream) { +- Stream stream1 = stream.map(StructurePiece::getBoundingBox); ++ public static BoundingBox createBoundingBox(Stream pieces) { ++ Stream stream1 = pieces.map(StructurePiece::getBoundingBox); // CraftBukkit - decompile error + + Objects.requireNonNull(stream1); + return (BoundingBox) BoundingBox.encapsulatingBoxes(stream1::iterator).orElseThrow(() -> { +@@ -441,8 +498,8 @@ + } + + @Nullable +- public static StructurePiece findCollisionPiece(List list, BoundingBox boundingbox) { +- Iterator iterator = list.iterator(); ++ public static StructurePiece findCollisionPiece(List pieces, BoundingBox boundingBox) { ++ Iterator iterator = pieces.iterator(); + + StructurePiece structurepiece; + +@@ -452,7 +509,7 @@ + } + + structurepiece = (StructurePiece) iterator.next(); +- } while (!structurepiece.getBoundingBox().intersects(boundingbox)); ++ } while (!structurepiece.getBoundingBox().intersects(boundingBox)); + + return structurepiece; + } +@@ -462,13 +519,13 @@ + return this.orientation; + } + +- public void setOrientation(@Nullable Direction direction) { +- this.orientation = direction; +- if (direction == null) { ++ public void setOrientation(@Nullable Direction orientation) { ++ this.orientation = orientation; ++ if (orientation == null) { + this.rotation = Rotation.NONE; + this.mirror = Mirror.NONE; + } else { +- switch (direction) { ++ switch (orientation) { + case SOUTH: + this.mirror = Mirror.LEFT_RIGHT; + this.rotation = Rotation.NONE; +@@ -503,7 +560,7 @@ + + public abstract static class BlockSelector { + +- protected BlockState next; ++ protected IBlockData next; + + public BlockSelector() { + this.next = Blocks.AIR.defaultBlockState(); +@@ -511,7 +568,7 @@ + + public abstract void next(RandomSource random, int x, int y, int z, boolean wall); + +- public BlockState getNext() { ++ public IBlockData getNext() { + return this.next; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/StructureStart.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/StructureStart.java.patch new file mode 100644 index 0000000000..d446fa97b2 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/StructureStart.java.patch @@ -0,0 +1,145 @@ +--- a/net/minecraft/world/level/levelgen/structure/StructureStart.java ++++ b/net/minecraft/world/level/levelgen/structure/StructureStart.java +@@ -31,40 +31,41 @@ + private int references; + @Nullable + private volatile BoundingBox cachedBoundingBox; ++ public org.bukkit.event.world.AsyncStructureGenerateEvent.Cause generationEventCause = org.bukkit.event.world.AsyncStructureGenerateEvent.Cause.WORLD_GENERATION; // CraftBukkit + +- public StructureStart(Structure structure, ChunkPos chunkpos, int i, PiecesContainer piecescontainer) { ++ public StructureStart(Structure structure, ChunkPos chunkPos, int references, PiecesContainer pieceContainer) { + this.structure = structure; +- this.chunkPos = chunkpos; +- this.references = i; +- this.pieceContainer = piecescontainer; ++ this.chunkPos = chunkPos; ++ this.references = references; ++ this.pieceContainer = pieceContainer; + } + + @Nullable +- public static StructureStart loadStaticStart(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag, long i) { +- String s = compoundtag.getString("id"); ++ public static StructureStart loadStaticStart(StructurePieceSerializationContext context, CompoundTag tag, long seed) { ++ String s = tag.getString("id"); + + if ("INVALID".equals(s)) { + return StructureStart.INVALID_START; + } else { +- Registry registry = structurepieceserializationcontext.registryAccess().registryOrThrow(Registries.STRUCTURE); +- Structure structure = (Structure) registry.get(new ResourceLocation(s)); ++ Registry iregistry = context.registryAccess().registryOrThrow(Registries.STRUCTURE); ++ Structure structure = (Structure) iregistry.get(new ResourceLocation(s)); + + if (structure == null) { + StructureStart.LOGGER.error("Unknown stucture id: {}", s); + return null; + } else { +- ChunkPos chunkpos = new ChunkPos(compoundtag.getInt("ChunkX"), compoundtag.getInt("ChunkZ")); +- int j = compoundtag.getInt("references"); +- ListTag listtag = compoundtag.getList("Children", 10); ++ ChunkPos chunkcoordintpair = new ChunkPos(tag.getInt("ChunkX"), tag.getInt("ChunkZ")); ++ int j = tag.getInt("references"); ++ ListTag nbttaglist = tag.getList("Children", 10); + + try { +- PiecesContainer piecescontainer = PiecesContainer.load(listtag, structurepieceserializationcontext); ++ PiecesContainer piecescontainer = PiecesContainer.load(nbttaglist, context); + + if (structure instanceof OceanMonumentStructure) { +- piecescontainer = OceanMonumentStructure.regeneratePiecesAfterLoad(chunkpos, i, piecescontainer); ++ piecescontainer = OceanMonumentStructure.regeneratePiecesAfterLoad(chunkcoordintpair, seed, piecescontainer); + } + +- return new StructureStart(structure, chunkpos, j, piecescontainer); ++ return new StructureStart(structure, chunkcoordintpair, j, piecescontainer); + } catch (Exception exception) { + StructureStart.LOGGER.error("Failed Start with id {}", s, exception); + return null; +@@ -74,50 +75,64 @@ + } + + public BoundingBox getBoundingBox() { +- BoundingBox boundingbox = this.cachedBoundingBox; ++ BoundingBox structureboundingbox = this.cachedBoundingBox; + +- if (boundingbox == null) { +- boundingbox = this.structure.adjustBoundingBox(this.pieceContainer.calculateBoundingBox()); +- this.cachedBoundingBox = boundingbox; ++ if (structureboundingbox == null) { ++ structureboundingbox = this.structure.adjustBoundingBox(this.pieceContainer.calculateBoundingBox()); ++ this.cachedBoundingBox = structureboundingbox; + } + +- return boundingbox; ++ return structureboundingbox; + } + +- public void placeInChunk(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos) { ++ public void placeInChunk(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos) { + List list = this.pieceContainer.pieces(); + + if (!list.isEmpty()) { +- BoundingBox boundingbox1 = ((StructurePiece) list.get(0)).boundingBox; +- BlockPos blockpos = boundingbox1.getCenter(); +- BlockPos blockpos1 = new BlockPos(blockpos.getX(), boundingbox1.minY(), blockpos.getZ()); ++ BoundingBox structureboundingbox1 = ((StructurePiece) list.get(0)).boundingBox; ++ BlockPos blockposition = structureboundingbox1.getCenter(); ++ BlockPos blockposition1 = new BlockPos(blockposition.getX(), structureboundingbox1.minY(), blockposition.getZ()); ++ // CraftBukkit start ++ /* + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { + StructurePiece structurepiece = (StructurePiece) iterator.next(); + +- if (structurepiece.getBoundingBox().intersects(boundingbox)) { +- structurepiece.postProcess(worldgenlevel, structuremanager, chunkgenerator, randomsource, boundingbox, chunkpos, blockpos1); ++ if (structurepiece.getBoundingBox().intersects(structureboundingbox)) { ++ structurepiece.postProcess(generatoraccessseed, structuremanager, chunkgenerator, randomsource, structureboundingbox, chunkcoordintpair, blockposition1); + } + } ++ */ ++ List pieces = list.stream().filter(piece -> piece.getBoundingBox().intersects(box)).toList(); ++ if (!pieces.isEmpty()) { ++ org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess = new org.bukkit.craftbukkit.util.TransformerGeneratorAccess(); ++ transformerAccess.setHandle(level); ++ transformerAccess.setStructureTransformer(new org.bukkit.craftbukkit.util.CraftStructureTransformer(generationEventCause, level, structureManager, structure, box, chunkPos)); ++ for (StructurePiece piece : pieces) { ++ piece.postProcess(transformerAccess, structureManager, generator, random, box, chunkPos, blockposition1); ++ } ++ transformerAccess.getStructureTransformer().discard(); ++ } ++ // CraftBukkit end + +- this.structure.afterPlace(worldgenlevel, structuremanager, chunkgenerator, randomsource, boundingbox, chunkpos, this.pieceContainer); ++ this.structure.afterPlace(level, structureManager, generator, random, box, chunkPos, this.pieceContainer); + } + } + +- public CompoundTag createTag(StructurePieceSerializationContext structurepieceserializationcontext, ChunkPos chunkpos) { +- CompoundTag compoundtag = new CompoundTag(); ++ public CompoundTag createTag(StructurePieceSerializationContext context, ChunkPos chunkPos) { ++ CompoundTag nbttagcompound = new CompoundTag(); + + if (this.isValid()) { +- compoundtag.putString("id", structurepieceserializationcontext.registryAccess().registryOrThrow(Registries.STRUCTURE).getKey(this.structure).toString()); +- compoundtag.putInt("ChunkX", chunkpos.x); +- compoundtag.putInt("ChunkZ", chunkpos.z); +- compoundtag.putInt("references", this.references); +- compoundtag.put("Children", this.pieceContainer.save(structurepieceserializationcontext)); +- return compoundtag; ++ nbttagcompound.putString("id", context.registryAccess().registryOrThrow(Registries.STRUCTURE).getKey(this.structure).toString()); ++ nbttagcompound.putInt("ChunkX", chunkPos.x); ++ nbttagcompound.putInt("ChunkZ", chunkPos.z); ++ nbttagcompound.putInt("references", this.references); ++ nbttagcompound.put("Children", this.pieceContainer.save(context)); ++ return nbttagcompound; + } else { +- compoundtag.putString("id", "INVALID"); +- return compoundtag; ++ nbttagcompound.putString("id", "INVALID"); ++ return nbttagcompound; + } + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java.patch new file mode 100644 index 0000000000..e9625407a6 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java.patch @@ -0,0 +1,85 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java +@@ -28,15 +28,14 @@ + + public static final Codec CODEC = simpleCodec(DesertPyramidStructure::new); + +- public DesertPyramidStructure(Structure.StructureSettings structure_structuresettings) { +- super(DesertPyramidPiece::new, 21, 21, structure_structuresettings); ++ public DesertPyramidStructure(Structure.c settings) { ++ super(DesertPyramidPiece::new, 21, 21, settings); + } + + @Override +- @Override +- public void afterPlace(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, PiecesContainer piecescontainer) { ++ public void afterPlace(WorldGenLevel level, StructureManager structureManager, ChunkGenerator chunkGenerator, RandomSource random, BoundingBox boundingBox, ChunkPos chunkPos, PiecesContainer pieces) { + Set set = SortedArraySet.create(Vec3i::compareTo); +- Iterator iterator = piecescontainer.pieces().iterator(); ++ Iterator iterator = pieces.pieces().iterator(); + + while (iterator.hasNext()) { + StructurePiece structurepiece = (StructurePiece) iterator.next(); +@@ -45,42 +44,50 @@ + DesertPyramidPiece desertpyramidpiece = (DesertPyramidPiece) structurepiece; + + set.addAll(desertpyramidpiece.getPotentialSuspiciousSandWorldPositions()); +- placeSuspiciousSand(boundingbox, worldgenlevel, desertpyramidpiece.getRandomCollapsedRoofPos()); ++ placeSuspiciousSand(boundingBox, level, desertpyramidpiece.getRandomCollapsedRoofPos()); + } + } + + ObjectArrayList objectarraylist = new ObjectArrayList(set.stream().toList()); +- RandomSource randomsource1 = RandomSource.create(worldgenlevel.getSeed()).forkPositional().at(piecescontainer.calculateBoundingBox().getCenter()); ++ RandomSource randomsource1 = RandomSource.create(level.getSeed()).forkPositional().at(pieces.calculateBoundingBox().getCenter()); + + Util.shuffle(objectarraylist, randomsource1); + int i = Math.min(set.size(), randomsource1.nextInt(5, 8)); + ObjectListIterator objectlistiterator = objectarraylist.iterator(); + + while (objectlistiterator.hasNext()) { +- BlockPos blockpos = (BlockPos) objectlistiterator.next(); ++ BlockPos blockposition = (BlockPos) objectlistiterator.next(); + + if (i > 0) { + --i; +- placeSuspiciousSand(boundingbox, worldgenlevel, blockpos); +- } else if (boundingbox.isInside(blockpos)) { +- worldgenlevel.setBlock(blockpos, Blocks.SAND.defaultBlockState(), 2); ++ placeSuspiciousSand(boundingBox, level, blockposition); ++ } else if (boundingBox.isInside(blockposition)) { ++ level.setBlock(blockposition, Blocks.SAND.defaultBlockState(), 2); + } + } + + } + +- private static void placeSuspiciousSand(BoundingBox boundingbox, WorldGenLevel worldgenlevel, BlockPos blockpos) { +- if (boundingbox.isInside(blockpos)) { +- worldgenlevel.setBlock(blockpos, Blocks.SUSPICIOUS_SAND.defaultBlockState(), 2); +- worldgenlevel.getBlockEntity(blockpos, BlockEntityType.BRUSHABLE_BLOCK).ifPresent((brushableblockentity) -> { +- brushableblockentity.setLootTable(BuiltInLootTables.DESERT_PYRAMID_ARCHAEOLOGY, blockpos.asLong()); ++ private static void placeSuspiciousSand(BoundingBox boundingBox, WorldGenLevel worldGenLevel, BlockPos pos) { ++ if (boundingBox.isInside(pos)) { ++ // CraftBukkit start ++ if (worldGenLevel instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ org.bukkit.craftbukkit.block.CraftBrushableBlock brushableState = (org.bukkit.craftbukkit.block.CraftBrushableBlock) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(pos, Blocks.SUSPICIOUS_SAND.defaultBlockState(), null); ++ brushableState.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(BuiltInLootTables.DESERT_PYRAMID_ARCHAEOLOGY))); ++ brushableState.setSeed(pos.asLong()); ++ transformerAccess.setCraftBlock(pos, brushableState, 2); ++ return; ++ } ++ // CraftBukkit end ++ worldGenLevel.setBlock(pos, Blocks.SUSPICIOUS_SAND.defaultBlockState(), 2); ++ worldGenLevel.getBlockEntity(pos, BlockEntityType.BRUSHABLE_BLOCK).ifPresent((brushableblockentity) -> { ++ brushableblockentity.setLootTable(BuiltInLootTables.DESERT_PYRAMID_ARCHAEOLOGY, pos.asLong()); + }); + } + + } + + @Override +- @Override + public StructureType type() { + return StructureType.DESERT_PYRAMID; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java.patch new file mode 100644 index 0000000000..2bf66e8c80 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java.patch @@ -0,0 +1,389 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java +@@ -33,30 +33,28 @@ + private static final int MAX_GEN_DEPTH = 8; + static final EndCityPieces.SectionGenerator HOUSE_TOWER_GENERATOR = new EndCityPieces.SectionGenerator() { + @Override +- @Override + public void init() {} + + @Override +- @Override +- public boolean generate(StructureTemplateManager structuretemplatemanager, int i, EndCityPieces.EndCityPiece endcitypieces_endcitypiece, BlockPos blockpos, List list, RandomSource randomsource) { +- if (i > 8) { ++ public boolean generate(StructureTemplateManager structureTemplateManager, int counter, EndCityPieces.EndCityPiece piece, BlockPos startPos, List pieces, RandomSource random) { ++ if (counter > 8) { + return false; + } else { +- Rotation rotation = endcitypieces_endcitypiece.placeSettings().getRotation(); +- EndCityPieces.EndCityPiece endcitypieces_endcitypiece1 = EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece, blockpos, "base_floor", rotation, true)); +- int j = randomsource.nextInt(3); ++ Rotation enumblockrotation = piece.placeSettings().getRotation(); ++ EndCityPieces.EndCityPiece endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, piece, startPos, "base_floor", enumblockrotation, true)); ++ int j = random.nextInt(3); + + if (j == 0) { +- EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece1, new BlockPos(-1, 4, -1), "base_roof", rotation, true)); ++ EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(-1, 4, -1), "base_roof", enumblockrotation, true)); + } else if (j == 1) { +- endcitypieces_endcitypiece1 = EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece1, new BlockPos(-1, 0, -1), "second_floor_2", rotation, false)); +- endcitypieces_endcitypiece1 = EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece1, new BlockPos(-1, 8, -1), "second_roof", rotation, false)); +- EndCityPieces.recursiveChildren(structuretemplatemanager, EndCityPieces.TOWER_GENERATOR, i + 1, endcitypieces_endcitypiece1, (BlockPos) null, list, randomsource); ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(-1, 0, -1), "second_floor_2", enumblockrotation, false)); ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(-1, 8, -1), "second_roof", enumblockrotation, false)); ++ EndCityPieces.recursiveChildren(structureTemplateManager, EndCityPieces.TOWER_GENERATOR, counter + 1, endcitypieces_a1, (BlockPos) null, pieces, random); + } else if (j == 2) { +- endcitypieces_endcitypiece1 = EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece1, new BlockPos(-1, 0, -1), "second_floor_2", rotation, false)); +- endcitypieces_endcitypiece1 = EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece1, new BlockPos(-1, 4, -1), "third_floor_2", rotation, false)); +- endcitypieces_endcitypiece1 = EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece1, new BlockPos(-1, 8, -1), "third_roof", rotation, true)); +- EndCityPieces.recursiveChildren(structuretemplatemanager, EndCityPieces.TOWER_GENERATOR, i + 1, endcitypieces_endcitypiece1, (BlockPos) null, list, randomsource); ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(-1, 0, -1), "second_floor_2", enumblockrotation, false)); ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(-1, 4, -1), "third_floor_2", enumblockrotation, false)); ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(-1, 8, -1), "third_roof", enumblockrotation, true)); ++ EndCityPieces.recursiveChildren(structureTemplateManager, EndCityPieces.TOWER_GENERATOR, counter + 1, endcitypieces_a1, (BlockPos) null, pieces, random); + } + + return true; +@@ -66,46 +64,44 @@ + static final List> TOWER_BRIDGES = Lists.newArrayList(new Tuple[]{new Tuple<>(Rotation.NONE, new BlockPos(1, -1, 0)), new Tuple<>(Rotation.CLOCKWISE_90, new BlockPos(6, -1, 1)), new Tuple<>(Rotation.COUNTERCLOCKWISE_90, new BlockPos(0, -1, 5)), new Tuple<>(Rotation.CLOCKWISE_180, new BlockPos(5, -1, 6))}); + static final EndCityPieces.SectionGenerator TOWER_GENERATOR = new EndCityPieces.SectionGenerator() { + @Override +- @Override + public void init() {} + + @Override +- @Override +- public boolean generate(StructureTemplateManager structuretemplatemanager, int i, EndCityPieces.EndCityPiece endcitypieces_endcitypiece, BlockPos blockpos, List list, RandomSource randomsource) { +- Rotation rotation = endcitypieces_endcitypiece.placeSettings().getRotation(); +- EndCityPieces.EndCityPiece endcitypieces_endcitypiece1 = EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece, new BlockPos(3 + randomsource.nextInt(2), -3, 3 + randomsource.nextInt(2)), "tower_base", rotation, true)); ++ public boolean generate(StructureTemplateManager structureTemplateManager, int counter, EndCityPieces.EndCityPiece piece, BlockPos startPos, List pieces, RandomSource random) { ++ Rotation enumblockrotation = piece.placeSettings().getRotation(); ++ EndCityPieces.EndCityPiece endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, piece, new BlockPos(3 + random.nextInt(2), -3, 3 + random.nextInt(2)), "tower_base", enumblockrotation, true)); + +- endcitypieces_endcitypiece1 = EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece1, new BlockPos(0, 7, 0), "tower_piece", rotation, true)); +- EndCityPieces.EndCityPiece endcitypieces_endcitypiece2 = randomsource.nextInt(3) == 0 ? endcitypieces_endcitypiece1 : null; +- int j = 1 + randomsource.nextInt(3); ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(0, 7, 0), "tower_piece", enumblockrotation, true)); ++ EndCityPieces.EndCityPiece endcitypieces_a2 = random.nextInt(3) == 0 ? endcitypieces_a1 : null; ++ int j = 1 + random.nextInt(3); + + for (int k = 0; k < j; ++k) { +- endcitypieces_endcitypiece1 = EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece1, new BlockPos(0, 4, 0), "tower_piece", rotation, true)); +- if (k < j - 1 && randomsource.nextBoolean()) { +- endcitypieces_endcitypiece2 = endcitypieces_endcitypiece1; ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(0, 4, 0), "tower_piece", enumblockrotation, true)); ++ if (k < j - 1 && random.nextBoolean()) { ++ endcitypieces_a2 = endcitypieces_a1; + } + } + +- if (endcitypieces_endcitypiece2 != null) { ++ if (endcitypieces_a2 != null) { + Iterator iterator = EndCityPieces.TOWER_BRIDGES.iterator(); + + while (iterator.hasNext()) { + Tuple tuple = (Tuple) iterator.next(); + +- if (randomsource.nextBoolean()) { +- EndCityPieces.EndCityPiece endcitypieces_endcitypiece3 = EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece2, (BlockPos) tuple.getB(), "bridge_end", rotation.getRotated((Rotation) tuple.getA()), true)); ++ if (random.nextBoolean()) { ++ EndCityPieces.EndCityPiece endcitypieces_a3 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a2, (BlockPos) tuple.getB(), "bridge_end", enumblockrotation.getRotated((Rotation) tuple.getA()), true)); + +- EndCityPieces.recursiveChildren(structuretemplatemanager, EndCityPieces.TOWER_BRIDGE_GENERATOR, i + 1, endcitypieces_endcitypiece3, (BlockPos) null, list, randomsource); ++ EndCityPieces.recursiveChildren(structureTemplateManager, EndCityPieces.TOWER_BRIDGE_GENERATOR, counter + 1, endcitypieces_a3, (BlockPos) null, pieces, random); + } + } + +- EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece1, new BlockPos(-1, 4, -1), "tower_top", rotation, true)); ++ EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(-1, 4, -1), "tower_top", enumblockrotation, true)); + } else { +- if (i != 7) { +- return EndCityPieces.recursiveChildren(structuretemplatemanager, EndCityPieces.FAT_TOWER_GENERATOR, i + 1, endcitypieces_endcitypiece1, (BlockPos) null, list, randomsource); ++ if (counter != 7) { ++ return EndCityPieces.recursiveChildren(structureTemplateManager, EndCityPieces.FAT_TOWER_GENERATOR, counter + 1, endcitypieces_a1, (BlockPos) null, pieces, random); + } + +- EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece1, new BlockPos(-1, 4, -1), "tower_top", rotation, true)); ++ EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(-1, 4, -1), "tower_top", enumblockrotation, true)); + } + + return true; +@@ -115,135 +111,131 @@ + public boolean shipCreated; + + @Override +- @Override + public void init() { + this.shipCreated = false; + } + + @Override +- @Override +- public boolean generate(StructureTemplateManager structuretemplatemanager, int i, EndCityPieces.EndCityPiece endcitypieces_endcitypiece, BlockPos blockpos, List list, RandomSource randomsource) { +- Rotation rotation = endcitypieces_endcitypiece.placeSettings().getRotation(); +- int j = randomsource.nextInt(4) + 1; +- EndCityPieces.EndCityPiece endcitypieces_endcitypiece1 = EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece, new BlockPos(0, 0, -4), "bridge_piece", rotation, true)); ++ public boolean generate(StructureTemplateManager structureTemplateManager, int counter, EndCityPieces.EndCityPiece piece, BlockPos startPos, List pieces, RandomSource random) { ++ Rotation enumblockrotation = piece.placeSettings().getRotation(); ++ int j = random.nextInt(4) + 1; ++ EndCityPieces.EndCityPiece endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, piece, new BlockPos(0, 0, -4), "bridge_piece", enumblockrotation, true)); + +- endcitypieces_endcitypiece1.setGenDepth(-1); ++ endcitypieces_a1.setGenDepth(-1); + byte b0 = 0; + + for (int k = 0; k < j; ++k) { +- if (randomsource.nextBoolean()) { +- endcitypieces_endcitypiece1 = EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece1, new BlockPos(0, b0, -4), "bridge_piece", rotation, true)); ++ if (random.nextBoolean()) { ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(0, b0, -4), "bridge_piece", enumblockrotation, true)); + b0 = 0; + } else { +- if (randomsource.nextBoolean()) { +- endcitypieces_endcitypiece1 = EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece1, new BlockPos(0, b0, -4), "bridge_steep_stairs", rotation, true)); ++ if (random.nextBoolean()) { ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(0, b0, -4), "bridge_steep_stairs", enumblockrotation, true)); + } else { +- endcitypieces_endcitypiece1 = EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece1, new BlockPos(0, b0, -8), "bridge_gentle_stairs", rotation, true)); ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(0, b0, -8), "bridge_gentle_stairs", enumblockrotation, true)); + } + + b0 = 4; + } + } + +- if (!this.shipCreated && randomsource.nextInt(10 - i) == 0) { +- EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece1, new BlockPos(-8 + randomsource.nextInt(8), b0, -70 + randomsource.nextInt(10)), "ship", rotation, true)); ++ if (!this.shipCreated && random.nextInt(10 - counter) == 0) { ++ EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(-8 + random.nextInt(8), b0, -70 + random.nextInt(10)), "ship", enumblockrotation, true)); + this.shipCreated = true; +- } else if (!EndCityPieces.recursiveChildren(structuretemplatemanager, EndCityPieces.HOUSE_TOWER_GENERATOR, i + 1, endcitypieces_endcitypiece1, new BlockPos(-3, b0 + 1, -11), list, randomsource)) { ++ } else if (!EndCityPieces.recursiveChildren(structureTemplateManager, EndCityPieces.HOUSE_TOWER_GENERATOR, counter + 1, endcitypieces_a1, new BlockPos(-3, b0 + 1, -11), pieces, random)) { + return false; + } + +- endcitypieces_endcitypiece1 = EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece1, new BlockPos(4, b0, 0), "bridge_end", rotation.getRotated(Rotation.CLOCKWISE_180), true)); +- endcitypieces_endcitypiece1.setGenDepth(-1); ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(4, b0, 0), "bridge_end", enumblockrotation.getRotated(Rotation.CLOCKWISE_180), true)); ++ endcitypieces_a1.setGenDepth(-1); + return true; + } + }; + static final List> FAT_TOWER_BRIDGES = Lists.newArrayList(new Tuple[]{new Tuple<>(Rotation.NONE, new BlockPos(4, -1, 0)), new Tuple<>(Rotation.CLOCKWISE_90, new BlockPos(12, -1, 4)), new Tuple<>(Rotation.COUNTERCLOCKWISE_90, new BlockPos(0, -1, 8)), new Tuple<>(Rotation.CLOCKWISE_180, new BlockPos(8, -1, 12))}); + static final EndCityPieces.SectionGenerator FAT_TOWER_GENERATOR = new EndCityPieces.SectionGenerator() { + @Override +- @Override + public void init() {} + + @Override +- @Override +- public boolean generate(StructureTemplateManager structuretemplatemanager, int i, EndCityPieces.EndCityPiece endcitypieces_endcitypiece, BlockPos blockpos, List list, RandomSource randomsource) { +- Rotation rotation = endcitypieces_endcitypiece.placeSettings().getRotation(); +- EndCityPieces.EndCityPiece endcitypieces_endcitypiece1 = EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece, new BlockPos(-3, 4, -3), "fat_tower_base", rotation, true)); ++ public boolean generate(StructureTemplateManager structureTemplateManager, int counter, EndCityPieces.EndCityPiece piece, BlockPos startPos, List pieces, RandomSource random) { ++ Rotation enumblockrotation = piece.placeSettings().getRotation(); ++ EndCityPieces.EndCityPiece endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, piece, new BlockPos(-3, 4, -3), "fat_tower_base", enumblockrotation, true)); + +- endcitypieces_endcitypiece1 = EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece1, new BlockPos(0, 4, 0), "fat_tower_middle", rotation, true)); ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(0, 4, 0), "fat_tower_middle", enumblockrotation, true)); + +- for (int j = 0; j < 2 && randomsource.nextInt(3) != 0; ++j) { +- endcitypieces_endcitypiece1 = EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece1, new BlockPos(0, 8, 0), "fat_tower_middle", rotation, true)); ++ for (int j = 0; j < 2 && random.nextInt(3) != 0; ++j) { ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(0, 8, 0), "fat_tower_middle", enumblockrotation, true)); + Iterator iterator = EndCityPieces.FAT_TOWER_BRIDGES.iterator(); + + while (iterator.hasNext()) { + Tuple tuple = (Tuple) iterator.next(); + +- if (randomsource.nextBoolean()) { +- EndCityPieces.EndCityPiece endcitypieces_endcitypiece2 = EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece1, (BlockPos) tuple.getB(), "bridge_end", rotation.getRotated((Rotation) tuple.getA()), true)); ++ if (random.nextBoolean()) { ++ EndCityPieces.EndCityPiece endcitypieces_a2 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, (BlockPos) tuple.getB(), "bridge_end", enumblockrotation.getRotated((Rotation) tuple.getA()), true)); + +- EndCityPieces.recursiveChildren(structuretemplatemanager, EndCityPieces.TOWER_BRIDGE_GENERATOR, i + 1, endcitypieces_endcitypiece2, (BlockPos) null, list, randomsource); ++ EndCityPieces.recursiveChildren(structureTemplateManager, EndCityPieces.TOWER_BRIDGE_GENERATOR, counter + 1, endcitypieces_a2, (BlockPos) null, pieces, random); + } + } + } + +- EndCityPieces.addHelper(list, EndCityPieces.addPiece(structuretemplatemanager, endcitypieces_endcitypiece1, new BlockPos(-2, 8, -2), "fat_tower_top", rotation, true)); ++ EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(-2, 8, -2), "fat_tower_top", enumblockrotation, true)); + return true; + } + }; + + public EndCityPieces() {} + +- static EndCityPieces.EndCityPiece addPiece(StructureTemplateManager structuretemplatemanager, EndCityPieces.EndCityPiece endcitypieces_endcitypiece, BlockPos blockpos, String s, Rotation rotation, boolean flag) { +- EndCityPieces.EndCityPiece endcitypieces_endcitypiece1 = new EndCityPieces.EndCityPiece(structuretemplatemanager, s, endcitypieces_endcitypiece.templatePosition(), rotation, flag); +- BlockPos blockpos1 = endcitypieces_endcitypiece.template().calculateConnectedPosition(endcitypieces_endcitypiece.placeSettings(), blockpos, endcitypieces_endcitypiece1.placeSettings(), BlockPos.ZERO); ++ static EndCityPieces.EndCityPiece addPiece(StructureTemplateManager structureTemplateManager, EndCityPieces.EndCityPiece piece, BlockPos startPos, String name, Rotation rotation, boolean overwrite) { ++ EndCityPieces.EndCityPiece endcitypieces_a1 = new EndCityPieces.EndCityPiece(structureTemplateManager, name, piece.templatePosition(), rotation, overwrite); ++ BlockPos blockposition1 = piece.template().calculateConnectedPosition(piece.placeSettings(), startPos, endcitypieces_a1.placeSettings(), BlockPos.ZERO); + +- endcitypieces_endcitypiece1.move(blockpos1.getX(), blockpos1.getY(), blockpos1.getZ()); +- return endcitypieces_endcitypiece1; ++ endcitypieces_a1.move(blockposition1.getX(), blockposition1.getY(), blockposition1.getZ()); ++ return endcitypieces_a1; + } + +- public static void startHouseTower(StructureTemplateManager structuretemplatemanager, BlockPos blockpos, Rotation rotation, List list, RandomSource randomsource) { ++ public static void startHouseTower(StructureTemplateManager structureTemplateManager, BlockPos startPos, Rotation rotation, List pieces, RandomSource random) { + EndCityPieces.FAT_TOWER_GENERATOR.init(); + EndCityPieces.HOUSE_TOWER_GENERATOR.init(); + EndCityPieces.TOWER_BRIDGE_GENERATOR.init(); + EndCityPieces.TOWER_GENERATOR.init(); +- EndCityPieces.EndCityPiece endcitypieces_endcitypiece = addHelper(list, new EndCityPieces.EndCityPiece(structuretemplatemanager, "base_floor", blockpos, rotation, true)); ++ EndCityPieces.EndCityPiece endcitypieces_a = addHelper(pieces, new EndCityPieces.EndCityPiece(structureTemplateManager, "base_floor", startPos, rotation, true)); + +- endcitypieces_endcitypiece = addHelper(list, addPiece(structuretemplatemanager, endcitypieces_endcitypiece, new BlockPos(-1, 0, -1), "second_floor_1", rotation, false)); +- endcitypieces_endcitypiece = addHelper(list, addPiece(structuretemplatemanager, endcitypieces_endcitypiece, new BlockPos(-1, 4, -1), "third_floor_1", rotation, false)); +- endcitypieces_endcitypiece = addHelper(list, addPiece(structuretemplatemanager, endcitypieces_endcitypiece, new BlockPos(-1, 8, -1), "third_roof", rotation, true)); +- recursiveChildren(structuretemplatemanager, EndCityPieces.TOWER_GENERATOR, 1, endcitypieces_endcitypiece, (BlockPos) null, list, randomsource); ++ endcitypieces_a = addHelper(pieces, addPiece(structureTemplateManager, endcitypieces_a, new BlockPos(-1, 0, -1), "second_floor_1", rotation, false)); ++ endcitypieces_a = addHelper(pieces, addPiece(structureTemplateManager, endcitypieces_a, new BlockPos(-1, 4, -1), "third_floor_1", rotation, false)); ++ endcitypieces_a = addHelper(pieces, addPiece(structureTemplateManager, endcitypieces_a, new BlockPos(-1, 8, -1), "third_roof", rotation, true)); ++ recursiveChildren(structureTemplateManager, EndCityPieces.TOWER_GENERATOR, 1, endcitypieces_a, (BlockPos) null, pieces, random); + } + +- static EndCityPieces.EndCityPiece addHelper(List list, EndCityPieces.EndCityPiece endcitypieces_endcitypiece) { +- list.add(endcitypieces_endcitypiece); +- return endcitypieces_endcitypiece; ++ static EndCityPieces.EndCityPiece addHelper(List pieces, EndCityPieces.EndCityPiece piece) { ++ pieces.add(piece); ++ return piece; + } + +- static boolean recursiveChildren(StructureTemplateManager structuretemplatemanager, EndCityPieces.SectionGenerator endcitypieces_sectiongenerator, int i, EndCityPieces.EndCityPiece endcitypieces_endcitypiece, BlockPos blockpos, List list, RandomSource randomsource) { +- if (i > 8) { ++ static boolean recursiveChildren(StructureTemplateManager structureTemplateManager, EndCityPieces.SectionGenerator sectionGenerator, int counter, EndCityPieces.EndCityPiece piece, BlockPos startPos, List pieces, RandomSource random) { ++ if (counter > 8) { + return false; + } else { + List list1 = Lists.newArrayList(); + +- if (endcitypieces_sectiongenerator.generate(structuretemplatemanager, i, endcitypieces_endcitypiece, blockpos, list1, randomsource)) { ++ if (sectionGenerator.generate(structureTemplateManager, counter, piece, startPos, list1, random)) { + boolean flag = false; +- int j = randomsource.nextInt(); ++ int j = random.nextInt(); + Iterator iterator = list1.iterator(); + + while (iterator.hasNext()) { + StructurePiece structurepiece = (StructurePiece) iterator.next(); + + structurepiece.setGenDepth(j); +- StructurePiece structurepiece1 = StructurePiece.findCollisionPiece(list, structurepiece.getBoundingBox()); ++ StructurePiece structurepiece1 = StructurePiece.findCollisionPiece(pieces, structurepiece.getBoundingBox()); + +- if (structurepiece1 != null && structurepiece1.getGenDepth() != endcitypieces_endcitypiece.getGenDepth()) { ++ if (structurepiece1 != null && structurepiece1.getGenDepth() != piece.getGenDepth()) { + flag = true; + break; + } + } + + if (!flag) { +- list.addAll(list1); ++ pieces.addAll(list1); + return true; + } + } +@@ -254,62 +246,64 @@ + + public static class EndCityPiece extends TemplateStructurePiece { + +- public EndCityPiece(StructureTemplateManager structuretemplatemanager, String s, BlockPos blockpos, Rotation rotation, boolean flag) { +- super(StructurePieceType.END_CITY_PIECE, 0, structuretemplatemanager, makeResourceLocation(s), s, makeSettings(flag, rotation), blockpos); ++ public EndCityPiece(StructureTemplateManager structureTemplateManager, String name, BlockPos startPos, Rotation rotation, boolean overwrite) { ++ super(StructurePieceType.END_CITY_PIECE, 0, structureTemplateManager, makeResourceLocation(name), name, makeSettings(overwrite, rotation), startPos); + } + +- public EndCityPiece(StructureTemplateManager structuretemplatemanager, CompoundTag compoundtag) { +- super(StructurePieceType.END_CITY_PIECE, compoundtag, structuretemplatemanager, (resourcelocation) -> { +- return makeSettings(compoundtag.getBoolean("OW"), Rotation.valueOf(compoundtag.getString("Rot"))); ++ public EndCityPiece(StructureTemplateManager structureTemplateManager, CompoundTag tag) { ++ super(StructurePieceType.END_CITY_PIECE, tag, structureTemplateManager, (minecraftkey) -> { ++ return makeSettings(tag.getBoolean("OW"), Rotation.valueOf(tag.getString("Rot"))); + }); + } + +- private static StructurePlaceSettings makeSettings(boolean flag, Rotation rotation) { +- BlockIgnoreProcessor blockignoreprocessor = flag ? BlockIgnoreProcessor.STRUCTURE_BLOCK : BlockIgnoreProcessor.STRUCTURE_AND_AIR; ++ private static StructurePlaceSettings makeSettings(boolean overwrite, Rotation rotation) { ++ BlockIgnoreProcessor definedstructureprocessorblockignore = overwrite ? BlockIgnoreProcessor.STRUCTURE_BLOCK : BlockIgnoreProcessor.STRUCTURE_AND_AIR; + +- return (new StructurePlaceSettings()).setIgnoreEntities(true).addProcessor(blockignoreprocessor).setRotation(rotation); ++ return (new StructurePlaceSettings()).setIgnoreEntities(true).addProcessor(definedstructureprocessorblockignore).setRotation(rotation); + } + + @Override +- @Override + protected ResourceLocation makeTemplateLocation() { + return makeResourceLocation(this.templateName); + } + +- private static ResourceLocation makeResourceLocation(String s) { +- return new ResourceLocation("end_city/" + s); ++ private static ResourceLocation makeResourceLocation(String name) { ++ return new ResourceLocation("end_city/" + name); + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- super.addAdditionalSaveData(structurepieceserializationcontext, compoundtag); +- compoundtag.putString("Rot", this.placeSettings.getRotation().name()); +- compoundtag.putBoolean("OW", this.placeSettings.getProcessors().get(0) == BlockIgnoreProcessor.STRUCTURE_BLOCK); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putString("Rot", this.placeSettings.getRotation().name()); ++ tag.putBoolean("OW", this.placeSettings.getProcessors().get(0) == BlockIgnoreProcessor.STRUCTURE_BLOCK); + } + + @Override +- @Override +- protected void handleDataMarker(String s, BlockPos blockpos, ServerLevelAccessor serverlevelaccessor, RandomSource randomsource, BoundingBox boundingbox) { +- if (s.startsWith("Chest")) { +- BlockPos blockpos1 = blockpos.below(); ++ protected void handleDataMarker(String name, BlockPos pos, ServerLevelAccessor level, RandomSource random, BoundingBox box) { ++ if (name.startsWith("Chest")) { ++ BlockPos blockposition1 = pos.below(); + +- if (boundingbox.isInside(blockpos1)) { +- RandomizableContainer.setBlockEntityLootTable(serverlevelaccessor, randomsource, blockpos1, BuiltInLootTables.END_CITY_TREASURE); ++ if (box.isInside(blockposition1)) { ++ // CraftBukkit start - ensure block transformation ++ /* ++ RandomizableContainer.setBlockEntityLootTable(worldaccess, randomsource, blockposition1, LootTables.END_CITY_TREASURE); ++ */ ++ setCraftLootTable(level, blockposition1, random, BuiltInLootTables.END_CITY_TREASURE); ++ // CraftBukkit end + } +- } else if (boundingbox.isInside(blockpos) && Level.isInSpawnableBounds(blockpos)) { +- if (s.startsWith("Sentry")) { +- Shulker shulker = (Shulker) EntityType.SHULKER.create(serverlevelaccessor.getLevel()); ++ } else if (box.isInside(pos) && Level.isInSpawnableBounds(pos)) { ++ if (name.startsWith("Sentry")) { ++ Shulker entityshulker = (Shulker) EntityType.SHULKER.create(level.getLevel()); + +- if (shulker != null) { +- shulker.setPos((double) blockpos.getX() + 0.5D, (double) blockpos.getY(), (double) blockpos.getZ() + 0.5D); +- serverlevelaccessor.addFreshEntity(shulker); ++ if (entityshulker != null) { ++ entityshulker.setPos((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D); ++ level.addFreshEntity(entityshulker); + } +- } else if (s.startsWith("Elytra")) { +- ItemFrame itemframe = new ItemFrame(serverlevelaccessor.getLevel(), blockpos, this.placeSettings.getRotation().rotate(Direction.SOUTH)); ++ } else if (name.startsWith("Elytra")) { ++ ItemFrame entityitemframe = new ItemFrame(level.getLevel(), pos, this.placeSettings.getRotation().rotate(Direction.SOUTH)); + +- itemframe.setItem(new ItemStack(Items.ELYTRA), false); +- serverlevelaccessor.addFreshEntity(itemframe); ++ entityitemframe.setItem(new ItemStack(Items.ELYTRA), false); ++ level.addFreshEntity(entityitemframe); + } + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java.patch new file mode 100644 index 0000000000..305c06a8bd --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java.patch @@ -0,0 +1,140 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java +@@ -14,9 +14,7 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.Mirror; + import net.minecraft.world.level.block.Rotation; +-import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.entity.ChestBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.levelgen.Heightmap; + import net.minecraft.world.level.levelgen.structure.BoundingBox; +@@ -41,83 +39,85 @@ + + public IglooPieces() {} + +- public static void addPieces(StructureTemplateManager structuretemplatemanager, BlockPos blockpos, Rotation rotation, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { +- if (randomsource.nextDouble() < 0.5D) { +- int i = randomsource.nextInt(8) + 4; ++ public static void addPieces(StructureTemplateManager structureTemplateManager, BlockPos startPos, Rotation rotation, StructurePieceAccessor pieces, RandomSource random) { ++ if (random.nextDouble() < 0.5D) { ++ int i = random.nextInt(8) + 4; + +- structurepieceaccessor.addPiece(new IglooPieces.IglooPiece(structuretemplatemanager, IglooPieces.STRUCTURE_LOCATION_LABORATORY, blockpos, rotation, i * 3)); ++ pieces.addPiece(new IglooPieces.IglooPiece(structureTemplateManager, IglooPieces.STRUCTURE_LOCATION_LABORATORY, startPos, rotation, i * 3)); + + for (int j = 0; j < i - 1; ++j) { +- structurepieceaccessor.addPiece(new IglooPieces.IglooPiece(structuretemplatemanager, IglooPieces.STRUCTURE_LOCATION_LADDER, blockpos, rotation, j * 3)); ++ pieces.addPiece(new IglooPieces.IglooPiece(structureTemplateManager, IglooPieces.STRUCTURE_LOCATION_LADDER, startPos, rotation, j * 3)); + } + } + +- structurepieceaccessor.addPiece(new IglooPieces.IglooPiece(structuretemplatemanager, IglooPieces.STRUCTURE_LOCATION_IGLOO, blockpos, rotation, 0)); ++ pieces.addPiece(new IglooPieces.IglooPiece(structureTemplateManager, IglooPieces.STRUCTURE_LOCATION_IGLOO, startPos, rotation, 0)); + } + + public static class IglooPiece extends TemplateStructurePiece { + +- public IglooPiece(StructureTemplateManager structuretemplatemanager, ResourceLocation resourcelocation, BlockPos blockpos, Rotation rotation, int i) { +- super(StructurePieceType.IGLOO, 0, structuretemplatemanager, resourcelocation, resourcelocation.toString(), makeSettings(rotation, resourcelocation), makePosition(resourcelocation, blockpos, i)); ++ public IglooPiece(StructureTemplateManager structureTemplateManager, ResourceLocation location, BlockPos startPos, Rotation rotation, int down) { ++ super(StructurePieceType.IGLOO, 0, structureTemplateManager, location, location.toString(), makeSettings(rotation, location), makePosition(location, startPos, down)); + } + +- public IglooPiece(StructureTemplateManager structuretemplatemanager, CompoundTag compoundtag) { +- super(StructurePieceType.IGLOO, compoundtag, structuretemplatemanager, (resourcelocation) -> { +- return makeSettings(Rotation.valueOf(compoundtag.getString("Rot")), resourcelocation); ++ public IglooPiece(StructureTemplateManager structureTemplateManager, CompoundTag tag) { ++ super(StructurePieceType.IGLOO, tag, structureTemplateManager, (minecraftkey) -> { ++ return makeSettings(Rotation.valueOf(tag.getString("Rot")), minecraftkey); + }); + } + +- private static StructurePlaceSettings makeSettings(Rotation rotation, ResourceLocation resourcelocation) { +- return (new StructurePlaceSettings()).setRotation(rotation).setMirror(Mirror.NONE).setRotationPivot((BlockPos) IglooPieces.PIVOTS.get(resourcelocation)).addProcessor(BlockIgnoreProcessor.STRUCTURE_BLOCK); ++ private static StructurePlaceSettings makeSettings(Rotation rotation, ResourceLocation location) { ++ return (new StructurePlaceSettings()).setRotation(rotation).setMirror(Mirror.NONE).setRotationPivot((BlockPos) IglooPieces.PIVOTS.get(location)).addProcessor(BlockIgnoreProcessor.STRUCTURE_BLOCK); + } + +- private static BlockPos makePosition(ResourceLocation resourcelocation, BlockPos blockpos, int i) { +- return blockpos.offset((Vec3i) IglooPieces.OFFSETS.get(resourcelocation)).below(i); ++ private static BlockPos makePosition(ResourceLocation location, BlockPos pos, int down) { ++ return pos.offset((Vec3i) IglooPieces.OFFSETS.get(location)).below(down); + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- super.addAdditionalSaveData(structurepieceserializationcontext, compoundtag); +- compoundtag.putString("Rot", this.placeSettings.getRotation().name()); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putString("Rot", this.placeSettings.getRotation().name()); + } + + @Override +- @Override +- protected void handleDataMarker(String s, BlockPos blockpos, ServerLevelAccessor serverlevelaccessor, RandomSource randomsource, BoundingBox boundingbox) { +- if ("chest".equals(s)) { +- serverlevelaccessor.setBlock(blockpos, Blocks.AIR.defaultBlockState(), 3); +- BlockEntity blockentity = serverlevelaccessor.getBlockEntity(blockpos.below()); ++ protected void handleDataMarker(String name, BlockPos pos, ServerLevelAccessor level, RandomSource random, BoundingBox box) { ++ if ("chest".equals(name)) { ++ level.setBlock(pos, Blocks.AIR.defaultBlockState(), 3); ++ // CraftBukkit start - ensure block transformation ++ /* ++ TileEntity tileentity = worldaccess.getBlockEntity(blockposition.below()); + +- if (blockentity instanceof ChestBlockEntity) { +- ((ChestBlockEntity) blockentity).setLootTable(BuiltInLootTables.IGLOO_CHEST, randomsource.nextLong()); ++ if (tileentity instanceof TileEntityChest) { ++ ((TileEntityChest) tileentity).setLootTable(LootTables.IGLOO_CHEST, randomsource.nextLong()); + } ++ */ ++ setCraftLootTable(level, pos.below(), random, BuiltInLootTables.IGLOO_CHEST); ++ // CraftBukkit end + + } + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- ResourceLocation resourcelocation = new ResourceLocation(this.templateName); +- StructurePlaceSettings structureplacesettings = makeSettings(this.placeSettings.getRotation(), resourcelocation); +- BlockPos blockpos1 = (BlockPos) IglooPieces.OFFSETS.get(resourcelocation); +- BlockPos blockpos2 = this.templatePosition.offset(StructureTemplate.calculateRelativePosition(structureplacesettings, new BlockPos(3 - blockpos1.getX(), 0, -blockpos1.getZ()))); +- int i = worldgenlevel.getHeight(Heightmap.Types.WORLD_SURFACE_WG, blockpos2.getX(), blockpos2.getZ()); +- BlockPos blockpos3 = this.templatePosition; ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ ResourceLocation minecraftkey = new ResourceLocation(this.templateName); ++ StructurePlaceSettings definedstructureinfo = makeSettings(this.placeSettings.getRotation(), minecraftkey); ++ BlockPos blockposition1 = (BlockPos) IglooPieces.OFFSETS.get(minecraftkey); ++ BlockPos blockposition2 = this.templatePosition.offset(StructureTemplate.calculateRelativePosition(definedstructureinfo, new BlockPos(3 - blockposition1.getX(), 0, -blockposition1.getZ()))); ++ int i = level.getHeight(Heightmap.Types.WORLD_SURFACE_WG, blockposition2.getX(), blockposition2.getZ()); ++ BlockPos blockposition3 = this.templatePosition; + + this.templatePosition = this.templatePosition.offset(0, i - 90 - 1, 0); +- super.postProcess(worldgenlevel, structuremanager, chunkgenerator, randomsource, boundingbox, chunkpos, blockpos); +- if (resourcelocation.equals(IglooPieces.STRUCTURE_LOCATION_IGLOO)) { +- BlockPos blockpos4 = this.templatePosition.offset(StructureTemplate.calculateRelativePosition(structureplacesettings, new BlockPos(3, 0, 5))); +- BlockState blockstate = worldgenlevel.getBlockState(blockpos4.below()); ++ super.postProcess(level, structureManager, generator, random, box, chunkPos, pos); ++ if (minecraftkey.equals(IglooPieces.STRUCTURE_LOCATION_IGLOO)) { ++ BlockPos blockposition4 = this.templatePosition.offset(StructureTemplate.calculateRelativePosition(definedstructureinfo, new BlockPos(3, 0, 5))); ++ IBlockData iblockdata = level.getBlockState(blockposition4.below()); + +- if (!blockstate.isAir() && !blockstate.is(Blocks.LADDER)) { +- worldgenlevel.setBlock(blockpos4, Blocks.SNOW_BLOCK.defaultBlockState(), 3); ++ if (!iblockdata.isAir() && !iblockdata.is(Blocks.LADDER)) { ++ level.setBlock(blockposition4, Blocks.SNOW_BLOCK.defaultBlockState(), 3); + } + } + +- this.templatePosition = blockpos3; ++ this.templatePosition = blockposition3; + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java.patch new file mode 100644 index 0000000000..996e46d217 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java.patch @@ -0,0 +1,1255 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java +@@ -12,10 +12,10 @@ + import net.minecraft.core.Direction; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.Tag; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.tags.BiomeTags; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.vehicle.MinecartChest; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.ChunkPos; +@@ -29,9 +29,7 @@ + import net.minecraft.world.level.block.FenceBlock; + import net.minecraft.world.level.block.RailBlock; + import net.minecraft.world.level.block.WallTorchBlock; +-import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.entity.SpawnerBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.RailShape; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.levelgen.structure.BoundingBox; +@@ -55,43 +53,43 @@ + + public MineshaftPieces() {} + +- private static MineshaftPieces.MineShaftPiece createRandomShaftPiece(StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, @Nullable Direction direction, int l, MineshaftStructure.Type mineshaftstructure_type) { +- int i1 = randomsource.nextInt(100); +- BoundingBox boundingbox; ++ private static MineshaftPieces.MineShaftPiece createRandomShaftPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, @Nullable Direction orientation, int genDepth, MineshaftStructure.Type type) { ++ int i1 = random.nextInt(100); ++ BoundingBox structureboundingbox; + + if (i1 >= 80) { +- boundingbox = MineshaftPieces.MineShaftCrossing.findCrossing(structurepieceaccessor, randomsource, i, j, k, direction); +- if (boundingbox != null) { +- return new MineshaftPieces.MineShaftCrossing(l, boundingbox, direction, mineshaftstructure_type); ++ structureboundingbox = MineshaftPieces.MineShaftCrossing.findCrossing(pieces, random, x, y, z, orientation); ++ if (structureboundingbox != null) { ++ return new MineshaftPieces.MineShaftCrossing(genDepth, structureboundingbox, orientation, type); + } + } else if (i1 >= 70) { +- boundingbox = MineshaftPieces.MineShaftStairs.findStairs(structurepieceaccessor, randomsource, i, j, k, direction); +- if (boundingbox != null) { +- return new MineshaftPieces.MineShaftStairs(l, boundingbox, direction, mineshaftstructure_type); ++ structureboundingbox = MineshaftPieces.MineShaftStairs.findStairs(pieces, random, x, y, z, orientation); ++ if (structureboundingbox != null) { ++ return new MineshaftPieces.MineShaftStairs(genDepth, structureboundingbox, orientation, type); + } + } else { +- boundingbox = MineshaftPieces.MineShaftCorridor.findCorridorSize(structurepieceaccessor, randomsource, i, j, k, direction); +- if (boundingbox != null) { +- return new MineshaftPieces.MineShaftCorridor(l, randomsource, boundingbox, direction, mineshaftstructure_type); ++ structureboundingbox = MineshaftPieces.MineShaftCorridor.findCorridorSize(pieces, random, x, y, z, orientation); ++ if (structureboundingbox != null) { ++ return new MineshaftPieces.MineShaftCorridor(genDepth, random, structureboundingbox, orientation, type); + } + } + + return null; + } + +- static MineshaftPieces.MineShaftPiece generateAndAddPiece(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction, int l) { +- if (l > 8) { ++ static MineshaftPieces.MineShaftPiece generateAndAddPiece(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction direction, int genDepth) { ++ if (genDepth > 8) { + return null; +- } else if (Math.abs(i - structurepiece.getBoundingBox().minX()) <= 80 && Math.abs(k - structurepiece.getBoundingBox().minZ()) <= 80) { +- MineshaftStructure.Type mineshaftstructure_type = ((MineshaftPieces.MineShaftPiece) structurepiece).type; +- MineshaftPieces.MineShaftPiece mineshaftpieces_mineshaftpiece = createRandomShaftPiece(structurepieceaccessor, randomsource, i, j, k, direction, l + 1, mineshaftstructure_type); ++ } else if (Math.abs(x - piece.getBoundingBox().minX()) <= 80 && Math.abs(z - piece.getBoundingBox().minZ()) <= 80) { ++ MineshaftStructure.Type mineshaftstructure_a = ((MineshaftPieces.MineShaftPiece) piece).type; ++ MineshaftPieces.MineShaftPiece mineshaftpieces_c = createRandomShaftPiece(pieces, random, x, y, z, direction, genDepth + 1, mineshaftstructure_a); + +- if (mineshaftpieces_mineshaftpiece != null) { +- structurepieceaccessor.addPiece(mineshaftpieces_mineshaftpiece); +- mineshaftpieces_mineshaftpiece.addChildren(structurepiece, structurepieceaccessor, randomsource); ++ if (mineshaftpieces_c != null) { ++ pieces.addPiece(mineshaftpieces_c); ++ mineshaftpieces_c.addChildren(piece, pieces, random); + } + +- return mineshaftpieces_mineshaftpiece; ++ return mineshaftpieces_c; + } else { + return null; + } +@@ -102,140 +100,137 @@ + private final Direction direction; + private final boolean isTwoFloored; + +- public MineShaftCrossing(CompoundTag compoundtag) { +- super(StructurePieceType.MINE_SHAFT_CROSSING, compoundtag); +- this.isTwoFloored = compoundtag.getBoolean("tf"); +- this.direction = Direction.from2DDataValue(compoundtag.getInt("D")); ++ public MineShaftCrossing(CompoundTag tag) { ++ super(StructurePieceType.MINE_SHAFT_CROSSING, tag); ++ this.isTwoFloored = tag.getBoolean("tf"); ++ this.direction = Direction.from2DDataValue(tag.getInt("D")); + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- super.addAdditionalSaveData(structurepieceserializationcontext, compoundtag); +- compoundtag.putBoolean("tf", this.isTwoFloored); +- compoundtag.putInt("D", this.direction.get2DDataValue()); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putBoolean("tf", this.isTwoFloored); ++ tag.putInt("D", this.direction.get2DDataValue()); + } + +- public MineShaftCrossing(int i, BoundingBox boundingbox, @Nullable Direction direction, MineshaftStructure.Type mineshaftstructure_type) { +- super(StructurePieceType.MINE_SHAFT_CROSSING, i, mineshaftstructure_type, boundingbox); ++ public MineShaftCrossing(int genDepth, BoundingBox boundingBox, @Nullable Direction direction, MineshaftStructure.Type type) { ++ super(StructurePieceType.MINE_SHAFT_CROSSING, genDepth, type, boundingBox); + this.direction = direction; +- this.isTwoFloored = boundingbox.getYSpan() > 3; ++ this.isTwoFloored = boundingBox.getYSpan() > 3; + } + + @Nullable +- public static BoundingBox findCrossing(StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction) { ++ public static BoundingBox findCrossing(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction direction) { + byte b0; + +- if (randomsource.nextInt(4) == 0) { ++ if (random.nextInt(4) == 0) { + b0 = 6; + } else { + b0 = 2; + } + +- BoundingBox boundingbox; ++ BoundingBox structureboundingbox; + + switch (direction) { + case NORTH: + default: +- boundingbox = new BoundingBox(-1, 0, -4, 3, b0, 0); ++ structureboundingbox = new BoundingBox(-1, 0, -4, 3, b0, 0); + break; + case SOUTH: +- boundingbox = new BoundingBox(-1, 0, 0, 3, b0, 4); ++ structureboundingbox = new BoundingBox(-1, 0, 0, 3, b0, 4); + break; + case WEST: +- boundingbox = new BoundingBox(-4, 0, -1, 0, b0, 3); ++ structureboundingbox = new BoundingBox(-4, 0, -1, 0, b0, 3); + break; + case EAST: +- boundingbox = new BoundingBox(0, 0, -1, 4, b0, 3); ++ structureboundingbox = new BoundingBox(0, 0, -1, 4, b0, 3); + } + +- boundingbox.move(i, j, k); +- return structurepieceaccessor.findCollisionPiece(boundingbox) != null ? null : boundingbox; ++ structureboundingbox.move(x, y, z); ++ return pieces.findCollisionPiece(structureboundingbox) != null ? null : structureboundingbox; + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { + int i = this.getGenDepth(); + + switch (this.direction) { + case NORTH: + default: +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() - 1, Direction.NORTH, i); +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX() - 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.WEST, i); +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.maxX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.EAST, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() - 1, Direction.NORTH, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.WEST, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.EAST, i); + break; + case SOUTH: +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.maxZ() + 1, Direction.SOUTH, i); +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX() - 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.WEST, i); +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.maxX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.EAST, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.maxZ() + 1, Direction.SOUTH, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.WEST, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.EAST, i); + break; + case WEST: +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() - 1, Direction.NORTH, i); +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.maxZ() + 1, Direction.SOUTH, i); +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX() - 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.WEST, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() - 1, Direction.NORTH, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.maxZ() + 1, Direction.SOUTH, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.WEST, i); + break; + case EAST: +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() - 1, Direction.NORTH, i); +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.maxZ() + 1, Direction.SOUTH, i); +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.maxX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.EAST, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() - 1, Direction.NORTH, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.maxZ() + 1, Direction.SOUTH, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.EAST, i); + } + + if (this.isTwoFloored) { +- if (randomsource.nextBoolean()) { +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + 1, this.boundingBox.minY() + 3 + 1, this.boundingBox.minZ() - 1, Direction.NORTH, i); ++ if (random.nextBoolean()) { ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY() + 3 + 1, this.boundingBox.minZ() - 1, Direction.NORTH, i); + } + +- if (randomsource.nextBoolean()) { +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX() - 1, this.boundingBox.minY() + 3 + 1, this.boundingBox.minZ() + 1, Direction.WEST, i); ++ if (random.nextBoolean()) { ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() + 3 + 1, this.boundingBox.minZ() + 1, Direction.WEST, i); + } + +- if (randomsource.nextBoolean()) { +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.maxX() + 1, this.boundingBox.minY() + 3 + 1, this.boundingBox.minZ() + 1, Direction.EAST, i); ++ if (random.nextBoolean()) { ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() + 3 + 1, this.boundingBox.minZ() + 1, Direction.EAST, i); + } + +- if (randomsource.nextBoolean()) { +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + 1, this.boundingBox.minY() + 3 + 1, this.boundingBox.maxZ() + 1, Direction.SOUTH, i); ++ if (random.nextBoolean()) { ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY() + 3 + 1, this.boundingBox.maxZ() + 1, Direction.SOUTH, i); + } + } + + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- if (!this.isInInvalidLocation(worldgenlevel, boundingbox)) { +- BlockState blockstate = this.type.getPlanksState(); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ if (!this.isInInvalidLocation(level, box)) { ++ IBlockData iblockdata = this.type.getPlanksState(); + + if (this.isTwoFloored) { +- this.generateBox(worldgenlevel, boundingbox, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ(), this.boundingBox.maxX() - 1, this.boundingBox.minY() + 3 - 1, this.boundingBox.maxZ(), MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); +- this.generateBox(worldgenlevel, boundingbox, this.boundingBox.minX(), this.boundingBox.minY(), this.boundingBox.minZ() + 1, this.boundingBox.maxX(), this.boundingBox.minY() + 3 - 1, this.boundingBox.maxZ() - 1, MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); +- this.generateBox(worldgenlevel, boundingbox, this.boundingBox.minX() + 1, this.boundingBox.maxY() - 2, this.boundingBox.minZ(), this.boundingBox.maxX() - 1, this.boundingBox.maxY(), this.boundingBox.maxZ(), MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); +- this.generateBox(worldgenlevel, boundingbox, this.boundingBox.minX(), this.boundingBox.maxY() - 2, this.boundingBox.minZ() + 1, this.boundingBox.maxX(), this.boundingBox.maxY(), this.boundingBox.maxZ() - 1, MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); +- this.generateBox(worldgenlevel, boundingbox, this.boundingBox.minX() + 1, this.boundingBox.minY() + 3, this.boundingBox.minZ() + 1, this.boundingBox.maxX() - 1, this.boundingBox.minY() + 3, this.boundingBox.maxZ() - 1, MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ(), this.boundingBox.maxX() - 1, this.boundingBox.minY() + 3 - 1, this.boundingBox.maxZ(), MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, this.boundingBox.minX(), this.boundingBox.minY(), this.boundingBox.minZ() + 1, this.boundingBox.maxX(), this.boundingBox.minY() + 3 - 1, this.boundingBox.maxZ() - 1, MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, this.boundingBox.minX() + 1, this.boundingBox.maxY() - 2, this.boundingBox.minZ(), this.boundingBox.maxX() - 1, this.boundingBox.maxY(), this.boundingBox.maxZ(), MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, this.boundingBox.minX(), this.boundingBox.maxY() - 2, this.boundingBox.minZ() + 1, this.boundingBox.maxX(), this.boundingBox.maxY(), this.boundingBox.maxZ() - 1, MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, this.boundingBox.minX() + 1, this.boundingBox.minY() + 3, this.boundingBox.minZ() + 1, this.boundingBox.maxX() - 1, this.boundingBox.minY() + 3, this.boundingBox.maxZ() - 1, MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); + } else { +- this.generateBox(worldgenlevel, boundingbox, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ(), this.boundingBox.maxX() - 1, this.boundingBox.maxY(), this.boundingBox.maxZ(), MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); +- this.generateBox(worldgenlevel, boundingbox, this.boundingBox.minX(), this.boundingBox.minY(), this.boundingBox.minZ() + 1, this.boundingBox.maxX(), this.boundingBox.maxY(), this.boundingBox.maxZ() - 1, MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ(), this.boundingBox.maxX() - 1, this.boundingBox.maxY(), this.boundingBox.maxZ(), MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, this.boundingBox.minX(), this.boundingBox.minY(), this.boundingBox.minZ() + 1, this.boundingBox.maxX(), this.boundingBox.maxY(), this.boundingBox.maxZ() - 1, MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); + } + +- this.placeSupportPillar(worldgenlevel, boundingbox, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, this.boundingBox.maxY()); +- this.placeSupportPillar(worldgenlevel, boundingbox, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.maxZ() - 1, this.boundingBox.maxY()); +- this.placeSupportPillar(worldgenlevel, boundingbox, this.boundingBox.maxX() - 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, this.boundingBox.maxY()); +- this.placeSupportPillar(worldgenlevel, boundingbox, this.boundingBox.maxX() - 1, this.boundingBox.minY(), this.boundingBox.maxZ() - 1, this.boundingBox.maxY()); ++ this.placeSupportPillar(level, box, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, this.boundingBox.maxY()); ++ this.placeSupportPillar(level, box, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.maxZ() - 1, this.boundingBox.maxY()); ++ this.placeSupportPillar(level, box, this.boundingBox.maxX() - 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, this.boundingBox.maxY()); ++ this.placeSupportPillar(level, box, this.boundingBox.maxX() - 1, this.boundingBox.minY(), this.boundingBox.maxZ() - 1, this.boundingBox.maxY()); + int i = this.boundingBox.minY() - 1; + + for (int j = this.boundingBox.minX(); j <= this.boundingBox.maxX(); ++j) { + for (int k = this.boundingBox.minZ(); k <= this.boundingBox.maxZ(); ++k) { +- this.setPlanksBlock(worldgenlevel, boundingbox, blockstate, j, i, k); ++ this.setPlanksBlock(level, box, iblockdata, j, i, k); + } + } + + } + } + +- private void placeSupportPillar(WorldGenLevel worldgenlevel, BoundingBox boundingbox, int i, int j, int k, int l) { +- if (!this.getBlock(worldgenlevel, i, l + 1, k, boundingbox).isAir()) { +- this.generateBox(worldgenlevel, boundingbox, i, j, k, i, l, k, this.type.getPlanksState(), MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); ++ private void placeSupportPillar(WorldGenLevel level, BoundingBox box, int x, int y, int z, int maxY) { ++ if (!this.getBlock(level, x, maxY + 1, z, box).isAir()) { ++ this.generateBox(level, box, x, y, z, x, maxY, z, this.type.getPlanksState(), MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); + } + + } +@@ -243,72 +238,70 @@ + + public static class MineShaftStairs extends MineshaftPieces.MineShaftPiece { + +- public MineShaftStairs(int i, BoundingBox boundingbox, Direction direction, MineshaftStructure.Type mineshaftstructure_type) { +- super(StructurePieceType.MINE_SHAFT_STAIRS, i, mineshaftstructure_type, boundingbox); +- this.setOrientation(direction); ++ public MineShaftStairs(int genDepth, BoundingBox boundingBox, Direction orientation, MineshaftStructure.Type type) { ++ super(StructurePieceType.MINE_SHAFT_STAIRS, genDepth, type, boundingBox); ++ this.setOrientation(orientation); + } + +- public MineShaftStairs(CompoundTag compoundtag) { +- super(StructurePieceType.MINE_SHAFT_STAIRS, compoundtag); ++ public MineShaftStairs(CompoundTag tag) { ++ super(StructurePieceType.MINE_SHAFT_STAIRS, tag); + } + + @Nullable +- public static BoundingBox findStairs(StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction) { +- BoundingBox boundingbox; ++ public static BoundingBox findStairs(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction direction) { ++ BoundingBox structureboundingbox; + + switch (direction) { + case NORTH: + default: +- boundingbox = new BoundingBox(0, -5, -8, 2, 2, 0); ++ structureboundingbox = new BoundingBox(0, -5, -8, 2, 2, 0); + break; + case SOUTH: +- boundingbox = new BoundingBox(0, -5, 0, 2, 2, 8); ++ structureboundingbox = new BoundingBox(0, -5, 0, 2, 2, 8); + break; + case WEST: +- boundingbox = new BoundingBox(-8, -5, 0, 0, 2, 2); ++ structureboundingbox = new BoundingBox(-8, -5, 0, 0, 2, 2); + break; + case EAST: +- boundingbox = new BoundingBox(0, -5, 0, 8, 2, 2); ++ structureboundingbox = new BoundingBox(0, -5, 0, 8, 2, 2); + } + +- boundingbox.move(i, j, k); +- return structurepieceaccessor.findCollisionPiece(boundingbox) != null ? null : boundingbox; ++ structureboundingbox.move(x, y, z); ++ return pieces.findCollisionPiece(structureboundingbox) != null ? null : structureboundingbox; + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { + int i = this.getGenDepth(); +- Direction direction = this.getOrientation(); ++ Direction enumdirection = this.getOrientation(); + +- if (direction != null) { +- switch (direction) { ++ if (enumdirection != null) { ++ switch (enumdirection) { + case NORTH: + default: +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX(), this.boundingBox.minY(), this.boundingBox.minZ() - 1, Direction.NORTH, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX(), this.boundingBox.minY(), this.boundingBox.minZ() - 1, Direction.NORTH, i); + break; + case SOUTH: +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX(), this.boundingBox.minY(), this.boundingBox.maxZ() + 1, Direction.SOUTH, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX(), this.boundingBox.minY(), this.boundingBox.maxZ() + 1, Direction.SOUTH, i); + break; + case WEST: +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX() - 1, this.boundingBox.minY(), this.boundingBox.minZ(), Direction.WEST, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY(), this.boundingBox.minZ(), Direction.WEST, i); + break; + case EAST: +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.maxX() + 1, this.boundingBox.minY(), this.boundingBox.minZ(), Direction.EAST, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY(), this.boundingBox.minZ(), Direction.EAST, i); + } + } + + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- if (!this.isInInvalidLocation(worldgenlevel, boundingbox)) { +- this.generateBox(worldgenlevel, boundingbox, 0, 5, 0, 2, 7, 1, MineshaftPieces.MineShaftStairs.CAVE_AIR, MineshaftPieces.MineShaftStairs.CAVE_AIR, false); +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 7, 2, 2, 8, MineshaftPieces.MineShaftStairs.CAVE_AIR, MineshaftPieces.MineShaftStairs.CAVE_AIR, false); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ if (!this.isInInvalidLocation(level, box)) { ++ this.generateBox(level, box, 0, 5, 0, 2, 7, 1, MineshaftPieces.MineShaftStairs.CAVE_AIR, MineshaftPieces.MineShaftStairs.CAVE_AIR, false); ++ this.generateBox(level, box, 0, 0, 7, 2, 2, 8, MineshaftPieces.MineShaftStairs.CAVE_AIR, MineshaftPieces.MineShaftStairs.CAVE_AIR, false); + + for (int i = 0; i < 5; ++i) { +- this.generateBox(worldgenlevel, boundingbox, 0, 5 - i - (i < 4 ? 1 : 0), 2 + i, 2, 7 - i, 2 + i, MineshaftPieces.MineShaftStairs.CAVE_AIR, MineshaftPieces.MineShaftStairs.CAVE_AIR, false); ++ this.generateBox(level, box, 0, 5 - i - (i < 4 ? 1 : 0), 2 + i, 2, 7 - i, 2 + i, MineshaftPieces.MineShaftStairs.CAVE_AIR, MineshaftPieces.MineShaftStairs.CAVE_AIR, false); + } + + } +@@ -322,61 +315,60 @@ + private boolean hasPlacedSpider; + private final int numSections; + +- public MineShaftCorridor(CompoundTag compoundtag) { +- super(StructurePieceType.MINE_SHAFT_CORRIDOR, compoundtag); +- this.hasRails = compoundtag.getBoolean("hr"); +- this.spiderCorridor = compoundtag.getBoolean("sc"); +- this.hasPlacedSpider = compoundtag.getBoolean("hps"); +- this.numSections = compoundtag.getInt("Num"); ++ public MineShaftCorridor(CompoundTag tag) { ++ super(StructurePieceType.MINE_SHAFT_CORRIDOR, tag); ++ this.hasRails = tag.getBoolean("hr"); ++ this.spiderCorridor = tag.getBoolean("sc"); ++ this.hasPlacedSpider = tag.getBoolean("hps"); ++ this.numSections = tag.getInt("Num"); + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- super.addAdditionalSaveData(structurepieceserializationcontext, compoundtag); +- compoundtag.putBoolean("hr", this.hasRails); +- compoundtag.putBoolean("sc", this.spiderCorridor); +- compoundtag.putBoolean("hps", this.hasPlacedSpider); +- compoundtag.putInt("Num", this.numSections); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putBoolean("hr", this.hasRails); ++ tag.putBoolean("sc", this.spiderCorridor); ++ tag.putBoolean("hps", this.hasPlacedSpider); ++ tag.putInt("Num", this.numSections); + } + +- public MineShaftCorridor(int i, RandomSource randomsource, BoundingBox boundingbox, Direction direction, MineshaftStructure.Type mineshaftstructure_type) { +- super(StructurePieceType.MINE_SHAFT_CORRIDOR, i, mineshaftstructure_type, boundingbox); +- this.setOrientation(direction); +- this.hasRails = randomsource.nextInt(3) == 0; +- this.spiderCorridor = !this.hasRails && randomsource.nextInt(23) == 0; ++ public MineShaftCorridor(int genDepth, RandomSource random, BoundingBox boundingBox, Direction orientation, MineshaftStructure.Type type) { ++ super(StructurePieceType.MINE_SHAFT_CORRIDOR, genDepth, type, boundingBox); ++ this.setOrientation(orientation); ++ this.hasRails = random.nextInt(3) == 0; ++ this.spiderCorridor = !this.hasRails && random.nextInt(23) == 0; + if (this.getOrientation().getAxis() == Direction.Axis.Z) { +- this.numSections = boundingbox.getZSpan() / 5; ++ this.numSections = boundingBox.getZSpan() / 5; + } else { +- this.numSections = boundingbox.getXSpan() / 5; ++ this.numSections = boundingBox.getXSpan() / 5; + } + + } + + @Nullable +- public static BoundingBox findCorridorSize(StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction) { +- for (int l = randomsource.nextInt(3) + 2; l > 0; --l) { ++ public static BoundingBox findCorridorSize(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction direction) { ++ for (int l = random.nextInt(3) + 2; l > 0; --l) { + int i1 = l * 5; +- BoundingBox boundingbox; ++ BoundingBox structureboundingbox; + + switch (direction) { + case NORTH: + default: +- boundingbox = new BoundingBox(0, 0, -(i1 - 1), 2, 2, 0); ++ structureboundingbox = new BoundingBox(0, 0, -(i1 - 1), 2, 2, 0); + break; + case SOUTH: +- boundingbox = new BoundingBox(0, 0, 0, 2, 2, i1 - 1); ++ structureboundingbox = new BoundingBox(0, 0, 0, 2, 2, i1 - 1); + break; + case WEST: +- boundingbox = new BoundingBox(-(i1 - 1), 0, 0, 0, 2, 2); ++ structureboundingbox = new BoundingBox(-(i1 - 1), 0, 0, 0, 2, 2); + break; + case EAST: +- boundingbox = new BoundingBox(0, 0, 0, i1 - 1, 2, 2); ++ structureboundingbox = new BoundingBox(0, 0, 0, i1 - 1, 2, 2); + } + +- boundingbox.move(i, j, k); +- if (structurepieceaccessor.findCollisionPiece(boundingbox) == null) { +- return boundingbox; ++ structureboundingbox.move(x, y, z); ++ if (pieces.findCollisionPiece(structureboundingbox) == null) { ++ return structureboundingbox; + } + } + +@@ -384,49 +376,48 @@ + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { + int i = this.getGenDepth(); +- int j = randomsource.nextInt(4); +- Direction direction = this.getOrientation(); ++ int j = random.nextInt(4); ++ Direction enumdirection = this.getOrientation(); + +- if (direction != null) { +- switch (direction) { ++ if (enumdirection != null) { ++ switch (enumdirection) { + case NORTH: + default: + if (j <= 1) { +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX(), this.boundingBox.minY() - 1 + randomsource.nextInt(3), this.boundingBox.minZ() - 1, direction, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX(), this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.minZ() - 1, enumdirection, i); + } else if (j == 2) { +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX() - 1, this.boundingBox.minY() - 1 + randomsource.nextInt(3), this.boundingBox.minZ(), Direction.WEST, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.minZ(), Direction.WEST, i); + } else { +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.maxX() + 1, this.boundingBox.minY() - 1 + randomsource.nextInt(3), this.boundingBox.minZ(), Direction.EAST, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.minZ(), Direction.EAST, i); + } + break; + case SOUTH: + if (j <= 1) { +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX(), this.boundingBox.minY() - 1 + randomsource.nextInt(3), this.boundingBox.maxZ() + 1, direction, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX(), this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.maxZ() + 1, enumdirection, i); + } else if (j == 2) { +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX() - 1, this.boundingBox.minY() - 1 + randomsource.nextInt(3), this.boundingBox.maxZ() - 3, Direction.WEST, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.maxZ() - 3, Direction.WEST, i); + } else { +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.maxX() + 1, this.boundingBox.minY() - 1 + randomsource.nextInt(3), this.boundingBox.maxZ() - 3, Direction.EAST, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.maxZ() - 3, Direction.EAST, i); + } + break; + case WEST: + if (j <= 1) { +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX() - 1, this.boundingBox.minY() - 1 + randomsource.nextInt(3), this.boundingBox.minZ(), direction, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.minZ(), enumdirection, i); + } else if (j == 2) { +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX(), this.boundingBox.minY() - 1 + randomsource.nextInt(3), this.boundingBox.minZ() - 1, Direction.NORTH, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX(), this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.minZ() - 1, Direction.NORTH, i); + } else { +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX(), this.boundingBox.minY() - 1 + randomsource.nextInt(3), this.boundingBox.maxZ() + 1, Direction.SOUTH, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX(), this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.maxZ() + 1, Direction.SOUTH, i); + } + break; + case EAST: + if (j <= 1) { +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.maxX() + 1, this.boundingBox.minY() - 1 + randomsource.nextInt(3), this.boundingBox.minZ(), direction, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.minZ(), enumdirection, i); + } else if (j == 2) { +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.maxX() - 3, this.boundingBox.minY() - 1 + randomsource.nextInt(3), this.boundingBox.minZ() - 1, Direction.NORTH, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() - 3, this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.minZ() - 1, Direction.NORTH, i); + } else { +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.maxX() - 3, this.boundingBox.minY() - 1 + randomsource.nextInt(3), this.boundingBox.maxZ() + 1, Direction.SOUTH, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() - 3, this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.maxZ() + 1, Direction.SOUTH, i); + } + } + } +@@ -435,22 +426,22 @@ + int k; + int l; + +- if (direction != Direction.NORTH && direction != Direction.SOUTH) { ++ if (enumdirection != Direction.NORTH && enumdirection != Direction.SOUTH) { + for (l = this.boundingBox.minX() + 3; l + 3 <= this.boundingBox.maxX(); l += 5) { +- k = randomsource.nextInt(5); ++ k = random.nextInt(5); + if (k == 0) { +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, l, this.boundingBox.minY(), this.boundingBox.minZ() - 1, Direction.NORTH, i + 1); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, l, this.boundingBox.minY(), this.boundingBox.minZ() - 1, Direction.NORTH, i + 1); + } else if (k == 1) { +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, l, this.boundingBox.minY(), this.boundingBox.maxZ() + 1, Direction.SOUTH, i + 1); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, l, this.boundingBox.minY(), this.boundingBox.maxZ() + 1, Direction.SOUTH, i + 1); + } + } + } else { + for (l = this.boundingBox.minZ() + 3; l + 3 <= this.boundingBox.maxZ(); l += 5) { +- k = randomsource.nextInt(5); ++ k = random.nextInt(5); + if (k == 0) { +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX() - 1, this.boundingBox.minY(), l, Direction.WEST, i + 1); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY(), l, Direction.WEST, i + 1); + } else if (k == 1) { +- MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.maxX() + 1, this.boundingBox.minY(), l, Direction.EAST, i + 1); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY(), l, Direction.EAST, i + 1); + } + } + } +@@ -459,18 +450,17 @@ + } + + @Override +- @Override +- protected boolean createChest(WorldGenLevel worldgenlevel, BoundingBox boundingbox, RandomSource randomsource, int i, int j, int k, ResourceLocation resourcelocation) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = this.getWorldPos(i, j, k); ++ protected boolean createChest(WorldGenLevel level, BoundingBox box, RandomSource random, int x, int y, int z, ResourceLocation lootTable) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y, z); + +- if (boundingbox.isInside(blockpos_mutableblockpos) && worldgenlevel.getBlockState(blockpos_mutableblockpos).isAir() && !worldgenlevel.getBlockState(blockpos_mutableblockpos.below()).isAir()) { +- BlockState blockstate = (BlockState) Blocks.RAIL.defaultBlockState().setValue(RailBlock.SHAPE, randomsource.nextBoolean() ? RailShape.NORTH_SOUTH : RailShape.EAST_WEST); ++ if (box.isInside(blockposition_mutableblockposition) && level.getBlockState(blockposition_mutableblockposition).isAir() && !level.getBlockState(blockposition_mutableblockposition.below()).isAir()) { ++ IBlockData iblockdata = (IBlockData) Blocks.RAIL.defaultBlockState().setValue(RailBlock.SHAPE, random.nextBoolean() ? RailShape.NORTH_SOUTH : RailShape.EAST_WEST); + +- this.placeBlock(worldgenlevel, blockstate, i, j, k, boundingbox); +- MinecartChest minecartchest = new MinecartChest(worldgenlevel.getLevel(), (double) blockpos_mutableblockpos.getX() + 0.5D, (double) blockpos_mutableblockpos.getY() + 0.5D, (double) blockpos_mutableblockpos.getZ() + 0.5D); ++ this.placeBlock(level, iblockdata, x, y, z, box); ++ MinecartChest entityminecartchest = new MinecartChest(level.getLevel(), (double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY() + 0.5D, (double) blockposition_mutableblockposition.getZ() + 0.5D); + +- minecartchest.setLootTable(resourcelocation, randomsource.nextLong()); +- worldgenlevel.addFreshEntity(minecartchest); ++ entityminecartchest.setLootTable(lootTable, random.nextLong()); ++ level.addFreshEntity(entityminecartchest); + return true; + } else { + return false; +@@ -478,20 +468,19 @@ + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- if (!this.isInInvalidLocation(worldgenlevel, boundingbox)) { ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ if (!this.isInInvalidLocation(level, box)) { + boolean flag = false; + boolean flag1 = true; + boolean flag2 = false; + boolean flag3 = true; + int i = this.numSections * 5 - 1; +- BlockState blockstate = this.type.getPlanksState(); ++ IBlockData iblockdata = this.type.getPlanksState(); + +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 0, 2, 1, i, MineshaftPieces.MineShaftCorridor.CAVE_AIR, MineshaftPieces.MineShaftCorridor.CAVE_AIR, false); +- this.generateMaybeBox(worldgenlevel, boundingbox, randomsource, 0.8F, 0, 2, 0, 2, 2, i, MineshaftPieces.MineShaftCorridor.CAVE_AIR, MineshaftPieces.MineShaftCorridor.CAVE_AIR, false, false); ++ this.generateBox(level, box, 0, 0, 0, 2, 1, i, MineshaftPieces.MineShaftCorridor.CAVE_AIR, MineshaftPieces.MineShaftCorridor.CAVE_AIR, false); ++ this.generateMaybeBox(level, box, random, 0.8F, 0, 2, 0, 2, 2, i, MineshaftPieces.MineShaftCorridor.CAVE_AIR, MineshaftPieces.MineShaftCorridor.CAVE_AIR, false, false); + if (this.spiderCorridor) { +- this.generateMaybeBox(worldgenlevel, boundingbox, randomsource, 0.6F, 0, 0, 0, 2, 1, i, Blocks.COBWEB.defaultBlockState(), MineshaftPieces.MineShaftCorridor.CAVE_AIR, false, true); ++ this.generateMaybeBox(level, box, random, 0.6F, 0, 0, 0, 2, 1, i, Blocks.COBWEB.defaultBlockState(), MineshaftPieces.MineShaftCorridor.CAVE_AIR, false, true); + } + + int j; +@@ -499,66 +488,71 @@ + + for (k = 0; k < this.numSections; ++k) { + j = 2 + k * 5; +- this.placeSupport(worldgenlevel, boundingbox, 0, 0, j, 2, 2, randomsource); +- this.maybePlaceCobWeb(worldgenlevel, boundingbox, randomsource, 0.1F, 0, 2, j - 1); +- this.maybePlaceCobWeb(worldgenlevel, boundingbox, randomsource, 0.1F, 2, 2, j - 1); +- this.maybePlaceCobWeb(worldgenlevel, boundingbox, randomsource, 0.1F, 0, 2, j + 1); +- this.maybePlaceCobWeb(worldgenlevel, boundingbox, randomsource, 0.1F, 2, 2, j + 1); +- this.maybePlaceCobWeb(worldgenlevel, boundingbox, randomsource, 0.05F, 0, 2, j - 2); +- this.maybePlaceCobWeb(worldgenlevel, boundingbox, randomsource, 0.05F, 2, 2, j - 2); +- this.maybePlaceCobWeb(worldgenlevel, boundingbox, randomsource, 0.05F, 0, 2, j + 2); +- this.maybePlaceCobWeb(worldgenlevel, boundingbox, randomsource, 0.05F, 2, 2, j + 2); +- if (randomsource.nextInt(100) == 0) { +- this.createChest(worldgenlevel, boundingbox, randomsource, 2, 0, j - 1, BuiltInLootTables.ABANDONED_MINESHAFT); ++ this.placeSupport(level, box, 0, 0, j, 2, 2, random); ++ this.maybePlaceCobWeb(level, box, random, 0.1F, 0, 2, j - 1); ++ this.maybePlaceCobWeb(level, box, random, 0.1F, 2, 2, j - 1); ++ this.maybePlaceCobWeb(level, box, random, 0.1F, 0, 2, j + 1); ++ this.maybePlaceCobWeb(level, box, random, 0.1F, 2, 2, j + 1); ++ this.maybePlaceCobWeb(level, box, random, 0.05F, 0, 2, j - 2); ++ this.maybePlaceCobWeb(level, box, random, 0.05F, 2, 2, j - 2); ++ this.maybePlaceCobWeb(level, box, random, 0.05F, 0, 2, j + 2); ++ this.maybePlaceCobWeb(level, box, random, 0.05F, 2, 2, j + 2); ++ if (random.nextInt(100) == 0) { ++ this.createChest(level, box, random, 2, 0, j - 1, BuiltInLootTables.ABANDONED_MINESHAFT); + } + +- if (randomsource.nextInt(100) == 0) { +- this.createChest(worldgenlevel, boundingbox, randomsource, 0, 0, j + 1, BuiltInLootTables.ABANDONED_MINESHAFT); ++ if (random.nextInt(100) == 0) { ++ this.createChest(level, box, random, 0, 0, j + 1, BuiltInLootTables.ABANDONED_MINESHAFT); + } + + if (this.spiderCorridor && !this.hasPlacedSpider) { + boolean flag4 = true; +- int l = j - 1 + randomsource.nextInt(3); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = this.getWorldPos(1, 0, l); ++ int l = j - 1 + random.nextInt(3); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(1, 0, l); + +- if (boundingbox.isInside(blockpos_mutableblockpos) && this.isInterior(worldgenlevel, 1, 0, l, boundingbox)) { ++ if (box.isInside(blockposition_mutableblockposition) && this.isInterior(level, 1, 0, l, box)) { + this.hasPlacedSpider = true; +- worldgenlevel.setBlock(blockpos_mutableblockpos, Blocks.SPAWNER.defaultBlockState(), 2); +- BlockEntity blockentity = worldgenlevel.getBlockEntity(blockpos_mutableblockpos); ++ // CraftBukkit start ++ /* ++ generatoraccessseed.setBlock(blockposition_mutableblockposition, Blocks.SPAWNER.defaultBlockState(), 2); ++ TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); + +- if (blockentity instanceof SpawnerBlockEntity) { +- SpawnerBlockEntity spawnerblockentity = (SpawnerBlockEntity) blockentity; ++ if (tileentity instanceof TileEntityMobSpawner) { ++ TileEntityMobSpawner tileentitymobspawner = (TileEntityMobSpawner) tileentity; + +- spawnerblockentity.setEntityId(EntityType.CAVE_SPIDER, randomsource); ++ tileentitymobspawner.setEntityId(EntityTypes.CAVE_SPIDER, randomsource); + } ++ */ ++ placeCraftSpawner(level, blockposition_mutableblockposition, org.bukkit.entity.EntityType.CAVE_SPIDER, 2); ++ // CraftBukkit end + } + } + } + + for (k = 0; k <= 2; ++k) { + for (j = 0; j <= i; ++j) { +- this.setPlanksBlock(worldgenlevel, boundingbox, blockstate, k, -1, j); ++ this.setPlanksBlock(level, box, iblockdata, k, -1, j); + } + } + + boolean flag5 = true; + +- this.placeDoubleLowerOrUpperSupport(worldgenlevel, boundingbox, 0, -1, 2); ++ this.placeDoubleLowerOrUpperSupport(level, box, 0, -1, 2); + if (this.numSections > 1) { + j = i - 2; +- this.placeDoubleLowerOrUpperSupport(worldgenlevel, boundingbox, 0, -1, j); ++ this.placeDoubleLowerOrUpperSupport(level, box, 0, -1, j); + } + + if (this.hasRails) { +- BlockState blockstate1 = (BlockState) Blocks.RAIL.defaultBlockState().setValue(RailBlock.SHAPE, RailShape.NORTH_SOUTH); ++ IBlockData iblockdata1 = (IBlockData) Blocks.RAIL.defaultBlockState().setValue(RailBlock.SHAPE, RailShape.NORTH_SOUTH); + + for (int i1 = 0; i1 <= i; ++i1) { +- BlockState blockstate2 = this.getBlock(worldgenlevel, 1, -1, i1, boundingbox); ++ IBlockData iblockdata2 = this.getBlock(level, 1, -1, i1, box); + +- if (!blockstate2.isAir() && blockstate2.isSolidRender(worldgenlevel, this.getWorldPos(1, -1, i1))) { +- float f = this.isInterior(worldgenlevel, 1, 0, i1, boundingbox) ? 0.7F : 0.9F; ++ if (!iblockdata2.isAir() && iblockdata2.isSolidRender(level, this.getWorldPos(1, -1, i1))) { ++ float f = this.isInterior(level, 1, 0, i1, box) ? 0.7F : 0.9F; + +- this.maybeGenerateBlock(worldgenlevel, boundingbox, randomsource, f, 1, 0, i1, blockstate1); ++ this.maybeGenerateBlock(level, box, random, f, 1, 0, i1, iblockdata1); + } + } + } +@@ -566,142 +560,141 @@ + } + } + +- private void placeDoubleLowerOrUpperSupport(WorldGenLevel worldgenlevel, BoundingBox boundingbox, int i, int j, int k) { +- BlockState blockstate = this.type.getWoodState(); +- BlockState blockstate1 = this.type.getPlanksState(); ++ private void placeDoubleLowerOrUpperSupport(WorldGenLevel level, BoundingBox box, int x, int y, int z) { ++ IBlockData iblockdata = this.type.getWoodState(); ++ IBlockData iblockdata1 = this.type.getPlanksState(); + +- if (this.getBlock(worldgenlevel, i, j, k, boundingbox).is(blockstate1.getBlock())) { +- this.fillPillarDownOrChainUp(worldgenlevel, blockstate, i, j, k, boundingbox); ++ if (this.getBlock(level, x, y, z, box).is(iblockdata1.getBlock())) { ++ this.fillPillarDownOrChainUp(level, iblockdata, x, y, z, box); + } + +- if (this.getBlock(worldgenlevel, i + 2, j, k, boundingbox).is(blockstate1.getBlock())) { +- this.fillPillarDownOrChainUp(worldgenlevel, blockstate, i + 2, j, k, boundingbox); ++ if (this.getBlock(level, x + 2, y, z, box).is(iblockdata1.getBlock())) { ++ this.fillPillarDownOrChainUp(level, iblockdata, x + 2, y, z, box); + } + + } + + @Override +- @Override +- protected void fillColumnDown(WorldGenLevel worldgenlevel, BlockState blockstate, int i, int j, int k, BoundingBox boundingbox) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = this.getWorldPos(i, j, k); ++ protected void fillColumnDown(WorldGenLevel level, IBlockData state, int x, int y, int z, BoundingBox box) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y, z); + +- if (boundingbox.isInside(blockpos_mutableblockpos)) { +- int l = blockpos_mutableblockpos.getY(); ++ if (box.isInside(blockposition_mutableblockposition)) { ++ int l = blockposition_mutableblockposition.getY(); + +- while (this.isReplaceableByStructures(worldgenlevel.getBlockState(blockpos_mutableblockpos)) && blockpos_mutableblockpos.getY() > worldgenlevel.getMinBuildHeight() + 1) { +- blockpos_mutableblockpos.move(Direction.DOWN); ++ while (this.isReplaceableByStructures(level.getBlockState(blockposition_mutableblockposition)) && blockposition_mutableblockposition.getY() > level.getMinBuildHeight() + 1) { ++ blockposition_mutableblockposition.move(Direction.DOWN); + } + +- if (this.canPlaceColumnOnTopOf(worldgenlevel, blockpos_mutableblockpos, worldgenlevel.getBlockState(blockpos_mutableblockpos))) { +- while (blockpos_mutableblockpos.getY() < l) { +- blockpos_mutableblockpos.move(Direction.UP); +- worldgenlevel.setBlock(blockpos_mutableblockpos, blockstate, 2); ++ if (this.canPlaceColumnOnTopOf(level, blockposition_mutableblockposition, level.getBlockState(blockposition_mutableblockposition))) { ++ while (blockposition_mutableblockposition.getY() < l) { ++ blockposition_mutableblockposition.move(Direction.UP); ++ level.setBlock(blockposition_mutableblockposition, state, 2); + } + + } + } + } + +- protected void fillPillarDownOrChainUp(WorldGenLevel worldgenlevel, BlockState blockstate, int i, int j, int k, BoundingBox boundingbox) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = this.getWorldPos(i, j, k); ++ protected void fillPillarDownOrChainUp(WorldGenLevel level, IBlockData state, int x, int y, int z, BoundingBox box) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y, z); + +- if (boundingbox.isInside(blockpos_mutableblockpos)) { +- int l = blockpos_mutableblockpos.getY(); ++ if (box.isInside(blockposition_mutableblockposition)) { ++ int l = blockposition_mutableblockposition.getY(); + int i1 = 1; + boolean flag = true; + + for (boolean flag1 = true; flag || flag1; ++i1) { +- BlockState blockstate1; ++ IBlockData iblockdata1; + boolean flag2; + + if (flag) { +- blockpos_mutableblockpos.setY(l - i1); +- blockstate1 = worldgenlevel.getBlockState(blockpos_mutableblockpos); +- flag2 = this.isReplaceableByStructures(blockstate1) && !blockstate1.is(Blocks.LAVA); +- if (!flag2 && this.canPlaceColumnOnTopOf(worldgenlevel, blockpos_mutableblockpos, blockstate1)) { +- fillColumnBetween(worldgenlevel, blockstate, blockpos_mutableblockpos, l - i1 + 1, l); ++ blockposition_mutableblockposition.setY(l - i1); ++ iblockdata1 = level.getBlockState(blockposition_mutableblockposition); ++ flag2 = this.isReplaceableByStructures(iblockdata1) && !iblockdata1.is(Blocks.LAVA); ++ if (!flag2 && this.canPlaceColumnOnTopOf(level, blockposition_mutableblockposition, iblockdata1)) { ++ fillColumnBetween(level, state, blockposition_mutableblockposition, l - i1 + 1, l); + return; + } + +- flag = i1 <= 20 && flag2 && blockpos_mutableblockpos.getY() > worldgenlevel.getMinBuildHeight() + 1; ++ flag = i1 <= 20 && flag2 && blockposition_mutableblockposition.getY() > level.getMinBuildHeight() + 1; + } + + if (flag1) { +- blockpos_mutableblockpos.setY(l + i1); +- blockstate1 = worldgenlevel.getBlockState(blockpos_mutableblockpos); +- flag2 = this.isReplaceableByStructures(blockstate1); +- if (!flag2 && this.canHangChainBelow(worldgenlevel, blockpos_mutableblockpos, blockstate1)) { +- worldgenlevel.setBlock(blockpos_mutableblockpos.setY(l + 1), this.type.getFenceState(), 2); +- fillColumnBetween(worldgenlevel, Blocks.CHAIN.defaultBlockState(), blockpos_mutableblockpos, l + 2, l + i1); ++ blockposition_mutableblockposition.setY(l + i1); ++ iblockdata1 = level.getBlockState(blockposition_mutableblockposition); ++ flag2 = this.isReplaceableByStructures(iblockdata1); ++ if (!flag2 && this.canHangChainBelow(level, blockposition_mutableblockposition, iblockdata1)) { ++ level.setBlock(blockposition_mutableblockposition.setY(l + 1), this.type.getFenceState(), 2); ++ fillColumnBetween(level, Blocks.CHAIN.defaultBlockState(), blockposition_mutableblockposition, l + 2, l + i1); + return; + } + +- flag1 = i1 <= 50 && flag2 && blockpos_mutableblockpos.getY() < worldgenlevel.getMaxBuildHeight() - 1; ++ flag1 = i1 <= 50 && flag2 && blockposition_mutableblockposition.getY() < level.getMaxBuildHeight() - 1; + } + } + + } + } + +- private static void fillColumnBetween(WorldGenLevel worldgenlevel, BlockState blockstate, BlockPos.MutableBlockPos blockpos_mutableblockpos, int i, int j) { +- for (int k = i; k < j; ++k) { +- worldgenlevel.setBlock(blockpos_mutableblockpos.setY(k), blockstate, 2); ++ private static void fillColumnBetween(WorldGenLevel level, IBlockData state, BlockPos.MutableBlockPos pos, int minY, int maxY) { ++ for (int k = minY; k < maxY; ++k) { ++ level.setBlock(pos.setY(k), state, 2); + } + + } + +- private boolean canPlaceColumnOnTopOf(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { +- return blockstate.isFaceSturdy(levelreader, blockpos, Direction.UP); ++ private boolean canPlaceColumnOnTopOf(LevelReader level, BlockPos pos, IBlockData state) { ++ return state.isFaceSturdy(level, pos, Direction.UP); + } + +- private boolean canHangChainBelow(LevelReader levelreader, BlockPos blockpos, BlockState blockstate) { +- return Block.canSupportCenter(levelreader, blockpos, Direction.DOWN) && !(blockstate.getBlock() instanceof FallingBlock); ++ private boolean canHangChainBelow(LevelReader level, BlockPos pos, IBlockData state) { ++ return Block.canSupportCenter(level, pos, Direction.DOWN) && !(state.getBlock() instanceof FallingBlock); + } + +- private void placeSupport(WorldGenLevel worldgenlevel, BoundingBox boundingbox, int i, int j, int k, int l, int i1, RandomSource randomsource) { +- if (this.isSupportingBox(worldgenlevel, boundingbox, i, i1, l, k)) { +- BlockState blockstate = this.type.getPlanksState(); +- BlockState blockstate1 = this.type.getFenceState(); ++ private void placeSupport(WorldGenLevel level, BoundingBox box, int minX, int minY, int z, int maxY, int maxX, RandomSource random) { ++ if (this.isSupportingBox(level, box, minX, maxX, maxY, z)) { ++ IBlockData iblockdata = this.type.getPlanksState(); ++ IBlockData iblockdata1 = this.type.getFenceState(); + +- this.generateBox(worldgenlevel, boundingbox, i, j, k, i, l - 1, k, (BlockState) blockstate1.setValue(FenceBlock.WEST, true), MineshaftPieces.MineShaftCorridor.CAVE_AIR, false); +- this.generateBox(worldgenlevel, boundingbox, i1, j, k, i1, l - 1, k, (BlockState) blockstate1.setValue(FenceBlock.EAST, true), MineshaftPieces.MineShaftCorridor.CAVE_AIR, false); +- if (randomsource.nextInt(4) == 0) { +- this.generateBox(worldgenlevel, boundingbox, i, l, k, i, l, k, blockstate, MineshaftPieces.MineShaftCorridor.CAVE_AIR, false); +- this.generateBox(worldgenlevel, boundingbox, i1, l, k, i1, l, k, blockstate, MineshaftPieces.MineShaftCorridor.CAVE_AIR, false); ++ this.generateBox(level, box, minX, minY, z, minX, maxY - 1, z, (IBlockData) iblockdata1.setValue(FenceBlock.WEST, true), MineshaftPieces.MineShaftCorridor.CAVE_AIR, false); ++ this.generateBox(level, box, maxX, minY, z, maxX, maxY - 1, z, (IBlockData) iblockdata1.setValue(FenceBlock.EAST, true), MineshaftPieces.MineShaftCorridor.CAVE_AIR, false); ++ if (random.nextInt(4) == 0) { ++ this.generateBox(level, box, minX, maxY, z, minX, maxY, z, iblockdata, MineshaftPieces.MineShaftCorridor.CAVE_AIR, false); ++ this.generateBox(level, box, maxX, maxY, z, maxX, maxY, z, iblockdata, MineshaftPieces.MineShaftCorridor.CAVE_AIR, false); + } else { +- this.generateBox(worldgenlevel, boundingbox, i, l, k, i1, l, k, blockstate, MineshaftPieces.MineShaftCorridor.CAVE_AIR, false); +- this.maybeGenerateBlock(worldgenlevel, boundingbox, randomsource, 0.05F, i + 1, l, k - 1, (BlockState) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.SOUTH)); +- this.maybeGenerateBlock(worldgenlevel, boundingbox, randomsource, 0.05F, i + 1, l, k + 1, (BlockState) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.NORTH)); ++ this.generateBox(level, box, minX, maxY, z, maxX, maxY, z, iblockdata, MineshaftPieces.MineShaftCorridor.CAVE_AIR, false); ++ this.maybeGenerateBlock(level, box, random, 0.05F, minX + 1, maxY, z - 1, (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.SOUTH)); ++ this.maybeGenerateBlock(level, box, random, 0.05F, minX + 1, maxY, z + 1, (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.NORTH)); + } + + } + } + +- private void maybePlaceCobWeb(WorldGenLevel worldgenlevel, BoundingBox boundingbox, RandomSource randomsource, float f, int i, int j, int k) { +- if (this.isInterior(worldgenlevel, i, j, k, boundingbox) && randomsource.nextFloat() < f && this.hasSturdyNeighbours(worldgenlevel, boundingbox, i, j, k, 2)) { +- this.placeBlock(worldgenlevel, Blocks.COBWEB.defaultBlockState(), i, j, k, boundingbox); ++ private void maybePlaceCobWeb(WorldGenLevel level, BoundingBox box, RandomSource random, float chance, int x, int y, int z) { ++ if (this.isInterior(level, x, y, z, box) && random.nextFloat() < chance && this.hasSturdyNeighbours(level, box, x, y, z, 2)) { ++ this.placeBlock(level, Blocks.COBWEB.defaultBlockState(), x, y, z, box); + } + + } + +- private boolean hasSturdyNeighbours(WorldGenLevel worldgenlevel, BoundingBox boundingbox, int i, int j, int k, int l) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = this.getWorldPos(i, j, k); ++ private boolean hasSturdyNeighbours(WorldGenLevel level, BoundingBox box, int x, int y, int z, int required) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y, z); + int i1 = 0; +- Direction[] adirection = Direction.values(); +- int j1 = adirection.length; ++ Direction[] aenumdirection = Direction.values(); ++ int j1 = aenumdirection.length; + + for (int k1 = 0; k1 < j1; ++k1) { +- Direction direction = adirection[k1]; ++ Direction enumdirection = aenumdirection[k1]; + +- blockpos_mutableblockpos.move(direction); +- if (boundingbox.isInside(blockpos_mutableblockpos) && worldgenlevel.getBlockState(blockpos_mutableblockpos).isFaceSturdy(worldgenlevel, blockpos_mutableblockpos, direction.getOpposite())) { ++ blockposition_mutableblockposition.move(enumdirection); ++ if (box.isInside(blockposition_mutableblockposition) && level.getBlockState(blockposition_mutableblockposition).isFaceSturdy(level, blockposition_mutableblockposition, enumdirection.getOpposite())) { + ++i1; +- if (i1 >= l) { ++ if (i1 >= required) { + return true; + } + } + +- blockpos_mutableblockpos.move(direction.getOpposite()); ++ blockposition_mutableblockposition.move(enumdirection.getOpposite()); + } + + return false; +@@ -712,33 +705,31 @@ + + protected MineshaftStructure.Type type; + +- public MineShaftPiece(StructurePieceType structurepiecetype, int i, MineshaftStructure.Type mineshaftstructure_type, BoundingBox boundingbox) { +- super(structurepiecetype, i, boundingbox); +- this.type = mineshaftstructure_type; ++ public MineShaftPiece(StructurePieceType structurePieceType, int genDepth, MineshaftStructure.Type type, BoundingBox boundingBox) { ++ super(structurePieceType, genDepth, boundingBox); ++ this.type = type; + } + +- public MineShaftPiece(StructurePieceType structurepiecetype, CompoundTag compoundtag) { +- super(structurepiecetype, compoundtag); +- this.type = MineshaftStructure.Type.byId(compoundtag.getInt("MST")); ++ public MineShaftPiece(StructurePieceType type, CompoundTag tag) { ++ super(type, tag); ++ this.type = MineshaftStructure.Type.byId(tag.getInt("MST")); + } + + @Override +- @Override +- protected boolean canBeReplaced(LevelReader levelreader, int i, int j, int k, BoundingBox boundingbox) { +- BlockState blockstate = this.getBlock(levelreader, i, j, k, boundingbox); ++ protected boolean canBeReplaced(LevelReader level, int x, int y, int z, BoundingBox box) { ++ IBlockData iblockdata = this.getBlock(level, x, y, z, box); + +- return !blockstate.is(this.type.getPlanksState().getBlock()) && !blockstate.is(this.type.getWoodState().getBlock()) && !blockstate.is(this.type.getFenceState().getBlock()) && !blockstate.is(Blocks.CHAIN); ++ return !iblockdata.is(this.type.getPlanksState().getBlock()) && !iblockdata.is(this.type.getWoodState().getBlock()) && !iblockdata.is(this.type.getFenceState().getBlock()) && !iblockdata.is(Blocks.CHAIN); + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- compoundtag.putInt("MST", this.type.ordinal()); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ tag.putInt("MST", this.type.ordinal()); + } + +- protected boolean isSupportingBox(BlockGetter blockgetter, BoundingBox boundingbox, int i, int j, int k, int l) { +- for (int i1 = i; i1 <= j; ++i1) { +- if (this.getBlock(blockgetter, i1, k + 1, l, boundingbox).isAir()) { ++ protected boolean isSupportingBox(BlockGetter level, BoundingBox box, int xStart, int xEnd, int y, int z) { ++ for (int i1 = xStart; i1 <= xEnd; ++i1) { ++ if (this.getBlock(level, i1, y + 1, z, box).isAir()) { + return false; + } + } +@@ -746,16 +737,16 @@ + return true; + } + +- protected boolean isInInvalidLocation(LevelAccessor levelaccessor, BoundingBox boundingbox) { +- int i = Math.max(this.boundingBox.minX() - 1, boundingbox.minX()); +- int j = Math.max(this.boundingBox.minY() - 1, boundingbox.minY()); +- int k = Math.max(this.boundingBox.minZ() - 1, boundingbox.minZ()); +- int l = Math.min(this.boundingBox.maxX() + 1, boundingbox.maxX()); +- int i1 = Math.min(this.boundingBox.maxY() + 1, boundingbox.maxY()); +- int j1 = Math.min(this.boundingBox.maxZ() + 1, boundingbox.maxZ()); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos((i + l) / 2, (j + i1) / 2, (k + j1) / 2); ++ protected boolean isInInvalidLocation(LevelAccessor level, BoundingBox boundingBox) { ++ int i = Math.max(this.boundingBox.minX() - 1, boundingBox.minX()); ++ int j = Math.max(this.boundingBox.minY() - 1, boundingBox.minY()); ++ int k = Math.max(this.boundingBox.minZ() - 1, boundingBox.minZ()); ++ int l = Math.min(this.boundingBox.maxX() + 1, boundingBox.maxX()); ++ int i1 = Math.min(this.boundingBox.maxY() + 1, boundingBox.maxY()); ++ int j1 = Math.min(this.boundingBox.maxZ() + 1, boundingBox.maxZ()); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos((i + l) / 2, (j + i1) / 2, (k + j1) / 2); + +- if (levelaccessor.getBiome(blockpos_mutableblockpos).is(BiomeTags.MINESHAFT_BLOCKING)) { ++ if (level.getBiome(blockposition_mutableblockposition).is(BiomeTags.MINESHAFT_BLOCKING)) { + return true; + } else { + int k1; +@@ -763,11 +754,11 @@ + + for (k1 = i; k1 <= l; ++k1) { + for (l1 = k; l1 <= j1; ++l1) { +- if (levelaccessor.getBlockState(blockpos_mutableblockpos.set(k1, j, l1)).liquid()) { ++ if (level.getBlockState(blockposition_mutableblockposition.set(k1, j, l1)).liquid()) { + return true; + } + +- if (levelaccessor.getBlockState(blockpos_mutableblockpos.set(k1, i1, l1)).liquid()) { ++ if (level.getBlockState(blockposition_mutableblockposition.set(k1, i1, l1)).liquid()) { + return true; + } + } +@@ -775,11 +766,11 @@ + + for (k1 = i; k1 <= l; ++k1) { + for (l1 = j; l1 <= i1; ++l1) { +- if (levelaccessor.getBlockState(blockpos_mutableblockpos.set(k1, l1, k)).liquid()) { ++ if (level.getBlockState(blockposition_mutableblockposition.set(k1, l1, k)).liquid()) { + return true; + } + +- if (levelaccessor.getBlockState(blockpos_mutableblockpos.set(k1, l1, j1)).liquid()) { ++ if (level.getBlockState(blockposition_mutableblockposition.set(k1, l1, j1)).liquid()) { + return true; + } + } +@@ -787,11 +778,11 @@ + + for (k1 = k; k1 <= j1; ++k1) { + for (l1 = j; l1 <= i1; ++l1) { +- if (levelaccessor.getBlockState(blockpos_mutableblockpos.set(i, l1, k1)).liquid()) { ++ if (level.getBlockState(blockposition_mutableblockposition.set(i, l1, k1)).liquid()) { + return true; + } + +- if (levelaccessor.getBlockState(blockpos_mutableblockpos.set(l, l1, k1)).liquid()) { ++ if (level.getBlockState(blockposition_mutableblockposition.set(l, l1, k1)).liquid()) { + return true; + } + } +@@ -801,13 +792,13 @@ + } + } + +- protected void setPlanksBlock(WorldGenLevel worldgenlevel, BoundingBox boundingbox, BlockState blockstate, int i, int j, int k) { +- if (this.isInterior(worldgenlevel, i, j, k, boundingbox)) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = this.getWorldPos(i, j, k); +- BlockState blockstate1 = worldgenlevel.getBlockState(blockpos_mutableblockpos); ++ protected void setPlanksBlock(WorldGenLevel level, BoundingBox box, IBlockData plankState, int x, int y, int z) { ++ if (this.isInterior(level, x, y, z, box)) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y, z); ++ IBlockData iblockdata1 = level.getBlockState(blockposition_mutableblockposition); + +- if (!blockstate1.isFaceSturdy(worldgenlevel, blockpos_mutableblockpos, Direction.UP)) { +- worldgenlevel.setBlock(blockpos_mutableblockpos, blockstate, 2); ++ if (!iblockdata1.isFaceSturdy(level, blockposition_mutableblockposition, Direction.UP)) { ++ level.setBlock(blockposition_mutableblockposition, plankState, 2); + } + + } +@@ -818,18 +809,18 @@ + + private final List childEntranceBoxes = Lists.newLinkedList(); + +- public MineShaftRoom(int i, RandomSource randomsource, int j, int k, MineshaftStructure.Type mineshaftstructure_type) { +- super(StructurePieceType.MINE_SHAFT_ROOM, i, mineshaftstructure_type, new BoundingBox(j, 50, k, j + 7 + randomsource.nextInt(6), 54 + randomsource.nextInt(6), k + 7 + randomsource.nextInt(6))); +- this.type = mineshaftstructure_type; ++ public MineShaftRoom(int genDepth, RandomSource random, int x, int z, MineshaftStructure.Type type) { ++ super(StructurePieceType.MINE_SHAFT_ROOM, genDepth, type, new BoundingBox(x, 50, z, x + 7 + random.nextInt(6), 54 + random.nextInt(6), z + 7 + random.nextInt(6))); ++ this.type = type; + } + +- public MineShaftRoom(CompoundTag compoundtag) { +- super(StructurePieceType.MINE_SHAFT_ROOM, compoundtag); +- DataResult dataresult = BoundingBox.CODEC.listOf().parse(NbtOps.INSTANCE, compoundtag.getList("Entrances", 11)); ++ public MineShaftRoom(CompoundTag tag) { ++ super(StructurePieceType.MINE_SHAFT_ROOM, tag); ++ DataResult> dataresult = BoundingBox.CODEC.listOf().parse(NbtOps.INSTANCE, tag.getList("Entrances", 11)); // CraftBukkit - decompile error + Logger logger = MineshaftPieces.LOGGER; + + Objects.requireNonNull(logger); +- Optional optional = dataresult.resultOrPartial(logger::error); ++ Optional> optional = dataresult.resultOrPartial(logger::error); // CraftBukkit - decompile error + List list = this.childEntranceBoxes; + + Objects.requireNonNull(this.childEntranceBoxes); +@@ -837,8 +828,7 @@ + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { + int i = this.getGenDepth(); + int j = this.boundingBox.getYSpan() - 3 - 1; + +@@ -847,104 +837,101 @@ + } + + int k; +- MineshaftPieces.MineShaftPiece mineshaftpieces_mineshaftpiece; +- BoundingBox boundingbox; ++ MineshaftPieces.MineShaftPiece mineshaftpieces_c; ++ BoundingBox structureboundingbox; + + for (k = 0; k < this.boundingBox.getXSpan(); k += 4) { +- k += randomsource.nextInt(this.boundingBox.getXSpan()); ++ k += random.nextInt(this.boundingBox.getXSpan()); + if (k + 3 > this.boundingBox.getXSpan()) { + break; + } + +- mineshaftpieces_mineshaftpiece = MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + k, this.boundingBox.minY() + randomsource.nextInt(j) + 1, this.boundingBox.minZ() - 1, Direction.NORTH, i); +- if (mineshaftpieces_mineshaftpiece != null) { +- boundingbox = mineshaftpieces_mineshaftpiece.getBoundingBox(); +- this.childEntranceBoxes.add(new BoundingBox(boundingbox.minX(), boundingbox.minY(), this.boundingBox.minZ(), boundingbox.maxX(), boundingbox.maxY(), this.boundingBox.minZ() + 1)); ++ mineshaftpieces_c = MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() + k, this.boundingBox.minY() + random.nextInt(j) + 1, this.boundingBox.minZ() - 1, Direction.NORTH, i); ++ if (mineshaftpieces_c != null) { ++ structureboundingbox = mineshaftpieces_c.getBoundingBox(); ++ this.childEntranceBoxes.add(new BoundingBox(structureboundingbox.minX(), structureboundingbox.minY(), this.boundingBox.minZ(), structureboundingbox.maxX(), structureboundingbox.maxY(), this.boundingBox.minZ() + 1)); + } + } + + for (k = 0; k < this.boundingBox.getXSpan(); k += 4) { +- k += randomsource.nextInt(this.boundingBox.getXSpan()); ++ k += random.nextInt(this.boundingBox.getXSpan()); + if (k + 3 > this.boundingBox.getXSpan()) { + break; + } + +- mineshaftpieces_mineshaftpiece = MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + k, this.boundingBox.minY() + randomsource.nextInt(j) + 1, this.boundingBox.maxZ() + 1, Direction.SOUTH, i); +- if (mineshaftpieces_mineshaftpiece != null) { +- boundingbox = mineshaftpieces_mineshaftpiece.getBoundingBox(); +- this.childEntranceBoxes.add(new BoundingBox(boundingbox.minX(), boundingbox.minY(), this.boundingBox.maxZ() - 1, boundingbox.maxX(), boundingbox.maxY(), this.boundingBox.maxZ())); ++ mineshaftpieces_c = MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() + k, this.boundingBox.minY() + random.nextInt(j) + 1, this.boundingBox.maxZ() + 1, Direction.SOUTH, i); ++ if (mineshaftpieces_c != null) { ++ structureboundingbox = mineshaftpieces_c.getBoundingBox(); ++ this.childEntranceBoxes.add(new BoundingBox(structureboundingbox.minX(), structureboundingbox.minY(), this.boundingBox.maxZ() - 1, structureboundingbox.maxX(), structureboundingbox.maxY(), this.boundingBox.maxZ())); + } + } + + for (k = 0; k < this.boundingBox.getZSpan(); k += 4) { +- k += randomsource.nextInt(this.boundingBox.getZSpan()); ++ k += random.nextInt(this.boundingBox.getZSpan()); + if (k + 3 > this.boundingBox.getZSpan()) { + break; + } + +- mineshaftpieces_mineshaftpiece = MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.minX() - 1, this.boundingBox.minY() + randomsource.nextInt(j) + 1, this.boundingBox.minZ() + k, Direction.WEST, i); +- if (mineshaftpieces_mineshaftpiece != null) { +- boundingbox = mineshaftpieces_mineshaftpiece.getBoundingBox(); +- this.childEntranceBoxes.add(new BoundingBox(this.boundingBox.minX(), boundingbox.minY(), boundingbox.minZ(), this.boundingBox.minX() + 1, boundingbox.maxY(), boundingbox.maxZ())); ++ mineshaftpieces_c = MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() + random.nextInt(j) + 1, this.boundingBox.minZ() + k, Direction.WEST, i); ++ if (mineshaftpieces_c != null) { ++ structureboundingbox = mineshaftpieces_c.getBoundingBox(); ++ this.childEntranceBoxes.add(new BoundingBox(this.boundingBox.minX(), structureboundingbox.minY(), structureboundingbox.minZ(), this.boundingBox.minX() + 1, structureboundingbox.maxY(), structureboundingbox.maxZ())); + } + } + + for (k = 0; k < this.boundingBox.getZSpan(); k += 4) { +- k += randomsource.nextInt(this.boundingBox.getZSpan()); ++ k += random.nextInt(this.boundingBox.getZSpan()); + if (k + 3 > this.boundingBox.getZSpan()) { + break; + } + +- mineshaftpieces_mineshaftpiece = MineshaftPieces.generateAndAddPiece(structurepiece, structurepieceaccessor, randomsource, this.boundingBox.maxX() + 1, this.boundingBox.minY() + randomsource.nextInt(j) + 1, this.boundingBox.minZ() + k, Direction.EAST, i); +- if (mineshaftpieces_mineshaftpiece != null) { +- boundingbox = mineshaftpieces_mineshaftpiece.getBoundingBox(); +- this.childEntranceBoxes.add(new BoundingBox(this.boundingBox.maxX() - 1, boundingbox.minY(), boundingbox.minZ(), this.boundingBox.maxX(), boundingbox.maxY(), boundingbox.maxZ())); ++ mineshaftpieces_c = MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() + random.nextInt(j) + 1, this.boundingBox.minZ() + k, Direction.EAST, i); ++ if (mineshaftpieces_c != null) { ++ structureboundingbox = mineshaftpieces_c.getBoundingBox(); ++ this.childEntranceBoxes.add(new BoundingBox(this.boundingBox.maxX() - 1, structureboundingbox.minY(), structureboundingbox.minZ(), this.boundingBox.maxX(), structureboundingbox.maxY(), structureboundingbox.maxZ())); + } + } + + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- if (!this.isInInvalidLocation(worldgenlevel, boundingbox)) { +- this.generateBox(worldgenlevel, boundingbox, this.boundingBox.minX(), this.boundingBox.minY() + 1, this.boundingBox.minZ(), this.boundingBox.maxX(), Math.min(this.boundingBox.minY() + 3, this.boundingBox.maxY()), this.boundingBox.maxZ(), MineshaftPieces.MineShaftRoom.CAVE_AIR, MineshaftPieces.MineShaftRoom.CAVE_AIR, false); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ if (!this.isInInvalidLocation(level, box)) { ++ this.generateBox(level, box, this.boundingBox.minX(), this.boundingBox.minY() + 1, this.boundingBox.minZ(), this.boundingBox.maxX(), Math.min(this.boundingBox.minY() + 3, this.boundingBox.maxY()), this.boundingBox.maxZ(), MineshaftPieces.MineShaftRoom.CAVE_AIR, MineshaftPieces.MineShaftRoom.CAVE_AIR, false); + Iterator iterator = this.childEntranceBoxes.iterator(); + + while (iterator.hasNext()) { +- BoundingBox boundingbox1 = (BoundingBox) iterator.next(); ++ BoundingBox structureboundingbox1 = (BoundingBox) iterator.next(); + +- this.generateBox(worldgenlevel, boundingbox, boundingbox1.minX(), boundingbox1.maxY() - 2, boundingbox1.minZ(), boundingbox1.maxX(), boundingbox1.maxY(), boundingbox1.maxZ(), MineshaftPieces.MineShaftRoom.CAVE_AIR, MineshaftPieces.MineShaftRoom.CAVE_AIR, false); ++ this.generateBox(level, box, structureboundingbox1.minX(), structureboundingbox1.maxY() - 2, structureboundingbox1.minZ(), structureboundingbox1.maxX(), structureboundingbox1.maxY(), structureboundingbox1.maxZ(), MineshaftPieces.MineShaftRoom.CAVE_AIR, MineshaftPieces.MineShaftRoom.CAVE_AIR, false); + } + +- this.generateUpperHalfSphere(worldgenlevel, boundingbox, this.boundingBox.minX(), this.boundingBox.minY() + 4, this.boundingBox.minZ(), this.boundingBox.maxX(), this.boundingBox.maxY(), this.boundingBox.maxZ(), MineshaftPieces.MineShaftRoom.CAVE_AIR, false); ++ this.generateUpperHalfSphere(level, box, this.boundingBox.minX(), this.boundingBox.minY() + 4, this.boundingBox.minZ(), this.boundingBox.maxX(), this.boundingBox.maxY(), this.boundingBox.maxZ(), MineshaftPieces.MineShaftRoom.CAVE_AIR, false); + } + } + + @Override +- @Override +- public void move(int i, int j, int k) { +- super.move(i, j, k); ++ public void move(int x, int y, int z) { ++ super.move(x, y, z); + Iterator iterator = this.childEntranceBoxes.iterator(); + + while (iterator.hasNext()) { +- BoundingBox boundingbox = (BoundingBox) iterator.next(); ++ BoundingBox structureboundingbox = (BoundingBox) iterator.next(); + +- boundingbox.move(i, j, k); ++ structureboundingbox.move(x, y, z); + } + + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- super.addAdditionalSaveData(structurepieceserializationcontext, compoundtag); +- DataResult dataresult = BoundingBox.CODEC.listOf().encodeStart(NbtOps.INSTANCE, this.childEntranceBoxes); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ DataResult dataresult = BoundingBox.CODEC.listOf().encodeStart(NbtOps.INSTANCE, this.childEntranceBoxes); // CraftBukkit - decompile error + Logger logger = MineshaftPieces.LOGGER; + + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((tag) -> { +- compoundtag.put("Entrances", tag); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ tag.put("Entrances", nbtbase); + }); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java.patch new file mode 100644 index 0000000000..5dc6beb817 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java.patch @@ -0,0 +1,1876 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java +@@ -8,16 +8,13 @@ + import net.minecraft.core.Direction; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.entity.EntityType; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.StructureManager; + import net.minecraft.world.level.WorldGenLevel; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.FenceBlock; + import net.minecraft.world.level.block.StairBlock; +-import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.entity.SpawnerBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.levelgen.structure.BoundingBox; + import net.minecraft.world.level.levelgen.structure.StructurePiece; +@@ -38,36 +35,36 @@ + + public NetherFortressPieces() {} + +- static NetherFortressPieces.NetherBridgePiece findAndCreateBridgePieceFactory(NetherFortressPieces.PieceWeight netherfortresspieces_pieceweight, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction, int l) { +- Class oclass = netherfortresspieces_pieceweight.pieceClass; ++ static NetherFortressPieces.NetherBridgePiece findAndCreateBridgePieceFactory(NetherFortressPieces.PieceWeight weight, StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ Class oclass = weight.pieceClass; + Object object = null; + + if (oclass == NetherFortressPieces.BridgeStraight.class) { +- object = NetherFortressPieces.BridgeStraight.createPiece(structurepieceaccessor, randomsource, i, j, k, direction, l); ++ object = NetherFortressPieces.BridgeStraight.createPiece(pieces, random, x, y, z, orientation, genDepth); + } else if (oclass == NetherFortressPieces.BridgeCrossing.class) { +- object = NetherFortressPieces.BridgeCrossing.createPiece(structurepieceaccessor, i, j, k, direction, l); ++ object = NetherFortressPieces.BridgeCrossing.createPiece(pieces, x, y, z, orientation, genDepth); + } else if (oclass == NetherFortressPieces.RoomCrossing.class) { +- object = NetherFortressPieces.RoomCrossing.createPiece(structurepieceaccessor, i, j, k, direction, l); ++ object = NetherFortressPieces.RoomCrossing.createPiece(pieces, x, y, z, orientation, genDepth); + } else if (oclass == NetherFortressPieces.StairsRoom.class) { +- object = NetherFortressPieces.StairsRoom.createPiece(structurepieceaccessor, i, j, k, l, direction); ++ object = NetherFortressPieces.StairsRoom.createPiece(pieces, x, y, z, genDepth, orientation); + } else if (oclass == NetherFortressPieces.MonsterThrone.class) { +- object = NetherFortressPieces.MonsterThrone.createPiece(structurepieceaccessor, i, j, k, l, direction); ++ object = NetherFortressPieces.MonsterThrone.createPiece(pieces, x, y, z, genDepth, orientation); + } else if (oclass == NetherFortressPieces.CastleEntrance.class) { +- object = NetherFortressPieces.CastleEntrance.createPiece(structurepieceaccessor, randomsource, i, j, k, direction, l); ++ object = NetherFortressPieces.CastleEntrance.createPiece(pieces, random, x, y, z, orientation, genDepth); + } else if (oclass == NetherFortressPieces.CastleSmallCorridorPiece.class) { +- object = NetherFortressPieces.CastleSmallCorridorPiece.createPiece(structurepieceaccessor, i, j, k, direction, l); ++ object = NetherFortressPieces.CastleSmallCorridorPiece.createPiece(pieces, x, y, z, orientation, genDepth); + } else if (oclass == NetherFortressPieces.CastleSmallCorridorRightTurnPiece.class) { +- object = NetherFortressPieces.CastleSmallCorridorRightTurnPiece.createPiece(structurepieceaccessor, randomsource, i, j, k, direction, l); ++ object = NetherFortressPieces.CastleSmallCorridorRightTurnPiece.createPiece(pieces, random, x, y, z, orientation, genDepth); + } else if (oclass == NetherFortressPieces.CastleSmallCorridorLeftTurnPiece.class) { +- object = NetherFortressPieces.CastleSmallCorridorLeftTurnPiece.createPiece(structurepieceaccessor, randomsource, i, j, k, direction, l); ++ object = NetherFortressPieces.CastleSmallCorridorLeftTurnPiece.createPiece(pieces, random, x, y, z, orientation, genDepth); + } else if (oclass == NetherFortressPieces.CastleCorridorStairsPiece.class) { +- object = NetherFortressPieces.CastleCorridorStairsPiece.createPiece(structurepieceaccessor, i, j, k, direction, l); ++ object = NetherFortressPieces.CastleCorridorStairsPiece.createPiece(pieces, x, y, z, orientation, genDepth); + } else if (oclass == NetherFortressPieces.CastleCorridorTBalconyPiece.class) { +- object = NetherFortressPieces.CastleCorridorTBalconyPiece.createPiece(structurepieceaccessor, i, j, k, direction, l); ++ object = NetherFortressPieces.CastleCorridorTBalconyPiece.createPiece(pieces, x, y, z, orientation, genDepth); + } else if (oclass == NetherFortressPieces.CastleSmallCorridorCrossingPiece.class) { +- object = NetherFortressPieces.CastleSmallCorridorCrossingPiece.createPiece(structurepieceaccessor, i, j, k, direction, l); ++ object = NetherFortressPieces.CastleSmallCorridorCrossingPiece.createPiece(pieces, x, y, z, orientation, genDepth); + } else if (oclass == NetherFortressPieces.CastleStalkRoom.class) { +- object = NetherFortressPieces.CastleStalkRoom.createPiece(structurepieceaccessor, i, j, k, direction, l); ++ object = NetherFortressPieces.CastleStalkRoom.createPiece(pieces, x, y, z, orientation, genDepth); + } + + return (NetherFortressPieces.NetherBridgePiece) object; +@@ -81,18 +78,18 @@ + public final int maxPlaceCount; + public final boolean allowInRow; + +- public PieceWeight(Class oclass, int i, int j, boolean flag) { +- this.pieceClass = oclass; +- this.weight = i; +- this.maxPlaceCount = j; +- this.allowInRow = flag; ++ public PieceWeight(Class pieceClass, int weight, int maxPlaceCount, boolean allowInRow) { ++ this.pieceClass = pieceClass; ++ this.weight = weight; ++ this.maxPlaceCount = maxPlaceCount; ++ this.allowInRow = allowInRow; + } + +- public PieceWeight(Class oclass, int i, int j) { +- this(oclass, i, j, false); ++ public PieceWeight(Class pieceClass, int weight, int maxPlaceCount) { ++ this(pieceClass, weight, maxPlaceCount, false); + } + +- public boolean doPlace(int i) { ++ public boolean doPlace(int genDepth) { + return this.maxPlaceCount == 0 || this.placeCount < this.maxPlaceCount; + } + +@@ -107,58 +104,56 @@ + private static final int HEIGHT = 10; + private static final int DEPTH = 19; + +- public BridgeStraight(int i, RandomSource randomsource, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.NETHER_FORTRESS_BRIDGE_STRAIGHT, i, boundingbox); +- this.setOrientation(direction); ++ public BridgeStraight(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_BRIDGE_STRAIGHT, genDepth, box); ++ this.setOrientation(orientation); + } + +- public BridgeStraight(CompoundTag compoundtag) { +- super(StructurePieceType.NETHER_FORTRESS_BRIDGE_STRAIGHT, compoundtag); ++ public BridgeStraight(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_BRIDGE_STRAIGHT, tag); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { +- this.generateChildForward((NetherFortressPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 1, 3, false); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateChildForward((NetherFortressPieces.StartPiece) piece, pieces, random, 1, 3, false); + } + +- public static NetherFortressPieces.BridgeStraight createPiece(StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -1, -3, 0, 5, 10, 19, direction); ++ public static NetherFortressPieces.BridgeStraight createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -3, 0, 5, 10, 19, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new NetherFortressPieces.BridgeStraight(l, randomsource, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.BridgeStraight(genDepth, random, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 0, 3, 0, 4, 4, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 5, 0, 3, 7, 18, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 5, 0, 0, 5, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 4, 5, 0, 4, 5, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 0, 4, 2, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 13, 4, 2, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 0, 4, 1, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 15, 4, 1, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 3, 0, 4, 4, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 5, 0, 3, 7, 18, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 5, 0, 0, 5, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 5, 0, 4, 5, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 4, 2, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 13, 4, 2, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 0, 0, 4, 1, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 0, 15, 4, 1, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + + for (int i = 0; i <= 4; ++i) { + for (int j = 0; j <= 2; ++j) { +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, boundingbox); +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, 18 - j, boundingbox); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, 18 - j, box); + } + } + +- BlockState blockstate = (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); +- BlockState blockstate1 = (BlockState) blockstate.setValue(FenceBlock.EAST, true); +- BlockState blockstate2 = (BlockState) blockstate.setValue(FenceBlock.WEST, true); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); ++ IBlockData iblockdata1 = (IBlockData) iblockdata.setValue(FenceBlock.EAST, true); ++ IBlockData iblockdata2 = (IBlockData) iblockdata.setValue(FenceBlock.WEST, true); + +- this.generateBox(worldgenlevel, boundingbox, 0, 1, 1, 0, 4, 1, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 0, 3, 4, 0, 4, 4, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 0, 3, 14, 0, 4, 14, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 0, 1, 17, 0, 4, 17, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 4, 1, 1, 4, 4, 1, blockstate2, blockstate2, false); +- this.generateBox(worldgenlevel, boundingbox, 4, 3, 4, 4, 4, 4, blockstate2, blockstate2, false); +- this.generateBox(worldgenlevel, boundingbox, 4, 3, 14, 4, 4, 14, blockstate2, blockstate2, false); +- this.generateBox(worldgenlevel, boundingbox, 4, 1, 17, 4, 4, 17, blockstate2, blockstate2, false); ++ this.generateBox(level, box, 0, 1, 1, 0, 4, 1, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 0, 3, 4, 0, 4, 4, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 0, 3, 14, 0, 4, 14, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 0, 1, 17, 0, 4, 17, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 4, 1, 1, 4, 4, 1, iblockdata2, iblockdata2, false); ++ this.generateBox(level, box, 4, 3, 4, 4, 4, 4, iblockdata2, iblockdata2, false); ++ this.generateBox(level, box, 4, 3, 14, 4, 4, 14, iblockdata2, iblockdata2, false); ++ this.generateBox(level, box, 4, 1, 17, 4, 4, 17, iblockdata2, iblockdata2, false); + } + } + +@@ -168,77 +163,75 @@ + private static final int HEIGHT = 10; + private static final int DEPTH = 19; + +- public BridgeCrossing(int i, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.NETHER_FORTRESS_BRIDGE_CROSSING, i, boundingbox); +- this.setOrientation(direction); ++ public BridgeCrossing(int genDepth, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_BRIDGE_CROSSING, genDepth, box); ++ this.setOrientation(orientation); + } + +- protected BridgeCrossing(int i, int j, Direction direction) { +- super(StructurePieceType.NETHER_FORTRESS_BRIDGE_CROSSING, 0, StructurePiece.makeBoundingBox(i, 64, j, direction, 19, 10, 19)); +- this.setOrientation(direction); ++ protected BridgeCrossing(int x, int z, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_BRIDGE_CROSSING, 0, StructurePiece.makeBoundingBox(x, 64, z, orientation, 19, 10, 19)); ++ this.setOrientation(orientation); + } + +- protected BridgeCrossing(StructurePieceType structurepiecetype, CompoundTag compoundtag) { +- super(structurepiecetype, compoundtag); ++ protected BridgeCrossing(StructurePieceType type, CompoundTag tag) { ++ super(type, tag); + } + +- public BridgeCrossing(CompoundTag compoundtag) { +- this(StructurePieceType.NETHER_FORTRESS_BRIDGE_CROSSING, compoundtag); ++ public BridgeCrossing(CompoundTag tag) { ++ this(StructurePieceType.NETHER_FORTRESS_BRIDGE_CROSSING, tag); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { +- this.generateChildForward((NetherFortressPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 8, 3, false); +- this.generateChildLeft((NetherFortressPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 3, 8, false); +- this.generateChildRight((NetherFortressPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 3, 8, false); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateChildForward((NetherFortressPieces.StartPiece) piece, pieces, random, 8, 3, false); ++ this.generateChildLeft((NetherFortressPieces.StartPiece) piece, pieces, random, 3, 8, false); ++ this.generateChildRight((NetherFortressPieces.StartPiece) piece, pieces, random, 3, 8, false); + } + +- public static NetherFortressPieces.BridgeCrossing createPiece(StructurePieceAccessor structurepieceaccessor, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -8, -3, 0, 19, 10, 19, direction); ++ public static NetherFortressPieces.BridgeCrossing createPiece(StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -8, -3, 0, 19, 10, 19, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new NetherFortressPieces.BridgeCrossing(l, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.BridgeCrossing(genDepth, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 7, 3, 0, 11, 4, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 3, 7, 18, 4, 11, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 8, 5, 0, 10, 7, 18, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 5, 8, 18, 7, 10, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 7, 5, 0, 7, 5, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 7, 5, 11, 7, 5, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 11, 5, 0, 11, 5, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 11, 5, 11, 11, 5, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 5, 7, 7, 5, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 11, 5, 7, 18, 5, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 5, 11, 7, 5, 11, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 11, 5, 11, 18, 5, 11, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 7, 2, 0, 11, 2, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 7, 2, 13, 11, 2, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 7, 0, 0, 11, 1, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 7, 0, 15, 11, 1, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 7, 3, 0, 11, 4, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 3, 7, 18, 4, 11, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 8, 5, 0, 10, 7, 18, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 5, 8, 18, 7, 10, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 7, 5, 0, 7, 5, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 7, 5, 11, 7, 5, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 11, 5, 0, 11, 5, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 11, 5, 11, 11, 5, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 5, 7, 7, 5, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 11, 5, 7, 18, 5, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 5, 11, 7, 5, 11, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 11, 5, 11, 18, 5, 11, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 7, 2, 0, 11, 2, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 7, 2, 13, 11, 2, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 7, 0, 0, 11, 1, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 7, 0, 15, 11, 1, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + + int i; + int j; + + for (i = 7; i <= 11; ++i) { + for (j = 0; j <= 2; ++j) { +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, boundingbox); +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, 18 - j, boundingbox); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, 18 - j, box); + } + } + +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 7, 5, 2, 11, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 13, 2, 7, 18, 2, 11, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 7, 3, 1, 11, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 15, 0, 7, 18, 1, 11, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 7, 5, 2, 11, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 13, 2, 7, 18, 2, 11, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 0, 7, 3, 1, 11, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 15, 0, 7, 18, 1, 11, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + + for (i = 0; i <= 2; ++i) { + for (j = 7; j <= 11; ++j) { +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, boundingbox); +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), 18 - i, -1, j, boundingbox); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), 18 - i, -1, j, box); + } + } + +@@ -251,57 +244,55 @@ + private static final int HEIGHT = 9; + private static final int DEPTH = 7; + +- public RoomCrossing(int i, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.NETHER_FORTRESS_ROOM_CROSSING, i, boundingbox); +- this.setOrientation(direction); ++ public RoomCrossing(int genDepth, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_ROOM_CROSSING, genDepth, box); ++ this.setOrientation(orientation); + } + +- public RoomCrossing(CompoundTag compoundtag) { +- super(StructurePieceType.NETHER_FORTRESS_ROOM_CROSSING, compoundtag); ++ public RoomCrossing(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_ROOM_CROSSING, tag); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { +- this.generateChildForward((NetherFortressPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 2, 0, false); +- this.generateChildLeft((NetherFortressPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 0, 2, false); +- this.generateChildRight((NetherFortressPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 0, 2, false); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateChildForward((NetherFortressPieces.StartPiece) piece, pieces, random, 2, 0, false); ++ this.generateChildLeft((NetherFortressPieces.StartPiece) piece, pieces, random, 0, 2, false); ++ this.generateChildRight((NetherFortressPieces.StartPiece) piece, pieces, random, 0, 2, false); + } + +- public static NetherFortressPieces.RoomCrossing createPiece(StructurePieceAccessor structurepieceaccessor, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -2, 0, 0, 7, 9, 7, direction); ++ public static NetherFortressPieces.RoomCrossing createPiece(StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -2, 0, 0, 7, 9, 7, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new NetherFortressPieces.RoomCrossing(l, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.RoomCrossing(genDepth, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 0, 6, 1, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 0, 6, 7, 6, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 0, 1, 6, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 6, 1, 6, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 5, 2, 0, 6, 6, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 5, 2, 6, 6, 6, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 0, 0, 6, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 5, 0, 6, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 6, 2, 0, 6, 6, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 6, 2, 5, 6, 6, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- BlockState blockstate = (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); +- BlockState blockstate1 = (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 6, 1, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 6, 7, 6, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 1, 6, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 6, 1, 6, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 2, 0, 6, 6, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 2, 6, 6, 6, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 0, 6, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 5, 0, 6, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 2, 0, 6, 6, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 2, 5, 6, 6, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); + +- this.generateBox(worldgenlevel, boundingbox, 2, 6, 0, 4, 6, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 2, 5, 0, 4, 5, 0, blockstate, blockstate, false); +- this.generateBox(worldgenlevel, boundingbox, 2, 6, 6, 4, 6, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 2, 5, 6, 4, 5, 6, blockstate, blockstate, false); +- this.generateBox(worldgenlevel, boundingbox, 0, 6, 2, 0, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 5, 2, 0, 5, 4, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 6, 6, 2, 6, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 6, 5, 2, 6, 5, 4, blockstate1, blockstate1, false); ++ this.generateBox(level, box, 2, 6, 0, 4, 6, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 5, 0, 4, 5, 0, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 2, 6, 6, 4, 6, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 5, 6, 4, 5, 6, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 0, 6, 2, 0, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 5, 2, 0, 5, 4, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 6, 6, 2, 6, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 5, 2, 6, 5, 4, iblockdata1, iblockdata1, false); + + for (int i = 0; i <= 6; ++i) { + for (int j = 0; j <= 6; ++j) { +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, boundingbox); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); + } + } + +@@ -314,56 +305,54 @@ + private static final int HEIGHT = 11; + private static final int DEPTH = 7; + +- public StairsRoom(int i, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.NETHER_FORTRESS_STAIRS_ROOM, i, boundingbox); +- this.setOrientation(direction); ++ public StairsRoom(int genDepth, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_STAIRS_ROOM, genDepth, box); ++ this.setOrientation(orientation); + } + +- public StairsRoom(CompoundTag compoundtag) { +- super(StructurePieceType.NETHER_FORTRESS_STAIRS_ROOM, compoundtag); ++ public StairsRoom(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_STAIRS_ROOM, tag); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { +- this.generateChildRight((NetherFortressPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 6, 2, false); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateChildRight((NetherFortressPieces.StartPiece) piece, pieces, random, 6, 2, false); + } + +- public static NetherFortressPieces.StairsRoom createPiece(StructurePieceAccessor structurepieceaccessor, int i, int j, int k, int l, Direction direction) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -2, 0, 0, 7, 11, 7, direction); ++ public static NetherFortressPieces.StairsRoom createPiece(StructurePieceAccessor pieces, int x, int y, int z, int genDepth, Direction orientation) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -2, 0, 0, 7, 11, 7, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new NetherFortressPieces.StairsRoom(l, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.StairsRoom(genDepth, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 0, 6, 1, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 0, 6, 10, 6, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 0, 1, 8, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 5, 2, 0, 6, 8, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 1, 0, 8, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 6, 2, 1, 6, 8, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 2, 6, 5, 8, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- BlockState blockstate = (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); +- BlockState blockstate1 = (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 6, 1, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 6, 10, 6, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 1, 8, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 2, 0, 6, 8, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 1, 0, 8, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 2, 1, 6, 8, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 2, 6, 5, 8, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); + +- this.generateBox(worldgenlevel, boundingbox, 0, 3, 2, 0, 5, 4, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 6, 3, 2, 6, 5, 2, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 6, 3, 4, 6, 5, 4, blockstate1, blockstate1, false); +- this.placeBlock(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), 5, 2, 5, boundingbox); +- this.generateBox(worldgenlevel, boundingbox, 4, 2, 5, 4, 3, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 3, 2, 5, 3, 4, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 2, 2, 5, 2, 5, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 2, 5, 1, 6, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 7, 1, 5, 7, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 6, 8, 2, 6, 8, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 2, 6, 0, 4, 8, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 2, 5, 0, 4, 5, 0, blockstate, blockstate, false); ++ this.generateBox(level, box, 0, 3, 2, 0, 5, 4, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 6, 3, 2, 6, 5, 2, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 6, 3, 4, 6, 5, 4, iblockdata1, iblockdata1, false); ++ this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), 5, 2, 5, box); ++ this.generateBox(level, box, 4, 2, 5, 4, 3, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 3, 2, 5, 3, 4, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 2, 5, 2, 5, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 2, 5, 1, 6, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 7, 1, 5, 7, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 8, 2, 6, 8, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 6, 0, 4, 8, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 5, 0, 4, 5, 0, iblockdata, iblockdata, false); + + for (int i = 0; i <= 6; ++i) { + for (int j = 0; j <= 6; ++j) { +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, boundingbox); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); + } + } + +@@ -377,81 +366,84 @@ + private static final int DEPTH = 9; + private boolean hasPlacedSpawner; + +- public MonsterThrone(int i, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.NETHER_FORTRESS_MONSTER_THRONE, i, boundingbox); +- this.setOrientation(direction); ++ public MonsterThrone(int genDepth, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_MONSTER_THRONE, genDepth, box); ++ this.setOrientation(orientation); + } + +- public MonsterThrone(CompoundTag compoundtag) { +- super(StructurePieceType.NETHER_FORTRESS_MONSTER_THRONE, compoundtag); +- this.hasPlacedSpawner = compoundtag.getBoolean("Mob"); ++ public MonsterThrone(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_MONSTER_THRONE, tag); ++ this.hasPlacedSpawner = tag.getBoolean("Mob"); + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- super.addAdditionalSaveData(structurepieceserializationcontext, compoundtag); +- compoundtag.putBoolean("Mob", this.hasPlacedSpawner); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putBoolean("Mob", this.hasPlacedSpawner); + } + +- public static NetherFortressPieces.MonsterThrone createPiece(StructurePieceAccessor structurepieceaccessor, int i, int j, int k, int l, Direction direction) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -2, 0, 0, 7, 8, 9, direction); ++ public static NetherFortressPieces.MonsterThrone createPiece(StructurePieceAccessor pieces, int x, int y, int z, int genDepth, Direction orientation) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -2, 0, 0, 7, 8, 9, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new NetherFortressPieces.MonsterThrone(l, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.MonsterThrone(genDepth, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 0, 6, 7, 7, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 0, 0, 5, 1, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 2, 1, 5, 2, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 3, 2, 5, 3, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 4, 3, 5, 4, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 2, 0, 1, 4, 2, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 5, 2, 0, 5, 4, 2, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 5, 2, 1, 5, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 5, 5, 2, 5, 5, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 5, 3, 0, 5, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 6, 5, 3, 6, 5, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 5, 8, 5, 5, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- BlockState blockstate = (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); +- BlockState blockstate1 = (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 2, 0, 6, 7, 7, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 0, 0, 5, 1, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 2, 1, 5, 2, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 3, 2, 5, 3, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 4, 3, 5, 4, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 2, 0, 1, 4, 2, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 2, 0, 5, 4, 2, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 5, 2, 1, 5, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 5, 2, 5, 5, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 5, 3, 0, 5, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 5, 3, 6, 5, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 5, 8, 5, 5, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); + +- this.placeBlock(worldgenlevel, (BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true), 1, 6, 3, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true), 5, 6, 3, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true)).setValue(FenceBlock.NORTH, true), 0, 6, 3, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.NORTH, true), 6, 6, 3, boundingbox); +- this.generateBox(worldgenlevel, boundingbox, 0, 6, 4, 0, 6, 7, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 6, 6, 4, 6, 6, 7, blockstate1, blockstate1, false); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true)).setValue(FenceBlock.SOUTH, true), 0, 6, 8, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.SOUTH, true), 6, 6, 8, boundingbox); +- this.generateBox(worldgenlevel, boundingbox, 1, 6, 8, 5, 6, 8, blockstate, blockstate, false); +- this.placeBlock(worldgenlevel, (BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true), 1, 7, 8, boundingbox); +- this.generateBox(worldgenlevel, boundingbox, 2, 7, 8, 4, 7, 8, blockstate, blockstate, false); +- this.placeBlock(worldgenlevel, (BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true), 5, 7, 8, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true), 2, 8, 8, boundingbox); +- this.placeBlock(worldgenlevel, blockstate, 3, 8, 8, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true), 4, 8, 8, boundingbox); ++ this.placeBlock(level, (IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true), 1, 6, 3, box); ++ this.placeBlock(level, (IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true), 5, 6, 3, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true)).setValue(FenceBlock.NORTH, true), 0, 6, 3, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.NORTH, true), 6, 6, 3, box); ++ this.generateBox(level, box, 0, 6, 4, 0, 6, 7, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 6, 6, 4, 6, 6, 7, iblockdata1, iblockdata1, false); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true)).setValue(FenceBlock.SOUTH, true), 0, 6, 8, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.SOUTH, true), 6, 6, 8, box); ++ this.generateBox(level, box, 1, 6, 8, 5, 6, 8, iblockdata, iblockdata, false); ++ this.placeBlock(level, (IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true), 1, 7, 8, box); ++ this.generateBox(level, box, 2, 7, 8, 4, 7, 8, iblockdata, iblockdata, false); ++ this.placeBlock(level, (IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true), 5, 7, 8, box); ++ this.placeBlock(level, (IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true), 2, 8, 8, box); ++ this.placeBlock(level, iblockdata, 3, 8, 8, box); ++ this.placeBlock(level, (IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true), 4, 8, 8, box); + if (!this.hasPlacedSpawner) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = this.getWorldPos(3, 5, 5); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(3, 5, 5); + +- if (boundingbox.isInside(blockpos_mutableblockpos)) { ++ if (box.isInside(blockposition_mutableblockposition)) { + this.hasPlacedSpawner = true; +- worldgenlevel.setBlock(blockpos_mutableblockpos, Blocks.SPAWNER.defaultBlockState(), 2); +- BlockEntity blockentity = worldgenlevel.getBlockEntity(blockpos_mutableblockpos); ++ // CraftBukkit start ++ /* ++ generatoraccessseed.setBlock(blockposition_mutableblockposition, Blocks.SPAWNER.defaultBlockState(), 2); ++ TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); + +- if (blockentity instanceof SpawnerBlockEntity) { +- SpawnerBlockEntity spawnerblockentity = (SpawnerBlockEntity) blockentity; ++ if (tileentity instanceof TileEntityMobSpawner) { ++ TileEntityMobSpawner tileentitymobspawner = (TileEntityMobSpawner) tileentity; + +- spawnerblockentity.setEntityId(EntityType.BLAZE, randomsource); ++ tileentitymobspawner.setEntityId(EntityTypes.BLAZE, randomsource); + } ++ */ ++ placeCraftSpawner(level, blockposition_mutableblockposition, org.bukkit.entity.EntityType.BLAZE, 2); ++ // CraftBukkit end + } + } + + for (int i = 0; i <= 6; ++i) { + for (int j = 0; j <= 6; ++j) { +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, boundingbox); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); + } + } + +@@ -464,105 +456,103 @@ + private static final int HEIGHT = 14; + private static final int DEPTH = 13; + +- public CastleEntrance(int i, RandomSource randomsource, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_ENTRANCE, i, boundingbox); +- this.setOrientation(direction); ++ public CastleEntrance(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_ENTRANCE, genDepth, box); ++ this.setOrientation(orientation); + } + +- public CastleEntrance(CompoundTag compoundtag) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_ENTRANCE, compoundtag); ++ public CastleEntrance(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_ENTRANCE, tag); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { +- this.generateChildForward((NetherFortressPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 5, 3, true); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateChildForward((NetherFortressPieces.StartPiece) piece, pieces, random, 5, 3, true); + } + +- public static NetherFortressPieces.CastleEntrance createPiece(StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -5, -3, 0, 13, 14, 13, direction); ++ public static NetherFortressPieces.CastleEntrance createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -5, -3, 0, 13, 14, 13, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new NetherFortressPieces.CastleEntrance(l, randomsource, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.CastleEntrance(genDepth, random, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 0, 3, 0, 12, 4, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 5, 0, 12, 13, 12, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 5, 0, 1, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 11, 5, 0, 12, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 2, 5, 11, 4, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 8, 5, 11, 10, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 5, 9, 11, 7, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 2, 5, 0, 4, 12, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 8, 5, 0, 10, 12, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 5, 9, 0, 7, 12, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 2, 11, 2, 10, 12, 10, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 5, 8, 0, 7, 8, 0, Blocks.NETHER_BRICK_FENCE.defaultBlockState(), Blocks.NETHER_BRICK_FENCE.defaultBlockState(), false); +- BlockState blockstate = (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); +- BlockState blockstate1 = (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 3, 0, 12, 4, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 5, 0, 12, 13, 12, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 5, 0, 1, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 11, 5, 0, 12, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 5, 11, 4, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 8, 5, 11, 10, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 9, 11, 7, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 5, 0, 4, 12, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 8, 5, 0, 10, 12, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 9, 0, 7, 12, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 11, 2, 10, 12, 10, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 8, 0, 7, 8, 0, Blocks.NETHER_BRICK_FENCE.defaultBlockState(), Blocks.NETHER_BRICK_FENCE.defaultBlockState(), false); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); + + int i; + + for (i = 1; i <= 11; i += 2) { +- this.generateBox(worldgenlevel, boundingbox, i, 10, 0, i, 11, 0, blockstate, blockstate, false); +- this.generateBox(worldgenlevel, boundingbox, i, 10, 12, i, 11, 12, blockstate, blockstate, false); +- this.generateBox(worldgenlevel, boundingbox, 0, 10, i, 0, 11, i, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 12, 10, i, 12, 11, i, blockstate1, blockstate1, false); +- this.placeBlock(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), i, 13, 0, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), i, 13, 12, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), 0, 13, i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), 12, 13, i, boundingbox); ++ this.generateBox(level, box, i, 10, 0, i, 11, 0, iblockdata, iblockdata, false); ++ this.generateBox(level, box, i, 10, 12, i, 11, 12, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 0, 10, i, 0, 11, i, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 12, 10, i, 12, 11, i, iblockdata1, iblockdata1, false); ++ this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, 13, 0, box); ++ this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, 13, 12, box); ++ this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), 0, 13, i, box); ++ this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), 12, 13, i, box); + if (i != 11) { +- this.placeBlock(worldgenlevel, blockstate, i + 1, 13, 0, boundingbox); +- this.placeBlock(worldgenlevel, blockstate, i + 1, 13, 12, boundingbox); +- this.placeBlock(worldgenlevel, blockstate1, 0, 13, i + 1, boundingbox); +- this.placeBlock(worldgenlevel, blockstate1, 12, 13, i + 1, boundingbox); ++ this.placeBlock(level, iblockdata, i + 1, 13, 0, box); ++ this.placeBlock(level, iblockdata, i + 1, 13, 12, box); ++ this.placeBlock(level, iblockdata1, 0, 13, i + 1, box); ++ this.placeBlock(level, iblockdata1, 12, 13, i + 1, box); + } + } + +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.EAST, true), 0, 13, 0, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.SOUTH, true)).setValue(FenceBlock.EAST, true), 0, 13, 12, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.SOUTH, true)).setValue(FenceBlock.WEST, true), 12, 13, 12, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.WEST, true), 12, 13, 0, boundingbox); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.EAST, true), 0, 13, 0, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.SOUTH, true)).setValue(FenceBlock.EAST, true), 0, 13, 12, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.SOUTH, true)).setValue(FenceBlock.WEST, true), 12, 13, 12, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.WEST, true), 12, 13, 0, box); + + for (i = 3; i <= 9; i += 2) { +- this.generateBox(worldgenlevel, boundingbox, 1, 7, i, 1, 8, i, (BlockState) blockstate1.setValue(FenceBlock.WEST, true), (BlockState) blockstate1.setValue(FenceBlock.WEST, true), false); +- this.generateBox(worldgenlevel, boundingbox, 11, 7, i, 11, 8, i, (BlockState) blockstate1.setValue(FenceBlock.EAST, true), (BlockState) blockstate1.setValue(FenceBlock.EAST, true), false); ++ this.generateBox(level, box, 1, 7, i, 1, 8, i, (IBlockData) iblockdata1.setValue(FenceBlock.WEST, true), (IBlockData) iblockdata1.setValue(FenceBlock.WEST, true), false); ++ this.generateBox(level, box, 11, 7, i, 11, 8, i, (IBlockData) iblockdata1.setValue(FenceBlock.EAST, true), (IBlockData) iblockdata1.setValue(FenceBlock.EAST, true), false); + } + +- this.generateBox(worldgenlevel, boundingbox, 4, 2, 0, 8, 2, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 4, 12, 2, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 4, 0, 0, 8, 1, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 4, 0, 9, 8, 1, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 4, 3, 1, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 9, 0, 4, 12, 1, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 2, 0, 8, 2, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 4, 12, 2, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 0, 0, 8, 1, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 0, 9, 8, 1, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 0, 4, 3, 1, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 9, 0, 4, 12, 1, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + + int j; + + for (i = 4; i <= 8; ++i) { + for (j = 0; j <= 2; ++j) { +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, boundingbox); +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, 12 - j, boundingbox); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, 12 - j, box); + } + } + + for (i = 0; i <= 2; ++i) { + for (j = 4; j <= 8; ++j) { +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, boundingbox); +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), 12 - i, -1, j, boundingbox); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), 12 - i, -1, j, box); + } + } + +- this.generateBox(worldgenlevel, boundingbox, 5, 5, 5, 7, 5, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 6, 1, 6, 6, 4, 6, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.placeBlock(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), 6, 0, 6, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.LAVA.defaultBlockState(), 6, 5, 6, boundingbox); +- BlockPos.MutableBlockPos blockpos_mutableblockpos = this.getWorldPos(6, 5, 6); ++ this.generateBox(level, box, 5, 5, 5, 7, 5, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 1, 6, 6, 4, 6, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), 6, 0, 6, box); ++ this.placeBlock(level, Blocks.LAVA.defaultBlockState(), 6, 5, 6, box); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(6, 5, 6); + +- if (boundingbox.isInside(blockpos_mutableblockpos)) { +- worldgenlevel.scheduleTick(blockpos_mutableblockpos, (Fluid) Fluids.LAVA, 0); ++ if (box.isInside(blockposition_mutableblockposition)) { ++ level.scheduleTick(blockposition_mutableblockposition, (Fluid) Fluids.LAVA, 0); + } + + } +@@ -574,45 +564,43 @@ + private static final int HEIGHT = 7; + private static final int DEPTH = 5; + +- public CastleSmallCorridorPiece(int i, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR, i, boundingbox); +- this.setOrientation(direction); ++ public CastleSmallCorridorPiece(int genDepth, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR, genDepth, box); ++ this.setOrientation(orientation); + } + +- public CastleSmallCorridorPiece(CompoundTag compoundtag) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR, compoundtag); ++ public CastleSmallCorridorPiece(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR, tag); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { +- this.generateChildForward((NetherFortressPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 1, 0, true); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateChildForward((NetherFortressPieces.StartPiece) piece, pieces, random, 1, 0, true); + } + +- public static NetherFortressPieces.CastleSmallCorridorPiece createPiece(StructurePieceAccessor structurepieceaccessor, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -1, 0, 0, 5, 7, 5, direction); ++ public static NetherFortressPieces.CastleSmallCorridorPiece createPiece(StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, 0, 0, 5, 7, 5, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new NetherFortressPieces.CastleSmallCorridorPiece(l, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.CastleSmallCorridorPiece(genDepth, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 0, 4, 1, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 0, 4, 5, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- BlockState blockstate = (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 4, 1, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 4, 5, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); + +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 0, 0, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 4, 2, 0, 4, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 3, 1, 0, 4, 1, blockstate, blockstate, false); +- this.generateBox(worldgenlevel, boundingbox, 0, 3, 3, 0, 4, 3, blockstate, blockstate, false); +- this.generateBox(worldgenlevel, boundingbox, 4, 3, 1, 4, 4, 1, blockstate, blockstate, false); +- this.generateBox(worldgenlevel, boundingbox, 4, 3, 3, 4, 4, 3, blockstate, blockstate, false); +- this.generateBox(worldgenlevel, boundingbox, 0, 6, 0, 4, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 0, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 2, 0, 4, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 3, 1, 0, 4, 1, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 0, 3, 3, 0, 4, 3, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 4, 3, 1, 4, 4, 1, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 4, 3, 3, 4, 4, 3, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 0, 6, 0, 4, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + + for (int i = 0; i <= 4; ++i) { + for (int j = 0; j <= 4; ++j) { +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, boundingbox); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); + } + } + +@@ -626,61 +614,58 @@ + private static final int DEPTH = 5; + private boolean isNeedingChest; + +- public CastleSmallCorridorRightTurnPiece(int i, RandomSource randomsource, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR_RIGHT_TURN, i, boundingbox); +- this.setOrientation(direction); +- this.isNeedingChest = randomsource.nextInt(3) == 0; ++ public CastleSmallCorridorRightTurnPiece(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR_RIGHT_TURN, genDepth, box); ++ this.setOrientation(orientation); ++ this.isNeedingChest = random.nextInt(3) == 0; + } + +- public CastleSmallCorridorRightTurnPiece(CompoundTag compoundtag) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR_RIGHT_TURN, compoundtag); +- this.isNeedingChest = compoundtag.getBoolean("Chest"); ++ public CastleSmallCorridorRightTurnPiece(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR_RIGHT_TURN, tag); ++ this.isNeedingChest = tag.getBoolean("Chest"); + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- super.addAdditionalSaveData(structurepieceserializationcontext, compoundtag); +- compoundtag.putBoolean("Chest", this.isNeedingChest); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putBoolean("Chest", this.isNeedingChest); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { +- this.generateChildRight((NetherFortressPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 0, 1, true); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateChildRight((NetherFortressPieces.StartPiece) piece, pieces, random, 0, 1, true); + } + +- public static NetherFortressPieces.CastleSmallCorridorRightTurnPiece createPiece(StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -1, 0, 0, 5, 7, 5, direction); ++ public static NetherFortressPieces.CastleSmallCorridorRightTurnPiece createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, 0, 0, 5, 7, 5, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new NetherFortressPieces.CastleSmallCorridorRightTurnPiece(l, randomsource, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.CastleSmallCorridorRightTurnPiece(genDepth, random, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 0, 4, 1, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 0, 4, 5, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- BlockState blockstate = (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); +- BlockState blockstate1 = (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 4, 1, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 4, 5, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); + +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 0, 0, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 3, 1, 0, 4, 1, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 0, 3, 3, 0, 4, 3, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 4, 2, 0, 4, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 2, 4, 4, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 3, 4, 1, 4, 4, blockstate, blockstate, false); +- this.generateBox(worldgenlevel, boundingbox, 3, 3, 4, 3, 4, 4, blockstate, blockstate, false); +- if (this.isNeedingChest && boundingbox.isInside(this.getWorldPos(1, 2, 3))) { ++ this.generateBox(level, box, 0, 2, 0, 0, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 3, 1, 0, 4, 1, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 0, 3, 3, 0, 4, 3, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 4, 2, 0, 4, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 2, 4, 4, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 3, 4, 1, 4, 4, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 3, 3, 4, 3, 4, 4, iblockdata, iblockdata, false); ++ if (this.isNeedingChest && box.isInside(this.getWorldPos(1, 2, 3))) { + this.isNeedingChest = false; +- this.createChest(worldgenlevel, boundingbox, randomsource, 1, 2, 3, BuiltInLootTables.NETHER_BRIDGE); ++ this.createChest(level, box, random, 1, 2, 3, BuiltInLootTables.NETHER_BRIDGE); + } + +- this.generateBox(worldgenlevel, boundingbox, 0, 6, 0, 4, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 6, 0, 4, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + + for (int i = 0; i <= 4; ++i) { + for (int j = 0; j <= 4; ++j) { +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, boundingbox); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); + } + } + +@@ -694,61 +679,58 @@ + private static final int DEPTH = 5; + private boolean isNeedingChest; + +- public CastleSmallCorridorLeftTurnPiece(int i, RandomSource randomsource, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR_LEFT_TURN, i, boundingbox); +- this.setOrientation(direction); +- this.isNeedingChest = randomsource.nextInt(3) == 0; ++ public CastleSmallCorridorLeftTurnPiece(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR_LEFT_TURN, genDepth, box); ++ this.setOrientation(orientation); ++ this.isNeedingChest = random.nextInt(3) == 0; + } + +- public CastleSmallCorridorLeftTurnPiece(CompoundTag compoundtag) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR_LEFT_TURN, compoundtag); +- this.isNeedingChest = compoundtag.getBoolean("Chest"); ++ public CastleSmallCorridorLeftTurnPiece(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR_LEFT_TURN, tag); ++ this.isNeedingChest = tag.getBoolean("Chest"); + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- super.addAdditionalSaveData(structurepieceserializationcontext, compoundtag); +- compoundtag.putBoolean("Chest", this.isNeedingChest); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putBoolean("Chest", this.isNeedingChest); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { +- this.generateChildLeft((NetherFortressPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 0, 1, true); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateChildLeft((NetherFortressPieces.StartPiece) piece, pieces, random, 0, 1, true); + } + +- public static NetherFortressPieces.CastleSmallCorridorLeftTurnPiece createPiece(StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -1, 0, 0, 5, 7, 5, direction); ++ public static NetherFortressPieces.CastleSmallCorridorLeftTurnPiece createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, 0, 0, 5, 7, 5, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new NetherFortressPieces.CastleSmallCorridorLeftTurnPiece(l, randomsource, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.CastleSmallCorridorLeftTurnPiece(genDepth, random, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 0, 4, 1, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 0, 4, 5, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- BlockState blockstate = (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); +- BlockState blockstate1 = (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 4, 1, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 4, 5, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); + +- this.generateBox(worldgenlevel, boundingbox, 4, 2, 0, 4, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 4, 3, 1, 4, 4, 1, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 4, 3, 3, 4, 4, 3, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 0, 0, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 4, 3, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 3, 4, 1, 4, 4, blockstate, blockstate, false); +- this.generateBox(worldgenlevel, boundingbox, 3, 3, 4, 3, 4, 4, blockstate, blockstate, false); +- if (this.isNeedingChest && boundingbox.isInside(this.getWorldPos(3, 2, 3))) { ++ this.generateBox(level, box, 4, 2, 0, 4, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 3, 1, 4, 4, 1, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 4, 3, 3, 4, 4, 3, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 0, 2, 0, 0, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 4, 3, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 3, 4, 1, 4, 4, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 3, 3, 4, 3, 4, 4, iblockdata, iblockdata, false); ++ if (this.isNeedingChest && box.isInside(this.getWorldPos(3, 2, 3))) { + this.isNeedingChest = false; +- this.createChest(worldgenlevel, boundingbox, randomsource, 3, 2, 3, BuiltInLootTables.NETHER_BRIDGE); ++ this.createChest(level, box, random, 3, 2, 3, BuiltInLootTables.NETHER_BRIDGE); + } + +- this.generateBox(worldgenlevel, boundingbox, 0, 6, 0, 4, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 6, 0, 4, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + + for (int i = 0; i <= 4; ++i) { + for (int j = 0; j <= 4; ++j) { +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, boundingbox); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); + } + } + +@@ -761,56 +743,54 @@ + private static final int HEIGHT = 14; + private static final int DEPTH = 10; + +- public CastleCorridorStairsPiece(int i, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_CORRIDOR_STAIRS, i, boundingbox); +- this.setOrientation(direction); ++ public CastleCorridorStairsPiece(int genDepth, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_CORRIDOR_STAIRS, genDepth, box); ++ this.setOrientation(orientation); + } + +- public CastleCorridorStairsPiece(CompoundTag compoundtag) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_CORRIDOR_STAIRS, compoundtag); ++ public CastleCorridorStairsPiece(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_CORRIDOR_STAIRS, tag); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { +- this.generateChildForward((NetherFortressPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 1, 0, true); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateChildForward((NetherFortressPieces.StartPiece) piece, pieces, random, 1, 0, true); + } + +- public static NetherFortressPieces.CastleCorridorStairsPiece createPiece(StructurePieceAccessor structurepieceaccessor, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -1, -7, 0, 5, 14, 10, direction); ++ public static NetherFortressPieces.CastleCorridorStairsPiece createPiece(StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -7, 0, 5, 14, 10, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new NetherFortressPieces.CastleCorridorStairsPiece(l, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.CastleCorridorStairsPiece(genDepth, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- BlockState blockstate = (BlockState) Blocks.NETHER_BRICK_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.SOUTH); +- BlockState blockstate1 = (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ IBlockData iblockdata = (IBlockData) Blocks.NETHER_BRICK_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.SOUTH); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); + + for (int i = 0; i <= 9; ++i) { + int j = Math.max(1, 7 - i); + int k = Math.min(Math.max(j + 5, 14 - i), 13); + int l = i; + +- this.generateBox(worldgenlevel, boundingbox, 0, 0, i, 4, j, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, j + 1, i, 3, k - 1, i, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 0, i, 4, j, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, j + 1, i, 3, k - 1, i, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); + if (i <= 6) { +- this.placeBlock(worldgenlevel, blockstate, 1, j + 1, i, boundingbox); +- this.placeBlock(worldgenlevel, blockstate, 2, j + 1, i, boundingbox); +- this.placeBlock(worldgenlevel, blockstate, 3, j + 1, i, boundingbox); ++ this.placeBlock(level, iblockdata, 1, j + 1, i, box); ++ this.placeBlock(level, iblockdata, 2, j + 1, i, box); ++ this.placeBlock(level, iblockdata, 3, j + 1, i, box); + } + +- this.generateBox(worldgenlevel, boundingbox, 0, k, i, 4, k, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, j + 1, i, 0, k - 1, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 4, j + 1, i, 4, k - 1, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, k, i, 4, k, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, j + 1, i, 0, k - 1, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 4, j + 1, i, 4, k - 1, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + if ((i & 1) == 0) { +- this.generateBox(worldgenlevel, boundingbox, 0, j + 2, i, 0, j + 3, i, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 4, j + 2, i, 4, j + 3, i, blockstate1, blockstate1, false); ++ this.generateBox(level, box, 0, j + 2, i, 0, j + 3, i, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 4, j + 2, i, 4, j + 3, i, iblockdata1, iblockdata1, false); + } + + for (int i1 = 0; i1 <= 4; ++i1) { +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), i1, -1, l, boundingbox); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i1, -1, l, box); + } + } + +@@ -823,66 +803,64 @@ + private static final int HEIGHT = 7; + private static final int DEPTH = 9; + +- public CastleCorridorTBalconyPiece(int i, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_CORRIDOR_T_BALCONY, i, boundingbox); +- this.setOrientation(direction); ++ public CastleCorridorTBalconyPiece(int genDepth, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_CORRIDOR_T_BALCONY, genDepth, box); ++ this.setOrientation(orientation); + } + +- public CastleCorridorTBalconyPiece(CompoundTag compoundtag) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_CORRIDOR_T_BALCONY, compoundtag); ++ public CastleCorridorTBalconyPiece(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_CORRIDOR_T_BALCONY, tag); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { + byte b0 = 1; +- Direction direction = this.getOrientation(); ++ Direction enumdirection = this.getOrientation(); + +- if (direction == Direction.WEST || direction == Direction.NORTH) { ++ if (enumdirection == Direction.WEST || enumdirection == Direction.NORTH) { + b0 = 5; + } + +- this.generateChildLeft((NetherFortressPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 0, b0, randomsource.nextInt(8) > 0); +- this.generateChildRight((NetherFortressPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 0, b0, randomsource.nextInt(8) > 0); ++ this.generateChildLeft((NetherFortressPieces.StartPiece) piece, pieces, random, 0, b0, random.nextInt(8) > 0); ++ this.generateChildRight((NetherFortressPieces.StartPiece) piece, pieces, random, 0, b0, random.nextInt(8) > 0); + } + +- public static NetherFortressPieces.CastleCorridorTBalconyPiece createPiece(StructurePieceAccessor structurepieceaccessor, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -3, 0, 0, 9, 7, 9, direction); ++ public static NetherFortressPieces.CastleCorridorTBalconyPiece createPiece(StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -3, 0, 0, 9, 7, 9, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new NetherFortressPieces.CastleCorridorTBalconyPiece(l, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.CastleCorridorTBalconyPiece(genDepth, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- BlockState blockstate = (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); +- BlockState blockstate1 = (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); + +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 0, 8, 1, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 0, 8, 5, 8, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 6, 0, 8, 6, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 0, 2, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 6, 2, 0, 8, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 3, 0, 1, 4, 0, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 7, 3, 0, 7, 4, 0, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 4, 8, 2, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 1, 4, 2, 2, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 6, 1, 4, 7, 2, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 3, 8, 7, 3, 8, blockstate1, blockstate1, false); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true)).setValue(FenceBlock.SOUTH, true), 0, 3, 8, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.SOUTH, true), 8, 3, 8, boundingbox); +- this.generateBox(worldgenlevel, boundingbox, 0, 3, 6, 0, 3, 7, blockstate, blockstate, false); +- this.generateBox(worldgenlevel, boundingbox, 8, 3, 6, 8, 3, 7, blockstate, blockstate, false); +- this.generateBox(worldgenlevel, boundingbox, 0, 3, 4, 0, 5, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 8, 3, 4, 8, 5, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 3, 5, 2, 5, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 6, 3, 5, 7, 5, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 4, 5, 1, 5, 5, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 7, 4, 5, 7, 5, 5, blockstate1, blockstate1, false); ++ this.generateBox(level, box, 0, 0, 0, 8, 1, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 8, 5, 8, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 6, 0, 8, 6, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 2, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 2, 0, 8, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 3, 0, 1, 4, 0, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 7, 3, 0, 7, 4, 0, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 0, 2, 4, 8, 2, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 1, 4, 2, 2, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 1, 4, 7, 2, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 3, 8, 7, 3, 8, iblockdata1, iblockdata1, false); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true)).setValue(FenceBlock.SOUTH, true), 0, 3, 8, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.SOUTH, true), 8, 3, 8, box); ++ this.generateBox(level, box, 0, 3, 6, 0, 3, 7, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 8, 3, 6, 8, 3, 7, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 0, 3, 4, 0, 5, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 8, 3, 4, 8, 5, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 3, 5, 2, 5, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 3, 5, 7, 5, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 4, 5, 1, 5, 5, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 7, 4, 5, 7, 5, 5, iblockdata1, iblockdata1, false); + + for (int i = 0; i <= 5; ++i) { + for (int j = 0; j <= 8; ++j) { +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), j, -1, i, boundingbox); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), j, -1, i, box); + } + } + +@@ -895,43 +873,41 @@ + private static final int HEIGHT = 7; + private static final int DEPTH = 5; + +- public CastleSmallCorridorCrossingPiece(int i, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR_CROSSING, i, boundingbox); +- this.setOrientation(direction); ++ public CastleSmallCorridorCrossingPiece(int genDepth, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR_CROSSING, genDepth, box); ++ this.setOrientation(orientation); + } + +- public CastleSmallCorridorCrossingPiece(CompoundTag compoundtag) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR_CROSSING, compoundtag); ++ public CastleSmallCorridorCrossingPiece(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR_CROSSING, tag); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { +- this.generateChildForward((NetherFortressPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 1, 0, true); +- this.generateChildLeft((NetherFortressPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 0, 1, true); +- this.generateChildRight((NetherFortressPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 0, 1, true); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateChildForward((NetherFortressPieces.StartPiece) piece, pieces, random, 1, 0, true); ++ this.generateChildLeft((NetherFortressPieces.StartPiece) piece, pieces, random, 0, 1, true); ++ this.generateChildRight((NetherFortressPieces.StartPiece) piece, pieces, random, 0, 1, true); + } + +- public static NetherFortressPieces.CastleSmallCorridorCrossingPiece createPiece(StructurePieceAccessor structurepieceaccessor, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -1, 0, 0, 5, 7, 5, direction); ++ public static NetherFortressPieces.CastleSmallCorridorCrossingPiece createPiece(StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, 0, 0, 5, 7, 5, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new NetherFortressPieces.CastleSmallCorridorCrossingPiece(l, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.CastleSmallCorridorCrossingPiece(genDepth, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 0, 4, 1, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 0, 4, 5, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 0, 0, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 4, 2, 0, 4, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 4, 0, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 4, 2, 4, 4, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 6, 0, 4, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 4, 1, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 4, 5, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 0, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 2, 0, 4, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 4, 0, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 2, 4, 4, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 6, 0, 4, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + + for (int i = 0; i <= 4; ++i) { + for (int j = 0; j <= 4; ++j) { +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, boundingbox); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); + } + } + +@@ -944,77 +920,75 @@ + private static final int HEIGHT = 14; + private static final int DEPTH = 13; + +- public CastleStalkRoom(int i, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_STALK_ROOM, i, boundingbox); +- this.setOrientation(direction); ++ public CastleStalkRoom(int genDepth, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_STALK_ROOM, genDepth, box); ++ this.setOrientation(orientation); + } + +- public CastleStalkRoom(CompoundTag compoundtag) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_STALK_ROOM, compoundtag); ++ public CastleStalkRoom(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_STALK_ROOM, tag); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { +- this.generateChildForward((NetherFortressPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 5, 3, true); +- this.generateChildForward((NetherFortressPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 5, 11, true); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateChildForward((NetherFortressPieces.StartPiece) piece, pieces, random, 5, 3, true); ++ this.generateChildForward((NetherFortressPieces.StartPiece) piece, pieces, random, 5, 11, true); + } + +- public static NetherFortressPieces.CastleStalkRoom createPiece(StructurePieceAccessor structurepieceaccessor, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -5, -3, 0, 13, 14, 13, direction); ++ public static NetherFortressPieces.CastleStalkRoom createPiece(StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -5, -3, 0, 13, 14, 13, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new NetherFortressPieces.CastleStalkRoom(l, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.CastleStalkRoom(genDepth, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 0, 3, 0, 12, 4, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 5, 0, 12, 13, 12, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 5, 0, 1, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 11, 5, 0, 12, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 2, 5, 11, 4, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 8, 5, 11, 10, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 5, 9, 11, 7, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 2, 5, 0, 4, 12, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 8, 5, 0, 10, 12, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 5, 9, 0, 7, 12, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 2, 11, 2, 10, 12, 10, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- BlockState blockstate = (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); +- BlockState blockstate1 = (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); +- BlockState blockstate2 = (BlockState) blockstate1.setValue(FenceBlock.WEST, true); +- BlockState blockstate3 = (BlockState) blockstate1.setValue(FenceBlock.EAST, true); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 3, 0, 12, 4, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 5, 0, 12, 13, 12, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 5, 0, 1, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 11, 5, 0, 12, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 5, 11, 4, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 8, 5, 11, 10, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 9, 11, 7, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 5, 0, 4, 12, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 8, 5, 0, 10, 12, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 9, 0, 7, 12, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 11, 2, 10, 12, 10, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); ++ IBlockData iblockdata2 = (IBlockData) iblockdata1.setValue(FenceBlock.WEST, true); ++ IBlockData iblockdata3 = (IBlockData) iblockdata1.setValue(FenceBlock.EAST, true); + + int i; + + for (i = 1; i <= 11; i += 2) { +- this.generateBox(worldgenlevel, boundingbox, i, 10, 0, i, 11, 0, blockstate, blockstate, false); +- this.generateBox(worldgenlevel, boundingbox, i, 10, 12, i, 11, 12, blockstate, blockstate, false); +- this.generateBox(worldgenlevel, boundingbox, 0, 10, i, 0, 11, i, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 12, 10, i, 12, 11, i, blockstate1, blockstate1, false); +- this.placeBlock(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), i, 13, 0, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), i, 13, 12, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), 0, 13, i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), 12, 13, i, boundingbox); ++ this.generateBox(level, box, i, 10, 0, i, 11, 0, iblockdata, iblockdata, false); ++ this.generateBox(level, box, i, 10, 12, i, 11, 12, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 0, 10, i, 0, 11, i, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 12, 10, i, 12, 11, i, iblockdata1, iblockdata1, false); ++ this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, 13, 0, box); ++ this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, 13, 12, box); ++ this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), 0, 13, i, box); ++ this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), 12, 13, i, box); + if (i != 11) { +- this.placeBlock(worldgenlevel, blockstate, i + 1, 13, 0, boundingbox); +- this.placeBlock(worldgenlevel, blockstate, i + 1, 13, 12, boundingbox); +- this.placeBlock(worldgenlevel, blockstate1, 0, 13, i + 1, boundingbox); +- this.placeBlock(worldgenlevel, blockstate1, 12, 13, i + 1, boundingbox); ++ this.placeBlock(level, iblockdata, i + 1, 13, 0, box); ++ this.placeBlock(level, iblockdata, i + 1, 13, 12, box); ++ this.placeBlock(level, iblockdata1, 0, 13, i + 1, box); ++ this.placeBlock(level, iblockdata1, 12, 13, i + 1, box); + } + } + +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.EAST, true), 0, 13, 0, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.SOUTH, true)).setValue(FenceBlock.EAST, true), 0, 13, 12, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.SOUTH, true)).setValue(FenceBlock.WEST, true), 12, 13, 12, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.WEST, true), 12, 13, 0, boundingbox); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.EAST, true), 0, 13, 0, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.SOUTH, true)).setValue(FenceBlock.EAST, true), 0, 13, 12, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.SOUTH, true)).setValue(FenceBlock.WEST, true), 12, 13, 12, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.WEST, true), 12, 13, 0, box); + + for (i = 3; i <= 9; i += 2) { +- this.generateBox(worldgenlevel, boundingbox, 1, 7, i, 1, 8, i, blockstate2, blockstate2, false); +- this.generateBox(worldgenlevel, boundingbox, 11, 7, i, 11, 8, i, blockstate3, blockstate3, false); ++ this.generateBox(level, box, 1, 7, i, 1, 8, i, iblockdata2, iblockdata2, false); ++ this.generateBox(level, box, 11, 7, i, 11, 8, i, iblockdata3, iblockdata3, false); + } + +- BlockState blockstate4 = (BlockState) Blocks.NETHER_BRICK_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.NORTH); ++ IBlockData iblockdata4 = (IBlockData) Blocks.NETHER_BRICK_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.NORTH); + + int j; + int k; +@@ -1023,68 +997,68 @@ + int l = j + 4; + + for (k = 5; k <= 7; ++k) { +- this.placeBlock(worldgenlevel, blockstate4, k, 5 + j, l, boundingbox); ++ this.placeBlock(level, iblockdata4, k, 5 + j, l, box); + } + + if (l >= 5 && l <= 8) { +- this.generateBox(worldgenlevel, boundingbox, 5, 5, l, 7, j + 4, l, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 5, l, 7, j + 4, l, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + } else if (l >= 9 && l <= 10) { +- this.generateBox(worldgenlevel, boundingbox, 5, 8, l, 7, j + 4, l, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 8, l, 7, j + 4, l, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + } + + if (j >= 1) { +- this.generateBox(worldgenlevel, boundingbox, 5, 6 + j, l, 7, 9 + j, l, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 6 + j, l, 7, 9 + j, l, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); + } + } + + for (j = 5; j <= 7; ++j) { +- this.placeBlock(worldgenlevel, blockstate4, j, 12, 11, boundingbox); ++ this.placeBlock(level, iblockdata4, j, 12, 11, box); + } + +- this.generateBox(worldgenlevel, boundingbox, 5, 6, 7, 5, 7, 7, blockstate3, blockstate3, false); +- this.generateBox(worldgenlevel, boundingbox, 7, 6, 7, 7, 7, 7, blockstate2, blockstate2, false); +- this.generateBox(worldgenlevel, boundingbox, 5, 13, 12, 7, 13, 12, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 2, 5, 2, 3, 5, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 2, 5, 9, 3, 5, 10, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 2, 5, 4, 2, 5, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 9, 5, 2, 10, 5, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 9, 5, 9, 10, 5, 10, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 10, 5, 4, 10, 5, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- BlockState blockstate5 = (BlockState) blockstate4.setValue(StairBlock.FACING, Direction.EAST); +- BlockState blockstate6 = (BlockState) blockstate4.setValue(StairBlock.FACING, Direction.WEST); ++ this.generateBox(level, box, 5, 6, 7, 5, 7, 7, iblockdata3, iblockdata3, false); ++ this.generateBox(level, box, 7, 6, 7, 7, 7, 7, iblockdata2, iblockdata2, false); ++ this.generateBox(level, box, 5, 13, 12, 7, 13, 12, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 5, 2, 3, 5, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 5, 9, 3, 5, 10, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 5, 4, 2, 5, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 9, 5, 2, 10, 5, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 9, 5, 9, 10, 5, 10, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 10, 5, 4, 10, 5, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ IBlockData iblockdata5 = (IBlockData) iblockdata4.setValue(StairBlock.FACING, Direction.EAST); ++ IBlockData iblockdata6 = (IBlockData) iblockdata4.setValue(StairBlock.FACING, Direction.WEST); + +- this.placeBlock(worldgenlevel, blockstate6, 4, 5, 2, boundingbox); +- this.placeBlock(worldgenlevel, blockstate6, 4, 5, 3, boundingbox); +- this.placeBlock(worldgenlevel, blockstate6, 4, 5, 9, boundingbox); +- this.placeBlock(worldgenlevel, blockstate6, 4, 5, 10, boundingbox); +- this.placeBlock(worldgenlevel, blockstate5, 8, 5, 2, boundingbox); +- this.placeBlock(worldgenlevel, blockstate5, 8, 5, 3, boundingbox); +- this.placeBlock(worldgenlevel, blockstate5, 8, 5, 9, boundingbox); +- this.placeBlock(worldgenlevel, blockstate5, 8, 5, 10, boundingbox); +- this.generateBox(worldgenlevel, boundingbox, 3, 4, 4, 4, 4, 8, Blocks.SOUL_SAND.defaultBlockState(), Blocks.SOUL_SAND.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 8, 4, 4, 9, 4, 8, Blocks.SOUL_SAND.defaultBlockState(), Blocks.SOUL_SAND.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 3, 5, 4, 4, 5, 8, Blocks.NETHER_WART.defaultBlockState(), Blocks.NETHER_WART.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 8, 5, 4, 9, 5, 8, Blocks.NETHER_WART.defaultBlockState(), Blocks.NETHER_WART.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 4, 2, 0, 8, 2, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 2, 4, 12, 2, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 4, 0, 0, 8, 1, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 4, 0, 9, 8, 1, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 4, 3, 1, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 9, 0, 4, 12, 1, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.placeBlock(level, iblockdata6, 4, 5, 2, box); ++ this.placeBlock(level, iblockdata6, 4, 5, 3, box); ++ this.placeBlock(level, iblockdata6, 4, 5, 9, box); ++ this.placeBlock(level, iblockdata6, 4, 5, 10, box); ++ this.placeBlock(level, iblockdata5, 8, 5, 2, box); ++ this.placeBlock(level, iblockdata5, 8, 5, 3, box); ++ this.placeBlock(level, iblockdata5, 8, 5, 9, box); ++ this.placeBlock(level, iblockdata5, 8, 5, 10, box); ++ this.generateBox(level, box, 3, 4, 4, 4, 4, 8, Blocks.SOUL_SAND.defaultBlockState(), Blocks.SOUL_SAND.defaultBlockState(), false); ++ this.generateBox(level, box, 8, 4, 4, 9, 4, 8, Blocks.SOUL_SAND.defaultBlockState(), Blocks.SOUL_SAND.defaultBlockState(), false); ++ this.generateBox(level, box, 3, 5, 4, 4, 5, 8, Blocks.NETHER_WART.defaultBlockState(), Blocks.NETHER_WART.defaultBlockState(), false); ++ this.generateBox(level, box, 8, 5, 4, 9, 5, 8, Blocks.NETHER_WART.defaultBlockState(), Blocks.NETHER_WART.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 2, 0, 8, 2, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 4, 12, 2, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 0, 0, 8, 1, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 0, 9, 8, 1, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 0, 4, 3, 1, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 9, 0, 4, 12, 1, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + + int i1; + + for (k = 4; k <= 8; ++k) { + for (i1 = 0; i1 <= 2; ++i1) { +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), k, -1, i1, boundingbox); +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), k, -1, 12 - i1, boundingbox); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), k, -1, i1, box); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), k, -1, 12 - i1, box); + } + } + + for (k = 0; k <= 2; ++k) { + for (i1 = 4; i1 <= 8; ++i1) { +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), k, -1, i1, boundingbox); +- this.fillColumnDown(worldgenlevel, Blocks.NETHER_BRICKS.defaultBlockState(), 12 - k, -1, i1, boundingbox); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), k, -1, i1, box); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), 12 - k, -1, i1, box); + } + } + +@@ -1098,33 +1072,31 @@ + private static final int DEPTH = 8; + private final int selfSeed; + +- public BridgeEndFiller(int i, RandomSource randomsource, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.NETHER_FORTRESS_BRIDGE_END_FILLER, i, boundingbox); +- this.setOrientation(direction); +- this.selfSeed = randomsource.nextInt(); ++ public BridgeEndFiller(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_BRIDGE_END_FILLER, genDepth, box); ++ this.setOrientation(orientation); ++ this.selfSeed = random.nextInt(); + } + +- public BridgeEndFiller(CompoundTag compoundtag) { +- super(StructurePieceType.NETHER_FORTRESS_BRIDGE_END_FILLER, compoundtag); +- this.selfSeed = compoundtag.getInt("Seed"); ++ public BridgeEndFiller(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_BRIDGE_END_FILLER, tag); ++ this.selfSeed = tag.getInt("Seed"); + } + +- public static NetherFortressPieces.BridgeEndFiller createPiece(StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -1, -3, 0, 5, 10, 8, direction); ++ public static NetherFortressPieces.BridgeEndFiller createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -3, 0, 5, 10, 8, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new NetherFortressPieces.BridgeEndFiller(l, randomsource, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.BridgeEndFiller(genDepth, random, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- super.addAdditionalSaveData(structurepieceserializationcontext, compoundtag); +- compoundtag.putInt("Seed", this.selfSeed); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putInt("Seed", this.selfSeed); + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { + RandomSource randomsource1 = RandomSource.create((long) this.selfSeed); + + int i; +@@ -1134,24 +1106,24 @@ + for (j = 0; j <= 4; ++j) { + for (k = 3; k <= 4; ++k) { + i = randomsource1.nextInt(8); +- this.generateBox(worldgenlevel, boundingbox, j, k, 0, j, k, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, j, k, 0, j, k, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + } + } + + j = randomsource1.nextInt(8); +- this.generateBox(worldgenlevel, boundingbox, 0, 5, 0, 0, 5, j, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 5, 0, 0, 5, j, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + j = randomsource1.nextInt(8); +- this.generateBox(worldgenlevel, boundingbox, 4, 5, 0, 4, 5, j, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 5, 0, 4, 5, j, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + + for (j = 0; j <= 4; ++j) { + k = randomsource1.nextInt(5); +- this.generateBox(worldgenlevel, boundingbox, j, 2, 0, j, 2, k, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, j, 2, 0, j, 2, k, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + } + + for (j = 0; j <= 4; ++j) { + for (k = 0; k <= 1; ++k) { + i = randomsource1.nextInt(3); +- this.generateBox(worldgenlevel, boundingbox, j, k, 0, j, k, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, j, k, 0, j, k, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + } + } + +@@ -1165,61 +1137,60 @@ + public List availableCastlePieces; + public final List pendingChildren = Lists.newArrayList(); + +- public StartPiece(RandomSource randomsource, int i, int j) { +- super(i, j, getRandomHorizontalDirection(randomsource)); ++ public StartPiece(RandomSource random, int x, int z) { ++ super(x, z, getRandomHorizontalDirection(random)); + this.availableBridgePieces = Lists.newArrayList(); +- NetherFortressPieces.PieceWeight[] anetherfortresspieces_pieceweight = NetherFortressPieces.BRIDGE_PIECE_WEIGHTS; +- int k = anetherfortresspieces_pieceweight.length; ++ NetherFortressPieces.PieceWeight[] anetherfortresspieces_n = NetherFortressPieces.BRIDGE_PIECE_WEIGHTS; ++ int k = anetherfortresspieces_n.length; + +- NetherFortressPieces.PieceWeight netherfortresspieces_pieceweight; ++ NetherFortressPieces.PieceWeight netherfortresspieces_n; + int l; + + for (l = 0; l < k; ++l) { +- netherfortresspieces_pieceweight = anetherfortresspieces_pieceweight[l]; +- netherfortresspieces_pieceweight.placeCount = 0; +- this.availableBridgePieces.add(netherfortresspieces_pieceweight); ++ netherfortresspieces_n = anetherfortresspieces_n[l]; ++ netherfortresspieces_n.placeCount = 0; ++ this.availableBridgePieces.add(netherfortresspieces_n); + } + + this.availableCastlePieces = Lists.newArrayList(); +- anetherfortresspieces_pieceweight = NetherFortressPieces.CASTLE_PIECE_WEIGHTS; +- k = anetherfortresspieces_pieceweight.length; ++ anetherfortresspieces_n = NetherFortressPieces.CASTLE_PIECE_WEIGHTS; ++ k = anetherfortresspieces_n.length; + + for (l = 0; l < k; ++l) { +- netherfortresspieces_pieceweight = anetherfortresspieces_pieceweight[l]; +- netherfortresspieces_pieceweight.placeCount = 0; +- this.availableCastlePieces.add(netherfortresspieces_pieceweight); ++ netherfortresspieces_n = anetherfortresspieces_n[l]; ++ netherfortresspieces_n.placeCount = 0; ++ this.availableCastlePieces.add(netherfortresspieces_n); + } + + } + +- public StartPiece(CompoundTag compoundtag) { +- super(StructurePieceType.NETHER_FORTRESS_START, compoundtag); ++ public StartPiece(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_START, tag); + } + } + + private abstract static class NetherBridgePiece extends StructurePiece { + +- protected NetherBridgePiece(StructurePieceType structurepiecetype, int i, BoundingBox boundingbox) { +- super(structurepiecetype, i, boundingbox); ++ protected NetherBridgePiece(StructurePieceType type, int genDepth, BoundingBox boundingBox) { ++ super(type, genDepth, boundingBox); + } + +- public NetherBridgePiece(StructurePieceType structurepiecetype, CompoundTag compoundtag) { +- super(structurepiecetype, compoundtag); ++ public NetherBridgePiece(StructurePieceType type, CompoundTag tag) { ++ super(type, tag); + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) {} ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) {} + +- private int updatePieceWeight(List list) { ++ private int updatePieceWeight(List weights) { + boolean flag = false; + int i = 0; + +- NetherFortressPieces.PieceWeight netherfortresspieces_pieceweight; ++ NetherFortressPieces.PieceWeight netherfortresspieces_n; + +- for (Iterator iterator = list.iterator(); iterator.hasNext(); i += netherfortresspieces_pieceweight.weight) { +- netherfortresspieces_pieceweight = (NetherFortressPieces.PieceWeight) iterator.next(); +- if (netherfortresspieces_pieceweight.maxPlaceCount > 0 && netherfortresspieces_pieceweight.placeCount < netherfortresspieces_pieceweight.maxPlaceCount) { ++ for (Iterator iterator = weights.iterator(); iterator.hasNext(); i += netherfortresspieces_n.weight) { ++ netherfortresspieces_n = (NetherFortressPieces.PieceWeight) iterator.next(); ++ if (netherfortresspieces_n.maxPlaceCount > 0 && netherfortresspieces_n.placeCount < netherfortresspieces_n.maxPlaceCount) { + flag = true; + } + } +@@ -1227,78 +1198,78 @@ + return flag ? i : -1; + } + +- private NetherFortressPieces.NetherBridgePiece generatePiece(NetherFortressPieces.StartPiece netherfortresspieces_startpiece, List list, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction, int l) { +- int i1 = this.updatePieceWeight(list); +- boolean flag = i1 > 0 && l <= 30; ++ private NetherFortressPieces.NetherBridgePiece generatePiece(NetherFortressPieces.StartPiece startPiece, List weights, StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ int i1 = this.updatePieceWeight(weights); ++ boolean flag = i1 > 0 && genDepth <= 30; + int j1 = 0; + + while (j1 < 5 && flag) { + ++j1; +- int k1 = randomsource.nextInt(i1); +- Iterator iterator = list.iterator(); ++ int k1 = random.nextInt(i1); ++ Iterator iterator = weights.iterator(); + + while (iterator.hasNext()) { +- NetherFortressPieces.PieceWeight netherfortresspieces_pieceweight = (NetherFortressPieces.PieceWeight) iterator.next(); ++ NetherFortressPieces.PieceWeight netherfortresspieces_n = (NetherFortressPieces.PieceWeight) iterator.next(); + +- k1 -= netherfortresspieces_pieceweight.weight; ++ k1 -= netherfortresspieces_n.weight; + if (k1 < 0) { +- if (!netherfortresspieces_pieceweight.doPlace(l) || netherfortresspieces_pieceweight == netherfortresspieces_startpiece.previousPiece && !netherfortresspieces_pieceweight.allowInRow) { ++ if (!netherfortresspieces_n.doPlace(genDepth) || netherfortresspieces_n == startPiece.previousPiece && !netherfortresspieces_n.allowInRow) { + break; + } + +- NetherFortressPieces.NetherBridgePiece netherfortresspieces_netherbridgepiece = NetherFortressPieces.findAndCreateBridgePieceFactory(netherfortresspieces_pieceweight, structurepieceaccessor, randomsource, i, j, k, direction, l); ++ NetherFortressPieces.NetherBridgePiece netherfortresspieces_m = NetherFortressPieces.findAndCreateBridgePieceFactory(netherfortresspieces_n, pieces, random, x, y, z, orientation, genDepth); + +- if (netherfortresspieces_netherbridgepiece != null) { +- ++netherfortresspieces_pieceweight.placeCount; +- netherfortresspieces_startpiece.previousPiece = netherfortresspieces_pieceweight; +- if (!netherfortresspieces_pieceweight.isValid()) { +- list.remove(netherfortresspieces_pieceweight); ++ if (netherfortresspieces_m != null) { ++ ++netherfortresspieces_n.placeCount; ++ startPiece.previousPiece = netherfortresspieces_n; ++ if (!netherfortresspieces_n.isValid()) { ++ weights.remove(netherfortresspieces_n); + } + +- return netherfortresspieces_netherbridgepiece; ++ return netherfortresspieces_m; + } + } + } + } + +- return NetherFortressPieces.BridgeEndFiller.createPiece(structurepieceaccessor, randomsource, i, j, k, direction, l); ++ return NetherFortressPieces.BridgeEndFiller.createPiece(pieces, random, x, y, z, orientation, genDepth); + } + +- private StructurePiece generateAndAddPiece(NetherFortressPieces.StartPiece netherfortresspieces_startpiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, @Nullable Direction direction, int l, boolean flag) { +- if (Math.abs(i - netherfortresspieces_startpiece.getBoundingBox().minX()) <= 112 && Math.abs(k - netherfortresspieces_startpiece.getBoundingBox().minZ()) <= 112) { +- List list = netherfortresspieces_startpiece.availableBridgePieces; ++ private StructurePiece generateAndAddPiece(NetherFortressPieces.StartPiece startPiece, StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, @Nullable Direction orientation, int genDepth, boolean castlePiece) { ++ if (Math.abs(x - startPiece.getBoundingBox().minX()) <= 112 && Math.abs(z - startPiece.getBoundingBox().minZ()) <= 112) { ++ List list = startPiece.availableBridgePieces; + +- if (flag) { +- list = netherfortresspieces_startpiece.availableCastlePieces; ++ if (castlePiece) { ++ list = startPiece.availableCastlePieces; + } + +- NetherFortressPieces.NetherBridgePiece netherfortresspieces_netherbridgepiece = this.generatePiece(netherfortresspieces_startpiece, list, structurepieceaccessor, randomsource, i, j, k, direction, l + 1); ++ NetherFortressPieces.NetherBridgePiece netherfortresspieces_m = this.generatePiece(startPiece, list, pieces, random, x, y, z, orientation, genDepth + 1); + +- if (netherfortresspieces_netherbridgepiece != null) { +- structurepieceaccessor.addPiece(netherfortresspieces_netherbridgepiece); +- netherfortresspieces_startpiece.pendingChildren.add(netherfortresspieces_netherbridgepiece); ++ if (netherfortresspieces_m != null) { ++ pieces.addPiece(netherfortresspieces_m); ++ startPiece.pendingChildren.add(netherfortresspieces_m); + } + +- return netherfortresspieces_netherbridgepiece; ++ return netherfortresspieces_m; + } else { +- return NetherFortressPieces.BridgeEndFiller.createPiece(structurepieceaccessor, randomsource, i, j, k, direction, l); ++ return NetherFortressPieces.BridgeEndFiller.createPiece(pieces, random, x, y, z, orientation, genDepth); + } + } + + @Nullable +- protected StructurePiece generateChildForward(NetherFortressPieces.StartPiece netherfortresspieces_startpiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, boolean flag) { +- Direction direction = this.getOrientation(); ++ protected StructurePiece generateChildForward(NetherFortressPieces.StartPiece startPiece, StructurePieceAccessor pieces, RandomSource random, int offsetX, int offsetY, boolean castlePiece) { ++ Direction enumdirection = this.getOrientation(); + +- if (direction != null) { +- switch (direction) { ++ if (enumdirection != null) { ++ switch (enumdirection) { + case NORTH: +- return this.generateAndAddPiece(netherfortresspieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + i, this.boundingBox.minY() + j, this.boundingBox.minZ() - 1, direction, this.getGenDepth(), flag); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() - 1, enumdirection, this.getGenDepth(), castlePiece); + case SOUTH: +- return this.generateAndAddPiece(netherfortresspieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + i, this.boundingBox.minY() + j, this.boundingBox.maxZ() + 1, direction, this.getGenDepth(), flag); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.maxZ() + 1, enumdirection, this.getGenDepth(), castlePiece); + case WEST: +- return this.generateAndAddPiece(netherfortresspieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.minX() - 1, this.boundingBox.minY() + j, this.boundingBox.minZ() + i, direction, this.getGenDepth(), flag); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, enumdirection, this.getGenDepth(), castlePiece); + case EAST: +- return this.generateAndAddPiece(netherfortresspieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.maxX() + 1, this.boundingBox.minY() + j, this.boundingBox.minZ() + i, direction, this.getGenDepth(), flag); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, enumdirection, this.getGenDepth(), castlePiece); + } + } + +@@ -1306,19 +1277,19 @@ + } + + @Nullable +- protected StructurePiece generateChildLeft(NetherFortressPieces.StartPiece netherfortresspieces_startpiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, boolean flag) { +- Direction direction = this.getOrientation(); ++ protected StructurePiece generateChildLeft(NetherFortressPieces.StartPiece startPiece, StructurePieceAccessor pieces, RandomSource random, int offsetY, int offsetX, boolean castlePiece) { ++ Direction enumdirection = this.getOrientation(); + +- if (direction != null) { +- switch (direction) { ++ if (enumdirection != null) { ++ switch (enumdirection) { + case NORTH: +- return this.generateAndAddPiece(netherfortresspieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.minX() - 1, this.boundingBox.minY() + i, this.boundingBox.minZ() + j, Direction.WEST, this.getGenDepth(), flag); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, Direction.WEST, this.getGenDepth(), castlePiece); + case SOUTH: +- return this.generateAndAddPiece(netherfortresspieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.minX() - 1, this.boundingBox.minY() + i, this.boundingBox.minZ() + j, Direction.WEST, this.getGenDepth(), flag); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, Direction.WEST, this.getGenDepth(), castlePiece); + case WEST: +- return this.generateAndAddPiece(netherfortresspieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + j, this.boundingBox.minY() + i, this.boundingBox.minZ() - 1, Direction.NORTH, this.getGenDepth(), flag); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() - 1, Direction.NORTH, this.getGenDepth(), castlePiece); + case EAST: +- return this.generateAndAddPiece(netherfortresspieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + j, this.boundingBox.minY() + i, this.boundingBox.minZ() - 1, Direction.NORTH, this.getGenDepth(), flag); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() - 1, Direction.NORTH, this.getGenDepth(), castlePiece); + } + } + +@@ -1326,27 +1297,27 @@ + } + + @Nullable +- protected StructurePiece generateChildRight(NetherFortressPieces.StartPiece netherfortresspieces_startpiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, boolean flag) { +- Direction direction = this.getOrientation(); ++ protected StructurePiece generateChildRight(NetherFortressPieces.StartPiece startPiece, StructurePieceAccessor pieces, RandomSource random, int offsetY, int offsetX, boolean castlePiece) { ++ Direction enumdirection = this.getOrientation(); + +- if (direction != null) { +- switch (direction) { ++ if (enumdirection != null) { ++ switch (enumdirection) { + case NORTH: +- return this.generateAndAddPiece(netherfortresspieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.maxX() + 1, this.boundingBox.minY() + i, this.boundingBox.minZ() + j, Direction.EAST, this.getGenDepth(), flag); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, Direction.EAST, this.getGenDepth(), castlePiece); + case SOUTH: +- return this.generateAndAddPiece(netherfortresspieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.maxX() + 1, this.boundingBox.minY() + i, this.boundingBox.minZ() + j, Direction.EAST, this.getGenDepth(), flag); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, Direction.EAST, this.getGenDepth(), castlePiece); + case WEST: +- return this.generateAndAddPiece(netherfortresspieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + j, this.boundingBox.minY() + i, this.boundingBox.maxZ() + 1, Direction.SOUTH, this.getGenDepth(), flag); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.maxZ() + 1, Direction.SOUTH, this.getGenDepth(), castlePiece); + case EAST: +- return this.generateAndAddPiece(netherfortresspieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + j, this.boundingBox.minY() + i, this.boundingBox.maxZ() + 1, Direction.SOUTH, this.getGenDepth(), flag); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.maxZ() + 1, Direction.SOUTH, this.getGenDepth(), castlePiece); + } + } + + return null; + } + +- protected static boolean isOkBox(BoundingBox boundingbox) { +- return boundingbox != null && boundingbox.minY() > 10; ++ protected static boolean isOkBox(BoundingBox box) { ++ return box != null && box.minY() > 10; + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java.patch new file mode 100644 index 0000000000..157fe81654 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java.patch @@ -0,0 +1,352 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java +@@ -13,8 +13,8 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.util.valueproviders.ConstantInt; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.monster.Drowned; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.ChunkPos; +@@ -26,9 +26,7 @@ + import net.minecraft.world.level.block.ChestBlock; + import net.minecraft.world.level.block.Mirror; + import net.minecraft.world.level.block.Rotation; +-import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.entity.ChestBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.levelgen.Heightmap; + import net.minecraft.world.level.levelgen.structure.BoundingBox; +@@ -36,12 +34,12 @@ + import net.minecraft.world.level.levelgen.structure.TemplateStructurePiece; + import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; + import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceType; +-import net.minecraft.world.level.levelgen.structure.templatesystem.AlwaysTrueTest; + import net.minecraft.world.level.levelgen.structure.templatesystem.BlockIgnoreProcessor; + import net.minecraft.world.level.levelgen.structure.templatesystem.BlockMatchTest; + import net.minecraft.world.level.levelgen.structure.templatesystem.BlockRotProcessor; + import net.minecraft.world.level.levelgen.structure.templatesystem.CappedProcessor; +-import net.minecraft.world.level.levelgen.structure.templatesystem.PosAlwaysTrueTest; ++import net.minecraft.world.level.levelgen.structure.templatesystem.DefinedStructureTestTrue; ++import net.minecraft.world.level.levelgen.structure.templatesystem.PosRuleTestTrue; + import net.minecraft.world.level.levelgen.structure.templatesystem.ProcessorRule; + import net.minecraft.world.level.levelgen.structure.templatesystem.RuleProcessor; + import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; +@@ -67,84 +65,84 @@ + + public OceanRuinPieces() {} + +- private static StructureProcessor archyRuleProcessor(Block block, Block block1, ResourceLocation resourcelocation) { +- return new CappedProcessor(new RuleProcessor(List.of(new ProcessorRule(new BlockMatchTest(block), AlwaysTrueTest.INSTANCE, PosAlwaysTrueTest.INSTANCE, block1.defaultBlockState(), new AppendLoot(resourcelocation)))), ConstantInt.of(5)); ++ private static StructureProcessor archyRuleProcessor(Block input, Block output, ResourceLocation lootTable) { ++ return new CappedProcessor(new RuleProcessor(List.of(new ProcessorRule(new BlockMatchTest(input), DefinedStructureTestTrue.INSTANCE, PosRuleTestTrue.INSTANCE, output.defaultBlockState(), new AppendLoot(lootTable)))), ConstantInt.of(5)); + } + +- private static ResourceLocation getSmallWarmRuin(RandomSource randomsource) { +- return (ResourceLocation) Util.getRandom((Object[]) OceanRuinPieces.WARM_RUINS, randomsource); ++ private static ResourceLocation getSmallWarmRuin(RandomSource random) { ++ return (ResourceLocation) Util.getRandom((Object[]) OceanRuinPieces.WARM_RUINS, random); + } + +- private static ResourceLocation getBigWarmRuin(RandomSource randomsource) { +- return (ResourceLocation) Util.getRandom((Object[]) OceanRuinPieces.BIG_WARM_RUINS, randomsource); ++ private static ResourceLocation getBigWarmRuin(RandomSource random) { ++ return (ResourceLocation) Util.getRandom((Object[]) OceanRuinPieces.BIG_WARM_RUINS, random); + } + +- public static void addPieces(StructureTemplateManager structuretemplatemanager, BlockPos blockpos, Rotation rotation, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, OceanRuinStructure oceanruinstructure) { +- boolean flag = randomsource.nextFloat() <= oceanruinstructure.largeProbability; ++ public static void addPieces(StructureTemplateManager structureTemplateManager, BlockPos pos, Rotation rotation, StructurePieceAccessor structurePieceAccessor, RandomSource random, OceanRuinStructure structure) { ++ boolean flag = random.nextFloat() <= structure.largeProbability; + float f = flag ? 0.9F : 0.8F; + +- addPiece(structuretemplatemanager, blockpos, rotation, structurepieceaccessor, randomsource, oceanruinstructure, flag, f); +- if (flag && randomsource.nextFloat() <= oceanruinstructure.clusterProbability) { +- addClusterRuins(structuretemplatemanager, randomsource, rotation, blockpos, oceanruinstructure, structurepieceaccessor); ++ addPiece(structureTemplateManager, pos, rotation, structurePieceAccessor, random, structure, flag, f); ++ if (flag && random.nextFloat() <= structure.clusterProbability) { ++ addClusterRuins(structureTemplateManager, random, rotation, pos, structure, structurePieceAccessor); + } + + } + +- private static void addClusterRuins(StructureTemplateManager structuretemplatemanager, RandomSource randomsource, Rotation rotation, BlockPos blockpos, OceanRuinStructure oceanruinstructure, StructurePieceAccessor structurepieceaccessor) { +- BlockPos blockpos1 = new BlockPos(blockpos.getX(), 90, blockpos.getZ()); +- BlockPos blockpos2 = StructureTemplate.transform(new BlockPos(15, 0, 15), Mirror.NONE, rotation, BlockPos.ZERO).offset(blockpos1); +- BoundingBox boundingbox = BoundingBox.fromCorners(blockpos1, blockpos2); +- BlockPos blockpos3 = new BlockPos(Math.min(blockpos1.getX(), blockpos2.getX()), blockpos1.getY(), Math.min(blockpos1.getZ(), blockpos2.getZ())); +- List list = allPositions(randomsource, blockpos3); +- int i = Mth.nextInt(randomsource, 4, 8); ++ private static void addClusterRuins(StructureTemplateManager structureTemplateManager, RandomSource random, Rotation rotation, BlockPos pos, OceanRuinStructure structure, StructurePieceAccessor structurePieceAccessor) { ++ BlockPos blockposition1 = new BlockPos(pos.getX(), 90, pos.getZ()); ++ BlockPos blockposition2 = StructureTemplate.transform(new BlockPos(15, 0, 15), Mirror.NONE, rotation, BlockPos.ZERO).offset(blockposition1); ++ BoundingBox structureboundingbox = BoundingBox.fromCorners(blockposition1, blockposition2); ++ BlockPos blockposition3 = new BlockPos(Math.min(blockposition1.getX(), blockposition2.getX()), blockposition1.getY(), Math.min(blockposition1.getZ(), blockposition2.getZ())); ++ List list = allPositions(random, blockposition3); ++ int i = Mth.nextInt(random, 4, 8); + + for (int j = 0; j < i; ++j) { + if (!list.isEmpty()) { +- int k = randomsource.nextInt(list.size()); +- BlockPos blockpos4 = (BlockPos) list.remove(k); +- Rotation rotation1 = Rotation.getRandom(randomsource); +- BlockPos blockpos5 = StructureTemplate.transform(new BlockPos(5, 0, 6), Mirror.NONE, rotation1, BlockPos.ZERO).offset(blockpos4); +- BoundingBox boundingbox1 = BoundingBox.fromCorners(blockpos4, blockpos5); ++ int k = random.nextInt(list.size()); ++ BlockPos blockposition4 = (BlockPos) list.remove(k); ++ Rotation enumblockrotation1 = Rotation.getRandom(random); ++ BlockPos blockposition5 = StructureTemplate.transform(new BlockPos(5, 0, 6), Mirror.NONE, enumblockrotation1, BlockPos.ZERO).offset(blockposition4); ++ BoundingBox structureboundingbox1 = BoundingBox.fromCorners(blockposition4, blockposition5); + +- if (!boundingbox1.intersects(boundingbox)) { +- addPiece(structuretemplatemanager, blockpos4, rotation1, structurepieceaccessor, randomsource, oceanruinstructure, false, 0.8F); ++ if (!structureboundingbox1.intersects(structureboundingbox)) { ++ addPiece(structureTemplateManager, blockposition4, enumblockrotation1, structurePieceAccessor, random, structure, false, 0.8F); + } + } + } + + } + +- private static List allPositions(RandomSource randomsource, BlockPos blockpos) { ++ private static List allPositions(RandomSource random, BlockPos pos) { + List list = Lists.newArrayList(); + +- list.add(blockpos.offset(-16 + Mth.nextInt(randomsource, 1, 8), 0, 16 + Mth.nextInt(randomsource, 1, 7))); +- list.add(blockpos.offset(-16 + Mth.nextInt(randomsource, 1, 8), 0, Mth.nextInt(randomsource, 1, 7))); +- list.add(blockpos.offset(-16 + Mth.nextInt(randomsource, 1, 8), 0, -16 + Mth.nextInt(randomsource, 4, 8))); +- list.add(blockpos.offset(Mth.nextInt(randomsource, 1, 7), 0, 16 + Mth.nextInt(randomsource, 1, 7))); +- list.add(blockpos.offset(Mth.nextInt(randomsource, 1, 7), 0, -16 + Mth.nextInt(randomsource, 4, 6))); +- list.add(blockpos.offset(16 + Mth.nextInt(randomsource, 1, 7), 0, 16 + Mth.nextInt(randomsource, 3, 8))); +- list.add(blockpos.offset(16 + Mth.nextInt(randomsource, 1, 7), 0, Mth.nextInt(randomsource, 1, 7))); +- list.add(blockpos.offset(16 + Mth.nextInt(randomsource, 1, 7), 0, -16 + Mth.nextInt(randomsource, 4, 8))); ++ list.add(pos.offset(-16 + Mth.nextInt(random, 1, 8), 0, 16 + Mth.nextInt(random, 1, 7))); ++ list.add(pos.offset(-16 + Mth.nextInt(random, 1, 8), 0, Mth.nextInt(random, 1, 7))); ++ list.add(pos.offset(-16 + Mth.nextInt(random, 1, 8), 0, -16 + Mth.nextInt(random, 4, 8))); ++ list.add(pos.offset(Mth.nextInt(random, 1, 7), 0, 16 + Mth.nextInt(random, 1, 7))); ++ list.add(pos.offset(Mth.nextInt(random, 1, 7), 0, -16 + Mth.nextInt(random, 4, 6))); ++ list.add(pos.offset(16 + Mth.nextInt(random, 1, 7), 0, 16 + Mth.nextInt(random, 3, 8))); ++ list.add(pos.offset(16 + Mth.nextInt(random, 1, 7), 0, Mth.nextInt(random, 1, 7))); ++ list.add(pos.offset(16 + Mth.nextInt(random, 1, 7), 0, -16 + Mth.nextInt(random, 4, 8))); + return list; + } + +- private static void addPiece(StructureTemplateManager structuretemplatemanager, BlockPos blockpos, Rotation rotation, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, OceanRuinStructure oceanruinstructure, boolean flag, float f) { +- switch (oceanruinstructure.biomeTemp) { ++ private static void addPiece(StructureTemplateManager structureTemplateManager, BlockPos pos, Rotation rotation, StructurePieceAccessor structurePieceAccessor, RandomSource random, OceanRuinStructure structure, boolean isLarge, float integrity) { ++ switch (structure.biomeTemp) { + case WARM: + default: +- ResourceLocation resourcelocation = flag ? getBigWarmRuin(randomsource) : getSmallWarmRuin(randomsource); ++ ResourceLocation minecraftkey = isLarge ? getBigWarmRuin(random) : getSmallWarmRuin(random); + +- structurepieceaccessor.addPiece(new OceanRuinPieces.OceanRuinPiece(structuretemplatemanager, resourcelocation, blockpos, rotation, f, oceanruinstructure.biomeTemp, flag)); ++ structurePieceAccessor.addPiece(new OceanRuinPieces.OceanRuinPiece(structureTemplateManager, minecraftkey, pos, rotation, integrity, structure.biomeTemp, isLarge)); + break; + case COLD: +- ResourceLocation[] aresourcelocation = flag ? OceanRuinPieces.BIG_RUINS_BRICK : OceanRuinPieces.RUINS_BRICK; +- ResourceLocation[] aresourcelocation1 = flag ? OceanRuinPieces.BIG_RUINS_CRACKED : OceanRuinPieces.RUINS_CRACKED; +- ResourceLocation[] aresourcelocation2 = flag ? OceanRuinPieces.BIG_RUINS_MOSSY : OceanRuinPieces.RUINS_MOSSY; +- int i = randomsource.nextInt(aresourcelocation.length); ++ ResourceLocation[] aminecraftkey = isLarge ? OceanRuinPieces.BIG_RUINS_BRICK : OceanRuinPieces.RUINS_BRICK; ++ ResourceLocation[] aminecraftkey1 = isLarge ? OceanRuinPieces.BIG_RUINS_CRACKED : OceanRuinPieces.RUINS_CRACKED; ++ ResourceLocation[] aminecraftkey2 = isLarge ? OceanRuinPieces.BIG_RUINS_MOSSY : OceanRuinPieces.RUINS_MOSSY; ++ int i = random.nextInt(aminecraftkey.length); + +- structurepieceaccessor.addPiece(new OceanRuinPieces.OceanRuinPiece(structuretemplatemanager, aresourcelocation[i], blockpos, rotation, f, oceanruinstructure.biomeTemp, flag)); +- structurepieceaccessor.addPiece(new OceanRuinPieces.OceanRuinPiece(structuretemplatemanager, aresourcelocation1[i], blockpos, rotation, 0.7F, oceanruinstructure.biomeTemp, flag)); +- structurepieceaccessor.addPiece(new OceanRuinPieces.OceanRuinPiece(structuretemplatemanager, aresourcelocation2[i], blockpos, rotation, 0.5F, oceanruinstructure.biomeTemp, flag)); ++ structurePieceAccessor.addPiece(new OceanRuinPieces.OceanRuinPiece(structureTemplateManager, aminecraftkey[i], pos, rotation, integrity, structure.biomeTemp, isLarge)); ++ structurePieceAccessor.addPiece(new OceanRuinPieces.OceanRuinPiece(structureTemplateManager, aminecraftkey1[i], pos, rotation, 0.7F, structure.biomeTemp, isLarge)); ++ structurePieceAccessor.addPiece(new OceanRuinPieces.OceanRuinPiece(structureTemplateManager, aminecraftkey2[i], pos, rotation, 0.5F, structure.biomeTemp, isLarge)); + } + + } +@@ -155,69 +153,75 @@ + private final float integrity; + private final boolean isLarge; + +- public OceanRuinPiece(StructureTemplateManager structuretemplatemanager, ResourceLocation resourcelocation, BlockPos blockpos, Rotation rotation, float f, OceanRuinStructure.Type oceanruinstructure_type, boolean flag) { +- super(StructurePieceType.OCEAN_RUIN, 0, structuretemplatemanager, resourcelocation, resourcelocation.toString(), makeSettings(rotation, f, oceanruinstructure_type), blockpos); +- this.integrity = f; +- this.biomeType = oceanruinstructure_type; +- this.isLarge = flag; ++ public OceanRuinPiece(StructureTemplateManager structureTemplateManager, ResourceLocation location, BlockPos pos, Rotation rotation, float integrity, OceanRuinStructure.Type biomeType, boolean isLarge) { ++ super(StructurePieceType.OCEAN_RUIN, 0, structureTemplateManager, location, location.toString(), makeSettings(rotation, integrity, biomeType), pos); ++ this.integrity = integrity; ++ this.biomeType = biomeType; ++ this.isLarge = isLarge; + } + +- private OceanRuinPiece(StructureTemplateManager structuretemplatemanager, CompoundTag compoundtag, Rotation rotation, float f, OceanRuinStructure.Type oceanruinstructure_type, boolean flag) { +- super(StructurePieceType.OCEAN_RUIN, compoundtag, structuretemplatemanager, (resourcelocation) -> { +- return makeSettings(rotation, f, oceanruinstructure_type); ++ private OceanRuinPiece(StructureTemplateManager structureTemplateManager, CompoundTag genDepth, Rotation rotation, float integrity, OceanRuinStructure.Type biomeType, boolean isLarge) { ++ super(StructurePieceType.OCEAN_RUIN, genDepth, structureTemplateManager, (minecraftkey) -> { ++ return makeSettings(rotation, integrity, biomeType); + }); +- this.integrity = f; +- this.biomeType = oceanruinstructure_type; +- this.isLarge = flag; ++ this.integrity = integrity; ++ this.biomeType = biomeType; ++ this.isLarge = isLarge; + } + +- private static StructurePlaceSettings makeSettings(Rotation rotation, float f, OceanRuinStructure.Type oceanruinstructure_type) { +- StructureProcessor structureprocessor = oceanruinstructure_type == OceanRuinStructure.Type.COLD ? OceanRuinPieces.COLD_SUSPICIOUS_BLOCK_PROCESSOR : OceanRuinPieces.WARM_SUSPICIOUS_BLOCK_PROCESSOR; ++ private static StructurePlaceSettings makeSettings(Rotation rotation, float integrity, OceanRuinStructure.Type structureType) { ++ StructureProcessor definedstructureprocessor = structureType == OceanRuinStructure.Type.COLD ? OceanRuinPieces.COLD_SUSPICIOUS_BLOCK_PROCESSOR : OceanRuinPieces.WARM_SUSPICIOUS_BLOCK_PROCESSOR; + +- return (new StructurePlaceSettings()).setRotation(rotation).setMirror(Mirror.NONE).addProcessor(new BlockRotProcessor(f)).addProcessor(BlockIgnoreProcessor.STRUCTURE_AND_AIR).addProcessor(structureprocessor); ++ return (new StructurePlaceSettings()).setRotation(rotation).setMirror(Mirror.NONE).addProcessor(new BlockRotProcessor(integrity)).addProcessor(BlockIgnoreProcessor.STRUCTURE_AND_AIR).addProcessor(definedstructureprocessor); + } + +- public static OceanRuinPieces.OceanRuinPiece create(StructureTemplateManager structuretemplatemanager, CompoundTag compoundtag) { +- Rotation rotation = Rotation.valueOf(compoundtag.getString("Rot")); +- float f = compoundtag.getFloat("Integrity"); +- OceanRuinStructure.Type oceanruinstructure_type = OceanRuinStructure.Type.valueOf(compoundtag.getString("BiomeType")); +- boolean flag = compoundtag.getBoolean("IsLarge"); ++ public static OceanRuinPieces.OceanRuinPiece create(StructureTemplateManager structureTemplateManager, CompoundTag tag) { ++ Rotation enumblockrotation = Rotation.valueOf(tag.getString("Rot")); ++ float f = tag.getFloat("Integrity"); ++ OceanRuinStructure.Type oceanruinstructure_a = OceanRuinStructure.Type.valueOf(tag.getString("BiomeType")); ++ boolean flag = tag.getBoolean("IsLarge"); + +- return new OceanRuinPieces.OceanRuinPiece(structuretemplatemanager, compoundtag, rotation, f, oceanruinstructure_type, flag); ++ return new OceanRuinPieces.OceanRuinPiece(structureTemplateManager, tag, enumblockrotation, f, oceanruinstructure_a, flag); + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- super.addAdditionalSaveData(structurepieceserializationcontext, compoundtag); +- compoundtag.putString("Rot", this.placeSettings.getRotation().name()); +- compoundtag.putFloat("Integrity", this.integrity); +- compoundtag.putString("BiomeType", this.biomeType.toString()); +- compoundtag.putBoolean("IsLarge", this.isLarge); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putString("Rot", this.placeSettings.getRotation().name()); ++ tag.putFloat("Integrity", this.integrity); ++ tag.putString("BiomeType", this.biomeType.toString()); ++ tag.putBoolean("IsLarge", this.isLarge); + } + + @Override +- @Override +- protected void handleDataMarker(String s, BlockPos blockpos, ServerLevelAccessor serverlevelaccessor, RandomSource randomsource, BoundingBox boundingbox) { +- if ("chest".equals(s)) { +- serverlevelaccessor.setBlock(blockpos, (BlockState) Blocks.CHEST.defaultBlockState().setValue(ChestBlock.WATERLOGGED, serverlevelaccessor.getFluidState(blockpos).is(FluidTags.WATER)), 2); +- BlockEntity blockentity = serverlevelaccessor.getBlockEntity(blockpos); ++ protected void handleDataMarker(String name, BlockPos pos, ServerLevelAccessor level, RandomSource random, BoundingBox box) { ++ if ("chest".equals(name)) { ++ // CraftBukkit start - transform block to ensure loot table is accessible ++ /* ++ worldaccess.setBlock(blockposition, (IBlockData) Blocks.CHEST.defaultBlockState().setValue(BlockChest.WATERLOGGED, worldaccess.getFluidState(blockposition).is(TagsFluid.WATER)), 2); ++ TileEntity tileentity = worldaccess.getBlockEntity(blockposition); + +- if (blockentity instanceof ChestBlockEntity) { +- ((ChestBlockEntity) blockentity).setLootTable(this.isLarge ? BuiltInLootTables.UNDERWATER_RUIN_BIG : BuiltInLootTables.UNDERWATER_RUIN_SMALL, randomsource.nextLong()); ++ if (tileentity instanceof TileEntityChest) { ++ ((TileEntityChest) tileentity).setLootTable(this.isLarge ? LootTables.UNDERWATER_RUIN_BIG : LootTables.UNDERWATER_RUIN_SMALL, randomsource.nextLong()); + } +- } else if ("drowned".equals(s)) { +- Drowned drowned = (Drowned) EntityType.DROWNED.create(serverlevelaccessor.getLevel()); ++ */ ++ org.bukkit.craftbukkit.block.CraftChest craftChest = (org.bukkit.craftbukkit.block.CraftChest) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(pos, Blocks.CHEST.defaultBlockState().setValue(ChestBlock.WATERLOGGED, level.getFluidState(pos).is(FluidTags.WATER)), null); ++ craftChest.setSeed(random.nextLong()); ++ craftChest.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.isLarge ? BuiltInLootTables.UNDERWATER_RUIN_BIG : BuiltInLootTables.UNDERWATER_RUIN_SMALL))); ++ placeCraftBlockEntity(level, pos, craftChest, 2); ++ // CraftBukkit end ++ } else if ("drowned".equals(name)) { ++ Drowned entitydrowned = (Drowned) EntityType.DROWNED.create(level.getLevel()); + +- if (drowned != null) { +- drowned.setPersistenceRequired(); +- drowned.moveTo(blockpos, 0.0F, 0.0F); +- drowned.finalizeSpawn(serverlevelaccessor, serverlevelaccessor.getCurrentDifficultyAt(blockpos), MobSpawnType.STRUCTURE, (SpawnGroupData) null, (CompoundTag) null); +- serverlevelaccessor.addFreshEntityWithPassengers(drowned); +- if (blockpos.getY() > serverlevelaccessor.getSeaLevel()) { +- serverlevelaccessor.setBlock(blockpos, Blocks.AIR.defaultBlockState(), 2); ++ if (entitydrowned != null) { ++ entitydrowned.setPersistenceRequired(); ++ entitydrowned.moveTo(pos, 0.0F, 0.0F); ++ entitydrowned.finalizeSpawn(level, level.getCurrentDifficultyAt(pos), EnumMobSpawn.STRUCTURE, (GroupDataEntity) null, (CompoundTag) null); ++ level.addFreshEntityWithPassengers(entitydrowned); ++ if (pos.getY() > level.getSeaLevel()) { ++ level.setBlock(pos, Blocks.AIR.defaultBlockState(), 2); + } else { +- serverlevelaccessor.setBlock(blockpos, Blocks.WATER.defaultBlockState(), 2); ++ level.setBlock(pos, Blocks.WATER.defaultBlockState(), 2); + } + } + } +@@ -225,36 +229,35 @@ + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- int i = worldgenlevel.getHeight(Heightmap.Types.OCEAN_FLOOR_WG, this.templatePosition.getX(), this.templatePosition.getZ()); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ int i = level.getHeight(Heightmap.Types.OCEAN_FLOOR_WG, this.templatePosition.getX(), this.templatePosition.getZ()); + + this.templatePosition = new BlockPos(this.templatePosition.getX(), i, this.templatePosition.getZ()); +- BlockPos blockpos1 = StructureTemplate.transform(new BlockPos(this.template.getSize().getX() - 1, 0, this.template.getSize().getZ() - 1), Mirror.NONE, this.placeSettings.getRotation(), BlockPos.ZERO).offset(this.templatePosition); ++ BlockPos blockposition1 = StructureTemplate.transform(new BlockPos(this.template.getSize().getX() - 1, 0, this.template.getSize().getZ() - 1), Mirror.NONE, this.placeSettings.getRotation(), BlockPos.ZERO).offset(this.templatePosition); + +- this.templatePosition = new BlockPos(this.templatePosition.getX(), this.getHeight(this.templatePosition, worldgenlevel, blockpos1), this.templatePosition.getZ()); +- super.postProcess(worldgenlevel, structuremanager, chunkgenerator, randomsource, boundingbox, chunkpos, blockpos); ++ this.templatePosition = new BlockPos(this.templatePosition.getX(), this.getHeight(this.templatePosition, level, blockposition1), this.templatePosition.getZ()); ++ super.postProcess(level, structureManager, generator, random, box, chunkPos, pos); + } + +- private int getHeight(BlockPos blockpos, BlockGetter blockgetter, BlockPos blockpos1) { +- int i = blockpos.getY(); ++ private int getHeight(BlockPos templatePos, BlockGetter level, BlockPos pos) { ++ int i = templatePos.getY(); + int j = 512; + int k = i - 1; + int l = 0; +- Iterator iterator = BlockPos.betweenClosed(blockpos, blockpos1).iterator(); ++ Iterator iterator = BlockPos.betweenClosed(templatePos, pos).iterator(); + + while (iterator.hasNext()) { +- BlockPos blockpos2 = (BlockPos) iterator.next(); +- int i1 = blockpos2.getX(); +- int j1 = blockpos2.getZ(); +- int k1 = blockpos.getY() - 1; +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(i1, k1, j1); +- BlockState blockstate = blockgetter.getBlockState(blockpos_mutableblockpos); ++ BlockPos blockposition2 = (BlockPos) iterator.next(); ++ int i1 = blockposition2.getX(); ++ int j1 = blockposition2.getZ(); ++ int k1 = templatePos.getY() - 1; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(i1, k1, j1); ++ IBlockData iblockdata = level.getBlockState(blockposition_mutableblockposition); + +- for (FluidState fluidstate = blockgetter.getFluidState(blockpos_mutableblockpos); (blockstate.isAir() || fluidstate.is(FluidTags.WATER) || blockstate.is(BlockTags.ICE)) && k1 > blockgetter.getMinBuildHeight() + 1; fluidstate = blockgetter.getFluidState(blockpos_mutableblockpos)) { ++ for (FluidState fluid = level.getFluidState(blockposition_mutableblockposition); (iblockdata.isAir() || fluid.is(FluidTags.WATER) || iblockdata.is(BlockTags.ICE)) && k1 > level.getMinBuildHeight() + 1; fluid = level.getFluidState(blockposition_mutableblockposition)) { + --k1; +- blockpos_mutableblockpos.set(i1, k1, j1); +- blockstate = blockgetter.getBlockState(blockpos_mutableblockpos); ++ blockposition_mutableblockposition.set(i1, k1, j1); ++ iblockdata = level.getBlockState(blockposition_mutableblockposition); + } + + j = Math.min(j, k1); +@@ -263,7 +266,7 @@ + } + } + +- int l1 = Math.abs(blockpos.getX() - blockpos1.getX()); ++ int l1 = Math.abs(templatePos.getX() - pos.getX()); + + if (k - j > 2 && l > l1 - 2) { + i = j + 1; diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java.patch new file mode 100644 index 0000000000..7a4c9b495e --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java.patch @@ -0,0 +1,2061 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java +@@ -8,7 +8,6 @@ + import net.minecraft.core.Direction; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.entity.EntityType; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.StructureManager; + import net.minecraft.world.level.WorldGenLevel; +@@ -22,10 +21,8 @@ + import net.minecraft.world.level.block.SlabBlock; + import net.minecraft.world.level.block.StairBlock; + import net.minecraft.world.level.block.WallTorchBlock; +-import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.entity.SpawnerBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; +-import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.block.state.properties.BlockPropertyDoubleBlockHalf; + import net.minecraft.world.level.block.state.properties.SlabType; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.levelgen.structure.BoundingBox; +@@ -45,34 +42,32 @@ + public static final int MAGIC_START_Y = 64; + private static final StrongholdPieces.PieceWeight[] STRONGHOLD_PIECE_WEIGHTS = new StrongholdPieces.PieceWeight[]{new StrongholdPieces.PieceWeight(StrongholdPieces.Straight.class, 40, 0), new StrongholdPieces.PieceWeight(StrongholdPieces.PrisonHall.class, 5, 5), new StrongholdPieces.PieceWeight(StrongholdPieces.LeftTurn.class, 20, 0), new StrongholdPieces.PieceWeight(StrongholdPieces.RightTurn.class, 20, 0), new StrongholdPieces.PieceWeight(StrongholdPieces.RoomCrossing.class, 10, 6), new StrongholdPieces.PieceWeight(StrongholdPieces.StraightStairsDown.class, 5, 5), new StrongholdPieces.PieceWeight(StrongholdPieces.StairsDown.class, 5, 5), new StrongholdPieces.PieceWeight(StrongholdPieces.FiveCrossing.class, 5, 4), new StrongholdPieces.PieceWeight(StrongholdPieces.ChestCorridor.class, 5, 4), new StrongholdPieces.PieceWeight(StrongholdPieces.Library.class, 10, 2) { + @Override +- @Override +- public boolean doPlace(int i) { +- return super.doPlace(i) && i > 4; ++ public boolean doPlace(int genDepth) { ++ return super.doPlace(genDepth) && genDepth > 4; + } + }, new StrongholdPieces.PieceWeight(StrongholdPieces.PortalRoom.class, 20, 1) { + @Override +- @Override +- public boolean doPlace(int i) { +- return super.doPlace(i) && i > 5; ++ public boolean doPlace(int genDepth) { ++ return super.doPlace(genDepth) && genDepth > 5; + } +- }}; ++ } }; // CraftBukkit - fix decompile styling + private static List currentPieces; + static Class imposedPiece; + private static int totalWeight; +- static final StrongholdPieces.SmoothStoneSelector SMOOTH_STONE_SELECTOR = new StrongholdPieces.SmoothStoneSelector(); ++ static final StrongholdPieces.k SMOOTH_STONE_SELECTOR = new StrongholdPieces.k(); + + public StrongholdPieces() {} + + public static void resetPieces() { + StrongholdPieces.currentPieces = Lists.newArrayList(); +- StrongholdPieces.PieceWeight[] astrongholdpieces_pieceweight = StrongholdPieces.STRONGHOLD_PIECE_WEIGHTS; +- int i = astrongholdpieces_pieceweight.length; ++ StrongholdPieces.PieceWeight[] astrongholdpieces_f = StrongholdPieces.STRONGHOLD_PIECE_WEIGHTS; ++ int i = astrongholdpieces_f.length; + + for (int j = 0; j < i; ++j) { +- StrongholdPieces.PieceWeight strongholdpieces_pieceweight = astrongholdpieces_pieceweight[j]; ++ StrongholdPieces.PieceWeight strongholdpieces_f = astrongholdpieces_f[j]; + +- strongholdpieces_pieceweight.placeCount = 0; +- StrongholdPieces.currentPieces.add(strongholdpieces_pieceweight); ++ strongholdpieces_f.placeCount = 0; ++ StrongholdPieces.currentPieces.add(strongholdpieces_f); + } + + StrongholdPieces.imposedPiece = null; +@@ -83,11 +78,11 @@ + + StrongholdPieces.totalWeight = 0; + +- StrongholdPieces.PieceWeight strongholdpieces_pieceweight; ++ StrongholdPieces.PieceWeight strongholdpieces_f; + +- for (Iterator iterator = StrongholdPieces.currentPieces.iterator(); iterator.hasNext(); StrongholdPieces.totalWeight += strongholdpieces_pieceweight.weight) { +- strongholdpieces_pieceweight = (StrongholdPieces.PieceWeight) iterator.next(); +- if (strongholdpieces_pieceweight.maxPlaceCount > 0 && strongholdpieces_pieceweight.placeCount < strongholdpieces_pieceweight.maxPlaceCount) { ++ for (Iterator iterator = StrongholdPieces.currentPieces.iterator(); iterator.hasNext(); StrongholdPieces.totalWeight += strongholdpieces_f.weight) { ++ strongholdpieces_f = (StrongholdPieces.PieceWeight) iterator.next(); ++ if (strongholdpieces_f.maxPlaceCount > 0 && strongholdpieces_f.placeCount < strongholdpieces_f.maxPlaceCount) { + flag = true; + } + } +@@ -95,46 +90,46 @@ + return flag; + } + +- private static StrongholdPieces.StrongholdPiece findAndCreatePieceFactory(Class oclass, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, @Nullable Direction direction, int l) { ++ private static StrongholdPieces.StrongholdPiece findAndCreatePieceFactory(Class pieceClass, StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, @Nullable Direction direction, int genDepth) { + Object object = null; + +- if (oclass == StrongholdPieces.Straight.class) { +- object = StrongholdPieces.Straight.createPiece(structurepieceaccessor, randomsource, i, j, k, direction, l); +- } else if (oclass == StrongholdPieces.PrisonHall.class) { +- object = StrongholdPieces.PrisonHall.createPiece(structurepieceaccessor, randomsource, i, j, k, direction, l); +- } else if (oclass == StrongholdPieces.LeftTurn.class) { +- object = StrongholdPieces.LeftTurn.createPiece(structurepieceaccessor, randomsource, i, j, k, direction, l); +- } else if (oclass == StrongholdPieces.RightTurn.class) { +- object = StrongholdPieces.RightTurn.createPiece(structurepieceaccessor, randomsource, i, j, k, direction, l); +- } else if (oclass == StrongholdPieces.RoomCrossing.class) { +- object = StrongholdPieces.RoomCrossing.createPiece(structurepieceaccessor, randomsource, i, j, k, direction, l); +- } else if (oclass == StrongholdPieces.StraightStairsDown.class) { +- object = StrongholdPieces.StraightStairsDown.createPiece(structurepieceaccessor, randomsource, i, j, k, direction, l); +- } else if (oclass == StrongholdPieces.StairsDown.class) { +- object = StrongholdPieces.StairsDown.createPiece(structurepieceaccessor, randomsource, i, j, k, direction, l); +- } else if (oclass == StrongholdPieces.FiveCrossing.class) { +- object = StrongholdPieces.FiveCrossing.createPiece(structurepieceaccessor, randomsource, i, j, k, direction, l); +- } else if (oclass == StrongholdPieces.ChestCorridor.class) { +- object = StrongholdPieces.ChestCorridor.createPiece(structurepieceaccessor, randomsource, i, j, k, direction, l); +- } else if (oclass == StrongholdPieces.Library.class) { +- object = StrongholdPieces.Library.createPiece(structurepieceaccessor, randomsource, i, j, k, direction, l); +- } else if (oclass == StrongholdPieces.PortalRoom.class) { +- object = StrongholdPieces.PortalRoom.createPiece(structurepieceaccessor, i, j, k, direction, l); ++ if (pieceClass == StrongholdPieces.Straight.class) { ++ object = StrongholdPieces.Straight.createPiece(pieces, random, x, y, z, direction, genDepth); ++ } else if (pieceClass == StrongholdPieces.PrisonHall.class) { ++ object = StrongholdPieces.PrisonHall.createPiece(pieces, random, x, y, z, direction, genDepth); ++ } else if (pieceClass == StrongholdPieces.LeftTurn.class) { ++ object = StrongholdPieces.LeftTurn.createPiece(pieces, random, x, y, z, direction, genDepth); ++ } else if (pieceClass == StrongholdPieces.RightTurn.class) { ++ object = StrongholdPieces.RightTurn.createPiece(pieces, random, x, y, z, direction, genDepth); ++ } else if (pieceClass == StrongholdPieces.RoomCrossing.class) { ++ object = StrongholdPieces.RoomCrossing.createPiece(pieces, random, x, y, z, direction, genDepth); ++ } else if (pieceClass == StrongholdPieces.StraightStairsDown.class) { ++ object = StrongholdPieces.StraightStairsDown.createPiece(pieces, random, x, y, z, direction, genDepth); ++ } else if (pieceClass == StrongholdPieces.StairsDown.class) { ++ object = StrongholdPieces.StairsDown.createPiece(pieces, random, x, y, z, direction, genDepth); ++ } else if (pieceClass == StrongholdPieces.FiveCrossing.class) { ++ object = StrongholdPieces.FiveCrossing.createPiece(pieces, random, x, y, z, direction, genDepth); ++ } else if (pieceClass == StrongholdPieces.ChestCorridor.class) { ++ object = StrongholdPieces.ChestCorridor.createPiece(pieces, random, x, y, z, direction, genDepth); ++ } else if (pieceClass == StrongholdPieces.Library.class) { ++ object = StrongholdPieces.Library.createPiece(pieces, random, x, y, z, direction, genDepth); ++ } else if (pieceClass == StrongholdPieces.PortalRoom.class) { ++ object = StrongholdPieces.PortalRoom.createPiece(pieces, x, y, z, direction, genDepth); + } + + return (StrongholdPieces.StrongholdPiece) object; + } + +- private static StrongholdPieces.StrongholdPiece generatePieceFromSmallDoor(StrongholdPieces.StartPiece strongholdpieces_startpiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction, int l) { ++ private static StrongholdPieces.StrongholdPiece generatePieceFromSmallDoor(StrongholdPieces.StartPiece piece, StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction direction, int genDepth) { + if (!updatePieceWeight()) { + return null; + } else { + if (StrongholdPieces.imposedPiece != null) { +- StrongholdPieces.StrongholdPiece strongholdpieces_strongholdpiece = findAndCreatePieceFactory(StrongholdPieces.imposedPiece, structurepieceaccessor, randomsource, i, j, k, direction, l); ++ StrongholdPieces.StrongholdPiece strongholdpieces_p = findAndCreatePieceFactory(StrongholdPieces.imposedPiece, pieces, random, x, y, z, direction, genDepth); + + StrongholdPieces.imposedPiece = null; +- if (strongholdpieces_strongholdpiece != null) { +- return strongholdpieces_strongholdpiece; ++ if (strongholdpieces_p != null) { ++ return strongholdpieces_p; + } + } + +@@ -142,55 +137,55 @@ + + while (i1 < 5) { + ++i1; +- int j1 = randomsource.nextInt(StrongholdPieces.totalWeight); ++ int j1 = random.nextInt(StrongholdPieces.totalWeight); + Iterator iterator = StrongholdPieces.currentPieces.iterator(); + + while (iterator.hasNext()) { +- StrongholdPieces.PieceWeight strongholdpieces_pieceweight = (StrongholdPieces.PieceWeight) iterator.next(); ++ StrongholdPieces.PieceWeight strongholdpieces_f = (StrongholdPieces.PieceWeight) iterator.next(); + +- j1 -= strongholdpieces_pieceweight.weight; ++ j1 -= strongholdpieces_f.weight; + if (j1 < 0) { +- if (!strongholdpieces_pieceweight.doPlace(l) || strongholdpieces_pieceweight == strongholdpieces_startpiece.previousPiece) { ++ if (!strongholdpieces_f.doPlace(genDepth) || strongholdpieces_f == piece.previousPiece) { + break; + } + +- StrongholdPieces.StrongholdPiece strongholdpieces_strongholdpiece1 = findAndCreatePieceFactory(strongholdpieces_pieceweight.pieceClass, structurepieceaccessor, randomsource, i, j, k, direction, l); ++ StrongholdPieces.StrongholdPiece strongholdpieces_p1 = findAndCreatePieceFactory(strongholdpieces_f.pieceClass, pieces, random, x, y, z, direction, genDepth); + +- if (strongholdpieces_strongholdpiece1 != null) { +- ++strongholdpieces_pieceweight.placeCount; +- strongholdpieces_startpiece.previousPiece = strongholdpieces_pieceweight; +- if (!strongholdpieces_pieceweight.isValid()) { +- StrongholdPieces.currentPieces.remove(strongholdpieces_pieceweight); ++ if (strongholdpieces_p1 != null) { ++ ++strongholdpieces_f.placeCount; ++ piece.previousPiece = strongholdpieces_f; ++ if (!strongholdpieces_f.isValid()) { ++ StrongholdPieces.currentPieces.remove(strongholdpieces_f); + } + +- return strongholdpieces_strongholdpiece1; ++ return strongholdpieces_p1; + } + } + } + } + +- BoundingBox boundingbox = StrongholdPieces.FillerCorridor.findPieceBox(structurepieceaccessor, randomsource, i, j, k, direction); ++ BoundingBox structureboundingbox = StrongholdPieces.FillerCorridor.findPieceBox(pieces, random, x, y, z, direction); + +- if (boundingbox != null && boundingbox.minY() > 1) { +- return new StrongholdPieces.FillerCorridor(l, boundingbox, direction); ++ if (structureboundingbox != null && structureboundingbox.minY() > 1) { ++ return new StrongholdPieces.FillerCorridor(genDepth, structureboundingbox, direction); + } else { + return null; + } + } + } + +- static StructurePiece generateAndAddPiece(StrongholdPieces.StartPiece strongholdpieces_startpiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, @Nullable Direction direction, int l) { +- if (l > 50) { ++ static StructurePiece generateAndAddPiece(StrongholdPieces.StartPiece piece, StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, @Nullable Direction direction, int genDepth) { ++ if (genDepth > 50) { + return null; +- } else if (Math.abs(i - strongholdpieces_startpiece.getBoundingBox().minX()) <= 112 && Math.abs(k - strongholdpieces_startpiece.getBoundingBox().minZ()) <= 112) { +- StrongholdPieces.StrongholdPiece strongholdpieces_strongholdpiece = generatePieceFromSmallDoor(strongholdpieces_startpiece, structurepieceaccessor, randomsource, i, j, k, direction, l + 1); ++ } else if (Math.abs(x - piece.getBoundingBox().minX()) <= 112 && Math.abs(z - piece.getBoundingBox().minZ()) <= 112) { ++ StrongholdPieces.StrongholdPiece strongholdpieces_p = generatePieceFromSmallDoor(piece, pieces, random, x, y, z, direction, genDepth + 1); + +- if (strongholdpieces_strongholdpiece != null) { +- structurepieceaccessor.addPiece(strongholdpieces_strongholdpiece); +- strongholdpieces_startpiece.pendingChildren.add(strongholdpieces_strongholdpiece); ++ if (strongholdpieces_p != null) { ++ pieces.addPiece(strongholdpieces_p); ++ piece.pendingChildren.add(strongholdpieces_p); + } + +- return strongholdpieces_strongholdpiece; ++ return strongholdpieces_p; + } else { + return null; + } +@@ -203,13 +198,13 @@ + public int placeCount; + public final int maxPlaceCount; + +- public PieceWeight(Class oclass, int i, int j) { +- this.pieceClass = oclass; +- this.weight = i; +- this.maxPlaceCount = j; ++ public PieceWeight(Class pieceClass, int weight, int maxPlaceCount) { ++ this.pieceClass = pieceClass; ++ this.weight = weight; ++ this.maxPlaceCount = maxPlaceCount; + } + +- public boolean doPlace(int i) { ++ public boolean doPlace(int genDepth) { + return this.maxPlaceCount == 0 || this.placeCount < this.maxPlaceCount; + } + +@@ -226,67 +221,64 @@ + private final boolean leftChild; + private final boolean rightChild; + +- public Straight(int i, RandomSource randomsource, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.STRONGHOLD_STRAIGHT, i, boundingbox); +- this.setOrientation(direction); +- this.entryDoor = this.randomSmallDoor(randomsource); +- this.leftChild = randomsource.nextInt(2) == 0; +- this.rightChild = randomsource.nextInt(2) == 0; ++ public Straight(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_STRAIGHT, genDepth, box); ++ this.setOrientation(orientation); ++ this.entryDoor = this.randomSmallDoor(random); ++ this.leftChild = random.nextInt(2) == 0; ++ this.rightChild = random.nextInt(2) == 0; + } + +- public Straight(CompoundTag compoundtag) { +- super(StructurePieceType.STRONGHOLD_STRAIGHT, compoundtag); +- this.leftChild = compoundtag.getBoolean("Left"); +- this.rightChild = compoundtag.getBoolean("Right"); ++ public Straight(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_STRAIGHT, tag); ++ this.leftChild = tag.getBoolean("Left"); ++ this.rightChild = tag.getBoolean("Right"); + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- super.addAdditionalSaveData(structurepieceserializationcontext, compoundtag); +- compoundtag.putBoolean("Left", this.leftChild); +- compoundtag.putBoolean("Right", this.rightChild); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putBoolean("Left", this.leftChild); ++ tag.putBoolean("Right", this.rightChild); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { +- this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 1, 1); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) piece, pieces, random, 1, 1); + if (this.leftChild) { +- this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 1, 2); ++ this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece) piece, pieces, random, 1, 2); + } + + if (this.rightChild) { +- this.generateSmallDoorChildRight((StrongholdPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 1, 2); ++ this.generateSmallDoorChildRight((StrongholdPieces.StartPiece) piece, pieces, random, 1, 2); + } + + } + +- public static StrongholdPieces.Straight createPiece(StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -1, -1, 0, 5, 5, 7, direction); ++ public static StrongholdPieces.Straight createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction direction, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, 7, direction); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new StrongholdPieces.Straight(l, randomsource, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new StrongholdPieces.Straight(genDepth, random, structureboundingbox, direction) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 0, 4, 4, 6, true, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateSmallDoor(worldgenlevel, randomsource, boundingbox, this.entryDoor, 1, 1, 0); +- this.generateSmallDoor(worldgenlevel, randomsource, boundingbox, StrongholdPieces.StrongholdPiece.SmallDoorType.OPENING, 1, 1, 6); +- BlockState blockstate = (BlockState) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.EAST); +- BlockState blockstate1 = (BlockState) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.WEST); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 4, 4, 6, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateSmallDoor(level, random, box, this.entryDoor, 1, 1, 0); ++ this.generateSmallDoor(level, random, box, StrongholdPieces.StrongholdPiece.a.OPENING, 1, 1, 6); ++ IBlockData iblockdata = (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.EAST); ++ IBlockData iblockdata1 = (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.WEST); + +- this.maybeGenerateBlock(worldgenlevel, boundingbox, randomsource, 0.1F, 1, 2, 1, blockstate); +- this.maybeGenerateBlock(worldgenlevel, boundingbox, randomsource, 0.1F, 3, 2, 1, blockstate1); +- this.maybeGenerateBlock(worldgenlevel, boundingbox, randomsource, 0.1F, 1, 2, 5, blockstate); +- this.maybeGenerateBlock(worldgenlevel, boundingbox, randomsource, 0.1F, 3, 2, 5, blockstate1); ++ this.maybeGenerateBlock(level, box, random, 0.1F, 1, 2, 1, iblockdata); ++ this.maybeGenerateBlock(level, box, random, 0.1F, 3, 2, 1, iblockdata1); ++ this.maybeGenerateBlock(level, box, random, 0.1F, 1, 2, 5, iblockdata); ++ this.maybeGenerateBlock(level, box, random, 0.1F, 3, 2, 5, iblockdata1); + if (this.leftChild) { +- this.generateBox(worldgenlevel, boundingbox, 0, 1, 2, 0, 3, 4, StrongholdPieces.Straight.CAVE_AIR, StrongholdPieces.Straight.CAVE_AIR, false); ++ this.generateBox(level, box, 0, 1, 2, 0, 3, 4, StrongholdPieces.Straight.CAVE_AIR, StrongholdPieces.Straight.CAVE_AIR, false); + } + + if (this.rightChild) { +- this.generateBox(worldgenlevel, boundingbox, 4, 1, 2, 4, 3, 4, StrongholdPieces.Straight.CAVE_AIR, StrongholdPieces.Straight.CAVE_AIR, false); ++ this.generateBox(level, box, 4, 1, 2, 4, 3, 4, StrongholdPieces.Straight.CAVE_AIR, StrongholdPieces.Straight.CAVE_AIR, false); + } + + } +@@ -298,149 +290,143 @@ + protected static final int HEIGHT = 5; + protected static final int DEPTH = 11; + +- public PrisonHall(int i, RandomSource randomsource, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.STRONGHOLD_PRISON_HALL, i, boundingbox); +- this.setOrientation(direction); +- this.entryDoor = this.randomSmallDoor(randomsource); ++ public PrisonHall(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_PRISON_HALL, genDepth, box); ++ this.setOrientation(orientation); ++ this.entryDoor = this.randomSmallDoor(random); + } + +- public PrisonHall(CompoundTag compoundtag) { +- super(StructurePieceType.STRONGHOLD_PRISON_HALL, compoundtag); ++ public PrisonHall(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_PRISON_HALL, tag); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { +- this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 1, 1); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) piece, pieces, random, 1, 1); + } + +- public static StrongholdPieces.PrisonHall createPiece(StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -1, -1, 0, 9, 5, 11, direction); ++ public static StrongholdPieces.PrisonHall createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 9, 5, 11, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new StrongholdPieces.PrisonHall(l, randomsource, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new StrongholdPieces.PrisonHall(genDepth, random, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 0, 8, 4, 10, true, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateSmallDoor(worldgenlevel, randomsource, boundingbox, this.entryDoor, 1, 1, 0); +- this.generateBox(worldgenlevel, boundingbox, 1, 1, 10, 3, 3, 10, StrongholdPieces.PrisonHall.CAVE_AIR, StrongholdPieces.PrisonHall.CAVE_AIR, false); +- this.generateBox(worldgenlevel, boundingbox, 4, 1, 1, 4, 3, 1, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(worldgenlevel, boundingbox, 4, 1, 3, 4, 3, 3, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(worldgenlevel, boundingbox, 4, 1, 7, 4, 3, 7, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(worldgenlevel, boundingbox, 4, 1, 9, 4, 3, 9, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 8, 4, 10, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateSmallDoor(level, random, box, this.entryDoor, 1, 1, 0); ++ this.generateBox(level, box, 1, 1, 10, 3, 3, 10, StrongholdPieces.PrisonHall.CAVE_AIR, StrongholdPieces.PrisonHall.CAVE_AIR, false); ++ this.generateBox(level, box, 4, 1, 1, 4, 3, 1, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 4, 1, 3, 4, 3, 3, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 4, 1, 7, 4, 3, 7, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 4, 1, 9, 4, 3, 9, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); + + for (int i = 1; i <= 3; ++i) { +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, true)).setValue(IronBarsBlock.SOUTH, true), 4, i, 4, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) ((BlockState) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, true)).setValue(IronBarsBlock.SOUTH, true)).setValue(IronBarsBlock.EAST, true), 4, i, 5, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, true)).setValue(IronBarsBlock.SOUTH, true), 4, i, 6, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, true)).setValue(IronBarsBlock.EAST, true), 5, i, 5, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, true)).setValue(IronBarsBlock.EAST, true), 6, i, 5, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, true)).setValue(IronBarsBlock.EAST, true), 7, i, 5, boundingbox); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, true)).setValue(IronBarsBlock.SOUTH, true), 4, i, 4, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, true)).setValue(IronBarsBlock.SOUTH, true)).setValue(IronBarsBlock.EAST, true), 4, i, 5, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, true)).setValue(IronBarsBlock.SOUTH, true), 4, i, 6, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, true)).setValue(IronBarsBlock.EAST, true), 5, i, 5, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, true)).setValue(IronBarsBlock.EAST, true), 6, i, 5, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, true)).setValue(IronBarsBlock.EAST, true), 7, i, 5, box); + } + +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, true)).setValue(IronBarsBlock.SOUTH, true), 4, 3, 2, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, true)).setValue(IronBarsBlock.SOUTH, true), 4, 3, 8, boundingbox); +- BlockState blockstate = (BlockState) Blocks.IRON_DOOR.defaultBlockState().setValue(DoorBlock.FACING, Direction.WEST); +- BlockState blockstate1 = (BlockState) ((BlockState) Blocks.IRON_DOOR.defaultBlockState().setValue(DoorBlock.FACING, Direction.WEST)).setValue(DoorBlock.HALF, DoubleBlockHalf.UPPER); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, true)).setValue(IronBarsBlock.SOUTH, true), 4, 3, 2, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, true)).setValue(IronBarsBlock.SOUTH, true), 4, 3, 8, box); ++ IBlockData iblockdata = (IBlockData) Blocks.IRON_DOOR.defaultBlockState().setValue(DoorBlock.FACING, Direction.WEST); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.IRON_DOOR.defaultBlockState().setValue(DoorBlock.FACING, Direction.WEST)).setValue(DoorBlock.HALF, BlockPropertyDoubleBlockHalf.UPPER); + +- this.placeBlock(worldgenlevel, blockstate, 4, 1, 2, boundingbox); +- this.placeBlock(worldgenlevel, blockstate1, 4, 2, 2, boundingbox); +- this.placeBlock(worldgenlevel, blockstate, 4, 1, 8, boundingbox); +- this.placeBlock(worldgenlevel, blockstate1, 4, 2, 8, boundingbox); ++ this.placeBlock(level, iblockdata, 4, 1, 2, box); ++ this.placeBlock(level, iblockdata1, 4, 2, 2, box); ++ this.placeBlock(level, iblockdata, 4, 1, 8, box); ++ this.placeBlock(level, iblockdata1, 4, 2, 8, box); + } + } + +- public static class LeftTurn extends StrongholdPieces.Turn { ++ public static class LeftTurn extends StrongholdPieces.q { + +- public LeftTurn(int i, RandomSource randomsource, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.STRONGHOLD_LEFT_TURN, i, boundingbox); +- this.setOrientation(direction); +- this.entryDoor = this.randomSmallDoor(randomsource); ++ public LeftTurn(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_LEFT_TURN, genDepth, box); ++ this.setOrientation(orientation); ++ this.entryDoor = this.randomSmallDoor(random); + } + +- public LeftTurn(CompoundTag compoundtag) { +- super(StructurePieceType.STRONGHOLD_LEFT_TURN, compoundtag); ++ public LeftTurn(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_LEFT_TURN, tag); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { +- Direction direction = this.getOrientation(); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ Direction enumdirection = this.getOrientation(); + +- if (direction != Direction.NORTH && direction != Direction.EAST) { +- this.generateSmallDoorChildRight((StrongholdPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 1, 1); ++ if (enumdirection != Direction.NORTH && enumdirection != Direction.EAST) { ++ this.generateSmallDoorChildRight((StrongholdPieces.StartPiece) piece, pieces, random, 1, 1); + } else { +- this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 1, 1); ++ this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece) piece, pieces, random, 1, 1); + } + + } + +- public static StrongholdPieces.LeftTurn createPiece(StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -1, -1, 0, 5, 5, 5, direction); ++ public static StrongholdPieces.LeftTurn createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, 5, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new StrongholdPieces.LeftTurn(l, randomsource, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new StrongholdPieces.LeftTurn(genDepth, random, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 0, 4, 4, 4, true, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateSmallDoor(worldgenlevel, randomsource, boundingbox, this.entryDoor, 1, 1, 0); +- Direction direction = this.getOrientation(); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 4, 4, 4, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateSmallDoor(level, random, box, this.entryDoor, 1, 1, 0); ++ Direction enumdirection = this.getOrientation(); + +- if (direction != Direction.NORTH && direction != Direction.EAST) { +- this.generateBox(worldgenlevel, boundingbox, 4, 1, 1, 4, 3, 3, StrongholdPieces.LeftTurn.CAVE_AIR, StrongholdPieces.LeftTurn.CAVE_AIR, false); ++ if (enumdirection != Direction.NORTH && enumdirection != Direction.EAST) { ++ this.generateBox(level, box, 4, 1, 1, 4, 3, 3, StrongholdPieces.LeftTurn.CAVE_AIR, StrongholdPieces.LeftTurn.CAVE_AIR, false); + } else { +- this.generateBox(worldgenlevel, boundingbox, 0, 1, 1, 0, 3, 3, StrongholdPieces.LeftTurn.CAVE_AIR, StrongholdPieces.LeftTurn.CAVE_AIR, false); ++ this.generateBox(level, box, 0, 1, 1, 0, 3, 3, StrongholdPieces.LeftTurn.CAVE_AIR, StrongholdPieces.LeftTurn.CAVE_AIR, false); + } + + } + } + +- public static class RightTurn extends StrongholdPieces.Turn { ++ public static class RightTurn extends StrongholdPieces.q { + +- public RightTurn(int i, RandomSource randomsource, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.STRONGHOLD_RIGHT_TURN, i, boundingbox); +- this.setOrientation(direction); +- this.entryDoor = this.randomSmallDoor(randomsource); ++ public RightTurn(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_RIGHT_TURN, genDepth, box); ++ this.setOrientation(orientation); ++ this.entryDoor = this.randomSmallDoor(random); + } + +- public RightTurn(CompoundTag compoundtag) { +- super(StructurePieceType.STRONGHOLD_RIGHT_TURN, compoundtag); ++ public RightTurn(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_RIGHT_TURN, tag); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { +- Direction direction = this.getOrientation(); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ Direction enumdirection = this.getOrientation(); + +- if (direction != Direction.NORTH && direction != Direction.EAST) { +- this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 1, 1); ++ if (enumdirection != Direction.NORTH && enumdirection != Direction.EAST) { ++ this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece) piece, pieces, random, 1, 1); + } else { +- this.generateSmallDoorChildRight((StrongholdPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 1, 1); ++ this.generateSmallDoorChildRight((StrongholdPieces.StartPiece) piece, pieces, random, 1, 1); + } + + } + +- public static StrongholdPieces.RightTurn createPiece(StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -1, -1, 0, 5, 5, 5, direction); ++ public static StrongholdPieces.RightTurn createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, 5, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new StrongholdPieces.RightTurn(l, randomsource, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new StrongholdPieces.RightTurn(genDepth, random, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 0, 4, 4, 4, true, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateSmallDoor(worldgenlevel, randomsource, boundingbox, this.entryDoor, 1, 1, 0); +- Direction direction = this.getOrientation(); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 4, 4, 4, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateSmallDoor(level, random, box, this.entryDoor, 1, 1, 0); ++ Direction enumdirection = this.getOrientation(); + +- if (direction != Direction.NORTH && direction != Direction.EAST) { +- this.generateBox(worldgenlevel, boundingbox, 0, 1, 1, 0, 3, 3, StrongholdPieces.RightTurn.CAVE_AIR, StrongholdPieces.RightTurn.CAVE_AIR, false); ++ if (enumdirection != Direction.NORTH && enumdirection != Direction.EAST) { ++ this.generateBox(level, box, 0, 1, 1, 0, 3, 3, StrongholdPieces.RightTurn.CAVE_AIR, StrongholdPieces.RightTurn.CAVE_AIR, false); + } else { +- this.generateBox(worldgenlevel, boundingbox, 4, 1, 1, 4, 3, 3, StrongholdPieces.RightTurn.CAVE_AIR, StrongholdPieces.RightTurn.CAVE_AIR, false); ++ this.generateBox(level, box, 4, 1, 1, 4, 3, 3, StrongholdPieces.RightTurn.CAVE_AIR, StrongholdPieces.RightTurn.CAVE_AIR, false); + } + + } +@@ -453,128 +439,125 @@ + protected static final int DEPTH = 11; + protected final int type; + +- public RoomCrossing(int i, RandomSource randomsource, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.STRONGHOLD_ROOM_CROSSING, i, boundingbox); +- this.setOrientation(direction); +- this.entryDoor = this.randomSmallDoor(randomsource); +- this.type = randomsource.nextInt(5); ++ public RoomCrossing(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_ROOM_CROSSING, genDepth, box); ++ this.setOrientation(orientation); ++ this.entryDoor = this.randomSmallDoor(random); ++ this.type = random.nextInt(5); + } + +- public RoomCrossing(CompoundTag compoundtag) { +- super(StructurePieceType.STRONGHOLD_ROOM_CROSSING, compoundtag); +- this.type = compoundtag.getInt("Type"); ++ public RoomCrossing(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_ROOM_CROSSING, tag); ++ this.type = tag.getInt("Type"); + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- super.addAdditionalSaveData(structurepieceserializationcontext, compoundtag); +- compoundtag.putInt("Type", this.type); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putInt("Type", this.type); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { +- this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 4, 1); +- this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 1, 4); +- this.generateSmallDoorChildRight((StrongholdPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 1, 4); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) piece, pieces, random, 4, 1); ++ this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece) piece, pieces, random, 1, 4); ++ this.generateSmallDoorChildRight((StrongholdPieces.StartPiece) piece, pieces, random, 1, 4); + } + +- public static StrongholdPieces.RoomCrossing createPiece(StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -4, -1, 0, 11, 7, 11, direction); ++ public static StrongholdPieces.RoomCrossing createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -4, -1, 0, 11, 7, 11, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new StrongholdPieces.RoomCrossing(l, randomsource, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new StrongholdPieces.RoomCrossing(genDepth, random, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 0, 10, 6, 10, true, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateSmallDoor(worldgenlevel, randomsource, boundingbox, this.entryDoor, 4, 1, 0); +- this.generateBox(worldgenlevel, boundingbox, 4, 1, 10, 6, 3, 10, StrongholdPieces.RoomCrossing.CAVE_AIR, StrongholdPieces.RoomCrossing.CAVE_AIR, false); +- this.generateBox(worldgenlevel, boundingbox, 0, 1, 4, 0, 3, 6, StrongholdPieces.RoomCrossing.CAVE_AIR, StrongholdPieces.RoomCrossing.CAVE_AIR, false); +- this.generateBox(worldgenlevel, boundingbox, 10, 1, 4, 10, 3, 6, StrongholdPieces.RoomCrossing.CAVE_AIR, StrongholdPieces.RoomCrossing.CAVE_AIR, false); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 10, 6, 10, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateSmallDoor(level, random, box, this.entryDoor, 4, 1, 0); ++ this.generateBox(level, box, 4, 1, 10, 6, 3, 10, StrongholdPieces.RoomCrossing.CAVE_AIR, StrongholdPieces.RoomCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, 0, 1, 4, 0, 3, 6, StrongholdPieces.RoomCrossing.CAVE_AIR, StrongholdPieces.RoomCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, 10, 1, 4, 10, 3, 6, StrongholdPieces.RoomCrossing.CAVE_AIR, StrongholdPieces.RoomCrossing.CAVE_AIR, false); + int i; + + switch (this.type) { + case 0: +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 5, 1, 5, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 5, 2, 5, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 5, 3, 5, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.WEST), 4, 3, 5, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.EAST), 6, 3, 5, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.SOUTH), 5, 3, 4, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.NORTH), 5, 3, 6, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 4, 1, 4, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 4, 1, 5, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 4, 1, 6, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 6, 1, 4, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 6, 1, 5, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 6, 1, 6, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 5, 1, 4, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 5, 1, 6, boundingbox); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 5, 1, 5, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 5, 2, 5, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 5, 3, 5, box); ++ this.placeBlock(level, (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.WEST), 4, 3, 5, box); ++ this.placeBlock(level, (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.EAST), 6, 3, 5, box); ++ this.placeBlock(level, (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.SOUTH), 5, 3, 4, box); ++ this.placeBlock(level, (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.NORTH), 5, 3, 6, box); ++ this.placeBlock(level, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 4, 1, 4, box); ++ this.placeBlock(level, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 4, 1, 5, box); ++ this.placeBlock(level, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 4, 1, 6, box); ++ this.placeBlock(level, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 6, 1, 4, box); ++ this.placeBlock(level, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 6, 1, 5, box); ++ this.placeBlock(level, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 6, 1, 6, box); ++ this.placeBlock(level, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 5, 1, 4, box); ++ this.placeBlock(level, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 5, 1, 6, box); + break; + case 1: + for (i = 0; i < 5; ++i) { +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 3, 1, 3 + i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 7, 1, 3 + i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 3 + i, 1, 3, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 3 + i, 1, 7, boundingbox); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 3, 1, 3 + i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 7, 1, 3 + i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 3 + i, 1, 3, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 3 + i, 1, 7, box); + } + +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 5, 1, 5, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 5, 2, 5, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 5, 3, 5, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.WATER.defaultBlockState(), 5, 4, 5, boundingbox); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 5, 1, 5, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 5, 2, 5, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 5, 3, 5, box); ++ this.placeBlock(level, Blocks.WATER.defaultBlockState(), 5, 4, 5, box); + break; + case 2: + for (i = 1; i <= 9; ++i) { +- this.placeBlock(worldgenlevel, Blocks.COBBLESTONE.defaultBlockState(), 1, 3, i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.COBBLESTONE.defaultBlockState(), 9, 3, i, boundingbox); ++ this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 1, 3, i, box); ++ this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 9, 3, i, box); + } + + for (i = 1; i <= 9; ++i) { +- this.placeBlock(worldgenlevel, Blocks.COBBLESTONE.defaultBlockState(), i, 3, 1, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.COBBLESTONE.defaultBlockState(), i, 3, 9, boundingbox); ++ this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), i, 3, 1, box); ++ this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), i, 3, 9, box); + } + +- this.placeBlock(worldgenlevel, Blocks.COBBLESTONE.defaultBlockState(), 5, 1, 4, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.COBBLESTONE.defaultBlockState(), 5, 1, 6, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.COBBLESTONE.defaultBlockState(), 5, 3, 4, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.COBBLESTONE.defaultBlockState(), 5, 3, 6, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.COBBLESTONE.defaultBlockState(), 4, 1, 5, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.COBBLESTONE.defaultBlockState(), 6, 1, 5, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.COBBLESTONE.defaultBlockState(), 4, 3, 5, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.COBBLESTONE.defaultBlockState(), 6, 3, 5, boundingbox); ++ this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 5, 1, 4, box); ++ this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 5, 1, 6, box); ++ this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 5, 3, 4, box); ++ this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 5, 3, 6, box); ++ this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 4, 1, 5, box); ++ this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 6, 1, 5, box); ++ this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 4, 3, 5, box); ++ this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 6, 3, 5, box); + + for (i = 1; i <= 3; ++i) { +- this.placeBlock(worldgenlevel, Blocks.COBBLESTONE.defaultBlockState(), 4, i, 4, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.COBBLESTONE.defaultBlockState(), 6, i, 4, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.COBBLESTONE.defaultBlockState(), 4, i, 6, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.COBBLESTONE.defaultBlockState(), 6, i, 6, boundingbox); ++ this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 4, i, 4, box); ++ this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 6, i, 4, box); ++ this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 4, i, 6, box); ++ this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 6, i, 6, box); + } + +- this.placeBlock(worldgenlevel, Blocks.WALL_TORCH.defaultBlockState(), 5, 3, 5, boundingbox); ++ this.placeBlock(level, Blocks.WALL_TORCH.defaultBlockState(), 5, 3, 5, box); + + for (i = 2; i <= 8; ++i) { +- this.placeBlock(worldgenlevel, Blocks.OAK_PLANKS.defaultBlockState(), 2, 3, i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.OAK_PLANKS.defaultBlockState(), 3, 3, i, boundingbox); ++ this.placeBlock(level, Blocks.OAK_PLANKS.defaultBlockState(), 2, 3, i, box); ++ this.placeBlock(level, Blocks.OAK_PLANKS.defaultBlockState(), 3, 3, i, box); + if (i <= 3 || i >= 7) { +- this.placeBlock(worldgenlevel, Blocks.OAK_PLANKS.defaultBlockState(), 4, 3, i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.OAK_PLANKS.defaultBlockState(), 5, 3, i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.OAK_PLANKS.defaultBlockState(), 6, 3, i, boundingbox); ++ this.placeBlock(level, Blocks.OAK_PLANKS.defaultBlockState(), 4, 3, i, box); ++ this.placeBlock(level, Blocks.OAK_PLANKS.defaultBlockState(), 5, 3, i, box); ++ this.placeBlock(level, Blocks.OAK_PLANKS.defaultBlockState(), 6, 3, i, box); + } + +- this.placeBlock(worldgenlevel, Blocks.OAK_PLANKS.defaultBlockState(), 7, 3, i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.OAK_PLANKS.defaultBlockState(), 8, 3, i, boundingbox); ++ this.placeBlock(level, Blocks.OAK_PLANKS.defaultBlockState(), 7, 3, i, box); ++ this.placeBlock(level, Blocks.OAK_PLANKS.defaultBlockState(), 8, 3, i, box); + } + +- BlockState blockstate = (BlockState) Blocks.LADDER.defaultBlockState().setValue(LadderBlock.FACING, Direction.WEST); ++ IBlockData iblockdata = (IBlockData) Blocks.LADDER.defaultBlockState().setValue(LadderBlock.FACING, Direction.WEST); + +- this.placeBlock(worldgenlevel, blockstate, 9, 1, 3, boundingbox); +- this.placeBlock(worldgenlevel, blockstate, 9, 2, 3, boundingbox); +- this.placeBlock(worldgenlevel, blockstate, 9, 3, 3, boundingbox); +- this.createChest(worldgenlevel, boundingbox, randomsource, 3, 4, 8, BuiltInLootTables.STRONGHOLD_CROSSING); ++ this.placeBlock(level, iblockdata, 9, 1, 3, box); ++ this.placeBlock(level, iblockdata, 9, 2, 3, box); ++ this.placeBlock(level, iblockdata, 9, 3, 3, box); ++ this.createChest(level, box, random, 3, 4, 8, BuiltInLootTables.STRONGHOLD_CROSSING); + } + + } +@@ -586,44 +569,42 @@ + private static final int HEIGHT = 11; + private static final int DEPTH = 8; + +- public StraightStairsDown(int i, RandomSource randomsource, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.STRONGHOLD_STRAIGHT_STAIRS_DOWN, i, boundingbox); +- this.setOrientation(direction); +- this.entryDoor = this.randomSmallDoor(randomsource); ++ public StraightStairsDown(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_STRAIGHT_STAIRS_DOWN, genDepth, box); ++ this.setOrientation(orientation); ++ this.entryDoor = this.randomSmallDoor(random); + } + +- public StraightStairsDown(CompoundTag compoundtag) { +- super(StructurePieceType.STRONGHOLD_STRAIGHT_STAIRS_DOWN, compoundtag); ++ public StraightStairsDown(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_STRAIGHT_STAIRS_DOWN, tag); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { +- this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 1, 1); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) piece, pieces, random, 1, 1); + } + +- public static StrongholdPieces.StraightStairsDown createPiece(StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -1, -7, 0, 5, 11, 8, direction); ++ public static StrongholdPieces.StraightStairsDown createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -7, 0, 5, 11, 8, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new StrongholdPieces.StraightStairsDown(l, randomsource, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new StrongholdPieces.StraightStairsDown(genDepth, random, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 0, 4, 10, 7, true, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateSmallDoor(worldgenlevel, randomsource, boundingbox, this.entryDoor, 1, 7, 0); +- this.generateSmallDoor(worldgenlevel, randomsource, boundingbox, StrongholdPieces.StrongholdPiece.SmallDoorType.OPENING, 1, 1, 7); +- BlockState blockstate = (BlockState) Blocks.COBBLESTONE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.SOUTH); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 4, 10, 7, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateSmallDoor(level, random, box, this.entryDoor, 1, 7, 0); ++ this.generateSmallDoor(level, random, box, StrongholdPieces.StrongholdPiece.a.OPENING, 1, 1, 7); ++ IBlockData iblockdata = (IBlockData) Blocks.COBBLESTONE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.SOUTH); + + for (int i = 0; i < 6; ++i) { +- this.placeBlock(worldgenlevel, blockstate, 1, 6 - i, 1 + i, boundingbox); +- this.placeBlock(worldgenlevel, blockstate, 2, 6 - i, 1 + i, boundingbox); +- this.placeBlock(worldgenlevel, blockstate, 3, 6 - i, 1 + i, boundingbox); ++ this.placeBlock(level, iblockdata, 1, 6 - i, 1 + i, box); ++ this.placeBlock(level, iblockdata, 2, 6 - i, 1 + i, box); ++ this.placeBlock(level, iblockdata, 3, 6 - i, 1 + i, box); + if (i < 5) { +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 1, 5 - i, 1 + i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 2, 5 - i, 1 + i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 3, 5 - i, 1 + i, boundingbox); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 1, 5 - i, 1 + i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 2, 5 - i, 1 + i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 3, 5 - i, 1 + i, box); + } + } + +@@ -637,75 +618,72 @@ + private static final int DEPTH = 5; + private final boolean isSource; + +- public StairsDown(StructurePieceType structurepiecetype, int i, int j, int k, Direction direction) { +- super(structurepiecetype, i, makeBoundingBox(j, 64, k, direction, 5, 11, 5)); ++ public StairsDown(StructurePieceType type, int genDepth, int x, int z, Direction orientation) { ++ super(type, genDepth, makeBoundingBox(x, 64, z, orientation, 5, 11, 5)); + this.isSource = true; +- this.setOrientation(direction); +- this.entryDoor = StrongholdPieces.StrongholdPiece.SmallDoorType.OPENING; ++ this.setOrientation(orientation); ++ this.entryDoor = StrongholdPieces.StrongholdPiece.a.OPENING; + } + +- public StairsDown(int i, RandomSource randomsource, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.STRONGHOLD_STAIRS_DOWN, i, boundingbox); ++ public StairsDown(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_STAIRS_DOWN, genDepth, box); + this.isSource = false; +- this.setOrientation(direction); +- this.entryDoor = this.randomSmallDoor(randomsource); ++ this.setOrientation(orientation); ++ this.entryDoor = this.randomSmallDoor(random); + } + +- public StairsDown(StructurePieceType structurepiecetype, CompoundTag compoundtag) { +- super(structurepiecetype, compoundtag); +- this.isSource = compoundtag.getBoolean("Source"); ++ public StairsDown(StructurePieceType type, CompoundTag tag) { ++ super(type, tag); ++ this.isSource = tag.getBoolean("Source"); + } + +- public StairsDown(CompoundTag compoundtag) { +- this(StructurePieceType.STRONGHOLD_STAIRS_DOWN, compoundtag); ++ public StairsDown(CompoundTag tag) { ++ this(StructurePieceType.STRONGHOLD_STAIRS_DOWN, tag); + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- super.addAdditionalSaveData(structurepieceserializationcontext, compoundtag); +- compoundtag.putBoolean("Source", this.isSource); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putBoolean("Source", this.isSource); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { + if (this.isSource) { + StrongholdPieces.imposedPiece = StrongholdPieces.FiveCrossing.class; + } + +- this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 1, 1); ++ this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) piece, pieces, random, 1, 1); + } + +- public static StrongholdPieces.StairsDown createPiece(StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -1, -7, 0, 5, 11, 5, direction); ++ public static StrongholdPieces.StairsDown createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -7, 0, 5, 11, 5, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new StrongholdPieces.StairsDown(l, randomsource, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new StrongholdPieces.StairsDown(genDepth, random, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 0, 4, 10, 4, true, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateSmallDoor(worldgenlevel, randomsource, boundingbox, this.entryDoor, 1, 7, 0); +- this.generateSmallDoor(worldgenlevel, randomsource, boundingbox, StrongholdPieces.StrongholdPiece.SmallDoorType.OPENING, 1, 1, 4); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 2, 6, 1, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 1, 5, 1, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 1, 6, 1, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 1, 5, 2, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 1, 4, 3, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 1, 5, 3, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 2, 4, 3, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 3, 3, 3, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 3, 4, 3, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 3, 3, 2, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 3, 2, 1, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 3, 3, 1, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 2, 2, 1, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 1, 1, 1, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 1, 2, 1, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 1, 1, 2, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 1, 1, 3, boundingbox); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 4, 10, 4, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateSmallDoor(level, random, box, this.entryDoor, 1, 7, 0); ++ this.generateSmallDoor(level, random, box, StrongholdPieces.StrongholdPiece.a.OPENING, 1, 1, 4); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 2, 6, 1, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 1, 5, 1, box); ++ this.placeBlock(level, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 1, 6, 1, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 1, 5, 2, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 1, 4, 3, box); ++ this.placeBlock(level, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 1, 5, 3, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 2, 4, 3, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 3, 3, 3, box); ++ this.placeBlock(level, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 3, 4, 3, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 3, 3, 2, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 3, 2, 1, box); ++ this.placeBlock(level, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 3, 3, 1, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 2, 2, 1, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 1, 1, 1, box); ++ this.placeBlock(level, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 1, 2, 1, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 1, 1, 2, box); ++ this.placeBlock(level, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 1, 1, 3, box); + } + } + +@@ -719,107 +697,104 @@ + private final boolean rightLow; + private final boolean rightHigh; + +- public FiveCrossing(int i, RandomSource randomsource, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.STRONGHOLD_FIVE_CROSSING, i, boundingbox); +- this.setOrientation(direction); +- this.entryDoor = this.randomSmallDoor(randomsource); +- this.leftLow = randomsource.nextBoolean(); +- this.leftHigh = randomsource.nextBoolean(); +- this.rightLow = randomsource.nextBoolean(); +- this.rightHigh = randomsource.nextInt(3) > 0; ++ public FiveCrossing(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_FIVE_CROSSING, genDepth, box); ++ this.setOrientation(orientation); ++ this.entryDoor = this.randomSmallDoor(random); ++ this.leftLow = random.nextBoolean(); ++ this.leftHigh = random.nextBoolean(); ++ this.rightLow = random.nextBoolean(); ++ this.rightHigh = random.nextInt(3) > 0; + } + +- public FiveCrossing(CompoundTag compoundtag) { +- super(StructurePieceType.STRONGHOLD_FIVE_CROSSING, compoundtag); +- this.leftLow = compoundtag.getBoolean("leftLow"); +- this.leftHigh = compoundtag.getBoolean("leftHigh"); +- this.rightLow = compoundtag.getBoolean("rightLow"); +- this.rightHigh = compoundtag.getBoolean("rightHigh"); ++ public FiveCrossing(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_FIVE_CROSSING, tag); ++ this.leftLow = tag.getBoolean("leftLow"); ++ this.leftHigh = tag.getBoolean("leftHigh"); ++ this.rightLow = tag.getBoolean("rightLow"); ++ this.rightHigh = tag.getBoolean("rightHigh"); + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- super.addAdditionalSaveData(structurepieceserializationcontext, compoundtag); +- compoundtag.putBoolean("leftLow", this.leftLow); +- compoundtag.putBoolean("leftHigh", this.leftHigh); +- compoundtag.putBoolean("rightLow", this.rightLow); +- compoundtag.putBoolean("rightHigh", this.rightHigh); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putBoolean("leftLow", this.leftLow); ++ tag.putBoolean("leftHigh", this.leftHigh); ++ tag.putBoolean("rightLow", this.rightLow); ++ tag.putBoolean("rightHigh", this.rightHigh); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { + int i = 3; + int j = 5; +- Direction direction = this.getOrientation(); ++ Direction enumdirection = this.getOrientation(); + +- if (direction == Direction.WEST || direction == Direction.NORTH) { ++ if (enumdirection == Direction.WEST || enumdirection == Direction.NORTH) { + i = 8 - i; + j = 8 - j; + } + +- this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 5, 1); ++ this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) piece, pieces, random, 5, 1); + if (this.leftLow) { +- this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, i, 1); ++ this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece) piece, pieces, random, i, 1); + } + + if (this.leftHigh) { +- this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, j, 7); ++ this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece) piece, pieces, random, j, 7); + } + + if (this.rightLow) { +- this.generateSmallDoorChildRight((StrongholdPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, i, 1); ++ this.generateSmallDoorChildRight((StrongholdPieces.StartPiece) piece, pieces, random, i, 1); + } + + if (this.rightHigh) { +- this.generateSmallDoorChildRight((StrongholdPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, j, 7); ++ this.generateSmallDoorChildRight((StrongholdPieces.StartPiece) piece, pieces, random, j, 7); + } + + } + +- public static StrongholdPieces.FiveCrossing createPiece(StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -4, -3, 0, 10, 9, 11, direction); ++ public static StrongholdPieces.FiveCrossing createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -4, -3, 0, 10, 9, 11, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new StrongholdPieces.FiveCrossing(l, randomsource, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new StrongholdPieces.FiveCrossing(genDepth, random, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 0, 9, 8, 10, true, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateSmallDoor(worldgenlevel, randomsource, boundingbox, this.entryDoor, 4, 3, 0); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 9, 8, 10, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateSmallDoor(level, random, box, this.entryDoor, 4, 3, 0); + if (this.leftLow) { +- this.generateBox(worldgenlevel, boundingbox, 0, 3, 1, 0, 5, 3, StrongholdPieces.FiveCrossing.CAVE_AIR, StrongholdPieces.FiveCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, 0, 3, 1, 0, 5, 3, StrongholdPieces.FiveCrossing.CAVE_AIR, StrongholdPieces.FiveCrossing.CAVE_AIR, false); + } + + if (this.rightLow) { +- this.generateBox(worldgenlevel, boundingbox, 9, 3, 1, 9, 5, 3, StrongholdPieces.FiveCrossing.CAVE_AIR, StrongholdPieces.FiveCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, 9, 3, 1, 9, 5, 3, StrongholdPieces.FiveCrossing.CAVE_AIR, StrongholdPieces.FiveCrossing.CAVE_AIR, false); + } + + if (this.leftHigh) { +- this.generateBox(worldgenlevel, boundingbox, 0, 5, 7, 0, 7, 9, StrongholdPieces.FiveCrossing.CAVE_AIR, StrongholdPieces.FiveCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, 0, 5, 7, 0, 7, 9, StrongholdPieces.FiveCrossing.CAVE_AIR, StrongholdPieces.FiveCrossing.CAVE_AIR, false); + } + + if (this.rightHigh) { +- this.generateBox(worldgenlevel, boundingbox, 9, 5, 7, 9, 7, 9, StrongholdPieces.FiveCrossing.CAVE_AIR, StrongholdPieces.FiveCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, 9, 5, 7, 9, 7, 9, StrongholdPieces.FiveCrossing.CAVE_AIR, StrongholdPieces.FiveCrossing.CAVE_AIR, false); + } + +- this.generateBox(worldgenlevel, boundingbox, 5, 1, 10, 7, 3, 10, StrongholdPieces.FiveCrossing.CAVE_AIR, StrongholdPieces.FiveCrossing.CAVE_AIR, false); +- this.generateBox(worldgenlevel, boundingbox, 1, 2, 1, 8, 2, 6, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(worldgenlevel, boundingbox, 4, 1, 5, 4, 4, 9, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(worldgenlevel, boundingbox, 8, 1, 5, 8, 4, 9, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(worldgenlevel, boundingbox, 1, 4, 7, 3, 4, 9, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(worldgenlevel, boundingbox, 1, 3, 5, 3, 3, 6, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(worldgenlevel, boundingbox, 1, 3, 4, 3, 3, 4, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 4, 6, 3, 4, 6, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 5, 1, 7, 7, 1, 8, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(worldgenlevel, boundingbox, 5, 1, 9, 7, 1, 9, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 5, 2, 7, 7, 2, 7, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 4, 5, 7, 4, 5, 9, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 8, 5, 7, 8, 5, 9, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 5, 5, 7, 7, 5, 9, (BlockState) Blocks.SMOOTH_STONE_SLAB.defaultBlockState().setValue(SlabBlock.TYPE, SlabType.DOUBLE), (BlockState) Blocks.SMOOTH_STONE_SLAB.defaultBlockState().setValue(SlabBlock.TYPE, SlabType.DOUBLE), false); +- this.placeBlock(worldgenlevel, (BlockState) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.SOUTH), 6, 5, 6, boundingbox); ++ this.generateBox(level, box, 5, 1, 10, 7, 3, 10, StrongholdPieces.FiveCrossing.CAVE_AIR, StrongholdPieces.FiveCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, 1, 2, 1, 8, 2, 6, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 4, 1, 5, 4, 4, 9, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 8, 1, 5, 8, 4, 9, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 1, 4, 7, 3, 4, 9, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 1, 3, 5, 3, 3, 6, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 1, 3, 4, 3, 3, 4, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 4, 6, 3, 4, 6, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 1, 7, 7, 1, 8, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 5, 1, 9, 7, 1, 9, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 2, 7, 7, 2, 7, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 5, 7, 4, 5, 9, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); ++ this.generateBox(level, box, 8, 5, 7, 8, 5, 9, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 5, 7, 7, 5, 9, (IBlockData) Blocks.SMOOTH_STONE_SLAB.defaultBlockState().setValue(SlabBlock.TYPE, SlabType.DOUBLE), (IBlockData) Blocks.SMOOTH_STONE_SLAB.defaultBlockState().setValue(SlabBlock.TYPE, SlabType.DOUBLE), false); ++ this.placeBlock(level, (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.SOUTH), 6, 5, 6, box); + } + } + +@@ -830,55 +805,52 @@ + private static final int DEPTH = 7; + private boolean hasPlacedChest; + +- public ChestCorridor(int i, RandomSource randomsource, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.STRONGHOLD_CHEST_CORRIDOR, i, boundingbox); +- this.setOrientation(direction); +- this.entryDoor = this.randomSmallDoor(randomsource); ++ public ChestCorridor(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_CHEST_CORRIDOR, genDepth, box); ++ this.setOrientation(orientation); ++ this.entryDoor = this.randomSmallDoor(random); + } + +- public ChestCorridor(CompoundTag compoundtag) { +- super(StructurePieceType.STRONGHOLD_CHEST_CORRIDOR, compoundtag); +- this.hasPlacedChest = compoundtag.getBoolean("Chest"); ++ public ChestCorridor(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_CHEST_CORRIDOR, tag); ++ this.hasPlacedChest = tag.getBoolean("Chest"); + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- super.addAdditionalSaveData(structurepieceserializationcontext, compoundtag); +- compoundtag.putBoolean("Chest", this.hasPlacedChest); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putBoolean("Chest", this.hasPlacedChest); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { +- this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) structurepiece, structurepieceaccessor, randomsource, 1, 1); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) piece, pieces, random, 1, 1); + } + +- public static StrongholdPieces.ChestCorridor createPiece(StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -1, -1, 0, 5, 5, 7, direction); ++ public static StrongholdPieces.ChestCorridor createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, 7, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new StrongholdPieces.ChestCorridor(l, randomsource, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new StrongholdPieces.ChestCorridor(genDepth, random, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 0, 4, 4, 6, true, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateSmallDoor(worldgenlevel, randomsource, boundingbox, this.entryDoor, 1, 1, 0); +- this.generateSmallDoor(worldgenlevel, randomsource, boundingbox, StrongholdPieces.StrongholdPiece.SmallDoorType.OPENING, 1, 1, 6); +- this.generateBox(worldgenlevel, boundingbox, 3, 1, 2, 3, 1, 4, Blocks.STONE_BRICKS.defaultBlockState(), Blocks.STONE_BRICKS.defaultBlockState(), false); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICK_SLAB.defaultBlockState(), 3, 1, 1, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICK_SLAB.defaultBlockState(), 3, 1, 5, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICK_SLAB.defaultBlockState(), 3, 2, 2, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICK_SLAB.defaultBlockState(), 3, 2, 4, boundingbox); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 4, 4, 6, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateSmallDoor(level, random, box, this.entryDoor, 1, 1, 0); ++ this.generateSmallDoor(level, random, box, StrongholdPieces.StrongholdPiece.a.OPENING, 1, 1, 6); ++ this.generateBox(level, box, 3, 1, 2, 3, 1, 4, Blocks.STONE_BRICKS.defaultBlockState(), Blocks.STONE_BRICKS.defaultBlockState(), false); ++ this.placeBlock(level, Blocks.STONE_BRICK_SLAB.defaultBlockState(), 3, 1, 1, box); ++ this.placeBlock(level, Blocks.STONE_BRICK_SLAB.defaultBlockState(), 3, 1, 5, box); ++ this.placeBlock(level, Blocks.STONE_BRICK_SLAB.defaultBlockState(), 3, 2, 2, box); ++ this.placeBlock(level, Blocks.STONE_BRICK_SLAB.defaultBlockState(), 3, 2, 4, box); + + for (int i = 2; i <= 4; ++i) { +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICK_SLAB.defaultBlockState(), 2, 1, i, boundingbox); ++ this.placeBlock(level, Blocks.STONE_BRICK_SLAB.defaultBlockState(), 2, 1, i, box); + } + +- if (!this.hasPlacedChest && boundingbox.isInside(this.getWorldPos(3, 2, 3))) { ++ if (!this.hasPlacedChest && box.isInside(this.getWorldPos(3, 2, 3))) { + this.hasPlacedChest = true; +- this.createChest(worldgenlevel, boundingbox, randomsource, 3, 2, 3, BuiltInLootTables.STRONGHOLD_CORRIDOR); ++ this.createChest(level, box, random, 3, 2, 3, BuiltInLootTables.STRONGHOLD_CORRIDOR); + } + + } +@@ -892,50 +864,48 @@ + protected static final int DEPTH = 15; + private final boolean isTall; + +- public Library(int i, RandomSource randomsource, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.STRONGHOLD_LIBRARY, i, boundingbox); +- this.setOrientation(direction); +- this.entryDoor = this.randomSmallDoor(randomsource); +- this.isTall = boundingbox.getYSpan() > 6; ++ public Library(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_LIBRARY, genDepth, box); ++ this.setOrientation(orientation); ++ this.entryDoor = this.randomSmallDoor(random); ++ this.isTall = box.getYSpan() > 6; + } + +- public Library(CompoundTag compoundtag) { +- super(StructurePieceType.STRONGHOLD_LIBRARY, compoundtag); +- this.isTall = compoundtag.getBoolean("Tall"); ++ public Library(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_LIBRARY, tag); ++ this.isTall = tag.getBoolean("Tall"); + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- super.addAdditionalSaveData(structurepieceserializationcontext, compoundtag); +- compoundtag.putBoolean("Tall", this.isTall); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putBoolean("Tall", this.isTall); + } + +- public static StrongholdPieces.Library createPiece(StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -4, -1, 0, 14, 11, 15, direction); ++ public static StrongholdPieces.Library createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -4, -1, 0, 14, 11, 15, orientation); + +- if (!isOkBox(boundingbox) || structurepieceaccessor.findCollisionPiece(boundingbox) != null) { +- boundingbox = BoundingBox.orientBox(i, j, k, -4, -1, 0, 14, 6, 15, direction); +- if (!isOkBox(boundingbox) || structurepieceaccessor.findCollisionPiece(boundingbox) != null) { ++ if (!isOkBox(structureboundingbox) || pieces.findCollisionPiece(structureboundingbox) != null) { ++ structureboundingbox = BoundingBox.orientBox(x, y, z, -4, -1, 0, 14, 6, 15, orientation); ++ if (!isOkBox(structureboundingbox) || pieces.findCollisionPiece(structureboundingbox) != null) { + return null; + } + } + +- return new StrongholdPieces.Library(l, randomsource, boundingbox, direction); ++ return new StrongholdPieces.Library(genDepth, random, structureboundingbox, orientation); + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { + byte b0 = 11; + + if (!this.isTall) { + b0 = 6; + } + +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 0, 13, b0 - 1, 14, true, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateSmallDoor(worldgenlevel, randomsource, boundingbox, this.entryDoor, 4, 1, 0); +- this.generateMaybeBox(worldgenlevel, boundingbox, randomsource, 0.07F, 2, 1, 1, 11, 4, 13, Blocks.COBWEB.defaultBlockState(), Blocks.COBWEB.defaultBlockState(), false, false); ++ this.generateBox(level, box, 0, 0, 0, 13, b0 - 1, 14, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateSmallDoor(level, random, box, this.entryDoor, 4, 1, 0); ++ this.generateMaybeBox(level, box, random, 0.07F, 2, 1, 1, 11, 4, 13, Blocks.COBWEB.defaultBlockState(), Blocks.COBWEB.defaultBlockState(), false, false); + boolean flag = true; + boolean flag1 = true; + +@@ -943,99 +913,99 @@ + + for (i = 1; i <= 13; ++i) { + if ((i - 1) % 4 == 0) { +- this.generateBox(worldgenlevel, boundingbox, 1, 1, i, 1, 4, i, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 12, 1, i, 12, 4, i, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); +- this.placeBlock(worldgenlevel, (BlockState) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.EAST), 2, 3, i, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.WEST), 11, 3, i, boundingbox); ++ this.generateBox(level, box, 1, 1, i, 1, 4, i, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); ++ this.generateBox(level, box, 12, 1, i, 12, 4, i, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); ++ this.placeBlock(level, (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.EAST), 2, 3, i, box); ++ this.placeBlock(level, (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.WEST), 11, 3, i, box); + if (this.isTall) { +- this.generateBox(worldgenlevel, boundingbox, 1, 6, i, 1, 9, i, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 12, 6, i, 12, 9, i, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 6, i, 1, 9, i, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); ++ this.generateBox(level, box, 12, 6, i, 12, 9, i, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); + } + } else { +- this.generateBox(worldgenlevel, boundingbox, 1, 1, i, 1, 4, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 12, 1, i, 12, 4, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 1, i, 1, 4, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); ++ this.generateBox(level, box, 12, 1, i, 12, 4, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); + if (this.isTall) { +- this.generateBox(worldgenlevel, boundingbox, 1, 6, i, 1, 9, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 12, 6, i, 12, 9, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 6, i, 1, 9, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); ++ this.generateBox(level, box, 12, 6, i, 12, 9, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); + } + } + } + + for (i = 3; i < 12; i += 2) { +- this.generateBox(worldgenlevel, boundingbox, 3, 1, i, 4, 3, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 6, 1, i, 7, 3, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 9, 1, i, 10, 3, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); ++ this.generateBox(level, box, 3, 1, i, 4, 3, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 1, i, 7, 3, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); ++ this.generateBox(level, box, 9, 1, i, 10, 3, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); + } + + if (this.isTall) { +- this.generateBox(worldgenlevel, boundingbox, 1, 5, 1, 3, 5, 13, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 10, 5, 1, 12, 5, 13, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 4, 5, 1, 9, 5, 2, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 4, 5, 12, 9, 5, 13, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); +- this.placeBlock(worldgenlevel, Blocks.OAK_PLANKS.defaultBlockState(), 9, 5, 11, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.OAK_PLANKS.defaultBlockState(), 8, 5, 11, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.OAK_PLANKS.defaultBlockState(), 9, 5, 10, boundingbox); +- BlockState blockstate = (BlockState) ((BlockState) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); +- BlockState blockstate1 = (BlockState) ((BlockState) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); ++ this.generateBox(level, box, 1, 5, 1, 3, 5, 13, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); ++ this.generateBox(level, box, 10, 5, 1, 12, 5, 13, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 5, 1, 9, 5, 2, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 5, 12, 9, 5, 13, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); ++ this.placeBlock(level, Blocks.OAK_PLANKS.defaultBlockState(), 9, 5, 11, box); ++ this.placeBlock(level, Blocks.OAK_PLANKS.defaultBlockState(), 8, 5, 11, box); ++ this.placeBlock(level, Blocks.OAK_PLANKS.defaultBlockState(), 9, 5, 10, box); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); + +- this.generateBox(worldgenlevel, boundingbox, 3, 6, 3, 3, 6, 11, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 10, 6, 3, 10, 6, 9, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 4, 6, 2, 9, 6, 2, blockstate, blockstate, false); +- this.generateBox(worldgenlevel, boundingbox, 4, 6, 12, 7, 6, 12, blockstate, blockstate, false); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.EAST, true), 3, 6, 2, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.SOUTH, true)).setValue(FenceBlock.EAST, true), 3, 6, 12, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.WEST, true), 10, 6, 2, boundingbox); ++ this.generateBox(level, box, 3, 6, 3, 3, 6, 11, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 10, 6, 3, 10, 6, 9, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 4, 6, 2, 9, 6, 2, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 4, 6, 12, 7, 6, 12, iblockdata, iblockdata, false); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.EAST, true), 3, 6, 2, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.SOUTH, true)).setValue(FenceBlock.EAST, true), 3, 6, 12, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.WEST, true), 10, 6, 2, box); + + for (int j = 0; j <= 2; ++j) { +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.SOUTH, true)).setValue(FenceBlock.WEST, true), 8 + j, 6, 12 - j, boundingbox); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.SOUTH, true)).setValue(FenceBlock.WEST, true), 8 + j, 6, 12 - j, box); + if (j != 2) { +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.EAST, true), 8 + j, 6, 11 - j, boundingbox); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.EAST, true), 8 + j, 6, 11 - j, box); + } + } + +- BlockState blockstate2 = (BlockState) Blocks.LADDER.defaultBlockState().setValue(LadderBlock.FACING, Direction.SOUTH); ++ IBlockData iblockdata2 = (IBlockData) Blocks.LADDER.defaultBlockState().setValue(LadderBlock.FACING, Direction.SOUTH); + +- this.placeBlock(worldgenlevel, blockstate2, 10, 1, 13, boundingbox); +- this.placeBlock(worldgenlevel, blockstate2, 10, 2, 13, boundingbox); +- this.placeBlock(worldgenlevel, blockstate2, 10, 3, 13, boundingbox); +- this.placeBlock(worldgenlevel, blockstate2, 10, 4, 13, boundingbox); +- this.placeBlock(worldgenlevel, blockstate2, 10, 5, 13, boundingbox); +- this.placeBlock(worldgenlevel, blockstate2, 10, 6, 13, boundingbox); +- this.placeBlock(worldgenlevel, blockstate2, 10, 7, 13, boundingbox); ++ this.placeBlock(level, iblockdata2, 10, 1, 13, box); ++ this.placeBlock(level, iblockdata2, 10, 2, 13, box); ++ this.placeBlock(level, iblockdata2, 10, 3, 13, box); ++ this.placeBlock(level, iblockdata2, 10, 4, 13, box); ++ this.placeBlock(level, iblockdata2, 10, 5, 13, box); ++ this.placeBlock(level, iblockdata2, 10, 6, 13, box); ++ this.placeBlock(level, iblockdata2, 10, 7, 13, box); + boolean flag2 = true; + boolean flag3 = true; +- BlockState blockstate3 = (BlockState) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true); ++ IBlockData iblockdata3 = (IBlockData) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true); + +- this.placeBlock(worldgenlevel, blockstate3, 6, 9, 7, boundingbox); +- BlockState blockstate4 = (BlockState) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true); ++ this.placeBlock(level, iblockdata3, 6, 9, 7, box); ++ IBlockData iblockdata4 = (IBlockData) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true); + +- this.placeBlock(worldgenlevel, blockstate4, 7, 9, 7, boundingbox); +- this.placeBlock(worldgenlevel, blockstate3, 6, 8, 7, boundingbox); +- this.placeBlock(worldgenlevel, blockstate4, 7, 8, 7, boundingbox); +- BlockState blockstate5 = (BlockState) ((BlockState) blockstate1.setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); ++ this.placeBlock(level, iblockdata4, 7, 9, 7, box); ++ this.placeBlock(level, iblockdata3, 6, 8, 7, box); ++ this.placeBlock(level, iblockdata4, 7, 8, 7, box); ++ IBlockData iblockdata5 = (IBlockData) ((IBlockData) iblockdata1.setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); + +- this.placeBlock(worldgenlevel, blockstate5, 6, 7, 7, boundingbox); +- this.placeBlock(worldgenlevel, blockstate5, 7, 7, 7, boundingbox); +- this.placeBlock(worldgenlevel, blockstate3, 5, 7, 7, boundingbox); +- this.placeBlock(worldgenlevel, blockstate4, 8, 7, 7, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) blockstate3.setValue(FenceBlock.NORTH, true), 6, 7, 6, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) blockstate3.setValue(FenceBlock.SOUTH, true), 6, 7, 8, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) blockstate4.setValue(FenceBlock.NORTH, true), 7, 7, 6, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) blockstate4.setValue(FenceBlock.SOUTH, true), 7, 7, 8, boundingbox); +- BlockState blockstate6 = Blocks.TORCH.defaultBlockState(); ++ this.placeBlock(level, iblockdata5, 6, 7, 7, box); ++ this.placeBlock(level, iblockdata5, 7, 7, 7, box); ++ this.placeBlock(level, iblockdata3, 5, 7, 7, box); ++ this.placeBlock(level, iblockdata4, 8, 7, 7, box); ++ this.placeBlock(level, (IBlockData) iblockdata3.setValue(FenceBlock.NORTH, true), 6, 7, 6, box); ++ this.placeBlock(level, (IBlockData) iblockdata3.setValue(FenceBlock.SOUTH, true), 6, 7, 8, box); ++ this.placeBlock(level, (IBlockData) iblockdata4.setValue(FenceBlock.NORTH, true), 7, 7, 6, box); ++ this.placeBlock(level, (IBlockData) iblockdata4.setValue(FenceBlock.SOUTH, true), 7, 7, 8, box); ++ IBlockData iblockdata6 = Blocks.TORCH.defaultBlockState(); + +- this.placeBlock(worldgenlevel, blockstate6, 5, 8, 7, boundingbox); +- this.placeBlock(worldgenlevel, blockstate6, 8, 8, 7, boundingbox); +- this.placeBlock(worldgenlevel, blockstate6, 6, 8, 6, boundingbox); +- this.placeBlock(worldgenlevel, blockstate6, 6, 8, 8, boundingbox); +- this.placeBlock(worldgenlevel, blockstate6, 7, 8, 6, boundingbox); +- this.placeBlock(worldgenlevel, blockstate6, 7, 8, 8, boundingbox); ++ this.placeBlock(level, iblockdata6, 5, 8, 7, box); ++ this.placeBlock(level, iblockdata6, 8, 8, 7, box); ++ this.placeBlock(level, iblockdata6, 6, 8, 6, box); ++ this.placeBlock(level, iblockdata6, 6, 8, 8, box); ++ this.placeBlock(level, iblockdata6, 7, 8, 6, box); ++ this.placeBlock(level, iblockdata6, 7, 8, 8, box); + } + +- this.createChest(worldgenlevel, boundingbox, randomsource, 3, 3, 5, BuiltInLootTables.STRONGHOLD_LIBRARY); ++ this.createChest(level, box, random, 3, 3, 5, BuiltInLootTables.STRONGHOLD_LIBRARY); + if (this.isTall) { +- this.placeBlock(worldgenlevel, StrongholdPieces.Library.CAVE_AIR, 12, 9, 1, boundingbox); +- this.createChest(worldgenlevel, boundingbox, randomsource, 12, 8, 1, BuiltInLootTables.STRONGHOLD_LIBRARY); ++ this.placeBlock(level, StrongholdPieces.Library.CAVE_AIR, 12, 9, 1, box); ++ this.createChest(level, box, random, 12, 8, 1, BuiltInLootTables.STRONGHOLD_LIBRARY); + } + + } +@@ -1048,132 +1018,134 @@ + protected static final int DEPTH = 16; + private boolean hasPlacedSpawner; + +- public PortalRoom(int i, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.STRONGHOLD_PORTAL_ROOM, i, boundingbox); +- this.setOrientation(direction); ++ public PortalRoom(int genDepth, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_PORTAL_ROOM, genDepth, box); ++ this.setOrientation(orientation); + } + +- public PortalRoom(CompoundTag compoundtag) { +- super(StructurePieceType.STRONGHOLD_PORTAL_ROOM, compoundtag); +- this.hasPlacedSpawner = compoundtag.getBoolean("Mob"); ++ public PortalRoom(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_PORTAL_ROOM, tag); ++ this.hasPlacedSpawner = tag.getBoolean("Mob"); + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- super.addAdditionalSaveData(structurepieceserializationcontext, compoundtag); +- compoundtag.putBoolean("Mob", this.hasPlacedSpawner); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putBoolean("Mob", this.hasPlacedSpawner); + } + + @Override +- @Override +- public void addChildren(StructurePiece structurepiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource) { +- if (structurepiece != null) { +- ((StrongholdPieces.StartPiece) structurepiece).portalRoomPiece = this; ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ if (piece != null) { ++ ((StrongholdPieces.StartPiece) piece).portalRoomPiece = this; + } + + } + +- public static StrongholdPieces.PortalRoom createPiece(StructurePieceAccessor structurepieceaccessor, int i, int j, int k, Direction direction, int l) { +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -4, -1, 0, 11, 8, 16, direction); ++ public static StrongholdPieces.PortalRoom createPiece(StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -4, -1, 0, 11, 8, 16, orientation); + +- return isOkBox(boundingbox) && structurepieceaccessor.findCollisionPiece(boundingbox) == null ? new StrongholdPieces.PortalRoom(l, boundingbox, direction) : null; ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new StrongholdPieces.PortalRoom(genDepth, structureboundingbox, orientation) : null; + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- this.generateBox(worldgenlevel, boundingbox, 0, 0, 0, 10, 7, 15, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateSmallDoor(worldgenlevel, randomsource, boundingbox, StrongholdPieces.StrongholdPiece.SmallDoorType.GRATES, 4, 1, 0); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 10, 7, 15, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateSmallDoor(level, random, box, StrongholdPieces.StrongholdPiece.a.GRATES, 4, 1, 0); + boolean flag = true; + +- this.generateBox(worldgenlevel, boundingbox, 1, 6, 1, 1, 6, 14, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(worldgenlevel, boundingbox, 9, 6, 1, 9, 6, 14, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(worldgenlevel, boundingbox, 2, 6, 1, 8, 6, 2, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(worldgenlevel, boundingbox, 2, 6, 14, 8, 6, 14, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(worldgenlevel, boundingbox, 1, 1, 1, 2, 1, 4, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(worldgenlevel, boundingbox, 8, 1, 1, 9, 1, 4, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(worldgenlevel, boundingbox, 1, 1, 1, 1, 1, 3, Blocks.LAVA.defaultBlockState(), Blocks.LAVA.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 9, 1, 1, 9, 1, 3, Blocks.LAVA.defaultBlockState(), Blocks.LAVA.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 3, 1, 8, 7, 1, 12, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(worldgenlevel, boundingbox, 4, 1, 9, 6, 1, 11, Blocks.LAVA.defaultBlockState(), Blocks.LAVA.defaultBlockState(), false); +- BlockState blockstate = (BlockState) ((BlockState) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, true)).setValue(IronBarsBlock.SOUTH, true); +- BlockState blockstate1 = (BlockState) ((BlockState) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, true)).setValue(IronBarsBlock.EAST, true); ++ this.generateBox(level, box, 1, 6, 1, 1, 6, 14, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 9, 6, 1, 9, 6, 14, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 2, 6, 1, 8, 6, 2, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 2, 6, 14, 8, 6, 14, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 1, 1, 1, 2, 1, 4, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 8, 1, 1, 9, 1, 4, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 1, 1, 1, 1, 1, 3, Blocks.LAVA.defaultBlockState(), Blocks.LAVA.defaultBlockState(), false); ++ this.generateBox(level, box, 9, 1, 1, 9, 1, 3, Blocks.LAVA.defaultBlockState(), Blocks.LAVA.defaultBlockState(), false); ++ this.generateBox(level, box, 3, 1, 8, 7, 1, 12, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 4, 1, 9, 6, 1, 11, Blocks.LAVA.defaultBlockState(), Blocks.LAVA.defaultBlockState(), false); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, true)).setValue(IronBarsBlock.SOUTH, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, true)).setValue(IronBarsBlock.EAST, true); + + int i; + + for (i = 3; i < 14; i += 2) { +- this.generateBox(worldgenlevel, boundingbox, 0, 3, i, 0, 4, i, blockstate, blockstate, false); +- this.generateBox(worldgenlevel, boundingbox, 10, 3, i, 10, 4, i, blockstate, blockstate, false); ++ this.generateBox(level, box, 0, 3, i, 0, 4, i, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 10, 3, i, 10, 4, i, iblockdata, iblockdata, false); + } + + for (i = 2; i < 9; i += 2) { +- this.generateBox(worldgenlevel, boundingbox, i, 3, 15, i, 4, 15, blockstate1, blockstate1, false); ++ this.generateBox(level, box, i, 3, 15, i, 4, 15, iblockdata1, iblockdata1, false); + } + +- BlockState blockstate2 = (BlockState) Blocks.STONE_BRICK_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.NORTH); ++ IBlockData iblockdata2 = (IBlockData) Blocks.STONE_BRICK_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.NORTH); + +- this.generateBox(worldgenlevel, boundingbox, 4, 1, 5, 6, 1, 7, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(worldgenlevel, boundingbox, 4, 2, 6, 6, 2, 7, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(worldgenlevel, boundingbox, 4, 3, 7, 6, 3, 7, false, randomsource, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 4, 1, 5, 6, 1, 7, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 4, 2, 6, 6, 2, 7, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 4, 3, 7, 6, 3, 7, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); + + for (int j = 4; j <= 6; ++j) { +- this.placeBlock(worldgenlevel, blockstate2, j, 1, 4, boundingbox); +- this.placeBlock(worldgenlevel, blockstate2, j, 2, 5, boundingbox); +- this.placeBlock(worldgenlevel, blockstate2, j, 3, 6, boundingbox); ++ this.placeBlock(level, iblockdata2, j, 1, 4, box); ++ this.placeBlock(level, iblockdata2, j, 2, 5, box); ++ this.placeBlock(level, iblockdata2, j, 3, 6, box); + } + +- BlockState blockstate3 = (BlockState) Blocks.END_PORTAL_FRAME.defaultBlockState().setValue(EndPortalFrameBlock.FACING, Direction.NORTH); +- BlockState blockstate4 = (BlockState) Blocks.END_PORTAL_FRAME.defaultBlockState().setValue(EndPortalFrameBlock.FACING, Direction.SOUTH); +- BlockState blockstate5 = (BlockState) Blocks.END_PORTAL_FRAME.defaultBlockState().setValue(EndPortalFrameBlock.FACING, Direction.EAST); +- BlockState blockstate6 = (BlockState) Blocks.END_PORTAL_FRAME.defaultBlockState().setValue(EndPortalFrameBlock.FACING, Direction.WEST); ++ IBlockData iblockdata3 = (IBlockData) Blocks.END_PORTAL_FRAME.defaultBlockState().setValue(EndPortalFrameBlock.FACING, Direction.NORTH); ++ IBlockData iblockdata4 = (IBlockData) Blocks.END_PORTAL_FRAME.defaultBlockState().setValue(EndPortalFrameBlock.FACING, Direction.SOUTH); ++ IBlockData iblockdata5 = (IBlockData) Blocks.END_PORTAL_FRAME.defaultBlockState().setValue(EndPortalFrameBlock.FACING, Direction.EAST); ++ IBlockData iblockdata6 = (IBlockData) Blocks.END_PORTAL_FRAME.defaultBlockState().setValue(EndPortalFrameBlock.FACING, Direction.WEST); + boolean flag1 = true; + boolean[] aboolean = new boolean[12]; + + for (int k = 0; k < aboolean.length; ++k) { +- aboolean[k] = randomsource.nextFloat() > 0.9F; ++ aboolean[k] = random.nextFloat() > 0.9F; + flag1 &= aboolean[k]; + } + +- this.placeBlock(worldgenlevel, (BlockState) blockstate3.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[0]), 4, 3, 8, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) blockstate3.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[1]), 5, 3, 8, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) blockstate3.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[2]), 6, 3, 8, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) blockstate4.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[3]), 4, 3, 12, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) blockstate4.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[4]), 5, 3, 12, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) blockstate4.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[5]), 6, 3, 12, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) blockstate5.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[6]), 3, 3, 9, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) blockstate5.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[7]), 3, 3, 10, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) blockstate5.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[8]), 3, 3, 11, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) blockstate6.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[9]), 7, 3, 9, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) blockstate6.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[10]), 7, 3, 10, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) blockstate6.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[11]), 7, 3, 11, boundingbox); ++ this.placeBlock(level, (IBlockData) iblockdata3.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[0]), 4, 3, 8, box); ++ this.placeBlock(level, (IBlockData) iblockdata3.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[1]), 5, 3, 8, box); ++ this.placeBlock(level, (IBlockData) iblockdata3.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[2]), 6, 3, 8, box); ++ this.placeBlock(level, (IBlockData) iblockdata4.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[3]), 4, 3, 12, box); ++ this.placeBlock(level, (IBlockData) iblockdata4.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[4]), 5, 3, 12, box); ++ this.placeBlock(level, (IBlockData) iblockdata4.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[5]), 6, 3, 12, box); ++ this.placeBlock(level, (IBlockData) iblockdata5.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[6]), 3, 3, 9, box); ++ this.placeBlock(level, (IBlockData) iblockdata5.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[7]), 3, 3, 10, box); ++ this.placeBlock(level, (IBlockData) iblockdata5.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[8]), 3, 3, 11, box); ++ this.placeBlock(level, (IBlockData) iblockdata6.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[9]), 7, 3, 9, box); ++ this.placeBlock(level, (IBlockData) iblockdata6.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[10]), 7, 3, 10, box); ++ this.placeBlock(level, (IBlockData) iblockdata6.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[11]), 7, 3, 11, box); + if (flag1) { +- BlockState blockstate7 = Blocks.END_PORTAL.defaultBlockState(); ++ IBlockData iblockdata7 = Blocks.END_PORTAL.defaultBlockState(); + +- this.placeBlock(worldgenlevel, blockstate7, 4, 3, 9, boundingbox); +- this.placeBlock(worldgenlevel, blockstate7, 5, 3, 9, boundingbox); +- this.placeBlock(worldgenlevel, blockstate7, 6, 3, 9, boundingbox); +- this.placeBlock(worldgenlevel, blockstate7, 4, 3, 10, boundingbox); +- this.placeBlock(worldgenlevel, blockstate7, 5, 3, 10, boundingbox); +- this.placeBlock(worldgenlevel, blockstate7, 6, 3, 10, boundingbox); +- this.placeBlock(worldgenlevel, blockstate7, 4, 3, 11, boundingbox); +- this.placeBlock(worldgenlevel, blockstate7, 5, 3, 11, boundingbox); +- this.placeBlock(worldgenlevel, blockstate7, 6, 3, 11, boundingbox); ++ this.placeBlock(level, iblockdata7, 4, 3, 9, box); ++ this.placeBlock(level, iblockdata7, 5, 3, 9, box); ++ this.placeBlock(level, iblockdata7, 6, 3, 9, box); ++ this.placeBlock(level, iblockdata7, 4, 3, 10, box); ++ this.placeBlock(level, iblockdata7, 5, 3, 10, box); ++ this.placeBlock(level, iblockdata7, 6, 3, 10, box); ++ this.placeBlock(level, iblockdata7, 4, 3, 11, box); ++ this.placeBlock(level, iblockdata7, 5, 3, 11, box); ++ this.placeBlock(level, iblockdata7, 6, 3, 11, box); + } + + if (!this.hasPlacedSpawner) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = this.getWorldPos(5, 3, 6); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(5, 3, 6); + +- if (boundingbox.isInside(blockpos_mutableblockpos)) { ++ if (box.isInside(blockposition_mutableblockposition)) { + this.hasPlacedSpawner = true; +- worldgenlevel.setBlock(blockpos_mutableblockpos, Blocks.SPAWNER.defaultBlockState(), 2); +- BlockEntity blockentity = worldgenlevel.getBlockEntity(blockpos_mutableblockpos); ++ // CraftBukkit start ++ /* ++ generatoraccessseed.setBlock(blockposition_mutableblockposition, Blocks.SPAWNER.defaultBlockState(), 2); ++ TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); + +- if (blockentity instanceof SpawnerBlockEntity) { +- SpawnerBlockEntity spawnerblockentity = (SpawnerBlockEntity) blockentity; ++ if (tileentity instanceof TileEntityMobSpawner) { ++ TileEntityMobSpawner tileentitymobspawner = (TileEntityMobSpawner) tileentity; + +- spawnerblockentity.setEntityId(EntityType.SILVERFISH, randomsource); ++ tileentitymobspawner.setEntityId(EntityTypes.SILVERFISH, randomsource); + } ++ */ ++ placeCraftSpawner(level, blockposition_mutableblockposition, org.bukkit.entity.EntityType.SILVERFISH, 2); ++ // CraftBukkit end + } + } + +@@ -1182,99 +1154,98 @@ + + private abstract static class StrongholdPiece extends StructurePiece { + +- protected StrongholdPieces.StrongholdPiece.SmallDoorType entryDoor; ++ protected StrongholdPieces.StrongholdPiece.a entryDoor; + +- protected StrongholdPiece(StructurePieceType structurepiecetype, int i, BoundingBox boundingbox) { +- super(structurepiecetype, i, boundingbox); +- this.entryDoor = StrongholdPieces.StrongholdPiece.SmallDoorType.OPENING; ++ protected StrongholdPiece(StructurePieceType type, int genDepth, BoundingBox boundingBox) { ++ super(type, genDepth, boundingBox); ++ this.entryDoor = StrongholdPieces.StrongholdPiece.a.OPENING; + } + +- public StrongholdPiece(StructurePieceType structurepiecetype, CompoundTag compoundtag) { +- super(structurepiecetype, compoundtag); +- this.entryDoor = StrongholdPieces.StrongholdPiece.SmallDoorType.OPENING; +- this.entryDoor = StrongholdPieces.StrongholdPiece.SmallDoorType.valueOf(compoundtag.getString("EntryDoor")); ++ public StrongholdPiece(StructurePieceType type, CompoundTag tag) { ++ super(type, tag); ++ this.entryDoor = StrongholdPieces.StrongholdPiece.a.OPENING; ++ this.entryDoor = StrongholdPieces.StrongholdPiece.a.valueOf(tag.getString("EntryDoor")); + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- compoundtag.putString("EntryDoor", this.entryDoor.name()); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ tag.putString("EntryDoor", this.entryDoor.name()); + } + +- protected void generateSmallDoor(WorldGenLevel worldgenlevel, RandomSource randomsource, BoundingBox boundingbox, StrongholdPieces.StrongholdPiece.SmallDoorType strongholdpieces_strongholdpiece_smalldoortype, int i, int j, int k) { +- switch (strongholdpieces_strongholdpiece_smalldoortype) { ++ protected void generateSmallDoor(WorldGenLevel level, RandomSource random, BoundingBox box, StrongholdPieces.StrongholdPiece.a type, int x, int y, int z) { ++ switch (type) { + case OPENING: +- this.generateBox(worldgenlevel, boundingbox, i, j, k, i + 3 - 1, j + 3 - 1, k, StrongholdPieces.StrongholdPiece.CAVE_AIR, StrongholdPieces.StrongholdPiece.CAVE_AIR, false); ++ this.generateBox(level, box, x, y, z, x + 3 - 1, y + 3 - 1, z, StrongholdPieces.StrongholdPiece.CAVE_AIR, StrongholdPieces.StrongholdPiece.CAVE_AIR, false); + break; + case WOOD_DOOR: +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), i, j, k, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), i, j + 1, k, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), i, j + 2, k, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), i + 1, j + 2, k, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), i + 2, j + 2, k, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), i + 2, j + 1, k, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), i + 2, j, k, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.OAK_DOOR.defaultBlockState(), i + 1, j, k, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) Blocks.OAK_DOOR.defaultBlockState().setValue(DoorBlock.HALF, DoubleBlockHalf.UPPER), i + 1, j + 1, k, boundingbox); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), x, y, z, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), x, y + 1, z, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), x, y + 2, z, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), x + 1, y + 2, z, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), x + 2, y + 2, z, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), x + 2, y + 1, z, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), x + 2, y, z, box); ++ this.placeBlock(level, Blocks.OAK_DOOR.defaultBlockState(), x + 1, y, z, box); ++ this.placeBlock(level, (IBlockData) Blocks.OAK_DOOR.defaultBlockState().setValue(DoorBlock.HALF, BlockPropertyDoubleBlockHalf.UPPER), x + 1, y + 1, z, box); + break; + case GRATES: +- this.placeBlock(worldgenlevel, Blocks.CAVE_AIR.defaultBlockState(), i + 1, j, k, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.CAVE_AIR.defaultBlockState(), i + 1, j + 1, k, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, true), i, j, k, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, true), i, j + 1, k, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.EAST, true)).setValue(IronBarsBlock.WEST, true), i, j + 2, k, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.EAST, true)).setValue(IronBarsBlock.WEST, true), i + 1, j + 2, k, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) ((BlockState) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.EAST, true)).setValue(IronBarsBlock.WEST, true), i + 2, j + 2, k, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.EAST, true), i + 2, j + 1, k, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.EAST, true), i + 2, j, k, boundingbox); ++ this.placeBlock(level, Blocks.CAVE_AIR.defaultBlockState(), x + 1, y, z, box); ++ this.placeBlock(level, Blocks.CAVE_AIR.defaultBlockState(), x + 1, y + 1, z, box); ++ this.placeBlock(level, (IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, true), x, y, z, box); ++ this.placeBlock(level, (IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, true), x, y + 1, z, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.EAST, true)).setValue(IronBarsBlock.WEST, true), x, y + 2, z, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.EAST, true)).setValue(IronBarsBlock.WEST, true), x + 1, y + 2, z, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.EAST, true)).setValue(IronBarsBlock.WEST, true), x + 2, y + 2, z, box); ++ this.placeBlock(level, (IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.EAST, true), x + 2, y + 1, z, box); ++ this.placeBlock(level, (IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.EAST, true), x + 2, y, z, box); + break; + case IRON_DOOR: +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), i, j, k, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), i, j + 1, k, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), i, j + 2, k, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), i + 1, j + 2, k, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), i + 2, j + 2, k, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), i + 2, j + 1, k, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), i + 2, j, k, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.IRON_DOOR.defaultBlockState(), i + 1, j, k, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) Blocks.IRON_DOOR.defaultBlockState().setValue(DoorBlock.HALF, DoubleBlockHalf.UPPER), i + 1, j + 1, k, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) Blocks.STONE_BUTTON.defaultBlockState().setValue(ButtonBlock.FACING, Direction.NORTH), i + 2, j + 1, k + 1, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) Blocks.STONE_BUTTON.defaultBlockState().setValue(ButtonBlock.FACING, Direction.SOUTH), i + 2, j + 1, k - 1, boundingbox); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), x, y, z, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), x, y + 1, z, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), x, y + 2, z, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), x + 1, y + 2, z, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), x + 2, y + 2, z, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), x + 2, y + 1, z, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), x + 2, y, z, box); ++ this.placeBlock(level, Blocks.IRON_DOOR.defaultBlockState(), x + 1, y, z, box); ++ this.placeBlock(level, (IBlockData) Blocks.IRON_DOOR.defaultBlockState().setValue(DoorBlock.HALF, BlockPropertyDoubleBlockHalf.UPPER), x + 1, y + 1, z, box); ++ this.placeBlock(level, (IBlockData) Blocks.STONE_BUTTON.defaultBlockState().setValue(ButtonBlock.FACING, Direction.NORTH), x + 2, y + 1, z + 1, box); ++ this.placeBlock(level, (IBlockData) Blocks.STONE_BUTTON.defaultBlockState().setValue(ButtonBlock.FACING, Direction.SOUTH), x + 2, y + 1, z - 1, box); + } + + } + +- protected StrongholdPieces.StrongholdPiece.SmallDoorType randomSmallDoor(RandomSource randomsource) { +- int i = randomsource.nextInt(5); ++ protected StrongholdPieces.StrongholdPiece.a randomSmallDoor(RandomSource random) { ++ int i = random.nextInt(5); + + switch (i) { + case 0: + case 1: + default: +- return StrongholdPieces.StrongholdPiece.SmallDoorType.OPENING; ++ return StrongholdPieces.StrongholdPiece.a.OPENING; + case 2: +- return StrongholdPieces.StrongholdPiece.SmallDoorType.WOOD_DOOR; ++ return StrongholdPieces.StrongholdPiece.a.WOOD_DOOR; + case 3: +- return StrongholdPieces.StrongholdPiece.SmallDoorType.GRATES; ++ return StrongholdPieces.StrongholdPiece.a.GRATES; + case 4: +- return StrongholdPieces.StrongholdPiece.SmallDoorType.IRON_DOOR; ++ return StrongholdPieces.StrongholdPiece.a.IRON_DOOR; + } + } + + @Nullable +- protected StructurePiece generateSmallDoorChildForward(StrongholdPieces.StartPiece strongholdpieces_startpiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j) { +- Direction direction = this.getOrientation(); ++ protected StructurePiece generateSmallDoorChildForward(StrongholdPieces.StartPiece startPiece, StructurePieceAccessor pieces, RandomSource random, int offsetX, int offsetY) { ++ Direction enumdirection = this.getOrientation(); + +- if (direction != null) { +- switch (direction) { ++ if (enumdirection != null) { ++ switch (enumdirection) { + case NORTH: +- return StrongholdPieces.generateAndAddPiece(strongholdpieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + i, this.boundingBox.minY() + j, this.boundingBox.minZ() - 1, direction, this.getGenDepth()); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() - 1, enumdirection, this.getGenDepth()); + case SOUTH: +- return StrongholdPieces.generateAndAddPiece(strongholdpieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + i, this.boundingBox.minY() + j, this.boundingBox.maxZ() + 1, direction, this.getGenDepth()); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.maxZ() + 1, enumdirection, this.getGenDepth()); + case WEST: +- return StrongholdPieces.generateAndAddPiece(strongholdpieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.minX() - 1, this.boundingBox.minY() + j, this.boundingBox.minZ() + i, direction, this.getGenDepth()); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, enumdirection, this.getGenDepth()); + case EAST: +- return StrongholdPieces.generateAndAddPiece(strongholdpieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.maxX() + 1, this.boundingBox.minY() + j, this.boundingBox.minZ() + i, direction, this.getGenDepth()); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, enumdirection, this.getGenDepth()); + } + } + +@@ -1282,19 +1253,19 @@ + } + + @Nullable +- protected StructurePiece generateSmallDoorChildLeft(StrongholdPieces.StartPiece strongholdpieces_startpiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j) { +- Direction direction = this.getOrientation(); ++ protected StructurePiece generateSmallDoorChildLeft(StrongholdPieces.StartPiece startPiece, StructurePieceAccessor pieces, RandomSource random, int offsetY, int offsetX) { ++ Direction enumdirection = this.getOrientation(); + +- if (direction != null) { +- switch (direction) { ++ if (enumdirection != null) { ++ switch (enumdirection) { + case NORTH: +- return StrongholdPieces.generateAndAddPiece(strongholdpieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.minX() - 1, this.boundingBox.minY() + i, this.boundingBox.minZ() + j, Direction.WEST, this.getGenDepth()); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, Direction.WEST, this.getGenDepth()); + case SOUTH: +- return StrongholdPieces.generateAndAddPiece(strongholdpieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.minX() - 1, this.boundingBox.minY() + i, this.boundingBox.minZ() + j, Direction.WEST, this.getGenDepth()); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, Direction.WEST, this.getGenDepth()); + case WEST: +- return StrongholdPieces.generateAndAddPiece(strongholdpieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + j, this.boundingBox.minY() + i, this.boundingBox.minZ() - 1, Direction.NORTH, this.getGenDepth()); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() - 1, Direction.NORTH, this.getGenDepth()); + case EAST: +- return StrongholdPieces.generateAndAddPiece(strongholdpieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + j, this.boundingBox.minY() + i, this.boundingBox.minZ() - 1, Direction.NORTH, this.getGenDepth()); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() - 1, Direction.NORTH, this.getGenDepth()); + } + } + +@@ -1302,34 +1273,34 @@ + } + + @Nullable +- protected StructurePiece generateSmallDoorChildRight(StrongholdPieces.StartPiece strongholdpieces_startpiece, StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j) { +- Direction direction = this.getOrientation(); ++ protected StructurePiece generateSmallDoorChildRight(StrongholdPieces.StartPiece startPiece, StructurePieceAccessor pieces, RandomSource random, int offsetY, int offsetX) { ++ Direction enumdirection = this.getOrientation(); + +- if (direction != null) { +- switch (direction) { ++ if (enumdirection != null) { ++ switch (enumdirection) { + case NORTH: +- return StrongholdPieces.generateAndAddPiece(strongholdpieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.maxX() + 1, this.boundingBox.minY() + i, this.boundingBox.minZ() + j, Direction.EAST, this.getGenDepth()); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, Direction.EAST, this.getGenDepth()); + case SOUTH: +- return StrongholdPieces.generateAndAddPiece(strongholdpieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.maxX() + 1, this.boundingBox.minY() + i, this.boundingBox.minZ() + j, Direction.EAST, this.getGenDepth()); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, Direction.EAST, this.getGenDepth()); + case WEST: +- return StrongholdPieces.generateAndAddPiece(strongholdpieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + j, this.boundingBox.minY() + i, this.boundingBox.maxZ() + 1, Direction.SOUTH, this.getGenDepth()); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.maxZ() + 1, Direction.SOUTH, this.getGenDepth()); + case EAST: +- return StrongholdPieces.generateAndAddPiece(strongholdpieces_startpiece, structurepieceaccessor, randomsource, this.boundingBox.minX() + j, this.boundingBox.minY() + i, this.boundingBox.maxZ() + 1, Direction.SOUTH, this.getGenDepth()); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.maxZ() + 1, Direction.SOUTH, this.getGenDepth()); + } + } + + return null; + } + +- protected static boolean isOkBox(BoundingBox boundingbox) { +- return boundingbox != null && boundingbox.minY() > 10; ++ protected static boolean isOkBox(BoundingBox box) { ++ return box != null && box.minY() > 10; + } + +- protected static enum SmallDoorType { ++ protected static enum a { + + OPENING, WOOD_DOOR, GRATES, IRON_DOOR; + +- private SmallDoorType() {} ++ private a() {} + } + } + +@@ -1340,16 +1311,15 @@ + public StrongholdPieces.PortalRoom portalRoomPiece; + public final List pendingChildren = Lists.newArrayList(); + +- public StartPiece(RandomSource randomsource, int i, int j) { +- super(StructurePieceType.STRONGHOLD_START, 0, i, j, getRandomHorizontalDirection(randomsource)); ++ public StartPiece(RandomSource random, int x, int z) { ++ super(StructurePieceType.STRONGHOLD_START, 0, x, z, getRandomHorizontalDirection(random)); + } + +- public StartPiece(CompoundTag compoundtag) { +- super(StructurePieceType.STRONGHOLD_START, compoundtag); ++ public StartPiece(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_START, tag); + } + + @Override +- @Override + public BlockPos getLocatorPosition() { + return this.portalRoomPiece != null ? this.portalRoomPiece.getLocatorPosition() : super.getLocatorPosition(); + } +@@ -1359,37 +1329,36 @@ + + private final int steps; + +- public FillerCorridor(int i, BoundingBox boundingbox, Direction direction) { +- super(StructurePieceType.STRONGHOLD_FILLER_CORRIDOR, i, boundingbox); +- this.setOrientation(direction); +- this.steps = direction != Direction.NORTH && direction != Direction.SOUTH ? boundingbox.getXSpan() : boundingbox.getZSpan(); ++ public FillerCorridor(int genDepth, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_FILLER_CORRIDOR, genDepth, box); ++ this.setOrientation(orientation); ++ this.steps = orientation != Direction.NORTH && orientation != Direction.SOUTH ? box.getXSpan() : box.getZSpan(); + } + +- public FillerCorridor(CompoundTag compoundtag) { +- super(StructurePieceType.STRONGHOLD_FILLER_CORRIDOR, compoundtag); +- this.steps = compoundtag.getInt("Steps"); ++ public FillerCorridor(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_FILLER_CORRIDOR, tag); ++ this.steps = tag.getInt("Steps"); + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- super.addAdditionalSaveData(structurepieceserializationcontext, compoundtag); +- compoundtag.putInt("Steps", this.steps); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putInt("Steps", this.steps); + } + +- public static BoundingBox findPieceBox(StructurePieceAccessor structurepieceaccessor, RandomSource randomsource, int i, int j, int k, Direction direction) { ++ public static BoundingBox findPieceBox(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation) { + boolean flag = true; +- BoundingBox boundingbox = BoundingBox.orientBox(i, j, k, -1, -1, 0, 5, 5, 4, direction); +- StructurePiece structurepiece = structurepieceaccessor.findCollisionPiece(boundingbox); ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, 4, orientation); ++ StructurePiece structurepiece = pieces.findCollisionPiece(structureboundingbox); + + if (structurepiece == null) { + return null; + } else { +- if (structurepiece.getBoundingBox().minY() == boundingbox.minY()) { ++ if (structurepiece.getBoundingBox().minY() == structureboundingbox.minY()) { + for (int l = 2; l >= 1; --l) { +- boundingbox = BoundingBox.orientBox(i, j, k, -1, -1, 0, 5, 5, l, direction); +- if (!structurepiece.getBoundingBox().intersects(boundingbox)) { +- return BoundingBox.orientBox(i, j, k, -1, -1, 0, 5, 5, l + 1, direction); ++ structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, l, orientation); ++ if (!structurepiece.getBoundingBox().intersects(structureboundingbox)) { ++ return BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, l + 1, orientation); + } + } + } +@@ -1399,42 +1368,40 @@ + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { + for (int i = 0; i < this.steps; ++i) { +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 0, 0, i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 1, 0, i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 2, 0, i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 3, 0, i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 4, 0, i, boundingbox); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 0, 0, i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 1, 0, i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 2, 0, i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 3, 0, i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 4, 0, i, box); + + for (int j = 1; j <= 3; ++j) { +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 0, j, i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.CAVE_AIR.defaultBlockState(), 1, j, i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.CAVE_AIR.defaultBlockState(), 2, j, i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.CAVE_AIR.defaultBlockState(), 3, j, i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 4, j, i, boundingbox); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 0, j, i, box); ++ this.placeBlock(level, Blocks.CAVE_AIR.defaultBlockState(), 1, j, i, box); ++ this.placeBlock(level, Blocks.CAVE_AIR.defaultBlockState(), 2, j, i, box); ++ this.placeBlock(level, Blocks.CAVE_AIR.defaultBlockState(), 3, j, i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 4, j, i, box); + } + +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 0, 4, i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 1, 4, i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 2, 4, i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 3, 4, i, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.STONE_BRICKS.defaultBlockState(), 4, 4, i, boundingbox); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 0, 4, i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 1, 4, i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 2, 4, i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 3, 4, i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 4, 4, i, box); + } + + } + } + +- private static class SmoothStoneSelector extends StructurePiece.BlockSelector { ++ private static class k extends StructurePiece.BlockSelector { + +- SmoothStoneSelector() {} ++ k() {} + + @Override +- @Override +- public void next(RandomSource randomsource, int i, int j, int k, boolean flag) { +- if (flag) { +- float f = randomsource.nextFloat(); ++ public void next(RandomSource random, int x, int y, int z, boolean wall) { ++ if (wall) { ++ float f = random.nextFloat(); + + if (f < 0.2F) { + this.next = Blocks.CRACKED_STONE_BRICKS.defaultBlockState(); +@@ -1452,18 +1419,18 @@ + } + } + +- public abstract static class Turn extends StrongholdPieces.StrongholdPiece { ++ public abstract static class q extends StrongholdPieces.StrongholdPiece { + + protected static final int WIDTH = 5; + protected static final int HEIGHT = 5; + protected static final int DEPTH = 5; + +- protected Turn(StructurePieceType structurepiecetype, int i, BoundingBox boundingbox) { +- super(structurepiecetype, i, boundingbox); ++ protected q(StructurePieceType type, int genDepth, BoundingBox boundingBox) { ++ super(type, genDepth, boundingBox); + } + +- public Turn(StructurePieceType structurepiecetype, CompoundTag compoundtag) { +- super(structurepiecetype, compoundtag); ++ public q(StructurePieceType type, CompoundTag tag) { ++ super(type, tag); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java.patch new file mode 100644 index 0000000000..e1dbc0d6bc --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java.patch @@ -0,0 +1,189 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java +@@ -5,8 +5,8 @@ + import net.minecraft.nbt.CompoundTag; + import net.minecraft.util.RandomSource; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.animal.Cat; + import net.minecraft.world.entity.monster.Witch; + import net.minecraft.world.level.ChunkPos; +@@ -15,7 +15,7 @@ + import net.minecraft.world.level.WorldGenLevel; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.StairBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.StairsShape; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.levelgen.structure.BoundingBox; +@@ -28,102 +28,100 @@ + private boolean spawnedWitch; + private boolean spawnedCat; + +- public SwampHutPiece(RandomSource randomsource, int i, int j) { +- super(StructurePieceType.SWAMPLAND_HUT, i, 64, j, 7, 7, 9, getRandomHorizontalDirection(randomsource)); ++ public SwampHutPiece(RandomSource random, int x, int z) { ++ super(StructurePieceType.SWAMPLAND_HUT, x, 64, z, 7, 7, 9, getRandomHorizontalDirection(random)); + } + +- public SwampHutPiece(CompoundTag compoundtag) { +- super(StructurePieceType.SWAMPLAND_HUT, compoundtag); +- this.spawnedWitch = compoundtag.getBoolean("Witch"); +- this.spawnedCat = compoundtag.getBoolean("Cat"); ++ public SwampHutPiece(CompoundTag tag) { ++ super(StructurePieceType.SWAMPLAND_HUT, tag); ++ this.spawnedWitch = tag.getBoolean("Witch"); ++ this.spawnedCat = tag.getBoolean("Cat"); + } + + @Override +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, CompoundTag compoundtag) { +- super.addAdditionalSaveData(structurepieceserializationcontext, compoundtag); +- compoundtag.putBoolean("Witch", this.spawnedWitch); +- compoundtag.putBoolean("Cat", this.spawnedCat); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putBoolean("Witch", this.spawnedWitch); ++ tag.putBoolean("Cat", this.spawnedCat); + } + + @Override +- @Override +- public void postProcess(WorldGenLevel worldgenlevel, StructureManager structuremanager, ChunkGenerator chunkgenerator, RandomSource randomsource, BoundingBox boundingbox, ChunkPos chunkpos, BlockPos blockpos) { +- if (this.updateAverageGroundHeight(worldgenlevel, boundingbox, 0)) { +- this.generateBox(worldgenlevel, boundingbox, 1, 1, 1, 5, 1, 7, Blocks.SPRUCE_PLANKS.defaultBlockState(), Blocks.SPRUCE_PLANKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 4, 2, 5, 4, 7, Blocks.SPRUCE_PLANKS.defaultBlockState(), Blocks.SPRUCE_PLANKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 2, 1, 0, 4, 1, 0, Blocks.SPRUCE_PLANKS.defaultBlockState(), Blocks.SPRUCE_PLANKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 2, 2, 2, 3, 3, 2, Blocks.SPRUCE_PLANKS.defaultBlockState(), Blocks.SPRUCE_PLANKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 2, 3, 1, 3, 6, Blocks.SPRUCE_PLANKS.defaultBlockState(), Blocks.SPRUCE_PLANKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 5, 2, 3, 5, 3, 6, Blocks.SPRUCE_PLANKS.defaultBlockState(), Blocks.SPRUCE_PLANKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 2, 2, 7, 4, 3, 7, Blocks.SPRUCE_PLANKS.defaultBlockState(), Blocks.SPRUCE_PLANKS.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 0, 2, 1, 3, 2, Blocks.OAK_LOG.defaultBlockState(), Blocks.OAK_LOG.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 5, 0, 2, 5, 3, 2, Blocks.OAK_LOG.defaultBlockState(), Blocks.OAK_LOG.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 1, 0, 7, 1, 3, 7, Blocks.OAK_LOG.defaultBlockState(), Blocks.OAK_LOG.defaultBlockState(), false); +- this.generateBox(worldgenlevel, boundingbox, 5, 0, 7, 5, 3, 7, Blocks.OAK_LOG.defaultBlockState(), Blocks.OAK_LOG.defaultBlockState(), false); +- this.placeBlock(worldgenlevel, Blocks.OAK_FENCE.defaultBlockState(), 2, 3, 2, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.OAK_FENCE.defaultBlockState(), 3, 3, 7, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.AIR.defaultBlockState(), 1, 3, 4, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.AIR.defaultBlockState(), 5, 3, 4, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.AIR.defaultBlockState(), 5, 3, 5, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.POTTED_RED_MUSHROOM.defaultBlockState(), 1, 3, 5, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.CRAFTING_TABLE.defaultBlockState(), 3, 2, 6, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.CAULDRON.defaultBlockState(), 4, 2, 6, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.OAK_FENCE.defaultBlockState(), 1, 2, 1, boundingbox); +- this.placeBlock(worldgenlevel, Blocks.OAK_FENCE.defaultBlockState(), 5, 2, 1, boundingbox); +- BlockState blockstate = (BlockState) Blocks.SPRUCE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.NORTH); +- BlockState blockstate1 = (BlockState) Blocks.SPRUCE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.EAST); +- BlockState blockstate2 = (BlockState) Blocks.SPRUCE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.WEST); +- BlockState blockstate3 = (BlockState) Blocks.SPRUCE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.SOUTH); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ if (this.updateAverageGroundHeight(level, box, 0)) { ++ this.generateBox(level, box, 1, 1, 1, 5, 1, 7, Blocks.SPRUCE_PLANKS.defaultBlockState(), Blocks.SPRUCE_PLANKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 4, 2, 5, 4, 7, Blocks.SPRUCE_PLANKS.defaultBlockState(), Blocks.SPRUCE_PLANKS.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 1, 0, 4, 1, 0, Blocks.SPRUCE_PLANKS.defaultBlockState(), Blocks.SPRUCE_PLANKS.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 2, 2, 3, 3, 2, Blocks.SPRUCE_PLANKS.defaultBlockState(), Blocks.SPRUCE_PLANKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 2, 3, 1, 3, 6, Blocks.SPRUCE_PLANKS.defaultBlockState(), Blocks.SPRUCE_PLANKS.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 2, 3, 5, 3, 6, Blocks.SPRUCE_PLANKS.defaultBlockState(), Blocks.SPRUCE_PLANKS.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 2, 7, 4, 3, 7, Blocks.SPRUCE_PLANKS.defaultBlockState(), Blocks.SPRUCE_PLANKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 0, 2, 1, 3, 2, Blocks.OAK_LOG.defaultBlockState(), Blocks.OAK_LOG.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 0, 2, 5, 3, 2, Blocks.OAK_LOG.defaultBlockState(), Blocks.OAK_LOG.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 0, 7, 1, 3, 7, Blocks.OAK_LOG.defaultBlockState(), Blocks.OAK_LOG.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 0, 7, 5, 3, 7, Blocks.OAK_LOG.defaultBlockState(), Blocks.OAK_LOG.defaultBlockState(), false); ++ this.placeBlock(level, Blocks.OAK_FENCE.defaultBlockState(), 2, 3, 2, box); ++ this.placeBlock(level, Blocks.OAK_FENCE.defaultBlockState(), 3, 3, 7, box); ++ this.placeBlock(level, Blocks.AIR.defaultBlockState(), 1, 3, 4, box); ++ this.placeBlock(level, Blocks.AIR.defaultBlockState(), 5, 3, 4, box); ++ this.placeBlock(level, Blocks.AIR.defaultBlockState(), 5, 3, 5, box); ++ this.placeBlock(level, Blocks.POTTED_RED_MUSHROOM.defaultBlockState(), 1, 3, 5, box); ++ this.placeBlock(level, Blocks.CRAFTING_TABLE.defaultBlockState(), 3, 2, 6, box); ++ this.placeBlock(level, Blocks.CAULDRON.defaultBlockState(), 4, 2, 6, box); ++ this.placeBlock(level, Blocks.OAK_FENCE.defaultBlockState(), 1, 2, 1, box); ++ this.placeBlock(level, Blocks.OAK_FENCE.defaultBlockState(), 5, 2, 1, box); ++ IBlockData iblockdata = (IBlockData) Blocks.SPRUCE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.NORTH); ++ IBlockData iblockdata1 = (IBlockData) Blocks.SPRUCE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.EAST); ++ IBlockData iblockdata2 = (IBlockData) Blocks.SPRUCE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.WEST); ++ IBlockData iblockdata3 = (IBlockData) Blocks.SPRUCE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.SOUTH); + +- this.generateBox(worldgenlevel, boundingbox, 0, 4, 1, 6, 4, 1, blockstate, blockstate, false); +- this.generateBox(worldgenlevel, boundingbox, 0, 4, 2, 0, 4, 7, blockstate1, blockstate1, false); +- this.generateBox(worldgenlevel, boundingbox, 6, 4, 2, 6, 4, 7, blockstate2, blockstate2, false); +- this.generateBox(worldgenlevel, boundingbox, 0, 4, 8, 6, 4, 8, blockstate3, blockstate3, false); +- this.placeBlock(worldgenlevel, (BlockState) blockstate.setValue(StairBlock.SHAPE, StairsShape.OUTER_RIGHT), 0, 4, 1, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) blockstate.setValue(StairBlock.SHAPE, StairsShape.OUTER_LEFT), 6, 4, 1, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) blockstate3.setValue(StairBlock.SHAPE, StairsShape.OUTER_LEFT), 0, 4, 8, boundingbox); +- this.placeBlock(worldgenlevel, (BlockState) blockstate3.setValue(StairBlock.SHAPE, StairsShape.OUTER_RIGHT), 6, 4, 8, boundingbox); ++ this.generateBox(level, box, 0, 4, 1, 6, 4, 1, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 0, 4, 2, 0, 4, 7, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 6, 4, 2, 6, 4, 7, iblockdata2, iblockdata2, false); ++ this.generateBox(level, box, 0, 4, 8, 6, 4, 8, iblockdata3, iblockdata3, false); ++ this.placeBlock(level, (IBlockData) iblockdata.setValue(StairBlock.SHAPE, StairsShape.OUTER_RIGHT), 0, 4, 1, box); ++ this.placeBlock(level, (IBlockData) iblockdata.setValue(StairBlock.SHAPE, StairsShape.OUTER_LEFT), 6, 4, 1, box); ++ this.placeBlock(level, (IBlockData) iblockdata3.setValue(StairBlock.SHAPE, StairsShape.OUTER_LEFT), 0, 4, 8, box); ++ this.placeBlock(level, (IBlockData) iblockdata3.setValue(StairBlock.SHAPE, StairsShape.OUTER_RIGHT), 6, 4, 8, box); + + for (int i = 2; i <= 7; i += 5) { + for (int j = 1; j <= 5; j += 4) { +- this.fillColumnDown(worldgenlevel, Blocks.OAK_LOG.defaultBlockState(), j, -1, i, boundingbox); ++ this.fillColumnDown(level, Blocks.OAK_LOG.defaultBlockState(), j, -1, i, box); + } + } + + if (!this.spawnedWitch) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = this.getWorldPos(2, 2, 5); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(2, 2, 5); + +- if (boundingbox.isInside(blockpos_mutableblockpos)) { ++ if (box.isInside(blockposition_mutableblockposition)) { + this.spawnedWitch = true; +- Witch witch = (Witch) EntityType.WITCH.create(worldgenlevel.getLevel()); ++ Witch entitywitch = (Witch) EntityType.WITCH.create(level.getLevel()); + +- if (witch != null) { +- witch.setPersistenceRequired(); +- witch.moveTo((double) blockpos_mutableblockpos.getX() + 0.5D, (double) blockpos_mutableblockpos.getY(), (double) blockpos_mutableblockpos.getZ() + 0.5D, 0.0F, 0.0F); +- witch.finalizeSpawn(worldgenlevel, worldgenlevel.getCurrentDifficultyAt(blockpos_mutableblockpos), MobSpawnType.STRUCTURE, (SpawnGroupData) null, (CompoundTag) null); +- worldgenlevel.addFreshEntityWithPassengers(witch); ++ if (entitywitch != null) { ++ entitywitch.setPersistenceRequired(); ++ entitywitch.moveTo((double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + 0.5D, 0.0F, 0.0F); ++ entitywitch.finalizeSpawn(level, level.getCurrentDifficultyAt(blockposition_mutableblockposition), EnumMobSpawn.STRUCTURE, (GroupDataEntity) null, (CompoundTag) null); ++ level.addFreshEntityWithPassengers(entitywitch, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN); // CraftBukkit - add SpawnReason + } + } + } + +- this.spawnCat(worldgenlevel, boundingbox); ++ this.spawnCat(level, box); + } + } + +- private void spawnCat(ServerLevelAccessor serverlevelaccessor, BoundingBox boundingbox) { ++ private void spawnCat(ServerLevelAccessor level, BoundingBox box) { + if (!this.spawnedCat) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = this.getWorldPos(2, 2, 5); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(2, 2, 5); + +- if (boundingbox.isInside(blockpos_mutableblockpos)) { ++ if (box.isInside(blockposition_mutableblockposition)) { + this.spawnedCat = true; +- Cat cat = (Cat) EntityType.CAT.create(serverlevelaccessor.getLevel()); ++ Cat entitycat = (Cat) EntityType.CAT.create(level.getLevel()); + +- if (cat != null) { +- cat.setPersistenceRequired(); +- cat.moveTo((double) blockpos_mutableblockpos.getX() + 0.5D, (double) blockpos_mutableblockpos.getY(), (double) blockpos_mutableblockpos.getZ() + 0.5D, 0.0F, 0.0F); +- cat.finalizeSpawn(serverlevelaccessor, serverlevelaccessor.getCurrentDifficultyAt(blockpos_mutableblockpos), MobSpawnType.STRUCTURE, (SpawnGroupData) null, (CompoundTag) null); +- serverlevelaccessor.addFreshEntityWithPassengers(cat); ++ if (entitycat != null) { ++ entitycat.setPersistenceRequired(); ++ entitycat.moveTo((double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + 0.5D, 0.0F, 0.0F); ++ entitycat.finalizeSpawn(level, level.getCurrentDifficultyAt(blockposition_mutableblockposition), EnumMobSpawn.STRUCTURE, (GroupDataEntity) null, (CompoundTag) null); ++ level.addFreshEntityWithPassengers(entitycat, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN); // CraftBukkit - add SpawnReason + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings.java.patch new file mode 100644 index 0000000000..3a0242d40d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings.java.patch @@ -0,0 +1,151 @@ +--- a/net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings.java ++++ b/net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings.java +@@ -22,7 +22,7 @@ + private boolean keepLiquids; + @Nullable + private RandomSource random; +- private int palette; ++ public int palette = -1; // CraftBukkit - Set initial value so we know if the palette has been set forcefully + private final List processors; + private boolean knownShape; + private boolean finalizeEntities; +@@ -36,20 +36,20 @@ + } + + public StructurePlaceSettings copy() { +- StructurePlaceSettings structureplacesettings = new StructurePlaceSettings(); ++ StructurePlaceSettings definedstructureinfo = new StructurePlaceSettings(); + +- structureplacesettings.mirror = this.mirror; +- structureplacesettings.rotation = this.rotation; +- structureplacesettings.rotationPivot = this.rotationPivot; +- structureplacesettings.ignoreEntities = this.ignoreEntities; +- structureplacesettings.boundingBox = this.boundingBox; +- structureplacesettings.keepLiquids = this.keepLiquids; +- structureplacesettings.random = this.random; +- structureplacesettings.palette = this.palette; +- structureplacesettings.processors.addAll(this.processors); +- structureplacesettings.knownShape = this.knownShape; +- structureplacesettings.finalizeEntities = this.finalizeEntities; +- return structureplacesettings; ++ definedstructureinfo.mirror = this.mirror; ++ definedstructureinfo.rotation = this.rotation; ++ definedstructureinfo.rotationPivot = this.rotationPivot; ++ definedstructureinfo.ignoreEntities = this.ignoreEntities; ++ definedstructureinfo.boundingBox = this.boundingBox; ++ definedstructureinfo.keepLiquids = this.keepLiquids; ++ definedstructureinfo.random = this.random; ++ definedstructureinfo.palette = this.palette; ++ definedstructureinfo.processors.addAll(this.processors); ++ definedstructureinfo.knownShape = this.knownShape; ++ definedstructureinfo.finalizeEntities = this.finalizeEntities; ++ return definedstructureinfo; + } + + public StructurePlaceSettings setMirror(Mirror mirror) { +@@ -62,33 +62,33 @@ + return this; + } + +- public StructurePlaceSettings setRotationPivot(BlockPos blockpos) { +- this.rotationPivot = blockpos; ++ public StructurePlaceSettings setRotationPivot(BlockPos rotationPivot) { ++ this.rotationPivot = rotationPivot; + return this; + } + +- public StructurePlaceSettings setIgnoreEntities(boolean flag) { +- this.ignoreEntities = flag; ++ public StructurePlaceSettings setIgnoreEntities(boolean ignoreEntities) { ++ this.ignoreEntities = ignoreEntities; + return this; + } + +- public StructurePlaceSettings setBoundingBox(BoundingBox boundingbox) { +- this.boundingBox = boundingbox; ++ public StructurePlaceSettings setBoundingBox(BoundingBox boundingBox) { ++ this.boundingBox = boundingBox; + return this; + } + +- public StructurePlaceSettings setRandom(@Nullable RandomSource randomsource) { +- this.random = randomsource; ++ public StructurePlaceSettings setRandom(@Nullable RandomSource random) { ++ this.random = random; + return this; + } + +- public StructurePlaceSettings setKeepLiquids(boolean flag) { +- this.keepLiquids = flag; ++ public StructurePlaceSettings setKeepLiquids(boolean keepLiquids) { ++ this.keepLiquids = keepLiquids; + return this; + } + +- public StructurePlaceSettings setKnownShape(boolean flag) { +- this.knownShape = flag; ++ public StructurePlaceSettings setKnownShape(boolean knownShape) { ++ this.knownShape = knownShape; + return this; + } + +@@ -97,13 +97,13 @@ + return this; + } + +- public StructurePlaceSettings addProcessor(StructureProcessor structureprocessor) { +- this.processors.add(structureprocessor); ++ public StructurePlaceSettings addProcessor(StructureProcessor processor) { ++ this.processors.add(processor); + return this; + } + +- public StructurePlaceSettings popProcessor(StructureProcessor structureprocessor) { +- this.processors.remove(structureprocessor); ++ public StructurePlaceSettings popProcessor(StructureProcessor processor) { ++ this.processors.remove(processor); + return this; + } + +@@ -119,8 +119,8 @@ + return this.rotationPivot; + } + +- public RandomSource getRandom(@Nullable BlockPos blockpos) { +- return this.random != null ? this.random : (blockpos == null ? RandomSource.create(Util.getMillis()) : RandomSource.create(Mth.getSeed(blockpos))); ++ public RandomSource getRandom(@Nullable BlockPos seedPos) { ++ return this.random != null ? this.random : (seedPos == null ? RandomSource.create(Util.getMillis()) : RandomSource.create(Mth.getSeed(seedPos))); + } + + public boolean isIgnoreEntities() { +@@ -144,18 +144,25 @@ + return this.keepLiquids; + } + +- public StructureTemplate.Palette getRandomPalette(List list, @Nullable BlockPos blockpos) { +- int i = list.size(); ++ public StructureTemplate.Palette getRandomPalette(List palettes, @Nullable BlockPos pos) { ++ int i = palettes.size(); + + if (i == 0) { + throw new IllegalStateException("No palettes"); ++ // CraftBukkit start ++ } else if (this.palette > 0) { ++ if (this.palette >= i) { ++ throw new IllegalArgumentException("Palette index out of bounds. Got " + this.palette + " where there are only " + i + " palettes available."); ++ } ++ return palettes.get(this.palette); ++ // CraftBukkit end + } else { +- return (StructureTemplate.Palette) list.get(this.getRandom(blockpos).nextInt(i)); ++ return (StructureTemplate.Palette) palettes.get(this.getRandom(pos).nextInt(i)); + } + } + +- public StructurePlaceSettings setFinalizeEntities(boolean flag) { +- this.finalizeEntities = flag; ++ public StructurePlaceSettings setFinalizeEntities(boolean finalizeEntities) { ++ this.finalizeEntities = finalizeEntities; + return this; + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java.patch new file mode 100644 index 0000000000..8979a6094a --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java.patch @@ -0,0 +1,1189 @@ +--- a/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java ++++ b/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java +@@ -24,14 +24,15 @@ + import net.minecraft.nbt.IntTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtUtils; ++import net.minecraft.nbt.Tag; + import net.minecraft.util.RandomSource; + import net.minecraft.world.Clearable; + import net.minecraft.world.RandomizableContainer; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.decoration.Painting; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.EmptyBlockGetter; +@@ -44,13 +45,16 @@ + import net.minecraft.world.level.block.Mirror; + import net.minecraft.world.level.block.Rotation; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.levelgen.structure.BoundingBox; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.BitSetDiscreteVoxelShape; + import net.minecraft.world.phys.shapes.DiscreteVoxelShape; ++import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer; ++import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry; ++// CraftBukkit end + + public class StructureTemplate { + +@@ -65,11 +69,16 @@ + public static final String ENTITY_TAG_BLOCKPOS = "blockPos"; + public static final String ENTITY_TAG_NBT = "nbt"; + public static final String SIZE_TAG = "size"; +- private final List palettes = Lists.newArrayList(); +- private final List entityInfoList = Lists.newArrayList(); ++ public final List palettes = Lists.newArrayList(); ++ public final List entityInfoList = Lists.newArrayList(); + private Vec3i size; + private String author; + ++ // CraftBukkit start - data containers ++ private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); ++ public CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); ++ // CraftBukkit end ++ + public StructureTemplate() { + this.size = Vec3i.ZERO; + this.author = "?"; +@@ -79,42 +88,42 @@ + return this.size; + } + +- public void setAuthor(String s) { +- this.author = s; ++ public void setAuthor(String author) { ++ this.author = author; + } + + public String getAuthor() { + return this.author; + } + +- public void fillFromWorld(Level level, BlockPos blockpos, Vec3i vec3i, boolean flag, @Nullable Block block) { +- if (vec3i.getX() >= 1 && vec3i.getY() >= 1 && vec3i.getZ() >= 1) { +- BlockPos blockpos1 = blockpos.offset(vec3i).offset(-1, -1, -1); ++ public void fillFromWorld(Level level, BlockPos pos, Vec3i size, boolean withEntities, @Nullable Block toIgnore) { ++ if (size.getX() >= 1 && size.getY() >= 1 && size.getZ() >= 1) { ++ BlockPos blockposition1 = pos.offset(size).offset(-1, -1, -1); + List list = Lists.newArrayList(); + List list1 = Lists.newArrayList(); + List list2 = Lists.newArrayList(); +- BlockPos blockpos2 = new BlockPos(Math.min(blockpos.getX(), blockpos1.getX()), Math.min(blockpos.getY(), blockpos1.getY()), Math.min(blockpos.getZ(), blockpos1.getZ())); +- BlockPos blockpos3 = new BlockPos(Math.max(blockpos.getX(), blockpos1.getX()), Math.max(blockpos.getY(), blockpos1.getY()), Math.max(blockpos.getZ(), blockpos1.getZ())); ++ BlockPos blockposition2 = new BlockPos(Math.min(pos.getX(), blockposition1.getX()), Math.min(pos.getY(), blockposition1.getY()), Math.min(pos.getZ(), blockposition1.getZ())); ++ BlockPos blockposition3 = new BlockPos(Math.max(pos.getX(), blockposition1.getX()), Math.max(pos.getY(), blockposition1.getY()), Math.max(pos.getZ(), blockposition1.getZ())); + +- this.size = vec3i; +- Iterator iterator = BlockPos.betweenClosed(blockpos2, blockpos3).iterator(); ++ this.size = size; ++ Iterator iterator = BlockPos.betweenClosed(blockposition2, blockposition3).iterator(); + + while (iterator.hasNext()) { +- BlockPos blockpos4 = (BlockPos) iterator.next(); +- BlockPos blockpos5 = blockpos4.subtract(blockpos2); +- BlockState blockstate = level.getBlockState(blockpos4); ++ BlockPos blockposition4 = (BlockPos) iterator.next(); ++ BlockPos blockposition5 = blockposition4.subtract(blockposition2); ++ IBlockData iblockdata = level.getBlockState(blockposition4); + +- if (block == null || !blockstate.is(block)) { +- BlockEntity blockentity = level.getBlockEntity(blockpos4); +- StructureTemplate.StructureBlockInfo structuretemplate_structureblockinfo; ++ if (toIgnore == null || !iblockdata.is(toIgnore)) { ++ BlockEntity tileentity = level.getBlockEntity(blockposition4); ++ StructureTemplate.StructureBlockInfo definedstructure_blockinfo; + +- if (blockentity != null) { +- structuretemplate_structureblockinfo = new StructureTemplate.StructureBlockInfo(blockpos5, blockstate, blockentity.saveWithId()); ++ if (tileentity != null) { ++ definedstructure_blockinfo = new StructureTemplate.StructureBlockInfo(blockposition5, iblockdata, tileentity.saveWithId()); + } else { +- structuretemplate_structureblockinfo = new StructureTemplate.StructureBlockInfo(blockpos5, blockstate, (CompoundTag) null); ++ definedstructure_blockinfo = new StructureTemplate.StructureBlockInfo(blockposition5, iblockdata, (CompoundTag) null); + } + +- addToLists(structuretemplate_structureblockinfo, list, list1, list2); ++ addToLists(definedstructure_blockinfo, list, list1, list2); + } + } + +@@ -122,8 +131,8 @@ + + this.palettes.clear(); + this.palettes.add(new StructureTemplate.Palette(list3)); +- if (flag) { +- this.fillEntityList(level, blockpos2, blockpos3); ++ if (withEntities) { ++ this.fillEntityList(level, blockposition2, blockposition3); + } else { + this.entityInfoList.clear(); + } +@@ -131,82 +140,82 @@ + } + } + +- private static void addToLists(StructureTemplate.StructureBlockInfo structuretemplate_structureblockinfo, List list, List list1, List list2) { +- if (structuretemplate_structureblockinfo.nbt != null) { +- list1.add(structuretemplate_structureblockinfo); +- } else if (!structuretemplate_structureblockinfo.state.getBlock().hasDynamicShape() && structuretemplate_structureblockinfo.state.isCollisionShapeFullBlock(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)) { +- list.add(structuretemplate_structureblockinfo); ++ private static void addToLists(StructureTemplate.StructureBlockInfo blockInfo, List normalBlocks, List blocksWithNbt, List blocksWithSpecialShape) { ++ if (blockInfo.nbt != null) { ++ blocksWithNbt.add(blockInfo); ++ } else if (!blockInfo.state.getBlock().hasDynamicShape() && blockInfo.state.isCollisionShapeFullBlock(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)) { ++ normalBlocks.add(blockInfo); + } else { +- list2.add(structuretemplate_structureblockinfo); ++ blocksWithSpecialShape.add(blockInfo); + } + + } + +- private static List buildInfoList(List list, List list1, List list2) { +- Comparator comparator = Comparator.comparingInt((structuretemplate_structureblockinfo) -> { +- return structuretemplate_structureblockinfo.pos.getY(); +- }).thenComparingInt((structuretemplate_structureblockinfo) -> { +- return structuretemplate_structureblockinfo.pos.getX(); +- }).thenComparingInt((structuretemplate_structureblockinfo) -> { +- return structuretemplate_structureblockinfo.pos.getZ(); ++ private static List buildInfoList(List normalBlocks, List blocksWithNbt, List blocksWithSpecialShape) { ++ Comparator comparator = Comparator.comparingInt((definedstructure_blockinfo) -> { // CraftBukkit - decompile error ++ return definedstructure_blockinfo.pos.getY(); ++ }).thenComparingInt((definedstructure_blockinfo) -> { ++ return definedstructure_blockinfo.pos.getX(); ++ }).thenComparingInt((definedstructure_blockinfo) -> { ++ return definedstructure_blockinfo.pos.getZ(); + }); + +- list.sort(comparator); +- list2.sort(comparator); +- list1.sort(comparator); ++ normalBlocks.sort(comparator); ++ blocksWithSpecialShape.sort(comparator); ++ blocksWithNbt.sort(comparator); + List list3 = Lists.newArrayList(); + +- list3.addAll(list); +- list3.addAll(list2); +- list3.addAll(list1); ++ list3.addAll(normalBlocks); ++ list3.addAll(blocksWithSpecialShape); ++ list3.addAll(blocksWithNbt); + return list3; + } + +- private void fillEntityList(Level level, BlockPos blockpos, BlockPos blockpos1) { +- List list = level.getEntitiesOfClass(Entity.class, AABB.encapsulatingFullBlocks(blockpos, blockpos1), (entity) -> { ++ private void fillEntityList(Level level, BlockPos startPos, BlockPos endPos) { ++ List list = level.getEntitiesOfClass(Entity.class, AABB.encapsulatingFullBlocks(startPos, endPos), (entity) -> { + return !(entity instanceof Player); + }); + + this.entityInfoList.clear(); + +- Vec3 vec3; +- CompoundTag compoundtag; +- BlockPos blockpos2; ++ Vec3 vec3d; ++ CompoundTag nbttagcompound; ++ BlockPos blockposition2; + +- for (Iterator iterator = list.iterator(); iterator.hasNext(); this.entityInfoList.add(new StructureTemplate.StructureEntityInfo(vec3, blockpos2, compoundtag.copy()))) { ++ for (Iterator iterator = list.iterator(); iterator.hasNext(); this.entityInfoList.add(new StructureTemplate.StructureEntityInfo(vec3d, blockposition2, nbttagcompound.copy()))) { + Entity entity = (Entity) iterator.next(); + +- vec3 = new Vec3(entity.getX() - (double) blockpos.getX(), entity.getY() - (double) blockpos.getY(), entity.getZ() - (double) blockpos.getZ()); +- compoundtag = new CompoundTag(); +- entity.save(compoundtag); ++ vec3d = new Vec3(entity.getX() - (double) startPos.getX(), entity.getY() - (double) startPos.getY(), entity.getZ() - (double) startPos.getZ()); ++ nbttagcompound = new CompoundTag(); ++ entity.save(nbttagcompound); + if (entity instanceof Painting) { +- blockpos2 = ((Painting) entity).getPos().subtract(blockpos); ++ blockposition2 = ((Painting) entity).getPos().subtract(startPos); + } else { +- blockpos2 = BlockPos.containing(vec3); ++ blockposition2 = BlockPos.containing(vec3d); + } + } + + } + +- public List filterBlocks(BlockPos blockpos, StructurePlaceSettings structureplacesettings, Block block) { +- return this.filterBlocks(blockpos, structureplacesettings, block, true); ++ public List filterBlocks(BlockPos pos, StructurePlaceSettings settings, Block block) { ++ return this.filterBlocks(pos, settings, block, true); + } + +- public ObjectArrayList filterBlocks(BlockPos blockpos, StructurePlaceSettings structureplacesettings, Block block, boolean flag) { ++ public ObjectArrayList filterBlocks(BlockPos pos, StructurePlaceSettings settings, Block block, boolean relativePosition) { + ObjectArrayList objectarraylist = new ObjectArrayList(); +- BoundingBox boundingbox = structureplacesettings.getBoundingBox(); ++ BoundingBox structureboundingbox = settings.getBoundingBox(); + + if (this.palettes.isEmpty()) { + return objectarraylist; + } else { +- Iterator iterator = structureplacesettings.getRandomPalette(this.palettes, blockpos).blocks(block).iterator(); ++ Iterator iterator = settings.getRandomPalette(this.palettes, pos).blocks(block).iterator(); + + while (iterator.hasNext()) { +- StructureTemplate.StructureBlockInfo structuretemplate_structureblockinfo = (StructureTemplate.StructureBlockInfo) iterator.next(); +- BlockPos blockpos1 = flag ? calculateRelativePosition(structureplacesettings, structuretemplate_structureblockinfo.pos).offset(blockpos) : structuretemplate_structureblockinfo.pos; ++ StructureTemplate.StructureBlockInfo definedstructure_blockinfo = (StructureTemplate.StructureBlockInfo) iterator.next(); ++ BlockPos blockposition1 = relativePosition ? calculateRelativePosition(settings, definedstructure_blockinfo.pos).offset(pos) : definedstructure_blockinfo.pos; + +- if (boundingbox == null || boundingbox.isInside(blockpos1)) { +- objectarraylist.add(new StructureTemplate.StructureBlockInfo(blockpos1, structuretemplate_structureblockinfo.state.rotate(structureplacesettings.getRotation()), structuretemplate_structureblockinfo.nbt)); ++ if (structureboundingbox == null || structureboundingbox.isInside(blockposition1)) { ++ objectarraylist.add(new StructureTemplate.StructureBlockInfo(blockposition1, definedstructure_blockinfo.state.rotate(settings.getRotation()), definedstructure_blockinfo.nbt)); + } + } + +@@ -214,27 +223,40 @@ + } + } + +- public BlockPos calculateConnectedPosition(StructurePlaceSettings structureplacesettings, BlockPos blockpos, StructurePlaceSettings structureplacesettings1, BlockPos blockpos1) { +- BlockPos blockpos2 = calculateRelativePosition(structureplacesettings, blockpos); +- BlockPos blockpos3 = calculateRelativePosition(structureplacesettings1, blockpos1); ++ public BlockPos calculateConnectedPosition(StructurePlaceSettings decorator, BlockPos start, StructurePlaceSettings settings, BlockPos end) { ++ BlockPos blockposition2 = calculateRelativePosition(decorator, start); ++ BlockPos blockposition3 = calculateRelativePosition(settings, end); + +- return blockpos2.subtract(blockpos3); ++ return blockposition2.subtract(blockposition3); + } + +- public static BlockPos calculateRelativePosition(StructurePlaceSettings structureplacesettings, BlockPos blockpos) { +- return transform(blockpos, structureplacesettings.getMirror(), structureplacesettings.getRotation(), structureplacesettings.getRotationPivot()); ++ public static BlockPos calculateRelativePosition(StructurePlaceSettings decorator, BlockPos pos) { ++ return transform(pos, decorator.getMirror(), decorator.getRotation(), decorator.getRotationPivot()); + } + +- public boolean placeInWorld(ServerLevelAccessor serverlevelaccessor, BlockPos blockpos, BlockPos blockpos1, StructurePlaceSettings structureplacesettings, RandomSource randomsource, int i) { ++ public boolean placeInWorld(ServerLevelAccessor serverLevel, BlockPos offset, BlockPos pos, StructurePlaceSettings settings, RandomSource random, int flags) { + if (this.palettes.isEmpty()) { + return false; + } else { +- List list = structureplacesettings.getRandomPalette(this.palettes, blockpos).blocks(); ++ // CraftBukkit start ++ // We only want the TransformerGeneratorAccess at certain locations because in here are many "block update" calls that shouldn't be transformed ++ ServerLevelAccessor wrappedAccess = serverLevel; ++ org.bukkit.craftbukkit.util.CraftStructureTransformer structureTransformer = null; ++ if (wrappedAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ serverLevel = transformerAccess.getHandle(); ++ structureTransformer = transformerAccess.getStructureTransformer(); ++ // The structureTransformer is not needed if we can not transform blocks therefore we can save a little bit of performance doing this ++ if (structureTransformer != null && !structureTransformer.canTransformBlocks()) { ++ structureTransformer = null; ++ } ++ } ++ // CraftBukkit end ++ List list = settings.getRandomPalette(this.palettes, offset).blocks(); + +- if ((!list.isEmpty() || !structureplacesettings.isIgnoreEntities() && !this.entityInfoList.isEmpty()) && this.size.getX() >= 1 && this.size.getY() >= 1 && this.size.getZ() >= 1) { +- BoundingBox boundingbox = structureplacesettings.getBoundingBox(); +- List list1 = Lists.newArrayListWithCapacity(structureplacesettings.shouldKeepLiquids() ? list.size() : 0); +- List list2 = Lists.newArrayListWithCapacity(structureplacesettings.shouldKeepLiquids() ? list.size() : 0); ++ if ((!list.isEmpty() || !settings.isIgnoreEntities() && !this.entityInfoList.isEmpty()) && this.size.getX() >= 1 && this.size.getY() >= 1 && this.size.getZ() >= 1) { ++ BoundingBox structureboundingbox = settings.getBoundingBox(); ++ List list1 = Lists.newArrayListWithCapacity(settings.shouldKeepLiquids() ? list.size() : 0); ++ List list2 = Lists.newArrayListWithCapacity(settings.shouldKeepLiquids() ? list.size() : 0); + List> list3 = Lists.newArrayListWithCapacity(list.size()); + int j = Integer.MAX_VALUE; + int k = Integer.MAX_VALUE; +@@ -242,51 +264,65 @@ + int i1 = Integer.MIN_VALUE; + int j1 = Integer.MIN_VALUE; + int k1 = Integer.MIN_VALUE; +- List list4 = processBlockInfos(serverlevelaccessor, blockpos, blockpos1, structureplacesettings, list); ++ List list4 = processBlockInfos(serverLevel, offset, pos, settings, list); + Iterator iterator = list4.iterator(); + +- BlockEntity blockentity; ++ BlockEntity tileentity; + + while (iterator.hasNext()) { +- StructureTemplate.StructureBlockInfo structuretemplate_structureblockinfo = (StructureTemplate.StructureBlockInfo) iterator.next(); +- BlockPos blockpos2 = structuretemplate_structureblockinfo.pos; ++ StructureTemplate.StructureBlockInfo definedstructure_blockinfo = (StructureTemplate.StructureBlockInfo) iterator.next(); ++ BlockPos blockposition2 = definedstructure_blockinfo.pos; + +- if (boundingbox == null || boundingbox.isInside(blockpos2)) { +- FluidState fluidstate = structureplacesettings.shouldKeepLiquids() ? serverlevelaccessor.getFluidState(blockpos2) : null; +- BlockState blockstate = structuretemplate_structureblockinfo.state.mirror(structureplacesettings.getMirror()).rotate(structureplacesettings.getRotation()); ++ if (structureboundingbox == null || structureboundingbox.isInside(blockposition2)) { ++ FluidState fluid = settings.shouldKeepLiquids() ? serverLevel.getFluidState(blockposition2) : null; ++ IBlockData iblockdata = definedstructure_blockinfo.state.mirror(settings.getMirror()).rotate(settings.getRotation()); + +- if (structuretemplate_structureblockinfo.nbt != null) { +- blockentity = serverlevelaccessor.getBlockEntity(blockpos2); +- Clearable.tryClear(blockentity); +- serverlevelaccessor.setBlock(blockpos2, Blocks.BARRIER.defaultBlockState(), 20); ++ if (definedstructure_blockinfo.nbt != null) { ++ tileentity = serverLevel.getBlockEntity(blockposition2); ++ Clearable.tryClear(tileentity); ++ serverLevel.setBlock(blockposition2, Blocks.BARRIER.defaultBlockState(), 20); + } ++ // CraftBukkit start ++ if (structureTransformer != null) { ++ org.bukkit.craftbukkit.block.CraftBlockState craftBlockState = (org.bukkit.craftbukkit.block.CraftBlockState) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockposition2, iblockdata, null); ++ if (definedstructure_blockinfo.nbt != null && craftBlockState instanceof org.bukkit.craftbukkit.block.CraftBlockEntityState entityState) { ++ entityState.loadData(definedstructure_blockinfo.nbt); ++ if (craftBlockState instanceof org.bukkit.craftbukkit.block.CraftLootable craftLootable) { ++ craftLootable.setSeed(random.nextLong()); ++ } ++ } ++ craftBlockState = structureTransformer.transformCraftState(craftBlockState); ++ iblockdata = craftBlockState.getHandle(); ++ definedstructure_blockinfo = new StructureTemplate.StructureBlockInfo(blockposition2, iblockdata, (craftBlockState instanceof org.bukkit.craftbukkit.block.CraftBlockEntityState craftBlockEntityState ? craftBlockEntityState.getSnapshotNBT() : null)); ++ } ++ // CraftBukkit end + +- if (serverlevelaccessor.setBlock(blockpos2, blockstate, i)) { +- j = Math.min(j, blockpos2.getX()); +- k = Math.min(k, blockpos2.getY()); +- l = Math.min(l, blockpos2.getZ()); +- i1 = Math.max(i1, blockpos2.getX()); +- j1 = Math.max(j1, blockpos2.getY()); +- k1 = Math.max(k1, blockpos2.getZ()); +- list3.add(Pair.of(blockpos2, structuretemplate_structureblockinfo.nbt)); +- if (structuretemplate_structureblockinfo.nbt != null) { +- blockentity = serverlevelaccessor.getBlockEntity(blockpos2); +- if (blockentity != null) { +- if (blockentity instanceof RandomizableContainer) { +- structuretemplate_structureblockinfo.nbt.putLong("LootTableSeed", randomsource.nextLong()); ++ if (serverLevel.setBlock(blockposition2, iblockdata, flags)) { ++ j = Math.min(j, blockposition2.getX()); ++ k = Math.min(k, blockposition2.getY()); ++ l = Math.min(l, blockposition2.getZ()); ++ i1 = Math.max(i1, blockposition2.getX()); ++ j1 = Math.max(j1, blockposition2.getY()); ++ k1 = Math.max(k1, blockposition2.getZ()); ++ list3.add(Pair.of(blockposition2, definedstructure_blockinfo.nbt)); ++ if (definedstructure_blockinfo.nbt != null) { ++ tileentity = serverLevel.getBlockEntity(blockposition2); ++ if (tileentity != null) { ++ if (structureTransformer == null && tileentity instanceof RandomizableContainer) { // CraftBukkit - only process if don't have a transformer access (Was already set above) - SPIGOT-7520: Use structureTransformer as check, so that it is the same as above ++ definedstructure_blockinfo.nbt.putLong("LootTableSeed", random.nextLong()); + } + +- blockentity.load(structuretemplate_structureblockinfo.nbt); ++ tileentity.load(definedstructure_blockinfo.nbt); + } + } + +- if (fluidstate != null) { +- if (blockstate.getFluidState().isSource()) { +- list2.add(blockpos2); +- } else if (blockstate.getBlock() instanceof LiquidBlockContainer) { +- ((LiquidBlockContainer) blockstate.getBlock()).placeLiquid(serverlevelaccessor, blockpos2, blockstate, fluidstate); +- if (!fluidstate.isSource()) { +- list1.add(blockpos2); ++ if (fluid != null) { ++ if (iblockdata.getFluidState().isSource()) { ++ list2.add(blockposition2); ++ } else if (iblockdata.getBlock() instanceof LiquidBlockContainer) { ++ ((LiquidBlockContainer) iblockdata.getBlock()).placeLiquid(serverLevel, blockposition2, iblockdata, fluid); ++ if (!fluid.isSource()) { ++ list1.add(blockposition2); + } + } + } +@@ -295,35 +331,35 @@ + } + + boolean flag = true; +- Direction[] adirection = new Direction[]{Direction.UP, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST}; ++ Direction[] aenumdirection = new Direction[]{Direction.UP, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST}; + + Iterator iterator1; + int l1; +- BlockState blockstate1; ++ IBlockData iblockdata1; + + while (flag && !list1.isEmpty()) { + flag = false; + iterator1 = list1.iterator(); + + while (iterator1.hasNext()) { +- BlockPos blockpos3 = (BlockPos) iterator1.next(); +- FluidState fluidstate1 = serverlevelaccessor.getFluidState(blockpos3); ++ BlockPos blockposition3 = (BlockPos) iterator1.next(); ++ FluidState fluid1 = serverLevel.getFluidState(blockposition3); + +- for (l1 = 0; l1 < adirection.length && !fluidstate1.isSource(); ++l1) { +- BlockPos blockpos4 = blockpos3.relative(adirection[l1]); +- FluidState fluidstate2 = serverlevelaccessor.getFluidState(blockpos4); ++ for (l1 = 0; l1 < aenumdirection.length && !fluid1.isSource(); ++l1) { ++ BlockPos blockposition4 = blockposition3.relative(aenumdirection[l1]); ++ FluidState fluid2 = serverLevel.getFluidState(blockposition4); + +- if (fluidstate2.isSource() && !list2.contains(blockpos4)) { +- fluidstate1 = fluidstate2; ++ if (fluid2.isSource() && !list2.contains(blockposition4)) { ++ fluid1 = fluid2; + } + } + +- if (fluidstate1.isSource()) { +- blockstate1 = serverlevelaccessor.getBlockState(blockpos3); +- Block block = blockstate1.getBlock(); ++ if (fluid1.isSource()) { ++ iblockdata1 = serverLevel.getBlockState(blockposition3); ++ Block block = iblockdata1.getBlock(); + + if (block instanceof LiquidBlockContainer) { +- ((LiquidBlockContainer) block).placeLiquid(serverlevelaccessor, blockpos3, blockstate1, fluidstate1); ++ ((LiquidBlockContainer) block).placeLiquid(serverLevel, blockposition3, iblockdata1, fluid1); + flag = true; + iterator1.remove(); + } +@@ -332,8 +368,8 @@ + } + + if (j <= i1) { +- if (!structureplacesettings.getKnownShape()) { +- BitSetDiscreteVoxelShape bitsetdiscretevoxelshape = new BitSetDiscreteVoxelShape(i1 - j + 1, j1 - k + 1, k1 - l + 1); ++ if (!settings.getKnownShape()) { ++ BitSetDiscreteVoxelShape voxelshapebitset = new BitSetDiscreteVoxelShape(i1 - j + 1, j1 - k + 1, k1 - l + 1); + int i2 = j; + int j2 = k; + +@@ -342,42 +378,42 @@ + + while (iterator2.hasNext()) { + Pair pair = (Pair) iterator2.next(); +- BlockPos blockpos5 = (BlockPos) pair.getFirst(); ++ BlockPos blockposition5 = (BlockPos) pair.getFirst(); + +- bitsetdiscretevoxelshape.fill(blockpos5.getX() - i2, blockpos5.getY() - j2, blockpos5.getZ() - l1); ++ voxelshapebitset.fill(blockposition5.getX() - i2, blockposition5.getY() - j2, blockposition5.getZ() - l1); + } + +- updateShapeAtEdge(serverlevelaccessor, i, bitsetdiscretevoxelshape, i2, j2, l1); ++ updateShapeAtEdge(serverLevel, flags, voxelshapebitset, i2, j2, l1); + } + + iterator1 = list3.iterator(); + + while (iterator1.hasNext()) { + Pair pair1 = (Pair) iterator1.next(); +- BlockPos blockpos6 = (BlockPos) pair1.getFirst(); ++ BlockPos blockposition6 = (BlockPos) pair1.getFirst(); + +- if (!structureplacesettings.getKnownShape()) { +- blockstate1 = serverlevelaccessor.getBlockState(blockpos6); +- BlockState blockstate2 = Block.updateFromNeighbourShapes(blockstate1, serverlevelaccessor, blockpos6); ++ if (!settings.getKnownShape()) { ++ iblockdata1 = serverLevel.getBlockState(blockposition6); ++ IBlockData iblockdata2 = Block.updateFromNeighbourShapes(iblockdata1, serverLevel, blockposition6); + +- if (blockstate1 != blockstate2) { +- serverlevelaccessor.setBlock(blockpos6, blockstate2, i & -2 | 16); ++ if (iblockdata1 != iblockdata2) { ++ serverLevel.setBlock(blockposition6, iblockdata2, flags & -2 | 16); + } + +- serverlevelaccessor.blockUpdated(blockpos6, blockstate2.getBlock()); ++ serverLevel.blockUpdated(blockposition6, iblockdata2.getBlock()); + } + + if (pair1.getSecond() != null) { +- blockentity = serverlevelaccessor.getBlockEntity(blockpos6); +- if (blockentity != null) { +- blockentity.setChanged(); ++ tileentity = serverLevel.getBlockEntity(blockposition6); ++ if (tileentity != null) { ++ tileentity.setChanged(); + } + } + } + } + +- if (!structureplacesettings.isIgnoreEntities()) { +- this.placeEntities(serverlevelaccessor, blockpos, structureplacesettings.getMirror(), structureplacesettings.getRotation(), structureplacesettings.getRotationPivot(), boundingbox, structureplacesettings.shouldFinalizeEntities()); ++ if (!settings.isIgnoreEntities()) { ++ this.placeEntities(wrappedAccess, offset, settings.getMirror(), settings.getRotation(), settings.getRotationPivot(), structureboundingbox, settings.shouldFinalizeEntities()); // CraftBukkit + } + + return true; +@@ -387,96 +423,98 @@ + } + } + +- public static void updateShapeAtEdge(LevelAccessor levelaccessor, int i, DiscreteVoxelShape discretevoxelshape, int j, int k, int l) { +- discretevoxelshape.forAllFaces((direction, i1, j1, k1) -> { +- BlockPos blockpos = new BlockPos(j + i1, k + j1, l + k1); +- BlockPos blockpos1 = blockpos.relative(direction); +- BlockState blockstate = levelaccessor.getBlockState(blockpos); +- BlockState blockstate1 = levelaccessor.getBlockState(blockpos1); +- BlockState blockstate2 = blockstate.updateShape(direction, blockstate1, levelaccessor, blockpos, blockpos1); ++ public static void updateShapeAtEdge(LevelAccessor level, int flags, DiscreteVoxelShape shape, int x, int y, int z) { ++ shape.forAllFaces((enumdirection, i1, j1, k1) -> { ++ BlockPos blockposition = new BlockPos(x + i1, y + j1, z + k1); ++ BlockPos blockposition1 = blockposition.relative(enumdirection); ++ IBlockData iblockdata = level.getBlockState(blockposition); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ IBlockData iblockdata2 = iblockdata.updateShape(enumdirection, iblockdata1, level, blockposition, blockposition1); + +- if (blockstate != blockstate2) { +- levelaccessor.setBlock(blockpos, blockstate2, i & -2); ++ if (iblockdata != iblockdata2) { ++ level.setBlock(blockposition, iblockdata2, flags & -2); + } + +- BlockState blockstate3 = blockstate1.updateShape(direction.getOpposite(), blockstate2, levelaccessor, blockpos1, blockpos); ++ IBlockData iblockdata3 = iblockdata1.updateShape(enumdirection.getOpposite(), iblockdata2, level, blockposition1, blockposition); + +- if (blockstate1 != blockstate3) { +- levelaccessor.setBlock(blockpos1, blockstate3, i & -2); ++ if (iblockdata1 != iblockdata3) { ++ level.setBlock(blockposition1, iblockdata3, flags & -2); + } + + }); + } + +- public static List processBlockInfos(ServerLevelAccessor serverlevelaccessor, BlockPos blockpos, BlockPos blockpos1, StructurePlaceSettings structureplacesettings, List list) { ++ public static List processBlockInfos(ServerLevelAccessor serverLevel, BlockPos offset, BlockPos pos, StructurePlaceSettings settings, List blockInfos) { + List list1 = new ArrayList(); + List list2 = new ArrayList(); +- Iterator iterator = list.iterator(); ++ Iterator iterator = blockInfos.iterator(); + + while (iterator.hasNext()) { +- StructureTemplate.StructureBlockInfo structuretemplate_structureblockinfo = (StructureTemplate.StructureBlockInfo) iterator.next(); +- BlockPos blockpos2 = calculateRelativePosition(structureplacesettings, structuretemplate_structureblockinfo.pos).offset(blockpos); +- StructureTemplate.StructureBlockInfo structuretemplate_structureblockinfo1 = new StructureTemplate.StructureBlockInfo(blockpos2, structuretemplate_structureblockinfo.state, structuretemplate_structureblockinfo.nbt != null ? structuretemplate_structureblockinfo.nbt.copy() : null); ++ StructureTemplate.StructureBlockInfo definedstructure_blockinfo = (StructureTemplate.StructureBlockInfo) iterator.next(); ++ BlockPos blockposition2 = calculateRelativePosition(settings, definedstructure_blockinfo.pos).offset(offset); ++ StructureTemplate.StructureBlockInfo definedstructure_blockinfo1 = new StructureTemplate.StructureBlockInfo(blockposition2, definedstructure_blockinfo.state, definedstructure_blockinfo.nbt != null ? definedstructure_blockinfo.nbt.copy() : null); + +- for (Iterator iterator1 = structureplacesettings.getProcessors().iterator(); structuretemplate_structureblockinfo1 != null && iterator1.hasNext(); structuretemplate_structureblockinfo1 = ((StructureProcessor) iterator1.next()).processBlock(serverlevelaccessor, blockpos, blockpos1, structuretemplate_structureblockinfo, structuretemplate_structureblockinfo1, structureplacesettings)) { ++ for (Iterator iterator1 = settings.getProcessors().iterator(); definedstructure_blockinfo1 != null && iterator1.hasNext(); definedstructure_blockinfo1 = ((StructureProcessor) iterator1.next()).processBlock(serverLevel, offset, pos, definedstructure_blockinfo, definedstructure_blockinfo1, settings)) { + ; + } + +- if (structuretemplate_structureblockinfo1 != null) { +- ((List) list2).add(structuretemplate_structureblockinfo1); +- list1.add(structuretemplate_structureblockinfo); ++ if (definedstructure_blockinfo1 != null) { ++ ((List) list2).add(definedstructure_blockinfo1); ++ list1.add(definedstructure_blockinfo); + } + } + +- StructureProcessor structureprocessor; ++ StructureProcessor definedstructureprocessor; + +- for (iterator = structureplacesettings.getProcessors().iterator(); iterator.hasNext(); list2 = structureprocessor.finalizeProcessing(serverlevelaccessor, blockpos, blockpos1, list1, (List) list2, structureplacesettings)) { +- structureprocessor = (StructureProcessor) iterator.next(); ++ for (iterator = settings.getProcessors().iterator(); iterator.hasNext(); list2 = definedstructureprocessor.finalizeProcessing(serverLevel, offset, pos, list1, (List) list2, settings)) { ++ definedstructureprocessor = (StructureProcessor) iterator.next(); + } + + return (List) list2; + } + +- private void placeEntities(ServerLevelAccessor serverlevelaccessor, BlockPos blockpos, Mirror mirror, Rotation rotation, BlockPos blockpos1, @Nullable BoundingBox boundingbox, boolean flag) { ++ private void placeEntities(ServerLevelAccessor serverLevel, BlockPos pos, Mirror mirror, Rotation rotation, BlockPos offset, @Nullable BoundingBox boundingBox, boolean withEntities) { + Iterator iterator = this.entityInfoList.iterator(); + + while (iterator.hasNext()) { +- StructureTemplate.StructureEntityInfo structuretemplate_structureentityinfo = (StructureTemplate.StructureEntityInfo) iterator.next(); +- BlockPos blockpos2 = transform(structuretemplate_structureentityinfo.blockPos, mirror, rotation, blockpos1).offset(blockpos); ++ StructureTemplate.StructureEntityInfo definedstructure_entityinfo = (StructureTemplate.StructureEntityInfo) iterator.next(); ++ BlockPos blockposition2 = transform(definedstructure_entityinfo.blockPos, mirror, rotation, offset).offset(pos); + +- if (boundingbox == null || boundingbox.isInside(blockpos2)) { +- CompoundTag compoundtag = structuretemplate_structureentityinfo.nbt.copy(); +- Vec3 vec3 = transform(structuretemplate_structureentityinfo.pos, mirror, rotation, blockpos1); +- Vec3 vec31 = vec3.add((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ()); +- ListTag listtag = new ListTag(); ++ if (boundingBox == null || boundingBox.isInside(blockposition2)) { ++ CompoundTag nbttagcompound = definedstructure_entityinfo.nbt.copy(); ++ Vec3 vec3d = transform(definedstructure_entityinfo.pos, mirror, rotation, offset); ++ Vec3 vec3d1 = vec3d.add((double) pos.getX(), (double) pos.getY(), (double) pos.getZ()); ++ ListTag nbttaglist = new ListTag(); + +- listtag.add(DoubleTag.valueOf(vec31.x)); +- listtag.add(DoubleTag.valueOf(vec31.y)); +- listtag.add(DoubleTag.valueOf(vec31.z)); +- compoundtag.put("Pos", listtag); +- compoundtag.remove("UUID"); +- createEntityIgnoreException(serverlevelaccessor, compoundtag).ifPresent((entity) -> { ++ nbttaglist.add(DoubleTag.valueOf(vec3d1.x)); ++ nbttaglist.add(DoubleTag.valueOf(vec3d1.y)); ++ nbttaglist.add(DoubleTag.valueOf(vec3d1.z)); ++ nbttagcompound.put("Pos", nbttaglist); ++ nbttagcompound.remove("UUID"); ++ createEntityIgnoreException(serverLevel, nbttagcompound).ifPresent((entity) -> { + float f = entity.rotate(rotation); + + f += entity.mirror(mirror) - entity.getYRot(); +- entity.moveTo(vec31.x, vec31.y, vec31.z, f, entity.getXRot()); +- if (flag && entity instanceof Mob) { +- ((Mob) entity).finalizeSpawn(serverlevelaccessor, serverlevelaccessor.getCurrentDifficultyAt(BlockPos.containing(vec31)), MobSpawnType.STRUCTURE, (SpawnGroupData) null, compoundtag); ++ entity.moveTo(vec3d1.x, vec3d1.y, vec3d1.z, f, entity.getXRot()); ++ if (withEntities && entity instanceof Mob) { ++ ((Mob) entity).finalizeSpawn(serverLevel, serverLevel.getCurrentDifficultyAt(BlockPos.containing(vec3d1)), EnumMobSpawn.STRUCTURE, (GroupDataEntity) null, nbttagcompound); + } + +- serverlevelaccessor.addFreshEntityWithPassengers(entity); ++ serverLevel.addFreshEntityWithPassengers(entity); + }); + } + } + + } + +- private static Optional createEntityIgnoreException(ServerLevelAccessor serverlevelaccessor, CompoundTag compoundtag) { +- try { +- return EntityType.create(compoundtag, serverlevelaccessor.getLevel()); +- } catch (Exception exception) { +- return Optional.empty(); +- } ++ private static Optional createEntityIgnoreException(ServerLevelAccessor level, CompoundTag tag) { ++ // CraftBukkit start ++ // try { ++ return EntityType.create(tag, level.getLevel()); ++ // } catch (Exception exception) { ++ // return Optional.empty(); ++ // } ++ // CraftBukkit end + } + + public Vec3i getSize(Rotation rotation) { +@@ -489,10 +527,10 @@ + } + } + +- public static BlockPos transform(BlockPos blockpos, Mirror mirror, Rotation rotation, BlockPos blockpos1) { +- int i = blockpos.getX(); +- int j = blockpos.getY(); +- int k = blockpos.getZ(); ++ public static BlockPos transform(BlockPos targetPos, Mirror mirror, Rotation rotation, BlockPos offset) { ++ int i = targetPos.getX(); ++ int j = targetPos.getY(); ++ int k = targetPos.getZ(); + boolean flag = true; + + switch (mirror) { +@@ -506,8 +544,8 @@ + flag = false; + } + +- int l = blockpos1.getX(); +- int i1 = blockpos1.getZ(); ++ int l = offset.getX(); ++ int i1 = offset.getZ(); + + switch (rotation) { + case COUNTERCLOCKWISE_90: +@@ -517,14 +555,14 @@ + case CLOCKWISE_180: + return new BlockPos(l + l - i, j, i1 + i1 - k); + default: +- return flag ? new BlockPos(i, j, k) : blockpos; ++ return flag ? new BlockPos(i, j, k) : targetPos; + } + } + +- public static Vec3 transform(Vec3 vec3, Mirror mirror, Rotation rotation, BlockPos blockpos) { +- double d0 = vec3.x; +- double d1 = vec3.y; +- double d2 = vec3.z; ++ public static Vec3 transform(Vec3 target, Mirror mirror, Rotation rotation, BlockPos centerOffset) { ++ double d0 = target.x; ++ double d1 = target.y; ++ double d2 = target.z; + boolean flag = true; + + switch (mirror) { +@@ -538,8 +576,8 @@ + flag = false; + } + +- int i = blockpos.getX(); +- int j = blockpos.getZ(); ++ int i = centerOffset.getX(); ++ int j = centerOffset.getZ(); + + switch (rotation) { + case COUNTERCLOCKWISE_90: +@@ -549,215 +587,226 @@ + case CLOCKWISE_180: + return new Vec3((double) (i + i + 1) - d0, d1, (double) (j + j + 1) - d2); + default: +- return flag ? new Vec3(d0, d1, d2) : vec3; ++ return flag ? new Vec3(d0, d1, d2) : target; + } + } + +- public BlockPos getZeroPositionWithTransform(BlockPos blockpos, Mirror mirror, Rotation rotation) { +- return getZeroPositionWithTransform(blockpos, mirror, rotation, this.getSize().getX(), this.getSize().getZ()); ++ public BlockPos getZeroPositionWithTransform(BlockPos targetPos, Mirror mirror, Rotation rotation) { ++ return getZeroPositionWithTransform(targetPos, mirror, rotation, this.getSize().getX(), this.getSize().getZ()); + } + +- public static BlockPos getZeroPositionWithTransform(BlockPos blockpos, Mirror mirror, Rotation rotation, int i, int j) { +- --i; +- --j; +- int k = mirror == Mirror.FRONT_BACK ? i : 0; +- int l = mirror == Mirror.LEFT_RIGHT ? j : 0; +- BlockPos blockpos1 = blockpos; ++ public static BlockPos getZeroPositionWithTransform(BlockPos pos, Mirror mirror, Rotation rotation, int sizeX, int sizeZ) { ++ --sizeX; ++ --sizeZ; ++ int k = mirror == Mirror.FRONT_BACK ? sizeX : 0; ++ int l = mirror == Mirror.LEFT_RIGHT ? sizeZ : 0; ++ BlockPos blockposition1 = pos; + + switch (rotation) { + case COUNTERCLOCKWISE_90: +- blockpos1 = blockpos.offset(l, 0, i - k); ++ blockposition1 = pos.offset(l, 0, sizeX - k); + break; + case CLOCKWISE_90: +- blockpos1 = blockpos.offset(j - l, 0, k); ++ blockposition1 = pos.offset(sizeZ - l, 0, k); + break; + case CLOCKWISE_180: +- blockpos1 = blockpos.offset(i - k, 0, j - l); ++ blockposition1 = pos.offset(sizeX - k, 0, sizeZ - l); + break; + case NONE: +- blockpos1 = blockpos.offset(k, 0, l); ++ blockposition1 = pos.offset(k, 0, l); + } + +- return blockpos1; ++ return blockposition1; + } + +- public BoundingBox getBoundingBox(StructurePlaceSettings structureplacesettings, BlockPos blockpos) { +- return this.getBoundingBox(blockpos, structureplacesettings.getRotation(), structureplacesettings.getRotationPivot(), structureplacesettings.getMirror()); ++ public BoundingBox getBoundingBox(StructurePlaceSettings settings, BlockPos startPos) { ++ return this.getBoundingBox(startPos, settings.getRotation(), settings.getRotationPivot(), settings.getMirror()); + } + +- public BoundingBox getBoundingBox(BlockPos blockpos, Rotation rotation, BlockPos blockpos1, Mirror mirror) { +- return getBoundingBox(blockpos, rotation, blockpos1, mirror, this.size); ++ public BoundingBox getBoundingBox(BlockPos startPos, Rotation rotation, BlockPos pivotPos, Mirror mirror) { ++ return getBoundingBox(startPos, rotation, pivotPos, mirror, this.size); + } + + @VisibleForTesting +- protected static BoundingBox getBoundingBox(BlockPos blockpos, Rotation rotation, BlockPos blockpos1, Mirror mirror, Vec3i vec3i) { +- Vec3i vec3i1 = vec3i.offset(-1, -1, -1); +- BlockPos blockpos2 = transform(BlockPos.ZERO, mirror, rotation, blockpos1); +- BlockPos blockpos3 = transform(BlockPos.ZERO.offset(vec3i1), mirror, rotation, blockpos1); ++ protected static BoundingBox getBoundingBox(BlockPos startPos, Rotation rotation, BlockPos pivotPos, Mirror mirror, Vec3i size) { ++ Vec3i baseblockposition1 = size.offset(-1, -1, -1); ++ BlockPos blockposition2 = transform(BlockPos.ZERO, mirror, rotation, pivotPos); ++ BlockPos blockposition3 = transform(BlockPos.ZERO.offset(baseblockposition1), mirror, rotation, pivotPos); + +- return BoundingBox.fromCorners(blockpos2, blockpos3).move(blockpos); ++ return BoundingBox.fromCorners(blockposition2, blockposition3).move(startPos); + } + +- public CompoundTag save(CompoundTag compoundtag) { ++ public CompoundTag save(CompoundTag tag) { + if (this.palettes.isEmpty()) { +- compoundtag.put("blocks", new ListTag()); +- compoundtag.put("palette", new ListTag()); ++ tag.put("blocks", new ListTag()); ++ tag.put("palette", new ListTag()); + } else { + List list = Lists.newArrayList(); +- StructureTemplate.SimplePalette structuretemplate_simplepalette = new StructureTemplate.SimplePalette(); ++ StructureTemplate.SimplePalette definedstructure_b = new StructureTemplate.SimplePalette(); + +- list.add(structuretemplate_simplepalette); ++ list.add(definedstructure_b); + + for (int i = 1; i < this.palettes.size(); ++i) { + list.add(new StructureTemplate.SimplePalette()); + } + +- ListTag listtag = new ListTag(); ++ ListTag nbttaglist = new ListTag(); + List list1 = ((StructureTemplate.Palette) this.palettes.get(0)).blocks(); + + for (int j = 0; j < list1.size(); ++j) { +- StructureTemplate.StructureBlockInfo structuretemplate_structureblockinfo = (StructureTemplate.StructureBlockInfo) list1.get(j); +- CompoundTag compoundtag1 = new CompoundTag(); ++ StructureTemplate.StructureBlockInfo definedstructure_blockinfo = (StructureTemplate.StructureBlockInfo) list1.get(j); ++ CompoundTag nbttagcompound1 = new CompoundTag(); + +- compoundtag1.put("pos", this.newIntegerList(structuretemplate_structureblockinfo.pos.getX(), structuretemplate_structureblockinfo.pos.getY(), structuretemplate_structureblockinfo.pos.getZ())); +- int k = structuretemplate_simplepalette.idFor(structuretemplate_structureblockinfo.state); ++ nbttagcompound1.put("pos", this.newIntegerList(definedstructure_blockinfo.pos.getX(), definedstructure_blockinfo.pos.getY(), definedstructure_blockinfo.pos.getZ())); ++ int k = definedstructure_b.idFor(definedstructure_blockinfo.state); + +- compoundtag1.putInt("state", k); +- if (structuretemplate_structureblockinfo.nbt != null) { +- compoundtag1.put("nbt", structuretemplate_structureblockinfo.nbt); ++ nbttagcompound1.putInt("state", k); ++ if (definedstructure_blockinfo.nbt != null) { ++ nbttagcompound1.put("nbt", definedstructure_blockinfo.nbt); + } + +- listtag.add(compoundtag1); ++ nbttaglist.add(nbttagcompound1); + + for (int l = 1; l < this.palettes.size(); ++l) { +- StructureTemplate.SimplePalette structuretemplate_simplepalette1 = (StructureTemplate.SimplePalette) list.get(l); ++ StructureTemplate.SimplePalette definedstructure_b1 = (StructureTemplate.SimplePalette) list.get(l); + +- structuretemplate_simplepalette1.addMapping(((StructureTemplate.StructureBlockInfo) ((StructureTemplate.Palette) this.palettes.get(l)).blocks().get(j)).state, k); ++ definedstructure_b1.addMapping(((StructureTemplate.StructureBlockInfo) ((StructureTemplate.Palette) this.palettes.get(l)).blocks().get(j)).state, k); + } + } + +- compoundtag.put("blocks", listtag); +- ListTag listtag1; ++ tag.put("blocks", nbttaglist); ++ ListTag nbttaglist1; + Iterator iterator; + + if (list.size() == 1) { +- listtag1 = new ListTag(); +- iterator = structuretemplate_simplepalette.iterator(); ++ nbttaglist1 = new ListTag(); ++ iterator = definedstructure_b.iterator(); + + while (iterator.hasNext()) { +- BlockState blockstate = (BlockState) iterator.next(); ++ IBlockData iblockdata = (IBlockData) iterator.next(); + +- listtag1.add(NbtUtils.writeBlockState(blockstate)); ++ nbttaglist1.add(NbtUtils.writeBlockState(iblockdata)); + } + +- compoundtag.put("palette", listtag1); ++ tag.put("palette", nbttaglist1); + } else { +- listtag1 = new ListTag(); ++ nbttaglist1 = new ListTag(); + iterator = list.iterator(); + + while (iterator.hasNext()) { +- StructureTemplate.SimplePalette structuretemplate_simplepalette2 = (StructureTemplate.SimplePalette) iterator.next(); +- ListTag listtag2 = new ListTag(); +- Iterator iterator1 = structuretemplate_simplepalette2.iterator(); ++ StructureTemplate.SimplePalette definedstructure_b2 = (StructureTemplate.SimplePalette) iterator.next(); ++ ListTag nbttaglist2 = new ListTag(); ++ Iterator iterator1 = definedstructure_b2.iterator(); + + while (iterator1.hasNext()) { +- BlockState blockstate1 = (BlockState) iterator1.next(); ++ IBlockData iblockdata1 = (IBlockData) iterator1.next(); + +- listtag2.add(NbtUtils.writeBlockState(blockstate1)); ++ nbttaglist2.add(NbtUtils.writeBlockState(iblockdata1)); + } + +- listtag1.add(listtag2); ++ nbttaglist1.add(nbttaglist2); + } + +- compoundtag.put("palettes", listtag1); ++ tag.put("palettes", nbttaglist1); + } + } + +- ListTag listtag3 = new ListTag(); ++ ListTag nbttaglist3 = new ListTag(); + +- CompoundTag compoundtag2; ++ CompoundTag nbttagcompound2; + +- for (Iterator iterator2 = this.entityInfoList.iterator(); iterator2.hasNext(); listtag3.add(compoundtag2)) { +- StructureTemplate.StructureEntityInfo structuretemplate_structureentityinfo = (StructureTemplate.StructureEntityInfo) iterator2.next(); ++ for (Iterator iterator2 = this.entityInfoList.iterator(); iterator2.hasNext(); nbttaglist3.add(nbttagcompound2)) { ++ StructureTemplate.StructureEntityInfo definedstructure_entityinfo = (StructureTemplate.StructureEntityInfo) iterator2.next(); + +- compoundtag2 = new CompoundTag(); +- compoundtag2.put("pos", this.newDoubleList(structuretemplate_structureentityinfo.pos.x, structuretemplate_structureentityinfo.pos.y, structuretemplate_structureentityinfo.pos.z)); +- compoundtag2.put("blockPos", this.newIntegerList(structuretemplate_structureentityinfo.blockPos.getX(), structuretemplate_structureentityinfo.blockPos.getY(), structuretemplate_structureentityinfo.blockPos.getZ())); +- if (structuretemplate_structureentityinfo.nbt != null) { +- compoundtag2.put("nbt", structuretemplate_structureentityinfo.nbt); ++ nbttagcompound2 = new CompoundTag(); ++ nbttagcompound2.put("pos", this.newDoubleList(definedstructure_entityinfo.pos.x, definedstructure_entityinfo.pos.y, definedstructure_entityinfo.pos.z)); ++ nbttagcompound2.put("blockPos", this.newIntegerList(definedstructure_entityinfo.blockPos.getX(), definedstructure_entityinfo.blockPos.getY(), definedstructure_entityinfo.blockPos.getZ())); ++ if (definedstructure_entityinfo.nbt != null) { ++ nbttagcompound2.put("nbt", definedstructure_entityinfo.nbt); + } + } + +- compoundtag.put("entities", listtag3); +- compoundtag.put("size", this.newIntegerList(this.size.getX(), this.size.getY(), this.size.getZ())); +- return NbtUtils.addCurrentDataVersion(compoundtag); ++ tag.put("entities", nbttaglist3); ++ tag.put("size", this.newIntegerList(this.size.getX(), this.size.getY(), this.size.getZ())); ++ // CraftBukkit start - PDC ++ if (!this.persistentDataContainer.isEmpty()) { ++ tag.put("BukkitValues", this.persistentDataContainer.toTagCompound()); ++ } ++ // CraftBukkit end ++ return NbtUtils.addCurrentDataVersion(tag); + } + +- public void load(HolderGetter holdergetter, CompoundTag compoundtag) { ++ public void load(HolderGetter blockGetter, CompoundTag tag) { + this.palettes.clear(); + this.entityInfoList.clear(); +- ListTag listtag = compoundtag.getList("size", 3); ++ ListTag nbttaglist = tag.getList("size", 3); + +- this.size = new Vec3i(listtag.getInt(0), listtag.getInt(1), listtag.getInt(2)); +- ListTag listtag1 = compoundtag.getList("blocks", 10); +- ListTag listtag2; ++ this.size = new Vec3i(nbttaglist.getInt(0), nbttaglist.getInt(1), nbttaglist.getInt(2)); ++ ListTag nbttaglist1 = tag.getList("blocks", 10); ++ ListTag nbttaglist2; + int i; + +- if (compoundtag.contains("palettes", 9)) { +- listtag2 = compoundtag.getList("palettes", 9); ++ if (tag.contains("palettes", 9)) { ++ nbttaglist2 = tag.getList("palettes", 9); + +- for (i = 0; i < listtag2.size(); ++i) { +- this.loadPalette(holdergetter, listtag2.getList(i), listtag1); ++ for (i = 0; i < nbttaglist2.size(); ++i) { ++ this.loadPalette(blockGetter, nbttaglist2.getList(i), nbttaglist1); + } + } else { +- this.loadPalette(holdergetter, compoundtag.getList("palette", 10), listtag1); ++ this.loadPalette(blockGetter, tag.getList("palette", 10), nbttaglist1); + } + +- listtag2 = compoundtag.getList("entities", 10); ++ nbttaglist2 = tag.getList("entities", 10); + +- for (i = 0; i < listtag2.size(); ++i) { +- CompoundTag compoundtag1 = listtag2.getCompound(i); +- ListTag listtag3 = compoundtag1.getList("pos", 6); +- Vec3 vec3 = new Vec3(listtag3.getDouble(0), listtag3.getDouble(1), listtag3.getDouble(2)); +- ListTag listtag4 = compoundtag1.getList("blockPos", 3); +- BlockPos blockpos = new BlockPos(listtag4.getInt(0), listtag4.getInt(1), listtag4.getInt(2)); ++ for (i = 0; i < nbttaglist2.size(); ++i) { ++ CompoundTag nbttagcompound1 = nbttaglist2.getCompound(i); ++ ListTag nbttaglist3 = nbttagcompound1.getList("pos", 6); ++ Vec3 vec3d = new Vec3(nbttaglist3.getDouble(0), nbttaglist3.getDouble(1), nbttaglist3.getDouble(2)); ++ ListTag nbttaglist4 = nbttagcompound1.getList("blockPos", 3); ++ BlockPos blockposition = new BlockPos(nbttaglist4.getInt(0), nbttaglist4.getInt(1), nbttaglist4.getInt(2)); + +- if (compoundtag1.contains("nbt")) { +- CompoundTag compoundtag2 = compoundtag1.getCompound("nbt"); ++ if (nbttagcompound1.contains("nbt")) { ++ CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("nbt"); + +- this.entityInfoList.add(new StructureTemplate.StructureEntityInfo(vec3, blockpos, compoundtag2)); ++ this.entityInfoList.add(new StructureTemplate.StructureEntityInfo(vec3d, blockposition, nbttagcompound2)); + } + } + ++ // CraftBukkit start - PDC ++ Tag base = tag.get("BukkitValues"); ++ if (base instanceof CompoundTag) { ++ this.persistentDataContainer.putAll((CompoundTag) base); ++ } ++ // CraftBukkit end + } + +- private void loadPalette(HolderGetter holdergetter, ListTag listtag, ListTag listtag1) { +- StructureTemplate.SimplePalette structuretemplate_simplepalette = new StructureTemplate.SimplePalette(); ++ private void loadPalette(HolderGetter blockGetter, ListTag paletteTag, ListTag blocksTag) { ++ StructureTemplate.SimplePalette definedstructure_b = new StructureTemplate.SimplePalette(); + +- for (int i = 0; i < listtag.size(); ++i) { +- structuretemplate_simplepalette.addMapping(NbtUtils.readBlockState(holdergetter, listtag.getCompound(i)), i); ++ for (int i = 0; i < paletteTag.size(); ++i) { ++ definedstructure_b.addMapping(NbtUtils.readBlockState(blockGetter, paletteTag.getCompound(i)), i); + } + + List list = Lists.newArrayList(); + List list1 = Lists.newArrayList(); + List list2 = Lists.newArrayList(); + +- for (int j = 0; j < listtag1.size(); ++j) { +- CompoundTag compoundtag = listtag1.getCompound(j); +- ListTag listtag2 = compoundtag.getList("pos", 3); +- BlockPos blockpos = new BlockPos(listtag2.getInt(0), listtag2.getInt(1), listtag2.getInt(2)); +- BlockState blockstate = structuretemplate_simplepalette.stateFor(compoundtag.getInt("state")); +- CompoundTag compoundtag1; ++ for (int j = 0; j < blocksTag.size(); ++j) { ++ CompoundTag nbttagcompound = blocksTag.getCompound(j); ++ ListTag nbttaglist2 = nbttagcompound.getList("pos", 3); ++ BlockPos blockposition = new BlockPos(nbttaglist2.getInt(0), nbttaglist2.getInt(1), nbttaglist2.getInt(2)); ++ IBlockData iblockdata = definedstructure_b.stateFor(nbttagcompound.getInt("state")); ++ CompoundTag nbttagcompound1; + +- if (compoundtag.contains("nbt")) { +- compoundtag1 = compoundtag.getCompound("nbt"); ++ if (nbttagcompound.contains("nbt")) { ++ nbttagcompound1 = nbttagcompound.getCompound("nbt"); + } else { +- compoundtag1 = null; ++ nbttagcompound1 = null; + } + +- StructureTemplate.StructureBlockInfo structuretemplate_structureblockinfo = new StructureTemplate.StructureBlockInfo(blockpos, blockstate, compoundtag1); ++ StructureTemplate.StructureBlockInfo definedstructure_blockinfo = new StructureTemplate.StructureBlockInfo(blockposition, iblockdata, nbttagcompound1); + +- addToLists(structuretemplate_structureblockinfo, list, list1, list2); ++ addToLists(definedstructure_blockinfo, list, list1, list2); + } + + List list3 = buildInfoList(list, list1, list2); +@@ -765,37 +814,36 @@ + this.palettes.add(new StructureTemplate.Palette(list3)); + } + +- private ListTag newIntegerList(int... aint) { +- ListTag listtag = new ListTag(); +- int[] aint1 = aint; +- int i = aint.length; ++ private ListTag newIntegerList(int... values) { ++ ListTag nbttaglist = new ListTag(); ++ int[] aint1 = values; ++ int i = values.length; + + for (int j = 0; j < i; ++j) { + int k = aint1[j]; + +- listtag.add(IntTag.valueOf(k)); ++ nbttaglist.add(IntTag.valueOf(k)); + } + +- return listtag; ++ return nbttaglist; + } + +- private ListTag newDoubleList(double... adouble) { +- ListTag listtag = new ListTag(); +- double[] adouble1 = adouble; +- int i = adouble.length; ++ private ListTag newDoubleList(double... values) { ++ ListTag nbttaglist = new ListTag(); ++ double[] adouble1 = values; ++ int i = values.length; + + for (int j = 0; j < i; ++j) { + double d0 = adouble1[j]; + +- listtag.add(DoubleTag.valueOf(d0)); ++ nbttaglist.add(DoubleTag.valueOf(d0)); + } + +- return listtag; ++ return nbttaglist; + } + +- public static record StructureBlockInfo(BlockPos pos, BlockState state, @Nullable CompoundTag nbt) { ++ public static record StructureBlockInfo(BlockPos pos, IBlockData state, @Nullable CompoundTag nbt) { + +- @Override + public String toString() { + return String.format(Locale.ROOT, "", this.pos, this.state, this.nbt); + } +@@ -806,8 +854,8 @@ + private final List blocks; + private final Map> cache = Maps.newHashMap(); + +- Palette(List list) { +- this.blocks = list; ++ Palette(List blocks) { ++ this.blocks = blocks; + } + + public List blocks() { +@@ -816,8 +864,8 @@ + + public List blocks(Block block) { + return (List) this.cache.computeIfAbsent(block, (block1) -> { +- return (List) this.blocks.stream().filter((structuretemplate_structureblockinfo) -> { +- return structuretemplate_structureblockinfo.state.is(block1); ++ return (List) this.blocks.stream().filter((definedstructure_blockinfo) -> { ++ return definedstructure_blockinfo.state.is(block1); + }).collect(Collectors.toList()); + }); + } +@@ -829,46 +877,45 @@ + public final BlockPos blockPos; + public final CompoundTag nbt; + +- public StructureEntityInfo(Vec3 vec3, BlockPos blockpos, CompoundTag compoundtag) { +- this.pos = vec3; +- this.blockPos = blockpos; +- this.nbt = compoundtag; ++ public StructureEntityInfo(Vec3 pos, BlockPos blockPos, CompoundTag nbt) { ++ this.pos = pos; ++ this.blockPos = blockPos; ++ this.nbt = nbt; + } + } + +- private static class SimplePalette implements Iterable { ++ private static class SimplePalette implements Iterable { + +- public static final BlockState DEFAULT_BLOCK_STATE = Blocks.AIR.defaultBlockState(); +- private final IdMapper ids = new IdMapper<>(16); ++ public static final IBlockData DEFAULT_BLOCK_STATE = Blocks.AIR.defaultBlockState(); ++ private final IdMapper ids = new IdMapper<>(16); + private int lastId; + + SimplePalette() {} + +- public int idFor(BlockState blockstate) { +- int i = this.ids.getId(blockstate); ++ public int idFor(IBlockData state) { ++ int i = this.ids.getId(state); + + if (i == -1) { + i = this.lastId++; +- this.ids.addMapping(blockstate, i); ++ this.ids.addMapping(state, i); + } + + return i; + } + + @Nullable +- public BlockState stateFor(int i) { +- BlockState blockstate = (BlockState) this.ids.byId(i); ++ public IBlockData stateFor(int id) { ++ IBlockData iblockdata = (IBlockData) this.ids.byId(id); + +- return blockstate == null ? StructureTemplate.SimplePalette.DEFAULT_BLOCK_STATE : blockstate; ++ return iblockdata == null ? DEFAULT_BLOCK_STATE : iblockdata; // CraftBukkit - decompile error + } + +- @Override +- public Iterator iterator() { ++ public Iterator iterator() { + return this.ids.iterator(); + } + +- public void addMapping(BlockState blockstate, int i) { +- this.ids.addMapping(blockstate, i); ++ public void addMapping(IBlockData state, int id) { ++ this.ids.addMapping(state, id); + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/material/FlowingFluid.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/material/FlowingFluid.java.patch new file mode 100644 index 0000000000..4cc34c0f86 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/material/FlowingFluid.java.patch @@ -0,0 +1,668 @@ +--- a/net/minecraft/world/level/material/FlowingFluid.java ++++ b/net/minecraft/world/level/material/FlowingFluid.java +@@ -23,7 +23,7 @@ + import net.minecraft.world.level.block.DoorBlock; + import net.minecraft.world.level.block.IceBlock; + import net.minecraft.world.level.block.LiquidBlockContainer; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -31,6 +31,14 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.block.BlockFace; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.block.BlockFromToEvent; ++import org.bukkit.event.block.FluidLevelChangeEvent; ++// CraftBukkit end + + public abstract class FlowingFluid extends Fluid { + +@@ -39,7 +47,6 @@ + private static final int CACHE_SIZE = 200; + private static final ThreadLocal> OCCLUSION_CACHE = ThreadLocal.withInitial(() -> { + Object2ByteLinkedOpenHashMap object2bytelinkedopenhashmap = new Object2ByteLinkedOpenHashMap(200) { +- @Override + protected void rehash(int i) {} + }; + +@@ -51,161 +58,177 @@ + public FlowingFluid() {} + + @Override +- @Override +- protected void createFluidStateDefinition(StateDefinition.Builder statedefinition_builder) { +- statedefinition_builder.add(FlowingFluid.FALLING); ++ protected void createFluidStateDefinition(StateDefinition.Builder builder) { ++ builder.add(FlowingFluid.FALLING); + } + + @Override +- @Override +- public Vec3 getFlow(BlockGetter blockgetter, BlockPos blockpos, FluidState fluidstate) { ++ public Vec3 getFlow(BlockGetter blockReader, BlockPos pos, FluidState fluidState) { + double d0 = 0.0D; + double d1 = 0.0D; +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); ++ Direction enumdirection = (Direction) iterator.next(); + +- blockpos_mutableblockpos.setWithOffset(blockpos, direction); +- FluidState fluidstate1 = blockgetter.getFluidState(blockpos_mutableblockpos); ++ blockposition_mutableblockposition.setWithOffset(pos, enumdirection); ++ FluidState fluid1 = blockReader.getFluidState(blockposition_mutableblockposition); + +- if (this.affectsFlow(fluidstate1)) { +- float f = fluidstate1.getOwnHeight(); ++ if (this.affectsFlow(fluid1)) { ++ float f = fluid1.getOwnHeight(); + float f1 = 0.0F; + + if (f == 0.0F) { +- if (!blockgetter.getBlockState(blockpos_mutableblockpos).blocksMotion()) { +- BlockPos blockpos1 = blockpos_mutableblockpos.below(); +- FluidState fluidstate2 = blockgetter.getFluidState(blockpos1); ++ if (!blockReader.getBlockState(blockposition_mutableblockposition).blocksMotion()) { ++ BlockPos blockposition1 = blockposition_mutableblockposition.below(); ++ FluidState fluid2 = blockReader.getFluidState(blockposition1); + +- if (this.affectsFlow(fluidstate2)) { +- f = fluidstate2.getOwnHeight(); ++ if (this.affectsFlow(fluid2)) { ++ f = fluid2.getOwnHeight(); + if (f > 0.0F) { +- f1 = fluidstate.getOwnHeight() - (f - 0.8888889F); ++ f1 = fluidState.getOwnHeight() - (f - 0.8888889F); + } + } + } + } else if (f > 0.0F) { +- f1 = fluidstate.getOwnHeight() - f; ++ f1 = fluidState.getOwnHeight() - f; + } + + if (f1 != 0.0F) { +- d0 += (double) ((float) direction.getStepX() * f1); +- d1 += (double) ((float) direction.getStepZ() * f1); ++ d0 += (double) ((float) enumdirection.getStepX() * f1); ++ d1 += (double) ((float) enumdirection.getStepZ() * f1); + } + } + } + +- Vec3 vec3 = new Vec3(d0, 0.0D, d1); ++ Vec3 vec3d = new Vec3(d0, 0.0D, d1); + +- if ((Boolean) fluidstate.getValue(FlowingFluid.FALLING)) { ++ if ((Boolean) fluidState.getValue(FlowingFluid.FALLING)) { + Iterator iterator1 = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator1.hasNext()) { +- Direction direction1 = (Direction) iterator1.next(); ++ Direction enumdirection1 = (Direction) iterator1.next(); + +- blockpos_mutableblockpos.setWithOffset(blockpos, direction1); +- if (this.isSolidFace(blockgetter, blockpos_mutableblockpos, direction1) || this.isSolidFace(blockgetter, blockpos_mutableblockpos.above(), direction1)) { +- vec3 = vec3.normalize().add(0.0D, -6.0D, 0.0D); ++ blockposition_mutableblockposition.setWithOffset(pos, enumdirection1); ++ if (this.isSolidFace(blockReader, blockposition_mutableblockposition, enumdirection1) || this.isSolidFace(blockReader, blockposition_mutableblockposition.above(), enumdirection1)) { ++ vec3d = vec3d.normalize().add(0.0D, -6.0D, 0.0D); + break; + } + } + } + +- return vec3.normalize(); ++ return vec3d.normalize(); + } + +- private boolean affectsFlow(FluidState fluidstate) { +- return fluidstate.isEmpty() || fluidstate.getType().isSame(this); ++ private boolean affectsFlow(FluidState state) { ++ return state.isEmpty() || state.getType().isSame(this); + } + +- protected boolean isSolidFace(BlockGetter blockgetter, BlockPos blockpos, Direction direction) { +- BlockState blockstate = blockgetter.getBlockState(blockpos); +- FluidState fluidstate = blockgetter.getFluidState(blockpos); ++ protected boolean isSolidFace(BlockGetter level, BlockPos neighborPos, Direction side) { ++ IBlockData iblockdata = level.getBlockState(neighborPos); ++ FluidState fluid = level.getFluidState(neighborPos); + +- return fluidstate.getType().isSame(this) ? false : (direction == Direction.UP ? true : (blockstate.getBlock() instanceof IceBlock ? false : blockstate.isFaceSturdy(blockgetter, blockpos, direction))); ++ return fluid.getType().isSame(this) ? false : (side == Direction.UP ? true : (iblockdata.getBlock() instanceof IceBlock ? false : iblockdata.isFaceSturdy(level, neighborPos, side))); + } + +- protected void spread(Level level, BlockPos blockpos, FluidState fluidstate) { +- if (!fluidstate.isEmpty()) { +- BlockState blockstate = level.getBlockState(blockpos); +- BlockPos blockpos1 = blockpos.below(); +- BlockState blockstate1 = level.getBlockState(blockpos1); +- FluidState fluidstate1 = this.getNewLiquid(level, blockpos1, blockstate1); ++ protected void spread(Level level, BlockPos pos, FluidState state) { ++ if (!state.isEmpty()) { ++ IBlockData iblockdata = level.getBlockState(pos); ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ FluidState fluid1 = this.getNewLiquid(level, blockposition1, iblockdata1); + +- if (this.canSpreadTo(level, blockpos, blockstate, Direction.DOWN, blockpos1, blockstate1, level.getFluidState(blockpos1), fluidstate1.getType())) { +- this.spreadTo(level, blockpos1, blockstate1, Direction.DOWN, fluidstate1); +- if (this.sourceNeighborCount(level, blockpos) >= 3) { +- this.spreadToSides(level, blockpos, fluidstate, blockstate); ++ if (this.canSpreadTo(level, pos, iblockdata, Direction.DOWN, blockposition1, iblockdata1, level.getFluidState(blockposition1), fluid1.getType())) { ++ // CraftBukkit start ++ org.bukkit.block.Block source = CraftBlock.at(level, pos); ++ BlockFromToEvent event = new BlockFromToEvent(source, BlockFace.DOWN); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; + } +- } else if (fluidstate.isSource() || !this.isWaterHole(level, fluidstate1.getType(), blockpos, blockstate, blockpos1, blockstate1)) { +- this.spreadToSides(level, blockpos, fluidstate, blockstate); ++ // CraftBukkit end ++ this.spreadTo(level, blockposition1, iblockdata1, Direction.DOWN, fluid1); ++ if (this.sourceNeighborCount(level, pos) >= 3) { ++ this.spreadToSides(level, pos, state, iblockdata); ++ } ++ } else if (state.isSource() || !this.isWaterHole(level, fluid1.getType(), pos, iblockdata, blockposition1, iblockdata1)) { ++ this.spreadToSides(level, pos, state, iblockdata); + } + + } + } + +- private void spreadToSides(Level level, BlockPos blockpos, FluidState fluidstate, BlockState blockstate) { +- int i = fluidstate.getAmount() - this.getDropOff(level); ++ private void spreadToSides(Level level, BlockPos pos, FluidState fluidState, IBlockData blockState) { ++ int i = fluidState.getAmount() - this.getDropOff(level); + +- if ((Boolean) fluidstate.getValue(FlowingFluid.FALLING)) { ++ if ((Boolean) fluidState.getValue(FlowingFluid.FALLING)) { + i = 7; + } + + if (i > 0) { +- Map map = this.getSpread(level, blockpos, blockstate); ++ Map map = this.getSpread(level, pos, blockState); + Iterator iterator = map.entrySet().iterator(); + + while (iterator.hasNext()) { + Entry entry = (Entry) iterator.next(); +- Direction direction = (Direction) entry.getKey(); +- FluidState fluidstate1 = (FluidState) entry.getValue(); +- BlockPos blockpos1 = blockpos.relative(direction); +- BlockState blockstate1 = level.getBlockState(blockpos1); ++ Direction enumdirection = (Direction) entry.getKey(); ++ FluidState fluid1 = (FluidState) entry.getValue(); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + +- if (this.canSpreadTo(level, blockpos, blockstate, direction, blockpos1, blockstate1, level.getFluidState(blockpos1), fluidstate1.getType())) { +- this.spreadTo(level, blockpos1, blockstate1, direction, fluidstate1); ++ if (this.canSpreadTo(level, pos, blockState, enumdirection, blockposition1, iblockdata1, level.getFluidState(blockposition1), fluid1.getType())) { ++ // CraftBukkit start ++ org.bukkit.block.Block source = CraftBlock.at(level, pos); ++ BlockFromToEvent event = new BlockFromToEvent(source, org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(enumdirection)); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end ++ this.spreadTo(level, blockposition1, iblockdata1, enumdirection, fluid1); + } + } + + } + } + +- protected FluidState getNewLiquid(Level level, BlockPos blockpos, BlockState blockstate) { ++ protected FluidState getNewLiquid(Level level, BlockPos pos, IBlockData blockState) { + int i = 0; + int j = 0; + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); +- BlockPos blockpos1 = blockpos.relative(direction); +- BlockState blockstate1 = level.getBlockState(blockpos1); +- FluidState fluidstate = blockstate1.getFluidState(); ++ Direction enumdirection = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ FluidState fluid = iblockdata1.getFluidState(); + +- if (fluidstate.getType().isSame(this) && this.canPassThroughWall(direction, level, blockpos, blockstate, blockpos1, blockstate1)) { +- if (fluidstate.isSource()) { ++ if (fluid.getType().isSame(this) && this.canPassThroughWall(enumdirection, level, pos, blockState, blockposition1, iblockdata1)) { ++ if (fluid.isSource()) { + ++j; + } + +- i = Math.max(i, fluidstate.getAmount()); ++ i = Math.max(i, fluid.getAmount()); + } + } + + if (this.canConvertToSource(level) && j >= 2) { +- BlockState blockstate2 = level.getBlockState(blockpos.below()); +- FluidState fluidstate1 = blockstate2.getFluidState(); ++ IBlockData iblockdata2 = level.getBlockState(pos.below()); ++ FluidState fluid1 = iblockdata2.getFluidState(); + +- if (blockstate2.isSolid() || this.isSourceBlockOfThisType(fluidstate1)) { ++ if (iblockdata2.isSolid() || this.isSourceBlockOfThisType(fluid1)) { + return this.getSource(false); + } + } + +- BlockPos blockpos2 = blockpos.above(); +- BlockState blockstate3 = level.getBlockState(blockpos2); +- FluidState fluidstate2 = blockstate3.getFluidState(); ++ BlockPos blockposition2 = pos.above(); ++ IBlockData iblockdata3 = level.getBlockState(blockposition2); ++ FluidState fluid2 = iblockdata3.getFluidState(); + +- if (!fluidstate2.isEmpty() && fluidstate2.getType().isSame(this) && this.canPassThroughWall(Direction.UP, level, blockpos, blockstate, blockpos2, blockstate3)) { ++ if (!fluid2.isEmpty() && fluid2.getType().isSame(this) && this.canPassThroughWall(Direction.UP, level, pos, blockState, blockposition2, iblockdata3)) { + return this.getFlowing(8, true); + } else { + int k = i - this.getDropOff(level); +@@ -214,30 +237,30 @@ + } + } + +- private boolean canPassThroughWall(Direction direction, BlockGetter blockgetter, BlockPos blockpos, BlockState blockstate, BlockPos blockpos1, BlockState blockstate1) { ++ private boolean canPassThroughWall(Direction direction, BlockGetter level, BlockPos pos, IBlockData state, BlockPos spreadPos, IBlockData spreadState) { + Object2ByteLinkedOpenHashMap object2bytelinkedopenhashmap; + +- if (!blockstate.getBlock().hasDynamicShape() && !blockstate1.getBlock().hasDynamicShape()) { ++ if (!state.getBlock().hasDynamicShape() && !spreadState.getBlock().hasDynamicShape()) { + object2bytelinkedopenhashmap = (Object2ByteLinkedOpenHashMap) FlowingFluid.OCCLUSION_CACHE.get(); + } else { + object2bytelinkedopenhashmap = null; + } + +- Block.BlockStatePairKey block_blockstatepairkey; ++ Block.BlockStatePairKey block_a; + + if (object2bytelinkedopenhashmap != null) { +- block_blockstatepairkey = new Block.BlockStatePairKey(blockstate, blockstate1, direction); +- byte b0 = object2bytelinkedopenhashmap.getAndMoveToFirst(block_blockstatepairkey); ++ block_a = new Block.BlockStatePairKey(state, spreadState, direction); ++ byte b0 = object2bytelinkedopenhashmap.getAndMoveToFirst(block_a); + + if (b0 != 127) { + return b0 != 0; + } + } else { +- block_blockstatepairkey = null; ++ block_a = null; + } + +- VoxelShape voxelshape = blockstate.getCollisionShape(blockgetter, blockpos); +- VoxelShape voxelshape1 = blockstate1.getCollisionShape(blockgetter, blockpos1); ++ VoxelShape voxelshape = state.getCollisionShape(level, pos); ++ VoxelShape voxelshape1 = spreadState.getCollisionShape(level, spreadPos); + boolean flag = !Shapes.mergedFaceOccludes(voxelshape, voxelshape1, direction); + + if (object2bytelinkedopenhashmap != null) { +@@ -245,7 +268,7 @@ + object2bytelinkedopenhashmap.removeLastByte(); + } + +- object2bytelinkedopenhashmap.putAndMoveToFirst(block_blockstatepairkey, (byte) (flag ? 1 : 0)); ++ object2bytelinkedopenhashmap.putAndMoveToFirst(block_a, (byte) (flag ? 1 : 0)); + } + + return flag; +@@ -253,72 +276,72 @@ + + public abstract Fluid getFlowing(); + +- public FluidState getFlowing(int i, boolean flag) { +- return (FluidState) ((FluidState) this.getFlowing().defaultFluidState().setValue(FlowingFluid.LEVEL, i)).setValue(FlowingFluid.FALLING, flag); ++ public FluidState getFlowing(int level, boolean falling) { ++ return (FluidState) ((FluidState) this.getFlowing().defaultFluidState().setValue(FlowingFluid.LEVEL, level)).setValue(FlowingFluid.FALLING, falling); + } + + public abstract Fluid getSource(); + +- public FluidState getSource(boolean flag) { +- return (FluidState) this.getSource().defaultFluidState().setValue(FlowingFluid.FALLING, flag); ++ public FluidState getSource(boolean falling) { ++ return (FluidState) this.getSource().defaultFluidState().setValue(FlowingFluid.FALLING, falling); + } + + protected abstract boolean canConvertToSource(Level level); + +- protected void spreadTo(LevelAccessor levelaccessor, BlockPos blockpos, BlockState blockstate, Direction direction, FluidState fluidstate) { +- if (blockstate.getBlock() instanceof LiquidBlockContainer) { +- ((LiquidBlockContainer) blockstate.getBlock()).placeLiquid(levelaccessor, blockpos, blockstate, fluidstate); ++ protected void spreadTo(LevelAccessor level, BlockPos pos, IBlockData blockState, Direction direction, FluidState fluidState) { ++ if (blockState.getBlock() instanceof LiquidBlockContainer) { ++ ((LiquidBlockContainer) blockState.getBlock()).placeLiquid(level, pos, blockState, fluidState); + } else { +- if (!blockstate.isAir()) { +- this.beforeDestroyingBlock(levelaccessor, blockpos, blockstate); ++ if (!blockState.isAir()) { ++ this.beforeDestroyingBlock(level, pos, blockState); + } + +- levelaccessor.setBlock(blockpos, fluidstate.createLegacyBlock(), 3); ++ level.setBlock(pos, fluidState.createLegacyBlock(), 3); + } + + } + +- protected abstract void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, BlockState state); ++ protected abstract void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, IBlockData state); + +- private static short getCacheKey(BlockPos blockpos, BlockPos blockpos1) { +- int i = blockpos1.getX() - blockpos.getX(); +- int j = blockpos1.getZ() - blockpos.getZ(); ++ private static short getCacheKey(BlockPos sourcePos, BlockPos spreadPos) { ++ int i = spreadPos.getX() - sourcePos.getX(); ++ int j = spreadPos.getZ() - sourcePos.getZ(); + + return (short) ((i + 128 & 255) << 8 | j + 128 & 255); + } + +- protected int getSlopeDistance(LevelReader levelreader, BlockPos blockpos, int i, Direction direction, BlockState blockstate, BlockPos blockpos1, Short2ObjectMap> short2objectmap, Short2BooleanMap short2booleanmap) { ++ protected int getSlopeDistance(LevelReader level, BlockPos spreadPos, int distance, Direction direction, IBlockData currentSpreadState, BlockPos sourcePos, Short2ObjectMap> stateCache, Short2BooleanMap waterHoleCache) { + int j = 1000; + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction1 = (Direction) iterator.next(); ++ Direction enumdirection1 = (Direction) iterator.next(); + +- if (direction1 != direction) { +- BlockPos blockpos2 = blockpos.relative(direction1); +- short short0 = getCacheKey(blockpos1, blockpos2); +- Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (short1) -> { +- BlockState blockstate1 = levelreader.getBlockState(blockpos2); ++ if (enumdirection1 != direction) { ++ BlockPos blockposition2 = spreadPos.relative(enumdirection1); ++ short short0 = getCacheKey(sourcePos, blockposition2); ++ Pair pair = (Pair) stateCache.computeIfAbsent(short0, (short1) -> { ++ IBlockData iblockdata1 = level.getBlockState(blockposition2); + +- return Pair.of(blockstate1, blockstate1.getFluidState()); ++ return Pair.of(iblockdata1, iblockdata1.getFluidState()); + }); +- BlockState blockstate1 = (BlockState) pair.getFirst(); +- FluidState fluidstate = (FluidState) pair.getSecond(); ++ IBlockData iblockdata1 = (IBlockData) pair.getFirst(); ++ FluidState fluid = (FluidState) pair.getSecond(); + +- if (this.canPassThrough(levelreader, this.getFlowing(), blockpos, blockstate, direction1, blockpos2, blockstate1, fluidstate)) { +- boolean flag = short2booleanmap.computeIfAbsent(short0, (short1) -> { +- BlockPos blockpos3 = blockpos2.below(); +- BlockState blockstate2 = levelreader.getBlockState(blockpos3); ++ if (this.canPassThrough(level, this.getFlowing(), spreadPos, currentSpreadState, enumdirection1, blockposition2, iblockdata1, fluid)) { ++ boolean flag = waterHoleCache.computeIfAbsent(short0, (short1) -> { ++ BlockPos blockposition3 = blockposition2.below(); ++ IBlockData iblockdata2 = level.getBlockState(blockposition3); + +- return this.isWaterHole(levelreader, this.getFlowing(), blockpos2, blockstate1, blockpos3, blockstate2); ++ return this.isWaterHole(level, this.getFlowing(), blockposition2, iblockdata1, blockposition3, iblockdata2); + }); + + if (flag) { +- return i; ++ return distance; + } + +- if (i < this.getSlopeFindDistance(levelreader)) { +- int k = this.getSlopeDistance(levelreader, blockpos2, i + 1, direction1.getOpposite(), blockstate1, blockpos1, short2objectmap, short2booleanmap); ++ if (distance < this.getSlopeFindDistance(level)) { ++ int k = this.getSlopeDistance(level, blockposition2, distance + 1, enumdirection1.getOpposite(), iblockdata1, sourcePos, stateCache, waterHoleCache); + + if (k < j) { + j = k; +@@ -331,30 +354,30 @@ + return j; + } + +- private boolean isWaterHole(BlockGetter blockgetter, Fluid fluid, BlockPos blockpos, BlockState blockstate, BlockPos blockpos1, BlockState blockstate1) { +- return !this.canPassThroughWall(Direction.DOWN, blockgetter, blockpos, blockstate, blockpos1, blockstate1) ? false : (blockstate1.getFluidState().getType().isSame(this) ? true : this.canHoldFluid(blockgetter, blockpos1, blockstate1, fluid)); ++ private boolean isWaterHole(BlockGetter level, Fluid fluid, BlockPos pos, IBlockData state, BlockPos spreadPos, IBlockData spreadState) { ++ return !this.canPassThroughWall(Direction.DOWN, level, pos, state, spreadPos, spreadState) ? false : (spreadState.getFluidState().getType().isSame(this) ? true : this.canHoldFluid(level, spreadPos, spreadState, fluid)); + } + +- private boolean canPassThrough(BlockGetter blockgetter, Fluid fluid, BlockPos blockpos, BlockState blockstate, Direction direction, BlockPos blockpos1, BlockState blockstate1, FluidState fluidstate) { +- return !this.isSourceBlockOfThisType(fluidstate) && this.canPassThroughWall(direction, blockgetter, blockpos, blockstate, blockpos1, blockstate1) && this.canHoldFluid(blockgetter, blockpos1, blockstate1, fluid); ++ private boolean canPassThrough(BlockGetter level, Fluid fluid, BlockPos pos, IBlockData state, Direction direction, BlockPos spreadPos, IBlockData spreadState, FluidState fluidState) { ++ return !this.isSourceBlockOfThisType(fluidState) && this.canPassThroughWall(direction, level, pos, state, spreadPos, spreadState) && this.canHoldFluid(level, spreadPos, spreadState, fluid); + } + +- private boolean isSourceBlockOfThisType(FluidState fluidstate) { +- return fluidstate.getType().isSame(this) && fluidstate.isSource(); ++ private boolean isSourceBlockOfThisType(FluidState state) { ++ return state.getType().isSame(this) && state.isSource(); + } + + protected abstract int getSlopeFindDistance(LevelReader level); + +- private int sourceNeighborCount(LevelReader levelreader, BlockPos blockpos) { ++ private int sourceNeighborCount(LevelReader level, BlockPos pos) { + int i = 0; + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); +- BlockPos blockpos1 = blockpos.relative(direction); +- FluidState fluidstate = levelreader.getFluidState(blockpos1); ++ Direction enumdirection = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ FluidState fluid = level.getFluidState(blockposition1); + +- if (this.isSourceBlockOfThisType(fluidstate)) { ++ if (this.isSourceBlockOfThisType(fluid)) { + ++i; + } + } +@@ -362,39 +385,39 @@ + return i; + } + +- protected Map getSpread(Level level, BlockPos blockpos, BlockState blockstate) { ++ protected Map getSpread(Level level, BlockPos pos, IBlockData state) { + int i = 1000; + Map map = Maps.newEnumMap(Direction.class); +- Short2ObjectMap> short2objectmap = new Short2ObjectOpenHashMap(); ++ Short2ObjectMap> short2objectmap = new Short2ObjectOpenHashMap(); + Short2BooleanOpenHashMap short2booleanopenhashmap = new Short2BooleanOpenHashMap(); + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + + while (iterator.hasNext()) { +- Direction direction = (Direction) iterator.next(); +- BlockPos blockpos1 = blockpos.relative(direction); +- short short0 = getCacheKey(blockpos, blockpos1); +- Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (short1) -> { +- BlockState blockstate1 = level.getBlockState(blockpos1); ++ Direction enumdirection = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ short short0 = getCacheKey(pos, blockposition1); ++ Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (short1) -> { ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + +- return Pair.of(blockstate1, blockstate1.getFluidState()); ++ return Pair.of(iblockdata1, iblockdata1.getFluidState()); + }); +- BlockState blockstate1 = (BlockState) pair.getFirst(); +- FluidState fluidstate = (FluidState) pair.getSecond(); +- FluidState fluidstate1 = this.getNewLiquid(level, blockpos1, blockstate1); ++ IBlockData iblockdata1 = (IBlockData) pair.getFirst(); ++ FluidState fluid = (FluidState) pair.getSecond(); ++ FluidState fluid1 = this.getNewLiquid(level, blockposition1, iblockdata1); + +- if (this.canPassThrough(level, fluidstate1.getType(), blockpos, blockstate, direction, blockpos1, blockstate1, fluidstate)) { +- BlockPos blockpos2 = blockpos1.below(); ++ if (this.canPassThrough(level, fluid1.getType(), pos, state, enumdirection, blockposition1, iblockdata1, fluid)) { ++ BlockPos blockposition2 = blockposition1.below(); + boolean flag = short2booleanopenhashmap.computeIfAbsent(short0, (short1) -> { +- BlockState blockstate2 = level.getBlockState(blockpos2); ++ IBlockData iblockdata2 = level.getBlockState(blockposition2); + +- return this.isWaterHole(level, this.getFlowing(), blockpos1, blockstate1, blockpos2, blockstate2); ++ return this.isWaterHole(level, this.getFlowing(), blockposition1, iblockdata1, blockposition2, iblockdata2); + }); + int j; + + if (flag) { + j = 0; + } else { +- j = this.getSlopeDistance(level, blockpos1, 1, direction.getOpposite(), blockstate1, blockpos, short2objectmap, short2booleanopenhashmap); ++ j = this.getSlopeDistance(level, blockposition1, 1, enumdirection.getOpposite(), iblockdata1, pos, short2objectmap, short2booleanopenhashmap); + } + + if (j < i) { +@@ -402,7 +425,7 @@ + } + + if (j <= i) { +- map.put(direction, fluidstate1); ++ map.put(enumdirection, fluid1); + i = j; + } + } +@@ -411,80 +434,86 @@ + return map; + } + +- private boolean canHoldFluid(BlockGetter blockgetter, BlockPos blockpos, BlockState blockstate, Fluid fluid) { +- Block block = blockstate.getBlock(); ++ private boolean canHoldFluid(BlockGetter level, BlockPos pos, IBlockData state, Fluid fluid) { ++ Block block = state.getBlock(); + + if (block instanceof LiquidBlockContainer) { +- LiquidBlockContainer liquidblockcontainer = (LiquidBlockContainer) block; ++ LiquidBlockContainer ifluidcontainer = (LiquidBlockContainer) block; + +- return liquidblockcontainer.canPlaceLiquid((Player) null, blockgetter, blockpos, blockstate, fluid); ++ return ifluidcontainer.canPlaceLiquid((Player) null, level, pos, state, fluid); + } else { +- return !(block instanceof DoorBlock) && !blockstate.is(BlockTags.SIGNS) && !blockstate.is(Blocks.LADDER) && !blockstate.is(Blocks.SUGAR_CANE) && !blockstate.is(Blocks.BUBBLE_COLUMN) ? (!blockstate.is(Blocks.NETHER_PORTAL) && !blockstate.is(Blocks.END_PORTAL) && !blockstate.is(Blocks.END_GATEWAY) && !blockstate.is(Blocks.STRUCTURE_VOID) ? !blockstate.blocksMotion() : false) : false; ++ return !(block instanceof DoorBlock) && !state.is(BlockTags.SIGNS) && !state.is(Blocks.LADDER) && !state.is(Blocks.SUGAR_CANE) && !state.is(Blocks.BUBBLE_COLUMN) ? (!state.is(Blocks.NETHER_PORTAL) && !state.is(Blocks.END_PORTAL) && !state.is(Blocks.END_GATEWAY) && !state.is(Blocks.STRUCTURE_VOID) ? !state.blocksMotion() : false) : false; + } + } + +- protected boolean canSpreadTo(BlockGetter blockgetter, BlockPos blockpos, BlockState blockstate, Direction direction, BlockPos blockpos1, BlockState blockstate1, FluidState fluidstate, Fluid fluid) { +- return fluidstate.canBeReplacedWith(blockgetter, blockpos1, fluid, direction) && this.canPassThroughWall(direction, blockgetter, blockpos, blockstate, blockpos1, blockstate1) && this.canHoldFluid(blockgetter, blockpos1, blockstate1, fluid); ++ protected boolean canSpreadTo(BlockGetter level, BlockPos fromPos, IBlockData fromBlockState, Direction direction, BlockPos toPos, IBlockData toBlockState, FluidState toFluidState, Fluid fluid) { ++ return toFluidState.canBeReplacedWith(level, toPos, fluid, direction) && this.canPassThroughWall(direction, level, fromPos, fromBlockState, toPos, toBlockState) && this.canHoldFluid(level, toPos, toBlockState, fluid); + } + + protected abstract int getDropOff(LevelReader level); + +- protected int getSpreadDelay(Level level, BlockPos blockpos, FluidState fluidstate, FluidState fluidstate1) { ++ protected int getSpreadDelay(Level level, BlockPos pos, FluidState currentState, FluidState newState) { + return this.getTickDelay(level); + } + + @Override +- @Override +- public void tick(Level level, BlockPos blockpos, FluidState fluidstate) { +- if (!fluidstate.isSource()) { +- FluidState fluidstate1 = this.getNewLiquid(level, blockpos, level.getBlockState(blockpos)); +- int i = this.getSpreadDelay(level, blockpos, fluidstate, fluidstate1); ++ public void tick(Level level, BlockPos pos, FluidState state) { ++ if (!state.isSource()) { ++ FluidState fluid1 = this.getNewLiquid(level, pos, level.getBlockState(pos)); ++ int i = this.getSpreadDelay(level, pos, state, fluid1); + +- if (fluidstate1.isEmpty()) { +- fluidstate = fluidstate1; +- level.setBlock(blockpos, Blocks.AIR.defaultBlockState(), 3); +- } else if (!fluidstate1.equals(fluidstate)) { +- fluidstate = fluidstate1; +- BlockState blockstate = fluidstate1.createLegacyBlock(); +- +- level.setBlock(blockpos, blockstate, 2); +- level.scheduleTick(blockpos, fluidstate1.getType(), i); +- level.updateNeighborsAt(blockpos, blockstate.getBlock()); ++ if (fluid1.isEmpty()) { ++ state = fluid1; ++ // CraftBukkit start ++ FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(level, pos, Blocks.AIR.defaultBlockState()); ++ if (event.isCancelled()) { ++ return; ++ } ++ level.setBlock(pos, ((CraftBlockData) event.getNewData()).getState(), 3); ++ // CraftBukkit end ++ } else if (!fluid1.equals(state)) { ++ state = fluid1; ++ IBlockData iblockdata = fluid1.createLegacyBlock(); ++ // CraftBukkit start ++ FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(level, pos, iblockdata); ++ if (event.isCancelled()) { ++ return; ++ } ++ level.setBlock(pos, ((CraftBlockData) event.getNewData()).getState(), 2); ++ // CraftBukkit end ++ level.scheduleTick(pos, fluid1.getType(), i); ++ level.updateNeighborsAt(pos, iblockdata.getBlock()); + } + } + +- this.spread(level, blockpos, fluidstate); ++ this.spread(level, pos, state); + } + +- protected static int getLegacyLevel(FluidState fluidstate) { +- return fluidstate.isSource() ? 0 : 8 - Math.min(fluidstate.getAmount(), 8) + ((Boolean) fluidstate.getValue(FlowingFluid.FALLING) ? 8 : 0); ++ protected static int getLegacyLevel(FluidState state) { ++ return state.isSource() ? 0 : 8 - Math.min(state.getAmount(), 8) + ((Boolean) state.getValue(FlowingFluid.FALLING) ? 8 : 0); + } + +- private static boolean hasSameAbove(FluidState fluidstate, BlockGetter blockgetter, BlockPos blockpos) { +- return fluidstate.getType().isSame(blockgetter.getFluidState(blockpos.above()).getType()); ++ private static boolean hasSameAbove(FluidState fluidState, BlockGetter level, BlockPos pos) { ++ return fluidState.getType().isSame(level.getFluidState(pos.above()).getType()); + } + + @Override +- @Override +- public float getHeight(FluidState fluidstate, BlockGetter blockgetter, BlockPos blockpos) { +- return hasSameAbove(fluidstate, blockgetter, blockpos) ? 1.0F : fluidstate.getOwnHeight(); ++ public float getHeight(FluidState state, BlockGetter level, BlockPos pos) { ++ return hasSameAbove(state, level, pos) ? 1.0F : state.getOwnHeight(); + } + + @Override +- @Override +- public float getOwnHeight(FluidState fluidstate) { +- return (float) fluidstate.getAmount() / 9.0F; ++ public float getOwnHeight(FluidState state) { ++ return (float) state.getAmount() / 9.0F; + } + + @Override +- @Override + public abstract int getAmount(FluidState state); + + @Override +- @Override +- public VoxelShape getShape(FluidState fluidstate, BlockGetter blockgetter, BlockPos blockpos) { +- return fluidstate.getAmount() == 9 && hasSameAbove(fluidstate, blockgetter, blockpos) ? Shapes.block() : (VoxelShape) this.shapes.computeIfAbsent(fluidstate, (fluidstate1) -> { +- return Shapes.box(0.0D, 0.0D, 0.0D, 1.0D, (double) fluidstate1.getHeight(blockgetter, blockpos), 1.0D); ++ public VoxelShape getShape(FluidState state, BlockGetter level, BlockPos pos) { ++ return state.getAmount() == 9 && hasSameAbove(state, level, pos) ? Shapes.block() : (VoxelShape) this.shapes.computeIfAbsent(state, (fluid1) -> { ++ return Shapes.box(0.0D, 0.0D, 0.0D, 1.0D, (double) fluid1.getHeight(level, pos), 1.0D); + }); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/material/LavaFluid.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/material/LavaFluid.java.patch new file mode 100644 index 0000000000..22f5f0380b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/material/LavaFluid.java.patch @@ -0,0 +1,341 @@ +--- a/net/minecraft/world/level/material/LavaFluid.java ++++ b/net/minecraft/world/level/material/LavaFluid.java +@@ -21,7 +21,7 @@ + import net.minecraft.world.level.block.BaseFireBlock; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.LiquidBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + + public abstract class LavaFluid extends FlowingFluid { +@@ -31,81 +31,91 @@ + public LavaFluid() {} + + @Override +- @Override + public Fluid getFlowing() { + return Fluids.FLOWING_LAVA; + } + + @Override +- @Override + public Fluid getSource() { + return Fluids.LAVA; + } + + @Override +- @Override + public Item getBucket() { + return Items.LAVA_BUCKET; + } + + @Override +- @Override +- public void animateTick(Level level, BlockPos blockpos, FluidState fluidstate, RandomSource randomsource) { +- BlockPos blockpos1 = blockpos.above(); ++ public void animateTick(Level level, BlockPos pos, FluidState state, RandomSource random) { ++ BlockPos blockposition1 = pos.above(); + +- if (level.getBlockState(blockpos1).isAir() && !level.getBlockState(blockpos1).isSolidRender(level, blockpos1)) { +- if (randomsource.nextInt(100) == 0) { +- double d0 = (double) blockpos.getX() + randomsource.nextDouble(); +- double d1 = (double) blockpos.getY() + 1.0D; +- double d2 = (double) blockpos.getZ() + randomsource.nextDouble(); ++ if (level.getBlockState(blockposition1).isAir() && !level.getBlockState(blockposition1).isSolidRender(level, blockposition1)) { ++ if (random.nextInt(100) == 0) { ++ double d0 = (double) pos.getX() + random.nextDouble(); ++ double d1 = (double) pos.getY() + 1.0D; ++ double d2 = (double) pos.getZ() + random.nextDouble(); + + level.addParticle(ParticleTypes.LAVA, d0, d1, d2, 0.0D, 0.0D, 0.0D); +- level.playLocalSound(d0, d1, d2, SoundEvents.LAVA_POP, SoundSource.BLOCKS, 0.2F + randomsource.nextFloat() * 0.2F, 0.9F + randomsource.nextFloat() * 0.15F, false); ++ level.playLocalSound(d0, d1, d2, SoundEvents.LAVA_POP, SoundSource.BLOCKS, 0.2F + random.nextFloat() * 0.2F, 0.9F + random.nextFloat() * 0.15F, false); + } + +- if (randomsource.nextInt(200) == 0) { +- level.playLocalSound((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), SoundEvents.LAVA_AMBIENT, SoundSource.BLOCKS, 0.2F + randomsource.nextFloat() * 0.2F, 0.9F + randomsource.nextFloat() * 0.15F, false); ++ if (random.nextInt(200) == 0) { ++ level.playLocalSound((double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), SoundEvents.LAVA_AMBIENT, SoundSource.BLOCKS, 0.2F + random.nextFloat() * 0.2F, 0.9F + random.nextFloat() * 0.15F, false); + } + } + + } + + @Override +- @Override +- public void randomTick(Level level, BlockPos blockpos, FluidState fluidstate, RandomSource randomsource) { ++ public void randomTick(Level level, BlockPos pos, FluidState state, RandomSource random) { + if (level.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) { +- int i = randomsource.nextInt(3); ++ int i = random.nextInt(3); + + if (i > 0) { +- BlockPos blockpos1 = blockpos; ++ BlockPos blockposition1 = pos; + + for (int j = 0; j < i; ++j) { +- blockpos1 = blockpos1.offset(randomsource.nextInt(3) - 1, 1, randomsource.nextInt(3) - 1); +- if (!level.isLoaded(blockpos1)) { ++ blockposition1 = blockposition1.offset(random.nextInt(3) - 1, 1, random.nextInt(3) - 1); ++ if (!level.isLoaded(blockposition1)) { + return; + } + +- BlockState blockstate = level.getBlockState(blockpos1); ++ IBlockData iblockdata = level.getBlockState(blockposition1); + +- if (blockstate.isAir()) { +- if (this.hasFlammableNeighbours(level, blockpos1)) { +- level.setBlockAndUpdate(blockpos1, BaseFireBlock.getState(level, blockpos1)); ++ if (iblockdata.isAir()) { ++ if (this.hasFlammableNeighbours(level, blockposition1)) { ++ // CraftBukkit start - Prevent lava putting something on fire ++ if (level.getBlockState(blockposition1).getBlock() != Blocks.FIRE) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, blockposition1, pos).isCancelled()) { ++ continue; ++ } ++ } ++ // CraftBukkit end ++ level.setBlockAndUpdate(blockposition1, BaseFireBlock.getState(level, blockposition1)); + return; + } +- } else if (blockstate.blocksMotion()) { ++ } else if (iblockdata.blocksMotion()) { + return; + } + } + } else { + for (int k = 0; k < 3; ++k) { +- BlockPos blockpos2 = blockpos.offset(randomsource.nextInt(3) - 1, 0, randomsource.nextInt(3) - 1); ++ BlockPos blockposition2 = pos.offset(random.nextInt(3) - 1, 0, random.nextInt(3) - 1); + +- if (!level.isLoaded(blockpos2)) { ++ if (!level.isLoaded(blockposition2)) { + return; + } + +- if (level.isEmptyBlock(blockpos2.above()) && this.isFlammable(level, blockpos2)) { +- level.setBlockAndUpdate(blockpos2.above(), BaseFireBlock.getState(level, blockpos2)); ++ if (level.isEmptyBlock(blockposition2.above()) && this.isFlammable(level, blockposition2)) { ++ // CraftBukkit start - Prevent lava putting something on fire ++ BlockPos up = blockposition2.above(); ++ if (level.getBlockState(up).getBlock() != Blocks.FIRE) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, up, pos).isCancelled()) { ++ continue; ++ } ++ } ++ // CraftBukkit end ++ level.setBlockAndUpdate(blockposition2.above(), BaseFireBlock.getState(level, blockposition2)); + } + } + } +@@ -113,14 +123,14 @@ + } + } + +- private boolean hasFlammableNeighbours(LevelReader levelreader, BlockPos blockpos) { +- Direction[] adirection = Direction.values(); +- int i = adirection.length; ++ private boolean hasFlammableNeighbours(LevelReader level, BlockPos pos) { ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction = adirection[j]; ++ Direction enumdirection = aenumdirection[j]; + +- if (this.isFlammable(levelreader, blockpos.relative(direction))) { ++ if (this.isFlammable(level, pos.relative(enumdirection))) { + return true; + } + } +@@ -128,114 +138,104 @@ + return false; + } + +- private boolean isFlammable(LevelReader levelreader, BlockPos blockpos) { +- return blockpos.getY() >= levelreader.getMinBuildHeight() && blockpos.getY() < levelreader.getMaxBuildHeight() && !levelreader.hasChunkAt(blockpos) ? false : levelreader.getBlockState(blockpos).ignitedByLava(); ++ private boolean isFlammable(LevelReader level, BlockPos pos) { ++ return pos.getY() >= level.getMinBuildHeight() && pos.getY() < level.getMaxBuildHeight() && !level.hasChunkAt(pos) ? false : level.getBlockState(pos).ignitedByLava(); + } + + @Nullable + @Override +- @Override + public ParticleOptions getDripParticle() { + return ParticleTypes.DRIPPING_LAVA; + } + + @Override +- @Override +- protected void beforeDestroyingBlock(LevelAccessor levelaccessor, BlockPos blockpos, BlockState blockstate) { +- this.fizz(levelaccessor, blockpos); ++ protected void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, IBlockData state) { ++ this.fizz(level, pos); + } + + @Override +- @Override +- public int getSlopeFindDistance(LevelReader levelreader) { +- return levelreader.dimensionType().ultraWarm() ? 4 : 2; ++ public int getSlopeFindDistance(LevelReader level) { ++ return level.dimensionType().ultraWarm() ? 4 : 2; + } + + @Override +- @Override +- public BlockState createLegacyBlock(FluidState fluidstate) { +- return (BlockState) Blocks.LAVA.defaultBlockState().setValue(LiquidBlock.LEVEL, getLegacyLevel(fluidstate)); ++ public IBlockData createLegacyBlock(FluidState state) { ++ return (IBlockData) Blocks.LAVA.defaultBlockState().setValue(LiquidBlock.LEVEL, getLegacyLevel(state)); + } + + @Override +- @Override + public boolean isSame(Fluid fluid) { + return fluid == Fluids.LAVA || fluid == Fluids.FLOWING_LAVA; + } + + @Override +- @Override +- public int getDropOff(LevelReader levelreader) { +- return levelreader.dimensionType().ultraWarm() ? 1 : 2; ++ public int getDropOff(LevelReader level) { ++ return level.dimensionType().ultraWarm() ? 1 : 2; + } + + @Override +- @Override +- public boolean canBeReplacedWith(FluidState fluidstate, BlockGetter blockgetter, BlockPos blockpos, Fluid fluid, Direction direction) { +- return fluidstate.getHeight(blockgetter, blockpos) >= 0.44444445F && fluid.is(FluidTags.WATER); ++ public boolean canBeReplacedWith(FluidState fluidState, BlockGetter blockReader, BlockPos pos, Fluid fluid, Direction direction) { ++ return fluidState.getHeight(blockReader, pos) >= 0.44444445F && fluid.is(FluidTags.WATER); + } + + @Override +- @Override +- public int getTickDelay(LevelReader levelreader) { +- return levelreader.dimensionType().ultraWarm() ? 10 : 30; ++ public int getTickDelay(LevelReader level) { ++ return level.dimensionType().ultraWarm() ? 10 : 30; + } + + @Override +- @Override +- public int getSpreadDelay(Level level, BlockPos blockpos, FluidState fluidstate, FluidState fluidstate1) { ++ public int getSpreadDelay(Level level, BlockPos pos, FluidState currentState, FluidState newState) { + int i = this.getTickDelay(level); + +- if (!fluidstate.isEmpty() && !fluidstate1.isEmpty() && !(Boolean) fluidstate.getValue(LavaFluid.FALLING) && !(Boolean) fluidstate1.getValue(LavaFluid.FALLING) && fluidstate1.getHeight(level, blockpos) > fluidstate.getHeight(level, blockpos) && level.getRandom().nextInt(4) != 0) { ++ if (!currentState.isEmpty() && !newState.isEmpty() && !(Boolean) currentState.getValue(LavaFluid.FALLING) && !(Boolean) newState.getValue(LavaFluid.FALLING) && newState.getHeight(level, pos) > currentState.getHeight(level, pos) && level.getRandom().nextInt(4) != 0) { + i *= 4; + } + + return i; + } + +- private void fizz(LevelAccessor levelaccessor, BlockPos blockpos) { +- levelaccessor.levelEvent(1501, blockpos, 0); ++ private void fizz(LevelAccessor level, BlockPos pos) { ++ level.levelEvent(1501, pos, 0); + } + + @Override +- @Override + protected boolean canConvertToSource(Level level) { + return level.getGameRules().getBoolean(GameRules.RULE_LAVA_SOURCE_CONVERSION); + } + + @Override +- @Override +- protected void spreadTo(LevelAccessor levelaccessor, BlockPos blockpos, BlockState blockstate, Direction direction, FluidState fluidstate) { ++ protected void spreadTo(LevelAccessor level, BlockPos pos, IBlockData blockState, Direction direction, FluidState fluidState) { + if (direction == Direction.DOWN) { +- FluidState fluidstate1 = levelaccessor.getFluidState(blockpos); ++ FluidState fluid1 = level.getFluidState(pos); + +- if (this.is(FluidTags.LAVA) && fluidstate1.is(FluidTags.WATER)) { +- if (blockstate.getBlock() instanceof LiquidBlock) { +- levelaccessor.setBlock(blockpos, Blocks.STONE.defaultBlockState(), 3); ++ if (this.is(FluidTags.LAVA) && fluid1.is(FluidTags.WATER)) { ++ if (blockState.getBlock() instanceof LiquidBlock) { ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level.getMinecraftWorld(), pos, Blocks.STONE.defaultBlockState(), 3)) { ++ return; ++ } ++ // CraftBukkit end + } + +- this.fizz(levelaccessor, blockpos); ++ this.fizz(level, pos); + return; + } + } + +- super.spreadTo(levelaccessor, blockpos, blockstate, direction, fluidstate); ++ super.spreadTo(level, pos, blockState, direction, fluidState); + } + + @Override +- @Override + protected boolean isRandomlyTicking() { + return true; + } + + @Override +- @Override + protected float getExplosionResistance() { + return 100.0F; + } + + @Override +- @Override + public Optional getPickupSound() { + return Optional.of(SoundEvents.BUCKET_FILL_LAVA); + } +@@ -245,21 +245,18 @@ + public Flowing() {} + + @Override +- @Override +- protected void createFluidStateDefinition(StateDefinition.Builder statedefinition_builder) { +- super.createFluidStateDefinition(statedefinition_builder); +- statedefinition_builder.add(LavaFluid.Flowing.LEVEL); ++ protected void createFluidStateDefinition(StateDefinition.Builder builder) { ++ super.createFluidStateDefinition(builder); ++ builder.add(LavaFluid.Flowing.LEVEL); + } + + @Override +- @Override +- public int getAmount(FluidState fluidstate) { +- return (Integer) fluidstate.getValue(LavaFluid.Flowing.LEVEL); ++ public int getAmount(FluidState state) { ++ return (Integer) state.getValue(LavaFluid.Flowing.LEVEL); + } + + @Override +- @Override +- public boolean isSource(FluidState fluidstate) { ++ public boolean isSource(FluidState state) { + return false; + } + } +@@ -269,14 +266,12 @@ + public Source() {} + + @Override +- @Override +- public int getAmount(FluidState fluidstate) { ++ public int getAmount(FluidState state) { + return 8; + } + + @Override +- @Override +- public boolean isSource(FluidState fluidstate) { ++ public boolean isSource(FluidState state) { + return true; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/portal/PortalForcer.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/portal/PortalForcer.java.patch new file mode 100644 index 0000000000..527aa8811d --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/portal/PortalForcer.java.patch @@ -0,0 +1,259 @@ +--- a/net/minecraft/world/level/portal/PortalForcer.java ++++ b/net/minecraft/world/level/portal/PortalForcer.java +@@ -15,7 +15,7 @@ + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.NetherPortalBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.border.WorldBorder; + import net.minecraft.world.level.levelgen.Heightmap; +@@ -37,67 +37,79 @@ + private static final int NOTHING_FOUND = -1; + private final ServerLevel level; + +- public PortalForcer(ServerLevel serverlevel) { +- this.level = serverlevel; ++ public PortalForcer(ServerLevel level) { ++ this.level = level; + } + +- public Optional findPortalAround(BlockPos blockpos, boolean flag, WorldBorder worldborder) { +- PoiManager poimanager = this.level.getPoiManager(); +- int i = flag ? 16 : 128; ++ public Optional findPortalAround(BlockPos pos, boolean isNether, WorldBorder worldBorder) { ++ // CraftBukkit start ++ return findPortalAround(pos, worldBorder, isNether ? 16 : 128); // Search Radius ++ } + +- poimanager.ensureLoadedAndValid(this.level, blockpos, i); +- Optional optional = poimanager.getInSquare((holder) -> { ++ public Optional findPortalAround(BlockPos blockposition, WorldBorder worldborder, int i) { ++ PoiManager villageplace = this.level.getPoiManager(); ++ // int i = flag ? 16 : 128; ++ // CraftBukkit end ++ ++ villageplace.ensureLoadedAndValid(this.level, blockposition, i); ++ Optional optional = villageplace.getInSquare((holder) -> { + return holder.is(PoiTypes.NETHER_PORTAL); +- }, blockpos, i, PoiManager.Occupancy.ANY).filter((poirecord) -> { +- return worldborder.isWithinBounds(poirecord.getPos()); +- }).sorted(Comparator.comparingDouble((poirecord) -> { +- return poirecord.getPos().distSqr(blockpos); +- }).thenComparingInt((poirecord) -> { +- return poirecord.getPos().getY(); +- })).filter((poirecord) -> { +- return this.level.getBlockState(poirecord.getPos()).hasProperty(BlockStateProperties.HORIZONTAL_AXIS); ++ }, blockposition, i, PoiManager.Occupancy.ANY).filter((villageplacerecord) -> { ++ return worldborder.isWithinBounds(villageplacerecord.getPos()); ++ }).sorted(Comparator.comparingDouble((PoiRecord villageplacerecord) -> { // CraftBukkit - decompile error ++ return villageplacerecord.getPos().distSqr(blockposition); ++ }).thenComparingInt((villageplacerecord) -> { ++ return villageplacerecord.getPos().getY(); ++ })).filter((villageplacerecord) -> { ++ return this.level.getBlockState(villageplacerecord.getPos()).hasProperty(BlockStateProperties.HORIZONTAL_AXIS); + }).findFirst(); + +- return optional.map((poirecord) -> { +- BlockPos blockpos1 = poirecord.getPos(); ++ return optional.map((villageplacerecord) -> { ++ BlockPos blockposition1 = villageplacerecord.getPos(); + +- this.level.getChunkSource().addRegionTicket(TicketType.PORTAL, new ChunkPos(blockpos1), 3, blockpos1); +- BlockState blockstate = this.level.getBlockState(blockpos1); ++ this.level.getChunkSource().addRegionTicket(TicketType.PORTAL, new ChunkPos(blockposition1), 3, blockposition1); ++ IBlockData iblockdata = this.level.getBlockState(blockposition1); + +- return BlockUtil.getLargestRectangleAround(blockpos1, (Direction.Axis) blockstate.getValue(BlockStateProperties.HORIZONTAL_AXIS), 21, Direction.Axis.Y, 21, (blockpos2) -> { +- return this.level.getBlockState(blockpos2) == blockstate; ++ return BlockUtil.getLargestRectangleAround(blockposition1, (Direction.Axis) iblockdata.getValue(BlockStateProperties.HORIZONTAL_AXIS), 21, Direction.Axis.Y, 21, (blockposition2) -> { ++ return this.level.getBlockState(blockposition2) == iblockdata; + }); + }); + } + +- public Optional createPortal(BlockPos blockpos, Direction.Axis direction_axis) { +- Direction direction = Direction.get(Direction.AxisDirection.POSITIVE, direction_axis); ++ public Optional createPortal(BlockPos pos, Direction.Axis axis) { ++ // CraftBukkit start ++ return this.createPortal(pos, axis, null, 16); ++ } ++ ++ public Optional createPortal(BlockPos blockposition, Direction.Axis enumdirection_enumaxis, net.minecraft.world.entity.Entity entity, int createRadius) { ++ // CraftBukkit end ++ Direction enumdirection = Direction.get(Direction.AxisDirection.POSITIVE, enumdirection_enumaxis); + double d0 = -1.0D; +- BlockPos blockpos1 = null; ++ BlockPos blockposition1 = null; + double d1 = -1.0D; +- BlockPos blockpos2 = null; ++ BlockPos blockposition2 = null; + WorldBorder worldborder = this.level.getWorldBorder(); + int i = Math.min(this.level.getMaxBuildHeight(), this.level.getMinBuildHeight() + this.level.getLogicalHeight()) - 1; +- BlockPos.MutableBlockPos blockpos_mutableblockpos = blockpos.mutable(); +- Iterator iterator = BlockPos.spiralAround(blockpos, 16, Direction.EAST, Direction.SOUTH).iterator(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = blockposition.mutable(); ++ Iterator iterator = BlockPos.spiralAround(blockposition, createRadius, Direction.EAST, Direction.SOUTH).iterator(); // CraftBukkit + + int j; + int k; + int l; + + while (iterator.hasNext()) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos1 = (BlockPos.MutableBlockPos) iterator.next(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition1 = (BlockPos.MutableBlockPos) iterator.next(); + +- j = Math.min(i, this.level.getHeight(Heightmap.Types.MOTION_BLOCKING, blockpos_mutableblockpos1.getX(), blockpos_mutableblockpos1.getZ())); ++ j = Math.min(i, this.level.getHeight(Heightmap.Types.MOTION_BLOCKING, blockposition_mutableblockposition1.getX(), blockposition_mutableblockposition1.getZ())); + boolean flag = true; + +- if (worldborder.isWithinBounds((BlockPos) blockpos_mutableblockpos1) && worldborder.isWithinBounds((BlockPos) blockpos_mutableblockpos1.move(direction, 1))) { +- blockpos_mutableblockpos1.move(direction.getOpposite(), 1); ++ if (worldborder.isWithinBounds((BlockPos) blockposition_mutableblockposition1) && worldborder.isWithinBounds((BlockPos) blockposition_mutableblockposition1.move(enumdirection, 1))) { ++ blockposition_mutableblockposition1.move(enumdirection.getOpposite(), 1); + + for (k = j; k >= this.level.getMinBuildHeight(); --k) { +- blockpos_mutableblockpos1.setY(k); +- if (this.canPortalReplaceBlock(blockpos_mutableblockpos1)) { +- for (l = k; k > this.level.getMinBuildHeight() && this.canPortalReplaceBlock(blockpos_mutableblockpos1.move(Direction.DOWN)); --k) { ++ blockposition_mutableblockposition1.setY(k); ++ if (this.canPortalReplaceBlock(blockposition_mutableblockposition1)) { ++ for (l = k; k > this.level.getMinBuildHeight() && this.canPortalReplaceBlock(blockposition_mutableblockposition1.move(Direction.DOWN)); --k) { + ; + } + +@@ -105,18 +117,18 @@ + int i1 = l - k; + + if (i1 <= 0 || i1 >= 3) { +- blockpos_mutableblockpos1.setY(k); +- if (this.canHostFrame(blockpos_mutableblockpos1, blockpos_mutableblockpos, direction, 0)) { +- double d2 = blockpos.distSqr(blockpos_mutableblockpos1); ++ blockposition_mutableblockposition1.setY(k); ++ if (this.canHostFrame(blockposition_mutableblockposition1, blockposition_mutableblockposition, enumdirection, 0)) { ++ double d2 = blockposition.distSqr(blockposition_mutableblockposition1); + +- if (this.canHostFrame(blockpos_mutableblockpos1, blockpos_mutableblockpos, direction, -1) && this.canHostFrame(blockpos_mutableblockpos1, blockpos_mutableblockpos, direction, 1) && (d0 == -1.0D || d0 > d2)) { ++ if (this.canHostFrame(blockposition_mutableblockposition1, blockposition_mutableblockposition, enumdirection, -1) && this.canHostFrame(blockposition_mutableblockposition1, blockposition_mutableblockposition, enumdirection, 1) && (d0 == -1.0D || d0 > d2)) { + d0 = d2; +- blockpos1 = blockpos_mutableblockpos1.immutable(); ++ blockposition1 = blockposition_mutableblockposition1.immutable(); + } + + if (d0 == -1.0D && (d1 == -1.0D || d1 > d2)) { + d1 = d2; +- blockpos2 = blockpos_mutableblockpos1.immutable(); ++ blockposition2 = blockposition_mutableblockposition1.immutable(); + } + } + } +@@ -127,13 +139,14 @@ + } + + if (d0 == -1.0D && d1 != -1.0D) { +- blockpos1 = blockpos2; ++ blockposition1 = blockposition2; + d0 = d1; + } + + int j1; + int k1; + ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(this.level); // CraftBukkit - Use BlockStateListPopulator + if (d0 == -1.0D) { + j1 = Math.max(this.level.getMinBuildHeight() - -1, 70); + k1 = i - 9; +@@ -141,20 +154,20 @@ + return Optional.empty(); + } + +- blockpos1 = (new BlockPos(blockpos.getX(), Mth.clamp(blockpos.getY(), j1, k1), blockpos.getZ())).immutable(); +- Direction direction1 = direction.getClockWise(); ++ blockposition1 = (new BlockPos(blockposition.getX(), Mth.clamp(blockposition.getY(), j1, k1), blockposition.getZ())).immutable(); ++ Direction enumdirection1 = enumdirection.getClockWise(); + +- if (!worldborder.isWithinBounds(blockpos1)) { ++ if (!worldborder.isWithinBounds(blockposition1)) { + return Optional.empty(); + } + + for (int l1 = -1; l1 < 2; ++l1) { + for (k = 0; k < 2; ++k) { + for (l = -1; l < 3; ++l) { +- BlockState blockstate = l < 0 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); ++ IBlockData iblockdata = l < 0 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); + +- blockpos_mutableblockpos.setWithOffset(blockpos1, k * direction.getStepX() + l1 * direction1.getStepX(), l, k * direction.getStepZ() + l1 * direction1.getStepZ()); +- this.level.setBlockAndUpdate(blockpos_mutableblockpos, blockstate); ++ blockposition_mutableblockposition.setWithOffset(blockposition1, k * enumdirection.getStepX() + l1 * enumdirection1.getStepX(), l, k * enumdirection.getStepZ() + l1 * enumdirection1.getStepZ()); ++ blockList.setBlock(blockposition_mutableblockposition, iblockdata, 3); // CraftBukkit + } + } + } +@@ -163,41 +176,51 @@ + for (j1 = -1; j1 < 3; ++j1) { + for (k1 = -1; k1 < 4; ++k1) { + if (j1 == -1 || j1 == 2 || k1 == -1 || k1 == 3) { +- blockpos_mutableblockpos.setWithOffset(blockpos1, j1 * direction.getStepX(), k1, j1 * direction.getStepZ()); +- this.level.setBlock(blockpos_mutableblockpos, Blocks.OBSIDIAN.defaultBlockState(), 3); ++ blockposition_mutableblockposition.setWithOffset(blockposition1, j1 * enumdirection.getStepX(), k1, j1 * enumdirection.getStepZ()); ++ blockList.setBlock(blockposition_mutableblockposition, Blocks.OBSIDIAN.defaultBlockState(), 3); // CraftBukkit + } + } + } + +- BlockState blockstate1 = (BlockState) Blocks.NETHER_PORTAL.defaultBlockState().setValue(NetherPortalBlock.AXIS, direction_axis); ++ IBlockData iblockdata1 = (IBlockData) Blocks.NETHER_PORTAL.defaultBlockState().setValue(NetherPortalBlock.AXIS, enumdirection_enumaxis); + + for (k1 = 0; k1 < 2; ++k1) { + for (j = 0; j < 3; ++j) { +- blockpos_mutableblockpos.setWithOffset(blockpos1, k1 * direction.getStepX(), j, k1 * direction.getStepZ()); +- this.level.setBlock(blockpos_mutableblockpos, blockstate1, 18); ++ blockposition_mutableblockposition.setWithOffset(blockposition1, k1 * enumdirection.getStepX(), j, k1 * enumdirection.getStepZ()); ++ blockList.setBlock(blockposition_mutableblockposition, iblockdata1, 18); // CraftBukkit + } + } + +- return Optional.of(new BlockUtil.FoundRectangle(blockpos1.immutable(), 2, 3)); ++ // CraftBukkit start ++ org.bukkit.World bworld = this.level.getWorld(); ++ org.bukkit.event.world.PortalCreateEvent event = new org.bukkit.event.world.PortalCreateEvent((java.util.List) (java.util.List) blockList.getList(), bworld, (entity == null) ? null : entity.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.NETHER_PAIR); ++ ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return Optional.empty(); ++ } ++ blockList.updateList(); ++ // CraftBukkit end ++ return Optional.of(new BlockUtil.FoundRectangle(blockposition1.immutable(), 2, 3)); + } + +- private boolean canPortalReplaceBlock(BlockPos.MutableBlockPos blockpos_mutableblockpos) { +- BlockState blockstate = this.level.getBlockState(blockpos_mutableblockpos); ++ private boolean canPortalReplaceBlock(BlockPos.MutableBlockPos pos) { ++ IBlockData iblockdata = this.level.getBlockState(pos); + +- return blockstate.canBeReplaced() && blockstate.getFluidState().isEmpty(); ++ return iblockdata.canBeReplaced() && iblockdata.getFluidState().isEmpty(); + } + +- private boolean canHostFrame(BlockPos blockpos, BlockPos.MutableBlockPos blockpos_mutableblockpos, Direction direction, int i) { +- Direction direction1 = direction.getClockWise(); ++ private boolean canHostFrame(BlockPos originalPos, BlockPos.MutableBlockPos offsetPos, Direction direction, int offsetScale) { ++ Direction enumdirection1 = direction.getClockWise(); + + for (int j = -1; j < 3; ++j) { + for (int k = -1; k < 4; ++k) { +- blockpos_mutableblockpos.setWithOffset(blockpos, direction.getStepX() * j + direction1.getStepX() * i, k, direction.getStepZ() * j + direction1.getStepZ() * i); +- if (k < 0 && !this.level.getBlockState(blockpos_mutableblockpos).isSolid()) { ++ offsetPos.setWithOffset(originalPos, direction.getStepX() * j + enumdirection1.getStepX() * offsetScale, k, direction.getStepZ() * j + enumdirection1.getStepZ() * offsetScale); ++ if (k < 0 && !this.level.getBlockState(offsetPos).isSolid()) { + return false; + } + +- if (k >= 0 && !this.canPortalReplaceBlock(blockpos_mutableblockpos)) { ++ if (k >= 0 && !this.canPortalReplaceBlock(offsetPos)) { + return false; + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/portal/PortalInfo.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/portal/PortalInfo.java.patch new file mode 100644 index 0000000000..fca3955e2c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/portal/PortalInfo.java.patch @@ -0,0 +1,32 @@ +--- a/net/minecraft/world/level/portal/PortalInfo.java ++++ b/net/minecraft/world/level/portal/PortalInfo.java +@@ -1,6 +1,9 @@ + package net.minecraft.world.level.portal; + ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.event.CraftPortalEvent; ++// CraftBukkit end + + public class PortalInfo { + +@@ -8,10 +11,16 @@ + public final Vec3 speed; + public final float yRot; + public final float xRot; ++ // CraftBukkit start ++ public final ServerLevel world; ++ public final CraftPortalEvent portalEventInfo; + +- public PortalInfo(Vec3 vec3, Vec3 vec31, float f, float f1) { +- this.pos = vec3; +- this.speed = vec31; ++ public PortalInfo(Vec3 vec3d, Vec3 vec3d1, float f, float f1, ServerLevel world, CraftPortalEvent portalEventInfo) { ++ this.world = world; ++ this.portalEventInfo = portalEventInfo; ++ // CraftBukkit end ++ this.pos = vec3d; ++ this.speed = vec3d1; + this.yRot = f; + this.xRot = f1; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/portal/PortalShape.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/portal/PortalShape.java.patch new file mode 100644 index 0000000000..a589fddbcf --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/portal/PortalShape.java.patch @@ -0,0 +1,350 @@ +--- a/net/minecraft/world/level/portal/PortalShape.java ++++ b/net/minecraft/world/level/portal/PortalShape.java +@@ -15,12 +15,16 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.NetherPortalBlock; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftPortalEvent; ++import org.bukkit.event.world.PortalCreateEvent; ++// CraftBukkit end + + public class PortalShape { + +@@ -28,8 +32,8 @@ + public static final int MAX_WIDTH = 21; + private static final int MIN_HEIGHT = 3; + public static final int MAX_HEIGHT = 21; +- private static final BlockBehaviour.StatePredicate FRAME = (blockstate, blockgetter, blockpos) -> { +- return blockstate.is(Blocks.OBSIDIAN); ++ private static final BlockBehaviour.StatePredicate FRAME = (iblockdata, iblockaccess, blockposition) -> { ++ return iblockdata.is(Blocks.OBSIDIAN); + }; + private static final float SAFE_TRAVEL_MAX_ENTITY_XY = 4.0F; + private static final double SAFE_TRAVEL_MAX_VERTICAL_DELTA = 1.0D; +@@ -41,32 +45,34 @@ + private BlockPos bottomLeft; + private int height; + private final int width; ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blocks; // CraftBukkit - add field + +- public static Optional findEmptyPortalShape(LevelAccessor levelaccessor, BlockPos blockpos, Direction.Axis direction_axis) { +- return findPortalShape(levelaccessor, blockpos, (portalshape) -> { +- return portalshape.isValid() && portalshape.numPortalBlocks == 0; +- }, direction_axis); ++ public static Optional findEmptyPortalShape(LevelAccessor level, BlockPos bottomLeft, Direction.Axis axis) { ++ return findPortalShape(level, bottomLeft, (blockportalshape) -> { ++ return blockportalshape.isValid() && blockportalshape.numPortalBlocks == 0; ++ }, axis); + } + +- public static Optional findPortalShape(LevelAccessor levelaccessor, BlockPos blockpos, Predicate predicate, Direction.Axis direction_axis) { +- Optional optional = Optional.of(new PortalShape(levelaccessor, blockpos, direction_axis)).filter(predicate); ++ public static Optional findPortalShape(LevelAccessor level, BlockPos bottomLeft, Predicate predicate, Direction.Axis axis) { ++ Optional optional = Optional.of(new PortalShape(level, bottomLeft, axis)).filter(predicate); + + if (optional.isPresent()) { + return optional; + } else { +- Direction.Axis direction_axis1 = direction_axis == Direction.Axis.X ? Direction.Axis.Z : Direction.Axis.X; ++ Direction.Axis enumdirection_enumaxis1 = axis == Direction.Axis.X ? Direction.Axis.Z : Direction.Axis.X; + +- return Optional.of(new PortalShape(levelaccessor, blockpos, direction_axis1)).filter(predicate); ++ return Optional.of(new PortalShape(level, bottomLeft, enumdirection_enumaxis1)).filter(predicate); + } + } + +- public PortalShape(LevelAccessor levelaccessor, BlockPos blockpos, Direction.Axis direction_axis) { +- this.level = levelaccessor; +- this.axis = direction_axis; +- this.rightDir = direction_axis == Direction.Axis.X ? Direction.WEST : Direction.SOUTH; +- this.bottomLeft = this.calculateBottomLeft(blockpos); ++ public PortalShape(LevelAccessor level, BlockPos bottomLeft, Direction.Axis axis) { ++ blocks = new org.bukkit.craftbukkit.util.BlockStateListPopulator(level.getMinecraftWorld()); // CraftBukkit ++ this.level = level; ++ this.axis = axis; ++ this.rightDir = axis == Direction.Axis.X ? Direction.WEST : Direction.SOUTH; ++ this.bottomLeft = this.calculateBottomLeft(bottomLeft); + if (this.bottomLeft == null) { +- this.bottomLeft = blockpos; ++ this.bottomLeft = bottomLeft; + this.width = 1; + this.height = 1; + } else { +@@ -79,15 +85,15 @@ + } + + @Nullable +- private BlockPos calculateBottomLeft(BlockPos blockpos) { +- for (int i = Math.max(this.level.getMinBuildHeight(), blockpos.getY() - 21); blockpos.getY() > i && isEmpty(this.level.getBlockState(blockpos.below())); blockpos = blockpos.below()) { ++ private BlockPos calculateBottomLeft(BlockPos pos) { ++ for (int i = Math.max(this.level.getMinBuildHeight(), pos.getY() - 21); pos.getY() > i && isEmpty(this.level.getBlockState(pos.below())); pos = pos.below()) { + ; + } + +- Direction direction = this.rightDir.getOpposite(); +- int j = this.getDistanceUntilEdgeAboveFrame(blockpos, direction) - 1; ++ Direction enumdirection = this.rightDir.getOpposite(); ++ int j = this.getDistanceUntilEdgeAboveFrame(pos, enumdirection) - 1; + +- return j < 0 ? null : blockpos.relative(direction, j); ++ return j < 0 ? null : pos.relative(enumdirection, j); + } + + private int calculateWidth() { +@@ -96,159 +102,182 @@ + return i >= 2 && i <= 21 ? i : 0; + } + +- private int getDistanceUntilEdgeAboveFrame(BlockPos blockpos, Direction direction) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); ++ private int getDistanceUntilEdgeAboveFrame(BlockPos pos, Direction direction) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + + for (int i = 0; i <= 21; ++i) { +- blockpos_mutableblockpos.set(blockpos).move(direction, i); +- BlockState blockstate = this.level.getBlockState(blockpos_mutableblockpos); ++ blockposition_mutableblockposition.set(pos).move(direction, i); ++ IBlockData iblockdata = this.level.getBlockState(blockposition_mutableblockposition); + +- if (!isEmpty(blockstate)) { +- if (PortalShape.FRAME.test(blockstate, this.level, blockpos_mutableblockpos)) { ++ if (!isEmpty(iblockdata)) { ++ if (PortalShape.FRAME.test(iblockdata, this.level, blockposition_mutableblockposition)) { ++ blocks.setBlock(blockposition_mutableblockposition, iblockdata, 18); // CraftBukkit - lower left / right + return i; + } + break; + } + +- BlockState blockstate1 = this.level.getBlockState(blockpos_mutableblockpos.move(Direction.DOWN)); ++ IBlockData iblockdata1 = this.level.getBlockState(blockposition_mutableblockposition.move(Direction.DOWN)); + +- if (!PortalShape.FRAME.test(blockstate1, this.level, blockpos_mutableblockpos)) { ++ if (!PortalShape.FRAME.test(iblockdata1, this.level, blockposition_mutableblockposition)) { + break; + } ++ blocks.setBlock(blockposition_mutableblockposition, iblockdata1, 18); // CraftBukkit - bottom row + } + + return 0; + } + + private int calculateHeight() { +- BlockPos.MutableBlockPos blockpos_mutableblockpos = new BlockPos.MutableBlockPos(); +- int i = this.getDistanceUntilTop(blockpos_mutableblockpos); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ int i = this.getDistanceUntilTop(blockposition_mutableblockposition); + +- return i >= 3 && i <= 21 && this.hasTopFrame(blockpos_mutableblockpos, i) ? i : 0; ++ return i >= 3 && i <= 21 && this.hasTopFrame(blockposition_mutableblockposition, i) ? i : 0; + } + +- private boolean hasTopFrame(BlockPos.MutableBlockPos blockpos_mutableblockpos, int i) { ++ private boolean hasTopFrame(BlockPos.MutableBlockPos pos, int distanceToTop) { + for (int j = 0; j < this.width; ++j) { +- BlockPos.MutableBlockPos blockpos_mutableblockpos1 = blockpos_mutableblockpos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, j); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition1 = pos.set(this.bottomLeft).move(Direction.UP, distanceToTop).move(this.rightDir, j); + +- if (!PortalShape.FRAME.test(this.level.getBlockState(blockpos_mutableblockpos1), this.level, blockpos_mutableblockpos1)) { ++ if (!PortalShape.FRAME.test(this.level.getBlockState(blockposition_mutableblockposition1), this.level, blockposition_mutableblockposition1)) { + return false; + } ++ blocks.setBlock(blockposition_mutableblockposition1, this.level.getBlockState(blockposition_mutableblockposition1), 18); // CraftBukkit - upper row + } + + return true; + } + +- private int getDistanceUntilTop(BlockPos.MutableBlockPos blockpos_mutableblockpos) { ++ private int getDistanceUntilTop(BlockPos.MutableBlockPos pos) { + for (int i = 0; i < 21; ++i) { +- blockpos_mutableblockpos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, -1); +- if (!PortalShape.FRAME.test(this.level.getBlockState(blockpos_mutableblockpos), this.level, blockpos_mutableblockpos)) { ++ pos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, -1); ++ if (!PortalShape.FRAME.test(this.level.getBlockState(pos), this.level, pos)) { + return i; + } + +- blockpos_mutableblockpos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, this.width); +- if (!PortalShape.FRAME.test(this.level.getBlockState(blockpos_mutableblockpos), this.level, blockpos_mutableblockpos)) { ++ pos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, this.width); ++ if (!PortalShape.FRAME.test(this.level.getBlockState(pos), this.level, pos)) { + return i; + } + + for (int j = 0; j < this.width; ++j) { +- blockpos_mutableblockpos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, j); +- BlockState blockstate = this.level.getBlockState(blockpos_mutableblockpos); ++ pos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, j); ++ IBlockData iblockdata = this.level.getBlockState(pos); + +- if (!isEmpty(blockstate)) { ++ if (!isEmpty(iblockdata)) { + return i; + } + +- if (blockstate.is(Blocks.NETHER_PORTAL)) { ++ if (iblockdata.is(Blocks.NETHER_PORTAL)) { + ++this.numPortalBlocks; + } + } ++ // CraftBukkit start - left and right ++ blocks.setBlock(pos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, -1), this.level.getBlockState(pos), 18); ++ blocks.setBlock(pos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, this.width), this.level.getBlockState(pos), 18); ++ // CraftBukkit end + } + + return 21; + } + +- private static boolean isEmpty(BlockState blockstate) { +- return blockstate.isAir() || blockstate.is(BlockTags.FIRE) || blockstate.is(Blocks.NETHER_PORTAL); ++ private static boolean isEmpty(IBlockData state) { ++ return state.isAir() || state.is(BlockTags.FIRE) || state.is(Blocks.NETHER_PORTAL); + } + + public boolean isValid() { + return this.bottomLeft != null && this.width >= 2 && this.width <= 21 && this.height >= 3 && this.height <= 21; + } + +- public void createPortalBlocks() { +- BlockState blockstate = (BlockState) Blocks.NETHER_PORTAL.defaultBlockState().setValue(NetherPortalBlock.AXIS, this.axis); ++ // CraftBukkit start - return boolean ++ public boolean createPortalBlocks() { ++ org.bukkit.World bworld = this.level.getMinecraftWorld().getWorld(); + +- BlockPos.betweenClosed(this.bottomLeft, this.bottomLeft.relative(Direction.UP, this.height - 1).relative(this.rightDir, this.width - 1)).forEach((blockpos) -> { +- this.level.setBlock(blockpos, blockstate, 18); ++ // Copy below for loop ++ IBlockData iblockdata = (IBlockData) Blocks.NETHER_PORTAL.defaultBlockState().setValue(NetherPortalBlock.AXIS, this.axis); ++ ++ BlockPos.betweenClosed(this.bottomLeft, this.bottomLeft.relative(Direction.UP, this.height - 1).relative(this.rightDir, this.width - 1)).forEach((blockposition) -> { ++ blocks.setBlock(blockposition, iblockdata, 18); + }); ++ ++ PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) blocks.getList(), bworld, null, PortalCreateEvent.CreateReason.FIRE); ++ this.level.getMinecraftWorld().getServer().server.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ BlockPos.betweenClosed(this.bottomLeft, this.bottomLeft.relative(Direction.UP, this.height - 1).relative(this.rightDir, this.width - 1)).forEach((blockposition) -> { ++ this.level.setBlock(blockposition, iblockdata, 18); ++ }); ++ return true; // CraftBukkit + } + + public boolean isComplete() { + return this.isValid() && this.numPortalBlocks == this.width * this.height; + } + +- public static Vec3 getRelativePosition(BlockUtil.FoundRectangle blockutil_foundrectangle, Direction.Axis direction_axis, Vec3 vec3, EntityDimensions entitydimensions) { +- double d0 = (double) blockutil_foundrectangle.axis1Size - (double) entitydimensions.width; +- double d1 = (double) blockutil_foundrectangle.axis2Size - (double) entitydimensions.height; +- BlockPos blockpos = blockutil_foundrectangle.minCorner; ++ public static Vec3 getRelativePosition(BlockUtil.FoundRectangle foundRectangle, Direction.Axis axis, Vec3 pos, EntityDimensions entityDimensions) { ++ double d0 = (double) foundRectangle.axis1Size - (double) entityDimensions.width; ++ double d1 = (double) foundRectangle.axis2Size - (double) entityDimensions.height; ++ BlockPos blockposition = foundRectangle.minCorner; + double d2; + double d3; + + if (d0 > 0.0D) { +- d2 = (double) blockpos.get(direction_axis) + (double) entitydimensions.width / 2.0D; +- d3 = Mth.clamp(Mth.inverseLerp(vec3.get(direction_axis) - d2, 0.0D, d0), 0.0D, 1.0D); ++ d2 = (double) blockposition.get(axis) + (double) entityDimensions.width / 2.0D; ++ d3 = Mth.clamp(Mth.inverseLerp(pos.get(axis) - d2, 0.0D, d0), 0.0D, 1.0D); + } else { + d3 = 0.5D; + } + +- Direction.Axis direction_axis1; ++ Direction.Axis enumdirection_enumaxis1; + + if (d1 > 0.0D) { +- direction_axis1 = Direction.Axis.Y; +- d2 = Mth.clamp(Mth.inverseLerp(vec3.get(direction_axis1) - (double) blockpos.get(direction_axis1), 0.0D, d1), 0.0D, 1.0D); ++ enumdirection_enumaxis1 = Direction.Axis.Y; ++ d2 = Mth.clamp(Mth.inverseLerp(pos.get(enumdirection_enumaxis1) - (double) blockposition.get(enumdirection_enumaxis1), 0.0D, d1), 0.0D, 1.0D); + } else { + d2 = 0.0D; + } + +- direction_axis1 = direction_axis == Direction.Axis.X ? Direction.Axis.Z : Direction.Axis.X; +- double d4 = vec3.get(direction_axis1) - ((double) blockpos.get(direction_axis1) + 0.5D); ++ enumdirection_enumaxis1 = axis == Direction.Axis.X ? Direction.Axis.Z : Direction.Axis.X; ++ double d4 = pos.get(enumdirection_enumaxis1) - ((double) blockposition.get(enumdirection_enumaxis1) + 0.5D); + + return new Vec3(d3, d2, d4); + } + +- public static PortalInfo createPortalInfo(ServerLevel serverlevel, BlockUtil.FoundRectangle blockutil_foundrectangle, Direction.Axis direction_axis, Vec3 vec3, Entity entity, Vec3 vec31, float f, float f1) { +- BlockPos blockpos = blockutil_foundrectangle.minCorner; +- BlockState blockstate = serverlevel.getBlockState(blockpos); +- Direction.Axis direction_axis1 = (Direction.Axis) blockstate.getOptionalValue(BlockStateProperties.HORIZONTAL_AXIS).orElse(Direction.Axis.X); +- double d0 = (double) blockutil_foundrectangle.axis1Size; +- double d1 = (double) blockutil_foundrectangle.axis2Size; +- EntityDimensions entitydimensions = entity.getDimensions(entity.getPose()); +- int i = direction_axis == direction_axis1 ? 0 : 90; +- Vec3 vec32 = direction_axis == direction_axis1 ? vec31 : new Vec3(vec31.z, vec31.y, -vec31.x); +- double d2 = (double) entitydimensions.width / 2.0D + (d0 - (double) entitydimensions.width) * vec3.x(); +- double d3 = (d1 - (double) entitydimensions.height) * vec3.y(); +- double d4 = 0.5D + vec3.z(); +- boolean flag = direction_axis1 == Direction.Axis.X; +- Vec3 vec33 = new Vec3((double) blockpos.getX() + (flag ? d2 : d4), (double) blockpos.getY() + d3, (double) blockpos.getZ() + (flag ? d4 : d2)); +- Vec3 vec34 = findCollisionFreePosition(vec33, serverlevel, entity, entitydimensions); ++ public static PortalInfo createPortalInfo(ServerLevel worldserver, BlockUtil.FoundRectangle blockutil_rectangle, Direction.Axis enumdirection_enumaxis, Vec3 vec3d, Entity entity, Vec3 vec3d1, float f, float f1, CraftPortalEvent portalEventInfo) { // CraftBukkit ++ BlockPos blockposition = blockutil_rectangle.minCorner; ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ Direction.Axis enumdirection_enumaxis1 = (Direction.Axis) iblockdata.getOptionalValue(BlockStateProperties.HORIZONTAL_AXIS).orElse(Direction.Axis.X); ++ double d0 = (double) blockutil_rectangle.axis1Size; ++ double d1 = (double) blockutil_rectangle.axis2Size; ++ EntityDimensions entitysize = entity.getDimensions(entity.getPose()); ++ int i = enumdirection_enumaxis == enumdirection_enumaxis1 ? 0 : 90; ++ Vec3 vec3d2 = enumdirection_enumaxis == enumdirection_enumaxis1 ? vec3d1 : new Vec3(vec3d1.z, vec3d1.y, -vec3d1.x); ++ double d2 = (double) entitysize.width / 2.0D + (d0 - (double) entitysize.width) * vec3d.x(); ++ double d3 = (d1 - (double) entitysize.height) * vec3d.y(); ++ double d4 = 0.5D + vec3d.z(); ++ boolean flag = enumdirection_enumaxis1 == Direction.Axis.X; ++ Vec3 vec3d3 = new Vec3((double) blockposition.getX() + (flag ? d2 : d4), (double) blockposition.getY() + d3, (double) blockposition.getZ() + (flag ? d4 : d2)); ++ Vec3 vec3d4 = findCollisionFreePosition(vec3d3, worldserver, entity, entitysize); + +- return new PortalInfo(vec34, vec32, f + (float) i, f1); ++ return new PortalInfo(vec3d4, vec3d2, f + (float) i, f1, worldserver, portalEventInfo); // CraftBukkit + } + +- private static Vec3 findCollisionFreePosition(Vec3 vec3, ServerLevel serverlevel, Entity entity, EntityDimensions entitydimensions) { +- if (entitydimensions.width <= 4.0F && entitydimensions.height <= 4.0F) { +- double d0 = (double) entitydimensions.height / 2.0D; +- Vec3 vec31 = vec3.add(0.0D, d0, 0.0D); +- VoxelShape voxelshape = Shapes.create(AABB.ofSize(vec31, (double) entitydimensions.width, 0.0D, (double) entitydimensions.width).expandTowards(0.0D, 1.0D, 0.0D).inflate(1.0E-6D)); +- Optional optional = serverlevel.findFreePosition(entity, voxelshape, vec31, (double) entitydimensions.width, (double) entitydimensions.height, (double) entitydimensions.width); +- Optional optional1 = optional.map((vec32) -> { +- return vec32.subtract(0.0D, d0, 0.0D); ++ private static Vec3 findCollisionFreePosition(Vec3 pos, ServerLevel level, Entity entity, EntityDimensions dimensions) { ++ if (dimensions.width <= 4.0F && dimensions.height <= 4.0F) { ++ double d0 = (double) dimensions.height / 2.0D; ++ Vec3 vec3d1 = pos.add(0.0D, d0, 0.0D); ++ VoxelShape voxelshape = Shapes.create(AABB.ofSize(vec3d1, (double) dimensions.width, 0.0D, (double) dimensions.width).expandTowards(0.0D, 1.0D, 0.0D).inflate(1.0E-6D)); ++ Optional optional = level.findFreePosition(entity, voxelshape, vec3d1, (double) dimensions.width, (double) dimensions.height, (double) dimensions.width); ++ Optional optional1 = optional.map((vec3d2) -> { ++ return vec3d2.subtract(0.0D, d0, 0.0D); + }); + +- return (Vec3) optional1.orElse(vec3); ++ return (Vec3) optional1.orElse(pos); + } else { +- return vec3; ++ return pos; + } + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/redstone/NeighborUpdater.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/redstone/NeighborUpdater.java.patch new file mode 100644 index 0000000000..4f4d6e55bf --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/redstone/NeighborUpdater.java.patch @@ -0,0 +1,97 @@ +--- a/net/minecraft/world/level/redstone/NeighborUpdater.java ++++ b/net/minecraft/world/level/redstone/NeighborUpdater.java +@@ -8,57 +8,74 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.core.registries.BuiltInRegistries; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.Block; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.event.block.BlockPhysicsEvent; ++// CraftBukkit end + + public interface NeighborUpdater { + + Direction[] UPDATE_ORDER = new Direction[]{Direction.WEST, Direction.EAST, Direction.DOWN, Direction.UP, Direction.NORTH, Direction.SOUTH}; + +- void shapeUpdate(Direction direction, BlockState state, BlockPos pos, BlockPos neighborPos, int flags, int recursionLevel); ++ void shapeUpdate(Direction direction, IBlockData state, BlockPos pos, BlockPos neighborPos, int flags, int recursionLevel); + + void neighborChanged(BlockPos pos, Block neighborBlock, BlockPos neighborPos); + +- void neighborChanged(BlockState state, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston); ++ void neighborChanged(IBlockData state, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston); + +- default void updateNeighborsAtExceptFromFacing(BlockPos blockpos, Block block, @Nullable Direction direction) { +- Direction[] adirection = NeighborUpdater.UPDATE_ORDER; +- int i = adirection.length; ++ default void updateNeighborsAtExceptFromFacing(BlockPos pos, Block block, @Nullable Direction facing) { ++ Direction[] aenumdirection = NeighborUpdater.UPDATE_ORDER; ++ int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { +- Direction direction1 = adirection[j]; ++ Direction enumdirection1 = aenumdirection[j]; + +- if (direction1 != direction) { +- this.neighborChanged(blockpos.relative(direction1), block, blockpos); ++ if (enumdirection1 != facing) { ++ this.neighborChanged(pos.relative(enumdirection1), block, pos); + } + } + + } + +- static void executeShapeUpdate(LevelAccessor levelaccessor, Direction direction, BlockState blockstate, BlockPos blockpos, BlockPos blockpos1, int i, int j) { +- BlockState blockstate1 = levelaccessor.getBlockState(blockpos); +- BlockState blockstate2 = blockstate1.updateShape(direction, blockstate, levelaccessor, blockpos, blockpos1); ++ static void executeShapeUpdate(LevelAccessor level, Direction direction, IBlockData state, BlockPos pos, BlockPos neighborPos, int flags, int recursionLevel) { ++ IBlockData iblockdata1 = level.getBlockState(pos); ++ IBlockData iblockdata2 = iblockdata1.updateShape(direction, state, level, pos, neighborPos); + +- Block.updateOrDestroy(blockstate1, blockstate2, levelaccessor, blockpos, i, j); ++ Block.updateOrDestroy(iblockdata1, iblockdata2, level, pos, flags, recursionLevel); + } + +- static void executeUpdate(Level level, BlockState blockstate, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) { ++ static void executeUpdate(Level level, IBlockData state, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston) { + try { +- blockstate.neighborChanged(level, blockpos, block, blockpos1, flag); ++ // CraftBukkit start ++ CraftWorld cworld = ((ServerLevel) level).getWorld(); ++ if (cworld != null) { ++ BlockPhysicsEvent event = new BlockPhysicsEvent(CraftBlock.at(level, pos), CraftBlockData.fromData(state), CraftBlock.at(level, neighborPos)); ++ ((ServerLevel) level).getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ state.neighborChanged(level, pos, neighborBlock, neighborPos, movedByPiston); + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception while updating neighbours"); +- CrashReportCategory crashreportcategory = crashreport.addCategory("Block being updated"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being updated"); + +- crashreportcategory.setDetail("Source block type", () -> { ++ crashreportsystemdetails.setDetail("Source block type", () -> { + try { +- return String.format(Locale.ROOT, "ID #%s (%s // %s)", BuiltInRegistries.BLOCK.getKey(block), block.getDescriptionId(), block.getClass().getCanonicalName()); ++ return String.format(Locale.ROOT, "ID #%s (%s // %s)", BuiltInRegistries.BLOCK.getKey(neighborBlock), neighborBlock.getDescriptionId(), neighborBlock.getClass().getCanonicalName()); + } catch (Throwable throwable1) { +- return "ID #" + BuiltInRegistries.BLOCK.getKey(block); ++ return "ID #" + BuiltInRegistries.BLOCK.getKey(neighborBlock); + } + }); +- CrashReportCategory.populateBlockDetails(crashreportcategory, level, blockpos, blockstate); ++ CrashReportCategory.populateBlockDetails(crashreportsystemdetails, level, pos, state); + throw new ReportedException(crashreport); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java.patch new file mode 100644 index 0000000000..d60c5999f3 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java.patch @@ -0,0 +1,822 @@ +--- a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java ++++ b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +@@ -15,6 +15,7 @@ + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.Tag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientboundMapItemDataPacket; +@@ -32,6 +33,15 @@ + import net.minecraft.world.level.saveddata.SavedData; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.UUID; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.map.CraftMapView; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++// CraftBukkit end ++ + public class MapItemSavedData extends SavedData { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -39,246 +49,293 @@ + private static final int HALF_MAP_SIZE = 64; + public static final int MAX_SCALE = 4; + public static final int TRACKED_DECORATION_LIMIT = 256; +- public final int centerX; +- public final int centerZ; +- public final ResourceKey dimension; +- private final boolean trackingPosition; +- private final boolean unlimitedTracking; +- public final byte scale; ++ public int centerX; ++ public int centerZ; ++ public ResourceKey dimension; ++ public boolean trackingPosition; ++ public boolean unlimitedTracking; ++ public byte scale; + public byte[] colors = new byte[16384]; +- public final boolean locked; +- private final List carriedBy = Lists.newArrayList(); +- private final Map carriedByPlayers = Maps.newHashMap(); ++ public boolean locked; ++ public final List carriedBy = Lists.newArrayList(); ++ public final Map carriedByPlayers = Maps.newHashMap(); + private final Map bannerMarkers = Maps.newHashMap(); +- final Map decorations = Maps.newLinkedHashMap(); ++ public final Map decorations = Maps.newLinkedHashMap(); + private final Map frameMarkers = Maps.newHashMap(); + private int trackedDecorationCount; + +- public static SavedData.Factory factory() { +- return new SavedData.Factory<>(() -> { ++ // CraftBukkit start ++ public final CraftMapView mapView; ++ private CraftServer server; ++ public UUID uniqueId = null; ++ public String id; ++ // CraftBukkit end ++ ++ public static SavedData.a factory() { ++ return new SavedData.a<>(() -> { + throw new IllegalStateException("Should never create an empty map saved data"); + }, MapItemSavedData::load, DataFixTypes.SAVED_DATA_MAP_DATA); + } + +- private MapItemSavedData(int i, int j, byte b0, boolean flag, boolean flag1, boolean flag2, ResourceKey resourcekey) { +- this.scale = b0; +- this.centerX = i; +- this.centerZ = j; +- this.dimension = resourcekey; +- this.trackingPosition = flag; +- this.unlimitedTracking = flag1; +- this.locked = flag2; ++ private MapItemSavedData(int x, int z, byte scale, boolean trackingPosition, boolean unlimitedTracking, boolean locked, ResourceKey dimension) { ++ this.scale = scale; ++ this.centerX = x; ++ this.centerZ = z; ++ this.dimension = dimension; ++ this.trackingPosition = trackingPosition; ++ this.unlimitedTracking = unlimitedTracking; ++ this.locked = locked; + this.setDirty(); ++ // CraftBukkit start ++ mapView = new CraftMapView(this); ++ server = (CraftServer) org.bukkit.Bukkit.getServer(); ++ // CraftBukkit end + } + +- public static MapItemSavedData createFresh(double d0, double d1, byte b0, boolean flag, boolean flag1, ResourceKey resourcekey) { +- int i = 128 * (1 << b0); +- int j = Mth.floor((d0 + 64.0D) / (double) i); ++ public static MapItemSavedData createFresh(double x, double d1, byte z, boolean flag, boolean scale, ResourceKey trackingPosition) { ++ int i = 128 * (1 << z); ++ int j = Mth.floor((x + 64.0D) / (double) i); + int k = Mth.floor((d1 + 64.0D) / (double) i); + int l = j * i + i / 2 - 64; + int i1 = k * i + i / 2 - 64; + +- return new MapItemSavedData(l, i1, b0, flag, flag1, false, resourcekey); ++ return new MapItemSavedData(l, i1, z, flag, scale, false, trackingPosition); + } + +- public static MapItemSavedData createForClient(byte b0, boolean flag, ResourceKey resourcekey) { +- return new MapItemSavedData(0, 0, b0, false, false, flag, resourcekey); ++ public static MapItemSavedData createForClient(byte scale, boolean locked, ResourceKey dimension) { ++ return new MapItemSavedData(0, 0, scale, false, false, locked, dimension); + } + +- public static MapItemSavedData load(CompoundTag compoundtag) { +- DataResult dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, compoundtag.get("dimension"))); ++ public static MapItemSavedData load(CompoundTag compoundTag) { ++ DataResult> dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, compoundTag.get("dimension"))); // CraftBukkit - decompile error + Logger logger = MapItemSavedData.LOGGER; + + Objects.requireNonNull(logger); +- ResourceKey resourcekey = (ResourceKey) dataresult.resultOrPartial(logger::error).orElseThrow(() -> { +- return new IllegalArgumentException("Invalid map dimension: " + compoundtag.get("dimension")); ++ // CraftBukkit start ++ ResourceKey resourcekey = dataresult.resultOrPartial(logger::error).orElseGet(() -> { ++ long least = compoundTag.getLong("UUIDLeast"); ++ long most = compoundTag.getLong("UUIDMost"); ++ ++ if (least != 0L && most != 0L) { ++ UUID uniqueId = new UUID(most, least); ++ ++ CraftWorld world = (CraftWorld) Bukkit.getWorld(uniqueId); ++ // Check if the stored world details are correct. ++ if (world == null) { ++ /* All Maps which do not have their valid world loaded are set to a dimension which hopefully won't be reached. ++ This is to prevent them being corrupted with the wrong map data. */ ++ // PAIL: Use Vanilla exception handling for now ++ } else { ++ return world.getHandle().dimension(); ++ } ++ } ++ throw new IllegalArgumentException("Invalid map dimension: " + compoundTag.get("dimension")); ++ // CraftBukkit end + }); +- int i = compoundtag.getInt("xCenter"); +- int j = compoundtag.getInt("zCenter"); +- byte b0 = (byte) Mth.clamp(compoundtag.getByte("scale"), 0, 4); +- boolean flag = !compoundtag.contains("trackingPosition", 1) || compoundtag.getBoolean("trackingPosition"); +- boolean flag1 = compoundtag.getBoolean("unlimitedTracking"); +- boolean flag2 = compoundtag.getBoolean("locked"); +- MapItemSavedData mapitemsaveddata = new MapItemSavedData(i, j, b0, flag, flag1, flag2, resourcekey); +- byte[] abyte = compoundtag.getByteArray("colors"); ++ int i = compoundTag.getInt("xCenter"); ++ int j = compoundTag.getInt("zCenter"); ++ byte b0 = (byte) Mth.clamp(compoundTag.getByte("scale"), 0, 4); ++ boolean flag = !compoundTag.contains("trackingPosition", 1) || compoundTag.getBoolean("trackingPosition"); ++ boolean flag1 = compoundTag.getBoolean("unlimitedTracking"); ++ boolean flag2 = compoundTag.getBoolean("locked"); ++ MapItemSavedData worldmap = new MapItemSavedData(i, j, b0, flag, flag1, flag2, resourcekey); ++ byte[] abyte = compoundTag.getByteArray("colors"); + + if (abyte.length == 16384) { +- mapitemsaveddata.colors = abyte; ++ worldmap.colors = abyte; + } + +- ListTag listtag = compoundtag.getList("banners", 10); ++ ListTag nbttaglist = compoundTag.getList("banners", 10); + +- for (int k = 0; k < listtag.size(); ++k) { +- MapBanner mapbanner = MapBanner.load(listtag.getCompound(k)); ++ for (int k = 0; k < nbttaglist.size(); ++k) { ++ MapBanner mapiconbanner = MapBanner.load(nbttaglist.getCompound(k)); + +- mapitemsaveddata.bannerMarkers.put(mapbanner.getId(), mapbanner); +- mapitemsaveddata.addDecoration(mapbanner.getDecoration(), (LevelAccessor) null, mapbanner.getId(), (double) mapbanner.getPos().getX(), (double) mapbanner.getPos().getZ(), 180.0D, mapbanner.getName()); ++ worldmap.bannerMarkers.put(mapiconbanner.getId(), mapiconbanner); ++ worldmap.addDecoration(mapiconbanner.getDecoration(), (LevelAccessor) null, mapiconbanner.getId(), (double) mapiconbanner.getPos().getX(), (double) mapiconbanner.getPos().getZ(), 180.0D, mapiconbanner.getName()); + } + +- ListTag listtag1 = compoundtag.getList("frames", 10); ++ ListTag nbttaglist1 = compoundTag.getList("frames", 10); + +- for (int l = 0; l < listtag1.size(); ++l) { +- MapFrame mapframe = MapFrame.load(listtag1.getCompound(l)); ++ for (int l = 0; l < nbttaglist1.size(); ++l) { ++ MapFrame worldmapframe = MapFrame.load(nbttaglist1.getCompound(l)); + +- mapitemsaveddata.frameMarkers.put(mapframe.getId(), mapframe); +- mapitemsaveddata.addDecoration(MapDecoration.Type.FRAME, (LevelAccessor) null, "frame-" + mapframe.getEntityId(), (double) mapframe.getPos().getX(), (double) mapframe.getPos().getZ(), (double) mapframe.getRotation(), (Component) null); ++ worldmap.frameMarkers.put(worldmapframe.getId(), worldmapframe); ++ worldmap.addDecoration(MapDecoration.Type.FRAME, (LevelAccessor) null, "frame-" + worldmapframe.getEntityId(), (double) worldmapframe.getPos().getX(), (double) worldmapframe.getPos().getZ(), (double) worldmapframe.getRotation(), (Component) null); + } + +- return mapitemsaveddata; ++ return worldmap; + } + + @Override +- @Override +- public CompoundTag save(CompoundTag compoundtag) { +- DataResult dataresult = ResourceLocation.CODEC.encodeStart(NbtOps.INSTANCE, this.dimension.location()); ++ public CompoundTag save(CompoundTag compound) { ++ DataResult dataresult = ResourceLocation.CODEC.encodeStart(NbtOps.INSTANCE, this.dimension.location()); // CraftBukkit - decompile error + Logger logger = MapItemSavedData.LOGGER; + + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((tag) -> { +- compoundtag.put("dimension", tag); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("dimension", nbtbase); + }); +- compoundtag.putInt("xCenter", this.centerX); +- compoundtag.putInt("zCenter", this.centerZ); +- compoundtag.putByte("scale", this.scale); +- compoundtag.putByteArray("colors", this.colors); +- compoundtag.putBoolean("trackingPosition", this.trackingPosition); +- compoundtag.putBoolean("unlimitedTracking", this.unlimitedTracking); +- compoundtag.putBoolean("locked", this.locked); +- ListTag listtag = new ListTag(); ++ // CraftBukkit start ++ if (true) { ++ if (this.uniqueId == null) { ++ for (org.bukkit.World world : server.getWorlds()) { ++ CraftWorld cWorld = (CraftWorld) world; ++ if (cWorld.getHandle().dimension() == this.dimension) { ++ this.uniqueId = cWorld.getUID(); ++ break; ++ } ++ } ++ } ++ /* Perform a second check to see if a matching world was found, this is a necessary ++ change incase Maps are forcefully unlinked from a World and lack a UID.*/ ++ if (this.uniqueId != null) { ++ compound.putLong("UUIDLeast", this.uniqueId.getLeastSignificantBits()); ++ compound.putLong("UUIDMost", this.uniqueId.getMostSignificantBits()); ++ } ++ } ++ // CraftBukkit end ++ compound.putInt("xCenter", this.centerX); ++ compound.putInt("zCenter", this.centerZ); ++ compound.putByte("scale", this.scale); ++ compound.putByteArray("colors", this.colors); ++ compound.putBoolean("trackingPosition", this.trackingPosition); ++ compound.putBoolean("unlimitedTracking", this.unlimitedTracking); ++ compound.putBoolean("locked", this.locked); ++ ListTag nbttaglist = new ListTag(); + Iterator iterator = this.bannerMarkers.values().iterator(); + + while (iterator.hasNext()) { +- MapBanner mapbanner = (MapBanner) iterator.next(); ++ MapBanner mapiconbanner = (MapBanner) iterator.next(); + +- listtag.add(mapbanner.save()); ++ nbttaglist.add(mapiconbanner.save()); + } + +- compoundtag.put("banners", listtag); +- ListTag listtag1 = new ListTag(); ++ compound.put("banners", nbttaglist); ++ ListTag nbttaglist1 = new ListTag(); + Iterator iterator1 = this.frameMarkers.values().iterator(); + + while (iterator1.hasNext()) { +- MapFrame mapframe = (MapFrame) iterator1.next(); ++ MapFrame worldmapframe = (MapFrame) iterator1.next(); + +- listtag1.add(mapframe.save()); ++ nbttaglist1.add(worldmapframe.save()); + } + +- compoundtag.put("frames", listtag1); +- return compoundtag; ++ compound.put("frames", nbttaglist1); ++ return compound; + } + + public MapItemSavedData locked() { +- MapItemSavedData mapitemsaveddata = new MapItemSavedData(this.centerX, this.centerZ, this.scale, this.trackingPosition, this.unlimitedTracking, true, this.dimension); ++ MapItemSavedData worldmap = new MapItemSavedData(this.centerX, this.centerZ, this.scale, this.trackingPosition, this.unlimitedTracking, true, this.dimension); + +- mapitemsaveddata.bannerMarkers.putAll(this.bannerMarkers); +- mapitemsaveddata.decorations.putAll(this.decorations); +- mapitemsaveddata.trackedDecorationCount = this.trackedDecorationCount; +- System.arraycopy(this.colors, 0, mapitemsaveddata.colors, 0, this.colors.length); +- mapitemsaveddata.setDirty(); +- return mapitemsaveddata; ++ worldmap.bannerMarkers.putAll(this.bannerMarkers); ++ worldmap.decorations.putAll(this.decorations); ++ worldmap.trackedDecorationCount = this.trackedDecorationCount; ++ System.arraycopy(this.colors, 0, worldmap.colors, 0, this.colors.length); ++ worldmap.setDirty(); ++ return worldmap; + } + +- public MapItemSavedData scaled(int i) { +- return createFresh((double) this.centerX, (double) this.centerZ, (byte) Mth.clamp(this.scale + i, 0, 4), this.trackingPosition, this.unlimitedTracking, this.dimension); ++ public MapItemSavedData scaled(int scalar) { ++ return createFresh((double) this.centerX, (double) this.centerZ, (byte) Mth.clamp(this.scale + scalar, 0, 4), this.trackingPosition, this.unlimitedTracking, this.dimension); + } + +- public void tickCarriedBy(Player player, ItemStack itemstack) { ++ public void tickCarriedBy(Player player, ItemStack mapStack) { + if (!this.carriedByPlayers.containsKey(player)) { +- MapItemSavedData.HoldingPlayer mapitemsaveddata_holdingplayer = new MapItemSavedData.HoldingPlayer(player); ++ MapItemSavedData.HoldingPlayer worldmap_worldmaphumantracker = new MapItemSavedData.HoldingPlayer(player); + +- this.carriedByPlayers.put(player, mapitemsaveddata_holdingplayer); +- this.carriedBy.add(mapitemsaveddata_holdingplayer); ++ this.carriedByPlayers.put(player, worldmap_worldmaphumantracker); ++ this.carriedBy.add(worldmap_worldmaphumantracker); + } + +- if (!player.getInventory().contains(itemstack)) { ++ if (!player.getInventory().contains(mapStack)) { + this.removeDecoration(player.getName().getString()); + } + + for (int i = 0; i < this.carriedBy.size(); ++i) { +- MapItemSavedData.HoldingPlayer mapitemsaveddata_holdingplayer1 = (MapItemSavedData.HoldingPlayer) this.carriedBy.get(i); +- String s = mapitemsaveddata_holdingplayer1.player.getName().getString(); ++ MapItemSavedData.HoldingPlayer worldmap_worldmaphumantracker1 = (MapItemSavedData.HoldingPlayer) this.carriedBy.get(i); ++ String s = worldmap_worldmaphumantracker1.player.getName().getString(); + +- if (!mapitemsaveddata_holdingplayer1.player.isRemoved() && (mapitemsaveddata_holdingplayer1.player.getInventory().contains(itemstack) || itemstack.isFramed())) { +- if (!itemstack.isFramed() && mapitemsaveddata_holdingplayer1.player.level().dimension() == this.dimension && this.trackingPosition) { +- this.addDecoration(MapDecoration.Type.PLAYER, mapitemsaveddata_holdingplayer1.player.level(), s, mapitemsaveddata_holdingplayer1.player.getX(), mapitemsaveddata_holdingplayer1.player.getZ(), (double) mapitemsaveddata_holdingplayer1.player.getYRot(), (Component) null); ++ if (!worldmap_worldmaphumantracker1.player.isRemoved() && (worldmap_worldmaphumantracker1.player.getInventory().contains(mapStack) || mapStack.isFramed())) { ++ if (!mapStack.isFramed() && worldmap_worldmaphumantracker1.player.level().dimension() == this.dimension && this.trackingPosition) { ++ this.addDecoration(MapDecoration.Type.PLAYER, worldmap_worldmaphumantracker1.player.level(), s, worldmap_worldmaphumantracker1.player.getX(), worldmap_worldmaphumantracker1.player.getZ(), (double) worldmap_worldmaphumantracker1.player.getYRot(), (Component) null); + } + } else { +- this.carriedByPlayers.remove(mapitemsaveddata_holdingplayer1.player); +- this.carriedBy.remove(mapitemsaveddata_holdingplayer1); ++ this.carriedByPlayers.remove(worldmap_worldmaphumantracker1.player); ++ this.carriedBy.remove(worldmap_worldmaphumantracker1); + this.removeDecoration(s); + } + } + +- if (itemstack.isFramed() && this.trackingPosition) { +- ItemFrame itemframe = itemstack.getFrame(); +- BlockPos blockpos = itemframe.getPos(); +- MapFrame mapframe = (MapFrame) this.frameMarkers.get(MapFrame.frameId(blockpos)); ++ if (mapStack.isFramed() && this.trackingPosition) { ++ ItemFrame entityitemframe = mapStack.getFrame(); ++ BlockPos blockposition = entityitemframe.getPos(); ++ MapFrame worldmapframe = (MapFrame) this.frameMarkers.get(MapFrame.frameId(blockposition)); + +- if (mapframe != null && itemframe.getId() != mapframe.getEntityId() && this.frameMarkers.containsKey(mapframe.getId())) { +- this.removeDecoration("frame-" + mapframe.getEntityId()); ++ if (worldmapframe != null && entityitemframe.getId() != worldmapframe.getEntityId() && this.frameMarkers.containsKey(worldmapframe.getId())) { ++ this.removeDecoration("frame-" + worldmapframe.getEntityId()); + } + +- MapFrame mapframe1 = new MapFrame(blockpos, itemframe.getDirection().get2DDataValue() * 90, itemframe.getId()); ++ MapFrame worldmapframe1 = new MapFrame(blockposition, entityitemframe.getDirection().get2DDataValue() * 90, entityitemframe.getId()); + +- this.addDecoration(MapDecoration.Type.FRAME, player.level(), "frame-" + itemframe.getId(), (double) blockpos.getX(), (double) blockpos.getZ(), (double) (itemframe.getDirection().get2DDataValue() * 90), (Component) null); +- this.frameMarkers.put(mapframe1.getId(), mapframe1); ++ this.addDecoration(MapDecoration.Type.FRAME, player.level(), "frame-" + entityitemframe.getId(), (double) blockposition.getX(), (double) blockposition.getZ(), (double) (entityitemframe.getDirection().get2DDataValue() * 90), (Component) null); ++ this.frameMarkers.put(worldmapframe1.getId(), worldmapframe1); + } + +- CompoundTag compoundtag = itemstack.getTag(); ++ CompoundTag nbttagcompound = mapStack.getTag(); + +- if (compoundtag != null && compoundtag.contains("Decorations", 9)) { +- ListTag listtag = compoundtag.getList("Decorations", 10); ++ if (nbttagcompound != null && nbttagcompound.contains("Decorations", 9)) { ++ ListTag nbttaglist = nbttagcompound.getList("Decorations", 10); + +- for (int j = 0; j < listtag.size(); ++j) { +- CompoundTag compoundtag1 = listtag.getCompound(j); ++ for (int j = 0; j < nbttaglist.size(); ++j) { ++ CompoundTag nbttagcompound1 = nbttaglist.getCompound(j); + +- if (!this.decorations.containsKey(compoundtag1.getString("id"))) { +- this.addDecoration(MapDecoration.Type.byIcon(compoundtag1.getByte("type")), player.level(), compoundtag1.getString("id"), compoundtag1.getDouble("x"), compoundtag1.getDouble("z"), compoundtag1.getDouble("rot"), (Component) null); ++ if (!this.decorations.containsKey(nbttagcompound1.getString("id"))) { ++ this.addDecoration(MapDecoration.Type.byIcon(nbttagcompound1.getByte("type")), player.level(), nbttagcompound1.getString("id"), nbttagcompound1.getDouble("x"), nbttagcompound1.getDouble("z"), nbttagcompound1.getDouble("rot"), (Component) null); + } + } + } + + } + +- private void removeDecoration(String s) { +- MapDecoration mapdecoration = (MapDecoration) this.decorations.remove(s); ++ private void removeDecoration(String identifier) { ++ MapDecoration mapicon = (MapDecoration) this.decorations.remove(identifier); + +- if (mapdecoration != null && mapdecoration.type().shouldTrackCount()) { ++ if (mapicon != null && mapicon.type().shouldTrackCount()) { + --this.trackedDecorationCount; + } + + this.setDecorationsDirty(); + } + +- public static void addTargetDecoration(ItemStack itemstack, BlockPos blockpos, String s, MapDecoration.Type mapdecoration_type) { +- ListTag listtag; ++ public static void addTargetDecoration(ItemStack map, BlockPos target, String decorationName, MapDecoration.Type type) { ++ ListTag nbttaglist; + +- if (itemstack.hasTag() && itemstack.getTag().contains("Decorations", 9)) { +- listtag = itemstack.getTag().getList("Decorations", 10); ++ if (map.hasTag() && map.getTag().contains("Decorations", 9)) { ++ nbttaglist = map.getTag().getList("Decorations", 10); + } else { +- listtag = new ListTag(); +- itemstack.addTagElement("Decorations", listtag); ++ nbttaglist = new ListTag(); ++ map.addTagElement("Decorations", nbttaglist); + } + +- CompoundTag compoundtag = new CompoundTag(); ++ CompoundTag nbttagcompound = new CompoundTag(); + +- compoundtag.putByte("type", mapdecoration_type.getIcon()); +- compoundtag.putString("id", s); +- compoundtag.putDouble("x", (double) blockpos.getX()); +- compoundtag.putDouble("z", (double) blockpos.getZ()); +- compoundtag.putDouble("rot", 180.0D); +- listtag.add(compoundtag); +- if (mapdecoration_type.hasMapColor()) { +- CompoundTag compoundtag1 = itemstack.getOrCreateTagElement("display"); ++ nbttagcompound.putByte("type", type.getIcon()); ++ nbttagcompound.putString("id", decorationName); ++ nbttagcompound.putDouble("x", (double) target.getX()); ++ nbttagcompound.putDouble("z", (double) target.getZ()); ++ nbttagcompound.putDouble("rot", 180.0D); ++ nbttaglist.add(nbttagcompound); ++ if (type.hasMapColor()) { ++ CompoundTag nbttagcompound1 = map.getOrCreateTagElement("display"); + +- compoundtag1.putInt("MapColor", mapdecoration_type.getMapColor()); ++ nbttagcompound1.putInt("MapColor", type.getMapColor()); + } + + } + +- private void addDecoration(MapDecoration.Type mapdecoration_type, @Nullable LevelAccessor levelaccessor, String s, double d0, double d1, double d2, @Nullable Component component) { ++ private void addDecoration(MapDecoration.Type type, @Nullable LevelAccessor level, String decorationName, double levelX, double d1, double levelZ, @Nullable Component ichatbasecomponent) { + int i = 1 << this.scale; +- float f = (float) (d0 - (double) this.centerX) / (float) i; ++ float f = (float) (levelX - (double) this.centerX) / (float) i; + float f1 = (float) (d1 - (double) this.centerZ) / (float) i; + byte b0 = (byte) ((int) ((double) (f * 2.0F) + 0.5D)); + byte b1 = (byte) ((int) ((double) (f1 * 2.0F) + 0.5D)); +@@ -286,30 +343,30 @@ + byte b2; + + if (f >= -63.0F && f1 >= -63.0F && f <= 63.0F && f1 <= 63.0F) { +- d2 += d2 < 0.0D ? -8.0D : 8.0D; +- b2 = (byte) ((int) (d2 * 16.0D / 360.0D)); +- if (this.dimension == Level.NETHER && levelaccessor != null) { +- int j = (int) (levelaccessor.getLevelData().getDayTime() / 10L); ++ levelZ += levelZ < 0.0D ? -8.0D : 8.0D; ++ b2 = (byte) ((int) (levelZ * 16.0D / 360.0D)); ++ if (this.dimension == Level.NETHER && level != null) { ++ int j = (int) (level.getLevelData().getDayTime() / 10L); + + b2 = (byte) (j * j * 34187121 + j * 121 >> 15 & 15); + } + } else { +- if (mapdecoration_type != MapDecoration.Type.PLAYER) { +- this.removeDecoration(s); ++ if (type != MapDecoration.Type.PLAYER) { ++ this.removeDecoration(decorationName); + return; + } + + boolean flag1 = true; + + if (Math.abs(f) < 320.0F && Math.abs(f1) < 320.0F) { +- mapdecoration_type = MapDecoration.Type.PLAYER_OFF_MAP; ++ type = MapDecoration.Type.PLAYER_OFF_MAP; + } else { + if (!this.unlimitedTracking) { +- this.removeDecoration(s); ++ this.removeDecoration(decorationName); + return; + } + +- mapdecoration_type = MapDecoration.Type.PLAYER_OFF_LIMITS; ++ type = MapDecoration.Type.PLAYER_OFF_LIMITS; + } + + b2 = 0; +@@ -330,15 +387,15 @@ + } + } + +- MapDecoration mapdecoration = new MapDecoration(mapdecoration_type, b0, b1, b2, component); +- MapDecoration mapdecoration1 = (MapDecoration) this.decorations.put(s, mapdecoration); ++ MapDecoration mapicon = new MapDecoration(type, b0, b1, b2, ichatbasecomponent); ++ MapDecoration mapicon1 = (MapDecoration) this.decorations.put(decorationName, mapicon); + +- if (!mapdecoration.equals(mapdecoration1)) { +- if (mapdecoration1 != null && mapdecoration1.type().shouldTrackCount()) { ++ if (!mapicon.equals(mapicon1)) { ++ if (mapicon1 != null && mapicon1.type().shouldTrackCount()) { + --this.trackedDecorationCount; + } + +- if (mapdecoration_type.shouldTrackCount()) { ++ if (type.shouldTrackCount()) { + ++this.trackedDecorationCount; + } + +@@ -348,64 +405,64 @@ + } + + @Nullable +- public Packet getUpdatePacket(int i, Player player) { +- MapItemSavedData.HoldingPlayer mapitemsaveddata_holdingplayer = (MapItemSavedData.HoldingPlayer) this.carriedByPlayers.get(player); ++ public Packet getUpdatePacket(int mapId, Player player) { ++ MapItemSavedData.HoldingPlayer worldmap_worldmaphumantracker = (MapItemSavedData.HoldingPlayer) this.carriedByPlayers.get(player); + +- return mapitemsaveddata_holdingplayer == null ? null : mapitemsaveddata_holdingplayer.nextUpdatePacket(i); ++ return worldmap_worldmaphumantracker == null ? null : worldmap_worldmaphumantracker.nextUpdatePacket(mapId); + } + +- private void setColorsDirty(int i, int j) { ++ public void setColorsDirty(int x, int z) { + this.setDirty(); + Iterator iterator = this.carriedBy.iterator(); + + while (iterator.hasNext()) { +- MapItemSavedData.HoldingPlayer mapitemsaveddata_holdingplayer = (MapItemSavedData.HoldingPlayer) iterator.next(); ++ MapItemSavedData.HoldingPlayer worldmap_worldmaphumantracker = (MapItemSavedData.HoldingPlayer) iterator.next(); + +- mapitemsaveddata_holdingplayer.markColorsDirty(i, j); ++ worldmap_worldmaphumantracker.markColorsDirty(x, z); + } + + } + +- private void setDecorationsDirty() { ++ public void setDecorationsDirty() { + this.setDirty(); + this.carriedBy.forEach(MapItemSavedData.HoldingPlayer::markDecorationsDirty); + } + + public MapItemSavedData.HoldingPlayer getHoldingPlayer(Player player) { +- MapItemSavedData.HoldingPlayer mapitemsaveddata_holdingplayer = (MapItemSavedData.HoldingPlayer) this.carriedByPlayers.get(player); ++ MapItemSavedData.HoldingPlayer worldmap_worldmaphumantracker = (MapItemSavedData.HoldingPlayer) this.carriedByPlayers.get(player); + +- if (mapitemsaveddata_holdingplayer == null) { +- mapitemsaveddata_holdingplayer = new MapItemSavedData.HoldingPlayer(player); +- this.carriedByPlayers.put(player, mapitemsaveddata_holdingplayer); +- this.carriedBy.add(mapitemsaveddata_holdingplayer); ++ if (worldmap_worldmaphumantracker == null) { ++ worldmap_worldmaphumantracker = new MapItemSavedData.HoldingPlayer(player); ++ this.carriedByPlayers.put(player, worldmap_worldmaphumantracker); ++ this.carriedBy.add(worldmap_worldmaphumantracker); + } + +- return mapitemsaveddata_holdingplayer; ++ return worldmap_worldmaphumantracker; + } + +- public boolean toggleBanner(LevelAccessor levelaccessor, BlockPos blockpos) { +- double d0 = (double) blockpos.getX() + 0.5D; +- double d1 = (double) blockpos.getZ() + 0.5D; ++ public boolean toggleBanner(LevelAccessor accessor, BlockPos pos) { ++ double d0 = (double) pos.getX() + 0.5D; ++ double d1 = (double) pos.getZ() + 0.5D; + int i = 1 << this.scale; + double d2 = (d0 - (double) this.centerX) / (double) i; + double d3 = (d1 - (double) this.centerZ) / (double) i; + boolean flag = true; + + if (d2 >= -63.0D && d3 >= -63.0D && d2 <= 63.0D && d3 <= 63.0D) { +- MapBanner mapbanner = MapBanner.fromWorld(levelaccessor, blockpos); ++ MapBanner mapiconbanner = MapBanner.fromWorld(accessor, pos); + +- if (mapbanner == null) { ++ if (mapiconbanner == null) { + return false; + } + +- if (this.bannerMarkers.remove(mapbanner.getId(), mapbanner)) { +- this.removeDecoration(mapbanner.getId()); ++ if (this.bannerMarkers.remove(mapiconbanner.getId(), mapiconbanner)) { ++ this.removeDecoration(mapiconbanner.getId()); + return true; + } + + if (!this.isTrackedCountOverLimit(256)) { +- this.bannerMarkers.put(mapbanner.getId(), mapbanner); +- this.addDecoration(mapbanner.getDecoration(), levelaccessor, mapbanner.getId(), d0, d1, 180.0D, mapbanner.getName()); ++ this.bannerMarkers.put(mapiconbanner.getId(), mapiconbanner); ++ this.addDecoration(mapiconbanner.getDecoration(), accessor, mapiconbanner.getId(), d0, d1, 180.0D, mapiconbanner.getName()); + return true; + } + } +@@ -413,18 +470,18 @@ + return false; + } + +- public void checkBanners(BlockGetter blockgetter, int i, int j) { ++ public void checkBanners(BlockGetter reader, int x, int z) { + Iterator iterator = this.bannerMarkers.values().iterator(); + + while (iterator.hasNext()) { +- MapBanner mapbanner = (MapBanner) iterator.next(); ++ MapBanner mapiconbanner = (MapBanner) iterator.next(); + +- if (mapbanner.getPos().getX() == i && mapbanner.getPos().getZ() == j) { +- MapBanner mapbanner1 = MapBanner.fromWorld(blockgetter, mapbanner.getPos()); ++ if (mapiconbanner.getPos().getX() == x && mapiconbanner.getPos().getZ() == z) { ++ MapBanner mapiconbanner1 = MapBanner.fromWorld(reader, mapiconbanner.getPos()); + +- if (!mapbanner.equals(mapbanner1)) { ++ if (!mapiconbanner.equals(mapiconbanner1)) { + iterator.remove(); +- this.removeDecoration(mapbanner.getId()); ++ this.removeDecoration(mapiconbanner.getId()); + } + } + } +@@ -435,52 +492,52 @@ + return this.bannerMarkers.values(); + } + +- public void removedFromFrame(BlockPos blockpos, int i) { +- this.removeDecoration("frame-" + i); +- this.frameMarkers.remove(MapFrame.frameId(blockpos)); ++ public void removedFromFrame(BlockPos pos, int entityId) { ++ this.removeDecoration("frame-" + entityId); ++ this.frameMarkers.remove(MapFrame.frameId(pos)); + } + +- public boolean updateColor(int i, int j, byte b0) { +- byte b1 = this.colors[i + j * 128]; ++ public boolean updateColor(int x, int z, byte color) { ++ byte b1 = this.colors[x + z * 128]; + +- if (b1 != b0) { +- this.setColor(i, j, b0); ++ if (b1 != color) { ++ this.setColor(x, z, color); + return true; + } else { + return false; + } + } + +- public void setColor(int i, int j, byte b0) { +- this.colors[i + j * 128] = b0; +- this.setColorsDirty(i, j); ++ public void setColor(int x, int z, byte color) { ++ this.colors[x + z * 128] = color; ++ this.setColorsDirty(x, z); + } + + public boolean isExplorationMap() { + Iterator iterator = this.decorations.values().iterator(); + +- MapDecoration mapdecoration; ++ MapDecoration mapicon; + + do { + if (!iterator.hasNext()) { + return false; + } + +- mapdecoration = (MapDecoration) iterator.next(); +- } while (!mapdecoration.type().isExplorationMapElement()); ++ mapicon = (MapDecoration) iterator.next(); ++ } while (!mapicon.type().isExplorationMapElement()); + + return true; + } + +- public void addClientSideDecorations(List list) { ++ public void addClientSideDecorations(List decorations) { + this.decorations.clear(); + this.trackedDecorationCount = 0; + +- for (int i = 0; i < list.size(); ++i) { +- MapDecoration mapdecoration = (MapDecoration) list.get(i); ++ for (int i = 0; i < decorations.size(); ++i) { ++ MapDecoration mapicon = (MapDecoration) decorations.get(i); + +- this.decorations.put("icon-" + i, mapdecoration); +- if (mapdecoration.type().shouldTrackCount()) { ++ this.decorations.put("icon-" + i, mapicon); ++ if (mapicon.type().shouldTrackCount()) { + ++this.trackedDecorationCount; + } + } +@@ -491,8 +548,8 @@ + return this.decorations.values(); + } + +- public boolean isTrackedCountOverLimit(int i) { +- return this.trackedDecorationCount >= i; ++ public boolean isTrackedCountOverLimit(int trackedCount) { ++ return this.trackedDecorationCount >= trackedCount; + } + + public class HoldingPlayer { +@@ -507,11 +564,11 @@ + private int tick; + public int step; + +- HoldingPlayer(Player player) { +- this.player = player; ++ HoldingPlayer(Player entityhuman) { ++ this.player = entityhuman; + } + +- private MapItemSavedData.MapPatch createPatch() { ++ private MapItemSavedData.MapPatch createPatch(byte[] buffer) { // CraftBukkit + int i = this.minDirtyX; + int j = this.minDirtyY; + int k = this.maxDirtyX + 1 - this.minDirtyX; +@@ -520,7 +577,7 @@ + + for (int i1 = 0; i1 < k; ++i1) { + for (int j1 = 0; j1 < l; ++j1) { +- abyte[i1 + j1 * k] = MapItemSavedData.this.colors[i + i1 + (j + j1) * 128]; ++ abyte[i1 + j1 * k] = buffer[i + i1 + (j + j1) * 128]; // CraftBukkit + } + } + +@@ -528,40 +585,50 @@ + } + + @Nullable +- Packet nextUpdatePacket(int i) { +- MapItemSavedData.MapPatch mapitemsaveddata_mappatch; ++ Packet nextUpdatePacket(int mapId) { ++ MapItemSavedData.MapPatch worldmap_b; ++ org.bukkit.craftbukkit.map.RenderData render = MapItemSavedData.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()); // CraftBukkit + + if (this.dirtyData) { + this.dirtyData = false; +- mapitemsaveddata_mappatch = this.createPatch(); ++ worldmap_b = this.createPatch(render.buffer); // CraftBukkit + } else { +- mapitemsaveddata_mappatch = null; ++ worldmap_b = null; + } + + Collection collection; + +- if (this.dirtyDecorations && this.tick++ % 5 == 0) { ++ if ((true || this.dirtyDecorations) && this.tick++ % 5 == 0) { // CraftBukkit - custom maps don't update this yet + this.dirtyDecorations = false; +- collection = MapItemSavedData.this.decorations.values(); ++ // CraftBukkit start ++ java.util.Collection icons = new java.util.ArrayList(); ++ ++ for (org.bukkit.map.MapCursor cursor : render.cursors) { ++ if (cursor.isVisible()) { ++ icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption()))); ++ } ++ } ++ collection = icons; ++ // CraftBukkit end + } else { + collection = null; + } + +- return collection == null && mapitemsaveddata_mappatch == null ? null : new ClientboundMapItemDataPacket(i, MapItemSavedData.this.scale, MapItemSavedData.this.locked, collection, mapitemsaveddata_mappatch); ++ return collection == null && worldmap_b == null ? null : new ClientboundMapItemDataPacket(mapId, MapItemSavedData.this.scale, MapItemSavedData.this.locked, collection, worldmap_b); + } + +- void markColorsDirty(int i, int j) { ++ void markColorsDirty(int x, int z) { + if (this.dirtyData) { +- this.minDirtyX = Math.min(this.minDirtyX, i); +- this.minDirtyY = Math.min(this.minDirtyY, j); +- this.maxDirtyX = Math.max(this.maxDirtyX, i); +- this.maxDirtyY = Math.max(this.maxDirtyY, j); ++ this.minDirtyX = Math.min(this.minDirtyX, x); ++ this.minDirtyY = Math.min(this.minDirtyY, z); ++ this.maxDirtyX = Math.max(this.maxDirtyX, x); ++ this.maxDirtyY = Math.max(this.maxDirtyY, z); + } else { + this.dirtyData = true; +- this.minDirtyX = i; +- this.minDirtyY = j; +- this.maxDirtyX = i; +- this.maxDirtyY = j; ++ this.minDirtyX = x; ++ this.minDirtyY = z; ++ this.maxDirtyX = x; ++ this.maxDirtyY = z; + } + + } +@@ -579,18 +646,18 @@ + public final int height; + public final byte[] mapColors; + +- public MapPatch(int i, int j, int k, int l, byte[] abyte) { +- this.startX = i; +- this.startY = j; +- this.width = k; +- this.height = l; +- this.mapColors = abyte; ++ public MapPatch(int startX, int startY, int width, int height, byte[] mapColors) { ++ this.startX = startX; ++ this.startY = startY; ++ this.width = width; ++ this.height = height; ++ this.mapColors = mapColors; + } + +- public void applyToMap(MapItemSavedData mapitemsaveddata) { ++ public void applyToMap(MapItemSavedData savedData) { + for (int i = 0; i < this.width; ++i) { + for (int j = 0; j < this.height; ++j) { +- mapitemsaveddata.setColor(this.startX + i, this.startY + j, this.mapColors[i + j * this.width]); ++ savedData.setColor(this.startX + i, this.startY + j, this.mapColors[i + j * this.width]); + } + } + diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/LevelStorageSource.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/LevelStorageSource.java.patch new file mode 100644 index 0000000000..b6ba3a7373 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/LevelStorageSource.java.patch @@ -0,0 +1,578 @@ +--- a/net/minecraft/world/level/storage/LevelStorageSource.java ++++ b/net/minecraft/world/level/storage/LevelStorageSource.java +@@ -71,7 +71,6 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelSettings; + import net.minecraft.world.level.WorldDataConfiguration; +-import net.minecraft.world.level.dimension.DimensionType; + import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.levelgen.WorldDimensions; + import net.minecraft.world.level.levelgen.WorldGenSettings; +@@ -91,29 +90,29 @@ + }; + public static final String ALLOWED_SYMLINKS_CONFIG_NAME = "allowed_symlinks.txt"; + private static final int UNCOMPRESSED_NBT_QUOTA = 104857600; +- private final Path baseDir; ++ public final Path baseDir; + private final Path backupDir; + final DataFixer fixerUpper; + private final DirectoryValidator worldDirValidator; + +- public LevelStorageSource(Path path, Path path1, DirectoryValidator directoryvalidator, DataFixer datafixer) { +- this.fixerUpper = datafixer; ++ public LevelStorageSource(Path baseDir, Path backupDir, DirectoryValidator worldDirValidator, DataFixer fixerUpper) { ++ this.fixerUpper = fixerUpper; + + try { +- FileUtil.createDirectoriesSafe(path); ++ FileUtil.createDirectoriesSafe(baseDir); + } catch (IOException ioexception) { + throw new UncheckedIOException(ioexception); + } + +- this.baseDir = path; +- this.backupDir = path1; +- this.worldDirValidator = directoryvalidator; ++ this.baseDir = baseDir; ++ this.backupDir = backupDir; ++ this.worldDirValidator = worldDirValidator; + } + +- public static DirectoryValidator parseValidator(Path path) { +- if (Files.exists(path, new LinkOption[0])) { ++ public static DirectoryValidator parseValidator(Path validator) { ++ if (Files.exists(validator, new LinkOption[0])) { + try { +- BufferedReader bufferedreader = Files.newBufferedReader(path); ++ BufferedReader bufferedreader = Files.newBufferedReader(validator); + + DirectoryValidator directoryvalidator; + +@@ -144,42 +143,43 @@ + return new DirectoryValidator(LevelStorageSource.NO_SYMLINKS_ALLOWED); + } + +- public static LevelStorageSource createDefault(Path path) { +- DirectoryValidator directoryvalidator = parseValidator(path.resolve("allowed_symlinks.txt")); ++ public static LevelStorageSource createDefault(Path savesDir) { ++ DirectoryValidator directoryvalidator = parseValidator(savesDir.resolve("allowed_symlinks.txt")); + +- return new LevelStorageSource(path, path.resolve("../backups"), directoryvalidator, DataFixers.getDataFixer()); ++ return new LevelStorageSource(savesDir, savesDir.resolve("../backups"), directoryvalidator, DataFixers.getDataFixer()); + } + + public static WorldDataConfiguration readDataConfig(Dynamic dynamic) { +- DataResult dataresult = WorldDataConfiguration.CODEC.parse(dynamic); ++ DataResult dataresult = WorldDataConfiguration.CODEC.parse(dynamic); // CraftBukkit - decompile error + Logger logger = LevelStorageSource.LOGGER; + + Objects.requireNonNull(logger); + return (WorldDataConfiguration) dataresult.resultOrPartial(logger::error).orElse(WorldDataConfiguration.DEFAULT); + } + +- public static WorldLoader.PackConfig getPackConfig(Dynamic dynamic, PackRepository packrepository, boolean flag) { +- return new WorldLoader.PackConfig(packrepository, readDataConfig(dynamic), flag, false); ++ public static WorldLoader.d getPackConfig(Dynamic dynamic, PackRepository resourcepackrepository, boolean flag) { ++ return new WorldLoader.d(resourcepackrepository, readDataConfig(dynamic), flag, false); + } + +- public static LevelDataAndDimensions getLevelDataAndDimensions(Dynamic dynamic, WorldDataConfiguration worlddataconfiguration, Registry registry, RegistryAccess.Frozen registryaccess_frozen) { +- Dynamic dynamic1 = wrapWithRegistryOps(dynamic, registryaccess_frozen); ++ public static LevelDataAndDimensions getLevelDataAndDimensions(Dynamic dynamic, WorldDataConfiguration worlddataconfiguration, Registry iregistry, RegistryAccess.Dimension iregistrycustom_dimension) { ++ Dynamic dynamic1 = wrapWithRegistryOps(dynamic, iregistrycustom_dimension); + Dynamic dynamic2 = dynamic1.get("WorldGenSettings").orElseEmptyMap(); + DataResult dataresult = WorldGenSettings.CODEC.parse(dynamic2); + Logger logger = LevelStorageSource.LOGGER; + + Objects.requireNonNull(logger); +- WorldGenSettings worldgensettings = (WorldGenSettings) dataresult.getOrThrow(false, Util.prefix("WorldGenSettings: ", logger::error)); +- LevelSettings levelsettings = LevelSettings.parse(dynamic1, worlddataconfiguration); +- WorldDimensions.Complete worlddimensions_complete = worldgensettings.dimensions().bake(registry); +- Lifecycle lifecycle = worlddimensions_complete.lifecycle().add(registryaccess_frozen.allRegistriesLifecycle()); +- PrimaryLevelData primaryleveldata = PrimaryLevelData.parse(dynamic1, levelsettings, worlddimensions_complete.specialWorldProperty(), worldgensettings.options(), lifecycle); ++ WorldGenSettings generatorsettings = (WorldGenSettings) dataresult.getOrThrow(false, Util.prefix("WorldGenSettings: ", logger::error)); ++ LevelSettings worldsettings = LevelSettings.parse(dynamic1, worlddataconfiguration); ++ WorldDimensions.b worlddimensions_b = generatorsettings.dimensions().bake(iregistry); ++ Lifecycle lifecycle = worlddimensions_b.lifecycle().add(iregistrycustom_dimension.allRegistriesLifecycle()); ++ PrimaryLevelData worlddataserver = PrimaryLevelData.parse(dynamic1, worldsettings, worlddimensions_b.specialWorldProperty(), generatorsettings.options(), lifecycle); ++ worlddataserver.pdc = ((Dynamic) dynamic1).getElement("BukkitValues", null); // CraftBukkit - Add PDC to world + +- return new LevelDataAndDimensions(primaryleveldata, worlddimensions_complete); ++ return new LevelDataAndDimensions(worlddataserver, worlddimensions_b); + } + +- private static Dynamic wrapWithRegistryOps(Dynamic dynamic, RegistryAccess.Frozen registryaccess_frozen) { +- RegistryOps registryops = RegistryOps.create(dynamic.getOps(), (HolderLookup.Provider) registryaccess_frozen); ++ private static Dynamic wrapWithRegistryOps(Dynamic dynamic, RegistryAccess.Dimension iregistrycustom_dimension) { ++ RegistryOps registryops = RegistryOps.create(dynamic.getOps(), (HolderLookup.Provider) iregistrycustom_dimension); + + return new Dynamic(registryops, dynamic.getValue()); + } +@@ -188,23 +188,23 @@ + return "Anvil"; + } + +- public LevelStorageSource.LevelCandidates findLevelCandidates() throws LevelStorageException { ++ public LevelStorageSource.a findLevelCandidates() throws LevelStorageException { + if (!Files.isDirectory(this.baseDir, new LinkOption[0])) { + throw new LevelStorageException(Component.translatable("selectWorld.load_folder_access")); + } else { + try { +- Stream stream = Files.list(this.baseDir); ++ Stream stream = Files.list(this.baseDir); // CraftBukkit - decompile error + +- LevelStorageSource.LevelCandidates levelstoragesource_levelcandidates; ++ LevelStorageSource.a convertable_a; + + try { + List list = stream.filter((path) -> { + return Files.isDirectory(path, new LinkOption[0]); +- }).map(LevelStorageSource.LevelDirectory::new).filter((levelstoragesource_leveldirectory) -> { +- return Files.isRegularFile(levelstoragesource_leveldirectory.dataFile(), new LinkOption[0]) || Files.isRegularFile(levelstoragesource_leveldirectory.oldDataFile(), new LinkOption[0]); ++ }).map(LevelStorageSource.LevelDirectory::new).filter((convertable_b) -> { ++ return Files.isRegularFile(convertable_b.dataFile(), new LinkOption[0]) || Files.isRegularFile(convertable_b.oldDataFile(), new LinkOption[0]); + }).toList(); + +- levelstoragesource_levelcandidates = new LevelStorageSource.LevelCandidates(list); ++ convertable_a = new LevelStorageSource.a(list); + } catch (Throwable throwable) { + if (stream != null) { + try { +@@ -221,52 +221,52 @@ + stream.close(); + } + +- return levelstoragesource_levelcandidates; ++ return convertable_a; + } catch (IOException ioexception) { + throw new LevelStorageException(Component.translatable("selectWorld.load_folder_access")); + } + } + } + +- public CompletableFuture> loadLevelSummaries(LevelStorageSource.LevelCandidates levelstoragesource_levelcandidates) { +- List> list = new ArrayList(levelstoragesource_levelcandidates.levels.size()); +- Iterator iterator = levelstoragesource_levelcandidates.levels.iterator(); ++ public CompletableFuture> loadLevelSummaries(LevelStorageSource.a candidates) { ++ List> list = new ArrayList(candidates.levels.size()); ++ Iterator iterator = candidates.levels.iterator(); + + while (iterator.hasNext()) { +- LevelStorageSource.LevelDirectory levelstoragesource_leveldirectory = (LevelStorageSource.LevelDirectory) iterator.next(); ++ LevelStorageSource.LevelDirectory convertable_b = (LevelStorageSource.LevelDirectory) iterator.next(); + + list.add(CompletableFuture.supplyAsync(() -> { + boolean flag; + + try { +- flag = DirectoryLock.isLocked(levelstoragesource_leveldirectory.path()); ++ flag = DirectoryLock.isLocked(convertable_b.path()); + } catch (Exception exception) { +- LevelStorageSource.LOGGER.warn("Failed to read {} lock", levelstoragesource_leveldirectory.path(), exception); ++ LevelStorageSource.LOGGER.warn("Failed to read {} lock", convertable_b.path(), exception); + return null; + } + + try { +- return this.readLevelSummary(levelstoragesource_leveldirectory, flag); ++ return this.readLevelSummary(convertable_b, flag); + } catch (OutOfMemoryError outofmemoryerror) { + MemoryReserve.release(); + System.gc(); +- String s = "Ran out of memory trying to read summary of world folder \"" + levelstoragesource_leveldirectory.directoryName() + "\""; ++ String s = "Ran out of memory trying to read summary of world folder \"" + convertable_b.directoryName() + "\""; + + LevelStorageSource.LOGGER.error(LogUtils.FATAL_MARKER, s); + OutOfMemoryError outofmemoryerror1 = new OutOfMemoryError("Ran out of memory reading level data"); + + outofmemoryerror1.initCause(outofmemoryerror); + CrashReport crashreport = CrashReport.forThrowable(outofmemoryerror1, s); +- CrashReportCategory crashreportcategory = crashreport.addCategory("World details"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("World details"); + +- crashreportcategory.setDetail("Folder Name", (Object) levelstoragesource_leveldirectory.directoryName()); ++ crashreportsystemdetails.setDetail("Folder Name", (Object) convertable_b.directoryName()); + + try { +- long i = Files.size(levelstoragesource_leveldirectory.dataFile()); ++ long i = Files.size(convertable_b.dataFile()); + +- crashreportcategory.setDetail("level.dat size", (Object) i); ++ crashreportsystemdetails.setDetail("level.dat size", (Object) i); + } catch (IOException ioexception) { +- crashreportcategory.setDetailError("level.dat size", ioexception); ++ crashreportsystemdetails.setDetailError("level.dat size", ioexception); + } + + throw new ReportedException(crashreport); +@@ -288,10 +288,10 @@ + } + + static Dynamic readLevelDataTagFixed(Path path, DataFixer datafixer) throws IOException { +- CompoundTag compoundtag = readLevelDataTagRaw(path); +- CompoundTag compoundtag1 = compoundtag.getCompound("Data"); +- int i = NbtUtils.getDataVersion(compoundtag1, -1); +- Dynamic dynamic = DataFixTypes.LEVEL.updateToCurrentVersion(datafixer, new Dynamic(NbtOps.INSTANCE, compoundtag1), i); ++ CompoundTag nbttagcompound = readLevelDataTagRaw(path); ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Data"); ++ int i = NbtUtils.getDataVersion(nbttagcompound1, -1); ++ Dynamic dynamic = DataFixTypes.LEVEL.updateToCurrentVersion(datafixer, new Dynamic(NbtOps.INSTANCE, nbttagcompound1), i); + Dynamic dynamic1 = dynamic.get("Player").orElseEmptyMap(); + Dynamic dynamic2 = DataFixTypes.PLAYER.updateToCurrentVersion(datafixer, dynamic1, i); + +@@ -303,8 +303,8 @@ + return dynamic; + } + +- private LevelSummary readLevelSummary(LevelStorageSource.LevelDirectory levelstoragesource_leveldirectory, boolean flag) { +- Path path = levelstoragesource_leveldirectory.dataFile(); ++ private LevelSummary readLevelSummary(LevelStorageSource.LevelDirectory convertable_b, boolean flag) { ++ Path path = convertable_b.dataFile(); + + if (Files.exists(path, new LinkOption[0])) { + try { +@@ -313,19 +313,19 @@ + + if (!list.isEmpty()) { + LevelStorageSource.LOGGER.warn("{}", ContentValidationException.getMessage(path, list)); +- return new LevelSummary.SymlinkLevelSummary(levelstoragesource_leveldirectory.directoryName(), levelstoragesource_leveldirectory.iconFile()); ++ return new LevelSummary.SymlinkLevelSummary(convertable_b.directoryName(), convertable_b.iconFile()); + } + } + +- Tag tag = readLightweightData(path); ++ Tag nbtbase = readLightweightData(path); + +- if (tag instanceof CompoundTag) { +- CompoundTag compoundtag = (CompoundTag) tag; +- CompoundTag compoundtag1 = compoundtag.getCompound("Data"); +- int i = NbtUtils.getDataVersion(compoundtag1, -1); +- Dynamic dynamic = DataFixTypes.LEVEL.updateToCurrentVersion(this.fixerUpper, new Dynamic(NbtOps.INSTANCE, compoundtag1), i); ++ if (nbtbase instanceof CompoundTag) { ++ CompoundTag nbttagcompound = (CompoundTag) nbtbase; ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Data"); ++ int i = NbtUtils.getDataVersion(nbttagcompound1, -1); ++ Dynamic dynamic = DataFixTypes.LEVEL.updateToCurrentVersion(this.fixerUpper, new Dynamic(NbtOps.INSTANCE, nbttagcompound1), i); + +- return this.makeLevelSummary(dynamic, levelstoragesource_leveldirectory, flag); ++ return this.makeLevelSummary(dynamic, convertable_b, flag); + } + + LevelStorageSource.LOGGER.warn("Invalid root tag in {}", path); +@@ -334,14 +334,14 @@ + } + } + +- return new LevelSummary.CorruptedLevelSummary(levelstoragesource_leveldirectory.directoryName(), levelstoragesource_leveldirectory.iconFile(), getFileModificationTime(levelstoragesource_leveldirectory)); ++ return new LevelSummary.b(convertable_b.directoryName(), convertable_b.iconFile(), getFileModificationTime(convertable_b)); + } + +- private static long getFileModificationTime(LevelStorageSource.LevelDirectory levelstoragesource_leveldirectory) { +- Instant instant = getFileModificationTime(levelstoragesource_leveldirectory.dataFile()); ++ private static long getFileModificationTime(LevelStorageSource.LevelDirectory convertable_b) { ++ Instant instant = getFileModificationTime(convertable_b.dataFile()); + + if (instant == null) { +- instant = getFileModificationTime(levelstoragesource_leveldirectory.oldDataFile()); ++ instant = getFileModificationTime(convertable_b.oldDataFile()); + } + + return instant == null ? -1L : instant.toEpochMilli(); +@@ -356,7 +356,7 @@ + } + } + +- LevelSummary makeLevelSummary(Dynamic dynamic, LevelStorageSource.LevelDirectory levelstoragesource_leveldirectory, boolean flag) { ++ LevelSummary makeLevelSummary(Dynamic dynamic, LevelStorageSource.LevelDirectory convertable_b, boolean flag) { + LevelVersion levelversion = LevelVersion.parse(dynamic); + int i = levelversion.levelDataVersion(); + +@@ -364,36 +364,36 @@ + throw new NbtFormatException("Unknown data version: " + Integer.toHexString(i)); + } else { + boolean flag1 = i != this.getStorageVersion(); +- Path path = levelstoragesource_leveldirectory.iconFile(); ++ Path path = convertable_b.iconFile(); + WorldDataConfiguration worlddataconfiguration = readDataConfig(dynamic); +- LevelSettings levelsettings = LevelSettings.parse(dynamic, worlddataconfiguration); ++ LevelSettings worldsettings = LevelSettings.parse(dynamic, worlddataconfiguration); + FeatureFlagSet featureflagset = parseFeatureFlagsFromSummary(dynamic); + boolean flag2 = FeatureFlags.isExperimental(featureflagset); + +- return new LevelSummary(levelsettings, levelversion, levelstoragesource_leveldirectory.directoryName(), flag1, flag, flag2, path); ++ return new LevelSummary(worldsettings, levelversion, convertable_b.directoryName(), flag1, flag, flag2, path); + } + } + +- private static FeatureFlagSet parseFeatureFlagsFromSummary(Dynamic dynamic) { +- Set set = (Set) dynamic.get("enabled_features").asStream().flatMap((dynamic1) -> { ++ private static FeatureFlagSet parseFeatureFlagsFromSummary(Dynamic dataDynamic) { ++ Set set = (Set) dataDynamic.get("enabled_features").asStream().flatMap((dynamic1) -> { + return dynamic1.asString().result().map(ResourceLocation::tryParse).stream(); + }).collect(Collectors.toSet()); + +- return FeatureFlags.REGISTRY.fromNames(set, (resourcelocation) -> { ++ return FeatureFlags.REGISTRY.fromNames(set, (minecraftkey) -> { + }); + } + + @Nullable +- private static Tag readLightweightData(Path path) throws IOException { ++ private static Tag readLightweightData(Path file) throws IOException { + SkipFields skipfields = new SkipFields(new FieldSelector[]{new FieldSelector("Data", CompoundTag.TYPE, "Player"), new FieldSelector("Data", CompoundTag.TYPE, "WorldGenSettings")}); + +- NbtIo.parseCompressed(path, skipfields, NbtAccounter.create(104857600L)); ++ NbtIo.parseCompressed(file, skipfields, NbtAccounter.create(104857600L)); + return skipfields.getResult(); + } + +- public boolean isNewLevelIdAcceptable(String s) { ++ public boolean isNewLevelIdAcceptable(String saveName) { + try { +- Path path = this.getLevelPath(s); ++ Path path = this.getLevelPath(saveName); + + Files.createDirectory(path); + Files.deleteIfExists(path); +@@ -403,16 +403,16 @@ + } + } + +- public boolean levelExists(String s) { ++ public boolean levelExists(String saveName) { + try { +- return Files.isDirectory(this.getLevelPath(s), new LinkOption[0]); ++ return Files.isDirectory(this.getLevelPath(saveName), new LinkOption[0]); + } catch (InvalidPathException invalidpathexception) { + return false; + } + } + +- public Path getLevelPath(String s) { +- return this.baseDir.resolve(s); ++ public Path getLevelPath(String saveName) { ++ return this.baseDir.resolve(saveName); + } + + public Path getBaseDir() { +@@ -423,34 +423,47 @@ + return this.backupDir; + } + +- public LevelStorageSource.LevelStorageAccess validateAndCreateAccess(String s) throws IOException, ContentValidationException { ++ public LevelStorageSource.LevelStorageAccess validateAndCreateAccess(String s, ResourceKey dimensionType) throws IOException, ContentValidationException { // CraftBukkit + Path path = this.getLevelPath(s); + List list = this.worldDirValidator.validateDirectory(path, true); + + if (!list.isEmpty()) { + throw new ContentValidationException(path, list); + } else { +- return new LevelStorageSource.LevelStorageAccess(s, path); ++ return new LevelStorageSource.LevelStorageAccess(s, path, dimensionType); // CraftBukkit + } + } + +- public LevelStorageSource.LevelStorageAccess createAccess(String s) throws IOException { ++ public LevelStorageSource.LevelStorageAccess createAccess(String s, ResourceKey dimensionType) throws IOException { // CraftBukkit + Path path = this.getLevelPath(s); + +- return new LevelStorageSource.LevelStorageAccess(s, path); ++ return new LevelStorageSource.LevelStorageAccess(s, path, dimensionType); // CraftBukkit + } + + public DirectoryValidator getWorldDirValidator() { + return this.worldDirValidator; + } + +- public static record LevelCandidates(List levels) implements Iterable { ++ // CraftBukkit start ++ public static Path getStorageFolder(Path path, ResourceKey dimensionType) { ++ if (dimensionType == LevelStem.OVERWORLD) { ++ return path; ++ } else if (dimensionType == LevelStem.NETHER) { ++ return path.resolve("DIM-1"); ++ } else if (dimensionType == LevelStem.END) { ++ return path.resolve("DIM1"); ++ } else { ++ return path.resolve("dimensions").resolve(dimensionType.location().getNamespace()).resolve(dimensionType.location().getPath()); ++ } ++ } ++ // CraftBukkit end + ++ public static record a(List levels) implements Iterable { ++ + public boolean isEmpty() { + return this.levels.isEmpty(); + } + +- @Override + public Iterator iterator() { + return this.levels.iterator(); + } +@@ -470,11 +483,11 @@ + return this.resourcePath(LevelResource.OLD_LEVEL_DATA_FILE); + } + +- public Path corruptedDataFile(LocalDateTime localdatetime) { ++ public Path corruptedDataFile(LocalDateTime dateTime) { + Path path = this.path; + String s = LevelResource.LEVEL_DATA_FILE.getId(); + +- return path.resolve(s + "_corrupted_" + localdatetime.format(LevelStorageSource.FORMATTER)); ++ return path.resolve(s + "_corrupted_" + dateTime.format(LevelStorageSource.FORMATTER)); + } + + public Path rawDataFile(LocalDateTime localdatetime) { +@@ -492,19 +505,23 @@ + return this.resourcePath(LevelResource.LOCK_FILE); + } + +- public Path resourcePath(LevelResource levelresource) { +- return this.path.resolve(levelresource.getId()); ++ public Path resourcePath(LevelResource resource) { ++ return this.path.resolve(resource.getId()); + } + } + + public class LevelStorageAccess implements AutoCloseable { + + final DirectoryLock lock; +- final LevelStorageSource.LevelDirectory levelDirectory; ++ public final LevelStorageSource.LevelDirectory levelDirectory; + private final String levelId; + private final Map resources = Maps.newHashMap(); ++ // CraftBukkit start ++ public final ResourceKey dimensionType; + +- LevelStorageAccess(String s, Path path) throws IOException { ++ LevelStorageAccess(String s, Path path, ResourceKey dimensionType) throws IOException { ++ this.dimensionType = dimensionType; ++ // CraftBukkit end + this.levelId = s; + this.levelDirectory = new LevelStorageSource.LevelDirectory(path); + this.lock = DirectoryLock.create(path); +@@ -531,16 +548,16 @@ + return this.levelId; + } + +- public Path getLevelPath(LevelResource levelresource) { +- Map map = this.resources; +- LevelStorageSource.LevelDirectory levelstoragesource_leveldirectory = this.levelDirectory; ++ public Path getLevelPath(LevelResource folderName) { ++ Map map = this.resources; // CraftBukkit - decompile error ++ LevelStorageSource.LevelDirectory convertable_b = this.levelDirectory; + + Objects.requireNonNull(this.levelDirectory); +- return (Path) map.computeIfAbsent(levelresource, levelstoragesource_leveldirectory::resourcePath); ++ return (Path) map.computeIfAbsent(folderName, convertable_b::resourcePath); + } + +- public Path getDimensionPath(ResourceKey resourcekey) { +- return DimensionType.getStorageFolder(resourcekey, this.levelDirectory.path()); ++ public Path getDimensionPath(ResourceKey dimensionPath) { ++ return getStorageFolder(this.levelDirectory.path(), this.dimensionType); // CraftBukkit + } + + private void checkLock() { +@@ -572,25 +589,25 @@ + return LevelStorageSource.readLevelDataTagFixed(flag ? this.levelDirectory.oldDataFile() : this.levelDirectory.dataFile(), LevelStorageSource.this.fixerUpper); + } + +- public void saveDataTag(RegistryAccess registryaccess, WorldData worlddata) { +- this.saveDataTag(registryaccess, worlddata, (CompoundTag) null); ++ public void saveDataTag(RegistryAccess registries, WorldData serverConfiguration) { ++ this.saveDataTag(registries, serverConfiguration, (CompoundTag) null); + } + +- public void saveDataTag(RegistryAccess registryaccess, WorldData worlddata, @Nullable CompoundTag compoundtag) { +- CompoundTag compoundtag1 = worlddata.createTag(registryaccess, compoundtag); +- CompoundTag compoundtag2 = new CompoundTag(); ++ public void saveDataTag(RegistryAccess registries, WorldData serverConfiguration, @Nullable CompoundTag hostPlayerNBT) { ++ CompoundTag nbttagcompound1 = serverConfiguration.createTag(registries, hostPlayerNBT); ++ CompoundTag nbttagcompound2 = new CompoundTag(); + +- compoundtag2.put("Data", compoundtag1); +- this.saveLevelData(compoundtag2); ++ nbttagcompound2.put("Data", nbttagcompound1); ++ this.saveLevelData(nbttagcompound2); + } + +- private void saveLevelData(CompoundTag compoundtag) { ++ private void saveLevelData(CompoundTag nbttagcompound) { + Path path = this.levelDirectory.path(); + + try { + Path path1 = Files.createTempFile(path, "level", ".dat"); + +- NbtIo.writeCompressed(compoundtag, path1); ++ NbtIo.writeCompressed(nbttagcompound, path1); + Path path2 = this.levelDirectory.oldDataFile(); + Path path3 = this.levelDirectory.dataFile(); + +@@ -617,7 +634,6 @@ + + try { + Files.walkFileTree(this.levelDirectory.path(), new SimpleFileVisitor() { +- @Override + public FileVisitResult visitFile(Path path1, BasicFileAttributes basicfileattributes) throws IOException { + if (!path1.equals(path)) { + LevelStorageSource.LOGGER.debug("Deleting {}", path1); +@@ -627,7 +643,6 @@ + return FileVisitResult.CONTINUE; + } + +- @Override + public FileVisitResult postVisitDirectory(Path path1, @Nullable IOException ioexception) throws IOException { + if (ioexception != null) { + throw ioexception; +@@ -662,25 +677,25 @@ + + } + +- public void renameLevel(String s) throws IOException { +- this.modifyLevelDataWithoutDatafix((compoundtag) -> { +- compoundtag.putString("LevelName", s.trim()); ++ public void renameLevel(String saveName) throws IOException { ++ this.modifyLevelDataWithoutDatafix((nbttagcompound) -> { ++ nbttagcompound.putString("LevelName", saveName.trim()); + }); + } + + public void renameAndDropPlayer(String s) throws IOException { +- this.modifyLevelDataWithoutDatafix((compoundtag) -> { +- compoundtag.putString("LevelName", s.trim()); +- compoundtag.remove("Player"); ++ this.modifyLevelDataWithoutDatafix((nbttagcompound) -> { ++ nbttagcompound.putString("LevelName", s.trim()); ++ nbttagcompound.remove("Player"); + }); + } + + private void modifyLevelDataWithoutDatafix(Consumer consumer) throws IOException { + this.checkLock(); +- CompoundTag compoundtag = LevelStorageSource.readLevelDataTagRaw(this.levelDirectory.dataFile()); ++ CompoundTag nbttagcompound = LevelStorageSource.readLevelDataTagRaw(this.levelDirectory.dataFile()); + +- consumer.accept(compoundtag.getCompound("Data")); +- this.saveLevelData(compoundtag); ++ consumer.accept(nbttagcompound.getCompound("Data")); ++ this.saveLevelData(nbttagcompound); + } + + public long makeWorldBackup() throws IOException { +@@ -702,7 +717,6 @@ + final Path path2 = Paths.get(this.levelId); + + Files.walkFileTree(this.levelDirectory.path(), new SimpleFileVisitor() { +- @Override + public FileVisitResult visitFile(Path path3, BasicFileAttributes basicfileattributes) throws IOException { + if (path3.endsWith("session.lock")) { + return FileVisitResult.CONTINUE; +@@ -735,7 +749,6 @@ + return Files.exists(this.levelDirectory.dataFile(), new LinkOption[0]) || Files.exists(this.levelDirectory.oldDataFile(), new LinkOption[0]); + } + +- @Override + public void close() throws IOException { + this.lock.close(); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/PlayerDataStorage.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/PlayerDataStorage.java.patch new file mode 100644 index 0000000000..e7828d5233 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/PlayerDataStorage.java.patch @@ -0,0 +1,117 @@ +--- a/net/minecraft/world/level/storage/PlayerDataStorage.java ++++ b/net/minecraft/world/level/storage/PlayerDataStorage.java +@@ -11,29 +11,36 @@ + import net.minecraft.nbt.NbtAccounter; + import net.minecraft.nbt.NbtIo; + import net.minecraft.nbt.NbtUtils; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.datafix.DataFixTypes; + import net.minecraft.world.entity.player.Player; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.io.FileInputStream; ++import java.io.InputStream; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++// CraftBukkit end ++ + public class PlayerDataStorage { + + private static final Logger LOGGER = LogUtils.getLogger(); + private final File playerDir; + protected final DataFixer fixerUpper; + +- public PlayerDataStorage(LevelStorageSource.LevelStorageAccess levelstoragesource_levelstorageaccess, DataFixer datafixer) { +- this.fixerUpper = datafixer; +- this.playerDir = levelstoragesource_levelstorageaccess.getLevelPath(LevelResource.PLAYER_DATA_DIR).toFile(); ++ public PlayerDataStorage(LevelStorageSource.LevelStorageAccess levelStorageAccess, DataFixer fixerUpper) { ++ this.fixerUpper = fixerUpper; ++ this.playerDir = levelStorageAccess.getLevelPath(LevelResource.PLAYER_DATA_DIR).toFile(); + this.playerDir.mkdirs(); + } + + public void save(Player player) { + try { +- CompoundTag compoundtag = player.saveWithoutId(new CompoundTag()); ++ CompoundTag nbttagcompound = player.saveWithoutId(new CompoundTag()); + Path path = this.playerDir.toPath(); + Path path1 = Files.createTempFile(path, player.getStringUUID() + "-", ".dat"); + +- NbtIo.writeCompressed(compoundtag, path1); ++ NbtIo.writeCompressed(nbttagcompound, path1); + Path path2 = path.resolve(player.getStringUUID() + ".dat"); + Path path3 = path.resolve(player.getStringUUID() + ".dat_old"); + +@@ -46,28 +53,54 @@ + + @Nullable + public CompoundTag load(Player player) { +- CompoundTag compoundtag = null; ++ CompoundTag nbttagcompound = null; + + try { + File file = new File(this.playerDir, player.getStringUUID() + ".dat"); + + if (file.exists() && file.isFile()) { +- compoundtag = NbtIo.readCompressed(file.toPath(), NbtAccounter.unlimitedHeap()); ++ nbttagcompound = NbtIo.readCompressed(file.toPath(), NbtAccounter.unlimitedHeap()); + } + } catch (Exception exception) { + PlayerDataStorage.LOGGER.warn("Failed to load player data for {}", player.getName().getString()); + } + +- if (compoundtag != null) { +- int i = NbtUtils.getDataVersion(compoundtag, -1); ++ if (nbttagcompound != null) { ++ // CraftBukkit start ++ if (player instanceof ServerPlayer) { ++ CraftPlayer player = (CraftPlayer) player.getBukkitEntity(); ++ // Only update first played if it is older than the one we have ++ long modified = new File(this.playerDir, player.getUUID().toString() + ".dat").lastModified(); ++ if (modified < player.getFirstPlayed()) { ++ player.setFirstPlayed(modified); ++ } ++ } ++ // CraftBukkit end ++ int i = NbtUtils.getDataVersion(nbttagcompound, -1); + +- compoundtag = DataFixTypes.PLAYER.updateToCurrentVersion(this.fixerUpper, compoundtag, i); +- player.load(compoundtag); ++ nbttagcompound = DataFixTypes.PLAYER.updateToCurrentVersion(this.fixerUpper, nbttagcompound, i); ++ player.load(nbttagcompound); + } + +- return compoundtag; ++ return nbttagcompound; + } + ++ // CraftBukkit start ++ public CompoundTag getPlayerData(String s) { ++ try { ++ File file1 = new File(this.playerDir, s + ".dat"); ++ ++ if (file1.exists()) { ++ return NbtIo.readCompressed(file1.toPath(), NbtAccounter.unlimitedHeap()); ++ } ++ } catch (Exception exception) { ++ LOGGER.warn("Failed to load player data for " + s); ++ } ++ ++ return null; ++ } ++ // CraftBukkit end ++ + public String[] getSeenPlayers() { + String[] astring = this.playerDir.list(); + +@@ -83,4 +116,10 @@ + + return astring; + } ++ ++ // CraftBukkit start ++ public File getPlayerDir() { ++ return playerDir; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/PrimaryLevelData.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/PrimaryLevelData.java.patch new file mode 100644 index 0000000000..520a834034 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/PrimaryLevelData.java.patch @@ -0,0 +1,803 @@ +--- a/net/minecraft/world/level/storage/PrimaryLevelData.java ++++ b/net/minecraft/world/level/storage/PrimaryLevelData.java +@@ -19,16 +19,13 @@ + import net.minecraft.Util; + import net.minecraft.core.BlockPos; + import net.minecraft.core.HolderLookup; ++import net.minecraft.core.Registry; + import net.minecraft.core.RegistryAccess; + import net.minecraft.core.UUIDUtil; +-import net.minecraft.nbt.CompoundTag; +-import net.minecraft.nbt.ListTag; +-import net.minecraft.nbt.NbtOps; +-import net.minecraft.nbt.NbtUtils; +-import net.minecraft.nbt.StringTag; +-import net.minecraft.nbt.Tag; + import net.minecraft.resources.RegistryOps; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.Difficulty; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.GameType; +@@ -36,12 +33,26 @@ + import net.minecraft.world.level.LevelSettings; + import net.minecraft.world.level.WorldDataConfiguration; + import net.minecraft.world.level.border.WorldBorder; ++import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.dimension.end.EndDragonFight; +-import net.minecraft.world.level.levelgen.WorldGenSettings; + import net.minecraft.world.level.levelgen.WorldOptions; + import net.minecraft.world.level.timers.TimerCallbacks; + import net.minecraft.world.level.timers.TimerQueue; + import org.slf4j.Logger; ++import net.minecraft.core.registries.Registries; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; ++import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.NbtUtils; ++import net.minecraft.nbt.StringTag; ++import net.minecraft.nbt.Tag; ++import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; ++import net.minecraft.world.level.levelgen.WorldDimensions; ++import net.minecraft.world.level.levelgen.WorldGenSettings; ++import org.bukkit.Bukkit; ++import org.bukkit.event.weather.ThunderChangeEvent; ++import org.bukkit.event.weather.WeatherChangeEvent; ++// CraftBukkit end + + public class PrimaryLevelData implements ServerLevelData, WorldData { + +@@ -49,9 +60,9 @@ + public static final String LEVEL_NAME = "LevelName"; + protected static final String PLAYER = "Player"; + protected static final String WORLD_GEN_SETTINGS = "WorldGenSettings"; +- private LevelSettings settings; ++ public LevelSettings settings; + private final WorldOptions worldOptions; +- private final PrimaryLevelData.SpecialWorldProperty specialWorldProperty; ++ private final PrimaryLevelData.a specialWorldProperty; + private final Lifecycle worldGenSettingsLifecycle; + private int xSpawn; + private int ySpawn; +@@ -81,8 +92,22 @@ + private boolean wasModded; + private final Set removedFeatureFlags; + private final TimerQueue scheduledEvents; ++ // CraftBukkit start - Add world and pdc ++ public Registry customDimensions; ++ private ServerLevel world; ++ protected Tag pdc; + +- private PrimaryLevelData(@Nullable CompoundTag compoundtag, boolean flag, int i, int j, int k, float f, long l, long i1, int j1, int k1, int l1, boolean flag1, int i2, boolean flag2, boolean flag3, boolean flag4, WorldBorder.Settings worldborder_settings, int j2, int k2, @Nullable UUID uuid, Set set, Set set1, TimerQueue timerqueue, @Nullable CompoundTag compoundtag1, EndDragonFight.Data enddragonfight_data, LevelSettings levelsettings, WorldOptions worldoptions, PrimaryLevelData.SpecialWorldProperty primaryleveldata_specialworldproperty, Lifecycle lifecycle) { ++ public void setWorld(ServerLevel world) { ++ if (this.world != null) { ++ return; ++ } ++ this.world = world; ++ world.getWorld().readBukkitValues(pdc); ++ pdc = null; ++ } ++ // CraftBukkit end ++ ++ private PrimaryLevelData(@Nullable CompoundTag nbttagcompound, boolean flag, int i, int j, int k, float f, long l, long i1, int j1, int k1, int l1, boolean flag1, int i2, boolean flag2, boolean flag3, boolean flag4, WorldBorder.Settings worldborder_c, int j2, int k2, @Nullable UUID uuid, Set set, Set set1, TimerQueue customfunctioncallbacktimerqueue, @Nullable CompoundTag nbttagcompound1, EndDragonFight.Data enderdragonbattle_a, LevelSettings worldsettings, WorldOptions worldoptions, PrimaryLevelData.a worlddataserver_a, Lifecycle lifecycle) { + this.wasModded = flag; + this.xSpawn = i; + this.ySpawn = j; +@@ -98,29 +123,29 @@ + this.thundering = flag2; + this.initialized = flag3; + this.difficultyLocked = flag4; +- this.worldBorder = worldborder_settings; ++ this.worldBorder = worldborder_c; + this.wanderingTraderSpawnDelay = j2; + this.wanderingTraderSpawnChance = k2; + this.wanderingTraderId = uuid; + this.knownServerBrands = set; + this.removedFeatureFlags = set1; +- this.loadedPlayerTag = compoundtag; +- this.scheduledEvents = timerqueue; +- this.customBossEvents = compoundtag1; +- this.endDragonFightData = enddragonfight_data; +- this.settings = levelsettings; ++ this.loadedPlayerTag = nbttagcompound; ++ this.scheduledEvents = customfunctioncallbacktimerqueue; ++ this.customBossEvents = nbttagcompound1; ++ this.endDragonFightData = enderdragonbattle_a; ++ this.settings = worldsettings; + this.worldOptions = worldoptions; +- this.specialWorldProperty = primaryleveldata_specialworldproperty; ++ this.specialWorldProperty = worlddataserver_a; + this.worldGenSettingsLifecycle = lifecycle; + } + +- public PrimaryLevelData(LevelSettings levelsettings, WorldOptions worldoptions, PrimaryLevelData.SpecialWorldProperty primaryleveldata_specialworldproperty, Lifecycle lifecycle) { +- this((CompoundTag) null, false, 0, 0, 0, 0.0F, 0L, 0L, 19133, 0, 0, false, 0, false, false, false, WorldBorder.DEFAULT_SETTINGS, 0, 0, (UUID) null, Sets.newLinkedHashSet(), new HashSet(), new TimerQueue<>(TimerCallbacks.SERVER_CALLBACKS), (CompoundTag) null, EndDragonFight.Data.DEFAULT, levelsettings.copy(), worldoptions, primaryleveldata_specialworldproperty, lifecycle); ++ public PrimaryLevelData(LevelSettings settings, WorldOptions worldOptions, PrimaryLevelData.a specialWorldProperty, Lifecycle worldGenSettingsLifecycle) { ++ this((CompoundTag) null, false, 0, 0, 0, 0.0F, 0L, 0L, 19133, 0, 0, false, 0, false, false, false, WorldBorder.DEFAULT_SETTINGS, 0, 0, (UUID) null, Sets.newLinkedHashSet(), new HashSet(), new TimerQueue<>(TimerCallbacks.SERVER_CALLBACKS), (CompoundTag) null, EndDragonFight.Data.DEFAULT, settings.copy(), worldOptions, specialWorldProperty, worldGenSettingsLifecycle); + } + +- public static PrimaryLevelData parse(Dynamic dynamic, LevelSettings levelsettings, PrimaryLevelData.SpecialWorldProperty primaryleveldata_specialworldproperty, WorldOptions worldoptions, Lifecycle lifecycle) { ++ public static PrimaryLevelData parse(Dynamic dynamic, LevelSettings worldsettings, PrimaryLevelData.a worlddataserver_a, WorldOptions worldoptions, Lifecycle lifecycle) { + long i = dynamic.get("Time").asLong(0L); +- CompoundTag compoundtag = (CompoundTag) CompoundTag.CODEC.parse(dynamic.get("Player").orElseEmptyMap()).result().orElse((Object) null); ++ CompoundTag nbttagcompound = (CompoundTag) CompoundTag.CODEC.parse(dynamic.get("Player").orElseEmptyMap()).result().orElse(null); // CraftBukkit - decompile error + boolean flag = dynamic.get("WasModded").asBoolean(false); + int j = dynamic.get("SpawnX").asInt(0); + int k = dynamic.get("SpawnY").asInt(0); +@@ -135,509 +160,489 @@ + boolean flag2 = dynamic.get("thundering").asBoolean(false); + boolean flag3 = dynamic.get("initialized").asBoolean(true); + boolean flag4 = dynamic.get("DifficultyLocked").asBoolean(false); +- WorldBorder.Settings worldborder_settings = WorldBorder.Settings.read(dynamic, WorldBorder.DEFAULT_SETTINGS); ++ WorldBorder.Settings worldborder_c = WorldBorder.Settings.read(dynamic, WorldBorder.DEFAULT_SETTINGS); + int j2 = dynamic.get("WanderingTraderSpawnDelay").asInt(0); + int k2 = dynamic.get("WanderingTraderSpawnChance").asInt(0); +- UUID uuid = (UUID) dynamic.get("WanderingTraderId").read(UUIDUtil.CODEC).result().orElse((Object) null); ++ UUID uuid = (UUID) dynamic.get("WanderingTraderId").read(UUIDUtil.CODEC).result().orElse(null); // CraftBukkit - decompile error + Set set = (Set) dynamic.get("ServerBrands").asStream().flatMap((dynamic1) -> { + return dynamic1.asString().result().stream(); + }).collect(Collectors.toCollection(Sets::newLinkedHashSet)); + Set set1 = (Set) dynamic.get("removed_features").asStream().flatMap((dynamic1) -> { + return dynamic1.asString().result().stream(); + }).collect(Collectors.toSet()); +- TimerQueue timerqueue = new TimerQueue<>(TimerCallbacks.SERVER_CALLBACKS, dynamic.get("ScheduledEvents").asStream()); +- CompoundTag compoundtag1 = (CompoundTag) dynamic.get("CustomBossEvents").orElseEmptyMap().getValue(); +- DataResult dataresult = dynamic.get("DragonFight").read(EndDragonFight.Data.CODEC); ++ TimerQueue customfunctioncallbacktimerqueue = new TimerQueue<>(TimerCallbacks.SERVER_CALLBACKS, dynamic.get("ScheduledEvents").asStream()); ++ CompoundTag nbttagcompound1 = (CompoundTag) dynamic.get("CustomBossEvents").orElseEmptyMap().getValue(); ++ DataResult dataresult = dynamic.get("DragonFight").read(EndDragonFight.Data.CODEC); // CraftBukkit - decompile error + Logger logger = PrimaryLevelData.LOGGER; + + Objects.requireNonNull(logger); +- return new PrimaryLevelData(compoundtag, flag, j, k, l, f, i, i1, j1, k1, l1, flag1, i2, flag2, flag3, flag4, worldborder_settings, j2, k2, uuid, set, set1, timerqueue, compoundtag1, (EndDragonFight.Data) dataresult.resultOrPartial(logger::error).orElse(EndDragonFight.Data.DEFAULT), levelsettings, worldoptions, primaryleveldata_specialworldproperty, lifecycle); ++ return new PrimaryLevelData(nbttagcompound, flag, j, k, l, f, i, i1, j1, k1, l1, flag1, i2, flag2, flag3, flag4, worldborder_c, j2, k2, uuid, set, set1, customfunctioncallbacktimerqueue, nbttagcompound1, (EndDragonFight.Data) dataresult.resultOrPartial(logger::error).orElse(EndDragonFight.Data.DEFAULT), worldsettings, worldoptions, worlddataserver_a, lifecycle); + } + + @Override +- @Override +- public CompoundTag createTag(RegistryAccess registryaccess, @Nullable CompoundTag compoundtag) { +- if (compoundtag == null) { +- compoundtag = this.loadedPlayerTag; ++ public CompoundTag createTag(RegistryAccess registries, @Nullable CompoundTag hostPlayerNBT) { ++ if (hostPlayerNBT == null) { ++ hostPlayerNBT = this.loadedPlayerTag; + } + +- CompoundTag compoundtag1 = new CompoundTag(); ++ CompoundTag nbttagcompound1 = new CompoundTag(); + +- this.setTagData(registryaccess, compoundtag1, compoundtag); +- return compoundtag1; ++ this.setTagData(registries, nbttagcompound1, hostPlayerNBT); ++ return nbttagcompound1; + } + +- private void setTagData(RegistryAccess registryaccess, CompoundTag compoundtag, @Nullable CompoundTag compoundtag1) { +- compoundtag.put("ServerBrands", stringCollectionToTag(this.knownServerBrands)); +- compoundtag.putBoolean("WasModded", this.wasModded); ++ private void setTagData(RegistryAccess registry, CompoundTag nbt, @Nullable CompoundTag playerNBT) { ++ nbt.put("ServerBrands", stringCollectionToTag(this.knownServerBrands)); ++ nbt.putBoolean("WasModded", this.wasModded); + if (!this.removedFeatureFlags.isEmpty()) { +- compoundtag.put("removed_features", stringCollectionToTag(this.removedFeatureFlags)); ++ nbt.put("removed_features", stringCollectionToTag(this.removedFeatureFlags)); + } + +- CompoundTag compoundtag2 = new CompoundTag(); ++ CompoundTag nbttagcompound2 = new CompoundTag(); + +- compoundtag2.putString("Name", SharedConstants.getCurrentVersion().getName()); +- compoundtag2.putInt("Id", SharedConstants.getCurrentVersion().getDataVersion().getVersion()); +- compoundtag2.putBoolean("Snapshot", !SharedConstants.getCurrentVersion().isStable()); +- compoundtag2.putString("Series", SharedConstants.getCurrentVersion().getDataVersion().getSeries()); +- compoundtag.put("Version", compoundtag2); +- NbtUtils.addCurrentDataVersion(compoundtag); +- DynamicOps dynamicops = RegistryOps.create(NbtOps.INSTANCE, (HolderLookup.Provider) registryaccess); +- DataResult dataresult = WorldGenSettings.encode(dynamicops, this.worldOptions, registryaccess); ++ nbttagcompound2.putString("Name", SharedConstants.getCurrentVersion().getName()); ++ nbttagcompound2.putInt("Id", SharedConstants.getCurrentVersion().getDataVersion().getVersion()); ++ nbttagcompound2.putBoolean("Snapshot", !SharedConstants.getCurrentVersion().isStable()); ++ nbttagcompound2.putString("Series", SharedConstants.getCurrentVersion().getDataVersion().getSeries()); ++ nbt.put("Version", nbttagcompound2); ++ NbtUtils.addCurrentDataVersion(nbt); ++ DynamicOps dynamicops = RegistryOps.create(NbtOps.INSTANCE, (HolderLookup.Provider) registry); ++ DataResult dataresult = WorldGenSettings.encode(dynamicops, this.worldOptions, new WorldDimensions(this.customDimensions != null ? this.customDimensions : registry.registryOrThrow(Registries.LEVEL_STEM))); // CraftBukkit + Logger logger = PrimaryLevelData.LOGGER; + + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(Util.prefix("WorldGenSettings: ", logger::error)).ifPresent((tag) -> { +- compoundtag.put("WorldGenSettings", tag); ++ dataresult.resultOrPartial(Util.prefix("WorldGenSettings: ", logger::error)).ifPresent((nbtbase) -> { ++ nbt.put("WorldGenSettings", nbtbase); + }); +- compoundtag.putInt("GameType", this.settings.gameType().getId()); +- compoundtag.putInt("SpawnX", this.xSpawn); +- compoundtag.putInt("SpawnY", this.ySpawn); +- compoundtag.putInt("SpawnZ", this.zSpawn); +- compoundtag.putFloat("SpawnAngle", this.spawnAngle); +- compoundtag.putLong("Time", this.gameTime); +- compoundtag.putLong("DayTime", this.dayTime); +- compoundtag.putLong("LastPlayed", Util.getEpochMillis()); +- compoundtag.putString("LevelName", this.settings.levelName()); +- compoundtag.putInt("version", 19133); +- compoundtag.putInt("clearWeatherTime", this.clearWeatherTime); +- compoundtag.putInt("rainTime", this.rainTime); +- compoundtag.putBoolean("raining", this.raining); +- compoundtag.putInt("thunderTime", this.thunderTime); +- compoundtag.putBoolean("thundering", this.thundering); +- compoundtag.putBoolean("hardcore", this.settings.hardcore()); +- compoundtag.putBoolean("allowCommands", this.settings.allowCommands()); +- compoundtag.putBoolean("initialized", this.initialized); +- this.worldBorder.write(compoundtag); +- compoundtag.putByte("Difficulty", (byte) this.settings.difficulty().getId()); +- compoundtag.putBoolean("DifficultyLocked", this.difficultyLocked); +- compoundtag.put("GameRules", this.settings.gameRules().createTag()); +- compoundtag.put("DragonFight", (Tag) Util.getOrThrow(EndDragonFight.Data.CODEC.encodeStart(NbtOps.INSTANCE, this.endDragonFightData), IllegalStateException::new)); +- if (compoundtag1 != null) { +- compoundtag.put("Player", compoundtag1); ++ nbt.putInt("GameType", this.settings.gameType().getId()); ++ nbt.putInt("SpawnX", this.xSpawn); ++ nbt.putInt("SpawnY", this.ySpawn); ++ nbt.putInt("SpawnZ", this.zSpawn); ++ nbt.putFloat("SpawnAngle", this.spawnAngle); ++ nbt.putLong("Time", this.gameTime); ++ nbt.putLong("DayTime", this.dayTime); ++ nbt.putLong("LastPlayed", Util.getEpochMillis()); ++ nbt.putString("LevelName", this.settings.levelName()); ++ nbt.putInt("version", 19133); ++ nbt.putInt("clearWeatherTime", this.clearWeatherTime); ++ nbt.putInt("rainTime", this.rainTime); ++ nbt.putBoolean("raining", this.raining); ++ nbt.putInt("thunderTime", this.thunderTime); ++ nbt.putBoolean("thundering", this.thundering); ++ nbt.putBoolean("hardcore", this.settings.hardcore()); ++ nbt.putBoolean("allowCommands", this.settings.allowCommands()); ++ nbt.putBoolean("initialized", this.initialized); ++ this.worldBorder.write(nbt); ++ nbt.putByte("Difficulty", (byte) this.settings.difficulty().getId()); ++ nbt.putBoolean("DifficultyLocked", this.difficultyLocked); ++ nbt.put("GameRules", this.settings.gameRules().createTag()); ++ nbt.put("DragonFight", (Tag) Util.getOrThrow(EndDragonFight.Data.CODEC.encodeStart(NbtOps.INSTANCE, this.endDragonFightData), IllegalStateException::new)); ++ if (playerNBT != null) { ++ nbt.put("Player", playerNBT); + } + + DataResult dataresult1 = WorldDataConfiguration.CODEC.encodeStart(NbtOps.INSTANCE, this.settings.getDataConfiguration()); + +- dataresult1.get().ifLeft((tag) -> { +- compoundtag.merge((CompoundTag) tag); ++ dataresult1.get().ifLeft((nbtbase) -> { ++ nbt.merge((CompoundTag) nbtbase); + }).ifRight((partialresult) -> { + PrimaryLevelData.LOGGER.warn("Failed to encode configuration {}", partialresult.message()); + }); + if (this.customBossEvents != null) { +- compoundtag.put("CustomBossEvents", this.customBossEvents); ++ nbt.put("CustomBossEvents", this.customBossEvents); + } + +- compoundtag.put("ScheduledEvents", this.scheduledEvents.store()); +- compoundtag.putInt("WanderingTraderSpawnDelay", this.wanderingTraderSpawnDelay); +- compoundtag.putInt("WanderingTraderSpawnChance", this.wanderingTraderSpawnChance); ++ nbt.put("ScheduledEvents", this.scheduledEvents.store()); ++ nbt.putInt("WanderingTraderSpawnDelay", this.wanderingTraderSpawnDelay); ++ nbt.putInt("WanderingTraderSpawnChance", this.wanderingTraderSpawnChance); + if (this.wanderingTraderId != null) { +- compoundtag.putUUID("WanderingTraderId", this.wanderingTraderId); ++ nbt.putUUID("WanderingTraderId", this.wanderingTraderId); + } + ++ nbt.putString("Bukkit.Version", Bukkit.getName() + "/" + Bukkit.getVersion() + "/" + Bukkit.getBukkitVersion()); // CraftBukkit ++ world.getWorld().storeBukkitValues(nbt); // CraftBukkit - add pdc + } + +- private static ListTag stringCollectionToTag(Set set) { +- ListTag listtag = new ListTag(); +- Stream stream = set.stream().map(StringTag::valueOf); ++ private static ListTag stringCollectionToTag(Set stringCollection) { ++ ListTag nbttaglist = new ListTag(); ++ Stream stream = stringCollection.stream().map(StringTag::valueOf); // CraftBukkit - decompile error + +- Objects.requireNonNull(listtag); +- stream.forEach(listtag::add); +- return listtag; ++ Objects.requireNonNull(nbttaglist); ++ stream.forEach(nbttaglist::add); ++ return nbttaglist; + } + + @Override +- @Override + public int getXSpawn() { + return this.xSpawn; + } + + @Override +- @Override + public int getYSpawn() { + return this.ySpawn; + } + + @Override +- @Override + public int getZSpawn() { + return this.zSpawn; + } + + @Override +- @Override + public float getSpawnAngle() { + return this.spawnAngle; + } + + @Override +- @Override + public long getGameTime() { + return this.gameTime; + } + + @Override +- @Override + public long getDayTime() { + return this.dayTime; + } + + @Nullable + @Override +- @Override + public CompoundTag getLoadedPlayerTag() { + return this.loadedPlayerTag; + } + + @Override +- @Override +- public void setXSpawn(int i) { +- this.xSpawn = i; ++ public void setXSpawn(int x) { ++ this.xSpawn = x; + } + + @Override +- @Override +- public void setYSpawn(int i) { +- this.ySpawn = i; ++ public void setYSpawn(int y) { ++ this.ySpawn = y; + } + + @Override +- @Override +- public void setZSpawn(int i) { +- this.zSpawn = i; ++ public void setZSpawn(int z) { ++ this.zSpawn = z; + } + + @Override +- @Override +- public void setSpawnAngle(float f) { +- this.spawnAngle = f; ++ public void setSpawnAngle(float angle) { ++ this.spawnAngle = angle; + } + + @Override +- @Override +- public void setGameTime(long i) { +- this.gameTime = i; ++ public void setGameTime(long time) { ++ this.gameTime = time; + } + + @Override +- @Override +- public void setDayTime(long i) { +- this.dayTime = i; ++ public void setDayTime(long time) { ++ this.dayTime = time; + } + + @Override +- @Override +- public void setSpawn(BlockPos blockpos, float f) { +- this.xSpawn = blockpos.getX(); +- this.ySpawn = blockpos.getY(); +- this.zSpawn = blockpos.getZ(); +- this.spawnAngle = f; ++ public void setSpawn(BlockPos spawnPoint, float angle) { ++ this.xSpawn = spawnPoint.getX(); ++ this.ySpawn = spawnPoint.getY(); ++ this.zSpawn = spawnPoint.getZ(); ++ this.spawnAngle = angle; + } + + @Override +- @Override + public String getLevelName() { + return this.settings.levelName(); + } + + @Override +- @Override + public int getVersion() { + return this.version; + } + + @Override +- @Override + public int getClearWeatherTime() { + return this.clearWeatherTime; + } + + @Override +- @Override +- public void setClearWeatherTime(int i) { +- this.clearWeatherTime = i; ++ public void setClearWeatherTime(int time) { ++ this.clearWeatherTime = time; + } + + @Override +- @Override + public boolean isThundering() { + return this.thundering; + } + + @Override +- @Override +- public void setThundering(boolean flag) { +- this.thundering = flag; ++ public void setThundering(boolean thundering) { ++ // CraftBukkit start ++ if (this.thundering == thundering) { ++ return; ++ } ++ ++ org.bukkit.World world = Bukkit.getWorld(getLevelName()); ++ if (world != null) { ++ ThunderChangeEvent thunder = new ThunderChangeEvent(world, thundering); ++ Bukkit.getServer().getPluginManager().callEvent(thunder); ++ if (thunder.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ this.thundering = thundering; + } + + @Override +- @Override + public int getThunderTime() { + return this.thunderTime; + } + + @Override +- @Override +- public void setThunderTime(int i) { +- this.thunderTime = i; ++ public void setThunderTime(int time) { ++ this.thunderTime = time; + } + + @Override +- @Override + public boolean isRaining() { + return this.raining; + } + + @Override +- @Override +- public void setRaining(boolean flag) { +- this.raining = flag; ++ public void setRaining(boolean isRaining) { ++ // CraftBukkit start ++ if (this.raining == isRaining) { ++ return; ++ } ++ ++ org.bukkit.World world = Bukkit.getWorld(getLevelName()); ++ if (world != null) { ++ WeatherChangeEvent weather = new WeatherChangeEvent(world, isRaining); ++ Bukkit.getServer().getPluginManager().callEvent(weather); ++ if (weather.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ this.raining = isRaining; + } + + @Override +- @Override + public int getRainTime() { + return this.rainTime; + } + + @Override +- @Override +- public void setRainTime(int i) { +- this.rainTime = i; ++ public void setRainTime(int time) { ++ this.rainTime = time; + } + + @Override +- @Override + public GameType getGameType() { + return this.settings.gameType(); + } + + @Override +- @Override +- public void setGameType(GameType gametype) { +- this.settings = this.settings.withGameType(gametype); ++ public void setGameType(GameType type) { ++ this.settings = this.settings.withGameType(type); + } + + @Override +- @Override + public boolean isHardcore() { + return this.settings.hardcore(); + } + + @Override +- @Override + public boolean getAllowCommands() { + return this.settings.allowCommands(); + } + + @Override +- @Override + public boolean isInitialized() { + return this.initialized; + } + + @Override +- @Override +- public void setInitialized(boolean flag) { +- this.initialized = flag; ++ public void setInitialized(boolean initialized) { ++ this.initialized = initialized; + } + + @Override +- @Override + public GameRules getGameRules() { + return this.settings.gameRules(); + } + + @Override +- @Override + public WorldBorder.Settings getWorldBorder() { + return this.worldBorder; + } + + @Override +- @Override +- public void setWorldBorder(WorldBorder.Settings worldborder_settings) { +- this.worldBorder = worldborder_settings; ++ public void setWorldBorder(WorldBorder.Settings serializer) { ++ this.worldBorder = serializer; + } + + @Override +- @Override + public Difficulty getDifficulty() { + return this.settings.difficulty(); + } + + @Override +- @Override + public void setDifficulty(Difficulty difficulty) { + this.settings = this.settings.withDifficulty(difficulty); ++ // CraftBukkit start ++ ClientboundChangeDifficultyPacket packet = new ClientboundChangeDifficultyPacket(this.getDifficulty(), this.isDifficultyLocked()); ++ for (ServerPlayer player : (java.util.List) (java.util.List) world.players()) { ++ player.connection.send(packet); ++ } ++ // CraftBukkit end + } + + @Override +- @Override + public boolean isDifficultyLocked() { + return this.difficultyLocked; + } + + @Override +- @Override +- public void setDifficultyLocked(boolean flag) { +- this.difficultyLocked = flag; ++ public void setDifficultyLocked(boolean locked) { ++ this.difficultyLocked = locked; + } + + @Override +- @Override + public TimerQueue getScheduledEvents() { + return this.scheduledEvents; + } + + @Override +- @Override +- public void fillCrashReportCategory(CrashReportCategory crashreportcategory, LevelHeightAccessor levelheightaccessor) { +- ServerLevelData.super.fillCrashReportCategory(crashreportcategory, levelheightaccessor); +- WorldData.super.fillCrashReportCategory(crashreportcategory); ++ public void fillCrashReportCategory(CrashReportCategory crashReportCategory, LevelHeightAccessor level) { ++ ServerLevelData.super.fillCrashReportCategory(crashReportCategory, level); ++ WorldData.super.fillCrashReportCategory(crashReportCategory); + } + + @Override +- @Override + public WorldOptions worldGenOptions() { + return this.worldOptions; + } + + @Override +- @Override + public boolean isFlatWorld() { +- return this.specialWorldProperty == PrimaryLevelData.SpecialWorldProperty.FLAT; ++ return this.specialWorldProperty == PrimaryLevelData.a.FLAT; + } + + @Override +- @Override + public boolean isDebugWorld() { +- return this.specialWorldProperty == PrimaryLevelData.SpecialWorldProperty.DEBUG; ++ return this.specialWorldProperty == PrimaryLevelData.a.DEBUG; + } + + @Override +- @Override + public Lifecycle worldGenSettingsLifecycle() { + return this.worldGenSettingsLifecycle; + } + + @Override +- @Override + public EndDragonFight.Data endDragonFightData() { + return this.endDragonFightData; + } + + @Override +- @Override +- public void setEndDragonFightData(EndDragonFight.Data enddragonfight_data) { +- this.endDragonFightData = enddragonfight_data; ++ public void setEndDragonFightData(EndDragonFight.Data endDragonFightData) { ++ this.endDragonFightData = endDragonFightData; + } + + @Override +- @Override + public WorldDataConfiguration getDataConfiguration() { + return this.settings.getDataConfiguration(); + } + + @Override +- @Override +- public void setDataConfiguration(WorldDataConfiguration worlddataconfiguration) { +- this.settings = this.settings.withDataConfiguration(worlddataconfiguration); ++ public void setDataConfiguration(WorldDataConfiguration dataConfiguration) { ++ this.settings = this.settings.withDataConfiguration(dataConfiguration); + } + + @Nullable + @Override +- @Override + public CompoundTag getCustomBossEvents() { + return this.customBossEvents; + } + + @Override +- @Override +- public void setCustomBossEvents(@Nullable CompoundTag compoundtag) { +- this.customBossEvents = compoundtag; ++ public void setCustomBossEvents(@Nullable CompoundTag nbt) { ++ this.customBossEvents = nbt; + } + + @Override +- @Override + public int getWanderingTraderSpawnDelay() { + return this.wanderingTraderSpawnDelay; + } + + @Override +- @Override +- public void setWanderingTraderSpawnDelay(int i) { +- this.wanderingTraderSpawnDelay = i; ++ public void setWanderingTraderSpawnDelay(int delay) { ++ this.wanderingTraderSpawnDelay = delay; + } + + @Override +- @Override + public int getWanderingTraderSpawnChance() { + return this.wanderingTraderSpawnChance; + } + + @Override +- @Override +- public void setWanderingTraderSpawnChance(int i) { +- this.wanderingTraderSpawnChance = i; ++ public void setWanderingTraderSpawnChance(int chance) { ++ this.wanderingTraderSpawnChance = chance; + } + + @Nullable + @Override +- @Override + public UUID getWanderingTraderId() { + return this.wanderingTraderId; + } + + @Override +- @Override +- public void setWanderingTraderId(UUID uuid) { +- this.wanderingTraderId = uuid; ++ public void setWanderingTraderId(UUID id) { ++ this.wanderingTraderId = id; + } + + @Override +- @Override +- public void setModdedInfo(String s, boolean flag) { +- this.knownServerBrands.add(s); +- this.wasModded |= flag; ++ public void setModdedInfo(String name, boolean isModded) { ++ this.knownServerBrands.add(name); ++ this.wasModded |= isModded; + } + + @Override +- @Override + public boolean wasModded() { + return this.wasModded; + } + + @Override +- @Override + public Set getKnownServerBrands() { + return ImmutableSet.copyOf(this.knownServerBrands); + } + + @Override +- @Override + public Set getRemovedFeatureFlags() { + return Set.copyOf(this.removedFeatureFlags); + } + + @Override +- @Override + public ServerLevelData overworldData() { + return this; + } + + @Override +- @Override + public LevelSettings getLevelSettings() { + return this.settings.copy(); + } + ++ // CraftBukkit start - Check if the name stored in NBT is the correct one ++ public void checkName(String name) { ++ if (!this.settings.levelName.equals(name)) { ++ this.settings.levelName = name; ++ } ++ } ++ // CraftBukkit end ++ + /** @deprecated */ + @Deprecated +- public static enum SpecialWorldProperty { ++ public static enum a { + + NONE, FLAT, DEBUG; + +- private SpecialWorldProperty() {} ++ private a() {} + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/loot/LootDataManager.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/loot/LootDataManager.java.patch new file mode 100644 index 0000000000..15dcf3c202 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/loot/LootDataManager.java.patch @@ -0,0 +1,136 @@ +--- a/net/minecraft/world/level/storage/loot/LootDataManager.java ++++ b/net/minecraft/world/level/storage/loot/LootDataManager.java +@@ -22,6 +22,8 @@ + import net.minecraft.util.ProblemReporter; + import net.minecraft.util.profiling.ProfilerFiller; + import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; ++import org.bukkit.craftbukkit.CraftLootTable; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; + import org.slf4j.Logger; + + public class LootDataManager implements PreparableReloadListener, LootDataResolver { +@@ -35,40 +37,39 @@ + public LootDataManager() {} + + @Override +- @Override +- public final CompletableFuture reload(PreparableReloadListener.PreparationBarrier preparablereloadlistener_preparationbarrier, ResourceManager resourcemanager, ProfilerFiller profilerfiller, ProfilerFiller profilerfiller1, Executor executor, Executor executor1) { ++ public final CompletableFuture reload(PreparableReloadListener.PreparationBarrier preparationBarrier, ResourceManager resourceManager, ProfilerFiller preparationsProfiler, ProfilerFiller reloadProfiler, Executor backgroundExecutor, Executor gameExecutor) { + Map, Map> map = new HashMap(); + CompletableFuture[] acompletablefuture = (CompletableFuture[]) LootDataType.values().map((lootdatatype) -> { +- return scheduleElementParse(lootdatatype, resourcemanager, executor, map); ++ return scheduleElementParse(lootdatatype, resourceManager, backgroundExecutor, map); + }).toArray((i) -> { + return new CompletableFuture[i]; + }); + CompletableFuture completablefuture = CompletableFuture.allOf(acompletablefuture); + +- Objects.requireNonNull(preparablereloadlistener_preparationbarrier); +- return completablefuture.thenCompose(preparablereloadlistener_preparationbarrier::wait).thenAcceptAsync((ovoid) -> { ++ Objects.requireNonNull(preparationBarrier); ++ return completablefuture.thenCompose(preparationBarrier::wait).thenAcceptAsync((ovoid) -> { + this.apply(map); +- }, executor1); ++ }, gameExecutor); + } + +- private static CompletableFuture scheduleElementParse(LootDataType lootdatatype, ResourceManager resourcemanager, Executor executor, Map, Map> map) { ++ private static CompletableFuture scheduleElementParse(LootDataType lootDataType, ResourceManager resourceManager, Executor backgroundExecutor, Map, Map> elementCollector) { + Map map1 = new HashMap(); + +- map.put(lootdatatype, map1); ++ elementCollector.put(lootDataType, map1); + return CompletableFuture.runAsync(() -> { + Map map2 = new HashMap(); + +- SimpleJsonResourceReloadListener.scanDirectory(resourcemanager, lootdatatype.directory(), LootDataManager.GSON, map2); +- map2.forEach((resourcelocation, jsonelement) -> { +- lootdatatype.deserialize(resourcelocation, jsonelement).ifPresent((object) -> { +- map1.put(resourcelocation, object); ++ SimpleJsonResourceReloadListener.scanDirectory(resourceManager, lootDataType.directory(), LootDataManager.GSON, map2); ++ map2.forEach((minecraftkey, jsonelement) -> { ++ lootDataType.deserialize(minecraftkey, jsonelement).ifPresent((object) -> { ++ map1.put(minecraftkey, object); + }); + }); +- }, executor); ++ }, backgroundExecutor); + } + +- private void apply(Map, Map> map) { +- Object object = ((Map) map.get(LootDataType.TABLE)).remove(BuiltInLootTables.EMPTY); ++ private void apply(Map, Map> collectedElements) { ++ Object object = ((Map) collectedElements.get(LootDataType.TABLE)).remove(BuiltInLootTables.EMPTY); + + if (object != null) { + LootDataManager.LOGGER.warn("Datapack tried to redefine {} loot table, ignoring", BuiltInLootTables.EMPTY); +@@ -77,46 +78,51 @@ + Builder, Object> builder = ImmutableMap.builder(); + com.google.common.collect.ImmutableMultimap.Builder, ResourceLocation> com_google_common_collect_immutablemultimap_builder = ImmutableMultimap.builder(); + +- map.forEach((lootdatatype, map1) -> { +- map1.forEach((resourcelocation, object1) -> { +- builder.put(new LootDataId<>(lootdatatype, resourcelocation), object1); +- com_google_common_collect_immutablemultimap_builder.put(lootdatatype, resourcelocation); ++ collectedElements.forEach((lootdatatype, map1) -> { ++ map1.forEach((minecraftkey, object1) -> { ++ builder.put(new LootDataId<>(lootdatatype, minecraftkey), object1); ++ com_google_common_collect_immutablemultimap_builder.put(lootdatatype, minecraftkey); + }); + }); + builder.put(LootDataManager.EMPTY_LOOT_TABLE_KEY, LootTable.EMPTY); +- ProblemReporter.Collector problemreporter_collector = new ProblemReporter.Collector(); ++ ProblemReporter.a problemreporter_a = new ProblemReporter.a(); + final Map, ?> map1 = builder.build(); +- ValidationContext validationcontext = new ValidationContext(problemreporter_collector, LootContextParamSets.ALL_PARAMS, new LootDataResolver() { ++ ValidationContext lootcollector = new ValidationContext(problemreporter_a, LootContextParamSets.ALL_PARAMS, new LootDataResolver() { + @Nullable + @Override +- @Override +- public T getElement(LootDataId lootdataid) { +- return map1.get(lootdataid); ++ public T getElement(LootDataId id) { ++ return (T) map1.get(id); // CraftBukkit - decompile error + } + }); + + map1.forEach((lootdataid, object1) -> { +- castAndValidate(validationcontext, lootdataid, object1); ++ castAndValidate(lootcollector, lootdataid, object1); + }); +- problemreporter_collector.get().forEach((s, s1) -> { ++ problemreporter_a.get().forEach((s, s1) -> { + LootDataManager.LOGGER.warn("Found loot table element validation problem in {}: {}", s, s1); + }); ++ // CraftBukkit start ++ map1.forEach((key, lootTable) -> { ++ if (object instanceof LootTable table) { ++ table.craftLootTable = new CraftLootTable(CraftNamespacedKey.fromMinecraft(key.location()), table); ++ } ++ }); ++ // CraftBukkit end + this.elements = map1; + this.typeKeys = com_google_common_collect_immutablemultimap_builder.build(); + } + +- private static void castAndValidate(ValidationContext validationcontext, LootDataId lootdataid, Object object) { +- lootdataid.type().runValidation(validationcontext, lootdataid, object); ++ private static void castAndValidate(ValidationContext context, LootDataId id, Object element) { ++ id.type().runValidation(context, id, (T) element); // CraftBukkit - decompile error + } + + @Nullable + @Override +- @Override +- public T getElement(LootDataId lootdataid) { +- return this.elements.get(lootdataid); ++ public T getElement(LootDataId id) { ++ return (T) this.elements.get(id); // CraftBukkit - decompile error + } + +- public Collection getKeys(LootDataType lootdatatype) { +- return this.typeKeys.get(lootdatatype); ++ public Collection getKeys(LootDataType type) { ++ return this.typeKeys.get(type); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/loot/LootTable.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/loot/LootTable.java.patch new file mode 100644 index 0000000000..6df5c365d2 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/loot/LootTable.java.patch @@ -0,0 +1,308 @@ +--- a/net/minecraft/world/level/storage/loot/LootTable.java ++++ b/net/minecraft/world/level/storage/loot/LootTable.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.storage.loot; + + import com.google.common.collect.ImmutableList; ++import com.google.common.collect.ImmutableList.Builder; + import com.google.common.collect.Lists; + import com.mojang.logging.LogUtils; + import com.mojang.serialization.Codec; +@@ -28,6 +29,13 @@ + import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.CraftLootTable; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.world.LootGenerateEvent; ++// CraftBukkit end ++ + public class LootTable { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -49,20 +57,21 @@ + private final List pools; + private final List functions; + private final BiFunction compositeFunction; ++ public CraftLootTable craftLootTable; // CraftBukkit + +- LootTable(LootContextParamSet lootcontextparamset, Optional optional, List list, List list1) { +- this.paramSet = lootcontextparamset; ++ LootTable(LootContextParamSet lootcontextparameterset, Optional optional, List list, List list1) { ++ this.paramSet = lootcontextparameterset; + this.randomSequence = optional; + this.pools = list; + this.functions = list1; + this.compositeFunction = LootItemFunctions.compose(list1); + } + +- public static Consumer createStackSplitter(ServerLevel serverlevel, Consumer consumer) { ++ public static Consumer createStackSplitter(ServerLevel level, Consumer output) { + return (itemstack) -> { +- if (itemstack.isItemEnabled(serverlevel.enabledFeatures())) { ++ if (itemstack.isItemEnabled(level.enabledFeatures())) { + if (itemstack.getCount() < itemstack.getMaxStackSize()) { +- consumer.accept(itemstack); ++ output.accept(itemstack); + } else { + int i = itemstack.getCount(); + +@@ -70,7 +79,7 @@ + ItemStack itemstack1 = itemstack.copyWithCount(Math.min(itemstack.getMaxStackSize(), i)); + + i -= itemstack1.getCount(); +- consumer.accept(itemstack1); ++ output.accept(itemstack1); + } + } + +@@ -78,55 +87,55 @@ + }; + } + +- public void getRandomItemsRaw(LootParams lootparams, Consumer consumer) { +- this.getRandomItemsRaw((new LootContext.Builder(lootparams)).create(this.randomSequence), consumer); ++ public void getRandomItemsRaw(LootParams params, Consumer output) { ++ this.getRandomItemsRaw((new LootContext.Builder(params)).create(this.randomSequence), output); + } + +- public void getRandomItemsRaw(LootContext lootcontext, Consumer consumer) { +- LootContext.VisitedEntry lootcontext_visitedentry = LootContext.createVisitedEntry(this); ++ public void getRandomItemsRaw(LootContext context, Consumer output) { ++ LootContext.c loottableinfo_c = LootContext.createVisitedEntry(this); + +- if (lootcontext.pushVisitedElement(lootcontext_visitedentry)) { +- Consumer consumer1 = LootItemFunction.decorate(this.compositeFunction, consumer, lootcontext); ++ if (context.pushVisitedElement(loottableinfo_c)) { ++ Consumer consumer1 = LootItemFunction.decorate(this.compositeFunction, output, context); + Iterator iterator = this.pools.iterator(); + + while (iterator.hasNext()) { +- LootPool lootpool = (LootPool) iterator.next(); ++ LootPool lootselector = (LootPool) iterator.next(); + +- lootpool.addRandomItems(consumer1, lootcontext); ++ lootselector.addRandomItems(consumer1, context); + } + +- lootcontext.popVisitedElement(lootcontext_visitedentry); ++ context.popVisitedElement(loottableinfo_c); + } else { + LootTable.LOGGER.warn("Detected infinite loop in loot tables"); + } + + } + +- public void getRandomItems(LootParams lootparams, long i, Consumer consumer) { +- this.getRandomItemsRaw((new LootContext.Builder(lootparams)).withOptionalRandomSeed(i).create(this.randomSequence), createStackSplitter(lootparams.getLevel(), consumer)); ++ public void getRandomItems(LootParams params, long seed, Consumer consumer) { ++ this.getRandomItemsRaw((new LootContext.Builder(params)).withOptionalRandomSeed(seed).create(this.randomSequence), createStackSplitter(params.getLevel(), consumer)); + } + +- public void getRandomItems(LootParams lootparams, Consumer consumer) { +- this.getRandomItemsRaw(lootparams, createStackSplitter(lootparams.getLevel(), consumer)); ++ public void getRandomItems(LootParams params, Consumer output) { ++ this.getRandomItemsRaw(params, createStackSplitter(params.getLevel(), output)); + } + +- public void getRandomItems(LootContext lootcontext, Consumer consumer) { +- this.getRandomItemsRaw(lootcontext, createStackSplitter(lootcontext.getLevel(), consumer)); ++ public void getRandomItems(LootContext contextData, Consumer output) { ++ this.getRandomItemsRaw(contextData, createStackSplitter(contextData.getLevel(), output)); + } + +- public ObjectArrayList getRandomItems(LootParams lootparams, long i) { +- return this.getRandomItems((new LootContext.Builder(lootparams)).withOptionalRandomSeed(i).create(this.randomSequence)); ++ public ObjectArrayList getRandomItems(LootParams params, long seed) { ++ return this.getRandomItems((new LootContext.Builder(params)).withOptionalRandomSeed(seed).create(this.randomSequence)); + } + +- public ObjectArrayList getRandomItems(LootParams lootparams) { +- return this.getRandomItems((new LootContext.Builder(lootparams)).create(this.randomSequence)); ++ public ObjectArrayList getRandomItems(LootParams params) { ++ return this.getRandomItems((new LootContext.Builder(params)).create(this.randomSequence)); + } + +- private ObjectArrayList getRandomItems(LootContext lootcontext) { ++ private ObjectArrayList getRandomItems(LootContext context) { + ObjectArrayList objectarraylist = new ObjectArrayList(); + + Objects.requireNonNull(objectarraylist); +- this.getRandomItems(lootcontext, objectarraylist::add); ++ this.getRandomItems(context, objectarraylist::add); + return objectarraylist; + } + +@@ -134,25 +143,38 @@ + return this.paramSet; + } + +- public void validate(ValidationContext validationcontext) { ++ public void validate(ValidationContext validator) { + int i; + + for (i = 0; i < this.pools.size(); ++i) { +- ((LootPool) this.pools.get(i)).validate(validationcontext.forChild(".pools[" + i + "]")); ++ ((LootPool) this.pools.get(i)).validate(validator.forChild(".pools[" + i + "]")); + } + + for (i = 0; i < this.functions.size(); ++i) { +- ((LootItemFunction) this.functions.get(i)).validate(validationcontext.forChild(".functions[" + i + "]")); ++ ((LootItemFunction) this.functions.get(i)).validate(validator.forChild(".functions[" + i + "]")); + } + + } + +- public void fill(Container container, LootParams lootparams, long i) { +- LootContext lootcontext = (new LootContext.Builder(lootparams)).withOptionalRandomSeed(i).create(this.randomSequence); +- ObjectArrayList objectarraylist = this.getRandomItems(lootcontext); +- RandomSource randomsource = lootcontext.getRandom(); +- List list = this.getAvailableSlots(container, randomsource); ++ public void fill(Container container, LootParams params, long seed) { ++ // CraftBukkit start ++ this.fillInventory(container, params, seed, false); ++ } + ++ public void fillInventory(Container iinventory, LootParams lootparams, long i, boolean plugin) { ++ // CraftBukkit end ++ LootContext loottableinfo = (new LootContext.Builder(lootparams)).withOptionalRandomSeed(i).create(this.randomSequence); ++ ObjectArrayList objectarraylist = this.getRandomItems(loottableinfo); ++ RandomSource randomsource = loottableinfo.getRandom(); ++ // CraftBukkit start ++ LootGenerateEvent event = CraftEventFactory.callLootGenerateEvent(iinventory, this, loottableinfo, objectarraylist, plugin); ++ if (event.isCancelled()) { ++ return; ++ } ++ objectarraylist = event.getLoot().stream().map(CraftItemStack::asNMSCopy).collect(ObjectArrayList.toList()); ++ // CraftBukkit end ++ List list = this.getAvailableSlots(iinventory, randomsource); ++ + this.shuffleAndSplitItems(objectarraylist, list.size(), randomsource); + ObjectListIterator objectlistiterator = objectarraylist.iterator(); + +@@ -165,17 +187,17 @@ + } + + if (itemstack.isEmpty()) { +- container.setItem((Integer) list.remove(list.size() - 1), ItemStack.EMPTY); ++ iinventory.setItem((Integer) list.remove(list.size() - 1), ItemStack.EMPTY); + } else { +- container.setItem((Integer) list.remove(list.size() - 1), itemstack); ++ iinventory.setItem((Integer) list.remove(list.size() - 1), itemstack); + } + } + + } + +- private void shuffleAndSplitItems(ObjectArrayList objectarraylist, int i, RandomSource randomsource) { ++ private void shuffleAndSplitItems(ObjectArrayList stacks, int emptySlotsCount, RandomSource random) { + List list = Lists.newArrayList(); +- ObjectListIterator objectlistiterator = objectarraylist.iterator(); ++ ObjectListIterator objectlistiterator = stacks.iterator(); + + while (objectlistiterator.hasNext()) { + ItemStack itemstack = (ItemStack) objectlistiterator.next(); +@@ -188,38 +210,38 @@ + } + } + +- while (i - objectarraylist.size() - list.size() > 0 && !list.isEmpty()) { +- ItemStack itemstack1 = (ItemStack) list.remove(Mth.nextInt(randomsource, 0, list.size() - 1)); +- int j = Mth.nextInt(randomsource, 1, itemstack1.getCount() / 2); ++ while (emptySlotsCount - stacks.size() - list.size() > 0 && !list.isEmpty()) { ++ ItemStack itemstack1 = (ItemStack) list.remove(Mth.nextInt(random, 0, list.size() - 1)); ++ int j = Mth.nextInt(random, 1, itemstack1.getCount() / 2); + ItemStack itemstack2 = itemstack1.split(j); + +- if (itemstack1.getCount() > 1 && randomsource.nextBoolean()) { ++ if (itemstack1.getCount() > 1 && random.nextBoolean()) { + list.add(itemstack1); + } else { +- objectarraylist.add(itemstack1); ++ stacks.add(itemstack1); + } + +- if (itemstack2.getCount() > 1 && randomsource.nextBoolean()) { ++ if (itemstack2.getCount() > 1 && random.nextBoolean()) { + list.add(itemstack2); + } else { +- objectarraylist.add(itemstack2); ++ stacks.add(itemstack2); + } + } + +- objectarraylist.addAll(list); +- Util.shuffle(objectarraylist, randomsource); ++ stacks.addAll(list); ++ Util.shuffle(stacks, random); + } + +- private List getAvailableSlots(Container container, RandomSource randomsource) { ++ private List getAvailableSlots(Container inventory, RandomSource random) { + ObjectArrayList objectarraylist = new ObjectArrayList(); + +- for (int i = 0; i < container.getContainerSize(); ++i) { +- if (container.getItem(i).isEmpty()) { ++ for (int i = 0; i < inventory.getContainerSize(); ++i) { ++ if (inventory.getItem(i).isEmpty()) { + objectarraylist.add(i); + } + } + +- Util.shuffle(objectarraylist, randomsource); ++ Util.shuffle(objectarraylist, random); + return objectarraylist; + } + +@@ -229,8 +251,8 @@ + + public static class Builder implements FunctionUserBuilder { + +- private final com.google.common.collect.ImmutableList.Builder pools = ImmutableList.builder(); +- private final com.google.common.collect.ImmutableList.Builder functions = ImmutableList.builder(); ++ private final Builder pools = ImmutableList.builder(); ++ private final Builder functions = ImmutableList.builder(); + private LootContextParamSet paramSet; + private Optional randomSequence; + +@@ -239,30 +261,28 @@ + this.randomSequence = Optional.empty(); + } + +- public LootTable.Builder withPool(LootPool.Builder lootpool_builder) { +- this.pools.add(lootpool_builder.build()); ++ public LootTable.Builder withPool(LootPool.Builder lootPool) { ++ this.pools.add(lootPool.build()); + return this; + } + +- public LootTable.Builder setParamSet(LootContextParamSet lootcontextparamset) { +- this.paramSet = lootcontextparamset; ++ public LootTable.Builder setParamSet(LootContextParamSet parameterSet) { ++ this.paramSet = parameterSet; + return this; + } + +- public LootTable.Builder setRandomSequence(ResourceLocation resourcelocation) { +- this.randomSequence = Optional.of(resourcelocation); ++ public LootTable.Builder setRandomSequence(ResourceLocation randomSequence) { ++ this.randomSequence = Optional.of(randomSequence); + return this; + } + + @Override +- @Override +- public LootTable.Builder apply(LootItemFunction.Builder lootitemfunction_builder) { +- this.functions.add(lootitemfunction_builder.build()); ++ public LootTable.Builder apply(LootItemFunction.a functionBuilder) { ++ this.functions.add(functionBuilder.build()); + return this; + } + + @Override +- @Override + public LootTable.Builder unwrap() { + return this; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java.patch new file mode 100644 index 0000000000..ac2ec6fc0b --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java.patch @@ -0,0 +1,107 @@ +--- a/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java ++++ b/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java +@@ -22,10 +22,10 @@ + + public static final int NO_LIMIT = 0; + public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { +- return commonFields(instance).and(instance.group(NumberProviders.CODEC.fieldOf("count").forGetter((lootingenchantfunction) -> { +- return lootingenchantfunction.value; +- }), ExtraCodecs.strictOptionalField(Codec.INT, "limit", 0).forGetter((lootingenchantfunction) -> { +- return lootingenchantfunction.limit; ++ return commonFields(instance).and(instance.group(NumberProviders.CODEC.fieldOf("count").forGetter((lootenchantfunction) -> { ++ return lootenchantfunction.value; ++ }), ExtraCodecs.strictOptionalField(Codec.INT, "limit", 0).forGetter((lootenchantfunction) -> { ++ return lootenchantfunction.limit; + }))).apply(instance, LootingEnchantFunction::new); + }); + private final NumberProvider value; +@@ -38,13 +38,11 @@ + } + + @Override +- @Override + public LootItemFunctionType getType() { + return LootItemFunctions.LOOTING_ENCHANT; + } + + @Override +- @Override + public Set> getReferencedContextParams() { + return Sets.union(ImmutableSet.of(LootContextParams.KILLER_ENTITY), this.value.getReferencedContextParams()); + } +@@ -54,54 +52,56 @@ + } + + @Override +- @Override +- public ItemStack run(ItemStack itemstack, LootContext lootcontext) { +- Entity entity = (Entity) lootcontext.getParamOrNull(LootContextParams.KILLER_ENTITY); ++ public ItemStack run(ItemStack stack, LootContext context) { ++ Entity entity = (Entity) context.getParamOrNull(LootContextParams.KILLER_ENTITY); + + if (entity instanceof LivingEntity) { + int i = EnchantmentHelper.getMobLooting((LivingEntity) entity); ++ // CraftBukkit start - use lootingModifier if set by plugin ++ if (context.hasParam(LootContextParams.LOOTING_MOD)) { ++ i = context.getParamOrNull(LootContextParams.LOOTING_MOD); ++ } ++ // CraftBukkit end + +- if (i == 0) { +- return itemstack; ++ if (i <= 0) { // CraftBukkit - account for possible negative looting values from Bukkit ++ return stack; + } + +- float f = (float) i * this.value.getFloat(lootcontext); ++ float f = (float) i * this.value.getFloat(context); + +- itemstack.grow(Math.round(f)); +- if (this.hasLimit() && itemstack.getCount() > this.limit) { +- itemstack.setCount(this.limit); ++ stack.grow(Math.round(f)); ++ if (this.hasLimit() && stack.getCount() > this.limit) { ++ stack.setCount(this.limit); + } + } + +- return itemstack; ++ return stack; + } + +- public static LootingEnchantFunction.Builder lootingMultiplier(NumberProvider numberprovider) { +- return new LootingEnchantFunction.Builder(numberprovider); ++ public static LootingEnchantFunction.Builder lootingMultiplier(NumberProvider lootingMultiplier) { ++ return new LootingEnchantFunction.Builder(lootingMultiplier); + } + +- public static class Builder extends LootItemConditionalFunction.Builder { ++ public static class Builder extends LootItemConditionalFunction.a { + + private final NumberProvider count; + private int limit = 0; + +- public Builder(NumberProvider numberprovider) { +- this.count = numberprovider; ++ public Builder(NumberProvider lootingMultiplier) { ++ this.count = lootingMultiplier; + } + + @Override +- @Override + protected LootingEnchantFunction.Builder getThis() { + return this; + } + +- public LootingEnchantFunction.Builder setLimit(int i) { +- this.limit = i; ++ public LootingEnchantFunction.Builder setLimit(int limit) { ++ this.limit = limit; + return this; + } + + @Override +- @Override + public LootItemFunction build() { + return new LootingEnchantFunction(this.getConditions(), this.count, this.limit); + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/loot/parameters/LootContextParams.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/loot/parameters/LootContextParams.java.patch new file mode 100644 index 0000000000..385051a7ab --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/loot/parameters/LootContextParams.java.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/level/storage/loot/parameters/LootContextParams.java ++++ b/net/minecraft/world/level/storage/loot/parameters/LootContextParams.java +@@ -6,7 +6,7 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; + + public class LootContextParams { +@@ -17,14 +17,15 @@ + public static final LootContextParam KILLER_ENTITY = create("killer_entity"); + public static final LootContextParam DIRECT_KILLER_ENTITY = create("direct_killer_entity"); + public static final LootContextParam ORIGIN = create("origin"); +- public static final LootContextParam BLOCK_STATE = create("block_state"); ++ public static final LootContextParam BLOCK_STATE = create("block_state"); + public static final LootContextParam BLOCK_ENTITY = create("block_entity"); + public static final LootContextParam TOOL = create("tool"); + public static final LootContextParam EXPLOSION_RADIUS = create("explosion_radius"); ++ public static final LootContextParam LOOTING_MOD = new LootContextParam<>(new ResourceLocation("bukkit:looting_mod")); // CraftBukkit + + public LootContextParams() {} + +- private static LootContextParam create(String s) { +- return new LootContextParam<>(new ResourceLocation(s)); ++ private static LootContextParam create(String id) { ++ return new LootContextParam<>(new ResourceLocation(id)); + } + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/loot/predicates/ExplosionCondition.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/loot/predicates/ExplosionCondition.java.patch new file mode 100644 index 0000000000..993555b33c --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/loot/predicates/ExplosionCondition.java.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/level/storage/loot/predicates/ExplosionCondition.java ++++ b/net/minecraft/world/level/storage/loot/predicates/ExplosionCondition.java +@@ -16,26 +16,24 @@ + private ExplosionCondition() {} + + @Override +- @Override + public LootItemConditionType getType() { + return LootItemConditions.SURVIVES_EXPLOSION; + } + + @Override +- @Override + public Set> getReferencedContextParams() { + return ImmutableSet.of(LootContextParams.EXPLOSION_RADIUS); + } + +- @Override +- public boolean test(LootContext lootcontext) { +- Float ofloat = (Float) lootcontext.getParamOrNull(LootContextParams.EXPLOSION_RADIUS); ++ public boolean test(LootContext context) { ++ Float ofloat = (Float) context.getParamOrNull(LootContextParams.EXPLOSION_RADIUS); + + if (ofloat != null) { +- RandomSource randomsource = lootcontext.getRandom(); ++ RandomSource randomsource = context.getRandom(); + float f = 1.0F / ofloat; + +- return randomsource.nextFloat() <= f; ++ // CraftBukkit - <= to < to allow for plugins to completely disable block drops from explosions ++ return randomsource.nextFloat() < f; + } else { + return true; + } diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/loot/predicates/LootItemRandomChanceWithLootingCondition.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/loot/predicates/LootItemRandomChanceWithLootingCondition.java.patch new file mode 100644 index 0000000000..40ebebfd98 --- /dev/null +++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/storage/loot/predicates/LootItemRandomChanceWithLootingCondition.java.patch @@ -0,0 +1,45 @@ +--- a/net/minecraft/world/level/storage/loot/predicates/LootItemRandomChanceWithLootingCondition.java ++++ b/net/minecraft/world/level/storage/loot/predicates/LootItemRandomChanceWithLootingCondition.java +@@ -18,32 +18,34 @@ + }); + + @Override +- @Override + public LootItemConditionType getType() { + return LootItemConditions.RANDOM_CHANCE_WITH_LOOTING; + } + + @Override +- @Override + public Set> getReferencedContextParams() { + return ImmutableSet.of(LootContextParams.KILLER_ENTITY); + } + +- @Override +- public boolean test(LootContext lootcontext) { +- Entity entity = (Entity) lootcontext.getParamOrNull(LootContextParams.KILLER_ENTITY); ++ public boolean test(LootContext context) { ++ Entity entity = (Entity) context.getParamOrNull(LootContextParams.KILLER_ENTITY); + int i = 0; + + if (entity instanceof LivingEntity) { + i = EnchantmentHelper.getMobLooting((LivingEntity) entity); + } ++ // CraftBukkit start - only use lootingModifier if set by Bukkit ++ if (context.hasParam(LootContextParams.LOOTING_MOD)) { ++ i = context.getParamOrNull(LootContextParams.LOOTING_MOD); ++ } ++ // CraftBukkit end + +- return lootcontext.getRandom().nextFloat() < this.percent + (float) i * this.lootingMultiplier; ++ return context.getRandom().nextFloat() < this.percent + (float) i * this.lootingMultiplier; + } + +- public static LootItemCondition.Builder randomChanceAndLootingBoost(float f, float f1) { ++ public static LootItemCondition.Builder randomChanceAndLootingBoost(float chance, float lootingMultiplier) { + return () -> { +- return new LootItemRandomChanceWithLootingCondition(f, f1); ++ return new LootItemRandomChanceWithLootingCondition(chance, lootingMultiplier); + }; + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/CrashReport.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/CrashReport.java.patch new file mode 100644 index 0000000000..3b58cd946f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/CrashReport.java.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/CrashReport.java ++++ b/net/minecraft/CrashReport.java +@@ -35,6 +36,7 @@ + public CrashReport(String title, Throwable exception) { + this.title = title; + this.exception = exception; ++ this.systemReport.setDetail("CraftBukkit Information", new org.bukkit.craftbukkit.CraftCrashReport()); // CraftBukkit + } + + public String getTitle() { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/advancements/AdvancementHolder.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/advancements/AdvancementHolder.java.patch new file mode 100644 index 0000000000..b9a4741667 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/advancements/AdvancementHolder.java.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/advancements/AdvancementHolder.java ++++ b/net/minecraft/advancements/AdvancementHolder.java +@@ -2,6 +2,10 @@ + + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.resources.ResourceLocation; ++// CraftBukkit start ++import org.bukkit.craftbukkit.advancement.CraftAdvancement; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++// CraftBukkit end + + public record AdvancementHolder(ResourceLocation id, Advancement value) { + public void write(FriendlyByteBuf friendlyByteBuf) { +@@ -35,4 +45,10 @@ + public String toString() { + return this.id.toString(); + } ++ ++ // CraftBukkit start ++ public final org.bukkit.advancement.Advancement toBukkit() { ++ return new CraftAdvancement(this); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/advancements/AdvancementTree.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/advancements/AdvancementTree.java.patch new file mode 100644 index 0000000000..31d8d7fc66 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/advancements/AdvancementTree.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/advancements/AdvancementTree.java ++++ b/net/minecraft/advancements/AdvancementTree.java +@@ -62,7 +77,7 @@ + } + } + +- LOGGER.info("Loaded {} advancements", this.nodes.size()); ++ // AdvancementTree.LOGGER.info("Loaded {} advancements", this.nodes.size()); // CraftBukkit - moved to AdvancementDataWorld#reload + } + + private boolean tryInsert(AdvancementHolder advancementHolder) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/commands/CommandSource.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/commands/CommandSource.java.patch new file mode 100644 index 0000000000..3b19ad7917 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/commands/CommandSource.java.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/commands/CommandSource.java ++++ b/net/minecraft/commands/CommandSource.java +@@ -22,6 +22,13 @@ + public boolean shouldInformAdmins() { + return false; + } ++ ++ // CraftBukkit start ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ // CraftBukkit end + }; + + void sendSystemMessage(Component component); +@@ -35,4 +42,6 @@ + default boolean alwaysAccepts() { + return false; + } ++ ++ org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper); // CraftBukkit + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/commands/CommandSourceStack.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/commands/CommandSourceStack.java.patch new file mode 100644 index 0000000000..9c3c14d70e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/commands/CommandSourceStack.java.patch @@ -0,0 +1,70 @@ +--- a/net/minecraft/commands/CommandSourceStack.java ++++ b/net/minecraft/commands/CommandSourceStack.java +@@ -42,6 +43,7 @@ + import net.minecraft.world.level.dimension.DimensionType; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; ++import com.mojang.brigadier.tree.CommandNode; // CraftBukkit + + public class CommandSourceStack implements ExecutionCommandSource, SharedSuggestionProvider { + public static final SimpleCommandExceptionType ERROR_NOT_PLAYER = new SimpleCommandExceptionType(Component.translatable("permissions.requires.player")); +@@ -61,6 +64,7 @@ + private final Vec2 rotation; + private final CommandSigningContext signingContext; + private final TaskChainer chatMessageChainer; ++ public volatile CommandNode currentCommand; // CraftBukkit + + public CommandSourceStack( + CommandSource source, +@@ -389,9 +171,23 @@ + + @Override + public boolean hasPermission(int level) { ++ // CraftBukkit start ++ CommandNode currentCommand = this.currentCommand; ++ if (currentCommand != null) { ++ return hasPermission(level, org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(currentCommand)); ++ } ++ // CraftBukkit end ++ + return this.permissionLevel >= level; + } + ++ // CraftBukkit start ++ public boolean hasPermission(int i, String bukkitPermission) { ++ // World is null when loading functions ++ return ((getLevel() == null || !getLevel().getCraftServer().ignoreVanillaPermissions) && this.permissionLevel >= i) || getBukkitSender().hasPermission(bukkitPermission); ++ } ++ // CraftBukkit end ++ + public Vec3 getPosition() { + return this.worldPosition; + } +@@ -496,9 +315,13 @@ + private void broadcastToAdmins(Component message) { + Component component = Component.translatable("chat.type.admin", this.getDisplayName(), message).withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC); + if (this.server.getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK)) { +- for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) { +- if (serverPlayer != this.source && this.server.getPlayerList().isOp(serverPlayer.getGameProfile())) { +- serverPlayer.sendSystemMessage(component); ++ Iterator iterator = this.server.getPlayerList().getPlayers().iterator(); ++ ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ if (entityplayer != this.source && entityplayer.getBukkitEntity().hasPermission("minecraft.admin.command_feedback")) { // CraftBukkit ++ entityplayer.sendSystemMessage(ichatmutablecomponent); + } + } + } +@@ -592,4 +413,10 @@ + public boolean isSilent() { + return this.silent; + } ++ ++ // CraftBukkit start ++ public org.bukkit.command.CommandSender getBukkitSender() { ++ return source.getBukkitSender(this); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/commands/Commands.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/commands/Commands.java.patch new file mode 100644 index 0000000000..26b1a12ad0 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/commands/Commands.java.patch @@ -0,0 +1,192 @@ +--- a/net/minecraft/commands/Commands.java ++++ b/net/minecraft/commands/Commands.java +@@ -137,6 +134,14 @@ + import net.minecraft.world.level.GameRules; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.google.common.base.Joiner; ++import java.util.Collection; ++import java.util.LinkedHashSet; ++import org.bukkit.event.player.PlayerCommandSendEvent; ++import org.bukkit.event.server.ServerCommandEvent; ++// CraftBukkit end ++ + public class Commands { + private static final ThreadLocal> CURRENT_EXECUTION_CONTEXT = new ThreadLocal<>(); + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -148,6 +154,7 @@ + private final CommandDispatcher dispatcher = new CommandDispatcher<>(); + + public Commands(Commands.CommandSelection selection, CommandBuildContext context) { ++ this(); // CraftBukkit + AdvancementCommands.register(this.dispatcher); + AttributeCommand.register(this.dispatcher, context); + ExecuteCommand.register(this.dispatcher, context); +@@ -248,6 +255,11 @@ + PublishCommand.register(this.dispatcher); + } + ++ // CraftBukkit start ++ } ++ ++ public Commands() { ++ // CraftBukkkit end + this.dispatcher.setConsumer(ExecutionCommandSource.resultConsumer()); + } + +@@ -257,16 +270,66 @@ + return new ParseResults<>(commandContextBuilder, parseResults.getReader(), parseResults.getExceptions()); + } + +- public void performPrefixedCommand(CommandSourceStack commandSourceStack, String string) { +- string = string.startsWith("/") ? string.substring(1) : string; +- this.performCommand(this.dispatcher.parse(string, commandSourceStack), string); ++ // CraftBukkit start ++ public void dispatchServerCommand(CommandSourceStack sender, String command) { ++ Joiner joiner = Joiner.on(" "); ++ if (command.startsWith("/")) { ++ command = command.substring(1); ++ } ++ ++ ServerCommandEvent event = new ServerCommandEvent(sender.getBukkitSender(), command); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ command = event.getCommand(); ++ ++ String[] args = command.split(" "); ++ ++ String cmd = args[0]; ++ if (cmd.startsWith("minecraft:")) cmd = cmd.substring("minecraft:".length()); ++ if (cmd.startsWith("bukkit:")) cmd = cmd.substring("bukkit:".length()); ++ ++ // Block disallowed commands ++ if (cmd.equalsIgnoreCase("stop") || cmd.equalsIgnoreCase("kick") || cmd.equalsIgnoreCase("op") ++ || cmd.equalsIgnoreCase("deop") || cmd.equalsIgnoreCase("ban") || cmd.equalsIgnoreCase("ban-ip") ++ || cmd.equalsIgnoreCase("pardon") || cmd.equalsIgnoreCase("pardon-ip") || cmd.equalsIgnoreCase("reload")) { ++ return; ++ } ++ ++ // Handle vanilla commands; ++ if (sender.getLevel().getCraftServer().getCommandBlockOverride(args[0])) { ++ args[0] = "minecraft:" + args[0]; ++ } ++ ++ String newCommand = joiner.join(args); ++ this.performPrefixedCommand(sender, newCommand, newCommand); + } ++ // CraftBukkit end + +- public void performCommand(ParseResults parseResults, String string) { +- CommandSourceStack commandSourceStack = parseResults.getContext().getSource(); +- commandSourceStack.getServer().getProfiler().push(() -> "/" + string); +- ContextChain contextChain = finishParsing(parseResults, string, commandSourceStack); ++ public void performPrefixedCommand(CommandSourceStack commandlistenerwrapper, String s) { ++ // CraftBukkit start ++ this.performPrefixedCommand(commandlistenerwrapper, s, s); ++ } + ++ public void performPrefixedCommand(CommandSourceStack commandlistenerwrapper, String s, String label) { ++ s = s.startsWith("/") ? s.substring(1) : s; ++ this.performCommand(this.dispatcher.parse(s, commandlistenerwrapper), s, label); ++ // CraftBukkit end ++ } ++ ++ public void performCommand(ParseResults parseresults, String s) { ++ this.performCommand(parseresults, s, s); ++ } ++ ++ public void performCommand(ParseResults parseresults, String s, String label) { // CraftBukkit ++ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) parseresults.getContext().getSource(); ++ ++ commandlistenerwrapper.getServer().getProfiler().push(() -> { ++ return "/" + s; ++ }); ++ ContextChain contextchain = finishParsing(parseresults, s, commandlistenerwrapper, label); // CraftBukkit ++ + try { + if (contextChain != null) { + executeCommandInContext( +@@ -306,22 +362,22 @@ + } + + @Nullable +- private static ContextChain finishParsing( +- ParseResults parseResults, String string, CommandSourceStack commandSourceStack +- ) { ++ private static ContextChain finishParsing(ParseResults parseresults, String s, CommandSourceStack commandlistenerwrapper, String label) { // CraftBukkit + try { +- validateParseResults(parseResults); +- return ContextChain.tryFlatten(parseResults.getContext().build(string)) +- .orElseThrow(() -> CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand().createWithContext(parseResults.getReader())); +- } catch (CommandSyntaxException var7) { +- commandSourceStack.sendFailure(ComponentUtils.fromMessage(var7.getRawMessage())); +- if (var7.getInput() != null && var7.getCursor() >= 0) { +- int min = Math.min(var7.getInput().length(), var7.getCursor()); +- MutableComponent mutableComponent = Component.empty() +- .withStyle(ChatFormatting.GRAY) +- .withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + string))); +- if (min > 10) { +- mutableComponent.append(CommonComponents.ELLIPSIS); ++ validateParseResults(parseresults); ++ return (ContextChain) ContextChain.tryFlatten(parseresults.getContext().build(s)).orElseThrow(() -> { ++ return CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand().createWithContext(parseresults.getReader()); ++ }); ++ } catch (CommandSyntaxException commandsyntaxexception) { ++ commandlistenerwrapper.sendFailure(ComponentUtils.fromMessage(commandsyntaxexception.getRawMessage())); ++ if (commandsyntaxexception.getInput() != null && commandsyntaxexception.getCursor() >= 0) { ++ int i = Math.min(commandsyntaxexception.getInput().length(), commandsyntaxexception.getCursor()); ++ MutableComponent ichatmutablecomponent = Component.empty().withStyle(ChatFormatting.GRAY).withStyle((chatmodifier) -> { ++ return chatmodifier.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, label)); // CraftBukkit ++ }); ++ ++ if (i > 10) { ++ ichatmutablecomponent.append(CommonComponents.ELLIPSIS); + } + + mutableComponent.append(var7.getInput().substring(Math.max(0, min - 10), min)); +@@ -359,11 +432,37 @@ + } + + public void sendCommands(ServerPlayer player) { +- Map, CommandNode> map = Maps.newHashMap(); +- RootCommandNode rootCommandNode = new RootCommandNode<>(); +- map.put(this.dispatcher.getRoot(), rootCommandNode); +- this.fillUsableCommands(this.dispatcher.getRoot(), rootCommandNode, player.createCommandSourceStack(), map); +- player.connection.send(new ClientboundCommandsPacket(rootCommandNode)); ++ // CraftBukkit start ++ // Register Vanilla commands into builtRoot as before ++ Map, CommandNode> map = Maps.newIdentityHashMap(); // Use identity to prevent aliasing issues ++ RootCommandNode vanillaRoot = new RootCommandNode(); ++ ++ RootCommandNode vanilla = player.server.vanillaCommandDispatcher.getDispatcher().getRoot(); ++ map.put(vanilla, vanillaRoot); ++ this.fillUsableCommands(vanilla, vanillaRoot, player.createCommandSourceStack(), (Map) map); ++ ++ // Now build the global commands in a second pass ++ RootCommandNode rootcommandnode = new RootCommandNode(); ++ ++ map.put(this.dispatcher.getRoot(), rootcommandnode); ++ this.fillUsableCommands(this.dispatcher.getRoot(), rootcommandnode, player.createCommandSourceStack(), map); ++ ++ Collection bukkit = new LinkedHashSet<>(); ++ for (CommandNode node : rootcommandnode.getChildren()) { ++ bukkit.add(node.getName()); ++ } ++ ++ PlayerCommandSendEvent event = new PlayerCommandSendEvent(player.getBukkitEntity(), new LinkedHashSet<>(bukkit)); ++ event.getPlayer().getServer().getPluginManager().callEvent(event); ++ ++ // Remove labels that were removed during the event ++ for (String orig : bukkit) { ++ if (!event.getCommands().contains(orig)) { ++ rootcommandnode.removeCommand(orig); ++ } ++ } ++ // CraftBukkit end ++ player.connection.send(new ClientboundCommandsPacket(rootcommandnode)); + } + + private void fillUsableCommands( diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/commands/arguments/EntityArgument.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/commands/arguments/EntityArgument.java.patch new file mode 100644 index 0000000000..ed40be16ac --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/commands/arguments/EntityArgument.java.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/commands/arguments/EntityArgument.java ++++ b/net/minecraft/commands/arguments/EntityArgument.java +@@ -96,10 +94,17 @@ + + @Override + public EntitySelector parse(StringReader reader) throws CommandSyntaxException { +- int i = 0; +- EntitySelectorParser entitySelectorParser = new EntitySelectorParser(reader); +- EntitySelector entitySelector = entitySelectorParser.parse(); +- if (entitySelector.getMaxResults() > 1 && this.single) { ++ // CraftBukkit start ++ return parse(reader, false); ++ } ++ ++ public EntitySelector parse(StringReader stringreader, boolean overridePermissions) throws CommandSyntaxException { ++ // CraftBukkit end ++ boolean flag = false; ++ EntitySelectorParser argumentparserselector = new EntitySelectorParser(stringreader); ++ EntitySelector entityselector = argumentparserselector.parse(overridePermissions); // CraftBukkit ++ ++ if (entityselector.getMaxResults() > 1 && this.single) { + if (this.playersOnly) { + reader.setCursor(0); + throw ERROR_NOT_SINGLE_PLAYER.createWithContext(reader); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/commands/arguments/blocks/BlockStateParser.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/commands/arguments/blocks/BlockStateParser.java.patch new file mode 100644 index 0000000000..480d8c4475 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/commands/arguments/blocks/BlockStateParser.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/commands/arguments/blocks/BlockStateParser.java ++++ b/net/minecraft/commands/arguments/blocks/BlockStateParser.java +@@ -69,7 +68,7 @@ + private final StringReader reader; + private final boolean forTesting; + private final boolean allowNbt; +- private final Map, Comparable> properties = Maps.newHashMap(); ++ private final Map, Comparable> properties = Maps.newLinkedHashMap(); // CraftBukkit - stable + private final Map vagueProperties = Maps.newHashMap(); + private ResourceLocation id = new ResourceLocation(""); + @Nullable diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/commands/arguments/selector/EntitySelector.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/commands/arguments/selector/EntitySelector.java.patch new file mode 100644 index 0000000000..ca6a686ad3 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/commands/arguments/selector/EntitySelector.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/commands/arguments/selector/EntitySelector.java ++++ b/net/minecraft/commands/arguments/selector/EntitySelector.java +@@ -105,7 +92,7 @@ + } + + private void checkPermissions(CommandSourceStack source) throws CommandSyntaxException { +- if (this.usesSelector && !source.hasPermission(2)) { ++ if (this.usesSelector && !source.hasPermission(2, "minecraft.command.selector")) { // CraftBukkit + throw EntityArgument.ERROR_SELECTORS_NOT_ALLOWED.create(); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/commands/arguments/selector/EntitySelectorParser.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/commands/arguments/selector/EntitySelectorParser.java.patch new file mode 100644 index 0000000000..39f5ad0c5f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/commands/arguments/selector/EntitySelectorParser.java.patch @@ -0,0 +1,37 @@ +--- a/net/minecraft/commands/arguments/selector/EntitySelectorParser.java ++++ b/net/minecraft/commands/arguments/selector/EntitySelectorParser.java +@@ -197,8 +204,10 @@ + }; + } + +- protected void parseSelector() throws CommandSyntaxException { +- this.usesSelectors = true; ++ // CraftBukkit start ++ protected void parseSelector(boolean overridePermissions) throws CommandSyntaxException { ++ this.usesSelectors = !overridePermissions; ++ // CraftBukkit end + this.suggestions = this::suggestSelector; + if (!this.reader.canRead()) { + throw ERROR_MISSING_SELECTOR_TYPE.createWithContext(this.reader); +@@ -448,6 +465,12 @@ + } + + public EntitySelector parse() throws CommandSyntaxException { ++ // CraftBukkit start ++ return parse(false); ++ } ++ ++ public EntitySelector parse(boolean overridePermissions) throws CommandSyntaxException { ++ // CraftBukkit end + this.startPosition = this.reader.getCursor(); + this.suggestions = this::suggestNameOrSelector; + if (this.reader.canRead() && this.reader.peek() == '@') { +@@ -456,7 +479,7 @@ + } + + this.reader.skip(); +- this.parseSelector(); ++ this.parseSelector(overridePermissions); // CraftBukkit + } else { + this.parseNameOrUUID(); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/core/cauldron/CauldronInteraction.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/core/cauldron/CauldronInteraction.java.patch new file mode 100644 index 0000000000..f0364dd0fa --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/core/cauldron/CauldronInteraction.java.patch @@ -0,0 +1,300 @@ +--- a/net/minecraft/core/cauldron/CauldronInteraction.java ++++ b/net/minecraft/core/cauldron/CauldronInteraction.java +@@ -30,6 +33,10 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.event.block.CauldronLevelChangeEvent; ++// CraftBukkit end ++ + public interface CauldronInteraction { + Map INTERACTIONS = new Object2ObjectArrayMap<>(); + Codec CODEC = ExtraCodecs.stringResolverCodec(CauldronInteraction.InteractionMap::name, INTERACTIONS::get); +@@ -69,10 +39,22 @@ + itemStack.setTag(stack.getTag().copy()); + } + +- player.setItemInHand(hand, itemStack); +- player.awardStat(Stats.CLEAN_SHULKER_BOX); +- LayeredCauldronBlock.lowerFillLevel(blockState, level, blockPos); +- } ++ Map INTERACTIONS = new Object2ObjectArrayMap(); ++ // CraftBukkit start - decompile error ++ /* ++ Codec CODEC; ++ CauldronInteraction.a EMPTY; ++ CauldronInteraction.a WATER; ++ CauldronInteraction.a LAVA; ++ CauldronInteraction.a POWDER_SNOW; ++ CauldronInteraction FILL_WATER; ++ CauldronInteraction FILL_LAVA; ++ CauldronInteraction FILL_POWDER_SNOW; ++ CauldronInteraction SHULKER_BOX; ++ CauldronInteraction BANNER; ++ CauldronInteraction DYED_ITEM; ++ */ ++ // CraftBukkit end + + return InteractionResult.sidedSuccess(level.isClientSide); + } +@@ -136,14 +78,20 @@ + if (PotionUtils.getPotion(stack) != Potions.WATER) { + return InteractionResult.PASS; + } else { +- if (!level.isClientSide) { +- Item item = stack.getItem(); +- player.setItemInHand(hand, ItemUtils.createFilledResult(stack, player, new ItemStack(Items.GLASS_BOTTLE))); +- player.awardStat(Stats.USE_CAULDRON); +- player.awardStat(Stats.ITEM_USED.get(item)); +- level.setBlockAndUpdate(blockPos, Blocks.WATER_CAULDRON.defaultBlockState()); +- level.playSound(null, blockPos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent(null, GameEvent.FLUID_PLACE, blockPos); ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.changeLevel(iblockdata, world, blockposition, Blocks.WATER_CAULDRON.defaultBlockState(), entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_EMPTY)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ Item item = itemstack.getItem(); ++ ++ entityhuman.setItemInHand(enumhand, ItemUtils.createFilledResult(itemstack, entityhuman, new ItemStack(Items.GLASS_BOTTLE))); ++ entityhuman.awardStat(Stats.USE_CAULDRON); ++ entityhuman.awardStat(Stats.ITEM_USED.get(item)); ++ // world.setBlockAndUpdate(blockposition, Blocks.WATER_CAULDRON.defaultBlockState()); // CraftBukkit ++ world.playSound((Player) null, blockposition, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockposition); + } + + return InteractionResult.sidedSuccess(level.isClientSide); +@@ -151,42 +100,44 @@ + }); + Map map1 = WATER.map(); + addDefaultInteractions(map1); +- map1.put( +- Items.BUCKET, +- (blockState, level, blockPos, player, hand, stack) -> fillBucket( +- blockState, +- level, +- blockPos, +- player, +- hand, +- stack, +- new ItemStack(Items.WATER_BUCKET), +- blockState1 -> blockState1.getValue(LayeredCauldronBlock.LEVEL) == 3, +- SoundEvents.BUCKET_FILL +- ) +- ); +- map1.put(Items.GLASS_BOTTLE, (blockState, level, blockPos, player, hand, stack) -> { +- if (!level.isClientSide) { +- Item item = stack.getItem(); +- player.setItemInHand(hand, ItemUtils.createFilledResult(stack, player, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER))); +- player.awardStat(Stats.USE_CAULDRON); +- player.awardStat(Stats.ITEM_USED.get(item)); +- LayeredCauldronBlock.lowerFillLevel(blockState, level, blockPos); +- level.playSound(null, blockPos, SoundEvents.BOTTLE_FILL, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent(null, GameEvent.FLUID_PICKUP, blockPos); ++ map1.put(Items.BUCKET, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ return fillBucket(iblockdata, world, blockposition, entityhuman, enumhand, itemstack, new ItemStack(Items.WATER_BUCKET), (iblockdata1) -> { ++ return (Integer) iblockdata1.getValue(LayeredCauldronBlock.LEVEL) == 3; ++ }, SoundEvents.BUCKET_FILL); ++ }); ++ map1.put(Items.GLASS_BOTTLE, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_FILL)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ Item item = itemstack.getItem(); ++ ++ entityhuman.setItemInHand(enumhand, ItemUtils.createFilledResult(itemstack, entityhuman, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER))); ++ entityhuman.awardStat(Stats.USE_CAULDRON); ++ entityhuman.awardStat(Stats.ITEM_USED.get(item)); ++ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit ++ world.playSound((Player) null, blockposition, SoundEvents.BOTTLE_FILL, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockposition); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + }); +- map1.put(Items.POTION, (blockState, level, blockPos, player, hand, stack) -> { +- if (blockState.getValue(LayeredCauldronBlock.LEVEL) != 3 && PotionUtils.getPotion(stack) == Potions.WATER) { +- if (!level.isClientSide) { +- player.setItemInHand(hand, ItemUtils.createFilledResult(stack, player, new ItemStack(Items.GLASS_BOTTLE))); +- player.awardStat(Stats.USE_CAULDRON); +- player.awardStat(Stats.ITEM_USED.get(stack.getItem())); +- level.setBlockAndUpdate(blockPos, blockState.cycle(LayeredCauldronBlock.LEVEL)); +- level.playSound(null, blockPos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent(null, GameEvent.FLUID_PLACE, blockPos); ++ map1.put(Items.POTION, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ if ((Integer) iblockdata.getValue(LayeredCauldronBlock.LEVEL) != 3 && PotionUtils.getPotion(itemstack) == Potions.WATER) { ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.changeLevel(iblockdata, world, blockposition, iblockdata.cycle(LayeredCauldronBlock.LEVEL), entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_EMPTY)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ entityhuman.setItemInHand(enumhand, ItemUtils.createFilledResult(itemstack, entityhuman, new ItemStack(Items.GLASS_BOTTLE))); ++ entityhuman.awardStat(Stats.USE_CAULDRON); ++ entityhuman.awardStat(Stats.ITEM_USED.get(itemstack.getItem())); ++ // world.setBlockAndUpdate(blockposition, (IBlockData) iblockdata.cycle(LayeredCauldronBlock.LEVEL)); // CraftBukkit ++ world.playSound((Player) null, blockposition, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockposition); + } + + return InteractionResult.sidedSuccess(level.isClientSide); +@@ -278,13 +211,18 @@ + return InteractionResult.PASS; + } else { + if (!level.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.changeLevel(blockState, level, pos, Blocks.CAULDRON.defaultBlockState(), player, CauldronLevelChangeEvent.ChangeReason.BUCKET_FILL)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + Item item = emptyStack.getItem(); + player.setItemInHand(hand, ItemUtils.createFilledResult(emptyStack, player, filledStack)); + player.awardStat(Stats.USE_CAULDRON); + player.awardStat(Stats.ITEM_USED.get(item)); +- level.setBlockAndUpdate(pos, Blocks.CAULDRON.defaultBlockState()); +- level.playSound(null, pos, fillSound, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent(null, GameEvent.FLUID_PICKUP, pos); ++ // world.setBlockAndUpdate(blockposition, Blocks.CAULDRON.defaultBlockState()); // CraftBukkit ++ level.playSound((Player) null, pos, fillSound, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, pos); + } + + return InteractionResult.sidedSuccess(level.isClientSide); +@@ -295,18 +232,127 @@ + Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack filledStack, BlockState state, SoundEvent emptySound + ) { + if (!level.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.changeLevel(state, level, pos, state, player, CauldronLevelChangeEvent.ChangeReason.BUCKET_EMPTY)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + Item item = filledStack.getItem(); + player.setItemInHand(hand, ItemUtils.createFilledResult(filledStack, player, new ItemStack(Items.BUCKET))); + player.awardStat(Stats.FILL_CAULDRON); + player.awardStat(Stats.ITEM_USED.get(item)); +- level.setBlockAndUpdate(pos, state); +- level.playSound(null, pos, emptySound, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent(null, GameEvent.FLUID_PLACE, pos); ++ // world.setBlockAndUpdate(blockposition, iblockdata); // CraftBukkit ++ level.playSound((Player) null, pos, emptySound, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.gameEvent((Entity) null, GameEvent.FLUID_PLACE, pos); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + } + +- public static record InteractionMap(String name, Map map) { ++ // CraftBukkit start - decompile errors ++ // static { ++ Codec CODEC = ExtraCodecs.stringResolverCodec(CauldronInteraction.a::name, CauldronInteraction.INTERACTIONS::get); ++ CauldronInteraction.a EMPTY = newInteractionMap("empty"); ++ CauldronInteraction.a WATER = newInteractionMap("water"); ++ CauldronInteraction.a LAVA = newInteractionMap("lava"); ++ CauldronInteraction.a POWDER_SNOW = newInteractionMap("powder_snow"); ++ CauldronInteraction FILL_WATER = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ return emptyBucket(world, blockposition, entityhuman, enumhand, itemstack, (IBlockData) Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY); ++ }; ++ CauldronInteraction FILL_LAVA = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ return emptyBucket(world, blockposition, entityhuman, enumhand, itemstack, Blocks.LAVA_CAULDRON.defaultBlockState(), SoundEvents.BUCKET_EMPTY_LAVA); ++ }; ++ CauldronInteraction FILL_POWDER_SNOW = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ return emptyBucket(world, blockposition, entityhuman, enumhand, itemstack, (IBlockData) Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY_POWDER_SNOW); ++ }; ++ CauldronInteraction SHULKER_BOX = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ // CraftBukkit end ++ Block block = Block.byItem(itemstack.getItem()); ++ ++ if (!(block instanceof ShulkerBoxBlock)) { ++ return InteractionResult.PASS; ++ } else { ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.SHULKER_WASH)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ ItemStack itemstack1 = new ItemStack(Blocks.SHULKER_BOX); ++ ++ if (itemstack.hasTag()) { ++ itemstack1.setTag(itemstack.getTag().copy()); ++ } ++ ++ entityhuman.setItemInHand(enumhand, itemstack1); ++ entityhuman.awardStat(Stats.CLEAN_SHULKER_BOX); ++ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit ++ } ++ ++ return InteractionResult.sidedSuccess(world.isClientSide); ++ } ++ }; ++ CauldronInteraction BANNER = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { // CraftBukkit - decompile error ++ if (BannerBlockEntity.getPatternCount(itemstack) <= 0) { ++ return InteractionResult.PASS; ++ } else { ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.BANNER_WASH)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ ItemStack itemstack1 = itemstack.copyWithCount(1); ++ ++ BannerBlockEntity.removeLastPattern(itemstack1); ++ if (!entityhuman.getAbilities().instabuild) { ++ itemstack.shrink(1); ++ } ++ ++ if (itemstack.isEmpty()) { ++ entityhuman.setItemInHand(enumhand, itemstack1); ++ } else if (entityhuman.getInventory().add(itemstack1)) { ++ entityhuman.inventoryMenu.sendAllDataToRemote(); ++ } else { ++ entityhuman.drop(itemstack1, false); ++ } ++ ++ entityhuman.awardStat(Stats.CLEAN_BANNER); ++ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit ++ } ++ ++ return InteractionResult.sidedSuccess(world.isClientSide); ++ } ++ }; ++ CauldronInteraction DYED_ITEM = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { // CraftBukkit - decompile error ++ Item item = itemstack.getItem(); ++ ++ if (!(item instanceof DyeableLeatherItem)) { ++ return InteractionResult.PASS; ++ } else { ++ DyeableLeatherItem idyeable = (DyeableLeatherItem) item; ++ ++ if (!idyeable.hasCustomColor(itemstack)) { ++ return InteractionResult.PASS; ++ } else { ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.ARMOR_WASH)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ idyeable.clearColor(itemstack); ++ entityhuman.awardStat(Stats.CLEAN_ARMOR); ++ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit ++ } ++ ++ return InteractionResult.sidedSuccess(world.isClientSide); ++ } ++ } ++ }; ++ // } // CraftBukkit - decompile error ++ ++ public static record a(String name, Map map) { ++ + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java.patch new file mode 100644 index 0000000000..1683198993 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java.patch @@ -0,0 +1,69 @@ +--- a/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java ++++ b/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java +@@ -6,20 +6,55 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.DispenserBlock; ++// CraftBukkit start ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.projectile.Projectile; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end + + public abstract class AbstractProjectileDispenseBehavior extends DefaultDispenseItemBehavior { + @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Level level = blockSource.level(); +- Position dispensePosition = DispenserBlock.getDispensePosition(blockSource); +- Direction direction = blockSource.state().getValue(DispenserBlock.FACING); +- Projectile projectile = this.getProjectile(level, dispensePosition, itemStack); +- projectile.shoot( +- (double)direction.getStepX(), (double)((float)direction.getStepY() + 0.1F), (double)direction.getStepZ(), this.getPower(), this.getUncertainty() +- ); +- level.addFreshEntity(projectile); +- itemStack.shrink(1); +- return itemStack; ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ IPosition iposition = DispenserBlock.getDispensePosition(sourceblock); ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ Projectile iprojectile = this.getProjectile(worldserver, iposition, itemstack); ++ ++ // CraftBukkit start ++ // iprojectile.shoot((double) enumdirection.getStepX(), (double) ((float) enumdirection.getStepY() + 0.1F), (double) enumdirection.getStepZ(), this.getPower(), this.getUncertainty()); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) enumdirection.getStepX(), (double) ((float) enumdirection.getStepY() + 0.1F), (double) enumdirection.getStepZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ iprojectile.shoot(event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), this.getPower(), this.getUncertainty()); ++ ((Entity) iprojectile).projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(sourceblock.blockEntity()); ++ // CraftBukkit end ++ worldserver.addFreshEntity(iprojectile); ++ // itemstack.shrink(1); // CraftBukkit - Handled during event processing ++ return itemstack; + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java.patch new file mode 100644 index 0000000000..4386593919 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java.patch @@ -0,0 +1,64 @@ +--- a/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java ++++ b/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java +@@ -10,6 +12,11 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.DispenserBlock; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end + + public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior { + private final DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior(); +@@ -46,13 +56,42 @@ + d4 = 0.0; + } + +- Boat boat = (Boat)(this.isChestBoat ? new ChestBoat(serverLevel, d1, d2 + d4, d3) : new Boat(serverLevel, d1, d2 + d4, d3)); +- EntityType.createDefaultStackConfig(serverLevel, itemStack, null).accept(boat); +- boat.setVariant(this.type); +- boat.setYRot(direction.toYRot()); +- serverLevel.addFreshEntity(boat); +- itemStack.shrink(1); +- return itemStack; ++ // Object object = this.isChestBoat ? new ChestBoat(worldserver, d1, d2 + d4, d3) : new EntityBoat(worldserver, d1, d2 + d4, d3); ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d1, d2 + d4, d3)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ Boat object = this.isChestBoat ? new ChestBoat(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ()) : new Boat(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ()); ++ // CraftBukkit end ++ ++ EntityType.createDefaultStackConfig(worldserver, itemstack, (Player) null).accept(object); ++ ((Boat) object).setVariant(this.type); ++ ((Boat) object).setYRot(enumdirection.toYRot()); ++ if (!worldserver.addFreshEntity((Entity) object)) itemstack.grow(1); // CraftBukkit ++ // itemstack.shrink(1); // CraftBukkit - handled during event processing ++ return itemstack; + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java.patch new file mode 100644 index 0000000000..2f73c33085 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java.patch @@ -0,0 +1,133 @@ +--- a/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java ++++ b/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java +@@ -6,8 +6,25 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.DispenserBlock; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftVector; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end + + public class DefaultDispenseItemBehavior implements DispenseItemBehavior { ++ ++ // CraftBukkit start ++ private boolean dropper; ++ ++ public DefaultDispenseItemBehavior(boolean dropper) { ++ this.dropper = dropper; ++ } ++ // CraftBukkit end ++ ++ public DefaultDispenseItemBehavior() {} ++ + @Override + public final ItemStack dispense(BlockSource blockSource, ItemStack itemStack) { + ItemStack itemStack1 = this.execute(blockSource, itemStack); +@@ -16,36 +34,82 @@ + return itemStack1; + } + +- protected ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Direction direction = blockSource.state().getValue(DispenserBlock.FACING); +- Position dispensePosition = DispenserBlock.getDispensePosition(blockSource); +- ItemStack itemStack1 = itemStack.split(1); +- spawnItem(blockSource.level(), itemStack1, 6, direction, dispensePosition); +- return itemStack; ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ IPosition iposition = DispenserBlock.getDispensePosition(sourceblock); ++ ItemStack itemstack1 = itemstack.split(1); ++ ++ // CraftBukkit start ++ if (!spawnItem(sourceblock.level(), itemstack1, 6, enumdirection, sourceblock, dropper)) { ++ itemstack.grow(1); ++ } ++ // CraftBukkit end ++ return itemstack; + } + +- public static void spawnItem(Level level, ItemStack stack, int speed, Direction facing, Position position) { +- double d = position.x(); +- double d1 = position.y(); +- double d2 = position.z(); +- if (facing.getAxis() == Direction.Axis.Y) { +- d1 -= 0.125; ++ public static void spawnItem(Level level, ItemStack stack, int speed, Direction facing, IPosition position) { ++ // CraftBukkit start ++ ItemEntity entityitem = prepareItem(level, stack, speed, facing, position); ++ level.addFreshEntity(entityitem); ++ } ++ ++ private static ItemEntity prepareItem(Level world, ItemStack itemstack, int i, Direction enumdirection, IPosition iposition) { ++ // CraftBukkit end ++ double d0 = iposition.x(); ++ double d1 = iposition.y(); ++ double d2 = iposition.z(); ++ ++ if (enumdirection.getAxis() == Direction.Axis.Y) { ++ d1 -= 0.125D; + } else { + d1 -= 0.15625; + } + +- ItemEntity itemEntity = new ItemEntity(level, d, d1, d2, stack); +- double d3 = level.random.nextDouble() * 0.1 + 0.2; +- itemEntity.setDeltaMovement( +- level.random.triangle((double)facing.getStepX() * d3, 0.0172275 * (double)speed), +- level.random.triangle(0.2, 0.0172275 * (double)speed), +- level.random.triangle((double)facing.getStepZ() * d3, 0.0172275 * (double)speed) +- ); +- level.addFreshEntity(itemEntity); ++ ItemEntity entityitem = new ItemEntity(world, d0, d1, d2, itemstack); ++ double d3 = world.random.nextDouble() * 0.1D + 0.2D; ++ ++ entityitem.setDeltaMovement(world.random.triangle((double) enumdirection.getStepX() * d3, 0.0172275D * (double) i), world.random.triangle(0.2D, 0.0172275D * (double) i), world.random.triangle((double) enumdirection.getStepZ() * d3, 0.0172275D * (double) i)); ++ // CraftBukkit start ++ return entityitem; + } + +- protected void playSound(BlockSource blockSource) { +- blockSource.level().levelEvent(1000, blockSource.pos(), 0); ++ // CraftBukkit - void -> boolean return, IPosition -> ISourceBlock last argument, dropper ++ public static boolean spawnItem(Level world, ItemStack itemstack, int i, Direction enumdirection, SourceBlock sourceblock, boolean dropper) { ++ if (itemstack.isEmpty()) return true; ++ IPosition iposition = DispenserBlock.getDispensePosition(sourceblock); ++ ItemEntity entityitem = prepareItem(world, itemstack, i, enumdirection, iposition); ++ ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), CraftVector.toBukkit(entityitem.getDeltaMovement())); ++ if (!DispenserBlock.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ entityitem.setItem(CraftItemStack.asNMSCopy(event.getItem())); ++ entityitem.setDeltaMovement(CraftVector.toNMS(event.getVelocity())); ++ ++ if (!dropper && !event.getItem().getType().equals(craftItem.getType())) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior.getClass() != DefaultDispenseItemBehavior.class) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ } else { ++ world.addFreshEntity(entityitem); ++ } ++ return false; ++ } ++ ++ world.addFreshEntity(entityitem); ++ ++ return true; ++ // CraftBukkit end + } + + protected void playAnimation(BlockSource blockSource, Direction direction) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/core/dispenser/DispenseItemBehavior.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/core/dispenser/DispenseItemBehavior.java.patch new file mode 100644 index 0000000000..0b4328d04e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/core/dispenser/DispenseItemBehavior.java.patch @@ -0,0 +1,908 @@ +--- a/net/minecraft/core/dispenser/DispenseItemBehavior.java ++++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java +@@ -72,6 +79,17 @@ + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; ++import org.bukkit.Location; ++import org.bukkit.TreeType; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.craftbukkit.util.DummyGeneratorAccess; ++import org.bukkit.event.block.BlockDispenseArmorEvent; ++import org.bukkit.event.block.BlockDispenseEvent; ++import org.bukkit.event.block.BlockFertilizeEvent; ++import org.bukkit.event.world.StructureGrowEvent; ++// CraftBukkit end + + public interface DispenseItemBehavior { + Logger LOGGER = LogUtils.getLogger(); +@@ -181,6 +215,33 @@ + Direction direction = blockSource.state().getValue(DispenserBlock.FACING); + EntityType type = ((SpawnEggItem)itemStack.getItem()).getType(itemStack.getTag()); + ++ // CraftBukkit start ++ ServerLevel worldserver = sourceblock.level(); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ + try { + type.spawn( + blockSource.level(), itemStack, null, blockSource.pos().relative(direction), MobSpawnType.DISPENSER, direction != Direction.UP, false +@@ -190,9 +249,10 @@ + return ItemStack.EMPTY; + } + +- itemStack.shrink(1); +- blockSource.level().gameEvent(null, GameEvent.ENTITY_PLACE, blockSource.pos()); +- return itemStack; ++ // itemstack.shrink(1); // Handled during event processing ++ // CraftBukkit end ++ sourceblock.level().gameEvent((Entity) null, GameEvent.ENTITY_PLACE, sourceblock.pos()); ++ return itemstack; + } + }; + +@@ -200,25 +263,52 @@ + DispenserBlock.registerBehavior(spawnEggItem, defaultDispenseItemBehavior); + } + +- DispenserBlock.registerBehavior( +- Items.ARMOR_STAND, +- new DefaultDispenseItemBehavior() { +- @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Direction direction = blockSource.state().getValue(DispenserBlock.FACING); +- BlockPos blockPos = blockSource.pos().relative(direction); +- ServerLevel serverLevel = blockSource.level(); +- Consumer consumer = EntityType.appendDefaultStackConfig( +- armorStand1 -> armorStand1.setYRot(direction.toYRot()), serverLevel, itemStack, null +- ); +- ArmorStand armorStand = EntityType.ARMOR_STAND +- .spawn(serverLevel, itemStack.getTag(), consumer, blockPos, MobSpawnType.DISPENSER, false, false); +- if (armorStand != null) { +- itemStack.shrink(1); ++ DispenserBlock.registerBehavior(Items.ARMOR_STAND, new DefaultDispenseItemBehavior() { ++ @Override ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ BlockPos blockposition = sourceblock.pos().relative(enumdirection); ++ ServerLevel worldserver = sourceblock.level(); ++ ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; + } + + return itemStack; + } ++ // CraftBukkit end ++ ++ Consumer consumer = EntityType.appendDefaultStackConfig((entityarmorstand) -> { ++ entityarmorstand.setYRot(enumdirection.toYRot()); ++ }, worldserver, itemstack, (Player) null); ++ ArmorStand entityarmorstand = (ArmorStand) EntityType.ARMOR_STAND.spawn(worldserver, itemstack.getTag(), consumer, blockposition, EnumMobSpawn.DISPENSER, false, false); ++ ++ if (entityarmorstand != null) { ++ // itemstack.shrink(1); // CraftBukkit - Handled during event processing ++ } ++ ++ return itemstack; + } + ); + DispenserBlock.registerBehavior( +@@ -241,6 +321,42 @@ + } else { + return super.execute(blockSource, itemStack); + } ++ }); ++ ++ if (!list.isEmpty()) { ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ Level world = sourceblock.level(); ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) list.get(0).getBukkitEntity()); ++ if (!DispenserBlock.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ ((Saddleable) list.get(0)).equipSaddle(SoundSource.BLOCKS); ++ // itemstack.shrink(1); // CraftBukkit - handled above ++ this.setSuccess(true); ++ return itemstack; ++ } else { ++ return super.execute(sourceblock, itemstack); + } + } + ); +@@ -256,9 +375,41 @@ + this.setSuccess(true); + return itemStack; + } ++ ++ entityhorseabstract = (AbstractHorse) iterator1.next(); ++ } while (!entityhorseabstract.isArmor(itemstack) || entityhorseabstract.isWearingArmor() || !entityhorseabstract.isTamed()); ++ ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ Level world = sourceblock.level(); ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityhorseabstract.getBukkitEntity()); ++ if (!DispenserBlock.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); + } + +- return super.execute(blockSource, itemStack); ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ entityhorseabstract.getSlot(401).set(CraftItemStack.asNMSCopy(event.getItem())); ++ // CraftBukkit end ++ this.setSuccess(true); ++ return itemstack; + } + }; + DispenserBlock.registerBehavior(Items.LEATHER_HORSE_ARMOR, defaultDispenseItemBehavior1); +@@ -296,50 +448,131 @@ + return itemStack; + } + } +- +- return super.execute(blockSource, itemStack); ++ ++ entityhorsechestedabstract = (AbstractChestedHorse) iterator1.next(); ++ // CraftBukkit start ++ } while (!entityhorsechestedabstract.isTamed()); ++ ItemStack itemstack1 = itemstack.split(1); ++ Level world = sourceblock.level(); ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityhorsechestedabstract.getBukkitEntity()); ++ if (!DispenserBlock.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); + } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ entityhorsechestedabstract.getSlot(499).set(CraftItemStack.asNMSCopy(event.getItem())); ++ // CraftBukkit end ++ ++ // itemstack.shrink(1); // CraftBukkit - handled above ++ this.setSuccess(true); ++ return itemstack; + } +- ); +- DispenserBlock.registerBehavior( +- Items.FIREWORK_ROCKET, +- new DefaultDispenseItemBehavior() { +- @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Direction direction = blockSource.state().getValue(DispenserBlock.FACING); +- Vec3 entityPokingOutOfBlockPos = DispenseItemBehavior.getEntityPokingOutOfBlockPos(blockSource, EntityType.FIREWORK_ROCKET, direction); +- FireworkRocketEntity fireworkRocketEntity = new FireworkRocketEntity( +- blockSource.level(), itemStack, entityPokingOutOfBlockPos.x(), entityPokingOutOfBlockPos.y(), entityPokingOutOfBlockPos.z(), true +- ); +- fireworkRocketEntity.shoot((double)direction.getStepX(), (double)direction.getStepY(), (double)direction.getStepZ(), 0.5F, 1.0F); +- blockSource.level().addFreshEntity(fireworkRocketEntity); +- itemStack.shrink(1); +- return itemStack; ++ }); ++ DispenserBlock.registerBehavior(Items.FIREWORK_ROCKET, new DefaultDispenseItemBehavior() { ++ @Override ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ // CraftBukkit start ++ ServerLevel worldserver = sourceblock.level(); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(enumdirection.getStepX(), enumdirection.getStepY(), enumdirection.getStepZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); + } + + @Override + protected void playSound(BlockSource blockSource) { + blockSource.level().levelEvent(1004, blockSource.pos(), 0); + } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); ++ Vec3 vec3d = DispenseItemBehavior.getEntityPokingOutOfBlockPos(sourceblock, EntityType.FIREWORK_ROCKET, enumdirection); ++ FireworkRocketEntity entityfireworks = new FireworkRocketEntity(sourceblock.level(), itemstack, vec3d.x(), vec3d.y(), vec3d.z(), true); ++ ++ entityfireworks.shoot((double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ(), 0.5F, 1.0F); ++ sourceblock.level().addFreshEntity(entityfireworks); ++ // itemstack.shrink(1); // Handled during event processing ++ // CraftBukkit end ++ return itemstack; + } + ); + DispenserBlock.registerBehavior(Items.FIRE_CHARGE, new DefaultDispenseItemBehavior() { + @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Direction direction = blockSource.state().getValue(DispenserBlock.FACING); +- Position dispensePosition = DispenserBlock.getDispensePosition(blockSource); +- double d = dispensePosition.x() + (double)((float)direction.getStepX() * 0.3F); +- double d1 = dispensePosition.y() + (double)((float)direction.getStepY() * 0.3F); +- double d2 = dispensePosition.z() + (double)((float)direction.getStepZ() * 0.3F); +- Level level = blockSource.level(); +- RandomSource randomSource = level.random; +- double d3 = randomSource.triangle((double)direction.getStepX(), 0.11485000000000001); +- double d4 = randomSource.triangle((double)direction.getStepY(), 0.11485000000000001); +- double d5 = randomSource.triangle((double)direction.getStepZ(), 0.11485000000000001); +- SmallFireball smallFireball = new SmallFireball(level, d, d1, d2, d3, d4, d5); +- level.addFreshEntity(Util.make(smallFireball, entity -> entity.setItem(itemStack))); +- itemStack.shrink(1); +- return itemStack; ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ IPosition iposition = DispenserBlock.getDispensePosition(sourceblock); ++ double d0 = iposition.x() + (double) ((float) enumdirection.getStepX() * 0.3F); ++ double d1 = iposition.y() + (double) ((float) enumdirection.getStepY() * 0.3F); ++ double d2 = iposition.z() + (double) ((float) enumdirection.getStepZ() * 0.3F); ++ ServerLevel worldserver = sourceblock.level(); ++ RandomSource randomsource = worldserver.random; ++ double d3 = randomsource.triangle((double) enumdirection.getStepX(), 0.11485000000000001D); ++ double d4 = randomsource.triangle((double) enumdirection.getStepY(), 0.11485000000000001D); ++ double d5 = randomsource.triangle((double) enumdirection.getStepZ(), 0.11485000000000001D); ++ ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d3, d4, d5)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ SmallFireball entitysmallfireball = new SmallFireball(worldserver, d0, d1, d2, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ()); ++ entitysmallfireball.setItem(itemstack1); ++ entitysmallfireball.projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(sourceblock.blockEntity()); ++ ++ worldserver.addFreshEntity(entitysmallfireball); ++ // itemstack.shrink(1); // Handled during event processing ++ // CraftBukkit end ++ return itemstack; + } + + @Override +@@ -369,13 +607,56 @@ + private final DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior(); + + @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- DispensibleContainerItem dispensibleContainerItem = (DispensibleContainerItem)itemStack.getItem(); +- BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); +- Level level = blockSource.level(); +- if (dispensibleContainerItem.emptyContents(null, level, blockPos, null)) { +- dispensibleContainerItem.checkExtraContent(null, level, itemStack, blockPos); +- return new ItemStack(Items.BUCKET); ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ DispensibleContainerItem dispensiblecontaineritem = (DispensibleContainerItem) itemstack.getItem(); ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ ServerLevel worldserver = sourceblock.level(); ++ ++ // CraftBukkit start ++ int x = blockposition.getX(); ++ int y = blockposition.getY(); ++ int z = blockposition.getZ(); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ if (iblockdata.isAir() || iblockdata.canBeReplaced() || (dispensiblecontaineritem instanceof BucketItem && iblockdata.getBlock() instanceof LiquidBlockContainer && ((LiquidBlockContainer) iblockdata.getBlock()).canPlaceLiquid((Player) null, worldserver, blockposition, iblockdata, ((BucketItem) dispensiblecontaineritem).content))) { ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(x, y, z)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ dispensiblecontaineritem = (DispensibleContainerItem) CraftItemStack.asNMSCopy(event.getItem()).getItem(); ++ } ++ // CraftBukkit end ++ ++ if (dispensiblecontaineritem.emptyContents((Player) null, worldserver, blockposition, (BlockHitResult) null)) { ++ dispensiblecontaineritem.checkExtraContent((Player) null, worldserver, itemstack, blockposition); ++ // CraftBukkit start - Handle stacked buckets ++ Item item = Items.BUCKET; ++ itemstack.shrink(1); ++ if (itemstack.isEmpty()) { ++ itemstack.setItem(Items.BUCKET); ++ itemstack.setCount(1); ++ } else if (sourceblock.blockEntity().addItem(new ItemStack(item)) < 0) { ++ this.defaultDispenseItemBehavior.dispense(sourceblock, new ItemStack(item)); ++ } ++ return itemstack; ++ // CraftBukkit end + } else { + return this.defaultDispenseItemBehavior.dispense(blockSource, itemStack); + } +@@ -394,19 +676,50 @@ + private final DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior(); + + @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- LevelAccessor levelAccessor = blockSource.level(); +- BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); +- BlockState blockState = levelAccessor.getBlockState(blockPos); +- if (blockState.getBlock() instanceof BucketPickup bucketPickup) { +- ItemStack itemStack1 = bucketPickup.pickupBlock(null, levelAccessor, blockPos, blockState); +- if (itemStack1.isEmpty()) { +- return super.execute(blockSource, itemStack); ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ Block block = iblockdata.getBlock(); ++ ++ if (block instanceof BucketPickup) { ++ BucketPickup ifluidsource = (BucketPickup) block; ++ ItemStack itemstack1 = ifluidsource.pickupBlock((Player) null, DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); // CraftBukkit ++ ++ if (itemstack1.isEmpty()) { ++ return super.execute(sourceblock, itemstack); + } else { +- levelAccessor.gameEvent(null, GameEvent.FLUID_PICKUP, blockPos); +- Item item = itemStack1.getItem(); +- itemStack.shrink(1); +- if (itemStack.isEmpty()) { ++ worldserver.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockposition); ++ Item item = itemstack1.getItem(); ++ ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ itemstack1 = ifluidsource.pickupBlock((Player) null, worldserver, blockposition, iblockdata); // From above ++ // CraftBukkit end ++ ++ itemstack.shrink(1); ++ if (itemstack.isEmpty()) { + return new ItemStack(item); + } else { + if (blockSource.blockEntity().addItem(new ItemStack(item)) < 0) { +@@ -423,21 +736,52 @@ + }); + DispenserBlock.registerBehavior(Items.FLINT_AND_STEEL, new OptionalDispenseItemBehavior() { + @Override +- protected ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Level level = blockSource.level(); ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ + this.setSuccess(true); +- Direction direction = blockSource.state().getValue(DispenserBlock.FACING); +- BlockPos blockPos = blockSource.pos().relative(direction); +- BlockState blockState = level.getBlockState(blockPos); +- if (BaseFireBlock.canBePlacedAt(level, blockPos, direction)) { +- level.setBlockAndUpdate(blockPos, BaseFireBlock.getState(level, blockPos)); +- level.gameEvent(null, GameEvent.BLOCK_PLACE, blockPos); +- } else if (CampfireBlock.canLight(blockState) || CandleBlock.canLight(blockState) || CandleCakeBlock.canLight(blockState)) { +- level.setBlockAndUpdate(blockPos, blockState.setValue(BlockStateProperties.LIT, Boolean.valueOf(true))); +- level.gameEvent(null, GameEvent.BLOCK_CHANGE, blockPos); +- } else if (blockState.getBlock() instanceof TntBlock) { +- TntBlock.explode(level, blockPos); +- level.removeBlock(blockPos, false); ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ BlockPos blockposition = sourceblock.pos().relative(enumdirection); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ ++ if (BaseFireBlock.canBePlacedAt(worldserver, blockposition, enumdirection)) { ++ // CraftBukkit start - Ignition by dispensing flint and steel ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(worldserver, blockposition, sourceblock.pos()).isCancelled()) { ++ worldserver.setBlockAndUpdate(blockposition, BaseFireBlock.getState(worldserver, blockposition)); ++ worldserver.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockposition); ++ } ++ // CraftBukkit end ++ } else if (!CampfireBlock.canLight(iblockdata) && !CandleBlock.canLight(iblockdata) && !CandleCakeBlock.canLight(iblockdata)) { ++ if (iblockdata.getBlock() instanceof TntBlock && org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(worldserver, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.DISPENSER, null, sourceblock.pos())) { // CraftBukkit - TNTPrimeEvent ++ TntBlock.explode(worldserver, blockposition); ++ worldserver.removeBlock(blockposition, false); ++ } else { ++ this.setSuccess(false); ++ } + } else { + this.setSuccess(false); + } +@@ -453,28 +798,109 @@ + @Override + protected ItemStack execute(BlockSource blockSource, ItemStack itemStack) { + this.setSuccess(true); +- Level level = blockSource.level(); +- BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); +- if (!BoneMealItem.growCrop(itemStack, level, blockPos) && !BoneMealItem.growWaterPlant(itemStack, level, blockPos, null)) { ++ ServerLevel worldserver = sourceblock.level(); ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ // CraftBukkit start ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ worldserver.captureTreeGeneration = true; ++ // CraftBukkit end ++ ++ if (!BoneMealItem.growCrop(itemstack, worldserver, blockposition) && !BoneMealItem.growWaterPlant(itemstack, worldserver, blockposition, (Direction) null)) { + this.setSuccess(false); + } else if (!level.isClientSide) { + level.levelEvent(1505, blockPos, 0); + } ++ // CraftBukkit start ++ worldserver.captureTreeGeneration = false; ++ if (worldserver.capturedBlockStates.size() > 0) { ++ TreeType treeType = SaplingBlock.treeType; ++ SaplingBlock.treeType = null; ++ Location location = CraftLocation.toBukkit(blockposition, worldserver.getWorld()); ++ List blocks = new java.util.ArrayList<>(worldserver.capturedBlockStates.values()); ++ worldserver.capturedBlockStates.clear(); ++ StructureGrowEvent structureEvent = null; ++ if (treeType != null) { ++ structureEvent = new StructureGrowEvent(location, treeType, false, null, blocks); ++ org.bukkit.Bukkit.getPluginManager().callEvent(structureEvent); ++ } + +- return itemStack; ++ BlockFertilizeEvent fertilizeEvent = new BlockFertilizeEvent(location.getBlock(), null, blocks); ++ fertilizeEvent.setCancelled(structureEvent != null && structureEvent.isCancelled()); ++ org.bukkit.Bukkit.getPluginManager().callEvent(fertilizeEvent); ++ ++ if (!fertilizeEvent.isCancelled()) { ++ for (org.bukkit.block.BlockState blockstate : blocks) { ++ blockstate.update(true); ++ } ++ } ++ } ++ // CraftBukkit end ++ ++ return itemstack; + } + }); + DispenserBlock.registerBehavior(Blocks.TNT, new DefaultDispenseItemBehavior() { + @Override +- protected ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Level level = blockSource.level(); +- BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); +- PrimedTnt primedTnt = new PrimedTnt(level, (double)blockPos.getX() + 0.5, (double)blockPos.getY(), (double)blockPos.getZ() + 0.5, null); +- level.addFreshEntity(primedTnt); +- level.playSound(null, primedTnt.getX(), primedTnt.getY(), primedTnt.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent(null, GameEvent.ENTITY_PLACE, blockPos); +- itemStack.shrink(1); +- return itemStack; ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ // CraftBukkit start ++ // EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, (EntityLiving) null); ++ ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ PrimedTnt entitytntprimed = new PrimedTnt(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), (LivingEntity) null); ++ // CraftBukkit end ++ ++ worldserver.addFreshEntity(entitytntprimed); ++ worldserver.playSound((Player) null, entitytntprimed.getX(), entitytntprimed.getY(), entitytntprimed.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F); ++ worldserver.gameEvent((Entity) null, GameEvent.ENTITY_PLACE, blockposition); ++ // itemstack.shrink(1); // CraftBukkit - handled above ++ return itemstack; + } + }); + DispenseItemBehavior dispenseItemBehavior1 = new OptionalDispenseItemBehavior() { +@@ -484,55 +910,94 @@ + return itemStack; + } + }; +- DispenserBlock.registerBehavior(Items.CREEPER_HEAD, dispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.ZOMBIE_HEAD, dispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.DRAGON_HEAD, dispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.SKELETON_SKULL, dispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.PIGLIN_HEAD, dispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.PLAYER_HEAD, dispenseItemBehavior1); +- DispenserBlock.registerBehavior( +- Items.WITHER_SKELETON_SKULL, +- new OptionalDispenseItemBehavior() { +- @Override +- protected ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Level level = blockSource.level(); +- Direction direction = blockSource.state().getValue(DispenserBlock.FACING); +- BlockPos blockPos = blockSource.pos().relative(direction); +- if (level.isEmptyBlock(blockPos) && WitherSkullBlock.canSpawnMob(level, blockPos, itemStack)) { +- level.setBlock( +- blockPos, +- Blocks.WITHER_SKELETON_SKULL +- .defaultBlockState() +- .setValue(SkullBlock.ROTATION, Integer.valueOf(RotationSegment.convertToSegment(direction))), +- 3 +- ); +- level.gameEvent(null, GameEvent.BLOCK_PLACE, blockPos); +- BlockEntity blockEntity = level.getBlockEntity(blockPos); +- if (blockEntity instanceof SkullBlockEntity) { +- WitherSkullBlock.checkSpawn(level, blockPos, (SkullBlockEntity)blockEntity); +- } +- +- itemStack.shrink(1); +- this.setSuccess(true); +- } else { +- this.setSuccess(ArmorItem.dispenseArmor(blockSource, itemStack)); ++ ++ DispenserBlock.registerBehavior(Items.CREEPER_HEAD, dispensebehaviormaybe1); ++ DispenserBlock.registerBehavior(Items.ZOMBIE_HEAD, dispensebehaviormaybe1); ++ DispenserBlock.registerBehavior(Items.DRAGON_HEAD, dispensebehaviormaybe1); ++ DispenserBlock.registerBehavior(Items.SKELETON_SKULL, dispensebehaviormaybe1); ++ DispenserBlock.registerBehavior(Items.PIGLIN_HEAD, dispensebehaviormaybe1); ++ DispenserBlock.registerBehavior(Items.PLAYER_HEAD, dispensebehaviormaybe1); ++ DispenserBlock.registerBehavior(Items.WITHER_SKELETON_SKULL, new OptionalDispenseItemBehavior() { ++ @Override ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ BlockPos blockposition = sourceblock.pos().relative(enumdirection); ++ ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; + } + + return itemStack; + } ++ // CraftBukkit end ++ ++ if (worldserver.isEmptyBlock(blockposition) && WitherSkullBlock.canSpawnMob(worldserver, blockposition, itemstack)) { ++ worldserver.setBlock(blockposition, (IBlockData) Blocks.WITHER_SKELETON_SKULL.defaultBlockState().setValue(SkullBlock.ROTATION, RotationSegment.convertToSegment(enumdirection)), 3); ++ worldserver.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockposition); ++ BlockEntity tileentity = worldserver.getBlockEntity(blockposition); ++ ++ if (tileentity instanceof SkullBlockEntity) { ++ WitherSkullBlock.checkSpawn(worldserver, blockposition, (SkullBlockEntity) tileentity); ++ } ++ ++ itemstack.shrink(1); ++ this.setSuccess(true); ++ } else { ++ this.setSuccess(ArmorItem.dispenseArmor(sourceblock, itemstack)); ++ } ++ ++ return itemstack; + } + ); + DispenserBlock.registerBehavior(Blocks.CARVED_PUMPKIN, new OptionalDispenseItemBehavior() { + @Override +- protected ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Level level = blockSource.level(); +- BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); +- CarvedPumpkinBlock carvedPumpkinBlock = (CarvedPumpkinBlock)Blocks.CARVED_PUMPKIN; +- if (level.isEmptyBlock(blockPos) && carvedPumpkinBlock.canSpawnGolem(level, blockPos)) { +- if (!level.isClientSide) { +- level.setBlock(blockPos, carvedPumpkinBlock.defaultBlockState(), 3); +- level.gameEvent(null, GameEvent.BLOCK_PLACE, blockPos); ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ CarvedPumpkinBlock blockpumpkincarved = (CarvedPumpkinBlock) Blocks.CARVED_PUMPKIN; ++ ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; + } ++ } ++ // CraftBukkit end + + itemStack.shrink(1); + this.setSuccess(true); +@@ -567,26 +1037,51 @@ + return itemStack; + } + } +- +- @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- this.setSuccess(false); +- ServerLevel serverLevel = blockSource.level(); +- BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); +- BlockState blockState = serverLevel.getBlockState(blockPos); +- if (blockState.is(BlockTags.BEEHIVES, hive -> hive.hasProperty(BeehiveBlock.HONEY_LEVEL) && hive.getBlock() instanceof BeehiveBlock) +- && blockState.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) { +- ((BeehiveBlock)blockState.getBlock()) +- .releaseBeesAndResetHoneyLevel(serverLevel, blockState, blockPos, null, BeehiveBlockEntity.BeeReleaseStatus.BEE_RELEASED); +- this.setSuccess(true); +- return this.takeLiquid(blockSource, itemStack, new ItemStack(Items.HONEY_BOTTLE)); +- } else if (serverLevel.getFluidState(blockPos).is(FluidTags.WATER)) { +- this.setSuccess(true); +- return this.takeLiquid(blockSource, itemStack, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER)); +- } else { +- return super.execute(blockSource, itemStack); ++ } ++ ++ @Override ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ this.setSuccess(false); ++ ServerLevel worldserver = sourceblock.level(); ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; + } + } ++ // CraftBukkit end ++ ++ if (iblockdata.is(BlockTags.BEEHIVES, (blockbase_blockdata) -> { ++ return blockbase_blockdata.hasProperty(BeehiveBlock.HONEY_LEVEL) && blockbase_blockdata.getBlock() instanceof BeehiveBlock; ++ }) && (Integer) iblockdata.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) { ++ ((BeehiveBlock) iblockdata.getBlock()).releaseBeesAndResetHoneyLevel(worldserver, iblockdata, blockposition, (Player) null, BeehiveBlockEntity.ReleaseStatus.BEE_RELEASED); ++ this.setSuccess(true); ++ return this.takeLiquid(sourceblock, itemstack, new ItemStack(Items.HONEY_BOTTLE)); ++ } else if (worldserver.getFluidState(blockposition).is(FluidTags.WATER)) { ++ this.setSuccess(true); ++ return this.takeLiquid(sourceblock, itemstack, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER)); ++ } else { ++ return super.execute(sourceblock, itemstack); ++ } + } + ); + DispenserBlock.registerBehavior(Items.GLOWSTONE, new OptionalDispenseItemBehavior() { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java.patch new file mode 100644 index 0000000000..bd4f8f33c6 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java.patch @@ -0,0 +1,95 @@ +--- a/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java ++++ b/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java +@@ -16,20 +21,51 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end + + public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior { + @Override +- protected ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- ServerLevel serverLevel = blockSource.level(); +- if (!serverLevel.isClientSide()) { +- BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); +- this.setSuccess(tryShearBeehive(serverLevel, blockPos) || tryShearLivingEntity(serverLevel, blockPos)); +- if (this.isSuccess() && itemStack.hurt(1, serverLevel.getRandom(), null)) { +- itemStack.setCount(0); ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; + } + } ++ // CraftBukkit end + +- return itemStack; ++ if (!worldserver.isClientSide()) { ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ ++ this.setSuccess(tryShearBeehive(worldserver, blockposition) || tryShearLivingEntity(worldserver, blockposition, bukkitBlock, craftItem)); // CraftBukkit ++ if (this.isSuccess() && itemstack.hurt(1, worldserver.getRandom(), (ServerPlayer) null)) { ++ itemstack.setCount(0); ++ } ++ } ++ ++ return itemstack; + } + + private static boolean tryShearBeehive(ServerLevel level, BlockPos pos) { +@@ -51,12 +91,26 @@ + return false; + } + +- private static boolean tryShearLivingEntity(ServerLevel level, BlockPos pos) { +- for (LivingEntity livingEntity : level.getEntitiesOfClass(LivingEntity.class, new AABB(pos), EntitySelector.NO_SPECTATORS)) { +- if (livingEntity instanceof Shearable shearable && shearable.readyForShearing()) { +- shearable.shear(SoundSource.BLOCKS); +- level.gameEvent(null, GameEvent.SHEAR, pos); +- return true; ++ private static boolean tryShearLivingEntity(ServerLevel worldserver, BlockPos blockposition, org.bukkit.block.Block bukkitBlock, CraftItemStack craftItem) { // CraftBukkit - add args ++ List list = worldserver.getEntitiesOfClass(LivingEntity.class, new AABB(blockposition), EntitySelector.NO_SPECTATORS); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ LivingEntity entityliving = (LivingEntity) iterator.next(); ++ ++ if (entityliving instanceof Shearable) { ++ Shearable ishearable = (Shearable) entityliving; ++ ++ if (ishearable.readyForShearing()) { ++ // CraftBukkit start ++ if (CraftEventFactory.callBlockShearEntityEvent(entityliving, bukkitBlock, craftItem).isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end ++ ishearable.shear(SoundSource.BLOCKS); ++ worldserver.gameEvent((Entity) null, GameEvent.SHEAR, blockposition); ++ return true; ++ } + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java.patch new file mode 100644 index 0000000000..caf361635c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java ++++ b/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java +@@ -10,6 +10,12 @@ + import net.minecraft.world.level.block.DispenserBlock; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end ++ + public class ShulkerBoxDispenseBehavior extends OptionalDispenseItemBehavior { + private static final Logger LOGGER = LogUtils.getLogger(); + +@@ -22,6 +32,30 @@ + BlockPos blockPos = blockSource.pos().relative(direction); + Direction direction1 = blockSource.level().isEmptyBlock(blockPos.below()) ? direction : Direction.UP; + ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(sourceblock.level(), sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!DispenserBlock.eventFired) { ++ sourceblock.level().getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ + try { + this.setSuccess( + ((BlockItem)item).place(new DirectionalPlaceContext(blockSource.level(), blockPos, direction, itemStack, direction1)).consumesAction() diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/nbt/ByteArrayTag.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/nbt/ByteArrayTag.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/nbt/ByteArrayTag.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/nbt/IntArrayTag.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/nbt/IntArrayTag.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/nbt/IntArrayTag.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/nbt/NbtIo.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/nbt/NbtIo.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/nbt/NbtIo.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/network/Connection.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/network/Connection.java.patch new file mode 100644 index 0000000000..43f5c67ab8 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/network/Connection.java.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/network/Connection.java ++++ b/net/minecraft/network/Connection.java +@@ -97,6 +105,7 @@ + private volatile Component delayedDisconnect; + @Nullable + BandwidthDebugMonitor bandwidthDebugMonitor; ++ public String hostname = ""; // CraftBukkit - add field + + public Connection(PacketFlow receiving) { + this.receiving = receiving; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/network/FriendlyByteBuf.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/network/FriendlyByteBuf.java.patch new file mode 100644 index 0000000000..471c61ca94 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/network/FriendlyByteBuf.java.patch @@ -0,0 +1,54 @@ +--- a/net/minecraft/network/FriendlyByteBuf.java ++++ b/net/minecraft/network/FriendlyByteBuf.java +@@ -80,6 +81,8 @@ + import org.joml.Quaternionf; + import org.joml.Vector3f; + ++import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit ++ + public class FriendlyByteBuf extends ByteBuf { + public static final int DEFAULT_NBT_QUOTA = 2097152; + private final ByteBuf source; +@@ -536,8 +586,8 @@ + try { + NbtIo.writeAnyTag(tag, new ByteBufOutputStream(this)); + return this; +- } catch (IOException var3) { +- throw new EncoderException(var3); ++ } catch (Exception ioexception) { // CraftBukkit - IOException -> Exception ++ throw new EncoderException(ioexception); + } + } + +@@ -562,7 +614,7 @@ + } + + public FriendlyByteBuf writeItem(ItemStack stack) { +- if (stack.isEmpty()) { ++ if (stack.isEmpty() || stack.getItem() == null) { // CraftBukkit - NPE fix itemstack.getItem() + this.writeBoolean(false); + } else { + this.writeBoolean(true); +@@ -584,11 +638,17 @@ + if (!this.readBoolean()) { + return ItemStack.EMPTY; + } else { +- Item item = this.readById(BuiltInRegistries.ITEM); +- int _byte = this.readByte(); +- ItemStack itemStack = new ItemStack(item, _byte); +- itemStack.setTag(this.readNbt()); +- return itemStack; ++ Item item = (Item) this.readById((IdMap) BuiltInRegistries.ITEM); ++ byte b0 = this.readByte(); ++ ItemStack itemstack = new ItemStack(item, b0); ++ ++ itemstack.setTag(this.readNbt()); ++ // CraftBukkit start ++ if (itemstack.getTag() != null) { ++ CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); ++ } ++ // CraftBukkit end ++ return itemstack; + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/network/chat/Component.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/network/chat/Component.java.patch new file mode 100644 index 0000000000..81502c0e4c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/network/chat/Component.java.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/network/chat/Component.java ++++ b/net/minecraft/network/chat/Component.java +@@ -33,8 +34,23 @@ + import net.minecraft.resources.ResourceLocation; + import net.minecraft.util.FormattedCharSequence; + import net.minecraft.world.level.ChunkPos; ++// CraftBukkit start ++import java.util.stream.Stream; ++// CraftBukkit end + +-public interface Component extends Message, FormattedText { ++public interface Component extends Message, FormattedText, Iterable { // CraftBukkit ++ ++ // CraftBukkit start ++ default Stream stream() { ++ return com.google.common.collect.Streams.concat(new Stream[]{Stream.of(this), this.getSiblings().stream().flatMap(Component::stream)}); ++ } ++ ++ @Override ++ default Iterator iterator() { ++ return this.stream().iterator(); ++ } ++ // CraftBukkit end ++ + Style getStyle(); + + ComponentContents getContents(); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/network/chat/TextColor.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/network/chat/TextColor.java.patch new file mode 100644 index 0000000000..cb8af9e589 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/network/chat/TextColor.java.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/network/chat/TextColor.java ++++ b/net/minecraft/network/chat/TextColor.java +@@ -15,15 +16,18 @@ + public final class TextColor { + private static final String CUSTOM_COLOR_PREFIX = "#"; + public static final Codec CODEC = Codec.STRING.comapFlatMap(TextColor::parseColor, TextColor::serialize); +- private static final Map LEGACY_FORMAT_TO_COLOR = Stream.of(ChatFormatting.values()) +- .filter(ChatFormatting::isColor) +- .collect(ImmutableMap.toImmutableMap(Function.identity(), chatFormatting -> new TextColor(chatFormatting.getColor(), chatFormatting.getName()))); +- private static final Map NAMED_COLORS = LEGACY_FORMAT_TO_COLOR.values() +- .stream() +- .collect(ImmutableMap.toImmutableMap(textColor -> textColor.name, Function.identity())); ++ private static final Map LEGACY_FORMAT_TO_COLOR = (Map) Stream.of(ChatFormatting.values()).filter(ChatFormatting::isColor).collect(ImmutableMap.toImmutableMap(Function.identity(), (enumchatformat) -> { ++ return new TextColor(enumchatformat.getColor(), enumchatformat.getName(), enumchatformat); // CraftBukkit ++ })); ++ private static final Map NAMED_COLORS = (Map) TextColor.LEGACY_FORMAT_TO_COLOR.values().stream().collect(ImmutableMap.toImmutableMap((chathexcolor) -> { ++ return chathexcolor.name; ++ }, Function.identity())); + private final int value; + @Nullable +- private final String name; ++ public final String name; ++ // CraftBukkit start ++ @Nullable ++ public final ChatFormatting format; + + private TextColor(int value, String name) { + this.value = value & 16777215; +@@ -34,6 +40,7 @@ + this.value = value & 16777215; + this.name = null; + } ++ // CraftBukkit end + + public int getValue() { + return this.value; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/PacketUtils.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/PacketUtils.java.patch new file mode 100644 index 0000000000..9c3a79df96 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/PacketUtils.java.patch @@ -0,0 +1,65 @@ +--- a/net/minecraft/network/protocol/PacketUtils.java ++++ b/net/minecraft/network/protocol/PacketUtils.java +@@ -4,8 +4,14 @@ + import net.minecraft.CrashReport; + import net.minecraft.ReportedException; + import net.minecraft.network.PacketListener; +-import net.minecraft.server.RunningOnDifferentThreadException; ++import net.minecraft.server.CancelledPacketHandleException; ++import org.slf4j.Logger; ++ ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.network.ServerCommonPacketListenerImpl; ++// CraftBukkit end + import net.minecraft.util.thread.BlockableEventLoop; + import org.slf4j.Logger; + +@@ -18,17 +26,19 @@ + + public static void ensureRunningOnSameThread(Packet packet, T processor, BlockableEventLoop executor) throws RunningOnDifferentThreadException { + if (!executor.isSameThread()) { +- executor.executeIfPossible( +- () -> { +- if (processor.shouldHandleMessage(packet)) { +- try { +- packet.handle(processor); +- } catch (Exception var6) { +- if (var6 instanceof ReportedException reportedException && reportedException.getCause() instanceof OutOfMemoryError +- || processor.shouldPropagateHandlingExceptions()) { +- if (var6 instanceof ReportedException reportedException1) { +- processor.fillCrashReport(reportedException1.getReport()); +- throw var6; ++ executor.executeIfPossible(() -> { ++ if (MinecraftServer.getServer().hasStopped() || (processor instanceof ServerCommonPacketListenerImpl && ((ServerCommonPacketListenerImpl) processor).processedDisconnect)) return; // CraftBukkit, MC-142590 ++ if (processor.shouldHandleMessage(packet)) { ++ try { ++ packet.handle(processor); ++ } catch (Exception exception) { ++ label25: ++ { ++ if (exception instanceof ReportedException) { ++ ReportedException reportedexception = (ReportedException) exception; ++ ++ if (reportedexception.getCause() instanceof OutOfMemoryError) { ++ break label25; + } + + CrashReport crashReport = CrashReport.forThrowable(var6, "Main thread packet handler"); +@@ -42,8 +63,13 @@ + LOGGER.debug("Ignoring packet due to disconnection: {}", packet); + } + } +- ); +- throw RunningOnDifferentThreadException.RUNNING_ON_DIFFERENT_THREAD; ++ ++ }); ++ throw CancelledPacketHandleException.RUNNING_ON_DIFFERENT_THREAD; ++ // CraftBukkit start - SPIGOT-5477, MC-142590 ++ } else if (MinecraftServer.getServer().hasStopped() || (processor instanceof ServerCommonPacketListenerImpl && ((ServerCommonPacketListenerImpl) processor).processedDisconnect)) { ++ throw CancelledPacketHandleException.RUNNING_ON_DIFFERENT_THREAD; ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java.patch new file mode 100644 index 0000000000..ecaab61eb6 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java ++++ b/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java +@@ -11,11 +12,7 @@ + + public record ServerboundCustomPayloadPacket(CustomPacketPayload payload) implements Packet { + private static final int MAX_PAYLOAD_SIZE = 32767; +- private static final Map> KNOWN_TYPES = ImmutableMap.>builder( +- +- ) +- .put(BrandPayload.ID, BrandPayload::new) +- .build(); ++ private static final Map> KNOWN_TYPES = ImmutableMap.>builder().build(); // CraftBukkit - no special handling + + public ServerboundCustomPayloadPacket(FriendlyByteBuf friendlyByteBuf) { + this(readPayload(friendlyByteBuf.readResourceLocation(), friendlyByteBuf)); +@@ -26,11 +24,13 @@ + return (CustomPacketPayload)(reader != null ? reader.apply(friendlyByteBuf) : readUnknownPayload(resourceLocation, friendlyByteBuf)); + } + +- private static DiscardedPayload readUnknownPayload(ResourceLocation resourceLocation, FriendlyByteBuf friendlyByteBuf) { +- int i = friendlyByteBuf.readableBytes(); ++ private static UnknownPayload readUnknownPayload(ResourceLocation minecraftkey, FriendlyByteBuf packetdataserializer) { // CraftBukkit ++ int i = packetdataserializer.readableBytes(); ++ + if (i >= 0 && i <= 32767) { +- friendlyByteBuf.skipBytes(i); +- return new DiscardedPayload(resourceLocation); ++ // CraftBukkit start ++ return new UnknownPayload(minecraftkey, packetdataserializer.readBytes(i)); ++ // CraftBukkit end + } else { + throw new IllegalArgumentException("Payload may not be larger than 32767 bytes"); + } +@@ -46,4 +45,14 @@ + public void handle(ServerCommonPacketListener handler) { + handler.handleCustomPayload(this); + } ++ ++ // CraftBukkit start ++ public record UnknownPayload(ResourceLocation id, io.netty.buffer.ByteBuf data) implements CustomPacketPayload { ++ ++ @Override ++ public void write(FriendlyByteBuf packetdataserializer) { ++ packetdataserializer.writeBytes(data); ++ } ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java.patch new file mode 100644 index 0000000000..11f0359b0a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java ++++ b/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java +@@ -26,8 +27,10 @@ + } + + public ClientboundInitializeBorderPacket(WorldBorder worldBorder) { +- this.newCenterX = worldBorder.getCenterX(); +- this.newCenterZ = worldBorder.getCenterZ(); ++ // CraftBukkit start - multiply out nether border ++ this.newCenterX = worldBorder.getCenterX() * worldBorder.world.dimensionType().coordinateScale(); ++ this.newCenterZ = worldBorder.getCenterZ() * worldBorder.world.dimensionType().coordinateScale(); ++ // CraftBukkit end + this.oldSize = worldBorder.getSize(); + this.newSize = worldBorder.getLerpTarget(); + this.lerpTime = worldBorder.getLerpRemainingTime(); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java.patch new file mode 100644 index 0000000000..01382a5fae --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java ++++ b/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java +@@ -23,13 +22,26 @@ + this.states = new BlockState[size]; + int i = 0; + +- for (short s : positions) { +- this.positions[i] = s; +- this.states[i] = section.getBlockState(SectionPos.sectionRelativeX(s), SectionPos.sectionRelativeY(s), SectionPos.sectionRelativeZ(s)); +- i++; ++ this.positions = new short[i]; ++ this.states = new IBlockData[i]; ++ int j = 0; ++ ++ for (ShortIterator shortiterator = positions.iterator(); shortiterator.hasNext(); ++j) { ++ short short0 = (Short) shortiterator.next(); ++ ++ this.positions[j] = short0; ++ this.states[j] = (section != null) ? section.getBlockState(SectionPos.sectionRelativeX(short0), SectionPos.sectionRelativeY(short0), SectionPos.sectionRelativeZ(short0)) : net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(); // CraftBukkit - SPIGOT-6076, Mojang bug when empty chunk section notified + } + } + ++ // CraftBukkit start - Add constructor ++ public ClientboundSectionBlocksUpdatePacket(SectionPos sectionposition, ShortSet shortset, IBlockData[] states) { ++ this.sectionPos = sectionposition; ++ this.positions = shortset.toShortArray(); ++ this.states = states; ++ } ++ // CraftBukkit end ++ + public ClientboundSectionBlocksUpdatePacket(FriendlyByteBuf buffer) { + this.sectionPos = SectionPos.of(buffer.readLong()); + int varInt = buffer.readVarInt(); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java.patch new file mode 100644 index 0000000000..5f90f331a9 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java ++++ b/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java +@@ -9,8 +10,10 @@ + private final double newCenterZ; + + public ClientboundSetBorderCenterPacket(WorldBorder worldBorder) { +- this.newCenterX = worldBorder.getCenterX(); +- this.newCenterZ = worldBorder.getCenterZ(); ++ // CraftBukkit start - multiply out nether border ++ this.newCenterX = worldBorder.getCenterX() * (worldBorder.world != null ? worldBorder.world.dimensionType().coordinateScale() : 1.0); ++ this.newCenterZ = worldBorder.getCenterZ() * (worldBorder.world != null ? worldBorder.world.dimensionType().coordinateScale() : 1.0); ++ // CraftBukkit end + } + + public ClientboundSetBorderCenterPacket(FriendlyByteBuf buffer) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/game/ServerboundUseItemOnPacket.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/game/ServerboundUseItemOnPacket.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/game/ServerboundUseItemOnPacket.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/game/ServerboundUseItemPacket.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/game/ServerboundUseItemPacket.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/game/ServerboundUseItemPacket.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/network/syncher/SynchedEntityData.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/network/syncher/SynchedEntityData.java.patch new file mode 100644 index 0000000000..a1f82288d1 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/network/syncher/SynchedEntityData.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/network/syncher/SynchedEntityData.java ++++ b/net/minecraft/network/syncher/SynchedEntityData.java +@@ -132,6 +148,13 @@ + } + } + ++ // CraftBukkit start - add method from above ++ public void markDirty(EntityDataAccessor datawatcherobject) { ++ this.getItem(datawatcherobject).setDirty(true); ++ this.isDirty = true; ++ } ++ // CraftBukkit end ++ + public boolean isDirty() { + return this.isDirty; + } +@@ -220,6 +244,18 @@ + return this.itemsById.isEmpty(); + } + ++ // CraftBukkit start ++ public void refresh(ServerPlayer to) { ++ if (!this.isEmpty()) { ++ List> list = this.getNonDefaultValues(); ++ ++ if (list != null) { ++ to.connection.send(new ClientboundSetEntityDataPacket(this.entity.getId(), list)); ++ } ++ } ++ } ++ // CraftBukkit end ++ + public static class DataItem { + final EntityDataAccessor accessor; + T value; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/Bootstrap.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/Bootstrap.java.patch new file mode 100644 index 0000000000..d2517a5bd1 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/Bootstrap.java.patch @@ -0,0 +1,100 @@ +--- a/net/minecraft/server/Bootstrap.java ++++ b/net/minecraft/server/Bootstrap.java +@@ -38,8 +43,25 @@ + public static final AtomicLong bootstrapDuration = new AtomicLong(-1L); + + public static void bootStrap() { +- if (!isBootstrapped) { +- isBootstrapped = true; ++ if (!Bootstrap.isBootstrapped) { ++ // CraftBukkit start ++ String name = Bootstrap.class.getSimpleName(); ++ switch (name) { ++ case "DispenserRegistry": ++ break; ++ case "Bootstrap": ++ System.err.println("***************************************************************************"); ++ System.err.println("*** WARNING: This server jar may only be used for development purposes. ***"); ++ System.err.println("***************************************************************************"); ++ break; ++ default: ++ System.err.println("**********************************************************************"); ++ System.err.println("*** WARNING: This server jar is unsupported, use at your own risk. ***"); ++ System.err.println("**********************************************************************"); ++ break; ++ } ++ // CraftBukkit end ++ Bootstrap.isBootstrapped = true; + Instant instant = Instant.now(); + if (BuiltInRegistries.REGISTRY.keySet().isEmpty()) { + throw new IllegalStateException("Unable to load registries"); +@@ -58,6 +81,69 @@ + wrapStreams(); + bootstrapDuration.set(Duration.between(instant, Instant.now()).toMillis()); + } ++ // CraftBukkit start - easier than fixing the decompile ++ BlockStateData.register(1008, "{Name:'minecraft:oak_sign',Properties:{rotation:'0'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'0'}}"); ++ BlockStateData.register(1009, "{Name:'minecraft:oak_sign',Properties:{rotation:'1'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'1'}}"); ++ BlockStateData.register(1010, "{Name:'minecraft:oak_sign',Properties:{rotation:'2'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'2'}}"); ++ BlockStateData.register(1011, "{Name:'minecraft:oak_sign',Properties:{rotation:'3'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'3'}}"); ++ BlockStateData.register(1012, "{Name:'minecraft:oak_sign',Properties:{rotation:'4'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'4'}}"); ++ BlockStateData.register(1013, "{Name:'minecraft:oak_sign',Properties:{rotation:'5'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'5'}}"); ++ BlockStateData.register(1014, "{Name:'minecraft:oak_sign',Properties:{rotation:'6'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'6'}}"); ++ BlockStateData.register(1015, "{Name:'minecraft:oak_sign',Properties:{rotation:'7'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'7'}}"); ++ BlockStateData.register(1016, "{Name:'minecraft:oak_sign',Properties:{rotation:'8'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'8'}}"); ++ BlockStateData.register(1017, "{Name:'minecraft:oak_sign',Properties:{rotation:'9'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'9'}}"); ++ BlockStateData.register(1018, "{Name:'minecraft:oak_sign',Properties:{rotation:'10'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'10'}}"); ++ BlockStateData.register(1019, "{Name:'minecraft:oak_sign',Properties:{rotation:'11'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'11'}}"); ++ BlockStateData.register(1020, "{Name:'minecraft:oak_sign',Properties:{rotation:'12'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'12'}}"); ++ BlockStateData.register(1021, "{Name:'minecraft:oak_sign',Properties:{rotation:'13'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'13'}}"); ++ BlockStateData.register(1022, "{Name:'minecraft:oak_sign',Properties:{rotation:'14'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'14'}}"); ++ BlockStateData.register(1023, "{Name:'minecraft:oak_sign',Properties:{rotation:'15'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'15'}}"); ++ ItemIdFix.ITEM_NAMES.put(323, "minecraft:oak_sign"); ++ ++ BlockStateData.register(1440, "{Name:\'minecraft:portal\',Properties:{axis:\'x\'}}", new String[]{"{Name:\'minecraft:portal\',Properties:{axis:\'x\'}}"}); ++ ++ ItemIdFix.ITEM_NAMES.put(409, "minecraft:prismarine_shard"); ++ ItemIdFix.ITEM_NAMES.put(410, "minecraft:prismarine_crystals"); ++ ItemIdFix.ITEM_NAMES.put(411, "minecraft:rabbit"); ++ ItemIdFix.ITEM_NAMES.put(412, "minecraft:cooked_rabbit"); ++ ItemIdFix.ITEM_NAMES.put(413, "minecraft:rabbit_stew"); ++ ItemIdFix.ITEM_NAMES.put(414, "minecraft:rabbit_foot"); ++ ItemIdFix.ITEM_NAMES.put(415, "minecraft:rabbit_hide"); ++ ItemIdFix.ITEM_NAMES.put(416, "minecraft:armor_stand"); ++ ++ ItemIdFix.ITEM_NAMES.put(423, "minecraft:mutton"); ++ ItemIdFix.ITEM_NAMES.put(424, "minecraft:cooked_mutton"); ++ ItemIdFix.ITEM_NAMES.put(425, "minecraft:banner"); ++ ItemIdFix.ITEM_NAMES.put(426, "minecraft:end_crystal"); ++ ItemIdFix.ITEM_NAMES.put(427, "minecraft:spruce_door"); ++ ItemIdFix.ITEM_NAMES.put(428, "minecraft:birch_door"); ++ ItemIdFix.ITEM_NAMES.put(429, "minecraft:jungle_door"); ++ ItemIdFix.ITEM_NAMES.put(430, "minecraft:acacia_door"); ++ ItemIdFix.ITEM_NAMES.put(431, "minecraft:dark_oak_door"); ++ ItemIdFix.ITEM_NAMES.put(432, "minecraft:chorus_fruit"); ++ ItemIdFix.ITEM_NAMES.put(433, "minecraft:chorus_fruit_popped"); ++ ItemIdFix.ITEM_NAMES.put(434, "minecraft:beetroot"); ++ ItemIdFix.ITEM_NAMES.put(435, "minecraft:beetroot_seeds"); ++ ItemIdFix.ITEM_NAMES.put(436, "minecraft:beetroot_soup"); ++ ItemIdFix.ITEM_NAMES.put(437, "minecraft:dragon_breath"); ++ ItemIdFix.ITEM_NAMES.put(438, "minecraft:splash_potion"); ++ ItemIdFix.ITEM_NAMES.put(439, "minecraft:spectral_arrow"); ++ ItemIdFix.ITEM_NAMES.put(440, "minecraft:tipped_arrow"); ++ ItemIdFix.ITEM_NAMES.put(441, "minecraft:lingering_potion"); ++ ItemIdFix.ITEM_NAMES.put(442, "minecraft:shield"); ++ ItemIdFix.ITEM_NAMES.put(443, "minecraft:elytra"); ++ ItemIdFix.ITEM_NAMES.put(444, "minecraft:spruce_boat"); ++ ItemIdFix.ITEM_NAMES.put(445, "minecraft:birch_boat"); ++ ItemIdFix.ITEM_NAMES.put(446, "minecraft:jungle_boat"); ++ ItemIdFix.ITEM_NAMES.put(447, "minecraft:acacia_boat"); ++ ItemIdFix.ITEM_NAMES.put(448, "minecraft:dark_oak_boat"); ++ ItemIdFix.ITEM_NAMES.put(449, "minecraft:totem_of_undying"); ++ ItemIdFix.ITEM_NAMES.put(450, "minecraft:shulker_shell"); ++ ItemIdFix.ITEM_NAMES.put(452, "minecraft:iron_nugget"); ++ ItemIdFix.ITEM_NAMES.put(453, "minecraft:knowledge_book"); ++ ++ ItemSpawnEggFix.ID_TO_ENTITY[23] = "Arrow"; ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/Main.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/Main.java.patch new file mode 100644 index 0000000000..9a3e9694d6 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/Main.java.patch @@ -0,0 +1,316 @@ +--- a/net/minecraft/server/Main.java ++++ b/net/minecraft/server/Main.java +@@ -59,28 +60,37 @@ + import net.minecraft.world.level.storage.WorldData; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.google.common.base.Charsets; ++import java.io.InputStreamReader; ++import java.util.concurrent.atomic.AtomicReference; ++import net.minecraft.SharedConstants; ++import org.bukkit.configuration.file.YamlConfiguration; ++// CraftBukkit end ++ + public class Main { + private static final Logger LOGGER = LogUtils.getLogger(); + + @DontObfuscate +- public static void main(String[] args) { ++ public static void main(final OptionSet optionset) { // CraftBukkit - replaces main(String[] astring) + SharedConstants.tryDetectVersion(); +- OptionParser optionParser = new OptionParser(); +- OptionSpec optionSpec = optionParser.accepts("nogui"); +- OptionSpec optionSpec1 = optionParser.accepts("initSettings", "Initializes 'server.properties' and 'eula.txt', then quits"); +- OptionSpec optionSpec2 = optionParser.accepts("demo"); +- OptionSpec optionSpec3 = optionParser.accepts("bonusChest"); +- OptionSpec optionSpec4 = optionParser.accepts("forceUpgrade"); +- OptionSpec optionSpec5 = optionParser.accepts("eraseCache"); +- OptionSpec optionSpec6 = optionParser.accepts("safeMode", "Loads level with vanilla datapack only"); +- OptionSpec optionSpec7 = optionParser.accepts("help").forHelp(); +- OptionSpec optionSpec8 = optionParser.accepts("universe").withRequiredArg().defaultsTo("."); +- OptionSpec optionSpec9 = optionParser.accepts("world").withRequiredArg(); +- OptionSpec optionSpec10 = optionParser.accepts("port").withRequiredArg().ofType(Integer.class).defaultsTo(-1); +- OptionSpec optionSpec11 = optionParser.accepts("serverId").withRequiredArg(); +- OptionSpec optionSpec12 = optionParser.accepts("jfrProfile"); +- OptionSpec optionSpec13 = optionParser.accepts("pidFile").withRequiredArg().withValuesConvertedBy(new PathConverter()); +- OptionSpec optionSpec14 = optionParser.nonOptions(); ++ /* CraftBukkit start - Replace everything ++ OptionParser optionparser = new OptionParser(); ++ OptionSpec optionspec = optionparser.accepts("nogui"); ++ OptionSpec optionspec1 = optionparser.accepts("initSettings", "Initializes 'server.properties' and 'eula.txt', then quits"); ++ OptionSpec optionspec2 = optionparser.accepts("demo"); ++ OptionSpec optionspec3 = optionparser.accepts("bonusChest"); ++ OptionSpec optionspec4 = optionparser.accepts("forceUpgrade"); ++ OptionSpec optionspec5 = optionparser.accepts("eraseCache"); ++ OptionSpec optionspec6 = optionparser.accepts("safeMode", "Loads level with vanilla datapack only"); ++ OptionSpec optionspec7 = optionparser.accepts("help").forHelp(); ++ OptionSpec optionspec8 = optionparser.accepts("universe").withRequiredArg().defaultsTo(".", new String[0]); ++ OptionSpec optionspec9 = optionparser.accepts("world").withRequiredArg(); ++ OptionSpec optionspec10 = optionparser.accepts("port").withRequiredArg().ofType(Integer.class).defaultsTo(-1, new Integer[0]); ++ OptionSpec optionspec11 = optionparser.accepts("serverId").withRequiredArg(); ++ OptionSpec optionspec12 = optionparser.accepts("jfrProfile"); ++ OptionSpec optionspec13 = optionparser.accepts("pidFile").withRequiredArg().withValuesConvertedBy(new PathConverter(new PathProperties[0])); ++ NonOptionArgumentSpec nonoptionargumentspec = optionparser.nonOptions(); + + try { + OptionSet optionSet = optionParser.parse(args); +@@ -88,14 +102,18 @@ + optionParser.printHelpOn(System.err); + return; + } ++ */ // CraftBukkit end + +- Path path = optionSet.valueOf(optionSpec13); ++ try { ++ ++ Path path = (Path) optionset.valueOf("pidFile"); // CraftBukkit ++ + if (path != null) { + writePidFile(path); + } + + CrashReport.preload(); +- if (optionSet.has(optionSpec12)) { ++ if (optionset.has("jfrProfile")) { // CraftBukkit + JvmProfiler.INSTANCE.start(Environment.SERVER); + } + +@@ -103,12 +121,27 @@ + Bootstrap.validate(); + Util.startTimerHackThread(); + Path path1 = Paths.get("server.properties"); +- DedicatedServerSettings dedicatedServerSettings = new DedicatedServerSettings(path1); +- dedicatedServerSettings.forceSave(); ++ DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(optionset); // CraftBukkit - CLI argument support ++ ++ dedicatedserversettings.forceSave(); + Path path2 = Paths.get("eula.txt"); + Eula eula = new Eula(path2); +- if (optionSet.has(optionSpec1)) { +- LOGGER.info("Initialized '{}' and '{}'", path1.toAbsolutePath(), path2.toAbsolutePath()); ++ ++ if (optionset.has("initSettings")) { // CraftBukkit ++ // CraftBukkit start - SPIGOT-5761: Create bukkit.yml and commands.yml if not present ++ File configFile = (File) optionset.valueOf("bukkit-settings"); ++ YamlConfiguration configuration = YamlConfiguration.loadConfiguration(configFile); ++ configuration.options().copyDefaults(true); ++ configuration.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/bukkit.yml"), Charsets.UTF_8))); ++ configuration.save(configFile); ++ ++ File commandFile = (File) optionset.valueOf("commands-settings"); ++ YamlConfiguration commandsConfiguration = YamlConfiguration.loadConfiguration(commandFile); ++ commandsConfiguration.options().copyDefaults(true); ++ commandsConfiguration.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/commands.yml"), Charsets.UTF_8))); ++ commandsConfiguration.save(commandFile); ++ // CraftBukkit end ++ Main.LOGGER.info("Initialized '{}' and '{}'", path1.toAbsolutePath(), path2.toAbsolutePath()); + return; + } + +@@ -117,14 +150,18 @@ + return; + } + +- File file = new File(optionSet.valueOf(optionSpec8)); ++ File file = (File) optionset.valueOf("universe"); // CraftBukkit + Services services = Services.create(new YggdrasilAuthenticationService(Proxy.NO_PROXY), file); +- String string = Optional.ofNullable(optionSet.valueOf(optionSpec9)).orElse(dedicatedServerSettings.getProperties().levelName); +- LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(file.toPath()); +- LevelStorageSource.LevelStorageAccess levelStorageAccess = levelStorageSource.validateAndCreateAccess(string); +- Dynamic dataTag; +- if (levelStorageAccess.hasWorldData()) { +- LevelSummary summary; ++ // CraftBukkit start ++ String s = (String) Optional.ofNullable((String) optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName); ++ LevelStorageSource convertable = LevelStorageSource.createDefault(file.toPath()); ++ LevelStorageSource.LevelStorageAccess convertable_conversionsession = convertable.validateAndCreateAccess(s, LevelStem.OVERWORLD); ++ // CraftBukkit end ++ Dynamic dynamic; ++ ++ if (convertable_conversionsession.hasWorldData()) { ++ LevelSummary worldinfo; ++ + try { + dataTag = levelStorageAccess.getDataTag(); + summary = levelStorageAccess.getSummary(dataTag); +@@ -162,72 +196,73 @@ + dataTag = null; + } + +- Dynamic dynamic = dataTag; +- boolean hasOptionSpec = optionSet.has(optionSpec6); +- if (hasOptionSpec) { +- LOGGER.warn("Safe mode active, only vanilla datapack will be loaded"); ++ Dynamic dynamic1 = dynamic; ++ boolean flag = optionset.has("safeMode"); // CraftBukkit ++ ++ if (flag) { ++ Main.LOGGER.warn("Safe mode active, only vanilla datapack will be loaded"); + } + +- PackRepository packRepository = ServerPacksSource.createPackRepository(levelStorageAccess); ++ PackRepository resourcepackrepository = ServerPacksSource.createPackRepository(convertable_conversionsession); ++ // CraftBukkit start ++ File bukkitDataPackFolder = new File(convertable_conversionsession.getLevelPath(LevelResource.DATAPACK_DIR).toFile(), "bukkit"); ++ if (!bukkitDataPackFolder.exists()) { ++ bukkitDataPackFolder.mkdirs(); ++ } ++ File mcMeta = new File(bukkitDataPackFolder, "pack.mcmeta"); ++ try { ++ com.google.common.io.Files.write("{\n" ++ + " \"pack\": {\n" ++ + " \"description\": \"Data pack for resources provided by Bukkit plugins\",\n" ++ + " \"pack_format\": " + SharedConstants.getCurrentVersion().getPackVersion(PackType.SERVER_DATA) + "\n" ++ + " }\n" ++ + "}\n", mcMeta, com.google.common.base.Charsets.UTF_8); ++ } catch (java.io.IOException ex) { ++ throw new RuntimeException("Could not initialize Bukkit datapack", ex); ++ } ++ AtomicReference worldLoader = new AtomicReference<>(); ++ // CraftBukkit end + + WorldStem worldStem; + try { +- WorldLoader.InitConfig initConfig = loadOrCreateConfig(dedicatedServerSettings.getProperties(), dynamic, hasOptionSpec, packRepository); +- worldStem = Util.blockUntilDone( +- executor -> WorldLoader.load( +- initConfig, +- context -> { +- Registry registry = context.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM); +- if (dynamic != null) { +- LevelDataAndDimensions levelDataAndDimensions = LevelStorageSource.getLevelDataAndDimensions( +- dynamic, context.dataConfiguration(), registry, context.datapackWorldgen() +- ); +- return new WorldLoader.DataLoadOutput<>( +- levelDataAndDimensions.worldData(), levelDataAndDimensions.dimensions().dimensionsRegistryAccess() +- ); +- } else { +- LOGGER.info("No existing world data, creating new world"); +- LevelSettings levelSettings; +- WorldOptions worldOptions; +- WorldDimensions worldDimensions; +- if (optionSet.has(optionSpec2)) { +- levelSettings = MinecraftServer.DEMO_SETTINGS; +- worldOptions = WorldOptions.DEMO_OPTIONS; +- worldDimensions = WorldPresets.createNormalWorldDimensions(context.datapackWorldgen()); +- } else { +- DedicatedServerProperties properties = dedicatedServerSettings.getProperties(); +- levelSettings = new LevelSettings( +- properties.levelName, +- properties.gamemode, +- properties.hardcore, +- properties.difficulty, +- false, +- new GameRules(), +- context.dataConfiguration() +- ); +- worldOptions = optionSet.has(optionSpec3) ? properties.worldOptions.withBonusChest(true) : properties.worldOptions; +- worldDimensions = properties.createDimensions(context.datapackWorldgen()); +- } +- +- WorldDimensions.Complete complete = worldDimensions.bake(registry); +- Lifecycle lifecycle = complete.lifecycle().add(context.datapackWorldgen().allRegistriesLifecycle()); +- return new WorldLoader.DataLoadOutput<>( +- new PrimaryLevelData(levelSettings, worldOptions, complete.specialWorldProperty(), lifecycle), +- complete.dimensionsRegistryAccess() +- ); +- } +- }, +- WorldStem::new, +- Util.backgroundExecutor(), +- executor +- ) +- ) +- .get(); +- } catch (Exception var37) { +- LOGGER.warn( +- "Failed to load datapacks, can't proceed with server load. You can either fix your datapacks or reset to vanilla with --safeMode", +- (Throwable)var37 +- ); ++ WorldLoader.c worldloader_c = loadOrCreateConfig(dedicatedserversettings.getProperties(), dynamic1, flag, resourcepackrepository); ++ ++ worldstem = (WorldStem) Util.blockUntilDone((executor) -> { ++ return WorldLoader.load(worldloader_c, (worldloader_a) -> { ++ worldLoader.set(worldloader_a); // CraftBukkit ++ Registry iregistry = worldloader_a.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM); ++ ++ if (dynamic1 != null) { ++ LevelDataAndDimensions leveldataanddimensions = LevelStorageSource.getLevelDataAndDimensions(dynamic1, worldloader_a.dataConfiguration(), iregistry, worldloader_a.datapackWorldgen()); ++ ++ return new WorldLoader.b<>(leveldataanddimensions.worldData(), leveldataanddimensions.dimensions().dimensionsRegistryAccess()); ++ } else { ++ Main.LOGGER.info("No existing world data, creating new world"); ++ LevelSettings worldsettings; ++ WorldOptions worldoptions; ++ WorldDimensions worlddimensions; ++ ++ if (optionset.has("demo")) { // CraftBukkit ++ worldsettings = MinecraftServer.DEMO_SETTINGS; ++ worldoptions = WorldOptions.DEMO_OPTIONS; ++ worlddimensions = WorldPresets.createNormalWorldDimensions(worldloader_a.datapackWorldgen()); ++ } else { ++ DedicatedServerProperties dedicatedserverproperties = dedicatedserversettings.getProperties(); ++ ++ worldsettings = new LevelSettings(dedicatedserverproperties.levelName, dedicatedserverproperties.gamemode, dedicatedserverproperties.hardcore, dedicatedserverproperties.difficulty, false, new GameRules(), worldloader_a.dataConfiguration()); ++ worldoptions = optionset.has("bonusChest") ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions; // CraftBukkit ++ worlddimensions = dedicatedserverproperties.createDimensions(worldloader_a.datapackWorldgen()); ++ } ++ ++ WorldDimensions.b worlddimensions_b = worlddimensions.bake(iregistry); ++ Lifecycle lifecycle = worlddimensions_b.lifecycle().add(worldloader_a.datapackWorldgen().allRegistriesLifecycle()); ++ ++ return new WorldLoader.b<>(new PrimaryLevelData(worldsettings, worldoptions, worlddimensions_b.specialWorldProperty(), lifecycle), worlddimensions_b.dimensionsRegistryAccess()); ++ } ++ }, WorldStem::new, Util.backgroundExecutor(), executor); ++ }).get(); ++ } catch (Exception exception) { ++ Main.LOGGER.warn("Failed to load datapacks, can't proceed with server load. You can either fix your datapacks or reset to vanilla with --safeMode", exception); + return; + } + +@@ -262,7 +300,10 @@ + + return dedicatedServer1; + } +- ); ++ ++ return dedicatedserver1; ++ }); ++ /* CraftBukkit start + Thread thread = new Thread("Server Shutdown Thread") { + @Override + public void run() { +@@ -271,8 +312,9 @@ + }; + thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER)); + Runtime.getRuntime().addShutdownHook(thread); +- } catch (Exception var40) { +- LOGGER.error(LogUtils.FATAL_MARKER, "Failed to start the minecraft server", (Throwable)var40); ++ */ // CraftBukkit end ++ } catch (Exception exception1) { ++ Main.LOGGER.error(LogUtils.FATAL_MARKER, "Failed to start the minecraft server", exception1); + } + } + +@@ -303,16 +348,10 @@ + return new WorldLoader.InitConfig(packConfig, Commands.CommandSelection.DEDICATED, dedicatedServerProperties.functionPermissionLevel); + } + +- private static void forceUpgrade( +- LevelStorageSource.LevelStorageAccess levelStorage, +- DataFixer dataFixer, +- boolean eraseCache, +- BooleanSupplier upgradeWorld, +- Registry dimesions +- ) { +- LOGGER.info("Forcing world upgrade!"); +- WorldUpgrader worldUpgrader = new WorldUpgrader(levelStorage, dataFixer, dimesions, eraseCache); +- Component component = null; ++ public static void forceUpgrade(LevelStorageSource.LevelStorageAccess levelStorage, DataFixer dataFixer, boolean eraseCache, BooleanSupplier upgradeWorld, Registry dimesions) { ++ Main.LOGGER.info("Forcing world upgrade! {}", levelStorage.getLevelId()); // CraftBukkit ++ WorldUpgrader worldupgrader = new WorldUpgrader(levelStorage, dataFixer, dimesions, eraseCache); ++ Component ichatbasecomponent = null; + + while (!worldUpgrader.isFinished()) { + Component status = worldUpgrader.getStatus(); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/MinecraftServer.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/MinecraftServer.java.patch new file mode 100644 index 0000000000..6f529f3152 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/MinecraftServer.java.patch @@ -0,0 +1,673 @@ +--- a/net/minecraft/server/MinecraftServer.java ++++ b/net/minecraft/server/MinecraftServer.java +@@ -145,6 +150,23 @@ + import net.minecraft.world.level.levelgen.PhantomSpawner; + import net.minecraft.world.level.levelgen.WorldOptions; + import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; ++import net.minecraft.world.level.storage.WorldData; ++import net.minecraft.world.level.storage.loot.LootDataManager; ++import org.slf4j.Logger; ++ ++// CraftBukkit start ++import com.mojang.serialization.Dynamic; ++import com.mojang.serialization.Lifecycle; ++import java.util.Random; ++import jline.console.ConsoleReader; ++import joptsimple.OptionSet; ++import net.minecraft.nbt.NbtException; ++import net.minecraft.nbt.ReportedNbtException; ++import net.minecraft.server.bossevents.CustomBossEvents; ++import net.minecraft.server.dedicated.DedicatedServer; ++import net.minecraft.server.dedicated.DedicatedServerProperties; ++import net.minecraft.world.level.levelgen.WorldDimensions; ++import net.minecraft.world.level.levelgen.presets.WorldPresets; + import net.minecraft.world.level.storage.CommandStorage; + import net.minecraft.world.level.storage.DerivedLevelData; + import net.minecraft.world.level.storage.DimensionDataStorage; +@@ -157,14 +180,18 @@ + import net.minecraft.world.level.storage.loot.LootDataManager; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; +-import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.Main; ++import org.bukkit.event.server.ServerLoadEvent; ++// CraftBukkit end + + public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements ServerInfo, CommandSource, AutoCloseable { + private static final Logger LOGGER = LogUtils.getLogger(); + public static final String VANILLA_BRAND = "vanilla"; + private static final float AVERAGE_TICK_TIME_SMOOTHING = 0.8F; + private static final int TICK_STATS_SPAN = 100; +- private static final long OVERLOADED_THRESHOLD_NANOS = 20L * TimeUtil.NANOSECONDS_PER_SECOND / 20L; ++ private static final long OVERLOADED_THRESHOLD_NANOS = 30L * TimeUtil.NANOSECONDS_PER_SECOND / 20L; // CraftBukkit + private static final int OVERLOADED_TICKS_THRESHOLD = 20; + private static final long OVERLOADED_WARNING_INTERVAL_NANOS = 10L * TimeUtil.NANOSECONDS_PER_SECOND; + private static final int OVERLOADED_TICKS_WARNING_INTERVAL = 100; +@@ -250,6 +275,19 @@ + protected final WorldData worldData; + private volatile boolean isSaving; + ++ // CraftBukkit start ++ public final WorldLoader.a worldLoader; ++ public org.bukkit.craftbukkit.CraftServer server; ++ public OptionSet options; ++ public org.bukkit.command.ConsoleCommandSender console; ++ public ConsoleReader reader; ++ public static int currentTick = (int) (System.currentTimeMillis() / 50); ++ public java.util.Queue processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); ++ public int autosavePeriod; ++ public Commands vanillaCommandDispatcher; ++ private boolean forceTicks; ++ // CraftBukkit end ++ + public static S spin(Function threadFunction) { + AtomicReference atomicReference = new AtomicReference<>(); + Thread thread = new Thread(() -> atomicReference.get().runServer(), "Server thread"); +@@ -275,9 +310,26 @@ + ChunkProgressListenerFactory progressListenerFactory + ) { + super("Server"); +- this.registries = worldStem.registries(); +- this.worldData = worldStem.worldData(); +- if (!this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM).containsKey(LevelStem.OVERWORLD)) { ++ this.metricsRecorder = InactiveMetricsRecorder.INSTANCE; ++ this.profiler = this.metricsRecorder.getProfiler(); ++ this.onMetricsRecordingStopped = (methodprofilerresults) -> { ++ this.stopRecordingMetrics(); ++ }; ++ this.onMetricsRecordingFinished = (path) -> { ++ }; ++ this.random = RandomSource.create(); ++ this.port = -1; ++ this.levels = Maps.newLinkedHashMap(); ++ this.running = true; ++ this.ticksUntilAutosave = 6000; ++ this.tickTimesNanos = new long[100]; ++ this.aggregatedTickTimesNanos = 0L; ++ this.nextTickTimeNanos = Util.getNanos(); ++ this.scoreboard = new ServerScoreboard(this); ++ this.customBossEvents = new CustomBossEvents(); ++ this.registries = worldstem.registries(); ++ this.worldData = worldstem.worldData(); ++ if (false && !this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM).containsKey(LevelStem.OVERWORLD)) { // CraftBukkit - initialised later + throw new IllegalStateException("Missing Overworld dimension data"); + } else { + this.proxy = proxy; +@@ -304,6 +353,33 @@ + this.serverThread = serverThread; + this.executor = Util.backgroundExecutor(); + } ++ // CraftBukkit start ++ this.options = options; ++ this.worldLoader = worldLoader; ++ this.vanillaCommandDispatcher = worldstem.dataPackResources().commands; // CraftBukkit ++ // Try to see if we're actually running in a terminal, disable jline if not ++ if (System.console() == null && System.getProperty("jline.terminal") == null) { ++ System.setProperty("jline.terminal", "jline.UnsupportedTerminal"); ++ Main.useJline = false; ++ } ++ ++ try { ++ reader = new ConsoleReader(System.in, System.out); ++ reader.setExpandEvents(false); // Avoid parsing exceptions for uncommonly used event designators ++ } catch (Throwable e) { ++ try { ++ // Try again with jline disabled for Windows users without C++ 2008 Redistributable ++ System.setProperty("jline.terminal", "jline.UnsupportedTerminal"); ++ System.setProperty("user.language", "en"); ++ Main.useJline = false; ++ reader = new ConsoleReader(System.in, System.out); ++ reader.setExpandEvents(false); ++ } catch (IOException ex) { ++ LOGGER.warn((String) null, ex); ++ } ++ } ++ Runtime.getRuntime().addShutdownHook(new org.bukkit.craftbukkit.util.ServerShutdownThread(this)); ++ // CraftBukkit end + } + + private void readScoreboard(DimensionDataStorage dataStorage) { +@@ -312,19 +388,17 @@ + + protected abstract boolean initServer() throws IOException; + +- protected void loadLevel() { ++ protected void loadLevel(String s) { // CraftBukkit + if (!JvmProfiler.INSTANCE.isRunning()) { + } + + boolean flag = false; +- ProfiledDuration profiledDuration = JvmProfiler.INSTANCE.onWorldLoadedStarted(); +- this.worldData.setModdedInfo(this.getServerModName(), this.getModdedStatus().shouldReportAsModified()); +- ChunkProgressListener chunkProgressListener = this.progressListenerFactory.create(11); +- this.createLevels(chunkProgressListener); +- this.forceDifficulty(); +- this.prepareLevels(chunkProgressListener); +- if (profiledDuration != null) { +- profiledDuration.finish(); ++ ProfiledDuration profiledduration = JvmProfiler.INSTANCE.onWorldLoadedStarted(); ++ ++ loadWorld0(s); // CraftBukkit ++ ++ if (profiledduration != null) { ++ profiledduration.finish(); + } + + if (flag) { +@@ -339,31 +412,24 @@ + protected void forceDifficulty() { + } + +- protected void createLevels(ChunkProgressListener listener) { +- ServerLevelData serverLevelData = this.worldData.overworldData(); +- boolean isDebugWorld = this.worldData.isDebugWorld(); +- Registry registry = this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM); +- WorldOptions worldOptions = this.worldData.worldGenOptions(); +- long l = worldOptions.seed(); +- long l1 = BiomeManager.obfuscateSeed(l); +- List list = ImmutableList.of( +- new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(serverLevelData) +- ); +- LevelStem levelStem = registry.get(LevelStem.OVERWORLD); +- ServerLevel serverLevel = new ServerLevel( +- this, this.executor, this.storageSource, serverLevelData, Level.OVERWORLD, levelStem, listener, isDebugWorld, l1, list, true, null +- ); +- this.levels.put(Level.OVERWORLD, serverLevel); +- DimensionDataStorage dataStorage = serverLevel.getDataStorage(); +- this.readScoreboard(dataStorage); +- this.commandStorage = new CommandStorage(dataStorage); +- WorldBorder worldBorder = serverLevel.getWorldBorder(); +- if (!serverLevelData.isInitialized()) { +- try { +- setInitialSpawn(serverLevel, serverLevelData, worldOptions.generateBonusChest(), isDebugWorld); +- serverLevelData.setInitialized(true); +- if (isDebugWorld) { +- this.setupDebugLevel(this.worldData); ++ protected void forceDifficulty() {} ++ ++ // CraftBukkit start ++ private void loadWorld0(String s) { ++ LevelStorageSource.LevelStorageAccess worldSession = this.storageSource; ++ ++ Registry dimensions = this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM); ++ for (LevelStem worldDimension : dimensions) { ++ ResourceKey dimensionKey = dimensions.getResourceKey(worldDimension).get(); ++ ++ ServerLevel world; ++ int dimension = 0; ++ ++ if (dimensionKey == LevelStem.NETHER) { ++ if (isNetherEnabled()) { ++ dimension = -1; ++ } else { ++ continue; + } + } catch (Throwable var23) { + CrashReport crashReport = CrashReport.forThrowable(var23, "Exception initializing level"); +@@ -376,13 +523,101 @@ + throw new ReportedException(crashReport); + } + +- serverLevelData.setInitialized(true); ++ org.bukkit.generator.ChunkGenerator gen = this.server.getGenerator(name); ++ org.bukkit.generator.BiomeProvider biomeProvider = this.server.getBiomeProvider(name); ++ ++ PrimaryLevelData worlddata; ++ WorldLoader.a worldloader_a = this.worldLoader; ++ Registry iregistry = worldloader_a.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM); ++ if (dynamic != null) { ++ LevelDataAndDimensions leveldataanddimensions = LevelStorageSource.getLevelDataAndDimensions(dynamic, worldloader_a.dataConfiguration(), iregistry, worldloader_a.datapackWorldgen()); ++ ++ worlddata = (PrimaryLevelData) leveldataanddimensions.worldData(); ++ } else { ++ LevelSettings worldsettings; ++ WorldOptions worldoptions; ++ WorldDimensions worlddimensions; ++ ++ if (this.isDemo()) { ++ worldsettings = MinecraftServer.DEMO_SETTINGS; ++ worldoptions = WorldOptions.DEMO_OPTIONS; ++ worlddimensions = WorldPresets.createNormalWorldDimensions(worldloader_a.datapackWorldgen()); ++ } else { ++ DedicatedServerProperties dedicatedserverproperties = ((DedicatedServer) this).getProperties(); ++ ++ worldsettings = new LevelSettings(dedicatedserverproperties.levelName, dedicatedserverproperties.gamemode, dedicatedserverproperties.hardcore, dedicatedserverproperties.difficulty, false, new GameRules(), worldloader_a.dataConfiguration()); ++ worldoptions = options.has("bonusChest") ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions; ++ worlddimensions = dedicatedserverproperties.createDimensions(worldloader_a.datapackWorldgen()); ++ } ++ ++ WorldDimensions.b worlddimensions_b = worlddimensions.bake(iregistry); ++ Lifecycle lifecycle = worlddimensions_b.lifecycle().add(worldloader_a.datapackWorldgen().allRegistriesLifecycle()); ++ ++ worlddata = new PrimaryLevelData(worldsettings, worldoptions, worlddimensions_b.specialWorldProperty(), lifecycle); ++ } ++ worlddata.checkName(name); // CraftBukkit - Migration did not rewrite the level.dat; This forces 1.8 to take the last loaded world as respawn (in this case the end) ++ if (options.has("forceUpgrade")) { ++ net.minecraft.server.Main.forceUpgrade(worldSession, DataFixers.getDataFixer(), options.has("eraseCache"), () -> { ++ return true; ++ }, dimensions); ++ } ++ ++ PrimaryLevelData iworlddataserver = worlddata; ++ boolean flag = worlddata.isDebugWorld(); ++ WorldOptions worldoptions = worlddata.worldGenOptions(); ++ long i = worldoptions.seed(); ++ long j = BiomeManager.obfuscateSeed(i); ++ List list = ImmutableList.of(new MobSpawnerPhantom(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(iworlddataserver)); ++ LevelStem worlddimension = (LevelStem) dimensions.get(dimensionKey); ++ ++ org.bukkit.generator.WorldInfo worldInfo = new org.bukkit.craftbukkit.generator.CraftWorldInfo(iworlddataserver, worldSession, org.bukkit.World.Environment.getEnvironment(dimension), worlddimension.type().value()); ++ if (biomeProvider == null && gen != null) { ++ biomeProvider = gen.getDefaultBiomeProvider(worldInfo); ++ } ++ ++ ResourceKey worldKey = ResourceKey.create(Registries.DIMENSION, dimensionKey.location()); ++ ++ if (dimensionKey == LevelStem.OVERWORLD) { ++ this.worldData = worlddata; ++ this.worldData.setGameType(((DedicatedServer) this).getProperties().gamemode); // From DedicatedServer.init ++ ++ ChunkProgressListener worldloadlistener = this.progressListenerFactory.create(11); ++ ++ world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, worlddimension, worldloadlistener, flag, j, list, true, (RandomSequences) null, org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider); ++ DimensionDataStorage worldpersistentdata = world.getDataStorage(); ++ this.readScoreboard(worldpersistentdata); ++ this.server.scoreboardManager = new org.bukkit.craftbukkit.scoreboard.CraftScoreboardManager(this, world.getScoreboard()); ++ this.commandStorage = new CommandStorage(worldpersistentdata); ++ } else { ++ ChunkProgressListener worldloadlistener = this.progressListenerFactory.create(11); ++ world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, worlddimension, worldloadlistener, flag, j, ImmutableList.of(), true, this.overworld().getRandomSequences(), org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider); ++ } ++ ++ worlddata.setModdedInfo(this.getServerModName(), this.getModdedStatus().shouldReportAsModified()); ++ this.initWorld(world, worlddata, worldData, worldoptions); ++ ++ this.addLevel(world); ++ this.getPlayerList().addWorldborderListener(world); ++ ++ if (worlddata.getCustomBossEvents() != null) { ++ this.getCustomBossEvents().load(worlddata.getCustomBossEvents()); ++ } + } + +- this.getPlayerList().addWorldborderListener(serverLevel); +- if (this.worldData.getCustomBossEvents() != null) { +- this.getCustomBossEvents().load(this.worldData.getCustomBossEvents()); ++ this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.POSTWORLD); ++ this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP)); ++ this.connection.acceptConnections(); ++ } ++ ++ public void initWorld(ServerLevel worldserver, ServerLevelData iworlddataserver, WorldData saveData, WorldOptions worldoptions) { ++ boolean flag = saveData.isDebugWorld(); ++ // CraftBukkit start ++ if (worldserver.generator != null) { ++ worldserver.getWorld().getPopulators().addAll(worldserver.generator.getDefaultPopulators(worldserver.getWorld())); + } ++ WorldBorder worldborder = worldserver.getWorldBorder(); ++ worldborder.applySettings(iworlddataserver.getWorldBorder()); // CraftBukkit - move up so that WorldBorder is set during WorldInitEvent ++ this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldInitEvent(worldserver.getWorld())); // CraftBukkit - SPIGOT-5569: Call WorldInitEvent before any chunks are generated + + RandomSequences randomSequences = serverLevel.getRandomSequences(); + +@@ -412,18 +648,30 @@ + + worldBorder.applySettings(serverLevelData.getWorldBorder()); + } ++ // CraftBukkit end + + private static void setInitialSpawn(ServerLevel level, ServerLevelData levelData, boolean generateBonusChest, boolean debug) { + if (debug) { + levelData.setSpawn(BlockPos.ZERO.above(80), 0.0F); + } else { +- ServerChunkCache chunkSource = level.getChunkSource(); +- ChunkPos chunkPos = new ChunkPos(chunkSource.randomState().sampler().findSpawnPosition()); +- int spawnHeight = chunkSource.getGenerator().getSpawnHeight(level); +- if (spawnHeight < level.getMinBuildHeight()) { +- BlockPos worldPosition = chunkPos.getWorldPosition(); +- spawnHeight = level.getHeight(Heightmap.Types.WORLD_SURFACE, worldPosition.getX() + 8, worldPosition.getZ() + 8); ++ ServerChunkCache chunkproviderserver = level.getChunkSource(); ++ ChunkPos chunkcoordintpair = new ChunkPos(chunkproviderserver.randomState().sampler().findSpawnPosition()); ++ // CraftBukkit start ++ if (level.generator != null) { ++ Random rand = new Random(level.getSeed()); ++ org.bukkit.Location spawn = level.generator.getFixedSpawnLocation(level.getWorld(), rand); ++ ++ if (spawn != null) { ++ if (spawn.getWorld() != level.getWorld()) { ++ throw new IllegalStateException("Cannot set spawn point for " + levelData.getLevelName() + " to be in another world (" + spawn.getWorld().getName() + ")"); ++ } else { ++ levelData.setSpawn(new BlockPos(spawn.getBlockX(), spawn.getBlockY(), spawn.getBlockZ()), spawn.getYaw()); ++ return; ++ } ++ } + } ++ // CraftBukkit end ++ int i = chunkproviderserver.getGenerator().getSpawnHeight(level); + + levelData.setSpawn(chunkPos.getWorldPosition().offset(8, spawnHeight, 8), 0.0F); + int i = 0; +@@ -479,14 +730,22 @@ + serverLevelData.setGameType(GameType.SPECTATOR); + } + +- private void prepareLevels(ChunkProgressListener listener) { +- ServerLevel serverLevel = this.overworld(); +- LOGGER.info("Preparing start region for dimension {}", serverLevel.dimension().location()); +- BlockPos sharedSpawnPos = serverLevel.getSharedSpawnPos(); +- listener.updateSpawnPos(new ChunkPos(sharedSpawnPos)); +- ServerChunkCache chunkSource = serverLevel.getChunkSource(); ++ // CraftBukkit start ++ public void prepareLevels(ChunkProgressListener worldloadlistener, ServerLevel worldserver) { ++ // WorldServer worldserver = this.overworld(); ++ this.forceTicks = true; ++ // CraftBukkit end ++ ++ MinecraftServer.LOGGER.info("Preparing start region for dimension {}", worldserver.dimension().location()); ++ BlockPos blockposition = worldserver.getSharedSpawnPos(); ++ ++ worldloadlistener.updateSpawnPos(new ChunkPos(blockposition)); ++ ServerChunkCache chunkproviderserver = worldserver.getChunkSource(); ++ + this.nextTickTimeNanos = Util.getNanos(); +- chunkSource.addRegionTicket(TicketType.START, new ChunkPos(sharedSpawnPos), 11, Unit.INSTANCE); ++ // CraftBukkit start ++ if (worldserver.getWorld().getKeepSpawnInMemory()) { ++ chunkproviderserver.addRegionTicket(TicketType.START, new ChunkPos(blockposition), 11, Unit.INSTANCE); + + while (chunkSource.getTickingGenerated() != 441) { + this.nextTickTimeNanos = Util.getNanos() + PREPARE_LEVELS_DEFAULT_DELAY_NANOS; +@@ -496,10 +757,10 @@ + this.nextTickTimeNanos = Util.getNanos() + PREPARE_LEVELS_DEFAULT_DELAY_NANOS; + this.waitUntilNextTick(); + +- for (ServerLevel serverLevel1 : this.levels.values()) { +- ForcedChunksSavedData forcedChunksSavedData = serverLevel1.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks"); +- if (forcedChunksSavedData != null) { +- LongIterator longIterator = forcedChunksSavedData.getChunks().iterator(); ++ if (true) { ++ ServerLevel worldserver1 = worldserver; ++ // CraftBukkit end ++ ForcedChunksSavedData forcedchunk = (ForcedChunksSavedData) worldserver1.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks"); + + while (longIterator.hasNext()) { + long l = longIterator.nextLong(); +@@ -509,10 +774,17 @@ + } + } + +- this.nextTickTimeNanos = Util.getNanos() + PREPARE_LEVELS_DEFAULT_DELAY_NANOS; +- this.waitUntilNextTick(); +- listener.stop(); +- this.updateMobSpawningFlags(); ++ // CraftBukkit start ++ // this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; ++ this.executeModerately(); ++ // CraftBukkit end ++ worldloadlistener.stop(); ++ // CraftBukkit start ++ // this.updateMobSpawningFlags(); ++ worldserver.setSpawnSettings(this.isSpawningMonsters(), this.isSpawningAnimals()); ++ ++ this.forceTicks = false; ++ // CraftBukkit end + } + + public GameType getDefaultGameType() { +@@ -541,11 +814,16 @@ + flag = true; + } + +- ServerLevel serverLevel1 = this.overworld(); +- ServerLevelData serverLevelData = this.worldData.overworldData(); +- serverLevelData.setWorldBorder(serverLevel1.getWorldBorder().createSettings()); ++ // CraftBukkit start - moved to WorldServer.save ++ /* ++ WorldServer worldserver1 = this.overworld(); ++ IWorldDataServer iworlddataserver = this.worldData.overworldData(); ++ ++ iworlddataserver.setWorldBorder(worldserver1.getWorldBorder().createSettings()); + this.worldData.setCustomBossEvents(this.getCustomBossEvents().save()); + this.storageSource.saveDataTag(this.registryAccess(), this.worldData, this.getPlayerList().getSingleplayerData()); ++ */ ++ // CraftBukkit end + if (flush) { + for (ServerLevel serverLevel2 : this.getAllLevels()) { + LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", serverLevel2.getChunkSource().chunkMap.getStorageName()); +@@ -575,18 +858,40 @@ + this.stopServer(); + } + ++ // CraftBukkit start ++ private boolean hasStopped = false; ++ private final Object stopLock = new Object(); ++ public final boolean hasStopped() { ++ synchronized (stopLock) { ++ return hasStopped; ++ } ++ } ++ // CraftBukkit end ++ + public void stopServer() { ++ // CraftBukkit start - prevent double stopping on multiple threads ++ synchronized(stopLock) { ++ if (hasStopped) return; ++ hasStopped = true; ++ } ++ // CraftBukkit end + if (this.metricsRecorder.isRecording()) { + this.cancelRecordingMetrics(); + } + +- LOGGER.info("Stopping server"); ++ MinecraftServer.LOGGER.info("Stopping server"); ++ // CraftBukkit start ++ if (this.server != null) { ++ this.server.disablePlugins(); ++ } ++ // CraftBukkit end + this.getConnection().stop(); + this.isSaving = true; + if (this.playerList != null) { + LOGGER.info("Saving players"); + this.playerList.saveAll(); + this.playerList.removeAll(); ++ try { Thread.sleep(100); } catch (InterruptedException ex) {} // CraftBukkit - SPIGOT-625 - give server at least a chance to send packets + } + + LOGGER.info("Saving worlds"); +@@ -670,13 +990,15 @@ + this.nextTickTimeNanos = Util.getNanos(); + this.lastOverloadWarningNanos = this.nextTickTimeNanos; + } else { +- l = this.tickRateManager.nanosecondsPerTick(); +- long l1 = Util.getNanos() - this.nextTickTimeNanos; +- if (l1 > OVERLOADED_THRESHOLD_NANOS + 20L * l +- && this.nextTickTimeNanos - this.lastOverloadWarningNanos >= OVERLOADED_WARNING_INTERVAL_NANOS + 100L * l) { +- long l2 = l1 / l; +- LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", l1 / TimeUtil.NANOSECONDS_PER_MILLISECOND, l2); +- this.nextTickTimeNanos += l2 * l; ++ i = this.tickRateManager.nanosecondsPerTick(); ++ long j = Util.getNanos() - this.nextTickTimeNanos; ++ ++ if (j > MinecraftServer.OVERLOADED_THRESHOLD_NANOS + 20L * i && this.nextTickTimeNanos - this.lastOverloadWarningNanos >= MinecraftServer.OVERLOADED_WARNING_INTERVAL_NANOS + 100L * i) { ++ long k = j / i; ++ ++ if (server.getWarnOnOverload()) // CraftBukkit ++ MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", j / TimeUtil.NANOSECONDS_PER_MILLISECOND, k); ++ this.nextTickTimeNanos += k * i; + this.lastOverloadWarningNanos = this.nextTickTimeNanos; + } + } +@@ -687,7 +1010,8 @@ + this.debugCommandProfiler = new MinecraftServer.TimeProfiler(Util.getNanos(), this.tickCount); + } + +- this.nextTickTimeNanos += l; ++ MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit ++ this.nextTickTimeNanos += i; + this.startMetricsRecordingTick(); + this.profiler.push("tick"); + this.tickServer(flag ? () -> false : this::haveTime); +@@ -727,6 +1055,12 @@ + this.services.profileCache().clearExecutor(); + } + ++ // CraftBukkit start - Restore terminal to original settings ++ try { ++ reader.getTerminal().restore(); ++ } catch (Exception ignored) { ++ } ++ // CraftBukkit end + this.onServerExit(); + } + } +@@ -755,9 +1094,16 @@ + } + + private boolean haveTime() { +- return this.runningTask() || Util.getNanos() < (this.mayHaveDelayedTasks ? this.delayedTasksMaxNextTickTimeNanos : this.nextTickTimeNanos); ++ // CraftBukkit start ++ return this.forceTicks || this.runningTask() || Util.getNanos() < (this.mayHaveDelayedTasks ? this.delayedTasksMaxNextTickTimeNanos : this.nextTickTimeNanos); + } + ++ private void executeModerately() { ++ this.runAllTasks(); ++ java.util.concurrent.locks.LockSupport.parkNanos("executing tasks", 1000L); ++ // CraftBukkit end ++ } ++ + protected void waitUntilNextTick() { + this.runAllTasks(); + this.managedBlock(() -> !this.haveTime()); +@@ -849,10 +1206,12 @@ + this.status = this.buildServerStatus(); + } + +- this.ticksUntilAutosave--; +- if (this.ticksUntilAutosave <= 0) { +- this.ticksUntilAutosave = this.computeNextAutosaveInterval(); +- LOGGER.debug("Autosave started"); ++ --this.ticksUntilAutosave; ++ // CraftBukkit start ++ if (this.autosavePeriod > 0 && this.ticksUntilAutosave <= 0) { ++ this.ticksUntilAutosave = this.autosavePeriod; ++ // CraftBukkit end ++ MinecraftServer.LOGGER.debug("Autosave started"); + this.profiler.push("save"); + this.saveEverything(true, false, false); + this.profiler.pop(); +@@ -926,18 +1288,41 @@ + } + + public void tickChildren(BooleanSupplier hasTimeLeft) { +- this.getPlayerList().getPlayers().forEach(serverPlayer1 -> serverPlayer1.connection.suspendFlushing()); ++ this.getPlayerList().getPlayers().forEach((entityplayer) -> { ++ entityplayer.connection.suspendFlushing(); ++ }); ++ this.server.getScheduler().mainThreadHeartbeat(this.tickCount); // CraftBukkit + this.profiler.push("commandFunctions"); + this.getFunctions().tick(); + this.profiler.popPush("levels"); + +- for (ServerLevel serverLevel : this.getAllLevels()) { +- this.profiler.push(() -> serverLevel + " " + serverLevel.dimension().location()); ++ // CraftBukkit start ++ // Run tasks that are waiting on processing ++ while (!processQueue.isEmpty()) { ++ processQueue.remove().run(); ++ } ++ ++ // Send time updates to everyone, it will get the right time from the world the player is in. ++ if (this.tickCount % 20 == 0) { ++ for (int i = 0; i < this.getPlayerList().players.size(); ++i) { ++ ServerPlayer entityplayer = (ServerPlayer) this.getPlayerList().players.get(i); ++ entityplayer.connection.send(new ClientboundSetTimePacket(entityplayer.level().getGameTime(), entityplayer.getPlayerTime(), entityplayer.level().getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); // Add support for per player time ++ } ++ } ++ ++ while (iterator.hasNext()) { ++ ServerLevel worldserver = (ServerLevel) iterator.next(); ++ ++ this.profiler.push(() -> { ++ return worldserver + " " + worldserver.dimension().location(); ++ }); ++ /* Drop global time updates + if (this.tickCount % 20 == 0) { + this.profiler.push("timeSync"); + this.synchronizeTime(serverLevel); + this.profiler.pop(); + } ++ // CraftBukkit end */ + + this.profiler.push("tick"); + +@@ -1024,6 +1413,22 @@ + return this.levels.get(dimension); + } + ++ // CraftBukkit start ++ public void addLevel(ServerLevel level) { ++ Map, ServerLevel> oldLevels = this.levels; ++ Map, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels); ++ newLevels.put(level.dimension(), level); ++ this.levels = Collections.unmodifiableMap(newLevels); ++ } ++ ++ public void removeLevel(ServerLevel level) { ++ Map, ServerLevel> oldLevels = this.levels; ++ Map, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels); ++ newLevels.remove(level.dimension()); ++ this.levels = Collections.unmodifiableMap(newLevels); ++ } ++ // CraftBukkit end ++ + public Set> levelKeys() { + return this.levels.keySet(); + } +@@ -1053,7 +1458,7 @@ + + @DontObfuscate + public String getServerModName() { +- return "vanilla"; ++ return server.getName(); // CraftBukkit - cb > vanilla! + } + + public SystemReport fillSystemReport(SystemReport systemReport) { +@@ -1714,6 +2237,22 @@ + } + } + ++ // CraftBukkit start ++ @Override ++ public boolean isSameThread() { ++ return super.isSameThread() || this.isStopped(); // CraftBukkit - MC-142590 ++ } ++ ++ public boolean isDebugging() { ++ return false; ++ } ++ ++ @Deprecated ++ public static MinecraftServer getServer() { ++ return (Bukkit.getServer() instanceof CraftServer) ? ((CraftServer) Bukkit.getServer()).getServer() : null; ++ } ++ // CraftBukkit end ++ + private void startMetricsRecordingTick() { + if (this.willStartRecordingMetrics) { + this.metricsRecorder = ActiveMetricsRecorder.createStarted( +@@ -1842,6 +2379,11 @@ + } + } + ++ // CraftBukkit start ++ public final java.util.concurrent.ExecutorService chatExecutor = java.util.concurrent.Executors.newCachedThreadPool( ++ new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon(true).setNameFormat("Async Chat Thread - #%d").build()); ++ // CraftBukkit end ++ + public ChatDecorator getChatDecorator() { + return ChatDecorator.PLAIN; + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/PlayerAdvancements.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/PlayerAdvancements.java.patch new file mode 100644 index 0000000000..83c81e405f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/PlayerAdvancements.java.patch @@ -0,0 +1,39 @@ +--- a/net/minecraft/server/PlayerAdvancements.java ++++ b/net/minecraft/server/PlayerAdvancements.java +@@ -142,11 +191,13 @@ + } + } + +- private void applyFrom(ServerAdvancementManager serverAdvancementManager, PlayerAdvancements.Data data) { +- data.forEach((resourceLocation, advancementProgress) -> { +- AdvancementHolder advancementHolder = serverAdvancementManager.get(resourceLocation); +- if (advancementHolder == null) { +- LOGGER.warn("Ignored advancement '{}' in progress file {} - it doesn't exist anymore?", resourceLocation, this.playerSavePath); ++ private void applyFrom(ServerAdvancementManager advancementdataworld, PlayerAdvancements.a advancementdataplayer_a) { ++ advancementdataplayer_a.forEach((minecraftkey, advancementprogress) -> { ++ AdvancementHolder advancementholder = advancementdataworld.get(minecraftkey); ++ ++ if (advancementholder == null) { ++ if (!minecraftkey.getNamespace().equals("minecraft")) return; // CraftBukkit ++ PlayerAdvancements.LOGGER.warn("Ignored advancement '{}' in progress file {} - it doesn't exist anymore?", minecraftkey, this.playerSavePath); + } else { + this.startProgress(advancementHolder, advancementProgress); + this.progressChanged.add(advancementHolder); +@@ -173,11 +227,12 @@ + this.unregisterListeners(advancementHolder); + this.progressChanged.add(advancementHolder); + flag = true; +- if (!isDone && orStartProgress.isDone()) { +- advancementHolder.value().rewards().grant(this.player); +- advancementHolder.value().display().ifPresent(displayInfo -> { +- if (displayInfo.shouldAnnounceChat() && this.player.level().getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { +- this.playerList.broadcastSystemMessage(displayInfo.getType().createAnnouncement(advancementHolder, this.player), false); ++ if (!flag1 && advancementprogress.isDone()) { ++ this.player.level().getCraftServer().getPluginManager().callEvent(new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancementholder.toBukkit())); // CraftBukkit ++ advancementholder.value().rewards().grant(this.player); ++ advancementholder.value().display().ifPresent((advancementdisplay) -> { ++ if (advancementdisplay.shouldAnnounceChat() && this.player.level().getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { ++ this.playerList.broadcastSystemMessage(advancementdisplay.getType().createAnnouncement(advancementholder, this.player), false); + } + }); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/ServerAdvancementManager.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/ServerAdvancementManager.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/ServerAdvancementManager.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/ServerFunctionManager.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/ServerFunctionManager.java.patch new file mode 100644 index 0000000000..bbd09dbee1 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/ServerFunctionManager.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/server/ServerFunctionManager.java ++++ b/net/minecraft/server/ServerFunctionManager.java +@@ -33,7 +36,7 @@ + } + + public CommandDispatcher getDispatcher() { +- return this.server.getCommands().getDispatcher(); ++ return this.server.vanillaCommandDispatcher.getDispatcher(); // CraftBukkit + } + + public void tick() { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/ServerScoreboard.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/ServerScoreboard.java.patch new file mode 100644 index 0000000000..7f18620a5e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/ServerScoreboard.java.patch @@ -0,0 +1,194 @@ +--- a/net/minecraft/server/ServerScoreboard.java ++++ b/net/minecraft/server/ServerScoreboard.java +@@ -34,14 +37,10 @@ + } + + @Override +- protected void onScoreChanged(ScoreHolder scoreHolder, Objective objective, Score score) { +- super.onScoreChanged(scoreHolder, objective, score); +- if (this.trackedObjectives.contains(objective)) { +- this.server +- .getPlayerList() +- .broadcastAll( +- new ClientboundSetScorePacket(scoreHolder.getScoreboardName(), objective.getName(), score.value(), score.display(), score.numberFormat()) +- ); ++ protected void onScoreChanged(ScoreHolder scoreholder, Objective scoreboardobjective, Score scoreboardscore) { ++ super.onScoreChanged(scoreholder, scoreboardobjective, scoreboardscore); ++ if (this.trackedObjectives.contains(scoreboardobjective)) { ++ this.broadcastAll(new ClientboundSetScorePacket(scoreholder.getScoreboardName(), scoreboardobjective.getName(), scoreboardscore.value(), scoreboardscore.display(), scoreboardscore.numberFormat())); // CraftBukkit + } + + this.setDirty(); +@@ -54,37 +53,38 @@ + } + + @Override +- public void onPlayerRemoved(ScoreHolder scoreHolder) { +- super.onPlayerRemoved(scoreHolder); +- this.server.getPlayerList().broadcastAll(new ClientboundResetScorePacket(scoreHolder.getScoreboardName(), null)); ++ public void onPlayerRemoved(ScoreHolder scoreholder) { ++ super.onPlayerRemoved(scoreholder); ++ this.broadcastAll(new ClientboundResetScorePacket(scoreholder.getScoreboardName(), (String) null)); // CraftBukkit + this.setDirty(); + } + + @Override +- public void onPlayerScoreRemoved(ScoreHolder scoreHolder, Objective objective) { +- super.onPlayerScoreRemoved(scoreHolder, objective); +- if (this.trackedObjectives.contains(objective)) { +- this.server.getPlayerList().broadcastAll(new ClientboundResetScorePacket(scoreHolder.getScoreboardName(), objective.getName())); ++ public void onPlayerScoreRemoved(ScoreHolder scoreholder, Objective scoreboardobjective) { ++ super.onPlayerScoreRemoved(scoreholder, scoreboardobjective); ++ if (this.trackedObjectives.contains(scoreboardobjective)) { ++ this.broadcastAll(new ClientboundResetScorePacket(scoreholder.getScoreboardName(), scoreboardobjective.getName())); // CraftBukkit + } + + this.setDirty(); + } + + @Override +- public void setDisplayObjective(DisplaySlot displaySlot, @Nullable Objective objective) { +- Objective displayObjective = this.getDisplayObjective(displaySlot); +- super.setDisplayObjective(displaySlot, objective); +- if (displayObjective != objective && displayObjective != null) { +- if (this.getObjectiveDisplaySlotCount(displayObjective) > 0) { +- this.server.getPlayerList().broadcastAll(new ClientboundSetDisplayObjectivePacket(displaySlot, objective)); ++ public void setDisplayObjective(DisplaySlot displayslot, @Nullable Objective scoreboardobjective) { ++ Objective scoreboardobjective1 = this.getDisplayObjective(displayslot); ++ ++ super.setDisplayObjective(displayslot, scoreboardobjective); ++ if (scoreboardobjective1 != scoreboardobjective && scoreboardobjective1 != null) { ++ if (this.getObjectiveDisplaySlotCount(scoreboardobjective1) > 0) { ++ this.broadcastAll(new ClientboundSetDisplayObjectivePacket(displayslot, scoreboardobjective)); // CraftBukkit + } else { + this.stopTrackingObjective(displayObjective); + } + } + +- if (objective != null) { +- if (this.trackedObjectives.contains(objective)) { +- this.server.getPlayerList().broadcastAll(new ClientboundSetDisplayObjectivePacket(displaySlot, objective)); ++ if (scoreboardobjective != null) { ++ if (this.trackedObjectives.contains(scoreboardobjective)) { ++ this.broadcastAll(new ClientboundSetDisplayObjectivePacket(displayslot, scoreboardobjective)); // CraftBukkit + } else { + this.startTrackingObjective(objective); + } +@@ -96,9 +96,7 @@ + @Override + public boolean addPlayerToTeam(String playerName, PlayerTeam team) { + if (super.addPlayerToTeam(playerName, team)) { +- this.server +- .getPlayerList() +- .broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(team, playerName, ClientboundSetPlayerTeamPacket.Action.ADD)); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(team, playerName, ClientboundSetPlayerTeamPacket.a.ADD)); // CraftBukkit + this.setDirty(); + return true; + } else { +@@ -109,9 +107,7 @@ + @Override + public void removePlayerFromTeam(String username, PlayerTeam playerTeam) { + super.removePlayerFromTeam(username, playerTeam); +- this.server +- .getPlayerList() +- .broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(playerTeam, username, ClientboundSetPlayerTeamPacket.Action.REMOVE)); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(playerTeam, username, ClientboundSetPlayerTeamPacket.a.REMOVE)); // CraftBukkit + this.setDirty(); + } + +@@ -125,7 +121,7 @@ + public void onObjectiveChanged(Objective objective) { + super.onObjectiveChanged(objective); + if (this.trackedObjectives.contains(objective)) { +- this.server.getPlayerList().broadcastAll(new ClientboundSetObjectivePacket(objective, 2)); ++ this.broadcastAll(new ClientboundSetObjectivePacket(objective, 2)); // CraftBukkit + } + + this.setDirty(); +@@ -144,21 +140,21 @@ + @Override + public void onTeamAdded(PlayerTeam playerTeam) { + super.onTeamAdded(playerTeam); +- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, true)); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, true)); // CraftBukkit + this.setDirty(); + } + + @Override + public void onTeamChanged(PlayerTeam playerTeam) { + super.onTeamChanged(playerTeam); +- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, false)); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, false)); // CraftBukkit + this.setDirty(); + } + + @Override + public void onTeamRemoved(PlayerTeam playerTeam) { + super.onTeamRemoved(playerTeam); +- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createRemovePacket(playerTeam)); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createRemovePacket(playerTeam)); // CraftBukkit + this.setDirty(); + } + +@@ -200,9 +203,15 @@ + public void startTrackingObjective(Objective objective) { + List> startTrackingPackets = this.getStartTrackingPackets(objective); + +- for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) { +- for (Packet packet : startTrackingPackets) { +- serverPlayer.connection.send(packet); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board ++ Iterator iterator1 = list.iterator(); ++ ++ while (iterator1.hasNext()) { ++ Packet packet = (Packet) iterator1.next(); ++ ++ entityplayer.connection.send(packet); + } + } + +@@ -225,9 +240,15 @@ + public void stopTrackingObjective(Objective objective) { + List> stopTrackingPackets = this.getStopTrackingPackets(objective); + +- for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) { +- for (Packet packet : stopTrackingPackets) { +- serverPlayer.connection.send(packet); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board ++ Iterator iterator1 = list.iterator(); ++ ++ while (iterator1.hasNext()) { ++ Packet packet = (Packet) iterator1.next(); ++ ++ entityplayer.connection.send(packet); + } + } + +@@ -260,8 +287,20 @@ + return this.createData().load(tag); + } + +- public static enum Method { +- CHANGE, +- REMOVE; ++ // CraftBukkit start - Send to players ++ private void broadcastAll(Packet packet) { ++ for (ServerPlayer entityplayer : (List) this.server.getPlayerList().players) { ++ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() == this) { ++ entityplayer.connection.send(packet); ++ } ++ } + } ++ // CraftBukkit end ++ ++ public static enum Action { ++ ++ CHANGE, REMOVE; ++ ++ private Action() {} ++ } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/ServerTickRateManager.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/ServerTickRateManager.java.patch new file mode 100644 index 0000000000..c245ad7f1a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/ServerTickRateManager.java.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/server/ServerTickRateManager.java ++++ b/net/minecraft/server/ServerTickRateManager.java +@@ -58,8 +59,14 @@ + } + + public boolean stopSprinting() { ++ // CraftBukkit start, add sendLog parameter ++ return stopSprinting(true); ++ } ++ ++ public boolean stopSprinting(boolean sendLog) { ++ // CraftBukkit end + if (this.remainingSprintTicks > 0L) { +- this.finishTickSprint(); ++ this.finishTickSprint(sendLog); // CraftBukkit - add sendLog parameter + return true; + } else { + return false; +@@ -76,14 +84,21 @@ + return flag; + } + +- private void finishTickSprint() { +- long l = this.scheduledCurrentSprintTicks - this.remainingSprintTicks; +- double d = Math.max(1.0, (double)this.sprintTimeSpend) / (double)TimeUtil.NANOSECONDS_PER_MILLISECOND; +- int i = (int)((double)(TimeUtil.MILLISECONDS_PER_SECOND * l) / d); +- String string = String.format("%.2f", l == 0L ? (double)this.millisecondsPerTick() : d / (double)l); ++ private void finishTickSprint(boolean sendLog) { // CraftBukkit - add sendLog parameter ++ long i = this.scheduledCurrentSprintTicks - this.remainingSprintTicks; ++ double d0 = Math.max(1.0D, (double) this.sprintTimeSpend) / (double) TimeUtil.NANOSECONDS_PER_MILLISECOND; ++ int j = (int) ((double) (TimeUtil.MILLISECONDS_PER_SECOND * i) / d0); ++ String s = String.format("%.2f", i == 0L ? (double) this.millisecondsPerTick() : d0 / (double) i); ++ + this.scheduledCurrentSprintTicks = 0L; + this.sprintTimeSpend = 0L; +- this.server.createCommandSourceStack().sendSuccess(() -> Component.translatable("commands.tick.sprint.report", i, string), true); ++ // CraftBukkit start - add sendLog parameter ++ if (sendLog) { ++ this.server.createCommandSourceStack().sendSuccess(() -> { ++ return Component.translatable("commands.tick.sprint.report", j, s); ++ }, true); ++ } ++ // CraftBukkit end + this.remainingSprintTicks = 0L; + this.setFrozen(this.previousIsFrozen); + this.server.onTickRateChanged(); +@@ -97,7 +112,7 @@ + this.remainingSprintTicks--; + return true; + } else { +- this.finishTickSprint(); ++ this.finishTickSprint(true); // CraftBukkit - add sendLog parameter + return false; + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/bossevents/CustomBossEvent.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/bossevents/CustomBossEvent.java.patch new file mode 100644 index 0000000000..33f0bf143a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/bossevents/CustomBossEvent.java.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/server/bossevents/CustomBossEvent.java ++++ b/net/minecraft/server/bossevents/CustomBossEvent.java +@@ -17,13 +17,27 @@ + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.Mth; + import net.minecraft.world.BossEvent; ++// CraftBukkit start ++import org.bukkit.boss.KeyedBossBar; ++import org.bukkit.craftbukkit.boss.CraftKeyedBossbar; ++// CraftBukkit end + + public class CustomBossEvent extends ServerBossEvent { + private final ResourceLocation id; + private final Set players = Sets.newHashSet(); + private int value; + private int max = 100; ++ // CraftBukkit start ++ private KeyedBossBar bossBar; + ++ public KeyedBossBar getBukkitEntity() { ++ if (bossBar == null) { ++ bossBar = new CraftKeyedBossbar(this); ++ } ++ return bossBar; ++ } ++ // CraftBukkit end ++ + public CustomBossEvent(ResourceLocation id, Component name) { + super(name, BossEvent.BossBarColor.WHITE, BossEvent.BossBarOverlay.PROGRESS); + this.id = id; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/DifficultyCommand.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/DifficultyCommand.java.patch new file mode 100644 index 0000000000..b15cddbe16 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/DifficultyCommand.java.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/server/commands/DifficultyCommand.java ++++ b/net/minecraft/server/commands/DifficultyCommand.java +@@ -31,12 +43,16 @@ + } + + public static int setDifficulty(CommandSourceStack source, Difficulty difficulty) throws CommandSyntaxException { +- MinecraftServer server = source.getServer(); +- if (server.getWorldData().getDifficulty() == difficulty) { +- throw ERROR_ALREADY_DIFFICULT.create(difficulty.getKey()); ++ MinecraftServer minecraftserver = source.getServer(); ++ net.minecraft.server.level.ServerLevel worldServer = source.getLevel(); // CraftBukkit ++ ++ if (worldServer.getDifficulty() == difficulty) { // CraftBukkit ++ throw DifficultyCommand.ERROR_ALREADY_DIFFICULT.create(difficulty.getKey()); + } else { +- server.setDifficulty(difficulty, true); +- source.sendSuccess(() -> Component.translatable("commands.difficulty.success", difficulty.getDisplayName()), true); ++ worldServer.serverLevelData.setDifficulty(difficulty); // CraftBukkit ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.difficulty.success", difficulty.getDisplayName()); ++ }, true); + return 0; + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/EffectCommands.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/EffectCommands.java.patch new file mode 100644 index 0000000000..30036ad39a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/EffectCommands.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/server/commands/EffectCommands.java ++++ b/net/minecraft/server/commands/EffectCommands.java +@@ -180,9 +82,10 @@ + + for (Entity entity : targets) { + if (entity instanceof LivingEntity) { +- MobEffectInstance mobEffectInstance = new MobEffectInstance(mobEffect, i1, amplifier, false, showParticles); +- if (((LivingEntity)entity).addEffect(mobEffectInstance, source.getEntity())) { +- i++; ++ MobEffectInstance mobeffect = new MobEffectInstance(mobeffectlist, k, amplifier, false, showParticles); ++ ++ if (((LivingEntity) entity).addEffect(mobeffect, source.getEntity(), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.COMMAND)) { // CraftBukkit ++ ++j; + } + } + } +@@ -210,9 +111,11 @@ + private static int clearEffects(CommandSourceStack source, Collection targets) throws CommandSyntaxException { + int i = 0; + +- for (Entity entity : targets) { +- if (entity instanceof LivingEntity && ((LivingEntity)entity).removeAllEffects()) { +- i++; ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ ++ if (entity instanceof LivingEntity && ((LivingEntity) entity).removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.COMMAND)) { // CraftBukkit ++ ++i; + } + } + +@@ -235,9 +141,11 @@ + MobEffect mobEffect = effect.value(); + int i = 0; + +- for (Entity entity : targets) { +- if (entity instanceof LivingEntity && ((LivingEntity)entity).removeEffect(mobEffect)) { +- i++; ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ ++ if (entity instanceof LivingEntity && ((LivingEntity) entity).removeEffect(mobeffectlist, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.COMMAND)) { // CraftBukkit ++ ++i; + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/GameRuleCommand.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/GameRuleCommand.java.patch new file mode 100644 index 0000000000..7c5cf0e4ab --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/GameRuleCommand.java.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/server/commands/GameRuleCommand.java ++++ b/net/minecraft/server/commands/GameRuleCommand.java +@@ -27,16 +30,22 @@ + } + + static > int setRule(CommandContext source, GameRules.Key gameRule) { +- CommandSourceStack commandSourceStack = source.getSource(); +- T rule = commandSourceStack.getServer().getGameRules().getRule(gameRule); +- rule.setFromArgument(source, "value"); +- commandSourceStack.sendSuccess(() -> Component.translatable("commands.gamerule.set", gameRule.getId(), rule.toString()), true); +- return rule.getCommandResult(); ++ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) source.getSource(); ++ T t0 = commandlistenerwrapper.getLevel().getGameRules().getRule(gameRule); // CraftBukkit ++ ++ t0.setFromArgument(source, "value"); ++ commandlistenerwrapper.sendSuccess(() -> { ++ return Component.translatable("commands.gamerule.set", gameRule.getId(), t0.toString()); ++ }, true); ++ return t0.getCommandResult(); + } + + static > int queryRule(CommandSourceStack source, GameRules.Key gameRule) { +- T rule = source.getServer().getGameRules().getRule(gameRule); +- source.sendSuccess(() -> Component.translatable("commands.gamerule.query", gameRule.getId(), rule.toString()), false); +- return rule.getCommandResult(); ++ T t0 = source.getLevel().getGameRules().getRule(gameRule); // CraftBukkit ++ ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.gamerule.query", gameRule.getId(), t0.toString()); ++ }, false); ++ return t0.getCommandResult(); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/GiveCommand.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/GiveCommand.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/GiveCommand.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/ListPlayersCommand.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/ListPlayersCommand.java.patch new file mode 100644 index 0000000000..6bf629b9b6 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/ListPlayersCommand.java.patch @@ -0,0 +1,28 @@ +--- a/net/minecraft/server/commands/ListPlayersCommand.java ++++ b/net/minecraft/server/commands/ListPlayersCommand.java +@@ -32,10 +34,20 @@ + } + + private static int format(CommandSourceStack source, Function nameExtractor) { +- PlayerList playerList = source.getServer().getPlayerList(); +- List players = playerList.getPlayers(); +- Component component = ComponentUtils.formatList(players, nameExtractor); +- source.sendSuccess(() -> Component.translatable("commands.list.players", players.size(), playerList.getMaxPlayers(), component), false); +- return players.size(); ++ PlayerList playerlist = source.getServer().getPlayerList(); ++ // CraftBukkit start ++ List players = playerlist.getPlayers(); ++ if (source.getBukkitSender() instanceof org.bukkit.entity.Player) { ++ org.bukkit.entity.Player sender = (org.bukkit.entity.Player) source.getBukkitSender(); ++ players = players.stream().filter((ep) -> sender.canSee(ep.getBukkitEntity())).collect(java.util.stream.Collectors.toList()); ++ } ++ List list = players; ++ // CraftBukkit end ++ Component ichatbasecomponent = ComponentUtils.formatList(list, nameExtractor); ++ ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.list.players", list.size(), playerlist.getMaxPlayers(), ichatbasecomponent); ++ }, false); ++ return list.size(); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/LootCommand.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/LootCommand.java.patch new file mode 100644 index 0000000000..1ab5f0f7ac --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/LootCommand.java.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/server/commands/LootCommand.java ++++ b/net/minecraft/server/commands/LootCommand.java +@@ -392,11 +245,14 @@ + } + + private static int dropInWorld(CommandSourceStack source, Vec3 pos, List items, LootCommand.Callback callback) throws CommandSyntaxException { +- ServerLevel level = source.getLevel(); +- items.forEach(itemStack -> { +- ItemEntity itemEntity = new ItemEntity(level, pos.x, pos.y, pos.z, itemStack.copy()); +- itemEntity.setDefaultPickUpDelay(); +- level.addFreshEntity(itemEntity); ++ ServerLevel worldserver = source.getLevel(); ++ ++ items.removeIf(ItemStack::isEmpty); // CraftBukkit - SPIGOT-6959 Remove empty items for avoid throw an error in new EntityItem ++ items.forEach((itemstack) -> { ++ ItemEntity entityitem = new ItemEntity(worldserver, pos.x, pos.y, pos.z, itemstack.copy()); ++ ++ entityitem.setDefaultPickUpDelay(); ++ worldserver.addFreshEntity(entityitem); + }); + callback.accept(items); + return items.size(); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/PlaceCommand.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/PlaceCommand.java.patch new file mode 100644 index 0000000000..56cb1597d9 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/PlaceCommand.java.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/server/commands/PlaceCommand.java ++++ b/net/minecraft/server/commands/PlaceCommand.java +@@ -278,30 +130,20 @@ + if (!structureStart.isValid()) { + throw ERROR_STRUCTURE_FAILED.create(); + } else { +- BoundingBox boundingBox = structureStart.getBoundingBox(); +- ChunkPos chunkPos = new ChunkPos(SectionPos.blockToSectionCoord(boundingBox.minX()), SectionPos.blockToSectionCoord(boundingBox.minZ())); +- ChunkPos chunkPos1 = new ChunkPos(SectionPos.blockToSectionCoord(boundingBox.maxX()), SectionPos.blockToSectionCoord(boundingBox.maxZ())); +- checkLoaded(level, chunkPos, chunkPos1); +- ChunkPos.rangeClosed(chunkPos, chunkPos1) +- .forEach( +- chunkPos2 -> structureStart.placeInChunk( +- level, +- level.structureManager(), +- generator, +- level.getRandom(), +- new BoundingBox( +- chunkPos2.getMinBlockX(), +- level.getMinBuildHeight(), +- chunkPos2.getMinBlockZ(), +- chunkPos2.getMaxBlockX(), +- level.getMaxBuildHeight(), +- chunkPos2.getMaxBlockZ() +- ), +- chunkPos2 +- ) +- ); +- String string = structure.key().location().toString(); +- source.sendSuccess(() -> Component.translatable("commands.place.structure.success", string, pos.getX(), pos.getY(), pos.getZ()), true); ++ structurestart.generationEventCause = org.bukkit.event.world.AsyncStructureGenerateEvent.Cause.COMMAND; // CraftBukkit - set AsyncStructureGenerateEvent.Cause.COMMAND as generation cause ++ BoundingBox structureboundingbox = structurestart.getBoundingBox(); ++ ChunkPos chunkcoordintpair = new ChunkPos(SectionPos.blockToSectionCoord(structureboundingbox.minX()), SectionPos.blockToSectionCoord(structureboundingbox.minZ())); ++ ChunkPos chunkcoordintpair1 = new ChunkPos(SectionPos.blockToSectionCoord(structureboundingbox.maxX()), SectionPos.blockToSectionCoord(structureboundingbox.maxZ())); ++ ++ checkLoaded(worldserver, chunkcoordintpair, chunkcoordintpair1); ++ ChunkPos.rangeClosed(chunkcoordintpair, chunkcoordintpair1).forEach((chunkcoordintpair2) -> { ++ structurestart.placeInChunk(worldserver, worldserver.structureManager(), chunkgenerator, worldserver.getRandom(), new BoundingBox(chunkcoordintpair2.getMinBlockX(), worldserver.getMinBuildHeight(), chunkcoordintpair2.getMinBlockZ(), chunkcoordintpair2.getMaxBlockX(), worldserver.getMaxBuildHeight(), chunkcoordintpair2.getMaxBlockZ()), chunkcoordintpair2); ++ }); ++ String s = structure.key().location().toString(); ++ ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.place.structure.success", s, pos.getX(), pos.getY(), pos.getZ()); ++ }, true); + return 1; + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/ReloadCommand.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/ReloadCommand.java.patch new file mode 100644 index 0000000000..a69371ae12 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/ReloadCommand.java.patch @@ -0,0 +1,19 @@ +--- a/net/minecraft/server/commands/ReloadCommand.java ++++ b/net/minecraft/server/commands/ReloadCommand.java +@@ -38,6 +44,16 @@ + return list; + } + ++ // CraftBukkit start ++ public static void reload(MinecraftServer minecraftserver) { ++ PackRepository resourcepackrepository = minecraftserver.getPackRepository(); ++ WorldData savedata = minecraftserver.getWorldData(); ++ Collection collection = resourcepackrepository.getSelectedIds(); ++ Collection collection1 = discoverNewPacks(resourcepackrepository, savedata, collection); ++ minecraftserver.reloadResources(collection1); ++ } ++ // CraftBukkit end ++ + public static void register(CommandDispatcher dispatcher) { + dispatcher.register(Commands.literal("reload").requires(source -> source.hasPermission(2)).executes(context -> { + CommandSourceStack commandSourceStack = context.getSource(); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/ScheduleCommand.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/ScheduleCommand.java.patch new file mode 100644 index 0000000000..52ffe0022a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/ScheduleCommand.java.patch @@ -0,0 +1,64 @@ +--- a/net/minecraft/server/commands/ScheduleCommand.java ++++ b/net/minecraft/server/commands/ScheduleCommand.java +@@ -98,33 +53,34 @@ + if (time == 0) { + throw ERROR_SAME_TICK.create(); + } else { +- long l = source.getLevel().getGameTime() + (long)time; +- ResourceLocation resourceLocation = function.getFirst(); +- TimerQueue scheduledEvents = source.getServer().getWorldData().overworldData().getScheduledEvents(); +- function.getSecond() +- .ifLeft( +- commandFunction -> { +- String string = resourceLocation.toString(); +- if (append) { +- scheduledEvents.remove(string); +- } +- +- scheduledEvents.schedule(string, l, new FunctionCallback(resourceLocation)); +- source.sendSuccess( +- () -> Component.translatable("commands.schedule.created.function", Component.translationArg(resourceLocation), time, l), true +- ); +- } +- ) +- .ifRight(functions -> { +- String string = "#" + resourceLocation; +- if (append) { +- scheduledEvents.remove(string); +- } +- +- scheduledEvents.schedule(string, l, new FunctionTagCallback(resourceLocation)); +- source.sendSuccess(() -> Component.translatable("commands.schedule.created.tag", Component.translationArg(resourceLocation), time, l), true); +- }); +- return Math.floorMod(l, Integer.MAX_VALUE); ++ long j = source.getLevel().getGameTime() + (long) time; ++ ResourceLocation minecraftkey = (ResourceLocation) function.getFirst(); ++ TimerQueue customfunctioncallbacktimerqueue = source.getLevel().serverLevelData.overworldData().getScheduledEvents(); // CraftBukkit - SPIGOT-6667: Use world specific function timer ++ ++ ((Either) function.getSecond()).ifLeft((net_minecraft_commands_functions_commandfunction) -> { ++ String s = minecraftkey.toString(); ++ ++ if (append) { ++ customfunctioncallbacktimerqueue.remove(s); ++ } ++ ++ customfunctioncallbacktimerqueue.schedule(s, j, new FunctionCallback(minecraftkey)); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.schedule.created.function", Component.translationArg(minecraftkey), time, j); ++ }, true); ++ }).ifRight((collection) -> { ++ String s = "#" + minecraftkey; ++ ++ if (append) { ++ customfunctioncallbacktimerqueue.remove(s); ++ } ++ ++ customfunctioncallbacktimerqueue.schedule(s, j, new FunctionTagCallback(minecraftkey)); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.schedule.created.tag", Component.translationArg(minecraftkey), time, j); ++ }, true); ++ }); ++ return Math.floorMod(j, Integer.MAX_VALUE); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/SetSpawnCommand.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/SetSpawnCommand.java.patch new file mode 100644 index 0000000000..356262cf04 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/SetSpawnCommand.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/server/commands/SetSpawnCommand.java ++++ b/net/minecraft/server/commands/SetSpawnCommand.java +@@ -67,8 +38,10 @@ + private static int setSpawn(CommandSourceStack source, Collection targets, BlockPos pos, float angle) { + ResourceKey resourceKey = source.getLevel().dimension(); + +- for (ServerPlayer serverPlayer : targets) { +- serverPlayer.setRespawnPosition(resourceKey, pos, angle, true, false); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ entityplayer.setRespawnPosition(resourcekey, pos, angle, true, false, org.bukkit.event.player.PlayerSpawnChangeEvent.Cause.COMMAND); // CraftBukkit + } + + String string = resourceKey.location().toString(); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/SpreadPlayersCommand.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/SpreadPlayersCommand.java.patch new file mode 100644 index 0000000000..d4a282363e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/SpreadPlayersCommand.java.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/server/commands/SpreadPlayersCommand.java ++++ b/net/minecraft/server/commands/SpreadPlayersCommand.java +@@ -247,16 +203,10 @@ + position = positions[i++]; + } + +- entity.teleportTo( +- level, +- (double)Mth.floor(position.x) + 0.5, +- (double)position.getSpawnY(level, maxHeight), +- (double)Mth.floor(position.z) + 0.5, +- Set.of(), +- entity.getYRot(), +- entity.getXRot() +- ); +- double d1 = Double.MAX_VALUE; ++ entity.teleportTo(level, (double) Mth.floor(commandspreadplayers_a.x) + 0.5D, (double) commandspreadplayers_a.getSpawnY(level, maxHeight), (double) Mth.floor(commandspreadplayers_a.z) + 0.5D, Set.of(), entity.getYRot(), entity.getXRot(), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.COMMAND); // CraftBukkit - handle teleport reason ++ d1 = Double.MAX_VALUE; ++ SpreadPlayersCommand.Position[] acommandspreadplayers_a1 = positions; ++ int k = positions.length; + + for (SpreadPlayersCommand.Position position1 : positions) { + if (position != position1) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/SummonCommand.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/SummonCommand.java.patch new file mode 100644 index 0000000000..78a9b9643e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/SummonCommand.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/server/commands/SummonCommand.java ++++ b/net/minecraft/server/commands/SummonCommand.java +@@ -93,8 +67,8 @@ + .finalizeSpawn(source.getLevel(), source.getLevel().getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.COMMAND, null, null); + } + +- if (!level.tryAddFreshEntityWithPassengers(entity)) { +- throw ERROR_DUPLICATE_UUID.create(); ++ if (!worldserver.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.COMMAND)) { // CraftBukkit - pass a spawn reason of "COMMAND" ++ throw SummonCommand.ERROR_DUPLICATE_UUID.create(); + } else { + return entity; + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/TeleportCommand.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/TeleportCommand.java.patch new file mode 100644 index 0000000000..7c48c84c90 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/TeleportCommand.java.patch @@ -0,0 +1,71 @@ +--- a/net/minecraft/server/commands/TeleportCommand.java ++++ b/net/minecraft/server/commands/TeleportCommand.java +@@ -31,6 +32,12 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.event.entity.EntityTeleportEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++// CraftBukkit end + + public class TeleportCommand { + private static final SimpleCommandExceptionType INVALID_POSITION = new SimpleCommandExceptionType( +@@ -278,15 +158,48 @@ + if (!Level.isInSpawnableBounds(blockPos)) { + throw INVALID_POSITION.create(); + } else { +- float f = Mth.wrapDegrees(yaw); +- float f1 = Mth.wrapDegrees(pitch); +- if (entity.teleportTo(level, x, y, z, relativeList, f, f1)) { +- if (facing != null) { +- facing.perform(source, entity); ++ float f2 = Mth.wrapDegrees(z); ++ float f3 = Mth.wrapDegrees(f1); ++ ++ // CraftBukkit start - Teleport event ++ boolean result; ++ if (entity instanceof ServerPlayer player) { ++ result = player.teleportTo(level, x, d1, y, set, f2, f3, PlayerTeleportEvent.TeleportCause.COMMAND); ++ } else { ++ Location to = new Location(level.getWorld(), x, d1, y, f2, f3); ++ EntityTeleportEvent event = new EntityTeleportEvent(entity.getBukkitEntity(), entity.getBukkitEntity().getLocation(), to); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; + } + +- if (!(entity instanceof LivingEntity livingEntity) || !livingEntity.isFallFlying()) { +- entity.setDeltaMovement(entity.getDeltaMovement().multiply(1.0, 0.0, 1.0)); ++ x = to.getX(); ++ d1 = to.getY(); ++ y = to.getZ(); ++ f2 = to.getYaw(); ++ f3 = to.getPitch(); ++ level = ((CraftWorld) to.getWorld()).getHandle(); ++ ++ result = entity.teleportTo(level, x, d1, y, set, f2, f3); ++ } ++ ++ if (result) { ++ // CraftBukkit end ++ if (relativeList != null) { ++ relativeList.perform(source, entity); ++ } ++ ++ label23: ++ { ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ if (entityliving.isFallFlying()) { ++ break label23; ++ } ++ } ++ ++ entity.setDeltaMovement(entity.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D)); + entity.setOnGround(true); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/TimeCommand.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/TimeCommand.java.patch new file mode 100644 index 0000000000..2b1aacbdab --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/TimeCommand.java.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/server/commands/TimeCommand.java ++++ b/net/minecraft/server/commands/TimeCommand.java +@@ -8,6 +8,10 @@ + import net.minecraft.commands.arguments.TimeArgument; + import net.minecraft.network.chat.Component; + import net.minecraft.server.level.ServerLevel; ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.event.world.TimeSkipEvent; ++// CraftBukkit end + + public class TimeCommand { + public static void register(CommandDispatcher dispatcher) { +@@ -57,8 +53,18 @@ + } + + public static int setTime(CommandSourceStack source, int time) { +- for (ServerLevel serverLevel : source.getServer().getAllLevels()) { +- serverLevel.setDayTime((long)time); ++ Iterator iterator = com.google.common.collect.Iterators.singletonIterator(source.getLevel()); // CraftBukkit - SPIGOT-6496: Only set the time for the world the command originates in ++ ++ while (iterator.hasNext()) { ++ ServerLevel worldserver = (ServerLevel) iterator.next(); ++ ++ // CraftBukkit start ++ TimeSkipEvent event = new TimeSkipEvent(worldserver.getWorld(), TimeSkipEvent.SkipReason.COMMAND, time - worldserver.getDayTime()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ worldserver.setDayTime((long) worldserver.getDayTime() + event.getSkipAmount()); ++ } ++ // CraftBukkit end + } + + source.sendSuccess(() -> Component.translatable("commands.time.set", time), true); +@@ -66,8 +74,18 @@ + } + + public static int addTime(CommandSourceStack source, int amount) { +- for (ServerLevel serverLevel : source.getServer().getAllLevels()) { +- serverLevel.setDayTime(serverLevel.getDayTime() + (long)amount); ++ Iterator iterator = com.google.common.collect.Iterators.singletonIterator(source.getLevel()); // CraftBukkit - SPIGOT-6496: Only set the time for the world the command originates in ++ ++ while (iterator.hasNext()) { ++ ServerLevel worldserver = (ServerLevel) iterator.next(); ++ ++ // CraftBukkit start ++ TimeSkipEvent event = new TimeSkipEvent(worldserver.getWorld(), TimeSkipEvent.SkipReason.COMMAND, amount); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ worldserver.setDayTime(worldserver.getDayTime() + event.getSkipAmount()); ++ } ++ // CraftBukkit end + } + + int dayTime = getDayTime(source.getLevel()); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/WorldBorderCommand.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/WorldBorderCommand.java.patch new file mode 100644 index 0000000000..62a4be2c2b --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/commands/WorldBorderCommand.java.patch @@ -0,0 +1,122 @@ +--- a/net/minecraft/server/commands/WorldBorderCommand.java ++++ b/net/minecraft/server/commands/WorldBorderCommand.java +@@ -137,9 +57,10 @@ + } + + private static int setDamageBuffer(CommandSourceStack source, float distance) throws CommandSyntaxException { +- WorldBorder worldBorder = source.getServer().overworld().getWorldBorder(); +- if (worldBorder.getDamageSafeZone() == (double)distance) { +- throw ERROR_SAME_DAMAGE_BUFFER.create(); ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit ++ ++ if (worldborder.getDamageSafeZone() == (double) distance) { ++ throw WorldBorderCommand.ERROR_SAME_DAMAGE_BUFFER.create(); + } else { + worldBorder.setDamageSafeZone((double)distance); + source.sendSuccess(() -> Component.translatable("commands.worldborder.damage.buffer.success", String.format(Locale.ROOT, "%.2f", distance)), true); +@@ -148,9 +71,10 @@ + } + + private static int setDamageAmount(CommandSourceStack source, float damagePerBlock) throws CommandSyntaxException { +- WorldBorder worldBorder = source.getServer().overworld().getWorldBorder(); +- if (worldBorder.getDamagePerBlock() == (double)damagePerBlock) { +- throw ERROR_SAME_DAMAGE_AMOUNT.create(); ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit ++ ++ if (worldborder.getDamagePerBlock() == (double) damagePerBlock) { ++ throw WorldBorderCommand.ERROR_SAME_DAMAGE_AMOUNT.create(); + } else { + worldBorder.setDamagePerBlock((double)damagePerBlock); + source.sendSuccess( +@@ -161,9 +85,10 @@ + } + + private static int setWarningTime(CommandSourceStack source, int time) throws CommandSyntaxException { +- WorldBorder worldBorder = source.getServer().overworld().getWorldBorder(); +- if (worldBorder.getWarningTime() == time) { +- throw ERROR_SAME_WARNING_TIME.create(); ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit ++ ++ if (worldborder.getWarningTime() == time) { ++ throw WorldBorderCommand.ERROR_SAME_WARNING_TIME.create(); + } else { + worldBorder.setWarningTime(time); + source.sendSuccess(() -> Component.translatable("commands.worldborder.warning.time.success", time), true); +@@ -172,9 +99,10 @@ + } + + private static int setWarningDistance(CommandSourceStack source, int distance) throws CommandSyntaxException { +- WorldBorder worldBorder = source.getServer().overworld().getWorldBorder(); +- if (worldBorder.getWarningBlocks() == distance) { +- throw ERROR_SAME_WARNING_DISTANCE.create(); ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit ++ ++ if (worldborder.getWarningBlocks() == distance) { ++ throw WorldBorderCommand.ERROR_SAME_WARNING_DISTANCE.create(); + } else { + worldBorder.setWarningBlocks(distance); + source.sendSuccess(() -> Component.translatable("commands.worldborder.warning.distance.success", distance), true); +@@ -183,38 +113,40 @@ + } + + private static int getSize(CommandSourceStack source) { +- double size = source.getServer().overworld().getWorldBorder().getSize(); +- source.sendSuccess(() -> Component.translatable("commands.worldborder.get", String.format(Locale.ROOT, "%.0f", size)), false); +- return Mth.floor(size + 0.5); ++ double d0 = source.getLevel().getWorldBorder().getSize(); // CraftBukkit ++ ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.worldborder.get", String.format(Locale.ROOT, "%.0f", d0)); ++ }, false); ++ return Mth.floor(d0 + 0.5D); + } + + private static int setCenter(CommandSourceStack source, Vec2 pos) throws CommandSyntaxException { +- WorldBorder worldBorder = source.getServer().overworld().getWorldBorder(); +- if (worldBorder.getCenterX() == (double)pos.x && worldBorder.getCenterZ() == (double)pos.y) { +- throw ERROR_SAME_CENTER.create(); +- } else if (!((double)Math.abs(pos.x) > 2.9999984E7) && !((double)Math.abs(pos.y) > 2.9999984E7)) { +- worldBorder.setCenter((double)pos.x, (double)pos.y); +- source.sendSuccess( +- () -> Component.translatable( +- "commands.worldborder.center.success", String.format(Locale.ROOT, "%.2f", pos.x), String.format(Locale.ROOT, "%.2f", pos.y) +- ), +- true +- ); ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit ++ ++ if (worldborder.getCenterX() == (double) pos.x && worldborder.getCenterZ() == (double) pos.y) { ++ throw WorldBorderCommand.ERROR_SAME_CENTER.create(); ++ } else if ((double) Math.abs(pos.x) <= 2.9999984E7D && (double) Math.abs(pos.y) <= 2.9999984E7D) { ++ worldborder.setCenter((double) pos.x, (double) pos.y); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.worldborder.center.success", String.format(Locale.ROOT, "%.2f", pos.x), String.format(Locale.ROOT, "%.2f", pos.y)); ++ }, true); + return 0; + } else { + throw ERROR_TOO_FAR_OUT.create(); + } + } + +- private static int setSize(CommandSourceStack source, double newSize, long time) throws CommandSyntaxException { +- WorldBorder worldBorder = source.getServer().overworld().getWorldBorder(); +- double size = worldBorder.getSize(); +- if (size == newSize) { +- throw ERROR_SAME_SIZE.create(); +- } else if (newSize < 1.0) { +- throw ERROR_TOO_SMALL.create(); +- } else if (newSize > 5.999997E7F) { +- throw ERROR_TOO_BIG.create(); ++ private static int setSize(CommandSourceStack source, double newSize, long i) throws CommandSyntaxException { ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit ++ double d1 = worldborder.getSize(); ++ ++ if (d1 == newSize) { ++ throw WorldBorderCommand.ERROR_SAME_SIZE.create(); ++ } else if (newSize < 1.0D) { ++ throw WorldBorderCommand.ERROR_TOO_SMALL.create(); ++ } else if (newSize > 5.9999968E7D) { ++ throw WorldBorderCommand.ERROR_TOO_BIG.create(); + } else { + if (time > 0L) { + worldBorder.lerpSizeBetween(size, newSize, time); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/dedicated/DedicatedServer.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/dedicated/DedicatedServer.java.patch new file mode 100644 index 0000000000..6aba594883 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/dedicated/DedicatedServer.java.patch @@ -0,0 +1,302 @@ +--- a/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/net/minecraft/server/dedicated/DedicatedServer.java +@@ -53,6 +52,16 @@ + import net.minecraft.world.level.storage.LevelStorageSource; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.server.WorldLoader; ++import org.apache.logging.log4j.Level; ++import org.apache.logging.log4j.LogManager; ++import org.apache.logging.log4j.io.IoBuilder; ++import org.bukkit.command.CommandSender; ++import org.bukkit.event.server.ServerCommandEvent; ++import org.bukkit.event.server.RemoteServerCommandEvent; ++// CraftBukkit end ++ + public class DedicatedServer extends MinecraftServer implements ServerInterface { + static final Logger LOGGER = LogUtils.getLogger(); + private static final int CONVERSION_RETRY_DELAY_MS = 5000; +@@ -60,7 +70,7 @@ + private final List consoleInput = Collections.synchronizedList(Lists.newArrayList()); + @Nullable + private QueryThreadGs4 queryThreadGs4; +- private final RconConsoleSource rconConsoleSource; ++ // private final RemoteControlCommandListener rconConsoleSource; // CraftBukkit - remove field + @Nullable + private RconThread rconThread; + private final DedicatedServerSettings settings; +@@ -69,20 +79,13 @@ + @Nullable + private final TextFilterClient textFilterClient; + +- public DedicatedServer( +- Thread serverThread, +- LevelStorageSource.LevelStorageAccess storageSource, +- PackRepository packRepository, +- WorldStem worldStem, +- DedicatedServerSettings settings, +- DataFixer fixerUpper, +- Services services, +- ChunkProgressListenerFactory progressListenerFactory +- ) { +- super(serverThread, storageSource, packRepository, worldStem, Proxy.NO_PROXY, fixerUpper, services, progressListenerFactory); +- this.settings = settings; +- this.rconConsoleSource = new RconConsoleSource(this); +- this.textFilterClient = TextFilterClient.createFromConfig(settings.getProperties().textFilteringConfig); ++ // CraftBukkit start - Signature changed ++ public DedicatedServer(joptsimple.OptionSet options, WorldLoader.a worldLoader, Thread thread, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PackRepository resourcepackrepository, WorldStem worldstem, DedicatedServerSettings dedicatedserversettings, DataFixer datafixer, Services services, ChunkProgressListenerFactory worldloadlistenerfactory) { ++ super(options, worldLoader, thread, convertable_conversionsession, resourcepackrepository, worldstem, Proxy.NO_PROXY, datafixer, services, worldloadlistenerfactory); ++ // CraftBukkit end ++ this.settings = dedicatedserversettings; ++ // this.rconConsoleSource = new RemoteControlCommandListener(this); // CraftBukkit - remove field ++ this.textFilterClient = TextFilterClient.createFromConfig(dedicatedserversettings.getProperties().textFilteringConfig); + } + + @Override +@@ -90,18 +92,72 @@ + Thread thread = new Thread("Server console handler") { + @Override + public void run() { +- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8)); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.Main.useConsole) { ++ return; ++ } ++ jline.console.ConsoleReader bufferedreader = reader; + + String string1; + try { +- while (!DedicatedServer.this.isStopped() && DedicatedServer.this.isRunning() && (string1 = bufferedReader.readLine()) != null) { +- DedicatedServer.this.handleConsoleInput(string1, DedicatedServer.this.createCommandSourceStack()); ++ System.in.available(); ++ } catch (IOException ex) { ++ return; ++ } ++ // CraftBukkit end ++ ++ String s; ++ ++ try { ++ // CraftBukkit start - JLine disabling compatibility ++ while (!DedicatedServer.this.isStopped() && DedicatedServer.this.isRunning()) { ++ if (org.bukkit.craftbukkit.Main.useJline) { ++ s = bufferedreader.readLine(">", null); ++ } else { ++ s = bufferedreader.readLine(); ++ } ++ ++ // SPIGOT-5220: Throttle if EOF (ctrl^d) or stdin is /dev/null ++ if (s == null) { ++ try { ++ Thread.sleep(50L); ++ } catch (InterruptedException ex) { ++ Thread.currentThread().interrupt(); ++ } ++ continue; ++ } ++ if (s.trim().length() > 0) { // Trim to filter lines which are just spaces ++ DedicatedServer.this.handleConsoleInput(s, DedicatedServer.this.createCommandSourceStack()); ++ } ++ // CraftBukkit end + } + } catch (IOException var4) { + DedicatedServer.LOGGER.error("Exception handling console input", (Throwable)var4); + } + } + }; ++ ++ // CraftBukkit start - TODO: handle command-line logging arguments ++ java.util.logging.Logger global = java.util.logging.Logger.getLogger(""); ++ global.setUseParentHandlers(false); ++ for (java.util.logging.Handler handler : global.getHandlers()) { ++ global.removeHandler(handler); ++ } ++ global.addHandler(new org.bukkit.craftbukkit.util.ForwardLogHandler()); ++ ++ final org.apache.logging.log4j.core.Logger logger = ((org.apache.logging.log4j.core.Logger) LogManager.getRootLogger()); ++ for (org.apache.logging.log4j.core.Appender appender : logger.getAppenders().values()) { ++ if (appender instanceof org.apache.logging.log4j.core.appender.ConsoleAppender) { ++ logger.removeAppender(appender); ++ } ++ } ++ ++ new org.bukkit.craftbukkit.util.TerminalConsoleWriterThread(System.out, this.reader).start(); ++ ++ System.setOut(IoBuilder.forLogger(logger).setLevel(Level.INFO).buildPrintStream()); ++ System.setErr(IoBuilder.forLogger(logger).setLevel(Level.WARN).buildPrintStream()); ++ // CraftBukkit end ++ + thread.setDaemon(true); + thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER)); + thread.start(); +@@ -120,14 +178,15 @@ + this.setLocalIp(properties.serverIp); + } + +- this.setPvpAllowed(properties.pvp); +- this.setFlightAllowed(properties.allowFlight); +- this.setMotd(properties.motd); +- super.setPlayerIdleTimeout(properties.playerIdleTimeout.get()); +- this.setEnforceWhitelist(properties.enforceWhitelist); +- this.worldData.setGameType(properties.gamemode); +- LOGGER.info("Default game type: {}", properties.gamemode); +- InetAddress inetAddress = null; ++ this.setPvpAllowed(dedicatedserverproperties.pvp); ++ this.setFlightAllowed(dedicatedserverproperties.allowFlight); ++ this.setMotd(dedicatedserverproperties.motd); ++ super.setPlayerIdleTimeout((Integer) dedicatedserverproperties.playerIdleTimeout.get()); ++ this.setEnforceWhitelist(dedicatedserverproperties.enforceWhitelist); ++ // this.worldData.setGameType(dedicatedserverproperties.gamemode); // CraftBukkit - moved to world loading ++ DedicatedServer.LOGGER.info("Default game type: {}", dedicatedserverproperties.gamemode); ++ InetAddress inetaddress = null; ++ + if (!this.getLocalIp().isEmpty()) { + inetAddress = InetAddress.getByName(this.getLocalIp()); + } +@@ -148,6 +207,12 @@ + return false; + } + ++ // CraftBukkit start ++ this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); ++ server.loadPlugins(); ++ server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.STARTUP); ++ // CraftBukkit end ++ + if (!this.usesAuthentication()) { + LOGGER.warn("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!"); + LOGGER.warn("The server will make no attempt to authenticate usernames. Beware."); +@@ -164,17 +227,19 @@ + if (!OldUsersConverter.serverReadyAfterUserconversion(this)) { + return false; + } else { +- this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); +- long nanos = Util.getNanos(); ++ // this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); // CraftBukkit - moved up ++ long i = Util.getNanos(); ++ + SkullBlockEntity.setup(this.services, this); + GameProfileCache.setUsesAuthentication(this.usesAuthentication()); +- LOGGER.info("Preparing level \"{}\"", this.getLevelIdName()); +- this.loadLevel(); +- long l = Util.getNanos() - nanos; +- String string = String.format(Locale.ROOT, "%.3fs", (double)l / 1.0E9); +- LOGGER.info("Done ({})! For help, type \"help\"", string); +- if (properties.announcePlayerAchievements != null) { +- this.getGameRules().getRule(GameRules.RULE_ANNOUNCE_ADVANCEMENTS).set(properties.announcePlayerAchievements, this); ++ DedicatedServer.LOGGER.info("Preparing level \"{}\"", this.getLevelIdName()); ++ this.loadLevel(storageSource.getLevelId()); // CraftBukkit ++ long j = Util.getNanos() - i; ++ String s = String.format(Locale.ROOT, "%.3fs", (double) j / 1.0E9D); ++ ++ DedicatedServer.LOGGER.info("Done ({})! For help, type \"help\"", s); ++ if (dedicatedserverproperties.announcePlayerAchievements != null) { ++ ((GameRules.BooleanValue) this.getGameRules().getRule(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)).set(dedicatedserverproperties.announcePlayerAchievements, this); + } + + if (properties.enableQuery) { +@@ -278,6 +364,8 @@ + if (this.queryThreadGs4 != null) { + this.queryThreadGs4.stop(); + } ++ ++ System.exit(0); // CraftBukkit + } + + @Override +@@ -297,8 +385,17 @@ + + public void handleConsoleInputs() { + while (!this.consoleInput.isEmpty()) { +- ConsoleInput consoleInput = this.consoleInput.remove(0); +- this.getCommands().performPrefixedCommand(consoleInput.source, consoleInput.msg); ++ ConsoleInput servercommand = (ConsoleInput) this.consoleInput.remove(0); ++ ++ // CraftBukkit start - ServerCommand for preprocessing ++ ServerCommandEvent event = new ServerCommandEvent(console, servercommand.msg); ++ server.getPluginManager().callEvent(event); ++ if (event.isCancelled()) continue; ++ servercommand = new ConsoleInput(event.getCommand(), servercommand.source); ++ ++ // this.getCommands().performPrefixedCommand(servercommand.source, servercommand.msg); // Called in dispatchServerCommand ++ server.dispatchServerCommand(console, servercommand); ++ // CraftBukkit end + } + } + +@@ -516,16 +622,54 @@ + + @Override + public String getPluginNames() { +- return ""; ++ // CraftBukkit start - Whole method ++ StringBuilder result = new StringBuilder(); ++ org.bukkit.plugin.Plugin[] plugins = server.getPluginManager().getPlugins(); ++ ++ result.append(server.getName()); ++ result.append(" on Bukkit "); ++ result.append(server.getBukkitVersion()); ++ ++ if (plugins.length > 0 && server.getQueryPlugins()) { ++ result.append(": "); ++ ++ for (int i = 0; i < plugins.length; i++) { ++ if (i > 0) { ++ result.append("; "); ++ } ++ ++ result.append(plugins[i].getDescription().getName()); ++ result.append(" "); ++ result.append(plugins[i].getDescription().getVersion().replaceAll(";", ",")); ++ } ++ } ++ ++ return result.toString(); ++ // CraftBukkit end + } + + @Override + public String runCommand(String command) { +- this.rconConsoleSource.prepareForCommand(); +- this.executeBlocking(() -> this.getCommands().performPrefixedCommand(this.rconConsoleSource.createCommandSourceStack(), command)); +- return this.rconConsoleSource.getCommandResponse(); ++ // CraftBukkit start - fire RemoteServerCommandEvent ++ throw new UnsupportedOperationException("Not supported - remote source required."); + } + ++ public String runCommand(RconConsoleSource rconConsoleSource, String s) { ++ rconConsoleSource.prepareForCommand(); ++ this.executeBlocking(() -> { ++ CommandSourceStack wrapper = rconConsoleSource.createCommandSourceStack(); ++ RemoteServerCommandEvent event = new RemoteServerCommandEvent(rconConsoleSource.getBukkitSender(wrapper), s); ++ server.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ ConsoleInput serverCommand = new ConsoleInput(event.getCommand(), wrapper); ++ server.dispatchServerCommand(event.getSender(), serverCommand); ++ }); ++ return rconConsoleSource.getCommandResponse(); ++ // CraftBukkit end ++ } ++ + public void storeUsingWhiteList(boolean isStoreUsingWhiteList) { + this.settings.update(dedicatedServerProperties -> dedicatedServerProperties.whiteList.update(this.registryAccess(), isStoreUsingWhiteList)); + } +@@ -572,4 +718,15 @@ + public Optional getServerResourcePack() { + return this.settings.getProperties().serverResourcePackInfo; + } ++ ++ // CraftBukkit start ++ public boolean isDebugging() { ++ return this.getProperties().debug; ++ } ++ ++ @Override ++ public CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return console; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/dedicated/DedicatedServerProperties.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/dedicated/DedicatedServerProperties.java.patch new file mode 100644 index 0000000000..83af36188f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/dedicated/DedicatedServerProperties.java.patch @@ -0,0 +1,95 @@ +--- a/net/minecraft/server/dedicated/DedicatedServerProperties.java ++++ b/net/minecraft/server/dedicated/DedicatedServerProperties.java +@@ -41,10 +44,15 @@ + import net.minecraft.world.level.levelgen.presets.WorldPresets; + import org.slf4j.Logger; + ++// CraftBukkit start ++import joptsimple.OptionSet; ++// CraftBukkit end ++ + public class DedicatedServerProperties extends Settings { + static final Logger LOGGER = LogUtils.getLogger(); + private static final Pattern SHA1 = Pattern.compile("^[a-fA-F0-9]{40}$"); + private static final Splitter COMMA_SPLITTER = Splitter.on(',').trimResults(); ++ public final boolean debug = this.get("debug", false); // CraftBukkit + public final boolean onlineMode = this.get("online-mode", true); + public final boolean preventProxyConnections = this.get("prevent-proxy-connections", false); + public final String serverIp = this.get("server-ip", ""); +@@ -101,9 +108,53 @@ + private final DedicatedServerProperties.WorldDimensionData worldDimensionData; + public final WorldOptions worldOptions; + +- public DedicatedServerProperties(Properties properties) { +- super(properties); +- String string = this.get("level-seed", ""); ++ // CraftBukkit start ++ public DedicatedServerProperties(Properties properties, OptionSet optionset) { ++ super(properties, optionset); ++ // CraftBukkit end ++ this.difficulty = (Difficulty) this.get("difficulty", dispatchNumberOrString(Difficulty::byId, Difficulty::byName), Difficulty::getKey, Difficulty.EASY); ++ this.gamemode = (GameType) this.get("gamemode", dispatchNumberOrString(GameType::byId, GameType::byName), GameType::getName, GameType.SURVIVAL); ++ this.levelName = this.get("level-name", "world"); ++ this.serverPort = this.get("server-port", 25565); ++ this.announcePlayerAchievements = this.getLegacyBoolean("announce-player-achievements"); ++ this.enableQuery = this.get("enable-query", false); ++ this.queryPort = this.get("query.port", 25565); ++ this.enableRcon = this.get("enable-rcon", false); ++ this.rconPort = this.get("rcon.port", 25575); ++ this.rconPassword = this.get("rcon.password", ""); ++ this.hardcore = this.get("hardcore", false); ++ this.allowNether = this.get("allow-nether", true); ++ this.spawnMonsters = this.get("spawn-monsters", true); ++ this.useNativeTransport = this.get("use-native-transport", true); ++ this.enableCommandBlock = this.get("enable-command-block", false); ++ this.spawnProtection = this.get("spawn-protection", 16); ++ this.opPermissionLevel = this.get("op-permission-level", 4); ++ this.functionPermissionLevel = this.get("function-permission-level", 2); ++ this.maxTickTime = this.get("max-tick-time", TimeUnit.MINUTES.toMillis(1L)); ++ this.maxChainedNeighborUpdates = this.get("max-chained-neighbor-updates", 1000000); ++ this.rateLimitPacketsPerSecond = this.get("rate-limit", 0); ++ this.viewDistance = this.get("view-distance", 10); ++ this.simulationDistance = this.get("simulation-distance", 10); ++ this.maxPlayers = this.get("max-players", 20); ++ this.networkCompressionThreshold = this.get("network-compression-threshold", 256); ++ this.broadcastRconToOps = this.get("broadcast-rcon-to-ops", true); ++ this.broadcastConsoleToOps = this.get("broadcast-console-to-ops", true); ++ this.maxWorldSize = this.get("max-world-size", (integer) -> { ++ return Mth.clamp(integer, 1, 29999984); ++ }, 29999984); ++ this.syncChunkWrites = this.get("sync-chunk-writes", true); ++ this.enableJmxMonitoring = this.get("enable-jmx-monitoring", false); ++ this.enableStatus = this.get("enable-status", true); ++ this.hideOnlinePlayers = this.get("hide-online-players", false); ++ this.entityBroadcastRangePercentage = this.get("entity-broadcast-range-percentage", (integer) -> { ++ return Mth.clamp(integer, 10, 1000); ++ }, 100); ++ this.textFilteringConfig = this.get("text-filtering-config", ""); ++ this.playerIdleTimeout = this.getMutable("player-idle-timeout", 0); ++ this.whiteList = this.getMutable("white-list", false); ++ this.enforceSecureProfile = this.get("enforce-secure-profile", true); ++ this.logIPs = this.get("log-ips", true); ++ String s = this.get("level-seed", ""); + boolean flag = this.get("generate-structures", true); + long l = WorldOptions.parseSeed(string).orElse(WorldOptions.randomSeed()); + this.worldOptions = new WorldOptions(l, flag, false); +@@ -125,13 +168,15 @@ + ); + } + +- public static DedicatedServerProperties fromFile(Path path) { +- return new DedicatedServerProperties(loadFromFile(path)); ++ // CraftBukkit start ++ public static DedicatedServerProperties fromFile(Path path, OptionSet optionset) { ++ return new DedicatedServerProperties(loadFromFile(path), optionset); + } + + @Override +- protected DedicatedServerProperties reload(RegistryAccess registryAccess, Properties properties) { +- return new DedicatedServerProperties(properties); ++ protected DedicatedServerProperties reload(RegistryAccess iregistrycustom, Properties properties, OptionSet optionset) { ++ return new DedicatedServerProperties(properties, optionset); ++ // CraftBukkit end + } + + @Nullable diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/dedicated/DedicatedServerSettings.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/dedicated/DedicatedServerSettings.java.patch new file mode 100644 index 0000000000..a79b915d5f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/dedicated/DedicatedServerSettings.java.patch @@ -0,0 +1,26 @@ +--- a/net/minecraft/server/dedicated/DedicatedServerSettings.java ++++ b/net/minecraft/server/dedicated/DedicatedServerSettings.java +@@ -3,13 +3,20 @@ + import java.nio.file.Path; + import java.util.function.UnaryOperator; + ++// CraftBukkit start ++import java.io.File; ++import joptsimple.OptionSet; ++// CraftBukkit end ++ + public class DedicatedServerSettings { + private final Path source; + private DedicatedServerProperties properties; + +- public DedicatedServerSettings(Path source) { +- this.source = source; +- this.properties = DedicatedServerProperties.fromFile(source); ++ // CraftBukkit start ++ public DedicatedServerSettings(OptionSet optionset) { ++ this.source = ((File) optionset.valueOf("config")).toPath(); ++ this.properties = DedicatedServerProperties.fromFile(source, optionset); ++ // CraftBukkit end + } + + public DedicatedServerProperties getProperties() { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/dedicated/Settings.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/dedicated/Settings.java.patch new file mode 100644 index 0000000000..35a501511c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/dedicated/Settings.java.patch @@ -0,0 +1,140 @@ +--- a/net/minecraft/server/dedicated/Settings.java ++++ b/net/minecraft/server/dedicated/Settings.java +@@ -23,16 +22,38 @@ + import net.minecraft.core.RegistryAccess; + import org.slf4j.Logger; + ++import joptsimple.OptionSet; // CraftBukkit ++import net.minecraft.core.RegistryAccess; ++ + public abstract class Settings> { + private static final Logger LOGGER = LogUtils.getLogger(); +- protected final Properties properties; ++ public final Properties properties; ++ // CraftBukkit start ++ private OptionSet options = null; + + public Settings(Properties properties) { + this.properties = properties; + } + ++ private String getOverride(String name, String value) { ++ if ((this.options != null) && (this.options.has(name))) { ++ return String.valueOf(this.options.valueOf(name)); ++ } ++ ++ return value; ++ // CraftBukkit end ++ } ++ + public static Properties loadFromFile(Path path) { + try { ++ // CraftBukkit start - SPIGOT-7465, MC-264979: Don't load if file doesn't exist ++ if (!path.toFile().exists()) { ++ return new Properties(); ++ } ++ // CraftBukkit end ++ Properties properties; ++ Properties properties1; ++ + try { + Properties var13; + try (InputStream inputStream = Files.newInputStream(path)) { +@@ -65,10 +116,33 @@ + } + + public void store(Path path) { +- try (Writer bufferedWriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) { +- this.properties.store(bufferedWriter, "Minecraft server properties"); +- } catch (IOException var7) { +- LOGGER.error("Failed to store properties to file: {}", path); ++ try { ++ // CraftBukkit start - Don't attempt writing to file if it's read only ++ if (path.toFile().exists() && !path.toFile().canWrite()) { ++ return; ++ } ++ // CraftBukkit end ++ BufferedWriter bufferedwriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8); ++ ++ try { ++ this.properties.store(bufferedwriter, "Minecraft server properties"); ++ } catch (Throwable throwable) { ++ if (bufferedwriter != null) { ++ try { ++ bufferedwriter.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; ++ } ++ ++ if (bufferedwriter != null) { ++ bufferedwriter.close(); ++ } ++ } catch (IOException ioexception) { ++ Settings.LOGGER.error("Failed to store properties to file: {}", path); + } + } + +@@ -94,7 +169,7 @@ + + @Nullable + private String getStringRaw(String key) { +- return (String)this.properties.get(key); ++ return (String) getOverride(key, this.properties.getProperty(key)); // CraftBukkit + } + + @Nullable +@@ -109,12 +185,23 @@ + } + + protected V get(String key, Function mapper, Function toString, V value) { +- String stringRaw = this.getStringRaw(key); +- V object = MoreObjects.firstNonNull(stringRaw != null ? mapper.apply(stringRaw) : null, value); +- this.properties.put(key, toString.apply(object)); +- return object; ++ // CraftBukkit start ++ try { ++ return get0(key, mapper, toString, value); ++ } catch (Exception ex) { ++ throw new RuntimeException("Could not load invalidly configured property '" + key + "'", ex); ++ } + } + ++ private V get0(String s, Function function, Function function1, V v0) { ++ // CraftBukkit end ++ String s1 = this.getStringRaw(s); ++ V v1 = MoreObjects.firstNonNull(s1 != null ? function.apply(s1) : null, v0); ++ ++ this.properties.put(s, function1.apply(v1)); ++ return v1; ++ } ++ + protected Settings.MutableValue getMutable(String key, Function mapper, Function toString, V value) { + String stringRaw = this.getStringRaw(key); + V object = MoreObjects.firstNonNull(stringRaw != null ? mapper.apply(stringRaw) : null, value); +@@ -181,7 +271,7 @@ + return map; + } + +- protected abstract T reload(RegistryAccess registryAccess, Properties properties); ++ protected abstract T reload(RegistryAccess iregistrycustom, Properties properties, OptionSet optionset); // CraftBukkit + + public class MutableValue implements Supplier { + private final String key; +@@ -200,9 +290,10 @@ + } + + public T update(RegistryAccess registryAccess, V newValue) { +- Properties map = Settings.this.cloneProperties(); +- map.put(this.key, this.serializer.apply(newValue)); +- return Settings.this.reload(registryAccess, map); ++ Properties properties = Settings.this.cloneProperties(); ++ ++ properties.put(this.key, this.serializer.apply(newValue)); ++ return Settings.this.reload(registryAccess, properties, Settings.this.options); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/gui/MinecraftServerGui.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/gui/MinecraftServerGui.java.patch new file mode 100644 index 0000000000..bdce3205fc --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/gui/MinecraftServerGui.java.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/server/gui/MinecraftServerGui.java ++++ b/net/minecraft/server/gui/MinecraftServerGui.java +@@ -151,6 +166,7 @@ + this.finalizers.forEach(Runnable::run); + } + ++ private static final java.util.regex.Pattern ANSI = java.util.regex.Pattern.compile("\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})*)?[m|K]"); // CraftBukkit + public void print(JTextArea textArea, JScrollPane scrollPane, String line) { + if (!SwingUtilities.isEventDispatchThread()) { + SwingUtilities.invokeLater(() -> this.print(textArea, scrollPane, line)); +@@ -164,8 +182,9 @@ + } + + try { +- document.insertString(document.getLength(), line, null); +- } catch (BadLocationException var8) { ++ document.insertString(document.getLength(), ANSI.matcher(line).replaceAll(""), (AttributeSet) null); // CraftBukkit ++ } catch (BadLocationException badlocationexception) { ++ ; + } + + if (flag) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ChunkHolder.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ChunkHolder.java.patch new file mode 100644 index 0000000000..81d8e68f87 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ChunkHolder.java.patch @@ -0,0 +1,153 @@ +--- a/net/minecraft/server/level/ChunkHolder.java ++++ b/net/minecraft/server/level/ChunkHolder.java +@@ -37,6 +36,10 @@ + import net.minecraft.world.level.chunk.ProtoChunk; + import net.minecraft.world.level.lighting.LevelLightEngine; + ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++// CraftBukkit end ++ + public class ChunkHolder { + public static final Either UNLOADED_CHUNK = Either.right(ChunkHolder.ChunkLoadingFailure.UNLOADED); + public static final CompletableFuture> UNLOADED_CHUNK_FUTURE = CompletableFuture.completedFuture( +@@ -93,14 +94,17 @@ + this.changedBlocksPerSection = new ShortSet[levelHeightAccessor.getSectionsCount()]; + } + +- public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus chunkStatus) { +- CompletableFuture> completableFuture = this.futures.get(chunkStatus.getIndex()); +- return completableFuture == null ? UNLOADED_CHUNK_FUTURE : completableFuture; ++ // CraftBukkit start ++ public LevelChunk getFullChunkNow() { ++ // Note: We use the oldTicketLevel for isLoaded checks. ++ if (!ChunkLevel.fullStatus(this.oldTicketLevel).isOrAfter(FullChunkStatus.FULL)) return null; ++ return this.getFullChunkNowUnchecked(); + } + + public CompletableFuture> getFutureIfPresent(ChunkStatus chunkStatus) { + return ChunkLevel.generationStatus(this.ticketLevel).isOrAfter(chunkStatus) ? this.getFutureIfPresentUnchecked(chunkStatus) : UNLOADED_CHUNK_FUTURE; + } ++ // CraftBukkit end + + public CompletableFuture> getTickingChunkFuture() { + return this.tickingChunkFuture; +@@ -171,10 +192,13 @@ + } + + public void blockChanged(BlockPos pos) { +- LevelChunk tickingChunk = this.getTickingChunk(); +- if (tickingChunk != null) { +- int sectionIndex = this.levelHeightAccessor.getSectionIndex(pos.getY()); +- if (this.changedBlocksPerSection[sectionIndex] == null) { ++ LevelChunk chunk = this.getTickingChunk(); ++ ++ if (chunk != null) { ++ int i = this.levelHeightAccessor.getSectionIndex(pos.getY()); ++ ++ if (i < 0 || i >= this.changedBlocksPerSection.length) return; // CraftBukkit - SPIGOT-6086, SPIGOT-6296 ++ if (this.changedBlocksPerSection[i] == null) { + this.hasChangedSections = true; + this.changedBlocksPerSection[sectionIndex] = new ShortOpenHashSet(); + } +@@ -238,14 +272,16 @@ + this.broadcast(players, new ClientboundBlockUpdatePacket(blockPos, blockState)); + this.broadcastBlockEntityIfNeeded(players, level, blockPos, blockState); + } else { +- LevelChunkSection section = chunk.getSection(i); +- ClientboundSectionBlocksUpdatePacket clientboundSectionBlocksUpdatePacket = new ClientboundSectionBlocksUpdatePacket( +- sectionPos, set, section +- ); +- this.broadcast(players, clientboundSectionBlocksUpdatePacket); +- clientboundSectionBlocksUpdatePacket.runUpdates( +- (blockPos1, blockState1) -> this.broadcastBlockEntityIfNeeded(players, level, blockPos1, blockState1) +- ); ++ LevelChunkSection chunksection = chunk.getSection(i); ++ ClientboundSectionBlocksUpdatePacket packetplayoutmultiblockchange = new ClientboundSectionBlocksUpdatePacket(sectionposition, shortset, chunksection); ++ ++ this.broadcast(list, packetplayoutmultiblockchange); ++ // CraftBukkit start ++ List finalList = list; ++ packetplayoutmultiblockchange.runUpdates((blockposition1, iblockdata1) -> { ++ this.broadcastBlockEntityIfNeeded(finalList, world, blockposition1, iblockdata1); ++ // CraftBukkit end ++ }); + } + } + } +@@ -368,15 +427,39 @@ + } + + protected void updateFutures(ChunkMap chunkMap, Executor executor) { +- ChunkStatus chunkStatus = ChunkLevel.generationStatus(this.oldTicketLevel); +- ChunkStatus chunkStatus1 = ChunkLevel.generationStatus(this.ticketLevel); +- boolean isLoaded = ChunkLevel.isLoaded(this.oldTicketLevel); +- boolean isLoaded1 = ChunkLevel.isLoaded(this.ticketLevel); +- FullChunkStatus fullChunkStatus = ChunkLevel.fullStatus(this.oldTicketLevel); +- FullChunkStatus fullChunkStatus1 = ChunkLevel.fullStatus(this.ticketLevel); +- if (isLoaded) { +- Either either = Either.right(new ChunkHolder.ChunkLoadingFailure() { +- @Override ++ ChunkStatus chunkstatus = ChunkLevel.generationStatus(this.oldTicketLevel); ++ ChunkStatus chunkstatus1 = ChunkLevel.generationStatus(this.ticketLevel); ++ boolean flag = ChunkLevel.isLoaded(this.oldTicketLevel); ++ boolean flag1 = ChunkLevel.isLoaded(this.ticketLevel); ++ FullChunkStatus fullchunkstatus = ChunkLevel.fullStatus(this.oldTicketLevel); ++ FullChunkStatus fullchunkstatus1 = ChunkLevel.fullStatus(this.ticketLevel); ++ // CraftBukkit start ++ // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins. ++ if (fullchunkstatus.isOrAfter(FullChunkStatus.FULL) && !fullchunkstatus1.isOrAfter(FullChunkStatus.FULL)) { ++ this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { ++ LevelChunk chunk = (LevelChunk)either.left().orElse(null); ++ if (chunk != null) { ++ chunkMap.callbackExecutor.execute(() -> { ++ // Minecraft will apply the chunks tick lists to the world once the chunk got loaded, and then store the tick ++ // lists again inside the chunk once the chunk becomes inaccessible and set the chunk's needsSaving flag. ++ // These actions may however happen deferred, so we manually set the needsSaving flag already here. ++ chunk.setUnsaved(true); ++ chunk.unloadCallback(); ++ }); ++ } ++ }).exceptionally((throwable) -> { ++ // ensure exceptions are printed, by default this is not the case ++ MinecraftServer.LOGGER.error("Failed to schedule unload callback for chunk " + ChunkHolder.this.pos, throwable); ++ return null; ++ }); ++ ++ // Run callback right away if the future was already done ++ chunkMap.callbackExecutor.run(); ++ } ++ // CraftBukkit end ++ ++ if (flag) { ++ Either either = Either.right(new ChunkHolder.Failure() { + public String toString() { + return "Unloaded ticket level " + ChunkHolder.this.pos; + } +@@ -440,6 +527,26 @@ + + this.onLevelChange.onLevelChange(this.pos, this::getQueueLevel, this.ticketLevel, this::setQueueLevel); + this.oldTicketLevel = this.ticketLevel; ++ // CraftBukkit start ++ // ChunkLoadEvent: Called after the chunk is loaded: isChunkLoaded returns true and chunk is ready to be modified by plugins. ++ if (!fullchunkstatus.isOrAfter(FullChunkStatus.FULL) && fullchunkstatus1.isOrAfter(FullChunkStatus.FULL)) { ++ this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { ++ LevelChunk chunk = (LevelChunk)either.left().orElse(null); ++ if (chunk != null) { ++ chunkMap.callbackExecutor.execute(() -> { ++ chunk.loadCallback(); ++ }); ++ } ++ }).exceptionally((throwable) -> { ++ // ensure exceptions are printed, by default this is not the case ++ MinecraftServer.LOGGER.error("Failed to schedule load callback for chunk " + ChunkHolder.this.pos, throwable); ++ return null; ++ }); ++ ++ // Run callback right away if the future was already done ++ chunkMap.callbackExecutor.run(); ++ } ++ // CraftBukkit end + } + + public boolean wasAccessibleSinceLastSave() { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ChunkMap.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ChunkMap.java.patch new file mode 100644 index 0000000000..663459c926 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ChunkMap.java.patch @@ -0,0 +1,171 @@ +--- a/net/minecraft/server/level/ChunkMap.java ++++ b/net/minecraft/server/level/ChunkMap.java +@@ -95,6 +100,9 @@ + import net.minecraft.world.phys.Vec3; + import org.apache.commons.lang3.mutable.MutableBoolean; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.generator.CustomChunkGenerator; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider { + private static final byte CHUNK_TYPE_REPLACEABLE = -1; +@@ -137,31 +146,46 @@ + private final Queue unloadQueue = Queues.newConcurrentLinkedQueue(); + private int serverViewDistance; + +- public ChunkMap( +- ServerLevel level, +- LevelStorageSource.LevelStorageAccess levelStorageAccess, +- DataFixer fixerUpper, +- StructureTemplateManager structureManager, +- Executor dispatcher, +- BlockableEventLoop mainThreadExecutor, +- LightChunkGetter lightChunk, +- ChunkGenerator generator, +- ChunkProgressListener progressListener, +- ChunkStatusUpdateListener chunkStatusListener, +- Supplier overworldDataStorage, +- int viewDistance, +- boolean sync +- ) { ++ // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() ++ public final CallbackExecutor callbackExecutor = new CallbackExecutor(); ++ public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable { ++ ++ private final java.util.Queue queue = new java.util.ArrayDeque<>(); ++ ++ @Override ++ public void execute(Runnable runnable) { ++ queue.add(runnable); ++ } ++ ++ @Override ++ public void run() { ++ Runnable task; ++ while ((task = queue.poll()) != null) { ++ task.run(); ++ } ++ } ++ }; ++ // CraftBukkit end ++ ++ public ChunkMap(ServerLevel level, LevelStorageSource.LevelStorageAccess levelStorageAccess, DataFixer fixerUpper, StructureTemplateManager structureManager, Executor dispatcher, BlockableEventLoop mainThreadExecutor, LightChunkGetter lightChunk, ChunkGenerator generator, ChunkProgressListener progressListener, ChunkStatusUpdateListener chunkStatusListener, Supplier overworldDataStorage, int viewDistance, boolean sync) { + super(levelStorageAccess.getDimensionPath(level.dimension()).resolve("region"), fixerUpper, sync); + this.structureTemplateManager = structureManager; + Path dimensionPath = levelStorageAccess.getDimensionPath(level.dimension()); + this.storageName = dimensionPath.getFileName().toString(); + this.level = level; + this.generator = generator; +- RegistryAccess registryAccess = level.registryAccess(); +- long seed = level.getSeed(); +- if (generator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) { +- this.randomState = RandomState.create(noiseBasedChunkGenerator.generatorSettings().value(), registryAccess.lookupOrThrow(Registries.NOISE), seed); ++ // CraftBukkit start - SPIGOT-7051: It's a rigged game! Use delegate for random state creation, otherwise it is not so random. ++ if (generator instanceof CustomChunkGenerator) { ++ generator = ((CustomChunkGenerator) generator).getDelegate(); ++ } ++ // CraftBukkit end ++ RegistryAccess iregistrycustom = level.registryAccess(); ++ long j = level.getSeed(); ++ ++ if (generator instanceof NoiseBasedChunkGenerator) { ++ NoiseBasedChunkGenerator chunkgeneratorabstract = (NoiseBasedChunkGenerator) generator; ++ ++ this.randomState = RandomState.create((NoiseGeneratorSettings) chunkgeneratorabstract.generatorSettings().value(), (HolderGetter) iregistrycustom.lookupOrThrow(Registries.NOISE), j); + } else { + this.randomState = RandomState.create(NoiseGeneratorSettings.dummy(), registryAccess.lookupOrThrow(Registries.NOISE), seed); + } +@@ -320,7 +364,11 @@ + List list3 = Lists.newArrayList(); + int i4 = 0; + +- for (final Either either : list2) { ++ for (Iterator iterator = list2.iterator(); iterator.hasNext(); ++cnt) { ++ final int l1 = cnt; ++ // CraftBukkit end ++ final Either either = (Either) iterator.next(); ++ + if (either == null) { + throw this.debugFuturesAndCreateReportedException(new IllegalStateException("At least one of the chunk futures were null"), "n/a"); + } +@@ -713,7 +780,21 @@ + + private static void postLoadProtoChunk(ServerLevel level, List tags) { + if (!tags.isEmpty()) { +- level.addWorldGenChunkEntities(EntityType.loadEntitiesRecursive(tags, level)); ++ // CraftBukkit start - these are spawned serialized (DefinedStructure) and we don't call an add event below at the moment due to ordering complexities ++ level.addWorldGenChunkEntities(EntityType.loadEntitiesRecursive(tags, level).filter((entity) -> { ++ boolean needsRemoval = false; ++ net.minecraft.server.dedicated.DedicatedServer server = level.getCraftServer().getServer(); ++ if (!server.areNpcsEnabled() && entity instanceof net.minecraft.world.entity.npc.NPC) { ++ entity.discard(); ++ needsRemoval = true; ++ } ++ if (!server.isSpawningAnimals() && (entity instanceof net.minecraft.world.entity.animal.Animal || entity instanceof net.minecraft.world.entity.animal.WaterAnimal)) { ++ entity.discard(); ++ needsRemoval = true; ++ } ++ return !needsRemoval; ++ })); ++ // CraftBukkit end + } + } + +@@ -986,11 +1092,15 @@ + } + + private CompletableFuture> readChunk(ChunkPos pos) { +- return this.read(pos).thenApplyAsync(optional -> optional.map(this::upgradeChunkTag), Util.backgroundExecutor()); ++ return this.read(pos).thenApplyAsync((optional) -> { ++ return optional.map((nbttagcompound) -> upgradeChunkTag(nbttagcompound, pos)); // CraftBukkit ++ }, Util.backgroundExecutor()); + } + +- private CompoundTag upgradeChunkTag(CompoundTag tag) { +- return this.upgradeChunkTag(this.level.dimension(), this.overworldDataStorage, tag, this.generator.getTypeNameForDataFixer()); ++ // CraftBukkit start ++ private CompoundTag upgradeChunkTag(CompoundTag nbttagcompound, ChunkPos chunkcoordintpair) { ++ return this.upgradeChunkTag(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, this.generator.getTypeNameForDataFixer(), chunkcoordintpair, level); ++ // CraftBukkit end + } + + boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkPos) { +@@ -1306,8 +1508,8 @@ + SectionPos lastSectionPos; + private final Set seenBy = Sets.newIdentityHashSet(); + +- public TrackedEntity(Entity entity, int range, int updateInterval, boolean trackDelta) { +- this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast); ++ public TrackedEntity(Entity entity, int i, int j, boolean flag) { ++ this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, seenBy); // CraftBukkit + this.entity = entity; + this.range = range; + this.lastSectionPos = SectionPos.of(entity); +@@ -1350,14 +1562,18 @@ + + public void updatePlayer(ServerPlayer player) { + if (player != this.entity) { +- Vec3 vec3 = player.position().subtract(this.entity.position()); +- int playerViewDistance = ChunkMap.this.getPlayerViewDistance(player); +- double d = (double)Math.min(this.getEffectiveRange(), playerViewDistance * 16); +- double d1 = vec3.x * vec3.x + vec3.z * vec3.z; +- double d2 = d * d; +- boolean flag = d1 <= d2 +- && this.entity.broadcastToPlayer(player) +- && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z); ++ Vec3 vec3d = player.position().subtract(this.entity.position()); ++ int i = ChunkMap.this.getPlayerViewDistance(player); ++ double d0 = (double) Math.min(this.getEffectiveRange(), i * 16); ++ double d1 = vec3d.x * vec3d.x + vec3d.z * vec3d.z; ++ double d2 = d0 * d0; ++ boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(player) && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z); ++ ++ // CraftBukkit start - respect vanish API ++ if (!player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { ++ flag = false; ++ } ++ // CraftBukkit end + if (flag) { + if (this.seenBy.add(player.connection)) { + this.serverEntity.addPairing(player); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/DistanceManager.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/DistanceManager.java.patch new file mode 100644 index 0000000000..064463f5c7 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/DistanceManager.java.patch @@ -0,0 +1,173 @@ +--- a/net/minecraft/server/level/DistanceManager.java ++++ b/net/minecraft/server/level/DistanceManager.java +@@ -114,8 +122,25 @@ + } + + if (!this.chunksToUpdateFutures.isEmpty()) { +- this.chunksToUpdateFutures.forEach(chunkHolder -> chunkHolder.updateFutures(chunkManager, this.mainThreadExecutor)); +- this.chunksToUpdateFutures.clear(); ++ // CraftBukkit start ++ // Iterate pending chunk updates with protection against concurrent modification exceptions ++ java.util.Iterator iter = this.chunksToUpdateFutures.iterator(); ++ int expectedSize = this.chunksToUpdateFutures.size(); ++ do { ++ ChunkHolder playerchunk = iter.next(); ++ iter.remove(); ++ expectedSize--; ++ ++ playerchunk.updateFutures(chunkManager, this.mainThreadExecutor); ++ ++ // Reset iterator if set was modified using add() ++ if (this.chunksToUpdateFutures.size() != expectedSize) { ++ expectedSize = this.chunksToUpdateFutures.size(); ++ iter = this.chunksToUpdateFutures.iterator(); ++ } ++ } while (iter.hasNext()); ++ // CraftBukkit end ++ + return true; + } else { + if (!this.ticketsToRelease.isEmpty()) { +@@ -146,26 +176,33 @@ + } + } + +- void addTicket(long chunkPos, Ticket ticket) { +- SortedArraySet> tickets = this.getTickets(chunkPos); +- int ticketLevelAt = getTicketLevelAt(tickets); +- Ticket ticket1 = tickets.addOrGet(ticket); ++ boolean addTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean ++ SortedArraySet> arraysetsorted = this.getTickets(i); ++ int j = getTicketLevelAt(arraysetsorted); ++ Ticket ticket1 = (Ticket) arraysetsorted.addOrGet(ticket); ++ + ticket1.setCreatedTick(this.ticketTickCounter); + if (ticket.getTicketLevel() < ticketLevelAt) { + this.ticketTracker.update(chunkPos, ticket.getTicketLevel(), true); + } ++ ++ return ticket == ticket1; // CraftBukkit + } + +- void removeTicket(long chunkPos, Ticket ticket) { +- SortedArraySet> tickets = this.getTickets(chunkPos); +- if (tickets.remove(ticket)) { ++ boolean removeTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean ++ SortedArraySet> arraysetsorted = this.getTickets(i); ++ ++ boolean removed = false; // CraftBukkit ++ if (arraysetsorted.remove(ticket)) { ++ removed = true; // CraftBukkit + } + + if (tickets.isEmpty()) { + this.tickets.remove(chunkPos); + } + +- this.ticketTracker.update(chunkPos, getTicketLevelAt(tickets), false); ++ this.ticketTracker.update(i, getTicketLevelAt(arraysetsorted), false); ++ return removed; // CraftBukkit + } + + public void addTicket(TicketType type, ChunkPos pos, int level, T value) { +@@ -178,19 +216,35 @@ + } + + public void addRegionTicket(TicketType type, ChunkPos pos, int distance, T value) { +- Ticket ticket = new Ticket<>(type, ChunkLevel.byStatus(FullChunkStatus.FULL) - distance, value); +- long l = pos.toLong(); +- this.addTicket(l, ticket); +- this.tickingTicketsTracker.addTicket(l, ticket); ++ // CraftBukkit start ++ addRegionTicketAtDistance(type, pos, distance, value); + } + ++ public boolean addRegionTicketAtDistance(TicketType tickettype, ChunkPos chunkcoordintpair, int i, T t0) { ++ // CraftBukkit end ++ Ticket ticket = new Ticket<>(tickettype, ChunkLevel.byStatus(FullChunkStatus.FULL) - i, t0); ++ long j = chunkcoordintpair.toLong(); ++ ++ boolean added = this.addTicket(j, ticket); // CraftBukkit ++ this.tickingTicketsTracker.addTicket(j, ticket); ++ return added; // CraftBukkit ++ } ++ + public void removeRegionTicket(TicketType type, ChunkPos pos, int distance, T value) { +- Ticket ticket = new Ticket<>(type, ChunkLevel.byStatus(FullChunkStatus.FULL) - distance, value); +- long l = pos.toLong(); +- this.removeTicket(l, ticket); +- this.tickingTicketsTracker.removeTicket(l, ticket); ++ // CraftBukkit start ++ removeRegionTicketAtDistance(type, pos, distance, value); + } + ++ public boolean removeRegionTicketAtDistance(TicketType tickettype, ChunkPos chunkcoordintpair, int i, T t0) { ++ // CraftBukkit end ++ Ticket ticket = new Ticket<>(tickettype, ChunkLevel.byStatus(FullChunkStatus.FULL) - i, t0); ++ long j = chunkcoordintpair.toLong(); ++ ++ boolean removed = this.removeTicket(j, ticket); // CraftBukkit ++ this.tickingTicketsTracker.removeTicket(j, ticket); ++ return removed; // CraftBukkit ++ } ++ + private SortedArraySet> getTickets(long chunkPos) { + return this.tickets.computeIfAbsent(chunkPos, l -> SortedArraySet.create(4)); + } +@@ -217,15 +278,17 @@ + } + + public void removePlayer(SectionPos sectionPos, ServerPlayer player) { +- ChunkPos chunkPos = sectionPos.chunk(); +- long l = chunkPos.toLong(); +- ObjectSet set = this.playersPerChunk.get(l); +- set.remove(player); +- if (set.isEmpty()) { +- this.playersPerChunk.remove(l); +- this.naturalSpawnChunkCounter.update(l, Integer.MAX_VALUE, false); +- this.playerTicketManager.update(l, Integer.MAX_VALUE, false); +- this.tickingTicketsTracker.removeTicket(TicketType.PLAYER, chunkPos, this.getPlayerTicketLevel(), chunkPos); ++ ChunkPos chunkcoordintpair = sectionPos.chunk(); ++ long i = chunkcoordintpair.toLong(); ++ ObjectSet objectset = (ObjectSet) this.playersPerChunk.get(i); ++ if (objectset == null) return; // CraftBukkit - SPIGOT-6208 ++ ++ objectset.remove(player); ++ if (objectset.isEmpty()) { ++ this.playersPerChunk.remove(i); ++ this.naturalSpawnChunkCounter.update(i, Integer.MAX_VALUE, false); ++ this.playerTicketManager.update(i, Integer.MAX_VALUE, false); ++ this.tickingTicketsTracker.removeTicket(TicketType.PLAYER, chunkcoordintpair, this.getPlayerTicketLevel(), chunkcoordintpair); + } + } + +@@ -324,7 +411,28 @@ + return !this.tickets.isEmpty(); + } + +- class ChunkTicketTracker extends ChunkTracker { ++ // CraftBukkit start ++ public void removeAllTicketsFor(TicketType ticketType, int ticketLevel, T ticketIdentifier) { ++ Ticket target = new Ticket<>(ticketType, ticketLevel, ticketIdentifier); ++ ++ for (java.util.Iterator>>> iterator = this.tickets.long2ObjectEntrySet().fastIterator(); iterator.hasNext();) { ++ Entry>> entry = iterator.next(); ++ SortedArraySet> tickets = entry.getValue(); ++ if (tickets.remove(target)) { ++ // copied from removeTicket ++ this.ticketTracker.update(entry.getLongKey(), getTicketLevelAt(tickets), false); ++ ++ // can't use entry after it's removed ++ if (tickets.isEmpty()) { ++ iterator.remove(); ++ } ++ } ++ } ++ } ++ // CraftBukkit end ++ ++ private class ChunkTicketTracker extends ChunkTracker { ++ + private static final int MAX_LEVEL = ChunkLevel.MAX_LEVEL + 1; + + public ChunkTicketTracker() { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ServerChunkCache.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ServerChunkCache.java.patch new file mode 100644 index 0000000000..7d99b3540f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ServerChunkCache.java.patch @@ -0,0 +1,167 @@ +--- a/net/minecraft/server/level/ServerChunkCache.java ++++ b/net/minecraft/server/level/ServerChunkCache.java +@@ -107,6 +83,16 @@ + this.clearCache(); + } + ++ // CraftBukkit start - properly implement isChunkLoaded ++ public boolean isChunkLoaded(int chunkX, int chunkZ) { ++ ChunkHolder chunk = this.chunkMap.getUpdatingChunkIfPresent(ChunkPos.asLong(chunkX, chunkZ)); ++ if (chunk == null) { ++ return false; ++ } ++ return chunk.getFullChunkNow() != null; ++ } ++ // CraftBukkit end ++ + @Override + public ThreadedLevelLightEngine getLightEngine() { + return this.lightEngine; +@@ -143,11 +129,16 @@ + profiler.incrementCounter("getChunk"); + long _long = ChunkPos.asLong(chunkX, chunkZ); + +- for (int i = 0; i < 4; i++) { +- if (_long == this.lastChunkPos[i] && requiredStatus == this.lastChunkStatus[i]) { +- ChunkAccess chunkAccess = this.lastChunk[i]; +- if (chunkAccess != null || !load) { +- return chunkAccess; ++ gameprofilerfiller.incrementCounter("getChunk"); ++ long k = ChunkPos.asLong(chunkX, chunkZ); ++ ++ ChunkAccess ichunkaccess; ++ ++ for (int l = 0; l < 4; ++l) { ++ if (k == this.lastChunkPos[l] && requiredStatus == this.lastChunkStatus[l]) { ++ ichunkaccess = this.lastChunk[l]; ++ if (ichunkaccess != null) { // CraftBukkit - the chunk can become accessible in the meantime TODO for non-null chunks it might also make sense to check that the chunk's state hasn't changed in the meantime ++ return ichunkaccess; + } + } + } +@@ -229,18 +232,26 @@ + return chunkFutureMainThread; + } + +- private CompletableFuture> getChunkFutureMainThread( +- int x, int y, ChunkStatus chunkStatus, boolean load +- ) { +- ChunkPos chunkPos = new ChunkPos(x, y); +- long l = chunkPos.toLong(); +- int i = ChunkLevel.byStatus(chunkStatus); +- ChunkHolder visibleChunkIfPresent = this.getVisibleChunkIfPresent(l); +- if (load) { +- this.distanceManager.addTicket(TicketType.UNKNOWN, chunkPos, i, chunkPos); +- if (this.chunkAbsent(visibleChunkIfPresent, i)) { +- ProfilerFiller profiler = this.level.getProfiler(); +- profiler.push("chunkLoad"); ++ private CompletableFuture> getChunkFutureMainThread(int x, int y, ChunkStatus chunkStatus, boolean load) { ++ ChunkPos chunkcoordintpair = new ChunkPos(x, y); ++ long k = chunkcoordintpair.toLong(); ++ int l = ChunkLevel.byStatus(chunkStatus); ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(k); ++ ++ // CraftBukkit start - don't add new ticket for currently unloading chunk ++ boolean currentlyUnloading = false; ++ if (playerchunk != null) { ++ FullChunkStatus oldChunkState = ChunkLevel.fullStatus(playerchunk.oldTicketLevel); ++ FullChunkStatus currentChunkState = ChunkLevel.fullStatus(playerchunk.getTicketLevel()); ++ currentlyUnloading = (oldChunkState.isOrAfter(FullChunkStatus.FULL) && !currentChunkState.isOrAfter(FullChunkStatus.FULL)); ++ } ++ if (load && !currentlyUnloading) { ++ // CraftBukkit end ++ this.distanceManager.addTicket(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); ++ if (this.chunkAbsent(playerchunk, l)) { ++ ProfilerFiller gameprofilerfiller = this.level.getProfiler(); ++ ++ gameprofilerfiller.push("chunkLoad"); + this.runDistanceManagerUpdates(); + visibleChunkIfPresent = this.getVisibleChunkIfPresent(l); + profiler.pop(); +@@ -256,7 +265,7 @@ + } + + private boolean chunkAbsent(@Nullable ChunkHolder chunkHolder, int status) { +- return chunkHolder == null || chunkHolder.getTicketLevel() > status; ++ return chunkHolder == null || chunkHolder.oldTicketLevel > status; // CraftBukkit using oldTicketLevel for isLoaded checks + } + + @Override +@@ -331,11 +346,31 @@ + + @Override + public void close() throws IOException { +- this.save(true); ++ // CraftBukkit start ++ close(true); ++ } ++ ++ public void close(boolean save) throws IOException { ++ if (save) { ++ this.save(true); ++ } ++ // CraftBukkit end + this.lightEngine.close(); + this.chunkMap.close(); + } + ++ // CraftBukkit start - modelled on below ++ public void purgeUnload() { ++ this.level.getProfiler().push("purge"); ++ this.distanceManager.purgeStaleTickets(); ++ this.runDistanceManagerUpdates(); ++ this.level.getProfiler().popPush("unload"); ++ this.chunkMap.tick(() -> true); ++ this.level.getProfiler().pop(); ++ this.clearCache(); ++ } ++ // CraftBukkit end ++ + @Override + public void tick(BooleanSupplier hasTimeLeft, boolean tickChunks) { + this.level.getProfiler().push("purge"); +@@ -371,17 +411,18 @@ + } + + if (this.level.getServer().tickRateManager().runsNormally()) { +- profiler.popPush("naturalSpawnCount"); +- int naturalSpawnChunkCount = this.distanceManager.getNaturalSpawnChunkCount(); +- NaturalSpawner.SpawnState spawnState = NaturalSpawner.createState( +- naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap) +- ); +- this.lastSpawnState = spawnState; +- profiler.popPush("spawnAndTick"); +- boolean _boolean = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING); ++ gameprofilerfiller.popPush("naturalSpawnCount"); ++ int k = this.distanceManager.getNaturalSpawnChunkCount(); ++ NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(k, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap)); ++ ++ this.lastSpawnState = spawnercreature_d; ++ gameprofilerfiller.popPush("spawnAndTick"); ++ boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit ++ + Util.shuffle(list, this.level.random); +- int _int = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); +- boolean flag = this.level.getLevelData().getGameTime() % 400L == 0L; ++ int l = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); ++ boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit ++ Iterator iterator1 = list.iterator(); + + for (ServerChunkCache.ChunkAndHolder chunkAndHolder : list) { + LevelChunk levelChunk = chunkAndHolder.chunk; +@@ -574,6 +624,7 @@ + } + + @Override ++ // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task + public boolean pollTask() { + if (ServerChunkCache.this.runDistanceManagerUpdates()) { + return true; +@@ -582,5 +636,7 @@ + return super.pollTask(); + } + } ++ // CraftBukkit end ++ } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ServerEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ServerEntity.java.patch new file mode 100644 index 0000000000..dbe60b2aa8 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ServerEntity.java.patch @@ -0,0 +1,199 @@ +--- a/net/minecraft/server/level/ServerEntity.java ++++ b/net/minecraft/server/level/ServerEntity.java +@@ -40,6 +41,13 @@ + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.server.network.ServerPlayerConnection; ++import net.minecraft.util.Mth; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerVelocityEvent; ++// CraftBukkit end ++ + public class ServerEntity { + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int TOLERANCE_LEVEL_ROTATION = 1; +@@ -63,10 +72,16 @@ + private boolean wasOnGround; + @Nullable + private List> trackedDataValues; ++ // CraftBukkit start ++ private final Set trackedPlayers; + +- public ServerEntity(ServerLevel level, Entity entity, int updateInterval, boolean trackDelta, Consumer> broadcast) { +- this.level = level; +- this.broadcast = broadcast; ++ public ServerEntity(ServerLevel worldserver, Entity entity, int i, boolean flag, Consumer> consumer, Set trackedPlayers) { ++ this.trackedPlayers = trackedPlayers; ++ // CraftBukkit end ++ this.ap = Vec3.ZERO; ++ this.lastPassengers = Collections.emptyList(); ++ this.level = worldserver; ++ this.broadcast = consumer; + this.entity = entity; + this.updateInterval = updateInterval; + this.trackDelta = trackDelta; +@@ -79,32 +94,45 @@ + } + + public void sendChanges() { +- List passengers = this.entity.getPassengers(); +- if (!passengers.equals(this.lastPassengers)) { +- this.broadcast.accept(new ClientboundSetPassengersPacket(this.entity)); +- removedPassengers(passengers, this.lastPassengers) +- .forEach( +- entity -> { +- if (entity instanceof ServerPlayer serverPlayer1) { +- serverPlayer1.connection +- .teleport(serverPlayer1.getX(), serverPlayer1.getY(), serverPlayer1.getZ(), serverPlayer1.getYRot(), serverPlayer1.getXRot()); +- } +- } +- ); +- this.lastPassengers = passengers; ++ List list = this.entity.getPassengers(); ++ ++ if (!list.equals(this.lastPassengers)) { ++ this.broadcastAndSend(new ClientboundSetPassengersPacket(this.entity)); // CraftBukkit ++ removedPassengers(list, this.lastPassengers).forEach((entity) -> { ++ if (entity instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entity; ++ ++ entityplayer.connection.teleport(entityplayer.getX(), entityplayer.getY(), entityplayer.getZ(), entityplayer.getYRot(), entityplayer.getXRot()); ++ } ++ ++ }); ++ this.lastPassengers = list; + } + +- if (this.entity instanceof ItemFrame itemFrame && this.tickCount % 10 == 0) { +- ItemStack item = itemFrame.getItem(); +- if (item.getItem() instanceof MapItem) { +- Integer mapId = MapItem.getMapId(item); +- MapItemSavedData savedData = MapItem.getSavedData(mapId, this.level); +- if (savedData != null) { +- for (ServerPlayer serverPlayer : this.level.players()) { +- savedData.tickCarriedBy(serverPlayer, item); +- Packet updatePacket = savedData.getUpdatePacket(mapId, serverPlayer); +- if (updatePacket != null) { +- serverPlayer.connection.send(updatePacket); ++ Entity entity = this.entity; ++ ++ if (entity instanceof ItemFrame) { ++ ItemFrame entityitemframe = (ItemFrame) entity; ++ ++ if (true || this.tickCount % 10 == 0) { // CraftBukkit - Moved below, should always enter this block ++ ItemStack itemstack = entityitemframe.getItem(); ++ ++ if (this.tickCount % 10 == 0 && itemstack.getItem() instanceof MapItem) { // CraftBukkit - Moved this.tickCounter % 10 logic here so item frames do not enter the other blocks ++ Integer integer = MapItem.getMapId(itemstack); ++ MapItemSavedData worldmap = MapItem.getSavedData(integer, this.level); ++ ++ if (worldmap != null) { ++ Iterator iterator = this.trackedPlayers.iterator(); // CraftBukkit ++ ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = iterator.next().getPlayer(); // CraftBukkit ++ ++ worldmap.tickCarriedBy(entityplayer, itemstack); ++ Packet packet = worldmap.getUpdatePacket(integer, entityplayer); ++ ++ if (packet != null) { ++ entityplayer.connection.send(packet); ++ } + } + } + } +@@ -206,7 +238,27 @@ + + this.tickCount++; + if (this.entity.hurtMarked) { +- this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity)); ++ // CraftBukkit start - Create PlayerVelocity event ++ boolean cancelled = false; ++ ++ if (this.entity instanceof ServerPlayer) { ++ Player player = (Player) this.entity.getBukkitEntity(); ++ org.bukkit.util.Vector velocity = player.getVelocity(); ++ ++ PlayerVelocityEvent event = new PlayerVelocityEvent(player, velocity.clone()); ++ this.entity.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ cancelled = true; ++ } else if (!velocity.equals(event.getVelocity())) { ++ player.setVelocity(event.getVelocity()); ++ } ++ } ++ ++ if (!cancelled) { ++ this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity)); ++ } ++ // CraftBukkit end + this.entity.hurtMarked = false; + } + } +@@ -229,7 +286,10 @@ + + public void sendPairingData(ServerPlayer player, Consumer> consumer) { + if (this.entity.isRemoved()) { +- LOGGER.warn("Fetching packet for removed entity {}", this.entity); ++ // CraftBukkit start - Remove useless error spam, just return ++ // EntityTrackerEntry.LOGGER.warn("Fetching packet for removed entity {}", this.entity); ++ return; ++ // CraftBukkit end + } + + Packet addEntityPacket = this.entity.getAddEntityPacket(); +@@ -241,10 +303,13 @@ + + boolean flag = this.trackDelta; + if (this.entity instanceof LivingEntity) { +- Collection syncableAttributes = ((LivingEntity)this.entity).getAttributes().getSyncableAttributes(); +- if (!syncableAttributes.isEmpty()) { +- consumer.accept(new ClientboundUpdateAttributesPacket(this.entity.getId(), syncableAttributes)); ++ Collection collection = ((LivingEntity) this.entity).getAttributes().getSyncableAttributes(); ++ ++ // CraftBukkit start - If sending own attributes send scaled health instead of current maximum health ++ if (this.entity.getId() == player.getId()) { ++ ((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(collection, false); + } ++ // CraftBukkit end + + if (((LivingEntity)this.entity).isFallFlying()) { + flag = true; +@@ -269,8 +342,15 @@ + if (!list.isEmpty()) { + consumer.accept(new ClientboundSetEquipmentPacket(this.entity.getId(), list)); + } ++ ((LivingEntity) this.entity).detectEquipmentUpdatesPublic(); // CraftBukkit - SPIGOT-3789: sync again immediately after sending + } + ++ // CraftBukkit start - MC-109346: Fix for nonsensical head yaw ++ if (this.entity instanceof ServerPlayer) { ++ consumer.accept(new ClientboundRotateHeadPacket(this.entity, (byte) Mth.floor(this.entity.getYHeadRot() * 256.0F / 360.0F))); ++ } ++ // CraftBukkit end ++ + if (!this.entity.getPassengers().isEmpty()) { + consumer.accept(new ClientboundSetPassengersPacket(this.entity)); + } +@@ -293,9 +381,15 @@ + } + + if (this.entity instanceof LivingEntity) { +- Set dirtyAttributes = ((LivingEntity)this.entity).getAttributes().getDirtyAttributes(); +- if (!dirtyAttributes.isEmpty()) { +- this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), dirtyAttributes)); ++ Set set = ((LivingEntity) this.entity).getAttributes().getDirtyAttributes(); ++ ++ if (!set.isEmpty()) { ++ // CraftBukkit start - Send scaled max health ++ if (this.entity instanceof ServerPlayer) { ++ ((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(set, false); ++ } ++ // CraftBukkit end ++ this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), set)); + } + + dirtyAttributes.clear(); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ServerLevel.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ServerLevel.java.patch new file mode 100644 index 0000000000..03bd29e1b2 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ServerLevel.java.patch @@ -0,0 +1,849 @@ +--- a/net/minecraft/server/level/ServerLevel.java ++++ b/net/minecraft/server/level/ServerLevel.java +@@ -158,6 +164,19 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.ticks.LevelTicks; + import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.WeatherType; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.generator.CustomWorldChunkManager; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.craftbukkit.util.WorldUUID; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.server.MapInitializeEvent; ++import org.bukkit.event.weather.LightningStrikeEvent; ++import org.bukkit.event.world.GenericGameEvent; ++import org.bukkit.event.world.TimeSkipEvent; ++// CraftBukkit end + + public class ServerLevel extends Level implements WorldGenLevel { + public static final BlockPos END_SPAWN_POINT = new BlockPos(100, 50, 0); +@@ -171,9 +191,9 @@ + final List players = Lists.newArrayList(); + private final ServerChunkCache chunkSource; + private final MinecraftServer server; +- private final ServerLevelData serverLevelData; +- final EntityTickList entityTickList = new EntityTickList(); +- private final PersistentEntitySectionManager entityManager; ++ public final PrimaryLevelData serverLevelData; // CraftBukkit - type ++ final EntityTickList entityTickList; ++ public final PersistentEntitySectionManager entityManager; + private final GameEventDispatcher gameEventDispatcher; + public boolean noSave; + private final SleepStatus sleepStatus; +@@ -196,56 +216,73 @@ + private final boolean tickTime; + private final RandomSequences randomSequences; + +- public ServerLevel( +- MinecraftServer server, +- Executor dispatcher, +- LevelStorageSource.LevelStorageAccess levelStorageAccess, +- ServerLevelData serverLevelData, +- ResourceKey dimension, +- LevelStem levelStem, +- ChunkProgressListener progressListener, +- boolean isDebug, +- long biomeZoomSeed, +- List customSpawners, +- boolean tickTime, +- @Nullable RandomSequences randomSequences +- ) { +- super( +- serverLevelData, +- dimension, +- server.registryAccess(), +- levelStem.type(), +- server::getProfiler, +- false, +- isDebug, +- biomeZoomSeed, +- server.getMaxChainedNeighborUpdates() +- ); +- this.tickTime = tickTime; +- this.server = server; +- this.customSpawners = customSpawners; +- this.serverLevelData = serverLevelData; +- ChunkGenerator chunkGenerator = levelStem.generator(); +- boolean flag = server.forceSynchronousWrites(); +- DataFixer fixerUpper = server.getFixerUpper(); +- EntityPersistentStorage entityPersistentStorage = new EntityStorage( +- this, levelStorageAccess.getDimensionPath(dimension).resolve("entities"), fixerUpper, flag, server +- ); +- this.entityManager = new PersistentEntitySectionManager<>(Entity.class, new ServerLevel.EntityCallbacks(), entityPersistentStorage); +- this.chunkSource = new ServerChunkCache( +- this, +- levelStorageAccess, +- fixerUpper, +- server.getStructureManager(), +- dispatcher, +- chunkGenerator, +- server.getPlayerList().getViewDistance(), +- server.getPlayerList().getSimulationDistance(), +- flag, +- progressListener, +- this.entityManager::updateChunkStatus, +- () -> server.overworld().getDataStorage() +- ); ++ // CraftBukkit start ++ public final LevelStorageSource.LevelStorageAccess convertable; ++ public final UUID uuid; ++ ++ public LevelChunk getChunkIfLoaded(int x, int z) { ++ return this.chunkSource.getChunk(x, z, false); ++ } ++ ++ @Override ++ public ResourceKey getTypeKey() { ++ return convertable.dimensionType; ++ } ++ ++ // Add env and gen to constructor, IWorldDataServer -> WorldDataServer ++ public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List list, boolean flag1, @Nullable RandomSequences randomsequences, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) { ++ // IRegistryCustom.Dimension iregistrycustom_dimension = minecraftserver.registryAccess(); // CraftBukkit - decompile error ++ // Holder holder = worlddimension.type(); // CraftBukkit - decompile error ++ ++ // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error ++ super(iworlddataserver, resourcekey, minecraftserver.registryAccess(), worlddimension.type(), minecraftserver::getProfiler, false, flag, i, minecraftserver.getMaxChainedNeighborUpdates(), gen, biomeProvider, env); ++ this.pvpMode = minecraftserver.isPvpAllowed(); ++ convertable = convertable_conversionsession; ++ uuid = WorldUUID.getUUID(convertable_conversionsession.levelDirectory.path().toFile()); ++ // CraftBukkit end ++ this.players = Lists.newArrayList(); ++ this.entityTickList = new EntityTickList(); ++ this.blockTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded, this.getProfilerSupplier()); ++ this.fluidTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded, this.getProfilerSupplier()); ++ this.navigatingMobs = new ObjectOpenHashSet(); ++ this.blockEvents = new ObjectLinkedOpenHashSet(); ++ this.blockEventsToReschedule = new ArrayList(64); ++ this.dragonParts = new Int2ObjectOpenHashMap(); ++ this.tickTime = flag1; ++ this.server = minecraftserver; ++ this.customSpawners = list; ++ this.serverLevelData = iworlddataserver; ++ ChunkGenerator chunkgenerator = worlddimension.generator(); ++ // CraftBukkit start ++ serverLevelData.setWorld(this); ++ ++ if (biomeProvider != null) { ++ BiomeSource worldChunkManager = new CustomWorldChunkManager(getWorld(), biomeProvider, server.registryAccess().registryOrThrow(Registries.BIOME)); ++ if (chunkgenerator instanceof NoiseBasedChunkGenerator cga) { ++ chunkgenerator = new NoiseBasedChunkGenerator(worldChunkManager, cga.settings); ++ } else if (chunkgenerator instanceof FlatLevelSource cpf) { ++ chunkgenerator = new FlatLevelSource(cpf.settings(), worldChunkManager); ++ } ++ } ++ ++ if (gen != null) { ++ chunkgenerator = new org.bukkit.craftbukkit.generator.CustomChunkGenerator(this, chunkgenerator, gen); ++ } ++ // CraftBukkit end ++ boolean flag2 = minecraftserver.forceSynchronousWrites(); ++ DataFixer datafixer = minecraftserver.getFixerUpper(); ++ EntityPersistentStorage entitypersistentstorage = new EntityStorage(this, convertable_conversionsession.getDimensionPath(resourcekey).resolve("entities"), datafixer, flag2, minecraftserver); ++ ++ this.entityManager = new PersistentEntitySectionManager<>(Entity.class, new ServerLevel.a(), entitypersistentstorage); ++ StructureTemplateManager structuretemplatemanager = minecraftserver.getStructureManager(); ++ int j = minecraftserver.getPlayerList().getViewDistance(); ++ int k = minecraftserver.getPlayerList().getSimulationDistance(); ++ PersistentEntitySectionManager persistententitysectionmanager = this.entityManager; ++ ++ Objects.requireNonNull(this.entityManager); ++ this.chunkSource = new ServerChunkCache(this, convertable_conversionsession, datafixer, structuretemplatemanager, executor, chunkgenerator, j, k, flag2, worldloadlistener, persistententitysectionmanager::updateChunkStatus, () -> { ++ return minecraftserver.overworld().getDataStorage(); ++ }); + this.chunkSource.getGeneratorState().ensureStructuresGenerated(); + this.portalForcer = new PortalForcer(this); + this.updateSkyBrightness(); +@@ -256,31 +293,22 @@ + serverLevelData.setGameType(server.getDefaultGameType()); + } + +- long l = server.getWorldData().worldGenOptions().seed(); +- this.structureCheck = new StructureCheck( +- this.chunkSource.chunkScanner(), +- this.registryAccess(), +- server.getStructureManager(), +- dimension, +- chunkGenerator, +- this.chunkSource.randomState(), +- this, +- chunkGenerator.getBiomeSource(), +- l, +- fixerUpper +- ); +- this.structureManager = new StructureManager(this, server.getWorldData().worldGenOptions(), this.structureCheck); +- if (this.dimension() == Level.END && this.dimensionTypeRegistration().is(BuiltinDimensionTypes.END)) { +- this.dragonFight = new EndDragonFight(this, l, server.getWorldData().endDragonFightData()); ++ long l = minecraftserver.getWorldData().worldGenOptions().seed(); ++ ++ this.structureCheck = new StructureCheck(this.chunkSource.chunkScanner(), this.registryAccess(), minecraftserver.getStructureManager(), resourcekey, chunkgenerator, this.chunkSource.randomState(), this, chunkgenerator.getBiomeSource(), l, datafixer); ++ this.structureManager = new StructureManager(this, this.serverLevelData.worldGenOptions(), structureCheck); // CraftBukkit ++ if ((this.dimension() == Level.END && this.dimensionTypeRegistration().is(BuiltinDimensionTypes.END)) || env == org.bukkit.World.Environment.THE_END) { // CraftBukkit - Allow to create EnderDragonBattle in default and custom END ++ this.dragonFight = new EndDragonFight(this, this.serverLevelData.worldGenOptions().seed(), this.serverLevelData.endDragonFightData()); // CraftBukkit + } else { + this.dragonFight = null; + } + + this.sleepStatus = new SleepStatus(); + this.gameEventDispatcher = new GameEventDispatcher(this); +- this.randomSequences = Objects.requireNonNullElseGet( +- randomSequences, () -> this.getDataStorage().computeIfAbsent(RandomSequences.factory(l), "random_sequences") +- ); ++ this.randomSequences = (RandomSequences) Objects.requireNonNullElseGet(randomsequences, () -> { ++ return (RandomSequences) this.getDataStorage().computeIfAbsent(RandomSequences.factory(l), "random_sequences"); ++ }); ++ this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit + } + + @Deprecated +@@ -318,14 +349,22 @@ + this.advanceWeatherCycle(); + } + +- int _int = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE); +- if (this.sleepStatus.areEnoughSleeping(_int) && this.sleepStatus.areEnoughDeepSleeping(_int, this.players)) { ++ int i = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE); ++ long j; ++ ++ if (this.sleepStatus.areEnoughSleeping(i) && this.sleepStatus.areEnoughDeepSleeping(i, this.players)) { ++ // CraftBukkit start ++ j = this.levelData.getDayTime() + 24000L; ++ TimeSkipEvent event = new TimeSkipEvent(this.getWorld(), TimeSkipEvent.SkipReason.NIGHT_SKIP, (j - j % 24000L) - this.getDayTime()); + if (this.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { + long l = this.levelData.getDayTime() + 24000L; + this.setDayTime(l - l % 24000L); + } + +- this.wakeUpAllPlayers(); ++ if (!event.isCancelled()) { ++ this.wakeUpAllPlayers(); ++ } ++ // CraftBukkit end + if (this.getGameRules().getBoolean(GameRules.RULE_WEATHER_CYCLE) && this.isRaining()) { + this.resetWeatherCycle(); + } +@@ -359,8 +400,9 @@ + } + + this.handlingTick = false; +- profiler.pop(); +- boolean flag1 = !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); ++ gameprofilerfiller.pop(); ++ boolean flag1 = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players ++ + if (flag1) { + this.resetEmptyTime(); + } +@@ -375,7 +417,7 @@ + + this.entityTickList.forEach(entity -> { + if (!entity.isRemoved()) { +- if (this.shouldDiscardEntity(entity)) { ++ if (false && this.shouldDiscardEntity(entity)) { // CraftBukkit - We prevent spawning in general, so this butchering is not needed + entity.discard(); + } else if (!tickRateManager.isEntityFrozen(entity)) { + profiler.push("checkDespawn"); +@@ -444,34 +495,37 @@ + } + + public void tickChunk(LevelChunk chunk, int randomTickSpeed) { +- ChunkPos pos = chunk.getPos(); +- boolean isRaining = this.isRaining(); +- int minBlockX = pos.getMinBlockX(); +- int minBlockZ = pos.getMinBlockZ(); +- ProfilerFiller profiler = this.getProfiler(); +- profiler.push("thunder"); +- if (isRaining && this.isThundering() && this.random.nextInt(100000) == 0) { +- BlockPos blockPos = this.findLightningTargetAround(this.getBlockRandomPos(minBlockX, 0, minBlockZ, 15)); +- if (this.isRainingAt(blockPos)) { +- DifficultyInstance currentDifficultyAt = this.getCurrentDifficultyAt(blockPos); +- boolean flag = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) +- && this.random.nextDouble() < (double)currentDifficultyAt.getEffectiveDifficulty() * 0.01 +- && !this.getBlockState(blockPos.below()).is(Blocks.LIGHTNING_ROD); +- if (flag) { +- SkeletonHorse skeletonHorse = EntityType.SKELETON_HORSE.create(this); +- if (skeletonHorse != null) { +- skeletonHorse.setTrap(true); +- skeletonHorse.setAge(0); +- skeletonHorse.setPos((double)blockPos.getX(), (double)blockPos.getY(), (double)blockPos.getZ()); +- this.addFreshEntity(skeletonHorse); ++ ChunkPos chunkcoordintpair = chunk.getPos(); ++ boolean flag = this.isRaining(); ++ int j = chunkcoordintpair.getMinBlockX(); ++ int k = chunkcoordintpair.getMinBlockZ(); ++ ProfilerFiller gameprofilerfiller = this.getProfiler(); ++ ++ gameprofilerfiller.push("thunder"); ++ if (flag && this.isThundering() && this.random.nextInt(100000) == 0) { ++ BlockPos blockposition = this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15)); ++ ++ if (this.isRainingAt(blockposition)) { ++ DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); ++ boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * 0.01D && !this.getBlockState(blockposition.below()).is(Blocks.LIGHTNING_ROD); ++ ++ if (flag1) { ++ SkeletonHorse entityhorseskeleton = (SkeletonHorse) EntityType.SKELETON_HORSE.create(this); ++ ++ if (entityhorseskeleton != null) { ++ entityhorseskeleton.setTrap(true); ++ entityhorseskeleton.setAge(0); ++ entityhorseskeleton.setPos((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()); ++ this.addFreshEntity(entityhorseskeleton, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); // CraftBukkit + } + } + +- LightningBolt lightningBolt = EntityType.LIGHTNING_BOLT.create(this); +- if (lightningBolt != null) { +- lightningBolt.moveTo(Vec3.atBottomCenterOf(blockPos)); +- lightningBolt.setVisualOnly(flag); +- this.addFreshEntity(lightningBolt); ++ LightningBolt entitylightning = (LightningBolt) EntityType.LIGHTNING_BOLT.create(this); ++ ++ if (entitylightning != null) { ++ entitylightning.moveTo(Vec3.atBottomCenterOf(blockposition)); ++ entitylightning.setVisualOnly(flag1); ++ this.strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.WEATHER); // CraftBukkit + } + } + } +@@ -519,27 +575,32 @@ + } + + @VisibleForTesting +- public void tickPrecipitation(BlockPos blockPos) { +- BlockPos heightmapPos = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, blockPos); +- BlockPos blockPos1 = heightmapPos.below(); +- Biome biome = this.getBiome(heightmapPos).value(); +- if (biome.shouldFreeze(this, blockPos1)) { +- this.setBlockAndUpdate(blockPos1, Blocks.ICE.defaultBlockState()); ++ public void tickPrecipitation(BlockPos blockposition) { ++ BlockPos blockposition1 = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, blockposition); ++ BlockPos blockposition2 = blockposition1.below(); ++ Biome biomebase = (Biome) this.getBiome(blockposition1).value(); ++ ++ if (biomebase.shouldFreeze(this, blockposition2)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition2, Blocks.ICE.defaultBlockState(), null); // CraftBukkit + } + + if (this.isRaining()) { +- int _int = this.getGameRules().getInt(GameRules.RULE_SNOW_ACCUMULATION_HEIGHT); +- if (_int > 0 && biome.shouldSnow(this, heightmapPos)) { +- BlockState blockState = this.getBlockState(heightmapPos); +- if (blockState.is(Blocks.SNOW)) { +- int i = blockState.getValue(SnowLayerBlock.LAYERS); +- if (i < Math.min(_int, 8)) { +- BlockState blockState1 = blockState.setValue(SnowLayerBlock.LAYERS, Integer.valueOf(i + 1)); +- Block.pushEntitiesUp(blockState, blockState1, this, heightmapPos); +- this.setBlockAndUpdate(heightmapPos, blockState1); ++ int i = this.getGameRules().getInt(GameRules.RULE_SNOW_ACCUMULATION_HEIGHT); ++ ++ if (i > 0 && biomebase.shouldSnow(this, blockposition1)) { ++ IBlockData iblockdata = this.getBlockState(blockposition1); ++ ++ if (iblockdata.is(Blocks.SNOW)) { ++ int j = (Integer) iblockdata.getValue(SnowLayerBlock.LAYERS); ++ ++ if (j < Math.min(i, 8)) { ++ IBlockData iblockdata1 = (IBlockData) iblockdata.setValue(SnowLayerBlock.LAYERS, j + 1); ++ ++ Block.pushEntitiesUp(iblockdata, iblockdata1, this, blockposition1); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, iblockdata1, null); // CraftBukkit + } + } else { +- this.setBlockAndUpdate(heightmapPos, Blocks.SNOW.defaultBlockState()); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, Blocks.SNOW.defaultBlockState(), null); // CraftBukkit + } + } + +@@ -684,6 +761,7 @@ + this.rainLevel = Mth.clamp(this.rainLevel, 0.0F, 1.0F); + } + ++ /* CraftBukkit start + if (this.oRainLevel != this.rainLevel) { + this.server + .getPlayerList() +@@ -706,14 +780,48 @@ + this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, this.rainLevel)); + this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, this.thunderLevel)); + } ++ // */ ++ for (int idx = 0; idx < this.players.size(); ++idx) { ++ if (((ServerPlayer) this.players.get(idx)).level() == this) { ++ ((ServerPlayer) this.players.get(idx)).tickWeather(); ++ } ++ } ++ ++ if (flag != this.isRaining()) { ++ // Only send weather packets to those affected ++ for (int idx = 0; idx < this.players.size(); ++idx) { ++ if (((ServerPlayer) this.players.get(idx)).level() == this) { ++ ((ServerPlayer) this.players.get(idx)).setPlayerWeather((!flag ? WeatherType.DOWNFALL : WeatherType.CLEAR), false); ++ } ++ } ++ } ++ for (int idx = 0; idx < this.players.size(); ++idx) { ++ if (((ServerPlayer) this.players.get(idx)).level() == this) { ++ ((ServerPlayer) this.players.get(idx)).updateWeather(this.oRainLevel, this.rainLevel, this.oThunderLevel, this.thunderLevel); ++ } ++ } ++ // CraftBukkit end ++ + } + + @VisibleForTesting + public void resetWeatherCycle() { +- this.serverLevelData.setRainTime(0); ++ // CraftBukkit start + this.serverLevelData.setRaining(false); +- this.serverLevelData.setThunderTime(0); ++ // If we stop due to everyone sleeping we should reset the weather duration to some other random value. ++ // Not that everyone ever manages to get the whole server to sleep at the same time.... ++ if (!this.serverLevelData.isRaining()) { ++ this.serverLevelData.setRainTime(0); ++ } ++ // CraftBukkit end + this.serverLevelData.setThundering(false); ++ // CraftBukkit start ++ // If we stop due to everyone sleeping we should reset the weather duration to some other random value. ++ // Not that everyone ever manages to get the whole server to sleep at the same time.... ++ if (!this.serverLevelData.isThundering()) { ++ this.serverLevelData.setThunderTime(0); ++ } ++ // CraftBukkit end + } + + public void resetEmptyTime() { +@@ -741,6 +856,7 @@ + this.getProfiler().push(() -> BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()).toString()); + profiler.incrementCounter("tickNonPassenger"); + entity.tick(); ++ entity.postTick(); // CraftBukkit + this.getProfiler().pop(); + + for (Entity entity1 : entity.getPassengers()) { +@@ -760,8 +875,21 @@ + passengerEntity.rideTick(); + profiler.pop(); + +- for (Entity entity : passengerEntity.getPassengers()) { +- this.tickPassenger(passengerEntity, entity); ++ gameprofilerfiller.push(() -> { ++ return BuiltInRegistries.ENTITY_TYPE.getKey(passengerEntity.getType()).toString(); ++ }); ++ gameprofilerfiller.incrementCounter("tickPassenger"); ++ passengerEntity.rideTick(); ++ passengerEntity.postTick(); // CraftBukkit ++ gameprofilerfiller.pop(); ++ Iterator iterator = passengerEntity.getPassengers().iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity2 = (Entity) iterator.next(); ++ ++ this.tickPassenger(passengerEntity, entity2); ++ } ++ + } + } + } +@@ -774,6 +905,7 @@ + public void save(@Nullable ProgressListener progress, boolean flush, boolean skipSave) { + ServerChunkCache chunkSource = this.getChunkSource(); + if (!skipSave) { ++ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit + if (progress != null) { + progress.progressStartNoAbort(Component.translatable("menu.savingLevel")); + } +@@ -790,11 +923,19 @@ + this.entityManager.autoSave(); + } + } ++ ++ // CraftBukkit start - moved from MinecraftServer.saveChunks ++ ServerLevel worldserver1 = this; ++ ++ serverLevelData.setWorldBorder(worldserver1.getWorldBorder().createSettings()); ++ serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save()); ++ convertable.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData()); ++ // CraftBukkit end + } + + private void saveLevelData() { + if (this.dragonFight != null) { +- this.server.getWorldData().setEndDragonFightData(this.dragonFight.saveData()); ++ this.serverLevelData.setEndDragonFightData(this.dragonFight.saveData()); // CraftBukkit + } + + this.getChunkSource().getDataStorage().save(); +@@ -854,17 +1000,39 @@ + + @Override + public boolean addFreshEntity(Entity entity) { +- return this.addEntity(entity); ++ // CraftBukkit start ++ return this.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.DEFAULT); + } + ++ @Override ++ public boolean addFreshEntity(Entity entity, CreatureSpawnEvent.SpawnReason reason) { ++ return this.addEntity(entity, reason); ++ // CraftBukkit end ++ } ++ + public boolean addWithUUID(Entity entity) { +- return this.addEntity(entity); ++ // CraftBukkit start ++ return this.addWithUUID(entity, CreatureSpawnEvent.SpawnReason.DEFAULT); + } + ++ public boolean addWithUUID(Entity entity, CreatureSpawnEvent.SpawnReason reason) { ++ return this.addEntity(entity, reason); ++ // CraftBukkit end ++ } ++ + public void addDuringTeleport(Entity entity) { +- this.addEntity(entity); ++ // CraftBukkit start ++ // SPIGOT-6415: Don't call spawn event for entities which travel trough worlds, ++ // since it is only an implementation detail, that a new entity is created when ++ // they are traveling between worlds. ++ this.addDuringTeleport(entity, null); + } + ++ public void addDuringTeleport(Entity entity, CreatureSpawnEvent.SpawnReason reason) { ++ this.addEntity(entity, reason); ++ // CraftBukkit end ++ } ++ + public void addDuringCommandTeleport(ServerPlayer player) { + this.addPlayer(player); + } +@@ -892,20 +1061,37 @@ + this.entityManager.addNewEntity(player); + } + +- private boolean addEntity(Entity entity) { ++ // CraftBukkit start ++ private boolean addEntity(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { + if (entity.isRemoved()) { +- LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityType.getKey(entity.getType())); ++ // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getKey(entity.getType())); // CraftBukkit + return false; + } else { ++ // SPIGOT-6415: Don't call spawn event when reason is null. For example when an entity teleports to a new world. ++ if (spawnReason != null && !CraftEventFactory.doEntityAddEventCalling(this, entity, spawnReason)) { ++ return false; ++ } ++ // CraftBukkit end ++ + return this.entityManager.addNewEntity(entity); + } + } + + public boolean tryAddFreshEntityWithPassengers(Entity entity) { +- if (entity.getSelfAndPassengers().map(Entity::getUUID).anyMatch(this.entityManager::isLoaded)) { ++ // CraftBukkit start ++ return this.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ public boolean tryAddFreshEntityWithPassengers(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ // CraftBukkit end ++ Stream stream = entity.getSelfAndPassengers().map(Entity::getUUID); // CraftBukkit - decompile error ++ PersistentEntitySectionManager persistententitysectionmanager = this.entityManager; ++ ++ Objects.requireNonNull(this.entityManager); ++ if (stream.anyMatch(persistententitysectionmanager::isLoaded)) { + return false; + } else { +- this.addFreshEntityWithPassengers(entity); ++ this.addFreshEntityWithPassengers(entity, reason); // CraftBukkit + return true; + } + } +@@ -919,16 +1105,49 @@ + player.remove(reason); + } + ++ // CraftBukkit start ++ public boolean strikeLightning(Entity entitylightning) { ++ return this.strikeLightning(entitylightning, LightningStrikeEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean strikeLightning(Entity entitylightning, LightningStrikeEvent.Cause cause) { ++ LightningStrikeEvent lightning = CraftEventFactory.callLightningStrikeEvent((org.bukkit.entity.LightningStrike) entitylightning.getBukkitEntity(), cause); ++ ++ if (lightning.isCancelled()) { ++ return false; ++ } ++ ++ return this.addFreshEntity(entitylightning); ++ } ++ // CraftBukkit end ++ + @Override + public void destroyBlockProgress(int breakerId, BlockPos pos, int progress) { +- for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) { +- if (serverPlayer != null && serverPlayer.level() == this && serverPlayer.getId() != breakerId) { +- double d = (double)pos.getX() - serverPlayer.getX(); +- double d1 = (double)pos.getY() - serverPlayer.getY(); +- double d2 = (double)pos.getZ() - serverPlayer.getZ(); +- if (d * d + d1 * d1 + d2 * d2 < 1024.0) { +- serverPlayer.connection.send(new ClientboundBlockDestructionPacket(breakerId, pos, progress)); ++ Iterator iterator = this.server.getPlayerList().getPlayers().iterator(); ++ ++ // CraftBukkit start ++ Player entityhuman = null; ++ Entity entity = this.getEntity(breakerId); ++ if (entity instanceof Player) entityhuman = (Player) entity; ++ // CraftBukkit end ++ ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ if (entityplayer != null && entityplayer.level() == this && entityplayer.getId() != breakerId) { ++ double d0 = (double) pos.getX() - entityplayer.getX(); ++ double d1 = (double) pos.getY() - entityplayer.getY(); ++ double d2 = (double) pos.getZ() - entityplayer.getZ(); ++ ++ // CraftBukkit start ++ if (entityhuman != null && !entityplayer.getBukkitEntity().canSee(entityhuman.getBukkitEntity())) { ++ continue; + } ++ // CraftBukkit end ++ ++ if (d0 * d0 + d1 * d1 + d2 * d2 < 1024.0D) { ++ entityplayer.connection.send(new ClientboundBlockDestructionPacket(breakerId, pos, progress)); ++ } + } + } + } +@@ -1011,11 +1199,28 @@ + if (Shapes.joinIsNotEmpty(collisionShape, collisionShape1, BooleanOp.NOT_SAME)) { + List list = new ObjectArrayList<>(); + +- for (Mob mob : this.navigatingMobs) { +- PathNavigation navigation = mob.getNavigation(); +- if (navigation.shouldRecomputePath(pos)) { +- list.add(navigation); ++ if (Shapes.joinIsNotEmpty(voxelshape, voxelshape1, BooleanOp.NOT_SAME)) { ++ List list = new ObjectArrayList(); ++ Iterator iterator = this.navigatingMobs.iterator(); ++ ++ while (iterator.hasNext()) { ++ // CraftBukkit start - fix SPIGOT-6362 ++ Mob entityinsentient; ++ try { ++ entityinsentient = (Mob) iterator.next(); ++ } catch (java.util.ConcurrentModificationException ex) { ++ // This can happen because the pathfinder update below may trigger a chunk load, which in turn may cause more navigators to register ++ // In this case we just run the update again across all the iterators as the chunk will then be loaded ++ // As this is a relative edge case it is much faster than copying navigators (on either read or write) ++ sendBlockUpdated(pos, oldState, newState, flags); ++ return; + } ++ // CraftBukkit end ++ PathNavigation navigationabstract = entityinsentient.getNavigation(); ++ ++ if (navigationabstract.shouldRecomputePath(pos)) { ++ list.add(navigationabstract); ++ } + } + + try { +@@ -1066,23 +1275,14 @@ + } + + @Override +- public Explosion explode( +- @Nullable Entity entity, +- @Nullable DamageSource damageSource, +- @Nullable ExplosionDamageCalculator explosionDamageCalculator, +- double d, +- double d1, +- double d2, +- float f, +- boolean flag, +- Level.ExplosionInteraction explosionInteraction, +- ParticleOptions particleOptions, +- ParticleOptions particleOptions1, +- SoundEvent soundEvent +- ) { +- Explosion explosion = this.explode( +- entity, damageSource, explosionDamageCalculator, d, d1, d2, f, flag, explosionInteraction, false, particleOptions, particleOptions1, soundEvent +- ); ++ public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.a world_a, ParticleOptions particleparam, ParticleOptions particleparam1, SoundEvent soundeffect) { ++ Explosion explosion = this.explode(entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, world_a, false, particleparam, particleparam1, soundeffect); ++ // CraftBukkit start ++ if (explosion.wasCanceled) { ++ return explosion; ++ } ++ // CraftBukkit end ++ + if (!explosion.interactsWithBlocks()) { + explosion.clearToBlow(); + } +@@ -1171,18 +1353,22 @@ + return this.server.getStructureManager(); + } + +- public int sendParticles( +- T type, double posX, double posY, double posZ, int particleCount, double xOffset, double yOffset, double zOffset, double speed +- ) { +- ClientboundLevelParticlesPacket clientboundLevelParticlesPacket = new ClientboundLevelParticlesPacket( +- type, false, posX, posY, posZ, (float)xOffset, (float)yOffset, (float)zOffset, (float)speed, particleCount +- ); +- int i = 0; ++ public int sendParticles(T type, double posX, double d1, double posY, int i, double posZ, double d4, double particleCount, double xOffset) { ++ // CraftBukkit - visibility api support ++ return sendParticles(null, type, posX, d1, posY, i, posZ, d4, particleCount, xOffset, false); ++ } + +- for (int i1 = 0; i1 < this.players.size(); i1++) { +- ServerPlayer serverPlayer = this.players.get(i1); +- if (this.sendParticles(serverPlayer, false, posX, posY, posZ, clientboundLevelParticlesPacket)) { +- i++; ++ public int sendParticles(ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { ++ ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(t0, force, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i); ++ // CraftBukkit end ++ int j = 0; ++ ++ for (int k = 0; k < this.players.size(); ++k) { ++ ServerPlayer entityplayer = (ServerPlayer) this.players.get(k); ++ if (sender != null && !entityplayer.getBukkitEntity().canSee(sender.getBukkitEntity())) continue; // CraftBukkit ++ ++ if (this.sendParticles(entityplayer, force, d0, d1, d2, packetplayoutworldparticles)) { // CraftBukkit ++ ++j; + } + } + +@@ -1242,7 +1418,7 @@ + + @Nullable + public BlockPos findNearestMapStructure(TagKey structureTag, BlockPos pos, int radius, boolean skipExistingChunks) { +- if (!this.server.getWorldData().worldGenOptions().generateStructures()) { ++ if (!this.serverLevelData.worldGenOptions().generateStructures()) { // CraftBukkit + return null; + } else { + Optional> tag = this.registryAccess().registryOrThrow(Registries.STRUCTURE).getTag(structureTag); +@@ -1287,11 +1460,22 @@ + @Nullable + @Override + public MapItemSavedData getMapData(String mapName) { +- return this.getServer().overworld().getDataStorage().get(MapItemSavedData.factory(), mapName); ++ // CraftBukkit start ++ MapItemSavedData worldmap = (MapItemSavedData) this.getServer().overworld().getDataStorage().get(MapItemSavedData.factory(), mapName); ++ if (worldmap != null) { ++ worldmap.id = mapName; ++ } ++ return worldmap; ++ // CraftBukkit end + } + + @Override + public void setMapData(String mapName, MapItemSavedData data) { ++ // CraftBukkit start ++ data.id = mapName; ++ MapInitializeEvent event = new MapInitializeEvent(data.mapView); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ // CraftBukkit end + this.getServer().overworld().getDataStorage().set(mapName, data); + } + +@@ -1491,6 +1773,11 @@ + @Override + public void blockUpdated(BlockPos pos, Block block) { + if (!this.isDebug()) { ++ // CraftBukkit start ++ if (populating) { ++ return; ++ } ++ // CraftBukkit end + this.updateNeighborsAt(pos, block); + } + } +@@ -1510,12 +1797,12 @@ + } + + public boolean isFlat() { +- return this.server.getWorldData().isFlatWorld(); ++ return this.serverLevelData.isFlatWorld(); // CraftBukkit + } + + @Override + public long getSeed() { +- return this.server.getWorldData().worldGenOptions().seed(); ++ return this.serverLevelData.worldGenOptions().seed(); // CraftBukkit + } + + @Nullable +@@ -1565,16 +1845,35 @@ + } + + public static void makeObsidianPlatform(ServerLevel serverLevel) { +- BlockPos blockPos = END_SPAWN_POINT; +- int x = blockPos.getX(); +- int i = blockPos.getY() - 2; +- int z = blockPos.getZ(); +- BlockPos.betweenClosed(x - 2, i + 1, z - 2, x + 2, i + 3, z + 2) +- .forEach(blockPos1 -> serverLevel.setBlockAndUpdate(blockPos1, Blocks.AIR.defaultBlockState())); +- BlockPos.betweenClosed(x - 2, i, z - 2, x + 2, i, z + 2) +- .forEach(blockPos1 -> serverLevel.setBlockAndUpdate(blockPos1, Blocks.OBSIDIAN.defaultBlockState())); ++ // CraftBukkit start ++ ServerLevel.makeObsidianPlatform(serverLevel, null); + } + ++ public static void makeObsidianPlatform(ServerLevel worldserver, Entity entity) { ++ // CraftBukkit end ++ BlockPos blockposition = ServerLevel.END_SPAWN_POINT; ++ int i = blockposition.getX(); ++ int j = blockposition.getY() - 2; ++ int k = blockposition.getZ(); ++ ++ // CraftBukkit start ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(worldserver); ++ BlockPos.betweenClosed(i - 2, j + 1, k - 2, i + 2, j + 3, k + 2).forEach((blockposition1) -> { ++ blockList.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3); ++ }); ++ BlockPos.betweenClosed(i - 2, j, k - 2, i + 2, j, k + 2).forEach((blockposition1) -> { ++ blockList.setBlock(blockposition1, Blocks.OBSIDIAN.defaultBlockState(), 3); ++ }); ++ org.bukkit.World bworld = worldserver.getWorld(); ++ org.bukkit.event.world.PortalCreateEvent portalEvent = new org.bukkit.event.world.PortalCreateEvent((List) (List) blockList.getList(), bworld, (entity == null) ? null : entity.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM); ++ ++ worldserver.getCraftServer().getPluginManager().callEvent(portalEvent); ++ if (!portalEvent.isCancelled()) { ++ blockList.updateList(); ++ } ++ // CraftBukkit end ++ } ++ + @Override + protected LevelEntityGetter getEntities() { + return this.entityManager.getEntityGetter(); +@@ -1693,6 +2005,8 @@ + } + + entity.updateDynamicGameEventListener(DynamicGameEventListener::add); ++ entity.inWorld = true; // CraftBukkit - Mark entity as in world ++ entity.valid = true; // CraftBukkit + } + + @Override +@@ -1721,6 +2043,14 @@ + } + + entity.updateDynamicGameEventListener(DynamicGameEventListener::remove); ++ // CraftBukkit start ++ entity.valid = false; ++ if (!(entity instanceof ServerPlayer)) { ++ for (ServerPlayer player : players) { ++ player.getBukkitEntity().onEntityRemove(entity); ++ } ++ } ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ServerPlayer.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ServerPlayer.java.patch new file mode 100644 index 0000000000..73b5562e43 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ServerPlayer.java.patch @@ -0,0 +1,1312 @@ +--- a/net/minecraft/server/level/ServerPlayer.java ++++ b/net/minecraft/server/level/ServerPlayer.java +@@ -152,7 +162,29 @@ + import net.minecraft.world.scores.ScoreHolder; + import net.minecraft.world.scores.Team; + import net.minecraft.world.scores.criteria.ObjectiveCriteria; +-import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.WeatherType; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.CraftWorldBorder; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.event.CraftPortalEvent; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftDimensionUtil; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.entity.EntityExhaustionEvent; ++import org.bukkit.event.player.PlayerBedLeaveEvent; ++import org.bukkit.event.player.PlayerChangedMainHandEvent; ++import org.bukkit.event.player.PlayerChangedWorldEvent; ++import org.bukkit.event.player.PlayerLocaleChangeEvent; ++import org.bukkit.event.player.PlayerPortalEvent; ++import org.bukkit.event.player.PlayerSpawnChangeEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; ++import org.bukkit.event.player.PlayerToggleSneakEvent; ++import org.bukkit.inventory.MainHand; ++// CraftBukkit end + + public class ServerPlayer extends Player { + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -187,8 +220,8 @@ + private Vec3 levitationStartPos; + private int levitationStartTime; + private boolean disconnected; +- private int requestedViewDistance = 2; +- private String language = "en_us"; ++ private int requestedViewDistance; ++ public String language = "en_us"; // CraftBukkit - default + @Nullable + private Vec3 startingToFallPosition; + @Nullable +@@ -212,8 +246,41 @@ + ServerPlayer.this.connection + .send(new ClientboundContainerSetContentPacket(container.containerId, container.incrementStateId(), items, carriedItem)); + +- for (int i = 0; i < initialData.length; i++) { +- this.broadcastDataValue(container, i, initialData[i]); ++ // CraftBukkit start ++ public String displayName; ++ public Component listName; ++ public org.bukkit.Location compassTarget; ++ public int newExp = 0; ++ public int newLevel = 0; ++ public int newTotalExp = 0; ++ public boolean keepLevel = false; ++ public double maxHealthCache; ++ public boolean joining = true; ++ public boolean sentListPacket = false; ++ public String kickLeaveMessage = null; // SPIGOT-3034: Forward leave message to PlayerQuitEvent ++ // CraftBukkit end ++ ++ public ServerPlayer(MinecraftServer minecraftserver, ServerLevel worldserver, GameProfile gameprofile, ClientInformation clientinformation) { ++ super(worldserver, worldserver.getSharedSpawnPos(), worldserver.getSharedSpawnAngle(), gameprofile); ++ this.chatVisibility = ChatVisiblity.FULL; ++ this.canChatColor = true; ++ this.lastActionTime = Util.getMillis(); ++ this.recipeBook = new ServerRecipeBook(); ++ this.requestedViewDistance = 2; ++ this.language = "en_us"; ++ this.lastSectionPos = SectionPos.of(0, 0, 0); ++ this.chunkTrackingView = ChunkTrackingView.EMPTY; ++ this.respawnDimension = Level.OVERWORLD; ++ this.wardenSpawnTracker = new WardenSpawnTracker(0, 0, 0); ++ this.containerSynchronizer = new ContainerSynchronizer() { ++ @Override ++ public void sendInitialData(AbstractContainerMenu container, NonNullList items, ItemStack carriedItem, int[] initialData) { ++ ServerPlayer.this.connection.send(new ClientboundContainerSetContentPacket(container.containerId, container.incrementStateId(), items, carriedItem)); ++ ++ for (int i = 0; i < initialData.length; ++i) { ++ this.broadcastDataValue(container, i, initialData[i]); ++ } ++ + } + } + +@@ -247,8 +315,57 @@ + } + } + +- @Override +- public void dataChanged(AbstractContainerMenu containerMenu, int dataSlotIndex, int value) { ++ @Override ++ public void dataChanged(AbstractContainerMenu containerMenu, int dataSlotIndex, int value) {} ++ }; ++ this.textFilter = minecraftserver.createTextFilterForPlayer(this); ++ this.gameMode = minecraftserver.createGameModeForPlayer(this); ++ this.server = minecraftserver; ++ this.stats = minecraftserver.getPlayerList().getPlayerStats(this); ++ this.advancements = minecraftserver.getPlayerList().getPlayerAdvancements(this); ++ this.setMaxUpStep(1.0F); ++ this.fudgeSpawnLocation(worldserver); ++ this.updateOptions(clientinformation); ++ ++ // CraftBukkit start ++ this.displayName = this.getScoreboardName(); ++ this.bukkitPickUpLoot = true; ++ this.maxHealthCache = this.getMaxHealth(); ++ } ++ ++ // Yes, this doesn't match Vanilla, but it's the best we can do for now. ++ // If this is an issue, PRs are welcome ++ public final BlockPos getSpawnPoint(ServerLevel worldserver) { ++ BlockPos blockposition = worldserver.getSharedSpawnPos(); ++ ++ if (worldserver.dimensionType().hasSkyLight() && worldserver.serverLevelData.getGameType() != GameType.ADVENTURE) { ++ int i = Math.max(0, this.server.getSpawnRadius(worldserver)); ++ int j = Mth.floor(worldserver.getWorldBorder().getDistanceToBorder((double) blockposition.getX(), (double) blockposition.getZ())); ++ ++ if (j < i) { ++ i = j; ++ } ++ ++ if (j <= 1) { ++ i = 1; ++ } ++ ++ long k = (long) (i * 2 + 1); ++ long l = k * k; ++ int i1 = l > 2147483647L ? Integer.MAX_VALUE : (int) l; ++ int j1 = this.getCoprime(i1); ++ int k1 = RandomSource.create().nextInt(i1); ++ ++ for (int l1 = 0; l1 < i1; ++l1) { ++ int i2 = (k1 + j1 * l1) % i1; ++ int j2 = i2 % (i * 2 + 1); ++ int k2 = i2 / (i * 2 + 1); ++ BlockPos blockposition1 = PlayerRespawnLogic.getOverworldRespawnPos(worldserver, blockposition.getX() + j2 - i, blockposition.getZ() + k2 - i); ++ ++ if (blockposition1 != null) { ++ return blockposition1; ++ } ++ } + } + }; + @Nullable +@@ -267,14 +370,17 @@ + this.fudgeSpawnLocation(level); + this.updateOptions(clientInformation); + } ++ // CraftBukkit end + + private void fudgeSpawnLocation(ServerLevel level) { +- BlockPos sharedSpawnPos = level.getSharedSpawnPos(); +- if (level.dimensionType().hasSkyLight() && level.getServer().getWorldData().getGameType() != GameType.ADVENTURE) { +- int max = Math.max(0, this.server.getSpawnRadius(level)); +- int floor = Mth.floor(level.getWorldBorder().getDistanceToBorder((double)sharedSpawnPos.getX(), (double)sharedSpawnPos.getZ())); +- if (floor < max) { +- max = floor; ++ BlockPos blockposition = level.getSharedSpawnPos(); ++ ++ if (level.dimensionType().hasSkyLight() && level.serverLevelData.getGameType() != GameType.ADVENTURE) { // CraftBukkit ++ int i = Math.max(0, this.server.getSpawnRadius(level)); ++ int j = Mth.floor(level.getWorldBorder().getDistanceToBorder((double) blockposition.getX(), (double) blockposition.getZ())); ++ ++ if (j < i) { ++ i = j; + } + + if (floor <= 1) { +@@ -333,11 +443,20 @@ + if (compound.contains("recipeBook", 10)) { + this.recipeBook.fromNbt(compound.getCompound("recipeBook"), this.server.getRecipeManager()); + } ++ this.getBukkitEntity().readExtraData(compound); // CraftBukkit + + if (this.isSleeping()) { + this.stopSleeping(); + } + ++ // CraftBukkit start ++ String spawnWorld = compound.getString("SpawnWorld"); ++ CraftWorld oldWorld = (CraftWorld) Bukkit.getWorld(spawnWorld); ++ if (oldWorld != null) { ++ this.respawnDimension = oldWorld.getHandle().dimension(); ++ } ++ // CraftBukkit end ++ + if (compound.contains("SpawnX", 99) && compound.contains("SpawnY", 99) && compound.contains("SpawnZ", 99)) { + this.respawnPosition = new BlockPos(compound.getInt("SpawnX"), compound.getInt("SpawnY"), compound.getInt("SpawnZ")); + this.respawnForced = compound.getBoolean("SpawnForced"); +@@ -368,17 +493,32 @@ + compound.put("enteredNetherPosition", compoundTag); + } + +- Entity rootVehicle = this.getRootVehicle(); +- Entity vehicle = this.getVehicle(); +- if (vehicle != null && rootVehicle != this && rootVehicle.hasExactlyOnePlayerPassenger()) { +- CompoundTag compoundTag1 = new CompoundTag(); +- CompoundTag compoundTag2 = new CompoundTag(); +- rootVehicle.save(compoundTag2); +- compoundTag1.putUUID("Attach", vehicle.getUUID()); +- compoundTag1.put("Entity", compoundTag2); +- compound.put("RootVehicle", compoundTag1); ++ Entity entity = this.getRootVehicle(); ++ Entity entity1 = this.getVehicle(); ++ ++ // CraftBukkit start - handle non-persistent vehicles ++ boolean persistVehicle = true; ++ if (entity1 != null) { ++ Entity vehicle; ++ for (vehicle = entity1; vehicle != null; vehicle = vehicle.getVehicle()) { ++ if (!vehicle.persist) { ++ persistVehicle = false; ++ break; ++ } ++ } + } + ++ if (persistVehicle && entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger()) { ++ // CraftBukkit end ++ CompoundTag nbttagcompound2 = new CompoundTag(); ++ CompoundTag nbttagcompound3 = new CompoundTag(); ++ ++ entity.save(nbttagcompound3); ++ nbttagcompound2.putUUID("Attach", entity1.getUUID()); ++ nbttagcompound2.put("Entity", nbttagcompound3); ++ compound.put("RootVehicle", nbttagcompound2); ++ } ++ + compound.put("recipeBook", this.recipeBook.toNbt()); + compound.putString("Dimension", this.level().dimension().location().toString()); + if (this.respawnPosition != null) { +@@ -392,8 +534,33 @@ + .resultOrPartial(LOGGER::error) + .ifPresent(tag -> compound.put("SpawnDimension", tag)); + } ++ this.getBukkitEntity().setExtraData(compound); // CraftBukkit ++ + } + ++ // CraftBukkit start - World fallback code, either respawn location or global spawn ++ public void spawnIn(Level world) { ++ this.setLevel(world); ++ if (world == null) { ++ this.unsetRemoved(); ++ Vec3 position = null; ++ if (this.respawnDimension != null) { ++ world = this.server.getLevel(this.respawnDimension); ++ if (world != null && this.getRespawnPosition() != null) { ++ position = Player.findRespawnPositionAndUseSpawnBlock((ServerLevel) world, this.getRespawnPosition(), this.getRespawnAngle(), false, false).orElse(null); ++ } ++ } ++ if (world == null || position == null) { ++ world = ((CraftWorld) Bukkit.getServer().getWorlds().get(0)).getHandle(); ++ position = Vec3.atCenterOf(world.getSharedSpawnPos()); ++ } ++ this.setLevel(world); ++ this.setPos(position); ++ } ++ this.gameMode.setLevel((ServerLevel) world); ++ } ++ // CraftBukkit end ++ + public void setExperiencePoints(int experiencePoints) { + float f = (float)this.getXpNeededForNextLevel(); + float f1 = (f - 1.0F) / f; +@@ -451,6 +619,11 @@ + + @Override + public void tick() { ++ // CraftBukkit start ++ if (this.joining) { ++ this.joining = false; ++ } ++ // CraftBukkit end + this.gameMode.tick(); + this.wardenSpawnTracker.tick(); + this.spawnInvulnerableTime--; +@@ -503,10 +679,8 @@ + } + } + +- if (this.getHealth() != this.lastSentHealth +- || this.lastSentFood != this.foodData.getFoodLevel() +- || this.foodData.getSaturationLevel() == 0.0F != this.lastFoodSaturationZero) { +- this.connection.send(new ClientboundSetHealthPacket(this.getHealth(), this.foodData.getFoodLevel(), this.foodData.getSaturationLevel())); ++ if (this.getHealth() != this.lastSentHealth || this.lastSentFood != this.foodData.getFoodLevel() || this.foodData.getSaturationLevel() == 0.0F != this.lastFoodSaturationZero) { ++ this.connection.send(new ClientboundSetHealthPacket(this.getBukkitEntity().getScaledHealth(), this.foodData.getFoodLevel(), this.foodData.getSaturationLevel())); // CraftBukkit + this.lastSentHealth = this.getHealth(); + this.lastSentFood = this.foodData.getFoodLevel(); + this.lastFoodSaturationZero = this.foodData.getSaturationLevel() == 0.0F; +@@ -537,6 +711,12 @@ + this.updateScoreForCriteria(ObjectiveCriteria.EXPERIENCE, Mth.ceil((float)this.lastRecordedExperience)); + } + ++ // CraftBukkit start - Force max health updates ++ if (this.maxHealthCache != this.getMaxHealth()) { ++ this.getBukkitEntity().updateScaledHealth(); ++ } ++ // CraftBukkit end ++ + if (this.experienceLevel != this.lastRecordedLevel) { + this.lastRecordedLevel = this.experienceLevel; + this.updateScoreForCriteria(ObjectiveCriteria.LEVEL, Mth.ceil((float)this.lastRecordedLevel)); +@@ -550,11 +730,27 @@ + if (this.tickCount % 20 == 0) { + CriteriaTriggers.LOCATION.trigger(this); + } +- } catch (Throwable var4) { +- CrashReport crashReport = CrashReport.forThrowable(var4, "Ticking player"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Player being ticked"); +- this.fillCrashReportCategory(crashReportCategory); +- throw new ReportedException(crashReport); ++ ++ // CraftBukkit start - initialize oldLevel, fire PlayerLevelChangeEvent, and tick client-sided world border ++ if (this.oldLevel == -1) { ++ this.oldLevel = this.experienceLevel; ++ } ++ ++ if (this.oldLevel != this.experienceLevel) { ++ CraftEventFactory.callPlayerLevelChangeEvent(this.getBukkitEntity(), this.oldLevel, this.experienceLevel); ++ this.oldLevel = this.experienceLevel; ++ } ++ ++ if (this.getBukkitEntity().hasClientWorldBorder()) { ++ ((CraftWorldBorder) this.getBukkitEntity().getWorldBorder()).getHandle().tick(); ++ } ++ // CraftBukkit end ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking player"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Player being ticked"); ++ ++ this.fillCrashReportCategory(crashreportsystemdetails); ++ throw new ReportedException(crashreport); + } + } + +@@ -589,38 +787,28 @@ + } + + private void updateScoreForCriteria(ObjectiveCriteria criteria, int points) { +- this.getScoreboard().forAllObjectives(criteria, this, scoreAccess -> scoreAccess.set(points)); ++ // CraftBukkit - Use our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(criteria, this, (scoreaccess) -> { ++ scoreaccess.set(points); ++ }); + } + + @Override + public void die(DamageSource cause) { + this.gameEvent(GameEvent.ENTITY_DIE); +- boolean _boolean = this.level().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); +- if (_boolean) { +- Component deathMessage = this.getCombatTracker().getDeathMessage(); +- this.connection +- .send( +- new ClientboundPlayerCombatKillPacket(this.getId(), deathMessage), +- PacketSendListener.exceptionallySend( +- () -> { +- int i = 256; +- String string = deathMessage.getString(256); +- Component component = Component.translatable( +- "death.attack.message_too_long", Component.literal(string).withStyle(ChatFormatting.YELLOW) +- ); +- Component component1 = Component.translatable("death.attack.even_more_magic", this.getDisplayName()) +- .withStyle(style -> style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, component))); +- return new ClientboundPlayerCombatKillPacket(this.getId(), component1); +- } +- ) +- ); +- Team team = this.getTeam(); +- if (team == null || team.getDeathMessageVisibility() == Team.Visibility.ALWAYS) { +- this.server.getPlayerList().broadcastSystemMessage(deathMessage, false); +- } else if (team.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OTHER_TEAMS) { +- this.server.getPlayerList().broadcastSystemToTeam(this, deathMessage); +- } else if (team.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OWN_TEAM) { +- this.server.getPlayerList().broadcastSystemToAllExceptTeam(this, deathMessage); ++ boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); ++ // CraftBukkit start - fire PlayerDeathEvent ++ if (this.isRemoved()) { ++ return; ++ } ++ java.util.List loot = new java.util.ArrayList(this.getInventory().getContainerSize()); ++ boolean keepInventory = this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || this.isSpectator(); ++ ++ if (!keepInventory) { ++ for (ItemStack item : this.getInventory().getContents()) { ++ if (!item.isEmpty() && !EnchantmentHelper.hasVanishingCurse(item)) { ++ loot.add(CraftItemStack.asCraftMirror(item)); ++ } + } + } else { + this.connection.send(new ClientboundPlayerCombatKillPacket(this.getId(), CommonComponents.EMPTY)); +@@ -635,12 +875,17 @@ + this.dropAllDeathLoot(cause); + } + +- this.getScoreboard().forAllObjectives(ObjectiveCriteria.DEATH_COUNT, this, ScoreAccess::increment); +- LivingEntity killCredit = this.getKillCredit(); +- if (killCredit != null) { +- this.awardStat(Stats.ENTITY_KILLED_BY.get(killCredit.getType())); +- killCredit.awardKillScore(this, this.deathScore, cause); +- this.createWitherRose(killCredit); ++ this.setCamera(this); // Remove spectated target ++ // CraftBukkit end ++ ++ // CraftBukkit - Get our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(ObjectiveCriteria.DEATH_COUNT, this, ScoreAccess::increment); ++ LivingEntity entityliving = this.getKillCredit(); ++ ++ if (entityliving != null) { ++ this.awardStat(Stats.ENTITY_KILLED_BY.get(entityliving.getType())); ++ entityliving.awardKillScore(this, this.deathScore, cause); ++ this.createWitherRose(entityliving); + } + + this.level().broadcastEntityEvent(this, (byte)3); +@@ -668,10 +914,12 @@ + if (killed != this) { + super.awardKillScore(killed, scoreValue, damageSource); + this.increaseScore(scoreValue); +- this.getScoreboard().forAllObjectives(ObjectiveCriteria.KILL_COUNT_ALL, this, ScoreAccess::increment); ++ // CraftBukkit - Get our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(ObjectiveCriteria.KILL_COUNT_ALL, this, ScoreAccess::increment); + if (killed instanceof Player) { + this.awardStat(Stats.PLAYER_KILLS); +- this.getScoreboard().forAllObjectives(ObjectiveCriteria.KILL_COUNT_PLAYERS, this, ScoreAccess::increment); ++ // CraftBukkit - Get our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(ObjectiveCriteria.KILL_COUNT_PLAYERS, this, ScoreAccess::increment); + } else { + this.awardStat(Stats.MOB_KILLS); + } +@@ -682,12 +930,15 @@ + } + } + +- private void handleTeamKill(ScoreHolder scoreHolder, ScoreHolder scoreHolder1, ObjectiveCriteria[] objectiveCriterias) { +- PlayerTeam playersTeam = this.getScoreboard().getPlayersTeam(scoreHolder1.getScoreboardName()); +- if (playersTeam != null) { +- int id = playersTeam.getColor().getId(); +- if (id >= 0 && id < objectiveCriterias.length) { +- this.getScoreboard().forAllObjectives(objectiveCriterias[id], scoreHolder, ScoreAccess::increment); ++ private void handleTeamKill(ScoreHolder scoreholder, ScoreHolder scoreholder1, ObjectiveCriteria[] aiscoreboardcriteria) { ++ PlayerTeam scoreboardteam = this.getScoreboard().getPlayersTeam(scoreholder1.getScoreboardName()); ++ ++ if (scoreboardteam != null) { ++ int i = scoreboardteam.getColor().getId(); ++ ++ if (i >= 0 && i < aiscoreboardcriteria.length) { ++ // CraftBukkit - Get our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(aiscoreboardcriteria[i], scoreholder, ScoreAccess::increment); + } + } + } +@@ -721,16 +988,20 @@ + } + + private boolean isPvpAllowed() { +- return this.server.isPvpAllowed(); ++ // CraftBukkit - this.server.isPvpAllowed() -> this.world.pvpMode ++ return this.level().pvpMode; + } + + @Nullable + @Override + protected PortalInfo findDimensionEntryPoint(ServerLevel destination) { +- PortalInfo portalInfo = super.findDimensionEntryPoint(destination); +- if (portalInfo != null && this.level().dimension() == Level.OVERWORLD && destination.dimension() == Level.END) { +- Vec3 vec3 = portalInfo.pos.add(0.0, -1.0, 0.0); +- return new PortalInfo(vec3, Vec3.ZERO, 90.0F, 0.0F); ++ PortalInfo shapedetectorshape = super.findDimensionEntryPoint(destination); ++ destination = (shapedetectorshape == null) ? destination : shapedetectorshape.world; // CraftBukkit ++ ++ if (shapedetectorshape != null && this.level().getTypeKey() == LevelStem.OVERWORLD && destination != null && destination.getTypeKey() == LevelStem.END) { // CraftBukkit ++ Vec3 vec3d = shapedetectorshape.pos.add(0.0D, -1.0D, 0.0D); ++ ++ return new PortalInfo(vec3d, Vec3.ZERO, 90.0F, 0.0F, destination, shapedetectorshape.portalEventInfo); // CraftBukkit + } else { + return portalInfo; + } +@@ -739,10 +1010,20 @@ + @Nullable + @Override + public Entity changeDimension(ServerLevel server) { +- this.isChangingDimension = true; +- ServerLevel serverLevel = this.serverLevel(); +- ResourceKey resourceKey = serverLevel.dimension(); +- if (resourceKey == Level.END && server.dimension() == Level.OVERWORLD) { ++ // CraftBukkit start ++ return changeDimension(server, TeleportCause.UNKNOWN); ++ } ++ ++ @Nullable ++ public Entity changeDimension(ServerLevel worldserver, PlayerTeleportEvent.TeleportCause cause) { ++ // CraftBukkit end ++ if (this.isSleeping()) return this; // CraftBukkit - SPIGOT-3154 ++ // this.isChangingDimension = true; // CraftBukkit - Moved down and into PlayerList#changeDimension ++ ServerLevel worldserver1 = this.serverLevel(); ++ ResourceKey resourcekey = worldserver1.getTypeKey(); // CraftBukkit ++ ++ if (resourcekey == LevelStem.END && worldserver != null && worldserver.getTypeKey() == LevelStem.OVERWORLD) { // CraftBukkit ++ this.isChangingDimension = true; // CraftBukkit - Moved down from above + this.unRide(); + this.serverLevel().removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); + if (!this.wonGame) { +@@ -753,26 +1034,61 @@ + + return this; + } else { +- LevelData levelData = server.getLevelData(); +- this.connection.send(new ClientboundRespawnPacket(this.createCommonSpawnInfo(server), (byte)3)); +- this.connection.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked())); +- PlayerList playerList = this.server.getPlayerList(); +- playerList.sendPlayerPermissionLevel(this); +- serverLevel.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); ++ // CraftBukkit start ++ /* ++ WorldData worlddata = worldserver.getLevelData(); ++ ++ this.connection.send(new PacketPlayOutRespawn(this.createCommonSpawnInfo(worldserver), (byte) 3)); ++ this.connection.send(new PacketPlayOutServerDifficulty(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); ++ PlayerList playerlist = this.server.getPlayerList(); ++ ++ playerlist.sendPlayerPermissionLevel(this); ++ worldserver1.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); + this.unsetRemoved(); +- PortalInfo portalInfo = this.findDimensionEntryPoint(server); +- if (portalInfo != null) { +- serverLevel.getProfiler().push("moving"); +- if (resourceKey == Level.OVERWORLD && server.dimension() == Level.NETHER) { ++ */ ++ // CraftBukkit end ++ PortalInfo shapedetectorshape = this.findDimensionEntryPoint(worldserver); ++ ++ if (shapedetectorshape != null) { ++ worldserver1.getProfiler().push("moving"); ++ worldserver = shapedetectorshape.world; // CraftBukkit ++ if (worldserver == null) { } else // CraftBukkit - empty to fall through to null to event ++ if (resourcekey == LevelStem.OVERWORLD && worldserver.getTypeKey() == LevelStem.NETHER) { // CraftBukkit + this.enteredNetherPosition = this.position(); +- } else if (server.dimension() == Level.END) { +- this.createEndPlatform(server, BlockPos.containing(portalInfo.pos)); ++ } else if (worldserver.getTypeKey() == LevelStem.END && shapedetectorshape.portalEventInfo != null && shapedetectorshape.portalEventInfo.getCanCreatePortal()) { // CraftBukkit ++ this.createEndPlatform(worldserver, BlockPos.containing(shapedetectorshape.pos)); + } ++ // CraftBukkit start ++ } else { ++ return null; ++ } ++ Location enter = this.getBukkitEntity().getLocation(); ++ Location exit = (worldserver == null) ? null : CraftLocation.toBukkit(shapedetectorshape.pos, worldserver.getWorld(), shapedetectorshape.yRot, shapedetectorshape.xRot); ++ PlayerTeleportEvent tpEvent = new PlayerTeleportEvent(this.getBukkitEntity(), enter, exit, cause); ++ Bukkit.getServer().getPluginManager().callEvent(tpEvent); ++ if (tpEvent.isCancelled() || tpEvent.getTo() == null) { ++ return null; ++ } ++ exit = tpEvent.getTo(); ++ worldserver = ((CraftWorld) exit.getWorld()).getHandle(); ++ // CraftBukkit end + +- serverLevel.getProfiler().pop(); +- serverLevel.getProfiler().push("placing"); +- this.setServerLevel(server); +- this.connection.teleport(portalInfo.pos.x, portalInfo.pos.y, portalInfo.pos.z, portalInfo.yRot, portalInfo.xRot); ++ worldserver1.getProfiler().pop(); ++ worldserver1.getProfiler().push("placing"); ++ if (true) { // CraftBukkit ++ this.isChangingDimension = true; // CraftBukkit - Set teleport invulnerability only if player changing worlds ++ ++ this.connection.send(new ClientboundRespawnPacket(this.createCommonSpawnInfo(worldserver), (byte) 3)); ++ this.connection.send(new ClientboundChangeDifficultyPacket(this.level().getDifficulty(), this.level().getLevelData().isDifficultyLocked())); ++ PlayerList playerlist = this.server.getPlayerList(); ++ ++ playerlist.sendPlayerPermissionLevel(this); ++ worldserver1.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); ++ this.unsetRemoved(); ++ ++ // CraftBukkit end ++ this.setServerLevel(worldserver); ++ this.connection.teleport(exit); // CraftBukkit - use internal teleport without event + this.connection.resetPosition(); + server.addDuringPortalTeleport(this); + serverLevel.getProfiler().pop(); +@@ -789,50 +1108,90 @@ + this.lastSentExp = -1; + this.lastSentHealth = -1.0F; + this.lastSentFood = -1; ++ ++ // CraftBukkit start ++ PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.getBukkitEntity(), worldserver1.getWorld()); ++ this.level().getCraftServer().getPluginManager().callEvent(changeEvent); ++ // CraftBukkit end + } + + return this; + } + } + ++ // CraftBukkit start ++ @Override ++ protected CraftPortalEvent callPortalEvent(Entity entity, ServerLevel exitWorldServer, Vec3 exitPosition, TeleportCause cause, int searchRadius, int creationRadius) { ++ Location enter = this.getBukkitEntity().getLocation(); ++ Location exit = CraftLocation.toBukkit(exitPosition, exitWorldServer.getWorld(), getYRot(), getXRot()); ++ PlayerPortalEvent event = new PlayerPortalEvent(this.getBukkitEntity(), enter, exit, cause, searchRadius, true, creationRadius); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null) { ++ return null; ++ } ++ return new CraftPortalEvent(event); ++ } ++ // CraftBukkit end ++ + private void createEndPlatform(ServerLevel level, BlockPos pos) { +- BlockPos.MutableBlockPos mutableBlockPos = pos.mutable(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(level); // CraftBukkit + +- for (int i = -2; i <= 2; i++) { +- for (int i1 = -2; i1 <= 2; i1++) { +- for (int i2 = -1; i2 < 3; i2++) { +- BlockState blockState = i2 == -1 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); +- level.setBlockAndUpdate(mutableBlockPos.set(pos).move(i1, i2, i), blockState); ++ for (int i = -2; i <= 2; ++i) { ++ for (int j = -2; j <= 2; ++j) { ++ for (int k = -1; k < 3; ++k) { ++ IBlockData iblockdata = k == -1 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); ++ ++ blockList.setBlock(blockposition_mutableblockposition.set(pos).move(j, k, i), iblockdata, 3); // CraftBukkit + } + } + } ++ // CraftBukkit start - call portal event ++ org.bukkit.event.world.PortalCreateEvent portalEvent = new org.bukkit.event.world.PortalCreateEvent((List) (List) blockList.getList(), level.getWorld(), this.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM); ++ level.getCraftServer().getPluginManager().callEvent(portalEvent); ++ if (!portalEvent.isCancelled()) { ++ blockList.updateList(); ++ } ++ // CraftBukkit end ++ + } + + @Override +- protected Optional getExitPortal(ServerLevel destination, BlockPos findFrom, boolean isToNether, WorldBorder worldBorder) { +- Optional optional = super.getExitPortal(destination, findFrom, isToNether, worldBorder); +- if (optional.isPresent()) { ++ protected Optional getExitPortal(ServerLevel worldserver, BlockPos blockposition, boolean flag, WorldBorder worldborder, int searchRadius, boolean canCreatePortal, int createRadius) { // CraftBukkit ++ Optional optional = super.getExitPortal(worldserver, blockposition, flag, worldborder, searchRadius, canCreatePortal, createRadius); // CraftBukkit ++ ++ if (optional.isPresent() || !canCreatePortal) { // CraftBukkit + return optional; + } else { +- Direction.Axis axis = this.level().getBlockState(this.portalEntrancePos).getOptionalValue(NetherPortalBlock.AXIS).orElse(Direction.Axis.X); +- Optional optional1 = destination.getPortalForcer().createPortal(findFrom, axis); ++ Direction.Axis enumdirection_enumaxis = (Direction.Axis) this.level().getBlockState(this.portalEntrancePos).getOptionalValue(NetherPortalBlock.AXIS).orElse(Direction.Axis.X); ++ Optional optional1 = worldserver.getPortalForcer().createPortal(blockposition, enumdirection_enumaxis, this, createRadius); // CraftBukkit ++ + if (optional1.isEmpty()) { +- LOGGER.error("Unable to create a portal, likely target out of worldborder"); ++ // EntityPlayer.LOGGER.error("Unable to create a portal, likely target out of worldborder"); // CraftBukkit + } + + return optional1; + } + } + +- private void triggerDimensionChangeTriggers(ServerLevel level) { +- ResourceKey resourceKey = level.dimension(); +- ResourceKey resourceKey1 = this.level().dimension(); +- CriteriaTriggers.CHANGED_DIMENSION.trigger(this, resourceKey, resourceKey1); +- if (resourceKey == Level.NETHER && resourceKey1 == Level.OVERWORLD && this.enteredNetherPosition != null) { ++ public void triggerDimensionChangeTriggers(ServerLevel level) { ++ ResourceKey resourcekey = level.dimension(); ++ ResourceKey resourcekey1 = this.level().dimension(); ++ // CraftBukkit start ++ ResourceKey maindimensionkey = CraftDimensionUtil.getMainDimensionKey(level); ++ ResourceKey maindimensionkey1 = CraftDimensionUtil.getMainDimensionKey(this.level()); ++ ++ CriteriaTriggers.CHANGED_DIMENSION.trigger(this, maindimensionkey, maindimensionkey1); ++ if (maindimensionkey != resourcekey || maindimensionkey1 != resourcekey1) { ++ CriteriaTriggers.CHANGED_DIMENSION.trigger(this, resourcekey, resourcekey1); ++ } ++ ++ if (maindimensionkey == Level.NETHER && maindimensionkey1 == Level.OVERWORLD && this.enteredNetherPosition != null) { ++ // CraftBukkit end + CriteriaTriggers.NETHER_TRAVEL.trigger(this, this.enteredNetherPosition); + } + +- if (resourceKey1 != Level.NETHER) { ++ if (maindimensionkey1 != Level.NETHER) { // CraftBukkit + this.enteredNetherPosition = null; + } + } +@@ -848,34 +1208,31 @@ + this.containerMenu.broadcastChanges(); + } + +- @Override +- public Either startSleepInBed(BlockPos at) { +- Direction direction = this.level().getBlockState(at).getValue(HorizontalDirectionalBlock.FACING); +- if (this.isSleeping() || !this.isAlive()) { +- return Either.left(Player.BedSleepingProblem.OTHER_PROBLEM); +- } else if (!this.level().dimensionType().natural()) { +- return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_HERE); +- } else if (!this.bedInRange(at, direction)) { +- return Either.left(Player.BedSleepingProblem.TOO_FAR_AWAY); +- } else if (this.bedBlocked(at, direction)) { +- return Either.left(Player.BedSleepingProblem.OBSTRUCTED); +- } else { +- this.setRespawnPosition(this.level().dimension(), at, this.getYRot(), false, true); +- if (this.level().isDay()) { +- return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_NOW); ++ // CraftBukkit start - moved bed result checks from below into separate method ++ private Either getBedResult(BlockPos blockposition, Direction enumdirection) { ++ if (!this.isSleeping() && this.isAlive()) { ++ if (!this.level().dimensionType().natural() || !this.level().dimensionType().bedWorks()) { ++ return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_HERE); ++ } else if (!this.bedInRange(blockposition, enumdirection)) { ++ return Either.left(Player.BedSleepingProblem.TOO_FAR_AWAY); ++ } else if (this.bedBlocked(blockposition, enumdirection)) { ++ return Either.left(Player.BedSleepingProblem.OBSTRUCTED); + } else { +- if (!this.isCreative()) { +- double d = 8.0; +- double d1 = 5.0; +- Vec3 vec3 = Vec3.atBottomCenterOf(at); +- List entitiesOfClass = this.level() +- .getEntitiesOfClass( +- Monster.class, +- new AABB(vec3.x() - 8.0, vec3.y() - 5.0, vec3.z() - 8.0, vec3.x() + 8.0, vec3.y() + 5.0, vec3.z() + 8.0), +- monster -> monster.isPreventingPlayerRest(this) +- ); +- if (!entitiesOfClass.isEmpty()) { +- return Either.left(Player.BedSleepingProblem.NOT_SAFE); ++ this.setRespawnPosition(this.level().dimension(), blockposition, this.getYRot(), false, true, PlayerSpawnChangeEvent.Cause.BED); // CraftBukkit ++ if (this.level().isDay()) { ++ return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_NOW); ++ } else { ++ if (!this.isCreative()) { ++ double d0 = 8.0D; ++ double d1 = 5.0D; ++ Vec3 vec3d = Vec3.atBottomCenterOf(blockposition); ++ List list = this.level().getEntitiesOfClass(Monster.class, new AABB(vec3d.x() - 8.0D, vec3d.y() - 5.0D, vec3d.z() - 8.0D, vec3d.x() + 8.0D, vec3d.y() + 5.0D, vec3d.z() + 8.0D), (entitymonster) -> { ++ return entitymonster.isPreventingPlayerRest(this); ++ }); ++ ++ if (!list.isEmpty()) { ++ return Either.left(Player.BedSleepingProblem.NOT_SAFE); ++ } + } + } + +@@ -891,6 +1278,7 @@ + return either; + } + } ++ // CraftBukkit end + } + + @Override +@@ -915,13 +1305,31 @@ + + @Override + public void stopSleepInBed(boolean wakeImmediately, boolean updateLevelForSleepingPlayers) { ++ if (!this.isSleeping()) return; // CraftBukkit - Can't leave bed if not in one! ++ // CraftBukkit start - fire PlayerBedLeaveEvent ++ CraftPlayer player = this.getBukkitEntity(); ++ BlockPos bedPosition = this.getSleepingPos().orElse(null); ++ ++ org.bukkit.block.Block bed; ++ if (bedPosition != null) { ++ bed = this.level().getWorld().getBlockAt(bedPosition.getX(), bedPosition.getY(), bedPosition.getZ()); ++ } else { ++ bed = this.level().getWorld().getBlockAt(player.getLocation()); ++ } ++ ++ PlayerBedLeaveEvent event = new PlayerBedLeaveEvent(player, bed, true); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + if (this.isSleeping()) { + this.serverLevel().getChunkSource().broadcastAndSend(this, new ClientboundAnimatePacket(this, 2)); + } + + super.stopSleepInBed(wakeImmediately, updateLevelForSleepingPlayers); + if (this.connection != null) { +- this.connection.teleport(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); ++ this.connection.teleport(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot(), TeleportCause.EXIT_BED); // CraftBukkit + } + } + +@@ -968,8 +1379,9 @@ + this.connection.send(new ClientboundOpenSignEditorPacket(signEntity.getBlockPos(), isFrontText)); + } + +- private void nextContainerCounter() { ++ public int nextContainerCounter() { // CraftBukkit - void -> int + this.containerCounter = this.containerCounter % 100 + 1; ++ return containerCounter; // CraftBukkit + } + + @Override +@@ -977,23 +1389,47 @@ + if (menu == null) { + return OptionalInt.empty(); + } else { ++ // CraftBukkit start - SPIGOT-6552: Handle inventory closing in CraftEventFactory#callInventoryOpenEvent(...) ++ /* + if (this.containerMenu != this.inventoryMenu) { + this.closeContainer(); + } ++ */ ++ // CraftBukkit end + + this.nextContainerCounter(); +- AbstractContainerMenu abstractContainerMenu = menu.createMenu(this.containerCounter, this.getInventory(), this); +- if (abstractContainerMenu == null) { ++ AbstractContainerMenu container = menu.createMenu(this.containerCounter, this.getInventory(), this); ++ ++ // CraftBukkit start - Inventory open hook ++ if (container != null) { ++ container.setTitle(menu.getDisplayName()); ++ ++ boolean cancelled = false; ++ container = CraftEventFactory.callInventoryOpenEvent(this, container, cancelled); ++ if (container == null && !cancelled) { // Let pre-cancelled events fall through ++ // SPIGOT-5263 - close chest if cancelled ++ if (menu instanceof Container) { ++ ((Container) menu).stopOpen(this); ++ } else if (menu instanceof ChestBlock.DoubleInventory) { ++ // SPIGOT-5355 - double chests too :( ++ ((ChestBlock.DoubleInventory) menu).inventorylargechest.stopOpen(this); ++ } ++ return OptionalInt.empty(); ++ } ++ } ++ // CraftBukkit end ++ if (container == null) { + if (this.isSpectator()) { + this.displayClientMessage(Component.translatable("container.spectatorCantOpen").withStyle(ChatFormatting.RED), true); + } + + return OptionalInt.empty(); + } else { +- this.connection +- .send(new ClientboundOpenScreenPacket(abstractContainerMenu.containerId, abstractContainerMenu.getType(), menu.getDisplayName())); +- this.initMenu(abstractContainerMenu); +- this.containerMenu = abstractContainerMenu; ++ // CraftBukkit start ++ this.containerMenu = container; ++ this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); ++ // CraftBukkit end ++ this.initMenu(container); + return OptionalInt.of(this.containerCounter); + } + } +@@ -1006,13 +1442,24 @@ + + @Override + public void openHorseInventory(AbstractHorse horse, Container inventory) { ++ // CraftBukkit start - Inventory open hook ++ this.nextContainerCounter(); ++ AbstractContainerMenu container = new HorseInventoryMenu(this.containerCounter, this.getInventory(), inventory, horse); ++ container.setTitle(horse.getDisplayName()); ++ container = CraftEventFactory.callInventoryOpenEvent(this, container); ++ ++ if (container == null) { ++ inventory.stopOpen(this); ++ return; ++ } ++ // CraftBukkit end + if (this.containerMenu != this.inventoryMenu) { + this.closeContainer(); + } + +- this.nextContainerCounter(); ++ // this.nextContainerCounter(); // CraftBukkit - moved up + this.connection.send(new ClientboundHorseScreenOpenPacket(this.containerCounter, inventory.getContainerSize(), horse.getId())); +- this.containerMenu = new HorseInventoryMenu(this.containerCounter, this.getInventory(), inventory, horse); ++ this.containerMenu = container; // CraftBukkit + this.initMenu(this.containerMenu); + } + +@@ -1034,6 +1482,7 @@ + + @Override + public void closeContainer() { ++ CraftEventFactory.handleInventoryCloseEvent(this); // CraftBukkit + this.connection.send(new ClientboundContainerClosePacket(this.containerMenu.containerId)); + this.doCloseContainer(); + } +@@ -1056,6 +1505,16 @@ + } + + this.jumping = jumping; ++ // CraftBukkit start ++ if (sneaking != this.isShiftKeyDown()) { ++ PlayerToggleSneakEvent event = new PlayerToggleSneakEvent(this.getBukkitEntity(), sneaking); ++ this.server.server.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + this.setShiftKeyDown(sneaking); + } + } +@@ -1081,22 +1545,22 @@ + public void checkMovementStatistics(double d, double d1, double d2) { + if (!this.isPassenger() && !didNotMove(d, d1, d2)) { + if (this.isSwimming()) { +- int rounded = Math.round((float)Math.sqrt(d * d + d1 * d1 + d2 * d2) * 100.0F); +- if (rounded > 0) { +- this.awardStat(Stats.SWIM_ONE_CM, rounded); +- this.causeFoodExhaustion(0.01F * (float)rounded * 0.01F); ++ i = Math.round((float) Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2) * 100.0F); ++ if (i > 0) { ++ this.awardStat(Stats.SWIM_ONE_CM, i); ++ this.causeFoodExhaustion(0.01F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.SWIM); // CraftBukkit - EntityExhaustionEvent + } + } else if (this.isEyeInFluid(FluidTags.WATER)) { +- int rounded = Math.round((float)Math.sqrt(d * d + d1 * d1 + d2 * d2) * 100.0F); +- if (rounded > 0) { +- this.awardStat(Stats.WALK_UNDER_WATER_ONE_CM, rounded); +- this.causeFoodExhaustion(0.01F * (float)rounded * 0.01F); ++ i = Math.round((float) Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2) * 100.0F); ++ if (i > 0) { ++ this.awardStat(Stats.WALK_UNDER_WATER_ONE_CM, i); ++ this.causeFoodExhaustion(0.01F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.WALK_UNDERWATER); // CraftBukkit - EntityExhaustionEvent + } + } else if (this.isInWater()) { +- int rounded = Math.round((float)Math.sqrt(d * d + d2 * d2) * 100.0F); +- if (rounded > 0) { +- this.awardStat(Stats.WALK_ON_WATER_ONE_CM, rounded); +- this.causeFoodExhaustion(0.01F * (float)rounded * 0.01F); ++ i = Math.round((float) Math.sqrt(d0 * d0 + d2 * d2) * 100.0F); ++ if (i > 0) { ++ this.awardStat(Stats.WALK_ON_WATER_ONE_CM, i); ++ this.causeFoodExhaustion(0.01F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.WALK_ON_WATER); // CraftBukkit - EntityExhaustionEvent + } + } else if (this.onClimbable()) { + if (d1 > 0.0) { +@@ -1106,14 +1570,14 @@ + int rounded = Math.round((float)Math.sqrt(d * d + d2 * d2) * 100.0F); + if (rounded > 0) { + if (this.isSprinting()) { +- this.awardStat(Stats.SPRINT_ONE_CM, rounded); +- this.causeFoodExhaustion(0.1F * (float)rounded * 0.01F); ++ this.awardStat(Stats.SPRINT_ONE_CM, i); ++ this.causeFoodExhaustion(0.1F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.SPRINT); // CraftBukkit - EntityExhaustionEvent + } else if (this.isCrouching()) { +- this.awardStat(Stats.CROUCH_ONE_CM, rounded); +- this.causeFoodExhaustion(0.0F * (float)rounded * 0.01F); ++ this.awardStat(Stats.CROUCH_ONE_CM, i); ++ this.causeFoodExhaustion(0.0F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.CROUCH); // CraftBukkit - EntityExhaustionEvent + } else { +- this.awardStat(Stats.WALK_ONE_CM, rounded); +- this.causeFoodExhaustion(0.0F * (float)rounded * 0.01F); ++ this.awardStat(Stats.WALK_ONE_CM, i); ++ this.causeFoodExhaustion(0.0F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.WALK); // CraftBukkit - EntityExhaustionEvent + } + } + } else if (this.isFallFlying()) { +@@ -1159,7 +1628,7 @@ + @Override + public void resetStat(Stat stat) { + this.stats.setValue(this, stat, 0); +- this.getScoreboard().forAllObjectives(stat, this, ScoreAccess::reset); ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(stat, this, ScoreAccess::reset); // CraftBukkit - Get our scores instead + } + + @Override +@@ -1205,6 +1676,7 @@ + + public void resetSentInfo() { + this.lastSentHealth = -1.0E8F; ++ this.lastSentExp = -1; // CraftBukkit - Added to reset + } + + @Override +@@ -1260,7 +1734,7 @@ + this.lastSentExp = -1; + this.lastSentHealth = -1.0F; + this.lastSentFood = -1; +- this.recipeBook.copyOverData(that.recipeBook); ++ // this.recipeBook.copyOverData(entityplayer.recipeBook); // CraftBukkit + this.seenCredits = that.seenCredits; + this.enteredNetherPosition = that.enteredNetherPosition; + this.chunkTrackingView = that.chunkTrackingView; +@@ -1310,18 +1784,25 @@ + } + + @Override +- public boolean teleportTo(ServerLevel level, double x, double y, double z, Set relativeMovements, float yRot, float xRot) { +- ChunkPos chunkPos = new ChunkPos(BlockPos.containing(x, y, z)); +- level.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, chunkPos, 1, this.getId()); ++ public boolean teleportTo(ServerLevel level, double x, double d1, double y, Set set, float z, float f1) { ++ // CraftBukkit start ++ return teleportTo(level, x, d1, y, set, z, f1, TeleportCause.UNKNOWN); ++ } ++ ++ public boolean teleportTo(ServerLevel worldserver, double d0, double d1, double d2, Set set, float f, float f1, TeleportCause cause) { ++ // CraftBukkit end ++ ChunkPos chunkcoordintpair = new ChunkPos(BlockPos.containing(d0, d1, d2)); ++ ++ worldserver.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, chunkcoordintpair, 1, this.getId()); + this.stopRiding(); + if (this.isSleeping()) { + this.stopSleepInBed(true, true); + } + +- if (level == this.level()) { +- this.connection.teleport(x, y, z, yRot, xRot, relativeMovements); ++ if (worldserver == this.level()) { ++ this.connection.teleport(d0, d1, d2, f, f1, set, cause); // CraftBukkit + } else { +- this.teleportTo(level, x, y, z, yRot, xRot); ++ this.teleportTo(worldserver, d0, d1, d2, f, f1, cause); // CraftBukkit + } + + this.setYHeadRot(yRot); +@@ -1424,15 +1905,25 @@ + : ""; + } + +- public void updateOptions(ClientInformation clientInformation) { +- this.language = clientInformation.language(); +- this.requestedViewDistance = clientInformation.viewDistance(); +- this.chatVisibility = clientInformation.chatVisibility(); +- this.canChatColor = clientInformation.chatColors(); +- this.textFilteringEnabled = clientInformation.textFilteringEnabled(); +- this.allowsListing = clientInformation.allowsListing(); +- this.getEntityData().set(DATA_PLAYER_MODE_CUSTOMISATION, (byte)clientInformation.modelCustomisation()); +- this.getEntityData().set(DATA_PLAYER_MAIN_HAND, (byte)clientInformation.mainHand().getId()); ++ public void updateOptions(ClientInformation clientinformation) { ++ // CraftBukkit start ++ if (getMainArm() != clientinformation.mainHand()) { ++ PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(getBukkitEntity(), getMainArm() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT); ++ this.server.server.getPluginManager().callEvent(event); ++ } ++ if (!this.language.equals(clientinformation.language())) { ++ PlayerLocaleChangeEvent event = new PlayerLocaleChangeEvent(getBukkitEntity(), clientinformation.language()); ++ this.server.server.getPluginManager().callEvent(event); ++ } ++ // CraftBukkit end ++ this.language = clientinformation.language(); ++ this.requestedViewDistance = clientinformation.viewDistance(); ++ this.chatVisibility = clientinformation.chatVisibility(); ++ this.canChatColor = clientinformation.chatColors(); ++ this.textFilteringEnabled = clientinformation.textFilteringEnabled(); ++ this.allowsListing = clientinformation.allowsListing(); ++ this.getEntityData().set(ServerPlayer.DATA_PLAYER_MODE_CUSTOMISATION, (byte) clientinformation.modelCustomisation()); ++ this.getEntityData().set(ServerPlayer.DATA_PLAYER_MAIN_HAND, (byte) clientinformation.mainHand().getId()); + } + + public ClientInformation clientInformation() { +@@ -1504,11 +1990,16 @@ + } + + public void setCamera(@Nullable Entity entityToSpectate) { +- Entity camera = this.getCamera(); +- this.camera = (Entity)(entityToSpectate == null ? this : entityToSpectate); +- if (camera != this.camera) { +- if (this.camera.level() instanceof ServerLevel serverLevel) { +- this.teleportTo(serverLevel, this.camera.getX(), this.camera.getY(), this.camera.getZ(), Set.of(), this.getYRot(), this.getXRot()); ++ Entity entity1 = this.getCamera(); ++ ++ this.camera = (Entity) (entityToSpectate == null ? this : entityToSpectate); ++ if (entity1 != this.camera) { ++ Level world = this.camera.level(); ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ ++ this.teleportTo(worldserver, this.camera.getX(), this.camera.getY(), this.camera.getZ(), Set.of(), this.getYRot(), this.getXRot(), TeleportCause.SPECTATE); // CraftBukkit + } + + if (entityToSpectate != null) { +@@ -1542,7 +2036,7 @@ + + @Nullable + public Component getTabListDisplayName() { +- return null; ++ return listName; // CraftBukkit + } + + @Override +@@ -1563,11 +2057,18 @@ + return this.advancements; + } + +- public void teleportTo(ServerLevel newLevel, double x, double y, double z, float yaw, float pitch) { ++ // CraftBukkit start ++ public void teleportTo(ServerLevel newLevel, double x, double d1, double y, float f, float z) { ++ this.teleportTo(newLevel, x, d1, y, f, z, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.UNKNOWN); ++ } ++ ++ public void teleportTo(ServerLevel worldserver, double d0, double d1, double d2, float f, float f1, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { ++ // CraftBukkit end + this.setCamera(this); + this.stopRiding(); +- if (newLevel == this.level()) { +- this.connection.teleport(x, y, z, yaw, pitch); ++ /* CraftBukkit start - replace with bukkit handling for multi-world ++ if (worldserver == this.level()) { ++ this.connection.teleport(d0, d1, d2, f, f1); + } else { + ServerLevel serverLevel = this.serverLevel(); + LevelData levelData = newLevel.getLevelData(); +@@ -1584,6 +2086,10 @@ + this.server.getPlayerList().sendLevelInfo(this, newLevel); + this.server.getPlayerList().sendAllPlayerInfo(this); + } ++ */ ++ this.getBukkitEntity().teleport(new Location(worldserver.getWorld(), d0, d1, d2, f, f1), cause); ++ // CraftBukkit end ++ + } + + @Nullable +@@ -1604,9 +2110,36 @@ + } + + public void setRespawnPosition(ResourceKey dimension, @Nullable BlockPos position, float angle, boolean forced, boolean sendMessage) { +- if (position != null) { +- boolean flag = position.equals(this.respawnPosition) && dimension.equals(this.respawnDimension); +- if (sendMessage && !flag) { ++ // CraftBukkit start ++ this.setRespawnPosition(dimension, position, angle, forced, sendMessage, PlayerSpawnChangeEvent.Cause.UNKNOWN); ++ } ++ ++ public void setRespawnPosition(ResourceKey resourcekey, @Nullable BlockPos blockposition, float f, boolean flag, boolean flag1, PlayerSpawnChangeEvent.Cause cause) { ++ ServerLevel newWorld = this.server.getLevel(resourcekey); ++ Location newSpawn = (blockposition != null) ? CraftLocation.toBukkit(blockposition, newWorld.getWorld(), f, 0) : null; ++ ++ PlayerSpawnChangeEvent event = new PlayerSpawnChangeEvent(this.getBukkitEntity(), newSpawn, flag, cause); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ newSpawn = event.getNewSpawn(); ++ flag = event.isForced(); ++ ++ if (newSpawn != null) { ++ resourcekey = ((CraftWorld) newSpawn.getWorld()).getHandle().dimension(); ++ blockposition = BlockPos.containing(newSpawn.getX(), newSpawn.getY(), newSpawn.getZ()); ++ f = newSpawn.getYaw(); ++ } else { ++ resourcekey = Level.OVERWORLD; ++ blockposition = null; ++ f = 0.0F; ++ } ++ // CraftBukkit end ++ if (blockposition != null) { ++ boolean flag2 = blockposition.equals(this.respawnPosition) && resourcekey.equals(this.respawnDimension); ++ ++ if (flag1 && !flag2) { + this.sendSystemMessage(Component.translatable("block.minecraft.set_spawn")); + } + +@@ -1805,4 +2341,146 @@ + this.getPortalCooldown() + ); + } ++ ++ // CraftBukkit start - Add per-player time and weather. ++ public long timeOffset = 0; ++ public boolean relativeTime = true; ++ ++ public long getPlayerTime() { ++ if (this.relativeTime) { ++ // Adds timeOffset to the current server time. ++ return this.level().getDayTime() + this.timeOffset; ++ } else { ++ // Adds timeOffset to the beginning of this day. ++ return this.level().getDayTime() - (this.level().getDayTime() % 24000) + this.timeOffset; ++ } ++ } ++ ++ public WeatherType weather = null; ++ ++ public WeatherType getPlayerWeather() { ++ return this.weather; ++ } ++ ++ public void setPlayerWeather(WeatherType type, boolean plugin) { ++ if (!plugin && this.weather != null) { ++ return; ++ } ++ ++ if (plugin) { ++ this.weather = type; ++ } ++ ++ if (type == WeatherType.DOWNFALL) { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.STOP_RAINING, 0)); ++ } else { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.START_RAINING, 0)); ++ } ++ } ++ ++ private float pluginRainPosition; ++ private float pluginRainPositionPrevious; ++ ++ public void updateWeather(float oldRain, float newRain, float oldThunder, float newThunder) { ++ if (this.weather == null) { ++ // Vanilla ++ if (oldRain != newRain) { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, newRain)); ++ } ++ } else { ++ // Plugin ++ if (pluginRainPositionPrevious != pluginRainPosition) { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, pluginRainPosition)); ++ } ++ } ++ ++ if (oldThunder != newThunder) { ++ if (weather == WeatherType.DOWNFALL || weather == null) { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, newThunder)); ++ } else { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, 0)); ++ } ++ } ++ } ++ ++ public void tickWeather() { ++ if (this.weather == null) return; ++ ++ pluginRainPositionPrevious = pluginRainPosition; ++ if (weather == WeatherType.DOWNFALL) { ++ pluginRainPosition += 0.01; ++ } else { ++ pluginRainPosition -= 0.01; ++ } ++ ++ pluginRainPosition = Mth.clamp(pluginRainPosition, 0.0F, 1.0F); ++ } ++ ++ public void resetPlayerWeather() { ++ this.weather = null; ++ this.setPlayerWeather(this.level().getLevelData().isRaining() ? WeatherType.DOWNFALL : WeatherType.CLEAR, false); ++ } ++ ++ @Override ++ public String toString() { ++ return super.toString() + "(" + this.getScoreboardName() + " at " + this.getX() + "," + this.getY() + "," + this.getZ() + ")"; ++ } ++ ++ // SPIGOT-1903, MC-98153 ++ public void forceSetPositionRotation(double x, double y, double z, float yaw, float pitch) { ++ this.moveTo(x, y, z, yaw, pitch); ++ this.connection.resetPosition(); ++ } ++ ++ @Override ++ public boolean isImmobile() { ++ return super.isImmobile() || !getBukkitEntity().isOnline(); ++ } ++ ++ @Override ++ public Scoreboard getScoreboard() { ++ return getBukkitEntity().getScoreboard().getHandle(); ++ } ++ ++ public void reset() { ++ float exp = 0; ++ boolean keepInventory = this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY); ++ ++ if (this.keepLevel) { // CraftBukkit - SPIGOT-6687: Only use keepLevel (was pre-set with RULE_KEEPINVENTORY value in PlayerDeathEvent) ++ exp = this.experienceProgress; ++ this.newTotalExp = this.totalExperience; ++ this.newLevel = this.experienceLevel; ++ } ++ ++ this.setHealth(this.getMaxHealth()); ++ this.stopUsingItem(); // CraftBukkit - SPIGOT-6682: Clear active item on reset ++ this.setRemainingFireTicks(0); ++ this.fallDistance = 0; ++ this.foodData = new FoodData(this); ++ this.experienceLevel = this.newLevel; ++ this.totalExperience = this.newTotalExp; ++ this.experienceProgress = 0; ++ this.deathTime = 0; ++ this.setArrowCount(0, true); // CraftBukkit - ArrowBodyCountChangeEvent ++ this.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.DEATH); ++ this.effectsDirty = true; ++ this.containerMenu = this.inventoryMenu; ++ this.lastHurtByPlayer = null; ++ this.lastHurtByMob = null; ++ this.combatTracker = new CombatTracker(this); ++ this.lastSentExp = -1; ++ if (this.keepLevel) { // CraftBukkit - SPIGOT-6687: Only use keepLevel (was pre-set with RULE_KEEPINVENTORY value in PlayerDeathEvent) ++ this.experienceProgress = exp; ++ } else { ++ this.giveExperiencePoints(this.newExp); ++ } ++ this.keepLevel = false; ++ this.setDeltaMovement(0, 0, 0); // CraftBukkit - SPIGOT-6948: Reset velocity on death ++ } ++ ++ @Override ++ public CraftPlayer getBukkitEntity() { ++ return (CraftPlayer) super.getBukkitEntity(); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ServerPlayerGameMode.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ServerPlayerGameMode.java.patch new file mode 100644 index 0000000000..1a1bd0900e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/ServerPlayerGameMode.java.patch @@ -0,0 +1,327 @@ +--- a/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -21,10 +23,28 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.GameMasterBlock; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; ++import org.slf4j.Logger; ++ ++// CraftBukkit start ++import java.util.ArrayList; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.network.ServerGamePacketListenerImpl; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.CakeBlock; ++import net.minecraft.world.level.block.DoorBlock; ++import net.minecraft.world.level.block.state.properties.BlockPropertyDoubleBlockHalf; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; +-import org.slf4j.Logger; ++import org.bukkit.GameMode; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockBreakEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.Event; ++import org.bukkit.event.block.Action; ++import org.bukkit.event.player.PlayerGameModeChangeEvent; ++import org.bukkit.event.player.PlayerInteractEvent; ++// CraftBukkit end + + public class ServerPlayerGameMode { + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -51,12 +76,16 @@ + if (gameModeForPlayer == this.gameModeForPlayer) { + return false; + } else { ++ // CraftBukkit start ++ PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(player.getBukkitEntity(), GameMode.getByValue(gameModeForPlayer.getId())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end + this.setGameModeForPlayer(gameModeForPlayer, this.previousGameModeForPlayer); + this.player.onUpdateAbilities(); +- this.player +- .server +- .getPlayerList() +- .broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player)); ++ this.player.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player), this.player); // CraftBukkit + this.level.updateSleepingPlayerList(); + return true; + } +@@ -86,7 +115,9 @@ + } + + public void tick() { +- this.gameTicks++; ++ this.gameTicks = MinecraftServer.currentTick; // CraftBukkit; ++ IBlockData iblockdata; ++ + if (this.hasDelayedDestroy) { + BlockState blockState = this.level.getBlockState(this.delayedDestroyPos); + if (blockState.isAir()) { +@@ -134,11 +169,33 @@ + } else { + if (action == ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK) { + if (!this.level.mayInteract(this.player, pos)) { ++ // CraftBukkit start - fire PlayerInteractEvent ++ CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, pos, face, this.player.getInventory().getSelected(), EnumHand.MAIN_HAND); + this.player.connection.send(new ClientboundBlockUpdatePacket(pos, this.level.getBlockState(pos))); + this.debugLogging(pos, false, sequence, "may not interact"); ++ // Update any tile entity data for this block ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ if (tileentity != null) { ++ this.player.connection.send(tileentity.getUpdatePacket()); ++ } ++ // CraftBukkit end + return; + } + ++ // CraftBukkit start ++ PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, pos, face, this.player.getInventory().getSelected(), EnumHand.MAIN_HAND); ++ if (event.isCancelled()) { ++ // Let the client know the block still exists ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ // Update any tile entity data for this block ++ BlockEntity tileentity = this.level.getBlockEntity(pos); ++ if (tileentity != null) { ++ this.player.connection.send(tileentity.getUpdatePacket()); ++ } ++ return; ++ } ++ // CraftBukkit end ++ + if (this.isCreative()) { + this.destroyAndAck(pos, sequence, "creative destroy"); + return; +@@ -152,13 +209,46 @@ + + this.destroyProgressStart = this.gameTicks; + float f = 1.0F; +- BlockState blockState = this.level.getBlockState(pos); +- if (!blockState.isAir()) { +- blockState.attack(this.level, pos, this.player); +- f = blockState.getDestroyProgress(this.player, this.player.level(), pos); ++ ++ iblockdata = this.level.getBlockState(pos); ++ // CraftBukkit start - Swings at air do *NOT* exist. ++ if (event.useInteractedBlock() == Event.Result.DENY) { ++ // If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door. ++ IBlockData data = this.level.getBlockState(pos); ++ if (data.getBlock() instanceof DoorBlock) { ++ // For some reason *BOTH* the bottom/top part have to be marked updated. ++ boolean bottom = data.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER; ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, bottom ? pos.above() : pos.below())); ++ } else if (data.getBlock() instanceof TrapDoorBlock) { ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ } ++ } else if (!iblockdata.isAir()) { ++ iblockdata.attack(this.level, pos, this.player); ++ f = iblockdata.getDestroyProgress(this.player, this.player.level(), pos); + } + +- if (!blockState.isAir() && f >= 1.0F) { ++ if (event.useItemInHand() == Event.Result.DENY) { ++ // If we 'insta destroyed' then the client needs to be informed. ++ if (f > 1.0f) { ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ } ++ return; ++ } ++ org.bukkit.event.block.BlockDamageEvent blockEvent = CraftEventFactory.callBlockDamageEvent(this.player, pos, this.player.getInventory().getSelected(), f >= 1.0f); ++ ++ if (blockEvent.isCancelled()) { ++ // Let the client know the block still exists ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ return; ++ } ++ ++ if (blockEvent.getInstaBreak()) { ++ f = 2.0f; ++ } ++ // CraftBukkit end ++ ++ if (!iblockdata.isAir() && f >= 1.0F) { + this.destroyAndAck(pos, sequence, "insta mine"); + } else { + if (this.isDestroyingBlock) { +@@ -199,13 +292,15 @@ + } else if (action == ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK) { + this.isDestroyingBlock = false; + if (!Objects.equals(this.destroyPos, pos)) { +- LOGGER.warn("Mismatch in destroy block pos: {} {}", this.destroyPos, pos); ++ ServerPlayerGameMode.LOGGER.debug("Mismatch in destroy block pos: {} {}", this.destroyPos, pos); // CraftBukkit - SPIGOT-5457 sent by client when interact event cancelled + this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); + this.debugLogging(pos, true, sequence, "aborted mismatched destroying"); + } + + this.level.destroyBlockProgress(this.player.getId(), pos, -1); + this.debugLogging(pos, true, sequence, "aborted destroying"); ++ ++ CraftEventFactory.callBlockDamageAbortEvent(this.player, pos, this.player.getInventory().getSelected()); // CraftBukkit + } + } + } +@@ -220,37 +317,112 @@ + } + + public boolean destroyBlock(BlockPos pos) { +- BlockState blockState = this.level.getBlockState(pos); +- if (!this.player.getMainHandItem().getItem().canAttackBlock(blockState, this.level, pos, this.player)) { ++ IBlockData iblockdata = this.level.getBlockState(pos); ++ // CraftBukkit start - fire BlockBreakEvent ++ org.bukkit.block.Block bblock = CraftBlock.at(level, pos); ++ BlockBreakEvent event = null; ++ ++ if (this.player instanceof ServerPlayer) { ++ // Sword + Creative mode pre-cancel ++ boolean isSwordNoBreak = !this.player.getMainHandItem().getItem().canAttackBlock(iblockdata, this.level, pos, this.player); ++ ++ // Tell client the block is gone immediately then process events ++ // Don't tell the client if its a creative sword break because its not broken! ++ if (level.getBlockEntity(pos) == null && !isSwordNoBreak) { ++ ClientboundBlockUpdatePacket packet = new ClientboundBlockUpdatePacket(pos, Blocks.AIR.defaultBlockState()); ++ this.player.connection.send(packet); ++ } ++ ++ event = new BlockBreakEvent(bblock, this.player.getBukkitEntity()); ++ ++ // Sword + Creative mode pre-cancel ++ event.setCancelled(isSwordNoBreak); ++ ++ // Calculate default block experience ++ IBlockData nmsData = this.level.getBlockState(pos); ++ Block nmsBlock = nmsData.getBlock(); ++ ++ ItemStack itemstack = this.player.getItemBySlot(EquipmentSlot.MAINHAND); ++ ++ if (nmsBlock != null && !event.isCancelled() && !this.isCreative() && this.player.hasCorrectToolForDrops(nmsBlock.defaultBlockState())) { ++ event.setExpToDrop(nmsBlock.getExpDrop(nmsData, this.level, pos, itemstack, true)); ++ } ++ ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ if (isSwordNoBreak) { ++ return false; ++ } ++ // Let the client know the block still exists ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ ++ // Brute force all possible updates ++ for (Direction dir : Direction.values()) { ++ this.player.connection.send(new ClientboundBlockUpdatePacket(level, pos.relative(dir))); ++ } ++ ++ // Update any tile entity data for this block ++ BlockEntity tileentity = this.level.getBlockEntity(pos); ++ if (tileentity != null) { ++ this.player.connection.send(tileentity.getUpdatePacket()); ++ } ++ return false; ++ } ++ } ++ // CraftBukkit end ++ ++ if (false && !this.player.getMainHandItem().getItem().canAttackBlock(iblockdata, this.level, pos, this.player)) { // CraftBukkit - false + return false; + } else { +- BlockEntity blockEntity = this.level.getBlockEntity(pos); +- Block block = blockState.getBlock(); ++ iblockdata = this.level.getBlockState(pos); // CraftBukkit - update state from plugins ++ if (iblockdata.isAir()) return false; // CraftBukkit - A plugin set block to air without cancelling ++ BlockEntity tileentity = this.level.getBlockEntity(pos); ++ Block block = iblockdata.getBlock(); ++ + if (block instanceof GameMasterBlock && !this.player.canUseGameMasterBlocks()) { + this.level.sendBlockUpdated(pos, blockState, blockState, 3); + return false; + } else if (this.player.blockActionRestricted(this.level, pos, this.gameModeForPlayer)) { + return false; + } else { +- BlockState blockState1 = block.playerWillDestroy(this.level, pos, blockState, this.player); ++ // CraftBukkit start ++ org.bukkit.block.BlockState state = bblock.getState(); ++ level.captureDrops = new ArrayList<>(); ++ // CraftBukkit end ++ IBlockData iblockdata1 = block.playerWillDestroy(this.level, pos, iblockdata, this.player); + boolean flag = this.level.removeBlock(pos, false); + if (flag) { + block.destroy(this.level, pos, blockState1); + } + + if (this.isCreative()) { +- return true; ++ // return true; // CraftBukkit + } else { +- ItemStack mainHandItem = this.player.getMainHandItem(); +- ItemStack itemStack = mainHandItem.copy(); +- boolean hasCorrectToolForDrops = this.player.hasCorrectToolForDrops(blockState1); +- mainHandItem.mineBlock(this.level, blockState1, pos, this.player); +- if (flag && hasCorrectToolForDrops) { +- block.playerDestroy(this.level, this.player, pos, blockState1, blockEntity, itemStack); ++ ItemStack itemstack = this.player.getMainHandItem(); ++ ItemStack itemstack1 = itemstack.copy(); ++ boolean flag1 = this.player.hasCorrectToolForDrops(iblockdata1); ++ ++ itemstack.mineBlock(this.level, iblockdata1, pos, this.player); ++ if (flag && flag1 && event.isDropItems()) { // CraftBukkit - Check if block should drop items ++ block.playerDestroy(this.level, this.player, pos, iblockdata1, tileentity, itemstack1); + } + +- return true; ++ // return true; // CraftBukkit + } ++ // CraftBukkit start ++ if (event.isDropItems()) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, level.captureDrops); ++ } ++ level.captureDrops = null; ++ ++ // Drop event experience ++ if (flag && event != null) { ++ iblockdata.getBlock().popExperience(this.level, pos, event.getExpToDrop()); ++ } ++ ++ return true; ++ // CraftBukkit end + } + } + } +@@ -294,10 +468,19 @@ + } + } + +- public InteractionResult useItemOn(ServerPlayer player, Level level, ItemStack stack, InteractionHand hand, BlockHitResult hitResult) { +- BlockPos blockPos = hitResult.getBlockPos(); +- BlockState blockState = level.getBlockState(blockPos); +- if (!blockState.getBlock().isEnabled(level.enabledFeatures())) { ++ // CraftBukkit start - whole method ++ public boolean interactResult = false; ++ public boolean firedInteract = false; ++ public BlockPos interactPosition; ++ public EnumHand interactHand; ++ public ItemStack interactItemStack; ++ public InteractionResult useItemOn(ServerPlayer player, Level level, ItemStack stack, EnumHand hand, BlockHitResult hitResult) { ++ BlockPos blockposition = hitResult.getBlockPos(); ++ IBlockData iblockdata = level.getBlockState(blockposition); ++ InteractionResult enuminteractionresult = InteractionResult.PASS; ++ boolean cancelledBlock = false; ++ ++ if (!iblockdata.getBlock().isEnabled(level.enabledFeatures())) { + return InteractionResult.FAIL; + } else if (this.gameModeForPlayer == GameType.SPECTATOR) { + MenuProvider menuProvider = blockState.getMenuProvider(level, blockPos); +@@ -339,6 +557,8 @@ + return InteractionResult.PASS; + } + } ++ return enuminteractionresult; ++ // CraftBukkit end + } + + public void setLevel(ServerLevel serverLevel) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/TicketType.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/TicketType.java.patch new file mode 100644 index 0000000000..91f6de154e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/TicketType.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/server/level/TicketType.java ++++ b/net/minecraft/server/level/TicketType.java +@@ -18,6 +23,8 @@ + public static final TicketType PORTAL = create("portal", Vec3i::compareTo, 300); + public static final TicketType POST_TELEPORT = create("post_teleport", Integer::compareTo, 5); + public static final TicketType UNKNOWN = create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1); ++ public static final TicketType PLUGIN = create("plugin", (a, b) -> 0); // CraftBukkit ++ public static final TicketType PLUGIN_TICKET = create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit + + public static TicketType create(String name, Comparator comparator) { + return new TicketType<>(name, comparator, 0L); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/WorldGenRegion.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/WorldGenRegion.java.patch new file mode 100644 index 0000000000..6b215d0f7c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/level/WorldGenRegion.java.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/server/level/WorldGenRegion.java ++++ b/net/minecraft/server/level/WorldGenRegion.java +@@ -207,9 +208,10 @@ + if (blockState.isAir()) { + return false; + } else { +- if (dropBlock) { +- BlockEntity blockEntity = blockState.hasBlockEntity() ? this.getBlockEntity(pos) : null; +- Block.dropResources(blockState, this.level, pos, blockEntity, entity, ItemStack.EMPTY); ++ if (false) { // CraftBukkit - SPIGOT-6833: Do not drop during world generation ++ BlockEntity tileentity = iblockdata.hasBlockEntity() ? this.getBlockEntity(pos) : null; ++ ++ Block.dropResources(iblockdata, this.level, pos, tileentity, entity, ItemStack.EMPTY); + } + + return this.setBlock(pos, Blocks.AIR.defaultBlockState(), 3, recursionLeft); +@@ -328,6 +327,13 @@ + + @Override + public boolean addFreshEntity(Entity entity) { ++ // CraftBukkit start ++ return addFreshEntity(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ @Override ++ public boolean addFreshEntity(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ // CraftBukkit end + int i = SectionPos.blockToSectionCoord(entity.getBlockX()); + int i1 = SectionPos.blockToSectionCoord(entity.getBlockZ()); + this.getChunk(i, i1).addEntity(entity); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/LegacyQueryHandler.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/LegacyQueryHandler.java.patch new file mode 100644 index 0000000000..e985c493ff --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/LegacyQueryHandler.java.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/server/network/LegacyQueryHandler.java ++++ b/net/minecraft/server/network/LegacyQueryHandler.java +@@ -31,12 +32,15 @@ + return; + } + +- SocketAddress socketAddress = context.channel().remoteAddress(); +- int i = byteBuf.readableBytes(); ++ SocketAddress socketaddress = channelhandlercontext.channel().remoteAddress(); ++ int i = bytebuf.readableBytes(); ++ String s; ++ org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(socketaddress, server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); // CraftBukkit ++ + if (i == 0) { +- LOGGER.debug("Ping: (<1.3.x) from {}", socketAddress); +- String string = createVersion0Response(this.server); +- sendFlushAndClose(context, createLegacyDisconnectPacket(context.alloc(), string)); ++ LegacyQueryHandler.LOGGER.debug("Ping: (<1.3.x) from {}", socketaddress); ++ s = createVersion0Response(this.server, event); // CraftBukkit ++ sendFlushAndClose(channelhandlercontext, createLegacyDisconnectPacket(channelhandlercontext.alloc(), s)); + } else { + if (byteBuf.readUnsignedByte() != 1) { + return; +@@ -52,8 +56,8 @@ + LOGGER.debug("Ping: (1.4-1.5.x) from {}", socketAddress); + } + +- String string = createVersion1Response(this.server); +- sendFlushAndClose(context, createLegacyDisconnectPacket(context.alloc(), string)); ++ s = createVersion1Response(this.server, event); // CraftBukkit ++ sendFlushAndClose(channelhandlercontext, createLegacyDisconnectPacket(channelhandlercontext.alloc(), s)); + } + + byteBuf.release(); +@@ -95,20 +107,16 @@ + } + } + +- private static String createVersion0Response(ServerInfo serverInfo) { +- return String.format(Locale.ROOT, "%s§%d§%d", serverInfo.getMotd(), serverInfo.getPlayerCount(), serverInfo.getMaxPlayers()); ++ // CraftBukkit start ++ private static String createVersion0Response(ServerInfo serverinfo, org.bukkit.event.server.ServerListPingEvent event) { ++ return String.format(Locale.ROOT, "%s\u00a7%d\u00a7%d", event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); ++ // CraftBukkit end + } + +- private static String createVersion1Response(ServerInfo serverInfo) { +- return String.format( +- Locale.ROOT, +- "§1\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", +- 127, +- serverInfo.getServerVersion(), +- serverInfo.getMotd(), +- serverInfo.getPlayerCount(), +- serverInfo.getMaxPlayers() +- ); ++ // CraftBukkit start ++ private static String createVersion1Response(ServerInfo serverinfo, org.bukkit.event.server.ServerListPingEvent event) { ++ return String.format(Locale.ROOT, "\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, serverinfo.getServerVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); ++ // CraftBukkit end + } + + private static void sendFlushAndClose(ChannelHandlerContext channelHandlerContext, ByteBuf context) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerCommonPacketListenerImpl.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerCommonPacketListenerImpl.java.patch new file mode 100644 index 0000000000..3575f2c830 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerCommonPacketListenerImpl.java.patch @@ -0,0 +1,187 @@ +--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java +@@ -24,6 +30,17 @@ + import net.minecraft.util.VisibleForDebug; + import org.slf4j.Logger; + ++// CraftBukkit start ++import io.netty.buffer.ByteBuf; ++import java.util.concurrent.ExecutionException; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.bukkit.event.player.PlayerKickEvent; ++import org.bukkit.event.player.PlayerResourcePackStatusEvent; ++// CraftBukkit end ++ + public abstract class ServerCommonPacketListenerImpl implements ServerCommonPacketListener { + private static final Logger LOGGER = LogUtils.getLogger(); + public static final int LATENCY_CHECK_INTERVAL = 15000; +@@ -36,13 +54,21 @@ + private int latency; + private volatile boolean suspendFlushingOnServerThread = false; + +- public ServerCommonPacketListenerImpl(MinecraftServer minecraftServer, Connection connection, CommonListenerCookie commonListenerCookie) { +- this.server = minecraftServer; +- this.connection = connection; ++ public ServerCommonPacketListenerImpl(MinecraftServer minecraftserver, Connection networkmanager, CommonListenerCookie commonlistenercookie, ServerPlayer player) { // CraftBukkit ++ this.server = minecraftserver; ++ this.connection = networkmanager; + this.keepAliveTime = Util.getMillis(); +- this.latency = commonListenerCookie.latency(); ++ this.latency = commonlistenercookie.latency(); ++ // CraftBukkit start - add fields and methods ++ this.player = player; ++ this.cserver = minecraftserver.server; + } + ++ public CraftPlayer getCraftPlayer() { ++ return (this.player == null) ? null : (CraftPlayer) this.player.getBukkitEntity(); ++ // CraftBukkit end ++ } ++ + @Override + public void onDisconnect(Component reason) { + if (this.isSingleplayerOwner()) { +@@ -52,9 +82,11 @@ + } + + @Override +- public void handleKeepAlive(ServerboundKeepAlivePacket serverboundKeepAlivePacket) { +- if (this.keepAlivePending && serverboundKeepAlivePacket.getId() == this.keepAliveChallenge) { +- int i = (int)(Util.getMillis() - this.keepAliveTime); ++ public void handleKeepAlive(ServerboundKeepAlivePacket serverboundkeepalivepacket) { ++ PacketUtils.ensureRunningOnSameThread(serverboundkeepalivepacket, this, this.player.serverLevel()); // CraftBukkit ++ if (this.keepAlivePending && serverboundkeepalivepacket.getId() == this.keepAliveChallenge) { ++ int i = (int) (Util.getMillis() - this.keepAliveTime); ++ + this.latency = (this.latency * 3 + i) / 4; + this.keepAlivePending = false; + } else if (!this.isSingleplayerOwner()) { +@@ -66,10 +98,19 @@ + public void handlePong(ServerboundPongPacket serverboundPongPacket) { + } + ++ // CraftBukkit start ++ private static final ResourceLocation CUSTOM_REGISTER = new ResourceLocation("register"); ++ private static final ResourceLocation CUSTOM_UNREGISTER = new ResourceLocation("unregister"); ++ + @Override + public void handleCustomPayload(ServerboundCustomPayloadPacket serverboundCustomPayloadPacket) { + } + ++ public final boolean isDisconnected() { ++ return !this.player.joining && !this.connection.isConnected(); ++ } ++ // CraftBukkit end ++ + @Override + public void handleResourcePackResponse(ServerboundResourcePackPacket serverboundResourcePackPacket) { + PacketUtils.ensureRunningOnSameThread(serverboundResourcePackPacket, this, this.server); +@@ -77,12 +156,15 @@ + LOGGER.info("Disconnecting {} due to resource pack {} rejection", this.playerProfile().getName(), serverboundResourcePackPacket.id()); + this.disconnect(Component.translatable("multiplayer.requiredTexturePrompt.disconnect")); + } ++ this.cserver.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getCraftPlayer(), serverboundresourcepackpacket.id(), PlayerResourcePackStatusEvent.Status.values()[serverboundresourcepackpacket.action().ordinal()])); // CraftBukkit ++ + } + + protected void keepConnectionAlive() { + this.server.getProfiler().push("keepAlive"); +- long millis = Util.getMillis(); +- if (millis - this.keepAliveTime >= 15000L) { ++ long i = Util.getMillis(); ++ ++ if (i - this.keepAliveTime >= 25000L) { // CraftBukkit + if (this.keepAlivePending) { + this.disconnect(TIMEOUT_DISCONNECTION_MESSAGE); + } else { +@@ -109,7 +191,15 @@ + this.send(packet, null); + } + +- public void send(Packet packet, @Nullable PacketSendListener packetSendListener) { ++ public void send(Packet packet, @Nullable PacketSendListener packetsendlistener) { ++ // CraftBukkit start ++ if (packet == null) { ++ return; ++ } else if (packet instanceof ClientboundSetDefaultSpawnPositionPacket) { ++ ClientboundSetDefaultSpawnPositionPacket packet6 = (ClientboundSetDefaultSpawnPositionPacket) packet; ++ this.player.compassTarget = CraftLocation.toBukkit(packet6.pos, this.getCraftPlayer().getWorld()); ++ } ++ // CraftBukkit end + boolean flag = !this.suspendFlushingOnServerThread || !this.server.isSameThread(); + + try { +@@ -122,10 +215,67 @@ + } + } + +- public void disconnect(Component component) { +- this.connection.send(new ClientboundDisconnectPacket(component), PacketSendListener.thenRun(() -> this.connection.disconnect(component))); ++ // CraftBukkit start ++ @Deprecated ++ public void disconnect(Component ichatbasecomponent) { ++ disconnect(CraftChatMessage.fromComponent(ichatbasecomponent)); ++ } ++ // CraftBukkit end ++ ++ public void disconnect(String s) { ++ // CraftBukkit start - fire PlayerKickEvent ++ if (this.processedDisconnect) { ++ return; ++ } ++ if (!this.cserver.isPrimaryThread()) { ++ Waitable waitable = new Waitable() { ++ @Override ++ protected Object evaluate() { ++ ServerCommonPacketListenerImpl.this.disconnect(s); ++ return null; ++ } ++ }; ++ ++ this.server.processQueue.add(waitable); ++ ++ try { ++ waitable.get(); ++ } catch (InterruptedException e) { ++ Thread.currentThread().interrupt(); ++ } catch (ExecutionException e) { ++ throw new RuntimeException(e); ++ } ++ return; ++ } ++ ++ String leaveMessage = ChatFormatting.YELLOW + this.player.getScoreboardName() + " left the game."; ++ ++ PlayerKickEvent event = new PlayerKickEvent(this.player.getBukkitEntity(), s, leaveMessage); ++ ++ if (this.cserver.getServer().isRunning()) { ++ this.cserver.getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ // Do not kick the player ++ return; ++ } ++ this.player.kickLeaveMessage = event.getLeaveMessage(); // CraftBukkit - SPIGOT-3034: Forward leave message to PlayerQuitEvent ++ // Send the possibly modified leave message ++ final Component ichatbasecomponent = CraftChatMessage.fromString(event.getReason(), true)[0]; ++ // CraftBukkit end ++ ++ this.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), PacketSendListener.thenRun(() -> { ++ this.connection.disconnect(ichatbasecomponent); ++ })); ++ this.onDisconnect(ichatbasecomponent); // CraftBukkit - fire quit instantly + this.connection.setReadOnly(); +- this.server.executeBlocking(this.connection::handleDisconnection); ++ MinecraftServer minecraftserver = this.server; ++ Connection networkmanager = this.connection; ++ ++ Objects.requireNonNull(this.connection); ++ // CraftBukkit - Don't wait ++ minecraftserver.wrapRunnable(networkmanager::handleDisconnection); + } + + protected boolean isSingleplayerOwner() { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java.patch new file mode 100644 index 0000000000..f007de6d2c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java.patch @@ -0,0 +1,39 @@ +--- a/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java +@@ -42,10 +44,10 @@ + private ConfigurationTask currentTask; + private ClientInformation clientInformation; + +- public ServerConfigurationPacketListenerImpl(MinecraftServer minecraftServer, Connection connection, CommonListenerCookie commonListenerCookie) { +- super(minecraftServer, connection, commonListenerCookie); +- this.gameProfile = commonListenerCookie.gameProfile(); +- this.clientInformation = commonListenerCookie.clientInformation(); ++ public ServerConfigurationPacketListenerImpl(MinecraftServer minecraftserver, Connection networkmanager, CommonListenerCookie commonlistenercookie, ServerPlayer player) { // CraftBukkit ++ super(minecraftserver, networkmanager, commonlistenercookie, player); // CraftBukkit ++ this.gameProfile = commonlistenercookie.gameProfile(); ++ this.clientInformation = commonlistenercookie.clientInformation(); + } + + @Override +@@ -116,14 +117,16 @@ + return; + } + +- Component component = playerList.canPlayerLogin(this.connection.getRemoteAddress(), this.gameProfile); +- if (component != null) { +- this.disconnect(component); ++ Component ichatbasecomponent = null; // CraftBukkit - login checks already completed ++ ++ if (ichatbasecomponent != null) { ++ this.disconnect(ichatbasecomponent); + return; + } + +- ServerPlayer playerForLogin = playerList.getPlayerForLogin(this.gameProfile, this.clientInformation); +- playerList.placeNewPlayer(this.connection, playerForLogin, this.createCookie(this.clientInformation)); ++ ServerPlayer entityplayer = playerlist.getPlayerForLogin(this.gameProfile, this.clientInformation, this.player); // CraftBukkit ++ ++ playerlist.placeNewPlayer(this.connection, entityplayer, this.createCookie(this.clientInformation)); + this.connection.resumeInboundAfterProtocolChange(); + } catch (Exception var5) { + LOGGER.error("Couldn't place player in world", (Throwable)var5); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerConnectionListener.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerConnectionListener.java.patch new file mode 100644 index 0000000000..27a9942ae4 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerConnectionListener.java.patch @@ -0,0 +1,79 @@ +--- a/net/minecraft/server/network/ServerConnectionListener.java ++++ b/net/minecraft/server/network/ServerConnectionListener.java +@@ -78,45 +84,40 @@ + LOGGER.info("Using default channel type"); + } + +- this.channels +- .add( +- new ServerBootstrap() +- .channel(clazz) +- .childHandler( +- new ChannelInitializer() { +- @Override +- protected void initChannel(Channel channel) { +- Connection.setInitialProtocolAttributes(channel); +- +- try { +- channel.config().setOption(ChannelOption.TCP_NODELAY, true); +- } catch (ChannelException var5) { +- } +- +- ChannelPipeline channelPipeline = channel.pipeline() +- .addLast("timeout", new ReadTimeoutHandler(30)) +- .addLast("legacy_query", new LegacyQueryHandler(ServerConnectionListener.this.getServer())); +- Connection.configureSerialization(channelPipeline, PacketFlow.SERVERBOUND, null); +- int rateLimitPacketsPerSecond = ServerConnectionListener.this.server.getRateLimitPacketsPerSecond(); +- Connection connection = (Connection)(rateLimitPacketsPerSecond > 0 +- ? new RateKickingConnection(rateLimitPacketsPerSecond) +- : new Connection(PacketFlow.SERVERBOUND)); +- ServerConnectionListener.this.connections.add(connection); +- connection.configurePacketHandler(channelPipeline); +- connection.setListenerForServerboundHandshake( +- new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, connection) +- ); +- } +- } +- ) +- .group(eventLoopGroup) +- .localAddress(address, port) +- .bind() +- .syncUninterruptibly() +- ); ++ this.channels.add(((ServerBootstrap) ((ServerBootstrap) (new ServerBootstrap()).channel(oclass)).childHandler(new ChannelInitializer() { ++ protected void initChannel(Channel channel) { ++ Connection.setInitialProtocolAttributes(channel); ++ ++ try { ++ channel.config().setOption(ChannelOption.TCP_NODELAY, true); ++ } catch (ChannelException channelexception) { ++ ; ++ } ++ ++ ChannelPipeline channelpipeline = channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("legacy_query", new LegacyQueryHandler(ServerConnectionListener.this.getServer())); ++ ++ Connection.configureSerialization(channelpipeline, PacketFlow.SERVERBOUND, (BandwidthDebugMonitor) null); ++ int j = ServerConnectionListener.this.server.getRateLimitPacketsPerSecond(); ++ Connection object = j > 0 ? new RateKickingConnection(j) : new Connection(PacketFlow.SERVERBOUND); // CraftBukkit - decompile error ++ ++ ServerConnectionListener.this.connections.add(object); ++ ((Connection) object).configurePacketHandler(channelpipeline); ++ ((Connection) object).setListenerForServerboundHandshake(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object)); ++ } ++ }).group(eventloopgroup).localAddress(address, port)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit + } + } + ++ // CraftBukkit start ++ public void acceptConnections() { ++ synchronized (this.channels) { ++ for (ChannelFuture future : this.channels) { ++ future.channel().config().setAutoRead(true); ++ } ++ } ++ } ++ // CraftBukkit end ++ + public SocketAddress startMemoryChannel() { + ChannelFuture channelFuture; + synchronized (this.channels) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch new file mode 100644 index 0000000000..1ce9adc6bb --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch @@ -0,0 +1,1729 @@ +--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -179,11 +185,64 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import org.slf4j.Logger; + +-public class ServerGamePacketListenerImpl +- extends ServerCommonPacketListenerImpl +- implements ServerGamePacketListener, +- ServerPlayerConnection, +- TickablePacketListener { ++// CraftBukkit start ++import com.mojang.datafixers.util.Pair; ++import java.util.Arrays; ++import java.util.concurrent.ExecutionException; ++import java.util.concurrent.atomic.AtomicInteger; ++import java.util.function.Function; ++import net.minecraft.network.chat.OutgoingChatMessage; ++import net.minecraft.world.entity.animal.Bucketable; ++import net.minecraft.world.entity.animal.allay.Allay; ++import net.minecraft.world.entity.item.ItemEntity; ++import net.minecraft.world.inventory.InventoryClickType; ++import net.minecraft.world.inventory.MerchantMenu; ++import net.minecraft.world.inventory.RecipeBookMenu; ++import net.minecraft.world.inventory.Slot; ++import net.minecraft.world.item.crafting.RecipeHolder; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftEntity; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.craftbukkit.util.LazyPlayerSet; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Event; ++import org.bukkit.event.block.Action; ++import org.bukkit.event.inventory.ClickType; ++import org.bukkit.event.inventory.CraftItemEvent; ++import org.bukkit.event.inventory.InventoryAction; ++import org.bukkit.event.inventory.InventoryClickEvent; ++import org.bukkit.event.inventory.InventoryCreativeEvent; ++import org.bukkit.event.inventory.InventoryType.SlotType; ++import org.bukkit.event.inventory.SmithItemEvent; ++import org.bukkit.event.player.AsyncPlayerChatEvent; ++import org.bukkit.event.player.PlayerAnimationEvent; ++import org.bukkit.event.player.PlayerAnimationType; ++import org.bukkit.event.player.PlayerChatEvent; ++import org.bukkit.event.player.PlayerCommandPreprocessEvent; ++import org.bukkit.event.player.PlayerInteractAtEntityEvent; ++import org.bukkit.event.player.PlayerInteractEntityEvent; ++import org.bukkit.event.player.PlayerItemHeldEvent; ++import org.bukkit.event.player.PlayerMoveEvent; ++import org.bukkit.event.player.PlayerRespawnEvent.RespawnReason; ++import org.bukkit.event.player.PlayerSwapHandItemsEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++import org.bukkit.event.player.PlayerToggleFlightEvent; ++import org.bukkit.event.player.PlayerToggleSneakEvent; ++import org.bukkit.event.player.PlayerToggleSprintEvent; ++import org.bukkit.inventory.CraftingInventory; ++import org.bukkit.inventory.EquipmentSlot; ++import org.bukkit.inventory.InventoryView; ++import org.bukkit.inventory.SmithingInventory; ++// CraftBukkit end ++ ++public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl implements ServerGamePacketListener, ServerPlayerConnection, TickablePacketListener { ++ + static final Logger LOGGER = LogUtils.getLogger(); + public static final double MAX_INTERACTION_DISTANCE = Mth.square(6.0); + private static final int NO_BLOCK_UPDATES_TO_ACK = -1; +@@ -193,7 +252,9 @@ + public final PlayerChunkSender chunkSender; + private int tickCount; + private int ackBlockChangesUpTo = -1; +- private int chatSpamTickCount; ++ // CraftBukkit start - multithreaded fields ++ private final AtomicInteger chatSpamTickCount = new AtomicInteger(); ++ // CraftBukkit end + private int dropSpamTickCount; + private double firstGoodX; + private double firstGoodY; +@@ -227,19 +288,36 @@ + private final FutureChain chatMessageChain; + private boolean waitingForSwitchToConfig; + +- public ServerGamePacketListenerImpl( +- MinecraftServer minecraftServer, Connection connection, ServerPlayer serverPlayer, CommonListenerCookie commonListenerCookie +- ) { +- super(minecraftServer, connection, commonListenerCookie); +- this.chunkSender = new PlayerChunkSender(connection.isMemoryConnection()); +- connection.setListener(this); +- this.player = serverPlayer; +- serverPlayer.connection = this; +- serverPlayer.getTextFilter().join(); +- this.signedMessageDecoder = SignedMessageChain.Decoder.unsigned(serverPlayer.getUUID(), minecraftServer::enforceSecureProfile); +- this.chatMessageChain = new FutureChain(minecraftServer); ++ public ServerGamePacketListenerImpl(MinecraftServer minecraftserver, Connection networkmanager, ServerPlayer entityplayer, CommonListenerCookie commonlistenercookie) { ++ super(minecraftserver, networkmanager, commonlistenercookie, entityplayer); // CraftBukkit ++ this.chunkSender = new PlayerChunkSender(networkmanager.isMemoryConnection()); ++ networkmanager.setListener(this); ++ this.player = entityplayer; ++ entityplayer.connection = this; ++ entityplayer.getTextFilter().join(); ++ UUID uuid = entityplayer.getUUID(); ++ ++ Objects.requireNonNull(minecraftserver); ++ this.signedMessageDecoder = SignedMessageChain.Decoder.unsigned(uuid, minecraftserver::enforceSecureProfile); ++ this.chatMessageChain = new FutureChain(minecraftserver.chatExecutor); // CraftBukkit - async chat + } + ++ // CraftBukkit start - add fields ++ private int lastTick = MinecraftServer.currentTick; ++ private int allowedPlayerTicks = 1; ++ private int lastDropTick = MinecraftServer.currentTick; ++ private int lastBookTick = MinecraftServer.currentTick; ++ private int dropCount = 0; ++ ++ // Get position of last block hit for BlockDamageLevel.STOPPED ++ private double lastPosX = Double.MAX_VALUE; ++ private double lastPosY = Double.MAX_VALUE; ++ private double lastPosZ = Double.MAX_VALUE; ++ private float lastPitch = Float.MAX_VALUE; ++ private float lastYaw = Float.MAX_VALUE; ++ private boolean justTeleported = false; ++ // CraftBukkit end ++ + @Override + public void tick() { + if (this.ackBlockChangesUpTo > -1) { +@@ -291,17 +369,21 @@ + } + + this.keepConnectionAlive(); ++ // CraftBukkit start ++ for (int spam; (spam = this.chatSpamTickCount.get()) > 0 && !chatSpamTickCount.compareAndSet(spam, spam - 1); ) ; ++ /* Use thread-safe field access instead + if (this.chatSpamTickCount > 0) { + this.chatSpamTickCount--; + } ++ */ ++ // CraftBukkit end + + if (this.dropSpamTickCount > 0) { + this.dropSpamTickCount--; + } + +- if (this.player.getLastActionTime() > 0L +- && this.server.getPlayerIdleTimeout() > 0 +- && Util.getMillis() - this.player.getLastActionTime() > (long)this.server.getPlayerIdleTimeout() * 1000L * 60L) { ++ if (this.player.getLastActionTime() > 0L && this.server.getPlayerIdleTimeout() > 0 && Util.getMillis() - this.player.getLastActionTime() > (long) this.server.getPlayerIdleTimeout() * 1000L * 60L) { ++ this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 + this.disconnect(Component.translatable("multiplayer.disconnect.idling")); + } + } +@@ -385,16 +468,42 @@ + double d2 = clampHorizontal(packet.getZ()); + float f = Mth.wrapDegrees(packet.getYRot()); + float f1 = Mth.wrapDegrees(packet.getXRot()); +- double d3 = d - this.vehicleFirstGoodX; +- double d4 = d1 - this.vehicleFirstGoodY; +- double d5 = d2 - this.vehicleFirstGoodZ; +- double d6 = rootVehicle.getDeltaMovement().lengthSqr(); +- double d7 = d3 * d3 + d4 * d4 + d5 * d5; +- if (d7 - d6 > 100.0 && !this.isSingleplayerOwner()) { +- LOGGER.warn( +- "{} (vehicle of {}) moved too quickly! {},{},{}", rootVehicle.getName().getString(), this.player.getName().getString(), d3, d4, d5 +- ); +- this.send(new ClientboundMoveVehiclePacket(rootVehicle)); ++ double d6 = d3 - this.vehicleFirstGoodX; ++ double d7 = d4 - this.vehicleFirstGoodY; ++ double d8 = d5 - this.vehicleFirstGoodZ; ++ double d9 = entity.getDeltaMovement().lengthSqr(); ++ double d10 = d6 * d6 + d7 * d7 + d8 * d8; ++ ++ ++ // CraftBukkit start - handle custom speeds and skipped ticks ++ this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick; ++ this.allowedPlayerTicks = Math.max(this.allowedPlayerTicks, 1); ++ this.lastTick = (int) (System.currentTimeMillis() / 50); ++ ++ ++this.receivedMovePacketCount; ++ int i = this.receivedMovePacketCount - this.knownMovePacketCount; ++ if (i > Math.max(this.allowedPlayerTicks, 5)) { ++ ServerGamePacketListenerImpl.LOGGER.debug(this.player.getScoreboardName() + " is sending move packets too frequently (" + i + " packets since last tick)"); ++ i = 1; ++ } ++ ++ if (d10 > 0) { ++ allowedPlayerTicks -= 1; ++ } else { ++ allowedPlayerTicks = 20; ++ } ++ double speed; ++ if (player.getAbilities().flying) { ++ speed = player.getAbilities().flyingSpeed * 20f; ++ } else { ++ speed = player.getAbilities().walkingSpeed * 10f; ++ } ++ speed *= 2f; // TODO: Get the speed of the vehicle instead of the player ++ ++ if (d10 - d9 > Math.max(100.0D, Math.pow((double) (10.0F * (float) i * speed), 2)) && !this.isSingleplayerOwner()) { ++ // CraftBukkit end ++ ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", new Object[]{entity.getName().getString(), this.player.getName().getString(), d6, d7, d8}); ++ this.send(new ClientboundMoveVehiclePacket(entity)); + return; + } + +@@ -422,14 +540,73 @@ + LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", rootVehicle.getName().getString(), this.player.getName().getString(), Math.sqrt(d7)); + } + +- rootVehicle.absMoveTo(d, d1, d2, f, f1); +- boolean flag3 = serverLevel.noCollision(rootVehicle, rootVehicle.getBoundingBox().deflate(0.0625)); ++ entity.absMoveTo(d3, d4, d5, f, f1); ++ player.absMoveTo(d3, d4, d5, this.player.getYRot(), this.player.getXRot()); // CraftBukkit ++ boolean flag3 = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D)); ++ + if (flag && (flag2 || !flag3)) { +- rootVehicle.absMoveTo(x, y, z, f, f1); +- this.send(new ClientboundMoveVehiclePacket(rootVehicle)); ++ entity.absMoveTo(d0, d1, d2, f, f1); ++ player.absMoveTo(d0, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit ++ this.send(new ClientboundMoveVehiclePacket(entity)); + return; + } + ++ // CraftBukkit start - fire PlayerMoveEvent ++ Player player = this.getCraftPlayer(); ++ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. ++ Location to = player.getLocation().clone(); // Start off the To location as the Players current location. ++ ++ // If the packet contains movement information then we update the To location with the correct XYZ. ++ to.setX(packet.getX()); ++ to.setY(packet.getY()); ++ to.setZ(packet.getZ()); ++ ++ ++ // If the packet contains look information then we update the To location with the correct Yaw & Pitch. ++ to.setYaw(packet.getYRot()); ++ to.setPitch(packet.getXRot()); ++ ++ // Prevent 40 event-calls for less than a single pixel of movement >.> ++ double delta = Math.pow(this.lastPosX - to.getX(), 2) + Math.pow(this.lastPosY - to.getY(), 2) + Math.pow(this.lastPosZ - to.getZ(), 2); ++ float deltaAngle = Math.abs(this.lastYaw - to.getYaw()) + Math.abs(this.lastPitch - to.getPitch()); ++ ++ if ((delta > 1f / 256 || deltaAngle > 10f) && !this.player.isImmobile()) { ++ this.lastPosX = to.getX(); ++ this.lastPosY = to.getY(); ++ this.lastPosZ = to.getZ(); ++ this.lastYaw = to.getYaw(); ++ this.lastPitch = to.getPitch(); ++ ++ // Skip the first time we do this ++ if (from.getX() != Double.MAX_VALUE) { ++ Location oldTo = to.clone(); ++ PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ // If the event is cancelled we move the player back to their old location. ++ if (event.isCancelled()) { ++ teleport(from); ++ return; ++ } ++ ++ // If a Plugin has changed the To destination then we teleport the Player ++ // there to avoid any 'Moved wrongly' or 'Moved too quickly' errors. ++ // We only do this if the Event was not cancelled. ++ if (!oldTo.equals(event.getTo()) && !event.isCancelled()) { ++ this.player.getBukkitEntity().teleport(event.getTo(), PlayerTeleportEvent.TeleportCause.PLUGIN); ++ return; ++ } ++ ++ // Check to see if the Players Location has some how changed during the call of the event. ++ // This can happen due to a plugin teleporting the player instead of using .setTo() ++ if (!from.equals(this.getCraftPlayer().getLocation()) && this.justTeleported) { ++ this.justTeleported = false; ++ return; ++ } ++ } ++ } ++ // CraftBukkit end ++ + this.player.serverLevel().getChunkSource().move(this.player); + this.player.checkMovementStatistics(this.player.getX() - x, this.player.getY() - y, this.player.getZ() - z); + this.clientVehicleIsFloating = d4 >= -0.03125 +@@ -475,6 +640,7 @@ + } + + this.awaitingPositionFromClient = null; ++ this.player.serverLevel().getChunkSource().move(this.player); // CraftBukkit + } + } + +@@ -487,6 +658,7 @@ + @Override + public void handleRecipeBookChangeSettingsPacket(ServerboundRecipeBookChangeSettingsPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ CraftEventFactory.callRecipeBookSettingsEvent(this.player, packet.getBookType(), packet.isOpen(), packet.isFiltering()); // CraftBukkit + this.player.getRecipeBook().setBookSetting(packet.getBookType(), packet.isOpen(), packet.isFiltering()); + } + +@@ -505,17 +679,24 @@ + @Override + public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); +- StringReader stringReader = new StringReader(packet.getCommand()); +- if (stringReader.canRead() && stringReader.peek() == '/') { +- stringReader.skip(); ++ // CraftBukkit start ++ if (chatSpamTickCount.addAndGet(1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { ++ this.disconnect(Component.translatable("disconnect.spam")); ++ return; + } ++ // CraftBukkit end ++ StringReader stringreader = new StringReader(packet.getCommand()); + +- ParseResults parseResults = this.server.getCommands().getDispatcher().parse(stringReader, this.player.createCommandSourceStack()); +- this.server +- .getCommands() +- .getDispatcher() +- .getCompletionSuggestions(parseResults) +- .thenAccept(suggestions -> this.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions))); ++ if (stringreader.canRead() && stringreader.peek() == '/') { ++ stringreader.skip(); ++ } ++ ++ ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); ++ ++ this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { ++ if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer ++ this.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions)); ++ }); + } + + @Override +@@ -721,12 +937,18 @@ + @Override + public void handleSelectTrade(ServerboundSelectTradePacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); +- int item = packet.getItem(); +- if (this.player.containerMenu instanceof MerchantMenu merchantMenu) { +- if (!merchantMenu.stillValid(this.player)) { +- LOGGER.debug("Player {} interacted with invalid menu {}", this.player, merchantMenu); ++ int i = packet.getItem(); ++ AbstractContainerMenu container = this.player.containerMenu; ++ ++ if (container instanceof MerchantMenu) { ++ MerchantMenu containermerchant = (MerchantMenu) container; ++ // CraftBukkit start ++ final org.bukkit.event.inventory.TradeSelectEvent tradeSelectEvent = CraftEventFactory.callTradeSelectEvent(this.player, i, containermerchant); ++ if (tradeSelectEvent.isCancelled()) { ++ this.player.getBukkitEntity().updateInventory(); + return; + } ++ // CraftBukkit end + + merchantMenu.setSelectionHint(item); + merchantMenu.tryMoveItems(item); +@@ -735,8 +963,16 @@ + + @Override + public void handleEditBook(ServerboundEditBookPacket packet) { +- int slot = packet.getSlot(); +- if (Inventory.isHotbarSlot(slot) || slot == 40) { ++ // CraftBukkit start ++ if (this.lastBookTick + 20 > MinecraftServer.currentTick) { ++ this.disconnect("Book edited too quickly!"); ++ return; ++ } ++ this.lastBookTick = MinecraftServer.currentTick; ++ // CraftBukkit end ++ int i = packet.getSlot(); ++ ++ if (Inventory.isHotbarSlot(i) || i == 40) { + List list = Lists.newArrayList(); + Optional title = packet.getTitle(); + title.ifPresent(list::add); +@@ -749,9 +993,10 @@ + } + + private void updateBookContents(List pages, int index) { +- ItemStack item = this.player.getInventory().getItem(index); +- if (item.is(Items.WRITABLE_BOOK)) { +- this.updateBookPages(pages, UnaryOperator.identity(), item); ++ ItemStack itemstack = this.player.getInventory().getItem(index); ++ ++ if (itemstack.is(Items.WRITABLE_BOOK)) { ++ this.updateBookPages(pages, UnaryOperator.identity(), itemstack.copy(), index, itemstack); // CraftBukkit + } + } + +@@ -772,13 +1019,16 @@ + itemStack.addTagElement("title", StringTag.valueOf(title.raw())); + } + +- this.updateBookPages(pages, string -> Component.Serializer.toJson(Component.literal(string)), itemStack); +- this.player.getInventory().setItem(index, itemStack); ++ this.updateBookPages(pages, (s) -> { ++ return Component.Serializer.toJson(Component.literal(s)); ++ }, itemstack1, index, itemstack); // CraftBukkit ++ this.player.getInventory().setItem(index, itemstack); // CraftBukkit - event factory updates the hand book + } + } + +- private void updateBookPages(List pages, UnaryOperator updater, ItemStack book) { +- ListTag list = new ListTag(); ++ private void updateBookPages(List list, UnaryOperator unaryoperator, ItemStack itemstack, int slot, ItemStack handItem) { // CraftBukkit ++ ListTag nbttaglist = new ListTag(); ++ + if (this.player.isTextFilteringEnabled()) { + pages.stream().map(filteredText1 -> StringTag.valueOf(updater.apply(filteredText1.filteredOrEmpty()))).forEach(list::add); + } else { +@@ -799,7 +1055,8 @@ + } + } + +- book.addTagElement("pages", list); ++ itemstack.addTagElement("pages", nbttaglist); ++ CraftEventFactory.handleEditBookEvent(player, slot, handItem, itemstack); // CraftBukkit + } + + @Override +@@ -840,8 +1111,9 @@ + if (containsInvalidValues(packet.getX(0.0), packet.getY(0.0), packet.getZ(0.0), packet.getYRot(0.0F), packet.getXRot(0.0F))) { + this.disconnect(Component.translatable("multiplayer.disconnect.invalid_player_movement")); + } else { +- ServerLevel serverLevel = this.player.serverLevel(); +- if (!this.player.wonGame) { ++ ServerLevel worldserver = this.player.serverLevel(); ++ ++ if (!this.player.wonGame && !this.player.isImmobile()) { // CraftBukkit + if (this.tickCount == 0) { + this.resetPosition(); + } +@@ -857,6 +1123,7 @@ + this.player.getXRot() + ); + } ++ this.allowedPlayerTicks = 20; // CraftBukkit + } else { + this.awaitingTeleportTime = this.tickCount; + double d = clampHorizontal(packet.getX(this.player.getX())); +@@ -867,15 +1135,24 @@ + if (this.player.isPassenger()) { + this.player.absMoveTo(this.player.getX(), this.player.getY(), this.player.getZ(), f, f1); + this.player.serverLevel().getChunkSource().move(this.player); ++ this.allowedPlayerTicks = 20; // CraftBukkit + } else { +- double x = this.player.getX(); +- double y = this.player.getY(); +- double z = this.player.getZ(); +- double d3 = d - this.firstGoodX; +- double d4 = d1 - this.firstGoodY; +- double d5 = d2 - this.firstGoodZ; +- double d6 = this.player.getDeltaMovement().lengthSqr(); +- double d7 = d3 * d3 + d4 * d4 + d5 * d5; ++ // CraftBukkit - Make sure the move is valid but then reset it for plugins to modify ++ double prevX = player.getX(); ++ double prevY = player.getY(); ++ double prevZ = player.getZ(); ++ float prevYaw = player.getYRot(); ++ float prevPitch = player.getXRot(); ++ // CraftBukkit end ++ double d3 = this.player.getX(); ++ double d4 = this.player.getY(); ++ double d5 = this.player.getZ(); ++ double d6 = d0 - this.firstGoodX; ++ double d7 = d1 - this.firstGoodY; ++ double d8 = d2 - this.firstGoodZ; ++ double d9 = this.player.getDeltaMovement().lengthSqr(); ++ double d10 = d6 * d6 + d7 * d7 + d8 * d8; ++ + if (this.player.isSleeping()) { + if (d7 > 1.0) { + this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), f, f1); +@@ -884,8 +1162,14 @@ + if (serverLevel.tickRateManager().runsNormally()) { + this.receivedMovePacketCount++; + int i = this.receivedMovePacketCount - this.knownMovePacketCount; +- if (i > 5) { +- LOGGER.debug("{} is sending move packets too frequently ({} packets since last tick)", this.player.getName().getString(), i); ++ ++ // CraftBukkit start - handle custom speeds and skipped ticks ++ this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick; ++ this.allowedPlayerTicks = Math.max(this.allowedPlayerTicks, 1); ++ this.lastTick = (int) (System.currentTimeMillis() / 50); ++ ++ if (i > Math.max(this.allowedPlayerTicks, 5)) { ++ ServerGamePacketListenerImpl.LOGGER.debug("{} is sending move packets too frequently ({} packets since last tick)", this.player.getName().getString(), i); + i = 1; + } + +@@ -895,8 +1187,10 @@ + || !this.player.isFallFlying() + )) { + float f2 = this.player.isFallFlying() ? 300.0F : 100.0F; +- if (d7 - d6 > (double)(f2 * (float)i) && !this.isSingleplayerOwner()) { +- LOGGER.warn("{} moved too quickly! {},{},{}", this.player.getName().getString(), d3, d4, d5); ++ ++ if (d10 - d9 > Math.max(f2, Math.pow((double) (10.0F * (float) i * speed), 2)) && !this.isSingleplayerOwner()) { ++ // CraftBukkit end ++ ServerGamePacketListenerImpl.LOGGER.warn("{} moved too quickly! {},{},{}", new Object[]{this.player.getName().getString(), d6, d7, d8}); + this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot()); + return; + } +@@ -913,11 +1209,15 @@ + } + + boolean flag1 = this.player.verticalCollisionBelow; +- this.player.move(MoverType.PLAYER, new Vec3(d3, d4, d5)); +- d3 = d - this.player.getX(); +- double var36 = d1 - this.player.getY(); +- if (var36 > -0.5 || var36 < 0.5) { +- var36 = 0.0; ++ ++ this.player.move(EnumMoveType.PLAYER, new Vec3(d6, d7, d8)); ++ this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move ++ double d11 = d7; ++ ++ d6 = d0 - this.player.getX(); ++ d7 = d1 - this.player.getY(); ++ if (d7 > -0.5D || d7 < 0.5D) { ++ d7 = 0.0D; + } + + d5 = d2 - this.player.getZ(); +@@ -932,20 +1229,73 @@ + LOGGER.warn("{} moved wrongly!", this.player.getName().getString()); + } + +- if (this.player.noPhysics +- || this.player.isSleeping() +- || (!flag2 || !serverLevel.noCollision(this.player, boundingBox)) +- && !this.isPlayerCollidingWithAnythingNew(serverLevel, boundingBox, d, d1, d2)) { +- this.player.absMoveTo(d, d1, d2, f, f1); +- this.clientIsFloating = d4 >= -0.03125 +- && !flag1 +- && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR +- && !this.server.isFlightAllowed() +- && !this.player.getAbilities().mayfly +- && !this.player.hasEffect(MobEffects.LEVITATION) +- && !this.player.isFallFlying() +- && !this.player.isAutoSpinAttack() +- && this.noBlocksAround(this.player); ++ if (!this.player.noPhysics && !this.player.isSleeping() && (flag2 && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb, d0, d1, d2))) { ++ this.internalTeleport(d3, d4, d5, f, f1, Collections.emptySet()); // CraftBukkit - SPIGOT-1807: Don't call teleport event, when the client thinks the player is falling, because the chunks are not loaded on the client yet. ++ this.player.doCheckFallDamage(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5, packet.isOnGround()); ++ } else { ++ // CraftBukkit start - fire PlayerMoveEvent ++ // Reset to old location first ++ this.player.absMoveTo(prevX, prevY, prevZ, prevYaw, prevPitch); ++ ++ Player player = this.getCraftPlayer(); ++ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. ++ Location to = player.getLocation().clone(); // Start off the To location as the Players current location. ++ ++ // If the packet contains movement information then we update the To location with the correct XYZ. ++ if (packet.hasPos) { ++ to.setX(packet.x); ++ to.setY(packet.y); ++ to.setZ(packet.z); ++ } ++ ++ // If the packet contains look information then we update the To location with the correct Yaw & Pitch. ++ if (packet.hasRot) { ++ to.setYaw(packet.yRot); ++ to.setPitch(packet.xRot); ++ } ++ ++ // Prevent 40 event-calls for less than a single pixel of movement >.> ++ double delta = Math.pow(this.lastPosX - to.getX(), 2) + Math.pow(this.lastPosY - to.getY(), 2) + Math.pow(this.lastPosZ - to.getZ(), 2); ++ float deltaAngle = Math.abs(this.lastYaw - to.getYaw()) + Math.abs(this.lastPitch - to.getPitch()); ++ ++ if ((delta > 1f / 256 || deltaAngle > 10f) && !this.player.isImmobile()) { ++ this.lastPosX = to.getX(); ++ this.lastPosY = to.getY(); ++ this.lastPosZ = to.getZ(); ++ this.lastYaw = to.getYaw(); ++ this.lastPitch = to.getPitch(); ++ ++ // Skip the first time we do this ++ if (from.getX() != Double.MAX_VALUE) { ++ Location oldTo = to.clone(); ++ PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ // If the event is cancelled we move the player back to their old location. ++ if (event.isCancelled()) { ++ teleport(from); ++ return; ++ } ++ ++ // If a Plugin has changed the To destination then we teleport the Player ++ // there to avoid any 'Moved wrongly' or 'Moved too quickly' errors. ++ // We only do this if the Event was not cancelled. ++ if (!oldTo.equals(event.getTo()) && !event.isCancelled()) { ++ this.player.getBukkitEntity().teleport(event.getTo(), PlayerTeleportEvent.TeleportCause.PLUGIN); ++ return; ++ } ++ ++ // Check to see if the Players Location has some how changed during the call of the event. ++ // This can happen due to a plugin teleporting the player instead of using .setTo() ++ if (!from.equals(this.getCraftPlayer().getLocation()) && this.justTeleported) { ++ this.justTeleported = false; ++ return; ++ } ++ } ++ } ++ // CraftBukkit end ++ this.player.absMoveTo(d0, d1, d2, f, f1); ++ this.clientIsFloating = d11 >= -0.03125D && !flag1 && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR && !this.server.isFlightAllowed() && !this.player.getAbilities().mayfly && !this.player.hasEffect(MobEffects.LEVITATION) && !this.player.isFallFlying() && !this.player.isAutoSpinAttack() && this.noBlocksAround(this.player); + this.player.serverLevel().getChunkSource().move(this.player); + this.player.doCheckFallDamage(this.player.getX() - x, this.player.getY() - y, this.player.getZ() - z, packet.isOnGround()); + this.player +@@ -980,26 +1327,94 @@ + if (!Shapes.joinIsNotEmpty(voxelShape1, voxelShape, BooleanOp.AND)) { + return true; + } ++ ++ voxelshape1 = (VoxelShape) iterator.next(); ++ } while (Shapes.joinIsNotEmpty(voxelshape1, voxelshape, BooleanOp.AND)); ++ ++ return true; ++ } ++ ++ // CraftBukkit start - Delegate to teleport(Location) ++ public void teleport(double x, double d1, double y, float f, float z) { ++ this.teleport(x, d1, y, f, z, PlayerTeleportEvent.TeleportCause.UNKNOWN); ++ } ++ ++ public void teleport(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { ++ this.teleport(d0, d1, d2, f, f1, Collections.emptySet(), cause); ++ } ++ ++ public void teleport(double x, double d1, double y, float f, float z, Set set) { ++ this.teleport(x, d1, y, f, z, set, PlayerTeleportEvent.TeleportCause.UNKNOWN); ++ } ++ ++ public boolean teleport(double d0, double d1, double d2, float f, float f1, Set set, PlayerTeleportEvent.TeleportCause cause) { // CraftBukkit - Return event status ++ Player player = this.getCraftPlayer(); ++ Location from = player.getLocation(); ++ ++ double x = d0; ++ double y = d1; ++ double z = d2; ++ float yaw = f; ++ float pitch = f1; ++ ++ Location to = new Location(this.getCraftPlayer().getWorld(), x, y, z, yaw, pitch); ++ // SPIGOT-5171: Triggered on join ++ if (from.equals(to)) { ++ this.internalTeleport(d0, d1, d2, f, f1, set); ++ return false; // CraftBukkit - Return event status + } + +- return false; ++ PlayerTeleportEvent event = new PlayerTeleportEvent(player, from.clone(), to.clone(), cause); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled() || !to.equals(event.getTo())) { ++ set.clear(); // Can't relative teleport ++ to = event.isCancelled() ? event.getFrom() : event.getTo(); ++ d0 = to.getX(); ++ d1 = to.getY(); ++ d2 = to.getZ(); ++ f = to.getYaw(); ++ f1 = to.getPitch(); ++ } ++ ++ this.internalTeleport(d0, d1, d2, f, f1, set); ++ return event.isCancelled(); // CraftBukkit - Return event status + } + + public void teleport(double x, double y, double z, float yaw, float pitch) { + this.teleport(x, y, z, yaw, pitch, Collections.emptySet()); + } + +- public void teleport(double x, double y, double z, float yaw, float pitch, Set relativeSet) { +- double d = relativeSet.contains(RelativeMovement.X) ? this.player.getX() : 0.0; +- double d1 = relativeSet.contains(RelativeMovement.Y) ? this.player.getY() : 0.0; +- double d2 = relativeSet.contains(RelativeMovement.Z) ? this.player.getZ() : 0.0; +- float f = relativeSet.contains(RelativeMovement.Y_ROT) ? this.player.getYRot() : 0.0F; +- float f1 = relativeSet.contains(RelativeMovement.X_ROT) ? this.player.getXRot() : 0.0F; +- this.awaitingPositionFromClient = new Vec3(x, y, z); ++ private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set set) { ++ // CraftBukkit start ++ if (Float.isNaN(f)) { ++ f = 0; ++ } ++ if (Float.isNaN(f1)) { ++ f1 = 0; ++ } ++ ++ this.justTeleported = true; ++ // CraftBukkit end ++ double d3 = set.contains(RelativeMovement.X) ? this.player.getX() : 0.0D; ++ double d4 = set.contains(RelativeMovement.Y) ? this.player.getY() : 0.0D; ++ double d5 = set.contains(RelativeMovement.Z) ? this.player.getZ() : 0.0D; ++ float f2 = set.contains(RelativeMovement.Y_ROT) ? this.player.getYRot() : 0.0F; ++ float f3 = set.contains(RelativeMovement.X_ROT) ? this.player.getXRot() : 0.0F; ++ ++ this.awaitingPositionFromClient = new Vec3(d0, d1, d2); + if (++this.awaitingTeleport == Integer.MAX_VALUE) { + this.awaitingTeleport = 0; + } + ++ // CraftBukkit start - update last location ++ this.lastPosX = this.awaitingPositionFromClient.x; ++ this.lastPosY = this.awaitingPositionFromClient.y; ++ this.lastPosZ = this.awaitingPositionFromClient.z; ++ this.lastYaw = f; ++ this.lastPitch = f1; ++ // CraftBukkit end ++ + this.awaitingTeleportTime = this.tickCount; + this.player.absMoveTo(x, y, z, yaw, pitch); + this.player.connection.send(new ClientboundPlayerPositionPacket(x - d, y - d1, z - d2, yaw - f, pitch - f1, relativeSet, this.awaitingTeleport)); +@@ -1008,21 +1423,56 @@ + @Override + public void handlePlayerAction(ServerboundPlayerActionPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); +- BlockPos pos = packet.getPos(); ++ if (this.player.isImmobile()) return; // CraftBukkit ++ BlockPos blockposition = packet.getPos(); ++ + this.player.resetLastActionTime(); + ServerboundPlayerActionPacket.Action action = packet.getAction(); + switch (action) { + case SWAP_ITEM_WITH_OFFHAND: + if (!this.player.isSpectator()) { +- ItemStack itemInHand = this.player.getItemInHand(InteractionHand.OFF_HAND); +- this.player.setItemInHand(InteractionHand.OFF_HAND, this.player.getItemInHand(InteractionHand.MAIN_HAND)); +- this.player.setItemInHand(InteractionHand.MAIN_HAND, itemInHand); ++ ItemStack itemstack = this.player.getItemInHand(EnumHand.OFF_HAND); ++ ++ // CraftBukkit start - inspiration taken from DispenserRegistry (See SpigotCraft#394) ++ CraftItemStack mainHand = CraftItemStack.asCraftMirror(itemstack); ++ CraftItemStack offHand = CraftItemStack.asCraftMirror(this.player.getItemInHand(EnumHand.MAIN_HAND)); ++ PlayerSwapHandItemsEvent swapItemsEvent = new PlayerSwapHandItemsEvent(getCraftPlayer(), mainHand.clone(), offHand.clone()); ++ this.cserver.getPluginManager().callEvent(swapItemsEvent); ++ if (swapItemsEvent.isCancelled()) { ++ return; ++ } ++ if (swapItemsEvent.getOffHandItem().equals(offHand)) { ++ this.player.setItemInHand(EnumHand.OFF_HAND, this.player.getItemInHand(EnumHand.MAIN_HAND)); ++ } else { ++ this.player.setItemInHand(EnumHand.OFF_HAND, CraftItemStack.asNMSCopy(swapItemsEvent.getOffHandItem())); ++ } ++ if (swapItemsEvent.getMainHandItem().equals(mainHand)) { ++ this.player.setItemInHand(EnumHand.MAIN_HAND, itemstack); ++ } else { ++ this.player.setItemInHand(EnumHand.MAIN_HAND, CraftItemStack.asNMSCopy(swapItemsEvent.getMainHandItem())); ++ } ++ // CraftBukkit end + this.player.stopUsingItem(); + } + + return; + case DROP_ITEM: + if (!this.player.isSpectator()) { ++ // limit how quickly items can be dropped ++ // If the ticks aren't the same then the count starts from 0 and we update the lastDropTick. ++ if (this.lastDropTick != MinecraftServer.currentTick) { ++ this.dropCount = 0; ++ this.lastDropTick = MinecraftServer.currentTick; ++ } else { ++ // Else we increment the drop count and check the amount. ++ this.dropCount++; ++ if (this.dropCount >= 20) { ++ LOGGER.warn(this.player.getScoreboardName() + " dropped their items too quickly!"); ++ this.disconnect("You dropped your items too quickly (Hacking?)"); ++ return; ++ } ++ } ++ // CraftBukkit end + this.player.drop(false); + } + +@@ -1059,6 +1511,7 @@ + @Override + public void handleUseItemOn(ServerboundUseItemOnPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.connection.ackBlockChangesUpTo(packet.getSequence()); + ServerLevel serverLevel = this.player.serverLevel(); + InteractionHand hand = packet.getHand(); +@@ -1074,20 +1531,19 @@ + if (Math.abs(vec31.x()) < 1.0000001 && Math.abs(vec31.y()) < 1.0000001 && Math.abs(vec31.z()) < 1.0000001) { + Direction direction = hitResult.getDirection(); + this.player.resetLastActionTime(); +- int maxBuildHeight = this.player.level().getMaxBuildHeight(); +- if (blockPos.getY() < maxBuildHeight) { +- if (this.awaitingPositionFromClient == null +- && this.player.distanceToSqr((double)blockPos.getX() + 0.5, (double)blockPos.getY() + 0.5, (double)blockPos.getZ() + 0.5) < 64.0 +- && serverLevel.mayInteract(this.player, blockPos)) { +- InteractionResult interactionResult = this.player.gameMode.useItemOn(this.player, serverLevel, itemInHand, hand, hitResult); +- if (direction == Direction.UP +- && !interactionResult.consumesAction() +- && blockPos.getY() >= maxBuildHeight - 1 +- && wasBlockPlacementAttempt(this.player, itemInHand)) { +- Component component = Component.translatable("build.tooHigh", maxBuildHeight - 1).withStyle(ChatFormatting.RED); +- this.player.sendSystemMessage(component, true); +- } else if (interactionResult.shouldSwing()) { +- this.player.swing(hand, true); ++ int i = this.player.level().getMaxBuildHeight(); ++ ++ if (blockposition.getY() < i) { ++ if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.mayInteract(this.player, blockposition)) { ++ this.player.stopUsingItem(); // CraftBukkit - SPIGOT-4706 ++ InteractionResult enuminteractionresult = this.player.gameMode.useItemOn(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock); ++ ++ if (enumdirection == Direction.UP && !enuminteractionresult.consumesAction() && blockposition.getY() >= i - 1 && wasBlockPlacementAttempt(this.player, itemstack)) { ++ MutableComponent ichatmutablecomponent = Component.translatable("build.tooHigh", i - 1).withStyle(ChatFormatting.RED); ++ ++ this.player.sendSystemMessage(ichatmutablecomponent, true); ++ } else if (enuminteractionresult.shouldSwing()) { ++ this.player.swing(enumhand, true); + } + } + } else { +@@ -1112,16 +1564,62 @@ + @Override + public void handleUseItem(ServerboundUseItemPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.ackBlockChangesUpTo(packet.getSequence()); + ServerLevel serverLevel = this.player.serverLevel(); + InteractionHand hand = packet.getHand(); + ItemStack itemInHand = this.player.getItemInHand(hand); + this.player.resetLastActionTime(); +- if (!itemInHand.isEmpty() && itemInHand.isItemEnabled(serverLevel.enabledFeatures())) { +- InteractionResult interactionResult = this.player.gameMode.useItem(this.player, serverLevel, itemInHand, hand); +- if (interactionResult.shouldSwing()) { +- this.player.swing(hand, true); ++ if (!itemstack.isEmpty() && itemstack.isItemEnabled(worldserver.enabledFeatures())) { ++ // CraftBukkit start ++ // Raytrace to look for 'rogue armswings' ++ float f1 = this.player.getXRot(); ++ float f2 = this.player.getYRot(); ++ double d0 = this.player.getX(); ++ double d1 = this.player.getY() + (double) this.player.getEyeHeight(); ++ double d2 = this.player.getZ(); ++ Vec3 vec3d = new Vec3(d0, d1, d2); ++ ++ float f3 = Mth.cos(-f2 * 0.017453292F - 3.1415927F); ++ float f4 = Mth.sin(-f2 * 0.017453292F - 3.1415927F); ++ float f5 = -Mth.cos(-f1 * 0.017453292F); ++ float f6 = Mth.sin(-f1 * 0.017453292F); ++ float f7 = f4 * f5; ++ float f8 = f3 * f5; ++ double d3 = player.gameMode.getGameModeForPlayer()== GameType.CREATIVE ? 5.0D : 4.5D; ++ Vec3 vec3d1 = vec3d.add((double) f7 * d3, (double) f6 * d3, (double) f8 * d3); ++ HitResult movingobjectposition = this.player.level().clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)); ++ ++ boolean cancelled; ++ if (movingobjectposition == null || movingobjectposition.getType() != HitResult.EnumMovingObjectType.BLOCK) { ++ org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.RIGHT_CLICK_AIR, itemstack, enumhand); ++ cancelled = event.useItemInHand() == Event.Result.DENY; ++ } else { ++ BlockHitResult movingobjectpositionblock = (BlockHitResult) movingobjectposition; ++ if (player.gameMode.firedInteract && player.gameMode.interactPosition.equals(movingobjectpositionblock.getBlockPos()) && player.gameMode.interactHand == enumhand && ItemStack.isSameItemSameTags(player.gameMode.interactItemStack, itemstack)) { ++ cancelled = player.gameMode.interactResult; ++ } else { ++ org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), itemstack, true, enumhand, movingobjectpositionblock.getLocation()); ++ cancelled = event.useItemInHand() == Event.Result.DENY; ++ } ++ player.gameMode.firedInteract = false; + } ++ ++ if (cancelled) { ++ this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524 ++ return; ++ } ++ itemstack = this.player.getItemInHand(enumhand); // Update in case it was changed in the event ++ if (itemstack.isEmpty()) { ++ return; ++ } ++ // CraftBukkit end ++ InteractionResult enuminteractionresult = this.player.gameMode.useItem(this.player, worldserver, itemstack, enumhand); ++ ++ if (enuminteractionresult.shouldSwing()) { ++ this.player.swing(enumhand, true); ++ } ++ + } + } + +@@ -1132,7 +1635,7 @@ + for (ServerLevel serverLevel : this.server.getAllLevels()) { + Entity entity = packet.getEntity(serverLevel); + if (entity != null) { +- this.player.teleportTo(serverLevel, entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot()); ++ this.player.teleportTo(worldserver, entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot(), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.SPECTATE); // CraftBukkit + return; + } + } +@@ -1149,19 +1658,32 @@ + + @Override + public void onDisconnect(Component reason) { +- LOGGER.info("{} lost connection: {}", this.player.getName().getString(), reason.getString()); ++ // CraftBukkit start - Rarely it would send a disconnect line twice ++ if (this.processedDisconnect) { ++ return; ++ } else { ++ this.processedDisconnect = true; ++ } ++ // CraftBukkit end ++ ServerGamePacketListenerImpl.LOGGER.info("{} lost connection: {}", this.player.getName().getString(), reason.getString()); + this.removePlayerFromWorld(); + super.onDisconnect(reason); + } + + private void removePlayerFromWorld() { + this.chatMessageChain.close(); ++ // CraftBukkit start - Replace vanilla quit message handling with our own. ++ /* + this.server.invalidateStatus(); + this.server + .getPlayerList() + .broadcastSystemMessage(Component.translatable("multiplayer.player.left", this.player.getDisplayName()).withStyle(ChatFormatting.YELLOW), false); + this.player.disconnect(); +- this.server.getPlayerList().remove(this.player); ++ String quitMessage = this.server.getPlayerList().remove(this.player); ++ if ((quitMessage != null) && (quitMessage.length() > 0)) { ++ this.server.getPlayerList().broadcastMessage(CraftChatMessage.fromString(quitMessage)); ++ } ++ // CraftBukkit end + this.player.getTextFilter().leave(); + } + +@@ -1176,27 +1698,44 @@ + @Override + public void handleSetCarriedItem(ServerboundSetCarriedItemPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + if (packet.getSlot() >= 0 && packet.getSlot() < Inventory.getSelectionSize()) { +- if (this.player.getInventory().selected != packet.getSlot() && this.player.getUsedItemHand() == InteractionHand.MAIN_HAND) { ++ PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getCraftPlayer(), this.player.getInventory().selected, packet.getSlot()); ++ this.cserver.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ this.send(new ClientboundSetCarriedItemPacket(this.player.getInventory().selected)); ++ this.player.resetLastActionTime(); ++ return; ++ } ++ // CraftBukkit end ++ if (this.player.getInventory().selected != packet.getSlot() && this.player.getUsedItemHand() == EnumHand.MAIN_HAND) { + this.player.stopUsingItem(); + } + + this.player.getInventory().selected = packet.getSlot(); + this.player.resetLastActionTime(); + } else { +- LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); ++ ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); ++ this.disconnect("Invalid hotbar selection (Hacking?)"); // CraftBukkit + } + } + + @Override + public void handleChat(ServerboundChatPacket packet) { ++ // CraftBukkit start - async chat ++ // SPIGOT-3638 ++ if (this.server.isStopped()) { ++ return; ++ } ++ // CraftBukkit end + if (isChatMessageIllegal(packet.message())) { + this.disconnect(Component.translatable("multiplayer.disconnect.illegal_characters")); + } else { + Optional optional = this.tryHandleChat(packet.lastSeenMessages()); + if (optional.isPresent()) { +- this.server.submit(() -> { +- PlayerChatMessage signedMessage; ++ // this.server.submit(() -> { // CraftBukkit - async chat ++ PlayerChatMessage playerchatmessage; ++ + try { + signedMessage = this.getSignedMessage(packet, optional.get()); + } catch (SignedMessageChain.DecodeException var6) { +@@ -1204,13 +1744,15 @@ + return; + } + +- CompletableFuture completableFuture = this.filterTextPacket(signedMessage.signedContent()); +- Component component = this.server.getChatDecorator().decorate(this.player, signedMessage.decoratedContent()); +- this.chatMessageChain.append(completableFuture, filteredText -> { +- PlayerChatMessage playerChatMessage = signedMessage.withUnsignedContent(component).filter(filteredText.mask()); +- this.broadcastChatMessage(playerChatMessage); ++ CompletableFuture completablefuture = this.filterTextPacket(playerchatmessage.signedContent()).thenApplyAsync(Function.identity(), this.server.chatExecutor); // CraftBukkit - async chat ++ Component ichatbasecomponent = this.server.getChatDecorator().decorate(this.player, playerchatmessage.decoratedContent()); ++ ++ this.chatMessageChain.append(completablefuture, (filteredtext) -> { ++ PlayerChatMessage playerchatmessage1 = playerchatmessage.withUnsignedContent(ichatbasecomponent).filter(filteredtext.mask()); ++ ++ this.broadcastChatMessage(playerchatmessage1); + }); +- }); ++ // }); // CraftBukkit - async chat + } + } + } +@@ -1223,7 +1767,13 @@ + Optional optional = this.tryHandleChat(packet.lastSeenMessages()); + if (optional.isPresent()) { + this.server.submit(() -> { +- this.performChatCommand(packet, optional.get()); ++ // CraftBukkit start - SPIGOT-7346: Prevent disconnected players from executing commands ++ if (player.hasDisconnected()) { ++ return; ++ } ++ // CraftBukkit end ++ ++ this.performChatCommand(packet, (LastSeenMessages) optional.get()); + this.detectRateSpam(); + }); + } +@@ -1231,21 +1782,36 @@ + } + + private void performChatCommand(ServerboundChatCommandPacket packet, LastSeenMessages lastSeenMessages) { +- ParseResults parseResults = this.parseCommand(packet.command()); ++ // CraftBukkit start ++ String command = "/" + packet.command(); ++ ServerGamePacketListenerImpl.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + command); + +- Map map; ++ PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(getCraftPlayer(), command, new LazyPlayerSet(server)); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ command = event.getMessage().substring(1); ++ ++ ParseResults parseresults = this.parseCommand(command); ++ // CraftBukkit end ++ ++ Map map; ++ + try { +- map = this.collectSignedArguments(packet, SignableCommand.of(parseResults), lastSeenMessages); +- } catch (SignedMessageChain.DecodeException var6) { +- this.handleMessageDecodeFailure(var6); ++ map = (packet.command().equals(command)) ? this.collectSignedArguments(packet, SignableCommand.of(parseresults), lastSeenMessages) : Collections.emptyMap(); // CraftBukkit ++ } catch (SignedMessageChain.DecodeException signedmessagechain_a) { ++ this.handleMessageDecodeFailure(signedmessagechain_a); + return; + } + +- CommandSigningContext commandSigningContext = new CommandSigningContext.SignedArguments(map); +- parseResults = Commands.mapSource( +- parseResults, commandSourceStack -> commandSourceStack.withSigningContext(commandSigningContext, this.chatMessageChain) +- ); +- this.server.getCommands().performCommand(parseResults, packet.command()); ++ CommandSigningContext.a commandsigningcontext_a = new CommandSigningContext.a(map); ++ ++ parseresults = Commands.mapSource(parseresults, (commandlistenerwrapper) -> { // CraftBukkit - decompile error ++ return commandlistenerwrapper.withSigningContext(commandsigningcontext_a, this.chatMessageChain); ++ }); ++ this.server.getCommands().performCommand(parseresults, command); // CraftBukkit + } + + private void handleMessageDecodeFailure(SignedMessageChain.DecodeException exception) { +@@ -1276,9 +1845,10 @@ + return dispatcher.parse(command, this.player.createCommandSourceStack()); + } + +- private Optional tryHandleChat(LastSeenMessages.Update update) { +- Optional optional = this.unpackAndApplyLastSeen(update); +- if (this.player.getChatVisibility() == ChatVisiblity.HIDDEN) { ++ private Optional tryHandleChat(LastSeenMessages.Update lastseenmessages_b) { ++ Optional optional = this.unpackAndApplyLastSeen(lastseenmessages_b); ++ ++ if (this.player.isRemoved() || this.player.getChatVisibility() == ChatVisiblity.HIDDEN) { // CraftBukkit - dead men tell no tales + this.send(new ClientboundSystemChatPacket(Component.translatable("chat.disabled.options").withStyle(ChatFormatting.RED), false)); + return Optional.empty(); + } else { +@@ -1309,19 +1882,149 @@ + return false; + } + ++ // CraftBukkit start - add method ++ public void chat(String s, PlayerChatMessage original, boolean async) { ++ if (s.isEmpty() || this.player.getChatVisibility() == ChatVisiblity.HIDDEN) { ++ return; ++ } ++ OutgoingChatMessage outgoing = OutgoingChatMessage.create(original); ++ ++ if (!async && s.startsWith("/")) { ++ this.handleCommand(s); ++ } else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { ++ // Do nothing, this is coming from a plugin ++ } else { ++ Player player = this.getCraftPlayer(); ++ AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(server)); ++ String originalFormat = event.getFormat(), originalMessage = event.getMessage(); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (PlayerChatEvent.getHandlerList().getRegisteredListeners().length != 0) { ++ // Evil plugins still listening to deprecated event ++ final PlayerChatEvent queueEvent = new PlayerChatEvent(player, event.getMessage(), event.getFormat(), event.getRecipients()); ++ queueEvent.setCancelled(event.isCancelled()); ++ Waitable waitable = new Waitable() { ++ @Override ++ protected Object evaluate() { ++ org.bukkit.Bukkit.getPluginManager().callEvent(queueEvent); ++ ++ if (queueEvent.isCancelled()) { ++ return null; ++ } ++ ++ String message = String.format(queueEvent.getFormat(), queueEvent.getPlayer().getDisplayName(), queueEvent.getMessage()); ++ if (((LazyPlayerSet) queueEvent.getRecipients()).isLazy()) { ++ if (originalFormat.equals(queueEvent.getFormat()) && originalMessage.equals(queueEvent.getMessage()) && queueEvent.getPlayer().getName().equalsIgnoreCase(queueEvent.getPlayer().getDisplayName())) { ++ ServerGamePacketListenerImpl.this.server.getPlayerList().broadcastChatMessage(original, ServerGamePacketListenerImpl.this.player, ChatType.bind(ChatType.CHAT, (Entity) ServerGamePacketListenerImpl.this.player)); ++ return null; ++ } ++ ++ for (ServerPlayer recipient : server.getPlayerList().players) { ++ recipient.getBukkitEntity().sendMessage(ServerGamePacketListenerImpl.this.player.getUUID(), message); ++ } ++ } else { ++ for (Player player : queueEvent.getRecipients()) { ++ player.sendMessage(ServerGamePacketListenerImpl.this.player.getUUID(), message); ++ } ++ } ++ ServerGamePacketListenerImpl.this.server.console.sendMessage(message); ++ ++ return null; ++ }}; ++ if (async) { ++ server.processQueue.add(waitable); ++ } else { ++ waitable.run(); ++ } ++ try { ++ waitable.get(); ++ } catch (InterruptedException e) { ++ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on! ++ } catch (ExecutionException e) { ++ throw new RuntimeException("Exception processing chat event", e.getCause()); ++ } ++ } else { ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ s = String.format(event.getFormat(), event.getPlayer().getDisplayName(), event.getMessage()); ++ if (((LazyPlayerSet) event.getRecipients()).isLazy()) { ++ if (originalFormat.equals(event.getFormat()) && originalMessage.equals(event.getMessage()) && event.getPlayer().getName().equalsIgnoreCase(event.getPlayer().getDisplayName())) { ++ ServerGamePacketListenerImpl.this.server.getPlayerList().broadcastChatMessage(original, ServerGamePacketListenerImpl.this.player, ChatType.bind(ChatType.CHAT, (Entity) ServerGamePacketListenerImpl.this.player)); ++ return; ++ } ++ ++ for (ServerPlayer recipient : server.getPlayerList().players) { ++ recipient.getBukkitEntity().sendMessage(ServerGamePacketListenerImpl.this.player.getUUID(), s); ++ } ++ } else { ++ for (Player recipient : event.getRecipients()) { ++ recipient.sendMessage(ServerGamePacketListenerImpl.this.player.getUUID(), s); ++ } ++ } ++ server.console.sendMessage(s); ++ } ++ } ++ } ++ ++ private void handleCommand(String s) { ++ this.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + s); ++ ++ CraftPlayer player = this.getCraftPlayer(); ++ ++ PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(player, s, new LazyPlayerSet(server)); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ try { ++ if (this.cserver.dispatchCommand(event.getPlayer(), event.getMessage().substring(1))) { ++ return; ++ } ++ } catch (org.bukkit.command.CommandException ex) { ++ player.sendMessage(org.bukkit.ChatColor.RED + "An internal error occurred while attempting to perform this command"); ++ java.util.logging.Logger.getLogger(ServerGamePacketListenerImpl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); ++ return; ++ } ++ } ++ // CraftBukkit end ++ + private PlayerChatMessage getSignedMessage(ServerboundChatPacket packet, LastSeenMessages lastSeenMessages) throws SignedMessageChain.DecodeException { + SignedMessageBody signedMessageBody = new SignedMessageBody(packet.message(), packet.timeStamp(), packet.salt(), lastSeenMessages); + return this.signedMessageDecoder.unpack(packet.signature(), signedMessageBody); + } + + private void broadcastChatMessage(PlayerChatMessage message) { +- this.server.getPlayerList().broadcastChatMessage(message, this.player, ChatType.bind(ChatType.CHAT, this.player)); ++ // CraftBukkit start ++ String s = message.signedContent(); ++ if (s.isEmpty()) { ++ LOGGER.warn(this.player.getScoreboardName() + " tried to send an empty message"); ++ } else if (getCraftPlayer().isConversing()) { ++ final String conversationInput = s; ++ this.server.processQueue.add(new Runnable() { ++ @Override ++ public void run() { ++ getCraftPlayer().acceptConversationInput(conversationInput); ++ } ++ }); ++ } else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { // Re-add "Command Only" flag check ++ this.send(new ClientboundSystemChatPacket(Component.translatable("chat.cannotSend").withStyle(ChatFormatting.RED), false)); ++ } else { ++ this.chat(s, message, true); ++ } ++ // this.server.getPlayerList().broadcastChatMessage(playerchatmessage, this.player, ChatMessageType.bind(ChatMessageType.CHAT, (Entity) this.player)); ++ // CraftBukkit end + this.detectRateSpam(); + } + + private void detectRateSpam() { +- this.chatSpamTickCount += 20; +- if (this.chatSpamTickCount > 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { ++ // CraftBukkit start - replaced with thread safe throttle ++ // this.chatSpamTickCount += 20; ++ if (this.chatSpamTickCount.addAndGet(20) > 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { ++ // CraftBukkit end + this.disconnect(Component.translatable("disconnect.spam")); + } + } +@@ -1339,13 +2047,62 @@ + @Override + public void handleAnimate(ServerboundSwingPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.resetLastActionTime(); ++ // CraftBukkit start - Raytrace to look for 'rogue armswings' ++ float f1 = this.player.getXRot(); ++ float f2 = this.player.getYRot(); ++ double d0 = this.player.getX(); ++ double d1 = this.player.getY() + (double) this.player.getEyeHeight(); ++ double d2 = this.player.getZ(); ++ Location origin = new Location(this.player.level().getWorld(), d0, d1, d2, f2, f1); ++ ++ double d3 = player.gameMode.getGameModeForPlayer() == GameType.CREATIVE ? 5.0D : 4.5D; ++ // SPIGOT-5607: Only call interact event if no block or entity is being clicked. Use bukkit ray trace method, because it handles blocks and entities at the same time ++ // SPIGOT-7429: Make sure to call PlayerInteractEvent for spectators and non-pickable entities ++ org.bukkit.util.RayTraceResult result = this.player.level().getWorld().rayTrace(origin, origin.getDirection(), d3, org.bukkit.FluidCollisionMode.NEVER, false, 0.1, entity -> { ++ Entity handle = ((CraftEntity) entity).getHandle(); ++ return entity != this.player.getBukkitEntity() && this.player.getBukkitEntity().canSee(entity) && !handle.isSpectator() && handle.isPickable() && !handle.isPassengerOfSameVehicle(player); ++ }); ++ if (result == null) { ++ CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_AIR, this.player.getInventory().getSelected(), EnumHand.MAIN_HAND); ++ } ++ ++ // Arm swing animation ++ PlayerAnimationEvent event = new PlayerAnimationEvent(this.getCraftPlayer(), (packet.getHand() == EnumHand.MAIN_HAND) ? PlayerAnimationType.ARM_SWING : PlayerAnimationType.OFF_ARM_SWING); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) return; ++ // CraftBukkit end + this.player.swing(packet.getHand()); + } + + @Override + public void handlePlayerCommand(ServerboundPlayerCommandPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ // CraftBukkit start ++ if (this.player.isRemoved()) return; ++ switch (packet.getAction()) { ++ case PRESS_SHIFT_KEY: ++ case RELEASE_SHIFT_KEY: ++ PlayerToggleSneakEvent event = new PlayerToggleSneakEvent(this.getCraftPlayer(), packet.getAction() == ServerboundPlayerCommandPacket.EnumPlayerAction.PRESS_SHIFT_KEY); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ break; ++ case START_SPRINTING: ++ case STOP_SPRINTING: ++ PlayerToggleSprintEvent e2 = new PlayerToggleSprintEvent(this.getCraftPlayer(), packet.getAction() == ServerboundPlayerCommandPacket.EnumPlayerAction.START_SPRINTING); ++ this.cserver.getPluginManager().callEvent(e2); ++ ++ if (e2.isCancelled()) { ++ return; ++ } ++ break; ++ } ++ // CraftBukkit end + this.player.resetLastActionTime(); + switch (packet.getAction()) { + case PRESS_SHIFT_KEY: +@@ -1411,17 +2184,13 @@ + } + + public void sendPlayerChatMessage(PlayerChatMessage chatMessage, ChatType.Bound boundType) { +- this.send( +- new ClientboundPlayerChatPacket( +- chatMessage.link().sender(), +- chatMessage.link().index(), +- chatMessage.signature(), +- chatMessage.signedBody().pack(this.messageSignatureCache), +- chatMessage.unsignedContent(), +- chatMessage.filterMask(), +- boundType.toNetwork(this.player.level().registryAccess()) +- ) +- ); ++ // CraftBukkit start - SPIGOT-7262: if hidden we have to send as disguised message. Query whether we should send at all (but changing this may not be expected). ++ if (!getCraftPlayer().canSee(chatMessage.link().sender())) { ++ sendDisguisedChatMessage(chatMessage.decoratedContent(), boundType); ++ return; ++ } ++ // CraftBukkit end ++ this.send(new ClientboundPlayerChatPacket(chatMessage.link().sender(), chatMessage.link().index(), chatMessage.signature(), chatMessage.signedBody().pack(this.messageSignatureCache), chatMessage.unsignedContent(), chatMessage.filterMask(), boundType.toNetwork(this.player.level().registryAccess()))); + this.addPendingMessage(chatMessage); + } + +@@ -1447,8 +2216,10 @@ + @Override + public void handleInteract(ServerboundInteractPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); +- final ServerLevel serverLevel = this.player.serverLevel(); +- final Entity target = packet.getTarget(serverLevel); ++ if (this.player.isImmobile()) return; // CraftBukkit ++ final ServerLevel worldserver = this.player.serverLevel(); ++ final Entity entity = packet.getTarget(worldserver); ++ + this.player.resetLastActionTime(); + this.player.setShiftKeyDown(packet.isUsingSecondaryAction()); + if (target != null) { +@@ -1456,48 +2227,90 @@ + return; + } + +- AABB boundingBox = target.getBoundingBox(); +- if (boundingBox.distanceToSqr(this.player.getEyePosition()) < MAX_INTERACTION_DISTANCE) { +- packet.dispatch( +- new ServerboundInteractPacket.Handler() { +- private void performInteraction(InteractionHand hand, ServerGamePacketListenerImpl.EntityInteraction entityInteraction) { +- ItemStack itemInHand = ServerGamePacketListenerImpl.this.player.getItemInHand(hand); +- if (itemInHand.isItemEnabled(serverLevel.enabledFeatures())) { +- ItemStack itemStack = itemInHand.copy(); +- InteractionResult interactionResult = entityInteraction.run(ServerGamePacketListenerImpl.this.player, target, hand); +- if (interactionResult.consumesAction()) { +- CriteriaTriggers.PLAYER_INTERACTED_WITH_ENTITY.trigger(ServerGamePacketListenerImpl.this.player, itemStack, target); +- if (interactionResult.shouldSwing()) { +- ServerGamePacketListenerImpl.this.player.swing(hand, true); +- } ++ AABB axisalignedbb = entity.getBoundingBox(); ++ ++ if (axisalignedbb.distanceToSqr(this.player.getEyePosition()) < ServerGamePacketListenerImpl.MAX_INTERACTION_DISTANCE) { ++ packet.dispatch(new ServerboundInteractPacket.Handler() { ++ private void performInteraction(EnumHand enumhand, ServerGamePacketListenerImpl.EntityInteraction playerconnection_a, PlayerInteractEntityEvent event) { // CraftBukkit ++ ItemStack itemstack = ServerGamePacketListenerImpl.this.player.getItemInHand(enumhand); ++ ++ if (itemstack.isItemEnabled(worldserver.enabledFeatures())) { ++ ItemStack itemstack1 = itemstack.copy(); ++ // CraftBukkit start ++ ItemStack itemInHand = ServerGamePacketListenerImpl.this.player.getItemInHand(enumhand); ++ boolean triggerLeashUpdate = itemInHand != null && itemInHand.getItem() == Items.LEAD && entity instanceof Mob; ++ Item origItem = player.getInventory().getSelected() == null ? null : player.getInventory().getSelected().getItem(); ++ ++ cserver.getPluginManager().callEvent(event); ++ ++ // Entity in bucket - SPIGOT-4048 and SPIGOT-6859a ++ if ((entity instanceof Bucketable && entity instanceof LivingEntity && origItem != null && origItem.asItem() == Items.WATER_BUCKET) && (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem)) { ++ send(new ClientboundAddEntityPacket(entity)); ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ ++ if (triggerLeashUpdate && (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem)) { ++ // Refresh the current leash state ++ send(new ClientboundSetEntityLinkPacket(entity, ((Mob) entity).getLeashHolder())); ++ } ++ ++ if (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem) { ++ // Refresh the current entity metadata ++ entity.getEntityData().refresh(player); ++ // SPIGOT-7136 - Allays ++ if (entity instanceof Allay) { ++ send(new ClientboundSetEquipmentPacket(entity.getId(), Arrays.stream(net.minecraft.world.entity.EquipmentSlot.values()).map((slot) -> Pair.of(slot, ((LivingEntity) entity).getItemBySlot(slot).copy())).collect(Collectors.toList()))); ++ player.containerMenu.sendAllDataToRemote(); + } + } ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ InteractionResult enuminteractionresult = playerconnection_a.run(ServerGamePacketListenerImpl.this.player, entity, enumhand); ++ ++ // CraftBukkit start ++ if (!itemInHand.isEmpty() && itemInHand.getCount() <= -1) { ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ // CraftBukkit end ++ ++ if (enuminteractionresult.consumesAction()) { ++ CriteriaTriggers.PLAYER_INTERACTED_WITH_ENTITY.trigger(ServerGamePacketListenerImpl.this.player, itemstack1, entity); ++ if (enuminteractionresult.shouldSwing()) { ++ ServerGamePacketListenerImpl.this.player.swing(enumhand, true); ++ } ++ } ++ + } +- +- @Override +- public void onInteraction(InteractionHand hand) { +- this.performInteraction(hand, Player::interactOn); +- } +- +- @Override +- public void onInteraction(InteractionHand hand, Vec3 interactionLocation) { +- this.performInteraction(hand, (player, entity, hand1) -> entity.interactAt(player, interactionLocation, hand1)); +- } +- +- @Override +- public void onAttack() { +- if (!(target instanceof ItemEntity) +- && !(target instanceof ExperienceOrb) +- && !(target instanceof AbstractArrow) +- && target != ServerGamePacketListenerImpl.this.player) { +- ItemStack itemInHand = ServerGamePacketListenerImpl.this.player.getItemInHand(InteractionHand.MAIN_HAND); +- if (itemInHand.isItemEnabled(serverLevel.enabledFeatures())) { +- ServerGamePacketListenerImpl.this.player.attack(target); ++ } ++ ++ @Override ++ public void onInteraction(EnumHand hand) { ++ this.performInteraction(hand, net.minecraft.world.entity.player.Player::interactOn, new PlayerInteractEntityEvent(getCraftPlayer(), entity.getBukkitEntity(), (hand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); // CraftBukkit ++ } ++ ++ @Override ++ public void onInteraction(EnumHand hand, Vec3 interactionLocation) { ++ this.performInteraction(hand, (entityplayer, entity1, enumhand1) -> { ++ return entity1.interactAt(entityplayer, interactionLocation, enumhand1); ++ }, new PlayerInteractAtEntityEvent(getCraftPlayer(), entity.getBukkitEntity(), new org.bukkit.util.Vector(interactionLocation.x, interactionLocation.y, interactionLocation.z), (hand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); // CraftBukkit ++ } ++ ++ @Override ++ public void onAttack() { ++ // CraftBukkit ++ if (!(entity instanceof ItemEntity) && !(entity instanceof ExperienceOrb) && !(entity instanceof AbstractArrow) && (entity != ServerGamePacketListenerImpl.this.player || player.isSpectator())) { ++ ItemStack itemstack = ServerGamePacketListenerImpl.this.player.getItemInHand(EnumHand.MAIN_HAND); ++ ++ if (itemstack.isItemEnabled(worldserver.enabledFeatures())) { ++ ServerGamePacketListenerImpl.this.player.attack(entity); ++ // CraftBukkit start ++ if (!itemstack.isEmpty() && itemstack.getCount() <= -1) { ++ player.containerMenu.sendAllDataToRemote(); + } +- } else { +- ServerGamePacketListenerImpl.this.disconnect(Component.translatable("multiplayer.disconnect.invalid_entity_attacked")); +- ServerGamePacketListenerImpl.LOGGER +- .warn("Player {} tried to attack an invalid entity", ServerGamePacketListenerImpl.this.player.getName().getString()); ++ // CraftBukkit end + } + } + } +@@ -1537,15 +2356,21 @@ + @Override + public void handleContainerClose(ServerboundContainerClosePacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ ++ if (this.player.isImmobile()) return; // CraftBukkit ++ CraftEventFactory.handleInventoryCloseEvent(this.player); // CraftBukkit ++ + this.player.doCloseContainer(); + } + + @Override + public void handleContainerClick(ServerboundContainerClickPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.resetLastActionTime(); +- if (this.player.containerMenu.containerId == packet.getContainerId()) { +- if (this.player.isSpectator()) { ++ if (this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu.stillValid(this.player)) { // CraftBukkit ++ boolean cancelled = this.player.isSpectator(); // CraftBukkit - see below if ++ if (false/*this.player.isSpectator()*/) { // CraftBukkit + this.player.containerMenu.sendAllDataToRemote(); + } else if (!this.player.containerMenu.stillValid(this.player)) { + LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu); +@@ -1558,12 +2383,122 @@ + } else { + boolean flag = packet.getStateId() != this.player.containerMenu.getStateId(); + this.player.containerMenu.suppressRemoteUpdates(); +- this.player.containerMenu.clicked(slotNum, packet.getButtonNum(), packet.getClickType(), this.player); ++ // CraftBukkit start - Call InventoryClickEvent ++ if (packet.getSlotNum() < -1 && packet.getSlotNum() != -999) { ++ return; ++ } + + for (Entry entry : Int2ObjectMaps.fastIterable(packet.getChangedSlots())) { + this.player.containerMenu.setRemoteSlotNoCopy(entry.getIntKey(), entry.getValue()); + } + ++ if (packet.getClickType() != InventoryClickType.QUICK_CRAFT) { ++ if (click == ClickType.NUMBER_KEY) { ++ event = new InventoryClickEvent(inventory, type, packet.getSlotNum(), click, action, packet.getButtonNum()); ++ } else { ++ event = new InventoryClickEvent(inventory, type, packet.getSlotNum(), click, action); ++ } ++ ++ org.bukkit.inventory.Inventory top = inventory.getTopInventory(); ++ if (packet.getSlotNum() == 0 && top instanceof CraftingInventory) { ++ org.bukkit.inventory.Recipe recipe = ((CraftingInventory) top).getRecipe(); ++ if (recipe != null) { ++ if (click == ClickType.NUMBER_KEY) { ++ event = new CraftItemEvent(recipe, inventory, type, packet.getSlotNum(), click, action, packet.getButtonNum()); ++ } else { ++ event = new CraftItemEvent(recipe, inventory, type, packet.getSlotNum(), click, action); ++ } ++ } ++ } ++ ++ if (packet.getSlotNum() == 3 && top instanceof SmithingInventory) { ++ org.bukkit.inventory.ItemStack result = ((SmithingInventory) top).getResult(); ++ if (result != null) { ++ if (click == ClickType.NUMBER_KEY) { ++ event = new SmithItemEvent(inventory, type, packet.getSlotNum(), click, action, packet.getButtonNum()); ++ } else { ++ event = new SmithItemEvent(inventory, type, packet.getSlotNum(), click, action); ++ } ++ } ++ } ++ ++ event.setCancelled(cancelled); ++ AbstractContainerMenu oldContainer = this.player.containerMenu; // SPIGOT-1224 ++ cserver.getPluginManager().callEvent(event); ++ if (this.player.containerMenu != oldContainer) { ++ return; ++ } ++ ++ switch (event.getResult()) { ++ case ALLOW: ++ case DEFAULT: ++ this.player.containerMenu.clicked(i, packet.getButtonNum(), packet.getClickType(), this.player); ++ break; ++ case DENY: ++ /* Needs enum constructor in InventoryAction ++ if (action.modifiesOtherSlots()) { ++ ++ } else { ++ if (action.modifiesCursor()) { ++ this.player.playerConnection.sendPacket(new Packet103SetSlot(-1, -1, this.player.inventory.getCarried())); ++ } ++ if (action.modifiesClicked()) { ++ this.player.playerConnection.sendPacket(new Packet103SetSlot(this.player.activeContainer.windowId, packet102windowclick.slot, this.player.activeContainer.getSlot(packet102windowclick.slot).getItem())); ++ } ++ }*/ ++ switch (action) { ++ // Modified other slots ++ case PICKUP_ALL: ++ case MOVE_TO_OTHER_INVENTORY: ++ case HOTBAR_MOVE_AND_READD: ++ case HOTBAR_SWAP: ++ case COLLECT_TO_CURSOR: ++ case UNKNOWN: ++ this.player.containerMenu.sendAllDataToRemote(); ++ break; ++ // Modified cursor and clicked ++ case PICKUP_SOME: ++ case PICKUP_HALF: ++ case PICKUP_ONE: ++ case PLACE_ALL: ++ case PLACE_SOME: ++ case PLACE_ONE: ++ case SWAP_WITH_CURSOR: ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(-1, -1, this.player.inventoryMenu.incrementStateId(), this.player.containerMenu.getCarried())); ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(this.player.containerMenu.containerId, this.player.inventoryMenu.incrementStateId(), packet.getSlotNum(), this.player.containerMenu.getSlot(packet.getSlotNum()).getItem())); ++ break; ++ // Modified clicked only ++ case DROP_ALL_SLOT: ++ case DROP_ONE_SLOT: ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(this.player.containerMenu.containerId, this.player.inventoryMenu.incrementStateId(), packet.getSlotNum(), this.player.containerMenu.getSlot(packet.getSlotNum()).getItem())); ++ break; ++ // Modified cursor only ++ case DROP_ALL_CURSOR: ++ case DROP_ONE_CURSOR: ++ case CLONE_STACK: ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(-1, -1, this.player.inventoryMenu.incrementStateId(), this.player.containerMenu.getCarried())); ++ break; ++ // Nothing ++ case NOTHING: ++ break; ++ } ++ } ++ ++ if (event instanceof CraftItemEvent || event instanceof SmithItemEvent) { ++ // Need to update the inventory on crafting to ++ // correctly support custom recipes ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ } ++ // CraftBukkit end ++ ObjectIterator objectiterator = Int2ObjectMaps.fastIterable(packet.getChangedSlots()).iterator(); ++ ++ while (objectiterator.hasNext()) { ++ Entry entry = (Entry) objectiterator.next(); ++ ++ this.player.containerMenu.setRemoteSlotNoCopy(entry.getIntKey(), (ItemStack) entry.getValue()); ++ } ++ + this.player.containerMenu.setRemoteCarried(packet.getCarriedItem()); + this.player.containerMenu.resumeRemoteUpdates(); + if (flag) { +@@ -1586,13 +2690,18 @@ + if (!this.player.containerMenu.stillValid(this.player)) { + LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu); + } else { +- this.server +- .getRecipeManager() +- .byKey(packet.getRecipe()) +- .ifPresent( +- recipeHolder -> ((RecipeBookMenu)this.player.containerMenu) +- .handlePlacement(packet.isShiftDown(), (RecipeHolder)recipeHolder, this.player) +- ); ++ // CraftBukkit start - implement PlayerRecipeBookClickEvent ++ org.bukkit.inventory.Recipe recipe = this.cserver.getRecipe(CraftNamespacedKey.fromMinecraft(packet.getRecipe())); ++ if (recipe == null) { ++ return; ++ } ++ org.bukkit.event.player.PlayerRecipeBookClickEvent event = CraftEventFactory.callRecipeBookClickEvent(this.player, recipe, packet.isShiftDown()); ++ ++ // Cast to keyed should be safe as the recipe will never be a MerchantRecipe. ++ this.server.getRecipeManager().byKey(CraftNamespacedKey.toMinecraft(((org.bukkit.Keyed) event.getRecipe()).getKey())).ifPresent((recipeholder) -> { ++ ((RecipeBookMenu) this.player.containerMenu).handlePlacement(event.isShiftClick(), recipeholder, this.player); ++ }); ++ // CraftBukkit end + } + } + } +@@ -1600,6 +2709,7 @@ + @Override + public void handleContainerButtonClick(ServerboundContainerButtonClickPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.resetLastActionTime(); + if (this.player.containerMenu.containerId == packet.getContainerId() && !this.player.isSpectator()) { + if (!this.player.containerMenu.stillValid(this.player)) { +@@ -1635,7 +2751,45 @@ + } + + boolean flag1 = packet.getSlotNum() >= 1 && packet.getSlotNum() <= 45; +- boolean flag2 = item.isEmpty() || item.getDamageValue() >= 0 && item.getCount() <= 64 && !item.isEmpty(); ++ boolean flag2 = itemstack.isEmpty() || itemstack.getDamageValue() >= 0 && itemstack.getCount() <= 64 && !itemstack.isEmpty(); ++ if (flag || (flag1 && !ItemStack.matches(this.player.inventoryMenu.getSlot(packet.getSlotNum()).getItem(), packet.getItem()))) { // Insist on valid slot ++ // CraftBukkit start - Call click event ++ InventoryView inventory = this.player.inventoryMenu.getBukkitView(); ++ org.bukkit.inventory.ItemStack item = CraftItemStack.asBukkitCopy(packet.getItem()); ++ ++ SlotType type = SlotType.QUICKBAR; ++ if (flag) { ++ type = SlotType.OUTSIDE; ++ } else if (packet.getSlotNum() < 36) { ++ if (packet.getSlotNum() >= 5 && packet.getSlotNum() < 9) { ++ type = SlotType.ARMOR; ++ } else { ++ type = SlotType.CONTAINER; ++ } ++ } ++ InventoryCreativeEvent event = new InventoryCreativeEvent(inventory, type, flag ? -999 : packet.getSlotNum(), item); ++ cserver.getPluginManager().callEvent(event); ++ ++ itemstack = CraftItemStack.asNMSCopy(event.getCursor()); ++ ++ switch (event.getResult()) { ++ case ALLOW: ++ // Plugin cleared the id / stacksize checks ++ flag2 = true; ++ break; ++ case DEFAULT: ++ break; ++ case DENY: ++ // Reset the slot ++ if (packet.getSlotNum() >= 0) { ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(this.player.inventoryMenu.containerId, this.player.inventoryMenu.incrementStateId(), packet.getSlotNum(), this.player.inventoryMenu.getSlot(packet.getSlotNum()).getItem())); ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(-1, this.player.inventoryMenu.incrementStateId(), -1, ItemStack.EMPTY)); ++ } ++ return; ++ } ++ } ++ // CraftBukkit end ++ + if (flag1 && flag2) { + this.player.inventoryMenu.getSlot(packet.getSlotNum()).setByPlayer(item); + this.player.inventoryMenu.broadcastChanges(); +@@ -1653,6 +2811,7 @@ + } + + private void updateSignText(ServerboundSignUpdatePacket packet, List filteredText) { ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.resetLastActionTime(); + ServerLevel serverLevel = this.player.serverLevel(); + BlockPos pos = packet.getPos(); +@@ -1668,7 +2833,17 @@ + @Override + public void handlePlayerAbilities(ServerboundPlayerAbilitiesPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); +- this.player.getAbilities().flying = packet.isFlying() && this.player.getAbilities().mayfly; ++ // CraftBukkit start ++ if (this.player.getAbilities().mayfly && this.player.getAbilities().flying != packet.isFlying()) { ++ PlayerToggleFlightEvent event = new PlayerToggleFlightEvent(this.player.getBukkitEntity(), packet.isFlying()); ++ this.cserver.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ this.player.getAbilities().flying = packet.isFlying(); // Actually set the player's flying status ++ } else { ++ this.player.onUpdateAbilities(); // Tell the player their ability was reverted ++ } ++ } ++ // CraftBukkit end + } + + @Override +@@ -1724,8 +2902,7 @@ + if (!this.waitingForSwitchToConfig) { + throw new IllegalStateException("Client acknowledged config, but none was requested"); + } else { +- this.connection +- .setListener(new ServerConfigurationPacketListenerImpl(this.server, this.connection, this.createCookie(this.player.clientInformation()))); ++ this.connection.setListener(new ServerConfigurationPacketListenerImpl(this.server, this.connection, this.createCookie(this.player.clientInformation()), this.player)); // CraftBukkit + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java.patch new file mode 100644 index 0000000000..b4887ad7c6 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java.patch @@ -0,0 +1,65 @@ +--- a/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +@@ -10,7 +11,17 @@ + import net.minecraft.network.protocol.status.ServerStatus; + import net.minecraft.server.MinecraftServer; + ++// CraftBukkit start ++import java.net.InetAddress; ++import java.util.HashMap; ++// CraftBukkit end ++ + public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketListener { ++ ++ // CraftBukkit start - add fields ++ private static final HashMap throttleTracker = new HashMap(); ++ private static int throttleCounter = 0; ++ // CraftBukkit end + private static final Component IGNORE_STATUS_REASON = Component.translatable("disconnect.ignoring_status_request"); + private final MinecraftServer server; + private final Connection connection; +@@ -22,9 +33,44 @@ + + @Override + public void handleIntention(ClientIntentionPacket packet) { ++ this.connection.hostname = packet.hostName() + ":" + packet.port(); // CraftBukkit - set hostname + switch (packet.intention()) { + case LOGIN: + this.connection.setClientboundProtocolAfterHandshake(ClientIntent.LOGIN); ++ // CraftBukkit start - Connection throttle ++ try { ++ long currentTime = System.currentTimeMillis(); ++ long connectionThrottle = this.server.server.getConnectionThrottle(); ++ InetAddress address = ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getAddress(); ++ ++ synchronized (throttleTracker) { ++ if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { ++ throttleTracker.put(address, currentTime); ++ MutableComponent chatmessage = Component.literal("Connection throttled! Please wait before reconnecting."); ++ this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); ++ this.connection.disconnect(chatmessage); ++ return; ++ } ++ ++ throttleTracker.put(address, currentTime); ++ throttleCounter++; ++ if (throttleCounter > 200) { ++ throttleCounter = 0; ++ ++ // Cleanup stale entries ++ java.util.Iterator iter = throttleTracker.entrySet().iterator(); ++ while (iter.hasNext()) { ++ java.util.Map.Entry entry = (java.util.Map.Entry) iter.next(); ++ if (entry.getValue() > connectionThrottle) { ++ iter.remove(); ++ } ++ } ++ } ++ } ++ } catch (Throwable t) { ++ org.apache.logging.log4j.LogManager.getLogger().debug("Failed to check connection throttle", t); ++ } ++ // CraftBukkit end + if (packet.protocolVersion() != SharedConstants.getCurrentVersion().getProtocolVersion()) { + Component component; + if (packet.protocolVersion() < 754) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerLoginPacketListenerImpl.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerLoginPacketListenerImpl.java.patch new file mode 100644 index 0000000000..4f1171a127 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerLoginPacketListenerImpl.java.patch @@ -0,0 +1,161 @@ +--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -39,6 +40,10 @@ + import net.minecraft.world.entity.player.Player; + import org.apache.commons.lang3.Validate; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.bukkit.event.player.AsyncPlayerPreLoginEvent; ++import org.bukkit.event.player.PlayerPreLoginEvent; ++// CraftBukkit end + + public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, TickablePacketListener { + private static final AtomicInteger UNIQUE_THREAD_ID = new AtomicInteger(0); +@@ -54,7 +60,8 @@ + String requestedUsername; + @Nullable + private GameProfile authenticatedProfile; +- private final String serverId = ""; ++ private final String serverId; ++ private ServerPlayer player; // CraftBukkit + + public ServerLoginPacketListenerImpl(MinecraftServer server, Connection connection) { + this.server = server; +@@ -78,6 +87,13 @@ + } + } + ++ // CraftBukkit start ++ @Deprecated ++ public void disconnect(String s) { ++ disconnect(Component.literal(s)); ++ } ++ // CraftBukkit end ++ + @Override + public boolean isAcceptingMessages() { + return this.connection.isConnected(); +@@ -130,11 +150,14 @@ + this.state = ServerLoginPacketListenerImpl.State.VERIFYING; + } + +- private void verifyLoginAndFinishConnectionSetup(GameProfile gameProfile) { +- PlayerList playerList = this.server.getPlayerList(); +- Component component = playerList.canPlayerLogin(this.connection.getRemoteAddress(), gameProfile); +- if (component != null) { +- this.disconnect(component); ++ private void verifyLoginAndFinishConnectionSetup(GameProfile gameprofile) { ++ PlayerList playerlist = this.server.getPlayerList(); ++ // CraftBukkit start - fire PlayerLoginEvent ++ this.player = playerlist.canPlayerLogin(this, gameprofile); // CraftBukkit ++ ++ if (this.player == null) { ++ // this.disconnect(ichatbasecomponent); ++ // CraftBukkit end + } else { + if (this.server.getCompressionThreshold() >= 0 && !this.connection.isMemoryConnection()) { + this.connection +@@ -144,7 +165,8 @@ + ); + } + +- boolean flag = playerList.disconnectAllPlayersWithProfile(gameProfile); ++ boolean flag = playerlist.disconnectAllPlayersWithProfile(gameprofile, this.player); // CraftBukkit - add player reference ++ + if (flag) { + this.state = ServerLoginPacketListenerImpl.State.WAITING_FOR_DUPE_DISCONNECT; + } else { +@@ -185,13 +210,50 @@ + String string1 = Objects.requireNonNull(ServerLoginPacketListenerImpl.this.requestedUsername, "Player name not initialized"); + + try { +- ProfileResult profileResult = ServerLoginPacketListenerImpl.this.server +- .getSessionService() +- .hasJoinedServer(string1, string, this.getAddress()); +- if (profileResult != null) { +- GameProfile gameProfile = profileResult.profile(); +- ServerLoginPacketListenerImpl.LOGGER.info("UUID of player {} is {}", gameProfile.getName(), gameProfile.getId()); +- ServerLoginPacketListenerImpl.this.startClientVerification(gameProfile); ++ ProfileResult profileresult = ServerLoginPacketListenerImpl.this.server.getSessionService().hasJoinedServer(s1, s, this.getAddress()); ++ ++ if (profileresult != null) { ++ GameProfile gameprofile = profileresult.profile(); ++ ++ // CraftBukkit start - fire PlayerPreLoginEvent ++ if (!connection.isConnected()) { ++ return; ++ } ++ ++ String playerName = gameprofile.getName(); ++ java.net.InetAddress address = ((java.net.InetSocketAddress) connection.getRemoteAddress()).getAddress(); ++ java.util.UUID uniqueId = gameprofile.getId(); ++ final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server; ++ ++ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId); ++ server.getPluginManager().callEvent(asyncEvent); ++ ++ if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { ++ final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); ++ if (asyncEvent.getResult() != PlayerPreLoginEvent.Result.ALLOWED) { ++ event.disallow(asyncEvent.getResult(), asyncEvent.getKickMessage()); ++ } ++ Waitable waitable = new Waitable() { ++ @Override ++ protected PlayerPreLoginEvent.Result evaluate() { ++ server.getPluginManager().callEvent(event); ++ return event.getResult(); ++ }}; ++ ++ ServerLoginPacketListenerImpl.this.server.processQueue.add(waitable); ++ if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) { ++ disconnect(event.getKickMessage()); ++ return; ++ } ++ } else { ++ if (asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { ++ disconnect(asyncEvent.getKickMessage()); ++ return; ++ } ++ } ++ // CraftBukkit end ++ ServerLoginPacketListenerImpl.LOGGER.info("UUID of player {} is {}", gameprofile.getName(), gameprofile.getId()); ++ ServerLoginPacketListenerImpl.this.startClientVerification(gameprofile); + } else if (ServerLoginPacketListenerImpl.this.server.isSingleplayer()) { + ServerLoginPacketListenerImpl.LOGGER.warn("Failed to verify username but will let them in anyway!"); + ServerLoginPacketListenerImpl.this.startClientVerification(UUIDUtil.createOfflineProfile(string1)); +@@ -207,6 +269,11 @@ + ServerLoginPacketListenerImpl.this.disconnect(Component.translatable("multiplayer.disconnect.authservers_down")); + ServerLoginPacketListenerImpl.LOGGER.error("Couldn't verify username because servers are unavailable"); + } ++ // CraftBukkit start - catch all exceptions ++ } catch (Exception exception) { ++ disconnect("Failed to verify username!"); ++ server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + s1, exception); ++ // CraftBukkit end + } + } + +@@ -228,15 +296,14 @@ + } + + @Override +- public void handleLoginAcknowledgement(ServerboundLoginAcknowledgedPacket serverboundLoginAcknowledgedPacket) { +- Validate.validState(this.state == ServerLoginPacketListenerImpl.State.PROTOCOL_SWITCHING, "Unexpected login acknowledgement packet"); +- CommonListenerCookie commonListenerCookie = CommonListenerCookie.createInitial(Objects.requireNonNull(this.authenticatedProfile)); +- ServerConfigurationPacketListenerImpl serverConfigurationPacketListenerImpl = new ServerConfigurationPacketListenerImpl( +- this.server, this.connection, commonListenerCookie +- ); +- this.connection.setListener(serverConfigurationPacketListenerImpl); +- serverConfigurationPacketListenerImpl.startConfiguration(); +- this.state = ServerLoginPacketListenerImpl.State.ACCEPTED; ++ public void handleLoginAcknowledgement(ServerboundLoginAcknowledgedPacket serverboundloginacknowledgedpacket) { ++ Validate.validState(this.state == ServerLoginPacketListenerImpl.EnumProtocolState.PROTOCOL_SWITCHING, "Unexpected login acknowledgement packet", new Object[0]); ++ CommonListenerCookie commonlistenercookie = CommonListenerCookie.createInitial((GameProfile) Objects.requireNonNull(this.authenticatedProfile)); ++ ServerConfigurationPacketListenerImpl serverconfigurationpacketlistenerimpl = new ServerConfigurationPacketListenerImpl(this.server, this.connection, commonlistenercookie, this.player); // CraftBukkit ++ ++ this.connection.setListener(serverconfigurationpacketlistenerimpl); ++ serverconfigurationpacketlistenerimpl.startConfiguration(); ++ this.state = ServerLoginPacketListenerImpl.EnumProtocolState.ACCEPTED; + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerStatusPacketListenerImpl.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerStatusPacketListenerImpl.java.patch new file mode 100644 index 0000000000..706bb740d5 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/network/ServerStatusPacketListenerImpl.java.patch @@ -0,0 +1,131 @@ +--- a/net/minecraft/server/network/ServerStatusPacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerStatusPacketListenerImpl.java +@@ -1,5 +1,12 @@ + package net.minecraft.server.network; + ++// CraftBukkit start ++import com.mojang.authlib.GameProfile; ++import java.net.InetSocketAddress; ++import java.util.Collections; ++import java.util.Iterator; ++import java.util.Optional; ++import net.minecraft.SharedConstants; + import net.minecraft.network.Connection; + import net.minecraft.network.chat.Component; + import net.minecraft.network.protocol.status.ClientboundPongResponsePacket; +@@ -8,6 +15,12 @@ + import net.minecraft.network.protocol.status.ServerStatusPacketListener; + import net.minecraft.network.protocol.status.ServerboundPingRequestPacket; + import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerPlayer; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.craftbukkit.util.CraftIconCache; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class ServerStatusPacketListenerImpl implements ServerStatusPacketListener { + private static final Component DISCONNECT_REASON = Component.translatable("multiplayer.status.request_handled"); +@@ -35,7 +48,101 @@ + this.connection.disconnect(DISCONNECT_REASON); + } else { + this.hasRequestedStatus = true; +- this.connection.send(new ClientboundStatusResponsePacket(this.status)); ++ // CraftBukkit start ++ // this.connection.send(new PacketStatusOutServerInfo(this.status)); ++ MinecraftServer server = MinecraftServer.getServer(); ++ final Object[] players = server.getPlayerList().players.toArray(); ++ class ServerListPingEvent extends org.bukkit.event.server.ServerListPingEvent { ++ ++ CraftIconCache icon = server.server.getServerIcon(); ++ ++ ServerListPingEvent() { ++ super(connection.hostname, ((InetSocketAddress) connection.getRemoteAddress()).getAddress(), server.getMotd(), server.getPlayerList().getMaxPlayers()); ++ } ++ ++ @Override ++ public void setServerIcon(org.bukkit.util.CachedServerIcon icon) { ++ if (!(icon instanceof CraftIconCache)) { ++ throw new IllegalArgumentException(icon + " was not created by " + org.bukkit.craftbukkit.CraftServer.class); ++ } ++ this.icon = (CraftIconCache) icon; ++ } ++ ++ @Override ++ public Iterator iterator() throws UnsupportedOperationException { ++ return new Iterator() { ++ int i; ++ int ret = Integer.MIN_VALUE; ++ ServerPlayer player; ++ ++ @Override ++ public boolean hasNext() { ++ if (player != null) { ++ return true; ++ } ++ final Object[] currentPlayers = players; ++ for (int length = currentPlayers.length, i = this.i; i < length; i++) { ++ final ServerPlayer player = (ServerPlayer) currentPlayers[i]; ++ if (player != null) { ++ this.i = i + 1; ++ this.player = player; ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ @Override ++ public Player next() { ++ if (!hasNext()) { ++ throw new java.util.NoSuchElementException(); ++ } ++ final ServerPlayer player = this.player; ++ this.player = null; ++ this.ret = this.i - 1; ++ return player.getBukkitEntity(); ++ } ++ ++ @Override ++ public void remove() { ++ final Object[] currentPlayers = players; ++ final int i = this.ret; ++ if (i < 0 || currentPlayers[i] == null) { ++ throw new IllegalStateException(); ++ } ++ currentPlayers[i] = null; ++ } ++ }; ++ } ++ } ++ ++ ServerListPingEvent event = new ServerListPingEvent(); ++ server.server.getPluginManager().callEvent(event); ++ ++ java.util.List profiles = new java.util.ArrayList(players.length); ++ for (Object player : players) { ++ if (player != null) { ++ ServerPlayer entityPlayer = ((ServerPlayer) player); ++ if (entityPlayer.allowsListing()) { ++ profiles.add(entityPlayer.getGameProfile()); ++ } else { ++ profiles.add(MinecraftServer.ANONYMOUS_PLAYER_PROFILE); ++ } ++ } ++ } ++ ++ ServerStatus.ServerPingPlayerSample playerSample = new ServerStatus.ServerPingPlayerSample(event.getMaxPlayers(), profiles.size(), (server.hidesOnlinePlayers()) ? Collections.emptyList() : profiles); ++ ++ ServerStatus ping = new ServerStatus( ++ CraftChatMessage.fromString(event.getMotd(), true)[0], ++ Optional.of(playerSample), ++ Optional.of(new ServerStatus.Version(server.getServerModName() + " " + server.getServerVersion(), SharedConstants.getCurrentVersion().getProtocolVersion())), ++ (event.icon.value != null) ? Optional.of(new ServerStatus.a(event.icon.value)) : Optional.empty(), ++ server.enforceSecureProfile() ++ ); ++ ++ this.connection.send(new ClientboundStatusResponsePacket(ping)); ++ // CraftBukkit end + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/BanListEntry.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/BanListEntry.java.patch new file mode 100644 index 0000000000..ef1bd2e41f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/BanListEntry.java.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/server/players/BanListEntry.java ++++ b/net/minecraft/server/players/BanListEntry.java +@@ -26,7 +27,7 @@ + } + + protected BanListEntry(@Nullable T user, JsonObject entryData) { +- super(user); ++ super(checkExpiry(user, entryData)); // CraftBukkit + + Date date; + try { +@@ -80,4 +83,22 @@ + data.addProperty("expires", this.expires == null ? "forever" : DATE_FORMAT.format(this.expires)); + data.addProperty("reason", this.reason); + } ++ ++ // CraftBukkit start ++ private static T checkExpiry(T object, JsonObject jsonobject) { ++ Date expires = null; ++ ++ try { ++ expires = jsonobject.has("expires") ? DATE_FORMAT.parse(jsonobject.get("expires").getAsString()) : null; ++ } catch (ParseException ex) { ++ // Guess we don't have a date ++ } ++ ++ if (expires == null || expires.after(new Date())) { ++ return object; ++ } else { ++ return null; ++ } ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/GameProfileCache.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/GameProfileCache.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/GameProfileCache.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/OldUsersConverter.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/OldUsersConverter.java.patch new file mode 100644 index 0000000000..e69f8d4e5e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/OldUsersConverter.java.patch @@ -0,0 +1,96 @@ +--- a/net/minecraft/server/players/OldUsersConverter.java ++++ b/net/minecraft/server/players/OldUsersConverter.java +@@ -63,9 +86,9 @@ + if (OLD_USERBANLIST.exists() && OLD_USERBANLIST.isFile()) { + if (userBanList.getFile().exists()) { + try { +- userBanList.load(); +- } catch (IOException var6) { +- LOGGER.warn("Could not load existing file {}", userBanList.getFile().getName(), var6); ++ gameprofilebanlist.load(); ++ } catch (IOException ioexception) { ++ OldUsersConverter.LOGGER.warn("Could not load existing file {}", gameprofilebanlist.getFile().getName()); // CraftBukkit - don't print stacktrace + } + } + +@@ -118,9 +144,9 @@ + if (OLD_IPBANLIST.exists() && OLD_IPBANLIST.isFile()) { + if (ipBanList.getFile().exists()) { + try { +- ipBanList.load(); +- } catch (IOException var11) { +- LOGGER.warn("Could not load existing file {}", ipBanList.getFile().getName(), var11); ++ ipbanlist.load(); ++ } catch (IOException ioexception) { ++ OldUsersConverter.LOGGER.warn("Could not load existing file {}", ipbanlist.getFile().getName()); // CraftBukkit - don't print stacktrace + } + } + +@@ -154,9 +185,9 @@ + if (OLD_OPLIST.exists() && OLD_OPLIST.isFile()) { + if (serverOpList.getFile().exists()) { + try { +- serverOpList.load(); +- } catch (IOException var6) { +- LOGGER.warn("Could not load existing file {}", serverOpList.getFile().getName(), var6); ++ oplist.load(); ++ } catch (IOException ioexception) { ++ OldUsersConverter.LOGGER.warn("Could not load existing file {}", oplist.getFile().getName()); // CraftBukkit - don't print stacktrace + } + } + +@@ -198,9 +229,9 @@ + if (OLD_WHITELIST.exists() && OLD_WHITELIST.isFile()) { + if (userWhiteList.getFile().exists()) { + try { +- userWhiteList.load(); +- } catch (IOException var6) { +- LOGGER.warn("Could not load existing file {}", userWhiteList.getFile().getName(), var6); ++ whitelist.load(); ++ } catch (IOException ioexception) { ++ OldUsersConverter.LOGGER.warn("Could not load existing file {}", whitelist.getFile().getName()); // CraftBukkit - don't print stacktrace + } + } + +@@ -310,11 +346,36 @@ + } + } + +- private void movePlayerFile(File file3, String oldFileName, String newFileName) { +- File file4 = new File(worldPlayersDirectory, oldFileName + ".dat"); +- File file5 = new File(file3, newFileName + ".dat"); +- OldUsersConverter.ensureDirectoryExists(file3); +- if (!file4.renameTo(file5)) { ++ private void movePlayerFile(File file, String oldFileName, String newFileName) { ++ File file5 = new File(file, oldFileName + ".dat"); ++ File file6 = new File(file, newFileName + ".dat"); ++ ++ // CraftBukkit start - Use old file name to seed lastKnownName ++ CompoundTag root = null; ++ ++ try { ++ root = NbtIo.readCompressed(new java.io.FileInputStream(file5), NbtAccounter.unlimitedHeap()); ++ } catch (Exception exception) { ++ exception.printStackTrace(); ++ } ++ ++ if (root != null) { ++ if (!root.contains("bukkit")) { ++ root.put("bukkit", new CompoundTag()); ++ } ++ CompoundTag data = root.getCompound("bukkit"); ++ data.putString("lastKnownName", oldFileName); ++ ++ try { ++ NbtIo.writeCompressed(root, new java.io.FileOutputStream(file2)); ++ } catch (Exception exception) { ++ exception.printStackTrace(); ++ } ++ } ++ // CraftBukkit end ++ ++ OldUsersConverter.ensureDirectoryExists(file); ++ if (!file5.renameTo(file6)) { + throw new OldUsersConverter.ConversionError("Could not convert file for " + oldFileName); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/PlayerList.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/PlayerList.java.patch new file mode 100644 index 0000000000..8555b90bc5 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/PlayerList.java.patch @@ -0,0 +1,968 @@ +--- a/net/minecraft/server/players/PlayerList.java ++++ b/net/minecraft/server/players/PlayerList.java +@@ -98,6 +101,25 @@ + import net.minecraft.world.scores.Team; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.stream.Collectors; ++import net.minecraft.server.dedicated.DedicatedServer; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerChangedWorldEvent; ++import org.bukkit.event.player.PlayerJoinEvent; ++import org.bukkit.event.player.PlayerLoginEvent; ++import org.bukkit.event.player.PlayerQuitEvent; ++import org.bukkit.event.player.PlayerRespawnEvent; ++import org.bukkit.event.player.PlayerRespawnEvent.RespawnReason; ++import org.bukkit.event.player.PlayerSpawnChangeEvent; ++// CraftBukkit end ++ + public abstract class PlayerList { + public static final File USERBANLIST_FILE = new File("banned-players.json"); + public static final File IPBANLIST_FILE = new File("banned-ips.json"); +@@ -109,15 +132,17 @@ + private static final int SEND_PLAYER_INFO_INTERVAL = 600; + private static final SimpleDateFormat BAN_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z"); + private final MinecraftServer server; +- private final List players = Lists.newArrayList(); ++ public final List players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety + private final Map playersByUUID = Maps.newHashMap(); +- private final UserBanList bans = new UserBanList(USERBANLIST_FILE); +- private final IpBanList ipBans = new IpBanList(IPBANLIST_FILE); +- private final ServerOpList ops = new ServerOpList(OPLIST_FILE); +- private final UserWhiteList whitelist = new UserWhiteList(WHITELIST_FILE); +- private final Map stats = Maps.newHashMap(); +- private final Map advancements = Maps.newHashMap(); +- private final PlayerDataStorage playerIo; ++ private final UserBanList bans; ++ private final IpBanList ipBans; ++ private final ServerOpList ops; ++ private final UserWhiteList whitelist; ++ // CraftBukkit start ++ // private final Map stats; ++ // private final Map advancements; ++ // CraftBukkit end ++ public final PlayerDataStorage playerIo; + private boolean doWhiteList; + private final LayeredRegistryAccess registries; + protected final int maxPlayers; +@@ -127,7 +152,23 @@ + private static final boolean ALLOW_LOGOUTIVATOR = false; + private int sendAllPlayerInfoIn; + ++ // CraftBukkit start ++ private CraftServer cserver; ++ + public PlayerList(MinecraftServer server, LayeredRegistryAccess registries, PlayerDataStorage playerIo, int maxPlayers) { ++ this.cserver = server.server = new CraftServer((DedicatedServer) server, this); ++ server.console = org.bukkit.craftbukkit.command.ColouredConsoleSender.getInstance(); ++ server.reader.addCompleter(new org.bukkit.craftbukkit.command.ConsoleCommandCompleter(server.server)); ++ // CraftBukkit end ++ ++ this.bans = new UserBanList(PlayerList.USERBANLIST_FILE); ++ this.ipBans = new IpBanList(PlayerList.IPBANLIST_FILE); ++ this.ops = new ServerOpList(PlayerList.OPLIST_FILE); ++ this.whitelist = new UserWhiteList(PlayerList.WHITELIST_FILE); ++ // CraftBukkit start ++ // this.stats = Maps.newHashMap(); ++ // this.advancements = Maps.newHashMap(); ++ // CraftBukkit end + this.server = server; + this.registries = registries; + this.maxPlayers = maxPlayers; +@@ -146,61 +189,60 @@ + string = gameProfile.getName(); + } + +- CompoundTag compoundTag = this.load(serverPlayer); +- ResourceKey resourceKey = compoundTag != null +- ? DimensionType.parseLegacy(new Dynamic<>(NbtOps.INSTANCE, compoundTag.get("Dimension"))).resultOrPartial(LOGGER::error).orElse(Level.OVERWORLD) +- : Level.OVERWORLD; +- ServerLevel level = this.server.getLevel(resourceKey); +- ServerLevel serverLevel; +- if (level == null) { +- LOGGER.warn("Unknown respawn dimension {}, defaulting to overworld", resourceKey); +- serverLevel = this.server.overworld(); ++ CompoundTag nbttagcompound = this.load(entityplayer); ++ ResourceKey resourcekey; ++ // CraftBukkit start - Better rename detection ++ if (nbttagcompound != null && nbttagcompound.contains("bukkit")) { ++ CompoundTag bukkit = nbttagcompound.getCompound("bukkit"); ++ s = bukkit.contains("lastKnownName", 8) ? bukkit.getString("lastKnownName") : s; ++ } ++ // CraftBukkit end ++ ++ if (nbttagcompound != null) { ++ DataResult> dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, nbttagcompound.get("Dimension"))); // CraftBukkit - decompile error ++ Logger logger = PlayerList.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ resourcekey = (ResourceKey) dataresult.resultOrPartial(logger::error).orElse(entityplayer.serverLevel().dimension()); // CraftBukkit - SPIGOT-7507: If no dimension, fall back to existing dimension loaded from "WorldUUID", which in turn defaults to World.OVERWORLD + } else { +- serverLevel = level; ++ resourcekey = entityplayer.serverLevel().dimension(); // CraftBukkit - SPIGOT-7507: If no dimension, fall back to existing dimension loaded from "WorldUUID", which in turn defaults to World.OVERWORLD + } + +- serverPlayer.setServerLevel(serverLevel); +- String loggableAddress = connection.getLoggableAddress(this.server.logIPs()); +- LOGGER.info( +- "{}[{}] logged in with entity id {} at ({}, {}, {})", +- serverPlayer.getName().getString(), +- loggableAddress, +- serverPlayer.getId(), +- serverPlayer.getX(), +- serverPlayer.getY(), +- serverPlayer.getZ() +- ); +- LevelData levelData = serverLevel.getLevelData(); +- serverPlayer.loadGameTypes(compoundTag); +- ServerGamePacketListenerImpl serverGamePacketListenerImpl = new ServerGamePacketListenerImpl( +- this.server, connection, serverPlayer, commonListenerCookie +- ); +- GameRules gameRules = serverLevel.getGameRules(); +- boolean _boolean = gameRules.getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN); +- boolean _boolean1 = gameRules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO); +- boolean _boolean2 = gameRules.getBoolean(GameRules.RULE_LIMITED_CRAFTING); +- serverGamePacketListenerImpl.send( +- new ClientboundLoginPacket( +- serverPlayer.getId(), +- levelData.isHardcore(), +- this.server.levelKeys(), +- this.getMaxPlayers(), +- this.viewDistance, +- this.simulationDistance, +- _boolean1, +- !_boolean, +- _boolean2, +- serverPlayer.createCommonSpawnInfo(serverLevel) +- ) +- ); +- serverGamePacketListenerImpl.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked())); +- serverGamePacketListenerImpl.send(new ClientboundPlayerAbilitiesPacket(serverPlayer.getAbilities())); +- serverGamePacketListenerImpl.send(new ClientboundSetCarriedItemPacket(serverPlayer.getInventory().selected)); +- serverGamePacketListenerImpl.send(new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes())); +- this.sendPlayerPermissionLevel(serverPlayer); +- serverPlayer.getStats().markAllDirty(); +- serverPlayer.getRecipeBook().sendInitialRecipeBook(serverPlayer); +- this.updateEntireScoreboard(serverLevel.getScoreboard(), serverPlayer); ++ ResourceKey resourcekey1 = resourcekey; ++ ServerLevel worldserver = this.server.getLevel(resourcekey1); ++ ServerLevel worldserver1; ++ ++ if (worldserver == null) { ++ PlayerList.LOGGER.warn("Unknown respawn dimension {}, defaulting to overworld", resourcekey1); ++ worldserver1 = this.server.overworld(); ++ } else { ++ worldserver1 = worldserver; ++ } ++ ++ entityplayer.setServerLevel(worldserver1); ++ String s1 = networkmanager.getLoggableAddress(this.server.logIPs()); ++ ++ // CraftBukkit - Moved message to after join ++ // PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ({}, {}, {})", new Object[]{entityplayer.getName().getString(), s1, entityplayer.getId(), entityplayer.getX(), entityplayer.getY(), entityplayer.getZ()}); ++ LevelData worlddata = worldserver1.getLevelData(); ++ ++ entityplayer.loadGameTypes(nbttagcompound); ++ ServerGamePacketListenerImpl playerconnection = new ServerGamePacketListenerImpl(this.server, networkmanager, entityplayer, commonlistenercookie); ++ GameRules gamerules = worldserver1.getGameRules(); ++ boolean flag = gamerules.getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN); ++ boolean flag1 = gamerules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO); ++ boolean flag2 = gamerules.getBoolean(GameRules.RULE_LIMITED_CRAFTING); ++ ++ playerconnection.send(new ClientboundLoginPacket(entityplayer.getId(), worlddata.isHardcore(), this.server.levelKeys(), this.getMaxPlayers(), this.viewDistance, this.simulationDistance, flag1, !flag, flag2, entityplayer.createCommonSpawnInfo(worldserver1))); ++ entityplayer.getBukkitEntity().sendSupportedChannels(); // CraftBukkit ++ playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); ++ playerconnection.send(new ClientboundPlayerAbilitiesPacket(entityplayer.getAbilities())); ++ playerconnection.send(new ClientboundSetCarriedItemPacket(entityplayer.getInventory().selected)); ++ playerconnection.send(new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes())); ++ this.sendPlayerPermissionLevel(entityplayer); ++ entityplayer.getStats().markAllDirty(); ++ entityplayer.getRecipeBook().sendInitialRecipeBook(entityplayer); ++ this.updateEntireScoreboard(worldserver1.getScoreboard(), entityplayer); + this.server.invalidateStatus(); + MutableComponent mutableComponent; + if (serverPlayer.getGameProfile().getName().equalsIgnoreCase(string)) { +@@ -208,6 +251,9 @@ + } else { + mutableComponent = Component.translatable("multiplayer.player.joined.renamed", serverPlayer.getDisplayName(), string); + } ++ // CraftBukkit start ++ ichatmutablecomponent.withStyle(ChatFormatting.YELLOW); ++ String joinMessage = CraftChatMessage.fromComponent(ichatmutablecomponent); + + this.broadcastSystemMessage(mutableComponent.withStyle(ChatFormatting.YELLOW), false); + serverGamePacketListenerImpl.teleport(serverPlayer.getX(), serverPlayer.getY(), serverPlayer.getZ(), serverPlayer.getYRot(), serverPlayer.getXRot()); +@@ -216,23 +262,81 @@ + serverPlayer.sendServerStatus(status); + } + +- serverPlayer.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); +- this.players.add(serverPlayer); +- this.playersByUUID.put(serverPlayer.getUUID(), serverPlayer); +- this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(serverPlayer))); +- this.sendLevelInfo(serverPlayer, serverLevel); +- serverLevel.addNewPlayer(serverPlayer); +- this.server.getCustomBossEvents().onPlayerConnect(serverPlayer); ++ // entityplayer.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below ++ this.players.add(entityplayer); ++ this.playersByUUID.put(entityplayer.getUUID(), entityplayer); ++ // this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer))); // CraftBukkit - replaced with loop below + +- for (MobEffectInstance mobEffectInstance : serverPlayer.getActiveEffects()) { +- serverGamePacketListenerImpl.send(new ClientboundUpdateMobEffectPacket(serverPlayer.getId(), mobEffectInstance)); ++ // CraftBukkit start ++ CraftPlayer bukkitPlayer = entityplayer.getBukkitEntity(); ++ ++ // Ensure that player inventory is populated with its viewer ++ entityplayer.containerMenu.transferTo(entityplayer.containerMenu, bukkitPlayer); ++ ++ PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(bukkitPlayer, joinMessage); ++ cserver.getPluginManager().callEvent(playerJoinEvent); ++ ++ if (!entityplayer.connection.isAcceptingMessages()) { ++ return; + } + +- if (compoundTag != null && compoundTag.contains("RootVehicle", 10)) { +- CompoundTag compound = compoundTag.getCompound("RootVehicle"); +- Entity entity = EntityType.loadEntityRecursive( +- compound.getCompound("Entity"), serverLevel, entity2 -> !serverLevel.addWithUUID(entity2) ? null : entity2 +- ); ++ joinMessage = playerJoinEvent.getJoinMessage(); ++ ++ if (joinMessage != null && joinMessage.length() > 0) { ++ for (Component line : org.bukkit.craftbukkit.util.CraftChatMessage.fromString(joinMessage)) { ++ server.getPlayerList().broadcastSystemMessage(line, false); ++ } ++ } ++ // CraftBukkit end ++ ++ // CraftBukkit start - sendAll above replaced with this loop ++ ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer)); ++ ++ for (int i = 0; i < this.players.size(); ++i) { ++ ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i); ++ ++ if (entityplayer1.getBukkitEntity().canSee(bukkitPlayer)) { ++ entityplayer1.connection.send(packet); ++ } ++ ++ if (!bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { ++ continue; ++ } ++ ++ entityplayer.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer1))); ++ } ++ entityplayer.sentListPacket = true; ++ // CraftBukkit end ++ ++ entityplayer.getEntityData().refresh(entityplayer); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn ++ ++ this.sendLevelInfo(entityplayer, worldserver1); ++ ++ // CraftBukkit start - Only add if the player wasn't moved in the event ++ if (entityplayer.level() == worldserver1 && !worldserver1.players().contains(entityplayer)) { ++ worldserver1.addNewPlayer(entityplayer); ++ this.server.getCustomBossEvents().onPlayerConnect(entityplayer); ++ } ++ ++ worldserver1 = entityplayer.serverLevel(); // CraftBukkit - Update in case join event changed it ++ // CraftBukkit end ++ Iterator iterator = entityplayer.getActiveEffects().iterator(); ++ ++ while (iterator.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); ++ ++ playerconnection.send(new ClientboundUpdateMobEffectPacket(entityplayer.getId(), mobeffect)); ++ } ++ ++ if (nbttagcompound != null && nbttagcompound.contains("RootVehicle", 10)) { ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("RootVehicle"); ++ // CraftBukkit start ++ ServerLevel finalWorldServer = worldserver1; ++ Entity entity = EntityType.loadEntityRecursive(nbttagcompound1.getCompound("Entity"), finalWorldServer, (entity1) -> { ++ return !finalWorldServer.addWithUUID(entity1) ? null : entity1; ++ // CraftBukkit end ++ }); ++ + if (entity != null) { + UUID uUID; + if (compound.hasUUID("Attach")) { +@@ -263,7 +376,9 @@ + } + } + +- serverPlayer.initInventoryMenu(); ++ entityplayer.initInventoryMenu(); ++ // CraftBukkit - Moved from above, added world ++ PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", entityplayer.getName().getString(), s1, entityplayer.getId(), worldserver1.serverLevelData.getLevelName(), entityplayer.getX(), entityplayer.getY(), entityplayer.getZ()); + } + + protected void updateEntireScoreboard(ServerScoreboard scoreboard, ServerPlayer player) { +@@ -286,30 +415,31 @@ + } + + public void addWorldborderListener(ServerLevel level) { ++ if (playerIo != null) return; // CraftBukkit + level.getWorldBorder().addListener(new BorderChangeListener() { + @Override + public void onBorderSizeSet(WorldBorder border, double size) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderSizePacket(border)); ++ PlayerList.this.broadcastAll(new ClientboundSetBorderSizePacket(border), border.world); // CraftBukkit + } + + @Override +- public void onBorderSizeLerping(WorldBorder border, double oldSize, double newSize, long time) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderLerpSizePacket(border)); ++ public void onBorderSizeLerping(WorldBorder border, double oldSize, double d1, long newSize) { ++ PlayerList.this.broadcastAll(new ClientboundSetBorderLerpSizePacket(border), border.world); // CraftBukkit + } + + @Override +- public void onBorderCenterSet(WorldBorder border, double x, double z) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderCenterPacket(border)); ++ public void onBorderCenterSet(WorldBorder border, double x, double d1) { ++ PlayerList.this.broadcastAll(new ClientboundSetBorderCenterPacket(border), border.world); // CraftBukkit + } + + @Override + public void onBorderSetWarningTime(WorldBorder border, int warningTime) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDelayPacket(border)); ++ PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDelayPacket(border), border.world); // CraftBukkit + } + + @Override + public void onBorderSetWarningBlocks(WorldBorder border, int warningBlocks) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDistancePacket(border)); ++ PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDistancePacket(border), border.world); // CraftBukkit + } + + @Override +@@ -338,68 +467,126 @@ + } + + protected void save(ServerPlayer player) { ++ if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit + this.playerIo.save(player); +- ServerStatsCounter serverStatsCounter = this.stats.get(player.getUUID()); +- if (serverStatsCounter != null) { +- serverStatsCounter.save(); ++ ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit ++ ++ if (serverstatisticmanager != null) { ++ serverstatisticmanager.save(); + } + +- PlayerAdvancements playerAdvancements = this.advancements.get(player.getUUID()); +- if (playerAdvancements != null) { +- playerAdvancements.save(); ++ PlayerAdvancements advancementdataplayer = (PlayerAdvancements) player.getAdvancements(); // CraftBukkit ++ ++ if (advancementdataplayer != null) { ++ advancementdataplayer.save(); + } + } + +- public void remove(ServerPlayer player) { +- ServerLevel serverLevel = player.serverLevel(); +- player.awardStat(Stats.LEAVE_GAME); +- this.save(player); +- if (player.isPassenger()) { +- Entity rootVehicle = player.getRootVehicle(); +- if (rootVehicle.hasExactlyOnePlayerPassenger()) { +- LOGGER.debug("Removing player mount"); +- player.stopRiding(); +- rootVehicle.getPassengersAndSelf().forEach(entity -> entity.setRemoved(Entity.RemovalReason.UNLOADED_WITH_PLAYER)); ++ public String remove(ServerPlayer entityplayer) { // CraftBukkit - return string ++ ServerLevel worldserver = entityplayer.serverLevel(); ++ ++ entityplayer.awardStat(Stats.LEAVE_GAME); ++ ++ // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it ++ // See SPIGOT-5799, SPIGOT-6145 ++ if (entityplayer.containerMenu != entityplayer.inventoryMenu) { ++ entityplayer.closeContainer(); ++ } ++ ++ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(entityplayer.getBukkitEntity(), entityplayer.kickLeaveMessage != null ? entityplayer.kickLeaveMessage : "\u00A7e" + entityplayer.getScoreboardName() + " left the game"); ++ cserver.getPluginManager().callEvent(playerQuitEvent); ++ entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); ++ ++ entityplayer.doTick(); // SPIGOT-924 ++ // CraftBukkit end ++ ++ this.save(entityplayer); ++ if (entityplayer.isPassenger()) { ++ Entity entity = entityplayer.getRootVehicle(); ++ ++ if (entity.hasExactlyOnePlayerPassenger()) { ++ PlayerList.LOGGER.debug("Removing player mount"); ++ entityplayer.stopRiding(); ++ entity.getPassengersAndSelf().forEach((entity1) -> { ++ entity1.setRemoved(Entity.RemovalReason.UNLOADED_WITH_PLAYER); ++ }); + } + } + +- player.unRide(); +- serverLevel.removePlayerImmediately(player, Entity.RemovalReason.UNLOADED_WITH_PLAYER); +- player.getAdvancements().stopListening(); +- this.players.remove(player); +- this.server.getCustomBossEvents().onPlayerDisconnect(player); +- UUID uUID = player.getUUID(); +- ServerPlayer serverPlayer = this.playersByUUID.get(uUID); +- if (serverPlayer == player) { +- this.playersByUUID.remove(uUID); +- this.stats.remove(uUID); +- this.advancements.remove(uUID); ++ entityplayer.unRide(); ++ worldserver.removePlayerImmediately(entityplayer, Entity.RemovalReason.UNLOADED_WITH_PLAYER); ++ entityplayer.getAdvancements().stopListening(); ++ this.players.remove(entityplayer); ++ this.server.getCustomBossEvents().onPlayerDisconnect(entityplayer); ++ UUID uuid = entityplayer.getUUID(); ++ ServerPlayer entityplayer1 = (ServerPlayer) this.playersByUUID.get(uuid); ++ ++ if (entityplayer1 == entityplayer) { ++ this.playersByUUID.remove(uuid); ++ // CraftBukkit start ++ // this.stats.remove(uuid); ++ // this.advancements.remove(uuid); ++ // CraftBukkit end + } + +- this.broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(player.getUUID()))); ++ // CraftBukkit start ++ // this.broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID()))); ++ ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID())); ++ for (int i = 0; i < players.size(); i++) { ++ ServerPlayer entityplayer2 = (ServerPlayer) this.players.get(i); ++ ++ if (entityplayer2.getBukkitEntity().canSee(entityplayer.getBukkitEntity())) { ++ entityplayer2.connection.send(packet); ++ } else { ++ entityplayer2.getBukkitEntity().onEntityRemove(entityplayer); ++ } ++ } ++ // This removes the scoreboard (and player reference) for the specific player in the manager ++ cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); ++ // CraftBukkit end ++ ++ return playerQuitEvent.getQuitMessage(); // CraftBukkit + } + +- @Nullable +- public Component canPlayerLogin(SocketAddress socketAddress, GameProfile gameProfile) { +- if (this.bans.isBanned(gameProfile)) { +- UserBanListEntry userBanListEntry = this.bans.get(gameProfile); +- MutableComponent mutableComponent = Component.translatable("multiplayer.disconnect.banned.reason", userBanListEntry.getReason()); +- if (userBanListEntry.getExpires() != null) { +- mutableComponent.append( +- Component.translatable("multiplayer.disconnect.banned.expiration", BAN_DATE_FORMAT.format(userBanListEntry.getExpires())) +- ); ++ // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer ++ public ServerPlayer canPlayerLogin(ServerLoginPacketListenerImpl loginlistener, GameProfile gameprofile) { ++ MutableComponent ichatmutablecomponent; ++ ++ // Moved from processLogin ++ UUID uuid = gameprofile.getId(); ++ List list = Lists.newArrayList(); ++ ++ ServerPlayer entityplayer; ++ ++ for (int i = 0; i < this.players.size(); ++i) { ++ entityplayer = (ServerPlayer) this.players.get(i); ++ if (entityplayer.getUUID().equals(uuid)) { ++ list.add(entityplayer); + } + +- return mutableComponent; +- } else if (!this.isWhiteListed(gameProfile)) { +- return Component.translatable("multiplayer.disconnect.not_whitelisted"); +- } else if (this.ipBans.isBanned(socketAddress)) { +- IpBanListEntry ipBanListEntry = this.ipBans.get(socketAddress); +- MutableComponent mutableComponent = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipBanListEntry.getReason()); +- if (ipBanListEntry.getExpires() != null) { +- mutableComponent.append( +- Component.translatable("multiplayer.disconnect.banned_ip.expiration", BAN_DATE_FORMAT.format(ipBanListEntry.getExpires())) +- ); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ entityplayer = (ServerPlayer) iterator.next(); ++ save(entityplayer); // CraftBukkit - Force the player's inventory to be saved ++ entityplayer.connection.disconnect(Component.translatable("multiplayer.disconnect.duplicate_login")); ++ } ++ ++ // Instead of kicking then returning, we need to store the kick reason ++ // in the event, check with plugins to see if it's ok, and THEN kick ++ // depending on the outcome. ++ SocketAddress socketaddress = loginlistener.connection.getRemoteAddress(); ++ ++ ServerPlayer entity = new ServerPlayer(this.server, this.server.getLevel(Level.OVERWORLD), gameprofile, ClientInformation.createDefault()); ++ Player player = entity.getBukkitEntity(); ++ PlayerLoginEvent event = new PlayerLoginEvent(player, loginlistener.connection.hostname, ((java.net.InetSocketAddress) socketaddress).getAddress()); ++ ++ if (getBans().isBanned(gameprofile) && !getBans().get(gameprofile).hasExpired()) { ++ UserBanListEntry gameprofilebanentry = (UserBanListEntry) this.bans.get(gameprofile); ++ ++ ichatmutablecomponent = Component.translatable("multiplayer.disconnect.banned.reason", gameprofilebanentry.getReason()); ++ if (gameprofilebanentry.getExpires() != null) { ++ ichatmutablecomponent.append((Component) Component.translatable("multiplayer.disconnect.banned.expiration", PlayerList.BAN_DATE_FORMAT.format(gameprofilebanentry.getExpires()))); + } + + return mutableComponent; +@@ -410,13 +621,18 @@ + } + } + +- public ServerPlayer getPlayerForLogin(GameProfile gameProfile, ClientInformation clientInformation) { +- return new ServerPlayer(this.server, this.server.overworld(), gameProfile, clientInformation); ++ // CraftBukkit start - added EntityPlayer ++ public ServerPlayer getPlayerForLogin(GameProfile gameprofile, ClientInformation clientinformation, ServerPlayer player) { ++ player.updateOptions(clientinformation); ++ return player; ++ // CraftBukkit end + } + +- public boolean disconnectAllPlayersWithProfile(GameProfile gameProfile) { +- UUID id = gameProfile.getId(); +- Set set = Sets.newIdentityHashSet(); ++ public boolean disconnectAllPlayersWithProfile(GameProfile gameprofile, ServerPlayer player) { // CraftBukkit - added EntityPlayer ++ /* CraftBukkit startMoved up ++ UUID uuid = gameprofile.getId(); ++ Set set = Sets.newIdentityHashSet(); ++ Iterator iterator = this.players.iterator(); + + for (ServerPlayer serverPlayer : this.players) { + if (serverPlayer.getUUID().equals(id)) { +@@ -434,44 +657,82 @@ + } + + return !set.isEmpty(); ++ */ ++ return player == null; ++ // CraftBukkit end + } + +- public ServerPlayer respawn(ServerPlayer player, boolean keepEverything) { +- this.players.remove(player); +- player.serverLevel().removePlayerImmediately(player, Entity.RemovalReason.DISCARDED); +- BlockPos respawnPosition = player.getRespawnPosition(); +- float respawnAngle = player.getRespawnAngle(); +- boolean isRespawnForced = player.isRespawnForced(); +- ServerLevel level = this.server.getLevel(player.getRespawnDimension()); +- Optional optional; +- if (level != null && respawnPosition != null) { +- optional = Player.findRespawnPositionAndUseSpawnBlock(level, respawnPosition, respawnAngle, isRespawnForced, keepEverything); ++ // CraftBukkit start ++ public ServerPlayer respawn(ServerPlayer entityplayer, boolean flag, RespawnReason reason) { ++ return this.respawn(entityplayer, this.server.getLevel(entityplayer.getRespawnDimension()), flag, null, true, reason); ++ } ++ ++ public ServerPlayer respawn(ServerPlayer entityplayer, ServerLevel worldserver, boolean flag, Location location, boolean avoidSuffocation, RespawnReason reason) { ++ entityplayer.stopRiding(); // CraftBukkit ++ this.players.remove(entityplayer); ++ entityplayer.serverLevel().removePlayerImmediately(entityplayer, Entity.RemovalReason.DISCARDED); ++ BlockPos blockposition = entityplayer.getRespawnPosition(); ++ float f = entityplayer.getRespawnAngle(); ++ boolean flag1 = entityplayer.isRespawnForced(); ++ /* CraftBukkit start ++ WorldServer worldserver = this.server.getLevel(entityplayer.getRespawnDimension()); ++ Optional optional; ++ ++ if (worldserver != null && blockposition != null) { ++ optional = EntityHuman.findRespawnPositionAndUseSpawnBlock(worldserver, blockposition, f, flag1, flag); + } else { + optional = Optional.empty(); + } + +- ServerLevel serverLevel = level != null && optional.isPresent() ? level : this.server.overworld(); +- ServerPlayer serverPlayer = new ServerPlayer(this.server, serverLevel, player.getGameProfile(), player.clientInformation()); +- serverPlayer.connection = player.connection; +- serverPlayer.restoreFrom(player, keepEverything); +- serverPlayer.setId(player.getId()); +- serverPlayer.setMainArm(player.getMainArm()); ++ WorldServer worldserver1 = worldserver != null && optional.isPresent() ? worldserver : this.server.overworld(); ++ EntityPlayer entityplayer1 = new EntityPlayer(this.server, worldserver1, entityplayer.getGameProfile(), entityplayer.clientInformation()); ++ // */ ++ ServerPlayer entityplayer1 = entityplayer; ++ org.bukkit.World fromWorld = entityplayer.getBukkitEntity().getWorld(); ++ entityplayer.wonGame = false; ++ // CraftBukkit end + + for (String string : player.getTags()) { + serverPlayer.addTag(string); + } + +- boolean flag = false; +- if (optional.isPresent()) { +- BlockState blockState = serverLevel.getBlockState(respawnPosition); +- boolean isRespawnAnchor = blockState.is(Blocks.RESPAWN_ANCHOR); +- Vec3 vec3 = optional.get(); +- float f; +- if (!blockState.is(BlockTags.BEDS) && !isRespawnAnchor) { +- f = respawnAngle; +- } else { +- Vec3 vec31 = Vec3.atBottomCenterOf(respawnPosition).subtract(vec3).normalize(); +- f = (float)Mth.wrapDegrees(Mth.atan2(vec31.z, vec31.x) * 180.0F / (float)Math.PI - 90.0); ++ boolean flag2 = false; ++ ++ // CraftBukkit start - fire PlayerRespawnEvent ++ if (location == null) { ++ boolean isBedSpawn = false; ++ ServerLevel worldserver1 = this.server.getLevel(entityplayer.getRespawnDimension()); ++ if (worldserver1 != null) { ++ Optional optional; ++ ++ if (blockposition != null) { ++ optional = net.minecraft.world.entity.player.Player.findRespawnPositionAndUseSpawnBlock(worldserver1, blockposition, f, flag1, flag); ++ } else { ++ optional = Optional.empty(); ++ } ++ ++ if (optional.isPresent()) { ++ IBlockData iblockdata = worldserver1.getBlockState(blockposition); ++ boolean flag3 = iblockdata.is(Blocks.RESPAWN_ANCHOR); ++ Vec3 vec3d = (Vec3) optional.get(); ++ float f1; ++ ++ if (!iblockdata.is(BlockTags.BEDS) && !flag3) { ++ f1 = f; ++ } else { ++ Vec3 vec3d1 = Vec3.atBottomCenterOf(blockposition).subtract(vec3d).normalize(); ++ ++ f1 = (float) Mth.wrapDegrees(Mth.atan2(vec3d1.z, vec3d1.x) * 57.2957763671875D - 90.0D); ++ } ++ ++ // entityplayer1.setRespawnPosition(worldserver1.dimension(), blockposition, f, flag1, false); // CraftBukkit - not required, just copies old location into reused entity ++ flag2 = !flag && flag3; ++ isBedSpawn = true; ++ location = CraftLocation.toBukkit(vec3d, worldserver1.getWorld(), f1, 0.0F); ++ } else if (blockposition != null) { ++ entityplayer1.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F)); ++ entityplayer1.setRespawnPosition(null, null, 0f, false, false, PlayerSpawnChangeEvent.Cause.RESET); // CraftBukkit - SPIGOT-5988: Clear respawn location when obstructed ++ } + } + + serverPlayer.moveTo(vec3.x, vec3.y, vec3.z, f, 0.0F); +@@ -481,43 +764,43 @@ + serverPlayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F)); + } + +- while (!serverLevel.noCollision(serverPlayer) && serverPlayer.getY() < (double)serverLevel.getMaxBuildHeight()) { +- serverPlayer.setPos(serverPlayer.getX(), serverPlayer.getY() + 1.0, serverPlayer.getZ()); ++ while (avoidSuffocation && !worldserver1.noCollision((Entity) entityplayer1) && entityplayer1.getY() < (double) worldserver1.getMaxBuildHeight()) { ++ // CraftBukkit end ++ entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); + } + +- byte b = (byte)(keepEverything ? 1 : 0); +- ServerLevel serverLevel1 = serverPlayer.serverLevel(); +- LevelData levelData = serverLevel1.getLevelData(); +- serverPlayer.connection.send(new ClientboundRespawnPacket(serverPlayer.createCommonSpawnInfo(serverLevel1), b)); +- serverPlayer.connection.teleport(serverPlayer.getX(), serverPlayer.getY(), serverPlayer.getZ(), serverPlayer.getYRot(), serverPlayer.getXRot()); +- serverPlayer.connection.send(new ClientboundSetDefaultSpawnPositionPacket(serverLevel.getSharedSpawnPos(), serverLevel.getSharedSpawnAngle())); +- serverPlayer.connection.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked())); +- serverPlayer.connection +- .send(new ClientboundSetExperiencePacket(serverPlayer.experienceProgress, serverPlayer.totalExperience, serverPlayer.experienceLevel)); +- this.sendLevelInfo(serverPlayer, serverLevel); +- this.sendPlayerPermissionLevel(serverPlayer); +- serverLevel.addRespawnedPlayer(serverPlayer); +- this.players.add(serverPlayer); +- this.playersByUUID.put(serverPlayer.getUUID(), serverPlayer); +- serverPlayer.initInventoryMenu(); +- serverPlayer.setHealth(serverPlayer.getHealth()); +- if (flag) { +- serverPlayer.connection +- .send( +- new ClientboundSoundPacket( +- SoundEvents.RESPAWN_ANCHOR_DEPLETE, +- SoundSource.BLOCKS, +- (double)respawnPosition.getX(), +- (double)respawnPosition.getY(), +- (double)respawnPosition.getZ(), +- 1.0F, +- 1.0F, +- serverLevel.getRandom().nextLong() +- ) +- ); ++ int i = flag ? 1 : 0; ++ ServerLevel worldserver2 = entityplayer1.serverLevel(); ++ LevelData worlddata = worldserver2.getLevelData(); ++ ++ entityplayer1.connection.send(new ClientboundRespawnPacket(entityplayer1.createCommonSpawnInfo(worldserver2), (byte) i)); ++ entityplayer1.connection.teleport(CraftLocation.toBukkit(entityplayer1.position(), worldserver2.getWorld(), entityplayer1.getYRot(), entityplayer1.getXRot())); // CraftBukkit ++ entityplayer1.connection.send(new ClientboundSetDefaultSpawnPositionPacket(worldserver1.getSharedSpawnPos(), worldserver1.getSharedSpawnAngle())); ++ entityplayer1.connection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); ++ entityplayer1.connection.send(new ClientboundSetExperiencePacket(entityplayer1.experienceProgress, entityplayer1.totalExperience, entityplayer1.experienceLevel)); ++ this.sendLevelInfo(entityplayer1, worldserver1); ++ this.sendPlayerPermissionLevel(entityplayer1); ++ if (!entityplayer.connection.isDisconnected()) { ++ worldserver1.addRespawnedPlayer(entityplayer1); ++ this.players.add(entityplayer1); ++ this.playersByUUID.put(entityplayer1.getUUID(), entityplayer1); + } + +- return serverPlayer; ++ // Fire advancement trigger ++ entityplayer.triggerDimensionChangeTriggers(((CraftWorld) fromWorld).getHandle()); ++ ++ // Don't fire on respawn ++ if (fromWorld != location.getWorld()) { ++ PlayerChangedWorldEvent event = new PlayerChangedWorldEvent(entityplayer.getBukkitEntity(), fromWorld); ++ server.server.getPluginManager().callEvent(event); ++ } ++ ++ // Save player file again if they were disconnected ++ if (entityplayer.connection.isDisconnected()) { ++ this.save(entityplayer); ++ } ++ // CraftBukkit end ++ return entityplayer1; + } + + public void sendPlayerPermissionLevel(ServerPlayer player) { +@@ -528,7 +823,18 @@ + + public void tick() { + if (++this.sendAllPlayerInfoIn > 600) { +- this.broadcastAll(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY), this.players)); ++ // CraftBukkit start ++ for (int i = 0; i < this.players.size(); ++i) { ++ final ServerPlayer target = (ServerPlayer) this.players.get(i); ++ ++ target.connection.send(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY), this.players.stream().filter(new Predicate() { ++ @Override ++ public boolean test(ServerPlayer input) { ++ return target.getBukkitEntity().canSee(input.getBukkitEntity()); ++ } ++ }).collect(Collectors.toList()))); ++ } ++ // CraftBukkit end + this.sendAllPlayerInfoIn = 0; + } + } +@@ -539,6 +851,25 @@ + } + } + ++ // CraftBukkit start - add a world/entity limited version ++ public void broadcastAll(Packet packet, net.minecraft.world.entity.player.Player entityhuman) { ++ for (int i = 0; i < this.players.size(); ++i) { ++ ServerPlayer entityplayer = this.players.get(i); ++ if (entityhuman != null && !entityplayer.getBukkitEntity().canSee(entityhuman.getBukkitEntity())) { ++ continue; ++ } ++ ((ServerPlayer) this.players.get(i)).connection.send(packet); ++ } ++ } ++ ++ public void broadcastAll(Packet packet, Level world) { ++ for (int i = 0; i < world.players().size(); ++i) { ++ ((ServerPlayer) world.players().get(i)).connection.send(packet); ++ } ++ ++ } ++ // CraftBukkit end ++ + public void broadcastAll(Packet packet, ResourceKey dimension) { + for (ServerPlayer serverPlayer : this.players) { + if (serverPlayer.level().dimension() == dimension) { +@@ -621,6 +972,7 @@ + player.connection.send(new ClientboundEntityEventPacket(player, b)); + } + ++ player.getBukkitEntity().recalculatePermissions(); // CraftBukkit + this.server.getCommands().sendCommands(player); + } + +@@ -648,15 +999,23 @@ + return null; + } + +- public void broadcast(@Nullable Player except, double x, double y, double z, double radius, ResourceKey dimension, Packet packet) { +- for (int i = 0; i < this.players.size(); i++) { +- ServerPlayer serverPlayer = this.players.get(i); +- if (serverPlayer != except && serverPlayer.level().dimension() == dimension) { +- double d = x - serverPlayer.getX(); +- double d1 = y - serverPlayer.getY(); +- double d2 = z - serverPlayer.getZ(); +- if (d * d + d1 * d1 + d2 * d2 < radius * radius) { +- serverPlayer.connection.send(packet); ++ public void broadcast(@Nullable net.minecraft.world.entity.player.Player except, double x, double d1, double y, double d3, ResourceKey z, Packet packet) { ++ for (int i = 0; i < this.players.size(); ++i) { ++ ServerPlayer entityplayer = (ServerPlayer) this.players.get(i); ++ ++ // CraftBukkit start - Test if player receiving packet can see the source of the packet ++ if (except != null && !entityplayer.getBukkitEntity().canSee(except.getBukkitEntity())) { ++ continue; ++ } ++ // CraftBukkit end ++ ++ if (entityplayer != except && entityplayer.level().dimension() == z) { ++ double d4 = x - entityplayer.getX(); ++ double d5 = d1 - entityplayer.getY(); ++ double d6 = y - entityplayer.getZ(); ++ ++ if (d4 * d4 + d5 * d5 + d6 * d6 < d3 * d3) { ++ entityplayer.connection.send(packet); + } + } + } +@@ -688,14 +1048,19 @@ + } + + public void sendLevelInfo(ServerPlayer player, ServerLevel level) { +- WorldBorder worldBorder = this.server.overworld().getWorldBorder(); +- player.connection.send(new ClientboundInitializeBorderPacket(worldBorder)); ++ WorldBorder worldborder = player.level().getWorldBorder(); // CraftBukkit ++ ++ player.connection.send(new ClientboundInitializeBorderPacket(worldborder)); + player.connection.send(new ClientboundSetTimePacket(level.getGameTime(), level.getDayTime(), level.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); + player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(level.getSharedSpawnPos(), level.getSharedSpawnAngle())); + if (level.isRaining()) { +- player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.START_RAINING, 0.0F)); +- player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, level.getRainLevel(1.0F))); +- player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, level.getThunderLevel(1.0F))); ++ // CraftBukkit start - handle player weather ++ // entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.START_RAINING, 0.0F)); ++ // entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.RAIN_LEVEL_CHANGE, worldserver.getRainLevel(1.0F))); ++ // entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, worldserver.getThunderLevel(1.0F))); ++ player.setPlayerWeather(org.bukkit.WeatherType.DOWNFALL, false); ++ player.updateWeather(-level.rainLevel, level.rainLevel, -level.thunderLevel, level.thunderLevel); ++ // CraftBukkit end + } + + player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LEVEL_CHUNKS_LOAD_START, 0.0F)); +@@ -704,8 +1069,16 @@ + + public void sendAllPlayerInfo(ServerPlayer player) { + player.inventoryMenu.sendAllDataToRemote(); +- player.resetSentInfo(); ++ // entityplayer.resetSentInfo(); ++ player.getBukkitEntity().updateScaledHealth(); // CraftBukkit - Update scaled health on respawn and worldchange ++ player.getEntityData().refresh(player); // CraftBukkkit - SPIGOT-7218: sync metadata + player.connection.send(new ClientboundSetCarriedItemPacket(player.getInventory().selected)); ++ // CraftBukkit start - from GameRules ++ int i = player.level().getGameRules().getBoolean(GameRules.RULE_REDUCEDDEBUGINFO) ? 22 : 23; ++ player.connection.send(new ClientboundEntityEventPacket(player, (byte) i)); ++ float immediateRespawn = player.level().getGameRules().getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN) ? 1.0F: 0.0F; ++ player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.IMMEDIATE_RESPAWN, immediateRespawn)); ++ // CraftBukkit end + } + + public int getPlayerCount() { +@@ -758,11 +1134,22 @@ + } + + public void removeAll() { +- for (int i = 0; i < this.players.size(); i++) { +- this.players.get(i).connection.disconnect(Component.translatable("multiplayer.disconnect.server_shutdown")); ++ // CraftBukkit start - disconnect safely ++ for (ServerPlayer player : this.players) { ++ player.connection.disconnect(this.server.server.getShutdownMessage()); // CraftBukkit - add custom shutdown message + } ++ // CraftBukkit end ++ + } + ++ // CraftBukkit start ++ public void broadcastMessage(Component[] iChatBaseComponents) { ++ for (Component component : iChatBaseComponents) { ++ broadcastSystemMessage(component, false); ++ } ++ } ++ // CraftBukkit end ++ + public void broadcastSystemMessage(Component message, boolean bypassHiddenChat) { + this.broadcastSystemMessage(message, serverPlayer -> message, bypassHiddenChat); + } +@@ -809,34 +1207,44 @@ + return message.hasSignature() && !message.hasExpiredServer(Instant.now()); + } + +- public ServerStatsCounter getPlayerStats(Player player) { +- UUID uUID = player.getUUID(); +- ServerStatsCounter serverStatsCounter = this.stats.get(uUID); +- if (serverStatsCounter == null) { ++ // CraftBukkit start ++ public ServerStatsCounter getPlayerStats(ServerPlayer entityhuman) { ++ ServerStatsCounter serverstatisticmanager = entityhuman.getStats(); ++ return serverstatisticmanager == null ? getPlayerStats(entityhuman.getUUID(), entityhuman.getDisplayName().getString()) : serverstatisticmanager; ++ } ++ ++ public ServerStatsCounter getPlayerStats(UUID uuid, String displayName) { ++ ServerPlayer entityhuman = this.getPlayer(uuid); ++ ServerStatsCounter serverstatisticmanager = entityhuman == null ? null : (ServerStatsCounter) entityhuman.getStats(); ++ // CraftBukkit end ++ ++ if (serverstatisticmanager == null) { + File file = this.server.getWorldPath(LevelResource.PLAYER_STATS_DIR).toFile(); + File file1 = new File(file, uUID + ".json"); + if (!file1.exists()) { +- File file2 = new File(file, player.getName().getString() + ".json"); ++ File file2 = new File(file, displayName + ".json"); // CraftBukkit + Path path = file2.toPath(); + if (FileUtil.isPathNormalized(path) && FileUtil.isPathPortable(path) && path.startsWith(file.getPath()) && file2.isFile()) { + file2.renameTo(file1); + } + } + +- serverStatsCounter = new ServerStatsCounter(this.server, file1); +- this.stats.put(uUID, serverStatsCounter); ++ serverstatisticmanager = new ServerStatsCounter(this.server, file1); ++ // this.stats.put(uuid, serverstatisticmanager); // CraftBukkit + } + + return serverStatsCounter; + } + + public PlayerAdvancements getPlayerAdvancements(ServerPlayer player) { +- UUID uUID = player.getUUID(); +- PlayerAdvancements playerAdvancements = this.advancements.get(uUID); +- if (playerAdvancements == null) { +- Path path = this.server.getWorldPath(LevelResource.PLAYER_ADVANCEMENTS_DIR).resolve(uUID + ".json"); +- playerAdvancements = new PlayerAdvancements(this.server.getFixerUpper(), this, this.server.getAdvancements(), path, player); +- this.advancements.put(uUID, playerAdvancements); ++ UUID uuid = player.getUUID(); ++ PlayerAdvancements advancementdataplayer = (PlayerAdvancements) player.getAdvancements(); // CraftBukkit ++ ++ if (advancementdataplayer == null) { ++ Path path = this.server.getWorldPath(LevelResource.PLAYER_ADVANCEMENTS_DIR).resolve(uuid + ".json"); ++ ++ advancementdataplayer = new PlayerAdvancements(this.server.getFixerUpper(), this, this.server.getAdvancements(), path, player); ++ // this.advancements.put(uuid, advancementdataplayer); // CraftBukkit + } + + playerAdvancements.setPlayer(player); +@@ -879,9 +1297,20 @@ + } + + public void reloadResources() { +- for (PlayerAdvancements playerAdvancements : this.advancements.values()) { +- playerAdvancements.reload(this.server.getAdvancements()); ++ // CraftBukkit start ++ /*Iterator iterator = this.advancements.values().iterator(); ++ ++ while (iterator.hasNext()) { ++ AdvancementDataPlayer advancementdataplayer = (AdvancementDataPlayer) iterator.next(); ++ ++ advancementdataplayer.reload(this.server.getAdvancements()); ++ }*/ ++ ++ for (ServerPlayer player : players) { ++ player.getAdvancements().reload(this.server.getAdvancements()); ++ player.getAdvancements().flushDirty(player); // CraftBukkit - trigger immediate flush of advancements + } ++ // CraftBukkit end + + this.broadcastAll(new ClientboundUpdateTagsPacket(TagNetworkSerialization.serializeTagsToNetwork(this.registries))); + ClientboundUpdateRecipesPacket clientboundUpdateRecipesPacket = new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes()); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/SleepStatus.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/SleepStatus.java.patch new file mode 100644 index 0000000000..ff7a4138c0 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/SleepStatus.java.patch @@ -0,0 +1,49 @@ +--- a/net/minecraft/server/players/SleepStatus.java ++++ b/net/minecraft/server/players/SleepStatus.java +@@ -14,8 +18,12 @@ + } + + public boolean areEnoughDeepSleeping(int requiredSleepPercentage, List sleepingPlayers) { +- int i = (int)sleepingPlayers.stream().filter(Player::isSleepingLongEnough).count(); +- return i >= this.sleepersNeeded(requiredSleepPercentage); ++ // CraftBukkit start ++ int j = (int) sleepingPlayers.stream().filter((eh) -> { return eh.isSleepingLongEnough() || eh.fauxSleeping; }).count(); ++ boolean anyDeepSleep = sleepingPlayers.stream().anyMatch(Player::isSleepingLongEnough); ++ ++ return anyDeepSleep && j >= this.sleepersNeeded(requiredSleepPercentage); ++ // CraftBukkit end + } + + public int sleepersNeeded(int requiredSleepPercentage) { +@@ -35,16 +44,25 @@ + int i1 = this.sleepingPlayers; + this.activePlayers = 0; + this.sleepingPlayers = 0; ++ Iterator iterator = players.iterator(); ++ boolean anySleep = false; // CraftBukkit + +- for (ServerPlayer serverPlayer : players) { +- if (!serverPlayer.isSpectator()) { +- this.activePlayers++; +- if (serverPlayer.isSleeping()) { +- this.sleepingPlayers++; ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ if (!entityplayer.isSpectator()) { ++ ++this.activePlayers; ++ if (entityplayer.isSleeping() || entityplayer.fauxSleeping) { // CraftBukkit ++ ++this.sleepingPlayers; + } ++ // CraftBukkit start ++ if (entityplayer.isSleeping()) { ++ anySleep = true; ++ } ++ // CraftBukkit end + } + } + +- return (i1 > 0 || this.sleepingPlayers > 0) && (i != this.activePlayers || i1 != this.sleepingPlayers); ++ return anySleep && (j > 0 || this.sleepingPlayers > 0) && (i != this.activePlayers || j != this.sleepingPlayers); // CraftBukkit + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/StoredUserList.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/StoredUserList.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/StoredUserList.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/UserBanListEntry.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/UserBanListEntry.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/players/UserBanListEntry.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/rcon/RconConsoleSource.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/rcon/RconConsoleSource.java.patch new file mode 100644 index 0000000000..90dbb187e4 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/rcon/RconConsoleSource.java.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/server/rcon/RconConsoleSource.java ++++ b/net/minecraft/server/rcon/RconConsoleSource.java +@@ -7,15 +8,23 @@ + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; +- ++// CraftBukkit start ++import java.net.SocketAddress; ++import org.bukkit.craftbukkit.command.CraftRemoteConsoleCommandSender; ++// CraftBukkit end + public class RconConsoleSource implements CommandSource { + private static final String RCON = "Rcon"; + private static final Component RCON_COMPONENT = Component.literal("Rcon"); + private final StringBuffer buffer = new StringBuffer(); + private final MinecraftServer server; ++ // CraftBukkit start ++ public final SocketAddress socketAddress; ++ private final CraftRemoteConsoleCommandSender remoteConsole = new CraftRemoteConsoleCommandSender(this); + +- public RconConsoleSource(MinecraftServer server) { +- this.server = server; ++ public RconConsoleSource(MinecraftServer minecraftserver, SocketAddress socketAddress) { ++ this.socketAddress = socketAddress; ++ // CraftBukkit end ++ this.server = minecraftserver; + } + + public void prepareForCommand() { +@@ -33,7 +42,18 @@ + ); + } + ++ // CraftBukkit start - Send a String ++ public void sendMessage(String message) { ++ this.buffer.append(message); ++ } ++ + @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return this.remoteConsole; ++ } ++ // CraftBukkit end ++ ++ @Override + public void sendSystemMessage(Component component) { + this.buffer.append(component.getString()); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/server/rcon/thread/RconClient.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/server/rcon/thread/RconClient.java.patch new file mode 100644 index 0000000000..61ad71d139 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/server/rcon/thread/RconClient.java.patch @@ -0,0 +1,83 @@ +--- a/net/minecraft/server/rcon/thread/RconClient.java ++++ b/net/minecraft/server/rcon/thread/RconClient.java +@@ -9,6 +10,8 @@ + import java.nio.charset.StandardCharsets; + import java.util.Locale; + import net.minecraft.server.ServerInterface; ++// CraftBukkit start ++import net.minecraft.server.dedicated.DedicatedServer; + import net.minecraft.server.rcon.PktUtils; + import org.slf4j.Logger; + +@@ -23,11 +27,14 @@ + private final Socket client; + private final byte[] buf = new byte[1460]; + private final String rconPassword; +- private final ServerInterface serverInterface; ++ // CraftBukkit start ++ private final DedicatedServer serverInterface; ++ private final RconConsoleSource rconConsoleSource; ++ // CraftBukkit end + + RconClient(ServerInterface serverInterface, String rconPassword, Socket client) { + super("RCON Client " + client.getInetAddress()); +- this.serverInterface = serverInterface; ++ this.serverInterface = (DedicatedServer) serverInterface; // CraftBukkit + this.client = client; + + try { +@@ -37,18 +44,17 @@ + } + + this.rconPassword = rconPassword; ++ this.rconConsoleSource = new net.minecraft.server.rcon.RconConsoleSource(this.serverInterface, client.getRemoteSocketAddress()); // CraftBukkit + } + + @Override + public void run() { + try { +- try { +- while (this.running) { +- BufferedInputStream bufferedInputStream = new BufferedInputStream(this.client.getInputStream()); +- int i = bufferedInputStream.read(this.buf, 0, 1460); +- if (10 > i) { +- return; +- } ++ while (true) { ++ // CraftBukkit end ++ if (!this.running) { ++ return; ++ } + + int i1 = 0; + int i2 = PktUtils.intFromByteArray(this.buf, 0, i); +@@ -67,9 +80,9 @@ + String string1 = PktUtils.stringFromByteArray(this.buf, var21, i); + + try { +- this.sendCmdResponse(i3, this.serverInterface.runCommand(string1)); +- } catch (Exception var15) { +- this.sendCmdResponse(i3, "Error executing: " + string1 + " (" + var15.getMessage() + ")"); ++ this.sendCmdResponse(l, this.serverInterface.runCommand(this.rconConsoleSource, s)); // CraftBukkit ++ } catch (Exception exception) { ++ this.sendCmdResponse(l, "Error executing: " + s + " (" + exception.getMessage() + ")"); + } + break; + } +@@ -98,11 +118,11 @@ + } catch (Exception var17) { + LOGGER.error("Exception whilst parsing RCON input", (Throwable)var17); + } +- } finally { +- this.closeSocket(); +- LOGGER.info("Thread {} shutting down", this.name); +- this.running = false; +- } ++ ++ // CraftBukkit start - decompile error: switch try / while statement ++ // return; ++ // } ++ // CraftBukkit end + } + + private void send(int id, int i, String message) throws IOException { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/stats/ServerRecipeBook.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/stats/ServerRecipeBook.java.patch new file mode 100644 index 0000000000..9be367b6e9 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/stats/ServerRecipeBook.java.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/stats/ServerRecipeBook.java ++++ b/net/minecraft/stats/ServerRecipeBook.java +@@ -19,6 +20,8 @@ + import net.minecraft.world.item.crafting.RecipeManager; + import org.slf4j.Logger; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public class ServerRecipeBook extends RecipeBook { + public static final String RECIPE_BOOK_TAG = "recipeBook"; + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -27,14 +34,16 @@ + List list = Lists.newArrayList(); + int i = 0; + +- for (RecipeHolder recipeHolder : recipes) { +- ResourceLocation resourceLocation = recipeHolder.id(); +- if (!this.known.contains(resourceLocation) && !recipeHolder.value().isSpecial()) { +- this.add(resourceLocation); +- this.addHighlight(resourceLocation); +- list.add(resourceLocation); +- CriteriaTriggers.RECIPE_UNLOCKED.trigger(player, recipeHolder); +- i++; ++ while (iterator.hasNext()) { ++ RecipeHolder recipeholder = (RecipeHolder) iterator.next(); ++ ResourceLocation minecraftkey = recipeholder.id(); ++ ++ if (!this.known.contains(minecraftkey) && !recipeholder.value().isSpecial() && CraftEventFactory.handlePlayerRecipeListUpdateEvent(player, minecraftkey)) { // CraftBukkit ++ this.add(minecraftkey); ++ this.addHighlight(minecraftkey); ++ list.add(minecraftkey); ++ CriteriaTriggers.RECIPE_UNLOCKED.trigger(player, recipeholder); ++ ++i; + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/stats/ServerStatsCounter.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/stats/ServerStatsCounter.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/stats/ServerStatsCounter.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/stats/StatsCounter.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/stats/StatsCounter.java.patch new file mode 100644 index 0000000000..b35df579f8 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/stats/StatsCounter.java.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/stats/StatsCounter.java ++++ b/net/minecraft/stats/StatsCounter.java +@@ -13,8 +14,15 @@ + } + + public void increment(Player player, Stat stat, int amount) { +- int i = (int)Math.min((long)this.getValue(stat) + (long)amount, 2147483647L); +- this.setValue(player, stat, i); ++ int j = (int) Math.min((long) this.getValue(stat) + (long) amount, 2147483647L); ++ ++ // CraftBukkit start - fire Statistic events ++ org.bukkit.event.Cancellable cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.handleStatisticsIncrease(player, stat, this.getValue(stat), j); ++ if (cancellable != null && cancellable.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ this.setValue(player, stat, j); + } + + public void setValue(Player player, Stat stat, int value) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/util/SpawnUtil.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/util/SpawnUtil.java.patch new file mode 100644 index 0000000000..1dd16178a2 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/util/SpawnUtil.java.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/util/SpawnUtil.java ++++ b/net/minecraft/util/SpawnUtil.java +@@ -20,16 +18,29 @@ + ) { + BlockPos.MutableBlockPos mutableBlockPos = pos.mutable(); + +- for (int i1 = 0; i1 < attempts; i1++) { +- int i2 = Mth.randomBetweenInclusive(level.random, -i, i); +- int i3 = Mth.randomBetweenInclusive(level.random, -i, i); +- mutableBlockPos.setWithOffset(pos, i2, yOffset, i3); +- if (level.getWorldBorder().isWithinBounds(mutableBlockPos) && moveToPossibleSpawnPosition(level, yOffset, mutableBlockPos, strategy)) { +- T mob = (T)entityType.create(level, null, null, mutableBlockPos, spawnType, false, false); +- if (mob != null) { +- if (mob.checkSpawnRules(level, spawnType) && mob.checkSpawnObstruction(level)) { +- level.addFreshEntityWithPassengers(mob); +- return Optional.of(mob); ++ public SpawnUtil() {} ++ ++ public static Optional trySpawnMob(EntityType entityType, EnumMobSpawn spawnType, ServerLevel level, BlockPos pos, int attempts, int j, int yOffset, SpawnUtil.Strategy strategy) { ++ // CraftBukkit start ++ return trySpawnMob(entityType, spawnType, level, pos, attempts, j, yOffset, strategy, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ public static Optional trySpawnMob(EntityType entitytypes, EnumMobSpawn enummobspawn, ServerLevel worldserver, BlockPos blockposition, int i, int j, int k, SpawnUtil.Strategy spawnutil_a, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ // CraftBukkit end ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = blockposition.mutable(); ++ ++ for (int l = 0; l < i; ++l) { ++ int i1 = Mth.randomBetweenInclusive(worldserver.random, -j, j); ++ int j1 = Mth.randomBetweenInclusive(worldserver.random, -j, j); ++ ++ blockposition_mutableblockposition.setWithOffset(blockposition, i1, k, j1); ++ if (worldserver.getWorldBorder().isWithinBounds((BlockPos) blockposition_mutableblockposition) && moveToPossibleSpawnPosition(worldserver, k, blockposition_mutableblockposition, spawnutil_a)) { ++ T t0 = entitytypes.create(worldserver, (CompoundTag) null, null, blockposition_mutableblockposition, enummobspawn, false, false); // CraftBukkit - decompile error ++ ++ if (t0 != null) { ++ if (t0.checkSpawnRules(worldserver, enummobspawn) && t0.checkSpawnObstruction(worldserver)) { ++ worldserver.addFreshEntityWithPassengers(t0, reason); // CraftBukkit ++ return Optional.of(t0); + } + + mob.discard(); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/util/datafix/DataFixers.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/util/datafix/DataFixers.java.patch new file mode 100644 index 0000000000..c9f3a2ae67 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/util/datafix/DataFixers.java.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/util/datafix/DataFixers.java ++++ b/net/minecraft/util/datafix/DataFixers.java +@@ -442,7 +277,20 @@ + builder.addFixer(new VillagerTradeFix(schema43, false)); + Schema schema44 = builder.addSchema(1456, SAME_NAMESPACED); + builder.addFixer(new EntityItemFrameDirectionFix(schema44, false)); +- Schema schema45 = builder.addSchema(1458, SAME_NAMESPACED); ++ Schema schema45 = builder.addSchema(1458, DataFixers.SAME_NAMESPACED); ++ ++ // CraftBukkit start ++ builder.addFixer(new com.mojang.datafixers.DataFix(schema45, false) { ++ @Override ++ protected com.mojang.datafixers.TypeRewriteRule makeRule() { ++ return this.fixTypeEverywhereTyped("Player CustomName", this.getInputSchema().getType(DataConverterTypes.PLAYER), (typed) -> { ++ return typed.update(DSL.remainderFinder(), (dynamic) -> { ++ return EntityCustomNameToComponentFix.fixTagCustomName(dynamic); ++ }); ++ }); ++ } ++ }); ++ // CraftBukkit end + builder.addFixer(new EntityCustomNameToComponentFix(schema45, false)); + builder.addFixer(new ItemCustomNameToComponentFix(schema45, false)); + builder.addFixer(new BlockEntityCustomNameToComponentFix(schema45, false)); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java.patch new file mode 100644 index 0000000000..f2a44f3590 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java ++++ b/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java +@@ -20,17 +20,20 @@ + + @Override + public TypeRewriteRule makeRule() { +- Type type = this.getInputSchema().getType(References.ITEM_STACK); +- OpticFinder> opticFinder = DSL.fieldFinder("id", DSL.named(References.ITEM_NAME.typeName(), NamespacedSchema.namespacedString())); +- OpticFinder opticFinder1 = type.findField("tag"); +- return this.fixTypeEverywhereTyped("ItemInstanceMapIdFix", type, typed -> { +- Optional> optional = typed.getOptional(opticFinder); +- if (optional.isPresent() && Objects.equals(optional.get().getSecond(), "minecraft:filled_map")) { +- Dynamic dynamic = typed.get(DSL.remainderFinder()); +- Typed typed1 = typed.getOrCreateTyped(opticFinder1); +- Dynamic dynamic1 = typed1.get(DSL.remainderFinder()); +- dynamic1 = dynamic1.set("map", dynamic1.createInt(dynamic.get("Damage").asInt(0))); +- return typed.set(opticFinder1, typed1.set(DSL.remainderFinder(), dynamic1)); ++ Type type = this.getInputSchema().getType(DataConverterTypes.ITEM_STACK); ++ OpticFinder> opticfinder = DSL.fieldFinder("id", DSL.named(DataConverterTypes.ITEM_NAME.typeName(), NamespacedSchema.namespacedString())); ++ OpticFinder opticfinder1 = type.findField("tag"); ++ ++ return this.fixTypeEverywhereTyped("ItemInstanceMapIdFix", type, (typed) -> { ++ Optional> optional = typed.getOptional(opticfinder); ++ ++ if (optional.isPresent() && Objects.equals(((Pair) optional.get()).getSecond(), "minecraft:filled_map")) { ++ Dynamic dynamic = (Dynamic) typed.get(DSL.remainderFinder()); ++ Typed typed1 = typed.getOrCreateTyped(opticfinder1); ++ Dynamic dynamic1 = (Dynamic) typed1.get(DSL.remainderFinder()); ++ ++ if (!dynamic1.getElement("map").result().isPresent()) dynamic1 = dynamic1.set("map", dynamic1.createInt(dynamic.get("Damage").asInt(0))); // CraftBukkit ++ return typed.set(opticfinder1, typed1.set(DSL.remainderFinder(), dynamic1)); + } else { + return typed; + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java.patch new file mode 100644 index 0000000000..cb554a827d --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java ++++ b/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java +@@ -421,11 +372,12 @@ + typed1 = typed.set(opticFinder, Pair.of(References.ITEM_NAME.typeName(), string)); + } + +- if (DAMAGE_IDS.contains(optional.get().getSecond())) { +- Typed typed2 = typed.getOrCreateTyped(opticFinder1); +- Dynamic dynamic1 = typed2.get(DSL.remainderFinder()); +- dynamic1 = dynamic1.set("Damage", dynamic1.createInt(_int)); +- typed1 = typed1.set(opticFinder1, typed2.set(DSL.remainderFinder(), dynamic1)); ++ if (ItemStackTheFlatteningFix.DAMAGE_IDS.contains(((Pair) optional.get()).getSecond())) { ++ Typed typed2 = typed.getOrCreateTyped(opticfinder1); ++ Dynamic dynamic1 = (Dynamic) typed2.get(DSL.remainderFinder()); ++ ++ if (i != 0) dynamic1 = dynamic1.set("Damage", dynamic1.createInt(i)); // CraftBukkit ++ typed1 = typed1.set(opticfinder1, typed2.set(DSL.remainderFinder(), dynamic1)); + } + + return typed1.set(DSL.remainderFinder(), dynamic.remove("Damage")); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/util/worldupdate/WorldUpgrader.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/util/worldupdate/WorldUpgrader.java.patch new file mode 100644 index 0000000000..1717a9783f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/util/worldupdate/WorldUpgrader.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/util/worldupdate/WorldUpgrader.java ++++ b/net/minecraft/util/worldupdate/WorldUpgrader.java +@@ -62,7 +66,7 @@ + + public WorldUpgrader(LevelStorageSource.LevelStorageAccess levelStoarge, DataFixer dataFixer, Registry dimensions, boolean eraseCache) { + this.dimensions = dimensions; +- this.levels = dimensions.registryKeySet().stream().map(Registries::levelStemToLevel).collect(Collectors.toUnmodifiableSet()); ++ this.levels = (Set) java.util.stream.Stream.of(levelStoarge.dimensionType).map(Registries::levelStemToLevel).collect(Collectors.toUnmodifiableSet()); // CraftBukkit + this.eraseCache = eraseCache; + this.dataFixer = dataFixer; + this.levelStorage = levelStoarge; +@@ -123,16 +140,18 @@ + boolean flag1 = false; + + try { +- CompoundTag compoundTag = chunkStorage.read(chunkPos).join().orElse(null); +- if (compoundTag != null) { +- int version = ChunkStorage.getVersion(compoundTag); +- ChunkGenerator chunkGenerator = this.dimensions.getOrThrow(Registries.levelToLevelStem(resourceKey2)).generator(); +- CompoundTag compoundTag1 = chunkStorage.upgradeChunkTag( +- resourceKey2, () -> this.overworldDataStorage, compoundTag, chunkGenerator.getTypeNameForDataFixer() +- ); +- ChunkPos chunkPos1 = new ChunkPos(compoundTag1.getInt("xPos"), compoundTag1.getInt("zPos")); +- if (!chunkPos1.equals(chunkPos)) { +- LOGGER.warn("Chunk {} has invalid position {}", chunkPos, chunkPos1); ++ CompoundTag nbttagcompound = (CompoundTag) ((Optional) ichunkloader.read(chunkcoordintpair).join()).orElse((Object) null); ++ ++ if (nbttagcompound != null) { ++ int j = ChunkStorage.getVersion(nbttagcompound); ++ ChunkGenerator chunkgenerator = ((LevelStem) this.dimensions.getOrThrow(Registries.levelToLevelStem(resourcekey2))).generator(); ++ CompoundTag nbttagcompound1 = ichunkloader.upgradeChunkTag(Registries.levelToLevelStem(resourcekey2), () -> { // CraftBukkit ++ return this.overworldDataStorage; ++ }, nbttagcompound, chunkgenerator.getTypeNameForDataFixer(), chunkcoordintpair, null); // CraftBukkit ++ ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); ++ ++ if (!chunkcoordintpair1.equals(chunkcoordintpair)) { ++ WorldUpgrader.LOGGER.warn("Chunk {} has invalid position {}", chunkcoordintpair, chunkcoordintpair1); + } + + boolean flag2 = version < SharedConstants.getCurrentVersion().getDataVersion().getVersion(); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/CompoundContainer.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/CompoundContainer.java.patch new file mode 100644 index 0000000000..e378d5fcef --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/CompoundContainer.java.patch @@ -0,0 +1,76 @@ +--- a/net/minecraft/world/CompoundContainer.java ++++ b/net/minecraft/world/CompoundContainer.java +@@ -3,10 +3,64 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import org.bukkit.Location; ++ ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class CompoundContainer implements Container { + private final Container container1; + private final Container container2; + ++ public final Container container1; ++ public final Container container2; ++ ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ ++ public List getContents() { ++ List result = new ArrayList(this.getContainerSize()); ++ for (int i = 0; i < this.getContainerSize(); i++) { ++ result.add(this.getItem(i)); ++ } ++ return result; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ this.container1.onOpen(who); ++ this.container2.onOpen(who); ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ this.container1.onClose(who); ++ this.container2.onClose(who); ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return null; // This method won't be called since CraftInventoryDoubleChest doesn't defer to here ++ } ++ ++ public void setMaxStackSize(int size) { ++ this.container1.setMaxStackSize(size); ++ this.container2.setMaxStackSize(size); ++ } ++ ++ @Override ++ public Location getLocation() { ++ return container1.getLocation(); // TODO: right? ++ } ++ // CraftBukkit end ++ + public CompoundContainer(Container container1, Container container2) { + this.container1 = container1; + this.container2 = container2; +@@ -58,7 +105,7 @@ + + @Override + public int getMaxStackSize() { +- return this.container1.getMaxStackSize(); ++ return Math.min(this.container1.getMaxStackSize(), this.container2.getMaxStackSize()); // CraftBukkit - check both sides + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/Container.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/Container.java.patch new file mode 100644 index 0000000000..032b8dcb9b --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/Container.java.patch @@ -0,0 +1,56 @@ +--- a/net/minecraft/world/Container.java ++++ b/net/minecraft/world/Container.java +@@ -6,8 +6,12 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; ++// CraftBukkit start ++import net.minecraft.world.item.crafting.RecipeHolder; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.BlockEntity; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++// CraftBukkit end + + public interface Container extends Clearable { + int LARGE_MAX_STACK_SIZE = 64; +@@ -25,9 +30,7 @@ + + void setItem(int slot, ItemStack stack); + +- default int getMaxStackSize() { +- return 64; +- } ++ int getMaxStackSize(); // CraftBukkit + + void setChanged(); + +@@ -87,4 +90,29 @@ + && player.distanceToSqr((double)blockPos.getX() + 0.5, (double)blockPos.getY() + 0.5, (double)blockPos.getZ() + 0.5) + <= (double)(maxDistance * maxDistance); + } ++ ++ // CraftBukkit start ++ java.util.List getContents(); ++ ++ void onOpen(CraftHumanEntity who); ++ ++ void onClose(CraftHumanEntity who); ++ ++ java.util.List getViewers(); ++ ++ org.bukkit.inventory.InventoryHolder getOwner(); ++ ++ void setMaxStackSize(int size); ++ ++ org.bukkit.Location getLocation(); ++ ++ default RecipeHolder getCurrentRecipe() { ++ return null; ++ } ++ ++ default void setCurrentRecipe(RecipeHolder recipe) { ++ } ++ ++ int MAX_STACK = 64; ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/LockCode.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/LockCode.java.patch new file mode 100644 index 0000000000..a5241b88c9 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/LockCode.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/LockCode.java ++++ b/net/minecraft/world/LockCode.java +@@ -4,6 +4,11 @@ + import net.minecraft.nbt.CompoundTag; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.ChatColor; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++// CraftBukkit end ++ + @Immutable + public class LockCode { + public static final LockCode NO_LOCK = new LockCode(""); +@@ -15,7 +21,19 @@ + } + + public boolean unlocksWith(ItemStack stack) { +- return this.key.isEmpty() || !stack.isEmpty() && stack.hasCustomHoverName() && this.key.equals(stack.getHoverName().getString()); ++ // CraftBukkit start - SPIGOT-6307: Check for color codes if the lock contains color codes ++ if (this.key.isEmpty()) return true; ++ if (!stack.isEmpty() && stack.hasCustomHoverName()) { ++ if (this.key.indexOf(ChatColor.COLOR_CHAR) == -1) { ++ // The lock key contains no color codes, so let's ignore colors in the item display name (vanilla Minecraft behavior): ++ return this.key.equals(stack.getHoverName().getString()); ++ } else { ++ // The lock key contains color codes, so let's take them into account: ++ return this.key.equals(CraftChatMessage.fromComponent(stack.getHoverName())); ++ } ++ } ++ return false; ++ // CraftBukkit end + } + + public void addToTag(CompoundTag nbt) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/SimpleContainer.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/SimpleContainer.java.patch new file mode 100644 index 0000000000..ad5df6ac40 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/SimpleContainer.java.patch @@ -0,0 +1,79 @@ +--- a/net/minecraft/world/SimpleContainer.java ++++ b/net/minecraft/world/SimpleContainer.java +@@ -13,17 +14,76 @@ + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class SimpleContainer implements Container, StackedContentsCompatible { + private final int size; + private final NonNullList items; + @Nullable + private List listeners; + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ protected org.bukkit.inventory.InventoryHolder bukkitOwner; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return bukkitOwner; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return null; ++ } ++ ++ public SimpleContainer(SimpleContainer original) { ++ this(original.size); ++ for (int slot = 0; slot < original.size; slot++) { ++ this.items.set(slot, original.items.get(slot).copy()); ++ } ++ } ++ + public SimpleContainer(int size) { + this.size = size; + this.items = NonNullList.withSize(size, ItemStack.EMPTY); + } + ++ public SimpleContainer(int i, org.bukkit.inventory.InventoryHolder owner) { ++ this.bukkitOwner = owner; ++ // CraftBukkit end ++ this.size = i; ++ this.items = NonNullList.withSize(i, ItemStack.EMPTY); ++ } ++ + public SimpleContainer(ItemStack... items) { + this.size = items.length; + this.items = NonNullList.of(ItemStack.EMPTY, items); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/damagesource/DamageSource.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/damagesource/DamageSource.java.patch new file mode 100644 index 0000000000..471b9ae2dd --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/damagesource/DamageSource.java.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/world/damagesource/DamageSource.java ++++ b/net/minecraft/world/damagesource/DamageSource.java +@@ -19,8 +20,39 @@ + private final Entity directEntity; + @Nullable + private final Vec3 damageSourcePosition; ++ // CraftBukkit start ++ private boolean sweep; ++ private boolean melting; ++ private boolean poison; + +- @Override ++ public boolean isSweep() { ++ return sweep; ++ } ++ ++ public DamageSource sweep() { ++ this.sweep = true; ++ return this; ++ } ++ ++ public boolean isMelting() { ++ return melting; ++ } ++ ++ public DamageSource melting() { ++ this.melting = true; ++ return this; ++ } ++ ++ public boolean isPoison() { ++ return poison; ++ } ++ ++ public DamageSource poison() { ++ this.poison = true; ++ return this; ++ } ++ // CraftBukkit end ++ + public String toString() { + return "DamageSource (" + this.type().msgId() + ")"; + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/damagesource/DamageSources.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/damagesource/DamageSources.java.patch new file mode 100644 index 0000000000..437fb8bf51 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/damagesource/DamageSources.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/damagesource/DamageSources.java ++++ b/net/minecraft/world/damagesource/DamageSources.java +@@ -40,9 +41,15 @@ + private final DamageSource stalagmite; + private final DamageSource outsideBorder; + private final DamageSource genericKill; ++ // CraftBukkit start ++ public final DamageSource melting; ++ public final DamageSource poison; + + public DamageSources(RegistryAccess registry) { + this.damageTypes = registry.registryOrThrow(Registries.DAMAGE_TYPE); ++ this.melting = this.source(DamageTypes.ON_FIRE).melting(); ++ this.poison = this.source(DamageTypes.MAGIC).poison(); ++ // CraftBukkit end + this.inFire = this.source(DamageTypes.IN_FIRE); + this.lightningBolt = this.source(DamageTypes.LIGHTNING_BOLT); + this.onFire = this.source(DamageTypes.ON_FIRE); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/effect/HealOrHarmMobEffect.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/effect/HealOrHarmMobEffect.java.patch new file mode 100644 index 0000000000..5cb5a9ac43 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/effect/HealOrHarmMobEffect.java.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/effect/HealOrHarmMobEffect.java ++++ b/net/minecraft/world/effect/HealOrHarmMobEffect.java +@@ -16,7 +17,7 @@ + public void applyEffectTick(LivingEntity livingEntity, int amplifier) { + super.applyEffectTick(livingEntity, amplifier); + if (this.isHarm == livingEntity.isInvertedHealAndHarm()) { +- livingEntity.heal((float)Math.max(4 << amplifier, 0)); ++ livingEntity.heal((float) Math.max(4 << amplifier, 0), org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.MAGIC); // CraftBukkit + } else { + livingEntity.hurt(livingEntity.damageSources().magic(), (float)(6 << amplifier)); + } +@@ -25,8 +29,8 @@ + @Override + public void applyInstantenousEffect(@Nullable Entity source, @Nullable Entity indirectSource, LivingEntity livingEntity, int amplifier, double health) { + if (this.isHarm == livingEntity.isInvertedHealAndHarm()) { +- int i = (int)(health * (double)(4 << amplifier) + 0.5); +- livingEntity.heal((float)i); ++ j = (int) (health * (double) (4 << amplifier) + 0.5D); ++ livingEntity.heal((float) j, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.MAGIC); // CraftBukkit + } else { + int i = (int)(health * (double)(6 << amplifier) + 0.5); + if (source == null) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/effect/HungerMobEffect.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/effect/HungerMobEffect.java.patch new file mode 100644 index 0000000000..139a72e2bd --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/effect/HungerMobEffect.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/effect/HungerMobEffect.java ++++ b/net/minecraft/world/effect/HungerMobEffect.java +@@ -11,8 +12,10 @@ + @Override + public void applyEffectTick(LivingEntity livingEntity, int amplifier) { + super.applyEffectTick(livingEntity, amplifier); +- if (livingEntity instanceof Player player) { +- player.causeFoodExhaustion(0.005F * (float)(amplifier + 1)); ++ if (livingEntity instanceof Player) { ++ Player entityhuman = (Player) livingEntity; ++ ++ entityhuman.causeFoodExhaustion(0.005F * (float) (amplifier + 1), org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.HUNGER_EFFECT); // CraftBukkit - EntityExhaustionEvent + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/effect/MobEffectUtil.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/effect/MobEffectUtil.java.patch new file mode 100644 index 0000000000..34b576545d --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/effect/MobEffectUtil.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/effect/MobEffectUtil.java ++++ b/net/minecraft/world/effect/MobEffectUtil.java +@@ -43,21 +48,21 @@ + return entity.hasEffect(MobEffects.WATER_BREATHING) || entity.hasEffect(MobEffects.CONDUIT_POWER); + } + +- public static List addEffectToPlayersAround( +- ServerLevel level, @Nullable Entity source, Vec3 pos, double radius, MobEffectInstance effect, int duration +- ) { +- MobEffect effect1 = effect.getEffect(); +- List players = level.getPlayers( +- serverPlayer -> serverPlayer.gameMode.isSurvival() +- && (source == null || !source.isAlliedTo(serverPlayer)) +- && pos.closerThan(serverPlayer.position(), radius) +- && ( +- !serverPlayer.hasEffect(effect1) +- || serverPlayer.getEffect(effect1).getAmplifier() < effect.getAmplifier() +- || serverPlayer.getEffect(effect1).endsWithin(duration - 1) +- ) +- ); +- players.forEach(serverPlayer -> serverPlayer.addEffect(new MobEffectInstance(effect), source)); +- return players; ++ public static List addEffectToPlayersAround(ServerLevel level, @Nullable Entity source, Vec3 pos, double radius, MobEffectInstance mobeffect, int effect) { ++ // CraftBukkit start ++ return addEffectToPlayersAround(level, source, pos, radius, mobeffect, effect, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); + } ++ ++ public static List addEffectToPlayersAround(ServerLevel worldserver, @Nullable Entity entity, Vec3 vec3d, double d0, MobEffectInstance mobeffect, int i, org.bukkit.event.entity.EntityPotionEffectEvent.Cause cause) { ++ // CraftBukkit end ++ MobEffect mobeffectlist = mobeffect.getEffect(); ++ List list = worldserver.getPlayers((entityplayer) -> { ++ return entityplayer.gameMode.isSurvival() && (entity == null || !entity.isAlliedTo((Entity) entityplayer)) && vec3d.closerThan(entityplayer.position(), d0) && (!entityplayer.hasEffect(mobeffectlist) || entityplayer.getEffect(mobeffectlist).getAmplifier() < mobeffect.getAmplifier() || entityplayer.getEffect(mobeffectlist).endsWithin(i - 1)); ++ }); ++ ++ list.forEach((entityplayer) -> { ++ entityplayer.addEffect(new MobEffectInstance(mobeffect), entity, cause); // CraftBukkit ++ }); ++ return list; ++ } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/effect/PoisonMobEffect.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/effect/PoisonMobEffect.java.patch new file mode 100644 index 0000000000..692eb9e956 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/effect/PoisonMobEffect.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/effect/PoisonMobEffect.java ++++ b/net/minecraft/world/effect/PoisonMobEffect.java +@@ -11,7 +12,7 @@ + public void applyEffectTick(LivingEntity livingEntity, int amplifier) { + super.applyEffectTick(livingEntity, amplifier); + if (livingEntity.getHealth() > 1.0F) { +- livingEntity.hurt(livingEntity.damageSources().magic(), 1.0F); ++ livingEntity.hurt(livingEntity.damageSources().poison, 1.0F); // CraftBukkit - DamageSource.MAGIC -> CraftEventFactory.POISON + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/effect/RegenerationMobEffect.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/effect/RegenerationMobEffect.java.patch new file mode 100644 index 0000000000..0bdab8d665 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/effect/RegenerationMobEffect.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/effect/RegenerationMobEffect.java ++++ b/net/minecraft/world/effect/RegenerationMobEffect.java +@@ -11,7 +12,7 @@ + public void applyEffectTick(LivingEntity livingEntity, int amplifier) { + super.applyEffectTick(livingEntity, amplifier); + if (livingEntity.getHealth() < livingEntity.getMaxHealth()) { +- livingEntity.heal(1.0F); ++ livingEntity.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.MAGIC_REGEN); // CraftBukkit + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/effect/SaturationMobEffect.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/effect/SaturationMobEffect.java.patch new file mode 100644 index 0000000000..d3290f2029 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/effect/SaturationMobEffect.java.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/effect/SaturationMobEffect.java ++++ b/net/minecraft/world/effect/SaturationMobEffect.java +@@ -2,6 +2,10 @@ + + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.player.Player; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + class SaturationMobEffect extends InstantenousMobEffect { + protected SaturationMobEffect(MobEffectCategory category, int color) { +@@ -11,8 +16,18 @@ + @Override + public void applyEffectTick(LivingEntity livingEntity, int amplifier) { + super.applyEffectTick(livingEntity, amplifier); +- if (!livingEntity.level().isClientSide && livingEntity instanceof Player player) { +- player.getFoodData().eat(amplifier + 1, 1.0F); ++ if (!livingEntity.level().isClientSide && livingEntity instanceof Player) { ++ Player entityhuman = (Player) livingEntity; ++ ++ // CraftBukkit start ++ int oldFoodLevel = entityhuman.getFoodData().foodLevel; ++ org.bukkit.event.entity.FoodLevelChangeEvent event = CraftEventFactory.callFoodLevelChangeEvent(entityhuman, amplifier + 1 + oldFoodLevel); ++ if (!event.isCancelled()) { ++ entityhuman.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, 1.0F); ++ } ++ ++ ((CraftPlayer) entityhuman.getBukkitEntity()).sendHealthUpdate(); ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/AgeableMob.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/AgeableMob.java.patch new file mode 100644 index 0000000000..2b255ec379 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/AgeableMob.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/entity/AgeableMob.java ++++ b/net/minecraft/world/entity/AgeableMob.java +@@ -19,6 +20,7 @@ + protected int age; + protected int forcedAge; + protected int forcedAgeTimer; ++ public boolean ageLocked; // CraftBukkit + + protected AgeableMob(EntityType entityType, Level level) { + super(entityType, level); +@@ -103,6 +104,7 @@ + super.addAdditionalSaveData(compound); + compound.putInt("Age", this.getAge()); + compound.putInt("ForcedAge", this.forcedAge); ++ compound.putBoolean("AgeLocked", this.ageLocked); // CraftBukkit + } + + @Override +@@ -110,6 +112,7 @@ + super.readAdditionalSaveData(compound); + this.setAge(compound.getInt("Age")); + this.forcedAge = compound.getInt("ForcedAge"); ++ this.ageLocked = compound.getBoolean("AgeLocked"); // CraftBukkit + } + + @Override +@@ -124,7 +127,7 @@ + @Override + public void aiStep() { + super.aiStep(); +- if (this.level().isClientSide) { ++ if (this.level().isClientSide || ageLocked) { // CraftBukkit + if (this.forcedAgeTimer > 0) { + if (this.forcedAgeTimer % 4 == 0) { + this.level().addParticle(ParticleTypes.HAPPY_VILLAGER, this.getRandomX(1.0), this.getRandomY() + 0.5, this.getRandomZ(1.0), 0.0, 0.0, 0.0); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/AreaEffectCloud.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/AreaEffectCloud.java.patch new file mode 100644 index 0000000000..64d33de08e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/AreaEffectCloud.java.patch @@ -0,0 +1,58 @@ +--- a/net/minecraft/world/entity/AreaEffectCloud.java ++++ b/net/minecraft/world/entity/AreaEffectCloud.java +@@ -28,6 +30,9 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.material.PushReaction; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.entity.LivingEntity; ++// CraftBukkit end + + public class AreaEffectCloud extends Entity implements TraceableEntity { + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -251,12 +264,40 @@ + if (d7 <= (double)(radius * radius)) { + this.victims.put(livingEntity, this.tickCount + this.reapplicationDelay); + +- for (MobEffectInstance mobEffectInstance1 : list) { +- if (mobEffectInstance1.getEffect().isInstantenous()) { +- mobEffectInstance1.getEffect() +- .applyInstantenousEffect(this, this.getOwner(), livingEntity, mobEffectInstance1.getAmplifier(), 0.5); ++ if (!list1.isEmpty()) { ++ Iterator iterator1 = list1.iterator(); ++ ++ List entities = new java.util.ArrayList(); // CraftBukkit ++ while (iterator1.hasNext()) { ++ net.minecraft.world.entity.LivingEntity entityliving = (net.minecraft.world.entity.LivingEntity) iterator1.next(); ++ ++ if (!this.victims.containsKey(entityliving) && entityliving.isAffectedByPotions()) { ++ double d6 = entityliving.getX() - this.getX(); ++ double d7 = entityliving.getZ() - this.getZ(); ++ double d8 = d6 * d6 + d7 * d7; ++ ++ if (d8 <= (double) (f * f)) { ++ // CraftBukkit start ++ entities.add((LivingEntity) entityliving.getBukkitEntity()); ++ } ++ } ++ } ++ org.bukkit.event.entity.AreaEffectCloudApplyEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callAreaEffectCloudApplyEvent(this, entities); ++ if (!event.isCancelled()) { ++ for (LivingEntity entity : event.getAffectedEntities()) { ++ if (entity instanceof CraftLivingEntity) { ++ net.minecraft.world.entity.LivingEntity entityliving = ((CraftLivingEntity) entity).getHandle(); ++ // CraftBukkit end ++ this.victims.put(entityliving, this.tickCount + this.reapplicationDelay); ++ Iterator iterator2 = list.iterator(); ++ ++ while (iterator2.hasNext()) { ++ MobEffectInstance mobeffect1 = (MobEffectInstance) iterator2.next(); ++ ++ if (mobeffect1.getEffect().isInstantenous()) { ++ mobeffect1.getEffect().applyInstantenousEffect(this, this.getOwner(), entityliving, mobeffect1.getAmplifier(), 0.5D); + } else { +- livingEntity.addEffect(new MobEffectInstance(mobEffectInstance1), this); ++ entityliving.addEffect(new MobEffectInstance(mobeffect1), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AREA_EFFECT_CLOUD); // CraftBukkit + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/Entity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/Entity.java.patch new file mode 100644 index 0000000000..108c062a94 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/Entity.java.patch @@ -0,0 +1,1065 @@ +--- a/net/minecraft/world/entity/Entity.java ++++ b/net/minecraft/world/entity/Entity.java +@@ -123,8 +126,63 @@ + import net.minecraft.world.scores.Team; + import org.joml.Vector3f; + import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.Server; ++import org.bukkit.block.BlockFace; ++import org.bukkit.command.CommandSender; ++import org.bukkit.craftbukkit.event.CraftPortalEvent; ++import org.bukkit.entity.Hanging; ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.entity.Vehicle; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.hanging.HangingBreakByEntityEvent; ++import org.bukkit.event.vehicle.VehicleBlockCollisionEvent; ++import org.bukkit.event.vehicle.VehicleEnterEvent; ++import org.bukkit.event.vehicle.VehicleExitEvent; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.entity.CraftEntity; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.Pose; ++import org.bukkit.event.entity.EntityAirChangeEvent; ++import org.bukkit.event.entity.EntityCombustEvent; ++import org.bukkit.event.entity.EntityDropItemEvent; ++import org.bukkit.event.entity.EntityPortalEvent; ++import org.bukkit.event.entity.EntityPoseChangeEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++import org.bukkit.plugin.PluginManager; ++// CraftBukkit end + +-public abstract class Entity implements Nameable, EntityAccess, CommandSource, ScoreHolder { ++public abstract class Entity implements INamableTileEntity, EntityAccess, CommandSource, ScoreHolder { ++ ++ // CraftBukkit start ++ private static final int CURRENT_LEVEL = 2; ++ static boolean isLevelAtLeast(CompoundTag tag, int level) { ++ return tag.contains("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; ++ } ++ ++ private CraftEntity bukkitEntity; ++ ++ public CraftEntity getBukkitEntity() { ++ if (bukkitEntity == null) { ++ bukkitEntity = CraftEntity.getEntity(level.getCraftServer(), this); ++ } ++ return bukkitEntity; ++ } ++ ++ @Override ++ public CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return getBukkitEntity(); ++ } ++ ++ // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ public int getDefaultMaxAirSupply() { ++ return TOTAL_AIR_SUPPLY; ++ } ++ // CraftBukkit end ++ + private static final Logger LOGGER = LogUtils.getLogger(); + public static final String ID_TAG = "id"; + public static final String PASSENGERS_TAG = "Passengers"; +@@ -240,8 +296,31 @@ + private int lastCrystalSoundPlayTick; + private boolean hasVisualFire; + @Nullable +- private BlockState feetBlockState = null; ++ private IBlockData feetBlockState; ++ // CraftBukkit start ++ public boolean persist = true; ++ public boolean visibleByDefault = true; ++ public boolean valid; ++ public boolean inWorld = false; ++ public boolean generation; ++ public int maxAirTicks = getDefaultMaxAirSupply(); // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only ++ public boolean lastDamageCancelled; // SPIGOT-5339, SPIGOT-6252, SPIGOT-6777: Keep track if the event was canceled ++ public boolean persistentInvisibility = false; ++ public BlockPos lastLavaContact; ++ // Marks an entity, that it was removed by a plugin via Entity#remove ++ // Main use case currently is for SPIGOT-7487, preventing dropping of leash when leash is removed ++ public boolean pluginRemoved = false; + ++ public float getBukkitYaw() { ++ return this.yRot; ++ } ++ ++ public boolean isChunkLoaded() { ++ return level.hasChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); ++ } ++ // CraftBukkit end ++ + public Entity(EntityType entityType, Level level) { + this.type = entityType; + this.level = level; +@@ -353,8 +452,14 @@ + public void onClientRemoval() { + } + +- public void setPose(Pose pose) { +- this.entityData.set(DATA_POSE, pose); ++ public void setPose(EntityPose pose) { ++ // CraftBukkit start ++ if (pose == this.getPose()) { ++ return; ++ } ++ this.level.getCraftServer().getPluginManager().callEvent(new EntityPoseChangeEvent(this.getBukkitEntity(), Pose.values()[pose.ordinal()])); ++ // CraftBukkit end ++ this.entityData.set(Entity.DATA_POSE, pose); + } + + public Pose getPose() { +@@ -377,6 +483,33 @@ + } + + protected void setRot(float yRot, float xRot) { ++ // CraftBukkit start - yaw was sometimes set to NaN, so we need to set it back to 0 ++ if (Float.isNaN(yRot)) { ++ yRot = 0; ++ } ++ ++ if (yRot == Float.POSITIVE_INFINITY || yRot == Float.NEGATIVE_INFINITY) { ++ if (this instanceof ServerPlayer) { ++ this.level.getCraftServer().getLogger().warning(this.getScoreboardName() + " was caught trying to crash the server with an invalid yaw"); ++ ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Infinite yaw (Hacking?)"); ++ } ++ yRot = 0; ++ } ++ ++ // pitch was sometimes set to NaN, so we need to set it back to 0 ++ if (Float.isNaN(xRot)) { ++ xRot = 0; ++ } ++ ++ if (xRot == Float.POSITIVE_INFINITY || xRot == Float.NEGATIVE_INFINITY) { ++ if (this instanceof ServerPlayer) { ++ this.level.getCraftServer().getLogger().warning(this.getScoreboardName() + " was caught trying to crash the server with an invalid pitch"); ++ ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Infinite pitch (Hacking?)"); ++ } ++ xRot = 0; ++ } ++ // CraftBukkit end ++ + this.setYRot(yRot % 360.0F); + this.setXRot(xRot % 360.0F); + } +@@ -416,6 +551,15 @@ + this.baseTick(); + } + ++ // CraftBukkit start ++ public void postTick() { ++ // No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle ++ if (!(this instanceof ServerPlayer)) { ++ this.handleNetherPortal(); ++ } ++ } ++ // CraftBukkit end ++ + public void baseTick() { + this.level().getProfiler().push("entityBaseTick"); + this.feetBlockState = null; +@@ -430,7 +574,7 @@ + this.walkDistO = this.walkDist; + this.xRotO = this.getXRot(); + this.yRotO = this.getYRot(); +- this.handleNetherPortal(); ++ if (this instanceof ServerPlayer) this.handleNetherPortal(); // CraftBukkit - // Moved up to postTick + if (this.canSpawnSprintParticle()) { + this.spawnSprintParticle(); + } +@@ -465,6 +609,10 @@ + if (this.isInLava()) { + this.lavaHurt(); + this.fallDistance *= 0.5F; ++ // CraftBukkit start ++ } else { ++ this.lastLavaContact = null; ++ // CraftBukkit end + } + + this.checkBelowWorld(); +@@ -514,18 +664,49 @@ + + public void lavaHurt() { + if (!this.fireImmune()) { +- this.setSecondsOnFire(15); ++ // CraftBukkit start - Fallen in lava TODO: this event spams! ++ if (this instanceof net.minecraft.world.entity.LivingEntity && remainingFireTicks <= 0) { ++ // not on fire yet ++ org.bukkit.block.Block damager = (lastLavaContact == null) ? null : org.bukkit.craftbukkit.block.CraftBlock.at(level, lastLavaContact); ++ org.bukkit.entity.Entity damagee = this.getBukkitEntity(); ++ EntityCombustEvent combustEvent = new org.bukkit.event.entity.EntityCombustByBlockEvent(damager, damagee, 15); ++ this.level.getCraftServer().getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ this.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ } else { ++ // This will be called every single tick the entity is in lava, so don't throw an event ++ this.setSecondsOnFire(15, false); ++ } ++ CraftEventFactory.blockDamage = (lastLavaContact) == null ? null : org.bukkit.craftbukkit.block.CraftBlock.at(level, lastLavaContact); + if (this.hurt(this.damageSources().lava(), 4.0F)) { + this.playSound(SoundEvents.GENERIC_BURN, 0.4F, 2.0F + this.random.nextFloat() * 0.4F); + } ++ CraftEventFactory.blockDamage = null; ++ // CraftBukkit end - we also don't throw an event unless the object in lava is living, to save on some event calls ++ + } + } + + public void setSecondsOnFire(int seconds) { +- int i = seconds * 20; +- if (this instanceof LivingEntity) { +- i = ProtectionEnchantment.getFireAfterDampener((LivingEntity)this, i); ++ // CraftBukkit start ++ this.setSecondsOnFire(seconds, true); ++ } ++ ++ public void setSecondsOnFire(int i, boolean callEvent) { ++ if (callEvent) { ++ EntityCombustEvent event = new EntityCombustEvent(this.getBukkitEntity(), i); ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ i = event.getDuration(); + } ++ // CraftBukkit end ++ int j = i * 20; + + if (this.remainingFireTicks < i) { + this.setRemainingFireTicks(i); +@@ -662,6 +856,28 @@ + block.updateEntityAfterFallOn(this.level(), this); + } + ++ // CraftBukkit start ++ if (horizontalCollision && getBukkitEntity() instanceof Vehicle) { ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ org.bukkit.block.Block bl = this.level.getWorld().getBlockAt(Mth.floor(this.getX()), Mth.floor(this.getY()), Mth.floor(this.getZ())); ++ ++ if (pos.x > vec3d1.x) { ++ bl = bl.getRelative(BlockFace.EAST); ++ } else if (pos.x < vec3d1.x) { ++ bl = bl.getRelative(BlockFace.WEST); ++ } else if (pos.z > vec3d1.z) { ++ bl = bl.getRelative(BlockFace.SOUTH); ++ } else if (pos.z < vec3d1.z) { ++ bl = bl.getRelative(BlockFace.NORTH); ++ } ++ ++ if (!bl.getType().isAir()) { ++ VehicleBlockCollisionEvent event = new VehicleBlockCollisionEvent(vehicle, bl); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ } ++ } ++ // CraftBukkit end ++ + if (this.onGround()) { + block.stepOn(this.level(), onPosLegacy, blockState, this); + } +@@ -976,6 +1205,20 @@ + return SoundEvents.GENERIC_SPLASH; + } + ++ // CraftBukkit start - Add delegate methods ++ public SoundEvent getSwimSound0() { ++ return getSwimSound(); ++ } ++ ++ public SoundEvent getSwimSplashSound0() { ++ return getSwimSplashSound(); ++ } ++ ++ public SoundEvent getSwimHighSpeedSplashSound0() { ++ return getSwimHighSpeedSplashSound(); ++ } ++ // CraftBukkit end ++ + protected void checkInsideBlocks() { + AABB boundingBox = this.getBoundingBox(); + BlockPos blockPos = BlockPos.containing(boundingBox.minX + 1.0E-7, boundingBox.minY + 1.0E-7, boundingBox.minZ + 1.0E-7); +@@ -1357,13 +1625,15 @@ + this.xRotO = this.getXRot(); + } + +- public void absMoveTo(double x, double y, double z) { +- double d = Mth.clamp(x, -3.0E7, 3.0E7); +- double d1 = Mth.clamp(z, -3.0E7, 3.0E7); +- this.xo = d; +- this.yo = y; +- this.zo = d1; +- this.setPos(d, y, d1); ++ public void absMoveTo(double x, double d1, double y) { ++ double d3 = Mth.clamp(x, -3.0E7D, 3.0E7D); ++ double d4 = Mth.clamp(y, -3.0E7D, 3.0E7D); ++ ++ this.xo = d3; ++ this.yo = d1; ++ this.zo = d4; ++ this.setPos(d3, d1, d4); ++ if (valid) level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit + } + + public void moveTo(Vec3 vec) { +@@ -1549,6 +1828,12 @@ + return false; + } + ++ // CraftBukkit start - collidable API ++ public boolean canCollideWithBukkit(Entity entity) { ++ return isPushable(); ++ } ++ // CraftBukkit end ++ + public void awardKillScore(Entity killed, int scoreValue, DamageSource source) { + if (killed instanceof ServerPlayer) { + CriteriaTriggers.ENTITY_KILLED_PLAYER.trigger((ServerPlayer)killed, this, source); +@@ -1574,15 +1862,22 @@ + } + + public boolean saveAsPassenger(CompoundTag compound) { ++ // CraftBukkit start - allow excluding certain data when saving ++ return saveAsPassenger(compound, true); ++ } ++ ++ public boolean saveAsPassenger(CompoundTag nbttagcompound, boolean includeAll) { ++ // CraftBukkit end + if (this.removalReason != null && !this.removalReason.shouldSave()) { + return false; + } else { +- String encodeId = this.getEncodeId(); +- if (encodeId == null) { ++ String s = this.getEncodeId(); ++ ++ if (!this.persist || s == null) { // CraftBukkit - persist flag + return false; + } else { +- compound.putString("id", encodeId); +- this.saveWithoutId(compound); ++ nbttagcompound.putString("id", s); ++ this.saveWithoutId(nbttagcompound, includeAll); // CraftBukkit - pass on includeAll + return true; + } + } +@@ -1593,28 +1888,73 @@ + } + + public CompoundTag saveWithoutId(CompoundTag compound) { ++ // CraftBukkit start - allow excluding certain data when saving ++ return saveWithoutId(compound, true); ++ } ++ ++ public CompoundTag saveWithoutId(CompoundTag nbttagcompound, boolean includeAll) { ++ // CraftBukkit end + try { +- if (this.vehicle != null) { +- compound.put("Pos", this.newDoubleList(this.vehicle.getX(), this.getY(), this.vehicle.getZ())); +- } else { +- compound.put("Pos", this.newDoubleList(this.getX(), this.getY(), this.getZ())); ++ // CraftBukkit start - selectively save position ++ if (includeAll) { ++ if (this.vehicle != null) { ++ nbttagcompound.put("Pos", this.newDoubleList(this.vehicle.getX(), this.getY(), this.vehicle.getZ())); ++ } else { ++ nbttagcompound.put("Pos", this.newDoubleList(this.getX(), this.getY(), this.getZ())); ++ } + } ++ // CraftBukkit end + +- Vec3 deltaMovement = this.getDeltaMovement(); +- compound.put("Motion", this.newDoubleList(deltaMovement.x, deltaMovement.y, deltaMovement.z)); +- compound.put("Rotation", this.newFloatList(this.getYRot(), this.getXRot())); +- compound.putFloat("FallDistance", this.fallDistance); +- compound.putShort("Fire", (short)this.remainingFireTicks); +- compound.putShort("Air", (short)this.getAirSupply()); +- compound.putBoolean("OnGround", this.onGround()); +- compound.putBoolean("Invulnerable", this.invulnerable); +- compound.putInt("PortalCooldown", this.portalCooldown); +- compound.putUUID("UUID", this.getUUID()); +- Component customName = this.getCustomName(); +- if (customName != null) { +- compound.putString("CustomName", Component.Serializer.toJson(customName)); ++ Vec3 vec3d = this.getDeltaMovement(); ++ ++ nbttagcompound.put("Motion", this.newDoubleList(vec3d.x, vec3d.y, vec3d.z)); ++ ++ // CraftBukkit start - Checking for NaN pitch/yaw and resetting to zero ++ // TODO: make sure this is the best way to address this. ++ if (Float.isNaN(this.yRot)) { ++ this.yRot = 0; + } + ++ if (Float.isNaN(this.xRot)) { ++ this.xRot = 0; ++ } ++ // CraftBukkit end ++ ++ nbttagcompound.put("Rotation", this.newFloatList(this.getYRot(), this.getXRot())); ++ nbttagcompound.putFloat("FallDistance", this.fallDistance); ++ nbttagcompound.putShort("Fire", (short) this.remainingFireTicks); ++ nbttagcompound.putShort("Air", (short) this.getAirSupply()); ++ nbttagcompound.putBoolean("OnGround", this.onGround()); ++ nbttagcompound.putBoolean("Invulnerable", this.invulnerable); ++ nbttagcompound.putInt("PortalCooldown", this.portalCooldown); ++ // CraftBukkit start - selectively save uuid and world ++ if (includeAll) { ++ nbttagcompound.putUUID("UUID", this.getUUID()); ++ // PAIL: Check above UUID reads 1.8 properly, ie: UUIDMost / UUIDLeast ++ nbttagcompound.putLong("WorldUUIDLeast", ((ServerLevel) this.level).getWorld().getUID().getLeastSignificantBits()); ++ nbttagcompound.putLong("WorldUUIDMost", ((ServerLevel) this.level).getWorld().getUID().getMostSignificantBits()); ++ } ++ nbttagcompound.putInt("Bukkit.updateLevel", CURRENT_LEVEL); ++ if (!this.persist) { ++ nbttagcompound.putBoolean("Bukkit.persist", this.persist); ++ } ++ if (!this.visibleByDefault) { ++ nbttagcompound.putBoolean("Bukkit.visibleByDefault", this.visibleByDefault); ++ } ++ if (this.persistentInvisibility) { ++ nbttagcompound.putBoolean("Bukkit.invisible", this.persistentInvisibility); ++ } ++ // SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ if (maxAirTicks != getDefaultMaxAirSupply()) { ++ nbttagcompound.putInt("Bukkit.MaxAirSupply", getMaxAirSupply()); ++ } ++ // CraftBukkit end ++ Component ichatbasecomponent = this.getCustomName(); ++ ++ if (ichatbasecomponent != null) { ++ nbttagcompound.putString("CustomName", Component.Serializer.toJson(ichatbasecomponent)); ++ } ++ + if (this.isCustomNameVisible()) { + compound.putBoolean("CustomNameVisible", this.isCustomNameVisible()); + } +@@ -1650,14 +1997,16 @@ + compound.put("Tags", list); + } + +- this.addAdditionalSaveData(compound); ++ this.addAdditionalSaveData(nbttagcompound, includeAll); // CraftBukkit - pass on includeAll + if (this.isVehicle()) { + ListTag list = new ListTag(); + +- for (Entity entity : this.getPassengers()) { +- CompoundTag compoundTag = new CompoundTag(); +- if (entity.saveAsPassenger(compoundTag)) { +- list.add(compoundTag); ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ CompoundTag nbttagcompound1 = new CompoundTag(); ++ ++ if (entity.saveAsPassenger(nbttagcompound1, includeAll)) { // CraftBukkit - pass on includeAll ++ nbttaglist.add(nbttagcompound1); + } + } + +@@ -1666,12 +2016,18 @@ + } + } + +- return compound; +- } catch (Throwable var9) { +- CrashReport crashReport = CrashReport.forThrowable(var9, "Saving entity NBT"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Entity being saved"); +- this.fillCrashReportCategory(crashReportCategory); +- throw new ReportedException(crashReport); ++ // CraftBukkit start - stores eventually existing bukkit values ++ if (this.bukkitEntity != null) { ++ this.bukkitEntity.storeBukkitValues(nbttagcompound); ++ } ++ // CraftBukkit end ++ return nbttagcompound; ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being saved"); ++ ++ this.fillCrashReportCategory(crashreportsystemdetails); ++ throw new ReportedException(crashreport); + } + } + +@@ -1749,11 +2104,51 @@ + } else { + throw new IllegalStateException("Entity has invalid rotation"); + } +- } catch (Throwable var17) { +- CrashReport crashReport = CrashReport.forThrowable(var17, "Loading entity NBT"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Entity being loaded"); +- this.fillCrashReportCategory(crashReportCategory); +- throw new ReportedException(crashReport); ++ ++ // CraftBukkit start ++ this.persist = !compound.contains("Bukkit.persist") || compound.getBoolean("Bukkit.persist"); ++ this.visibleByDefault = !compound.contains("Bukkit.visibleByDefault") || compound.getBoolean("Bukkit.visibleByDefault"); ++ // SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ if (compound.contains("Bukkit.MaxAirSupply")) { ++ maxAirTicks = compound.getInt("Bukkit.MaxAirSupply"); ++ } ++ // CraftBukkit end ++ ++ // CraftBukkit start - Reset world ++ if (this instanceof ServerPlayer) { ++ Server server = Bukkit.getServer(); ++ org.bukkit.World bworld = null; ++ ++ // TODO: Remove World related checks, replaced with WorldUID ++ String worldName = compound.getString("world"); ++ ++ if (compound.contains("WorldUUIDMost") && compound.contains("WorldUUIDLeast")) { ++ UUID uid = new UUID(compound.getLong("WorldUUIDMost"), compound.getLong("WorldUUIDLeast")); ++ bworld = server.getWorld(uid); ++ } else { ++ bworld = server.getWorld(worldName); ++ } ++ ++ if (bworld == null) { ++ bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getLevel(Level.OVERWORLD).getWorld(); ++ } ++ ++ ((ServerPlayer) this).setLevel(bworld == null ? null : ((CraftWorld) bworld).getHandle()); ++ } ++ this.getBukkitEntity().readBukkitValues(compound); ++ if (compound.contains("Bukkit.invisible")) { ++ boolean bukkitInvisible = compound.getBoolean("Bukkit.invisible"); ++ this.setInvisible(bukkitInvisible); ++ this.persistentInvisibility = bukkitInvisible; ++ } ++ // CraftBukkit end ++ ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being loaded"); ++ ++ this.fillCrashReportCategory(crashreportsystemdetails); ++ throw new ReportedException(crashreport); + } + } + +@@ -1768,6 +2164,12 @@ + return type.canSerialize() && key != null ? key.toString() : null; + } + ++ // CraftBukkit start - allow excluding certain data when saving ++ protected void addAdditionalSaveData(CompoundTag nbttagcompound, boolean includeAll) { ++ addAdditionalSaveData(nbttagcompound); ++ } ++ // CraftBukkit end ++ + protected abstract void readAdditionalSaveData(CompoundTag compound); + + protected abstract void addAdditionalSaveData(CompoundTag compound); +@@ -1814,10 +2224,24 @@ + } else if (this.level().isClientSide) { + return null; + } else { +- ItemEntity itemEntity = new ItemEntity(this.level(), this.getX(), this.getY() + (double)offsetY, this.getZ(), stack); +- itemEntity.setDefaultPickUpDelay(); +- this.level().addFreshEntity(itemEntity); +- return itemEntity; ++ // CraftBukkit start - Capture drops for death event ++ if (this instanceof net.minecraft.world.entity.LivingEntity && !((net.minecraft.world.entity.LivingEntity) this).forceDrops) { ++ ((net.minecraft.world.entity.LivingEntity) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(stack)); ++ return null; ++ } ++ // CraftBukkit end ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY() + (double) offsetY, this.getZ(), stack); ++ ++ entityitem.setDefaultPickUpDelay(); ++ // CraftBukkit start ++ EntityDropItemEvent event = new EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return null; ++ } ++ // CraftBukkit end ++ this.level().addFreshEntity(entityitem); ++ return entityitem; + } + } + +@@ -1918,7 +2334,21 @@ + } + } + +- if (force || this.canRide(vehicle) && vehicle.canAddPassenger(this)) { ++ if (!force && (!this.canRide(vehicle) || !vehicle.canAddPassenger(this))) { ++ return false; ++ } else { ++ // CraftBukkit start ++ if (vehicle.getBukkitEntity() instanceof Vehicle && this.getBukkitEntity() instanceof LivingEntity) { ++ VehicleEnterEvent event = new VehicleEnterEvent((Vehicle) vehicle.getBukkitEntity(), this.getBukkitEntity()); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ if (event.isCancelled()) { ++ return false; ++ } ++ } ++ // CraftBukkit end + if (this.isPassenger()) { + this.stopRiding(); + } +@@ -1950,7 +2382,7 @@ + if (this.vehicle != null) { + Entity entity = this.vehicle; + this.vehicle = null; +- entity.removePassenger(this); ++ if (!entity.removePassenger(this)) this.vehicle = entity; // CraftBukkit + } + } + +@@ -1979,11 +2413,30 @@ + } + } + +- protected void removePassenger(Entity passenger) { +- if (passenger.getVehicle() == this) { ++ protected boolean removePassenger(Entity entity) { // CraftBukkit ++ if (entity.getVehicle() == this) { + throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); + } else { +- if (this.passengers.size() == 1 && this.passengers.get(0) == passenger) { ++ // CraftBukkit start ++ CraftEntity craft = (CraftEntity) entity.getBukkitEntity().getVehicle(); ++ Entity orig = craft == null ? null : craft.getHandle(); ++ if (getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { ++ VehicleExitEvent event = new VehicleExitEvent( ++ (Vehicle) getBukkitEntity(), ++ (LivingEntity) entity.getBukkitEntity() ++ ); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ CraftEntity craftn = (CraftEntity) entity.getBukkitEntity().getVehicle(); ++ Entity n = craftn == null ? null : craftn.getHandle(); ++ if (event.isCancelled() || n != orig) { ++ return false; ++ } ++ } ++ // CraftBukkit end ++ if (this.passengers.size() == 1 && this.passengers.get(0) == entity) { + this.passengers = ImmutableList.of(); + } else { + this.passengers = this.passengers.stream().filter(entity -> entity != passenger).collect(ImmutableList.toImmutableList()); +@@ -1992,6 +2447,7 @@ + passenger.boardingCooldown = 60; + this.gameEvent(GameEvent.ENTITY_DISMOUNT, passenger); + } ++ return true; // CraftBukkit + } + + protected boolean canAddPassenger(Entity passenger) { +@@ -2074,14 +2533,21 @@ + int portalWaitTime = this.getPortalWaitTime(); + ServerLevel serverLevel = (ServerLevel)this.level(); + if (this.isInsidePortal) { +- MinecraftServer server = serverLevel.getServer(); +- ResourceKey resourceKey = this.level().dimension() == Level.NETHER ? Level.OVERWORLD : Level.NETHER; +- ServerLevel level = server.getLevel(resourceKey); +- if (level != null && server.isNetherEnabled() && !this.isPassenger() && this.portalTime++ >= portalWaitTime) { ++ MinecraftServer minecraftserver = worldserver.getServer(); ++ ResourceKey resourcekey = this.level().getTypeKey() == LevelStem.NETHER ? Level.OVERWORLD : Level.NETHER; // CraftBukkit ++ ServerLevel worldserver1 = minecraftserver.getLevel(resourcekey); ++ ++ if (true && !this.isPassenger() && this.portalTime++ >= i) { // CraftBukkit + this.level().getProfiler().push("portal"); + this.portalTime = portalWaitTime; + this.setPortalCooldown(); +- this.changeDimension(level); ++ // CraftBukkit start ++ if (this instanceof ServerPlayer) { ++ ((ServerPlayer) this).changeDimension(worldserver1, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL); ++ } else { ++ this.changeDimension(worldserver1); ++ } ++ // CraftBukkit end + this.level().getProfiler().pop(); + } + +@@ -2206,6 +2671,13 @@ + } + + public void setSwimming(boolean swimming) { ++ // CraftBukkit start ++ if (valid && this.isSwimming() != swimming && this instanceof net.minecraft.world.entity.LivingEntity) { ++ if (CraftEventFactory.callToggleSwimEvent((net.minecraft.world.entity.LivingEntity) this, swimming).isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + this.setSharedFlag(4, swimming); + } + +@@ -2255,8 +2727,12 @@ + return this.getTeam() != null && this.getTeam().isAlliedTo(team); + } + ++ // CraftBukkit - start + public void setInvisible(boolean invisible) { +- this.setSharedFlag(5, invisible); ++ if (!this.persistentInvisibility) { // Prevent Minecraft from removing our invisibility flag ++ this.setSharedFlag(5, invisible); ++ } ++ // CraftBukkit - end + } + + protected boolean getSharedFlag(int flag) { +@@ -2273,7 +2751,7 @@ + } + + public int getMaxAirSupply() { +- return 300; ++ return maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() + } + + public int getAirSupply() { +@@ -2281,7 +2759,18 @@ + } + + public void setAirSupply(int air) { +- this.entityData.set(DATA_AIR_SUPPLY_ID, air); ++ // CraftBukkit start ++ EntityAirChangeEvent event = new EntityAirChangeEvent(this.getBukkitEntity(), air); ++ // Suppress during worldgen ++ if (this.valid) { ++ event.getEntity().getServer().getPluginManager().callEvent(event); ++ } ++ if (event.isCancelled() && this.getAirSupply() != air) { ++ this.entityData.markDirty(Entity.DATA_AIR_SUPPLY_ID); ++ return; ++ } ++ this.entityData.set(Entity.DATA_AIR_SUPPLY_ID, event.getAmount()); ++ // CraftBukkit end + } + + public int getTicksFrozen() { +@@ -2307,11 +2797,41 @@ + + public void thunderHit(ServerLevel level, LightningBolt lightning) { + this.setRemainingFireTicks(this.remainingFireTicks + 1); ++ // CraftBukkit start ++ final org.bukkit.entity.Entity thisBukkitEntity = this.getBukkitEntity(); ++ final org.bukkit.entity.Entity stormBukkitEntity = lightning.getBukkitEntity(); ++ final PluginManager pluginManager = Bukkit.getPluginManager(); ++ // CraftBukkit end ++ + if (this.remainingFireTicks == 0) { +- this.setSecondsOnFire(8); ++ // CraftBukkit start - Call a combust event when lightning strikes ++ EntityCombustByEntityEvent entityCombustEvent = new EntityCombustByEntityEvent(stormBukkitEntity, thisBukkitEntity, 8); ++ pluginManager.callEvent(entityCombustEvent); ++ if (!entityCombustEvent.isCancelled()) { ++ this.setSecondsOnFire(entityCombustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + +- this.hurt(this.damageSources().lightningBolt(), 5.0F); ++ // CraftBukkit start ++ if (thisBukkitEntity instanceof Hanging) { ++ HangingBreakByEntityEvent hangingEvent = new HangingBreakByEntityEvent((Hanging) thisBukkitEntity, stormBukkitEntity); ++ pluginManager.callEvent(hangingEvent); ++ ++ if (hangingEvent.isCancelled()) { ++ return; ++ } ++ } ++ ++ if (this.fireImmune()) { ++ return; ++ } ++ CraftEventFactory.entityDamage = lightning; ++ if (!this.hurt(this.damageSources().lightningBolt(), 5.0F)) { ++ CraftEventFactory.entityDamage = null; ++ return; ++ } ++ // CraftBukkit end + } + + public void onAboveBubbleCol(boolean downwards) { +@@ -2489,24 +2996,60 @@ + + @Nullable + public Entity changeDimension(ServerLevel destination) { ++ // CraftBukkit start ++ return teleportTo(destination, null); ++ } ++ ++ @Nullable ++ public Entity teleportTo(ServerLevel worldserver, Vec3 location) { ++ // CraftBukkit end + if (this.level() instanceof ServerLevel && !this.isRemoved()) { + this.level().getProfiler().push("changeDimension"); +- this.unRide(); ++ // CraftBukkit start ++ // this.unRide(); ++ if (worldserver == null) { ++ return null; ++ } ++ // CraftBukkit end + this.level().getProfiler().push("reposition"); +- PortalInfo portalInfo = this.findDimensionEntryPoint(destination); +- if (portalInfo == null) { ++ PortalInfo shapedetectorshape = (location == null) ? this.findDimensionEntryPoint(worldserver) : new PortalInfo(new Vec3(location.x(), location.y(), location.z()), Vec3.ZERO, this.yRot, this.xRot, worldserver, null); // CraftBukkit ++ ++ if (shapedetectorshape == null) { + return null; + } else { ++ // CraftBukkit start ++ worldserver = shapedetectorshape.world; ++ if (worldserver == level) { ++ // SPIGOT-6782: Just move the entity if a plugin changed the world to the one the entity is already in ++ moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, shapedetectorshape.xRot); ++ setDeltaMovement(shapedetectorshape.speed); ++ return this; ++ } ++ this.unRide(); ++ // CraftBukkit end ++ + this.level().getProfiler().popPush("reloading"); + Entity entity = this.getType().create(destination); + if (entity != null) { + entity.restoreFrom(this); +- entity.moveTo(portalInfo.pos.x, portalInfo.pos.y, portalInfo.pos.z, portalInfo.yRot, entity.getXRot()); +- entity.setDeltaMovement(portalInfo.speed); +- destination.addDuringTeleport(entity); +- if (destination.dimension() == Level.END) { +- ServerLevel.makeObsidianPlatform(destination); ++ entity.moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, entity.getXRot()); ++ entity.setDeltaMovement(shapedetectorshape.speed); ++ // CraftBukkit start - Don't spawn the new entity if the current entity isn't spawned ++ if (this.inWorld) { ++ worldserver.addDuringTeleport(entity); ++ if (worldserver.getTypeKey() == LevelStem.END) { // CraftBukkit ++ ServerLevel.makeObsidianPlatform(worldserver, this); // CraftBukkit ++ } + } ++ // CraftBukkit end ++ // CraftBukkit start - Forward the CraftEntity to the new entity ++ this.getBukkitEntity().setHandle(entity); ++ entity.bukkitEntity = this.getBukkitEntity(); ++ ++ if (this instanceof Mob) { ++ ((Mob) this).dropLeash(true, false); // Unleash to prevent duping of leads. ++ } ++ // CraftBukkit end + } + + this.removeAfterChangingDimensions(); +@@ -2527,39 +3071,52 @@ + + @Nullable + protected PortalInfo findDimensionEntryPoint(ServerLevel destination) { +- boolean flag = this.level().dimension() == Level.END && destination.dimension() == Level.OVERWORLD; +- boolean flag1 = destination.dimension() == Level.END; ++ // CraftBukkit start ++ if (destination == null) { ++ return null; ++ } ++ boolean flag = this.level().getTypeKey() == LevelStem.END && destination.getTypeKey() == LevelStem.OVERWORLD; // fromEndToOverworld ++ boolean flag1 = destination.getTypeKey() == LevelStem.END; // targetIsEnd ++ // CraftBukkit end ++ + if (!flag && !flag1) { +- boolean flag2 = destination.dimension() == Level.NETHER; +- if (this.level().dimension() != Level.NETHER && !flag2) { ++ boolean flag2 = destination.getTypeKey() == LevelStem.NETHER; // CraftBukkit ++ ++ if (this.level().getTypeKey() != LevelStem.NETHER && !flag2) { // CraftBukkit + return null; + } else { +- WorldBorder worldBorder = destination.getWorldBorder(); +- double teleportationScale = DimensionType.getTeleportationScale(this.level().dimensionType(), destination.dimensionType()); +- BlockPos blockPos1 = worldBorder.clampToBounds(this.getX() * teleportationScale, this.getY(), this.getZ() * teleportationScale); +- return this.getExitPortal(destination, blockPos1, flag2, worldBorder) +- .map( +- foundRectangle -> { +- BlockState blockState = this.level().getBlockState(this.portalEntrancePos); +- Direction.Axis axis; +- Vec3 relativePortalPosition; +- if (blockState.hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) { +- axis = blockState.getValue(BlockStateProperties.HORIZONTAL_AXIS); +- BlockUtil.FoundRectangle largestRectangleAround = BlockUtil.getLargestRectangleAround( +- this.portalEntrancePos, axis, 21, Direction.Axis.Y, 21, blockPos2 -> this.level().getBlockState(blockPos2) == blockState +- ); +- relativePortalPosition = this.getRelativePortalPosition(axis, largestRectangleAround); +- } else { +- axis = Direction.Axis.X; +- relativePortalPosition = new Vec3(0.5, 0.0, 0.0); +- } +- +- return PortalShape.createPortalInfo( +- destination, foundRectangle, axis, relativePortalPosition, this, this.getDeltaMovement(), this.getYRot(), this.getXRot() +- ); +- } +- ) +- .orElse(null); ++ WorldBorder worldborder = destination.getWorldBorder(); ++ double d0 = DimensionType.getTeleportationScale(this.level().dimensionType(), destination.dimensionType()); ++ BlockPos blockposition = worldborder.clampToBounds(this.getX() * d0, this.getY(), this.getZ() * d0); ++ // CraftBukkit start ++ CraftPortalEvent event = callPortalEvent(this, destination, new Vec3(blockposition.getX(), blockposition.getY(), blockposition.getZ()), PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, flag2 ? 16 : 128, 16); ++ if (event == null) { ++ return null; ++ } ++ final ServerLevel worldserverFinal = destination = ((CraftWorld) event.getTo().getWorld()).getHandle(); ++ worldborder = worldserverFinal.getWorldBorder(); ++ blockposition = worldborder.clampToBounds(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); ++ ++ return (PortalInfo) this.getExitPortal(destination, blockposition, flag2, worldborder, event.getSearchRadius(), event.getCanCreatePortal(), event.getCreationRadius()).map((blockutil_rectangle) -> { ++ // CraftBukkit end ++ IBlockData iblockdata = this.level().getBlockState(this.portalEntrancePos); ++ Direction.Axis enumdirection_enumaxis; ++ Vec3 vec3d; ++ ++ if (iblockdata.hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) { ++ enumdirection_enumaxis = (Direction.Axis) iblockdata.getValue(BlockStateProperties.HORIZONTAL_AXIS); ++ BlockUtil.FoundRectangle blockutil_rectangle1 = BlockUtil.getLargestRectangleAround(this.portalEntrancePos, enumdirection_enumaxis, 21, Direction.Axis.Y, 21, (blockposition1) -> { ++ return this.level().getBlockState(blockposition1) == iblockdata; ++ }); ++ ++ vec3d = this.getRelativePortalPosition(enumdirection_enumaxis, blockutil_rectangle1); ++ } else { ++ enumdirection_enumaxis = Direction.Axis.X; ++ vec3d = new Vec3(0.5D, 0.0D, 0.0D); ++ } ++ ++ return PortalShape.createPortalInfo(worldserverFinal, blockutil_rectangle, enumdirection_enumaxis, vec3d, this, this.getDeltaMovement(), this.getYRot(), this.getXRot(), event); // CraftBukkit ++ }).orElse(null); // CraftBukkit - decompile error + } + } else { + BlockPos blockPos; +@@ -2568,13 +3126,14 @@ + } else { + blockPos = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSharedSpawnPos()); + } ++ // CraftBukkit start ++ CraftPortalEvent event = callPortalEvent(this, destination, new Vec3(blockposition1.getX() + 0.5D, blockposition1.getY(), blockposition1.getZ() + 0.5D), PlayerTeleportEvent.TeleportCause.END_PORTAL, 0, 0); ++ if (event == null) { ++ return null; ++ } + +- return new PortalInfo( +- new Vec3((double)blockPos.getX() + 0.5, (double)blockPos.getY(), (double)blockPos.getZ() + 0.5), +- this.getDeltaMovement(), +- this.getYRot(), +- this.getXRot() +- ); ++ return new PortalInfo(new Vec3(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()), this.getDeltaMovement(), this.getYRot(), this.getXRot(), ((CraftWorld) event.getTo().getWorld()).getHandle(), event); ++ // CraftBukkit end + } + } + +@@ -2582,10 +3141,25 @@ + return PortalShape.getRelativePosition(portal, axis, this.position(), this.getDimensions(this.getPose())); + } + +- protected Optional getExitPortal(ServerLevel destination, BlockPos findFrom, boolean isToNether, WorldBorder worldBorder) { +- return destination.getPortalForcer().findPortalAround(findFrom, isToNether, worldBorder); ++ // CraftBukkit start ++ protected CraftPortalEvent callPortalEvent(Entity entity, ServerLevel exitWorldServer, Vec3 exitPosition, PlayerTeleportEvent.TeleportCause cause, int searchRadius, int creationRadius) { ++ org.bukkit.entity.Entity bukkitEntity = entity.getBukkitEntity(); ++ Location enter = bukkitEntity.getLocation(); ++ Location exit = CraftLocation.toBukkit(exitPosition, exitWorldServer.getWorld()); ++ ++ EntityPortalEvent event = new EntityPortalEvent(bukkitEntity, enter, exit, searchRadius); ++ event.getEntity().getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null || !entity.isAlive()) { ++ return null; ++ } ++ return new CraftPortalEvent(event); + } + ++ protected Optional getExitPortal(ServerLevel worldserver, BlockPos blockposition, boolean flag, WorldBorder worldborder, int searchRadius, boolean canCreatePortal, int createRadius) { ++ return worldserver.getPortalForcer().findPortalAround(blockposition, worldborder, searchRadius); ++ // CraftBukkit end ++ } ++ + public boolean canChangeDimensions() { + return !this.isPassenger() && !this.isVehicle(); + } +@@ -2695,8 +3278,15 @@ + } + } + +- public boolean teleportTo(ServerLevel level, double x, double y, double z, Set relativeMovements, float yRot, float xRot) { +- float f = Mth.clamp(xRot, -90.0F, 90.0F); ++ // CraftBukkit start ++ public boolean teleportTo(ServerLevel worldserver, double d0, double d1, double d2, Set set, float f, float f1, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { ++ return this.teleportTo(worldserver, d0, d1, d2, set, f, f1); ++ } ++ // CraftBukkit end ++ ++ public boolean teleportTo(ServerLevel level, double x, double d1, double y, Set set, float z, float f1) { ++ float f2 = Mth.clamp(f1, -90.0F, 90.0F); ++ + if (level == this.level()) { + this.moveTo(x, y, z, yRot, f); + this.teleportPassengers(); +@@ -2712,7 +3303,11 @@ + entity.moveTo(x, y, z, yRot, f); + entity.setYHeadRot(yRot); + this.setRemoved(Entity.RemovalReason.CHANGED_DIMENSION); +- level.addDuringTeleport(entity); ++ // CraftBukkit start - Don't spawn the new entity if the current entity isn't spawned ++ if (inWorld) { ++ level.addDuringTeleport(entity); ++ } ++ // CraftBukkit end + } + + return true; +@@ -2812,7 +3413,26 @@ + } + + public final void setBoundingBox(AABB bb) { +- this.bb = bb; ++ // CraftBukkit start - block invalid bounding boxes ++ double minX = bb.minX, ++ minY = bb.minY, ++ minZ = bb.minZ, ++ maxX = bb.maxX, ++ maxY = bb.maxY, ++ maxZ = bb.maxZ; ++ double len = bb.maxX - bb.minX; ++ if (len < 0) maxX = minX; ++ if (len > 64) maxX = minX + 64.0; ++ ++ len = bb.maxY - bb.minY; ++ if (len < 0) maxY = minY; ++ if (len > 64) maxY = minY + 64.0; ++ ++ len = bb.maxZ - bb.minZ; ++ if (len < 0) maxZ = minZ; ++ if (len > 64) maxZ = minZ + 64.0; ++ this.bb = new AABB(minX, minY, minZ, maxX, maxY, maxZ); ++ // CraftBukkit end + } + + protected float getEyeHeight(Pose pose, EntityDimensions dimensions) { +@@ -3114,6 +3747,11 @@ + vec3 = vec3.add(flow); + i++; + } ++ // CraftBukkit start - store last lava contact location ++ if (fluidTag == FluidTags.LAVA) { ++ this.lastLavaContact = blockposition_mutableblockposition.immutable(); ++ } ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/EntitySelector.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/EntitySelector.java.patch new file mode 100644 index 0000000000..e03a629440 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/EntitySelector.java.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/world/entity/EntitySelector.java ++++ b/net/minecraft/world/entity/EntitySelector.java +@@ -27,27 +40,24 @@ + } + + public static Predicate pushableBy(Entity entity) { +- Team team = entity.getTeam(); +- Team.CollisionRule collisionRule = team == null ? Team.CollisionRule.ALWAYS : team.getCollisionRule(); +- return (Predicate)(collisionRule == Team.CollisionRule.NEVER +- ? Predicates.alwaysFalse() +- : NO_SPECTATORS.and( +- pushedEntity -> { +- if (!pushedEntity.isPushable()) { +- return false; +- } else if (!entity.level().isClientSide || pushedEntity instanceof Player && ((Player)pushedEntity).isLocalPlayer()) { +- Team team1 = pushedEntity.getTeam(); +- Team.CollisionRule collisionRule1 = team1 == null ? Team.CollisionRule.ALWAYS : team1.getCollisionRule(); +- if (collisionRule1 == Team.CollisionRule.NEVER) { +- return false; +- } else { +- boolean flag = team != null && team.isAlliedTo(team1); +- return (collisionRule != Team.CollisionRule.PUSH_OWN_TEAM && collisionRule1 != Team.CollisionRule.PUSH_OWN_TEAM || !flag) +- && (collisionRule != Team.CollisionRule.PUSH_OTHER_TEAMS && collisionRule1 != Team.CollisionRule.PUSH_OTHER_TEAMS || flag); +- } +- } else { +- return false; +- } ++ PlayerTeam scoreboardteam = entity.getTeam(); ++ Team.CollisionRule scoreboardteambase_enumteampush = scoreboardteam == null ? Team.CollisionRule.ALWAYS : scoreboardteam.getCollisionRule(); ++ ++ return (Predicate) (scoreboardteambase_enumteampush == Team.CollisionRule.NEVER ? Predicates.alwaysFalse() : EntitySelector.NO_SPECTATORS.and((entity1) -> { ++ if (!entity1.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(entity1)) { // CraftBukkit - collidable API ++ return false; ++ } else if (entity.level().isClientSide && (!(entity1 instanceof Player) || !((Player) entity1).isLocalPlayer())) { ++ return false; ++ } else { ++ PlayerTeam scoreboardteam1 = entity1.getTeam(); ++ Team.CollisionRule scoreboardteambase_enumteampush1 = scoreboardteam1 == null ? Team.CollisionRule.ALWAYS : scoreboardteam1.getCollisionRule(); ++ ++ if (scoreboardteambase_enumteampush1 == Team.CollisionRule.NEVER) { ++ return false; ++ } else { ++ boolean flag = scoreboardteam != null && scoreboardteam.isAlliedTo(scoreboardteam1); ++ ++ return (scoreboardteambase_enumteampush == Team.CollisionRule.PUSH_OWN_TEAM || scoreboardteambase_enumteampush1 == Team.CollisionRule.PUSH_OWN_TEAM) && flag ? false : scoreboardteambase_enumteampush != Team.CollisionRule.PUSH_OTHER_TEAMS && scoreboardteambase_enumteampush1 != Team.CollisionRule.PUSH_OTHER_TEAMS || flag; + } + )); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/EntityType.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/EntityType.java.patch new file mode 100644 index 0000000000..21f87b5994 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/EntityType.java.patch @@ -0,0 +1,138 @@ +--- a/net/minecraft/world/entity/EntityType.java ++++ b/net/minecraft/world/entity/EntityType.java +@@ -168,26 +170,11 @@ + private final Holder.Reference> builtInRegistryHolder = BuiltInRegistries.ENTITY_TYPE.createIntrusiveHolder(this); + private static final float MAGIC_HORSE_WIDTH = 1.3964844F; + private static final int DISPLAY_TRACKING_RANGE = 10; +- public static final EntityType ALLAY = register( +- "allay", EntityType.Builder.of(Allay::new, MobCategory.CREATURE).sized(0.35F, 0.6F).clientTrackingRange(8).updateInterval(2) +- ); +- public static final EntityType AREA_EFFECT_CLOUD = register( +- "area_effect_cloud", +- EntityType.Builder.of(AreaEffectCloud::new, MobCategory.MISC) +- .fireImmune() +- .sized(6.0F, 0.5F) +- .clientTrackingRange(10) +- .updateInterval(Integer.MAX_VALUE) +- ); +- public static final EntityType ARMOR_STAND = register( +- "armor_stand", EntityType.Builder.of(ArmorStand::new, MobCategory.MISC).sized(0.5F, 1.975F).clientTrackingRange(10) +- ); +- public static final EntityType ARROW = register( +- "arrow", EntityType.Builder.of(Arrow::new, MobCategory.MISC).sized(0.5F, 0.5F).clientTrackingRange(4).updateInterval(20) +- ); +- public static final EntityType AXOLOTL = register( +- "axolotl", EntityType.Builder.of(Axolotl::new, MobCategory.AXOLOTLS).sized(0.75F, 0.42F).clientTrackingRange(10) +- ); ++ public static final EntityType ALLAY = register("allay", EntityType.Builder.of(Allay::new, MobCategory.CREATURE).sized(0.35F, 0.6F).clientTrackingRange(8).updateInterval(2)); ++ public static final EntityType AREA_EFFECT_CLOUD = register("area_effect_cloud", EntityType.Builder.of(AreaEffectCloud::new, MobCategory.MISC).fireImmune().sized(6.0F, 0.5F).clientTrackingRange(10).updateInterval(10)); // CraftBukkit - SPIGOT-3729: track area effect clouds ++ public static final EntityType ARMOR_STAND = register("armor_stand", EntityType.Builder.of(ArmorStand::new, MobCategory.MISC).sized(0.5F, 1.975F).clientTrackingRange(10)); ++ public static final EntityType ARROW = register("arrow", EntityType.Builder.of(Arrow::new, MobCategory.MISC).sized(0.5F, 0.5F).clientTrackingRange(4).updateInterval(20)); ++ public static final EntityType AXOLOTL = register("axolotl", EntityType.Builder.of(Axolotl::new, MobCategory.AXOLOTLS).sized(0.75F, 0.42F).clientTrackingRange(10)); + public static final EntityType BAT = register("bat", EntityType.Builder.of(Bat::new, MobCategory.AMBIENT).sized(0.5F, 0.9F).clientTrackingRange(5)); + public static final EntityType BEE = register("bee", EntityType.Builder.of(Bee::new, MobCategory.CREATURE).sized(0.7F, 0.6F).clientTrackingRange(8)); + public static final EntityType BLAZE = register( +@@ -627,27 +342,27 @@ + } + + @Nullable +- public T spawn( +- ServerLevel serverLevel, +- @Nullable ItemStack stack, +- @Nullable Player player, +- BlockPos pos, +- MobSpawnType spawnType, +- boolean shouldOffsetY, +- boolean shouldOffsetYMore +- ) { +- Consumer consumer; +- CompoundTag tag; +- if (stack != null) { +- tag = stack.getTag(); +- consumer = createDefaultStackConfig(serverLevel, stack, player); ++ public T spawn(ServerLevel serverLevel, @Nullable ItemStack stack, @Nullable Player player, BlockPos pos, EnumMobSpawn spawnType, boolean shouldOffsetY, boolean shouldOffsetYMore) { ++ // CraftBukkit start ++ return this.spawn(serverLevel, stack, player, pos, spawnType, shouldOffsetY, shouldOffsetYMore, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG); ++ } ++ ++ @Nullable ++ public T spawn(ServerLevel worldserver, @Nullable ItemStack itemstack, @Nullable Player entityhuman, BlockPos blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end ++ CompoundTag nbttagcompound; ++ Consumer consumer; // CraftBukkit - decompile error ++ ++ if (itemstack != null) { ++ nbttagcompound = itemstack.getTag(); ++ consumer = createDefaultStackConfig(worldserver, itemstack, entityhuman); + } else { + consumer = entity -> { + }; + tag = null; + } + +- return this.spawn(serverLevel, tag, consumer, pos, spawnType, shouldOffsetY, shouldOffsetYMore); ++ return this.spawn(worldserver, nbttagcompound, consumer, blockposition, enummobspawn, flag, flag1, spawnReason); // CraftBukkit + } + + public static Consumer createDefaultStackConfig(ServerLevel serverLevel, ItemStack stack, @Nullable Player player) { +@@ -665,31 +380,41 @@ + return stack.hasCustomHoverName() ? consumer.andThen(entity -> entity.setCustomName(stack.getHoverName())) : consumer; + } + +- public static Consumer appendCustomEntityStackConfig( +- Consumer consumer, ServerLevel level, ItemStack stack, @Nullable Player player +- ) { +- CompoundTag tag = stack.getTag(); +- return tag != null ? consumer.andThen(spawnedEntity -> updateCustomEntityTag(level, player, spawnedEntity, tag)) : consumer; ++ public static Consumer appendCustomEntityStackConfig(Consumer consumer, ServerLevel level, ItemStack stack, @Nullable Player player) { ++ CompoundTag nbttagcompound = stack.getTag(); ++ ++ return nbttagcompound != null ? consumer.andThen((entity) -> { ++ try { updateCustomEntityTag(level, player, entity, nbttagcompound); } catch (Throwable t) { LOGGER.warn("Error loading spawn egg NBT", t); } // CraftBukkit - SPIGOT-5665 ++ }) : consumer; + } + + @Nullable +- public T spawn(ServerLevel level, BlockPos pos, MobSpawnType spawnType) { +- return this.spawn(level, (CompoundTag)null, null, pos, spawnType, false, false); ++ public T spawn(ServerLevel level, BlockPos pos, EnumMobSpawn spawnType) { ++ // CraftBukkit start ++ return this.spawn(level, pos, spawnType, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); + } + + @Nullable +- public T spawn( +- ServerLevel level, +- @Nullable CompoundTag compound, +- @Nullable Consumer consumer, +- BlockPos pos, +- MobSpawnType spawnType, +- boolean shouldOffsetY, +- boolean shouldOffsetYMore +- ) { +- T entity = this.create(level, compound, consumer, pos, spawnType, shouldOffsetY, shouldOffsetYMore); +- if (entity != null) { +- level.addFreshEntityWithPassengers(entity); ++ public T spawn(ServerLevel worldserver, BlockPos blockposition, EnumMobSpawn enummobspawn, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ return this.spawn(worldserver, (CompoundTag) null, null, blockposition, enummobspawn, false, false, spawnReason); // CraftBukkit - decompile error ++ // CraftBukkit end ++ } ++ ++ @Nullable ++ public T spawn(ServerLevel level, @Nullable CompoundTag compound, @Nullable Consumer consumer, BlockPos pos, EnumMobSpawn spawnType, boolean shouldOffsetY, boolean shouldOffsetYMore) { ++ // CraftBukkit start ++ return this.spawn(level, compound, consumer, pos, spawnType, shouldOffsetY, shouldOffsetYMore, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ @Nullable ++ public T spawn(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Consumer consumer, BlockPos blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end ++ T t0 = this.create(worldserver, nbttagcompound, consumer, blockposition, enummobspawn, flag, flag1); ++ ++ if (t0 != null) { ++ worldserver.addFreshEntityWithPassengers(t0, spawnReason); ++ return !t0.isRemoved() ? t0 : null; // Don't return an entity when CreatureSpawnEvent is canceled ++ // CraftBukkit end + } + + return entity; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ExperienceOrb.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ExperienceOrb.java.patch new file mode 100644 index 0000000000..c1c9baa94c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ExperienceOrb.java.patch @@ -0,0 +1,161 @@ +--- a/net/minecraft/world/entity/ExperienceOrb.java ++++ b/net/minecraft/world/entity/ExperienceOrb.java +@@ -19,6 +20,12 @@ + import net.minecraft.world.level.entity.EntityTypeTest; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.player.PlayerExpCooldownChangeEvent; ++// CraftBukkit end + + public class ExperienceOrb extends Entity { + private static final int LIFETIME = 6000; +@@ -58,6 +65,7 @@ + @Override + public void tick() { + super.tick(); ++ Player prevTarget = this.followingPlayer;// CraftBukkit - store old target + this.xo = this.getX(); + this.yo = this.getY(); + this.zo = this.getZ(); +@@ -87,20 +91,33 @@ + this.followingPlayer = null; + } + +- if (this.followingPlayer != null) { +- Vec3 vec3 = new Vec3( +- this.followingPlayer.getX() - this.getX(), +- this.followingPlayer.getY() + (double)this.followingPlayer.getEyeHeight() / 2.0 - this.getY(), +- this.followingPlayer.getZ() - this.getZ() +- ); +- double d = vec3.lengthSqr(); +- if (d < 64.0) { +- double d1 = 1.0 - Math.sqrt(d) / 8.0; +- this.setDeltaMovement(this.getDeltaMovement().add(vec3.normalize().scale(d1 * d1 * 0.1))); ++ // CraftBukkit start ++ boolean cancelled = false; ++ if (this.followingPlayer != prevTarget) { ++ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(this, followingPlayer, (followingPlayer != null) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.FORGOT_TARGET); ++ LivingEntity target = (event.getTarget() == null) ? null : ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getTarget()).getHandle(); ++ cancelled = event.isCancelled(); ++ ++ if (cancelled) { ++ followingPlayer = prevTarget; ++ } else { ++ followingPlayer = (target instanceof Player) ? (Player) target : null; + } + } + +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ if (this.followingPlayer != null && !cancelled) { ++ // CraftBukkit end ++ Vec3 vec3d = new Vec3(this.followingPlayer.getX() - this.getX(), this.followingPlayer.getY() + (double) this.followingPlayer.getEyeHeight() / 2.0D - this.getY(), this.followingPlayer.getZ() - this.getZ()); ++ double d0 = vec3d.lengthSqr(); ++ ++ if (d0 < 64.0D) { ++ double d1 = 1.0D - Math.sqrt(d0) / 8.0D; ++ ++ this.setDeltaMovement(this.getDeltaMovement().add(vec3d.normalize().scale(d1 * d1 * 0.1D))); ++ } ++ } ++ ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + float f = 0.98F; + if (this.onGround()) { + f = this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getFriction() * 0.98F; +@@ -219,11 +249,11 @@ + public void playerTouch(Player entity) { + if (!this.level().isClientSide) { + if (entity.takeXpDelay == 0) { +- entity.takeXpDelay = 2; ++ entity.takeXpDelay = CraftEventFactory.callPlayerXpCooldownEvent(entity, 2, PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2; + entity.take(this, 1); + int i = this.repairPlayerItems(entity, this.value); + if (i > 0) { +- entity.giveExperiencePoints(i); ++ entity.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(entity, i).getAmount()); // CraftBukkit - this.value -> event.getAmount() + } + + this.count--; +@@ -235,13 +267,24 @@ + } + + private int repairPlayerItems(Player player, int repairAmount) { +- Entry randomItemWith = EnchantmentHelper.getRandomItemWith(Enchantments.MENDING, player, ItemStack::isDamaged); +- if (randomItemWith != null) { +- ItemStack itemStack = randomItemWith.getValue(); +- int min = Math.min(this.xpToDurability(repairAmount), itemStack.getDamageValue()); +- itemStack.setDamageValue(itemStack.getDamageValue() - min); +- int i = repairAmount - this.durabilityToXp(min); +- return i > 0 ? this.repairPlayerItems(player, i) : 0; ++ Entry entry = EnchantmentHelper.getRandomItemWith(Enchantments.MENDING, player, ItemStack::isDamaged); ++ ++ if (entry != null) { ++ ItemStack itemstack = (ItemStack) entry.getValue(); ++ int j = Math.min(this.xpToDurability(repairAmount), itemstack.getDamageValue()); ++ // CraftBukkit start ++ org.bukkit.event.player.PlayerItemMendEvent event = CraftEventFactory.callPlayerItemMendEvent(player, this, itemstack, entry.getKey(), j); ++ j = event.getRepairAmount(); ++ if (event.isCancelled()) { ++ return repairAmount; ++ } ++ // CraftBukkit end ++ ++ itemstack.setDamageValue(itemstack.getDamageValue() - j); ++ int k = repairAmount - this.durabilityToXp(j); ++ this.value = k; // CraftBukkit - update exp value of orb for PlayerItemMendEvent calls ++ ++ return k > 0 ? this.repairPlayerItems(player, k) : 0; + } else { + return repairAmount; + } +@@ -284,27 +307,25 @@ + } + + public static int getExperienceValue(int expValue) { +- if (expValue >= 2477) { +- return 2477; +- } else if (expValue >= 1237) { +- return 1237; +- } else if (expValue >= 617) { +- return 617; +- } else if (expValue >= 307) { +- return 307; +- } else if (expValue >= 149) { +- return 149; +- } else if (expValue >= 73) { +- return 73; +- } else if (expValue >= 37) { +- return 37; +- } else if (expValue >= 17) { +- return 17; +- } else if (expValue >= 7) { +- return 7; +- } else { +- return expValue >= 3 ? 3 : 1; +- } ++ // CraftBukkit start ++ if (expValue > 162670129) return expValue - 100000; ++ if (expValue > 81335063) return 81335063; ++ if (expValue > 40667527) return 40667527; ++ if (expValue > 20333759) return 20333759; ++ if (expValue > 10166857) return 10166857; ++ if (expValue > 5083423) return 5083423; ++ if (expValue > 2541701) return 2541701; ++ if (expValue > 1270849) return 1270849; ++ if (expValue > 635413) return 635413; ++ if (expValue > 317701) return 317701; ++ if (expValue > 158849) return 158849; ++ if (expValue > 79423) return 79423; ++ if (expValue > 39709) return 39709; ++ if (expValue > 19853) return 19853; ++ if (expValue > 9923) return 9923; ++ if (expValue > 4957) return 4957; ++ // CraftBukkit end ++ return expValue >= 2477 ? 2477 : (expValue >= 1237 ? 1237 : (expValue >= 617 ? 617 : (expValue >= 307 ? 307 : (expValue >= 149 ? 149 : (expValue >= 73 ? 73 : (expValue >= 37 ? 37 : (expValue >= 17 ? 17 : (expValue >= 7 ? 7 : (expValue >= 3 ? 3 : 1))))))))); + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/Interaction.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/Interaction.java.patch new file mode 100644 index 0000000000..c03fcd8095 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/Interaction.java.patch @@ -0,0 +1,44 @@ +--- a/net/minecraft/world/entity/Interaction.java ++++ b/net/minecraft/world/entity/Interaction.java +@@ -25,6 +23,13 @@ + import net.minecraft.world.phys.AABB; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.world.damagesource.DamageSource; ++import net.minecraft.world.entity.player.Player; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityDamageEvent; ++// CraftBukkit end ++ + public class Interaction extends Entity implements Attackable, Targeting { + private static final Logger LOGGER = LogUtils.getLogger(); + private static final EntityDataAccessor DATA_WIDTH_ID = SynchedEntityData.defineId(Interaction.class, EntityDataSerializers.FLOAT); +@@ -129,12 +147,23 @@ + + @Override + public boolean skipAttackInteraction(Entity entity) { +- if (entity instanceof Player player) { +- this.attack = new Interaction.PlayerAction(player.getUUID(), this.level().getGameTime()); +- if (player instanceof ServerPlayer serverPlayer) { +- CriteriaTriggers.PLAYER_HURT_ENTITY.trigger(serverPlayer, this, player.damageSources().generic(), 1.0F, 1.0F, false); ++ if (entity instanceof Player) { ++ Player entityhuman = (Player) entity; ++ // CraftBukkit start ++ DamageSource source = entityhuman.damageSources().playerAttack(entityhuman); ++ EntityDamageEvent event = CraftEventFactory.callNonLivingEntityDamageEvent(this, source, 1.0F, false); ++ if (event.isCancelled()) { ++ return true; + } ++ // CraftBukkit end + ++ this.attack = new Interaction.PlayerAction(entityhuman.getUUID(), this.level().getGameTime()); ++ if (entityhuman instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entityhuman; ++ ++ CriteriaTriggers.PLAYER_HURT_ENTITY.trigger(entityplayer, this, source, (float) event.getFinalDamage(), 1.0F, false); // CraftBukkit ++ } ++ + return !this.getResponse(); + } else { + return false; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ItemBasedSteering.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ItemBasedSteering.java.patch new file mode 100644 index 0000000000..85f6fe1e3c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ItemBasedSteering.java.patch @@ -0,0 +1,17 @@ +--- a/net/minecraft/world/entity/ItemBasedSteering.java ++++ b/net/minecraft/world/entity/ItemBasedSteering.java +@@ -51,6 +53,14 @@ + return this.entityData.get(this.boostTimeAccessor); + } + ++ // CraftBukkit add setBoostTicks(int) ++ public void setBoostTicks(int ticks) { ++ this.boosting = true; ++ this.boostTime = 0; ++ this.entityData.set(this.boostTimeAccessor, ticks); ++ } ++ // CraftBukkit end ++ + public void addAdditionalSaveData(CompoundTag nbt) { + nbt.putBoolean("Saddle", this.hasSaddle()); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/LightningBolt.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/LightningBolt.java.patch new file mode 100644 index 0000000000..6c5a520ade --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/LightningBolt.java.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/entity/LightningBolt.java ++++ b/net/minecraft/world/entity/LightningBolt.java +@@ -24,6 +28,9 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class LightningBolt extends Entity { + private static final int START_LIFE = 2; +@@ -138,7 +132,7 @@ + } + } + +- if (this.life >= 0) { ++ if (this.life >= 0 && !this.visualOnly) { // CraftBukkit - add !this.visualOnly + if (!(this.level() instanceof ServerLevel)) { + this.level().setSkyFlashTime(2); + } else if (!this.visualOnly) { +@@ -168,19 +162,29 @@ + + private void spawnFire(int extraIgnitions) { + if (!this.visualOnly && !this.level().isClientSide && this.level().getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) { +- BlockPos blockPos = this.blockPosition(); +- BlockState state = BaseFireBlock.getState(this.level(), blockPos); +- if (this.level().getBlockState(blockPos).isAir() && state.canSurvive(this.level(), blockPos)) { +- this.level().setBlockAndUpdate(blockPos, state); +- this.blocksSetOnFire++; ++ BlockPos blockposition = this.blockPosition(); ++ IBlockData iblockdata = BaseFireBlock.getState(this.level(), blockposition); ++ ++ if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) { ++ // CraftBukkit start - add "!visualOnly" ++ if (!visualOnly && !CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition, this).isCancelled()) { ++ this.level().setBlockAndUpdate(blockposition, iblockdata); ++ ++this.blocksSetOnFire; ++ } ++ // CraftBukkit end + } + +- for (int i = 0; i < extraIgnitions; i++) { +- BlockPos blockPos1 = blockPos.offset(this.random.nextInt(3) - 1, this.random.nextInt(3) - 1, this.random.nextInt(3) - 1); +- state = BaseFireBlock.getState(this.level(), blockPos1); +- if (this.level().getBlockState(blockPos1).isAir() && state.canSurvive(this.level(), blockPos1)) { +- this.level().setBlockAndUpdate(blockPos1, state); +- this.blocksSetOnFire++; ++ for (int j = 0; j < extraIgnitions; ++j) { ++ BlockPos blockposition1 = blockposition.offset(this.random.nextInt(3) - 1, this.random.nextInt(3) - 1, this.random.nextInt(3) - 1); ++ ++ iblockdata = BaseFireBlock.getState(this.level(), blockposition1); ++ if (this.level().getBlockState(blockposition1).isAir() && iblockdata.canSurvive(this.level(), blockposition1)) { ++ // CraftBukkit start - add "!visualOnly" ++ if (!visualOnly && !CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition1, this).isCancelled()) { ++ this.level().setBlockAndUpdate(blockposition1, iblockdata); ++ ++this.blocksSetOnFire; ++ } ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/LivingEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/LivingEntity.java.patch new file mode 100644 index 0000000000..f09edaaa57 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/LivingEntity.java.patch @@ -0,0 +1,1095 @@ +--- a/net/minecraft/world/entity/LivingEntity.java ++++ b/net/minecraft/world/entity/LivingEntity.java +@@ -119,6 +120,26 @@ + import net.minecraft.world.scores.PlayerTeam; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.HashSet; ++import java.util.Set; ++import com.google.common.base.Function; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.attribute.CraftAttributeMap; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.Player; ++import org.bukkit.event.entity.ArrowBodyCountChangeEvent; ++import org.bukkit.event.entity.EntityDamageEvent; ++import org.bukkit.event.entity.EntityDamageEvent.DamageModifier; ++import org.bukkit.event.entity.EntityPotionEffectEvent; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++import org.bukkit.event.entity.EntityResurrectEvent; ++import org.bukkit.event.entity.EntityTeleportEvent; ++import org.bukkit.event.player.PlayerItemConsumeEvent; ++// CraftBukkit end ++ + public abstract class LivingEntity extends Entity implements Attackable { + private static final Logger LOGGER = LogUtils.getLogger(); + private static final String TAG_ACTIVE_EFFECTS = "active_effects"; +@@ -229,11 +247,27 @@ + private float swimAmountO; + protected Brain brain; + private boolean skipDropExperience; ++ // CraftBukkit start ++ public int expToDrop; ++ public boolean forceDrops; ++ public ArrayList drops = new ArrayList(); ++ public final org.bukkit.craftbukkit.attribute.CraftAttributeMap craftAttributes; ++ public boolean collides = true; ++ public Set collidableExemptions = new HashSet<>(); ++ public boolean bukkitPickUpLoot; + ++ @Override ++ public float getBukkitYaw() { ++ return getYHeadRot(); ++ } ++ // CraftBukkit end ++ + protected LivingEntity(EntityType entityType, Level level) { + super(entityType, level); + this.attributes = new AttributeMap(DefaultAttributes.getSupplier(entityType)); +- this.setHealth(this.getMaxHealth()); ++ this.craftAttributes = new CraftAttributeMap(attributes); // CraftBukkit ++ // CraftBukkit - setHealth(getMaxHealth()) inlined and simplified to skip the instanceof check for EntityPlayer, as getBukkitEntity() is not initialized in constructor ++ this.entityData.set(LivingEntity.DATA_HEALTH_ID, (float) this.getAttribute(Attributes.MAX_HEALTH).getValue()); + this.blocksBuilding = true; + this.rotA = (float)((Math.random() + 1.0) * 0.01F); + this.reapplyPosition(); +@@ -311,10 +350,17 @@ + z = (double)pos.getZ() + 0.5 + d1 / max * 0.5; + } + +- float f = (float)Mth.ceil(this.fallDistance - 3.0F); +- double min = Math.min((double)(0.2F + f / 15.0F), 2.5); +- int i = (int)(150.0 * min); +- ((ServerLevel)this.level()).sendParticles(new BlockParticleOption(ParticleTypes.BLOCK, state), x, y1, z, i, 0.0, 0.0, 0.0, 0.15F); ++ float f = (float) Mth.ceil(this.fallDistance - 3.0F); ++ double d7 = Math.min((double) (0.2F + f / 15.0F), 2.5D); ++ int i = (int) (150.0D * d7); ++ ++ // CraftBukkit start - visiblity api ++ if (this instanceof ServerPlayer) { ++ ((ServerLevel) this.level()).sendParticles((ServerPlayer) this, new BlockParticleOption(ParticleTypes.BLOCK, onGround), this.getX(), this.getY(), this.getZ(), i, 0.0D, 0.0D, 0.0D, 0.15000000596046448D, false); ++ } else { ++ ((ServerLevel) this.level()).sendParticles(new BlockParticleOption(ParticleTypes.BLOCK, onGround), d1, d2, d3, i, 0.0D, 0.0D, 0.0D, 0.15000000596046448D); ++ } ++ // CraftBukkit end + } + + super.checkFallDamage(y, onGround, state, pos); +@@ -678,12 +715,20 @@ + } + + public void onEquipItem(EquipmentSlot slot, ItemStack oldItem, ItemStack newItem) { +- boolean flag = newItem.isEmpty() && oldItem.isEmpty(); +- if (!flag && !ItemStack.isSameItemSameTags(oldItem, newItem) && !this.firstTick) { +- Equipable equipable = Equipable.get(newItem); ++ // CraftBukkit start ++ onEquipItem(slot, oldItem, newItem, false); ++ } ++ ++ public void onEquipItem(EquipmentSlot enumitemslot, ItemStack itemstack, ItemStack itemstack1, boolean silent) { ++ // CraftBukkit end ++ boolean flag = itemstack1.isEmpty() && itemstack.isEmpty(); ++ ++ if (!flag && !ItemStack.isSameItemSameTags(itemstack, itemstack1) && !this.firstTick) { ++ Equipable equipable = Equipable.get(itemstack1); ++ + if (!this.level().isClientSide() && !this.isSpectator()) { +- if (!this.isSilent() && equipable != null && equipable.getEquipmentSlot() == slot) { +- this.level().playSound(null, this.getX(), this.getY(), this.getZ(), equipable.getEquipSound(), this.getSoundSource(), 1.0F, 1.0F); ++ if (!this.isSilent() && equipable != null && equipable.getEquipmentSlot() == enumitemslot && !silent) { // CraftBukkit ++ this.level().playSound((net.minecraft.world.entity.player.Player) null, this.getX(), this.getY(), this.getZ(), equipable.getEquipSound(), this.getSoundSource(), 1.0F, 1.0F); + } + + if (this.doesEmitEquipEvent(slot)) { +@@ -746,6 +801,17 @@ + } + } + ++ // CraftBukkit start ++ if (compound.contains("Bukkit.MaxHealth")) { ++ Tag nbtbase = compound.get("Bukkit.MaxHealth"); ++ if (nbtbase.getId() == 5) { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(((FloatTag) nbtbase).getAsDouble()); ++ } else if (nbtbase.getId() == 3) { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(((IntTag) nbtbase).getAsDouble()); ++ } ++ } ++ // CraftBukkit end ++ + if (compound.contains("Health", 99)) { + this.setHealth(compound.getFloat("Health")); + } +@@ -780,15 +849,44 @@ + } + } + ++ // CraftBukkit start ++ private boolean isTickingEffects = false; ++ private List effectsToProcess = Lists.newArrayList(); ++ ++ private static class ProcessableEffect { ++ ++ private MobEffect type; ++ private MobEffectInstance effect; ++ private final EntityPotionEffectEvent.Cause cause; ++ ++ private ProcessableEffect(MobEffectInstance effect, EntityPotionEffectEvent.Cause cause) { ++ this.effect = effect; ++ this.cause = cause; ++ } ++ ++ private ProcessableEffect(MobEffect type, EntityPotionEffectEvent.Cause cause) { ++ this.type = type; ++ this.cause = cause; ++ } ++ } ++ // CraftBukkit end ++ + protected void tickEffects() { + Iterator iterator = this.activeEffects.keySet().iterator(); + ++ isTickingEffects = true; // CraftBukkit + try { + while (iterator.hasNext()) { + MobEffect mobEffect = iterator.next(); + MobEffectInstance mobEffectInstance = this.activeEffects.get(mobEffect); + if (!mobEffectInstance.tick(this, () -> this.onEffectUpdated(mobEffectInstance, true, null))) { + if (!this.level().isClientSide) { ++ // CraftBukkit start ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, mobeffect, null, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.EXPIRATION); ++ if (event.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end + iterator.remove(); + this.onEffectRemoved(mobEffectInstance); + } +@@ -798,6 +900,17 @@ + } + } catch (ConcurrentModificationException var11) { + } ++ // CraftBukkit start ++ isTickingEffects = false; ++ for (ProcessableEffect e : effectsToProcess) { ++ if (e.effect != null) { ++ addEffect(e.effect, e.cause); ++ } else { ++ removeEffect(e.type, e.cause); ++ } ++ } ++ effectsToProcess.clear(); ++ // CraftBukkit end + + if (this.effectsDirty) { + if (!this.level().isClientSide) { +@@ -920,7 +1037,13 @@ + this.entityData.set(DATA_EFFECT_COLOR_ID, 0); + } + ++ // CraftBukkit start + public boolean removeAllEffects() { ++ return removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean removeAllEffects(EntityPotionEffectEvent.Cause cause) { ++ // CraftBukkit end + if (this.level().isClientSide) { + return false; + } else { +@@ -928,7 +1052,14 @@ + + boolean flag; + for (flag = false; iterator.hasNext(); flag = true) { +- this.onEffectRemoved(iterator.next()); ++ // CraftBukkit start ++ MobEffectInstance effect = (MobEffectInstance) iterator.next(); ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, effect, null, cause, EntityPotionEffectEvent.Action.CLEARED); ++ if (event.isCancelled()) { ++ continue; ++ } ++ this.onEffectRemoved(effect); ++ // CraftBukkit end + iterator.remove(); + } + +@@ -957,18 +1088,49 @@ + return this.addEffect(effectInstance, null); + } + ++ // CraftBukkit start ++ public boolean addEffect(MobEffectInstance mobeffect, EntityPotionEffectEvent.Cause cause) { ++ return this.addEffect(mobeffect, (Entity) null, cause); ++ } ++ + public boolean addEffect(MobEffectInstance effectInstance, @Nullable Entity entity) { +- if (!this.canBeAffected(effectInstance)) { ++ return this.addEffect(effectInstance, entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean addEffect(MobEffectInstance mobeffect, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause) { ++ if (isTickingEffects) { ++ effectsToProcess.add(new ProcessableEffect(mobeffect, cause)); ++ return true; ++ } ++ // CraftBukkit end ++ ++ if (!this.canBeAffected(mobeffect)) { + return false; + } else { + MobEffectInstance mobEffectInstance = this.activeEffects.get(effectInstance.getEffect()); + boolean flag = false; +- if (mobEffectInstance == null) { +- this.activeEffects.put(effectInstance.getEffect(), effectInstance); +- this.onEffectAdded(effectInstance, entity); ++ ++ // CraftBukkit start ++ boolean override = false; ++ if (mobeffect1 != null) { ++ override = new MobEffectInstance(mobeffect1).update(mobeffect); ++ } ++ ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, mobeffect1, mobeffect, cause, override); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ ++ if (mobeffect1 == null) { ++ this.activeEffects.put(mobeffect.getEffect(), mobeffect); ++ this.onEffectAdded(mobeffect, entity); + flag = true; +- } else if (mobEffectInstance.update(effectInstance)) { +- this.onEffectUpdated(mobEffectInstance, true, entity); ++ // CraftBukkit start ++ } else if (event.isOverride()) { ++ mobeffect1.update(mobeffect); ++ this.onEffectUpdated(mobeffect1, true, entity); ++ // CraftBukkit end + flag = true; + } + +@@ -1003,15 +1168,22 @@ + return this.getMobType() == MobType.UNDEAD; + } + ++ // CraftBukkit start + @Nullable + public MobEffectInstance removeEffectNoUpdate(@Nullable MobEffect effect) { + return this.activeEffects.remove(effect); + } + + public boolean removeEffect(MobEffect effect) { +- MobEffectInstance mobEffectInstance = this.removeEffectNoUpdate(effect); +- if (mobEffectInstance != null) { +- this.onEffectRemoved(mobEffectInstance); ++ return removeEffect(effect, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean removeEffect(MobEffect mobeffectlist, EntityPotionEffectEvent.Cause cause) { ++ MobEffectInstance mobeffect = this.c(mobeffectlist, cause); ++ // CraftBukkit end ++ ++ if (mobeffect != null) { ++ this.onEffectRemoved(mobeffect); + return true; + } else { + return false; +@@ -1082,19 +1298,55 @@ + } + } + ++ // CraftBukkit start - Delegate so we can handle providing a reason for health being regained + public void heal(float healAmount) { +- float health = this.getHealth(); +- if (health > 0.0F) { +- this.setHealth(health + healAmount); ++ heal(healAmount, EntityRegainHealthEvent.RegainReason.CUSTOM); ++ } ++ ++ public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason) { ++ float f1 = this.getHealth(); ++ ++ if (f1 > 0.0F) { ++ EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason); ++ // Suppress during worldgen ++ if (this.valid) { ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (!event.isCancelled()) { ++ this.setHealth((float) (this.getHealth() + event.getAmount())); ++ } ++ // CraftBukkit end + } + } + + public float getHealth() { +- return this.entityData.get(DATA_HEALTH_ID); ++ // CraftBukkit start - Use unscaled health ++ if (this instanceof ServerPlayer) { ++ return (float) ((ServerPlayer) this).getBukkitEntity().getHealth(); ++ } ++ // CraftBukkit end ++ return (Float) this.entityData.get(LivingEntity.DATA_HEALTH_ID); + } + + public void setHealth(float health) { +- this.entityData.set(DATA_HEALTH_ID, Mth.clamp(health, 0.0F, this.getMaxHealth())); ++ // CraftBukkit start - Handle scaled health ++ if (this instanceof ServerPlayer) { ++ org.bukkit.craftbukkit.entity.CraftPlayer player = ((ServerPlayer) this).getBukkitEntity(); ++ // Squeeze ++ if (health < 0.0F) { ++ player.setRealHealth(0.0D); ++ } else if (health > player.getMaxHealth()) { ++ player.setRealHealth(player.getMaxHealth()); ++ } else { ++ player.setRealHealth(health); ++ } ++ ++ player.updateScaledHealth(false); ++ return; ++ } ++ // CraftBukkit end ++ this.entityData.set(LivingEntity.DATA_HEALTH_ID, Mth.clamp(health, 0.0F, this.getMaxHealth())); + } + + public boolean isDeadOrDying() { +@@ -1107,7 +1360,7 @@ + return false; + } else if (this.level().isClientSide) { + return false; +- } else if (this.isDeadOrDying()) { ++ } else if (this.isRemoved() || this.dead || this.getHealth() <= 0.0F) { // CraftBukkit - Don't allow entities that got set to dead/killed elsewhere to get damaged and die + return false; + } else if (source.is(DamageTypeTags.IS_FIRE) && this.hasEffect(MobEffects.FIRE_RESISTANCE)) { + return false; +@@ -1117,10 +1370,12 @@ + } + + this.noActionTime = 0; +- float f = amount; +- boolean flag = false; +- float f1 = 0.0F; +- if (amount > 0.0F && this.isDamageSourceBlocked(source)) { ++ float f1 = amount; ++ boolean flag = amount > 0.0F && this.isDamageSourceBlocked(source); // Copied from below ++ float f2 = 0.0F; ++ ++ // CraftBukkit - Moved into damageEntity0(DamageSource, float) ++ if (false && amount > 0.0F && this.isDamageSourceBlocked(source)) { + this.hurtCurrentlyUsedShield(amount); + f1 = amount; + amount = 0.0F; +@@ -1137,23 +1398,34 @@ + + this.walkAnimation.setSpeed(1.5F); + boolean flag1 = true; +- if ((float)this.invulnerableTime > 10.0F && !source.is(DamageTypeTags.BYPASSES_COOLDOWN)) { ++ ++ if ((float) this.invulnerableTime > (float) this.invulnerableDuration / 2.0F && !source.is(DamageTypeTags.BYPASSES_COOLDOWN)) { // CraftBukkit - restore use of maxNoDamageTicks + if (amount <= this.lastHurt) { + return false; + } + +- this.actuallyHurt(source, amount - this.lastHurt); ++ // CraftBukkit start ++ if (!this.damageEntity0(source, amount - this.lastHurt)) { ++ return false; ++ } ++ // CraftBukkit end + this.lastHurt = amount; + flag1 = false; + } else { ++ // CraftBukkit start ++ if (!this.damageEntity0(source, amount)) { ++ return false; ++ } + this.lastHurt = amount; +- this.invulnerableTime = 20; +- this.actuallyHurt(source, amount); ++ this.invulnerableTime = this.invulnerableDuration; // CraftBukkit - restore use of maxNoDamageTicks ++ // this.damageEntity0(damagesource, f); ++ // CraftBukkit end + this.hurtDuration = 10; + this.hurtTime = this.hurtDuration; + } + +- if (source.is(DamageTypeTags.DAMAGES_HELMET) && !this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { ++ // CraftBukkit - Moved into damageEntity0(DamageSource, float) ++ if (false && source.is(DamageTypeTags.DAMAGES_HELMET) && !this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { + this.hurtHelmet(source, amount); + amount *= 0.75F; + } +@@ -1251,28 +1543,47 @@ + } else { + ItemStack itemStack = null; + +- for (InteractionHand interactionHand : InteractionHand.values()) { +- ItemStack itemInHand = this.getItemInHand(interactionHand); +- if (itemInHand.is(Items.TOTEM_OF_UNDYING)) { +- itemStack = itemInHand.copy(); +- itemInHand.shrink(1); ++ // CraftBukkit start ++ EnumHand hand = null; ++ ItemStack itemstack1 = ItemStack.EMPTY; ++ for (int j = 0; j < i; ++j) { ++ EnumHand enumhand = aenumhand[j]; ++ itemstack1 = this.getItemInHand(enumhand); ++ ++ if (itemstack1.is(Items.TOTEM_OF_UNDYING)) { ++ hand = enumhand; // CraftBukkit ++ itemstack = itemstack1.copy(); ++ // itemstack1.subtract(1); // CraftBukkit + break; + } + } + +- if (itemStack != null) { +- if (this instanceof ServerPlayer serverPlayer) { +- serverPlayer.awardStat(Stats.ITEM_USED.get(Items.TOTEM_OF_UNDYING)); +- CriteriaTriggers.USED_TOTEM.trigger(serverPlayer, itemStack); ++ org.bukkit.inventory.EquipmentSlot handSlot = (hand != null) ? org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand) : null; ++ EntityResurrectEvent event = new EntityResurrectEvent((org.bukkit.entity.LivingEntity) this.getBukkitEntity(), handSlot); ++ event.setCancelled(itemstack == null); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ if (!itemstack1.isEmpty()) { ++ itemstack1.shrink(1); ++ } ++ if (itemstack != null && this instanceof ServerPlayer) { ++ // CraftBukkit end ++ ServerPlayer entityplayer = (ServerPlayer) this; ++ ++ entityplayer.awardStat(Stats.ITEM_USED.get(Items.TOTEM_OF_UNDYING)); ++ CriteriaTriggers.USED_TOTEM.trigger(entityplayer, itemstack); + this.gameEvent(GameEvent.ITEM_INTERACT_FINISH); + } + + this.setHealth(1.0F); +- this.removeAllEffects(); +- this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 900, 1)); +- this.addEffect(new MobEffectInstance(MobEffects.ABSORPTION, 100, 1)); +- this.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 800, 0)); +- this.level().broadcastEntityEvent(this, (byte)35); ++ // CraftBukkit start ++ this.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 900, 1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ this.addEffect(new MobEffectInstance(MobEffects.ABSORPTION, 100, 1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ this.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 800, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ // CraftBukkit end ++ this.level().broadcastEntityEvent(this, (byte) 35); + } + + return itemStack != null; +@@ -1372,17 +1689,27 @@ + boolean flag = false; + if (entitySource instanceof WitherBoss) { + if (this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- BlockPos blockPos = this.blockPosition(); +- BlockState blockState = Blocks.WITHER_ROSE.defaultBlockState(); +- if (this.level().getBlockState(blockPos).isAir() && blockState.canSurvive(this.level(), blockPos)) { +- this.level().setBlock(blockPos, blockState, 3); +- flag = true; ++ BlockPos blockposition = this.blockPosition(); ++ IBlockData iblockdata = Blocks.WITHER_ROSE.defaultBlockState(); ++ ++ if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) { ++ // CraftBukkit start - call EntityBlockFormEvent for Wither Rose ++ flag = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this.level(), blockposition, iblockdata, 3, this); ++ // CraftBukkit end + } + } + + if (!flag) { +- ItemEntity itemEntity = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), new ItemStack(Items.WITHER_ROSE)); +- this.level().addFreshEntity(itemEntity); ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), new ItemStack(Items.WITHER_ROSE)); ++ ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ CraftEventFactory.callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ this.level().addFreshEntity(entityitem); + } + } + } +@@ -1398,28 +1727,41 @@ + } + + boolean flag = this.lastHurtByPlayerTime > 0; ++ ++ this.dropEquipment(); // CraftBukkit - from below + if (this.shouldDropLoot() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { + this.dropFromLootTable(damageSource, flag); + this.dropCustomDeathLoot(damageSource, mobLooting, flag); + } ++ // CraftBukkit start - Call death event ++ CraftEventFactory.callEntityDeathEvent(this, this.drops); ++ this.drops = new ArrayList<>(); ++ // CraftBukkit end + +- this.dropEquipment(); ++ // this.dropInventory();// CraftBukkit - moved up + this.dropExperience(); + } + +- protected void dropEquipment() { ++ protected void dropEquipment() {} ++ ++ // CraftBukkit start ++ public int getExpReward() { ++ if (this.level() instanceof ServerLevel && !this.wasExperienceConsumed() && (this.isAlwaysExperienceDropper() || this.lastHurtByPlayerTime > 0 && this.shouldDropExperience() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT))) { ++ int i = this.getExperienceReward(); ++ return i; ++ } else { ++ return 0; ++ } + } ++ // CraftBukkit end + + protected void dropExperience() { +- if (this.level() instanceof ServerLevel +- && !this.wasExperienceConsumed() +- && ( +- this.isAlwaysExperienceDropper() +- || this.lastHurtByPlayerTime > 0 && this.shouldDropExperience() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT) +- )) { +- ExperienceOrb.award((ServerLevel)this.level(), this.position(), this.getExperienceReward()); ++ // CraftBukkit start - Update getExpReward() above if the removed if() changes! ++ if (true && !(this instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon)) { // CraftBukkit - SPIGOT-2420: Special case ender dragon will drop the xp over time ++ ExperienceOrb.award((ServerLevel) this.level(), this.position(), this.expToDrop); ++ this.expToDrop = 0; + } +- } ++ // CraftBukkit end + + protected void dropCustomDeathLoot(DamageSource damageSource, int looting, boolean hitByPlayer) { + } +@@ -1513,6 +1853,28 @@ + return stack.getEatingSound(); + } + ++ // CraftBukkit start - Add delegate methods ++ public SoundEvent getHurtSound0(DamageSource damagesource) { ++ return getHurtSound(damagesource); ++ } ++ ++ public SoundEvent getDeathSound0() { ++ return getDeathSound(); ++ } ++ ++ public SoundEvent getFallDamageSound0(int fallHeight) { ++ return getFallDamageSound(fallHeight); ++ } ++ ++ public SoundEvent getDrinkingSound0(ItemStack itemstack) { ++ return getDrinkingSound(itemstack); ++ } ++ ++ public SoundEvent getEatingSound0(ItemStack itemstack) { ++ return getEatingSound(itemstack); ++ } ++ // CraftBukkit end ++ + public Optional getLastClimbablePos() { + return this.lastClimbablePos; + } +@@ -1556,9 +1921,14 @@ + boolean flag = super.causeFallDamage(fallDistance, multiplier, source); + int i = this.calculateFallDamage(fallDistance, multiplier); + if (i > 0) { ++ // CraftBukkit start ++ if (!this.hurt(source, (float) i)) { ++ return true; ++ } ++ // CraftBukkit end + this.playSound(this.getFallDamageSound(i), 1.0F, 1.0F); + this.playBlockFallSound(); +- this.hurt(source, (float)i); ++ // this.damageEntity(damagesource, (float) i); // CraftBukkit - moved up + return true; + } else { + return flag; +@@ -1609,10 +1980,8 @@ + + protected float getDamageAfterArmorAbsorb(DamageSource damageSource, float damageAmount) { + if (!damageSource.is(DamageTypeTags.BYPASSES_ARMOR)) { +- this.hurtArmor(damageSource, damageAmount); +- damageAmount = CombatRules.getDamageAfterAbsorb( +- damageAmount, (float)this.getArmorValue(), (float)this.getAttributeValue(Attributes.ARMOR_TOUGHNESS) +- ); ++ // this.hurtArmor(damagesource, f); // CraftBukkit - Moved into damageEntity0(DamageSource, float) ++ damageAmount = CombatRules.getDamageAfterAbsorb(damageAmount, (float) this.getArmorValue(), (float) this.getAttributeValue(Attributes.ARMOR_TOUGHNESS)); + } + + return damageAmount; +@@ -1622,14 +1991,19 @@ + if (damageSource.is(DamageTypeTags.BYPASSES_EFFECTS)) { + return damageAmount; + } else { +- if (this.hasEffect(MobEffects.DAMAGE_RESISTANCE) && !damageSource.is(DamageTypeTags.BYPASSES_RESISTANCE)) { +- int i = (this.getEffect(MobEffects.DAMAGE_RESISTANCE).getAmplifier() + 1) * 5; +- int i1 = 25 - i; +- float f = damageAmount * (float)i1; +- float f1 = damageAmount; +- damageAmount = Math.max(f / 25.0F, 0.0F); +- float f2 = f1 - damageAmount; +- if (f2 > 0.0F && f2 < 3.4028235E37F) { ++ int i; ++ ++ // CraftBukkit - Moved to damageEntity0(DamageSource, float) ++ if (false && this.hasEffect(MobEffects.DAMAGE_RESISTANCE) && !damageSource.is(DamageTypeTags.BYPASSES_RESISTANCE)) { ++ i = (this.getEffect(MobEffects.DAMAGE_RESISTANCE).getAmplifier() + 1) * 5; ++ int j = 25 - i; ++ float f1 = damageAmount * (float) j; ++ float f2 = damageAmount; ++ ++ damageAmount = Math.max(f1 / 25.0F, 0.0F); ++ float f3 = f2 - damageAmount; ++ ++ if (f3 > 0.0F && f3 < 3.4028235E37F) { + if (this instanceof ServerPlayer) { + ((ServerPlayer)this).awardStat(Stats.DAMAGE_RESISTED, Math.round(f2 * 10.0F)); + } else if (damageSource.getEntity() instanceof ServerPlayer) { +@@ -1653,24 +2027,173 @@ + } + } + +- protected void actuallyHurt(DamageSource damageSource, float damageAmount) { +- if (!this.isInvulnerableTo(damageSource)) { +- damageAmount = this.getDamageAfterArmorAbsorb(damageSource, damageAmount); +- damageAmount = this.getDamageAfterMagicAbsorb(damageSource, damageAmount); +- float var9 = Math.max(damageAmount - this.getAbsorptionAmount(), 0.0F); +- this.setAbsorptionAmount(this.getAbsorptionAmount() - (damageAmount - var9)); +- float f1 = damageAmount - var9; +- if (f1 > 0.0F && f1 < 3.4028235E37F && damageSource.getEntity() instanceof ServerPlayer serverPlayer) { +- serverPlayer.awardStat(Stats.DAMAGE_DEALT_ABSORBED, Math.round(f1 * 10.0F)); ++ // CraftBukkit start ++ protected boolean damageEntity0(final DamageSource damagesource, float f) { // void -> boolean, add final ++ if (!this.isInvulnerableTo(damagesource)) { ++ final boolean human = this instanceof net.minecraft.world.entity.player.Player; ++ float originalDamage = f; ++ Function hardHat = new Function() { ++ @Override ++ public Double apply(Double f) { ++ if (damagesource.is(DamageTypeTags.DAMAGES_HELMET) && !LivingEntity.this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { ++ return -(f - (f * 0.75F)); ++ ++ } ++ return -0.0; ++ } ++ }; ++ float hardHatModifier = hardHat.apply((double) f).floatValue(); ++ f += hardHatModifier; ++ ++ Function blocking = new Function() { ++ @Override ++ public Double apply(Double f) { ++ return -((LivingEntity.this.isDamageSourceBlocked(damagesource)) ? f : 0.0); ++ } ++ }; ++ float blockingModifier = blocking.apply((double) f).floatValue(); ++ f += blockingModifier; ++ ++ Function armor = new Function() { ++ @Override ++ public Double apply(Double f) { ++ return -(f - LivingEntity.this.getDamageAfterArmorAbsorb(damagesource, f.floatValue())); ++ } ++ }; ++ float armorModifier = armor.apply((double) f).floatValue(); ++ f += armorModifier; ++ ++ Function resistance = new Function() { ++ @Override ++ public Double apply(Double f) { ++ if (!damagesource.is(DamageTypeTags.BYPASSES_EFFECTS) && LivingEntity.this.hasEffect(MobEffects.DAMAGE_RESISTANCE) && !damagesource.is(DamageTypeTags.BYPASSES_RESISTANCE)) { ++ int i = (LivingEntity.this.getEffect(MobEffects.DAMAGE_RESISTANCE).getAmplifier() + 1) * 5; ++ int j = 25 - i; ++ float f1 = f.floatValue() * (float) j; ++ return -(f - (f1 / 25.0F)); ++ } ++ return -0.0; ++ } ++ }; ++ float resistanceModifier = resistance.apply((double) f).floatValue(); ++ f += resistanceModifier; ++ ++ Function magic = new Function() { ++ @Override ++ public Double apply(Double f) { ++ return -(f - LivingEntity.this.getDamageAfterMagicAbsorb(damagesource, f.floatValue())); ++ } ++ }; ++ float magicModifier = magic.apply((double) f).floatValue(); ++ f += magicModifier; ++ ++ Function absorption = new Function() { ++ @Override ++ public Double apply(Double f) { ++ return -(Math.max(f - Math.max(f - LivingEntity.this.getAbsorptionAmount(), 0.0F), 0.0F)); ++ } ++ }; ++ float absorptionModifier = absorption.apply((double) f).floatValue(); ++ ++ EntityDamageEvent event = CraftEventFactory.handleLivingEntityDamageEvent(this, damagesource, originalDamage, hardHatModifier, blockingModifier, armorModifier, resistanceModifier, magicModifier, absorptionModifier, hardHat, blocking, armor, resistance, magic, absorption); ++ if (damagesource.getEntity() instanceof net.minecraft.world.entity.player.Player) { ++ ((net.minecraft.world.entity.player.Player) damagesource.getEntity()).resetAttackStrengthTicker(); // Moved from EntityHuman in order to make the cooldown reset get called after the damage event is fired + } + +- if (var9 != 0.0F) { +- this.getCombatTracker().recordDamage(damageSource, var9); +- this.setHealth(this.getHealth() - var9); +- this.setAbsorptionAmount(this.getAbsorptionAmount() - var9); ++ f = (float) event.getFinalDamage(); ++ ++ // Resistance ++ if (event.getDamage(DamageModifier.RESISTANCE) < 0) { ++ float f3 = (float) -event.getDamage(DamageModifier.RESISTANCE); ++ if (f3 > 0.0F && f3 < 3.4028235E37F) { ++ if (this instanceof ServerPlayer) { ++ ((ServerPlayer) this).awardStat(Stats.DAMAGE_RESISTED, Math.round(f3 * 10.0F)); ++ } else if (damagesource.getEntity() instanceof ServerPlayer) { ++ ((ServerPlayer) damagesource.getEntity()).awardStat(Stats.DAMAGE_DEALT_RESISTED, Math.round(f3 * 10.0F)); ++ } ++ } ++ } ++ ++ // Apply damage to helmet ++ if (damagesource.is(DamageTypeTags.DAMAGES_HELMET) && !this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { ++ this.hurtHelmet(damagesource, f); ++ } ++ ++ // Apply damage to armor ++ if (!damagesource.is(DamageTypeTags.BYPASSES_ARMOR)) { ++ float armorDamage = (float) (event.getDamage() + event.getDamage(DamageModifier.BLOCKING) + event.getDamage(DamageModifier.HARD_HAT)); ++ this.hurtArmor(damagesource, armorDamage); ++ } ++ ++ // Apply blocking code // PAIL: steal from above ++ if (event.getDamage(DamageModifier.BLOCKING) < 0) { ++ this.level().broadcastEntityEvent(this, (byte) 29); // SPIGOT-4635 - shield damage sound ++ this.hurtCurrentlyUsedShield((float) -event.getDamage(DamageModifier.BLOCKING)); ++ Entity entity = damagesource.getDirectEntity(); ++ ++ if (entity instanceof LivingEntity) { ++ this.blockUsingShield((LivingEntity) entity); ++ } ++ } ++ ++ absorptionModifier = (float) -event.getDamage(DamageModifier.ABSORPTION); ++ this.setAbsorptionAmount(Math.max(this.getAbsorptionAmount() - absorptionModifier, 0.0F)); ++ float f2 = absorptionModifier; ++ ++ if (f2 > 0.0F && f2 < 3.4028235E37F && this instanceof net.minecraft.world.entity.player.Player) { ++ ((net.minecraft.world.entity.player.Player) this).awardStat(Stats.DAMAGE_ABSORBED, Math.round(f2 * 10.0F)); ++ } ++ if (f2 > 0.0F && f2 < 3.4028235E37F) { ++ Entity entity = damagesource.getEntity(); ++ ++ if (entity instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entity; ++ ++ entityplayer.awardStat(Stats.DAMAGE_DEALT_ABSORBED, Math.round(f2 * 10.0F)); ++ } ++ } ++ ++ if (f > 0 || !human) { ++ if (human) { ++ // PAIL: Be sure to drag all this code from the EntityHuman subclass each update. ++ ((net.minecraft.world.entity.player.Player) this).causeFoodExhaustion(damagesource.getFoodExhaustion(), org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.DAMAGED); // CraftBukkit - EntityExhaustionEvent ++ if (f < 3.4028235E37F) { ++ ((net.minecraft.world.entity.player.Player) this).awardStat(Stats.DAMAGE_TAKEN, Math.round(f * 10.0F)); ++ } ++ } ++ // CraftBukkit end ++ this.getCombatTracker().recordDamage(damagesource, f); ++ this.setHealth(this.getHealth() - f); ++ // CraftBukkit start ++ if (!human) { ++ this.setAbsorptionAmount(this.getAbsorptionAmount() - f); ++ } + this.gameEvent(GameEvent.ENTITY_DAMAGE); ++ ++ return true; ++ } else { ++ // Duplicate triggers if blocking ++ if (event.getDamage(DamageModifier.BLOCKING) < 0) { ++ if (this instanceof ServerPlayer) { ++ CriteriaTriggers.ENTITY_HURT_PLAYER.trigger((ServerPlayer) this, damagesource, f, originalDamage, true); ++ f2 = (float) -event.getDamage(DamageModifier.BLOCKING); ++ if (f2 > 0.0F && f2 < 3.4028235E37F) { ++ ((ServerPlayer) this).awardStat(Stats.DAMAGE_BLOCKED_BY_SHIELD, Math.round(originalDamage * 10.0F)); ++ } ++ } ++ ++ if (damagesource.getEntity() instanceof ServerPlayer) { ++ CriteriaTriggers.PLAYER_HURT_ENTITY.trigger((ServerPlayer) damagesource.getEntity(), this, damagesource, f, originalDamage, true); ++ } ++ ++ return false; ++ } else { ++ return originalDamage > 0; ++ } ++ // CraftBukkit end + } + } ++ return false; // CraftBukkit + } + + public CombatTracker getCombatTracker() { +@@ -1699,9 +2221,19 @@ + } + + public final void setArrowCount(int count) { +- this.entityData.set(DATA_ARROW_COUNT_ID, count); ++ // CraftBukkit start ++ setArrowCount(count, false); + } + ++ public final void setArrowCount(int i, boolean flag) { ++ ArrowBodyCountChangeEvent event = CraftEventFactory.callArrowBodyCountChangeEvent(this, getArrowCount(), i, flag); ++ if (event.isCancelled()) { ++ return; ++ } ++ this.entityData.set(LivingEntity.DATA_ARROW_COUNT_ID, event.getNewAmount()); ++ } ++ // CraftBukkit end ++ + public final int getStingerCount() { + return this.entityData.get(DATA_STINGER_COUNT_ID); + } +@@ -1932,6 +2474,12 @@ + + public abstract ItemStack getItemBySlot(EquipmentSlot slot); + ++ // CraftBukkit start ++ public void setItemSlot(EquipmentSlot enumitemslot, ItemStack itemstack, boolean silent) { ++ this.setItemSlot(enumitemslot, itemstack); ++ } ++ // CraftBukkit end ++ + @Override + public abstract void setItemSlot(EquipmentSlot slot, ItemStack stack); + +@@ -2149,6 +2714,7 @@ + } + + if (this.onGround() && !this.level().isClientSide) { ++ if (getSharedFlag(7) && !CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) // CraftBukkit + this.setSharedFlag(7, false); + } + } else { +@@ -2310,7 +2885,7 @@ + } + } + +- this.detectEquipmentUpdates(); ++ this.detectEquipmentUpdatesPublic(); // CraftBukkit + if (this.tickCount % 20 == 0) { + this.getCombatTracker().recheckStatus(); + } +@@ -2404,7 +2982,7 @@ + this.refreshDirtyAttributes(); + } + +- private void detectEquipmentUpdates() { ++ public void detectEquipmentUpdatesPublic() { // CraftBukkit + Map map = this.collectEquipmentChanges(); + if (map != null) { + this.handleHandSwap(map); +@@ -2679,7 +3284,8 @@ + } + + if (!this.level().isClientSide) { +- this.setSharedFlag(7, sharedFlag); ++ if (flag != this.getSharedFlag(7) && !CraftEventFactory.callToggleGlideEvent(this, flag).isCancelled()) // CraftBukkit ++ this.setSharedFlag(7, flag); + } + } + +@@ -2850,15 +3475,22 @@ + + @Override + public boolean isPickable() { +- return !this.isRemoved(); ++ return !this.isRemoved() && this.collides; // CraftBukkit + } + + @Override + public boolean isPushable() { +- return this.isAlive() && !this.isSpectator() && !this.onClimbable(); ++ return this.isAlive() && !this.isSpectator() && !this.onClimbable() && this.collides; // CraftBukkit + } + ++ // CraftBukkit start - collidable API + @Override ++ public boolean canCollideWithBukkit(Entity entity) { ++ return isPushable() && this.collides != this.collidableExemptions.contains(entity.getUUID()); ++ } ++ // CraftBukkit end ++ ++ @Override + public float getYHeadRot() { + return this.yHeadRot; + } +@@ -3042,10 +3684,26 @@ + } else { + if (!this.useItem.isEmpty() && this.isUsingItem()) { + this.triggerItemUseEffects(this.useItem, 16); +- ItemStack itemStack = this.useItem.finishUsingItem(this.level(), this); +- if (itemStack != this.useItem) { +- this.setItemInHand(usedItemHand, itemStack); ++ // CraftBukkit start - fire PlayerItemConsumeEvent ++ ItemStack itemstack; ++ if (this instanceof ServerPlayer) { ++ org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(this.useItem); ++ org.bukkit.inventory.EquipmentSlot hand = org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(enumhand); ++ PlayerItemConsumeEvent event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem, hand); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ // Update client ++ ((ServerPlayer) this).getBukkitEntity().updateInventory(); ++ ((ServerPlayer) this).getBukkitEntity().updateScaledHealth(); ++ return; ++ } ++ ++ itemstack = (craftItem.equals(event.getItem())) ? this.useItem.finishUsingItem(this.level(), this) : CraftItemStack.asNMSCopy(event.getItem()).finishUsingItem(this.level(), this); ++ } else { ++ itemstack = this.useItem.finishUsingItem(this.level(), this); + } ++ // CraftBukkit end + + this.stopUsingItem(); + } +@@ -3115,39 +3780,72 @@ + return this.fallFlyTicks; + } + +- public boolean randomTeleport(double x, double y, double z, boolean broadcastTeleport) { +- double x1 = this.getX(); +- double y1 = this.getY(); +- double z1 = this.getZ(); +- double d = y; +- boolean flag = false; +- BlockPos blockPos = BlockPos.containing(x, y, z); +- Level level = this.level(); +- if (level.hasChunkAt(blockPos)) { +- boolean flag1 = false; ++ public boolean randomTeleport(double x, double d1, double y, boolean flag) { ++ // CraftBukkit start ++ return randomTeleport(x, d1, y, flag, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.UNKNOWN).orElse(false); ++ } + +- while (!flag1 && blockPos.getY() > level.getMinBuildHeight()) { +- BlockPos blockPos1 = blockPos.below(); +- BlockState blockState = level.getBlockState(blockPos1); +- if (blockState.blocksMotion()) { +- flag1 = true; ++ public Optional randomTeleport(double d0, double d1, double d2, boolean flag, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { ++ // CraftBukkit end ++ double d3 = this.getX(); ++ double d4 = this.getY(); ++ double d5 = this.getZ(); ++ double d6 = d1; ++ boolean flag1 = false; ++ BlockPos blockposition = BlockPos.containing(d0, d1, d2); ++ Level world = this.level(); ++ ++ if (world.hasChunkAt(blockposition)) { ++ boolean flag2 = false; ++ ++ while (!flag2 && blockposition.getY() > world.getMinBuildHeight()) { ++ BlockPos blockposition1 = blockposition.below(); ++ IBlockData iblockdata = world.getBlockState(blockposition1); ++ ++ if (iblockdata.blocksMotion()) { ++ flag2 = true; + } else { + d--; + blockPos = blockPos1; + } + } + +- if (flag1) { +- this.teleportTo(x, d, z); +- if (level.noCollision(this) && !level.containsAnyLiquid(this.getBoundingBox())) { +- flag = true; ++ if (flag2) { ++ // CraftBukkit start - Teleport event ++ // this.teleportTo(d0, d6, d2); ++ ++ // first set position, to check if the place to teleport is valid ++ this.setPos(d0, d6, d2); ++ if (world.noCollision((Entity) this) && !world.containsAnyLiquid(this.getBoundingBox())) { ++ flag1 = true; + } ++ // now revert and call event if the teleport place is valid ++ this.setPos(d3, d4, d5); ++ ++ if (flag1) { ++ if (!(this instanceof ServerPlayer)) { ++ EntityTeleportEvent teleport = new EntityTeleportEvent(this.getBukkitEntity(), new Location(this.level().getWorld(), d3, d4, d5), new Location(this.level().getWorld(), d0, d6, d2)); ++ this.level().getCraftServer().getPluginManager().callEvent(teleport); ++ if (!teleport.isCancelled()) { ++ Location to = teleport.getTo(); ++ this.teleportTo(to.getX(), to.getY(), to.getZ()); ++ } else { ++ return Optional.empty(); ++ } ++ } else { ++ // player teleport event is called in the underlining code ++ if (((ServerPlayer) this).connection.teleport(d0, d6, d2, this.getYRot(), this.getXRot(), java.util.Collections.emptySet(), cause)) { ++ return Optional.empty(); ++ } ++ } ++ } ++ // CraftBukkit end + } + } + +- if (!flag) { +- this.teleportTo(x1, y1, z1); +- return false; ++ if (!flag1) { ++ // this.enderTeleportTo(d3, d4, d5); // CraftBukkit - already set the location back ++ return Optional.of(false); // CraftBukkit + } else { + if (broadcastTeleport) { + level.broadcastEntityEvent(this, (byte)46); +@@ -3157,7 +3857,7 @@ + pathfinderMob.getNavigation().stop(); + } + +- return true; ++ return Optional.of(true); // CraftBukkit + } + } + +@@ -3321,9 +4021,14 @@ + private void addEatEffect(ItemStack food, Level level, LivingEntity livingEntity) { + Item item = food.getItem(); + if (item.isEdible()) { +- for (Pair pair : item.getFoodProperties().getEffects()) { +- if (!level.isClientSide && pair.getFirst() != null && level.random.nextFloat() < pair.getSecond()) { +- livingEntity.addEffect(new MobEffectInstance(pair.getFirst())); ++ List> list = item.getFoodProperties().getEffects(); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Pair pair = (Pair) iterator.next(); ++ ++ if (!level.isClientSide && pair.getFirst() != null && level.random.nextFloat() < (Float) pair.getSecond()) { ++ livingEntity.addEffect(new MobEffectInstance((MobEffectInstance) pair.getFirst()), EntityPotionEffectEvent.Cause.FOOD); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/Mob.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/Mob.java.patch new file mode 100644 index 0000000000..79388388c3 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/Mob.java.patch @@ -0,0 +1,358 @@ +--- a/net/minecraft/world/entity/Mob.java ++++ b/net/minecraft/world/entity/Mob.java +@@ -72,6 +76,16 @@ + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.AABB; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++import org.bukkit.event.entity.EntityUnleashEvent; ++import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; ++// CraftBukkit end + + public abstract class Mob extends LivingEntity implements Targeting { + private static final EntityDataAccessor DATA_MOB_FLAGS_ID = SynchedEntityData.defineId(Mob.class, EntityDataSerializers.BYTE); +@@ -119,6 +134,8 @@ + private BlockPos restrictCenter = BlockPos.ZERO; + private float restrictRadius = -1.0F; + ++ public boolean aware = true; // CraftBukkit ++ + protected Mob(EntityType entityType, Level level) { + super(entityType, level); + this.goalSelector = new GoalSelector(level.getProfilerSupplier()); +@@ -136,8 +161,11 @@ + } + } + +- protected void registerGoals() { ++ // CraftBukkit start ++ public void setPersistenceRequired(boolean persistenceRequired) { ++ this.persistenceRequired = persistenceRequired; + } ++ // CraftBukkit end + + public static AttributeSupplier.Builder createMobAttributes() { + return LivingEntity.createLivingAttributes().add(Attributes.FOLLOW_RANGE, 16.0).add(Attributes.ATTACK_KNOCKBACK); +@@ -218,9 +278,40 @@ + } + + public void setTarget(@Nullable LivingEntity target) { +- this.target = target; ++ // CraftBukkit start - fire event ++ setTarget(target, EntityTargetEvent.TargetReason.UNKNOWN, true); + } + ++ public boolean setTarget(LivingEntity entityliving, EntityTargetEvent.TargetReason reason, boolean fireEvent) { ++ if (getTarget() == entityliving) return false; ++ if (fireEvent) { ++ if (reason == EntityTargetEvent.TargetReason.UNKNOWN && getTarget() != null && entityliving == null) { ++ reason = getTarget().isAlive() ? EntityTargetEvent.TargetReason.FORGOT_TARGET : EntityTargetEvent.TargetReason.TARGET_DIED; ++ } ++ if (reason == EntityTargetEvent.TargetReason.UNKNOWN) { ++ this.level().getCraftServer().getLogger().log(java.util.logging.Level.WARNING, "Unknown target reason, please report on the issue tracker", new Exception()); ++ } ++ CraftLivingEntity ctarget = null; ++ if (entityliving != null) { ++ ctarget = (CraftLivingEntity) entityliving.getBukkitEntity(); ++ } ++ EntityTargetLivingEntityEvent event = new EntityTargetLivingEntityEvent(this.getBukkitEntity(), ctarget, reason); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ if (event.getTarget() != null) { ++ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ } else { ++ entityliving = null; ++ } ++ } ++ this.target = entityliving; ++ return true; ++ // CraftBukkit end ++ } ++ + @Override + public boolean canAttackType(EntityType type) { + return type != EntityType.GHAST; +@@ -350,6 +449,12 @@ + return null; + } + ++ // CraftBukkit start - Add delegate method ++ public SoundEvent getAmbientSound0() { ++ return getAmbientSound(); ++ } ++ // CraftBukkit end ++ + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +@@ -392,9 +512,9 @@ + list3.add(FloatTag.valueOf(f1)); + } + +- compound.put("HandDropChances", list3); +- if (this.leashHolder != null) { +- CompoundTag compoundTag1 = new CompoundTag(); ++ compound.put("HandDropChances", nbttaglist3); ++ if (this.leashHolder != null && !this.leashHolder.pluginRemoved) { // CraftBukkit - SPIGOT-7487: Don't save (and possible drop) leash, when the holder was removed by a plugin ++ nbttagcompound2 = new CompoundTag(); + if (this.leashHolder instanceof LivingEntity) { + UUID uUID = this.leashHolder.getUUID(); + compoundTag1.putUUID("UUID", uUID); +@@ -421,16 +543,27 @@ + if (this.isNoAi()) { + compound.putBoolean("NoAI", this.isNoAi()); + } ++ ++ compound.putBoolean("Bukkit.Aware", this.aware); // CraftBukkit + } + + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); ++ ++ // CraftBukkit start - If looting or persistence is false only use it if it was set after we started using it + if (compound.contains("CanPickUpLoot", 1)) { + this.setCanPickUpLoot(compound.getBoolean("CanPickUpLoot")); + } + +- this.persistenceRequired = compound.getBoolean("PersistenceRequired"); ++ boolean data = compound.getBoolean("PersistenceRequired"); ++ if (isLevelAtLeast(compound, 1) || data) { ++ this.persistenceRequired = data; ++ } ++ // CraftBukkit end ++ ListTag nbttaglist; ++ int i; ++ + if (compound.contains("ArmorItems", 9)) { + ListTag list = compound.getList("ArmorItems", 10); + +@@ -474,6 +610,11 @@ + } + + this.setNoAi(compound.getBoolean("NoAI")); ++ // CraftBukkit start ++ if (compound.contains("Bukkit.Aware")) { ++ this.aware = compound.getBoolean("Bukkit.Aware"); ++ } ++ // CraftBukkit end + } + + @Override +@@ -543,9 +681,10 @@ + } + + protected void pickUpItem(ItemEntity itemEntity) { +- ItemStack item = itemEntity.getItem(); +- ItemStack itemStack = this.equipItemIfPossible(item.copy()); +- if (!itemStack.isEmpty()) { ++ ItemStack itemstack = itemEntity.getItem(); ++ ItemStack itemstack1 = this.equipItemIfPossible(itemstack.copy(), itemEntity); // CraftBukkit - add item ++ ++ if (!itemstack1.isEmpty()) { + this.onItemPickup(itemEntity); + this.take(itemEntity, itemStack.getCount()); + item.shrink(itemStack.getCount()); +@@ -556,19 +696,35 @@ + } + + public ItemStack equipItemIfPossible(ItemStack stack) { +- EquipmentSlot equipmentSlotForItem = getEquipmentSlotForItem(stack); +- ItemStack itemBySlot = this.getItemBySlot(equipmentSlotForItem); +- boolean canReplaceCurrentItem = this.canReplaceCurrentItem(stack, itemBySlot); +- if (equipmentSlotForItem.isArmor() && !canReplaceCurrentItem) { +- equipmentSlotForItem = EquipmentSlot.MAINHAND; +- itemBySlot = this.getItemBySlot(equipmentSlotForItem); +- canReplaceCurrentItem = itemBySlot.isEmpty(); ++ // CraftBukkit start - add item ++ return this.equipItemIfPossible(stack, null); ++ } ++ ++ public ItemStack equipItemIfPossible(ItemStack itemstack, ItemEntity entityitem) { ++ // CraftBukkit end ++ EquipmentSlot enumitemslot = getEquipmentSlotForItem(itemstack); ++ ItemStack itemstack1 = this.getItemBySlot(enumitemslot); ++ boolean flag = this.canReplaceCurrentItem(itemstack, itemstack1); ++ ++ if (enumitemslot.isArmor() && !flag) { ++ enumitemslot = EquipmentSlot.MAINHAND; ++ itemstack1 = this.getItemBySlot(enumitemslot); ++ flag = itemstack1.isEmpty(); + } + +- if (canReplaceCurrentItem && this.canHoldItem(stack)) { +- double d = (double)this.getEquipmentDropChance(equipmentSlotForItem); +- if (!itemBySlot.isEmpty() && (double)Math.max(this.random.nextFloat() - 0.1F, 0.0F) < d) { +- this.spawnAtLocation(itemBySlot); ++ // CraftBukkit start ++ boolean canPickup = flag && this.canHoldItem(itemstack); ++ if (entityitem != null) { ++ canPickup = !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, entityitem, 0, !canPickup).isCancelled(); ++ } ++ if (canPickup) { ++ // CraftBukkit end ++ double d0 = (double) this.getEquipmentDropChance(enumitemslot); ++ ++ if (!itemstack1.isEmpty() && (double) Math.max(this.random.nextFloat() - 0.1F, 0.0F) < d0) { ++ this.forceDrops = true; // CraftBukkit ++ this.spawnAtLocation(itemstack1); ++ this.forceDrops = false; // CraftBukkit + } + + if (equipmentSlotForItem.isArmor() && stack.getCount() > 1) { +@@ -710,7 +875,8 @@ + + @Override + protected final void serverAiStep() { +- this.noActionTime++; ++ ++this.noActionTime; ++ if (!this.aware) return; // CraftBukkit + this.level().getProfiler().push("sensing"); + this.sensing.tick(); + this.level().getProfiler().pop(); +@@ -1075,6 +1270,12 @@ + if (!this.isAlive()) { + return InteractionResult.PASS; + } else if (this.getLeashHolder() == player) { ++ // CraftBukkit start - fire PlayerUnleashEntityEvent ++ if (CraftEventFactory.callPlayerUnleashEntityEvent(this, player, hand).isCancelled()) { ++ ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, this.getLeashHolder())); ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.dropLeash(true, !player.getAbilities().instabuild); + this.gameEvent(GameEvent.ENTITY_INTERACT, player); + return InteractionResult.sidedSuccess(this.level().isClientSide); +@@ -1095,9 +1297,16 @@ + } + } + +- private InteractionResult checkAndHandleImportantInteractions(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (itemInHand.is(Items.LEAD) && this.canBeLeashed(player)) { ++ private InteractionResult checkAndHandleImportantInteractions(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (itemstack.is(Items.LEAD) && this.canBeLeashed(player)) { ++ // CraftBukkit start - fire PlayerLeashEntityEvent ++ if (CraftEventFactory.callPlayerLeashEntityEvent(this, player, player, hand).isCancelled()) { ++ ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, this.getLeashHolder())); ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.setLeashedTo(player, true); + itemInHand.shrink(1); + return InteractionResult.sidedSuccess(this.level().isClientSide); +@@ -1162,8 +1372,15 @@ + return this.restrictRadius != -1.0F; + } + ++ // CraftBukkit start + @Nullable + public T convertTo(EntityType entityType, boolean transferInventory) { ++ return this.convertTo(entityType, transferInventory, EntityTransformEvent.TransformReason.UNKNOWN, CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ @Nullable ++ public T convertTo(EntityType entitytypes, boolean flag, EntityTransformEvent.TransformReason transformReason, CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end + if (this.isRemoved()) { + return null; + } else { +@@ -1196,7 +1418,12 @@ + } + } + +- this.level().addFreshEntity(mob); ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, t0, transformReason).isCancelled()) { ++ return null; ++ } ++ this.level().addFreshEntity(t0, spawnReason); ++ // CraftBukkit end + if (this.isPassenger()) { + Entity vehicle = this.getVehicle(); + this.stopRiding(); +@@ -1216,7 +1444,8 @@ + + if (this.leashHolder != null) { + if (!this.isAlive() || !this.leashHolder.isAlive()) { +- this.dropLeash(true, true); ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE)); // CraftBukkit ++ this.dropLeash(true, !this.leashHolder.pluginRemoved);// CraftBukkit - SPIGOT-7487: Don't drop leash, when the holder was removed by a plugin + } + } + } +@@ -1226,7 +1456,9 @@ + this.leashHolder = null; + this.leashInfoTag = null; + if (!this.level().isClientSide && dropLeash) { +- this.spawnAtLocation(Items.LEAD); ++ this.forceDrops = true; // CraftBukkit ++ this.spawnAtLocation((IMaterial) Items.LEAD); ++ this.forceDrops = false; // CraftBukkit + } + + if (!this.level().isClientSide && broadcastPacket && this.level() instanceof ServerLevel) { +@@ -1271,8 +1505,10 @@ + + @Override + public boolean startRiding(Entity entity, boolean force) { +- boolean flag = super.startRiding(entity, force); +- if (flag && this.isLeashed()) { ++ boolean flag1 = super.startRiding(entity, force); ++ ++ if (flag1 && this.isLeashed()) { ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit + this.dropLeash(true, true); + } + +@@ -1295,7 +1533,9 @@ + } + + if (this.tickCount > 100) { +- this.spawnAtLocation(Items.LEAD); ++ this.forceDrops = true; // CraftBukkit ++ this.spawnAtLocation((IMaterial) Items.LEAD); ++ this.forceDrops = false; // CraftBukkit + this.leashInfoTag = null; + } + } +@@ -1375,9 +1614,17 @@ + f1 += (float)EnchantmentHelper.getKnockbackBonus(this); + } + +- int fireAspect = EnchantmentHelper.getFireAspect(this); +- if (fireAspect > 0) { +- entity.setSecondsOnFire(fireAspect * 4); ++ int i = EnchantmentHelper.getFireAspect(this); ++ ++ if (i > 0) { ++ // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), i * 4); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ entity.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + + boolean flag = entity.hurt(this.damageSources().mobAttack(this), f); +@@ -1451,6 +1699,7 @@ + @Override + protected void removeAfterChangingDimensions() { + super.removeAfterChangingDimensions(); ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit + this.dropLeash(true, false); + this.getAllSlots().forEach(slot -> { + if (!slot.isEmpty()) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/NeutralMob.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/NeutralMob.java.patch new file mode 100644 index 0000000000..a3a2598a99 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/NeutralMob.java.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/world/entity/NeutralMob.java ++++ b/net/minecraft/world/entity/NeutralMob.java +@@ -100,9 +106,9 @@ + } + + default void stopBeingAngry() { +- this.setLastHurtByMob(null); +- this.setPersistentAngerTarget(null); +- this.setTarget(null); ++ this.setLastHurtByMob((LivingEntity) null); ++ this.setPersistentAngerTarget((UUID) null); ++ this.setTarget((LivingEntity) null, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET, true); // CraftBukkit + this.setRemainingPersistentAngerTime(0); + } + +@@ -115,6 +121,8 @@ + + void setTarget(@Nullable LivingEntity livingEntity); + ++ boolean setTarget(@Nullable LivingEntity entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent); // CraftBukkit ++ + boolean canAttack(LivingEntity entity); + + @Nullable diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/PathfinderMob.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/PathfinderMob.java.patch new file mode 100644 index 0000000000..444be03daa --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/PathfinderMob.java.patch @@ -0,0 +1,28 @@ +--- a/net/minecraft/world/entity/PathfinderMob.java ++++ b/net/minecraft/world/entity/PathfinderMob.java +@@ -9,6 +8,9 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.event.entity.EntityUnleashEvent; ++// CraftBukkit end + + public abstract class PathfinderMob extends Mob { + protected static final float DEFAULT_WALK_TARGET_VALUE = 0.0F; +@@ -49,6 +54,7 @@ + float f = this.distanceTo(leashHolder); + if (this instanceof TamableAnimal && ((TamableAnimal)this).isInSittingPose()) { + if (f > 10.0F) { ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit + this.dropLeash(true, true); + } + +@@ -57,6 +63,7 @@ + + this.onLeashDistance(f); + if (f > 10.0F) { ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit + this.dropLeash(true, true); + this.goalSelector.disableControlFlag(Goal.Flag.MOVE); + } else if (f > 6.0F) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/attributes/Attributes.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/attributes/Attributes.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/attributes/Attributes.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java.patch new file mode 100644 index 0000000000..6f6c7099a9 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java.patch @@ -0,0 +1,88 @@ +--- a/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java ++++ b/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java +@@ -13,41 +9,52 @@ + import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.entity.npc.VillagerProfession; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftVillager; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.VillagerCareerChangeEvent; ++// CraftBukkit end ++ + public class AssignProfessionFromJobSite { + public static BehaviorControl create() { +- return BehaviorBuilder.create( +- instance -> instance.group(instance.present(MemoryModuleType.POTENTIAL_JOB_SITE), instance.registered(MemoryModuleType.JOB_SITE)) +- .apply( +- instance, +- (potentialJobSite, jobSite) -> (level, villager, gameTime) -> { +- GlobalPos globalPos = instance.get(potentialJobSite); +- if (!globalPos.pos().closerToCenterThan(villager.position(), 2.0) && !villager.assignProfessionWhenSpawned()) { +- return false; +- } else { +- potentialJobSite.erase(); +- jobSite.set(globalPos); +- level.broadcastEntityEvent(villager, (byte)14); +- if (villager.getVillagerData().getProfession() != VillagerProfession.NONE) { +- return true; +- } else { +- MinecraftServer server = level.getServer(); +- Optional.ofNullable(server.getLevel(globalPos.dimension())) +- .flatMap(posLevel -> posLevel.getPoiManager().getType(globalPos.pos())) +- .flatMap( +- poi -> BuiltInRegistries.VILLAGER_PROFESSION +- .stream() +- .filter(profession -> profession.heldJobSite().test((Holder)poi)) +- .findFirst() +- ) +- .ifPresent(profession -> { +- villager.setVillagerData(villager.getVillagerData().setProfession(profession)); +- villager.refreshBrain(level); +- }); +- return true; +- } ++ return BehaviorBuilder.create((behaviorbuilder_b) -> { ++ return behaviorbuilder_b.group(behaviorbuilder_b.present(MemoryModuleType.POTENTIAL_JOB_SITE), behaviorbuilder_b.registered(MemoryModuleType.JOB_SITE)).apply(behaviorbuilder_b, (memoryaccessor, memoryaccessor1) -> { ++ return (worldserver, entityvillager, i) -> { ++ GlobalPos globalpos = (GlobalPos) behaviorbuilder_b.get(memoryaccessor); ++ ++ if (!globalpos.pos().closerToCenterThan(entityvillager.position(), 2.0D) && !entityvillager.assignProfessionWhenSpawned()) { ++ return false; ++ } else { ++ memoryaccessor.erase(); ++ memoryaccessor1.set(globalpos); ++ worldserver.broadcastEntityEvent(entityvillager, (byte) 14); ++ if (entityvillager.getVillagerData().getProfession() != VillagerProfession.NONE) { ++ return true; ++ } else { ++ MinecraftServer minecraftserver = worldserver.getServer(); ++ ++ Optional.ofNullable(minecraftserver.getLevel(globalpos.dimension())).flatMap((worldserver1) -> { ++ return worldserver1.getPoiManager().getType(globalpos.pos()); ++ }).flatMap((holder) -> { ++ return BuiltInRegistries.VILLAGER_PROFESSION.stream().filter((villagerprofession) -> { ++ return villagerprofession.heldJobSite().test(holder); ++ }).findFirst(); ++ }).ifPresent((villagerprofession) -> { ++ // CraftBukkit start - Fire VillagerCareerChangeEvent where Villager gets employed ++ VillagerCareerChangeEvent event = CraftEventFactory.callVillagerCareerChangeEvent(entityvillager, CraftVillager.CraftProfession.minecraftToBukkit(villagerprofession), VillagerCareerChangeEvent.ChangeReason.EMPLOYED); ++ if (event.isCancelled()) { ++ return; + } +- } +- ) +- ); ++ ++ entityvillager.setVillagerData(entityvillager.getVillagerData().setProfession(CraftVillager.CraftProfession.bukkitToMinecraft(event.getProfession()))); ++ // CraftBukkit end ++ entityvillager.refreshBrain(worldserver); ++ }); ++ return true; ++ } ++ } ++ }; ++ }); ++ }); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java.patch new file mode 100644 index 0000000000..1b5acf363d --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java.patch @@ -0,0 +1,80 @@ +--- a/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java ++++ b/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java +@@ -9,6 +7,12 @@ + import net.minecraft.world.entity.ai.behavior.declarative.MemoryAccessor; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + import net.minecraft.world.entity.ai.memory.WalkTarget; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++// CraftBukkit end + + public class BabyFollowAdult { + public static OneShot create(UniformInt followRange, float speedModifier) { +@@ -16,33 +25,37 @@ + } + + public static OneShot create(UniformInt followRange, Function speedModifier) { +- return BehaviorBuilder.create( +- instance -> instance.group( +- instance.present(MemoryModuleType.NEAREST_VISIBLE_ADULT), +- instance.registered(MemoryModuleType.LOOK_TARGET), +- instance.absent(MemoryModuleType.WALK_TARGET) +- ) +- .apply( +- instance, +- (nearestVisibleAdult, lookTarget, walkTarget) -> (level, mob, gameTime) -> { +- if (!mob.isBaby()) { +- return false; +- } else { +- AgeableMob ageableMob = instance.get(nearestVisibleAdult); +- if (mob.closerThan(ageableMob, (double)(followRange.getMaxValue() + 1)) +- && !mob.closerThan(ageableMob, (double)followRange.getMinValue())) { +- WalkTarget walkTarget1 = new WalkTarget( +- new EntityTracker(ageableMob, false), speedModifier.apply(mob), followRange.getMinValue() - 1 +- ); +- lookTarget.set(new EntityTracker(ageableMob, true)); +- walkTarget.set(walkTarget1); +- return true; +- } else { +- return false; +- } +- } ++ return BehaviorBuilder.create((behaviorbuilder_b) -> { ++ return behaviorbuilder_b.group(behaviorbuilder_b.present(MemoryModuleType.NEAREST_VISIBLE_ADULT), behaviorbuilder_b.registered(MemoryModuleType.LOOK_TARGET), behaviorbuilder_b.absent(MemoryModuleType.WALK_TARGET)).apply(behaviorbuilder_b, (memoryaccessor, memoryaccessor1, memoryaccessor2) -> { ++ return (worldserver, entityageable, i) -> { ++ if (!entityageable.isBaby()) { ++ return false; ++ } else { ++ LivingEntity entityageable1 = (AgeableMob) behaviorbuilder_b.get(memoryaccessor); // CraftBukkit - type ++ ++ if (entityageable.closerThan(entityageable1, (double) (followRange.getMaxValue() + 1)) && !entityageable.closerThan(entityageable1, (double) followRange.getMinValue())) { ++ // CraftBukkit start ++ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(entityageable, entityageable1, EntityTargetEvent.TargetReason.FOLLOW_LEADER); ++ if (event.isCancelled()) { ++ return false; + } +- ) +- ); ++ if (event.getTarget() == null) { ++ memoryaccessor.erase(); ++ return true; ++ } ++ entityageable1 = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ // CraftBukkit end ++ WalkTarget memorytarget = new WalkTarget(new EntityTracker(entityageable1, false), (Float) speedModifier.apply(entityageable), followRange.getMinValue() - 1); ++ ++ memoryaccessor1.set(new EntityTracker(entityageable1, true)); ++ memoryaccessor2.set(memorytarget); ++ return true; ++ } else { ++ return false; ++ } ++ } ++ }; ++ }); ++ }); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java.patch new file mode 100644 index 0000000000..fc5a721a15 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java ++++ b/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java +@@ -81,14 +92,24 @@ + } + + public static void throwItem(LivingEntity entity, ItemStack stack, Vec3 offset, Vec3 speedMultiplier, float yOffset) { +- double d = entity.getEyeY() - (double)yOffset; +- ItemEntity itemEntity = new ItemEntity(entity.level(), entity.getX(), d, entity.getZ(), stack); +- itemEntity.setThrower(entity); +- Vec3 vec3 = offset.subtract(entity.position()); +- vec3 = vec3.normalize().multiply(speedMultiplier.x, speedMultiplier.y, speedMultiplier.z); +- itemEntity.setDeltaMovement(vec3); +- itemEntity.setDefaultPickUpDelay(); +- entity.level().addFreshEntity(itemEntity); ++ if (stack.isEmpty()) return; // CraftBukkit - SPIGOT-4940: no empty loot ++ double d0 = entity.getEyeY() - (double) yOffset; ++ ItemEntity entityitem = new ItemEntity(entity.level(), entity.getX(), d0, entity.getZ(), stack); ++ ++ entityitem.setThrower(entity); ++ Vec3 vec3d2 = offset.subtract(entity.position()); ++ ++ vec3d2 = vec3d2.normalize().multiply(speedMultiplier.x, speedMultiplier.y, speedMultiplier.z); ++ entityitem.setDeltaMovement(vec3d2); ++ entityitem.setDefaultPickUpDelay(); ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(entity.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ entityitem.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ entity.level().addFreshEntity(entityitem); + } + + public static SectionPos findSectionClosestToVillage(ServerLevel serverLevel, SectionPos sectionPos, int radius) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java.patch new file mode 100644 index 0000000000..7dbdb7864e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java.patch @@ -0,0 +1,70 @@ +--- a/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java ++++ b/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java +@@ -16,35 +20,38 @@ + } + + public static BehaviorControl create(Predicate canWalkToItem, float speedModifier, boolean hasTarget, int maxDistToWalk) { +- return BehaviorBuilder.create( +- instance -> { +- BehaviorBuilder> behaviorBuilder = hasTarget +- ? instance.registered(MemoryModuleType.WALK_TARGET) +- : instance.absent(MemoryModuleType.WALK_TARGET); +- return instance.group( +- instance.registered(MemoryModuleType.LOOK_TARGET), +- behaviorBuilder, +- instance.present(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM), +- instance.registered(MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS) +- ) +- .apply( +- instance, +- (lookTarget, walkTarget, nearestVisibleWantedItem, itemPickupCooldownTicks) -> (level, entity, gameTime) -> { +- ItemEntity itemEntity = instance.get(nearestVisibleWantedItem); +- if (instance.tryGet(itemPickupCooldownTicks).isEmpty() +- && canWalkToItem.test(entity) +- && itemEntity.closerThan(entity, (double)maxDistToWalk) +- && entity.level().getWorldBorder().isWithinBounds(itemEntity.blockPosition())) { +- WalkTarget walkTarget1 = new WalkTarget(new EntityTracker(itemEntity, false), speedModifier, 0); +- lookTarget.set(new EntityTracker(itemEntity, true)); +- walkTarget.set(walkTarget1); +- return true; +- } else { +- return false; +- } ++ return BehaviorBuilder.create((behaviorbuilder_b) -> { ++ BehaviorBuilder> behaviorbuilder = hasTarget ? behaviorbuilder_b.registered(MemoryModuleType.WALK_TARGET) : behaviorbuilder_b.absent(MemoryModuleType.WALK_TARGET); ++ ++ return behaviorbuilder_b.group(behaviorbuilder_b.registered(MemoryModuleType.LOOK_TARGET), behaviorbuilder, behaviorbuilder_b.present(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM), behaviorbuilder_b.registered(MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS)).apply(behaviorbuilder_b, (memoryaccessor, memoryaccessor1, memoryaccessor2, memoryaccessor3) -> { ++ return (worldserver, entityliving, j) -> { ++ ItemEntity entityitem = (ItemEntity) behaviorbuilder_b.get(memoryaccessor2); ++ ++ if (behaviorbuilder_b.tryGet(memoryaccessor3).isEmpty() && canWalkToItem.test(entityliving) && entityitem.closerThan(entityliving, (double) maxDistToWalk) && entityliving.level().getWorldBorder().isWithinBounds(entityitem.blockPosition())) { ++ // CraftBukkit start ++ if (entityliving instanceof net.minecraft.world.entity.animal.allay.Allay) { ++ org.bukkit.event.entity.EntityTargetEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTargetEvent(entityliving, entityitem, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_ENTITY); ++ ++ if (event.isCancelled()) { ++ return false; + } +- ); +- } +- ); ++ if (!(event.getTarget() instanceof ItemEntity)) { ++ memoryaccessor2.erase(); ++ } ++ ++ entityitem = (ItemEntity) ((org.bukkit.craftbukkit.entity.CraftEntity) event.getTarget()).getHandle(); ++ } ++ // CraftBukkit end ++ WalkTarget memorytarget = new WalkTarget(new EntityTracker(entityitem, false), speedModifier, 0); ++ ++ memoryaccessor.set(new EntityTracker(entityitem, true)); ++ memoryaccessor1.set(memorytarget); ++ return true; ++ } else { ++ return false; ++ } ++ }; ++ }); ++ }); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java.patch new file mode 100644 index 0000000000..803d5c87b9 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java.patch @@ -0,0 +1,59 @@ +--- a/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java ++++ b/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java +@@ -19,10 +21,15 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.gameevent.GameEvent; ++ ++// CraftBukkit start ++import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.CropBlock; + import net.minecraft.world.level.block.FarmBlock; +-import net.minecraft.world.level.block.state.BlockState; +-import net.minecraft.world.level.gameevent.GameEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class HarvestFarmland extends Behavior { + private static final int HARVEST_DURATION = 200; +@@ -109,8 +105,11 @@ + BlockState blockState = level.getBlockState(this.aboveFarmlandPos); + Block block = blockState.getBlock(); + Block block1 = level.getBlockState(this.aboveFarmlandPos.below()).getBlock(); +- if (block instanceof CropBlock && ((CropBlock)block).isMaxAge(blockState)) { ++ ++ if (block instanceof CropBlock && ((CropBlock) block).isMaxAge(iblockdata)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(owner, this.aboveFarmlandPos, Blocks.AIR.defaultBlockState())) { // CraftBukkit + level.destroyBlock(this.aboveFarmlandPos, true, owner); ++ } // CraftBukkit + } + + if (blockState.isAir() && block1 instanceof FarmBlock && owner.hasFarmSeeds()) { +@@ -119,11 +118,20 @@ + for (int i = 0; i < inventory.getContainerSize(); i++) { + ItemStack item = inventory.getItem(i); + boolean flag = false; +- if (!item.isEmpty() && item.is(ItemTags.VILLAGER_PLANTABLE_SEEDS) && item.getItem() instanceof BlockItem blockItem) { +- BlockState blockState1 = blockItem.getBlock().defaultBlockState(); +- level.setBlockAndUpdate(this.aboveFarmlandPos, blockState1); +- level.gameEvent(GameEvent.BLOCK_PLACE, this.aboveFarmlandPos, GameEvent.Context.of(owner, blockState1)); +- flag = true; ++ ++ if (!itemstack.isEmpty() && itemstack.is(ItemTags.VILLAGER_PLANTABLE_SEEDS)) { ++ Item item = itemstack.getItem(); ++ ++ if (item instanceof BlockItem) { ++ BlockItem itemblock = (BlockItem) item; ++ IBlockData iblockdata1 = itemblock.getBlock().defaultBlockState(); ++ ++ if (CraftEventFactory.callEntityChangeBlockEvent(owner, this.aboveFarmlandPos, iblockdata1)) { // CraftBukkit ++ level.setBlockAndUpdate(this.aboveFarmlandPos, iblockdata1); ++ level.gameEvent(GameEvent.BLOCK_PLACE, this.aboveFarmlandPos, GameEvent.Context.of(owner, iblockdata1)); ++ flag = true; ++ } // CraftBukkit ++ } + } + + if (flag) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java.patch new file mode 100644 index 0000000000..ad54be668c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java.patch @@ -0,0 +1,134 @@ +--- a/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java ++++ b/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java +@@ -31,62 +33,78 @@ + private static final double MAX_DISTANCE_TO_HOLD_DOOR_OPEN_FOR_OTHER_MOBS = 2.0; + + public static BehaviorControl create() { +- MutableObject mutableObject = new MutableObject<>(null); +- MutableInt mutableInt = new MutableInt(0); +- return BehaviorBuilder.create( +- instance -> instance.group( +- instance.present(MemoryModuleType.PATH), +- instance.registered(MemoryModuleType.DOORS_TO_CLOSE), +- instance.registered(MemoryModuleType.NEAREST_LIVING_ENTITIES) +- ) +- .apply( +- instance, +- (navigationPath, doorsToClose, nearestLivingEntities) -> (level, entity, gameTime) -> { +- Path path = instance.get(navigationPath); +- Optional> optional = instance.tryGet(doorsToClose); +- if (!path.notStarted() && !path.isDone()) { +- if (Objects.equals(mutableObject.getValue(), path.getNextNode())) { +- mutableInt.setValue(20); +- } else if (mutableInt.decrementAndGet() > 0) { +- return false; +- } +- +- mutableObject.setValue(path.getNextNode()); +- Node previousNode = path.getPreviousNode(); +- Node nextNode = path.getNextNode(); +- BlockPos blockPos = previousNode.asBlockPos(); +- BlockState blockState = level.getBlockState(blockPos); +- if (blockState.is(BlockTags.WOODEN_DOORS, state -> state.getBlock() instanceof DoorBlock)) { +- DoorBlock doorBlock = (DoorBlock)blockState.getBlock(); +- if (!doorBlock.isOpen(blockState)) { +- doorBlock.setOpen(entity, level, blockState, blockPos, true); +- } +- +- optional = rememberDoorToClose(doorsToClose, optional, level, blockPos); +- } +- +- BlockPos blockPos1 = nextNode.asBlockPos(); +- BlockState blockState1 = level.getBlockState(blockPos1); +- if (blockState1.is(BlockTags.WOODEN_DOORS, state -> state.getBlock() instanceof DoorBlock)) { +- DoorBlock doorBlock1 = (DoorBlock)blockState1.getBlock(); +- if (!doorBlock1.isOpen(blockState1)) { +- doorBlock1.setOpen(entity, level, blockState1, blockPos1, true); +- optional = rememberDoorToClose(doorsToClose, optional, level, blockPos1); +- } +- } +- +- optional.ifPresent( +- doorPositions -> closeDoorsThatIHaveOpenedOrPassedThrough( +- level, entity, previousNode, nextNode, (Set)doorPositions, instance.tryGet(nearestLivingEntities) +- ) +- ); +- return true; +- } else { ++ MutableObject mutableobject = new MutableObject((Object) null); ++ MutableInt mutableint = new MutableInt(0); ++ ++ return BehaviorBuilder.create((behaviorbuilder_b) -> { ++ return behaviorbuilder_b.group(behaviorbuilder_b.present(MemoryModuleType.PATH), behaviorbuilder_b.registered(MemoryModuleType.DOORS_TO_CLOSE), behaviorbuilder_b.registered(MemoryModuleType.NEAREST_LIVING_ENTITIES)).apply(behaviorbuilder_b, (memoryaccessor, memoryaccessor1, memoryaccessor2) -> { ++ return (worldserver, entityliving, i) -> { ++ Path pathentity = (Path) behaviorbuilder_b.get(memoryaccessor); ++ Optional> optional = behaviorbuilder_b.tryGet(memoryaccessor1); ++ ++ if (!pathentity.notStarted() && !pathentity.isDone()) { ++ if (Objects.equals(mutableobject.getValue(), pathentity.getNextNode())) { ++ mutableint.setValue(20); ++ } else if (mutableint.decrementAndGet() > 0) { ++ return false; ++ } ++ ++ mutableobject.setValue(pathentity.getNextNode()); ++ Node pathpoint = pathentity.getPreviousNode(); ++ Node pathpoint1 = pathentity.getNextNode(); ++ BlockPos blockposition = pathpoint.asBlockPos(); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ ++ if (iblockdata.is(BlockTags.WOODEN_DOORS, (blockbase_blockdata) -> { ++ return blockbase_blockdata.getBlock() instanceof DoorBlock; ++ })) { ++ DoorBlock blockdoor = (DoorBlock) iblockdata.getBlock(); ++ ++ if (!blockdoor.isOpen(iblockdata)) { ++ // CraftBukkit start - entities opening doors ++ org.bukkit.event.entity.EntityInteractEvent event = new org.bukkit.event.entity.EntityInteractEvent(entityliving.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(entityliving.level(), blockposition)); ++ entityliving.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { + return false; + } ++ // CraftBukkit end ++ blockdoor.setOpen(entityliving, worldserver, iblockdata, blockposition, true); + } +- ) +- ); ++ ++ optional = rememberDoorToClose(memoryaccessor1, optional, worldserver, blockposition); ++ } ++ ++ BlockPos blockposition1 = pathpoint1.asBlockPos(); ++ IBlockData iblockdata1 = worldserver.getBlockState(blockposition1); ++ ++ if (iblockdata1.is(BlockTags.WOODEN_DOORS, (blockbase_blockdata) -> { ++ return blockbase_blockdata.getBlock() instanceof DoorBlock; ++ })) { ++ DoorBlock blockdoor1 = (DoorBlock) iblockdata1.getBlock(); ++ ++ if (!blockdoor1.isOpen(iblockdata1)) { ++ // CraftBukkit start - entities opening doors ++ org.bukkit.event.entity.EntityInteractEvent event = new org.bukkit.event.entity.EntityInteractEvent(entityliving.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(entityliving.level(), blockposition1)); ++ entityliving.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ blockdoor1.setOpen(entityliving, worldserver, iblockdata1, blockposition1, true); ++ optional = rememberDoorToClose(memoryaccessor1, optional, worldserver, blockposition1); ++ } ++ } ++ ++ optional.ifPresent((set) -> { ++ closeDoorsThatIHaveOpenedOrPassedThrough(worldserver, entityliving, pathpoint, pathpoint1, set, behaviorbuilder_b.tryGet(memoryaccessor2)); ++ }); ++ return true; ++ } else { ++ return false; ++ } ++ }; ++ }); ++ }); + } + + public static void closeDoorsThatIHaveOpenedOrPassedThrough( diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java.patch new file mode 100644 index 0000000000..3aef9ce46c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java ++++ b/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java +@@ -25,6 +30,10 @@ + import net.minecraft.world.level.pathfinder.Path; + import net.minecraft.world.level.pathfinder.WalkNodeEvaluator; + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end + + public class PrepareRamNearestTarget extends Behavior { + public static final int TIME_OUT_DURATION = 160; +@@ -71,10 +60,22 @@ + + @Override + protected void start(ServerLevel level, PathfinderMob entity, long gameTime) { +- Brain brain = entity.getBrain(); +- brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES) +- .flatMap(memory -> memory.findClosest(entity1 -> this.ramTargeting.test(entity, entity1))) +- .ifPresent(entity1 -> this.chooseRamPosition(entity, entity1)); ++ Brain behaviorcontroller = entity.getBrain(); ++ ++ behaviorcontroller.getMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES).flatMap((nearestvisiblelivingentities) -> { ++ return nearestvisiblelivingentities.findClosest((entityliving) -> { ++ return this.ramTargeting.test(entity, entityliving); ++ }); ++ }).ifPresent((entityliving) -> { ++ // CraftBukkit start ++ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entity, entityliving, (entityliving instanceof ServerPlayer) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.CLOSEST_ENTITY); ++ if (event.isCancelled() || event.getTarget() == null) { ++ return; ++ } ++ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ // CraftBukkit end ++ this.chooseRamPosition(entity, entityliving); ++ }); + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/ResetProfession.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/ResetProfession.java.patch new file mode 100644 index 0000000000..25e3b3da22 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/ResetProfession.java.patch @@ -0,0 +1,57 @@ +--- a/net/minecraft/world/entity/ai/behavior/ResetProfession.java ++++ b/net/minecraft/world/entity/ai/behavior/ResetProfession.java +@@ -8,26 +6,35 @@ + import net.minecraft.world.entity.npc.VillagerData; + import net.minecraft.world.entity.npc.VillagerProfession; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftVillager; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.VillagerCareerChangeEvent; ++// CraftBukkit end ++ + public class ResetProfession { + public static BehaviorControl create() { +- return BehaviorBuilder.create( +- instance -> instance.group(instance.absent(MemoryModuleType.JOB_SITE)) +- .apply( +- instance, +- jobSite -> (level, villager, gameTime) -> { +- VillagerData villagerData = villager.getVillagerData(); +- if (villagerData.getProfession() != VillagerProfession.NONE +- && villagerData.getProfession() != VillagerProfession.NITWIT +- && villager.getVillagerXp() == 0 +- && villagerData.getLevel() <= 1) { +- villager.setVillagerData(villager.getVillagerData().setProfession(VillagerProfession.NONE)); +- villager.refreshBrain(level); +- return true; +- } else { +- return false; +- } +- } +- ) +- ); ++ return BehaviorBuilder.create((behaviorbuilder_b) -> { ++ return behaviorbuilder_b.group(behaviorbuilder_b.absent(MemoryModuleType.JOB_SITE)).apply(behaviorbuilder_b, (memoryaccessor) -> { ++ return (worldserver, entityvillager, i) -> { ++ VillagerData villagerdata = entityvillager.getVillagerData(); ++ ++ if (villagerdata.getProfession() != VillagerProfession.NONE && villagerdata.getProfession() != VillagerProfession.NITWIT && entityvillager.getVillagerXp() == 0 && villagerdata.getLevel() <= 1) { ++ // CraftBukkit start ++ VillagerCareerChangeEvent event = CraftEventFactory.callVillagerCareerChangeEvent(entityvillager, CraftVillager.CraftProfession.minecraftToBukkit(VillagerProfession.NONE), VillagerCareerChangeEvent.ChangeReason.LOSING_JOB); ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ entityvillager.setVillagerData(entityvillager.getVillagerData().setProfession(CraftVillager.CraftProfession.bukkitToMinecraft(event.getProfession()))); ++ // CraftBukkit end ++ entityvillager.refreshBrain(worldserver); ++ return true; ++ } else { ++ return false; ++ } ++ }; ++ }); ++ }); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/StartAttacking.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/StartAttacking.java.patch new file mode 100644 index 0000000000..0a8ebe023a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/StartAttacking.java.patch @@ -0,0 +1,41 @@ +--- a/net/minecraft/world/entity/ai/behavior/StartAttacking.java ++++ b/net/minecraft/world/entity/ai/behavior/StartAttacking.java +@@ -9,6 +8,10 @@ + import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder; + import net.minecraft.world.entity.ai.behavior.declarative.MemoryAccessor; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end + + public class StartAttacking { + public static BehaviorControl create(Function> targetFinder) { +@@ -22,8 +40,9 @@ + if (!canAttack.test(mob)) { + return false; + } else { +- Optional optional = targetFinder.apply(mob); +- if (optional.isEmpty()) { ++ // CraftBukkit start ++ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entityinsentient, entityliving, (entityliving instanceof ServerPlayer) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.CLOSEST_ENTITY); ++ if (event.isCancelled()) { + return false; + } else { + LivingEntity livingEntity = optional.get(); +@@ -35,6 +45,15 @@ + return true; + } + } ++ if (event.getTarget() == null) { ++ memoryaccessor.erase(); ++ return true; ++ } ++ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ // CraftBukkit end ++ memoryaccessor.set(entityliving); ++ memoryaccessor1.erase(); ++ return true; + } + }) + ); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java.patch new file mode 100644 index 0000000000..9e38734ea7 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java.patch @@ -0,0 +1,73 @@ +--- a/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java ++++ b/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java +@@ -10,6 +8,12 @@ + import net.minecraft.world.entity.ai.behavior.declarative.MemoryAccessor; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end ++ + public class StopAttackingIfTargetInvalid { + private static final int TIMEOUT_TO_GET_WITHIN_ATTACK_RANGE = 200; + +@@ -27,29 +38,34 @@ + }, true); + } + +- public static BehaviorControl create( +- Predicate canStopAttacking, BiConsumer onStopAttacking, boolean canGrowTiredOfTryingToReachTarget +- ) { +- return BehaviorBuilder.create( +- instance -> instance.group(instance.present(MemoryModuleType.ATTACK_TARGET), instance.registered(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)) +- .apply( +- instance, +- (attackTarget, cantReachWalkTargetSince) -> (level, mob, gameTime) -> { +- LivingEntity livingEntity = instance.get(attackTarget); +- if (mob.canAttack(livingEntity) +- && (!canGrowTiredOfTryingToReachTarget || !isTiredOfTryingToReachTarget(mob, instance.tryGet(cantReachWalkTargetSince))) +- && livingEntity.isAlive() +- && livingEntity.level() == mob.level() +- && !canStopAttacking.test(livingEntity)) { +- return true; +- } else { +- onStopAttacking.accept(mob, livingEntity); +- attackTarget.erase(); +- return true; +- } +- } +- ) +- ); ++ public static BehaviorControl create(Predicate canStopAttacking, BiConsumer onStopAttacking, boolean canGrowTiredOfTryingToReachTarget) { ++ return BehaviorBuilder.create((behaviorbuilder_b) -> { ++ return behaviorbuilder_b.group(behaviorbuilder_b.present(MemoryModuleType.ATTACK_TARGET), behaviorbuilder_b.registered(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)).apply(behaviorbuilder_b, (memoryaccessor, memoryaccessor1) -> { ++ return (worldserver, entityinsentient, i) -> { ++ LivingEntity entityliving = (LivingEntity) behaviorbuilder_b.get(memoryaccessor); ++ ++ if (entityinsentient.canAttack(entityliving) && (!canGrowTiredOfTryingToReachTarget || !isTiredOfTryingToReachTarget(entityinsentient, behaviorbuilder_b.tryGet(memoryaccessor1))) && entityliving.isAlive() && entityliving.level() == entityinsentient.level() && !canStopAttacking.test(entityliving)) { ++ return true; ++ } else { ++ // CraftBukkit start ++ LivingEntity old = entityinsentient.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); ++ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entityinsentient, null, (old != null && !old.isAlive()) ? EntityTargetEvent.TargetReason.TARGET_DIED : EntityTargetEvent.TargetReason.FORGOT_TARGET); ++ if (event.isCancelled()) { ++ return false; ++ } ++ if (event.getTarget() == null) { ++ memoryaccessor.erase(); ++ return true; ++ } ++ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ // CraftBukkit end ++ onStopAttacking.accept(entityinsentient, entityliving); ++ memoryaccessor.erase(); ++ return true; ++ } ++ }; ++ }); ++ }); + } + + private static boolean isTiredOfTryingToReachTarget(LivingEntity entity, Optional timeSinceInvalidTarget) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java.patch new file mode 100644 index 0000000000..df807a5849 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java ++++ b/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java +@@ -16,6 +17,10 @@ + import net.minecraft.world.entity.ai.village.poi.PoiTypes; + import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.level.pathfinder.Path; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++// CraftBukkit end + + public class VillagerMakeLove extends Behavior { + private static final int INTERACT_DIST_SQR = 5; +@@ -113,13 +120,19 @@ + if (breedOffspring == null) { + return Optional.empty(); + } else { ++ entityvillager2.setAge(-24000); ++ entityvillager2.moveTo(parent.getX(), parent.getY(), parent.getZ(), 0.0F, 0.0F); ++ // CraftBukkit start - call EntityBreedEvent ++ if (CraftEventFactory.callEntityBreedEvent(entityvillager2, parent, partner, null, null, 0).isCancelled()) { ++ return Optional.empty(); ++ } ++ // Move age setting down + parent.setAge(6000); + partner.setAge(6000); +- breedOffspring.setAge(-24000); +- breedOffspring.moveTo(parent.getX(), parent.getY(), parent.getZ(), 0.0F, 0.0F); +- level.addFreshEntityWithPassengers(breedOffspring); +- level.broadcastEntityEvent(breedOffspring, (byte)12); +- return Optional.of(breedOffspring); ++ level.addFreshEntityWithPassengers(entityvillager2, CreatureSpawnEvent.SpawnReason.BREEDING); ++ // CraftBukkit end ++ level.broadcastEntityEvent(entityvillager2, (byte) 12); ++ return Optional.of(entityvillager2); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java.patch new file mode 100644 index 0000000000..099dd811ea --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java ++++ b/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java +@@ -73,6 +71,12 @@ + } + + if (this.breakTime == this.getDoorBreakTime() && this.isValidDifficulty(this.mob.level().getDifficulty())) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreakDoorEvent(this.mob, this.doorPos).isCancelled()) { ++ this.start(); ++ return; ++ } ++ // CraftBukkit end + this.mob.level().removeBlock(this.doorPos, false); + this.mob.level().levelEvent(1021, this.doorPos, 0); + this.mob.level().levelEvent(2001, this.doorPos, Block.getId(this.mob.level().getBlockState(this.doorPos))); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/EatBlockGoal.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/EatBlockGoal.java.patch new file mode 100644 index 0000000000..d0cc4e84a3 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/EatBlockGoal.java.patch @@ -0,0 +1,44 @@ +--- a/net/minecraft/world/entity/ai/goal/EatBlockGoal.java ++++ b/net/minecraft/world/entity/ai/goal/EatBlockGoal.java +@@ -11,6 +11,10 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.block.state.predicate.BlockStatePredicate; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class EatBlockGoal extends Goal { + private static final int EAT_ANIMATION_TICKS = 40; + private static final Predicate IS_TALL_GRASS = BlockStatePredicate.forBlock(Blocks.SHORT_GRASS); +@@ -59,19 +65,21 @@ + public void tick() { + this.eatAnimationTick = Math.max(0, this.eatAnimationTick - 1); + if (this.eatAnimationTick == this.adjustedTickDelay(4)) { +- BlockPos blockPos = this.mob.blockPosition(); +- if (IS_TALL_GRASS.test(this.level.getBlockState(blockPos))) { +- if (this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- this.level.destroyBlock(blockPos, false); ++ BlockPos blockposition = this.mob.blockPosition(); ++ ++ if (EatBlockGoal.IS_TALL_GRASS.test(this.level.getBlockState(blockposition))) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition, Blocks.AIR.defaultBlockState(), !this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit ++ this.level.destroyBlock(blockposition, false); + } + + this.mob.ate(); + } else { +- BlockPos blockPos1 = blockPos.below(); +- if (this.level.getBlockState(blockPos1).is(Blocks.GRASS_BLOCK)) { +- if (this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- this.level.levelEvent(2001, blockPos1, Block.getId(Blocks.GRASS_BLOCK.defaultBlockState())); +- this.level.setBlock(blockPos1, Blocks.DIRT.defaultBlockState(), 2); ++ BlockPos blockposition1 = blockposition.below(); ++ ++ if (this.level.getBlockState(blockposition1).is(Blocks.GRASS_BLOCK)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition1, Blocks.AIR.defaultBlockState(), !this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit ++ this.level.levelEvent(2001, blockposition1, Block.getId(Blocks.GRASS_BLOCK.defaultBlockState())); ++ this.level.setBlock(blockposition1, Blocks.DIRT.defaultBlockState(), 2); + } + + this.mob.ate(); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java.patch new file mode 100644 index 0000000000..14d66ab275 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java ++++ b/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java +@@ -12,6 +13,11 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.level.pathfinder.WalkNodeEvaluator; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTeleportEvent; ++// CraftBukkit end + + public class FollowOwnerGoal extends Goal { + public static final int TELEPORT_WHEN_DISTANCE_IS = 12; +@@ -118,7 +127,14 @@ + } else if (!this.canTeleportTo(new BlockPos(x, y, z))) { + return false; + } else { +- this.tamable.moveTo((double)x + 0.5, (double)y, (double)z + 0.5, this.tamable.getYRot(), this.tamable.getXRot()); ++ // CraftBukkit start ++ EntityTeleportEvent event = CraftEventFactory.callEntityTeleportEvent(this.tamable, (double) x + 0.5D, (double) y, (double) z + 0.5D); ++ if (event.isCancelled()) { ++ return false; ++ } ++ Location to = event.getTo(); ++ this.tamable.moveTo(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch()); ++ // CraftBukkit end + this.navigation.stop(); + return true; + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java.patch new file mode 100644 index 0000000000..ccacbd0a95 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java.patch @@ -0,0 +1,51 @@ +--- a/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java ++++ b/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java +@@ -20,6 +20,10 @@ + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class RemoveBlockGoal extends MoveToBlockGoal { + private final Block blockToRemove; +@@ -104,24 +100,19 @@ + } + + if (this.ticksSinceReachedGoal > 60) { +- level.removeBlock(posWithBlock, false); +- if (!level.isClientSide) { +- for (int i = 0; i < 20; i++) { +- double d = random.nextGaussian() * 0.02; +- double d1 = random.nextGaussian() * 0.02; +- double d2 = random.nextGaussian() * 0.02; +- ((ServerLevel)level) +- .sendParticles( +- ParticleTypes.POOF, +- (double)posWithBlock.getX() + 0.5, +- (double)posWithBlock.getY(), +- (double)posWithBlock.getZ() + 0.5, +- 1, +- d, +- d1, +- d2, +- 0.15F +- ); ++ // CraftBukkit start - Step on eggs ++ if (!CraftEventFactory.callEntityInteractEvent(this.removerMob, CraftBlock.at(world, blockposition1))) { ++ return; ++ } ++ // CraftBukkit end ++ world.removeBlock(blockposition1, false); ++ if (!world.isClientSide) { ++ for (int i = 0; i < 20; ++i) { ++ d0 = randomsource.nextGaussian() * 0.02D; ++ double d1 = randomsource.nextGaussian() * 0.02D; ++ double d2 = randomsource.nextGaussian() * 0.02D; ++ ++ ((ServerLevel) world).sendParticles(ParticleTypes.POOF, (double) blockposition1.getX() + 0.5D, (double) blockposition1.getY(), (double) blockposition1.getZ() + 0.5D, 1, d0, d1, d2, 0.15000000596046448D); + } + + this.playBreakSound(level, posWithBlock); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java.patch new file mode 100644 index 0000000000..b3a0825d6b --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java.patch @@ -0,0 +1,32 @@ +--- a/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java ++++ b/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java +@@ -6,6 +6,10 @@ + import net.minecraft.world.entity.animal.horse.AbstractHorse; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class RunAroundLikeCrazyGoal extends Goal { + private final AbstractHorse horse; +@@ -55,11 +62,13 @@ + return; + } + +- if (firstPassenger instanceof Player player) { +- int temper = this.horse.getTemper(); +- int maxTemper = this.horse.getMaxTemper(); +- if (maxTemper > 0 && this.horse.getRandom().nextInt(maxTemper) < temper) { +- this.horse.tameWithName(player); ++ if (entity instanceof Player) { ++ Player entityhuman = (Player) entity; ++ int i = this.horse.getTemper(); ++ int j = this.horse.getMaxTemper(); ++ ++ if (j > 0 && this.horse.getRandom().nextInt(j) < i && !CraftEventFactory.callEntityTameEvent(this.horse, ((CraftHumanEntity) this.horse.getBukkitEntity().getPassenger()).getHandle()).isCancelled()) { // CraftBukkit - fire EntityTameEvent ++ this.horse.tameWithName(entityhuman); + return; + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java.patch new file mode 100644 index 0000000000..56c93d0edc --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java ++++ b/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java +@@ -20,7 +22,7 @@ + @Override + public boolean canUse() { + if (!this.mob.isTame()) { +- return false; ++ return this.mob.isOrderedToSit() && this.mob.getTarget() == null; // CraftBukkit - Allow sitting for wild animals + } else if (this.mob.isInWaterOrBubble()) { + return false; + } else if (!this.mob.onGround()) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/TemptGoal.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/TemptGoal.java.patch new file mode 100644 index 0000000000..2630595259 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/goal/TemptGoal.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/entity/ai/goal/TemptGoal.java ++++ b/net/minecraft/world/entity/ai/goal/TemptGoal.java +@@ -7,6 +7,12 @@ + import net.minecraft.world.entity.ai.targeting.TargetingConditions; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.crafting.Ingredient; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++// CraftBukkit end + + public class TemptGoal extends Goal { + private static final TargetingConditions TEMP_TARGETING = TargetingConditions.forNonCombat().range(10.0).ignoreLineOfSight(); +@@ -19,7 +26,7 @@ + private double pRotX; + private double pRotY; + @Nullable +- protected Player player; ++ protected LivingEntity player; // CraftBukkit + private int calmDown; + private boolean isRunning; + private final Ingredient items; +@@ -41,6 +48,15 @@ + return false; + } else { + this.player = this.mob.level().getNearestPlayer(this.targetingConditions, this.mob); ++ // CraftBukkit start ++ if (this.player != null) { ++ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(this.mob, this.player, EntityTargetEvent.TargetReason.TEMPT); ++ if (event.isCancelled()) { ++ return false; ++ } ++ this.player = (event.getTarget() == null) ? null : ((CraftLivingEntity) event.getTarget()).getHandle(); ++ } ++ // CraftBukkit end + return this.player != null; + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/sensing/TemptingSensor.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/sensing/TemptingSensor.java.patch new file mode 100644 index 0000000000..5dfbcde9c3 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/sensing/TemptingSensor.java.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/world/entity/ai/sensing/TemptingSensor.java ++++ b/net/minecraft/world/entity/ai/sensing/TemptingSensor.java +@@ -15,6 +17,13 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.crafting.Ingredient; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++// CraftBukkit end + + public class TemptingSensor extends Sensor { + public static final int TEMPTATION_RANGE = 10; +@@ -38,8 +49,19 @@ + .sorted(Comparator.comparingDouble(entity::distanceToSqr)) + .collect(Collectors.toList()); + if (!list.isEmpty()) { +- Player player = list.get(0); +- brain.setMemory(MemoryModuleType.TEMPTING_PLAYER, player); ++ Player entityhuman = (Player) list.get(0); ++ ++ // CraftBukkit start ++ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(entity, entityhuman, EntityTargetEvent.TargetReason.TEMPT); ++ if (event.isCancelled()) { ++ return; ++ } ++ if (event.getTarget() instanceof HumanEntity) { ++ behaviorcontroller.setMemory(MemoryModuleType.TEMPTING_PLAYER, ((CraftHumanEntity) event.getTarget()).getHandle()); ++ } else { ++ behaviorcontroller.eraseMemory(MemoryModuleType.TEMPTING_PLAYER); ++ } ++ // CraftBukkit end + } else { + brain.eraseMemory(MemoryModuleType.TEMPTING_PLAYER); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/village/VillageSiege.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/village/VillageSiege.java.patch new file mode 100644 index 0000000000..0ec3865e87 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ai/village/VillageSiege.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/entity/ai/village/VillageSiege.java ++++ b/net/minecraft/world/entity/ai/village/VillageSiege.java +@@ -104,8 +121,8 @@ + return; + } + +- zombie.moveTo(vec3.x, vec3.y, vec3.z, level.random.nextFloat() * 360.0F, 0.0F); +- level.addFreshEntityWithPassengers(zombie); ++ entityzombie.moveTo(vec3d.x, vec3d.y, vec3d.z, level.random.nextFloat() * 360.0F, 0.0F); ++ level.addFreshEntityWithPassengers(entityzombie, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_INVASION); // CraftBukkit + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ambient/Bat.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ambient/Bat.java.patch new file mode 100644 index 0000000000..450a695e17 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/ambient/Bat.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/world/entity/ambient/Bat.java ++++ b/net/minecraft/world/entity/ambient/Bat.java +@@ -27,6 +28,9 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class Bat extends AmbientCreature { + public static final float FLAP_LENGTH_SECONDS = 0.5F; +@@ -138,13 +146,13 @@ + this.yHeadRot = (float)this.random.nextInt(360); + } + +- if (this.level().getNearestPlayer(BAT_RESTING_TARGETING, this) != null) { ++ if (this.level().getNearestPlayer(Bat.BAT_RESTING_TARGETING, this) != null && CraftEventFactory.handleBatToggleSleepEvent(this, true)) { // CraftBukkit - Call BatToggleSleepEvent + this.setResting(false); + if (!isSilent) { + this.level().levelEvent(null, 1025, blockPos, 0); + } + } +- } else { ++ } else if (CraftEventFactory.handleBatToggleSleepEvent(this, true)) { // CraftBukkit - Call BatToggleSleepEvent + this.setResting(false); + if (!isSilent) { + this.level().levelEvent(null, 1025, blockPos, 0); +@@ -178,7 +179,7 @@ + float f1 = Mth.wrapDegrees(f - this.getYRot()); + this.zza = 0.5F; + this.setYRot(this.getYRot() + f1); +- if (this.random.nextInt(100) == 0 && this.level().getBlockState(blockPos1).isRedstoneConductor(this.level(), blockPos1)) { ++ if (this.random.nextInt(100) == 0 && this.level().getBlockState(blockposition1).isRedstoneConductor(this.level(), blockposition1) && CraftEventFactory.handleBatToggleSleepEvent(this, false)) { // CraftBukkit - Call BatToggleSleepEvent + this.setResting(true); + } + } +@@ -203,7 +204,7 @@ + if (this.isInvulnerableTo(source)) { + return false; + } else { +- if (!this.level().isClientSide && this.isResting()) { ++ if (!this.level().isClientSide && this.isResting() && CraftEventFactory.handleBatToggleSleepEvent(this, true)) { // CraftBukkit - Call BatToggleSleepEvent + this.setResting(false); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Animal.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Animal.java.patch new file mode 100644 index 0000000000..f5e68c0a52 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Animal.java.patch @@ -0,0 +1,121 @@ +--- a/net/minecraft/world/entity/animal/Animal.java ++++ b/net/minecraft/world/entity/animal/Animal.java +@@ -29,12 +29,18 @@ + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.pathfinder.BlockPathTypes; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityBreedEvent; ++import org.bukkit.event.entity.EntityEnterLoveModeEvent; ++// CraftBukkit end + + public abstract class Animal extends AgeableMob { + protected static final int PARENT_AGE_AFTER_BREEDING = 6000; + private int inLove; + @Nullable +- private UUID loveCause; ++ public UUID loveCause; ++ public ItemStack breedItem; // CraftBukkit - Add breedItem variable + + protected Animal(EntityType entityType, Level level) { + super(entityType, level); +@@ -74,8 +83,13 @@ + if (this.isInvulnerableTo(source)) { + return false; + } else { ++ // CraftBukkit start ++ boolean result = super.hurt(source, amount); ++ if (result) { + this.inLove = 0; +- return super.hurt(source, amount); ++ } ++ return result; ++ // CraftBukkit end + } + } + +@@ -166,10 +183,17 @@ + } + + public void setInLove(@Nullable Player player) { +- this.inLove = 600; ++ // CraftBukkit start ++ EntityEnterLoveModeEvent entityEnterLoveModeEvent = CraftEventFactory.callEntityEnterLoveModeEvent(player, this, 600); ++ if (entityEnterLoveModeEvent.isCancelled()) { ++ return; ++ } ++ this.inLove = entityEnterLoveModeEvent.getTicksInLove(); ++ // CraftBukkit end + if (player != null) { + this.loveCause = player.getUUID(); + } ++ this.breedItem = player.getInventory().getSelected(); // CraftBukkit + + this.level().broadcastEntityEvent(this, (byte)18); + } +@@ -205,27 +230,51 @@ + } + + public void spawnChildFromBreeding(ServerLevel level, Animal mate) { +- AgeableMob breedOffspring = this.getBreedOffspring(level, mate); +- if (breedOffspring != null) { +- breedOffspring.setBaby(true); +- breedOffspring.moveTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F); +- this.finalizeSpawnChildFromBreeding(level, mate, breedOffspring); +- level.addFreshEntityWithPassengers(breedOffspring); ++ AgeableMob entityageable = this.getBreedOffspring(level, mate); ++ ++ if (entityageable != null) { ++ entityageable.setBaby(true); ++ entityageable.moveTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F); ++ // CraftBukkit start - call EntityBreedEvent ++ ServerPlayer breeder = Optional.ofNullable(this.getLoveCause()).or(() -> { ++ return Optional.ofNullable(mate.getLoveCause()); ++ }).orElse(null); ++ int experience = this.getRandom().nextInt(7) + 1; ++ EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(entityageable, this, mate, breeder, this.breedItem, experience); ++ if (entityBreedEvent.isCancelled()) { ++ return; ++ } ++ experience = entityBreedEvent.getExperience(); ++ this.finalizeSpawnChildFromBreeding(level, mate, entityageable, experience); ++ level.addFreshEntityWithPassengers(entityageable, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); ++ // CraftBukkit end + } + } + + public void finalizeSpawnChildFromBreeding(ServerLevel level, Animal animal, @Nullable AgeableMob baby) { +- Optional.ofNullable(this.getLoveCause()).or(() -> Optional.ofNullable(animal.getLoveCause())).ifPresent(player -> { +- player.awardStat(Stats.ANIMALS_BRED); +- CriteriaTriggers.BRED_ANIMALS.trigger(player, this, animal, baby); ++ // CraftBukkit start ++ this.finalizeSpawnChildFromBreeding(level, animal, baby, this.getRandom().nextInt(7) + 1); ++ } ++ ++ public void finalizeSpawnChildFromBreeding(ServerLevel worldserver, Animal entityanimal, @Nullable AgeableMob entityageable, int experience) { ++ // CraftBukkit end ++ Optional.ofNullable(this.getLoveCause()).or(() -> { ++ return Optional.ofNullable(entityanimal.getLoveCause()); ++ }).ifPresent((entityplayer) -> { ++ entityplayer.awardStat(Stats.ANIMALS_BRED); ++ CriteriaTriggers.BRED_ANIMALS.trigger(entityplayer, this, entityanimal, entityageable); + }); + this.setAge(6000); + animal.setAge(6000); + this.resetLove(); +- animal.resetLove(); +- level.broadcastEntityEvent(this, (byte)18); +- if (level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +- level.addFreshEntity(new ExperienceOrb(level, this.getX(), this.getY(), this.getZ(), this.getRandom().nextInt(7) + 1)); ++ entityanimal.resetLove(); ++ worldserver.broadcastEntityEvent(this, (byte) 18); ++ if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { ++ // CraftBukkit start - use event experience ++ if (experience > 0) { ++ worldserver.addFreshEntity(new ExperienceOrb(worldserver, this.getX(), this.getY(), this.getZ(), experience)); ++ } ++ // CraftBukkit end + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Bee.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Bee.java.patch new file mode 100644 index 0000000000..26d2dc069c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Bee.java.patch @@ -0,0 +1,128 @@ +--- a/net/minecraft/world/entity/animal/Bee.java ++++ b/net/minecraft/world/entity/animal/Bee.java +@@ -88,6 +89,11 @@ + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.level.pathfinder.Path; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityPotionEffectEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end + + public class Bee extends Animal implements NeutralMob, FlyingAnimal { + public static final float FLAP_DEGREES_PER_TICK = 120.32113F; +@@ -184,13 +192,20 @@ + + @Override + public void addAdditionalSaveData(CompoundTag compound) { +- super.addAdditionalSaveData(compound); +- if (this.hasHive()) { +- compound.put("HivePos", NbtUtils.writeBlockPos(this.getHivePos())); ++ // CraftBukkit start - selectively save data ++ addAdditionalSaveData(compound, true); ++ } ++ ++ @Override ++ public void addAdditionalSaveData(CompoundTag nbttagcompound, boolean includeAll) { ++ // CraftBukkit end ++ super.addAdditionalSaveData(nbttagcompound); ++ if (includeAll && this.hasHive()) { // CraftBukkit - selectively save hive ++ nbttagcompound.put("HivePos", NbtUtils.writeBlockPos(this.getHivePos())); + } + +- if (this.hasSavedFlowerPos()) { +- compound.put("FlowerPos", NbtUtils.writeBlockPos(this.getSavedFlowerPos())); ++ if (includeAll && this.hasSavedFlowerPos()) { // CraftBukkit - selectively save flower ++ nbttagcompound.put("FlowerPos", NbtUtils.writeBlockPos(this.getSavedFlowerPos())); + } + + compound.putBoolean("HasNectar", this.hasNectar()); +@@ -236,8 +253,8 @@ + i = 18; + } + +- if (i > 0) { +- ((LivingEntity)entity).addEffect(new MobEffectInstance(MobEffects.POISON, i * 20, 0), this); ++ if (b0 > 0) { ++ ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.POISON, b0 * 20, 0), this, EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + +@@ -632,11 +652,14 @@ + if (this.isInvulnerableTo(source)) { + return false; + } else { +- if (!this.level().isClientSide) { ++ // CraftBukkit start - Only stop pollinating if entity was damaged ++ boolean result = super.hurt(source, amount); ++ if (result && !this.level().isClientSide) { ++ // CraftBukkit end + this.beePollinateGoal.stopPollinating(); + } + +- return super.hurt(source, amount); ++ return result; // CraftBukkit + } + } + +@@ -760,7 +1013,10 @@ + private int ticksStuck; + + BeeGoToHiveGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ super(); ++ this.travellingTicks = Bee.this.random.nextInt(10); // CraftBukkit - SPIGOT-7495: Give Bees another chance and let them use their own random, avoid concurrency issues ++ this.blacklistedTargets = Lists.newArrayList(); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +@@ -873,7 +1130,9 @@ + int travellingTicks = Bee.this.level().random.nextInt(10); + + BeeGoToKnownFlowerGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ super(); ++ this.travellingTicks = Bee.this.random.nextInt(10); // CraftBukkit - SPIGOT-7495: Give Bees another chance and let them use their own random, avoid concurrency issues ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +@@ -965,9 +1231,9 @@ + ((BonemealableBlock)blockState.getBlock()).performBonemeal((ServerLevel)Bee.this.level(), Bee.this.random, blockPos, blockState); + } + +- if (blockState1 != null) { +- Bee.this.level().levelEvent(2005, blockPos, 0); +- Bee.this.level().setBlockAndUpdate(blockPos, blockState1); ++ if (iblockdata1 != null && CraftEventFactory.callEntityChangeBlockEvent(Bee.this, blockposition, iblockdata1)) { // CraftBukkit ++ Bee.this.level().levelEvent(2005, blockposition, 0); ++ Bee.this.level().setBlockAndUpdate(blockposition, iblockdata1); + Bee.this.incrementNumCropsGrownSincePollination(); + } + } +@@ -1105,20 +1302,9 @@ + } + + @Override +- public boolean canBeeContinueToUse() { +- if (!this.pollinating) { +- return false; +- } else if (!Bee.this.hasSavedFlowerPos()) { +- return false; +- } else if (Bee.this.level().isRaining()) { +- return false; +- } else if (this.hasPollinatedLongEnough()) { +- return Bee.this.random.nextFloat() < 0.2F; +- } else if (Bee.this.tickCount % 20 == 0 && !Bee.this.isFlowerValid(Bee.this.savedFlowerPos)) { +- Bee.this.savedFlowerPos = null; +- return false; +- } else { +- return true; ++ protected void alertOther(Mob mob, LivingEntity target) { ++ if (mob instanceof Bee && this.mob.hasLineOfSight(target)) { ++ mob.setTarget(target, EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY, true); // CraftBukkit - reason + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Bucketable.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Bucketable.java.patch new file mode 100644 index 0000000000..c8e76a8437 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Bucketable.java.patch @@ -0,0 +1,52 @@ +--- a/net/minecraft/world/entity/animal/Bucketable.java ++++ b/net/minecraft/world/entity/animal/Bucketable.java +@@ -14,6 +15,10 @@ + import net.minecraft.world.item.ItemUtils; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerBucketEntityEvent; ++// CraftBukkit end + + public interface Bucketable { + boolean fromBucket(); +@@ -85,18 +95,27 @@ + } + } + +- static Optional bucketMobPickup(Player player, InteractionHand hand, T entity) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (itemInHand.getItem() == Items.WATER_BUCKET && entity.isAlive()) { +- entity.playSound(entity.getPickupSound(), 1.0F, 1.0F); +- ItemStack bucketItemStack = entity.getBucketItemStack(); +- entity.saveToBucketTag(bucketItemStack); +- ItemStack itemStack = ItemUtils.createFilledResult(itemInHand, player, bucketItemStack, false); +- player.setItemInHand(hand, itemStack); +- Level level = entity.level(); +- if (!level.isClientSide) { +- CriteriaTriggers.FILLED_BUCKET.trigger((ServerPlayer)player, bucketItemStack); ++ static Optional bucketMobPickup(Player player, EnumHand hand, T entity) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (itemstack.getItem() == Items.WATER_BUCKET && entity.isAlive()) { ++ // CraftBukkit start ++ // t0.playSound(((Bucketable) t0).getPickupSound(), 1.0F, 1.0F); // CraftBukkit - moved down ++ ItemStack itemstack1 = ((Bucketable) entity).getBucketItemStack(); ++ ++ ((Bucketable) entity).saveToBucketTag(itemstack1); ++ ++ PlayerBucketEntityEvent playerBucketFishEvent = CraftEventFactory.callPlayerFishBucketEvent(entity, player, itemstack, itemstack1, hand); ++ itemstack1 = CraftItemStack.asNMSCopy(playerBucketFishEvent.getEntityBucket()); ++ if (playerBucketFishEvent.isCancelled()) { ++ ((ServerPlayer) player).containerMenu.sendAllDataToRemote(); // We need to update inventory to resync client's bucket ++ ((ServerPlayer) player).connection.send(new ClientboundAddEntityPacket(entity)); // We need to play out these packets as the client assumes the fish is gone ++ entity.getEntityData().refresh((ServerPlayer) player); // Need to send data such as the display name to client ++ return Optional.of(InteractionResult.FAIL); + } ++ entity.playSound(((Bucketable) entity).getPickupSound(), 1.0F, 1.0F); ++ // CraftBukkit end ++ ItemStack itemstack2 = ItemUtils.createFilledResult(itemstack, player, itemstack1, false); + + entity.discard(); + return Optional.of(InteractionResult.sidedSuccess(level.isClientSide)); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Cat.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Cat.java.patch new file mode 100644 index 0000000000..65713dfd29 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Cat.java.patch @@ -0,0 +1,66 @@ +--- a/net/minecraft/world/entity/animal/Cat.java ++++ b/net/minecraft/world/entity/animal/Cat.java +@@ -402,9 +411,9 @@ + return InteractionResult.CONSUME; + } + } +- } else if (this.isFood(itemInHand)) { +- this.usePlayerItem(player, hand, itemInHand); +- if (this.random.nextInt(3) == 0) { ++ } else if (this.isFood(itemstack)) { ++ this.usePlayerItem(player, hand, itemstack); ++ if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit + this.tame(player); + this.setOrderedToSit(true); + this.level().broadcastEntityEvent(this, (byte)7); +@@ -462,7 +472,10 @@ + return new Vector3f(0.0F, entityDimensions.height - 0.1875F * f, 0.0F); + } + +- static class CatAvoidEntityGoal extends AvoidEntityGoal { ++ private static class CatTemptGoal extends TemptGoal { ++ ++ @Nullable ++ private LivingEntity selectedPlayer; // CraftBukkit + private final Cat cat; + + public CatAvoidEntityGoal(Cat cat, Class entityClassToAvoid, float maxDist, double walkSpeedModifier, double sprintSpeedModifier) { +@@ -587,18 +605,26 @@ + .withParameter(LootContextParams.THIS_ENTITY, this.cat) + .create(LootContextParamSets.GIFT); + +- for (ItemStack itemStack : lootTable.getRandomItems(lootParams)) { +- this.cat +- .level() +- .addFreshEntity( +- new ItemEntity( +- this.cat.level(), +- (double)mutableBlockPos.getX() - (double)Mth.sin(this.cat.yBodyRot * (float) (Math.PI / 180.0)), +- (double)mutableBlockPos.getY(), +- (double)mutableBlockPos.getZ() + (double)Mth.cos(this.cat.yBodyRot * (float) (Math.PI / 180.0)), +- itemStack +- ) +- ); ++ blockposition_mutableblockposition.set(this.cat.isLeashed() ? this.cat.getLeashHolder().blockPosition() : this.cat.blockPosition()); ++ this.cat.randomTeleport((double) (blockposition_mutableblockposition.getX() + randomsource.nextInt(11) - 5), (double) (blockposition_mutableblockposition.getY() + randomsource.nextInt(5) - 2), (double) (blockposition_mutableblockposition.getZ() + randomsource.nextInt(11) - 5), false); ++ blockposition_mutableblockposition.set(this.cat.blockPosition()); ++ LootTable loottable = this.cat.level().getServer().getLootData().getLootTable(BuiltInLootTables.CAT_MORNING_GIFT); ++ LootParams lootparams = (new LootParams.Builder((ServerLevel) this.cat.level())).withParameter(LootContextParams.ORIGIN, this.cat.position()).withParameter(LootContextParams.THIS_ENTITY, this.cat).create(LootContextParamSets.GIFT); ++ List list = loottable.getRandomItems(lootparams); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ ItemStack itemstack = (ItemStack) iterator.next(); ++ ++ // CraftBukkit start ++ ItemEntity entityitem = new ItemEntity(this.cat.level(), (double) blockposition_mutableblockposition.getX() - (double) Mth.sin(this.cat.yBodyRot * 0.017453292F), (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + (double) Mth.cos(this.cat.yBodyRot * 0.017453292F), itemstack); ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.cat.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ entityitem.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ continue; ++ } ++ this.cat.level().addFreshEntity(entityitem); ++ // CraftBukkit end + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Chicken.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Chicken.java.patch new file mode 100644 index 0000000000..c67f62d332 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Chicken.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/entity/animal/Chicken.java ++++ b/net/minecraft/world/entity/animal/Chicken.java +@@ -95,7 +97,9 @@ + this.flap = this.flap + this.flapping * 2.0F; + if (!this.level().isClientSide && this.isAlive() && !this.isBaby() && !this.isChickenJockey() && --this.eggTime <= 0) { + this.playSound(SoundEvents.CHICKEN_EGG, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); +- this.spawnAtLocation(Items.EGG); ++ this.forceDrops = true; // CraftBukkit ++ this.spawnAtLocation((IMaterial) Items.EGG); ++ this.forceDrops = false; // CraftBukkit + this.gameEvent(GameEvent.ENTITY_PLACE); + this.eggTime = this.random.nextInt(6000) + 6000; + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Cow.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Cow.java.patch new file mode 100644 index 0000000000..1dbc9445d4 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Cow.java.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/world/entity/animal/Cow.java ++++ b/net/minecraft/world/entity/animal/Cow.java +@@ -33,6 +33,12 @@ + import net.minecraft.world.level.block.state.BlockState; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerBucketFillEvent; ++// CraftBukkit end ++ + public class Cow extends Animal { + public Cow(EntityType entityType, Level level) { + super(entityType, level); +@@ -80,12 +87,22 @@ + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (itemInHand.is(Items.BUCKET) && !this.isBaby()) { ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (itemstack.is(Items.BUCKET) && !this.isBaby()) { ++ // CraftBukkit start - Got milk? ++ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level(), player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand); ++ ++ if (event.isCancelled()) { ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end ++ + player.playSound(SoundEvents.COW_MILK, 1.0F, 1.0F); +- ItemStack itemStack = ItemUtils.createFilledResult(itemInHand, player, Items.MILK_BUCKET.getDefaultInstance()); +- player.setItemInHand(hand, itemStack); ++ ItemStack itemstack1 = ItemUtils.createFilledResult(itemstack, player, CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit ++ ++ player.setItemInHand(hand, itemstack1); + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { + return super.mobInteract(player, hand); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Dolphin.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Dolphin.java.patch new file mode 100644 index 0000000000..12722c7dcd --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Dolphin.java.patch @@ -0,0 +1,67 @@ +--- a/net/minecraft/world/entity/animal/Dolphin.java ++++ b/net/minecraft/world/entity/animal/Dolphin.java +@@ -60,8 +60,19 @@ + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityPotionEffectEvent; ++// CraftBukkit end + + public class Dolphin extends WaterAnimal { ++ ++ // CraftBukkit start - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ @Override ++ public int getDefaultMaxAirSupply() { ++ return TOTAL_AIR_SUPPLY; ++ } ++ // CraftBukkit end + private static final EntityDataAccessor TREASURE_POS = SynchedEntityData.defineId(Dolphin.class, EntityDataSerializers.BLOCK_POS); + private static final EntityDataAccessor GOT_FISH = SynchedEntityData.defineId(Dolphin.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor MOISTNESS_LEVEL = SynchedEntityData.defineId(Dolphin.class, EntityDataSerializers.INT); +@@ -183,7 +195,7 @@ + + @Override + public int getMaxAirSupply() { +- return 4800; ++ return maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() + } + + @Override +@@ -220,8 +233,15 @@ + @Override + protected void pickUpItem(ItemEntity itemEntity) { + if (this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty()) { +- ItemStack item = itemEntity.getItem(); +- if (this.canHoldItem(item)) { ++ ItemStack itemstack = itemEntity.getItem(); ++ ++ if (this.canHoldItem(itemstack)) { ++ // CraftBukkit start - call EntityPickupItemEvent ++ if (CraftEventFactory.callEntityPickupItemEvent(this, itemEntity, 0, false).isCancelled()) { ++ return; ++ } ++ itemstack = itemEntity.getItem(); // CraftBukkit- update ItemStack from event ++ // CraftBukkit start + this.onItemPickup(itemEntity); + this.setItemSlot(EquipmentSlot.MAINHAND, item); + this.setGuaranteedDrop(EquipmentSlot.MAINHAND); +@@ -490,7 +500,7 @@ + + @Override + public void start() { +- this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin); ++ this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin, EntityPotionEffectEvent.Cause.DOLPHIN); // CraftBukkit + } + + @Override +@@ -509,7 +519,7 @@ + } + + if (this.player.isSwimming() && this.player.level().random.nextInt(6) == 0) { +- this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin); ++ this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin, EntityPotionEffectEvent.Cause.DOLPHIN); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Fox.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Fox.java.patch new file mode 100644 index 0000000000..d9ce3fc633 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Fox.java.patch @@ -0,0 +1,106 @@ +--- a/net/minecraft/world/entity/animal/Fox.java ++++ b/net/minecraft/world/entity/animal/Fox.java +@@ -508,11 +521,14 @@ + + @Override + protected void pickUpItem(ItemEntity itemEntity) { +- ItemStack item = itemEntity.getItem(); +- if (this.canHoldItem(item)) { +- int count = item.getCount(); +- if (count > 1) { +- this.dropItemStack(item.split(count - 1)); ++ ItemStack itemstack = itemEntity.getItem(); ++ ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, itemEntity, itemstack.getCount() - 1, !this.canHoldItem(itemstack)).isCancelled()) { // CraftBukkit - call EntityPickupItemEvent ++ itemstack = itemEntity.getItem(); // CraftBukkit - update ItemStack from event ++ int i = itemstack.getCount(); ++ ++ if (i > 1) { ++ this.dropItemStack(itemstack.split(i - 1)); + } + + this.spitOutItem(this.getItemBySlot(EquipmentSlot.MAINHAND)); +@@ -874,6 +884,16 @@ + if (loveCause1 != null && loveCause != loveCause1) { + fox.addTrustedUUID(loveCause1.getUUID()); + } ++ // CraftBukkit start - call EntityBreedEvent ++ entityfox.setAge(-24000); ++ entityfox.moveTo(this.animal.getX(), this.animal.getY(), this.animal.getZ(), 0.0F, 0.0F); ++ int experience = this.animal.getRandom().nextInt(7) + 1; ++ org.bukkit.event.entity.EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(entityfox, animal, partner, entityplayer, this.animal.breedItem, experience); ++ if (entityBreedEvent.isCancelled()) { ++ return; ++ } ++ experience = entityBreedEvent.getExperience(); ++ // CraftBukkit end + + if (serverPlayer != null) { + serverPlayer.awardStat(Stats.ANIMALS_BRED); +@@ -884,15 +904,14 @@ + this.partner.setAge(6000); + this.animal.resetLove(); + this.partner.resetLove(); +- fox.setAge(-24000); +- fox.moveTo(this.animal.getX(), this.animal.getY(), this.animal.getZ(), 0.0F, 0.0F); +- serverLevel.addFreshEntityWithPassengers(fox); +- this.level.broadcastEntityEvent(this.animal, (byte)18); ++ worldserver.addFreshEntityWithPassengers(entityfox, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - added SpawnReason ++ this.level.broadcastEntityEvent(this.animal, (byte) 18); + if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +- this.level +- .addFreshEntity( +- new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), this.animal.getRandom().nextInt(7) + 1) +- ); ++ // CraftBukkit start - use event experience ++ if (experience > 0) { ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience)); ++ } ++ // CraftBukkit end + } + } + } +@@ -1203,16 +1299,34 @@ + } + } + +- if (target != null && Fox.this.distanceTo(target) <= 2.0F) { +- Fox.this.doHurtTarget(target); +- } else if (Fox.this.getXRot() > 0.0F +- && Fox.this.onGround() +- && (float)Fox.this.getDeltaMovement().y != 0.0F +- && Fox.this.level().getBlockState(Fox.this.blockPosition()).is(Blocks.SNOW)) { +- Fox.this.setXRot(60.0F); +- Fox.this.setTarget(null); +- Fox.this.setFaceplanted(true); ++ private void pickGlowBerry(IBlockData state) { ++ CaveVines.use(Fox.this, state, Fox.this.level(), this.blockPos); ++ } ++ ++ private void pickSweetBerries(IBlockData state) { ++ int i = (Integer) state.getValue(SweetBerryBushBlock.AGE); ++ ++ state.setValue(SweetBerryBushBlock.AGE, 1); ++ // CraftBukkit start - call EntityChangeBlockEvent ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(Fox.this, this.blockPos, state.setValue(SweetBerryBushBlock.AGE, 1))) { ++ return; + } ++ // CraftBukkit end ++ int j = 1 + Fox.this.level().random.nextInt(2) + (i == 3 ? 1 : 0); ++ ItemStack itemstack = Fox.this.getItemBySlot(EquipmentSlot.MAINHAND); ++ ++ if (itemstack.isEmpty()) { ++ Fox.this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.SWEET_BERRIES)); ++ --j; ++ } ++ ++ if (j > 0) { ++ Block.popResource(Fox.this.level(), this.blockPos, new ItemStack(Items.SWEET_BERRIES, j)); ++ } ++ ++ Fox.this.playSound(SoundEvents.SWEET_BERRY_BUSH_PICK_BERRIES, 1.0F, 1.0F); ++ Fox.this.level().setBlock(this.blockPos, (IBlockData) state.setValue(SweetBerryBushBlock.AGE, 1), 2); ++ Fox.this.level().gameEvent(GameEvent.BLOCK_CHANGE, this.blockPos, GameEvent.Context.of((Entity) Fox.this)); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/IronGolem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/IronGolem.java.patch new file mode 100644 index 0000000000..519c37e6c0 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/IronGolem.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/entity/animal/IronGolem.java ++++ b/net/minecraft/world/entity/animal/IronGolem.java +@@ -102,8 +101,8 @@ + + @Override + protected void doPush(Entity entity) { +- if (entity instanceof Enemy && !(entity instanceof Creeper) && this.getRandom().nextInt(20) == 0) { +- this.setTarget((LivingEntity)entity); ++ if (entity instanceof IMonster && !(entity instanceof Creeper) && this.getRandom().nextInt(20) == 0) { ++ this.setTarget((LivingEntity) entity, org.bukkit.event.entity.EntityTargetLivingEntityEvent.TargetReason.COLLISION, true); // CraftBukkit - set reason + } + + super.doPush(entity); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/MushroomCow.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/MushroomCow.java.patch new file mode 100644 index 0000000000..2cb2fbe4b2 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/MushroomCow.java.patch @@ -0,0 +1,86 @@ +--- a/net/minecraft/world/entity/animal/MushroomCow.java ++++ b/net/minecraft/world/entity/animal/MushroomCow.java +@@ -42,6 +42,13 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityDropItemEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++// CraftBukkit end ++ + public class MushroomCow extends Cow implements Shearable, VariantHolder { + private static final EntityDataAccessor DATA_TYPE = SynchedEntityData.defineId(MushroomCow.class, EntityDataSerializers.STRING); + private static final int MUTATE_CHANCE = 1024; +@@ -108,7 +120,12 @@ + + this.playSound(soundEvent, 1.0F, 1.0F); + return InteractionResult.sidedSuccess(this.level().isClientSide); +- } else if (itemInHand.is(Items.SHEARS) && this.readyForShearing()) { ++ } else if (itemstack.is(Items.SHEARS) && this.readyForShearing()) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) { ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.shear(SoundSource.PLAYERS); + this.gameEvent(GameEvent.SHEAR, player); + if (!this.level().isClientSide) { +@@ -167,13 +169,14 @@ + public void shear(SoundSource category) { + this.level().playSound(null, this, SoundEvents.MOOSHROOM_SHEAR, category, 1.0F, 1.0F); + if (!this.level().isClientSide()) { +- Cow cow = EntityType.COW.create(this.level()); +- if (cow != null) { +- ((ServerLevel)this.level()).sendParticles(ParticleTypes.EXPLOSION, this.getX(), this.getY(0.5), this.getZ(), 1, 0.0, 0.0, 0.0, 0.0); +- this.discard(); +- cow.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); +- cow.setHealth(this.getHealth()); +- cow.yBodyRot = this.yBodyRot; ++ Cow entitycow = (Cow) EntityType.COW.create(this.level()); ++ ++ if (entitycow != null) { ++ ((ServerLevel) this.level()).sendParticles(ParticleTypes.EXPLOSION, this.getX(), this.getY(0.5D), this.getZ(), 1, 0.0D, 0.0D, 0.0D, 0.0D); ++ // this.discard(); // CraftBukkit - moved down ++ entitycow.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); ++ entitycow.setHealth(this.getHealth()); ++ entitycow.yBodyRot = this.yBodyRot; + if (this.hasCustomName()) { + cow.setCustomName(this.getCustomName()); + cow.setCustomNameVisible(this.isCustomNameVisible()); +@@ -183,14 +186,26 @@ + cow.setPersistenceRequired(); + } + +- cow.setInvulnerable(this.isInvulnerable()); +- this.level().addFreshEntity(cow); ++ entitycow.setInvulnerable(this.isInvulnerable()); ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, entitycow, EntityTransformEvent.TransformReason.SHEARED).isCancelled()) { ++ return; ++ } ++ this.level().addFreshEntity(entitycow, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SHEARED); + +- for (int i = 0; i < 5; i++) { +- this.level() +- .addFreshEntity( +- new ItemEntity(this.level(), this.getX(), this.getY(1.0), this.getZ(), new ItemStack(this.getVariant().blockState.getBlock())) +- ); ++ this.discard(); // CraftBukkit - from above ++ // CraftBukkit end ++ ++ for (int i = 0; i < 5; ++i) { ++ // CraftBukkit start ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY(1.0D), this.getZ(), new ItemStack(this.getVariant().blockState.getBlock())); ++ EntityDropItemEvent event = new EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ continue; ++ } ++ this.level().addFreshEntity(entityitem); ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Ocelot.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Ocelot.java.patch new file mode 100644 index 0000000000..5e8c505644 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Ocelot.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/animal/Ocelot.java ++++ b/net/minecraft/world/entity/animal/Ocelot.java +@@ -173,7 +179,7 @@ + if ((this.temptGoal == null || this.temptGoal.isRunning()) && !this.isTrusting() && this.isFood(itemInHand) && player.distanceToSqr(this) < 9.0) { + this.usePlayerItem(player, hand, itemInHand); + if (!this.level().isClientSide) { +- if (this.random.nextInt(3) == 0) { ++ if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit - added event call and isCancelled check + this.setTrusting(true); + this.spawnTrustingParticles(true); + this.level().broadcastEntityEvent(this, (byte)41); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Panda.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Panda.java.patch new file mode 100644 index 0000000000..c22cdec6b8 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Panda.java.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/world/entity/animal/Panda.java ++++ b/net/minecraft/world/entity/animal/Panda.java +@@ -64,6 +67,11 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end ++ + public class Panda extends Animal { + private static final EntityDataAccessor UNHAPPY_COUNTER = SynchedEntityData.defineId(Panda.class, EntityDataSerializers.INT); + private static final EntityDataAccessor SNEEZE_COUNTER = SynchedEntityData.defineId(Panda.class, EntityDataSerializers.INT); +@@ -524,7 +539,7 @@ + + @Override + protected void pickUpItem(ItemEntity itemEntity) { +- if (this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty() && PANDA_ITEMS.test(itemEntity)) { ++ if (!CraftEventFactory.callEntityPickupItemEvent(this, itemEntity, 0, !(this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty() && Panda.PANDA_ITEMS.test(itemEntity))).isCancelled()) { // CraftBukkit + this.onItemPickup(itemEntity); + ItemStack item = itemEntity.getItem(); + this.setItemSlot(EquipmentSlot.MAINHAND, item); +@@ -1066,16 +1115,9 @@ + } + + @Override +- public boolean canContinueToUse() { +- return !Panda.this.isInWater() +- && (Panda.this.isLazy() || Panda.this.random.nextInt(reducedTickDelay(600)) != 1) +- && Panda.this.random.nextInt(reducedTickDelay(2000)) != 1; +- } +- +- @Override +- public void tick() { +- if (!Panda.this.isSitting() && !Panda.this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty()) { +- Panda.this.tryToSit(); ++ protected void alertOther(Mob mob, LivingEntity target) { ++ if (mob instanceof Panda && mob.isAggressive()) { ++ mob.setTarget(target, EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY, true); // CraftBukkit + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Parrot.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Parrot.java.patch new file mode 100644 index 0000000000..e233a11dc5 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Parrot.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/world/entity/animal/Parrot.java ++++ b/net/minecraft/world/entity/animal/Parrot.java +@@ -271,7 +263,7 @@ + } + + if (!this.level().isClientSide) { +- if (this.random.nextInt(10) == 0) { ++ if (this.random.nextInt(10) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit + this.tame(player); + this.level().broadcastEntityEvent(this, (byte)7); + } else { +@@ -285,7 +277,7 @@ + itemInHand.shrink(1); + } + +- this.addEffect(new MobEffectInstance(MobEffects.POISON, 900)); ++ this.addEffect(new MobEffectInstance(MobEffects.POISON, 900), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.FOOD); // CraftBukkit + if (player.isCreative() || !this.isInvulnerable()) { + this.hurt(this.damageSources().playerAttack(player), Float.MAX_VALUE); + } +@@ -392,7 +384,7 @@ + + @Override + public boolean isPushable() { +- return true; ++ return super.isPushable(); // CraftBukkit - collidable API + } + + @Override +@@ -407,11 +399,14 @@ + if (this.isInvulnerableTo(source)) { + return false; + } else { +- if (!this.level().isClientSide) { ++ // CraftBukkit start ++ boolean result = super.hurt(source, amount); ++ if (!this.level().isClientSide && result) { ++ // CraftBukkit end + this.setOrderedToSit(false); + } + +- return super.hurt(source, amount); ++ return result; // CraftBukkit + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Pig.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Pig.java.patch new file mode 100644 index 0000000000..59fd343ecf --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Pig.java.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/world/entity/animal/Pig.java ++++ b/net/minecraft/world/entity/animal/Pig.java +@@ -49,7 +51,12 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Pig extends Animal implements ItemSteerable, Saddleable { ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ ++public class Pig extends Animal implements ISteerable, Saddleable { ++ + private static final EntityDataAccessor DATA_SADDLE_ID = SynchedEntityData.defineId(Pig.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_BOOST_TIME = SynchedEntityData.defineId(Pig.class, EntityDataSerializers.INT); + private static final Ingredient FOOD_ITEMS = Ingredient.of(Items.CARROT, Items.POTATO, Items.BEETROOT); +@@ -222,8 +255,14 @@ + zombifiedPiglin.setCustomNameVisible(this.isCustomNameVisible()); + } + +- zombifiedPiglin.setPersistenceRequired(); +- level.addFreshEntity(zombifiedPiglin); ++ entitypigzombie.setPersistenceRequired(); ++ // CraftBukkit start ++ if (CraftEventFactory.callPigZapEvent(this, lightning, entitypigzombie).isCancelled()) { ++ return; ++ } ++ // CraftBukkit - added a reason for spawning this creature ++ level.addFreshEntity(entitypigzombie, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); ++ // CraftBukkit end + this.discard(); + } else { + super.thunderHit(level, lightning); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Pufferfish.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Pufferfish.java.patch new file mode 100644 index 0000000000..2a6bd1c25f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Pufferfish.java.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/world/entity/animal/Pufferfish.java ++++ b/net/minecraft/world/entity/animal/Pufferfish.java +@@ -133,9 +141,10 @@ + } + + private void touch(Mob mob) { +- int puffState = this.getPuffState(); +- if (mob.hurt(this.damageSources().mobAttack(this), (float)(1 + puffState))) { +- mob.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * puffState, 0), this); ++ int i = this.getPuffState(); ++ ++ if (mob.hurt(this.damageSources().mobAttack(this), (float) (1 + i))) { ++ mob.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * i, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + this.playSound(SoundEvents.PUFFER_FISH_STING, 1.0F, 1.0F); + } + } +@@ -148,7 +159,7 @@ + ((ServerPlayer)entity).connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.PUFFER_FISH_STING, 0.0F)); + } + +- entity.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * puffState, 0), this); ++ entity.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * i, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Rabbit.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Rabbit.java.patch new file mode 100644 index 0000000000..9808520a10 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Rabbit.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/entity/animal/Rabbit.java ++++ b/net/minecraft/world/entity/animal/Rabbit.java +@@ -66,6 +66,9 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.pathfinder.Path; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class Rabbit extends Animal implements VariantHolder { + public static final double STROLL_SPEED_MOD = 0.6; +@@ -571,12 +579,22 @@ + if (this.canRaid && block instanceof CarrotBlock) { + int i = blockState.getValue(CarrotBlock.AGE); + if (i == 0) { +- level.setBlock(blockPos, Blocks.AIR.defaultBlockState(), 2); +- level.destroyBlock(blockPos, true, this.rabbit); ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.rabbit, blockposition, Blocks.AIR.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end ++ world.setBlock(blockposition, Blocks.AIR.defaultBlockState(), 2); ++ world.destroyBlock(blockposition, true, this.rabbit); + } else { +- level.setBlock(blockPos, blockState.setValue(CarrotBlock.AGE, Integer.valueOf(i - 1)), 2); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockPos, GameEvent.Context.of(this.rabbit)); +- level.levelEvent(2001, blockPos, Block.getId(blockState)); ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.rabbit, blockposition, iblockdata.setValue(CarrotBlock.AGE, i - 1))) { ++ return; ++ } ++ // CraftBukkit end ++ world.setBlock(blockposition, (IBlockData) iblockdata.setValue(CarrotBlock.AGE, i - 1), 2); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of((Entity) this.rabbit)); ++ world.levelEvent(2001, blockposition, Block.getId(iblockdata)); + } + + this.rabbit.moreCarrotTicks = 40; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Sheep.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Sheep.java.patch new file mode 100644 index 0000000000..d2e75670e0 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Sheep.java.patch @@ -0,0 +1,89 @@ +--- a/net/minecraft/world/entity/animal/Sheep.java ++++ b/net/minecraft/world/entity/animal/Sheep.java +@@ -64,6 +64,13 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.storage.loot.BuiltInLootTables; + import org.joml.Vector3f; ++import net.minecraft.world.item.DyeColor; ++import net.minecraft.world.item.DyeItem; ++import net.minecraft.world.item.Item; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.SheepRegrowWoolEvent; ++import org.bukkit.inventory.InventoryView; ++// CraftBukkit end + + public class Sheep extends Animal implements Shearable { + private static final int EAT_ANIMATION_TICKS = 40; +@@ -210,6 +252,11 @@ + ItemStack itemInHand = player.getItemInHand(hand); + if (itemInHand.is(Items.SHEARS)) { + if (!this.level().isClientSide && this.readyForShearing()) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) { ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.shear(SoundSource.PLAYERS); + this.gameEvent(GameEvent.SHEAR, player); + itemInHand.hurtAndBreak(1, player, entity -> entity.broadcastBreakEvent(hand)); +@@ -228,17 +277,13 @@ + this.setSheared(true); + int i = 1 + this.random.nextInt(3); + +- for (int i1 = 0; i1 < i; i1++) { +- ItemEntity itemEntity = this.spawnAtLocation(ITEM_BY_DYE.get(this.getColor()), 1); +- if (itemEntity != null) { +- itemEntity.setDeltaMovement( +- itemEntity.getDeltaMovement() +- .add( +- (double)((this.random.nextFloat() - this.random.nextFloat()) * 0.1F), +- (double)(this.random.nextFloat() * 0.05F), +- (double)((this.random.nextFloat() - this.random.nextFloat()) * 0.1F) +- ) +- ); ++ for (int j = 0; j < i; ++j) { ++ this.forceDrops = true; // CraftBukkit ++ ItemEntity entityitem = this.spawnAtLocation((IMaterial) Sheep.ITEM_BY_DYE.get(this.getColor()), 1); ++ this.forceDrops = false; // CraftBukkit ++ ++ if (entityitem != null) { ++ entityitem.setDeltaMovement(entityitem.getDeltaMovement().add((double) ((this.random.nextFloat() - this.random.nextFloat()) * 0.1F), (double) (this.random.nextFloat() * 0.05F), (double) ((this.random.nextFloat() - this.random.nextFloat()) * 0.1F))); + } + } + } +@@ -332,6 +373,12 @@ + + @Override + public void ate() { ++ // CraftBukkit start ++ SheepRegrowWoolEvent event = new SheepRegrowWoolEvent((org.bukkit.entity.Sheep) this.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) return; ++ // CraftBukkit end + super.ate(); + this.setSheared(false); + if (this.isBaby()) { +@@ -374,10 +421,19 @@ + public boolean stillValid(Player player) { + return false; + } ++ ++ // CraftBukkit start ++ @Override ++ public InventoryView getBukkitView() { ++ return null; // TODO: O.O ++ } ++ // CraftBukkit end + }, 2, 1); +- craftingContainer.setItem(0, new ItemStack(DyeItem.byColor(fatherColor))); +- craftingContainer.setItem(1, new ItemStack(DyeItem.byColor(motherColor))); +- return craftingContainer; ++ ++ transientcraftingcontainer.setItem(0, new ItemStack(DyeItem.byColor(fatherColor))); ++ transientcraftingcontainer.setItem(1, new ItemStack(DyeItem.byColor(motherColor))); ++ transientcraftingcontainer.resultInventory = new ResultContainer(); // CraftBukkit - add result slot for event ++ return transientcraftingcontainer; + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/SnowGolem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/SnowGolem.java.patch new file mode 100644 index 0000000000..d6c54722b1 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/SnowGolem.java.patch @@ -0,0 +1,78 @@ +--- a/net/minecraft/world/entity/animal/SnowGolem.java ++++ b/net/minecraft/world/entity/animal/SnowGolem.java +@@ -39,6 +40,9 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackMob { + private static final EntityDataAccessor DATA_PUMPKIN_ID = SynchedEntityData.defineId(SnowGolem.class, EntityDataSerializers.BYTE); +@@ -92,7 +100,7 @@ + super.aiStep(); + if (!this.level().isClientSide) { + if (this.level().getBiome(this.blockPosition()).is(BiomeTags.SNOW_GOLEM_MELTS)) { +- this.hurt(this.damageSources().onFire(), 1.0F); ++ this.hurt(this.damageSources().melting, 1.0F); // CraftBukkit - DamageSource.BURN -> CraftEventFactory.MELTING + } + + if (!this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +@@ -101,14 +109,19 @@ + + BlockState blockState = Blocks.SNOW.defaultBlockState(); + +- for (int i = 0; i < 4; i++) { +- int floor = Mth.floor(this.getX() + (double)((float)(i % 2 * 2 - 1) * 0.25F)); +- int floor1 = Mth.floor(this.getY()); +- int floor2 = Mth.floor(this.getZ() + (double)((float)(i / 2 % 2 * 2 - 1) * 0.25F)); +- BlockPos blockPos = new BlockPos(floor, floor1, floor2); +- if (this.level().getBlockState(blockPos).isAir() && blockState.canSurvive(this.level(), blockPos)) { +- this.level().setBlockAndUpdate(blockPos, blockState); +- this.level().gameEvent(GameEvent.BLOCK_PLACE, blockPos, GameEvent.Context.of(this, blockState)); ++ for (int i = 0; i < 4; ++i) { ++ int j = Mth.floor(this.getX() + (double) ((float) (i % 2 * 2 - 1) * 0.25F)); ++ int k = Mth.floor(this.getY()); ++ int l = Mth.floor(this.getZ() + (double) ((float) (i / 2 % 2 * 2 - 1) * 0.25F)); ++ BlockPos blockposition = new BlockPos(j, k, l); ++ ++ if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handleBlockFormEvent(this.level(), blockposition, iblockdata, this)) { ++ continue; ++ } ++ // CraftBukkit end ++ this.level().gameEvent(GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(this, iblockdata)); + } + } + } +@@ -133,9 +148,15 @@ + } + + @Override +- protected InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (itemInHand.is(Items.SHEARS) && this.readyForShearing()) { ++ protected InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (itemstack.is(Items.SHEARS) && this.readyForShearing()) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) { ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.shear(SoundSource.PLAYERS); + this.gameEvent(GameEvent.SHEAR, player); + if (!this.level().isClientSide) { +@@ -153,7 +176,9 @@ + this.level().playSound(null, this, SoundEvents.SNOW_GOLEM_SHEAR, category, 1.0F, 1.0F); + if (!this.level().isClientSide()) { + this.setPumpkin(false); ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation(new ItemStack(Items.CARVED_PUMPKIN), 1.7F); ++ this.forceDrops = false; // CraftBukkit + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Turtle.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Turtle.java.patch new file mode 100644 index 0000000000..485d31894e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Turtle.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/world/entity/animal/Turtle.java ++++ b/net/minecraft/world/entity/animal/Turtle.java +@@ -305,7 +307,9 @@ + protected void ageBoundaryReached() { + super.ageBoundaryReached(); + if (!this.isBaby() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation(Items.SCUTE, 1); ++ this.forceDrops = false; // CraftBukkit + } + } + +@@ -330,7 +336,9 @@ + + @Override + public void thunderHit(ServerLevel level, LightningBolt lightning) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = lightning; // CraftBukkit + this.hurt(this.damageSources().lightningBolt(), Float.MAX_VALUE); ++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = null; // CraftBukkit + } + + @Override +@@ -431,13 +495,17 @@ + posTowards = DefaultRandomPos.getPosTowards(this.turtle, 8, 7, vec3, (float) (Math.PI / 2)); + } + +- if (posTowards != null && !flag && !this.turtle.level().getBlockState(BlockPos.containing(posTowards)).is(Blocks.WATER)) { +- posTowards = DefaultRandomPos.getPosTowards(this.turtle, 16, 5, vec3, (float) (Math.PI / 2)); +- } ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.turtle, this.blockPos.above(), (IBlockData) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1))) { // CraftBukkit ++ world.playSound((Player) null, blockposition, SoundEvents.TURTLE_LAY_EGG, SoundSource.BLOCKS, 0.3F, 0.9F + world.random.nextFloat() * 0.2F); ++ BlockPos blockposition1 = this.blockPos.above(); ++ IBlockData iblockdata = (IBlockData) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1); + +- if (posTowards == null) { +- this.stuck = true; +- return; ++ world.setBlock(blockposition1, iblockdata, 3); ++ world.gameEvent(GameEvent.BLOCK_PLACE, blockposition1, GameEvent.Context.of(this.turtle, iblockdata)); ++ } // CraftBukkit ++ this.turtle.setHasEgg(false); ++ this.turtle.setLayingEgg(false); ++ this.turtle.setInLoveTime(600); + } + + this.turtle.getNavigation().moveTo(posTowards.x, posTowards.y, posTowards.z, this.speedModifier); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Wolf.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Wolf.java.patch new file mode 100644 index 0000000000..797e233cff --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/Wolf.java.patch @@ -0,0 +1,75 @@ +--- a/net/minecraft/world/entity/animal/Wolf.java ++++ b/net/minecraft/world/entity/animal/Wolf.java +@@ -70,6 +70,12 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class Wolf extends TamableAnimal implements NeutralMob { + private static final EntityDataAccessor DATA_INTERESTED_ID = SynchedEntityData.defineId(Wolf.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_COLLAR_COLOR = SynchedEntityData.defineId(Wolf.class, EntityDataSerializers.INT); +@@ -310,11 +304,19 @@ + this.setOrderedToSit(false); + } + ++ // CraftBukkit - move diff down ++ + if (entity != null && !(entity instanceof Player) && !(entity instanceof AbstractArrow)) { + amount = (amount + 1.0F) / 2.0F; + } + +- return super.hurt(source, amount); ++ // CraftBukkit start ++ boolean result = super.hurt(source, amount); ++ if (!this.level().isClientSide && result) { ++ this.setOrderedToSit(false); ++ } ++ return result; ++ // CraftBukkit end + } + } + +@@ -332,8 +335,8 @@ + public void setTame(boolean tamed) { + super.setTame(tamed); + if (tamed) { +- this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(20.0); +- this.setHealth(20.0F); ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(20.0D); ++ this.setHealth(this.getMaxHealth()); // CraftBukkit - 20.0 -> getMaxHealth() + } else { + this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(8.0); + } +@@ -354,7 +359,7 @@ + itemInHand.shrink(1); + } + +- this.heal((float)item.getFoodProperties().getNutrition()); ++ this.heal((float) item.getFoodProperties().getNutrition(), EntityRegainHealthEvent.RegainReason.EATING); // CraftBukkit + return InteractionResult.SUCCESS; + } else { + if (item instanceof DyeItem dyeItem && this.isOwnedBy(player)) { +@@ -376,7 +387,7 @@ + this.setOrderedToSit(!this.isOrderedToSit()); + this.jumping = false; + this.navigation.stop(); +- this.setTarget(null); ++ this.setTarget((LivingEntity) null, EntityTargetEvent.TargetReason.FORGOT_TARGET, true); // CraftBukkit - reason + return InteractionResult.SUCCESS; + } else { + return interactionResult; +@@ -387,7 +398,8 @@ + itemInHand.shrink(1); + } + +- if (this.random.nextInt(3) == 0) { ++ // CraftBukkit - added event call and isCancelled check. ++ if (this.random.nextInt(3) == 0 && !CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { + this.tame(player); + this.navigation.stop(); + this.setTarget(null); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/allay/Allay.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/allay/Allay.java.patch new file mode 100644 index 0000000000..7cb091317b --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/allay/Allay.java.patch @@ -0,0 +1,94 @@ +--- a/net/minecraft/world/entity/animal/allay/Allay.java ++++ b/net/minecraft/world/entity/animal/allay/Allay.java +@@ -112,6 +99,7 @@ + private float dancingAnimationTicks; + private float spinningAnimationTicks; + private float spinningAnimationTicks0; ++ public boolean forceDancing = false; // CraftBukkit + + public Allay(EntityType entityType, Level level) { + super(entityType, level); +@@ -125,6 +111,12 @@ + ); + } + ++ // CraftBukkit start ++ public void setCanDuplicate(boolean canDuplicate) { ++ this.entityData.set(Allay.DATA_CAN_DUPLICATE, canDuplicate); ++ } ++ // CraftBukkit end ++ + @Override + protected Brain.Provider brainProvider() { + return Brain.provider(MEMORY_TYPES, SENSOR_TYPES); +@@ -246,7 +236,7 @@ + public void aiStep() { + super.aiStep(); + if (!this.level().isClientSide && this.isAlive() && this.tickCount % 10 == 0) { +- this.heal(1.0F); ++ this.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit + } + + if (this.isDancing() && this.shouldStopDancing() && this.tickCount % 20 == 0) { +@@ -310,14 +301,20 @@ + } + + @Override +- protected InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- ItemStack itemInHand1 = this.getItemInHand(InteractionHand.MAIN_HAND); +- if (this.isDancing() && this.isDuplicationItem(itemInHand) && this.canDuplicate()) { +- this.duplicateAllay(); +- this.level().broadcastEntityEvent(this, (byte)18); +- this.level().playSound(player, this, SoundEvents.AMETHYST_BLOCK_CHIME, SoundSource.NEUTRAL, 2.0F, 1.0F); +- this.removeInteractionItem(player, itemInHand); ++ protected InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ItemStack itemstack1 = this.getItemInHand(EnumHand.MAIN_HAND); ++ ++ if (this.isDancing() && this.isDuplicationItem(itemstack) && this.canDuplicate()) { ++ // CraftBukkit start - handle cancel duplication ++ Allay allay = this.duplicateAllay(); ++ if (allay == null) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ this.level().broadcastEntityEvent(this, (byte) 18); ++ this.level().playSound(player, (Entity) this, SoundEvents.AMETHYST_BLOCK_CHIME, SoundSource.NEUTRAL, 2.0F, 1.0F); ++ this.removeInteractionItem(player, itemstack); + return InteractionResult.SUCCESS; + } else if (itemInHand1.isEmpty() && !itemInHand.isEmpty()) { + ItemStack itemStack = itemInHand.copyWithCount(1); +@@ -431,9 +439,8 @@ + } + + private boolean shouldStopDancing() { +- return this.jukeboxPos == null +- || !this.jukeboxPos.closerToCenterThan(this.position(), (double)GameEvent.JUKEBOX_PLAY.getNotificationRadius()) +- || !this.level().getBlockState(this.jukeboxPos).is(Blocks.JUKEBOX); ++ if (this.forceDancing) {return false;} // CraftBukkit ++ return this.jukeboxPos == null || !this.jukeboxPos.closerToCenterThan(this.position(), (double) GameEvent.JUKEBOX_PLAY.getNotificationRadius()) || !this.level().getBlockState(this.jukeboxPos).is(Blocks.JUKEBOX); + } + + public float getHoldingItemAnimationProgress(float partialTick) { +@@ -516,15 +533,17 @@ + return DUPLICATION_ITEM.test(stack); + } + +- private void duplicateAllay() { +- Allay allay = EntityType.ALLAY.create(this.level()); ++ public Allay duplicateAllay() { // CraftBukkit - return allay ++ Allay allay = (Allay) EntityType.ALLAY.create(this.level()); ++ + if (allay != null) { + allay.moveTo(this.position()); + allay.setPersistenceRequired(); + allay.resetDuplicationCooldown(); + this.resetDuplicationCooldown(); +- this.level().addFreshEntity(allay); ++ this.level().addFreshEntity(allay, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DUPLICATION); // CraftBukkit - reason for duplicated allay + } ++ return allay; // CraftBukkit + } + + private void resetDuplicationCooldown() { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/axolotl/Axolotl.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/axolotl/Axolotl.java.patch new file mode 100644 index 0000000000..243c02b137 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/axolotl/Axolotl.java.patch @@ -0,0 +1,44 @@ +--- a/net/minecraft/world/entity/animal/axolotl/Axolotl.java ++++ b/net/minecraft/world/entity/animal/axolotl/Axolotl.java +@@ -67,6 +67,13 @@ + import org.joml.Vector3f; + + public class Axolotl extends Animal implements LerpingModel, VariantHolder, Bucketable { ++ ++ // CraftBukkit start - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ @Override ++ public int getDefaultMaxAirSupply() { ++ return AXOLOTL_TOTAL_AIR_SUPPLY; ++ } ++ // CraftBukkit end + public static final int TOTAL_PLAYDEAD_TIME = 200; + protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of( + SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_ADULT, SensorType.HURT_BY, SensorType.AXOLOTL_ATTACKABLES, SensorType.AXOLOTL_TEMPTATIONS +@@ -206,7 +195,7 @@ + + @Override + public int getMaxAirSupply() { +- return 6000; ++ return maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() + } + + @Override +@@ -414,11 +410,13 @@ + } + + public void applySupportingEffects(Player player) { +- MobEffectInstance effect = player.getEffect(MobEffects.REGENERATION); +- if (effect == null || effect.endsWithin(2399)) { +- int i = effect != null ? effect.getDuration() : 0; +- int min = Math.min(2400, 100 + i); +- player.addEffect(new MobEffectInstance(MobEffects.REGENERATION, min, 0), this); ++ MobEffectInstance mobeffect = player.getEffect(MobEffects.REGENERATION); ++ ++ if (mobeffect == null || mobeffect.endsWithin(2399)) { ++ int i = mobeffect != null ? mobeffect.getDuration() : 0; ++ int j = Math.min(2400, 100 + i); ++ ++ player.addEffect(new MobEffectInstance(MobEffects.REGENERATION, j, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AXOLOTL); // CraftBukkit + } + + player.removeEffect(MobEffects.DIG_SLOWDOWN); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/frog/Tadpole.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/frog/Tadpole.java.patch new file mode 100644 index 0000000000..122d63658a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/frog/Tadpole.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/entity/animal/frog/Tadpole.java ++++ b/net/minecraft/world/entity/animal/frog/Tadpole.java +@@ -236,8 +233,14 @@ + } + + frog.setPersistenceRequired(); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTransformEvent(this, frog, org.bukkit.event.entity.EntityTransformEvent.TransformReason.METAMORPHOSIS).isCancelled()) { ++ this.setAge(0); // Sets the age to 0 for avoid a loop if the event is canceled ++ return; ++ } ++ // CraftBukkit end + this.playSound(SoundEvents.TADPOLE_GROW_UP, 0.15F, 1.0F); +- serverLevel.addFreshEntityWithPassengers(frog); ++ worldserver.addFreshEntityWithPassengers(frog, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.METAMORPHOSIS); // CraftBukkit - add SpawnReason + this.discard(); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/goat/Goat.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/goat/Goat.java.patch new file mode 100644 index 0000000000..1f49245a0c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/goat/Goat.java.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/world/entity/animal/goat/Goat.java ++++ b/net/minecraft/world/entity/animal/goat/Goat.java +@@ -54,6 +55,12 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerBucketFillEvent; ++// CraftBukkit end ++ + public class Goat extends Animal { + public static final EntityDimensions LONG_JUMPING_DIMENSIONS = EntityDimensions.scalable(0.9F, 1.3F).scale(0.7F); + private static final int ADULT_ATTACK_DAMAGE = 2; +@@ -210,12 +222,21 @@ + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (itemInHand.is(Items.BUCKET) && !this.isBaby()) { ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (itemstack.is(Items.BUCKET) && !this.isBaby()) { ++ // CraftBukkit start - Got milk? ++ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level(), player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand); ++ ++ if (event.isCancelled()) { ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + player.playSound(this.getMilkingSound(), 1.0F, 1.0F); +- ItemStack itemStack = ItemUtils.createFilledResult(itemInHand, player, Items.MILK_BUCKET.getDefaultInstance()); +- player.setItemInHand(hand, itemStack); ++ ItemStack itemstack1 = ItemUtils.createFilledResult(itemstack, player, CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit ++ ++ player.setItemInHand(hand, itemstack1); + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { + InteractionResult interactionResult = super.mobInteract(player, hand); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/horse/AbstractHorse.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/horse/AbstractHorse.java.patch new file mode 100644 index 0000000000..58b38c01f5 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/horse/AbstractHorse.java.patch @@ -0,0 +1,108 @@ +--- a/net/minecraft/world/entity/animal/horse/AbstractHorse.java ++++ b/net/minecraft/world/entity/animal/horse/AbstractHorse.java +@@ -77,6 +79,11 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++// CraftBukkit end ++ + public abstract class AbstractHorse extends Animal implements ContainerListener, HasCustomInventoryScreen, OwnableEntity, PlayerRideableJumping, Saddleable { + public static final int EQUIPMENT_SLOT_OFFSET = 400; + public static final int CHEST_SLOT_OFFSET = 499; +@@ -129,6 +145,7 @@ + protected int gallopSoundCounter; + @Nullable + private UUID owner; ++ public int maxDomestication = 100; // CraftBukkit - store max domestication value + + protected AbstractHorse(EntityType entityType, Level level) { + super(entityType, level); +@@ -326,10 +341,16 @@ + simpleContainer.removeListener(this); + int min = Math.min(simpleContainer.getContainerSize(), this.inventory.getContainerSize()); + +- for (int i = 0; i < min; i++) { +- ItemStack item = simpleContainer.getItem(i); +- if (!item.isEmpty()) { +- this.inventory.setItem(i, item.copy()); ++ this.inventory = new SimpleContainer(this.getInventorySize(), (org.bukkit.entity.AbstractHorse) this.getBukkitEntity()); // CraftBukkit ++ if (inventorysubcontainer != null) { ++ inventorysubcontainer.removeListener(this); ++ int i = Math.min(inventorysubcontainer.getContainerSize(), this.inventory.getContainerSize()); ++ ++ for (int j = 0; j < i; ++j) { ++ ItemStack itemstack = inventorysubcontainer.getItem(j); ++ ++ if (!itemstack.isEmpty()) { ++ this.inventory.setItem(j, itemstack.copy()); + } + } + } +@@ -427,7 +449,7 @@ + } + + public int getMaxTemper() { +- return 100; ++ return this.maxDomestication; // CraftBukkit - return stored max domestication instead of 100 + } + + @Override +@@ -499,7 +520,7 @@ + } + + if (this.getHealth() < this.getMaxHealth() && f > 0.0F) { +- this.heal(f); ++ this.heal(f, EntityRegainHealthEvent.RegainReason.EATING); // CraftBukkit + flag = true; + } + +@@ -570,7 +594,7 @@ + super.aiStep(); + if (!this.level().isClientSide && this.isAlive()) { + if (this.random.nextInt(900) == 0 && this.deathTime == 0) { +- this.heal(1.0F); ++ this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit + } + + if (this.canEatGrass()) { +@@ -826,6 +861,7 @@ + if (this.getOwnerUUID() != null) { + compound.putUUID("Owner", this.getOwnerUUID()); + } ++ compound.putInt("Bukkit.MaxDomestication", this.maxDomestication); // CraftBukkit + + if (!this.inventory.getItem(0).isEmpty()) { + compound.put("SaddleItem", this.inventory.getItem(0).save(new CompoundTag())); +@@ -850,6 +889,11 @@ + if (uUID != null) { + this.setOwnerUUID(uUID); + } ++ // CraftBukkit start ++ if (compound.contains("Bukkit.MaxDomestication")) { ++ this.maxDomestication = compound.getInt("Bukkit.MaxDomestication"); ++ } ++ // CraftBukkit end + + if (compound.contains("SaddleItem", 10)) { + ItemStack itemStack = ItemStack.of(compound.getCompound("SaddleItem")); +@@ -947,6 +996,17 @@ + + @Override + public void handleStartJump(int jumpPower) { ++ // CraftBukkit start ++ float power; ++ if (jumpPower >= 90) { ++ power = 1.0F; ++ } else { ++ power = 0.4F + 0.4F * (float) jumpPower / 90.0F; ++ } ++ if (!CraftEventFactory.callHorseJumpEvent(this, power)) { ++ return; ++ } ++ // CraftBukkit end + this.allowStandSliding = true; + this.standIfPossible(); + this.playJumpSound(); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/horse/Llama.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/horse/Llama.java.patch new file mode 100644 index 0000000000..c9ec510516 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/horse/Llama.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/entity/animal/horse/Llama.java ++++ b/net/minecraft/world/entity/animal/horse/Llama.java +@@ -81,6 +84,11 @@ + return false; + } + ++ // CraftBukkit start ++ public void setStrengthPublic(int i) { ++ this.setStrength(i); ++ } ++ // CraftBukkit end + private void setStrength(int strength) { + this.entityData.set(DATA_STRENGTH_ID, Math.max(1, Math.min(5, strength))); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java.patch new file mode 100644 index 0000000000..0c833c627f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java.patch @@ -0,0 +1,37 @@ +--- a/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java ++++ b/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java +@@ -42,14 +38,26 @@ + skeleton.startRiding(this.horse); + serverLevel.addFreshEntityWithPassengers(skeleton); + +- for (int i = 0; i < 3; i++) { +- AbstractHorse abstractHorse = this.createHorse(currentDifficultyAt); +- if (abstractHorse != null) { +- Skeleton skeleton1 = this.createSkeleton(currentDifficultyAt, abstractHorse); +- if (skeleton1 != null) { +- skeleton1.startRiding(abstractHorse); +- abstractHorse.push(this.horse.getRandom().triangle(0.0, 1.1485), 0.0, this.horse.getRandom().triangle(0.0, 1.1485)); +- serverLevel.addFreshEntityWithPassengers(abstractHorse); ++ if (entitylightning != null) { ++ entitylightning.moveTo(this.horse.getX(), this.horse.getY(), this.horse.getZ()); ++ entitylightning.setVisualOnly(true); ++ worldserver.strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.TRAP); // CraftBukkit ++ Skeleton entityskeleton = this.createSkeleton(difficultydamagescaler, this.horse); ++ ++ if (entityskeleton != null) { ++ entityskeleton.startRiding(this.horse); ++ worldserver.addFreshEntityWithPassengers(entityskeleton, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.TRAP); // CraftBukkit ++ ++ for (int i = 0; i < 3; ++i) { ++ AbstractHorse entityhorseabstract = this.createHorse(difficultydamagescaler); ++ ++ if (entityhorseabstract != null) { ++ Skeleton entityskeleton1 = this.createSkeleton(difficultydamagescaler, entityhorseabstract); ++ ++ if (entityskeleton1 != null) { ++ entityskeleton1.startRiding(entityhorseabstract); ++ entityhorseabstract.push(this.horse.getRandom().triangle(0.0D, 1.1485D), 0.0D, this.horse.getRandom().triangle(0.0D, 1.1485D)); ++ worldserver.addFreshEntityWithPassengers(entityhorseabstract, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.JOCKEY); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/horse/TraderLlama.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/horse/TraderLlama.java.patch new file mode 100644 index 0000000000..bdb92a4495 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/horse/TraderLlama.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/entity/animal/horse/TraderLlama.java ++++ b/net/minecraft/world/entity/animal/horse/TraderLlama.java +@@ -142,10 +153,11 @@ + + @Override + public void start() { +- this.mob.setTarget(this.ownerLastHurtBy); +- Entity leashHolder = this.llama.getLeashHolder(); +- if (leashHolder instanceof WanderingTrader) { +- this.timestamp = ((WanderingTrader)leashHolder).getLastHurtByMobTimestamp(); ++ this.mob.setTarget(this.ownerLastHurtBy, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_OWNER, true); // CraftBukkit ++ Entity entity = this.llama.getLeashHolder(); ++ ++ if (entity instanceof WanderingTrader) { ++ this.timestamp = ((WanderingTrader) entity).getLastHurtByMobTimestamp(); + } + + super.start(); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/sniffer/Sniffer.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/sniffer/Sniffer.java.patch new file mode 100644 index 0000000000..597a35b403 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/animal/sniffer/Sniffer.java.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/entity/animal/sniffer/Sniffer.java ++++ b/net/minecraft/world/entity/animal/sniffer/Sniffer.java +@@ -81,16 +83,25 @@ + + public Sniffer(EntityType entityType, Level level) { + super(entityType, level); +- this.entityData.define(DATA_STATE, Sniffer.State.IDLING); +- this.entityData.define(DATA_DROP_SEED_AT_TICK, 0); ++ // this.entityData.define(Sniffer.DATA_STATE, Sniffer.State.IDLING); // CraftBukkit - moved down to appropriate location ++ // this.entityData.define(Sniffer.DATA_DROP_SEED_AT_TICK, 0); // CraftBukkit - moved down to appropriate location + this.getNavigation().setCanFloat(true); + this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); + this.setPathfindingMalus(BlockPathTypes.DANGER_POWDER_SNOW, -1.0F); + this.setPathfindingMalus(BlockPathTypes.DAMAGE_CAUTIOUS, -1.0F); + } + ++ // CraftBukkit start - SPIGOT-7295: moved from constructor to appropriate location + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) { ++ protected void defineSynchedData() { ++ super.defineSynchedData(); ++ this.entityData.define(Sniffer.DATA_STATE, Sniffer.State.IDLING); ++ this.entityData.define(Sniffer.DATA_DROP_SEED_AT_TICK, 0); ++ } ++ // CraftBukkit end ++ ++ @Override ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions dimensions) { + return this.getDimensions(pose).height * 0.6F; + } + +@@ -271,10 +272,19 @@ + List randomItems = lootTable.getRandomItems(lootParams); + BlockPos headBlock = this.getHeadBlock(); + +- for (ItemStack itemStack : randomItems) { +- ItemEntity itemEntity = new ItemEntity(serverLevel, (double)headBlock.getX(), (double)headBlock.getY(), (double)headBlock.getZ(), itemStack); +- itemEntity.setDefaultPickUpDelay(); +- serverLevel.addFreshEntity(itemEntity); ++ while (iterator.hasNext()) { ++ ItemStack itemstack = (ItemStack) iterator.next(); ++ ItemEntity entityitem = new ItemEntity(worldserver, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), itemstack); ++ ++ // CraftBukkit start - handle EntityDropItemEvent ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end ++ entityitem.setDefaultPickUpDelay(); ++ worldserver.addFreshEntity(entityitem); + } + + this.playSound(SoundEvents.SNIFFER_DROP_SEED, 1.0F, 1.0F); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java.patch new file mode 100644 index 0000000000..9c1b232434 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java.patch @@ -0,0 +1,57 @@ +--- a/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java ++++ b/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java +@@ -18,6 +19,10 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.BaseFireBlock; + import net.minecraft.world.level.dimension.end.EndDragonFight; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end + + public class EndCrystal extends Entity { + private static final EntityDataAccessor> DATA_BEAM_TARGET = SynchedEntityData.defineId( +@@ -52,9 +56,14 @@ + public void tick() { + this.time++; + if (this.level() instanceof ServerLevel) { +- BlockPos blockPos = this.blockPosition(); +- if (((ServerLevel)this.level()).getDragonFight() != null && this.level().getBlockState(blockPos).isAir()) { +- this.level().setBlockAndUpdate(blockPos, BaseFireBlock.getState(this.level(), blockPos)); ++ BlockPos blockposition = this.blockPosition(); ++ ++ if (((ServerLevel) this.level()).getDragonFight() != null && this.level().getBlockState(blockposition).isAir()) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition, this).isCancelled()) { ++ this.level().setBlockAndUpdate(blockposition, BaseFireBlock.getState(this.level(), blockposition)); ++ } ++ // CraftBukkit end + } + } + } +@@ -92,10 +103,23 @@ + return false; + } else { + if (!this.isRemoved() && !this.level().isClientSide) { ++ // CraftBukkit start - All non-living entities need this ++ if (CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, false)) { ++ return false; ++ } ++ // CraftBukkit end + this.remove(Entity.RemovalReason.KILLED); + if (!source.is(DamageTypeTags.IS_EXPLOSION)) { +- DamageSource damageSource = source.getEntity() != null ? this.damageSources().explosion(this, source.getEntity()) : null; +- this.level().explode(this, damageSource, null, this.getX(), this.getY(), this.getZ(), 6.0F, false, Level.ExplosionInteraction.BLOCK); ++ DamageSource damagesource1 = source.getEntity() != null ? this.damageSources().explosion(this, source.getEntity()) : null; ++ ++ // CraftBukkit start ++ ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent(this, 6.0F, false); ++ if (event.isCancelled()) { ++ this.unsetRemoved(); ++ return false; ++ } ++ this.level().explode(this, damagesource1, (ExplosionDamageCalculator) null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.BLOCK); ++ // CraftBukkit end + } + + this.onDestroyedBy(source); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java.patch new file mode 100644 index 0000000000..15b1ccddaa --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java.patch @@ -0,0 +1,258 @@ +--- a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java ++++ b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +@@ -52,7 +51,22 @@ + import org.joml.Vector3f; + import org.slf4j.Logger; + +-public class EnderDragon extends Mob implements Enemy { ++// CraftBukkit start ++import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.level.Explosion; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.entity.BlockEntity; ++import net.minecraft.world.level.storage.loot.LootParams; ++import net.minecraft.world.level.storage.loot.parameters.LootContextParams; ++import net.minecraft.world.phys.AABB; ++import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.entity.EntityExplodeEvent; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++// CraftBukkit end ++ ++public class EnderDragon extends Mob implements IMonster { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + public static final EntityDataAccessor DATA_PHASE = SynchedEntityData.defineId(EnderDragon.class, EntityDataSerializers.INT); + private static final TargetingConditions CRYSTAL_DESTROY_TARGETING = TargetingConditions.forCombat().range(64.0); +@@ -85,9 +99,10 @@ + private final EnderDragonPhaseManager phaseManager; + private int growlTime = 100; + private float sittingDamageReceived; +- private final Node[] nodes = new Node[24]; +- private final int[] nodeAdjacency = new int[24]; +- private final BinaryHeap openSet = new BinaryHeap(); ++ private final Node[] nodes; ++ private final int[] nodeAdjacency; ++ private final BinaryHeap openSet; ++ private final Explosion explosionSource; // CraftBukkit - reusable source for CraftTNTPrimed.getSource() + + public EnderDragon(EntityType entityType, Level level) { + super(EntityType.ENDER_DRAGON, level); +@@ -104,6 +124,7 @@ + this.noPhysics = true; + this.noCulling = true; + this.phaseManager = new EnderDragonPhaseManager(this); ++ this.explosionSource = new Explosion(level, this, null, null, Double.NaN, Double.NaN, Double.NaN, Float.NaN, true, Explosion.Effect.DESTROY, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); // CraftBukkit + } + + public void setDragonFight(EndDragonFight dragonFight) { +@@ -250,16 +270,18 @@ + currentPhase.doServerTick(); + } + +- Vec3 flyTargetLocation = currentPhase.getFlyTargetLocation(); +- if (flyTargetLocation != null) { +- double d = flyTargetLocation.x - this.getX(); +- double d1 = flyTargetLocation.y - this.getY(); +- double d2 = flyTargetLocation.z - this.getZ(); +- double d3 = d * d + d1 * d1 + d2 * d2; +- float flySpeed = currentPhase.getFlySpeed(); +- double squareRoot = Math.sqrt(d * d + d2 * d2); +- if (squareRoot > 0.0) { +- d1 = Mth.clamp(d1 / squareRoot, (double)(-flySpeed), (double)flySpeed); ++ Vec3 vec3d1 = idragoncontroller.getFlyTargetLocation(); ++ ++ if (vec3d1 != null && idragoncontroller.getPhase() != EnderDragonPhase.HOVERING) { // CraftBukkit - Don't move when hovering ++ double d0 = vec3d1.x - this.getX(); ++ double d1 = vec3d1.y - this.getY(); ++ double d2 = vec3d1.z - this.getZ(); ++ double d3 = d0 * d0 + d1 * d1 + d2 * d2; ++ float f6 = idragoncontroller.getFlySpeed(); ++ double d4 = Math.sqrt(d0 * d0 + d2 * d2); ++ ++ if (d4 > 0.0D) { ++ d1 = Mth.clamp(d1 / d4, (double) (-f6), (double) f6); + } + + this.setDeltaMovement(this.getDeltaMovement().add(0.0, d1 * 0.01, 0.0)); +@@ -398,7 +413,14 @@ + if (this.nearestCrystal.isRemoved()) { + this.nearestCrystal = null; + } else if (this.tickCount % 10 == 0 && this.getHealth() < this.getMaxHealth()) { +- this.setHealth(this.getHealth() + 1.0F); ++ // CraftBukkit start ++ EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), 1.0F, EntityRegainHealthEvent.RegainReason.ENDER_CRYSTAL); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ this.setHealth((float) (this.getHealth() + event.getAmount())); ++ } ++ // CraftBukkit end + } + } + +@@ -459,15 +495,23 @@ + int floor5 = Mth.floor(area.maxZ); + boolean flag = false; + boolean flag1 = false; ++ // CraftBukkit start - Create a list to hold all the destroyed blocks ++ List destroyedBlocks = new java.util.ArrayList(); ++ // CraftBukkit end + +- for (int i = floor; i <= floor3; i++) { +- for (int i1 = floor1; i1 <= floor4; i1++) { +- for (int i2 = floor2; i2 <= floor5; i2++) { +- BlockPos blockPos = new BlockPos(i, i1, i2); +- BlockState blockState = this.level().getBlockState(blockPos); +- if (!blockState.isAir() && !blockState.is(BlockTags.DRAGON_TRANSPARENT)) { +- if (this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && !blockState.is(BlockTags.DRAGON_IMMUNE)) { +- flag1 = this.level().removeBlock(blockPos, false) || flag1; ++ for (int k1 = i; k1 <= l; ++k1) { ++ for (int l1 = j; l1 <= i1; ++l1) { ++ for (int i2 = k; i2 <= j1; ++i2) { ++ BlockPos blockposition = new BlockPos(k1, l1, i2); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); ++ ++ if (!iblockdata.isAir() && !iblockdata.is(BlockTags.DRAGON_TRANSPARENT)) { ++ if (this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && !iblockdata.is(BlockTags.DRAGON_IMMUNE)) { ++ // CraftBukkit start - Add blocks to list rather than destroying them ++ // flag1 = this.level().removeBlock(blockposition, false) || flag1; ++ flag1 = true; ++ destroyedBlocks.add(CraftBlock.at(this.level(), blockposition)); ++ // CraftBukkit end + } else { + flag = true; + } +@@ -476,6 +520,51 @@ + } + } + ++ // CraftBukkit start - Set off an EntityExplodeEvent for the dragon exploding all these blocks ++ // SPIGOT-4882: don't fire event if nothing hit ++ if (!flag1) { ++ return flag; ++ } ++ ++ org.bukkit.entity.Entity bukkitEntity = this.getBukkitEntity(); ++ EntityExplodeEvent event = new EntityExplodeEvent(bukkitEntity, bukkitEntity.getLocation(), destroyedBlocks, 0F); ++ bukkitEntity.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ // This flag literally means 'Dragon hit something hard' (Obsidian, White Stone or Bedrock) and will cause the dragon to slow down. ++ // We should consider adding an event extension for it, or perhaps returning true if the event is cancelled. ++ return flag; ++ } else if (event.getYield() == 0F) { ++ // Yield zero ==> no drops ++ for (org.bukkit.block.Block block : event.blockList()) { ++ this.level().removeBlock(new BlockPos(block.getX(), block.getY(), block.getZ()), false); ++ } ++ } else { ++ for (org.bukkit.block.Block block : event.blockList()) { ++ org.bukkit.Material blockId = block.getType(); ++ if (blockId.isAir()) { ++ continue; ++ } ++ ++ CraftBlock craftBlock = ((CraftBlock) block); ++ BlockPos blockposition = craftBlock.getPosition(); ++ ++ Block nmsBlock = craftBlock.getNMS().getBlock(); ++ if (nmsBlock.dropFromExplosion(explosionSource)) { ++ BlockEntity tileentity = craftBlock.getNMS().hasBlockEntity() ? this.level().getBlockEntity(blockposition) : null; ++ LootParams.Builder loottableinfo_builder = (new LootParams.Builder((ServerLevel) this.level())).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockposition)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withParameter(LootContextParams.EXPLOSION_RADIUS, 1.0F / event.getYield()).withOptionalParameter(LootContextParams.BLOCK_ENTITY, tileentity); ++ ++ craftBlock.getNMS().getDrops(loottableinfo_builder).forEach((itemstack) -> { ++ Block.popResource(this.level(), blockposition, itemstack); ++ }); ++ craftBlock.getNMS().spawnAfterBreak((ServerLevel) this.level(), blockposition, ItemStack.EMPTY, false); ++ } ++ nmsBlock.wasExploded(this.level(), blockposition, explosionSource); ++ ++ this.level().removeBlock(blockposition, false); ++ } ++ } ++ // CraftBukkit end ++ + if (flag1) { + BlockPos blockPos1 = new BlockPos( + floor + this.random.nextInt(floor3 - floor + 1), +@@ -541,7 +629,22 @@ + } + } + ++ // CraftBukkit start - SPIGOT-2420: Special case, the ender dragon drops 12000 xp for the first kill and 500 xp for every other kill and this over time. + @Override ++ public int getExpReward() { ++ // CraftBukkit - Moved from #tickDeath method ++ boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT); ++ short short0 = 500; ++ ++ if (this.dragonFight != null && !this.dragonFight.hasPreviouslyKilledDragon()) { ++ short0 = 12000; ++ } ++ ++ return flag ? short0 : 0; ++ } ++ // CraftBukkit end ++ ++ @Override + protected void tickDeath() { + if (this.dragonFight != null) { + this.dragonFight.updateDragon(this); +@@ -556,15 +659,21 @@ + .addParticle(ParticleTypes.EXPLOSION_EMITTER, this.getX() + (double)f, this.getY() + 2.0 + (double)f1, this.getZ() + (double)f2, 0.0, 0.0, 0.0); + } + +- boolean _boolean = this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT); +- int i = 500; ++ // CraftBukkit start - SPIGOT-2420: Moved up to #getExpReward method ++ /* ++ boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT); ++ short short0 = 500; ++ + if (this.dragonFight != null && !this.dragonFight.hasPreviouslyKilledDragon()) { + i = 12000; + } ++ */ ++ int short0 = expToDrop; ++ // CraftBukkit end + + if (this.level() instanceof ServerLevel) { +- if (this.dragonDeathTime > 150 && this.dragonDeathTime % 5 == 0 && _boolean) { +- ExperienceOrb.award((ServerLevel)this.level(), this.position(), Mth.floor((float)i * 0.08F)); ++ if (this.dragonDeathTime > 150 && this.dragonDeathTime % 5 == 0 && true) { // CraftBukkit - SPIGOT-2420: Already checked for the game rule when calculating the xp ++ ExperienceOrb.award((ServerLevel) this.level(), this.position(), Mth.floor((float) short0 * 0.08F)); + } + + if (this.dragonDeathTime == 1 && !this.isSilent()) { +@@ -574,8 +683,8 @@ + + this.move(MoverType.SELF, new Vec3(0.0, 0.1F, 0.0)); + if (this.dragonDeathTime == 200 && this.level() instanceof ServerLevel) { +- if (_boolean) { +- ExperienceOrb.award((ServerLevel)this.level(), this.position(), Mth.floor((float)i * 0.2F)); ++ if (true) { // CraftBukkit - SPIGOT-2420: Already checked for the game rule when calculating the xp ++ ExperienceOrb.award((ServerLevel) this.level(), this.position(), Mth.floor((float) short0 * 0.2F)); + } + + if (this.dragonFight != null) { +@@ -767,6 +904,7 @@ + super.addAdditionalSaveData(compound); + compound.putInt("DragonPhase", this.phaseManager.getCurrentPhase().getPhase().getId()); + compound.putInt("DragonDeathTime", this.dragonDeathTime); ++ compound.putInt("Bukkit.expToDrop", expToDrop); // CraftBukkit - SPIGOT-2420: The ender dragon drops xp over time which can also happen between server starts + } + + @Override +@@ -779,6 +917,12 @@ + if (compound.contains("DragonDeathTime")) { + this.dragonDeathTime = compound.getInt("DragonDeathTime"); + } ++ ++ // CraftBukkit start - SPIGOT-2420: The ender dragon drops xp over time which can also happen between server starts ++ if (compound.contains("Bukkit.expToDrop")) { ++ this.expToDrop = compound.getInt("Bukkit.expToDrop"); ++ } ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhaseManager.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhaseManager.java.patch new file mode 100644 index 0000000000..aed8d587b5 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhaseManager.java.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhaseManager.java ++++ b/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhaseManager.java +@@ -5,6 +5,11 @@ + import net.minecraft.world.entity.boss.enderdragon.EnderDragon; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftEnderDragon; ++import org.bukkit.event.entity.EnderDragonChangePhaseEvent; ++// CraftBukkit end ++ + public class EnderDragonPhaseManager { + private static final Logger LOGGER = LogUtils.getLogger(); + private final EnderDragon dragon; +@@ -23,7 +29,20 @@ + this.currentPhase.end(); + } + +- this.currentPhase = this.getPhase((EnderDragonPhase)phase); ++ // CraftBukkit start - Call EnderDragonChangePhaseEvent ++ EnderDragonChangePhaseEvent event = new EnderDragonChangePhaseEvent( ++ (CraftEnderDragon) this.dragon.getBukkitEntity(), ++ (this.currentPhase == null) ? null : CraftEnderDragon.getBukkitPhase(this.currentPhase.getPhase()), ++ CraftEnderDragon.getBukkitPhase(phase) ++ ); ++ this.dragon.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ phase = CraftEnderDragon.getMinecraftPhase(event.getNewPhase()); ++ // CraftBukkit end ++ ++ this.currentPhase = this.getPhase(phase); + if (!this.dragon.level().isClientSide) { + this.dragon.getEntityData().set(EnderDragon.DATA_PHASE, phase.getId()); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/boss/wither/WitherBoss.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/boss/wither/WitherBoss.java.patch new file mode 100644 index 0000000000..d0328a9f3e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/boss/wither/WitherBoss.java.patch @@ -0,0 +1,134 @@ +--- a/net/minecraft/world/entity/boss/wither/WitherBoss.java ++++ b/net/minecraft/world/entity/boss/wither/WitherBoss.java +@@ -53,6 +43,26 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.Vec3; ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.particles.ParticleTypes; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.network.chat.Component; ++import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; ++import net.minecraft.network.syncher.EntityDataAccessor; ++import net.minecraft.network.syncher.EntityDataSerializers; ++import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerBossEvent; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundEvents; ++import net.minecraft.world.level.block.Blocks; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end + + public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob { + private static final EntityDataAccessor DATA_TARGET_A = SynchedEntityData.defineId(WitherBoss.class, EntityDataSerializers.INT); +@@ -256,15 +257,40 @@ + int i = this.getInvulnerableTicks() - 1; + this.bossEvent.setProgress(1.0F - (float)i / 220.0F); + if (i <= 0) { +- this.level().explode(this, this.getX(), this.getEyeY(), this.getZ(), 7.0F, false, Level.ExplosionInteraction.MOB); ++ // CraftBukkit start ++ // this.level().explode(this, this.getX(), this.getEyeY(), this.getZ(), 7.0F, false, World.a.MOB); ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), 7.0F, false); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ this.level().explode(this, this.getX(), this.getEyeY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.MOB); ++ } ++ // CraftBukkit end ++ + if (!this.isSilent()) { +- this.level().globalLevelEvent(1023, this.blockPosition(), 0); ++ // CraftBukkit start - Use relative location for far away sounds ++ // this.level().globalLevelEvent(1023, new BlockPosition(this), 0); ++ int viewDistance = ((ServerLevel) this.level()).getCraftServer().getViewDistance() * 16; ++ for (ServerPlayer player : (List) MinecraftServer.getServer().getPlayerList().players) { ++ double deltaX = this.getX() - player.getX(); ++ double deltaZ = this.getZ() - player.getZ(); ++ double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; ++ if (distanceSquared > viewDistance * viewDistance) { ++ double deltaLength = Math.sqrt(distanceSquared); ++ double relativeX = player.getX() + (deltaX / deltaLength) * viewDistance; ++ double relativeZ = player.getZ() + (deltaZ / deltaLength) * viewDistance; ++ player.connection.send(new ClientboundLevelEventPacket(1023, new BlockPos((int) relativeX, (int) this.getY(), (int) relativeZ), 0, true)); ++ } else { ++ player.connection.send(new ClientboundLevelEventPacket(1023, this.blockPosition(), 0, true)); ++ } ++ } ++ // CraftBukkit end + } + } + + this.setInvulnerableTicks(i); + if (this.tickCount % 10 == 0) { +- this.heal(10.0F); ++ this.heal(10.0F, EntityRegainHealthEvent.RegainReason.WITHER_SPAWN); // CraftBukkit + } + } else { + super.customServerAiStep(); +@@ -297,11 +330,13 @@ + this.setAlternativeTarget(ix, 0); + } + } else { +- List nearbyEntities = this.level() +- .getNearbyEntities(LivingEntity.class, TARGETING_CONDITIONS, this, this.getBoundingBox().inflate(20.0, 8.0, 20.0)); +- if (!nearbyEntities.isEmpty()) { +- LivingEntity livingEntity1 = nearbyEntities.get(this.random.nextInt(nearbyEntities.size())); +- this.setAlternativeTarget(ix, livingEntity1.getId()); ++ List list = this.level().getNearbyEntities(LivingEntity.class, WitherBoss.TARGETING_CONDITIONS, this, this.getBoundingBox().inflate(20.0D, 8.0D, 20.0D)); ++ ++ if (!list.isEmpty()) { ++ LivingEntity entityliving1 = (LivingEntity) list.get(this.random.nextInt(list.size())); ++ ++ if (CraftEventFactory.callEntityTargetLivingEvent(this, entityliving1, EntityTargetEvent.TargetReason.CLOSEST_ENTITY).isCancelled()) continue; // CraftBukkit ++ this.setAlternativeTarget(i, entityliving1.getId()); + } + } + } +@@ -321,16 +356,22 @@ + int floor = Mth.floor(this.getZ()); + boolean flag = false; + +- for (int i1 = -1; i1 <= 1; i1++) { +- for (int i2 = -1; i2 <= 1; i2++) { +- for (int i3 = 0; i3 <= 3; i3++) { +- int i4 = alternativeTarget + i1; +- int i5 = ixx + i3; +- int i6 = floor + i2; +- BlockPos blockPos = new BlockPos(i4, i5, i6); +- BlockState blockState = this.level().getBlockState(blockPos); +- if (canDestroy(blockState)) { +- flag = this.level().destroyBlock(blockPos, true, this) || flag; ++ for (int j1 = -1; j1 <= 1; ++j1) { ++ for (int k1 = -1; k1 <= 1; ++k1) { ++ for (int l1 = 0; l1 <= 3; ++l1) { ++ int i2 = j + j1; ++ int j2 = i + l1; ++ int k2 = i1 + k1; ++ BlockPos blockposition = new BlockPos(i2, j2, k2); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); ++ ++ if (canDestroy(iblockdata)) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState())) { ++ continue; ++ } ++ // CraftBukkit end ++ flag = this.level().destroyBlock(blockposition, true, this) || flag; + } + } + } +@@ -343,7 +384,7 @@ + } + + if (this.tickCount % 20 == 0) { +- this.heal(1.0F); ++ this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit + } + + this.bossEvent.setProgress(this.getHealth() / this.getMaxHealth()); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/decoration/ArmorStand.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/decoration/ArmorStand.java.patch new file mode 100644 index 0000000000..24f5e342ed --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/decoration/ArmorStand.java.patch @@ -0,0 +1,259 @@ +--- a/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -41,6 +41,13 @@ + import net.minecraft.world.level.material.PushReaction; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.inventory.EquipmentSlot; ++import org.bukkit.craftbukkit.CraftEquipmentSlot; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerArmorStandManipulateEvent; ++// CraftBukkit end + + public class ArmorStand extends LivingEntity { + public static final int WOBBLE_TIME = 5; +@@ -94,7 +111,14 @@ + this.setPos(x, y, z); + } + ++ // CraftBukkit start - SPIGOT-3607, SPIGOT-3637 + @Override ++ public float getBukkitYaw() { ++ return this.getYRot(); ++ } ++ // CraftBukkit end ++ ++ @Override + public void refreshDimensions() { + double x = this.getX(); + double y = this.getY(); +@@ -147,14 +172,21 @@ + } + + @Override +- public void setItemSlot(EquipmentSlot slot, ItemStack stack) { +- this.verifyEquippedItem(stack); +- switch (slot.getType()) { ++ public void setItemSlot(net.minecraft.world.entity.EquipmentSlot slot, ItemStack stack) { ++ // CraftBukkit start ++ this.setItemSlot(slot, stack, false); ++ } ++ ++ @Override ++ public void setItemSlot(net.minecraft.world.entity.EquipmentSlot enumitemslot, ItemStack itemstack, boolean silent) { ++ // CraftBukkit end ++ this.verifyEquippedItem(itemstack); ++ switch (enumitemslot.getType()) { + case HAND: +- this.onEquipItem(slot, this.handItems.set(slot.getIndex(), stack), stack); ++ this.onEquipItem(enumitemslot, (ItemStack) this.handItems.set(enumitemslot.getIndex(), itemstack), itemstack, silent); // CraftBukkit + break; + case ARMOR: +- this.onEquipItem(slot, this.armorItems.set(slot.getIndex(), stack), stack); ++ this.onEquipItem(enumitemslot, (ItemStack) this.armorItems.set(enumitemslot.getIndex(), itemstack), itemstack, silent); // CraftBukkit + } + } + +@@ -360,7 +421,25 @@ + return false; + } else if (itemBySlot.isEmpty() && (this.disabledSlots & 1 << slot.getFilterFlag() + 16) != 0) { + return false; +- } else if (player.getAbilities().instabuild && itemBySlot.isEmpty() && !stack.isEmpty()) { ++ // CraftBukkit start ++ } else { ++ org.bukkit.inventory.ItemStack armorStandItem = CraftItemStack.asCraftMirror(itemstack1); ++ org.bukkit.inventory.ItemStack playerHeldItem = CraftItemStack.asCraftMirror(stack); ++ ++ Player player1 = (Player) player.getBukkitEntity(); ++ org.bukkit.entity.ArmorStand self = (org.bukkit.entity.ArmorStand) this.getBukkitEntity(); ++ ++ EquipmentSlot slot1 = CraftEquipmentSlot.getSlot(slot); ++ EquipmentSlot hand = CraftEquipmentSlot.getHand(hand); ++ PlayerArmorStandManipulateEvent armorStandManipulateEvent = new PlayerArmorStandManipulateEvent(player1, self, playerHeldItem, armorStandItem, slot1, hand); ++ this.level().getCraftServer().getPluginManager().callEvent(armorStandManipulateEvent); ++ ++ if (armorStandManipulateEvent.isCancelled()) { ++ return true; ++ } ++ ++ if (player.getAbilities().instabuild && itemstack1.isEmpty() && !stack.isEmpty()) { ++ // CraftBukkit end + this.setItemSlot(slot, stack.copyWithCount(1)); + return true; + } else if (stack.isEmpty() || stack.getCount() <= 1) { +@@ -373,45 +454,28 @@ + this.setItemSlot(slot, stack.split(1)); + return true; + } ++ } // CraftBukkit + } + + @Override + public boolean hurt(DamageSource source, float amount) { +- if (this.level().isClientSide || this.isRemoved()) { +- return false; +- } else if (source.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { +- this.kill(); +- return false; +- } else if (this.isInvulnerableTo(source) || this.invisible || this.isMarker()) { +- return false; +- } else if (source.is(DamageTypeTags.IS_EXPLOSION)) { +- this.brokenByAnything(source); +- this.kill(); +- return false; +- } else if (source.is(DamageTypeTags.IGNITES_ARMOR_STANDS)) { +- if (this.isOnFire()) { +- this.causeDamage(source, 0.15F); +- } else { +- this.setSecondsOnFire(5); +- } +- +- return false; +- } else if (source.is(DamageTypeTags.BURNS_ARMOR_STANDS) && this.getHealth() > 0.5F) { +- this.causeDamage(source, 4.0F); +- return false; +- } else { +- boolean isCanBreakArmorStand = source.is(DamageTypeTags.CAN_BREAK_ARMOR_STAND); +- boolean isAlwaysKillsArmorStands = source.is(DamageTypeTags.ALWAYS_KILLS_ARMOR_STANDS); +- if (!isCanBreakArmorStand && !isAlwaysKillsArmorStands) { ++ if (!this.level().isClientSide && !this.isRemoved()) { ++ if (source.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount)) { ++ return false; ++ } ++ // CraftBukkit end ++ this.kill(); + return false; +- } else { +- if (source.getEntity() instanceof Player player && !player.getAbilities().mayBuild) { ++ } else if (!this.isInvulnerableTo(source) && (true || !this.invisible) && !this.isMarker()) { // CraftBukkit ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, true, this.invisible)) { + return false; + } +- +- if (source.isCreativePlayer()) { +- this.playBrokenSound(); +- this.showBreakingParticles(); ++ // CraftBukkit end ++ if (source.is(DamageTypeTags.IS_EXPLOSION)) { ++ this.brokenByAnything(source); + this.kill(); + return true; + } else { +@@ -426,7 +485,48 @@ + this.kill(); + } + +- return true; ++ return false; ++ } else if (source.is(DamageTypeTags.BURNS_ARMOR_STANDS) && this.getHealth() > 0.5F) { ++ this.causeDamage(source, 4.0F); ++ return false; ++ } else { ++ boolean flag = source.is(DamageTypeTags.CAN_BREAK_ARMOR_STAND); ++ boolean flag1 = source.is(DamageTypeTags.ALWAYS_KILLS_ARMOR_STANDS); ++ ++ if (!flag && !flag1) { ++ return false; ++ } else { ++ Entity entity = source.getEntity(); ++ ++ if (entity instanceof net.minecraft.world.entity.player.Player) { ++ net.minecraft.world.entity.player.Player entityhuman = (net.minecraft.world.entity.player.Player) entity; ++ ++ if (!entityhuman.getAbilities().mayBuild) { ++ return false; ++ } ++ } ++ ++ if (source.isCreativePlayer()) { ++ this.playBrokenSound(); ++ this.showBreakingParticles(); ++ this.kill(); ++ return true; ++ } else { ++ long i = this.level().getGameTime(); ++ ++ if (i - this.lastHit > 5L && !flag1) { ++ this.level().broadcastEntityEvent(this, (byte) 32); ++ this.gameEvent(GameEvent.ENTITY_DAMAGE, source.getEntity()); ++ this.lastHit = i; ++ } else { ++ this.brokenByPlayer(source); ++ this.showBreakingParticles(); ++ this.discard(); // CraftBukkit - SPIGOT-4890: remain as this.discard() since above damagesource method will call death event ++ } ++ ++ return true; ++ } ++ } + } + } + } +@@ -490,29 +589,34 @@ + itemStack.setHoverName(this.getCustomName()); + } + +- Block.popResource(this.level(), this.blockPosition(), itemStack); ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops + this.brokenByAnything(damageSource); + } + + private void brokenByAnything(DamageSource damageSource) { + this.playBrokenSound(); +- this.dropAllDeathLoot(damageSource); ++ // this.dropAllDeathLoot(damagesource); // CraftBukkit - moved down + +- for (int i = 0; i < this.handItems.size(); i++) { +- ItemStack itemStack = this.handItems.get(i); +- if (!itemStack.isEmpty()) { +- Block.popResource(this.level(), this.blockPosition().above(), itemStack); ++ ItemStack itemstack; ++ int i; ++ ++ for (i = 0; i < this.handItems.size(); ++i) { ++ itemstack = (ItemStack) this.handItems.get(i); ++ if (!itemstack.isEmpty()) { ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops + this.handItems.set(i, ItemStack.EMPTY); + } + } + +- for (int ix = 0; ix < this.armorItems.size(); ix++) { +- ItemStack itemStack = this.armorItems.get(ix); +- if (!itemStack.isEmpty()) { +- Block.popResource(this.level(), this.blockPosition().above(), itemStack); +- this.armorItems.set(ix, ItemStack.EMPTY); ++ for (i = 0; i < this.armorItems.size(); ++i) { ++ itemstack = (ItemStack) this.armorItems.get(i); ++ if (!itemstack.isEmpty()) { ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops ++ this.armorItems.set(i, ItemStack.EMPTY); + } + } ++ this.dropAllDeathLoot(damageSource); // CraftBukkit - moved from above ++ + } + + private void playBrokenSound() { +@@ -600,8 +711,16 @@ + return this.isSmall(); + } + ++ // CraftBukkit start + @Override ++ public boolean shouldDropExperience() { ++ return true; // MC-157395, SPIGOT-5193 even baby (small) armor stands should drop ++ } ++ // CraftBukkit end ++ ++ @Override + public void kill() { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event + this.remove(Entity.RemovalReason.KILLED); + this.gameEvent(GameEvent.ENTITY_DIE); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/decoration/HangingEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/decoration/HangingEntity.java.patch new file mode 100644 index 0000000000..d25b03fe7f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/decoration/HangingEntity.java.patch @@ -0,0 +1,186 @@ +--- a/net/minecraft/world/entity/decoration/HangingEntity.java ++++ b/net/minecraft/world/entity/decoration/HangingEntity.java +@@ -25,6 +20,17 @@ + import net.minecraft.world.phys.Vec3; + import org.apache.commons.lang3.Validate; + import org.slf4j.Logger; ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.Direction; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.server.level.ServerLevel; ++// CraftBukkit start ++import net.minecraft.tags.DamageTypeTags; ++import net.minecraft.util.Mth; ++import org.bukkit.entity.Hanging; ++import org.bukkit.event.hanging.HangingBreakByEntityEvent; ++import org.bukkit.event.hanging.HangingBreakEvent; ++// CraftBukkit end + + public abstract class HangingEntity extends Entity { + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -57,24 +66,38 @@ + + protected void recalculateBoundingBox() { + if (this.direction != null) { +- double d = (double)this.pos.getX() + 0.5; +- double d1 = (double)this.pos.getY() + 0.5; +- double d2 = (double)this.pos.getZ() + 0.5; +- double d3 = 0.46875; +- double d4 = this.offs(this.getWidth()); +- double d5 = this.offs(this.getHeight()); +- d -= (double)this.direction.getStepX() * 0.46875; +- d2 -= (double)this.direction.getStepZ() * 0.46875; +- double var22 = d1 + d5; +- Direction counterClockWise = this.direction.getCounterClockWise(); +- double var21 = d + d4 * (double)counterClockWise.getStepX(); +- double var24 = d2 + d4 * (double)counterClockWise.getStepZ(); +- this.setPosRaw(var21, var22, var24); +- double d6 = (double)this.getWidth(); +- double d7 = (double)this.getHeight(); +- double d8 = (double)this.getWidth(); +- if (this.direction.getAxis() == Direction.Axis.Z) { +- d8 = 1.0; ++ // CraftBukkit start code moved in to calculateBoundingBox ++ this.setBoundingBox(calculateBoundingBox(this, this.pos, this.direction, this.getWidth(), this.getHeight())); ++ // CraftBukkit end ++ } ++ } ++ ++ // CraftBukkit start - break out BB calc into own method ++ public static AABB calculateBoundingBox(@Nullable Entity entity, BlockPos blockPosition, Direction direction, int width, int height) { ++ { ++ double d0 = (double) blockPosition.getX() + 0.5D; ++ double d1 = (double) blockPosition.getY() + 0.5D; ++ double d2 = (double) blockPosition.getZ() + 0.5D; ++ double d3 = 0.46875D; ++ double d4 = offs(width); ++ double d5 = offs(height); ++ ++ d0 -= (double) direction.getStepX() * 0.46875D; ++ d2 -= (double) direction.getStepZ() * 0.46875D; ++ d1 += d5; ++ Direction enumdirection = direction.getCounterClockWise(); ++ ++ d0 += d4 * (double) enumdirection.getStepX(); ++ d2 += d4 * (double) enumdirection.getStepZ(); ++ if (entity != null) { ++ entity.setPosRaw(d0, d1, d2); ++ } ++ double d6 = (double) width; ++ double d7 = (double) height; ++ double d8 = (double) width; ++ ++ if (direction.getAxis() == Direction.Axis.Z) { ++ d8 = 1.0D; + } else { + d6 = 1.0; + } +@@ -85,9 +108,10 @@ + this.setBoundingBox(new AABB(var21 - d6, var22 - d7, var24 - d8, var21 + d6, var22 + d7, var24 + d8)); + } + } ++ // CraftBukkit end + +- private double offs(int offset) { +- return offset % 32 == 0 ? 0.5 : 0.0; ++ private static double offs(int i) { // CraftBukkit - static ++ return i % 32 == 0 ? 0.5D : 0.0D; + } + + @Override +@@ -97,6 +121,24 @@ + if (this.checkInterval++ == 100) { + this.checkInterval = 0; + if (!this.isRemoved() && !this.survives()) { ++ // CraftBukkit start - fire break events ++ IBlockData material = this.level().getBlockState(this.blockPosition()); ++ HangingBreakEvent.RemoveCause cause; ++ ++ if (!material.isAir()) { ++ // TODO: This feels insufficient to catch 100% of suffocation cases ++ cause = HangingBreakEvent.RemoveCause.OBSTRUCTION; ++ } else { ++ cause = HangingBreakEvent.RemoveCause.PHYSICS; ++ } ++ ++ HangingBreakEvent event = new HangingBreakEvent((Hanging) this.getBukkitEntity(), cause); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (this.isRemoved() || event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.discard(); + this.dropItem(null); + } +@@ -151,6 +202,22 @@ + return false; + } else { + if (!this.isRemoved() && !this.level().isClientSide) { ++ // CraftBukkit start - fire break events ++ Entity damager = (source.isIndirect()) ? source.getEntity() : source.getDirectEntity(); ++ HangingBreakEvent event; ++ if (damager != null) { ++ event = new HangingBreakByEntityEvent((Hanging) this.getBukkitEntity(), damager.getBukkitEntity(), source.is(DamageTypeTags.IS_EXPLOSION) ? HangingBreakEvent.RemoveCause.EXPLOSION : HangingBreakEvent.RemoveCause.ENTITY); ++ } else { ++ event = new HangingBreakEvent((Hanging) this.getBukkitEntity(), source.is(DamageTypeTags.IS_EXPLOSION) ? HangingBreakEvent.RemoveCause.EXPLOSION : HangingBreakEvent.RemoveCause.DEFAULT); ++ } ++ ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (this.isRemoved() || event.isCancelled()) { ++ return true; ++ } ++ // CraftBukkit end ++ + this.kill(); + this.markHurt(); + this.dropItem(source.getEntity()); +@@ -161,22 +228,43 @@ + } + + @Override +- public void move(MoverType type, Vec3 pos) { +- if (!this.level().isClientSide && !this.isRemoved() && pos.lengthSqr() > 0.0) { ++ public void move(EnumMoveType type, Vec3 pos) { ++ if (!this.level().isClientSide && !this.isRemoved() && pos.lengthSqr() > 0.0D) { ++ if (this.isRemoved()) return; // CraftBukkit ++ ++ // CraftBukkit start - fire break events ++ // TODO - Does this need its own cause? Seems to only be triggered by pistons ++ HangingBreakEvent event = new HangingBreakEvent((Hanging) this.getBukkitEntity(), HangingBreakEvent.RemoveCause.PHYSICS); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (this.isRemoved() || event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ + this.kill(); + this.dropItem(null); + } + } + + @Override +- public void push(double x, double y, double z) { +- if (!this.level().isClientSide && !this.isRemoved() && x * x + y * y + z * z > 0.0) { ++ public void push(double x, double d1, double y) { ++ if (false && !this.level().isClientSide && !this.isRemoved() && x * x + d1 * d1 + y * y > 0.0D) { // CraftBukkit - not needed + this.kill(); + this.dropItem(null); + } + } + ++ // CraftBukkit start - selectively save tile position + @Override ++ public void addAdditionalSaveData(CompoundTag nbttagcompound, boolean includeAll) { ++ if (includeAll) { ++ addAdditionalSaveData(nbttagcompound); ++ } ++ } ++ // CraftBukkit end ++ ++ @Override + public void addAdditionalSaveData(CompoundTag compound) { + BlockPos pos = this.getPos(); + compound.putInt("TileX", pos.getX()); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/decoration/ItemFrame.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/decoration/ItemFrame.java.patch new file mode 100644 index 0000000000..3382e654fc --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/decoration/ItemFrame.java.patch @@ -0,0 +1,87 @@ +--- a/net/minecraft/world/entity/decoration/ItemFrame.java ++++ b/net/minecraft/world/entity/decoration/ItemFrame.java +@@ -93,16 +96,29 @@ + @Override + protected void recalculateBoundingBox() { + if (this.direction != null) { +- double d = 0.46875; +- double d1 = (double)this.pos.getX() + 0.5 - (double)this.direction.getStepX() * 0.46875; +- double d2 = (double)this.pos.getY() + 0.5 - (double)this.direction.getStepY() * 0.46875; +- double d3 = (double)this.pos.getZ() + 0.5 - (double)this.direction.getStepZ() * 0.46875; +- this.setPosRaw(d1, d2, d3); +- double d4 = (double)this.getWidth(); +- double d5 = (double)this.getHeight(); +- double d6 = (double)this.getWidth(); +- Direction.Axis axis = this.direction.getAxis(); +- switch (axis) { ++ // CraftBukkit start code moved in to calculateBoundingBox ++ this.setBoundingBox(calculateBoundingBox(this, this.pos, this.direction, this.getWidth(), this.getHeight())); ++ // CraftBukkit end ++ } ++ } ++ ++ // CraftBukkit start - break out BB calc into own method ++ public static AABB calculateBoundingBox(@Nullable Entity entity, BlockPos blockPosition, Direction direction, int width, int height) { ++ { ++ double d0 = 0.46875D; ++ double d1 = (double) blockPosition.getX() + 0.5D - (double) direction.getStepX() * 0.46875D; ++ double d2 = (double) blockPosition.getY() + 0.5D - (double) direction.getStepY() * 0.46875D; ++ double d3 = (double) blockPosition.getZ() + 0.5D - (double) direction.getStepZ() * 0.46875D; ++ ++ if (entity != null) { ++ entity.setPosRaw(d1, d2, d3); ++ } ++ double d4 = (double) width; ++ double d5 = (double) height; ++ double d6 = (double) width; ++ Direction.Axis enumdirection_enumaxis = direction.getAxis(); ++ ++ switch (enumdirection_enumaxis) { + case X: + d4 = 1.0; + break; +@@ -119,6 +135,7 @@ + this.setBoundingBox(new AABB(d1 - d4, d2 - d5, d3 - d6, d1 + d4, d2 + d5, d3 + d6)); + } + } ++ // CraftBukkit end + + @Override + public boolean survives() { +@@ -161,6 +180,11 @@ + return false; + } else if (!source.is(DamageTypeTags.IS_EXPLOSION) && !this.getItem().isEmpty()) { + if (!this.level().isClientSide) { ++ // CraftBukkit start - fire EntityDamageEvent ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, false) || this.isRemoved()) { ++ return true; ++ } ++ // CraftBukkit end + this.dropItem(source.getEntity(), false); + this.gameEvent(GameEvent.BLOCK_CHANGE, source.getEntity()); + this.playSound(this.getRemoveItemSound(), 1.0F, 1.0F); +@@ -278,13 +314,19 @@ + } + + public void setItem(ItemStack stack, boolean updateNeighbours) { +- if (!stack.isEmpty()) { +- stack = stack.copyWithCount(1); ++ // CraftBukkit start ++ this.setItem(stack, updateNeighbours, true); ++ } ++ ++ public void setItem(ItemStack itemstack, boolean flag, boolean playSound) { ++ // CraftBukkit end ++ if (!itemstack.isEmpty()) { ++ itemstack = itemstack.copyWithCount(1); + } + +- this.onItemChanged(stack); +- this.getEntityData().set(DATA_ITEM, stack); +- if (!stack.isEmpty()) { ++ this.onItemChanged(itemstack); ++ this.getEntityData().set(ItemFrame.DATA_ITEM, itemstack); ++ if (!itemstack.isEmpty() && playSound) { // CraftBukkit + this.playSound(this.getAddItemSound(), 1.0F, 1.0F); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java.patch new file mode 100644 index 0000000000..144137fc8b --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java.patch @@ -0,0 +1,69 @@ +--- a/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java ++++ b/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java +@@ -24,6 +27,8 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class LeashFenceKnotEntity extends HangingEntity { + public static final double OFFSET_Y = 0.375; +@@ -94,23 +96,49 @@ + Mob.class, new AABB(this.getX() - 7.0, this.getY() - 7.0, this.getZ() - 7.0, this.getX() + 7.0, this.getY() + 7.0, this.getZ() + 7.0) + ); + +- for (Mob mob : entitiesOfClass) { +- if (mob.getLeashHolder() == player) { +- mob.setLeashedTo(this, true); ++ while (iterator.hasNext()) { ++ Mob entityinsentient = (Mob) iterator.next(); ++ ++ if (entityinsentient.getLeashHolder() == player) { ++ // CraftBukkit start ++ if (CraftEventFactory.callPlayerLeashEntityEvent(entityinsentient, this, player, hand).isCancelled()) { ++ ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(entityinsentient, entityinsentient.getLeashHolder())); ++ continue; ++ } ++ // CraftBukkit end ++ entityinsentient.setLeashedTo(this, true); + flag = true; + } + } + + boolean flag1 = false; + if (!flag) { +- this.discard(); +- if (player.getAbilities().instabuild) { +- for (Mob mob1 : entitiesOfClass) { +- if (mob1.isLeashed() && mob1.getLeashHolder() == this) { +- mob1.dropLeash(true, false); ++ // CraftBukkit start - Move below ++ // this.discard(); ++ boolean die = true; ++ // CraftBukkit end ++ if (true || player.getAbilities().instabuild) { // CraftBukkit - Process for non-creative as well ++ Iterator iterator1 = list.iterator(); ++ ++ while (iterator1.hasNext()) { ++ Mob entityinsentient1 = (Mob) iterator1.next(); ++ ++ if (entityinsentient1.isLeashed() && entityinsentient1.getLeashHolder() == this) { ++ // CraftBukkit start ++ if (CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient1, player, hand).isCancelled()) { ++ die = false; ++ continue; ++ } ++ entityinsentient1.dropLeash(true, !player.getAbilities().instabuild); // false -> survival mode boolean ++ // CraftBukkit end + flag1 = true; + } + } ++ // CraftBukkit start ++ if (die) { ++ this.discard(); ++ } ++ // CraftBukkit end + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/item/FallingBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/item/FallingBlockEntity.java.patch new file mode 100644 index 0000000000..f6e260e8ea --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/item/FallingBlockEntity.java.patch @@ -0,0 +1,109 @@ +--- a/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -46,6 +49,10 @@ + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class FallingBlockEntity extends Entity { + private static final Logger LOGGER = LogUtils.getLogger(); + private BlockState blockState = Blocks.SAND.defaultBlockState(); +@@ -75,21 +86,21 @@ + this.setStartPos(this.blockPosition()); + } + +- public static FallingBlockEntity fall(Level level, BlockPos pos, BlockState blockState) { +- FallingBlockEntity fallingBlockEntity = new FallingBlockEntity( +- level, +- (double)pos.getX() + 0.5, +- (double)pos.getY(), +- (double)pos.getZ() + 0.5, +- blockState.hasProperty(BlockStateProperties.WATERLOGGED) +- ? blockState.setValue(BlockStateProperties.WATERLOGGED, Boolean.valueOf(false)) +- : blockState +- ); +- level.setBlock(pos, blockState.getFluidState().createLegacyBlock(), 3); +- level.addFreshEntity(fallingBlockEntity); +- return fallingBlockEntity; ++ public static FallingBlockEntity fall(Level level, BlockPos pos, IBlockData blockState) { ++ // CraftBukkit start ++ return fall(level, pos, blockState, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); + } + ++ public static FallingBlockEntity fall(Level world, BlockPos blockposition, IBlockData iblockdata, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end ++ FallingBlockEntity entityfallingblock = new FallingBlockEntity(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, iblockdata.hasProperty(BlockStateProperties.WATERLOGGED) ? (IBlockData) iblockdata.setValue(BlockStateProperties.WATERLOGGED, false) : iblockdata); ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entityfallingblock, blockposition, iblockdata.getFluidState().createLegacyBlock())) return entityfallingblock; // CraftBukkit ++ ++ world.setBlock(blockposition, iblockdata.getFluidState().createLegacyBlock(), 3); ++ world.addFreshEntity(entityfallingblock, spawnReason); // CraftBukkit ++ return entityfallingblock; ++ } ++ + @Override + public boolean isAttackable() { + return false; +@@ -164,11 +180,14 @@ + this.blockState = this.blockState.setValue(BlockStateProperties.WATERLOGGED, Boolean.valueOf(true)); + } + +- if (this.level().setBlock(blockPos, this.blockState, 3)) { +- ((ServerLevel)this.level()) +- .getChunkSource() +- .chunkMap +- .broadcast(this, new ClientboundBlockUpdatePacket(blockPos, this.level().getBlockState(blockPos))); ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, this.blockState)) { ++ this.discard(); // SPIGOT-6586 called before the event in previous versions ++ return; ++ } ++ // CraftBukkit end ++ if (this.level().setBlock(blockposition, this.blockState, 3)) { ++ ((ServerLevel) this.level()).getChunkSource().chunkMap.broadcast(this, new ClientboundBlockUpdatePacket(blockposition, this.level().getBlockState(blockposition))); + this.discard(); + if (block instanceof Fallable) { + ((Fallable)block).onLand(this.level(), blockPos, this.blockState, blockState, this); +@@ -242,15 +257,31 @@ + return false; + } else { + Predicate predicate = EntitySelector.NO_CREATIVE_OR_SPECTATOR.and(EntitySelector.LIVING_ENTITY_STILL_ALIVE); +- DamageSource damageSource = this.blockState.getBlock() instanceof Fallable fallable +- ? fallable.getFallDamageSource(this) +- : this.damageSources().fallingBlock(this); +- float f = (float)Math.min(Mth.floor((float)ceil * this.fallDamagePerDistance), this.fallDamageMax); +- this.level().getEntities(this, this.getBoundingBox(), predicate).forEach(entity -> entity.hurt(damageSource, f)); +- boolean isAnvil = this.blockState.is(BlockTags.ANVIL); +- if (isAnvil && f > 0.0F && this.random.nextFloat() < 0.05F + (float)ceil * 0.05F) { +- BlockState blockState = AnvilBlock.damage(this.blockState); +- if (blockState == null) { ++ Block block = this.blockState.getBlock(); ++ DamageSource damagesource1; ++ ++ if (block instanceof Fallable) { ++ Fallable fallable = (Fallable) block; ++ ++ damagesource1 = fallable.getFallDamageSource(this); ++ } else { ++ damagesource1 = this.damageSources().fallingBlock(this); ++ } ++ ++ DamageSource damagesource2 = damagesource1; ++ float f2 = (float) Math.min(Mth.floor((float) i * this.fallDamagePerDistance), this.fallDamageMax); ++ ++ this.level().getEntities((Entity) this, this.getBoundingBox(), predicate).forEach((entity) -> { ++ CraftEventFactory.entityDamage = this; // CraftBukkit ++ entity.hurt(damagesource2, f2); ++ CraftEventFactory.entityDamage = null; // CraftBukkit ++ }); ++ boolean flag = this.blockState.is(BlockTags.ANVIL); ++ ++ if (flag && f2 > 0.0F && this.random.nextFloat() < 0.05F + (float) i * 0.05F) { ++ IBlockData iblockdata = AnvilBlock.damage(this.blockState); ++ ++ if (iblockdata == null) { + this.cancelDrop = true; + } else { + this.blockState = blockState; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/item/ItemEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/item/ItemEntity.java.patch new file mode 100644 index 0000000000..fd93ebc427 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/item/ItemEntity.java.patch @@ -0,0 +1,158 @@ +--- a/net/minecraft/world/entity/item/ItemEntity.java ++++ b/net/minecraft/world/entity/item/ItemEntity.java +@@ -28,6 +20,22 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3; ++import net.minecraft.core.BlockPos; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.network.chat.Component; ++import net.minecraft.network.syncher.EntityDataAccessor; ++import net.minecraft.network.syncher.EntityDataSerializers; ++import net.minecraft.network.syncher.SynchedEntityData; ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.sounds.SoundSource; ++import net.minecraft.stats.Stats; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.entity.Player; ++import org.bukkit.event.entity.EntityPickupItemEvent; ++import org.bukkit.event.player.PlayerPickupItemEvent; ++// CraftBukkit end + + public class ItemEntity extends Entity implements TraceableEntity { + private static final EntityDataAccessor DATA_ITEM = SynchedEntityData.defineId(ItemEntity.class, EntityDataSerializers.ITEM_STACK); +@@ -44,6 +53,7 @@ + @Nullable + private UUID target; + public final float bobOffs; ++ private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit + + public ItemEntity(EntityType entityType, Level level) { + super(entityType, level); +@@ -112,9 +135,12 @@ + this.discard(); + } else { + super.tick(); +- if (this.pickupDelay > 0 && this.pickupDelay != 32767) { +- this.pickupDelay--; +- } ++ // CraftBukkit start - Use wall time for pickup and despawn timers ++ int elapsedTicks = MinecraftServer.currentTick - this.lastTick; ++ if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; ++ if (this.age != -32768) this.age += elapsedTicks; ++ this.lastTick = MinecraftServer.currentTick; ++ // CraftBukkit end + + this.xo = this.getX(); + this.yo = this.getY(); +@@ -162,9 +190,11 @@ + this.mergeWithNeighbours(); + } + ++ /* CraftBukkit start - moved up + if (this.age != -32768) { + this.age++; + } ++ // CraftBukkit end */ + + this.hasImpulse = this.hasImpulse | this.updateInWaterStateAndDoFluidPushing(); + if (!this.level().isClientSide) { +@@ -175,6 +206,12 @@ + } + + if (!this.level().isClientSide && this.age >= 6000) { ++ // CraftBukkit start - fire ItemDespawnEvent ++ if (CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { ++ this.age = 0; ++ return; ++ } ++ // CraftBukkit end + this.discard(); + } + } +@@ -246,6 +295,11 @@ + } + + private static void merge(ItemEntity destinationEntity, ItemStack destinationStack, ItemEntity originEntity, ItemStack originStack) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callItemMergeEvent(originEntity, destinationEntity)) { ++ return; ++ } ++ // CraftBukkit end + merge(destinationEntity, destinationStack, originStack); + destinationEntity.pickupDelay = Math.max(destinationEntity.pickupDelay, originEntity.pickupDelay); + destinationEntity.age = Math.min(destinationEntity.age, originEntity.age); +@@ -270,6 +325,11 @@ + } else if (this.level().isClientSide) { + return true; + } else { ++ // CraftBukkit start ++ if (CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount)) { ++ return false; ++ } ++ // CraftBukkit end + this.markHurt(); + this.health = (int)((float)this.health - amount); + this.gameEvent(GameEvent.ENTITY_DAMAGE, source.getEntity()); +@@ -327,12 +390,53 @@ + @Override + public void playerTouch(Player entity) { + if (!this.level().isClientSide) { +- ItemStack item = this.getItem(); +- Item item1 = item.getItem(); +- int count = item.getCount(); +- if (this.pickupDelay == 0 && (this.target == null || this.target.equals(entity.getUUID())) && entity.getInventory().add(item)) { +- entity.take(this, count); +- if (item.isEmpty()) { ++ ItemStack itemstack = this.getItem(); ++ Item item = itemstack.getItem(); ++ int i = itemstack.getCount(); ++ ++ // CraftBukkit start - fire PlayerPickupItemEvent ++ int canHold = entity.getInventory().canHold(itemstack); ++ int remaining = i - canHold; ++ ++ if (this.pickupDelay <= 0 && canHold > 0) { ++ itemstack.setCount(canHold); ++ // Call legacy event ++ PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent((Player) entity.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); ++ playerEvent.setCancelled(!playerEvent.getPlayer().getCanPickupItems()); ++ this.level().getCraftServer().getPluginManager().callEvent(playerEvent); ++ if (playerEvent.isCancelled()) { ++ itemstack.setCount(i); // SPIGOT-5294 - restore count ++ return; ++ } ++ ++ // Call newer event afterwards ++ EntityPickupItemEvent entityEvent = new EntityPickupItemEvent((Player) entity.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); ++ entityEvent.setCancelled(!entityEvent.getEntity().getCanPickupItems()); ++ this.level().getCraftServer().getPluginManager().callEvent(entityEvent); ++ if (entityEvent.isCancelled()) { ++ itemstack.setCount(i); // SPIGOT-5294 - restore count ++ return; ++ } ++ ++ // Update the ItemStack if it was changed in the event ++ ItemStack current = this.getItem(); ++ if (!itemstack.equals(current)) { ++ itemstack = current; ++ } else { ++ itemstack.setCount(canHold + remaining); // = i ++ } ++ ++ // Possibly < 0; fix here so we do not have to modify code below ++ this.pickupDelay = 0; ++ } else if (this.pickupDelay == 0) { ++ // ensure that the code below isn't triggered if canHold says we can't pick the items up ++ this.pickupDelay = -1; ++ } ++ // CraftBukkit end ++ ++ if (this.pickupDelay == 0 && (this.target == null || this.target.equals(entity.getUUID())) && entity.getInventory().add(itemstack)) { ++ entity.take(this, i); ++ if (itemstack.isEmpty()) { + this.discard(); + item.setCount(count); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/item/PrimedTnt.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/item/PrimedTnt.java.patch new file mode 100644 index 0000000000..d4574d5308 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/item/PrimedTnt.java.patch @@ -0,0 +1,57 @@ +--- a/net/minecraft/world/entity/item/PrimedTnt.java ++++ b/net/minecraft/world/entity/item/PrimedTnt.java +@@ -19,6 +19,11 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end ++ + public class PrimedTnt extends Entity implements TraceableEntity { + private static final EntityDataAccessor DATA_FUSE_ID = SynchedEntityData.defineId(PrimedTnt.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_BLOCK_STATE_ID = SynchedEntityData.defineId(PrimedTnt.class, EntityDataSerializers.BLOCK_STATE); +@@ -26,7 +32,9 @@ + private static final String TAG_BLOCK_STATE = "block_state"; + public static final String TAG_FUSE = "fuse"; + @Nullable +- private LivingEntity owner; ++ public LivingEntity owner; ++ public float yield = 4; // CraftBukkit - add field ++ public boolean isIncendiary = false; // CraftBukkit - add field + + public PrimedTnt(EntityType entityType, Level level) { + super(entityType, level); +@@ -76,10 +86,13 @@ + int i = this.getFuse() - 1; + this.setFuse(i); + if (i <= 0) { +- this.discard(); ++ // CraftBukkit start - Need to reverse the order of the explosion and the entity death so we have a location for the event ++ // this.discard(); + if (!this.level().isClientSide) { + this.explode(); + } ++ this.discard(); ++ // CraftBukkit end + } else { + this.updateInWaterStateAndDoFluidPushing(); + if (this.level().isClientSide) { +@@ -89,8 +103,14 @@ + } + + private void explode() { +- float f = 4.0F; +- this.level().explode(this, this.getX(), this.getY(0.0625), this.getZ(), 4.0F, Level.ExplosionInteraction.TNT); ++ // CraftBukkit start ++ // float f = 4.0F; ++ ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent((org.bukkit.entity.Explosive)this.getBukkitEntity()); ++ ++ if (!event.isCancelled()) { ++ this.level().explode(this, this.getX(), this.getY(0.0625D), this.getZ(), event.getRadius(), event.getFire(), Level.a.TNT); ++ } ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/AbstractSkeleton.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/AbstractSkeleton.java.patch new file mode 100644 index 0000000000..cd9b888c27 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/AbstractSkeleton.java.patch @@ -0,0 +1,28 @@ +--- a/net/minecraft/world/entity/monster/AbstractSkeleton.java ++++ b/net/minecraft/world/entity/monster/AbstractSkeleton.java +@@ -186,10 +197,22 @@ + double d = target.getX() - this.getX(); + double d1 = target.getY(0.3333333333333333) - arrow.getY(); + double d2 = target.getZ() - this.getZ(); +- double squareRoot = Math.sqrt(d * d + d2 * d2); +- arrow.shoot(d, d1 + squareRoot * 0.2F, d2, 1.6F, (float)(14 - this.level().getDifficulty().getId() * 4)); ++ double d3 = Math.sqrt(d0 * d0 + d2 * d2); ++ ++ entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level().getDifficulty().getId() * 4)); ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), null, entityarrow, net.minecraft.world.EnumHand.MAIN_HAND, 0.8F, true); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ ++ if (event.getProjectile() == entityarrow.getBukkitEntity()) { ++ this.level().addFreshEntity(entityarrow); ++ } ++ // CraftBukkit end + this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); +- this.level().addFreshEntity(arrow); ++ // this.level().addFreshEntity(entityarrow); // CraftBukkit - moved up + } + + protected AbstractArrow getArrow(ItemStack arrowStack, float velocity) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/CaveSpider.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/CaveSpider.java.patch new file mode 100644 index 0000000000..92ed453b51 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/CaveSpider.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/entity/monster/CaveSpider.java ++++ b/net/minecraft/world/entity/monster/CaveSpider.java +@@ -39,8 +41,8 @@ + i = 15; + } + +- if (i > 0) { +- ((LivingEntity)entity).addEffect(new MobEffectInstance(MobEffects.POISON, i * 20, 0), this); ++ if (b0 > 0) { ++ ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.POISON, b0 * 20, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Creeper.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Creeper.java.patch new file mode 100644 index 0000000000..6a51fae160 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Creeper.java.patch @@ -0,0 +1,98 @@ +--- a/net/minecraft/world/entity/monster/Creeper.java ++++ b/net/minecraft/world/entity/monster/Creeper.java +@@ -41,6 +43,12 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end ++ + public class Creeper extends Monster implements PowerableMob { + private static final EntityDataAccessor DATA_SWELL_DIR = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_IS_POWERED = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.BOOLEAN); +@@ -206,9 +224,20 @@ + @Override + public void thunderHit(ServerLevel level, LightningBolt lightning) { + super.thunderHit(level, lightning); +- this.entityData.set(DATA_IS_POWERED, true); ++ // CraftBukkit start ++ if (CraftEventFactory.callCreeperPowerEvent(this, lightning, org.bukkit.event.entity.CreeperPowerEvent.PowerCause.LIGHTNING).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ this.entityData.set(Creeper.DATA_IS_POWERED, true); + } + ++ // CraftBukkit start ++ public void setPowered(boolean powered) { ++ this.entityData.set(Creeper.DATA_IS_POWERED, powered); ++ } ++ // CraftBukkit end ++ + @Override + protected InteractionResult mobInteract(Player player, InteractionHand hand) { + ItemStack itemInHand = player.getItemInHand(hand); +@@ -218,8 +248,8 @@ + .playSound(player, this.getX(), this.getY(), this.getZ(), soundEvent, this.getSoundSource(), 1.0F, this.random.nextFloat() * 0.4F + 0.8F); + if (!this.level().isClientSide) { + this.ignite(); +- if (!itemInHand.isDamageableItem()) { +- itemInHand.shrink(1); ++ if (itemstack.getItem().getMaxDamage() == 0) { // CraftBukkit - fix MC-264285: unbreakable flint and steels are completely consumed when igniting a creeper ++ itemstack.shrink(1); + } else { + itemInHand.hurtAndBreak(1, player, entity -> entity.broadcastBreakEvent(hand)); + } +@@ -234,10 +266,20 @@ + private void explodeCreeper() { + if (!this.level().isClientSide) { + float f = this.isPowered() ? 2.0F : 1.0F; ++ ++ // CraftBukkit start ++ ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent(this, this.explosionRadius * f, false); ++ if (!event.isCancelled()) { ++ // CraftBukkit end + this.dead = true; +- this.level().explode(this, this.getX(), this.getY(), this.getZ(), (float)this.explosionRadius * f, Level.ExplosionInteraction.MOB); ++ this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.MOB); // CraftBukkit + this.discard(); + this.spawnLingeringCloud(); ++ // CraftBukkit start ++ } else { ++ swell = 0; ++ } ++ // CraftBukkit end + } + } + +@@ -251,11 +287,24 @@ + areaEffectCloud.setDuration(areaEffectCloud.getDuration() / 2); + areaEffectCloud.setRadiusPerTick(-areaEffectCloud.getRadius() / (float)areaEffectCloud.getDuration()); + +- for (MobEffectInstance mobEffectInstance : activeEffects) { +- areaEffectCloud.addEffect(new MobEffectInstance(mobEffectInstance)); ++ if (!collection.isEmpty()) { ++ AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); ++ ++ entityareaeffectcloud.setOwner(this); // CraftBukkit ++ entityareaeffectcloud.setRadius(2.5F); ++ entityareaeffectcloud.setRadiusOnUse(-0.5F); ++ entityareaeffectcloud.setWaitTime(10); ++ entityareaeffectcloud.setDuration(entityareaeffectcloud.getDuration() / 2); ++ entityareaeffectcloud.setRadiusPerTick(-entityareaeffectcloud.getRadius() / (float) entityareaeffectcloud.getDuration()); ++ Iterator iterator = collection.iterator(); ++ ++ while (iterator.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); ++ ++ entityareaeffectcloud.addEffect(new MobEffectInstance(mobeffect)); + } + +- this.level().addFreshEntity(areaEffectCloud); ++ this.level().addFreshEntity(entityareaeffectcloud, CreatureSpawnEvent.SpawnReason.EXPLOSION); // CraftBukkit + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Drowned.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Drowned.java.patch new file mode 100644 index 0000000000..41a99efcc4 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Drowned.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/entity/monster/Drowned.java ++++ b/net/minecraft/world/entity/monster/Drowned.java +@@ -252,9 +244,9 @@ + + @Override + public void performRangedAttack(LivingEntity target, float distanceFactor) { +- ThrownTrident thrownTrident = new ThrownTrident(this.level(), this, new ItemStack(Items.TRIDENT)); +- double d = target.getX() - this.getX(); +- double d1 = target.getY(0.3333333333333333) - thrownTrident.getY(); ++ ThrownTrident entitythrowntrident = new ThrownTrident(this.level(), this, this.getItemInHand(net.minecraft.world.entity.projectile.ProjectileUtil.getWeaponHoldingHand(this, Items.TRIDENT))); // CraftBukkit - Use Trident in hand like skeletons (SPIGOT-7025) ++ double d0 = target.getX() - this.getX(); ++ double d1 = target.getY(0.3333333333333333D) - entitythrowntrident.getY(); + double d2 = target.getZ() - this.getZ(); + double squareRoot = Math.sqrt(d * d + d2 * d2); + thrownTrident.shoot(d, d1 + squareRoot * 0.2F, d2, 1.6F, (float)(14 - this.level().getDifficulty().getId() * 4)); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/ElderGuardian.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/ElderGuardian.java.patch new file mode 100644 index 0000000000..7c4840c414 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/ElderGuardian.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/entity/monster/ElderGuardian.java ++++ b/net/minecraft/world/entity/monster/ElderGuardian.java +@@ -67,12 +69,12 @@ + protected void customServerAiStep() { + super.customServerAiStep(); + if ((this.tickCount + this.getId()) % 1200 == 0) { +- MobEffectInstance mobEffectInstance = new MobEffectInstance(MobEffects.DIG_SLOWDOWN, 6000, 2); +- List list = MobEffectUtil.addEffectToPlayersAround((ServerLevel)this.level(), this, this.position(), 50.0, mobEffectInstance, 1200); +- list.forEach( +- serverPlayer -> serverPlayer.connection +- .send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, this.isSilent() ? 0.0F : 1.0F)) +- ); ++ MobEffectInstance mobeffect = new MobEffectInstance(MobEffects.DIG_SLOWDOWN, 6000, 2); ++ List list = MobEffectUtil.addEffectToPlayersAround((ServerLevel) this.level(), this, this.position(), 50.0D, mobeffect, 1200, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit ++ ++ list.forEach((entityplayer) -> { ++ entityplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, this.isSilent() ? 0.0F : 1.0F)); ++ }); + } + + if (!this.hasRestriction()) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/EnderMan.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/EnderMan.java.patch new file mode 100644 index 0000000000..9507bf06a9 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/EnderMan.java.patch @@ -0,0 +1,125 @@ +--- a/net/minecraft/world/entity/monster/EnderMan.java ++++ b/net/minecraft/world/entity/monster/EnderMan.java +@@ -70,6 +71,11 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end ++ + public class EnderMan extends Monster implements NeutralMob { + private static final UUID SPEED_MODIFIER_ATTACKING_UUID = UUID.fromString("020E0DFB-87AE-4653-9556-831010E291A0"); + private static final AttributeModifier SPEED_MODIFIER_ATTACKING = new AttributeModifier( +@@ -121,9 +120,20 @@ + + @Override + public void setTarget(@Nullable LivingEntity livingEntity) { +- super.setTarget(livingEntity); +- AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED); +- if (livingEntity == null) { ++ // CraftBukkit start - fire event ++ setTarget(livingEntity, EntityTargetEvent.TargetReason.UNKNOWN, true); ++ } ++ ++ @Override ++ public boolean setTarget(LivingEntity entityliving, EntityTargetEvent.TargetReason reason, boolean fireEvent) { ++ if (!super.setTarget(entityliving, reason, fireEvent)) { ++ return false; ++ } ++ entityliving = getTarget(); ++ // CraftBukkit end ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ ++ if (entityliving == null) { + this.targetChangeTime = 0; + this.entityData.set(DATA_CREEPY, false); + this.entityData.set(DATA_STARED_AT, false); +@@ -474,22 +495,25 @@ + + @Override + public void tick() { +- RandomSource random = this.enderman.getRandom(); +- Level level = this.enderman.level(); +- int floor = Mth.floor(this.enderman.getX() - 1.0 + random.nextDouble() * 2.0); +- int floor1 = Mth.floor(this.enderman.getY() + random.nextDouble() * 2.0); +- int floor2 = Mth.floor(this.enderman.getZ() - 1.0 + random.nextDouble() * 2.0); +- BlockPos blockPos = new BlockPos(floor, floor1, floor2); +- BlockState blockState = level.getBlockState(blockPos); +- BlockPos blockPos1 = blockPos.below(); +- BlockState blockState1 = level.getBlockState(blockPos1); +- BlockState carriedBlock = this.enderman.getCarriedBlock(); +- if (carriedBlock != null) { +- BlockState var11 = Block.updateFromNeighbourShapes(carriedBlock, this.enderman.level(), blockPos); +- if (this.canPlaceBlock(level, blockPos, var11, blockState, blockState1, blockPos1)) { +- level.setBlock(blockPos, var11, 3); +- level.gameEvent(GameEvent.BLOCK_PLACE, blockPos, GameEvent.Context.of(this.enderman, var11)); +- this.enderman.setCarriedBlock(null); ++ RandomSource randomsource = this.enderman.getRandom(); ++ Level world = this.enderman.level(); ++ int i = Mth.floor(this.enderman.getX() - 1.0D + randomsource.nextDouble() * 2.0D); ++ int j = Mth.floor(this.enderman.getY() + randomsource.nextDouble() * 2.0D); ++ int k = Mth.floor(this.enderman.getZ() - 1.0D + randomsource.nextDouble() * 2.0D); ++ BlockPos blockposition = new BlockPos(i, j, k); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ BlockPos blockposition1 = blockposition.below(); ++ IBlockData iblockdata1 = world.getBlockState(blockposition1); ++ IBlockData iblockdata2 = this.enderman.getCarriedBlock(); ++ ++ if (iblockdata2 != null) { ++ iblockdata2 = Block.updateFromNeighbourShapes(iblockdata2, this.enderman.level(), blockposition); ++ if (this.canPlaceBlock(world, blockposition, iblockdata2, iblockdata, iblockdata1, blockposition1)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockposition, iblockdata2)) { // CraftBukkit - Place event ++ world.setBlock(blockposition, iblockdata2, 3); ++ world.gameEvent(GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(this.enderman, iblockdata2)); ++ this.enderman.setCarriedBlock((IBlockData) null); ++ } // CraftBukkit + } + } + } +@@ -513,6 +527,44 @@ + + static class EndermanLookForPlayerGoal extends NearestAttackableTargetGoal { + private final EnderMan enderman; ++ ++ public EndermanTakeBlockGoal(EnderMan enderman) { ++ this.enderman = enderman; ++ } ++ ++ @Override ++ public boolean canUse() { ++ return this.enderman.getCarriedBlock() != null ? false : (!this.enderman.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? false : this.enderman.getRandom().nextInt(reducedTickDelay(20)) == 0); ++ } ++ ++ @Override ++ public void tick() { ++ RandomSource randomsource = this.enderman.getRandom(); ++ Level world = this.enderman.level(); ++ int i = Mth.floor(this.enderman.getX() - 2.0D + randomsource.nextDouble() * 4.0D); ++ int j = Mth.floor(this.enderman.getY() + randomsource.nextDouble() * 3.0D); ++ int k = Mth.floor(this.enderman.getZ() - 2.0D + randomsource.nextDouble() * 4.0D); ++ BlockPos blockposition = new BlockPos(i, j, k); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ Vec3 vec3d = new Vec3((double) this.enderman.getBlockX() + 0.5D, (double) j + 0.5D, (double) this.enderman.getBlockZ() + 0.5D); ++ Vec3 vec3d1 = new Vec3((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D); ++ BlockHitResult movingobjectpositionblock = world.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.enderman)); ++ boolean flag = movingobjectpositionblock.getBlockPos().equals(blockposition); ++ ++ if (iblockdata.is(BlockTags.ENDERMAN_HOLDABLE) && flag) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockposition, Blocks.AIR.defaultBlockState())) { // CraftBukkit - Place event ++ world.removeBlock(blockposition, false); ++ world.gameEvent(GameEvent.BLOCK_DESTROY, blockposition, GameEvent.Context.of(this.enderman, iblockdata)); ++ this.enderman.setCarriedBlock(iblockdata.getBlock().defaultBlockState()); ++ } // CraftBukkit ++ } ++ ++ } ++ } ++ ++ private static class EndermanLookForPlayerGoal extends NearestAttackableTargetGoal { ++ ++ private final EnderMan enderman; + @Nullable + private Player pendingTarget; + private int aggroTime; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Evoker.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Evoker.java.patch new file mode 100644 index 0000000000..51d989fab0 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Evoker.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/entity/monster/Evoker.java ++++ b/net/minecraft/world/entity/monster/Evoker.java +@@ -200,8 +200,8 @@ + } + } + +- flag = true; +- break; ++ worldserver.addFreshEntityWithPassengers(entityvex, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPELL); // CraftBukkit - Add SpawnReason ++ worldserver.gameEvent(GameEvent.ENTITY_PLACE, blockposition, GameEvent.Context.of((Entity) Evoker.this)); + } + + blockPos = blockPos.below(); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Ghast.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Ghast.java.patch new file mode 100644 index 0000000000..894e9c848c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Ghast.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/entity/monster/Ghast.java ++++ b/net/minecraft/world/entity/monster/Ghast.java +@@ -291,9 +346,12 @@ + level.levelEvent(null, 1016, this.ghast.blockPosition(), 0); + } + +- LargeFireball largeFireball = new LargeFireball(level, this.ghast, d2, d3, d4, this.ghast.getExplosionPower()); +- largeFireball.setPos(this.ghast.getX() + viewVector.x * 4.0, this.ghast.getY(0.5) + 0.5, largeFireball.getZ() + viewVector.z * 4.0); +- level.addFreshEntity(largeFireball); ++ LargeFireball entitylargefireball = new LargeFireball(world, this.ghast, d2, d3, d4, this.ghast.getExplosionPower()); ++ ++ // CraftBukkit - set bukkitYield when setting explosionpower ++ entitylargefireball.bukkitYield = entitylargefireball.explosionPower = this.ghast.getExplosionPower(); ++ entitylargefireball.setPos(this.ghast.getX() + vec3d.x * 4.0D, this.ghast.getY(0.5D) + 0.5D, entitylargefireball.getZ() + vec3d.z * 4.0D); ++ world.addFreshEntity(entitylargefireball); + this.chargeTime = -40; + } + } else if (this.chargeTime > 0) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Guardian.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Guardian.java.patch new file mode 100644 index 0000000000..49115ccb40 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Guardian.java.patch @@ -0,0 +1,28 @@ +--- a/net/minecraft/world/entity/monster/Guardian.java ++++ b/net/minecraft/world/entity/monster/Guardian.java +@@ -61,7 +62,8 @@ + private int clientSideAttackTime; + private boolean clientSideTouchedGround; + @Nullable +- protected RandomStrollGoal randomStrollGoal; ++ public RandomStrollGoal randomStrollGoal; ++ public Guardian.GuardianAttackGoal guardianAttackGoal; // CraftBukkit - add field + + public Guardian(EntityType entityType, Level level) { + super(entityType, level); +@@ -74,10 +76,11 @@ + + @Override + protected void registerGoals() { +- MoveTowardsRestrictionGoal moveTowardsRestrictionGoal = new MoveTowardsRestrictionGoal(this, 1.0); +- this.randomStrollGoal = new RandomStrollGoal(this, 1.0, 80); +- this.goalSelector.addGoal(4, new Guardian.GuardianAttackGoal(this)); +- this.goalSelector.addGoal(5, moveTowardsRestrictionGoal); ++ MoveTowardsRestrictionGoal pathfindergoalmovetowardsrestriction = new MoveTowardsRestrictionGoal(this, 1.0D); ++ ++ this.randomStrollGoal = new RandomStrollGoal(this, 1.0D, 80); ++ this.goalSelector.addGoal(4, guardianAttackGoal = new Guardian.GuardianAttackGoal(this)); // CraftBukkit - assign field ++ this.goalSelector.addGoal(5, pathfindergoalmovetowardsrestriction); + this.goalSelector.addGoal(7, this.randomStrollGoal); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Guardian.class, 12.0F, 0.01F)); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Husk.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Husk.java.patch new file mode 100644 index 0000000000..5909521e20 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Husk.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/entity/monster/Husk.java ++++ b/net/minecraft/world/entity/monster/Husk.java +@@ -55,8 +58,9 @@ + public boolean doHurtTarget(Entity entity) { + boolean flag = super.doHurtTarget(entity); + if (flag && this.getMainHandItem().isEmpty() && entity instanceof LivingEntity) { +- float effectiveDifficulty = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty(); +- ((LivingEntity)entity).addEffect(new MobEffectInstance(MobEffects.HUNGER, 140 * (int)effectiveDifficulty), this); ++ float f = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty(); ++ ++ ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.HUNGER, 140 * (int) f), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + + return flag; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Illusioner.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Illusioner.java.patch new file mode 100644 index 0000000000..22e9fe5629 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Illusioner.java.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/entity/monster/Illusioner.java ++++ b/net/minecraft/world/entity/monster/Illusioner.java +@@ -241,7 +228,7 @@ + + @Override + protected void performSpellCasting() { +- Illusioner.this.getTarget().addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 400), Illusioner.this); ++ Illusioner.this.addEffect(new MobEffectInstance(MobEffects.INVISIBILITY, 1200), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ILLUSION); // CraftBukkit + } + + @Override +@@ -273,7 +279,7 @@ + + @Override + protected void performSpellCasting() { +- Illusioner.this.addEffect(new MobEffectInstance(MobEffects.INVISIBILITY, 1200)); ++ Illusioner.this.getTarget().addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 400), Illusioner.this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + + @Nullable diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Phantom.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Phantom.java.patch new file mode 100644 index 0000000000..85732351ac --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Phantom.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/entity/monster/Phantom.java ++++ b/net/minecraft/world/entity/monster/Phantom.java +@@ -508,7 +549,10 @@ + cat.hiss(); + } + +- this.isScaredOfCat = !entitiesOfClass.isEmpty(); ++ if (Phantom.this.canAttack(entityhuman, TargetingConditions.DEFAULT)) { ++ Phantom.this.setTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit - reason ++ return true; ++ } + } + + return !this.isScaredOfCat; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Ravager.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Ravager.java.patch new file mode 100644 index 0000000000..052e734c64 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Ravager.java.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/world/entity/monster/Ravager.java ++++ b/net/minecraft/world/entity/monster/Ravager.java +@@ -41,6 +43,10 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class Ravager extends Raider { + private static final Predicate NO_RAVAGER_AND_ALIVE = entity -> entity.isAlive() && !(entity instanceof Ravager); + private static final double BASE_MOVEMENT_SPEED = 0.3; +@@ -149,7 +157,12 @@ + BlockState blockState = this.level().getBlockState(blockPos); + Block block = blockState.getBlock(); + if (block instanceof LeavesBlock) { +- flag = this.level().destroyBlock(blockPos, true, this) || flag; ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState())) { ++ continue; ++ } ++ // CraftBukkit end ++ flag = this.level().destroyBlock(blockposition, true, this) || flag; + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Shulker.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Shulker.java.patch new file mode 100644 index 0000000000..fa79916f85 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Shulker.java.patch @@ -0,0 +1,77 @@ +--- a/net/minecraft/world/entity/monster/Shulker.java ++++ b/net/minecraft/world/entity/monster/Shulker.java +@@ -56,7 +59,14 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Shulker extends AbstractGolem implements VariantHolder>, Enemy { ++// CraftBukkit start ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.entity.EntityTeleportEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ ++public class Shulker extends AbstractGolem implements VariantHolder>, IMonster { ++ + private static final UUID COVERED_ARMOR_MODIFIER_UUID = UUID.fromString("7E0292F2-9434-48D5-A29F-9583AF7DF27F"); + private static final AttributeModifier COVERED_ARMOR_MODIFIER = new AttributeModifier( + COVERED_ARMOR_MODIFIER_UUID, "Covered armor bonus", 20.0, AttributeModifier.Operation.ADDITION +@@ -373,18 +399,21 @@ + if (!this.isNoAi() && this.isAlive()) { + BlockPos blockPos = this.blockPosition(); + +- for (int i = 0; i < 5; i++) { +- BlockPos blockPos1 = blockPos.offset( +- Mth.randomBetweenInclusive(this.random, -8, 8), +- Mth.randomBetweenInclusive(this.random, -8, 8), +- Mth.randomBetweenInclusive(this.random, -8, 8) +- ); +- if (blockPos1.getY() > this.level().getMinBuildHeight() +- && this.level().isEmptyBlock(blockPos1) +- && this.level().getWorldBorder().isWithinBounds(blockPos1) +- && this.level().noCollision(this, new AABB(blockPos1).deflate(1.0E-6))) { +- Direction direction = this.findAttachableSurface(blockPos1); +- if (direction != null) { ++ for (int i = 0; i < 5; ++i) { ++ BlockPos blockposition1 = blockposition.offset(Mth.randomBetweenInclusive(this.random, -8, 8), Mth.randomBetweenInclusive(this.random, -8, 8), Mth.randomBetweenInclusive(this.random, -8, 8)); ++ ++ if (blockposition1.getY() > this.level().getMinBuildHeight() && this.level().isEmptyBlock(blockposition1) && this.level().getWorldBorder().isWithinBounds(blockposition1) && this.level().noCollision(this, (new AABB(blockposition1)).deflate(1.0E-6D))) { ++ Direction enumdirection = this.findAttachableSurface(blockposition1); ++ ++ if (enumdirection != null) { ++ // CraftBukkit start ++ EntityTeleportEvent teleportEvent = CraftEventFactory.callEntityTeleportEvent(this, blockposition1.getX(), blockposition1.getY(), blockposition1.getZ()); ++ if (teleportEvent.isCancelled()) { ++ return false; ++ } else { ++ blockposition1 = CraftLocation.toBlockPosition(teleportEvent.getTo()); ++ } ++ // CraftBukkit end + this.unRide(); + this.setAttachFace(direction); + this.playSound(SoundEvents.SHULKER_TELEPORT, 1.0F, 1.0F); +@@ -443,14 +475,16 @@ + Vec3 vec3 = this.position(); + AABB boundingBox = this.getBoundingBox(); + if (!this.isClosed() && this.teleportSomewhere()) { +- int size = this.level().getEntities(EntityType.SHULKER, boundingBox.inflate(8.0), Entity::isAlive).size(); +- float f = (float)(size - 1) / 5.0F; +- if (!(this.level().random.nextFloat() < f)) { +- Shulker shulker = EntityType.SHULKER.create(this.level()); +- if (shulker != null) { +- shulker.setVariant(this.getVariant()); +- shulker.moveTo(vec3); +- this.level().addFreshEntity(shulker); ++ int i = this.level().getEntities((EntityTypeTest) EntityType.SHULKER, axisalignedbb.inflate(8.0D), Entity::isAlive).size(); ++ float f = (float) (i - 1) / 5.0F; ++ ++ if (this.level().random.nextFloat() >= f) { ++ Shulker entityshulker = (Shulker) EntityType.SHULKER.create(this.level()); ++ ++ if (entityshulker != null) { ++ entityshulker.setVariant(this.getVariant()); ++ entityshulker.moveTo(vec3d); ++ this.level().addFreshEntity(entityshulker, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - the mysteries of life + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Silverfish.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Silverfish.java.patch new file mode 100644 index 0000000000..bde77f90a3 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Silverfish.java.patch @@ -0,0 +1,106 @@ +--- a/net/minecraft/world/entity/monster/Silverfish.java ++++ b/net/minecraft/world/entity/monster/Silverfish.java +@@ -34,6 +34,10 @@ + import net.minecraft.world.level.block.state.BlockState; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class Silverfish extends Monster { + @Nullable + private Silverfish.SilverfishWakeUpFriendsGoal friendsGoal; +@@ -139,7 +143,68 @@ + return new Vector3f(0.0F, entityDimensions.height - 0.0625F * f, 0.0F); + } + +- static class SilverfishMergeWithStoneGoal extends RandomStrollGoal { ++ private static class SilverfishWakeUpFriendsGoal extends Goal { ++ ++ private final Silverfish silverfish; ++ private int lookForFriends; ++ ++ public SilverfishWakeUpFriendsGoal(Silverfish silverfish) { ++ this.silverfish = silverfish; ++ } ++ ++ public void notifyHurt() { ++ if (this.lookForFriends == 0) { ++ this.lookForFriends = this.adjustedTickDelay(20); ++ } ++ ++ } ++ ++ @Override ++ public boolean canUse() { ++ return this.lookForFriends > 0; ++ } ++ ++ @Override ++ public void tick() { ++ --this.lookForFriends; ++ if (this.lookForFriends <= 0) { ++ Level world = this.silverfish.level(); ++ RandomSource randomsource = this.silverfish.getRandom(); ++ BlockPos blockposition = this.silverfish.blockPosition(); ++ ++ for (int i = 0; i <= 5 && i >= -5; i = (i <= 0 ? 1 : 0) - i) { ++ for (int j = 0; j <= 10 && j >= -10; j = (j <= 0 ? 1 : 0) - j) { ++ for (int k = 0; k <= 10 && k >= -10; k = (k <= 0 ? 1 : 0) - k) { ++ BlockPos blockposition1 = blockposition.offset(j, i, k); ++ IBlockData iblockdata = world.getBlockState(blockposition1); ++ Block block = iblockdata.getBlock(); ++ ++ if (block instanceof InfestedBlock) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.silverfish, blockposition1, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState())) { ++ continue; ++ } ++ // CraftBukkit end ++ if (world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ world.destroyBlock(blockposition1, true, this.silverfish); ++ } else { ++ world.setBlock(blockposition1, ((InfestedBlock) block).hostStateByInfested(world.getBlockState(blockposition1)), 3); ++ } ++ ++ if (randomsource.nextBoolean()) { ++ return; ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ } ++ } ++ ++ private static class SilverfishMergeWithStoneGoal extends RandomStrollGoal { ++ + @Nullable + private Direction selectedDirection; + private boolean doMerge; +@@ -182,11 +249,17 @@ + if (!this.doMerge) { + super.start(); + } else { +- LevelAccessor levelAccessor = this.mob.level(); +- BlockPos blockPos = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5, this.mob.getZ()).relative(this.selectedDirection); +- BlockState blockState = levelAccessor.getBlockState(blockPos); +- if (InfestedBlock.isCompatibleHostBlock(blockState)) { +- levelAccessor.setBlock(blockPos, InfestedBlock.infestedStateByHost(blockState), 3); ++ Level world = this.mob.level(); ++ BlockPos blockposition = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5D, this.mob.getZ()).relative(this.selectedDirection); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ ++ if (InfestedBlock.isCompatibleHostBlock(iblockdata)) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition, InfestedBlock.infestedStateByHost(iblockdata))) { ++ return; ++ } ++ // CraftBukkit end ++ world.setBlock(blockposition, InfestedBlock.infestedStateByHost(iblockdata), 3); + this.mob.spawnAnim(); + this.mob.discard(); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Skeleton.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Skeleton.java.patch new file mode 100644 index 0000000000..a4bf214045 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Skeleton.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/monster/Skeleton.java ++++ b/net/minecraft/world/entity/monster/Skeleton.java +@@ -85,7 +90,7 @@ + } + + protected void doFreezeConversion() { +- this.convertTo(EntityType.STRAY, true); ++ this.convertTo(EntityType.STRAY, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.FROZEN, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.FROZEN); // CraftBukkit - add spawn and transform reasons + if (!this.isSilent()) { + this.level().levelEvent(null, 1048, this.blockPosition(), 0); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Slime.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Slime.java.patch new file mode 100644 index 0000000000..e937d8eaea --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Slime.java.patch @@ -0,0 +1,85 @@ +--- a/net/minecraft/world/entity/monster/Slime.java ++++ b/net/minecraft/world/entity/monster/Slime.java +@@ -44,7 +44,16 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Slime extends Mob implements Enemy { ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTransformEvent; ++import org.bukkit.event.entity.SlimeSplitEvent; ++// CraftBukkit end ++ ++public class Slime extends Mob implements IMonster { ++ + private static final EntityDataAccessor ID_SIZE = SynchedEntityData.defineId(Slime.class, EntityDataSerializers.INT); + public static final int MIN_SIZE = 1; + public static final int MAX_SIZE = 127; +@@ -202,23 +207,53 @@ + int i = size / 2; + int i1 = 2 + this.random.nextInt(3); + +- for (int i2 = 0; i2 < i1; i2++) { +- float f1 = ((float)(i2 % 2) - 0.5F) * f; +- float f2 = ((float)(i2 / 2) - 0.5F) * f; +- Slime slime = this.getType().create(this.level()); +- if (slime != null) { ++ if (!this.level().isClientSide && i > 1 && this.isDeadOrDying()) { ++ Component ichatbasecomponent = this.getCustomName(); ++ boolean flag = this.isNoAi(); ++ float f = (float) i / 4.0F; ++ int j = i / 2; ++ int k = 2 + this.random.nextInt(3); ++ ++ // CraftBukkit start ++ SlimeSplitEvent event = new SlimeSplitEvent((org.bukkit.entity.Slime) this.getBukkitEntity(), k); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled() && event.getCount() > 0) { ++ k = event.getCount(); ++ } else { ++ super.remove(reason); ++ return; ++ } ++ List slimes = new ArrayList<>(j); ++ // CraftBukkit end ++ ++ for (int l = 0; l < k; ++l) { ++ float f1 = ((float) (l % 2) - 0.5F) * f; ++ float f2 = ((float) (l / 2) - 0.5F) * f; ++ Slime entityslime = (Slime) this.getType().create(this.level()); ++ ++ if (entityslime != null) { + if (this.isPersistenceRequired()) { + slime.setPersistenceRequired(); + } + +- slime.setCustomName(customName); +- slime.setNoAi(isNoAi); +- slime.setInvulnerable(this.isInvulnerable()); +- slime.setSize(i, true); +- slime.moveTo(this.getX() + (double)f1, this.getY() + 0.5, this.getZ() + (double)f2, this.random.nextFloat() * 360.0F, 0.0F); +- this.level().addFreshEntity(slime); ++ entityslime.setCustomName(ichatbasecomponent); ++ entityslime.setNoAi(flag); ++ entityslime.setInvulnerable(this.isInvulnerable()); ++ entityslime.setSize(j, true); ++ entityslime.moveTo(this.getX() + (double) f1, this.getY() + 0.5D, this.getZ() + (double) f2, this.random.nextFloat() * 360.0F, 0.0F); ++ slimes.add(entityslime); // CraftBukkit + } + } ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, slimes, EntityTransformEvent.TransformReason.SPLIT).isCancelled()) { ++ super.remove(reason); ++ return; ++ } ++ for (LivingEntity living : slimes) { ++ this.level().addFreshEntity(living, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SLIME_SPLIT); // CraftBukkit - SpawnReason ++ } ++ // CraftBukkit end + } + + super.remove(reason); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/SpellcasterIllager.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/SpellcasterIllager.java.patch new file mode 100644 index 0000000000..a456cdba28 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/SpellcasterIllager.java.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/world/entity/monster/SpellcasterIllager.java ++++ b/net/minecraft/world/entity/monster/SpellcasterIllager.java +@@ -15,6 +15,9 @@ + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.ai.goal.Goal; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public abstract class SpellcasterIllager extends AbstractIllager { + private static final EntityDataAccessor DATA_SPELL_CASTING_ID = SynchedEntityData.defineId(SpellcasterIllager.class, EntityDataSerializers.BYTE); +@@ -190,6 +158,11 @@ + public void tick() { + this.attackWarmupDelay--; + if (this.attackWarmupDelay == 0) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handleEntitySpellCastEvent(SpellcasterIllager.this, this.getSpell())) { ++ return; ++ } ++ // CraftBukkit end + this.performSpellCasting(); + SpellcasterIllager.this.playSound(SpellcasterIllager.this.getCastingSoundEvent(), 1.0F, 1.0F); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Spider.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Spider.java.patch new file mode 100644 index 0000000000..036f0e8e36 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Spider.java.patch @@ -0,0 +1,19 @@ +--- a/net/minecraft/world/entity/monster/Spider.java ++++ b/net/minecraft/world/entity/monster/Spider.java +@@ -173,10 +177,12 @@ + } + } + +- if (var9 instanceof Spider.SpiderEffectsGroupData spiderEffectsGroupData) { +- MobEffect mobEffect = spiderEffectsGroupData.effect; +- if (mobEffect != null) { +- this.addEffect(new MobEffectInstance(mobEffect, -1)); ++ if (object instanceof Spider.SpiderEffectsGroupData) { ++ Spider.SpiderEffectsGroupData entityspider_groupdataspider = (Spider.SpiderEffectsGroupData) object; ++ MobEffect mobeffectlist = entityspider_groupdataspider.effect; ++ ++ if (mobeffectlist != null) { ++ this.addEffect(new MobEffectInstance(mobeffectlist, -1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.SPIDER_SPAWN); // CraftBukkit + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Strider.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Strider.java.patch new file mode 100644 index 0000000000..7db33003e2 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Strider.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/entity/monster/Strider.java ++++ b/net/minecraft/world/entity/monster/Strider.java +@@ -320,8 +349,16 @@ + var10000 = false; + } + +- boolean flag1 = var10000; +- this.setSuffocating(!flag || flag1); ++ boolean flag2 = flag1; ++ ++ // CraftBukkit start ++ boolean suffocating = !flag || flag2; ++ if (suffocating ^ this.isSuffocating()) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callStriderTemperatureChangeEvent(this, suffocating)) { ++ this.setSuffocating(suffocating); ++ } ++ } ++ // CraftBukkit end + } + + super.tick(); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Vex.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Vex.java.patch new file mode 100644 index 0000000000..a7c7978c7a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Vex.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/entity/monster/Vex.java ++++ b/net/minecraft/world/entity/monster/Vex.java +@@ -362,8 +403,9 @@ + } + + @Override +- public boolean canContinueToUse() { +- return false; ++ public void start() { ++ Vex.this.setTarget(Vex.this.owner.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.OWNER_ATTACKED_TARGET, true); // CraftBukkit ++ super.start(); + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Witch.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Witch.java.patch new file mode 100644 index 0000000000..e518e8dd84 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Witch.java.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/world/entity/monster/Witch.java ++++ b/net/minecraft/world/entity/monster/Witch.java +@@ -123,11 +125,16 @@ + this.setUsingItem(false); + ItemStack mainHandItem = this.getMainHandItem(); + this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); +- if (mainHandItem.is(Items.POTION)) { +- List mobEffects = PotionUtils.getMobEffects(mainHandItem); +- if (mobEffects != null) { +- for (MobEffectInstance mobEffectInstance : mobEffects) { +- this.addEffect(new MobEffectInstance(mobEffectInstance)); ++ if (itemstack.is(Items.POTION)) { ++ List list = PotionUtils.getMobEffects(itemstack); ++ ++ if (list != null) { ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); ++ ++ this.addEffect(new MobEffectInstance(mobeffect), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/WitherSkeleton.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/WitherSkeleton.java.patch new file mode 100644 index 0000000000..af3413f316 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/WitherSkeleton.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/monster/WitherSkeleton.java ++++ b/net/minecraft/world/entity/monster/WitherSkeleton.java +@@ -104,7 +111,7 @@ + return false; + } else { + if (entity instanceof LivingEntity) { +- ((LivingEntity)entity).addEffect(new MobEffectInstance(MobEffects.WITHER, 200), this); ++ ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.WITHER, 200), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + + return true; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Zombie.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Zombie.java.patch new file mode 100644 index 0000000000..385c5f7f80 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/Zombie.java.patch @@ -0,0 +1,228 @@ +--- a/net/minecraft/world/entity/monster/Zombie.java ++++ b/net/minecraft/world/entity/monster/Zombie.java +@@ -65,6 +54,25 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; + import org.joml.Vector3f; ++import net.minecraft.core.BlockPos; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.Tag; ++import net.minecraft.network.syncher.EntityDataAccessor; ++import net.minecraft.network.syncher.EntityDataSerializers; ++import net.minecraft.network.syncher.SynchedEntityData; ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundEvents; ++import net.minecraft.sounds.SoundSource; ++import net.minecraft.tags.FluidTags; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++// CraftBukkit end + + public class Zombie extends Monster { + private static final UUID SPEED_MODIFIER_BABY_UUID = UUID.fromString("B9766B59-9566-4402-BC1F-2EE2A276D836"); +@@ -84,7 +93,8 @@ + private final BreakDoorGoal breakDoorGoal = new BreakDoorGoal(this, DOOR_BREAKING_PREDICATE); + private boolean canBreakDoors; + private int inWaterTime; +- private int conversionTime; ++ public int conversionTime; ++ private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field + + public Zombie(EntityType entityType, Level level) { + super(entityType, level); +@@ -202,7 +211,10 @@ + public void tick() { + if (!this.level().isClientSide && this.isAlive() && !this.isNoAi()) { + if (this.isUnderWaterConverting()) { +- this.conversionTime--; ++ // CraftBukkit start - Use wall time instead of ticks for conversion ++ int elapsedTicks = MinecraftServer.currentTick - this.lastTick; ++ this.conversionTime -= elapsedTicks; ++ // CraftBukkit end + if (this.conversionTime < 0) { + this.doUnderWaterConversion(); + } +@@ -219,6 +231,7 @@ + } + + super.tick(); ++ this.lastTick = MinecraftServer.currentTick; // CraftBukkit + } + + @Override +@@ -248,7 +263,8 @@ + super.aiStep(); + } + +- private void startUnderWaterConversion(int conversionTime) { ++ public void startUnderWaterConversion(int conversionTime) { ++ this.lastTick = MinecraftServer.currentTick; // CraftBukkit + this.conversionTime = conversionTime; + this.getEntityData().set(DATA_DROWNED_CONVERSION_ID, true); + } +@@ -261,10 +278,15 @@ + } + + protected void convertToZombieType(EntityType entityType) { +- Zombie zombie = this.convertTo(entityType, true); +- if (zombie != null) { +- zombie.handleAttributes(zombie.level().getCurrentDifficultyAt(zombie.blockPosition()).getSpecialMultiplier()); +- zombie.setCanBreakDoors(zombie.supportsBreakDoorGoal() && this.canBreakDoors()); ++ Zombie entityzombie = (Zombie) this.convertTo(entityType, true, EntityTransformEvent.TransformReason.DROWNED, CreatureSpawnEvent.SpawnReason.DROWNED); ++ ++ if (entityzombie != null) { ++ entityzombie.handleAttributes(entityzombie.level().getCurrentDifficultyAt(entityzombie.blockPosition()).getSpecialMultiplier()); ++ entityzombie.setCanBreakDoors(entityzombie.supportsBreakDoorGoal() && this.canBreakDoors()); ++ // CraftBukkit start - SPIGOT-5208: End conversion to stop event spam ++ } else { ++ ((org.bukkit.entity.Zombie) getBukkitEntity()).setConversionTime(-1); ++ // CraftBukkit end + } + } + +@@ -294,29 +315,22 @@ + int floor2 = Mth.floor(this.getZ()); + Zombie zombie = new Zombie(this.level()); + +- for (int i = 0; i < 50; i++) { +- int i1 = floor + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); +- int i2 = floor1 + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); +- int i3 = floor2 + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); +- BlockPos blockPos = new BlockPos(i1, i2, i3); +- EntityType type = zombie.getType(); +- SpawnPlacements.Type placementType = SpawnPlacements.getPlacementType(type); +- if (NaturalSpawner.isSpawnPositionOk(placementType, this.level(), blockPos, type) +- && SpawnPlacements.checkSpawnRules(type, serverLevel, MobSpawnType.REINFORCEMENT, blockPos, this.level().random)) { +- zombie.setPos((double)i1, (double)i2, (double)i3); +- if (!this.level().hasNearbyAlivePlayer((double)i1, (double)i2, (double)i3, 7.0) +- && this.level().isUnobstructed(zombie) +- && this.level().noCollision(zombie) +- && !this.level().containsAnyLiquid(zombie.getBoundingBox())) { +- zombie.setTarget(target); +- zombie.finalizeSpawn( +- serverLevel, this.level().getCurrentDifficultyAt(zombie.blockPosition()), MobSpawnType.REINFORCEMENT, null, null +- ); +- serverLevel.addFreshEntityWithPassengers(zombie); +- this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE) +- .addPermanentModifier(new AttributeModifier("Zombie reinforcement caller charge", -0.05F, AttributeModifier.Operation.ADDITION)); +- zombie.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE) +- .addPermanentModifier(new AttributeModifier("Zombie reinforcement callee charge", -0.05F, AttributeModifier.Operation.ADDITION)); ++ for (int l = 0; l < 50; ++l) { ++ int i1 = i + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); ++ int j1 = j + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); ++ int k1 = k + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); ++ BlockPos blockposition = new BlockPos(i1, j1, k1); ++ EntityType entitytypes = entityzombie.getType(); ++ SpawnPlacements.Surface entitypositiontypes_surface = SpawnPlacements.getPlacementType(entitytypes); ++ ++ if (NaturalSpawner.isSpawnPositionOk(entitypositiontypes_surface, this.level(), blockposition, entitytypes) && SpawnPlacements.checkSpawnRules(entitytypes, worldserver, EnumMobSpawn.REINFORCEMENT, blockposition, this.level().random)) { ++ entityzombie.setPos((double) i1, (double) j1, (double) k1); ++ if (!this.level().hasNearbyAlivePlayer((double) i1, (double) j1, (double) k1, 7.0D) && this.level().isUnobstructed(entityzombie) && this.level().noCollision((Entity) entityzombie) && !this.level().containsAnyLiquid(entityzombie.getBoundingBox())) { ++ entityzombie.setTarget(entityliving, EntityTargetEvent.TargetReason.REINFORCEMENT_TARGET, true); // CraftBukkit ++ entityzombie.finalizeSpawn(worldserver, this.level().getCurrentDifficultyAt(entityzombie.blockPosition()), EnumMobSpawn.REINFORCEMENT, (GroupDataEntity) null, (CompoundTag) null); ++ worldserver.addFreshEntityWithPassengers(entityzombie, CreatureSpawnEvent.SpawnReason.REINFORCEMENTS); // CraftBukkit ++ this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).addPermanentModifier(new AttributeModifier("Zombie reinforcement caller charge", -0.05000000074505806D, AttributeModifier.Operation.ADDITION)); ++ entityzombie.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).addPermanentModifier(new AttributeModifier("Zombie reinforcement callee charge", -0.05000000074505806D, AttributeModifier.Operation.ADDITION)); + break; + } + } +@@ -331,9 +346,17 @@ + public boolean doHurtTarget(Entity entity) { + boolean flag = super.doHurtTarget(entity); + if (flag) { +- float effectiveDifficulty = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty(); +- if (this.getMainHandItem().isEmpty() && this.isOnFire() && this.random.nextFloat() < effectiveDifficulty * 0.3F) { +- entity.setSecondsOnFire(2 * (int)effectiveDifficulty); ++ float f = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty(); ++ ++ if (this.getMainHandItem().isEmpty() && this.isOnFire() && this.random.nextFloat() < f * 0.3F) { ++ // CraftBukkit start ++ EntityCombustByEntityEvent event = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), 2 * (int) f); // PAIL: fixme ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ entity.setSecondsOnFire(event.getDuration(), false); ++ } ++ // CraftBukkit end + } + } + +@@ -409,25 +438,36 @@ + if (level.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { + return flag; + } ++ // CraftBukkit start ++ flag = zombifyVillager(level, entityvillager, this.blockPosition(), this.isSilent(), CreatureSpawnEvent.SpawnReason.INFECTION) == null; ++ } + +- ZombieVillager zombieVillager = villager.convertTo(EntityType.ZOMBIE_VILLAGER, false); +- if (zombieVillager != null) { +- zombieVillager.finalizeSpawn( +- level, level.getCurrentDifficultyAt(zombieVillager.blockPosition()), MobSpawnType.CONVERSION, new Zombie.ZombieGroupData(false, true), null +- ); +- zombieVillager.setVillagerData(villager.getVillagerData()); +- zombieVillager.setGossips(villager.getGossips().store(NbtOps.INSTANCE)); +- zombieVillager.setTradeOffers(villager.getOffers().createTag()); +- zombieVillager.setVillagerXp(villager.getVillagerXp()); +- if (!this.isSilent()) { +- level.levelEvent(null, 1026, this.blockPosition(), 0); ++ return flag; ++ } ++ ++ public static ZombieVillager zombifyVillager(ServerLevel worldserver, Villager entityvillager, net.minecraft.core.BlockPos blockPosition, boolean silent, CreatureSpawnEvent.SpawnReason spawnReason) { ++ { ++ ZombieVillager entityzombievillager = (ZombieVillager) entityvillager.convertTo(EntityType.ZOMBIE_VILLAGER, false, EntityTransformEvent.TransformReason.INFECTION, spawnReason); ++ // CraftBukkit end ++ ++ if (entityzombievillager != null) { ++ entityzombievillager.finalizeSpawn(worldserver, worldserver.getCurrentDifficultyAt(entityzombievillager.blockPosition()), EnumMobSpawn.CONVERSION, new Zombie.ZombieGroupData(false, true), (CompoundTag) null); ++ entityzombievillager.setVillagerData(entityvillager.getVillagerData()); ++ entityzombievillager.setGossips((Tag) entityvillager.getGossips().store(NbtOps.INSTANCE)); ++ entityzombievillager.setTradeOffers(entityvillager.getOffers().createTag()); ++ entityzombievillager.setVillagerXp(entityvillager.getVillagerXp()); ++ // CraftBukkit start ++ if (!silent) { ++ worldserver.levelEvent((Player) null, 1026, blockPosition, 0); + } + + flag = false; + } + } + +- return flag; ++ return entityzombievillager; ++ } ++ // CraftBukkit end + } + + @Override +@@ -471,14 +511,15 @@ + chicken.setChickenJockey(true); + this.startRiding(chicken); + } +- } else if ((double)random.nextFloat() < 0.05) { +- Chicken chicken1 = EntityType.CHICKEN.create(this.level()); +- if (chicken1 != null) { +- chicken1.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); +- chicken1.finalizeSpawn(level, difficulty, MobSpawnType.JOCKEY, null, null); +- chicken1.setChickenJockey(true); +- this.startRiding(chicken1); +- level.addFreshEntity(chicken1); ++ } else if ((double) randomsource.nextFloat() < 0.05D) { ++ Chicken entitychicken1 = (Chicken) EntityType.CHICKEN.create(this.level()); ++ ++ if (entitychicken1 != null) { ++ entitychicken1.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); ++ entitychicken1.finalizeSpawn(level, difficulty, EnumMobSpawn.JOCKEY, (GroupDataEntity) null, (CompoundTag) null); ++ entitychicken1.setChickenJockey(true); ++ this.startRiding(entitychicken1); ++ level.addFreshEntity(entitychicken1, CreatureSpawnEvent.SpawnReason.MOUNT); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/ZombieVillager.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/ZombieVillager.java.patch new file mode 100644 index 0000000000..f18b0413fb --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/ZombieVillager.java.patch @@ -0,0 +1,109 @@ +--- a/net/minecraft/world/entity/monster/ZombieVillager.java ++++ b/net/minecraft/world/entity/monster/ZombieVillager.java +@@ -50,6 +46,16 @@ + import org.joml.Vector3f; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundEvents; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++// CraftBukkit end ++ + public class ZombieVillager extends Zombie implements VillagerDataHolder { + private static final Logger LOGGER = LogUtils.getLogger(); + private static final EntityDataAccessor DATA_CONVERTING_ID = SynchedEntityData.defineId(ZombieVillager.class, EntityDataSerializers.BOOLEAN); +@@ -68,6 +73,7 @@ + @Nullable + private CompoundTag tradeOffers; + private int villagerXp; ++ private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field + + public ZombieVillager(EntityType entityType, Level level) { + super(entityType, level); +@@ -134,14 +147,20 @@ + @Override + public void tick() { + if (!this.level().isClientSide && this.isAlive() && this.isConverting()) { +- int conversionProgress = this.getConversionProgress(); +- this.villagerConversionTime -= conversionProgress; ++ int i = this.getConversionProgress(); ++ // CraftBukkit start - Use wall time instead of ticks for villager conversion ++ int elapsedTicks = MinecraftServer.currentTick - this.lastTick; ++ i *= elapsedTicks; ++ // CraftBukkit end ++ ++ this.villagerConversionTime -= i; + if (this.villagerConversionTime <= 0) { + this.finishConversion((ServerLevel)this.level()); + } + } + + super.tick(); ++ this.lastTick = MinecraftServer.currentTick; // CraftBukkit + } + + @Override +@@ -183,10 +203,12 @@ + private void startConverting(@Nullable UUID conversionStarter, int villagerConversionTime) { + this.conversionStarter = conversionStarter; + this.villagerConversionTime = villagerConversionTime; +- this.getEntityData().set(DATA_CONVERTING_ID, true); +- this.removeEffect(MobEffects.WEAKNESS); +- this.addEffect(new MobEffectInstance(MobEffects.DAMAGE_BOOST, villagerConversionTime, Math.min(this.level().getDifficulty().getId() - 1, 0))); +- this.level().broadcastEntityEvent(this, (byte)16); ++ this.getEntityData().set(ZombieVillager.DATA_CONVERTING_ID, true); ++ // CraftBukkit start ++ this.removeEffect(MobEffects.WEAKNESS, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); ++ this.addEffect(new MobEffectInstance(MobEffects.DAMAGE_BOOST, villagerConversionTime, Math.min(this.level().getDifficulty().getId() - 1, 0)), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); ++ // CraftBukkit end ++ this.level().broadcastEntityEvent(this, (byte) 16); + } + + @Override +@@ -211,7 +224,15 @@ + } + + private void finishConversion(ServerLevel serverLevel) { +- Villager villager = this.convertTo(EntityType.VILLAGER, false); ++ // CraftBukkit start ++ Villager entityvillager = (Villager) this.convertTo(EntityType.VILLAGER, false, EntityTransformEvent.TransformReason.CURED, CreatureSpawnEvent.SpawnReason.CURED); ++ if (entityvillager == null) { ++ ((org.bukkit.entity.ZombieVillager) getBukkitEntity()).setConversionTime(-1); // SPIGOT-5208: End conversion to stop event spam ++ return; ++ } ++ // CraftBukkit end ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ int i = aenumitemslot.length; + + for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) { + ItemStack itemBySlot = this.getItemBySlot(equipmentSlot); +@@ -219,9 +242,12 @@ + if (EnchantmentHelper.hasBindingCurse(itemBySlot)) { + villager.getSlot(equipmentSlot.getIndex() + 300).set(itemBySlot); + } else { +- double d = (double)this.getEquipmentDropChance(equipmentSlot); +- if (d > 1.0) { +- this.spawnAtLocation(itemBySlot); ++ double d0 = (double) this.getEquipmentDropChance(enumitemslot); ++ ++ if (d0 > 1.0D) { ++ this.forceDrops = true; // CraftBukkit ++ this.spawnAtLocation(itemstack); ++ this.forceDrops = false; // CraftBukkit + } + } + } +@@ -247,7 +274,7 @@ + } + } + +- villager.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0)); ++ entityvillager.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); // CraftBukkit + if (!this.isSilent()) { + serverLevel.levelEvent(null, 1027, this.blockPosition(), 0); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/ZombifiedPiglin.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/ZombifiedPiglin.java.patch new file mode 100644 index 0000000000..ca4080c2ed --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/ZombifiedPiglin.java.patch @@ -0,0 +1,68 @@ +--- a/net/minecraft/world/entity/monster/ZombifiedPiglin.java ++++ b/net/minecraft/world/entity/monster/ZombifiedPiglin.java +@@ -142,15 +140,18 @@ + } + + private void alertOthers() { +- double attributeValue = this.getAttributeValue(Attributes.FOLLOW_RANGE); +- AABB aABB = AABB.unitCubeFromLowerCorner(this.position()).inflate(attributeValue, 10.0, attributeValue); +- this.level() +- .getEntitiesOfClass(ZombifiedPiglin.class, aABB, EntitySelector.NO_SPECTATORS) +- .stream() +- .filter(zombifiedPiglin -> zombifiedPiglin != this) +- .filter(zombifiedPiglin -> zombifiedPiglin.getTarget() == null) +- .filter(zombifiedPiglin -> !zombifiedPiglin.isAlliedTo(this.getTarget())) +- .forEach(zombifiedPiglin -> zombifiedPiglin.setTarget(this.getTarget())); ++ double d0 = this.getAttributeValue(Attributes.FOLLOW_RANGE); ++ AABB axisalignedbb = AABB.unitCubeFromLowerCorner(this.position()).inflate(d0, 10.0D, d0); ++ ++ this.level().getEntitiesOfClass(ZombifiedPiglin.class, axisalignedbb, EntitySelector.NO_SPECTATORS).stream().filter((entitypigzombie) -> { ++ return entitypigzombie != this; ++ }).filter((entitypigzombie) -> { ++ return entitypigzombie.getTarget() == null; ++ }).filter((entitypigzombie) -> { ++ return !entitypigzombie.isAlliedTo((Entity) this.getTarget()); ++ }).forEach((entitypigzombie) -> { ++ entitypigzombie.setTarget(this.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_NEARBY_ENTITY, true); // CraftBukkit ++ }); + } + + private void playAngerSound() { +@@ -158,22 +159,31 @@ + } + + @Override +- public void setTarget(@Nullable LivingEntity livingEntity) { +- if (this.getTarget() == null && livingEntity != null) { +- this.playFirstAngerSoundIn = FIRST_ANGER_SOUND_DELAY.sample(this.random); +- this.ticksUntilNextAlert = ALERT_INTERVAL.sample(this.random); ++ public boolean setTarget(@Nullable LivingEntity entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) { // CraftBukkit - signature ++ if (this.getTarget() == null && entityliving != null) { ++ this.playFirstAngerSoundIn = ZombifiedPiglin.FIRST_ANGER_SOUND_DELAY.sample(this.random); ++ this.ticksUntilNextAlert = ZombifiedPiglin.ALERT_INTERVAL.sample(this.random); + } + + if (livingEntity instanceof Player) { + this.setLastHurtByPlayer((Player)livingEntity); + } + +- super.setTarget(livingEntity); ++ return super.setTarget(entityliving, reason, fireEvent); // CraftBukkit + } + + @Override + public void startPersistentAngerTimer() { +- this.setRemainingPersistentAngerTime(PERSISTENT_ANGER_TIME.sample(this.random)); ++ // CraftBukkit start ++ Entity entity = ((ServerLevel) this.level()).getEntity(getPersistentAngerTarget()); ++ org.bukkit.event.entity.PigZombieAngerEvent event = new org.bukkit.event.entity.PigZombieAngerEvent((org.bukkit.entity.PigZombie) this.getBukkitEntity(), (entity == null) ? null : entity.getBukkitEntity(), ZombifiedPiglin.PERSISTENT_ANGER_TIME.sample(this.random)); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ this.setPersistentAngerTarget(null); ++ return; ++ } ++ this.setRemainingPersistentAngerTime(event.getNewAnger()); ++ // CraftBukkit end + } + + public static boolean checkZombifiedPiglinSpawnRules( diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java.patch new file mode 100644 index 0000000000..589d7f3bb9 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java ++++ b/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java +@@ -114,9 +115,10 @@ + } + + protected void finishConversion(ServerLevel serverLevel) { +- ZombifiedPiglin zombifiedPiglin = this.convertTo(EntityType.ZOMBIFIED_PIGLIN, true); +- if (zombifiedPiglin != null) { +- zombifiedPiglin.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0)); ++ ZombifiedPiglin entitypigzombie = (ZombifiedPiglin) this.convertTo(EntityType.ZOMBIFIED_PIGLIN, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.PIGLIN_ZOMBIFIED, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.PIGLIN_ZOMBIFIED); // CraftBukkit - add spawn and transform reasons ++ ++ if (entitypigzombie != null) { ++ entitypigzombie.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0)); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/piglin/Piglin.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/piglin/Piglin.java.patch new file mode 100644 index 0000000000..d34be168ba --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/piglin/Piglin.java.patch @@ -0,0 +1,162 @@ +--- a/net/minecraft/world/entity/monster/piglin/Piglin.java ++++ b/net/minecraft/world/entity/monster/piglin/Piglin.java +@@ -55,6 +47,26 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; + ++// CraftBukkit start ++import java.util.stream.Collectors; ++import java.util.HashSet; ++import java.util.Set; ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.registries.BuiltInRegistries; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; ++import net.minecraft.nbt.StringTag; ++import net.minecraft.nbt.Tag; ++import net.minecraft.network.syncher.EntityDataAccessor; ++import net.minecraft.network.syncher.EntityDataSerializers; ++import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundEvents; ++import net.minecraft.world.item.Item; ++// CraftBukkit end ++ + public class Piglin extends AbstractPiglin implements CrossbowAttackMob, InventoryCarrier { + private static final EntityDataAccessor DATA_BABY_ID = SynchedEntityData.defineId(Piglin.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_IS_CHARGING_CROSSBOW = SynchedEntityData.defineId(Piglin.class, EntityDataSerializers.BOOLEAN); +@@ -71,53 +82,15 @@ + private static final int MAX_PASSENGERS_ON_ONE_HOGLIN = 3; + private static final float PROBABILITY_OF_SPAWNING_AS_BABY = 0.2F; + private static final float BABY_EYE_HEIGHT_ADJUSTMENT = 0.82F; +- private static final double PROBABILITY_OF_SPAWNING_WITH_CROSSBOW_INSTEAD_OF_SWORD = 0.5; +- private final SimpleContainer inventory = new SimpleContainer(8); +- private boolean cannotHunt; +- protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of( +- SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.NEAREST_ITEMS, SensorType.HURT_BY, SensorType.PIGLIN_SPECIFIC_SENSOR +- ); +- protected static final ImmutableList> MEMORY_TYPES = ImmutableList.of( +- MemoryModuleType.LOOK_TARGET, +- MemoryModuleType.DOORS_TO_CLOSE, +- MemoryModuleType.NEAREST_LIVING_ENTITIES, +- MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, +- MemoryModuleType.NEAREST_VISIBLE_PLAYER, +- MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, +- MemoryModuleType.NEAREST_VISIBLE_ADULT_PIGLINS, +- MemoryModuleType.NEARBY_ADULT_PIGLINS, +- MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, +- MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS, +- MemoryModuleType.HURT_BY, +- MemoryModuleType.HURT_BY_ENTITY, +- MemoryModuleType.WALK_TARGET, +- MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, +- MemoryModuleType.ATTACK_TARGET, +- MemoryModuleType.ATTACK_COOLING_DOWN, +- MemoryModuleType.INTERACTION_TARGET, +- MemoryModuleType.PATH, +- MemoryModuleType.ANGRY_AT, +- MemoryModuleType.UNIVERSAL_ANGER, +- MemoryModuleType.AVOID_TARGET, +- MemoryModuleType.ADMIRING_ITEM, +- MemoryModuleType.TIME_TRYING_TO_REACH_ADMIRE_ITEM, +- MemoryModuleType.ADMIRING_DISABLED, +- MemoryModuleType.DISABLE_WALK_TO_ADMIRE_ITEM, +- MemoryModuleType.CELEBRATE_LOCATION, +- MemoryModuleType.DANCING, +- MemoryModuleType.HUNTED_RECENTLY, +- MemoryModuleType.NEAREST_VISIBLE_BABY_HOGLIN, +- MemoryModuleType.NEAREST_VISIBLE_NEMESIS, +- MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED, +- MemoryModuleType.RIDE_TARGET, +- MemoryModuleType.VISIBLE_ADULT_PIGLIN_COUNT, +- MemoryModuleType.VISIBLE_ADULT_HOGLIN_COUNT, +- MemoryModuleType.NEAREST_VISIBLE_HUNTABLE_HOGLIN, +- MemoryModuleType.NEAREST_TARGETABLE_PLAYER_NOT_WEARING_GOLD, +- MemoryModuleType.NEAREST_PLAYER_HOLDING_WANTED_ITEM, +- MemoryModuleType.ATE_RECENTLY, +- MemoryModuleType.NEAREST_REPELLENT +- ); ++ private static final double PROBABILITY_OF_SPAWNING_WITH_CROSSBOW_INSTEAD_OF_SWORD = 0.5D; ++ public final SimpleContainer inventory = new SimpleContainer(8); ++ public boolean cannotHunt; ++ protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.NEAREST_ITEMS, SensorType.HURT_BY, SensorType.PIGLIN_SPECIFIC_SENSOR); ++ protected static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.LOOK_TARGET, MemoryModuleType.DOORS_TO_CLOSE, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ADULT_PIGLINS, MemoryModuleType.NEARBY_ADULT_PIGLINS, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, new MemoryModuleType[]{MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.ATTACK_TARGET, MemoryModuleType.ATTACK_COOLING_DOWN, MemoryModuleType.INTERACTION_TARGET, MemoryModuleType.PATH, MemoryModuleType.ANGRY_AT, MemoryModuleType.UNIVERSAL_ANGER, MemoryModuleType.AVOID_TARGET, MemoryModuleType.ADMIRING_ITEM, MemoryModuleType.TIME_TRYING_TO_REACH_ADMIRE_ITEM, MemoryModuleType.ADMIRING_DISABLED, MemoryModuleType.DISABLE_WALK_TO_ADMIRE_ITEM, MemoryModuleType.CELEBRATE_LOCATION, MemoryModuleType.DANCING, MemoryModuleType.HUNTED_RECENTLY, MemoryModuleType.NEAREST_VISIBLE_BABY_HOGLIN, MemoryModuleType.NEAREST_VISIBLE_NEMESIS, MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED, MemoryModuleType.RIDE_TARGET, MemoryModuleType.VISIBLE_ADULT_PIGLIN_COUNT, MemoryModuleType.VISIBLE_ADULT_HOGLIN_COUNT, MemoryModuleType.NEAREST_VISIBLE_HUNTABLE_HOGLIN, MemoryModuleType.NEAREST_TARGETABLE_PLAYER_NOT_WEARING_GOLD, MemoryModuleType.NEAREST_PLAYER_HOLDING_WANTED_ITEM, MemoryModuleType.ATE_RECENTLY, MemoryModuleType.NEAREST_REPELLENT}); ++ // CraftBukkit start - Custom bartering and interest list ++ public Set allowedBarterItems = new HashSet<>(); ++ public Set interestItems = new HashSet<>(); ++ // CraftBukkit end + + public Piglin(EntityType entityType, Level level) { + super(entityType, level); +@@ -136,6 +109,14 @@ + } + + this.writeInventoryToTag(compound); ++ // CraftBukkit start ++ ListTag barterList = new ListTag(); ++ allowedBarterItems.stream().map(BuiltInRegistries.ITEM::getKey).map(ResourceLocation::toString).map(StringTag::valueOf).forEach(barterList::add); ++ compound.put("Bukkit.BarterList", barterList); ++ ListTag interestList = new ListTag(); ++ interestItems.stream().map(BuiltInRegistries.ITEM::getKey).map(ResourceLocation::toString).map(StringTag::valueOf).forEach(interestList::add); ++ compound.put("Bukkit.InterestList", interestList); ++ // CraftBukkit end + } + + @Override +@@ -144,6 +125,10 @@ + this.setBaby(compound.getBoolean("IsBaby")); + this.setCannotHunt(compound.getBoolean("CannotHunt")); + this.readInventoryFromTag(compound); ++ // CraftBukkit start ++ this.allowedBarterItems = compound.getList("Bukkit.BarterList", 8).stream().map(Tag::getAsString).map(ResourceLocation::tryParse).map(BuiltInRegistries.ITEM::get).collect(Collectors.toCollection(HashSet::new)); ++ this.interestItems = compound.getList("Bukkit.InterestList", 8).stream().map(Tag::getAsString).map(ResourceLocation::tryParse).map(BuiltInRegistries.ITEM::get).collect(Collectors.toCollection(HashSet::new)); ++ // CraftBukkit end + } + + @VisibleForDebug +@@ -254,7 +248,7 @@ + + @Override + public Brain getBrain() { +- return (Brain)super.getBrain(); ++ return (Brain) super.getBrain(); // CraftBukkit - Decompile error + } + + @Override +@@ -398,7 +388,7 @@ + } + + protected void holdInOffHand(ItemStack stack) { +- if (stack.is(PiglinAi.BARTERING_ITEM)) { ++ if (stack.is(PiglinAi.BARTERING_ITEM) || allowedBarterItems.contains(stack.getItem())) { // CraftBukkit - Changes to accept custom payment items + this.setItemSlot(EquipmentSlot.OFFHAND, stack); + this.setGuaranteedDrop(EquipmentSlot.OFFHAND); + } else { +@@ -422,12 +414,10 @@ + if (EnchantmentHelper.hasBindingCurse(existing)) { + return false; + } else { +- boolean flag = PiglinAi.isLovedItem(candidate) || candidate.is(Items.CROSSBOW); +- boolean flag1 = PiglinAi.isLovedItem(existing) || existing.is(Items.CROSSBOW); +- return flag && !flag1 +- || (flag || !flag1) +- && (!this.isAdult() || candidate.is(Items.CROSSBOW) || !existing.is(Items.CROSSBOW)) +- && super.canReplaceCurrentItem(candidate, existing); ++ boolean flag = PiglinAi.isLovedItem(candidate, this) || candidate.is(Items.CROSSBOW); // CraftBukkit ++ boolean flag1 = PiglinAi.isLovedItem(existing, this) || existing.is(Items.CROSSBOW); // CraftBukkit ++ ++ return flag && !flag1 ? true : (!flag && flag1 ? false : (this.isAdult() && !candidate.is(Items.CROSSBOW) && existing.is(Items.CROSSBOW) ? false : super.canReplaceCurrentItem(candidate, existing))); + } + } + +@@ -453,7 +444,7 @@ + + @Override + protected SoundEvent getAmbientSound() { +- return this.level().isClientSide ? null : PiglinAi.getSoundForCurrentActivity(this).orElse(null); ++ return this.level().isClientSide ? null : (SoundEvent) PiglinAi.getSoundForCurrentActivity(this).orElse(null); // CraftBukkit - Decompile error + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/piglin/PiglinAi.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/piglin/PiglinAi.java.patch new file mode 100644 index 0000000000..1f9d3de4ad --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/piglin/PiglinAi.java.patch @@ -0,0 +1,142 @@ +--- a/net/minecraft/world/entity/monster/piglin/PiglinAi.java ++++ b/net/minecraft/world/entity/monster/piglin/PiglinAi.java +@@ -72,6 +73,12 @@ + import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; + import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import java.util.stream.Collectors; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.entity.PiglinBarterEvent; ++// CraftBukkit end + + public class PiglinAi { + public static final int REPELLENT_DETECTION_RANGE_HORIZONTAL = 8; +@@ -329,8 +238,10 @@ + + protected static void pickUpItem(Piglin piglin, ItemEntity itemEntity) { + stopWalking(piglin); +- ItemStack item; +- if (itemEntity.getItem().is(Items.GOLD_NUGGET)) { ++ ItemStack itemstack; ++ ++ // CraftBukkit start ++ if (itemEntity.getItem().is(Items.GOLD_NUGGET) && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(piglin, itemEntity, 0, false).isCancelled()) { + piglin.take(itemEntity, itemEntity.getItem().getCount()); + item = itemEntity.getItem(); + itemEntity.discard(); +@@ -338,15 +251,17 @@ + piglin.take(itemEntity, 1); + item = removeOneItemFromItemEntity(itemEntity); + } ++ // CraftBukkit end + +- if (isLovedItem(item)) { ++ if (isLovedItem(itemstack, piglin)) { // CraftBukkit - Changes to allow for custom payment in bartering + piglin.getBrain().eraseMemory(MemoryModuleType.TIME_TRYING_TO_REACH_ADMIRE_ITEM); + holdInOffhand(piglin, item); + admireGoldItem(piglin); + } else if (isFood(item) && !hasEatenRecently(piglin)) { + eat(piglin); + } else { +- boolean flag = !piglin.equipItemIfPossible(item).equals(ItemStack.EMPTY); ++ boolean flag = !piglin.equipItemIfPossible(itemstack, itemEntity).equals(ItemStack.EMPTY); // CraftBukkit ++ + if (!flag) { + putInInventory(piglin, item); + } +@@ -377,21 +296,28 @@ + ItemStack itemInHand = piglin.getItemInHand(InteractionHand.OFF_HAND); + piglin.setItemInHand(InteractionHand.OFF_HAND, ItemStack.EMPTY); + if (piglin.isAdult()) { +- boolean isBarterCurrency = isBarterCurrency(itemInHand); +- if (shouldBarter && isBarterCurrency) { +- throwItems(piglin, getBarterResponseItems(piglin)); +- } else if (!isBarterCurrency) { +- boolean flag = !piglin.equipItemIfPossible(itemInHand).isEmpty(); +- if (!flag) { +- putInInventory(piglin, itemInHand); ++ flag1 = isBarterCurrency(itemstack, piglin); // CraftBukkit - Changes to allow custom payment for bartering ++ if (shouldBarter && flag1) { ++ // CraftBukkit start ++ PiglinBarterEvent event = CraftEventFactory.callPiglinBarterEvent(piglin, getBarterResponseItems(piglin), itemstack); ++ if (!event.isCancelled()) { ++ throwItems(piglin, event.getOutcome().stream().map(CraftItemStack::asNMSCopy).collect(Collectors.toList())); + } ++ // CraftBukkit end ++ } else if (!flag1) { ++ boolean flag2 = !piglin.equipItemIfPossible(itemstack).isEmpty(); ++ ++ if (!flag2) { ++ putInInventory(piglin, itemstack); ++ } + } + } else { +- boolean isBarterCurrency = !piglin.equipItemIfPossible(itemInHand).isEmpty(); +- if (!isBarterCurrency) { +- ItemStack mainHandItem = piglin.getMainHandItem(); +- if (isLovedItem(mainHandItem)) { +- putInInventory(piglin, mainHandItem); ++ flag1 = !piglin.equipItemIfPossible(itemstack).isEmpty(); ++ if (!flag1) { ++ ItemStack itemstack1 = piglin.getMainHandItem(); ++ ++ if (isLovedItem(itemstack1, piglin)) { // CraftBukkit - Changes to allow for custom payment in bartering ++ putInInventory(piglin, itemstack1); + } else { + throwItems(piglin, Collections.singletonList(mainHandItem)); + } +@@ -459,7 +393,7 @@ + return false; + } else if (isAdmiringDisabled(piglin) && piglin.getBrain().hasMemoryValue(MemoryModuleType.ATTACK_TARGET)) { + return false; +- } else if (isBarterCurrency(stack)) { ++ } else if (isBarterCurrency(stack, piglin)) { // CraftBukkit + return isNotHoldingLovedItemInOffHand(piglin); + } else { + boolean canAddToInventory = piglin.canAddToInventory(stack); +@@ -473,6 +402,12 @@ + } + } + ++ // CraftBukkit start - Added method to allow checking for custom payment items ++ protected static boolean isLovedItem(ItemStack itemstack, Piglin piglin) { ++ return isLovedItem(itemstack) || (piglin.interestItems.contains(itemstack.getItem()) || piglin.allowedBarterItems.contains(itemstack.getItem())); ++ } ++ // CraftBukkit end ++ + protected static boolean isLovedItem(ItemStack item) { + return item.is(ItemTags.PIGLIN_LOVED); + } +@@ -548,7 +503,7 @@ + } + + protected static boolean canAdmire(Piglin piglin, ItemStack stack) { +- return !isAdmiringDisabled(piglin) && !isAdmiringItem(piglin) && piglin.isAdult() && isBarterCurrency(stack); ++ return !isAdmiringDisabled(piglin) && !isAdmiringItem(piglin) && piglin.isAdult() && isBarterCurrency(stack, piglin); // CraftBukkit + } + + protected static void wasHurtBy(Piglin piglin, LivingEntity target) { +@@ -796,6 +760,12 @@ + return piglin.getBrain().hasMemoryValue(MemoryModuleType.ADMIRING_ITEM); + } + ++ // CraftBukkit start - Changes to allow custom payment for bartering ++ private static boolean isBarterCurrency(ItemStack itemstack, Piglin piglin) { ++ return isBarterCurrency(itemstack) || piglin.allowedBarterItems.contains(itemstack.getItem()); ++ } ++ // CraftBukkit end ++ + private static boolean isBarterCurrency(ItemStack stack) { + return stack.is(BARTERING_ITEM); + } +@@ -833,7 +803,7 @@ + } + + private static boolean isNotHoldingLovedItemInOffHand(Piglin piglin) { +- return piglin.getOffhandItem().isEmpty() || !isLovedItem(piglin.getOffhandItem()); ++ return piglin.getOffhandItem().isEmpty() || !isLovedItem(piglin.getOffhandItem(), piglin); // CraftBukkit - Changes to allow custom payment for bartering + } + + public static boolean isZombified(EntityType entityType) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/warden/Warden.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/warden/Warden.java.patch new file mode 100644 index 0000000000..23a489b117 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/monster/warden/Warden.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/entity/monster/warden/Warden.java ++++ b/net/minecraft/world/entity/monster/warden/Warden.java +@@ -404,8 +412,9 @@ + } + + public static void applyDarknessAround(ServerLevel level, Vec3 pos, @Nullable Entity source, int radius) { +- MobEffectInstance mobEffectInstance = new MobEffectInstance(MobEffects.DARKNESS, 260, 0, false, false); +- MobEffectUtil.addEffectToPlayersAround(level, source, pos, (double)radius, mobEffectInstance, 200); ++ MobEffectInstance mobeffect = new MobEffectInstance(MobEffects.DARKNESS, 260, 0, false, false); ++ ++ MobEffectUtil.addEffectToPlayersAround(level, source, pos, radius, mobeffect, 200, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.WARDEN); // CraftBukkit - Add EntityPotionEffectEvent.Cause + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/npc/AbstractVillager.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/npc/AbstractVillager.java.patch new file mode 100644 index 0000000000..f8fffcf3b4 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/npc/AbstractVillager.java.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/world/entity/npc/AbstractVillager.java ++++ b/net/minecraft/world/entity/npc/AbstractVillager.java +@@ -34,8 +34,23 @@ + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.inventory.CraftMerchant; ++import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; ++import org.bukkit.event.entity.VillagerAcquireTradeEvent; ++// CraftBukkit end + +-public abstract class AbstractVillager extends AgeableMob implements InventoryCarrier, Npc, Merchant { ++public abstract class AbstractVillager extends AgeableMob implements InventoryCarrier, NPC, Merchant { ++ ++ // CraftBukkit start ++ private CraftMerchant craftMerchant; ++ ++ @Override ++ public CraftMerchant getCraftMerchant() { ++ return (craftMerchant == null) ? craftMerchant = new CraftMerchant(this) : craftMerchant; ++ } ++ // CraftBukkit end + private static final EntityDataAccessor DATA_UNHAPPY_COUNTER = SynchedEntityData.defineId(AbstractVillager.class, EntityDataSerializers.INT); + public static final int VILLAGER_SLOT_OFFSET = 300; + private static final int VILLAGER_INVENTORY_SIZE = 8; +@@ -43,7 +58,7 @@ + private Player tradingPlayer; + @Nullable + protected MerchantOffers offers; +- private final SimpleContainer inventory = new SimpleContainer(8); ++ private final SimpleContainer inventory = new SimpleContainer(8, (org.bukkit.craftbukkit.entity.CraftAbstractVillager) this.getBukkitEntity()); // CraftBukkit add argument + + public AbstractVillager(EntityType entityType, Level level) { + super(entityType, level); +@@ -226,11 +243,21 @@ + ArrayList list = Lists.newArrayList(newTrades); + int i = 0; + +- while (i < maxNumbers && !list.isEmpty()) { +- MerchantOffer offer = list.remove(this.random.nextInt(list.size())).getOffer(this, this.random); +- if (offer != null) { +- givenMerchantOffers.add(offer); +- i++; ++ while (j < maxNumbers && !arraylist.isEmpty()) { ++ MerchantOffer merchantrecipe = ((VillagerTrades.ItemListing) arraylist.remove(this.random.nextInt(arraylist.size()))).getOffer(this, this.random); ++ ++ if (merchantrecipe != null) { ++ // CraftBukkit start ++ VillagerAcquireTradeEvent event = new VillagerAcquireTradeEvent((org.bukkit.entity.AbstractVillager) getBukkitEntity(), merchantrecipe.asBukkit()); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ if (!event.isCancelled()) { ++ givenMerchantOffers.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); ++ } ++ // CraftBukkit end ++ ++j; + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/npc/InventoryCarrier.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/npc/InventoryCarrier.java.patch new file mode 100644 index 0000000000..e3a2262da9 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/npc/InventoryCarrier.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/entity/npc/InventoryCarrier.java ++++ b/net/minecraft/world/entity/npc/InventoryCarrier.java +@@ -20,6 +23,13 @@ + return; + } + ++ // CraftBukkit start ++ ItemStack remaining = new SimpleContainer(inventorysubcontainer).addItem(itemstack); ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(mob, itemEntity, remaining.getCount(), false).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ + mob.onItemPickup(itemEntity); + int count = item.getCount(); + ItemStack itemStack = inventory.addItem(item); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/npc/Villager.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/npc/Villager.java.patch new file mode 100644 index 0000000000..eab608f375 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/npc/Villager.java.patch @@ -0,0 +1,106 @@ +--- a/net/minecraft/world/entity/npc/Villager.java ++++ b/net/minecraft/world/entity/npc/Villager.java +@@ -91,6 +92,13 @@ + import net.minecraft.world.phys.AABB; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTransformEvent; ++import org.bukkit.event.entity.VillagerReplenishTradeEvent; ++// CraftBukkit end ++ + public class Villager extends AbstractVillager implements ReputationEventHandler, VillagerDataHolder { + private static final Logger LOGGER = LogUtils.getLogger(); + private static final EntityDataAccessor DATA_VILLAGER_DATA = SynchedEntityData.defineId(Villager.class, EntityDataSerializers.VILLAGER_DATA); +@@ -286,7 +240,7 @@ + this.increaseProfessionLevelOnUpdate = false; + } + +- this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 200, 0)); ++ this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 200, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.VILLAGER_TRADE); // CraftBukkit + } + } + +@@ -397,8 +365,16 @@ + public void restock() { + this.updateDemand(); + +- for (MerchantOffer merchantOffer : this.getOffers()) { +- merchantOffer.resetUses(); ++ while (iterator.hasNext()) { ++ MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); ++ ++ // CraftBukkit start ++ VillagerReplenishTradeEvent event = new VillagerReplenishTradeEvent((org.bukkit.entity.Villager) this.getBukkitEntity(), merchantrecipe.asBukkit()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ merchantrecipe.resetUses(); ++ } ++ // CraftBukkit end + } + + this.resendOffersToTradingPlayer(); +@@ -458,8 +438,18 @@ + private void catchUpDemand() { + int i = 2 - this.numberOfRestocksToday; + if (i > 0) { +- for (MerchantOffer merchantOffer : this.getOffers()) { +- merchantOffer.resetUses(); ++ Iterator iterator = this.getOffers().iterator(); ++ ++ while (iterator.hasNext()) { ++ MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); ++ ++ // CraftBukkit start ++ VillagerReplenishTradeEvent event = new VillagerReplenishTradeEvent((org.bukkit.entity.Villager) this.getBukkitEntity(), merchantrecipe.asBukkit()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ merchantrecipe.resetUses(); ++ } ++ // CraftBukkit end + } + } + +@@ -818,8 +852,13 @@ + witch.setCustomNameVisible(this.isCustomNameVisible()); + } + +- witch.setPersistenceRequired(); +- level.addFreshEntityWithPassengers(witch); ++ entitywitch.setPersistenceRequired(); ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, entitywitch, EntityTransformEvent.TransformReason.LIGHTNING).isCancelled()) { ++ return; ++ } ++ level.addFreshEntityWithPassengers(entitywitch, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); ++ // CraftBukkit end + this.releaseAllPois(); + this.discard(); + } else { +@@ -900,15 +950,15 @@ + + public void spawnGolemIfNeeded(ServerLevel serverLevel, long gameTime, int minVillagerAmount) { + if (this.wantsToSpawnGolem(gameTime)) { +- AABB aABB = this.getBoundingBox().inflate(10.0, 10.0, 10.0); +- List entitiesOfClass = serverLevel.getEntitiesOfClass(Villager.class, aABB); +- List list = entitiesOfClass.stream().filter(villager -> villager.wantsToSpawnGolem(gameTime)).limit(5L).collect(Collectors.toList()); +- if (list.size() >= minVillagerAmount) { +- if (!SpawnUtil.trySpawnMob( +- EntityType.IRON_GOLEM, MobSpawnType.MOB_SUMMONED, serverLevel, this.blockPosition(), 10, 8, 6, SpawnUtil.Strategy.LEGACY_IRON_GOLEM +- ) +- .isEmpty()) { +- entitiesOfClass.forEach(GolemSensor::golemDetected); ++ AABB axisalignedbb = this.getBoundingBox().inflate(10.0D, 10.0D, 10.0D); ++ List list = serverLevel.getEntitiesOfClass(Villager.class, axisalignedbb); ++ List list1 = (List) list.stream().filter((entityvillager) -> { ++ return entityvillager.wantsToSpawnGolem(gameTime); ++ }).limit(5L).collect(Collectors.toList()); ++ ++ if (list1.size() >= j) { ++ if (!SpawnUtil.trySpawnMob(EntityType.IRON_GOLEM, EnumMobSpawn.MOB_SUMMONED, serverLevel, this.blockPosition(), 10, 8, 6, SpawnUtil.Strategy.LEGACY_IRON_GOLEM, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE).isEmpty()) { // CraftBukkit ++ list.forEach(GolemSensor::golemDetected); + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/npc/WanderingTrader.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/npc/WanderingTrader.java.patch new file mode 100644 index 0000000000..8894c943c2 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/npc/WanderingTrader.java.patch @@ -0,0 +1,66 @@ +--- a/net/minecraft/world/entity/npc/WanderingTrader.java ++++ b/net/minecraft/world/entity/npc/WanderingTrader.java +@@ -46,7 +47,15 @@ + import net.minecraft.world.phys.Vec3; + import org.apache.commons.lang3.tuple.Pair; + +-public class WanderingTrader extends AbstractVillager { ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; ++import org.bukkit.entity.AbstractVillager; ++import org.bukkit.event.entity.VillagerAcquireTradeEvent; ++// CraftBukkit end ++ ++public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVillager { ++ + private static final int NUMBER_OF_TRADE_OFFERS = 5; + @Nullable + private BlockPos wanderTarget; +@@ -54,6 +63,7 @@ + + public WanderingTrader(EntityType entityType, Level level) { + super(entityType, level); ++ this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader + } + + @Override +@@ -135,16 +132,28 @@ + if (this.level().enabledFeatures().contains(FeatureFlags.TRADE_REBALANCE)) { + this.experimentalUpdateTrades(); + } else { +- VillagerTrades.ItemListing[] itemListings = VillagerTrades.WANDERING_TRADER_TRADES.get(1); +- VillagerTrades.ItemListing[] itemListings1 = VillagerTrades.WANDERING_TRADER_TRADES.get(2); +- if (itemListings != null && itemListings1 != null) { +- MerchantOffers offers = this.getOffers(); +- this.addOffersFromItemListings(offers, itemListings, 5); +- int randomInt = this.random.nextInt(itemListings1.length); +- VillagerTrades.ItemListing itemListing = itemListings1[randomInt]; +- MerchantOffer offer = itemListing.getOffer(this, this.random); +- if (offer != null) { +- offers.add(offer); ++ VillagerTrades.ItemListing[] avillagertrades_imerchantrecipeoption = (VillagerTrades.ItemListing[]) VillagerTrades.WANDERING_TRADER_TRADES.get(1); ++ VillagerTrades.ItemListing[] avillagertrades_imerchantrecipeoption1 = (VillagerTrades.ItemListing[]) VillagerTrades.WANDERING_TRADER_TRADES.get(2); ++ ++ if (avillagertrades_imerchantrecipeoption != null && avillagertrades_imerchantrecipeoption1 != null) { ++ MerchantOffers merchantrecipelist = this.getOffers(); ++ ++ this.addOffersFromItemListings(merchantrecipelist, avillagertrades_imerchantrecipeoption, 5); ++ int i = this.random.nextInt(avillagertrades_imerchantrecipeoption1.length); ++ VillagerTrades.ItemListing villagertrades_imerchantrecipeoption = avillagertrades_imerchantrecipeoption1[i]; ++ MerchantOffer merchantrecipe = villagertrades_imerchantrecipeoption.getOffer(this, this.random); ++ ++ if (merchantrecipe != null) { ++ // CraftBukkit start ++ VillagerAcquireTradeEvent event = new VillagerAcquireTradeEvent((AbstractVillager) getBukkitEntity(), merchantrecipe.asBukkit()); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ if (!event.isCancelled()) { ++ merchantrecipelist.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); ++ } ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/npc/WanderingTraderSpawner.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/npc/WanderingTraderSpawner.java.patch new file mode 100644 index 0000000000..7be38ff45b --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/npc/WanderingTraderSpawner.java.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/world/entity/npc/WanderingTraderSpawner.java ++++ b/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +@@ -101,16 +110,17 @@ + return false; + } + +- WanderingTrader wanderingTrader = EntityType.WANDERING_TRADER.spawn(serverLevel, blockPos2, MobSpawnType.EVENT); +- if (wanderingTrader != null) { +- for (int i1 = 0; i1 < 2; i1++) { +- this.tryToSpawnLlamaFor(serverLevel, wanderingTrader, 4); ++ WanderingTrader entityvillagertrader = (WanderingTrader) EntityType.WANDERING_TRADER.spawn(serverLevel, blockposition2, EnumMobSpawn.EVENT, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit ++ ++ if (entityvillagertrader != null) { ++ for (int i = 0; i < 2; ++i) { ++ this.tryToSpawnLlamaFor(serverLevel, entityvillagertrader, 4); + } + +- this.serverLevelData.setWanderingTraderId(wanderingTrader.getUUID()); +- wanderingTrader.setDespawnDelay(48000); +- wanderingTrader.setWanderTarget(blockPos1); +- wanderingTrader.restrictTo(blockPos1, 16); ++ this.serverLevelData.setWanderingTraderId(entityvillagertrader.getUUID()); ++ // entityvillagertrader.setDespawnDelay(48000); // CraftBukkit - moved to EntityVillagerTrader constructor. This lets the value be modified by plugins on CreatureSpawnEvent ++ entityvillagertrader.setWanderTarget(blockposition1); ++ entityvillagertrader.restrictTo(blockposition1, 16); + return true; + } + } +@@ -120,11 +130,13 @@ + } + + private void tryToSpawnLlamaFor(ServerLevel serverLevel, WanderingTrader trader, int maxDistance) { +- BlockPos blockPos = this.findSpawnPositionNear(serverLevel, trader.blockPosition(), maxDistance); +- if (blockPos != null) { +- TraderLlama traderLlama = EntityType.TRADER_LLAMA.spawn(serverLevel, blockPos, MobSpawnType.EVENT); +- if (traderLlama != null) { +- traderLlama.setLeashedTo(trader, true); ++ BlockPos blockposition = this.findSpawnPositionNear(serverLevel, trader.blockPosition(), maxDistance); ++ ++ if (blockposition != null) { ++ TraderLlama entityllamatrader = (TraderLlama) EntityType.TRADER_LLAMA.spawn(serverLevel, blockposition, EnumMobSpawn.EVENT, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit ++ ++ if (entityllamatrader != null) { ++ entityllamatrader.setLeashedTo(trader, true); + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/player/Inventory.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/player/Inventory.java.patch new file mode 100644 index 0000000000..78b7c418e9 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/player/Inventory.java.patch @@ -0,0 +1,103 @@ +--- a/net/minecraft/world/entity/player/Inventory.java ++++ b/net/minecraft/world/entity/player/Inventory.java +@@ -24,7 +26,15 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.state.BlockState; + +-public class Inventory implements Container, Nameable { ++// CraftBukkit start ++import java.util.ArrayList; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ ++public class Inventory implements Container, INamableTileEntity { ++ + public static final int POP_TIME_DURATION = 5; + public static final int INVENTORY_SIZE = 36; + private static final int SELECTION_SIZE = 9; +@@ -40,6 +50,54 @@ + public final Player player; + private int timesChanged; + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ List combined = new ArrayList(items.size() + armor.size() + offhand.size()); ++ for (List sub : this.compartments) { ++ combined.addAll(sub); ++ } ++ ++ return combined; ++ } ++ ++ public List getArmorContents() { ++ return this.armor; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return this.player.getBukkitEntity(); ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return player.getBukkitEntity().getLocation(); ++ } ++ // CraftBukkit end ++ + public Inventory(Player player) { + this.player = player; + } +@@ -60,6 +118,28 @@ + && destination.getCount() < this.getMaxStackSize(); + } + ++ // CraftBukkit start - Watch method above! :D ++ public int canHold(ItemStack itemstack) { ++ int remains = itemstack.getCount(); ++ for (int i = 0; i < this.items.size(); ++i) { ++ ItemStack itemstack1 = this.getItem(i); ++ if (itemstack1.isEmpty()) return itemstack.getCount(); ++ ++ if (this.hasRemainingSpaceForItem(itemstack1, itemstack)) { ++ remains -= (itemstack1.getMaxStackSize() < this.getMaxStackSize() ? itemstack1.getMaxStackSize() : this.getMaxStackSize()) - itemstack1.getCount(); ++ } ++ if (remains <= 0) return itemstack.getCount(); ++ } ++ ItemStack offhandItemStack = this.getItem(this.items.size() + this.armor.size()); ++ if (this.hasRemainingSpaceForItem(offhandItemStack, itemstack)) { ++ remains -= (offhandItemStack.getMaxStackSize() < this.getMaxStackSize() ? offhandItemStack.getMaxStackSize() : this.getMaxStackSize()) - offhandItemStack.getCount(); ++ } ++ if (remains <= 0) return itemstack.getCount(); ++ ++ return itemstack.getCount() - remains; ++ } ++ // CraftBukkit end ++ + public int getFreeSlot() { + for (int i = 0; i < this.items.size(); i++) { + if (this.items.get(i).isEmpty()) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/player/Player.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/player/Player.java.patch new file mode 100644 index 0000000000..0a462b50bf --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/player/Player.java.patch @@ -0,0 +1,560 @@ +--- a/net/minecraft/world/entity/player/Player.java ++++ b/net/minecraft/world/entity/player/Player.java +@@ -111,6 +112,16 @@ + import net.minecraft.world.scores.Scoreboard; + import net.minecraft.world.scores.Team; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.util.CraftVector; ++import org.bukkit.entity.Item; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.entity.EntityExhaustionEvent; ++import org.bukkit.event.player.PlayerDropItemEvent; ++import org.bukkit.event.player.PlayerVelocityEvent; ++// CraftBukkit end + + public abstract class Player extends LivingEntity { + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -143,10 +148,10 @@ + protected static final EntityDataAccessor DATA_SHOULDER_RIGHT = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG); + private long timeEntitySatOnShoulder; + private final Inventory inventory = new Inventory(this); +- protected PlayerEnderChestContainer enderChestInventory = new PlayerEnderChestContainer(); ++ protected PlayerEnderChestContainer enderChestInventory = new PlayerEnderChestContainer(this); // CraftBukkit - add "this" to constructor + public final InventoryMenu inventoryMenu; + public AbstractContainerMenu containerMenu; +- protected FoodData foodData = new FoodData(); ++ protected FoodData foodData = new FoodData(this); // CraftBukkit - add "this" to constructor + protected int jumpTriggerTime; + public float oBob; + public float bob; +@@ -175,6 +180,16 @@ + public FishingHook fishing; + protected float hurtDir; + ++ // CraftBukkit start ++ public boolean fauxSleeping; ++ public int oldLevel = -1; ++ ++ @Override ++ public CraftHumanEntity getBukkitEntity() { ++ return (CraftHumanEntity) super.getBukkitEntity(); ++ } ++ // CraftBukkit end ++ + public Player(Level level, BlockPos pos, float yRot, GameProfile gameProfile) { + super(EntityType.PLAYER, level); + this.setUUID(gameProfile.getId()); +@@ -315,9 +331,10 @@ + } + + private void turtleHelmetTick() { +- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.HEAD); +- if (itemBySlot.is(Items.TURTLE_HELMET) && !this.isEyeInFluid(FluidTags.WATER)) { +- this.addEffect(new MobEffectInstance(MobEffects.WATER_BREATHING, 200, 0, false, false, true)); ++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); ++ ++ if (itemstack.is(Items.TURTLE_HELMET) && !this.isEyeInFluid(FluidTags.WATER)) { ++ this.addEffect(new MobEffectInstance(MobEffects.WATER_BREATHING, 200, 0, false, false, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TURTLE_HELMET); // CraftBukkit + } + } + +@@ -485,8 +504,14 @@ + public void rideTick() { + if (!this.level().isClientSide && this.wantsToStopRiding() && this.isPassenger()) { + this.stopRiding(); +- this.setShiftKeyDown(false); +- } else { ++ // CraftBukkit start - SPIGOT-7316: no longer passenger, dismount and return ++ if (!this.isPassenger()) { ++ this.setShiftKeyDown(false); ++ return; ++ } ++ } ++ { ++ // CraftBukkit end + super.rideTick(); + this.oBob = this.bob; + this.bob = 0.0F; +@@ -508,7 +533,8 @@ + + if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.level().getGameRules().getBoolean(GameRules.RULE_NATURAL_REGENERATION)) { + if (this.getHealth() < this.getMaxHealth() && this.tickCount % 20 == 0) { +- this.heal(1.0F); ++ // CraftBukkit - added regain reason of "REGEN" for filtering purposes. ++ this.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.REGEN); + } + + if (this.foodData.needsFood() && this.tickCount % 10 == 0) { +@@ -670,7 +694,14 @@ + + @Nullable + public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean includeThrowerName) { +- if (droppedItem.isEmpty()) { ++ // CraftBukkit start - SPIGOT-2942: Add boolean to call event ++ return drop(droppedItem, dropAround, includeThrowerName, true); ++ } ++ ++ @Nullable ++ public ItemEntity drop(ItemStack itemstack, boolean flag, boolean flag1, boolean callEvent) { ++ // CraftBukkit end ++ if (itemstack.isEmpty()) { + return null; + } else { + if (this.level().isClientSide) { +@@ -703,7 +735,34 @@ + ); + } + +- return itemEntity; ++ // CraftBukkit start - fire PlayerDropItemEvent ++ if (!callEvent) { // SPIGOT-2942: Add boolean to call event ++ return entityitem; ++ } ++ org.bukkit.entity.Player player = (org.bukkit.entity.Player) this.getBukkitEntity(); ++ Item drop = (Item) entityitem.getBukkitEntity(); ++ ++ PlayerDropItemEvent event = new PlayerDropItemEvent(player, drop); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ org.bukkit.inventory.ItemStack cur = player.getInventory().getItemInHand(); ++ if (flag1 && (cur == null || cur.getAmount() == 0)) { ++ // The complete stack was dropped ++ player.getInventory().setItemInHand(drop.getItemStack()); ++ } else if (flag1 && cur.isSimilar(drop.getItemStack()) && cur.getAmount() < cur.getMaxStackSize() && drop.getItemStack().getAmount() == 1) { ++ // Only one item is dropped ++ cur.setAmount(cur.getAmount() + 1); ++ player.getInventory().setItemInHand(cur); ++ } else { ++ // Fallback ++ player.getInventory().addItem(drop.getItemStack()); ++ } ++ return null; ++ } ++ // CraftBukkit end ++ ++ return entityitem; + } + } + +@@ -837,12 +912,12 @@ + return false; + } else { + if (!this.level().isClientSide) { +- this.removeEntitiesOnShoulder(); ++ // this.removeEntitiesOnShoulder(); // CraftBukkit - moved down + } + + if (source.scalesWithDifficulty()) { + if (this.level().getDifficulty() == Difficulty.PEACEFUL) { +- amount = 0.0F; ++ return false; // CraftBukkit - f = 0.0f -> return false + } + + if (this.level().getDifficulty() == Difficulty.EASY) { +@@ -854,7 +929,13 @@ + } + } + +- return amount != 0.0F && super.hurt(source, amount); ++ // CraftBukkit start - Don't filter out 0 damage ++ boolean damaged = super.hurt(source, amount); ++ if (damaged) { ++ this.removeEntitiesOnShoulder(); ++ } ++ return damaged; ++ // CraftBukkit end + } + } + } +@@ -873,9 +955,29 @@ + } + + public boolean canHarmPlayer(Player other) { +- Team team = this.getTeam(); +- Team team1 = other.getTeam(); +- return team == null || !team.isAlliedTo(team1) || team.isAllowFriendlyFire(); ++ // CraftBukkit start - Change to check OTHER player's scoreboard team according to API ++ // To summarize this method's logic, it's "Can parameter hurt this" ++ org.bukkit.scoreboard.Team team; ++ if (other instanceof ServerPlayer) { ++ ServerPlayer thatPlayer = (ServerPlayer) other; ++ team = thatPlayer.getBukkitEntity().getScoreboard().getPlayerTeam(thatPlayer.getBukkitEntity()); ++ if (team == null || team.allowFriendlyFire()) { ++ return true; ++ } ++ } else { ++ // This should never be called, but is implemented anyway ++ org.bukkit.OfflinePlayer thisPlayer = other.level().getCraftServer().getOfflinePlayer(other.getScoreboardName()); ++ team = other.level().getCraftServer().getScoreboardManager().getMainScoreboard().getPlayerTeam(thisPlayer); ++ if (team == null || team.allowFriendlyFire()) { ++ return true; ++ } ++ } ++ ++ if (this instanceof ServerPlayer) { ++ return !team.hasPlayer(((ServerPlayer) this).getBukkitEntity()); ++ } ++ return !team.hasPlayer(this.level().getCraftServer().getOfflinePlayer(this.getScoreboardName())); ++ // CraftBukkit end + } + + @Override +@@ -913,29 +1019,38 @@ + } + } + ++ // CraftBukkit start + @Override +- protected void actuallyHurt(DamageSource damageSrc, float damageAmount) { +- if (!this.isInvulnerableTo(damageSrc)) { +- damageAmount = this.getDamageAfterArmorAbsorb(damageSrc, damageAmount); +- damageAmount = this.getDamageAfterMagicAbsorb(damageSrc, damageAmount); +- float var7 = Math.max(damageAmount - this.getAbsorptionAmount(), 0.0F); +- this.setAbsorptionAmount(this.getAbsorptionAmount() - (damageAmount - var7)); +- float f1 = damageAmount - var7; +- if (f1 > 0.0F && f1 < 3.4028235E37F) { +- this.awardStat(Stats.DAMAGE_ABSORBED, Math.round(f1 * 10.0F)); ++ protected boolean damageEntity0(DamageSource damagesource, float f) { // void -> boolean ++ if (true) { ++ return super.damageEntity0(damagesource, f); ++ } ++ // CraftBukkit end ++ if (!this.isInvulnerableTo(damagesource)) { ++ f = this.getDamageAfterArmorAbsorb(damagesource, f); ++ f = this.getDamageAfterMagicAbsorb(damagesource, f); ++ float f1 = f; ++ ++ f = Math.max(f - this.getAbsorptionAmount(), 0.0F); ++ this.setAbsorptionAmount(this.getAbsorptionAmount() - (f1 - f)); ++ float f2 = f1 - f; ++ ++ if (f2 > 0.0F && f2 < 3.4028235E37F) { ++ this.awardStat(Stats.DAMAGE_ABSORBED, Math.round(f2 * 10.0F)); + } + +- if (var7 != 0.0F) { +- this.causeFoodExhaustion(damageSrc.getFoodExhaustion()); +- this.getCombatTracker().recordDamage(damageSrc, var7); +- this.setHealth(this.getHealth() - var7); +- if (var7 < 3.4028235E37F) { +- this.awardStat(Stats.DAMAGE_TAKEN, Math.round(var7 * 10.0F)); ++ if (f != 0.0F) { ++ this.causeFoodExhaustion(damagesource.getFoodExhaustion(), EntityExhaustionEvent.ExhaustionReason.DAMAGED); // CraftBukkit - EntityExhaustionEvent ++ this.getCombatTracker().recordDamage(damagesource, f); ++ this.setHealth(this.getHealth() - f); ++ if (f < 3.4028235E37F) { ++ this.awardStat(Stats.DAMAGE_TAKEN, Math.round(f * 10.0F)); + } + + this.gameEvent(GameEvent.ENTITY_DAMAGE); + } + } ++ return false; // CraftBukkit + } + + @Override +@@ -1107,12 +1211,13 @@ + damageBonus = EnchantmentHelper.getDamageBonus(this.getMainHandItem(), MobType.UNDEFINED); + } + +- float attackStrengthScale = this.getAttackStrengthScale(0.5F); +- float var21 = f * (0.2F + attackStrengthScale * attackStrengthScale * 0.8F); +- float var23 = damageBonus * attackStrengthScale; +- this.resetAttackStrengthTicker(); +- if (var21 > 0.0F || var23 > 0.0F) { +- boolean flag = attackStrengthScale > 0.9F; ++ float f2 = this.getAttackStrengthScale(0.5F); ++ ++ f *= 0.2F + f2 * f2 * 0.8F; ++ f1 *= f2; ++ // this.resetAttackCooldown(); // CraftBukkit - Moved to EntityLiving to reset the cooldown after the damage is dealt ++ if (f > 0.0F || f1 > 0.0F) { ++ boolean flag = f2 > 0.9F; + boolean flag1 = false; + int i = 0; + int var24 = i + EnchantmentHelper.getKnockbackBonus(this); +@@ -1150,10 +1252,17 @@ + boolean flag4 = false; + int fireAspect = EnchantmentHelper.getFireAspect(this); + if (target instanceof LivingEntity) { +- f1 = ((LivingEntity)target).getHealth(); +- if (fireAspect > 0 && !target.isOnFire()) { +- flag4 = true; +- target.setSecondsOnFire(1); ++ f3 = ((LivingEntity) target).getHealth(); ++ if (j > 0 && !target.isOnFire()) { ++ // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), target.getBukkitEntity(), 1); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ flag4 = true; ++ target.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + } + +@@ -1183,19 +1286,15 @@ + if (flag3) { + float f2 = 1.0F + EnchantmentHelper.getSweepingDamageRatio(this) * f; + +- for (LivingEntity livingEntity : this.level() +- .getEntitiesOfClass(LivingEntity.class, target.getBoundingBox().inflate(1.0, 0.25, 1.0))) { +- if (livingEntity != this +- && livingEntity != target +- && !this.isAlliedTo(livingEntity) +- && (!(livingEntity instanceof ArmorStand) || !((ArmorStand)livingEntity).isMarker()) +- && this.distanceToSqr(livingEntity) < 9.0) { +- livingEntity.knockback( +- 0.4F, +- (double)Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)), +- (double)(-Mth.cos(this.getYRot() * (float) (Math.PI / 180.0))) +- ); +- livingEntity.hurt(this.damageSources().playerAttack(this), f2); ++ while (iterator.hasNext()) { ++ LivingEntity entityliving = (LivingEntity) iterator.next(); ++ ++ if (entityliving != this && entityliving != target && !this.isAlliedTo((Entity) entityliving) && (!(entityliving instanceof ArmorStand) || !((ArmorStand) entityliving).isMarker()) && this.distanceToSqr((Entity) entityliving) < 9.0D) { ++ // CraftBukkit start - Only apply knockback if the damage hits ++ if (entityliving.hurt(this.damageSources().playerAttack(this).sweep(), f4)) { ++ entityliving.knockback(0.4000000059604645D, (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F))); ++ } ++ // CraftBukkit end + } + } + +@@ -1205,9 +1303,26 @@ + } + + if (target instanceof ServerPlayer && target.hurtMarked) { +- ((ServerPlayer)target).connection.send(new ClientboundSetEntityMotionPacket(target)); ++ // CraftBukkit start - Add Velocity Event ++ boolean cancelled = false; ++ org.bukkit.entity.Player player = (org.bukkit.entity.Player) target.getBukkitEntity(); ++ org.bukkit.util.Vector velocity = CraftVector.toBukkit(vec3d); ++ ++ PlayerVelocityEvent event = new PlayerVelocityEvent(player, velocity.clone()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ cancelled = true; ++ } else if (!velocity.equals(event.getVelocity())) { ++ player.setVelocity(event.getVelocity()); ++ } ++ ++ if (!cancelled) { ++ ((ServerPlayer) target).connection.send(new ClientboundSetEntityMotionPacket(target)); + target.hurtMarked = false; +- target.setDeltaMovement(deltaMovement); ++ target.setDeltaMovement(vec3d); ++ } ++ // CraftBukkit end + } + + if (flag2) { +@@ -1250,10 +1363,18 @@ + } + + if (target instanceof LivingEntity) { +- float f3 = f1 - ((LivingEntity)target).getHealth(); +- this.awardStat(Stats.DAMAGE_DEALT, Math.round(f3 * 10.0F)); +- if (fireAspect > 0) { +- target.setSecondsOnFire(fireAspect * 4); ++ float f5 = f3 - ((LivingEntity) target).getHealth(); ++ ++ this.awardStat(Stats.DAMAGE_DEALT, Math.round(f5 * 10.0F)); ++ if (j > 0) { ++ // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), target.getBukkitEntity(), j * 4); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ target.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + + if (this.level() instanceof ServerLevel && f3 > 2.0F) { +@@ -1263,13 +1384,18 @@ + } + } + +- this.causeFoodExhaustion(0.1F); ++ this.causeFoodExhaustion(0.1F, EntityExhaustionEvent.ExhaustionReason.ATTACK); // CraftBukkit - EntityExhaustionEvent + } else { + this.level() + .playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F); + if (flag4) { + target.clearFire(); + } ++ // CraftBukkit start - resync on cancelled event ++ if (this instanceof ServerPlayer) { ++ ((ServerPlayer) this).getBukkitEntity().updateInventory(); ++ } ++ // CraftBukkit end + } + } + } +@@ -1344,7 +1471,13 @@ + } + + public Either startSleepInBed(BlockPos bedPos) { +- this.startSleeping(bedPos); ++ // CraftBukkit start ++ return this.startSleepInBed(bedPos, false); ++ } ++ ++ public Either startSleepInBed(BlockPos blockposition, boolean force) { ++ // CraftBukkit end ++ this.startSleeping(blockposition); + this.sleepCounter = 0; + return Either.right(Unit.INSTANCE); + } +@@ -1441,9 +1564,9 @@ + super.jumpFromGround(); + this.awardStat(Stats.JUMP); + if (this.isSprinting()) { +- this.causeFoodExhaustion(0.2F); ++ this.causeFoodExhaustion(0.2F, EntityExhaustionEvent.ExhaustionReason.JUMP_SPRINT); // CraftBukkit - EntityExhaustionEvent + } else { +- this.causeFoodExhaustion(0.05F); ++ this.causeFoodExhaustion(0.05F, EntityExhaustionEvent.ExhaustionReason.JUMP); // CraftBukkit - EntityExhaustionEvent + } + } + +@@ -1466,7 +1593,11 @@ + Vec3 deltaMovement1 = this.getDeltaMovement(); + this.setDeltaMovement(deltaMovement1.x, d * 0.6, deltaMovement1.z); + this.resetFallDistance(); +- this.setSharedFlag(7, false); ++ // CraftBukkit start ++ if (getSharedFlag(7) && !org.bukkit.craftbukkit.event.CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) { ++ this.setSharedFlag(7, false); ++ } ++ // CraftBukkit end + } else { + super.travel(travelVector); + } +@@ -1516,12 +1650,24 @@ + } + + public void startFallFlying() { +- this.setSharedFlag(7, true); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callToggleGlideEvent(this, true).isCancelled()) { ++ this.setSharedFlag(7, true); ++ } else { ++ // SPIGOT-5542: must toggle like below ++ this.setSharedFlag(7, true); ++ this.setSharedFlag(7, false); ++ } ++ // CraftBukkit end + } + + public void stopFallFlying() { ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) { + this.setSharedFlag(7, true); + this.setSharedFlag(7, false); ++ } ++ // CraftBukkit end + } + + @Override +@@ -1630,10 +1781,21 @@ + } + } + ++ // CraftBukkit start + public void causeFoodExhaustion(float exhaustion) { ++ this.causeFoodExhaustion(exhaustion, EntityExhaustionEvent.ExhaustionReason.UNKNOWN); ++ } ++ ++ public void causeFoodExhaustion(float f, EntityExhaustionEvent.ExhaustionReason reason) { ++ // CraftBukkit end + if (!this.abilities.invulnerable) { + if (!this.level().isClientSide) { +- this.foodData.addExhaustion(exhaustion); ++ // CraftBukkit start ++ EntityExhaustionEvent event = CraftEventFactory.callPlayerExhaustionEvent(this, reason, f); ++ if (!event.isCancelled()) { ++ this.foodData.addExhaustion(event.getExhaustion()); ++ } ++ // CraftBukkit end + } + } + } +@@ -1723,13 +1881,20 @@ + + @Override + public void setItemSlot(EquipmentSlot slot, ItemStack stack) { +- this.verifyEquippedItem(stack); +- if (slot == EquipmentSlot.MAINHAND) { +- this.onEquipItem(slot, this.inventory.items.set(this.inventory.selected, stack), stack); +- } else if (slot == EquipmentSlot.OFFHAND) { +- this.onEquipItem(slot, this.inventory.offhand.set(0, stack), stack); +- } else if (slot.getType() == EquipmentSlot.Type.ARMOR) { +- this.onEquipItem(slot, this.inventory.armor.set(slot.getIndex(), stack), stack); ++ // CraftBukkit start ++ setItemSlot(slot, stack, false); ++ } ++ ++ @Override ++ public void setItemSlot(EquipmentSlot enumitemslot, ItemStack itemstack, boolean silent) { ++ // CraftBukkit end ++ this.verifyEquippedItem(itemstack); ++ if (enumitemslot == EquipmentSlot.MAINHAND) { ++ this.onEquipItem(enumitemslot, (ItemStack) this.inventory.items.set(this.inventory.selected, itemstack), itemstack, silent); // CraftBukkit ++ } else if (enumitemslot == EquipmentSlot.OFFHAND) { ++ this.onEquipItem(enumitemslot, (ItemStack) this.inventory.offhand.set(0, itemstack), itemstack, silent); // CraftBukkit ++ } else if (enumitemslot.getType() == EquipmentSlot.Function.ARMOR) { ++ this.onEquipItem(enumitemslot, (ItemStack) this.inventory.armor.set(enumitemslot.getIndex(), itemstack), itemstack, silent); // CraftBukkit + } + } + +@@ -1765,24 +1933,30 @@ + + protected void removeEntitiesOnShoulder() { + if (this.timeEntitySatOnShoulder + 20L < this.level().getGameTime()) { +- this.respawnEntityOnShoulder(this.getShoulderEntityLeft()); +- this.setShoulderEntityLeft(new CompoundTag()); +- this.respawnEntityOnShoulder(this.getShoulderEntityRight()); +- this.setShoulderEntityRight(new CompoundTag()); ++ // CraftBukkit start ++ if (this.respawnEntityOnShoulder(this.getShoulderEntityLeft())) { ++ this.setShoulderEntityLeft(new CompoundTag()); ++ } ++ if (this.respawnEntityOnShoulder(this.getShoulderEntityRight())) { ++ this.setShoulderEntityRight(new CompoundTag()); ++ } ++ // CraftBukkit end + } + } + +- private void respawnEntityOnShoulder(CompoundTag entityCompound) { +- if (!this.level().isClientSide && !entityCompound.isEmpty()) { +- EntityType.create(entityCompound, this.level()).ifPresent(entity -> { ++ private boolean respawnEntityOnShoulder(CompoundTag nbttagcompound) { // CraftBukkit void->boolean ++ if (!this.level().isClientSide && !nbttagcompound.isEmpty()) { ++ return EntityType.create(nbttagcompound, this.level()).map((entity) -> { // CraftBukkit + if (entity instanceof TamableAnimal) { + ((TamableAnimal)entity).setOwnerUUID(this.uuid); + } + +- entity.setPos(this.getX(), this.getY() + 0.7F, this.getZ()); +- ((ServerLevel)this.level()).addWithUUID(entity); +- }); ++ entity.setPos(this.getX(), this.getY() + 0.699999988079071D, this.getZ()); ++ return ((ServerLevel) this.level()).addWithUUID(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit ++ }).orElse(true); // CraftBukkit + } ++ ++ return true; // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/AbstractArrow.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/AbstractArrow.java.patch new file mode 100644 index 0000000000..f87c49e800 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/AbstractArrow.java.patch @@ -0,0 +1,69 @@ +--- a/net/minecraft/world/entity/projectile/AbstractArrow.java ++++ b/net/minecraft/world/entity/projectile/AbstractArrow.java +@@ -44,6 +47,9 @@ + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.player.PlayerPickupArrowEvent; ++// CraftBukkit end + + public abstract class AbstractArrow extends Projectile { + private static final double ARROW_BASE_DAMAGE = 2.0; +@@ -197,8 +222,8 @@ + } + } + +- if (hitResult != null && !isNoPhysics) { +- this.onHit(hitResult); ++ if (object != null && !flag) { ++ this.preOnHit((HitResult) object); // CraftBukkit - projectile hit event + this.hasImpulse = true; + } + +@@ -341,10 +367,17 @@ + } + + boolean flag = entity.getType() == EntityType.ENDERMAN; +- int remainingFireTicks = entity.getRemainingFireTicks(); +- boolean isDeflectsArrows = entity.getType().is(EntityTypeTags.DEFLECTS_ARROWS); +- if (this.isOnFire() && !flag && !isDeflectsArrows) { +- entity.setSecondsOnFire(5); ++ int k = entity.getRemainingFireTicks(); ++ boolean flag1 = entity.getType().is(EntityTypeTags.DEFLECTS_ARROWS); ++ ++ if (this.isOnFire() && !flag && !flag1) { ++ // CraftBukkit start ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), 5); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ if (!combustEvent.isCancelled()) { ++ entity.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + + if (entity.hurt(damageSource, (float)ceil)) { +@@ -516,7 +555,22 @@ + @Override + public void playerTouch(Player entity) { + if (!this.level().isClientSide && (this.inGround || this.isNoPhysics()) && this.shakeTime <= 0) { +- if (this.tryPickup(entity)) { ++ // CraftBukkit start ++ ItemStack itemstack = this.getPickupItem(); ++ if (this.pickup == Pickup.ALLOWED && !itemstack.isEmpty() && entity.getInventory().canHold(itemstack) > 0) { ++ ItemEntity item = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), itemstack); ++ PlayerPickupArrowEvent event = new PlayerPickupArrowEvent((org.bukkit.entity.Player) entity.getBukkitEntity(), new org.bukkit.craftbukkit.entity.CraftItem(this.level().getCraftServer(), item), (org.bukkit.entity.AbstractArrow) this.getBukkitEntity()); ++ // event.setCancelled(!entityhuman.canPickUpLoot); TODO ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ itemstack = item.getItem(); ++ } ++ ++ if ((this.pickup == AbstractArrow.Pickup.ALLOWED && entity.getInventory().add(itemstack)) || (this.pickup == AbstractArrow.Pickup.CREATIVE_ONLY && entity.getAbilities().instabuild)) { ++ // CraftBukkit end + entity.take(this, 1); + this.discard(); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java.patch new file mode 100644 index 0000000000..0d280ee620 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java.patch @@ -0,0 +1,84 @@ +--- a/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java ++++ b/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java +@@ -16,11 +16,14 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public abstract class AbstractHurtingProjectile extends Projectile { + public double xPower; + public double yPower; + public double zPower; ++ public float bukkitYield = 1; // CraftBukkit ++ public boolean isIncendiary = true; // CraftBukkit + + protected AbstractHurtingProjectile(EntityType entityType, Level level) { + super(entityType, level); +@@ -37,11 +39,18 @@ + this(entityType, level); + this.moveTo(x, y, z, this.getYRot(), this.getXRot()); + this.reapplyPosition(); +- double squareRoot = Math.sqrt(offsetX * offsetX + offsetY * offsetY + offsetZ * offsetZ); +- if (squareRoot != 0.0) { +- this.xPower = offsetX / squareRoot * 0.1; +- this.yPower = offsetY / squareRoot * 0.1; +- this.zPower = offsetZ / squareRoot * 0.1; ++ // CraftBukkit start - Added setDirection method ++ this.setDirection(d3, z, d5); ++ } ++ ++ public void setDirection(double d3, double d4, double d5) { ++ // CraftBukkit end ++ double d6 = Math.sqrt(d3 * d3 + d4 * d4 + d5 * d5); ++ ++ if (d6 != 0.0D) { ++ this.xPower = d3 / d6 * 0.1D; ++ this.yPower = d4 / d6 * 0.1D; ++ this.zPower = d5 / d6 * 0.1D; + } + } + +@@ -81,9 +92,16 @@ + this.setSecondsOnFire(1); + } + +- HitResult hitResultOnMoveVector = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity, this.getClipType()); +- if (hitResultOnMoveVector.getType() != HitResult.Type.MISS) { +- this.onHit(hitResultOnMoveVector); ++ HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity, this.getClipType()); ++ ++ if (movingobjectposition.getType() != HitResult.EnumMovingObjectType.MISS) { ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event ++ ++ // CraftBukkit start - Fire ProjectileHitEvent ++ if (this.isRemoved()) { ++ CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); ++ } ++ // CraftBukkit end + } + + this.checkInsideBlocks(); +@@ -185,11 +199,17 @@ + Entity entity = source.getEntity(); + if (entity != null) { + if (!this.level().isClientSide) { +- Vec3 lookAngle = entity.getLookAngle(); +- this.setDeltaMovement(lookAngle); +- this.xPower = lookAngle.x * 0.1; +- this.yPower = lookAngle.y * 0.1; +- this.zPower = lookAngle.z * 0.1; ++ // CraftBukkit start ++ if (CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, false)) { ++ return false; ++ } ++ // CraftBukkit end ++ Vec3 vec3d = entity.getLookAngle(); ++ ++ this.setDeltaMovement(vec3d); ++ this.xPower = vec3d.x * 0.1D; ++ this.yPower = vec3d.y * 0.1D; ++ this.zPower = vec3d.z * 0.1D; + this.setOwner(entity); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/Arrow.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/Arrow.java.patch new file mode 100644 index 0000000000..6c7f584823 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/Arrow.java.patch @@ -0,0 +1,37 @@ +--- a/net/minecraft/world/entity/projectile/Arrow.java ++++ b/net/minecraft/world/entity/projectile/Arrow.java +@@ -177,22 +207,21 @@ + super.doPostHurtEffects(living); + Entity effectSource = this.getEffectSource(); + +- for (MobEffectInstance mobEffectInstance : this.potion.getEffects()) { +- living.addEffect( +- new MobEffectInstance( +- mobEffectInstance.getEffect(), +- Math.max(mobEffectInstance.mapDuration(i -> i / 8), 1), +- mobEffectInstance.getAmplifier(), +- mobEffectInstance.isAmbient(), +- mobEffectInstance.isVisible() +- ), +- effectSource +- ); ++ MobEffectInstance mobeffect; ++ ++ while (iterator.hasNext()) { ++ mobeffect = (MobEffectInstance) iterator.next(); ++ living.addEffect(new MobEffectInstance(mobeffect.getEffect(), Math.max(mobeffect.mapDuration((i) -> { ++ return i / 8; ++ }), 1), mobeffect.getAmplifier(), mobeffect.isAmbient(), mobeffect.isVisible()), entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ARROW); // CraftBukkit + } + + if (!this.effects.isEmpty()) { +- for (MobEffectInstance mobEffectInstance : this.effects) { +- living.addEffect(mobEffectInstance, effectSource); ++ iterator = this.effects.iterator(); ++ ++ while (iterator.hasNext()) { ++ mobeffect = (MobEffectInstance) iterator.next(); ++ living.addEffect(mobeffect, entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ARROW); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/EvokerFangs.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/EvokerFangs.java.patch new file mode 100644 index 0000000000..582caa9bf3 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/EvokerFangs.java.patch @@ -0,0 +1,19 @@ +--- a/net/minecraft/world/entity/projectile/EvokerFangs.java ++++ b/net/minecraft/world/entity/projectile/EvokerFangs.java +@@ -112,10 +125,13 @@ + } + + private void dealDamageTo(LivingEntity target) { +- LivingEntity owner = this.getOwner(); +- if (target.isAlive() && !target.isInvulnerable() && target != owner) { +- if (owner == null) { ++ LivingEntity entityliving1 = this.getOwner(); ++ ++ if (target.isAlive() && !target.isInvulnerable() && target != entityliving1) { ++ if (entityliving1 == null) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = this; // CraftBukkit + target.hurt(this.damageSources().magic(), 6.0F); ++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = null; // CraftBukkit + } else { + if (owner.isAlliedTo(target)) { + return; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/EyeOfEnder.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/EyeOfEnder.java.patch new file mode 100644 index 0000000000..b3e85b40a3 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/EyeOfEnder.java.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/world/entity/projectile/EyeOfEnder.java ++++ b/net/minecraft/world/entity/projectile/EyeOfEnder.java +@@ -34,8 +35,8 @@ + } + + public void setItem(ItemStack stack) { +- if (!stack.is(Items.ENDER_EYE) || stack.hasTag()) { +- this.getEntityData().set(DATA_ITEM_STACK, stack.copyWithCount(1)); ++ if (true || !stack.is(Items.ENDER_EYE) || stack.hasTag()) { // CraftBukkit - always allow item changing ++ this.getEntityData().set(EyeOfEnder.DATA_ITEM_STACK, stack.copyWithCount(1)); + } + } + +@@ -179,8 +175,9 @@ + + @Override + public void readAdditionalSaveData(CompoundTag compound) { +- ItemStack itemStack = ItemStack.of(compound.getCompound("Item")); +- this.setItem(itemStack); ++ ItemStack itemstack = ItemStack.of(compound.getCompound("Item")); ++ ++ if (!itemstack.isEmpty()) this.setItem(itemstack); // CraftBukkit - SPIGOT-6103 summon, see also SPIGOT-5474 + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/Fireball.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/Fireball.java.patch new file mode 100644 index 0000000000..1965d9c38c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/Fireball.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/entity/projectile/Fireball.java ++++ b/net/minecraft/world/entity/projectile/Fireball.java +@@ -58,7 +63,8 @@ + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); +- ItemStack itemStack = ItemStack.of(compound.getCompound("Item")); +- this.setItem(itemStack); ++ ItemStack itemstack = ItemStack.of(compound.getCompound("Item")); ++ ++ if (!itemstack.isEmpty()) this.setItem(itemstack); // CraftBukkit - SPIGOT-5474 probably came from bugged earlier versions + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/FireworkRocketEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/FireworkRocketEntity.java.patch new file mode 100644 index 0000000000..8927e9a414 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/FireworkRocketEntity.java.patch @@ -0,0 +1,83 @@ +--- a/net/minecraft/world/entity/projectile/FireworkRocketEntity.java ++++ b/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +@@ -24,6 +27,7 @@ + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class FireworkRocketEntity extends Projectile implements ItemSupplier { + private static final EntityDataAccessor DATA_ID_FIREWORKS_ITEM = SynchedEntityData.defineId( +@@ -147,7 +144,7 @@ + + HitResult hitResultOnMoveVector = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); + if (!this.noPhysics) { +- this.onHit(hitResultOnMoveVector); ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + this.hasImpulse = true; + } + +@@ -171,7 +159,11 @@ + } + + if (!this.level().isClientSide && this.life > this.lifetime) { +- this.explode(); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) { ++ this.explode(); ++ } ++ // CraftBukkit end + } + } + +@@ -186,7 +179,11 @@ + protected void onHitEntity(EntityHitResult result) { + super.onHitEntity(result); + if (!this.level().isClientSide) { +- this.explode(); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) { ++ this.explode(); ++ } ++ // CraftBukkit end + } + } + +@@ -195,7 +193,11 @@ + BlockPos blockPos = new BlockPos(result.getBlockPos()); + this.level().getBlockState(blockPos).entityInside(this.level(), blockPos, this); + if (!this.level().isClientSide() && this.hasExplosion()) { +- this.explode(); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) { ++ this.explode(); ++ } ++ // CraftBukkit end + } + + super.onHitBlock(result); +@@ -219,7 +223,9 @@ + + if (f > 0.0F) { + if (this.attachedToEntity != null) { +- this.attachedToEntity.hurt(this.damageSources().fireworks(this, this.getOwner()), 5.0F + (float)(list.size() * 2)); ++ CraftEventFactory.entityDamage = this; // CraftBukkit ++ this.attachedToEntity.hurt(this.damageSources().fireworks(this, this.getOwner()), 5.0F + (float) (nbttaglist.size() * 2)); ++ CraftEventFactory.entityDamage = null; // CraftBukkit + } + + double d = 5.0; +@@ -239,8 +250,11 @@ + } + + if (flag) { +- float f1 = f * (float)Math.sqrt((5.0 - (double)this.distanceTo(livingEntity)) / 5.0); +- livingEntity.hurt(this.damageSources().fireworks(this, this.getOwner()), f1); ++ float f1 = f * (float) Math.sqrt((5.0D - (double) this.distanceTo(entityliving)) / 5.0D); ++ ++ CraftEventFactory.entityDamage = this; // CraftBukkit ++ entityliving.hurt(this.damageSources().fireworks(this, this.getOwner()), f1); ++ CraftEventFactory.entityDamage = null; // CraftBukkit + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/FishingHook.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/FishingHook.java.patch new file mode 100644 index 0000000000..01e178dd07 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/FishingHook.java.patch @@ -0,0 +1,210 @@ +--- a/net/minecraft/world/entity/projectile/FishingHook.java ++++ b/net/minecraft/world/entity/projectile/FishingHook.java +@@ -45,6 +45,12 @@ + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.entity.Player; ++import org.bukkit.entity.FishHook; ++import org.bukkit.event.player.PlayerFishEvent; ++// CraftBukkit end ++ + public class FishingHook extends Projectile { + private static final Logger LOGGER = LogUtils.getLogger(); + private final RandomSource syncronizedRandom = RandomSource.create(); +@@ -65,6 +72,18 @@ + private final int luck; + private final int lureSpeed; + ++ // CraftBukkit start - Extra variables to enable modification of fishing wait time, values are minecraft defaults ++ public int minWaitTime = 100; ++ public int maxWaitTime = 600; ++ public int minLureTime = 20; ++ public int maxLureTime = 80; ++ public float minLureAngle = 0.0F; ++ public float maxLureAngle = 360.0F; ++ public boolean applyLure = true; ++ public boolean rainInfluenced = true; ++ public boolean skyInfluenced = true; ++ // CraftBukkit end ++ + private FishingHook(EntityType entityType, Level level, int luck, int lureSpeed) { + super(entityType, level); + this.noCulling = true; +@@ -252,8 +276,9 @@ + } + + private void checkCollision() { +- HitResult hitResultOnMoveVector = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); +- this.onHit(hitResultOnMoveVector); ++ HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); ++ ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + } + + @Override +@@ -283,13 +309,14 @@ + private void catchingFish(BlockPos pos) { + ServerLevel serverLevel = (ServerLevel)this.level(); + int i = 1; +- BlockPos blockPos = pos.above(); +- if (this.random.nextFloat() < 0.25F && this.level().isRainingAt(blockPos)) { +- i++; ++ BlockPos blockposition1 = pos.above(); ++ ++ if (this.rainInfluenced && this.random.nextFloat() < 0.25F && this.level().isRainingAt(blockposition1)) { // CraftBukkit ++ ++i; + } + +- if (this.random.nextFloat() < 0.5F && !this.level().canSeeSky(blockPos)) { +- i--; ++ if (this.skyInfluenced && this.random.nextFloat() < 0.5F && !this.level().canSeeSky(blockposition1)) { // CraftBukkit ++ --i; + } + + if (this.nibble > 0) { +@@ -297,7 +324,11 @@ + if (this.nibble <= 0) { + this.timeUntilLured = 0; + this.timeUntilHooked = 0; +- this.getEntityData().set(DATA_BITING, false); ++ this.getEntityData().set(FishingHook.DATA_BITING, false); ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) this.getPlayerOwner().getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.FAILED_ATTEMPT); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ // CraftBukkit end + } + } else if (this.timeUntilHooked > 0) { + this.timeUntilHooked -= i; +@@ -314,6 +361,16 @@ + if (this.random.nextFloat() < 0.15F) { + serverLevel.sendParticles(ParticleTypes.BUBBLE, d, d1 - 0.1F, d2, 1, (double)sin, 0.1, (double)cos, 0.0); + } ++ } else { ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) this.getPlayerOwner().getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.BITE); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ if (playerFishEvent.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ this.playSound(SoundEvents.FISHING_BOBBER_SPLASH, 0.25F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); ++ double d3 = this.getY() + 0.5D; + + float f1 = sin * 0.04F; + float f2 = cos * 0.04F; +@@ -371,9 +400,17 @@ + } + } + +- if (this.timeUntilLured <= 0) { +- this.fishAngle = Mth.nextFloat(this.random, 0.0F, 360.0F); +- this.timeUntilHooked = Mth.nextInt(this.random, 20, 80); ++ if (this.timeUntilLured <= 0) { ++ // CraftBukkit start - logic to modify fishing wait time, lure time, and lure angle ++ this.fishAngle = Mth.nextFloat(this.random, this.minLureAngle, this.maxLureAngle); ++ this.timeUntilHooked = Mth.nextInt(this.random, this.minLureTime, this.maxLureTime); ++ // CraftBukkit end ++ } ++ } else { ++ // CraftBukkit start - logic to modify fishing wait time ++ this.timeUntilLured = Mth.nextInt(this.random, this.minWaitTime, this.maxWaitTime); ++ this.timeUntilLured -= (this.applyLure) ? this.lureSpeed * 20 * 5 : 0; ++ // CraftBukkit end + } + } else { + this.timeUntilLured = Mth.nextInt(this.random, 100, 600); +@@ -442,6 +477,14 @@ + if (!this.level().isClientSide && playerOwner != null && !this.shouldStopFishing(playerOwner)) { + int i = 0; + if (this.hookedIn != null) { ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), this.hookedIn.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_ENTITY); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ return 0; ++ } ++ // CraftBukkit end + this.pullEntity(this.hookedIn); + CriteriaTriggers.FISHING_ROD_HOOKED.trigger((ServerPlayer)playerOwner, stack, this, Collections.emptyList()); + this.level().broadcastEntityEvent(this, (byte)31); +@@ -457,31 +494,61 @@ + List randomItems = lootTable.getRandomItems(lootParams); + CriteriaTriggers.FISHING_ROD_HOOKED.trigger((ServerPlayer)playerOwner, stack, this, randomItems); + +- for (ItemStack itemStack : randomItems) { +- ItemEntity itemEntity = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), itemStack); +- double d = playerOwner.getX() - this.getX(); +- double d1 = playerOwner.getY() - this.getY(); +- double d2 = playerOwner.getZ() - this.getZ(); +- double d3 = 0.1; +- itemEntity.setDeltaMovement(d * 0.1, d1 * 0.1 + Math.sqrt(Math.sqrt(d * d + d1 * d1 + d2 * d2)) * 0.08, d2 * 0.1); +- this.level().addFreshEntity(itemEntity); +- playerOwner.level() +- .addFreshEntity( +- new ExperienceOrb( +- playerOwner.level(), playerOwner.getX(), playerOwner.getY() + 0.5, playerOwner.getZ() + 0.5, this.random.nextInt(6) + 1 +- ) +- ); +- if (itemStack.is(ItemTags.FISHES)) { +- playerOwner.awardStat(Stats.FISH_CAUGHT, 1); ++ CriteriaTriggers.FISHING_ROD_HOOKED.trigger((ServerPlayer) entityhuman, stack, this, list); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ ItemStack itemstack1 = (ItemStack) iterator.next(); ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), itemstack1); ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); ++ playerFishEvent.setExpToDrop(this.random.nextInt(6) + 1); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ return 0; + } ++ // CraftBukkit end ++ double d0 = entityhuman.getX() - this.getX(); ++ double d1 = entityhuman.getY() - this.getY(); ++ double d2 = entityhuman.getZ() - this.getZ(); ++ double d3 = 0.1D; ++ ++ entityitem.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); ++ this.level().addFreshEntity(entityitem); ++ // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() ++ if (playerFishEvent.getExpToDrop() > 0) { ++ entityhuman.level().addFreshEntity(new ExperienceOrb(entityhuman.level(), entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop())); ++ } ++ // CraftBukkit end ++ if (itemstack1.is(ItemTags.FISHES)) { ++ entityhuman.awardStat(Stats.FISH_CAUGHT, 1); ++ } + } + + i = 1; + } + + if (this.onGround()) { ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.IN_GROUND); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ return 0; ++ } ++ // CraftBukkit end + i = 2; + } ++ // CraftBukkit start ++ if (i == 0) { ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.REEL_IN); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ if (playerFishEvent.isCancelled()) { ++ return 0; ++ } ++ } ++ // CraftBukkit end + + this.discard(); + return i; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/LargeFireball.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/LargeFireball.java.patch new file mode 100644 index 0000000000..dce2bb426e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/LargeFireball.java.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/entity/projectile/LargeFireball.java ++++ b/net/minecraft/world/entity/projectile/LargeFireball.java +@@ -8,25 +8,37 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++import org.bukkit.event.entity.ExplosionPrimeEvent; // CraftBukkit + + public class LargeFireball extends Fireball { + private int explosionPower = 1; + + public LargeFireball(EntityType entityType, Level level) { + super(entityType, level); ++ isIncendiary = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // CraftBukkit + } + +- public LargeFireball(Level level, LivingEntity shooter, double offsetX, double offsetY, double offsetZ, int explosionPower) { +- super(EntityType.FIREBALL, shooter, offsetX, offsetY, offsetZ, level); +- this.explosionPower = explosionPower; ++ public LargeFireball(Level level, LivingEntity shooter, double offsetX, double d1, double offsetY, int i) { ++ super(EntityType.FIREBALL, shooter, offsetX, d1, offsetY, level); ++ this.explosionPower = i; ++ isIncendiary = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // CraftBukkit + } + + @Override + protected void onHit(HitResult result) { + super.onHit(result); + if (!this.level().isClientSide) { +- boolean _boolean = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); +- this.level().explode(this, this.getX(), this.getY(), this.getZ(), (float)this.explosionPower, _boolean, Level.ExplosionInteraction.MOB); ++ boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); ++ ++ // CraftBukkit start - fire ExplosionPrimeEvent ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent((org.bukkit.entity.Explosive) this.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ // give 'this' instead of (Entity) null so we know what causes the damage ++ this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.MOB); ++ } ++ // CraftBukkit end + this.discard(); + } + } +@@ -54,7 +70,8 @@ + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); + if (compound.contains("ExplosionPower", 99)) { +- this.explosionPower = compound.getByte("ExplosionPower"); ++ // CraftBukkit - set bukkitYield when setting explosionpower ++ bukkitYield = this.explosionPower = compound.getByte("ExplosionPower"); + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/LlamaSpit.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/LlamaSpit.java.patch new file mode 100644 index 0000000000..5886254a3a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/LlamaSpit.java.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/world/entity/projectile/LlamaSpit.java ++++ b/net/minecraft/world/entity/projectile/LlamaSpit.java +@@ -31,12 +29,14 @@ + @Override + public void tick() { + super.tick(); +- Vec3 deltaMovement = this.getDeltaMovement(); +- HitResult hitResultOnMoveVector = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); +- this.onHit(hitResultOnMoveVector); +- double d = this.getX() + deltaMovement.x; +- double d1 = this.getY() + deltaMovement.y; +- double d2 = this.getZ() + deltaMovement.z; ++ Vec3 vec3d = this.getDeltaMovement(); ++ HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); ++ ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event ++ double d0 = this.getX() + vec3d.x; ++ double d1 = this.getY() + vec3d.y; ++ double d2 = this.getZ() + vec3d.z; ++ + this.updateRotation(); + float f = 0.99F; + float f1 = 0.06F; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/Projectile.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/Projectile.java.patch new file mode 100644 index 0000000000..30c39d21e6 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/Projectile.java.patch @@ -0,0 +1,73 @@ +--- a/net/minecraft/world/entity/projectile/Projectile.java ++++ b/net/minecraft/world/entity/projectile/Projectile.java +@@ -23,6 +24,9 @@ + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.projectiles.ProjectileSource; ++// CraftBukkit end + + public abstract class Projectile extends Entity implements TraceableEntity { + @Nullable +@@ -32,6 +37,10 @@ + private boolean leftOwner; + private boolean hasBeenShot; + ++ // CraftBukkit start ++ private boolean hitCancelled = false; ++ // CraftBukkit end ++ + Projectile(EntityType entityType, Level level) { + super(entityType, level); + } +@@ -41,6 +50,8 @@ + this.ownerUUID = owner.getUUID(); + this.cachedOwner = owner; + } ++ this.projectileSource = (owner != null && owner.getBukkitEntity() instanceof ProjectileSource) ? (ProjectileSource) owner.getBukkitEntity() : null; // CraftBukkit ++ + } + + @Nullable +@@ -152,25 +175,28 @@ + this.setDeltaMovement(this.getDeltaMovement().add(deltaMovement.x, shooter.onGround() ? 0.0 : deltaMovement.y, deltaMovement.z)); + } + +- protected void onHit(HitResult result) { +- HitResult.Type type = result.getType(); +- if (type == HitResult.Type.ENTITY) { +- this.onHitEntity((EntityHitResult)result); +- this.level().gameEvent(GameEvent.PROJECTILE_LAND, result.getLocation(), GameEvent.Context.of(this, null)); +- } else if (type == HitResult.Type.BLOCK) { +- BlockHitResult blockHitResult = (BlockHitResult)result; +- this.onHitBlock(blockHitResult); +- BlockPos blockPos = blockHitResult.getBlockPos(); +- this.level().gameEvent(GameEvent.PROJECTILE_LAND, blockPos, GameEvent.Context.of(this, this.level().getBlockState(blockPos))); ++ // CraftBukkit start - call projectile hit event ++ protected void preOnHit(HitResult movingobjectposition) { ++ org.bukkit.event.entity.ProjectileHitEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); ++ this.hitCancelled = event != null && event.isCancelled(); ++ if (movingobjectposition.getType() == HitResult.EnumMovingObjectType.BLOCK || !this.hitCancelled) { ++ this.onHit(movingobjectposition); + } + } ++ // CraftBukkit end + + protected void onHitEntity(EntityHitResult result) { + } + + protected void onHitBlock(BlockHitResult result) { +- BlockState blockState = this.level().getBlockState(result.getBlockPos()); +- blockState.onProjectileHit(this.level(), blockState, result, this); ++ // CraftBukkit start - cancellable hit event ++ if (hitCancelled) { ++ return; ++ } ++ // CraftBukkit end ++ IBlockData iblockdata = this.level().getBlockState(result.getBlockPos()); ++ ++ iblockdata.onProjectileHit(this.level(), iblockdata, result, this); + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ShulkerBullet.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ShulkerBullet.java.patch new file mode 100644 index 0000000000..5c3c112607 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ShulkerBullet.java.patch @@ -0,0 +1,65 @@ +--- a/net/minecraft/world/entity/projectile/ShulkerBullet.java ++++ b/net/minecraft/world/entity/projectile/ShulkerBullet.java +@@ -58,8 +60,21 @@ + this.finalTarget = finalTarget; + this.currentMoveDirection = Direction.UP; + this.selectNextMoveDirection(axis); ++ projectileSource = (org.bukkit.entity.LivingEntity) shooter.getBukkitEntity(); // CraftBukkit + } + ++ // CraftBukkit start ++ public Entity getTarget() { ++ return this.finalTarget; ++ } ++ ++ public void setTarget(Entity e) { ++ this.finalTarget = e; ++ this.currentMoveDirection = Direction.UP; ++ this.selectNextMoveDirection(Direction.Axis.X); ++ } ++ // CraftBukkit end ++ + @Override + public SoundSource getSoundSource() { + return SoundSource.HOSTILE; +@@ -219,9 +235,10 @@ + ); + } + +- HitResult hitResultOnMoveVector = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); +- if (hitResultOnMoveVector.getType() != HitResult.Type.MISS) { +- this.onHit(hitResultOnMoveVector); ++ HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); ++ ++ if (movingobjectposition.getType() != HitResult.EnumMovingObjectType.MISS) { ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + } + } + +@@ -287,9 +303,11 @@ + LivingEntity livingEntity = owner instanceof LivingEntity ? (LivingEntity)owner : null; + boolean flag = entity.hurt(this.damageSources().mobProjectile(this, livingEntity), 4.0F); + if (flag) { +- this.doEnchantDamageEffects(livingEntity, entity); +- if (entity instanceof LivingEntity livingEntity1) { +- livingEntity1.addEffect(new MobEffectInstance(MobEffects.LEVITATION, 200), MoreObjects.firstNonNull(owner, this)); ++ this.doEnchantDamageEffects(entityliving, entity); ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving1 = (LivingEntity) entity; ++ ++ entityliving1.addEffect(new MobEffectInstance(MobEffects.LEVITATION, 200), (Entity) MoreObjects.firstNonNull(entity1, this), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + } +@@ -319,6 +338,11 @@ + + @Override + public boolean hurt(DamageSource source, float amount) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, false)) { ++ return false; ++ } ++ // CraftBukkit end + if (!this.level().isClientSide) { + this.playSound(SoundEvents.SHULKER_BULLET_HURT, 1.0F, 1.0F); + ((ServerLevel)this.level()).sendParticles(ParticleTypes.CRIT, this.getX(), this.getY(), this.getZ(), 15, 0.2, 0.2, 0.2, 0.0); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/SmallFireball.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/SmallFireball.java.patch new file mode 100644 index 0000000000..ad12c17e8a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/SmallFireball.java.patch @@ -0,0 +1,75 @@ +--- a/net/minecraft/world/entity/projectile/SmallFireball.java ++++ b/net/minecraft/world/entity/projectile/SmallFireball.java +@@ -12,14 +12,20 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; // CraftBukkit + + public class SmallFireball extends Fireball { + public SmallFireball(EntityType entityType, Level level) { + super(entityType, level); + } + +- public SmallFireball(Level level, LivingEntity shooter, double offsetX, double offsetY, double offsetZ) { +- super(EntityType.SMALL_FIREBALL, shooter, offsetX, offsetY, offsetZ, level); ++ public SmallFireball(Level level, LivingEntity shooter, double offsetX, double d1, double offsetY) { ++ super(EntityType.SMALL_FIREBALL, shooter, offsetX, d1, offsetY, level); ++ // CraftBukkit start ++ if (this.getOwner() != null && this.getOwner() instanceof Mob) { ++ isIncendiary = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); ++ } ++ // CraftBukkit end + } + + public SmallFireball(Level level, double x, double y, double z, double offsetX, double offsetY, double offsetZ) { +@@ -31,14 +38,23 @@ + super.onHitEntity(result); + if (!this.level().isClientSide) { + Entity entity = result.getEntity(); +- Entity owner = this.getOwner(); +- int remainingFireTicks = entity.getRemainingFireTicks(); +- entity.setSecondsOnFire(5); +- if (!entity.hurt(this.damageSources().fireball(this, owner), 5.0F)) { +- entity.setRemainingFireTicks(remainingFireTicks); +- } else if (owner instanceof LivingEntity) { +- this.doEnchantDamageEffects((LivingEntity)owner, entity); ++ Entity entity1 = this.getOwner(); ++ int i = entity.getRemainingFireTicks(); ++ ++ // CraftBukkit start - Entity damage by entity event + combust event ++ EntityCombustByEntityEvent event = new EntityCombustByEntityEvent((org.bukkit.entity.Projectile) this.getBukkitEntity(), entity.getBukkitEntity(), 5); ++ entity.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ entity.setSecondsOnFire(event.getDuration(), false); + } ++ // CraftBukkit end ++ if (!entity.hurt(this.damageSources().fireball(this, entity1), 5.0F)) { ++ entity.setRemainingFireTicks(i); ++ } else if (entity1 instanceof LivingEntity) { ++ this.doEnchantDamageEffects((LivingEntity) entity1, entity); ++ } ++ + } + } + +@@ -46,11 +62,13 @@ + protected void onHitBlock(BlockHitResult result) { + super.onHitBlock(result); + if (!this.level().isClientSide) { +- Entity owner = this.getOwner(); +- if (!(owner instanceof Mob) || this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- BlockPos blockPos = result.getBlockPos().relative(result.getDirection()); +- if (this.level().isEmptyBlock(blockPos)) { +- this.level().setBlockAndUpdate(blockPos, BaseFireBlock.getState(this.level(), blockPos)); ++ Entity entity = this.getOwner(); ++ ++ if (isIncendiary) { // CraftBukkit ++ BlockPos blockposition = result.getBlockPos().relative(result.getDirection()); ++ ++ if (this.level().isEmptyBlock(blockposition) && !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition, this).isCancelled()) { // CraftBukkit ++ this.level().setBlockAndUpdate(blockposition, BaseFireBlock.getState(this.level(), blockposition)); + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/SpectralArrow.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/SpectralArrow.java.patch new file mode 100644 index 0000000000..ac1ab70833 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/SpectralArrow.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/entity/projectile/SpectralArrow.java ++++ b/net/minecraft/world/entity/projectile/SpectralArrow.java +@@ -37,8 +39,9 @@ + @Override + protected void doPostHurtEffects(LivingEntity living) { + super.doPostHurtEffects(living); +- MobEffectInstance mobEffectInstance = new MobEffectInstance(MobEffects.GLOWING, this.duration, 0); +- living.addEffect(mobEffectInstance, this.getEffectSource()); ++ MobEffectInstance mobeffect = new MobEffectInstance(MobEffects.GLOWING, this.duration, 0); ++ ++ living.addEffect(mobeffect, this.getEffectSource(), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ARROW); // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrowableItemProjectile.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrowableItemProjectile.java.patch new file mode 100644 index 0000000000..ac288da8e9 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrowableItemProjectile.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/entity/projectile/ThrowableItemProjectile.java ++++ b/net/minecraft/world/entity/projectile/ThrowableItemProjectile.java +@@ -35,9 +35,11 @@ + + protected abstract Item getDefaultItem(); + +- protected ItemStack getItemRaw() { +- return this.getEntityData().get(DATA_ITEM_STACK); ++ // CraftBukkit start ++ public Item getDefaultItemPublic() { ++ return getDefaultItem(); + } ++ // CraftBukkit end + + @Override + public ItemStack getItem() { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrowableProjectile.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrowableProjectile.java.patch new file mode 100644 index 0000000000..21a6b48b1b --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrowableProjectile.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/entity/projectile/ThrowableProjectile.java ++++ b/net/minecraft/world/entity/projectile/ThrowableProjectile.java +@@ -60,8 +65,8 @@ + } + } + +- if (hitResultOnMoveVector.getType() != HitResult.Type.MISS && !flag) { +- this.onHit(hitResultOnMoveVector); ++ if (movingobjectposition.getType() != HitResult.EnumMovingObjectType.MISS && !flag) { ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + } + + this.checkInsideBlocks(); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrownEgg.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrownEgg.java.patch new file mode 100644 index 0000000000..00e2f8f468 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrownEgg.java.patch @@ -0,0 +1,77 @@ +--- a/net/minecraft/world/entity/projectile/ThrownEgg.java ++++ b/net/minecraft/world/entity/projectile/ThrownEgg.java +@@ -10,6 +5,16 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++import net.minecraft.core.particles.ItemParticleOption; ++import net.minecraft.core.particles.ParticleTypes; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.LivingEntity; ++import org.bukkit.entity.Ageable; ++import org.bukkit.entity.EntityType; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerEggThrowEvent; ++// CraftBukkit end + + public class ThrownEgg extends ThrowableItemProjectile { + public ThrownEgg(EntityType entityType, Level level) { +@@ -54,20 +52,49 @@ + protected void onHit(HitResult result) { + super.onHit(result); + if (!this.level().isClientSide) { +- if (this.random.nextInt(8) == 0) { +- int i = 1; ++ // CraftBukkit start ++ boolean hatching = this.random.nextInt(8) == 0; ++ if (true) { ++ // CraftBukkit end ++ byte b0 = 1; ++ + if (this.random.nextInt(32) == 0) { + i = 4; + } + +- for (int i1 = 0; i1 < i; i1++) { +- Chicken chicken = EntityType.CHICKEN.create(this.level()); +- if (chicken != null) { +- chicken.setAge(-24000); +- chicken.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); +- this.level().addFreshEntity(chicken); ++ // CraftBukkit start ++ EntityType hatchingType = EntityType.CHICKEN; ++ ++ Entity shooter = this.getOwner(); ++ if (!hatching) { ++ b0 = 0; ++ } ++ if (shooter instanceof ServerPlayer) { ++ PlayerEggThrowEvent event = new PlayerEggThrowEvent((Player) shooter.getBukkitEntity(), (org.bukkit.entity.Egg) this.getBukkitEntity(), hatching, b0, hatchingType); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ b0 = event.getNumHatches(); ++ hatching = event.isHatching(); ++ hatchingType = event.getHatchingType(); ++ // If hatching is set to false, ensure child count is 0 ++ if (!hatching) { ++ b0 = 0; + } + } ++ // CraftBukkit end ++ ++ for (int i = 0; i < b0; ++i) { ++ Entity entitychicken = this.level().getWorld().makeEntity(new org.bukkit.Location(this.level().getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F), hatchingType.getEntityClass()); // CraftBukkit ++ ++ if (entitychicken != null) { ++ // CraftBukkit start ++ if (entitychicken.getBukkitEntity() instanceof Ageable) { ++ ((Ageable) entitychicken.getBukkitEntity()).setBaby(); ++ } ++ this.level().addFreshEntity(entitychicken, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); ++ // CraftBukkit end ++ } ++ } + } + + this.level().broadcastEntityEvent(this, (byte)3); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrownEnderpearl.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrownEnderpearl.java.patch new file mode 100644 index 0000000000..47973145b3 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrownEnderpearl.java.patch @@ -0,0 +1,85 @@ +--- a/net/minecraft/world/entity/projectile/ThrownEnderpearl.java ++++ b/net/minecraft/world/entity/projectile/ThrownEnderpearl.java +@@ -16,6 +17,12 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++// CraftBukkit end + + public class ThrownEnderpearl extends ThrowableItemProjectile { + public ThrownEnderpearl(EntityType entityType, Level level) { +@@ -55,14 +54,29 @@ + } + + if (!this.level().isClientSide && !this.isRemoved()) { +- Entity owner = this.getOwner(); +- if (owner instanceof ServerPlayer serverPlayer) { +- if (serverPlayer.connection.isAcceptingMessages() && serverPlayer.level() == this.level() && !serverPlayer.isSleeping()) { +- if (this.random.nextFloat() < 0.05F && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { +- Endermite endermite = EntityType.ENDERMITE.create(this.level()); +- if (endermite != null) { +- endermite.moveTo(owner.getX(), owner.getY(), owner.getZ(), owner.getYRot(), owner.getXRot()); +- this.level().addFreshEntity(endermite); ++ Entity entity = this.getOwner(); ++ ++ if (entity instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entity; ++ ++ if (entityplayer.connection.isAcceptingMessages() && entityplayer.level() == this.level() && !entityplayer.isSleeping()) { ++ // CraftBukkit start - Fire PlayerTeleportEvent ++ org.bukkit.craftbukkit.entity.CraftPlayer player = entityplayer.getBukkitEntity(); ++ org.bukkit.Location location = getBukkitEntity().getLocation(); ++ location.setPitch(player.getLocation().getPitch()); ++ location.setYaw(player.getLocation().getYaw()); ++ ++ PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.ENDER_PEARL); ++ Bukkit.getPluginManager().callEvent(teleEvent); ++ ++ if (!teleEvent.isCancelled() && entityplayer.connection.isAcceptingMessages()) { ++ if (this.random.nextFloat() < 0.05F && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { ++ Endermite entityendermite = (Endermite) EntityType.ENDERMITE.create(this.level()); ++ ++ if (entityendermite != null) { ++ entityendermite.moveTo(entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot()); ++ this.level().addFreshEntity(entityendermite, CreatureSpawnEvent.SpawnReason.ENDER_PEARL); ++ } + } + } + +@@ -72,9 +83,14 @@ + owner.teleportTo(this.getX(), this.getY(), this.getZ()); + } + +- owner.resetFallDistance(); +- owner.hurt(this.damageSources().fall(), 5.0F); +- this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_TELEPORT, SoundSource.PLAYERS); ++ entityplayer.connection.teleport(teleEvent.getTo()); ++ entity.resetFallDistance(); ++ CraftEventFactory.entityDamage = this; ++ entity.hurt(this.damageSources().fall(), 5.0F); ++ CraftEventFactory.entityDamage = null; ++ } ++ // CraftBukkit end ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_TELEPORT, SoundSource.PLAYERS); + } + } else if (owner != null) { + owner.teleportTo(this.getX(), this.getY(), this.getZ()); +@@ -98,9 +117,10 @@ + @Nullable + @Override + public Entity changeDimension(ServerLevel server) { +- Entity owner = this.getOwner(); +- if (owner != null && owner.level().dimension() != server.dimension()) { +- this.setOwner(null); ++ Entity entity = this.getOwner(); ++ ++ if (entity != null && server != null && entity.level().dimension() != server.dimension()) { // CraftBukkit - SPIGOT-6113 ++ this.setOwner((Entity) null); + } + + return super.changeDimension(server); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java.patch new file mode 100644 index 0000000000..d3ab8c972a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java ++++ b/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java +@@ -38,9 +39,19 @@ + protected void onHit(HitResult result) { + super.onHit(result); + if (this.level() instanceof ServerLevel) { +- this.level().levelEvent(2002, this.blockPosition(), PotionUtils.getColor(Potions.WATER)); ++ // CraftBukkit - moved to after event ++ // this.level().levelEvent(2002, this.blockPosition(), PotionUtil.getColor(Potions.WATER)); + int i = 3 + this.level().random.nextInt(5) + this.level().random.nextInt(5); +- ExperienceOrb.award((ServerLevel)this.level(), this.position(), i); ++ ++ // CraftBukkit start ++ org.bukkit.event.entity.ExpBottleEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExpBottleEvent(this, result, i); ++ i = event.getExperience(); ++ if (event.getShowEffect()) { ++ this.level().levelEvent(2002, this.blockPosition(), PotionUtils.getColor(Potions.WATER)); ++ } ++ // CraftBukkit end ++ ++ ExperienceOrb.award((ServerLevel) this.level(), this.position(), i); + this.discard(); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrownPotion.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrownPotion.java.patch new file mode 100644 index 0000000000..430cfe9c4f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrownPotion.java.patch @@ -0,0 +1,185 @@ +--- a/net/minecraft/world/entity/projectile/ThrownPotion.java ++++ b/net/minecraft/world/entity/projectile/ThrownPotion.java +@@ -28,6 +29,16 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++// CraftBukkit start ++import java.util.HashMap; ++import java.util.Map; ++import net.minecraft.world.effect.MobEffects; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.CampfireBlock; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.entity.LivingEntity; ++// CraftBukkit end + + public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplier { + public static final double SPLASH_RANGE = 4.0; +@@ -88,11 +108,11 @@ + boolean flag = potion == Potions.WATER && mobEffects.isEmpty(); + if (flag) { + this.applyWater(); +- } else if (!mobEffects.isEmpty()) { ++ } else if (true || !list.isEmpty()) { // CraftBukkit - Call event even if no effects to apply + if (this.isLingering()) { +- this.makeAreaOfEffectCloud(item, potion); ++ this.makeAreaOfEffectCloud(itemstack, potionregistry, result); // CraftBukkit - Pass MovingObjectPosition + } else { +- this.applySplash(mobEffects, result.getType() == HitResult.Type.ENTITY ? ((EntityHitResult)result).getEntity() : null); ++ this.applySplash(list, result.getType() == HitResult.EnumMovingObjectType.ENTITY ? ((EntityHitResult) result).getEntity() : null, result); // CraftBukkit - Pass MovingObjectPosition + } + } + +@@ -123,11 +154,10 @@ + } + } + +- private void applySplash(List effectInstances, @Nullable Entity target) { +- AABB aABB = this.getBoundingBox().inflate(4.0, 2.0, 4.0); +- List entitiesOfClass = this.level().getEntitiesOfClass(LivingEntity.class, aABB); +- if (!entitiesOfClass.isEmpty()) { +- Entity effectSource = this.getEffectSource(); ++ private void applySplash(List list, @Nullable Entity entity, HitResult position) { // CraftBukkit - Pass MovingObjectPosition ++ AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D); ++ List list1 = this.level().getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb); ++ Map affected = new HashMap(); // CraftBukkit + + for (LivingEntity livingEntity : entitiesOfClass) { + if (livingEntity.isAffectedByPotions()) { +@@ -140,31 +178,62 @@ + d1 = 1.0 - Math.sqrt(d) / 4.0; + } + +- for (MobEffectInstance mobEffectInstance : effectInstances) { +- MobEffect effect = mobEffectInstance.getEffect(); +- if (effect.isInstantenous()) { +- effect.applyInstantenousEffect(this, this.getOwner(), livingEntity, mobEffectInstance.getAmplifier(), d1); +- } else { +- int i = mobEffectInstance.mapDuration(i1 -> (int)(d1 * (double)i1 + 0.5)); +- MobEffectInstance mobEffectInstance1 = new MobEffectInstance( +- effect, i, mobEffectInstance.getAmplifier(), mobEffectInstance.isAmbient(), mobEffectInstance.isVisible() +- ); +- if (!mobEffectInstance1.endsWithin(20)) { +- livingEntity.addEffect(mobEffectInstance1, effectSource); +- } +- } ++ // CraftBukkit start ++ affected.put((LivingEntity) entityliving.getBukkitEntity(), d1); ++ } ++ } ++ } ++ } ++ ++ org.bukkit.event.entity.PotionSplashEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPotionSplashEvent(this, position, affected); ++ if (!event.isCancelled() && list != null && !list.isEmpty()) { // do not process effects if there are no effects to process ++ Entity entity1 = this.getEffectSource(); ++ for (LivingEntity victim : event.getAffectedEntities()) { ++ if (!(victim instanceof CraftLivingEntity)) { ++ continue; ++ } ++ ++ net.minecraft.world.entity.LivingEntity entityliving = ((CraftLivingEntity) victim).getHandle(); ++ double d1 = event.getIntensity(victim); ++ // CraftBukkit end ++ ++ Iterator iterator1 = list.iterator(); ++ ++ while (iterator1.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator1.next(); ++ MobEffect mobeffectlist = mobeffect.getEffect(); ++ // CraftBukkit start - Abide by PVP settings - for players only! ++ if (!this.level().pvpMode && this.getOwner() instanceof ServerPlayer && entityliving instanceof ServerPlayer && entityliving != this.getOwner()) { ++ if (mobeffectlist == MobEffects.MOVEMENT_SLOWDOWN || mobeffectlist == MobEffects.DIG_SLOWDOWN || mobeffectlist == MobEffects.HARM || mobeffectlist == MobEffects.BLINDNESS ++ || mobeffectlist == MobEffects.HUNGER || mobeffectlist == MobEffects.WEAKNESS || mobeffectlist == MobEffects.POISON) { ++ continue; + } + } ++ // CraftBukkit end ++ ++ if (mobeffectlist.isInstantenous()) { ++ mobeffectlist.applyInstantenousEffect(this, this.getOwner(), entityliving, mobeffect.getAmplifier(), d1); ++ } else { ++ int i = mobeffect.mapDuration((j) -> { ++ return (int) (d1 * (double) j + 0.5D); ++ }); ++ MobEffectInstance mobeffect1 = new MobEffectInstance(mobeffectlist, i, mobeffect.getAmplifier(), mobeffect.isAmbient(), mobeffect.isVisible()); ++ ++ if (!mobeffect1.endsWithin(20)) { ++ entityliving.addEffect(mobeffect1, entity1, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_SPLASH); // CraftBukkit ++ } ++ } + } + } + } + } + +- private void makeAreaOfEffectCloud(ItemStack stack, Potion potion) { +- AreaEffectCloud areaEffectCloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); +- Entity owner = this.getOwner(); +- if (owner instanceof LivingEntity) { +- areaEffectCloud.setOwner((LivingEntity)owner); ++ private void makeAreaOfEffectCloud(ItemStack itemstack, Potion potionregistry, HitResult position) { // CraftBukkit - Pass MovingObjectPosition ++ AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); ++ Entity entity = this.getOwner(); ++ ++ if (entity instanceof net.minecraft.world.entity.LivingEntity) { ++ entityareaeffectcloud.setOwner((net.minecraft.world.entity.LivingEntity) entity); + } + + areaEffectCloud.setRadius(3.0F); +@@ -182,7 +256,14 @@ + areaEffectCloud.setFixedColor(tag.getInt("CustomPotionColor")); + } + +- this.level().addFreshEntity(areaEffectCloud); ++ // CraftBukkit start ++ org.bukkit.event.entity.LingeringPotionSplashEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callLingeringPotionSplashEvent(this, position, entityareaeffectcloud); ++ if (!(event.isCancelled() || entityareaeffectcloud.isRemoved())) { ++ this.level().addFreshEntity(entityareaeffectcloud); ++ } else { ++ entityareaeffectcloud.discard(); ++ } ++ // CraftBukkit end + } + + private boolean isLingering() { +@@ -190,15 +271,28 @@ + } + + private void dowseFire(BlockPos pos) { +- BlockState blockState = this.level().getBlockState(pos); +- if (blockState.is(BlockTags.FIRE)) { +- this.level().destroyBlock(pos, false, this); +- } else if (AbstractCandleBlock.isLit(blockState)) { +- AbstractCandleBlock.extinguish(null, blockState, this.level(), pos); +- } else if (CampfireBlock.isLitCampfire(blockState)) { +- this.level().levelEvent(null, 1009, pos, 0); +- CampfireBlock.dowse(this.getOwner(), this.level(), pos, blockState); +- this.level().setBlockAndUpdate(pos, blockState.setValue(CampfireBlock.LIT, Boolean.valueOf(false))); ++ IBlockData iblockdata = this.level().getBlockState(pos); ++ ++ if (iblockdata.is(BlockTags.FIRE)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityChangeBlockEvent(this, pos, Blocks.AIR.defaultBlockState())) { ++ this.level().destroyBlock(pos, false, this); ++ } ++ // CraftBukkit end ++ } else if (AbstractCandleBlock.isLit(iblockdata)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityChangeBlockEvent(this, pos, iblockdata.setValue(AbstractCandleBlock.LIT, false))) { ++ AbstractCandleBlock.extinguish((Player) null, iblockdata, this.level(), pos); ++ } ++ // CraftBukkit end ++ } else if (CampfireBlock.isLitCampfire(iblockdata)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityChangeBlockEvent(this, pos, iblockdata.setValue(CampfireBlock.LIT, false))) { ++ this.level().levelEvent((Player) null, 1009, pos, 0); ++ CampfireBlock.dowse(this.getOwner(), this.level(), pos, iblockdata); ++ this.level().setBlockAndUpdate(pos, (IBlockData) iblockdata.setValue(CampfireBlock.LIT, false)); ++ } ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrownTrident.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrownTrident.java.patch new file mode 100644 index 0000000000..6fc1b65499 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/ThrownTrident.java.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/world/entity/projectile/ThrownTrident.java ++++ b/net/minecraft/world/entity/projectile/ThrownTrident.java +@@ -132,14 +145,16 @@ + this.setDeltaMovement(this.getDeltaMovement().multiply(-0.01, -0.1, -0.01)); + float f1 = 1.0F; + if (this.level() instanceof ServerLevel && this.level().isThundering() && this.isChanneling()) { +- BlockPos blockPos = entity.blockPosition(); +- if (this.level().canSeeSky(blockPos)) { +- LightningBolt lightningBolt = EntityType.LIGHTNING_BOLT.create(this.level()); +- if (lightningBolt != null) { +- lightningBolt.moveTo(Vec3.atBottomCenterOf(blockPos)); +- lightningBolt.setCause(owner instanceof ServerPlayer ? (ServerPlayer)owner : null); +- this.level().addFreshEntity(lightningBolt); +- soundEvent = SoundEvents.TRIDENT_THUNDER; ++ BlockPos blockposition = entity.blockPosition(); ++ ++ if (this.level().canSeeSky(blockposition)) { ++ LightningBolt entitylightning = (LightningBolt) EntityType.LIGHTNING_BOLT.create(this.level()); ++ ++ if (entitylightning != null) { ++ entitylightning.moveTo(Vec3.atBottomCenterOf(blockposition)); ++ entitylightning.setCause(entity1 instanceof ServerPlayer ? (ServerPlayer) entity1 : null); ++ ((ServerLevel) this.level()).strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.TRIDENT); // CraftBukkit ++ soundeffect = SoundEvents.TRIDENT_THUNDER; + f1 = 5.0F; + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/WindCharge.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/WindCharge.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/WindCharge.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/WitherSkull.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/WitherSkull.java.patch new file mode 100644 index 0000000000..1037b4002e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/projectile/WitherSkull.java.patch @@ -0,0 +1,49 @@ +--- a/net/minecraft/world/entity/projectile/WitherSkull.java ++++ b/net/minecraft/world/entity/projectile/WitherSkull.java +@@ -20,6 +20,9 @@ + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++// CraftBukkit start ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end + + public class WitherSkull extends AbstractHurtingProjectile { + private static final EntityDataAccessor DATA_DANGEROUS = SynchedEntityData.defineId(WitherSkull.class, EntityDataSerializers.BOOLEAN); +@@ -61,7 +67,7 @@ + if (entity.isAlive()) { + this.doEnchantDamageEffects(livingEntity, entity); + } else { +- livingEntity.heal(5.0F); ++ entityliving.heal(5.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.WITHER); // CraftBukkit + } + } + } else { +@@ -76,8 +84,8 @@ + i = 40; + } + +- if (i > 0) { +- livingEntityx.addEffect(new MobEffectInstance(MobEffects.WITHER, 20 * i, 1), this.getEffectSource()); ++ if (b0 > 0) { ++ entityliving.addEffect(new MobEffectInstance(MobEffects.WITHER, 20 * b0, 1), this.getEffectSource(), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + } +@@ -87,7 +96,15 @@ + protected void onHit(HitResult result) { + super.onHit(result); + if (!this.level().isClientSide) { +- this.level().explode(this, this.getX(), this.getY(), this.getZ(), 1.0F, false, Level.ExplosionInteraction.MOB); ++ // CraftBukkit start ++ // this.level().explode(this, this.getX(), this.getY(), this.getZ(), 1.0F, false, World.a.MOB); ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), 1.0F, false); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.MOB); ++ } ++ // CraftBukkit end + this.discard(); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/raid/Raid.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/raid/Raid.java.patch new file mode 100644 index 0000000000..8cd48b035c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/raid/Raid.java.patch @@ -0,0 +1,199 @@ +--- a/net/minecraft/world/entity/raid/Raid.java ++++ b/net/minecraft/world/entity/raid/Raid.java +@@ -160,6 +176,12 @@ + return this.status == Raid.RaidStatus.LOSS; + } + ++ // CraftBukkit start ++ public boolean isInProgress() { ++ return this.status == RaidStatus.ONGOING; ++ } ++ // CraftBukkit end ++ + public float getTotalHealth() { + return this.totalHealth; + } +@@ -243,6 +278,7 @@ + boolean flag = this.active; + this.active = this.level.hasChunkAt(this.center); + if (this.level.getDifficulty() == Difficulty.PEACEFUL) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.PEACE); // CraftBukkit + this.stop(); + return; + } +@@ -262,13 +298,16 @@ + if (!this.level.isVillage(this.center)) { + if (this.groupsSpawned > 0) { + this.status = Raid.RaidStatus.LOSS; ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidFinishEvent(this, new java.util.ArrayList<>()); // CraftBukkit + } else { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.NOT_IN_VILLAGE); // CraftBukkit + this.stop(); + } + } + + this.ticksActive++; + if (this.ticksActive >= 48000L) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.TIMEOUT); // CraftBukkit + this.stop(); + return; + } +@@ -343,7 +380,8 @@ + i1++; + } + +- if (i1 > 3) { ++ if (j > 3) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.UNSPAWNABLE); // CraftBukkit + this.stop(); + break; + } +@@ -355,21 +394,26 @@ + } else { + this.status = Raid.RaidStatus.VICTORY; + +- for (UUID uUID : this.heroesOfTheVillage) { +- Entity entity = this.level.getEntity(uUID); ++ List winners = new java.util.ArrayList<>(); // CraftBukkit ++ while (iterator.hasNext()) { ++ UUID uuid = (UUID) iterator.next(); ++ Entity entity = this.level.getEntity(uuid); ++ + if (entity instanceof LivingEntity) { + LivingEntity livingEntity = (LivingEntity)entity; + if (!entity.isSpectator()) { +- livingEntity.addEffect( +- new MobEffectInstance(MobEffects.HERO_OF_THE_VILLAGE, 48000, this.badOmenLevel - 1, false, false, true) +- ); +- if (livingEntity instanceof ServerPlayer serverPlayer) { +- serverPlayer.awardStat(Stats.RAID_WIN); +- CriteriaTriggers.RAID_WIN.trigger(serverPlayer); ++ entityliving.addEffect(new MobEffectInstance(MobEffects.HERO_OF_THE_VILLAGE, 48000, this.badOmenLevel - 1, false, false, true)); ++ if (entityliving instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entityliving; ++ ++ entityplayer.awardStat(Stats.RAID_WIN); ++ CriteriaTriggers.RAID_WIN.trigger(entityplayer); ++ winners.add(entityplayer.getBukkitEntity()); // CraftBukkit + } + } + } + } ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidFinishEvent(this, winners); // CraftBukkit + } + } + +@@ -377,6 +422,7 @@ + } else if (this.isOver()) { + this.celebrationTicks++; + if (this.celebrationTicks >= 600) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.FINISHED); // CraftBukkit + this.stop(); + return; + } +@@ -492,10 +559,15 @@ + DifficultyInstance currentDifficultyAt = this.level.getCurrentDifficultyAt(pos); + boolean shouldSpawnBonusGroup = this.shouldSpawnBonusGroup(); + +- for (Raid.RaiderType raiderType : Raid.RaiderType.VALUES) { +- int i1 = this.getDefaultNumSpawns(raiderType, i, shouldSpawnBonusGroup) +- + this.getPotentialBonusSpawns(raiderType, this.random, i, currentDifficultyAt, shouldSpawnBonusGroup); +- int i2 = 0; ++ // CraftBukkit start ++ Raider leader = null; ++ List raiders = new java.util.ArrayList<>(); ++ // CraftBukkit end ++ while (k < j) { ++ Raid.RaiderType raid_wave = araid_wave[k]; ++ int l = this.getDefaultNumSpawns(raid_wave, i, flag1) + this.getPotentialBonusSpawns(raid_wave, this.random, i, difficultydamagescaler, flag1); ++ int i1 = 0; ++ int j1 = 0; + + for (int i3 = 0; i3 < i1; i3++) { + Raider raider = raiderType.entityType.create(this.level); +@@ -503,22 +573,36 @@ + break; + } + +- if (!flag && raider.canBeLeader()) { +- raider.setPatrolLeader(true); +- this.setLeader(i, raider); +- flag = true; +- } ++ if (entityraider != null) { ++ if (!flag && entityraider.canBeLeader()) { ++ entityraider.setPatrolLeader(true); ++ this.setLeader(i, entityraider); ++ flag = true; ++ leader = entityraider; // CraftBukkit ++ } + +- this.joinRaid(i, raider, pos, false); +- if (raiderType.entityType == EntityType.RAVAGER) { +- Raider raider1 = null; +- if (i == this.getNumGroups(Difficulty.NORMAL)) { +- raider1 = EntityType.PILLAGER.create(this.level); +- } else if (i >= this.getNumGroups(Difficulty.HARD)) { +- if (i2 == 0) { +- raider1 = EntityType.EVOKER.create(this.level); +- } else { +- raider1 = EntityType.VINDICATOR.create(this.level); ++ this.joinRaid(i, entityraider, pos, false); ++ raiders.add(entityraider); // CraftBukkit ++ if (raid_wave.entityType == EntityType.RAVAGER) { ++ Raider entityraider1 = null; ++ ++ if (i == this.getNumGroups(Difficulty.NORMAL)) { ++ entityraider1 = (Raider) EntityType.PILLAGER.create(this.level); ++ } else if (i >= this.getNumGroups(Difficulty.HARD)) { ++ if (i1 == 0) { ++ entityraider1 = (Raider) EntityType.EVOKER.create(this.level); ++ } else { ++ entityraider1 = (Raider) EntityType.VINDICATOR.create(this.level); ++ } ++ } ++ ++ ++i1; ++ if (entityraider1 != null) { ++ this.joinRaid(i, entityraider1, pos, false); ++ entityraider1.moveTo(pos, 0.0F, 0.0F); ++ entityraider1.startRiding(entityraider); ++ raiders.add(entityraider); // CraftBukkit ++ } + } + } + +@@ -536,6 +619,7 @@ + this.groupsSpawned++; + this.updateBossbar(); + this.setDirty(); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidSpawnWaveEvent(this, leader, raiders); // CraftBukkit + } + + public void joinRaid(int wave, Raider raider, @Nullable BlockPos pos, boolean isRecruited) { +@@ -550,7 +635,7 @@ + raider.finalizeSpawn(this.level, this.level.getCurrentDifficultyAt(pos), MobSpawnType.EVENT, null, null); + raider.applyRaidBuffs(wave, false); + raider.setOnGround(true); +- this.level.addFreshEntityWithPassengers(raider); ++ this.level.addFreshEntityWithPassengers(raider, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.RAID); // CraftBukkit + } + } + } +@@ -800,11 +885,11 @@ + this.heroesOfTheVillage.add(player.getUUID()); + } + +- static enum RaidStatus { +- ONGOING, +- VICTORY, +- LOSS, +- STOPPED; ++ // CraftBukkit start - a method to get all raiders ++ public java.util.Collection getRaiders() { ++ return this.groupRaiderMap.values().stream().flatMap(Set::stream).collect(java.util.stream.Collectors.toSet()); ++ } ++ // CraftBukkit end + + private static final Raid.RaidStatus[] VALUES = values(); + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/raid/Raider.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/raid/Raider.java.patch new file mode 100644 index 0000000000..01720c3ef4 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/raid/Raider.java.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/world/entity/raid/Raider.java ++++ b/net/minecraft/world/entity/raid/Raider.java +@@ -154,7 +165,7 @@ + i = Mth.clamp(i, 0, 4); + MobEffectInstance mobEffectInstance = new MobEffectInstance(MobEffects.BAD_OMEN, 120000, i, false, false, true); + if (!this.level().getGameRules().getBoolean(GameRules.RULE_DISABLE_RAIDS)) { +- player.addEffect(mobEffectInstance); ++ entityhuman.addEffect(mobeffect1, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN); // CraftBukkit + } + } + } +@@ -468,16 +511,17 @@ + return this.raider.hasActiveRaid() && !this.raider.getCurrentRaid().isOver(); + } + +- private boolean hasSuitablePoi() { +- ServerLevel serverLevel = (ServerLevel)this.raider.level(); +- BlockPos blockPos = this.raider.blockPosition(); +- Optional random = serverLevel.getPoiManager() +- .getRandom(holder -> holder.is(PoiTypes.HOME), this::hasNotVisited, PoiManager.Occupancy.ANY, blockPos, 48, this.raider.random); +- if (random.isEmpty()) { +- return false; +- } else { +- this.poiPos = random.get().immutable(); +- return true; ++ @Override ++ public void start() { ++ super.start(); ++ this.mob.getNavigation().stop(); ++ List list = this.mob.level().getNearbyEntities(Raider.class, this.shoutTargeting, this.mob, this.mob.getBoundingBox().inflate(8.0D, 8.0D, 8.0D)); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Raider entityraider = (Raider) iterator.next(); ++ ++ entityraider.setTarget(this.mob.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.FOLLOW_LEADER, true); // CraftBukkit + } + } + +@@ -491,8 +528,21 @@ + + @Override + public void stop() { +- if (this.poiPos.closerToCenterThan(this.raider.position(), (double)this.distanceToPoi)) { +- this.visited.add(this.poiPos); ++ super.stop(); ++ LivingEntity entityliving = this.mob.getTarget(); ++ ++ if (entityliving != null) { ++ List list = this.mob.level().getNearbyEntities(Raider.class, this.shoutTargeting, this.mob, this.mob.getBoundingBox().inflate(8.0D, 8.0D, 8.0D)); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Raider entityraider = (Raider) iterator.next(); ++ ++ entityraider.setTarget(this.mob.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.FOLLOW_LEADER, true); // CraftBukkit ++ entityraider.setAggressive(true); ++ } ++ ++ this.mob.setAggressive(true); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/raid/Raids.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/raid/Raids.java.patch new file mode 100644 index 0000000000..8c6e6b1a8e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/raid/Raids.java.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/world/entity/raid/Raids.java ++++ b/net/minecraft/world/entity/raid/Raids.java +@@ -118,19 +121,32 @@ + Raid raid = this.getOrCreateRaid(serverPlayer.serverLevel(), blockPos1); + boolean flag = false; + if (!raid.isStarted()) { ++ /* CraftBukkit - moved down + if (!this.raidMap.containsKey(raid.getId())) { + this.raidMap.put(raid.getId(), raid); + } + + flag = true; +- } else if (raid.getBadOmenLevel() < raid.getMaxBadOmenLevel()) { ++ // CraftBukkit start - fixed a bug with raid: players could add up Bad Omen level even when the raid had finished ++ } else if (raid.isInProgress() && raid.getBadOmenLevel() < raid.getMaxBadOmenLevel()) { + flag = true; ++ // CraftBukkit end + } else { + serverPlayer.removeEffect(MobEffects.BAD_OMEN); + serverPlayer.connection.send(new ClientboundEntityEventPacket(serverPlayer, (byte)43)); + } + + if (flag) { ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callRaidTriggerEvent(raid, serverPlayer)) { ++ serverPlayer.removeEffect(MobEffects.BAD_OMEN); ++ return null; ++ } ++ ++ if (!this.raidMap.containsKey(raid.getId())) { ++ this.raidMap.put(raid.getId(), raid); ++ } ++ // CraftBukkit end + raid.absorbBadOmen(serverPlayer); + serverPlayer.connection.send(new ClientboundEntityEventPacket(serverPlayer, (byte)43)); + if (!raid.hasFirstWaveSpawned()) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/AbstractMinecart.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/AbstractMinecart.java.patch new file mode 100644 index 0000000000..9ba7ab24fd --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/AbstractMinecart.java.patch @@ -0,0 +1,218 @@ +--- a/net/minecraft/world/entity/vehicle/AbstractMinecart.java ++++ b/net/minecraft/world/entity/vehicle/AbstractMinecart.java +@@ -46,6 +48,14 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.Vehicle; ++import org.bukkit.event.vehicle.VehicleEntityCollisionEvent; ++import org.bukkit.util.Vector; ++// CraftBukkit end ++ + public abstract class AbstractMinecart extends VehicleEntity { + private static final float LOWERED_PASSENGER_ATTACHMENT_Y = 0.0F; + private static final float PASSENGER_ATTACHMENT_Y = 0.1875F; +@@ -86,6 +96,17 @@ + map.put(RailShape.NORTH_EAST, Pair.of(normal2, normal1)); + }); + ++ // CraftBukkit start ++ public boolean slowWhenEmpty = true; ++ private double derailedX = 0.5; ++ private double derailedY = 0.5; ++ private double derailedZ = 0.5; ++ private double flyingX = 0.95; ++ private double flyingY = 0.95; ++ private double flyingZ = 0.95; ++ public double maxSpeed = 0.4D; ++ // CraftBukkit end ++ + protected AbstractMinecart(EntityType entityType, Level level) { + super(entityType, level); + this.blocksBuilding = true; +@@ -230,6 +286,14 @@ + + @Override + public void tick() { ++ // CraftBukkit start ++ double prevX = this.getX(); ++ double prevY = this.getY(); ++ double prevZ = this.getZ(); ++ float prevYaw = this.getYRot(); ++ float prevPitch = this.getXRot(); ++ // CraftBukkit end ++ + if (this.getHurtTime() > 0) { + this.setHurtTime(this.getHurtTime() - 1); + } +@@ -239,7 +303,7 @@ + } + + this.checkBelowWorld(); +- this.handleNetherPortal(); ++ // this.handleNetherPortal(); // CraftBukkit - handled in postTick + if (this.level().isClientSide) { + if (this.lerpSteps > 0) { + this.lerpPositionAndRotationStep(this.lerpSteps, this.lerpX, this.lerpY, this.lerpZ, this.lerpYRot, this.lerpXRot); +@@ -291,17 +361,48 @@ + } + + this.setRot(this.getYRot(), this.getXRot()); +- if (this.getMinecartType() == AbstractMinecart.Type.RIDEABLE && this.getDeltaMovement().horizontalDistanceSqr() > 0.01) { +- List entities = this.level().getEntities(this, this.getBoundingBox().inflate(0.2F, 0.0, 0.2F), EntitySelector.pushableBy(this)); +- if (!entities.isEmpty()) { +- for (Entity entity : entities) { +- if (!(entity instanceof Player) +- && !(entity instanceof IronGolem) +- && !(entity instanceof AbstractMinecart) +- && !this.isVehicle() +- && !entity.isPassenger()) { ++ // CraftBukkit start ++ org.bukkit.World bworld = this.level().getWorld(); ++ Location from = new Location(bworld, prevX, prevY, prevZ, prevYaw, prevPitch); ++ Location to = CraftLocation.toBukkit(this.position(), bworld, this.getYRot(), this.getXRot()); ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ ++ this.level().getCraftServer().getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleUpdateEvent(vehicle)); ++ ++ if (!from.equals(to)) { ++ this.level().getCraftServer().getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleMoveEvent(vehicle, from, to)); ++ } ++ // CraftBukkit end ++ if (this.getMinecartType() == AbstractMinecart.EnumMinecartType.RIDEABLE && this.getDeltaMovement().horizontalDistanceSqr() > 0.01D) { ++ List list = this.level().getEntities((Entity) this, this.getBoundingBox().inflate(0.20000000298023224D, 0.0D, 0.20000000298023224D), EntitySelector.pushableBy(this)); ++ ++ if (!list.isEmpty()) { ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ ++ if (!(entity instanceof Player) && !(entity instanceof IronGolem) && !(entity instanceof AbstractMinecart) && !this.isVehicle() && !entity.isPassenger()) { ++ // CraftBukkit start ++ VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(collisionEvent); ++ ++ if (collisionEvent.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end + entity.startRiding(this); + } else { ++ // CraftBukkit start ++ if (!this.isPassengerOfSameVehicle(entity)) { ++ VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(collisionEvent); ++ ++ if (collisionEvent.isCancelled()) { ++ continue; ++ } ++ } ++ // CraftBukkit end + entity.push(this); + } + } +@@ -309,6 +414,14 @@ + } else { + for (Entity entity1 : this.level().getEntities(this, this.getBoundingBox().inflate(0.2F, 0.0, 0.2F))) { + if (!this.hasPassenger(entity1) && entity1.isPushable() && entity1 instanceof AbstractMinecart) { ++ // CraftBukkit start ++ VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, entity1.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(collisionEvent); ++ ++ if (collisionEvent.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end + entity1.push(this); + } + } +@@ -325,7 +438,7 @@ + } + + protected double getMaxSpeed() { +- return (this.isInWater() ? 4.0 : 8.0) / 20.0; ++ return (this.isInWater() ? this.maxSpeed / 2.0D: this.maxSpeed); // CraftBukkit + } + + public void activateMinecart(int x, int y, int z, boolean powered) { +@@ -336,12 +449,16 @@ + Vec3 deltaMovement = this.getDeltaMovement(); + this.setDeltaMovement(Mth.clamp(deltaMovement.x, -maxSpeed, maxSpeed), deltaMovement.y, Mth.clamp(deltaMovement.z, -maxSpeed, maxSpeed)); + if (this.onGround()) { +- this.setDeltaMovement(this.getDeltaMovement().scale(0.5)); ++ // CraftBukkit start - replace magic numbers with our variables ++ this.setDeltaMovement(new Vec3(this.getDeltaMovement().x * this.derailedX, this.getDeltaMovement().y * this.derailedY, this.getDeltaMovement().z * this.derailedZ)); ++ // CraftBukkit end + } + + this.move(MoverType.SELF, this.getDeltaMovement()); + if (!this.onGround()) { +- this.setDeltaMovement(this.getDeltaMovement().scale(0.95)); ++ // CraftBukkit start - replace magic numbers with our variables ++ this.setDeltaMovement(new Vec3(this.getDeltaMovement().x * this.flyingX, this.getDeltaMovement().y * this.flyingY, this.getDeltaMovement().z * this.flyingZ)); ++ // CraftBukkit end + } + } + +@@ -514,9 +654,10 @@ + } + + protected void applyNaturalSlowdown() { +- double d = this.isVehicle() ? 0.997 : 0.96; +- Vec3 deltaMovement = this.getDeltaMovement(); +- Vec3 var4 = deltaMovement.multiply(d, 0.0, d); ++ double d0 = this.isVehicle() || !this.slowWhenEmpty ? 0.997D : 0.96D; // CraftBukkit - add !this.slowWhenEmpty ++ Vec3 vec3d = this.getDeltaMovement(); ++ ++ vec3d = vec3d.multiply(d0, 0.0D, d0); + if (this.isInWater()) { + var4 = var4.scale(0.95F); + } +@@ -641,7 +793,15 @@ + if (!this.level().isClientSide) { + if (!entity.noPhysics && !this.noPhysics) { + if (!this.hasPassenger(entity)) { +- double d = entity.getX() - this.getX(); ++ // CraftBukkit start ++ VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(collisionEvent); ++ ++ if (collisionEvent.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ double d0 = entity.getX() - this.getX(); + double d1 = entity.getZ() - this.getZ(); + double d2 = d * d + d1 * d1; + if (d2 >= 1.0E-4F) { +@@ -803,4 +975,26 @@ + HOPPER, + COMMAND_BLOCK; + } ++ ++ // CraftBukkit start - Methods for getting and setting flying and derailed velocity modifiers ++ public Vector getFlyingVelocityMod() { ++ return new Vector(flyingX, flyingY, flyingZ); ++ } ++ ++ public void setFlyingVelocityMod(Vector flying) { ++ flyingX = flying.getX(); ++ flyingY = flying.getY(); ++ flyingZ = flying.getZ(); ++ } ++ ++ public Vector getDerailedVelocityMod() { ++ return new Vector(derailedX, derailedY, derailedZ); ++ } ++ ++ public void setDerailedVelocityMod(Vector derailed) { ++ derailedX = derailed.getX(); ++ derailedY = derailed.getY(); ++ derailedZ = derailed.getZ(); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java.patch new file mode 100644 index 0000000000..31135f280a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java.patch @@ -0,0 +1,74 @@ +--- a/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java ++++ b/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java +@@ -16,6 +17,13 @@ + import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end + + public abstract class AbstractMinecartContainer extends AbstractMinecart implements ContainerEntity { + private NonNullList itemStacks = NonNullList.withSize(36, ItemStack.EMPTY); +@@ -23,12 +32,55 @@ + private ResourceLocation lootTable; + private long lootTableSeed; + ++ // CraftBukkit start ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.itemStacks; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public InventoryHolder getOwner() { ++ org.bukkit.entity.Entity cart = getBukkitEntity(); ++ if(cart instanceof InventoryHolder) return (InventoryHolder) cart; ++ return null; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return getBukkitEntity().getLocation(); ++ } ++ // CraftBukkit end ++ + protected AbstractMinecartContainer(EntityType entityType, Level level) { + super(entityType, level); ++ this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); // CraftBukkit - SPIGOT-3513 + } + +- protected AbstractMinecartContainer(EntityType entityType, double x, double y, double z, Level level) { +- super(entityType, level, x, y, z); ++ protected AbstractMinecartContainer(EntityType entityType, double x, double d1, double y, Level world) { ++ super(entityType, world, x, d1, y); ++ this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); // CraftBukkit - SPIGOT-3513 + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/Boat.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/Boat.java.patch new file mode 100644 index 0000000000..4fb52855db --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/Boat.java.patch @@ -0,0 +1,114 @@ +--- a/net/minecraft/world/entity/vehicle/Boat.java ++++ b/net/minecraft/world/entity/vehicle/Boat.java +@@ -52,6 +55,15 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.Vehicle; ++import org.bukkit.event.vehicle.VehicleDestroyEvent; ++import org.bukkit.event.vehicle.VehicleEntityCollisionEvent; ++import org.bukkit.event.vehicle.VehicleMoveEvent; ++// CraftBukkit end ++ + public class Boat extends VehicleEntity implements VariantHolder { + private static final EntityDataAccessor DATA_ID_TYPE = SynchedEntityData.defineId(Boat.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_ID_PADDLE_LEFT = SynchedEntityData.defineId(Boat.class, EntityDataSerializers.BOOLEAN); +@@ -88,6 +101,14 @@ + private float bubbleAngle; + private float bubbleAngleO; + ++ // CraftBukkit start ++ // PAIL: Some of these haven't worked since a few updates, and since 1.9 they are less and less applicable. ++ public double maxSpeed = 0.4D; ++ public double occupiedDeceleration = 0.2D; ++ public double unoccupiedDeceleration = -1; ++ public boolean landBoats = false; ++ // CraftBukkit end ++ + public Boat(EntityType entityType, Level level) { + super(entityType, level); + this.blocksBuilding = true; +@@ -198,9 +209,29 @@ + public void push(Entity entity) { + if (entity instanceof Boat) { + if (entity.getBoundingBox().minY < this.getBoundingBox().maxY) { ++ // CraftBukkit start ++ if (!this.isPassengerOfSameVehicle(entity)) { ++ VehicleEntityCollisionEvent event = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + super.push(entity); + } + } else if (entity.getBoundingBox().minY <= this.getBoundingBox().minY) { ++ // CraftBukkit start ++ if (!this.isPassengerOfSameVehicle(entity)) { ++ VehicleEntityCollisionEvent event = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + super.push(entity); + } + } +@@ -272,6 +325,7 @@ + return this.getDirection().getClockWise(); + } + ++ private Location lastLocation; // CraftBukkit + @Override + public void tick() { + this.oldStatus = this.status; +@@ -312,6 +366,22 @@ + this.setDeltaMovement(Vec3.ZERO); + } + ++ // CraftBukkit start ++ org.bukkit.Server server = this.level().getCraftServer(); ++ org.bukkit.World bworld = this.level().getWorld(); ++ ++ Location to = CraftLocation.toBukkit(this.position(), bworld, this.getYRot(), this.getXRot()); ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ ++ server.getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleUpdateEvent(vehicle)); ++ ++ if (lastLocation != null && !lastLocation.equals(to)) { ++ VehicleMoveEvent event = new VehicleMoveEvent(vehicle, lastLocation, to); ++ server.getPluginManager().callEvent(event); ++ } ++ lastLocation = vehicle.getLocation(); ++ // CraftBukkit end ++ + this.tickBubbleColumn(); + + for (int i = 0; i <= 1; i++) { +@@ -782,6 +867,11 @@ + + this.causeFallDamage(this.fallDistance, 1.0F, this.damageSources().fall()); + if (!this.level().isClientSide && !this.isRemoved()) { ++ // CraftBukkit start ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, null); ++ this.level().getCraftServer().getPluginManager().callEvent(destroyEvent); ++ if (!destroyEvent.isCancelled()) { + this.kill(); + if (this.level().getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { + for (int i = 0; i < 3; i++) { +@@ -793,6 +885,7 @@ + } + } + } ++ } // CraftBukkit end + } + + this.resetFallDistance(); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/ChestBoat.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/ChestBoat.java.patch new file mode 100644 index 0000000000..9d7239e776 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/ChestBoat.java.patch @@ -0,0 +1,68 @@ +--- a/net/minecraft/world/entity/vehicle/ChestBoat.java ++++ b/net/minecraft/world/entity/vehicle/ChestBoat.java +@@ -22,6 +23,13 @@ + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end + + public class ChestBoat extends Boat implements HasCustomInventoryScreen, ContainerEntity { + private static final int CONTAINER_SIZE = 27; +@@ -212,4 +245,51 @@ + public void stopOpen(Player player) { + this.level().gameEvent(GameEvent.CONTAINER_CLOSE, this.position(), GameEvent.Context.of(player)); + } ++ ++ // CraftBukkit start ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ @Override ++ public List getContents() { ++ return this.itemStacks; ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public InventoryHolder getOwner() { ++ org.bukkit.entity.Entity entity = getBukkitEntity(); ++ if (entity instanceof InventoryHolder) return (InventoryHolder) entity; ++ return null; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ @Override ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return getBukkitEntity().getLocation(); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java.patch new file mode 100644 index 0000000000..b008b28e5d --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java ++++ b/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java +@@ -146,5 +143,12 @@ + public boolean isValid() { + return !MinecartCommandBlock.this.isRemoved(); + } ++ ++ // CraftBukkit start ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return (org.bukkit.craftbukkit.entity.CraftMinecartCommand) MinecartCommandBlock.this.getBukkitEntity(); ++ } ++ // CraftBukkit end + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/MinecartTNT.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/MinecartTNT.java.patch new file mode 100644 index 0000000000..ddd764dafa --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/MinecartTNT.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/entity/vehicle/MinecartTNT.java ++++ b/net/minecraft/world/entity/vehicle/MinecartTNT.java +@@ -19,6 +22,9 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.material.FluidState; ++// CraftBukkit start ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end + + public class MinecartTNT extends AbstractMinecart { + private static final byte EVENT_PRIME = 10; +@@ -99,18 +118,15 @@ + squareRoot = 5.0; + } + +- this.level() +- .explode( +- this, +- damageSource, +- null, +- this.getX(), +- this.getY(), +- this.getZ(), +- (float)(4.0 + this.random.nextDouble() * 1.5 * squareRoot), +- false, +- Level.ExplosionInteraction.TNT +- ); ++ // CraftBukkit start ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), (float) (4.0D + this.random.nextDouble() * 1.5D * d1), false); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ fuse = -1; ++ return; ++ } ++ this.level().explode(this, damageSource, (ExplosionDamageCalculator) null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.TNT); ++ // CraftBukkit end + this.discard(); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/VehicleEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/VehicleEntity.java.patch new file mode 100644 index 0000000000..3300c9d219 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/entity/vehicle/VehicleEntity.java.patch @@ -0,0 +1,72 @@ +--- a/net/minecraft/world/entity/vehicle/VehicleEntity.java ++++ b/net/minecraft/world/entity/vehicle/VehicleEntity.java +@@ -13,6 +13,12 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.entity.Vehicle; ++import org.bukkit.event.vehicle.VehicleDamageEvent; ++import org.bukkit.event.vehicle.VehicleDestroyEvent; ++// CraftBukkit end ++ + public abstract class VehicleEntity extends Entity { + protected static final EntityDataAccessor DATA_ID_HURT = SynchedEntityData.defineId(VehicleEntity.class, EntityDataSerializers.INT); + protected static final EntityDataAccessor DATA_ID_HURTDIR = SynchedEntityData.defineId(VehicleEntity.class, EntityDataSerializers.INT); +@@ -40,9 +35,54 @@ + this.discard(); + } + } else { +- this.destroy(source); +- } ++ // CraftBukkit start ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ org.bukkit.entity.Entity attacker = (source.getEntity() == null) ? null : source.getEntity().getBukkitEntity(); + ++ VehicleDamageEvent event = new VehicleDamageEvent(vehicle, attacker, (double) amount); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ amount = (float) event.getDamage(); ++ // CraftBukkit end ++ this.setHurtDir(-this.getHurtDir()); ++ this.setHurtTime(10); ++ this.markHurt(); ++ this.setDamage(this.getDamage() + amount * 10.0F); ++ this.gameEvent(GameEvent.ENTITY_DAMAGE, source.getEntity()); ++ boolean flag = source.getEntity() instanceof Player && ((Player) source.getEntity()).getAbilities().instabuild; ++ ++ if ((flag || this.getDamage() <= 40.0F) && !this.shouldSourceDestroy(source)) { ++ if (flag) { ++ // CraftBukkit start ++ VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, attacker); ++ this.level().getCraftServer().getPluginManager().callEvent(destroyEvent); ++ ++ if (destroyEvent.isCancelled()) { ++ this.setDamage(40.0F); // Maximize damage so this doesn't get triggered again right away ++ return true; ++ } ++ // CraftBukkit end ++ this.discard(); ++ } ++ } else { ++ // CraftBukkit start ++ VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, attacker); ++ this.level().getCraftServer().getPluginManager().callEvent(destroyEvent); ++ ++ if (destroyEvent.isCancelled()) { ++ this.setDamage(40.0F); // Maximize damage so this doesn't get triggered again right away ++ return true; ++ } ++ // CraftBukkit end ++ this.destroy(source); ++ } ++ ++ return true; ++ } ++ } else { + return true; + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/food/FoodData.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/food/FoodData.java.patch new file mode 100644 index 0000000000..7c9248adc9 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/food/FoodData.java.patch @@ -0,0 +1,109 @@ +--- a/net/minecraft/world/food/FoodData.java ++++ b/net/minecraft/world/food/FoodData.java +@@ -12,11 +15,22 @@ + private float saturationLevel; + private float exhaustionLevel; + private int tickTimer; ++ // CraftBukkit start ++ private Player entityhuman; ++ public int saturatedRegenRate = 10; ++ public int unsaturatedRegenRate = 80; ++ public int starvationRate = 80; ++ // CraftBukkit end + private int lastFoodLevel = 20; + +- public FoodData() { +- this.saturationLevel = 5.0F; ++ public FoodData() { throw new AssertionError("Whoopsie, we missed the bukkit."); } // CraftBukkit start - throw an error ++ ++ // CraftBukkit start - added EntityHuman constructor ++ public FoodData(Player entityhuman) { ++ org.apache.commons.lang.Validate.notNull(entityhuman); ++ this.entityhuman = entityhuman; + } ++ // CraftBukkit end + + public void eat(int foodLevelModifier, float saturationLevelModifier) { + this.foodLevel = Math.min(foodLevelModifier + this.foodLevel, 20); +@@ -25,8 +39,18 @@ + + public void eat(Item item, ItemStack stack) { + if (item.isEdible()) { +- FoodProperties foodProperties = item.getFoodProperties(); +- this.eat(foodProperties.getNutrition(), foodProperties.getSaturationModifier()); ++ FoodProperties foodinfo = item.getFoodProperties(); ++ // CraftBukkit start ++ int oldFoodLevel = foodLevel; ++ ++ org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(entityhuman, foodinfo.getNutrition() + oldFoodLevel, stack); ++ ++ if (!event.isCancelled()) { ++ this.eat(event.getFoodLevel() - oldFoodLevel, foodinfo.getSaturationModifier()); ++ } ++ ++ ((ServerPlayer) entityhuman).getBukkitEntity().sendHealthUpdate(); ++ // CraftBukkit end + } + } + +@@ -37,31 +63,43 @@ + this.exhaustionLevel -= 4.0F; + if (this.saturationLevel > 0.0F) { + this.saturationLevel = Math.max(this.saturationLevel - 1.0F, 0.0F); +- } else if (difficulty != Difficulty.PEACEFUL) { +- this.foodLevel = Math.max(this.foodLevel - 1, 0); ++ } else if (enumdifficulty != Difficulty.PEACEFUL) { ++ // CraftBukkit start ++ org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(player, Math.max(this.foodLevel - 1, 0)); ++ ++ if (!event.isCancelled()) { ++ this.foodLevel = event.getFoodLevel(); ++ } ++ ++ ((ServerPlayer) player).connection.send(new ClientboundSetHealthPacket(((ServerPlayer) player).getBukkitEntity().getScaledHealth(), this.foodLevel, this.saturationLevel)); ++ // CraftBukkit end + } + } + +- boolean _boolean = player.level().getGameRules().getBoolean(GameRules.RULE_NATURAL_REGENERATION); +- if (_boolean && this.saturationLevel > 0.0F && player.isHurt() && this.foodLevel >= 20) { +- this.tickTimer++; +- if (this.tickTimer >= 10) { +- float min = Math.min(this.saturationLevel, 6.0F); +- player.heal(min / 6.0F); +- this.addExhaustion(min); ++ boolean flag = player.level().getGameRules().getBoolean(GameRules.RULE_NATURAL_REGENERATION); ++ ++ if (flag && this.saturationLevel > 0.0F && player.isHurt() && this.foodLevel >= 20) { ++ ++this.tickTimer; ++ if (this.tickTimer >= this.saturatedRegenRate) { // CraftBukkit ++ float f = Math.min(this.saturationLevel, 6.0F); ++ ++ player.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED); // CraftBukkit - added RegainReason ++ // this.addExhaustion(f); CraftBukkit - EntityExhaustionEvent ++ player.causeFoodExhaustion(f, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.REGEN); // CraftBukkit - EntityExhaustionEvent + this.tickTimer = 0; + } +- } else if (_boolean && this.foodLevel >= 18 && player.isHurt()) { +- this.tickTimer++; +- if (this.tickTimer >= 80) { +- player.heal(1.0F); +- this.addExhaustion(6.0F); ++ } else if (flag && this.foodLevel >= 18 && player.isHurt()) { ++ ++this.tickTimer; ++ if (this.tickTimer >= this.unsaturatedRegenRate) { // CraftBukkit - add regen rate manipulation ++ player.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED); // CraftBukkit - added RegainReason ++ // this.a(6.0F); CraftBukkit - EntityExhaustionEvent ++ player.causeFoodExhaustion(6.0f, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.REGEN); // CraftBukkit - EntityExhaustionEvent + this.tickTimer = 0; + } + } else if (this.foodLevel <= 0) { +- this.tickTimer++; +- if (this.tickTimer >= 80) { +- if (player.getHealth() > 10.0F || difficulty == Difficulty.HARD || player.getHealth() > 1.0F && difficulty == Difficulty.NORMAL) { ++ ++this.tickTimer; ++ if (this.tickTimer >= this.starvationRate) { // CraftBukkit - add regen rate manipulation ++ if (player.getHealth() > 10.0F || enumdifficulty == Difficulty.HARD || player.getHealth() > 1.0F && enumdifficulty == Difficulty.NORMAL) { + player.hurt(player.damageSources().starve(), 1.0F); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/AbstractContainerMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/AbstractContainerMenu.java.patch new file mode 100644 index 0000000000..d577eee6c2 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/AbstractContainerMenu.java.patch @@ -0,0 +1,304 @@ +--- a/net/minecraft/world/inventory/AbstractContainerMenu.java ++++ b/net/minecraft/world/inventory/AbstractContainerMenu.java +@@ -33,6 +35,18 @@ + import net.minecraft.world.level.block.entity.BlockEntity; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.google.common.base.Preconditions; ++import java.util.HashMap; ++import java.util.Map; ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.Event.Result; ++import org.bukkit.event.inventory.InventoryDragEvent; ++import org.bukkit.event.inventory.InventoryType; ++import org.bukkit.inventory.InventoryView; ++// CraftBukkit end ++ + public abstract class AbstractContainerMenu { + private static final Logger LOGGER = LogUtils.getLogger(); + public static final int SLOT_CLICKED_OUTSIDE = -999; +@@ -62,6 +77,27 @@ + private ContainerSynchronizer synchronizer; + private boolean suppressRemoteUpdates; + ++ // CraftBukkit start ++ public boolean checkReachable = true; ++ public abstract InventoryView getBukkitView(); ++ public void transferTo(AbstractContainerMenu other, org.bukkit.craftbukkit.entity.CraftHumanEntity player) { ++ InventoryView source = this.getBukkitView(), destination = other.getBukkitView(); ++ ((CraftInventory) source.getTopInventory()).getInventory().onClose(player); ++ ((CraftInventory) source.getBottomInventory()).getInventory().onClose(player); ++ ((CraftInventory) destination.getTopInventory()).getInventory().onOpen(player); ++ ((CraftInventory) destination.getBottomInventory()).getInventory().onOpen(player); ++ } ++ private Component title; ++ public final Component getTitle() { ++ Preconditions.checkState(this.title != null, "Title not set"); ++ return this.title; ++ } ++ public final void setTitle(Component title) { ++ Preconditions.checkState(this.title == null, "Title already set"); ++ this.title = title; ++ } ++ // CraftBukkit end ++ + protected AbstractContainerMenu(@Nullable MenuType menuType, int containerId) { + this.menuType = menuType; + this.containerId = containerId; +@@ -153,6 +199,15 @@ + } + } + ++ // CraftBukkit start ++ public void broadcastCarriedItem() { ++ this.remoteCarried = this.getCarried().copy(); ++ if (this.synchronizer != null) { ++ this.synchronizer.sendCarriedChange(this, this.remoteCarried); ++ } ++ } ++ // CraftBukkit end ++ + public void removeSlotListener(ContainerListener listener) { + this.containerListeners.remove(listener); + } +@@ -328,8 +424,8 @@ + } + } else if (this.quickcraftStatus == 2) { + if (!this.quickcraftSlots.isEmpty()) { +- if (this.quickcraftSlots.size() == 1) { +- int i1 = this.quickcraftSlots.iterator().next().index; ++ if (false && this.quickcraftSlots.size() == 1) { // CraftBukkit - treat everything as a drag since we are unable to easily call InventoryClickEvent instead ++ k = ((Slot) this.quickcraftSlots.iterator().next()).index; + this.resetQuickCraft(); + this.doClick(i1, this.quickcraftType, ClickType.PICKUP, player); + return; +@@ -343,23 +440,59 @@ + + int count = this.getCarried().getCount(); + +- for (Slot slot1 : this.quickcraftSlots) { +- ItemStack carried1 = this.getCarried(); +- if (slot1 != null +- && canItemQuickReplace(slot1, carried1, true) +- && slot1.mayPlace(carried1) +- && (this.quickcraftType == 2 || carried1.getCount() >= this.quickcraftSlots.size()) +- && this.canDragTo(slot1)) { +- int i2 = slot1.hasItem() ? slot1.getItem().getCount() : 0; +- int min = Math.min(itemStack.getMaxStackSize(), slot1.getMaxStackSize(itemStack)); +- int min1 = Math.min(getQuickCraftPlaceCount(this.quickcraftSlots, this.quickcraftType, itemStack) + i2, min); +- count -= min1 - i2; +- slot1.setByPlayer(itemStack.copyWithCount(min1)); ++ Map draggedSlots = new HashMap(); // CraftBukkit - Store slots from drag in map (raw slot id -> new stack) ++ while (iterator.hasNext()) { ++ Slot slot1 = (Slot) iterator.next(); ++ ItemStack itemstack2 = this.getCarried(); ++ ++ if (slot1 != null && canItemQuickReplace(slot1, itemstack2, true) && slot1.mayPlace(itemstack2) && (this.quickcraftType == 2 || itemstack2.getCount() >= this.quickcraftSlots.size()) && this.canDragTo(slot1)) { ++ int j1 = slot1.hasItem() ? slot1.getItem().getCount() : 0; ++ int k1 = Math.min(itemstack1.getMaxStackSize(), slot1.getMaxStackSize(itemstack1)); ++ int l1 = Math.min(getQuickCraftPlaceCount(this.quickcraftSlots, this.quickcraftType, itemstack1) + j1, k1); ++ ++ l -= l1 - j1; ++ // slot1.setByPlayer(itemstack1.copyWithCount(l1)); ++ draggedSlots.put(slot1.index, itemstack1.copyWithCount(l1)); // CraftBukkit - Put in map instead of setting + } + } + +- itemStack.setCount(count); +- this.setCarried(itemStack); ++ // CraftBukkit start - InventoryDragEvent ++ InventoryView view = getBukkitView(); ++ org.bukkit.inventory.ItemStack newcursor = CraftItemStack.asCraftMirror(itemstack1); ++ newcursor.setAmount(l); ++ Map eventmap = new HashMap(); ++ for (Map.Entry ditem : draggedSlots.entrySet()) { ++ eventmap.put(ditem.getKey(), CraftItemStack.asBukkitCopy(ditem.getValue())); ++ } ++ ++ // It's essential that we set the cursor to the new value here to prevent item duplication if a plugin closes the inventory. ++ ItemStack oldCursor = this.getCarried(); ++ this.setCarried(CraftItemStack.asNMSCopy(newcursor)); ++ ++ InventoryDragEvent event = new InventoryDragEvent(view, (newcursor.getType() != org.bukkit.Material.AIR ? newcursor : null), CraftItemStack.asBukkitCopy(oldCursor), this.quickcraftType == 1, eventmap); ++ player.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ // Whether or not a change was made to the inventory that requires an update. ++ boolean needsUpdate = event.getResult() != Result.DEFAULT; ++ ++ if (event.getResult() != Result.DENY) { ++ for (Map.Entry dslot : draggedSlots.entrySet()) { ++ view.setItem(dslot.getKey(), CraftItemStack.asBukkitCopy(dslot.getValue())); ++ } ++ // The only time the carried item will be set to null is if the inventory is closed by the server. ++ // If the inventory is closed by the server, then the cursor items are dropped. This is why we change the cursor early. ++ if (this.getCarried() != null) { ++ this.setCarried(CraftItemStack.asNMSCopy(event.getCursor())); ++ needsUpdate = true; ++ } ++ } else { ++ this.setCarried(oldCursor); ++ } ++ ++ if (needsUpdate && player instanceof ServerPlayer) { ++ this.sendAllDataToRemote(); ++ } ++ // CraftBukkit end + } + + this.resetQuickCraft(); +@@ -368,15 +501,23 @@ + } + } else if (this.quickcraftStatus != 0) { + this.resetQuickCraft(); +- } else if ((clickType == ClickType.PICKUP || clickType == ClickType.QUICK_MOVE) && (button == 0 || button == 1)) { +- ClickAction clickAction = button == 0 ? ClickAction.PRIMARY : ClickAction.SECONDARY; +- if (slotId == -999) { +- if (!this.getCarried().isEmpty()) { +- if (clickAction == ClickAction.PRIMARY) { +- player.drop(this.getCarried(), true); +- this.setCarried(ItemStack.EMPTY); +- } else { +- player.drop(this.getCarried().split(1), true); ++ } else { ++ int i2; ++ ++ if ((clickType == InventoryClickType.PICKUP || clickType == InventoryClickType.QUICK_MOVE) && (button == 0 || button == 1)) { ++ ClickAction clickaction = button == 0 ? ClickAction.PRIMARY : ClickAction.SECONDARY; ++ ++ if (slotId == -999) { ++ if (!this.getCarried().isEmpty()) { ++ if (clickaction == ClickAction.PRIMARY) { ++ // CraftBukkit start ++ ItemStack carried = this.getCarried(); ++ this.setCarried(ItemStack.EMPTY); ++ player.drop(carried, true); ++ // CraftBukkit start ++ } else { ++ player.drop(this.getCarried().split(1), true); ++ } + } + } + } else if (clickType == ClickType.QUICK_MOVE) { +@@ -435,37 +576,56 @@ + } + } + +- slot.setChanged(); +- } +- } else if (clickType == ClickType.SWAP && (button >= 0 && button < 9 || button == 40)) { +- ItemStack item = inventory.getItem(button); +- Slot slot = this.slots.get(slotId); +- ItemStack carried = slot.getItem(); +- if (!item.isEmpty() || !carried.isEmpty()) { +- if (item.isEmpty()) { +- if (slot.mayPickup(player)) { +- inventory.setItem(button, carried); +- slot.onSwapCraft(carried.getCount()); +- slot.setByPlayer(ItemStack.EMPTY); +- slot.onTake(player, carried); +- } +- } else if (carried.isEmpty()) { +- if (slot.mayPlace(item)) { +- int maxStackSize = slot.getMaxStackSize(item); +- if (item.getCount() > maxStackSize) { +- slot.setByPlayer(item.split(maxStackSize)); +- } else { +- inventory.setItem(button, ItemStack.EMPTY); +- slot.setByPlayer(item); ++ slot.setChanged(); ++ // CraftBukkit start - Make sure the client has the right slot contents ++ if (player instanceof ServerPlayer && slot.getMaxStackSize() != 64) { ++ ((ServerPlayer) player).connection.send(new ClientboundContainerSetSlotPacket(this.containerId, this.incrementStateId(), slot.index, slot.getItem())); ++ // Updating a crafting inventory makes the client reset the result slot, have to send it again ++ if (this.getBukkitView().getType() == InventoryType.WORKBENCH || this.getBukkitView().getType() == InventoryType.CRAFTING) { ++ ((ServerPlayer) player).connection.send(new ClientboundContainerSetSlotPacket(this.containerId, this.incrementStateId(), 0, this.getSlot(0).getItem())); + } + } +- } else if (slot.mayPickup(player) && slot.mayPlace(item)) { +- int maxStackSize = slot.getMaxStackSize(item); +- if (item.getCount() > maxStackSize) { +- slot.setByPlayer(item.split(maxStackSize)); +- slot.onTake(player, carried); +- if (!inventory.add(carried)) { +- player.drop(carried, true); ++ // CraftBukkit end ++ } ++ } else { ++ int j2; ++ ++ if (clickType == InventoryClickType.SWAP && (button >= 0 && button < 9 || button == 40)) { ++ ItemStack itemstack4 = playerinventory.getItem(button); ++ ++ slot = (Slot) this.slots.get(slotId); ++ itemstack = slot.getItem(); ++ if (!itemstack4.isEmpty() || !itemstack.isEmpty()) { ++ if (itemstack4.isEmpty()) { ++ if (slot.mayPickup(player)) { ++ playerinventory.setItem(button, itemstack); ++ slot.onSwapCraft(itemstack.getCount()); ++ slot.setByPlayer(ItemStack.EMPTY); ++ slot.onTake(player, itemstack); ++ } ++ } else if (itemstack.isEmpty()) { ++ if (slot.mayPlace(itemstack4)) { ++ j2 = slot.getMaxStackSize(itemstack4); ++ if (itemstack4.getCount() > j2) { ++ slot.setByPlayer(itemstack4.split(j2)); ++ } else { ++ playerinventory.setItem(button, ItemStack.EMPTY); ++ slot.setByPlayer(itemstack4); ++ } ++ } ++ } else if (slot.mayPickup(player) && slot.mayPlace(itemstack4)) { ++ j2 = slot.getMaxStackSize(itemstack4); ++ if (itemstack4.getCount() > j2) { ++ slot.setByPlayer(itemstack4.split(j2)); ++ slot.onTake(player, itemstack); ++ if (!playerinventory.add(itemstack)) { ++ player.drop(itemstack, true); ++ } ++ } else { ++ playerinventory.setItem(button, itemstack); ++ slot.setByPlayer(itemstack4); ++ slot.onTake(player, itemstack); ++ } + } + } else { + inventory.setItem(button, carried); +@@ -539,15 +699,17 @@ + + public void removed(Player player) { + if (player instanceof ServerPlayer) { +- ItemStack carried = this.getCarried(); +- if (!carried.isEmpty()) { +- if (player.isAlive() && !((ServerPlayer)player).hasDisconnected()) { +- player.getInventory().placeItemBackInInventory(carried); ++ ItemStack itemstack = this.getCarried(); ++ ++ if (!itemstack.isEmpty()) { ++ this.setCarried(ItemStack.EMPTY); // CraftBukkit - SPIGOT-4556 - from below ++ if (player.isAlive() && !((ServerPlayer) player).hasDisconnected()) { ++ player.getInventory().placeItemBackInInventory(itemstack); + } else { + player.drop(carried, false); + } + +- this.setCarried(ItemStack.EMPTY); ++ // this.setCarried(ItemStack.EMPTY); // CraftBukkit - moved up + } + } + } +@@ -726,6 +926,11 @@ + } + + public ItemStack getCarried() { ++ // CraftBukkit start ++ if (this.carried.isEmpty()) { ++ this.setCarried(ItemStack.EMPTY); ++ } ++ // CraftBukkit end + return this.carried; + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/AbstractFurnaceMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/AbstractFurnaceMenu.java.patch new file mode 100644 index 0000000000..e7ef236514 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/AbstractFurnaceMenu.java.patch @@ -0,0 +1,56 @@ +--- a/net/minecraft/world/inventory/AbstractFurnaceMenu.java ++++ b/net/minecraft/world/inventory/AbstractFurnaceMenu.java +@@ -13,6 +13,10 @@ + import net.minecraft.world.item.crafting.RecipeType; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryFurnace; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + + public abstract class AbstractFurnaceMenu extends RecipeBookMenu { + public static final int INGREDIENT_SLOT = 0; +@@ -30,9 +35,23 @@ + private final RecipeType recipeType; + private final RecipeBookType recipeBookType; + +- protected AbstractFurnaceMenu( +- MenuType menuType, RecipeType recipeType, RecipeBookType recipeBookType, int containerId, Inventory playerInventory +- ) { ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryFurnace inventory = new CraftInventoryFurnace((AbstractFurnaceBlockEntity) this.container); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end ++ ++ protected AbstractFurnaceMenu(MenuType menuType, RecipeType recipeType, RecipeBookType recipeBookType, int containerId, Inventory playerInventory) { + this(menuType, recipeType, recipeBookType, containerId, playerInventory, new SimpleContainer(3), new SimpleContainerData(4)); + } + +@@ -56,6 +67,7 @@ + this.addSlot(new Slot(container, 0, 56, 17)); + this.addSlot(new FurnaceFuelSlot(this, container, 1, 56, 53)); + this.addSlot(new FurnaceResultSlot(playerInventory.player, container, 2, 116, 35)); ++ this.player = playerInventory; // CraftBukkit - save player + + for (int i = 0; i < 3; i++) { + for (int i1 = 0; i1 < 9; i1++) { +@@ -110,6 +125,7 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(player); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/AnvilMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/AnvilMenu.java.patch new file mode 100644 index 0000000000..85a10c1c6c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/AnvilMenu.java.patch @@ -0,0 +1,171 @@ +--- a/net/minecraft/world/inventory/AnvilMenu.java ++++ b/net/minecraft/world/inventory/AnvilMenu.java +@@ -20,6 +19,10 @@ + import net.minecraft.world.level.block.state.BlockState; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class AnvilMenu extends ItemCombinerMenu { + public static final int INPUT_SLOT = 0; + public static final int ADDITIONAL_SLOT = 1; +@@ -42,6 +46,11 @@ + private static final int ADDITIONAL_SLOT_X_PLACEMENT = 76; + private static final int RESULT_SLOT_X_PLACEMENT = 134; + private static final int SLOT_Y_PLACEMENT = 47; ++ // CraftBukkit start ++ public static final int DEFAULT_DENIED_COST = -1; ++ public int maximumRepairCost = 40; ++ private CraftInventoryView bukkitEntity; ++ // CraftBukkit end + + public AnvilMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, ContainerLevelAccess.NULL); +@@ -68,7 +78,7 @@ + + @Override + protected boolean mayPickup(Player player, boolean hasStack) { +- return (player.getAbilities().instabuild || player.experienceLevel >= this.cost.get()) && this.cost.get() > 0; ++ return (player.getAbilities().instabuild || player.experienceLevel >= this.cost.get()) && this.cost.get() > AnvilMenu.DEFAULT_DENIED_COST && hasStack; // CraftBukkit - allow cost 0 like a free item + } + + @Override +@@ -90,14 +101,16 @@ + this.inputSlots.setItem(1, ItemStack.EMPTY); + } + +- this.cost.set(0); +- this.access.execute((level, blockPos) -> { +- BlockState blockState = level.getBlockState(blockPos); +- if (!player.getAbilities().instabuild && blockState.is(BlockTags.ANVIL) && player.getRandom().nextFloat() < 0.12F) { +- BlockState blockState1 = AnvilBlock.damage(blockState); +- if (blockState1 == null) { +- level.removeBlock(blockPos, false); +- level.levelEvent(1029, blockPos, 0); ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item ++ this.access.execute((world, blockposition) -> { ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ ++ if (!player.getAbilities().instabuild && iblockdata.is(BlockTags.ANVIL) && player.getRandom().nextFloat() < 0.12F) { ++ IBlockData iblockdata1 = AnvilBlock.damage(iblockdata); ++ ++ if (iblockdata1 == null) { ++ world.removeBlock(blockposition, false); ++ world.levelEvent(1029, blockposition, 0); + } else { + level.setBlock(blockPos, blockState1, 2); + level.levelEvent(1030, blockPos, 0); +@@ -113,24 +128,29 @@ + ItemStack item = this.inputSlots.getItem(0); + this.cost.set(1); + int i = 0; +- int i1 = 0; +- int i2 = 0; +- if (item.isEmpty()) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- this.cost.set(0); ++ byte b0 = 0; ++ byte b1 = 0; ++ ++ if (itemstack.isEmpty()) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + } else { + ItemStack itemStack = item.copy(); + ItemStack item1 = this.inputSlots.getItem(1); + Map enchantments = EnchantmentHelper.getEnchantments(itemStack); + int var19 = i1 + item.getBaseRepairCost() + (item1.isEmpty() ? 0 : item1.getBaseRepairCost()); + this.repairItemCountCost = 0; +- if (!item1.isEmpty()) { +- boolean flag = item1.is(Items.ENCHANTED_BOOK) && !EnchantedBookItem.getEnchantments(item1).isEmpty(); +- if (itemStack.isDamageableItem() && itemStack.getItem().isValidRepairItem(item, item1)) { +- int min = Math.min(itemStack.getDamageValue(), itemStack.getMaxDamage() / 4); +- if (min <= 0) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- this.cost.set(0); ++ if (!itemstack2.isEmpty()) { ++ boolean flag = itemstack2.is(Items.ENCHANTED_BOOK) && !EnchantedBookItem.getEnchantments(itemstack2).isEmpty(); ++ int k; ++ int l; ++ int i1; ++ ++ if (itemstack1.isDamageableItem() && itemstack1.getItem().isValidRepairItem(itemstack, itemstack2)) { ++ k = Math.min(itemstack1.getDamageValue(), itemstack1.getMaxDamage() / 4); ++ if (k <= 0) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + return; + } + +@@ -144,9 +164,9 @@ + + this.repairItemCountCost = i3; + } else { +- if (!flag && (!itemStack.is(item1.getItem()) || !itemStack.isDamageableItem())) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- this.cost.set(0); ++ if (!flag && (!itemstack1.is(itemstack2.getItem()) || !itemstack1.isDamageableItem())) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + return; + } + +@@ -224,8 +255,8 @@ + } + + if (flag2 && !flag1) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- this.cost.set(0); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + return; + } + } +@@ -248,12 +279,12 @@ + itemStack = ItemStack.EMPTY; + } + +- if (i2 == i && i2 > 0 && this.cost.get() >= 40) { +- this.cost.set(39); ++ if (b1 == i && b1 > 0 && this.cost.get() >= maximumRepairCost) { // CraftBukkit ++ this.cost.set(maximumRepairCost - 1); // CraftBukkit + } + +- if (this.cost.get() >= 40 && !this.player.getAbilities().instabuild) { +- itemStack = ItemStack.EMPTY; ++ if (this.cost.get() >= maximumRepairCost && !this.player.getAbilities().instabuild) { // CraftBukkit ++ itemstack1 = ItemStack.EMPTY; + } + + if (!itemStack.isEmpty()) { +@@ -270,7 +302,8 @@ + EnchantmentHelper.setEnchantments(enchantments, itemStack); + } + +- this.resultSlots.setItem(0, itemStack); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), itemstack1); // CraftBukkit ++ sendAllDataToRemote(); // CraftBukkit - SPIGOT-6686: Always send completed inventory to stay in sync with client + this.broadcastChanges(); + } + } +@@ -308,4 +344,18 @@ + public int getCost() { + return this.cost.get(); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventory inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryAnvil( ++ access.getLocation(), this.inputSlots, this.resultSlots, this); ++ bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/BeaconMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/BeaconMenu.java.patch new file mode 100644 index 0000000000..1ff8b5d884 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/BeaconMenu.java.patch @@ -0,0 +1,67 @@ +--- a/net/minecraft/world/inventory/BeaconMenu.java ++++ b/net/minecraft/world/inventory/BeaconMenu.java +@@ -11,6 +12,8 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + + public class BeaconMenu extends AbstractContainerMenu { + private static final int PAYMENT_SLOT = 0; +@@ -35,6 +29,10 @@ + private final BeaconMenu.PaymentSlot paymentSlot; + private final ContainerLevelAccess access; + private final ContainerData beaconData; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ // CraftBukkit end + + public BeaconMenu(int containerId, Container container) { + this(containerId, container, new SimpleContainerData(3), ContainerLevelAccess.NULL); +@@ -42,6 +40,18 @@ + + public BeaconMenu(int containerId, Container container, ContainerData beaconData, ContainerLevelAccess access) { + super(MenuType.BEACON, containerId); ++ player = (Inventory) container; // CraftBukkit - TODO: check this ++ this.beacon = new SimpleContainer(1) { ++ @Override ++ public boolean canPlaceItem(int index, ItemStack stack) { ++ return stack.is(ItemTags.BEACON_PAYMENT_ITEMS); ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return 1; ++ } ++ }; + checkContainerDataCount(beaconData, 3); + this.beaconData = beaconData; + this.access = access; +@@ -75,6 +90,7 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.BEACON); + } + +@@ -180,4 +200,17 @@ + return 1; + } + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventory inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryBeacon(this.beacon); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/BrewingStandMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/BrewingStandMenu.java.patch new file mode 100644 index 0000000000..5e8cb51206 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/BrewingStandMenu.java.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/inventory/BrewingStandMenu.java ++++ b/net/minecraft/world/inventory/BrewingStandMenu.java +@@ -11,6 +12,10 @@ + import net.minecraft.world.item.alchemy.Potion; + import net.minecraft.world.item.alchemy.PotionBrewing; + import net.minecraft.world.item.alchemy.PotionUtils; ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryBrewer; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + + public class BrewingStandMenu extends AbstractContainerMenu { + private static final int BOTTLE_SLOT_START = 0; +@@ -27,12 +33,18 @@ + private final ContainerData brewingStandData; + private final Slot ingredientSlot; + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ // CraftBukkit end ++ + public BrewingStandMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, new SimpleContainer(5), new SimpleContainerData(2)); + } + + public BrewingStandMenu(int containerId, Inventory playerInventory, Container brewingStandContainer, ContainerData brewingStandData) { + super(MenuType.BREWING_STAND, containerId); ++ player = playerInventory; // CraftBukkit + checkContainerSize(brewingStandContainer, 5); + checkContainerDataCount(brewingStandData, 2); + this.brewingStand = brewingStandContainer; +@@ -57,6 +72,7 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.brewingStand.stillValid(player); + } + +@@ -184,8 +211,12 @@ + super.onTake(player, stack); + } + +- public static boolean mayPlaceItem(ItemStack stack) { +- return stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE); ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; + } + } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/CartographyTableMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/CartographyTableMenu.java.patch new file mode 100644 index 0000000000..e43bc7634d --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/CartographyTableMenu.java.patch @@ -0,0 +1,83 @@ +--- a/net/minecraft/world/inventory/CartographyTableMenu.java ++++ b/net/minecraft/world/inventory/CartographyTableMenu.java +@@ -13,8 +10,30 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.saveddata.maps.MapItemSavedData; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.inventory.CraftInventoryCartography; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class CartographyTableMenu extends AbstractContainerMenu { ++ ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryCartography inventory = new CraftInventoryCartography(this.container, this.resultContainer); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + public static final int MAP_SLOT = 0; + public static final int ADDITIONAL_SLOT = 1; + public static final int RESULT_SLOT = 2; +@@ -45,6 +52,34 @@ + + public CartographyTableMenu(int containerId, Inventory playerInventory, final ContainerLevelAccess access) { + super(MenuType.CARTOGRAPHY_TABLE, containerId); ++ this.container = new SimpleContainer(2) { ++ @Override ++ public void setChanged() { ++ CartographyTableMenu.this.slotsChanged(this); ++ super.setChanged(); ++ } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end ++ }; ++ this.resultContainer = new ResultContainer() { ++ @Override ++ public void setChanged() { ++ CartographyTableMenu.this.slotsChanged(this); ++ super.setChanged(); ++ } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end ++ }; + this.access = access; + this.addSlot(new Slot(this.container, 0, 15, 15) { + @Override +@@ -89,10 +128,13 @@ + for (int i = 0; i < 9; i++) { + this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142)); + } ++ ++ player = (Player) playerInventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.CARTOGRAPHY_TABLE); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/ChestMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/ChestMenu.java.patch new file mode 100644 index 0000000000..c65288c9f3 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/ChestMenu.java.patch @@ -0,0 +1,69 @@ +--- a/net/minecraft/world/inventory/ChestMenu.java ++++ b/net/minecraft/world/inventory/ChestMenu.java +@@ -5,12 +6,38 @@ + import net.minecraft.world.entity.player.Inventory; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + + public class ChestMenu extends AbstractContainerMenu { + private static final int SLOTS_PER_ROW = 9; + private final Container container; + private final int containerRows; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; + ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventory inventory; ++ if (this.container instanceof Inventory) { ++ inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryPlayer((Inventory) this.container); ++ } else if (this.container instanceof CompoundContainer) { ++ inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) this.container); ++ } else { ++ inventory = new CraftInventory(this.container); ++ } ++ ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end ++ + private ChestMenu(MenuType type, int containerId, Inventory playerInventory, int rows) { + this(type, containerId, playerInventory, new SimpleContainer(9 * rows), rows); + } +@@ -55,9 +83,16 @@ + container.startOpen(playerInventory.player); + int i = (this.containerRows - 4) * 18; + +- for (int i1 = 0; i1 < this.containerRows; i1++) { +- for (int i2 = 0; i2 < 9; i2++) { +- this.addSlot(new Slot(container, i2 + i1 * 9, 8 + i2 * 18, 18 + i1 * 18)); ++ // CraftBukkit start - Save player ++ this.player = playerInventory; ++ // CraftBukkit end ++ ++ int l; ++ int i1; ++ ++ for (l = 0; l < this.containerRows; ++l) { ++ for (i1 = 0; i1 < 9; ++i1) { ++ this.addSlot(new Slot(container, i1 + l * 9, 8 + i1 * 18, 18 + l * 18)); + } + } + +@@ -74,6 +110,7 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(player); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/ContainerLevelAccess.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/ContainerLevelAccess.java.patch new file mode 100644 index 0000000000..dce50df107 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/ContainerLevelAccess.java.patch @@ -0,0 +1,44 @@ +--- a/net/minecraft/world/inventory/ContainerLevelAccess.java ++++ b/net/minecraft/world/inventory/ContainerLevelAccess.java +@@ -7,6 +7,21 @@ + import net.minecraft.world.level.Level; + + public interface ContainerLevelAccess { ++ ++ // CraftBukkit start ++ default Level getWorld() { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ ++ default BlockPos getPosition() { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ ++ default org.bukkit.Location getLocation() { ++ return new org.bukkit.Location(getWorld().getWorld(), getPosition().getX(), getPosition().getY(), getPosition().getZ()); ++ } ++ // CraftBukkit end ++ + ContainerLevelAccess NULL = new ContainerLevelAccess() { + @Override + public Optional evaluate(BiFunction levelPosConsumer) { +@@ -16,7 +31,19 @@ + + static ContainerLevelAccess create(final Level level, final BlockPos pos) { + return new ContainerLevelAccess() { ++ // CraftBukkit start + @Override ++ public Level getWorld() { ++ return level; ++ } ++ ++ @Override ++ public BlockPos getPosition() { ++ return pos; ++ } ++ // CraftBukkit end ++ ++ @Override + public Optional evaluate(BiFunction levelPosConsumer) { + return Optional.of(levelPosConsumer.apply(level, pos)); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/CrafterMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/CrafterMenu.java.patch new file mode 100644 index 0000000000..13c60f6388 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/CrafterMenu.java.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/world/inventory/CrafterMenu.java ++++ b/net/minecraft/world/inventory/CrafterMenu.java +@@ -9,7 +8,27 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.CrafterBlock; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryCrafter; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class CrafterMenu extends AbstractContainerMenu implements ContainerListener { ++ ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryCrafter inventory = new CraftInventoryCrafter(this.container, this.resultContainer); ++ bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + protected static final int SLOT_COUNT = 9; + private static final int INV_SLOT_START = 9; + private static final int INV_SLOT_END = 36; +@@ -109,6 +135,7 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(player); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/CraftingMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/CraftingMenu.java.patch new file mode 100644 index 0000000000..168643e8b3 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/CraftingMenu.java.patch @@ -0,0 +1,75 @@ +--- a/net/minecraft/world/inventory/CraftingMenu.java ++++ b/net/minecraft/world/inventory/CraftingMenu.java +@@ -15,6 +15,9 @@ + import net.minecraft.world.item.crafting.RecipeType; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; ++import org.bukkit.craftbukkit.inventory.CraftInventoryCrafting; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + + public class CraftingMenu extends RecipeBookMenu { + public static final int RESULT_SLOT = 0; +@@ -24,10 +28,13 @@ + private static final int INV_SLOT_END = 37; + private static final int USE_ROW_SLOT_START = 37; + private static final int USE_ROW_SLOT_END = 46; +- private final CraftingContainer craftSlots = new TransientCraftingContainer(this, 3, 3); +- private final ResultContainer resultSlots = new ResultContainer(); +- private final ContainerLevelAccess access; ++ public final TransientCraftingContainer craftSlots; // CraftBukkit ++ public final ResultContainer resultSlots; ++ public final ContainerLevelAccess access; + private final Player player; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ // CraftBukkit end + + public CraftingMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, ContainerLevelAccess.NULL); +@@ -35,6 +42,11 @@ + + public CraftingMenu(int containerId, Inventory playerInventory, ContainerLevelAccess access) { + super(MenuType.CRAFTING, containerId); ++ // CraftBukkit start - Switched order of IInventory construction and stored player ++ this.resultSlots = new ResultContainer(); ++ this.craftSlots = new TransientCraftingContainer(this, 3, 3, playerInventory.player); // CraftBukkit - pass player ++ this.craftSlots.resultInventory = this.resultSlots; ++ // CraftBukkit end + this.access = access; + this.player = playerInventory.player; + this.addSlot(new ResultSlot(playerInventory.player, this.craftSlots, this.resultSlots, 0, 124, 35)); +@@ -71,6 +90,7 @@ + } + } + } ++ itemstack = org.bukkit.craftbukkit.event.CraftEventFactory.callPreCraftEvent(container, result, itemstack, menu.getBukkitView(), optional.map(RecipeHolder::toBukkitRecipe).orElse(null) instanceof RepairItemRecipe); // CraftBukkit + + result.setItem(0, itemStack); + menu.setRemoteSlot(0, itemStack); +@@ -107,6 +131,7 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.CRAFTING_TABLE); + } + +@@ -191,4 +220,17 @@ + public boolean shouldMoveToInventory(int slotIndex) { + return slotIndex != this.getResultSlotIndex(); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryCrafting inventory = new CraftInventoryCrafting(this.craftSlots, this.resultSlots); ++ bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/DispenserMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/DispenserMenu.java.patch new file mode 100644 index 0000000000..bf785b0632 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/DispenserMenu.java.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/world/inventory/DispenserMenu.java ++++ b/net/minecraft/world/inventory/DispenserMenu.java +@@ -6,13 +6,22 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class DispenserMenu extends AbstractContainerMenu { + private static final int SLOT_COUNT = 9; + private static final int INV_SLOT_START = 9; + private static final int INV_SLOT_END = 36; + private static final int USE_ROW_SLOT_START = 36; + private static final int USE_ROW_SLOT_END = 45; +- private final Container dispenser; ++ public final Container dispenser; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ // CraftBukkit end + + public DispenserMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, new SimpleContainer(9)); +@@ -20,6 +30,10 @@ + + public DispenserMenu(int containerId, Inventory playerInventory, Container container) { + super(MenuType.GENERIC_3x3, containerId); ++ // CraftBukkit start - Save player ++ this.player = playerInventory; ++ // CraftBukkit end ++ + checkContainerSize(container, 9); + this.dispenser = container; + container.startOpen(playerInventory.player); +@@ -43,6 +61,7 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.dispenser.stillValid(player); + } + +@@ -82,4 +103,17 @@ + super.removed(player); + this.dispenser.stopOpen(player); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventory inventory = new CraftInventory(this.dispenser); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/EnchantmentMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/EnchantmentMenu.java.patch new file mode 100644 index 0000000000..1a830e8631 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/EnchantmentMenu.java.patch @@ -0,0 +1,261 @@ +--- a/net/minecraft/world/inventory/EnchantmentMenu.java ++++ b/net/minecraft/world/inventory/EnchantmentMenu.java +@@ -25,6 +23,22 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.EnchantmentTableBlock; ++// CraftBukkit start ++import java.util.Map; ++import net.minecraft.world.item.enchantment.Enchantment; ++import net.minecraft.world.item.enchantment.EnchantmentHelper; ++import net.minecraft.world.item.enchantment.EnchantmentInstance; ++import org.bukkit.Location; ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftInventoryEnchanting; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.enchantments.EnchantmentOffer; ++import org.bukkit.event.enchantment.EnchantItemEvent; ++import org.bukkit.event.enchantment.PrepareItemEnchantEvent; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class EnchantmentMenu extends AbstractContainerMenu { + static final ResourceLocation EMPTY_SLOT_LAPIS_LAZULI = new ResourceLocation("item/empty_slot_lapis_lazuli"); +@@ -36,11 +45,15 @@ + } + }; + private final ContainerLevelAccess access; +- private final RandomSource random = RandomSource.create(); +- private final DataSlot enchantmentSeed = DataSlot.standalone(); +- public final int[] costs = new int[3]; +- public final int[] enchantClue = new int[]{-1, -1, -1}; +- public final int[] levelClue = new int[]{-1, -1, -1}; ++ private final RandomSource random; ++ private final DataSlot enchantmentSeed; ++ public final int[] costs; ++ public final int[] enchantClue; ++ public final int[] levelClue; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ // CraftBukkit end + + public EnchantmentMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, ContainerLevelAccess.NULL); +@@ -48,6 +61,25 @@ + + public EnchantmentMenu(int containerId, Inventory playerInventory, ContainerLevelAccess access) { + super(MenuType.ENCHANTMENT, containerId); ++ this.enchantSlots = new SimpleContainer(2) { ++ @Override ++ public void setChanged() { ++ super.setChanged(); ++ EnchantmentMenu.this.slotsChanged(this); ++ } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end ++ }; ++ this.random = RandomSource.create(); ++ this.enchantmentSeed = DataSlot.standalone(); ++ this.costs = new int[3]; ++ this.enchantClue = new int[]{-1, -1, -1}; ++ this.levelClue = new int[]{-1, -1, -1}; + this.access = access; + this.addSlot(new Slot(this.enchantSlots, 0, 15, 47) { + @Override +@@ -87,6 +121,9 @@ + this.addDataSlot(DataSlot.shared(this.levelClue, 0)); + this.addDataSlot(DataSlot.shared(this.levelClue, 1)); + this.addDataSlot(DataSlot.shared(this.levelClue, 2)); ++ // CraftBukkit start ++ player = (Player) playerInventory.player.getBukkitEntity(); ++ // CraftBukkit end + } + + @Override +@@ -97,9 +131,16 @@ + this.access.execute((level, blockPos) -> { + int i1 = 0; + +- for (BlockPos blockPos1 : EnchantmentTableBlock.BOOKSHELF_OFFSETS) { +- if (EnchantmentTableBlock.isValidBookShelf(level, blockPos, blockPos1)) { +- i1++; ++ if (!itemstack.isEmpty()) { // CraftBukkit - relax condition ++ this.access.execute((world, blockposition) -> { ++ int i = 0; ++ Iterator iterator = EnchantmentTableBlock.BOOKSHELF_OFFSETS.iterator(); ++ ++ while (iterator.hasNext()) { ++ BlockPos blockposition1 = (BlockPos) iterator.next(); ++ ++ if (EnchantmentTableBlock.isValidBookShelf(world, blockposition, blockposition1)) { ++ ++i; + } + } + +@@ -125,6 +170,41 @@ + } + } + ++ // CraftBukkit start ++ CraftItemStack item = CraftItemStack.asCraftMirror(itemstack); ++ org.bukkit.enchantments.EnchantmentOffer[] offers = new EnchantmentOffer[3]; ++ for (j = 0; j < 3; ++j) { ++ org.bukkit.enchantments.Enchantment enchantment = (this.enchantClue[j] >= 0) ? org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(BuiltInRegistries.ENCHANTMENT.byId(this.enchantClue[j])))) : null; ++ offers[j] = (enchantment != null) ? new EnchantmentOffer(enchantment, this.levelClue[j], this.costs[j]) : null; ++ } ++ ++ PrepareItemEnchantEvent event = new PrepareItemEnchantEvent(player, this.getBukkitView(), access.getLocation().getBlock(), item, offers, i); ++ event.setCancelled(!itemstack.isEnchantable()); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ for (j = 0; j < 3; ++j) { ++ this.costs[j] = 0; ++ this.enchantClue[j] = -1; ++ this.levelClue[j] = -1; ++ } ++ return; ++ } ++ ++ for (j = 0; j < 3; j++) { ++ EnchantmentOffer offer = event.getOffers()[j]; ++ if (offer != null) { ++ this.costs[j] = offer.getCost(); ++ this.enchantClue[j] = BuiltInRegistries.ENCHANTMENT.getId(BuiltInRegistries.ENCHANTMENT.get(CraftNamespacedKey.toMinecraft(offer.getEnchantment().getKey()))); ++ this.levelClue[j] = offer.getEnchantmentLevel(); ++ } else { ++ this.costs[j] = 0; ++ this.enchantClue[j] = -1; ++ this.levelClue[j] = -1; ++ } ++ } ++ // CraftBukkit end ++ + this.broadcastChanges(); + }); + } else { +@@ -145,35 +227,67 @@ + int i = id + 1; + if ((item1.isEmpty() || item1.getCount() < i) && !player.getAbilities().instabuild) { + return false; +- } else if (this.costs[id] <= 0 +- || item.isEmpty() +- || (player.experienceLevel < i || player.experienceLevel < this.costs[id]) && !player.getAbilities().instabuild) { +- return false; +- } else { +- this.access.execute((level, blockPos) -> { +- ItemStack itemStack = item; +- List enchantmentList = this.getEnchantmentList(item, id, this.costs[id]); +- if (!enchantmentList.isEmpty()) { +- player.onEnchantmentPerformed(item, i); +- boolean isBook = item.is(Items.BOOK); +- if (isBook) { +- itemStack = new ItemStack(Items.ENCHANTED_BOOK); +- CompoundTag tag = item.getTag(); +- if (tag != null) { +- itemStack.setTag(tag.copy()); ++ } else if (this.costs[id] > 0 && !itemstack.isEmpty() && (player.experienceLevel >= j && player.experienceLevel >= this.costs[id] || player.getAbilities().instabuild)) { ++ this.access.execute((world, blockposition) -> { ++ ItemStack itemstack2 = itemstack; ++ List list = this.getEnchantmentList(itemstack, id, this.costs[id]); ++ ++ // CraftBukkit start ++ if (true || !list.isEmpty()) { ++ // entityhuman.onEnchantmentPerformed(itemstack, j); // Moved down ++ Map enchants = new java.util.HashMap(); ++ for (EnchantmentInstance instance : list) { ++ enchants.put(org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(instance.enchantment))), instance.level); ++ } ++ CraftItemStack item = CraftItemStack.asCraftMirror(itemstack2); ++ ++ org.bukkit.enchantments.Enchantment hintedEnchantment = org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(Enchantment.byId(enchantClue[id])))); ++ int hintedEnchantmentLevel = levelClue[id]; ++ EnchantItemEvent event = new EnchantItemEvent((Player) player.getBukkitEntity(), this.getBukkitView(), access.getLocation().getBlock(), item, this.costs[id], enchants, hintedEnchantment, hintedEnchantmentLevel, id); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ int level = event.getExpLevelCost(); ++ if (event.isCancelled() || (level > player.experienceLevel && !player.getAbilities().instabuild) || event.getEnchantsToAdd().isEmpty()) { ++ return; ++ } ++ // CraftBukkit end ++ boolean flag = itemstack.is(Items.BOOK); ++ ++ if (flag) { ++ itemstack2 = new ItemStack(Items.ENCHANTED_BOOK); ++ CompoundTag nbttagcompound = itemstack.getTag(); ++ ++ if (nbttagcompound != null) { ++ itemstack2.setTag(nbttagcompound.copy()); + } + + this.enchantSlots.setItem(0, itemStack); + } + +- for (EnchantmentInstance enchantmentInstance : enchantmentList) { +- if (isBook) { +- EnchantedBookItem.addEnchantment(itemStack, enchantmentInstance); +- } else { +- itemStack.enchant(enchantmentInstance.enchantment, enchantmentInstance.level); ++ // CraftBukkit start ++ for (Map.Entry entry : event.getEnchantsToAdd().entrySet()) { ++ try { ++ if (flag) { ++ NamespacedKey enchantId = entry.getKey().getKey(); ++ Enchantment nms = BuiltInRegistries.ENCHANTMENT.get(CraftNamespacedKey.toMinecraft(enchantId)); ++ if (nms == null) { ++ continue; ++ } ++ ++ EnchantmentInstance weightedrandomenchant = new EnchantmentInstance(nms, entry.getValue()); ++ EnchantedBookItem.addEnchantment(itemstack2, weightedrandomenchant); ++ } else { ++ item.addUnsafeEnchantment(entry.getKey(), entry.getValue()); ++ } ++ } catch (IllegalArgumentException e) { ++ /* Just swallow invalid enchantments */ + } + } + ++ player.onEnchantmentPerformed(itemstack, j); ++ // CraftBukkit end ++ ++ // CraftBukkit - TODO: let plugins change this + if (!player.getAbilities().instabuild) { + item1.shrink(i); + if (item1.isEmpty()) { +@@ -226,7 +349,8 @@ + } + + @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.ENCHANTING_TABLE); + } + +@@ -274,4 +401,17 @@ + + return itemStack; + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryEnchanting inventory = new CraftInventoryEnchanting(this.enchantSlots); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/FurnaceResultSlot.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/FurnaceResultSlot.java.patch new file mode 100644 index 0000000000..4eb56f49d4 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/FurnaceResultSlot.java.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/inventory/FurnaceResultSlot.java ++++ b/net/minecraft/world/inventory/FurnaceResultSlot.java +@@ -44,8 +45,17 @@ + @Override + protected void checkTakeAchievements(ItemStack stack) { + stack.onCraftedBy(this.player.level(), this.player, this.removeCount); +- if (this.player instanceof ServerPlayer serverPlayer && this.container instanceof AbstractFurnaceBlockEntity abstractFurnaceBlockEntity) { +- abstractFurnaceBlockEntity.awardUsedRecipesAndPopExperience(serverPlayer); ++ Player entityhuman = this.player; ++ ++ if (entityhuman instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entityhuman; ++ Container iinventory = this.container; ++ ++ if (iinventory instanceof AbstractFurnaceBlockEntity) { ++ AbstractFurnaceBlockEntity tileentityfurnace = (AbstractFurnaceBlockEntity) iinventory; ++ ++ tileentityfurnace.awardUsedRecipesAndPopExperience(entityplayer, stack, this.removeCount); // CraftBukkit ++ } + } + + this.removeCount = 0; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/GrindstoneMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/GrindstoneMenu.java.patch new file mode 100644 index 0000000000..948728da0b --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/GrindstoneMenu.java.patch @@ -0,0 +1,153 @@ +--- a/net/minecraft/world/inventory/GrindstoneMenu.java ++++ b/net/minecraft/world/inventory/GrindstoneMenu.java +@@ -18,8 +17,30 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.inventory.CraftInventoryGrindstone; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class GrindstoneMenu extends AbstractContainerMenu { ++ ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryGrindstone inventory = new CraftInventoryGrindstone(this.repairSlots, this.resultSlots); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + public static final int MAX_NAME_LENGTH = 35; + public static final int INPUT_SLOT = 0; + public static final int ADDITIONAL_SLOT = 1; +@@ -44,6 +59,21 @@ + + public GrindstoneMenu(int containerId, Inventory playerInventory, final ContainerLevelAccess access) { + super(MenuType.GRINDSTONE, containerId); ++ this.resultSlots = new ResultContainer(); ++ this.repairSlots = new SimpleContainer(2) { ++ @Override ++ public void setChanged() { ++ super.setChanged(); ++ GrindstoneMenu.this.slotsChanged(this); ++ } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end ++ }; + this.access = access; + this.addSlot(new Slot(this.repairSlots, 0, 49, 19) { + @Override +@@ -113,6 +150,8 @@ + for (int i = 0; i < 9; i++) { + this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142)); + } ++ ++ player = (Player) playerInventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override +@@ -124,17 +164,16 @@ + } + + private void createResult() { +- ItemStack item = this.repairSlots.getItem(0); +- ItemStack item1 = this.repairSlots.getItem(1); +- boolean flag = !item.isEmpty() || !item1.isEmpty(); +- boolean flag1 = !item.isEmpty() && !item1.isEmpty(); +- if (!flag) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- } else { +- boolean flag2 = !item.isEmpty() && !item.is(Items.ENCHANTED_BOOK) && !item.isEnchanted() +- || !item1.isEmpty() && !item1.is(Items.ENCHANTED_BOOK) && !item1.isEnchanted(); +- if (item.getCount() > 1 || item1.getCount() > 1 || !flag1 && flag2) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ ItemStack itemstack = this.repairSlots.getItem(0); ++ ItemStack itemstack1 = this.repairSlots.getItem(1); ++ boolean flag = !itemstack.isEmpty() || !itemstack1.isEmpty(); ++ boolean flag1 = !itemstack.isEmpty() && !itemstack1.isEmpty(); ++ ++ if (flag) { ++ boolean flag2 = !itemstack.isEmpty() && !itemstack.is(Items.ENCHANTED_BOOK) && !itemstack.isEnchanted() || !itemstack1.isEmpty() && !itemstack1.is(Items.ENCHANTED_BOOK) && !itemstack1.isEnchanted(); ++ ++ if (itemstack.getCount() > 1 || itemstack1.getCount() > 1 || !flag1 && flag2) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + this.broadcastChanges(); + return; + } +@@ -143,21 +183,22 @@ + int max; + ItemStack itemStack; + if (flag1) { +- if (!item.is(item1.getItem())) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ if (!itemstack.is(itemstack1.getItem())) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + this.broadcastChanges(); + return; + } + +- Item item2 = item.getItem(); +- int i1 = item2.getMaxDamage() - item.getDamageValue(); +- int i2 = item2.getMaxDamage() - item1.getDamageValue(); +- int i3 = i1 + i2 + item2.getMaxDamage() * 5 / 100; +- max = Math.max(item2.getMaxDamage() - i3, 0); +- itemStack = this.mergeEnchants(item, item1); +- if (!itemStack.isDamageableItem()) { +- if (!ItemStack.matches(item, item1)) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ Item item = itemstack.getItem(); ++ int j = item.getMaxDamage() - itemstack.getDamageValue(); ++ int k = item.getMaxDamage() - itemstack1.getDamageValue(); ++ int l = j + k + item.getMaxDamage() * 5 / 100; ++ ++ i = Math.max(item.getMaxDamage() - l, 0); ++ itemstack2 = this.mergeEnchants(itemstack, itemstack1); ++ if (!itemstack2.isDamageableItem()) { ++ if (!ItemStack.matches(itemstack, itemstack1)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + this.broadcastChanges(); + return; + } +@@ -170,9 +208,15 @@ + itemStack = flag3 ? item : item1; + } + +- this.resultSlots.setItem(0, this.removeNonCurses(itemStack, max, i)); ++ i = flag3 ? itemstack.getDamageValue() : itemstack1.getDamageValue(); ++ itemstack2 = flag3 ? itemstack : itemstack1; ++ } ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), this.removeNonCurses(itemstack2, i, b0)); // CraftBukkit ++ } else { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + } + ++ sendAllDataToRemote(); // CraftBukkit - SPIGOT-6686: Always send completed inventory to stay in sync with client + this.broadcastChanges(); + } + +@@ -228,7 +277,8 @@ + } + + @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.GRINDSTONE); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/HopperMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/HopperMenu.java.patch new file mode 100644 index 0000000000..457749fe53 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/HopperMenu.java.patch @@ -0,0 +1,50 @@ +--- a/net/minecraft/world/inventory/HopperMenu.java ++++ b/net/minecraft/world/inventory/HopperMenu.java +@@ -6,10 +6,31 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class HopperMenu extends AbstractContainerMenu { + public static final int CONTAINER_SIZE = 5; + private final Container hopper; + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventory inventory = new CraftInventory(this.hopper); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end ++ + public HopperMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, new SimpleContainer(5)); + } +@@ -17,6 +39,7 @@ + public HopperMenu(int containerId, Inventory playerInventory, Container container) { + super(MenuType.HOPPER, containerId); + this.hopper = container; ++ this.player = playerInventory; // CraftBukkit - save player + checkContainerSize(container, 5); + container.startOpen(playerInventory.player); + int i = 51; +@@ -38,6 +64,7 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.hopper.stillValid(player); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/HorseInventoryMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/HorseInventoryMenu.java.patch new file mode 100644 index 0000000000..019a6bc21f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/HorseInventoryMenu.java.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/world/inventory/HorseInventoryMenu.java ++++ b/net/minecraft/world/inventory/HorseInventoryMenu.java +@@ -8,12 +8,32 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.inventory.InventoryView; ++// CraftBukkit end ++ + public class HorseInventoryMenu extends AbstractContainerMenu { + private final Container horseContainer; + private final AbstractHorse horse; + ++ // CraftBukkit start ++ org.bukkit.craftbukkit.inventory.CraftInventoryView bukkitEntity; ++ Inventory player; ++ ++ @Override ++ public InventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ return bukkitEntity = new CraftInventoryView(player.player.getBukkitEntity(), horseContainer.getOwner().getInventory(), this); ++ } ++ + public HorseInventoryMenu(int containerId, Inventory playerInventory, Container container, final AbstractHorse horse) { +- super(null, containerId); ++ super((MenuType) null, containerId); ++ player = playerInventory; ++ // CraftBukkit end + this.horseContainer = container; + this.horse = horse; + int i = 3; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/InventoryMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/InventoryMenu.java.patch new file mode 100644 index 0000000000..e8bd160dfb --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/InventoryMenu.java.patch @@ -0,0 +1,61 @@ +--- a/net/minecraft/world/inventory/InventoryMenu.java ++++ b/net/minecraft/world/inventory/InventoryMenu.java +@@ -12,6 +13,9 @@ + import net.minecraft.world.item.crafting.Recipe; + import net.minecraft.world.item.crafting.RecipeHolder; + import net.minecraft.world.item.enchantment.EnchantmentHelper; ++import org.bukkit.craftbukkit.inventory.CraftInventoryCrafting; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + + public class InventoryMenu extends RecipeBookMenu { + public static final int CONTAINER_ID = 0; +@@ -35,15 +38,28 @@ + EMPTY_ARMOR_SLOT_BOOTS, EMPTY_ARMOR_SLOT_LEGGINGS, EMPTY_ARMOR_SLOT_CHESTPLATE, EMPTY_ARMOR_SLOT_HELMET + }; + private static final EquipmentSlot[] SLOT_IDS = new EquipmentSlot[]{EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET}; +- private final CraftingContainer craftSlots = new TransientCraftingContainer(this, 2, 2); +- private final ResultContainer resultSlots = new ResultContainer(); ++ // CraftBukkit start ++ private final TransientCraftingContainer craftSlots; ++ private final ResultContainer resultSlots; ++ // CraftBukkit end + public final boolean active; + private final Player owner; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ // CraftBukkit end + + public InventoryMenu(Inventory playerInventory, boolean active, final Player owner) { + super(null, 0); + this.active = active; + this.owner = owner; ++ // CraftBukkit start ++ this.resultSlots = new ResultContainer(); // CraftBukkit - moved to before InventoryCrafting construction ++ this.craftSlots = new TransientCraftingContainer(this, 2, 2, playerInventory.player); // CraftBukkit - pass player ++ this.craftSlots.resultInventory = this.resultSlots; // CraftBukkit - let InventoryCrafting know about its result slot ++ this.player = playerInventory; // CraftBukkit - save player ++ setTitle(Component.translatable("container.crafting")); // SPIGOT-4722: Allocate title for player inventory ++ // CraftBukkit end + this.addSlot(new ResultSlot(playerInventory.player, this.craftSlots, this.resultSlots, 0, 154, 28)); + + for (int i = 0; i < 2; i++) { +@@ -251,4 +276,17 @@ + public boolean shouldMoveToInventory(int slotIndex) { + return slotIndex != this.getResultSlotIndex(); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryCrafting inventory = new CraftInventoryCrafting(this.craftSlots, this.resultSlots); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/ItemCombinerMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/ItemCombinerMenu.java.patch new file mode 100644 index 0000000000..87031d2383 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/ItemCombinerMenu.java.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/inventory/ItemCombinerMenu.java ++++ b/net/minecraft/world/inventory/ItemCombinerMenu.java +@@ -114,13 +124,10 @@ + + @Override + public boolean stillValid(Player player) { +- return this.access +- .evaluate( +- (level, blockPos) -> !this.isValidBlock(level.getBlockState(blockPos)) +- ? false +- : player.distanceToSqr((double)blockPos.getX() + 0.5, (double)blockPos.getY() + 0.5, (double)blockPos.getZ() + 0.5) <= 64.0, +- true +- ); ++ if (!this.checkReachable) return true; // CraftBukkit ++ return (Boolean) this.access.evaluate((world, blockposition) -> { ++ return !this.isValidBlock(world.getBlockState(blockposition)) ? false : player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) <= 64.0D; ++ }, true); + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/LecternMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/LecternMenu.java.patch new file mode 100644 index 0000000000..51e9a044f2 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/LecternMenu.java.patch @@ -0,0 +1,100 @@ +--- a/net/minecraft/world/inventory/LecternMenu.java ++++ b/net/minecraft/world/inventory/LecternMenu.java +@@ -4,8 +4,31 @@ + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.level.block.entity.LecternBlockEntity.LecternInventory; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.inventory.CraftInventoryLectern; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerTakeLecternBookEvent; ++// CraftBukkit end + + public class LecternMenu extends AbstractContainerMenu { ++ ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryLectern inventory = new CraftInventoryLectern(this.lectern); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + private static final int DATA_COUNT = 1; + private static final int SLOT_COUNT = 1; + public static final int BUTTON_PREV_PAGE = 1; +@@ -15,24 +38,27 @@ + private final Container lectern; + private final ContainerData lecternData; + +- public LecternMenu(int containerId) { +- this(containerId, new SimpleContainer(1), new SimpleContainerData(1)); ++ // CraftBukkit start - add player ++ public LecternMenu(int i, Inventory playerinventory) { ++ this(i, new SimpleContainer(1), new SimpleContainerData(1), playerinventory); + } + +- public LecternMenu(int containerId, Container lectern, ContainerData lecternData) { +- super(MenuType.LECTERN, containerId); +- checkContainerSize(lectern, 1); +- checkContainerDataCount(lecternData, 1); +- this.lectern = lectern; +- this.lecternData = lecternData; +- this.addSlot(new Slot(lectern, 0, 0, 0) { ++ public LecternMenu(int i, Container iinventory, ContainerData icontainerproperties, Inventory playerinventory) { ++ // CraftBukkit end ++ super(MenuType.LECTERN, i); ++ checkContainerSize(iinventory, 1); ++ checkContainerDataCount(icontainerproperties, 1); ++ this.lectern = iinventory; ++ this.lecternData = icontainerproperties; ++ this.addSlot(new Slot(iinventory, 0, 0, 0) { + @Override + public void setChanged() { + super.setChanged(); + LecternMenu.this.slotsChanged(this.container); + } + }); +- this.addDataSlots(lecternData); ++ this.addDataSlots(icontainerproperties); ++ player = (Player) playerinventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override +@@ -58,7 +84,15 @@ + return false; + } + +- ItemStack itemStack = this.lectern.removeItemNoUpdate(0); ++ // CraftBukkit start - Event for taking the book ++ PlayerTakeLecternBookEvent event = new PlayerTakeLecternBookEvent(player, ((CraftInventoryLectern) getBukkitView().getTopInventory()).getHolder()); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ ItemStack itemstack = this.lectern.removeItemNoUpdate(0); ++ + this.lectern.setChanged(); + if (!player.getInventory().add(itemStack)) { + player.drop(itemStack, false); +@@ -83,7 +117,9 @@ + } + + @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (lectern instanceof LecternInventory && !((LecternInventory) lectern).getLectern().hasBook()) return false; // CraftBukkit ++ if (!this.checkReachable) return true; // CraftBukkit + return this.lectern.stillValid(player); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/LoomMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/LoomMenu.java.patch new file mode 100644 index 0000000000..0fa04cefb8 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/LoomMenu.java.patch @@ -0,0 +1,121 @@ +--- a/net/minecraft/world/inventory/LoomMenu.java ++++ b/net/minecraft/world/inventory/LoomMenu.java +@@ -24,8 +22,30 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.BannerPattern; + import net.minecraft.world.level.block.entity.BlockEntityType; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.inventory.CraftInventoryLoom; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class LoomMenu extends AbstractContainerMenu { ++ ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryLoom inventory = new CraftInventoryLoom(this.inputContainer, this.outputContainer); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + private static final int PATTERN_NOT_SET = -1; + private static final int INV_SLOT_START = 4; + private static final int INV_SLOT_END = 31; +@@ -63,6 +69,39 @@ + + public LoomMenu(int containerId, Inventory playerInventory, final ContainerLevelAccess access) { + super(MenuType.LOOM, containerId); ++ this.selectedBannerPatternIndex = DataSlot.standalone(); ++ this.selectablePatterns = List.of(); ++ this.slotUpdateListener = () -> { ++ }; ++ this.inputContainer = new SimpleContainer(3) { ++ @Override ++ public void setChanged() { ++ super.setChanged(); ++ LoomMenu.this.slotsChanged(this); ++ LoomMenu.this.slotUpdateListener.run(); ++ } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end ++ }; ++ this.outputContainer = new SimpleContainer(1) { ++ @Override ++ public void setChanged() { ++ super.setChanged(); ++ LoomMenu.this.slotUpdateListener.run(); ++ } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end ++ }; + this.access = access; + this.bannerSlot = this.addSlot(new Slot(this.inputContainer, 0, 13, 26) { + @Override +@@ -118,10 +161,12 @@ + } + + this.addDataSlot(this.selectedBannerPatternIndex); ++ player = (Player) playerInventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.LOOM); + } + +@@ -275,16 +332,23 @@ + } + + private void setupResultSlot(Holder pattern) { +- ItemStack item = this.bannerSlot.getItem(); +- ItemStack item1 = this.dyeSlot.getItem(); +- ItemStack itemStack = ItemStack.EMPTY; +- if (!item.isEmpty() && !item1.isEmpty()) { +- itemStack = item.copyWithCount(1); +- DyeColor dyeColor = ((DyeItem)item1.getItem()).getDyeColor(); +- CompoundTag blockEntityData = BlockItem.getBlockEntityData(itemStack); +- ListTag list; +- if (blockEntityData != null && blockEntityData.contains("Patterns", 9)) { +- list = blockEntityData.getList("Patterns", 10); ++ ItemStack itemstack = this.bannerSlot.getItem(); ++ ItemStack itemstack1 = this.dyeSlot.getItem(); ++ ItemStack itemstack2 = ItemStack.EMPTY; ++ ++ if (!itemstack.isEmpty() && !itemstack1.isEmpty()) { ++ itemstack2 = itemstack.copyWithCount(1); ++ DyeColor enumcolor = ((DyeItem) itemstack1.getItem()).getDyeColor(); ++ CompoundTag nbttagcompound = BlockItem.getBlockEntityData(itemstack2); ++ ListTag nbttaglist; ++ ++ if (nbttagcompound != null && nbttagcompound.contains("Patterns", 9)) { ++ nbttaglist = nbttagcompound.getList("Patterns", 10); ++ // CraftBukkit start ++ while (nbttaglist.size() > 20) { ++ nbttaglist.remove(20); ++ } ++ // CraftBukkit end + } else { + list = new ListTag(); + if (blockEntityData == null) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/MenuType.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/MenuType.java.patch new file mode 100644 index 0000000000..2b0f95c21c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/MenuType.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/inventory/MenuType.java ++++ b/net/minecraft/world/inventory/MenuType.java +@@ -26,7 +27,9 @@ + public static final MenuType FURNACE = register("furnace", FurnaceMenu::new); + public static final MenuType GRINDSTONE = register("grindstone", GrindstoneMenu::new); + public static final MenuType HOPPER = register("hopper", HopperMenu::new); +- public static final MenuType LECTERN = register("lectern", (containerId, playerInventory) -> new LecternMenu(containerId)); ++ public static final MenuType LECTERN = register("lectern", (i, playerinventory) -> { ++ return new LecternMenu(i, playerinventory); // CraftBukkit ++ }); + public static final MenuType LOOM = register("loom", LoomMenu::new); + public static final MenuType MERCHANT = register("merchant", MerchantMenu::new); + public static final MenuType SHULKER_BOX = register("shulker_box", ShulkerBoxMenu::new); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/MerchantContainer.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/MerchantContainer.java.patch new file mode 100644 index 0000000000..b4ca78ad64 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/MerchantContainer.java.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/world/inventory/MerchantContainer.java ++++ b/net/minecraft/world/inventory/MerchantContainer.java +@@ -9,6 +12,13 @@ + import net.minecraft.world.item.trading.Merchant; + import net.minecraft.world.item.trading.MerchantOffer; + import net.minecraft.world.item.trading.MerchantOffers; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.entity.CraftAbstractVillager; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end + + public class MerchantContainer implements Container { + private final Merchant merchant; +@@ -18,6 +29,46 @@ + private int selectionHint; + private int futureXp; + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.itemStacks; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ merchant.setTradingPlayer((Player) null); // SPIGOT-4860 ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return (merchant instanceof AbstractVillager) ? (CraftAbstractVillager) ((AbstractVillager) this.merchant).getBukkitEntity() : null; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return (merchant instanceof Villager) ? ((Villager) this.merchant).getBukkitEntity().getLocation() : null; ++ } ++ // CraftBukkit end ++ + public MerchantContainer(Merchant merchant) { + this.merchant = merchant; + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/MerchantMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/MerchantMenu.java.patch new file mode 100644 index 0000000000..db2427ffea --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/MerchantMenu.java.patch @@ -0,0 +1,53 @@ +--- a/net/minecraft/world/inventory/MerchantMenu.java ++++ b/net/minecraft/world/inventory/MerchantMenu.java +@@ -10,6 +11,7 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.trading.Merchant; + import net.minecraft.world.item.trading.MerchantOffers; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; // CraftBukkit + + public class MerchantMenu extends AbstractContainerMenu { + protected static final int PAYMENT1_SLOT = 0; +@@ -29,6 +32,19 @@ + private boolean showProgressBar; + private boolean canRestock; + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity == null) { ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), new org.bukkit.craftbukkit.inventory.CraftInventoryMerchant(trader, tradeContainer), this); ++ } ++ return bukkitEntity; ++ } ++ // CraftBukkit end ++ + public MerchantMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, new ClientSideMerchant(playerInventory.player)); + } +@@ -40,6 +56,7 @@ + this.addSlot(new Slot(this.tradeContainer, 0, 136, 37)); + this.addSlot(new Slot(this.tradeContainer, 1, 162, 37)); + this.addSlot(new MerchantResultSlot(playerInventory.player, trader, this.tradeContainer, 2, 220, 37)); ++ this.player = playerInventory; // CraftBukkit - save player + + for (int i = 0; i < 3; i++) { + for (int i1 = 0; i1 < 9; i1++) { +@@ -147,10 +169,10 @@ + } + + private void playTradeSound() { +- if (!this.trader.isClientSide()) { +- Entity entity = (Entity)this.trader; +- entity.level() +- .playLocalSound(entity.getX(), entity.getY(), entity.getZ(), this.trader.getNotifyTradeSound(), SoundSource.NEUTRAL, 1.0F, 1.0F, false); ++ if (!this.trader.isClientSide() && this.trader instanceof Entity) { // CraftBukkit - SPIGOT-5035 ++ Entity entity = (Entity) this.trader; ++ ++ entity.level().playLocalSound(entity.getX(), entity.getY(), entity.getZ(), this.trader.getNotifyTradeSound(), SoundSource.NEUTRAL, 1.0F, 1.0F, false); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/PlayerEnderChestContainer.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/PlayerEnderChestContainer.java.patch new file mode 100644 index 0000000000..e8a784f511 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/PlayerEnderChestContainer.java.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/world/inventory/PlayerEnderChestContainer.java ++++ b/net/minecraft/world/inventory/PlayerEnderChestContainer.java +@@ -7,13 +7,22 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.entity.EnderChestBlockEntity; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end + + public class PlayerEnderChestContainer extends SimpleContainer { + @Nullable + private EnderChestBlockEntity activeChest; ++ // CraftBukkit start ++ private final Player owner; + + public PlayerEnderChestContainer() { + super(27); ++ this.owner = owner; ++ // CraftBukkit end + } + + public void setActiveChest(EnderChestBlockEntity enderChestBlockEntity) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/ResultContainer.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/ResultContainer.java.patch new file mode 100644 index 0000000000..1a0059accf --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/ResultContainer.java.patch @@ -0,0 +1,58 @@ +--- a/net/minecraft/world/inventory/ResultContainer.java ++++ b/net/minecraft/world/inventory/ResultContainer.java +@@ -8,12 +9,55 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.crafting.RecipeHolder; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class ResultContainer implements Container, RecipeCraftingHolder { + private final NonNullList itemStacks = NonNullList.withSize(1, ItemStack.EMPTY); + @Nullable + private RecipeHolder recipeUsed; + ++ // CraftBukkit start ++ private int maxStack = MAX_STACK; ++ ++ public java.util.List getContents() { ++ return this.itemStacks; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return null; // Result slots don't get an owner ++ } ++ ++ // Don't need a transaction; the InventoryCrafting keeps track of it for us ++ public void onOpen(CraftHumanEntity who) {} ++ public void onClose(CraftHumanEntity who) {} ++ public java.util.List getViewers() { ++ return new java.util.ArrayList(); ++ } ++ + @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return null; ++ } ++ // CraftBukkit end ++ ++ public ResultContainer() { ++ this.itemStacks = NonNullList.withSize(1, ItemStack.EMPTY); ++ } ++ ++ @Override + public int getContainerSize() { + return 1; + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/ShulkerBoxMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/ShulkerBoxMenu.java.patch new file mode 100644 index 0000000000..256b91aa07 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/ShulkerBoxMenu.java.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/world/inventory/ShulkerBoxMenu.java ++++ b/net/minecraft/world/inventory/ShulkerBoxMenu.java +@@ -6,10 +6,29 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class ShulkerBoxMenu extends AbstractContainerMenu { + private static final int CONTAINER_SIZE = 27; + private final Container container; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity; ++ private Inventory player; + ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), new CraftInventory(this.container), this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end ++ + public ShulkerBoxMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, new SimpleContainer(27)); + } +@@ -18,6 +38,7 @@ + super(MenuType.SHULKER_BOX, containerId); + checkContainerSize(container, 27); + this.container = container; ++ this.player = playerInventory; // CraftBukkit - save player + container.startOpen(playerInventory.player); + int i = 3; + int i1 = 9; +@@ -41,6 +66,7 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(player); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/SmithingMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/SmithingMenu.java.patch new file mode 100644 index 0000000000..7360f102ae --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/SmithingMenu.java.patch @@ -0,0 +1,70 @@ +--- a/net/minecraft/world/inventory/SmithingMenu.java ++++ b/net/minecraft/world/inventory/SmithingMenu.java +@@ -14,6 +13,8 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; + ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; // CraftBukkit ++ + public class SmithingMenu extends ItemCombinerMenu { + public static final int TEMPLATE_SLOT = 0; + public static final int BASE_SLOT = 1; +@@ -28,6 +30,9 @@ + @Nullable + private RecipeHolder selectedRecipe; + private final List> recipes; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity; ++ // CraftBukkit end + + public SmithingMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, ContainerLevelAccess.NULL); +@@ -83,16 +99,20 @@ + + @Override + public void createResult() { +- List> recipesFor = this.level.getRecipeManager().getRecipesFor(RecipeType.SMITHING, this.inputSlots, this.level); +- if (recipesFor.isEmpty()) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ List> list = this.level.getRecipeManager().getRecipesFor(RecipeType.SMITHING, this.inputSlots, this.level); ++ ++ if (list.isEmpty()) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareSmithingEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + } else { +- RecipeHolder recipeHolder = recipesFor.get(0); +- ItemStack itemStack = recipeHolder.value().assemble(this.inputSlots, this.level.registryAccess()); +- if (itemStack.isItemEnabled(this.level.enabledFeatures())) { +- this.selectedRecipe = recipeHolder; +- this.resultSlots.setRecipeUsed(recipeHolder); +- this.resultSlots.setItem(0, itemStack); ++ RecipeHolder recipeholder = (RecipeHolder) list.get(0); ++ ItemStack itemstack = ((SmithingRecipe) recipeholder.value()).assemble(this.inputSlots, this.level.registryAccess()); ++ ++ if (itemstack.isItemEnabled(this.level.enabledFeatures())) { ++ this.selectedRecipe = recipeholder; ++ this.resultSlots.setRecipeUsed(recipeholder); ++ // CraftBukkit start ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareSmithingEvent(getBukkitView(), itemstack); ++ // CraftBukkit end + } + } + } +@@ -129,4 +144,18 @@ + .filter(i -> !this.getSlot(i).hasItem()) + .findFirst(); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventory inventory = new org.bukkit.craftbukkit.inventory.CraftInventorySmithing( ++ access.getLocation(), this.inputSlots, this.resultSlots); ++ bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/StonecutterMenu.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/StonecutterMenu.java.patch new file mode 100644 index 0000000000..8e7c6ff799 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/StonecutterMenu.java.patch @@ -0,0 +1,97 @@ +--- a/net/minecraft/world/inventory/StonecutterMenu.java ++++ b/net/minecraft/world/inventory/StonecutterMenu.java +@@ -17,6 +15,13 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.inventory.CraftInventoryStonecutter; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++// CraftBukkit end ++ + public class StonecutterMenu extends AbstractContainerMenu { + public static final int INPUT_SLOT = 0; + public static final int RESULT_SLOT = 1; +@@ -32,24 +38,54 @@ + long lastSoundTime; + final Slot inputSlot; + final Slot resultSlot; +- Runnable slotUpdateListener = () -> { +- }; +- public final Container container = new SimpleContainer(1) { +- @Override +- public void setChanged() { +- super.setChanged(); +- StonecutterMenu.this.slotsChanged(this); +- StonecutterMenu.this.slotUpdateListener.run(); ++ Runnable slotUpdateListener; ++ public final Container container; ++ final ResultContainer resultContainer; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; + } + }; + final ResultContainer resultContainer = new ResultContainer(); + ++ CraftInventoryStonecutter inventory = new CraftInventoryStonecutter(this.container, this.resultContainer); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end ++ + public StonecutterMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, ContainerLevelAccess.NULL); + } + + public StonecutterMenu(int containerId, Inventory playerInventory, final ContainerLevelAccess access) { + super(MenuType.STONECUTTER, containerId); ++ this.selectedRecipeIndex = DataSlot.standalone(); ++ this.recipes = Lists.newArrayList(); ++ this.input = ItemStack.EMPTY; ++ this.slotUpdateListener = () -> { ++ }; ++ this.container = new SimpleContainer(1) { ++ @Override ++ public void setChanged() { ++ super.setChanged(); ++ StonecutterMenu.this.slotsChanged(this); ++ StonecutterMenu.this.slotUpdateListener.run(); ++ } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end ++ }; ++ this.resultContainer = new ResultContainer(); + this.access = access; + this.level = playerInventory.player.level(); + this.inputSlot = this.addSlot(new Slot(this.container, 0, 20, 33)); +@@ -94,6 +133,7 @@ + } + + this.addDataSlot(this.selectedRecipeIndex); ++ player = (Player) playerInventory.player.getBukkitEntity(); // CraftBukkit + } + + public int getSelectedRecipeIndex() { +@@ -113,7 +153,8 @@ + } + + @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.STONECUTTER); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/TransientCraftingContainer.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/TransientCraftingContainer.java.patch new file mode 100644 index 0000000000..1914af6287 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/inventory/TransientCraftingContainer.java.patch @@ -0,0 +1,88 @@ +--- a/net/minecraft/world/inventory/TransientCraftingContainer.java ++++ b/net/minecraft/world/inventory/TransientCraftingContainer.java +@@ -7,12 +9,84 @@ + import net.minecraft.world.entity.player.StackedContents; + import net.minecraft.world.item.ItemStack; + +-public class TransientCraftingContainer implements CraftingContainer { ++// CraftBukkit start ++import java.util.List; ++import net.minecraft.world.item.crafting.RecipeHolder; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.event.inventory.InventoryType; ++// CraftBukkit end ++ ++public class TransientCraftingContainer implements InventoryCrafting { ++ + private final NonNullList items; + private final int width; + private final int height; + private final AbstractContainerMenu menu; + ++ // CraftBukkit start - add fields ++ public List transaction = new java.util.ArrayList(); ++ private RecipeHolder currentRecipe; ++ public Container resultInventory; ++ private Player owner; ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public InventoryType getInvType() { ++ return items.size() == 4 ? InventoryType.CRAFTING : InventoryType.WORKBENCH; ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return (owner == null) ? null : owner.getBukkitEntity(); ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ resultInventory.setMaxStackSize(size); ++ } ++ ++ @Override ++ public Location getLocation() { ++ return menu instanceof CraftingMenu ? ((CraftingMenu) menu).access.getLocation() : owner.getBukkitEntity().getLocation(); ++ } ++ ++ @Override ++ public RecipeHolder getCurrentRecipe() { ++ return currentRecipe; ++ } ++ ++ @Override ++ public void setCurrentRecipe(RecipeHolder currentRecipe) { ++ this.currentRecipe = currentRecipe; ++ } ++ ++ public TransientCraftingContainer(AbstractContainerMenu container, int i, int j, Player player) { ++ this(container, i, j); ++ this.owner = player; ++ } ++ // CraftBukkit end ++ + public TransientCraftingContainer(AbstractContainerMenu menu, int width, int height) { + this(menu, width, height, NonNullList.withSize(width * height, ItemStack.EMPTY)); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/ArmorItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/ArmorItem.java.patch new file mode 100644 index 0000000000..0074fd1f09 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/ArmorItem.java.patch @@ -0,0 +1,64 @@ +--- a/net/minecraft/world/item/ArmorItem.java ++++ b/net/minecraft/world/item/ArmorItem.java +@@ -25,6 +26,11 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.DispenserBlock; + import net.minecraft.world.phys.AABB; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseArmorEvent; ++// CraftBukkit end + + public class ArmorItem extends Item implements Equipable { + private static final EnumMap ARMOR_MODIFIER_UUID_PER_TYPE = Util.make(new EnumMap<>(ArmorItem.Type.class), map -> { +@@ -55,15 +60,42 @@ + if (entitiesOfClass.isEmpty()) { + return false; + } else { +- LivingEntity livingEntity = entitiesOfClass.get(0); +- EquipmentSlot equipmentSlotForItem = Mob.getEquipmentSlotForItem(itemStack); +- ItemStack itemStack1 = itemStack.split(1); +- livingEntity.setItemSlot(equipmentSlotForItem, itemStack1); +- if (livingEntity instanceof Mob) { +- ((Mob)livingEntity).setDropChance(equipmentSlotForItem, 2.0F); +- ((Mob)livingEntity).setPersistenceRequired(); ++ LivingEntity entityliving = (LivingEntity) list.get(0); ++ EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(itemstack); ++ ItemStack itemstack1 = itemstack.split(1); ++ // CraftBukkit start ++ Level world = sourceblock.level(); ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityliving.getBukkitEntity()); ++ if (!DispenserBlock.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); + } + ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return false; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return true; ++ } ++ } ++ ++ entityliving.setItemSlot(enumitemslot, CraftItemStack.asNMSCopy(event.getItem())); ++ // CraftBukkit end ++ if (entityliving instanceof Mob) { ++ ((Mob) entityliving).setDropChance(enumitemslot, 2.0F); ++ ((Mob) entityliving).setPersistenceRequired(); ++ } ++ + return true; + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/ArmorStandItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/ArmorStandItem.java.patch new file mode 100644 index 0000000000..4c3a37c97b --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/ArmorStandItem.java.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/world/item/ArmorStandItem.java ++++ b/net/minecraft/world/item/ArmorStandItem.java +@@ -44,13 +50,17 @@ + return InteractionResult.FAIL; + } + +- float f = (float)Mth.floor((Mth.wrapDegrees(context.getRotation() - 180.0F) + 22.5F) / 45.0F) * 45.0F; +- armorStand.moveTo(armorStand.getX(), armorStand.getY(), armorStand.getZ(), f, 0.0F); +- serverLevel.addFreshEntityWithPassengers(armorStand); +- level.playSound( +- null, armorStand.getX(), armorStand.getY(), armorStand.getZ(), SoundEvents.ARMOR_STAND_PLACE, SoundSource.BLOCKS, 0.75F, 0.8F +- ); +- armorStand.gameEvent(GameEvent.ENTITY_PLACE, context.getPlayer()); ++ float f = (float) Mth.floor((Mth.wrapDegrees(context.getRotation() - 180.0F) + 22.5F) / 45.0F) * 45.0F; ++ ++ entityarmorstand.moveTo(entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), f, 0.0F); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(context, entityarmorstand).isCancelled()) { ++ return InteractionResult.FAIL; ++ } ++ // CraftBukkit end ++ worldserver.addFreshEntityWithPassengers(entityarmorstand); ++ world.playSound((Player) null, entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), SoundEvents.ARMOR_STAND_PLACE, SoundSource.BLOCKS, 0.75F, 0.8F); ++ entityarmorstand.gameEvent(GameEvent.ENTITY_PLACE, context.getPlayer()); + } + + itemInHand.shrink(1); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/BlockItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/BlockItem.java.patch new file mode 100644 index 0000000000..d8963fdd26 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/BlockItem.java.patch @@ -0,0 +1,159 @@ +--- a/net/minecraft/world/item/BlockItem.java ++++ b/net/minecraft/world/item/BlockItem.java +@@ -29,6 +32,10 @@ + import net.minecraft.world.level.block.state.properties.Property; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.CollisionContext; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.event.block.BlockCanBuildEvent; ++// CraftBukkit end + + public class BlockItem extends Item { + public static final String BLOCK_ENTITY_TAG = "BlockEntityTag"; +@@ -62,38 +74,53 @@ + if (blockPlaceContext == null) { + return InteractionResult.FAIL; + } else { +- BlockState placementState = this.getPlacementState(blockPlaceContext); +- if (placementState == null) { ++ IBlockData iblockdata = this.getPlacementState(blockactioncontext1); ++ // CraftBukkit start - special case for handling block placement with water lilies and snow buckets ++ org.bukkit.block.BlockState blockstate = null; ++ if (this instanceof PlaceOnWaterBlockItem || this instanceof SolidBucketItem) { ++ blockstate = org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockactioncontext1.getLevel(), blockactioncontext1.getClickedPos()); ++ } ++ // CraftBukkit end ++ ++ if (iblockdata == null) { + return InteractionResult.FAIL; + } else if (!this.placeBlock(blockPlaceContext, placementState)) { + return InteractionResult.FAIL; + } else { +- BlockPos clickedPos = blockPlaceContext.getClickedPos(); +- Level level = blockPlaceContext.getLevel(); +- Player player = blockPlaceContext.getPlayer(); +- ItemStack itemInHand = blockPlaceContext.getItemInHand(); +- BlockState blockState = level.getBlockState(clickedPos); +- if (blockState.is(placementState.getBlock())) { +- blockState = this.updateBlockStateFromTag(clickedPos, level, itemInHand, blockState); +- this.updateCustomBlockEntityTag(clickedPos, level, player, itemInHand, blockState); +- blockState.getBlock().setPlacedBy(level, clickedPos, blockState, player, itemInHand); +- if (player instanceof ServerPlayer) { +- CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer)player, clickedPos, itemInHand); ++ BlockPos blockposition = blockactioncontext1.getClickedPos(); ++ Level world = blockactioncontext1.getLevel(); ++ Player entityhuman = blockactioncontext1.getPlayer(); ++ ItemStack itemstack = blockactioncontext1.getItemInHand(); ++ IBlockData iblockdata1 = world.getBlockState(blockposition); ++ ++ if (iblockdata1.is(iblockdata.getBlock())) { ++ iblockdata1 = this.updateBlockStateFromTag(blockposition, world, itemstack, iblockdata1); ++ this.updateCustomBlockEntityTag(blockposition, world, entityhuman, itemstack, iblockdata1); ++ iblockdata1.getBlock().setPlacedBy(world, blockposition, iblockdata1, entityhuman, itemstack); ++ // CraftBukkit start ++ if (blockstate != null) { ++ org.bukkit.event.block.BlockPlaceEvent placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEvent((ServerLevel) world, entityhuman, blockactioncontext1.getHand(), blockstate, blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild())) { ++ blockstate.update(true, false); ++ ++ if (this instanceof SolidBucketItem) { ++ ((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 ++ } ++ return InteractionResult.FAIL; ++ } + } ++ // CraftBukkit end ++ if (entityhuman instanceof ServerPlayer) { ++ CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) entityhuman, blockposition, itemstack); ++ } + } + +- SoundType soundType = blockState.getSoundType(); +- level.playSound( +- player, +- clickedPos, +- this.getPlaceSound(blockState), +- SoundSource.BLOCKS, +- (soundType.getVolume() + 1.0F) / 2.0F, +- soundType.getPitch() * 0.8F +- ); +- level.gameEvent(GameEvent.BLOCK_PLACE, clickedPos, GameEvent.Context.of(player, blockState)); +- if (player == null || !player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ SoundType soundeffecttype = iblockdata1.getSoundType(); ++ ++ // world.playSound(entityhuman, blockposition, this.getPlaceSound(iblockdata1), SoundCategory.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F); ++ world.gameEvent(GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(entityhuman, iblockdata1)); ++ if ((entityhuman == null || !entityhuman.getAbilities().instabuild) && itemstack != ItemStack.EMPTY) { // CraftBukkit ++ itemstack.shrink(1); + } + + return InteractionResult.sidedSuccess(level.isClientSide); +@@ -128,13 +153,10 @@ + CompoundTag compound = tag.getCompound("BlockStateTag"); + StateDefinition stateDefinition = state.getBlock().getStateDefinition(); + +- for (String string : compound.getAllKeys()) { +- Property property = stateDefinition.getProperty(string); +- if (property != null) { +- String asString = compound.get(string).getAsString(); +- blockState = updateState(blockState, property, asString); +- } +- } ++ if (nbttagcompound != null) { ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("BlockStateTag"); ++ // CraftBukkit start ++ iblockdata1 = getBlockState(iblockdata1, nbttagcompound1); + } + + if (blockState != state) { +@@ -144,8 +166,25 @@ + return blockState; + } + +- private static > BlockState updateState(BlockState state, Property property, String valueIdentifier) { +- return property.getValue(valueIdentifier).map(comparable -> state.setValue(property, comparable)).orElse(state); ++ public static IBlockData getBlockState(IBlockData iblockdata, CompoundTag nbttagcompound1) { ++ IBlockData iblockdata1 = iblockdata; ++ { ++ // CraftBukkit end ++ StateDefinition blockstatelist = iblockdata.getBlock().getStateDefinition(); ++ Iterator iterator = nbttagcompound1.getAllKeys().iterator(); ++ ++ while (iterator.hasNext()) { ++ String s = (String) iterator.next(); ++ Property iblockstate = blockstatelist.getProperty(s); ++ ++ if (iblockstate != null) { ++ String s1 = nbttagcompound1.get(s).getAsString(); ++ ++ iblockdata1 = updateState(iblockdata1, iblockstate, s1); ++ } ++ } ++ } ++ return iblockdata1; + } + + protected boolean canPlace(BlockPlaceContext context, BlockState state) { +@@ -155,6 +193,20 @@ + && context.getLevel().isUnobstructed(state, context.getClickedPos(), collisionContext); + } + ++ protected boolean canPlace(BlockPlaceContext context, IBlockData state) { ++ Player entityhuman = context.getPlayer(); ++ CollisionContext voxelshapecollision = entityhuman == null ? CollisionContext.empty() : CollisionContext.of(entityhuman); ++ // CraftBukkit start - store default return ++ boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && context.getLevel().isUnobstructed(state, context.getClickedPos(), voxelshapecollision); ++ org.bukkit.entity.Player player = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null; ++ ++ BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(context.getLevel(), context.getClickedPos()), player, CraftBlockData.fromData(state), defaultReturn); ++ context.getLevel().getCraftServer().getPluginManager().callEvent(event); ++ ++ return event.isBuildable(); ++ // CraftBukkit end ++ } ++ + protected boolean mustSurvive() { + return true; + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/BoatItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/BoatItem.java.patch new file mode 100644 index 0000000000..28d2866305 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/BoatItem.java.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/world/item/BoatItem.java ++++ b/net/minecraft/world/item/BoatItem.java +@@ -51,16 +59,32 @@ + } + } + +- if (playerPOVHitResult.getType() == HitResult.Type.BLOCK) { +- Boat boat = this.getBoat(level, playerPOVHitResult, itemInHand, player); +- boat.setVariant(this.type); +- boat.setYRot(player.getYRot()); +- if (!level.noCollision(boat, boat.getBoundingBox())) { +- return InteractionResultHolder.fail(itemInHand); ++ if (movingobjectpositionblock.getType() == HitResult.EnumMovingObjectType.BLOCK) { ++ // CraftBukkit start - Boat placement ++ org.bukkit.event.player.PlayerInteractEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(player, org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), itemstack, false, hand, movingobjectpositionblock.getLocation()); ++ ++ if (event.isCancelled()) { ++ return InteractionResultHolder.pass(itemstack); ++ } ++ // CraftBukkit end ++ Boat entityboat = this.getBoat(level, movingobjectpositionblock, itemstack, player); ++ ++ entityboat.setVariant(this.type); ++ entityboat.setYRot(player.getYRot()); ++ if (!level.noCollision(entityboat, entityboat.getBoundingBox())) { ++ return InteractionResultHolder.fail(itemstack); + } else { + if (!level.isClientSide) { +- level.addFreshEntity(boat); +- level.gameEvent(player, GameEvent.ENTITY_PLACE, playerPOVHitResult.getLocation()); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(level, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), player, entityboat, hand).isCancelled()) { ++ return InteractionResultHolder.fail(itemstack); ++ } ++ ++ if (!level.addFreshEntity(entityboat)) { ++ return InteractionResultHolder.pass(itemstack); ++ } ++ // CraftBukkit end ++ level.gameEvent((Entity) player, GameEvent.ENTITY_PLACE, movingobjectpositionblock.getLocation()); + if (!player.getAbilities().instabuild) { + itemInHand.shrink(1); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/BoneMealItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/BoneMealItem.java.patch new file mode 100644 index 0000000000..8dec6340c2 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/BoneMealItem.java.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/world/item/BoneMealItem.java ++++ b/net/minecraft/world/item/BoneMealItem.java +@@ -34,23 +34,31 @@ + + @Override + public InteractionResult useOn(UseOnContext context) { +- Level level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- BlockPos blockPos = clickedPos.relative(context.getClickedFace()); +- if (growCrop(context.getItemInHand(), level, clickedPos)) { +- if (!level.isClientSide) { +- context.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); +- level.levelEvent(1505, clickedPos, 0); ++ // CraftBukkit start - extract bonemeal application logic to separate, static method ++ return applyBonemeal(context); ++ } ++ ++ public static InteractionResult applyBonemeal(UseOnContext itemactioncontext) { ++ // CraftBukkit end ++ Level world = itemactioncontext.getLevel(); ++ BlockPos blockposition = itemactioncontext.getClickedPos(); ++ BlockPos blockposition1 = blockposition.relative(itemactioncontext.getClickedFace()); ++ ++ if (growCrop(itemactioncontext.getItemInHand(), world, blockposition)) { ++ if (!world.isClientSide) { ++ if (itemactioncontext.getPlayer() != null) itemactioncontext.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); // CraftBukkit - SPIGOT-7518 ++ world.levelEvent(1505, blockposition, 0); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + } else { +- BlockState blockState = level.getBlockState(clickedPos); +- boolean isFaceSturdy = blockState.isFaceSturdy(level, clickedPos, context.getClickedFace()); +- if (isFaceSturdy && growWaterPlant(context.getItemInHand(), level, blockPos, context.getClickedFace())) { +- if (!level.isClientSide) { +- context.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); +- level.levelEvent(1505, blockPos, 0); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ boolean flag = iblockdata.isFaceSturdy(world, blockposition, itemactioncontext.getClickedFace()); ++ ++ if (flag && growWaterPlant(itemactioncontext.getItemInHand(), world, blockposition1, itemactioncontext.getClickedFace())) { ++ if (!world.isClientSide) { ++ if (itemactioncontext.getPlayer() != null) itemactioncontext.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); // CraftBukkit - SPIGOT-7518 ++ world.levelEvent(1505, blockposition1, 0); + } + + return InteractionResult.sidedSuccess(level.isClientSide); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/BowItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/BowItem.java.patch new file mode 100644 index 0000000000..9c7d43a137 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/BowItem.java.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/item/BowItem.java ++++ b/net/minecraft/world/item/BowItem.java +@@ -56,13 +64,30 @@ + if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.FLAMING_ARROWS, stack) > 0) { + abstractArrow.setSecondsOnFire(100); + } ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(entityhuman, stack, itemstack1, entityarrow, entityhuman.getUsedItemHand(), f, !flag1); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ flag1 = !event.shouldConsumeItem(); ++ // CraftBukkit end + + stack.hurtAndBreak(1, player, player1 -> player1.broadcastBreakEvent(player.getUsedItemHand())); + if (flag1 || player.getAbilities().instabuild && (projectile.is(Items.SPECTRAL_ARROW) || projectile.is(Items.TIPPED_ARROW))) { + abstractArrow.pickup = AbstractArrow.Pickup.CREATIVE_ONLY; + } + +- level.addFreshEntity(abstractArrow); ++ // CraftBukkit start ++ if (event.getProjectile() == entityarrow.getBukkitEntity()) { ++ if (!level.addFreshEntity(entityarrow)) { ++ if (entityhuman instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } ++ return; ++ } ++ } ++ // CraftBukkit end + } + + level.playSound( diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/BucketItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/BucketItem.java.patch new file mode 100644 index 0000000000..744bc0754d --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/BucketItem.java.patch @@ -0,0 +1,138 @@ +--- a/net/minecraft/world/item/BucketItem.java ++++ b/net/minecraft/world/item/BucketItem.java +@@ -27,6 +30,12 @@ + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.HitResult; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.DummyGeneratorAccess; ++import org.bukkit.event.player.PlayerBucketEmptyEvent; ++import org.bukkit.event.player.PlayerBucketFillEvent; ++// CraftBukkit end + + public class BucketItem extends Item implements DispensibleContainerItem { + private final Fluid content; +@@ -47,27 +56,39 @@ + } else if (playerPOVHitResult.getType() != HitResult.Type.BLOCK) { + return InteractionResultHolder.pass(itemInHand); + } else { +- BlockPos blockPos = playerPOVHitResult.getBlockPos(); +- Direction direction = playerPOVHitResult.getDirection(); +- BlockPos blockPos1 = blockPos.relative(direction); +- if (!level.mayInteract(player, blockPos) || !player.mayUseItemAt(blockPos1, direction, itemInHand)) { +- return InteractionResultHolder.fail(itemInHand); +- } else if (this.content == Fluids.EMPTY) { +- BlockState blockState = level.getBlockState(blockPos); +- if (blockState.getBlock() instanceof BucketPickup bucketPickup) { +- ItemStack itemStack = bucketPickup.pickupBlock(player, level, blockPos, blockState); +- if (!itemStack.isEmpty()) { +- player.awardStat(Stats.ITEM_USED.get(this)); +- bucketPickup.getPickupSound().ifPresent(soundEvent -> player.playSound(soundEvent, 1.0F, 1.0F)); +- level.gameEvent(player, GameEvent.FLUID_PICKUP, blockPos); +- ItemStack itemStack1 = ItemUtils.createFilledResult(itemInHand, player, itemStack); +- if (!level.isClientSide) { +- CriteriaTriggers.FILLED_BUCKET.trigger((ServerPlayer)player, itemStack); ++ BlockPos blockposition = movingobjectpositionblock.getBlockPos(); ++ Direction enumdirection = movingobjectpositionblock.getDirection(); ++ BlockPos blockposition1 = blockposition.relative(enumdirection); ++ ++ if (level.mayInteract(player, blockposition) && player.mayUseItemAt(blockposition1, enumdirection, itemstack)) { ++ IBlockData iblockdata; ++ ++ if (this.content == Fluids.EMPTY) { ++ iblockdata = level.getBlockState(blockposition); ++ Block block = iblockdata.getBlock(); ++ ++ if (block instanceof BucketPickup) { ++ BucketPickup ifluidsource = (BucketPickup) block; ++ // CraftBukkit start ++ ItemStack dummyFluid = ifluidsource.pickupBlock(player, DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); ++ if (dummyFluid.isEmpty()) return InteractionResultHolder.fail(itemstack); // Don't fire event if the bucket won't be filled. ++ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) level, player, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.getItem(), hand); ++ ++ if (event.isCancelled()) { ++ ((ServerPlayer) player).connection.send(new ClientboundBlockUpdatePacket(level, blockposition)); // SPIGOT-5163 (see PlayerInteractManager) ++ ((ServerPlayer) player).getBukkitEntity().updateInventory(); // SPIGOT-4541 ++ return InteractionResultHolder.fail(itemstack); + } ++ // CraftBukkit end ++ ItemStack itemstack1 = ifluidsource.pickupBlock(player, level, blockposition, iblockdata); + +- return InteractionResultHolder.sidedSuccess(itemStack1, level.isClientSide()); +- } +- } ++ if (!itemstack1.isEmpty()) { ++ player.awardStat(Stats.ITEM_USED.get(this)); ++ ifluidsource.getPickupSound().ifPresent((soundeffect) -> { ++ player.playSound(soundeffect, 1.0F, 1.0F); ++ }); ++ level.gameEvent((Entity) player, GameEvent.FLUID_PICKUP, blockposition); ++ ItemStack itemstack2 = ItemUtils.createFilledResult(itemstack, player, CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit + + return InteractionResultHolder.fail(itemInHand); + } else { +@@ -82,7 +100,20 @@ + player.awardStat(Stats.ITEM_USED.get(this)); + return InteractionResultHolder.sidedSuccess(getEmptySuccessItem(itemInHand, player), level.isClientSide()); + } else { +- return InteractionResultHolder.fail(itemInHand); ++ iblockdata = level.getBlockState(blockposition); ++ BlockPos blockposition2 = iblockdata.getBlock() instanceof LiquidBlockContainer && this.content == Fluids.WATER ? blockposition : blockposition1; ++ ++ if (this.emptyContents(player, level, blockposition2, movingobjectpositionblock, movingobjectpositionblock.getDirection(), blockposition, itemstack, hand)) { // CraftBukkit ++ this.checkExtraContent(player, level, itemstack, blockposition2); ++ if (player instanceof ServerPlayer) { ++ CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) player, blockposition2, itemstack); ++ } ++ ++ player.awardStat(Stats.ITEM_USED.get(this)); ++ return InteractionResultHolder.sidedSuccess(getEmptySuccessItem(itemstack, player), level.isClientSide()); ++ } else { ++ return InteractionResultHolder.fail(itemstack); ++ } + } + } + } +@@ -98,7 +130,15 @@ + + @Override + public boolean emptyContents(@Nullable Player player, Level level, BlockPos pos, @Nullable BlockHitResult result) { +- if (!(this.content instanceof FlowingFluid flowingFluid)) { ++ // CraftBukkit start ++ return emptyContents(player, level, pos, result, null, null, null, EnumHand.MAIN_HAND); ++ } ++ ++ public boolean emptyContents(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack, EnumHand enumhand) { ++ // CraftBukkit end ++ Fluid fluidtype = this.content; ++ ++ if (!(fluidtype instanceof FlowingFluid)) { + return false; + } else { + Block block; +@@ -134,9 +173,22 @@ + player, pos, SoundEvents.FIRE_EXTINGUISH, SoundSource.BLOCKS, 0.5F, 2.6F + (level.random.nextFloat() - level.random.nextFloat()) * 0.8F + ); + +- for (int i = 0; i < 8; i++) { +- level.addParticle(ParticleTypes.LARGE_SMOKE, (double)x + Math.random(), (double)y + Math.random(), (double)z + Math.random(), 0.0, 0.0, 0.0); ++ // CraftBukkit start ++ if (flag2 && entityhuman != null) { ++ PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((ServerLevel) world, entityhuman, blockposition, clicked, enumdirection, itemstack, enumhand); ++ if (event.isCancelled()) { ++ ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-4238: needed when looking through entity ++ ((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 ++ return false; + } ++ } ++ // CraftBukkit end ++ if (!flag2) { ++ return movingobjectpositionblock != null && this.emptyContents(entityhuman, world, movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()), (BlockHitResult) null, enumdirection, clicked, itemstack, enumhand); // CraftBukkit ++ } else if (world.dimensionType().ultraWarm() && this.content.is(FluidTags.WATER)) { ++ int i = blockposition.getX(); ++ int j = blockposition.getY(); ++ int k = blockposition.getZ(); + + return true; + } else { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/ChorusFruitItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/ChorusFruitItem.java.patch new file mode 100644 index 0000000000..b5bec9cc49 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/ChorusFruitItem.java.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/item/ChorusFruitItem.java ++++ b/net/minecraft/world/item/ChorusFruitItem.java +@@ -33,11 +33,22 @@ + entityLiving.stopRiding(); + } + +- Vec3 vec3 = entityLiving.position(); +- if (entityLiving.randomTeleport(d, d1, d2, true)) { +- level.gameEvent(GameEvent.TELEPORT, vec3, GameEvent.Context.of(entityLiving)); +- SoundSource soundSource; +- SoundEvent soundEvent; ++ Vec3 vec3d = entityLiving.position(); ++ ++ // CraftBukkit start - handle canceled status of teleport event ++ java.util.Optional status = entityLiving.randomTeleport(d0, d1, d2, true, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.CHORUS_FRUIT); ++ ++ if (!status.isPresent()) { ++ // teleport event was canceled, no more tries ++ break; ++ } ++ ++ if (status.get()) { ++ // CraftBukkit end ++ level.gameEvent(GameEvent.TELEPORT, vec3d, GameEvent.Context.of((Entity) entityLiving)); ++ SoundEvent soundeffect; ++ SoundSource soundcategory; ++ + if (entityLiving instanceof Fox) { + soundEvent = SoundEvents.FOX_TELEPORT; + soundSource = SoundSource.NEUTRAL; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/CrossbowItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/CrossbowItem.java.patch new file mode 100644 index 0000000000..49ad59c5bf --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/CrossbowItem.java.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/item/CrossbowItem.java ++++ b/net/minecraft/world/item/CrossbowItem.java +@@ -234,10 +236,28 @@ + Vector3f vector3f = viewVector.toVector3f().rotate(quaternionf); + projectile.shoot((double)vector3f.x(), (double)vector3f.y(), (double)vector3f.z(), velocity, inaccuracy); + } ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(shooter, crossbowStack, ammoStack, (Entity) object, shooter.getUsedItemHand(), soundPitch, true); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ // CraftBukkit end + +- crossbowStack.hurtAndBreak(isFireworkRocket ? 3 : 1, shooter, contextEntity -> contextEntity.broadcastBreakEvent(hand)); +- level.addFreshEntity(projectile); +- level.playSound(null, shooter.getX(), shooter.getY(), shooter.getZ(), SoundEvents.CROSSBOW_SHOOT, SoundSource.PLAYERS, 1.0F, soundPitch); ++ crossbowStack.hurtAndBreak(flag1 ? 3 : 1, shooter, (entityliving1) -> { ++ entityliving1.broadcastBreakEvent(hand); ++ }); ++ // CraftBukkit start ++ if (event.getProjectile() == ((Entity) object).getBukkitEntity()) { ++ if (!level.addFreshEntity((Entity) object)) { ++ if (shooter instanceof ServerPlayer) { ++ ((ServerPlayer) shooter).getBukkitEntity().updateInventory(); ++ } ++ return; ++ } ++ } ++ // CraftBukkit end ++ level.playSound((Player) null, shooter.getX(), shooter.getY(), shooter.getZ(), SoundEvents.CROSSBOW_SHOOT, SoundSource.PLAYERS, 1.0F, soundPitch); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/DebugStickItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/DebugStickItem.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/DebugStickItem.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/DyeItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/DyeItem.java.patch new file mode 100644 index 0000000000..0d41c2aec7 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/DyeItem.java.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/world/item/DyeItem.java ++++ b/net/minecraft/world/item/DyeItem.java +@@ -11,7 +12,7 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.SignBlockEntity; +-import net.minecraft.world.level.block.entity.SignText; ++import org.bukkit.event.entity.SheepDyeWoolEvent; // CraftBukkit + + public class DyeItem extends Item implements SignApplicator { + private static final Map ITEM_BY_COLOR = Maps.newEnumMap(DyeColor.class); +@@ -32,7 +30,25 @@ + stack.shrink(1); + } + +- return InteractionResult.sidedSuccess(player.level().isClientSide); ++ if (entitysheep.isAlive() && !entitysheep.isSheared() && entitysheep.getColor() != this.dyeColor) { ++ entitysheep.level().playSound(player, (Entity) entitysheep, SoundEvents.DYE_USE, SoundSource.PLAYERS, 1.0F, 1.0F); ++ if (!player.level().isClientSide) { ++ // CraftBukkit start ++ byte bColor = (byte) this.dyeColor.getId(); ++ SheepDyeWoolEvent event = new SheepDyeWoolEvent((org.bukkit.entity.Sheep) entitysheep.getBukkitEntity(), org.bukkit.DyeColor.getByWoolData(bColor), (org.bukkit.entity.Player) player.getBukkitEntity()); ++ entitysheep.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return InteractionResult.PASS; ++ } ++ ++ entitysheep.setColor(DyeColor.byId((byte) event.getColor().getWoolData())); ++ // CraftBukkit end ++ stack.shrink(1); ++ } ++ ++ return InteractionResult.sidedSuccess(player.level().isClientSide); ++ } + } + + return InteractionResult.PASS; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/EggItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/EggItem.java.patch new file mode 100644 index 0000000000..07e2bf1538 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/EggItem.java.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/world/item/EggItem.java ++++ b/net/minecraft/world/item/EggItem.java +@@ -15,23 +16,23 @@ + } + + @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- level.playSound( +- null, +- player.getX(), +- player.getY(), +- player.getZ(), +- SoundEvents.EGG_THROW, +- SoundSource.PLAYERS, +- 0.5F, +- 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F) +- ); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ // world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); // CraftBukkit - moved down + if (!level.isClientSide) { +- ThrownEgg thrownEgg = new ThrownEgg(level, player); +- thrownEgg.setItem(itemInHand); +- thrownEgg.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 1.5F, 1.0F); +- level.addFreshEntity(thrownEgg); ++ ThrownEgg entityegg = new ThrownEgg(level, player); ++ ++ entityegg.setItem(itemstack); ++ entityegg.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 1.5F, 1.0F); ++ // CraftBukkit start ++ if (!level.addFreshEntity(entityegg)) { ++ if (player instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().updateInventory(); ++ } ++ return InteractionResultHolder.fail(itemstack); ++ } ++ // CraftBukkit end + } + + player.awardStat(Stats.ITEM_USED.get(this)); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/EndCrystalItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/EndCrystalItem.java.patch new file mode 100644 index 0000000000..d755b53015 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/EndCrystalItem.java.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/world/item/EndCrystalItem.java ++++ b/net/minecraft/world/item/EndCrystalItem.java +@@ -38,15 +42,22 @@ + if (!entities.isEmpty()) { + return InteractionResult.FAIL; + } else { +- if (level instanceof ServerLevel) { +- EndCrystal endCrystal = new EndCrystal(level, d + 0.5, d1, d2 + 0.5); +- endCrystal.setShowBottom(false); +- level.addFreshEntity(endCrystal); +- level.gameEvent(context.getPlayer(), GameEvent.ENTITY_PLACE, blockPos); +- EndDragonFight dragonFight = ((ServerLevel)level).getDragonFight(); +- if (dragonFight != null) { +- dragonFight.tryRespawn(); ++ if (world instanceof ServerLevel) { ++ EndCrystal entityendercrystal = new EndCrystal(world, d0 + 0.5D, d1, d2 + 0.5D); ++ ++ entityendercrystal.setShowBottom(false); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(context, entityendercrystal).isCancelled()) { ++ return InteractionResult.FAIL; + } ++ // CraftBukkit end ++ world.addFreshEntity(entityendercrystal); ++ world.gameEvent((Entity) context.getPlayer(), GameEvent.ENTITY_PLACE, blockposition1); ++ EndDragonFight enderdragonbattle = ((ServerLevel) world).getDragonFight(); ++ ++ if (enderdragonbattle != null) { ++ enderdragonbattle.tryRespawn(); ++ } + } + + context.getItemInHand().shrink(1); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/EnderEyeItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/EnderEyeItem.java.patch new file mode 100644 index 0000000000..3d409494f3 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/EnderEyeItem.java.patch @@ -0,0 +1,32 @@ +--- a/net/minecraft/world/item/EnderEyeItem.java ++++ b/net/minecraft/world/item/EnderEyeItem.java +@@ -71,14 +79,21 @@ + return InteractionResultHolder.pass(itemInHand); + } else { + player.startUsingItem(hand); +- if (level instanceof ServerLevel serverLevel) { +- BlockPos blockPos = serverLevel.findNearestMapStructure(StructureTags.EYE_OF_ENDER_LOCATED, player.blockPosition(), 100, false); +- if (blockPos != null) { +- EyeOfEnder eyeOfEnder = new EyeOfEnder(level, player.getX(), player.getY(0.5), player.getZ()); +- eyeOfEnder.setItem(itemInHand); +- eyeOfEnder.signalTo(blockPos); +- level.gameEvent(GameEvent.PROJECTILE_SHOOT, eyeOfEnder.position(), GameEvent.Context.of(player)); +- level.addFreshEntity(eyeOfEnder); ++ if (level instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) level; ++ BlockPos blockposition = worldserver.findNearestMapStructure(StructureTags.EYE_OF_ENDER_LOCATED, player.blockPosition(), 100, false); ++ ++ if (blockposition != null) { ++ EyeOfEnder entityendersignal = new EyeOfEnder(level, player.getX(), player.getY(0.5D), player.getZ()); ++ ++ entityendersignal.setItem(itemstack); ++ entityendersignal.signalTo(blockposition); ++ level.gameEvent(GameEvent.PROJECTILE_SHOOT, entityendersignal.position(), GameEvent.Context.of((Entity) player)); ++ // CraftBukkit start ++ if (!level.addFreshEntity(entityendersignal)) { ++ return new InteractionResultHolder(InteractionResult.FAIL, itemstack); ++ } ++ // CraftBukkit end + if (player instanceof ServerPlayer) { + CriteriaTriggers.USED_ENDER_EYE.trigger((ServerPlayer)player, blockPos); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/EnderpearlItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/EnderpearlItem.java.patch new file mode 100644 index 0000000000..4851eaadc8 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/EnderpearlItem.java.patch @@ -0,0 +1,37 @@ +--- a/net/minecraft/world/item/EnderpearlItem.java ++++ b/net/minecraft/world/item/EnderpearlItem.java +@@ -15,19 +16,10 @@ + } + + @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- level.playSound( +- null, +- player.getX(), +- player.getY(), +- player.getZ(), +- SoundEvents.ENDER_PEARL_THROW, +- SoundSource.NEUTRAL, +- 0.5F, +- 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F) +- ); +- player.getCooldowns().addCooldown(this, 20); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ // CraftBukkit start - change order + if (!level.isClientSide) { + ThrownEnderpearl thrownEnderpearl = new ThrownEnderpearl(level, player); + thrownEnderpearl.setItem(itemInHand); +@@ -35,6 +33,10 @@ + level.addFreshEntity(thrownEnderpearl); + } + ++ level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); ++ player.getCooldowns().addCooldown(this, 20); ++ // CraftBukkit end ++ + player.awardStat(Stats.ITEM_USED.get(this)); + if (!player.getAbilities().instabuild) { + itemInHand.shrink(1); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/FireChargeItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/FireChargeItem.java.patch new file mode 100644 index 0000000000..3db64e44df --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/FireChargeItem.java.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/world/item/FireChargeItem.java ++++ b/net/minecraft/world/item/FireChargeItem.java +@@ -26,18 +29,35 @@ + BlockPos clickedPos = context.getClickedPos(); + BlockState blockState = level.getBlockState(clickedPos); + boolean flag = false; +- if (!CampfireBlock.canLight(blockState) && !CandleBlock.canLight(blockState) && !CandleCakeBlock.canLight(blockState)) { +- BlockPos var6 = clickedPos.relative(context.getClickedFace()); +- if (BaseFireBlock.canBePlacedAt(level, var6, context.getHorizontalDirection())) { +- this.playSound(level, var6); +- level.setBlockAndUpdate(var6, BaseFireBlock.getState(level, var6)); +- level.gameEvent(context.getPlayer(), GameEvent.BLOCK_PLACE, var6); ++ ++ if (!CampfireBlock.canLight(iblockdata) && !CandleBlock.canLight(iblockdata) && !CandleCakeBlock.canLight(iblockdata)) { ++ blockposition = blockposition.relative(context.getClickedFace()); ++ if (BaseFireBlock.canBePlacedAt(world, blockposition, context.getHorizontalDirection())) { ++ // CraftBukkit start - fire BlockIgniteEvent ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FIREBALL, context.getPlayer()).isCancelled()) { ++ if (!context.getPlayer().getAbilities().instabuild) { ++ context.getItemInHand().shrink(1); ++ } ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end ++ this.playSound(world, blockposition); ++ world.setBlockAndUpdate(blockposition, BaseFireBlock.getState(world, blockposition)); ++ world.gameEvent((Entity) context.getPlayer(), GameEvent.BLOCK_PLACE, blockposition); + flag = true; + } + } else { +- this.playSound(level, clickedPos); +- level.setBlockAndUpdate(clickedPos, blockState.setValue(BlockStateProperties.LIT, Boolean.valueOf(true))); +- level.gameEvent(context.getPlayer(), GameEvent.BLOCK_CHANGE, clickedPos); ++ // CraftBukkit start - fire BlockIgniteEvent ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FIREBALL, context.getPlayer()).isCancelled()) { ++ if (!context.getPlayer().getAbilities().instabuild) { ++ context.getItemInHand().shrink(1); ++ } ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end ++ this.playSound(world, blockposition); ++ world.setBlockAndUpdate(blockposition, (IBlockData) iblockdata.setValue(BlockStateProperties.LIT, true)); ++ world.gameEvent((Entity) context.getPlayer(), GameEvent.BLOCK_CHANGE, blockposition); + flag = true; + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/FishingRodItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/FishingRodItem.java.patch new file mode 100644 index 0000000000..cc2d211ac0 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/FishingRodItem.java.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/world/item/FishingRodItem.java ++++ b/net/minecraft/world/item/FishingRodItem.java +@@ -11,7 +11,13 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + +-public class FishingRodItem extends Item implements Vanishable { ++// CraftBukkit start ++import org.bukkit.event.player.PlayerFishEvent; ++import org.bukkit.craftbukkit.CraftEquipmentSlot; ++// CraftBukkit end ++ ++public class FishingRodItem extends Item implements ItemVanishable { ++ + public FishingRodItem(Item.Properties properties) { + super(properties); + } +@@ -48,9 +40,21 @@ + 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F) + ); + if (!level.isClientSide) { +- int i = EnchantmentHelper.getFishingSpeedBonus(itemInHand); +- int fishingLuckBonus = EnchantmentHelper.getFishingLuckBonus(itemInHand); +- level.addFreshEntity(new FishingHook(player, level, fishingLuckBonus, i)); ++ i = EnchantmentHelper.getFishingSpeedBonus(itemstack); ++ int j = EnchantmentHelper.getFishingLuckBonus(itemstack); ++ ++ // CraftBukkit start ++ FishingHook entityfishinghook = new FishingHook(player, level, j, i); ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((org.bukkit.entity.Player) player.getBukkitEntity(), null, (org.bukkit.entity.FishHook) entityfishinghook.getBukkitEntity(), CraftEquipmentSlot.getHand(hand), PlayerFishEvent.State.FISHING); ++ level.getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ player.fishing = null; ++ return InteractionResultHolder.pass(itemstack); ++ } ++ level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.FISHING_BOBBER_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); ++ level.addFreshEntity(entityfishinghook); ++ // CraftBukkit end + } + + player.awardStat(Stats.ITEM_USED.get(this)); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/FlintAndSteelItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/FlintAndSteelItem.java.patch new file mode 100644 index 0000000000..33db34830e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/FlintAndSteelItem.java.patch @@ -0,0 +1,70 @@ +--- a/net/minecraft/world/item/FlintAndSteelItem.java ++++ b/net/minecraft/world/item/FlintAndSteelItem.java +@@ -24,34 +26,47 @@ + + @Override + public InteractionResult useOn(UseOnContext context) { +- Player player = context.getPlayer(); +- Level level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- BlockState blockState = level.getBlockState(clickedPos); +- if (!CampfireBlock.canLight(blockState) && !CandleBlock.canLight(blockState) && !CandleCakeBlock.canLight(blockState)) { +- BlockPos blockPos = clickedPos.relative(context.getClickedFace()); +- if (BaseFireBlock.canBePlacedAt(level, blockPos, context.getHorizontalDirection())) { +- level.playSound(player, blockPos, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.4F + 0.8F); +- BlockState state = BaseFireBlock.getState(level, blockPos); +- level.setBlock(blockPos, state, 11); +- level.gameEvent(player, GameEvent.BLOCK_PLACE, clickedPos); +- ItemStack itemInHand = context.getItemInHand(); +- if (player instanceof ServerPlayer) { +- CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer)player, blockPos, itemInHand); +- itemInHand.hurtAndBreak(1, player, contextPlayer -> contextPlayer.broadcastBreakEvent(context.getHand())); ++ Player entityhuman = context.getPlayer(); ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ ++ if (!CampfireBlock.canLight(iblockdata) && !CandleBlock.canLight(iblockdata) && !CandleCakeBlock.canLight(iblockdata)) { ++ BlockPos blockposition1 = blockposition.relative(context.getClickedFace()); ++ ++ if (BaseFireBlock.canBePlacedAt(world, blockposition1, context.getHorizontalDirection())) { ++ // CraftBukkit start - Store the clicked block ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition1, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL, entityhuman).isCancelled()) { ++ context.getItemInHand().hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(context.getHand()); ++ }); ++ return InteractionResult.PASS; + } ++ // CraftBukkit end ++ world.playSound(entityhuman, blockposition1, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, world.getRandom().nextFloat() * 0.4F + 0.8F); ++ IBlockData iblockdata1 = BaseFireBlock.getState(world, blockposition1); + + return InteractionResult.sidedSuccess(level.isClientSide()); + } else { + return InteractionResult.FAIL; + } + } else { +- level.playSound(player, clickedPos, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.4F + 0.8F); +- level.setBlock(clickedPos, blockState.setValue(BlockStateProperties.LIT, Boolean.valueOf(true)), 11); +- level.gameEvent(player, GameEvent.BLOCK_CHANGE, clickedPos); +- if (player != null) { +- context.getItemInHand().hurtAndBreak(1, player, contextPlayer -> contextPlayer.broadcastBreakEvent(context.getHand())); ++ // CraftBukkit start - Store the clicked block ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL, entityhuman).isCancelled()) { ++ context.getItemInHand().hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(context.getHand()); ++ }); ++ return InteractionResult.PASS; + } ++ // CraftBukkit end ++ world.playSound(entityhuman, blockposition, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, world.getRandom().nextFloat() * 0.4F + 0.8F); ++ world.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockStateProperties.LIT, true), 11); ++ world.gameEvent((Entity) entityhuman, GameEvent.BLOCK_CHANGE, blockposition); ++ if (entityhuman != null) { ++ context.getItemInHand().hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(context.getHand()); ++ }); ++ } + + return InteractionResult.sidedSuccess(level.isClientSide()); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/HangingEntityItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/HangingEntityItem.java.patch new file mode 100644 index 0000000000..af58c26e59 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/HangingEntityItem.java.patch @@ -0,0 +1,44 @@ +--- a/net/minecraft/world/item/HangingEntityItem.java ++++ b/net/minecraft/world/item/HangingEntityItem.java +@@ -22,6 +21,11 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.entity.Player; ++import org.bukkit.event.hanging.HangingPlaceEvent; ++// CraftBukkit end ++ + public class HangingEntityItem extends Item { + private static final Component TOOLTIP_RANDOM_VARIANT = Component.translatable("painting.random").withStyle(ChatFormatting.GRAY); + private final EntityType type; +@@ -65,11 +74,24 @@ + EntityType.updateCustomEntityTag(level, player, hangingEntity, tag); + } + +- if (hangingEntity.survives()) { +- if (!level.isClientSide) { +- hangingEntity.playPlacementSound(); +- level.gameEvent(player, GameEvent.ENTITY_PLACE, hangingEntity.position()); +- level.addFreshEntity(hangingEntity); ++ if (((HangingEntity) object).survives()) { ++ if (!world.isClientSide) { ++ // CraftBukkit start - fire HangingPlaceEvent ++ Player who = (context.getPlayer() == null) ? null : (Player) context.getPlayer().getBukkitEntity(); ++ org.bukkit.block.Block blockClicked = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(enumdirection); ++ org.bukkit.inventory.EquipmentSlot hand = org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand()); ++ ++ HangingPlaceEvent event = new HangingPlaceEvent((org.bukkit.entity.Hanging) ((HangingEntity) object).getBukkitEntity(), who, blockClicked, blockFace, hand, org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return InteractionResult.FAIL; ++ } ++ // CraftBukkit end ++ ((HangingEntity) object).playPlacementSound(); ++ world.gameEvent((Entity) entityhuman, GameEvent.ENTITY_PLACE, ((HangingEntity) object).position()); ++ world.addFreshEntity((Entity) object); + } + + itemInHand.shrink(1); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/ItemStack.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/ItemStack.java.patch new file mode 100644 index 0000000000..e318ac0812 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/ItemStack.java.patch @@ -0,0 +1,327 @@ +--- a/net/minecraft/world/item/ItemStack.java ++++ b/net/minecraft/world/item/ItemStack.java +@@ -81,6 +82,41 @@ + import net.minecraft.world.level.block.state.pattern.BlockInWorld; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.mojang.serialization.Dynamic; ++import java.util.Map; ++import java.util.Objects; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundSource; ++import net.minecraft.stats.Stats; ++import net.minecraft.util.datafix.fixes.DataConverterTypes; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.SaplingBlock; ++import net.minecraft.world.level.block.SignBlock; ++import net.minecraft.world.level.block.SoundType; ++import net.minecraft.world.level.block.WitherSkullBlock; ++import net.minecraft.world.level.block.entity.BlockEntity; ++import net.minecraft.world.level.block.entity.JukeboxBlockEntity; ++import net.minecraft.world.level.block.entity.SignBlockEntity; ++import net.minecraft.world.level.block.entity.SkullBlockEntity; ++import net.minecraft.world.level.gameevent.GameEvent; ++import org.bukkit.Location; ++import org.bukkit.TreeType; ++import org.bukkit.block.BlockState; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.entity.Player; ++import org.bukkit.event.block.BlockFertilizeEvent; ++import org.bukkit.event.player.PlayerItemDamageEvent; ++import org.bukkit.event.world.StructureGrowEvent; ++// CraftBukkit end ++ + public final class ItemStack { + public static final Codec CODEC = RecordCodecBuilder.create( + instance -> instance.group( +@@ -181,11 +211,22 @@ + this.item = null; + } + +- private ItemStack(CompoundTag compoundTag) { +- this.item = BuiltInRegistries.ITEM.get(new ResourceLocation(compoundTag.getString("id"))); +- this.count = compoundTag.getByte("Count"); +- if (compoundTag.contains("tag", 10)) { +- this.tag = compoundTag.getCompound("tag").copy(); ++ // Called to run this stack through the data converter to handle older storage methods and serialized items ++ public void convertStack(int version) { ++ if (0 < version && version < CraftMagicNumbers.INSTANCE.getDataVersion()) { ++ CompoundTag savedStack = new CompoundTag(); ++ this.save(savedStack); ++ savedStack = (CompoundTag) MinecraftServer.getServer().fixerUpper.update(DataConverterTypes.ITEM_STACK, new Dynamic(NbtOps.INSTANCE, savedStack), version, CraftMagicNumbers.INSTANCE.getDataVersion()).getValue(); ++ this.load(savedStack); ++ } ++ } ++ ++ // CraftBukkit - break into own method ++ private void load(CompoundTag nbttagcompound) { ++ this.item = (Item) BuiltInRegistries.ITEM.get(new ResourceLocation(nbttagcompound.getString("id"))); ++ this.count = nbttagcompound.getByte("Count"); ++ if (nbttagcompound.contains("tag", 10)) { ++ this.tag = nbttagcompound.getCompound("tag").copy(); + this.getItem().verifyTagAfterLoad(this.tag); + } + +@@ -194,6 +236,11 @@ + } + } + ++ private ItemStack(CompoundTag compoundTag) { ++ this.load(compoundTag); ++ // CraftBukkit end ++ } ++ + public static ItemStack of(CompoundTag compoundTag) { + try { + return new ItemStack(compoundTag); +@@ -270,12 +318,169 @@ + return InteractionResult.PASS; + } else { + Item item = this.getItem(); +- InteractionResult interactionResult = item.useOn(context); +- if (player != null && interactionResult.shouldAwardStats()) { +- player.awardStat(Stats.ITEM_USED.get(item)); ++ // CraftBukkit start - handle all block place event logic here ++ CompoundTag oldData = this.getTagClone(); ++ int oldCount = this.getCount(); ++ ServerLevel world = (ServerLevel) context.getLevel(); ++ ++ if (!(item instanceof BucketItem || item instanceof SolidBucketItem)) { // if not bucket ++ world.captureBlockStates = true; ++ // special case bonemeal ++ if (item == Items.BONE_MEAL) { ++ world.captureTreeGeneration = true; ++ } + } + +- return interactionResult; ++ BlockFertilizeEvent fertilizeEvent = new BlockFertilizeEvent(CraftBlock.at(world, blockposition), (Player) entityhuman.getBukkitEntity(), (List< BlockState>) (List) blocks); ++ fertilizeEvent.setCancelled(structureEvent != null && structureEvent.isCancelled()); ++ org.bukkit.Bukkit.getPluginManager().callEvent(fertilizeEvent); ++ ++ if (!fertilizeEvent.isCancelled()) { ++ // Change the stack to its new contents if it hasn't been tampered with. ++ if (this.getCount() == oldCount && Objects.equals(this.tag, oldData)) { ++ this.setTag(newData); ++ this.setCount(newCount); ++ } ++ for (CraftBlockState blockstate : blocks) { ++ world.setBlock(blockstate.getPosition(),blockstate.getHandle(), blockstate.getFlag()); // SPIGOT-7248 - manual update to avoid physics where appropriate ++ } ++ entityhuman.awardStat(Stats.ITEM_USED.get(item)); // SPIGOT-7236 - award stat ++ } ++ ++ SignItem.openSign = null; // SPIGOT-6758 - Reset on early return ++ return enuminteractionresult; ++ } ++ world.captureTreeGeneration = false; ++ ++ if (entityhuman != null && enuminteractionresult.shouldAwardStats()) { ++ EnumHand enumhand = context.getHand(); ++ org.bukkit.event.block.BlockPlaceEvent placeEvent = null; ++ List blocks = new java.util.ArrayList<>(world.capturedBlockStates.values()); ++ world.capturedBlockStates.clear(); ++ if (blocks.size() > 1) { ++ placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockMultiPlaceEvent(world, entityhuman, enumhand, blocks, blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ } else if (blocks.size() == 1) { ++ placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEvent(world, entityhuman, enumhand, blocks.get(0), blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ } ++ ++ if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild())) { ++ enuminteractionresult = InteractionResult.FAIL; // cancel placement ++ // PAIL: Remove this when MC-99075 fixed ++ placeEvent.getPlayer().updateInventory(); ++ // revert back all captured blocks ++ world.preventPoiUpdated = true; // CraftBukkit - SPIGOT-5710 ++ for (BlockState blockstate : blocks) { ++ blockstate.update(true, false); ++ } ++ world.preventPoiUpdated = false; ++ ++ // Brute force all possible updates ++ BlockPos placedPos = ((CraftBlock) placeEvent.getBlock()).getPosition(); ++ for (Direction dir : Direction.values()) { ++ ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, placedPos.relative(dir))); ++ } ++ SignItem.openSign = null; // SPIGOT-6758 - Reset on early return ++ } else { ++ // Change the stack to its new contents if it hasn't been tampered with. ++ if (this.getCount() == oldCount && Objects.equals(this.tag, oldData)) { ++ this.setTag(newData); ++ this.setCount(newCount); ++ } ++ ++ for (Map.Entry e : world.capturedTileEntities.entrySet()) { ++ world.setBlockEntity(e.getValue()); ++ } ++ ++ for (BlockState blockstate : blocks) { ++ int updateFlag = ((CraftBlockState) blockstate).getFlag(); ++ IBlockData oldBlock = ((CraftBlockState) blockstate).getHandle(); ++ BlockPos newblockposition = ((CraftBlockState) blockstate).getPosition(); ++ IBlockData block = world.getBlockState(newblockposition); ++ ++ if (!(block.getBlock() instanceof BaseEntityBlock)) { // Containers get placed automatically ++ block.getBlock().onPlace(block, world, newblockposition, oldBlock, true); ++ } ++ ++ world.notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, world.getBlockState(newblockposition), updateFlag, 512); // send null chunk as chunk.k() returns false by this point ++ } ++ ++ // Special case juke boxes as they update their tile entity. Copied from ItemRecord. ++ // PAIL: checkme on updates. ++ if (this.item instanceof RecordItem) { ++ BlockEntity tileentity = world.getBlockEntity(blockposition); ++ ++ if (tileentity instanceof JukeboxBlockEntity) { ++ JukeboxBlockEntity tileentityjukebox = (JukeboxBlockEntity) tileentity; ++ ++ // There can only be one ++ ItemStack record = this.copy(); ++ if (!record.isEmpty()) { ++ record.setCount(1); ++ } ++ ++ tileentityjukebox.setTheItem(record); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entityhuman, world.getBlockState(blockposition))); ++ } ++ ++ this.shrink(1); ++ entityhuman.awardStat(Stats.PLAY_RECORD); ++ } ++ ++ if (this.item == Items.WITHER_SKELETON_SKULL) { // Special case skulls to allow wither spawns to be cancelled ++ BlockPos bp = blockposition; ++ if (!world.getBlockState(blockposition).canBeReplaced()) { ++ if (!world.getBlockState(blockposition).isSolid()) { ++ bp = null; ++ } else { ++ bp = bp.relative(context.getClickedFace()); ++ } ++ } ++ if (bp != null) { ++ BlockEntity te = world.getBlockEntity(bp); ++ if (te instanceof SkullBlockEntity) { ++ WitherSkullBlock.checkSpawn(world, bp, (SkullBlockEntity) te); ++ } ++ } ++ } ++ ++ // SPIGOT-4678 ++ if (this.item instanceof SignItem && SignItem.openSign != null) { ++ try { ++ if (world.getBlockEntity(SignItem.openSign) instanceof SignBlockEntity tileentitysign) { ++ if (world.getBlockState(SignItem.openSign).getBlock() instanceof SignBlock blocksign) { ++ blocksign.openTextEdit(entityhuman, tileentitysign, true, org.bukkit.event.player.PlayerSignOpenEvent.Cause.PLACE); // Craftbukkit ++ } ++ } ++ } finally { ++ SignItem.openSign = null; ++ } ++ } ++ ++ // SPIGOT-7315: Moved from BlockBed#setPlacedBy ++ if (placeEvent != null && this.item instanceof BedItem) { ++ BlockPos position = ((CraftBlock) placeEvent.getBlock()).getPosition(); ++ IBlockData blockData = world.getBlockState(position); ++ ++ if (blockData.getBlock() instanceof BedBlock) { ++ world.blockUpdated(position, Blocks.AIR); ++ blockData.updateNeighbourShapes(world, position, 3); ++ } ++ } ++ ++ // SPIGOT-1288 - play sound stripped from ItemBlock ++ if (this.item instanceof BlockItem) { ++ SoundType soundeffecttype = ((BlockItem) this.item).getBlock().defaultBlockState().getSoundType(); // TODO: not strictly correct, however currently only affects decorated pots ++ world.playSound(entityhuman, blockposition, soundeffecttype.getPlaceSound(), SoundSource.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F); ++ } ++ ++ entityhuman.awardStat(Stats.ITEM_USED.get(item)); ++ } ++ } ++ world.capturedTileEntities.clear(); ++ world.capturedBlockStates.clear(); ++ // CraftBukkit end ++ ++ return enuminteractionresult; + } + } + +@@ -349,7 +581,22 @@ + } + } + +- amount -= i; ++ amount -= k; ++ // CraftBukkit start ++ if (user != null) { ++ PlayerItemDamageEvent event = new PlayerItemDamageEvent(user.getBukkitEntity(), CraftItemStack.asCraftMirror(this), amount); ++ event.getPlayer().getServer().getPluginManager().callEvent(event); ++ ++ if (amount != event.getDamage() || event.isCancelled()) { ++ event.getPlayer().updateInventory(); ++ } ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ amount = event.getDamage(); ++ } ++ // CraftBukkit end + if (amount <= 0) { + return false; + } +@@ -371,6 +618,12 @@ + if (this.hurt(amount, entity.getRandom(), entity instanceof ServerPlayer ? (ServerPlayer)entity : null)) { + onBroken.accept(entity); + Item item = this.getItem(); ++ // CraftBukkit start - Check for item breaking ++ if (this.count == 1 && entity instanceof net.minecraft.world.entity.player.Player) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemBreakEvent((net.minecraft.world.entity.player.Player) entity, this); ++ } ++ // CraftBukkit end ++ + this.shrink(1); + if (entity instanceof Player) { + ((Player)entity).awardStat(Stats.ITEM_BROKEN.get(item)); +@@ -513,6 +775,17 @@ + return this.tag; + } + ++ // CraftBukkit start ++ @Nullable ++ private CompoundTag getTagClone() { ++ return this.tag == null ? null : this.tag.copy(); ++ } ++ ++ private void setTagClone(@Nullable CompoundTag nbtttagcompound) { ++ this.setTag(nbtttagcompound == null ? null : nbtttagcompound.copy()); ++ } ++ // CraftBukkit end ++ + public CompoundTag getOrCreateTag() { + if (this.tag == null) { + this.setTag(new CompoundTag()); +@@ -925,6 +1210,13 @@ + list.add(compoundTag); + } + ++ // CraftBukkit start ++ @Deprecated ++ public void setItem(Item item) { ++ this.item = item; ++ } ++ // CraftBukkit end ++ + public Component getDisplayName() { + MutableComponent mutableComponent = Component.empty().append(this.getHoverName()); + if (this.hasCustomHoverName()) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/LeadItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/LeadItem.java.patch new file mode 100644 index 0000000000..db1ad8e4ff --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/LeadItem.java.patch @@ -0,0 +1,99 @@ +--- a/net/minecraft/world/item/LeadItem.java ++++ b/net/minecraft/world/item/LeadItem.java +@@ -11,6 +14,10 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; ++// CraftBukkit start ++import org.bukkit.craftbukkit.CraftEquipmentSlot; ++import org.bukkit.event.hanging.HangingPlaceEvent; ++// CraftBukkit end + + public class LeadItem extends Item { + public LeadItem(Item.Properties properties) { +@@ -19,13 +27,15 @@ + + @Override + public InteractionResult useOn(UseOnContext context) { +- Level level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- BlockState blockState = level.getBlockState(clickedPos); +- if (blockState.is(BlockTags.FENCES)) { +- Player player = context.getPlayer(); +- if (!level.isClientSide && player != null) { +- bindPlayerMobs(player, level, clickedPos); ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ ++ if (iblockdata.is(BlockTags.FENCES)) { ++ Player entityhuman = context.getPlayer(); ++ ++ if (!world.isClientSide && entityhuman != null) { ++ bindPlayerMobs(entityhuman, world, blockposition, context.getHand()); // CraftBukkit - Pass hand + } + + return InteractionResult.sidedSuccess(level.isClientSide); +@@ -34,24 +44,41 @@ + } + } + +- public static InteractionResult bindPlayerMobs(Player player, Level level, BlockPos pos) { +- LeashFenceKnotEntity leashFenceKnotEntity = null; ++ public static InteractionResult bindPlayerMobs(Player entityhuman, Level world, BlockPos blockposition, net.minecraft.world.EnumHand enumhand) { // CraftBukkit - Add EnumHand ++ LeashFenceKnotEntity entityleash = null; + boolean flag = false; + double d = 7.0; + int x = pos.getX(); + int y = pos.getY(); + int z = pos.getZ(); + +- for (Mob mob : level.getEntitiesOfClass( +- Mob.class, new AABB((double)x - 7.0, (double)y - 7.0, (double)z - 7.0, (double)x + 7.0, (double)y + 7.0, (double)z + 7.0) +- )) { +- if (mob.getLeashHolder() == player) { +- if (leashFenceKnotEntity == null) { +- leashFenceKnotEntity = LeashFenceKnotEntity.getOrCreateKnot(level, pos); +- leashFenceKnotEntity.playPlacementSound(); ++ while (iterator.hasNext()) { ++ Mob entityinsentient = (Mob) iterator.next(); ++ ++ if (entityinsentient.getLeashHolder() == entityhuman) { ++ if (entityleash == null) { ++ entityleash = LeashFenceKnotEntity.getOrCreateKnot(world, blockposition); ++ ++ // CraftBukkit start - fire HangingPlaceEvent ++ org.bukkit.inventory.EquipmentSlot hand = CraftEquipmentSlot.getHand(enumhand); ++ HangingPlaceEvent event = new HangingPlaceEvent((org.bukkit.entity.Hanging) entityleash.getBukkitEntity(), entityhuman != null ? (org.bukkit.entity.Player) entityhuman.getBukkitEntity() : null, world.getWorld().getBlockAt(i, j, k), org.bukkit.block.BlockFace.SELF, hand); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ entityleash.discard(); ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end ++ entityleash.playPlacementSound(); + } + +- mob.setLeashedTo(leashFenceKnotEntity, true); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerLeashEntityEvent(entityinsentient, entityleash, entityhuman, enumhand).isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end ++ ++ entityinsentient.setLeashedTo(entityleash, true); + flag = true; + } + } +@@ -62,4 +91,10 @@ + + return flag ? InteractionResult.SUCCESS : InteractionResult.PASS; + } ++ ++ // CraftBukkit start ++ public static InteractionResult bindPlayerMobs(Player player, Level level, BlockPos pos) { ++ return bindPlayerMobs(player, level, pos, net.minecraft.world.EnumHand.MAIN_HAND); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/MapItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/MapItem.java.patch new file mode 100644 index 0000000000..06b6d7d15a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/MapItem.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/item/MapItem.java ++++ b/net/minecraft/world/item/MapItem.java +@@ -64,8 +67,9 @@ + + @Nullable + public static Integer getMapId(ItemStack stack) { +- CompoundTag tag = stack.getTag(); +- return tag != null && tag.contains("map", 99) ? tag.getInt("map") : null; ++ CompoundTag nbttagcompound = stack.getTag(); ++ ++ return nbttagcompound != null && nbttagcompound.contains("map", 99) ? nbttagcompound.getInt("map") : -1; // CraftBukkit - make new maps for no tag + } + + private static int createNewSavedData( diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/MilkBucketItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/MilkBucketItem.java.patch new file mode 100644 index 0000000000..45e78e72b9 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/MilkBucketItem.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/item/MilkBucketItem.java ++++ b/net/minecraft/world/item/MilkBucketItem.java +@@ -28,7 +31,7 @@ + } + + if (!level.isClientSide) { +- entityLiving.removeAllEffects(); ++ entityLiving.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.MILK); // CraftBukkit + } + + return stack.isEmpty() ? new ItemStack(Items.BUCKET) : stack; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/MinecartItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/MinecartItem.java.patch new file mode 100644 index 0000000000..5c82298462 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/MinecartItem.java.patch @@ -0,0 +1,90 @@ +--- a/net/minecraft/world/item/MinecartItem.java ++++ b/net/minecraft/world/item/MinecartItem.java +@@ -17,6 +18,11 @@ + import net.minecraft.world.level.block.state.properties.RailShape; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end + + public class MinecartItem extends Item { + private static final DispenseItemBehavior DISPENSE_ITEM_BEHAVIOR = new DefaultDispenseItemBehavior() { +@@ -58,12 +63,40 @@ + } + } + +- AbstractMinecart abstractMinecart = AbstractMinecart.createMinecart( +- serverLevel, d, d1 + d3, d2, ((MinecartItem)itemStack.getItem()).type, itemStack, null +- ); +- serverLevel.addFreshEntity(abstractMinecart); +- itemStack.shrink(1); +- return itemStack; ++ // CraftBukkit start ++ // EntityMinecartAbstract entityminecartabstract = EntityMinecartAbstract.createMinecart(worldserver, d0, d1 + d3, d2, ((ItemMinecart) itemstack.getItem()).type); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block2 = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block2, craftItem.clone(), new org.bukkit.util.Vector(d0, d1 + d3, d2)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); ++ AbstractMinecart entityminecartabstract = AbstractMinecart.createMinecart(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), ((MinecartItem) itemstack1.getItem()).type, itemstack1, (Player) null); ++ ++ if (!worldserver.addFreshEntity(entityminecartabstract)) itemstack.grow(1); ++ // itemstack.shrink(1); // CraftBukkit - handled during event processing ++ // CraftBukkit end ++ return itemstack; + } + + @Override +@@ -97,19 +132,15 @@ + d = 0.5; + } + +- AbstractMinecart abstractMinecart = AbstractMinecart.createMinecart( +- serverLevel, +- (double)clickedPos.getX() + 0.5, +- (double)clickedPos.getY() + 0.0625 + d, +- (double)clickedPos.getZ() + 0.5, +- this.type, +- itemInHand, +- context.getPlayer() +- ); +- serverLevel.addFreshEntity(abstractMinecart); +- serverLevel.gameEvent( +- GameEvent.ENTITY_PLACE, clickedPos, GameEvent.Context.of(context.getPlayer(), serverLevel.getBlockState(clickedPos.below())) +- ); ++ AbstractMinecart entityminecartabstract = AbstractMinecart.createMinecart(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.0625D + d0, (double) blockposition.getZ() + 0.5D, this.type, itemstack, context.getPlayer()); ++ ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(context, entityminecartabstract).isCancelled()) { ++ return InteractionResult.FAIL; ++ } ++ // CraftBukkit end ++ if (!worldserver.addFreshEntity(entityminecartabstract)) return InteractionResult.PASS; // CraftBukkit ++ worldserver.gameEvent(GameEvent.ENTITY_PLACE, blockposition, GameEvent.Context.of(context.getPlayer(), worldserver.getBlockState(blockposition.below()))); + } + + itemInHand.shrink(1); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/PotionItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/PotionItem.java.patch new file mode 100644 index 0000000000..fce2791a33 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/PotionItem.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/item/PotionItem.java ++++ b/net/minecraft/world/item/PotionItem.java +@@ -51,7 +60,7 @@ + if (mobEffectInstance.getEffect().isInstantenous()) { + mobEffectInstance.getEffect().applyInstantenousEffect(player, player, entityLiving, mobEffectInstance.getAmplifier(), 1.0); + } else { +- entityLiving.addEffect(new MobEffectInstance(mobEffectInstance)); ++ entityLiving.addEffect(new MobEffectInstance(mobeffect), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_DRINK); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/RecordItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/RecordItem.java.patch new file mode 100644 index 0000000000..d1ff6cdcae --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/RecordItem.java.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/world/item/RecordItem.java ++++ b/net/minecraft/world/item/RecordItem.java +@@ -36,16 +38,23 @@ + + @Override + public InteractionResult useOn(UseOnContext context) { +- Level level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- BlockState blockState = level.getBlockState(clickedPos); +- if (blockState.is(Blocks.JUKEBOX) && !blockState.getValue(JukeboxBlock.HAS_RECORD)) { +- ItemStack itemInHand = context.getItemInHand(); +- if (!level.isClientSide) { +- Player player = context.getPlayer(); +- if (level.getBlockEntity(clickedPos) instanceof JukeboxBlockEntity jukeboxBlockEntity) { +- jukeboxBlockEntity.setTheItem(itemInHand.copy()); +- level.gameEvent(GameEvent.BLOCK_CHANGE, clickedPos, GameEvent.Context.of(player, blockState)); ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ ++ if (iblockdata.is(Blocks.JUKEBOX) && !(Boolean) iblockdata.getValue(JukeboxBlock.HAS_RECORD)) { ++ ItemStack itemstack = context.getItemInHand(); ++ ++ if (!world.isClientSide) { ++ if (true) return InteractionResult.SUCCESS; // CraftBukkit - handled in ItemStack ++ Player entityhuman = context.getPlayer(); ++ BlockEntity tileentity = world.getBlockEntity(blockposition); ++ ++ if (tileentity instanceof JukeboxBlockEntity) { ++ JukeboxBlockEntity tileentityjukebox = (JukeboxBlockEntity) tileentity; ++ ++ tileentityjukebox.setTheItem(itemstack.copy()); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entityhuman, iblockdata)); + } + + itemInHand.shrink(1); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/SignItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/SignItem.java.patch new file mode 100644 index 0000000000..686ee12c1c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/SignItem.java.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/world/item/SignItem.java ++++ b/net/minecraft/world/item/SignItem.java +@@ -11,6 +12,9 @@ + import net.minecraft.world.level.block.state.BlockState; + + public class SignItem extends StandingAndWallBlockItem { ++ ++ public static BlockPos openSign; // CraftBukkit ++ + public SignItem(Item.Properties properties, Block standingBlock, Block wallBlock) { + super(standingBlock, wallBlock, properties, Direction.DOWN); + } +@@ -22,12 +26,23 @@ + @Override + protected boolean updateCustomBlockEntityTag(BlockPos pos, Level level, @Nullable Player player, ItemStack stack, BlockState state) { + boolean flag = super.updateCustomBlockEntityTag(pos, level, player, stack, state); +- if (!level.isClientSide +- && !flag +- && player != null +- && level.getBlockEntity(pos) instanceof SignBlockEntity signBlockEntity +- && level.getBlockState(pos).getBlock() instanceof SignBlock signBlock) { +- signBlock.openTextEdit(player, signBlockEntity, true); ++ ++ if (!level.isClientSide && !flag && player != null) { ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof SignBlockEntity) { ++ SignBlockEntity tileentitysign = (SignBlockEntity) tileentity; ++ Block block = level.getBlockState(pos).getBlock(); ++ ++ if (block instanceof SignBlock) { ++ SignBlock blocksign = (SignBlock) block; ++ ++ // CraftBukkit start - SPIGOT-4678 ++ // blocksign.openTextEdit(entityhuman, tileentitysign, true); ++ SignItem.openSign = pos; ++ // CraftBukkit end ++ } ++ } + } + + return flag; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/SnowballItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/SnowballItem.java.patch new file mode 100644 index 0000000000..84d40286bb --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/SnowballItem.java.patch @@ -0,0 +1,41 @@ +--- a/net/minecraft/world/item/SnowballItem.java ++++ b/net/minecraft/world/item/SnowballItem.java +@@ -15,28 +16,24 @@ + } + + @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- level.playSound( +- null, +- player.getX(), +- player.getY(), +- player.getZ(), +- SoundEvents.SNOWBALL_THROW, +- SoundSource.NEUTRAL, +- 0.5F, +- 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F) +- ); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ // CraftBukkit - moved down ++ // world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.SNOWBALL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); + if (!level.isClientSide) { + Snowball snowball = new Snowball(level, player); + snowball.setItem(itemInHand); + snowball.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 1.5F, 1.0F); + level.addFreshEntity(snowball); + } ++ // CraftBukkit end + + player.awardStat(Stats.ITEM_USED.get(this)); +- if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ // CraftBukkit start - moved up ++ /* ++ if (!entityhuman.getAbilities().instabuild) { ++ itemstack.shrink(1); + } + + return InteractionResultHolder.sidedSuccess(itemInHand, level.isClientSide()); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/SpawnEggItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/SpawnEggItem.java.patch new file mode 100644 index 0000000000..dad4efbbc6 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/SpawnEggItem.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/item/SpawnEggItem.java ++++ b/net/minecraft/world/item/SpawnEggItem.java +@@ -176,8 +179,8 @@ + if (!breedOffspring.isBaby()) { + return Optional.empty(); + } else { +- breedOffspring.moveTo(pos.x(), pos.y(), pos.z(), 0.0F, 0.0F); +- serverLevel.addFreshEntityWithPassengers(breedOffspring); ++ ((Mob) object).moveTo(pos.x(), pos.y(), pos.z(), 0.0F, 0.0F); ++ serverLevel.addFreshEntityWithPassengers((Entity) object, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG); // CraftBukkit + if (stack.hasCustomHoverName()) { + breedOffspring.setCustomName(stack.getHoverName()); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/StandingAndWallBlockItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/StandingAndWallBlockItem.java.patch new file mode 100644 index 0000000000..5c47dd78db --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/StandingAndWallBlockItem.java.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/item/StandingAndWallBlockItem.java ++++ b/net/minecraft/world/item/StandingAndWallBlockItem.java +@@ -9,6 +11,10 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.shapes.CollisionContext; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.event.block.BlockCanBuildEvent; ++// CraftBukkit end + + public class StandingAndWallBlockItem extends BlockItem { + protected final Block wallBlock; +@@ -42,7 +54,19 @@ + } + } + +- return blockState != null && level.isUnobstructed(blockState, clickedPos, CollisionContext.empty()) ? blockState : null; ++ // CraftBukkit start ++ if (iblockdata1 != null) { ++ boolean defaultReturn = world.isUnobstructed(iblockdata1, blockposition, CollisionContext.empty()); ++ org.bukkit.entity.Player player = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null; ++ ++ BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(world, blockposition), player, CraftBlockData.fromData(iblockdata1), defaultReturn); ++ context.getLevel().getCraftServer().getPluginManager().callEvent(event); ++ ++ return (event.isBuildable()) ? iblockdata1 : null; ++ } else { ++ return null; ++ } ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/TridentItem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/TridentItem.java.patch new file mode 100644 index 0000000000..e2792900ad --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/TridentItem.java.patch @@ -0,0 +1,100 @@ +--- a/net/minecraft/world/item/TridentItem.java ++++ b/net/minecraft/world/item/TridentItem.java +@@ -62,39 +68,70 @@ + int riptide = EnchantmentHelper.getRiptide(stack); + if (riptide <= 0 || player.isInWaterOrRain()) { + if (!level.isClientSide) { +- stack.hurtAndBreak(1, player, contextEntity -> contextEntity.broadcastBreakEvent(entityLiving.getUsedItemHand())); +- if (riptide == 0) { +- ThrownTrident thrownTrident = new ThrownTrident(level, player, stack); +- thrownTrident.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 2.5F + (float)riptide * 0.5F, 1.0F); +- if (player.getAbilities().instabuild) { +- thrownTrident.pickup = AbstractArrow.Pickup.CREATIVE_ONLY; ++ // CraftBukkit - moved down ++ /* ++ itemstack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(entityliving.getUsedItemHand()); ++ }); ++ */ ++ if (k == 0) { ++ ThrownTrident entitythrowntrident = new ThrownTrident(level, entityhuman, stack); ++ ++ entitythrowntrident.shootFromRotation(entityhuman, entityhuman.getXRot(), entityhuman.getYRot(), 0.0F, 2.5F + (float) k * 0.5F, 1.0F); ++ if (entityhuman.getAbilities().instabuild) { ++ entitythrowntrident.pickup = AbstractArrow.Pickup.CREATIVE_ONLY; + } + +- level.addFreshEntity(thrownTrident); +- level.playSound(null, thrownTrident, SoundEvents.TRIDENT_THROW, SoundSource.PLAYERS, 1.0F, 1.0F); +- if (!player.getAbilities().instabuild) { +- player.getInventory().removeItem(stack); ++ // CraftBukkit start ++ if (!level.addFreshEntity(entitythrowntrident)) { ++ if (entityhuman instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } ++ return; + } ++ ++ stack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(entityLiving.getUsedItemHand()); ++ }); ++ entitythrowntrident.pickupItemStack = stack.copy(); // SPIGOT-4511 update since damage call moved ++ // CraftBukkit end ++ ++ level.playSound((Player) null, (Entity) entitythrowntrident, SoundEvents.TRIDENT_THROW, SoundSource.PLAYERS, 1.0F, 1.0F); ++ if (!entityhuman.getAbilities().instabuild) { ++ entityhuman.getInventory().removeItem(stack); ++ } ++ // CraftBukkit start - SPIGOT-5458 also need in this branch :( ++ } else { ++ stack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(entityLiving.getUsedItemHand()); ++ }); ++ // CraftBukkkit end + } + } + +- player.awardStat(Stats.ITEM_USED.get(this)); +- if (riptide > 0) { +- float yRot = player.getYRot(); +- float xRot = player.getXRot(); +- float f = -Mth.sin(yRot * (float) (Math.PI / 180.0)) * Mth.cos(xRot * (float) (Math.PI / 180.0)); +- float f1 = -Mth.sin(xRot * (float) (Math.PI / 180.0)); +- float f2 = Mth.cos(yRot * (float) (Math.PI / 180.0)) * Mth.cos(xRot * (float) (Math.PI / 180.0)); +- float squareRoot = Mth.sqrt(f * f + f1 * f1 + f2 * f2); +- float f3 = 3.0F * ((1.0F + (float)riptide) / 4.0F); +- f *= f3 / squareRoot; +- f1 *= f3 / squareRoot; +- f2 *= f3 / squareRoot; +- player.push((double)f, (double)f1, (double)f2); +- player.startAutoSpinAttack(20); +- if (player.onGround()) { +- float f4 = 1.1999999F; +- player.move(MoverType.SELF, new Vec3(0.0, 1.1999999F, 0.0)); ++ entityhuman.awardStat(Stats.ITEM_USED.get(this)); ++ if (k > 0) { ++ // CraftBukkit start ++ org.bukkit.event.player.PlayerRiptideEvent event = new org.bukkit.event.player.PlayerRiptideEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack)); ++ event.getPlayer().getServer().getPluginManager().callEvent(event); ++ // CraftBukkit end ++ float f = entityhuman.getYRot(); ++ float f1 = entityhuman.getXRot(); ++ float f2 = -Mth.sin(f * 0.017453292F) * Mth.cos(f1 * 0.017453292F); ++ float f3 = -Mth.sin(f1 * 0.017453292F); ++ float f4 = Mth.cos(f * 0.017453292F) * Mth.cos(f1 * 0.017453292F); ++ float f5 = Mth.sqrt(f2 * f2 + f3 * f3 + f4 * f4); ++ float f6 = 3.0F * ((1.0F + (float) k) / 4.0F); ++ ++ f2 *= f6 / f5; ++ f3 *= f6 / f5; ++ f4 *= f6 / f5; ++ entityhuman.push((double) f2, (double) f3, (double) f4); ++ entityhuman.startAutoSpinAttack(20); ++ if (entityhuman.onGround()) { ++ float f7 = 1.1999999F; ++ ++ entityhuman.move(EnumMoveType.SELF, new Vec3(0.0D, 1.1999999284744263D, 0.0D)); + } + + SoundEvent soundEvent; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/BlastingRecipe.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/BlastingRecipe.java.patch new file mode 100644 index 0000000000..f73982496b --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/BlastingRecipe.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/item/crafting/BlastingRecipe.java ++++ b/net/minecraft/world/item/crafting/BlastingRecipe.java +@@ -3,6 +3,14 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftBlastingRecipe; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class BlastingRecipe extends AbstractCookingRecipe { + public BlastingRecipe(String string, CookingBookCategory cookingBookCategory, Ingredient ingredient, ItemStack itemStack, float f, int i) { + super(RecipeType.BLASTING, string, cookingBookCategory, ingredient, itemStack, f, i); +@@ -17,4 +26,17 @@ + public RecipeSerializer getSerializer() { + return RecipeSerializer.BLASTING_RECIPE; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftBlastingRecipe recipe = new CraftBlastingRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/CampfireCookingRecipe.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/CampfireCookingRecipe.java.patch new file mode 100644 index 0000000000..c33d2d4a9b --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/CampfireCookingRecipe.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/item/crafting/CampfireCookingRecipe.java ++++ b/net/minecraft/world/item/crafting/CampfireCookingRecipe.java +@@ -3,6 +3,14 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftCampfireRecipe; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class CampfireCookingRecipe extends AbstractCookingRecipe { + public CampfireCookingRecipe(String string, CookingBookCategory cookingBookCategory, Ingredient ingredient, ItemStack itemStack, float f, int i) { + super(RecipeType.CAMPFIRE_COOKING, string, cookingBookCategory, ingredient, itemStack, f, i); +@@ -17,4 +26,17 @@ + public RecipeSerializer getSerializer() { + return RecipeSerializer.CAMPFIRE_COOKING_RECIPE; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftCampfireRecipe recipe = new CraftCampfireRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/CustomRecipe.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/CustomRecipe.java.patch new file mode 100644 index 0000000000..0a032bd01d --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/CustomRecipe.java.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/world/item/crafting/CustomRecipe.java ++++ b/net/minecraft/world/item/crafting/CustomRecipe.java +@@ -3,7 +3,13 @@ + import net.minecraft.core.RegistryAccess; + import net.minecraft.world.item.ItemStack; + +-public abstract class CustomRecipe implements CraftingRecipe { ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ ++public abstract class CustomRecipe implements RecipeCrafting { ++ + private final CraftingBookCategory category; + + public CustomRecipe(CraftingBookCategory craftingBookCategory) { +@@ -24,4 +30,11 @@ + public CraftingBookCategory category() { + return this.category; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ return new org.bukkit.craftbukkit.inventory.CraftComplexRecipe(id, this); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/Ingredient.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/Ingredient.java.patch new file mode 100644 index 0000000000..17af072826 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/Ingredient.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/item/crafting/Ingredient.java ++++ b/net/minecraft/world/item/crafting/Ingredient.java +@@ -34,6 +35,7 @@ + private ItemStack[] itemStacks; + @Nullable + private IntList stackingIds; ++ public boolean exact; // CraftBukkit + public static final Codec CODEC = codec(true); + public static final Codec CODEC_NONEMPTY = codec(false); + +@@ -60,8 +67,22 @@ + } else if (this.isEmpty()) { + return stack.isEmpty(); + } else { +- for (ItemStack itemStack : this.getItems()) { +- if (itemStack.is(stack.getItem())) { ++ ItemStack[] aitemstack = this.getItems(); ++ int i = aitemstack.length; ++ ++ for (int j = 0; j < i; ++j) { ++ ItemStack itemstack1 = aitemstack[j]; ++ ++ // CraftBukkit start ++ if (exact) { ++ if (itemstack1.getItem() == stack.getItem() && ItemStack.isSameItemSameTags(stack, itemstack1)) { ++ return true; ++ } ++ ++ continue; ++ } ++ // CraftBukkit end ++ if (itemstack1.is(stack.getItem())) { + return true; + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/Recipe.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/Recipe.java.patch new file mode 100644 index 0000000000..00d4c5ced3 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/Recipe.java.patch @@ -0,0 +1,9 @@ +--- a/net/minecraft/world/item/crafting/Recipe.java ++++ b/net/minecraft/world/item/crafting/Recipe.java +@@ -62,4 +67,6 @@ + NonNullList ingredients = this.getIngredients(); + return ingredients.isEmpty() || ingredients.stream().anyMatch(ingredient -> ingredient.getItems().length == 0); + } ++ ++ org.bukkit.inventory.Recipe toBukkitRecipe(org.bukkit.NamespacedKey id); // CraftBukkit + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/RecipeHolder.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/RecipeHolder.java.patch new file mode 100644 index 0000000000..d7bfcda029 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/RecipeHolder.java.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/item/crafting/RecipeHolder.java ++++ b/net/minecraft/world/item/crafting/RecipeHolder.java +@@ -1,9 +1,17 @@ + package net.minecraft.world.item.crafting; + + import net.minecraft.resources.ResourceLocation; ++// CraftBukkit start ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.inventory.Recipe; + +-public record RecipeHolder>(ResourceLocation id, T value) { +- @Override ++public record RecipeHolder>(ResourceLocation id, T value) { ++ ++ public final Recipe toBukkitRecipe() { ++ return this.value.toBukkitRecipe(CraftNamespacedKey.fromMinecraft(this.id)); ++ } ++ // CraftBukkit end ++ + public boolean equals(Object object) { + if (this == object) { + return true; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/RecipeManager.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/RecipeManager.java.patch new file mode 100644 index 0000000000..ea766ea2ff --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/RecipeManager.java.patch @@ -0,0 +1,165 @@ +--- a/net/minecraft/world/item/crafting/RecipeManager.java ++++ b/net/minecraft/world/item/crafting/RecipeManager.java +@@ -23,6 +24,15 @@ + import javax.annotation.Nullable; + import net.minecraft.Util; + import net.minecraft.core.NonNullList; ++import net.minecraft.world.Container; ++import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.level.Level; ++import org.slf4j.Logger; ++ ++// CraftBukkit start ++import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; ++import net.minecraft.core.registries.BuiltInRegistries; ++// CraftBukkit end + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.packs.resources.ResourceManager; + import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; +@@ -36,7 +43,7 @@ + public class RecipeManager extends SimpleJsonResourceReloadListener { + private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); + private static final Logger LOGGER = LogUtils.getLogger(); +- private Map, Map>> recipes = ImmutableMap.of(); ++ public Map, Object2ObjectLinkedOpenHashMap>> recipes = ImmutableMap.of(); // CraftBukkit + private Map> byName = ImmutableMap.of(); + private boolean hasErrors; + +@@ -47,32 +53,63 @@ + @Override + protected void apply(Map object, ResourceManager resourceManager, ProfilerFiller profiler) { + this.hasErrors = false; +- Map, Builder>> map = Maps.newHashMap(); ++ // CraftBukkit start - SPIGOT-5667 make sure all types are populated and mutable ++ Map, Object2ObjectLinkedOpenHashMap>> map1 = Maps.newHashMap(); ++ for (RecipeType recipeType : BuiltInRegistries.RECIPE_TYPE) { ++ map1.put(recipeType, new Object2ObjectLinkedOpenHashMap<>()); ++ } ++ // CraftBukkit end + Builder> builder = ImmutableMap.builder(); + + for (Entry entry : object.entrySet()) { + ResourceLocation resourceLocation = entry.getKey(); + + try { +- RecipeHolder recipeHolder = fromJson(resourceLocation, GsonHelper.convertToJsonObject(entry.getValue(), "top element")); +- map.computeIfAbsent(recipeHolder.value().getType(), type -> ImmutableMap.builder()).put(resourceLocation, recipeHolder); +- builder.put(resourceLocation, recipeHolder); +- } catch (IllegalArgumentException | JsonParseException var10) { +- LOGGER.error("Parsing error loading recipe {}", resourceLocation, var10); ++ RecipeHolder recipeholder = fromJson(minecraftkey, GsonHelper.convertToJsonObject((JsonElement) entry.getValue(), "top element")); ++ ++ // CraftBukkit start ++ (map1.computeIfAbsent(recipeholder.value().getType(), (recipes) -> { ++ return new Object2ObjectLinkedOpenHashMap<>(); ++ // CraftBukkit end ++ })).put(minecraftkey, recipeholder); ++ builder.put(minecraftkey, recipeholder); ++ } catch (IllegalArgumentException | JsonParseException jsonparseexception) { ++ RecipeManager.LOGGER.error("Parsing error loading recipe {}", minecraftkey, jsonparseexception); + } + } + +- this.recipes = map.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, entry1 -> entry1.getValue().build())); +- this.byName = builder.build(); +- LOGGER.info("Loaded {} recipes", map.size()); ++ this.recipes = (Map) map1.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry1) -> { ++ return (entry1.getValue()); // CraftBukkit ++ })); ++ this.byName = Maps.newHashMap(builder.build()); // CraftBukkit ++ RecipeManager.LOGGER.info("Loaded {} recipes", map1.size()); + } + ++ // CraftBukkit start ++ public void addRecipe(RecipeHolder irecipe) { ++ Object2ObjectLinkedOpenHashMap> map = this.recipes.get(irecipe.value().getType()); // CraftBukkit ++ ++ if (byName.containsKey(irecipe.id()) || map.containsKey(irecipe.id())) { ++ throw new IllegalStateException("Duplicate recipe ignored with ID " + irecipe.id()); ++ } else { ++ map.putAndMoveToFirst(irecipe.id(), irecipe); // CraftBukkit - SPIGOT-4638: last recipe gets priority ++ byName.put(irecipe.id(), irecipe); ++ } ++ } ++ // CraftBukkit end ++ + public boolean hadErrorsLoading() { + return this.hasErrors; + } + + public > Optional> getRecipeFor(RecipeType recipeType, C inventory, Level level) { +- return this.byType(recipeType).values().stream().filter(recipeHolder -> recipeHolder.value().matches(inventory, level)).findFirst(); ++ // CraftBukkit start ++ Optional> recipe = this.byType(recipeType).values().stream().filter((recipeholder) -> { ++ return recipeholder.value().matches(inventory, level); ++ }).findFirst(); ++ inventory.setCurrentRecipe(recipe.orElse(null)); // CraftBukkit - Clear recipe when no recipe is found ++ return recipe; ++ // CraftBukkit end + } + + public > Optional>> getRecipeFor( +@@ -107,7 +145,7 @@ + } + + private > Map> byType(RecipeType recipeType) { +- return (Map>) ((Map) this.recipes.getOrDefault(recipeType, Collections.emptyMap())); ++ return (Map) this.recipes.getOrDefault(recipeType, new Object2ObjectLinkedOpenHashMap<>()); // CraftBukkit + } + + public > NonNullList getRemainingItemsFor(RecipeType recipeType, C inventory, Level level) { +@@ -144,21 +188,45 @@ + + public void replaceRecipes(Iterable> recipes) { + this.hasErrors = false; +- Map, Map>> map = Maps.newHashMap(); ++ Map, Object2ObjectLinkedOpenHashMap>> map = Maps.newHashMap(); // CraftBukkit + Builder> builder = ImmutableMap.builder(); +- recipes.forEach(recipeHolder -> { +- Map> map1 = map.computeIfAbsent(recipeHolder.value().getType(), recipeType -> Maps.newHashMap()); +- ResourceLocation resourceLocation = recipeHolder.id(); +- RecipeHolder recipeHolder1 = map1.put(resourceLocation, (RecipeHolder)recipeHolder); +- builder.put(resourceLocation, (RecipeHolder)recipeHolder); +- if (recipeHolder1 != null) { +- throw new IllegalStateException("Duplicate recipe ignored with ID " + resourceLocation); ++ ++ recipes.forEach((recipeholder) -> { ++ Map> map1 = (Map) map.computeIfAbsent(recipeholder.value().getType(), (recipes) -> { ++ return new Object2ObjectLinkedOpenHashMap<>(); // CraftBukkit ++ }); ++ ResourceLocation minecraftkey = recipeholder.id(); ++ RecipeHolder recipeholder1 = (RecipeHolder) map1.put(minecraftkey, recipeholder); ++ ++ builder.put(minecraftkey, recipeholder); ++ if (recipeholder1 != null) { ++ throw new IllegalStateException("Duplicate recipe ignored with ID " + minecraftkey); + } + }); + this.recipes = ImmutableMap.copyOf(map); +- this.byName = builder.build(); ++ this.byName = Maps.newHashMap(builder.build()); // CraftBukkit + } + ++ // CraftBukkit start ++ public boolean removeRecipe(ResourceLocation mcKey) { ++ for (Object2ObjectLinkedOpenHashMap> recipes : recipes.values()) { ++ recipes.remove(mcKey); ++ } ++ ++ return byName.remove(mcKey) != null; ++ } ++ ++ public void clearRecipes() { ++ this.recipes = Maps.newHashMap(); ++ ++ for (RecipeType recipeType : BuiltInRegistries.RECIPE_TYPE) { ++ this.recipes.put(recipeType, new Object2ObjectLinkedOpenHashMap<>()); ++ } ++ ++ this.byName = Maps.newHashMap(); ++ } ++ // CraftBukkit end ++ + public static > RecipeManager.CachedCheck createCheck(final RecipeType recipeType) { + return new RecipeManager.CachedCheck() { + @Nullable diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/ShapedRecipe.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/ShapedRecipe.java.patch new file mode 100644 index 0000000000..f5537291f4 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/ShapedRecipe.java.patch @@ -0,0 +1,86 @@ +--- a/net/minecraft/world/item/crafting/ShapedRecipe.java ++++ b/net/minecraft/world/item/crafting/ShapedRecipe.java +@@ -10,6 +9,13 @@ + import net.minecraft.world.inventory.CraftingContainer; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftShapedRecipe; ++import org.bukkit.inventory.RecipeChoice; ++// CraftBukkit end + + public class ShapedRecipe implements CraftingRecipe { + final ShapedRecipePattern pattern; +@@ -30,7 +37,69 @@ + this(string, craftingBookCategory, shapedRecipePattern, itemStack, true); + } + ++ // CraftBukkit start + @Override ++ public org.bukkit.inventory.ShapedRecipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ CraftShapedRecipe recipe = new CraftShapedRecipe(id, result, this); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ switch (this.pattern.height()) { ++ case 1: ++ switch (this.pattern.width()) { ++ case 1: ++ recipe.shape("a"); ++ break; ++ case 2: ++ recipe.shape("ab"); ++ break; ++ case 3: ++ recipe.shape("abc"); ++ break; ++ } ++ break; ++ case 2: ++ switch (this.pattern.width()) { ++ case 1: ++ recipe.shape("a","b"); ++ break; ++ case 2: ++ recipe.shape("ab","cd"); ++ break; ++ case 3: ++ recipe.shape("abc","def"); ++ break; ++ } ++ break; ++ case 3: ++ switch (this.pattern.width()) { ++ case 1: ++ recipe.shape("a","b","c"); ++ break; ++ case 2: ++ recipe.shape("ab","cd","ef"); ++ break; ++ case 3: ++ recipe.shape("abc","def","ghi"); ++ break; ++ } ++ break; ++ } ++ char c = 'a'; ++ for (Ingredient list : this.pattern.ingredients()) { ++ RecipeChoice choice = CraftRecipe.toBukkit(list); ++ if (choice != null) { ++ recipe.setIngredient(c, choice); ++ } ++ ++ c++; ++ } ++ return recipe; ++ } ++ // CraftBukkit end ++ ++ @Override + public RecipeSerializer getSerializer() { + return RecipeSerializer.SHAPED_RECIPE; + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/ShapelessRecipe.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/ShapelessRecipe.java.patch new file mode 100644 index 0000000000..97a06c348e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/ShapelessRecipe.java.patch @@ -0,0 +1,39 @@ +--- a/net/minecraft/world/item/crafting/ShapelessRecipe.java ++++ b/net/minecraft/world/item/crafting/ShapelessRecipe.java +@@ -13,6 +13,12 @@ + import net.minecraft.world.inventory.CraftingContainer; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftShapelessRecipe; ++// CraftBukkit end + + public class ShapelessRecipe implements CraftingRecipe { + final String group; +@@ -27,7 +34,23 @@ + this.ingredients = list; + } + ++ // CraftBukkit start ++ @SuppressWarnings("unchecked") + @Override ++ public org.bukkit.inventory.ShapelessRecipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ CraftShapelessRecipe recipe = new CraftShapelessRecipe(id, result, this); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ for (Ingredient list : this.ingredients) { ++ recipe.addIngredient(CraftRecipe.toBukkit(list)); ++ } ++ return recipe; ++ } ++ // CraftBukkit end ++ ++ @Override + public RecipeSerializer getSerializer() { + return RecipeSerializer.SHAPELESS_RECIPE; + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/SmeltingRecipe.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/SmeltingRecipe.java.patch new file mode 100644 index 0000000000..352ab54802 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/SmeltingRecipe.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/item/crafting/SmeltingRecipe.java ++++ b/net/minecraft/world/item/crafting/SmeltingRecipe.java +@@ -3,6 +3,14 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftFurnaceRecipe; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class SmeltingRecipe extends AbstractCookingRecipe { + public SmeltingRecipe(String string, CookingBookCategory cookingBookCategory, Ingredient ingredient, ItemStack itemStack, float f, int i) { + super(RecipeType.SMELTING, string, cookingBookCategory, ingredient, itemStack, f, i); +@@ -17,4 +26,17 @@ + public RecipeSerializer getSerializer() { + return RecipeSerializer.SMELTING_RECIPE; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftFurnaceRecipe recipe = new CraftFurnaceRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/SmithingTransformRecipe.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/SmithingTransformRecipe.java.patch new file mode 100644 index 0000000000..1928a3054d --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/SmithingTransformRecipe.java.patch @@ -0,0 +1,60 @@ +--- a/net/minecraft/world/item/crafting/SmithingTransformRecipe.java ++++ b/net/minecraft/world/item/crafting/SmithingTransformRecipe.java +@@ -10,6 +9,13 @@ + import net.minecraft.world.Container; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftSmithingTransformRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end + + public class SmithingTransformRecipe implements SmithingRecipe { + final Ingredient template; +@@ -70,17 +78,33 @@ + return Stream.of(this.template, this.base, this.addition).anyMatch(Ingredient::isEmpty); + } + +- public static class Serializer implements RecipeSerializer { +- private static final Codec CODEC = RecordCodecBuilder.create( +- instance -> instance.group( +- Ingredient.CODEC.fieldOf("template").forGetter(smithingTransformRecipe -> smithingTransformRecipe.template), +- Ingredient.CODEC.fieldOf("base").forGetter(smithingTransformRecipe -> smithingTransformRecipe.base), +- Ingredient.CODEC.fieldOf("addition").forGetter(smithingTransformRecipe -> smithingTransformRecipe.addition), +- ItemStack.ITEM_WITH_COUNT_CODEC.fieldOf("result").forGetter(smithingTransformRecipe -> smithingTransformRecipe.result) +- ) +- .apply(instance, SmithingTransformRecipe::new) +- ); ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); + ++ CraftSmithingTransformRecipe recipe = new CraftSmithingTransformRecipe(id, result, CraftRecipe.toBukkit(this.template), CraftRecipe.toBukkit(this.base), CraftRecipe.toBukkit(this.addition)); ++ ++ return recipe; ++ } ++ // CraftBukkit end ++ ++ public static class a implements RecipeSerializer { ++ ++ private static final Codec CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(Ingredient.CODEC.fieldOf("template").forGetter((smithingtransformrecipe) -> { ++ return smithingtransformrecipe.template; ++ }), Ingredient.CODEC.fieldOf("base").forGetter((smithingtransformrecipe) -> { ++ return smithingtransformrecipe.base; ++ }), Ingredient.CODEC.fieldOf("addition").forGetter((smithingtransformrecipe) -> { ++ return smithingtransformrecipe.addition; ++ }), ItemStack.ITEM_WITH_COUNT_CODEC.fieldOf("result").forGetter((smithingtransformrecipe) -> { ++ return smithingtransformrecipe.result; ++ })).apply(instance, SmithingTransformRecipe::new); ++ }); ++ ++ public a() {} ++ + @Override + public Codec codec() { + return CODEC; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/SmithingTrimRecipe.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/SmithingTrimRecipe.java.patch new file mode 100644 index 0000000000..400058b878 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/SmithingTrimRecipe.java.patch @@ -0,0 +1,37 @@ +--- a/net/minecraft/world/item/crafting/SmithingTrimRecipe.java ++++ b/net/minecraft/world/item/crafting/SmithingTrimRecipe.java +@@ -18,6 +17,12 @@ + import net.minecraft.world.item.armortrim.TrimPattern; + import net.minecraft.world.item.armortrim.TrimPatterns; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftSmithingTrimRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end + + public class SmithingTrimRecipe implements SmithingRecipe { + final Ingredient template; +@@ -99,15 +113,12 @@ + return Stream.of(this.template, this.base, this.addition).anyMatch(Ingredient::isEmpty); + } + +- public static class Serializer implements RecipeSerializer { +- private static final Codec CODEC = RecordCodecBuilder.create( +- instance -> instance.group( +- Ingredient.CODEC.fieldOf("template").forGetter(smithingTrimRecipe -> smithingTrimRecipe.template), +- Ingredient.CODEC.fieldOf("base").forGetter(smithingTrimRecipe -> smithingTrimRecipe.base), +- Ingredient.CODEC.fieldOf("addition").forGetter(smithingTrimRecipe -> smithingTrimRecipe.addition) +- ) +- .apply(instance, SmithingTrimRecipe::new) +- ); ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ return new CraftSmithingTrimRecipe(id, CraftRecipe.toBukkit(this.template), CraftRecipe.toBukkit(this.base), CraftRecipe.toBukkit(this.addition)); ++ } ++ // CraftBukkit end + + @Override + public Codec codec() { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/SmokingRecipe.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/SmokingRecipe.java.patch new file mode 100644 index 0000000000..8ca8e06845 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/SmokingRecipe.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/item/crafting/SmokingRecipe.java ++++ b/net/minecraft/world/item/crafting/SmokingRecipe.java +@@ -3,6 +3,14 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftSmokingRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class SmokingRecipe extends AbstractCookingRecipe { + public SmokingRecipe(String string, CookingBookCategory cookingBookCategory, Ingredient ingredient, ItemStack itemStack, float f, int i) { + super(RecipeType.SMOKING, string, cookingBookCategory, ingredient, itemStack, f, i); +@@ -17,4 +26,17 @@ + public RecipeSerializer getSerializer() { + return RecipeSerializer.SMOKING_RECIPE; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftSmokingRecipe recipe = new CraftSmokingRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/StonecutterRecipe.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/StonecutterRecipe.java.patch new file mode 100644 index 0000000000..3d3dd4157c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/crafting/StonecutterRecipe.java.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/item/crafting/StonecutterRecipe.java ++++ b/net/minecraft/world/item/crafting/StonecutterRecipe.java +@@ -5,6 +5,14 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftStonecuttingRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class StonecutterRecipe extends SingleItemRecipe { + public StonecutterRecipe(String string, Ingredient ingredient, ItemStack itemStack) { + super(RecipeType.STONECUTTING, RecipeSerializer.STONECUTTER, string, ingredient, itemStack); +@@ -19,4 +28,16 @@ + public ItemStack getToastSymbol() { + return new ItemStack(Blocks.STONECUTTER); + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftStonecuttingRecipe recipe = new CraftStonecuttingRecipe(id, result, CraftRecipe.toBukkit(this.ingredient)); ++ recipe.setGroup(this.group); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/enchantment/DamageEnchantment.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/enchantment/DamageEnchantment.java.patch new file mode 100644 index 0000000000..e89dde3451 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/enchantment/DamageEnchantment.java.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/item/enchantment/DamageEnchantment.java ++++ b/net/minecraft/world/item/enchantment/DamageEnchantment.java +@@ -62,9 +57,14 @@ + + @Override + public void doPostAttack(LivingEntity user, Entity target, int level) { +- if (target instanceof LivingEntity livingEntity && this.type == 2 && level > 0 && livingEntity.getMobType() == MobType.ARTHROPOD) { +- int i = 20 + user.getRandom().nextInt(10 * level); +- livingEntity.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, i, 3)); ++ if (target instanceof LivingEntity) { ++ LivingEntity entityliving1 = (LivingEntity) target; ++ ++ if (this.type == 2 && level > 0 && entityliving1.getMobType() == EnumMonsterType.ARTHROPOD) { ++ int j = 20 + user.getRandom().nextInt(10 * level); ++ ++ entityliving1.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, j, 3), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit ++ } + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/enchantment/FrostWalkerEnchantment.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/enchantment/FrostWalkerEnchantment.java.patch new file mode 100644 index 0000000000..89a7a488e8 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/enchantment/FrostWalkerEnchantment.java.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/world/item/enchantment/FrostWalkerEnchantment.java ++++ b/net/minecraft/world/item/enchantment/FrostWalkerEnchantment.java +@@ -41,17 +44,22 @@ + int min = Math.min(16, 2 + levelConflicting); + BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); + +- for (BlockPos blockPos : BlockPos.betweenClosed(pos.offset(-min, -1, -min), pos.offset(min, -1, min))) { +- if (blockPos.closerToCenterThan(living.position(), (double)min)) { +- mutableBlockPos.set(blockPos.getX(), blockPos.getY() + 1, blockPos.getZ()); +- BlockState blockState1 = level.getBlockState(mutableBlockPos); +- if (blockState1.isAir()) { +- BlockState blockState2 = level.getBlockState(blockPos); +- if (blockState2 == FrostedIceBlock.meltsInto() +- && blockState.canSurvive(level, blockPos) +- && level.isUnobstructed(blockState, blockPos, CollisionContext.empty())) { +- level.setBlockAndUpdate(blockPos, blockState); +- level.scheduleTick(blockPos, Blocks.FROSTED_ICE, Mth.nextInt(living.getRandom(), 60, 120)); ++ while (iterator.hasNext()) { ++ BlockPos blockposition1 = (BlockPos) iterator.next(); ++ ++ if (blockposition1.closerToCenterThan(living.position(), (double) j)) { ++ blockposition_mutableblockposition.set(blockposition1.getX(), blockposition1.getY() + 1, blockposition1.getZ()); ++ IBlockData iblockdata1 = level.getBlockState(blockposition_mutableblockposition); ++ ++ if (iblockdata1.isAir()) { ++ IBlockData iblockdata2 = level.getBlockState(blockposition1); ++ ++ if (iblockdata2 == FrostedIceBlock.meltsInto() && iblockdata.canSurvive(level, blockposition1) && level.isUnobstructed(iblockdata, blockposition1, CollisionContext.empty())) { ++ // CraftBukkit Start - Call EntityBlockFormEvent for Frost Walker ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, blockposition1, iblockdata, living)) { ++ level.scheduleTick(blockposition1, Blocks.FROSTED_ICE, Mth.nextInt(living.getRandom(), 60, 120)); ++ } ++ // CraftBukkit End + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/trading/Merchant.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/trading/Merchant.java.patch new file mode 100644 index 0000000000..75f2487c54 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/trading/Merchant.java.patch @@ -0,0 +1,9 @@ +--- a/net/minecraft/world/item/trading/Merchant.java ++++ b/net/minecraft/world/item/trading/Merchant.java +@@ -49,4 +52,6 @@ + } + + boolean isClientSide(); ++ ++ org.bukkit.craftbukkit.inventory.CraftMerchant getCraftMerchant(); // CraftBukkit + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/trading/MerchantOffer.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/trading/MerchantOffer.java.patch new file mode 100644 index 0000000000..260f3829e8 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/item/trading/MerchantOffer.java.patch @@ -0,0 +1,73 @@ +--- a/net/minecraft/world/item/trading/MerchantOffer.java ++++ b/net/minecraft/world/item/trading/MerchantOffer.java +@@ -5,6 +5,8 @@ + import net.minecraft.util.Mth; + import net.minecraft.world.item.ItemStack; + ++import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; // CraftBukkit ++ + public class MerchantOffer { + private final ItemStack baseCostA; + private final ItemStack costB; +@@ -17,6 +9,33 @@ + private float priceMultiplier; + private int xp = 1; + ++ public ItemStack baseCostA; ++ public ItemStack costB; ++ public final ItemStack result; ++ public int uses; ++ public int maxUses; ++ public boolean rewardExp; ++ public int specialPriceDiff; ++ public int demand; ++ public float priceMultiplier; ++ public int xp; ++ // CraftBukkit start ++ private CraftMerchantRecipe bukkitHandle; ++ ++ public CraftMerchantRecipe asBukkit() { ++ return (bukkitHandle == null) ? bukkitHandle = new CraftMerchantRecipe(this) : bukkitHandle; ++ } ++ ++ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, CraftMerchantRecipe bukkit) { ++ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, 0, bukkit); ++ } ++ ++ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, int demand, CraftMerchantRecipe bukkit) { ++ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, demand); ++ this.bukkitHandle = bukkit; ++ } ++ // CraftBukkit end ++ + public MerchantOffer(CompoundTag compoundTag) { + this.baseCostA = ItemStack.of(compoundTag.getCompound("buy")); + this.costB = ItemStack.of(compoundTag.getCompound("buyB")); +@@ -88,9 +113,11 @@ + if (this.baseCostA.isEmpty()) { + return ItemStack.EMPTY; + } else { +- int count = this.baseCostA.getCount(); +- int max = Math.max(0, Mth.floor((float)(count * this.demand) * this.priceMultiplier)); +- return this.baseCostA.copyWithCount(Mth.clamp(count + max + this.specialPriceDiff, 1, this.baseCostA.getItem().getMaxStackSize())); ++ int i = this.baseCostA.getCount(); ++ if (i <= 0) return ItemStack.EMPTY; // CraftBukkit - SPIGOT-5476 ++ int j = Math.max(0, Mth.floor((float) (i * this.demand) * this.priceMultiplier)); ++ ++ return this.baseCostA.copyWithCount(Mth.clamp(i + j + this.specialPriceDiff, 1, this.baseCostA.getItem().getMaxStackSize())); + } + } + +@@ -210,7 +235,11 @@ + if (!this.satisfiedBy(playerOfferA, playerOfferB)) { + return false; + } else { +- playerOfferA.shrink(this.getCostA().getCount()); ++ // CraftBukkit start ++ if (!this.getCostA().isEmpty()) { ++ playerOfferA.shrink(this.getCostA().getCount()); ++ } ++ // CraftBukkit end + if (!this.getCostB().isEmpty()) { + playerOfferB.shrink(this.getCostB().getCount()); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/BaseCommandBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/BaseCommandBlock.java.patch new file mode 100644 index 0000000000..6ad276ed91 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/BaseCommandBlock.java.patch @@ -0,0 +1,76 @@ +--- a/net/minecraft/world/level/BaseCommandBlock.java ++++ b/net/minecraft/world/level/BaseCommandBlock.java +@@ -28,7 +29,11 @@ + @Nullable + private Component lastOutput; + private String command = ""; +- private Component name = DEFAULT_NAME; ++ private Component name; ++ // CraftBukkit start ++ @Override ++ public abstract org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper); ++ // CraftBukkit end + + public int getSuccessCount() { + return this.successCount; +@@ -101,30 +111,36 @@ + } + + public boolean performCommand(Level level) { +- if (level.isClientSide || level.getGameTime() == this.lastExecution) { +- return false; +- } else if ("Searge".equalsIgnoreCase(this.command)) { +- this.lastOutput = Component.literal("#itzlipofutzli"); +- this.successCount = 1; +- return true; +- } else { +- this.successCount = 0; +- MinecraftServer server = this.getLevel().getServer(); +- if (server.isCommandBlockEnabled() && !StringUtil.isNullOrEmpty(this.command)) { +- try { +- this.lastOutput = null; +- CommandSourceStack commandSourceStack = this.createCommandSourceStack().withCallback((flag, i) -> { +- if (flag) { +- this.successCount++; +- } +- }); +- server.getCommands().performPrefixedCommand(commandSourceStack, this.command); +- } catch (Throwable var6) { +- CrashReport crashReport = CrashReport.forThrowable(var6, "Executing command block"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Command to be executed"); +- crashReportCategory.setDetail("Command", this::getCommand); +- crashReportCategory.setDetail("Name", () -> this.getName().getString()); +- throw new ReportedException(crashReport); ++ if (!level.isClientSide && level.getGameTime() != this.lastExecution) { ++ if ("Searge".equalsIgnoreCase(this.command)) { ++ this.lastOutput = Component.literal("#itzlipofutzli"); ++ this.successCount = 1; ++ return true; ++ } else { ++ this.successCount = 0; ++ MinecraftServer minecraftserver = this.getLevel().getServer(); ++ ++ if (minecraftserver.isCommandBlockEnabled() && !StringUtil.isNullOrEmpty(this.command)) { ++ try { ++ this.lastOutput = null; ++ CommandSourceStack commandlistenerwrapper = this.createCommandSourceStack().withCallback((flag, i) -> { ++ if (flag) { ++ ++this.successCount; ++ } ++ ++ }); ++ ++ minecraftserver.getCommands().dispatchServerCommand(commandlistenerwrapper, this.command); // CraftBukkit ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Executing command block"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Command to be executed"); ++ ++ crashreportsystemdetails.setDetail("Command", this::getCommand); ++ crashreportsystemdetails.setDetail("Name", () -> { ++ return this.getName().getString(); ++ }); ++ throw new ReportedException(crashreport); ++ } + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/BaseSpawner.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/BaseSpawner.java.patch new file mode 100644 index 0000000000..b15a786d4a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/BaseSpawner.java.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/world/level/BaseSpawner.java ++++ b/net/minecraft/world/level/BaseSpawner.java +@@ -47,6 +52,7 @@ + + public void setEntityId(EntityType type, @Nullable Level level, RandomSource random, BlockPos pos) { + this.getOrCreateNextSpawnData(level, random, pos).getEntityToSpawn().putString("id", BuiltInRegistries.ENTITY_TYPE.getKey(type).toString()); ++ this.spawnPotentials = SimpleWeightedRandomList.empty(); // CraftBukkit - SPIGOT-3496, MC-92282 + } + + private boolean isNearPlayer(Level level, BlockPos pos) { +@@ -157,7 +155,12 @@ + } + } + +- if (!serverLevel.tryAddFreshEntityWithPassengers(entity)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) { ++ continue; ++ } ++ if (!serverLevel.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER)) { ++ // CraftBukkit end + this.delay(serverLevel, pos); + return; + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/BlockGetter.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/BlockGetter.java.patch new file mode 100644 index 0000000000..792bece095 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/BlockGetter.java.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/world/level/BlockGetter.java ++++ b/net/minecraft/world/level/BlockGetter.java +@@ -64,22 +58,30 @@ + ); + } + ++ // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace ++ default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition) { ++ IBlockData iblockdata = this.getBlockState(blockposition); ++ FluidState fluid = this.getFluidState(blockposition); ++ Vec3 vec3d = raytrace1.getFrom(); ++ Vec3 vec3d1 = raytrace1.getTo(); ++ VoxelShape voxelshape = raytrace1.getBlockShape(iblockdata, this, blockposition); ++ BlockHitResult movingobjectpositionblock = this.clipWithInteractionOverride(vec3d, vec3d1, blockposition, voxelshape, iblockdata); ++ VoxelShape voxelshape1 = raytrace1.getFluidShape(fluid, this, blockposition); ++ BlockHitResult movingobjectpositionblock1 = voxelshape1.clip(vec3d, vec3d1, blockposition); ++ double d0 = movingobjectpositionblock == null ? Double.MAX_VALUE : raytrace1.getFrom().distanceToSqr(movingobjectpositionblock.getLocation()); ++ double d1 = movingobjectpositionblock1 == null ? Double.MAX_VALUE : raytrace1.getFrom().distanceToSqr(movingobjectpositionblock1.getLocation()); ++ ++ return d0 <= d1 ? movingobjectpositionblock : movingobjectpositionblock1; ++ } ++ // CraftBukkit end ++ + default BlockHitResult clip(ClipContext context) { +- return traverseBlocks(context.getFrom(), context.getTo(), context, (traverseContext, traversePos) -> { +- BlockState blockState = this.getBlockState(traversePos); +- FluidState fluidState = this.getFluidState(traversePos); +- Vec3 from = traverseContext.getFrom(); +- Vec3 to = traverseContext.getTo(); +- VoxelShape blockShape = traverseContext.getBlockShape(blockState, this, traversePos); +- BlockHitResult blockHitResult = this.clipWithInteractionOverride(from, to, traversePos, blockShape, blockState); +- VoxelShape fluidShape = traverseContext.getFluidShape(fluidState, this, traversePos); +- BlockHitResult blockHitResult1 = fluidShape.clip(from, to, traversePos); +- double d = blockHitResult == null ? Double.MAX_VALUE : traverseContext.getFrom().distanceToSqr(blockHitResult.getLocation()); +- double d1 = blockHitResult1 == null ? Double.MAX_VALUE : traverseContext.getFrom().distanceToSqr(blockHitResult1.getLocation()); +- return d <= d1 ? blockHitResult : blockHitResult1; +- }, failContext -> { +- Vec3 vec3 = failContext.getFrom().subtract(failContext.getTo()); +- return BlockHitResult.miss(failContext.getTo(), Direction.getNearest(vec3.x, vec3.y, vec3.z), BlockPos.containing(failContext.getTo())); ++ return (BlockHitResult) traverseBlocks(context.getFrom(), context.getTo(), context, (raytrace1, blockposition) -> { ++ return this.clip(raytrace1, blockposition); // CraftBukkit - moved into separate method ++ }, (raytrace1) -> { ++ Vec3 vec3d = raytrace1.getFrom().subtract(raytrace1.getTo()); ++ ++ return BlockHitResult.miss(raytrace1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(raytrace1.getTo())); + }); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/ClipContext.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/ClipContext.java.patch new file mode 100644 index 0000000000..a747312578 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/ClipContext.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/level/ClipContext.java ++++ b/net/minecraft/world/level/ClipContext.java +@@ -21,7 +22,7 @@ + private final CollisionContext collisionContext; + + public ClipContext(Vec3 from, Vec3 to, ClipContext.Block block, ClipContext.Fluid fluid, Entity entity) { +- this(from, to, block, fluid, CollisionContext.of(entity)); ++ this(from, to, block, fluid, (entity == null) ? CollisionContext.empty() : CollisionContext.of(entity)); // CraftBukkit + } + + public ClipContext(Vec3 vec3, Vec3 vec31, ClipContext.Block block, ClipContext.Fluid fluid, CollisionContext collisionContext) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/Explosion.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/Explosion.java.patch new file mode 100644 index 0000000000..c30cb70685 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/Explosion.java.patch @@ -0,0 +1,209 @@ +--- a/net/minecraft/world/level/Explosion.java ++++ b/net/minecraft/world/level/Explosion.java +@@ -36,6 +40,12 @@ + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++import net.minecraft.world.level.block.Blocks; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityExplodeEvent; ++import org.bukkit.Location; ++import org.bukkit.event.block.BlockExplodeEvent; ++// CraftBukkit end + + public class Explosion { + private static final ExplosionDamageCalculator EXPLOSION_DAMAGE_CALCULATOR = new ExplosionDamageCalculator(); +@@ -55,8 +66,12 @@ + private final ParticleOptions smallExplosionParticles; + private final ParticleOptions largeExplosionParticles; + private final SoundEvent explosionSound; +- private final ObjectArrayList toBlow = new ObjectArrayList<>(); +- private final Map hitPlayers = Maps.newHashMap(); ++ private final ObjectArrayList toBlow; ++ private final Map hitPlayers; ++ // CraftBukkit - add field ++ public boolean wasCanceled = false; ++ public float yield; ++ // CraftBukkit end + + public static DamageSource getDefaultDamageSource(Level level, @Nullable Entity entity) { + return level.damageSources().explosion(entity, getIndirectSourceEntityInternal(entity)); +@@ -138,17 +97,18 @@ + ) { + this.level = level; + this.source = entity; +- this.radius = f; +- this.x = d; ++ this.radius = (float) Math.max(f, 0.0); // CraftBukkit - clamp bad values ++ this.x = d0; + this.y = d1; + this.z = d2; + this.fire = flag; +- this.blockInteraction = blockInteraction; +- this.damageSource = damageSource == null ? level.damageSources().explosion(this) : damageSource; +- this.damageCalculator = explosionDamageCalculator == null ? this.makeDamageCalculator(entity) : explosionDamageCalculator; +- this.smallExplosionParticles = particleOptions; +- this.largeExplosionParticles = particleOptions1; +- this.explosionSound = soundEvent; ++ this.blockInteraction = explosion_effect; ++ this.damageSource = damagesource == null ? world.damageSources().explosion(this) : damagesource; ++ this.damageCalculator = explosiondamagecalculator == null ? this.makeDamageCalculator(entity) : explosiondamagecalculator; ++ this.smallExplosionParticles = particleparam; ++ this.largeExplosionParticles = particleparam1; ++ this.explosionSound = soundeffect; ++ this.yield = this.blockInteraction == Explosion.Effect.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F; // CraftBukkit + } + + private ExplosionDamageCalculator makeDamageCalculator(@Nullable Entity entity) { +@@ -198,6 +159,11 @@ + } + + public void explode() { ++ // CraftBukkit start ++ if (this.radius < 0.1F) { ++ return; ++ } ++ // CraftBukkit end + this.level.gameEvent(this.source, GameEvent.EXPLODE, new Vec3(this.x, this.y, this.z)); + Set set = Sets.newHashSet(); + int i = 16; +@@ -270,7 +246,37 @@ + double var43 = d8 / squareRoot1; + double var45 = d9 / squareRoot1; + if (this.damageCalculator.shouldDamageEntity(this, entity)) { +- entity.hurt(this.damageSource, this.damageCalculator.getEntityDamageAmount(this, entity)); ++ // CraftBukkit start ++ ++ // Special case ender dragon only give knockback if no damage is cancelled ++ // Thinks to note: ++ // - Setting a velocity to a ComplexEntityPart is ignored (and therefore not needed) ++ // - Damaging ComplexEntityPart while forward the damage to EntityEnderDragon ++ // - Damaging EntityEnderDragon does nothing ++ // - EntityEnderDragon hitbock always covers the other parts and is therefore always present ++ if (entity instanceof EnderDragonPart) { ++ continue; ++ } ++ ++ CraftEventFactory.entityDamage = source; ++ entity.lastDamageCancelled = false; ++ ++ if (entity instanceof EnderDragon) { ++ for (EnderDragonPart entityComplexPart : ((EnderDragon) entity).subEntities) { ++ // Calculate damage separately for each EntityComplexPart ++ if (list.contains(entityComplexPart)) { ++ entityComplexPart.hurt(this.damageSource, this.damageCalculator.getEntityDamageAmount(this, entity)); ++ } ++ } ++ } else { ++ entity.hurt(this.damageSource, this.damageCalculator.getEntityDamageAmount(this, entity)); ++ } ++ ++ CraftEventFactory.entityDamage = null; ++ if (entity.lastDamageCancelled) { // SPIGOT-5339, SPIGOT-6252, SPIGOT-6777: Skip entity if damage event was cancelled ++ continue; ++ } ++ // CraftBukkit end + } + + double d10 = (1.0 - d6) * (double)getSeenPercent(vec3, entity); +@@ -329,6 +334,11 @@ + this.level.getProfiler().push("explosion_blocks"); + List> list = new ArrayList<>(); + Util.shuffle(this.toBlow, this.level.random); ++ ObjectListIterator objectlistiterator = this.toBlow.iterator(); ++ // CraftBukkit start ++ org.bukkit.World bworld = this.level.getWorld(); ++ org.bukkit.entity.Entity explode = this.source == null ? null : this.source.getBukkitEntity(); ++ Location location = new Location(bworld, this.x, this.y, this.z); + + for (BlockPos blockPos : this.toBlow) { + this.level +@@ -340,27 +365,76 @@ + Block.popResource(this.level, pair.getSecond(), pair.getFirst()); + } + ++ this.toBlow.clear(); ++ ++ for (org.bukkit.block.Block bblock : bukkitBlocks) { ++ BlockPos coords = new BlockPos(bblock.getX(), bblock.getY(), bblock.getZ()); ++ toBlow.add(coords); ++ } ++ ++ if (this.wasCanceled) { ++ return; ++ } ++ // CraftBukkit end ++ objectlistiterator = this.toBlow.iterator(); ++ ++ while (objectlistiterator.hasNext()) { ++ BlockPos blockposition = (BlockPos) objectlistiterator.next(); ++ // CraftBukkit start - TNTPrimeEvent ++ IBlockData iblockdata = this.level.getBlockState(blockposition); ++ Block block = iblockdata.getBlock(); ++ if (block instanceof net.minecraft.world.level.block.TntBlock) { ++ Entity sourceEntity = source == null ? null : source; ++ BlockPos sourceBlock = sourceEntity == null ? BlockPos.containing(this.x, this.y, this.z) : null; ++ if (!CraftEventFactory.callTNTPrimeEvent(this.level, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.EXPLOSION, sourceEntity, sourceBlock)) { ++ this.level.sendBlockUpdated(blockposition, Blocks.AIR.defaultBlockState(), iblockdata, 3); // Update the block on the client ++ continue; ++ } ++ } ++ // CraftBukkit end ++ ++ this.level.getBlockState(blockposition).onExplosionHit(this.level, blockposition, this, (itemstack, blockposition1) -> { ++ addOrAppendStack(list, itemstack, blockposition1); ++ }); ++ } ++ ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Pair pair = (Pair) iterator.next(); ++ ++ Block.popResource(this.level, (BlockPos) pair.getSecond(), (ItemStack) pair.getFirst()); ++ } ++ + this.level.getProfiler().pop(); + } + + if (this.fire) { +- for (BlockPos blockPos1 : this.toBlow) { +- if (this.random.nextInt(3) == 0 +- && this.level.getBlockState(blockPos1).isAir() +- && this.level.getBlockState(blockPos1.below()).isSolidRender(this.level, blockPos1.below())) { +- this.level.setBlockAndUpdate(blockPos1, BaseFireBlock.getState(this.level, blockPos1)); ++ ObjectListIterator objectlistiterator1 = this.toBlow.iterator(); ++ ++ while (objectlistiterator1.hasNext()) { ++ BlockPos blockposition1 = (BlockPos) objectlistiterator1.next(); ++ ++ if (this.random.nextInt(3) == 0 && this.level.getBlockState(blockposition1).isAir() && this.level.getBlockState(blockposition1.below()).isSolidRender(this.level, blockposition1.below())) { ++ // CraftBukkit start - Ignition by explosion ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(this.level, blockposition1, this).isCancelled()) { ++ this.level.setBlockAndUpdate(blockposition1, BaseFireBlock.getState(this.level, blockposition1)); ++ } ++ // CraftBukkit end + } + } + } + } + +- private static void addOrAppendStack(List> list, ItemStack itemStack, BlockPos blockPos) { +- for (int i = 0; i < list.size(); i++) { +- Pair pair = list.get(i); +- ItemStack itemStack1 = pair.getFirst(); +- if (ItemEntity.areMergable(itemStack1, itemStack)) { +- list.set(i, Pair.of(ItemEntity.merge(itemStack1, itemStack, 16), pair.getSecond())); +- if (itemStack.isEmpty()) { ++ private static void addOrAppendStack(List> list, ItemStack itemstack, BlockPos blockposition) { ++ if (itemstack.isEmpty()) return; // CraftBukkit - SPIGOT-5425 ++ for (int i = 0; i < list.size(); ++i) { ++ Pair pair = (Pair) list.get(i); ++ ItemStack itemstack1 = (ItemStack) pair.getFirst(); ++ ++ if (ItemEntity.areMergable(itemstack1, itemstack)) { ++ list.set(i, Pair.of(ItemEntity.merge(itemstack1, itemstack, 16), (BlockPos) pair.getSecond())); ++ if (itemstack.isEmpty()) { + return; + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/GameRules.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/GameRules.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/GameRules.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/Level.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/Level.java.patch new file mode 100644 index 0000000000..1511956e29 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/Level.java.patch @@ -0,0 +1,341 @@ +--- a/net/minecraft/world/level/Level.java ++++ b/net/minecraft/world/level/Level.java +@@ -73,6 +79,27 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.scores.Scoreboard; + ++// CraftBukkit start ++import java.util.HashMap; ++import java.util.Map; ++import net.minecraft.network.protocol.game.ClientboundSetBorderCenterPacket; ++import net.minecraft.network.protocol.game.ClientboundSetBorderLerpSizePacket; ++import net.minecraft.network.protocol.game.ClientboundSetBorderSizePacket; ++import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDelayPacket; ++import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDistancePacket; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.block.CapturedBlockState; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.craftbukkit.util.CraftSpawnCategory; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.entity.SpawnCategory; ++import org.bukkit.event.block.BlockPhysicsEvent; ++import org.bukkit.event.world.GenericGameEvent; ++// CraftBukkit end ++ + public abstract class Level implements LevelAccessor, AutoCloseable { + public static final Codec> RESOURCE_KEY_CODEC = ResourceKey.codec(Registries.DIMENSION); + public static final ResourceKey OVERWORLD = ResourceKey.create(Registries.DIMENSION, new ResourceLocation("overworld")); +@@ -113,35 +142,63 @@ + private final DamageSources damageSources; + private long subTickCount; + +- protected Level( +- WritableLevelData levelData, +- ResourceKey dimension, +- RegistryAccess registryAccess, +- Holder dimensionTypeRegistration, +- Supplier profiler, +- boolean isClientSide, +- boolean isDebug, +- long biomeZoomSeed, +- int maxChainedNeighborUpdates +- ) { +- this.profiler = profiler; +- this.levelData = levelData; +- this.dimensionTypeRegistration = dimensionTypeRegistration; +- this.dimensionTypeId = dimensionTypeRegistration.unwrapKey() +- .orElseThrow(() -> new IllegalArgumentException("Dimension must be registered, got " + dimensionTypeRegistration)); +- final DimensionType dimensionType = dimensionTypeRegistration.value(); +- this.dimension = dimension; +- this.isClientSide = isClientSide; +- if (dimensionType.coordinateScale() != 1.0) { ++ // CraftBukkit start Added the following ++ private final CraftWorld world; ++ public boolean pvpMode; ++ public boolean keepSpawnInMemory = true; ++ public org.bukkit.generator.ChunkGenerator generator; ++ ++ public boolean preventPoiUpdated = false; // CraftBukkit - SPIGOT-5710 ++ public boolean captureBlockStates = false; ++ public boolean captureTreeGeneration = false; ++ public Map capturedBlockStates = new java.util.LinkedHashMap<>(); ++ public Map capturedTileEntities = new HashMap<>(); ++ public List captureDrops; ++ public final it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap ticksPerSpawnCategory = new it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<>(); ++ public boolean populating; ++ ++ public CraftWorld getWorld() { ++ return this.world; ++ } ++ ++ public CraftServer getCraftServer() { ++ return (CraftServer) Bukkit.getServer(); ++ } ++ ++ public abstract ResourceKey getTypeKey(); ++ ++ protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env) { ++ this.generator = gen; ++ this.world = new CraftWorld((ServerLevel) this, gen, biomeProvider, env); ++ ++ // CraftBukkit Ticks things ++ for (SpawnCategory spawnCategory : SpawnCategory.values()) { ++ if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { ++ this.ticksPerSpawnCategory.put(spawnCategory, (long) this.getCraftServer().getTicksPerSpawns(spawnCategory)); ++ } ++ } ++ ++ // CraftBukkit end ++ this.profiler = supplier; ++ this.levelData = worlddatamutable; ++ this.dimensionTypeRegistration = holder; ++ this.dimensionTypeId = (ResourceKey) holder.unwrapKey().orElseThrow(() -> { ++ return new IllegalArgumentException("Dimension must be registered, got " + holder); ++ }); ++ final DimensionType dimensionmanager = (DimensionType) holder.value(); ++ ++ this.dimension = resourcekey; ++ this.isClientSide = flag; ++ if (dimensionmanager.coordinateScale() != 1.0D) { + this.worldBorder = new WorldBorder() { + @Override + public double getCenterX() { +- return super.getCenterX() / dimensionType.coordinateScale(); ++ return super.getCenterX(); // CraftBukkit + } + + @Override + public double getCenterZ() { +- return super.getCenterZ() / dimensionType.coordinateScale(); ++ return super.getCenterZ(); // CraftBukkit + } + }; + } else { +@@ -149,11 +206,47 @@ + } + + this.thread = Thread.currentThread(); +- this.biomeManager = new BiomeManager(this, biomeZoomSeed); +- this.isDebug = isDebug; +- this.neighborUpdater = new CollectingNeighborUpdater(this, maxChainedNeighborUpdates); +- this.registryAccess = registryAccess; +- this.damageSources = new DamageSources(registryAccess); ++ this.biomeManager = new BiomeManager(this, i); ++ this.isDebug = flag1; ++ this.neighborUpdater = new CollectingNeighborUpdater(this, j); ++ this.registryAccess = iregistrycustom; ++ this.damageSources = new DamageSources(iregistrycustom); ++ // CraftBukkit start ++ getWorldBorder().world = (ServerLevel) this; ++ // From PlayerList.setPlayerFileData ++ getWorldBorder().addListener(new BorderChangeListener() { ++ @Override ++ public void onBorderSizeSet(WorldBorder border, double size) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderSizePacket(border), border.world); ++ } ++ ++ @Override ++ public void onBorderSizeLerping(WorldBorder border, double oldSize, double d1, long newSize) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderLerpSizePacket(border), border.world); ++ } ++ ++ @Override ++ public void onBorderCenterSet(WorldBorder border, double x, double d1) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderCenterPacket(border), border.world); ++ } ++ ++ @Override ++ public void onBorderSetWarningTime(WorldBorder border, int warningTime) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderWarningDelayPacket(border), border.world); ++ } ++ ++ @Override ++ public void onBorderSetWarningBlocks(WorldBorder border, int warningBlocks) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderWarningDistancePacket(border), border.world); ++ } ++ ++ @Override ++ public void onBorderSetDamagePerBlock(WorldBorder border, double damagePerBlock) {} ++ ++ @Override ++ public void onBorderSetDamageSafeZOne(WorldBorder border, double damageSafeZone) {} ++ }); ++ // CraftBukkit end + } + + @Override +@@ -209,7 +303,18 @@ + } + + @Override +- public boolean setBlock(BlockPos pos, BlockState state, int flags, int recursionLeft) { ++ public boolean setBlock(BlockPos pos, IBlockData state, int flags, int recursionLeft) { ++ // CraftBukkit start - tree generation ++ if (this.captureTreeGeneration) { ++ CapturedBlockState blockstate = capturedBlockStates.get(pos); ++ if (blockstate == null) { ++ blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags); ++ this.capturedBlockStates.put(pos.immutable(), blockstate); ++ } ++ blockstate.setData(state); ++ return true; ++ } ++ // CraftBukkit end + if (this.isOutsideBuildHeight(pos)) { + return false; + } else if (!this.isClientSide && this.isDebug()) { +@@ -217,8 +322,24 @@ + } else { + LevelChunk chunkAt = this.getChunkAt(pos); + Block block = state.getBlock(); +- BlockState blockState = chunkAt.setBlockState(pos, state, (flags & 64) != 0); +- if (blockState == null) { ++ ++ // CraftBukkit start - capture blockstates ++ boolean captured = false; ++ if (this.captureBlockStates && !this.capturedBlockStates.containsKey(pos)) { ++ CapturedBlockState blockstate = CapturedBlockState.getBlockState(this, pos, flags); ++ this.capturedBlockStates.put(pos.immutable(), blockstate); ++ captured = true; ++ } ++ // CraftBukkit end ++ ++ IBlockData iblockdata1 = chunk.setBlockState(pos, state, (flags & 64) != 0, (flags & 1024) == 0); // CraftBukkit custom NO_PLACE flag ++ ++ if (iblockdata1 == null) { ++ // CraftBukkit start - remove blockstate if failed (or the same) ++ if (this.captureBlockStates && captured) { ++ this.capturedBlockStates.remove(pos); ++ } ++ // CraftBukkit end + return false; + } else { + BlockState blockState1 = this.getBlockState(pos); +@@ -250,13 +373,66 @@ + this.onBlockStateChange(pos, blockState, blockState1); + } + ++ // CraftBukkit start ++ if (!this.captureBlockStates) { // Don't notify clients or update physics while capturing blockstates ++ // Modularize client and physic updates ++ notifyAndUpdatePhysics(pos, chunk, iblockdata1, state, iblockdata2, flags, recursionLeft); ++ } ++ // CraftBukkit end ++ + return true; + } + } + } + +- public void onBlockStateChange(BlockPos pos, BlockState blockState, BlockState newState) { ++ // CraftBukkit start - Split off from above in order to directly send client and physic updates ++ public void notifyAndUpdatePhysics(BlockPos blockposition, LevelChunk chunk, IBlockData oldBlock, IBlockData newBlock, IBlockData actualBlock, int i, int j) { ++ IBlockData iblockdata = newBlock; ++ IBlockData iblockdata1 = oldBlock; ++ IBlockData iblockdata2 = actualBlock; ++ if (iblockdata2 == iblockdata) { ++ if (iblockdata1 != iblockdata2) { ++ this.setBlocksDirty(blockposition, iblockdata1, iblockdata2); ++ } ++ ++ if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getFullStatus() != null && chunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement ++ this.sendBlockUpdated(blockposition, iblockdata1, iblockdata, i); ++ } ++ ++ if ((i & 1) != 0) { ++ this.blockUpdated(blockposition, iblockdata1.getBlock()); ++ if (!this.isClientSide && iblockdata.hasAnalogOutputSignal()) { ++ this.updateNeighbourForOutputSignal(blockposition, newBlock.getBlock()); ++ } ++ } ++ ++ if ((i & 16) == 0 && j > 0) { ++ int k = i & -34; ++ ++ // CraftBukkit start ++ iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam ++ CraftWorld world = ((ServerLevel) this).getWorld(); ++ if (world != null) { ++ BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata)); ++ this.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ iblockdata.updateNeighbourShapes(this, blockposition, k, j - 1); ++ iblockdata.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); ++ } ++ ++ // CraftBukkit start - SPIGOT-5710 ++ if (!preventPoiUpdated) { ++ this.onBlockStateChange(blockposition, iblockdata1, iblockdata2); ++ } ++ // CraftBukkit end ++ } + } ++ // CraftBukkit end + + @Override + public boolean removeBlock(BlockPos pos, boolean isMoving) { +@@ -340,7 +518,15 @@ + } + + @Override +- public BlockState getBlockState(BlockPos pos) { ++ public IBlockData getBlockState(BlockPos pos) { ++ // CraftBukkit start - tree generation ++ if (captureTreeGeneration) { ++ CapturedBlockState previous = capturedBlockStates.get(pos); ++ if (previous != null) { ++ return previous.getHandle(); ++ } ++ } ++ // CraftBukkit end + if (this.isOutsideBuildHeight(pos)) { + return Blocks.VOID_AIR.defaultBlockState(); + } else { +@@ -630,19 +732,30 @@ + @Nullable + @Override + public BlockEntity getBlockEntity(BlockPos pos) { +- if (this.isOutsideBuildHeight(pos)) { +- return null; +- } else { +- return !this.isClientSide && Thread.currentThread() != this.thread +- ? null +- : this.getChunkAt(pos).getBlockEntity(pos, LevelChunk.EntityCreationType.IMMEDIATE); ++ // CraftBukkit start ++ return getBlockEntity(pos, true); ++ } ++ ++ @Nullable ++ public BlockEntity getBlockEntity(BlockPos blockposition, boolean validate) { ++ if (capturedTileEntities.containsKey(blockposition)) { ++ return capturedTileEntities.get(blockposition); + } ++ // CraftBukkit end ++ return this.isOutsideBuildHeight(blockposition) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(blockposition).getBlockEntity(blockposition, LevelChunk.EnumTileEntityState.IMMEDIATE)); + } + + public void setBlockEntity(BlockEntity blockEntity) { +- BlockPos blockPos = blockEntity.getBlockPos(); +- if (!this.isOutsideBuildHeight(blockPos)) { +- this.getChunkAt(blockPos).addAndRegisterBlockEntity(blockEntity); ++ BlockPos blockposition = blockEntity.getBlockPos(); ++ ++ if (!this.isOutsideBuildHeight(blockposition)) { ++ // CraftBukkit start ++ if (captureBlockStates) { ++ capturedTileEntities.put(blockposition.immutable(), blockEntity); ++ return; ++ } ++ // CraftBukkit end ++ this.getChunkAt(blockposition).addAndRegisterBlockEntity(blockEntity); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/LevelAccessor.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/LevelAccessor.java.patch new file mode 100644 index 0000000000..af665f012d --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/LevelAccessor.java.patch @@ -0,0 +1,9 @@ +--- a/net/minecraft/world/level/LevelAccessor.java ++++ b/net/minecraft/world/level/LevelAccessor.java +@@ -114,4 +114,6 @@ + default void gameEvent(GameEvent event, BlockPos pos, GameEvent.Context context) { + this.gameEvent(event, Vec3.atCenterOf(pos), context); + } ++ ++ net.minecraft.server.level.ServerLevel getMinecraftWorld(); // CraftBukkit + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/LevelWriter.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/LevelWriter.java.patch new file mode 100644 index 0000000000..0a28444cc3 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/LevelWriter.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/level/LevelWriter.java ++++ b/net/minecraft/world/level/LevelWriter.java +@@ -27,4 +28,10 @@ + default boolean addFreshEntity(Entity entity) { + return false; + } ++ ++ // CraftBukkit start ++ default boolean addFreshEntity(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ return false; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/NaturalSpawner.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/NaturalSpawner.java.patch new file mode 100644 index 0000000000..eb4649b9bd --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/NaturalSpawner.java.patch @@ -0,0 +1,132 @@ +--- a/net/minecraft/world/level/NaturalSpawner.java ++++ b/net/minecraft/world/level/NaturalSpawner.java +@@ -46,6 +49,10 @@ + import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.util.CraftSpawnCategory; ++import org.bukkit.entity.SpawnCategory; ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; ++// CraftBukkit end + + public final class NaturalSpawner { + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -101,13 +118,31 @@ + ) { + level.getProfiler().push("spawner"); + +- for (MobCategory mobCategory : SPAWNING_CATEGORIES) { +- if ((spawnFriendlies || !mobCategory.isFriendly()) +- && (spawnMonsters || mobCategory.isFriendly()) +- && (forcedDespawn || !mobCategory.isPersistent()) +- && spawnState.canSpawnForCategory(mobCategory, chunk.getPos())) { +- spawnCategoryForChunk(mobCategory, level, chunk, spawnState::canSpawn, spawnState::afterSpawn); ++ LevelData worlddata = level.getLevelData(); // CraftBukkit - Other mob type spawn tick rate ++ ++ for (int j = 0; j < i; ++j) { ++ MobCategory enumcreaturetype = aenumcreaturetype[j]; ++ // CraftBukkit start - Use per-world spawn limits ++ boolean spawnThisTick = true; ++ int limit = enumcreaturetype.getMaxInstancesPerChunk(); ++ SpawnCategory spawnCategory = CraftSpawnCategory.toBukkit(enumcreaturetype); ++ if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { ++ spawnThisTick = level.ticksPerSpawnCategory.getLong(spawnCategory) != 0 && worlddata.getGameTime() % level.ticksPerSpawnCategory.getLong(spawnCategory) == 0; ++ limit = level.getWorld().getSpawnLimit(spawnCategory); + } ++ ++ if (!spawnThisTick || limit == 0) { ++ continue; ++ } ++ ++ if ((spawnFriendlies || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (forcedDespawn || !enumcreaturetype.isPersistent()) && spawnState.canSpawnForCategory(enumcreaturetype, chunk.getPos(), limit)) { ++ // CraftBukkit end ++ Objects.requireNonNull(spawnState); ++ NaturalSpawner.SpawnPredicate spawnercreature_c = spawnState::canSpawn; ++ ++ Objects.requireNonNull(spawnState); ++ spawnCategoryForChunk(enumcreaturetype, level, chunk, spawnercreature_c, spawnState::afterSpawn); ++ } + } + + level.getProfiler().pop(); +@@ -195,8 +211,33 @@ + return; + } + +- if (mobForSpawn.isMaxGroupSizeReached(i3)) { +- break; ++ if (isValidSpawnPostitionForType(level, category, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2) && filter.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { ++ Mob entityinsentient = getMobForSpawn(level, biomesettingsmobs_c.type); ++ ++ if (entityinsentient == null) { ++ return; ++ } ++ ++ entityinsentient.moveTo(d0, (double) i, d1, level.random.nextFloat() * 360.0F, 0.0F); ++ if (isValidPositionForMob(level, entityinsentient, d2)) { ++ groupdataentity = entityinsentient.finalizeSpawn(level, level.getCurrentDifficultyAt(entityinsentient.blockPosition()), EnumMobSpawn.NATURAL, groupdataentity, (CompoundTag) null); ++ // CraftBukkit start ++ // SPIGOT-7045: Give ocelot babies back their special spawn reason. Note: This is the only modification required as ocelots count as monsters which means they only spawn during normal chunk ticking and do not spawn during chunk generation as starter mobs. ++ level.addFreshEntityWithPassengers(entityinsentient, (entityinsentient instanceof net.minecraft.world.entity.animal.Ocelot && !((org.bukkit.entity.Ageable) entityinsentient.getBukkitEntity()).isAdult()) ? SpawnReason.OCELOT_BABY : SpawnReason.NATURAL); ++ if (!entityinsentient.isRemoved()) { ++ ++j; ++ ++k1; ++ callback.run(entityinsentient, chunk); ++ } ++ // CraftBukkit end ++ if (j >= entityinsentient.getMaxSpawnClusterSize()) { ++ return; ++ } ++ ++ if (entityinsentient.isMaxGroupSizeReached(k1)) { ++ break label53; ++ } ++ } + } + } + } +@@ -388,19 +409,15 @@ + continue; + } + +- entity.moveTo(d, (double)topNonCollidingPos.getY(), d1, random.nextFloat() * 360.0F, 0.0F); +- if (entity instanceof Mob mob +- && mob.checkSpawnRules(levelAccessor, MobSpawnType.CHUNK_GENERATION) +- && mob.checkSpawnObstruction(levelAccessor)) { +- spawnGroupData = mob.finalizeSpawn( +- levelAccessor, +- levelAccessor.getCurrentDifficultyAt(mob.blockPosition()), +- MobSpawnType.CHUNK_GENERATION, +- spawnGroupData, +- null +- ); +- levelAccessor.addFreshEntityWithPassengers(mob); +- flag = true; ++ entity.moveTo(d0, (double) blockposition.getY(), d1, random.nextFloat() * 360.0F, 0.0F); ++ if (entity instanceof Mob) { ++ Mob entityinsentient = (Mob) entity; ++ ++ if (entityinsentient.checkSpawnRules(levelAccessor, EnumMobSpawn.CHUNK_GENERATION) && entityinsentient.checkSpawnObstruction(levelAccessor)) { ++ groupdataentity = entityinsentient.finalizeSpawn(levelAccessor, levelAccessor.getCurrentDifficultyAt(entityinsentient.blockPosition()), EnumMobSpawn.CHUNK_GENERATION, groupdataentity, (CompoundTag) null); ++ levelAccessor.addFreshEntityWithPassengers(entityinsentient, SpawnReason.CHUNK_GEN); // CraftBukkit ++ flag = true; ++ } + } + } + +@@ -526,9 +536,12 @@ + return this.unmodifiableMobCategoryCounts; + } + +- boolean canSpawnForCategory(MobCategory category, ChunkPos pos) { +- int i = category.getMaxInstancesPerChunk() * this.spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER; +- return this.mobCategoryCounts.getInt(category) < i && this.localMobCapCalculator.canSpawn(category, pos); ++ // CraftBukkit start ++ boolean canSpawnForCategory(MobCategory enumcreaturetype, ChunkPos chunkcoordintpair, int limit) { ++ int i = limit * this.spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER; ++ // CraftBukkit end ++ ++ return this.mobCategoryCounts.getInt(enumcreaturetype) >= i ? false : this.localMobCapCalculator.canSpawn(enumcreaturetype, chunkcoordintpair); + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/ServerLevelAccessor.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/ServerLevelAccessor.java.patch new file mode 100644 index 0000000000..3ca302d2f6 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/ServerLevelAccessor.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/level/ServerLevelAccessor.java ++++ b/net/minecraft/world/level/ServerLevelAccessor.java +@@ -7,6 +8,17 @@ + ServerLevel getLevel(); + + default void addFreshEntityWithPassengers(Entity entity) { +- entity.getSelfAndPassengers().forEach(this::addFreshEntity); ++ // CraftBukkit start ++ this.addFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); + } ++ ++ default void addFreshEntityWithPassengers(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ entity.getSelfAndPassengers().forEach((e) -> this.addFreshEntity(e, reason)); ++ } ++ ++ @Override ++ default ServerLevel getMinecraftWorld() { ++ return getLevel(); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/AbstractCandleBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/AbstractCandleBlock.java.patch new file mode 100644 index 0000000000..d34ac23abf --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/AbstractCandleBlock.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/block/AbstractCandleBlock.java ++++ b/net/minecraft/world/level/block/AbstractCandleBlock.java +@@ -43,6 +45,11 @@ + @Override + public void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) { + if (!level.isClientSide && projectile.isOnFire() && this.canBeLit(state)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, hit.getBlockPos(), projectile).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + setLit(level, state, hit.getBlockPos(), true); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BambooSaplingBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BambooSaplingBlock.java.patch new file mode 100644 index 0000000000..e084647095 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BambooSaplingBlock.java.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/world/level/block/BambooSaplingBlock.java ++++ b/net/minecraft/world/level/block/BambooSaplingBlock.java +@@ -92,6 +95,6 @@ + } + + protected void growBamboo(Level level, BlockPos state) { +- level.setBlock(state.above(), Blocks.BAMBOO.defaultBlockState().setValue(BambooStalkBlock.LEAVES, BambooLeaves.SMALL), 3); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, state, state.above(), (IBlockData) Blocks.BAMBOO.defaultBlockState().setValue(BambooStalkBlock.LEAVES, BambooLeaves.SMALL), 3); // CraftBukkit - BlockSpreadEvent + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BambooStalkBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BambooStalkBlock.java.patch new file mode 100644 index 0000000000..15d1b8e885 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BambooStalkBlock.java.patch @@ -0,0 +1,75 @@ +--- a/net/minecraft/world/level/block/BambooStalkBlock.java ++++ b/net/minecraft/world/level/block/BambooStalkBlock.java +@@ -176,10 +183,11 @@ + int i = heightAboveUpToMax + heightBelowUpToMax + 1; + int i1 = 1 + random.nextInt(2); + +- for (int i2 = 0; i2 < i1; i2++) { +- BlockPos blockPos = pos.above(heightAboveUpToMax); +- BlockState blockState = level.getBlockState(blockPos); +- if (i >= 16 || blockState.getValue(STAGE) == 1 || !level.isEmptyBlock(blockPos.above())) { ++ for (int i1 = 0; i1 < l; ++i1) { ++ BlockPos blockposition1 = pos.above(i); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ if (k >= 16 || !iblockdata1.is(Blocks.BAMBOO) || (Integer) iblockdata1.getValue(BambooStalkBlock.STAGE) == 1 || !level.isEmptyBlock(blockposition1.above())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here + return; + } + +@@ -194,28 +203,39 @@ + return player.getMainHandItem().getItem() instanceof SwordItem ? 1.0F : super.getDestroyProgress(state, player, level, pos); + } + +- protected void growBamboo(BlockState state, Level level, BlockPos pos, RandomSource random, int age) { +- BlockState blockState = level.getBlockState(pos.below()); +- BlockPos blockPos = pos.below(2); +- BlockState blockState1 = level.getBlockState(blockPos); +- BambooLeaves bambooLeaves = BambooLeaves.NONE; ++ protected void growBamboo(IBlockData state, Level level, BlockPos pos, RandomSource random, int age) { ++ IBlockData iblockdata1 = level.getBlockState(pos.below()); ++ BlockPos blockposition1 = pos.below(2); ++ IBlockData iblockdata2 = level.getBlockState(blockposition1); ++ BambooLeaves blockpropertybamboosize = BambooLeaves.NONE; ++ boolean shouldUpdateOthers = false; // CraftBukkit ++ + if (age >= 1) { +- if (!blockState.is(Blocks.BAMBOO) || blockState.getValue(LEAVES) == BambooLeaves.NONE) { +- bambooLeaves = BambooLeaves.SMALL; +- } else if (blockState.is(Blocks.BAMBOO) && blockState.getValue(LEAVES) != BambooLeaves.NONE) { +- bambooLeaves = BambooLeaves.LARGE; +- if (blockState1.is(Blocks.BAMBOO)) { +- level.setBlock(pos.below(), blockState.setValue(LEAVES, BambooLeaves.SMALL), 3); +- level.setBlock(blockPos, blockState1.setValue(LEAVES, BambooLeaves.NONE), 3); ++ if (iblockdata1.is(Blocks.BAMBOO) && iblockdata1.getValue(BambooStalkBlock.LEAVES) != BambooLeaves.NONE) { ++ if (iblockdata1.is(Blocks.BAMBOO) && iblockdata1.getValue(BambooStalkBlock.LEAVES) != BambooLeaves.NONE) { ++ blockpropertybamboosize = BambooLeaves.LARGE; ++ if (iblockdata2.is(Blocks.BAMBOO)) { ++ // CraftBukkit start - moved down ++ // world.setBlock(blockposition.below(), (IBlockData) iblockdata1.setValue(BlockBamboo.LEAVES, BlockPropertyBambooSize.SMALL), 3); ++ // world.setBlock(blockposition1, (IBlockData) iblockdata2.setValue(BlockBamboo.LEAVES, BlockPropertyBambooSize.NONE), 3); ++ shouldUpdateOthers = true; ++ // CraftBukkit end ++ } + } + } + } + +- int i = state.getValue(AGE) != 1 && !blockState1.is(Blocks.BAMBOO) ? 0 : 1; +- int i1 = (age < 11 || !(random.nextFloat() < 0.25F)) && age != 15 ? 0 : 1; +- level.setBlock( +- pos.above(), this.defaultBlockState().setValue(AGE, Integer.valueOf(i)).setValue(LEAVES, bambooLeaves).setValue(STAGE, Integer.valueOf(i1)), 3 +- ); ++ int j = (Integer) state.getValue(BambooStalkBlock.AGE) != 1 && !iblockdata2.is(Blocks.BAMBOO) ? 0 : 1; ++ int k = (age < 11 || random.nextFloat() >= 0.25F) && age != 15 ? 0 : 1; ++ ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, pos.above(), (IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(BambooStalkBlock.AGE, j)).setValue(BambooStalkBlock.LEAVES, blockpropertybamboosize)).setValue(BambooStalkBlock.STAGE, k), 3)) { ++ if (shouldUpdateOthers) { ++ level.setBlock(pos.below(), (IBlockData) iblockdata1.setValue(BambooStalkBlock.LEAVES, BambooLeaves.SMALL), 3); ++ level.setBlock(blockposition1, (IBlockData) iblockdata2.setValue(BambooStalkBlock.LEAVES, BambooLeaves.NONE), 3); ++ } ++ } ++ // CraftBukkit end + } + + protected int getHeightAboveUpToMax(BlockGetter level, BlockPos pos) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BaseFireBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BaseFireBlock.java.patch new file mode 100644 index 0000000000..6683c134f4 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BaseFireBlock.java.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/world/level/block/BaseFireBlock.java ++++ b/net/minecraft/world/level/block/BaseFireBlock.java +@@ -128,7 +127,14 @@ + if (!entity.fireImmune()) { + entity.setRemainingFireTicks(entity.getRemainingFireTicks() + 1); + if (entity.getRemainingFireTicks() == 0) { +- entity.setSecondsOnFire(8); ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityCombustEvent event = new org.bukkit.event.entity.EntityCombustByBlockEvent(org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), entity.getBukkitEntity(), 8); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ entity.setSecondsOnFire(event.getDuration(), false); ++ } ++ // CraftBukkit end + } + } + +@@ -148,13 +155,13 @@ + } + + if (!state.canSurvive(level, pos)) { +- level.removeBlock(pos, false); ++ fireExtinguished(level, pos); // CraftBukkit - fuel block broke + } + } + } + + private static boolean inPortalDimension(Level level) { +- return level.dimension() == Level.OVERWORLD || level.dimension() == Level.NETHER; ++ return level.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.OVERWORLD || level.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.NETHER; // CraftBukkit - getTypeKey() + } + + @Override +@@ -199,4 +210,12 @@ + } + } + } ++ ++ // CraftBukkit start ++ protected void fireExtinguished(net.minecraft.world.level.LevelAccessor world, BlockPos position) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, position, Blocks.AIR.defaultBlockState()).isCancelled()) { ++ world.removeBlock(position, false); ++ } ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BasePressurePlateBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BasePressurePlateBlock.java.patch new file mode 100644 index 0000000000..782819529b --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BasePressurePlateBlock.java.patch @@ -0,0 +1,59 @@ +--- a/net/minecraft/world/level/block/BasePressurePlateBlock.java ++++ b/net/minecraft/world/level/block/BasePressurePlateBlock.java +@@ -20,6 +21,7 @@ + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public abstract class BasePressurePlateBlock extends Block { + protected static final VoxelShape PRESSED_AABB = Block.box(1.0, 0.0, 1.0, 15.0, 0.5, 15.0); +@@ -83,10 +89,25 @@ + private void checkPressed(@Nullable Entity entity, Level level, BlockPos pos, BlockState state, int currentSignal) { + int signalStrength = this.getSignalStrength(level, pos); + boolean flag = currentSignal > 0; +- boolean flag1 = signalStrength > 0; +- if (currentSignal != signalStrength) { +- BlockState blockState = this.setSignalForState(state, signalStrength); +- level.setBlock(pos, blockState, 2); ++ boolean flag1 = j > 0; ++ ++ // CraftBukkit start - Interact Pressure Plate ++ org.bukkit.World bworld = level.getWorld(); ++ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager(); ++ ++ if (flag != flag1) { ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), currentSignal, j); ++ manager.callEvent(eventRedstone); ++ ++ flag1 = eventRedstone.getNewCurrent() > 0; ++ j = eventRedstone.getNewCurrent(); ++ } ++ // CraftBukkit end ++ ++ if (currentSignal != j) { ++ IBlockData iblockdata1 = this.setSignalForState(state, j); ++ ++ level.setBlock(pos, iblockdata1, 2); + this.updateNeighbours(level, pos); + level.setBlocksDirty(pos, state, blockState); + } +@@ -136,9 +158,17 @@ + } + + protected static int getEntityCount(Level level, AABB box, Class entityClass) { +- return level.getEntitiesOfClass(entityClass, box, EntitySelector.NO_SPECTATORS.and(entity -> !entity.isIgnoringBlockTriggers())).size(); ++ // CraftBukkit start ++ return getEntities(level, box, entityClass).size(); + } + ++ protected static java.util.List getEntities(Level world, AABB axisalignedbb, Class oclass) { ++ // CraftBukkit end ++ return world.getEntitiesOfClass(oclass, axisalignedbb, EntitySelector.NO_SPECTATORS.and((entity) -> { ++ return !entity.isIgnoringBlockTriggers(); ++ })); // CraftBukkit ++ } ++ + protected abstract int getSignalStrength(Level level, BlockPos pos); + + protected abstract int getSignalForState(BlockState state); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BedBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BedBlock.java.patch new file mode 100644 index 0000000000..9c276d1845 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BedBlock.java.patch @@ -0,0 +1,82 @@ +--- a/net/minecraft/world/level/block/BedBlock.java ++++ b/net/minecraft/world/level/block/BedBlock.java +@@ -92,7 +94,8 @@ + } + } + +- if (!canSetSpawn(level)) { ++ // CraftBukkit - moved world and biome check into EntityHuman ++ if (false && !canSetSpawn(level)) { + level.removeBlock(pos, false); + BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite()); + if (level.getBlockState(blockPos).is(this)) { +@@ -109,9 +114,18 @@ + + return InteractionResult.SUCCESS; + } else { +- player.startSleepInBed(pos).ifLeft(bedSleepingProblem -> { +- if (bedSleepingProblem.getMessage() != null) { +- player.displayClientMessage(bedSleepingProblem.getMessage(), true); ++ // CraftBukkit start ++ IBlockData finaliblockdata = state; ++ BlockPos finalblockposition = pos; ++ // CraftBukkit end ++ player.startSleepInBed(pos).ifLeft((entityhuman_enumbedresult) -> { ++ // CraftBukkit start - handling bed explosion from below here ++ if (!level.dimensionType().bedWorks()) { ++ this.explodeBed(finaliblockdata, level, finalblockposition); ++ } else ++ // CraftBukkit end ++ if (entityhuman_enumbedresult.getMessage() != null) { ++ player.displayClientMessage(entityhuman_enumbedresult.getMessage(), true); + } + }); + return InteractionResult.SUCCESS; +@@ -119,8 +134,29 @@ + } + } + ++ // CraftBukkit start ++ private InteractionResult explodeBed(IBlockData iblockdata, Level world, BlockPos blockposition) { ++ { ++ { ++ world.removeBlock(blockposition, false); ++ BlockPos blockposition1 = blockposition.relative(((Direction) iblockdata.getValue(BedBlock.FACING)).getOpposite()); ++ ++ if (world.getBlockState(blockposition1).getBlock() == this) { ++ world.removeBlock(blockposition1, false); ++ } ++ ++ Vec3 vec3d = blockposition.getCenter(); ++ ++ world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.a.BLOCK); ++ return InteractionResult.SUCCESS; ++ } ++ } ++ } ++ // CraftBukkit end ++ + public static boolean canSetSpawn(Level level) { +- return level.dimensionType().bedWorks(); ++ // CraftBukkit - moved world and biome check into EntityHuman ++ return true || level.dimensionType().bedWorks(); + } + + private boolean kickVillagerOutOfBed(Level level, BlockPos pos) { +@@ -305,8 +352,14 @@ + public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) { + super.setPlacedBy(level, pos, state, placer, stack); + if (!level.isClientSide) { +- BlockPos blockPos = pos.relative(state.getValue(FACING)); +- level.setBlock(blockPos, state.setValue(PART, BedPart.HEAD), 3); ++ BlockPos blockposition1 = pos.relative((Direction) state.getValue(BedBlock.FACING)); ++ ++ level.setBlock(blockposition1, (IBlockData) state.setValue(BedBlock.PART, BedPart.HEAD), 3); ++ // CraftBukkit start - SPIGOT-7315: Don't updated if we capture block states ++ if (level.captureBlockStates) { ++ return; ++ } ++ // CraftBukkit end + level.blockUpdated(pos, Blocks.AIR); + state.updateNeighbourShapes(level, pos, 3); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BeehiveBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BeehiveBlock.java.patch new file mode 100644 index 0000000000..1b83368ec4 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BeehiveBlock.java.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/level/block/BeehiveBlock.java ++++ b/net/minecraft/world/level/block/BeehiveBlock.java +@@ -104,10 +111,15 @@ + return; + } + +- for (Bee bee : entitiesOfClass) { +- if (bee.getTarget() == null) { +- Player player = Util.getRandom(entitiesOfClass1, level.random); +- bee.setTarget(player); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Bee entitybee = (Bee) iterator.next(); ++ ++ if (entitybee.getTarget() == null) { ++ Player entityhuman = (Player) Util.getRandom(list1, level.random); ++ ++ entitybee.setTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BellBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BellBlock.java.patch new file mode 100644 index 0000000000..86f3d426df --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BellBlock.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/block/BellBlock.java ++++ b/net/minecraft/world/level/block/BellBlock.java +@@ -140,6 +146,11 @@ + if (direction == null) { + direction = level.getBlockState(pos).getValue(FACING); + } ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBellRingEvent(level, pos, direction, entity)) { ++ return false; ++ } ++ // CraftBukkit end + + ((BellBlockEntity)blockEntity).onHit(direction); + level.playSound(null, pos, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2.0F, 1.0F); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BigDripleafBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BigDripleafBlock.java.patch new file mode 100644 index 0000000000..ede16ddc3f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BigDripleafBlock.java.patch @@ -0,0 +1,113 @@ +--- a/net/minecraft/world/level/block/BigDripleafBlock.java ++++ b/net/minecraft/world/level/block/BigDripleafBlock.java +@@ -39,6 +41,10 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end + + public class BigDripleafBlock extends HorizontalDirectionalBlock implements BonemealableBlock, SimpleWaterloggedBlock { + public static final MapCodec CODEC = simpleCodec(BigDripleafBlock::new); +@@ -133,8 +119,8 @@ + } + + @Override +- public void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) { +- this.setTiltAndScheduleTick(state, level, hit.getBlockPos(), Tilt.FULL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN); ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { ++ this.setTiltAndScheduleTick(state, level, hit.getBlockPos(), Tilt.FULL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN, projectile); // CraftBukkit + } + + @Override +@@ -189,8 +178,21 @@ + @Override + public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { + if (!level.isClientSide) { +- if (state.getValue(TILT) == Tilt.NONE && canEntityTilt(pos, entity) && !level.hasNeighborSignal(pos)) { +- this.setTiltAndScheduleTick(state, level, pos, Tilt.UNSTABLE, null); ++ if (state.getValue(BigDripleafBlock.TILT) == Tilt.NONE && canEntityTilt(pos, entity) && !level.hasNeighborSignal(pos)) { ++ // CraftBukkit start - tilt dripleaf ++ org.bukkit.event.Cancellable cancellable; ++ if (entity instanceof Player) { ++ cancellable = CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ if (cancellable.isCancelled()) { ++ return; ++ } ++ this.setTiltAndScheduleTick(state, level, pos, Tilt.UNSTABLE, (SoundEvent) null, entity); ++ // CraftBukkit end + } + } + } +@@ -202,9 +206,9 @@ + } else { + Tilt tilt = state.getValue(TILT); + if (tilt == Tilt.UNSTABLE) { +- this.setTiltAndScheduleTick(state, level, pos, Tilt.PARTIAL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN); ++ this.setTiltAndScheduleTick(state, level, pos, Tilt.PARTIAL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN, null); // CraftBukkit + } else if (tilt == Tilt.PARTIAL) { +- this.setTiltAndScheduleTick(state, level, pos, Tilt.FULL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN); ++ this.setTiltAndScheduleTick(state, level, pos, Tilt.FULL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN, null); // CraftBukkit + } else if (tilt == Tilt.FULL) { + resetTilt(state, level, pos); + } +@@ -227,10 +234,12 @@ + return entity.onGround() && entity.position().y > (double)((float)pos.getY() + 0.6875F); + } + +- private void setTiltAndScheduleTick(BlockState state, Level level, BlockPos pos, Tilt tilt, @Nullable SoundEvent sound) { +- setTilt(state, level, pos, tilt); +- if (sound != null) { +- playTiltSound(level, pos, sound); ++ // CraftBukkit start ++ private void setTiltAndScheduleTick(IBlockData iblockdata, Level world, BlockPos blockposition, Tilt tilt, @Nullable SoundEvent soundeffect, @Nullable Entity entity) { ++ if (!setTilt(iblockdata, world, blockposition, tilt, entity)) return; ++ // CraftBukkit end ++ if (soundeffect != null) { ++ playTiltSound(world, blockposition, soundeffect); + } + + int _int = DELAY_UNTIL_NEXT_TILT_STATE.getInt(tilt); +@@ -239,19 +250,29 @@ + } + } + +- private static void resetTilt(BlockState state, Level level, BlockPos pos) { +- setTilt(state, level, pos, Tilt.NONE); +- if (state.getValue(TILT) != Tilt.NONE) { ++ private static void resetTilt(IBlockData state, Level level, BlockPos pos) { ++ setTilt(state, level, pos, Tilt.NONE, null); // CraftBukkit ++ if (state.getValue(BigDripleafBlock.TILT) != Tilt.NONE) { + playTiltSound(level, pos, SoundEvents.BIG_DRIPLEAF_TILT_UP); + } + } + +- private static void setTilt(BlockState state, Level level, BlockPos pos, Tilt tilt) { +- Tilt tilt1 = state.getValue(TILT); +- level.setBlock(pos, state.setValue(TILT, tilt), 2); ++ // CraftBukkit start ++ private static boolean setTilt(IBlockData iblockdata, Level world, BlockPos blockposition, Tilt tilt, @Nullable Entity entity) { ++ if (entity != null) { ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, iblockdata.setValue(BigDripleafBlock.TILT, tilt))) { ++ return false; ++ } ++ } ++ // CraftBukkit end ++ Tilt tilt1 = (Tilt) iblockdata.getValue(BigDripleafBlock.TILT); ++ ++ world.setBlock(blockposition, (IBlockData) iblockdata.setValue(BigDripleafBlock.TILT, tilt), 2); + if (tilt.causesVibration() && tilt != tilt1) { + level.gameEvent(null, GameEvent.BLOCK_CHANGE, pos); + } ++ ++ return true; // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/Block.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/Block.java.patch new file mode 100644 index 0000000000..e13e448ee0 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/Block.java.patch @@ -0,0 +1,57 @@ +--- a/net/minecraft/world/level/block/Block.java ++++ b/net/minecraft/world/level/block/Block.java +@@ -328,9 +346,16 @@ + + private static void popResource(Level level, Supplier itemEntitySupplier, ItemStack stack) { + if (!level.isClientSide && !stack.isEmpty() && level.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { +- ItemEntity itemEntity = itemEntitySupplier.get(); +- itemEntity.setDefaultPickUpDelay(); +- level.addFreshEntity(itemEntity); ++ ItemEntity entityitem = (ItemEntity) itemEntitySupplier.get(); ++ ++ entityitem.setDefaultPickUpDelay(); ++ // CraftBukkit start ++ if (level.captureDrops != null) { ++ level.captureDrops.add(entityitem); ++ } else { ++ level.addFreshEntity(entityitem); ++ } ++ // CraftBukkit end + } + } + +@@ -357,7 +381,7 @@ + + public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) { + player.awardStat(Stats.BLOCK_MINED.get(this)); +- player.causeFoodExhaustion(0.005F); ++ player.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED); // CraftBukkit - EntityExhaustionEvent + dropResources(state, level, pos, blockEntity, player, tool); + } + +@@ -495,15 +518,22 @@ + return this.builtInRegistryHolder; + } + +- protected void tryDropExperience(ServerLevel level, BlockPos pos, ItemStack heldItem, IntProvider amount) { +- if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, heldItem) == 0) { +- int i = amount.sample(level.random); ++ // CraftBukkit start ++ protected int tryDropExperience(ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, IntProvider intprovider) { ++ if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, itemstack) == 0) { ++ int i = intprovider.sample(worldserver.random); ++ + if (i > 0) { + this.popExperience(level, pos, i); + } + } + } + ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { ++ return 0; ++ } ++ // CraftBukkit end ++ + public static final class BlockStatePairKey { + private final BlockState first; + private final BlockState second; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BuddingAmethystBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BuddingAmethystBlock.java.patch new file mode 100644 index 0000000000..493f0f9ea9 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BuddingAmethystBlock.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/level/block/BuddingAmethystBlock.java ++++ b/net/minecraft/world/level/block/BuddingAmethystBlock.java +@@ -41,10 +43,9 @@ + } + + if (block != null) { +- BlockState blockState1 = block.defaultBlockState() +- .setValue(AmethystClusterBlock.FACING, direction) +- .setValue(AmethystClusterBlock.WATERLOGGED, Boolean.valueOf(blockState.getFluidState().getType() == Fluids.WATER)); +- level.setBlockAndUpdate(blockPos, blockState1); ++ IBlockData iblockdata2 = (IBlockData) ((IBlockData) block.defaultBlockState().setValue(AmethystClusterBlock.FACING, enumdirection)).setValue(AmethystClusterBlock.WATERLOGGED, iblockdata1.getFluidState().getType() == Fluids.WATER); ++ ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition1, iblockdata2); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BushBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BushBlock.java.patch new file mode 100644 index 0000000000..58e85bc2cf --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/BushBlock.java.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/level/block/BushBlock.java ++++ b/net/minecraft/world/level/block/BushBlock.java +@@ -24,10 +25,15 @@ + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- return !state.canSurvive(level, currentPos) +- ? Blocks.AIR.defaultBlockState() +- : super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ // CraftBukkit start ++ if (!state.canSurvive(level, currentPos)) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(level, currentPos).isCancelled()) { ++ return Blocks.AIR.defaultBlockState(); ++ } ++ } ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ButtonBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ButtonBlock.java.patch new file mode 100644 index 0000000000..1c6b231b61 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ButtonBlock.java.patch @@ -0,0 +1,79 @@ +--- a/net/minecraft/world/level/block/ButtonBlock.java ++++ b/net/minecraft/world/level/block/ButtonBlock.java +@@ -33,6 +32,10 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.event.block.BlockRedstoneEvent; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end + + public class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +@@ -114,6 +128,19 @@ + if (state.getValue(POWERED)) { + return InteractionResult.CONSUME; + } else { ++ // CraftBukkit start ++ boolean powered = ((Boolean) state.getValue(POWERED)); ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ int old = (powered) ? 15 : 0; ++ int current = (!powered) ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if ((eventRedstone.getNewCurrent() > 0) != (!powered)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + this.press(state, level, pos); + this.playSound(player, level, pos, true); + level.gameEvent(player, GameEvent.BLOCK_ACTIVATE, pos); +@@ -184,14 +211,38 @@ + } + } + +- protected void checkPressed(BlockState state, Level level, BlockPos pos) { +- AbstractArrow abstractArrow = this.type.canButtonBeActivatedByArrows() +- ? level.getEntitiesOfClass(AbstractArrow.class, state.getShape(level, pos).bounds().move(pos)).stream().findFirst().orElse(null) +- : null; +- boolean flag = abstractArrow != null; +- boolean flag1 = state.getValue(POWERED); ++ protected void checkPressed(IBlockData state, Level level, BlockPos pos) { ++ AbstractArrow entityarrow = this.type.canButtonBeActivatedByArrows() ? (AbstractArrow) level.getEntitiesOfClass(AbstractArrow.class, state.getShape(level, pos).bounds().move(pos)).stream().findFirst().orElse(null) : null; // CraftBukkit - decompile error ++ boolean flag = entityarrow != null; ++ boolean flag1 = (Boolean) state.getValue(ButtonBlock.POWERED); ++ ++ // CraftBukkit start - Call interact event when arrows turn on wooden buttons ++ if (flag1 != flag && flag) { ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ EntityInteractEvent event = new EntityInteractEvent(entityarrow.getBukkitEntity(), block); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ + if (flag != flag1) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(flag)), 3); ++ // CraftBukkit start ++ boolean powered = flag1; ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ int old = (powered) ? 15 : 0; ++ int current = (!powered) ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if ((flag && eventRedstone.getNewCurrent() <= 0) || (!flag && eventRedstone.getNewCurrent() > 0)) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(ButtonBlock.POWERED, flag), 3); + this.updateNeighbours(state, level, pos); + this.playSound(null, level, pos, flag); + level.gameEvent(abstractArrow, flag ? GameEvent.BLOCK_ACTIVATE : GameEvent.BLOCK_DEACTIVATE, pos); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CactusBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CactusBlock.java.patch new file mode 100644 index 0000000000..b1cf4e1b6a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CactusBlock.java.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/world/level/block/CactusBlock.java ++++ b/net/minecraft/world/level/block/CactusBlock.java +@@ -20,6 +21,7 @@ + import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class CactusBlock extends Block { + public static final MapCodec CODEC = simpleCodec(CactusBlock::new); +@@ -57,12 +62,14 @@ + } + + if (i < 3) { +- int i1 = state.getValue(AGE); +- if (i1 == 15) { +- level.setBlockAndUpdate(blockPos, this.defaultBlockState()); +- BlockState blockState = state.setValue(AGE, Integer.valueOf(0)); +- level.setBlock(pos, blockState, 4); +- level.neighborChanged(blockState, blockPos, this, pos, false); ++ int j = (Integer) state.getValue(CactusBlock.AGE); ++ ++ if (j == 15) { ++ CraftEventFactory.handleBlockGrowEvent(level, blockposition1, this.defaultBlockState()); // CraftBukkit ++ IBlockData iblockdata1 = (IBlockData) state.setValue(CactusBlock.AGE, 0); ++ ++ level.setBlock(pos, iblockdata1, 4); ++ level.neighborChanged(iblockdata1, blockposition1, this, pos, false); + } else { + level.setBlock(pos, state.setValue(AGE, Integer.valueOf(i1 + 1)), 4); + } +@@ -103,8 +119,10 @@ + } + + @Override +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ CraftEventFactory.blockDamage = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); // CraftBukkit + entity.hurt(level.damageSources().cactus(), 1.0F); ++ CraftEventFactory.blockDamage = null; // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CakeBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CakeBlock.java.patch new file mode 100644 index 0000000000..1e895b0276 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CakeBlock.java.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/world/level/block/CakeBlock.java ++++ b/net/minecraft/world/level/block/CakeBlock.java +@@ -96,9 +92,21 @@ + return InteractionResult.PASS; + } else { + player.awardStat(Stats.EAT_CAKE_SLICE); +- player.getFoodData().eat(2, 0.1F); +- int i = state.getValue(BITES); +- level.gameEvent(player, GameEvent.EAT, pos); ++ // CraftBukkit start ++ // entityhuman.getFoodData().eat(2, 0.1F); ++ int oldFoodLevel = player.getFoodData().foodLevel; ++ ++ org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(player, 2 + oldFoodLevel); ++ ++ if (!event.isCancelled()) { ++ player.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, 0.1F); ++ } ++ ++ ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().sendHealthUpdate(); ++ // CraftBukkit end ++ int i = (Integer) state.getValue(CakeBlock.BITES); ++ ++ level.gameEvent((Entity) player, GameEvent.EAT, pos); + if (i < 6) { + level.setBlock(pos, state.setValue(BITES, Integer.valueOf(i + 1)), 3); + } else { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CampfireBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CampfireBlock.java.patch new file mode 100644 index 0000000000..af0c8b6a1c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CampfireBlock.java.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/world/level/block/CampfireBlock.java ++++ b/net/minecraft/world/level/block/CampfireBlock.java +@@ -49,6 +49,9 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++// CraftBukkit end + + public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedBlock { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +@@ -110,9 +107,11 @@ + } + + @Override +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { +- if (state.getValue(LIT) && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity)entity)) { +- entity.hurt(level.damageSources().inFire(), (float)this.fireDamage); ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ if ((Boolean) state.getValue(CampfireBlock.LIT) && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity) entity)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = CraftBlock.at(level, pos); // CraftBukkit ++ entity.hurt(level.damageSources().inFire(), (float) this.fireDamage); ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = null; // CraftBukkit + } + + super.entityInside(state, level, pos, entity); +@@ -236,10 +217,16 @@ + } + + @Override +- public void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) { +- BlockPos blockPos = hit.getBlockPos(); +- if (!level.isClientSide && projectile.isOnFire() && projectile.mayInteract(level, blockPos) && !state.getValue(LIT) && !state.getValue(WATERLOGGED)) { +- level.setBlock(blockPos, state.setValue(BlockStateProperties.LIT, Boolean.valueOf(true)), 11); ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { ++ BlockPos blockposition = hit.getBlockPos(); ++ ++ if (!level.isClientSide && projectile.isOnFire() && projectile.mayInteract(level, blockposition) && !(Boolean) state.getValue(CampfireBlock.LIT) && !(Boolean) state.getValue(CampfireBlock.WATERLOGGED)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, blockposition, projectile).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(blockposition, (IBlockData) state.setValue(BlockStateProperties.LIT, true), 11); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CarvedPumpkinBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CarvedPumpkinBlock.java.patch new file mode 100644 index 0000000000..d1513a9c00 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CarvedPumpkinBlock.java.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/level/block/CarvedPumpkinBlock.java ++++ b/net/minecraft/world/level/block/CarvedPumpkinBlock.java +@@ -22,6 +23,9 @@ + import net.minecraft.world.level.block.state.pattern.BlockPatternBuilder; + import net.minecraft.world.level.block.state.predicate.BlockStatePredicate; + import net.minecraft.world.level.block.state.properties.DirectionProperty; ++// CraftBukkit start ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; ++// CraftBukkit end + + public class CarvedPumpkinBlock extends HorizontalDirectionalBlock { + public static final MapCodec CODEC = simpleCodec(CarvedPumpkinBlock::new); +@@ -78,9 +89,15 @@ + } + + private static void spawnGolemInWorld(Level level, BlockPattern.BlockPatternMatch patternMatch, Entity golem, BlockPos pos) { +- clearPatternBlocks(level, patternMatch); +- golem.moveTo((double)pos.getX() + 0.5, (double)pos.getY() + 0.05, (double)pos.getZ() + 0.5, 0.0F, 0.0F); +- level.addFreshEntity(golem); ++ // clearPatternBlocks(world, shapedetector_shapedetectorcollection); // CraftBukkit - moved down ++ golem.moveTo((double) pos.getX() + 0.5D, (double) pos.getY() + 0.05D, (double) pos.getZ() + 0.5D, 0.0F, 0.0F); ++ // CraftBukkit start ++ if (!level.addFreshEntity(golem, SpawnReason.BUILD_IRONGOLEM)) { ++ return; ++ } ++ clearPatternBlocks(level, patternMatch); // CraftBukkit - from above ++ // CraftBukkit end ++ Iterator iterator = level.getEntitiesOfClass(ServerPlayer.class, golem.getBoundingBox().inflate(5.0D)).iterator(); + + for (ServerPlayer serverPlayer : level.getEntitiesOfClass(ServerPlayer.class, golem.getBoundingBox().inflate(5.0))) { + CriteriaTriggers.SUMMONED_ENTITY.trigger(serverPlayer, golem); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CauldronBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CauldronBlock.java.patch new file mode 100644 index 0000000000..1cfb65fad4 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CauldronBlock.java.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/level/block/CauldronBlock.java ++++ b/net/minecraft/world/level/block/CauldronBlock.java +@@ -10,6 +11,9 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; ++// CraftBukkit start ++import org.bukkit.event.block.CauldronLevelChangeEvent; ++// CraftBukkit end + + public class CauldronBlock extends AbstractCauldronBlock { + public static final MapCodec CODEC = simpleCodec(CauldronBlock::new); +@@ -57,14 +63,12 @@ + @Override + protected void receiveStalactiteDrip(BlockState state, Level level, BlockPos pos, Fluid fluid) { + if (fluid == Fluids.WATER) { +- BlockState blockState = Blocks.WATER_CAULDRON.defaultBlockState(); +- level.setBlockAndUpdate(pos, blockState); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(blockState)); ++ iblockdata1 = Blocks.WATER_CAULDRON.defaultBlockState(); ++ LayeredCauldronBlock.changeLevel(state, level, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL); // CraftBukkit + level.levelEvent(1047, pos, 0); + } else if (fluid == Fluids.LAVA) { +- BlockState blockState = Blocks.LAVA_CAULDRON.defaultBlockState(); +- level.setBlockAndUpdate(pos, blockState); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(blockState)); ++ iblockdata1 = Blocks.LAVA_CAULDRON.defaultBlockState(); ++ LayeredCauldronBlock.changeLevel(state, level, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL); // CraftBukkit + level.levelEvent(1046, pos, 0); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CaveVines.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CaveVines.java.patch new file mode 100644 index 0000000000..fb71d103ab --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CaveVines.java.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/world/level/block/CaveVines.java ++++ b/net/minecraft/world/level/block/CaveVines.java +@@ -17,13 +18,37 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.VoxelShape; + ++// CraftBukkit start ++import java.util.Collections; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerHarvestBlockEvent; ++// CraftBukkit end ++ + public interface CaveVines { + VoxelShape SHAPE = Block.box(1.0, 0.0, 1.0, 15.0, 16.0, 15.0); + BooleanProperty BERRIES = BlockStateProperties.BERRIES; + +- static InteractionResult use(@Nullable Entity entity, BlockState state, Level level, BlockPos pos) { +- if (state.getValue(BERRIES)) { +- Block.popResource(level, pos, new ItemStack(Items.GLOW_BERRIES, 1)); ++ static InteractionResult use(@Nullable Entity entity, IBlockData state, Level level, BlockPos pos) { ++ if ((Boolean) state.getValue(CaveVines.BERRIES)) { ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, (IBlockData) state.setValue(CaveVines.BERRIES, false))) { ++ return InteractionResult.SUCCESS; ++ } ++ ++ if (entity instanceof Player) { ++ PlayerHarvestBlockEvent event = CraftEventFactory.callPlayerHarvestBlockEvent(level, pos, (Player) entity, net.minecraft.world.EnumHand.MAIN_HAND, Collections.singletonList(new ItemStack(Items.GLOW_BERRIES, 1))); ++ if (event.isCancelled()) { ++ return InteractionResult.SUCCESS; // We need to return a success either way, because making it PASS or FAIL will result in a bug where cancelling while harvesting w/ block in hand places block ++ } ++ for (org.bukkit.inventory.ItemStack itemStack : event.getItemsHarvested()) { ++ Block.popResource(level, pos, CraftItemStack.asNMSCopy(itemStack)); ++ } ++ } else { ++ Block.popResource(level, pos, new ItemStack(Items.GLOW_BERRIES, 1)); ++ } ++ // CraftBukkit end ++ + float f = Mth.randomBetween(level.random, 0.8F, 1.2F); + level.playSound(null, pos, SoundEvents.CAVE_VINES_PICK_BERRIES, SoundSource.BLOCKS, 1.0F, f); + BlockState blockState = state.setValue(BERRIES, Boolean.valueOf(false)); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CeilingHangingSignBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CeilingHangingSignBlock.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CeilingHangingSignBlock.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ChangeOverTimeBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ChangeOverTimeBlock.java.patch new file mode 100644 index 0000000000..3028aee354 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ChangeOverTimeBlock.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/level/block/ChangeOverTimeBlock.java ++++ b/net/minecraft/world/level/block/ChangeOverTimeBlock.java +@@ -15,8 +17,11 @@ + + default void changeOverTime(BlockState blockState, ServerLevel serverLevel, BlockPos blockPos, RandomSource randomSource) { + float f = 0.05688889F; +- if (randomSource.nextFloat() < 0.05688889F) { +- this.getNextState(blockState, serverLevel, blockPos, randomSource).ifPresent(blockState1 -> serverLevel.setBlockAndUpdate(blockPos, blockState1)); ++ ++ if (randomsource.nextFloat() < 0.05688889F) { ++ this.getNextState(iblockdata, worldserver, blockposition, randomsource).ifPresent((iblockdata1) -> { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(worldserver, blockposition, iblockdata1); // CraftBukkit ++ }); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ChestBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ChestBlock.java.patch new file mode 100644 index 0000000000..2470949692 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ChestBlock.java.patch @@ -0,0 +1,78 @@ +--- a/net/minecraft/world/level/block/ChestBlock.java ++++ b/net/minecraft/world/level/block/ChestBlock.java +@@ -85,9 +89,17 @@ + return Optional.empty(); + } + }; +- private static final DoubleBlockCombiner.Combiner> MENU_PROVIDER_COMBINER = new DoubleBlockCombiner.Combiner>( +- +- ) { ++ private static final DoubleBlockCombiner.Combiner> MENU_PROVIDER_COMBINER = new DoubleBlockCombiner.Combiner>() { ++ public Optional acceptDouble(final ChestBlockEntity tileentitychest, final ChestBlockEntity tileentitychest1) { ++ final CompoundContainer inventorylargechest = new CompoundContainer(tileentitychest, tileentitychest1); ++ ++ return Optional.of(new DoubleInventory(tileentitychest, tileentitychest1, inventorylargechest)); // CraftBukkit ++ } ++ ++ public Optional acceptSingle(ChestBlockEntity tileentitychest) { ++ return Optional.of(tileentitychest); ++ } ++ + @Override + public Optional acceptDouble(final ChestBlockEntity first, final ChestBlockEntity second) { + final Container container = new CompoundContainer(first, second); +@@ -104,15 +106,17 @@ + } + } + +- @Override +- public Component getDisplayName() { +- if (first.hasCustomName()) { +- return first.getDisplayName(); +- } else { +- return (Component)(second.hasCustomName() ? second.getDisplayName() : Component.translatable("container.chestDouble")); +- } +- } +- }); ++ // CraftBukkit start ++ public static class DoubleInventory implements ITileInventory { ++ ++ private final ChestBlockEntity tileentitychest; ++ private final ChestBlockEntity tileentitychest1; ++ public final CompoundContainer inventorylargechest; ++ ++ public DoubleInventory(ChestBlockEntity tileentitychest, ChestBlockEntity tileentitychest1, CompoundContainer inventorylargechest) { ++ this.tileentitychest = tileentitychest; ++ this.tileentitychest1 = tileentitychest1; ++ this.inventorylargechest = inventorylargechest; + } + + @Override +@@ -125,6 +136,7 @@ + return Optional.empty(); + } + }; ++ // CraftBukkit end + + @Override + public MapCodec codec() { +@@ -298,10 +308,17 @@ + + @Nullable + @Override +- public MenuProvider getMenuProvider(BlockState state, Level level, BlockPos pos) { +- return this.combine(state, level, pos, false).apply(MENU_PROVIDER_COMBINER).orElse(null); ++ public ITileInventory getMenuProvider(IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ return getMenuProvider(state, level, pos, false); + } + ++ @Nullable ++ public ITileInventory getMenuProvider(IBlockData iblockdata, Level world, BlockPos blockposition, boolean ignoreObstructions) { ++ return (ITileInventory) ((Optional) this.combine(iblockdata, world, blockposition, ignoreObstructions).apply(ChestBlock.MENU_PROVIDER_COMBINER)).orElse((Object) null); ++ // CraftBukkit end ++ } ++ + public static DoubleBlockCombiner.Combiner opennessCombiner(final LidBlockEntity lid) { + return new DoubleBlockCombiner.Combiner() { + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ChorusFlowerBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ChorusFlowerBlock.java.patch new file mode 100644 index 0000000000..451b46f71b --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ChorusFlowerBlock.java.patch @@ -0,0 +1,95 @@ +--- a/net/minecraft/world/level/block/ChorusFlowerBlock.java ++++ b/net/minecraft/world/level/block/ChorusFlowerBlock.java +@@ -22,6 +22,8 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.VoxelShape; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public class ChorusFlowerBlock extends Block { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( + instance -> instance.group( +@@ -95,9 +103,13 @@ + flag = true; + } + +- if (flag && allNeighborsEmpty(level, blockPos, null) && level.isEmptyBlock(pos.above(2))) { +- level.setBlock(pos, ChorusPlantBlock.getStateWithConnections(level, pos, this.plant.defaultBlockState()), 2); +- this.placeGrownFlower(level, blockPos, i); ++ if (flag && allNeighborsEmpty(level, blockposition1, (Direction) null) && level.isEmptyBlock(pos.above(2))) { ++ // CraftBukkit start - add event ++ if (CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition1, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(i)), 2)) { ++ level.setBlock(pos, ChorusPlantBlock.getStateWithConnections(level, pos, this.plant.defaultBlockState()), 2); ++ this.placeGrownFlower(level, blockposition1, i); ++ } ++ // CraftBukkit end + } else if (i < 4) { + int i1 = random.nextInt(4); + if (flag1) { +@@ -106,24 +118,35 @@ + + boolean flag2 = false; + +- for (int i3 = 0; i3 < i1; i3++) { +- Direction randomDirection = Direction.Plane.HORIZONTAL.getRandomDirection(random); +- BlockPos blockPos1 = pos.relative(randomDirection); +- if (level.isEmptyBlock(blockPos1) +- && level.isEmptyBlock(blockPos1.below()) +- && allNeighborsEmpty(level, blockPos1, randomDirection.getOpposite())) { +- this.placeGrownFlower(level, blockPos1, i + 1); +- flag2 = true; ++ for (int l = 0; l < j; ++l) { ++ Direction enumdirection = Direction.Plane.HORIZONTAL.getRandomDirection(random); ++ BlockPos blockposition2 = pos.relative(enumdirection); ++ ++ if (level.isEmptyBlock(blockposition2) && level.isEmptyBlock(blockposition2.below()) && allNeighborsEmpty(level, blockposition2, enumdirection.getOpposite())) { ++ // CraftBukkit start - add event ++ if (CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition2, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(i + 1)), 2)) { ++ this.placeGrownFlower(level, blockposition2, i + 1); ++ flag2 = true; ++ } ++ // CraftBukkit end + } + } + + if (flag2) { + level.setBlock(pos, ChorusPlantBlock.getStateWithConnections(level, pos, this.plant.defaultBlockState()), 2); + } else { +- this.placeDeadFlower(level, pos); ++ // CraftBukkit start - add event ++ if (CraftEventFactory.handleBlockGrowEvent(level, pos, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(5)), 2)) { ++ this.placeDeadFlower(level, pos); ++ } ++ // CraftBukkit end + } + } else { +- this.placeDeadFlower(level, pos); ++ // CraftBukkit start - add event ++ if (CraftEventFactory.handleBlockGrowEvent(level, pos, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(5)), 2)) { ++ this.placeDeadFlower(level, pos); ++ } ++ // CraftBukkit end + } + } + } +@@ -249,10 +279,16 @@ + } + + @Override +- public void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) { +- BlockPos blockPos = hit.getBlockPos(); +- if (!level.isClientSide && projectile.mayInteract(level, blockPos) && projectile.mayBreak(level)) { +- level.destroyBlock(blockPos, true, projectile); ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { ++ BlockPos blockposition = hit.getBlockPos(); ++ ++ if (!level.isClientSide && projectile.mayInteract(level, blockposition) && projectile.mayBreak(level)) { ++ // CraftBukkit ++ if (!CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, Blocks.AIR.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end ++ level.destroyBlock(blockposition, true, projectile); + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CocoaBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CocoaBlock.java.patch new file mode 100644 index 0000000000..c7c8c72b71 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CocoaBlock.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/level/block/CocoaBlock.java ++++ b/net/minecraft/world/level/block/CocoaBlock.java +@@ -20,6 +20,7 @@ + import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class CocoaBlock extends HorizontalDirectionalBlock implements BonemealableBlock { + public static final MapCodec CODEC = simpleCodec(CocoaBlock::new); +@@ -131,8 +131,8 @@ + } + + @Override +- public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) { +- level.setBlock(pos, state.setValue(AGE, Integer.valueOf(state.getValue(AGE) + 1)), 2); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ CraftEventFactory.handleBlockGrowEvent(level, pos, (IBlockData) state.setValue(CocoaBlock.AGE, (Integer) state.getValue(CocoaBlock.AGE) + 1), 2); // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CommandBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CommandBlock.java.patch new file mode 100644 index 0000000000..4df7027985 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CommandBlock.java.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/world/level/block/CommandBlock.java ++++ b/net/minecraft/world/level/block/CommandBlock.java +@@ -31,6 +30,8 @@ + import net.minecraft.world.phys.BlockHitResult; + import org.slf4j.Logger; + ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit ++ + public class CommandBlock extends BaseEntityBlock implements GameMasterBlock { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( + instance -> instance.group(Codec.BOOL.fieldOf("automatic").forGetter(commandBlock -> commandBlock.automatic), propertiesCodec()) +@@ -62,14 +66,27 @@ + @Override + public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { + if (!level.isClientSide) { +- if (level.getBlockEntity(pos) instanceof CommandBlockEntity commandBlockEntity) { +- boolean hasNeighborSignal = level.hasNeighborSignal(pos); +- boolean isPowered = commandBlockEntity.isPowered(); +- commandBlockEntity.setPowered(hasNeighborSignal); +- if (!isPowered && !commandBlockEntity.isAutomatic() && commandBlockEntity.getMode() != CommandBlockEntity.Mode.SEQUENCE) { +- if (hasNeighborSignal) { +- commandBlockEntity.markConditionMet(); +- level.scheduleTick(pos, this, 1); ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof CommandBlockEntity) { ++ CommandBlockEntity tileentitycommand = (CommandBlockEntity) tileentity; ++ boolean flag1 = level.hasNeighborSignal(pos); ++ boolean flag2 = tileentitycommand.isPowered(); ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ int old = flag2 ? 15 : 0; ++ int current = flag1 ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bukkitBlock, old, current); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ flag1 = eventRedstone.getNewCurrent() > 0; ++ // CraftBukkit end ++ ++ tileentitycommand.setPowered(flag1); ++ if (!flag2 && !tileentitycommand.isAutomatic() && tileentitycommand.getMode() != CommandBlockEntity.Type.SEQUENCE) { ++ if (flag1) { ++ tileentitycommand.markConditionMet(); ++ level.scheduleTick(pos, (Block) this, 1); + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ComparatorBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ComparatorBlock.java.patch new file mode 100644 index 0000000000..db3ff9b0f0 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ComparatorBlock.java.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/world/level/block/ComparatorBlock.java ++++ b/net/minecraft/world/level/block/ComparatorBlock.java +@@ -27,6 +27,7 @@ + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.ticks.TickPriority; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class ComparatorBlock extends DiodeBlock implements EntityBlock { + public static final MapCodec CODEC = simpleCodec(ComparatorBlock::new); +@@ -157,13 +162,24 @@ + comparatorBlockEntity.setOutputSignal(i); + } + +- if (i1 != i || state.getValue(MODE) == ComparatorMode.COMPARE) { +- boolean shouldTurnOn = this.shouldTurnOn(level, pos, state); +- boolean flag = state.getValue(POWERED); +- if (flag && !shouldTurnOn) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(false)), 2); +- } else if (!flag && shouldTurnOn) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(true)), 2); ++ if (j != i || state.getValue(ComparatorBlock.MODE) == ComparatorMode.COMPARE) { ++ boolean flag = this.shouldTurnOn(level, pos, state); ++ boolean flag1 = (Boolean) state.getValue(ComparatorBlock.POWERED); ++ ++ if (flag1 && !flag) { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 15, 0).getNewCurrent() != 0) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(ComparatorBlock.POWERED, false), 2); ++ } else if (!flag1 && flag) { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 0, 15).getNewCurrent() != 15) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(ComparatorBlock.POWERED, true), 2); + } + + this.updateNeighborsInFront(level, pos, state); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ComposterBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ComposterBlock.java.patch new file mode 100644 index 0000000000..690b7d1f1b --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ComposterBlock.java.patch @@ -0,0 +1,158 @@ +--- a/net/minecraft/world/level/block/ComposterBlock.java ++++ b/net/minecraft/world/level/block/ComposterBlock.java +@@ -40,6 +40,10 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftBlockInventoryHolder; ++import org.bukkit.craftbukkit.util.DummyGeneratorAccess; ++// CraftBukkit end + + public class ComposterBlock extends Block implements WorldlyContainerHolder { + public static final MapCodec CODEC = simpleCodec(ComposterBlock::new); +@@ -251,10 +255,19 @@ + } + } + +- public static BlockState insertItem(Entity entity, BlockState state, ServerLevel level, ItemStack stack, BlockPos pos) { +- int i = state.getValue(LEVEL); +- if (i < 7 && COMPOSTABLES.containsKey(stack.getItem())) { +- BlockState blockState = addItem(entity, state, level, pos, stack); ++ public static IBlockData insertItem(Entity entity, IBlockData state, ServerLevel level, ItemStack stack, BlockPos pos) { ++ int i = (Integer) state.getValue(ComposterBlock.LEVEL); ++ ++ if (i < 7 && ComposterBlock.COMPOSTABLES.containsKey(stack.getItem())) { ++ // CraftBukkit start ++ double rand = level.getRandom().nextDouble(); ++ IBlockData iblockdata1 = addItem(entity, state, DummyGeneratorAccess.INSTANCE, pos, stack, rand); ++ if (state == iblockdata1 || !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, iblockdata1)) { ++ return state; ++ } ++ iblockdata1 = addItem(entity, state, level, pos, stack, rand); ++ // CraftBukkit end ++ + stack.shrink(1); + return blockState; + } else { +@@ -262,7 +275,15 @@ + } + } + +- public static BlockState extractProduce(Entity entity, BlockState state, Level level, BlockPos pos) { ++ public static IBlockData extractProduce(Entity entity, IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ if (entity != null && !(entity instanceof Player)) { ++ IBlockData iblockdata1 = empty(entity, state, DummyGeneratorAccess.INSTANCE, pos); ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, iblockdata1)) { ++ return state; ++ } ++ } ++ // CraftBukkit end + if (!level.isClientSide) { + Vec3 vec3 = Vec3.atLowerCornerWithOffset(pos, 0.5, 1.01, 0.5).offsetRandom(level.random, 0.7F); + ItemEntity itemEntity = new ItemEntity(level, vec3.x(), vec3.y(), vec3.z(), new ItemStack(Items.BONE_MEAL)); +@@ -282,11 +306,18 @@ + return blockState; + } + +- static BlockState addItem(@Nullable Entity entity, BlockState state, LevelAccessor level, BlockPos pos, ItemStack stack) { +- int i = state.getValue(LEVEL); +- float _float = COMPOSTABLES.getFloat(stack.getItem()); +- if ((i != 0 || !(_float > 0.0F)) && !(level.getRandom().nextDouble() < (double)_float)) { +- return state; ++ static IBlockData addItem(@Nullable Entity entity, IBlockData state, LevelAccessor level, BlockPos pos, ItemStack stack) { ++ // CraftBukkit start ++ return addItem(entity, state, level, pos, stack, level.getRandom().nextDouble()); ++ } ++ ++ static IBlockData addItem(@Nullable Entity entity, IBlockData iblockdata, LevelAccessor generatoraccess, BlockPos blockposition, ItemStack itemstack, double rand) { ++ // CraftBukkit end ++ int i = (Integer) iblockdata.getValue(ComposterBlock.LEVEL); ++ float f = ComposterBlock.COMPOSTABLES.getFloat(itemstack.getItem()); ++ ++ if ((i != 0 || f <= 0.0F) && rand >= (double) f) { ++ return iblockdata; + } else { + int i1 = i + 1; + BlockState blockState = state.setValue(LEVEL, Integer.valueOf(i1)); +@@ -329,18 +362,26 @@ + } + + @Override +- public WorldlyContainer getContainer(BlockState state, LevelAccessor level, BlockPos pos) { +- int i = state.getValue(LEVEL); +- if (i == 8) { +- return new ComposterBlock.OutputContainer(state, level, pos, new ItemStack(Items.BONE_MEAL)); +- } else { +- return (WorldlyContainer)(i < 7 ? new ComposterBlock.InputContainer(state, level, pos) : new ComposterBlock.EmptyContainer()); +- } ++ public WorldlyContainer getContainer(IBlockData state, LevelAccessor level, BlockPos pos) { ++ int i = (Integer) state.getValue(ComposterBlock.LEVEL); ++ ++ // CraftBukkit - empty generatoraccess, blockposition ++ return (WorldlyContainer) (i == 8 ? new ComposterBlock.OutputContainer(state, level, pos, new ItemStack(Items.BONE_MEAL)) : (i < 7 ? new ComposterBlock.InputContainer(state, level, pos) : new ComposterBlock.EmptyContainer(level, pos))); + } + +- static class EmptyContainer extends SimpleContainer implements WorldlyContainer { +- public EmptyContainer() { +- super(0); ++ public static class OutputContainer extends SimpleContainer implements WorldlyContainer { ++ ++ private final IBlockData state; ++ private final LevelAccessor level; ++ private final BlockPos pos; ++ private boolean changed; ++ ++ public OutputContainer(IBlockData state, LevelAccessor level, BlockPos pos, ItemStack stack) { ++ super(stack); ++ this.state = state; ++ this.level = level; ++ this.pos = pos; ++ this.bukkitOwner = new CraftBlockInventoryHolder(level, pos, this); // CraftBukkit + } + + @Override +@@ -357,6 +403,19 @@ + public boolean canTakeItemThroughFace(int index, ItemStack stack, Direction direction) { + return false; + } ++ ++ @Override ++ public void setChanged() { ++ // CraftBukkit start - allow putting items back (eg cancelled InventoryMoveItemEvent) ++ if (this.isEmpty()) { ++ ComposterBlock.empty((Entity) null, this.state, this.level, this.pos); ++ this.changed = true; ++ } else { ++ this.level.setBlock(this.pos, this.state, 3); ++ this.changed = false; ++ } ++ // CraftBukkit end ++ } + } + + static class InputContainer extends SimpleContainer implements WorldlyContainer { +@@ -367,6 +427,7 @@ + + public InputContainer(BlockState state, LevelAccessor level, BlockPos pos) { + super(1); ++ this.bukkitOwner = new CraftBlockInventoryHolder(level, pos, this); // CraftBukkit + this.state = state; + this.level = level; + this.pos = pos; +@@ -410,11 +470,9 @@ + private final BlockPos pos; + private boolean changed; + +- public OutputContainer(BlockState state, LevelAccessor level, BlockPos pos, ItemStack stack) { +- super(stack); +- this.state = state; +- this.level = level; +- this.pos = pos; ++ public EmptyContainer(LevelAccessor generatoraccess, BlockPos blockposition) { // CraftBukkit ++ super(0); ++ this.bukkitOwner = new CraftBlockInventoryHolder(generatoraccess, blockposition, this); // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ConcretePowderBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ConcretePowderBlock.java.patch new file mode 100644 index 0000000000..7334a8a06a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ConcretePowderBlock.java.patch @@ -0,0 +1,87 @@ +--- a/net/minecraft/world/level/block/ConcretePowderBlock.java ++++ b/net/minecraft/world/level/block/ConcretePowderBlock.java +@@ -15,6 +14,12 @@ + import net.minecraft.world.level.block.state.BlockBehaviour; + import net.minecraft.world.level.block.state.BlockState; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.block.CraftBlockStates; ++import org.bukkit.event.block.BlockFormEvent; ++// CraftBukkit end ++ + public class ConcretePowderBlock extends FallingBlock { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( + instance -> instance.group( +@@ -37,16 +42,34 @@ + @Override + public void onLand(Level level, BlockPos pos, BlockState state, BlockState replaceableState, FallingBlockEntity fallingBlock) { + if (shouldSolidify(level, pos, replaceableState)) { +- level.setBlock(pos, this.concrete.defaultBlockState(), 3); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, this.concrete.defaultBlockState(), 3); // CraftBukkit + } + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- BlockGetter level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- BlockState blockState = level.getBlockState(clickedPos); +- return shouldSolidify(level, clickedPos, blockState) ? this.concrete.defaultBlockState() : super.getStateForPlacement(context); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ ++ // CraftBukkit start ++ if (!shouldSolidify(world, blockposition, iblockdata)) { ++ return super.getStateForPlacement(context); ++ } ++ ++ // TODO: An event factory call for methods like this ++ CraftBlockState blockState = CraftBlockStates.getBlockState(world, blockposition); ++ blockState.setData(this.concrete.defaultBlockState()); ++ ++ BlockFormEvent event = new BlockFormEvent(blockState.getBlock(), blockState); ++ world.getServer().server.getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ return blockState.getHandle(); ++ } ++ ++ return super.getStateForPlacement(context); ++ // CraftBukkit end + } + + private static boolean shouldSolidify(BlockGetter level, BlockPos pos, BlockState state) { +@@ -77,10 +105,26 @@ + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- return touchesLiquid(level, currentPos) +- ? this.concrete.defaultBlockState() +- : super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ // CraftBukkit start ++ if (touchesLiquid(level, currentPos)) { ++ // Suppress during worldgen ++ if (!(level instanceof Level)) { ++ return this.concrete.defaultBlockState(); ++ } ++ CraftBlockState blockState = CraftBlockStates.getBlockState(level, currentPos); ++ blockState.setData(this.concrete.defaultBlockState()); ++ ++ BlockFormEvent event = new BlockFormEvent(blockState.getBlock(), blockState); ++ ((Level) level).getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ return blockState.getHandle(); ++ } ++ } ++ ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CoralBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CoralBlock.java.patch new file mode 100644 index 0000000000..39f509e892 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CoralBlock.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/block/CoralBlock.java ++++ b/net/minecraft/world/level/block/CoralBlock.java +@@ -37,6 +39,11 @@ + @Override + public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { + if (!this.scanForWater(level, pos)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, this.deadBlock.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + level.setBlock(pos, this.deadBlock.defaultBlockState(), 2); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CoralFanBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CoralFanBlock.java.patch new file mode 100644 index 0000000000..e5fbee2b9a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CoralFanBlock.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/level/block/CoralFanBlock.java ++++ b/net/minecraft/world/level/block/CoralFanBlock.java +@@ -38,7 +40,12 @@ + @Override + public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { + if (!scanForWater(state, level, pos)) { +- level.setBlock(pos, this.deadBlock.defaultBlockState().setValue(WATERLOGGED, Boolean.valueOf(false)), 2); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, this.deadBlock.defaultBlockState().setValue(CoralFanBlock.WATERLOGGED, false)).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) this.deadBlock.defaultBlockState().setValue(CoralFanBlock.WATERLOGGED, false), 2); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CoralPlantBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CoralPlantBlock.java.patch new file mode 100644 index 0000000000..9d6f2c3db4 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CoralPlantBlock.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/level/block/CoralPlantBlock.java ++++ b/net/minecraft/world/level/block/CoralPlantBlock.java +@@ -43,7 +45,12 @@ + @Override + public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { + if (!scanForWater(state, level, pos)) { +- level.setBlock(pos, this.deadBlock.defaultBlockState().setValue(WATERLOGGED, Boolean.valueOf(false)), 2); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, this.deadBlock.defaultBlockState().setValue(CoralPlantBlock.WATERLOGGED, false)).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) this.deadBlock.defaultBlockState().setValue(CoralPlantBlock.WATERLOGGED, false), 2); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CoralWallFanBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CoralWallFanBlock.java.patch new file mode 100644 index 0000000000..1c33d2a2d2 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CoralWallFanBlock.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/level/block/CoralWallFanBlock.java ++++ b/net/minecraft/world/level/block/CoralWallFanBlock.java +@@ -38,7 +40,12 @@ + @Override + public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { + if (!scanForWater(state, level, pos)) { +- level.setBlock(pos, this.deadBlock.defaultBlockState().setValue(WATERLOGGED, Boolean.valueOf(false)).setValue(FACING, state.getValue(FACING)), 2); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, this.deadBlock.defaultBlockState().setValue(CoralWallFanBlock.WATERLOGGED, false).setValue(CoralWallFanBlock.FACING, state.getValue(CoralWallFanBlock.FACING))).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) ((IBlockData) this.deadBlock.defaultBlockState().setValue(CoralWallFanBlock.WATERLOGGED, false)).setValue(CoralWallFanBlock.FACING, (Direction) state.getValue(CoralWallFanBlock.FACING)), 2); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CropBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CropBlock.java.patch new file mode 100644 index 0000000000..9376dde184 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/CropBlock.java.patch @@ -0,0 +1,49 @@ +--- a/net/minecraft/world/level/block/CropBlock.java ++++ b/net/minecraft/world/level/block/CropBlock.java +@@ -21,6 +21,7 @@ + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class CropBlock extends BushBlock implements BonemealableBlock { + public static final MapCodec CODEC = simpleCodec(CropBlock::new); +@@ -85,11 +78,13 @@ + @Override + public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { + if (level.getRawBrightness(pos, 0) >= 9) { +- int age = this.getAge(state); +- if (age < this.getMaxAge()) { +- float growthSpeed = getGrowthSpeed(this, level, pos); +- if (random.nextInt((int)(25.0F / growthSpeed) + 1) == 0) { +- level.setBlock(pos, this.getStateForAge(age + 1), 2); ++ int i = this.getAge(state); ++ ++ if (i < this.getMaxAge()) { ++ float f = getGrowthSpeed(this, level, pos); ++ ++ if (random.nextInt((int) (25.0F / f) + 1) == 0) { ++ CraftEventFactory.handleBlockGrowEvent(level, pos, this.getStateForAge(i + 1), 2); // CraftBukkit + } + } + } +@@ -102,7 +99,7 @@ + i = maxAge; + } + +- level.setBlock(pos, this.getStateForAge(i), 2); ++ CraftEventFactory.handleBlockGrowEvent(level, pos, this.getStateForAge(i), 2); // CraftBukkit + } + + protected int getBonemealAgeIncrease(Level level) { +@@ -163,8 +160,8 @@ + } + + @Override +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { +- if (entity instanceof Ravager && level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ if (entity instanceof Ravager && CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit + level.destroyBlock(pos, true, entity); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DaylightDetectorBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DaylightDetectorBlock.java.patch new file mode 100644 index 0000000000..944ed45073 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DaylightDetectorBlock.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/level/block/DaylightDetectorBlock.java ++++ b/net/minecraft/world/level/block/DaylightDetectorBlock.java +@@ -69,9 +72,10 @@ + i = Math.round((float)i * Mth.cos(sunAngle)); + } + +- int var7 = Mth.clamp(i, 0, 15); +- if (state.getValue(POWER) != var7) { +- level.setBlock(pos, state.setValue(POWER, Integer.valueOf(var7)), 3); ++ i = Mth.clamp(i, 0, 15); ++ if ((Integer) state.getValue(DaylightDetectorBlock.POWER) != i) { ++ i = org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(level, pos, ((Integer) state.getValue(POWER)), i).getNewCurrent(); // CraftBukkit - Call BlockRedstoneEvent ++ level.setBlock(pos, (IBlockData) state.setValue(DaylightDetectorBlock.POWER, i), 3); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DetectorRailBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DetectorRailBlock.java.patch new file mode 100644 index 0000000000..48e8df7fa7 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DetectorRailBlock.java.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/world/level/block/DetectorRailBlock.java ++++ b/net/minecraft/world/level/block/DetectorRailBlock.java +@@ -24,6 +25,7 @@ + import net.minecraft.world.level.block.state.properties.Property; + import net.minecraft.world.level.block.state.properties.RailShape; + import net.minecraft.world.phys.AABB; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class DetectorRailBlock extends BaseRailBlock { + public static final MapCodec CODEC = simpleCodec(DetectorRailBlock::new); +@@ -91,6 +87,18 @@ + flag1 = true; + } + ++ IBlockData iblockdata1; ++ // CraftBukkit start ++ if (flag != flag1) { ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, flag ? 15 : 0, flag1 ? 15 : 0); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ flag1 = eventRedstone.getNewCurrent() > 0; ++ } ++ // CraftBukkit end ++ + if (flag1 && !flag) { + BlockState blockState = state.setValue(POWERED, Boolean.valueOf(true)); + level.setBlock(pos, blockState, 3); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DiodeBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DiodeBlock.java.patch new file mode 100644 index 0000000000..dc5eef8e62 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DiodeBlock.java.patch @@ -0,0 +1,44 @@ +--- a/net/minecraft/world/level/block/DiodeBlock.java ++++ b/net/minecraft/world/level/block/DiodeBlock.java +@@ -20,6 +20,7 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.ticks.TickPriority; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public abstract class DiodeBlock extends HorizontalDirectionalBlock { + protected static final VoxelShape SHAPE = Block.box(0.0, 0.0, 0.0, 16.0, 2.0, 16.0); +@@ -50,15 +53,26 @@ + @Override + public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { + if (!this.isLocked(level, pos, state)) { +- boolean flag = state.getValue(POWERED); +- boolean shouldTurnOn = this.shouldTurnOn(level, pos, state); +- if (flag && !shouldTurnOn) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(false)), 2); ++ boolean flag = (Boolean) state.getValue(DiodeBlock.POWERED); ++ boolean flag1 = this.shouldTurnOn(level, pos, state); ++ ++ if (flag && !flag1) { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 15, 0).getNewCurrent() != 0) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(DiodeBlock.POWERED, false), 2); + } else if (!flag) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(true)), 2); +- if (!shouldTurnOn) { +- level.scheduleTick(pos, this, this.getDelay(state), TickPriority.VERY_HIGH); ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 0, 15).getNewCurrent() != 15) { ++ return; + } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(DiodeBlock.POWERED, true), 2); ++ if (!flag1) { ++ level.scheduleTick(pos, (Block) this, this.getDelay(state), TickPriority.VERY_HIGH); ++ } + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DispenserBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DispenserBlock.java.patch new file mode 100644 index 0000000000..e4f1362f72 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DispenserBlock.java.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/world/level/block/DispenserBlock.java ++++ b/net/minecraft/world/level/block/DispenserBlock.java +@@ -48,6 +49,7 @@ + new Object2ObjectOpenHashMap<>(), map -> map.defaultReturnValue(new DefaultDispenseItemBehavior()) + ); + private static final int TRIGGER_DURATION = 4; ++ public static boolean eventFired = false; // CraftBukkit + + @Override + public MapCodec codec() { +@@ -93,10 +98,12 @@ + serverLevel.levelEvent(1001, blockPos, 0); + serverLevel.gameEvent(GameEvent.BLOCK_ACTIVATE, blockPos, GameEvent.Context.of(dispenserBlockEntity.getBlockState())); + } else { +- ItemStack item = dispenserBlockEntity.getItem(randomSlot); +- DispenseItemBehavior dispenseMethod = this.getDispenseMethod(item); +- if (dispenseMethod != DispenseItemBehavior.NOOP) { +- dispenserBlockEntity.setItem(randomSlot, dispenseMethod.dispense(blockSource, item)); ++ ItemStack itemstack = tileentitydispenser.getItem(i); ++ DispenseItemBehavior idispensebehavior = this.getDispenseMethod(itemstack); ++ ++ if (idispensebehavior != DispenseItemBehavior.NOOP) { ++ eventFired = false; // CraftBukkit - reset event status ++ tileentitydispenser.setItem(i, idispensebehavior.dispense(sourceblock, itemstack)); + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DoorBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DoorBlock.java.patch new file mode 100644 index 0000000000..4c9bb9185a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DoorBlock.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/world/level/block/DoorBlock.java ++++ b/net/minecraft/world/level/block/DoorBlock.java +@@ -37,6 +36,7 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class DoorBlock extends Block { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +@@ -223,13 +220,28 @@ + } + + @Override +- public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { +- boolean flag = level.hasNeighborSignal(pos) +- || level.hasNeighborSignal(pos.relative(state.getValue(HALF) == DoubleBlockHalf.LOWER ? Direction.UP : Direction.DOWN)); +- if (!this.defaultBlockState().is(block) && flag != state.getValue(POWERED)) { +- if (flag != state.getValue(OPEN)) { +- this.playSound(null, level, pos, flag); +- level.gameEvent(null, flag ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ // CraftBukkit start ++ BlockPos otherHalf = pos.relative(state.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER ? Direction.UP : Direction.DOWN); ++ ++ org.bukkit.World bworld = level.getWorld(); ++ org.bukkit.block.Block bukkitBlock = bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ org.bukkit.block.Block blockTop = bworld.getBlockAt(otherHalf.getX(), otherHalf.getY(), otherHalf.getZ()); ++ ++ int power = bukkitBlock.getBlockPower(); ++ int powerTop = blockTop.getBlockPower(); ++ if (powerTop > power) power = powerTop; ++ int oldPower = (Boolean) state.getValue(DoorBlock.POWERED) ? 15 : 0; ++ ++ if (oldPower == 0 ^ power == 0) { ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bukkitBlock, oldPower, power); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ boolean flag1 = eventRedstone.getNewCurrent() > 0; ++ // CraftBukkit end ++ if (flag1 != (Boolean) state.getValue(DoorBlock.OPEN)) { ++ this.playSound((Entity) null, level, pos, flag1); ++ level.gameEvent((Entity) null, flag1 ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); + } + + level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(flag)).setValue(OPEN, Boolean.valueOf(flag)), 2); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DoublePlantBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DoublePlantBlock.java.patch new file mode 100644 index 0000000000..c37c0fc460 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DoublePlantBlock.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/level/block/DoublePlantBlock.java ++++ b/net/minecraft/world/level/block/DoublePlantBlock.java +@@ -105,15 +100,23 @@ + super.playerDestroy(level, player, pos, Blocks.AIR.defaultBlockState(), te, stack); + } + +- protected static void preventDropFromBottomPart(Level level, BlockPos blockPos, BlockState blockState, Player player) { +- DoubleBlockHalf doubleBlockHalf = blockState.getValue(HALF); +- if (doubleBlockHalf == DoubleBlockHalf.UPPER) { +- BlockPos blockPos1 = blockPos.below(); +- BlockState blockState1 = level.getBlockState(blockPos1); +- if (blockState1.is(blockState.getBlock()) && blockState1.getValue(HALF) == DoubleBlockHalf.LOWER) { +- BlockState blockState2 = blockState1.getFluidState().is(Fluids.WATER) ? Blocks.WATER.defaultBlockState() : Blocks.AIR.defaultBlockState(); +- level.setBlock(blockPos1, blockState2, 35); +- level.levelEvent(player, 2001, blockPos1, Block.getId(blockState1)); ++ protected static void preventDropFromBottomPart(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, blockposition).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ BlockPropertyDoubleBlockHalf blockpropertydoubleblockhalf = (BlockPropertyDoubleBlockHalf) iblockdata.getValue(DoublePlantBlock.HALF); ++ ++ if (blockpropertydoubleblockhalf == BlockPropertyDoubleBlockHalf.UPPER) { ++ BlockPos blockposition1 = blockposition.below(); ++ IBlockData iblockdata1 = world.getBlockState(blockposition1); ++ ++ if (iblockdata1.is(iblockdata.getBlock()) && iblockdata1.getValue(DoublePlantBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER) { ++ IBlockData iblockdata2 = iblockdata1.getFluidState().is((Fluid) Fluids.WATER) ? Blocks.WATER.defaultBlockState() : Blocks.AIR.defaultBlockState(); ++ ++ world.setBlock(blockposition1, iblockdata2, 35); ++ world.levelEvent(entityhuman, 2001, blockposition1, Block.getId(iblockdata1)); + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DragonEggBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DragonEggBlock.java.patch new file mode 100644 index 0000000000..f0402a4d3f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DragonEggBlock.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/level/block/DragonEggBlock.java ++++ b/net/minecraft/world/level/block/DragonEggBlock.java +@@ -16,6 +16,7 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockFromToEvent; // CraftBukkit + + public class DragonEggBlock extends FallingBlock { + public static final MapCodec CODEC = simpleCodec(DragonEggBlock::new); +@@ -49,13 +51,22 @@ + private void teleport(BlockState state, Level level, BlockPos pos) { + WorldBorder worldBorder = level.getWorldBorder(); + +- for (int i = 0; i < 1000; i++) { +- BlockPos blockPos = pos.offset( +- level.random.nextInt(16) - level.random.nextInt(16), +- level.random.nextInt(8) - level.random.nextInt(8), +- level.random.nextInt(16) - level.random.nextInt(16) +- ); +- if (level.getBlockState(blockPos).isAir() && worldBorder.isWithinBounds(blockPos)) { ++ for (int i = 0; i < 1000; ++i) { ++ BlockPos blockposition1 = pos.offset(level.random.nextInt(16) - level.random.nextInt(16), level.random.nextInt(8) - level.random.nextInt(8), level.random.nextInt(16) - level.random.nextInt(16)); ++ ++ if (level.getBlockState(blockposition1).isAir() && worldborder.isWithinBounds(blockposition1)) { ++ // CraftBukkit start ++ org.bukkit.block.Block from = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ org.bukkit.block.Block to = level.getWorld().getBlockAt(blockposition1.getX(), blockposition1.getY(), blockposition1.getZ()); ++ BlockFromToEvent event = new BlockFromToEvent(from, to); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ blockposition1 = new BlockPos(event.getToBlock().getX(), event.getToBlock().getY(), event.getToBlock().getZ()); ++ // CraftBukkit end + if (level.isClientSide) { + for (int i1 = 0; i1 < 128; i1++) { + double randomDouble = level.random.nextDouble(); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DropExperienceBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DropExperienceBlock.java.patch new file mode 100644 index 0000000000..9a32d222bf --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DropExperienceBlock.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/level/block/DropExperienceBlock.java ++++ b/net/minecraft/world/level/block/DropExperienceBlock.java +@@ -32,8 +31,16 @@ + @Override + public void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { + super.spawnAfterBreak(state, level, pos, stack, dropExperience); +- if (dropExperience) { +- this.tryDropExperience(level, pos, stack, this.xpRange); ++ // CraftBukkit start - Delegate to getExpDrop ++ } ++ ++ @Override ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { ++ if (flag) { ++ return this.tryDropExperience(worldserver, blockposition, itemstack, this.xpRange); + } ++ ++ return 0; ++ // CraftBukkit end + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DropperBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DropperBlock.java.patch new file mode 100644 index 0000000000..e7aa037c18 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/DropperBlock.java.patch @@ -0,0 +1,53 @@ +--- a/net/minecraft/world/level/block/DropperBlock.java ++++ b/net/minecraft/world/level/block/DropperBlock.java +@@ -18,11 +19,14 @@ + import net.minecraft.world.level.block.state.BlockBehaviour; + import net.minecraft.world.level.block.state.BlockState; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.inventory.InventoryMoveItemEvent; ++// CraftBukkit end + + public class DropperBlock extends DispenserBlock { + private static final Logger LOGGER = LogUtils.getLogger(); + public static final MapCodec CODEC = simpleCodec(DropperBlock::new); +- private static final DispenseItemBehavior DISPENSE_BEHAVIOUR = new DefaultDispenseItemBehavior(); ++ private static final DispenseItemBehavior DISPENSE_BEHAVIOUR = new DefaultDispenseItemBehavior(true); // CraftBukkit + + @Override + public MapCodec codec() { +@@ -62,13 +71,30 @@ + if (containerAt == null) { + itemStack = DISPENSE_BEHAVIOUR.dispense(blockSource, item); + } else { +- itemStack = HopperBlockEntity.addItem(dispenserBlockEntity, containerAt, item.copy().split(1), direction.getOpposite()); +- if (itemStack.isEmpty()) { +- itemStack = item.copy(); +- itemStack.shrink(1); ++ // CraftBukkit start - Fire event when pushing items into other inventories ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(itemstack.copy().split(1)); ++ ++ org.bukkit.inventory.Inventory destinationInventory; ++ // Have to special case large chests as they work oddly ++ if (iinventory instanceof CompoundContainer) { ++ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory); + } else { + itemStack = item.copy(); + } ++ ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(tileentitydispenser.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true); ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ itemstack1 = HopperBlockEntity.addItem(tileentitydispenser, iinventory, CraftItemStack.asNMSCopy(event.getItem()), enumdirection.getOpposite()); ++ if (event.getItem().equals(oitemstack) && itemstack1.isEmpty()) { ++ // CraftBukkit end ++ itemstack1 = itemstack.copy(); ++ itemstack1.shrink(1); ++ } else { ++ itemstack1 = itemstack.copy(); ++ } + } + + dispenserBlockEntity.setItem(randomSlot, itemStack); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/EndPortalBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/EndPortalBlock.java.patch new file mode 100644 index 0000000000..47f398995a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/EndPortalBlock.java.patch @@ -0,0 +1,51 @@ +--- a/net/minecraft/world/level/block/EndPortalBlock.java ++++ b/net/minecraft/world/level/block/EndPortalBlock.java +@@ -20,6 +22,9 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.entity.EntityPortalEnterEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++// CraftBukkit end + + public class EndPortalBlock extends BaseEntityBlock { + public static final MapCodec CODEC = simpleCodec(EndPortalBlock::new); +@@ -45,21 +51,25 @@ + } + + @Override +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { +- if (level instanceof ServerLevel +- && entity.canChangeDimensions() +- && Shapes.joinIsNotEmpty( +- Shapes.create(entity.getBoundingBox().move((double)(-pos.getX()), (double)(-pos.getY()), (double)(-pos.getZ()))), +- state.getShape(level, pos), +- BooleanOp.AND +- )) { +- ResourceKey resourceKey = level.dimension() == Level.END ? Level.OVERWORLD : Level.END; +- ServerLevel level1 = ((ServerLevel)level).getServer().getLevel(resourceKey); +- if (level1 == null) { +- return; ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ if (level instanceof ServerLevel && entity.canChangeDimensions() && Shapes.joinIsNotEmpty(Shapes.create(entity.getBoundingBox().move((double) (-pos.getX()), (double) (-pos.getY()), (double) (-pos.getZ()))), state.getShape(level, pos), BooleanOp.AND)) { ++ ResourceKey resourcekey = level.getTypeKey() == LevelStem.END ? Level.OVERWORLD : Level.END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends ++ ServerLevel worldserver = ((ServerLevel) level).getServer().getLevel(resourcekey); ++ ++ if (worldserver == null) { ++ // return; // CraftBukkit - always fire event in case plugins wish to change it + } + +- entity.changeDimension(level1); ++ // CraftBukkit start - Entity in portal ++ EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(level.getWorld(), pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (entity instanceof ServerPlayer) { ++ ((ServerPlayer) entity).changeDimension(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); ++ return; ++ } ++ // CraftBukkit end ++ entity.changeDimension(worldserver); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/FarmBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/FarmBlock.java.patch new file mode 100644 index 0000000000..af8d092023 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/FarmBlock.java.patch @@ -0,0 +1,79 @@ +--- a/net/minecraft/world/level/block/FarmBlock.java ++++ b/net/minecraft/world/level/block/FarmBlock.java +@@ -27,6 +28,10 @@ + import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.event.entity.EntityInteractEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class FarmBlock extends Block { + public static final MapCodec CODEC = simpleCodec(FarmBlock::new); +@@ -88,32 +95,52 @@ + int i = state.getValue(MOISTURE); + if (!isNearWater(level, pos) && !level.isRainingAt(pos.above())) { + if (i > 0) { +- level.setBlock(pos, state.setValue(MOISTURE, Integer.valueOf(i - 1)), 2); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleMoistureChangeEvent(level, pos, (IBlockData) state.setValue(FarmBlock.MOISTURE, i - 1), 2); // CraftBukkit + } else if (!shouldMaintainFarmland(level, pos)) { + turnToDirt(null, state, level, pos); + } + } else if (i < 7) { +- level.setBlock(pos, state.setValue(MOISTURE, Integer.valueOf(7)), 2); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleMoistureChangeEvent(level, pos, (IBlockData) state.setValue(FarmBlock.MOISTURE, 7), 2); // CraftBukkit + } + } + + @Override +- public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, float fallDistance) { +- if (!level.isClientSide +- && level.random.nextFloat() < fallDistance - 0.5F +- && entity instanceof LivingEntity +- && (entity instanceof Player || level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) +- && entity.getBbWidth() * entity.getBbWidth() * entity.getBbHeight() > 0.512F) { ++ public void fallOn(Level level, IBlockData state, BlockPos pos, Entity entity, float fallDistance) { ++ super.fallOn(level, state, pos, entity, fallDistance); // CraftBukkit - moved here as game rules / events shouldn't affect fall damage. ++ if (!level.isClientSide && level.random.nextFloat() < fallDistance - 0.5F && entity instanceof LivingEntity && (entity instanceof Player || level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && entity.getBbWidth() * entity.getBbWidth() * entity.getBbHeight() > 0.512F) { ++ // CraftBukkit start - Interact soil ++ org.bukkit.event.Cancellable cancellable; ++ if (entity instanceof Player) { ++ cancellable = CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ if (cancellable.isCancelled()) { ++ return; ++ } ++ ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.DIRT.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end + turnToDirt(entity, state, level, pos); + } + +- super.fallOn(level, state, pos, entity, fallDistance); ++ // super.fallOn(world, iblockdata, blockposition, entity, f); // CraftBukkit - moved up + } + +- public static void turnToDirt(@Nullable Entity entity, BlockState state, Level level, BlockPos pos) { +- BlockState blockState = pushEntitiesUp(state, Blocks.DIRT.defaultBlockState(), level, pos); +- level.setBlockAndUpdate(pos, blockState); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, blockState)); ++ public static void turnToDirt(@Nullable Entity entity, IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ if (CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ IBlockData iblockdata1 = pushEntitiesUp(state, Blocks.DIRT.defaultBlockState(), level, pos); ++ ++ level.setBlockAndUpdate(pos, iblockdata1); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, iblockdata1)); + } + + private static boolean shouldMaintainFarmland(BlockGetter level, BlockPos pos) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/FenceGateBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/FenceGateBlock.java.patch new file mode 100644 index 0000000000..1e6032f92b --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/FenceGateBlock.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/level/block/FenceGateBlock.java ++++ b/net/minecraft/world/level/block/FenceGateBlock.java +@@ -195,19 +167,24 @@ + @Override + public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { + if (!level.isClientSide) { +- boolean hasNeighborSignal = level.hasNeighborSignal(pos); +- if (state.getValue(POWERED) != hasNeighborSignal) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(hasNeighborSignal)).setValue(OPEN, Boolean.valueOf(hasNeighborSignal)), 2); +- if (state.getValue(OPEN) != hasNeighborSignal) { +- level.playSound( +- null, +- pos, +- hasNeighborSignal ? this.type.fenceGateOpen() : this.type.fenceGateClose(), +- SoundSource.BLOCKS, +- 1.0F, +- level.getRandom().nextFloat() * 0.1F + 0.9F +- ); +- level.gameEvent(null, hasNeighborSignal ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); ++ boolean flag1 = level.hasNeighborSignal(pos); ++ // CraftBukkit start ++ boolean oldPowered = state.getValue(FenceGateBlock.POWERED); ++ if (oldPowered != flag1) { ++ int newPower = flag1 ? 15 : 0; ++ int oldPower = oldPowered ? 15 : 0; ++ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos); ++ org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(bukkitBlock, oldPower, newPower); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ flag1 = eventRedstone.getNewCurrent() > 0; ++ } ++ // CraftBukkit end ++ ++ if ((Boolean) state.getValue(FenceGateBlock.POWERED) != flag1) { ++ level.setBlock(pos, (IBlockData) ((IBlockData) state.setValue(FenceGateBlock.POWERED, flag1)).setValue(FenceGateBlock.OPEN, flag1), 2); ++ if ((Boolean) state.getValue(FenceGateBlock.OPEN) != flag1) { ++ level.playSound((Player) null, pos, flag1 ? this.type.fenceGateOpen() : this.type.fenceGateClose(), SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.1F + 0.9F); ++ level.gameEvent((Entity) null, flag1 ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/FireBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/FireBlock.java.patch new file mode 100644 index 0000000000..2fa5e5c3d2 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/FireBlock.java.patch @@ -0,0 +1,182 @@ +--- a/net/minecraft/world/level/block/FireBlock.java ++++ b/net/minecraft/world/level/block/FireBlock.java +@@ -29,6 +28,13 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.block.CraftBlockStates; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.block.BlockBurnEvent; ++import org.bukkit.event.block.BlockFadeEvent; ++// CraftBukkit end + + public class FireBlock extends BaseFireBlock { + public static final MapCodec CODEC = simpleCodec(FireBlock::new); +@@ -113,8 +106,25 @@ + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- return this.canSurvive(state, level, currentPos) ? this.getStateWithAge(level, currentPos, state.getValue(AGE)) : Blocks.AIR.defaultBlockState(); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ // CraftBukkit start ++ if (!this.canSurvive(state, level, currentPos)) { ++ // Suppress during worldgen ++ if (!(level instanceof Level)) { ++ return Blocks.AIR.defaultBlockState(); ++ } ++ CraftBlockState blockState = CraftBlockStates.getBlockState(level, currentPos); ++ blockState.setData(Blocks.AIR.defaultBlockState()); ++ ++ BlockFadeEvent event = new BlockFadeEvent(blockState.getBlock(), blockState); ++ ((Level) level).getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ return blockState.getHandle(); ++ } ++ } ++ return this.getStateWithAge(level, currentPos, (Integer) state.getValue(FireBlock.AGE)); ++ // CraftBukkit end + } + + @Override +@@ -157,14 +173,15 @@ + level.scheduleTick(pos, this, getFireTickDelay(level.random)); + if (level.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) { + if (!state.canSurvive(level, pos)) { +- level.removeBlock(pos, false); ++ fireExtinguished(level, pos); // CraftBukkit - invalid place location + } + +- BlockState blockState = level.getBlockState(pos.below()); +- boolean isTag = blockState.is(level.dimensionType().infiniburn()); +- int i = state.getValue(AGE); +- if (!isTag && level.isRaining() && this.isNearRain(level, pos) && random.nextFloat() < 0.2F + (float)i * 0.03F) { +- level.removeBlock(pos, false); ++ IBlockData iblockdata1 = level.getBlockState(pos.below()); ++ boolean flag = iblockdata1.is(level.dimensionType().infiniburn()); ++ int i = (Integer) state.getValue(FireBlock.AGE); ++ ++ if (!flag && level.isRaining() && this.isNearRain(level, pos) && random.nextFloat() < 0.2F + (float) i * 0.03F) { ++ fireExtinguished(level, pos); // CraftBukkit - extinguished by rain + } else { + int min = Math.min(15, i + random.nextInt(3) / 2); + if (i != min) { +@@ -174,16 +192,17 @@ + + if (!isTag) { + if (!this.isValidFireLocation(level, pos)) { +- BlockPos blockPos = pos.below(); +- if (!level.getBlockState(blockPos).isFaceSturdy(level, blockPos, Direction.UP) || i > 3) { +- level.removeBlock(pos, false); ++ BlockPos blockposition1 = pos.below(); ++ ++ if (!level.getBlockState(blockposition1).isFaceSturdy(level, blockposition1, Direction.UP) || i > 3) { ++ fireExtinguished(level, pos); // CraftBukkit + } + + return; + } + + if (i == 15 && random.nextInt(4) == 0 && !this.canBurn(level.getBlockState(pos.below()))) { +- level.removeBlock(pos, false); ++ fireExtinguished(level, pos); // CraftBukkit + return; + } + } +@@ -198,13 +210,24 @@ + this.checkBurnOut(level, pos.south(), 300 + i1, random, i); + BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); + +- for (int i2 = -1; i2 <= 1; i2++) { +- for (int i3 = -1; i3 <= 1; i3++) { +- for (int i4 = -1; i4 <= 4; i4++) { +- if (i2 != 0 || i4 != 0 || i3 != 0) { +- int i5 = 100; +- if (i4 > 1) { +- i5 += (i4 - 1) * 100; ++ // CraftBukkit start - add source blockposition to burn calls ++ this.trySpread(level, pos.east(), 300 + k, random, i, pos); ++ this.trySpread(level, pos.west(), 300 + k, random, i, pos); ++ this.trySpread(level, pos.below(), 250 + k, random, i, pos); ++ this.trySpread(level, pos.above(), 250 + k, random, i, pos); ++ this.trySpread(level, pos.north(), 300 + k, random, i, pos); ++ this.trySpread(level, pos.south(), 300 + k, random, i, pos); ++ // CraftBukkit end ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ ++ for (int l = -1; l <= 1; ++l) { ++ for (int i1 = -1; i1 <= 1; ++i1) { ++ for (int j1 = -1; j1 <= 4; ++j1) { ++ if (l != 0 || j1 != 0 || i1 != 0) { ++ int k1 = 100; ++ ++ if (j1 > 1) { ++ k1 += (j1 - 1) * 100; + } + + mutableBlockPos.setWithOffset(pos, i2, i4, i3); +@@ -215,9 +240,18 @@ + i6 /= 2; + } + +- if (i6 > 0 && random.nextInt(i5) <= i6 && (!level.isRaining() || !this.isNearRain(level, mutableBlockPos))) { +- int min1 = Math.min(15, i + random.nextInt(5) / 4); +- level.setBlock(mutableBlockPos, this.getStateWithAge(level, mutableBlockPos, min1), 3); ++ if (i2 > 0 && random.nextInt(k1) <= i2 && (!level.isRaining() || !this.isNearRain(level, blockposition_mutableblockposition))) { ++ int j2 = Math.min(15, i + random.nextInt(5) / 4); ++ ++ // CraftBukkit start - Call to stop spread of fire ++ if (level.getBlockState(blockposition_mutableblockposition).getBlock() != Blocks.FIRE) { ++ if (CraftEventFactory.callBlockIgniteEvent(level, blockposition_mutableblockposition, pos).isCancelled()) { ++ continue; ++ } ++ ++ CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition_mutableblockposition, this.getStateWithAge(level, blockposition_mutableblockposition, j2), 3); // CraftBukkit ++ } ++ // CraftBukkit end + } + } + } +@@ -248,13 +275,32 @@ + : this.igniteOdds.getInt(state.getBlock()); + } + +- private void checkBurnOut(Level level, BlockPos pos, int chance, RandomSource random, int age) { +- int burnOdds = this.getBurnOdds(level.getBlockState(pos)); +- if (random.nextInt(chance) < burnOdds) { +- BlockState blockState = level.getBlockState(pos); +- if (random.nextInt(age + 10) < 5 && !level.isRainingAt(pos)) { +- int min = Math.min(age + random.nextInt(5) / 4, 15); +- level.setBlock(pos, this.getStateWithAge(level, pos, min), 3); ++ private void trySpread(Level world, BlockPos blockposition, int i, RandomSource randomsource, int j, BlockPos sourceposition) { // CraftBukkit add sourceposition ++ int k = this.getBurnOdds(world.getBlockState(blockposition)); ++ ++ if (randomsource.nextInt(i) < k) { ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ ++ // CraftBukkit start ++ org.bukkit.block.Block theBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ org.bukkit.block.Block sourceBlock = world.getWorld().getBlockAt(sourceposition.getX(), sourceposition.getY(), sourceposition.getZ()); ++ ++ BlockBurnEvent event = new BlockBurnEvent(theBlock, sourceBlock); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ if (iblockdata.getBlock() instanceof TntBlock && !CraftEventFactory.callTNTPrimeEvent(world, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.FIRE, null, sourceposition)) { ++ return; ++ } ++ // CraftBukkit end ++ ++ if (randomsource.nextInt(j + 10) < 5 && !world.isRainingAt(blockposition)) { ++ int l = Math.min(j + randomsource.nextInt(5) / 4, 15); ++ ++ world.setBlock(blockposition, this.getStateWithAge(world, blockposition, l), 3); + } else { + level.removeBlock(pos, false); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/FungusBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/FungusBlock.java.patch new file mode 100644 index 0000000000..31d4b67445 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/FungusBlock.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/level/block/FungusBlock.java ++++ b/net/minecraft/world/level/block/FungusBlock.java +@@ -72,7 +72,16 @@ + } + + @Override +- public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) { +- this.getFeature(level).ifPresent(holder -> holder.value().place(level, level.getChunkSource().getGenerator(), random, pos)); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ this.getFeature(level).ifPresent((holder) -> { ++ // CraftBukkit start ++ if (this == Blocks.WARPED_FUNGUS) { ++ SaplingBlock.treeType = org.bukkit.TreeType.WARPED_FUNGUS; ++ } else if (this == Blocks.CRIMSON_FUNGUS) { ++ SaplingBlock.treeType = org.bukkit.TreeType.CRIMSON_FUNGUS; ++ } ++ // CraftBukkit end ++ ((ConfiguredFeature) holder.value()).place(level, level.getChunkSource().getGenerator(), random, pos); ++ }); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/GrowingPlantHeadBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/GrowingPlantHeadBlock.java.patch new file mode 100644 index 0000000000..1c29745146 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/GrowingPlantHeadBlock.java.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/level/block/GrowingPlantHeadBlock.java ++++ b/net/minecraft/world/level/block/GrowingPlantHeadBlock.java +@@ -43,11 +43,12 @@ + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- if (state.getValue(AGE) < 25 && random.nextDouble() < this.growPerTickProbability) { +- BlockPos blockPos = pos.relative(this.growthDirection); +- if (this.canGrowInto(level.getBlockState(blockPos))) { +- level.setBlockAndUpdate(blockPos, this.getGrowIntoState(state, level.random)); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Integer) state.getValue(GrowingPlantHeadBlock.AGE) < 25 && random.nextDouble() < this.growPerTickProbability) { ++ BlockPos blockposition1 = pos.relative(this.growthDirection); ++ ++ if (this.canGrowInto(level.getBlockState(blockposition1))) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition1, this.getGrowIntoState(state, level.random)); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/IceBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/IceBlock.java.patch new file mode 100644 index 0000000000..4edb78a100 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/IceBlock.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/level/block/IceBlock.java ++++ b/net/minecraft/world/level/block/IceBlock.java +@@ -54,7 +58,12 @@ + } + } + +- protected void melt(BlockState state, Level level, BlockPos pos) { ++ protected void melt(IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, level.dimensionType().ultraWarm() ? Blocks.AIR.defaultBlockState() : Blocks.WATER.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + if (level.dimensionType().ultraWarm()) { + level.removeBlock(pos, false); + } else { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/InfestedBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/InfestedBlock.java.patch new file mode 100644 index 0000000000..b858fa3c4c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/InfestedBlock.java.patch @@ -0,0 +1,28 @@ +--- a/net/minecraft/world/level/block/InfestedBlock.java ++++ b/net/minecraft/world/level/block/InfestedBlock.java +@@ -18,6 +18,7 @@ + import net.minecraft.world.level.block.state.BlockBehaviour; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.block.state.properties.Property; ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; // CraftBukkit + + public class InfestedBlock extends Block { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +@@ -49,11 +50,12 @@ + } + + private void spawnInfestation(ServerLevel level, BlockPos pos) { +- Silverfish silverfish = EntityType.SILVERFISH.create(level); +- if (silverfish != null) { +- silverfish.moveTo((double)pos.getX() + 0.5, (double)pos.getY(), (double)pos.getZ() + 0.5, 0.0F, 0.0F); +- level.addFreshEntity(silverfish); +- silverfish.spawnAnim(); ++ Silverfish entitysilverfish = (Silverfish) EntityType.SILVERFISH.create(level); ++ ++ if (entitysilverfish != null) { ++ entitysilverfish.moveTo((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, 0.0F, 0.0F); ++ level.addFreshEntity(entitysilverfish, SpawnReason.SILVERFISH_BLOCK); // CraftBukkit - add SpawnReason ++ entitysilverfish.spawnAnim(); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/LayeredCauldronBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/LayeredCauldronBlock.java.patch new file mode 100644 index 0000000000..a74549e358 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/LayeredCauldronBlock.java.patch @@ -0,0 +1,99 @@ +--- a/net/minecraft/world/level/block/LayeredCauldronBlock.java ++++ b/net/minecraft/world/level/block/LayeredCauldronBlock.java +@@ -16,6 +15,11 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.block.CraftBlockStates; ++import org.bukkit.event.block.CauldronLevelChangeEvent; ++// CraftBukkit end + + public class LayeredCauldronBlock extends AbstractCauldronBlock { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +@@ -62,10 +66,12 @@ + @Override + public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { + if (!level.isClientSide && entity.isOnFire() && this.isEntityInsideContent(state, pos, entity)) { +- entity.clearFire(); ++ // CraftBukkit start + if (entity.mayInteract(level, pos)) { + this.handleEntityOnFireInside(state, level, pos); + } ++ entity.clearFire(); ++ // CraftBukkit end + } + } + +@@ -77,19 +87,43 @@ + } + } + +- public static void lowerFillLevel(BlockState state, Level level, BlockPos pos) { +- int i = state.getValue(LEVEL) - 1; +- BlockState blockState = i == 0 ? Blocks.CAULDRON.defaultBlockState() : state.setValue(LEVEL, Integer.valueOf(i)); +- level.setBlockAndUpdate(pos, blockState); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(blockState)); ++ public static void lowerFillLevel(IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ lowerFillLevel(state, level, pos, null, CauldronLevelChangeEvent.ChangeReason.UNKNOWN); + } + ++ public static boolean lowerFillLevel(IBlockData iblockdata, Level world, BlockPos blockposition, Entity entity, CauldronLevelChangeEvent.ChangeReason reason) { ++ int i = (Integer) iblockdata.getValue(LayeredCauldronBlock.LEVEL) - 1; ++ IBlockData iblockdata1 = i == 0 ? Blocks.CAULDRON.defaultBlockState() : (IBlockData) iblockdata.setValue(LayeredCauldronBlock.LEVEL, i); ++ ++ return changeLevel(iblockdata, world, blockposition, iblockdata1, entity, reason); ++ } ++ ++ // CraftBukkit start ++ public static boolean changeLevel(IBlockData iblockdata, Level world, BlockPos blockposition, IBlockData newBlock, Entity entity, CauldronLevelChangeEvent.ChangeReason reason) { ++ CraftBlockState newState = CraftBlockStates.getBlockState(world, blockposition); ++ newState.setData(newBlock); ++ ++ CauldronLevelChangeEvent event = new CauldronLevelChangeEvent( ++ world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), ++ (entity == null) ? null : entity.getBukkitEntity(), reason, newState ++ ); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ newState.update(true); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(newBlock)); ++ return true; ++ } ++ // CraftBukkit end ++ + @Override +- public void handlePrecipitation(BlockState state, Level level, BlockPos pos, Biome.Precipitation precipitation) { +- if (CauldronBlock.shouldHandlePrecipitation(level, precipitation) && state.getValue(LEVEL) != 3 && precipitation == this.precipitationType) { +- BlockState blockState = state.cycle(LEVEL); +- level.setBlockAndUpdate(pos, blockState); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(blockState)); ++ public void handlePrecipitation(IBlockData state, Level level, BlockPos pos, Biome.Precipitation precipitation) { ++ if (CauldronBlock.shouldHandlePrecipitation(level, precipitation) && (Integer) state.getValue(LayeredCauldronBlock.LEVEL) != 3 && precipitation == this.precipitationType) { ++ IBlockData iblockdata1 = (IBlockData) state.cycle(LayeredCauldronBlock.LEVEL); ++ ++ changeLevel(state, level, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL); // CraftBukkit + } + } + +@@ -106,9 +140,13 @@ + @Override + protected void receiveStalactiteDrip(BlockState state, Level level, BlockPos pos, Fluid fluid) { + if (!this.isFull(state)) { +- BlockState blockState = state.setValue(LEVEL, Integer.valueOf(state.getValue(LEVEL) + 1)); +- level.setBlockAndUpdate(pos, blockState); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(blockState)); ++ IBlockData iblockdata1 = (IBlockData) state.setValue(LayeredCauldronBlock.LEVEL, (Integer) state.getValue(LayeredCauldronBlock.LEVEL) + 1); ++ ++ // CraftBukkit start ++ if (!changeLevel(state, level, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL)) { ++ return; ++ } ++ // CraftBukkit end + level.levelEvent(1047, pos, 0); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/LeavesBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/LeavesBlock.java.patch new file mode 100644 index 0000000000..993ad9adb7 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/LeavesBlock.java.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/world/level/block/LeavesBlock.java ++++ b/net/minecraft/world/level/block/LeavesBlock.java +@@ -23,6 +24,7 @@ + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.LeavesDecayEvent; // CraftBukkit + + public class LeavesBlock extends Block implements SimpleWaterloggedBlock { + public static final MapCodec CODEC = simpleCodec(LeavesBlock::new); +@@ -61,6 +58,14 @@ + @Override + public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { + if (this.decaying(state)) { ++ // CraftBukkit start ++ LeavesDecayEvent event = new LeavesDecayEvent(level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled() || level.getBlockState(pos).getBlock() != this) { ++ return; ++ } ++ // CraftBukkit end + dropResources(state, level, pos); + level.removeBlock(pos, false); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/LecternBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/LecternBlock.java.patch new file mode 100644 index 0000000000..db1ae8d6c9 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/LecternBlock.java.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/world/level/block/LecternBlock.java ++++ b/net/minecraft/world/level/block/LecternBlock.java +@@ -219,18 +206,21 @@ + } + } + +- private void popBook(BlockState state, Level level, BlockPos pos) { +- if (level.getBlockEntity(pos) instanceof LecternBlockEntity lecternBlockEntity) { +- Direction direction = state.getValue(FACING); +- ItemStack itemStack = lecternBlockEntity.getBook().copy(); +- float f = 0.25F * (float)direction.getStepX(); +- float f1 = 0.25F * (float)direction.getStepZ(); +- ItemEntity itemEntity = new ItemEntity( +- level, (double)pos.getX() + 0.5 + (double)f, (double)(pos.getY() + 1), (double)pos.getZ() + 0.5 + (double)f1, itemStack +- ); +- itemEntity.setDefaultPickUpDelay(); +- level.addFreshEntity(itemEntity); +- lecternBlockEntity.clearContent(); ++ private void popBook(IBlockData state, Level level, BlockPos pos) { ++ BlockEntity tileentity = level.getBlockEntity(pos, false); // CraftBukkit - don't validate, type may be changed already ++ ++ if (tileentity instanceof LecternBlockEntity) { ++ LecternBlockEntity tileentitylectern = (LecternBlockEntity) tileentity; ++ Direction enumdirection = (Direction) state.getValue(LecternBlock.FACING); ++ ItemStack itemstack = tileentitylectern.getBook().copy(); ++ if (itemstack.isEmpty()) return; // CraftBukkit - SPIGOT-5500 ++ float f = 0.25F * (float) enumdirection.getStepX(); ++ float f1 = 0.25F * (float) enumdirection.getStepZ(); ++ ItemEntity entityitem = new ItemEntity(level, (double) pos.getX() + 0.5D + (double) f, (double) (pos.getY() + 1), (double) pos.getZ() + 0.5D + (double) f1, itemstack); ++ ++ entityitem.setDefaultPickUpDelay(); ++ level.addFreshEntity(entityitem); ++ tileentitylectern.clearContent(); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/LeverBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/LeverBlock.java.patch new file mode 100644 index 0000000000..c922efe239 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/LeverBlock.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/level/block/LeverBlock.java ++++ b/net/minecraft/world/level/block/LeverBlock.java +@@ -26,6 +27,7 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class LeverBlock extends FaceAttachedHorizontalDirectionalBlock { + public static final MapCodec CODEC = simpleCodec(LeverBlock::new); +@@ -99,10 +102,25 @@ + + return InteractionResult.SUCCESS; + } else { +- BlockState blockState = this.pull(state, level, pos); +- float f = blockState.getValue(POWERED) ? 0.6F : 0.5F; +- level.playSound(null, pos, SoundEvents.LEVER_CLICK, SoundSource.BLOCKS, 0.3F, f); +- level.gameEvent(player, blockState.getValue(POWERED) ? GameEvent.BLOCK_ACTIVATE : GameEvent.BLOCK_DEACTIVATE, pos); ++ // CraftBukkit start - Interact Lever ++ boolean powered = state.getValue(LeverBlock.POWERED); // Old powered state ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ int old = (powered) ? 15 : 0; ++ int current = (!powered) ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if ((eventRedstone.getNewCurrent() > 0) != (!powered)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ ++ iblockdata1 = this.pull(state, level, pos); ++ float f = (Boolean) iblockdata1.getValue(LeverBlock.POWERED) ? 0.6F : 0.5F; ++ ++ level.playSound((Player) null, pos, SoundEvents.LEVER_CLICK, SoundSource.BLOCKS, 0.3F, f); ++ level.gameEvent((Entity) player, (Boolean) iblockdata1.getValue(LeverBlock.POWERED) ? GameEvent.BLOCK_ACTIVATE : GameEvent.BLOCK_DEACTIVATE, pos); + return InteractionResult.CONSUME; + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/LightningRodBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/LightningRodBlock.java.patch new file mode 100644 index 0000000000..109f8d0bd8 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/LightningRodBlock.java.patch @@ -0,0 +1,66 @@ +--- a/net/minecraft/world/level/block/LightningRodBlock.java ++++ b/net/minecraft/world/level/block/LightningRodBlock.java +@@ -30,6 +32,10 @@ + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockRedstoneEvent; ++// CraftBukkit end + + public class LightningRodBlock extends RodBlock implements SimpleWaterloggedBlock { + public static final MapCodec CODEC = simpleCodec(LightningRodBlock::new); +@@ -82,8 +88,20 @@ + return state.getValue(POWERED) && state.getValue(FACING) == direction ? 15 : 0; + } + +- public void onLightningStrike(BlockState state, Level level, BlockPos pos) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(true)), 3); ++ public void onLightningStrike(IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ boolean powered = state.getValue(LightningRodBlock.POWERED); ++ int old = (powered) ? 15 : 0; ++ int current = (!powered) ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(level, pos), old, current); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if (eventRedstone.getNewCurrent() <= 0) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(LightningRodBlock.POWERED, true), 3); + this.updateNeighbours(state, level, pos); + level.scheduleTick(pos, this, 8); + level.levelEvent(3002, pos, state.getValue(FACING).getAxis().ordinal()); +@@ -129,16 +146,19 @@ + } + + @Override +- public void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) { +- if (level.isThundering() && projectile instanceof ThrownTrident && ((ThrownTrident)projectile).isChanneling()) { +- BlockPos blockPos = hit.getBlockPos(); +- if (level.canSeeSky(blockPos)) { +- LightningBolt lightningBolt = EntityType.LIGHTNING_BOLT.create(level); +- if (lightningBolt != null) { +- lightningBolt.moveTo(Vec3.atBottomCenterOf(blockPos.above())); +- Entity owner = projectile.getOwner(); +- lightningBolt.setCause(owner instanceof ServerPlayer ? (ServerPlayer)owner : null); +- level.addFreshEntity(lightningBolt); ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { ++ if (level.isThundering() && projectile instanceof ThrownTrident && ((ThrownTrident) projectile).isChanneling()) { ++ BlockPos blockposition = hit.getBlockPos(); ++ ++ if (level.canSeeSky(blockposition)) { ++ LightningBolt entitylightning = (LightningBolt) EntityType.LIGHTNING_BOLT.create(level); ++ ++ if (entitylightning != null) { ++ entitylightning.moveTo(Vec3.atBottomCenterOf(blockposition.above())); ++ Entity entity = projectile.getOwner(); ++ ++ entitylightning.setCause(entity instanceof ServerPlayer ? (ServerPlayer) entity : null); ++ ((ServerLevel) level).strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.TRIDENT); // CraftBukkit + } + + level.playSound(null, blockPos, SoundEvents.TRIDENT_THUNDER, SoundSource.WEATHER, 5.0F, 1.0F); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/LiquidBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/LiquidBlock.java.patch new file mode 100644 index 0000000000..9deb7262c9 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/LiquidBlock.java.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/world/level/block/LiquidBlock.java ++++ b/net/minecraft/world/level/block/LiquidBlock.java +@@ -161,14 +173,21 @@ + BlockPos blockPos = pos.relative(direction.getOpposite()); + if (level.getFluidState(blockPos).is(FluidTags.WATER)) { + Block block = level.getFluidState(pos).isSource() ? Blocks.OBSIDIAN : Blocks.COBBLESTONE; +- level.setBlockAndUpdate(pos, block.defaultBlockState()); +- this.fizz(level, pos); ++ ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, block.defaultBlockState())) { ++ this.fizz(level, pos); ++ } ++ // CraftBukkit end + return false; + } + +- if (isSoulSoil && level.getBlockState(blockPos).is(Blocks.BLUE_ICE)) { +- level.setBlockAndUpdate(pos, Blocks.BASALT.defaultBlockState()); +- this.fizz(level, pos); ++ if (flag && level.getBlockState(blockposition1).is(Blocks.BLUE_ICE)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, Blocks.BASALT.defaultBlockState())) { ++ this.fizz(level, pos); ++ } ++ // CraftBukkit end + return false; + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/MagmaBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/MagmaBlock.java.patch new file mode 100644 index 0000000000..24fc3f4695 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/MagmaBlock.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/level/block/MagmaBlock.java ++++ b/net/minecraft/world/level/block/MagmaBlock.java +@@ -27,9 +28,11 @@ + } + + @Override +- public void stepOn(Level level, BlockPos pos, BlockState state, Entity entity) { +- if (!entity.isSteppingCarefully() && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity)entity)) { ++ public void stepOn(Level level, BlockPos pos, IBlockData state, Entity entity) { ++ if (!entity.isSteppingCarefully() && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity) entity)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); // CraftBukkit + entity.hurt(level.damageSources().hotFloor(), 1.0F); ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = null; // CraftBukkit + } + + super.stepOn(level, pos, state, entity); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/MultifaceSpreader.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/MultifaceSpreader.java.patch new file mode 100644 index 0000000000..a2aa4aa01e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/MultifaceSpreader.java.patch @@ -0,0 +1,45 @@ +--- a/net/minecraft/world/level/block/MultifaceSpreader.java ++++ b/net/minecraft/world/level/block/MultifaceSpreader.java +@@ -154,7 +156,7 @@ + level.getChunk(pos.pos()).markPosForPostprocessing(pos.pos()); + } + +- return level.setBlock(pos.pos(), stateForPlacement, 2); ++ return org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos.source(), pos.pos(), iblockdata1, 2); // CraftBukkit + } else { + return false; + } +@@ -172,23 +173,27 @@ + public static enum SpreadType { + SAME_POSITION { + @Override +- public MultifaceSpreader.SpreadPos getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection) { +- return new MultifaceSpreader.SpreadPos(pos, face); ++ public MultifaceSpreader.c getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection) { ++ return new MultifaceSpreader.c(pos, face, pos); // CraftBukkit + } + }, + SAME_PLANE { + @Override +- public MultifaceSpreader.SpreadPos getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection) { +- return new MultifaceSpreader.SpreadPos(pos.relative(face), spreadDirection); ++ public MultifaceSpreader.c getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection) { ++ return new MultifaceSpreader.c(pos.relative(face), spreadDirection, pos); // CraftBukkit + } + }, + WRAP_AROUND { + @Override +- public MultifaceSpreader.SpreadPos getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection) { +- return new MultifaceSpreader.SpreadPos(pos.relative(face).relative(spreadDirection), face.getOpposite()); ++ public MultifaceSpreader.c getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection) { ++ return new MultifaceSpreader.c(pos.relative(face).relative(spreadDirection), face.getOpposite(), pos); // CraftBukkit + } + }; + + public abstract MultifaceSpreader.SpreadPos getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection); + } ++ ++ public static record c(BlockPos pos, Direction face, BlockPos source) { // CraftBukkit ++ ++ } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/MushroomBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/MushroomBlock.java.patch new file mode 100644 index 0000000000..3bc07bbf21 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/MushroomBlock.java.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/world/level/block/MushroomBlock.java ++++ b/net/minecraft/world/level/block/MushroomBlock.java +@@ -19,6 +19,9 @@ + import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.TreeType; ++// CraftBukkit end + + public class MushroomBlock extends BushBlock implements BonemealableBlock { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +@@ -70,8 +77,8 @@ + blockPos1 = pos.offset(random.nextInt(3) - 1, random.nextInt(2) - random.nextInt(2), random.nextInt(3) - 1); + } + +- if (level.isEmptyBlock(blockPos1) && state.canSurvive(level, blockPos1)) { +- level.setBlock(blockPos1, state, 2); ++ if (level.isEmptyBlock(blockposition2) && state.canSurvive(level, blockposition2)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition2, state, 2); // CraftBukkit + } + } + } +@@ -96,7 +104,8 @@ + return false; + } else { + level.removeBlock(pos, false); +- if (holder.get().value().place(level, level.getChunkSource().getGenerator(), random, pos)) { ++ SaplingBlock.treeType = (this == Blocks.BROWN_MUSHROOM) ? TreeType.BROWN_MUSHROOM : TreeType.BROWN_MUSHROOM; // CraftBukkit ++ if (((ConfiguredFeature) ((Holder) optional.get()).value()).place(level, level.getChunkSource().getGenerator(), random, pos)) { + return true; + } else { + level.setBlock(pos, state, 3); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/NetherPortalBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/NetherPortalBlock.java.patch new file mode 100644 index 0000000000..9cddb7990f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/NetherPortalBlock.java.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/level/block/NetherPortalBlock.java ++++ b/net/minecraft/world/level/block/NetherPortalBlock.java +@@ -25,6 +25,9 @@ + import net.minecraft.world.level.portal.PortalShape; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.event.entity.EntityPortalEnterEvent; ++// CraftBukkit end + + public class NetherPortalBlock extends Block { + public static final MapCodec CODEC = simpleCodec(NetherPortalBlock::new); +@@ -64,7 +66,9 @@ + } + + if (level.getBlockState(pos).isValidSpawn(level, pos, EntityType.ZOMBIFIED_PIGLIN)) { +- Entity entity = EntityType.ZOMBIFIED_PIGLIN.spawn(level, pos.above(), MobSpawnType.STRUCTURE); ++ // CraftBukkit - set spawn reason to NETHER_PORTAL ++ Entity entity = EntityType.ZOMBIFIED_PIGLIN.spawn(level, pos.above(), EnumMobSpawn.STRUCTURE, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NETHER_PORTAL); ++ + if (entity != null) { + entity.setPortalCooldown(); + } +@@ -85,6 +89,10 @@ + @Override + public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { + if (entity.canChangeDimensions()) { ++ // CraftBukkit start - Entity in portal ++ EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(level.getWorld(), pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ // CraftBukkit end + entity.handleInsidePortal(pos); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/NetherWartBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/NetherWartBlock.java.patch new file mode 100644 index 0000000000..bd1f6de6ec --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/NetherWartBlock.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/level/block/NetherWartBlock.java ++++ b/net/minecraft/world/level/block/NetherWartBlock.java +@@ -56,8 +53,8 @@ + public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { + int i = state.getValue(AGE); + if (i < 3 && random.nextInt(10) == 0) { +- state = state.setValue(AGE, Integer.valueOf(i + 1)); +- level.setBlock(pos, state, 2); ++ state = (IBlockData) state.setValue(NetherWartBlock.AGE, i + 1); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, state, 2); // CraftBukkit + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/NoteBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/NoteBlock.java.patch new file mode 100644 index 0000000000..9694e75e40 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/NoteBlock.java.patch @@ -0,0 +1,37 @@ +--- a/net/minecraft/world/level/block/NoteBlock.java ++++ b/net/minecraft/world/level/block/NoteBlock.java +@@ -77,19 +76,27 @@ + } + + @Override +- public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { +- boolean hasNeighborSignal = level.hasNeighborSignal(pos); +- if (hasNeighborSignal != state.getValue(POWERED)) { +- if (hasNeighborSignal) { +- this.playNote(null, state, level, pos); ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ boolean flag1 = level.hasNeighborSignal(pos); ++ ++ if (flag1 != (Boolean) state.getValue(NoteBlock.POWERED)) { ++ if (flag1) { ++ this.playNote((Entity) null, state, level, pos); ++ state = level.getBlockState(pos); // CraftBukkit - SPIGOT-5617: update in case changed in event + } + + level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(hasNeighborSignal)), 3); + } + } + +- private void playNote(@Nullable Entity entity, BlockState state, Level level, BlockPos pos) { +- if (state.getValue(INSTRUMENT).worksAboveNoteBlock() || level.getBlockState(pos.above()).isAir()) { ++ private void playNote(@Nullable Entity entity, IBlockData state, Level level, BlockPos pos) { ++ if (((NoteBlockInstrument) state.getValue(NoteBlock.INSTRUMENT)).worksAboveNoteBlock() || level.getBlockState(pos.above()).isAir()) { ++ // CraftBukkit start ++ org.bukkit.event.block.NotePlayEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callNotePlayEvent(level, pos, state.getValue(NoteBlock.INSTRUMENT), state.getValue(NoteBlock.NOTE)); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + level.blockEvent(pos, this, 0, 0); + level.gameEvent(entity, GameEvent.NOTE_BLOCK_PLAY, pos); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/NyliumBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/NyliumBlock.java.patch new file mode 100644 index 0000000000..0c4d9bac2e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/NyliumBlock.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/block/NyliumBlock.java ++++ b/net/minecraft/world/level/block/NyliumBlock.java +@@ -40,6 +41,11 @@ + @Override + public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { + if (!canBeNylium(state, level, pos)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.NETHERRACK.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + level.setBlockAndUpdate(pos, Blocks.NETHERRACK.defaultBlockState()); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ObserverBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ObserverBlock.java.patch new file mode 100644 index 0000000000..8d0c96f787 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ObserverBlock.java.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/world/level/block/ObserverBlock.java ++++ b/net/minecraft/world/level/block/ObserverBlock.java +@@ -14,6 +14,7 @@ + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class ObserverBlock extends DirectionalBlock { + public static final MapCodec CODEC = simpleCodec(ObserverBlock::new); +@@ -45,12 +47,22 @@ + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- if (state.getValue(POWERED)) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(false)), 2); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(ObserverBlock.POWERED)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 15, 0).getNewCurrent() != 0) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(ObserverBlock.POWERED, false), 2); + } else { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(true)), 2); +- level.scheduleTick(pos, this, 2); ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 0, 15).getNewCurrent() != 15) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(ObserverBlock.POWERED, true), 2); ++ level.scheduleTick(pos, (Block) this, 2); + } + + this.updateNeighborsInFront(level, pos, state); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/PointedDripstoneBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/PointedDripstoneBlock.java.patch new file mode 100644 index 0000000000..419d583826 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/PointedDripstoneBlock.java.patch @@ -0,0 +1,92 @@ +--- a/net/minecraft/world/level/block/PointedDripstoneBlock.java ++++ b/net/minecraft/world/level/block/PointedDripstoneBlock.java +@@ -42,6 +42,10 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class PointedDripstoneBlock extends Block implements Fallable, SimpleWaterloggedBlock { + public static final MapCodec CODEC = simpleCodec(PointedDripstoneBlock::new); +@@ -132,20 +133,25 @@ + @Override + public void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) { + if (!level.isClientSide) { +- BlockPos blockPos = hit.getBlockPos(); +- if (projectile.mayInteract(level, blockPos) +- && projectile.mayBreak(level) +- && projectile instanceof ThrownTrident +- && projectile.getDeltaMovement().length() > 0.6) { +- level.destroyBlock(blockPos, true); ++ BlockPos blockposition = hit.getBlockPos(); ++ ++ if (projectile.mayInteract(level, blockposition) && projectile.mayBreak(level) && projectile instanceof ThrownTrident && projectile.getDeltaMovement().length() > 0.6D) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, Blocks.AIR.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end ++ level.destroyBlock(blockposition, true); + } + } + } + + @Override +- public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, float fallDistance) { +- if (state.getValue(TIP_DIRECTION) == Direction.UP && state.getValue(THICKNESS) == DripstoneThickness.TIP) { ++ public void fallOn(Level level, IBlockData state, BlockPos pos, Entity entity, float fallDistance) { ++ if (state.getValue(PointedDripstoneBlock.TIP_DIRECTION) == Direction.UP && state.getValue(PointedDripstoneBlock.THICKNESS) == DripstoneThickness.TIP) { ++ CraftEventFactory.blockDamage = CraftBlock.at(level, pos); // CraftBukkit + entity.causeFallDamage(fallDistance + 2.0F, 2.0F, level.damageSources().stalagmite()); ++ CraftEventFactory.blockDamage = null; // CraftBukkit + } else { + super.fallOn(level, state, pos, entity, fallDistance); + } +@@ -365,22 +391,20 @@ + } + + private static void grow(ServerLevel server, BlockPos pos, Direction direction) { +- BlockPos blockPos = pos.relative(direction); +- BlockState blockState = server.getBlockState(blockPos); +- if (isUnmergedTipWithDirection(blockState, direction.getOpposite())) { +- createMergedTips(blockState, server, blockPos); +- } else if (blockState.isAir() || blockState.is(Blocks.WATER)) { +- createDripstone(server, blockPos, direction, DripstoneThickness.TIP); ++ BlockPos blockposition1 = pos.relative(direction); ++ IBlockData iblockdata = server.getBlockState(blockposition1); ++ ++ if (isUnmergedTipWithDirection(iblockdata, direction.getOpposite())) { ++ createMergedTips(iblockdata, server, blockposition1); ++ } else if (iblockdata.isAir() || iblockdata.is(Blocks.WATER)) { ++ createDripstone(server, blockposition1, direction, DripstoneThickness.TIP, pos); // CraftBukkit + } + } + +- private static void createDripstone(LevelAccessor level, BlockPos pos, Direction direction, DripstoneThickness thickness) { +- BlockState blockState = Blocks.POINTED_DRIPSTONE +- .defaultBlockState() +- .setValue(TIP_DIRECTION, direction) +- .setValue(THICKNESS, thickness) +- .setValue(WATERLOGGED, Boolean.valueOf(level.getFluidState(pos).getType() == Fluids.WATER)); +- level.setBlock(pos, blockState, 3); ++ private static void createDripstone(LevelAccessor generatoraccess, BlockPos blockposition, Direction enumdirection, DripstoneThickness dripstonethickness, BlockPos source) { // CraftBukkit ++ IBlockData iblockdata = (IBlockData) ((IBlockData) ((IBlockData) Blocks.POINTED_DRIPSTONE.defaultBlockState().setValue(PointedDripstoneBlock.TIP_DIRECTION, enumdirection)).setValue(PointedDripstoneBlock.THICKNESS, dripstonethickness)).setValue(PointedDripstoneBlock.WATERLOGGED, generatoraccess.getFluidState(blockposition).getType() == Fluids.WATER); ++ ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(generatoraccess, source, blockposition, iblockdata, 3); // CraftBukkit + } + + private static void createMergedTips(BlockState state, LevelAccessor level, BlockPos pos) { +@@ -394,8 +420,8 @@ + blockPos = pos.below(); + } + +- createDripstone(level, blockPos1, Direction.DOWN, DripstoneThickness.TIP_MERGE); +- createDripstone(level, blockPos, Direction.UP, DripstoneThickness.TIP_MERGE); ++ createDripstone(level, blockposition2, Direction.DOWN, DripstoneThickness.TIP_MERGE, pos); // CraftBukkit ++ createDripstone(level, blockposition1, Direction.UP, DripstoneThickness.TIP_MERGE, pos); // CraftBukkit + } + + public static void spawnDripParticle(Level level, BlockPos pos, BlockState state) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/PowderSnowBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/PowderSnowBlock.java.patch new file mode 100644 index 0000000000..389faf8561 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/PowderSnowBlock.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/level/block/PowderSnowBlock.java ++++ b/net/minecraft/world/level/block/PowderSnowBlock.java +@@ -83,9 +77,12 @@ + + entity.setIsInPowderSnow(true); + if (!level.isClientSide) { +- if (entity.isOnFire() +- && (level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity instanceof Player) +- && entity.mayInteract(level, pos)) { ++ // CraftBukkit start ++ if (entity.isOnFire() && entity.mayInteract(level, pos)) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !(level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity instanceof Player))) { ++ return; ++ } ++ // CraftBukkit end + level.destroyBlock(pos, false); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/PoweredRailBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/PoweredRailBlock.java.patch new file mode 100644 index 0000000000..05f9229490 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/PoweredRailBlock.java.patch @@ -0,0 +1,26 @@ +--- a/net/minecraft/world/level/block/PoweredRailBlock.java ++++ b/net/minecraft/world/level/block/PoweredRailBlock.java +@@ -11,6 +11,7 @@ + import net.minecraft.world.level.block.state.properties.EnumProperty; + import net.minecraft.world.level.block.state.properties.Property; + import net.minecraft.world.level.block.state.properties.RailShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class PoweredRailBlock extends BaseRailBlock { + public static final MapCodec CODEC = simpleCodec(PoweredRailBlock::new); +@@ -133,7 +121,14 @@ + || this.findPoweredRailSignal(level, pos, state, true, 0) + || this.findPoweredRailSignal(level, pos, state, false, 0); + if (flag1 != flag) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(flag1)), 3); ++ // CraftBukkit start ++ int power = flag ? 15 : 0; ++ int newPower = CraftEventFactory.callRedstoneChange(level, pos, power, 15 - power).getNewCurrent(); ++ if (newPower == power) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(PoweredRailBlock.POWERED, flag1), 3); + level.updateNeighborsAt(pos.below(), this); + if (state.getValue(SHAPE).isAscending()) { + level.updateNeighborsAt(pos.above(), this); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/PressurePlateBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/PressurePlateBlock.java.patch new file mode 100644 index 0000000000..776a9aaf3d --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/PressurePlateBlock.java.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/world/level/block/PressurePlateBlock.java ++++ b/net/minecraft/world/level/block/PressurePlateBlock.java +@@ -13,6 +13,8 @@ + import net.minecraft.world.level.block.state.properties.BlockSetType; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end + + public class PressurePlateBlock extends BasePressurePlateBlock { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +@@ -43,11 +47,46 @@ + + @Override + protected int getSignalStrength(Level level, BlockPos pos) { +- Class clazz = switch (this.type.pressurePlateSensitivity()) { +- case EVERYTHING -> Entity.class; +- case MOBS -> LivingEntity.class; +- }; +- return getEntityCount(level, TOUCH_AABB.move(pos), clazz) > 0 ? 15 : 0; ++ Class oclass; // CraftBukkit ++ ++ switch (this.type.pressurePlateSensitivity()) { ++ case EVERYTHING: ++ oclass = Entity.class; ++ break; ++ case MOBS: ++ oclass = LivingEntity.class; ++ break; ++ default: ++ throw new IncompatibleClassChangeError(); ++ } ++ ++ Class oclass1 = oclass; ++ ++ // CraftBukkit start - Call interact event when turning on a pressure plate ++ for (Entity entity : getEntities(level, PressurePlateBlock.TOUCH_AABB.move(pos), oclass)) { ++ if (this.getSignalForState(level.getBlockState(pos)) == 0) { ++ org.bukkit.World bworld = level.getWorld(); ++ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager(); ++ org.bukkit.event.Cancellable cancellable; ++ ++ if (entity instanceof Player) { ++ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ manager.callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ // We only want to block turning the plate on if all events are cancelled ++ if (cancellable.isCancelled()) { ++ continue; ++ } ++ } ++ ++ return 15; ++ } ++ ++ return 0; ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/RedStoneOreBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/RedStoneOreBlock.java.patch new file mode 100644 index 0000000000..3797f5f059 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/RedStoneOreBlock.java.patch @@ -0,0 +1,115 @@ +--- a/net/minecraft/world/level/block/RedStoneOreBlock.java ++++ b/net/minecraft/world/level/block/RedStoneOreBlock.java +@@ -21,6 +21,10 @@ + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.phys.BlockHitResult; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end + + public class RedStoneOreBlock extends Block { + public static final MapCodec CODEC = simpleCodec(RedStoneOreBlock::new); +@@ -37,15 +42,28 @@ + } + + @Override +- public void attack(BlockState state, Level level, BlockPos pos, Player player) { +- interact(state, level, pos); ++ public void attack(IBlockData state, Level level, BlockPos pos, Player player) { ++ interact(state, level, pos, player); // CraftBukkit - add entityhuman + super.attack(state, level, pos, player); + } + + @Override + public void stepOn(Level level, BlockPos pos, BlockState state, Entity entity) { + if (!entity.isSteppingCarefully()) { +- interact(state, level, pos); ++ // CraftBukkit start ++ if (entity instanceof Player) { ++ org.bukkit.event.player.PlayerInteractEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ if (!event.isCancelled()) { ++ interact(level.getBlockState(pos), level, pos, entity); // add entity ++ } ++ } else { ++ EntityInteractEvent event = new EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ interact(level.getBlockState(pos), level, pos, entity); // add entity ++ } ++ } ++ // CraftBukkit end + } + + super.stepOn(level, pos, state, entity); +@@ -56,7 +74,7 @@ + if (level.isClientSide) { + spawnParticles(level, pos); + } else { +- interact(state, level, pos); ++ interact(state, level, pos, player); // CraftBukkit - add entityhuman + } + + ItemStack itemInHand = player.getItemInHand(hand); +@@ -65,10 +82,15 @@ + : InteractionResult.SUCCESS; + } + +- private static void interact(BlockState state, Level level, BlockPos pos) { +- spawnParticles(level, pos); +- if (!state.getValue(LIT)) { +- level.setBlock(pos, state.setValue(LIT, Boolean.valueOf(true)), 3); ++ private static void interact(IBlockData iblockdata, Level world, BlockPos blockposition, Entity entity) { // CraftBukkit - add Entity ++ spawnParticles(world, blockposition); ++ if (!(Boolean) iblockdata.getValue(RedStoneOreBlock.LIT)) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, iblockdata.setValue(RedStoneOreBlock.LIT, true))) { ++ return; ++ } ++ // CraftBukkit end ++ world.setBlock(blockposition, (IBlockData) iblockdata.setValue(RedStoneOreBlock.LIT, true), 3); + } + } + +@@ -78,19 +101,34 @@ + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- if (state.getValue(LIT)) { +- level.setBlock(pos, state.setValue(LIT, Boolean.valueOf(false)), 3); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(RedStoneOreBlock.LIT)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callBlockFadeEvent(level, pos, state.setValue(RedStoneOreBlock.LIT, false)).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(RedStoneOreBlock.LIT, false), 3); + } + } + + @Override + public void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { + super.spawnAfterBreak(state, level, pos, stack, dropExperience); +- if (dropExperience && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack) == 0) { +- int i = 1 + level.random.nextInt(5); +- this.popExperience(level, pos, i); ++ // CraftBukkit start - Delegated to getExpDrop ++ } ++ ++ @Override ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { ++ if (flag && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, itemstack) == 0) { ++ int i = 1 + worldserver.random.nextInt(5); ++ ++ // this.popExperience(worldserver, blockposition, i); ++ return i; + } ++ ++ return 0; ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/RedStoneWireBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/RedStoneWireBlock.java.patch new file mode 100644 index 0000000000..6d81ae2cf8 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/RedStoneWireBlock.java.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/world/level/block/RedStoneWireBlock.java ++++ b/net/minecraft/world/level/block/RedStoneWireBlock.java +@@ -33,6 +36,7 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class RedStoneWireBlock extends Block { + public static final MapCodec CODEC = simpleCodec(RedStoneWireBlock::new); +@@ -278,7 +261,17 @@ + + private void updatePowerStrength(Level level, BlockPos pos, BlockState state) { + int i = this.calculateTargetStrength(level, pos); +- if (state.getValue(POWER) != i) { ++ ++ // CraftBukkit start ++ int oldPower = (Integer) state.getValue(RedStoneWireBlock.POWER); ++ if (oldPower != i) { ++ BlockRedstoneEvent event = new BlockRedstoneEvent(level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()), oldPower, i); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ i = event.getNewCurrent(); ++ } ++ if (oldPower != i) { ++ // CraftBukkit end + if (level.getBlockState(pos) == state) { + level.setBlock(pos, state.setValue(POWER, Integer.valueOf(i)), 2); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/RedstoneLampBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/RedstoneLampBlock.java.patch new file mode 100644 index 0000000000..78a6f44e9c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/RedstoneLampBlock.java.patch @@ -0,0 +1,41 @@ +--- a/net/minecraft/world/level/block/RedstoneLampBlock.java ++++ b/net/minecraft/world/level/block/RedstoneLampBlock.java +@@ -11,6 +11,7 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BooleanProperty; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class RedstoneLampBlock extends Block { + public static final MapCodec CODEC = simpleCodec(RedstoneLampBlock::new); +@@ -40,16 +43,26 @@ + if (flag) { + level.scheduleTick(pos, this, 4); + } else { +- level.setBlock(pos, state.cycle(LIT), 2); ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 0, 15).getNewCurrent() != 15) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.cycle(RedstoneLampBlock.LIT), 2); + } + } + } + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- if (state.getValue(LIT) && !level.hasNeighborSignal(pos)) { +- level.setBlock(pos, state.cycle(LIT), 2); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(RedstoneLampBlock.LIT) && !level.hasNeighborSignal(pos)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 15, 0).getNewCurrent() != 0) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.cycle(RedstoneLampBlock.LIT), 2); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/RedstoneTorchBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/RedstoneTorchBlock.java.patch new file mode 100644 index 0000000000..1d61d6b50a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/RedstoneTorchBlock.java.patch @@ -0,0 +1,57 @@ +--- a/net/minecraft/world/level/block/RedstoneTorchBlock.java ++++ b/net/minecraft/world/level/block/RedstoneTorchBlock.java +@@ -17,6 +18,7 @@ + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class RedstoneTorchBlock extends BaseTorchBlock { + public static final MapCodec CODEC = simpleCodec(RedstoneTorchBlock::new); +@@ -71,16 +86,41 @@ + list.remove(0); + } + +- if (state.getValue(LIT)) { +- if (hasNeighborSignal) { +- level.setBlock(pos, state.setValue(LIT, Boolean.valueOf(false)), 3); ++ // CraftBukkit start ++ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager(); ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ int oldCurrent = ((Boolean) state.getValue(RedstoneTorchBlock.LIT)).booleanValue() ? 15 : 0; ++ ++ BlockRedstoneEvent event = new BlockRedstoneEvent(block, oldCurrent, oldCurrent); ++ // CraftBukkit end ++ if ((Boolean) state.getValue(RedstoneTorchBlock.LIT)) { ++ if (flag) { ++ // CraftBukkit start ++ if (oldCurrent != 0) { ++ event.setNewCurrent(0); ++ manager.callEvent(event); ++ if (event.getNewCurrent() != 0) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(RedstoneTorchBlock.LIT, false), 3); + if (isToggledTooFrequently(level, pos, true)) { + level.levelEvent(1502, pos, 0); + level.scheduleTick(pos, level.getBlockState(pos).getBlock(), 160); + } + } +- } else if (!hasNeighborSignal && !isToggledTooFrequently(level, pos, false)) { +- level.setBlock(pos, state.setValue(LIT, Boolean.valueOf(true)), 3); ++ } else if (!flag && !isToggledTooFrequently(level, pos, false)) { ++ // CraftBukkit start ++ if (oldCurrent != 15) { ++ event.setNewCurrent(15); ++ manager.callEvent(event); ++ if (event.getNewCurrent() != 15) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(RedstoneTorchBlock.LIT, true), 3); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/RespawnAnchorBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/RespawnAnchorBlock.java.patch new file mode 100644 index 0000000000..b603a260a7 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/RespawnAnchorBlock.java.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/world/level/block/RespawnAnchorBlock.java ++++ b/net/minecraft/world/level/block/RespawnAnchorBlock.java +@@ -93,19 +84,11 @@ + return InteractionResult.sidedSuccess(level.isClientSide); + } else { + if (!level.isClientSide) { +- ServerPlayer serverPlayer = (ServerPlayer)player; +- if (serverPlayer.getRespawnDimension() != level.dimension() || !pos.equals(serverPlayer.getRespawnPosition())) { +- serverPlayer.setRespawnPosition(level.dimension(), pos, 0.0F, false, true); +- level.playSound( +- null, +- (double)pos.getX() + 0.5, +- (double)pos.getY() + 0.5, +- (double)pos.getZ() + 0.5, +- SoundEvents.RESPAWN_ANCHOR_SET_SPAWN, +- SoundSource.BLOCKS, +- 1.0F, +- 1.0F +- ); ++ ServerPlayer entityplayer = (ServerPlayer) player; ++ ++ if (entityplayer.getRespawnDimension() != level.dimension() || !pos.equals(entityplayer.getRespawnPosition())) { ++ entityplayer.setRespawnPosition(level.dimension(), pos, 0.0F, false, true, org.bukkit.event.player.PlayerSpawnChangeEvent.Cause.RESPAWN_ANCHOR); // CraftBukkit ++ level.playSound((Player) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.RESPAWN_ANCHOR_SET_SPAWN, SoundSource.BLOCKS, 1.0F, 1.0F); + return InteractionResult.SUCCESS; + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/RootedDirtBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/RootedDirtBlock.java.patch new file mode 100644 index 0000000000..6ad22b5539 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/RootedDirtBlock.java.patch @@ -0,0 +1,12 @@ +--- a/net/minecraft/world/level/block/RootedDirtBlock.java ++++ b/net/minecraft/world/level/block/RootedDirtBlock.java +@@ -32,7 +33,7 @@ + } + + @Override +- public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) { +- level.setBlockAndUpdate(pos.below(), Blocks.HANGING_ROOTS.defaultBlockState()); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, pos.below(), Blocks.HANGING_ROOTS.defaultBlockState()); // CraftBukkit + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SaplingBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SaplingBlock.java.patch new file mode 100644 index 0000000000..3e4dc6d7c8 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SaplingBlock.java.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/level/block/SaplingBlock.java ++++ b/net/minecraft/world/level/block/SaplingBlock.java +@@ -17,6 +16,13 @@ + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.TreeType; ++import org.bukkit.block.BlockState; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.world.StructureGrowEvent; ++// CraftBukkit end + + public class SaplingBlock extends BushBlock implements BonemealableBlock { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +@@ -25,8 +33,9 @@ + ); + public static final IntegerProperty STAGE = BlockStateProperties.STAGE; + protected static final float AABB_OFFSET = 6.0F; +- protected static final VoxelShape SHAPE = Block.box(2.0, 0.0, 2.0, 14.0, 12.0, 14.0); +- protected final TreeGrower treeGrower; ++ protected static final VoxelShape SHAPE = Block.box(2.0D, 0.0D, 2.0D, 14.0D, 12.0D, 14.0D); ++ protected final WorldGenTreeProvider treeGrower; ++ public static TreeType treeType; // CraftBukkit + + @Override + public MapCodec codec() { +@@ -55,7 +65,32 @@ + if (state.getValue(STAGE) == 0) { + level.setBlock(pos, state.cycle(STAGE), 4); + } else { +- this.treeGrower.growTree(level, level.getChunkSource().getGenerator(), pos, state, random); ++ // CraftBukkit start ++ if (level.captureTreeGeneration) { ++ this.treeGrower.growTree(level, level.getChunkSource().getGenerator(), pos, state, random); ++ } else { ++ level.captureTreeGeneration = true; ++ this.treeGrower.growTree(level, level.getChunkSource().getGenerator(), pos, state, random); ++ level.captureTreeGeneration = false; ++ if (level.capturedBlockStates.size() > 0) { ++ TreeType treeType = SaplingBlock.treeType; ++ SaplingBlock.treeType = null; ++ Location location = CraftLocation.toBukkit(pos, level.getWorld()); ++ java.util.List blocks = new java.util.ArrayList<>(level.capturedBlockStates.values()); ++ level.capturedBlockStates.clear(); ++ StructureGrowEvent event = null; ++ if (treeType != null) { ++ event = new StructureGrowEvent(location, treeType, false, null, blocks); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ } ++ if (event == null || !event.isCancelled()) { ++ for (BlockState blockstate : blocks) { ++ blockstate.update(true); ++ } ++ } ++ } ++ } ++ // CraftBukkit end + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ScaffoldingBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ScaffoldingBlock.java.patch new file mode 100644 index 0000000000..980267e902 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/ScaffoldingBlock.java.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/level/block/ScaffoldingBlock.java ++++ b/net/minecraft/world/level/block/ScaffoldingBlock.java +@@ -107,12 +99,13 @@ + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- int distance = getDistance(level, pos); +- BlockState blockState = state.setValue(DISTANCE, Integer.valueOf(distance)).setValue(BOTTOM, Boolean.valueOf(this.isBottom(level, pos, distance))); +- if (blockState.getValue(DISTANCE) == 7) { +- if (state.getValue(DISTANCE) == 7) { +- FallingBlockEntity.fall(level, pos, blockState); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ int i = getDistance(level, pos); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) state.setValue(ScaffoldingBlock.DISTANCE, i)).setValue(ScaffoldingBlock.BOTTOM, this.isBottom(level, pos, i)); ++ ++ if ((Integer) iblockdata1.getValue(ScaffoldingBlock.DISTANCE) == 7 && !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.AIR.defaultBlockState()).isCancelled()) { // CraftBukkit - BlockFadeEvent ++ if ((Integer) state.getValue(ScaffoldingBlock.DISTANCE) == 7) { ++ FallingBlockEntity.fall(level, pos, iblockdata1); + } else { + level.destroyBlock(pos, true); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SculkBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SculkBlock.java.patch new file mode 100644 index 0000000000..630c4ffcd1 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SculkBlock.java.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/world/level/block/SculkBlock.java ++++ b/net/minecraft/world/level/block/SculkBlock.java +@@ -25,20 +29,25 @@ + } + + @Override +- public int attemptUseCharge( +- SculkSpreader.ChargeCursor cursor, LevelAccessor level, BlockPos pos, RandomSource random, SculkSpreader spreader, boolean shouldConvertBlocks +- ) { +- int charge = cursor.getCharge(); +- if (charge != 0 && random.nextInt(spreader.chargeDecayRate()) == 0) { +- BlockPos pos1 = cursor.getPos(); +- boolean flag = pos1.closerThan(pos, (double)spreader.noGrowthRadius()); +- if (!flag && canPlaceGrowth(level, pos1)) { +- int i = spreader.growthSpawnCost(); +- if (random.nextInt(i) < charge) { +- BlockPos blockPos = pos1.above(); +- BlockState randomGrowthState = this.getRandomGrowthState(level, blockPos, random, spreader.isWorldGeneration()); +- level.setBlock(blockPos, randomGrowthState, 3); +- level.playSound(null, pos1, randomGrowthState.getSoundType().getPlaceSound(), SoundSource.BLOCKS, 1.0F, 1.0F); ++ public int attemptUseCharge(SculkSpreader.ChargeCursor cursor, LevelAccessor level, BlockPos pos, RandomSource random, SculkSpreader spreader, boolean shouldConvertBlocks) { ++ int i = cursor.getCharge(); ++ ++ if (i != 0 && random.nextInt(spreader.chargeDecayRate()) == 0) { ++ BlockPos blockposition1 = cursor.getPos(); ++ boolean flag1 = blockposition1.closerThan(pos, (double) spreader.noGrowthRadius()); ++ ++ if (!flag1 && canPlaceGrowth(level, blockposition1)) { ++ int j = spreader.growthSpawnCost(); ++ ++ if (random.nextInt(j) < i) { ++ BlockPos blockposition2 = blockposition1.above(); ++ IBlockData iblockdata = this.getRandomGrowthState(level, blockposition2, random, spreader.isWorldGeneration()); ++ ++ // CraftBukkit start - Call BlockSpreadEvent ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition2, iblockdata, 3)) { ++ level.playSound((Player) null, blockposition1, iblockdata.getSoundType().getPlaceSound(), SoundSource.BLOCKS, 1.0F, 1.0F); ++ } ++ // CraftBukkit end + } + + return Math.max(0, charge - i); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SculkCatalystBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SculkCatalystBlock.java.patch new file mode 100644 index 0000000000..01d0c3dc99 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SculkCatalystBlock.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/level/block/SculkCatalystBlock.java ++++ b/net/minecraft/world/level/block/SculkCatalystBlock.java +@@ -66,8 +68,16 @@ + @Override + public void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { + super.spawnAfterBreak(state, level, pos, stack, dropExperience); +- if (dropExperience) { +- this.tryDropExperience(level, pos, stack, this.xpRange); ++ // CraftBukkit start - Delegate to getExpDrop ++ } ++ ++ @Override ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { ++ if (flag) { ++ return this.tryDropExperience(worldserver, blockposition, itemstack, this.xpRange); + } ++ ++ return 0; ++ // CraftBukkit end + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SculkSensorBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SculkSensorBlock.java.patch new file mode 100644 index 0000000000..4a0459ff91 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SculkSensorBlock.java.patch @@ -0,0 +1,114 @@ +--- a/net/minecraft/world/level/block/SculkSensorBlock.java ++++ b/net/minecraft/world/level/block/SculkSensorBlock.java +@@ -39,6 +41,10 @@ + import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockRedstoneEvent; ++// CraftBukkit end + + public class SculkSensorBlock extends BaseEntityBlock implements SimpleWaterloggedBlock { + public static final MapCodec CODEC = simpleCodec(SculkSensorBlock::new); +@@ -100,14 +104,33 @@ + } + + @Override +- public void stepOn(Level level, BlockPos pos, BlockState state, Entity entity) { +- if (!level.isClientSide() +- && canActivate(state) +- && entity.getType() != EntityType.WARDEN +- && level.getBlockEntity(pos) instanceof SculkSensorBlockEntity sculkSensorBlockEntity +- && level instanceof ServerLevel serverLevel +- && sculkSensorBlockEntity.getVibrationUser().canReceiveVibration(serverLevel, pos, GameEvent.STEP, GameEvent.Context.of(state))) { +- sculkSensorBlockEntity.getListener().forceScheduleVibration(serverLevel, GameEvent.STEP, GameEvent.Context.of(entity), entity.position()); ++ public void stepOn(Level level, BlockPos pos, IBlockData state, Entity entity) { ++ if (!level.isClientSide() && canActivate(state) && entity.getType() != EntityType.WARDEN) { ++ // CraftBukkit start ++ org.bukkit.event.Cancellable cancellable; ++ if (entity instanceof Player) { ++ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new org.bukkit.event.entity.EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent((org.bukkit.event.entity.EntityInteractEvent) cancellable); ++ } ++ if (cancellable.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof SculkSensorBlockEntity) { ++ SculkSensorBlockEntity sculksensorblockentity = (SculkSensorBlockEntity) tileentity; ++ ++ if (level instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) level; ++ ++ if (sculksensorblockentity.getVibrationUser().canReceiveVibration(worldserver, pos, GameEvent.STEP, GameEvent.Context.of(state))) { ++ sculksensorblockentity.getListener().forceScheduleVibration(worldserver, GameEvent.STEP, GameEvent.Context.of(entity), entity.position()); ++ } ++ } ++ } + } + + super.stepOn(level, pos, state, entity); +@@ -199,8 +220,17 @@ + return getPhase(state) == SculkSensorPhase.INACTIVE; + } + +- public static void deactivate(Level level, BlockPos pos, BlockState state) { +- level.setBlock(pos, state.setValue(PHASE, SculkSensorPhase.COOLDOWN).setValue(POWER, Integer.valueOf(0)), 3); ++ public static void deactivate(Level level, BlockPos pos, IBlockData state) { ++ // CraftBukkit start ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(level, pos), state.getValue(SculkSensorBlock.POWER), 0); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if (eventRedstone.getNewCurrent() > 0) { ++ level.setBlock(pos, state.setValue(SculkSensorBlock.POWER, eventRedstone.getNewCurrent()), 3); ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) ((IBlockData) state.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.COOLDOWN)).setValue(SculkSensorBlock.POWER, 0), 3); + level.scheduleTick(pos, state.getBlock(), 10); + updateNeighbours(level, pos, state); + } +@@ -210,8 +240,17 @@ + return 30; + } + +- public void activate(@Nullable Entity entity, Level level, BlockPos pos, BlockState state, int power, int frequency) { +- level.setBlock(pos, state.setValue(PHASE, SculkSensorPhase.ACTIVE).setValue(POWER, Integer.valueOf(power)), 3); ++ public void activate(@Nullable Entity entity, Level level, BlockPos pos, IBlockData state, int power, int frequency) { ++ // CraftBukkit start ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(level, pos), state.getValue(SculkSensorBlock.POWER), power); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if (eventRedstone.getNewCurrent() <= 0) { ++ return; ++ } ++ power = eventRedstone.getNewCurrent(); ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) ((IBlockData) state.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.ACTIVE)).setValue(SculkSensorBlock.POWER, power), 3); + level.scheduleTick(pos, state.getBlock(), this.getActiveTicks()); + updateNeighbours(level, pos, state); + tryResonateVibration(entity, level, pos, frequency); +@@ -288,8 +332,16 @@ + @Override + public void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { + super.spawnAfterBreak(state, level, pos, stack, dropExperience); +- if (dropExperience) { +- this.tryDropExperience(level, pos, stack, ConstantInt.of(5)); ++ // CraftBukkit start - Delegate to getExpDrop ++ } ++ ++ @Override ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { ++ if (flag) { ++ return this.tryDropExperience(worldserver, blockposition, itemstack, ConstantInt.of(5)); + } ++ ++ return 0; ++ // CraftBukkit end + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SculkShriekerBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SculkShriekerBlock.java.patch new file mode 100644 index 0000000000..c4ad66e5af --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SculkShriekerBlock.java.patch @@ -0,0 +1,44 @@ +--- a/net/minecraft/world/level/block/SculkShriekerBlock.java ++++ b/net/minecraft/world/level/block/SculkShriekerBlock.java +@@ -61,11 +57,16 @@ + } + + @Override +- public void stepOn(Level level, BlockPos pos, BlockState state, Entity entity) { +- if (level instanceof ServerLevel serverLevel) { +- ServerPlayer serverPlayer = SculkShriekerBlockEntity.tryGetPlayer(entity); +- if (serverPlayer != null) { +- serverLevel.getBlockEntity(pos, BlockEntityType.SCULK_SHRIEKER).ifPresent(sculkShrieker -> sculkShrieker.tryShriek(serverLevel, serverPlayer)); ++ public void stepOn(Level level, BlockPos pos, IBlockData state, Entity entity) { ++ if (level instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) level; ++ ServerPlayer entityplayer = SculkShriekerBlockEntity.tryGetPlayer(entity); ++ ++ if (entityplayer != null) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(entityplayer, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null).isCancelled()) return; // CraftBukkit ++ worldserver.getBlockEntity(pos, BlockEntityType.SCULK_SHRIEKER).ifPresent((sculkshriekerblockentity) -> { ++ sculkshriekerblockentity.tryShriek(worldserver, entityplayer); ++ }); + } + } + +@@ -139,9 +148,17 @@ + @Override + public void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { + super.spawnAfterBreak(state, level, pos, stack, dropExperience); +- if (dropExperience) { +- this.tryDropExperience(level, pos, stack, ConstantInt.of(5)); ++ // CraftBukkit start - Delegate to getExpDrop ++ } ++ ++ @Override ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { ++ if (flag) { ++ return this.tryDropExperience(worldserver, blockposition, itemstack, ConstantInt.of(5)); + } ++ ++ return 0; ++ // CraftBukkit end + } + + @Nullable diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SculkSpreader.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SculkSpreader.java.patch new file mode 100644 index 0000000000..3db9c3c729 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SculkSpreader.java.patch @@ -0,0 +1,41 @@ +--- a/net/minecraft/world/level/block/SculkSpreader.java ++++ b/net/minecraft/world/level/block/SculkSpreader.java +@@ -36,6 +42,10 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockState; + import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.SculkBloomEvent; ++// CraftBukkit end + + public class SculkSpreader { + public static final int MAX_GROWTH_RATE_RADIUS = 24; +@@ -51,6 +62,7 @@ + private final int additionalDecayRate; + private List cursors = new ArrayList<>(); + private static final Logger LOGGER = LogUtils.getLogger(); ++ public Level level; // CraftBukkit + + public SculkSpreader( + boolean isWorldGeneration, TagKey replaceableBlocks, int growthSpawnCoat, int noGrowthRadius, int chargeDecayRate, int additionalDecayRate +@@ -138,6 +153,19 @@ + + private void addCursor(SculkSpreader.ChargeCursor cursor) { + if (this.cursors.size() < 32) { ++ // CraftBukkit start ++ if (!isWorldGeneration()) { // CraftBukkit - SPIGOT-7475: Don't call event during world generation ++ CraftBlock bukkitBlock = CraftBlock.at(level, cursor.pos); ++ SculkBloomEvent event = new SculkBloomEvent(bukkitBlock, cursor.getCharge()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ cursor.charge = event.getCharge(); ++ } ++ // CraftBukkit end ++ + this.cursors.add(cursor); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SculkVeinBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SculkVeinBlock.java.patch new file mode 100644 index 0000000000..c32812a39f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SculkVeinBlock.java.patch @@ -0,0 +1,70 @@ +--- a/net/minecraft/world/level/block/SculkVeinBlock.java ++++ b/net/minecraft/world/level/block/SculkVeinBlock.java +@@ -94,19 +107,15 @@ + } + + @Override +- public int attemptUseCharge( +- SculkSpreader.ChargeCursor cursor, LevelAccessor level, BlockPos pos, RandomSource random, SculkSpreader spreader, boolean shouldConvertBlocks +- ) { +- if (shouldConvertBlocks && this.attemptPlaceSculk(spreader, level, cursor.getPos(), random)) { +- return cursor.getCharge() - 1; +- } else { +- return random.nextInt(spreader.chargeDecayRate()) == 0 ? Mth.floor((float)cursor.getCharge() * 0.5F) : cursor.getCharge(); +- } ++ public int attemptUseCharge(SculkSpreader.ChargeCursor cursor, LevelAccessor level, BlockPos pos, RandomSource random, SculkSpreader spreader, boolean shouldConvertBlocks) { ++ // CraftBukkit - add source block ++ return shouldConvertBlocks && this.attemptPlaceSculk(spreader, level, cursor.getPos(), random, pos) ? cursor.getCharge() - 1 : (random.nextInt(spreader.chargeDecayRate()) == 0 ? Mth.floor((float) cursor.getCharge() * 0.5F) : cursor.getCharge()); + } + +- private boolean attemptPlaceSculk(SculkSpreader spreader, LevelAccessor level, BlockPos pos, RandomSource random) { +- BlockState blockState = level.getBlockState(pos); +- TagKey tagKey = spreader.replaceableBlocks(); ++ private boolean attemptPlaceSculk(SculkSpreader sculkspreader, LevelAccessor generatoraccess, BlockPos blockposition, RandomSource randomsource, BlockPos sourceBlock) { // CraftBukkit ++ IBlockData iblockdata = generatoraccess.getBlockState(blockposition); ++ TagKey tagkey = sculkspreader.replaceableBlocks(); ++ Iterator iterator = Direction.allShuffled(randomsource).iterator(); + + for (Direction direction : Direction.allShuffled(random)) { + if (hasFace(blockState, direction)) { +@@ -120,12 +120,34 @@ + this.veinSpreader.spreadAll(blockState2, level, blockPos, spreader.isWorldGeneration()); + Direction opposite = direction.getOpposite(); + +- for (Direction direction1 : DIRECTIONS) { +- if (direction1 != opposite) { +- BlockPos blockPos1 = blockPos.relative(direction1); +- BlockState blockState3 = level.getBlockState(blockPos1); +- if (blockState3.is(this)) { +- this.onDischarged(level, blockState3, blockPos1, random); ++ if (hasFace(iblockdata, enumdirection)) { ++ BlockPos blockposition1 = blockposition.relative(enumdirection); ++ IBlockData iblockdata1 = generatoraccess.getBlockState(blockposition1); ++ ++ if (iblockdata1.is(tagkey)) { ++ IBlockData iblockdata2 = Blocks.SCULK.defaultBlockState(); ++ ++ // CraftBukkit start - Call BlockSpreadEvent ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(generatoraccess, sourceBlock, blockposition1, iblockdata2, 3)) { ++ return false; ++ } ++ // CraftBukkit end ++ Block.pushEntitiesUp(iblockdata1, iblockdata2, generatoraccess, blockposition1); ++ generatoraccess.playSound((Player) null, blockposition1, SoundEvents.SCULK_BLOCK_SPREAD, SoundSource.BLOCKS, 1.0F, 1.0F); ++ this.veinSpreader.spreadAll(iblockdata2, generatoraccess, blockposition1, sculkspreader.isWorldGeneration()); ++ Direction enumdirection1 = enumdirection.getOpposite(); ++ Direction[] aenumdirection = SculkVeinBlock.DIRECTIONS; ++ int i = aenumdirection.length; ++ ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection2 = aenumdirection[j]; ++ ++ if (enumdirection2 != enumdirection1) { ++ BlockPos blockposition2 = blockposition1.relative(enumdirection2); ++ IBlockData iblockdata3 = generatoraccess.getBlockState(blockposition2); ++ ++ if (iblockdata3.is((Block) this)) { ++ this.onDischarged(generatoraccess, iblockdata3, blockposition2, randomsource); + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SignBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SignBlock.java.patch new file mode 100644 index 0000000000..88351e4710 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SignBlock.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/level/block/SignBlock.java ++++ b/net/minecraft/world/level/block/SignBlock.java +@@ -103,10 +117,8 @@ + return InteractionResult.SUCCESS; + } else if (flag1) { + return InteractionResult.SUCCESS; +- } else if (!this.otherPlayerIsEditingSign(player, signBlockEntity) +- && player.mayBuild() +- && this.hasEditableText(player, signBlockEntity, isFacingFrontText)) { +- this.openTextEdit(player, signBlockEntity, isFacingFrontText); ++ } else if (!this.otherPlayerIsEditingSign(player, tileentitysign) && player.mayBuild() && this.hasEditableText(player, tileentitysign, flag1)) { ++ this.openTextEdit(player, tileentitysign, flag1, org.bukkit.event.player.PlayerSignOpenEvent.Cause.INTERACT); // CraftBukkit + return this.getInteractionResult(flag); + } else { + return InteractionResult.PASS; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SnowLayerBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SnowLayerBlock.java.patch new file mode 100644 index 0000000000..0fb71b7e6c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SnowLayerBlock.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/level/block/SnowLayerBlock.java ++++ b/net/minecraft/world/level/block/SnowLayerBlock.java +@@ -112,8 +97,13 @@ + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- if (level.getBrightness(LightLayer.BLOCK, pos) > 11) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (level.getBrightness(EnumSkyBlock.BLOCK, pos) > 11) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.AIR.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + dropResources(state, level, pos); + level.removeBlock(pos, false); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SpawnerBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SpawnerBlock.java.patch new file mode 100644 index 0000000000..d63a95061e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SpawnerBlock.java.patch @@ -0,0 +1,26 @@ +--- a/net/minecraft/world/level/block/SpawnerBlock.java ++++ b/net/minecraft/world/level/block/SpawnerBlock.java +@@ -46,10 +45,20 @@ + @Override + public void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { + super.spawnAfterBreak(state, level, pos, stack, dropExperience); +- if (dropExperience) { +- int i = 15 + level.random.nextInt(15) + level.random.nextInt(15); +- this.popExperience(level, pos, i); ++ // CraftBukkit start - Delegate to getExpDrop ++ } ++ ++ @Override ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { ++ if (flag) { ++ int i = 15 + worldserver.random.nextInt(15) + worldserver.random.nextInt(15); ++ ++ // this.popExperience(worldserver, blockposition, i); ++ return i; + } ++ ++ return 0; ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SpongeBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SpongeBlock.java.patch new file mode 100644 index 0000000000..c32faa3473 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SpongeBlock.java.patch @@ -0,0 +1,122 @@ +--- a/net/minecraft/world/level/block/SpongeBlock.java ++++ b/net/minecraft/world/level/block/SpongeBlock.java +@@ -12,6 +12,12 @@ + import net.minecraft.world.level.block.state.BlockBehaviour; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.material.FluidState; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.util.BlockStateListPopulator; ++import org.bukkit.event.block.SpongeAbsorbEvent; ++// CraftBukkit end + + public class SpongeBlock extends Block { + public static final MapCodec CODEC = simpleCodec(SpongeBlock::new); +@@ -49,18 +57,41 @@ + } + + private boolean removeWaterBreadthFirstSearch(Level level, BlockPos pos) { +- return BlockPos.breadthFirstTraversal( +- pos, +- 6, +- 65, +- (validPos, queueAdder) -> { +- for (Direction direction : ALL_DIRECTIONS) { +- queueAdder.accept(validPos.relative(direction)); ++ BlockStateListPopulator blockList = new BlockStateListPopulator(level); // CraftBukkit - Use BlockStateListPopulator ++ BlockPos.breadthFirstTraversal(pos, 6, 65, (blockposition1, consumer) -> { ++ Direction[] aenumdirection = SpongeBlock.ALL_DIRECTIONS; ++ int i = aenumdirection.length; ++ ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ ++ consumer.accept(blockposition1.relative(enumdirection)); ++ } ++ ++ }, (blockposition1) -> { ++ if (blockposition1.equals(pos)) { ++ return true; ++ } else { ++ // CraftBukkit start ++ IBlockData iblockdata = blockList.getBlockState(blockposition1); ++ FluidState fluid = blockList.getFluidState(blockposition1); ++ // CraftBukkit end ++ ++ if (!fluid.is(FluidTags.WATER)) { ++ return false; ++ } else { ++ Block block = iblockdata.getBlock(); ++ ++ if (block instanceof BucketPickup) { ++ BucketPickup ifluidsource = (BucketPickup) block; ++ ++ if (!ifluidsource.pickupBlock((Player) null, blockList, blockposition1, iblockdata).isEmpty()) { // CraftBukkit ++ return true; ++ } + } +- }, +- currentPos -> { +- if (currentPos.equals(pos)) { +- return true; ++ ++ if (iblockdata.getBlock() instanceof LiquidBlock) { ++ blockList.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3); // CraftBukkit + } else { + BlockState blockState = level.getBlockState(currentPos); + FluidState fluidState = level.getFluidState(currentPos); +@@ -89,9 +96,51 @@ + + return true; + } ++ ++ // CraftBukkit start ++ // TileEntity tileentity = iblockdata.hasBlockEntity() ? world.getBlockEntity(blockposition1) : null; ++ ++ // dropResources(iblockdata, world, blockposition1, tileentity); ++ blockList.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3); ++ // CraftBukkit end + } + } +- ) +- > 1; ++ } ++ }); ++ // CraftBukkit start ++ List blocks = blockList.getList(); // Is a clone ++ if (!blocks.isEmpty()) { ++ final org.bukkit.block.Block bblock = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ ++ SpongeAbsorbEvent event = new SpongeAbsorbEvent(bblock, (List) (List) blocks); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ for (CraftBlockState block : blocks) { ++ BlockPos blockposition1 = block.getPosition(); ++ IBlockData iblockdata = level.getBlockState(blockposition1); ++ FluidState fluid = level.getFluidState(blockposition1); ++ ++ if (fluid.is(FluidTags.WATER)) { ++ if (iblockdata.getBlock() instanceof BucketPickup && !((BucketPickup) iblockdata.getBlock()).pickupBlock((Player) null, blockList, blockposition1, iblockdata).isEmpty()) { ++ // NOP ++ } else if (iblockdata.getBlock() instanceof LiquidBlock) { ++ // NOP ++ } else if (iblockdata.is(Blocks.KELP) || iblockdata.is(Blocks.KELP_PLANT) || iblockdata.is(Blocks.SEAGRASS) || iblockdata.is(Blocks.TALL_SEAGRASS)) { ++ BlockEntity tileentity = iblockdata.hasBlockEntity() ? level.getBlockEntity(blockposition1) : null; ++ ++ dropResources(iblockdata, level, blockposition1, tileentity); ++ } ++ } ++ level.setBlock(blockposition1, block.getHandle(), block.getFlag()); ++ } ++ ++ return true; ++ } ++ return false; ++ // CraftBukkit end + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java.patch new file mode 100644 index 0000000000..bab2dbe00e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java.patch @@ -0,0 +1,28 @@ +--- a/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java ++++ b/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java +@@ -42,15 +44,21 @@ + @Override + public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { + if (!canBeGrass(state, level, pos)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + level.setBlockAndUpdate(pos, Blocks.DIRT.defaultBlockState()); + } else { + if (level.getMaxLocalRawBrightness(pos.above()) >= 9) { + BlockState blockState = this.defaultBlockState(); + +- for (int i = 0; i < 4; i++) { +- BlockPos blockPos = pos.offset(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1); +- if (level.getBlockState(blockPos).is(Blocks.DIRT) && canPropagate(blockState, level, blockPos)) { +- level.setBlockAndUpdate(blockPos, blockState.setValue(SNOWY, Boolean.valueOf(level.getBlockState(blockPos.above()).is(Blocks.SNOW)))); ++ for (int i = 0; i < 4; ++i) { ++ BlockPos blockposition1 = pos.offset(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1); ++ ++ if (level.getBlockState(blockposition1).is(Blocks.DIRT) && canPropagate(iblockdata1, level, blockposition1)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition1, (IBlockData) iblockdata1.setValue(SpreadingSnowyDirtBlock.SNOWY, level.getBlockState(blockposition1.above()).is(Blocks.SNOW))); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/StemBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/StemBlock.java.patch new file mode 100644 index 0000000000..3664a93515 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/StemBlock.java.patch @@ -0,0 +1,56 @@ +--- a/net/minecraft/world/level/block/StemBlock.java ++++ b/net/minecraft/world/level/block/StemBlock.java +@@ -26,6 +26,7 @@ + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class StemBlock extends BushBlock implements BonemealableBlock { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +@@ -84,8 +79,8 @@ + if (random.nextInt((int)(25.0F / growthSpeed) + 1) == 0) { + int i = state.getValue(AGE); + if (i < 7) { +- state = state.setValue(AGE, Integer.valueOf(i + 1)); +- level.setBlock(pos, state, 2); ++ state = (IBlockData) state.setValue(StemBlock.AGE, i + 1); ++ CraftEventFactory.handleBlockGrowEvent(level, pos, state, 2); // CraftBukkit + } else { + Direction randomDirection = Direction.Plane.HORIZONTAL.getRandomDirection(random); + BlockPos blockPos = pos.relative(randomDirection); +@@ -95,8 +92,12 @@ + Optional optional = registry.getOptional(this.fruit); + Optional optional1 = registry.getOptional(this.attachedStem); + if (optional.isPresent() && optional1.isPresent()) { +- level.setBlockAndUpdate(blockPos, optional.get().defaultBlockState()); +- level.setBlockAndUpdate(pos, optional1.get().defaultBlockState().setValue(HorizontalDirectionalBlock.FACING, randomDirection)); ++ // CraftBukkit start ++ if (!CraftEventFactory.handleBlockGrowEvent(level, blockposition1, ((Block) optional.get()).defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlockAndUpdate(pos, (IBlockData) ((Block) optional1.get()).defaultBlockState().setValue(HorizontalDirectionalBlock.FACING, enumdirection)); + } + } + } +@@ -120,12 +122,13 @@ + } + + @Override +- public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) { +- int min = Math.min(7, state.getValue(AGE) + Mth.nextInt(level.random, 2, 5)); +- BlockState blockState = state.setValue(AGE, Integer.valueOf(min)); +- level.setBlock(pos, blockState, 2); +- if (min == 7) { +- blockState.randomTick(level, pos, level.random); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ int i = Math.min(7, (Integer) state.getValue(StemBlock.AGE) + Mth.nextInt(level.random, 2, 5)); ++ IBlockData iblockdata1 = (IBlockData) state.setValue(StemBlock.AGE, i); ++ ++ CraftEventFactory.handleBlockGrowEvent(level, pos, iblockdata1, 2); // CraftBukkit ++ if (i == 7) { ++ iblockdata1.randomTick(level, pos, level.random); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SugarCaneBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SugarCaneBlock.java.patch new file mode 100644 index 0000000000..519b55072d --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SugarCaneBlock.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/level/block/SugarCaneBlock.java ++++ b/net/minecraft/world/level/block/SugarCaneBlock.java +@@ -57,10 +60,11 @@ + } + + if (i < 3) { +- int i1 = state.getValue(AGE); +- if (i1 == 15) { +- level.setBlockAndUpdate(pos.above(), this.defaultBlockState()); +- level.setBlock(pos, state.setValue(AGE, Integer.valueOf(0)), 4); ++ int j = (Integer) state.getValue(SugarCaneBlock.AGE); ++ ++ if (j == 15) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos.above(), this.defaultBlockState()); // CraftBukkit ++ level.setBlock(pos, (IBlockData) state.setValue(SugarCaneBlock.AGE, 0), 4); + } else { + level.setBlock(pos, state.setValue(AGE, Integer.valueOf(i1 + 1)), 4); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SweetBerryBushBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SweetBerryBushBlock.java.patch new file mode 100644 index 0000000000..96f4c6b00e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/SweetBerryBushBlock.java.patch @@ -0,0 +1,79 @@ +--- a/net/minecraft/world/level/block/SweetBerryBushBlock.java ++++ b/net/minecraft/world/level/block/SweetBerryBushBlock.java +@@ -27,6 +27,13 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import java.util.Collections; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerHarvestBlockEvent; ++// CraftBukkit end + + public class SweetBerryBushBlock extends BushBlock implements BonemealableBlock { + public static final MapCodec CODEC = simpleCodec(SweetBerryBushBlock::new); +@@ -69,21 +74,25 @@ + public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { + int i = state.getValue(AGE); + if (i < 3 && random.nextInt(5) == 0 && level.getRawBrightness(pos.above(), 0) >= 9) { +- BlockState blockState = state.setValue(AGE, Integer.valueOf(i + 1)); +- level.setBlock(pos, blockState, 2); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(blockState)); ++ IBlockData iblockdata1 = (IBlockData) state.setValue(SweetBerryBushBlock.AGE, i + 1); ++ ++ if (!CraftEventFactory.handleBlockGrowEvent(level, pos, iblockdata1, 2)) return; // CraftBukkit ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(iblockdata1)); + } + } + + @Override + public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { + if (entity instanceof LivingEntity && entity.getType() != EntityType.FOX && entity.getType() != EntityType.BEE) { +- entity.makeStuckInBlock(state, new Vec3(0.8F, 0.75, 0.8F)); +- if (!level.isClientSide && state.getValue(AGE) > 0 && (entity.xOld != entity.getX() || entity.zOld != entity.getZ())) { +- double abs = Math.abs(entity.getX() - entity.xOld); +- double abs1 = Math.abs(entity.getZ() - entity.zOld); +- if (abs >= 0.003F || abs1 >= 0.003F) { ++ entity.makeStuckInBlock(state, new Vec3(0.800000011920929D, 0.75D, 0.800000011920929D)); ++ if (!level.isClientSide && (Integer) state.getValue(SweetBerryBushBlock.AGE) > 0 && (entity.xOld != entity.getX() || entity.zOld != entity.getZ())) { ++ double d0 = Math.abs(entity.getX() - entity.xOld); ++ double d1 = Math.abs(entity.getZ() - entity.zOld); ++ ++ if (d0 >= 0.003000000026077032D || d1 >= 0.003000000026077032D) { ++ CraftEventFactory.blockDamage = CraftBlock.at(level, pos); // CraftBukkit + entity.hurt(level.damageSources().sweetBerryBush(), 1.0F); ++ CraftEventFactory.blockDamage = null; // CraftBukkit + } + } + } +@@ -96,12 +108,22 @@ + if (!flag && player.getItemInHand(hand).is(Items.BONE_MEAL)) { + return InteractionResult.PASS; + } else if (i > 1) { +- int i1 = 1 + level.random.nextInt(2); +- popResource(level, pos, new ItemStack(Items.SWEET_BERRIES, i1 + (flag ? 1 : 0))); +- level.playSound(null, pos, SoundEvents.SWEET_BERRY_BUSH_PICK_BERRIES, SoundSource.BLOCKS, 1.0F, 0.8F + level.random.nextFloat() * 0.4F); +- BlockState blockState = state.setValue(AGE, Integer.valueOf(1)); +- level.setBlock(pos, blockState, 2); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(player, blockState)); ++ int j = 1 + level.random.nextInt(2); ++ ++ // CraftBukkit start ++ PlayerHarvestBlockEvent event = CraftEventFactory.callPlayerHarvestBlockEvent(level, pos, player, hand, Collections.singletonList(new ItemStack(Items.SWEET_BERRIES, j + (flag ? 1 : 0)))); ++ if (event.isCancelled()) { ++ return InteractionResult.SUCCESS; // We need to return a success either way, because making it PASS or FAIL will result in a bug where cancelling while harvesting w/ block in hand places block ++ } ++ for (org.bukkit.inventory.ItemStack itemStack : event.getItemsHarvested()) { ++ popResource(level, pos, CraftItemStack.asNMSCopy(itemStack)); ++ } ++ // CraftBukkit end ++ level.playSound((Player) null, pos, SoundEvents.SWEET_BERRY_BUSH_PICK_BERRIES, SoundSource.BLOCKS, 1.0F, 0.8F + level.random.nextFloat() * 0.4F); ++ IBlockData iblockdata1 = (IBlockData) state.setValue(SweetBerryBushBlock.AGE, 1); ++ ++ level.setBlock(pos, iblockdata1, 2); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(player, iblockdata1)); + return InteractionResult.sidedSuccess(level.isClientSide); + } else { + return super.use(state, level, pos, player, hand, hit); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/TntBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/TntBlock.java.patch new file mode 100644 index 0000000000..c2a97e5ea5 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/TntBlock.java.patch @@ -0,0 +1,80 @@ +--- a/net/minecraft/world/level/block/TntBlock.java ++++ b/net/minecraft/world/level/block/TntBlock.java +@@ -25,6 +25,10 @@ + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.BlockHitResult; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.block.TNTPrimeEvent.PrimeCause; ++// CraftBukkit end + + public class TntBlock extends Block { + public static final MapCodec CODEC = simpleCodec(TntBlock::new); +@@ -43,7 +48,7 @@ + @Override + public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { + if (!oldState.is(state.getBlock())) { +- if (level.hasNeighborSignal(pos)) { ++ if (level.hasNeighborSignal(pos) && CraftEventFactory.callTNTPrimeEvent(level, pos, PrimeCause.REDSTONE, null, null)) { // CraftBukkit - TNTPrimeEvent + explode(level, pos); + level.removeBlock(pos, false); + } +@@ -51,17 +57,17 @@ + } + + @Override +- public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { +- if (level.hasNeighborSignal(pos)) { ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ if (level.hasNeighborSignal(pos) && CraftEventFactory.callTNTPrimeEvent(level, pos, PrimeCause.REDSTONE, null, fromPos)) { // CraftBukkit - TNTPrimeEvent + explode(level, pos); + level.removeBlock(pos, false); + } + } + + @Override +- public BlockState playerWillDestroy(Level level, BlockPos blockPos, BlockState blockState, Player player) { +- if (!level.isClientSide() && !player.isCreative() && blockState.getValue(UNSTABLE)) { +- explode(level, blockPos); ++ public IBlockData playerWillDestroy(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ if (!world.isClientSide() && !entityhuman.isCreative() && (Boolean) iblockdata.getValue(TntBlock.UNSTABLE) && CraftEventFactory.callTNTPrimeEvent(world, blockposition, PrimeCause.BLOCK_BREAK, entityhuman, null)) { // CraftBukkit - TNTPrimeEvent ++ explode(world, blockposition); + } + + return super.playerWillDestroy(level, blockPos, blockState, player); +@@ -98,6 +106,11 @@ + if (!itemInHand.is(Items.FLINT_AND_STEEL) && !itemInHand.is(Items.FIRE_CHARGE)) { + return super.use(state, level, pos, player, hand, hit); + } else { ++ // CraftBukkit start - TNTPrimeEvent ++ if (!CraftEventFactory.callTNTPrimeEvent(level, pos, PrimeCause.PLAYER, player, null)) { ++ return InteractionResult.CONSUME; ++ } ++ // CraftBukkit end + explode(level, pos, player); + level.setBlock(pos, Blocks.AIR.defaultBlockState(), 11); + Item item = itemInHand.getItem(); +@@ -117,11 +133,17 @@ + @Override + public void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) { + if (!level.isClientSide) { +- BlockPos blockPos = hit.getBlockPos(); +- Entity owner = projectile.getOwner(); +- if (projectile.isOnFire() && projectile.mayInteract(level, blockPos)) { +- explode(level, blockPos, owner instanceof LivingEntity ? (LivingEntity)owner : null); +- level.removeBlock(blockPos, false); ++ BlockPos blockposition = hit.getBlockPos(); ++ Entity entity = projectile.getOwner(); ++ ++ if (projectile.isOnFire() && projectile.mayInteract(level, blockposition)) { ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, Blocks.AIR.defaultBlockState()) || !CraftEventFactory.callTNTPrimeEvent(level, blockposition, PrimeCause.PROJECTILE, projectile, null)) { ++ return; ++ } ++ // CraftBukkit end ++ explode(level, blockposition, entity instanceof LivingEntity ? (LivingEntity) entity : null); ++ level.removeBlock(blockposition, false); + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/TrapDoorBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/TrapDoorBlock.java.patch new file mode 100644 index 0000000000..d1c1cd8d07 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/TrapDoorBlock.java.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/world/level/block/TrapDoorBlock.java ++++ b/net/minecraft/world/level/block/TrapDoorBlock.java +@@ -32,6 +33,7 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class TrapDoorBlock extends HorizontalDirectionalBlock implements SimpleWaterloggedBlock { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +@@ -145,12 +137,26 @@ + @Override + public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { + if (!level.isClientSide) { +- boolean hasNeighborSignal = level.hasNeighborSignal(pos); +- if (hasNeighborSignal != state.getValue(POWERED)) { +- if (state.getValue(OPEN) != hasNeighborSignal) { +- state = state.setValue(OPEN, Boolean.valueOf(hasNeighborSignal)); +- this.playSound(null, level, pos, hasNeighborSignal); ++ boolean flag1 = level.hasNeighborSignal(pos); ++ ++ if (flag1 != (Boolean) state.getValue(TrapDoorBlock.POWERED)) { ++ // CraftBukkit start ++ org.bukkit.World bworld = level.getWorld(); ++ org.bukkit.block.Block bblock = bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ ++ int power = bblock.getBlockPower(); ++ int oldPower = (Boolean) state.getValue(OPEN) ? 15 : 0; ++ ++ if (oldPower == 0 ^ power == 0 || block.defaultBlockState().isSignalSource()) { ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bblock, oldPower, power); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ flag1 = eventRedstone.getNewCurrent() > 0; + } ++ // CraftBukkit end ++ if ((Boolean) state.getValue(TrapDoorBlock.OPEN) != flag1) { ++ state = (IBlockData) state.setValue(TrapDoorBlock.OPEN, flag1); ++ this.playSound((Player) null, level, pos, flag1); ++ } + + level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(hasNeighborSignal)), 2); + if (state.getValue(WATERLOGGED)) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/TripWireBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/TripWireBlock.java.patch new file mode 100644 index 0000000000..953ce1d85f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/TripWireBlock.java.patch @@ -0,0 +1,51 @@ +--- a/net/minecraft/world/level/block/TripWireBlock.java ++++ b/net/minecraft/world/level/block/TripWireBlock.java +@@ -25,6 +26,7 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.entity.EntityInteractEvent; // CraftBukkit + + public class TripWireBlock extends Block { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +@@ -161,6 +167,40 @@ + } + } + ++ // CraftBukkit start - Call interact even when triggering connected tripwire ++ if (flag != flag1 && flag1 && (Boolean)iblockdata.getValue(ATTACHED)) { ++ org.bukkit.World bworld = level.getWorld(); ++ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager(); ++ org.bukkit.block.Block block = bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ boolean allowed = false; ++ ++ // If all of the events are cancelled block the tripwire trigger, else allow ++ for (Object object : list) { ++ if (object != null) { ++ org.bukkit.event.Cancellable cancellable; ++ ++ if (object instanceof Player) { ++ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) object, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else if (object instanceof Entity) { ++ cancellable = new EntityInteractEvent(((Entity) object).getBukkitEntity(), block); ++ manager.callEvent((EntityInteractEvent) cancellable); ++ } else { ++ continue; ++ } ++ ++ if (!cancellable.isCancelled()) { ++ allowed = true; ++ break; ++ } ++ } ++ } ++ ++ if (!allowed) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ + if (flag1 != flag) { + blockState = blockState.setValue(POWERED, Boolean.valueOf(flag1)); + level.setBlock(pos, blockState, 3); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/TripWireHookBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/TripWireHookBlock.java.patch new file mode 100644 index 0000000000..f73c8995e6 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/TripWireHookBlock.java.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/level/block/TripWireHookBlock.java ++++ b/net/minecraft/world/level/block/TripWireHookBlock.java +@@ -26,6 +28,10 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockRedstoneEvent; ++// CraftBukkit end + + public class TripWireHookBlock extends Block { + public static final MapCodec CODEC = simpleCodec(TripWireHookBlock::new); +@@ -163,7 +177,16 @@ + emitState(level, blockPosx, var21, var22, flag, flag1); + } + +- emitState(level, level1, var21, var22, flag, flag1); ++ // CraftBukkit start ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(world, level), 15, 0); ++ world.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if (eventRedstone.getNewCurrent() > 0) { ++ return; ++ } ++ // CraftBukkit end ++ ++ emitState(world, level, flag4, flag5, flag2, flag3); + if (!hookState) { + level.setBlock(level1, blockState1.setValue(FACING, direction), 3); + if (attaching) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/TurtleEggBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/TurtleEggBlock.java.patch new file mode 100644 index 0000000000..7336dd2cb8 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/TurtleEggBlock.java.patch @@ -0,0 +1,77 @@ +--- a/net/minecraft/world/level/block/TurtleEggBlock.java ++++ b/net/minecraft/world/level/block/TurtleEggBlock.java +@@ -29,6 +29,11 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.event.entity.EntityInteractEvent; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class TurtleEggBlock extends Block { + public static final MapCodec CODEC = simpleCodec(TurtleEggBlock::new); +@@ -71,6 +77,19 @@ + private void destroyEgg(Level level, BlockState state, BlockPos pos, Entity entity, int chance) { + if (this.canDestroyEgg(level, entity)) { + if (!level.isClientSide && level.random.nextInt(chance) == 0 && state.is(Blocks.TURTLE_EGG)) { ++ // CraftBukkit start - Step on eggs ++ org.bukkit.event.Cancellable cancellable; ++ if (entity instanceof Player) { ++ cancellable = CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), CraftBlock.at(level, pos)); ++ level.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ if (cancellable.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.decreaseEggs(level, pos, state); + } + } +@@ -93,22 +116,33 @@ + if (this.shouldUpdateHatchLevel(level) && onSand(level, pos)) { + int i = state.getValue(HATCH); + if (i < 2) { +- level.playSound(null, pos, SoundEvents.TURTLE_EGG_CRACK, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F); +- level.setBlock(pos, state.setValue(HATCH, Integer.valueOf(i + 1)), 2); ++ // CraftBukkit start - Call BlockGrowEvent ++ if (!CraftEventFactory.handleBlockGrowEvent(level, pos, state.setValue(TurtleEggBlock.HATCH, i + 1), 2)) { ++ return; ++ } ++ // CraftBukkit end ++ level.playSound((Player) null, pos, SoundEvents.TURTLE_EGG_CRACK, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F); ++ // worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockTurtleEgg.HATCH, i + 1), 2); // CraftBukkit - handled above + level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(state)); + } else { +- level.playSound(null, pos, SoundEvents.TURTLE_EGG_HATCH, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F); ++ // CraftBukkit start - Call BlockFadeEvent ++ if (CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.AIR.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.playSound((Player) null, pos, SoundEvents.TURTLE_EGG_HATCH, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F); + level.removeBlock(pos, false); + level.gameEvent(GameEvent.BLOCK_DESTROY, pos, GameEvent.Context.of(state)); + + for (int i1 = 0; i1 < state.getValue(EGGS); i1++) { + level.levelEvent(2001, pos, Block.getId(state)); +- Turtle turtle = EntityType.TURTLE.create(level); +- if (turtle != null) { +- turtle.setAge(-24000); +- turtle.setHomePos(pos); +- turtle.moveTo((double)pos.getX() + 0.3 + (double)i1 * 0.2, (double)pos.getY(), (double)pos.getZ() + 0.3, 0.0F, 0.0F); +- level.addFreshEntity(turtle); ++ Turtle entityturtle = (Turtle) EntityType.TURTLE.create(level); ++ ++ if (entityturtle != null) { ++ entityturtle.setAge(-24000); ++ entityturtle.setHomePos(pos); ++ entityturtle.moveTo((double) pos.getX() + 0.3D + (double) j * 0.2D, (double) pos.getY(), (double) pos.getZ() + 0.3D, 0.0F, 0.0F); ++ level.addFreshEntity(entityturtle, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/VineBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/VineBlock.java.patch new file mode 100644 index 0000000000..7769430bf5 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/VineBlock.java.patch @@ -0,0 +1,102 @@ +--- a/net/minecraft/world/level/block/VineBlock.java ++++ b/net/minecraft/world/level/block/VineBlock.java +@@ -24,6 +24,7 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class VineBlock extends Block { + public static final MapCodec CODEC = simpleCodec(VineBlock::new); +@@ -188,19 +194,23 @@ + BlockPos blockPos = pos.above(); + if (random1.getAxis().isHorizontal() && !state.getValue(getPropertyForFace(random1))) { + if (this.canSpread(level, pos)) { +- BlockPos blockPos1 = pos.relative(random1); +- BlockState blockState = level.getBlockState(blockPos1); +- if (blockState.isAir()) { +- Direction clockWise = random1.getClockWise(); +- Direction counterClockWise = random1.getCounterClockWise(); +- boolean flag = state.getValue(getPropertyForFace(clockWise)); +- boolean flag1 = state.getValue(getPropertyForFace(counterClockWise)); +- BlockPos blockPos2 = blockPos1.relative(clockWise); +- BlockPos blockPos3 = blockPos1.relative(counterClockWise); +- if (flag && isAcceptableNeighbour(level, blockPos2, clockWise)) { +- level.setBlock(blockPos1, this.defaultBlockState().setValue(getPropertyForFace(clockWise), Boolean.valueOf(true)), 2); +- } else if (flag1 && isAcceptableNeighbour(level, blockPos3, counterClockWise)) { +- level.setBlock(blockPos1, this.defaultBlockState().setValue(getPropertyForFace(counterClockWise), Boolean.valueOf(true)), 2); ++ blockposition2 = pos.relative(enumdirection); ++ iblockdata1 = level.getBlockState(blockposition2); ++ if (iblockdata1.isAir()) { ++ enumdirection1 = enumdirection.getClockWise(); ++ Direction enumdirection2 = enumdirection.getCounterClockWise(); ++ boolean flag = (Boolean) state.getValue(getPropertyForFace(enumdirection1)); ++ boolean flag1 = (Boolean) state.getValue(getPropertyForFace(enumdirection2)); ++ BlockPos blockposition3 = blockposition2.relative(enumdirection1); ++ BlockPos blockposition4 = blockposition2.relative(enumdirection2); ++ ++ // CraftBukkit start - Call BlockSpreadEvent ++ BlockPos source = pos; ++ ++ if (flag && isAcceptableNeighbour(level, blockposition3, enumdirection1)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, source, blockposition2, (IBlockData) this.defaultBlockState().setValue(getPropertyForFace(enumdirection1), true), 2); ++ } else if (flag1 && isAcceptableNeighbour(level, blockposition4, enumdirection2)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, source, blockposition2, (IBlockData) this.defaultBlockState().setValue(getPropertyForFace(enumdirection2), true), 2); + } else { + Direction opposite = random1.getOpposite(); + if (flag && level.isEmptyBlock(blockPos2) && isAcceptableNeighbour(level, pos.relative(clockWise), opposite)) { +@@ -210,15 +221,16 @@ + } else if ((double)random.nextFloat() < 0.05 && isAcceptableNeighbour(level, blockPos1.above(), Direction.UP)) { + level.setBlock(blockPos1, this.defaultBlockState().setValue(UP, Boolean.valueOf(true)), 2); + } ++ // CraftBukkit end + } +- } else if (isAcceptableNeighbour(level, blockPos1, random1)) { +- level.setBlock(pos, state.setValue(getPropertyForFace(random1), Boolean.valueOf(true)), 2); ++ } else if (isAcceptableNeighbour(level, blockposition2, enumdirection)) { ++ CraftEventFactory.handleBlockGrowEvent(level, pos, (IBlockData) state.setValue(getPropertyForFace(enumdirection), true), 2); // CraftBukkit + } + } + } else { +- if (random1 == Direction.UP && pos.getY() < level.getMaxBuildHeight() - 1) { +- if (this.canSupportAtFace(level, pos, random1)) { +- level.setBlock(pos, state.setValue(UP, Boolean.valueOf(true)), 2); ++ if (enumdirection == Direction.UP && pos.getY() < level.getMaxBuildHeight() - 1) { ++ if (this.canSupportAtFace(level, pos, enumdirection)) { ++ CraftEventFactory.handleBlockGrowEvent(level, pos, (IBlockData) state.setValue(VineBlock.UP, true), 2); // CraftBukkit + return; + } + +@@ -235,8 +250,8 @@ + } + } + +- if (this.hasHorizontalConnection(blockState1)) { +- level.setBlock(blockPos, blockState1, 2); ++ if (this.hasHorizontalConnection(iblockdata2)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition1, iblockdata2, 2); // CraftBukkit + } + + return; +@@ -244,13 +259,14 @@ + } + + if (pos.getY() > level.getMinBuildHeight()) { +- BlockPos blockPos1 = pos.below(); +- BlockState blockState = level.getBlockState(blockPos1); +- if (blockState.isAir() || blockState.is(this)) { +- BlockState blockState2 = blockState.isAir() ? this.defaultBlockState() : blockState; +- BlockState blockState3 = this.copyRandomFaces(state, blockState2, random); +- if (blockState2 != blockState3 && this.hasHorizontalConnection(blockState3)) { +- level.setBlock(blockPos1, blockState3, 2); ++ blockposition2 = pos.below(); ++ iblockdata1 = level.getBlockState(blockposition2); ++ if (iblockdata1.isAir() || iblockdata1.is((Block) this)) { ++ IBlockData iblockdata3 = iblockdata1.isAir() ? this.defaultBlockState() : iblockdata1; ++ IBlockData iblockdata4 = this.copyRandomFaces(state, iblockdata3, random); ++ ++ if (iblockdata3 != iblockdata4 && this.hasHorizontalConnection(iblockdata4)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition2, iblockdata4, 2); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/WallHangingSignBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/WallHangingSignBlock.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/WallHangingSignBlock.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/WaterlilyBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/WaterlilyBlock.java.patch new file mode 100644 index 0000000000..5b7f2f89bb --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/WaterlilyBlock.java.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/world/level/block/WaterlilyBlock.java ++++ b/net/minecraft/world/level/block/WaterlilyBlock.java +@@ -13,6 +13,9 @@ + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class WaterlilyBlock extends BushBlock { + public static final MapCodec CODEC = simpleCodec(WaterlilyBlock::new); +@@ -31,6 +35,11 @@ + public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { + super.entityInside(state, level, pos, entity); + if (level instanceof ServerLevel && entity instanceof Boat) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end + level.destroyBlock(new BlockPos(pos), true, entity); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/WeightedPressurePlateBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/WeightedPressurePlateBlock.java.patch new file mode 100644 index 0000000000..d5bbe02130 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/WeightedPressurePlateBlock.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/world/level/block/WeightedPressurePlateBlock.java ++++ b/net/minecraft/world/level/block/WeightedPressurePlateBlock.java +@@ -14,6 +14,8 @@ + import net.minecraft.world.level.block.state.properties.BlockSetType; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end + + public class WeightedPressurePlateBlock extends BasePressurePlateBlock { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +@@ -40,9 +42,31 @@ + + @Override + protected int getSignalStrength(Level level, BlockPos pos) { +- int min = Math.min(getEntityCount(level, TOUCH_AABB.move(pos), Entity.class), this.maxWeight); +- if (min > 0) { +- float f = (float)Math.min(this.maxWeight, min) / (float)this.maxWeight; ++ // CraftBukkit start ++ // int i = Math.min(getEntityCount(world, BlockPressurePlateWeighted.TOUCH_AABB.move(blockposition), Entity.class), this.maxWeight); ++ int i = 0; ++ for (Entity entity : getEntities(level, WeightedPressurePlateBlock.TOUCH_AABB.move(pos), Entity.class)) { ++ org.bukkit.event.Cancellable cancellable; ++ ++ if (entity instanceof Player) { ++ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ // We only want to block turning the plate on if all events are cancelled ++ if (!cancellable.isCancelled()) { ++ i++; ++ } ++ } ++ ++ i = Math.min(i, this.maxWeight); ++ // CraftBukkit end ++ ++ if (i > 0) { ++ float f = (float) Math.min(this.maxWeight, i) / (float) this.maxWeight; ++ + return Mth.ceil(f * 15.0F); + } else { + return 0; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/WitherRoseBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/WitherRoseBlock.java.patch new file mode 100644 index 0000000000..732ee40145 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/WitherRoseBlock.java.patch @@ -0,0 +1,17 @@ +--- a/net/minecraft/world/level/block/WitherRoseBlock.java ++++ b/net/minecraft/world/level/block/WitherRoseBlock.java +@@ -69,8 +62,12 @@ + @Override + public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { + if (!level.isClientSide && level.getDifficulty() != Difficulty.PEACEFUL) { +- if (entity instanceof LivingEntity livingEntity && !livingEntity.isInvulnerableTo(level.damageSources().wither())) { +- livingEntity.addEffect(new MobEffectInstance(MobEffects.WITHER, 40)); ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ if (!entityliving.isInvulnerableTo(level.damageSources().wither())) { ++ entityliving.addEffect(new MobEffectInstance(MobEffects.WITHER, 40), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.WITHER_ROSE); // CraftBukkit ++ } + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/WitherSkullBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/WitherSkullBlock.java.patch new file mode 100644 index 0000000000..a4f62eda4d --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/WitherSkullBlock.java.patch @@ -0,0 +1,58 @@ +--- a/net/minecraft/world/level/block/WitherSkullBlock.java ++++ b/net/minecraft/world/level/block/WitherSkullBlock.java +@@ -23,6 +25,10 @@ + import net.minecraft.world.level.block.state.pattern.BlockPatternBuilder; + import net.minecraft.world.level.block.state.predicate.BlockStatePredicate; + ++// CraftBukkit start ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; ++// CraftBukkit end ++ + public class WitherSkullBlock extends SkullBlock { + public static final MapCodec CODEC = simpleCodec(WitherSkullBlock::new); + @Nullable +@@ -49,6 +58,7 @@ + } + + public static void checkSpawn(Level level, BlockPos pos, SkullBlockEntity blockEntity) { ++ if (level.captureBlockStates) return; // CraftBukkit + if (!level.isClientSide) { + BlockState blockState = blockEntity.getBlockState(); + boolean flag = blockState.is(Blocks.WITHER_SKELETON_SKULL) || blockState.is(Blocks.WITHER_SKELETON_WALL_SKULL); +@@ -69,12 +66,32 @@ + witherBoss.yBodyRot = blockPatternMatch.getForwards().getAxis() == Direction.Axis.X ? 0.0F : 90.0F; + witherBoss.makeInvulnerable(); + +- for (ServerPlayer serverPlayer : level.getEntitiesOfClass(ServerPlayer.class, witherBoss.getBoundingBox().inflate(50.0))) { +- CriteriaTriggers.SUMMONED_ENTITY.trigger(serverPlayer, witherBoss); ++ if (shapedetector_shapedetectorcollection != null) { ++ WitherBoss entitywither = (WitherBoss) EntityType.WITHER.create(level); ++ ++ if (entitywither != null) { ++ // BlockPumpkinCarved.clearPatternBlocks(world, shapedetector_shapedetectorcollection); // CraftBukkit - move down ++ BlockPos blockposition1 = shapedetector_shapedetectorcollection.getBlock(1, 2, 0).getPos(); ++ ++ entitywither.moveTo((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.55D, (double) blockposition1.getZ() + 0.5D, shapedetector_shapedetectorcollection.getForwards().getAxis() == Direction.Axis.X ? 0.0F : 90.0F, 0.0F); ++ entitywither.yBodyRot = shapedetector_shapedetectorcollection.getForwards().getAxis() == Direction.Axis.X ? 0.0F : 90.0F; ++ entitywither.makeInvulnerable(); ++ // CraftBukkit start ++ if (!level.addFreshEntity(entitywither, SpawnReason.BUILD_WITHER)) { ++ return; + } ++ CarvedPumpkinBlock.clearPatternBlocks(level, shapedetector_shapedetectorcollection); // CraftBukkit - from above ++ // CraftBukkit end ++ Iterator iterator = level.getEntitiesOfClass(ServerPlayer.class, entitywither.getBoundingBox().inflate(50.0D)).iterator(); + +- level.addFreshEntity(witherBoss); +- CarvedPumpkinBlock.updatePatternBlocks(level, blockPatternMatch); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ CriteriaTriggers.SUMMONED_ENTITY.trigger(entityplayer, (Entity) entitywither); ++ } ++ ++ // world.addFreshEntity(entitywither); // CraftBukkit - moved up ++ CarvedPumpkinBlock.updatePatternBlocks(level, shapedetector_shapedetectorcollection); + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java.patch new file mode 100644 index 0000000000..d879117ad3 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java.patch @@ -0,0 +1,268 @@ +--- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -44,6 +45,19 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.block.BlockExpEvent; ++import org.bukkit.event.inventory.FurnaceBurnEvent; ++import org.bukkit.event.inventory.FurnaceExtractEvent; ++import org.bukkit.event.inventory.FurnaceSmeltEvent; ++import org.bukkit.event.inventory.FurnaceStartSmeltEvent; ++import org.bukkit.inventory.CookingRecipe; ++// CraftBukkit end + + public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntity implements WorldlyContainer, RecipeCraftingHolder, StackedContentsCompatible { + protected static final int SLOT_INPUT = 0; +@@ -175,6 +195,40 @@ + return map; + } + ++ // CraftBukkit start - add fields and methods ++ private int maxStack = MAX_STACK; ++ public List transaction = new java.util.ArrayList(); ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ public Object2IntOpenHashMap getRecipesUsed() { ++ return this.recipesUsed; // PAIL private -> public ++ } ++ // CraftBukkit end ++ + private static boolean isNeverAFurnaceFuel(Item item) { + return item.builtInRegistryHolder().is(ItemTags.NON_FLAMMABLE_WOOD); + } +@@ -252,30 +322,56 @@ + recipeHolder = null; + } + +- int maxStackSize = blockEntity.getMaxStackSize(); +- if (!blockEntity.isLit() && canBurn(level.registryAccess(), recipeHolder, blockEntity.items, maxStackSize)) { +- blockEntity.litTime = blockEntity.getBurnDuration(itemStack); ++ int i = blockEntity.getMaxStackSize(); ++ ++ if (!blockEntity.isLit() && canBurn(level.registryAccess(), recipeholder, blockEntity.items, i)) { ++ // CraftBukkit start ++ CraftItemStack fuel = CraftItemStack.asCraftMirror(itemstack); ++ ++ FurnaceBurnEvent furnaceBurnEvent = new FurnaceBurnEvent(CraftBlock.at(level, pos), fuel, blockEntity.getBurnDuration(itemstack)); ++ level.getCraftServer().getPluginManager().callEvent(furnaceBurnEvent); ++ ++ if (furnaceBurnEvent.isCancelled()) { ++ return; ++ } ++ ++ blockEntity.litTime = furnaceBurnEvent.getBurnTime(); + blockEntity.litDuration = blockEntity.litTime; +- if (blockEntity.isLit()) { +- flag = true; +- if (flag2) { +- Item item = itemStack.getItem(); +- itemStack.shrink(1); +- if (itemStack.isEmpty()) { +- Item craftingRemainingItem = item.getCraftingRemainingItem(); +- blockEntity.items.set(1, craftingRemainingItem == null ? ItemStack.EMPTY : new ItemStack(craftingRemainingItem)); ++ if (blockEntity.isLit() && furnaceBurnEvent.isBurning()) { ++ // CraftBukkit end ++ flag1 = true; ++ if (flag3) { ++ Item item = itemstack.getItem(); ++ ++ itemstack.shrink(1); ++ if (itemstack.isEmpty()) { ++ Item item1 = item.getCraftingRemainingItem(); ++ ++ blockEntity.items.set(1, item1 == null ? ItemStack.EMPTY : new ItemStack(item1)); + } + } + } + } + +- if (blockEntity.isLit() && canBurn(level.registryAccess(), recipeHolder, blockEntity.items, maxStackSize)) { +- blockEntity.cookingProgress++; ++ if (blockEntity.isLit() && canBurn(level.registryAccess(), recipeholder, blockEntity.items, i)) { ++ // CraftBukkit start ++ if (recipeholder != null && blockEntity.cookingProgress == 0) { ++ CraftItemStack source = CraftItemStack.asCraftMirror(blockEntity.items.get(0)); ++ CookingRecipe recipe = (CookingRecipe) recipeholder.toBukkitRecipe(); ++ ++ FurnaceStartSmeltEvent event = new FurnaceStartSmeltEvent(CraftBlock.at(level, pos), source, recipe); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ blockEntity.cookingTotalTime = event.getTotalCookTime(); ++ } ++ // CraftBukkit end ++ ++ ++blockEntity.cookingProgress; + if (blockEntity.cookingProgress == blockEntity.cookingTotalTime) { + blockEntity.cookingProgress = 0; + blockEntity.cookingTotalTime = getTotalCookTime(level, blockEntity); +- if (burn(level.registryAccess(), recipeHolder, blockEntity.items, maxStackSize)) { +- blockEntity.setRecipeUsed(recipeHolder); ++ if (burn(blockEntity.level, blockEntity.worldPosition, level.registryAccess(), recipeholder, blockEntity.items, i)) { // CraftBukkit ++ blockEntity.setRecipeUsed(recipeholder); + } + + flag = true; +@@ -317,22 +409,41 @@ + } + } + +- private static boolean burn(RegistryAccess registryAccess, @Nullable RecipeHolder recipeHolder, NonNullList list, int i) { +- if (recipeHolder != null && canBurn(registryAccess, recipeHolder, list, i)) { +- ItemStack itemStack = list.get(0); +- ItemStack resultItem = recipeHolder.value().getResultItem(registryAccess); +- ItemStack itemStack1 = list.get(2); +- if (itemStack1.isEmpty()) { +- list.set(2, resultItem.copy()); +- } else if (itemStack1.is(resultItem.getItem())) { +- itemStack1.grow(1); ++ private static boolean burn(Level world, BlockPos blockposition, RegistryAccess iregistrycustom, @Nullable RecipeHolder recipeholder, NonNullList nonnulllist, int i) { // CraftBukkit ++ if (recipeholder != null && canBurn(iregistrycustom, recipeholder, nonnulllist, i)) { ++ ItemStack itemstack = (ItemStack) nonnulllist.get(0); ++ ItemStack itemstack1 = recipeholder.value().getResultItem(iregistrycustom); ++ ItemStack itemstack2 = (ItemStack) nonnulllist.get(2); ++ ++ // CraftBukkit start - fire FurnaceSmeltEvent ++ CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); ++ org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); ++ ++ FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(CraftBlock.at(world, blockposition), source, result); ++ world.getCraftServer().getPluginManager().callEvent(furnaceSmeltEvent); ++ ++ if (furnaceSmeltEvent.isCancelled()) { ++ return false; + } + + if (itemStack.is(Blocks.WET_SPONGE.asItem()) && !list.get(1).isEmpty() && list.get(1).is(Items.BUCKET)) { + list.set(1, new ItemStack(Items.WATER_BUCKET)); + } + +- itemStack.shrink(1); ++ /* ++ if (itemstack2.isEmpty()) { ++ nonnulllist.set(2, itemstack1.copy()); ++ } else if (itemstack2.is(itemstack1.getItem())) { ++ itemstack2.grow(1); ++ } ++ */ ++ // CraftBukkit end ++ ++ if (itemstack.is(Blocks.WET_SPONGE.asItem()) && !((ItemStack) nonnulllist.get(1)).isEmpty() && ((ItemStack) nonnulllist.get(1)).is(Items.BUCKET)) { ++ nonnulllist.set(1, new ItemStack(Items.WATER_BUCKET)); ++ } ++ ++ itemstack.shrink(1); + return true; + } else { + return false; +@@ -349,7 +470,10 @@ + } + + private static int getTotalCookTime(Level level, AbstractFurnaceBlockEntity blockEntity) { +- return blockEntity.quickCheck.getRecipeFor(blockEntity, level).map(recipeHolder -> recipeHolder.value().getCookingTime()).orElse(200); ++ if (level == null) return 200; // CraftBukkit - SPIGOT-4302 ++ return (Integer) blockEntity.quickCheck.getRecipeFor(blockEntity, level).map((recipeholder) -> { ++ return ((AbstractCookingRecipe) recipeholder.value()).getCookingTime(); ++ }).orElse(200); + } + + public static boolean isFuel(ItemStack stack) { +@@ -462,9 +592,8 @@ + public void awardUsedRecipes(Player player, List items) { + } + +- public void awardUsedRecipesAndPopExperience(ServerPlayer player) { +- List> recipesToAwardAndPopExperience = this.getRecipesToAwardAndPopExperience(player.serverLevel(), player.position()); +- player.awardRecipes(recipesToAwardAndPopExperience); ++ public void awardUsedRecipesAndPopExperience(ServerPlayer entityplayer, ItemStack itemstack, int amount) { // CraftBukkit ++ List> list = this.getRecipesToAwardAndPopExperience(entityplayer.serverLevel(), entityplayer.position(), this.worldPosition, entityplayer, itemstack, amount); // CraftBukkit + + for (RecipeHolder recipeHolder : recipesToAwardAndPopExperience) { + if (recipeHolder != null) { +@@ -476,26 +610,46 @@ + } + + public List> getRecipesToAwardAndPopExperience(ServerLevel level, Vec3 popVec) { ++ // CraftBukkit start ++ return this.getRecipesToAwardAndPopExperience(level, popVec, this.worldPosition, null, null, 0); ++ } ++ ++ public List> getRecipesToAwardAndPopExperience(ServerLevel worldserver, Vec3 vec3d, BlockPos blockposition, ServerPlayer entityplayer, ItemStack itemstack, int amount) { ++ // CraftBukkit end + List> list = Lists.newArrayList(); + +- for (Entry entry : this.recipesUsed.object2IntEntrySet()) { +- level.getRecipeManager().byKey(entry.getKey()).ifPresent(recipeHolder -> { +- list.add((RecipeHolder)recipeHolder); +- createExperience(level, popVec, entry.getIntValue(), ((AbstractCookingRecipe)recipeHolder.value()).getExperience()); ++ while (objectiterator.hasNext()) { ++ Entry entry = (Entry) objectiterator.next(); ++ ++ worldserver.getRecipeManager().byKey((ResourceLocation) entry.getKey()).ifPresent((recipeholder) -> { ++ list.add(recipeholder); ++ createExperience(worldserver, vec3d, entry.getIntValue(), ((AbstractCookingRecipe) recipeholder.value()).getExperience(), blockposition, entityplayer, itemstack, amount); // CraftBukkit + }); + } + + return list; + } + +- private static void createExperience(ServerLevel level, Vec3 popVec, int recipeIndex, float experience) { +- int floor = Mth.floor((float)recipeIndex * experience); +- float fraction = Mth.frac((float)recipeIndex * experience); +- if (fraction != 0.0F && Math.random() < (double)fraction) { +- floor++; ++ private static void createExperience(ServerLevel worldserver, Vec3 vec3d, int i, float f, BlockPos blockposition, net.minecraft.world.entity.player.Player entityhuman, ItemStack itemstack, int amount) { // CraftBukkit ++ int j = Mth.floor((float) i * f); ++ float f1 = Mth.frac((float) i * f); ++ ++ if (f1 != 0.0F && Math.random() < (double) f1) { ++ ++j; + } + +- ExperienceOrb.award(level, popVec, floor); ++ // CraftBukkit start - fire FurnaceExtractEvent / BlockExpEvent ++ BlockExpEvent event; ++ if (amount != 0) { ++ event = new FurnaceExtractEvent((Player) entityhuman.getBukkitEntity(), CraftBlock.at(worldserver, blockposition), org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(itemstack.getItem()), amount, j); ++ } else { ++ event = new BlockExpEvent(CraftBlock.at(worldserver, blockposition), j); ++ } ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ j = event.getExpToDrop(); ++ // CraftBukkit end ++ ++ ExperienceOrb.award(worldserver, vec3d, j); + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BannerBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BannerBlockEntity.java.patch new file mode 100644 index 0000000000..af12c497af --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BannerBlockEntity.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/block/entity/BannerBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BannerBlockEntity.java +@@ -99,6 +102,11 @@ + } + + this.itemPatterns = tag.getList("Patterns", 10); ++ // CraftBukkit start ++ while (this.itemPatterns.size() > 20) { ++ this.itemPatterns.remove(20); ++ } ++ // CraftBukkit end + this.patterns = null; + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BarrelBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BarrelBlockEntity.java.patch new file mode 100644 index 0000000000..a78514a16d --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BarrelBlockEntity.java.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java +@@ -19,6 +20,13 @@ + import net.minecraft.world.level.block.BarrelBlock; + import net.minecraft.world.level.block.state.BlockState; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class BarrelBlockEntity extends RandomizableContainerBlockEntity { + private NonNullList items = NonNullList.withSize(27, ItemStack.EMPTY); + private final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() { +@@ -28,11 +29,9 @@ + BarrelBlockEntity.this.updateBlockState(state, true); + } + +- @Override +- protected void onClose(Level level, BlockPos pos, BlockState state) { +- BarrelBlockEntity.this.playSound(state, SoundEvents.BARREL_CLOSE); +- BarrelBlockEntity.this.updateBlockState(state, false); +- } ++ // CraftBukkit start - add fields and methods ++ public List transaction = new ArrayList<>(); ++ private int maxStack = MAX_STACK; + + @Override + protected void openerCountChanged(Level level, BlockPos pos, BlockState state, int count, int openCount) { +@@ -49,7 +43,30 @@ + } + }; + +- public BarrelBlockEntity(BlockPos pos, BlockState blockState) { ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ @Override ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ // CraftBukkit end ++ private NonNullList items; ++ public final ContainerOpenersCounter openersCounter; ++ ++ public BarrelBlockEntity(BlockPos pos, IBlockData blockState) { + super(BlockEntityType.BARREL, pos, blockState); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java.patch new file mode 100644 index 0000000000..5ae4f7ec74 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java +@@ -85,4 +89,12 @@ + } + + protected abstract AbstractContainerMenu createMenu(int containerId, Inventory inventory); ++ ++ // CraftBukkit start ++ @Override ++ public org.bukkit.Location getLocation() { ++ if (level == null) return null; ++ return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BeaconBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BeaconBlockEntity.java.patch new file mode 100644 index 0000000000..7df6f57821 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BeaconBlockEntity.java.patch @@ -0,0 +1,123 @@ +--- a/net/minecraft/world/level/block/entity/BeaconBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +@@ -38,6 +39,10 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.levelgen.Heightmap; + import net.minecraft.world.phys.AABB; ++// CraftBukkit start ++import org.bukkit.craftbukkit.potion.CraftPotionUtil; ++import org.bukkit.potion.PotionEffect; ++// CraftBukkit end + + public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Nameable { + private static final int MAX_LEVELS = 4; +@@ -65,29 +66,18 @@ + @Nullable + MobEffect secondaryPower; + @Nullable +- private Component name; +- private LockCode lockKey = LockCode.NO_LOCK; +- private final ContainerData dataAccess = new ContainerData() { +- @Override +- public int get(int index) { +- return switch (index) { +- case 0 -> BeaconBlockEntity.this.levels; +- case 1 -> BeaconMenu.encodeEffect(BeaconBlockEntity.this.primaryPower); +- case 2 -> BeaconMenu.encodeEffect(BeaconBlockEntity.this.secondaryPower); +- default -> 0; +- }; +- } ++ public Component name; ++ public LockCode lockKey; ++ private final ContainerData dataAccess; ++ // CraftBukkit start - add fields and methods ++ public PotionEffect getPrimaryEffect() { ++ return (this.primaryPower != null) ? CraftPotionUtil.toBukkit(new MobEffectInstance(this.primaryPower, getLevel(this.levels), getAmplification(levels, primaryPower, secondaryPower), true, true)) : null; ++ } + +- @Override +- public void set(int index, int value) { +- switch (index) { +- case 0: +- BeaconBlockEntity.this.levels = value; +- break; +- case 1: +- if (!BeaconBlockEntity.this.level.isClientSide && !BeaconBlockEntity.this.beamSections.isEmpty()) { +- BeaconBlockEntity.playSound(BeaconBlockEntity.this.level, BeaconBlockEntity.this.worldPosition, SoundEvents.BEACON_POWER_SELECT); +- } ++ public PotionEffect getSecondaryEffect() { ++ return (hasSecondaryEffect(levels, primaryPower, secondaryPower)) ? CraftPotionUtil.toBukkit(new MobEffectInstance(this.secondaryPower, getLevel(this.levels), getAmplification(levels, primaryPower, secondaryPower), true, true)) : null; ++ } ++ // CraftBukkit end + + BeaconBlockEntity.this.primaryPower = BeaconBlockEntity.filterEffect(BeaconMenu.decodeEffect(value)); + break; +@@ -232,12 +258,13 @@ + super.setRemoved(); + } + +- private static void applyEffects(Level level, BlockPos pos, int levels, @Nullable MobEffect primary, @Nullable MobEffect secondary) { +- if (!level.isClientSide && primary != null) { +- double d = (double)(levels * 10 + 10); +- int i = 0; +- if (levels >= 4 && primary == secondary) { +- i = 1; ++ // CraftBukkit start - split into components ++ private static byte getAmplification(int i, @Nullable MobEffect mobeffectlist, @Nullable MobEffect mobeffectlist1) { ++ { ++ byte b0 = 0; ++ ++ if (i >= 4 && mobeffectlist == mobeffectlist1) { ++ b0 = 1; + } + + int i1 = (9 + levels * 2) * 20; +@@ -256,6 +312,24 @@ + } + } + ++ private static void applyEffects(Level level, BlockPos pos, int levels, @Nullable MobEffect primary, @Nullable MobEffect secondary) { ++ if (!level.isClientSide && primary != null) { ++ double d0 = (double) (levels * 10 + 10); ++ byte b0 = getAmplification(levels, primary, secondary); ++ ++ int j = getLevel(levels); ++ List list = getHumansInRange(level, pos, levels); ++ ++ applyEffect(list, primary, j, b0); ++ ++ if (hasSecondaryEffect(levels, primary, secondary)) { ++ applyEffect(list, secondary, j, 0); ++ } ++ } ++ ++ } ++ // CraftBukkit end ++ + public static void playSound(Level level, BlockPos pos, SoundEvent sound) { + level.playSound(null, pos, sound, SoundSource.BLOCKS, 1.0F, 1.0F); + } +@@ -284,10 +360,11 @@ + } + + @Nullable +- private static MobEffect loadEffect(CompoundTag compoundTag, String string) { +- if (compoundTag.contains(string, 8)) { +- ResourceLocation resourceLocation = ResourceLocation.tryParse(compoundTag.getString(string)); +- return filterEffect(BuiltInRegistries.MOB_EFFECT.get(resourceLocation)); ++ private static MobEffect loadEffect(CompoundTag nbttagcompound, String s) { ++ if (nbttagcompound.contains(s, 8)) { ++ ResourceLocation minecraftkey = ResourceLocation.tryParse(nbttagcompound.getString(s)); ++ ++ return (MobEffect) BuiltInRegistries.MOB_EFFECT.get(minecraftkey); // CraftBukkit - persist manually set non-default beacon effects (SPIGOT-3598) + } else { + return null; + } +@@ -298,6 +375,7 @@ + super.load(tag); + this.primaryPower = loadEffect(tag, "primary_effect"); + this.secondaryPower = loadEffect(tag, "secondary_effect"); ++ this.levels = tag.getInt("Levels"); // CraftBukkit - SPIGOT-5053, use where available + if (tag.contains("CustomName", 8)) { + this.name = Component.Serializer.fromJson(tag.getString("CustomName")); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java.patch new file mode 100644 index 0000000000..50c6c909d1 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java.patch @@ -0,0 +1,186 @@ +--- a/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java +@@ -70,7 +42,8 @@ + public static final int MIN_OCCUPATION_TICKS_NECTARLESS = 600; + private final List stored = Lists.newArrayList(); + @Nullable +- private BlockPos savedFlowerPos; ++ public BlockPos savedFlowerPos; ++ public int maxBees = 3; // CraftBukkit - allow setting max amount of bees a hive can hold + + public BeehiveBlockEntity(BlockPos pos, BlockState blockState) { + super(BlockEntityType.BEEHIVE, pos, blockState); +@@ -104,7 +83,7 @@ + } + + public boolean isFull() { +- return this.stored.size() == 3; ++ return this.stored.size() == this.maxBees; // CraftBukkit + } + + public void emptyAllLivingFromHive(@Nullable Player player, BlockState state, BeehiveBlockEntity.BeeReleaseStatus releaseStatus) { +@@ -115,7 +100,7 @@ + Bee bee = (Bee)entity; + if (player.position().distanceToSqr(entity.position()) <= 16.0) { + if (!this.isSedated()) { +- bee.setTarget(player); ++ entitybee.setTarget(player, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit + } else { + bee.setStayOutOfHiveCountdown(400); + } +@@ -125,9 +111,18 @@ + } + } + +- private List releaseAllOccupants(BlockState state, BeehiveBlockEntity.BeeReleaseStatus releaseStatus) { ++ private List releaseAllOccupants(IBlockData state, BeehiveBlockEntity.ReleaseStatus releaseStatus) { ++ // CraftBukkit start - This allows us to bypass the night/rain/emergency check ++ return releaseBees(state, releaseStatus, false); ++ } ++ ++ public List releaseBees(IBlockData iblockdata, BeehiveBlockEntity.ReleaseStatus tileentitybeehive_releasestatus, boolean force) { + List list = Lists.newArrayList(); +- this.stored.removeIf(data -> releaseOccupant(this.level, this.worldPosition, state, data, list, releaseStatus, this.savedFlowerPos)); ++ ++ this.stored.removeIf((tileentitybeehive_hivebee) -> { ++ return releaseBee(this.level, this.worldPosition, iblockdata, tileentitybeehive_hivebee, list, tileentitybeehive_releasestatus, this.savedFlowerPos, force); ++ // CraftBukkit end ++ }); + if (!list.isEmpty()) { + super.setChanged(); + } +@@ -154,7 +149,19 @@ + } + + public void addOccupantWithPresetTicks(Entity occupant, boolean hasNectar, int ticksInHive) { +- if (this.stored.size() < 3) { ++ if (this.stored.size() < this.maxBees) { // CraftBukkit ++ // CraftBukkit start ++ if (this.level != null) { ++ org.bukkit.event.entity.EntityEnterBlockEvent event = new org.bukkit.event.entity.EntityEnterBlockEvent(occupant.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, getBlockPos())); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ if (occupant instanceof Bee) { ++ ((Bee) occupant).setStayOutOfHiveCountdown(400); ++ } ++ return; ++ } ++ } ++ // CraftBukkit end + occupant.stopRiding(); + occupant.ejectPassengers(); + CompoundTag compoundTag = new CompoundTag(); +@@ -189,16 +192,14 @@ + this.stored.add(new BeehiveBlockEntity.BeeData(entityData, ticksInHive, hasNectar ? 2400 : 600)); + } + +- private static boolean releaseOccupant( +- Level level, +- BlockPos pos, +- BlockState state, +- BeehiveBlockEntity.BeeData data, +- @Nullable List storedInHives, +- BeehiveBlockEntity.BeeReleaseStatus releaseStatus, +- @Nullable BlockPos savedFlowerPos +- ) { +- if ((level.isNight() || level.isRaining()) && releaseStatus != BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY) { ++ private static boolean releaseOccupant(Level level, BlockPos pos, IBlockData state, BeehiveBlockEntity.BeeData data, @Nullable List storedInHives, BeehiveBlockEntity.ReleaseStatus releaseStatus, @Nullable BlockPos savedFlowerPos) { ++ // CraftBukkit start - This allows us to bypass the night/rain/emergency check ++ return releaseBee(level, pos, state, data, storedInHives, releaseStatus, savedFlowerPos, false); ++ } ++ ++ private static boolean releaseBee(Level world, BlockPos blockposition, IBlockData iblockdata, BeehiveBlockEntity.BeeData tileentitybeehive_hivebee, @Nullable List list, BeehiveBlockEntity.ReleaseStatus tileentitybeehive_releasestatus, @Nullable BlockPos blockposition1, boolean force) { ++ if (!force && (world.isNight() || world.isRaining()) && tileentitybeehive_releasestatus != BeehiveBlockEntity.ReleaseStatus.EMERGENCY) { ++ // CraftBukkit end + return false; + } else { + CompoundTag compoundTag = data.entityData.copy(); +@@ -216,9 +222,23 @@ + if (!entity.getType().is(EntityTypeTags.BEEHIVE_INHABITORS)) { + return false; + } else { +- if (entity instanceof Bee bee) { +- if (savedFlowerPos != null && !bee.hasSavedFlowerPos() && level.random.nextFloat() < 0.9F) { +- bee.setSavedFlowerPos(savedFlowerPos); ++ // CraftBukkit start ++ if (entity instanceof Bee) { ++ float f = entity.getBbWidth(); ++ double d0 = flag ? 0.0D : 0.55D + (double) (f / 2.0F); ++ double d1 = (double) blockposition.getX() + 0.5D + d0 * (double) enumdirection.getStepX(); ++ double d2 = (double) blockposition.getY() + 0.5D - (double) (entity.getBbHeight() / 2.0F); ++ double d3 = (double) blockposition.getZ() + 0.5D + d0 * (double) enumdirection.getStepZ(); ++ ++ entity.moveTo(d1, d2, d3, entity.getYRot(), entity.getXRot()); ++ } ++ if (!world.addFreshEntity(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BEEHIVE)) return false; // CraftBukkit - SpawnReason, moved from below ++ // CraftBukkit end ++ if (entity instanceof Bee) { ++ Bee entitybee = (Bee) entity; ++ ++ if (blockposition1 != null && !entitybee.hasSavedFlowerPos() && world.random.nextFloat() < 0.9F) { ++ entitybee.setSavedFlowerPos(blockposition1); + } + + if (releaseStatus == BeehiveBlockEntity.BeeReleaseStatus.HONEY_DELIVERED) { +@@ -241,17 +265,20 @@ + storedInHives.add(bee); + } + +- float bbWidth = entity.getBbWidth(); +- double d = flag ? 0.0 : 0.55 + (double)(bbWidth / 2.0F); +- double d1 = (double)pos.getX() + 0.5 + d * (double)direction.getStepX(); +- double d2 = (double)pos.getY() + 0.5 - (double)(entity.getBbHeight() / 2.0F); +- double d3 = (double)pos.getZ() + 0.5 + d * (double)direction.getStepZ(); ++ /* // CraftBukkit start ++ float f = entity.getBbWidth(); ++ double d0 = flag ? 0.0D : 0.55D + (double) (f / 2.0F); ++ double d1 = (double) blockposition.getX() + 0.5D + d0 * (double) enumdirection.getStepX(); ++ double d2 = (double) blockposition.getY() + 0.5D - (double) (entity.getBbHeight() / 2.0F); ++ double d3 = (double) blockposition.getZ() + 0.5D + d0 * (double) enumdirection.getStepZ(); ++ + entity.moveTo(d1, d2, d3, entity.getYRot(), entity.getXRot()); ++ */ // CraftBukkit end + } + +- level.playSound(null, pos, SoundEvents.BEEHIVE_EXIT, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, level.getBlockState(pos))); +- return level.addFreshEntity(entity); ++ world.playSound((Player) null, blockposition, SoundEvents.BEEHIVE_EXIT, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entity, world.getBlockState(blockposition))); ++ return true; // return this.world.addFreshEntity(entity); // CraftBukkit - moved up + } + } else { + return false; +@@ -294,6 +327,10 @@ + if (releaseOccupant(level, pos, state, beeData, null, beeReleaseStatus, savedFlowerPos)) { + flag = true; + iterator.remove(); ++ // CraftBukkit start ++ } else { ++ tileentitybeehive_hivebee.ticksInHive = tileentitybeehive_hivebee.minOccupationTicks / 2; // Not strictly Vanilla behaviour in cases where bees cannot spawn but still reasonable ++ // CraftBukkit end + } + } + +@@ -335,6 +371,12 @@ + if (tag.contains("FlowerPos")) { + this.savedFlowerPos = NbtUtils.readBlockPos(tag.getCompound("FlowerPos")); + } ++ ++ // CraftBukkit start ++ if (tag.contains("Bukkit.MaxEntities")) { ++ this.maxBees = tag.getInt("Bukkit.MaxEntities"); ++ } ++ // CraftBukkit end + } + + @Override +@@ -344,6 +386,8 @@ + if (this.hasSavedFlowerPos()) { + tag.put("FlowerPos", NbtUtils.writeBlockPos(this.savedFlowerPos)); + } ++ tag.putInt("Bukkit.MaxEntities", this.maxBees); // CraftBukkit ++ + } + + public ListTag writeBees() { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BellBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BellBlockEntity.java.patch new file mode 100644 index 0000000000..7395d0f362 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BellBlockEntity.java.patch @@ -0,0 +1,17 @@ +--- a/net/minecraft/world/level/block/entity/BellBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BellBlockEntity.java +@@ -129,7 +144,13 @@ + } + + private static void makeRaidersGlow(Level level, BlockPos pos, List raiders) { +- raiders.stream().filter(raider -> isRaiderWithinRange(pos, raider)).forEach(BellBlockEntity::glow); ++ List entities = // CraftBukkit ++ raiders.stream().filter((entityliving) -> { ++ return isRaiderWithinRange(pos, entityliving); ++ }).map((entity) -> (org.bukkit.entity.LivingEntity) entity.getBukkitEntity()).collect(java.util.stream.Collectors.toCollection(java.util.ArrayList::new)); // CraftBukkit ++ ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBellResonateEvent(level, pos, entities).forEach(BellBlockEntity::glow); ++ // CraftBukkit end + } + + private static void showBellParticles(Level level, BlockPos pos, List raiders) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BlockEntity.java.patch new file mode 100644 index 0000000000..8d9c62e9fe --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BlockEntity.java.patch @@ -0,0 +1,68 @@ +--- a/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -15,7 +15,18 @@ + import net.minecraft.world.level.block.state.BlockState; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer; ++import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end ++ + public abstract class BlockEntity { ++ ++ // CraftBukkit start - data containers ++ private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); ++ public CraftPersistentDataContainer persistentDataContainer; ++ // CraftBukkit end + private static final Logger LOGGER = LogUtils.getLogger(); + private final BlockEntityType type; + @Nullable +@@ -47,11 +58,13 @@ + return this.level != null; + } + ++ // CraftBukkit start - read container + public void load(CompoundTag tag) { + } + + protected void saveAdditional(CompoundTag tag) { + } ++ // CraftBukkit end + + public final CompoundTag saveWithFullMetadata() { + CompoundTag compoundTag = this.saveWithoutMetadata(); +@@ -66,9 +86,15 @@ + } + + public final CompoundTag saveWithoutMetadata() { +- CompoundTag compoundTag = new CompoundTag(); +- this.saveAdditional(compoundTag); +- return compoundTag; ++ CompoundTag nbttagcompound = new CompoundTag(); ++ ++ this.saveAdditional(nbttagcompound); ++ // CraftBukkit start - store container ++ if (this.persistentDataContainer != null && !this.persistentDataContainer.isEmpty()) { ++ nbttagcompound.put("PublicBukkitValues", this.persistentDataContainer.toTagCompound()); ++ } ++ // CraftBukkit end ++ return nbttagcompound; + } + + private void saveId(CompoundTag tag) { +@@ -191,4 +226,13 @@ + public void setBlockState(BlockState blockState) { + this.blockState = blockState; + } ++ ++ // CraftBukkit start - add method ++ public InventoryHolder getOwner() { ++ if (level == null) return null; ++ org.bukkit.block.BlockState state = level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()).getState(); ++ if (state instanceof InventoryHolder) return (InventoryHolder) state; ++ return null; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java.patch new file mode 100644 index 0000000000..5f4c563bd4 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java.patch @@ -0,0 +1,189 @@ +--- a/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java +@@ -24,6 +25,20 @@ + import net.minecraft.world.level.block.BrewingStandBlock; + import net.minecraft.world.level.block.state.BlockState; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.event.block.BrewingStartEvent; ++import org.bukkit.event.inventory.BrewEvent; ++import org.bukkit.event.inventory.BrewingStandFuelEvent; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end ++ + public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements WorldlyContainer { + private static final int INGREDIENT_SLOT = 3; + private static final int FUEL_SLOT = 4; +@@ -38,19 +54,12 @@ + int brewTime; + private boolean[] lastPotionCount; + private Item ingredient; +- int fuel; +- protected final ContainerData dataAccess = new ContainerData() { +- @Override +- public int get(int index) { +- switch (index) { +- case 0: +- return BrewingStandBlockEntity.this.brewTime; +- case 1: +- return BrewingStandBlockEntity.this.fuel; +- default: +- return 0; +- } +- } ++ public int fuel; ++ protected final ContainerData dataAccess; ++ // CraftBukkit start - add fields and methods ++ private int lastTick = MinecraftServer.currentTick; ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = 64; + + @Override + public void set(int index, int value) { +@@ -69,7 +69,25 @@ + } + }; + +- public BrewingStandBlockEntity(BlockPos pos, BlockState state) { ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ ++ public BrewingStandBlockEntity(BlockPos pos, IBlockData state) { + super(BlockEntityType.BREWING_STAND, pos, state); + } + +@@ -94,31 +149,54 @@ + return true; + } + +- public static void serverTick(Level level, BlockPos pos, BlockState state, BrewingStandBlockEntity blockEntity) { +- ItemStack itemStack = blockEntity.items.get(4); +- if (blockEntity.fuel <= 0 && itemStack.is(Items.BLAZE_POWDER)) { +- blockEntity.fuel = 20; +- itemStack.shrink(1); ++ public static void serverTick(Level level, BlockPos pos, IBlockData state, BrewingStandBlockEntity blockEntity) { ++ ItemStack itemstack = (ItemStack) blockEntity.items.get(4); ++ ++ if (blockEntity.fuel <= 0 && itemstack.is(Items.BLAZE_POWDER)) { ++ // CraftBukkit start ++ BrewingStandFuelEvent event = new BrewingStandFuelEvent(CraftBlock.at(level, pos), CraftItemStack.asCraftMirror(itemstack), 20); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ blockEntity.fuel = event.getFuelPower(); ++ if (blockEntity.fuel > 0 && event.isConsuming()) { ++ itemstack.shrink(1); ++ } ++ // CraftBukkit end + setChanged(level, pos, state); + } + +- boolean isBrewable = isBrewable(blockEntity.items); +- boolean flag = blockEntity.brewTime > 0; +- ItemStack itemStack1 = blockEntity.items.get(3); +- if (flag) { +- blockEntity.brewTime--; +- boolean flag1 = blockEntity.brewTime == 0; +- if (flag1 && isBrewable) { +- doBrew(level, pos, blockEntity.items); ++ boolean flag = isBrewable(blockEntity.items); ++ boolean flag1 = blockEntity.brewTime > 0; ++ ItemStack itemstack1 = (ItemStack) blockEntity.items.get(3); ++ ++ // CraftBukkit start - Use wall time instead of ticks for brewing ++ int elapsedTicks = MinecraftServer.currentTick - blockEntity.lastTick; ++ blockEntity.lastTick = MinecraftServer.currentTick; ++ ++ if (flag1) { ++ blockEntity.brewTime -= elapsedTicks; ++ boolean flag2 = blockEntity.brewTime <= 0; // == -> <= ++ // CraftBukkit end ++ ++ if (flag2 && flag) { ++ doBrew(level, pos, blockEntity.items, blockEntity); // CraftBukkit + setChanged(level, pos, state); + } else if (!isBrewable || !itemStack1.is(blockEntity.ingredient)) { + blockEntity.brewTime = 0; + setChanged(level, pos, state); + } +- } else if (isBrewable && blockEntity.fuel > 0) { +- blockEntity.fuel--; +- blockEntity.brewTime = 400; +- blockEntity.ingredient = itemStack1.getItem(); ++ } else if (flag && blockEntity.fuel > 0) { ++ --blockEntity.fuel; ++ // CraftBukkit start ++ BrewingStartEvent event = new BrewingStartEvent(CraftBlock.at(level, pos), CraftItemStack.asCraftMirror(itemstack1), 400); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ blockEntity.brewTime = event.getTotalBrewTime(); // 400 -> event.getTotalBrewTime() ++ // CraftBukkit end ++ blockEntity.ingredient = itemstack1.getItem(); + setChanged(level, pos, state); + } + +@@ -168,21 +251,33 @@ + } + } + +- private static void doBrew(Level level, BlockPos pos, NonNullList items) { +- ItemStack itemStack = items.get(3); ++ // CraftBukkit start ++ private static void doBrew(Level world, BlockPos blockposition, NonNullList nonnulllist, BrewingStandBlockEntity tileentitybrewingstand) { ++ ItemStack itemstack = (ItemStack) nonnulllist.get(3); ++ InventoryHolder owner = tileentitybrewingstand.getOwner(); ++ List brewResults = new ArrayList<>(3); + + for (int i = 0; i < 3; i++) { + items.set(i, PotionBrewing.mix(itemStack, items.get(i))); + } + +- itemStack.shrink(1); +- if (itemStack.getItem().hasCraftingRemainingItem()) { +- ItemStack itemStack1 = new ItemStack(itemStack.getItem().getCraftingRemainingItem()); +- if (itemStack.isEmpty()) { +- itemStack = itemStack1; ++ if (owner != null) { ++ BrewEvent event = new BrewEvent(CraftBlock.at(world, blockposition), (org.bukkit.inventory.BrewerInventory) owner.getInventory(), brewResults, tileentitybrewingstand.fuel); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ ++ for (int i = 0; i < 3; ++i) { ++ // CraftBukkit start - validate index in case it is cleared by plugins ++ if (i < brewResults.size()) { ++ nonnulllist.set(i, CraftItemStack.asNMSCopy(brewResults.get(i))); + } else { + Containers.dropItemStack(level, (double)pos.getX(), (double)pos.getY(), (double)pos.getZ(), itemStack1); + } ++ // CraftBukkit end + } + + items.set(3, itemStack); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BrushableBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BrushableBlockEntity.java.patch new file mode 100644 index 0000000000..57849c0e54 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/BrushableBlockEntity.java.patch @@ -0,0 +1,56 @@ +--- a/net/minecraft/world/level/block/entity/BrushableBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BrushableBlockEntity.java +@@ -28,6 +28,12 @@ + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.Arrays; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class BrushableBlockEntity extends BlockEntity { + private static final Logger LOGGER = LogUtils.getLogger(); + private static final String LOOT_TABLE_TAG = "LootTable"; +@@ -127,17 +148,21 @@ + if (this.level != null && this.level.getServer() != null) { + this.unpackLootTable(player); + if (!this.item.isEmpty()) { +- double d = (double)EntityType.ITEM.getWidth(); +- double d1 = 1.0 - d; +- double d2 = d / 2.0; +- Direction direction = Objects.requireNonNullElse(this.hitDirection, Direction.UP); +- BlockPos blockPos = this.worldPosition.relative(direction, 1); +- double d3 = (double)blockPos.getX() + 0.5 * d1 + d2; +- double d4 = (double)blockPos.getY() + 0.5 + (double)(EntityType.ITEM.getHeight() / 2.0F); +- double d5 = (double)blockPos.getZ() + 0.5 * d1 + d2; +- ItemEntity itemEntity = new ItemEntity(this.level, d3, d4, d5, this.item.split(this.level.random.nextInt(21) + 10)); +- itemEntity.setDeltaMovement(Vec3.ZERO); +- this.level.addFreshEntity(itemEntity); ++ double d0 = (double) EntityType.ITEM.getWidth(); ++ double d1 = 1.0D - d0; ++ double d2 = d0 / 2.0D; ++ Direction enumdirection = (Direction) Objects.requireNonNullElse(this.hitDirection, Direction.UP); ++ BlockPos blockposition = this.worldPosition.relative(enumdirection, 1); ++ double d3 = (double) blockposition.getX() + 0.5D * d1 + d2; ++ double d4 = (double) blockposition.getY() + 0.5D + (double) (EntityType.ITEM.getHeight() / 2.0F); ++ double d5 = (double) blockposition.getZ() + 0.5D * d1 + d2; ++ ItemEntity entityitem = new ItemEntity(this.level, d3, d4, d5, this.item.split(this.level.random.nextInt(21) + 10)); ++ ++ entityitem.setDeltaMovement(Vec3.ZERO); ++ // CraftBukkit start ++ org.bukkit.block.Block bblock = CraftBlock.at(this.level, this.worldPosition); ++ CraftEventFactory.handleBlockDropItemEvent(bblock, bblock.getState(), (ServerPlayer) player, Arrays.asList(entityitem)); ++ // CraftBukkit end + this.item = ItemStack.EMPTY; + } + } +@@ -208,6 +239,7 @@ + + @Override + public void load(CompoundTag tag) { ++ super.load(tag); // CraftBukkit - SPIGOT-7393: Load super Bukkit data + if (!this.tryLoadLootTable(tag) && tag.contains("item")) { + this.item = ItemStack.of(tag.getCompound("item")); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/CampfireBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/CampfireBlockEntity.java.patch new file mode 100644 index 0000000000..ae5d69ea43 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/CampfireBlockEntity.java.patch @@ -0,0 +1,76 @@ +--- a/net/minecraft/world/level/block/entity/CampfireBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/CampfireBlockEntity.java +@@ -26,6 +26,14 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockCookEvent; ++import org.bukkit.event.block.CampfireStartEvent; ++import org.bukkit.inventory.CampfireRecipe; ++// CraftBukkit end ++ + public class CampfireBlockEntity extends BlockEntity implements Clearable { + private static final int BURN_COOL_SPEED = 2; + private static final int NUM_SLOTS = 4; +@@ -47,13 +62,27 @@ + flag = true; + blockEntity.cookingProgress[i]++; + if (blockEntity.cookingProgress[i] >= blockEntity.cookingTime[i]) { +- Container container = new SimpleContainer(itemStack); +- ItemStack itemStack1 = blockEntity.quickCheck +- .getRecipeFor(container, level) +- .map(recipeHolder -> recipeHolder.value().assemble(container, level.registryAccess())) +- .orElse(itemStack); +- if (itemStack1.isItemEnabled(level.enabledFeatures())) { +- Containers.dropItemStack(level, (double)pos.getX(), (double)pos.getY(), (double)pos.getZ(), itemStack1); ++ SimpleContainer inventorysubcontainer = new SimpleContainer(new ItemStack[]{itemstack}); ++ ItemStack itemstack1 = (ItemStack) blockEntity.quickCheck.getRecipeFor(inventorysubcontainer, level).map((recipeholder) -> { ++ return ((CampfireCookingRecipe) recipeholder.value()).assemble(inventorysubcontainer, level.registryAccess()); ++ }).orElse(itemstack); ++ ++ if (itemstack1.isItemEnabled(level.enabledFeatures())) { ++ // CraftBukkit start - fire BlockCookEvent ++ CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); ++ org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); ++ ++ BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(level, pos), source, result); ++ level.getCraftServer().getPluginManager().callEvent(blockCookEvent); ++ ++ if (blockCookEvent.isCancelled()) { ++ return; ++ } ++ ++ result = blockCookEvent.getResult(); ++ itemstack1 = CraftItemStack.asNMSCopy(result); ++ // CraftBukkit end ++ Containers.dropItemStack(level, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), itemstack1); + blockEntity.items.set(i, ItemStack.EMPTY); + level.sendBlockUpdated(pos, state, state, 3); + level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(state)); +@@ -158,12 +190,17 @@ + } + + public boolean placeFood(@Nullable Entity entity, ItemStack stack, int cookTime) { +- for (int i = 0; i < this.items.size(); i++) { +- ItemStack itemStack = this.items.get(i); +- if (itemStack.isEmpty()) { +- this.cookingTime[i] = cookTime; +- this.cookingProgress[i] = 0; +- this.items.set(i, stack.split(1)); ++ for (int j = 0; j < this.items.size(); ++j) { ++ ItemStack itemstack1 = (ItemStack) this.items.get(j); ++ ++ if (itemstack1.isEmpty()) { ++ // CraftBukkit start ++ CampfireStartEvent event = new CampfireStartEvent(CraftBlock.at(this.level,this.worldPosition), CraftItemStack.asCraftMirror(stack), (CampfireRecipe) getCookableRecipe(stack).get().toBukkitRecipe()); ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ this.cookingTime[j] = event.getTotalCookTime(); // i -> event.getTotalCookTime() ++ // CraftBukkit end ++ this.cookingProgress[j] = 0; ++ this.items.set(j, stack.split(1)); + this.level.gameEvent(GameEvent.BLOCK_CHANGE, this.getBlockPos(), GameEvent.Context.of(entity, this.getBlockState())); + this.markUpdated(); + return true; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/ChestBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/ChestBlockEntity.java.patch new file mode 100644 index 0000000000..fad929d5b4 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/ChestBlockEntity.java.patch @@ -0,0 +1,67 @@ +--- a/net/minecraft/world/level/block/entity/ChestBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/ChestBlockEntity.java +@@ -22,6 +22,11 @@ + import net.minecraft.world.level.block.ChestBlock; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.block.state.properties.ChestType; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end + + public class ChestBlockEntity extends RandomizableContainerBlockEntity implements LidBlockEntity { + private static final int EVENT_SET_OPEN_COUNT = 1; +@@ -32,10 +35,9 @@ + ChestBlockEntity.playSound(level, pos, state, SoundEvents.CHEST_OPEN); + } + +- @Override +- protected void onClose(Level level, BlockPos pos, BlockState state) { +- ChestBlockEntity.playSound(level, pos, state, SoundEvents.CHEST_CLOSE); +- } ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; + + @Override + protected void openerCountChanged(Level level, BlockPos pos, BlockState state, int count, int openCount) { +@@ -55,7 +47,25 @@ + }; + private final ChestLidController chestLidController = new ChestLidController(); + +- protected ChestBlockEntity(BlockEntityType type, BlockPos pos, BlockState blockState) { ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ ++ protected ChestBlockEntity(BlockEntityType type, BlockPos pos, IBlockData blockState) { + super(type, pos, blockState); + } + +@@ -182,4 +233,11 @@ + Block block = state.getBlock(); + level.blockEvent(pos, block, 1, eventParam); + } ++ ++ // CraftBukkit start ++ @Override ++ public boolean onlyOpCanSetNbt() { ++ return true; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java.patch new file mode 100644 index 0000000000..ede2f8b490 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java.patch @@ -0,0 +1,98 @@ +--- a/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java +@@ -17,13 +18,55 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class ChiseledBookShelfBlockEntity extends BlockEntity implements Container { + public static final int MAX_BOOKS_IN_STORAGE = 6; + private static final Logger LOGGER = LogUtils.getLogger(); +- private final NonNullList items = NonNullList.withSize(6, ItemStack.EMPTY); +- private int lastInteractedSlot = -1; ++ private final NonNullList items; ++ public int lastInteractedSlot; ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList<>(); ++ private int maxStack = 1; + +- public ChiseledBookShelfBlockEntity(BlockPos pos, BlockState state) { ++ @Override ++ public List getContents() { ++ return this.items; ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ } ++ // CraftBukkit end ++ ++ public ChiseledBookShelfBlockEntity(BlockPos pos, IBlockData state) { + super(BlockEntityType.CHISELED_BOOKSHELF, pos, state); + } + +@@ -47,6 +94,7 @@ + + @Override + public void load(CompoundTag tag) { ++ super.load(tag); // CraftBukkit - SPIGOT-7393: Load super Bukkit data + this.items.clear(); + ContainerHelper.loadAllItems(tag, this.items); + this.lastInteractedSlot = tag.getInt("last_interacted_slot"); +@@ -86,8 +135,8 @@ + public ItemStack removeItem(int slot, int amount) { + ItemStack itemStack = Objects.requireNonNullElse(this.items.get(slot), ItemStack.EMPTY); + this.items.set(slot, ItemStack.EMPTY); +- if (!itemStack.isEmpty()) { +- this.updateState(slot); ++ if (!itemstack.isEmpty()) { ++ if (level != null) this.updateState(slot); // CraftBukkit - SPIGOT-7381: check for null world + } + + return itemStack; +@@ -102,7 +151,7 @@ + public void setItem(int slot, ItemStack stack) { + if (stack.is(ItemTags.BOOKSHELF_BOOKS)) { + this.items.set(slot, stack); +- this.updateState(slot); ++ if (level != null) this.updateState(slot); // CraftBukkit - SPIGOT-7381: check for null world + } else if (stack.isEmpty()) { + this.removeItem(slot, 1); + } +@@ -119,7 +167,7 @@ + + @Override + public int getMaxStackSize() { +- return 1; ++ return maxStack; // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/CommandBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/CommandBlockEntity.java.patch new file mode 100644 index 0000000000..08d8c11523 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/CommandBlockEntity.java.patch @@ -0,0 +1,17 @@ +--- a/net/minecraft/world/level/block/entity/CommandBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/CommandBlockEntity.java +@@ -18,7 +20,14 @@ + private boolean auto; + private boolean conditionMet; + private final BaseCommandBlock commandBlock = new BaseCommandBlock() { ++ // CraftBukkit start + @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return new org.bukkit.craftbukkit.command.CraftBlockCommandSender(wrapper, CommandBlockEntity.this); ++ } ++ // CraftBukkit end ++ ++ @Override + public void setCommand(String command) { + super.setCommand(command); + CommandBlockEntity.this.setChanged(); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/ConduitBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/ConduitBlockEntity.java.patch new file mode 100644 index 0000000000..7f39d91040 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/ConduitBlockEntity.java.patch @@ -0,0 +1,74 @@ +--- a/net/minecraft/world/level/block/entity/ConduitBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/ConduitBlockEntity.java +@@ -25,6 +26,10 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class ConduitBlockEntity extends BlockEntity { + private static final int BLOCK_REFRESH_RATE = 2; +@@ -167,19 +190,22 @@ + } + + private static void applyEffects(Level level, BlockPos pos, List positions) { +- int size = positions.size(); +- int i = size / 7 * 16; +- int x = pos.getX(); +- int y = pos.getY(); +- int z = pos.getZ(); +- AABB aABB = new AABB((double)x, (double)y, (double)z, (double)(x + 1), (double)(y + 1), (double)(z + 1)) +- .inflate((double)i) +- .expandTowards(0.0, (double)level.getHeight(), 0.0); +- List entitiesOfClass = level.getEntitiesOfClass(Player.class, aABB); +- if (!entitiesOfClass.isEmpty()) { +- for (Player player : entitiesOfClass) { +- if (pos.closerThan(player.blockPosition(), (double)i) && player.isInWaterOrRain()) { +- player.addEffect(new MobEffectInstance(MobEffects.CONDUIT_POWER, 260, 0, true, true)); ++ int i = positions.size(); ++ int j = i / 7 * 16; ++ int k = pos.getX(); ++ int l = pos.getY(); ++ int i1 = pos.getZ(); ++ AABB axisalignedbb = (new AABB((double) k, (double) l, (double) i1, (double) (k + 1), (double) (l + 1), (double) (i1 + 1))).inflate((double) j).expandTowards(0.0D, (double) level.getHeight(), 0.0D); ++ List list1 = level.getEntitiesOfClass(Player.class, axisalignedbb); ++ ++ if (!list1.isEmpty()) { ++ Iterator iterator = list1.iterator(); ++ ++ while (iterator.hasNext()) { ++ Player entityhuman = (Player) iterator.next(); ++ ++ if (pos.closerThan(entityhuman.blockPosition(), (double) j) && entityhuman.isInWaterOrRain()) { ++ entityhuman.addEffect(new MobEffectInstance(MobEffects.CONDUIT_POWER, 260, 0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONDUIT); // CraftBukkit + } + } + } +@@ -205,17 +234,13 @@ + } + + if (blockEntity.destroyTarget != null) { +- level.playSound( +- null, +- blockEntity.destroyTarget.getX(), +- blockEntity.destroyTarget.getY(), +- blockEntity.destroyTarget.getZ(), +- SoundEvents.CONDUIT_ATTACK_TARGET, +- SoundSource.BLOCKS, +- 1.0F, +- 1.0F +- ); +- blockEntity.destroyTarget.hurt(level.damageSources().magic(), 4.0F); ++ // CraftBukkit start ++ CraftEventFactory.blockDamage = CraftBlock.at(level, pos); ++ if (blockEntity.destroyTarget.hurt(level.damageSources().magic(), 4.0F)) { ++ level.playSound((Player) null, blockEntity.destroyTarget.getX(), blockEntity.destroyTarget.getY(), blockEntity.destroyTarget.getZ(), SoundEvents.CONDUIT_ATTACK_TARGET, SoundSource.BLOCKS, 1.0F, 1.0F); ++ } ++ CraftEventFactory.blockDamage = null; ++ // CraftBukkit end + } + + if (livingEntity != blockEntity.destroyTarget) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java.patch new file mode 100644 index 0000000000..3c36db0c9e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java.patch @@ -0,0 +1,94 @@ +--- a/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java ++++ b/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java +@@ -11,6 +13,7 @@ + public abstract class ContainerOpenersCounter { + private static final int CHECK_TICK_DELAY = 5; + private int openCount; ++ public boolean opened; // CraftBukkit + + protected abstract void onOpen(Level level, BlockPos pos, BlockState state); + +@@ -18,10 +21,38 @@ + + protected abstract void openerCountChanged(Level level, BlockPos pos, BlockState state, int count, int openCount); + ++ protected abstract void openerCountChanged(Level level, BlockPos pos, IBlockData state, int count, int openCount); ++ ++ // CraftBukkit start ++ public void onAPIOpen(Level world, BlockPos blockposition, IBlockData iblockdata) { ++ onOpen(world, blockposition, iblockdata); ++ } ++ ++ public void onAPIClose(Level world, BlockPos blockposition, IBlockData iblockdata) { ++ onClose(world, blockposition, iblockdata); ++ } ++ ++ public void openerAPICountChanged(Level world, BlockPos blockposition, IBlockData iblockdata, int i, int j) { ++ openerCountChanged(world, blockposition, iblockdata, i, j); ++ } ++ // CraftBukkit end ++ + protected abstract boolean isOwnContainer(Player player); + +- public void incrementOpeners(Player player, Level level, BlockPos pos, BlockState state) { ++ public void incrementOpeners(Player player, Level level, BlockPos pos, IBlockData state) { ++ int oldPower = Math.max(0, Math.min(15, this.openCount)); // CraftBukkit - Get power before new viewer is added + int i = this.openCount++; ++ ++ // CraftBukkit start - Call redstone event ++ if (level.getBlockState(pos).is(net.minecraft.world.level.block.Blocks.TRAPPED_CHEST)) { ++ int newPower = Math.max(0, Math.min(15, this.openCount)); ++ ++ if (oldPower != newPower) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(level, pos, oldPower, newPower); ++ } ++ } ++ // CraftBukkit end ++ + if (i == 0) { + this.onOpen(level, pos, state); + level.gameEvent(player, GameEvent.CONTAINER_OPEN, pos); +@@ -31,8 +62,20 @@ + this.openerCountChanged(level, pos, state, i, this.openCount); + } + +- public void decrementOpeners(Player player, Level level, BlockPos pos, BlockState state) { ++ public void decrementOpeners(Player player, Level level, BlockPos pos, IBlockData state) { ++ int oldPower = Math.max(0, Math.min(15, this.openCount)); // CraftBukkit - Get power before new viewer is added + int i = this.openCount--; ++ ++ // CraftBukkit start - Call redstone event ++ if (level.getBlockState(pos).is(net.minecraft.world.level.block.Blocks.TRAPPED_CHEST)) { ++ int newPower = Math.max(0, Math.min(15, this.openCount)); ++ ++ if (oldPower != newPower) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(level, pos, oldPower, newPower); ++ } ++ } ++ // CraftBukkit end ++ + if (this.openCount == 0) { + this.onClose(level, pos, state); + level.gameEvent(player, GameEvent.CONTAINER_CLOSE, pos); +@@ -57,12 +94,15 @@ + return level.getEntities(EntityTypeTest.forClass(Player.class), aABB, this::isOwnContainer).size(); + } + +- public void recheckOpeners(Level level, BlockPos pos, BlockState state) { +- int openCount = this.getOpenCount(level, pos); +- int i = this.openCount; +- if (i != openCount) { +- boolean flag = openCount != 0; +- boolean flag1 = i != 0; ++ public void recheckOpeners(Level level, BlockPos pos, IBlockData state) { ++ int i = this.getOpenCount(level, pos); ++ if (opened) i++; // CraftBukkit - add dummy count from API ++ int j = this.openCount; ++ ++ if (j != i) { ++ boolean flag = i != 0; ++ boolean flag1 = j != 0; ++ + if (flag && !flag1) { + this.onOpen(level, pos, state); + level.gameEvent(null, GameEvent.CONTAINER_OPEN, pos); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/CrafterBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/CrafterBlockEntity.java.patch new file mode 100644 index 0000000000..8735859759 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/CrafterBlockEntity.java.patch @@ -0,0 +1,91 @@ +--- a/net/minecraft/world/level/block/entity/CrafterBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/CrafterBlockEntity.java +@@ -20,7 +21,14 @@ + import net.minecraft.world.level.block.CrafterBlock; + import net.minecraft.world.level.block.state.BlockState; + +-public class CrafterBlockEntity extends RandomizableContainerBlockEntity implements CraftingContainer { ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ ++public class CrafterBlockEntity extends RandomizableContainerBlockEntity implements InventoryCrafting { ++ + public static final int CONTAINER_WIDTH = 3; + public static final int CONTAINER_HEIGHT = 3; + public static final int CONTAINER_SIZE = 9; +@@ -28,23 +36,61 @@ + public static final int SLOT_ENABLED = 0; + public static final int DATA_TRIGGERED = 9; + public static final int NUM_DATA = 10; +- private NonNullList items = NonNullList.withSize(9, ItemStack.EMPTY); +- private int craftingTicksRemaining = 0; +- protected final ContainerData containerData = new ContainerData() { +- private final int[] slotStates = new int[9]; +- private int triggered = 0; ++ private NonNullList items; ++ public int craftingTicksRemaining; ++ protected final ContainerData containerData; ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList<>(); ++ private int maxStack = 1; + + @Override + public int get(int index) { + return index == 9 ? this.triggered : this.slotStates[index]; + } + +- @Override +- public void set(int index, int value) { +- if (index == 9) { +- this.triggered = value; +- } else { +- this.slotStates[index] = value; ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ @Override ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ } ++ // CraftBukkit end ++ ++ public CrafterBlockEntity(BlockPos blockposition, IBlockData iblockdata) { ++ super(BlockEntityType.CRAFTER, blockposition, iblockdata); ++ this.items = NonNullList.withSize(9, ItemStack.EMPTY); ++ this.craftingTicksRemaining = 0; ++ this.containerData = new ContainerData() { ++ private final int[] slotStates = new int[9]; ++ private int triggered = 0; ++ ++ @Override ++ public int get(int index) { ++ return index == 9 ? this.triggered : this.slotStates[index]; + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java.patch new file mode 100644 index 0000000000..29c15bb99a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java +@@ -20,7 +21,59 @@ + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.ticks.ContainerSingleItem; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class DecoratedPotBlockEntity extends BlockEntity implements RandomizableContainer, ContainerSingleItem { ++ ++ // CraftBukkit start - add fields and methods ++ public List transaction = new ArrayList<>(); ++ private int maxStack = MAX_STACK; ++ ++ @Override ++ public List getContents() { ++ return Arrays.asList(this.item); ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ @Override ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return CraftLocation.toBukkit(worldPosition, level.getWorld()); ++ } ++ // CraftBukkit end ++ + public static final String TAG_SHERDS = "sherds"; + public static final String TAG_ITEM = "item"; + public static final int EVENT_POT_WOBBLES = 1; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/DispenserBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/DispenserBlockEntity.java.patch new file mode 100644 index 0000000000..d341480175 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/DispenserBlockEntity.java.patch @@ -0,0 +1,51 @@ +--- a/net/minecraft/world/level/block/entity/DispenserBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/DispenserBlockEntity.java +@@ -12,11 +13,47 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.state.BlockState; + ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class DispenserBlockEntity extends RandomizableContainerBlockEntity { + public static final int CONTAINER_SIZE = 9; + private NonNullList items = NonNullList.withSize(9, ItemStack.EMPTY); + +- protected DispenserBlockEntity(BlockEntityType type, BlockPos pos, BlockState blockState) { ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ ++ protected DispenserBlockEntity(BlockEntityType type, BlockPos pos, IBlockData blockState) { + super(type, pos, blockState); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/HopperBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/HopperBlockEntity.java.patch new file mode 100644 index 0000000000..becf7c3ca2 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/HopperBlockEntity.java.patch @@ -0,0 +1,231 @@ +--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java +@@ -29,6 +31,17 @@ + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.Shapes; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.event.inventory.HopperInventorySearchEvent; ++import org.bukkit.event.inventory.InventoryMoveItemEvent; ++import org.bukkit.event.inventory.InventoryPickupItemEvent; ++import org.bukkit.inventory.Inventory; ++// CraftBukkit end + + public class HopperBlockEntity extends RandomizableContainerBlockEntity implements Hopper { + public static final int MOVE_ITEM_SPEED = 8; +@@ -37,7 +51,37 @@ + private int cooldownTime = -1; + private long tickedGameTime; + +- public HopperBlockEntity(BlockPos pos, BlockState blockState) { ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ ++ public HopperBlockEntity(BlockPos pos, IBlockData blockState) { + super(BlockEntityType.HOPPER, pos, blockState); + } + +@@ -103,7 +154,7 @@ + if (!blockEntity.isOnCooldown() && state.getValue(HopperBlock.ENABLED)) { + boolean flag = false; + if (!blockEntity.isEmpty()) { +- flag = ejectItems(level, pos, state, blockEntity); ++ flag = ejectItems(level, pos, state, (Container) blockEntity, blockEntity); // CraftBukkit + } + + if (!blockEntity.inventoryFull()) { +@@ -131,21 +188,46 @@ + return true; + } + +- private static boolean ejectItems(Level level, BlockPos pos, BlockState state, Container sourceContainer) { +- Container attachedContainer = getAttachedContainer(level, pos, state); +- if (attachedContainer == null) { ++ private static boolean ejectItems(Level world, BlockPos blockposition, IBlockData iblockdata, Container iinventory, HopperBlockEntity hopper) { // CraftBukkit ++ Container iinventory1 = getAttachedContainer(world, blockposition, iblockdata); ++ ++ if (iinventory1 == null) { + return false; + } else { + Direction opposite = state.getValue(HopperBlock.FACING).getOpposite(); + if (isFullContainer(attachedContainer, opposite)) { + return false; + } else { +- for (int i = 0; i < sourceContainer.getContainerSize(); i++) { +- if (!sourceContainer.getItem(i).isEmpty()) { +- ItemStack itemStack = sourceContainer.getItem(i).copy(); +- ItemStack itemStack1 = addItem(sourceContainer, attachedContainer, sourceContainer.removeItem(i, 1), opposite); +- if (itemStack1.isEmpty()) { +- attachedContainer.setChanged(); ++ for (int i = 0; i < iinventory.getContainerSize(); ++i) { ++ if (!iinventory.getItem(i).isEmpty()) { ++ ItemStack itemstack = iinventory.getItem(i).copy(); ++ // ItemStack itemstack1 = addItem(iinventory, iinventory1, iinventory.removeItem(i, 1), enumdirection); ++ ++ // CraftBukkit start - Call event when pushing items into other inventories ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.removeItem(i, 1)); ++ ++ Inventory destinationInventory; ++ // Have to special case large chests as they work oddly ++ if (iinventory1 instanceof CompoundContainer) { ++ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory1); ++ } else if (iinventory1.getOwner() != null) { ++ destinationInventory = iinventory1.getOwner().getInventory(); ++ } else { ++ destinationInventory = new CraftInventory(iinventory); ++ } ++ ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(iinventory.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ hopper.setItem(i, itemstack); ++ hopper.setCooldown(8); // Delay hopper checks ++ return false; ++ } ++ ItemStack itemstack1 = addItem(iinventory, iinventory1, CraftItemStack.asNMSCopy(event.getItem()), enumdirection); ++ // CraftBukkit end ++ ++ if (itemstack1.isEmpty()) { ++ iinventory1.setChanged(); + return true; + } + +@@ -193,11 +286,40 @@ + } + + private static boolean tryTakeInItemFromSlot(Hopper hopper, Container container, int slot, Direction direction) { +- ItemStack item = container.getItem(slot); +- if (!item.isEmpty() && canTakeItemFromContainer(hopper, container, item, slot, direction)) { +- ItemStack itemStack = item.copy(); +- ItemStack itemStack1 = addItem(container, hopper, container.removeItem(slot, 1), null); +- if (itemStack1.isEmpty()) { ++ ItemStack itemstack = container.getItem(slot); ++ ++ if (!itemstack.isEmpty() && canTakeItemFromContainer(hopper, container, itemstack, slot, direction)) { ++ ItemStack itemstack1 = itemstack.copy(); ++ // ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.removeItem(i, 1), (EnumDirection) null); ++ // CraftBukkit start - Call event on collection of items from inventories into the hopper ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(container.removeItem(slot, 1)); ++ ++ Inventory sourceInventory; ++ // Have to special case large chests as they work oddly ++ if (container instanceof CompoundContainer) { ++ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) container); ++ } else if (container.getOwner() != null) { ++ sourceInventory = container.getOwner().getInventory(); ++ } else { ++ sourceInventory = new CraftInventory(container); ++ } ++ ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack.clone(), hopper.getOwner().getInventory(), false); ++ ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ container.setItem(slot, itemstack1); ++ ++ if (hopper instanceof HopperBlockEntity) { ++ ((HopperBlockEntity) hopper).setCooldown(8); // Delay hopper checks ++ } ++ ++ return false; ++ } ++ ItemStack itemstack2 = addItem(container, hopper, CraftItemStack.asNMSCopy(event.getItem()), null); ++ // CraftBukkit end ++ ++ if (itemstack2.isEmpty()) { + container.setChanged(); + return true; + } +@@ -210,9 +332,17 @@ + + public static boolean addItem(Container container, ItemEntity item) { + boolean flag = false; +- ItemStack itemStack = item.getItem().copy(); +- ItemStack itemStack1 = addItem(null, container, itemStack, null); +- if (itemStack1.isEmpty()) { ++ // CraftBukkit start ++ InventoryPickupItemEvent event = new InventoryPickupItemEvent(container.getOwner().getInventory(), (org.bukkit.entity.Item) item.getBukkitEntity()); ++ item.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ ItemStack itemstack = item.getItem().copy(); ++ ItemStack itemstack1 = addItem((Container) null, container, itemstack, (Direction) null); ++ ++ if (itemstack1.isEmpty()) { + flag = true; + item.setItem(ItemStack.EMPTY); + item.discard(); +@@ -301,15 +465,38 @@ + return stack; + } + ++ // CraftBukkit start + @Nullable + private static Container getAttachedContainer(Level level, BlockPos pos, BlockState state) { + Direction direction = state.getValue(HopperBlock.FACING); + return getContainerAt(level, pos.relative(direction)); + } ++ // CraftBukkit end + + @Nullable ++ private static Container getAttachedContainer(Level level, BlockPos pos, IBlockData state) { ++ Direction enumdirection = (Direction) state.getValue(HopperBlock.FACING); ++ ++ // CraftBukkit start ++ BlockPos searchPosition = pos.relative(enumdirection); ++ Container inventory = getContainerAt(level, pos.relative(enumdirection)); ++ ++ CraftBlock hopper = CraftBlock.at(level, pos); ++ CraftBlock searchBlock = CraftBlock.at(level, searchPosition); ++ return runHopperInventorySearchEvent(inventory, hopper, searchBlock, HopperInventorySearchEvent.ContainerType.DESTINATION); ++ // CraftBukkit end ++ } ++ ++ @Nullable + private static Container getSourceContainer(Level level, Hopper hopper) { +- return getContainerAt(level, hopper.getLevelX(), hopper.getLevelY() + 1.0, hopper.getLevelZ()); ++ // CraftBukkit start ++ Container inventory = getContainerAt(level, hopper.getLevelX(), hopper.getLevelY() + 1.0D, hopper.getLevelZ()); ++ ++ BlockPos blockPosition = BlockPos.containing(hopper.getLevelX(), hopper.getLevelY(), hopper.getLevelZ()); ++ CraftBlock hopper1 = CraftBlock.at(level, blockPosition); ++ CraftBlock container = CraftBlock.at(level, blockPosition.above()); ++ return runHopperInventorySearchEvent(inventory, hopper1, container, HopperInventorySearchEvent.ContainerType.SOURCE); ++ // CraftBukkit end + } + + public static List getItemsAtAndAbove(Level level, Hopper hopper) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java.patch new file mode 100644 index 0000000000..7c87f0c2bd --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java.patch @@ -0,0 +1,88 @@ +--- a/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java +@@ -21,15 +22,59 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.ticks.ContainerSingleItem; + ++// CraftBukkit start ++import java.util.Collections; ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class JukeboxBlockEntity extends BlockEntity implements Clearable, ContainerSingleItem { + private static final int SONG_END_PADDING = 20; + private ItemStack item = ItemStack.EMPTY; + private int ticksSinceLastEvent; +- private long tickCount; +- private long recordStartedTick; +- private boolean isPlaying; ++ public long tickCount; ++ public long recordStartedTick; ++ public boolean isPlaying; ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ public boolean opened; + +- public JukeboxBlockEntity(BlockPos pos, BlockState blockState) { ++ @Override ++ public List getContents() { ++ return Collections.singletonList(item); ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ } ++ // CraftBukkit end ++ ++ public JukeboxBlockEntity(BlockPos pos, IBlockData blockState) { + super(BlockEntityType.JUKEBOX, pos, blockState); + } + +@@ -138,7 +194,7 @@ + + @Override + public int getMaxStackSize() { +- return 1; ++ return maxStack; // CraftBukkit + } + + @Override +@@ -186,7 +247,11 @@ + @VisibleForTesting + public void setRecordWithoutPlaying(ItemStack stack) { + this.item = stack; +- this.level.updateNeighborsAt(this.getBlockPos(), this.getBlockState().getBlock()); ++ // CraftBukkit start - add null check for level ++ if (level != null) { ++ this.level.updateNeighborsAt(this.getBlockPos(), this.getBlockState().getBlock()); ++ } ++ // CraftBukkit end + this.setChanged(); + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/LecternBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/LecternBlockEntity.java.patch new file mode 100644 index 0000000000..e75ceb1d54 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/LecternBlockEntity.java.patch @@ -0,0 +1,158 @@ +--- a/net/minecraft/world/level/block/entity/LecternBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/LecternBlockEntity.java +@@ -23,14 +24,73 @@ + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.block.Lectern; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end + +-public class LecternBlockEntity extends BlockEntity implements Clearable, MenuProvider { ++public class LecternBlockEntity extends BlockEntity implements Clearable, ITileInventory, CommandSource { // CraftBukkit - ICommandListener ++ + public static final int DATA_PAGE = 0; + public static final int NUM_DATA = 1; + public static final int SLOT_BOOK = 0; + public static final int NUM_SLOTS = 1; +- private final Container bookAccess = new Container() { ++ // CraftBukkit start - add fields and methods ++ public final Container bookAccess = new LecternInventory(); ++ public class LecternInventory implements Container { ++ ++ public List transaction = new ArrayList<>(); ++ private int maxStack = 1; ++ + @Override ++ public List getContents() { ++ return Arrays.asList(book); ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return CraftLocation.toBukkit(worldPosition, level.getWorld()); ++ } ++ ++ @Override ++ public InventoryHolder getOwner() { ++ return (Lectern) LecternBlockEntity.this.getOwner(); ++ } ++ ++ public LecternBlockEntity getLectern() { ++ return LecternBlockEntity.this; ++ } ++ // CraftBukkit end ++ ++ @Override + public int getContainerSize() { + return 1; + } +@@ -72,12 +134,14 @@ + } + + @Override ++ // CraftBukkit start + public void setItem(int slot, ItemStack stack) { + } ++ // CraftBukkit end + + @Override + public int getMaxStackSize() { +- return 1; ++ return maxStack; // CraftBukkit + } + + @Override +@@ -155,7 +227,7 @@ + if (i != this.page) { + this.page = i; + this.setChanged(); +- LecternBlock.signalPageChange(this.getLevel(), this.getBlockPos(), this.getBlockState()); ++ if (this.level != null) LecternBlock.signalPageChange(this.getLevel(), this.getBlockPos(), this.getBlockState()); // CraftBukkit + } + } + +@@ -176,6 +250,32 @@ + return stack; + } + ++ // CraftBukkit start ++ @Override ++ public void sendSystemMessage(Component component) { ++ } ++ ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return wrapper.getEntity() != null ? wrapper.getEntity().getBukkitSender(wrapper) : new org.bukkit.craftbukkit.command.CraftBlockCommandSender(wrapper, this); ++ } ++ ++ @Override ++ public boolean acceptsSuccess() { ++ return false; ++ } ++ ++ @Override ++ public boolean acceptsFailure() { ++ return false; ++ } ++ ++ @Override ++ public boolean shouldInformAdmins() { ++ return false; ++ } ++ ++ // CraftBukkit end + private CommandSourceStack createCommandSourceStack(@Nullable Player player) { + String string; + Component component; +@@ -187,8 +288,10 @@ + component = player.getDisplayName(); + } + +- Vec3 vec3 = Vec3.atCenterOf(this.worldPosition); +- return new CommandSourceStack(CommandSource.NULL, vec3, Vec2.ZERO, (ServerLevel)this.level, 2, string, component, this.level.getServer(), player); ++ Vec3 vec3d = Vec3.atCenterOf(this.worldPosition); ++ ++ // CraftBukkit - this ++ return new CommandSourceStack(this, vec3d, Vec2.ZERO, (ServerLevel) this.level, 2, s, (Component) object, this.level.getServer(), player); + } + + @Override +@@ -225,7 +329,7 @@ + + @Override + public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { +- return new LecternMenu(containerId, this.bookAccess, this.dataAccess); ++ return new LecternMenu(containerId, this.bookAccess, this.dataAccess, playerInventory); // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java.patch new file mode 100644 index 0000000000..0412fb5179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java +@@ -29,14 +32,18 @@ + public SculkCatalystBlockEntity(BlockPos pos, BlockState blockState) { + super(BlockEntityType.SCULK_CATALYST, pos, blockState); + this.catalystListener = new SculkCatalystBlockEntity.CatalystListener(blockState, new BlockPositionSource(pos)); ++ catalystListener.level = level; // CraftBukkit + } + +- public static void serverTick(Level level, BlockPos pos, BlockState state, SculkCatalystBlockEntity sculkCatalyst) { ++ public static void serverTick(Level level, BlockPos pos, IBlockData state, SculkCatalystBlockEntity sculkCatalyst) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = sculkCatalyst.getBlockPos(); // CraftBukkit - SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep. + sculkCatalyst.catalystListener.getSculkSpreader().updateCursors(level, pos, level.getRandom(), true); ++ org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = null; // CraftBukkit + } + + @Override + public void load(CompoundTag tag) { ++ super.load(tag); // CraftBukkit - SPIGOT-7393: Load super Bukkit data + this.catalystListener.sculkSpreader.load(tag); + } + +@@ -56,11 +64,13 @@ + final SculkSpreader sculkSpreader; + private final BlockState blockState; + private final PositionSource positionSource; ++ private Level level; // CraftBukkit + + public CatalystListener(BlockState blockState, PositionSource positionSource) { + this.blockState = blockState; + this.positionSource = positionSource; + this.sculkSpreader = SculkSpreader.createLevelSpreader(); ++ this.sculkSpreader.level = level; // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java.patch new file mode 100644 index 0000000000..ca6c1febb6 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java.patch @@ -0,0 +1,73 @@ +--- a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java +@@ -30,6 +31,10 @@ + import net.minecraft.world.level.material.PushReaction; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end + + public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity implements WorldlyContainer { + public static final int COLUMNS = 9; +@@ -49,7 +55,38 @@ + @Nullable + private final DyeColor color; + +- public ShulkerBoxBlockEntity(@Nullable DyeColor color, BlockPos pos, BlockState blockState) { ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ public boolean opened; ++ ++ public List getContents() { ++ return this.itemStacks; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ ++ public ShulkerBoxBlockEntity(@Nullable DyeColor color, BlockPos pos, IBlockData blockState) { + super(BlockEntityType.SHULKER_BOX, pos, blockState); + this.color = color; + } +@@ -165,7 +206,8 @@ + this.openCount = 0; + } + +- this.openCount++; ++ ++this.openCount; ++ if (opened) return; // CraftBukkit - only animate if the ShulkerBox hasn't been forced open already by an API call. + this.level.blockEvent(this.worldPosition, this.getBlockState().getBlock(), 1, this.openCount); + if (this.openCount == 1) { + this.level.gameEvent(player, GameEvent.CONTAINER_OPEN, this.worldPosition); +@@ -178,7 +220,8 @@ + @Override + public void stopOpen(Player player) { + if (!this.remove && !player.isSpectator()) { +- this.openCount--; ++ --this.openCount; ++ if (opened) return; // CraftBukkit - only animate if the ShulkerBox hasn't been forced open already by an API call. + this.level.blockEvent(this.worldPosition, this.getBlockState().getBlock(), 1, this.openCount); + if (this.openCount <= 0) { + this.level.gameEvent(player, GameEvent.CONTAINER_CLOSE, this.worldPosition); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/SignBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/SignBlockEntity.java.patch new file mode 100644 index 0000000000..91afbab194 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/SignBlockEntity.java.patch @@ -0,0 +1,154 @@ +--- a/net/minecraft/world/level/block/entity/SignBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/SignBlockEntity.java +@@ -29,8 +33,15 @@ + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; ++import org.bukkit.block.sign.Side; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.entity.Player; ++import org.bukkit.event.block.SignChangeEvent; ++// CraftBukkit end + +-public class SignBlockEntity extends BlockEntity { ++public class SignBlockEntity extends BlockEntity implements CommandSource { // CraftBukkit - implements ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int MAX_TEXT_LINE_WIDTH = 90; + private static final int TEXT_LINE_HEIGHT = 10; +@@ -142,11 +177,14 @@ + + public void updateSignText(Player player, boolean isFrontText, List filteredText) { + if (!this.isWaxed() && player.getUUID().equals(this.getPlayerWhoMayEdit()) && this.level != null) { +- this.updateText(signText -> this.setMessages(player, filteredText, signText), isFrontText); +- this.setAllowedPlayerEditor(null); ++ this.updateText((signtext) -> { ++ return this.setMessages(player, filteredText, signtext, isFrontText); // CraftBukkit ++ }, isFrontText); ++ this.setAllowedPlayerEditor((UUID) null); + this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3); + } else { +- LOGGER.warn("Player {} just tried to change non-editable sign", player.getName().getString()); ++ SignBlockEntity.LOGGER.warn("Player {} just tried to change non-editable sign", player.getName().getString()); ++ ((ServerPlayer) player).connection.send(this.getUpdatePacket()); // CraftBukkit + } + } + +@@ -155,12 +194,14 @@ + return this.setText(updater.apply(text), isFrontText); + } + +- private SignText setMessages(Player player, List filteredText, SignText text) { +- for (int i = 0; i < filteredText.size(); i++) { +- FilteredText filteredText1 = filteredText.get(i); +- Style style = text.getMessage(i, player.isTextFilteringEnabled()).getStyle(); +- if (player.isTextFilteringEnabled()) { +- text = text.setMessage(i, Component.literal(filteredText1.filteredOrEmpty()).setStyle(style)); ++ private SignText setMessages(net.minecraft.world.entity.player.Player entityhuman, List list, SignText signtext, boolean front) { // CraftBukkit ++ SignText originalText = signtext; // CraftBukkit ++ for (int i = 0; i < list.size(); ++i) { ++ FilteredText filteredtext = (FilteredText) list.get(i); ++ Style chatmodifier = signtext.getMessage(i, entityhuman.isTextFilteringEnabled()).getStyle(); ++ ++ if (entityhuman.isTextFilteringEnabled()) { ++ signtext = signtext.setMessage(i, Component.literal(filteredtext.filteredOrEmpty()).setStyle(chatmodifier)); + } else { + text = text.setMessage( + i, Component.literal(filteredText1.raw()).setStyle(style), Component.literal(filteredText1.filteredOrEmpty()).setStyle(style) +@@ -168,7 +207,30 @@ + } + } + +- return text; ++ // CraftBukkit start ++ Player player = ((ServerPlayer) entityhuman).getBukkitEntity(); ++ String[] lines = new String[4]; ++ ++ for (int i = 0; i < list.size(); ++i) { ++ lines[i] = CraftChatMessage.fromComponent(signtext.getMessage(i, entityhuman.isTextFilteringEnabled())); ++ } ++ ++ SignChangeEvent event = new SignChangeEvent(CraftBlock.at(this.level, this.worldPosition), player, lines.clone(), (front) ? Side.FRONT : Side.BACK); ++ entityhuman.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return originalText; ++ } ++ ++ Component[] components = org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()); ++ for (int i = 0; i < components.length; i++) { ++ if (!Objects.equals(lines[i], event.getLine(i))) { ++ signtext = signtext.setMessage(i, components[i]); ++ } ++ } ++ // CraftBukkit end ++ ++ return signtext; + } + + public boolean setText(SignText text, boolean isFrontText) { +@@ -214,13 +280,40 @@ + return flag; + } + +- private static CommandSourceStack createCommandSourceStack(@Nullable Player player, Level level, BlockPos pos) { +- String string = player == null ? "Sign" : player.getName().getString(); +- Component component = (Component)(player == null ? Component.literal("Sign") : player.getDisplayName()); +- return new CommandSourceStack(CommandSource.NULL, Vec3.atCenterOf(pos), Vec2.ZERO, (ServerLevel)level, 2, string, component, level.getServer(), player); ++ // CraftBukkit start ++ @Override ++ public void sendSystemMessage(Component component) {} ++ ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return wrapper.getEntity() != null ? wrapper.getEntity().getBukkitSender(wrapper) : new org.bukkit.craftbukkit.command.CraftBlockCommandSender(wrapper, this); + } + + @Override ++ public boolean acceptsSuccess() { ++ return false; ++ } ++ ++ @Override ++ public boolean acceptsFailure() { ++ return false; ++ } ++ ++ @Override ++ public boolean shouldInformAdmins() { ++ return false; ++ } ++ ++ private CommandSourceStack createCommandSourceStack(@Nullable net.minecraft.world.entity.player.Player level, Level pos, BlockPos blockposition) { ++ // CraftBukkit end ++ String s = level == null ? "Sign" : level.getName().getString(); ++ Object object = level == null ? Component.literal("Sign") : level.getDisplayName(); ++ ++ // CraftBukkit - this ++ return new CommandSourceStack(this, Vec3.atCenterOf(blockposition), Vec2.ZERO, (ServerLevel) pos, 2, s, (Component) object, pos.getServer(), level); ++ } ++ ++ @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } +@@ -241,12 +334,17 @@ + + @Nullable + public UUID getPlayerWhoMayEdit() { ++ // CraftBukkit start - unnecessary sign ticking removed, so do this lazily ++ if (this.level != null && this.playerWhoMayEdit != null) { ++ clearInvalidPlayerWhoMayEdit(this, this.level, this.playerWhoMayEdit); ++ } ++ // CraftBukkit end + return this.playerWhoMayEdit; + } + + private void markUpdated() { + this.setChanged(); +- this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3); ++ if (this.level != null) this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3); // CraftBukkit - skip notify if world is null (SPIGOT-5122) + } + + public boolean isWaxed() { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/SkullBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/SkullBlockEntity.java.patch new file mode 100644 index 0000000000..5faaf60c6f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/SkullBlockEntity.java.patch @@ -0,0 +1,28 @@ +--- a/net/minecraft/world/level/block/entity/SkullBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/SkullBlockEntity.java +@@ -184,10 +189,21 @@ + } + } + +- public static void resolveGameProfile(CompoundTag compoundTag) { +- String string = compoundTag.getString("SkullOwner"); +- if (!Util.isBlank(string)) { +- resolveGameProfile(compoundTag, string); ++ public static void resolveGameProfile(CompoundTag nbttagcompound) { ++ String s = nbttagcompound.getString("SkullOwner"); ++ ++ if (!Util.isBlank(s)) { ++ resolveGameProfile(nbttagcompound, s); ++ // CraftBukkit start ++ } else { ++ net.minecraft.nbt.ListTag textures = nbttagcompound.getCompound("SkullOwner").getCompound("Properties").getList("textures", 10); // Safe due to method contracts ++ for (int i = 0; i < textures.size(); i++) { ++ if (textures.get(i) instanceof CompoundTag && !((CompoundTag) textures.get(i)).contains("Signature", 8) && ((CompoundTag) textures.get(i)).getString("Value").trim().isEmpty()) { ++ nbttagcompound.remove("SkullOwner"); ++ break; ++ } ++ } ++ // CraftBukkit end + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java.patch new file mode 100644 index 0000000000..2d316c42ef --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java.patch @@ -0,0 +1,71 @@ +--- a/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +@@ -32,6 +33,11 @@ + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.player.PlayerTeleportEvent; ++// CraftBukkit end + + public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -158,12 +173,14 @@ + if (level instanceof ServerLevel && !blockEntity.isCoolingDown()) { + ServerLevel serverLevel = (ServerLevel)level; + blockEntity.teleportCooldown = 100; +- if (blockEntity.exitPortal == null && level.dimension() == Level.END) { +- BlockPos blockPos = findOrCreateValidTeleportPos(serverLevel, pos); +- blockPos = blockPos.above(10); +- LOGGER.debug("Creating portal at {}", blockPos); +- spawnGatewayPortal(serverLevel, blockPos, EndGatewayConfiguration.knownExit(pos, false)); +- blockEntity.exitPortal = blockPos; ++ BlockPos blockposition1; ++ ++ if (blockEntity.exitPortal == null && level.getTypeKey() == LevelStem.END) { // CraftBukkit - work in alternate worlds ++ blockposition1 = findOrCreateValidTeleportPos(worldserver, pos); ++ blockposition1 = blockposition1.above(10); ++ TheEndGatewayBlockEntity.LOGGER.debug("Creating portal at {}", blockposition1); ++ spawnGatewayPortal(worldserver, blockposition1, EndGatewayConfiguration.knownExit(pos, false)); ++ blockEntity.exitPortal = blockposition1; + } + + if (blockEntity.exitPortal != null) { +@@ -185,8 +204,34 @@ + entity1 = entity.getRootVehicle(); + } + ++ // CraftBukkit start - Fire PlayerTeleportEvent/EntityTeleportEvent ++ if (entity1 instanceof ServerPlayer) { ++ org.bukkit.craftbukkit.entity.CraftPlayer player = (CraftPlayer) entity1.getBukkitEntity(); ++ org.bukkit.Location location = CraftLocation.toBukkit(blockposition1, level.getWorld()).add(0.5D, 0.5D, 0.5D); ++ location.setPitch(player.getLocation().getPitch()); ++ location.setYaw(player.getLocation().getYaw()); ++ ++ PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.END_GATEWAY); ++ Bukkit.getPluginManager().callEvent(teleEvent); ++ if (teleEvent.isCancelled()) { ++ return; ++ } ++ ++ entity1.setPortalCooldown(); ++ ((ServerPlayer) entity1).connection.teleport(teleEvent.getTo()); ++ triggerCooldown(level, pos, state, blockEntity); // CraftBukkit - call at end of method ++ return; ++ ++ } ++ ++ org.bukkit.event.entity.EntityTeleportEvent teleEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTeleportEvent(entity1, blockposition1.getX() + 0.5, blockposition1.getY() + 0.5, blockposition1.getZ() + 0.5); ++ if (teleEvent.isCancelled()) { ++ return; ++ } ++ + entity1.setPortalCooldown(); +- entity1.teleportToWithTicket((double)blockPos.getX() + 0.5, (double)blockPos.getY(), (double)blockPos.getZ() + 0.5); ++ entity1.teleportToWithTicket(teleEvent.getTo().getX(), teleEvent.getTo().getY(), teleEvent.getTo().getZ()); ++ // CraftBukkit end + } + + triggerCooldown(level, pos, state, blockEntity); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/piston/PistonBaseBlock.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/piston/PistonBaseBlock.java.patch new file mode 100644 index 0000000000..e4ab11fddd --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/piston/PistonBaseBlock.java.patch @@ -0,0 +1,54 @@ +--- a/net/minecraft/world/level/block/piston/PistonBaseBlock.java ++++ b/net/minecraft/world/level/block/piston/PistonBaseBlock.java +@@ -39,6 +40,13 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import com.google.common.collect.ImmutableList; ++import java.util.AbstractList; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockPistonRetractEvent; ++import org.bukkit.event.block.BlockPistonExtendEvent; ++// CraftBukkit end + + public class PistonBaseBlock extends DirectionalBlock { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +@@ -143,7 +158,19 @@ + i = 2; + } + +- level.blockEvent(pos, this, i, direction.get3DDataValue()); ++ // CraftBukkit start ++ if (!this.isSticky) { ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ BlockPistonRetractEvent event = new BlockPistonRetractEvent(block, ImmutableList.of(), CraftBlock.notchToBlockFace(enumdirection)); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // PAIL: checkME - what happened to setTypeAndData? ++ // CraftBukkit end ++ level.blockEvent(pos, this, b0, enumdirection.get3DDataValue()); + } + } + +@@ -303,6 +350,8 @@ + BlockState[] blockStates = new BlockState[toPush.size() + toDestroy.size()]; + Direction direction = extending ? facing : facing.getOpposite(); + int i = 0; ++ // CraftBukkit start ++ final org.bukkit.block.Block bblock = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); + + for (int i1 = toDestroy.size() - 1; i1 >= 0; i1--) { + BlockPos blockPos2 = toDestroy.get(i1); +@@ -328,6 +391,7 @@ + level.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(blockPos2, blockState2, list.get(i1), facing, extending, false)); + blockStates[i++] = blockState1; + } ++ // CraftBukkit end + + if (extending) { + PistonType pistonType = this.isSticky ? PistonType.STICKY : PistonType.DEFAULT; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/state/BlockBehaviour.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/state/BlockBehaviour.java.patch new file mode 100644 index 0000000000..9179d48363 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/block/state/BlockBehaviour.java.patch @@ -0,0 +1,28 @@ +--- a/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -175,15 +182,16 @@ + if (!blockState.isAir() && explosion.getBlockInteraction() != Explosion.BlockInteraction.TRIGGER_BLOCK) { + Block block = blockState.getBlock(); + boolean flag = explosion.getIndirectSourceEntity() instanceof Player; +- if (block.dropFromExplosion(explosion) && level instanceof ServerLevel serverLevel) { +- BlockEntity blockEntity = blockState.hasBlockEntity() ? level.getBlockEntity(blockPos) : null; +- LootParams.Builder builder = new LootParams.Builder(serverLevel) +- .withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockPos)) +- .withParameter(LootContextParams.TOOL, ItemStack.EMPTY) +- .withOptionalParameter(LootContextParams.BLOCK_ENTITY, blockEntity) +- .withOptionalParameter(LootContextParams.THIS_ENTITY, explosion.getDirectSourceEntity()); +- if (explosion.getBlockInteraction() == Explosion.BlockInteraction.DESTROY_WITH_DECAY) { +- builder.withParameter(LootContextParams.EXPLOSION_RADIUS, explosion.radius()); ++ ++ if (block.dropFromExplosion(explosion) && world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ BlockEntity tileentity = iblockdata.hasBlockEntity() ? world.getBlockEntity(blockposition) : null; ++ LootParams.Builder lootparams_a = (new LootParams.Builder(worldserver)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockposition)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withOptionalParameter(LootContextParams.BLOCK_ENTITY, tileentity).withOptionalParameter(LootContextParams.THIS_ENTITY, explosion.getDirectSourceEntity()); ++ ++ // CraftBukkit start - add yield ++ if (explosion.yield < 1.0F) { ++ lootparams_a.withParameter(LootContextParams.EXPLOSION_RADIUS, 1.0F / explosion.yield); ++ // CraftBukkit end + } + + blockState.spawnAfterBreak(serverLevel, blockPos, ItemStack.EMPTY, flag); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/border/WorldBorder.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/border/WorldBorder.java.patch new file mode 100644 index 0000000000..2a18eb1563 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/border/WorldBorder.java.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/level/border/WorldBorder.java ++++ b/net/minecraft/world/level/border/WorldBorder.java +@@ -25,8 +27,9 @@ + private double centerX; + private double centerZ; + int absoluteMaxSize = 29999984; +- private WorldBorder.BorderExtent extent = new WorldBorder.StaticBorderExtent(5.999997E7F); +- public static final WorldBorder.Settings DEFAULT_SETTINGS = new WorldBorder.Settings(0.0, 0.0, 0.2, 5.0, 5, 15, 5.999997E7F, 0L, 0.0); ++ private WorldBorder.a extent = new WorldBorder.StaticBorderExtent(5.9999968E7D); ++ public static final WorldBorder.Settings DEFAULT_SETTINGS = new WorldBorder.Settings(0.0D, 0.0D, 0.2D, 5.0D, 5, 15, 5.9999968E7D, 0L, 0.0D); ++ public net.minecraft.server.level.ServerLevel world; // CraftBukkit + + public boolean isWithinBounds(BlockPos pos) { + return (double)(pos.getX() + 1) > this.getMinX() +@@ -154,6 +165,7 @@ + } + + public void addListener(BorderChangeListener listener) { ++ if (listeners.contains(listener)) return; // CraftBukkit + this.listeners.add(listener); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkAccess.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkAccess.java.patch new file mode 100644 index 0000000000..b8de6931b4 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkAccess.java.patch @@ -0,0 +1,77 @@ +--- a/net/minecraft/world/level/chunk/ChunkAccess.java ++++ b/net/minecraft/world/level/chunk/ChunkAccess.java +@@ -80,15 +82,12 @@ + protected final LevelHeightAccessor levelHeightAccessor; + protected final LevelChunkSection[] sections; + +- public ChunkAccess( +- ChunkPos chunkPos, +- UpgradeData upgradeData, +- LevelHeightAccessor levelHeightAccessor, +- Registry biomeRegistry, +- long inhabitedTime, +- @Nullable LevelChunkSection[] sections, +- @Nullable BlendingData blendingData +- ) { ++ // CraftBukkit start - SPIGOT-6814: move to IChunkAccess to account for 1.17 to 1.18 chunk upgrading. ++ private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry(); ++ public org.bukkit.craftbukkit.persistence.DirtyCraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.DirtyCraftPersistentDataContainer(DATA_TYPE_REGISTRY); ++ // CraftBukkit end ++ ++ public ChunkAccess(ChunkPos chunkPos, UpgradeData upgradeData, LevelHeightAccessor levelHeightAccessor, Registry biomeRegistry, long inhabitedTime, @Nullable LevelChunkSection[] achunksection, @Nullable BlendingData sections) { + this.chunkPos = chunkPos; + this.upgradeData = upgradeData; + this.levelHeightAccessor = levelHeightAccessor; +@@ -106,7 +105,11 @@ + } + + replaceMissingSections(biomeRegistry, this.sections); ++ // CraftBukkit start ++ this.biomeRegistry = biomeRegistry; + } ++ public final Registry biomeRegistry; ++ // CraftBukkit end + + private static void replaceMissingSections(Registry biomeRegistry, LevelChunkSection[] sections) { + for (int i = 0; i < sections.length; i++) { +@@ -263,10 +272,11 @@ + + public void setUnsaved(boolean unsaved) { + this.unsaved = unsaved; ++ if (!unsaved) this.persistentDataContainer.dirty(false); // CraftBukkit - SPIGOT-6814: chunk was saved, pdc is no longer dirty + } + + public boolean isUnsaved() { +- return this.unsaved; ++ return this.unsaved || this.persistentDataContainer.dirty(); // CraftBukkit - SPIGOT-6814: chunk is unsaved if pdc was mutated + } + + public abstract ChunkStatus getStatus(); +@@ -430,6 +452,27 @@ + } + } + ++ // CraftBukkit start ++ public void setBiome(int i, int j, int k, Holder biome) { ++ try { ++ int l = QuartPos.fromBlock(this.getMinBuildHeight()); ++ int i1 = l + QuartPos.fromBlock(this.getHeight()) - 1; ++ int j1 = Mth.clamp(j, l, i1); ++ int k1 = this.getSectionIndex(QuartPos.toBlock(j1)); ++ ++ this.sections[k1].setBiome(i & 3, j1 & 3, k & 3, biome); ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Setting biome"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Biome being set"); ++ ++ crashreportsystemdetails.setDetail("Location", () -> { ++ return CrashReportCategory.formatLocation(this, i, j, k); ++ }); ++ throw new ReportedException(crashreport); ++ } ++ } ++ // CraftBukkit end ++ + public void fillBiomesFromNoise(BiomeResolver resolver, Climate.Sampler sampler) { + ChunkPos pos = this.getPos(); + int i = QuartPos.fromBlock(pos.getMinBlockX()); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkGenerator.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkGenerator.java.patch new file mode 100644 index 0000000000..6e1646322f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkGenerator.java.patch @@ -0,0 +1,104 @@ +--- a/net/minecraft/world/level/chunk/ChunkGenerator.java ++++ b/net/minecraft/world/level/chunk/ChunkGenerator.java +@@ -314,19 +306,8 @@ + } + } + +- public void applyBiomeDecoration(WorldGenLevel level, ChunkAccess chunk, StructureManager structureManager) { +- ChunkPos pos = chunk.getPos(); +- if (!SharedConstants.debugVoidTerrain(pos)) { +- SectionPos sectionPos = SectionPos.of(pos, level.getMinSection()); +- BlockPos blockPos = sectionPos.origin(); +- Registry registry = level.registryAccess().registryOrThrow(Registries.STRUCTURE); +- Map> map = registry.stream().collect(Collectors.groupingBy(structure1 -> structure1.step().ordinal())); +- List list = this.featuresPerStep.get(); +- WorldgenRandom worldgenRandom = new WorldgenRandom(new XoroshiroRandomSource(RandomSupport.generateUniqueSeed())); +- long l = worldgenRandom.setDecorationSeed(level.getSeed(), blockPos.getX(), blockPos.getZ()); +- Set> set = new ObjectArraySet<>(); +- ChunkPos.rangeClosed(sectionPos.chunk(), 1).forEach(chunkPos -> { +- ChunkAccess chunk1 = level.getChunk(chunkPos.x, chunkPos.z); ++ public void addVanillaDecorations(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager) { // CraftBukkit ++ ChunkPos chunkcoordintpair = ichunkaccess.getPos(); + + for (LevelChunkSection levelChunkSection : chunk1.getSections()) { + levelChunkSection.getBiomes().getAll(set::add); +@@ -410,6 +439,33 @@ + } + } + ++ // CraftBukkit start ++ public void applyBiomeDecoration(WorldGenLevel level, ChunkAccess chunk, StructureManager structureManager) { ++ applyBiomeDecoration(level, chunk, structureManager, true); ++ } ++ ++ public void applyBiomeDecoration(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager, boolean vanilla) { ++ if (vanilla) { ++ addVanillaDecorations(generatoraccessseed, ichunkaccess, structuremanager); ++ } ++ ++ org.bukkit.World world = generatoraccessseed.getMinecraftWorld().getWorld(); ++ // only call when a populator is present (prevents unnecessary entity conversion) ++ if (!world.getPopulators().isEmpty()) { ++ org.bukkit.craftbukkit.generator.CraftLimitedRegion limitedRegion = new org.bukkit.craftbukkit.generator.CraftLimitedRegion(generatoraccessseed, ichunkaccess.getPos()); ++ int x = ichunkaccess.getPos().x; ++ int z = ichunkaccess.getPos().z; ++ for (org.bukkit.generator.BlockPopulator populator : world.getPopulators()) { ++ WorldgenRandom seededrandom = new WorldgenRandom(new net.minecraft.world.level.levelgen.LegacyRandomSource(generatoraccessseed.getSeed())); ++ seededrandom.setDecorationSeed(generatoraccessseed.getSeed(), x, z); ++ populator.populate(world, new org.bukkit.craftbukkit.util.RandomSourceWrapper.RandomWrapper(seededrandom), x, z, limitedRegion); ++ } ++ limitedRegion.saveEntities(); ++ limitedRegion.breakLink(); ++ } ++ } ++ // CraftBukkit end ++ + private static BoundingBox getWritableArea(ChunkAccess chunk) { + ChunkPos pos = chunk.getPos(); + int minBlockX = pos.getMinBlockX(); +@@ -545,26 +593,25 @@ + ); + } + +- private boolean tryGenerateStructure( +- StructureSet.StructureSelectionEntry structureSelectionEntry, +- StructureManager structureManager, +- RegistryAccess registryAccess, +- RandomState random, +- StructureTemplateManager structureTemplateManager, +- long seed, +- ChunkAccess chunk, +- ChunkPos chunkPos, +- SectionPos sectionPos +- ) { +- Structure structure = structureSelectionEntry.structure().value(); +- int i = fetchReferences(structureManager, chunk, sectionPos, structure); +- HolderSet holderSet = structure.biomes(); +- Predicate> predicate = holderSet::contains; +- StructureStart structureStart = structure.generate( +- registryAccess, this, this.biomeSource, random, structureTemplateManager, seed, chunkPos, i, chunk, predicate +- ); +- if (structureStart.isValid()) { +- structureManager.setStartForStructure(sectionPos, structure, structureStart, chunk); ++ private boolean tryGenerateStructure(StructureSet.a structureSelectionEntry, StructureManager structureManager, RegistryAccess registryAccess, RandomState random, StructureTemplateManager structureTemplateManager, long seed, ChunkAccess ichunkaccess, ChunkPos chunk, SectionPos chunkPos) { ++ Structure structure = (Structure) structureSelectionEntry.structure().value(); ++ int j = fetchReferences(structureManager, ichunkaccess, chunkPos, structure); ++ HolderSet holderset = structure.biomes(); ++ ++ Objects.requireNonNull(holderset); ++ Predicate> predicate = holderset::contains; ++ StructureStart structurestart = structure.generate(registryAccess, this, this.biomeSource, random, structureTemplateManager, seed, chunk, j, ichunkaccess, predicate); ++ ++ if (structurestart.isValid()) { ++ // CraftBukkit start ++ BoundingBox box = structurestart.getBoundingBox(); ++ org.bukkit.event.world.AsyncStructureSpawnEvent event = new org.bukkit.event.world.AsyncStructureSpawnEvent(structureManager.level.getMinecraftWorld().getWorld(), org.bukkit.craftbukkit.generator.structure.CraftStructure.minecraftToBukkit(structure, registryAccess), new org.bukkit.util.BoundingBox(box.minX(), box.minY(), box.minZ(), box.maxX(), box.maxY(), box.maxZ()), chunk.x, chunk.z); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return true; ++ } ++ // CraftBukkit end ++ structureManager.setStartForStructure(chunkPos, structure, structurestart, ichunkaccess); + return true; + } else { + return false; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkStatus.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkStatus.java.patch new file mode 100644 index 0000000000..0127726c74 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/ChunkStatus.java.patch @@ -0,0 +1,26 @@ +--- a/net/minecraft/world/level/chunk/ChunkStatus.java ++++ b/net/minecraft/world/level/chunk/ChunkStatus.java +@@ -31,14 +32,15 @@ + public class ChunkStatus { + public static final int MAX_STRUCTURE_DISTANCE = 8; + private static final EnumSet PRE_FEATURES = EnumSet.of(Heightmap.Types.OCEAN_FLOOR_WG, Heightmap.Types.WORLD_SURFACE_WG); +- public static final EnumSet POST_FEATURES = EnumSet.of( +- Heightmap.Types.OCEAN_FLOOR, Heightmap.Types.WORLD_SURFACE, Heightmap.Types.MOTION_BLOCKING, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES +- ); +- private static final ChunkStatus.LoadingTask PASSTHROUGH_LOAD_TASK = (status, level, structureTemplateManager, lightEngine, task, chunk) -> CompletableFuture.completedFuture( +- Either.left(chunk) +- ); +- public static final ChunkStatus EMPTY = registerSimple( +- "empty", null, -1, PRE_FEATURES, ChunkStatus.ChunkType.PROTOCHUNK, (status, level, chunkGenerator, neighboringChunks, loadingChunk) -> { ++ public static final EnumSet POST_FEATURES = EnumSet.of(Heightmap.Types.OCEAN_FLOOR, Heightmap.Types.WORLD_SURFACE, Heightmap.Types.MOTION_BLOCKING, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES); ++ private static final ChunkStatus.LoadingTask PASSTHROUGH_LOAD_TASK = (chunkstatus, worldserver, structuretemplatemanager, lightenginethreaded, function, ichunkaccess) -> { ++ return CompletableFuture.completedFuture(Either.left(ichunkaccess)); ++ }; ++ public static final ChunkStatus EMPTY = registerSimple("empty", (ChunkStatus) null, -1, ChunkStatus.PRE_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, list, ichunkaccess) -> { ++ }); ++ public static final ChunkStatus STRUCTURE_STARTS = register("structure_starts", ChunkStatus.EMPTY, 0, false, ChunkStatus.PRE_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, executor, worldserver, chunkgenerator, structuretemplatemanager, lightenginethreaded, function, list, ichunkaccess) -> { ++ if (worldserver.serverLevelData.worldGenOptions().generateStructures()) { // CraftBukkit ++ chunkgenerator.createStructures(worldserver.registryAccess(), worldserver.getChunkSource().getGeneratorState(), worldserver.structureManager(), ichunkaccess, structuretemplatemanager); + } + ); + public static final ChunkStatus STRUCTURE_STARTS = register( diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/DataLayer.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/DataLayer.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/DataLayer.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/LevelChunk.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/LevelChunk.java.patch new file mode 100644 index 0000000000..5cda59a305 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/LevelChunk.java.patch @@ -0,0 +1,235 @@ +--- a/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/net/minecraft/world/level/chunk/LevelChunk.java +@@ -70,9 +73,9 @@ + return ""; + } + }; +- private final Map tickersInLevel = Maps.newHashMap(); +- private boolean loaded; +- final Level level; ++ private final Map tickersInLevel; ++ public boolean loaded; ++ public final ServerLevel level; // CraftBukkit - type + @Nullable + private Supplier fullStatus; + @Nullable +@@ -85,20 +88,13 @@ + this(level, pos, UpgradeData.EMPTY, new LevelChunkTicks<>(), new LevelChunkTicks<>(), 0L, null, null, null); + } + +- public LevelChunk( +- Level level, +- ChunkPos pos, +- UpgradeData data, +- LevelChunkTicks blockTicks, +- LevelChunkTicks fluidTicks, +- long inhabitedTime, +- @Nullable LevelChunkSection[] sections, +- @Nullable LevelChunk.PostLoadProcessor postLoad, +- @Nullable BlendingData blendingData +- ) { +- super(pos, data, level, level.registryAccess().registryOrThrow(Registries.BIOME), inhabitedTime, sections, blendingData); +- this.level = level; +- this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap<>(); ++ public LevelChunk(Level level, ChunkPos pos, UpgradeData data, LevelChunkTicks blockTicks, LevelChunkTicks fluidTicks, long inhabitedTime, @Nullable LevelChunkSection[] achunksection, @Nullable LevelChunk.PostLoadProcessor sections, @Nullable BlendingData postLoad) { ++ super(pos, data, level, level.registryAccess().registryOrThrow(Registries.BIOME), inhabitedTime, achunksection, postLoad); ++ this.tickersInLevel = Maps.newHashMap(); ++ this.level = (ServerLevel) level; // CraftBukkit - type ++ this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap(); ++ Heightmap.Types[] aheightmap_type = Heightmap.Types.values(); ++ int j = aheightmap_type.length; + + for (Heightmap.Types types : Heightmap.Types.values()) { + if (ChunkStatus.FULL.heightmapsAfter().contains(types)) { +@@ -111,6 +109,11 @@ + this.fluidTicks = fluidTicks; + } + ++ // CraftBukkit start ++ public boolean mustNotSave; ++ public boolean needsDecoration; ++ // CraftBukkit end ++ + public LevelChunk(ServerLevel level, ProtoChunk chunk, @Nullable LevelChunk.PostLoadProcessor postLoad) { + this( + level, +@@ -146,6 +145,10 @@ + this.skyLightSources = chunk.skyLightSources; + this.setLightCorrect(chunk.isLightCorrect()); + this.unsaved = true; ++ this.needsDecoration = true; // CraftBukkit ++ // CraftBukkit start ++ this.persistentDataContainer = chunk.persistentDataContainer; // SPIGOT-6814: copy PDC to account for 1.17 to 1.18 chunk upgrading. ++ // CraftBukkit end + } + + @Override +@@ -231,13 +253,21 @@ + } + } + ++ // CraftBukkit start + @Nullable + @Override +- public BlockState setBlockState(BlockPos pos, BlockState state, boolean isMoving) { +- int y = pos.getY(); +- LevelChunkSection section = this.getSection(this.getSectionIndex(y)); +- boolean hasOnlyAir = section.hasOnlyAir(); +- if (hasOnlyAir && state.isAir()) { ++ public IBlockData setBlockState(BlockPos pos, IBlockData state, boolean isMoving) { ++ return this.setBlockState(pos, state, isMoving, true); ++ } ++ ++ @Nullable ++ public IBlockData setBlockState(BlockPos blockposition, IBlockData iblockdata, boolean flag, boolean doPlace) { ++ // CraftBukkit end ++ int i = blockposition.getY(); ++ LevelChunkSection chunksection = this.getSection(this.getSectionIndex(i)); ++ boolean flag1 = chunksection.hasOnlyAir(); ++ ++ if (flag1 && iblockdata.isAir()) { + return null; + } else { + int i = pos.getX() & 15; +@@ -276,8 +311,9 @@ + if (!section.getBlockState(i, i1, i2).is(block)) { + return null; + } else { +- if (!this.level.isClientSide) { +- state.onPlace(this.level, pos, blockState, isMoving); ++ // CraftBukkit - Don't place while processing the BlockPlaceEvent, unless it's a BlockContainer. Prevents blocks such as TNT from activating when cancelled. ++ if (!this.level.isClientSide && doPlace && (!this.level.captureBlockStates || block instanceof net.minecraft.world.level.block.BaseEntityBlock)) { ++ iblockdata.onPlace(this.level, blockposition, iblockdata1, flag); + } + + if (state.hasBlockEntity()) { +@@ -318,14 +356,22 @@ + } + + @Nullable +- public BlockEntity getBlockEntity(BlockPos pos, LevelChunk.EntityCreationType creationType) { +- BlockEntity blockEntity = this.blockEntities.get(pos); +- if (blockEntity == null) { +- CompoundTag compoundTag = this.pendingBlockEntities.remove(pos); +- if (compoundTag != null) { +- BlockEntity blockEntity1 = this.promotePendingBlockEntity(pos, compoundTag); +- if (blockEntity1 != null) { +- return blockEntity1; ++ public BlockEntity getBlockEntity(BlockPos pos, LevelChunk.EnumTileEntityState creationType) { ++ // CraftBukkit start ++ BlockEntity tileentity = level.capturedTileEntities.get(pos); ++ if (tileentity == null) { ++ tileentity = (BlockEntity) this.blockEntities.get(pos); ++ } ++ // CraftBukkit end ++ ++ if (tileentity == null) { ++ CompoundTag nbttagcompound = (CompoundTag) this.pendingBlockEntities.remove(pos); ++ ++ if (nbttagcompound != null) { ++ BlockEntity tileentity1 = this.promotePendingBlockEntity(pos, nbttagcompound); ++ ++ if (tileentity1 != null) { ++ return tileentity1; + } + } + } +@@ -378,6 +439,14 @@ + if (blockEntity1 != null && blockEntity1 != blockEntity) { + blockEntity1.setRemoved(); + } ++ ++ // CraftBukkit start ++ } else { ++ System.out.println("Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() ++ + " (" + getBlockState(blockposition) + ") where there was no entity tile!"); ++ System.out.println("Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); ++ new Exception().printStackTrace(); ++ // CraftBukkit end + } + } + +@@ -403,10 +474,21 @@ + @Override + public void removeBlockEntity(BlockPos pos) { + if (this.isInLevel()) { +- BlockEntity blockEntity = this.blockEntities.remove(pos); +- if (blockEntity != null) { +- if (this.level instanceof ServerLevel serverLevel) { +- this.removeGameEventListener(blockEntity, serverLevel); ++ BlockEntity tileentity = (BlockEntity) this.blockEntities.remove(pos); ++ ++ // CraftBukkit start - SPIGOT-5561: Also remove from pending map ++ if (!pendingBlockEntities.isEmpty()) { ++ pendingBlockEntities.remove(pos); ++ } ++ // CraftBukkit end ++ ++ if (tileentity != null) { ++ Level world = this.level; ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ ++ this.removeGameEventListener(tileentity, worldserver); + } + + blockEntity.setRemoved(); +@@ -446,6 +535,57 @@ + } + } + ++ // CraftBukkit start ++ public void loadCallback() { ++ org.bukkit.Server server = this.level.getCraftServer(); ++ if (server != null) { ++ /* ++ * If it's a new world, the first few chunks are generated inside ++ * the World constructor. We can't reliably alter that, so we have ++ * no way of creating a CraftWorld/CraftServer at that point. ++ */ ++ org.bukkit.Chunk bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this); ++ server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(bukkitChunk, this.needsDecoration)); ++ ++ if (this.needsDecoration) { ++ this.needsDecoration = false; ++ java.util.Random random = new java.util.Random(); ++ random.setSeed(level.getSeed()); ++ long xRand = random.nextLong() / 2L * 2L + 1L; ++ long zRand = random.nextLong() / 2L * 2L + 1L; ++ random.setSeed((long) this.chunkPos.x * xRand + (long) this.chunkPos.z * zRand ^ level.getSeed()); ++ ++ org.bukkit.World world = this.level.getWorld(); ++ if (world != null) { ++ this.level.populating = true; ++ try { ++ for (org.bukkit.generator.BlockPopulator populator : world.getPopulators()) { ++ populator.populate(world, random, bukkitChunk); ++ } ++ } finally { ++ this.level.populating = false; ++ } ++ } ++ server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk)); ++ } ++ } ++ } ++ ++ public void unloadCallback() { ++ org.bukkit.Server server = this.level.getCraftServer(); ++ org.bukkit.Chunk bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this); ++ org.bukkit.event.world.ChunkUnloadEvent unloadEvent = new org.bukkit.event.world.ChunkUnloadEvent(bukkitChunk, this.isUnsaved()); ++ server.getPluginManager().callEvent(unloadEvent); ++ // note: saving can be prevented, but not forced if no saving is actually required ++ this.mustNotSave = !unloadEvent.isSaveChunk(); ++ } ++ ++ @Override ++ public boolean isUnsaved() { ++ return super.isUnsaved() && !this.mustNotSave; ++ } ++ // CraftBukkit end ++ + public boolean isEmpty() { + return false; + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/LevelChunkSection.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/LevelChunkSection.java.patch new file mode 100644 index 0000000000..704eb84a2a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/LevelChunkSection.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -21,12 +22,14 @@ + private short nonEmptyBlockCount; + private short tickingBlockCount; + private short tickingFluidCount; +- private final PalettedContainer states; +- private PalettedContainerRO> biomes; ++ private final PalettedContainer states; ++ // CraftBukkit start - read/write ++ private PalettedContainer> biomes; + +- public LevelChunkSection(PalettedContainer states, PalettedContainerRO> biomes) { +- this.states = states; +- this.biomes = biomes; ++ public LevelChunkSection(PalettedContainer datapaletteblock, PalettedContainer> palettedcontainerro) { ++ // CraftBukkit end ++ this.states = datapaletteblock; ++ this.biomes = palettedcontainerro; + this.recalcBlockCounts(); + } + +@@ -180,6 +190,12 @@ + return this.biomes.get(x, y, z); + } + ++ // CraftBukkit start ++ public void setBiome(int i, int j, int k, Holder biome) { ++ this.biomes.set(i, j, k, biome); ++ } ++ // CraftBukkit end ++ + public void fillBiomesFromNoise(BiomeResolver biomeResolver, Climate.Sampler climateSampler, int x, int y, int z) { + PalettedContainer> palettedContainer = this.biomes.recreate(); + int i = 4; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/ChunkSerializer.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/ChunkSerializer.java.patch new file mode 100644 index 0000000000..13e6943d3a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/ChunkSerializer.java.patch @@ -0,0 +1,117 @@ +--- a/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -86,17 +93,17 @@ + LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", pos, pos, chunkPos); + } + +- UpgradeData upgradeData = tag.contains("UpgradeData", 10) ? new UpgradeData(tag.getCompound("UpgradeData"), level) : UpgradeData.EMPTY; +- boolean _boolean = tag.getBoolean("isLightOn"); +- ListTag list = tag.getList("sections", 10); +- int sectionsCount = level.getSectionsCount(); +- LevelChunkSection[] levelChunkSections = new LevelChunkSection[sectionsCount]; +- boolean hasSkyLight = level.dimensionType().hasSkyLight(); +- ChunkSource chunkSource = level.getChunkSource(); +- LevelLightEngine lightEngine = chunkSource.getLightEngine(); +- Registry registry = level.registryAccess().registryOrThrow(Registries.BIOME); +- Codec>> codec = makeBiomeCodec(registry); +- boolean flag = false; ++ UpgradeData chunkconverter = tag.contains("UpgradeData", 10) ? new UpgradeData(tag.getCompound("UpgradeData"), level) : UpgradeData.EMPTY; ++ boolean flag = tag.getBoolean("isLightOn"); ++ ListTag nbttaglist = tag.getList("sections", 10); ++ int i = level.getSectionsCount(); ++ LevelChunkSection[] achunksection = new LevelChunkSection[i]; ++ boolean flag1 = level.dimensionType().hasSkyLight(); ++ ServerChunkCache chunkproviderserver = level.getChunkSource(); ++ LevelLightEngine levellightengine = chunkproviderserver.getLightEngine(); ++ Registry iregistry = level.registryAccess().registryOrThrow(Registries.BIOME); ++ Codec>> codec = makeBiomeCodecRW(iregistry); // CraftBukkit - read/write ++ boolean flag2 = false; + + for (int i = 0; i < list.size(); i++) { + CompoundTag compound = list.getCompound(i); +@@ -114,21 +127,27 @@ + ); + } + +- PalettedContainerRO> palettedContainerRO; +- if (compound.contains("biomes", 10)) { +- palettedContainerRO = codec.parse(NbtOps.INSTANCE, compound.getCompound("biomes")) +- .promotePartial(errorMessage -> logErrors(pos, _byte, errorMessage)) +- .getOrThrow(false, LOGGER::error); ++ PalettedContainer object; // CraftBukkit - read/write ++ ++ if (nbttagcompound1.contains("biomes", 10)) { ++ dataresult = codec.parse(NbtOps.INSTANCE, nbttagcompound1.getCompound("biomes")).promotePartial((s) -> { ++ logErrors(pos, b0, s); ++ }); ++ logger = ChunkSerializer.LOGGER; ++ Objects.requireNonNull(logger); ++ object = ((DataResult>>) dataresult).getOrThrow(false, logger::error); // CraftBukkit - decompile error + } else { + palettedContainerRO = new PalettedContainer<>( + registry.asHolderIdMap(), registry.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES + ); + } + +- LevelChunkSection levelChunkSection = new LevelChunkSection(palettedContainer, palettedContainerRO); +- levelChunkSections[sectionIndexFromSectionY] = levelChunkSection; +- SectionPos sectionPos = SectionPos.of(pos, _byte); +- poiManager.checkConsistencyWithBlocks(sectionPos, levelChunkSection); ++ LevelChunkSection chunksection = new LevelChunkSection(datapaletteblock, (PalettedContainer) object); // CraftBukkit - read/write ++ ++ achunksection[k] = chunksection; ++ SectionPos sectionposition = SectionPos.of(pos, b0); ++ ++ poiManager.checkConsistencyWithBlocks(sectionposition, chunksection); + } + + boolean flag1 = compound.contains("BlockLight", 7); +@@ -196,9 +221,12 @@ + } + } + +- chunkAccess.setLightCorrect(_boolean); +- CompoundTag compound1 = tag.getCompound("Heightmaps"); +- EnumSet set = EnumSet.noneOf(Heightmap.Types.class); ++ // CraftBukkit start - load chunk persistent data from nbt - SPIGOT-6814: Already load PDC here to account for 1.17 to 1.18 chunk upgrading. ++ net.minecraft.nbt.Tag persistentBase = tag.get("ChunkBukkitValues"); ++ if (persistentBase instanceof CompoundTag) { ++ ((ChunkAccess) object1).persistentDataContainer.putAll((CompoundTag) persistentBase); ++ } ++ // CraftBukkit end + + for (Heightmap.Types types : chunkAccess.getStatus().heightmapsAfter()) { + String serializationKey = types.getSerializationKey(); +@@ -268,6 +307,12 @@ + ); + } + ++ // CraftBukkit start - read/write ++ private static Codec>> makeBiomeCodecRW(Registry iregistry) { ++ return PalettedContainer.codecRW(iregistry.asHolderIdMap(), iregistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, iregistry.getHolderOrThrow(Biomes.PLAINS)); ++ } ++ // CraftBukkit end ++ + public static CompoundTag write(ServerLevel level, ChunkAccess chunk) { + ChunkPos pos = chunk.getPos(); + CompoundTag compoundTag = NbtUtils.addCurrentDataVersion(new CompoundTag()); +@@ -377,11 +452,14 @@ + } + } + +- compoundTag.put("Heightmaps", compoundTag2); +- compoundTag.put( +- "structures", packStructureData(StructurePieceSerializationContext.fromLevel(level), pos, chunk.getAllStarts(), chunk.getAllReferences()) +- ); +- return compoundTag; ++ nbttagcompound.put("Heightmaps", nbttagcompound3); ++ nbttagcompound.put("structures", packStructureData(StructurePieceSerializationContext.fromLevel(level), chunkcoordintpair, chunk.getAllStarts(), chunk.getAllReferences())); ++ // CraftBukkit start - store chunk persistent data in nbt ++ if (!chunk.persistentDataContainer.isEmpty()) { // SPIGOT-6814: Always save PDC to account for 1.17 to 1.18 chunk upgrading. ++ nbttagcompound.put("ChunkBukkitValues", chunk.persistentDataContainer.toTagCompound()); ++ } ++ // CraftBukkit end ++ return nbttagcompound; + } + + private static void saveTicks(ServerLevel level, CompoundTag tag, ChunkAccess.TicksToSave ticksToSave) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/ChunkStorage.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/ChunkStorage.java.patch new file mode 100644 index 0000000000..71479e6a9a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/ChunkStorage.java.patch @@ -0,0 +1,110 @@ +--- a/net/minecraft/world/level/chunk/storage/ChunkStorage.java ++++ b/net/minecraft/world/level/chunk/storage/ChunkStorage.java +@@ -16,6 +18,10 @@ + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.chunk.ChunkGenerator; ++// CraftBukkit start ++import java.util.concurrent.ExecutionException; ++import net.minecraft.world.level.chunk.ChunkStatus; ++import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.levelgen.structure.LegacyStructureDataHandler; + import net.minecraft.world.level.storage.DimensionDataStorage; + +@@ -35,18 +42,13 @@ + return this.worker.isOldChunkAround(pos, radius); + } + +- public CompoundTag upgradeChunkTag( +- ResourceKey levelKey, +- Supplier storage, +- CompoundTag chunkData, +- Optional>> chunkGeneratorKey +- ) { +- int version = getVersion(chunkData); +- if (version < 1493) { +- chunkData = DataFixTypes.CHUNK.update(this.fixerUpper, chunkData, version, 1493); +- if (chunkData.getCompound("Level").getBoolean("hasLegacyStructureData")) { +- LegacyStructureDataHandler legacyStructureHandler = this.getLegacyStructureHandler(levelKey, storage); +- chunkData = legacyStructureHandler.updateFromLegacy(chunkData); ++ // CraftBukkit start ++ private boolean check(ServerChunkCache cps, int x, int z) { ++ ChunkPos pos = new ChunkPos(x, z); ++ if (cps != null) { ++ com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); ++ if (cps.hasChunk(x, z)) { ++ return true; + } + } + +@@ -60,9 +73,45 @@ + return var7; + } + +- private LegacyStructureDataHandler getLegacyStructureHandler(ResourceKey level, Supplier storage) { +- LegacyStructureDataHandler legacyStructureDataHandler = this.legacyStructureHandler; +- if (legacyStructureDataHandler == null) { ++ public CompoundTag upgradeChunkTag(ResourceKey resourcekey, Supplier supplier, CompoundTag nbttagcompound, Optional>> optional, ChunkPos pos, @Nullable LevelAccessor generatoraccess) { ++ // CraftBukkit end ++ int i = getVersion(nbttagcompound); ++ ++ // CraftBukkit start ++ if (i < 1466) { ++ CompoundTag level = nbttagcompound.getCompound("Level"); ++ if (level.getBoolean("TerrainPopulated") && !level.getBoolean("LightPopulated")) { ++ ServerChunkCache cps = (generatoraccess == null) ? null : ((ServerLevel) generatoraccess).getChunkSource(); ++ if (check(cps, pos.x - 1, pos.z) && check(cps, pos.x - 1, pos.z - 1) && check(cps, pos.x, pos.z - 1)) { ++ level.putBoolean("LightPopulated", true); ++ } ++ } ++ } ++ // CraftBukkit end ++ ++ if (i < 1493) { ++ nbttagcompound = DataFixTypes.CHUNK.update(this.fixerUpper, nbttagcompound, i, 1493); ++ if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) { ++ LegacyStructureDataHandler persistentstructurelegacy = this.getLegacyStructureHandler(resourcekey, supplier); ++ ++ nbttagcompound = persistentstructurelegacy.updateFromLegacy(nbttagcompound); ++ } ++ } ++ ++ injectDatafixingContext(nbttagcompound, resourcekey, optional); ++ nbttagcompound = DataFixTypes.CHUNK.updateToCurrentVersion(this.fixerUpper, nbttagcompound, Math.max(1493, i)); ++ if (i < SharedConstants.getCurrentVersion().getDataVersion().getVersion()) { ++ NbtUtils.addCurrentDataVersion(nbttagcompound); ++ } ++ ++ nbttagcompound.remove("__context"); ++ return nbttagcompound; ++ } ++ ++ private LegacyStructureDataHandler getLegacyStructureHandler(ResourceKey level, Supplier storage) { // CraftBukkit ++ LegacyStructureDataHandler persistentstructurelegacy = this.legacyStructureHandler; ++ ++ if (persistentstructurelegacy == null) { + synchronized (this) { + legacyStructureDataHandler = this.legacyStructureHandler; + if (legacyStructureDataHandler == null) { +@@ -74,13 +123,14 @@ + return legacyStructureDataHandler; + } + +- public static void injectDatafixingContext( +- CompoundTag chunkData, ResourceKey levelKey, Optional>> chunkGeneratorKey +- ) { +- CompoundTag compoundTag = new CompoundTag(); +- compoundTag.putString("dimension", levelKey.location().toString()); +- chunkGeneratorKey.ifPresent(generator -> compoundTag.putString("generator", generator.location().toString())); +- chunkData.put("__context", compoundTag); ++ public static void injectDatafixingContext(CompoundTag chunkData, ResourceKey levelKey, Optional>> chunkGeneratorKey) { // CraftBukkit ++ CompoundTag nbttagcompound1 = new CompoundTag(); ++ ++ nbttagcompound1.putString("dimension", levelKey.location().toString()); ++ chunkGeneratorKey.ifPresent((resourcekey1) -> { ++ nbttagcompound1.putString("generator", resourcekey1.location().toString()); ++ }); ++ chunkData.put("__context", nbttagcompound1); + } + + public static int getVersion(CompoundTag chunkData) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/RegionFile.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/RegionFile.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/RegionFile.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch new file mode 100644 index 0000000000..637d17ecdc --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch @@ -0,0 +1,76 @@ +--- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -26,27 +30,38 @@ + this.sync = sync; + } + +- private RegionFile getRegionFile(ChunkPos chunkPos) throws IOException { +- long _long = ChunkPos.asLong(chunkPos.getRegionX(), chunkPos.getRegionZ()); +- RegionFile regionFile = this.regionCache.getAndMoveToFirst(_long); +- if (regionFile != null) { +- return regionFile; ++ private RegionFile getRegionFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit ++ long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); ++ RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i); ++ ++ if (regionfile != null) { ++ return regionfile; + } else { + if (this.regionCache.size() >= 256) { + this.regionCache.removeLast().close(); + } + + FileUtil.createDirectoriesSafe(this.folder); +- Path path = this.folder.resolve("r." + chunkPos.getRegionX() + "." + chunkPos.getRegionZ() + ".mca"); +- RegionFile regionFile1 = new RegionFile(path, this.folder, this.sync); +- this.regionCache.putAndMoveToFirst(_long, regionFile1); +- return regionFile1; ++ Path path = this.folder; ++ int j = chunkcoordintpair.getRegionX(); ++ Path path1 = path.resolve("r." + j + "." + chunkcoordintpair.getRegionZ() + ".mca"); ++ if (existingOnly && !java.nio.file.Files.exists(path1)) return null; // CraftBukkit ++ RegionFile regionfile1 = new RegionFile(path1, this.folder, this.sync); ++ ++ this.regionCache.putAndMoveToFirst(i, regionfile1); ++ return regionfile1; + } + } + + @Nullable + public CompoundTag read(ChunkPos chunkPos) throws IOException { +- RegionFile regionFile = this.getRegionFile(chunkPos); ++ // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing ++ RegionFile regionfile = this.getRegionFile(chunkPos, true); ++ if (regionfile == null) { ++ return null; ++ } ++ // CraftBukkit end ++ DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkPos); + + CompoundTag var4; + try (DataInputStream chunkDataInputStream = regionFile.getChunkDataInputStream(chunkPos)) { +@@ -61,7 +100,13 @@ + } + + public void scanChunk(ChunkPos chunkPos, StreamTagVisitor visitor) throws IOException { +- RegionFile regionFile = this.getRegionFile(chunkPos); ++ // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing ++ RegionFile regionfile = this.getRegionFile(chunkPos, true); ++ if (regionfile == null) { ++ return; ++ } ++ // CraftBukkit end ++ DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkPos); + + try (DataInputStream chunkDataInputStream = regionFile.getChunkDataInputStream(chunkPos)) { + if (chunkDataInputStream != null) { +@@ -71,7 +131,8 @@ + } + + protected void write(ChunkPos chunkPos, @Nullable CompoundTag chunkData) throws IOException { +- RegionFile regionFile = this.getRegionFile(chunkPos); ++ RegionFile regionfile = this.getRegionFile(chunkPos, false); // CraftBukkit ++ + if (chunkData == null) { + regionFile.clear(chunkPos); + } else { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/dimension/end/EndDragonFight.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/dimension/end/EndDragonFight.java.patch new file mode 100644 index 0000000000..466735910a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/dimension/end/EndDragonFight.java.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -476,7 +510,7 @@ + return this.previouslyKilled; + } + +- public void tryRespawn() { ++ public boolean tryRespawn() { // CraftBukkit - return boolean + if (this.dragonKilled && this.respawnStage == null) { + BlockPos blockPos = this.portalLocation; + if (blockPos == null) { +@@ -495,21 +532,24 @@ + List list = Lists.newArrayList(); + BlockPos blockPos1 = blockPos.above(1); + +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- List entitiesOfClass = this.level.getEntitiesOfClass(EndCrystal.class, new AABB(blockPos1.relative(direction, 2))); +- if (entitiesOfClass.isEmpty()) { +- return; ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ List list1 = this.level.getEntitiesOfClass(EndCrystal.class, new AABB(blockposition1.relative(enumdirection, 2))); ++ ++ if (list1.isEmpty()) { ++ return false; // CraftBukkit - return value + } + + list.addAll(entitiesOfClass); + } + +- LOGGER.debug("Found all crystals, respawning dragon."); +- this.respawnDragon(list); ++ EndDragonFight.LOGGER.debug("Found all crystals, respawning dragon."); ++ return this.respawnDragon(list); // CraftBukkit - return value + } ++ return false; // CraftBukkit - return value + } + +- private void respawnDragon(List crystals) { ++ public boolean respawnDragon(List list) { // CraftBukkit - return boolean + if (this.dragonKilled && this.respawnStage == null) { + for (BlockPattern.BlockPatternMatch blockPatternMatch = this.findExitPortal(); blockPatternMatch != null; blockPatternMatch = this.findExitPortal()) { + for (int i = 0; i < this.exitPortalPattern.getWidth(); i++) { +@@ -527,8 +568,10 @@ + this.respawnStage = DragonRespawnAnimation.START; + this.respawnTime = 0; + this.spawnExitPortal(false); +- this.respawnCrystals = crystals; ++ this.respawnCrystals = list; ++ return true; // CraftBukkit - return value + } ++ return false; // CraftBukkit - return value + } + + public void resetSpikeCrystals() { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/entity/PersistentEntitySectionManager.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/entity/PersistentEntitySectionManager.java.patch new file mode 100644 index 0000000000..c646ec5ff8 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/entity/PersistentEntitySectionManager.java.patch @@ -0,0 +1,130 @@ +--- a/net/minecraft/world/level/entity/PersistentEntitySectionManager.java ++++ b/net/minecraft/world/level/entity/PersistentEntitySectionManager.java +@@ -28,6 +30,11 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.ChunkPos; + import org.slf4j.Logger; ++import net.minecraft.world.level.ChunkPos; ++// CraftBukkit start ++import net.minecraft.world.level.chunk.storage.EntityStorage; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class PersistentEntitySectionManager implements AutoCloseable { + static final Logger LOGGER = LogUtils.getLogger(); +@@ -52,8 +59,18 @@ + this.entityGetter = new LevelEntityGetterAdapter<>(this.visibleEntityStorage, this.sectionStorage); + } + +- void removeSectionIfEmpty(long sectionKey, EntitySection section) { +- if (section.isEmpty()) { ++ // CraftBukkit start - add method to get all entities in chunk ++ public List getEntities(ChunkPos chunkCoordIntPair) { ++ return sectionStorage.getExistingSectionsInChunk(chunkCoordIntPair.toLong()).flatMap(EntitySection::getEntities).map(entity -> (Entity) entity).collect(Collectors.toList()); ++ } ++ ++ public boolean isPending(long pair) { ++ return chunkLoadStatuses.get(pair) == b.PENDING; ++ } ++ // CraftBukkit end ++ ++ void removeSectionIfEmpty(long sectionKey, EntitySection entitysection) { ++ if (entitysection.isEmpty()) { + this.sectionStorage.remove(sectionKey); + } + } +@@ -171,9 +209,16 @@ + } + } + +- private boolean storeChunkSections(long chunkPosValue, Consumer entityAction) { +- PersistentEntitySectionManager.ChunkLoadStatus chunkLoadStatus = this.chunkLoadStatuses.get(chunkPosValue); +- if (chunkLoadStatus == PersistentEntitySectionManager.ChunkLoadStatus.PENDING) { ++ private boolean storeChunkSections(long chunkPosValue, Consumer consumer) { ++ // CraftBukkit start - add boolean for event call ++ return storeChunkSections(chunkPosValue, consumer, false); ++ } ++ ++ private boolean storeChunkSections(long i, Consumer consumer, boolean callEvent) { ++ // CraftBukkit end ++ PersistentEntitySectionManager.b persistententitysectionmanager_b = (PersistentEntitySectionManager.b) this.chunkLoadStatuses.get(i); ++ ++ if (persistententitysectionmanager_b == PersistentEntitySectionManager.b.PENDING) { + return false; + } else { + List list = this.sectionStorage +@@ -181,8 +226,9 @@ + .flatMap(entitySection -> entitySection.getEntities().filter(EntityAccess::shouldBeSaved)) + .collect(Collectors.toList()); + if (list.isEmpty()) { +- if (chunkLoadStatus == PersistentEntitySectionManager.ChunkLoadStatus.LOADED) { +- this.permanentStorage.storeEntities(new ChunkEntities<>(new ChunkPos(chunkPosValue), ImmutableList.of())); ++ if (persistententitysectionmanager_b == PersistentEntitySectionManager.b.LOADED) { ++ if (callEvent) CraftEventFactory.callEntitiesUnloadEvent(((EntityStorage) permanentStorage).level, new ChunkPos(i), ImmutableList.of()); // CraftBukkit ++ this.permanentStorage.storeEntities(new ChunkEntities<>(new ChunkPos(i), ImmutableList.of())); + } + + return true; +@@ -190,8 +236,9 @@ + this.requestChunkLoad(chunkPosValue); + return false; + } else { +- this.permanentStorage.storeEntities(new ChunkEntities<>(new ChunkPos(chunkPosValue), list)); +- list.forEach(entityAction); ++ if (callEvent) CraftEventFactory.callEntitiesUnloadEvent(((EntityStorage) permanentStorage).level, new ChunkPos(i), list.stream().map(entity -> (Entity) entity).collect(Collectors.toList())); // CraftBukkit ++ this.permanentStorage.storeEntities(new ChunkEntities<>(new ChunkPos(i), list)); ++ list.forEach(consumer); + return true; + } + } +@@ -207,7 +258,10 @@ + } + + private boolean processChunkUnload(long chunkPosValue) { +- boolean flag = this.storeChunkSections(chunkPosValue, entity -> entity.getPassengersAndSelf().forEach(this::unloadEntity)); ++ boolean flag = this.storeChunkSections(chunkPosValue, (entityaccess) -> { ++ entityaccess.getPassengersAndSelf().forEach(this::unloadEntity); ++ }, true); // CraftBukkit - add boolean for event call ++ + if (!flag) { + return false; + } else { +@@ -227,10 +282,17 @@ + } + + private void processPendingLoads() { +- ChunkEntities chunkEntities; +- while ((chunkEntities = this.loadingInbox.poll()) != null) { +- chunkEntities.getEntities().forEach(entity -> this.addEntity((T)entity, true)); +- this.chunkLoadStatuses.put(chunkEntities.getPos().toLong(), PersistentEntitySectionManager.ChunkLoadStatus.LOADED); ++ ChunkEntities chunkentities; // CraftBukkit - decompile error ++ ++ while ((chunkentities = (ChunkEntities) this.loadingInbox.poll()) != null) { ++ chunkentities.getEntities().forEach((entityaccess) -> { ++ this.addEntity(entityaccess, true); ++ }); ++ this.chunkLoadStatuses.put(chunkentities.getPos().toLong(), PersistentEntitySectionManager.b.LOADED); ++ // CraftBukkit start - call entity load event ++ List entities = getEntities(chunkentities.getPos()); ++ CraftEventFactory.callEntitiesLoadEvent(((EntityStorage) permanentStorage).level, chunkentities.getPos(), entities); ++ // CraftBukkit end + } + } + +@@ -281,7 +349,15 @@ + + @Override + public void close() throws IOException { +- this.saveAll(); ++ // CraftBukkit start - add save boolean ++ close(true); ++ } ++ ++ public void close(boolean save) throws IOException { ++ if (save) { ++ this.saveAll(); ++ } ++ // CraftBukkit end + this.permanentStorage.close(); + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/gameevent/GameEventDispatcher.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/gameevent/GameEventDispatcher.java.patch new file mode 100644 index 0000000000..cf7dcc844a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/gameevent/GameEventDispatcher.java.patch @@ -0,0 +1,54 @@ +--- a/net/minecraft/world/level/gameevent/GameEventDispatcher.java ++++ b/net/minecraft/world/level/gameevent/GameEventDispatcher.java +@@ -9,6 +10,12 @@ + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.CraftGameEvent; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.world.GenericGameEvent; ++// CraftBukkit end + + public class GameEventDispatcher { + private final ServerLevel level; +@@ -18,18 +26,26 @@ + } + + public void post(GameEvent event, Vec3 pos, GameEvent.Context context) { +- int notificationRadius = event.getNotificationRadius(); +- BlockPos blockPos = BlockPos.containing(pos); +- int i = SectionPos.blockToSectionCoord(blockPos.getX() - notificationRadius); +- int i1 = SectionPos.blockToSectionCoord(blockPos.getY() - notificationRadius); +- int i2 = SectionPos.blockToSectionCoord(blockPos.getZ() - notificationRadius); +- int i3 = SectionPos.blockToSectionCoord(blockPos.getX() + notificationRadius); +- int i4 = SectionPos.blockToSectionCoord(blockPos.getY() + notificationRadius); +- int i5 = SectionPos.blockToSectionCoord(blockPos.getZ() + notificationRadius); +- List list = new ArrayList<>(); +- GameEventListenerRegistry.ListenerVisitor listenerVisitor = (listener, pos1) -> { +- if (listener.getDeliveryMode() == GameEventListener.DeliveryMode.BY_DISTANCE) { +- list.add(new GameEvent.ListenerInfo(event, pos, context, listener, pos1)); ++ int i = event.getNotificationRadius(); ++ BlockPos blockposition = BlockPos.containing(pos); ++ // CraftBukkit start ++ GenericGameEvent event1 = new GenericGameEvent(CraftGameEvent.minecraftToBukkit(event), CraftLocation.toBukkit(blockposition, level.getWorld()), (context.sourceEntity() == null) ? null : context.sourceEntity().getBukkitEntity(), i, !Bukkit.isPrimaryThread()); ++ level.getCraftServer().getPluginManager().callEvent(event1); ++ if (event1.isCancelled()) { ++ return; ++ } ++ i = event1.getRadius(); ++ // CraftBukkit end ++ int j = SectionPos.blockToSectionCoord(blockposition.getX() - i); ++ int k = SectionPos.blockToSectionCoord(blockposition.getY() - i); ++ int l = SectionPos.blockToSectionCoord(blockposition.getZ() - i); ++ int i1 = SectionPos.blockToSectionCoord(blockposition.getX() + i); ++ int j1 = SectionPos.blockToSectionCoord(blockposition.getY() + i); ++ int k1 = SectionPos.blockToSectionCoord(blockposition.getZ() + i); ++ List list = new ArrayList(); ++ GameEventListenerRegistry.ListenerVisitor gameeventlistenerregistry_a = (gameeventlistener, vec3d1) -> { ++ if (gameeventlistener.getDeliveryMode() == GameEventListener.a.BY_DISTANCE) { ++ list.add(new GameEvent.ListenerInfo(event, pos, context, gameeventlistener, vec3d1)); + } else { + listener.handleGameEvent(this.level, event, context, pos); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java.patch new file mode 100644 index 0000000000..f1fabc54f0 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java ++++ b/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java +@@ -29,6 +27,11 @@ + import net.minecraft.world.level.gameevent.PositionSource; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.CraftGameEvent; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockReceiveGameEvent; ++// CraftBukkit end + + public interface VibrationSystem { + GameEvent[] RESONANCE_EVENTS = new GameEvent[]{ +@@ -389,11 +284,18 @@ + return false; + } + +- if (entity.isSteppingCarefully() && gameEvent.is(GameEventTags.IGNORE_VIBRATIONS_SNEAKING)) { +- if (this.canTriggerAvoidVibration() && entity instanceof ServerPlayer serverPlayer) { +- CriteriaTriggers.AVOID_VIBRATION.trigger(serverPlayer); +- } +- ++ if (optional.isEmpty()) { ++ return false; ++ } else { ++ Vec3 vec3d1 = (Vec3) optional.get(); ++ // CraftBukkit start ++ boolean defaultCancel = !vibrationsystem_d.canReceiveVibration(level, BlockPos.containing(pos), gameEvent, context); ++ Entity entity = context.sourceEntity(); ++ BlockReceiveGameEvent event = new BlockReceiveGameEvent(CraftGameEvent.minecraftToBukkit(gameEvent), CraftBlock.at(level, BlockPos.containing(vec3d1)), (entity == null) ? null : entity.getBukkitEntity()); ++ event.setCancelled(defaultCancel); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ // CraftBukkit end + return false; + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/FlatLevelSource.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/FlatLevelSource.java.patch new file mode 100644 index 0000000000..c8d944bd9f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/FlatLevelSource.java.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/world/level/levelgen/FlatLevelSource.java ++++ b/net/minecraft/world/level/levelgen/FlatLevelSource.java +@@ -35,10 +35,19 @@ + private final FlatLevelGeneratorSettings settings; + + public FlatLevelSource(FlatLevelGeneratorSettings settings) { +- super(new FixedBiomeSource(settings.getBiome()), Util.memoize(settings::adjustGenerationSettings)); +- this.settings = settings; ++ // CraftBukkit start ++ // WorldChunkManagerHell worldchunkmanagerhell = new WorldChunkManagerHell(generatorsettingsflat.getBiome()); ++ ++ // Objects.requireNonNull(generatorsettingsflat); ++ this(settings, new FixedBiomeSource(settings.getBiome())); + } + ++ public FlatLevelSource(FlatLevelGeneratorSettings generatorsettingsflat, net.minecraft.world.level.biome.BiomeSource worldchunkmanager) { ++ super(worldchunkmanager, Util.memoize(generatorsettingsflat::adjustGenerationSettings)); ++ // CraftBukkit end ++ this.settings = generatorsettingsflat; ++ } ++ + @Override + public ChunkGeneratorStructureState createState(HolderLookup structureSetLookup, RandomState randomState, long seed) { + Stream> stream = this.settings diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java.patch new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java.patch @@ -0,0 +1 @@ + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/PatrolSpawner.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/PatrolSpawner.java.patch new file mode 100644 index 0000000000..820b8fc893 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/PatrolSpawner.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/level/levelgen/PatrolSpawner.java ++++ b/net/minecraft/world/level/levelgen/PatrolSpawner.java +@@ -102,9 +115,9 @@ + patrollingMonster.findPatrolTarget(); + } + +- patrollingMonster.setPos((double)pos.getX(), (double)pos.getY(), (double)pos.getZ()); +- patrollingMonster.finalizeSpawn(level, level.getCurrentDifficultyAt(pos), MobSpawnType.PATROL, null, null); +- level.addFreshEntityWithPassengers(patrollingMonster); ++ entitymonsterpatrolling.setPos((double) pos.getX(), (double) pos.getY(), (double) pos.getZ()); ++ entitymonsterpatrolling.finalizeSpawn(level, level.getCurrentDifficultyAt(pos), EnumMobSpawn.PATROL, (GroupDataEntity) null, (CompoundTag) null); ++ level.addFreshEntityWithPassengers(entitymonsterpatrolling, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.PATROL); // CraftBukkit + return true; + } else { + return false; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java.patch new file mode 100644 index 0000000000..e6492444e1 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java ++++ b/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java +@@ -221,21 +236,21 @@ + } + } + +- public static LegacyStructureDataHandler getLegacyStructureHandler(ResourceKey level, @Nullable DimensionDataStorage storage) { +- if (level == Level.OVERWORLD) { +- return new LegacyStructureDataHandler( +- storage, +- ImmutableList.of("Monument", "Stronghold", "Village", "Mineshaft", "Temple", "Mansion"), +- ImmutableList.of("Village", "Mineshaft", "Mansion", "Igloo", "Desert_Pyramid", "Jungle_Pyramid", "Swamp_Hut", "Stronghold", "Monument") +- ); +- } else if (level == Level.NETHER) { +- List list = ImmutableList.of("Fortress"); +- return new LegacyStructureDataHandler(storage, list, list); +- } else if (level == Level.END) { +- List list = ImmutableList.of("EndCity"); +- return new LegacyStructureDataHandler(storage, list, list); ++ public static LegacyStructureDataHandler getLegacyStructureHandler(ResourceKey level, @Nullable DimensionDataStorage storage) { // CraftBukkit ++ if (level == LevelStem.OVERWORLD) { // CraftBukkit ++ return new LegacyStructureDataHandler(storage, ImmutableList.of("Monument", "Stronghold", "Village", "Mineshaft", "Temple", "Mansion"), ImmutableList.of("Village", "Mineshaft", "Mansion", "Igloo", "Desert_Pyramid", "Jungle_Pyramid", "Swamp_Hut", "Stronghold", "Monument")); + } else { +- throw new RuntimeException(String.format(Locale.ROOT, "Unknown dimension type : %s", level)); ++ ImmutableList immutablelist; ++ ++ if (level == LevelStem.NETHER) { // CraftBukkit ++ immutablelist = ImmutableList.of("Fortress"); ++ return new LegacyStructureDataHandler(storage, immutablelist, immutablelist); ++ } else if (level == LevelStem.END) { // CraftBukkit ++ immutablelist = ImmutableList.of("EndCity"); ++ return new LegacyStructureDataHandler(storage, immutablelist, immutablelist); ++ } else { ++ throw new RuntimeException(String.format(Locale.ROOT, "Unknown dimension type : %s", level)); ++ } + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/StructurePiece.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/StructurePiece.java.patch new file mode 100644 index 0000000000..e65fdfeae4 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/StructurePiece.java.patch @@ -0,0 +1,173 @@ +--- a/net/minecraft/world/level/levelgen/structure/StructurePiece.java ++++ b/net/minecraft/world/level/levelgen/structure/StructurePiece.java +@@ -68,16 +57,14 @@ + } + + public StructurePiece(StructurePieceType type, CompoundTag tag) { +- this( +- type, +- tag.getInt("GD"), +- BoundingBox.CODEC +- .parse(NbtOps.INSTANCE, tag.get("BB")) +- .resultOrPartial(LOGGER::error) +- .orElseThrow(() -> new IllegalArgumentException("Invalid boundingbox")) +- ); +- int _int = tag.getInt("O"); +- this.setOrientation(_int == -1 ? null : Direction.from2DDataValue(_int)); ++ // CraftBukkit start - decompile error ++ this(type, tag.getInt("GD"), (BoundingBox) BoundingBox.CODEC.parse(NbtOps.INSTANCE, tag.get("BB")).resultOrPartial(Objects.requireNonNull(StructurePiece.LOGGER)::error).orElseThrow(() -> { ++ return new IllegalArgumentException("Invalid boundingbox"); ++ })); ++ // CraftBukkit end ++ int j = tag.getInt("O"); ++ ++ this.setOrientation(j == -1 ? null : Direction.from2DDataValue(j)); + } + + protected static BoundingBox makeBoundingBox(int x, int y, int z, Direction direction, int offsetX, int offsetY, int offsetZ) { +@@ -91,14 +76,20 @@ + } + + public final CompoundTag createTag(StructurePieceSerializationContext context) { +- CompoundTag compoundTag = new CompoundTag(); +- compoundTag.putString("id", BuiltInRegistries.STRUCTURE_PIECE.getKey(this.getType()).toString()); +- BoundingBox.CODEC.encodeStart(NbtOps.INSTANCE, this.boundingBox).resultOrPartial(LOGGER::error).ifPresent(tag -> compoundTag.put("BB", tag)); +- Direction orientation = this.getOrientation(); +- compoundTag.putInt("O", orientation == null ? -1 : orientation.get2DDataValue()); +- compoundTag.putInt("GD", this.genDepth); +- this.addAdditionalSaveData(context, compoundTag); +- return compoundTag; ++ CompoundTag nbttagcompound = new CompoundTag(); ++ ++ nbttagcompound.putString("id", BuiltInRegistries.STRUCTURE_PIECE.getKey(this.getType()).toString()); ++ // CraftBukkit start - decompile error ++ BoundingBox.CODEC.encodeStart(NbtOps.INSTANCE, this.boundingBox).resultOrPartial(Objects.requireNonNull(StructurePiece.LOGGER)::error).ifPresent((nbtbase) -> { ++ nbttagcompound.put("BB", nbtbase); ++ }); ++ // CraftBukkit end ++ Direction enumdirection = this.getOrientation(); ++ ++ nbttagcompound.putInt("O", enumdirection == null ? -1 : enumdirection.get2DDataValue()); ++ nbttagcompound.putInt("GD", this.genDepth); ++ this.addAdditionalSaveData(context, nbttagcompound); ++ return nbttagcompound; + } + + protected abstract void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag); +@@ -190,11 +182,13 @@ + blockstate = blockstate.rotate(this.rotation); + } + +- level.setBlock(worldPos, blockstate, 2); +- FluidState fluidState = level.getFluidState(worldPos); +- if (!fluidState.isEmpty()) { +- level.scheduleTick(worldPos, fluidState.getType(), 0); ++ level.setBlock(blockposition_mutableblockposition, blockstate, 2); ++ // CraftBukkit start - fluid handling is already done if we have a transformer generator access ++ if (level instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess) { ++ return; + } ++ // CraftBukkit end ++ FluidState fluid = level.getFluidState(blockposition_mutableblockposition); + + if (SHAPE_CHECK_BLOCKS.contains(blockstate.getBlock())) { + level.getChunk(worldPos).markPosForPostprocessing(worldPos); +@@ -203,6 +202,38 @@ + } + } + ++ // CraftBukkit start ++ protected boolean placeCraftBlockEntity(ServerLevelAccessor worldAccess, BlockPos position, org.bukkit.craftbukkit.block.CraftBlockEntityState craftBlockEntityState, int i) { ++ if (worldAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ return transformerAccess.setCraftBlock(position, craftBlockEntityState, i); ++ } ++ boolean result = worldAccess.setBlock(position, craftBlockEntityState.getHandle(), i); ++ BlockEntity tileEntity = worldAccess.getBlockEntity(position); ++ if (tileEntity != null) { ++ tileEntity.load(craftBlockEntityState.getSnapshotNBT()); ++ } ++ return result; ++ } ++ ++ protected void placeCraftSpawner(ServerLevelAccessor worldAccess, BlockPos position, org.bukkit.entity.EntityType entityType, int i) { ++ // This method is used in structures that are generated by code and place spawners as they set the entity after the block was placed making it impossible for plugins to access that information ++ org.bukkit.craftbukkit.block.CraftCreatureSpawner spawner = (org.bukkit.craftbukkit.block.CraftCreatureSpawner) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(position, Blocks.SPAWNER.defaultBlockState(), null); ++ spawner.setSpawnedType(entityType); ++ placeCraftBlockEntity(worldAccess, position, spawner, i); ++ } ++ ++ protected void setCraftLootTable(ServerLevelAccessor worldAccess, BlockPos position, RandomSource randomSource, net.minecraft.resources.ResourceLocation loottableKey) { ++ // This method is used in structures that use data markers to a loot table to loot containers as otherwise plugins won't have access to that information. ++ net.minecraft.world.level.block.entity.BlockEntity tileEntity = worldAccess.getBlockEntity(position); ++ if (tileEntity instanceof net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity tileEntityLootable) { ++ tileEntityLootable.setLootTable(loottableKey, randomSource.nextLong()); ++ if (worldAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ transformerAccess.setCraftBlock(position, (org.bukkit.craftbukkit.block.CraftBlockState) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(position, tileEntity.getBlockState(), tileEntityLootable.saveWithFullMetadata()), 3); ++ } ++ } ++ } ++ // CraftBukkit end ++ + protected boolean canBeReplaced(LevelReader level, int x, int y, int z, BoundingBox box) { + return true; + } +@@ -431,11 +427,20 @@ + state = reorient(level, pos, Blocks.CHEST.defaultBlockState()); + } + +- level.setBlock(pos, state, 2); +- BlockEntity blockEntity = level.getBlockEntity(pos); +- if (blockEntity instanceof ChestBlockEntity) { +- ((ChestBlockEntity)blockEntity).setLootTable(lootTable, random.nextLong()); ++ // CraftBukkit start ++ /* ++ worldaccess.setBlock(blockposition, iblockdata, 2); ++ TileEntity tileentity = worldaccess.getBlockEntity(blockposition); ++ ++ if (tileentity instanceof TileEntityChest) { ++ ((TileEntityChest) tileentity).setLootTable(minecraftkey, randomsource.nextLong()); + } ++ */ ++ org.bukkit.craftbukkit.block.CraftChest chestState = (org.bukkit.craftbukkit.block.CraftChest) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(pos, state, null); ++ chestState.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(lootTable))); ++ chestState.setSeed(random.nextLong()); ++ placeCraftBlockEntity(level, pos, chestState, 2); ++ // CraftBukkit end + + return true; + } else { +@@ -443,17 +448,25 @@ + } + } + +- protected boolean createDispenser( +- WorldGenLevel level, BoundingBox box, RandomSource random, int x, int y, int z, Direction facing, ResourceLocation lootTable +- ) { +- BlockPos worldPos = this.getWorldPos(x, y, z); +- if (box.isInside(worldPos) && !level.getBlockState(worldPos).is(Blocks.DISPENSER)) { +- this.placeBlock(level, Blocks.DISPENSER.defaultBlockState().setValue(DispenserBlock.FACING, facing), x, y, z, box); +- BlockEntity blockEntity = level.getBlockEntity(worldPos); +- if (blockEntity instanceof DispenserBlockEntity) { +- ((DispenserBlockEntity)blockEntity).setLootTable(lootTable, random.nextLong()); ++ protected boolean createDispenser(WorldGenLevel level, BoundingBox box, RandomSource random, int x, int y, int z, Direction facing, ResourceLocation lootTable) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y, z); ++ ++ if (box.isInside(blockposition_mutableblockposition) && !level.getBlockState(blockposition_mutableblockposition).is(Blocks.DISPENSER)) { ++ // CraftBukkit start ++ /* ++ this.placeBlock(generatoraccessseed, (IBlockData) Blocks.DISPENSER.defaultBlockState().setValue(BlockDispenser.FACING, enumdirection), i, j, k, structureboundingbox); ++ TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); ++ ++ if (tileentity instanceof TileEntityDispenser) { ++ ((TileEntityDispenser) tileentity).setLootTable(minecraftkey, randomsource.nextLong()); + } + ++ org.bukkit.craftbukkit.block.CraftDispenser dispenserState = (org.bukkit.craftbukkit.block.CraftDispenser) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockposition_mutableblockposition, iblockdata, null); ++ dispenserState.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(lootTable))); ++ dispenserState.setSeed(random.nextLong()); ++ placeCraftBlockEntity(level, blockposition_mutableblockposition, dispenserState, 2); ++ // CraftBukkit end ++ + return true; + } else { + return false; diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/StructureStart.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/StructureStart.java.patch new file mode 100644 index 0000000000..589645b182 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/StructureStart.java.patch @@ -0,0 +1,44 @@ +--- a/net/minecraft/world/level/levelgen/structure/StructureStart.java ++++ b/net/minecraft/world/level/levelgen/structure/StructureStart.java +@@ -29,6 +31,7 @@ + private int references; + @Nullable + private volatile BoundingBox cachedBoundingBox; ++ public org.bukkit.event.world.AsyncStructureGenerateEvent.Cause generationEventCause = org.bukkit.event.world.AsyncStructureGenerateEvent.Cause.WORLD_GENERATION; // CraftBukkit + + public StructureStart(Structure structure, ChunkPos chunkPos, int references, PiecesContainer pieceContainer) { + this.structure = structure; +@@ -83,15 +89,30 @@ + ) { + List list = this.pieceContainer.pieces(); + if (!list.isEmpty()) { +- BoundingBox boundingBox = list.get(0).boundingBox; +- BlockPos center = boundingBox.getCenter(); +- BlockPos blockPos = new BlockPos(center.getX(), boundingBox.minY(), center.getZ()); ++ BoundingBox structureboundingbox1 = ((StructurePiece) list.get(0)).boundingBox; ++ BlockPos blockposition = structureboundingbox1.getCenter(); ++ BlockPos blockposition1 = new BlockPos(blockposition.getX(), structureboundingbox1.minY(), blockposition.getZ()); ++ // CraftBukkit start ++ /* ++ Iterator iterator = list.iterator(); + + for (StructurePiece structurePiece : list) { + if (structurePiece.getBoundingBox().intersects(box)) { + structurePiece.postProcess(level, structureManager, generator, random, box, chunkPos, blockPos); + } + } ++ */ ++ List pieces = list.stream().filter(piece -> piece.getBoundingBox().intersects(box)).toList(); ++ if (!pieces.isEmpty()) { ++ org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess = new org.bukkit.craftbukkit.util.TransformerGeneratorAccess(); ++ transformerAccess.setHandle(level); ++ transformerAccess.setStructureTransformer(new org.bukkit.craftbukkit.util.CraftStructureTransformer(generationEventCause, level, structureManager, structure, box, chunkPos)); ++ for (StructurePiece piece : pieces) { ++ piece.postProcess(transformerAccess, structureManager, generator, random, box, chunkPos, blockposition1); ++ } ++ transformerAccess.getStructureTransformer().discard(); ++ } ++ // CraftBukkit end + + this.structure.afterPlace(level, structureManager, generator, random, box, chunkPos, this.pieceContainer); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java.patch new file mode 100644 index 0000000000..ab9ce00134 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java +@@ -66,6 +70,15 @@ + + private static void placeSuspiciousSand(BoundingBox boundingBox, WorldGenLevel worldGenLevel, BlockPos pos) { + if (boundingBox.isInside(pos)) { ++ // CraftBukkit start ++ if (worldGenLevel instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ org.bukkit.craftbukkit.block.CraftBrushableBlock brushableState = (org.bukkit.craftbukkit.block.CraftBrushableBlock) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(pos, Blocks.SUSPICIOUS_SAND.defaultBlockState(), null); ++ brushableState.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(BuiltInLootTables.DESERT_PYRAMID_ARCHAEOLOGY))); ++ brushableState.setSeed(pos.asLong()); ++ transformerAccess.setCraftBlock(pos, brushableState, 2); ++ return; ++ } ++ // CraftBukkit end + worldGenLevel.setBlock(pos, Blocks.SUSPICIOUS_SAND.defaultBlockState(), 2); + worldGenLevel.getBlockEntity(pos, BlockEntityType.BRUSHABLE_BLOCK) + .ifPresent(brushableBlockEntity -> brushableBlockEntity.setLootTable(BuiltInLootTables.DESERT_PYRAMID_ARCHAEOLOGY, pos.asLong())); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java.patch new file mode 100644 index 0000000000..b863c0c2bb --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java +@@ -387,9 +281,15 @@ + @Override + protected void handleDataMarker(String name, BlockPos pos, ServerLevelAccessor level, RandomSource random, BoundingBox box) { + if (name.startsWith("Chest")) { +- BlockPos blockPos = pos.below(); +- if (box.isInside(blockPos)) { +- RandomizableContainer.setBlockEntityLootTable(level, random, blockPos, BuiltInLootTables.END_CITY_TREASURE); ++ BlockPos blockposition1 = pos.below(); ++ ++ if (box.isInside(blockposition1)) { ++ // CraftBukkit start - ensure block transformation ++ /* ++ RandomizableContainer.setBlockEntityLootTable(worldaccess, randomsource, blockposition1, LootTables.END_CITY_TREASURE); ++ */ ++ setCraftLootTable(level, blockposition1, random, BuiltInLootTables.END_CITY_TREASURE); ++ // CraftBukkit end + } + } else if (box.isInside(pos) && Level.isInSpawnableBounds(pos)) { + if (name.startsWith("Sentry")) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java.patch new file mode 100644 index 0000000000..83e942700f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java +@@ -100,10 +83,17 @@ + protected void handleDataMarker(String name, BlockPos pos, ServerLevelAccessor level, RandomSource random, BoundingBox box) { + if ("chest".equals(name)) { + level.setBlock(pos, Blocks.AIR.defaultBlockState(), 3); +- BlockEntity blockEntity = level.getBlockEntity(pos.below()); +- if (blockEntity instanceof ChestBlockEntity) { +- ((ChestBlockEntity)blockEntity).setLootTable(BuiltInLootTables.IGLOO_CHEST, random.nextLong()); ++ // CraftBukkit start - ensure block transformation ++ /* ++ TileEntity tileentity = worldaccess.getBlockEntity(blockposition.below()); ++ ++ if (tileentity instanceof TileEntityChest) { ++ ((TileEntityChest) tileentity).setLootTable(LootTables.IGLOO_CHEST, randomsource.nextLong()); + } ++ */ ++ setCraftLootTable(level, pos.below(), random, BuiltInLootTables.IGLOO_CHEST); ++ // CraftBukkit end ++ + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java.patch new file mode 100644 index 0000000000..99fa2b5342 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java +@@ -398,10 +512,19 @@ + BlockPos worldPos = this.getWorldPos(1, 0, i8); + if (box.isInside(worldPos) && this.isInterior(level, 1, 0, i8, box)) { + this.hasPlacedSpider = true; +- level.setBlock(worldPos, Blocks.SPAWNER.defaultBlockState(), 2); +- if (level.getBlockEntity(worldPos) instanceof SpawnerBlockEntity spawnerBlockEntity) { +- spawnerBlockEntity.setEntityId(EntityType.CAVE_SPIDER, random); ++ // CraftBukkit start ++ /* ++ generatoraccessseed.setBlock(blockposition_mutableblockposition, Blocks.SPAWNER.defaultBlockState(), 2); ++ TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); ++ ++ if (tileentity instanceof TileEntityMobSpawner) { ++ TileEntityMobSpawner tileentitymobspawner = (TileEntityMobSpawner) tileentity; ++ ++ tileentitymobspawner.setEntityId(EntityTypes.CAVE_SPIDER, randomsource); + } ++ */ ++ placeCraftSpawner(level, blockposition_mutableblockposition, org.bukkit.entity.EntityType.CAVE_SPIDER, 2); ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java.patch new file mode 100644 index 0000000000..08716c3519 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java.patch @@ -0,0 +1,37 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java +@@ -369,20 +423,21 @@ + this.placeBlock(level, blockState, 3, max + 1, i, box); + } + +- this.generateBox(level, box, 0, min, i, 4, min, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox( +- level, box, 0, max + 1, i, 0, min - 1, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false +- ); +- this.generateBox( +- level, box, 4, max + 1, i, 4, min - 1, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false +- ); +- if ((i & 1) == 0) { +- this.generateBox(level, box, 0, max + 2, i, 0, max + 3, i, blockState1, blockState1, false); +- this.generateBox(level, box, 4, max + 2, i, 4, max + 3, i, blockState1, blockState1, false); +- } ++ if (box.isInside(blockposition_mutableblockposition)) { ++ this.hasPlacedSpawner = true; ++ // CraftBukkit start ++ /* ++ generatoraccessseed.setBlock(blockposition_mutableblockposition, Blocks.SPAWNER.defaultBlockState(), 2); ++ TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); + +- for (int i2 = 0; i2 <= 4; i2++) { +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i2, -1, i1, box); ++ if (tileentity instanceof TileEntityMobSpawner) { ++ TileEntityMobSpawner tileentitymobspawner = (TileEntityMobSpawner) tileentity; ++ ++ tileentitymobspawner.setEntityId(EntityTypes.BLAZE, randomsource); ++ } ++ */ ++ placeCraftSpawner(level, blockposition_mutableblockposition, org.bukkit.entity.EntityType.BLAZE, 2); ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java.patch new file mode 100644 index 0000000000..9fc76fa2d8 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java +@@ -308,14 +196,20 @@ + @Override + protected void handleDataMarker(String name, BlockPos pos, ServerLevelAccessor level, RandomSource random, BoundingBox box) { + if ("chest".equals(name)) { +- level.setBlock( +- pos, Blocks.CHEST.defaultBlockState().setValue(ChestBlock.WATERLOGGED, Boolean.valueOf(level.getFluidState(pos).is(FluidTags.WATER))), 2 +- ); +- BlockEntity blockEntity = level.getBlockEntity(pos); +- if (blockEntity instanceof ChestBlockEntity) { +- ((ChestBlockEntity)blockEntity) +- .setLootTable(this.isLarge ? BuiltInLootTables.UNDERWATER_RUIN_BIG : BuiltInLootTables.UNDERWATER_RUIN_SMALL, random.nextLong()); ++ // CraftBukkit start - transform block to ensure loot table is accessible ++ /* ++ worldaccess.setBlock(blockposition, (IBlockData) Blocks.CHEST.defaultBlockState().setValue(BlockChest.WATERLOGGED, worldaccess.getFluidState(blockposition).is(TagsFluid.WATER)), 2); ++ TileEntity tileentity = worldaccess.getBlockEntity(blockposition); ++ ++ if (tileentity instanceof TileEntityChest) { ++ ((TileEntityChest) tileentity).setLootTable(this.isLarge ? LootTables.UNDERWATER_RUIN_BIG : LootTables.UNDERWATER_RUIN_SMALL, randomsource.nextLong()); + } ++ */ ++ org.bukkit.craftbukkit.block.CraftChest craftChest = (org.bukkit.craftbukkit.block.CraftChest) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(pos, Blocks.CHEST.defaultBlockState().setValue(ChestBlock.WATERLOGGED, level.getFluidState(pos).is(FluidTags.WATER)), null); ++ craftChest.setSeed(random.nextLong()); ++ craftChest.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.isLarge ? BuiltInLootTables.UNDERWATER_RUIN_BIG : BuiltInLootTables.UNDERWATER_RUIN_SMALL))); ++ placeCraftBlockEntity(level, pos, craftChest, 2); ++ // CraftBukkit end + } else if ("drowned".equals(name)) { + Drowned drowned = EntityType.DROWNED.create(level.getLevel()); + if (drowned != null) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java.patch new file mode 100644 index 0000000000..d6a57416bd --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java.patch @@ -0,0 +1,150 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java +@@ -40,29 +40,17 @@ + private static final int LOWEST_Y_POSITION = 10; + private static final boolean CHECK_AIR = true; + public static final int MAGIC_START_Y = 64; +- private static final StrongholdPieces.PieceWeight[] STRONGHOLD_PIECE_WEIGHTS = new StrongholdPieces.PieceWeight[]{ +- new StrongholdPieces.PieceWeight(StrongholdPieces.Straight.class, 40, 0), +- new StrongholdPieces.PieceWeight(StrongholdPieces.PrisonHall.class, 5, 5), +- new StrongholdPieces.PieceWeight(StrongholdPieces.LeftTurn.class, 20, 0), +- new StrongholdPieces.PieceWeight(StrongholdPieces.RightTurn.class, 20, 0), +- new StrongholdPieces.PieceWeight(StrongholdPieces.RoomCrossing.class, 10, 6), +- new StrongholdPieces.PieceWeight(StrongholdPieces.StraightStairsDown.class, 5, 5), +- new StrongholdPieces.PieceWeight(StrongholdPieces.StairsDown.class, 5, 5), +- new StrongholdPieces.PieceWeight(StrongholdPieces.FiveCrossing.class, 5, 4), +- new StrongholdPieces.PieceWeight(StrongholdPieces.ChestCorridor.class, 5, 4), +- new StrongholdPieces.PieceWeight(StrongholdPieces.Library.class, 10, 2) { +- @Override +- public boolean doPlace(int genDepth) { +- return super.doPlace(genDepth) && genDepth > 4; +- } +- }, +- new StrongholdPieces.PieceWeight(StrongholdPieces.PortalRoom.class, 20, 1) { +- @Override +- public boolean doPlace(int genDepth) { +- return super.doPlace(genDepth) && genDepth > 5; +- } +- } +- }; ++ private static final StrongholdPieces.PieceWeight[] STRONGHOLD_PIECE_WEIGHTS = new StrongholdPieces.PieceWeight[]{new StrongholdPieces.PieceWeight(StrongholdPieces.Straight.class, 40, 0), new StrongholdPieces.PieceWeight(StrongholdPieces.PrisonHall.class, 5, 5), new StrongholdPieces.PieceWeight(StrongholdPieces.LeftTurn.class, 20, 0), new StrongholdPieces.PieceWeight(StrongholdPieces.RightTurn.class, 20, 0), new StrongholdPieces.PieceWeight(StrongholdPieces.RoomCrossing.class, 10, 6), new StrongholdPieces.PieceWeight(StrongholdPieces.StraightStairsDown.class, 5, 5), new StrongholdPieces.PieceWeight(StrongholdPieces.StairsDown.class, 5, 5), new StrongholdPieces.PieceWeight(StrongholdPieces.FiveCrossing.class, 5, 4), new StrongholdPieces.PieceWeight(StrongholdPieces.ChestCorridor.class, 5, 4), new StrongholdPieces.PieceWeight(StrongholdPieces.Library.class, 10, 2) { ++ @Override ++ public boolean doPlace(int genDepth) { ++ return super.doPlace(genDepth) && genDepth > 4; ++ } ++ }, new StrongholdPieces.PieceWeight(StrongholdPieces.PortalRoom.class, 20, 1) { ++ @Override ++ public boolean doPlace(int genDepth) { ++ return super.doPlace(genDepth) && genDepth > 5; ++ } ++ } }; // CraftBukkit - fix decompile styling + private static List currentPieces; + static Class imposedPiece; + private static int totalWeight; +@@ -1460,14 +1054,98 @@ + this.generateSmallDoor(level, random, box, StrongholdPieces.StrongholdPiece.SmallDoorType.OPENING, 1, 1, 7); + BlockState blockState = Blocks.COBBLESTONE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.SOUTH); + +- for (int i = 0; i < 6; i++) { +- this.placeBlock(level, blockState, 1, 6 - i, 1 + i, box); +- this.placeBlock(level, blockState, 2, 6 - i, 1 + i, box); +- this.placeBlock(level, blockState, 3, 6 - i, 1 + i, box); +- if (i < 5) { +- this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 1, 5 - i, 1 + i, box); +- this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 2, 5 - i, 1 + i, box); +- this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 3, 5 - i, 1 + i, box); ++ this.generateBox(level, box, 1, 6, 1, 1, 6, 14, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 9, 6, 1, 9, 6, 14, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 2, 6, 1, 8, 6, 2, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 2, 6, 14, 8, 6, 14, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 1, 1, 1, 2, 1, 4, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 8, 1, 1, 9, 1, 4, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 1, 1, 1, 1, 1, 3, Blocks.LAVA.defaultBlockState(), Blocks.LAVA.defaultBlockState(), false); ++ this.generateBox(level, box, 9, 1, 1, 9, 1, 3, Blocks.LAVA.defaultBlockState(), Blocks.LAVA.defaultBlockState(), false); ++ this.generateBox(level, box, 3, 1, 8, 7, 1, 12, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 4, 1, 9, 6, 1, 11, Blocks.LAVA.defaultBlockState(), Blocks.LAVA.defaultBlockState(), false); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, true)).setValue(IronBarsBlock.SOUTH, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, true)).setValue(IronBarsBlock.EAST, true); ++ ++ int i; ++ ++ for (i = 3; i < 14; i += 2) { ++ this.generateBox(level, box, 0, 3, i, 0, 4, i, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 10, 3, i, 10, 4, i, iblockdata, iblockdata, false); ++ } ++ ++ for (i = 2; i < 9; i += 2) { ++ this.generateBox(level, box, i, 3, 15, i, 4, 15, iblockdata1, iblockdata1, false); ++ } ++ ++ IBlockData iblockdata2 = (IBlockData) Blocks.STONE_BRICK_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.NORTH); ++ ++ this.generateBox(level, box, 4, 1, 5, 6, 1, 7, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 4, 2, 6, 6, 2, 7, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 4, 3, 7, 6, 3, 7, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ ++ for (int j = 4; j <= 6; ++j) { ++ this.placeBlock(level, iblockdata2, j, 1, 4, box); ++ this.placeBlock(level, iblockdata2, j, 2, 5, box); ++ this.placeBlock(level, iblockdata2, j, 3, 6, box); ++ } ++ ++ IBlockData iblockdata3 = (IBlockData) Blocks.END_PORTAL_FRAME.defaultBlockState().setValue(EndPortalFrameBlock.FACING, Direction.NORTH); ++ IBlockData iblockdata4 = (IBlockData) Blocks.END_PORTAL_FRAME.defaultBlockState().setValue(EndPortalFrameBlock.FACING, Direction.SOUTH); ++ IBlockData iblockdata5 = (IBlockData) Blocks.END_PORTAL_FRAME.defaultBlockState().setValue(EndPortalFrameBlock.FACING, Direction.EAST); ++ IBlockData iblockdata6 = (IBlockData) Blocks.END_PORTAL_FRAME.defaultBlockState().setValue(EndPortalFrameBlock.FACING, Direction.WEST); ++ boolean flag1 = true; ++ boolean[] aboolean = new boolean[12]; ++ ++ for (int k = 0; k < aboolean.length; ++k) { ++ aboolean[k] = random.nextFloat() > 0.9F; ++ flag1 &= aboolean[k]; ++ } ++ ++ this.placeBlock(level, (IBlockData) iblockdata3.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[0]), 4, 3, 8, box); ++ this.placeBlock(level, (IBlockData) iblockdata3.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[1]), 5, 3, 8, box); ++ this.placeBlock(level, (IBlockData) iblockdata3.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[2]), 6, 3, 8, box); ++ this.placeBlock(level, (IBlockData) iblockdata4.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[3]), 4, 3, 12, box); ++ this.placeBlock(level, (IBlockData) iblockdata4.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[4]), 5, 3, 12, box); ++ this.placeBlock(level, (IBlockData) iblockdata4.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[5]), 6, 3, 12, box); ++ this.placeBlock(level, (IBlockData) iblockdata5.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[6]), 3, 3, 9, box); ++ this.placeBlock(level, (IBlockData) iblockdata5.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[7]), 3, 3, 10, box); ++ this.placeBlock(level, (IBlockData) iblockdata5.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[8]), 3, 3, 11, box); ++ this.placeBlock(level, (IBlockData) iblockdata6.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[9]), 7, 3, 9, box); ++ this.placeBlock(level, (IBlockData) iblockdata6.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[10]), 7, 3, 10, box); ++ this.placeBlock(level, (IBlockData) iblockdata6.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[11]), 7, 3, 11, box); ++ if (flag1) { ++ IBlockData iblockdata7 = Blocks.END_PORTAL.defaultBlockState(); ++ ++ this.placeBlock(level, iblockdata7, 4, 3, 9, box); ++ this.placeBlock(level, iblockdata7, 5, 3, 9, box); ++ this.placeBlock(level, iblockdata7, 6, 3, 9, box); ++ this.placeBlock(level, iblockdata7, 4, 3, 10, box); ++ this.placeBlock(level, iblockdata7, 5, 3, 10, box); ++ this.placeBlock(level, iblockdata7, 6, 3, 10, box); ++ this.placeBlock(level, iblockdata7, 4, 3, 11, box); ++ this.placeBlock(level, iblockdata7, 5, 3, 11, box); ++ this.placeBlock(level, iblockdata7, 6, 3, 11, box); ++ } ++ ++ if (!this.hasPlacedSpawner) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(5, 3, 6); ++ ++ if (box.isInside(blockposition_mutableblockposition)) { ++ this.hasPlacedSpawner = true; ++ // CraftBukkit start ++ /* ++ generatoraccessseed.setBlock(blockposition_mutableblockposition, Blocks.SPAWNER.defaultBlockState(), 2); ++ TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); ++ ++ if (tileentity instanceof TileEntityMobSpawner) { ++ TileEntityMobSpawner tileentitymobspawner = (TileEntityMobSpawner) tileentity; ++ ++ tileentitymobspawner.setEntityId(EntityTypes.SILVERFISH, randomsource); ++ } ++ */ ++ placeCraftSpawner(level, blockposition_mutableblockposition, org.bukkit.entity.EntityType.SILVERFISH, 2); ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java.patch new file mode 100644 index 0000000000..1849c3b3c4 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java +@@ -92,12 +94,13 @@ + BlockPos worldPos = this.getWorldPos(2, 2, 5); + if (box.isInside(worldPos)) { + this.spawnedWitch = true; +- Witch witch = EntityType.WITCH.create(level.getLevel()); +- if (witch != null) { +- witch.setPersistenceRequired(); +- witch.moveTo((double)worldPos.getX() + 0.5, (double)worldPos.getY(), (double)worldPos.getZ() + 0.5, 0.0F, 0.0F); +- witch.finalizeSpawn(level, level.getCurrentDifficultyAt(worldPos), MobSpawnType.STRUCTURE, null, null); +- level.addFreshEntityWithPassengers(witch); ++ Witch entitywitch = (Witch) EntityType.WITCH.create(level.getLevel()); ++ ++ if (entitywitch != null) { ++ entitywitch.setPersistenceRequired(); ++ entitywitch.moveTo((double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + 0.5D, 0.0F, 0.0F); ++ entitywitch.finalizeSpawn(level, level.getCurrentDifficultyAt(blockposition_mutableblockposition), EnumMobSpawn.STRUCTURE, (GroupDataEntity) null, (CompoundTag) null); ++ level.addFreshEntityWithPassengers(entitywitch, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN); // CraftBukkit - add SpawnReason + } + } + } +@@ -111,12 +115,13 @@ + BlockPos worldPos = this.getWorldPos(2, 2, 5); + if (box.isInside(worldPos)) { + this.spawnedCat = true; +- Cat cat = EntityType.CAT.create(level.getLevel()); +- if (cat != null) { +- cat.setPersistenceRequired(); +- cat.moveTo((double)worldPos.getX() + 0.5, (double)worldPos.getY(), (double)worldPos.getZ() + 0.5, 0.0F, 0.0F); +- cat.finalizeSpawn(level, level.getCurrentDifficultyAt(worldPos), MobSpawnType.STRUCTURE, null, null); +- level.addFreshEntityWithPassengers(cat); ++ Cat entitycat = (Cat) EntityType.CAT.create(level.getLevel()); ++ ++ if (entitycat != null) { ++ entitycat.setPersistenceRequired(); ++ entitycat.moveTo((double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + 0.5D, 0.0F, 0.0F); ++ entitycat.finalizeSpawn(level, level.getCurrentDifficultyAt(blockposition_mutableblockposition), EnumMobSpawn.STRUCTURE, (GroupDataEntity) null, (CompoundTag) null); ++ level.addFreshEntityWithPassengers(entitycat, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN); // CraftBukkit - add SpawnReason + } + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings.java.patch new file mode 100644 index 0000000000..2552b5982c --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings.java.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings.java ++++ b/net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings.java +@@ -21,8 +22,8 @@ + private boolean keepLiquids = true; + @Nullable + private RandomSource random; +- private int palette; +- private final List processors = Lists.newArrayList(); ++ public int palette = -1; // CraftBukkit - Set initial value so we know if the palette has been set forcefully ++ private final List processors; + private boolean knownShape; + private boolean finalizeEntities; + +@@ -142,6 +149,13 @@ + int size = palettes.size(); + if (size == 0) { + throw new IllegalStateException("No palettes"); ++ // CraftBukkit start ++ } else if (this.palette > 0) { ++ if (this.palette >= i) { ++ throw new IllegalArgumentException("Palette index out of bounds. Got " + this.palette + " where there are only " + i + " palettes available."); ++ } ++ return palettes.get(this.palette); ++ // CraftBukkit end + } else { + return palettes.get(this.getRandom(pos).nextInt(size)); + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java.patch new file mode 100644 index 0000000000..b8119871ce --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java.patch @@ -0,0 +1,158 @@ +--- a/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java ++++ b/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java +@@ -50,6 +52,9 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.BitSetDiscreteVoxelShape; + import net.minecraft.world.phys.shapes.DiscreteVoxelShape; ++import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer; ++import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry; ++// CraftBukkit end + + public class StructureTemplate { + public static final String PALETTE_TAG = "palette"; +@@ -68,6 +74,16 @@ + private Vec3i size = Vec3i.ZERO; + private String author = "?"; + ++ // CraftBukkit start - data containers ++ private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); ++ public CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); ++ // CraftBukkit end ++ ++ public StructureTemplate() { ++ this.size = Vec3i.ZERO; ++ this.author = "?"; ++ } ++ + public Vec3i getSize() { + return this.size; + } +@@ -216,6 +238,19 @@ + if (this.palettes.isEmpty()) { + return false; + } else { ++ // CraftBukkit start ++ // We only want the TransformerGeneratorAccess at certain locations because in here are many "block update" calls that shouldn't be transformed ++ ServerLevelAccessor wrappedAccess = serverLevel; ++ org.bukkit.craftbukkit.util.CraftStructureTransformer structureTransformer = null; ++ if (wrappedAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ serverLevel = transformerAccess.getHandle(); ++ structureTransformer = transformerAccess.getStructureTransformer(); ++ // The structureTransformer is not needed if we can not transform blocks therefore we can save a little bit of performance doing this ++ if (structureTransformer != null && !structureTransformer.canTransformBlocks()) { ++ structureTransformer = null; ++ } ++ } ++ // CraftBukkit end + List list = settings.getRandomPalette(this.palettes, offset).blocks(); + if ((!list.isEmpty() || !settings.isIgnoreEntities() && !this.entityInfoList.isEmpty()) + && this.size.getX() >= 1 +@@ -242,20 +282,34 @@ + Clearable.tryClear(blockEntity); + serverLevel.setBlock(blockPos, Blocks.BARRIER.defaultBlockState(), 20); + } ++ // CraftBukkit start ++ if (structureTransformer != null) { ++ org.bukkit.craftbukkit.block.CraftBlockState craftBlockState = (org.bukkit.craftbukkit.block.CraftBlockState) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockposition2, iblockdata, null); ++ if (definedstructure_blockinfo.nbt != null && craftBlockState instanceof org.bukkit.craftbukkit.block.CraftBlockEntityState entityState) { ++ entityState.loadData(definedstructure_blockinfo.nbt); ++ if (craftBlockState instanceof org.bukkit.craftbukkit.block.CraftLootable craftLootable) { ++ craftLootable.setSeed(random.nextLong()); ++ } ++ } ++ craftBlockState = structureTransformer.transformCraftState(craftBlockState); ++ iblockdata = craftBlockState.getHandle(); ++ definedstructure_blockinfo = new StructureTemplate.StructureBlockInfo(blockposition2, iblockdata, (craftBlockState instanceof org.bukkit.craftbukkit.block.CraftBlockEntityState craftBlockEntityState ? craftBlockEntityState.getSnapshotNBT() : null)); ++ } ++ // CraftBukkit end + +- if (serverLevel.setBlock(blockPos, blockState, flags)) { +- i = Math.min(i, blockPos.getX()); +- i1 = Math.min(i1, blockPos.getY()); +- i2 = Math.min(i2, blockPos.getZ()); +- i3 = Math.max(i3, blockPos.getX()); +- i4 = Math.max(i4, blockPos.getY()); +- i5 = Math.max(i5, blockPos.getZ()); +- list3.add(Pair.of(blockPos, structureBlockInfo.nbt)); +- if (structureBlockInfo.nbt != null) { +- BlockEntity blockEntity = serverLevel.getBlockEntity(blockPos); +- if (blockEntity != null) { +- if (blockEntity instanceof RandomizableContainer) { +- structureBlockInfo.nbt.putLong("LootTableSeed", random.nextLong()); ++ if (serverLevel.setBlock(blockposition2, iblockdata, flags)) { ++ j = Math.min(j, blockposition2.getX()); ++ k = Math.min(k, blockposition2.getY()); ++ l = Math.min(l, blockposition2.getZ()); ++ i1 = Math.max(i1, blockposition2.getX()); ++ j1 = Math.max(j1, blockposition2.getY()); ++ k1 = Math.max(k1, blockposition2.getZ()); ++ list3.add(Pair.of(blockposition2, definedstructure_blockinfo.nbt)); ++ if (definedstructure_blockinfo.nbt != null) { ++ tileentity = serverLevel.getBlockEntity(blockposition2); ++ if (tileentity != null) { ++ if (structureTransformer == null && tileentity instanceof RandomizableContainer) { // CraftBukkit - only process if don't have a transformer access (Was already set above) - SPIGOT-7520: Use structureTransformer as check, so that it is the same as above ++ definedstructure_blockinfo.nbt.putLong("LootTableSeed", random.nextLong()); + } + + blockEntity.load(structureBlockInfo.nbt); +@@ -344,15 +413,7 @@ + } + + if (!settings.isIgnoreEntities()) { +- this.placeEntities( +- serverLevel, +- offset, +- settings.getMirror(), +- settings.getRotation(), +- settings.getRotationPivot(), +- boundingBox, +- settings.shouldFinalizeEntities() +- ); ++ this.placeEntities(wrappedAccess, offset, settings.getMirror(), settings.getRotation(), settings.getRotationPivot(), structureboundingbox, settings.shouldFinalizeEntities()); // CraftBukkit + } + + return true; +@@ -452,11 +508,13 @@ + } + + private static Optional createEntityIgnoreException(ServerLevelAccessor level, CompoundTag tag) { +- try { ++ // CraftBukkit start ++ // try { + return EntityType.create(tag, level.getLevel()); +- } catch (Exception var3) { +- return Optional.empty(); +- } ++ // } catch (Exception exception) { ++ // return Optional.empty(); ++ // } ++ // CraftBukkit end + } + + public Vec3i getSize(Rotation rotation) { +@@ -649,6 +728,11 @@ + + tag.put("entities", list5); + tag.put("size", this.newIntegerList(this.size.getX(), this.size.getY(), this.size.getZ())); ++ // CraftBukkit start - PDC ++ if (!this.persistentDataContainer.isEmpty()) { ++ tag.put("BukkitValues", this.persistentDataContainer.toTagCompound()); ++ } ++ // CraftBukkit end + return NbtUtils.addCurrentDataVersion(tag); + } + +@@ -681,6 +771,13 @@ + this.entityInfoList.add(new StructureTemplate.StructureEntityInfo(vec3, blockPos, compound1)); + } + } ++ ++ // CraftBukkit start - PDC ++ Tag base = tag.get("BukkitValues"); ++ if (base instanceof CompoundTag) { ++ this.persistentDataContainer.putAll((CompoundTag) base); ++ } ++ // CraftBukkit end + } + + private void loadPalette(HolderGetter blockGetter, ListTag paletteTag, ListTag blocksTag) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/material/FlowingFluid.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/material/FlowingFluid.java.patch new file mode 100644 index 0000000000..76aac7251d --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/material/FlowingFluid.java.patch @@ -0,0 +1,120 @@ +--- a/net/minecraft/world/level/material/FlowingFluid.java ++++ b/net/minecraft/world/level/material/FlowingFluid.java +@@ -29,6 +31,14 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.block.BlockFace; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.block.BlockFromToEvent; ++import org.bukkit.event.block.FluidLevelChangeEvent; ++// CraftBukkit end + + public abstract class FlowingFluid extends Fluid { + public static final BooleanProperty FALLING = BlockStateProperties.FALLING; +@@ -111,12 +134,22 @@ + + protected void spread(Level level, BlockPos pos, FluidState state) { + if (!state.isEmpty()) { +- BlockState blockState = level.getBlockState(pos); +- BlockPos blockPos = pos.below(); +- BlockState blockState1 = level.getBlockState(blockPos); +- FluidState newLiquid = this.getNewLiquid(level, blockPos, blockState1); +- if (this.canSpreadTo(level, pos, blockState, Direction.DOWN, blockPos, blockState1, level.getFluidState(blockPos), newLiquid.getType())) { +- this.spreadTo(level, blockPos, blockState1, Direction.DOWN, newLiquid); ++ IBlockData iblockdata = level.getBlockState(pos); ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ FluidState fluid1 = this.getNewLiquid(level, blockposition1, iblockdata1); ++ ++ if (this.canSpreadTo(level, pos, iblockdata, Direction.DOWN, blockposition1, iblockdata1, level.getFluidState(blockposition1), fluid1.getType())) { ++ // CraftBukkit start ++ org.bukkit.block.Block source = CraftBlock.at(level, pos); ++ BlockFromToEvent event = new BlockFromToEvent(source, BlockFace.DOWN); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ this.spreadTo(level, blockposition1, iblockdata1, Direction.DOWN, fluid1); + if (this.sourceNeighborCount(level, pos) >= 3) { + this.spreadToSides(level, pos, state, blockState); + } +@@ -135,13 +171,24 @@ + if (i > 0) { + Map spread = this.getSpread(level, pos, blockState); + +- for (Entry entry : spread.entrySet()) { +- Direction direction = entry.getKey(); +- FluidState fluidState1 = entry.getValue(); +- BlockPos blockPos = pos.relative(direction); +- BlockState blockState1 = level.getBlockState(blockPos); +- if (this.canSpreadTo(level, pos, blockState, direction, blockPos, blockState1, level.getFluidState(blockPos), fluidState1.getType())) { +- this.spreadTo(level, blockPos, blockState1, direction, fluidState1); ++ while (iterator.hasNext()) { ++ Entry entry = (Entry) iterator.next(); ++ Direction enumdirection = (Direction) entry.getKey(); ++ FluidState fluid1 = (FluidState) entry.getValue(); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ if (this.canSpreadTo(level, pos, blockState, enumdirection, blockposition1, iblockdata1, level.getFluidState(blockposition1), fluid1.getType())) { ++ // CraftBukkit start ++ org.bukkit.block.Block source = CraftBlock.at(level, pos); ++ BlockFromToEvent event = new BlockFromToEvent(source, org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(enumdirection)); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end ++ this.spreadTo(level, blockposition1, iblockdata1, enumdirection, fluid1); + } + } + } +@@ -415,17 +459,30 @@ + @Override + public void tick(Level level, BlockPos pos, FluidState state) { + if (!state.isSource()) { +- FluidState newLiquid = this.getNewLiquid(level, pos, level.getBlockState(pos)); +- int spreadDelay = this.getSpreadDelay(level, pos, state, newLiquid); +- if (newLiquid.isEmpty()) { +- state = newLiquid; +- level.setBlock(pos, Blocks.AIR.defaultBlockState(), 3); +- } else if (!newLiquid.equals(state)) { +- state = newLiquid; +- BlockState blockState = newLiquid.createLegacyBlock(); +- level.setBlock(pos, blockState, 2); +- level.scheduleTick(pos, newLiquid.getType(), spreadDelay); +- level.updateNeighborsAt(pos, blockState.getBlock()); ++ FluidState fluid1 = this.getNewLiquid(level, pos, level.getBlockState(pos)); ++ int i = this.getSpreadDelay(level, pos, state, fluid1); ++ ++ if (fluid1.isEmpty()) { ++ state = fluid1; ++ // CraftBukkit start ++ FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(level, pos, Blocks.AIR.defaultBlockState()); ++ if (event.isCancelled()) { ++ return; ++ } ++ level.setBlock(pos, ((CraftBlockData) event.getNewData()).getState(), 3); ++ // CraftBukkit end ++ } else if (!fluid1.equals(state)) { ++ state = fluid1; ++ IBlockData iblockdata = fluid1.createLegacyBlock(); ++ // CraftBukkit start ++ FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(level, pos, iblockdata); ++ if (event.isCancelled()) { ++ return; ++ } ++ level.setBlock(pos, ((CraftBlockData) event.getNewData()).getState(), 2); ++ // CraftBukkit end ++ level.scheduleTick(pos, fluid1.getType(), i); ++ level.updateNeighborsAt(pos, iblockdata.getBlock()); + } + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/material/LavaFluid.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/material/LavaFluid.java.patch new file mode 100644 index 0000000000..c36dbb9da2 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/material/LavaFluid.java.patch @@ -0,0 +1,57 @@ +--- a/net/minecraft/world/level/material/LavaFluid.java ++++ b/net/minecraft/world/level/material/LavaFluid.java +@@ -84,10 +80,18 @@ + return; + } + +- BlockState blockState = level.getBlockState(blockPos); +- if (blockState.isAir()) { +- if (this.hasFlammableNeighbours(level, blockPos)) { +- level.setBlockAndUpdate(blockPos, BaseFireBlock.getState(level, blockPos)); ++ IBlockData iblockdata = level.getBlockState(blockposition1); ++ ++ if (iblockdata.isAir()) { ++ if (this.hasFlammableNeighbours(level, blockposition1)) { ++ // CraftBukkit start - Prevent lava putting something on fire ++ if (level.getBlockState(blockposition1).getBlock() != Blocks.FIRE) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, blockposition1, pos).isCancelled()) { ++ continue; ++ } ++ } ++ // CraftBukkit end ++ level.setBlockAndUpdate(blockposition1, BaseFireBlock.getState(level, blockposition1)); + return; + } + } else if (blockState.blocksMotion()) { +@@ -101,8 +106,16 @@ + return; + } + +- if (level.isEmptyBlock(blockPos1.above()) && this.isFlammable(level, blockPos1)) { +- level.setBlockAndUpdate(blockPos1.above(), BaseFireBlock.getState(level, blockPos1)); ++ if (level.isEmptyBlock(blockposition2.above()) && this.isFlammable(level, blockposition2)) { ++ // CraftBukkit start - Prevent lava putting something on fire ++ BlockPos up = blockposition2.above(); ++ if (level.getBlockState(up).getBlock() != Blocks.FIRE) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, up, pos).isCancelled()) { ++ continue; ++ } ++ } ++ // CraftBukkit end ++ level.setBlockAndUpdate(blockposition2.above(), BaseFireBlock.getState(level, blockposition2)); + } + } + } +@@ -195,7 +210,11 @@ + FluidState fluidState1 = level.getFluidState(pos); + if (this.is(FluidTags.LAVA) && fluidState1.is(FluidTags.WATER)) { + if (blockState.getBlock() instanceof LiquidBlock) { +- level.setBlock(pos, Blocks.STONE.defaultBlockState(), 3); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level.getMinecraftWorld(), pos, Blocks.STONE.defaultBlockState(), 3)) { ++ return; ++ } ++ // CraftBukkit end + } + + this.fizz(level, pos); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/portal/PortalForcer.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/portal/PortalForcer.java.patch new file mode 100644 index 0000000000..0688334b1a --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/portal/PortalForcer.java.patch @@ -0,0 +1,176 @@ +--- a/net/minecraft/world/level/portal/PortalForcer.java ++++ b/net/minecraft/world/level/portal/PortalForcer.java +@@ -41,42 +42,56 @@ + } + + public Optional findPortalAround(BlockPos pos, boolean isNether, WorldBorder worldBorder) { +- PoiManager poiManager = this.level.getPoiManager(); +- int i = isNether ? 16 : 128; +- poiManager.ensureLoadedAndValid(this.level, pos, i); +- Optional optional = poiManager.getInSquare(poiType -> poiType.is(PoiTypes.NETHER_PORTAL), pos, i, PoiManager.Occupancy.ANY) +- .filter(poiRecord -> worldBorder.isWithinBounds(poiRecord.getPos())) +- .sorted( +- Comparator.comparingDouble(poiRecord -> poiRecord.getPos().distSqr(pos)).thenComparingInt(poiRecord -> poiRecord.getPos().getY()) +- ) +- .filter(poiRecord -> this.level.getBlockState(poiRecord.getPos()).hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) +- .findFirst(); +- return optional.map( +- poiRecord -> { +- BlockPos pos1 = poiRecord.getPos(); +- this.level.getChunkSource().addRegionTicket(TicketType.PORTAL, new ChunkPos(pos1), 3, pos1); +- BlockState blockState = this.level.getBlockState(pos1); +- return BlockUtil.getLargestRectangleAround( +- pos1, +- blockState.getValue(BlockStateProperties.HORIZONTAL_AXIS), +- 21, +- Direction.Axis.Y, +- 21, +- possibleBlockPos -> this.level.getBlockState(possibleBlockPos) == blockState +- ); +- } +- ); ++ // CraftBukkit start ++ return findPortalAround(pos, worldBorder, isNether ? 16 : 128); // Search Radius + } + ++ public Optional findPortalAround(BlockPos blockposition, WorldBorder worldborder, int i) { ++ PoiManager villageplace = this.level.getPoiManager(); ++ // int i = flag ? 16 : 128; ++ // CraftBukkit end ++ ++ villageplace.ensureLoadedAndValid(this.level, blockposition, i); ++ Optional optional = villageplace.getInSquare((holder) -> { ++ return holder.is(PoiTypes.NETHER_PORTAL); ++ }, blockposition, i, PoiManager.Occupancy.ANY).filter((villageplacerecord) -> { ++ return worldborder.isWithinBounds(villageplacerecord.getPos()); ++ }).sorted(Comparator.comparingDouble((PoiRecord villageplacerecord) -> { // CraftBukkit - decompile error ++ return villageplacerecord.getPos().distSqr(blockposition); ++ }).thenComparingInt((villageplacerecord) -> { ++ return villageplacerecord.getPos().getY(); ++ })).filter((villageplacerecord) -> { ++ return this.level.getBlockState(villageplacerecord.getPos()).hasProperty(BlockStateProperties.HORIZONTAL_AXIS); ++ }).findFirst(); ++ ++ return optional.map((villageplacerecord) -> { ++ BlockPos blockposition1 = villageplacerecord.getPos(); ++ ++ this.level.getChunkSource().addRegionTicket(TicketType.PORTAL, new ChunkPos(blockposition1), 3, blockposition1); ++ IBlockData iblockdata = this.level.getBlockState(blockposition1); ++ ++ return BlockUtil.getLargestRectangleAround(blockposition1, (Direction.Axis) iblockdata.getValue(BlockStateProperties.HORIZONTAL_AXIS), 21, Direction.Axis.Y, 21, (blockposition2) -> { ++ return this.level.getBlockState(blockposition2) == iblockdata; ++ }); ++ }); ++ } ++ + public Optional createPortal(BlockPos pos, Direction.Axis axis) { +- Direction direction = Direction.get(Direction.AxisDirection.POSITIVE, axis); +- double d = -1.0; +- BlockPos blockPos = null; +- double d1 = -1.0; +- BlockPos blockPos1 = null; +- WorldBorder worldBorder = this.level.getWorldBorder(); ++ // CraftBukkit start ++ return this.createPortal(pos, axis, null, 16); ++ } ++ ++ public Optional createPortal(BlockPos blockposition, Direction.Axis enumdirection_enumaxis, net.minecraft.world.entity.Entity entity, int createRadius) { ++ // CraftBukkit end ++ Direction enumdirection = Direction.get(Direction.AxisDirection.POSITIVE, enumdirection_enumaxis); ++ double d0 = -1.0D; ++ BlockPos blockposition1 = null; ++ double d1 = -1.0D; ++ BlockPos blockposition2 = null; ++ WorldBorder worldborder = this.level.getWorldBorder(); + int i = Math.min(this.level.getMaxBuildHeight(), this.level.getMinBuildHeight() + this.level.getLogicalHeight()) - 1; +- BlockPos.MutableBlockPos mutableBlockPos = pos.mutable(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = blockposition.mutable(); ++ Iterator iterator = BlockPos.spiralAround(blockposition, createRadius, Direction.EAST, Direction.SOUTH).iterator(); // CraftBukkit + + for (BlockPos.MutableBlockPos mutableBlockPos1 : BlockPos.spiralAround(pos, 16, Direction.EAST, Direction.SOUTH)) { + int min = Math.min(i, this.level.getHeight(Heightmap.Types.MOTION_BLOCKING, mutableBlockPos1.getX(), mutableBlockPos1.getZ())); +@@ -123,10 +143,14 @@ + d = d1; + } + +- if (d == -1.0) { +- int max = Math.max(this.level.getMinBuildHeight() - -1, 70); +- int i5 = i - 9; +- if (i5 < max) { ++ int j1; ++ int k1; ++ ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(this.level); // CraftBukkit - Use BlockStateListPopulator ++ if (d0 == -1.0D) { ++ j1 = Math.max(this.level.getMinBuildHeight() - -1, 70); ++ k1 = i - 9; ++ if (k1 < j1) { + return Optional.empty(); + } + +@@ -136,38 +161,47 @@ + return Optional.empty(); + } + +- for (int i1 = -1; i1 < 2; i1++) { +- for (int i2x = 0; i2x < 2; i2x++) { +- for (int i3 = -1; i3 < 3; i3++) { +- BlockState blockState = i3 < 0 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); +- mutableBlockPos.setWithOffset( +- blockPos, i2x * direction.getStepX() + i1 * clockWise.getStepX(), i3, i2x * direction.getStepZ() + i1 * clockWise.getStepZ() +- ); +- this.level.setBlockAndUpdate(mutableBlockPos, blockState); ++ for (int l1 = -1; l1 < 2; ++l1) { ++ for (k = 0; k < 2; ++k) { ++ for (l = -1; l < 3; ++l) { ++ IBlockData iblockdata = l < 0 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); ++ ++ blockposition_mutableblockposition.setWithOffset(blockposition1, k * enumdirection.getStepX() + l1 * enumdirection1.getStepX(), l, k * enumdirection.getStepZ() + l1 * enumdirection1.getStepZ()); ++ blockList.setBlock(blockposition_mutableblockposition, iblockdata, 3); // CraftBukkit + } + } + } + } + +- for (int maxx = -1; maxx < 3; maxx++) { +- for (int i5x = -1; i5x < 4; i5x++) { +- if (maxx == -1 || maxx == 2 || i5x == -1 || i5x == 3) { +- mutableBlockPos.setWithOffset(blockPos, maxx * direction.getStepX(), i5x, maxx * direction.getStepZ()); +- this.level.setBlock(mutableBlockPos, Blocks.OBSIDIAN.defaultBlockState(), 3); ++ for (j1 = -1; j1 < 3; ++j1) { ++ for (k1 = -1; k1 < 4; ++k1) { ++ if (j1 == -1 || j1 == 2 || k1 == -1 || k1 == 3) { ++ blockposition_mutableblockposition.setWithOffset(blockposition1, j1 * enumdirection.getStepX(), k1, j1 * enumdirection.getStepZ()); ++ blockList.setBlock(blockposition_mutableblockposition, Blocks.OBSIDIAN.defaultBlockState(), 3); // CraftBukkit + } + } + } + + BlockState blockState1 = Blocks.NETHER_PORTAL.defaultBlockState().setValue(NetherPortalBlock.AXIS, axis); + +- for (int i5xx = 0; i5xx < 2; i5xx++) { +- for (int min = 0; min < 3; min++) { +- mutableBlockPos.setWithOffset(blockPos, i5xx * direction.getStepX(), min, i5xx * direction.getStepZ()); +- this.level.setBlock(mutableBlockPos, blockState1, 18); ++ for (k1 = 0; k1 < 2; ++k1) { ++ for (j = 0; j < 3; ++j) { ++ blockposition_mutableblockposition.setWithOffset(blockposition1, k1 * enumdirection.getStepX(), j, k1 * enumdirection.getStepZ()); ++ blockList.setBlock(blockposition_mutableblockposition, iblockdata1, 18); // CraftBukkit + } + } + +- return Optional.of(new BlockUtil.FoundRectangle(blockPos.immutable(), 2, 3)); ++ // CraftBukkit start ++ org.bukkit.World bworld = this.level.getWorld(); ++ org.bukkit.event.world.PortalCreateEvent event = new org.bukkit.event.world.PortalCreateEvent((java.util.List) (java.util.List) blockList.getList(), bworld, (entity == null) ? null : entity.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.NETHER_PAIR); ++ ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return Optional.empty(); ++ } ++ blockList.updateList(); ++ // CraftBukkit end ++ return Optional.of(new BlockUtil.FoundRectangle(blockposition1.immutable(), 2, 3)); + } + + private boolean canPortalReplaceBlock(BlockPos.MutableBlockPos pos) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/portal/PortalInfo.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/portal/PortalInfo.java.patch new file mode 100644 index 0000000000..902de997af --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/portal/PortalInfo.java.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/world/level/portal/PortalInfo.java ++++ b/net/minecraft/world/level/portal/PortalInfo.java +@@ -1,17 +2,25 @@ + package net.minecraft.world.level.portal; + + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.event.CraftPortalEvent; ++// CraftBukkit end + + public class PortalInfo { + public final Vec3 pos; + public final Vec3 speed; + public final float yRot; + public final float xRot; ++ // CraftBukkit start ++ public final ServerLevel world; ++ public final CraftPortalEvent portalEventInfo; + +- public PortalInfo(Vec3 pos, Vec3 speed, float yRot, float xRot) { +- this.pos = pos; +- this.speed = speed; +- this.yRot = yRot; +- this.xRot = xRot; ++ public PortalInfo(Vec3 vec3d, Vec3 vec3d1, float f, float f1, ServerLevel world, CraftPortalEvent portalEventInfo) { ++ this.world = world; ++ this.portalEventInfo = portalEventInfo; ++ // CraftBukkit end ++ this.pos = vec3d; ++ this.speed = vec3d1; ++ this.yRot = f; ++ this.xRot = f1; + } + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/portal/PortalShape.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/portal/PortalShape.java.patch new file mode 100644 index 0000000000..44dc6ce9ca --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/portal/PortalShape.java.patch @@ -0,0 +1,150 @@ +--- a/net/minecraft/world/level/portal/PortalShape.java ++++ b/net/minecraft/world/level/portal/PortalShape.java +@@ -22,6 +21,10 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftPortalEvent; ++import org.bukkit.event.world.PortalCreateEvent; ++// CraftBukkit end + + public class PortalShape { + private static final int MIN_WIDTH = 2; +@@ -39,6 +45,7 @@ + private BlockPos bottomLeft; + private int height; + private final int width; ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blocks; // CraftBukkit - add field + + public static Optional findEmptyPortalShape(LevelAccessor level, BlockPos bottomLeft, Direction.Axis axis) { + return findPortalShape(level, bottomLeft, shape -> shape.isValid() && shape.numPortalBlocks == 0, axis); +@@ -55,6 +66,7 @@ + } + + public PortalShape(LevelAccessor level, BlockPos bottomLeft, Direction.Axis axis) { ++ blocks = new org.bukkit.craftbukkit.util.BlockStateListPopulator(level.getMinecraftWorld()); // CraftBukkit + this.level = level; + this.axis = axis; + this.rightDir = axis == Direction.Axis.X ? Direction.WEST : Direction.SOUTH; +@@ -92,11 +105,13 @@ + private int getDistanceUntilEdgeAboveFrame(BlockPos pos, Direction direction) { + BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); + +- for (int i = 0; i <= 21; i++) { +- mutableBlockPos.set(pos).move(direction, i); +- BlockState blockState = this.level.getBlockState(mutableBlockPos); +- if (!isEmpty(blockState)) { +- if (FRAME.test(blockState, this.level, mutableBlockPos)) { ++ for (int i = 0; i <= 21; ++i) { ++ blockposition_mutableblockposition.set(pos).move(direction, i); ++ IBlockData iblockdata = this.level.getBlockState(blockposition_mutableblockposition); ++ ++ if (!isEmpty(iblockdata)) { ++ if (PortalShape.FRAME.test(iblockdata, this.level, blockposition_mutableblockposition)) { ++ blocks.setBlock(blockposition_mutableblockposition, iblockdata, 18); // CraftBukkit - lower left / right + return i; + } + break; +@@ -106,6 +122,7 @@ + if (!FRAME.test(blockState1, this.level, mutableBlockPos)) { + break; + } ++ blocks.setBlock(blockposition_mutableblockposition, iblockdata1, 18); // CraftBukkit - bottom row + } + + return 0; +@@ -123,6 +142,7 @@ + if (!FRAME.test(this.level.getBlockState(mutableBlockPos), this.level, mutableBlockPos)) { + return false; + } ++ blocks.setBlock(blockposition_mutableblockposition1, this.level.getBlockState(blockposition_mutableblockposition1), 18); // CraftBukkit - upper row + } + + return true; +@@ -151,6 +172,10 @@ + this.numPortalBlocks++; + } + } ++ // CraftBukkit start - left and right ++ blocks.setBlock(pos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, -1), this.level.getBlockState(pos), 18); ++ blocks.setBlock(pos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, this.width), this.level.getBlockState(pos), 18); ++ // CraftBukkit end + } + + return 21; +@@ -164,10 +189,28 @@ + return this.bottomLeft != null && this.width >= 2 && this.width <= 21 && this.height >= 3 && this.height <= 21; + } + +- public void createPortalBlocks() { +- BlockState blockState = Blocks.NETHER_PORTAL.defaultBlockState().setValue(NetherPortalBlock.AXIS, this.axis); +- BlockPos.betweenClosed(this.bottomLeft, this.bottomLeft.relative(Direction.UP, this.height - 1).relative(this.rightDir, this.width - 1)) +- .forEach(pos -> this.level.setBlock(pos, blockState, 18)); ++ // CraftBukkit start - return boolean ++ public boolean createPortalBlocks() { ++ org.bukkit.World bworld = this.level.getMinecraftWorld().getWorld(); ++ ++ // Copy below for loop ++ IBlockData iblockdata = (IBlockData) Blocks.NETHER_PORTAL.defaultBlockState().setValue(NetherPortalBlock.AXIS, this.axis); ++ ++ BlockPos.betweenClosed(this.bottomLeft, this.bottomLeft.relative(Direction.UP, this.height - 1).relative(this.rightDir, this.width - 1)).forEach((blockposition) -> { ++ blocks.setBlock(blockposition, iblockdata, 18); ++ }); ++ ++ PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) blocks.getList(), bworld, null, PortalCreateEvent.CreateReason.FIRE); ++ this.level.getMinecraftWorld().getServer().server.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ BlockPos.betweenClosed(this.bottomLeft, this.bottomLeft.relative(Direction.UP, this.height - 1).relative(this.rightDir, this.width - 1)).forEach((blockposition) -> { ++ this.level.setBlock(blockposition, iblockdata, 18); ++ }); ++ return true; // CraftBukkit + } + + public boolean isComplete() { +@@ -199,24 +246,23 @@ + return new Vec3(d3, d2, d4); + } + +- public static PortalInfo createPortalInfo( +- ServerLevel level, BlockUtil.FoundRectangle portalPos, Direction.Axis axis, Vec3 relativePos, Entity entity, Vec3 velocity, float yRot, float xRot +- ) { +- BlockPos blockPos = portalPos.minCorner; +- BlockState blockState = level.getBlockState(blockPos); +- Direction.Axis axis1 = blockState.getOptionalValue(BlockStateProperties.HORIZONTAL_AXIS).orElse(Direction.Axis.X); +- double d = (double)portalPos.axis1Size; +- double d1 = (double)portalPos.axis2Size; +- EntityDimensions dimensions = entity.getDimensions(entity.getPose()); +- int i = axis == axis1 ? 0 : 90; +- Vec3 vec3 = axis == axis1 ? velocity : new Vec3(velocity.z, velocity.y, -velocity.x); +- double d2 = (double)dimensions.width / 2.0 + (d - (double)dimensions.width) * relativePos.x(); +- double d3 = (d1 - (double)dimensions.height) * relativePos.y(); +- double d4 = 0.5 + relativePos.z(); +- boolean flag = axis1 == Direction.Axis.X; +- Vec3 vec31 = new Vec3((double)blockPos.getX() + (flag ? d2 : d4), (double)blockPos.getY() + d3, (double)blockPos.getZ() + (flag ? d4 : d2)); +- Vec3 vec32 = findCollisionFreePosition(vec31, level, entity, dimensions); +- return new PortalInfo(vec32, vec3, yRot + (float)i, xRot); ++ public static PortalInfo createPortalInfo(ServerLevel worldserver, BlockUtil.FoundRectangle blockutil_rectangle, Direction.Axis enumdirection_enumaxis, Vec3 vec3d, Entity entity, Vec3 vec3d1, float f, float f1, CraftPortalEvent portalEventInfo) { // CraftBukkit ++ BlockPos blockposition = blockutil_rectangle.minCorner; ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ Direction.Axis enumdirection_enumaxis1 = (Direction.Axis) iblockdata.getOptionalValue(BlockStateProperties.HORIZONTAL_AXIS).orElse(Direction.Axis.X); ++ double d0 = (double) blockutil_rectangle.axis1Size; ++ double d1 = (double) blockutil_rectangle.axis2Size; ++ EntityDimensions entitysize = entity.getDimensions(entity.getPose()); ++ int i = enumdirection_enumaxis == enumdirection_enumaxis1 ? 0 : 90; ++ Vec3 vec3d2 = enumdirection_enumaxis == enumdirection_enumaxis1 ? vec3d1 : new Vec3(vec3d1.z, vec3d1.y, -vec3d1.x); ++ double d2 = (double) entitysize.width / 2.0D + (d0 - (double) entitysize.width) * vec3d.x(); ++ double d3 = (d1 - (double) entitysize.height) * vec3d.y(); ++ double d4 = 0.5D + vec3d.z(); ++ boolean flag = enumdirection_enumaxis1 == Direction.Axis.X; ++ Vec3 vec3d3 = new Vec3((double) blockposition.getX() + (flag ? d2 : d4), (double) blockposition.getY() + d3, (double) blockposition.getZ() + (flag ? d4 : d2)); ++ Vec3 vec3d4 = findCollisionFreePosition(vec3d3, worldserver, entity, entitysize); ++ ++ return new PortalInfo(vec3d4, vec3d2, f + (float) i, f1, worldserver, portalEventInfo); // CraftBukkit + } + + private static Vec3 findCollisionFreePosition(Vec3 pos, ServerLevel level, Entity entity, EntityDimensions dimensions) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/redstone/NeighborUpdater.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/redstone/NeighborUpdater.java.patch new file mode 100644 index 0000000000..f74d683981 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/redstone/NeighborUpdater.java.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/level/redstone/NeighborUpdater.java ++++ b/net/minecraft/world/level/redstone/NeighborUpdater.java +@@ -11,7 +12,12 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.Block; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.event.block.BlockPhysicsEvent; ++// CraftBukkit end + + public interface NeighborUpdater { + Direction[] UPDATE_ORDER = new Direction[]{Direction.WEST, Direction.EAST, Direction.DOWN, Direction.UP, Direction.NORTH, Direction.SOUTH}; +@@ -40,6 +52,17 @@ + + static void executeUpdate(Level level, BlockState state, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston) { + try { ++ // CraftBukkit start ++ CraftWorld cworld = ((ServerLevel) level).getWorld(); ++ if (cworld != null) { ++ BlockPhysicsEvent event = new BlockPhysicsEvent(CraftBlock.at(level, pos), CraftBlockData.fromData(state), CraftBlock.at(level, neighborPos)); ++ ((ServerLevel) level).getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + state.neighborChanged(level, pos, neighborBlock, neighborPos, movedByPiston); + } catch (Throwable var9) { + CrashReport crashReport = CrashReport.forThrowable(var9, "Exception while updating neighbours"); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java.patch new file mode 100644 index 0000000000..5db06ac6bc --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java.patch @@ -0,0 +1,182 @@ +--- a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java ++++ b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +@@ -31,6 +33,15 @@ + import net.minecraft.world.level.saveddata.SavedData; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.UUID; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.map.CraftMapView; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++// CraftBukkit end ++ + public class MapItemSavedData extends SavedData { + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int MAP_SIZE = 128; +@@ -52,8 +64,15 @@ + private final Map frameMarkers = Maps.newHashMap(); + private int trackedDecorationCount; + +- public static SavedData.Factory factory() { +- return new SavedData.Factory<>(() -> { ++ // CraftBukkit start ++ public final CraftMapView mapView; ++ private CraftServer server; ++ public UUID uniqueId = null; ++ public String id; ++ // CraftBukkit end ++ ++ public static SavedData.a factory() { ++ return new SavedData.a<>(() -> { + throw new IllegalStateException("Should never create an empty map saved data"); + }, MapItemSavedData::load, DataFixTypes.SAVED_DATA_MAP_DATA); + } +@@ -67,6 +86,10 @@ + this.unlimitedTracking = unlimitedTracking; + this.locked = locked; + this.setDirty(); ++ // CraftBukkit start ++ mapView = new CraftMapView(this); ++ server = (CraftServer) org.bukkit.Bukkit.getServer(); ++ // CraftBukkit end + } + + public static MapItemSavedData createFresh( +@@ -85,12 +107,34 @@ + } + + public static MapItemSavedData load(CompoundTag compoundTag) { +- ResourceKey resourceKey = DimensionType.parseLegacy(new Dynamic<>(NbtOps.INSTANCE, compoundTag.get("dimension"))) +- .resultOrPartial(LOGGER::error) +- .orElseThrow(() -> new IllegalArgumentException("Invalid map dimension: " + compoundTag.get("dimension"))); +- int _int = compoundTag.getInt("xCenter"); +- int _int1 = compoundTag.getInt("zCenter"); +- byte b = (byte)Mth.clamp(compoundTag.getByte("scale"), 0, 4); ++ DataResult> dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, compoundTag.get("dimension"))); // CraftBukkit - decompile error ++ Logger logger = MapItemSavedData.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ // CraftBukkit start ++ ResourceKey resourcekey = dataresult.resultOrPartial(logger::error).orElseGet(() -> { ++ long least = compoundTag.getLong("UUIDLeast"); ++ long most = compoundTag.getLong("UUIDMost"); ++ ++ if (least != 0L && most != 0L) { ++ UUID uniqueId = new UUID(most, least); ++ ++ CraftWorld world = (CraftWorld) Bukkit.getWorld(uniqueId); ++ // Check if the stored world details are correct. ++ if (world == null) { ++ /* All Maps which do not have their valid world loaded are set to a dimension which hopefully won't be reached. ++ This is to prevent them being corrupted with the wrong map data. */ ++ // PAIL: Use Vanilla exception handling for now ++ } else { ++ return world.getHandle().dimension(); ++ } ++ } ++ throw new IllegalArgumentException("Invalid map dimension: " + compoundTag.get("dimension")); ++ // CraftBukkit end ++ }); ++ int i = compoundTag.getInt("xCenter"); ++ int j = compoundTag.getInt("zCenter"); ++ byte b0 = (byte) Mth.clamp(compoundTag.getByte("scale"), 0, 4); + boolean flag = !compoundTag.contains("trackingPosition", 1) || compoundTag.getBoolean("trackingPosition"); + boolean _boolean = compoundTag.getBoolean("unlimitedTracking"); + boolean _boolean1 = compoundTag.getBoolean("locked"); +@@ -137,10 +168,32 @@ + + @Override + public CompoundTag save(CompoundTag compound) { +- ResourceLocation.CODEC +- .encodeStart(NbtOps.INSTANCE, this.dimension.location()) +- .resultOrPartial(LOGGER::error) +- .ifPresent(tag -> compound.put("dimension", tag)); ++ DataResult dataresult = ResourceLocation.CODEC.encodeStart(NbtOps.INSTANCE, this.dimension.location()); // CraftBukkit - decompile error ++ Logger logger = MapItemSavedData.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("dimension", nbtbase); ++ }); ++ // CraftBukkit start ++ if (true) { ++ if (this.uniqueId == null) { ++ for (org.bukkit.World world : server.getWorlds()) { ++ CraftWorld cWorld = (CraftWorld) world; ++ if (cWorld.getHandle().dimension() == this.dimension) { ++ this.uniqueId = cWorld.getUID(); ++ break; ++ } ++ } ++ } ++ /* Perform a second check to see if a matching world was found, this is a necessary ++ change incase Maps are forcefully unlinked from a World and lack a UID.*/ ++ if (this.uniqueId != null) { ++ compound.putLong("UUIDLeast", this.uniqueId.getLeastSignificantBits()); ++ compound.putLong("UUIDMost", this.uniqueId.getMostSignificantBits()); ++ } ++ } ++ // CraftBukkit end + compound.putInt("xCenter", this.centerX); + compound.putInt("zCenter", this.centerZ); + compound.putByte("scale", this.scale); +@@ -505,16 +568,16 @@ + this.player = player; + } + +- private MapItemSavedData.MapPatch createPatch() { ++ private MapItemSavedData.MapPatch createPatch(byte[] buffer) { // CraftBukkit + int i = this.minDirtyX; + int i1 = this.minDirtyY; + int i2 = this.maxDirtyX + 1 - this.minDirtyX; + int i3 = this.maxDirtyY + 1 - this.minDirtyY; + byte[] bytes = new byte[i2 * i3]; + +- for (int i4 = 0; i4 < i2; i4++) { +- for (int i5 = 0; i5 < i3; i5++) { +- bytes[i4 + i5 * i2] = MapItemSavedData.this.colors[i + i4 + (i1 + i5) * 128]; ++ for (int i1 = 0; i1 < k; ++i1) { ++ for (int j1 = 0; j1 < l; ++j1) { ++ abyte[i1 + j1 * k] = buffer[i + i1 + (j + j1) * 128]; // CraftBukkit + } + } + +@@ -523,18 +586,30 @@ + + @Nullable + Packet nextUpdatePacket(int mapId) { +- MapItemSavedData.MapPatch mapPatch; ++ MapItemSavedData.MapPatch worldmap_b; ++ org.bukkit.craftbukkit.map.RenderData render = MapItemSavedData.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()); // CraftBukkit ++ + if (this.dirtyData) { + this.dirtyData = false; +- mapPatch = this.createPatch(); ++ worldmap_b = this.createPatch(render.buffer); // CraftBukkit + } else { + mapPatch = null; + } + +- Collection collection; +- if (this.dirtyDecorations && this.tick++ % 5 == 0) { ++ Collection collection; ++ ++ if ((true || this.dirtyDecorations) && this.tick++ % 5 == 0) { // CraftBukkit - custom maps don't update this yet + this.dirtyDecorations = false; +- collection = MapItemSavedData.this.decorations.values(); ++ // CraftBukkit start ++ java.util.Collection icons = new java.util.ArrayList(); ++ ++ for (org.bukkit.map.MapCursor cursor : render.cursors) { ++ if (cursor.isVisible()) { ++ icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption()))); ++ } ++ } ++ collection = icons; ++ // CraftBukkit end + } else { + collection = null; + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/LevelStorageSource.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/LevelStorageSource.java.patch new file mode 100644 index 0000000000..ce297e5b2e --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/LevelStorageSource.java.patch @@ -0,0 +1,110 @@ +--- a/net/minecraft/world/level/storage/LevelStorageSource.java ++++ b/net/minecraft/world/level/storage/LevelStorageSource.java +@@ -151,14 +164,18 @@ + ) { + Dynamic dynamic1 = wrapWithRegistryOps(dynamic, frozen); + Dynamic dynamic2 = dynamic1.get("WorldGenSettings").orElseEmptyMap(); +- WorldGenSettings worldGenSettings = WorldGenSettings.CODEC.parse(dynamic2).getOrThrow(false, Util.prefix("WorldGenSettings: ", LOGGER::error)); +- LevelSettings levelSettings = LevelSettings.parse(dynamic1, worldDataConfiguration); +- WorldDimensions.Complete complete = worldGenSettings.dimensions().bake(registry); +- Lifecycle lifecycle = complete.lifecycle().add(frozen.allRegistriesLifecycle()); +- PrimaryLevelData primaryLevelData = PrimaryLevelData.parse( +- dynamic1, levelSettings, complete.specialWorldProperty(), worldGenSettings.options(), lifecycle +- ); +- return new LevelDataAndDimensions(primaryLevelData, complete); ++ DataResult dataresult = WorldGenSettings.CODEC.parse(dynamic2); ++ Logger logger = LevelStorageSource.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ WorldGenSettings generatorsettings = (WorldGenSettings) dataresult.getOrThrow(false, Util.prefix("WorldGenSettings: ", logger::error)); ++ LevelSettings worldsettings = LevelSettings.parse(dynamic1, worlddataconfiguration); ++ WorldDimensions.b worlddimensions_b = generatorsettings.dimensions().bake(iregistry); ++ Lifecycle lifecycle = worlddimensions_b.lifecycle().add(iregistrycustom_dimension.allRegistriesLifecycle()); ++ PrimaryLevelData worlddataserver = PrimaryLevelData.parse(dynamic1, worldsettings, worlddimensions_b.specialWorldProperty(), generatorsettings.options(), lifecycle); ++ worlddataserver.pdc = ((Dynamic) dynamic1).getElement("BukkitValues", null); // CraftBukkit - Add PDC to world ++ ++ return new LevelDataAndDimensions(worlddataserver, worlddimensions_b); + } + + private static Dynamic wrapWithRegistryOps(Dynamic dynamic, RegistryAccess.Frozen frozen) { +@@ -364,26 +423,43 @@ + return this.backupDir; + } + +- public LevelStorageSource.LevelStorageAccess validateAndCreateAccess(String saveName) throws IOException, ContentValidationException { +- Path levelPath = this.getLevelPath(saveName); +- List list = this.worldDirValidator.validateDirectory(levelPath, true); ++ public LevelStorageSource.LevelStorageAccess validateAndCreateAccess(String s, ResourceKey dimensionType) throws IOException, ContentValidationException { // CraftBukkit ++ Path path = this.getLevelPath(s); ++ List list = this.worldDirValidator.validateDirectory(path, true); ++ + if (!list.isEmpty()) { + throw new ContentValidationException(levelPath, list); + } else { +- return new LevelStorageSource.LevelStorageAccess(saveName, levelPath); ++ return new LevelStorageSource.LevelStorageAccess(s, path, dimensionType); // CraftBukkit + } + } + +- public LevelStorageSource.LevelStorageAccess createAccess(String saveName) throws IOException { +- Path levelPath = this.getLevelPath(saveName); +- return new LevelStorageSource.LevelStorageAccess(saveName, levelPath); ++ public LevelStorageSource.LevelStorageAccess createAccess(String s, ResourceKey dimensionType) throws IOException { // CraftBukkit ++ Path path = this.getLevelPath(s); ++ ++ return new LevelStorageSource.LevelStorageAccess(s, path, dimensionType); // CraftBukkit + } + + public DirectoryValidator getWorldDirValidator() { + return this.worldDirValidator; + } + +- public static record LevelCandidates(List levels) implements Iterable { ++ // CraftBukkit start ++ public static Path getStorageFolder(Path path, ResourceKey dimensionType) { ++ if (dimensionType == LevelStem.OVERWORLD) { ++ return path; ++ } else if (dimensionType == LevelStem.NETHER) { ++ return path.resolve("DIM-1"); ++ } else if (dimensionType == LevelStem.END) { ++ return path.resolve("DIM1"); ++ } else { ++ return path.resolve("dimensions").resolve(dimensionType.location().getNamespace()).resolve(dimensionType.location().getPath()); ++ } ++ } ++ // CraftBukkit end ++ ++ public static record a(List levels) implements Iterable { ++ + public boolean isEmpty() { + return this.levels.isEmpty(); + } +@@ -433,11 +516,15 @@ + final LevelStorageSource.LevelDirectory levelDirectory; + private final String levelId; + private final Map resources = Maps.newHashMap(); ++ // CraftBukkit start ++ public final ResourceKey dimensionType; + +- LevelStorageAccess(String levelId, Path levelDir) throws IOException { +- this.levelId = levelId; +- this.levelDirectory = new LevelStorageSource.LevelDirectory(levelDir); +- this.lock = DirectoryLock.create(levelDir); ++ LevelStorageAccess(String s, Path path, ResourceKey dimensionType) throws IOException { ++ this.dimensionType = dimensionType; ++ // CraftBukkit end ++ this.levelId = s; ++ this.levelDirectory = new LevelStorageSource.LevelDirectory(path); ++ this.lock = DirectoryLock.create(path); + } + + public void safeClose() { +@@ -465,7 +557,7 @@ + } + + public Path getDimensionPath(ResourceKey dimensionPath) { +- return DimensionType.getStorageFolder(dimensionPath, this.levelDirectory.path()); ++ return getStorageFolder(this.levelDirectory.path(), this.dimensionType); // CraftBukkit + } + + private void checkLock() { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/PlayerDataStorage.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/PlayerDataStorage.java.patch new file mode 100644 index 0000000000..c7d0a3a7fc --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/PlayerDataStorage.java.patch @@ -0,0 +1,73 @@ +--- a/net/minecraft/world/level/storage/PlayerDataStorage.java ++++ b/net/minecraft/world/level/storage/PlayerDataStorage.java +@@ -15,6 +16,12 @@ + import net.minecraft.world.entity.player.Player; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.io.FileInputStream; ++import java.io.InputStream; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++// CraftBukkit end ++ + public class PlayerDataStorage { + private static final Logger LOGGER = LogUtils.getLogger(); + private final File playerDir; +@@ -53,15 +65,42 @@ + LOGGER.warn("Failed to load player data for {}", player.getName().getString()); + } + +- if (compoundTag != null) { +- int dataVersion = NbtUtils.getDataVersion(compoundTag, -1); +- compoundTag = DataFixTypes.PLAYER.updateToCurrentVersion(this.fixerUpper, compoundTag, dataVersion); +- player.load(compoundTag); ++ if (nbttagcompound != null) { ++ // CraftBukkit start ++ if (player instanceof ServerPlayer) { ++ CraftPlayer player = (CraftPlayer) player.getBukkitEntity(); ++ // Only update first played if it is older than the one we have ++ long modified = new File(this.playerDir, player.getUUID().toString() + ".dat").lastModified(); ++ if (modified < player.getFirstPlayed()) { ++ player.setFirstPlayed(modified); ++ } ++ } ++ // CraftBukkit end ++ int i = NbtUtils.getDataVersion(nbttagcompound, -1); ++ ++ nbttagcompound = DataFixTypes.PLAYER.updateToCurrentVersion(this.fixerUpper, nbttagcompound, i); ++ player.load(nbttagcompound); + } + + return compoundTag; + } + ++ // CraftBukkit start ++ public CompoundTag getPlayerData(String s) { ++ try { ++ File file1 = new File(this.playerDir, s + ".dat"); ++ ++ if (file1.exists()) { ++ return NbtIo.readCompressed(file1.toPath(), NbtAccounter.unlimitedHeap()); ++ } ++ } catch (Exception exception) { ++ LOGGER.warn("Failed to load player data for " + s); ++ } ++ ++ return null; ++ } ++ // CraftBukkit end ++ + public String[] getSeenPlayers() { + String[] strings = this.playerDir.list(); + if (strings == null) { +@@ -76,4 +116,10 @@ + + return strings; + } ++ ++ // CraftBukkit start ++ public File getPlayerDir() { ++ return playerDir; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/PrimaryLevelData.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/PrimaryLevelData.java.patch new file mode 100644 index 0000000000..6b00cebc70 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/PrimaryLevelData.java.patch @@ -0,0 +1,177 @@ +--- a/net/minecraft/world/level/storage/PrimaryLevelData.java ++++ b/net/minecraft/world/level/storage/PrimaryLevelData.java +@@ -40,6 +39,20 @@ + import net.minecraft.world.level.timers.TimerCallbacks; + import net.minecraft.world.level.timers.TimerQueue; + import org.slf4j.Logger; ++import net.minecraft.core.registries.Registries; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; ++import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.NbtUtils; ++import net.minecraft.nbt.StringTag; ++import net.minecraft.nbt.Tag; ++import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; ++import net.minecraft.world.level.levelgen.WorldDimensions; ++import net.minecraft.world.level.levelgen.WorldGenSettings; ++import org.bukkit.Bukkit; ++import org.bukkit.event.weather.ThunderChangeEvent; ++import org.bukkit.event.weather.WeatherChangeEvent; ++// CraftBukkit end + + public class PrimaryLevelData implements ServerLevelData, WorldData { + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -78,38 +92,22 @@ + private boolean wasModded; + private final Set removedFeatureFlags; + private final TimerQueue scheduledEvents; ++ // CraftBukkit start - Add world and pdc ++ public Registry customDimensions; ++ private ServerLevel world; ++ protected Tag pdc; + +- private PrimaryLevelData( +- @Nullable CompoundTag compoundTag, +- boolean flag, +- int i, +- int i1, +- int i2, +- float f, +- long l, +- long l1, +- int i3, +- int i4, +- int i5, +- boolean flag1, +- int i6, +- boolean flag2, +- boolean flag3, +- boolean flag4, +- WorldBorder.Settings settings, +- int i7, +- int i8, +- @Nullable UUID uUID, +- Set set, +- Set set1, +- TimerQueue timerQueue, +- @Nullable CompoundTag compoundTag1, +- EndDragonFight.Data data, +- LevelSettings levelSettings, +- WorldOptions worldOptions, +- PrimaryLevelData.SpecialWorldProperty specialWorldProperty, +- Lifecycle lifecycle +- ) { ++ public void setWorld(ServerLevel world) { ++ if (this.world != null) { ++ return; ++ } ++ this.world = world; ++ world.getWorld().readBukkitValues(pdc); ++ pdc = null; ++ } ++ // CraftBukkit end ++ ++ private PrimaryLevelData(@Nullable CompoundTag nbttagcompound, boolean flag, int i, int j, int k, float f, long l, long i1, int j1, int k1, int l1, boolean flag1, int i2, boolean flag2, boolean flag3, boolean flag4, WorldBorder.Settings worldborder_c, int j2, int k2, @Nullable UUID uuid, Set set, Set set1, TimerQueue customfunctioncallbacktimerqueue, @Nullable CompoundTag nbttagcompound1, EndDragonFight.Data enderdragonbattle_a, LevelSettings worldsettings, WorldOptions worldoptions, PrimaryLevelData.a worlddataserver_a, Lifecycle lifecycle) { + this.wasModded = flag; + this.xSpawn = i; + this.ySpawn = i1; +@@ -249,10 +206,14 @@ + compoundTag.putString("Series", SharedConstants.getCurrentVersion().getDataVersion().getSeries()); + nbt.put("Version", compoundTag); + NbtUtils.addCurrentDataVersion(nbt); +- DynamicOps dynamicOps = RegistryOps.create(NbtOps.INSTANCE, registry); +- WorldGenSettings.encode(dynamicOps, this.worldOptions, registry) +- .resultOrPartial(Util.prefix("WorldGenSettings: ", LOGGER::error)) +- .ifPresent(worldOptionsTag -> nbt.put("WorldGenSettings", worldOptionsTag)); ++ DynamicOps dynamicops = RegistryOps.create(NbtOps.INSTANCE, (HolderLookup.Provider) registry); ++ DataResult dataresult = WorldGenSettings.encode(dynamicops, this.worldOptions, new WorldDimensions(this.customDimensions != null ? this.customDimensions : registry.registryOrThrow(Registries.LEVEL_STEM))); // CraftBukkit ++ Logger logger = PrimaryLevelData.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(Util.prefix("WorldGenSettings: ", logger::error)).ifPresent((nbtbase) -> { ++ nbt.put("WorldGenSettings", nbtbase); ++ }); + nbt.putInt("GameType", this.settings.gameType().getId()); + nbt.putInt("SpawnX", this.xSpawn); + nbt.putInt("SpawnY", this.ySpawn); +@@ -294,6 +258,9 @@ + if (this.wanderingTraderId != null) { + nbt.putUUID("WanderingTraderId", this.wanderingTraderId); + } ++ ++ nbt.putString("Bukkit.Version", Bukkit.getName() + "/" + Bukkit.getVersion() + "/" + Bukkit.getBukkitVersion()); // CraftBukkit ++ world.getWorld().storeBukkitValues(nbt); // CraftBukkit - add pdc + } + + private static ListTag stringCollectionToTag(Set stringCollection) { +@@ -403,6 +373,20 @@ + + @Override + public void setThundering(boolean thundering) { ++ // CraftBukkit start ++ if (this.thundering == thundering) { ++ return; ++ } ++ ++ org.bukkit.World world = Bukkit.getWorld(getLevelName()); ++ if (world != null) { ++ ThunderChangeEvent thunder = new ThunderChangeEvent(world, thundering); ++ Bukkit.getServer().getPluginManager().callEvent(thunder); ++ if (thunder.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + this.thundering = thundering; + } + +@@ -423,6 +407,20 @@ + + @Override + public void setRaining(boolean isRaining) { ++ // CraftBukkit start ++ if (this.raining == isRaining) { ++ return; ++ } ++ ++ org.bukkit.World world = Bukkit.getWorld(getLevelName()); ++ if (world != null) { ++ WeatherChangeEvent weather = new WeatherChangeEvent(world, isRaining); ++ Bukkit.getServer().getPluginManager().callEvent(weather); ++ if (weather.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + this.raining = isRaining; + } + +@@ -489,6 +487,12 @@ + @Override + public void setDifficulty(Difficulty difficulty) { + this.settings = this.settings.withDifficulty(difficulty); ++ // CraftBukkit start ++ ClientboundChangeDifficultyPacket packet = new ClientboundChangeDifficultyPacket(this.getDifficulty(), this.isDifficultyLocked()); ++ for (ServerPlayer player : (java.util.List) (java.util.List) world.players()) { ++ player.connection.send(packet); ++ } ++ // CraftBukkit end + } + + @Override +@@ -625,6 +629,15 @@ + return this.settings.copy(); + } + ++ // CraftBukkit start - Check if the name stored in NBT is the correct one ++ public void checkName(String name) { ++ if (!this.settings.levelName.equals(name)) { ++ this.settings.levelName = name; ++ } ++ } ++ // CraftBukkit end ++ ++ /** @deprecated */ + @Deprecated + public static enum SpecialWorldProperty { + NONE, diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/loot/LootDataManager.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/loot/LootDataManager.java.patch new file mode 100644 index 0000000000..738861faa0 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/loot/LootDataManager.java.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/world/level/storage/loot/LootDataManager.java ++++ b/net/minecraft/world/level/storage/loot/LootDataManager.java +@@ -88,10 +94,22 @@ + return (T)map.get(id); + } + }); +- map.forEach((id, element) -> castAndValidate(validationContext, id, element)); +- collector.get().forEach((errorOwner, errorMessage) -> LOGGER.warn("Found loot table element validation problem in {}: {}", errorOwner, errorMessage)); +- this.elements = map; +- this.typeKeys = builder1.build(); ++ ++ map1.forEach((lootdataid, object1) -> { ++ castAndValidate(lootcollector, lootdataid, object1); ++ }); ++ problemreporter_a.get().forEach((s, s1) -> { ++ LootDataManager.LOGGER.warn("Found loot table element validation problem in {}: {}", s, s1); ++ }); ++ // CraftBukkit start ++ map1.forEach((key, lootTable) -> { ++ if (object instanceof LootTable table) { ++ table.craftLootTable = new CraftLootTable(CraftNamespacedKey.fromMinecraft(key.location()), table); ++ } ++ }); ++ // CraftBukkit end ++ this.elements = map1; ++ this.typeKeys = com_google_common_collect_immutablemultimap_builder.build(); + } + + private static void castAndValidate(ValidationContext context, LootDataId id, Object element) { diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/loot/LootTable.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/loot/LootTable.java.patch new file mode 100644 index 0000000000..378c4c09a4 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/loot/LootTable.java.patch @@ -0,0 +1,65 @@ +--- a/net/minecraft/world/level/storage/loot/LootTable.java ++++ b/net/minecraft/world/level/storage/loot/LootTable.java +@@ -27,6 +29,13 @@ + import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.CraftLootTable; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.world.LootGenerateEvent; ++// CraftBukkit end ++ + public class LootTable { + private static final Logger LOGGER = LogUtils.getLogger(); + public static final LootTable EMPTY = new LootTable(LootContextParamSets.EMPTY, Optional.empty(), List.of(), List.of()); +@@ -45,6 +57,7 @@ + private final List pools; + private final List functions; + private final BiFunction compositeFunction; ++ public CraftLootTable craftLootTable; // CraftBukkit + + LootTable(LootContextParamSet lootContextParamSet, Optional optional, List list, List list1) { + this.paramSet = lootContextParamSet; +@@ -134,15 +157,32 @@ + } + + public void fill(Container container, LootParams params, long seed) { +- LootContext lootContext = new LootContext.Builder(params).withOptionalRandomSeed(seed).create(this.randomSequence); +- ObjectArrayList randomItems = this.getRandomItems(lootContext); +- RandomSource random = lootContext.getRandom(); +- List availableSlots = this.getAvailableSlots(container, random); +- this.shuffleAndSplitItems(randomItems, availableSlots.size(), random); ++ // CraftBukkit start ++ this.fillInventory(container, params, seed, false); ++ } + +- for (ItemStack itemStack : randomItems) { +- if (availableSlots.isEmpty()) { +- LOGGER.warn("Tried to over-fill a container"); ++ public void fillInventory(Container iinventory, LootParams lootparams, long i, boolean plugin) { ++ // CraftBukkit end ++ LootContext loottableinfo = (new LootContext.Builder(lootparams)).withOptionalRandomSeed(i).create(this.randomSequence); ++ ObjectArrayList objectarraylist = this.getRandomItems(loottableinfo); ++ RandomSource randomsource = loottableinfo.getRandom(); ++ // CraftBukkit start ++ LootGenerateEvent event = CraftEventFactory.callLootGenerateEvent(iinventory, this, loottableinfo, objectarraylist, plugin); ++ if (event.isCancelled()) { ++ return; ++ } ++ objectarraylist = event.getLoot().stream().map(CraftItemStack::asNMSCopy).collect(ObjectArrayList.toList()); ++ // CraftBukkit end ++ List list = this.getAvailableSlots(iinventory, randomsource); ++ ++ this.shuffleAndSplitItems(objectarraylist, list.size(), randomsource); ++ ObjectListIterator objectlistiterator = objectarraylist.iterator(); ++ ++ while (objectlistiterator.hasNext()) { ++ ItemStack itemstack = (ItemStack) objectlistiterator.next(); ++ ++ if (list.isEmpty()) { ++ LootTable.LOGGER.warn("Tried to over-fill a container"); + return; + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java.patch new file mode 100644 index 0000000000..21d48a2880 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java.patch @@ -0,0 +1,19 @@ +--- a/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java ++++ b/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java +@@ -58,8 +56,14 @@ + public ItemStack run(ItemStack stack, LootContext context) { + Entity entity = context.getParamOrNull(LootContextParams.KILLER_ENTITY); + if (entity instanceof LivingEntity) { +- int mobLooting = EnchantmentHelper.getMobLooting((LivingEntity)entity); +- if (mobLooting == 0) { ++ int i = EnchantmentHelper.getMobLooting((LivingEntity) entity); ++ // CraftBukkit start - use lootingModifier if set by plugin ++ if (context.hasParam(LootContextParams.LOOTING_MOD)) { ++ i = context.getParamOrNull(LootContextParams.LOOTING_MOD); ++ } ++ // CraftBukkit end ++ ++ if (i <= 0) { // CraftBukkit - account for possible negative looting values from Bukkit + return stack; + } + diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/loot/parameters/LootContextParams.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/loot/parameters/LootContextParams.java.patch new file mode 100644 index 0000000000..e4f512167f --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/loot/parameters/LootContextParams.java.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/world/level/storage/loot/parameters/LootContextParams.java ++++ b/net/minecraft/world/level/storage/loot/parameters/LootContextParams.java +@@ -20,6 +21,7 @@ + public static final LootContextParam BLOCK_ENTITY = create("block_entity"); + public static final LootContextParam TOOL = create("tool"); + public static final LootContextParam EXPLOSION_RADIUS = create("explosion_radius"); ++ public static final LootContextParam LOOTING_MOD = new LootContextParam<>(new ResourceLocation("bukkit:looting_mod")); // CraftBukkit + + private static LootContextParam create(String id) { + return new LootContextParam<>(new ResourceLocation(id)); diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/loot/predicates/ExplosionCondition.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/loot/predicates/ExplosionCondition.java.patch new file mode 100644 index 0000000000..772c6496e2 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/loot/predicates/ExplosionCondition.java.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/level/storage/loot/predicates/ExplosionCondition.java ++++ b/net/minecraft/world/level/storage/loot/predicates/ExplosionCondition.java +@@ -27,11 +26,14 @@ + + @Override + public boolean test(LootContext context) { +- Float _float = context.getParamOrNull(LootContextParams.EXPLOSION_RADIUS); +- if (_float != null) { +- RandomSource random = context.getRandom(); +- float f = 1.0F / _float; +- return random.nextFloat() <= f; ++ Float ofloat = (Float) context.getParamOrNull(LootContextParams.EXPLOSION_RADIUS); ++ ++ if (ofloat != null) { ++ RandomSource randomsource = context.getRandom(); ++ float f = 1.0F / ofloat; ++ ++ // CraftBukkit - <= to < to allow for plugins to completely disable block drops from explosions ++ return randomsource.nextFloat() < f; + } else { + return true; + } diff --git a/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/loot/predicates/LootItemRandomChanceWithLootingCondition.java.patch b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/loot/predicates/LootItemRandomChanceWithLootingCondition.java.patch new file mode 100644 index 0000000000..7181274268 --- /dev/null +++ b/patch-remap/mache-vineflower-stripped/net/minecraft/world/level/storage/loot/predicates/LootItemRandomChanceWithLootingCondition.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/storage/loot/predicates/LootItemRandomChanceWithLootingCondition.java ++++ b/net/minecraft/world/level/storage/loot/predicates/LootItemRandomChanceWithLootingCondition.java +@@ -38,6 +34,11 @@ + if (entity instanceof LivingEntity) { + i = EnchantmentHelper.getMobLooting((LivingEntity)entity); + } ++ // CraftBukkit start - only use lootingModifier if set by Bukkit ++ if (context.hasParam(LootContextParams.LOOTING_MOD)) { ++ i = context.getParamOrNull(LootContextParams.LOOTING_MOD); ++ } ++ // CraftBukkit end + + return context.getRandom().nextFloat() < this.percent + (float)i * this.lootingMultiplier; + } diff --git a/patch-remap/mache-vineflower/net/minecraft/CrashReport.java.patch b/patch-remap/mache-vineflower/net/minecraft/CrashReport.java.patch new file mode 100644 index 0000000000..b0b7dbf292 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/CrashReport.java.patch @@ -0,0 +1,343 @@ +--- a/net/minecraft/CrashReport.java ++++ b/net/minecraft/CrashReport.java +@@ -7,10 +7,10 @@ + import java.io.OutputStreamWriter; + import java.io.PrintWriter; + import java.io.StringWriter; +-import java.io.Writer; + import java.nio.charset.StandardCharsets; + import java.time.ZonedDateTime; + import java.time.format.DateTimeFormatter; ++import java.util.Iterator; + import java.util.List; + import java.util.Locale; + import java.util.concurrent.CompletionException; +@@ -21,6 +21,7 @@ + import org.slf4j.Logger; + + public class CrashReport { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.ROOT); + private final String title; +@@ -35,6 +36,7 @@ + public CrashReport(String title, Throwable exception) { + this.title = title; + this.exception = exception; ++ this.systemReport.setDetail("CraftBukkit Information", new org.bukkit.craftbukkit.CraftCrashReport()); // CraftBukkit + } + + public String getTitle() { +@@ -46,31 +48,40 @@ + } + + public String getDetails() { +- StringBuilder stringBuilder = new StringBuilder(); +- this.getDetails(stringBuilder); +- return stringBuilder.toString(); ++ StringBuilder stringbuilder = new StringBuilder(); ++ ++ this.getDetails(stringbuilder); ++ return stringbuilder.toString(); + } + + public void getDetails(StringBuilder builder) { + if ((this.uncategorizedStackTrace == null || this.uncategorizedStackTrace.length <= 0) && !this.details.isEmpty()) { +- this.uncategorizedStackTrace = ArrayUtils.subarray(this.details.get(0).getStacktrace(), 0, 1); ++ this.uncategorizedStackTrace = (StackTraceElement[]) ArrayUtils.subarray(((CrashReportCategory) this.details.get(0)).getStacktrace(), 0, 1); + } + + if (this.uncategorizedStackTrace != null && this.uncategorizedStackTrace.length > 0) { + builder.append("-- Head --\n"); + builder.append("Thread: ").append(Thread.currentThread().getName()).append("\n"); + builder.append("Stacktrace:\n"); ++ StackTraceElement[] astacktraceelement = this.uncategorizedStackTrace; ++ int i = astacktraceelement.length; + +- for (StackTraceElement stackTraceElement : this.uncategorizedStackTrace) { +- builder.append("\t").append("at ").append(stackTraceElement); ++ for (int j = 0; j < i; ++j) { ++ StackTraceElement stacktraceelement = astacktraceelement[j]; ++ ++ builder.append("\t").append("at ").append(stacktraceelement); + builder.append("\n"); + } + + builder.append("\n"); + } + +- for (CrashReportCategory crashReportCategory : this.details) { +- crashReportCategory.getDetails(builder); ++ Iterator iterator = this.details.iterator(); ++ ++ while (iterator.hasNext()) { ++ CrashReportCategory crashreportsystemdetails = (CrashReportCategory) iterator.next(); ++ ++ crashreportsystemdetails.getDetails(builder); + builder.append("\n\n"); + } + +@@ -78,57 +89,60 @@ + } + + public String getExceptionMessage() { +- StringWriter stringWriter = null; +- PrintWriter printWriter = null; +- Throwable throwable = this.exception; +- if (throwable.getMessage() == null) { +- if (throwable instanceof NullPointerException) { +- throwable = new NullPointerException(this.title); +- } else if (throwable instanceof StackOverflowError) { +- throwable = new StackOverflowError(this.title); +- } else if (throwable instanceof OutOfMemoryError) { +- throwable = new OutOfMemoryError(this.title); ++ StringWriter stringwriter = null; ++ PrintWriter printwriter = null; ++ Object object = this.exception; ++ ++ if (((Throwable) object).getMessage() == null) { ++ if (object instanceof NullPointerException) { ++ object = new NullPointerException(this.title); ++ } else if (object instanceof StackOverflowError) { ++ object = new StackOverflowError(this.title); ++ } else if (object instanceof OutOfMemoryError) { ++ object = new OutOfMemoryError(this.title); + } + +- throwable.setStackTrace(this.exception.getStackTrace()); ++ ((Throwable) object).setStackTrace(this.exception.getStackTrace()); + } + +- String var4; ++ String s; ++ + try { +- stringWriter = new StringWriter(); +- printWriter = new PrintWriter(stringWriter); +- throwable.printStackTrace(printWriter); +- var4 = stringWriter.toString(); ++ stringwriter = new StringWriter(); ++ printwriter = new PrintWriter(stringwriter); ++ ((Throwable) object).printStackTrace(printwriter); ++ s = stringwriter.toString(); + } finally { +- IOUtils.closeQuietly((Writer)stringWriter); +- IOUtils.closeQuietly((Writer)printWriter); ++ IOUtils.closeQuietly(stringwriter); ++ IOUtils.closeQuietly(printwriter); + } + +- return var4; ++ return s; + } + + public String getFriendlyReport() { +- StringBuilder stringBuilder = new StringBuilder(); +- stringBuilder.append("---- Minecraft Crash Report ----\n"); +- stringBuilder.append("// "); +- stringBuilder.append(getErrorComment()); +- stringBuilder.append("\n\n"); +- stringBuilder.append("Time: "); +- stringBuilder.append(DATE_TIME_FORMATTER.format(ZonedDateTime.now())); +- stringBuilder.append("\n"); +- stringBuilder.append("Description: "); +- stringBuilder.append(this.title); +- stringBuilder.append("\n\n"); +- stringBuilder.append(this.getExceptionMessage()); +- stringBuilder.append("\n\nA detailed walkthrough of the error, its code path and all known details is as follows:\n"); ++ StringBuilder stringbuilder = new StringBuilder(); + +- for (int i = 0; i < 87; i++) { +- stringBuilder.append("-"); ++ stringbuilder.append("---- Minecraft Crash Report ----\n"); ++ stringbuilder.append("// "); ++ stringbuilder.append(getErrorComment()); ++ stringbuilder.append("\n\n"); ++ stringbuilder.append("Time: "); ++ stringbuilder.append(CrashReport.DATE_TIME_FORMATTER.format(ZonedDateTime.now())); ++ stringbuilder.append("\n"); ++ stringbuilder.append("Description: "); ++ stringbuilder.append(this.title); ++ stringbuilder.append("\n\n"); ++ stringbuilder.append(this.getExceptionMessage()); ++ stringbuilder.append("\n\nA detailed walkthrough of the error, its code path and all known details is as follows:\n"); ++ ++ for (int i = 0; i < 87; ++i) { ++ stringbuilder.append("-"); + } + +- stringBuilder.append("\n\n"); +- this.getDetails(stringBuilder); +- return stringBuilder.toString(); ++ stringbuilder.append("\n\n"); ++ this.getDetails(stringbuilder); ++ return stringbuilder.toString(); + } + + @Nullable +@@ -144,22 +158,25 @@ + toFile.getParentFile().mkdirs(); + } + +- Writer writer = null; ++ OutputStreamWriter outputstreamwriter = null; + +- boolean var4; ++ boolean flag; ++ + try { +- writer = new OutputStreamWriter(new FileOutputStream(toFile), StandardCharsets.UTF_8); +- writer.write(this.getFriendlyReport()); ++ outputstreamwriter = new OutputStreamWriter(new FileOutputStream(toFile), StandardCharsets.UTF_8); ++ outputstreamwriter.write(this.getFriendlyReport()); + this.saveFile = toFile; +- return true; +- } catch (Throwable var8) { +- LOGGER.error("Could not save crash report to {}", toFile, var8); +- var4 = false; ++ boolean flag1 = true; ++ ++ return flag1; ++ } catch (Throwable throwable) { ++ CrashReport.LOGGER.error("Could not save crash report to {}", toFile, throwable); ++ flag = false; + } finally { +- IOUtils.closeQuietly(writer); ++ IOUtils.closeQuietly(outputstreamwriter); + } + +- return var4; ++ return flag; + } + } + +@@ -172,78 +189,45 @@ + } + + public CrashReportCategory addCategory(String categoryName, int stacktraceLength) { +- CrashReportCategory crashReportCategory = new CrashReportCategory(categoryName); ++ CrashReportCategory crashreportsystemdetails = new CrashReportCategory(categoryName); ++ + if (this.trackingStackTrace) { +- int i = crashReportCategory.fillInStackTrace(stacktraceLength); +- StackTraceElement[] stackTrace = this.exception.getStackTrace(); +- StackTraceElement stackTraceElement = null; +- StackTraceElement stackTraceElement1 = null; +- int i1 = stackTrace.length - i; +- if (i1 < 0) { +- LOGGER.error("Negative index in crash report handler ({}/{})", stackTrace.length, i); ++ int j = crashreportsystemdetails.fillInStackTrace(stacktraceLength); ++ StackTraceElement[] astacktraceelement = this.exception.getStackTrace(); ++ StackTraceElement stacktraceelement = null; ++ StackTraceElement stacktraceelement1 = null; ++ int k = astacktraceelement.length - j; ++ ++ if (k < 0) { ++ CrashReport.LOGGER.error("Negative index in crash report handler ({}/{})", astacktraceelement.length, j); + } + +- if (stackTrace != null && 0 <= i1 && i1 < stackTrace.length) { +- stackTraceElement = stackTrace[i1]; +- if (stackTrace.length + 1 - i < stackTrace.length) { +- stackTraceElement1 = stackTrace[stackTrace.length + 1 - i]; ++ if (astacktraceelement != null && 0 <= k && k < astacktraceelement.length) { ++ stacktraceelement = astacktraceelement[k]; ++ if (astacktraceelement.length + 1 - j < astacktraceelement.length) { ++ stacktraceelement1 = astacktraceelement[astacktraceelement.length + 1 - j]; + } + } + +- this.trackingStackTrace = crashReportCategory.validateStackTrace(stackTraceElement, stackTraceElement1); +- if (stackTrace != null && stackTrace.length >= i && 0 <= i1 && i1 < stackTrace.length) { +- this.uncategorizedStackTrace = new StackTraceElement[i1]; +- System.arraycopy(stackTrace, 0, this.uncategorizedStackTrace, 0, this.uncategorizedStackTrace.length); ++ this.trackingStackTrace = crashreportsystemdetails.validateStackTrace(stacktraceelement, stacktraceelement1); ++ if (astacktraceelement != null && astacktraceelement.length >= j && 0 <= k && k < astacktraceelement.length) { ++ this.uncategorizedStackTrace = new StackTraceElement[k]; ++ System.arraycopy(astacktraceelement, 0, this.uncategorizedStackTrace, 0, this.uncategorizedStackTrace.length); + } else { + this.trackingStackTrace = false; + } + } + +- this.details.add(crashReportCategory); +- return crashReportCategory; ++ this.details.add(crashreportsystemdetails); ++ return crashreportsystemdetails; + } + + private static String getErrorComment() { +- String[] strings = new String[]{ +- "Who set us up the TNT?", +- "Everything's going to plan. No, really, that was supposed to happen.", +- "Uh... Did I do that?", +- "Oops.", +- "Why did you do that?", +- "I feel sad now :(", +- "My bad.", +- "I'm sorry, Dave.", +- "I let you down. Sorry :(", +- "On the bright side, I bought you a teddy bear!", +- "Daisy, daisy...", +- "Oh - I know what I did wrong!", +- "Hey, that tickles! Hehehe!", +- "I blame Dinnerbone.", +- "You should try our sister game, Minceraft!", +- "Don't be sad. I'll do better next time, I promise!", +- "Don't be sad, have a hug! <3", +- "I just don't know what went wrong :(", +- "Shall we play a game?", +- "Quite honestly, I wouldn't worry myself about that.", +- "I bet Cylons wouldn't have this problem.", +- "Sorry :(", +- "Surprise! Haha. Well, this is awkward.", +- "Would you like a cupcake?", +- "Hi. I'm Minecraft, and I'm a crashaholic.", +- "Ooh. Shiny.", +- "This doesn't make any sense!", +- "Why is it breaking :(", +- "Don't do that.", +- "Ouch. That hurt :(", +- "You're mean.", +- "This is a token for 1 free hug. Redeem at your nearest Mojangsta: [~~HUG~~]", +- "There are four lights!", +- "But it works on my machine." +- }; ++ String[] astring = new String[]{"Who set us up the TNT?", "Everything's going to plan. No, really, that was supposed to happen.", "Uh... Did I do that?", "Oops.", "Why did you do that?", "I feel sad now :(", "My bad.", "I'm sorry, Dave.", "I let you down. Sorry :(", "On the bright side, I bought you a teddy bear!", "Daisy, daisy...", "Oh - I know what I did wrong!", "Hey, that tickles! Hehehe!", "I blame Dinnerbone.", "You should try our sister game, Minceraft!", "Don't be sad. I'll do better next time, I promise!", "Don't be sad, have a hug! <3", "I just don't know what went wrong :(", "Shall we play a game?", "Quite honestly, I wouldn't worry myself about that.", "I bet Cylons wouldn't have this problem.", "Sorry :(", "Surprise! Haha. Well, this is awkward.", "Would you like a cupcake?", "Hi. I'm Minecraft, and I'm a crashaholic.", "Ooh. Shiny.", "This doesn't make any sense!", "Why is it breaking :(", "Don't do that.", "Ouch. That hurt :(", "You're mean.", "This is a token for 1 free hug. Redeem at your nearest Mojangsta: [~~HUG~~]", "There are four lights!", "But it works on my machine."}; + + try { +- return strings[(int)(Util.getNanos() % (long)strings.length)]; +- } catch (Throwable var2) { ++ return astring[(int) (Util.getNanos() % (long) astring.length)]; ++ } catch (Throwable throwable) { + return "Witty comment unavailable :("; + } + } +@@ -253,18 +237,21 @@ + cause = cause.getCause(); + } + +- CrashReport report; +- if (cause instanceof ReportedException reportedException) { +- report = reportedException.getReport(); ++ CrashReport crashreport; ++ ++ if (cause instanceof ReportedException) { ++ ReportedException reportedexception = (ReportedException) cause; ++ ++ crashreport = reportedexception.getReport(); + } else { +- report = new CrashReport(description, cause); ++ crashreport = new CrashReport(description, cause); + } + +- return report; ++ return crashreport; + } + + public static void preload() { + MemoryReserve.allocate(); +- new CrashReport("Don't panic!", new Throwable()).getFriendlyReport(); ++ (new CrashReport("Don't panic!", new Throwable())).getFriendlyReport(); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/advancements/AdvancementHolder.java.patch b/patch-remap/mache-vineflower/net/minecraft/advancements/AdvancementHolder.java.patch new file mode 100644 index 0000000000..947996e005 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/advancements/AdvancementHolder.java.patch @@ -0,0 +1,67 @@ +--- a/net/minecraft/advancements/AdvancementHolder.java ++++ b/net/minecraft/advancements/AdvancementHolder.java +@@ -2,37 +2,53 @@ + + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.resources.ResourceLocation; ++// CraftBukkit start ++import org.bukkit.craftbukkit.advancement.CraftAdvancement; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++// CraftBukkit end + + public record AdvancementHolder(ResourceLocation id, Advancement value) { +- public void write(FriendlyByteBuf friendlyByteBuf) { +- friendlyByteBuf.writeResourceLocation(this.id); +- this.value.write(friendlyByteBuf); ++ ++ public void write(FriendlyByteBuf packetdataserializer) { ++ packetdataserializer.writeResourceLocation(this.id); ++ this.value.write(packetdataserializer); + } + +- public static AdvancementHolder read(FriendlyByteBuf friendlyByteBuf) { +- return new AdvancementHolder(friendlyByteBuf.readResourceLocation(), Advancement.read(friendlyByteBuf)); ++ public static AdvancementHolder read(FriendlyByteBuf packetdataserializer) { ++ return new AdvancementHolder(packetdataserializer.readResourceLocation(), Advancement.read(packetdataserializer)); + } + +- @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } else { +- if (object instanceof AdvancementHolder advancementHolder && this.id.equals(advancementHolder.id)) { +- return true; ++ boolean flag; ++ ++ if (object instanceof AdvancementHolder) { ++ AdvancementHolder advancementholder = (AdvancementHolder) object; ++ ++ if (this.id.equals(advancementholder.id)) { ++ flag = true; ++ return flag; ++ } + } + +- return false; ++ flag = false; ++ return flag; + } + } + +- @Override + public int hashCode() { + return this.id.hashCode(); + } + +- @Override + public String toString() { + return this.id.toString(); + } ++ ++ // CraftBukkit start ++ public final org.bukkit.advancement.Advancement toBukkit() { ++ return new CraftAdvancement(this); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/advancements/AdvancementTree.java.patch b/patch-remap/mache-vineflower/net/minecraft/advancements/AdvancementTree.java.patch new file mode 100644 index 0000000000..7e52db7819 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/advancements/AdvancementTree.java.patch @@ -0,0 +1,219 @@ +--- a/net/minecraft/advancements/AdvancementTree.java ++++ b/net/minecraft/advancements/AdvancementTree.java +@@ -5,8 +5,10 @@ + import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; + import java.util.ArrayList; + import java.util.Collection; ++import java.util.Iterator; + import java.util.List; + import java.util.Map; ++import java.util.Objects; + import java.util.Optional; + import java.util.Set; + import javax.annotation.Nullable; +@@ -14,78 +16,96 @@ + import org.slf4j.Logger; + + public class AdvancementTree { ++ + private static final Logger LOGGER = LogUtils.getLogger(); +- private final Map nodes = new Object2ObjectOpenHashMap<>(); +- private final Set roots = new ObjectLinkedOpenHashSet<>(); +- private final Set tasks = new ObjectLinkedOpenHashSet<>(); ++ private final Map nodes = new Object2ObjectOpenHashMap(); ++ private final Set roots = new ObjectLinkedOpenHashSet(); ++ private final Set tasks = new ObjectLinkedOpenHashSet(); + @Nullable +- private AdvancementTree.Listener listener; ++ private AdvancementTree.a listener; + +- private void remove(AdvancementNode advancementNode) { +- for (AdvancementNode advancementNode1 : advancementNode.children()) { +- this.remove(advancementNode1); ++ public AdvancementTree() {} ++ ++ private void remove(AdvancementNode advancementnode) { ++ Iterator iterator = advancementnode.children().iterator(); ++ ++ while (iterator.hasNext()) { ++ AdvancementNode advancementnode1 = (AdvancementNode) iterator.next(); ++ ++ this.remove(advancementnode1); + } + +- LOGGER.info("Forgot about advancement {}", advancementNode.holder()); +- this.nodes.remove(advancementNode.holder().id()); +- if (advancementNode.parent() == null) { +- this.roots.remove(advancementNode); ++ AdvancementTree.LOGGER.info("Forgot about advancement {}", advancementnode.holder()); ++ this.nodes.remove(advancementnode.holder().id()); ++ if (advancementnode.parent() == null) { ++ this.roots.remove(advancementnode); + if (this.listener != null) { +- this.listener.onRemoveAdvancementRoot(advancementNode); ++ this.listener.onRemoveAdvancementRoot(advancementnode); + } + } else { +- this.tasks.remove(advancementNode); ++ this.tasks.remove(advancementnode); + if (this.listener != null) { +- this.listener.onRemoveAdvancementTask(advancementNode); ++ this.listener.onRemoveAdvancementTask(advancementnode); + } + } ++ + } + + public void remove(Set set) { +- for (ResourceLocation resourceLocation : set) { +- AdvancementNode advancementNode = this.nodes.get(resourceLocation); +- if (advancementNode == null) { +- LOGGER.warn("Told to remove advancement {} but I don't know what that is", resourceLocation); ++ Iterator iterator = set.iterator(); ++ ++ while (iterator.hasNext()) { ++ ResourceLocation minecraftkey = (ResourceLocation) iterator.next(); ++ AdvancementNode advancementnode = (AdvancementNode) this.nodes.get(minecraftkey); ++ ++ if (advancementnode == null) { ++ AdvancementTree.LOGGER.warn("Told to remove advancement {} but I don't know what that is", minecraftkey); + } else { +- this.remove(advancementNode); ++ this.remove(advancementnode); + } + } ++ + } + + public void addAll(Collection collection) { +- List list = new ArrayList<>(collection); ++ ArrayList arraylist = new ArrayList(collection); // CraftBukkit - decompile error + +- while (!list.isEmpty()) { +- if (!list.removeIf(this::tryInsert)) { +- LOGGER.error("Couldn't load advancements: {}", list); ++ while (!arraylist.isEmpty()) { ++ if (!arraylist.removeIf(this::tryInsert)) { ++ AdvancementTree.LOGGER.error("Couldn't load advancements: {}", arraylist); + break; + } + } + +- LOGGER.info("Loaded {} advancements", this.nodes.size()); ++ // AdvancementTree.LOGGER.info("Loaded {} advancements", this.nodes.size()); // CraftBukkit - moved to AdvancementDataWorld#reload + } + +- private boolean tryInsert(AdvancementHolder advancementHolder) { +- Optional optional = advancementHolder.value().parent(); +- AdvancementNode advancementNode = optional.map(this.nodes::get).orElse(null); +- if (advancementNode == null && optional.isPresent()) { ++ private boolean tryInsert(AdvancementHolder advancementholder) { ++ Optional optional = advancementholder.value().parent(); ++ Map map = this.nodes; ++ ++ Objects.requireNonNull(this.nodes); ++ AdvancementNode advancementnode = (AdvancementNode) optional.map(map::get).orElse((Object) null); ++ ++ if (advancementnode == null && optional.isPresent()) { + return false; + } else { +- AdvancementNode advancementNode1 = new AdvancementNode(advancementHolder, advancementNode); +- if (advancementNode != null) { +- advancementNode.addChild(advancementNode1); ++ AdvancementNode advancementnode1 = new AdvancementNode(advancementholder, advancementnode); ++ ++ if (advancementnode != null) { ++ advancementnode.addChild(advancementnode1); + } + +- this.nodes.put(advancementHolder.id(), advancementNode1); +- if (advancementNode == null) { +- this.roots.add(advancementNode1); ++ this.nodes.put(advancementholder.id(), advancementnode1); ++ if (advancementnode == null) { ++ this.roots.add(advancementnode1); + if (this.listener != null) { +- this.listener.onAddAdvancementRoot(advancementNode1); ++ this.listener.onAddAdvancementRoot(advancementnode1); + } + } else { +- this.tasks.add(advancementNode1); ++ this.tasks.add(advancementnode1); + if (this.listener != null) { +- this.listener.onAddAdvancementTask(advancementNode1); ++ this.listener.onAddAdvancementTask(advancementnode1); + } + } + +@@ -100,6 +120,7 @@ + if (this.listener != null) { + this.listener.onAdvancementsCleared(); + } ++ + } + + public Iterable roots() { +@@ -111,37 +132,47 @@ + } + + @Nullable +- public AdvancementNode get(ResourceLocation resourceLocation) { +- return this.nodes.get(resourceLocation); ++ public AdvancementNode get(ResourceLocation minecraftkey) { ++ return (AdvancementNode) this.nodes.get(minecraftkey); + } + + @Nullable +- public AdvancementNode get(AdvancementHolder advancementHolder) { +- return this.nodes.get(advancementHolder.id()); ++ public AdvancementNode get(AdvancementHolder advancementholder) { ++ return (AdvancementNode) this.nodes.get(advancementholder.id()); + } + +- public void setListener(@Nullable AdvancementTree.Listener listener) { +- this.listener = listener; +- if (listener != null) { +- for (AdvancementNode advancementNode : this.roots) { +- listener.onAddAdvancementRoot(advancementNode); ++ public void setListener(@Nullable AdvancementTree.a advancementtree_a) { ++ this.listener = advancementtree_a; ++ if (advancementtree_a != null) { ++ Iterator iterator = this.roots.iterator(); ++ ++ AdvancementNode advancementnode; ++ ++ while (iterator.hasNext()) { ++ advancementnode = (AdvancementNode) iterator.next(); ++ advancementtree_a.onAddAdvancementRoot(advancementnode); + } + +- for (AdvancementNode advancementNode : this.tasks) { +- listener.onAddAdvancementTask(advancementNode); ++ iterator = this.tasks.iterator(); ++ ++ while (iterator.hasNext()) { ++ advancementnode = (AdvancementNode) iterator.next(); ++ advancementtree_a.onAddAdvancementTask(advancementnode); + } + } ++ + } + +- public interface Listener { +- void onAddAdvancementRoot(AdvancementNode advancementNode); ++ public interface a { + +- void onRemoveAdvancementRoot(AdvancementNode advancementNode); ++ void onAddAdvancementRoot(AdvancementNode advancementnode); + +- void onAddAdvancementTask(AdvancementNode advancementNode); ++ void onRemoveAdvancementRoot(AdvancementNode advancementnode); + +- void onRemoveAdvancementTask(AdvancementNode advancementNode); ++ void onAddAdvancementTask(AdvancementNode advancementnode); + ++ void onRemoveAdvancementTask(AdvancementNode advancementnode); ++ + void onAdvancementsCleared(); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/commands/CommandSource.java.patch b/patch-remap/mache-vineflower/net/minecraft/commands/CommandSource.java.patch new file mode 100644 index 0000000000..ee54b4a935 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/commands/CommandSource.java.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/commands/CommandSource.java ++++ b/net/minecraft/commands/CommandSource.java +@@ -3,10 +3,10 @@ + import net.minecraft.network.chat.Component; + + public interface CommandSource { ++ + CommandSource NULL = new CommandSource() { + @Override +- public void sendSystemMessage(Component component) { +- } ++ public void sendSystemMessage(Component component) {} + + @Override + public boolean acceptsSuccess() { +@@ -22,6 +22,13 @@ + public boolean shouldInformAdmins() { + return false; + } ++ ++ // CraftBukkit start ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ // CraftBukkit end + }; + + void sendSystemMessage(Component component); +@@ -35,4 +42,6 @@ + default boolean alwaysAccepts() { + return false; + } ++ ++ org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper); // CraftBukkit + } diff --git a/patch-remap/mache-vineflower/net/minecraft/commands/CommandSourceStack.java.patch b/patch-remap/mache-vineflower/net/minecraft/commands/CommandSourceStack.java.patch new file mode 100644 index 0000000000..97067f7d0a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/commands/CommandSourceStack.java.patch @@ -0,0 +1,631 @@ +--- a/net/minecraft/commands/CommandSourceStack.java ++++ b/net/minecraft/commands/CommandSourceStack.java +@@ -1,7 +1,6 @@ + package net.minecraft.commands; + + import com.google.common.collect.Lists; +-import com.mojang.brigadier.CommandDispatcher; + import com.mojang.brigadier.Message; + import com.mojang.brigadier.context.CommandContext; + import com.mojang.brigadier.exceptions.CommandExceptionType; +@@ -10,6 +9,7 @@ + import com.mojang.brigadier.suggestion.Suggestions; + import com.mojang.brigadier.suggestion.SuggestionsBuilder; + import java.util.Collection; ++import java.util.Iterator; + import java.util.Objects; + import java.util.Set; + import java.util.concurrent.CompletableFuture; +@@ -26,6 +26,7 @@ + import net.minecraft.network.chat.ChatType; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.ComponentUtils; ++import net.minecraft.network.chat.MutableComponent; + import net.minecraft.network.chat.OutgoingChatMessage; + import net.minecraft.resources.ResourceKey; + import net.minecraft.resources.ResourceLocation; +@@ -42,11 +43,13 @@ + import net.minecraft.world.level.dimension.DimensionType; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; ++import com.mojang.brigadier.tree.CommandNode; // CraftBukkit + + public class CommandSourceStack implements ExecutionCommandSource, SharedSuggestionProvider { ++ + public static final SimpleCommandExceptionType ERROR_NOT_PLAYER = new SimpleCommandExceptionType(Component.translatable("permissions.requires.player")); + public static final SimpleCommandExceptionType ERROR_NOT_ENTITY = new SimpleCommandExceptionType(Component.translatable("permissions.requires.entity")); +- private final CommandSource source; ++ public final CommandSource source; + private final Vec3 worldPosition; + private final ServerLevel level; + private final int permissionLevel; +@@ -61,285 +64,80 @@ + private final Vec2 rotation; + private final CommandSigningContext signingContext; + private final TaskChainer chatMessageChainer; ++ public volatile CommandNode currentCommand; // CraftBukkit + +- public CommandSourceStack( +- CommandSource source, +- Vec3 worldPosition, +- Vec2 rotation, +- ServerLevel level, +- int permissionLevel, +- String textName, +- Component displayName, +- MinecraftServer server, +- @Nullable Entity entity +- ) { +- this( +- source, +- worldPosition, +- rotation, +- level, +- permissionLevel, +- textName, +- displayName, +- server, +- entity, +- false, +- CommandResultCallback.EMPTY, +- EntityAnchorArgument.Anchor.FEET, +- CommandSigningContext.ANONYMOUS, +- TaskChainer.immediate(server) +- ); ++ public CommandSourceStack(CommandSource source, Vec3 worldPosition, Vec2 rotation, ServerLevel level, int permissionLevel, String textName, Component displayName, MinecraftServer server, @Nullable Entity entity) { ++ this(source, worldPosition, rotation, level, permissionLevel, textName, displayName, server, entity, false, CommandResultCallback.EMPTY, EntityAnchorArgument.Anchor.FEET, CommandSigningContext.ANONYMOUS, TaskChainer.immediate(server)); + } + +- protected CommandSourceStack( +- CommandSource commandSource, +- Vec3 vec3, +- Vec2 vec2, +- ServerLevel serverLevel, +- int i, +- String string, +- Component component, +- MinecraftServer minecraftServer, +- @Nullable Entity entity, +- boolean flag, +- CommandResultCallback commandResultCallback, +- EntityAnchorArgument.Anchor anchor, +- CommandSigningContext commandSigningContext, +- TaskChainer taskChainer +- ) { +- this.source = commandSource; +- this.worldPosition = vec3; +- this.level = serverLevel; ++ protected CommandSourceStack(CommandSource icommandlistener, Vec3 vec3d, Vec2 vec2f, ServerLevel worldserver, int i, String s, Component ichatbasecomponent, MinecraftServer minecraftserver, @Nullable Entity entity, boolean flag, CommandResultCallback commandresultcallback, EntityAnchorArgument.Anchor argumentanchor_anchor, CommandSigningContext commandsigningcontext, TaskChainer taskchainer) { ++ this.source = icommandlistener; ++ this.worldPosition = vec3d; ++ this.level = worldserver; + this.silent = flag; + this.entity = entity; + this.permissionLevel = i; +- this.textName = string; +- this.displayName = component; +- this.server = minecraftServer; +- this.resultCallback = commandResultCallback; +- this.anchor = anchor; +- this.rotation = vec2; +- this.signingContext = commandSigningContext; +- this.chatMessageChainer = taskChainer; ++ this.textName = s; ++ this.displayName = ichatbasecomponent; ++ this.server = minecraftserver; ++ this.resultCallback = commandresultcallback; ++ this.anchor = argumentanchor_anchor; ++ this.rotation = vec2f; ++ this.signingContext = commandsigningcontext; ++ this.chatMessageChainer = taskchainer; + } + + public CommandSourceStack withSource(CommandSource source) { +- return this.source == source +- ? this +- : new CommandSourceStack( +- source, +- this.worldPosition, +- this.rotation, +- this.level, +- this.permissionLevel, +- this.textName, +- this.displayName, +- this.server, +- this.entity, +- this.silent, +- this.resultCallback, +- this.anchor, +- this.signingContext, +- this.chatMessageChainer +- ); ++ return this.source == source ? this : new CommandSourceStack(source, this.worldPosition, this.rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); + } + + public CommandSourceStack withEntity(Entity entity) { +- return this.entity == entity +- ? this +- : new CommandSourceStack( +- this.source, +- this.worldPosition, +- this.rotation, +- this.level, +- this.permissionLevel, +- entity.getName().getString(), +- entity.getDisplayName(), +- this.server, +- entity, +- this.silent, +- this.resultCallback, +- this.anchor, +- this.signingContext, +- this.chatMessageChainer +- ); ++ return this.entity == entity ? this : new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, this.permissionLevel, entity.getName().getString(), entity.getDisplayName(), this.server, entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); + } + + public CommandSourceStack withPosition(Vec3 pos) { +- return this.worldPosition.equals(pos) +- ? this +- : new CommandSourceStack( +- this.source, +- pos, +- this.rotation, +- this.level, +- this.permissionLevel, +- this.textName, +- this.displayName, +- this.server, +- this.entity, +- this.silent, +- this.resultCallback, +- this.anchor, +- this.signingContext, +- this.chatMessageChainer +- ); ++ return this.worldPosition.equals(pos) ? this : new CommandSourceStack(this.source, pos, this.rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); + } + + public CommandSourceStack withRotation(Vec2 rotation) { +- return this.rotation.equals(rotation) +- ? this +- : new CommandSourceStack( +- this.source, +- this.worldPosition, +- rotation, +- this.level, +- this.permissionLevel, +- this.textName, +- this.displayName, +- this.server, +- this.entity, +- this.silent, +- this.resultCallback, +- this.anchor, +- this.signingContext, +- this.chatMessageChainer +- ); ++ return this.rotation.equals(rotation) ? this : new CommandSourceStack(this.source, this.worldPosition, rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); + } + + @Override +- public CommandSourceStack withCallback(CommandResultCallback commandResultCallback) { +- return Objects.equals(this.resultCallback, commandResultCallback) +- ? this +- : new CommandSourceStack( +- this.source, +- this.worldPosition, +- this.rotation, +- this.level, +- this.permissionLevel, +- this.textName, +- this.displayName, +- this.server, +- this.entity, +- this.silent, +- commandResultCallback, +- this.anchor, +- this.signingContext, +- this.chatMessageChainer +- ); ++ public CommandSourceStack withCallback(CommandResultCallback commandresultcallback) { ++ return Objects.equals(this.resultCallback, commandresultcallback) ? this : new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, commandresultcallback, this.anchor, this.signingContext, this.chatMessageChainer); + } + +- public CommandSourceStack withCallback(CommandResultCallback commandResultCallback, BinaryOperator binaryOperator) { +- CommandResultCallback commandResultCallback1 = binaryOperator.apply(this.resultCallback, commandResultCallback); +- return this.withCallback(commandResultCallback1); ++ public CommandSourceStack withCallback(CommandResultCallback commandresultcallback, BinaryOperator binaryoperator) { ++ CommandResultCallback commandresultcallback1 = (CommandResultCallback) binaryoperator.apply(this.resultCallback, commandresultcallback); ++ ++ return this.withCallback(commandresultcallback1); + } + + public CommandSourceStack withSuppressedOutput() { +- return !this.silent && !this.source.alwaysAccepts() +- ? new CommandSourceStack( +- this.source, +- this.worldPosition, +- this.rotation, +- this.level, +- this.permissionLevel, +- this.textName, +- this.displayName, +- this.server, +- this.entity, +- true, +- this.resultCallback, +- this.anchor, +- this.signingContext, +- this.chatMessageChainer +- ) +- : this; ++ return !this.silent && !this.source.alwaysAccepts() ? new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, true, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer) : this; + } + + public CommandSourceStack withPermission(int permissionLevel) { +- return permissionLevel == this.permissionLevel +- ? this +- : new CommandSourceStack( +- this.source, +- this.worldPosition, +- this.rotation, +- this.level, +- permissionLevel, +- this.textName, +- this.displayName, +- this.server, +- this.entity, +- this.silent, +- this.resultCallback, +- this.anchor, +- this.signingContext, +- this.chatMessageChainer +- ); ++ return permissionLevel == this.permissionLevel ? this : new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); + } + + public CommandSourceStack withMaximumPermission(int permissionLevel) { +- return permissionLevel <= this.permissionLevel +- ? this +- : new CommandSourceStack( +- this.source, +- this.worldPosition, +- this.rotation, +- this.level, +- permissionLevel, +- this.textName, +- this.displayName, +- this.server, +- this.entity, +- this.silent, +- this.resultCallback, +- this.anchor, +- this.signingContext, +- this.chatMessageChainer +- ); ++ return permissionLevel <= this.permissionLevel ? this : new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); + } + + public CommandSourceStack withAnchor(EntityAnchorArgument.Anchor anchor) { +- return anchor == this.anchor +- ? this +- : new CommandSourceStack( +- this.source, +- this.worldPosition, +- this.rotation, +- this.level, +- this.permissionLevel, +- this.textName, +- this.displayName, +- this.server, +- this.entity, +- this.silent, +- this.resultCallback, +- anchor, +- this.signingContext, +- this.chatMessageChainer +- ); ++ return anchor == this.anchor ? this : new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, anchor, this.signingContext, this.chatMessageChainer); + } + + public CommandSourceStack withLevel(ServerLevel level) { + if (level == this.level) { + return this; + } else { +- double teleportationScale = DimensionType.getTeleportationScale(this.level.dimensionType(), level.dimensionType()); +- Vec3 vec3 = new Vec3(this.worldPosition.x * teleportationScale, this.worldPosition.y, this.worldPosition.z * teleportationScale); +- return new CommandSourceStack( +- this.source, +- vec3, +- this.rotation, +- level, +- this.permissionLevel, +- this.textName, +- this.displayName, +- this.server, +- this.entity, +- this.silent, +- this.resultCallback, +- this.anchor, +- this.signingContext, +- this.chatMessageChainer +- ); ++ double d0 = DimensionType.getTeleportationScale(this.level.dimensionType(), level.dimensionType()); ++ Vec3 vec3d = new Vec3(this.worldPosition.x * d0, this.worldPosition.y, this.worldPosition.z * d0); ++ ++ return new CommandSourceStack(this.source, vec3d, this.rotation, level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, this.signingContext, this.chatMessageChainer); + } + } + +@@ -348,35 +146,19 @@ + } + + public CommandSourceStack facing(Vec3 lookPos) { +- Vec3 vec3 = this.anchor.apply(this); +- double d = lookPos.x - vec3.x; +- double d1 = lookPos.y - vec3.y; +- double d2 = lookPos.z - vec3.z; +- double squareRoot = Math.sqrt(d * d + d2 * d2); +- float f = Mth.wrapDegrees((float)(-(Mth.atan2(d1, squareRoot) * 180.0F / (float)Math.PI))); +- float f1 = Mth.wrapDegrees((float)(Mth.atan2(d2, d) * 180.0F / (float)Math.PI) - 90.0F); ++ Vec3 vec3d1 = this.anchor.apply(this); ++ double d0 = lookPos.x - vec3d1.x; ++ double d1 = lookPos.y - vec3d1.y; ++ double d2 = lookPos.z - vec3d1.z; ++ double d3 = Math.sqrt(d0 * d0 + d2 * d2); ++ float f = Mth.wrapDegrees((float) (-(Mth.atan2(d1, d3) * 57.2957763671875D))); ++ float f1 = Mth.wrapDegrees((float) (Mth.atan2(d2, d0) * 57.2957763671875D) - 90.0F); ++ + return this.withRotation(new Vec2(f, f1)); + } + +- public CommandSourceStack withSigningContext(CommandSigningContext commandSigningContext, TaskChainer taskChainer) { +- return commandSigningContext == this.signingContext && taskChainer == this.chatMessageChainer +- ? this +- : new CommandSourceStack( +- this.source, +- this.worldPosition, +- this.rotation, +- this.level, +- this.permissionLevel, +- this.textName, +- this.displayName, +- this.server, +- this.entity, +- this.silent, +- this.resultCallback, +- this.anchor, +- commandSigningContext, +- taskChainer +- ); ++ public CommandSourceStack withSigningContext(CommandSigningContext commandsigningcontext, TaskChainer taskchainer) { ++ return commandsigningcontext == this.signingContext && taskchainer == this.chatMessageChainer ? this : new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.resultCallback, this.anchor, commandsigningcontext, taskchainer); + } + + public Component getDisplayName() { +@@ -389,9 +171,23 @@ + + @Override + public boolean hasPermission(int level) { ++ // CraftBukkit start ++ CommandNode currentCommand = this.currentCommand; ++ if (currentCommand != null) { ++ return hasPermission(level, org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(currentCommand)); ++ } ++ // CraftBukkit end ++ + return this.permissionLevel >= level; + } + ++ // CraftBukkit start ++ public boolean hasPermission(int i, String bukkitPermission) { ++ // World is null when loading functions ++ return ((getLevel() == null || !getLevel().getCraftServer().ignoreVanillaPermissions) && this.permissionLevel >= i) || getBukkitSender().hasPermission(bukkitPermission); ++ } ++ // CraftBukkit end ++ + public Vec3 getPosition() { + return this.worldPosition; + } +@@ -407,24 +203,38 @@ + + public Entity getEntityOrException() throws CommandSyntaxException { + if (this.entity == null) { +- throw ERROR_NOT_ENTITY.create(); ++ throw CommandSourceStack.ERROR_NOT_ENTITY.create(); + } else { + return this.entity; + } + } + + public ServerPlayer getPlayerOrException() throws CommandSyntaxException { +- Entity var2 = this.entity; +- if (var2 instanceof ServerPlayer) { +- return (ServerPlayer)var2; ++ Entity entity = this.entity; ++ ++ if (entity instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entity; ++ ++ return entityplayer; + } else { +- throw ERROR_NOT_PLAYER.create(); ++ throw CommandSourceStack.ERROR_NOT_PLAYER.create(); + } + } + + @Nullable + public ServerPlayer getPlayer() { +- return this.entity instanceof ServerPlayer serverPlayer ? serverPlayer : null; ++ Entity entity = this.entity; ++ ServerPlayer entityplayer; ++ ++ if (entity instanceof ServerPlayer) { ++ ServerPlayer entityplayer1 = (ServerPlayer) entity; ++ ++ entityplayer = entityplayer1; ++ } else { ++ entityplayer = null; ++ } ++ ++ return entityplayer; + } + + public boolean isPlayer() { +@@ -452,66 +262,81 @@ + } + + public boolean shouldFilterMessageTo(ServerPlayer receiver) { +- ServerPlayer player = this.getPlayer(); +- return receiver != player && (player != null && player.isTextFilteringEnabled() || receiver.isTextFilteringEnabled()); ++ ServerPlayer entityplayer1 = this.getPlayer(); ++ ++ return receiver == entityplayer1 ? false : entityplayer1 != null && entityplayer1.isTextFilteringEnabled() || receiver.isTextFilteringEnabled(); + } + + public void sendChatMessage(OutgoingChatMessage message, boolean shouldFilter, ChatType.Bound boundChatType) { + if (!this.silent) { +- ServerPlayer player = this.getPlayer(); +- if (player != null) { +- player.sendChatMessage(message, shouldFilter, boundChatType); ++ ServerPlayer entityplayer = this.getPlayer(); ++ ++ if (entityplayer != null) { ++ entityplayer.sendChatMessage(message, shouldFilter, boundChatType); + } else { + this.source.sendSystemMessage(boundChatType.decorate(message.content())); + } ++ + } + } + + public void sendSystemMessage(Component message) { + if (!this.silent) { +- ServerPlayer player = this.getPlayer(); +- if (player != null) { +- player.sendSystemMessage(message); ++ ServerPlayer entityplayer = this.getPlayer(); ++ ++ if (entityplayer != null) { ++ entityplayer.sendSystemMessage(message); + } else { + this.source.sendSystemMessage(message); + } ++ + } + } + + public void sendSuccess(Supplier messageSupplier, boolean allowLogging) { +- boolean flag = this.source.acceptsSuccess() && !this.silent; +- boolean flag1 = allowLogging && this.source.shouldInformAdmins() && !this.silent; +- if (flag || flag1) { +- Component component = messageSupplier.get(); +- if (flag) { +- this.source.sendSystemMessage(component); +- } ++ boolean flag1 = this.source.acceptsSuccess() && !this.silent; ++ boolean flag2 = allowLogging && this.source.shouldInformAdmins() && !this.silent; + ++ if (flag1 || flag2) { ++ Component ichatbasecomponent = (Component) messageSupplier.get(); ++ + if (flag1) { +- this.broadcastToAdmins(component); ++ this.source.sendSystemMessage(ichatbasecomponent); + } ++ ++ if (flag2) { ++ this.broadcastToAdmins(ichatbasecomponent); ++ } ++ + } + } + + private void broadcastToAdmins(Component message) { +- Component component = Component.translatable("chat.type.admin", this.getDisplayName(), message).withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC); ++ MutableComponent ichatmutablecomponent = Component.translatable("chat.type.admin", this.getDisplayName(), message).withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC); ++ + if (this.server.getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK)) { +- for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) { +- if (serverPlayer != this.source && this.server.getPlayerList().isOp(serverPlayer.getGameProfile())) { +- serverPlayer.sendSystemMessage(component); ++ Iterator iterator = this.server.getPlayerList().getPlayers().iterator(); ++ ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ if (entityplayer != this.source && entityplayer.getBukkitEntity().hasPermission("minecraft.admin.command_feedback")) { // CraftBukkit ++ entityplayer.sendSystemMessage(ichatmutablecomponent); + } + } + } + + if (this.source != this.server && this.server.getGameRules().getBoolean(GameRules.RULE_LOGADMINCOMMANDS)) { +- this.server.sendSystemMessage(component); ++ this.server.sendSystemMessage(ichatmutablecomponent); + } ++ + } + + public void sendFailure(Component message) { + if (this.source.acceptsFailure() && !this.silent) { + this.source.sendSystemMessage(Component.empty().append(message).withStyle(ChatFormatting.RED)); + } ++ + } + + @Override +@@ -545,14 +370,9 @@ + } + + @Override +- public CompletableFuture suggestRegistryElements( +- ResourceKey> resourceKey, +- SharedSuggestionProvider.ElementSuggestionType registryKey, +- SuggestionsBuilder builder, +- CommandContext context +- ) { +- return this.registryAccess().registry(resourceKey).map(registry -> { +- this.suggestRegistryElements((Registry)registry, registryKey, builder); ++ public CompletableFuture suggestRegistryElements(ResourceKey> resourceKey, SharedSuggestionProvider.a registryKey, SuggestionsBuilder builder, CommandContext context) { ++ return (CompletableFuture) this.registryAccess().registry(resourceKey).map((iregistry) -> { ++ this.suggestRegistryElements(iregistry, registryKey, builder); + return builder.buildFuture(); + }).orElseGet(Suggestions::empty); + } +@@ -573,23 +393,30 @@ + } + + @Override +- public CommandDispatcher dispatcher() { ++ public com.mojang.brigadier.CommandDispatcher dispatcher() { + return this.getServer().getFunctions().getDispatcher(); + } + + @Override +- public void handleError(CommandExceptionType commandExceptionType, Message message, boolean flag, @Nullable TraceCallbacks traceCallbacks) { +- if (traceCallbacks != null) { +- traceCallbacks.onError(message.getString()); ++ public void handleError(CommandExceptionType commandexceptiontype, Message message, boolean flag, @Nullable TraceCallbacks tracecallbacks) { ++ if (tracecallbacks != null) { ++ tracecallbacks.onError(message.getString()); + } + + if (!flag) { + this.sendFailure(ComponentUtils.fromMessage(message)); + } ++ + } + + @Override + public boolean isSilent() { + return this.silent; + } ++ ++ // CraftBukkit start ++ public org.bukkit.command.CommandSender getBukkitSender() { ++ return source.getBukkitSender(this); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/commands/Commands.java.patch b/patch-remap/mache-vineflower/net/minecraft/commands/Commands.java.patch new file mode 100644 index 0000000000..3091ae10af --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/commands/Commands.java.patch @@ -0,0 +1,556 @@ +--- a/net/minecraft/commands/Commands.java ++++ b/net/minecraft/commands/Commands.java +@@ -1,21 +1,19 @@ + package net.minecraft.commands; + + import com.google.common.collect.Maps; +-import com.mojang.brigadier.CommandDispatcher; + import com.mojang.brigadier.ParseResults; + import com.mojang.brigadier.StringReader; + import com.mojang.brigadier.arguments.ArgumentType; + import com.mojang.brigadier.builder.ArgumentBuilder; + import com.mojang.brigadier.builder.LiteralArgumentBuilder; + import com.mojang.brigadier.builder.RequiredArgumentBuilder; +-import com.mojang.brigadier.context.CommandContext; + import com.mojang.brigadier.context.CommandContextBuilder; + import com.mojang.brigadier.context.ContextChain; + import com.mojang.brigadier.exceptions.CommandSyntaxException; + import com.mojang.brigadier.tree.CommandNode; + import com.mojang.brigadier.tree.RootCommandNode; + import com.mojang.logging.LogUtils; +-import java.util.Collection; ++import java.util.Iterator; + import java.util.Map; + import java.util.Optional; + import java.util.Set; +@@ -42,7 +40,6 @@ + import net.minecraft.network.chat.ComponentUtils; + import net.minecraft.network.chat.HoverEvent; + import net.minecraft.network.chat.MutableComponent; +-import net.minecraft.network.chat.Style; + import net.minecraft.network.protocol.game.ClientboundCommandsPacket; + import net.minecraft.resources.ResourceKey; + import net.minecraft.server.MinecraftServer; +@@ -137,17 +134,27 @@ + import net.minecraft.world.level.GameRules; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.google.common.base.Joiner; ++import java.util.Collection; ++import java.util.LinkedHashSet; ++import org.bukkit.event.player.PlayerCommandSendEvent; ++import org.bukkit.event.server.ServerCommandEvent; ++// CraftBukkit end ++ + public class Commands { +- private static final ThreadLocal> CURRENT_EXECUTION_CONTEXT = new ThreadLocal<>(); ++ ++ private static final ThreadLocal> CURRENT_EXECUTION_CONTEXT = new ThreadLocal(); + private static final Logger LOGGER = LogUtils.getLogger(); + public static final int LEVEL_ALL = 0; + public static final int LEVEL_MODERATORS = 1; + public static final int LEVEL_GAMEMASTERS = 2; + public static final int LEVEL_ADMINS = 3; + public static final int LEVEL_OWNERS = 4; +- private final CommandDispatcher dispatcher = new CommandDispatcher<>(); ++ private final com.mojang.brigadier.CommandDispatcher dispatcher = new com.mojang.brigadier.CommandDispatcher(); + + public Commands(Commands.CommandSelection selection, CommandBuildContext context) { ++ this(); // CraftBukkit + AdvancementCommands.register(this.dispatcher); + AttributeCommand.register(this.dispatcher, context); + ExecuteCommand.register(this.dispatcher, context); +@@ -248,157 +255,256 @@ + PublishCommand.register(this.dispatcher); + } + ++ // CraftBukkit start ++ } ++ ++ public Commands() { ++ // CraftBukkkit end + this.dispatcher.setConsumer(ExecutionCommandSource.resultConsumer()); + } + + public static ParseResults mapSource(ParseResults parseResults, UnaryOperator mapper) { +- CommandContextBuilder context = parseResults.getContext(); +- CommandContextBuilder commandContextBuilder = context.withSource(mapper.apply(context.getSource())); +- return new ParseResults<>(commandContextBuilder, parseResults.getReader(), parseResults.getExceptions()); ++ CommandContextBuilder commandcontextbuilder = parseResults.getContext(); ++ CommandContextBuilder commandcontextbuilder1 = commandcontextbuilder.withSource(mapper.apply(commandcontextbuilder.getSource())); ++ ++ return new ParseResults(commandcontextbuilder1, parseResults.getReader(), parseResults.getExceptions()); + } + +- public void performPrefixedCommand(CommandSourceStack commandSourceStack, String string) { +- string = string.startsWith("/") ? string.substring(1) : string; +- this.performCommand(this.dispatcher.parse(string, commandSourceStack), string); ++ // CraftBukkit start ++ public void dispatchServerCommand(CommandSourceStack sender, String command) { ++ Joiner joiner = Joiner.on(" "); ++ if (command.startsWith("/")) { ++ command = command.substring(1); ++ } ++ ++ ServerCommandEvent event = new ServerCommandEvent(sender.getBukkitSender(), command); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ command = event.getCommand(); ++ ++ String[] args = command.split(" "); ++ ++ String cmd = args[0]; ++ if (cmd.startsWith("minecraft:")) cmd = cmd.substring("minecraft:".length()); ++ if (cmd.startsWith("bukkit:")) cmd = cmd.substring("bukkit:".length()); ++ ++ // Block disallowed commands ++ if (cmd.equalsIgnoreCase("stop") || cmd.equalsIgnoreCase("kick") || cmd.equalsIgnoreCase("op") ++ || cmd.equalsIgnoreCase("deop") || cmd.equalsIgnoreCase("ban") || cmd.equalsIgnoreCase("ban-ip") ++ || cmd.equalsIgnoreCase("pardon") || cmd.equalsIgnoreCase("pardon-ip") || cmd.equalsIgnoreCase("reload")) { ++ return; ++ } ++ ++ // Handle vanilla commands; ++ if (sender.getLevel().getCraftServer().getCommandBlockOverride(args[0])) { ++ args[0] = "minecraft:" + args[0]; ++ } ++ ++ String newCommand = joiner.join(args); ++ this.performPrefixedCommand(sender, newCommand, newCommand); + } ++ // CraftBukkit end + +- public void performCommand(ParseResults parseResults, String string) { +- CommandSourceStack commandSourceStack = parseResults.getContext().getSource(); +- commandSourceStack.getServer().getProfiler().push(() -> "/" + string); +- ContextChain contextChain = finishParsing(parseResults, string, commandSourceStack); ++ public void performPrefixedCommand(CommandSourceStack commandlistenerwrapper, String s) { ++ // CraftBukkit start ++ this.performPrefixedCommand(commandlistenerwrapper, s, s); ++ } + ++ public void performPrefixedCommand(CommandSourceStack commandlistenerwrapper, String s, String label) { ++ s = s.startsWith("/") ? s.substring(1) : s; ++ this.performCommand(this.dispatcher.parse(s, commandlistenerwrapper), s, label); ++ // CraftBukkit end ++ } ++ ++ public void performCommand(ParseResults parseresults, String s) { ++ this.performCommand(parseresults, s, s); ++ } ++ ++ public void performCommand(ParseResults parseresults, String s, String label) { // CraftBukkit ++ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) parseresults.getContext().getSource(); ++ ++ commandlistenerwrapper.getServer().getProfiler().push(() -> { ++ return "/" + s; ++ }); ++ ContextChain contextchain = finishParsing(parseresults, s, commandlistenerwrapper, label); // CraftBukkit ++ + try { +- if (contextChain != null) { +- executeCommandInContext( +- commandSourceStack, +- executionContext -> ExecutionContext.queueInitialCommandExecution( +- executionContext, string, contextChain, commandSourceStack, CommandResultCallback.EMPTY +- ) +- ); ++ if (contextchain != null) { ++ executeCommandInContext(commandlistenerwrapper, (executioncontext) -> { ++ ExecutionContext.queueInitialCommandExecution(executioncontext, s, contextchain, commandlistenerwrapper, CommandResultCallback.EMPTY); ++ }); + } +- } catch (Exception var12) { +- MutableComponent mutableComponent = Component.literal(var12.getMessage() == null ? var12.getClass().getName() : var12.getMessage()); +- if (LOGGER.isDebugEnabled()) { +- LOGGER.error("Command exception: /{}", string, var12); +- StackTraceElement[] stackTrace = var12.getStackTrace(); ++ } catch (Exception exception) { ++ MutableComponent ichatmutablecomponent = Component.literal(exception.getMessage() == null ? exception.getClass().getName() : exception.getMessage()); + +- for (int i = 0; i < Math.min(stackTrace.length, 3); i++) { +- mutableComponent.append("\n\n") +- .append(stackTrace[i].getMethodName()) +- .append("\n ") +- .append(stackTrace[i].getFileName()) +- .append(":") +- .append(String.valueOf(stackTrace[i].getLineNumber())); ++ if (Commands.LOGGER.isDebugEnabled()) { ++ Commands.LOGGER.error("Command exception: /{}", s, exception); ++ StackTraceElement[] astacktraceelement = exception.getStackTrace(); ++ ++ for (int i = 0; i < Math.min(astacktraceelement.length, 3); ++i) { ++ ichatmutablecomponent.append("\n\n").append(astacktraceelement[i].getMethodName()).append("\n ").append(astacktraceelement[i].getFileName()).append(":").append(String.valueOf(astacktraceelement[i].getLineNumber())); + } + } + +- commandSourceStack.sendFailure( +- Component.translatable("command.failed") +- .withStyle(style -> style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, mutableComponent))) +- ); ++ commandlistenerwrapper.sendFailure(Component.translatable("command.failed").withStyle((chatmodifier) -> { ++ return chatmodifier.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, ichatmutablecomponent)); ++ })); + if (SharedConstants.IS_RUNNING_IN_IDE) { +- commandSourceStack.sendFailure(Component.literal(Util.describeError(var12))); +- LOGGER.error("'/{}' threw an exception", string, var12); ++ commandlistenerwrapper.sendFailure(Component.literal(Util.describeError(exception))); ++ Commands.LOGGER.error("'/{}' threw an exception", s, exception); + } + } finally { +- commandSourceStack.getServer().getProfiler().pop(); ++ commandlistenerwrapper.getServer().getProfiler().pop(); + } ++ + } + + @Nullable +- private static ContextChain finishParsing( +- ParseResults parseResults, String string, CommandSourceStack commandSourceStack +- ) { ++ private static ContextChain finishParsing(ParseResults parseresults, String s, CommandSourceStack commandlistenerwrapper, String label) { // CraftBukkit + try { +- validateParseResults(parseResults); +- return ContextChain.tryFlatten(parseResults.getContext().build(string)) +- .orElseThrow(() -> CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand().createWithContext(parseResults.getReader())); +- } catch (CommandSyntaxException var7) { +- commandSourceStack.sendFailure(ComponentUtils.fromMessage(var7.getRawMessage())); +- if (var7.getInput() != null && var7.getCursor() >= 0) { +- int min = Math.min(var7.getInput().length(), var7.getCursor()); +- MutableComponent mutableComponent = Component.empty() +- .withStyle(ChatFormatting.GRAY) +- .withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/" + string))); +- if (min > 10) { +- mutableComponent.append(CommonComponents.ELLIPSIS); ++ validateParseResults(parseresults); ++ return (ContextChain) ContextChain.tryFlatten(parseresults.getContext().build(s)).orElseThrow(() -> { ++ return CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand().createWithContext(parseresults.getReader()); ++ }); ++ } catch (CommandSyntaxException commandsyntaxexception) { ++ commandlistenerwrapper.sendFailure(ComponentUtils.fromMessage(commandsyntaxexception.getRawMessage())); ++ if (commandsyntaxexception.getInput() != null && commandsyntaxexception.getCursor() >= 0) { ++ int i = Math.min(commandsyntaxexception.getInput().length(), commandsyntaxexception.getCursor()); ++ MutableComponent ichatmutablecomponent = Component.empty().withStyle(ChatFormatting.GRAY).withStyle((chatmodifier) -> { ++ return chatmodifier.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, label)); // CraftBukkit ++ }); ++ ++ if (i > 10) { ++ ichatmutablecomponent.append(CommonComponents.ELLIPSIS); + } + +- mutableComponent.append(var7.getInput().substring(Math.max(0, min - 10), min)); +- if (min < var7.getInput().length()) { +- Component component = Component.literal(var7.getInput().substring(min)).withStyle(ChatFormatting.RED, ChatFormatting.UNDERLINE); +- mutableComponent.append(component); ++ ichatmutablecomponent.append(commandsyntaxexception.getInput().substring(Math.max(0, i - 10), i)); ++ if (i < commandsyntaxexception.getInput().length()) { ++ MutableComponent ichatmutablecomponent1 = Component.literal(commandsyntaxexception.getInput().substring(i)).withStyle(ChatFormatting.RED, ChatFormatting.UNDERLINE); ++ ++ ichatmutablecomponent.append((Component) ichatmutablecomponent1); + } + +- mutableComponent.append(Component.translatable("command.context.here").withStyle(ChatFormatting.RED, ChatFormatting.ITALIC)); +- commandSourceStack.sendFailure(mutableComponent); ++ ichatmutablecomponent.append((Component) Component.translatable("command.context.here").withStyle(ChatFormatting.RED, ChatFormatting.ITALIC)); ++ commandlistenerwrapper.sendFailure(ichatmutablecomponent); + } + + return null; + } + } + +- public static void executeCommandInContext(CommandSourceStack commandSourceStack, Consumer> consumer) { +- MinecraftServer server = commandSourceStack.getServer(); +- ExecutionContext executionContext = CURRENT_EXECUTION_CONTEXT.get(); +- boolean flag = executionContext == null; ++ public static void executeCommandInContext(CommandSourceStack commandlistenerwrapper, Consumer> consumer) { ++ MinecraftServer minecraftserver = commandlistenerwrapper.getServer(); ++ ExecutionContext executioncontext = (ExecutionContext) Commands.CURRENT_EXECUTION_CONTEXT.get(); ++ boolean flag = executioncontext == null; ++ + if (flag) { +- int max = Math.max(1, server.getGameRules().getInt(GameRules.RULE_MAX_COMMAND_CHAIN_LENGTH)); +- int _int = server.getGameRules().getInt(GameRules.RULE_MAX_COMMAND_FORK_COUNT); ++ int i = Math.max(1, minecraftserver.getGameRules().getInt(GameRules.RULE_MAX_COMMAND_CHAIN_LENGTH)); ++ int j = minecraftserver.getGameRules().getInt(GameRules.RULE_MAX_COMMAND_FORK_COUNT); + +- try (ExecutionContext executionContext1 = new ExecutionContext<>(max, _int, server.getProfiler())) { +- CURRENT_EXECUTION_CONTEXT.set(executionContext1); +- consumer.accept(executionContext1); +- executionContext1.runCommandQueue(); ++ try { ++ ExecutionContext executioncontext1 = new ExecutionContext<>(i, j, minecraftserver.getProfiler()); ++ ++ try { ++ Commands.CURRENT_EXECUTION_CONTEXT.set(executioncontext1); ++ consumer.accept(executioncontext1); ++ executioncontext1.runCommandQueue(); ++ } catch (Throwable throwable) { ++ try { ++ executioncontext1.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ ++ throw throwable; ++ } ++ ++ executioncontext1.close(); + } finally { +- CURRENT_EXECUTION_CONTEXT.set(null); ++ Commands.CURRENT_EXECUTION_CONTEXT.set(null); // CraftBukkit - decompile error + } + } else { +- consumer.accept(executionContext); ++ consumer.accept(executioncontext); + } ++ + } + + public void sendCommands(ServerPlayer player) { +- Map, CommandNode> map = Maps.newHashMap(); +- RootCommandNode rootCommandNode = new RootCommandNode<>(); +- map.put(this.dispatcher.getRoot(), rootCommandNode); +- this.fillUsableCommands(this.dispatcher.getRoot(), rootCommandNode, player.createCommandSourceStack(), map); +- player.connection.send(new ClientboundCommandsPacket(rootCommandNode)); ++ // CraftBukkit start ++ // Register Vanilla commands into builtRoot as before ++ Map, CommandNode> map = Maps.newIdentityHashMap(); // Use identity to prevent aliasing issues ++ RootCommandNode vanillaRoot = new RootCommandNode(); ++ ++ RootCommandNode vanilla = player.server.vanillaCommandDispatcher.getDispatcher().getRoot(); ++ map.put(vanilla, vanillaRoot); ++ this.fillUsableCommands(vanilla, vanillaRoot, player.createCommandSourceStack(), (Map) map); ++ ++ // Now build the global commands in a second pass ++ RootCommandNode rootcommandnode = new RootCommandNode(); ++ ++ map.put(this.dispatcher.getRoot(), rootcommandnode); ++ this.fillUsableCommands(this.dispatcher.getRoot(), rootcommandnode, player.createCommandSourceStack(), map); ++ ++ Collection bukkit = new LinkedHashSet<>(); ++ for (CommandNode node : rootcommandnode.getChildren()) { ++ bukkit.add(node.getName()); ++ } ++ ++ PlayerCommandSendEvent event = new PlayerCommandSendEvent(player.getBukkitEntity(), new LinkedHashSet<>(bukkit)); ++ event.getPlayer().getServer().getPluginManager().callEvent(event); ++ ++ // Remove labels that were removed during the event ++ for (String orig : bukkit) { ++ if (!event.getCommands().contains(orig)) { ++ rootcommandnode.removeCommand(orig); ++ } ++ } ++ // CraftBukkit end ++ player.connection.send(new ClientboundCommandsPacket(rootcommandnode)); + } + +- private void fillUsableCommands( +- CommandNode rootCommandSource, +- CommandNode rootSuggestion, +- CommandSourceStack source, +- Map, CommandNode> commandNodeToSuggestionNode +- ) { +- for (CommandNode commandNode : rootCommandSource.getChildren()) { +- if (commandNode.canUse(source)) { +- ArgumentBuilder argumentBuilder = (ArgumentBuilder) commandNode.createBuilder(); +- argumentBuilder.requires(sharedSuggestionProvider -> true); +- if (argumentBuilder.getCommand() != null) { +- argumentBuilder.executes(commandContext -> 0); ++ private void fillUsableCommands(CommandNode rootCommandSource, CommandNode rootSuggestion, CommandSourceStack source, Map, CommandNode> commandNodeToSuggestionNode) { ++ Iterator iterator = rootCommandSource.getChildren().iterator(); ++ ++ while (iterator.hasNext()) { ++ CommandNode commandnode2 = (CommandNode) iterator.next(); ++ ++ if (commandnode2.canUse(source)) { ++ ArgumentBuilder argumentbuilder = commandnode2.createBuilder(); // CraftBukkit - decompile error ++ ++ argumentbuilder.requires((icompletionprovider) -> { ++ return true; ++ }); ++ if (argumentbuilder.getCommand() != null) { ++ argumentbuilder.executes((commandcontext) -> { ++ return 0; ++ }); + } + +- if (argumentBuilder instanceof RequiredArgumentBuilder) { +- RequiredArgumentBuilder requiredArgumentBuilder = (RequiredArgumentBuilder)argumentBuilder; +- if (requiredArgumentBuilder.getSuggestionsProvider() != null) { +- requiredArgumentBuilder.suggests(SuggestionProviders.safelySwap(requiredArgumentBuilder.getSuggestionsProvider())); ++ if (argumentbuilder instanceof RequiredArgumentBuilder) { ++ RequiredArgumentBuilder requiredargumentbuilder = (RequiredArgumentBuilder) argumentbuilder; ++ ++ if (requiredargumentbuilder.getSuggestionsProvider() != null) { ++ requiredargumentbuilder.suggests(SuggestionProviders.safelySwap(requiredargumentbuilder.getSuggestionsProvider())); + } + } + +- if (argumentBuilder.getRedirect() != null) { +- argumentBuilder.redirect(commandNodeToSuggestionNode.get(argumentBuilder.getRedirect())); ++ if (argumentbuilder.getRedirect() != null) { ++ argumentbuilder.redirect((CommandNode) commandNodeToSuggestionNode.get(argumentbuilder.getRedirect())); + } + +- CommandNode commandNode1 = argumentBuilder.build(); +- commandNodeToSuggestionNode.put(commandNode, commandNode1); +- rootSuggestion.addChild(commandNode1); +- if (!commandNode.getChildren().isEmpty()) { +- this.fillUsableCommands(commandNode, commandNode1, source, commandNodeToSuggestionNode); ++ CommandNode commandnode3 = argumentbuilder.build(); // CraftBukkit - decompile error ++ ++ commandNodeToSuggestionNode.put(commandnode2, commandnode3); ++ rootSuggestion.addChild(commandnode3); ++ if (!commandnode2.getChildren().isEmpty()) { ++ this.fillUsableCommands(commandnode2, commandnode3, source, commandNodeToSuggestionNode); + } + } + } ++ + } + + public static LiteralArgumentBuilder literal(String name) { +@@ -410,46 +516,40 @@ + } + + public static Predicate createValidator(Commands.ParseFunction parser) { +- return string -> { ++ return (s) -> { + try { +- parser.parse(new StringReader(string)); ++ parser.parse(new StringReader(s)); + return true; +- } catch (CommandSyntaxException var3) { ++ } catch (CommandSyntaxException commandsyntaxexception) { + return false; + } + }; + } + +- public CommandDispatcher getDispatcher() { ++ public com.mojang.brigadier.CommandDispatcher getDispatcher() { + return this.dispatcher; + } + +- public static void validateParseResults(ParseResults parseResults) throws CommandSyntaxException { +- CommandSyntaxException parseException = getParseException(parseResults); +- if (parseException != null) { +- throw parseException; ++ public static void validateParseResults(ParseResults parseresults) throws CommandSyntaxException { ++ CommandSyntaxException commandsyntaxexception = getParseException(parseresults); ++ ++ if (commandsyntaxexception != null) { ++ throw commandsyntaxexception; + } + } + + @Nullable + public static CommandSyntaxException getParseException(ParseResults result) { +- if (!result.getReader().canRead()) { +- return null; +- } else if (result.getExceptions().size() == 1) { +- return result.getExceptions().values().iterator().next(); +- } else { +- return result.getContext().getRange().isEmpty() +- ? CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand().createWithContext(result.getReader()) +- : CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().createWithContext(result.getReader()); +- } ++ return !result.getReader().canRead() ? null : (result.getExceptions().size() == 1 ? (CommandSyntaxException) result.getExceptions().values().iterator().next() : (result.getContext().getRange().isEmpty() ? CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand().createWithContext(result.getReader()) : CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().createWithContext(result.getReader()))); + } + + public static CommandBuildContext createValidationContext(final HolderLookup.Provider provider) { + return new CommandBuildContext() { + @Override + public HolderLookup holderLookup(ResourceKey> registryResourceKey) { +- final HolderLookup.RegistryLookup registryLookup = provider.lookupOrThrow(registryResourceKey); +- return new HolderLookup.Delegate(registryLookup) { ++ final HolderLookup.RegistryLookup holderlookup_c = provider.lookupOrThrow(registryResourceKey); ++ ++ return new HolderLookup.Delegate(holderlookup_c) { + @Override + public Optional> get(TagKey tagKey) { + return Optional.of(this.getOrThrow(tagKey)); +@@ -457,8 +557,11 @@ + + @Override + public HolderSet.Named getOrThrow(TagKey tagKey) { +- Optional> optional = registryLookup.get(tagKey); +- return optional.orElseGet(() -> HolderSet.emptyNamed(registryLookup, tagKey)); ++ Optional> optional = holderlookup_c.get(tagKey); ++ ++ return (HolderSet.Named) optional.orElseGet(() -> { ++ return HolderSet.emptyNamed(holderlookup_c, tagKey); ++ }); + } + }; + } +@@ -466,43 +569,42 @@ + } + + public static void validate() { +- CommandBuildContext commandBuildContext = createValidationContext(VanillaRegistries.createLookup()); +- CommandDispatcher dispatcher = new Commands(Commands.CommandSelection.ALL, commandBuildContext).getDispatcher(); +- RootCommandNode root = dispatcher.getRoot(); +- dispatcher.findAmbiguities( +- (commandNode, commandNode1, commandNode2, collection) -> LOGGER.warn( +- "Ambiguity between arguments {} and {} with inputs: {}", dispatcher.getPath(commandNode1), dispatcher.getPath(commandNode2), collection +- ) +- ); +- Set> set = ArgumentUtils.findUsedArgumentTypes(root); +- Set> set1 = set.stream() +- .filter(argumentType -> !ArgumentTypeInfos.isClassRecognized(argumentType.getClass())) +- .collect(Collectors.toSet()); ++ CommandBuildContext commandbuildcontext = createValidationContext(VanillaRegistries.createLookup()); ++ com.mojang.brigadier.CommandDispatcher com_mojang_brigadier_commanddispatcher = (new Commands(Commands.CommandSelection.ALL, commandbuildcontext)).getDispatcher(); ++ RootCommandNode rootcommandnode = com_mojang_brigadier_commanddispatcher.getRoot(); ++ ++ com_mojang_brigadier_commanddispatcher.findAmbiguities((commandnode, commandnode1, commandnode2, collection) -> { ++ Commands.LOGGER.warn("Ambiguity between arguments {} and {} with inputs: {}", new Object[]{com_mojang_brigadier_commanddispatcher.getPath(commandnode1), com_mojang_brigadier_commanddispatcher.getPath(commandnode2), collection}); ++ }); ++ Set> set = ArgumentUtils.findUsedArgumentTypes(rootcommandnode); ++ Set> set1 = (Set) set.stream().filter((argumenttype) -> { ++ return !ArgumentTypeInfos.isClassRecognized(argumenttype.getClass()); ++ }).collect(Collectors.toSet()); ++ + if (!set1.isEmpty()) { +- LOGGER.warn( +- "Missing type registration for following arguments:\n {}", +- set1.stream().map(argumentType -> "\t" + argumentType).collect(Collectors.joining(",\n")) +- ); ++ Commands.LOGGER.warn("Missing type registration for following arguments:\n {}", set1.stream().map((argumenttype) -> { ++ return "\t" + argumenttype; ++ }).collect(Collectors.joining(",\n"))); + throw new IllegalStateException("Unregistered argument types"); + } + } + + public static enum CommandSelection { +- ALL(true, true), +- DEDICATED(false, true), +- INTEGRATED(true, false); + ++ ALL(true, true), DEDICATED(false, true), INTEGRATED(true, false); ++ + final boolean includeIntegrated; + final boolean includeDedicated; + +- private CommandSelection(boolean includeIntegrated, boolean includeDedicated) { +- this.includeIntegrated = includeIntegrated; +- this.includeDedicated = includeDedicated; ++ private CommandSelection(boolean flag, boolean flag1) { ++ this.includeIntegrated = flag; ++ this.includeDedicated = flag1; + } + } + + @FunctionalInterface + public interface ParseFunction { ++ + void parse(StringReader input) throws CommandSyntaxException; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/commands/arguments/EntityArgument.java.patch b/patch-remap/mache-vineflower/net/minecraft/commands/arguments/EntityArgument.java.patch new file mode 100644 index 0000000000..b7d912eaab --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/commands/arguments/EntityArgument.java.patch @@ -0,0 +1,225 @@ +--- a/net/minecraft/commands/arguments/EntityArgument.java ++++ b/net/minecraft/commands/arguments/EntityArgument.java +@@ -25,17 +25,14 @@ + import net.minecraft.world.entity.Entity; + + public class EntityArgument implements ArgumentType { ++ + private static final Collection EXAMPLES = Arrays.asList("Player", "0123", "@e", "@e[type=foo]", "dd12be42-52a9-4a91-a8a1-11c01849e498"); + public static final SimpleCommandExceptionType ERROR_NOT_SINGLE_ENTITY = new SimpleCommandExceptionType(Component.translatable("argument.entity.toomany")); + public static final SimpleCommandExceptionType ERROR_NOT_SINGLE_PLAYER = new SimpleCommandExceptionType(Component.translatable("argument.player.toomany")); +- public static final SimpleCommandExceptionType ERROR_ONLY_PLAYERS_ALLOWED = new SimpleCommandExceptionType( +- Component.translatable("argument.player.entities") +- ); ++ public static final SimpleCommandExceptionType ERROR_ONLY_PLAYERS_ALLOWED = new SimpleCommandExceptionType(Component.translatable("argument.player.entities")); + public static final SimpleCommandExceptionType NO_ENTITIES_FOUND = new SimpleCommandExceptionType(Component.translatable("argument.entity.notfound.entity")); + public static final SimpleCommandExceptionType NO_PLAYERS_FOUND = new SimpleCommandExceptionType(Component.translatable("argument.entity.notfound.player")); +- public static final SimpleCommandExceptionType ERROR_SELECTORS_NOT_ALLOWED = new SimpleCommandExceptionType( +- Component.translatable("argument.entity.selector.not_allowed") +- ); ++ public static final SimpleCommandExceptionType ERROR_SELECTORS_NOT_ALLOWED = new SimpleCommandExceptionType(Component.translatable("argument.entity.selector.not_allowed")); + final boolean single; + final boolean playersOnly; + +@@ -49,7 +46,7 @@ + } + + public static Entity getEntity(CommandContext context, String name) throws CommandSyntaxException { +- return context.getArgument(name, EntitySelector.class).findSingleEntity(context.getSource()); ++ return ((EntitySelector) context.getArgument(name, EntitySelector.class)).findSingleEntity((CommandSourceStack) context.getSource()); + } + + public static EntityArgument entities() { +@@ -57,20 +54,21 @@ + } + + public static Collection getEntities(CommandContext context, String name) throws CommandSyntaxException { +- Collection optionalEntities = getOptionalEntities(context, name); +- if (optionalEntities.isEmpty()) { +- throw NO_ENTITIES_FOUND.create(); ++ Collection collection = getOptionalEntities(context, name); ++ ++ if (collection.isEmpty()) { ++ throw EntityArgument.NO_ENTITIES_FOUND.create(); + } else { +- return optionalEntities; ++ return collection; + } + } + + public static Collection getOptionalEntities(CommandContext context, String name) throws CommandSyntaxException { +- return context.getArgument(name, EntitySelector.class).findEntities(context.getSource()); ++ return ((EntitySelector) context.getArgument(name, EntitySelector.class)).findEntities((CommandSourceStack) context.getSource()); + } + + public static Collection getOptionalPlayers(CommandContext context, String name) throws CommandSyntaxException { +- return context.getArgument(name, EntitySelector.class).findPlayers(context.getSource()); ++ return ((EntitySelector) context.getArgument(name, EntitySelector.class)).findPlayers((CommandSourceStack) context.getSource()); + } + + public static EntityArgument player() { +@@ -78,7 +76,7 @@ + } + + public static ServerPlayer getPlayer(CommandContext context, String name) throws CommandSyntaxException { +- return context.getArgument(name, EntitySelector.class).findSinglePlayer(context.getSource()); ++ return ((EntitySelector) context.getArgument(name, EntitySelector.class)).findSinglePlayer((CommandSourceStack) context.getSource()); + } + + public static EntityArgument players() { +@@ -86,74 +84,83 @@ + } + + public static Collection getPlayers(CommandContext context, String name) throws CommandSyntaxException { +- List list = context.getArgument(name, EntitySelector.class).findPlayers(context.getSource()); ++ List list = ((EntitySelector) context.getArgument(name, EntitySelector.class)).findPlayers((CommandSourceStack) context.getSource()); ++ + if (list.isEmpty()) { +- throw NO_PLAYERS_FOUND.create(); ++ throw EntityArgument.NO_PLAYERS_FOUND.create(); + } else { + return list; + } + } + +- @Override + public EntitySelector parse(StringReader reader) throws CommandSyntaxException { +- int i = 0; +- EntitySelectorParser entitySelectorParser = new EntitySelectorParser(reader); +- EntitySelector entitySelector = entitySelectorParser.parse(); +- if (entitySelector.getMaxResults() > 1 && this.single) { ++ // CraftBukkit start ++ return parse(reader, false); ++ } ++ ++ public EntitySelector parse(StringReader stringreader, boolean overridePermissions) throws CommandSyntaxException { ++ // CraftBukkit end ++ boolean flag = false; ++ EntitySelectorParser argumentparserselector = new EntitySelectorParser(stringreader); ++ EntitySelector entityselector = argumentparserselector.parse(overridePermissions); // CraftBukkit ++ ++ if (entityselector.getMaxResults() > 1 && this.single) { + if (this.playersOnly) { +- reader.setCursor(0); +- throw ERROR_NOT_SINGLE_PLAYER.createWithContext(reader); ++ stringreader.setCursor(0); ++ throw EntityArgument.ERROR_NOT_SINGLE_PLAYER.createWithContext(stringreader); + } else { +- reader.setCursor(0); +- throw ERROR_NOT_SINGLE_ENTITY.createWithContext(reader); ++ stringreader.setCursor(0); ++ throw EntityArgument.ERROR_NOT_SINGLE_ENTITY.createWithContext(stringreader); + } +- } else if (entitySelector.includesEntities() && this.playersOnly && !entitySelector.isSelfSelector()) { +- reader.setCursor(0); +- throw ERROR_ONLY_PLAYERS_ALLOWED.createWithContext(reader); ++ } else if (entityselector.includesEntities() && this.playersOnly && !entityselector.isSelfSelector()) { ++ stringreader.setCursor(0); ++ throw EntityArgument.ERROR_ONLY_PLAYERS_ALLOWED.createWithContext(stringreader); + } else { +- return entitySelector; ++ return entityselector; + } + } + +- @Override +- public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { +- if (context.getSource() instanceof SharedSuggestionProvider sharedSuggestionProvider) { +- StringReader stringReader = new StringReader(builder.getInput()); +- stringReader.setCursor(builder.getStart()); +- EntitySelectorParser entitySelectorParser = new EntitySelectorParser(stringReader, sharedSuggestionProvider.hasPermission(2)); ++ public CompletableFuture listSuggestions(CommandContext commandcontext, SuggestionsBuilder suggestionsbuilder) { ++ Object object = commandcontext.getSource(); + ++ if (object instanceof SharedSuggestionProvider) { ++ SharedSuggestionProvider icompletionprovider = (SharedSuggestionProvider) object; ++ StringReader stringreader = new StringReader(suggestionsbuilder.getInput()); ++ ++ stringreader.setCursor(suggestionsbuilder.getStart()); ++ EntitySelectorParser argumentparserselector = new EntitySelectorParser(stringreader, icompletionprovider.hasPermission(2)); ++ + try { +- entitySelectorParser.parse(); +- } catch (CommandSyntaxException var7) { ++ argumentparserselector.parse(); ++ } catch (CommandSyntaxException commandsyntaxexception) { ++ ; + } + +- return entitySelectorParser.fillSuggestions( +- builder, +- offsetBuilder -> { +- Collection onlinePlayerNames = sharedSuggestionProvider.getOnlinePlayerNames(); +- Iterable iterable = (Iterable)(this.playersOnly +- ? onlinePlayerNames +- : Iterables.concat(onlinePlayerNames, sharedSuggestionProvider.getSelectedEntities())); +- SharedSuggestionProvider.suggest(iterable, offsetBuilder); +- } +- ); ++ return argumentparserselector.fillSuggestions(suggestionsbuilder, (suggestionsbuilder1) -> { ++ Collection collection = icompletionprovider.getOnlinePlayerNames(); ++ Iterable iterable = this.playersOnly ? collection : Iterables.concat(collection, icompletionprovider.getSelectedEntities()); ++ ++ SharedSuggestionProvider.suggest((Iterable) iterable, suggestionsbuilder1); ++ }); + } else { + return Suggestions.empty(); + } + } + +- @Override + public Collection getExamples() { +- return EXAMPLES; ++ return EntityArgument.EXAMPLES; + } + + public static class Info implements ArgumentTypeInfo { ++ + private static final byte FLAG_SINGLE = 1; + private static final byte FLAG_PLAYERS_ONLY = 2; + +- @Override ++ public Info() {} ++ + public void serializeToNetwork(EntityArgument.Info.Template template, FriendlyByteBuf buffer) { + int i = 0; ++ + if (template.single) { + i |= 1; + } +@@ -167,28 +174,28 @@ + + @Override + public EntityArgument.Info.Template deserializeFromNetwork(FriendlyByteBuf buffer) { +- byte _byte = buffer.readByte(); +- return new EntityArgument.Info.Template((_byte & 1) != 0, (_byte & 2) != 0); ++ byte b0 = buffer.readByte(); ++ ++ return new EntityArgument.Info.Template((b0 & 1) != 0, (b0 & 2) != 0); + } + +- @Override + public void serializeToJson(EntityArgument.Info.Template template, JsonObject json) { + json.addProperty("amount", template.single ? "single" : "multiple"); + json.addProperty("type", template.playersOnly ? "players" : "entities"); + } + +- @Override + public EntityArgument.Info.Template unpack(EntityArgument argument) { + return new EntityArgument.Info.Template(argument.single, argument.playersOnly); + } + + public final class Template implements ArgumentTypeInfo.Template { ++ + final boolean single; + final boolean playersOnly; + +- Template(boolean single, boolean playersOnly) { +- this.single = single; +- this.playersOnly = playersOnly; ++ Template(boolean flag, boolean flag1) { ++ this.single = flag; ++ this.playersOnly = flag1; + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/commands/arguments/blocks/BlockStateParser.java.patch b/patch-remap/mache-vineflower/net/minecraft/commands/arguments/blocks/BlockStateParser.java.patch new file mode 100644 index 0000000000..77aa7b9a06 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/commands/arguments/blocks/BlockStateParser.java.patch @@ -0,0 +1,641 @@ +--- a/net/minecraft/commands/arguments/blocks/BlockStateParser.java ++++ b/net/minecraft/commands/arguments/blocks/BlockStateParser.java +@@ -1,6 +1,7 @@ + package net.minecraft.commands.arguments.blocks; + + import com.google.common.collect.Maps; ++import com.google.common.collect.UnmodifiableIterator; + import com.mojang.brigadier.StringReader; + import com.mojang.brigadier.exceptions.CommandSyntaxException; + import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; +@@ -10,10 +11,11 @@ + import com.mojang.brigadier.suggestion.Suggestions; + import com.mojang.brigadier.suggestion.SuggestionsBuilder; + import com.mojang.datafixers.util.Either; ++import java.util.Iterator; + import java.util.Locale; + import java.util.Map; +-import java.util.Optional; + import java.util.Map.Entry; ++import java.util.Optional; + import java.util.concurrent.CompletableFuture; + import java.util.function.Function; + import javax.annotation.Nullable; +@@ -29,35 +31,32 @@ + import net.minecraft.resources.ResourceLocation; + import net.minecraft.tags.TagKey; + import net.minecraft.world.level.block.Block; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.Property; + + public class BlockStateParser { +- public static final SimpleCommandExceptionType ERROR_NO_TAGS_ALLOWED = new SimpleCommandExceptionType( +- Component.translatable("argument.block.tag.disallowed") +- ); +- public static final DynamicCommandExceptionType ERROR_UNKNOWN_BLOCK = new DynamicCommandExceptionType( +- block -> Component.translatableEscape("argument.block.id.invalid", block) +- ); +- public static final Dynamic2CommandExceptionType ERROR_UNKNOWN_PROPERTY = new Dynamic2CommandExceptionType( +- (block, property) -> Component.translatableEscape("argument.block.property.unknown", block, property) +- ); +- public static final Dynamic2CommandExceptionType ERROR_DUPLICATE_PROPERTY = new Dynamic2CommandExceptionType( +- (property, block) -> Component.translatableEscape("argument.block.property.duplicate", block, property) +- ); +- public static final Dynamic3CommandExceptionType ERROR_INVALID_VALUE = new Dynamic3CommandExceptionType( +- (block, value, property) -> Component.translatableEscape("argument.block.property.invalid", block, property, value) +- ); +- public static final Dynamic2CommandExceptionType ERROR_EXPECTED_VALUE = new Dynamic2CommandExceptionType( +- (property, block) -> Component.translatableEscape("argument.block.property.novalue", property, block) +- ); +- public static final SimpleCommandExceptionType ERROR_EXPECTED_END_OF_PROPERTIES = new SimpleCommandExceptionType( +- Component.translatable("argument.block.property.unclosed") +- ); +- public static final DynamicCommandExceptionType ERROR_UNKNOWN_TAG = new DynamicCommandExceptionType( +- blockTag -> Component.translatableEscape("arguments.block.tag.unknown", blockTag) +- ); ++ ++ public static final SimpleCommandExceptionType ERROR_NO_TAGS_ALLOWED = new SimpleCommandExceptionType(Component.translatable("argument.block.tag.disallowed")); ++ public static final DynamicCommandExceptionType ERROR_UNKNOWN_BLOCK = new DynamicCommandExceptionType((object) -> { ++ return Component.translatableEscape("argument.block.id.invalid", object); ++ }); ++ public static final Dynamic2CommandExceptionType ERROR_UNKNOWN_PROPERTY = new Dynamic2CommandExceptionType((object, object1) -> { ++ return Component.translatableEscape("argument.block.property.unknown", object, object1); ++ }); ++ public static final Dynamic2CommandExceptionType ERROR_DUPLICATE_PROPERTY = new Dynamic2CommandExceptionType((object, object1) -> { ++ return Component.translatableEscape("argument.block.property.duplicate", object1, object); ++ }); ++ public static final Dynamic3CommandExceptionType ERROR_INVALID_VALUE = new Dynamic3CommandExceptionType((object, object1, object2) -> { ++ return Component.translatableEscape("argument.block.property.invalid", object, object2, object1); ++ }); ++ public static final Dynamic2CommandExceptionType ERROR_EXPECTED_VALUE = new Dynamic2CommandExceptionType((object, object1) -> { ++ return Component.translatableEscape("argument.block.property.novalue", object, object1); ++ }); ++ public static final SimpleCommandExceptionType ERROR_EXPECTED_END_OF_PROPERTIES = new SimpleCommandExceptionType(Component.translatable("argument.block.property.unclosed")); ++ public static final DynamicCommandExceptionType ERROR_UNKNOWN_TAG = new DynamicCommandExceptionType((object) -> { ++ return Component.translatableEscape("arguments.block.tag.unknown", object); ++ }); + private static final char SYNTAX_START_PROPERTIES = '['; + private static final char SYNTAX_START_NBT = '{'; + private static final char SYNTAX_END_PROPERTIES = ']'; +@@ -69,75 +68,76 @@ + private final StringReader reader; + private final boolean forTesting; + private final boolean allowNbt; +- private final Map, Comparable> properties = Maps.newHashMap(); ++ private final Map, Comparable> properties = Maps.newLinkedHashMap(); // CraftBukkit - stable + private final Map vagueProperties = Maps.newHashMap(); + private ResourceLocation id = new ResourceLocation(""); + @Nullable +- private StateDefinition definition; ++ private StateDefinition definition; + @Nullable +- private BlockState state; ++ private IBlockData state; + @Nullable + private CompoundTag nbt; + @Nullable + private HolderSet tag; +- private Function> suggestions = SUGGEST_NOTHING; ++ private Function> suggestions; + + private BlockStateParser(HolderLookup blocks, StringReader reader, boolean forTesting, boolean allowNbt) { ++ this.suggestions = BlockStateParser.SUGGEST_NOTHING; + this.blocks = blocks; + this.reader = reader; + this.forTesting = forTesting; + this.allowNbt = allowNbt; + } + +- public static BlockStateParser.BlockResult parseForBlock(HolderLookup lookup, String input, boolean allowNbt) throws CommandSyntaxException { ++ public static BlockStateParser.a parseForBlock(HolderLookup lookup, String input, boolean allowNbt) throws CommandSyntaxException { + return parseForBlock(lookup, new StringReader(input), allowNbt); + } + +- public static BlockStateParser.BlockResult parseForBlock(HolderLookup lookup, StringReader reader, boolean allowNbt) throws CommandSyntaxException { +- int cursor = reader.getCursor(); ++ public static BlockStateParser.a parseForBlock(HolderLookup lookup, StringReader reader, boolean allowNbt) throws CommandSyntaxException { ++ int i = reader.getCursor(); + + try { +- BlockStateParser blockStateParser = new BlockStateParser(lookup, reader, false, allowNbt); +- blockStateParser.parse(); +- return new BlockStateParser.BlockResult(blockStateParser.state, blockStateParser.properties, blockStateParser.nbt); +- } catch (CommandSyntaxException var5) { +- reader.setCursor(cursor); +- throw var5; ++ BlockStateParser argumentblock = new BlockStateParser(lookup, reader, false, allowNbt); ++ ++ argumentblock.parse(); ++ return new BlockStateParser.a(argumentblock.state, argumentblock.properties, argumentblock.nbt); ++ } catch (CommandSyntaxException commandsyntaxexception) { ++ reader.setCursor(i); ++ throw commandsyntaxexception; + } + } + +- public static Either parseForTesting(HolderLookup lookup, String input, boolean allowNbt) throws CommandSyntaxException { ++ public static Either parseForTesting(HolderLookup lookup, String input, boolean allowNbt) throws CommandSyntaxException { + return parseForTesting(lookup, new StringReader(input), allowNbt); + } + +- public static Either parseForTesting( +- HolderLookup lookup, StringReader reader, boolean allowNbt +- ) throws CommandSyntaxException { +- int cursor = reader.getCursor(); ++ public static Either parseForTesting(HolderLookup lookup, StringReader reader, boolean allowNbt) throws CommandSyntaxException { ++ int i = reader.getCursor(); + + try { +- BlockStateParser blockStateParser = new BlockStateParser(lookup, reader, true, allowNbt); +- blockStateParser.parse(); +- return blockStateParser.tag != null +- ? Either.right(new BlockStateParser.TagResult(blockStateParser.tag, blockStateParser.vagueProperties, blockStateParser.nbt)) +- : Either.left(new BlockStateParser.BlockResult(blockStateParser.state, blockStateParser.properties, blockStateParser.nbt)); +- } catch (CommandSyntaxException var5) { +- reader.setCursor(cursor); +- throw var5; ++ BlockStateParser argumentblock = new BlockStateParser(lookup, reader, true, allowNbt); ++ ++ argumentblock.parse(); ++ return argumentblock.tag != null ? Either.right(new BlockStateParser.b(argumentblock.tag, argumentblock.vagueProperties, argumentblock.nbt)) : Either.left(new BlockStateParser.a(argumentblock.state, argumentblock.properties, argumentblock.nbt)); ++ } catch (CommandSyntaxException commandsyntaxexception) { ++ reader.setCursor(i); ++ throw commandsyntaxexception; + } + } + + public static CompletableFuture fillSuggestions(HolderLookup lookup, SuggestionsBuilder builder, boolean forTesting, boolean allowNbt) { +- StringReader stringReader = new StringReader(builder.getInput()); +- stringReader.setCursor(builder.getStart()); +- BlockStateParser blockStateParser = new BlockStateParser(lookup, stringReader, forTesting, allowNbt); ++ StringReader stringreader = new StringReader(builder.getInput()); + ++ stringreader.setCursor(builder.getStart()); ++ BlockStateParser argumentblock = new BlockStateParser(lookup, stringreader, forTesting, allowNbt); ++ + try { +- blockStateParser.parse(); +- } catch (CommandSyntaxException var7) { ++ argumentblock.parse(); ++ } catch (CommandSyntaxException commandsyntaxexception) { ++ ; + } + +- return blockStateParser.suggestions.apply(builder.createOffset(stringReader.getCursor())); ++ return (CompletableFuture) argumentblock.suggestions.apply(builder.createOffset(stringreader.getCursor())); + } + + private void parse() throws CommandSyntaxException { +@@ -164,9 +164,10 @@ + } + + if (this.allowNbt && this.reader.canRead() && this.reader.peek() == '{') { +- this.suggestions = SUGGEST_NOTHING; ++ this.suggestions = BlockStateParser.SUGGEST_NOTHING; + this.readNbt(); + } ++ + } + + private CompletableFuture suggestPropertyNameOrEnd(SuggestionsBuilder builder) { +@@ -186,11 +187,14 @@ + } + + private CompletableFuture suggestPropertyName(SuggestionsBuilder builder) { +- String string = builder.getRemaining().toLowerCase(Locale.ROOT); ++ String s = builder.getRemaining().toLowerCase(Locale.ROOT); ++ Iterator iterator = this.state.getProperties().iterator(); + +- for (Property property : this.state.getProperties()) { +- if (!this.properties.containsKey(property) && property.getName().startsWith(string)) { +- builder.suggest(property.getName() + "="); ++ while (iterator.hasNext()) { ++ Property iblockstate = (Property) iterator.next(); ++ ++ if (!this.properties.containsKey(iblockstate) && iblockstate.getName().startsWith(s)) { ++ builder.suggest(iblockstate.getName() + "="); + } + } + +@@ -198,12 +202,20 @@ + } + + private CompletableFuture suggestVaguePropertyName(SuggestionsBuilder builder) { +- String string = builder.getRemaining().toLowerCase(Locale.ROOT); ++ String s = builder.getRemaining().toLowerCase(Locale.ROOT); ++ + if (this.tag != null) { +- for (Holder holder : this.tag) { +- for (Property property : holder.value().getStateDefinition().getProperties()) { +- if (!this.vagueProperties.containsKey(property.getName()) && property.getName().startsWith(string)) { +- builder.suggest(property.getName() + "="); ++ Iterator iterator = this.tag.iterator(); ++ ++ while (iterator.hasNext()) { ++ Holder holder = (Holder) iterator.next(); ++ Iterator iterator1 = ((Block) holder.value()).getStateDefinition().getProperties().iterator(); ++ ++ while (iterator1.hasNext()) { ++ Property iblockstate = (Property) iterator1.next(); ++ ++ if (!this.vagueProperties.containsKey(iblockstate.getName()) && iblockstate.getName().startsWith(s)) { ++ builder.suggest(iblockstate.getName() + "="); + } + } + } +@@ -225,8 +237,12 @@ + return this.state.hasBlockEntity(); + } else { + if (this.tag != null) { +- for (Holder holder : this.tag) { +- if (holder.value().defaultBlockState().hasBlockEntity()) { ++ Iterator iterator = this.tag.iterator(); ++ ++ while (iterator.hasNext()) { ++ Holder holder = (Holder) iterator.next(); ++ ++ if (((Block) holder.value()).defaultBlockState().hasBlockEntity()) { + return true; + } + } +@@ -257,11 +273,17 @@ + } + + private static > SuggestionsBuilder addSuggestions(SuggestionsBuilder builder, Property property) { +- for (T comparable : property.getPossibleValues()) { +- if (comparable instanceof Integer integer) { ++ Iterator iterator = property.getPossibleValues().iterator(); ++ ++ while (iterator.hasNext()) { ++ T t0 = (T) iterator.next(); // CraftBukkit - decompile error ++ ++ if (t0 instanceof Integer) { ++ Integer integer = (Integer) t0; ++ + builder.suggest(integer); + } else { +- builder.suggest(property.getName(comparable)); ++ builder.suggest(property.getName(t0)); + } + } + +@@ -270,17 +292,26 @@ + + private CompletableFuture suggestVaguePropertyValue(SuggestionsBuilder builder, String propertyName) { + boolean flag = false; ++ + if (this.tag != null) { +- for (Holder holder : this.tag) { +- Block block = holder.value(); +- Property property = block.getStateDefinition().getProperty(propertyName); +- if (property != null) { +- addSuggestions(builder, property); ++ Iterator iterator = this.tag.iterator(); ++ ++ while (iterator.hasNext()) { ++ Holder holder = (Holder) iterator.next(); ++ Block block = (Block) holder.value(); ++ Property iblockstate = block.getStateDefinition().getProperty(propertyName); ++ ++ if (iblockstate != null) { ++ addSuggestions(builder, iblockstate); + } + + if (!flag) { +- for (Property property1 : block.getStateDefinition().getProperties()) { +- if (!this.vagueProperties.containsKey(property1.getName())) { ++ Iterator iterator1 = block.getStateDefinition().getProperties().iterator(); ++ ++ while (iterator1.hasNext()) { ++ Property iblockstate1 = (Property) iterator1.next(); ++ ++ if (!this.vagueProperties.containsKey(iblockstate1.getName())) { + flag = true; + break; + } +@@ -301,9 +332,12 @@ + if (builder.getRemaining().isEmpty() && this.tag != null) { + boolean flag = false; + boolean flag1 = false; ++ Iterator iterator = this.tag.iterator(); + +- for (Holder holder : this.tag) { +- Block block = holder.value(); ++ while (iterator.hasNext()) { ++ Holder holder = (Holder) iterator.next(); ++ Block block = (Block) holder.value(); ++ + flag |= !block.getStateDefinition().getProperties().isEmpty(); + flag1 |= block.defaultBlockState().hasBlockEntity(); + if (flag && flag1) { +@@ -352,27 +386,31 @@ + } + + private void readBlock() throws CommandSyntaxException { +- int cursor = this.reader.getCursor(); ++ int i = this.reader.getCursor(); ++ + this.id = ResourceLocation.read(this.reader); +- Block block = this.blocks.get(ResourceKey.create(Registries.BLOCK, this.id)).orElseThrow(() -> { +- this.reader.setCursor(cursor); +- return ERROR_UNKNOWN_BLOCK.createWithContext(this.reader, this.id.toString()); +- }).value(); ++ Block block = (Block) ((Holder.Reference) this.blocks.get(ResourceKey.create(Registries.BLOCK, this.id)).orElseThrow(() -> { ++ this.reader.setCursor(i); ++ return BlockStateParser.ERROR_UNKNOWN_BLOCK.createWithContext(this.reader, this.id.toString()); ++ })).value(); ++ + this.definition = block.getStateDefinition(); + this.state = block.defaultBlockState(); + } + + private void readTag() throws CommandSyntaxException { + if (!this.forTesting) { +- throw ERROR_NO_TAGS_ALLOWED.createWithContext(this.reader); ++ throw BlockStateParser.ERROR_NO_TAGS_ALLOWED.createWithContext(this.reader); + } else { +- int cursor = this.reader.getCursor(); ++ int i = this.reader.getCursor(); ++ + this.reader.expect('#'); + this.suggestions = this::suggestTag; +- ResourceLocation resourceLocation = ResourceLocation.read(this.reader); +- this.tag = this.blocks.get(TagKey.create(Registries.BLOCK, resourceLocation)).orElseThrow(() -> { +- this.reader.setCursor(cursor); +- return ERROR_UNKNOWN_TAG.createWithContext(this.reader, resourceLocation.toString()); ++ ResourceLocation minecraftkey = ResourceLocation.read(this.reader); ++ ++ this.tag = (HolderSet) this.blocks.get(TagKey.create(Registries.BLOCK, minecraftkey)).orElseThrow(() -> { ++ this.reader.setCursor(i); ++ return BlockStateParser.ERROR_UNKNOWN_TAG.createWithContext(this.reader, minecraftkey.toString()); + }); + } + } +@@ -382,51 +420,60 @@ + this.suggestions = this::suggestPropertyNameOrEnd; + this.reader.skipWhitespace(); + +- while (this.reader.canRead() && this.reader.peek() != ']') { +- this.reader.skipWhitespace(); +- int cursor = this.reader.getCursor(); +- String string = this.reader.readString(); +- Property property = this.definition.getProperty(string); +- if (property == null) { +- this.reader.setCursor(cursor); +- throw ERROR_UNKNOWN_PROPERTY.createWithContext(this.reader, this.id.toString(), string); +- } ++ while (true) { ++ if (this.reader.canRead() && this.reader.peek() != ']') { ++ this.reader.skipWhitespace(); ++ int i = this.reader.getCursor(); ++ String s = this.reader.readString(); ++ Property iblockstate = this.definition.getProperty(s); + +- if (this.properties.containsKey(property)) { +- this.reader.setCursor(cursor); +- throw ERROR_DUPLICATE_PROPERTY.createWithContext(this.reader, this.id.toString(), string); +- } ++ if (iblockstate == null) { ++ this.reader.setCursor(i); ++ throw BlockStateParser.ERROR_UNKNOWN_PROPERTY.createWithContext(this.reader, this.id.toString(), s); ++ } + +- this.reader.skipWhitespace(); +- this.suggestions = this::suggestEquals; +- if (!this.reader.canRead() || this.reader.peek() != '=') { +- throw ERROR_EXPECTED_VALUE.createWithContext(this.reader, this.id.toString(), string); +- } ++ if (this.properties.containsKey(iblockstate)) { ++ this.reader.setCursor(i); ++ throw BlockStateParser.ERROR_DUPLICATE_PROPERTY.createWithContext(this.reader, this.id.toString(), s); ++ } + +- this.reader.skip(); +- this.reader.skipWhitespace(); +- this.suggestions = builder -> addSuggestions(builder, property).buildFuture(); +- int cursor1 = this.reader.getCursor(); +- this.setValue(property, this.reader.readString(), cursor1); +- this.suggestions = this::suggestNextPropertyOrEnd; +- this.reader.skipWhitespace(); +- if (this.reader.canRead()) { +- if (this.reader.peek() != ',') { +- if (this.reader.peek() != ']') { +- throw ERROR_EXPECTED_END_OF_PROPERTIES.createWithContext(this.reader); +- } +- break; ++ this.reader.skipWhitespace(); ++ this.suggestions = this::suggestEquals; ++ if (!this.reader.canRead() || this.reader.peek() != '=') { ++ throw BlockStateParser.ERROR_EXPECTED_VALUE.createWithContext(this.reader, this.id.toString(), s); + } + + this.reader.skip(); +- this.suggestions = this::suggestPropertyName; ++ this.reader.skipWhitespace(); ++ this.suggestions = (suggestionsbuilder) -> { ++ return addSuggestions(suggestionsbuilder, iblockstate).buildFuture(); ++ }; ++ int j = this.reader.getCursor(); ++ ++ this.setValue(iblockstate, this.reader.readString(), j); ++ this.suggestions = this::suggestNextPropertyOrEnd; ++ this.reader.skipWhitespace(); ++ if (!this.reader.canRead()) { ++ continue; ++ } ++ ++ if (this.reader.peek() == ',') { ++ this.reader.skip(); ++ this.suggestions = this::suggestPropertyName; ++ continue; ++ } ++ ++ if (this.reader.peek() != ']') { ++ throw BlockStateParser.ERROR_EXPECTED_END_OF_PROPERTIES.createWithContext(this.reader); ++ } + } +- } + +- if (this.reader.canRead()) { +- this.reader.skip(); +- } else { +- throw ERROR_EXPECTED_END_OF_PROPERTIES.createWithContext(this.reader); ++ if (this.reader.canRead()) { ++ this.reader.skip(); ++ return; ++ } ++ ++ throw BlockStateParser.ERROR_EXPECTED_END_OF_PROPERTIES.createWithContext(this.reader); + } + } + +@@ -434,100 +481,117 @@ + this.reader.skip(); + this.suggestions = this::suggestVaguePropertyNameOrEnd; + int i = -1; ++ + this.reader.skipWhitespace(); + +- while (this.reader.canRead() && this.reader.peek() != ']') { +- this.reader.skipWhitespace(); +- int cursor = this.reader.getCursor(); +- String string = this.reader.readString(); +- if (this.vagueProperties.containsKey(string)) { +- this.reader.setCursor(cursor); +- throw ERROR_DUPLICATE_PROPERTY.createWithContext(this.reader, this.id.toString(), string); +- } ++ while (true) { ++ if (this.reader.canRead() && this.reader.peek() != ']') { ++ this.reader.skipWhitespace(); ++ int j = this.reader.getCursor(); ++ String s = this.reader.readString(); + +- this.reader.skipWhitespace(); +- if (!this.reader.canRead() || this.reader.peek() != '=') { +- this.reader.setCursor(cursor); +- throw ERROR_EXPECTED_VALUE.createWithContext(this.reader, this.id.toString(), string); +- } ++ if (this.vagueProperties.containsKey(s)) { ++ this.reader.setCursor(j); ++ throw BlockStateParser.ERROR_DUPLICATE_PROPERTY.createWithContext(this.reader, this.id.toString(), s); ++ } + +- this.reader.skip(); +- this.reader.skipWhitespace(); +- this.suggestions = builder -> this.suggestVaguePropertyValue(builder, string); +- i = this.reader.getCursor(); +- String string1 = this.reader.readString(); +- this.vagueProperties.put(string, string1); +- this.reader.skipWhitespace(); +- if (this.reader.canRead()) { ++ this.reader.skipWhitespace(); ++ if (!this.reader.canRead() || this.reader.peek() != '=') { ++ this.reader.setCursor(j); ++ throw BlockStateParser.ERROR_EXPECTED_VALUE.createWithContext(this.reader, this.id.toString(), s); ++ } ++ ++ this.reader.skip(); ++ this.reader.skipWhitespace(); ++ this.suggestions = (suggestionsbuilder) -> { ++ return this.suggestVaguePropertyValue(suggestionsbuilder, s); ++ }; ++ i = this.reader.getCursor(); ++ String s1 = this.reader.readString(); ++ ++ this.vagueProperties.put(s, s1); ++ this.reader.skipWhitespace(); ++ if (!this.reader.canRead()) { ++ continue; ++ } ++ + i = -1; +- if (this.reader.peek() != ',') { +- if (this.reader.peek() != ']') { +- throw ERROR_EXPECTED_END_OF_PROPERTIES.createWithContext(this.reader); +- } +- break; ++ if (this.reader.peek() == ',') { ++ this.reader.skip(); ++ this.suggestions = this::suggestVaguePropertyName; ++ continue; + } + ++ if (this.reader.peek() != ']') { ++ throw BlockStateParser.ERROR_EXPECTED_END_OF_PROPERTIES.createWithContext(this.reader); ++ } ++ } ++ ++ if (this.reader.canRead()) { + this.reader.skip(); +- this.suggestions = this::suggestVaguePropertyName; ++ return; + } +- } + +- if (this.reader.canRead()) { +- this.reader.skip(); +- } else { + if (i >= 0) { + this.reader.setCursor(i); + } + +- throw ERROR_EXPECTED_END_OF_PROPERTIES.createWithContext(this.reader); ++ throw BlockStateParser.ERROR_EXPECTED_END_OF_PROPERTIES.createWithContext(this.reader); + } + } + + private void readNbt() throws CommandSyntaxException { +- this.nbt = new TagParser(this.reader).readStruct(); ++ this.nbt = (new TagParser(this.reader)).readStruct(); + } + + private > void setValue(Property property, String value, int valuePosition) throws CommandSyntaxException { +- Optional value1 = property.getValue(value); +- if (value1.isPresent()) { +- this.state = this.state.setValue(property, value1.get()); +- this.properties.put(property, value1.get()); ++ Optional optional = property.getValue(value); ++ ++ if (optional.isPresent()) { ++ this.state = (IBlockData) this.state.setValue(property, (T) optional.get()); // CraftBukkit - decompile error ++ this.properties.put(property, (Comparable) optional.get()); + } else { + this.reader.setCursor(valuePosition); +- throw ERROR_INVALID_VALUE.createWithContext(this.reader, this.id.toString(), property.getName(), value); ++ throw BlockStateParser.ERROR_INVALID_VALUE.createWithContext(this.reader, this.id.toString(), property.getName(), value); + } + } + +- public static String serialize(BlockState state) { +- StringBuilder stringBuilder = new StringBuilder(state.getBlockHolder().unwrapKey().map(blockKey -> blockKey.location().toString()).orElse("air")); ++ public static String serialize(IBlockData state) { ++ StringBuilder stringbuilder = new StringBuilder((String) state.getBlockHolder().unwrapKey().map((resourcekey) -> { ++ return resourcekey.location().toString(); ++ }).orElse("air")); ++ + if (!state.getProperties().isEmpty()) { +- stringBuilder.append('['); ++ stringbuilder.append('['); + boolean flag = false; + +- for (Entry, Comparable> entry : state.getValues().entrySet()) { ++ for (UnmodifiableIterator unmodifiableiterator = state.getValues().entrySet().iterator(); unmodifiableiterator.hasNext(); flag = true) { ++ Entry, Comparable> entry = (Entry) unmodifiableiterator.next(); ++ + if (flag) { +- stringBuilder.append(','); ++ stringbuilder.append(','); + } + +- appendProperty(stringBuilder, entry.getKey(), entry.getValue()); +- flag = true; ++ appendProperty(stringbuilder, (Property) entry.getKey(), (Comparable) entry.getValue()); + } + +- stringBuilder.append(']'); ++ stringbuilder.append(']'); + } + +- return stringBuilder.toString(); ++ return stringbuilder.toString(); + } + + private static > void appendProperty(StringBuilder builder, Property property, Comparable value) { + builder.append(property.getName()); + builder.append('='); +- builder.append(property.getName((T)value)); ++ builder.append(property.getName((T) value)); // CraftBukkit - decompile error + } + +- public static record BlockResult(BlockState blockState, Map, Comparable> properties, @Nullable CompoundTag nbt) { ++ public static record a(IBlockData blockState, Map, Comparable> properties, @Nullable CompoundTag nbt) { ++ + } + +- public static record TagResult(HolderSet tag, Map vagueProperties, @Nullable CompoundTag nbt) { ++ public static record b(HolderSet tag, Map vagueProperties, @Nullable CompoundTag nbt) { ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/commands/arguments/selector/EntitySelector.java.patch b/patch-remap/mache-vineflower/net/minecraft/commands/arguments/selector/EntitySelector.java.patch new file mode 100644 index 0000000000..150b9bd72a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/commands/arguments/selector/EntitySelector.java.patch @@ -0,0 +1,280 @@ +--- a/net/minecraft/commands/arguments/selector/EntitySelector.java ++++ b/net/minecraft/commands/arguments/selector/EntitySelector.java +@@ -3,6 +3,7 @@ + import com.google.common.collect.Lists; + import com.mojang.brigadier.exceptions.CommandSyntaxException; + import java.util.Collections; ++import java.util.Iterator; + import java.util.List; + import java.util.UUID; + import java.util.function.BiConsumer; +@@ -23,11 +24,11 @@ + import net.minecraft.world.phys.Vec3; + + public class EntitySelector { ++ + public static final int INFINITE = Integer.MAX_VALUE; +- public static final BiConsumer> ORDER_ARBITRARY = (center, entityList) -> { ++ public static final BiConsumer> ORDER_ARBITRARY = (vec3d, list) -> { + }; + private static final EntityTypeTest ANY_TYPE = new EntityTypeTest() { +- @Override + public Entity tryCast(Entity entity) { + return entity; + } +@@ -54,21 +55,7 @@ + private final EntityTypeTest type; + private final boolean usesSelector; + +- public EntitySelector( +- int maxResults, +- boolean includeEntities, +- boolean worldLimited, +- Predicate predicate, +- MinMaxBounds.Doubles range, +- Function positions, +- @Nullable AABB aabb, +- BiConsumer> order, +- boolean currentEntity, +- @Nullable String playerName, +- @Nullable UUID entityUUID, +- @Nullable EntityType type, +- boolean usesSelector +- ) { ++ public EntitySelector(int maxResults, boolean includeEntities, boolean worldLimited, Predicate predicate, MinMaxBounds.Doubles range, Function positions, @Nullable AABB aabb, BiConsumer> order, boolean currentEntity, @Nullable String playerName, @Nullable UUID entityUUID, @Nullable EntityType type, boolean usesSelector) { + this.maxResults = maxResults; + this.includesEntities = includeEntities; + this.worldLimited = worldLimited; +@@ -80,7 +67,7 @@ + this.currentEntity = currentEntity; + this.playerName = playerName; + this.entityUUID = entityUUID; +- this.type = (EntityTypeTest)(type == null ? ANY_TYPE : type); ++ this.type = (EntityTypeTest) (type == null ? EntitySelector.ANY_TYPE : type); + this.usesSelector = usesSelector; + } + +@@ -105,7 +92,7 @@ + } + + private void checkPermissions(CommandSourceStack source) throws CommandSyntaxException { +- if (this.usesSelector && !source.hasPermission(2)) { ++ if (this.usesSelector && !source.hasPermission(2, "minecraft.command.selector")) { // CraftBukkit + throw EntityArgument.ERROR_SELECTORS_NOT_ALLOWED.create(); + } + } +@@ -113,17 +100,20 @@ + public Entity findSingleEntity(CommandSourceStack source) throws CommandSyntaxException { + this.checkPermissions(source); + List list = this.findEntities(source); ++ + if (list.isEmpty()) { + throw EntityArgument.NO_ENTITIES_FOUND.create(); + } else if (list.size() > 1) { + throw EntityArgument.ERROR_NOT_SINGLE_ENTITY.create(); + } else { +- return list.get(0); ++ return (Entity) list.get(0); + } + } + + public List findEntities(CommandSourceStack source) throws CommandSyntaxException { +- return this.findEntitiesRaw(source).stream().filter(entity -> entity.getType().isEnabled(source.enabledFeatures())).toList(); ++ return this.findEntitiesRaw(source).stream().filter((entity) -> { ++ return entity.getType().isEnabled(source.enabledFeatures()); ++ }).toList(); + } + + private List findEntitiesRaw(CommandSourceStack source) throws CommandSyntaxException { +@@ -131,113 +121,147 @@ + if (!this.includesEntities) { + return this.findPlayers(source); + } else if (this.playerName != null) { +- ServerPlayer playerByName = source.getServer().getPlayerList().getPlayerByName(this.playerName); +- return (List)(playerByName == null ? Collections.emptyList() : Lists.newArrayList(playerByName)); ++ ServerPlayer entityplayer = source.getServer().getPlayerList().getPlayerByName(this.playerName); ++ ++ return (List) (entityplayer == null ? Collections.emptyList() : Lists.newArrayList(new ServerPlayer[]{entityplayer})); + } else if (this.entityUUID != null) { +- for (ServerLevel serverLevel : source.getServer().getAllLevels()) { +- Entity entity = serverLevel.getEntity(this.entityUUID); +- if (entity != null) { +- return Lists.newArrayList(entity); ++ Iterator iterator = source.getServer().getAllLevels().iterator(); ++ ++ Entity entity; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return Collections.emptyList(); + } +- } + +- return Collections.emptyList(); ++ ServerLevel worldserver = (ServerLevel) iterator.next(); ++ ++ entity = worldserver.getEntity(this.entityUUID); ++ } while (entity == null); ++ ++ return Lists.newArrayList(new Entity[]{entity}); + } else { +- Vec3 vec3 = this.position.apply(source.getPosition()); +- Predicate predicate = this.getPredicate(vec3); ++ Vec3 vec3d = (Vec3) this.position.apply(source.getPosition()); ++ Predicate predicate = this.getPredicate(vec3d); ++ + if (this.currentEntity) { +- return (List)(source.getEntity() != null && predicate.test(source.getEntity()) +- ? Lists.newArrayList(source.getEntity()) +- : Collections.emptyList()); ++ return (List) (source.getEntity() != null && predicate.test(source.getEntity()) ? Lists.newArrayList(new Entity[]{source.getEntity()}) : Collections.emptyList()); + } else { + List list = Lists.newArrayList(); ++ + if (this.isWorldLimited()) { +- this.addEntities(list, source.getLevel(), vec3, predicate); ++ this.addEntities(list, source.getLevel(), vec3d, predicate); + } else { +- for (ServerLevel serverLevel1 : source.getServer().getAllLevels()) { +- this.addEntities(list, serverLevel1, vec3, predicate); ++ Iterator iterator1 = source.getServer().getAllLevels().iterator(); ++ ++ while (iterator1.hasNext()) { ++ ServerLevel worldserver1 = (ServerLevel) iterator1.next(); ++ ++ this.addEntities(list, worldserver1, vec3d, predicate); + } + } + +- return this.sortAndLimit(vec3, list); ++ return this.sortAndLimit(vec3d, list); + } + } + } + + private void addEntities(List result, ServerLevel level, Vec3 pos, Predicate predicate) { +- int resultLimit = this.getResultLimit(); +- if (result.size() < resultLimit) { ++ int i = this.getResultLimit(); ++ ++ if (result.size() < i) { + if (this.aabb != null) { +- level.getEntities(this.type, this.aabb.move(pos), predicate, result, resultLimit); ++ level.getEntities(this.type, this.aabb.move(pos), predicate, result, i); + } else { +- level.getEntities(this.type, predicate, result, resultLimit); ++ level.getEntities(this.type, predicate, result, i); + } ++ + } + } + + private int getResultLimit() { +- return this.order == ORDER_ARBITRARY ? this.maxResults : Integer.MAX_VALUE; ++ return this.order == EntitySelector.ORDER_ARBITRARY ? this.maxResults : Integer.MAX_VALUE; + } + + public ServerPlayer findSinglePlayer(CommandSourceStack source) throws CommandSyntaxException { + this.checkPermissions(source); + List list = this.findPlayers(source); ++ + if (list.size() != 1) { + throw EntityArgument.NO_PLAYERS_FOUND.create(); + } else { +- return list.get(0); ++ return (ServerPlayer) list.get(0); + } + } + + public List findPlayers(CommandSourceStack source) throws CommandSyntaxException { + this.checkPermissions(source); ++ ServerPlayer entityplayer; ++ + if (this.playerName != null) { +- ServerPlayer playerByName = source.getServer().getPlayerList().getPlayerByName(this.playerName); +- return (List)(playerByName == null ? Collections.emptyList() : Lists.newArrayList(playerByName)); ++ entityplayer = source.getServer().getPlayerList().getPlayerByName(this.playerName); ++ return (List) (entityplayer == null ? Collections.emptyList() : Lists.newArrayList(new ServerPlayer[]{entityplayer})); + } else if (this.entityUUID != null) { +- ServerPlayer playerByName = source.getServer().getPlayerList().getPlayer(this.entityUUID); +- return (List)(playerByName == null ? Collections.emptyList() : Lists.newArrayList(playerByName)); ++ entityplayer = source.getServer().getPlayerList().getPlayer(this.entityUUID); ++ return (List) (entityplayer == null ? Collections.emptyList() : Lists.newArrayList(new ServerPlayer[]{entityplayer})); + } else { +- Vec3 vec3 = this.position.apply(source.getPosition()); +- Predicate predicate = this.getPredicate(vec3); ++ Vec3 vec3d = (Vec3) this.position.apply(source.getPosition()); ++ Predicate predicate = this.getPredicate(vec3d); ++ + if (this.currentEntity) { +- if (source.getEntity() instanceof ServerPlayer serverPlayer && predicate.test(serverPlayer)) { +- return Lists.newArrayList(serverPlayer); ++ Entity entity = source.getEntity(); ++ ++ if (entity instanceof ServerPlayer) { ++ ServerPlayer entityplayer1 = (ServerPlayer) entity; ++ ++ if (predicate.test(entityplayer1)) { ++ return Lists.newArrayList(new ServerPlayer[]{entityplayer1}); ++ } + } + + return Collections.emptyList(); + } else { +- int resultLimit = this.getResultLimit(); +- List players; ++ int i = this.getResultLimit(); ++ Object object; ++ + if (this.isWorldLimited()) { +- players = source.getLevel().getPlayers(predicate, resultLimit); ++ object = source.getLevel().getPlayers(predicate, i); + } else { +- players = Lists.newArrayList(); ++ object = Lists.newArrayList(); ++ Iterator iterator = source.getServer().getPlayerList().getPlayers().iterator(); + +- for (ServerPlayer serverPlayer1 : source.getServer().getPlayerList().getPlayers()) { +- if (predicate.test(serverPlayer1)) { +- players.add(serverPlayer1); +- if (players.size() >= resultLimit) { +- return players; ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer2 = (ServerPlayer) iterator.next(); ++ ++ if (predicate.test(entityplayer2)) { ++ ((List) object).add(entityplayer2); ++ if (((List) object).size() >= i) { ++ return (List) object; + } + } + } + } + +- return this.sortAndLimit(vec3, players); ++ return this.sortAndLimit(vec3d, (List) object); + } + } + } + + private Predicate getPredicate(Vec3 pos) { + Predicate predicate = this.predicate; ++ + if (this.aabb != null) { +- AABB aABB = this.aabb.move(pos); +- predicate = predicate.and(entity -> aABB.intersects(entity.getBoundingBox())); ++ AABB axisalignedbb = this.aabb.move(pos); ++ ++ predicate = predicate.and((entity) -> { ++ return axisalignedbb.intersects(entity.getBoundingBox()); ++ }); + } + + if (!this.range.isAny()) { +- predicate = predicate.and(entity -> this.range.matchesSqr(entity.distanceToSqr(pos))); ++ predicate = predicate.and((entity) -> { ++ return this.range.matchesSqr(entity.distanceToSqr(pos)); ++ }); + } + + return predicate; diff --git a/patch-remap/mache-vineflower/net/minecraft/commands/arguments/selector/EntitySelectorParser.java.patch b/patch-remap/mache-vineflower/net/minecraft/commands/arguments/selector/EntitySelectorParser.java.patch new file mode 100644 index 0000000000..174e410812 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/commands/arguments/selector/EntitySelectorParser.java.patch @@ -0,0 +1,449 @@ +--- a/net/minecraft/commands/arguments/selector/EntitySelectorParser.java ++++ b/net/minecraft/commands/arguments/selector/EntitySelectorParser.java +@@ -30,6 +30,7 @@ + import net.minecraft.world.phys.Vec3; + + public class EntitySelectorParser { ++ + public static final char SYNTAX_SELECTOR_START = '@'; + private static final char SYNTAX_OPTIONS_START = '['; + private static final char SYNTAX_OPTIONS_END = ']'; +@@ -42,41 +43,39 @@ + private static final char SELECTOR_RANDOM_PLAYERS = 'r'; + private static final char SELECTOR_CURRENT_ENTITY = 's'; + private static final char SELECTOR_ALL_ENTITIES = 'e'; +- public static final SimpleCommandExceptionType ERROR_INVALID_NAME_OR_UUID = new SimpleCommandExceptionType( +- Component.translatable("argument.entity.invalid") +- ); +- public static final DynamicCommandExceptionType ERROR_UNKNOWN_SELECTOR_TYPE = new DynamicCommandExceptionType( +- type -> Component.translatableEscape("argument.entity.selector.unknown", type) +- ); +- public static final SimpleCommandExceptionType ERROR_SELECTORS_NOT_ALLOWED = new SimpleCommandExceptionType( +- Component.translatable("argument.entity.selector.not_allowed") +- ); +- public static final SimpleCommandExceptionType ERROR_MISSING_SELECTOR_TYPE = new SimpleCommandExceptionType( +- Component.translatable("argument.entity.selector.missing") +- ); +- public static final SimpleCommandExceptionType ERROR_EXPECTED_END_OF_OPTIONS = new SimpleCommandExceptionType( +- Component.translatable("argument.entity.options.unterminated") +- ); +- public static final DynamicCommandExceptionType ERROR_EXPECTED_OPTION_VALUE = new DynamicCommandExceptionType( +- value -> Component.translatableEscape("argument.entity.options.valueless", value) +- ); +- public static final BiConsumer> ORDER_NEAREST = (pos, entities) -> entities.sort( +- (entity1, entity2) -> Doubles.compare(entity1.distanceToSqr(pos), entity2.distanceToSqr(pos)) +- ); +- public static final BiConsumer> ORDER_FURTHEST = (pos, entities) -> entities.sort( +- (entity1, entity2) -> Doubles.compare(entity2.distanceToSqr(pos), entity1.distanceToSqr(pos)) +- ); +- public static final BiConsumer> ORDER_RANDOM = (pos, entities) -> Collections.shuffle(entities); +- public static final BiFunction, CompletableFuture> SUGGEST_NOTHING = (builder, consumer) -> builder.buildFuture( +- +- ); ++ public static final SimpleCommandExceptionType ERROR_INVALID_NAME_OR_UUID = new SimpleCommandExceptionType(Component.translatable("argument.entity.invalid")); ++ public static final DynamicCommandExceptionType ERROR_UNKNOWN_SELECTOR_TYPE = new DynamicCommandExceptionType((object) -> { ++ return Component.translatableEscape("argument.entity.selector.unknown", object); ++ }); ++ public static final SimpleCommandExceptionType ERROR_SELECTORS_NOT_ALLOWED = new SimpleCommandExceptionType(Component.translatable("argument.entity.selector.not_allowed")); ++ public static final SimpleCommandExceptionType ERROR_MISSING_SELECTOR_TYPE = new SimpleCommandExceptionType(Component.translatable("argument.entity.selector.missing")); ++ public static final SimpleCommandExceptionType ERROR_EXPECTED_END_OF_OPTIONS = new SimpleCommandExceptionType(Component.translatable("argument.entity.options.unterminated")); ++ public static final DynamicCommandExceptionType ERROR_EXPECTED_OPTION_VALUE = new DynamicCommandExceptionType((object) -> { ++ return Component.translatableEscape("argument.entity.options.valueless", object); ++ }); ++ public static final BiConsumer> ORDER_NEAREST = (vec3d, list) -> { ++ list.sort((entity, entity1) -> { ++ return Doubles.compare(entity.distanceToSqr(vec3d), entity1.distanceToSqr(vec3d)); ++ }); ++ }; ++ public static final BiConsumer> ORDER_FURTHEST = (vec3d, list) -> { ++ list.sort((entity, entity1) -> { ++ return Doubles.compare(entity1.distanceToSqr(vec3d), entity.distanceToSqr(vec3d)); ++ }); ++ }; ++ public static final BiConsumer> ORDER_RANDOM = (vec3d, list) -> { ++ Collections.shuffle(list); ++ }; ++ public static final BiFunction, CompletableFuture> SUGGEST_NOTHING = (suggestionsbuilder, consumer) -> { ++ return suggestionsbuilder.buildFuture(); ++ }; + private final StringReader reader; + private final boolean allowSelectors; + private int maxResults; + private boolean includesEntities; + private boolean worldLimited; +- private MinMaxBounds.Doubles distance = MinMaxBounds.Doubles.ANY; +- private MinMaxBounds.Ints level = MinMaxBounds.Ints.ANY; ++ private MinMaxBounds.Doubles distance; ++ private MinMaxBounds.Ints level; + @Nullable + private Double x; + @Nullable +@@ -89,17 +88,17 @@ + private Double deltaY; + @Nullable + private Double deltaZ; +- private WrappedMinMaxBounds rotX = WrappedMinMaxBounds.ANY; +- private WrappedMinMaxBounds rotY = WrappedMinMaxBounds.ANY; +- private Predicate predicate = entity -> true; +- private BiConsumer> order = EntitySelector.ORDER_ARBITRARY; ++ private WrappedMinMaxBounds rotX; ++ private WrappedMinMaxBounds rotY; ++ private Predicate predicate; ++ private BiConsumer> order; + private boolean currentEntity; + @Nullable + private String playerName; + private int startPosition; + @Nullable + private UUID entityUUID; +- private BiFunction, CompletableFuture> suggestions = SUGGEST_NOTHING; ++ private BiFunction, CompletableFuture> suggestions; + private boolean hasNameEquals; + private boolean hasNameNotEquals; + private boolean isLimited; +@@ -120,58 +119,61 @@ + } + + public EntitySelectorParser(StringReader reader, boolean allowSelectors) { ++ this.distance = MinMaxBounds.Doubles.ANY; ++ this.level = MinMaxBounds.Ints.ANY; ++ this.rotX = WrappedMinMaxBounds.ANY; ++ this.rotY = WrappedMinMaxBounds.ANY; ++ this.predicate = (entity) -> { ++ return true; ++ }; ++ this.order = EntitySelector.ORDER_ARBITRARY; ++ this.suggestions = EntitySelectorParser.SUGGEST_NOTHING; + this.reader = reader; + this.allowSelectors = allowSelectors; + } + + public EntitySelector getSelector() { +- AABB aABB; ++ AABB axisalignedbb; ++ + if (this.deltaX == null && this.deltaY == null && this.deltaZ == null) { + if (this.distance.max().isPresent()) { +- double d = this.distance.max().get(); +- aABB = new AABB(-d, -d, -d, d + 1.0, d + 1.0, d + 1.0); ++ double d0 = (Double) this.distance.max().get(); ++ ++ axisalignedbb = new AABB(-d0, -d0, -d0, d0 + 1.0D, d0 + 1.0D, d0 + 1.0D); + } else { +- aABB = null; ++ axisalignedbb = null; + } + } else { +- aABB = this.createAabb(this.deltaX == null ? 0.0 : this.deltaX, this.deltaY == null ? 0.0 : this.deltaY, this.deltaZ == null ? 0.0 : this.deltaZ); ++ axisalignedbb = this.createAabb(this.deltaX == null ? 0.0D : this.deltaX, this.deltaY == null ? 0.0D : this.deltaY, this.deltaZ == null ? 0.0D : this.deltaZ); + } + +- Function function; ++ Function function; // CraftBukkit - decompile error ++ + if (this.x == null && this.y == null && this.z == null) { +- function = vec -> vec; ++ function = (vec3d) -> { ++ return vec3d; ++ }; + } else { +- function = vec -> new Vec3(this.x == null ? vec.x : this.x, this.y == null ? vec.y : this.y, this.z == null ? vec.z : this.z); ++ function = (vec3d) -> { ++ return new Vec3(this.x == null ? vec3d.x : this.x, this.y == null ? vec3d.y : this.y, this.z == null ? vec3d.z : this.z); ++ }; + } + +- return new EntitySelector( +- this.maxResults, +- this.includesEntities, +- this.worldLimited, +- this.predicate, +- this.distance, +- function, +- aABB, +- this.order, +- this.currentEntity, +- this.playerName, +- this.entityUUID, +- this.type, +- this.usesSelectors +- ); ++ return new EntitySelector(this.maxResults, this.includesEntities, this.worldLimited, this.predicate, this.distance, function, axisalignedbb, this.order, this.currentEntity, this.playerName, this.entityUUID, this.type, this.usesSelectors); + } + +- private AABB createAabb(double sizeX, double sizeY, double sizeZ) { +- boolean flag = sizeX < 0.0; +- boolean flag1 = sizeY < 0.0; +- boolean flag2 = sizeZ < 0.0; +- double d = flag ? sizeX : 0.0; +- double d1 = flag1 ? sizeY : 0.0; +- double d2 = flag2 ? sizeZ : 0.0; +- double d3 = (flag ? 0.0 : sizeX) + 1.0; +- double d4 = (flag1 ? 0.0 : sizeY) + 1.0; +- double d5 = (flag2 ? 0.0 : sizeZ) + 1.0; +- return new AABB(d, d1, d2, d3, d4, d5); ++ private AABB createAabb(double sizeX, double d1, double sizeY) { ++ boolean flag = sizeX < 0.0D; ++ boolean flag1 = d1 < 0.0D; ++ boolean flag2 = sizeY < 0.0D; ++ double d3 = flag ? sizeX : 0.0D; ++ double d4 = flag1 ? d1 : 0.0D; ++ double d5 = flag2 ? sizeY : 0.0D; ++ double d6 = (flag ? 0.0D : sizeX) + 1.0D; ++ double d7 = (flag1 ? 0.0D : d1) + 1.0D; ++ double d8 = (flag2 ? 0.0D : sizeY) + 1.0D; ++ ++ return new AABB(d3, d4, d5, d6, d7, d8); + } + + private void finalizePredicates() { +@@ -184,50 +186,58 @@ + } + + if (!this.level.isAny()) { +- this.predicate = this.predicate.and(entity -> entity instanceof ServerPlayer && this.level.matches(((ServerPlayer)entity).experienceLevel)); ++ this.predicate = this.predicate.and((entity) -> { ++ return !(entity instanceof ServerPlayer) ? false : this.level.matches(((ServerPlayer) entity).experienceLevel); ++ }); + } ++ + } + + private Predicate createRotationPredicate(WrappedMinMaxBounds angleBounds, ToDoubleFunction angleFunction) { +- double d = (double)Mth.wrapDegrees(angleBounds.min() == null ? 0.0F : angleBounds.min()); +- double d1 = (double)Mth.wrapDegrees(angleBounds.max() == null ? 359.0F : angleBounds.max()); +- return entity -> { +- double d3 = Mth.wrapDegrees(angleFunction.applyAsDouble(entity)); +- return d > d1 ? d3 >= d || d3 <= d1 : d3 >= d && d3 <= d1; ++ double d0 = (double) Mth.wrapDegrees(angleBounds.min() == null ? 0.0F : angleBounds.min()); ++ double d1 = (double) Mth.wrapDegrees(angleBounds.max() == null ? 359.0F : angleBounds.max()); ++ ++ return (entity) -> { ++ double d2 = Mth.wrapDegrees(angleFunction.applyAsDouble(entity)); ++ ++ return d0 > d1 ? d2 >= d0 || d2 <= d1 : d2 >= d0 && d2 <= d1; + }; + } + +- protected void parseSelector() throws CommandSyntaxException { +- this.usesSelectors = true; ++ // CraftBukkit start ++ protected void parseSelector(boolean overridePermissions) throws CommandSyntaxException { ++ this.usesSelectors = !overridePermissions; ++ // CraftBukkit end + this.suggestions = this::suggestSelector; + if (!this.reader.canRead()) { +- throw ERROR_MISSING_SELECTOR_TYPE.createWithContext(this.reader); ++ throw EntitySelectorParser.ERROR_MISSING_SELECTOR_TYPE.createWithContext(this.reader); + } else { +- int cursor = this.reader.getCursor(); +- char c = this.reader.read(); +- if (c == 'p') { ++ int i = this.reader.getCursor(); ++ char c0 = this.reader.read(); ++ ++ if (c0 == 'p') { + this.maxResults = 1; + this.includesEntities = false; +- this.order = ORDER_NEAREST; ++ this.order = EntitySelectorParser.ORDER_NEAREST; + this.limitToType(EntityType.PLAYER); +- } else if (c == 'a') { ++ } else if (c0 == 'a') { + this.maxResults = Integer.MAX_VALUE; + this.includesEntities = false; + this.order = EntitySelector.ORDER_ARBITRARY; + this.limitToType(EntityType.PLAYER); +- } else if (c == 'r') { ++ } else if (c0 == 'r') { + this.maxResults = 1; + this.includesEntities = false; +- this.order = ORDER_RANDOM; ++ this.order = EntitySelectorParser.ORDER_RANDOM; + this.limitToType(EntityType.PLAYER); +- } else if (c == 's') { ++ } else if (c0 == 's') { + this.maxResults = 1; + this.includesEntities = true; + this.currentEntity = true; + } else { +- if (c != 'e') { +- this.reader.setCursor(cursor); +- throw ERROR_UNKNOWN_SELECTOR_TYPE.createWithContext(this.reader, "@" + c); ++ if (c0 != 'e') { ++ this.reader.setCursor(i); ++ throw EntitySelectorParser.ERROR_UNKNOWN_SELECTOR_TYPE.createWithContext(this.reader, "@" + String.valueOf(c0)); + } + + this.maxResults = Integer.MAX_VALUE; +@@ -242,6 +252,7 @@ + this.suggestions = this::suggestOptionsKeyOrClose; + this.parseOptions(); + } ++ + } + } + +@@ -250,20 +261,20 @@ + this.suggestions = this::suggestName; + } + +- int cursor = this.reader.getCursor(); +- String string = this.reader.readString(); ++ int i = this.reader.getCursor(); ++ String s = this.reader.readString(); + + try { +- this.entityUUID = UUID.fromString(string); ++ this.entityUUID = UUID.fromString(s); + this.includesEntities = true; +- } catch (IllegalArgumentException var4) { +- if (string.isEmpty() || string.length() > 16) { +- this.reader.setCursor(cursor); +- throw ERROR_INVALID_NAME_OR_UUID.createWithContext(this.reader); ++ } catch (IllegalArgumentException illegalargumentexception) { ++ if (s.isEmpty() || s.length() > 16) { ++ this.reader.setCursor(i); ++ throw EntitySelectorParser.ERROR_INVALID_NAME_OR_UUID.createWithContext(this.reader); + } + + this.includesEntities = false; +- this.playerName = string; ++ this.playerName = s; + } + + this.maxResults = 1; +@@ -273,41 +284,47 @@ + this.suggestions = this::suggestOptionsKey; + this.reader.skipWhitespace(); + +- while (this.reader.canRead() && this.reader.peek() != ']') { +- this.reader.skipWhitespace(); +- int cursor = this.reader.getCursor(); +- String string = this.reader.readString(); +- EntitySelectorOptions.Modifier modifier = EntitySelectorOptions.get(this, string, cursor); +- this.reader.skipWhitespace(); +- if (!this.reader.canRead() || this.reader.peek() != '=') { +- this.reader.setCursor(cursor); +- throw ERROR_EXPECTED_OPTION_VALUE.createWithContext(this.reader, string); +- } ++ while (true) { ++ if (this.reader.canRead() && this.reader.peek() != ']') { ++ this.reader.skipWhitespace(); ++ int i = this.reader.getCursor(); ++ String s = this.reader.readString(); ++ EntitySelectorOptions.Modifier playerselector_a = EntitySelectorOptions.get(this, s, i); + +- this.reader.skip(); +- this.reader.skipWhitespace(); +- this.suggestions = SUGGEST_NOTHING; +- modifier.handle(this); +- this.reader.skipWhitespace(); +- this.suggestions = this::suggestOptionsNextOrClose; +- if (this.reader.canRead()) { +- if (this.reader.peek() != ',') { +- if (this.reader.peek() != ']') { +- throw ERROR_EXPECTED_END_OF_OPTIONS.createWithContext(this.reader); +- } +- break; ++ this.reader.skipWhitespace(); ++ if (!this.reader.canRead() || this.reader.peek() != '=') { ++ this.reader.setCursor(i); ++ throw EntitySelectorParser.ERROR_EXPECTED_OPTION_VALUE.createWithContext(this.reader, s); + } + + this.reader.skip(); +- this.suggestions = this::suggestOptionsKey; ++ this.reader.skipWhitespace(); ++ this.suggestions = EntitySelectorParser.SUGGEST_NOTHING; ++ playerselector_a.handle(this); ++ this.reader.skipWhitespace(); ++ this.suggestions = this::suggestOptionsNextOrClose; ++ if (!this.reader.canRead()) { ++ continue; ++ } ++ ++ if (this.reader.peek() == ',') { ++ this.reader.skip(); ++ this.suggestions = this::suggestOptionsKey; ++ continue; ++ } ++ ++ if (this.reader.peek() != ']') { ++ throw EntitySelectorParser.ERROR_EXPECTED_END_OF_OPTIONS.createWithContext(this.reader); ++ } + } +- } + +- if (this.reader.canRead()) { +- this.reader.skip(); +- this.suggestions = SUGGEST_NOTHING; +- } else { +- throw ERROR_EXPECTED_END_OF_OPTIONS.createWithContext(this.reader); ++ if (this.reader.canRead()) { ++ this.reader.skip(); ++ this.suggestions = EntitySelectorParser.SUGGEST_NOTHING; ++ return; ++ } ++ ++ throw EntitySelectorParser.ERROR_EXPECTED_END_OF_OPTIONS.createWithContext(this.reader); + } + } + +@@ -448,15 +465,21 @@ + } + + public EntitySelector parse() throws CommandSyntaxException { ++ // CraftBukkit start ++ return parse(false); ++ } ++ ++ public EntitySelector parse(boolean overridePermissions) throws CommandSyntaxException { ++ // CraftBukkit end + this.startPosition = this.reader.getCursor(); + this.suggestions = this::suggestNameOrSelector; + if (this.reader.canRead() && this.reader.peek() == '@') { + if (!this.allowSelectors) { +- throw ERROR_SELECTORS_NOT_ALLOWED.createWithContext(this.reader); ++ throw EntitySelectorParser.ERROR_SELECTORS_NOT_ALLOWED.createWithContext(this.reader); + } + + this.reader.skip(); +- this.parseSelector(); ++ this.parseSelector(overridePermissions); // CraftBukkit + } else { + this.parseNameOrUUID(); + } +@@ -483,15 +506,17 @@ + } + + private CompletableFuture suggestName(SuggestionsBuilder builder, Consumer consumer) { +- SuggestionsBuilder suggestionsBuilder = builder.createOffset(this.startPosition); +- consumer.accept(suggestionsBuilder); +- return builder.add(suggestionsBuilder).buildFuture(); ++ SuggestionsBuilder suggestionsbuilder1 = builder.createOffset(this.startPosition); ++ ++ consumer.accept(suggestionsbuilder1); ++ return builder.add(suggestionsbuilder1).buildFuture(); + } + + private CompletableFuture suggestSelector(SuggestionsBuilder builder, Consumer consumer) { +- SuggestionsBuilder suggestionsBuilder = builder.createOffset(builder.getStart() - 1); +- fillSelectorSuggestions(suggestionsBuilder); +- builder.add(suggestionsBuilder); ++ SuggestionsBuilder suggestionsbuilder1 = builder.createOffset(builder.getStart() - 1); ++ ++ fillSelectorSuggestions(suggestionsbuilder1); ++ builder.add(suggestionsbuilder1); + return builder.buildFuture(); + } + +@@ -531,7 +556,7 @@ + } + + public CompletableFuture fillSuggestions(SuggestionsBuilder builder, Consumer consumer) { +- return this.suggestions.apply(builder.createOffset(this.reader.getCursor()), consumer); ++ return (CompletableFuture) this.suggestions.apply(builder.createOffset(this.reader.getCursor()), consumer); + } + + public boolean hasNameEquals() { diff --git a/patch-remap/mache-vineflower/net/minecraft/core/cauldron/CauldronInteraction.java.patch b/patch-remap/mache-vineflower/net/minecraft/core/cauldron/CauldronInteraction.java.patch new file mode 100644 index 0000000000..8b2d7b6f05 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/core/cauldron/CauldronInteraction.java.patch @@ -0,0 +1,574 @@ +--- a/net/minecraft/core/cauldron/CauldronInteraction.java ++++ b/net/minecraft/core/cauldron/CauldronInteraction.java +@@ -4,6 +4,8 @@ + import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; + import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + import java.util.Map; ++import java.util.Objects; ++import java.util.function.Function; + import java.util.function.Predicate; + import net.minecraft.core.BlockPos; + import net.minecraft.sounds.SoundEvent; +@@ -11,8 +13,9 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; + import net.minecraft.util.ExtraCodecs; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.DyeableLeatherItem; + import net.minecraft.world.item.Item; +@@ -27,286 +30,330 @@ + import net.minecraft.world.level.block.LayeredCauldronBlock; + import net.minecraft.world.level.block.ShulkerBoxBlock; + import net.minecraft.world.level.block.entity.BannerBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.event.block.CauldronLevelChangeEvent; ++// CraftBukkit end ++ + public interface CauldronInteraction { +- Map INTERACTIONS = new Object2ObjectArrayMap<>(); +- Codec CODEC = ExtraCodecs.stringResolverCodec(CauldronInteraction.InteractionMap::name, INTERACTIONS::get); +- CauldronInteraction.InteractionMap EMPTY = newInteractionMap("empty"); +- CauldronInteraction.InteractionMap WATER = newInteractionMap("water"); +- CauldronInteraction.InteractionMap LAVA = newInteractionMap("lava"); +- CauldronInteraction.InteractionMap POWDER_SNOW = newInteractionMap("powder_snow"); +- CauldronInteraction FILL_WATER = (blockState, level, blockPos, player, hand, stack) -> emptyBucket( +- level, +- blockPos, +- player, +- hand, +- stack, +- Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, Integer.valueOf(3)), +- SoundEvents.BUCKET_EMPTY +- ); +- CauldronInteraction FILL_LAVA = (blockState, level, blockPos, player, hand, stack) -> emptyBucket( +- level, blockPos, player, hand, stack, Blocks.LAVA_CAULDRON.defaultBlockState(), SoundEvents.BUCKET_EMPTY_LAVA +- ); +- CauldronInteraction FILL_POWDER_SNOW = (blockState, level, blockPos, player, hand, stack) -> emptyBucket( +- level, +- blockPos, +- player, +- hand, +- stack, +- Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, Integer.valueOf(3)), +- SoundEvents.BUCKET_EMPTY_POWDER_SNOW +- ); +- CauldronInteraction SHULKER_BOX = (blockState, level, blockPos, player, hand, stack) -> { +- Block block = Block.byItem(stack.getItem()); +- if (!(block instanceof ShulkerBoxBlock)) { +- return InteractionResult.PASS; +- } else { +- if (!level.isClientSide) { +- ItemStack itemStack = new ItemStack(Blocks.SHULKER_BOX); +- if (stack.hasTag()) { +- itemStack.setTag(stack.getTag().copy()); +- } + +- player.setItemInHand(hand, itemStack); +- player.awardStat(Stats.CLEAN_SHULKER_BOX); +- LayeredCauldronBlock.lowerFillLevel(blockState, level, blockPos); +- } ++ Map INTERACTIONS = new Object2ObjectArrayMap(); ++ // CraftBukkit start - decompile error ++ /* ++ Codec CODEC; ++ CauldronInteraction.a EMPTY; ++ CauldronInteraction.a WATER; ++ CauldronInteraction.a LAVA; ++ CauldronInteraction.a POWDER_SNOW; ++ CauldronInteraction FILL_WATER; ++ CauldronInteraction FILL_LAVA; ++ CauldronInteraction FILL_POWDER_SNOW; ++ CauldronInteraction SHULKER_BOX; ++ CauldronInteraction BANNER; ++ CauldronInteraction DYED_ITEM; ++ */ ++ // CraftBukkit end + +- return InteractionResult.sidedSuccess(level.isClientSide); +- } +- }; +- CauldronInteraction BANNER = (blockState, level, blockPos, player, hand, stack) -> { +- if (BannerBlockEntity.getPatternCount(stack) <= 0) { +- return InteractionResult.PASS; +- } else { +- if (!level.isClientSide) { +- ItemStack itemStack = stack.copyWithCount(1); +- BannerBlockEntity.removeLastPattern(itemStack); +- if (!player.getAbilities().instabuild) { +- stack.shrink(1); +- } ++ static CauldronInteraction.a newInteractionMap(String s) { ++ Object2ObjectOpenHashMap object2objectopenhashmap = new Object2ObjectOpenHashMap(); + +- if (stack.isEmpty()) { +- player.setItemInHand(hand, itemStack); +- } else if (player.getInventory().add(itemStack)) { +- player.inventoryMenu.sendAllDataToRemote(); +- } else { +- player.drop(itemStack, false); +- } +- +- player.awardStat(Stats.CLEAN_BANNER); +- LayeredCauldronBlock.lowerFillLevel(blockState, level, blockPos); +- } +- +- return InteractionResult.sidedSuccess(level.isClientSide); +- } +- }; +- CauldronInteraction DYED_ITEM = (blockState, level, blockPos, player, hand, stack) -> { +- if (!(stack.getItem() instanceof DyeableLeatherItem dyeableLeatherItem)) { ++ object2objectopenhashmap.defaultReturnValue((iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { + return InteractionResult.PASS; +- } else if (!dyeableLeatherItem.hasCustomColor(stack)) { +- return InteractionResult.PASS; +- } else { +- if (!level.isClientSide) { +- dyeableLeatherItem.clearColor(stack); +- player.awardStat(Stats.CLEAN_ARMOR); +- LayeredCauldronBlock.lowerFillLevel(blockState, level, blockPos); +- } ++ }); ++ CauldronInteraction.a cauldroninteraction_a = new CauldronInteraction.a(s, object2objectopenhashmap); + +- return InteractionResult.sidedSuccess(level.isClientSide); +- } +- }; +- +- static CauldronInteraction.InteractionMap newInteractionMap(String string) { +- Object2ObjectOpenHashMap map = new Object2ObjectOpenHashMap<>(); +- map.defaultReturnValue((blockState, level, blockPos, player, hand, stack) -> InteractionResult.PASS); +- CauldronInteraction.InteractionMap interactionMap = new CauldronInteraction.InteractionMap(string, map); +- INTERACTIONS.put(string, interactionMap); +- return interactionMap; ++ CauldronInteraction.INTERACTIONS.put(s, cauldroninteraction_a); ++ return cauldroninteraction_a; + } + +- InteractionResult interact(BlockState blockState, Level level, BlockPos blockPos, Player player, InteractionHand hand, ItemStack stack); ++ InteractionResult interact(IBlockData blockState, Level level, BlockPos blockPos, Player player, EnumHand hand, ItemStack stack); + + static void bootStrap() { +- Map map = EMPTY.map(); ++ Map map = CauldronInteraction.EMPTY.map(); ++ + addDefaultInteractions(map); +- map.put(Items.POTION, (blockState, level, blockPos, player, hand, stack) -> { +- if (PotionUtils.getPotion(stack) != Potions.WATER) { ++ map.put(Items.POTION, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ if (PotionUtils.getPotion(itemstack) != Potions.WATER) { + return InteractionResult.PASS; + } else { +- if (!level.isClientSide) { +- Item item = stack.getItem(); +- player.setItemInHand(hand, ItemUtils.createFilledResult(stack, player, new ItemStack(Items.GLASS_BOTTLE))); +- player.awardStat(Stats.USE_CAULDRON); +- player.awardStat(Stats.ITEM_USED.get(item)); +- level.setBlockAndUpdate(blockPos, Blocks.WATER_CAULDRON.defaultBlockState()); +- level.playSound(null, blockPos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent(null, GameEvent.FLUID_PLACE, blockPos); ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.changeLevel(iblockdata, world, blockposition, Blocks.WATER_CAULDRON.defaultBlockState(), entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_EMPTY)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ Item item = itemstack.getItem(); ++ ++ entityhuman.setItemInHand(enumhand, ItemUtils.createFilledResult(itemstack, entityhuman, new ItemStack(Items.GLASS_BOTTLE))); ++ entityhuman.awardStat(Stats.USE_CAULDRON); ++ entityhuman.awardStat(Stats.ITEM_USED.get(item)); ++ // world.setBlockAndUpdate(blockposition, Blocks.WATER_CAULDRON.defaultBlockState()); // CraftBukkit ++ world.playSound((Player) null, blockposition, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockposition); + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } + }); +- Map map1 = WATER.map(); ++ Map map1 = CauldronInteraction.WATER.map(); ++ + addDefaultInteractions(map1); +- map1.put( +- Items.BUCKET, +- (blockState, level, blockPos, player, hand, stack) -> fillBucket( +- blockState, +- level, +- blockPos, +- player, +- hand, +- stack, +- new ItemStack(Items.WATER_BUCKET), +- blockState1 -> blockState1.getValue(LayeredCauldronBlock.LEVEL) == 3, +- SoundEvents.BUCKET_FILL +- ) +- ); +- map1.put(Items.GLASS_BOTTLE, (blockState, level, blockPos, player, hand, stack) -> { +- if (!level.isClientSide) { +- Item item = stack.getItem(); +- player.setItemInHand(hand, ItemUtils.createFilledResult(stack, player, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER))); +- player.awardStat(Stats.USE_CAULDRON); +- player.awardStat(Stats.ITEM_USED.get(item)); +- LayeredCauldronBlock.lowerFillLevel(blockState, level, blockPos); +- level.playSound(null, blockPos, SoundEvents.BOTTLE_FILL, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent(null, GameEvent.FLUID_PICKUP, blockPos); ++ map1.put(Items.BUCKET, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ return fillBucket(iblockdata, world, blockposition, entityhuman, enumhand, itemstack, new ItemStack(Items.WATER_BUCKET), (iblockdata1) -> { ++ return (Integer) iblockdata1.getValue(LayeredCauldronBlock.LEVEL) == 3; ++ }, SoundEvents.BUCKET_FILL); ++ }); ++ map1.put(Items.GLASS_BOTTLE, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_FILL)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ Item item = itemstack.getItem(); ++ ++ entityhuman.setItemInHand(enumhand, ItemUtils.createFilledResult(itemstack, entityhuman, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER))); ++ entityhuman.awardStat(Stats.USE_CAULDRON); ++ entityhuman.awardStat(Stats.ITEM_USED.get(item)); ++ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit ++ world.playSound((Player) null, blockposition, SoundEvents.BOTTLE_FILL, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockposition); + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + }); +- map1.put(Items.POTION, (blockState, level, blockPos, player, hand, stack) -> { +- if (blockState.getValue(LayeredCauldronBlock.LEVEL) != 3 && PotionUtils.getPotion(stack) == Potions.WATER) { +- if (!level.isClientSide) { +- player.setItemInHand(hand, ItemUtils.createFilledResult(stack, player, new ItemStack(Items.GLASS_BOTTLE))); +- player.awardStat(Stats.USE_CAULDRON); +- player.awardStat(Stats.ITEM_USED.get(stack.getItem())); +- level.setBlockAndUpdate(blockPos, blockState.cycle(LayeredCauldronBlock.LEVEL)); +- level.playSound(null, blockPos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent(null, GameEvent.FLUID_PLACE, blockPos); ++ map1.put(Items.POTION, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ if ((Integer) iblockdata.getValue(LayeredCauldronBlock.LEVEL) != 3 && PotionUtils.getPotion(itemstack) == Potions.WATER) { ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.changeLevel(iblockdata, world, blockposition, iblockdata.cycle(LayeredCauldronBlock.LEVEL), entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_EMPTY)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ entityhuman.setItemInHand(enumhand, ItemUtils.createFilledResult(itemstack, entityhuman, new ItemStack(Items.GLASS_BOTTLE))); ++ entityhuman.awardStat(Stats.USE_CAULDRON); ++ entityhuman.awardStat(Stats.ITEM_USED.get(itemstack.getItem())); ++ // world.setBlockAndUpdate(blockposition, (IBlockData) iblockdata.cycle(LayeredCauldronBlock.LEVEL)); // CraftBukkit ++ world.playSound((Player) null, blockposition, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockposition); + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } else { + return InteractionResult.PASS; + } + }); +- map1.put(Items.LEATHER_BOOTS, DYED_ITEM); +- map1.put(Items.LEATHER_LEGGINGS, DYED_ITEM); +- map1.put(Items.LEATHER_CHESTPLATE, DYED_ITEM); +- map1.put(Items.LEATHER_HELMET, DYED_ITEM); +- map1.put(Items.LEATHER_HORSE_ARMOR, DYED_ITEM); +- map1.put(Items.WHITE_BANNER, BANNER); +- map1.put(Items.GRAY_BANNER, BANNER); +- map1.put(Items.BLACK_BANNER, BANNER); +- map1.put(Items.BLUE_BANNER, BANNER); +- map1.put(Items.BROWN_BANNER, BANNER); +- map1.put(Items.CYAN_BANNER, BANNER); +- map1.put(Items.GREEN_BANNER, BANNER); +- map1.put(Items.LIGHT_BLUE_BANNER, BANNER); +- map1.put(Items.LIGHT_GRAY_BANNER, BANNER); +- map1.put(Items.LIME_BANNER, BANNER); +- map1.put(Items.MAGENTA_BANNER, BANNER); +- map1.put(Items.ORANGE_BANNER, BANNER); +- map1.put(Items.PINK_BANNER, BANNER); +- map1.put(Items.PURPLE_BANNER, BANNER); +- map1.put(Items.RED_BANNER, BANNER); +- map1.put(Items.YELLOW_BANNER, BANNER); +- map1.put(Items.WHITE_SHULKER_BOX, SHULKER_BOX); +- map1.put(Items.GRAY_SHULKER_BOX, SHULKER_BOX); +- map1.put(Items.BLACK_SHULKER_BOX, SHULKER_BOX); +- map1.put(Items.BLUE_SHULKER_BOX, SHULKER_BOX); +- map1.put(Items.BROWN_SHULKER_BOX, SHULKER_BOX); +- map1.put(Items.CYAN_SHULKER_BOX, SHULKER_BOX); +- map1.put(Items.GREEN_SHULKER_BOX, SHULKER_BOX); +- map1.put(Items.LIGHT_BLUE_SHULKER_BOX, SHULKER_BOX); +- map1.put(Items.LIGHT_GRAY_SHULKER_BOX, SHULKER_BOX); +- map1.put(Items.LIME_SHULKER_BOX, SHULKER_BOX); +- map1.put(Items.MAGENTA_SHULKER_BOX, SHULKER_BOX); +- map1.put(Items.ORANGE_SHULKER_BOX, SHULKER_BOX); +- map1.put(Items.PINK_SHULKER_BOX, SHULKER_BOX); +- map1.put(Items.PURPLE_SHULKER_BOX, SHULKER_BOX); +- map1.put(Items.RED_SHULKER_BOX, SHULKER_BOX); +- map1.put(Items.YELLOW_SHULKER_BOX, SHULKER_BOX); +- Map map2 = LAVA.map(); +- map2.put( +- Items.BUCKET, +- (blockState, level, blockPos, player, hand, stack) -> fillBucket( +- blockState, level, blockPos, player, hand, stack, new ItemStack(Items.LAVA_BUCKET), blockState1 -> true, SoundEvents.BUCKET_FILL_LAVA +- ) +- ); ++ map1.put(Items.LEATHER_BOOTS, CauldronInteraction.DYED_ITEM); ++ map1.put(Items.LEATHER_LEGGINGS, CauldronInteraction.DYED_ITEM); ++ map1.put(Items.LEATHER_CHESTPLATE, CauldronInteraction.DYED_ITEM); ++ map1.put(Items.LEATHER_HELMET, CauldronInteraction.DYED_ITEM); ++ map1.put(Items.LEATHER_HORSE_ARMOR, CauldronInteraction.DYED_ITEM); ++ map1.put(Items.WHITE_BANNER, CauldronInteraction.BANNER); ++ map1.put(Items.GRAY_BANNER, CauldronInteraction.BANNER); ++ map1.put(Items.BLACK_BANNER, CauldronInteraction.BANNER); ++ map1.put(Items.BLUE_BANNER, CauldronInteraction.BANNER); ++ map1.put(Items.BROWN_BANNER, CauldronInteraction.BANNER); ++ map1.put(Items.CYAN_BANNER, CauldronInteraction.BANNER); ++ map1.put(Items.GREEN_BANNER, CauldronInteraction.BANNER); ++ map1.put(Items.LIGHT_BLUE_BANNER, CauldronInteraction.BANNER); ++ map1.put(Items.LIGHT_GRAY_BANNER, CauldronInteraction.BANNER); ++ map1.put(Items.LIME_BANNER, CauldronInteraction.BANNER); ++ map1.put(Items.MAGENTA_BANNER, CauldronInteraction.BANNER); ++ map1.put(Items.ORANGE_BANNER, CauldronInteraction.BANNER); ++ map1.put(Items.PINK_BANNER, CauldronInteraction.BANNER); ++ map1.put(Items.PURPLE_BANNER, CauldronInteraction.BANNER); ++ map1.put(Items.RED_BANNER, CauldronInteraction.BANNER); ++ map1.put(Items.YELLOW_BANNER, CauldronInteraction.BANNER); ++ map1.put(Items.WHITE_SHULKER_BOX, CauldronInteraction.SHULKER_BOX); ++ map1.put(Items.GRAY_SHULKER_BOX, CauldronInteraction.SHULKER_BOX); ++ map1.put(Items.BLACK_SHULKER_BOX, CauldronInteraction.SHULKER_BOX); ++ map1.put(Items.BLUE_SHULKER_BOX, CauldronInteraction.SHULKER_BOX); ++ map1.put(Items.BROWN_SHULKER_BOX, CauldronInteraction.SHULKER_BOX); ++ map1.put(Items.CYAN_SHULKER_BOX, CauldronInteraction.SHULKER_BOX); ++ map1.put(Items.GREEN_SHULKER_BOX, CauldronInteraction.SHULKER_BOX); ++ map1.put(Items.LIGHT_BLUE_SHULKER_BOX, CauldronInteraction.SHULKER_BOX); ++ map1.put(Items.LIGHT_GRAY_SHULKER_BOX, CauldronInteraction.SHULKER_BOX); ++ map1.put(Items.LIME_SHULKER_BOX, CauldronInteraction.SHULKER_BOX); ++ map1.put(Items.MAGENTA_SHULKER_BOX, CauldronInteraction.SHULKER_BOX); ++ map1.put(Items.ORANGE_SHULKER_BOX, CauldronInteraction.SHULKER_BOX); ++ map1.put(Items.PINK_SHULKER_BOX, CauldronInteraction.SHULKER_BOX); ++ map1.put(Items.PURPLE_SHULKER_BOX, CauldronInteraction.SHULKER_BOX); ++ map1.put(Items.RED_SHULKER_BOX, CauldronInteraction.SHULKER_BOX); ++ map1.put(Items.YELLOW_SHULKER_BOX, CauldronInteraction.SHULKER_BOX); ++ Map map2 = CauldronInteraction.LAVA.map(); ++ ++ map2.put(Items.BUCKET, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ return fillBucket(iblockdata, world, blockposition, entityhuman, enumhand, itemstack, new ItemStack(Items.LAVA_BUCKET), (iblockdata1) -> { ++ return true; ++ }, SoundEvents.BUCKET_FILL_LAVA); ++ }); + addDefaultInteractions(map2); +- Map map3 = POWDER_SNOW.map(); +- map3.put( +- Items.BUCKET, +- (blockState, level, blockPos, player, hand, stack) -> fillBucket( +- blockState, +- level, +- blockPos, +- player, +- hand, +- stack, +- new ItemStack(Items.POWDER_SNOW_BUCKET), +- blockState1 -> blockState1.getValue(LayeredCauldronBlock.LEVEL) == 3, +- SoundEvents.BUCKET_FILL_POWDER_SNOW +- ) +- ); ++ Map map3 = CauldronInteraction.POWDER_SNOW.map(); ++ ++ map3.put(Items.BUCKET, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ return fillBucket(iblockdata, world, blockposition, entityhuman, enumhand, itemstack, new ItemStack(Items.POWDER_SNOW_BUCKET), (iblockdata1) -> { ++ return (Integer) iblockdata1.getValue(LayeredCauldronBlock.LEVEL) == 3; ++ }, SoundEvents.BUCKET_FILL_POWDER_SNOW); ++ }); + addDefaultInteractions(map3); + } + + static void addDefaultInteractions(Map interactionsMap) { +- interactionsMap.put(Items.LAVA_BUCKET, FILL_LAVA); +- interactionsMap.put(Items.WATER_BUCKET, FILL_WATER); +- interactionsMap.put(Items.POWDER_SNOW_BUCKET, FILL_POWDER_SNOW); ++ interactionsMap.put(Items.LAVA_BUCKET, CauldronInteraction.FILL_LAVA); ++ interactionsMap.put(Items.WATER_BUCKET, CauldronInteraction.FILL_WATER); ++ interactionsMap.put(Items.POWDER_SNOW_BUCKET, CauldronInteraction.FILL_POWDER_SNOW); + } + +- static InteractionResult fillBucket( +- BlockState blockState, +- Level level, +- BlockPos pos, +- Player player, +- InteractionHand hand, +- ItemStack emptyStack, +- ItemStack filledStack, +- Predicate statePredicate, +- SoundEvent fillSound +- ) { ++ static InteractionResult fillBucket(IBlockData blockState, Level level, BlockPos pos, Player player, EnumHand hand, ItemStack emptyStack, ItemStack filledStack, Predicate statePredicate, SoundEvent fillSound) { + if (!statePredicate.test(blockState)) { + return InteractionResult.PASS; + } else { + if (!level.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.changeLevel(blockState, level, pos, Blocks.CAULDRON.defaultBlockState(), player, CauldronLevelChangeEvent.ChangeReason.BUCKET_FILL)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + Item item = emptyStack.getItem(); ++ + player.setItemInHand(hand, ItemUtils.createFilledResult(emptyStack, player, filledStack)); + player.awardStat(Stats.USE_CAULDRON); + player.awardStat(Stats.ITEM_USED.get(item)); +- level.setBlockAndUpdate(pos, Blocks.CAULDRON.defaultBlockState()); +- level.playSound(null, pos, fillSound, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent(null, GameEvent.FLUID_PICKUP, pos); ++ // world.setBlockAndUpdate(blockposition, Blocks.CAULDRON.defaultBlockState()); // CraftBukkit ++ level.playSound((Player) null, pos, fillSound, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, pos); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + } + } + +- static InteractionResult emptyBucket( +- Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack filledStack, BlockState state, SoundEvent emptySound +- ) { ++ static InteractionResult emptyBucket(Level level, BlockPos pos, Player player, EnumHand hand, ItemStack filledStack, IBlockData state, SoundEvent emptySound) { + if (!level.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.changeLevel(state, level, pos, state, player, CauldronLevelChangeEvent.ChangeReason.BUCKET_EMPTY)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + Item item = filledStack.getItem(); ++ + player.setItemInHand(hand, ItemUtils.createFilledResult(filledStack, player, new ItemStack(Items.BUCKET))); + player.awardStat(Stats.FILL_CAULDRON); + player.awardStat(Stats.ITEM_USED.get(item)); +- level.setBlockAndUpdate(pos, state); +- level.playSound(null, pos, emptySound, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent(null, GameEvent.FLUID_PLACE, pos); ++ // world.setBlockAndUpdate(blockposition, iblockdata); // CraftBukkit ++ level.playSound((Player) null, pos, emptySound, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.gameEvent((Entity) null, GameEvent.FLUID_PLACE, pos); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + } + +- public static record InteractionMap(String name, Map map) { ++ // CraftBukkit start - decompile errors ++ // static { ++ Codec CODEC = ExtraCodecs.stringResolverCodec(CauldronInteraction.a::name, CauldronInteraction.INTERACTIONS::get); ++ CauldronInteraction.a EMPTY = newInteractionMap("empty"); ++ CauldronInteraction.a WATER = newInteractionMap("water"); ++ CauldronInteraction.a LAVA = newInteractionMap("lava"); ++ CauldronInteraction.a POWDER_SNOW = newInteractionMap("powder_snow"); ++ CauldronInteraction FILL_WATER = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ return emptyBucket(world, blockposition, entityhuman, enumhand, itemstack, (IBlockData) Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY); ++ }; ++ CauldronInteraction FILL_LAVA = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ return emptyBucket(world, blockposition, entityhuman, enumhand, itemstack, Blocks.LAVA_CAULDRON.defaultBlockState(), SoundEvents.BUCKET_EMPTY_LAVA); ++ }; ++ CauldronInteraction FILL_POWDER_SNOW = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ return emptyBucket(world, blockposition, entityhuman, enumhand, itemstack, (IBlockData) Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY_POWDER_SNOW); ++ }; ++ CauldronInteraction SHULKER_BOX = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ // CraftBukkit end ++ Block block = Block.byItem(itemstack.getItem()); ++ ++ if (!(block instanceof ShulkerBoxBlock)) { ++ return InteractionResult.PASS; ++ } else { ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.SHULKER_WASH)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ ItemStack itemstack1 = new ItemStack(Blocks.SHULKER_BOX); ++ ++ if (itemstack.hasTag()) { ++ itemstack1.setTag(itemstack.getTag().copy()); ++ } ++ ++ entityhuman.setItemInHand(enumhand, itemstack1); ++ entityhuman.awardStat(Stats.CLEAN_SHULKER_BOX); ++ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit ++ } ++ ++ return InteractionResult.sidedSuccess(world.isClientSide); ++ } ++ }; ++ CauldronInteraction BANNER = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { // CraftBukkit - decompile error ++ if (BannerBlockEntity.getPatternCount(itemstack) <= 0) { ++ return InteractionResult.PASS; ++ } else { ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.BANNER_WASH)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ ItemStack itemstack1 = itemstack.copyWithCount(1); ++ ++ BannerBlockEntity.removeLastPattern(itemstack1); ++ if (!entityhuman.getAbilities().instabuild) { ++ itemstack.shrink(1); ++ } ++ ++ if (itemstack.isEmpty()) { ++ entityhuman.setItemInHand(enumhand, itemstack1); ++ } else if (entityhuman.getInventory().add(itemstack1)) { ++ entityhuman.inventoryMenu.sendAllDataToRemote(); ++ } else { ++ entityhuman.drop(itemstack1, false); ++ } ++ ++ entityhuman.awardStat(Stats.CLEAN_BANNER); ++ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit ++ } ++ ++ return InteractionResult.sidedSuccess(world.isClientSide); ++ } ++ }; ++ CauldronInteraction DYED_ITEM = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { // CraftBukkit - decompile error ++ Item item = itemstack.getItem(); ++ ++ if (!(item instanceof DyeableLeatherItem)) { ++ return InteractionResult.PASS; ++ } else { ++ DyeableLeatherItem idyeable = (DyeableLeatherItem) item; ++ ++ if (!idyeable.hasCustomColor(itemstack)) { ++ return InteractionResult.PASS; ++ } else { ++ if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.ARMOR_WASH)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ idyeable.clearColor(itemstack); ++ entityhuman.awardStat(Stats.CLEAN_ARMOR); ++ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit ++ } ++ ++ return InteractionResult.sidedSuccess(world.isClientSide); ++ } ++ } ++ }; ++ // } // CraftBukkit - decompile error ++ ++ public static record a(String name, Map map) { ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java.patch b/patch-remap/mache-vineflower/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java.patch new file mode 100644 index 0000000000..962fbb6244 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java.patch @@ -0,0 +1,90 @@ +--- a/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java ++++ b/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java +@@ -1,33 +1,71 @@ + package net.minecraft.core.dispenser; + + import net.minecraft.core.Direction; +-import net.minecraft.core.Position; +-import net.minecraft.world.entity.projectile.Projectile; ++import net.minecraft.core.IPosition; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.DispenserBlock; ++// CraftBukkit start ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.projectile.Projectile; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end + + public abstract class AbstractProjectileDispenseBehavior extends DefaultDispenseItemBehavior { ++ ++ public AbstractProjectileDispenseBehavior() {} ++ + @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Level level = blockSource.level(); +- Position dispensePosition = DispenserBlock.getDispensePosition(blockSource); +- Direction direction = blockSource.state().getValue(DispenserBlock.FACING); +- Projectile projectile = this.getProjectile(level, dispensePosition, itemStack); +- projectile.shoot( +- (double)direction.getStepX(), (double)((float)direction.getStepY() + 0.1F), (double)direction.getStepZ(), this.getPower(), this.getUncertainty() +- ); +- level.addFreshEntity(projectile); +- itemStack.shrink(1); +- return itemStack; ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ IPosition iposition = DispenserBlock.getDispensePosition(sourceblock); ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ Projectile iprojectile = this.getProjectile(worldserver, iposition, itemstack); ++ ++ // CraftBukkit start ++ // iprojectile.shoot((double) enumdirection.getStepX(), (double) ((float) enumdirection.getStepY() + 0.1F), (double) enumdirection.getStepZ(), this.getPower(), this.getUncertainty()); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) enumdirection.getStepX(), (double) ((float) enumdirection.getStepY() + 0.1F), (double) enumdirection.getStepZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ iprojectile.shoot(event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), this.getPower(), this.getUncertainty()); ++ ((Entity) iprojectile).projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(sourceblock.blockEntity()); ++ // CraftBukkit end ++ worldserver.addFreshEntity(iprojectile); ++ // itemstack.shrink(1); // CraftBukkit - Handled during event processing ++ return itemstack; + } + + @Override +- protected void playSound(BlockSource blockSource) { +- blockSource.level().levelEvent(1002, blockSource.pos(), 0); ++ protected void playSound(SourceBlock sourceblock) { ++ sourceblock.level().levelEvent(1002, sourceblock.pos(), 0); + } + +- protected abstract Projectile getProjectile(Level level, Position position, ItemStack stack); ++ protected abstract Projectile getProjectile(Level level, IPosition position, ItemStack stack); + + protected float getUncertainty() { + return 6.0F; diff --git a/patch-remap/mache-vineflower/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java.patch b/patch-remap/mache-vineflower/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java.patch new file mode 100644 index 0000000000..b9d44c6282 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java.patch @@ -0,0 +1,124 @@ +--- a/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java ++++ b/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java +@@ -4,15 +4,23 @@ + import net.minecraft.core.Direction; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.tags.FluidTags; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.vehicle.Boat; + import net.minecraft.world.entity.vehicle.ChestBoat; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.DispenserBlock; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end + + public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior { +- private final DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior(); ++ ++ private final DefaultDispenseItemBehavior defaultDispenseItemBehavior; + private final Boat.Type type; + private final boolean isChestBoat; + +@@ -21,42 +29,73 @@ + } + + public BoatDispenseItemBehavior(Boat.Type type, boolean isChestBoat) { ++ this.defaultDispenseItemBehavior = new DefaultDispenseItemBehavior(); + this.type = type; + this.isChestBoat = isChestBoat; + } + + @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Direction direction = blockSource.state().getValue(DispenserBlock.FACING); +- ServerLevel serverLevel = blockSource.level(); +- Vec3 vec3 = blockSource.center(); +- double d = 0.5625 + (double)EntityType.BOAT.getWidth() / 2.0; +- double d1 = vec3.x() + (double)direction.getStepX() * d; +- double d2 = vec3.y() + (double)((float)direction.getStepY() * 1.125F); +- double d3 = vec3.z() + (double)direction.getStepZ() * d; +- BlockPos blockPos = blockSource.pos().relative(direction); ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ ServerLevel worldserver = sourceblock.level(); ++ Vec3 vec3d = sourceblock.center(); ++ double d0 = 0.5625D + (double) EntityType.BOAT.getWidth() / 2.0D; ++ double d1 = vec3d.x() + (double) enumdirection.getStepX() * d0; ++ double d2 = vec3d.y() + (double) ((float) enumdirection.getStepY() * 1.125F); ++ double d3 = vec3d.z() + (double) enumdirection.getStepZ() * d0; ++ BlockPos blockposition = sourceblock.pos().relative(enumdirection); + double d4; +- if (serverLevel.getFluidState(blockPos).is(FluidTags.WATER)) { +- d4 = 1.0; ++ ++ if (worldserver.getFluidState(blockposition).is(FluidTags.WATER)) { ++ d4 = 1.0D; + } else { +- if (!serverLevel.getBlockState(blockPos).isAir() || !serverLevel.getFluidState(blockPos.below()).is(FluidTags.WATER)) { +- return this.defaultDispenseItemBehavior.dispense(blockSource, itemStack); ++ if (!worldserver.getBlockState(blockposition).isAir() || !worldserver.getFluidState(blockposition.below()).is(FluidTags.WATER)) { ++ return this.defaultDispenseItemBehavior.dispense(sourceblock, itemstack); + } + +- d4 = 0.0; ++ d4 = 0.0D; + } + +- Boat boat = (Boat)(this.isChestBoat ? new ChestBoat(serverLevel, d1, d2 + d4, d3) : new Boat(serverLevel, d1, d2 + d4, d3)); +- EntityType.createDefaultStackConfig(serverLevel, itemStack, null).accept(boat); +- boat.setVariant(this.type); +- boat.setYRot(direction.toYRot()); +- serverLevel.addFreshEntity(boat); +- itemStack.shrink(1); +- return itemStack; ++ // Object object = this.isChestBoat ? new ChestBoat(worldserver, d1, d2 + d4, d3) : new EntityBoat(worldserver, d1, d2 + d4, d3); ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d1, d2 + d4, d3)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ Boat object = this.isChestBoat ? new ChestBoat(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ()) : new Boat(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ()); ++ // CraftBukkit end ++ ++ EntityType.createDefaultStackConfig(worldserver, itemstack, (Player) null).accept(object); ++ ((Boat) object).setVariant(this.type); ++ ((Boat) object).setYRot(enumdirection.toYRot()); ++ if (!worldserver.addFreshEntity((Entity) object)) itemstack.grow(1); // CraftBukkit ++ // itemstack.shrink(1); // CraftBukkit - handled during event processing ++ return itemstack; + } + + @Override +- protected void playSound(BlockSource blockSource) { +- blockSource.level().levelEvent(1000, blockSource.pos(), 0); ++ protected void playSound(SourceBlock sourceblock) { ++ sourceblock.level().levelEvent(1000, sourceblock.pos(), 0); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java.patch b/patch-remap/mache-vineflower/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java.patch new file mode 100644 index 0000000000..368c3ea64d --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java.patch @@ -0,0 +1,156 @@ +--- a/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java ++++ b/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java +@@ -1,54 +1,122 @@ + package net.minecraft.core.dispenser; + + import net.minecraft.core.Direction; +-import net.minecraft.core.Position; ++import net.minecraft.core.IPosition; + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.DispenserBlock; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftVector; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end + + public class DefaultDispenseItemBehavior implements DispenseItemBehavior { ++ ++ // CraftBukkit start ++ private boolean dropper; ++ ++ public DefaultDispenseItemBehavior(boolean dropper) { ++ this.dropper = dropper; ++ } ++ // CraftBukkit end ++ ++ public DefaultDispenseItemBehavior() {} ++ + @Override +- public final ItemStack dispense(BlockSource blockSource, ItemStack itemStack) { +- ItemStack itemStack1 = this.execute(blockSource, itemStack); +- this.playSound(blockSource); +- this.playAnimation(blockSource, blockSource.state().getValue(DispenserBlock.FACING)); +- return itemStack1; ++ public final ItemStack dispense(SourceBlock sourceblock, ItemStack itemstack) { ++ ItemStack itemstack1 = this.execute(sourceblock, itemstack); ++ ++ this.playSound(sourceblock); ++ this.playAnimation(sourceblock, (Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ return itemstack1; + } + +- protected ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Direction direction = blockSource.state().getValue(DispenserBlock.FACING); +- Position dispensePosition = DispenserBlock.getDispensePosition(blockSource); +- ItemStack itemStack1 = itemStack.split(1); +- spawnItem(blockSource.level(), itemStack1, 6, direction, dispensePosition); +- return itemStack; ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ IPosition iposition = DispenserBlock.getDispensePosition(sourceblock); ++ ItemStack itemstack1 = itemstack.split(1); ++ ++ // CraftBukkit start ++ if (!spawnItem(sourceblock.level(), itemstack1, 6, enumdirection, sourceblock, dropper)) { ++ itemstack.grow(1); ++ } ++ // CraftBukkit end ++ return itemstack; + } + +- public static void spawnItem(Level level, ItemStack stack, int speed, Direction facing, Position position) { +- double d = position.x(); +- double d1 = position.y(); +- double d2 = position.z(); +- if (facing.getAxis() == Direction.Axis.Y) { +- d1 -= 0.125; ++ public static void spawnItem(Level level, ItemStack stack, int speed, Direction facing, IPosition position) { ++ // CraftBukkit start ++ ItemEntity entityitem = prepareItem(level, stack, speed, facing, position); ++ level.addFreshEntity(entityitem); ++ } ++ ++ private static ItemEntity prepareItem(Level world, ItemStack itemstack, int i, Direction enumdirection, IPosition iposition) { ++ // CraftBukkit end ++ double d0 = iposition.x(); ++ double d1 = iposition.y(); ++ double d2 = iposition.z(); ++ ++ if (enumdirection.getAxis() == Direction.Axis.Y) { ++ d1 -= 0.125D; + } else { +- d1 -= 0.15625; ++ d1 -= 0.15625D; + } + +- ItemEntity itemEntity = new ItemEntity(level, d, d1, d2, stack); +- double d3 = level.random.nextDouble() * 0.1 + 0.2; +- itemEntity.setDeltaMovement( +- level.random.triangle((double)facing.getStepX() * d3, 0.0172275 * (double)speed), +- level.random.triangle(0.2, 0.0172275 * (double)speed), +- level.random.triangle((double)facing.getStepZ() * d3, 0.0172275 * (double)speed) +- ); +- level.addFreshEntity(itemEntity); ++ ItemEntity entityitem = new ItemEntity(world, d0, d1, d2, itemstack); ++ double d3 = world.random.nextDouble() * 0.1D + 0.2D; ++ ++ entityitem.setDeltaMovement(world.random.triangle((double) enumdirection.getStepX() * d3, 0.0172275D * (double) i), world.random.triangle(0.2D, 0.0172275D * (double) i), world.random.triangle((double) enumdirection.getStepZ() * d3, 0.0172275D * (double) i)); ++ // CraftBukkit start ++ return entityitem; + } + +- protected void playSound(BlockSource blockSource) { +- blockSource.level().levelEvent(1000, blockSource.pos(), 0); ++ // CraftBukkit - void -> boolean return, IPosition -> ISourceBlock last argument, dropper ++ public static boolean spawnItem(Level world, ItemStack itemstack, int i, Direction enumdirection, SourceBlock sourceblock, boolean dropper) { ++ if (itemstack.isEmpty()) return true; ++ IPosition iposition = DispenserBlock.getDispensePosition(sourceblock); ++ ItemEntity entityitem = prepareItem(world, itemstack, i, enumdirection, iposition); ++ ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), CraftVector.toBukkit(entityitem.getDeltaMovement())); ++ if (!DispenserBlock.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ entityitem.setItem(CraftItemStack.asNMSCopy(event.getItem())); ++ entityitem.setDeltaMovement(CraftVector.toNMS(event.getVelocity())); ++ ++ if (!dropper && !event.getItem().getType().equals(craftItem.getType())) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior.getClass() != DefaultDispenseItemBehavior.class) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ } else { ++ world.addFreshEntity(entityitem); ++ } ++ return false; ++ } ++ ++ world.addFreshEntity(entityitem); ++ ++ return true; ++ // CraftBukkit end + } + +- protected void playAnimation(BlockSource blockSource, Direction direction) { +- blockSource.level().levelEvent(2000, blockSource.pos(), direction.get3DDataValue()); ++ protected void playSound(SourceBlock sourceblock) { ++ sourceblock.level().levelEvent(1000, sourceblock.pos(), 0); + } ++ ++ protected void playAnimation(SourceBlock sourceblock, Direction enumdirection) { ++ sourceblock.level().levelEvent(2000, sourceblock.pos(), enumdirection.get3DDataValue()); ++ } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/core/dispenser/DispenseItemBehavior.java.patch b/patch-remap/mache-vineflower/net/minecraft/core/dispenser/DispenseItemBehavior.java.patch new file mode 100644 index 0000000000..120e8d2a6b --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/core/dispenser/DispenseItemBehavior.java.patch @@ -0,0 +1,1517 @@ +--- a/net/minecraft/core/dispenser/DispenseItemBehavior.java ++++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java +@@ -1,28 +1,32 @@ + package net.minecraft.core.dispenser; + + import com.mojang.logging.LogUtils; ++import java.util.Iterator; + import java.util.List; + import java.util.Optional; + import java.util.function.Consumer; + import net.minecraft.Util; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.Position; ++import net.minecraft.core.IPosition; + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.FluidTags; + import net.minecraft.util.RandomSource; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.Saddleable; + import net.minecraft.world.entity.animal.horse.AbstractChestedHorse; + import net.minecraft.world.entity.animal.horse.AbstractHorse; + import net.minecraft.world.entity.decoration.ArmorStand; + import net.minecraft.world.entity.item.PrimedTnt; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.AbstractArrow; + import net.minecraft.world.entity.projectile.Arrow; + import net.minecraft.world.entity.projectile.FireworkRocketEntity; +@@ -36,6 +40,7 @@ + import net.minecraft.world.entity.vehicle.Boat; + import net.minecraft.world.item.ArmorItem; + import net.minecraft.world.item.BoneMealItem; ++import net.minecraft.world.item.BucketItem; + import net.minecraft.world.item.DispensibleContainerItem; + import net.minecraft.world.item.DyeColor; + import net.minecraft.world.item.HoneycombItem; +@@ -46,9 +51,9 @@ + import net.minecraft.world.item.alchemy.PotionUtils; + import net.minecraft.world.item.alchemy.Potions; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.BaseFireBlock; + import net.minecraft.world.level.block.BeehiveBlock; ++import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.BucketPickup; + import net.minecraft.world.level.block.CampfireBlock; +@@ -56,7 +61,9 @@ + import net.minecraft.world.level.block.CandleCakeBlock; + import net.minecraft.world.level.block.CarvedPumpkinBlock; + import net.minecraft.world.level.block.DispenserBlock; ++import net.minecraft.world.level.block.LiquidBlockContainer; + import net.minecraft.world.level.block.RespawnAnchorBlock; ++import net.minecraft.world.level.block.SaplingBlock; + import net.minecraft.world.level.block.ShulkerBoxBlock; + import net.minecraft.world.level.block.SkullBlock; + import net.minecraft.world.level.block.TntBlock; +@@ -64,63 +71,86 @@ + import net.minecraft.world.level.block.entity.BeehiveBlockEntity; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.SkullBlockEntity; +-import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.RotationSegment; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; ++import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; ++import org.bukkit.Location; ++import org.bukkit.TreeType; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.craftbukkit.util.DummyGeneratorAccess; ++import org.bukkit.event.block.BlockDispenseArmorEvent; ++import org.bukkit.event.block.BlockDispenseEvent; ++import org.bukkit.event.block.BlockFertilizeEvent; ++import org.bukkit.event.world.StructureGrowEvent; ++// CraftBukkit end + + public interface DispenseItemBehavior { ++ + Logger LOGGER = LogUtils.getLogger(); +- DispenseItemBehavior NOOP = (blockSource, itemStack) -> itemStack; ++ DispenseItemBehavior NOOP = (sourceblock, itemstack) -> { ++ return itemstack; ++ }; + +- ItemStack dispense(BlockSource blockSource, ItemStack itemStack); ++ ItemStack dispense(SourceBlock sourceblock, ItemStack itemstack); + + static void bootStrap() { + DispenserBlock.registerBehavior(Items.ARROW, new AbstractProjectileDispenseBehavior() { + @Override +- protected Projectile getProjectile(Level level, Position position, ItemStack stack) { +- Arrow arrow = new Arrow(level, position.x(), position.y(), position.z(), stack.copyWithCount(1)); +- arrow.pickup = AbstractArrow.Pickup.ALLOWED; +- return arrow; ++ protected Projectile getProjectile(Level level, IPosition position, ItemStack stack) { ++ Arrow entitytippedarrow = new Arrow(level, position.x(), position.y(), position.z(), stack.copyWithCount(1)); ++ ++ entitytippedarrow.pickup = AbstractArrow.Pickup.ALLOWED; ++ return entitytippedarrow; + } + }); + DispenserBlock.registerBehavior(Items.TIPPED_ARROW, new AbstractProjectileDispenseBehavior() { + @Override +- protected Projectile getProjectile(Level level, Position position, ItemStack stack) { +- Arrow arrow = new Arrow(level, position.x(), position.y(), position.z(), stack.copyWithCount(1)); +- arrow.setEffectsFromItem(stack); +- arrow.pickup = AbstractArrow.Pickup.ALLOWED; +- return arrow; ++ protected Projectile getProjectile(Level level, IPosition position, ItemStack stack) { ++ Arrow entitytippedarrow = new Arrow(level, position.x(), position.y(), position.z(), stack.copyWithCount(1)); ++ ++ entitytippedarrow.setEffectsFromItem(stack); ++ entitytippedarrow.pickup = AbstractArrow.Pickup.ALLOWED; ++ return entitytippedarrow; + } + }); + DispenserBlock.registerBehavior(Items.SPECTRAL_ARROW, new AbstractProjectileDispenseBehavior() { + @Override +- protected Projectile getProjectile(Level level, Position position, ItemStack stack) { +- AbstractArrow abstractArrow = new SpectralArrow(level, position.x(), position.y(), position.z(), stack.copyWithCount(1)); +- abstractArrow.pickup = AbstractArrow.Pickup.ALLOWED; +- return abstractArrow; ++ protected Projectile getProjectile(Level level, IPosition position, ItemStack stack) { ++ SpectralArrow entityspectralarrow = new SpectralArrow(level, position.x(), position.y(), position.z(), stack.copyWithCount(1)); ++ ++ entityspectralarrow.pickup = AbstractArrow.Pickup.ALLOWED; ++ return entityspectralarrow; + } + }); + DispenserBlock.registerBehavior(Items.EGG, new AbstractProjectileDispenseBehavior() { + @Override +- protected Projectile getProjectile(Level level, Position position, ItemStack stack) { +- return Util.make(new ThrownEgg(level, position.x(), position.y(), position.z()), entity -> entity.setItem(stack)); ++ protected Projectile getProjectile(Level level, IPosition position, ItemStack stack) { ++ return (Projectile) Util.make(new ThrownEgg(level, position.x(), position.y(), position.z()), (entityegg) -> { ++ entityegg.setItem(stack); ++ }); + } + }); + DispenserBlock.registerBehavior(Items.SNOWBALL, new AbstractProjectileDispenseBehavior() { + @Override +- protected Projectile getProjectile(Level level, Position position, ItemStack stack) { +- return Util.make(new Snowball(level, position.x(), position.y(), position.z()), entity -> entity.setItem(stack)); ++ protected Projectile getProjectile(Level level, IPosition position, ItemStack stack) { ++ return (Projectile) Util.make(new Snowball(level, position.x(), position.y(), position.z()), (entitysnowball) -> { ++ entitysnowball.setItem(stack); ++ }); + } + }); + DispenserBlock.registerBehavior(Items.EXPERIENCE_BOTTLE, new AbstractProjectileDispenseBehavior() { + @Override +- protected Projectile getProjectile(Level level, Position position, ItemStack stack) { +- return Util.make(new ThrownExperienceBottle(level, position.x(), position.y(), position.z()), entity -> entity.setItem(stack)); ++ protected Projectile getProjectile(Level level, IPosition position, ItemStack stack) { ++ return (Projectile) Util.make(new ThrownExperienceBottle(level, position.x(), position.y(), position.z()), (entitythrownexpbottle) -> { ++ entitythrownexpbottle.setItem(stack); ++ }); + } + + @Override +@@ -135,11 +165,13 @@ + }); + DispenserBlock.registerBehavior(Items.SPLASH_POTION, new DispenseItemBehavior() { + @Override +- public ItemStack dispense(BlockSource blockSource, ItemStack itemStack) { ++ public ItemStack dispense(SourceBlock sourceblock, ItemStack itemstack) { + return (new AbstractProjectileDispenseBehavior() { + @Override +- protected Projectile getProjectile(Level level, Position position, ItemStack stack) { +- return Util.make(new ThrownPotion(level, position.x(), position.y(), position.z()), entity -> entity.setItem(stack)); ++ protected Projectile getProjectile(Level level, IPosition position, ItemStack stack) { ++ return (Projectile) Util.make(new ThrownPotion(level, position.x(), position.y(), position.z()), (entitypotion) -> { ++ entitypotion.setItem(stack); ++ }); + } + + @Override +@@ -151,16 +183,18 @@ + protected float getPower() { + return super.getPower() * 1.25F; + } +- }).dispense(blockSource, itemStack); ++ }).dispense(sourceblock, itemstack); + } + }); + DispenserBlock.registerBehavior(Items.LINGERING_POTION, new DispenseItemBehavior() { + @Override +- public ItemStack dispense(BlockSource blockSource, ItemStack itemStack) { ++ public ItemStack dispense(SourceBlock sourceblock, ItemStack itemstack) { + return (new AbstractProjectileDispenseBehavior() { + @Override +- protected Projectile getProjectile(Level level, Position position, ItemStack stack) { +- return Util.make(new ThrownPotion(level, position.x(), position.y(), position.z()), entity -> entity.setItem(stack)); ++ protected Projectile getProjectile(Level level, IPosition position, ItemStack stack) { ++ return (Projectile) Util.make(new ThrownPotion(level, position.x(), position.y(), position.z()), (entitypotion) -> { ++ entitypotion.setItem(stack); ++ }); + } + + @Override +@@ -172,179 +206,383 @@ + protected float getPower() { + return super.getPower() * 1.25F; + } +- }).dispense(blockSource, itemStack); ++ }).dispense(sourceblock, itemstack); + } + }); +- DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior() { ++ DefaultDispenseItemBehavior dispensebehavioritem = new DefaultDispenseItemBehavior() { + @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Direction direction = blockSource.state().getValue(DispenserBlock.FACING); +- EntityType type = ((SpawnEggItem)itemStack.getItem()).getType(itemStack.getTag()); ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ EntityType entitytypes = ((SpawnEggItem) itemstack.getItem()).getType(itemstack.getTag()); + ++ // CraftBukkit start ++ ServerLevel worldserver = sourceblock.level(); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ + try { +- type.spawn( +- blockSource.level(), itemStack, null, blockSource.pos().relative(direction), MobSpawnType.DISPENSER, direction != Direction.UP, false +- ); +- } catch (Exception var6) { +- LOGGER.error("Error while dispensing spawn egg from dispenser at {}", blockSource.pos(), var6); ++ entitytypes.spawn(sourceblock.level(), itemstack, (Player) null, sourceblock.pos().relative(enumdirection), EnumMobSpawn.DISPENSER, enumdirection != Direction.UP, false); ++ } catch (Exception exception) { ++ LOGGER.error("Error while dispensing spawn egg from dispenser at {}", sourceblock.pos(), exception); // CraftBukkit - decompile error + return ItemStack.EMPTY; + } + +- itemStack.shrink(1); +- blockSource.level().gameEvent(null, GameEvent.ENTITY_PLACE, blockSource.pos()); +- return itemStack; ++ // itemstack.shrink(1); // Handled during event processing ++ // CraftBukkit end ++ sourceblock.level().gameEvent((Entity) null, GameEvent.ENTITY_PLACE, sourceblock.pos()); ++ return itemstack; + } + }; ++ Iterator iterator = SpawnEggItem.eggs().iterator(); + +- for (SpawnEggItem spawnEggItem : SpawnEggItem.eggs()) { +- DispenserBlock.registerBehavior(spawnEggItem, defaultDispenseItemBehavior); ++ while (iterator.hasNext()) { ++ SpawnEggItem itemmonsteregg = (SpawnEggItem) iterator.next(); ++ ++ DispenserBlock.registerBehavior(itemmonsteregg, dispensebehavioritem); + } + +- DispenserBlock.registerBehavior( +- Items.ARMOR_STAND, +- new DefaultDispenseItemBehavior() { +- @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Direction direction = blockSource.state().getValue(DispenserBlock.FACING); +- BlockPos blockPos = blockSource.pos().relative(direction); +- ServerLevel serverLevel = blockSource.level(); +- Consumer consumer = EntityType.appendDefaultStackConfig( +- armorStand1 -> armorStand1.setYRot(direction.toYRot()), serverLevel, itemStack, null +- ); +- ArmorStand armorStand = EntityType.ARMOR_STAND +- .spawn(serverLevel, itemStack.getTag(), consumer, blockPos, MobSpawnType.DISPENSER, false, false); +- if (armorStand != null) { +- itemStack.shrink(1); ++ DispenserBlock.registerBehavior(Items.ARMOR_STAND, new DefaultDispenseItemBehavior() { ++ @Override ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ BlockPos blockposition = sourceblock.pos().relative(enumdirection); ++ ServerLevel worldserver = sourceblock.level(); ++ ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; + } +- +- return itemStack; + } ++ // CraftBukkit end ++ ++ Consumer consumer = EntityType.appendDefaultStackConfig((entityarmorstand) -> { ++ entityarmorstand.setYRot(enumdirection.toYRot()); ++ }, worldserver, itemstack, (Player) null); ++ ArmorStand entityarmorstand = (ArmorStand) EntityType.ARMOR_STAND.spawn(worldserver, itemstack.getTag(), consumer, blockposition, EnumMobSpawn.DISPENSER, false, false); ++ ++ if (entityarmorstand != null) { ++ // itemstack.shrink(1); // CraftBukkit - Handled during event processing ++ } ++ ++ return itemstack; + } +- ); +- DispenserBlock.registerBehavior( +- Items.SADDLE, +- new OptionalDispenseItemBehavior() { +- @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); +- List entitiesOfClass = blockSource.level() +- .getEntitiesOfClass( +- LivingEntity.class, +- new AABB(blockPos), +- entity -> entity instanceof Saddleable saddleable && !saddleable.isSaddled() && saddleable.isSaddleable() +- ); +- if (!entitiesOfClass.isEmpty()) { +- ((Saddleable)entitiesOfClass.get(0)).equipSaddle(SoundSource.BLOCKS); +- itemStack.shrink(1); +- this.setSuccess(true); +- return itemStack; ++ }); ++ DispenserBlock.registerBehavior(Items.SADDLE, new OptionalDispenseItemBehavior() { ++ @Override ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ List list = sourceblock.level().getEntitiesOfClass(LivingEntity.class, new AABB(blockposition), (entityliving) -> { ++ if (!(entityliving instanceof Saddleable)) { ++ return false; + } else { +- return super.execute(blockSource, itemStack); ++ Saddleable isaddleable = (Saddleable) entityliving; ++ ++ return !isaddleable.isSaddled() && isaddleable.isSaddleable(); + } ++ }); ++ ++ if (!list.isEmpty()) { ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ Level world = sourceblock.level(); ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) list.get(0).getBukkitEntity()); ++ if (!DispenserBlock.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ ((Saddleable) list.get(0)).equipSaddle(SoundSource.BLOCKS); ++ // itemstack.shrink(1); // CraftBukkit - handled above ++ this.setSuccess(true); ++ return itemstack; ++ } else { ++ return super.execute(sourceblock, itemstack); + } + } +- ); +- DefaultDispenseItemBehavior defaultDispenseItemBehavior1 = new OptionalDispenseItemBehavior() { ++ }); ++ OptionalDispenseItemBehavior dispensebehaviormaybe = new OptionalDispenseItemBehavior() { + @Override +- protected ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ List list = sourceblock.level().getEntitiesOfClass(AbstractHorse.class, new AABB(blockposition), (entityhorseabstract) -> { ++ return entityhorseabstract.isAlive() && entityhorseabstract.canWearArmor(); ++ }); ++ Iterator iterator1 = list.iterator(); + +- for (AbstractHorse abstractHorse : blockSource.level() +- .getEntitiesOfClass(AbstractHorse.class, new AABB(blockPos), entity -> entity.isAlive() && entity.canWearArmor())) { +- if (abstractHorse.isArmor(itemStack) && !abstractHorse.isWearingArmor() && abstractHorse.isTamed()) { +- abstractHorse.getSlot(401).set(itemStack.split(1)); +- this.setSuccess(true); +- return itemStack; ++ AbstractHorse entityhorseabstract; ++ ++ do { ++ if (!iterator1.hasNext()) { ++ return super.execute(sourceblock, itemstack); + } ++ ++ entityhorseabstract = (AbstractHorse) iterator1.next(); ++ } while (!entityhorseabstract.isArmor(itemstack) || entityhorseabstract.isWearingArmor() || !entityhorseabstract.isTamed()); ++ ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ Level world = sourceblock.level(); ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityhorseabstract.getBukkitEntity()); ++ if (!DispenserBlock.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); + } + +- return super.execute(blockSource, itemStack); ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ entityhorseabstract.getSlot(401).set(CraftItemStack.asNMSCopy(event.getItem())); ++ // CraftBukkit end ++ this.setSuccess(true); ++ return itemstack; + } + }; +- DispenserBlock.registerBehavior(Items.LEATHER_HORSE_ARMOR, defaultDispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.IRON_HORSE_ARMOR, defaultDispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.GOLDEN_HORSE_ARMOR, defaultDispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.DIAMOND_HORSE_ARMOR, defaultDispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.WHITE_CARPET, defaultDispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.ORANGE_CARPET, defaultDispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.CYAN_CARPET, defaultDispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.BLUE_CARPET, defaultDispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.BROWN_CARPET, defaultDispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.BLACK_CARPET, defaultDispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.GRAY_CARPET, defaultDispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.GREEN_CARPET, defaultDispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.LIGHT_BLUE_CARPET, defaultDispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.LIGHT_GRAY_CARPET, defaultDispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.LIME_CARPET, defaultDispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.MAGENTA_CARPET, defaultDispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.PINK_CARPET, defaultDispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.PURPLE_CARPET, defaultDispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.RED_CARPET, defaultDispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.YELLOW_CARPET, defaultDispenseItemBehavior1); +- DispenserBlock.registerBehavior( +- Items.CHEST, +- new OptionalDispenseItemBehavior() { +- @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); +- +- for (AbstractChestedHorse abstractChestedHorse : blockSource.level() +- .getEntitiesOfClass(AbstractChestedHorse.class, new AABB(blockPos), entity -> entity.isAlive() && !entity.hasChest())) { +- if (abstractChestedHorse.isTamed() && abstractChestedHorse.getSlot(499).set(itemStack)) { +- itemStack.shrink(1); +- this.setSuccess(true); +- return itemStack; +- } ++ ++ DispenserBlock.registerBehavior(Items.LEATHER_HORSE_ARMOR, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.IRON_HORSE_ARMOR, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.GOLDEN_HORSE_ARMOR, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.DIAMOND_HORSE_ARMOR, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.WHITE_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.ORANGE_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.CYAN_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.BLUE_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.BROWN_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.BLACK_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.GRAY_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.GREEN_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.LIGHT_BLUE_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.LIGHT_GRAY_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.LIME_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.MAGENTA_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.PINK_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.PURPLE_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.RED_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.YELLOW_CARPET, dispensebehaviormaybe); ++ DispenserBlock.registerBehavior(Items.CHEST, new OptionalDispenseItemBehavior() { ++ @Override ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ List list = sourceblock.level().getEntitiesOfClass(AbstractChestedHorse.class, new AABB(blockposition), (entityhorsechestedabstract) -> { ++ return entityhorsechestedabstract.isAlive() && !entityhorsechestedabstract.hasChest(); ++ }); ++ Iterator iterator1 = list.iterator(); ++ ++ AbstractChestedHorse entityhorsechestedabstract; ++ ++ do { ++ if (!iterator1.hasNext()) { ++ return super.execute(sourceblock, itemstack); + } +- +- return super.execute(blockSource, itemStack); ++ ++ entityhorsechestedabstract = (AbstractChestedHorse) iterator1.next(); ++ // CraftBukkit start ++ } while (!entityhorsechestedabstract.isTamed()); ++ ItemStack itemstack1 = itemstack.split(1); ++ Level world = sourceblock.level(); ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityhorsechestedabstract.getBukkitEntity()); ++ if (!DispenserBlock.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); + } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ entityhorsechestedabstract.getSlot(499).set(CraftItemStack.asNMSCopy(event.getItem())); ++ // CraftBukkit end ++ ++ // itemstack.shrink(1); // CraftBukkit - handled above ++ this.setSuccess(true); ++ return itemstack; + } +- ); +- DispenserBlock.registerBehavior( +- Items.FIREWORK_ROCKET, +- new DefaultDispenseItemBehavior() { +- @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Direction direction = blockSource.state().getValue(DispenserBlock.FACING); +- Vec3 entityPokingOutOfBlockPos = DispenseItemBehavior.getEntityPokingOutOfBlockPos(blockSource, EntityType.FIREWORK_ROCKET, direction); +- FireworkRocketEntity fireworkRocketEntity = new FireworkRocketEntity( +- blockSource.level(), itemStack, entityPokingOutOfBlockPos.x(), entityPokingOutOfBlockPos.y(), entityPokingOutOfBlockPos.z(), true +- ); +- fireworkRocketEntity.shoot((double)direction.getStepX(), (double)direction.getStepY(), (double)direction.getStepZ(), 0.5F, 1.0F); +- blockSource.level().addFreshEntity(fireworkRocketEntity); +- itemStack.shrink(1); +- return itemStack; ++ }); ++ DispenserBlock.registerBehavior(Items.FIREWORK_ROCKET, new DefaultDispenseItemBehavior() { ++ @Override ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ // CraftBukkit start ++ ServerLevel worldserver = sourceblock.level(); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(enumdirection.getStepX(), enumdirection.getStepY(), enumdirection.getStepZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); + } +- +- @Override +- protected void playSound(BlockSource blockSource) { +- blockSource.level().levelEvent(1004, blockSource.pos(), 0); ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; + } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); ++ Vec3 vec3d = DispenseItemBehavior.getEntityPokingOutOfBlockPos(sourceblock, EntityType.FIREWORK_ROCKET, enumdirection); ++ FireworkRocketEntity entityfireworks = new FireworkRocketEntity(sourceblock.level(), itemstack, vec3d.x(), vec3d.y(), vec3d.z(), true); ++ ++ entityfireworks.shoot((double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ(), 0.5F, 1.0F); ++ sourceblock.level().addFreshEntity(entityfireworks); ++ // itemstack.shrink(1); // Handled during event processing ++ // CraftBukkit end ++ return itemstack; + } +- ); ++ ++ @Override ++ protected void playSound(SourceBlock sourceblock) { ++ sourceblock.level().levelEvent(1004, sourceblock.pos(), 0); ++ } ++ }); + DispenserBlock.registerBehavior(Items.FIRE_CHARGE, new DefaultDispenseItemBehavior() { + @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Direction direction = blockSource.state().getValue(DispenserBlock.FACING); +- Position dispensePosition = DispenserBlock.getDispensePosition(blockSource); +- double d = dispensePosition.x() + (double)((float)direction.getStepX() * 0.3F); +- double d1 = dispensePosition.y() + (double)((float)direction.getStepY() * 0.3F); +- double d2 = dispensePosition.z() + (double)((float)direction.getStepZ() * 0.3F); +- Level level = blockSource.level(); +- RandomSource randomSource = level.random; +- double d3 = randomSource.triangle((double)direction.getStepX(), 0.11485000000000001); +- double d4 = randomSource.triangle((double)direction.getStepY(), 0.11485000000000001); +- double d5 = randomSource.triangle((double)direction.getStepZ(), 0.11485000000000001); +- SmallFireball smallFireball = new SmallFireball(level, d, d1, d2, d3, d4, d5); +- level.addFreshEntity(Util.make(smallFireball, entity -> entity.setItem(itemStack))); +- itemStack.shrink(1); +- return itemStack; ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ IPosition iposition = DispenserBlock.getDispensePosition(sourceblock); ++ double d0 = iposition.x() + (double) ((float) enumdirection.getStepX() * 0.3F); ++ double d1 = iposition.y() + (double) ((float) enumdirection.getStepY() * 0.3F); ++ double d2 = iposition.z() + (double) ((float) enumdirection.getStepZ() * 0.3F); ++ ServerLevel worldserver = sourceblock.level(); ++ RandomSource randomsource = worldserver.random; ++ double d3 = randomsource.triangle((double) enumdirection.getStepX(), 0.11485000000000001D); ++ double d4 = randomsource.triangle((double) enumdirection.getStepY(), 0.11485000000000001D); ++ double d5 = randomsource.triangle((double) enumdirection.getStepZ(), 0.11485000000000001D); ++ ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d3, d4, d5)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ SmallFireball entitysmallfireball = new SmallFireball(worldserver, d0, d1, d2, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ()); ++ entitysmallfireball.setItem(itemstack1); ++ entitysmallfireball.projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(sourceblock.blockEntity()); ++ ++ worldserver.addFreshEntity(entitysmallfireball); ++ // itemstack.shrink(1); // Handled during event processing ++ // CraftBukkit end ++ return itemstack; + } + + @Override +- protected void playSound(BlockSource blockSource) { +- blockSource.level().levelEvent(1018, blockSource.pos(), 0); ++ protected void playSound(SourceBlock sourceblock) { ++ sourceblock.level().levelEvent(1018, sourceblock.pos(), 0); + } + }); + DispenserBlock.registerBehavior(Items.OAK_BOAT, new BoatDispenseItemBehavior(Boat.Type.OAK)); +@@ -365,320 +603,562 @@ + DispenserBlock.registerBehavior(Items.CHERRY_CHEST_BOAT, new BoatDispenseItemBehavior(Boat.Type.CHERRY, true)); + DispenserBlock.registerBehavior(Items.MANGROVE_CHEST_BOAT, new BoatDispenseItemBehavior(Boat.Type.MANGROVE, true)); + DispenserBlock.registerBehavior(Items.BAMBOO_CHEST_RAFT, new BoatDispenseItemBehavior(Boat.Type.BAMBOO, true)); +- DispenseItemBehavior dispenseItemBehavior = new DefaultDispenseItemBehavior() { ++ DefaultDispenseItemBehavior dispensebehavioritem1 = new DefaultDispenseItemBehavior() { + private final DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior(); + + @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- DispensibleContainerItem dispensibleContainerItem = (DispensibleContainerItem)itemStack.getItem(); +- BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); +- Level level = blockSource.level(); +- if (dispensibleContainerItem.emptyContents(null, level, blockPos, null)) { +- dispensibleContainerItem.checkExtraContent(null, level, itemStack, blockPos); +- return new ItemStack(Items.BUCKET); ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ DispensibleContainerItem dispensiblecontaineritem = (DispensibleContainerItem) itemstack.getItem(); ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ ServerLevel worldserver = sourceblock.level(); ++ ++ // CraftBukkit start ++ int x = blockposition.getX(); ++ int y = blockposition.getY(); ++ int z = blockposition.getZ(); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ if (iblockdata.isAir() || iblockdata.canBeReplaced() || (dispensiblecontaineritem instanceof BucketItem && iblockdata.getBlock() instanceof LiquidBlockContainer && ((LiquidBlockContainer) iblockdata.getBlock()).canPlaceLiquid((Player) null, worldserver, blockposition, iblockdata, ((BucketItem) dispensiblecontaineritem).content))) { ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(x, y, z)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ dispensiblecontaineritem = (DispensibleContainerItem) CraftItemStack.asNMSCopy(event.getItem()).getItem(); ++ } ++ // CraftBukkit end ++ ++ if (dispensiblecontaineritem.emptyContents((Player) null, worldserver, blockposition, (BlockHitResult) null)) { ++ dispensiblecontaineritem.checkExtraContent((Player) null, worldserver, itemstack, blockposition); ++ // CraftBukkit start - Handle stacked buckets ++ Item item = Items.BUCKET; ++ itemstack.shrink(1); ++ if (itemstack.isEmpty()) { ++ itemstack.setItem(Items.BUCKET); ++ itemstack.setCount(1); ++ } else if (sourceblock.blockEntity().addItem(new ItemStack(item)) < 0) { ++ this.defaultDispenseItemBehavior.dispense(sourceblock, new ItemStack(item)); ++ } ++ return itemstack; ++ // CraftBukkit end + } else { +- return this.defaultDispenseItemBehavior.dispense(blockSource, itemStack); ++ return this.defaultDispenseItemBehavior.dispense(sourceblock, itemstack); + } + } + }; +- DispenserBlock.registerBehavior(Items.LAVA_BUCKET, dispenseItemBehavior); +- DispenserBlock.registerBehavior(Items.WATER_BUCKET, dispenseItemBehavior); +- DispenserBlock.registerBehavior(Items.POWDER_SNOW_BUCKET, dispenseItemBehavior); +- DispenserBlock.registerBehavior(Items.SALMON_BUCKET, dispenseItemBehavior); +- DispenserBlock.registerBehavior(Items.COD_BUCKET, dispenseItemBehavior); +- DispenserBlock.registerBehavior(Items.PUFFERFISH_BUCKET, dispenseItemBehavior); +- DispenserBlock.registerBehavior(Items.TROPICAL_FISH_BUCKET, dispenseItemBehavior); +- DispenserBlock.registerBehavior(Items.AXOLOTL_BUCKET, dispenseItemBehavior); +- DispenserBlock.registerBehavior(Items.TADPOLE_BUCKET, dispenseItemBehavior); ++ ++ DispenserBlock.registerBehavior(Items.LAVA_BUCKET, dispensebehavioritem1); ++ DispenserBlock.registerBehavior(Items.WATER_BUCKET, dispensebehavioritem1); ++ DispenserBlock.registerBehavior(Items.POWDER_SNOW_BUCKET, dispensebehavioritem1); ++ DispenserBlock.registerBehavior(Items.SALMON_BUCKET, dispensebehavioritem1); ++ DispenserBlock.registerBehavior(Items.COD_BUCKET, dispensebehavioritem1); ++ DispenserBlock.registerBehavior(Items.PUFFERFISH_BUCKET, dispensebehavioritem1); ++ DispenserBlock.registerBehavior(Items.TROPICAL_FISH_BUCKET, dispensebehavioritem1); ++ DispenserBlock.registerBehavior(Items.AXOLOTL_BUCKET, dispensebehavioritem1); ++ DispenserBlock.registerBehavior(Items.TADPOLE_BUCKET, dispensebehavioritem1); + DispenserBlock.registerBehavior(Items.BUCKET, new DefaultDispenseItemBehavior() { + private final DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior(); + + @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- LevelAccessor levelAccessor = blockSource.level(); +- BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); +- BlockState blockState = levelAccessor.getBlockState(blockPos); +- if (blockState.getBlock() instanceof BucketPickup bucketPickup) { +- ItemStack itemStack1 = bucketPickup.pickupBlock(null, levelAccessor, blockPos, blockState); +- if (itemStack1.isEmpty()) { +- return super.execute(blockSource, itemStack); ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ Block block = iblockdata.getBlock(); ++ ++ if (block instanceof BucketPickup) { ++ BucketPickup ifluidsource = (BucketPickup) block; ++ ItemStack itemstack1 = ifluidsource.pickupBlock((Player) null, DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); // CraftBukkit ++ ++ if (itemstack1.isEmpty()) { ++ return super.execute(sourceblock, itemstack); + } else { +- levelAccessor.gameEvent(null, GameEvent.FLUID_PICKUP, blockPos); +- Item item = itemStack1.getItem(); +- itemStack.shrink(1); +- if (itemStack.isEmpty()) { ++ worldserver.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockposition); ++ Item item = itemstack1.getItem(); ++ ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ itemstack1 = ifluidsource.pickupBlock((Player) null, worldserver, blockposition, iblockdata); // From above ++ // CraftBukkit end ++ ++ itemstack.shrink(1); ++ if (itemstack.isEmpty()) { + return new ItemStack(item); + } else { +- if (blockSource.blockEntity().addItem(new ItemStack(item)) < 0) { +- this.defaultDispenseItemBehavior.dispense(blockSource, new ItemStack(item)); ++ if (sourceblock.blockEntity().addItem(new ItemStack(item)) < 0) { ++ this.defaultDispenseItemBehavior.dispense(sourceblock, new ItemStack(item)); + } + +- return itemStack; ++ return itemstack; + } + } + } else { +- return super.execute(blockSource, itemStack); ++ return super.execute(sourceblock, itemstack); + } + } + }); + DispenserBlock.registerBehavior(Items.FLINT_AND_STEEL, new OptionalDispenseItemBehavior() { + @Override +- protected ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Level level = blockSource.level(); ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ + this.setSuccess(true); +- Direction direction = blockSource.state().getValue(DispenserBlock.FACING); +- BlockPos blockPos = blockSource.pos().relative(direction); +- BlockState blockState = level.getBlockState(blockPos); +- if (BaseFireBlock.canBePlacedAt(level, blockPos, direction)) { +- level.setBlockAndUpdate(blockPos, BaseFireBlock.getState(level, blockPos)); +- level.gameEvent(null, GameEvent.BLOCK_PLACE, blockPos); +- } else if (CampfireBlock.canLight(blockState) || CandleBlock.canLight(blockState) || CandleCakeBlock.canLight(blockState)) { +- level.setBlockAndUpdate(blockPos, blockState.setValue(BlockStateProperties.LIT, Boolean.valueOf(true))); +- level.gameEvent(null, GameEvent.BLOCK_CHANGE, blockPos); +- } else if (blockState.getBlock() instanceof TntBlock) { +- TntBlock.explode(level, blockPos); +- level.removeBlock(blockPos, false); ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ BlockPos blockposition = sourceblock.pos().relative(enumdirection); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ ++ if (BaseFireBlock.canBePlacedAt(worldserver, blockposition, enumdirection)) { ++ // CraftBukkit start - Ignition by dispensing flint and steel ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(worldserver, blockposition, sourceblock.pos()).isCancelled()) { ++ worldserver.setBlockAndUpdate(blockposition, BaseFireBlock.getState(worldserver, blockposition)); ++ worldserver.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockposition); ++ } ++ // CraftBukkit end ++ } else if (!CampfireBlock.canLight(iblockdata) && !CandleBlock.canLight(iblockdata) && !CandleCakeBlock.canLight(iblockdata)) { ++ if (iblockdata.getBlock() instanceof TntBlock && org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(worldserver, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.DISPENSER, null, sourceblock.pos())) { // CraftBukkit - TNTPrimeEvent ++ TntBlock.explode(worldserver, blockposition); ++ worldserver.removeBlock(blockposition, false); ++ } else { ++ this.setSuccess(false); ++ } + } else { +- this.setSuccess(false); ++ worldserver.setBlockAndUpdate(blockposition, (IBlockData) iblockdata.setValue(BlockStateProperties.LIT, true)); ++ worldserver.gameEvent((Entity) null, GameEvent.BLOCK_CHANGE, blockposition); + } + +- if (this.isSuccess() && itemStack.hurt(1, level.random, null)) { +- itemStack.setCount(0); ++ if (this.isSuccess() && itemstack.hurt(1, worldserver.random, (ServerPlayer) null)) { ++ itemstack.setCount(0); + } + +- return itemStack; ++ return itemstack; + } + }); + DispenserBlock.registerBehavior(Items.BONE_MEAL, new OptionalDispenseItemBehavior() { + @Override +- protected ItemStack execute(BlockSource blockSource, ItemStack itemStack) { ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { + this.setSuccess(true); +- Level level = blockSource.level(); +- BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); +- if (!BoneMealItem.growCrop(itemStack, level, blockPos) && !BoneMealItem.growWaterPlant(itemStack, level, blockPos, null)) { ++ ServerLevel worldserver = sourceblock.level(); ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ // CraftBukkit start ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ worldserver.captureTreeGeneration = true; ++ // CraftBukkit end ++ ++ if (!BoneMealItem.growCrop(itemstack, worldserver, blockposition) && !BoneMealItem.growWaterPlant(itemstack, worldserver, blockposition, (Direction) null)) { + this.setSuccess(false); +- } else if (!level.isClientSide) { +- level.levelEvent(1505, blockPos, 0); ++ } else if (!worldserver.isClientSide) { ++ worldserver.levelEvent(1505, blockposition, 0); + } ++ // CraftBukkit start ++ worldserver.captureTreeGeneration = false; ++ if (worldserver.capturedBlockStates.size() > 0) { ++ TreeType treeType = SaplingBlock.treeType; ++ SaplingBlock.treeType = null; ++ Location location = CraftLocation.toBukkit(blockposition, worldserver.getWorld()); ++ List blocks = new java.util.ArrayList<>(worldserver.capturedBlockStates.values()); ++ worldserver.capturedBlockStates.clear(); ++ StructureGrowEvent structureEvent = null; ++ if (treeType != null) { ++ structureEvent = new StructureGrowEvent(location, treeType, false, null, blocks); ++ org.bukkit.Bukkit.getPluginManager().callEvent(structureEvent); ++ } + +- return itemStack; ++ BlockFertilizeEvent fertilizeEvent = new BlockFertilizeEvent(location.getBlock(), null, blocks); ++ fertilizeEvent.setCancelled(structureEvent != null && structureEvent.isCancelled()); ++ org.bukkit.Bukkit.getPluginManager().callEvent(fertilizeEvent); ++ ++ if (!fertilizeEvent.isCancelled()) { ++ for (org.bukkit.block.BlockState blockstate : blocks) { ++ blockstate.update(true); ++ } ++ } ++ } ++ // CraftBukkit end ++ ++ return itemstack; + } + }); + DispenserBlock.registerBehavior(Blocks.TNT, new DefaultDispenseItemBehavior() { + @Override +- protected ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Level level = blockSource.level(); +- BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); +- PrimedTnt primedTnt = new PrimedTnt(level, (double)blockPos.getX() + 0.5, (double)blockPos.getY(), (double)blockPos.getZ() + 0.5, null); +- level.addFreshEntity(primedTnt); +- level.playSound(null, primedTnt.getX(), primedTnt.getY(), primedTnt.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent(null, GameEvent.ENTITY_PLACE, blockPos); +- itemStack.shrink(1); +- return itemStack; ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ // CraftBukkit start ++ // EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, (EntityLiving) null); ++ ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ PrimedTnt entitytntprimed = new PrimedTnt(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), (LivingEntity) null); ++ // CraftBukkit end ++ ++ worldserver.addFreshEntity(entitytntprimed); ++ worldserver.playSound((Player) null, entitytntprimed.getX(), entitytntprimed.getY(), entitytntprimed.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F); ++ worldserver.gameEvent((Entity) null, GameEvent.ENTITY_PLACE, blockposition); ++ // itemstack.shrink(1); // CraftBukkit - handled above ++ return itemstack; + } + }); +- DispenseItemBehavior dispenseItemBehavior1 = new OptionalDispenseItemBehavior() { ++ OptionalDispenseItemBehavior dispensebehaviormaybe1 = new OptionalDispenseItemBehavior() { + @Override +- protected ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- this.setSuccess(ArmorItem.dispenseArmor(blockSource, itemStack)); +- return itemStack; ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ this.setSuccess(ArmorItem.dispenseArmor(sourceblock, itemstack)); ++ return itemstack; + } + }; +- DispenserBlock.registerBehavior(Items.CREEPER_HEAD, dispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.ZOMBIE_HEAD, dispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.DRAGON_HEAD, dispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.SKELETON_SKULL, dispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.PIGLIN_HEAD, dispenseItemBehavior1); +- DispenserBlock.registerBehavior(Items.PLAYER_HEAD, dispenseItemBehavior1); +- DispenserBlock.registerBehavior( +- Items.WITHER_SKELETON_SKULL, +- new OptionalDispenseItemBehavior() { +- @Override +- protected ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Level level = blockSource.level(); +- Direction direction = blockSource.state().getValue(DispenserBlock.FACING); +- BlockPos blockPos = blockSource.pos().relative(direction); +- if (level.isEmptyBlock(blockPos) && WitherSkullBlock.canSpawnMob(level, blockPos, itemStack)) { +- level.setBlock( +- blockPos, +- Blocks.WITHER_SKELETON_SKULL +- .defaultBlockState() +- .setValue(SkullBlock.ROTATION, Integer.valueOf(RotationSegment.convertToSegment(direction))), +- 3 +- ); +- level.gameEvent(null, GameEvent.BLOCK_PLACE, blockPos); +- BlockEntity blockEntity = level.getBlockEntity(blockPos); +- if (blockEntity instanceof SkullBlockEntity) { +- WitherSkullBlock.checkSpawn(level, blockPos, (SkullBlockEntity)blockEntity); +- } +- +- itemStack.shrink(1); +- this.setSuccess(true); +- } else { +- this.setSuccess(ArmorItem.dispenseArmor(blockSource, itemStack)); ++ ++ DispenserBlock.registerBehavior(Items.CREEPER_HEAD, dispensebehaviormaybe1); ++ DispenserBlock.registerBehavior(Items.ZOMBIE_HEAD, dispensebehaviormaybe1); ++ DispenserBlock.registerBehavior(Items.DRAGON_HEAD, dispensebehaviormaybe1); ++ DispenserBlock.registerBehavior(Items.SKELETON_SKULL, dispensebehaviormaybe1); ++ DispenserBlock.registerBehavior(Items.PIGLIN_HEAD, dispensebehaviormaybe1); ++ DispenserBlock.registerBehavior(Items.PLAYER_HEAD, dispensebehaviormaybe1); ++ DispenserBlock.registerBehavior(Items.WITHER_SKELETON_SKULL, new OptionalDispenseItemBehavior() { ++ @Override ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ BlockPos blockposition = sourceblock.pos().relative(enumdirection); ++ ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; + } +- +- return itemStack; + } ++ // CraftBukkit end ++ ++ if (worldserver.isEmptyBlock(blockposition) && WitherSkullBlock.canSpawnMob(worldserver, blockposition, itemstack)) { ++ worldserver.setBlock(blockposition, (IBlockData) Blocks.WITHER_SKELETON_SKULL.defaultBlockState().setValue(SkullBlock.ROTATION, RotationSegment.convertToSegment(enumdirection)), 3); ++ worldserver.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockposition); ++ BlockEntity tileentity = worldserver.getBlockEntity(blockposition); ++ ++ if (tileentity instanceof SkullBlockEntity) { ++ WitherSkullBlock.checkSpawn(worldserver, blockposition, (SkullBlockEntity) tileentity); ++ } ++ ++ itemstack.shrink(1); ++ this.setSuccess(true); ++ } else { ++ this.setSuccess(ArmorItem.dispenseArmor(sourceblock, itemstack)); ++ } ++ ++ return itemstack; + } +- ); ++ }); + DispenserBlock.registerBehavior(Blocks.CARVED_PUMPKIN, new OptionalDispenseItemBehavior() { + @Override +- protected ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Level level = blockSource.level(); +- BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); +- CarvedPumpkinBlock carvedPumpkinBlock = (CarvedPumpkinBlock)Blocks.CARVED_PUMPKIN; +- if (level.isEmptyBlock(blockPos) && carvedPumpkinBlock.canSpawnGolem(level, blockPos)) { +- if (!level.isClientSide) { +- level.setBlock(blockPos, carvedPumpkinBlock.defaultBlockState(), 3); +- level.gameEvent(null, GameEvent.BLOCK_PLACE, blockPos); ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ CarvedPumpkinBlock blockpumpkincarved = (CarvedPumpkinBlock) Blocks.CARVED_PUMPKIN; ++ ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; + } ++ } ++ // CraftBukkit end + +- itemStack.shrink(1); ++ if (worldserver.isEmptyBlock(blockposition) && blockpumpkincarved.canSpawnGolem(worldserver, blockposition)) { ++ if (!worldserver.isClientSide) { ++ worldserver.setBlock(blockposition, blockpumpkincarved.defaultBlockState(), 3); ++ worldserver.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockposition); ++ } ++ ++ itemstack.shrink(1); + this.setSuccess(true); + } else { +- this.setSuccess(ArmorItem.dispenseArmor(blockSource, itemStack)); ++ this.setSuccess(ArmorItem.dispenseArmor(sourceblock, itemstack)); + } + +- return itemStack; ++ return itemstack; + } + }); + DispenserBlock.registerBehavior(Blocks.SHULKER_BOX.asItem(), new ShulkerBoxDispenseBehavior()); ++ DyeColor[] aenumcolor = DyeColor.values(); ++ int i = aenumcolor.length; + +- for (DyeColor dyeColor : DyeColor.values()) { +- DispenserBlock.registerBehavior(ShulkerBoxBlock.getBlockByColor(dyeColor).asItem(), new ShulkerBoxDispenseBehavior()); ++ for (int j = 0; j < i; ++j) { ++ DyeColor enumcolor = aenumcolor[j]; ++ ++ DispenserBlock.registerBehavior(ShulkerBoxBlock.getBlockByColor(enumcolor).asItem(), new ShulkerBoxDispenseBehavior()); + } + +- DispenserBlock.registerBehavior( +- Items.GLASS_BOTTLE.asItem(), +- new OptionalDispenseItemBehavior() { +- private final DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior(); +- +- private ItemStack takeLiquid(BlockSource blockSource, ItemStack itemStack, ItemStack itemStack1) { +- itemStack.shrink(1); +- if (itemStack.isEmpty()) { +- blockSource.level().gameEvent(null, GameEvent.FLUID_PICKUP, blockSource.pos()); +- return itemStack1.copy(); +- } else { +- if (blockSource.blockEntity().addItem(itemStack1.copy()) < 0) { +- this.defaultDispenseItemBehavior.dispense(blockSource, itemStack1.copy()); +- } +- +- return itemStack; ++ DispenserBlock.registerBehavior(Items.GLASS_BOTTLE.asItem(), new OptionalDispenseItemBehavior() { ++ private final DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior(); ++ ++ private ItemStack takeLiquid(SourceBlock sourceblock, ItemStack itemstack, ItemStack itemstack1) { ++ itemstack.shrink(1); ++ if (itemstack.isEmpty()) { ++ sourceblock.level().gameEvent((Entity) null, GameEvent.FLUID_PICKUP, sourceblock.pos()); ++ return itemstack1.copy(); ++ } else { ++ if (sourceblock.blockEntity().addItem(itemstack1.copy()) < 0) { ++ this.defaultDispenseItemBehavior.dispense(sourceblock, itemstack1.copy()); + } ++ ++ return itemstack; + } +- +- @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- this.setSuccess(false); +- ServerLevel serverLevel = blockSource.level(); +- BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); +- BlockState blockState = serverLevel.getBlockState(blockPos); +- if (blockState.is(BlockTags.BEEHIVES, hive -> hive.hasProperty(BeehiveBlock.HONEY_LEVEL) && hive.getBlock() instanceof BeehiveBlock) +- && blockState.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) { +- ((BeehiveBlock)blockState.getBlock()) +- .releaseBeesAndResetHoneyLevel(serverLevel, blockState, blockPos, null, BeehiveBlockEntity.BeeReleaseStatus.BEE_RELEASED); +- this.setSuccess(true); +- return this.takeLiquid(blockSource, itemStack, new ItemStack(Items.HONEY_BOTTLE)); +- } else if (serverLevel.getFluidState(blockPos).is(FluidTags.WATER)) { +- this.setSuccess(true); +- return this.takeLiquid(blockSource, itemStack, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER)); +- } else { +- return super.execute(blockSource, itemStack); ++ } ++ ++ @Override ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ this.setSuccess(false); ++ ServerLevel worldserver = sourceblock.level(); ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; + } + } ++ // CraftBukkit end ++ ++ if (iblockdata.is(BlockTags.BEEHIVES, (blockbase_blockdata) -> { ++ return blockbase_blockdata.hasProperty(BeehiveBlock.HONEY_LEVEL) && blockbase_blockdata.getBlock() instanceof BeehiveBlock; ++ }) && (Integer) iblockdata.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) { ++ ((BeehiveBlock) iblockdata.getBlock()).releaseBeesAndResetHoneyLevel(worldserver, iblockdata, blockposition, (Player) null, BeehiveBlockEntity.ReleaseStatus.BEE_RELEASED); ++ this.setSuccess(true); ++ return this.takeLiquid(sourceblock, itemstack, new ItemStack(Items.HONEY_BOTTLE)); ++ } else if (worldserver.getFluidState(blockposition).is(FluidTags.WATER)) { ++ this.setSuccess(true); ++ return this.takeLiquid(sourceblock, itemstack, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.WATER)); ++ } else { ++ return super.execute(sourceblock, itemstack); ++ } + } +- ); ++ }); + DispenserBlock.registerBehavior(Items.GLOWSTONE, new OptionalDispenseItemBehavior() { + @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Direction direction = blockSource.state().getValue(DispenserBlock.FACING); +- BlockPos blockPos = blockSource.pos().relative(direction); +- Level level = blockSource.level(); +- BlockState blockState = level.getBlockState(blockPos); ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ BlockPos blockposition = sourceblock.pos().relative(enumdirection); ++ ServerLevel worldserver = sourceblock.level(); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ + this.setSuccess(true); +- if (blockState.is(Blocks.RESPAWN_ANCHOR)) { +- if (blockState.getValue(RespawnAnchorBlock.CHARGE) != 4) { +- RespawnAnchorBlock.charge(null, level, blockPos, blockState); +- itemStack.shrink(1); ++ if (iblockdata.is(Blocks.RESPAWN_ANCHOR)) { ++ if ((Integer) iblockdata.getValue(RespawnAnchorBlock.CHARGE) != 4) { ++ RespawnAnchorBlock.charge((Entity) null, worldserver, blockposition, iblockdata); ++ itemstack.shrink(1); + } else { + this.setSuccess(false); + } + +- return itemStack; ++ return itemstack; + } else { +- return super.execute(blockSource, itemStack); ++ return super.execute(sourceblock, itemstack); + } + } + }); + DispenserBlock.registerBehavior(Items.SHEARS.asItem(), new ShearsDispenseItemBehavior()); + DispenserBlock.registerBehavior(Items.HONEYCOMB, new OptionalDispenseItemBehavior() { + @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); +- Level level = blockSource.level(); +- BlockState blockState = level.getBlockState(blockPos); +- Optional waxed = HoneycombItem.getWaxed(blockState); +- if (waxed.isPresent()) { +- level.setBlockAndUpdate(blockPos, waxed.get()); +- level.levelEvent(3003, blockPos, 0); +- itemStack.shrink(1); ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ ServerLevel worldserver = sourceblock.level(); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ Optional optional = HoneycombItem.getWaxed(iblockdata); ++ ++ if (optional.isPresent()) { ++ worldserver.setBlockAndUpdate(blockposition, (IBlockData) optional.get()); ++ worldserver.levelEvent(3003, blockposition, 0); ++ itemstack.shrink(1); + this.setSuccess(true); +- return itemStack; ++ return itemstack; + } else { +- return super.execute(blockSource, itemStack); ++ return super.execute(sourceblock, itemstack); + } + } + }); +- DispenserBlock.registerBehavior( +- Items.POTION, +- new DefaultDispenseItemBehavior() { +- private final DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior(); +- +- @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- if (PotionUtils.getPotion(itemStack) != Potions.WATER) { +- return this.defaultDispenseItemBehavior.dispense(blockSource, itemStack); ++ DispenserBlock.registerBehavior(Items.POTION, new DefaultDispenseItemBehavior() { ++ private final DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior(); ++ ++ @Override ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ if (PotionUtils.getPotion(itemstack) != Potions.WATER) { ++ return this.defaultDispenseItemBehavior.dispense(sourceblock, itemstack); ++ } else { ++ ServerLevel worldserver = sourceblock.level(); ++ BlockPos blockposition = sourceblock.pos(); ++ BlockPos blockposition1 = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ ++ if (!worldserver.getBlockState(blockposition1).is(BlockTags.CONVERTABLE_TO_MUD)) { ++ return this.defaultDispenseItemBehavior.dispense(sourceblock, itemstack); + } else { +- ServerLevel serverLevel = blockSource.level(); +- BlockPos blockPos = blockSource.pos(); +- BlockPos blockPos1 = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); +- if (!serverLevel.getBlockState(blockPos1).is(BlockTags.CONVERTABLE_TO_MUD)) { +- return this.defaultDispenseItemBehavior.dispense(blockSource, itemStack); +- } else { +- if (!serverLevel.isClientSide) { +- for (int i = 0; i < 5; i++) { +- serverLevel.sendParticles( +- ParticleTypes.SPLASH, +- (double)blockPos.getX() + serverLevel.random.nextDouble(), +- (double)(blockPos.getY() + 1), +- (double)blockPos.getZ() + serverLevel.random.nextDouble(), +- 1, +- 0.0, +- 0.0, +- 0.0, +- 1.0 +- ); +- } ++ if (!worldserver.isClientSide) { ++ for (int k = 0; k < 5; ++k) { ++ worldserver.sendParticles(ParticleTypes.SPLASH, (double) blockposition.getX() + worldserver.random.nextDouble(), (double) (blockposition.getY() + 1), (double) blockposition.getZ() + worldserver.random.nextDouble(), 1, 0.0D, 0.0D, 0.0D, 1.0D); + } +- +- serverLevel.playSound(null, blockPos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); +- serverLevel.gameEvent(null, GameEvent.FLUID_PLACE, blockPos); +- serverLevel.setBlockAndUpdate(blockPos1, Blocks.MUD.defaultBlockState()); +- return new ItemStack(Items.GLASS_BOTTLE); + } ++ ++ worldserver.playSound((Player) null, blockposition, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); ++ worldserver.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockposition); ++ worldserver.setBlockAndUpdate(blockposition1, Blocks.MUD.defaultBlockState()); ++ return new ItemStack(Items.GLASS_BOTTLE); + } + } + } +- ); ++ }); + } + +- static Vec3 getEntityPokingOutOfBlockPos(BlockSource blockSource, EntityType entityType, Direction direction) { +- return blockSource.center() +- .add( +- (double)direction.getStepX() * (0.5000099999997474 - (double)entityType.getWidth() / 2.0), +- (double)direction.getStepY() * (0.5000099999997474 - (double)entityType.getHeight() / 2.0) - (double)entityType.getHeight() / 2.0, +- (double)direction.getStepZ() * (0.5000099999997474 - (double)entityType.getWidth() / 2.0) +- ); ++ static Vec3 getEntityPokingOutOfBlockPos(SourceBlock sourceblock, EntityType entitytypes, Direction enumdirection) { ++ return sourceblock.center().add((double) enumdirection.getStepX() * (0.5000099999997474D - (double) entitytypes.getWidth() / 2.0D), (double) enumdirection.getStepY() * (0.5000099999997474D - (double) entitytypes.getHeight() / 2.0D) - (double) entitytypes.getHeight() / 2.0D, (double) enumdirection.getStepZ() * (0.5000099999997474D - (double) entitytypes.getWidth() / 2.0D)); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java.patch b/patch-remap/mache-vineflower/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java.patch new file mode 100644 index 0000000000..5597de857b --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java.patch @@ -0,0 +1,144 @@ +--- a/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java ++++ b/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java +@@ -1,49 +1,89 @@ + package net.minecraft.core.dispenser; + ++import java.util.Iterator; ++import java.util.List; + import net.minecraft.core.BlockPos; ++import net.minecraft.core.Direction; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.tags.BlockTags; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Shearable; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.BeehiveBlock; + import net.minecraft.world.level.block.DispenserBlock; + import net.minecraft.world.level.block.entity.BeehiveBlockEntity; +-import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end + + public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior { ++ ++ public ShearsDispenseItemBehavior() {} ++ + @Override +- protected ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- ServerLevel serverLevel = blockSource.level(); +- if (!serverLevel.isClientSide()) { +- BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); +- this.setSuccess(tryShearBeehive(serverLevel, blockPos) || tryShearLivingEntity(serverLevel, blockPos)); +- if (this.isSuccess() && itemStack.hurt(1, serverLevel.getRandom(), null)) { +- itemStack.setCount(0); ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ ServerLevel worldserver = sourceblock.level(); ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; + } + } ++ // CraftBukkit end + +- return itemStack; ++ if (!worldserver.isClientSide()) { ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ ++ this.setSuccess(tryShearBeehive(worldserver, blockposition) || tryShearLivingEntity(worldserver, blockposition, bukkitBlock, craftItem)); // CraftBukkit ++ if (this.isSuccess() && itemstack.hurt(1, worldserver.getRandom(), (ServerPlayer) null)) { ++ itemstack.setCount(0); ++ } ++ } ++ ++ return itemstack; + } + + private static boolean tryShearBeehive(ServerLevel level, BlockPos pos) { +- BlockState blockState = level.getBlockState(pos); +- if (blockState.is( +- BlockTags.BEEHIVES, blockStateBase -> blockStateBase.hasProperty(BeehiveBlock.HONEY_LEVEL) && blockStateBase.getBlock() instanceof BeehiveBlock +- )) { +- int i = blockState.getValue(BeehiveBlock.HONEY_LEVEL); ++ IBlockData iblockdata = level.getBlockState(pos); ++ ++ if (iblockdata.is(BlockTags.BEEHIVES, (blockbase_blockdata) -> { ++ return blockbase_blockdata.hasProperty(BeehiveBlock.HONEY_LEVEL) && blockbase_blockdata.getBlock() instanceof BeehiveBlock; ++ })) { ++ int i = (Integer) iblockdata.getValue(BeehiveBlock.HONEY_LEVEL); ++ + if (i >= 5) { +- level.playSound(null, pos, SoundEvents.BEEHIVE_SHEAR, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.playSound((Player) null, pos, SoundEvents.BEEHIVE_SHEAR, SoundSource.BLOCKS, 1.0F, 1.0F); + BeehiveBlock.dropHoneycomb(level, pos); +- ((BeehiveBlock)blockState.getBlock()) +- .releaseBeesAndResetHoneyLevel(level, blockState, pos, null, BeehiveBlockEntity.BeeReleaseStatus.BEE_RELEASED); +- level.gameEvent(null, GameEvent.SHEAR, pos); ++ ((BeehiveBlock) iblockdata.getBlock()).releaseBeesAndResetHoneyLevel(level, iblockdata, pos, (Player) null, BeehiveBlockEntity.ReleaseStatus.BEE_RELEASED); ++ level.gameEvent((Entity) null, GameEvent.SHEAR, pos); + return true; + } + } +@@ -51,12 +91,26 @@ + return false; + } + +- private static boolean tryShearLivingEntity(ServerLevel level, BlockPos pos) { +- for (LivingEntity livingEntity : level.getEntitiesOfClass(LivingEntity.class, new AABB(pos), EntitySelector.NO_SPECTATORS)) { +- if (livingEntity instanceof Shearable shearable && shearable.readyForShearing()) { +- shearable.shear(SoundSource.BLOCKS); +- level.gameEvent(null, GameEvent.SHEAR, pos); +- return true; ++ private static boolean tryShearLivingEntity(ServerLevel worldserver, BlockPos blockposition, org.bukkit.block.Block bukkitBlock, CraftItemStack craftItem) { // CraftBukkit - add args ++ List list = worldserver.getEntitiesOfClass(LivingEntity.class, new AABB(blockposition), EntitySelector.NO_SPECTATORS); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ LivingEntity entityliving = (LivingEntity) iterator.next(); ++ ++ if (entityliving instanceof Shearable) { ++ Shearable ishearable = (Shearable) entityliving; ++ ++ if (ishearable.readyForShearing()) { ++ // CraftBukkit start ++ if (CraftEventFactory.callBlockShearEntityEvent(entityliving, bukkitBlock, craftItem).isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end ++ ishearable.shear(SoundSource.BLOCKS); ++ worldserver.gameEvent((Entity) null, GameEvent.SHEAR, blockposition); ++ return true; ++ } + } + } + diff --git a/patch-remap/mache-vineflower/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java.patch b/patch-remap/mache-vineflower/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java.patch new file mode 100644 index 0000000000..fc66914d24 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java.patch @@ -0,0 +1,73 @@ +--- a/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java ++++ b/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java +@@ -10,27 +10,59 @@ + import net.minecraft.world.level.block.DispenserBlock; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end ++ + public class ShulkerBoxDispenseBehavior extends OptionalDispenseItemBehavior { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + ++ public ShulkerBoxDispenseBehavior() {} ++ + @Override +- protected ItemStack execute(BlockSource blockSource, ItemStack itemStack) { ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { + this.setSuccess(false); +- Item item = itemStack.getItem(); ++ Item item = itemstack.getItem(); ++ + if (item instanceof BlockItem) { +- Direction direction = blockSource.state().getValue(DispenserBlock.FACING); +- BlockPos blockPos = blockSource.pos().relative(direction); +- Direction direction1 = blockSource.level().isEmptyBlock(blockPos.below()) ? direction : Direction.UP; ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ BlockPos blockposition = sourceblock.pos().relative(enumdirection); ++ Direction enumdirection1 = sourceblock.level().isEmptyBlock(blockposition.below()) ? enumdirection : Direction.UP; + ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(sourceblock.level(), sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!DispenserBlock.eventFired) { ++ sourceblock.level().getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ + try { +- this.setSuccess( +- ((BlockItem)item).place(new DirectionalPlaceContext(blockSource.level(), blockPos, direction, itemStack, direction1)).consumesAction() +- ); +- } catch (Exception var8) { +- LOGGER.error("Error trying to place shulker box at {}", blockPos, var8); ++ this.setSuccess(((BlockItem) item).place(new DirectionalPlaceContext(sourceblock.level(), blockposition, enumdirection, itemstack, enumdirection1)).consumesAction()); ++ } catch (Exception exception) { ++ ShulkerBoxDispenseBehavior.LOGGER.error("Error trying to place shulker box at {}", blockposition, exception); + } + } + +- return itemStack; ++ return itemstack; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/nbt/ByteArrayTag.java.patch b/patch-remap/mache-vineflower/net/minecraft/nbt/ByteArrayTag.java.patch new file mode 100644 index 0000000000..8f929c09f9 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/nbt/ByteArrayTag.java.patch @@ -0,0 +1,197 @@ +--- a/net/minecraft/nbt/ByteArrayTag.java ++++ b/net/minecraft/nbt/ByteArrayTag.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.nbt; + + import java.io.DataInput; +@@ -8,30 +9,33 @@ + import org.apache.commons.lang3.ArrayUtils; + + public class ByteArrayTag extends CollectionTag { ++ + private static final int SELF_SIZE_IN_BYTES = 24; +- public static final TagType TYPE = new TagType.VariableSize() { ++ public static final TagType TYPE = new TagType.b() { + @Override +- public ByteArrayTag load(DataInput dataInput, NbtAccounter nbtAccounter) throws IOException { +- return new ByteArrayTag(readAccounted(dataInput, nbtAccounter)); ++ public ByteArrayTag load(DataInput datainput, NbtAccounter nbtreadlimiter) throws IOException { ++ return new ByteArrayTag(readAccounted(datainput, nbtreadlimiter)); + } + + @Override +- public StreamTagVisitor.ValueResult parse(DataInput dataInput, StreamTagVisitor streamTagVisitor, NbtAccounter nbtAccounter) throws IOException { +- return streamTagVisitor.visit(readAccounted(dataInput, nbtAccounter)); ++ public StreamTagVisitor.b parse(DataInput datainput, StreamTagVisitor streamtagvisitor, NbtAccounter nbtreadlimiter) throws IOException { ++ return streamtagvisitor.visit(readAccounted(datainput, nbtreadlimiter)); + } + +- private static byte[] readAccounted(DataInput dataInput, NbtAccounter nbtAccounter) throws IOException { +- nbtAccounter.accountBytes(24L); +- int _int = dataInput.readInt(); +- nbtAccounter.accountBytes(1L, (long)_int); +- byte[] bytes = new byte[_int]; +- dataInput.readFully(bytes); +- return bytes; ++ private static byte[] readAccounted(DataInput datainput, NbtAccounter nbtreadlimiter) throws IOException { ++ nbtreadlimiter.accountBytes(24L); ++ int i = datainput.readInt(); ++ ++ nbtreadlimiter.accountBytes(1L, (long) i); ++ byte[] abyte = new byte[i]; ++ ++ datainput.readFully(abyte); ++ return abyte; + } + + @Override +- public void skip(DataInput dataInput, NbtAccounter nbtAccounter) throws IOException { +- dataInput.skipBytes(dataInput.readInt() * 1); ++ public void skip(DataInput datainput, NbtAccounter nbtreadlimiter) throws IOException { ++ datainput.skipBytes(datainput.readInt() * 1); + } + + @Override +@@ -50,19 +54,20 @@ + this.data = data; + } + +- public ByteArrayTag(List data) { +- this(toArray(data)); ++ public ByteArrayTag(List dataList) { ++ this(toArray(dataList)); + } + + private static byte[] toArray(List dataList) { +- byte[] bytes = new byte[dataList.size()]; ++ byte[] abyte = new byte[dataList.size()]; + +- for (int i = 0; i < dataList.size(); i++) { +- Byte _byte = dataList.get(i); +- bytes[i] = _byte == null ? 0 : _byte; ++ for (int i = 0; i < dataList.size(); ++i) { ++ Byte obyte = (Byte) dataList.get(i); ++ ++ abyte[i] = obyte == null ? 0 : obyte; + } + +- return bytes; ++ return abyte; + } + + @Override +@@ -83,7 +88,7 @@ + + @Override + public TagType getType() { +- return TYPE; ++ return ByteArrayTag.TYPE; + } + + @Override +@@ -93,17 +98,16 @@ + + @Override + public Tag copy() { +- byte[] bytes = new byte[this.data.length]; +- System.arraycopy(this.data, 0, bytes, 0, this.data.length); +- return new ByteArrayTag(bytes); ++ byte[] abyte = new byte[this.data.length]; ++ ++ System.arraycopy(this.data, 0, abyte, 0, this.data.length); ++ return new ByteArrayTag(abyte); + } + +- @Override +- public boolean equals(Object other) { +- return this == other || other instanceof ByteArrayTag && Arrays.equals(this.data, ((ByteArrayTag)other).data); ++ public boolean equals(Object object) { ++ return this == object ? true : object instanceof ByteArrayTag && Arrays.equals(this.data, ((ByteArrayTag) object).data); + } + +- @Override + public int hashCode() { + return Arrays.hashCode(this.data); + } +@@ -117,32 +121,29 @@ + return this.data; + } + +- @Override + public int size() { + return this.data.length; + } + +- @Override + public ByteTag get(int i) { + return ByteTag.valueOf(this.data[i]); + } + +- @Override +- public ByteTag set(int i, ByteTag byteTag) { +- byte b = this.data[i]; +- this.data[i] = byteTag.getAsByte(); +- return ByteTag.valueOf(b); ++ public ByteTag set(int i, ByteTag nbttagbyte) { ++ byte b0 = this.data[i]; ++ ++ this.data[i] = nbttagbyte.getAsByte(); ++ return ByteTag.valueOf(b0); + } + +- @Override +- public void add(int i, ByteTag byteTag) { +- this.data = ArrayUtils.add(this.data, i, byteTag.getAsByte()); ++ public void add(int i, ByteTag nbttagbyte) { ++ this.data = ArrayUtils.add(this.data, i, nbttagbyte.getAsByte()); + } + + @Override + public boolean setTag(int index, Tag nbt) { +- if (nbt instanceof NumericTag) { +- this.data[index] = ((NumericTag)nbt).getAsByte(); ++ if (nbt instanceof NBTNumber) { ++ this.data[index] = ((NBTNumber) nbt).getAsByte(); + return true; + } else { + return false; +@@ -151,8 +152,8 @@ + + @Override + public boolean addTag(int index, Tag nbt) { +- if (nbt instanceof NumericTag) { +- this.data = ArrayUtils.add(this.data, index, ((NumericTag)nbt).getAsByte()); ++ if (nbt instanceof NBTNumber) { ++ this.data = ArrayUtils.add(this.data, index, ((NBTNumber) nbt).getAsByte()); + return true; + } else { + return false; +@@ -161,9 +162,10 @@ + + @Override + public ByteTag remove(int i) { +- byte b = this.data[i]; ++ byte b0 = this.data[i]; ++ + this.data = ArrayUtils.remove(this.data, i); +- return ByteTag.valueOf(b); ++ return ByteTag.valueOf(b0); + } + + @Override +@@ -171,13 +173,12 @@ + return 1; + } + +- @Override + public void clear() { + this.data = new byte[0]; + } + + @Override +- public StreamTagVisitor.ValueResult accept(StreamTagVisitor visitor) { ++ public StreamTagVisitor.b accept(StreamTagVisitor visitor) { + return visitor.visit(this.data); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/nbt/IntArrayTag.java.patch b/patch-remap/mache-vineflower/net/minecraft/nbt/IntArrayTag.java.patch new file mode 100644 index 0000000000..2020ecc472 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/nbt/IntArrayTag.java.patch @@ -0,0 +1,217 @@ +--- a/net/minecraft/nbt/IntArrayTag.java ++++ b/net/minecraft/nbt/IntArrayTag.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.nbt; + + import java.io.DataInput; +@@ -8,34 +9,36 @@ + import org.apache.commons.lang3.ArrayUtils; + + public class IntArrayTag extends CollectionTag { ++ + private static final int SELF_SIZE_IN_BYTES = 24; +- public static final TagType TYPE = new TagType.VariableSize() { ++ public static final TagType TYPE = new TagType.b() { + @Override +- public IntArrayTag load(DataInput dataInput, NbtAccounter nbtAccounter) throws IOException { +- return new IntArrayTag(readAccounted(dataInput, nbtAccounter)); ++ public IntArrayTag load(DataInput datainput, NbtAccounter nbtreadlimiter) throws IOException { ++ return new IntArrayTag(readAccounted(datainput, nbtreadlimiter)); + } + + @Override +- public StreamTagVisitor.ValueResult parse(DataInput dataInput, StreamTagVisitor streamTagVisitor, NbtAccounter nbtAccounter) throws IOException { +- return streamTagVisitor.visit(readAccounted(dataInput, nbtAccounter)); ++ public StreamTagVisitor.b parse(DataInput datainput, StreamTagVisitor streamtagvisitor, NbtAccounter nbtreadlimiter) throws IOException { ++ return streamtagvisitor.visit(readAccounted(datainput, nbtreadlimiter)); + } + +- private static int[] readAccounted(DataInput dataInput, NbtAccounter nbtAccounter) throws IOException { +- nbtAccounter.accountBytes(24L); +- int _int = dataInput.readInt(); +- nbtAccounter.accountBytes(4L, (long)_int); +- int[] ints = new int[_int]; ++ private static int[] readAccounted(DataInput datainput, NbtAccounter nbtreadlimiter) throws IOException { ++ nbtreadlimiter.accountBytes(24L); ++ int i = datainput.readInt(); + +- for (int i = 0; i < _int; i++) { +- ints[i] = dataInput.readInt(); ++ nbtreadlimiter.accountBytes(4L, (long) i); ++ int[] aint = new int[i]; ++ ++ for (int j = 0; j < i; ++j) { ++ aint[j] = datainput.readInt(); + } + +- return ints; ++ return aint; + } + + @Override +- public void skip(DataInput dataInput, NbtAccounter nbtAccounter) throws IOException { +- dataInput.skipBytes(dataInput.readInt() * 4); ++ public void skip(DataInput datainput, NbtAccounter nbtreadlimiter) throws IOException { ++ datainput.skipBytes(datainput.readInt() * 4); + } + + @Override +@@ -54,28 +57,34 @@ + this.data = data; + } + +- public IntArrayTag(List data) { +- this(toArray(data)); ++ public IntArrayTag(List dataList) { ++ this(toArray(dataList)); + } + + private static int[] toArray(List dataList) { +- int[] ints = new int[dataList.size()]; ++ int[] aint = new int[dataList.size()]; + +- for (int i = 0; i < dataList.size(); i++) { +- Integer integer = dataList.get(i); +- ints[i] = integer == null ? 0 : integer; ++ for (int i = 0; i < dataList.size(); ++i) { ++ Integer integer = (Integer) dataList.get(i); ++ ++ aint[i] = integer == null ? 0 : integer; + } + +- return ints; ++ return aint; + } + + @Override + public void write(DataOutput output) throws IOException { + output.writeInt(this.data.length); ++ int[] aint = this.data; ++ int i = aint.length; + +- for (int i : this.data) { +- output.writeInt(i); ++ for (int j = 0; j < i; ++j) { ++ int k = aint[j]; ++ ++ output.writeInt(k); + } ++ + } + + @Override +@@ -90,7 +99,7 @@ + + @Override + public TagType getType() { +- return TYPE; ++ return IntArrayTag.TYPE; + } + + @Override +@@ -100,17 +109,16 @@ + + @Override + public IntArrayTag copy() { +- int[] ints = new int[this.data.length]; +- System.arraycopy(this.data, 0, ints, 0, this.data.length); +- return new IntArrayTag(ints); ++ int[] aint = new int[this.data.length]; ++ ++ System.arraycopy(this.data, 0, aint, 0, this.data.length); ++ return new IntArrayTag(aint); + } + +- @Override +- public boolean equals(Object other) { +- return this == other || other instanceof IntArrayTag && Arrays.equals(this.data, ((IntArrayTag)other).data); ++ public boolean equals(Object object) { ++ return this == object ? true : object instanceof IntArrayTag && Arrays.equals(this.data, ((IntArrayTag) object).data); + } + +- @Override + public int hashCode() { + return Arrays.hashCode(this.data); + } +@@ -124,32 +132,29 @@ + visitor.visitIntArray(this); + } + +- @Override + public int size() { + return this.data.length; + } + +- @Override + public IntTag get(int i) { + return IntTag.valueOf(this.data[i]); + } + +- @Override +- public IntTag set(int i, IntTag intTag) { +- int i1 = this.data[i]; +- this.data[i] = intTag.getAsInt(); +- return IntTag.valueOf(i1); ++ public IntTag set(int i, IntTag nbttagint) { ++ int j = this.data[i]; ++ ++ this.data[i] = nbttagint.getAsInt(); ++ return IntTag.valueOf(j); + } + +- @Override +- public void add(int i, IntTag intTag) { +- this.data = ArrayUtils.add(this.data, i, intTag.getAsInt()); ++ public void add(int i, IntTag nbttagint) { ++ this.data = ArrayUtils.add(this.data, i, nbttagint.getAsInt()); + } + + @Override + public boolean setTag(int index, Tag nbt) { +- if (nbt instanceof NumericTag) { +- this.data[index] = ((NumericTag)nbt).getAsInt(); ++ if (nbt instanceof NBTNumber) { ++ this.data[index] = ((NBTNumber) nbt).getAsInt(); + return true; + } else { + return false; +@@ -158,8 +163,8 @@ + + @Override + public boolean addTag(int index, Tag nbt) { +- if (nbt instanceof NumericTag) { +- this.data = ArrayUtils.add(this.data, index, ((NumericTag)nbt).getAsInt()); ++ if (nbt instanceof NBTNumber) { ++ this.data = ArrayUtils.add(this.data, index, ((NBTNumber) nbt).getAsInt()); + return true; + } else { + return false; +@@ -168,9 +173,10 @@ + + @Override + public IntTag remove(int i) { +- int i1 = this.data[i]; ++ int j = this.data[i]; ++ + this.data = ArrayUtils.remove(this.data, i); +- return IntTag.valueOf(i1); ++ return IntTag.valueOf(j); + } + + @Override +@@ -178,13 +184,12 @@ + return 3; + } + +- @Override + public void clear() { + this.data = new int[0]; + } + + @Override +- public StreamTagVisitor.ValueResult accept(StreamTagVisitor visitor) { ++ public StreamTagVisitor.b accept(StreamTagVisitor visitor) { + return visitor.visit(this.data); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/nbt/NbtIo.java.patch b/patch-remap/mache-vineflower/net/minecraft/nbt/NbtIo.java.patch new file mode 100644 index 0000000000..fae3c9ea36 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/nbt/NbtIo.java.patch @@ -0,0 +1,473 @@ +--- a/net/minecraft/nbt/NbtIo.java ++++ b/net/minecraft/nbt/NbtIo.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.nbt; + + import java.io.BufferedOutputStream; +@@ -10,6 +11,7 @@ + import java.io.OutputStream; + import java.io.UTFDataFormatException; + import java.nio.file.Files; ++import java.nio.file.LinkOption; + import java.nio.file.OpenOption; + import java.nio.file.Path; + import java.nio.file.StandardOpenOption; +@@ -23,87 +25,270 @@ + import net.minecraft.util.FastBufferedInputStream; + + public class NbtIo { +- private static final OpenOption[] SYNC_OUTPUT_OPTIONS = new OpenOption[]{ +- StandardOpenOption.SYNC, StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING +- }; + +- public static CompoundTag readCompressed(Path path, NbtAccounter nbtAccounter) throws IOException { +- CompoundTag var3; +- try (InputStream inputStream = Files.newInputStream(path)) { +- var3 = readCompressed(inputStream, nbtAccounter); ++ private static final OpenOption[] SYNC_OUTPUT_OPTIONS = new OpenOption[]{StandardOpenOption.SYNC, StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING}; ++ ++ public NbtIo() {} ++ ++ public static CompoundTag readCompressed(Path path, NbtAccounter nbtreadlimiter) throws IOException { ++ InputStream inputstream = Files.newInputStream(path); ++ ++ CompoundTag nbttagcompound; ++ ++ try { ++ nbttagcompound = readCompressed(inputstream, nbtreadlimiter); ++ } catch (Throwable throwable) { ++ if (inputstream != null) { ++ try { ++ inputstream.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } + +- return var3; ++ if (inputstream != null) { ++ inputstream.close(); ++ } ++ ++ return nbttagcompound; + } + + private static DataInputStream createDecompressorStream(InputStream zippedStream) throws IOException { + return new DataInputStream(new FastBufferedInputStream(new GZIPInputStream(zippedStream))); + } + +- private static DataOutputStream createCompressorStream(OutputStream outputStream) throws IOException { +- return new DataOutputStream(new BufferedOutputStream(new GZIPOutputStream(outputStream))); ++ private static DataOutputStream createCompressorStream(OutputStream outputstream) throws IOException { ++ return new DataOutputStream(new BufferedOutputStream(new GZIPOutputStream(outputstream))); + } + +- public static CompoundTag readCompressed(InputStream inputStream, NbtAccounter nbtAccounter) throws IOException { +- CompoundTag var3; +- try (DataInputStream dataInputStream = createDecompressorStream(inputStream)) { +- var3 = read(dataInputStream, nbtAccounter); ++ public static CompoundTag readCompressed(InputStream inputstream, NbtAccounter nbtreadlimiter) throws IOException { ++ DataInputStream datainputstream = createDecompressorStream(inputstream); ++ ++ CompoundTag nbttagcompound; ++ ++ try { ++ nbttagcompound = read(datainputstream, nbtreadlimiter); ++ } catch (Throwable throwable) { ++ if (datainputstream != null) { ++ try { ++ datainputstream.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } + +- return var3; ++ if (datainputstream != null) { ++ datainputstream.close(); ++ } ++ ++ return nbttagcompound; + } + +- public static void parseCompressed(Path path, StreamTagVisitor streamTagVisitor, NbtAccounter nbtAccounter) throws IOException { +- try (InputStream inputStream = Files.newInputStream(path)) { +- parseCompressed(inputStream, streamTagVisitor, nbtAccounter); ++ public static void parseCompressed(Path path, StreamTagVisitor streamtagvisitor, NbtAccounter nbtreadlimiter) throws IOException { ++ InputStream inputstream = Files.newInputStream(path); ++ ++ try { ++ parseCompressed(inputstream, streamtagvisitor, nbtreadlimiter); ++ } catch (Throwable throwable) { ++ if (inputstream != null) { ++ try { ++ inputstream.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } ++ ++ if (inputstream != null) { ++ inputstream.close(); ++ } ++ + } + +- public static void parseCompressed(InputStream inputStream, StreamTagVisitor streamTagVisitor, NbtAccounter nbtAccounter) throws IOException { +- try (DataInputStream dataInputStream = createDecompressorStream(inputStream)) { +- parse(dataInputStream, streamTagVisitor, nbtAccounter); ++ public static void parseCompressed(InputStream inputstream, StreamTagVisitor streamtagvisitor, NbtAccounter nbtreadlimiter) throws IOException { ++ DataInputStream datainputstream = createDecompressorStream(inputstream); ++ ++ try { ++ parse(datainputstream, streamtagvisitor, nbtreadlimiter); ++ } catch (Throwable throwable) { ++ if (datainputstream != null) { ++ try { ++ datainputstream.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } ++ ++ if (datainputstream != null) { ++ datainputstream.close(); ++ } ++ + } + +- public static void writeCompressed(CompoundTag compoundTag, Path path) throws IOException { +- try ( +- OutputStream outputStream = Files.newOutputStream(path, SYNC_OUTPUT_OPTIONS); +- OutputStream outputStream1 = new BufferedOutputStream(outputStream); +- ) { +- writeCompressed(compoundTag, outputStream1); ++ public static void writeCompressed(CompoundTag nbttagcompound, Path path) throws IOException { ++ OutputStream outputstream = Files.newOutputStream(path, NbtIo.SYNC_OUTPUT_OPTIONS); ++ ++ try { ++ BufferedOutputStream bufferedoutputstream = new BufferedOutputStream(outputstream); ++ ++ try { ++ writeCompressed(nbttagcompound, (OutputStream) bufferedoutputstream); ++ } catch (Throwable throwable) { ++ try { ++ bufferedoutputstream.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ ++ throw throwable; ++ } ++ ++ bufferedoutputstream.close(); ++ } catch (Throwable throwable2) { ++ if (outputstream != null) { ++ try { ++ outputstream.close(); ++ } catch (Throwable throwable3) { ++ throwable2.addSuppressed(throwable3); ++ } ++ } ++ ++ throw throwable2; + } ++ ++ if (outputstream != null) { ++ outputstream.close(); ++ } ++ + } + + public static void writeCompressed(CompoundTag compoundTag, OutputStream outputStream) throws IOException { +- try (DataOutputStream dataOutputStream = createCompressorStream(outputStream)) { +- write(compoundTag, dataOutputStream); ++ DataOutputStream dataoutputstream = createCompressorStream(outputStream); ++ ++ try { ++ write(compoundTag, (DataOutput) dataoutputstream); ++ } catch (Throwable throwable) { ++ if (dataoutputstream != null) { ++ try { ++ dataoutputstream.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } ++ ++ if (dataoutputstream != null) { ++ dataoutputstream.close(); ++ } ++ + } + +- public static void write(CompoundTag compoundTag, Path path) throws IOException { +- try ( +- OutputStream outputStream = Files.newOutputStream(path, SYNC_OUTPUT_OPTIONS); +- OutputStream outputStream1 = new BufferedOutputStream(outputStream); +- DataOutputStream dataOutputStream = new DataOutputStream(outputStream1); +- ) { +- write(compoundTag, dataOutputStream); ++ public static void write(CompoundTag nbttagcompound, Path path) throws IOException { ++ OutputStream outputstream = Files.newOutputStream(path, NbtIo.SYNC_OUTPUT_OPTIONS); ++ ++ try { ++ BufferedOutputStream bufferedoutputstream = new BufferedOutputStream(outputstream); ++ ++ try { ++ DataOutputStream dataoutputstream = new DataOutputStream(bufferedoutputstream); ++ ++ try { ++ write(nbttagcompound, (DataOutput) dataoutputstream); ++ } catch (Throwable throwable) { ++ try { ++ dataoutputstream.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ ++ throw throwable; ++ } ++ ++ dataoutputstream.close(); ++ } catch (Throwable throwable2) { ++ try { ++ bufferedoutputstream.close(); ++ } catch (Throwable throwable3) { ++ throwable2.addSuppressed(throwable3); ++ } ++ ++ throw throwable2; ++ } ++ ++ bufferedoutputstream.close(); ++ } catch (Throwable throwable4) { ++ if (outputstream != null) { ++ try { ++ outputstream.close(); ++ } catch (Throwable throwable5) { ++ throwable4.addSuppressed(throwable5); ++ } ++ } ++ ++ throw throwable4; + } ++ ++ if (outputstream != null) { ++ outputstream.close(); ++ } ++ + } + + @Nullable + public static CompoundTag read(Path path) throws IOException { +- if (!Files.exists(path)) { ++ if (!Files.exists(path, new LinkOption[0])) { + return null; + } else { +- CompoundTag var3; +- try ( +- InputStream inputStream = Files.newInputStream(path); +- DataInputStream dataInputStream = new DataInputStream(inputStream); +- ) { +- var3 = read(dataInputStream, NbtAccounter.unlimitedHeap()); ++ InputStream inputstream = Files.newInputStream(path); ++ ++ CompoundTag nbttagcompound; ++ ++ try { ++ DataInputStream datainputstream = new DataInputStream(inputstream); ++ ++ try { ++ nbttagcompound = read(datainputstream, NbtAccounter.unlimitedHeap()); ++ } catch (Throwable throwable) { ++ try { ++ datainputstream.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ ++ throw throwable; ++ } ++ ++ datainputstream.close(); ++ } catch (Throwable throwable2) { ++ if (inputstream != null) { ++ try { ++ inputstream.close(); ++ } catch (Throwable throwable3) { ++ throwable2.addSuppressed(throwable3); ++ } ++ } ++ ++ throw throwable2; + } + +- return var3; ++ if (inputstream != null) { ++ inputstream.close(); ++ } ++ ++ return nbttagcompound; + } + } + +@@ -112,9 +297,10 @@ + } + + public static CompoundTag read(DataInput input, NbtAccounter accounter) throws IOException { +- Tag unnamedTag = readUnnamedTag(input, accounter); +- if (unnamedTag instanceof CompoundTag) { +- return (CompoundTag)unnamedTag; ++ Tag nbtbase = readUnnamedTag(input, accounter); ++ ++ if (nbtbase instanceof CompoundTag) { ++ return (CompoundTag) nbtbase; + } else { + throw new IOException("Root tag must be a named compound tag"); + } +@@ -124,37 +310,41 @@ + writeUnnamedTagWithFallback(compoundTag, output); + } + +- public static void parse(DataInput dataInput, StreamTagVisitor streamTagVisitor, NbtAccounter nbtAccounter) throws IOException { +- TagType type = TagTypes.getType(dataInput.readByte()); +- if (type == EndTag.TYPE) { +- if (streamTagVisitor.visitRootEntry(EndTag.TYPE) == StreamTagVisitor.ValueResult.CONTINUE) { +- streamTagVisitor.visitEnd(); ++ public static void parse(DataInput datainput, StreamTagVisitor streamtagvisitor, NbtAccounter nbtreadlimiter) throws IOException { ++ TagType nbttagtype = TagTypes.getType(datainput.readByte()); ++ ++ if (nbttagtype == EndTag.TYPE) { ++ if (streamtagvisitor.visitRootEntry(EndTag.TYPE) == StreamTagVisitor.b.CONTINUE) { ++ streamtagvisitor.visitEnd(); + } ++ + } else { +- switch (streamTagVisitor.visitRootEntry(type)) { ++ switch (streamtagvisitor.visitRootEntry(nbttagtype)) { + case HALT: + default: + break; + case BREAK: +- StringTag.skipString(dataInput); +- type.skip(dataInput, nbtAccounter); ++ StringTag.skipString(datainput); ++ nbttagtype.skip(datainput, nbtreadlimiter); + break; + case CONTINUE: +- StringTag.skipString(dataInput); +- type.parse(dataInput, streamTagVisitor, nbtAccounter); ++ StringTag.skipString(datainput); ++ nbttagtype.parse(datainput, streamtagvisitor, nbtreadlimiter); + } ++ + } + } + +- public static Tag readAnyTag(DataInput dataInput, NbtAccounter nbtAccounter) throws IOException { +- byte _byte = dataInput.readByte(); +- return (Tag)(_byte == 0 ? EndTag.INSTANCE : readTagSafe(dataInput, nbtAccounter, _byte)); ++ public static Tag readAnyTag(DataInput datainput, NbtAccounter nbtreadlimiter) throws IOException { ++ byte b0 = datainput.readByte(); ++ ++ return (Tag) (b0 == 0 ? EndTag.INSTANCE : readTagSafe(datainput, nbtreadlimiter, b0)); + } + +- public static void writeAnyTag(Tag tag, DataOutput dataOutput) throws IOException { +- dataOutput.writeByte(tag.getId()); +- if (tag.getId() != 0) { +- tag.write(dataOutput); ++ public static void writeAnyTag(Tag nbtbase, DataOutput dataoutput) throws IOException { ++ dataoutput.writeByte(nbtbase.getId()); ++ if (nbtbase.getId() != 0) { ++ nbtbase.write(dataoutput); + } + } + +@@ -166,44 +356,48 @@ + } + } + +- public static void writeUnnamedTagWithFallback(Tag tag, DataOutput dataOutput) throws IOException { +- writeUnnamedTag(tag, new NbtIo.StringFallbackDataOutput(dataOutput)); ++ public static void writeUnnamedTagWithFallback(Tag nbtbase, DataOutput dataoutput) throws IOException { ++ writeUnnamedTag(nbtbase, new NbtIo.a(dataoutput)); + } + +- private static Tag readUnnamedTag(DataInput dataInput, NbtAccounter nbtAccounter) throws IOException { +- byte _byte = dataInput.readByte(); +- if (_byte == 0) { ++ private static Tag readUnnamedTag(DataInput datainput, NbtAccounter nbtreadlimiter) throws IOException { ++ byte b0 = datainput.readByte(); ++ ++ if (b0 == 0) { + return EndTag.INSTANCE; + } else { +- StringTag.skipString(dataInput); +- return readTagSafe(dataInput, nbtAccounter, _byte); ++ StringTag.skipString(datainput); ++ return readTagSafe(datainput, nbtreadlimiter, b0); + } + } + +- private static Tag readTagSafe(DataInput dataInput, NbtAccounter nbtAccounter, byte b) { ++ private static Tag readTagSafe(DataInput datainput, NbtAccounter nbtreadlimiter, byte b0) { + try { +- return TagTypes.getType(b).load(dataInput, nbtAccounter); +- } catch (IOException var6) { +- CrashReport crashReport = CrashReport.forThrowable(var6, "Loading NBT data"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("NBT Tag"); +- crashReportCategory.setDetail("Tag type", b); +- throw new ReportedNbtException(crashReport); ++ return TagTypes.getType(b0).load(datainput, nbtreadlimiter); ++ } catch (IOException ioexception) { ++ CrashReport crashreport = CrashReport.forThrowable(ioexception, "Loading NBT data"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("NBT Tag"); ++ ++ crashreportsystemdetails.setDetail("Tag type", (Object) b0); ++ throw new ReportedNbtException(crashreport); + } + } + +- public static class StringFallbackDataOutput extends DelegateDataOutput { +- public StringFallbackDataOutput(DataOutput dataOutput) { +- super(dataOutput); ++ public static class a extends DelegateDataOutput { ++ ++ public a(DataOutput dataoutput) { ++ super(dataoutput); + } + + @Override +- public void writeUTF(String string) throws IOException { ++ public void writeUTF(String s) throws IOException { + try { +- super.writeUTF(string); +- } catch (UTFDataFormatException var3) { +- Util.logAndPauseIfInIde("Failed to write NBT String", var3); ++ super.writeUTF(s); ++ } catch (UTFDataFormatException utfdataformatexception) { ++ Util.logAndPauseIfInIde("Failed to write NBT String", utfdataformatexception); + super.writeUTF(""); + } ++ + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/network/Connection.java.patch b/patch-remap/mache-vineflower/net/minecraft/network/Connection.java.patch new file mode 100644 index 0000000000..a6d2bea9d7 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/network/Connection.java.patch @@ -0,0 +1,697 @@ +--- a/net/minecraft/network/Connection.java ++++ b/net/minecraft/network/Connection.java +@@ -9,6 +9,7 @@ + import io.netty.channel.ChannelException; + import io.netty.channel.ChannelFuture; + import io.netty.channel.ChannelFutureListener; ++import io.netty.channel.ChannelHandler; + import io.netty.channel.ChannelHandlerContext; + import io.netty.channel.ChannelInitializer; + import io.netty.channel.ChannelOption; +@@ -28,7 +29,6 @@ + import io.netty.handler.timeout.ReadTimeoutHandler; + import io.netty.handler.timeout.TimeoutException; + import io.netty.util.AttributeKey; +-import io.netty.util.concurrent.Future; + import java.net.InetSocketAddress; + import java.net.SocketAddress; + import java.util.Objects; +@@ -41,6 +41,7 @@ + import net.minecraft.SharedConstants; + import net.minecraft.Util; + import net.minecraft.network.chat.Component; ++import net.minecraft.network.chat.MutableComponent; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.PacketFlow; + import net.minecraft.network.protocol.common.ClientboundDisconnectPacket; +@@ -49,7 +50,7 @@ + import net.minecraft.network.protocol.login.ClientLoginPacketListener; + import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket; + import net.minecraft.network.protocol.status.ClientStatusPacketListener; +-import net.minecraft.server.RunningOnDifferentThreadException; ++import net.minecraft.server.CancelledPacketHandleException; + import net.minecraft.util.Mth; + import net.minecraft.util.SampleLogger; + import org.apache.commons.lang3.Validate; +@@ -58,27 +59,34 @@ + import org.slf4j.MarkerFactory; + + public class Connection extends SimpleChannelInboundHandler> { ++ + private static final float AVERAGE_PACKETS_SMOOTHING = 0.75F; + private static final Logger LOGGER = LogUtils.getLogger(); + public static final Marker ROOT_MARKER = MarkerFactory.getMarker("NETWORK"); +- public static final Marker PACKET_MARKER = Util.make(MarkerFactory.getMarker("NETWORK_PACKETS"), marker -> marker.add(ROOT_MARKER)); +- public static final Marker PACKET_RECEIVED_MARKER = Util.make(MarkerFactory.getMarker("PACKET_RECEIVED"), marker -> marker.add(PACKET_MARKER)); +- public static final Marker PACKET_SENT_MARKER = Util.make(MarkerFactory.getMarker("PACKET_SENT"), marker -> marker.add(PACKET_MARKER)); +- public static final AttributeKey> ATTRIBUTE_SERVERBOUND_PROTOCOL = AttributeKey.valueOf("serverbound_protocol"); +- public static final AttributeKey> ATTRIBUTE_CLIENTBOUND_PROTOCOL = AttributeKey.valueOf("clientbound_protocol"); +- public static final Supplier NETWORK_WORKER_GROUP = Suppliers.memoize( +- () -> new NioEventLoopGroup(0, new ThreadFactoryBuilder().setNameFormat("Netty Client IO #%d").setDaemon(true).build()) +- ); +- public static final Supplier NETWORK_EPOLL_WORKER_GROUP = Suppliers.memoize( +- () -> new EpollEventLoopGroup(0, new ThreadFactoryBuilder().setNameFormat("Netty Epoll Client IO #%d").setDaemon(true).build()) +- ); +- public static final Supplier LOCAL_WORKER_GROUP = Suppliers.memoize( +- () -> new DefaultEventLoopGroup(0, new ThreadFactoryBuilder().setNameFormat("Netty Local Client IO #%d").setDaemon(true).build()) +- ); ++ public static final Marker PACKET_MARKER = (Marker) Util.make(MarkerFactory.getMarker("NETWORK_PACKETS"), (marker) -> { ++ marker.add(Connection.ROOT_MARKER); ++ }); ++ public static final Marker PACKET_RECEIVED_MARKER = (Marker) Util.make(MarkerFactory.getMarker("PACKET_RECEIVED"), (marker) -> { ++ marker.add(Connection.PACKET_MARKER); ++ }); ++ public static final Marker PACKET_SENT_MARKER = (Marker) Util.make(MarkerFactory.getMarker("PACKET_SENT"), (marker) -> { ++ marker.add(Connection.PACKET_MARKER); ++ }); ++ public static final AttributeKey> ATTRIBUTE_SERVERBOUND_PROTOCOL = AttributeKey.valueOf("serverbound_protocol"); ++ public static final AttributeKey> ATTRIBUTE_CLIENTBOUND_PROTOCOL = AttributeKey.valueOf("clientbound_protocol"); ++ public static final Supplier NETWORK_WORKER_GROUP = Suppliers.memoize(() -> { ++ return new NioEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Client IO #%d").setDaemon(true).build()); ++ }); ++ public static final Supplier NETWORK_EPOLL_WORKER_GROUP = Suppliers.memoize(() -> { ++ return new EpollEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Epoll Client IO #%d").setDaemon(true).build()); ++ }); ++ public static final Supplier LOCAL_WORKER_GROUP = Suppliers.memoize(() -> { ++ return new DefaultEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Local Client IO #%d").setDaemon(true).build()); ++ }); + private final PacketFlow receiving; + private final Queue> pendingActions = Queues.newConcurrentLinkedQueue(); +- private Channel channel; +- private SocketAddress address; ++ public Channel channel; ++ public SocketAddress address; + @Nullable + private volatile PacketListener disconnectListener; + @Nullable +@@ -97,92 +105,97 @@ + private volatile Component delayedDisconnect; + @Nullable + BandwidthDebugMonitor bandwidthDebugMonitor; ++ public String hostname = ""; // CraftBukkit - add field + + public Connection(PacketFlow receiving) { + this.receiving = receiving; + } + +- @Override +- public void channelActive(ChannelHandlerContext context) throws Exception { +- super.channelActive(context); +- this.channel = context.channel(); ++ public void channelActive(ChannelHandlerContext channelhandlercontext) throws Exception { ++ super.channelActive(channelhandlercontext); ++ this.channel = channelhandlercontext.channel(); + this.address = this.channel.remoteAddress(); + if (this.delayedDisconnect != null) { + this.disconnect(this.delayedDisconnect); + } ++ + } + + public static void setInitialProtocolAttributes(Channel channel) { +- channel.attr(ATTRIBUTE_SERVERBOUND_PROTOCOL).set(ConnectionProtocol.HANDSHAKING.codec(PacketFlow.SERVERBOUND)); +- channel.attr(ATTRIBUTE_CLIENTBOUND_PROTOCOL).set(ConnectionProtocol.HANDSHAKING.codec(PacketFlow.CLIENTBOUND)); ++ channel.attr(Connection.ATTRIBUTE_SERVERBOUND_PROTOCOL).set(ConnectionProtocol.HANDSHAKING.codec(PacketFlow.SERVERBOUND)); ++ channel.attr(Connection.ATTRIBUTE_CLIENTBOUND_PROTOCOL).set(ConnectionProtocol.HANDSHAKING.codec(PacketFlow.CLIENTBOUND)); + } + +- @Override +- public void channelInactive(ChannelHandlerContext context) { ++ public void channelInactive(ChannelHandlerContext channelhandlercontext) { + this.disconnect(Component.translatable("disconnect.endOfStream")); + } + +- @Override +- public void exceptionCaught(ChannelHandlerContext context, Throwable exception) { +- if (exception instanceof SkipPacketException) { +- LOGGER.debug("Skipping packet due to errors", exception.getCause()); ++ public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) { ++ if (throwable instanceof SkipPacketException) { ++ Connection.LOGGER.debug("Skipping packet due to errors", throwable.getCause()); + } else { + boolean flag = !this.handlingFault; ++ + this.handlingFault = true; + if (this.channel.isOpen()) { +- if (exception instanceof TimeoutException) { +- LOGGER.debug("Timeout", exception); ++ if (throwable instanceof TimeoutException) { ++ Connection.LOGGER.debug("Timeout", throwable); + this.disconnect(Component.translatable("disconnect.timeout")); + } else { +- Component component = Component.translatable("disconnect.genericReason", "Internal Exception: " + exception); ++ MutableComponent ichatmutablecomponent = Component.translatable("disconnect.genericReason", "Internal Exception: " + throwable); ++ + if (flag) { +- LOGGER.debug("Failed to sent packet", exception); ++ Connection.LOGGER.debug("Failed to sent packet", throwable); + if (this.getSending() == PacketFlow.CLIENTBOUND) { +- ConnectionProtocol connectionProtocol = this.channel.attr(ATTRIBUTE_CLIENTBOUND_PROTOCOL).get().protocol(); +- Packet packet = (Packet)(connectionProtocol == ConnectionProtocol.LOGIN +- ? new ClientboundLoginDisconnectPacket(component) +- : new ClientboundDisconnectPacket(component)); +- this.send(packet, PacketSendListener.thenRun(() -> this.disconnect(component))); ++ ConnectionProtocol enumprotocol = ((ConnectionProtocol.a) this.channel.attr(Connection.ATTRIBUTE_CLIENTBOUND_PROTOCOL).get()).protocol(); ++ Packet packet = enumprotocol == ConnectionProtocol.LOGIN ? new ClientboundLoginDisconnectPacket(ichatmutablecomponent) : new ClientboundDisconnectPacket(ichatmutablecomponent); ++ ++ this.send((Packet) packet, PacketSendListener.thenRun(() -> { ++ this.disconnect(ichatmutablecomponent); ++ })); + } else { +- this.disconnect(component); ++ this.disconnect(ichatmutablecomponent); + } + + this.setReadOnly(); + } else { +- LOGGER.debug("Double fault", exception); +- this.disconnect(component); ++ Connection.LOGGER.debug("Double fault", throwable); ++ this.disconnect(ichatmutablecomponent); + } + } ++ + } + } + } + +- @Override + protected void channelRead0(ChannelHandlerContext context, Packet packet) { + if (this.channel.isOpen()) { +- PacketListener packetListener = this.packetListener; +- if (packetListener == null) { ++ PacketListener packetlistener = this.packetListener; ++ ++ if (packetlistener == null) { + throw new IllegalStateException("Received a packet before the packet listener was initialized"); + } else { +- if (packetListener.shouldHandleMessage(packet)) { ++ if (packetlistener.shouldHandleMessage(packet)) { + try { +- genericsFtw(packet, packetListener); +- } catch (RunningOnDifferentThreadException var5) { +- } catch (RejectedExecutionException var6) { ++ genericsFtw(packet, packetlistener); ++ } catch (CancelledPacketHandleException cancelledpackethandleexception) { ++ ; ++ } catch (RejectedExecutionException rejectedexecutionexception) { + this.disconnect(Component.translatable("multiplayer.disconnect.server_shutdown")); +- } catch (ClassCastException var7) { +- LOGGER.error("Received {} that couldn't be processed", packet.getClass(), var7); ++ } catch (ClassCastException classcastexception) { ++ Connection.LOGGER.error("Received {} that couldn't be processed", packet.getClass(), classcastexception); + this.disconnect(Component.translatable("multiplayer.disconnect.invalid_packet")); + } + +- this.receivedPackets++; ++ ++this.receivedPackets; + } ++ + } + } + } + + private static void genericsFtw(Packet packet, PacketListener listener) { +- packet.handle((T)listener); ++ packet.handle((T) listener); // CraftBukkit - decompile error + } + + public void suspendInboundAfterProtocolChange() { +@@ -194,22 +207,17 @@ + } + + public void setListener(PacketListener handler) { +- Validate.notNull(handler, "packetListener"); +- PacketFlow packetFlow = handler.flow(); +- if (packetFlow != this.receiving) { +- throw new IllegalStateException("Trying to set listener for wrong side: connection is " + this.receiving + ", but listener is " + packetFlow); ++ Validate.notNull(handler, "packetListener", new Object[0]); ++ PacketFlow enumprotocoldirection = handler.flow(); ++ ++ if (enumprotocoldirection != this.receiving) { ++ throw new IllegalStateException("Trying to set listener for wrong side: connection is " + this.receiving + ", but listener is " + enumprotocoldirection); + } else { +- ConnectionProtocol connectionProtocol = handler.protocol(); +- ConnectionProtocol connectionProtocol1 = this.channel.attr(getProtocolKey(packetFlow)).get().protocol(); +- if (connectionProtocol1 != connectionProtocol) { +- throw new IllegalStateException( +- "Trying to set listener for protocol " +- + connectionProtocol.id() +- + ", but current " +- + packetFlow +- + " protocol is " +- + connectionProtocol1.id() +- ); ++ ConnectionProtocol enumprotocol = handler.protocol(); ++ ConnectionProtocol enumprotocol1 = ((ConnectionProtocol.a) this.channel.attr(getProtocolKey(enumprotocoldirection)).get()).protocol(); ++ ++ if (enumprotocol1 != enumprotocol) { ++ throw new IllegalStateException("Trying to set listener for protocol " + enumprotocol.id() + ", but current " + enumprotocoldirection + " protocol is " + enumprotocol1.id()); + } else { + this.packetListener = handler; + this.disconnectListener = null; +@@ -217,54 +225,55 @@ + } + } + +- public void setListenerForServerboundHandshake(PacketListener packetListener) { ++ public void setListenerForServerboundHandshake(PacketListener packetlistener) { + if (this.packetListener != null) { + throw new IllegalStateException("Listener already set"); +- } else if (this.receiving == PacketFlow.SERVERBOUND +- && packetListener.flow() == PacketFlow.SERVERBOUND +- && packetListener.protocol() == ConnectionProtocol.HANDSHAKING) { +- this.packetListener = packetListener; ++ } else if (this.receiving == PacketFlow.SERVERBOUND && packetlistener.flow() == PacketFlow.SERVERBOUND && packetlistener.protocol() == ConnectionProtocol.HANDSHAKING) { ++ this.packetListener = packetlistener; + } else { + throw new IllegalStateException("Invalid initial listener"); + } + } + +- public void initiateServerboundStatusConnection(String string, int i, ClientStatusPacketListener clientStatusPacketListener) { +- this.initiateServerboundConnection(string, i, clientStatusPacketListener, ClientIntent.STATUS); ++ public void initiateServerboundStatusConnection(String s, int i, ClientStatusPacketListener packetstatusoutlistener) { ++ this.initiateServerboundConnection(s, i, packetstatusoutlistener, ClientIntent.STATUS); + } + +- public void initiateServerboundPlayConnection(String string, int i, ClientLoginPacketListener clientLoginPacketListener) { +- this.initiateServerboundConnection(string, i, clientLoginPacketListener, ClientIntent.LOGIN); ++ public void initiateServerboundPlayConnection(String s, int i, ClientLoginPacketListener packetloginoutlistener) { ++ this.initiateServerboundConnection(s, i, packetloginoutlistener, ClientIntent.LOGIN); + } + +- private void initiateServerboundConnection(String string, int i, PacketListener packetListener, ClientIntent clientIntent) { +- this.disconnectListener = packetListener; +- this.runOnceConnected(connection -> { +- connection.setClientboundProtocolAfterHandshake(clientIntent); +- this.setListener(packetListener); +- connection.sendPacket(new ClientIntentionPacket(SharedConstants.getCurrentVersion().getProtocolVersion(), string, i, clientIntent), null, true); ++ private void initiateServerboundConnection(String s, int i, PacketListener packetlistener, ClientIntent clientintent) { ++ this.disconnectListener = packetlistener; ++ this.runOnceConnected((networkmanager) -> { ++ networkmanager.setClientboundProtocolAfterHandshake(clientintent); ++ this.setListener(packetlistener); ++ networkmanager.sendPacket(new ClientIntentionPacket(SharedConstants.getCurrentVersion().getProtocolVersion(), s, i, clientintent), (PacketSendListener) null, true); + }); + } + +- public void setClientboundProtocolAfterHandshake(ClientIntent clientIntent) { +- this.channel.attr(ATTRIBUTE_CLIENTBOUND_PROTOCOL).set(clientIntent.protocol().codec(PacketFlow.CLIENTBOUND)); ++ public void setClientboundProtocolAfterHandshake(ClientIntent clientintent) { ++ this.channel.attr(Connection.ATTRIBUTE_CLIENTBOUND_PROTOCOL).set(clientintent.protocol().codec(PacketFlow.CLIENTBOUND)); + } + + public void send(Packet packet) { +- this.send(packet, null); ++ this.send(packet, (PacketSendListener) null); + } + + public void send(Packet packet, @Nullable PacketSendListener sendListener) { + this.send(packet, sendListener, true); + } + +- public void send(Packet packet, @Nullable PacketSendListener packetSendListener, boolean flag) { ++ public void send(Packet packet, @Nullable PacketSendListener packetsendlistener, boolean flag) { + if (this.isConnected()) { + this.flushQueue(); +- this.sendPacket(packet, packetSendListener, flag); ++ this.sendPacket(packet, packetsendlistener, flag); + } else { +- this.pendingActions.add(connection -> connection.sendPacket(packet, packetSendListener, flag)); ++ this.pendingActions.add((networkmanager) -> { ++ networkmanager.sendPacket(packet, packetsendlistener, flag); ++ }); + } ++ + } + + public void runOnceConnected(Consumer consumer) { +@@ -274,34 +283,42 @@ + } else { + this.pendingActions.add(consumer); + } ++ + } + +- private void sendPacket(Packet packet, @Nullable PacketSendListener packetSendListener, boolean flag) { +- this.sentPackets++; ++ private void sendPacket(Packet packet, @Nullable PacketSendListener packetsendlistener, boolean flag) { ++ ++this.sentPackets; + if (this.channel.eventLoop().inEventLoop()) { +- this.doSendPacket(packet, packetSendListener, flag); ++ this.doSendPacket(packet, packetsendlistener, flag); + } else { +- this.channel.eventLoop().execute(() -> this.doSendPacket(packet, packetSendListener, flag)); ++ this.channel.eventLoop().execute(() -> { ++ this.doSendPacket(packet, packetsendlistener, flag); ++ }); + } ++ + } + +- private void doSendPacket(Packet packet, @Nullable PacketSendListener packetSendListener, boolean flag) { +- ChannelFuture channelFuture = flag ? this.channel.writeAndFlush(packet) : this.channel.write(packet); +- if (packetSendListener != null) { +- channelFuture.addListener(future -> { ++ private void doSendPacket(Packet packet, @Nullable PacketSendListener packetsendlistener, boolean flag) { ++ ChannelFuture channelfuture = flag ? this.channel.writeAndFlush(packet) : this.channel.write(packet); ++ ++ if (packetsendlistener != null) { ++ channelfuture.addListener((future) -> { + if (future.isSuccess()) { +- packetSendListener.onSuccess(); ++ packetsendlistener.onSuccess(); + } else { +- Packet packet1 = packetSendListener.onFailure(); ++ Packet packet1 = packetsendlistener.onFailure(); ++ + if (packet1 != null) { +- ChannelFuture channelFuture1 = this.channel.writeAndFlush(packet1); +- channelFuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); ++ ChannelFuture channelfuture1 = this.channel.writeAndFlush(packet1); ++ ++ channelfuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); + } + } ++ + }); + } + +- channelFuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); ++ channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); + } + + public void flushChannel() { +@@ -310,38 +327,60 @@ + } else { + this.pendingActions.add(Connection::flush); + } ++ + } + + private void flush() { + if (this.channel.eventLoop().inEventLoop()) { + this.channel.flush(); + } else { +- this.channel.eventLoop().execute(() -> this.channel.flush()); ++ this.channel.eventLoop().execute(() -> { ++ this.channel.flush(); ++ }); + } ++ + } + +- private static AttributeKey> getProtocolKey(PacketFlow packetFlow) { +- return switch (packetFlow) { +- case CLIENTBOUND -> ATTRIBUTE_CLIENTBOUND_PROTOCOL; +- case SERVERBOUND -> ATTRIBUTE_SERVERBOUND_PROTOCOL; +- }; ++ private static AttributeKey> getProtocolKey(PacketFlow enumprotocoldirection) { ++ AttributeKey attributekey; ++ ++ switch (enumprotocoldirection) { ++ case CLIENTBOUND: ++ attributekey = Connection.ATTRIBUTE_CLIENTBOUND_PROTOCOL; ++ break; ++ case SERVERBOUND: ++ attributekey = Connection.ATTRIBUTE_SERVERBOUND_PROTOCOL; ++ break; ++ default: ++ throw new IncompatibleClassChangeError(); ++ } ++ ++ return attributekey; + } + + private void flushQueue() { + if (this.channel != null && this.channel.isOpen()) { ++ Queue queue = this.pendingActions; ++ + synchronized (this.pendingActions) { +- Consumer consumer; +- while ((consumer = this.pendingActions.poll()) != null) { ++ Consumer consumer; ++ ++ while ((consumer = (Consumer) this.pendingActions.poll()) != null) { + consumer.accept(this); + } ++ + } + } + } + + public void tick() { + this.flushQueue(); +- if (this.packetListener instanceof TickablePacketListener tickablePacketListener) { +- tickablePacketListener.tick(); ++ PacketListener packetlistener = this.packetListener; ++ ++ if (packetlistener instanceof TickablePacketListener) { ++ TickablePacketListener tickablepacketlistener = (TickablePacketListener) packetlistener; ++ ++ tickablepacketlistener.tick(); + } + + if (!this.isConnected() && !this.disconnectionHandled) { +@@ -359,11 +398,12 @@ + if (this.bandwidthDebugMonitor != null) { + this.bandwidthDebugMonitor.tick(); + } ++ + } + + protected void tickSecond() { +- this.averageSentPackets = Mth.lerp(0.75F, (float)this.sentPackets, this.averageSentPackets); +- this.averageReceivedPackets = Mth.lerp(0.75F, (float)this.receivedPackets, this.averageReceivedPackets); ++ this.averageSentPackets = Mth.lerp(0.75F, (float) this.sentPackets, this.averageSentPackets); ++ this.averageReceivedPackets = Mth.lerp(0.75F, (float) this.receivedPackets, this.averageReceivedPackets); + this.sentPackets = 0; + this.receivedPackets = 0; + } +@@ -373,11 +413,7 @@ + } + + public String getLoggableAddress(boolean flag) { +- if (this.address == null) { +- return "local"; +- } else { +- return flag ? this.address.toString() : "IP hidden"; +- } ++ return this.address == null ? "local" : (flag ? this.address.toString() : "IP hidden"); + } + + public void disconnect(Component message) { +@@ -386,9 +422,10 @@ + } + + if (this.isConnected()) { +- this.channel.close().awaitUninterruptibly(); ++ this.channel.close(); // We can't wait as this may be called from an event loop. + this.disconnectedReason = message; + } ++ + } + + public boolean isMemoryConnection() { +@@ -403,84 +440,86 @@ + return this.receiving.getOpposite(); + } + +- public static Connection connectToServer(InetSocketAddress inetSocketAddress, boolean flag, @Nullable SampleLogger sampleLogger) { +- Connection connection = new Connection(PacketFlow.CLIENTBOUND); +- if (sampleLogger != null) { +- connection.setBandwidthLogger(sampleLogger); ++ public static Connection connectToServer(InetSocketAddress inetsocketaddress, boolean flag, @Nullable SampleLogger samplelogger) { ++ Connection networkmanager = new Connection(PacketFlow.CLIENTBOUND); ++ ++ if (samplelogger != null) { ++ networkmanager.setBandwidthLogger(samplelogger); + } + +- ChannelFuture channelFuture = connect(inetSocketAddress, flag, connection); +- channelFuture.syncUninterruptibly(); +- return connection; ++ ChannelFuture channelfuture = connect(inetsocketaddress, flag, networkmanager); ++ ++ channelfuture.syncUninterruptibly(); ++ return networkmanager; + } + + public static ChannelFuture connect(InetSocketAddress address, boolean useEpollIfAvailable, final Connection connection) { +- Class clazz; +- EventLoopGroup eventLoopGroup; ++ Class oclass; ++ EventLoopGroup eventloopgroup; ++ + if (Epoll.isAvailable() && useEpollIfAvailable) { +- clazz = EpollSocketChannel.class; +- eventLoopGroup = NETWORK_EPOLL_WORKER_GROUP.get(); ++ oclass = EpollSocketChannel.class; ++ eventloopgroup = (EventLoopGroup) Connection.NETWORK_EPOLL_WORKER_GROUP.get(); + } else { +- clazz = NioSocketChannel.class; +- eventLoopGroup = NETWORK_WORKER_GROUP.get(); ++ oclass = NioSocketChannel.class; ++ eventloopgroup = (EventLoopGroup) Connection.NETWORK_WORKER_GROUP.get(); + } + +- return new Bootstrap().group(eventLoopGroup).handler(new ChannelInitializer() { +- @Override ++ return ((Bootstrap) ((Bootstrap) ((Bootstrap) (new Bootstrap()).group(eventloopgroup)).handler(new ChannelInitializer() { + protected void initChannel(Channel channel) { + Connection.setInitialProtocolAttributes(channel); + + try { + channel.config().setOption(ChannelOption.TCP_NODELAY, true); +- } catch (ChannelException var3) { ++ } catch (ChannelException channelexception) { ++ ; + } + +- ChannelPipeline channelPipeline = channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)); +- Connection.configureSerialization(channelPipeline, PacketFlow.CLIENTBOUND, connection.bandwidthDebugMonitor); +- connection.configurePacketHandler(channelPipeline); ++ ChannelPipeline channelpipeline = channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)); ++ ++ Connection.configureSerialization(channelpipeline, PacketFlow.CLIENTBOUND, connection.bandwidthDebugMonitor); ++ connection.configurePacketHandler(channelpipeline); + } +- }).channel(clazz).connect(address.getAddress(), address.getPort()); ++ })).channel(oclass)).connect(address.getAddress(), address.getPort()); + } + +- public static void configureSerialization(ChannelPipeline channelPipeline, PacketFlow packetFlow, @Nullable BandwidthDebugMonitor bandwidthDebugMonitor) { +- PacketFlow opposite = packetFlow.getOpposite(); +- AttributeKey> protocolKey = getProtocolKey(packetFlow); +- AttributeKey> protocolKey1 = getProtocolKey(opposite); +- channelPipeline.addLast("splitter", new Varint21FrameDecoder(bandwidthDebugMonitor)) +- .addLast("decoder", new PacketDecoder(protocolKey)) +- .addLast("prepender", new Varint21LengthFieldPrepender()) +- .addLast("encoder", new PacketEncoder(protocolKey1)) +- .addLast("unbundler", new PacketBundleUnpacker(protocolKey1)) +- .addLast("bundler", new PacketBundlePacker(protocolKey)); ++ public static void configureSerialization(ChannelPipeline channelpipeline, PacketFlow enumprotocoldirection, @Nullable BandwidthDebugMonitor bandwidthdebugmonitor) { ++ PacketFlow enumprotocoldirection1 = enumprotocoldirection.getOpposite(); ++ AttributeKey> attributekey = getProtocolKey(enumprotocoldirection); ++ AttributeKey> attributekey1 = getProtocolKey(enumprotocoldirection1); ++ ++ channelpipeline.addLast("splitter", new Varint21FrameDecoder(bandwidthdebugmonitor)).addLast("decoder", new PacketDecoder(attributekey)).addLast("prepender", new Varint21LengthFieldPrepender()).addLast("encoder", new PacketEncoder(attributekey1)).addLast("unbundler", new PacketBundleUnpacker(attributekey1)).addLast("bundler", new PacketBundlePacker(attributekey)); + } + +- public void configurePacketHandler(ChannelPipeline channelPipeline) { +- channelPipeline.addLast(new FlowControlHandler()).addLast("packet_handler", this); ++ public void configurePacketHandler(ChannelPipeline channelpipeline) { ++ channelpipeline.addLast(new ChannelHandler[]{new FlowControlHandler()}).addLast("packet_handler", this); + } + +- private static void configureInMemoryPacketValidation(ChannelPipeline channelPipeline, PacketFlow packetFlow) { +- PacketFlow opposite = packetFlow.getOpposite(); +- AttributeKey> protocolKey = getProtocolKey(packetFlow); +- AttributeKey> protocolKey1 = getProtocolKey(opposite); +- channelPipeline.addLast("validator", new PacketFlowValidator(protocolKey, protocolKey1)); ++ private static void configureInMemoryPacketValidation(ChannelPipeline channelpipeline, PacketFlow enumprotocoldirection) { ++ PacketFlow enumprotocoldirection1 = enumprotocoldirection.getOpposite(); ++ AttributeKey> attributekey = getProtocolKey(enumprotocoldirection); ++ AttributeKey> attributekey1 = getProtocolKey(enumprotocoldirection1); ++ ++ channelpipeline.addLast("validator", new PacketFlowValidator(attributekey, attributekey1)); + } + +- public static void configureInMemoryPipeline(ChannelPipeline channelPipeline, PacketFlow packetFlow) { +- configureInMemoryPacketValidation(channelPipeline, packetFlow); ++ public static void configureInMemoryPipeline(ChannelPipeline channelpipeline, PacketFlow enumprotocoldirection) { ++ configureInMemoryPacketValidation(channelpipeline, enumprotocoldirection); + } + + public static Connection connectToLocalServer(SocketAddress address) { +- final Connection connection = new Connection(PacketFlow.CLIENTBOUND); +- new Bootstrap().group(LOCAL_WORKER_GROUP.get()).handler(new ChannelInitializer() { +- @Override ++ final Connection networkmanager = new Connection(PacketFlow.CLIENTBOUND); ++ ++ ((Bootstrap) ((Bootstrap) ((Bootstrap) (new Bootstrap()).group((EventLoopGroup) Connection.LOCAL_WORKER_GROUP.get())).handler(new ChannelInitializer() { + protected void initChannel(Channel channel) { + Connection.setInitialProtocolAttributes(channel); +- ChannelPipeline channelPipeline = channel.pipeline(); +- Connection.configureInMemoryPacketValidation(channelPipeline, PacketFlow.CLIENTBOUND); +- connection.configurePacketHandler(channelPipeline); ++ ChannelPipeline channelpipeline = channel.pipeline(); ++ ++ Connection.configureInMemoryPipeline(channelpipeline, PacketFlow.CLIENTBOUND); ++ networkmanager.configurePacketHandler(channelpipeline); + } +- }).channel(LocalChannel.class).connect(address).syncUninterruptibly(); +- return connection; ++ })).channel(LocalChannel.class)).connect(address).syncUninterruptibly(); ++ return networkmanager; + } + + public void setEncryptionKey(Cipher decryptingCipher, Cipher encryptingCipher) { +@@ -515,18 +554,19 @@ + if (this.channel != null) { + this.channel.config().setAutoRead(false); + } ++ + } + + public void setupCompression(int threshold, boolean validateDecompressed) { + if (threshold >= 0) { + if (this.channel.pipeline().get("decompress") instanceof CompressionDecoder) { +- ((CompressionDecoder)this.channel.pipeline().get("decompress")).setThreshold(threshold, validateDecompressed); ++ ((CompressionDecoder) this.channel.pipeline().get("decompress")).setThreshold(threshold, validateDecompressed); + } else { + this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(threshold, validateDecompressed)); + } + + if (this.channel.pipeline().get("compress") instanceof CompressionEncoder) { +- ((CompressionEncoder)this.channel.pipeline().get("compress")).setThreshold(threshold); ++ ((CompressionEncoder) this.channel.pipeline().get("compress")).setThreshold(threshold); + } else { + this.channel.pipeline().addBefore("encoder", "compress", new CompressionEncoder(threshold)); + } +@@ -539,22 +579,26 @@ + this.channel.pipeline().remove("compress"); + } + } ++ + } + + public void handleDisconnection() { + if (this.channel != null && !this.channel.isOpen()) { + if (this.disconnectionHandled) { +- LOGGER.warn("handleDisconnection() called twice"); ++ Connection.LOGGER.warn("handleDisconnection() called twice"); + } else { + this.disconnectionHandled = true; +- PacketListener packetListener = this.getPacketListener(); +- PacketListener packetListener1 = packetListener != null ? packetListener : this.disconnectListener; +- if (packetListener1 != null) { +- Component component = Objects.requireNonNullElseGet( +- this.getDisconnectedReason(), () -> Component.translatable("multiplayer.disconnect.generic") +- ); +- packetListener1.onDisconnect(component); ++ PacketListener packetlistener = this.getPacketListener(); ++ PacketListener packetlistener1 = packetlistener != null ? packetlistener : this.disconnectListener; ++ ++ if (packetlistener1 != null) { ++ Component ichatbasecomponent = (Component) Objects.requireNonNullElseGet(this.getDisconnectedReason(), () -> { ++ return Component.translatable("multiplayer.disconnect.generic"); ++ }); ++ ++ packetlistener1.onDisconnect(ichatbasecomponent); + } ++ + } + } + } +@@ -567,7 +611,7 @@ + return this.averageSentPackets; + } + +- public void setBandwidthLogger(SampleLogger sampleLogger) { +- this.bandwidthDebugMonitor = new BandwidthDebugMonitor(sampleLogger); ++ public void setBandwidthLogger(SampleLogger samplelogger) { ++ this.bandwidthDebugMonitor = new BandwidthDebugMonitor(samplelogger); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/network/FriendlyByteBuf.java.patch b/patch-remap/mache-vineflower/net/minecraft/network/FriendlyByteBuf.java.patch new file mode 100644 index 0000000000..dc2a12e244 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/network/FriendlyByteBuf.java.patch @@ -0,0 +1,2067 @@ +--- a/net/minecraft/network/FriendlyByteBuf.java ++++ b/net/minecraft/network/FriendlyByteBuf.java +@@ -37,6 +37,7 @@ + import java.util.Collection; + import java.util.Date; + import java.util.EnumSet; ++import java.util.Iterator; + import java.util.List; + import java.util.Map; + import java.util.Optional; +@@ -80,7 +81,10 @@ + import org.joml.Quaternionf; + import org.joml.Vector3f; + ++import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit ++ + public class FriendlyByteBuf extends ByteBuf { ++ + public static final int DEFAULT_NBT_QUOTA = 2097152; + private final ByteBuf source; + public static final short MAX_STRING_LENGTH = 32767; +@@ -94,74 +98,97 @@ + this.source = source; + } + ++ /** @deprecated */ + @Deprecated +- public T readWithCodecTrusted(DynamicOps dynamicOps, Codec codec) { +- return this.readWithCodec(dynamicOps, codec, NbtAccounter.unlimitedHeap()); ++ public T readWithCodecTrusted(DynamicOps dynamicops, Codec codec) { ++ return this.readWithCodec(dynamicops, codec, NbtAccounter.unlimitedHeap()); + } + ++ /** @deprecated */ + @Deprecated +- public T readWithCodec(DynamicOps dynamicOps, Codec codec, NbtAccounter nbtAccounter) { +- Tag nbt = this.readNbt(nbtAccounter); +- return Util.getOrThrow(codec.parse(dynamicOps, nbt), string -> new DecoderException("Failed to decode: " + string + " " + nbt)); ++ public T readWithCodec(DynamicOps dynamicops, Codec codec, NbtAccounter nbtreadlimiter) { ++ Tag nbtbase = this.readNbt(nbtreadlimiter); ++ ++ return Util.getOrThrow(codec.parse(dynamicops, nbtbase), (s) -> { ++ return new DecoderException("Failed to decode: " + s + " " + nbtbase); ++ }); + } + ++ /** @deprecated */ + @Deprecated +- public FriendlyByteBuf writeWithCodec(DynamicOps dynamicOps, Codec codec, T object) { +- Tag tag = Util.getOrThrow(codec.encodeStart(dynamicOps, object), string -> new EncoderException("Failed to encode: " + string + " " + object)); +- this.writeNbt(tag); ++ public FriendlyByteBuf writeWithCodec(DynamicOps dynamicops, Codec codec, T t0) { ++ Tag nbtbase = (Tag) Util.getOrThrow(codec.encodeStart(dynamicops, t0), (s) -> { ++ return new EncoderException("Failed to encode: " + s + " " + t0); ++ }); ++ ++ this.writeNbt(nbtbase); + return this; + } + + public T readJsonWithCodec(Codec codec) { +- JsonElement jsonElement = GsonHelper.fromJson(GSON, this.readUtf(), JsonElement.class); +- DataResult dataResult = codec.parse(JsonOps.INSTANCE, jsonElement); +- return Util.getOrThrow(dataResult, string -> new DecoderException("Failed to decode json: " + string)); ++ JsonElement jsonelement = (JsonElement) GsonHelper.fromJson(FriendlyByteBuf.GSON, this.readUtf(), JsonElement.class); ++ DataResult dataresult = codec.parse(JsonOps.INSTANCE, jsonelement); ++ ++ return Util.getOrThrow(dataresult, (s) -> { ++ return new DecoderException("Failed to decode json: " + s); ++ }); + } + + public void writeJsonWithCodec(Codec codec, T value) { +- DataResult dataResult = codec.encodeStart(JsonOps.INSTANCE, value); +- this.writeUtf(GSON.toJson(Util.getOrThrow(dataResult, string -> new EncoderException("Failed to encode: " + string + " " + value)))); ++ DataResult dataresult = codec.encodeStart(JsonOps.INSTANCE, value); ++ ++ this.writeUtf(FriendlyByteBuf.GSON.toJson((JsonElement) Util.getOrThrow(dataresult, (s) -> { ++ return new EncoderException("Failed to encode: " + s + " " + value); ++ }))); + } + + public void writeId(IdMap idMap, T value) { +- int id = idMap.getId(value); +- if (id == -1) { ++ int i = idMap.getId(value); ++ ++ if (i == -1) { + throw new IllegalArgumentException("Can't find id for '" + value + "' in map " + idMap); + } else { +- this.writeVarInt(id); ++ this.writeVarInt(i); + } + } + +- public void writeId(IdMap> idMap, Holder value, FriendlyByteBuf.Writer writer) { ++ public void writeId(IdMap> idMap, Holder value, FriendlyByteBuf.b writer) { + switch (value.kind()) { + case REFERENCE: +- int id = idMap.getId(value); +- if (id == -1) { +- throw new IllegalArgumentException("Can't find id for '" + value.value() + "' in map " + idMap); ++ int i = idMap.getId(value); ++ ++ if (i == -1) { ++ Object object = value.value(); ++ ++ throw new IllegalArgumentException("Can't find id for '" + object + "' in map " + idMap); + } + +- this.writeVarInt(id + 1); ++ this.writeVarInt(i + 1); + break; + case DIRECT: + this.writeVarInt(0); + writer.accept(this, value.value()); + } ++ + } + + @Nullable + public T readById(IdMap idMap) { +- int varInt = this.readVarInt(); +- return idMap.byId(varInt); ++ int i = this.readVarInt(); ++ ++ return idMap.byId(i); + } + +- public Holder readById(IdMap> idMap, FriendlyByteBuf.Reader reader) { +- int varInt = this.readVarInt(); +- if (varInt == 0) { ++ public Holder readById(IdMap> idMap, FriendlyByteBuf.a reader) { ++ int i = this.readVarInt(); ++ ++ if (i == 0) { + return Holder.direct(reader.apply(this)); + } else { +- Holder holder = idMap.byId(varInt - 1); ++ Holder holder = (Holder) idMap.byId(i - 1); ++ + if (holder == null) { +- throw new IllegalArgumentException("Can't find element with id " + varInt); ++ throw new IllegalArgumentException("Can't find element with id " + i); + } else { + return holder; + } +@@ -169,150 +196,158 @@ + } + + public static IntFunction limitValue(IntFunction function, int limit) { +- return i -> { +- if (i > limit) { +- throw new DecoderException("Value " + i + " is larger than limit " + limit); ++ return (j) -> { ++ if (j > limit) { ++ throw new DecoderException("Value " + j + " is larger than limit " + limit); + } else { +- return function.apply(i); ++ return function.apply(j); + } + }; + } + +- public > C readCollection(IntFunction collectionFactory, FriendlyByteBuf.Reader elementReader) { +- int varInt = this.readVarInt(); +- C collection = (C)collectionFactory.apply(varInt); ++ public > C readCollection(IntFunction collectionFactory, FriendlyByteBuf.a elementReader) { ++ int i = this.readVarInt(); ++ C c0 = collectionFactory.apply(i); // CraftBukkit - decompile error + +- for (int i = 0; i < varInt; i++) { +- collection.add(elementReader.apply(this)); ++ for (int j = 0; j < i; ++j) { ++ c0.add(elementReader.apply(this)); + } + +- return collection; ++ return c0; + } + +- public void writeCollection(Collection collection, FriendlyByteBuf.Writer elementWriter) { ++ public void writeCollection(Collection collection, FriendlyByteBuf.b elementWriter) { + this.writeVarInt(collection.size()); ++ Iterator iterator = collection.iterator(); // CraftBukkit - decompile error + +- for (T object : collection) { +- elementWriter.accept(this, object); ++ while (iterator.hasNext()) { ++ T t0 = iterator.next(); ++ ++ elementWriter.accept(this, t0); + } ++ + } + +- public List readList(FriendlyByteBuf.Reader elementReader) { +- return this.readCollection(Lists::newArrayListWithCapacity, elementReader); ++ public List readList(FriendlyByteBuf.a elementReader) { ++ return (List) this.readCollection(Lists::newArrayListWithCapacity, elementReader); + } + + public IntList readIntIdList() { +- int varInt = this.readVarInt(); +- IntList list = new IntArrayList(); ++ int i = this.readVarInt(); ++ IntArrayList intarraylist = new IntArrayList(); + +- for (int i = 0; i < varInt; i++) { +- list.add(this.readVarInt()); ++ for (int j = 0; j < i; ++j) { ++ intarraylist.add(this.readVarInt()); + } + +- return list; ++ return intarraylist; + } + + public void writeIntIdList(IntList itIdList) { + this.writeVarInt(itIdList.size()); +- itIdList.forEach(this::writeVarInt); ++ itIdList.forEach((java.util.function.IntConsumer) this::writeVarInt); // CraftBukkit - decompile error + } + +- public > M readMap(IntFunction mapFactory, FriendlyByteBuf.Reader keyReader, FriendlyByteBuf.Reader valueReader) { +- int varInt = this.readVarInt(); +- M map = (M)mapFactory.apply(varInt); ++ public > M readMap(IntFunction mapFactory, FriendlyByteBuf.a keyReader, FriendlyByteBuf.a valueReader) { ++ int i = this.readVarInt(); ++ M m0 = mapFactory.apply(i); // CraftBukkit - decompile error + +- for (int i = 0; i < varInt; i++) { +- K object = keyReader.apply(this); +- V object1 = valueReader.apply(this); +- map.put(object, object1); ++ for (int j = 0; j < i; ++j) { ++ K k0 = keyReader.apply(this); ++ V v0 = valueReader.apply(this); ++ ++ m0.put(k0, v0); + } + +- return map; ++ return m0; + } + +- public Map readMap(FriendlyByteBuf.Reader keyReader, FriendlyByteBuf.Reader valueReader) { ++ public Map readMap(FriendlyByteBuf.a keyReader, FriendlyByteBuf.a valueReader) { + return this.readMap(Maps::newHashMapWithExpectedSize, keyReader, valueReader); + } + +- public void writeMap(Map map, FriendlyByteBuf.Writer keyWriter, FriendlyByteBuf.Writer valueWriter) { ++ public void writeMap(Map map, FriendlyByteBuf.b keyWriter, FriendlyByteBuf.b valueWriter) { + this.writeVarInt(map.size()); + map.forEach((object, object1) -> { +- keyWriter.accept(this, (K)object); +- valueWriter.accept(this, (V)object1); ++ keyWriter.accept(this, object); ++ valueWriter.accept(this, object1); + }); + } + + public void readWithCount(Consumer reader) { +- int varInt = this.readVarInt(); ++ int i = this.readVarInt(); + +- for (int i = 0; i < varInt; i++) { ++ for (int j = 0; j < i; ++j) { + reader.accept(this); + } ++ + } + + public > void writeEnumSet(EnumSet enumSet, Class enumClass) { +- E[] enums = (E[])enumClass.getEnumConstants(); +- BitSet bitSet = new BitSet(enums.length); ++ E[] ae = enumClass.getEnumConstants(); // CraftBukkit - decompile error ++ BitSet bitset = new BitSet(ae.length); + +- for (int i = 0; i < enums.length; i++) { +- bitSet.set(i, enumSet.contains(enums[i])); ++ for (int i = 0; i < ae.length; ++i) { ++ bitset.set(i, enumSet.contains(ae[i])); + } + +- this.writeFixedBitSet(bitSet, enums.length); ++ this.writeFixedBitSet(bitset, ae.length); + } + + public > EnumSet readEnumSet(Class enumClass) { +- E[] enums = (E[])enumClass.getEnumConstants(); +- BitSet fixedBitSet = this.readFixedBitSet(enums.length); +- EnumSet set = EnumSet.noneOf(enumClass); ++ E[] ae = enumClass.getEnumConstants(); // CraftBukkit - decompile error ++ BitSet bitset = this.readFixedBitSet(ae.length); ++ EnumSet enumset = EnumSet.noneOf(enumClass); + +- for (int i = 0; i < enums.length; i++) { +- if (fixedBitSet.get(i)) { +- set.add(enums[i]); ++ for (int i = 0; i < ae.length; ++i) { ++ if (bitset.get(i)) { ++ enumset.add(ae[i]); + } + } + +- return set; ++ return enumset; + } + +- public void writeOptional(Optional optional, FriendlyByteBuf.Writer writer) { ++ public void writeOptional(Optional optional, FriendlyByteBuf.b writer) { + if (optional.isPresent()) { + this.writeBoolean(true); + writer.accept(this, optional.get()); + } else { + this.writeBoolean(false); + } ++ + } + +- public Optional readOptional(FriendlyByteBuf.Reader reader) { ++ public Optional readOptional(FriendlyByteBuf.a reader) { + return this.readBoolean() ? Optional.of(reader.apply(this)) : Optional.empty(); + } + + @Nullable +- public T readNullable(FriendlyByteBuf.Reader reader) { ++ public T readNullable(FriendlyByteBuf.a reader) { + return this.readBoolean() ? reader.apply(this) : null; + } + +- public void writeNullable(@Nullable T value, FriendlyByteBuf.Writer writer) { ++ public void writeNullable(@Nullable T value, FriendlyByteBuf.b writer) { + if (value != null) { + this.writeBoolean(true); + writer.accept(this, value); + } else { + this.writeBoolean(false); + } ++ + } + +- public void writeEither(Either value, FriendlyByteBuf.Writer leftWriter, FriendlyByteBuf.Writer rightWriter) { +- value.ifLeft(object -> { ++ public void writeEither(Either value, FriendlyByteBuf.b leftWriter, FriendlyByteBuf.b rightWriter) { ++ value.ifLeft((object) -> { + this.writeBoolean(true); +- leftWriter.accept(this, (L)object); +- }).ifRight(object -> { ++ leftWriter.accept(this, object); ++ }).ifRight((object) -> { + this.writeBoolean(false); +- rightWriter.accept(this, (R)object); ++ rightWriter.accept(this, object); + }); + } + +- public Either readEither(FriendlyByteBuf.Reader leftReader, FriendlyByteBuf.Reader rightReader) { ++ public Either readEither(FriendlyByteBuf.a leftReader, FriendlyByteBuf.a rightReader) { + return this.readBoolean() ? Either.left(leftReader.apply(this)) : Either.right(rightReader.apply(this)); + } + +@@ -327,21 +362,27 @@ + } + + public byte[] readByteArray(int maxLength) { +- int varInt = this.readVarInt(); +- if (varInt > maxLength) { +- throw new DecoderException("ByteArray with size " + varInt + " is bigger than allowed " + maxLength); ++ int j = this.readVarInt(); ++ ++ if (j > maxLength) { ++ throw new DecoderException("ByteArray with size " + j + " is bigger than allowed " + maxLength); + } else { +- byte[] bytes = new byte[varInt]; +- this.readBytes(bytes); +- return bytes; ++ byte[] abyte = new byte[j]; ++ ++ this.readBytes(abyte); ++ return abyte; + } + } + + public FriendlyByteBuf writeVarIntArray(int[] array) { + this.writeVarInt(array.length); ++ int[] aint1 = array; ++ int i = array.length; + +- for (int i : array) { +- this.writeVarInt(i); ++ for (int j = 0; j < i; ++j) { ++ int k = aint1[j]; ++ ++ this.writeVarInt(k); + } + + return this; +@@ -352,32 +393,37 @@ + } + + public int[] readVarIntArray(int maxLength) { +- int varInt = this.readVarInt(); +- if (varInt > maxLength) { +- throw new DecoderException("VarIntArray with size " + varInt + " is bigger than allowed " + maxLength); ++ int j = this.readVarInt(); ++ ++ if (j > maxLength) { ++ throw new DecoderException("VarIntArray with size " + j + " is bigger than allowed " + maxLength); + } else { +- int[] ints = new int[varInt]; ++ int[] aint = new int[j]; + +- for (int i = 0; i < ints.length; i++) { +- ints[i] = this.readVarInt(); ++ for (int k = 0; k < aint.length; ++k) { ++ aint[k] = this.readVarInt(); + } + +- return ints; ++ return aint; + } + } + + public FriendlyByteBuf writeLongArray(long[] array) { + this.writeVarInt(array.length); ++ long[] along1 = array; ++ int i = array.length; + +- for (long l : array) { +- this.writeLong(l); ++ for (int j = 0; j < i; ++j) { ++ long k = along1[j]; ++ ++ this.writeLong(k); + } + + return this; + } + + public long[] readLongArray() { +- return this.readLongArray(null); ++ return this.readLongArray((long[]) null); + } + + public long[] readLongArray(@Nullable long[] array) { +@@ -385,17 +431,18 @@ + } + + public long[] readLongArray(@Nullable long[] array, int maxLength) { +- int varInt = this.readVarInt(); +- if (array == null || array.length != varInt) { +- if (varInt > maxLength) { +- throw new DecoderException("LongArray with size " + varInt + " is bigger than allowed " + maxLength); ++ int j = this.readVarInt(); ++ ++ if (array == null || array.length != j) { ++ if (j > maxLength) { ++ throw new DecoderException("LongArray with size " + j + " is bigger than allowed " + maxLength); + } + +- array = new long[varInt]; ++ array = new long[j]; + } + +- for (int i = 0; i < array.length; i++) { +- array[i] = this.readLong(); ++ for (int k = 0; k < array.length; ++k) { ++ array[k] = this.readLong(); + } + + return array; +@@ -429,9 +476,10 @@ + } + + public GlobalPos readGlobalPos() { +- ResourceKey resourceKey = this.readResourceKey(Registries.DIMENSION); +- BlockPos blockPos = this.readBlockPos(); +- return GlobalPos.of(resourceKey, blockPos); ++ ResourceKey resourcekey = this.readResourceKey(Registries.DIMENSION); ++ BlockPos blockposition = this.readBlockPos(); ++ ++ return GlobalPos.of(resourcekey, blockposition); + } + + public void writeGlobalPos(GlobalPos pos) { +@@ -464,18 +512,18 @@ + return new Vec3(this.readDouble(), this.readDouble(), this.readDouble()); + } + +- public void writeVec3(Vec3 vec3) { +- this.writeDouble(vec3.x()); +- this.writeDouble(vec3.y()); +- this.writeDouble(vec3.z()); ++ public void writeVec3(Vec3 vec3d) { ++ this.writeDouble(vec3d.x()); ++ this.writeDouble(vec3d.y()); ++ this.writeDouble(vec3d.z()); + } + + public Component readComponent() { +- return this.readWithCodec(NbtOps.INSTANCE, ComponentSerialization.CODEC, NbtAccounter.create(2097152L)); ++ return (Component) this.readWithCodec(NbtOps.INSTANCE, ComponentSerialization.CODEC, NbtAccounter.create(2097152L)); + } + + public Component readComponentTrusted() { +- return this.readWithCodecTrusted(NbtOps.INSTANCE, ComponentSerialization.CODEC); ++ return (Component) this.readWithCodecTrusted(NbtOps.INSTANCE, ComponentSerialization.CODEC); + } + + public FriendlyByteBuf writeComponent(Component component) { +@@ -483,20 +531,22 @@ + } + + public > T readEnum(Class enumClass) { +- return enumClass.getEnumConstants()[this.readVarInt()]; ++ return ((T[]) enumClass.getEnumConstants())[this.readVarInt()]; // CraftBukkit - fix decompile error + } + + public FriendlyByteBuf writeEnum(Enum value) { + return this.writeVarInt(value.ordinal()); + } + +- public T readById(IntFunction intFunction) { +- int varInt = this.readVarInt(); +- return intFunction.apply(varInt); ++ public T readById(IntFunction intfunction) { ++ int i = this.readVarInt(); ++ ++ return intfunction.apply(i); + } + +- public FriendlyByteBuf writeById(ToIntFunction toIntFunction, T object) { +- int i = toIntFunction.applyAsInt(object); ++ public FriendlyByteBuf writeById(ToIntFunction tointfunction, T t0) { ++ int i = tointfunction.applyAsInt(t0); ++ + return this.writeVarInt(i); + } + +@@ -528,53 +578,57 @@ + return this; + } + +- public FriendlyByteBuf writeNbt(@Nullable Tag tag) { +- if (tag == null) { +- tag = EndTag.INSTANCE; ++ public FriendlyByteBuf writeNbt(@Nullable Tag nbtbase) { ++ if (nbtbase == null) { ++ nbtbase = EndTag.INSTANCE; + } + + try { +- NbtIo.writeAnyTag(tag, new ByteBufOutputStream(this)); ++ NbtIo.writeAnyTag((Tag) nbtbase, new ByteBufOutputStream(this)); + return this; +- } catch (IOException var3) { +- throw new EncoderException(var3); ++ } catch (Exception ioexception) { // CraftBukkit - IOException -> Exception ++ throw new EncoderException(ioexception); + } + } + + @Nullable + public CompoundTag readNbt() { +- Tag nbt = this.readNbt(NbtAccounter.create(2097152L)); +- if (nbt != null && !(nbt instanceof CompoundTag)) { +- throw new DecoderException("Not a compound tag: " + nbt); ++ Tag nbtbase = this.readNbt(NbtAccounter.create(2097152L)); ++ ++ if (nbtbase != null && !(nbtbase instanceof CompoundTag)) { ++ throw new DecoderException("Not a compound tag: " + nbtbase); + } else { +- return (CompoundTag)nbt; ++ return (CompoundTag) nbtbase; + } + } + + @Nullable +- public Tag readNbt(NbtAccounter nbtAccounter) { ++ public Tag readNbt(NbtAccounter nbtreadlimiter) { + try { +- Tag anyTag = NbtIo.readAnyTag(new ByteBufInputStream(this), nbtAccounter); +- return anyTag.getId() == 0 ? null : anyTag; +- } catch (IOException var3) { +- throw new EncoderException(var3); ++ Tag nbtbase = NbtIo.readAnyTag(new ByteBufInputStream(this), nbtreadlimiter); ++ ++ return nbtbase.getId() == 0 ? null : nbtbase; ++ } catch (IOException ioexception) { ++ throw new EncoderException(ioexception); + } + } + + public FriendlyByteBuf writeItem(ItemStack stack) { +- if (stack.isEmpty()) { ++ if (stack.isEmpty() || stack.getItem() == null) { // CraftBukkit - NPE fix itemstack.getItem() + this.writeBoolean(false); + } else { + this.writeBoolean(true); + Item item = stack.getItem(); ++ + this.writeId(BuiltInRegistries.ITEM, item); + this.writeByte(stack.getCount()); +- CompoundTag compoundTag = null; ++ CompoundTag nbttagcompound = null; ++ + if (item.canBeDepleted() || item.shouldOverrideMultiplayerNbt()) { +- compoundTag = stack.getTag(); ++ nbttagcompound = stack.getTag(); + } + +- this.writeNbt(compoundTag); ++ this.writeNbt(nbttagcompound); + } + + return this; +@@ -584,11 +638,17 @@ + if (!this.readBoolean()) { + return ItemStack.EMPTY; + } else { +- Item item = this.readById(BuiltInRegistries.ITEM); +- int _byte = this.readByte(); +- ItemStack itemStack = new ItemStack(item, _byte); +- itemStack.setTag(this.readNbt()); +- return itemStack; ++ Item item = (Item) this.readById((IdMap) BuiltInRegistries.ITEM); ++ byte b0 = this.readByte(); ++ ItemStack itemstack = new ItemStack(item, b0); ++ ++ itemstack.setTag(this.readNbt()); ++ // CraftBukkit start ++ if (itemstack.getTag() != null) { ++ CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); ++ } ++ // CraftBukkit end ++ return itemstack; + } + } + +@@ -619,8 +679,9 @@ + } + + public ResourceKey readResourceKey(ResourceKey> registryKey) { +- ResourceLocation resourceLocation = this.readResourceLocation(); +- return ResourceKey.create(registryKey, resourceLocation); ++ ResourceLocation minecraftkey = this.readResourceLocation(); ++ ++ return ResourceKey.create(registryKey, minecraftkey); + } + + public void writeResourceKey(ResourceKey resourceKey) { +@@ -628,8 +689,9 @@ + } + + public ResourceKey> readRegistryKey() { +- ResourceLocation resourceLocation = this.readResourceLocation(); +- return ResourceKey.createRegistryKey(resourceLocation); ++ ResourceLocation minecraftkey = this.readResourceLocation(); ++ ++ return ResourceKey.createRegistryKey(minecraftkey); + } + + public Date readDate() { +@@ -652,8 +714,8 @@ + public PublicKey readPublicKey() { + try { + return Crypt.byteToPublicKey(this.readByteArray(512)); +- } catch (CryptException var2) { +- throw new DecoderException("Malformed public key bytes", var2); ++ } catch (CryptException cryptographyexception) { ++ throw new DecoderException("Malformed public key bytes", cryptographyexception); + } + } + +@@ -663,28 +725,26 @@ + } + + public BlockHitResult readBlockHitResult() { +- BlockPos blockPos = this.readBlockPos(); +- Direction direction = this.readEnum(Direction.class); +- float _float = this.readFloat(); +- float _float1 = this.readFloat(); +- float _float2 = this.readFloat(); +- boolean _boolean = this.readBoolean(); +- return new BlockHitResult( +- new Vec3((double)blockPos.getX() + (double)_float, (double)blockPos.getY() + (double)_float1, (double)blockPos.getZ() + (double)_float2), +- direction, +- blockPos, +- _boolean +- ); ++ BlockPos blockposition = this.readBlockPos(); ++ Direction enumdirection = (Direction) this.readEnum(Direction.class); ++ float f = this.readFloat(); ++ float f1 = this.readFloat(); ++ float f2 = this.readFloat(); ++ boolean flag = this.readBoolean(); ++ ++ return new BlockHitResult(new Vec3((double) blockposition.getX() + (double) f, (double) blockposition.getY() + (double) f1, (double) blockposition.getZ() + (double) f2), enumdirection, blockposition, flag); + } + + public void writeBlockHitResult(BlockHitResult result) { +- BlockPos blockPos = result.getBlockPos(); +- this.writeBlockPos(blockPos); ++ BlockPos blockposition = result.getBlockPos(); ++ ++ this.writeBlockPos(blockposition); + this.writeEnum(result.getDirection()); +- Vec3 location = result.getLocation(); +- this.writeFloat((float)(location.x - (double)blockPos.getX())); +- this.writeFloat((float)(location.y - (double)blockPos.getY())); +- this.writeFloat((float)(location.z - (double)blockPos.getZ())); ++ Vec3 vec3d = result.getLocation(); ++ ++ this.writeFloat((float) (vec3d.x - (double) blockposition.getX())); ++ this.writeFloat((float) (vec3d.y - (double) blockposition.getY())); ++ this.writeFloat((float) (vec3d.z - (double) blockposition.getZ())); + this.writeBoolean(result.isInside()); + } + +@@ -697,26 +757,31 @@ + } + + public BitSet readFixedBitSet(int size) { +- byte[] bytes = new byte[Mth.positiveCeilDiv(size, 8)]; +- this.readBytes(bytes); +- return BitSet.valueOf(bytes); ++ byte[] abyte = new byte[Mth.positiveCeilDiv(size, 8)]; ++ ++ this.readBytes(abyte); ++ return BitSet.valueOf(abyte); + } + + public void writeFixedBitSet(BitSet bitSet, int size) { + if (bitSet.length() > size) { +- throw new EncoderException("BitSet is larger than expected size (" + bitSet.length() + ">" + size + ")"); ++ int j = bitSet.length(); ++ ++ throw new EncoderException("BitSet is larger than expected size (" + j + ">" + size + ")"); + } else { +- byte[] bytes = bitSet.toByteArray(); +- this.writeBytes(Arrays.copyOf(bytes, Mth.positiveCeilDiv(size, 8))); ++ byte[] abyte = bitSet.toByteArray(); ++ ++ this.writeBytes(Arrays.copyOf(abyte, Mth.positiveCeilDiv(size, 8))); + } + } + + public GameProfile readGameProfile() { +- UUID uUID = this.readUUID(); +- String utf = this.readUtf(16); +- GameProfile gameProfile = new GameProfile(uUID, utf); +- gameProfile.getProperties().putAll(this.readGameProfileProperties()); +- return gameProfile; ++ UUID uuid = this.readUUID(); ++ String s = this.readUtf(16); ++ GameProfile gameprofile = new GameProfile(uuid, s); ++ ++ gameprofile.getProperties().putAll(this.readGameProfileProperties()); ++ return gameprofile; + } + + public void writeGameProfile(GameProfile gameProfile) { +@@ -726,12 +791,14 @@ + } + + public PropertyMap readGameProfileProperties() { +- PropertyMap propertyMap = new PropertyMap(); +- this.readWithCount(friendlyByteBuf -> { ++ PropertyMap propertymap = new PropertyMap(); ++ ++ this.readWithCount((packetdataserializer) -> { + Property property = this.readProperty(); +- propertyMap.put(property.name(), property); ++ ++ propertymap.put(property.name(), property); + }); +- return propertyMap; ++ return propertymap; + } + + public void writeGameProfileProperties(PropertyMap gameProfileProperties) { +@@ -739,10 +806,11 @@ + } + + public Property readProperty() { +- String utf = this.readUtf(); +- String utf1 = this.readUtf(); +- String string = this.readNullable(FriendlyByteBuf::readUtf); +- return new Property(utf, utf1, string); ++ String s = this.readUtf(); ++ String s1 = this.readUtf(); ++ String s2 = (String) this.readNullable(FriendlyByteBuf::readUtf); ++ ++ return new Property(s, s1, s2); + } + + public void writeProperty(Property property) { +@@ -751,1013 +819,834 @@ + this.writeNullable(property.signature(), FriendlyByteBuf::writeUtf); + } + +- @Override + public boolean isContiguous() { + return this.source.isContiguous(); + } + +- @Override + public int maxFastWritableBytes() { + return this.source.maxFastWritableBytes(); + } + +- @Override + public int capacity() { + return this.source.capacity(); + } + +- @Override +- public FriendlyByteBuf capacity(int newCapacity) { +- this.source.capacity(newCapacity); ++ public FriendlyByteBuf capacity(int i) { ++ this.source.capacity(i); + return this; + } + +- @Override + public int maxCapacity() { + return this.source.maxCapacity(); + } + +- @Override + public ByteBufAllocator alloc() { + return this.source.alloc(); + } + +- @Override + public ByteOrder order() { + return this.source.order(); + } + +- @Override +- public ByteBuf order(ByteOrder endianness) { +- return this.source.order(endianness); ++ public ByteBuf order(ByteOrder byteorder) { ++ return this.source.order(byteorder); + } + +- @Override + public ByteBuf unwrap() { + return this.source; + } + +- @Override + public boolean isDirect() { + return this.source.isDirect(); + } + +- @Override + public boolean isReadOnly() { + return this.source.isReadOnly(); + } + +- @Override + public ByteBuf asReadOnly() { + return this.source.asReadOnly(); + } + +- @Override + public int readerIndex() { + return this.source.readerIndex(); + } + +- @Override +- public FriendlyByteBuf readerIndex(int readerIndex) { +- this.source.readerIndex(readerIndex); ++ public FriendlyByteBuf readerIndex(int i) { ++ this.source.readerIndex(i); + return this; + } + +- @Override + public int writerIndex() { + return this.source.writerIndex(); + } + +- @Override +- public FriendlyByteBuf writerIndex(int writerIndex) { +- this.source.writerIndex(writerIndex); ++ public FriendlyByteBuf writerIndex(int i) { ++ this.source.writerIndex(i); + return this; + } + +- @Override +- public FriendlyByteBuf setIndex(int readerIndex, int writerIndex) { +- this.source.setIndex(readerIndex, writerIndex); ++ public FriendlyByteBuf setIndex(int i, int j) { ++ this.source.setIndex(i, j); + return this; + } + +- @Override + public int readableBytes() { + return this.source.readableBytes(); + } + +- @Override + public int writableBytes() { + return this.source.writableBytes(); + } + +- @Override + public int maxWritableBytes() { + return this.source.maxWritableBytes(); + } + +- @Override + public boolean isReadable() { + return this.source.isReadable(); + } + +- @Override +- public boolean isReadable(int size) { +- return this.source.isReadable(size); ++ public boolean isReadable(int i) { ++ return this.source.isReadable(i); + } + +- @Override + public boolean isWritable() { + return this.source.isWritable(); + } + +- @Override +- public boolean isWritable(int size) { +- return this.source.isWritable(size); ++ public boolean isWritable(int i) { ++ return this.source.isWritable(i); + } + +- @Override + public FriendlyByteBuf clear() { + this.source.clear(); + return this; + } + +- @Override + public FriendlyByteBuf markReaderIndex() { + this.source.markReaderIndex(); + return this; + } + +- @Override + public FriendlyByteBuf resetReaderIndex() { + this.source.resetReaderIndex(); + return this; + } + +- @Override + public FriendlyByteBuf markWriterIndex() { + this.source.markWriterIndex(); + return this; + } + +- @Override + public FriendlyByteBuf resetWriterIndex() { + this.source.resetWriterIndex(); + return this; + } + +- @Override + public FriendlyByteBuf discardReadBytes() { + this.source.discardReadBytes(); + return this; + } + +- @Override + public FriendlyByteBuf discardSomeReadBytes() { + this.source.discardSomeReadBytes(); + return this; + } + +- @Override +- public FriendlyByteBuf ensureWritable(int size) { +- this.source.ensureWritable(size); ++ public FriendlyByteBuf ensureWritable(int i) { ++ this.source.ensureWritable(i); + return this; + } + +- @Override +- public int ensureWritable(int size, boolean force) { +- return this.source.ensureWritable(size, force); ++ public int ensureWritable(int i, boolean flag) { ++ return this.source.ensureWritable(i, flag); + } + +- @Override +- public boolean getBoolean(int index) { +- return this.source.getBoolean(index); ++ public boolean getBoolean(int i) { ++ return this.source.getBoolean(i); + } + +- @Override +- public byte getByte(int index) { +- return this.source.getByte(index); ++ public byte getByte(int i) { ++ return this.source.getByte(i); + } + +- @Override +- public short getUnsignedByte(int index) { +- return this.source.getUnsignedByte(index); ++ public short getUnsignedByte(int i) { ++ return this.source.getUnsignedByte(i); + } + +- @Override +- public short getShort(int index) { +- return this.source.getShort(index); ++ public short getShort(int i) { ++ return this.source.getShort(i); + } + +- @Override +- public short getShortLE(int index) { +- return this.source.getShortLE(index); ++ public short getShortLE(int i) { ++ return this.source.getShortLE(i); + } + +- @Override +- public int getUnsignedShort(int index) { +- return this.source.getUnsignedShort(index); ++ public int getUnsignedShort(int i) { ++ return this.source.getUnsignedShort(i); + } + +- @Override +- public int getUnsignedShortLE(int index) { +- return this.source.getUnsignedShortLE(index); ++ public int getUnsignedShortLE(int i) { ++ return this.source.getUnsignedShortLE(i); + } + +- @Override +- public int getMedium(int index) { +- return this.source.getMedium(index); ++ public int getMedium(int i) { ++ return this.source.getMedium(i); + } + +- @Override +- public int getMediumLE(int index) { +- return this.source.getMediumLE(index); ++ public int getMediumLE(int i) { ++ return this.source.getMediumLE(i); + } + +- @Override +- public int getUnsignedMedium(int index) { +- return this.source.getUnsignedMedium(index); ++ public int getUnsignedMedium(int i) { ++ return this.source.getUnsignedMedium(i); + } + +- @Override +- public int getUnsignedMediumLE(int index) { +- return this.source.getUnsignedMediumLE(index); ++ public int getUnsignedMediumLE(int i) { ++ return this.source.getUnsignedMediumLE(i); + } + +- @Override +- public int getInt(int index) { +- return this.source.getInt(index); ++ public int getInt(int i) { ++ return this.source.getInt(i); + } + +- @Override +- public int getIntLE(int index) { +- return this.source.getIntLE(index); ++ public int getIntLE(int i) { ++ return this.source.getIntLE(i); + } + +- @Override +- public long getUnsignedInt(int index) { +- return this.source.getUnsignedInt(index); ++ public long getUnsignedInt(int i) { ++ return this.source.getUnsignedInt(i); + } + +- @Override +- public long getUnsignedIntLE(int index) { +- return this.source.getUnsignedIntLE(index); ++ public long getUnsignedIntLE(int i) { ++ return this.source.getUnsignedIntLE(i); + } + +- @Override +- public long getLong(int index) { +- return this.source.getLong(index); ++ public long getLong(int i) { ++ return this.source.getLong(i); + } + +- @Override +- public long getLongLE(int index) { +- return this.source.getLongLE(index); ++ public long getLongLE(int i) { ++ return this.source.getLongLE(i); + } + +- @Override +- public char getChar(int index) { +- return this.source.getChar(index); ++ public char getChar(int i) { ++ return this.source.getChar(i); + } + +- @Override +- public float getFloat(int index) { +- return this.source.getFloat(index); ++ public float getFloat(int i) { ++ return this.source.getFloat(i); + } + +- @Override +- public double getDouble(int index) { +- return this.source.getDouble(index); ++ public double getDouble(int i) { ++ return this.source.getDouble(i); + } + +- @Override +- public FriendlyByteBuf getBytes(int index, ByteBuf destination) { +- this.source.getBytes(index, destination); ++ public FriendlyByteBuf getBytes(int i, ByteBuf bytebuf) { ++ this.source.getBytes(i, bytebuf); + return this; + } + +- @Override +- public FriendlyByteBuf getBytes(int index, ByteBuf destination, int length) { +- this.source.getBytes(index, destination, length); ++ public FriendlyByteBuf getBytes(int i, ByteBuf bytebuf, int j) { ++ this.source.getBytes(i, bytebuf, j); + return this; + } + +- @Override +- public FriendlyByteBuf getBytes(int index, ByteBuf destination, int destinationIndex, int length) { +- this.source.getBytes(index, destination, destinationIndex, length); ++ public FriendlyByteBuf getBytes(int i, ByteBuf bytebuf, int j, int k) { ++ this.source.getBytes(i, bytebuf, j, k); + return this; + } + +- @Override +- public FriendlyByteBuf getBytes(int index, byte[] destination) { +- this.source.getBytes(index, destination); ++ public FriendlyByteBuf getBytes(int i, byte[] abyte) { ++ this.source.getBytes(i, abyte); + return this; + } + +- @Override +- public FriendlyByteBuf getBytes(int index, byte[] destination, int destinationIndex, int length) { +- this.source.getBytes(index, destination, destinationIndex, length); ++ public FriendlyByteBuf getBytes(int i, byte[] abyte, int j, int k) { ++ this.source.getBytes(i, abyte, j, k); + return this; + } + +- @Override +- public FriendlyByteBuf getBytes(int index, ByteBuffer destination) { +- this.source.getBytes(index, destination); ++ public FriendlyByteBuf getBytes(int i, ByteBuffer bytebuffer) { ++ this.source.getBytes(i, bytebuffer); + return this; + } + +- @Override +- public FriendlyByteBuf getBytes(int index, OutputStream out, int length) throws IOException { +- this.source.getBytes(index, out, length); ++ public FriendlyByteBuf getBytes(int i, OutputStream outputstream, int j) throws IOException { ++ this.source.getBytes(i, outputstream, j); + return this; + } + +- @Override +- public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { +- return this.source.getBytes(index, out, length); ++ public int getBytes(int i, GatheringByteChannel gatheringbytechannel, int j) throws IOException { ++ return this.source.getBytes(i, gatheringbytechannel, j); + } + +- @Override +- public int getBytes(int index, FileChannel out, long position, int length) throws IOException { +- return this.source.getBytes(index, out, position, length); ++ public int getBytes(int i, FileChannel filechannel, long j, int k) throws IOException { ++ return this.source.getBytes(i, filechannel, j, k); + } + +- @Override +- public CharSequence getCharSequence(int index, int length, Charset charset) { +- return this.source.getCharSequence(index, length, charset); ++ public CharSequence getCharSequence(int i, int j, Charset charset) { ++ return this.source.getCharSequence(i, j, charset); + } + +- @Override +- public FriendlyByteBuf setBoolean(int index, boolean value) { +- this.source.setBoolean(index, value); ++ public FriendlyByteBuf setBoolean(int i, boolean flag) { ++ this.source.setBoolean(i, flag); + return this; + } + +- @Override +- public FriendlyByteBuf setByte(int index, int value) { +- this.source.setByte(index, value); ++ public FriendlyByteBuf setByte(int i, int j) { ++ this.source.setByte(i, j); + return this; + } + +- @Override +- public FriendlyByteBuf setShort(int index, int value) { +- this.source.setShort(index, value); ++ public FriendlyByteBuf setShort(int i, int j) { ++ this.source.setShort(i, j); + return this; + } + +- @Override +- public FriendlyByteBuf setShortLE(int index, int value) { +- this.source.setShortLE(index, value); ++ public FriendlyByteBuf setShortLE(int i, int j) { ++ this.source.setShortLE(i, j); + return this; + } + +- @Override +- public FriendlyByteBuf setMedium(int index, int value) { +- this.source.setMedium(index, value); ++ public FriendlyByteBuf setMedium(int i, int j) { ++ this.source.setMedium(i, j); + return this; + } + +- @Override +- public FriendlyByteBuf setMediumLE(int index, int value) { +- this.source.setMediumLE(index, value); ++ public FriendlyByteBuf setMediumLE(int i, int j) { ++ this.source.setMediumLE(i, j); + return this; + } + +- @Override +- public FriendlyByteBuf setInt(int index, int value) { +- this.source.setInt(index, value); ++ public FriendlyByteBuf setInt(int i, int j) { ++ this.source.setInt(i, j); + return this; + } + +- @Override +- public FriendlyByteBuf setIntLE(int index, int value) { +- this.source.setIntLE(index, value); ++ public FriendlyByteBuf setIntLE(int i, int j) { ++ this.source.setIntLE(i, j); + return this; + } + +- @Override +- public FriendlyByteBuf setLong(int index, long value) { +- this.source.setLong(index, value); ++ public FriendlyByteBuf setLong(int i, long j) { ++ this.source.setLong(i, j); + return this; + } + +- @Override +- public FriendlyByteBuf setLongLE(int index, long value) { +- this.source.setLongLE(index, value); ++ public FriendlyByteBuf setLongLE(int i, long j) { ++ this.source.setLongLE(i, j); + return this; + } + +- @Override +- public FriendlyByteBuf setChar(int index, int value) { +- this.source.setChar(index, value); ++ public FriendlyByteBuf setChar(int i, int j) { ++ this.source.setChar(i, j); + return this; + } + +- @Override +- public FriendlyByteBuf setFloat(int index, float value) { +- this.source.setFloat(index, value); ++ public FriendlyByteBuf setFloat(int i, float f) { ++ this.source.setFloat(i, f); + return this; + } + +- @Override +- public FriendlyByteBuf setDouble(int index, double value) { +- this.source.setDouble(index, value); ++ public FriendlyByteBuf setDouble(int i, double d0) { ++ this.source.setDouble(i, d0); + return this; + } + +- @Override +- public FriendlyByteBuf setBytes(int index, ByteBuf source) { +- this.source.setBytes(index, source); ++ public FriendlyByteBuf setBytes(int i, ByteBuf bytebuf) { ++ this.source.setBytes(i, bytebuf); + return this; + } + +- @Override +- public FriendlyByteBuf setBytes(int index, ByteBuf source, int length) { +- this.source.setBytes(index, source, length); ++ public FriendlyByteBuf setBytes(int i, ByteBuf bytebuf, int j) { ++ this.source.setBytes(i, bytebuf, j); + return this; + } + +- @Override +- public FriendlyByteBuf setBytes(int index, ByteBuf source, int sourceIndex, int length) { +- this.source.setBytes(index, source, sourceIndex, length); ++ public FriendlyByteBuf setBytes(int i, ByteBuf bytebuf, int j, int k) { ++ this.source.setBytes(i, bytebuf, j, k); + return this; + } + +- @Override +- public FriendlyByteBuf setBytes(int index, byte[] source) { +- this.source.setBytes(index, source); ++ public FriendlyByteBuf setBytes(int i, byte[] abyte) { ++ this.source.setBytes(i, abyte); + return this; + } + +- @Override +- public FriendlyByteBuf setBytes(int index, byte[] source, int sourceIndex, int length) { +- this.source.setBytes(index, source, sourceIndex, length); ++ public FriendlyByteBuf setBytes(int i, byte[] abyte, int j, int k) { ++ this.source.setBytes(i, abyte, j, k); + return this; + } + +- @Override +- public FriendlyByteBuf setBytes(int index, ByteBuffer source) { +- this.source.setBytes(index, source); ++ public FriendlyByteBuf setBytes(int i, ByteBuffer bytebuffer) { ++ this.source.setBytes(i, bytebuffer); + return this; + } + +- @Override +- public int setBytes(int index, InputStream in, int length) throws IOException { +- return this.source.setBytes(index, in, length); ++ public int setBytes(int i, InputStream inputstream, int j) throws IOException { ++ return this.source.setBytes(i, inputstream, j); + } + +- @Override +- public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { +- return this.source.setBytes(index, in, length); ++ public int setBytes(int i, ScatteringByteChannel scatteringbytechannel, int j) throws IOException { ++ return this.source.setBytes(i, scatteringbytechannel, j); + } + +- @Override +- public int setBytes(int index, FileChannel in, long position, int length) throws IOException { +- return this.source.setBytes(index, in, position, length); ++ public int setBytes(int i, FileChannel filechannel, long j, int k) throws IOException { ++ return this.source.setBytes(i, filechannel, j, k); + } + +- @Override +- public FriendlyByteBuf setZero(int index, int length) { +- this.source.setZero(index, length); ++ public FriendlyByteBuf setZero(int i, int j) { ++ this.source.setZero(i, j); + return this; + } + +- @Override +- public int setCharSequence(int index, CharSequence charSequence, Charset charset) { +- return this.source.setCharSequence(index, charSequence, charset); ++ public int setCharSequence(int i, CharSequence charsequence, Charset charset) { ++ return this.source.setCharSequence(i, charsequence, charset); + } + +- @Override + public boolean readBoolean() { + return this.source.readBoolean(); + } + +- @Override + public byte readByte() { + return this.source.readByte(); + } + +- @Override + public short readUnsignedByte() { + return this.source.readUnsignedByte(); + } + +- @Override + public short readShort() { + return this.source.readShort(); + } + +- @Override + public short readShortLE() { + return this.source.readShortLE(); + } + +- @Override + public int readUnsignedShort() { + return this.source.readUnsignedShort(); + } + +- @Override + public int readUnsignedShortLE() { + return this.source.readUnsignedShortLE(); + } + +- @Override + public int readMedium() { + return this.source.readMedium(); + } + +- @Override + public int readMediumLE() { + return this.source.readMediumLE(); + } + +- @Override + public int readUnsignedMedium() { + return this.source.readUnsignedMedium(); + } + +- @Override + public int readUnsignedMediumLE() { + return this.source.readUnsignedMediumLE(); + } + +- @Override + public int readInt() { + return this.source.readInt(); + } + +- @Override + public int readIntLE() { + return this.source.readIntLE(); + } + +- @Override + public long readUnsignedInt() { + return this.source.readUnsignedInt(); + } + +- @Override + public long readUnsignedIntLE() { + return this.source.readUnsignedIntLE(); + } + +- @Override + public long readLong() { + return this.source.readLong(); + } + +- @Override + public long readLongLE() { + return this.source.readLongLE(); + } + +- @Override + public char readChar() { + return this.source.readChar(); + } + +- @Override + public float readFloat() { + return this.source.readFloat(); + } + +- @Override + public double readDouble() { + return this.source.readDouble(); + } + +- @Override +- public ByteBuf readBytes(int length) { +- return this.source.readBytes(length); ++ public ByteBuf readBytes(int i) { ++ return this.source.readBytes(i); + } + +- @Override +- public ByteBuf readSlice(int length) { +- return this.source.readSlice(length); ++ public ByteBuf readSlice(int i) { ++ return this.source.readSlice(i); + } + +- @Override +- public ByteBuf readRetainedSlice(int length) { +- return this.source.readRetainedSlice(length); ++ public ByteBuf readRetainedSlice(int i) { ++ return this.source.readRetainedSlice(i); + } + +- @Override +- public FriendlyByteBuf readBytes(ByteBuf destination) { +- this.source.readBytes(destination); ++ public FriendlyByteBuf readBytes(ByteBuf bytebuf) { ++ this.source.readBytes(bytebuf); + return this; + } + +- @Override +- public FriendlyByteBuf readBytes(ByteBuf destination, int length) { +- this.source.readBytes(destination, length); ++ public FriendlyByteBuf readBytes(ByteBuf bytebuf, int i) { ++ this.source.readBytes(bytebuf, i); + return this; + } + +- @Override +- public FriendlyByteBuf readBytes(ByteBuf destination, int destinationIndex, int length) { +- this.source.readBytes(destination, destinationIndex, length); ++ public FriendlyByteBuf readBytes(ByteBuf bytebuf, int i, int j) { ++ this.source.readBytes(bytebuf, i, j); + return this; + } + +- @Override +- public FriendlyByteBuf readBytes(byte[] destination) { +- this.source.readBytes(destination); ++ public FriendlyByteBuf readBytes(byte[] abyte) { ++ this.source.readBytes(abyte); + return this; + } + +- @Override +- public FriendlyByteBuf readBytes(byte[] destination, int destinationIndex, int length) { +- this.source.readBytes(destination, destinationIndex, length); ++ public FriendlyByteBuf readBytes(byte[] abyte, int i, int j) { ++ this.source.readBytes(abyte, i, j); + return this; + } + +- @Override +- public FriendlyByteBuf readBytes(ByteBuffer destination) { +- this.source.readBytes(destination); ++ public FriendlyByteBuf readBytes(ByteBuffer bytebuffer) { ++ this.source.readBytes(bytebuffer); + return this; + } + +- @Override +- public FriendlyByteBuf readBytes(OutputStream out, int length) throws IOException { +- this.source.readBytes(out, length); ++ public FriendlyByteBuf readBytes(OutputStream outputstream, int i) throws IOException { ++ this.source.readBytes(outputstream, i); + return this; + } + +- @Override +- public int readBytes(GatheringByteChannel out, int length) throws IOException { +- return this.source.readBytes(out, length); ++ public int readBytes(GatheringByteChannel gatheringbytechannel, int i) throws IOException { ++ return this.source.readBytes(gatheringbytechannel, i); + } + +- @Override +- public CharSequence readCharSequence(int length, Charset charset) { +- return this.source.readCharSequence(length, charset); ++ public CharSequence readCharSequence(int i, Charset charset) { ++ return this.source.readCharSequence(i, charset); + } + +- @Override +- public int readBytes(FileChannel out, long position, int length) throws IOException { +- return this.source.readBytes(out, position, length); ++ public int readBytes(FileChannel filechannel, long i, int j) throws IOException { ++ return this.source.readBytes(filechannel, i, j); + } + +- @Override +- public FriendlyByteBuf skipBytes(int length) { +- this.source.skipBytes(length); ++ public FriendlyByteBuf skipBytes(int i) { ++ this.source.skipBytes(i); + return this; + } + +- @Override +- public FriendlyByteBuf writeBoolean(boolean value) { +- this.source.writeBoolean(value); ++ public FriendlyByteBuf writeBoolean(boolean flag) { ++ this.source.writeBoolean(flag); + return this; + } + +- @Override +- public FriendlyByteBuf writeByte(int value) { +- this.source.writeByte(value); ++ public FriendlyByteBuf writeByte(int i) { ++ this.source.writeByte(i); + return this; + } + +- @Override +- public FriendlyByteBuf writeShort(int value) { +- this.source.writeShort(value); ++ public FriendlyByteBuf writeShort(int i) { ++ this.source.writeShort(i); + return this; + } + +- @Override +- public FriendlyByteBuf writeShortLE(int value) { +- this.source.writeShortLE(value); ++ public FriendlyByteBuf writeShortLE(int i) { ++ this.source.writeShortLE(i); + return this; + } + +- @Override +- public FriendlyByteBuf writeMedium(int value) { +- this.source.writeMedium(value); ++ public FriendlyByteBuf writeMedium(int i) { ++ this.source.writeMedium(i); + return this; + } + +- @Override +- public FriendlyByteBuf writeMediumLE(int value) { +- this.source.writeMediumLE(value); ++ public FriendlyByteBuf writeMediumLE(int i) { ++ this.source.writeMediumLE(i); + return this; + } + +- @Override +- public FriendlyByteBuf writeInt(int value) { +- this.source.writeInt(value); ++ public FriendlyByteBuf writeInt(int i) { ++ this.source.writeInt(i); + return this; + } + +- @Override +- public FriendlyByteBuf writeIntLE(int value) { +- this.source.writeIntLE(value); ++ public FriendlyByteBuf writeIntLE(int i) { ++ this.source.writeIntLE(i); + return this; + } + +- @Override +- public FriendlyByteBuf writeLong(long value) { +- this.source.writeLong(value); ++ public FriendlyByteBuf writeLong(long i) { ++ this.source.writeLong(i); + return this; + } + +- @Override +- public FriendlyByteBuf writeLongLE(long value) { +- this.source.writeLongLE(value); ++ public FriendlyByteBuf writeLongLE(long i) { ++ this.source.writeLongLE(i); + return this; + } + +- @Override +- public FriendlyByteBuf writeChar(int value) { +- this.source.writeChar(value); ++ public FriendlyByteBuf writeChar(int i) { ++ this.source.writeChar(i); + return this; + } + +- @Override +- public FriendlyByteBuf writeFloat(float value) { +- this.source.writeFloat(value); ++ public FriendlyByteBuf writeFloat(float f) { ++ this.source.writeFloat(f); + return this; + } + +- @Override +- public FriendlyByteBuf writeDouble(double value) { +- this.source.writeDouble(value); ++ public FriendlyByteBuf writeDouble(double d0) { ++ this.source.writeDouble(d0); + return this; + } + +- @Override +- public FriendlyByteBuf writeBytes(ByteBuf source) { +- this.source.writeBytes(source); ++ public FriendlyByteBuf writeBytes(ByteBuf bytebuf) { ++ this.source.writeBytes(bytebuf); + return this; + } + +- @Override +- public FriendlyByteBuf writeBytes(ByteBuf source, int length) { +- this.source.writeBytes(source, length); ++ public FriendlyByteBuf writeBytes(ByteBuf bytebuf, int i) { ++ this.source.writeBytes(bytebuf, i); + return this; + } + +- @Override +- public FriendlyByteBuf writeBytes(ByteBuf source, int sourceIndex, int length) { +- this.source.writeBytes(source, sourceIndex, length); ++ public FriendlyByteBuf writeBytes(ByteBuf bytebuf, int i, int j) { ++ this.source.writeBytes(bytebuf, i, j); + return this; + } + +- @Override +- public FriendlyByteBuf writeBytes(byte[] source) { +- this.source.writeBytes(source); ++ public FriendlyByteBuf writeBytes(byte[] abyte) { ++ this.source.writeBytes(abyte); + return this; + } + +- @Override +- public FriendlyByteBuf writeBytes(byte[] source, int sourceIndex, int length) { +- this.source.writeBytes(source, sourceIndex, length); ++ public FriendlyByteBuf writeBytes(byte[] abyte, int i, int j) { ++ this.source.writeBytes(abyte, i, j); + return this; + } + +- @Override +- public FriendlyByteBuf writeBytes(ByteBuffer source) { +- this.source.writeBytes(source); ++ public FriendlyByteBuf writeBytes(ByteBuffer bytebuffer) { ++ this.source.writeBytes(bytebuffer); + return this; + } + +- @Override +- public int writeBytes(InputStream in, int length) throws IOException { +- return this.source.writeBytes(in, length); ++ public int writeBytes(InputStream inputstream, int i) throws IOException { ++ return this.source.writeBytes(inputstream, i); + } + +- @Override +- public int writeBytes(ScatteringByteChannel in, int length) throws IOException { +- return this.source.writeBytes(in, length); ++ public int writeBytes(ScatteringByteChannel scatteringbytechannel, int i) throws IOException { ++ return this.source.writeBytes(scatteringbytechannel, i); + } + +- @Override +- public int writeBytes(FileChannel in, long position, int length) throws IOException { +- return this.source.writeBytes(in, position, length); ++ public int writeBytes(FileChannel filechannel, long i, int j) throws IOException { ++ return this.source.writeBytes(filechannel, i, j); + } + +- @Override +- public FriendlyByteBuf writeZero(int length) { +- this.source.writeZero(length); ++ public FriendlyByteBuf writeZero(int i) { ++ this.source.writeZero(i); + return this; + } + +- @Override +- public int writeCharSequence(CharSequence charSequence, Charset charset) { +- return this.source.writeCharSequence(charSequence, charset); ++ public int writeCharSequence(CharSequence charsequence, Charset charset) { ++ return this.source.writeCharSequence(charsequence, charset); + } + +- @Override +- public int indexOf(int fromIndex, int toIndex, byte value) { +- return this.source.indexOf(fromIndex, toIndex, value); ++ public int indexOf(int i, int j, byte b0) { ++ return this.source.indexOf(i, j, b0); + } + +- @Override +- public int bytesBefore(byte value) { +- return this.source.bytesBefore(value); ++ public int bytesBefore(byte b0) { ++ return this.source.bytesBefore(b0); + } + +- @Override +- public int bytesBefore(int length, byte value) { +- return this.source.bytesBefore(length, value); ++ public int bytesBefore(int i, byte b0) { ++ return this.source.bytesBefore(i, b0); + } + +- @Override +- public int bytesBefore(int index, int length, byte value) { +- return this.source.bytesBefore(index, length, value); ++ public int bytesBefore(int i, int j, byte b0) { ++ return this.source.bytesBefore(i, j, b0); + } + +- @Override +- public int forEachByte(ByteProcessor processor) { +- return this.source.forEachByte(processor); ++ public int forEachByte(ByteProcessor byteprocessor) { ++ return this.source.forEachByte(byteprocessor); + } + +- @Override +- public int forEachByte(int index, int length, ByteProcessor processor) { +- return this.source.forEachByte(index, length, processor); ++ public int forEachByte(int i, int j, ByteProcessor byteprocessor) { ++ return this.source.forEachByte(i, j, byteprocessor); + } + +- @Override +- public int forEachByteDesc(ByteProcessor processor) { +- return this.source.forEachByteDesc(processor); ++ public int forEachByteDesc(ByteProcessor byteprocessor) { ++ return this.source.forEachByteDesc(byteprocessor); + } + +- @Override +- public int forEachByteDesc(int index, int length, ByteProcessor processor) { +- return this.source.forEachByteDesc(index, length, processor); ++ public int forEachByteDesc(int i, int j, ByteProcessor byteprocessor) { ++ return this.source.forEachByteDesc(i, j, byteprocessor); + } + +- @Override + public ByteBuf copy() { + return this.source.copy(); + } + +- @Override +- public ByteBuf copy(int index, int length) { +- return this.source.copy(index, length); ++ public ByteBuf copy(int i, int j) { ++ return this.source.copy(i, j); + } + +- @Override + public ByteBuf slice() { + return this.source.slice(); + } + +- @Override + public ByteBuf retainedSlice() { + return this.source.retainedSlice(); + } + +- @Override +- public ByteBuf slice(int index, int length) { +- return this.source.slice(index, length); ++ public ByteBuf slice(int i, int j) { ++ return this.source.slice(i, j); + } + +- @Override +- public ByteBuf retainedSlice(int index, int length) { +- return this.source.retainedSlice(index, length); ++ public ByteBuf retainedSlice(int i, int j) { ++ return this.source.retainedSlice(i, j); + } + +- @Override + public ByteBuf duplicate() { + return this.source.duplicate(); + } + +- @Override + public ByteBuf retainedDuplicate() { + return this.source.retainedDuplicate(); + } + +- @Override + public int nioBufferCount() { + return this.source.nioBufferCount(); + } + +- @Override + public ByteBuffer nioBuffer() { + return this.source.nioBuffer(); + } + +- @Override +- public ByteBuffer nioBuffer(int index, int length) { +- return this.source.nioBuffer(index, length); ++ public ByteBuffer nioBuffer(int i, int j) { ++ return this.source.nioBuffer(i, j); + } + +- @Override +- public ByteBuffer internalNioBuffer(int index, int length) { +- return this.source.internalNioBuffer(index, length); ++ public ByteBuffer internalNioBuffer(int i, int j) { ++ return this.source.internalNioBuffer(i, j); + } + +- @Override + public ByteBuffer[] nioBuffers() { + return this.source.nioBuffers(); + } + +- @Override +- public ByteBuffer[] nioBuffers(int index, int length) { +- return this.source.nioBuffers(index, length); ++ public ByteBuffer[] nioBuffers(int i, int j) { ++ return this.source.nioBuffers(i, j); + } + +- @Override + public boolean hasArray() { + return this.source.hasArray(); + } + +- @Override + public byte[] array() { + return this.source.array(); + } + +- @Override + public int arrayOffset() { + return this.source.arrayOffset(); + } + +- @Override + public boolean hasMemoryAddress() { + return this.source.hasMemoryAddress(); + } + +- @Override + public long memoryAddress() { + return this.source.memoryAddress(); + } + +- @Override + public String toString(Charset charset) { + return this.source.toString(charset); + } + +- @Override +- public String toString(int index, int length, Charset charset) { +- return this.source.toString(index, length, charset); ++ public String toString(int i, int j, Charset charset) { ++ return this.source.toString(i, j, charset); + } + +- @Override + public int hashCode() { + return this.source.hashCode(); + } + +- @Override +- public boolean equals(Object other) { +- return this.source.equals(other); ++ public boolean equals(Object object) { ++ return this.source.equals(object); + } + +- @Override +- public int compareTo(ByteBuf other) { +- return this.source.compareTo(other); ++ public int compareTo(ByteBuf bytebuf) { ++ return this.source.compareTo(bytebuf); + } + +- @Override + public String toString() { + return this.source.toString(); + } + +- @Override +- public FriendlyByteBuf retain(int increment) { +- this.source.retain(increment); ++ public FriendlyByteBuf retain(int i) { ++ this.source.retain(i); + return this; + } + +- @Override + public FriendlyByteBuf retain() { + this.source.retain(); + return this; + } + +- @Override + public FriendlyByteBuf touch() { + this.source.touch(); + return this; + } + +- @Override +- public FriendlyByteBuf touch(Object hint) { +- this.source.touch(hint); ++ public FriendlyByteBuf touch(Object object) { ++ this.source.touch(object); + return this; + } + +- @Override + public int refCnt() { + return this.source.refCnt(); + } + +- @Override + public boolean release() { + return this.source.release(); + } + +- @Override +- public boolean release(int decrement) { +- return this.source.release(decrement); ++ public boolean release(int i) { ++ return this.source.release(i); + } + + @FunctionalInterface +- public interface Reader extends Function { +- default FriendlyByteBuf.Reader> asOptional() { +- return friendlyByteBuf -> friendlyByteBuf.readOptional(this); ++ public interface b extends BiConsumer { ++ ++ default FriendlyByteBuf.b> asOptional() { ++ return (packetdataserializer, optional) -> { ++ packetdataserializer.writeOptional(optional, this); ++ }; + } + } + + @FunctionalInterface +- public interface Writer extends BiConsumer { +- default FriendlyByteBuf.Writer> asOptional() { +- return (friendlyByteBuf, optional) -> friendlyByteBuf.writeOptional(optional, this); ++ public interface a extends Function { ++ ++ default FriendlyByteBuf.a> asOptional() { ++ return (packetdataserializer) -> { ++ return packetdataserializer.readOptional(this); ++ }; + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/network/chat/Component.java.patch b/patch-remap/mache-vineflower/net/minecraft/network/chat/Component.java.patch new file mode 100644 index 0000000000..cdb34a0911 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/network/chat/Component.java.patch @@ -0,0 +1,347 @@ +--- a/net/minecraft/network/chat/Component.java ++++ b/net/minecraft/network/chat/Component.java +@@ -18,6 +18,7 @@ + import java.util.ArrayList; + import java.util.Collections; + import java.util.Date; ++import java.util.Iterator; + import java.util.List; + import java.util.Optional; + import java.util.UUID; +@@ -25,16 +26,31 @@ + import net.minecraft.Util; + import net.minecraft.network.chat.contents.DataSource; + import net.minecraft.network.chat.contents.KeybindContents; ++import net.minecraft.network.chat.contents.LiteralContents; + import net.minecraft.network.chat.contents.NbtContents; +-import net.minecraft.network.chat.contents.PlainTextContents; + import net.minecraft.network.chat.contents.ScoreContents; + import net.minecraft.network.chat.contents.SelectorContents; + import net.minecraft.network.chat.contents.TranslatableContents; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.util.FormattedCharSequence; + import net.minecraft.world.level.ChunkPos; ++// CraftBukkit start ++import java.util.stream.Stream; ++// CraftBukkit end + +-public interface Component extends Message, FormattedText { ++public interface Component extends Message, FormattedText, Iterable { // CraftBukkit ++ ++ // CraftBukkit start ++ default Stream stream() { ++ return com.google.common.collect.Streams.concat(new Stream[]{Stream.of(this), this.getSiblings().stream().flatMap(Component::stream)}); ++ } ++ ++ @Override ++ default Iterator iterator() { ++ return this.stream().iterator(); ++ } ++ // CraftBukkit end ++ + Style getStyle(); + + ComponentContents getContents(); +@@ -45,25 +61,33 @@ + } + + default String getString(int maxLength) { +- StringBuilder stringBuilder = new StringBuilder(); +- this.visit(content -> { +- int i = maxLength - stringBuilder.length(); +- if (i <= 0) { +- return STOP_ITERATION; ++ StringBuilder stringbuilder = new StringBuilder(); ++ ++ this.visit((s) -> { ++ int j = maxLength - stringbuilder.length(); ++ ++ if (j <= 0) { ++ return Component.STOP_ITERATION; + } else { +- stringBuilder.append(content.length() <= i ? content : content.substring(0, i)); ++ stringbuilder.append(s.length() <= j ? s : s.substring(0, j)); + return Optional.empty(); + } + }); +- return stringBuilder.toString(); ++ return stringbuilder.toString(); + } + + List getSiblings(); + + @Nullable + default String tryCollapseToString() { +- if (this.getContents() instanceof PlainTextContents plainTextContents && this.getSiblings().isEmpty() && this.getStyle().isEmpty()) { +- return plainTextContents.text(); ++ ComponentContents componentcontents = this.getContents(); ++ ++ if (componentcontents instanceof LiteralContents) { ++ LiteralContents literalcontents = (LiteralContents) componentcontents; ++ ++ if (this.getSiblings().isEmpty() && this.getStyle().isEmpty()) { ++ return literalcontents.text(); ++ } + } + + return null; +@@ -74,43 +98,59 @@ + } + + default MutableComponent copy() { +- return new MutableComponent(this.getContents(), new ArrayList<>(this.getSiblings()), this.getStyle()); ++ return new MutableComponent(this.getContents(), new ArrayList(this.getSiblings()), this.getStyle()); + } + + FormattedCharSequence getVisualOrderText(); + + @Override + default Optional visit(FormattedText.StyledContentConsumer acceptor, Style style) { +- Style style1 = this.getStyle().applyTo(style); +- Optional optional = this.getContents().visit(acceptor, style1); ++ Style chatmodifier1 = this.getStyle().applyTo(style); ++ Optional optional = this.getContents().visit(acceptor, chatmodifier1); ++ + if (optional.isPresent()) { + return optional; + } else { +- for (Component component : this.getSiblings()) { +- Optional optional1 = component.visit(acceptor, style1); +- if (optional1.isPresent()) { +- return optional1; ++ Iterator iterator = this.getSiblings().iterator(); ++ ++ Optional optional1; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return Optional.empty(); + } +- } + +- return Optional.empty(); ++ Component ichatbasecomponent = (Component) iterator.next(); ++ ++ optional1 = ichatbasecomponent.visit(acceptor, chatmodifier1); ++ } while (!optional1.isPresent()); ++ ++ return optional1; + } + } + + @Override + default Optional visit(FormattedText.ContentConsumer acceptor) { + Optional optional = this.getContents().visit(acceptor); ++ + if (optional.isPresent()) { + return optional; + } else { +- for (Component component : this.getSiblings()) { +- Optional optional1 = component.visit(acceptor); +- if (optional1.isPresent()) { +- return optional1; ++ Iterator iterator = this.getSiblings().iterator(); ++ ++ Optional optional1; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return Optional.empty(); + } +- } + +- return Optional.empty(); ++ Component ichatbasecomponent = (Component) iterator.next(); ++ ++ optional1 = ichatbasecomponent.visit(acceptor); ++ } while (!optional1.isPresent()); ++ ++ return optional1; + } + } + +@@ -120,9 +160,10 @@ + + default List toFlatList(Style style) { + List list = Lists.newArrayList(); +- this.visit((style1, content) -> { +- if (!content.isEmpty()) { +- list.add(literal(content).withStyle(style1)); ++ ++ this.visit((chatmodifier1, s) -> { ++ if (!s.isEmpty()) { ++ list.add(literal(s).withStyle(chatmodifier1)); + } + + return Optional.empty(); +@@ -136,35 +177,37 @@ + } else { + List list = this.toFlatList(); + List list1 = other.toFlatList(this.getStyle()); ++ + return Collections.indexOfSubList(list, list1) != -1; + } + } + + static Component nullToEmpty(@Nullable String text) { +- return (Component)(text != null ? literal(text) : CommonComponents.EMPTY); ++ return (Component) (text != null ? literal(text) : CommonComponents.EMPTY); + } + + static MutableComponent literal(String text) { +- return MutableComponent.create(PlainTextContents.create(text)); ++ return MutableComponent.create(LiteralContents.create(text)); + } + + static MutableComponent translatable(String key) { +- return MutableComponent.create(new TranslatableContents(key, null, TranslatableContents.NO_ARGS)); ++ return MutableComponent.create(new TranslatableContents(key, (String) null, TranslatableContents.NO_ARGS)); + } + + static MutableComponent translatable(String key, Object... args) { +- return MutableComponent.create(new TranslatableContents(key, null, args)); ++ return MutableComponent.create(new TranslatableContents(key, (String) null, args)); + } + +- static MutableComponent translatableEscape(String string, Object... objects) { +- for (int i = 0; i < objects.length; i++) { +- Object object = objects[i]; ++ static MutableComponent translatableEscape(String s, Object... aobject) { ++ for (int i = 0; i < aobject.length; ++i) { ++ Object object = aobject[i]; ++ + if (!TranslatableContents.isAllowedPrimitiveArgument(object) && !(object instanceof Component)) { +- objects[i] = String.valueOf(object); ++ aobject[i] = String.valueOf(object); + } + } + +- return translatable(string, objects); ++ return translatable(s, aobject); + } + + static MutableComponent translatableWithFallback(String key, @Nullable String fallback) { +@@ -176,7 +219,7 @@ + } + + static MutableComponent empty() { +- return MutableComponent.create(PlainTextContents.EMPTY); ++ return MutableComponent.create(LiteralContents.EMPTY); + } + + static MutableComponent keybind(String name) { +@@ -200,37 +243,60 @@ + } + + static Component translationArg(Message message) { +- return (Component)(message instanceof Component component ? component : literal(message.getString())); ++ Object object; ++ ++ if (message instanceof Component) { ++ Component ichatbasecomponent = (Component) message; ++ ++ object = ichatbasecomponent; ++ } else { ++ object = literal(message.getString()); ++ } ++ ++ return (Component) object; + } + +- static Component translationArg(UUID uUID) { +- return literal(uUID.toString()); ++ static Component translationArg(UUID uuid) { ++ return literal(uuid.toString()); + } + +- static Component translationArg(ResourceLocation resourceLocation) { +- return literal(resourceLocation.toString()); ++ static Component translationArg(ResourceLocation minecraftkey) { ++ return literal(minecraftkey.toString()); + } + +- static Component translationArg(ChunkPos chunkPos) { +- return literal(chunkPos.toString()); ++ static Component translationArg(ChunkPos chunkcoordintpair) { ++ return literal(chunkcoordintpair.toString()); + } + +- public static class Serializer { +- private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create(); ++ public static class b implements JsonDeserializer, JsonSerializer { + +- private Serializer() { ++ public b() {} ++ ++ public MutableComponent deserialize(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException { ++ return Component.Serializer.deserialize(jsonelement); + } + +- static MutableComponent deserialize(JsonElement jsonElement) { +- return (MutableComponent)Util.getOrThrow(ComponentSerialization.CODEC.parse(JsonOps.INSTANCE, jsonElement), JsonParseException::new); ++ public JsonElement serialize(Component ichatbasecomponent, Type type, JsonSerializationContext jsonserializationcontext) { ++ return Component.Serializer.serialize(ichatbasecomponent); + } ++ } + +- static JsonElement serialize(Component component) { +- return Util.getOrThrow(ComponentSerialization.CODEC.encodeStart(JsonOps.INSTANCE, component), JsonParseException::new); ++ public static class Serializer { ++ ++ private static final Gson GSON = (new GsonBuilder()).disableHtmlEscaping().create(); ++ ++ private Serializer() {} ++ ++ static MutableComponent deserialize(JsonElement jsonelement) { ++ return (MutableComponent) Util.getOrThrow(ComponentSerialization.CODEC.parse(JsonOps.INSTANCE, jsonelement), JsonParseException::new); + } + ++ static JsonElement serialize(Component ichatbasecomponent) { ++ return (JsonElement) Util.getOrThrow(ComponentSerialization.CODEC.encodeStart(JsonOps.INSTANCE, ichatbasecomponent), JsonParseException::new); ++ } ++ + public static String toJson(Component component) { +- return GSON.toJson(serialize(component)); ++ return Component.Serializer.GSON.toJson(serialize(component)); + } + + public static JsonElement toJsonTree(Component component) { +@@ -239,8 +305,9 @@ + + @Nullable + public static MutableComponent fromJson(String json) { +- JsonElement jsonElement = JsonParser.parseString(json); +- return jsonElement == null ? null : deserialize(jsonElement); ++ JsonElement jsonelement = JsonParser.parseString(json); ++ ++ return jsonelement == null ? null : deserialize(jsonelement); + } + + @Nullable +@@ -250,22 +317,12 @@ + + @Nullable + public static MutableComponent fromJsonLenient(String json) { +- JsonReader jsonReader = new JsonReader(new StringReader(json)); +- jsonReader.setLenient(true); +- JsonElement jsonElement = JsonParser.parseReader(jsonReader); +- return jsonElement == null ? null : deserialize(jsonElement); +- } +- } ++ JsonReader jsonreader = new JsonReader(new StringReader(json)); + +- public static class SerializerAdapter implements JsonDeserializer, JsonSerializer { +- @Override +- public MutableComponent deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { +- return Component.Serializer.deserialize(jsonElement); +- } ++ jsonreader.setLenient(true); ++ JsonElement jsonelement = JsonParser.parseReader(jsonreader); + +- @Override +- public JsonElement serialize(Component component, Type type, JsonSerializationContext jsonSerializationContext) { +- return Component.Serializer.serialize(component); ++ return jsonelement == null ? null : deserialize(jsonelement); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/network/chat/TextColor.java.patch b/patch-remap/mache-vineflower/net/minecraft/network/chat/TextColor.java.patch new file mode 100644 index 0000000000..0a26692999 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/network/chat/TextColor.java.patch @@ -0,0 +1,122 @@ +--- a/net/minecraft/network/chat/TextColor.java ++++ b/net/minecraft/network/chat/TextColor.java +@@ -13,27 +13,34 @@ + import net.minecraft.ChatFormatting; + + public final class TextColor { ++ + private static final String CUSTOM_COLOR_PREFIX = "#"; + public static final Codec CODEC = Codec.STRING.comapFlatMap(TextColor::parseColor, TextColor::serialize); +- private static final Map LEGACY_FORMAT_TO_COLOR = Stream.of(ChatFormatting.values()) +- .filter(ChatFormatting::isColor) +- .collect(ImmutableMap.toImmutableMap(Function.identity(), chatFormatting -> new TextColor(chatFormatting.getColor(), chatFormatting.getName()))); +- private static final Map NAMED_COLORS = LEGACY_FORMAT_TO_COLOR.values() +- .stream() +- .collect(ImmutableMap.toImmutableMap(textColor -> textColor.name, Function.identity())); ++ private static final Map LEGACY_FORMAT_TO_COLOR = (Map) Stream.of(ChatFormatting.values()).filter(ChatFormatting::isColor).collect(ImmutableMap.toImmutableMap(Function.identity(), (enumchatformat) -> { ++ return new TextColor(enumchatformat.getColor(), enumchatformat.getName(), enumchatformat); // CraftBukkit ++ })); ++ private static final Map NAMED_COLORS = (Map) TextColor.LEGACY_FORMAT_TO_COLOR.values().stream().collect(ImmutableMap.toImmutableMap((chathexcolor) -> { ++ return chathexcolor.name; ++ }, Function.identity())); + private final int value; + @Nullable +- private final String name; ++ public final String name; ++ // CraftBukkit start ++ @Nullable ++ public final ChatFormatting format; + +- private TextColor(int value, String name) { +- this.value = value & 16777215; +- this.name = name; ++ private TextColor(int i, String s, ChatFormatting format) { ++ this.value = i & 16777215; ++ this.name = s; ++ this.format = format; + } + + private TextColor(int value) { + this.value = value & 16777215; + this.name = null; ++ this.format = null; + } ++ // CraftBukkit end + + public int getValue() { + return this.value; +@@ -47,50 +54,54 @@ + return String.format(Locale.ROOT, "#%06X", this.value); + } + +- @Override +- public boolean equals(Object other) { +- if (this == other) { ++ public boolean equals(Object object) { ++ if (this == object) { + return true; +- } else if (other != null && this.getClass() == other.getClass()) { +- TextColor textColor = (TextColor)other; +- return this.value == textColor.value; ++ } else if (object != null && this.getClass() == object.getClass()) { ++ TextColor chathexcolor = (TextColor) object; ++ ++ return this.value == chathexcolor.value; + } else { + return false; + } + } + +- @Override + public int hashCode() { +- return Objects.hash(this.value, this.name); ++ return Objects.hash(new Object[]{this.value, this.name}); + } + +- @Override + public String toString() { + return this.serialize(); + } + + @Nullable + public static TextColor fromLegacyFormat(ChatFormatting formatting) { +- return LEGACY_FORMAT_TO_COLOR.get(formatting); ++ return (TextColor) TextColor.LEGACY_FORMAT_TO_COLOR.get(formatting); + } + + public static TextColor fromRgb(int color) { + return new TextColor(color); + } + +- public static DataResult parseColor(String string) { +- if (string.startsWith("#")) { ++ public static DataResult parseColor(String s) { ++ if (s.startsWith("#")) { + try { +- int i = Integer.parseInt(string.substring(1), 16); +- return i >= 0 && i <= 16777215 +- ? DataResult.success(fromRgb(i), Lifecycle.stable()) +- : DataResult.error(() -> "Color value out of range: " + string); +- } catch (NumberFormatException var2) { +- return DataResult.error(() -> "Invalid color value: " + string); ++ int i = Integer.parseInt(s.substring(1), 16); ++ ++ return i >= 0 && i <= 16777215 ? DataResult.success(fromRgb(i), Lifecycle.stable()) : DataResult.error(() -> { ++ return "Color value out of range: " + s; ++ }); ++ } catch (NumberFormatException numberformatexception) { ++ return DataResult.error(() -> { ++ return "Invalid color value: " + s; ++ }); + } + } else { +- TextColor textColor = NAMED_COLORS.get(string); +- return textColor == null ? DataResult.error(() -> "Invalid color name: " + string) : DataResult.success(textColor, Lifecycle.stable()); ++ TextColor chathexcolor = (TextColor) TextColor.NAMED_COLORS.get(s); ++ ++ return chathexcolor == null ? DataResult.error(() -> { ++ return "Invalid color name: " + s; ++ }) : DataResult.success(chathexcolor, Lifecycle.stable()); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/network/protocol/PacketUtils.java.patch b/patch-remap/mache-vineflower/net/minecraft/network/protocol/PacketUtils.java.patch new file mode 100644 index 0000000000..bcdb7c2578 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/network/protocol/PacketUtils.java.patch @@ -0,0 +1,101 @@ +--- a/net/minecraft/network/protocol/PacketUtils.java ++++ b/net/minecraft/network/protocol/PacketUtils.java +@@ -4,46 +4,72 @@ + import net.minecraft.CrashReport; + import net.minecraft.ReportedException; + import net.minecraft.network.PacketListener; +-import net.minecraft.server.RunningOnDifferentThreadException; ++import net.minecraft.server.CancelledPacketHandleException; ++import org.slf4j.Logger; ++ ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.network.ServerCommonPacketListenerImpl; ++// CraftBukkit end + import net.minecraft.util.thread.BlockableEventLoop; +-import org.slf4j.Logger; + + public class PacketUtils { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + +- public static void ensureRunningOnSameThread(Packet packet, T processor, ServerLevel level) throws RunningOnDifferentThreadException { +- ensureRunningOnSameThread(packet, processor, level.getServer()); ++ public PacketUtils() {} ++ ++ public static void ensureRunningOnSameThread(Packet packet, T processor, ServerLevel level) throws CancelledPacketHandleException { ++ ensureRunningOnSameThread(packet, processor, (BlockableEventLoop) level.getServer()); + } + +- public static void ensureRunningOnSameThread(Packet packet, T processor, BlockableEventLoop executor) throws RunningOnDifferentThreadException { ++ public static void ensureRunningOnSameThread(Packet packet, T processor, BlockableEventLoop executor) throws CancelledPacketHandleException { + if (!executor.isSameThread()) { +- executor.executeIfPossible( +- () -> { +- if (processor.shouldHandleMessage(packet)) { +- try { +- packet.handle(processor); +- } catch (Exception var6) { +- if (var6 instanceof ReportedException reportedException && reportedException.getCause() instanceof OutOfMemoryError +- || processor.shouldPropagateHandlingExceptions()) { +- if (var6 instanceof ReportedException reportedException1) { +- processor.fillCrashReport(reportedException1.getReport()); +- throw var6; ++ executor.executeIfPossible(() -> { ++ if (MinecraftServer.getServer().hasStopped() || (processor instanceof ServerCommonPacketListenerImpl && ((ServerCommonPacketListenerImpl) processor).processedDisconnect)) return; // CraftBukkit, MC-142590 ++ if (processor.shouldHandleMessage(packet)) { ++ try { ++ packet.handle(processor); ++ } catch (Exception exception) { ++ label25: ++ { ++ if (exception instanceof ReportedException) { ++ ReportedException reportedexception = (ReportedException) exception; ++ ++ if (reportedexception.getCause() instanceof OutOfMemoryError) { ++ break label25; + } +- +- CrashReport crashReport = CrashReport.forThrowable(var6, "Main thread packet handler"); +- processor.fillCrashReport(crashReport); +- throw new ReportedException(crashReport); + } +- +- LOGGER.error("Failed to handle packet {}, suppressing error", packet, var6); ++ ++ if (!processor.shouldPropagateHandlingExceptions()) { ++ PacketUtils.LOGGER.error("Failed to handle packet {}, suppressing error", packet, exception); ++ return; ++ } + } +- } else { +- LOGGER.debug("Ignoring packet due to disconnection: {}", packet); ++ ++ if (exception instanceof ReportedException) { ++ ReportedException reportedexception1 = (ReportedException) exception; ++ ++ processor.fillCrashReport(reportedexception1.getReport()); ++ throw exception; ++ } ++ ++ CrashReport crashreport = CrashReport.forThrowable(exception, "Main thread packet handler"); ++ ++ processor.fillCrashReport(crashreport); ++ throw new ReportedException(crashreport); + } ++ } else { ++ PacketUtils.LOGGER.debug("Ignoring packet due to disconnection: {}", packet); + } +- ); +- throw RunningOnDifferentThreadException.RUNNING_ON_DIFFERENT_THREAD; ++ ++ }); ++ throw CancelledPacketHandleException.RUNNING_ON_DIFFERENT_THREAD; ++ // CraftBukkit start - SPIGOT-5477, MC-142590 ++ } else if (MinecraftServer.getServer().hasStopped() || (processor instanceof ServerCommonPacketListenerImpl && ((ServerCommonPacketListenerImpl) processor).processedDisconnect)) { ++ throw CancelledPacketHandleException.RUNNING_ON_DIFFERENT_THREAD; ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java.patch b/patch-remap/mache-vineflower/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java.patch new file mode 100644 index 0000000000..ae35fedaf7 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java ++++ b/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java +@@ -10,27 +10,27 @@ + import net.minecraft.resources.ResourceLocation; + + public record ServerboundCustomPayloadPacket(CustomPacketPayload payload) implements Packet { ++ + private static final int MAX_PAYLOAD_SIZE = 32767; +- private static final Map> KNOWN_TYPES = ImmutableMap.>builder( +- +- ) +- .put(BrandPayload.ID, BrandPayload::new) +- .build(); ++ private static final Map> KNOWN_TYPES = ImmutableMap.>builder().build(); // CraftBukkit - no special handling + +- public ServerboundCustomPayloadPacket(FriendlyByteBuf friendlyByteBuf) { +- this(readPayload(friendlyByteBuf.readResourceLocation(), friendlyByteBuf)); ++ public ServerboundCustomPayloadPacket(FriendlyByteBuf packetdataserializer) { ++ this(readPayload(packetdataserializer.readResourceLocation(), packetdataserializer)); + } + +- private static CustomPacketPayload readPayload(ResourceLocation resourceLocation, FriendlyByteBuf friendlyByteBuf) { +- FriendlyByteBuf.Reader reader = KNOWN_TYPES.get(resourceLocation); +- return (CustomPacketPayload)(reader != null ? reader.apply(friendlyByteBuf) : readUnknownPayload(resourceLocation, friendlyByteBuf)); ++ private static CustomPacketPayload readPayload(ResourceLocation minecraftkey, FriendlyByteBuf packetdataserializer) { ++ FriendlyByteBuf.a packetdataserializer_a = (FriendlyByteBuf.a) ServerboundCustomPayloadPacket.KNOWN_TYPES.get(minecraftkey); ++ ++ return (CustomPacketPayload) (packetdataserializer_a != null ? (CustomPacketPayload) packetdataserializer_a.apply(packetdataserializer) : readUnknownPayload(minecraftkey, packetdataserializer)); + } + +- private static DiscardedPayload readUnknownPayload(ResourceLocation resourceLocation, FriendlyByteBuf friendlyByteBuf) { +- int i = friendlyByteBuf.readableBytes(); ++ private static UnknownPayload readUnknownPayload(ResourceLocation minecraftkey, FriendlyByteBuf packetdataserializer) { // CraftBukkit ++ int i = packetdataserializer.readableBytes(); ++ + if (i >= 0 && i <= 32767) { +- friendlyByteBuf.skipBytes(i); +- return new DiscardedPayload(resourceLocation); ++ // CraftBukkit start ++ return new UnknownPayload(minecraftkey, packetdataserializer.readBytes(i)); ++ // CraftBukkit end + } else { + throw new IllegalArgumentException("Payload may not be larger than 32767 bytes"); + } +@@ -42,8 +42,17 @@ + this.payload.write(buffer); + } + +- @Override + public void handle(ServerCommonPacketListener handler) { + handler.handleCustomPayload(this); + } ++ ++ // CraftBukkit start ++ public record UnknownPayload(ResourceLocation id, io.netty.buffer.ByteBuf data) implements CustomPacketPayload { ++ ++ @Override ++ public void write(FriendlyByteBuf packetdataserializer) { ++ packetdataserializer.writeBytes(data); ++ } ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java.patch b/patch-remap/mache-vineflower/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java.patch new file mode 100644 index 0000000000..1143697c4a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java ++++ b/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java +@@ -5,6 +5,7 @@ + import net.minecraft.world.level.border.WorldBorder; + + public class ClientboundInitializeBorderPacket implements Packet { ++ + private final double newCenterX; + private final double newCenterZ; + private final double oldSize; +@@ -26,8 +27,10 @@ + } + + public ClientboundInitializeBorderPacket(WorldBorder worldBorder) { +- this.newCenterX = worldBorder.getCenterX(); +- this.newCenterZ = worldBorder.getCenterZ(); ++ // CraftBukkit start - multiply out nether border ++ this.newCenterX = worldBorder.getCenterX() * worldBorder.world.dimensionType().coordinateScale(); ++ this.newCenterZ = worldBorder.getCenterZ() * worldBorder.world.dimensionType().coordinateScale(); ++ // CraftBukkit end + this.oldSize = worldBorder.getSize(); + this.newSize = worldBorder.getLerpTarget(); + this.lerpTime = worldBorder.getLerpRemainingTime(); +@@ -48,7 +51,6 @@ + buffer.writeVarInt(this.warningTime); + } + +- @Override + public void handle(ClientGamePacketListener handler) { + handler.handleInitializeBorder(this); + } diff --git a/patch-remap/mache-vineflower/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java.patch b/patch-remap/mache-vineflower/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java.patch new file mode 100644 index 0000000000..0ff164615d --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java.patch @@ -0,0 +1,117 @@ +--- a/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java ++++ b/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java +@@ -1,5 +1,6 @@ + package net.minecraft.network.protocol.game; + ++import it.unimi.dsi.fastutil.shorts.ShortIterator; + import it.unimi.dsi.fastutil.shorts.ShortSet; + import java.util.function.BiConsumer; + import net.minecraft.core.BlockPos; +@@ -7,40 +8,55 @@ + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.protocol.Packet; + import net.minecraft.world.level.block.Block; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.LevelChunkSection; + + public class ClientboundSectionBlocksUpdatePacket implements Packet { ++ + private static final int POS_IN_SECTION_BITS = 12; + private final SectionPos sectionPos; + private final short[] positions; +- private final BlockState[] states; ++ private final IBlockData[] states; + + public ClientboundSectionBlocksUpdatePacket(SectionPos sectionPos, ShortSet positions, LevelChunkSection section) { + this.sectionPos = sectionPos; +- int size = positions.size(); +- this.positions = new short[size]; +- this.states = new BlockState[size]; +- int i = 0; ++ int i = positions.size(); + +- for (short s : positions) { +- this.positions[i] = s; +- this.states[i] = section.getBlockState(SectionPos.sectionRelativeX(s), SectionPos.sectionRelativeY(s), SectionPos.sectionRelativeZ(s)); +- i++; ++ this.positions = new short[i]; ++ this.states = new IBlockData[i]; ++ int j = 0; ++ ++ for (ShortIterator shortiterator = positions.iterator(); shortiterator.hasNext(); ++j) { ++ short short0 = (Short) shortiterator.next(); ++ ++ this.positions[j] = short0; ++ this.states[j] = (section != null) ? section.getBlockState(SectionPos.sectionRelativeX(short0), SectionPos.sectionRelativeY(short0), SectionPos.sectionRelativeZ(short0)) : net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(); // CraftBukkit - SPIGOT-6076, Mojang bug when empty chunk section notified + } ++ + } + ++ // CraftBukkit start - Add constructor ++ public ClientboundSectionBlocksUpdatePacket(SectionPos sectionposition, ShortSet shortset, IBlockData[] states) { ++ this.sectionPos = sectionposition; ++ this.positions = shortset.toShortArray(); ++ this.states = states; ++ } ++ // CraftBukkit end ++ + public ClientboundSectionBlocksUpdatePacket(FriendlyByteBuf buffer) { + this.sectionPos = SectionPos.of(buffer.readLong()); +- int varInt = buffer.readVarInt(); +- this.positions = new short[varInt]; +- this.states = new BlockState[varInt]; ++ int i = buffer.readVarInt(); + +- for (int i = 0; i < varInt; i++) { +- long varLong = buffer.readVarLong(); +- this.positions[i] = (short)((int)(varLong & 4095L)); +- this.states[i] = Block.BLOCK_STATE_REGISTRY.byId((int)(varLong >>> 12)); ++ this.positions = new short[i]; ++ this.states = new IBlockData[i]; ++ ++ for (int j = 0; j < i; ++j) { ++ long k = buffer.readVarLong(); ++ ++ this.positions[j] = (short) ((int) (k & 4095L)); ++ this.states[j] = (IBlockData) Block.BLOCK_STATE_REGISTRY.byId((int) (k >>> 12)); + } ++ + } + + @Override +@@ -48,23 +64,25 @@ + buffer.writeLong(this.sectionPos.asLong()); + buffer.writeVarInt(this.positions.length); + +- for (int i = 0; i < this.positions.length; i++) { +- buffer.writeVarLong((long)Block.getId(this.states[i]) << 12 | (long)this.positions[i]); ++ for (int i = 0; i < this.positions.length; ++i) { ++ buffer.writeVarLong((long) Block.getId(this.states[i]) << 12 | (long) this.positions[i]); + } ++ + } + +- @Override + public void handle(ClientGamePacketListener handler) { + handler.handleChunkBlocksUpdate(this); + } + +- public void runUpdates(BiConsumer consumer) { +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ public void runUpdates(BiConsumer consumer) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + +- for (int i = 0; i < this.positions.length; i++) { +- short s = this.positions[i]; +- mutableBlockPos.set(this.sectionPos.relativeToBlockX(s), this.sectionPos.relativeToBlockY(s), this.sectionPos.relativeToBlockZ(s)); +- consumer.accept(mutableBlockPos, this.states[i]); ++ for (int i = 0; i < this.positions.length; ++i) { ++ short short0 = this.positions[i]; ++ ++ blockposition_mutableblockposition.set(this.sectionPos.relativeToBlockX(short0), this.sectionPos.relativeToBlockY(short0), this.sectionPos.relativeToBlockZ(short0)); ++ consumer.accept(blockposition_mutableblockposition, this.states[i]); + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java.patch b/patch-remap/mache-vineflower/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java.patch new file mode 100644 index 0000000000..0470cad420 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java.patch @@ -0,0 +1,28 @@ +--- a/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java ++++ b/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java +@@ -5,12 +5,15 @@ + import net.minecraft.world.level.border.WorldBorder; + + public class ClientboundSetBorderCenterPacket implements Packet { ++ + private final double newCenterX; + private final double newCenterZ; + + public ClientboundSetBorderCenterPacket(WorldBorder worldBorder) { +- this.newCenterX = worldBorder.getCenterX(); +- this.newCenterZ = worldBorder.getCenterZ(); ++ // CraftBukkit start - multiply out nether border ++ this.newCenterX = worldBorder.getCenterX() * (worldBorder.world != null ? worldBorder.world.dimensionType().coordinateScale() : 1.0); ++ this.newCenterZ = worldBorder.getCenterZ() * (worldBorder.world != null ? worldBorder.world.dimensionType().coordinateScale() : 1.0); ++ // CraftBukkit end + } + + public ClientboundSetBorderCenterPacket(FriendlyByteBuf buffer) { +@@ -24,7 +27,6 @@ + buffer.writeDouble(this.newCenterZ); + } + +- @Override + public void handle(ClientGamePacketListener handler) { + handler.handleSetBorderCenter(this); + } diff --git a/patch-remap/mache-vineflower/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.java.patch b/patch-remap/mache-vineflower/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.java.patch new file mode 100644 index 0000000000..53212e50fa --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.java.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.java ++++ b/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.network.protocol.game; + + import net.minecraft.network.FriendlyByteBuf; +@@ -5,6 +6,7 @@ + import net.minecraft.network.protocol.Packet; + + public record ClientboundSystemChatPacket(Component content, boolean overlay) implements Packet { ++ + public ClientboundSystemChatPacket(FriendlyByteBuf buffer) { + this(buffer.readComponentTrusted(), buffer.readBoolean()); + } +@@ -15,7 +17,6 @@ + buffer.writeBoolean(this.overlay); + } + +- @Override + public void handle(ClientGamePacketListener handler) { + handler.handleSystemChat(this); + } diff --git a/patch-remap/mache-vineflower/net/minecraft/network/protocol/game/ServerboundUseItemOnPacket.java.patch b/patch-remap/mache-vineflower/net/minecraft/network/protocol/game/ServerboundUseItemOnPacket.java.patch new file mode 100644 index 0000000000..d49deb4a55 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/network/protocol/game/ServerboundUseItemOnPacket.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/network/protocol/game/ServerboundUseItemOnPacket.java ++++ b/net/minecraft/network/protocol/game/ServerboundUseItemOnPacket.java +@@ -1,23 +1,25 @@ ++// mc-dev import + package net.minecraft.network.protocol.game; + + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.protocol.Packet; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.phys.BlockHitResult; + + public class ServerboundUseItemOnPacket implements Packet { ++ + private final BlockHitResult blockHit; +- private final InteractionHand hand; ++ private final EnumHand hand; + private final int sequence; + +- public ServerboundUseItemOnPacket(InteractionHand hand, BlockHitResult blockHit, int sequence) { ++ public ServerboundUseItemOnPacket(EnumHand hand, BlockHitResult blockHit, int sequence) { + this.hand = hand; + this.blockHit = blockHit; + this.sequence = sequence; + } + + public ServerboundUseItemOnPacket(FriendlyByteBuf buffer) { +- this.hand = buffer.readEnum(InteractionHand.class); ++ this.hand = (EnumHand) buffer.readEnum(EnumHand.class); + this.blockHit = buffer.readBlockHitResult(); + this.sequence = buffer.readVarInt(); + } +@@ -29,12 +31,11 @@ + buffer.writeVarInt(this.sequence); + } + +- @Override + public void handle(ServerGamePacketListener handler) { + handler.handleUseItemOn(this); + } + +- public InteractionHand getHand() { ++ public EnumHand getHand() { + return this.hand; + } + diff --git a/patch-remap/mache-vineflower/net/minecraft/network/protocol/game/ServerboundUseItemPacket.java.patch b/patch-remap/mache-vineflower/net/minecraft/network/protocol/game/ServerboundUseItemPacket.java.patch new file mode 100644 index 0000000000..db097997e2 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/network/protocol/game/ServerboundUseItemPacket.java.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/network/protocol/game/ServerboundUseItemPacket.java ++++ b/net/minecraft/network/protocol/game/ServerboundUseItemPacket.java +@@ -1,20 +1,22 @@ ++// mc-dev import + package net.minecraft.network.protocol.game; + + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.protocol.Packet; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + + public class ServerboundUseItemPacket implements Packet { +- private final InteractionHand hand; ++ ++ private final EnumHand hand; + private final int sequence; + +- public ServerboundUseItemPacket(InteractionHand hand, int sequence) { ++ public ServerboundUseItemPacket(EnumHand hand, int sequence) { + this.hand = hand; + this.sequence = sequence; + } + + public ServerboundUseItemPacket(FriendlyByteBuf buffer) { +- this.hand = buffer.readEnum(InteractionHand.class); ++ this.hand = (EnumHand) buffer.readEnum(EnumHand.class); + this.sequence = buffer.readVarInt(); + } + +@@ -24,12 +26,11 @@ + buffer.writeVarInt(this.sequence); + } + +- @Override + public void handle(ServerGamePacketListener handler) { + handler.handleUseItem(this); + } + +- public InteractionHand getHand() { ++ public EnumHand getHand() { + return this.hand; + } + diff --git a/patch-remap/mache-vineflower/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java.patch b/patch-remap/mache-vineflower/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java.patch new file mode 100644 index 0000000000..879d7c0cbf --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java ++++ b/net/minecraft/network/protocol/handshake/ClientIntentionPacket.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.network.protocol.handshake; + + import net.minecraft.network.ConnectionProtocol; +@@ -5,16 +6,9 @@ + import net.minecraft.network.protocol.Packet; + + public record ClientIntentionPacket(int protocolVersion, String hostName, int port, ClientIntent intention) implements Packet { ++ + private static final int MAX_HOST_LENGTH = 255; + +- @Deprecated +- public ClientIntentionPacket(int protocolVersion, String hostName, int port, ClientIntent intention) { +- this.protocolVersion = protocolVersion; +- this.hostName = hostName; +- this.port = port; +- this.intention = intention; +- } +- + public ClientIntentionPacket(FriendlyByteBuf buffer) { + this(buffer.readVarInt(), buffer.readUtf(255), buffer.readUnsignedShort(), ClientIntent.byId(buffer.readVarInt())); + } +@@ -27,7 +21,6 @@ + buffer.writeVarInt(this.intention.id()); + } + +- @Override + public void handle(ServerHandshakePacketListener handler) { + handler.handleIntention(this); + } diff --git a/patch-remap/mache-vineflower/net/minecraft/network/syncher/SynchedEntityData.java.patch b/patch-remap/mache-vineflower/net/minecraft/network/syncher/SynchedEntityData.java.patch new file mode 100644 index 0000000000..6071a786aa --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/network/syncher/SynchedEntityData.java.patch @@ -0,0 +1,345 @@ +--- a/net/minecraft/network/syncher/SynchedEntityData.java ++++ b/net/minecraft/network/syncher/SynchedEntityData.java +@@ -7,7 +7,9 @@ + import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + import it.unimi.dsi.fastutil.objects.Object2IntMap; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectIterator; + import java.util.ArrayList; ++import java.util.Iterator; + import java.util.List; + import java.util.Locale; + import java.util.Objects; +@@ -18,16 +20,19 @@ + import net.minecraft.CrashReportCategory; + import net.minecraft.ReportedException; + import net.minecraft.network.FriendlyByteBuf; ++import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.entity.Entity; + import org.apache.commons.lang3.ObjectUtils; + import org.slf4j.Logger; + + public class SynchedEntityData { ++ + private static final Logger LOGGER = LogUtils.getLogger(); +- private static final Object2IntMap> ENTITY_ID_POOL = new Object2IntOpenHashMap<>(); ++ private static final Object2IntMap> ENTITY_ID_POOL = new Object2IntOpenHashMap(); + private static final int MAX_ID_VALUE = 254; + private final Entity entity; +- private final Int2ObjectMap> itemsById = new Int2ObjectOpenHashMap<>(); ++ private final Int2ObjectMap> itemsById = new Int2ObjectOpenHashMap(); + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + private boolean isDirty; + +@@ -36,59 +41,66 @@ + } + + public static EntityDataAccessor defineId(Class clazz, EntityDataSerializer serializer) { +- if (LOGGER.isDebugEnabled()) { ++ if (SynchedEntityData.LOGGER.isDebugEnabled()) { + try { +- Class clazz1 = Class.forName(Thread.currentThread().getStackTrace()[2].getClassName()); +- if (!clazz1.equals(clazz)) { +- LOGGER.debug("defineId called for: {} from {}", clazz, clazz1, new RuntimeException()); ++ Class oclass1 = Class.forName(Thread.currentThread().getStackTrace()[2].getClassName()); ++ ++ if (!oclass1.equals(clazz)) { ++ SynchedEntityData.LOGGER.debug("defineId called for: {} from {}", new Object[]{clazz, oclass1, new RuntimeException()}); + } +- } catch (ClassNotFoundException var5) { ++ } catch (ClassNotFoundException classnotfoundexception) { ++ ; + } + } + + int i; +- if (ENTITY_ID_POOL.containsKey(clazz)) { +- i = ENTITY_ID_POOL.getInt(clazz) + 1; ++ ++ if (SynchedEntityData.ENTITY_ID_POOL.containsKey(clazz)) { ++ i = SynchedEntityData.ENTITY_ID_POOL.getInt(clazz) + 1; + } else { +- int i1 = 0; +- Class clazz2 = clazz; ++ int j = 0; ++ Class oclass2 = clazz; + +- while (clazz2 != Entity.class) { +- clazz2 = clazz2.getSuperclass(); +- if (ENTITY_ID_POOL.containsKey(clazz2)) { +- i1 = ENTITY_ID_POOL.getInt(clazz2) + 1; ++ while (oclass2 != Entity.class) { ++ oclass2 = oclass2.getSuperclass(); ++ if (SynchedEntityData.ENTITY_ID_POOL.containsKey(oclass2)) { ++ j = SynchedEntityData.ENTITY_ID_POOL.getInt(oclass2) + 1; + break; + } + } + +- i = i1; ++ i = j; + } + + if (i > 254) { + throw new IllegalArgumentException("Data value id is too big with " + i + "! (Max is 254)"); + } else { +- ENTITY_ID_POOL.put(clazz, i); ++ SynchedEntityData.ENTITY_ID_POOL.put(clazz, i); + return serializer.createAccessor(i); + } + } + + public void define(EntityDataAccessor key, T value) { +- int id = key.getId(); +- if (id > 254) { +- throw new IllegalArgumentException("Data value id is too big with " + id + "! (Max is 254)"); +- } else if (this.itemsById.containsKey(id)) { +- throw new IllegalArgumentException("Duplicate id value for " + id + "!"); ++ int i = key.getId(); ++ ++ if (i > 254) { ++ throw new IllegalArgumentException("Data value id is too big with " + i + "! (Max is 254)"); ++ } else if (this.itemsById.containsKey(i)) { ++ throw new IllegalArgumentException("Duplicate id value for " + i + "!"); + } else if (EntityDataSerializers.getSerializedId(key.getSerializer()) < 0) { +- throw new IllegalArgumentException("Unregistered serializer " + key.getSerializer() + " for " + id + "!"); ++ EntityDataSerializer datawatcherserializer = key.getSerializer(); ++ ++ throw new IllegalArgumentException("Unregistered serializer " + datawatcherserializer + " for " + i + "!"); + } else { + this.createDataItem(key, value); + } + } + + private void createDataItem(EntityDataAccessor key, T value) { +- SynchedEntityData.DataItem dataItem = new SynchedEntityData.DataItem<>(key, value); ++ SynchedEntityData.DataItem datawatcher_item = new SynchedEntityData.DataItem<>(key, value); ++ + this.lock.writeLock().lock(); +- this.itemsById.put(key.getId(), dataItem); ++ this.itemsById.put(key.getId(), datawatcher_item); + this.lock.writeLock().unlock(); + } + +@@ -99,19 +111,21 @@ + private SynchedEntityData.DataItem getItem(EntityDataAccessor key) { + this.lock.readLock().lock(); + +- SynchedEntityData.DataItem dataItem; ++ SynchedEntityData.DataItem datawatcher_item; ++ + try { +- dataItem = (SynchedEntityData.DataItem)this.itemsById.get(key.getId()); +- } catch (Throwable var9) { +- CrashReport crashReport = CrashReport.forThrowable(var9, "Getting synched entity data"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Synched entity data"); +- crashReportCategory.setDetail("Data ID", key); +- throw new ReportedException(crashReport); ++ datawatcher_item = (SynchedEntityData.DataItem) this.itemsById.get(key.getId()); ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting synched entity data"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Synched entity data"); ++ ++ crashreportsystemdetails.setDetail("Data ID", (Object) key); ++ throw new ReportedException(crashreport); + } finally { + this.lock.readLock().unlock(); + } + +- return dataItem; ++ return datawatcher_item; + } + + public T get(EntityDataAccessor key) { +@@ -123,15 +137,24 @@ + } + + public void set(EntityDataAccessor key, T value, boolean force) { +- SynchedEntityData.DataItem item = this.getItem(key); +- if (force || ObjectUtils.notEqual(value, item.getValue())) { +- item.setValue(value); ++ SynchedEntityData.DataItem datawatcher_item = this.getItem(key); ++ ++ if (force || ObjectUtils.notEqual(value, datawatcher_item.getValue())) { ++ datawatcher_item.setValue(value); + this.entity.onSyncedDataUpdated(key); +- item.setDirty(true); ++ datawatcher_item.setDirty(true); + this.isDirty = true; + } ++ + } + ++ // CraftBukkit start - add method from above ++ public void markDirty(EntityDataAccessor datawatcherobject) { ++ this.getItem(datawatcherobject).setDirty(true); ++ this.isDirty = true; ++ } ++ // CraftBukkit end ++ + public boolean isDirty() { + return this.isDirty; + } +@@ -139,17 +162,21 @@ + @Nullable + public List> packDirty() { + List> list = null; ++ + if (this.isDirty) { + this.lock.readLock().lock(); ++ ObjectIterator objectiterator = this.itemsById.values().iterator(); + +- for (SynchedEntityData.DataItem dataItem : this.itemsById.values()) { +- if (dataItem.isDirty()) { +- dataItem.setDirty(false); ++ while (objectiterator.hasNext()) { ++ SynchedEntityData.DataItem datawatcher_item = (SynchedEntityData.DataItem) objectiterator.next(); ++ ++ if (datawatcher_item.isDirty()) { ++ datawatcher_item.setDirty(false); + if (list == null) { +- list = new ArrayList<>(); ++ list = new ArrayList(); + } + +- list.add(dataItem.value()); ++ list.add(datawatcher_item.value()); + } + } + +@@ -163,15 +190,19 @@ + @Nullable + public List> getNonDefaultValues() { + List> list = null; ++ + this.lock.readLock().lock(); ++ ObjectIterator objectiterator = this.itemsById.values().iterator(); + +- for (SynchedEntityData.DataItem dataItem : this.itemsById.values()) { +- if (!dataItem.isSetToDefault()) { ++ while (objectiterator.hasNext()) { ++ SynchedEntityData.DataItem datawatcher_item = (SynchedEntityData.DataItem) objectiterator.next(); ++ ++ if (!datawatcher_item.isSetToDefault()) { + if (list == null) { +- list = new ArrayList<>(); ++ list = new ArrayList(); + } + +- list.add(dataItem.value()); ++ list.add(datawatcher_item.value()); + } + } + +@@ -183,11 +214,15 @@ + this.lock.writeLock().lock(); + + try { +- for (SynchedEntityData.DataValue dataValue : entries) { +- SynchedEntityData.DataItem dataItem = this.itemsById.get(dataValue.id); +- if (dataItem != null) { +- this.assignValue(dataItem, dataValue); +- this.entity.onSyncedDataUpdated(dataItem.getAccessor()); ++ Iterator iterator = entries.iterator(); ++ ++ while (iterator.hasNext()) { ++ SynchedEntityData.DataValue datawatcher_b = (SynchedEntityData.DataValue) iterator.next(); ++ SynchedEntityData.DataItem datawatcher_item = (SynchedEntityData.DataItem) this.itemsById.get(datawatcher_b.id); ++ ++ if (datawatcher_item != null) { ++ this.assignValue(datawatcher_item, datawatcher_b); ++ this.entity.onSyncedDataUpdated(datawatcher_item.getAccessor()); + } + } + } finally { +@@ -199,20 +234,9 @@ + + private void assignValue(SynchedEntityData.DataItem target, SynchedEntityData.DataValue entry) { + if (!Objects.equals(entry.serializer(), target.accessor.getSerializer())) { +- throw new IllegalStateException( +- String.format( +- Locale.ROOT, +- "Invalid entity data item type for field %d on entity %s: old=%s(%s), new=%s(%s)", +- target.accessor.getId(), +- this.entity, +- target.value, +- target.value.getClass(), +- entry.value, +- entry.value.getClass() +- ) +- ); ++ throw new IllegalStateException(String.format(Locale.ROOT, "Invalid entity data item type for field %d on entity %s: old=%s(%s), new=%s(%s)", target.accessor.getId(), this.entity, target.value, target.value.getClass(), entry.value, entry.value.getClass())); + } else { +- target.setValue((T)entry.value); ++ target.setValue((T) entry.value); // CraftBukkit - decompile error + } + } + +@@ -220,7 +244,20 @@ + return this.itemsById.isEmpty(); + } + ++ // CraftBukkit start ++ public void refresh(ServerPlayer to) { ++ if (!this.isEmpty()) { ++ List> list = this.getNonDefaultValues(); ++ ++ if (list != null) { ++ to.connection.send(new ClientboundSetEntityDataPacket(this.entity.getId(), list)); ++ } ++ } ++ } ++ // CraftBukkit end ++ + public static class DataItem { ++ + final EntityDataAccessor accessor; + T value; + private final T initialValue; +@@ -261,30 +298,34 @@ + } + } + +- public static record DataValue(int id, EntityDataSerializer serializer, T value) { ++ public static record DataValue(int id, EntityDataSerializer serializer, T value) { // CraftBukkit - decompile error ++ + public static SynchedEntityData.DataValue create(EntityDataAccessor dataAccessor, T value) { +- EntityDataSerializer serializer = dataAccessor.getSerializer(); +- return new SynchedEntityData.DataValue<>(dataAccessor.getId(), serializer, serializer.copy(value)); ++ EntityDataSerializer datawatcherserializer = dataAccessor.getSerializer(); ++ ++ return new SynchedEntityData.DataValue<>(dataAccessor.getId(), datawatcherserializer, datawatcherserializer.copy(value)); + } + + public void write(FriendlyByteBuf buffer) { +- int serializedId = EntityDataSerializers.getSerializedId(this.serializer); +- if (serializedId < 0) { ++ int i = EntityDataSerializers.getSerializedId(this.serializer); ++ ++ if (i < 0) { + throw new EncoderException("Unknown serializer type " + this.serializer); + } else { + buffer.writeByte(this.id); +- buffer.writeVarInt(serializedId); ++ buffer.writeVarInt(i); + this.serializer.write(buffer, this.value); + } + } + + public static SynchedEntityData.DataValue read(FriendlyByteBuf buffer, int id) { +- int varInt = buffer.readVarInt(); +- EntityDataSerializer serializer = EntityDataSerializers.getSerializer(varInt); +- if (serializer == null) { +- throw new DecoderException("Unknown serializer type " + varInt); ++ int j = buffer.readVarInt(); ++ EntityDataSerializer datawatcherserializer = EntityDataSerializers.getSerializer(j); ++ ++ if (datawatcherserializer == null) { ++ throw new DecoderException("Unknown serializer type " + j); + } else { +- return read(buffer, id, serializer); ++ return read(buffer, id, datawatcherserializer); + } + } + diff --git a/patch-remap/mache-vineflower/net/minecraft/server/Bootstrap.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/Bootstrap.java.patch new file mode 100644 index 0000000000..f9bb5c82b8 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/Bootstrap.java.patch @@ -0,0 +1,241 @@ +--- a/net/minecraft/server/Bootstrap.java ++++ b/net/minecraft/server/Bootstrap.java +@@ -16,7 +16,9 @@ + import net.minecraft.core.dispenser.DispenseItemBehavior; + import net.minecraft.core.registries.BuiltInRegistries; + import net.minecraft.locale.Language; +-import net.minecraft.resources.ResourceLocation; ++import net.minecraft.util.datafix.fixes.BlockStateData; ++import net.minecraft.util.datafix.fixes.ItemIdFix; ++import net.minecraft.util.datafix.fixes.ItemSpawnEggFix; + import net.minecraft.world.effect.MobEffect; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.ai.attributes.Attribute; +@@ -32,15 +34,36 @@ + import org.slf4j.Logger; + + public class Bootstrap { ++ + public static final PrintStream STDOUT = System.out; + private static volatile boolean isBootstrapped; + private static final Logger LOGGER = LogUtils.getLogger(); + public static final AtomicLong bootstrapDuration = new AtomicLong(-1L); + ++ public Bootstrap() {} ++ + public static void bootStrap() { +- if (!isBootstrapped) { +- isBootstrapped = true; ++ if (!Bootstrap.isBootstrapped) { ++ // CraftBukkit start ++ String name = Bootstrap.class.getSimpleName(); ++ switch (name) { ++ case "DispenserRegistry": ++ break; ++ case "Bootstrap": ++ System.err.println("***************************************************************************"); ++ System.err.println("*** WARNING: This server jar may only be used for development purposes. ***"); ++ System.err.println("***************************************************************************"); ++ break; ++ default: ++ System.err.println("**********************************************************************"); ++ System.err.println("*** WARNING: This server jar is unsupported, use at your own risk. ***"); ++ System.err.println("**********************************************************************"); ++ break; ++ } ++ // CraftBukkit end ++ Bootstrap.isBootstrapped = true; + Instant instant = Instant.now(); ++ + if (BuiltInRegistries.REGISTRY.keySet().isEmpty()) { + throw new IllegalStateException("Unable to load registries"); + } else { +@@ -56,68 +79,147 @@ + BuiltInRegistries.bootStrap(); + CreativeModeTabs.validate(); + wrapStreams(); +- bootstrapDuration.set(Duration.between(instant, Instant.now()).toMillis()); ++ Bootstrap.bootstrapDuration.set(Duration.between(instant, Instant.now()).toMillis()); + } ++ // CraftBukkit start - easier than fixing the decompile ++ BlockStateData.register(1008, "{Name:'minecraft:oak_sign',Properties:{rotation:'0'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'0'}}"); ++ BlockStateData.register(1009, "{Name:'minecraft:oak_sign',Properties:{rotation:'1'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'1'}}"); ++ BlockStateData.register(1010, "{Name:'minecraft:oak_sign',Properties:{rotation:'2'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'2'}}"); ++ BlockStateData.register(1011, "{Name:'minecraft:oak_sign',Properties:{rotation:'3'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'3'}}"); ++ BlockStateData.register(1012, "{Name:'minecraft:oak_sign',Properties:{rotation:'4'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'4'}}"); ++ BlockStateData.register(1013, "{Name:'minecraft:oak_sign',Properties:{rotation:'5'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'5'}}"); ++ BlockStateData.register(1014, "{Name:'minecraft:oak_sign',Properties:{rotation:'6'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'6'}}"); ++ BlockStateData.register(1015, "{Name:'minecraft:oak_sign',Properties:{rotation:'7'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'7'}}"); ++ BlockStateData.register(1016, "{Name:'minecraft:oak_sign',Properties:{rotation:'8'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'8'}}"); ++ BlockStateData.register(1017, "{Name:'minecraft:oak_sign',Properties:{rotation:'9'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'9'}}"); ++ BlockStateData.register(1018, "{Name:'minecraft:oak_sign',Properties:{rotation:'10'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'10'}}"); ++ BlockStateData.register(1019, "{Name:'minecraft:oak_sign',Properties:{rotation:'11'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'11'}}"); ++ BlockStateData.register(1020, "{Name:'minecraft:oak_sign',Properties:{rotation:'12'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'12'}}"); ++ BlockStateData.register(1021, "{Name:'minecraft:oak_sign',Properties:{rotation:'13'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'13'}}"); ++ BlockStateData.register(1022, "{Name:'minecraft:oak_sign',Properties:{rotation:'14'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'14'}}"); ++ BlockStateData.register(1023, "{Name:'minecraft:oak_sign',Properties:{rotation:'15'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'15'}}"); ++ ItemIdFix.ITEM_NAMES.put(323, "minecraft:oak_sign"); ++ ++ BlockStateData.register(1440, "{Name:\'minecraft:portal\',Properties:{axis:\'x\'}}", new String[]{"{Name:\'minecraft:portal\',Properties:{axis:\'x\'}}"}); ++ ++ ItemIdFix.ITEM_NAMES.put(409, "minecraft:prismarine_shard"); ++ ItemIdFix.ITEM_NAMES.put(410, "minecraft:prismarine_crystals"); ++ ItemIdFix.ITEM_NAMES.put(411, "minecraft:rabbit"); ++ ItemIdFix.ITEM_NAMES.put(412, "minecraft:cooked_rabbit"); ++ ItemIdFix.ITEM_NAMES.put(413, "minecraft:rabbit_stew"); ++ ItemIdFix.ITEM_NAMES.put(414, "minecraft:rabbit_foot"); ++ ItemIdFix.ITEM_NAMES.put(415, "minecraft:rabbit_hide"); ++ ItemIdFix.ITEM_NAMES.put(416, "minecraft:armor_stand"); ++ ++ ItemIdFix.ITEM_NAMES.put(423, "minecraft:mutton"); ++ ItemIdFix.ITEM_NAMES.put(424, "minecraft:cooked_mutton"); ++ ItemIdFix.ITEM_NAMES.put(425, "minecraft:banner"); ++ ItemIdFix.ITEM_NAMES.put(426, "minecraft:end_crystal"); ++ ItemIdFix.ITEM_NAMES.put(427, "minecraft:spruce_door"); ++ ItemIdFix.ITEM_NAMES.put(428, "minecraft:birch_door"); ++ ItemIdFix.ITEM_NAMES.put(429, "minecraft:jungle_door"); ++ ItemIdFix.ITEM_NAMES.put(430, "minecraft:acacia_door"); ++ ItemIdFix.ITEM_NAMES.put(431, "minecraft:dark_oak_door"); ++ ItemIdFix.ITEM_NAMES.put(432, "minecraft:chorus_fruit"); ++ ItemIdFix.ITEM_NAMES.put(433, "minecraft:chorus_fruit_popped"); ++ ItemIdFix.ITEM_NAMES.put(434, "minecraft:beetroot"); ++ ItemIdFix.ITEM_NAMES.put(435, "minecraft:beetroot_seeds"); ++ ItemIdFix.ITEM_NAMES.put(436, "minecraft:beetroot_soup"); ++ ItemIdFix.ITEM_NAMES.put(437, "minecraft:dragon_breath"); ++ ItemIdFix.ITEM_NAMES.put(438, "minecraft:splash_potion"); ++ ItemIdFix.ITEM_NAMES.put(439, "minecraft:spectral_arrow"); ++ ItemIdFix.ITEM_NAMES.put(440, "minecraft:tipped_arrow"); ++ ItemIdFix.ITEM_NAMES.put(441, "minecraft:lingering_potion"); ++ ItemIdFix.ITEM_NAMES.put(442, "minecraft:shield"); ++ ItemIdFix.ITEM_NAMES.put(443, "minecraft:elytra"); ++ ItemIdFix.ITEM_NAMES.put(444, "minecraft:spruce_boat"); ++ ItemIdFix.ITEM_NAMES.put(445, "minecraft:birch_boat"); ++ ItemIdFix.ITEM_NAMES.put(446, "minecraft:jungle_boat"); ++ ItemIdFix.ITEM_NAMES.put(447, "minecraft:acacia_boat"); ++ ItemIdFix.ITEM_NAMES.put(448, "minecraft:dark_oak_boat"); ++ ItemIdFix.ITEM_NAMES.put(449, "minecraft:totem_of_undying"); ++ ItemIdFix.ITEM_NAMES.put(450, "minecraft:shulker_shell"); ++ ItemIdFix.ITEM_NAMES.put(452, "minecraft:iron_nugget"); ++ ItemIdFix.ITEM_NAMES.put(453, "minecraft:knowledge_book"); ++ ++ ItemSpawnEggFix.ID_TO_ENTITY[23] = "Arrow"; ++ // CraftBukkit end + } + } + } + + private static void checkTranslations(Iterable objects, Function objectToKeyFunction, Set translationSet) { +- Language instance = Language.getInstance(); +- objects.forEach(object -> { +- String string = objectToKeyFunction.apply((T)object); +- if (!instance.has(string)) { +- translationSet.add(string); ++ Language localelanguage = Language.getInstance(); ++ ++ objects.forEach((object) -> { ++ String s = (String) objectToKeyFunction.apply(object); ++ ++ if (!localelanguage.has(s)) { ++ translationSet.add(s); + } ++ + }); + } + + private static void checkGameruleTranslations(final Set translations) { +- final Language instance = Language.getInstance(); ++ final Language localelanguage = Language.getInstance(); ++ + GameRules.visitGameRuleTypes(new GameRules.GameRuleTypeVisitor() { + @Override + public > void visit(GameRules.Key key, GameRules.Type type) { +- if (!instance.has(key.getDescriptionId())) { ++ if (!localelanguage.has(key.getDescriptionId())) { + translations.add(key.getId()); + } ++ + } + }); + } + + public static Set getMissingTranslations() { +- Set set = new TreeSet<>(); ++ Set set = new TreeSet(); ++ + checkTranslations(BuiltInRegistries.ATTRIBUTE, Attribute::getDescriptionId, set); + checkTranslations(BuiltInRegistries.ENTITY_TYPE, EntityType::getDescriptionId, set); + checkTranslations(BuiltInRegistries.MOB_EFFECT, MobEffect::getDescriptionId, set); + checkTranslations(BuiltInRegistries.ITEM, Item::getDescriptionId, set); + checkTranslations(BuiltInRegistries.ENCHANTMENT, Enchantment::getDescriptionId, set); + checkTranslations(BuiltInRegistries.BLOCK, Block::getDescriptionId, set); +- checkTranslations(BuiltInRegistries.CUSTOM_STAT, resourceLocation -> "stat." + resourceLocation.toString().replace(':', '.'), set); ++ checkTranslations(BuiltInRegistries.CUSTOM_STAT, (minecraftkey) -> { ++ String s = minecraftkey.toString(); ++ ++ return "stat." + s.replace(':', '.'); ++ }, set); + checkGameruleTranslations(set); + return set; + } + + public static void checkBootstrapCalled(Supplier callSite) { +- if (!isBootstrapped) { ++ if (!Bootstrap.isBootstrapped) { + throw createBootstrapException(callSite); + } + } + + private static RuntimeException createBootstrapException(Supplier callSite) { + try { +- String string = callSite.get(); +- return new IllegalArgumentException("Not bootstrapped (called from " + string + ")"); +- } catch (Exception var3) { +- RuntimeException runtimeException = new IllegalArgumentException("Not bootstrapped (failed to resolve location)"); +- runtimeException.addSuppressed(var3); +- return runtimeException; ++ String s = (String) callSite.get(); ++ ++ return new IllegalArgumentException("Not bootstrapped (called from " + s + ")"); ++ } catch (Exception exception) { ++ IllegalArgumentException illegalargumentexception = new IllegalArgumentException("Not bootstrapped (failed to resolve location)"); ++ ++ illegalargumentexception.addSuppressed(exception); ++ return illegalargumentexception; + } + } + + public static void validate() { +- checkBootstrapCalled(() -> "validate"); ++ checkBootstrapCalled(() -> { ++ return "validate"; ++ }); + if (SharedConstants.IS_RUNNING_IN_IDE) { +- getMissingTranslations().forEach(string -> LOGGER.error("Missing translations: {}", string)); ++ getMissingTranslations().forEach((s) -> { ++ Bootstrap.LOGGER.error("Missing translations: {}", s); ++ }); + Commands.validate(); + } + +@@ -125,16 +227,17 @@ + } + + private static void wrapStreams() { +- if (LOGGER.isDebugEnabled()) { ++ if (Bootstrap.LOGGER.isDebugEnabled()) { + System.setErr(new DebugLoggedPrintStream("STDERR", System.err)); +- System.setOut(new DebugLoggedPrintStream("STDOUT", STDOUT)); ++ System.setOut(new DebugLoggedPrintStream("STDOUT", Bootstrap.STDOUT)); + } else { + System.setErr(new LoggedPrintStream("STDERR", System.err)); +- System.setOut(new LoggedPrintStream("STDOUT", STDOUT)); ++ System.setOut(new LoggedPrintStream("STDOUT", Bootstrap.STDOUT)); + } ++ + } + + public static void realStdoutPrintln(String message) { +- STDOUT.println(message); ++ Bootstrap.STDOUT.println(message); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/Main.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/Main.java.patch new file mode 100644 index 0000000000..3183d249fe --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/Main.java.patch @@ -0,0 +1,550 @@ +--- a/net/minecraft/server/Main.java ++++ b/net/minecraft/server/Main.java +@@ -14,20 +14,20 @@ + import java.nio.file.Path; + import java.nio.file.Paths; + import java.util.Optional; +-import java.util.concurrent.Executor; + import java.util.function.BooleanSupplier; + import javax.annotation.Nullable; ++import joptsimple.NonOptionArgumentSpec; + import joptsimple.OptionParser; + import joptsimple.OptionSet; + import joptsimple.OptionSpec; + import joptsimple.util.PathConverter; ++import joptsimple.util.PathProperties; + import net.minecraft.CrashReport; + import net.minecraft.DefaultUncaughtExceptionHandler; + import net.minecraft.SharedConstants; + import net.minecraft.Util; + import net.minecraft.commands.Commands; + import net.minecraft.core.Registry; +-import net.minecraft.core.RegistryAccess; + import net.minecraft.core.registries.Registries; + import net.minecraft.nbt.NbtException; + import net.minecraft.nbt.ReportedNbtException; +@@ -37,6 +37,7 @@ + import net.minecraft.server.dedicated.DedicatedServerProperties; + import net.minecraft.server.dedicated.DedicatedServerSettings; + import net.minecraft.server.level.progress.LoggerChunkProgressListener; ++import net.minecraft.server.packs.PackType; + import net.minecraft.server.packs.repository.PackRepository; + import net.minecraft.server.packs.repository.ServerPacksSource; + import net.minecraft.util.Mth; +@@ -53,49 +54,66 @@ + import net.minecraft.world.level.levelgen.WorldOptions; + import net.minecraft.world.level.levelgen.presets.WorldPresets; + import net.minecraft.world.level.storage.LevelDataAndDimensions; ++import net.minecraft.world.level.storage.LevelResource; + import net.minecraft.world.level.storage.LevelStorageSource; + import net.minecraft.world.level.storage.LevelSummary; + import net.minecraft.world.level.storage.PrimaryLevelData; +-import net.minecraft.world.level.storage.WorldData; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.google.common.base.Charsets; ++import java.io.InputStreamReader; ++import java.util.concurrent.atomic.AtomicReference; ++import net.minecraft.SharedConstants; ++import org.bukkit.configuration.file.YamlConfiguration; ++// CraftBukkit end ++ + public class Main { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + ++ public Main() {} ++ + @DontObfuscate +- public static void main(String[] args) { ++ public static void main(final OptionSet optionset) { // CraftBukkit - replaces main(String[] astring) + SharedConstants.tryDetectVersion(); +- OptionParser optionParser = new OptionParser(); +- OptionSpec optionSpec = optionParser.accepts("nogui"); +- OptionSpec optionSpec1 = optionParser.accepts("initSettings", "Initializes 'server.properties' and 'eula.txt', then quits"); +- OptionSpec optionSpec2 = optionParser.accepts("demo"); +- OptionSpec optionSpec3 = optionParser.accepts("bonusChest"); +- OptionSpec optionSpec4 = optionParser.accepts("forceUpgrade"); +- OptionSpec optionSpec5 = optionParser.accepts("eraseCache"); +- OptionSpec optionSpec6 = optionParser.accepts("safeMode", "Loads level with vanilla datapack only"); +- OptionSpec optionSpec7 = optionParser.accepts("help").forHelp(); +- OptionSpec optionSpec8 = optionParser.accepts("universe").withRequiredArg().defaultsTo("."); +- OptionSpec optionSpec9 = optionParser.accepts("world").withRequiredArg(); +- OptionSpec optionSpec10 = optionParser.accepts("port").withRequiredArg().ofType(Integer.class).defaultsTo(-1); +- OptionSpec optionSpec11 = optionParser.accepts("serverId").withRequiredArg(); +- OptionSpec optionSpec12 = optionParser.accepts("jfrProfile"); +- OptionSpec optionSpec13 = optionParser.accepts("pidFile").withRequiredArg().withValuesConvertedBy(new PathConverter()); +- OptionSpec optionSpec14 = optionParser.nonOptions(); ++ /* CraftBukkit start - Replace everything ++ OptionParser optionparser = new OptionParser(); ++ OptionSpec optionspec = optionparser.accepts("nogui"); ++ OptionSpec optionspec1 = optionparser.accepts("initSettings", "Initializes 'server.properties' and 'eula.txt', then quits"); ++ OptionSpec optionspec2 = optionparser.accepts("demo"); ++ OptionSpec optionspec3 = optionparser.accepts("bonusChest"); ++ OptionSpec optionspec4 = optionparser.accepts("forceUpgrade"); ++ OptionSpec optionspec5 = optionparser.accepts("eraseCache"); ++ OptionSpec optionspec6 = optionparser.accepts("safeMode", "Loads level with vanilla datapack only"); ++ OptionSpec optionspec7 = optionparser.accepts("help").forHelp(); ++ OptionSpec optionspec8 = optionparser.accepts("universe").withRequiredArg().defaultsTo(".", new String[0]); ++ OptionSpec optionspec9 = optionparser.accepts("world").withRequiredArg(); ++ OptionSpec optionspec10 = optionparser.accepts("port").withRequiredArg().ofType(Integer.class).defaultsTo(-1, new Integer[0]); ++ OptionSpec optionspec11 = optionparser.accepts("serverId").withRequiredArg(); ++ OptionSpec optionspec12 = optionparser.accepts("jfrProfile"); ++ OptionSpec optionspec13 = optionparser.accepts("pidFile").withRequiredArg().withValuesConvertedBy(new PathConverter(new PathProperties[0])); ++ NonOptionArgumentSpec nonoptionargumentspec = optionparser.nonOptions(); + + try { +- OptionSet optionSet = optionParser.parse(args); +- if (optionSet.has(optionSpec7)) { +- optionParser.printHelpOn(System.err); ++ OptionSet optionset = optionparser.parse(astring); ++ ++ if (optionset.has(optionspec7)) { ++ optionparser.printHelpOn(System.err); + return; + } ++ */ // CraftBukkit end + +- Path path = optionSet.valueOf(optionSpec13); ++ try { ++ ++ Path path = (Path) optionset.valueOf("pidFile"); // CraftBukkit ++ + if (path != null) { + writePidFile(path); + } + + CrashReport.preload(); +- if (optionSet.has(optionSpec12)) { ++ if (optionset.has("jfrProfile")) { // CraftBukkit + JvmProfiler.INSTANCE.start(Environment.SERVER); + } + +@@ -103,238 +121,264 @@ + Bootstrap.validate(); + Util.startTimerHackThread(); + Path path1 = Paths.get("server.properties"); +- DedicatedServerSettings dedicatedServerSettings = new DedicatedServerSettings(path1); +- dedicatedServerSettings.forceSave(); ++ DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(optionset); // CraftBukkit - CLI argument support ++ ++ dedicatedserversettings.forceSave(); + Path path2 = Paths.get("eula.txt"); + Eula eula = new Eula(path2); +- if (optionSet.has(optionSpec1)) { +- LOGGER.info("Initialized '{}' and '{}'", path1.toAbsolutePath(), path2.toAbsolutePath()); ++ ++ if (optionset.has("initSettings")) { // CraftBukkit ++ // CraftBukkit start - SPIGOT-5761: Create bukkit.yml and commands.yml if not present ++ File configFile = (File) optionset.valueOf("bukkit-settings"); ++ YamlConfiguration configuration = YamlConfiguration.loadConfiguration(configFile); ++ configuration.options().copyDefaults(true); ++ configuration.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/bukkit.yml"), Charsets.UTF_8))); ++ configuration.save(configFile); ++ ++ File commandFile = (File) optionset.valueOf("commands-settings"); ++ YamlConfiguration commandsConfiguration = YamlConfiguration.loadConfiguration(commandFile); ++ commandsConfiguration.options().copyDefaults(true); ++ commandsConfiguration.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/commands.yml"), Charsets.UTF_8))); ++ commandsConfiguration.save(commandFile); ++ // CraftBukkit end ++ Main.LOGGER.info("Initialized '{}' and '{}'", path1.toAbsolutePath(), path2.toAbsolutePath()); + return; + } + + if (!eula.hasAgreedToEULA()) { +- LOGGER.info("You need to agree to the EULA in order to run the server. Go to eula.txt for more info."); ++ Main.LOGGER.info("You need to agree to the EULA in order to run the server. Go to eula.txt for more info."); + return; + } + +- File file = new File(optionSet.valueOf(optionSpec8)); ++ File file = (File) optionset.valueOf("universe"); // CraftBukkit + Services services = Services.create(new YggdrasilAuthenticationService(Proxy.NO_PROXY), file); +- String string = Optional.ofNullable(optionSet.valueOf(optionSpec9)).orElse(dedicatedServerSettings.getProperties().levelName); +- LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(file.toPath()); +- LevelStorageSource.LevelStorageAccess levelStorageAccess = levelStorageSource.validateAndCreateAccess(string); +- Dynamic dataTag; +- if (levelStorageAccess.hasWorldData()) { +- LevelSummary summary; ++ // CraftBukkit start ++ String s = (String) Optional.ofNullable((String) optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName); ++ LevelStorageSource convertable = LevelStorageSource.createDefault(file.toPath()); ++ LevelStorageSource.LevelStorageAccess convertable_conversionsession = convertable.validateAndCreateAccess(s, LevelStem.OVERWORLD); ++ // CraftBukkit end ++ Dynamic dynamic; ++ ++ if (convertable_conversionsession.hasWorldData()) { ++ LevelSummary worldinfo; ++ + try { +- dataTag = levelStorageAccess.getDataTag(); +- summary = levelStorageAccess.getSummary(dataTag); +- } catch (NbtException | ReportedNbtException | IOException var39) { +- LevelStorageSource.LevelDirectory levelDirectory = levelStorageAccess.getLevelDirectory(); +- LOGGER.warn("Failed to load world data from {}", levelDirectory.dataFile(), var39); +- LOGGER.info("Attempting to use fallback"); ++ dynamic = convertable_conversionsession.getDataTag(); ++ worldinfo = convertable_conversionsession.getSummary(dynamic); ++ } catch (NbtException | ReportedNbtException | IOException ioexception) { ++ LevelStorageSource.LevelDirectory convertable_b = convertable_conversionsession.getLevelDirectory(); + ++ Main.LOGGER.warn("Failed to load world data from {}", convertable_b.dataFile(), ioexception); ++ Main.LOGGER.info("Attempting to use fallback"); ++ + try { +- dataTag = levelStorageAccess.getDataTagFallback(); +- summary = levelStorageAccess.getSummary(dataTag); +- } catch (NbtException | ReportedNbtException | IOException var38) { +- LOGGER.error("Failed to load world data from {}", levelDirectory.oldDataFile(), var38); +- LOGGER.error( +- "Failed to load world data from {} and {}. World files may be corrupted. Shutting down.", +- levelDirectory.dataFile(), +- levelDirectory.oldDataFile() +- ); ++ dynamic = convertable_conversionsession.getDataTagFallback(); ++ worldinfo = convertable_conversionsession.getSummary(dynamic); ++ } catch (NbtException | ReportedNbtException | IOException ioexception1) { ++ Main.LOGGER.error("Failed to load world data from {}", convertable_b.oldDataFile(), ioexception1); ++ Main.LOGGER.error("Failed to load world data from {} and {}. World files may be corrupted. Shutting down.", convertable_b.dataFile(), convertable_b.oldDataFile()); + return; + } + +- levelStorageAccess.restoreLevelDataFromOld(); ++ convertable_conversionsession.restoreLevelDataFromOld(); + } + +- if (summary.requiresManualConversion()) { +- LOGGER.info("This world must be opened in an older version (like 1.6.4) to be safely converted"); ++ if (worldinfo.requiresManualConversion()) { ++ Main.LOGGER.info("This world must be opened in an older version (like 1.6.4) to be safely converted"); + return; + } + +- if (!summary.isCompatible()) { +- LOGGER.info("This world was created by an incompatible version."); ++ if (!worldinfo.isCompatible()) { ++ Main.LOGGER.info("This world was created by an incompatible version."); + return; + } + } else { +- dataTag = null; ++ dynamic = null; + } + +- Dynamic dynamic = dataTag; +- boolean hasOptionSpec = optionSet.has(optionSpec6); +- if (hasOptionSpec) { +- LOGGER.warn("Safe mode active, only vanilla datapack will be loaded"); ++ Dynamic dynamic1 = dynamic; ++ boolean flag = optionset.has("safeMode"); // CraftBukkit ++ ++ if (flag) { ++ Main.LOGGER.warn("Safe mode active, only vanilla datapack will be loaded"); + } + +- PackRepository packRepository = ServerPacksSource.createPackRepository(levelStorageAccess); ++ PackRepository resourcepackrepository = ServerPacksSource.createPackRepository(convertable_conversionsession); ++ // CraftBukkit start ++ File bukkitDataPackFolder = new File(convertable_conversionsession.getLevelPath(LevelResource.DATAPACK_DIR).toFile(), "bukkit"); ++ if (!bukkitDataPackFolder.exists()) { ++ bukkitDataPackFolder.mkdirs(); ++ } ++ File mcMeta = new File(bukkitDataPackFolder, "pack.mcmeta"); ++ try { ++ com.google.common.io.Files.write("{\n" ++ + " \"pack\": {\n" ++ + " \"description\": \"Data pack for resources provided by Bukkit plugins\",\n" ++ + " \"pack_format\": " + SharedConstants.getCurrentVersion().getPackVersion(PackType.SERVER_DATA) + "\n" ++ + " }\n" ++ + "}\n", mcMeta, com.google.common.base.Charsets.UTF_8); ++ } catch (java.io.IOException ex) { ++ throw new RuntimeException("Could not initialize Bukkit datapack", ex); ++ } ++ AtomicReference worldLoader = new AtomicReference<>(); ++ // CraftBukkit end + +- WorldStem worldStem; ++ WorldStem worldstem; ++ + try { +- WorldLoader.InitConfig initConfig = loadOrCreateConfig(dedicatedServerSettings.getProperties(), dynamic, hasOptionSpec, packRepository); +- worldStem = Util.blockUntilDone( +- executor -> WorldLoader.load( +- initConfig, +- context -> { +- Registry registry = context.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM); +- if (dynamic != null) { +- LevelDataAndDimensions levelDataAndDimensions = LevelStorageSource.getLevelDataAndDimensions( +- dynamic, context.dataConfiguration(), registry, context.datapackWorldgen() +- ); +- return new WorldLoader.DataLoadOutput<>( +- levelDataAndDimensions.worldData(), levelDataAndDimensions.dimensions().dimensionsRegistryAccess() +- ); +- } else { +- LOGGER.info("No existing world data, creating new world"); +- LevelSettings levelSettings; +- WorldOptions worldOptions; +- WorldDimensions worldDimensions; +- if (optionSet.has(optionSpec2)) { +- levelSettings = MinecraftServer.DEMO_SETTINGS; +- worldOptions = WorldOptions.DEMO_OPTIONS; +- worldDimensions = WorldPresets.createNormalWorldDimensions(context.datapackWorldgen()); +- } else { +- DedicatedServerProperties properties = dedicatedServerSettings.getProperties(); +- levelSettings = new LevelSettings( +- properties.levelName, +- properties.gamemode, +- properties.hardcore, +- properties.difficulty, +- false, +- new GameRules(), +- context.dataConfiguration() +- ); +- worldOptions = optionSet.has(optionSpec3) ? properties.worldOptions.withBonusChest(true) : properties.worldOptions; +- worldDimensions = properties.createDimensions(context.datapackWorldgen()); +- } +- +- WorldDimensions.Complete complete = worldDimensions.bake(registry); +- Lifecycle lifecycle = complete.lifecycle().add(context.datapackWorldgen().allRegistriesLifecycle()); +- return new WorldLoader.DataLoadOutput<>( +- new PrimaryLevelData(levelSettings, worldOptions, complete.specialWorldProperty(), lifecycle), +- complete.dimensionsRegistryAccess() +- ); +- } +- }, +- WorldStem::new, +- Util.backgroundExecutor(), +- executor +- ) +- ) +- .get(); +- } catch (Exception var37) { +- LOGGER.warn( +- "Failed to load datapacks, can't proceed with server load. You can either fix your datapacks or reset to vanilla with --safeMode", +- (Throwable)var37 +- ); ++ WorldLoader.c worldloader_c = loadOrCreateConfig(dedicatedserversettings.getProperties(), dynamic1, flag, resourcepackrepository); ++ ++ worldstem = (WorldStem) Util.blockUntilDone((executor) -> { ++ return WorldLoader.load(worldloader_c, (worldloader_a) -> { ++ worldLoader.set(worldloader_a); // CraftBukkit ++ Registry iregistry = worldloader_a.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM); ++ ++ if (dynamic1 != null) { ++ LevelDataAndDimensions leveldataanddimensions = LevelStorageSource.getLevelDataAndDimensions(dynamic1, worldloader_a.dataConfiguration(), iregistry, worldloader_a.datapackWorldgen()); ++ ++ return new WorldLoader.b<>(leveldataanddimensions.worldData(), leveldataanddimensions.dimensions().dimensionsRegistryAccess()); ++ } else { ++ Main.LOGGER.info("No existing world data, creating new world"); ++ LevelSettings worldsettings; ++ WorldOptions worldoptions; ++ WorldDimensions worlddimensions; ++ ++ if (optionset.has("demo")) { // CraftBukkit ++ worldsettings = MinecraftServer.DEMO_SETTINGS; ++ worldoptions = WorldOptions.DEMO_OPTIONS; ++ worlddimensions = WorldPresets.createNormalWorldDimensions(worldloader_a.datapackWorldgen()); ++ } else { ++ DedicatedServerProperties dedicatedserverproperties = dedicatedserversettings.getProperties(); ++ ++ worldsettings = new LevelSettings(dedicatedserverproperties.levelName, dedicatedserverproperties.gamemode, dedicatedserverproperties.hardcore, dedicatedserverproperties.difficulty, false, new GameRules(), worldloader_a.dataConfiguration()); ++ worldoptions = optionset.has("bonusChest") ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions; // CraftBukkit ++ worlddimensions = dedicatedserverproperties.createDimensions(worldloader_a.datapackWorldgen()); ++ } ++ ++ WorldDimensions.b worlddimensions_b = worlddimensions.bake(iregistry); ++ Lifecycle lifecycle = worlddimensions_b.lifecycle().add(worldloader_a.datapackWorldgen().allRegistriesLifecycle()); ++ ++ return new WorldLoader.b<>(new PrimaryLevelData(worldsettings, worldoptions, worlddimensions_b.specialWorldProperty(), lifecycle), worlddimensions_b.dimensionsRegistryAccess()); ++ } ++ }, WorldStem::new, Util.backgroundExecutor(), executor); ++ }).get(); ++ } catch (Exception exception) { ++ Main.LOGGER.warn("Failed to load datapacks, can't proceed with server load. You can either fix your datapacks or reset to vanilla with --safeMode", exception); + return; + } + +- RegistryAccess.Frozen frozen = worldStem.registries().compositeAccess(); +- if (optionSet.has(optionSpec4)) { +- forceUpgrade( +- levelStorageAccess, DataFixers.getDataFixer(), optionSet.has(optionSpec5), () -> true, frozen.registryOrThrow(Registries.LEVEL_STEM) +- ); ++ /* ++ IRegistryCustom.Dimension iregistrycustom_dimension = worldstem.registries().compositeAccess(); ++ ++ if (optionset.has(optionspec4)) { ++ forceUpgrade(convertable_conversionsession, DataConverterRegistry.getDataFixer(), optionset.has(optionspec5), () -> { ++ return true; ++ }, iregistrycustom_dimension.registryOrThrow(Registries.LEVEL_STEM)); + } + +- WorldData worldData = worldStem.worldData(); +- levelStorageAccess.saveDataTag(frozen, worldData); +- final DedicatedServer dedicatedServer = MinecraftServer.spin( +- thread1 -> { +- DedicatedServer dedicatedServer1 = new DedicatedServer( +- thread1, +- levelStorageAccess, +- packRepository, +- worldStem, +- dedicatedServerSettings, +- DataFixers.getDataFixer(), +- services, +- LoggerChunkProgressListener::new +- ); +- dedicatedServer1.setPort(optionSet.valueOf(optionSpec10)); +- dedicatedServer1.setDemo(optionSet.has(optionSpec2)); +- dedicatedServer1.setId(optionSet.valueOf(optionSpec11)); +- boolean flag = !optionSet.has(optionSpec) && !optionSet.valuesOf(optionSpec14).contains("nogui"); +- if (flag && !GraphicsEnvironment.isHeadless()) { +- dedicatedServer1.showGui(); ++ SaveData savedata = worldstem.worldData(); ++ ++ convertable_conversionsession.saveDataTag(iregistrycustom_dimension, savedata); ++ */ ++ final DedicatedServer dedicatedserver = (DedicatedServer) MinecraftServer.spin((thread) -> { ++ DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, worldLoader.get(), thread, convertable_conversionsession, resourcepackrepository, worldstem, dedicatedserversettings, DataFixers.getDataFixer(), services, LoggerChunkProgressListener::new); ++ ++ /* ++ dedicatedserver1.setPort((Integer) optionset.valueOf(optionspec10)); ++ dedicatedserver1.setDemo(optionset.has(optionspec2)); ++ dedicatedserver1.setId((String) optionset.valueOf(optionspec11)); ++ */ ++ boolean flag1 = !optionset.has("nogui") && !optionset.nonOptionArguments().contains("nogui"); ++ ++ if (flag1 && !GraphicsEnvironment.isHeadless()) { ++ dedicatedserver1.showGui(); ++ } ++ ++ if (optionset.has("port")) { ++ int port = (Integer) optionset.valueOf("port"); ++ if (port > 0) { ++ dedicatedserver1.setPort(port); + } +- +- return dedicatedServer1; + } +- ); ++ ++ return dedicatedserver1; ++ }); ++ /* CraftBukkit start + Thread thread = new Thread("Server Shutdown Thread") { +- @Override + public void run() { +- dedicatedServer.halt(true); ++ dedicatedserver.halt(true); + } + }; +- thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER)); ++ ++ thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(Main.LOGGER)); + Runtime.getRuntime().addShutdownHook(thread); +- } catch (Exception var40) { +- LOGGER.error(LogUtils.FATAL_MARKER, "Failed to start the minecraft server", (Throwable)var40); ++ */ // CraftBukkit end ++ } catch (Exception exception1) { ++ Main.LOGGER.error(LogUtils.FATAL_MARKER, "Failed to start the minecraft server", exception1); + } ++ + } + + private static void writePidFile(Path path) { + try { +- long l = ProcessHandle.current().pid(); +- Files.writeString(path, Long.toString(l)); +- } catch (IOException var3) { +- throw new UncheckedIOException(var3); ++ long i = ProcessHandle.current().pid(); ++ ++ Files.writeString(path, Long.toString(i)); ++ } catch (IOException ioexception) { ++ throw new UncheckedIOException(ioexception); + } + } + +- private static WorldLoader.InitConfig loadOrCreateConfig( +- DedicatedServerProperties dedicatedServerProperties, @Nullable Dynamic dynamic, boolean flag, PackRepository packRepository +- ) { ++ private static WorldLoader.c loadOrCreateConfig(DedicatedServerProperties dedicatedserverproperties, @Nullable Dynamic dynamic, boolean flag, PackRepository resourcepackrepository) { + boolean flag1; +- WorldDataConfiguration worldDataConfiguration; ++ WorldDataConfiguration worlddataconfiguration; ++ + if (dynamic != null) { +- WorldDataConfiguration dataConfig = LevelStorageSource.readDataConfig(dynamic); ++ WorldDataConfiguration worlddataconfiguration1 = LevelStorageSource.readDataConfig(dynamic); ++ + flag1 = false; +- worldDataConfiguration = dataConfig; ++ worlddataconfiguration = worlddataconfiguration1; + } else { + flag1 = true; +- worldDataConfiguration = new WorldDataConfiguration(dedicatedServerProperties.initialDataPackConfiguration, FeatureFlags.DEFAULT_FLAGS); ++ worlddataconfiguration = new WorldDataConfiguration(dedicatedserverproperties.initialDataPackConfiguration, FeatureFlags.DEFAULT_FLAGS); + } + +- WorldLoader.PackConfig packConfig = new WorldLoader.PackConfig(packRepository, worldDataConfiguration, flag, flag1); +- return new WorldLoader.InitConfig(packConfig, Commands.CommandSelection.DEDICATED, dedicatedServerProperties.functionPermissionLevel); ++ WorldLoader.d worldloader_d = new WorldLoader.d(resourcepackrepository, worlddataconfiguration, flag, flag1); ++ ++ return new WorldLoader.c(worldloader_d, Commands.CommandSelection.DEDICATED, dedicatedserverproperties.functionPermissionLevel); + } + +- private static void forceUpgrade( +- LevelStorageSource.LevelStorageAccess levelStorage, +- DataFixer dataFixer, +- boolean eraseCache, +- BooleanSupplier upgradeWorld, +- Registry dimesions +- ) { +- LOGGER.info("Forcing world upgrade!"); +- WorldUpgrader worldUpgrader = new WorldUpgrader(levelStorage, dataFixer, dimesions, eraseCache); +- Component component = null; ++ public static void forceUpgrade(LevelStorageSource.LevelStorageAccess levelStorage, DataFixer dataFixer, boolean eraseCache, BooleanSupplier upgradeWorld, Registry dimesions) { ++ Main.LOGGER.info("Forcing world upgrade! {}", levelStorage.getLevelId()); // CraftBukkit ++ WorldUpgrader worldupgrader = new WorldUpgrader(levelStorage, dataFixer, dimesions, eraseCache); ++ Component ichatbasecomponent = null; + +- while (!worldUpgrader.isFinished()) { +- Component status = worldUpgrader.getStatus(); +- if (component != status) { +- component = status; +- LOGGER.info(worldUpgrader.getStatus().getString()); ++ while (!worldupgrader.isFinished()) { ++ Component ichatbasecomponent1 = worldupgrader.getStatus(); ++ ++ if (ichatbasecomponent != ichatbasecomponent1) { ++ ichatbasecomponent = ichatbasecomponent1; ++ Main.LOGGER.info(worldupgrader.getStatus().getString()); + } + +- int totalChunks = worldUpgrader.getTotalChunks(); +- if (totalChunks > 0) { +- int i = worldUpgrader.getConverted() + worldUpgrader.getSkipped(); +- LOGGER.info("{}% completed ({} / {} chunks)...", Mth.floor((float)i / (float)totalChunks * 100.0F), i, totalChunks); ++ int i = worldupgrader.getTotalChunks(); ++ ++ if (i > 0) { ++ int j = worldupgrader.getConverted() + worldupgrader.getSkipped(); ++ ++ Main.LOGGER.info("{}% completed ({} / {} chunks)...", new Object[]{Mth.floor((float) j / (float) i * 100.0F), j, i}); + } + + if (!upgradeWorld.getAsBoolean()) { +- worldUpgrader.cancel(); ++ worldupgrader.cancel(); + } else { + try { + Thread.sleep(1000L); +- } catch (InterruptedException var10) { ++ } catch (InterruptedException interruptedexception) { ++ ; + } + } + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/MinecraftServer.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/MinecraftServer.java.patch new file mode 100644 index 0000000000..8b50495875 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/MinecraftServer.java.patch @@ -0,0 +1,2472 @@ +--- a/net/minecraft/server/MinecraftServer.java ++++ b/net/minecraft/server/MinecraftServer.java +@@ -14,29 +14,32 @@ + import it.unimi.dsi.fastutil.longs.LongIterator; + import it.unimi.dsi.fastutil.objects.ObjectArrayList; + import java.awt.image.BufferedImage; ++import java.io.BufferedWriter; + import java.io.ByteArrayOutputStream; + import java.io.File; + import java.io.IOException; +-import java.io.Writer; + import java.lang.management.ManagementFactory; + import java.lang.management.ThreadInfo; + import java.lang.management.ThreadMXBean; + import java.net.Proxy; + import java.nio.file.Files; ++import java.nio.file.LinkOption; + import java.nio.file.Path; + import java.security.KeyPair; ++import java.util.ArrayList; + import java.util.Arrays; + import java.util.Collection; + import java.util.Collections; + import java.util.Comparator; ++import java.util.Iterator; + import java.util.List; + import java.util.Locale; + import java.util.Map; ++import java.util.Map.Entry; + import java.util.Objects; + import java.util.Optional; + import java.util.Set; + import java.util.UUID; +-import java.util.Map.Entry; + import java.util.concurrent.CompletableFuture; + import java.util.concurrent.Executor; + import java.util.concurrent.RejectedExecutionException; +@@ -45,6 +48,7 @@ + import java.util.function.Consumer; + import java.util.function.Function; + import java.util.stream.Collectors; ++import java.util.stream.Stream; + import javax.annotation.Nullable; + import javax.imageio.ImageIO; + import net.minecraft.CrashReport; +@@ -56,7 +60,6 @@ + import net.minecraft.commands.CommandSourceStack; + import net.minecraft.commands.Commands; + import net.minecraft.core.BlockPos; +-import net.minecraft.core.Holder; + import net.minecraft.core.HolderGetter; + import net.minecraft.core.LayeredRegistryAccess; + import net.minecraft.core.Registry; +@@ -73,7 +76,6 @@ + import net.minecraft.obfuscate.DontObfuscate; + import net.minecraft.resources.ResourceKey; + import net.minecraft.resources.ResourceLocation; +-import net.minecraft.server.bossevents.CustomBossEvents; + import net.minecraft.server.level.DemoMode; + import net.minecraft.server.level.PlayerRespawnLogic; + import net.minecraft.server.level.ServerChunkCache; +@@ -88,7 +90,7 @@ + import net.minecraft.server.packs.PackType; + import net.minecraft.server.packs.repository.Pack; + import net.minecraft.server.packs.repository.PackRepository; +-import net.minecraft.server.packs.resources.CloseableResourceManager; ++import net.minecraft.server.packs.resources.IReloadableResourceManager; + import net.minecraft.server.packs.resources.MultiPackResourceManager; + import net.minecraft.server.packs.resources.ResourceManager; + import net.minecraft.server.players.GameProfileCache; +@@ -100,10 +102,12 @@ + import net.minecraft.util.ModCheck; + import net.minecraft.util.Mth; + import net.minecraft.util.NativeModuleLister; ++import net.minecraft.util.ProgressListener; + import net.minecraft.util.RandomSource; + import net.minecraft.util.SignatureValidator; + import net.minecraft.util.TimeUtil; + import net.minecraft.util.Unit; ++import net.minecraft.util.datafix.DataFixers; + import net.minecraft.util.profiling.EmptyProfileResults; + import net.minecraft.util.profiling.ProfileResults; + import net.minecraft.util.profiling.ProfilerFiller; +@@ -119,6 +123,7 @@ + import net.minecraft.util.thread.ReentrantBlockableEventLoop; + import net.minecraft.world.Difficulty; + import net.minecraft.world.RandomSequences; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.ai.village.VillageSiege; + import net.minecraft.world.entity.npc.CatSpawner; + import net.minecraft.world.entity.npc.WanderingTraderSpawner; +@@ -137,34 +142,57 @@ + import net.minecraft.world.level.WorldDataConfiguration; + import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.block.Block; +-import net.minecraft.world.level.border.BorderChangeListener; + import net.minecraft.world.level.border.WorldBorder; + import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.levelgen.Heightmap; ++import net.minecraft.world.level.levelgen.MobSpawnerPhantom; + import net.minecraft.world.level.levelgen.PatrolSpawner; +-import net.minecraft.world.level.levelgen.PhantomSpawner; + import net.minecraft.world.level.levelgen.WorldOptions; ++import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; + import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; ++import net.minecraft.world.level.storage.WorldData; ++import net.minecraft.world.level.storage.loot.LootDataManager; ++import org.slf4j.Logger; ++ ++// CraftBukkit start ++import com.mojang.serialization.Dynamic; ++import com.mojang.serialization.Lifecycle; ++import java.util.Random; ++import jline.console.ConsoleReader; ++import joptsimple.OptionSet; ++import net.minecraft.nbt.NbtException; ++import net.minecraft.nbt.ReportedNbtException; ++import net.minecraft.server.bossevents.CustomBossEvents; ++import net.minecraft.server.dedicated.DedicatedServer; ++import net.minecraft.server.dedicated.DedicatedServerProperties; ++import net.minecraft.world.level.levelgen.WorldDimensions; ++import net.minecraft.world.level.levelgen.presets.WorldPresets; + import net.minecraft.world.level.storage.CommandStorage; +-import net.minecraft.world.level.storage.DerivedLevelData; + import net.minecraft.world.level.storage.DimensionDataStorage; + import net.minecraft.world.level.storage.LevelData; ++import net.minecraft.world.level.storage.LevelDataAndDimensions; + import net.minecraft.world.level.storage.LevelResource; + import net.minecraft.world.level.storage.LevelStorageSource; ++import net.minecraft.world.level.storage.LevelSummary; + import net.minecraft.world.level.storage.PlayerDataStorage; ++import net.minecraft.world.level.storage.PrimaryLevelData; + import net.minecraft.world.level.storage.ServerLevelData; +-import net.minecraft.world.level.storage.WorldData; +-import net.minecraft.world.level.storage.loot.LootDataManager; ++import net.minecraft.world.level.validation.ContentValidationException; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; +-import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.Main; ++import org.bukkit.event.server.ServerLoadEvent; ++// CraftBukkit end + + public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements ServerInfo, CommandSource, AutoCloseable { +- private static final Logger LOGGER = LogUtils.getLogger(); ++ ++ public static final Logger LOGGER = LogUtils.getLogger(); + public static final String VANILLA_BRAND = "vanilla"; + private static final float AVERAGE_TICK_TIME_SMOOTHING = 0.8F; + private static final int TICK_STATS_SPAN = 100; +- private static final long OVERLOADED_THRESHOLD_NANOS = 20L * TimeUtil.NANOSECONDS_PER_SECOND / 20L; ++ private static final long OVERLOADED_THRESHOLD_NANOS = 30L * TimeUtil.NANOSECONDS_PER_SECOND / 20L; // CraftBukkit + private static final int OVERLOADED_TICKS_THRESHOLD = 20; + private static final long OVERLOADED_WARNING_INTERVAL_NANOS = 10L * TimeUtil.NANOSECONDS_PER_SECOND; + private static final int OVERLOADED_TICKS_WARNING_INTERVAL = 100; +@@ -177,39 +205,36 @@ + private static final int MIMINUM_AUTOSAVE_TICKS = 100; + private static final int MAX_TICK_LATENCY = 3; + public static final int ABSOLUTE_MAX_WORLD_SIZE = 29999984; +- public static final LevelSettings DEMO_SETTINGS = new LevelSettings( +- "Demo World", GameType.SURVIVAL, false, Difficulty.NORMAL, false, new GameRules(), WorldDataConfiguration.DEFAULT +- ); ++ public static final LevelSettings DEMO_SETTINGS = new LevelSettings("Demo World", GameType.SURVIVAL, false, Difficulty.NORMAL, false, new GameRules(), WorldDataConfiguration.DEFAULT); + public static final GameProfile ANONYMOUS_PLAYER_PROFILE = new GameProfile(Util.NIL_UUID, "Anonymous Player"); +- protected final LevelStorageSource.LevelStorageAccess storageSource; +- protected final PlayerDataStorage playerDataStorage; ++ public LevelStorageSource.LevelStorageAccess storageSource; ++ public final PlayerDataStorage playerDataStorage; + private final List tickables = Lists.newArrayList(); +- private MetricsRecorder metricsRecorder = InactiveMetricsRecorder.INSTANCE; +- private ProfilerFiller profiler = this.metricsRecorder.getProfiler(); +- private Consumer onMetricsRecordingStopped = profileResults -> this.stopRecordingMetrics(); +- private Consumer onMetricsRecordingFinished = path -> { +- }; ++ private MetricsRecorder metricsRecorder; ++ private ProfilerFiller profiler; ++ private Consumer onMetricsRecordingStopped; ++ private Consumer onMetricsRecordingFinished; + private boolean willStartRecordingMetrics; + @Nullable + private MinecraftServer.TimeProfiler debugCommandProfiler; + private boolean debugCommandProfilerDelayStart; +- private final ServerConnectionListener connection; +- private final ChunkProgressListenerFactory progressListenerFactory; ++ private ServerConnectionListener connection; ++ public final ChunkProgressListenerFactory progressListenerFactory; + @Nullable + private ServerStatus status; + @Nullable +- private ServerStatus.Favicon statusIcon; +- private final RandomSource random = RandomSource.create(); +- private final DataFixer fixerUpper; ++ private ServerStatus.a statusIcon; ++ private final RandomSource random; ++ public final DataFixer fixerUpper; + private String localIp; +- private int port = -1; ++ private int port; + private final LayeredRegistryAccess registries; +- private final Map, ServerLevel> levels = Maps.newLinkedHashMap(); ++ private Map, ServerLevel> levels; + private PlayerList playerList; +- private volatile boolean running = true; ++ private volatile boolean running; + private boolean stopped; + private int tickCount; +- private int ticksUntilAutosave = 6000; ++ private int ticksUntilAutosave; + protected final Proxy proxy; + private boolean onlineMode; + private boolean preventProxyConnections; +@@ -218,8 +243,8 @@ + @Nullable + private String motd; + private int playerIdleTimeout; +- private final long[] tickTimesNanos = new long[100]; +- private long aggregatedTickTimesNanos = 0L; ++ private final long[] tickTimesNanos; ++ private long aggregatedTickTimesNanos; + @Nullable + private KeyPair keyPair; + @Nullable +@@ -229,60 +254,87 @@ + private long lastOverloadWarningNanos; + protected final Services services; + private long lastServerStatus; +- private final Thread serverThread; +- private long nextTickTimeNanos = Util.getNanos(); ++ public final Thread serverThread; ++ private long nextTickTimeNanos; + private long delayedTasksMaxNextTickTimeNanos; + private boolean mayHaveDelayedTasks; + private final PackRepository packRepository; +- private final ServerScoreboard scoreboard = new ServerScoreboard(this); ++ private final ServerScoreboard scoreboard; + @Nullable + private CommandStorage commandStorage; +- private final CustomBossEvents customBossEvents = new CustomBossEvents(); ++ private final CustomBossEvents customBossEvents; + private final ServerFunctionManager functionManager; + private boolean enforceWhitelist; + private float smoothedTickTimeMillis; +- private final Executor executor; ++ public final Executor executor; + @Nullable + private String serverId; +- private MinecraftServer.ReloadableResources resources; ++ public MinecraftServer.ReloadableResources resources; + private final StructureTemplateManager structureTemplateManager; + private final ServerTickRateManager tickRateManager; +- protected final WorldData worldData; ++ protected WorldData worldData; + private volatile boolean isSaving; + ++ // CraftBukkit start ++ public final WorldLoader.a worldLoader; ++ public org.bukkit.craftbukkit.CraftServer server; ++ public OptionSet options; ++ public org.bukkit.command.ConsoleCommandSender console; ++ public ConsoleReader reader; ++ public static int currentTick = (int) (System.currentTimeMillis() / 50); ++ public java.util.Queue processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); ++ public int autosavePeriod; ++ public Commands vanillaCommandDispatcher; ++ private boolean forceTicks; ++ // CraftBukkit end ++ + public static S spin(Function threadFunction) { +- AtomicReference atomicReference = new AtomicReference<>(); +- Thread thread = new Thread(() -> atomicReference.get().runServer(), "Server thread"); +- thread.setUncaughtExceptionHandler((thread1, throwable) -> LOGGER.error("Uncaught exception in server thread", throwable)); ++ AtomicReference atomicreference = new AtomicReference(); ++ Thread thread = new Thread(() -> { ++ ((MinecraftServer) atomicreference.get()).runServer(); ++ }, "Server thread"); ++ ++ thread.setUncaughtExceptionHandler((thread1, throwable) -> { ++ MinecraftServer.LOGGER.error("Uncaught exception in server thread", throwable); ++ }); + if (Runtime.getRuntime().availableProcessors() > 4) { + thread.setPriority(8); + } + +- S minecraftServer = (S)threadFunction.apply(thread); +- atomicReference.set(minecraftServer); ++ S s0 = threadFunction.apply(thread); // CraftBukkit - decompile error ++ ++ atomicreference.set(s0); + thread.start(); +- return minecraftServer; ++ return s0; + } + +- public MinecraftServer( +- Thread serverThread, +- LevelStorageSource.LevelStorageAccess storageSource, +- PackRepository packRepository, +- WorldStem worldStem, +- Proxy proxy, +- DataFixer fixerUpper, +- Services services, +- ChunkProgressListenerFactory progressListenerFactory +- ) { ++ public MinecraftServer(OptionSet options, WorldLoader.a worldLoader, Thread thread, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PackRepository resourcepackrepository, WorldStem worldstem, Proxy proxy, DataFixer datafixer, Services services, ChunkProgressListenerFactory worldloadlistenerfactory) { + super("Server"); +- this.registries = worldStem.registries(); +- this.worldData = worldStem.worldData(); +- if (!this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM).containsKey(LevelStem.OVERWORLD)) { ++ this.metricsRecorder = InactiveMetricsRecorder.INSTANCE; ++ this.profiler = this.metricsRecorder.getProfiler(); ++ this.onMetricsRecordingStopped = (methodprofilerresults) -> { ++ this.stopRecordingMetrics(); ++ }; ++ this.onMetricsRecordingFinished = (path) -> { ++ }; ++ this.random = RandomSource.create(); ++ this.port = -1; ++ this.levels = Maps.newLinkedHashMap(); ++ this.running = true; ++ this.ticksUntilAutosave = 6000; ++ this.tickTimesNanos = new long[100]; ++ this.aggregatedTickTimesNanos = 0L; ++ this.nextTickTimeNanos = Util.getNanos(); ++ this.scoreboard = new ServerScoreboard(this); ++ this.customBossEvents = new CustomBossEvents(); ++ this.registries = worldstem.registries(); ++ this.worldData = worldstem.worldData(); ++ if (false && !this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM).containsKey(LevelStem.OVERWORLD)) { // CraftBukkit - initialised later + throw new IllegalStateException("Missing Overworld dimension data"); + } else { + this.proxy = proxy; +- this.packRepository = packRepository; +- this.resources = new MinecraftServer.ReloadableResources(worldStem.resourceManager(), worldStem.dataPackResources()); ++ this.packRepository = resourcepackrepository; ++ this.resources = new MinecraftServer.ReloadableResources(worldstem.resourceManager(), worldstem.dataPackResources()); + this.services = services; + if (services.profileCache() != null) { + services.profileCache().setExecutor(this); +@@ -290,20 +342,44 @@ + + this.connection = new ServerConnectionListener(this); + this.tickRateManager = new ServerTickRateManager(this); +- this.progressListenerFactory = progressListenerFactory; +- this.storageSource = storageSource; +- this.playerDataStorage = storageSource.createPlayerStorage(); +- this.fixerUpper = fixerUpper; ++ this.progressListenerFactory = worldloadlistenerfactory; ++ this.storageSource = convertable_conversionsession; ++ this.playerDataStorage = convertable_conversionsession.createPlayerStorage(); ++ this.fixerUpper = datafixer; + this.functionManager = new ServerFunctionManager(this, this.resources.managers.getFunctionLibrary()); +- HolderGetter holderGetter = this.registries +- .compositeAccess() +- .registryOrThrow(Registries.BLOCK) +- .asLookup() +- .filterFeatures(this.worldData.enabledFeatures()); +- this.structureTemplateManager = new StructureTemplateManager(worldStem.resourceManager(), storageSource, fixerUpper, holderGetter); +- this.serverThread = serverThread; ++ HolderGetter holdergetter = this.registries.compositeAccess().registryOrThrow(Registries.BLOCK).asLookup().filterFeatures(this.worldData.enabledFeatures()); ++ ++ this.structureTemplateManager = new StructureTemplateManager(worldstem.resourceManager(), convertable_conversionsession, datafixer, holdergetter); ++ this.serverThread = thread; + this.executor = Util.backgroundExecutor(); + } ++ // CraftBukkit start ++ this.options = options; ++ this.worldLoader = worldLoader; ++ this.vanillaCommandDispatcher = worldstem.dataPackResources().commands; // CraftBukkit ++ // Try to see if we're actually running in a terminal, disable jline if not ++ if (System.console() == null && System.getProperty("jline.terminal") == null) { ++ System.setProperty("jline.terminal", "jline.UnsupportedTerminal"); ++ Main.useJline = false; ++ } ++ ++ try { ++ reader = new ConsoleReader(System.in, System.out); ++ reader.setExpandEvents(false); // Avoid parsing exceptions for uncommonly used event designators ++ } catch (Throwable e) { ++ try { ++ // Try again with jline disabled for Windows users without C++ 2008 Redistributable ++ System.setProperty("jline.terminal", "jline.UnsupportedTerminal"); ++ System.setProperty("user.language", "en"); ++ Main.useJline = false; ++ reader = new ConsoleReader(System.in, System.out); ++ reader.setExpandEvents(false); ++ } catch (IOException ex) { ++ LOGGER.warn((String) null, ex); ++ } ++ } ++ Runtime.getRuntime().addShutdownHook(new org.bukkit.craftbukkit.util.ServerShutdownThread(this)); ++ // CraftBukkit end + } + + private void readScoreboard(DimensionDataStorage dataStorage) { +@@ -312,207 +388,403 @@ + + protected abstract boolean initServer() throws IOException; + +- protected void loadLevel() { ++ protected void loadLevel(String s) { // CraftBukkit + if (!JvmProfiler.INSTANCE.isRunning()) { ++ ; + } + + boolean flag = false; +- ProfiledDuration profiledDuration = JvmProfiler.INSTANCE.onWorldLoadedStarted(); +- this.worldData.setModdedInfo(this.getServerModName(), this.getModdedStatus().shouldReportAsModified()); +- ChunkProgressListener chunkProgressListener = this.progressListenerFactory.create(11); +- this.createLevels(chunkProgressListener); +- this.forceDifficulty(); +- this.prepareLevels(chunkProgressListener); +- if (profiledDuration != null) { +- profiledDuration.finish(); ++ ProfiledDuration profiledduration = JvmProfiler.INSTANCE.onWorldLoadedStarted(); ++ ++ loadWorld0(s); // CraftBukkit ++ ++ if (profiledduration != null) { ++ profiledduration.finish(); + } + + if (flag) { + try { + JvmProfiler.INSTANCE.stop(); +- } catch (Throwable var5) { +- LOGGER.warn("Failed to stop JFR profiling", var5); ++ } catch (Throwable throwable) { ++ MinecraftServer.LOGGER.warn("Failed to stop JFR profiling", throwable); + } + } +- } + +- protected void forceDifficulty() { + } + +- protected void createLevels(ChunkProgressListener listener) { +- ServerLevelData serverLevelData = this.worldData.overworldData(); +- boolean isDebugWorld = this.worldData.isDebugWorld(); +- Registry registry = this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM); +- WorldOptions worldOptions = this.worldData.worldGenOptions(); +- long l = worldOptions.seed(); +- long l1 = BiomeManager.obfuscateSeed(l); +- List list = ImmutableList.of( +- new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(serverLevelData) +- ); +- LevelStem levelStem = registry.get(LevelStem.OVERWORLD); +- ServerLevel serverLevel = new ServerLevel( +- this, this.executor, this.storageSource, serverLevelData, Level.OVERWORLD, levelStem, listener, isDebugWorld, l1, list, true, null +- ); +- this.levels.put(Level.OVERWORLD, serverLevel); +- DimensionDataStorage dataStorage = serverLevel.getDataStorage(); +- this.readScoreboard(dataStorage); +- this.commandStorage = new CommandStorage(dataStorage); +- WorldBorder worldBorder = serverLevel.getWorldBorder(); +- if (!serverLevelData.isInitialized()) { +- try { +- setInitialSpawn(serverLevel, serverLevelData, worldOptions.generateBonusChest(), isDebugWorld); +- serverLevelData.setInitialized(true); +- if (isDebugWorld) { +- this.setupDebugLevel(this.worldData); ++ protected void forceDifficulty() {} ++ ++ // CraftBukkit start ++ private void loadWorld0(String s) { ++ LevelStorageSource.LevelStorageAccess worldSession = this.storageSource; ++ ++ Registry dimensions = this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM); ++ for (LevelStem worldDimension : dimensions) { ++ ResourceKey dimensionKey = dimensions.getResourceKey(worldDimension).get(); ++ ++ ServerLevel world; ++ int dimension = 0; ++ ++ if (dimensionKey == LevelStem.NETHER) { ++ if (isNetherEnabled()) { ++ dimension = -1; ++ } else { ++ continue; + } +- } catch (Throwable var23) { +- CrashReport crashReport = CrashReport.forThrowable(var23, "Exception initializing level"); ++ } else if (dimensionKey == LevelStem.END) { ++ if (server.getAllowEnd()) { ++ dimension = 1; ++ } else { ++ continue; ++ } ++ } else if (dimensionKey != LevelStem.OVERWORLD) { ++ dimension = -999; ++ } + ++ String worldType = (dimension == -999) ? dimensionKey.location().getNamespace() + "_" + dimensionKey.location().getPath() : org.bukkit.World.Environment.getEnvironment(dimension).toString().toLowerCase(); ++ String name = (dimensionKey == LevelStem.OVERWORLD) ? s : s + "_" + worldType; ++ if (dimension != 0) { ++ File newWorld = LevelStorageSource.getStorageFolder(new File(name).toPath(), dimensionKey).toFile(); ++ File oldWorld = LevelStorageSource.getStorageFolder(new File(s).toPath(), dimensionKey).toFile(); ++ File oldLevelDat = new File(new File(s), "level.dat"); // The data folders exist on first run as they are created in the PersistentCollection constructor above, but the level.dat won't ++ ++ if (!newWorld.isDirectory() && oldWorld.isDirectory() && oldLevelDat.isFile()) { ++ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder required ----"); ++ MinecraftServer.LOGGER.info("Unfortunately due to the way that Minecraft implemented multiworld support in 1.6, Bukkit requires that you move your " + worldType + " folder to a new location in order to operate correctly."); ++ MinecraftServer.LOGGER.info("We will move this folder for you, but it will mean that you need to move it back should you wish to stop using Bukkit in the future."); ++ MinecraftServer.LOGGER.info("Attempting to move " + oldWorld + " to " + newWorld + "..."); ++ ++ if (newWorld.exists()) { ++ MinecraftServer.LOGGER.warn("A file or folder already exists at " + newWorld + "!"); ++ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder failed ----"); ++ } else if (newWorld.getParentFile().mkdirs()) { ++ if (oldWorld.renameTo(newWorld)) { ++ MinecraftServer.LOGGER.info("Success! To restore " + worldType + " in the future, simply move " + newWorld + " to " + oldWorld); ++ // Migrate world data too. ++ try { ++ com.google.common.io.Files.copy(oldLevelDat, new File(new File(name), "level.dat")); ++ org.apache.commons.io.FileUtils.copyDirectory(new File(new File(s), "data"), new File(new File(name), "data")); ++ } catch (IOException exception) { ++ MinecraftServer.LOGGER.warn("Unable to migrate world data."); ++ } ++ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder complete ----"); ++ } else { ++ MinecraftServer.LOGGER.warn("Could not move folder " + oldWorld + " to " + newWorld + "!"); ++ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder failed ----"); ++ } ++ } else { ++ MinecraftServer.LOGGER.warn("Could not create path for " + newWorld + "!"); ++ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder failed ----"); ++ } ++ } ++ + try { +- serverLevel.fillReportDetails(crashReport); +- } catch (Throwable var22) { ++ worldSession = LevelStorageSource.createDefault(server.getWorldContainer().toPath()).validateAndCreateAccess(name, dimensionKey); ++ } catch (IOException | ContentValidationException ex) { ++ throw new RuntimeException(ex); + } ++ } + +- throw new ReportedException(crashReport); ++ Dynamic dynamic; ++ if (worldSession.hasWorldData()) { ++ LevelSummary worldinfo; ++ ++ try { ++ dynamic = worldSession.getDataTag(); ++ worldinfo = worldSession.getSummary(dynamic); ++ } catch (NbtException | ReportedNbtException | IOException ioexception) { ++ LevelStorageSource.LevelDirectory convertable_b = worldSession.getLevelDirectory(); ++ ++ MinecraftServer.LOGGER.warn("Failed to load world data from {}", convertable_b.dataFile(), ioexception); ++ MinecraftServer.LOGGER.info("Attempting to use fallback"); ++ ++ try { ++ dynamic = worldSession.getDataTagFallback(); ++ worldinfo = worldSession.getSummary(dynamic); ++ } catch (NbtException | ReportedNbtException | IOException ioexception1) { ++ MinecraftServer.LOGGER.error("Failed to load world data from {}", convertable_b.oldDataFile(), ioexception1); ++ MinecraftServer.LOGGER.error("Failed to load world data from {} and {}. World files may be corrupted. Shutting down.", convertable_b.dataFile(), convertable_b.oldDataFile()); ++ return; ++ } ++ ++ worldSession.restoreLevelDataFromOld(); ++ } ++ ++ if (worldinfo.requiresManualConversion()) { ++ MinecraftServer.LOGGER.info("This world must be opened in an older version (like 1.6.4) to be safely converted"); ++ return; ++ } ++ ++ if (!worldinfo.isCompatible()) { ++ MinecraftServer.LOGGER.info("This world was created by an incompatible version."); ++ return; ++ } ++ } else { ++ dynamic = null; + } + +- serverLevelData.setInitialized(true); ++ org.bukkit.generator.ChunkGenerator gen = this.server.getGenerator(name); ++ org.bukkit.generator.BiomeProvider biomeProvider = this.server.getBiomeProvider(name); ++ ++ PrimaryLevelData worlddata; ++ WorldLoader.a worldloader_a = this.worldLoader; ++ Registry iregistry = worldloader_a.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM); ++ if (dynamic != null) { ++ LevelDataAndDimensions leveldataanddimensions = LevelStorageSource.getLevelDataAndDimensions(dynamic, worldloader_a.dataConfiguration(), iregistry, worldloader_a.datapackWorldgen()); ++ ++ worlddata = (PrimaryLevelData) leveldataanddimensions.worldData(); ++ } else { ++ LevelSettings worldsettings; ++ WorldOptions worldoptions; ++ WorldDimensions worlddimensions; ++ ++ if (this.isDemo()) { ++ worldsettings = MinecraftServer.DEMO_SETTINGS; ++ worldoptions = WorldOptions.DEMO_OPTIONS; ++ worlddimensions = WorldPresets.createNormalWorldDimensions(worldloader_a.datapackWorldgen()); ++ } else { ++ DedicatedServerProperties dedicatedserverproperties = ((DedicatedServer) this).getProperties(); ++ ++ worldsettings = new LevelSettings(dedicatedserverproperties.levelName, dedicatedserverproperties.gamemode, dedicatedserverproperties.hardcore, dedicatedserverproperties.difficulty, false, new GameRules(), worldloader_a.dataConfiguration()); ++ worldoptions = options.has("bonusChest") ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions; ++ worlddimensions = dedicatedserverproperties.createDimensions(worldloader_a.datapackWorldgen()); ++ } ++ ++ WorldDimensions.b worlddimensions_b = worlddimensions.bake(iregistry); ++ Lifecycle lifecycle = worlddimensions_b.lifecycle().add(worldloader_a.datapackWorldgen().allRegistriesLifecycle()); ++ ++ worlddata = new PrimaryLevelData(worldsettings, worldoptions, worlddimensions_b.specialWorldProperty(), lifecycle); ++ } ++ worlddata.checkName(name); // CraftBukkit - Migration did not rewrite the level.dat; This forces 1.8 to take the last loaded world as respawn (in this case the end) ++ if (options.has("forceUpgrade")) { ++ net.minecraft.server.Main.forceUpgrade(worldSession, DataFixers.getDataFixer(), options.has("eraseCache"), () -> { ++ return true; ++ }, dimensions); ++ } ++ ++ PrimaryLevelData iworlddataserver = worlddata; ++ boolean flag = worlddata.isDebugWorld(); ++ WorldOptions worldoptions = worlddata.worldGenOptions(); ++ long i = worldoptions.seed(); ++ long j = BiomeManager.obfuscateSeed(i); ++ List list = ImmutableList.of(new MobSpawnerPhantom(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(iworlddataserver)); ++ LevelStem worlddimension = (LevelStem) dimensions.get(dimensionKey); ++ ++ org.bukkit.generator.WorldInfo worldInfo = new org.bukkit.craftbukkit.generator.CraftWorldInfo(iworlddataserver, worldSession, org.bukkit.World.Environment.getEnvironment(dimension), worlddimension.type().value()); ++ if (biomeProvider == null && gen != null) { ++ biomeProvider = gen.getDefaultBiomeProvider(worldInfo); ++ } ++ ++ ResourceKey worldKey = ResourceKey.create(Registries.DIMENSION, dimensionKey.location()); ++ ++ if (dimensionKey == LevelStem.OVERWORLD) { ++ this.worldData = worlddata; ++ this.worldData.setGameType(((DedicatedServer) this).getProperties().gamemode); // From DedicatedServer.init ++ ++ ChunkProgressListener worldloadlistener = this.progressListenerFactory.create(11); ++ ++ world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, worlddimension, worldloadlistener, flag, j, list, true, (RandomSequences) null, org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider); ++ DimensionDataStorage worldpersistentdata = world.getDataStorage(); ++ this.readScoreboard(worldpersistentdata); ++ this.server.scoreboardManager = new org.bukkit.craftbukkit.scoreboard.CraftScoreboardManager(this, world.getScoreboard()); ++ this.commandStorage = new CommandStorage(worldpersistentdata); ++ } else { ++ ChunkProgressListener worldloadlistener = this.progressListenerFactory.create(11); ++ world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, worlddimension, worldloadlistener, flag, j, ImmutableList.of(), true, this.overworld().getRandomSequences(), org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider); ++ } ++ ++ worlddata.setModdedInfo(this.getServerModName(), this.getModdedStatus().shouldReportAsModified()); ++ this.initWorld(world, worlddata, worldData, worldoptions); ++ ++ this.addLevel(world); ++ this.getPlayerList().addWorldborderListener(world); ++ ++ if (worlddata.getCustomBossEvents() != null) { ++ this.getCustomBossEvents().load(worlddata.getCustomBossEvents()); ++ } + } ++ this.forceDifficulty(); ++ for (ServerLevel worldserver : this.getAllLevels()) { ++ this.prepareLevels(worldserver.getChunkSource().chunkMap.progressListener, worldserver); ++ worldserver.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API ++ this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldLoadEvent(worldserver.getWorld())); ++ } + +- this.getPlayerList().addWorldborderListener(serverLevel); +- if (this.worldData.getCustomBossEvents() != null) { +- this.getCustomBossEvents().load(this.worldData.getCustomBossEvents()); ++ this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.POSTWORLD); ++ this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP)); ++ this.connection.acceptConnections(); ++ } ++ ++ public void initWorld(ServerLevel worldserver, ServerLevelData iworlddataserver, WorldData saveData, WorldOptions worldoptions) { ++ boolean flag = saveData.isDebugWorld(); ++ // CraftBukkit start ++ if (worldserver.generator != null) { ++ worldserver.getWorld().getPopulators().addAll(worldserver.generator.getDefaultPopulators(worldserver.getWorld())); + } ++ WorldBorder worldborder = worldserver.getWorldBorder(); ++ worldborder.applySettings(iworlddataserver.getWorldBorder()); // CraftBukkit - move up so that WorldBorder is set during WorldInitEvent ++ this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldInitEvent(worldserver.getWorld())); // CraftBukkit - SPIGOT-5569: Call WorldInitEvent before any chunks are generated + +- RandomSequences randomSequences = serverLevel.getRandomSequences(); ++ if (!iworlddataserver.isInitialized()) { ++ try { ++ setInitialSpawn(worldserver, iworlddataserver, worldoptions.generateBonusChest(), flag); ++ iworlddataserver.setInitialized(true); ++ if (flag) { ++ this.setupDebugLevel(this.worldData); ++ } ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception initializing level"); + +- for (Entry, LevelStem> entry : registry.entrySet()) { +- ResourceKey resourceKey = entry.getKey(); +- if (resourceKey != LevelStem.OVERWORLD) { +- ResourceKey resourceKey1 = ResourceKey.create(Registries.DIMENSION, resourceKey.location()); +- DerivedLevelData derivedLevelData = new DerivedLevelData(this.worldData, serverLevelData); +- ServerLevel serverLevel1 = new ServerLevel( +- this, +- this.executor, +- this.storageSource, +- derivedLevelData, +- resourceKey1, +- entry.getValue(), +- listener, +- isDebugWorld, +- l1, +- ImmutableList.of(), +- false, +- randomSequences +- ); +- worldBorder.addListener(new BorderChangeListener.DelegateBorderChangeListener(serverLevel1.getWorldBorder())); +- this.levels.put(resourceKey1, serverLevel1); ++ try { ++ worldserver.fillReportDetails(crashreport); ++ } catch (Throwable throwable1) { ++ ; ++ } ++ ++ throw new ReportedException(crashreport); + } ++ ++ iworlddataserver.setInitialized(true); + } + +- worldBorder.applySettings(serverLevelData.getWorldBorder()); + } ++ // CraftBukkit end + + private static void setInitialSpawn(ServerLevel level, ServerLevelData levelData, boolean generateBonusChest, boolean debug) { + if (debug) { + levelData.setSpawn(BlockPos.ZERO.above(80), 0.0F); + } else { +- ServerChunkCache chunkSource = level.getChunkSource(); +- ChunkPos chunkPos = new ChunkPos(chunkSource.randomState().sampler().findSpawnPosition()); +- int spawnHeight = chunkSource.getGenerator().getSpawnHeight(level); +- if (spawnHeight < level.getMinBuildHeight()) { +- BlockPos worldPosition = chunkPos.getWorldPosition(); +- spawnHeight = level.getHeight(Heightmap.Types.WORLD_SURFACE, worldPosition.getX() + 8, worldPosition.getZ() + 8); ++ ServerChunkCache chunkproviderserver = level.getChunkSource(); ++ ChunkPos chunkcoordintpair = new ChunkPos(chunkproviderserver.randomState().sampler().findSpawnPosition()); ++ // CraftBukkit start ++ if (level.generator != null) { ++ Random rand = new Random(level.getSeed()); ++ org.bukkit.Location spawn = level.generator.getFixedSpawnLocation(level.getWorld(), rand); ++ ++ if (spawn != null) { ++ if (spawn.getWorld() != level.getWorld()) { ++ throw new IllegalStateException("Cannot set spawn point for " + levelData.getLevelName() + " to be in another world (" + spawn.getWorld().getName() + ")"); ++ } else { ++ levelData.setSpawn(new BlockPos(spawn.getBlockX(), spawn.getBlockY(), spawn.getBlockZ()), spawn.getYaw()); ++ return; ++ } ++ } + } ++ // CraftBukkit end ++ int i = chunkproviderserver.getGenerator().getSpawnHeight(level); + +- levelData.setSpawn(chunkPos.getWorldPosition().offset(8, spawnHeight, 8), 0.0F); +- int i = 0; +- int i1 = 0; +- int i2 = 0; +- int i3 = -1; +- int i4 = 5; ++ if (i < level.getMinBuildHeight()) { ++ BlockPos blockposition = chunkcoordintpair.getWorldPosition(); + +- for (int i5 = 0; i5 < Mth.square(11); i5++) { +- if (i >= -5 && i <= 5 && i1 >= -5 && i1 <= 5) { +- BlockPos spawnPosInChunk = PlayerRespawnLogic.getSpawnPosInChunk(level, new ChunkPos(chunkPos.x + i, chunkPos.z + i1)); +- if (spawnPosInChunk != null) { +- levelData.setSpawn(spawnPosInChunk, 0.0F); ++ i = level.getHeight(Heightmap.Types.WORLD_SURFACE, blockposition.getX() + 8, blockposition.getZ() + 8); ++ } ++ ++ levelData.setSpawn(chunkcoordintpair.getWorldPosition().offset(8, i, 8), 0.0F); ++ int j = 0; ++ int k = 0; ++ int l = 0; ++ int i1 = -1; ++ boolean flag2 = true; ++ ++ for (int j1 = 0; j1 < Mth.square(11); ++j1) { ++ if (j >= -5 && j <= 5 && k >= -5 && k <= 5) { ++ BlockPos blockposition1 = PlayerRespawnLogic.getSpawnPosInChunk(level, new ChunkPos(chunkcoordintpair.x + j, chunkcoordintpair.z + k)); ++ ++ if (blockposition1 != null) { ++ levelData.setSpawn(blockposition1, 0.0F); + break; + } + } + +- if (i == i1 || i < 0 && i == -i1 || i > 0 && i == 1 - i1) { +- int i6 = i2; +- i2 = -i3; +- i3 = i6; ++ if (j == k || j < 0 && j == -k || j > 0 && j == 1 - k) { ++ int k1 = l; ++ ++ l = -i1; ++ i1 = k1; + } + +- i += i2; +- i1 += i3; ++ j += l; ++ k += i1; + } + + if (generateBonusChest) { +- level.registryAccess() +- .registry(Registries.CONFIGURED_FEATURE) +- .flatMap(registry -> registry.getHolder(MiscOverworldFeatures.BONUS_CHEST)) +- .ifPresent( +- reference -> reference.value() +- .place( +- level, +- chunkSource.getGenerator(), +- level.random, +- new BlockPos(levelData.getXSpawn(), levelData.getYSpawn(), levelData.getZSpawn()) +- ) +- ); ++ level.registryAccess().registry(Registries.CONFIGURED_FEATURE).flatMap((iregistry) -> { ++ return iregistry.getHolder(MiscOverworldFeatures.BONUS_CHEST); ++ }).ifPresent((holder_c) -> { ++ ((ConfiguredFeature) holder_c.value()).place(level, chunkproviderserver.getGenerator(), level.random, new BlockPos(levelData.getXSpawn(), levelData.getYSpawn(), levelData.getZSpawn())); ++ }); + } ++ + } + } + + private void setupDebugLevel(WorldData worldData) { + worldData.setDifficulty(Difficulty.PEACEFUL); + worldData.setDifficultyLocked(true); +- ServerLevelData serverLevelData = worldData.overworldData(); +- serverLevelData.setRaining(false); +- serverLevelData.setThundering(false); +- serverLevelData.setClearWeatherTime(1000000000); +- serverLevelData.setDayTime(6000L); +- serverLevelData.setGameType(GameType.SPECTATOR); ++ ServerLevelData iworlddataserver = worldData.overworldData(); ++ ++ iworlddataserver.setRaining(false); ++ iworlddataserver.setThundering(false); ++ iworlddataserver.setClearWeatherTime(1000000000); ++ iworlddataserver.setDayTime(6000L); ++ iworlddataserver.setGameType(GameType.SPECTATOR); + } + +- private void prepareLevels(ChunkProgressListener listener) { +- ServerLevel serverLevel = this.overworld(); +- LOGGER.info("Preparing start region for dimension {}", serverLevel.dimension().location()); +- BlockPos sharedSpawnPos = serverLevel.getSharedSpawnPos(); +- listener.updateSpawnPos(new ChunkPos(sharedSpawnPos)); +- ServerChunkCache chunkSource = serverLevel.getChunkSource(); ++ // CraftBukkit start ++ public void prepareLevels(ChunkProgressListener worldloadlistener, ServerLevel worldserver) { ++ // WorldServer worldserver = this.overworld(); ++ this.forceTicks = true; ++ // CraftBukkit end ++ ++ MinecraftServer.LOGGER.info("Preparing start region for dimension {}", worldserver.dimension().location()); ++ BlockPos blockposition = worldserver.getSharedSpawnPos(); ++ ++ worldloadlistener.updateSpawnPos(new ChunkPos(blockposition)); ++ ServerChunkCache chunkproviderserver = worldserver.getChunkSource(); ++ + this.nextTickTimeNanos = Util.getNanos(); +- chunkSource.addRegionTicket(TicketType.START, new ChunkPos(sharedSpawnPos), 11, Unit.INSTANCE); ++ // CraftBukkit start ++ if (worldserver.getWorld().getKeepSpawnInMemory()) { ++ chunkproviderserver.addRegionTicket(TicketType.START, new ChunkPos(blockposition), 11, Unit.INSTANCE); + +- while (chunkSource.getTickingGenerated() != 441) { +- this.nextTickTimeNanos = Util.getNanos() + PREPARE_LEVELS_DEFAULT_DELAY_NANOS; +- this.waitUntilNextTick(); ++ while (chunkproviderserver.getTickingGenerated() != 441) { ++ // this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; ++ this.executeModerately(); ++ } + } + +- this.nextTickTimeNanos = Util.getNanos() + PREPARE_LEVELS_DEFAULT_DELAY_NANOS; +- this.waitUntilNextTick(); ++ // this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; ++ this.executeModerately(); ++ // Iterator iterator = this.levels.values().iterator(); + +- for (ServerLevel serverLevel1 : this.levels.values()) { +- ForcedChunksSavedData forcedChunksSavedData = serverLevel1.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks"); +- if (forcedChunksSavedData != null) { +- LongIterator longIterator = forcedChunksSavedData.getChunks().iterator(); ++ if (true) { ++ ServerLevel worldserver1 = worldserver; ++ // CraftBukkit end ++ ForcedChunksSavedData forcedchunk = (ForcedChunksSavedData) worldserver1.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks"); + +- while (longIterator.hasNext()) { +- long l = longIterator.nextLong(); +- ChunkPos chunkPos = new ChunkPos(l); +- serverLevel1.getChunkSource().updateChunkForced(chunkPos, true); ++ if (forcedchunk != null) { ++ LongIterator longiterator = forcedchunk.getChunks().iterator(); ++ ++ while (longiterator.hasNext()) { ++ long i = longiterator.nextLong(); ++ ChunkPos chunkcoordintpair = new ChunkPos(i); ++ ++ worldserver1.getChunkSource().updateChunkForced(chunkcoordintpair, true); + } + } + } + +- this.nextTickTimeNanos = Util.getNanos() + PREPARE_LEVELS_DEFAULT_DELAY_NANOS; +- this.waitUntilNextTick(); +- listener.stop(); +- this.updateMobSpawningFlags(); ++ // CraftBukkit start ++ // this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; ++ this.executeModerately(); ++ // CraftBukkit end ++ worldloadlistener.stop(); ++ // CraftBukkit start ++ // this.updateMobSpawningFlags(); ++ worldserver.setSpawnSettings(this.isSpawningMonsters(), this.isSpawningAnimals()); ++ ++ this.forceTicks = false; ++ // CraftBukkit end + } + + public GameType getDefaultGameType() { +@@ -530,44 +802,55 @@ + public abstract boolean shouldRconBroadcast(); + + public boolean saveAllChunks(boolean suppressLog, boolean flush, boolean forced) { +- boolean flag = false; ++ boolean flag3 = false; + +- for (ServerLevel serverLevel : this.getAllLevels()) { ++ for (Iterator iterator = this.getAllLevels().iterator(); iterator.hasNext(); flag3 = true) { ++ ServerLevel worldserver = (ServerLevel) iterator.next(); ++ + if (!suppressLog) { +- LOGGER.info("Saving chunks for level '{}'/{}", serverLevel, serverLevel.dimension().location()); ++ MinecraftServer.LOGGER.info("Saving chunks for level '{}'/{}", worldserver, worldserver.dimension().location()); + } + +- serverLevel.save(null, flush, serverLevel.noSave && !forced); +- flag = true; ++ worldserver.save((ProgressListener) null, flush, worldserver.noSave && !forced); + } + +- ServerLevel serverLevel1 = this.overworld(); +- ServerLevelData serverLevelData = this.worldData.overworldData(); +- serverLevelData.setWorldBorder(serverLevel1.getWorldBorder().createSettings()); ++ // CraftBukkit start - moved to WorldServer.save ++ /* ++ WorldServer worldserver1 = this.overworld(); ++ IWorldDataServer iworlddataserver = this.worldData.overworldData(); ++ ++ iworlddataserver.setWorldBorder(worldserver1.getWorldBorder().createSettings()); + this.worldData.setCustomBossEvents(this.getCustomBossEvents().save()); + this.storageSource.saveDataTag(this.registryAccess(), this.worldData, this.getPlayerList().getSingleplayerData()); ++ */ ++ // CraftBukkit end + if (flush) { +- for (ServerLevel serverLevel2 : this.getAllLevels()) { +- LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", serverLevel2.getChunkSource().chunkMap.getStorageName()); ++ Iterator iterator1 = this.getAllLevels().iterator(); ++ ++ while (iterator1.hasNext()) { ++ ServerLevel worldserver2 = (ServerLevel) iterator1.next(); ++ ++ MinecraftServer.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", worldserver2.getChunkSource().chunkMap.getStorageName()); + } + +- LOGGER.info("ThreadedAnvilChunkStorage: All dimensions are saved"); ++ MinecraftServer.LOGGER.info("ThreadedAnvilChunkStorage: All dimensions are saved"); + } + +- return flag; ++ return flag3; + } + + public boolean saveEverything(boolean suppressLog, boolean flush, boolean forced) { +- boolean var4; ++ boolean flag3; ++ + try { + this.isSaving = true; + this.getPlayerList().saveAll(); +- var4 = this.saveAllChunks(suppressLog, flush, forced); ++ flag3 = this.saveAllChunks(suppressLog, flush, forced); + } finally { + this.isSaving = false; + } + +- return var4; ++ return flag3; + } + + @Override +@@ -575,47 +858,81 @@ + this.stopServer(); + } + ++ // CraftBukkit start ++ private boolean hasStopped = false; ++ private final Object stopLock = new Object(); ++ public final boolean hasStopped() { ++ synchronized (stopLock) { ++ return hasStopped; ++ } ++ } ++ // CraftBukkit end ++ + public void stopServer() { ++ // CraftBukkit start - prevent double stopping on multiple threads ++ synchronized(stopLock) { ++ if (hasStopped) return; ++ hasStopped = true; ++ } ++ // CraftBukkit end + if (this.metricsRecorder.isRecording()) { + this.cancelRecordingMetrics(); + } + +- LOGGER.info("Stopping server"); ++ MinecraftServer.LOGGER.info("Stopping server"); ++ // CraftBukkit start ++ if (this.server != null) { ++ this.server.disablePlugins(); ++ } ++ // CraftBukkit end + this.getConnection().stop(); + this.isSaving = true; + if (this.playerList != null) { +- LOGGER.info("Saving players"); ++ MinecraftServer.LOGGER.info("Saving players"); + this.playerList.saveAll(); + this.playerList.removeAll(); ++ try { Thread.sleep(100); } catch (InterruptedException ex) {} // CraftBukkit - SPIGOT-625 - give server at least a chance to send packets + } + +- LOGGER.info("Saving worlds"); ++ MinecraftServer.LOGGER.info("Saving worlds"); ++ Iterator iterator = this.getAllLevels().iterator(); + +- for (ServerLevel serverLevel : this.getAllLevels()) { +- if (serverLevel != null) { +- serverLevel.noSave = false; ++ ServerLevel worldserver; ++ ++ while (iterator.hasNext()) { ++ worldserver = (ServerLevel) iterator.next(); ++ if (worldserver != null) { ++ worldserver.noSave = false; + } + } + +- while (this.levels.values().stream().anyMatch(serverLevel1 -> serverLevel1.getChunkSource().chunkMap.hasWork())) { ++ while (this.levels.values().stream().anyMatch((worldserver1) -> { ++ return worldserver1.getChunkSource().chunkMap.hasWork(); ++ })) { + this.nextTickTimeNanos = Util.getNanos() + TimeUtil.NANOSECONDS_PER_MILLISECOND; ++ iterator = this.getAllLevels().iterator(); + +- for (ServerLevel serverLevelx : this.getAllLevels()) { +- serverLevelx.getChunkSource().removeTicketsOnClosing(); +- serverLevelx.getChunkSource().tick(() -> true, false); ++ while (iterator.hasNext()) { ++ worldserver = (ServerLevel) iterator.next(); ++ worldserver.getChunkSource().removeTicketsOnClosing(); ++ worldserver.getChunkSource().tick(() -> { ++ return true; ++ }, false); + } + + this.waitUntilNextTick(); + } + + this.saveAllChunks(false, true, false); ++ iterator = this.getAllLevels().iterator(); + +- for (ServerLevel serverLevelx : this.getAllLevels()) { +- if (serverLevelx != null) { ++ while (iterator.hasNext()) { ++ worldserver = (ServerLevel) iterator.next(); ++ if (worldserver != null) { + try { +- serverLevelx.close(); +- } catch (IOException var5) { +- LOGGER.error("Exception closing the level", (Throwable)var5); ++ worldserver.close(); ++ } catch (IOException ioexception) { ++ MinecraftServer.LOGGER.error("Exception closing the level", ioexception); + } + } + } +@@ -625,9 +942,10 @@ + + try { + this.storageSource.close(); +- } catch (IOException var4) { +- LOGGER.error("Failed to unlock level {}", this.storageSource.getLevelId(), var4); ++ } catch (IOException ioexception1) { ++ MinecraftServer.LOGGER.error("Failed to unlock level {}", this.storageSource.getLevelId(), ioexception1); + } ++ + } + + public String getLocalIp() { +@@ -647,10 +965,11 @@ + if (waitForServer) { + try { + this.serverThread.join(); +- } catch (InterruptedException var3) { +- LOGGER.error("Error while shutting down", (Throwable)var3); ++ } catch (InterruptedException interruptedexception) { ++ MinecraftServer.LOGGER.error("Error while shutting down", interruptedexception); + } + } ++ + } + + protected void runServer() { +@@ -660,40 +979,47 @@ + } + + this.nextTickTimeNanos = Util.getNanos(); +- this.statusIcon = this.loadStatusIcon().orElse(null); ++ this.statusIcon = (ServerStatus.a) this.loadStatusIcon().orElse(null); // CraftBukkit - decompile error + this.status = this.buildServerStatus(); + + while (this.running) { +- long l; ++ long i; ++ + if (!this.isPaused() && this.tickRateManager.isSprinting() && this.tickRateManager.checkShouldSprintThisTick()) { +- l = 0L; ++ i = 0L; + this.nextTickTimeNanos = Util.getNanos(); + this.lastOverloadWarningNanos = this.nextTickTimeNanos; + } else { +- l = this.tickRateManager.nanosecondsPerTick(); +- long l1 = Util.getNanos() - this.nextTickTimeNanos; +- if (l1 > OVERLOADED_THRESHOLD_NANOS + 20L * l +- && this.nextTickTimeNanos - this.lastOverloadWarningNanos >= OVERLOADED_WARNING_INTERVAL_NANOS + 100L * l) { +- long l2 = l1 / l; +- LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", l1 / TimeUtil.NANOSECONDS_PER_MILLISECOND, l2); +- this.nextTickTimeNanos += l2 * l; ++ i = this.tickRateManager.nanosecondsPerTick(); ++ long j = Util.getNanos() - this.nextTickTimeNanos; ++ ++ if (j > MinecraftServer.OVERLOADED_THRESHOLD_NANOS + 20L * i && this.nextTickTimeNanos - this.lastOverloadWarningNanos >= MinecraftServer.OVERLOADED_WARNING_INTERVAL_NANOS + 100L * i) { ++ long k = j / i; ++ ++ if (server.getWarnOnOverload()) // CraftBukkit ++ MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", j / TimeUtil.NANOSECONDS_PER_MILLISECOND, k); ++ this.nextTickTimeNanos += k * i; + this.lastOverloadWarningNanos = this.nextTickTimeNanos; + } + } + +- boolean flag = l == 0L; ++ boolean flag = i == 0L; ++ + if (this.debugCommandProfilerDelayStart) { + this.debugCommandProfilerDelayStart = false; + this.debugCommandProfiler = new MinecraftServer.TimeProfiler(Util.getNanos(), this.tickCount); + } + +- this.nextTickTimeNanos += l; ++ MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit ++ this.nextTickTimeNanos += i; + this.startMetricsRecordingTick(); + this.profiler.push("tick"); +- this.tickServer(flag ? () -> false : this::haveTime); ++ this.tickServer(flag ? () -> { ++ return false; ++ } : this::haveTime); + this.profiler.popPush("nextTickWait"); + this.mayHaveDelayedTasks = true; +- this.delayedTasksMaxNextTickTimeNanos = Math.max(Util.getNanos() + l, this.nextTickTimeNanos); ++ this.delayedTasksMaxNextTickTimeNanos = Math.max(Util.getNanos() + i, this.nextTickTimeNanos); + this.waitUntilNextTick(); + if (flag) { + this.tickRateManager.endTickWork(); +@@ -704,78 +1030,100 @@ + this.isReady = true; + JvmProfiler.INSTANCE.onServerTick(this.smoothedTickTimeMillis); + } +- } catch (Throwable var46) { +- LOGGER.error("Encountered an unexpected exception", var46); +- CrashReport crashReport = constructOrExtractCrashReport(var46); +- this.fillSystemReport(crashReport.getSystemReport()); ++ } catch (Throwable throwable) { ++ MinecraftServer.LOGGER.error("Encountered an unexpected exception", throwable); ++ CrashReport crashreport = constructOrExtractCrashReport(throwable); ++ ++ this.fillSystemReport(crashreport.getSystemReport()); + File file = new File(new File(this.getServerDirectory(), "crash-reports"), "crash-" + Util.getFilenameFormattedDateTime() + "-server.txt"); +- if (crashReport.saveToFile(file)) { +- LOGGER.error("This crash report has been saved to: {}", file.getAbsolutePath()); ++ ++ if (crashreport.saveToFile(file)) { ++ MinecraftServer.LOGGER.error("This crash report has been saved to: {}", file.getAbsolutePath()); + } else { +- LOGGER.error("We were unable to save this crash report to disk."); ++ MinecraftServer.LOGGER.error("We were unable to save this crash report to disk."); + } + +- this.onServerCrash(crashReport); ++ this.onServerCrash(crashreport); + } finally { + try { + this.stopped = true; + this.stopServer(); +- } catch (Throwable var44) { +- LOGGER.error("Exception stopping the server", var44); ++ } catch (Throwable throwable1) { ++ MinecraftServer.LOGGER.error("Exception stopping the server", throwable1); + } finally { + if (this.services.profileCache() != null) { + this.services.profileCache().clearExecutor(); + } + ++ // CraftBukkit start - Restore terminal to original settings ++ try { ++ reader.getTerminal().restore(); ++ } catch (Exception ignored) { ++ } ++ // CraftBukkit end + this.onServerExit(); + } ++ + } ++ + } + + private static CrashReport constructOrExtractCrashReport(Throwable cause) { +- ReportedException reportedException = null; ++ ReportedException reportedexception = null; + +- for (Throwable throwable = cause; throwable != null; throwable = throwable.getCause()) { +- if (throwable instanceof ReportedException reportedException1) { +- reportedException = reportedException1; ++ for (Throwable throwable1 = cause; throwable1 != null; throwable1 = throwable1.getCause()) { ++ if (throwable1 instanceof ReportedException) { ++ ReportedException reportedexception1 = (ReportedException) throwable1; ++ ++ reportedexception = reportedexception1; + } + } + +- CrashReport report; +- if (reportedException != null) { +- report = reportedException.getReport(); +- if (reportedException != cause) { +- report.addCategory("Wrapped in").setDetailError("Wrapping exception", cause); ++ CrashReport crashreport; ++ ++ if (reportedexception != null) { ++ crashreport = reportedexception.getReport(); ++ if (reportedexception != cause) { ++ crashreport.addCategory("Wrapped in").setDetailError("Wrapping exception", cause); + } + } else { +- report = new CrashReport("Exception in server tick loop", cause); ++ crashreport = new CrashReport("Exception in server tick loop", cause); + } + +- return report; ++ return crashreport; + } + + private boolean haveTime() { +- return this.runningTask() || Util.getNanos() < (this.mayHaveDelayedTasks ? this.delayedTasksMaxNextTickTimeNanos : this.nextTickTimeNanos); ++ // CraftBukkit start ++ return this.forceTicks || this.runningTask() || Util.getNanos() < (this.mayHaveDelayedTasks ? this.delayedTasksMaxNextTickTimeNanos : this.nextTickTimeNanos); + } + ++ private void executeModerately() { ++ this.runAllTasks(); ++ java.util.concurrent.locks.LockSupport.parkNanos("executing tasks", 1000L); ++ // CraftBukkit end ++ } ++ + protected void waitUntilNextTick() { + this.runAllTasks(); +- this.managedBlock(() -> !this.haveTime()); ++ this.managedBlock(() -> { ++ return !this.haveTime(); ++ }); + } + + @Override +- protected TickTask wrapRunnable(Runnable runnable) { ++ public TickTask wrapRunnable(Runnable runnable) { + return new TickTask(this.tickCount, runnable); + } + +- @Override +- protected boolean shouldRun(TickTask runnable) { +- return runnable.getTick() + 3 < this.tickCount || this.haveTime(); ++ protected boolean shouldRun(TickTask ticktask) { ++ return ticktask.getTick() + 3 < this.tickCount || this.haveTime(); + } + + @Override + public boolean pollTask() { + boolean flag = this.pollTaskInternal(); ++ + this.mayHaveDelayedTasks = flag; + return flag; + } +@@ -785,8 +1133,12 @@ + return true; + } else { + if (this.tickRateManager.isSprinting() || this.haveTime()) { +- for (ServerLevel serverLevel : this.getAllLevels()) { +- if (serverLevel.getChunkSource().pollTask()) { ++ Iterator iterator = this.getAllLevels().iterator(); ++ ++ while (iterator.hasNext()) { ++ ServerLevel worldserver = (ServerLevel) iterator.next(); ++ ++ if (worldserver.getChunkSource().pollTask()) { + return true; + } + } +@@ -796,26 +1148,32 @@ + } + } + +- @Override +- public void doRunTask(TickTask task) { ++ public void doRunTask(TickTask ticktask) { // CraftBukkit - decompile error + this.getProfiler().incrementCounter("runTask"); +- super.doRunTask(task); ++ super.doRunTask(ticktask); + } + +- private Optional loadStatusIcon() { +- Optional optional = Optional.of(this.getFile("server-icon.png").toPath()) +- .filter(path -> Files.isRegularFile(path)) +- .or(() -> this.storageSource.getIconFile().filter(path -> Files.isRegularFile(path))); +- return optional.flatMap(path -> { ++ private Optional loadStatusIcon() { ++ Optional optional = Optional.of(this.getFile("server-icon.png").toPath()).filter((path) -> { ++ return Files.isRegularFile(path, new LinkOption[0]); ++ }).or(() -> { ++ return this.storageSource.getIconFile().filter((path) -> { ++ return Files.isRegularFile(path, new LinkOption[0]); ++ }); ++ }); ++ ++ return optional.flatMap((path) -> { + try { +- BufferedImage bufferedImage = ImageIO.read(path.toFile()); +- Preconditions.checkState(bufferedImage.getWidth() == 64, "Must be 64 pixels wide"); +- Preconditions.checkState(bufferedImage.getHeight() == 64, "Must be 64 pixels high"); +- ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); +- ImageIO.write(bufferedImage, "PNG", byteArrayOutputStream); +- return Optional.of(new ServerStatus.Favicon(byteArrayOutputStream.toByteArray())); +- } catch (Exception var3) { +- LOGGER.error("Couldn't load server icon", (Throwable)var3); ++ BufferedImage bufferedimage = ImageIO.read(path.toFile()); ++ ++ Preconditions.checkState(bufferedimage.getWidth() == 64, "Must be 64 pixels wide"); ++ Preconditions.checkState(bufferedimage.getHeight() == 64, "Must be 64 pixels high"); ++ ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(); ++ ++ ImageIO.write(bufferedimage, "PNG", bytearrayoutputstream); ++ return Optional.of(new ServerStatus.a(bytearrayoutputstream.toByteArray())); ++ } catch (Exception exception) { ++ MinecraftServer.LOGGER.error("Couldn't load server icon", exception); + return Optional.empty(); + } + }); +@@ -829,124 +1187,153 @@ + return new File("."); + } + +- public void onServerCrash(CrashReport report) { +- } ++ public void onServerCrash(CrashReport report) {} + +- public void onServerExit() { +- } ++ public void onServerExit() {} + + public boolean isPaused() { + return false; + } + + public void tickServer(BooleanSupplier hasTimeLeft) { +- long nanos = Util.getNanos(); +- this.tickCount++; ++ long i = Util.getNanos(); ++ ++ ++this.tickCount; + this.tickRateManager.tick(); + this.tickChildren(hasTimeLeft); +- if (nanos - this.lastServerStatus >= STATUS_EXPIRE_TIME_NANOS) { +- this.lastServerStatus = nanos; ++ if (i - this.lastServerStatus >= MinecraftServer.STATUS_EXPIRE_TIME_NANOS) { ++ this.lastServerStatus = i; + this.status = this.buildServerStatus(); + } + +- this.ticksUntilAutosave--; +- if (this.ticksUntilAutosave <= 0) { +- this.ticksUntilAutosave = this.computeNextAutosaveInterval(); +- LOGGER.debug("Autosave started"); ++ --this.ticksUntilAutosave; ++ // CraftBukkit start ++ if (this.autosavePeriod > 0 && this.ticksUntilAutosave <= 0) { ++ this.ticksUntilAutosave = this.autosavePeriod; ++ // CraftBukkit end ++ MinecraftServer.LOGGER.debug("Autosave started"); + this.profiler.push("save"); + this.saveEverything(true, false, false); + this.profiler.pop(); +- LOGGER.debug("Autosave finished"); ++ MinecraftServer.LOGGER.debug("Autosave finished"); + } + + this.profiler.push("tallying"); +- long l = Util.getNanos() - nanos; +- int i = this.tickCount % 100; +- this.aggregatedTickTimesNanos = this.aggregatedTickTimesNanos - this.tickTimesNanos[i]; +- this.aggregatedTickTimesNanos += l; +- this.tickTimesNanos[i] = l; +- this.smoothedTickTimeMillis = this.smoothedTickTimeMillis * 0.8F + (float)l / (float)TimeUtil.NANOSECONDS_PER_MILLISECOND * 0.19999999F; +- long nanos1 = Util.getNanos(); +- this.logTickTime(nanos1 - nanos); ++ long j = Util.getNanos() - i; ++ int k = this.tickCount % 100; ++ ++ this.aggregatedTickTimesNanos -= this.tickTimesNanos[k]; ++ this.aggregatedTickTimesNanos += j; ++ this.tickTimesNanos[k] = j; ++ this.smoothedTickTimeMillis = this.smoothedTickTimeMillis * 0.8F + (float) j / (float) TimeUtil.NANOSECONDS_PER_MILLISECOND * 0.19999999F; ++ long l = Util.getNanos(); ++ ++ this.logTickTime(l - i); + this.profiler.pop(); + } + + private int computeNextAutosaveInterval() { + float f; ++ + if (this.tickRateManager.isSprinting()) { +- long l = this.getAverageTickTimeNanos() + 1L; +- f = (float)TimeUtil.NANOSECONDS_PER_SECOND / (float)l; ++ long i = this.getAverageTickTimeNanos() + 1L; ++ ++ f = (float) TimeUtil.NANOSECONDS_PER_SECOND / (float) i; + } else { + f = this.tickRateManager.tickrate(); + } + +- int i = 300; +- return Math.max(100, (int)(f * 300.0F)); ++ boolean flag = true; ++ ++ return Math.max(100, (int) (f * 300.0F)); + } + + public void onTickRateChanged() { + int i = this.computeNextAutosaveInterval(); ++ + if (i < this.ticksUntilAutosave) { + this.ticksUntilAutosave = i; + } +- } + +- protected void logTickTime(long l) { + } + ++ protected void logTickTime(long i) {} ++ + private ServerStatus buildServerStatus() { +- ServerStatus.Players players = this.buildPlayerStatus(); +- return new ServerStatus( +- Component.nullToEmpty(this.motd), +- Optional.of(players), +- Optional.of(ServerStatus.Version.current()), +- Optional.ofNullable(this.statusIcon), +- this.enforceSecureProfile() +- ); ++ ServerStatus.ServerPingPlayerSample serverping_serverpingplayersample = this.buildPlayerStatus(); ++ ++ return new ServerStatus(Component.nullToEmpty(this.motd), Optional.of(serverping_serverpingplayersample), Optional.of(ServerStatus.Version.current()), Optional.ofNullable(this.statusIcon), this.enforceSecureProfile()); + } + +- private ServerStatus.Players buildPlayerStatus() { +- List players = this.playerList.getPlayers(); +- int maxPlayers = this.getMaxPlayers(); ++ private ServerStatus.ServerPingPlayerSample buildPlayerStatus() { ++ List list = this.playerList.getPlayers(); ++ int i = this.getMaxPlayers(); ++ + if (this.hidesOnlinePlayers()) { +- return new ServerStatus.Players(maxPlayers, players.size(), List.of()); ++ return new ServerStatus.ServerPingPlayerSample(i, list.size(), List.of()); + } else { +- int min = Math.min(players.size(), 12); +- ObjectArrayList list = new ObjectArrayList<>(min); +- int randomInt = Mth.nextInt(this.random, 0, players.size() - min); ++ int j = Math.min(list.size(), 12); ++ ObjectArrayList objectarraylist = new ObjectArrayList(j); ++ int k = Mth.nextInt(this.random, 0, list.size() - j); + +- for (int i = 0; i < min; i++) { +- ServerPlayer serverPlayer = players.get(randomInt + i); +- list.add(serverPlayer.allowsListing() ? serverPlayer.getGameProfile() : ANONYMOUS_PLAYER_PROFILE); ++ for (int l = 0; l < j; ++l) { ++ ServerPlayer entityplayer = (ServerPlayer) list.get(k + l); ++ ++ objectarraylist.add(entityplayer.allowsListing() ? entityplayer.getGameProfile() : MinecraftServer.ANONYMOUS_PLAYER_PROFILE); + } + +- Util.shuffle(list, this.random); +- return new ServerStatus.Players(maxPlayers, players.size(), list); ++ Util.shuffle(objectarraylist, this.random); ++ return new ServerStatus.ServerPingPlayerSample(i, list.size(), objectarraylist); + } + } + + public void tickChildren(BooleanSupplier hasTimeLeft) { +- this.getPlayerList().getPlayers().forEach(serverPlayer1 -> serverPlayer1.connection.suspendFlushing()); ++ this.getPlayerList().getPlayers().forEach((entityplayer) -> { ++ entityplayer.connection.suspendFlushing(); ++ }); ++ this.server.getScheduler().mainThreadHeartbeat(this.tickCount); // CraftBukkit + this.profiler.push("commandFunctions"); + this.getFunctions().tick(); + this.profiler.popPush("levels"); ++ Iterator iterator = this.getAllLevels().iterator(); + +- for (ServerLevel serverLevel : this.getAllLevels()) { +- this.profiler.push(() -> serverLevel + " " + serverLevel.dimension().location()); ++ // CraftBukkit start ++ // Run tasks that are waiting on processing ++ while (!processQueue.isEmpty()) { ++ processQueue.remove().run(); ++ } ++ ++ // Send time updates to everyone, it will get the right time from the world the player is in. ++ if (this.tickCount % 20 == 0) { ++ for (int i = 0; i < this.getPlayerList().players.size(); ++i) { ++ ServerPlayer entityplayer = (ServerPlayer) this.getPlayerList().players.get(i); ++ entityplayer.connection.send(new ClientboundSetTimePacket(entityplayer.level().getGameTime(), entityplayer.getPlayerTime(), entityplayer.level().getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); // Add support for per player time ++ } ++ } ++ ++ while (iterator.hasNext()) { ++ ServerLevel worldserver = (ServerLevel) iterator.next(); ++ ++ this.profiler.push(() -> { ++ return worldserver + " " + worldserver.dimension().location(); ++ }); ++ /* Drop global time updates + if (this.tickCount % 20 == 0) { + this.profiler.push("timeSync"); +- this.synchronizeTime(serverLevel); ++ this.synchronizeTime(worldserver); + this.profiler.pop(); + } ++ // CraftBukkit end */ + + this.profiler.push("tick"); + + try { +- serverLevel.tick(hasTimeLeft); +- } catch (Throwable var6) { +- CrashReport crashReport = CrashReport.forThrowable(var6, "Exception ticking world"); +- serverLevel.fillReportDetails(crashReport); +- throw new ReportedException(crashReport); ++ worldserver.tick(hasTimeLeft); ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception ticking world"); ++ ++ worldserver.fillReportDetails(crashreport); ++ throw new ReportedException(crashreport); + } + + this.profiler.pop(); +@@ -963,33 +1350,35 @@ + + this.profiler.popPush("server gui refresh"); + +- for (int i = 0; i < this.tickables.size(); i++) { +- this.tickables.get(i).run(); ++ for (int i = 0; i < this.tickables.size(); ++i) { ++ ((Runnable) this.tickables.get(i)).run(); + } + + this.profiler.popPush("send chunks"); ++ iterator = this.playerList.getPlayers().iterator(); + +- for (ServerPlayer serverPlayer : this.playerList.getPlayers()) { +- serverPlayer.connection.chunkSender.sendNextChunks(serverPlayer); +- serverPlayer.connection.resumeFlushing(); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ entityplayer.connection.chunkSender.sendNextChunks(entityplayer); ++ entityplayer.connection.resumeFlushing(); + } + + this.profiler.pop(); + } + + private void synchronizeTime(ServerLevel level) { +- this.playerList +- .broadcastAll( +- new ClientboundSetTimePacket(level.getGameTime(), level.getDayTime(), level.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)), +- level.dimension() +- ); ++ this.playerList.broadcastAll(new ClientboundSetTimePacket(level.getGameTime(), level.getDayTime(), level.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)), level.dimension()); + } + + public void forceTimeSynchronization() { + this.profiler.push("timeSync"); ++ Iterator iterator = this.getAllLevels().iterator(); + +- for (ServerLevel serverLevel : this.getAllLevels()) { +- this.synchronizeTime(serverLevel); ++ while (iterator.hasNext()) { ++ ServerLevel worldserver = (ServerLevel) iterator.next(); ++ ++ this.synchronizeTime(worldserver); + } + + this.profiler.pop(); +@@ -1016,14 +1405,30 @@ + } + + public final ServerLevel overworld() { +- return this.levels.get(Level.OVERWORLD); ++ return (ServerLevel) this.levels.get(Level.OVERWORLD); + } + + @Nullable + public ServerLevel getLevel(ResourceKey dimension) { +- return this.levels.get(dimension); ++ return (ServerLevel) this.levels.get(dimension); + } + ++ // CraftBukkit start ++ public void addLevel(ServerLevel level) { ++ Map, ServerLevel> oldLevels = this.levels; ++ Map, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels); ++ newLevels.put(level.dimension(), level); ++ this.levels = Collections.unmodifiableMap(newLevels); ++ } ++ ++ public void removeLevel(ServerLevel level) { ++ Map, ServerLevel> oldLevels = this.levels; ++ Map, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels); ++ newLevels.remove(level.dimension()); ++ this.levels = Collections.unmodifiableMap(newLevels); ++ } ++ // CraftBukkit end ++ + public Set> levelKeys() { + return this.levels.keySet(); + } +@@ -1053,32 +1458,38 @@ + + @DontObfuscate + public String getServerModName() { +- return "vanilla"; ++ return server.getName(); // CraftBukkit - cb > vanilla! + } + + public SystemReport fillSystemReport(SystemReport systemReport) { +- systemReport.setDetail("Server Running", () -> Boolean.toString(this.running)); ++ systemReport.setDetail("Server Running", () -> { ++ return Boolean.toString(this.running); ++ }); + if (this.playerList != null) { +- systemReport.setDetail( +- "Player Count", () -> this.playerList.getPlayerCount() + " / " + this.playerList.getMaxPlayers() + "; " + this.playerList.getPlayers() +- ); ++ systemReport.setDetail("Player Count", () -> { ++ int i = this.playerList.getPlayerCount(); ++ ++ return i + " / " + this.playerList.getMaxPlayers() + "; " + this.playerList.getPlayers(); ++ }); + } + +- systemReport.setDetail( +- "Data Packs", +- () -> this.packRepository +- .getSelectedPacks() +- .stream() +- .map(pack -> pack.getId() + (pack.getCompatibility().isCompatible() ? "" : " (incompatible)")) +- .collect(Collectors.joining(", ")) +- ); +- systemReport.setDetail( +- "Enabled Feature Flags", +- () -> FeatureFlags.REGISTRY.toNames(this.worldData.enabledFeatures()).stream().map(ResourceLocation::toString).collect(Collectors.joining(", ")) +- ); +- systemReport.setDetail("World Generation", () -> this.worldData.worldGenSettingsLifecycle().toString()); ++ systemReport.setDetail("Data Packs", () -> { ++ return (String) this.packRepository.getSelectedPacks().stream().map((resourcepackloader) -> { ++ String s = resourcepackloader.getId(); ++ ++ return s + (resourcepackloader.getCompatibility().isCompatible() ? "" : " (incompatible)"); ++ }).collect(Collectors.joining(", ")); ++ }); ++ systemReport.setDetail("Enabled Feature Flags", () -> { ++ return (String) FeatureFlags.REGISTRY.toNames(this.worldData.enabledFeatures()).stream().map(ResourceLocation::toString).collect(Collectors.joining(", ")); ++ }); ++ systemReport.setDetail("World Generation", () -> { ++ return this.worldData.worldGenSettingsLifecycle().toString(); ++ }); + if (this.serverId != null) { +- systemReport.setDetail("Server Id", () -> this.serverId); ++ systemReport.setDetail("Server Id", () -> { ++ return this.serverId; ++ }); + } + + return this.fillServerSystemReport(systemReport); +@@ -1092,7 +1503,7 @@ + + @Override + public void sendSystemMessage(Component component) { +- LOGGER.info(component.getString()); ++ MinecraftServer.LOGGER.info(component.getString()); + } + + public KeyPair getKeyPair() { +@@ -1121,12 +1532,12 @@ + } + + protected void initializeKeyPair() { +- LOGGER.info("Generating keypair"); ++ MinecraftServer.LOGGER.info("Generating keypair"); + + try { + this.keyPair = Crypt.generateKeyPair(); +- } catch (CryptException var2) { +- throw new IllegalStateException("Failed to generate key pair", var2); ++ } catch (CryptException cryptographyexception) { ++ throw new IllegalStateException("Failed to generate key pair", cryptographyexception); + } + } + +@@ -1143,9 +1554,14 @@ + } + + private void updateMobSpawningFlags() { +- for (ServerLevel serverLevel : this.getAllLevels()) { +- serverLevel.setSpawnSettings(this.isSpawningMonsters(), this.isSpawningAnimals()); ++ Iterator iterator = this.getAllLevels().iterator(); ++ ++ while (iterator.hasNext()) { ++ ServerLevel worldserver = (ServerLevel) iterator.next(); ++ ++ worldserver.setSpawnSettings(this.isSpawningMonsters(), this.isSpawningAnimals()); + } ++ + } + + public void setDifficultyLocked(boolean locked) { +@@ -1154,8 +1570,9 @@ + } + + private void sendDifficultyUpdate(ServerPlayer player) { +- LevelData levelData = player.level().getLevelData(); +- player.connection.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked())); ++ LevelData worlddata = player.level().getLevelData(); ++ ++ player.connection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); + } + + public boolean isSpawningMonsters() { +@@ -1380,131 +1797,130 @@ + } + + public CompletableFuture reloadResources(Collection selectedIds) { +- RegistryAccess.Frozen accessForLoading = this.registries.getAccessForLoading(RegistryLayer.RELOADABLE); +- CompletableFuture completableFuture = CompletableFuture.supplyAsync( +- () -> selectedIds.stream().map(this.packRepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()), +- this +- ) +- .thenCompose( +- list -> { +- CloseableResourceManager closeableResourceManager = new MultiPackResourceManager(PackType.SERVER_DATA, list); +- return ReloadableServerResources.loadResources( +- closeableResourceManager, +- accessForLoading, +- this.worldData.enabledFeatures(), +- this.isDedicatedServer() ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED, +- this.getFunctionCompilationLevel(), +- this.executor, +- this +- ) +- .whenComplete((reloadableServerResources, throwable) -> { +- if (throwable != null) { +- closeableResourceManager.close(); +- } +- }) +- .thenApply(reloadableServerResources -> new MinecraftServer.ReloadableResources(closeableResourceManager, reloadableServerResources)); ++ RegistryAccess.Dimension iregistrycustom_dimension = this.registries.getAccessForLoading(RegistryLayer.RELOADABLE); ++ CompletableFuture completablefuture = CompletableFuture.supplyAsync(() -> { ++ Stream stream = selectedIds.stream(); // CraftBukkit - decompile error ++ PackRepository resourcepackrepository = this.packRepository; ++ ++ Objects.requireNonNull(this.packRepository); ++ return stream.map(resourcepackrepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()); // CraftBukkit - decompile error ++ }, this).thenCompose((immutablelist) -> { ++ MultiPackResourceManager resourcemanager = new MultiPackResourceManager(PackType.SERVER_DATA, immutablelist); ++ ++ return ReloadableServerResources.loadResources(resourcemanager, iregistrycustom_dimension, this.worldData.enabledFeatures(), this.isDedicatedServer() ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED, this.getFunctionCompilationLevel(), this.executor, this).whenComplete((datapackresources, throwable) -> { ++ if (throwable != null) { ++ resourcemanager.close(); + } +- ) +- .thenAcceptAsync( +- reloadableResources -> { +- this.resources.close(); +- this.resources = reloadableResources; +- this.packRepository.setSelected(selectedIds); +- WorldDataConfiguration worldDataConfiguration = new WorldDataConfiguration( +- getSelectedPacks(this.packRepository), this.worldData.enabledFeatures() +- ); +- this.worldData.setDataConfiguration(worldDataConfiguration); +- this.resources.managers.updateRegistryTags(this.registryAccess()); +- this.getPlayerList().saveAll(); +- this.getPlayerList().reloadResources(); +- this.functionManager.replaceLibrary(this.resources.managers.getFunctionLibrary()); +- this.structureTemplateManager.onResourceManagerReload(this.resources.resourceManager); +- }, +- this +- ); ++ ++ }).thenApply((datapackresources) -> { ++ return new MinecraftServer.ReloadableResources(resourcemanager, datapackresources); ++ }); ++ }).thenAcceptAsync((minecraftserver_reloadableresources) -> { ++ this.resources.close(); ++ this.resources = minecraftserver_reloadableresources; ++ this.server.syncCommands(); // SPIGOT-5884: Lost on reload ++ this.packRepository.setSelected(selectedIds); ++ WorldDataConfiguration worlddataconfiguration = new WorldDataConfiguration(getSelectedPacks(this.packRepository), this.worldData.enabledFeatures()); ++ ++ this.worldData.setDataConfiguration(worlddataconfiguration); ++ this.resources.managers.updateRegistryTags(this.registryAccess()); ++ this.getPlayerList().saveAll(); ++ this.getPlayerList().reloadResources(); ++ this.functionManager.replaceLibrary(this.resources.managers.getFunctionLibrary()); ++ this.structureTemplateManager.onResourceManagerReload(this.resources.resourceManager); ++ }, this); ++ + if (this.isSameThread()) { +- this.managedBlock(completableFuture::isDone); ++ Objects.requireNonNull(completablefuture); ++ this.managedBlock(completablefuture::isDone); + } + +- return completableFuture; ++ return completablefuture; + } + +- public static WorldDataConfiguration configurePackRepository( +- PackRepository packRepository, DataPackConfig dataPackConfig, boolean safeMode, FeatureFlagSet enabledFeatures +- ) { ++ public static WorldDataConfiguration configurePackRepository(PackRepository packRepository, DataPackConfig dataPackConfig, boolean safeMode, FeatureFlagSet enabledFeatures) { + packRepository.reload(); + if (safeMode) { + packRepository.setSelected(Collections.singleton("vanilla")); + return WorldDataConfiguration.DEFAULT; + } else { + Set set = Sets.newLinkedHashSet(); ++ Iterator iterator = dataPackConfig.getEnabled().iterator(); + +- for (String string : dataPackConfig.getEnabled()) { +- if (packRepository.isAvailable(string)) { +- set.add(string); ++ while (iterator.hasNext()) { ++ String s = (String) iterator.next(); ++ ++ if (packRepository.isAvailable(s)) { ++ set.add(s); + } else { +- LOGGER.warn("Missing data pack {}", string); ++ MinecraftServer.LOGGER.warn("Missing data pack {}", s); + } + } + +- for (Pack pack : packRepository.getAvailablePacks()) { +- String id = pack.getId(); +- if (!dataPackConfig.getDisabled().contains(id)) { +- FeatureFlagSet requestedFeatures = pack.getRequestedFeatures(); +- boolean flag = set.contains(id); +- if (!flag && pack.getPackSource().shouldAddAutomatically()) { +- if (requestedFeatures.isSubsetOf(enabledFeatures)) { +- LOGGER.info("Found new data pack {}, loading it automatically", id); +- set.add(id); ++ iterator = packRepository.getAvailablePacks().iterator(); ++ ++ while (iterator.hasNext()) { ++ Pack resourcepackloader = (Pack) iterator.next(); ++ String s1 = resourcepackloader.getId(); ++ ++ if (!dataPackConfig.getDisabled().contains(s1)) { ++ FeatureFlagSet featureflagset1 = resourcepackloader.getRequestedFeatures(); ++ boolean flag1 = set.contains(s1); ++ ++ if (!flag1 && resourcepackloader.getPackSource().shouldAddAutomatically()) { ++ if (featureflagset1.isSubsetOf(enabledFeatures)) { ++ MinecraftServer.LOGGER.info("Found new data pack {}, loading it automatically", s1); ++ set.add(s1); + } else { +- LOGGER.info( +- "Found new data pack {}, but can't load it due to missing features {}", +- id, +- FeatureFlags.printMissingFlags(enabledFeatures, requestedFeatures) +- ); ++ MinecraftServer.LOGGER.info("Found new data pack {}, but can't load it due to missing features {}", s1, FeatureFlags.printMissingFlags(enabledFeatures, featureflagset1)); + } + } + +- if (flag && !requestedFeatures.isSubsetOf(enabledFeatures)) { +- LOGGER.warn( +- "Pack {} requires features {} that are not enabled for this world, disabling pack.", +- id, +- FeatureFlags.printMissingFlags(enabledFeatures, requestedFeatures) +- ); +- set.remove(id); ++ if (flag1 && !featureflagset1.isSubsetOf(enabledFeatures)) { ++ MinecraftServer.LOGGER.warn("Pack {} requires features {} that are not enabled for this world, disabling pack.", s1, FeatureFlags.printMissingFlags(enabledFeatures, featureflagset1)); ++ set.remove(s1); + } + } + } + + if (set.isEmpty()) { +- LOGGER.info("No datapacks selected, forcing vanilla"); ++ MinecraftServer.LOGGER.info("No datapacks selected, forcing vanilla"); + set.add("vanilla"); + } + + packRepository.setSelected(set); +- DataPackConfig selectedPacks = getSelectedPacks(packRepository); +- FeatureFlagSet requestedFeatureFlags = packRepository.getRequestedFeatureFlags(); +- return new WorldDataConfiguration(selectedPacks, requestedFeatureFlags); ++ DataPackConfig datapackconfiguration1 = getSelectedPacks(packRepository); ++ FeatureFlagSet featureflagset2 = packRepository.getRequestedFeatureFlags(); ++ ++ return new WorldDataConfiguration(datapackconfiguration1, featureflagset2); + } + } + + private static DataPackConfig getSelectedPacks(PackRepository packRepository) { +- Collection selectedIds = packRepository.getSelectedIds(); +- List list = ImmutableList.copyOf(selectedIds); +- List list1 = packRepository.getAvailableIds().stream().filter(string -> !selectedIds.contains(string)).collect(ImmutableList.toImmutableList()); ++ Collection collection = packRepository.getSelectedIds(); ++ List list = ImmutableList.copyOf(collection); ++ List list1 = (List) packRepository.getAvailableIds().stream().filter((s) -> { ++ return !collection.contains(s); ++ }).collect(ImmutableList.toImmutableList()); ++ + return new DataPackConfig(list, list1); + } + + public void kickUnlistedPlayers(CommandSourceStack commandSource) { + if (this.isEnforceWhitelist()) { +- PlayerList playerList = commandSource.getServer().getPlayerList(); +- UserWhiteList whiteList = playerList.getWhiteList(); ++ PlayerList playerlist = commandSource.getServer().getPlayerList(); ++ UserWhiteList whitelist = playerlist.getWhiteList(); ++ List list = Lists.newArrayList(playerlist.getPlayers()); ++ Iterator iterator = list.iterator(); + +- for (ServerPlayer serverPlayer : Lists.newArrayList(playerList.getPlayers())) { +- if (!whiteList.isWhiteListed(serverPlayer.getGameProfile())) { +- serverPlayer.connection.disconnect(Component.translatable("multiplayer.disconnect.not_whitelisted")); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ if (!whitelist.isWhiteListed(entityplayer.getGameProfile())) { ++ entityplayer.connection.disconnect(Component.translatable("multiplayer.disconnect.not_whitelisted")); + } + } ++ + } + } + +@@ -1517,18 +1933,9 @@ + } + + public CommandSourceStack createCommandSourceStack() { +- ServerLevel serverLevel = this.overworld(); +- return new CommandSourceStack( +- this, +- serverLevel == null ? Vec3.ZERO : Vec3.atLowerCornerOf(serverLevel.getSharedSpawnPos()), +- Vec2.ZERO, +- serverLevel, +- 4, +- "Server", +- Component.literal("Server"), +- this, +- null +- ); ++ ServerLevel worldserver = this.overworld(); ++ ++ return new CommandSourceStack(this, worldserver == null ? Vec3.ZERO : Vec3.atLowerCornerOf(worldserver.getSharedSpawnPos()), Vec2.ZERO, worldserver, 4, "Server", Component.literal("Server"), this, (Entity) null); + } + + @Override +@@ -1589,7 +1996,7 @@ + } + + public long getAverageTickTimeNanos() { +- return this.aggregatedTickTimesNanos / (long)Math.min(100, Math.max(this.tickCount, 1)); ++ return this.aggregatedTickTimesNanos / (long) Math.min(100, Math.max(this.tickCount, 1)); + } + + public long[] getTickTimesNanos() { +@@ -1598,16 +2005,9 @@ + + public int getProfilePermissions(GameProfile profile) { + if (this.getPlayerList().isOp(profile)) { +- ServerOpListEntry serverOpListEntry = this.getPlayerList().getOps().get(profile); +- if (serverOpListEntry != null) { +- return serverOpListEntry.getLevel(); +- } else if (this.isSingleplayerOwner(profile)) { +- return 4; +- } else if (this.isSingleplayer()) { +- return this.getPlayerList().isAllowCheatsForAllPlayers() ? 4 : 0; +- } else { +- return this.getOperatorUserPermissionLevel(); +- } ++ ServerOpListEntry oplistentry = (ServerOpListEntry) this.getPlayerList().getOps().get(profile); ++ ++ return oplistentry != null ? oplistentry.getLevel() : (this.isSingleplayerOwner(profile) ? 4 : (this.isSingleplayer() ? (this.getPlayerList().isAllowCheatsForAllPlayers() ? 4 : 0) : this.getOperatorUserPermissionLevel())); + } else { + return 0; + } +@@ -1619,18 +2019,21 @@ + + public abstract boolean isSingleplayerOwner(GameProfile profile); + +- public void dumpServerProperties(Path path) throws IOException { +- } ++ public void dumpServerProperties(Path path) throws IOException {} + + private void saveDebugReport(Path path) { + Path path1 = path.resolve("levels"); + + try { +- for (Entry, ServerLevel> entry : this.levels.entrySet()) { +- ResourceLocation resourceLocation = entry.getKey().location(); +- Path path2 = path1.resolve(resourceLocation.getNamespace()).resolve(resourceLocation.getPath()); ++ Iterator iterator = this.levels.entrySet().iterator(); ++ ++ while (iterator.hasNext()) { ++ Entry, ServerLevel> entry = (Entry) iterator.next(); ++ ResourceLocation minecraftkey = ((ResourceKey) entry.getKey()).location(); ++ Path path2 = path1.resolve(minecraftkey.getNamespace()).resolve(minecraftkey.getPath()); ++ + Files.createDirectories(path2); +- entry.getValue().saveDebugReport(path2); ++ ((ServerLevel) entry.getValue()).saveDebugReport(path2); + } + + this.dumpGameRules(path.resolve("gamerules.txt")); +@@ -1639,94 +2042,225 @@ + this.dumpThreads(path.resolve("threads.txt")); + this.dumpServerProperties(path.resolve("server.properties.txt")); + this.dumpNativeModules(path.resolve("modules.txt")); +- } catch (IOException var7) { +- LOGGER.warn("Failed to save debug report", (Throwable)var7); ++ } catch (IOException ioexception) { ++ MinecraftServer.LOGGER.warn("Failed to save debug report", ioexception); + } ++ + } + + private void dumpMiscStats(Path path) throws IOException { +- try (Writer bufferedWriter = Files.newBufferedWriter(path)) { +- bufferedWriter.write(String.format(Locale.ROOT, "pending_tasks: %d\n", this.getPendingTasksCount())); +- bufferedWriter.write(String.format(Locale.ROOT, "average_tick_time: %f\n", this.getCurrentSmoothedTickTime())); +- bufferedWriter.write(String.format(Locale.ROOT, "tick_times: %s\n", Arrays.toString(this.tickTimesNanos))); +- bufferedWriter.write(String.format(Locale.ROOT, "queue: %s\n", Util.backgroundExecutor())); ++ BufferedWriter bufferedwriter = Files.newBufferedWriter(path); ++ ++ try { ++ bufferedwriter.write(String.format(Locale.ROOT, "pending_tasks: %d\n", this.getPendingTasksCount())); ++ bufferedwriter.write(String.format(Locale.ROOT, "average_tick_time: %f\n", this.getCurrentSmoothedTickTime())); ++ bufferedwriter.write(String.format(Locale.ROOT, "tick_times: %s\n", Arrays.toString(this.tickTimesNanos))); ++ bufferedwriter.write(String.format(Locale.ROOT, "queue: %s\n", Util.backgroundExecutor())); ++ } catch (Throwable throwable) { ++ if (bufferedwriter != null) { ++ try { ++ bufferedwriter.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } ++ ++ if (bufferedwriter != null) { ++ bufferedwriter.close(); ++ } ++ + } + + private void dumpGameRules(Path path) throws IOException { +- try (Writer bufferedWriter = Files.newBufferedWriter(path)) { ++ BufferedWriter bufferedwriter = Files.newBufferedWriter(path); ++ ++ try { + final List list = Lists.newArrayList(); +- final GameRules gameRules = this.getGameRules(); ++ final GameRules gamerules = this.getGameRules(); ++ + GameRules.visitGameRuleTypes(new GameRules.GameRuleTypeVisitor() { + @Override + public > void visit(GameRules.Key key, GameRules.Type type) { +- list.add(String.format(Locale.ROOT, "%s=%s\n", key.getId(), gameRules.getRule(key))); ++ list.add(String.format(Locale.ROOT, "%s=%s\n", key.getId(), gamerules.getRule(key))); + } + }); ++ Iterator iterator = list.iterator(); + +- for (String string : list) { +- bufferedWriter.write(string); ++ while (iterator.hasNext()) { ++ String s = (String) iterator.next(); ++ ++ bufferedwriter.write(s); + } ++ } catch (Throwable throwable) { ++ if (bufferedwriter != null) { ++ try { ++ bufferedwriter.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } ++ ++ if (bufferedwriter != null) { ++ bufferedwriter.close(); ++ } ++ + } + + private void dumpClasspath(Path path) throws IOException { +- try (Writer bufferedWriter = Files.newBufferedWriter(path)) { +- String property = System.getProperty("java.class.path"); +- String property1 = System.getProperty("path.separator"); ++ BufferedWriter bufferedwriter = Files.newBufferedWriter(path); + +- for (String string : Splitter.on(property1).split(property)) { +- bufferedWriter.write(string); +- bufferedWriter.write("\n"); ++ try { ++ String s = System.getProperty("java.class.path"); ++ String s1 = System.getProperty("path.separator"); ++ Iterator iterator = Splitter.on(s1).split(s).iterator(); ++ ++ while (iterator.hasNext()) { ++ String s2 = (String) iterator.next(); ++ ++ bufferedwriter.write(s2); ++ bufferedwriter.write("\n"); + } ++ } catch (Throwable throwable) { ++ if (bufferedwriter != null) { ++ try { ++ bufferedwriter.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } ++ ++ if (bufferedwriter != null) { ++ bufferedwriter.close(); ++ } ++ + } + + private void dumpThreads(Path path) throws IOException { +- ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); +- ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(true, true); +- Arrays.sort(threadInfos, Comparator.comparing(ThreadInfo::getThreadName)); ++ ThreadMXBean threadmxbean = ManagementFactory.getThreadMXBean(); ++ ThreadInfo[] athreadinfo = threadmxbean.dumpAllThreads(true, true); + +- try (Writer bufferedWriter = Files.newBufferedWriter(path)) { +- for (ThreadInfo threadInfo : threadInfos) { +- bufferedWriter.write(threadInfo.toString()); +- bufferedWriter.write(10); ++ Arrays.sort(athreadinfo, Comparator.comparing(ThreadInfo::getThreadName)); ++ BufferedWriter bufferedwriter = Files.newBufferedWriter(path); ++ ++ try { ++ ThreadInfo[] athreadinfo1 = athreadinfo; ++ int i = athreadinfo.length; ++ ++ for (int j = 0; j < i; ++j) { ++ ThreadInfo threadinfo = athreadinfo1[j]; ++ ++ bufferedwriter.write(threadinfo.toString()); ++ bufferedwriter.write(10); + } ++ } catch (Throwable throwable) { ++ if (bufferedwriter != null) { ++ try { ++ bufferedwriter.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } ++ ++ if (bufferedwriter != null) { ++ bufferedwriter.close(); ++ } ++ + } + + private void dumpNativeModules(Path path) throws IOException { +- try (Writer bufferedWriter = Files.newBufferedWriter(path)) { +- List list; ++ BufferedWriter bufferedwriter = Files.newBufferedWriter(path); ++ ++ label50: ++ { + try { +- list = Lists.newArrayList(NativeModuleLister.listModules()); +- } catch (Throwable var7) { +- LOGGER.warn("Failed to list native modules", var7); +- return; +- } ++ label51: ++ { ++ ArrayList arraylist; // CraftBukkit - decompile error + +- list.sort(Comparator.comparing(nativeModuleInfo1 -> nativeModuleInfo1.name)); ++ try { ++ arraylist = Lists.newArrayList(NativeModuleLister.listModules()); ++ } catch (Throwable throwable) { ++ MinecraftServer.LOGGER.warn("Failed to list native modules", throwable); ++ break label51; ++ } + +- for (NativeModuleLister.NativeModuleInfo nativeModuleInfo : list) { +- bufferedWriter.write(nativeModuleInfo.toString()); +- bufferedWriter.write(10); ++ arraylist.sort(Comparator.comparing((nativemodulelister_a) -> { ++ return nativemodulelister_a.name; ++ })); ++ Iterator iterator = arraylist.iterator(); ++ ++ while (true) { ++ if (!iterator.hasNext()) { ++ break label50; ++ } ++ ++ NativeModuleLister.NativeModuleInfo nativemodulelister_a = (NativeModuleLister.NativeModuleInfo) iterator.next(); ++ ++ bufferedwriter.write(nativemodulelister_a.toString()); ++ bufferedwriter.write(10); ++ } ++ } ++ } catch (Throwable throwable1) { ++ if (bufferedwriter != null) { ++ try { ++ bufferedwriter.close(); ++ } catch (Throwable throwable2) { ++ throwable1.addSuppressed(throwable2); ++ } ++ } ++ ++ throw throwable1; + } ++ ++ if (bufferedwriter != null) { ++ bufferedwriter.close(); ++ } ++ ++ return; + } ++ ++ if (bufferedwriter != null) { ++ bufferedwriter.close(); ++ } ++ + } + ++ // CraftBukkit start ++ @Override ++ public boolean isSameThread() { ++ return super.isSameThread() || this.isStopped(); // CraftBukkit - MC-142590 ++ } ++ ++ public boolean isDebugging() { ++ return false; ++ } ++ ++ @Deprecated ++ public static MinecraftServer getServer() { ++ return (Bukkit.getServer() instanceof CraftServer) ? ((CraftServer) Bukkit.getServer()).getServer() : null; ++ } ++ // CraftBukkit end ++ + private void startMetricsRecordingTick() { + if (this.willStartRecordingMetrics) { +- this.metricsRecorder = ActiveMetricsRecorder.createStarted( +- new ServerMetricsSamplersProvider(Util.timeSource, this.isDedicatedServer()), +- Util.timeSource, +- Util.ioPool(), +- new MetricsPersister("server"), +- this.onMetricsRecordingStopped, +- path -> { +- this.executeBlocking(() -> this.saveDebugReport(path.resolve("server"))); +- this.onMetricsRecordingFinished.accept(path); +- } +- ); ++ this.metricsRecorder = ActiveMetricsRecorder.createStarted(new ServerMetricsSamplersProvider(Util.timeSource, this.isDedicatedServer()), Util.timeSource, Util.ioPool(), new MetricsPersister("server"), this.onMetricsRecordingStopped, (path) -> { ++ this.executeBlocking(() -> { ++ this.saveDebugReport(path.resolve("server")); ++ }); ++ this.onMetricsRecordingFinished.accept(path); ++ }); + this.willStartRecordingMetrics = false; + } + +@@ -1745,9 +2279,9 @@ + } + + public void startRecordingMetrics(Consumer output, Consumer onMetricsRecordingFinished) { +- this.onMetricsRecordingStopped = profileResults -> { ++ this.onMetricsRecordingStopped = (methodprofilerresults) -> { + this.stopRecordingMetrics(); +- output.accept(profileResults); ++ output.accept(methodprofilerresults); + }; + this.onMetricsRecordingFinished = onMetricsRecordingFinished; + this.willStartRecordingMetrics = true; +@@ -1782,7 +2316,7 @@ + return this.worldData; + } + +- public RegistryAccess.Frozen registryAccess() { ++ public RegistryAccess.Dimension registryAccess() { + return this.registries.compositeAccess(); + } + +@@ -1795,7 +2329,7 @@ + } + + public ServerPlayerGameMode createGameModeForPlayer(ServerPlayer player) { +- return (ServerPlayerGameMode)(this.isDemo() ? new DemoMode(player) : new ServerPlayerGameMode(player)); ++ return (ServerPlayerGameMode) (this.isDemo() ? new DemoMode(player) : new ServerPlayerGameMode(player)); + } + + @Nullable +@@ -1823,9 +2357,10 @@ + if (this.debugCommandProfiler == null) { + return EmptyProfileResults.EMPTY; + } else { +- ProfileResults profileResults = this.debugCommandProfiler.stop(Util.getNanos(), this.tickCount); ++ ProfileResults methodprofilerresults = this.debugCommandProfiler.stop(Util.getNanos(), this.tickCount); ++ + this.debugCommandProfiler = null; +- return profileResults; ++ return methodprofilerresults; + } + } + +@@ -1834,14 +2369,21 @@ + } + + public void logChatMessage(Component content, ChatType.Bound boundChatType, @Nullable String header) { +- String string = boundChatType.decorate(content).getString(); ++ String s1 = boundChatType.decorate(content).getString(); ++ + if (header != null) { +- LOGGER.info("[{}] {}", header, string); ++ MinecraftServer.LOGGER.info("[{}] {}", header, s1); + } else { +- LOGGER.info("{}", string); ++ MinecraftServer.LOGGER.info("{}", s1); + } ++ + } + ++ // CraftBukkit start ++ public final java.util.concurrent.ExecutorService chatExecutor = java.util.concurrent.Executors.newCachedThreadPool( ++ new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon(true).setNameFormat("Async Chat Thread - #%d").build()); ++ // CraftBukkit end ++ + public ChatDecorator getChatDecorator() { + return ChatDecorator.PLAIN; + } +@@ -1850,26 +2392,24 @@ + return true; + } + +- static record ReloadableResources(CloseableResourceManager resourceManager, ReloadableServerResources managers) implements AutoCloseable { +- @Override ++ public static record ReloadableResources(IReloadableResourceManager resourceManager, ReloadableServerResources managers) implements AutoCloseable { ++ + public void close() { + this.resourceManager.close(); + } + } + +- public static record ServerResourcePackInfo(UUID id, String url, String hash, boolean isRequired, @Nullable Component prompt) { +- } ++ private static class TimeProfiler { + +- static class TimeProfiler { + final long startNanos; + final int startTick; + +- TimeProfiler(long startNanos, int startTick) { ++ TimeProfiler(long startNanos, int j) { + this.startNanos = startNanos; +- this.startTick = startTick; ++ this.startTick = j; + } + +- ProfileResults stop(final long endTimeNano, final int endTimeTicks) { ++ ProfileResults stop(final long endTimeNano, final int j) { + return new ProfileResults() { + @Override + public List getTimes(String sectionPath) { +@@ -1898,7 +2438,7 @@ + + @Override + public int getEndTimeTicks() { +- return endTimeTicks; ++ return j; + } + + @Override +@@ -1908,4 +2448,8 @@ + }; + } + } ++ ++ public static record ServerResourcePackInfo(UUID id, String url, String hash, boolean isRequired, @Nullable Component prompt) { ++ ++ } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/PlayerAdvancements.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/PlayerAdvancements.java.patch new file mode 100644 index 0000000000..9bd25106d5 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/PlayerAdvancements.java.patch @@ -0,0 +1,508 @@ +--- a/net/minecraft/server/PlayerAdvancements.java ++++ b/net/minecraft/server/PlayerAdvancements.java +@@ -10,17 +10,19 @@ + import com.mojang.logging.LogUtils; + import com.mojang.serialization.Codec; + import com.mojang.serialization.JsonOps; ++import java.io.BufferedWriter; + import java.io.IOException; +-import java.io.Writer; + import java.nio.charset.StandardCharsets; + import java.nio.file.Files; ++import java.nio.file.LinkOption; + import java.nio.file.Path; + import java.util.HashMap; + import java.util.HashSet; ++import java.util.Iterator; + import java.util.LinkedHashMap; + import java.util.Map; +-import java.util.Set; + import java.util.Map.Entry; ++import java.util.Set; + import java.util.function.BiConsumer; + import javax.annotation.Nullable; + import net.minecraft.FileUtil; +@@ -34,7 +36,6 @@ + import net.minecraft.advancements.CriterionProgress; + import net.minecraft.advancements.CriterionTrigger; + import net.minecraft.advancements.CriterionTriggerInstance; +-import net.minecraft.advancements.DisplayInfo; + import net.minecraft.core.registries.BuiltInRegistries; + import net.minecraft.network.protocol.game.ClientboundSelectAdvancementsTabPacket; + import net.minecraft.network.protocol.game.ClientboundUpdateAdvancementsPacket; +@@ -47,28 +48,30 @@ + import org.slf4j.Logger; + + public class PlayerAdvancements { ++ + private static final Logger LOGGER = LogUtils.getLogger(); +- private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); ++ private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create(); + private final PlayerList playerList; + private final Path playerSavePath; + private AdvancementTree tree; +- private final Map progress = new LinkedHashMap<>(); +- private final Set visible = new HashSet<>(); +- private final Set progressChanged = new HashSet<>(); +- private final Set rootsToUpdate = new HashSet<>(); ++ private final Map progress = new LinkedHashMap(); ++ private final Set visible = new HashSet(); ++ private final Set progressChanged = new HashSet(); ++ private final Set rootsToUpdate = new HashSet(); + private ServerPlayer player; + @Nullable + private AdvancementHolder lastSelectedTab; + private boolean isFirstPacket = true; +- private final Codec codec; ++ private final Codec codec; + + public PlayerAdvancements(DataFixer dataFixer, PlayerList playerList, ServerAdvancementManager manager, Path playerSavePath, ServerPlayer player) { + this.playerList = playerList; + this.playerSavePath = playerSavePath; + this.player = player; + this.tree = manager.tree(); +- int i = 1343; +- this.codec = DataFixTypes.ADVANCEMENTS.wrapCodec(PlayerAdvancements.Data.CODEC, dataFixer, 1343); ++ boolean flag = true; ++ ++ this.codec = DataFixTypes.ADVANCEMENTS.wrapCodec(PlayerAdvancements.a.CODEC, dataFixer, 1343); + this.load(manager); + } + +@@ -77,9 +80,14 @@ + } + + public void stopListening() { +- for (CriterionTrigger criterionTrigger : BuiltInRegistries.TRIGGER_TYPES) { +- criterionTrigger.removePlayerListeners(this); ++ Iterator iterator = BuiltInRegistries.TRIGGER_TYPES.iterator(); ++ ++ while (iterator.hasNext()) { ++ CriterionTrigger criteriontrigger = (CriterionTrigger) iterator.next(); ++ ++ criteriontrigger.removePlayerListeners(this); + } ++ + } + + public void reload(ServerAdvancementManager manager) { +@@ -95,32 +103,57 @@ + } + + private void registerListeners(ServerAdvancementManager manager) { +- for (AdvancementHolder advancementHolder : manager.getAllAdvancements()) { +- this.registerListeners(advancementHolder); ++ Iterator iterator = manager.getAllAdvancements().iterator(); ++ ++ while (iterator.hasNext()) { ++ AdvancementHolder advancementholder = (AdvancementHolder) iterator.next(); ++ ++ this.registerListeners(advancementholder); + } ++ + } + + private void checkForAutomaticTriggers(ServerAdvancementManager manager) { +- for (AdvancementHolder advancementHolder : manager.getAllAdvancements()) { +- Advancement advancement = advancementHolder.value(); ++ Iterator iterator = manager.getAllAdvancements().iterator(); ++ ++ while (iterator.hasNext()) { ++ AdvancementHolder advancementholder = (AdvancementHolder) iterator.next(); ++ Advancement advancement = advancementholder.value(); ++ + if (advancement.criteria().isEmpty()) { +- this.award(advancementHolder, ""); ++ this.award(advancementholder, ""); + advancement.rewards().grant(this.player); + } + } ++ + } + + private void load(ServerAdvancementManager manager) { +- if (Files.isRegularFile(this.playerSavePath)) { +- try (JsonReader jsonReader = new JsonReader(Files.newBufferedReader(this.playerSavePath, StandardCharsets.UTF_8))) { +- jsonReader.setLenient(false); +- JsonElement jsonElement = Streams.parse(jsonReader); +- PlayerAdvancements.Data data = Util.getOrThrow(this.codec.parse(JsonOps.INSTANCE, jsonElement), JsonParseException::new); +- this.applyFrom(manager, data); +- } catch (JsonParseException var7) { +- LOGGER.error("Couldn't parse player advancements in {}", this.playerSavePath, var7); +- } catch (IOException var8) { +- LOGGER.error("Couldn't access player advancements in {}", this.playerSavePath, var8); ++ if (Files.isRegularFile(this.playerSavePath, new LinkOption[0])) { ++ try { ++ JsonReader jsonreader = new JsonReader(Files.newBufferedReader(this.playerSavePath, StandardCharsets.UTF_8)); ++ ++ try { ++ jsonreader.setLenient(false); ++ JsonElement jsonelement = Streams.parse(jsonreader); ++ PlayerAdvancements.a advancementdataplayer_a = (PlayerAdvancements.a) Util.getOrThrow(this.codec.parse(JsonOps.INSTANCE, jsonelement), JsonParseException::new); ++ ++ this.applyFrom(manager, advancementdataplayer_a); ++ } catch (Throwable throwable) { ++ try { ++ jsonreader.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ ++ throw throwable; ++ } ++ ++ jsonreader.close(); ++ } catch (JsonParseException jsonparseexception) { ++ PlayerAdvancements.LOGGER.error("Couldn't parse player advancements in {}", this.playerSavePath, jsonparseexception); ++ } catch (IOException ioexception) { ++ PlayerAdvancements.LOGGER.error("Couldn't access player advancements in {}", this.playerSavePath, ioexception); + } + } + +@@ -129,137 +162,179 @@ + } + + public void save() { +- JsonElement jsonElement = Util.getOrThrow(this.codec.encodeStart(JsonOps.INSTANCE, this.asData()), IllegalStateException::new); ++ JsonElement jsonelement = (JsonElement) Util.getOrThrow(this.codec.encodeStart(JsonOps.INSTANCE, this.asData()), IllegalStateException::new); + + try { + FileUtil.createDirectoriesSafe(this.playerSavePath.getParent()); ++ BufferedWriter bufferedwriter = Files.newBufferedWriter(this.playerSavePath, StandardCharsets.UTF_8); + +- try (Writer bufferedWriter = Files.newBufferedWriter(this.playerSavePath, StandardCharsets.UTF_8)) { +- GSON.toJson(jsonElement, bufferedWriter); ++ try { ++ PlayerAdvancements.GSON.toJson(jsonelement, bufferedwriter); ++ } catch (Throwable throwable) { ++ if (bufferedwriter != null) { ++ try { ++ bufferedwriter.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } +- } catch (IOException var7) { +- LOGGER.error("Couldn't save player advancements to {}", this.playerSavePath, var7); ++ ++ if (bufferedwriter != null) { ++ bufferedwriter.close(); ++ } ++ } catch (IOException ioexception) { ++ PlayerAdvancements.LOGGER.error("Couldn't save player advancements to {}", this.playerSavePath, ioexception); + } ++ + } + +- private void applyFrom(ServerAdvancementManager serverAdvancementManager, PlayerAdvancements.Data data) { +- data.forEach((resourceLocation, advancementProgress) -> { +- AdvancementHolder advancementHolder = serverAdvancementManager.get(resourceLocation); +- if (advancementHolder == null) { +- LOGGER.warn("Ignored advancement '{}' in progress file {} - it doesn't exist anymore?", resourceLocation, this.playerSavePath); ++ private void applyFrom(ServerAdvancementManager advancementdataworld, PlayerAdvancements.a advancementdataplayer_a) { ++ advancementdataplayer_a.forEach((minecraftkey, advancementprogress) -> { ++ AdvancementHolder advancementholder = advancementdataworld.get(minecraftkey); ++ ++ if (advancementholder == null) { ++ if (!minecraftkey.getNamespace().equals("minecraft")) return; // CraftBukkit ++ PlayerAdvancements.LOGGER.warn("Ignored advancement '{}' in progress file {} - it doesn't exist anymore?", minecraftkey, this.playerSavePath); + } else { +- this.startProgress(advancementHolder, advancementProgress); +- this.progressChanged.add(advancementHolder); +- this.markForVisibilityUpdate(advancementHolder); ++ this.startProgress(advancementholder, advancementprogress); ++ this.progressChanged.add(advancementholder); ++ this.markForVisibilityUpdate(advancementholder); + } + }); + } + +- private PlayerAdvancements.Data asData() { +- Map map = new LinkedHashMap<>(); +- this.progress.forEach((advancementHolder, advancementProgress) -> { +- if (advancementProgress.hasProgress()) { +- map.put(advancementHolder.id(), advancementProgress); ++ private PlayerAdvancements.a asData() { ++ Map map = new LinkedHashMap(); ++ ++ this.progress.forEach((advancementholder, advancementprogress) -> { ++ if (advancementprogress.hasProgress()) { ++ map.put(advancementholder.id(), advancementprogress); + } ++ + }); +- return new PlayerAdvancements.Data(map); ++ return new PlayerAdvancements.a(map); + } + +- public boolean award(AdvancementHolder advancementHolder, String string) { ++ public boolean award(AdvancementHolder advancementholder, String s) { + boolean flag = false; +- AdvancementProgress orStartProgress = this.getOrStartProgress(advancementHolder); +- boolean isDone = orStartProgress.isDone(); +- if (orStartProgress.grantProgress(string)) { +- this.unregisterListeners(advancementHolder); +- this.progressChanged.add(advancementHolder); ++ AdvancementProgress advancementprogress = this.getOrStartProgress(advancementholder); ++ boolean flag1 = advancementprogress.isDone(); ++ ++ if (advancementprogress.grantProgress(s)) { ++ this.unregisterListeners(advancementholder); ++ this.progressChanged.add(advancementholder); + flag = true; +- if (!isDone && orStartProgress.isDone()) { +- advancementHolder.value().rewards().grant(this.player); +- advancementHolder.value().display().ifPresent(displayInfo -> { +- if (displayInfo.shouldAnnounceChat() && this.player.level().getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { +- this.playerList.broadcastSystemMessage(displayInfo.getType().createAnnouncement(advancementHolder, this.player), false); ++ if (!flag1 && advancementprogress.isDone()) { ++ this.player.level().getCraftServer().getPluginManager().callEvent(new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancementholder.toBukkit())); // CraftBukkit ++ advancementholder.value().rewards().grant(this.player); ++ advancementholder.value().display().ifPresent((advancementdisplay) -> { ++ if (advancementdisplay.shouldAnnounceChat() && this.player.level().getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { ++ this.playerList.broadcastSystemMessage(advancementdisplay.getType().createAnnouncement(advancementholder, this.player), false); + } ++ + }); + } + } + +- if (!isDone && orStartProgress.isDone()) { +- this.markForVisibilityUpdate(advancementHolder); ++ if (!flag1 && advancementprogress.isDone()) { ++ this.markForVisibilityUpdate(advancementholder); + } + + return flag; + } + +- public boolean revoke(AdvancementHolder advancementHolder, String string) { ++ public boolean revoke(AdvancementHolder advancementholder, String s) { + boolean flag = false; +- AdvancementProgress orStartProgress = this.getOrStartProgress(advancementHolder); +- boolean isDone = orStartProgress.isDone(); +- if (orStartProgress.revokeProgress(string)) { +- this.registerListeners(advancementHolder); +- this.progressChanged.add(advancementHolder); ++ AdvancementProgress advancementprogress = this.getOrStartProgress(advancementholder); ++ boolean flag1 = advancementprogress.isDone(); ++ ++ if (advancementprogress.revokeProgress(s)) { ++ this.registerListeners(advancementholder); ++ this.progressChanged.add(advancementholder); + flag = true; + } + +- if (isDone && !orStartProgress.isDone()) { +- this.markForVisibilityUpdate(advancementHolder); ++ if (flag1 && !advancementprogress.isDone()) { ++ this.markForVisibilityUpdate(advancementholder); + } + + return flag; + } + +- private void markForVisibilityUpdate(AdvancementHolder advancementHolder) { +- AdvancementNode advancementNode = this.tree.get(advancementHolder); +- if (advancementNode != null) { +- this.rootsToUpdate.add(advancementNode.root()); ++ private void markForVisibilityUpdate(AdvancementHolder advancementholder) { ++ AdvancementNode advancementnode = this.tree.get(advancementholder); ++ ++ if (advancementnode != null) { ++ this.rootsToUpdate.add(advancementnode.root()); + } ++ + } + +- private void registerListeners(AdvancementHolder advancementHolder) { +- AdvancementProgress orStartProgress = this.getOrStartProgress(advancementHolder); +- if (!orStartProgress.isDone()) { +- for (Entry> entry : advancementHolder.value().criteria().entrySet()) { +- CriterionProgress criterion = orStartProgress.getCriterion(entry.getKey()); +- if (criterion != null && !criterion.isDone()) { +- this.registerListener(advancementHolder, entry.getKey(), entry.getValue()); ++ private void registerListeners(AdvancementHolder advancementholder) { ++ AdvancementProgress advancementprogress = this.getOrStartProgress(advancementholder); ++ ++ if (!advancementprogress.isDone()) { ++ Iterator iterator = advancementholder.value().criteria().entrySet().iterator(); ++ ++ while (iterator.hasNext()) { ++ Entry> entry = (Entry) iterator.next(); ++ CriterionProgress criterionprogress = advancementprogress.getCriterion((String) entry.getKey()); ++ ++ if (criterionprogress != null && !criterionprogress.isDone()) { ++ this.registerListener(advancementholder, (String) entry.getKey(), (Criterion) entry.getValue()); + } + } ++ + } + } + +- private void registerListener(AdvancementHolder advancementHolder, String string, Criterion criterion) { +- criterion.trigger().addPlayerListener(this, new CriterionTrigger.Listener<>(criterion.triggerInstance(), advancementHolder, string)); ++ private void registerListener(AdvancementHolder advancementholder, String s, Criterion criterion) { ++ criterion.trigger().addPlayerListener(this, new CriterionTrigger.Listener<>(criterion.triggerInstance(), advancementholder, s)); + } + +- private void unregisterListeners(AdvancementHolder advancementHolder) { +- AdvancementProgress orStartProgress = this.getOrStartProgress(advancementHolder); ++ private void unregisterListeners(AdvancementHolder advancementholder) { ++ AdvancementProgress advancementprogress = this.getOrStartProgress(advancementholder); ++ Iterator iterator = advancementholder.value().criteria().entrySet().iterator(); + +- for (Entry> entry : advancementHolder.value().criteria().entrySet()) { +- CriterionProgress criterion = orStartProgress.getCriterion(entry.getKey()); +- if (criterion != null && (criterion.isDone() || orStartProgress.isDone())) { +- this.removeListener(advancementHolder, entry.getKey(), entry.getValue()); ++ while (iterator.hasNext()) { ++ Entry> entry = (Entry) iterator.next(); ++ CriterionProgress criterionprogress = advancementprogress.getCriterion((String) entry.getKey()); ++ ++ if (criterionprogress != null && (criterionprogress.isDone() || advancementprogress.isDone())) { ++ this.removeListener(advancementholder, (String) entry.getKey(), (Criterion) entry.getValue()); + } + } ++ + } + +- private void removeListener(AdvancementHolder advancementHolder, String string, Criterion criterion) { +- criterion.trigger().removePlayerListener(this, new CriterionTrigger.Listener<>(criterion.triggerInstance(), advancementHolder, string)); ++ private void removeListener(AdvancementHolder advancementholder, String s, Criterion criterion) { ++ criterion.trigger().removePlayerListener(this, new CriterionTrigger.Listener<>(criterion.triggerInstance(), advancementholder, s)); + } + + public void flushDirty(ServerPlayer serverPlayer) { + if (this.isFirstPacket || !this.rootsToUpdate.isEmpty() || !this.progressChanged.isEmpty()) { +- Map map = new HashMap<>(); +- Set set = new HashSet<>(); +- Set set1 = new HashSet<>(); ++ Map map = new HashMap(); ++ Set set = new HashSet(); ++ Set set1 = new HashSet(); ++ Iterator iterator = this.rootsToUpdate.iterator(); + +- for (AdvancementNode advancementNode : this.rootsToUpdate) { +- this.updateTreeVisibility(advancementNode, set, set1); ++ while (iterator.hasNext()) { ++ AdvancementNode advancementnode = (AdvancementNode) iterator.next(); ++ ++ this.updateTreeVisibility(advancementnode, set, set1); + } + + this.rootsToUpdate.clear(); ++ iterator = this.progressChanged.iterator(); + +- for (AdvancementHolder advancementHolder : this.progressChanged) { +- if (this.visible.contains(advancementHolder)) { +- map.put(advancementHolder.id(), this.progress.get(advancementHolder)); ++ while (iterator.hasNext()) { ++ AdvancementHolder advancementholder = (AdvancementHolder) iterator.next(); ++ ++ if (this.visible.contains(advancementholder)) { ++ map.put(advancementholder.id(), (AdvancementProgress) this.progress.get(advancementholder)); + } + } + +@@ -272,58 +347,65 @@ + this.isFirstPacket = false; + } + +- public void setSelectedTab(@Nullable AdvancementHolder advancementHolder) { +- AdvancementHolder advancementHolder1 = this.lastSelectedTab; +- if (advancementHolder != null && advancementHolder.value().isRoot() && advancementHolder.value().display().isPresent()) { +- this.lastSelectedTab = advancementHolder; ++ public void setSelectedTab(@Nullable AdvancementHolder advancementholder) { ++ AdvancementHolder advancementholder1 = this.lastSelectedTab; ++ ++ if (advancementholder != null && advancementholder.value().isRoot() && advancementholder.value().display().isPresent()) { ++ this.lastSelectedTab = advancementholder; + } else { + this.lastSelectedTab = null; + } + +- if (advancementHolder1 != this.lastSelectedTab) { ++ if (advancementholder1 != this.lastSelectedTab) { + this.player.connection.send(new ClientboundSelectAdvancementsTabPacket(this.lastSelectedTab == null ? null : this.lastSelectedTab.id())); + } ++ + } + +- public AdvancementProgress getOrStartProgress(AdvancementHolder advancementHolder) { +- AdvancementProgress advancementProgress = this.progress.get(advancementHolder); +- if (advancementProgress == null) { +- advancementProgress = new AdvancementProgress(); +- this.startProgress(advancementHolder, advancementProgress); ++ public AdvancementProgress getOrStartProgress(AdvancementHolder advancementholder) { ++ AdvancementProgress advancementprogress = (AdvancementProgress) this.progress.get(advancementholder); ++ ++ if (advancementprogress == null) { ++ advancementprogress = new AdvancementProgress(); ++ this.startProgress(advancementholder, advancementprogress); + } + +- return advancementProgress; ++ return advancementprogress; + } + +- private void startProgress(AdvancementHolder advancementHolder, AdvancementProgress advancementProgress) { +- advancementProgress.update(advancementHolder.value().requirements()); +- this.progress.put(advancementHolder, advancementProgress); ++ private void startProgress(AdvancementHolder advancementholder, AdvancementProgress advancementprogress) { ++ advancementprogress.update(advancementholder.value().requirements()); ++ this.progress.put(advancementholder, advancementprogress); + } + +- private void updateTreeVisibility(AdvancementNode advancementNode, Set set, Set set1) { +- AdvancementVisibilityEvaluator.evaluateVisibility( +- advancementNode, advancementNode1 -> this.getOrStartProgress(advancementNode1.holder()).isDone(), (advancementNode1, flag) -> { +- AdvancementHolder advancementHolder = advancementNode1.holder(); +- if (flag) { +- if (this.visible.add(advancementHolder)) { +- set.add(advancementHolder); +- if (this.progress.containsKey(advancementHolder)) { +- this.progressChanged.add(advancementHolder); +- } ++ private void updateTreeVisibility(AdvancementNode advancementnode, Set set, Set set1) { ++ AdvancementVisibilityEvaluator.evaluateVisibility(advancementnode, (advancementnode1) -> { ++ return this.getOrStartProgress(advancementnode1.holder()).isDone(); ++ }, (advancementnode1, flag) -> { ++ AdvancementHolder advancementholder = advancementnode1.holder(); ++ ++ if (flag) { ++ if (this.visible.add(advancementholder)) { ++ set.add(advancementholder); ++ if (this.progress.containsKey(advancementholder)) { ++ this.progressChanged.add(advancementholder); + } +- } else if (this.visible.remove(advancementHolder)) { +- set1.add(advancementHolder.id()); + } ++ } else if (this.visible.remove(advancementholder)) { ++ set1.add(advancementholder.id()); + } +- ); ++ ++ }); + } + +- static record Data(Map map) { +- public static final Codec CODEC = Codec.unboundedMap(ResourceLocation.CODEC, AdvancementProgress.CODEC) +- .xmap(PlayerAdvancements.Data::new, PlayerAdvancements.Data::map); ++ private static record a(Map map) { + +- public void forEach(BiConsumer biConsumer) { +- this.map.entrySet().stream().sorted(Entry.comparingByValue()).forEach(entry -> biConsumer.accept(entry.getKey(), entry.getValue())); ++ public static final Codec CODEC = Codec.unboundedMap(ResourceLocation.CODEC, AdvancementProgress.CODEC).xmap(PlayerAdvancements.a::new, PlayerAdvancements.a::map); ++ ++ public void forEach(BiConsumer biconsumer) { ++ this.map.entrySet().stream().sorted(Entry.comparingByValue()).forEach((entry) -> { ++ biconsumer.accept((ResourceLocation) entry.getKey(), (AdvancementProgress) entry.getValue()); ++ }); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/ServerAdvancementManager.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/ServerAdvancementManager.java.patch new file mode 100644 index 0000000000..785be48a0f --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/ServerAdvancementManager.java.patch @@ -0,0 +1,122 @@ +--- a/net/minecraft/server/ServerAdvancementManager.java ++++ b/net/minecraft/server/ServerAdvancementManager.java +@@ -1,8 +1,9 @@ ++// mc-dev import + package net.minecraft.server; + + import com.google.common.collect.ImmutableMap; +-import com.google.common.collect.Multimap; + import com.google.common.collect.ImmutableMap.Builder; ++import com.google.common.collect.Multimap; + import com.google.gson.Gson; + import com.google.gson.GsonBuilder; + import com.google.gson.JsonElement; +@@ -10,8 +11,8 @@ + import com.mojang.logging.LogUtils; + import com.mojang.serialization.JsonOps; + import java.util.Collection; ++import java.util.Iterator; + import java.util.Map; +-import java.util.Map.Entry; + import java.util.stream.Collectors; + import javax.annotation.Nullable; + import net.minecraft.Util; +@@ -29,59 +30,70 @@ + import org.slf4j.Logger; + + public class ServerAdvancementManager extends SimpleJsonResourceReloadListener { ++ + private static final Logger LOGGER = LogUtils.getLogger(); +- private static final Gson GSON = new GsonBuilder().create(); +- private Map advancements = Map.of(); ++ public static final Gson GSON = (new GsonBuilder()).create(); ++ public Map advancements = Map.of(); + private AdvancementTree tree = new AdvancementTree(); + private final LootDataManager lootData; + + public ServerAdvancementManager(LootDataManager lootData) { +- super(GSON, "advancements"); ++ super(ServerAdvancementManager.GSON, "advancements"); + this.lootData = lootData; + } + +- @Override + protected void apply(Map object, ResourceManager resourceManager, ProfilerFiller profiler) { + Builder builder = ImmutableMap.builder(); +- object.forEach((resourceLocation, jsonElement) -> { ++ ++ object.forEach((minecraftkey, jsonelement) -> { + try { +- Advancement advancement = Util.getOrThrow(Advancement.CODEC.parse(JsonOps.INSTANCE, jsonElement), JsonParseException::new); +- this.validate(resourceLocation, advancement); +- builder.put(resourceLocation, new AdvancementHolder(resourceLocation, advancement)); +- } catch (Exception var5x) { +- LOGGER.error("Parsing error loading custom advancement {}: {}", resourceLocation, var5x.getMessage()); ++ Advancement advancement = (Advancement) Util.getOrThrow(Advancement.CODEC.parse(JsonOps.INSTANCE, jsonelement), JsonParseException::new); ++ ++ this.validate(minecraftkey, advancement); ++ builder.put(minecraftkey, new AdvancementHolder(minecraftkey, advancement)); ++ } catch (Exception exception) { ++ ServerAdvancementManager.LOGGER.error("Parsing error loading custom advancement {}: {}", minecraftkey, exception.getMessage()); + } ++ + }); + this.advancements = builder.buildOrThrow(); +- AdvancementTree advancementTree = new AdvancementTree(); +- advancementTree.addAll(this.advancements.values()); ++ AdvancementTree advancementtree = new AdvancementTree(); + +- for (AdvancementNode advancementNode : advancementTree.roots()) { +- if (advancementNode.holder().value().display().isPresent()) { +- TreeNodePosition.run(advancementNode); ++ advancementtree.addAll(this.advancements.values()); ++ Iterator iterator = advancementtree.roots().iterator(); ++ ++ while (iterator.hasNext()) { ++ AdvancementNode advancementnode = (AdvancementNode) iterator.next(); ++ ++ if (advancementnode.holder().value().display().isPresent()) { ++ TreeNodePosition.run(advancementnode); + } + } + +- this.tree = advancementTree; ++ this.tree = advancementtree; + } + +- private void validate(ResourceLocation resourceLocation, Advancement advancement) { +- ProblemReporter.Collector collector = new ProblemReporter.Collector(); +- advancement.validate(collector, this.lootData); +- Multimap multimap = collector.get(); ++ private void validate(ResourceLocation minecraftkey, Advancement advancement) { ++ ProblemReporter.a problemreporter_a = new ProblemReporter.a(); ++ ++ advancement.validate(problemreporter_a, this.lootData); ++ Multimap multimap = problemreporter_a.get(); ++ + if (!multimap.isEmpty()) { +- String string = multimap.asMap() +- .entrySet() +- .stream() +- .map(entry -> " at " + entry.getKey() + ": " + String.join("; ", entry.getValue())) +- .collect(Collectors.joining("\n")); +- LOGGER.warn("Found validation problems in advancement {}: \n{}", resourceLocation, string); ++ String s = (String) multimap.asMap().entrySet().stream().map((entry) -> { ++ String s1 = (String) entry.getKey(); ++ ++ return " at " + s1 + ": " + String.join("; ", (Iterable) entry.getValue()); ++ }).collect(Collectors.joining("\n")); ++ ++ ServerAdvancementManager.LOGGER.warn("Found validation problems in advancement {}: \n{}", minecraftkey, s); + } ++ + } + + @Nullable +- public AdvancementHolder get(ResourceLocation resourceLocation) { +- return this.advancements.get(resourceLocation); ++ public AdvancementHolder get(ResourceLocation minecraftkey) { ++ return (AdvancementHolder) this.advancements.get(minecraftkey); + } + + public AdvancementTree tree() { diff --git a/patch-remap/mache-vineflower/net/minecraft/server/ServerFunctionManager.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/ServerFunctionManager.java.patch new file mode 100644 index 0000000000..ee6e86f137 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/ServerFunctionManager.java.patch @@ -0,0 +1,117 @@ +--- a/net/minecraft/server/ServerFunctionManager.java ++++ b/net/minecraft/server/ServerFunctionManager.java +@@ -4,20 +4,23 @@ + import com.mojang.brigadier.CommandDispatcher; + import com.mojang.logging.LogUtils; + import java.util.Collection; ++import java.util.Iterator; + import java.util.List; ++import java.util.Objects; + import java.util.Optional; + import net.minecraft.commands.CommandResultCallback; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.FunctionInstantiationException; + import net.minecraft.commands.execution.ExecutionContext; + import net.minecraft.commands.functions.CommandFunction; + import net.minecraft.commands.functions.InstantiatedFunction; ++import net.minecraft.nbt.CompoundTag; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.util.profiling.ProfilerFiller; + import org.slf4j.Logger; + + public class ServerFunctionManager { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final ResourceLocation TICK_FUNCTION_TAG = new ResourceLocation("tick"); + private static final ResourceLocation LOAD_FUNCTION_TAG = new ResourceLocation("load"); +@@ -33,49 +36,59 @@ + } + + public CommandDispatcher getDispatcher() { +- return this.server.getCommands().getDispatcher(); ++ return this.server.vanillaCommandDispatcher.getDispatcher(); // CraftBukkit + } + + public void tick() { + if (this.server.tickRateManager().runsNormally()) { + if (this.postReload) { + this.postReload = false; +- Collection> tag = this.library.getTag(LOAD_FUNCTION_TAG); +- this.executeTagFunctions(tag, LOAD_FUNCTION_TAG); ++ Collection> collection = this.library.getTag(ServerFunctionManager.LOAD_FUNCTION_TAG); ++ ++ this.executeTagFunctions(collection, ServerFunctionManager.LOAD_FUNCTION_TAG); + } + +- this.executeTagFunctions(this.ticking, TICK_FUNCTION_TAG); ++ this.executeTagFunctions(this.ticking, ServerFunctionManager.TICK_FUNCTION_TAG); + } + } + + private void executeTagFunctions(Collection> functionObjects, ResourceLocation identifier) { +- this.server.getProfiler().push(identifier::toString); ++ ProfilerFiller gameprofilerfiller = this.server.getProfiler(); + +- for (CommandFunction commandFunction : functionObjects) { +- this.execute(commandFunction, this.getGameLoopSender()); ++ Objects.requireNonNull(identifier); ++ gameprofilerfiller.push(identifier::toString); ++ Iterator iterator = functionObjects.iterator(); ++ ++ while (iterator.hasNext()) { ++ CommandFunction commandfunction = (CommandFunction) iterator.next(); ++ ++ this.execute(commandfunction, this.getGameLoopSender()); + } + + this.server.getProfiler().pop(); + } + +- public void execute(CommandFunction commandFunction, CommandSourceStack commandSourceStack) { +- ProfilerFiller profiler = this.server.getProfiler(); +- profiler.push(() -> "function " + commandFunction.id()); ++ public void execute(CommandFunction commandfunction, CommandSourceStack commandlistenerwrapper) { ++ ProfilerFiller gameprofilerfiller = this.server.getProfiler(); + ++ gameprofilerfiller.push(() -> { ++ return "function " + commandfunction.id(); ++ }); ++ + try { +- InstantiatedFunction instantiatedFunction = commandFunction.instantiate(null, this.getDispatcher(), commandSourceStack); +- Commands.executeCommandInContext( +- commandSourceStack, +- executionContext -> ExecutionContext.queueInitialFunctionCall( +- executionContext, instantiatedFunction, commandSourceStack, CommandResultCallback.EMPTY +- ) +- ); +- } catch (FunctionInstantiationException var9) { +- } catch (Exception var10) { +- LOGGER.warn("Failed to execute function {}", commandFunction.id(), var10); ++ InstantiatedFunction instantiatedfunction = commandfunction.instantiate((CompoundTag) null, this.getDispatcher(), commandlistenerwrapper); ++ ++ net.minecraft.commands.Commands.executeCommandInContext(commandlistenerwrapper, (executioncontext) -> { ++ ExecutionContext.queueInitialFunctionCall(executioncontext, instantiatedfunction, commandlistenerwrapper, CommandResultCallback.EMPTY); ++ }); ++ } catch (FunctionInstantiationException functioninstantiationexception) { ++ ; ++ } catch (Exception exception) { ++ ServerFunctionManager.LOGGER.warn("Failed to execute function {}", commandfunction.id(), exception); + } finally { +- profiler.pop(); ++ gameprofilerfiller.pop(); + } ++ + } + + public void replaceLibrary(ServerFunctionLibrary reloader) { +@@ -84,7 +97,7 @@ + } + + private void postReload(ServerFunctionLibrary reloader) { +- this.ticking = ImmutableList.copyOf(reloader.getTag(TICK_FUNCTION_TAG)); ++ this.ticking = ImmutableList.copyOf(reloader.getTag(ServerFunctionManager.TICK_FUNCTION_TAG)); + this.postReload = true; + } + diff --git a/patch-remap/mache-vineflower/net/minecraft/server/ServerScoreboard.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/ServerScoreboard.java.patch new file mode 100644 index 0000000000..5c8085db82 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/ServerScoreboard.java.patch @@ -0,0 +1,340 @@ +--- a/net/minecraft/server/ServerScoreboard.java ++++ b/net/minecraft/server/ServerScoreboard.java +@@ -2,7 +2,9 @@ + + import com.google.common.collect.Lists; + import com.google.common.collect.Sets; ++import java.util.Iterator; + import java.util.List; ++import java.util.Objects; + import java.util.Set; + import javax.annotation.Nullable; + import net.minecraft.nbt.CompoundTag; +@@ -25,6 +27,7 @@ + import net.minecraft.world.scores.ScoreboardSaveData; + + public class ServerScoreboard extends Scoreboard { ++ + private final MinecraftServer server; + private final Set trackedObjectives = Sets.newHashSet(); + private final List dirtyListeners = Lists.newArrayList(); +@@ -34,59 +37,56 @@ + } + + @Override +- protected void onScoreChanged(ScoreHolder scoreHolder, Objective objective, Score score) { +- super.onScoreChanged(scoreHolder, objective, score); +- if (this.trackedObjectives.contains(objective)) { +- this.server +- .getPlayerList() +- .broadcastAll( +- new ClientboundSetScorePacket(scoreHolder.getScoreboardName(), objective.getName(), score.value(), score.display(), score.numberFormat()) +- ); ++ protected void onScoreChanged(ScoreHolder scoreholder, Objective scoreboardobjective, Score scoreboardscore) { ++ super.onScoreChanged(scoreholder, scoreboardobjective, scoreboardscore); ++ if (this.trackedObjectives.contains(scoreboardobjective)) { ++ this.broadcastAll(new ClientboundSetScorePacket(scoreholder.getScoreboardName(), scoreboardobjective.getName(), scoreboardscore.value(), scoreboardscore.display(), scoreboardscore.numberFormat())); // CraftBukkit + } + + this.setDirty(); + } + + @Override +- protected void onScoreLockChanged(ScoreHolder scoreHolder, Objective objective) { +- super.onScoreLockChanged(scoreHolder, objective); ++ protected void onScoreLockChanged(ScoreHolder scoreholder, Objective scoreboardobjective) { ++ super.onScoreLockChanged(scoreholder, scoreboardobjective); + this.setDirty(); + } + + @Override +- public void onPlayerRemoved(ScoreHolder scoreHolder) { +- super.onPlayerRemoved(scoreHolder); +- this.server.getPlayerList().broadcastAll(new ClientboundResetScorePacket(scoreHolder.getScoreboardName(), null)); ++ public void onPlayerRemoved(ScoreHolder scoreholder) { ++ super.onPlayerRemoved(scoreholder); ++ this.broadcastAll(new ClientboundResetScorePacket(scoreholder.getScoreboardName(), (String) null)); // CraftBukkit + this.setDirty(); + } + + @Override +- public void onPlayerScoreRemoved(ScoreHolder scoreHolder, Objective objective) { +- super.onPlayerScoreRemoved(scoreHolder, objective); +- if (this.trackedObjectives.contains(objective)) { +- this.server.getPlayerList().broadcastAll(new ClientboundResetScorePacket(scoreHolder.getScoreboardName(), objective.getName())); ++ public void onPlayerScoreRemoved(ScoreHolder scoreholder, Objective scoreboardobjective) { ++ super.onPlayerScoreRemoved(scoreholder, scoreboardobjective); ++ if (this.trackedObjectives.contains(scoreboardobjective)) { ++ this.broadcastAll(new ClientboundResetScorePacket(scoreholder.getScoreboardName(), scoreboardobjective.getName())); // CraftBukkit + } + + this.setDirty(); + } + + @Override +- public void setDisplayObjective(DisplaySlot displaySlot, @Nullable Objective objective) { +- Objective displayObjective = this.getDisplayObjective(displaySlot); +- super.setDisplayObjective(displaySlot, objective); +- if (displayObjective != objective && displayObjective != null) { +- if (this.getObjectiveDisplaySlotCount(displayObjective) > 0) { +- this.server.getPlayerList().broadcastAll(new ClientboundSetDisplayObjectivePacket(displaySlot, objective)); ++ public void setDisplayObjective(DisplaySlot displayslot, @Nullable Objective scoreboardobjective) { ++ Objective scoreboardobjective1 = this.getDisplayObjective(displayslot); ++ ++ super.setDisplayObjective(displayslot, scoreboardobjective); ++ if (scoreboardobjective1 != scoreboardobjective && scoreboardobjective1 != null) { ++ if (this.getObjectiveDisplaySlotCount(scoreboardobjective1) > 0) { ++ this.broadcastAll(new ClientboundSetDisplayObjectivePacket(displayslot, scoreboardobjective)); // CraftBukkit + } else { +- this.stopTrackingObjective(displayObjective); ++ this.stopTrackingObjective(scoreboardobjective1); + } + } + +- if (objective != null) { +- if (this.trackedObjectives.contains(objective)) { +- this.server.getPlayerList().broadcastAll(new ClientboundSetDisplayObjectivePacket(displaySlot, objective)); ++ if (scoreboardobjective != null) { ++ if (this.trackedObjectives.contains(scoreboardobjective)) { ++ this.broadcastAll(new ClientboundSetDisplayObjectivePacket(displayslot, scoreboardobjective)); // CraftBukkit + } else { +- this.startTrackingObjective(objective); ++ this.startTrackingObjective(scoreboardobjective); + } + } + +@@ -96,9 +96,7 @@ + @Override + public boolean addPlayerToTeam(String playerName, PlayerTeam team) { + if (super.addPlayerToTeam(playerName, team)) { +- this.server +- .getPlayerList() +- .broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(team, playerName, ClientboundSetPlayerTeamPacket.Action.ADD)); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(team, playerName, ClientboundSetPlayerTeamPacket.a.ADD)); // CraftBukkit + this.setDirty(); + return true; + } else { +@@ -109,9 +107,7 @@ + @Override + public void removePlayerFromTeam(String username, PlayerTeam playerTeam) { + super.removePlayerFromTeam(username, playerTeam); +- this.server +- .getPlayerList() +- .broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(playerTeam, username, ClientboundSetPlayerTeamPacket.Action.REMOVE)); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(playerTeam, username, ClientboundSetPlayerTeamPacket.a.REMOVE)); // CraftBukkit + this.setDirty(); + } + +@@ -125,7 +121,7 @@ + public void onObjectiveChanged(Objective objective) { + super.onObjectiveChanged(objective); + if (this.trackedObjectives.contains(objective)) { +- this.server.getPlayerList().broadcastAll(new ClientboundSetObjectivePacket(objective, 2)); ++ this.broadcastAll(new ClientboundSetObjectivePacket(objective, 2)); // CraftBukkit + } + + this.setDirty(); +@@ -144,21 +140,21 @@ + @Override + public void onTeamAdded(PlayerTeam playerTeam) { + super.onTeamAdded(playerTeam); +- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, true)); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, true)); // CraftBukkit + this.setDirty(); + } + + @Override + public void onTeamChanged(PlayerTeam playerTeam) { + super.onTeamChanged(playerTeam); +- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, false)); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, false)); // CraftBukkit + this.setDirty(); + } + + @Override + public void onTeamRemoved(PlayerTeam playerTeam) { + super.onTeamRemoved(playerTeam); +- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createRemovePacket(playerTeam)); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createRemovePacket(playerTeam)); // CraftBukkit + this.setDirty(); + } + +@@ -167,42 +163,55 @@ + } + + protected void setDirty() { +- for (Runnable runnable : this.dirtyListeners) { ++ Iterator iterator = this.dirtyListeners.iterator(); ++ ++ while (iterator.hasNext()) { ++ Runnable runnable = (Runnable) iterator.next(); ++ + runnable.run(); + } ++ + } + + public List> getStartTrackingPackets(Objective objective) { + List> list = Lists.newArrayList(); ++ + list.add(new ClientboundSetObjectivePacket(objective, 0)); ++ DisplaySlot[] adisplayslot = DisplaySlot.values(); ++ int i = adisplayslot.length; + +- for (DisplaySlot displaySlot : DisplaySlot.values()) { +- if (this.getDisplayObjective(displaySlot) == objective) { +- list.add(new ClientboundSetDisplayObjectivePacket(displaySlot, objective)); ++ for (int j = 0; j < i; ++j) { ++ DisplaySlot displayslot = adisplayslot[j]; ++ ++ if (this.getDisplayObjective(displayslot) == objective) { ++ list.add(new ClientboundSetDisplayObjectivePacket(displayslot, objective)); + } + } + +- for (PlayerScoreEntry playerScoreEntry : this.listPlayerScores(objective)) { +- list.add( +- new ClientboundSetScorePacket( +- playerScoreEntry.owner(), +- objective.getName(), +- playerScoreEntry.value(), +- playerScoreEntry.display(), +- playerScoreEntry.numberFormatOverride() +- ) +- ); ++ Iterator iterator = this.listPlayerScores(objective).iterator(); ++ ++ while (iterator.hasNext()) { ++ PlayerScoreEntry playerscoreentry = (PlayerScoreEntry) iterator.next(); ++ ++ list.add(new ClientboundSetScorePacket(playerscoreentry.owner(), objective.getName(), playerscoreentry.value(), playerscoreentry.display(), playerscoreentry.numberFormatOverride())); + } + + return list; + } + + public void startTrackingObjective(Objective objective) { +- List> startTrackingPackets = this.getStartTrackingPackets(objective); ++ List> list = this.getStartTrackingPackets(objective); ++ Iterator iterator = this.server.getPlayerList().getPlayers().iterator(); + +- for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) { +- for (Packet packet : startTrackingPackets) { +- serverPlayer.connection.send(packet); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board ++ Iterator iterator1 = list.iterator(); ++ ++ while (iterator1.hasNext()) { ++ Packet packet = (Packet) iterator1.next(); ++ ++ entityplayer.connection.send(packet); + } + } + +@@ -211,11 +220,16 @@ + + public List> getStopTrackingPackets(Objective objective) { + List> list = Lists.newArrayList(); ++ + list.add(new ClientboundSetObjectivePacket(objective, 1)); ++ DisplaySlot[] adisplayslot = DisplaySlot.values(); ++ int i = adisplayslot.length; + +- for (DisplaySlot displaySlot : DisplaySlot.values()) { +- if (this.getDisplayObjective(displaySlot) == objective) { +- list.add(new ClientboundSetDisplayObjectivePacket(displaySlot, objective)); ++ for (int j = 0; j < i; ++j) { ++ DisplaySlot displayslot = adisplayslot[j]; ++ ++ if (this.getDisplayObjective(displayslot) == objective) { ++ list.add(new ClientboundSetDisplayObjectivePacket(displayslot, objective)); + } + } + +@@ -223,11 +237,18 @@ + } + + public void stopTrackingObjective(Objective objective) { +- List> stopTrackingPackets = this.getStopTrackingPackets(objective); ++ List> list = this.getStopTrackingPackets(objective); ++ Iterator iterator = this.server.getPlayerList().getPlayers().iterator(); + +- for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) { +- for (Packet packet : stopTrackingPackets) { +- serverPlayer.connection.send(packet); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board ++ Iterator iterator1 = list.iterator(); ++ ++ while (iterator1.hasNext()) { ++ Packet packet = (Packet) iterator1.next(); ++ ++ entityplayer.connection.send(packet); + } + } + +@@ -236,32 +257,50 @@ + + public int getObjectiveDisplaySlotCount(Objective objective) { + int i = 0; ++ DisplaySlot[] adisplayslot = DisplaySlot.values(); ++ int j = adisplayslot.length; + +- for (DisplaySlot displaySlot : DisplaySlot.values()) { +- if (this.getDisplayObjective(displaySlot) == objective) { +- i++; ++ for (int k = 0; k < j; ++k) { ++ DisplaySlot displayslot = adisplayslot[k]; ++ ++ if (this.getDisplayObjective(displayslot) == objective) { ++ ++i; + } + } + + return i; + } + +- public SavedData.Factory dataFactory() { +- return new SavedData.Factory<>(this::createData, this::createData, DataFixTypes.SAVED_DATA_SCOREBOARD); ++ public SavedData.a dataFactory() { ++ return new SavedData.a<>(this::createData, this::createData, DataFixTypes.SAVED_DATA_SCOREBOARD); + } + + private ScoreboardSaveData createData() { +- ScoreboardSaveData scoreboardSaveData = new ScoreboardSaveData(this); +- this.addDirtyListener(scoreboardSaveData::setDirty); +- return scoreboardSaveData; ++ ScoreboardSaveData persistentscoreboard = new ScoreboardSaveData(this); ++ ++ Objects.requireNonNull(persistentscoreboard); ++ this.addDirtyListener(persistentscoreboard::setDirty); ++ return persistentscoreboard; + } + + private ScoreboardSaveData createData(CompoundTag tag) { + return this.createData().load(tag); + } + +- public static enum Method { +- CHANGE, +- REMOVE; ++ // CraftBukkit start - Send to players ++ private void broadcastAll(Packet packet) { ++ for (ServerPlayer entityplayer : (List) this.server.getPlayerList().players) { ++ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() == this) { ++ entityplayer.connection.send(packet); ++ } ++ } + } ++ // CraftBukkit end ++ ++ public static enum Action { ++ ++ CHANGE, REMOVE; ++ ++ private Action() {} ++ } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/ServerTickRateManager.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/ServerTickRateManager.java.patch new file mode 100644 index 0000000000..4cbcec6fa8 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/ServerTickRateManager.java.patch @@ -0,0 +1,108 @@ +--- a/net/minecraft/server/ServerTickRateManager.java ++++ b/net/minecraft/server/ServerTickRateManager.java +@@ -8,6 +8,7 @@ + import net.minecraft.world.TickRateManager; + + public class ServerTickRateManager extends TickRateManager { ++ + private long remainingSprintTicks = 0L; + private long sprintTickStartTime = 0L; + private long sprintTimeSpend = 0L; +@@ -15,8 +16,8 @@ + private boolean previousIsFrozen = false; + private final MinecraftServer server; + +- public ServerTickRateManager(MinecraftServer minecraftServer) { +- this.server = minecraftServer; ++ public ServerTickRateManager(MinecraftServer minecraftserver) { ++ this.server = minecraftserver; + } + + public boolean isSprinting() { +@@ -58,8 +59,14 @@ + } + + public boolean stopSprinting() { ++ // CraftBukkit start, add sendLog parameter ++ return stopSprinting(true); ++ } ++ ++ public boolean stopSprinting(boolean sendLog) { ++ // CraftBukkit end + if (this.remainingSprintTicks > 0L) { +- this.finishTickSprint(); ++ this.finishTickSprint(sendLog); // CraftBukkit - add sendLog parameter + return true; + } else { + return false; +@@ -68,22 +75,30 @@ + + public boolean requestGameToSprint(int i) { + boolean flag = this.remainingSprintTicks > 0L; ++ + this.sprintTimeSpend = 0L; +- this.scheduledCurrentSprintTicks = (long)i; +- this.remainingSprintTicks = (long)i; ++ this.scheduledCurrentSprintTicks = (long) i; ++ this.remainingSprintTicks = (long) i; + this.previousIsFrozen = this.isFrozen(); + this.setFrozen(false); + return flag; + } + +- private void finishTickSprint() { +- long l = this.scheduledCurrentSprintTicks - this.remainingSprintTicks; +- double d = Math.max(1.0, (double)this.sprintTimeSpend) / (double)TimeUtil.NANOSECONDS_PER_MILLISECOND; +- int i = (int)((double)(TimeUtil.MILLISECONDS_PER_SECOND * l) / d); +- String string = String.format("%.2f", l == 0L ? (double)this.millisecondsPerTick() : d / (double)l); ++ private void finishTickSprint(boolean sendLog) { // CraftBukkit - add sendLog parameter ++ long i = this.scheduledCurrentSprintTicks - this.remainingSprintTicks; ++ double d0 = Math.max(1.0D, (double) this.sprintTimeSpend) / (double) TimeUtil.NANOSECONDS_PER_MILLISECOND; ++ int j = (int) ((double) (TimeUtil.MILLISECONDS_PER_SECOND * i) / d0); ++ String s = String.format("%.2f", i == 0L ? (double) this.millisecondsPerTick() : d0 / (double) i); ++ + this.scheduledCurrentSprintTicks = 0L; + this.sprintTimeSpend = 0L; +- this.server.createCommandSourceStack().sendSuccess(() -> Component.translatable("commands.tick.sprint.report", i, string), true); ++ // CraftBukkit start - add sendLog parameter ++ if (sendLog) { ++ this.server.createCommandSourceStack().sendSuccess(() -> { ++ return Component.translatable("commands.tick.sprint.report", j, s); ++ }, true); ++ } ++ // CraftBukkit end + this.remainingSprintTicks = 0L; + this.setFrozen(this.previousIsFrozen); + this.server.onTickRateChanged(); +@@ -94,16 +109,16 @@ + return false; + } else if (this.remainingSprintTicks > 0L) { + this.sprintTickStartTime = System.nanoTime(); +- this.remainingSprintTicks--; ++ --this.remainingSprintTicks; + return true; + } else { +- this.finishTickSprint(); ++ this.finishTickSprint(true); // CraftBukkit - add sendLog parameter + return false; + } + } + + public void endTickWork() { +- this.sprintTimeSpend = this.sprintTimeSpend + (System.nanoTime() - this.sprintTickStartTime); ++ this.sprintTimeSpend += System.nanoTime() - this.sprintTickStartTime; + } + + @Override +@@ -113,8 +128,8 @@ + this.updateStateToClients(); + } + +- public void updateJoiningPlayer(ServerPlayer serverPlayer) { +- serverPlayer.connection.send(ClientboundTickingStatePacket.from(this)); +- serverPlayer.connection.send(ClientboundTickingStepPacket.from(this)); ++ public void updateJoiningPlayer(ServerPlayer entityplayer) { ++ entityplayer.connection.send(ClientboundTickingStatePacket.from(this)); ++ entityplayer.connection.send(ClientboundTickingStepPacket.from(this)); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/bossevents/CustomBossEvent.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/bossevents/CustomBossEvent.java.patch new file mode 100644 index 0000000000..e23c45c318 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/bossevents/CustomBossEvent.java.patch @@ -0,0 +1,270 @@ +--- a/net/minecraft/server/bossevents/CustomBossEvent.java ++++ b/net/minecraft/server/bossevents/CustomBossEvent.java +@@ -2,6 +2,7 @@ + + import com.google.common.collect.Sets; + import java.util.Collection; ++import java.util.Iterator; + import java.util.Set; + import java.util.UUID; + import net.minecraft.nbt.CompoundTag; +@@ -11,19 +12,33 @@ + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.ComponentUtils; + import net.minecraft.network.chat.HoverEvent; +-import net.minecraft.network.chat.Style; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.level.ServerBossEvent; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.Mth; + import net.minecraft.world.BossEvent; ++// CraftBukkit start ++import org.bukkit.boss.KeyedBossBar; ++import org.bukkit.craftbukkit.boss.CraftKeyedBossbar; ++// CraftBukkit end + + public class CustomBossEvent extends ServerBossEvent { ++ + private final ResourceLocation id; + private final Set players = Sets.newHashSet(); + private int value; + private int max = 100; ++ // CraftBukkit start ++ private KeyedBossBar bossBar; + ++ public KeyedBossBar getBukkitEntity() { ++ if (bossBar == null) { ++ bossBar = new CraftKeyedBossbar(this); ++ } ++ return bossBar; ++ } ++ // CraftBukkit end ++ + public CustomBossEvent(ResourceLocation id, Component name) { + super(name, BossEvent.BossBarColor.WHITE, BossEvent.BossBarOverlay.PROGRESS); + this.id = id; +@@ -66,118 +81,164 @@ + + public void setValue(int value) { + this.value = value; +- this.setProgress(Mth.clamp((float)value / (float)this.max, 0.0F, 1.0F)); ++ this.setProgress(Mth.clamp((float) value / (float) this.max, 0.0F, 1.0F)); + } + + public void setMax(int max) { + this.max = max; +- this.setProgress(Mth.clamp((float)this.value / (float)max, 0.0F, 1.0F)); ++ this.setProgress(Mth.clamp((float) this.value / (float) max, 0.0F, 1.0F)); + } + + public final Component getDisplayName() { +- return ComponentUtils.wrapInSquareBrackets(this.getName()) +- .withStyle( +- style -> style.withColor(this.getColor().getFormatting()) +- .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.literal(this.getTextId().toString()))) +- .withInsertion(this.getTextId().toString()) +- ); ++ return ComponentUtils.wrapInSquareBrackets(this.getName()).withStyle((chatmodifier) -> { ++ return chatmodifier.withColor(this.getColor().getFormatting()).withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.literal(this.getTextId().toString()))).withInsertion(this.getTextId().toString()); ++ }); + } + + public boolean setPlayers(Collection serverPlayerList) { + Set set = Sets.newHashSet(); + Set set1 = Sets.newHashSet(); ++ Iterator iterator = this.players.iterator(); + +- for (UUID uUID : this.players) { +- boolean flag = false; ++ UUID uuid; ++ boolean flag; ++ Iterator iterator1; + +- for (ServerPlayer serverPlayer : serverPlayerList) { +- if (serverPlayer.getUUID().equals(uUID)) { ++ while (iterator.hasNext()) { ++ uuid = (UUID) iterator.next(); ++ flag = false; ++ iterator1 = serverPlayerList.iterator(); ++ ++ while (true) { ++ if (iterator1.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator1.next(); ++ ++ if (!entityplayer.getUUID().equals(uuid)) { ++ continue; ++ } ++ + flag = true; +- break; + } +- } + +- if (!flag) { +- set.add(uUID); ++ if (!flag) { ++ set.add(uuid); ++ } ++ break; + } + } + +- for (ServerPlayer serverPlayer1 : serverPlayerList) { +- boolean flag = false; ++ iterator = serverPlayerList.iterator(); + +- for (UUID uUID1 : this.players) { +- if (serverPlayer1.getUUID().equals(uUID1)) { ++ ServerPlayer entityplayer1; ++ ++ while (iterator.hasNext()) { ++ entityplayer1 = (ServerPlayer) iterator.next(); ++ flag = false; ++ iterator1 = this.players.iterator(); ++ ++ while (true) { ++ if (iterator1.hasNext()) { ++ UUID uuid1 = (UUID) iterator1.next(); ++ ++ if (!entityplayer1.getUUID().equals(uuid1)) { ++ continue; ++ } ++ + flag = true; +- break; + } +- } + +- if (!flag) { +- set1.add(serverPlayer1); ++ if (!flag) { ++ set1.add(entityplayer1); ++ } ++ break; + } + } + +- for (UUID uUID : set) { +- for (ServerPlayer serverPlayer2 : this.getPlayers()) { +- if (serverPlayer2.getUUID().equals(uUID)) { +- this.removePlayer(serverPlayer2); +- break; ++ iterator = set.iterator(); ++ ++ while (iterator.hasNext()) { ++ uuid = (UUID) iterator.next(); ++ Iterator iterator2 = this.getPlayers().iterator(); ++ ++ while (true) { ++ if (iterator2.hasNext()) { ++ ServerPlayer entityplayer2 = (ServerPlayer) iterator2.next(); ++ ++ if (!entityplayer2.getUUID().equals(uuid)) { ++ continue; ++ } ++ ++ this.removePlayer(entityplayer2); + } +- } + +- this.players.remove(uUID); ++ this.players.remove(uuid); ++ break; ++ } + } + +- for (ServerPlayer serverPlayer1 : set1) { +- this.addPlayer(serverPlayer1); ++ iterator = set1.iterator(); ++ ++ while (iterator.hasNext()) { ++ entityplayer1 = (ServerPlayer) iterator.next(); ++ this.addPlayer(entityplayer1); + } + + return !set.isEmpty() || !set1.isEmpty(); + } + + public CompoundTag save() { +- CompoundTag compoundTag = new CompoundTag(); +- compoundTag.putString("Name", Component.Serializer.toJson(this.name)); +- compoundTag.putBoolean("Visible", this.isVisible()); +- compoundTag.putInt("Value", this.value); +- compoundTag.putInt("Max", this.max); +- compoundTag.putString("Color", this.getColor().getName()); +- compoundTag.putString("Overlay", this.getOverlay().getName()); +- compoundTag.putBoolean("DarkenScreen", this.shouldDarkenScreen()); +- compoundTag.putBoolean("PlayBossMusic", this.shouldPlayBossMusic()); +- compoundTag.putBoolean("CreateWorldFog", this.shouldCreateWorldFog()); +- ListTag list = new ListTag(); ++ CompoundTag nbttagcompound = new CompoundTag(); + +- for (UUID uUID : this.players) { +- list.add(NbtUtils.createUUID(uUID)); ++ nbttagcompound.putString("Name", Component.Serializer.toJson(this.name)); ++ nbttagcompound.putBoolean("Visible", this.isVisible()); ++ nbttagcompound.putInt("Value", this.value); ++ nbttagcompound.putInt("Max", this.max); ++ nbttagcompound.putString("Color", this.getColor().getName()); ++ nbttagcompound.putString("Overlay", this.getOverlay().getName()); ++ nbttagcompound.putBoolean("DarkenScreen", this.shouldDarkenScreen()); ++ nbttagcompound.putBoolean("PlayBossMusic", this.shouldPlayBossMusic()); ++ nbttagcompound.putBoolean("CreateWorldFog", this.shouldCreateWorldFog()); ++ ListTag nbttaglist = new ListTag(); ++ Iterator iterator = this.players.iterator(); ++ ++ while (iterator.hasNext()) { ++ UUID uuid = (UUID) iterator.next(); ++ ++ nbttaglist.add(NbtUtils.createUUID(uuid)); + } + +- compoundTag.put("Players", list); +- return compoundTag; ++ nbttagcompound.put("Players", nbttaglist); ++ return nbttagcompound; + } + + public static CustomBossEvent load(CompoundTag nbt, ResourceLocation id) { +- CustomBossEvent customBossEvent = new CustomBossEvent(id, Component.Serializer.fromJson(nbt.getString("Name"))); +- customBossEvent.setVisible(nbt.getBoolean("Visible")); +- customBossEvent.setValue(nbt.getInt("Value")); +- customBossEvent.setMax(nbt.getInt("Max")); +- customBossEvent.setColor(BossEvent.BossBarColor.byName(nbt.getString("Color"))); +- customBossEvent.setOverlay(BossEvent.BossBarOverlay.byName(nbt.getString("Overlay"))); +- customBossEvent.setDarkenScreen(nbt.getBoolean("DarkenScreen")); +- customBossEvent.setPlayBossMusic(nbt.getBoolean("PlayBossMusic")); +- customBossEvent.setCreateWorldFog(nbt.getBoolean("CreateWorldFog")); ++ CustomBossEvent bossbattlecustom = new CustomBossEvent(id, Component.Serializer.fromJson(nbt.getString("Name"))); + +- for (Tag tag : nbt.getList("Players", 11)) { +- customBossEvent.addOfflinePlayer(NbtUtils.loadUUID(tag)); ++ bossbattlecustom.setVisible(nbt.getBoolean("Visible")); ++ bossbattlecustom.setValue(nbt.getInt("Value")); ++ bossbattlecustom.setMax(nbt.getInt("Max")); ++ bossbattlecustom.setColor(BossEvent.BossBarColor.byName(nbt.getString("Color"))); ++ bossbattlecustom.setOverlay(BossEvent.BossBarOverlay.byName(nbt.getString("Overlay"))); ++ bossbattlecustom.setDarkenScreen(nbt.getBoolean("DarkenScreen")); ++ bossbattlecustom.setPlayBossMusic(nbt.getBoolean("PlayBossMusic")); ++ bossbattlecustom.setCreateWorldFog(nbt.getBoolean("CreateWorldFog")); ++ ListTag nbttaglist = nbt.getList("Players", 11); ++ Iterator iterator = nbttaglist.iterator(); ++ ++ while (iterator.hasNext()) { ++ Tag nbtbase = (Tag) iterator.next(); ++ ++ bossbattlecustom.addOfflinePlayer(NbtUtils.loadUUID(nbtbase)); + } + +- return customBossEvent; ++ return bossbattlecustom; + } + + public void onPlayerConnect(ServerPlayer player) { + if (this.players.contains(player.getUUID())) { + this.addPlayer(player); + } ++ + } + + public void onPlayerDisconnect(ServerPlayer player) { diff --git a/patch-remap/mache-vineflower/net/minecraft/server/commands/DifficultyCommand.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/commands/DifficultyCommand.java.patch new file mode 100644 index 0000000000..991375d013 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/commands/DifficultyCommand.java.patch @@ -0,0 +1,77 @@ +--- a/net/minecraft/server/commands/DifficultyCommand.java ++++ b/net/minecraft/server/commands/DifficultyCommand.java +@@ -2,41 +2,57 @@ + + import com.mojang.brigadier.CommandDispatcher; + import com.mojang.brigadier.builder.LiteralArgumentBuilder; +-import com.mojang.brigadier.context.CommandContext; + import com.mojang.brigadier.exceptions.CommandSyntaxException; + import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.network.chat.Component; + import net.minecraft.server.MinecraftServer; + import net.minecraft.world.Difficulty; + + public class DifficultyCommand { +- private static final DynamicCommandExceptionType ERROR_ALREADY_DIFFICULT = new DynamicCommandExceptionType( +- difficulty -> Component.translatableEscape("commands.difficulty.failure", difficulty) +- ); + ++ private static final DynamicCommandExceptionType ERROR_ALREADY_DIFFICULT = new DynamicCommandExceptionType((object) -> { ++ return Component.translatableEscape("commands.difficulty.failure", object); ++ }); ++ ++ public DifficultyCommand() {} ++ + public static void register(CommandDispatcher dispatcher) { +- LiteralArgumentBuilder literalArgumentBuilder = Commands.literal("difficulty"); ++ LiteralArgumentBuilder literalargumentbuilder = net.minecraft.commands.Commands.literal("difficulty"); ++ Difficulty[] aenumdifficulty = Difficulty.values(); ++ int i = aenumdifficulty.length; + +- for (Difficulty difficulty : Difficulty.values()) { +- literalArgumentBuilder.then(Commands.literal(difficulty.getKey()).executes(context -> setDifficulty(context.getSource(), difficulty))); ++ for (int j = 0; j < i; ++j) { ++ Difficulty enumdifficulty = aenumdifficulty[j]; ++ ++ literalargumentbuilder.then(net.minecraft.commands.Commands.literal(enumdifficulty.getKey()).executes((commandcontext) -> { ++ return setDifficulty((CommandSourceStack) commandcontext.getSource(), enumdifficulty); ++ })); + } + +- dispatcher.register(literalArgumentBuilder.requires(source -> source.hasPermission(2)).executes(context -> { +- Difficulty difficulty1 = context.getSource().getLevel().getDifficulty(); +- context.getSource().sendSuccess(() -> Component.translatable("commands.difficulty.query", difficulty1.getDisplayName()), false); +- return difficulty1.getId(); ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) literalargumentbuilder.requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).executes((commandcontext) -> { ++ Difficulty enumdifficulty1 = ((CommandSourceStack) commandcontext.getSource()).getLevel().getDifficulty(); ++ ++ ((CommandSourceStack) commandcontext.getSource()).sendSuccess(() -> { ++ return Component.translatable("commands.difficulty.query", enumdifficulty1.getDisplayName()); ++ }, false); ++ return enumdifficulty1.getId(); + })); + } + + public static int setDifficulty(CommandSourceStack source, Difficulty difficulty) throws CommandSyntaxException { +- MinecraftServer server = source.getServer(); +- if (server.getWorldData().getDifficulty() == difficulty) { +- throw ERROR_ALREADY_DIFFICULT.create(difficulty.getKey()); ++ MinecraftServer minecraftserver = source.getServer(); ++ net.minecraft.server.level.ServerLevel worldServer = source.getLevel(); // CraftBukkit ++ ++ if (worldServer.getDifficulty() == difficulty) { // CraftBukkit ++ throw DifficultyCommand.ERROR_ALREADY_DIFFICULT.create(difficulty.getKey()); + } else { +- server.setDifficulty(difficulty, true); +- source.sendSuccess(() -> Component.translatable("commands.difficulty.success", difficulty.getDisplayName()), true); ++ worldServer.serverLevelData.setDifficulty(difficulty); // CraftBukkit ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.difficulty.success", difficulty.getDisplayName()); ++ }, true); + return 0; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/commands/EffectCommands.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/commands/EffectCommands.java.patch new file mode 100644 index 0000000000..155d6ee789 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/commands/EffectCommands.java.patch @@ -0,0 +1,344 @@ +--- a/net/minecraft/server/commands/EffectCommands.java ++++ b/net/minecraft/server/commands/EffectCommands.java +@@ -4,14 +4,15 @@ + import com.mojang.brigadier.CommandDispatcher; + import com.mojang.brigadier.arguments.BoolArgumentType; + import com.mojang.brigadier.arguments.IntegerArgumentType; +-import com.mojang.brigadier.context.CommandContext; ++import com.mojang.brigadier.builder.LiteralArgumentBuilder; ++import com.mojang.brigadier.builder.RequiredArgumentBuilder; + import com.mojang.brigadier.exceptions.CommandSyntaxException; + import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; + import java.util.Collection; ++import java.util.Iterator; + import javax.annotation.Nullable; + import net.minecraft.commands.CommandBuildContext; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.arguments.EntityArgument; + import net.minecraft.commands.arguments.ResourceArgument; + import net.minecraft.core.Holder; +@@ -23,208 +24,112 @@ + import net.minecraft.world.entity.LivingEntity; + + public class EffectCommands { ++ + private static final SimpleCommandExceptionType ERROR_GIVE_FAILED = new SimpleCommandExceptionType(Component.translatable("commands.effect.give.failed")); +- private static final SimpleCommandExceptionType ERROR_CLEAR_EVERYTHING_FAILED = new SimpleCommandExceptionType( +- Component.translatable("commands.effect.clear.everything.failed") +- ); +- private static final SimpleCommandExceptionType ERROR_CLEAR_SPECIFIC_FAILED = new SimpleCommandExceptionType( +- Component.translatable("commands.effect.clear.specific.failed") +- ); ++ private static final SimpleCommandExceptionType ERROR_CLEAR_EVERYTHING_FAILED = new SimpleCommandExceptionType(Component.translatable("commands.effect.clear.everything.failed")); ++ private static final SimpleCommandExceptionType ERROR_CLEAR_SPECIFIC_FAILED = new SimpleCommandExceptionType(Component.translatable("commands.effect.clear.specific.failed")); + ++ public EffectCommands() {} ++ + public static void register(CommandDispatcher dispatcher, CommandBuildContext context) { +- dispatcher.register( +- Commands.literal("effect") +- .requires(source -> source.hasPermission(2)) +- .then( +- Commands.literal("clear") +- .executes(context1 -> clearEffects(context1.getSource(), ImmutableList.of(context1.getSource().getEntityOrException()))) +- .then( +- Commands.argument("targets", EntityArgument.entities()) +- .executes(context1 -> clearEffects(context1.getSource(), EntityArgument.getEntities(context1, "targets"))) +- .then( +- Commands.argument("effect", ResourceArgument.resource(context, Registries.MOB_EFFECT)) +- .executes( +- context1 -> clearEffect( +- context1.getSource(), +- EntityArgument.getEntities(context1, "targets"), +- ResourceArgument.getMobEffect(context1, "effect") +- ) +- ) +- ) +- ) +- ) +- .then( +- Commands.literal("give") +- .then( +- Commands.argument("targets", EntityArgument.entities()) +- .then( +- Commands.argument("effect", ResourceArgument.resource(context, Registries.MOB_EFFECT)) +- .executes( +- context1 -> giveEffect( +- context1.getSource(), +- EntityArgument.getEntities(context1, "targets"), +- ResourceArgument.getMobEffect(context1, "effect"), +- null, +- 0, +- true +- ) +- ) +- .then( +- Commands.argument("seconds", IntegerArgumentType.integer(1, 1000000)) +- .executes( +- context1 -> giveEffect( +- context1.getSource(), +- EntityArgument.getEntities(context1, "targets"), +- ResourceArgument.getMobEffect(context1, "effect"), +- IntegerArgumentType.getInteger(context1, "seconds"), +- 0, +- true +- ) +- ) +- .then( +- Commands.argument("amplifier", IntegerArgumentType.integer(0, 255)) +- .executes( +- context1 -> giveEffect( +- context1.getSource(), +- EntityArgument.getEntities(context1, "targets"), +- ResourceArgument.getMobEffect(context1, "effect"), +- IntegerArgumentType.getInteger(context1, "seconds"), +- IntegerArgumentType.getInteger(context1, "amplifier"), +- true +- ) +- ) +- .then( +- Commands.argument("hideParticles", BoolArgumentType.bool()) +- .executes( +- context1 -> giveEffect( +- context1.getSource(), +- EntityArgument.getEntities(context1, "targets"), +- ResourceArgument.getMobEffect(context1, "effect"), +- IntegerArgumentType.getInteger(context1, "seconds"), +- IntegerArgumentType.getInteger(context1, "amplifier"), +- !BoolArgumentType.getBool(context1, "hideParticles") +- ) +- ) +- ) +- ) +- ) +- .then( +- Commands.literal("infinite") +- .executes( +- context1 -> giveEffect( +- context1.getSource(), +- EntityArgument.getEntities(context1, "targets"), +- ResourceArgument.getMobEffect(context1, "effect"), +- -1, +- 0, +- true +- ) +- ) +- .then( +- Commands.argument("amplifier", IntegerArgumentType.integer(0, 255)) +- .executes( +- context1 -> giveEffect( +- context1.getSource(), +- EntityArgument.getEntities(context1, "targets"), +- ResourceArgument.getMobEffect(context1, "effect"), +- -1, +- IntegerArgumentType.getInteger(context1, "amplifier"), +- true +- ) +- ) +- .then( +- Commands.argument("hideParticles", BoolArgumentType.bool()) +- .executes( +- context1 -> giveEffect( +- context1.getSource(), +- EntityArgument.getEntities(context1, "targets"), +- ResourceArgument.getMobEffect(context1, "effect"), +- -1, +- IntegerArgumentType.getInteger(context1, "amplifier"), +- !BoolArgumentType.getBool(context1, "hideParticles") +- ) +- ) +- ) +- ) +- ) +- ) +- ) +- ) +- ); ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("effect").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).then(((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("clear").executes((commandcontext) -> { ++ return clearEffects((CommandSourceStack) commandcontext.getSource(), ImmutableList.of(((CommandSourceStack) commandcontext.getSource()).getEntityOrException())); ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("targets", EntityArgument.entities()).executes((commandcontext) -> { ++ return clearEffects((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets")); ++ })).then(net.minecraft.commands.Commands.argument("effect", ResourceArgument.resource(context, Registries.MOB_EFFECT)).executes((commandcontext) -> { ++ return clearEffect((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ResourceArgument.getMobEffect(commandcontext, "effect")); ++ }))))).then(net.minecraft.commands.Commands.literal("give").then(net.minecraft.commands.Commands.argument("targets", EntityArgument.entities()).then(((RequiredArgumentBuilder) ((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("effect", ResourceArgument.resource(context, Registries.MOB_EFFECT)).executes((commandcontext) -> { ++ return giveEffect((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ResourceArgument.getMobEffect(commandcontext, "effect"), (Integer) null, 0, true); ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("seconds", IntegerArgumentType.integer(1, 1000000)).executes((commandcontext) -> { ++ return giveEffect((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ResourceArgument.getMobEffect(commandcontext, "effect"), IntegerArgumentType.getInteger(commandcontext, "seconds"), 0, true); ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("amplifier", IntegerArgumentType.integer(0, 255)).executes((commandcontext) -> { ++ return giveEffect((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ResourceArgument.getMobEffect(commandcontext, "effect"), IntegerArgumentType.getInteger(commandcontext, "seconds"), IntegerArgumentType.getInteger(commandcontext, "amplifier"), true); ++ })).then(net.minecraft.commands.Commands.argument("hideParticles", BoolArgumentType.bool()).executes((commandcontext) -> { ++ return giveEffect((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ResourceArgument.getMobEffect(commandcontext, "effect"), IntegerArgumentType.getInteger(commandcontext, "seconds"), IntegerArgumentType.getInteger(commandcontext, "amplifier"), !BoolArgumentType.getBool(commandcontext, "hideParticles")); ++ }))))).then(((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("infinite").executes((commandcontext) -> { ++ return giveEffect((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ResourceArgument.getMobEffect(commandcontext, "effect"), -1, 0, true); ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("amplifier", IntegerArgumentType.integer(0, 255)).executes((commandcontext) -> { ++ return giveEffect((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ResourceArgument.getMobEffect(commandcontext, "effect"), -1, IntegerArgumentType.getInteger(commandcontext, "amplifier"), true); ++ })).then(net.minecraft.commands.Commands.argument("hideParticles", BoolArgumentType.bool()).executes((commandcontext) -> { ++ return giveEffect((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ResourceArgument.getMobEffect(commandcontext, "effect"), -1, IntegerArgumentType.getInteger(commandcontext, "amplifier"), !BoolArgumentType.getBool(commandcontext, "hideParticles")); ++ })))))))); + } + +- private static int giveEffect( +- CommandSourceStack source, +- Collection targets, +- Holder effect, +- @Nullable Integer seconds, +- int amplifier, +- boolean showParticles +- ) throws CommandSyntaxException { +- MobEffect mobEffect = effect.value(); +- int i = 0; +- int i1; ++ private static int giveEffect(CommandSourceStack source, Collection targets, Holder effect, @Nullable Integer seconds, int amplifier, boolean showParticles) throws CommandSyntaxException { ++ MobEffect mobeffectlist = (MobEffect) effect.value(); ++ int j = 0; ++ int k; ++ + if (seconds != null) { +- if (mobEffect.isInstantenous()) { +- i1 = seconds; ++ if (mobeffectlist.isInstantenous()) { ++ k = seconds; + } else if (seconds == -1) { +- i1 = -1; ++ k = -1; + } else { +- i1 = seconds * 20; ++ k = seconds * 20; + } +- } else if (mobEffect.isInstantenous()) { +- i1 = 1; ++ } else if (mobeffectlist.isInstantenous()) { ++ k = 1; + } else { +- i1 = 600; ++ k = 600; + } + +- for (Entity entity : targets) { ++ Iterator iterator = targets.iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ + if (entity instanceof LivingEntity) { +- MobEffectInstance mobEffectInstance = new MobEffectInstance(mobEffect, i1, amplifier, false, showParticles); +- if (((LivingEntity)entity).addEffect(mobEffectInstance, source.getEntity())) { +- i++; ++ MobEffectInstance mobeffect = new MobEffectInstance(mobeffectlist, k, amplifier, false, showParticles); ++ ++ if (((LivingEntity) entity).addEffect(mobeffect, source.getEntity(), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.COMMAND)) { // CraftBukkit ++ ++j; + } + } + } + +- if (i == 0) { +- throw ERROR_GIVE_FAILED.create(); ++ if (j == 0) { ++ throw EffectCommands.ERROR_GIVE_FAILED.create(); + } else { + if (targets.size() == 1) { +- source.sendSuccess( +- () -> Component.translatable( +- "commands.effect.give.success.single", mobEffect.getDisplayName(), targets.iterator().next().getDisplayName(), i1 / 20 +- ), +- true +- ); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.effect.give.success.single", mobeffectlist.getDisplayName(), ((Entity) targets.iterator().next()).getDisplayName(), k / 20); ++ }, true); + } else { +- source.sendSuccess( +- () -> Component.translatable("commands.effect.give.success.multiple", mobEffect.getDisplayName(), targets.size(), i1 / 20), true +- ); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.effect.give.success.multiple", mobeffectlist.getDisplayName(), targets.size(), k / 20); ++ }, true); + } + +- return i; ++ return j; + } + } + + private static int clearEffects(CommandSourceStack source, Collection targets) throws CommandSyntaxException { + int i = 0; ++ Iterator iterator = targets.iterator(); + +- for (Entity entity : targets) { +- if (entity instanceof LivingEntity && ((LivingEntity)entity).removeAllEffects()) { +- i++; ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ ++ if (entity instanceof LivingEntity && ((LivingEntity) entity).removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.COMMAND)) { // CraftBukkit ++ ++i; + } + } + + if (i == 0) { +- throw ERROR_CLEAR_EVERYTHING_FAILED.create(); ++ throw EffectCommands.ERROR_CLEAR_EVERYTHING_FAILED.create(); + } else { + if (targets.size() == 1) { +- source.sendSuccess( +- () -> Component.translatable("commands.effect.clear.everything.success.single", targets.iterator().next().getDisplayName()), true +- ); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.effect.clear.everything.success.single", ((Entity) targets.iterator().next()).getDisplayName()); ++ }, true); + } else { +- source.sendSuccess(() -> Component.translatable("commands.effect.clear.everything.success.multiple", targets.size()), true); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.effect.clear.everything.success.multiple", targets.size()); ++ }, true); + } + + return i; +@@ -232,29 +137,29 @@ + } + + private static int clearEffect(CommandSourceStack source, Collection targets, Holder effect) throws CommandSyntaxException { +- MobEffect mobEffect = effect.value(); ++ MobEffect mobeffectlist = (MobEffect) effect.value(); + int i = 0; ++ Iterator iterator = targets.iterator(); + +- for (Entity entity : targets) { +- if (entity instanceof LivingEntity && ((LivingEntity)entity).removeEffect(mobEffect)) { +- i++; ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ ++ if (entity instanceof LivingEntity && ((LivingEntity) entity).removeEffect(mobeffectlist, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.COMMAND)) { // CraftBukkit ++ ++i; + } + } + + if (i == 0) { +- throw ERROR_CLEAR_SPECIFIC_FAILED.create(); ++ throw EffectCommands.ERROR_CLEAR_SPECIFIC_FAILED.create(); + } else { + if (targets.size() == 1) { +- source.sendSuccess( +- () -> Component.translatable( +- "commands.effect.clear.specific.success.single", mobEffect.getDisplayName(), targets.iterator().next().getDisplayName() +- ), +- true +- ); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.effect.clear.specific.success.single", mobeffectlist.getDisplayName(), ((Entity) targets.iterator().next()).getDisplayName()); ++ }, true); + } else { +- source.sendSuccess( +- () -> Component.translatable("commands.effect.clear.specific.success.multiple", mobEffect.getDisplayName(), targets.size()), true +- ); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.effect.clear.specific.success.multiple", mobeffectlist.getDisplayName(), targets.size()); ++ }, true); + } + + return i; diff --git a/patch-remap/mache-vineflower/net/minecraft/server/commands/GameRuleCommand.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/commands/GameRuleCommand.java.patch new file mode 100644 index 0000000000..4ac723ebec --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/commands/GameRuleCommand.java.patch @@ -0,0 +1,73 @@ +--- a/net/minecraft/server/commands/GameRuleCommand.java ++++ b/net/minecraft/server/commands/GameRuleCommand.java +@@ -4,39 +4,48 @@ + import com.mojang.brigadier.builder.LiteralArgumentBuilder; + import com.mojang.brigadier.context.CommandContext; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.network.chat.Component; + import net.minecraft.world.level.GameRules; + + public class GameRuleCommand { ++ ++ public GameRuleCommand() {} ++ + public static void register(CommandDispatcher dispatcher) { +- final LiteralArgumentBuilder literalArgumentBuilder = Commands.literal("gamerule").requires(source -> source.hasPermission(2)); +- GameRules.visitGameRuleTypes( +- new GameRules.GameRuleTypeVisitor() { +- @Override +- public > void visit(GameRules.Key key, GameRules.Type type) { +- literalArgumentBuilder.then( +- Commands.literal(key.getId()) +- .executes(context -> GameRuleCommand.queryRule(context.getSource(), key)) +- .then(type.createArgument("value").executes(context -> GameRuleCommand.setRule(context, key))) +- ); +- } ++ final LiteralArgumentBuilder literalargumentbuilder = (LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("gamerule").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ }); ++ ++ GameRules.visitGameRuleTypes(new GameRules.GameRuleTypeVisitor() { ++ @Override ++ public > void visit(GameRules.Key key, GameRules.Type type) { ++ literalargumentbuilder.then(((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal(key.getId()).executes((commandcontext) -> { ++ return GameRuleCommand.queryRule((CommandSourceStack) commandcontext.getSource(), key); ++ })).then(type.createArgument("value").executes((commandcontext) -> { ++ return GameRuleCommand.setRule(commandcontext, key); ++ }))); + } +- ); +- dispatcher.register(literalArgumentBuilder); ++ }); ++ dispatcher.register(literalargumentbuilder); + } + + static > int setRule(CommandContext source, GameRules.Key gameRule) { +- CommandSourceStack commandSourceStack = source.getSource(); +- T rule = commandSourceStack.getServer().getGameRules().getRule(gameRule); +- rule.setFromArgument(source, "value"); +- commandSourceStack.sendSuccess(() -> Component.translatable("commands.gamerule.set", gameRule.getId(), rule.toString()), true); +- return rule.getCommandResult(); ++ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) source.getSource(); ++ T t0 = commandlistenerwrapper.getLevel().getGameRules().getRule(gameRule); // CraftBukkit ++ ++ t0.setFromArgument(source, "value"); ++ commandlistenerwrapper.sendSuccess(() -> { ++ return Component.translatable("commands.gamerule.set", gameRule.getId(), t0.toString()); ++ }, true); ++ return t0.getCommandResult(); + } + + static > int queryRule(CommandSourceStack source, GameRules.Key gameRule) { +- T rule = source.getServer().getGameRules().getRule(gameRule); +- source.sendSuccess(() -> Component.translatable("commands.gamerule.query", gameRule.getId(), rule.toString()), false); +- return rule.getCommandResult(); ++ T t0 = source.getLevel().getGameRules().getRule(gameRule); // CraftBukkit ++ ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.gamerule.query", gameRule.getId(), t0.toString()); ++ }, false); ++ return t0.getCommandResult(); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/commands/GiveCommand.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/commands/GiveCommand.java.patch new file mode 100644 index 0000000000..22ce2f6dab --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/commands/GiveCommand.java.patch @@ -0,0 +1,158 @@ +--- a/net/minecraft/server/commands/GiveCommand.java ++++ b/net/minecraft/server/commands/GiveCommand.java +@@ -2,12 +2,13 @@ + + import com.mojang.brigadier.CommandDispatcher; + import com.mojang.brigadier.arguments.IntegerArgumentType; +-import com.mojang.brigadier.context.CommandContext; ++import com.mojang.brigadier.builder.LiteralArgumentBuilder; ++import com.mojang.brigadier.builder.RequiredArgumentBuilder; + import com.mojang.brigadier.exceptions.CommandSyntaxException; + import java.util.Collection; ++import java.util.Iterator; + import net.minecraft.commands.CommandBuildContext; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.arguments.EntityArgument; + import net.minecraft.commands.arguments.item.ItemArgument; + import net.minecraft.commands.arguments.item.ItemInput; +@@ -16,92 +17,75 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.entity.item.ItemEntity; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + + public class GiveCommand { ++ + public static final int MAX_ALLOWED_ITEMSTACKS = 100; + ++ public GiveCommand() {} ++ + public static void register(CommandDispatcher dispatcher, CommandBuildContext context) { +- dispatcher.register( +- Commands.literal("give") +- .requires(source -> source.hasPermission(2)) +- .then( +- Commands.argument("targets", EntityArgument.players()) +- .then( +- Commands.argument("item", ItemArgument.item(context)) +- .executes( +- context1 -> giveItem( +- context1.getSource(), ItemArgument.getItem(context1, "item"), EntityArgument.getPlayers(context1, "targets"), 1 +- ) +- ) +- .then( +- Commands.argument("count", IntegerArgumentType.integer(1)) +- .executes( +- context1 -> giveItem( +- context1.getSource(), +- ItemArgument.getItem(context1, "item"), +- EntityArgument.getPlayers(context1, "targets"), +- IntegerArgumentType.getInteger(context1, "count") +- ) +- ) +- ) +- ) +- ) +- ); ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("give").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).then(net.minecraft.commands.Commands.argument("targets", EntityArgument.players()).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("item", ItemArgument.item(context)).executes((commandcontext) -> { ++ return giveItem((CommandSourceStack) commandcontext.getSource(), ItemArgument.getItem(commandcontext, "item"), EntityArgument.getPlayers(commandcontext, "targets"), 1); ++ })).then(net.minecraft.commands.Commands.argument("count", IntegerArgumentType.integer(1)).executes((commandcontext) -> { ++ return giveItem((CommandSourceStack) commandcontext.getSource(), ItemArgument.getItem(commandcontext, "item"), EntityArgument.getPlayers(commandcontext, "targets"), IntegerArgumentType.getInteger(commandcontext, "count")); ++ }))))); + } + + private static int giveItem(CommandSourceStack source, ItemInput item, Collection targets, int count) throws CommandSyntaxException { +- int maxStackSize = item.getItem().getMaxStackSize(); +- int i = maxStackSize * 100; +- ItemStack itemStack = item.createItemStack(count, false); +- if (count > i) { +- source.sendFailure(Component.translatable("commands.give.failed.toomanyitems", i, itemStack.getDisplayName())); ++ int j = item.getItem().getMaxStackSize(); ++ int k = j * 100; ++ ItemStack itemstack = item.createItemStack(count, false); ++ ++ if (count > k) { ++ source.sendFailure(Component.translatable("commands.give.failed.toomanyitems", k, itemstack.getDisplayName())); + return 0; + } else { +- for (ServerPlayer serverPlayer : targets) { +- int i1 = count; ++ Iterator iterator = targets.iterator(); + +- while (i1 > 0) { +- int min = Math.min(maxStackSize, i1); +- i1 -= min; +- ItemStack itemStack1 = item.createItemStack(min, false); +- boolean flag = serverPlayer.getInventory().add(itemStack1); +- if (flag && itemStack1.isEmpty()) { +- itemStack1.setCount(1); +- ItemEntity itemEntity = serverPlayer.drop(itemStack1, false); +- if (itemEntity != null) { +- itemEntity.makeFakeItem(); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ int l = count; ++ ++ while (l > 0) { ++ int i1 = Math.min(j, l); ++ ++ l -= i1; ++ ItemStack itemstack1 = item.createItemStack(i1, false); ++ boolean flag = entityplayer.getInventory().add(itemstack1); ++ ItemEntity entityitem; ++ ++ if (flag && itemstack1.isEmpty()) { ++ itemstack1.setCount(1); ++ entityitem = entityplayer.drop(itemstack1, false, false, false); // SPIGOT-2942: Add boolean to call event ++ if (entityitem != null) { ++ entityitem.makeFakeItem(); + } + +- serverPlayer.level() +- .playSound( +- null, +- serverPlayer.getX(), +- serverPlayer.getY(), +- serverPlayer.getZ(), +- SoundEvents.ITEM_PICKUP, +- SoundSource.PLAYERS, +- 0.2F, +- ((serverPlayer.getRandom().nextFloat() - serverPlayer.getRandom().nextFloat()) * 0.7F + 1.0F) * 2.0F +- ); +- serverPlayer.containerMenu.broadcastChanges(); ++ entityplayer.level().playSound((Player) null, entityplayer.getX(), entityplayer.getY(), entityplayer.getZ(), SoundEvents.ITEM_PICKUP, SoundSource.PLAYERS, 0.2F, ((entityplayer.getRandom().nextFloat() - entityplayer.getRandom().nextFloat()) * 0.7F + 1.0F) * 2.0F); ++ entityplayer.containerMenu.broadcastChanges(); + } else { +- ItemEntity itemEntity = serverPlayer.drop(itemStack1, false); +- if (itemEntity != null) { +- itemEntity.setNoPickUpDelay(); +- itemEntity.setTarget(serverPlayer.getUUID()); ++ entityitem = entityplayer.drop(itemstack1, false); ++ if (entityitem != null) { ++ entityitem.setNoPickUpDelay(); ++ entityitem.setTarget(entityplayer.getUUID()); + } + } + } + } + + if (targets.size() == 1) { +- source.sendSuccess( +- () -> Component.translatable("commands.give.success.single", count, itemStack.getDisplayName(), targets.iterator().next().getDisplayName()), +- true +- ); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.give.success.single", count, itemstack.getDisplayName(), ((ServerPlayer) targets.iterator().next()).getDisplayName()); ++ }, true); + } else { +- source.sendSuccess(() -> Component.translatable("commands.give.success.single", count, itemStack.getDisplayName(), targets.size()), true); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.give.success.single", count, itemstack.getDisplayName(), targets.size()); ++ }, true); + } + + return targets.size(); diff --git a/patch-remap/mache-vineflower/net/minecraft/server/commands/ListPlayersCommand.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/commands/ListPlayersCommand.java.patch new file mode 100644 index 0000000000..f1123c53ed --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/commands/ListPlayersCommand.java.patch @@ -0,0 +1,71 @@ +--- a/net/minecraft/server/commands/ListPlayersCommand.java ++++ b/net/minecraft/server/commands/ListPlayersCommand.java +@@ -1,11 +1,10 @@ + package net.minecraft.server.commands; + + import com.mojang.brigadier.CommandDispatcher; +-import com.mojang.brigadier.context.CommandContext; ++import com.mojang.brigadier.builder.LiteralArgumentBuilder; + import java.util.List; + import java.util.function.Function; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.ComponentUtils; + import net.minecraft.server.level.ServerPlayer; +@@ -13,12 +12,15 @@ + import net.minecraft.world.entity.player.Player; + + public class ListPlayersCommand { ++ ++ public ListPlayersCommand() {} ++ + public static void register(CommandDispatcher dispatcher) { +- dispatcher.register( +- Commands.literal("list") +- .executes(context -> listPlayers(context.getSource())) +- .then(Commands.literal("uuids").executes(context -> listPlayersWithUuids(context.getSource()))) +- ); ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("list").executes((commandcontext) -> { ++ return listPlayers((CommandSourceStack) commandcontext.getSource()); ++ })).then(net.minecraft.commands.Commands.literal("uuids").executes((commandcontext) -> { ++ return listPlayersWithUuids((CommandSourceStack) commandcontext.getSource()); ++ }))); + } + + private static int listPlayers(CommandSourceStack source) { +@@ -26,16 +28,26 @@ + } + + private static int listPlayersWithUuids(CommandSourceStack source) { +- return format( +- source, player -> Component.translatable("commands.list.nameAndId", player.getName(), Component.translationArg(player.getGameProfile().getId())) +- ); ++ return format(source, (entityplayer) -> { ++ return Component.translatable("commands.list.nameAndId", entityplayer.getName(), Component.translationArg(entityplayer.getGameProfile().getId())); ++ }); + } + + private static int format(CommandSourceStack source, Function nameExtractor) { +- PlayerList playerList = source.getServer().getPlayerList(); +- List players = playerList.getPlayers(); +- Component component = ComponentUtils.formatList(players, nameExtractor); +- source.sendSuccess(() -> Component.translatable("commands.list.players", players.size(), playerList.getMaxPlayers(), component), false); +- return players.size(); ++ PlayerList playerlist = source.getServer().getPlayerList(); ++ // CraftBukkit start ++ List players = playerlist.getPlayers(); ++ if (source.getBukkitSender() instanceof org.bukkit.entity.Player) { ++ org.bukkit.entity.Player sender = (org.bukkit.entity.Player) source.getBukkitSender(); ++ players = players.stream().filter((ep) -> sender.canSee(ep.getBukkitEntity())).collect(java.util.stream.Collectors.toList()); ++ } ++ List list = players; ++ // CraftBukkit end ++ Component ichatbasecomponent = ComponentUtils.formatList(list, nameExtractor); ++ ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.list.players", list.size(), playerlist.getMaxPlayers(), ichatbasecomponent); ++ }, false); ++ return list.size(); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/commands/LootCommand.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/commands/LootCommand.java.patch new file mode 100644 index 0000000000..784839a984 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/commands/LootCommand.java.patch @@ -0,0 +1,715 @@ +--- a/net/minecraft/server/commands/LootCommand.java ++++ b/net/minecraft/server/commands/LootCommand.java +@@ -4,16 +4,17 @@ + import com.mojang.brigadier.CommandDispatcher; + import com.mojang.brigadier.arguments.IntegerArgumentType; + import com.mojang.brigadier.builder.ArgumentBuilder; ++import com.mojang.brigadier.builder.LiteralArgumentBuilder; ++import com.mojang.brigadier.builder.RequiredArgumentBuilder; + import com.mojang.brigadier.context.CommandContext; + import com.mojang.brigadier.exceptions.CommandSyntaxException; + import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; + import com.mojang.brigadier.suggestion.SuggestionProvider; +-import com.mojang.brigadier.suggestion.SuggestionsBuilder; + import java.util.Collection; ++import java.util.Iterator; + import java.util.List; + import net.minecraft.commands.CommandBuildContext; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.SharedSuggestionProvider; + import net.minecraft.commands.arguments.EntityArgument; + import net.minecraft.commands.arguments.ResourceLocationArgument; +@@ -35,7 +36,7 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.storage.loot.LootDataManager; + import net.minecraft.world.level.storage.loot.LootDataType; + import net.minecraft.world.level.storage.loot.LootParams; +@@ -45,277 +46,114 @@ + import net.minecraft.world.phys.Vec3; + + public class LootCommand { +- public static final SuggestionProvider SUGGEST_LOOT_TABLE = (context, builder) -> { +- LootDataManager lootData = context.getSource().getServer().getLootData(); +- return SharedSuggestionProvider.suggestResource(lootData.getKeys(LootDataType.TABLE), builder); ++ ++ public static final SuggestionProvider SUGGEST_LOOT_TABLE = (commandcontext, suggestionsbuilder) -> { ++ LootDataManager lootdatamanager = ((CommandSourceStack) commandcontext.getSource()).getServer().getLootData(); ++ ++ return SharedSuggestionProvider.suggestResource((Iterable) lootdatamanager.getKeys(LootDataType.TABLE), suggestionsbuilder); + }; +- private static final DynamicCommandExceptionType ERROR_NO_HELD_ITEMS = new DynamicCommandExceptionType( +- target -> Component.translatableEscape("commands.drop.no_held_items", target) +- ); +- private static final DynamicCommandExceptionType ERROR_NO_LOOT_TABLE = new DynamicCommandExceptionType( +- target -> Component.translatableEscape("commands.drop.no_loot_table", target) +- ); ++ private static final DynamicCommandExceptionType ERROR_NO_HELD_ITEMS = new DynamicCommandExceptionType((object) -> { ++ return Component.translatableEscape("commands.drop.no_held_items", object); ++ }); ++ private static final DynamicCommandExceptionType ERROR_NO_LOOT_TABLE = new DynamicCommandExceptionType((object) -> { ++ return Component.translatableEscape("commands.drop.no_loot_table", object); ++ }); + ++ public LootCommand() {} ++ + public static void register(CommandDispatcher dispatcher, CommandBuildContext context) { +- dispatcher.register( +- addTargets( +- Commands.literal("loot").requires(source -> source.hasPermission(2)), +- (argumentBuilder, dropConsumer) -> argumentBuilder.then( +- Commands.literal("fish") +- .then( +- Commands.argument("loot_table", ResourceLocationArgument.id()) +- .suggests(SUGGEST_LOOT_TABLE) +- .then( +- Commands.argument("pos", BlockPosArgument.blockPos()) +- .executes( +- context1 -> dropFishingLoot( +- context1, +- ResourceLocationArgument.getId(context1, "loot_table"), +- BlockPosArgument.getLoadedBlockPos(context1, "pos"), +- ItemStack.EMPTY, +- dropConsumer +- ) +- ) +- .then( +- Commands.argument("tool", ItemArgument.item(context)) +- .executes( +- context1 -> dropFishingLoot( +- context1, +- ResourceLocationArgument.getId(context1, "loot_table"), +- BlockPosArgument.getLoadedBlockPos(context1, "pos"), +- ItemArgument.getItem(context1, "tool").createItemStack(1, false), +- dropConsumer +- ) +- ) +- ) +- .then( +- Commands.literal("mainhand") +- .executes( +- context1 -> dropFishingLoot( +- context1, +- ResourceLocationArgument.getId(context1, "loot_table"), +- BlockPosArgument.getLoadedBlockPos(context1, "pos"), +- getSourceHandItem(context1.getSource(), EquipmentSlot.MAINHAND), +- dropConsumer +- ) +- ) +- ) +- .then( +- Commands.literal("offhand") +- .executes( +- context1 -> dropFishingLoot( +- context1, +- ResourceLocationArgument.getId(context1, "loot_table"), +- BlockPosArgument.getLoadedBlockPos(context1, "pos"), +- getSourceHandItem(context1.getSource(), EquipmentSlot.OFFHAND), +- dropConsumer +- ) +- ) +- ) +- ) +- ) +- ) +- .then( +- Commands.literal("loot") +- .then( +- Commands.argument("loot_table", ResourceLocationArgument.id()) +- .suggests(SUGGEST_LOOT_TABLE) +- .executes(context1 -> dropChestLoot(context1, ResourceLocationArgument.getId(context1, "loot_table"), dropConsumer)) +- ) +- ) +- .then( +- Commands.literal("kill") +- .then( +- Commands.argument("target", EntityArgument.entity()) +- .executes(context1 -> dropKillLoot(context1, EntityArgument.getEntity(context1, "target"), dropConsumer)) +- ) +- ) +- .then( +- Commands.literal("mine") +- .then( +- Commands.argument("pos", BlockPosArgument.blockPos()) +- .executes( +- context1 -> dropBlockLoot( +- context1, BlockPosArgument.getLoadedBlockPos(context1, "pos"), ItemStack.EMPTY, dropConsumer +- ) +- ) +- .then( +- Commands.argument("tool", ItemArgument.item(context)) +- .executes( +- context1 -> dropBlockLoot( +- context1, +- BlockPosArgument.getLoadedBlockPos(context1, "pos"), +- ItemArgument.getItem(context1, "tool").createItemStack(1, false), +- dropConsumer +- ) +- ) +- ) +- .then( +- Commands.literal("mainhand") +- .executes( +- context1 -> dropBlockLoot( +- context1, +- BlockPosArgument.getLoadedBlockPos(context1, "pos"), +- getSourceHandItem(context1.getSource(), EquipmentSlot.MAINHAND), +- dropConsumer +- ) +- ) +- ) +- .then( +- Commands.literal("offhand") +- .executes( +- context1 -> dropBlockLoot( +- context1, +- BlockPosArgument.getLoadedBlockPos(context1, "pos"), +- getSourceHandItem(context1.getSource(), EquipmentSlot.OFFHAND), +- dropConsumer +- ) +- ) +- ) +- ) +- ) +- ) +- ); ++ dispatcher.register((LiteralArgumentBuilder) addTargets((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("loot").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ }), (argumentbuilder, commandloot_b) -> { ++ return argumentbuilder.then(net.minecraft.commands.Commands.literal("fish").then(net.minecraft.commands.Commands.argument("loot_table", ResourceLocationArgument.id()).suggests(LootCommand.SUGGEST_LOOT_TABLE).then(((RequiredArgumentBuilder) ((RequiredArgumentBuilder) ((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("pos", BlockPosArgument.blockPos()).executes((commandcontext) -> { ++ return dropFishingLoot(commandcontext, ResourceLocationArgument.getId(commandcontext, "loot_table"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), ItemStack.EMPTY, commandloot_b); ++ })).then(net.minecraft.commands.Commands.argument("tool", ItemArgument.item(context)).executes((commandcontext) -> { ++ return dropFishingLoot(commandcontext, ResourceLocationArgument.getId(commandcontext, "loot_table"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), ItemArgument.getItem(commandcontext, "tool").createItemStack(1, false), commandloot_b); ++ }))).then(net.minecraft.commands.Commands.literal("mainhand").executes((commandcontext) -> { ++ return dropFishingLoot(commandcontext, ResourceLocationArgument.getId(commandcontext, "loot_table"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), getSourceHandItem((CommandSourceStack) commandcontext.getSource(), EquipmentSlot.MAINHAND), commandloot_b); ++ }))).then(net.minecraft.commands.Commands.literal("offhand").executes((commandcontext) -> { ++ return dropFishingLoot(commandcontext, ResourceLocationArgument.getId(commandcontext, "loot_table"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), getSourceHandItem((CommandSourceStack) commandcontext.getSource(), EquipmentSlot.OFFHAND), commandloot_b); ++ }))))).then(net.minecraft.commands.Commands.literal("loot").then(net.minecraft.commands.Commands.argument("loot_table", ResourceLocationArgument.id()).suggests(LootCommand.SUGGEST_LOOT_TABLE).executes((commandcontext) -> { ++ return dropChestLoot(commandcontext, ResourceLocationArgument.getId(commandcontext, "loot_table"), commandloot_b); ++ }))).then(net.minecraft.commands.Commands.literal("kill").then(net.minecraft.commands.Commands.argument("target", EntityArgument.entity()).executes((commandcontext) -> { ++ return dropKillLoot(commandcontext, EntityArgument.getEntity(commandcontext, "target"), commandloot_b); ++ }))).then(net.minecraft.commands.Commands.literal("mine").then(((RequiredArgumentBuilder) ((RequiredArgumentBuilder) ((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("pos", BlockPosArgument.blockPos()).executes((commandcontext) -> { ++ return dropBlockLoot(commandcontext, BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), ItemStack.EMPTY, commandloot_b); ++ })).then(net.minecraft.commands.Commands.argument("tool", ItemArgument.item(context)).executes((commandcontext) -> { ++ return dropBlockLoot(commandcontext, BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), ItemArgument.getItem(commandcontext, "tool").createItemStack(1, false), commandloot_b); ++ }))).then(net.minecraft.commands.Commands.literal("mainhand").executes((commandcontext) -> { ++ return dropBlockLoot(commandcontext, BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), getSourceHandItem((CommandSourceStack) commandcontext.getSource(), EquipmentSlot.MAINHAND), commandloot_b); ++ }))).then(net.minecraft.commands.Commands.literal("offhand").executes((commandcontext) -> { ++ return dropBlockLoot(commandcontext, BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), getSourceHandItem((CommandSourceStack) commandcontext.getSource(), EquipmentSlot.OFFHAND), commandloot_b); ++ })))); ++ })); + } + + private static > T addTargets(T builder, LootCommand.TailProvider tailProvider) { +- return builder.then( +- Commands.literal("replace") +- .then( +- Commands.literal("entity") +- .then( +- Commands.argument("entities", EntityArgument.entities()) +- .then( +- tailProvider.construct( +- Commands.argument("slot", SlotArgument.slot()), +- (context, items, callback) -> entityReplace( +- EntityArgument.getEntities(context, "entities"), +- SlotArgument.getSlot(context, "slot"), +- items.size(), +- items, +- callback +- ) +- ) +- .then( +- tailProvider.construct( +- Commands.argument("count", IntegerArgumentType.integer(0)), +- (context, items, callback) -> entityReplace( +- EntityArgument.getEntities(context, "entities"), +- SlotArgument.getSlot(context, "slot"), +- IntegerArgumentType.getInteger(context, "count"), +- items, +- callback +- ) +- ) +- ) +- ) +- ) +- ) +- .then( +- Commands.literal("block") +- .then( +- Commands.argument("targetPos", BlockPosArgument.blockPos()) +- .then( +- tailProvider.construct( +- Commands.argument("slot", SlotArgument.slot()), +- (context, items, callback) -> blockReplace( +- context.getSource(), +- BlockPosArgument.getLoadedBlockPos(context, "targetPos"), +- SlotArgument.getSlot(context, "slot"), +- items.size(), +- items, +- callback +- ) +- ) +- .then( +- tailProvider.construct( +- Commands.argument("count", IntegerArgumentType.integer(0)), +- (context, items, callback) -> blockReplace( +- context.getSource(), +- BlockPosArgument.getLoadedBlockPos(context, "targetPos"), +- IntegerArgumentType.getInteger(context, "slot"), +- IntegerArgumentType.getInteger(context, "count"), +- items, +- callback +- ) +- ) +- ) +- ) +- ) +- ) +- ) +- .then( +- Commands.literal("insert") +- .then( +- tailProvider.construct( +- Commands.argument("targetPos", BlockPosArgument.blockPos()), +- (context, items, callback) -> blockDistribute( +- context.getSource(), BlockPosArgument.getLoadedBlockPos(context, "targetPos"), items, callback +- ) +- ) +- ) +- ) +- .then( +- Commands.literal("give") +- .then( +- tailProvider.construct( +- Commands.argument("players", EntityArgument.players()), +- (context, items, callback) -> playerGive(EntityArgument.getPlayers(context, "players"), items, callback) +- ) +- ) +- ) +- .then( +- Commands.literal("spawn") +- .then( +- tailProvider.construct( +- Commands.argument("targetPos", Vec3Argument.vec3()), +- (context, items, callback) -> dropInWorld(context.getSource(), Vec3Argument.getVec3(context, "targetPos"), items, callback) +- ) +- ) +- ); ++ return (T) builder.then(((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("replace").then(net.minecraft.commands.Commands.literal("entity").then(net.minecraft.commands.Commands.argument("entities", EntityArgument.entities()).then(tailProvider.construct(net.minecraft.commands.Commands.argument("slot", SlotArgument.slot()), (commandcontext, list, commandloot_a) -> { // CraftBukkit - decompile error ++ return entityReplace(EntityArgument.getEntities(commandcontext, "entities"), SlotArgument.getSlot(commandcontext, "slot"), list.size(), list, commandloot_a); ++ }).then(tailProvider.construct(net.minecraft.commands.Commands.argument("count", IntegerArgumentType.integer(0)), (commandcontext, list, commandloot_a) -> { ++ return entityReplace(EntityArgument.getEntities(commandcontext, "entities"), SlotArgument.getSlot(commandcontext, "slot"), IntegerArgumentType.getInteger(commandcontext, "count"), list, commandloot_a); ++ })))))).then(net.minecraft.commands.Commands.literal("block").then(net.minecraft.commands.Commands.argument("targetPos", BlockPosArgument.blockPos()).then(tailProvider.construct(net.minecraft.commands.Commands.argument("slot", SlotArgument.slot()), (commandcontext, list, commandloot_a) -> { ++ return blockReplace((CommandSourceStack) commandcontext.getSource(), BlockPosArgument.getLoadedBlockPos(commandcontext, "targetPos"), SlotArgument.getSlot(commandcontext, "slot"), list.size(), list, commandloot_a); ++ }).then(tailProvider.construct(net.minecraft.commands.Commands.argument("count", IntegerArgumentType.integer(0)), (commandcontext, list, commandloot_a) -> { ++ return blockReplace((CommandSourceStack) commandcontext.getSource(), BlockPosArgument.getLoadedBlockPos(commandcontext, "targetPos"), IntegerArgumentType.getInteger(commandcontext, "slot"), IntegerArgumentType.getInteger(commandcontext, "count"), list, commandloot_a); ++ })))))).then(net.minecraft.commands.Commands.literal("insert").then(tailProvider.construct(net.minecraft.commands.Commands.argument("targetPos", BlockPosArgument.blockPos()), (commandcontext, list, commandloot_a) -> { ++ return blockDistribute((CommandSourceStack) commandcontext.getSource(), BlockPosArgument.getLoadedBlockPos(commandcontext, "targetPos"), list, commandloot_a); ++ }))).then(net.minecraft.commands.Commands.literal("give").then(tailProvider.construct(net.minecraft.commands.Commands.argument("players", EntityArgument.players()), (commandcontext, list, commandloot_a) -> { ++ return playerGive(EntityArgument.getPlayers(commandcontext, "players"), list, commandloot_a); ++ }))).then(net.minecraft.commands.Commands.literal("spawn").then(tailProvider.construct(net.minecraft.commands.Commands.argument("targetPos", Vec3Argument.vec3()), (commandcontext, list, commandloot_a) -> { ++ return dropInWorld((CommandSourceStack) commandcontext.getSource(), Vec3Argument.getVec3(commandcontext, "targetPos"), list, commandloot_a); ++ }))); + } + + private static Container getContainer(CommandSourceStack source, BlockPos pos) throws CommandSyntaxException { +- BlockEntity blockEntity = source.getLevel().getBlockEntity(pos); +- if (!(blockEntity instanceof Container)) { ++ BlockEntity tileentity = source.getLevel().getBlockEntity(pos); ++ ++ if (!(tileentity instanceof Container)) { + throw ItemCommands.ERROR_TARGET_NOT_A_CONTAINER.create(pos.getX(), pos.getY(), pos.getZ()); + } else { +- return (Container)blockEntity; ++ return (Container) tileentity; + } + } + + private static int blockDistribute(CommandSourceStack source, BlockPos pos, List items, LootCommand.Callback callback) throws CommandSyntaxException { +- Container container = getContainer(source, pos); +- List list = Lists.newArrayListWithCapacity(items.size()); ++ Container iinventory = getContainer(source, pos); ++ List list1 = Lists.newArrayListWithCapacity(items.size()); ++ Iterator iterator = items.iterator(); + +- for (ItemStack itemStack : items) { +- if (distributeToContainer(container, itemStack.copy())) { +- container.setChanged(); +- list.add(itemStack); ++ while (iterator.hasNext()) { ++ ItemStack itemstack = (ItemStack) iterator.next(); ++ ++ if (distributeToContainer(iinventory, itemstack.copy())) { ++ iinventory.setChanged(); ++ list1.add(itemstack); + } + } + +- callback.accept(list); +- return list.size(); ++ callback.accept(list1); ++ return list1.size(); + } + + private static boolean distributeToContainer(Container container, ItemStack item) { + boolean flag = false; + +- for (int i = 0; i < container.getContainerSize() && !item.isEmpty(); i++) { +- ItemStack item1 = container.getItem(i); ++ for (int i = 0; i < container.getContainerSize() && !item.isEmpty(); ++i) { ++ ItemStack itemstack1 = container.getItem(i); ++ + if (container.canPlaceItem(i, item)) { +- if (item1.isEmpty()) { ++ if (itemstack1.isEmpty()) { + container.setItem(i, item); + flag = true; + break; + } + +- if (canMergeItems(item1, item)) { +- int i1 = item.getMaxStackSize() - item1.getCount(); +- int min = Math.min(item.getCount(), i1); +- item.shrink(min); +- item1.grow(min); ++ if (canMergeItems(itemstack1, item)) { ++ int j = item.getMaxStackSize() - itemstack1.getCount(); ++ int k = Math.min(item.getCount(), j); ++ ++ item.shrink(k); ++ itemstack1.grow(k); + flag = true; + } + } +@@ -325,22 +163,24 @@ + } + + private static int blockReplace(CommandSourceStack source, BlockPos pos, int slot, int numSlots, List items, LootCommand.Callback callback) throws CommandSyntaxException { +- Container container = getContainer(source, pos); +- int containerSize = container.getContainerSize(); +- if (slot >= 0 && slot < containerSize) { +- List list = Lists.newArrayListWithCapacity(items.size()); ++ Container iinventory = getContainer(source, pos); ++ int k = iinventory.getContainerSize(); + +- for (int i = 0; i < numSlots; i++) { +- int i1 = slot + i; +- ItemStack itemStack = i < items.size() ? items.get(i) : ItemStack.EMPTY; +- if (container.canPlaceItem(i1, itemStack)) { +- container.setItem(i1, itemStack); +- list.add(itemStack); ++ if (slot >= 0 && slot < k) { ++ List list1 = Lists.newArrayListWithCapacity(items.size()); ++ ++ for (int l = 0; l < numSlots; ++l) { ++ int i1 = slot + l; ++ ItemStack itemstack = l < items.size() ? (ItemStack) items.get(l) : ItemStack.EMPTY; ++ ++ if (iinventory.canPlaceItem(i1, itemstack)) { ++ iinventory.setItem(i1, itemstack); ++ list1.add(itemstack); + } + } + +- callback.accept(list); +- return list.size(); ++ callback.accept(list1); ++ return list1.size(); + } else { + throw ItemCommands.ERROR_TARGET_INAPPLICABLE_SLOT.create(slot); + } +@@ -351,52 +191,68 @@ + } + + private static int playerGive(Collection targets, List items, LootCommand.Callback callback) throws CommandSyntaxException { +- List list = Lists.newArrayListWithCapacity(items.size()); ++ List list1 = Lists.newArrayListWithCapacity(items.size()); ++ Iterator iterator = items.iterator(); + +- for (ItemStack itemStack : items) { +- for (ServerPlayer serverPlayer : targets) { +- if (serverPlayer.getInventory().add(itemStack.copy())) { +- list.add(itemStack); ++ while (iterator.hasNext()) { ++ ItemStack itemstack = (ItemStack) iterator.next(); ++ Iterator iterator1 = targets.iterator(); ++ ++ while (iterator1.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator1.next(); ++ ++ if (entityplayer.getInventory().add(itemstack.copy())) { ++ list1.add(itemstack); + } + } + } + +- callback.accept(list); +- return list.size(); ++ callback.accept(list1); ++ return list1.size(); + } + + private static void setSlots(Entity target, List items, int startSlot, int numSlots, List setItems) { +- for (int i = 0; i < numSlots; i++) { +- ItemStack itemStack = i < items.size() ? items.get(i) : ItemStack.EMPTY; +- SlotAccess slot = target.getSlot(startSlot + i); +- if (slot != SlotAccess.NULL && slot.set(itemStack.copy())) { +- setItems.add(itemStack); ++ for (int k = 0; k < numSlots; ++k) { ++ ItemStack itemstack = k < items.size() ? (ItemStack) items.get(k) : ItemStack.EMPTY; ++ SlotAccess slotaccess = target.getSlot(startSlot + k); ++ ++ if (slotaccess != SlotAccess.NULL && slotaccess.set(itemstack.copy())) { ++ setItems.add(itemstack); + } + } ++ + } + + private static int entityReplace(Collection targets, int startSlot, int numSlots, List items, LootCommand.Callback callback) throws CommandSyntaxException { +- List list = Lists.newArrayListWithCapacity(items.size()); ++ List list1 = Lists.newArrayListWithCapacity(items.size()); ++ Iterator iterator = targets.iterator(); + +- for (Entity entity : targets) { +- if (entity instanceof ServerPlayer serverPlayer) { +- setSlots(entity, items, startSlot, numSlots, list); +- serverPlayer.containerMenu.broadcastChanges(); ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ ++ if (entity instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entity; ++ ++ setSlots(entity, items, startSlot, numSlots, list1); ++ entityplayer.containerMenu.broadcastChanges(); + } else { +- setSlots(entity, items, startSlot, numSlots, list); ++ setSlots(entity, items, startSlot, numSlots, list1); + } + } + +- callback.accept(list); +- return list.size(); ++ callback.accept(list1); ++ return list1.size(); + } + + private static int dropInWorld(CommandSourceStack source, Vec3 pos, List items, LootCommand.Callback callback) throws CommandSyntaxException { +- ServerLevel level = source.getLevel(); +- items.forEach(itemStack -> { +- ItemEntity itemEntity = new ItemEntity(level, pos.x, pos.y, pos.z, itemStack.copy()); +- itemEntity.setDefaultPickUpDelay(); +- level.addFreshEntity(itemEntity); ++ ServerLevel worldserver = source.getLevel(); ++ ++ items.removeIf(ItemStack::isEmpty); // CraftBukkit - SPIGOT-6959 Remove empty items for avoid throw an error in new EntityItem ++ items.forEach((itemstack) -> { ++ ItemEntity entityitem = new ItemEntity(worldserver, pos.x, pos.y, pos.z, itemstack.copy()); ++ ++ entityitem.setDefaultPickUpDelay(); ++ worldserver.addFreshEntity(entityitem); + }); + callback.accept(items); + return items.size(); +@@ -404,117 +260,126 @@ + + private static void callback(CommandSourceStack source, List items) { + if (items.size() == 1) { +- ItemStack itemStack = items.get(0); +- source.sendSuccess(() -> Component.translatable("commands.drop.success.single", itemStack.getCount(), itemStack.getDisplayName()), false); ++ ItemStack itemstack = (ItemStack) items.get(0); ++ ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.drop.success.single", itemstack.getCount(), itemstack.getDisplayName()); ++ }, false); + } else { +- source.sendSuccess(() -> Component.translatable("commands.drop.success.multiple", items.size()), false); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.drop.success.multiple", items.size()); ++ }, false); + } ++ + } + + private static void callback(CommandSourceStack source, List items, ResourceLocation lootTable) { + if (items.size() == 1) { +- ItemStack itemStack = items.get(0); +- source.sendSuccess( +- () -> Component.translatable( +- "commands.drop.success.single_with_table", itemStack.getCount(), itemStack.getDisplayName(), Component.translationArg(lootTable) +- ), +- false +- ); ++ ItemStack itemstack = (ItemStack) items.get(0); ++ ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.drop.success.single_with_table", itemstack.getCount(), itemstack.getDisplayName(), Component.translationArg(lootTable)); ++ }, false); + } else { +- source.sendSuccess( +- () -> Component.translatable("commands.drop.success.multiple_with_table", items.size(), Component.translationArg(lootTable)), false +- ); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.drop.success.multiple_with_table", items.size(), Component.translationArg(lootTable)); ++ }, false); + } ++ + } + + private static ItemStack getSourceHandItem(CommandSourceStack source, EquipmentSlot slot) throws CommandSyntaxException { +- Entity entityOrException = source.getEntityOrException(); +- if (entityOrException instanceof LivingEntity) { +- return ((LivingEntity)entityOrException).getItemBySlot(slot); ++ Entity entity = source.getEntityOrException(); ++ ++ if (entity instanceof LivingEntity) { ++ return ((LivingEntity) entity).getItemBySlot(slot); + } else { +- throw ERROR_NO_HELD_ITEMS.create(entityOrException.getDisplayName()); ++ throw LootCommand.ERROR_NO_HELD_ITEMS.create(entity.getDisplayName()); + } + } + + private static int dropBlockLoot(CommandContext context, BlockPos pos, ItemStack tool, LootCommand.DropConsumer dropConsumer) throws CommandSyntaxException { +- CommandSourceStack commandSourceStack = context.getSource(); +- ServerLevel level = commandSourceStack.getLevel(); +- BlockState blockState = level.getBlockState(pos); +- BlockEntity blockEntity = level.getBlockEntity(pos); +- LootParams.Builder builder = new LootParams.Builder(level) +- .withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos)) +- .withParameter(LootContextParams.BLOCK_STATE, blockState) +- .withOptionalParameter(LootContextParams.BLOCK_ENTITY, blockEntity) +- .withOptionalParameter(LootContextParams.THIS_ENTITY, commandSourceStack.getEntity()) +- .withParameter(LootContextParams.TOOL, tool); +- List drops = blockState.getDrops(builder); +- return dropConsumer.accept(context, drops, itemsDropped -> callback(commandSourceStack, itemsDropped, blockState.getBlock().getLootTable())); ++ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) context.getSource(); ++ ServerLevel worldserver = commandlistenerwrapper.getLevel(); ++ IBlockData iblockdata = worldserver.getBlockState(pos); ++ BlockEntity tileentity = worldserver.getBlockEntity(pos); ++ LootParams.Builder lootparams_a = (new LootParams.Builder(worldserver)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos)).withParameter(LootContextParams.BLOCK_STATE, iblockdata).withOptionalParameter(LootContextParams.BLOCK_ENTITY, tileentity).withOptionalParameter(LootContextParams.THIS_ENTITY, commandlistenerwrapper.getEntity()).withParameter(LootContextParams.TOOL, tool); ++ List list = iblockdata.getDrops(lootparams_a); ++ ++ return dropConsumer.accept(context, list, (list1) -> { ++ callback(commandlistenerwrapper, list1, iblockdata.getBlock().getLootTable()); ++ }); + } + + private static int dropKillLoot(CommandContext context, Entity entity, LootCommand.DropConsumer dropConsumer) throws CommandSyntaxException { + if (!(entity instanceof LivingEntity)) { +- throw ERROR_NO_LOOT_TABLE.create(entity.getDisplayName()); ++ throw LootCommand.ERROR_NO_LOOT_TABLE.create(entity.getDisplayName()); + } else { +- ResourceLocation lootTable = ((LivingEntity)entity).getLootTable(); +- CommandSourceStack commandSourceStack = context.getSource(); +- LootParams.Builder builder = new LootParams.Builder(commandSourceStack.getLevel()); +- Entity entity1 = commandSourceStack.getEntity(); +- if (entity1 instanceof Player player) { +- builder.withParameter(LootContextParams.LAST_DAMAGE_PLAYER, player); ++ ResourceLocation minecraftkey = ((LivingEntity) entity).getLootTable(); ++ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) context.getSource(); ++ LootParams.Builder lootparams_a = new LootParams.Builder(commandlistenerwrapper.getLevel()); ++ Entity entity1 = commandlistenerwrapper.getEntity(); ++ ++ if (entity1 instanceof Player) { ++ Player entityhuman = (Player) entity1; ++ ++ lootparams_a.withParameter(LootContextParams.LAST_DAMAGE_PLAYER, entityhuman); + } + +- builder.withParameter(LootContextParams.DAMAGE_SOURCE, entity.damageSources().magic()); +- builder.withOptionalParameter(LootContextParams.DIRECT_KILLER_ENTITY, entity1); +- builder.withOptionalParameter(LootContextParams.KILLER_ENTITY, entity1); +- builder.withParameter(LootContextParams.THIS_ENTITY, entity); +- builder.withParameter(LootContextParams.ORIGIN, commandSourceStack.getPosition()); +- LootParams lootParams = builder.create(LootContextParamSets.ENTITY); +- LootTable lootTable1 = commandSourceStack.getServer().getLootData().getLootTable(lootTable); +- List randomItems = lootTable1.getRandomItems(lootParams); +- return dropConsumer.accept(context, randomItems, itemsDropped -> callback(commandSourceStack, itemsDropped, lootTable)); ++ lootparams_a.withParameter(LootContextParams.DAMAGE_SOURCE, entity.damageSources().magic()); ++ lootparams_a.withOptionalParameter(LootContextParams.DIRECT_KILLER_ENTITY, entity1); ++ lootparams_a.withOptionalParameter(LootContextParams.KILLER_ENTITY, entity1); ++ lootparams_a.withParameter(LootContextParams.THIS_ENTITY, entity); ++ lootparams_a.withParameter(LootContextParams.ORIGIN, commandlistenerwrapper.getPosition()); ++ LootParams lootparams = lootparams_a.create(LootContextParamSets.ENTITY); ++ LootTable loottable = commandlistenerwrapper.getServer().getLootData().getLootTable(minecraftkey); ++ List list = loottable.getRandomItems(lootparams); ++ ++ return dropConsumer.accept(context, list, (list1) -> { ++ callback(commandlistenerwrapper, list1, minecraftkey); ++ }); + } + } + + private static int dropChestLoot(CommandContext context, ResourceLocation lootTable, LootCommand.DropConsumer dropConsumer) throws CommandSyntaxException { +- CommandSourceStack commandSourceStack = context.getSource(); +- LootParams lootParams = new LootParams.Builder(commandSourceStack.getLevel()) +- .withOptionalParameter(LootContextParams.THIS_ENTITY, commandSourceStack.getEntity()) +- .withParameter(LootContextParams.ORIGIN, commandSourceStack.getPosition()) +- .create(LootContextParamSets.CHEST); +- return drop(context, lootTable, lootParams, dropConsumer); ++ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) context.getSource(); ++ LootParams lootparams = (new LootParams.Builder(commandlistenerwrapper.getLevel())).withOptionalParameter(LootContextParams.THIS_ENTITY, commandlistenerwrapper.getEntity()).withParameter(LootContextParams.ORIGIN, commandlistenerwrapper.getPosition()).create(LootContextParamSets.CHEST); ++ ++ return drop(context, lootTable, lootparams, dropConsumer); + } + +- private static int dropFishingLoot( +- CommandContext context, ResourceLocation lootTable, BlockPos pos, ItemStack tool, LootCommand.DropConsumer dropConsumer +- ) throws CommandSyntaxException { +- CommandSourceStack commandSourceStack = context.getSource(); +- LootParams lootParams = new LootParams.Builder(commandSourceStack.getLevel()) +- .withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos)) +- .withParameter(LootContextParams.TOOL, tool) +- .withOptionalParameter(LootContextParams.THIS_ENTITY, commandSourceStack.getEntity()) +- .create(LootContextParamSets.FISHING); +- return drop(context, lootTable, lootParams, dropConsumer); ++ private static int dropFishingLoot(CommandContext context, ResourceLocation lootTable, BlockPos pos, ItemStack tool, LootCommand.DropConsumer dropConsumer) throws CommandSyntaxException { ++ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) context.getSource(); ++ LootParams lootparams = (new LootParams.Builder(commandlistenerwrapper.getLevel())).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos)).withParameter(LootContextParams.TOOL, tool).withOptionalParameter(LootContextParams.THIS_ENTITY, commandlistenerwrapper.getEntity()).create(LootContextParamSets.FISHING); ++ ++ return drop(context, lootTable, lootparams, dropConsumer); + } + + private static int drop(CommandContext context, ResourceLocation lootTable, LootParams params, LootCommand.DropConsumer dropConsumer) throws CommandSyntaxException { +- CommandSourceStack commandSourceStack = context.getSource(); +- LootTable lootTable1 = commandSourceStack.getServer().getLootData().getLootTable(lootTable); +- List randomItems = lootTable1.getRandomItems(params); +- return dropConsumer.accept(context, randomItems, itemsDropped -> callback(commandSourceStack, itemsDropped)); ++ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) context.getSource(); ++ LootTable loottable = commandlistenerwrapper.getServer().getLootData().getLootTable(lootTable); ++ List list = loottable.getRandomItems(params); ++ ++ return dropConsumer.accept(context, list, (list1) -> { ++ callback(commandlistenerwrapper, list1); ++ }); + } + + @FunctionalInterface +- interface Callback { +- void accept(List items) throws CommandSyntaxException; ++ private interface TailProvider { ++ ++ ArgumentBuilder construct(ArgumentBuilder builder, LootCommand.DropConsumer dropConsumer); + } + + @FunctionalInterface +- interface DropConsumer { ++ private interface DropConsumer { ++ + int accept(CommandContext context, List items, LootCommand.Callback callback) throws CommandSyntaxException; + } + + @FunctionalInterface +- interface TailProvider { +- ArgumentBuilder construct(ArgumentBuilder builder, LootCommand.DropConsumer dropConsumer); ++ private interface Callback { ++ ++ void accept(List items) throws CommandSyntaxException; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/commands/PlaceCommand.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/commands/PlaceCommand.java.patch new file mode 100644 index 0000000000..feea12601a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/commands/PlaceCommand.java.patch @@ -0,0 +1,437 @@ +--- a/net/minecraft/server/commands/PlaceCommand.java ++++ b/net/minecraft/server/commands/PlaceCommand.java +@@ -3,16 +3,15 @@ + import com.mojang.brigadier.CommandDispatcher; + import com.mojang.brigadier.arguments.FloatArgumentType; + import com.mojang.brigadier.arguments.IntegerArgumentType; +-import com.mojang.brigadier.context.CommandContext; ++import com.mojang.brigadier.builder.LiteralArgumentBuilder; ++import com.mojang.brigadier.builder.RequiredArgumentBuilder; + import com.mojang.brigadier.exceptions.CommandSyntaxException; + import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; + import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; + import com.mojang.brigadier.suggestion.SuggestionProvider; +-import com.mojang.brigadier.suggestion.SuggestionsBuilder; + import java.util.Optional; + import net.minecraft.ResourceLocationException; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.SharedSuggestionProvider; + import net.minecraft.commands.arguments.ResourceKeyArgument; + import net.minecraft.commands.arguments.ResourceLocationArgument; +@@ -43,309 +42,153 @@ + import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; + + public class PlaceCommand { +- private static final SimpleCommandExceptionType ERROR_FEATURE_FAILED = new SimpleCommandExceptionType( +- Component.translatable("commands.place.feature.failed") +- ); ++ ++ private static final SimpleCommandExceptionType ERROR_FEATURE_FAILED = new SimpleCommandExceptionType(Component.translatable("commands.place.feature.failed")); + private static final SimpleCommandExceptionType ERROR_JIGSAW_FAILED = new SimpleCommandExceptionType(Component.translatable("commands.place.jigsaw.failed")); +- private static final SimpleCommandExceptionType ERROR_STRUCTURE_FAILED = new SimpleCommandExceptionType( +- Component.translatable("commands.place.structure.failed") +- ); +- private static final DynamicCommandExceptionType ERROR_TEMPLATE_INVALID = new DynamicCommandExceptionType( +- template -> Component.translatableEscape("commands.place.template.invalid", template) +- ); +- private static final SimpleCommandExceptionType ERROR_TEMPLATE_FAILED = new SimpleCommandExceptionType( +- Component.translatable("commands.place.template.failed") +- ); +- private static final SuggestionProvider SUGGEST_TEMPLATES = (context, builder) -> { +- StructureTemplateManager structureManager = context.getSource().getLevel().getStructureManager(); +- return SharedSuggestionProvider.suggestResource(structureManager.listTemplates(), builder); ++ private static final SimpleCommandExceptionType ERROR_STRUCTURE_FAILED = new SimpleCommandExceptionType(Component.translatable("commands.place.structure.failed")); ++ private static final DynamicCommandExceptionType ERROR_TEMPLATE_INVALID = new DynamicCommandExceptionType((object) -> { ++ return Component.translatableEscape("commands.place.template.invalid", object); ++ }); ++ private static final SimpleCommandExceptionType ERROR_TEMPLATE_FAILED = new SimpleCommandExceptionType(Component.translatable("commands.place.template.failed")); ++ private static final SuggestionProvider SUGGEST_TEMPLATES = (commandcontext, suggestionsbuilder) -> { ++ StructureTemplateManager structuretemplatemanager = ((CommandSourceStack) commandcontext.getSource()).getLevel().getStructureManager(); ++ ++ return SharedSuggestionProvider.suggestResource(structuretemplatemanager.listTemplates(), suggestionsbuilder); + }; + ++ public PlaceCommand() {} ++ + public static void register(CommandDispatcher dispatcher) { +- dispatcher.register( +- Commands.literal("place") +- .requires(source -> source.hasPermission(2)) +- .then( +- Commands.literal("feature") +- .then( +- Commands.argument("feature", ResourceKeyArgument.key(Registries.CONFIGURED_FEATURE)) +- .executes( +- context -> placeFeature( +- context.getSource(), +- ResourceKeyArgument.getConfiguredFeature(context, "feature"), +- BlockPos.containing(context.getSource().getPosition()) +- ) +- ) +- .then( +- Commands.argument("pos", BlockPosArgument.blockPos()) +- .executes( +- context -> placeFeature( +- context.getSource(), +- ResourceKeyArgument.getConfiguredFeature(context, "feature"), +- BlockPosArgument.getLoadedBlockPos(context, "pos") +- ) +- ) +- ) +- ) +- ) +- .then( +- Commands.literal("jigsaw") +- .then( +- Commands.argument("pool", ResourceKeyArgument.key(Registries.TEMPLATE_POOL)) +- .then( +- Commands.argument("target", ResourceLocationArgument.id()) +- .then( +- Commands.argument("max_depth", IntegerArgumentType.integer(1, 7)) +- .executes( +- context -> placeJigsaw( +- context.getSource(), +- ResourceKeyArgument.getStructureTemplatePool(context, "pool"), +- ResourceLocationArgument.getId(context, "target"), +- IntegerArgumentType.getInteger(context, "max_depth"), +- BlockPos.containing(context.getSource().getPosition()) +- ) +- ) +- .then( +- Commands.argument("position", BlockPosArgument.blockPos()) +- .executes( +- context -> placeJigsaw( +- context.getSource(), +- ResourceKeyArgument.getStructureTemplatePool(context, "pool"), +- ResourceLocationArgument.getId(context, "target"), +- IntegerArgumentType.getInteger(context, "max_depth"), +- BlockPosArgument.getLoadedBlockPos(context, "position") +- ) +- ) +- ) +- ) +- ) +- ) +- ) +- .then( +- Commands.literal("structure") +- .then( +- Commands.argument("structure", ResourceKeyArgument.key(Registries.STRUCTURE)) +- .executes( +- context -> placeStructure( +- context.getSource(), +- ResourceKeyArgument.getStructure(context, "structure"), +- BlockPos.containing(context.getSource().getPosition()) +- ) +- ) +- .then( +- Commands.argument("pos", BlockPosArgument.blockPos()) +- .executes( +- context -> placeStructure( +- context.getSource(), +- ResourceKeyArgument.getStructure(context, "structure"), +- BlockPosArgument.getLoadedBlockPos(context, "pos") +- ) +- ) +- ) +- ) +- ) +- .then( +- Commands.literal("template") +- .then( +- Commands.argument("template", ResourceLocationArgument.id()) +- .suggests(SUGGEST_TEMPLATES) +- .executes( +- context -> placeTemplate( +- context.getSource(), +- ResourceLocationArgument.getId(context, "template"), +- BlockPos.containing(context.getSource().getPosition()), +- Rotation.NONE, +- Mirror.NONE, +- 1.0F, +- 0 +- ) +- ) +- .then( +- Commands.argument("pos", BlockPosArgument.blockPos()) +- .executes( +- context -> placeTemplate( +- context.getSource(), +- ResourceLocationArgument.getId(context, "template"), +- BlockPosArgument.getLoadedBlockPos(context, "pos"), +- Rotation.NONE, +- Mirror.NONE, +- 1.0F, +- 0 +- ) +- ) +- .then( +- Commands.argument("rotation", TemplateRotationArgument.templateRotation()) +- .executes( +- context -> placeTemplate( +- context.getSource(), +- ResourceLocationArgument.getId(context, "template"), +- BlockPosArgument.getLoadedBlockPos(context, "pos"), +- TemplateRotationArgument.getRotation(context, "rotation"), +- Mirror.NONE, +- 1.0F, +- 0 +- ) +- ) +- .then( +- Commands.argument("mirror", TemplateMirrorArgument.templateMirror()) +- .executes( +- context -> placeTemplate( +- context.getSource(), +- ResourceLocationArgument.getId(context, "template"), +- BlockPosArgument.getLoadedBlockPos(context, "pos"), +- TemplateRotationArgument.getRotation(context, "rotation"), +- TemplateMirrorArgument.getMirror(context, "mirror"), +- 1.0F, +- 0 +- ) +- ) +- .then( +- Commands.argument("integrity", FloatArgumentType.floatArg(0.0F, 1.0F)) +- .executes( +- context -> placeTemplate( +- context.getSource(), +- ResourceLocationArgument.getId(context, "template"), +- BlockPosArgument.getLoadedBlockPos(context, "pos"), +- TemplateRotationArgument.getRotation(context, "rotation"), +- TemplateMirrorArgument.getMirror(context, "mirror"), +- FloatArgumentType.getFloat(context, "integrity"), +- 0 +- ) +- ) +- .then( +- Commands.argument("seed", IntegerArgumentType.integer()) +- .executes( +- context -> placeTemplate( +- context.getSource(), +- ResourceLocationArgument.getId(context, "template"), +- BlockPosArgument.getLoadedBlockPos(context, "pos"), +- TemplateRotationArgument.getRotation(context, "rotation"), +- TemplateMirrorArgument.getMirror(context, "mirror"), +- FloatArgumentType.getFloat(context, "integrity"), +- IntegerArgumentType.getInteger(context, "seed") +- ) +- ) +- ) +- ) +- ) +- ) +- ) +- ) +- ) +- ); ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("place").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).then(net.minecraft.commands.Commands.literal("feature").then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("feature", ResourceKeyArgument.key(Registries.CONFIGURED_FEATURE)).executes((commandcontext) -> { ++ return placeFeature((CommandSourceStack) commandcontext.getSource(), ResourceKeyArgument.getConfiguredFeature(commandcontext, "feature"), BlockPos.containing(((CommandSourceStack) commandcontext.getSource()).getPosition())); ++ })).then(net.minecraft.commands.Commands.argument("pos", BlockPosArgument.blockPos()).executes((commandcontext) -> { ++ return placeFeature((CommandSourceStack) commandcontext.getSource(), ResourceKeyArgument.getConfiguredFeature(commandcontext, "feature"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos")); ++ }))))).then(net.minecraft.commands.Commands.literal("jigsaw").then(net.minecraft.commands.Commands.argument("pool", ResourceKeyArgument.key(Registries.TEMPLATE_POOL)).then(net.minecraft.commands.Commands.argument("target", ResourceLocationArgument.id()).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("max_depth", IntegerArgumentType.integer(1, 7)).executes((commandcontext) -> { ++ return placeJigsaw((CommandSourceStack) commandcontext.getSource(), ResourceKeyArgument.getStructureTemplatePool(commandcontext, "pool"), ResourceLocationArgument.getId(commandcontext, "target"), IntegerArgumentType.getInteger(commandcontext, "max_depth"), BlockPos.containing(((CommandSourceStack) commandcontext.getSource()).getPosition())); ++ })).then(net.minecraft.commands.Commands.argument("position", BlockPosArgument.blockPos()).executes((commandcontext) -> { ++ return placeJigsaw((CommandSourceStack) commandcontext.getSource(), ResourceKeyArgument.getStructureTemplatePool(commandcontext, "pool"), ResourceLocationArgument.getId(commandcontext, "target"), IntegerArgumentType.getInteger(commandcontext, "max_depth"), BlockPosArgument.getLoadedBlockPos(commandcontext, "position")); ++ }))))))).then(net.minecraft.commands.Commands.literal("structure").then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("structure", ResourceKeyArgument.key(Registries.STRUCTURE)).executes((commandcontext) -> { ++ return placeStructure((CommandSourceStack) commandcontext.getSource(), ResourceKeyArgument.getStructure(commandcontext, "structure"), BlockPos.containing(((CommandSourceStack) commandcontext.getSource()).getPosition())); ++ })).then(net.minecraft.commands.Commands.argument("pos", BlockPosArgument.blockPos()).executes((commandcontext) -> { ++ return placeStructure((CommandSourceStack) commandcontext.getSource(), ResourceKeyArgument.getStructure(commandcontext, "structure"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos")); ++ }))))).then(net.minecraft.commands.Commands.literal("template").then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("template", ResourceLocationArgument.id()).suggests(PlaceCommand.SUGGEST_TEMPLATES).executes((commandcontext) -> { ++ return placeTemplate((CommandSourceStack) commandcontext.getSource(), ResourceLocationArgument.getId(commandcontext, "template"), BlockPos.containing(((CommandSourceStack) commandcontext.getSource()).getPosition()), Rotation.NONE, Mirror.NONE, 1.0F, 0); ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("pos", BlockPosArgument.blockPos()).executes((commandcontext) -> { ++ return placeTemplate((CommandSourceStack) commandcontext.getSource(), ResourceLocationArgument.getId(commandcontext, "template"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), Rotation.NONE, Mirror.NONE, 1.0F, 0); ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("rotation", TemplateRotationArgument.templateRotation()).executes((commandcontext) -> { ++ return placeTemplate((CommandSourceStack) commandcontext.getSource(), ResourceLocationArgument.getId(commandcontext, "template"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), TemplateRotationArgument.getRotation(commandcontext, "rotation"), Mirror.NONE, 1.0F, 0); ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("mirror", TemplateMirrorArgument.templateMirror()).executes((commandcontext) -> { ++ return placeTemplate((CommandSourceStack) commandcontext.getSource(), ResourceLocationArgument.getId(commandcontext, "template"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), TemplateRotationArgument.getRotation(commandcontext, "rotation"), TemplateMirrorArgument.getMirror(commandcontext, "mirror"), 1.0F, 0); ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("integrity", FloatArgumentType.floatArg(0.0F, 1.0F)).executes((commandcontext) -> { ++ return placeTemplate((CommandSourceStack) commandcontext.getSource(), ResourceLocationArgument.getId(commandcontext, "template"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), TemplateRotationArgument.getRotation(commandcontext, "rotation"), TemplateMirrorArgument.getMirror(commandcontext, "mirror"), FloatArgumentType.getFloat(commandcontext, "integrity"), 0); ++ })).then(net.minecraft.commands.Commands.argument("seed", IntegerArgumentType.integer()).executes((commandcontext) -> { ++ return placeTemplate((CommandSourceStack) commandcontext.getSource(), ResourceLocationArgument.getId(commandcontext, "template"), BlockPosArgument.getLoadedBlockPos(commandcontext, "pos"), TemplateRotationArgument.getRotation(commandcontext, "rotation"), TemplateMirrorArgument.getMirror(commandcontext, "mirror"), FloatArgumentType.getFloat(commandcontext, "integrity"), IntegerArgumentType.getInteger(commandcontext, "seed")); ++ }))))))))); + } + + public static int placeFeature(CommandSourceStack source, Holder.Reference> feature, BlockPos pos) throws CommandSyntaxException { +- ServerLevel level = source.getLevel(); +- ConfiguredFeature configuredFeature = feature.value(); +- ChunkPos chunkPos = new ChunkPos(pos); +- checkLoaded(level, new ChunkPos(chunkPos.x - 1, chunkPos.z - 1), new ChunkPos(chunkPos.x + 1, chunkPos.z + 1)); +- if (!configuredFeature.place(level, level.getChunkSource().getGenerator(), level.getRandom(), pos)) { +- throw ERROR_FEATURE_FAILED.create(); ++ ServerLevel worldserver = source.getLevel(); ++ ConfiguredFeature worldgenfeatureconfigured = (ConfiguredFeature) feature.value(); ++ ChunkPos chunkcoordintpair = new ChunkPos(pos); ++ ++ checkLoaded(worldserver, new ChunkPos(chunkcoordintpair.x - 1, chunkcoordintpair.z - 1), new ChunkPos(chunkcoordintpair.x + 1, chunkcoordintpair.z + 1)); ++ if (!worldgenfeatureconfigured.place(worldserver, worldserver.getChunkSource().getGenerator(), worldserver.getRandom(), pos)) { ++ throw PlaceCommand.ERROR_FEATURE_FAILED.create(); + } else { +- String string = feature.key().location().toString(); +- source.sendSuccess(() -> Component.translatable("commands.place.feature.success", string, pos.getX(), pos.getY(), pos.getZ()), true); ++ String s = feature.key().location().toString(); ++ ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.place.feature.success", s, pos.getX(), pos.getY(), pos.getZ()); ++ }, true); + return 1; + } + } + + public static int placeJigsaw(CommandSourceStack source, Holder templatePool, ResourceLocation target, int maxDepth, BlockPos pos) throws CommandSyntaxException { +- ServerLevel level = source.getLevel(); +- if (!JigsawPlacement.generateJigsaw(level, templatePool, target, maxDepth, pos, false)) { +- throw ERROR_JIGSAW_FAILED.create(); ++ ServerLevel worldserver = source.getLevel(); ++ ++ if (!JigsawPlacement.generateJigsaw(worldserver, templatePool, target, maxDepth, pos, false)) { ++ throw PlaceCommand.ERROR_JIGSAW_FAILED.create(); + } else { +- source.sendSuccess(() -> Component.translatable("commands.place.jigsaw.success", pos.getX(), pos.getY(), pos.getZ()), true); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.place.jigsaw.success", pos.getX(), pos.getY(), pos.getZ()); ++ }, true); + return 1; + } + } + + public static int placeStructure(CommandSourceStack source, Holder.Reference structure, BlockPos pos) throws CommandSyntaxException { +- ServerLevel level = source.getLevel(); +- Structure structure1 = structure.value(); +- ChunkGenerator generator = level.getChunkSource().getGenerator(); +- StructureStart structureStart = structure1.generate( +- source.registryAccess(), +- generator, +- generator.getBiomeSource(), +- level.getChunkSource().randomState(), +- level.getStructureManager(), +- level.getSeed(), +- new ChunkPos(pos), +- 0, +- level, +- biome -> true +- ); +- if (!structureStart.isValid()) { +- throw ERROR_STRUCTURE_FAILED.create(); ++ ServerLevel worldserver = source.getLevel(); ++ Structure structure1 = (Structure) structure.value(); ++ ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator(); ++ StructureStart structurestart = structure1.generate(source.registryAccess(), chunkgenerator, chunkgenerator.getBiomeSource(), worldserver.getChunkSource().randomState(), worldserver.getStructureManager(), worldserver.getSeed(), new ChunkPos(pos), 0, worldserver, (holder) -> { ++ return true; ++ }); ++ ++ if (!structurestart.isValid()) { ++ throw PlaceCommand.ERROR_STRUCTURE_FAILED.create(); + } else { +- BoundingBox boundingBox = structureStart.getBoundingBox(); +- ChunkPos chunkPos = new ChunkPos(SectionPos.blockToSectionCoord(boundingBox.minX()), SectionPos.blockToSectionCoord(boundingBox.minZ())); +- ChunkPos chunkPos1 = new ChunkPos(SectionPos.blockToSectionCoord(boundingBox.maxX()), SectionPos.blockToSectionCoord(boundingBox.maxZ())); +- checkLoaded(level, chunkPos, chunkPos1); +- ChunkPos.rangeClosed(chunkPos, chunkPos1) +- .forEach( +- chunkPos2 -> structureStart.placeInChunk( +- level, +- level.structureManager(), +- generator, +- level.getRandom(), +- new BoundingBox( +- chunkPos2.getMinBlockX(), +- level.getMinBuildHeight(), +- chunkPos2.getMinBlockZ(), +- chunkPos2.getMaxBlockX(), +- level.getMaxBuildHeight(), +- chunkPos2.getMaxBlockZ() +- ), +- chunkPos2 +- ) +- ); +- String string = structure.key().location().toString(); +- source.sendSuccess(() -> Component.translatable("commands.place.structure.success", string, pos.getX(), pos.getY(), pos.getZ()), true); ++ structurestart.generationEventCause = org.bukkit.event.world.AsyncStructureGenerateEvent.Cause.COMMAND; // CraftBukkit - set AsyncStructureGenerateEvent.Cause.COMMAND as generation cause ++ BoundingBox structureboundingbox = structurestart.getBoundingBox(); ++ ChunkPos chunkcoordintpair = new ChunkPos(SectionPos.blockToSectionCoord(structureboundingbox.minX()), SectionPos.blockToSectionCoord(structureboundingbox.minZ())); ++ ChunkPos chunkcoordintpair1 = new ChunkPos(SectionPos.blockToSectionCoord(structureboundingbox.maxX()), SectionPos.blockToSectionCoord(structureboundingbox.maxZ())); ++ ++ checkLoaded(worldserver, chunkcoordintpair, chunkcoordintpair1); ++ ChunkPos.rangeClosed(chunkcoordintpair, chunkcoordintpair1).forEach((chunkcoordintpair2) -> { ++ structurestart.placeInChunk(worldserver, worldserver.structureManager(), chunkgenerator, worldserver.getRandom(), new BoundingBox(chunkcoordintpair2.getMinBlockX(), worldserver.getMinBuildHeight(), chunkcoordintpair2.getMinBlockZ(), chunkcoordintpair2.getMaxBlockX(), worldserver.getMaxBuildHeight(), chunkcoordintpair2.getMaxBlockZ()), chunkcoordintpair2); ++ }); ++ String s = structure.key().location().toString(); ++ ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.place.structure.success", s, pos.getX(), pos.getY(), pos.getZ()); ++ }, true); + return 1; + } + } + +- public static int placeTemplate( +- CommandSourceStack source, ResourceLocation template, BlockPos pos, Rotation rotation, Mirror mirror, float integrity, int seed +- ) throws CommandSyntaxException { +- ServerLevel level = source.getLevel(); +- StructureTemplateManager structureManager = level.getStructureManager(); ++ public static int placeTemplate(CommandSourceStack source, ResourceLocation template, BlockPos pos, Rotation rotation, Mirror mirror, float integrity, int seed) throws CommandSyntaxException { ++ ServerLevel worldserver = source.getLevel(); ++ StructureTemplateManager structuretemplatemanager = worldserver.getStructureManager(); + +- Optional optional; ++ Optional optional; ++ + try { +- optional = structureManager.get(template); +- } catch (ResourceLocationException var13) { +- throw ERROR_TEMPLATE_INVALID.create(template); ++ optional = structuretemplatemanager.get(template); ++ } catch (ResourceLocationException resourcekeyinvalidexception) { ++ throw PlaceCommand.ERROR_TEMPLATE_INVALID.create(template); + } + + if (optional.isEmpty()) { +- throw ERROR_TEMPLATE_INVALID.create(template); ++ throw PlaceCommand.ERROR_TEMPLATE_INVALID.create(template); + } else { +- StructureTemplate structureTemplate = optional.get(); +- checkLoaded(level, new ChunkPos(pos), new ChunkPos(pos.offset(structureTemplate.getSize()))); +- StructurePlaceSettings structurePlaceSettings = new StructurePlaceSettings().setMirror(mirror).setRotation(rotation); ++ StructureTemplate definedstructure = (StructureTemplate) optional.get(); ++ ++ checkLoaded(worldserver, new ChunkPos(pos), new ChunkPos(pos.offset(definedstructure.getSize()))); ++ StructurePlaceSettings definedstructureinfo = (new StructurePlaceSettings()).setMirror(mirror).setRotation(rotation); ++ + if (integrity < 1.0F) { +- structurePlaceSettings.clearProcessors() +- .addProcessor(new BlockRotProcessor(integrity)) +- .setRandom(StructureBlockEntity.createRandom((long)seed)); ++ definedstructureinfo.clearProcessors().addProcessor(new BlockRotProcessor(integrity)).setRandom(StructureBlockEntity.createRandom((long) seed)); + } + +- boolean flag = structureTemplate.placeInWorld(level, pos, pos, structurePlaceSettings, StructureBlockEntity.createRandom((long)seed), 2); ++ boolean flag = definedstructure.placeInWorld(worldserver, pos, pos, definedstructureinfo, StructureBlockEntity.createRandom((long) seed), 2); ++ + if (!flag) { +- throw ERROR_TEMPLATE_FAILED.create(); ++ throw PlaceCommand.ERROR_TEMPLATE_FAILED.create(); + } else { +- source.sendSuccess( +- () -> Component.translatable("commands.place.template.success", Component.translationArg(template), pos.getX(), pos.getY(), pos.getZ()), +- true +- ); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.place.template.success", Component.translationArg(template), pos.getX(), pos.getY(), pos.getZ()); ++ }, true); + return 1; + } + } + } + + private static void checkLoaded(ServerLevel level, ChunkPos start, ChunkPos end) throws CommandSyntaxException { +- if (ChunkPos.rangeClosed(start, end).filter(chunkPos -> !level.isLoaded(chunkPos.getWorldPosition())).findAny().isPresent()) { ++ if (ChunkPos.rangeClosed(start, end).filter((chunkcoordintpair2) -> { ++ return !level.isLoaded(chunkcoordintpair2.getWorldPosition()); ++ }).findAny().isPresent()) { + throw BlockPosArgument.ERROR_NOT_LOADED.create(); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/commands/ReloadCommand.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/commands/ReloadCommand.java.patch new file mode 100644 index 0000000000..5913a6accf --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/commands/ReloadCommand.java.patch @@ -0,0 +1,95 @@ +--- a/net/minecraft/server/commands/ReloadCommand.java ++++ b/net/minecraft/server/commands/ReloadCommand.java +@@ -2,11 +2,11 @@ + + import com.google.common.collect.Lists; + import com.mojang.brigadier.CommandDispatcher; +-import com.mojang.brigadier.context.CommandContext; ++import com.mojang.brigadier.builder.LiteralArgumentBuilder; + import com.mojang.logging.LogUtils; + import java.util.Collection; ++import java.util.Iterator; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.network.chat.Component; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.packs.repository.PackRepository; +@@ -14,11 +14,14 @@ + import org.slf4j.Logger; + + public class ReloadCommand { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + ++ public ReloadCommand() {} ++ + public static void reloadPacks(Collection selectedIds, CommandSourceStack source) { +- source.getServer().reloadResources(selectedIds).exceptionally(throwable -> { +- LOGGER.warn("Failed to execute reload", throwable); ++ source.getServer().reloadResources(selectedIds).exceptionally((throwable) -> { ++ ReloadCommand.LOGGER.warn("Failed to execute reload", throwable); + source.sendFailure(Component.translatable("commands.reload.failure")); + return null; + }); +@@ -26,28 +29,46 @@ + + private static Collection discoverNewPacks(PackRepository packRepository, WorldData worldData, Collection selectedIds) { + packRepository.reload(); +- Collection list = Lists.newArrayList(selectedIds); +- Collection disabled = worldData.getDataConfiguration().dataPacks().getDisabled(); ++ Collection collection1 = Lists.newArrayList(selectedIds); ++ Collection collection2 = worldData.getDataConfiguration().dataPacks().getDisabled(); ++ Iterator iterator = packRepository.getAvailableIds().iterator(); + +- for (String string : packRepository.getAvailableIds()) { +- if (!disabled.contains(string) && !list.contains(string)) { +- list.add(string); ++ while (iterator.hasNext()) { ++ String s = (String) iterator.next(); ++ ++ if (!collection2.contains(s) && !collection1.contains(s)) { ++ collection1.add(s); + } + } + +- return list; ++ return collection1; + } + ++ // CraftBukkit start ++ public static void reload(MinecraftServer minecraftserver) { ++ PackRepository resourcepackrepository = minecraftserver.getPackRepository(); ++ WorldData savedata = minecraftserver.getWorldData(); ++ Collection collection = resourcepackrepository.getSelectedIds(); ++ Collection collection1 = discoverNewPacks(resourcepackrepository, savedata, collection); ++ minecraftserver.reloadResources(collection1); ++ } ++ // CraftBukkit end ++ + public static void register(CommandDispatcher dispatcher) { +- dispatcher.register(Commands.literal("reload").requires(source -> source.hasPermission(2)).executes(context -> { +- CommandSourceStack commandSourceStack = context.getSource(); +- MinecraftServer server = commandSourceStack.getServer(); +- PackRepository packRepository = server.getPackRepository(); +- WorldData worldData = server.getWorldData(); +- Collection selectedIds = packRepository.getSelectedIds(); +- Collection collection = discoverNewPacks(packRepository, worldData, selectedIds); +- commandSourceStack.sendSuccess(() -> Component.translatable("commands.reload.success"), true); +- reloadPacks(collection, commandSourceStack); ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("reload").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).executes((commandcontext) -> { ++ CommandSourceStack commandlistenerwrapper = (CommandSourceStack) commandcontext.getSource(); ++ MinecraftServer minecraftserver = commandlistenerwrapper.getServer(); ++ PackRepository resourcepackrepository = minecraftserver.getPackRepository(); ++ WorldData savedata = minecraftserver.getWorldData(); ++ Collection collection = resourcepackrepository.getSelectedIds(); ++ Collection collection1 = discoverNewPacks(resourcepackrepository, savedata, collection); ++ ++ commandlistenerwrapper.sendSuccess(() -> { ++ return Component.translatable("commands.reload.success"); ++ }, true); ++ reloadPacks(collection1, commandlistenerwrapper); + return 0; + })); + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/commands/ScheduleCommand.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/commands/ScheduleCommand.java.patch new file mode 100644 index 0000000000..e63f3cfbfa --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/commands/ScheduleCommand.java.patch @@ -0,0 +1,196 @@ +--- a/net/minecraft/server/commands/ScheduleCommand.java ++++ b/net/minecraft/server/commands/ScheduleCommand.java +@@ -3,21 +3,19 @@ + import com.mojang.brigadier.CommandDispatcher; + import com.mojang.brigadier.arguments.IntegerArgumentType; + import com.mojang.brigadier.arguments.StringArgumentType; +-import com.mojang.brigadier.context.CommandContext; ++import com.mojang.brigadier.builder.LiteralArgumentBuilder; ++import com.mojang.brigadier.builder.RequiredArgumentBuilder; + import com.mojang.brigadier.exceptions.CommandSyntaxException; + import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; + import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; + import com.mojang.brigadier.suggestion.SuggestionProvider; +-import com.mojang.brigadier.suggestion.SuggestionsBuilder; + import com.mojang.datafixers.util.Either; + import com.mojang.datafixers.util.Pair; + import java.util.Collection; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.SharedSuggestionProvider; + import net.minecraft.commands.arguments.TimeArgument; + import net.minecraft.commands.arguments.item.FunctionArgument; +-import net.minecraft.commands.functions.CommandFunction; + import net.minecraft.network.chat.Component; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MinecraftServer; +@@ -26,114 +24,75 @@ + import net.minecraft.world.level.timers.TimerQueue; + + public class ScheduleCommand { ++ + private static final SimpleCommandExceptionType ERROR_SAME_TICK = new SimpleCommandExceptionType(Component.translatable("commands.schedule.same_tick")); +- private static final DynamicCommandExceptionType ERROR_CANT_REMOVE = new DynamicCommandExceptionType( +- functionName -> Component.translatableEscape("commands.schedule.cleared.failure", functionName) +- ); +- private static final SuggestionProvider SUGGEST_SCHEDULE = (context, builder) -> SharedSuggestionProvider.suggest( +- context.getSource().getServer().getWorldData().overworldData().getScheduledEvents().getEventsIds(), builder +- ); ++ private static final DynamicCommandExceptionType ERROR_CANT_REMOVE = new DynamicCommandExceptionType((object) -> { ++ return Component.translatableEscape("commands.schedule.cleared.failure", object); ++ }); ++ private static final SuggestionProvider SUGGEST_SCHEDULE = (commandcontext, suggestionsbuilder) -> { ++ return SharedSuggestionProvider.suggest((Iterable) ((CommandSourceStack) commandcontext.getSource()).getServer().getWorldData().overworldData().getScheduledEvents().getEventsIds(), suggestionsbuilder); ++ }; + ++ public ScheduleCommand() {} ++ + public static void register(CommandDispatcher dispatcher) { +- dispatcher.register( +- Commands.literal("schedule") +- .requires(source -> source.hasPermission(2)) +- .then( +- Commands.literal("function") +- .then( +- Commands.argument("function", FunctionArgument.functions()) +- .suggests(FunctionCommand.SUGGEST_FUNCTION) +- .then( +- Commands.argument("time", TimeArgument.time()) +- .executes( +- context -> schedule( +- context.getSource(), +- FunctionArgument.getFunctionOrTag(context, "function"), +- IntegerArgumentType.getInteger(context, "time"), +- true +- ) +- ) +- .then( +- Commands.literal("append") +- .executes( +- context -> schedule( +- context.getSource(), +- FunctionArgument.getFunctionOrTag(context, "function"), +- IntegerArgumentType.getInteger(context, "time"), +- false +- ) +- ) +- ) +- .then( +- Commands.literal("replace") +- .executes( +- context -> schedule( +- context.getSource(), +- FunctionArgument.getFunctionOrTag(context, "function"), +- IntegerArgumentType.getInteger(context, "time"), +- true +- ) +- ) +- ) +- ) +- ) +- ) +- .then( +- Commands.literal("clear") +- .then( +- Commands.argument("function", StringArgumentType.greedyString()) +- .suggests(SUGGEST_SCHEDULE) +- .executes(context -> remove(context.getSource(), StringArgumentType.getString(context, "function"))) +- ) +- ) +- ); ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("schedule").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).then(net.minecraft.commands.Commands.literal("function").then(net.minecraft.commands.Commands.argument("function", FunctionArgument.functions()).suggests(FunctionCommand.SUGGEST_FUNCTION).then(((RequiredArgumentBuilder) ((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("time", TimeArgument.time()).executes((commandcontext) -> { ++ return schedule((CommandSourceStack) commandcontext.getSource(), FunctionArgument.getFunctionOrTag(commandcontext, "function"), IntegerArgumentType.getInteger(commandcontext, "time"), true); ++ })).then(net.minecraft.commands.Commands.literal("append").executes((commandcontext) -> { ++ return schedule((CommandSourceStack) commandcontext.getSource(), FunctionArgument.getFunctionOrTag(commandcontext, "function"), IntegerArgumentType.getInteger(commandcontext, "time"), false); ++ }))).then(net.minecraft.commands.Commands.literal("replace").executes((commandcontext) -> { ++ return schedule((CommandSourceStack) commandcontext.getSource(), FunctionArgument.getFunctionOrTag(commandcontext, "function"), IntegerArgumentType.getInteger(commandcontext, "time"), true); ++ })))))).then(net.minecraft.commands.Commands.literal("clear").then(net.minecraft.commands.Commands.argument("function", StringArgumentType.greedyString()).suggests(ScheduleCommand.SUGGEST_SCHEDULE).executes((commandcontext) -> { ++ return remove((CommandSourceStack) commandcontext.getSource(), StringArgumentType.getString(commandcontext, "function")); ++ })))); + } + +- private static int schedule( +- CommandSourceStack source, +- Pair, Collection>>> function, +- int time, +- boolean append +- ) throws CommandSyntaxException { ++ private static int schedule(CommandSourceStack source, Pair, Collection>>> function, int time, boolean append) throws CommandSyntaxException { + if (time == 0) { +- throw ERROR_SAME_TICK.create(); ++ throw ScheduleCommand.ERROR_SAME_TICK.create(); + } else { +- long l = source.getLevel().getGameTime() + (long)time; +- ResourceLocation resourceLocation = function.getFirst(); +- TimerQueue scheduledEvents = source.getServer().getWorldData().overworldData().getScheduledEvents(); +- function.getSecond() +- .ifLeft( +- commandFunction -> { +- String string = resourceLocation.toString(); +- if (append) { +- scheduledEvents.remove(string); +- } +- +- scheduledEvents.schedule(string, l, new FunctionCallback(resourceLocation)); +- source.sendSuccess( +- () -> Component.translatable("commands.schedule.created.function", Component.translationArg(resourceLocation), time, l), true +- ); +- } +- ) +- .ifRight(functions -> { +- String string = "#" + resourceLocation; +- if (append) { +- scheduledEvents.remove(string); +- } +- +- scheduledEvents.schedule(string, l, new FunctionTagCallback(resourceLocation)); +- source.sendSuccess(() -> Component.translatable("commands.schedule.created.tag", Component.translationArg(resourceLocation), time, l), true); +- }); +- return Math.floorMod(l, Integer.MAX_VALUE); ++ long j = source.getLevel().getGameTime() + (long) time; ++ ResourceLocation minecraftkey = (ResourceLocation) function.getFirst(); ++ TimerQueue customfunctioncallbacktimerqueue = source.getLevel().serverLevelData.overworldData().getScheduledEvents(); // CraftBukkit - SPIGOT-6667: Use world specific function timer ++ ++ ((Either) function.getSecond()).ifLeft((net_minecraft_commands_functions_commandfunction) -> { ++ String s = minecraftkey.toString(); ++ ++ if (append) { ++ customfunctioncallbacktimerqueue.remove(s); ++ } ++ ++ customfunctioncallbacktimerqueue.schedule(s, j, new FunctionCallback(minecraftkey)); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.schedule.created.function", Component.translationArg(minecraftkey), time, j); ++ }, true); ++ }).ifRight((collection) -> { ++ String s = "#" + minecraftkey; ++ ++ if (append) { ++ customfunctioncallbacktimerqueue.remove(s); ++ } ++ ++ customfunctioncallbacktimerqueue.schedule(s, j, new FunctionTagCallback(minecraftkey)); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.schedule.created.tag", Component.translationArg(minecraftkey), time, j); ++ }, true); ++ }); ++ return Math.floorMod(j, Integer.MAX_VALUE); + } + } + + private static int remove(CommandSourceStack source, String function) throws CommandSyntaxException { + int i = source.getServer().getWorldData().overworldData().getScheduledEvents().remove(function); ++ + if (i == 0) { +- throw ERROR_CANT_REMOVE.create(function); ++ throw ScheduleCommand.ERROR_CANT_REMOVE.create(function); + } else { +- source.sendSuccess(() -> Component.translatable("commands.schedule.cleared.success", i, function), true); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.schedule.cleared.success", i, function); ++ }, true); + return i; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/commands/SetSpawnCommand.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/commands/SetSpawnCommand.java.patch new file mode 100644 index 0000000000..eb3ee460fb --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/commands/SetSpawnCommand.java.patch @@ -0,0 +1,119 @@ +--- a/net/minecraft/server/commands/SetSpawnCommand.java ++++ b/net/minecraft/server/commands/SetSpawnCommand.java +@@ -1,11 +1,12 @@ + package net.minecraft.server.commands; + + import com.mojang.brigadier.CommandDispatcher; +-import com.mojang.brigadier.context.CommandContext; ++import com.mojang.brigadier.builder.LiteralArgumentBuilder; ++import com.mojang.brigadier.builder.RequiredArgumentBuilder; + import java.util.Collection; + import java.util.Collections; ++import java.util.Iterator; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.arguments.AngleArgument; + import net.minecraft.commands.arguments.EntityArgument; + import net.minecraft.commands.arguments.coordinates.BlockPosArgument; +@@ -16,73 +17,43 @@ + import net.minecraft.world.level.Level; + + public class SetSpawnCommand { ++ ++ public SetSpawnCommand() {} ++ + public static void register(CommandDispatcher dispatcher) { +- dispatcher.register( +- Commands.literal("spawnpoint") +- .requires(source -> source.hasPermission(2)) +- .executes( +- context -> setSpawn( +- context.getSource(), +- Collections.singleton(context.getSource().getPlayerOrException()), +- BlockPos.containing(context.getSource().getPosition()), +- 0.0F +- ) +- ) +- .then( +- Commands.argument("targets", EntityArgument.players()) +- .executes( +- context -> setSpawn( +- context.getSource(), +- EntityArgument.getPlayers(context, "targets"), +- BlockPos.containing(context.getSource().getPosition()), +- 0.0F +- ) +- ) +- .then( +- Commands.argument("pos", BlockPosArgument.blockPos()) +- .executes( +- context -> setSpawn( +- context.getSource(), +- EntityArgument.getPlayers(context, "targets"), +- BlockPosArgument.getSpawnablePos(context, "pos"), +- 0.0F +- ) +- ) +- .then( +- Commands.argument("angle", AngleArgument.angle()) +- .executes( +- context -> setSpawn( +- context.getSource(), +- EntityArgument.getPlayers(context, "targets"), +- BlockPosArgument.getSpawnablePos(context, "pos"), +- AngleArgument.getAngle(context, "angle") +- ) +- ) +- ) +- ) +- ) +- ); ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("spawnpoint").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).executes((commandcontext) -> { ++ return setSpawn((CommandSourceStack) commandcontext.getSource(), Collections.singleton(((CommandSourceStack) commandcontext.getSource()).getPlayerOrException()), BlockPos.containing(((CommandSourceStack) commandcontext.getSource()).getPosition()), 0.0F); ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("targets", EntityArgument.players()).executes((commandcontext) -> { ++ return setSpawn((CommandSourceStack) commandcontext.getSource(), EntityArgument.getPlayers(commandcontext, "targets"), BlockPos.containing(((CommandSourceStack) commandcontext.getSource()).getPosition()), 0.0F); ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("pos", BlockPosArgument.blockPos()).executes((commandcontext) -> { ++ return setSpawn((CommandSourceStack) commandcontext.getSource(), EntityArgument.getPlayers(commandcontext, "targets"), BlockPosArgument.getSpawnablePos(commandcontext, "pos"), 0.0F); ++ })).then(net.minecraft.commands.Commands.argument("angle", AngleArgument.angle()).executes((commandcontext) -> { ++ return setSpawn((CommandSourceStack) commandcontext.getSource(), EntityArgument.getPlayers(commandcontext, "targets"), BlockPosArgument.getSpawnablePos(commandcontext, "pos"), AngleArgument.getAngle(commandcontext, "angle")); ++ }))))); + } + + private static int setSpawn(CommandSourceStack source, Collection targets, BlockPos pos, float angle) { +- ResourceKey resourceKey = source.getLevel().dimension(); ++ ResourceKey resourcekey = source.getLevel().dimension(); ++ Iterator iterator = targets.iterator(); + +- for (ServerPlayer serverPlayer : targets) { +- serverPlayer.setRespawnPosition(resourceKey, pos, angle, true, false); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ entityplayer.setRespawnPosition(resourcekey, pos, angle, true, false, org.bukkit.event.player.PlayerSpawnChangeEvent.Cause.COMMAND); // CraftBukkit + } + +- String string = resourceKey.location().toString(); ++ String s = resourcekey.location().toString(); ++ + if (targets.size() == 1) { +- source.sendSuccess( +- () -> Component.translatable( +- "commands.spawnpoint.success.single", pos.getX(), pos.getY(), pos.getZ(), angle, string, targets.iterator().next().getDisplayName() +- ), +- true +- ); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.spawnpoint.success.single", pos.getX(), pos.getY(), pos.getZ(), angle, s, ((ServerPlayer) targets.iterator().next()).getDisplayName()); ++ }, true); + } else { +- source.sendSuccess( +- () -> Component.translatable("commands.spawnpoint.success.multiple", pos.getX(), pos.getY(), pos.getZ(), angle, string, targets.size()), true +- ); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.spawnpoint.success.multiple", pos.getX(), pos.getY(), pos.getZ(), angle, s, targets.size()); ++ }, true); + } + + return targets.size(); diff --git a/patch-remap/mache-vineflower/net/minecraft/server/commands/SpreadPlayersCommand.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/commands/SpreadPlayersCommand.java.patch new file mode 100644 index 0000000000..572aabc632 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/commands/SpreadPlayersCommand.java.patch @@ -0,0 +1,537 @@ +--- a/net/minecraft/server/commands/SpreadPlayersCommand.java ++++ b/net/minecraft/server/commands/SpreadPlayersCommand.java +@@ -6,16 +6,17 @@ + import com.mojang.brigadier.arguments.BoolArgumentType; + import com.mojang.brigadier.arguments.FloatArgumentType; + import com.mojang.brigadier.arguments.IntegerArgumentType; +-import com.mojang.brigadier.context.CommandContext; ++import com.mojang.brigadier.builder.LiteralArgumentBuilder; ++import com.mojang.brigadier.builder.RequiredArgumentBuilder; + import com.mojang.brigadier.exceptions.CommandSyntaxException; + import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; + import com.mojang.brigadier.exceptions.Dynamic4CommandExceptionType; + import java.util.Collection; ++import java.util.Iterator; + import java.util.Locale; + import java.util.Map; + import java.util.Set; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.arguments.EntityArgument; + import net.minecraft.commands.arguments.coordinates.Vec2Argument; + import net.minecraft.core.BlockPos; +@@ -28,275 +29,236 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.BlockGetter; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec2; ++import net.minecraft.world.scores.PlayerTeam; + import net.minecraft.world.scores.Team; + + public class SpreadPlayersCommand { ++ + private static final int MAX_ITERATION_COUNT = 10000; +- private static final Dynamic4CommandExceptionType ERROR_FAILED_TO_SPREAD_TEAMS = new Dynamic4CommandExceptionType( +- (teamCount, x, z, suggestedSpread) -> Component.translatableEscape("commands.spreadplayers.failed.teams", teamCount, x, z, suggestedSpread) +- ); +- private static final Dynamic4CommandExceptionType ERROR_FAILED_TO_SPREAD_ENTITIES = new Dynamic4CommandExceptionType( +- (entityCount, x, z, suggestedSpread) -> Component.translatableEscape("commands.spreadplayers.failed.entities", entityCount, x, z, suggestedSpread) +- ); +- private static final Dynamic2CommandExceptionType ERROR_INVALID_MAX_HEIGHT = new Dynamic2CommandExceptionType( +- (maxHeight, worldMin) -> Component.translatableEscape("commands.spreadplayers.failed.invalid.height", maxHeight, worldMin) +- ); ++ private static final Dynamic4CommandExceptionType ERROR_FAILED_TO_SPREAD_TEAMS = new Dynamic4CommandExceptionType((object, object1, object2, object3) -> { ++ return Component.translatableEscape("commands.spreadplayers.failed.teams", object, object1, object2, object3); ++ }); ++ private static final Dynamic4CommandExceptionType ERROR_FAILED_TO_SPREAD_ENTITIES = new Dynamic4CommandExceptionType((object, object1, object2, object3) -> { ++ return Component.translatableEscape("commands.spreadplayers.failed.entities", object, object1, object2, object3); ++ }); ++ private static final Dynamic2CommandExceptionType ERROR_INVALID_MAX_HEIGHT = new Dynamic2CommandExceptionType((object, object1) -> { ++ return Component.translatableEscape("commands.spreadplayers.failed.invalid.height", object, object1); ++ }); + ++ public SpreadPlayersCommand() {} ++ + public static void register(CommandDispatcher dispatcher) { +- dispatcher.register( +- Commands.literal("spreadplayers") +- .requires(source -> source.hasPermission(2)) +- .then( +- Commands.argument("center", Vec2Argument.vec2()) +- .then( +- Commands.argument("spreadDistance", FloatArgumentType.floatArg(0.0F)) +- .then( +- Commands.argument("maxRange", FloatArgumentType.floatArg(1.0F)) +- .then( +- Commands.argument("respectTeams", BoolArgumentType.bool()) +- .then( +- Commands.argument("targets", EntityArgument.entities()) +- .executes( +- context -> spreadPlayers( +- context.getSource(), +- Vec2Argument.getVec2(context, "center"), +- FloatArgumentType.getFloat(context, "spreadDistance"), +- FloatArgumentType.getFloat(context, "maxRange"), +- context.getSource().getLevel().getMaxBuildHeight(), +- BoolArgumentType.getBool(context, "respectTeams"), +- EntityArgument.getEntities(context, "targets") +- ) +- ) +- ) +- ) +- .then( +- Commands.literal("under") +- .then( +- Commands.argument("maxHeight", IntegerArgumentType.integer()) +- .then( +- Commands.argument("respectTeams", BoolArgumentType.bool()) +- .then( +- Commands.argument("targets", EntityArgument.entities()) +- .executes( +- context -> spreadPlayers( +- context.getSource(), +- Vec2Argument.getVec2(context, "center"), +- FloatArgumentType.getFloat(context, "spreadDistance"), +- FloatArgumentType.getFloat(context, "maxRange"), +- IntegerArgumentType.getInteger(context, "maxHeight"), +- BoolArgumentType.getBool(context, "respectTeams"), +- EntityArgument.getEntities(context, "targets") +- ) +- ) +- ) +- ) +- ) +- ) +- ) +- ) +- ) +- ); ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("spreadplayers").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).then(net.minecraft.commands.Commands.argument("center", Vec2Argument.vec2()).then(net.minecraft.commands.Commands.argument("spreadDistance", FloatArgumentType.floatArg(0.0F)).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("maxRange", FloatArgumentType.floatArg(1.0F)).then(net.minecraft.commands.Commands.argument("respectTeams", BoolArgumentType.bool()).then(net.minecraft.commands.Commands.argument("targets", EntityArgument.entities()).executes((commandcontext) -> { ++ return spreadPlayers((CommandSourceStack) commandcontext.getSource(), Vec2Argument.getVec2(commandcontext, "center"), FloatArgumentType.getFloat(commandcontext, "spreadDistance"), FloatArgumentType.getFloat(commandcontext, "maxRange"), ((CommandSourceStack) commandcontext.getSource()).getLevel().getMaxBuildHeight(), BoolArgumentType.getBool(commandcontext, "respectTeams"), EntityArgument.getEntities(commandcontext, "targets")); ++ })))).then(net.minecraft.commands.Commands.literal("under").then(net.minecraft.commands.Commands.argument("maxHeight", IntegerArgumentType.integer()).then(net.minecraft.commands.Commands.argument("respectTeams", BoolArgumentType.bool()).then(net.minecraft.commands.Commands.argument("targets", EntityArgument.entities()).executes((commandcontext) -> { ++ return spreadPlayers((CommandSourceStack) commandcontext.getSource(), Vec2Argument.getVec2(commandcontext, "center"), FloatArgumentType.getFloat(commandcontext, "spreadDistance"), FloatArgumentType.getFloat(commandcontext, "maxRange"), IntegerArgumentType.getInteger(commandcontext, "maxHeight"), BoolArgumentType.getBool(commandcontext, "respectTeams"), EntityArgument.getEntities(commandcontext, "targets")); ++ }))))))))); + } + +- private static int spreadPlayers( +- CommandSourceStack source, Vec2 center, float spreadDistance, float maxRange, int maxHeight, boolean respectTeams, Collection targets +- ) throws CommandSyntaxException { +- ServerLevel level = source.getLevel(); +- int minBuildHeight = level.getMinBuildHeight(); +- if (maxHeight < minBuildHeight) { +- throw ERROR_INVALID_MAX_HEIGHT.create(maxHeight, minBuildHeight); ++ private static int spreadPlayers(CommandSourceStack source, Vec2 center, float spreadDistance, float maxRange, int maxHeight, boolean respectTeams, Collection targets) throws CommandSyntaxException { ++ ServerLevel worldserver = source.getLevel(); ++ int j = worldserver.getMinBuildHeight(); ++ ++ if (maxHeight < j) { ++ throw SpreadPlayersCommand.ERROR_INVALID_MAX_HEIGHT.create(maxHeight, j); + } else { +- RandomSource randomSource = RandomSource.create(); +- double d = (double)(center.x - maxRange); +- double d1 = (double)(center.y - maxRange); +- double d2 = (double)(center.x + maxRange); +- double d3 = (double)(center.y + maxRange); +- SpreadPlayersCommand.Position[] positions = createInitialPositions( +- randomSource, respectTeams ? getNumberOfTeams(targets) : targets.size(), d, d1, d2, d3 +- ); +- spreadPositions(center, (double)spreadDistance, level, randomSource, d, d1, d2, d3, maxHeight, positions, respectTeams); +- double d4 = setPlayerPositions(targets, level, positions, maxHeight, respectTeams); +- source.sendSuccess( +- () -> Component.translatable( +- "commands.spreadplayers.success." + (respectTeams ? "teams" : "entities"), +- positions.length, +- center.x, +- center.y, +- String.format(Locale.ROOT, "%.2f", d4) +- ), +- true +- ); +- return positions.length; ++ RandomSource randomsource = RandomSource.create(); ++ double d0 = (double) (center.x - maxRange); ++ double d1 = (double) (center.y - maxRange); ++ double d2 = (double) (center.x + maxRange); ++ double d3 = (double) (center.y + maxRange); ++ SpreadPlayersCommand.Position[] acommandspreadplayers_a = createInitialPositions(randomsource, respectTeams ? getNumberOfTeams(targets) : targets.size(), d0, d1, d2, d3); ++ ++ spreadPositions(center, (double) spreadDistance, worldserver, randomsource, d0, d1, d2, d3, maxHeight, acommandspreadplayers_a, respectTeams); ++ double d4 = setPlayerPositions(targets, worldserver, acommandspreadplayers_a, maxHeight, respectTeams); ++ ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.spreadplayers.success." + (respectTeams ? "teams" : "entities"), acommandspreadplayers_a.length, center.x, center.y, String.format(Locale.ROOT, "%.2f", d4)); ++ }, true); ++ return acommandspreadplayers_a.length; + } + } + + private static int getNumberOfTeams(Collection entities) { + Set set = Sets.newHashSet(); ++ Iterator iterator = entities.iterator(); + +- for (Entity entity : entities) { ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ + if (entity instanceof Player) { + set.add(entity.getTeam()); + } else { +- set.add(null); ++ set.add((Team) null); // CraftBukkit - decompile error + } + } + + return set.size(); + } + +- private static void spreadPositions( +- Vec2 center, +- double spreadDistance, +- ServerLevel level, +- RandomSource random, +- double minX, +- double minZ, +- double maxX, +- double maxZ, +- int maxHeight, +- SpreadPlayersCommand.Position[] positions, +- boolean respectTeams +- ) throws CommandSyntaxException { +- boolean flag = true; +- double d = Float.MAX_VALUE; ++ private static void spreadPositions(Vec2 center, double spreadDistance, ServerLevel worldserver, RandomSource level, double random, double minX, double d3, double minZ, int i, SpreadPlayersCommand.Position[] maxX, boolean flag) throws CommandSyntaxException { ++ boolean flag1 = true; ++ double d5 = 3.4028234663852886E38D; + +- int i; +- for (i = 0; i < 10000 && flag; i++) { +- flag = false; +- d = Float.MAX_VALUE; ++ int j; + +- for (int i1 = 0; i1 < positions.length; i1++) { +- SpreadPlayersCommand.Position position = positions[i1]; +- int i2 = 0; +- SpreadPlayersCommand.Position position1 = new SpreadPlayersCommand.Position(); ++ for (j = 0; j < 10000 && flag1; ++j) { ++ flag1 = false; ++ d5 = 3.4028234663852886E38D; + +- for (int i3 = 0; i3 < positions.length; i3++) { +- if (i1 != i3) { +- SpreadPlayersCommand.Position position2 = positions[i3]; +- double d1 = position.dist(position2); +- d = Math.min(d1, d); +- if (d1 < spreadDistance) { +- i2++; +- position1.x = position1.x + (position2.x - position.x); +- position1.z = position1.z + (position2.z - position.z); ++ int k; ++ SpreadPlayersCommand.Position commandspreadplayers_a; ++ ++ for (int l = 0; l < maxX.length; ++l) { ++ SpreadPlayersCommand.Position commandspreadplayers_a1 = maxX[l]; ++ ++ k = 0; ++ commandspreadplayers_a = new SpreadPlayersCommand.Position(); ++ ++ for (int i1 = 0; i1 < maxX.length; ++i1) { ++ if (l != i1) { ++ SpreadPlayersCommand.Position commandspreadplayers_a2 = maxX[i1]; ++ double d6 = commandspreadplayers_a1.dist(commandspreadplayers_a2); ++ ++ d5 = Math.min(d6, d5); ++ if (d6 < spreadDistance) { ++ ++k; ++ commandspreadplayers_a.x += commandspreadplayers_a2.x - commandspreadplayers_a1.x; ++ commandspreadplayers_a.z += commandspreadplayers_a2.z - commandspreadplayers_a1.z; + } + } + } + +- if (i2 > 0) { +- position1.x /= (double)i2; +- position1.z /= (double)i2; +- double length = position1.getLength(); +- if (length > 0.0) { +- position1.normalize(); +- position.moveAway(position1); ++ if (k > 0) { ++ commandspreadplayers_a.x /= (double) k; ++ commandspreadplayers_a.z /= (double) k; ++ double d7 = commandspreadplayers_a.getLength(); ++ ++ if (d7 > 0.0D) { ++ commandspreadplayers_a.normalize(); ++ commandspreadplayers_a1.moveAway(commandspreadplayers_a); + } else { +- position.randomize(random, minX, minZ, maxX, maxZ); ++ commandspreadplayers_a1.randomize(level, random, minX, d3, minZ); + } + +- flag = true; ++ flag1 = true; + } + +- if (position.clamp(minX, minZ, maxX, maxZ)) { +- flag = true; ++ if (commandspreadplayers_a1.clamp(random, minX, d3, minZ)) { ++ flag1 = true; + } + } + +- if (!flag) { +- for (SpreadPlayersCommand.Position position1 : positions) { +- if (!position1.isSafe(level, maxHeight)) { +- position1.randomize(random, minX, minZ, maxX, maxZ); +- flag = true; ++ if (!flag1) { ++ SpreadPlayersCommand.Position[] acommandspreadplayers_a1 = maxX; ++ int j1 = maxX.length; ++ ++ for (k = 0; k < j1; ++k) { ++ commandspreadplayers_a = acommandspreadplayers_a1[k]; ++ if (!commandspreadplayers_a.isSafe(worldserver, i)) { ++ commandspreadplayers_a.randomize(level, random, minX, d3, minZ); ++ flag1 = true; + } + } + } + } + +- if (d == Float.MAX_VALUE) { +- d = 0.0; ++ if (d5 == 3.4028234663852886E38D) { ++ d5 = 0.0D; + } + +- if (i >= 10000) { +- if (respectTeams) { +- throw ERROR_FAILED_TO_SPREAD_TEAMS.create(positions.length, center.x, center.y, String.format(Locale.ROOT, "%.2f", d)); ++ if (j >= 10000) { ++ if (flag) { ++ throw SpreadPlayersCommand.ERROR_FAILED_TO_SPREAD_TEAMS.create(maxX.length, center.x, center.y, String.format(Locale.ROOT, "%.2f", d5)); + } else { +- throw ERROR_FAILED_TO_SPREAD_ENTITIES.create(positions.length, center.x, center.y, String.format(Locale.ROOT, "%.2f", d)); ++ throw SpreadPlayersCommand.ERROR_FAILED_TO_SPREAD_ENTITIES.create(maxX.length, center.x, center.y, String.format(Locale.ROOT, "%.2f", d5)); + } + } + } + +- private static double setPlayerPositions( +- Collection targets, ServerLevel level, SpreadPlayersCommand.Position[] positions, int maxHeight, boolean respectTeams +- ) { +- double d = 0.0; +- int i = 0; ++ private static double setPlayerPositions(Collection targets, ServerLevel level, SpreadPlayersCommand.Position[] positions, int maxHeight, boolean respectTeams) { ++ double d0 = 0.0D; ++ int j = 0; + Map map = Maps.newHashMap(); + +- for (Entity entity : targets) { +- SpreadPlayersCommand.Position position; ++ double d1; ++ ++ for (Iterator iterator = targets.iterator(); iterator.hasNext(); d0 += d1) { ++ Entity entity = (Entity) iterator.next(); ++ SpreadPlayersCommand.Position commandspreadplayers_a; ++ + if (respectTeams) { +- Team team = entity instanceof Player ? entity.getTeam() : null; +- if (!map.containsKey(team)) { +- map.put(team, positions[i++]); ++ PlayerTeam scoreboardteam = entity instanceof Player ? entity.getTeam() : null; ++ ++ if (!map.containsKey(scoreboardteam)) { ++ map.put(scoreboardteam, positions[j++]); + } + +- position = map.get(team); ++ commandspreadplayers_a = (SpreadPlayersCommand.Position) map.get(scoreboardteam); + } else { +- position = positions[i++]; ++ commandspreadplayers_a = positions[j++]; + } + +- entity.teleportTo( +- level, +- (double)Mth.floor(position.x) + 0.5, +- (double)position.getSpawnY(level, maxHeight), +- (double)Mth.floor(position.z) + 0.5, +- Set.of(), +- entity.getYRot(), +- entity.getXRot() +- ); +- double d1 = Double.MAX_VALUE; ++ entity.teleportTo(level, (double) Mth.floor(commandspreadplayers_a.x) + 0.5D, (double) commandspreadplayers_a.getSpawnY(level, maxHeight), (double) Mth.floor(commandspreadplayers_a.z) + 0.5D, Set.of(), entity.getYRot(), entity.getXRot(), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.COMMAND); // CraftBukkit - handle teleport reason ++ d1 = Double.MAX_VALUE; ++ SpreadPlayersCommand.Position[] acommandspreadplayers_a1 = positions; ++ int k = positions.length; + +- for (SpreadPlayersCommand.Position position1 : positions) { +- if (position != position1) { +- double d2 = position.dist(position1); ++ for (int l = 0; l < k; ++l) { ++ SpreadPlayersCommand.Position commandspreadplayers_a1 = acommandspreadplayers_a1[l]; ++ ++ if (commandspreadplayers_a != commandspreadplayers_a1) { ++ double d2 = commandspreadplayers_a.dist(commandspreadplayers_a1); ++ + d1 = Math.min(d2, d1); + } + } +- +- d += d1; + } + +- return targets.size() < 2 ? 0.0 : d / (double)targets.size(); ++ if (targets.size() < 2) { ++ return 0.0D; ++ } else { ++ d0 /= (double) targets.size(); ++ return d0; ++ } + } + +- private static SpreadPlayersCommand.Position[] createInitialPositions(RandomSource random, int count, double minX, double minZ, double maxX, double maxZ) { +- SpreadPlayersCommand.Position[] positions = new SpreadPlayersCommand.Position[count]; ++ private static SpreadPlayersCommand.Position[] createInitialPositions(RandomSource random, int count, double minX, double d1, double minZ, double d3) { ++ SpreadPlayersCommand.Position[] acommandspreadplayers_a = new SpreadPlayersCommand.Position[count]; + +- for (int i = 0; i < positions.length; i++) { +- SpreadPlayersCommand.Position position = new SpreadPlayersCommand.Position(); +- position.randomize(random, minX, minZ, maxX, maxZ); +- positions[i] = position; ++ for (int j = 0; j < acommandspreadplayers_a.length; ++j) { ++ SpreadPlayersCommand.Position commandspreadplayers_a = new SpreadPlayersCommand.Position(); ++ ++ commandspreadplayers_a.randomize(random, minX, d1, minZ, d3); ++ acommandspreadplayers_a[j] = commandspreadplayers_a; + } + +- return positions; ++ return acommandspreadplayers_a; + } + +- static class Position { ++ private static class Position { ++ + double x; + double z; + ++ Position() {} ++ + double dist(SpreadPlayersCommand.Position other) { +- double d = this.x - other.x; ++ double d0 = this.x - other.x; + double d1 = this.z - other.z; +- return Math.sqrt(d * d + d1 * d1); ++ ++ return Math.sqrt(d0 * d0 + d1 * d1); + } + + void normalize() { +- double length = this.getLength(); +- this.x /= length; +- this.z /= length; ++ double d0 = this.getLength(); ++ ++ this.x /= d0; ++ this.z /= d0; + } + + double getLength() { +@@ -304,25 +266,26 @@ + } + + public void moveAway(SpreadPlayersCommand.Position other) { +- this.x = this.x - other.x; +- this.z = this.z - other.z; ++ this.x -= other.x; ++ this.z -= other.z; + } + +- public boolean clamp(double minX, double minZ, double maxX, double maxZ) { ++ public boolean clamp(double minX, double d1, double minZ, double d3) { + boolean flag = false; ++ + if (this.x < minX) { + this.x = minX; + flag = true; +- } else if (this.x > maxX) { +- this.x = maxX; ++ } else if (this.x > minZ) { ++ this.x = minZ; + flag = true; + } + +- if (this.z < minZ) { +- this.z = minZ; ++ if (this.z < d1) { ++ this.z = d1; + flag = true; +- } else if (this.z > maxZ) { +- this.z = maxZ; ++ } else if (this.z > d3) { ++ this.z = d3; + flag = true; + } + +@@ -330,34 +293,36 @@ + } + + public int getSpawnY(BlockGetter level, int y) { +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(this.x, (double)(y + 1), this.z); +- boolean isAir = level.getBlockState(mutableBlockPos).isAir(); +- mutableBlockPos.move(Direction.DOWN); +- boolean isAir1 = level.getBlockState(mutableBlockPos).isAir(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(this.x, (double) (y + 1), this.z); ++ boolean flag = level.getBlockState(blockposition_mutableblockposition).isAir(); + +- while (mutableBlockPos.getY() > level.getMinBuildHeight()) { +- mutableBlockPos.move(Direction.DOWN); +- boolean isAir2 = level.getBlockState(mutableBlockPos).isAir(); +- if (!isAir2 && isAir1 && isAir) { +- return mutableBlockPos.getY() + 1; ++ blockposition_mutableblockposition.move(Direction.DOWN); ++ ++ boolean flag1; ++ ++ for (boolean flag2 = level.getBlockState(blockposition_mutableblockposition).isAir(); blockposition_mutableblockposition.getY() > level.getMinBuildHeight(); flag2 = flag1) { ++ blockposition_mutableblockposition.move(Direction.DOWN); ++ flag1 = level.getBlockState(blockposition_mutableblockposition).isAir(); ++ if (!flag1 && flag2 && flag) { ++ return blockposition_mutableblockposition.getY() + 1; + } + +- isAir = isAir1; +- isAir1 = isAir2; ++ flag = flag2; + } + + return y + 1; + } + + public boolean isSafe(BlockGetter level, int y) { +- BlockPos blockPos = BlockPos.containing(this.x, (double)(this.getSpawnY(level, y) - 1), this.z); +- BlockState blockState = level.getBlockState(blockPos); +- return blockPos.getY() < y && !blockState.liquid() && !blockState.is(BlockTags.FIRE); ++ BlockPos blockposition = BlockPos.containing(this.x, (double) (this.getSpawnY(level, y) - 1), this.z); ++ IBlockData iblockdata = level.getBlockState(blockposition); ++ ++ return blockposition.getY() < y && !iblockdata.liquid() && !iblockdata.is(BlockTags.FIRE); + } + +- public void randomize(RandomSource random, double minX, double minZ, double maxX, double maxZ) { +- this.x = Mth.nextDouble(random, minX, maxX); +- this.z = Mth.nextDouble(random, minZ, maxZ); ++ public void randomize(RandomSource random, double minX, double d1, double minZ, double d3) { ++ this.x = Mth.nextDouble(random, minX, minZ); ++ this.z = Mth.nextDouble(random, d1, d3); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/commands/SummonCommand.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/commands/SummonCommand.java.patch new file mode 100644 index 0000000000..fb70452a26 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/commands/SummonCommand.java.patch @@ -0,0 +1,140 @@ +--- a/net/minecraft/server/commands/SummonCommand.java ++++ b/net/minecraft/server/commands/SummonCommand.java +@@ -1,12 +1,12 @@ + package net.minecraft.server.commands; + + import com.mojang.brigadier.CommandDispatcher; +-import com.mojang.brigadier.context.CommandContext; ++import com.mojang.brigadier.builder.LiteralArgumentBuilder; ++import com.mojang.brigadier.builder.RequiredArgumentBuilder; + import com.mojang.brigadier.exceptions.CommandSyntaxException; + import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; + import net.minecraft.commands.CommandBuildContext; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.arguments.CompoundTagArgument; + import net.minecraft.commands.arguments.ResourceArgument; + import net.minecraft.commands.arguments.coordinates.Vec3Argument; +@@ -19,82 +19,56 @@ + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.Vec3; + + public class SummonCommand { ++ + private static final SimpleCommandExceptionType ERROR_FAILED = new SimpleCommandExceptionType(Component.translatable("commands.summon.failed")); + private static final SimpleCommandExceptionType ERROR_DUPLICATE_UUID = new SimpleCommandExceptionType(Component.translatable("commands.summon.failed.uuid")); + private static final SimpleCommandExceptionType INVALID_POSITION = new SimpleCommandExceptionType(Component.translatable("commands.summon.invalidPosition")); + ++ public SummonCommand() {} ++ + public static void register(CommandDispatcher dispatcher, CommandBuildContext context) { +- dispatcher.register( +- Commands.literal("summon") +- .requires(source -> source.hasPermission(2)) +- .then( +- Commands.argument("entity", ResourceArgument.resource(context, Registries.ENTITY_TYPE)) +- .suggests(SuggestionProviders.SUMMONABLE_ENTITIES) +- .executes( +- context1 -> spawnEntity( +- context1.getSource(), +- ResourceArgument.getSummonableEntityType(context1, "entity"), +- context1.getSource().getPosition(), +- new CompoundTag(), +- true +- ) +- ) +- .then( +- Commands.argument("pos", Vec3Argument.vec3()) +- .executes( +- context1 -> spawnEntity( +- context1.getSource(), +- ResourceArgument.getSummonableEntityType(context1, "entity"), +- Vec3Argument.getVec3(context1, "pos"), +- new CompoundTag(), +- true +- ) +- ) +- .then( +- Commands.argument("nbt", CompoundTagArgument.compoundTag()) +- .executes( +- context1 -> spawnEntity( +- context1.getSource(), +- ResourceArgument.getSummonableEntityType(context1, "entity"), +- Vec3Argument.getVec3(context1, "pos"), +- CompoundTagArgument.getCompoundTag(context1, "nbt"), +- false +- ) +- ) +- ) +- ) +- ) +- ); ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("summon").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("entity", ResourceArgument.resource(context, Registries.ENTITY_TYPE)).suggests(SuggestionProviders.SUMMONABLE_ENTITIES).executes((commandcontext) -> { ++ return spawnEntity((CommandSourceStack) commandcontext.getSource(), ResourceArgument.getSummonableEntityType(commandcontext, "entity"), ((CommandSourceStack) commandcontext.getSource()).getPosition(), new CompoundTag(), true); ++ })).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("pos", Vec3Argument.vec3()).executes((commandcontext) -> { ++ return spawnEntity((CommandSourceStack) commandcontext.getSource(), ResourceArgument.getSummonableEntityType(commandcontext, "entity"), Vec3Argument.getVec3(commandcontext, "pos"), new CompoundTag(), true); ++ })).then(net.minecraft.commands.Commands.argument("nbt", CompoundTagArgument.compoundTag()).executes((commandcontext) -> { ++ return spawnEntity((CommandSourceStack) commandcontext.getSource(), ResourceArgument.getSummonableEntityType(commandcontext, "entity"), Vec3Argument.getVec3(commandcontext, "pos"), CompoundTagArgument.getCompoundTag(commandcontext, "nbt"), false); ++ }))))); + } + + public static Entity createEntity(CommandSourceStack source, Holder.Reference> type, Vec3 pos, CompoundTag tag, boolean randomizeProperties) throws CommandSyntaxException { +- BlockPos blockPos = BlockPos.containing(pos); +- if (!Level.isInSpawnableBounds(blockPos)) { +- throw INVALID_POSITION.create(); ++ BlockPos blockposition = BlockPos.containing(pos); ++ ++ if (!Level.isInSpawnableBounds(blockposition)) { ++ throw SummonCommand.INVALID_POSITION.create(); + } else { +- CompoundTag compoundTag = tag.copy(); +- compoundTag.putString("id", type.key().location().toString()); +- ServerLevel level = source.getLevel(); +- Entity entity = EntityType.loadEntityRecursive(compoundTag, level, entity1 -> { ++ CompoundTag nbttagcompound1 = tag.copy(); ++ ++ nbttagcompound1.putString("id", type.key().location().toString()); ++ ServerLevel worldserver = source.getLevel(); ++ Entity entity = EntityType.loadEntityRecursive(nbttagcompound1, worldserver, (entity1) -> { + entity1.moveTo(pos.x, pos.y, pos.z, entity1.getYRot(), entity1.getXRot()); + return entity1; + }); ++ + if (entity == null) { +- throw ERROR_FAILED.create(); ++ throw SummonCommand.ERROR_FAILED.create(); + } else { + if (randomizeProperties && entity instanceof Mob) { +- ((Mob)entity) +- .finalizeSpawn(source.getLevel(), source.getLevel().getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.COMMAND, null, null); ++ ((Mob) entity).finalizeSpawn(source.getLevel(), source.getLevel().getCurrentDifficultyAt(entity.blockPosition()), EnumMobSpawn.COMMAND, (GroupDataEntity) null, (CompoundTag) null); + } + +- if (!level.tryAddFreshEntityWithPassengers(entity)) { +- throw ERROR_DUPLICATE_UUID.create(); ++ if (!worldserver.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.COMMAND)) { // CraftBukkit - pass a spawn reason of "COMMAND" ++ throw SummonCommand.ERROR_DUPLICATE_UUID.create(); + } else { + return entity; + } +@@ -104,7 +78,10 @@ + + private static int spawnEntity(CommandSourceStack source, Holder.Reference> type, Vec3 pos, CompoundTag tag, boolean randomizeProperties) throws CommandSyntaxException { + Entity entity = createEntity(source, type, pos, tag, randomizeProperties); +- source.sendSuccess(() -> Component.translatable("commands.summon.success", entity.getDisplayName()), true); ++ ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.summon.success", entity.getDisplayName()); ++ }, true); + return 1; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/commands/TeleportCommand.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/commands/TeleportCommand.java.patch new file mode 100644 index 0000000000..cd02501708 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/commands/TeleportCommand.java.patch @@ -0,0 +1,408 @@ +--- a/net/minecraft/server/commands/TeleportCommand.java ++++ b/net/minecraft/server/commands/TeleportCommand.java +@@ -1,18 +1,19 @@ + package net.minecraft.server.commands; + + import com.mojang.brigadier.CommandDispatcher; +-import com.mojang.brigadier.context.CommandContext; ++import com.mojang.brigadier.builder.LiteralArgumentBuilder; ++import com.mojang.brigadier.builder.RequiredArgumentBuilder; + import com.mojang.brigadier.exceptions.CommandSyntaxException; + import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; + import com.mojang.brigadier.tree.LiteralCommandNode; + import java.util.Collection; + import java.util.Collections; + import java.util.EnumSet; ++import java.util.Iterator; + import java.util.Locale; + import java.util.Set; + import javax.annotation.Nullable; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.arguments.EntityAnchorArgument; + import net.minecraft.commands.arguments.EntityArgument; + import net.minecraft.commands.arguments.coordinates.Coordinates; +@@ -31,173 +32,72 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.event.entity.EntityTeleportEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++// CraftBukkit end + + public class TeleportCommand { +- private static final SimpleCommandExceptionType INVALID_POSITION = new SimpleCommandExceptionType( +- Component.translatable("commands.teleport.invalidPosition") +- ); + ++ private static final SimpleCommandExceptionType INVALID_POSITION = new SimpleCommandExceptionType(Component.translatable("commands.teleport.invalidPosition")); ++ ++ public TeleportCommand() {} ++ + public static void register(CommandDispatcher dispatcher) { +- LiteralCommandNode literalCommandNode = dispatcher.register( +- Commands.literal("teleport") +- .requires(source -> source.hasPermission(2)) +- .then( +- Commands.argument("location", Vec3Argument.vec3()) +- .executes( +- context -> teleportToPos( +- context.getSource(), +- Collections.singleton(context.getSource().getEntityOrException()), +- context.getSource().getLevel(), +- Vec3Argument.getCoordinates(context, "location"), +- WorldCoordinates.current(), +- null +- ) +- ) +- ) +- .then( +- Commands.argument("destination", EntityArgument.entity()) +- .executes( +- context -> teleportToEntity( +- context.getSource(), +- Collections.singleton(context.getSource().getEntityOrException()), +- EntityArgument.getEntity(context, "destination") +- ) +- ) +- ) +- .then( +- Commands.argument("targets", EntityArgument.entities()) +- .then( +- Commands.argument("location", Vec3Argument.vec3()) +- .executes( +- context -> teleportToPos( +- context.getSource(), +- EntityArgument.getEntities(context, "targets"), +- context.getSource().getLevel(), +- Vec3Argument.getCoordinates(context, "location"), +- null, +- null +- ) +- ) +- .then( +- Commands.argument("rotation", RotationArgument.rotation()) +- .executes( +- context -> teleportToPos( +- context.getSource(), +- EntityArgument.getEntities(context, "targets"), +- context.getSource().getLevel(), +- Vec3Argument.getCoordinates(context, "location"), +- RotationArgument.getRotation(context, "rotation"), +- null +- ) +- ) +- ) +- .then( +- Commands.literal("facing") +- .then( +- Commands.literal("entity") +- .then( +- Commands.argument("facingEntity", EntityArgument.entity()) +- .executes( +- context -> teleportToPos( +- context.getSource(), +- EntityArgument.getEntities(context, "targets"), +- context.getSource().getLevel(), +- Vec3Argument.getCoordinates(context, "location"), +- null, +- new TeleportCommand.LookAt( +- EntityArgument.getEntity(context, "facingEntity"), EntityAnchorArgument.Anchor.FEET +- ) +- ) +- ) +- .then( +- Commands.argument("facingAnchor", EntityAnchorArgument.anchor()) +- .executes( +- context -> teleportToPos( +- context.getSource(), +- EntityArgument.getEntities(context, "targets"), +- context.getSource().getLevel(), +- Vec3Argument.getCoordinates(context, "location"), +- null, +- new TeleportCommand.LookAt( +- EntityArgument.getEntity(context, "facingEntity"), +- EntityAnchorArgument.getAnchor(context, "facingAnchor") +- ) +- ) +- ) +- ) +- ) +- ) +- .then( +- Commands.argument("facingLocation", Vec3Argument.vec3()) +- .executes( +- context -> teleportToPos( +- context.getSource(), +- EntityArgument.getEntities(context, "targets"), +- context.getSource().getLevel(), +- Vec3Argument.getCoordinates(context, "location"), +- null, +- new TeleportCommand.LookAt(Vec3Argument.getVec3(context, "facingLocation")) +- ) +- ) +- ) +- ) +- ) +- .then( +- Commands.argument("destination", EntityArgument.entity()) +- .executes( +- context -> teleportToEntity( +- context.getSource(), +- EntityArgument.getEntities(context, "targets"), +- EntityArgument.getEntity(context, "destination") +- ) +- ) +- ) +- ) +- ); +- dispatcher.register(Commands.literal("tp").requires(source -> source.hasPermission(2)).redirect(literalCommandNode)); ++ LiteralCommandNode literalcommandnode = dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("teleport").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).then(net.minecraft.commands.Commands.argument("location", Vec3Argument.vec3()).executes((commandcontext) -> { ++ return teleportToPos((CommandSourceStack) commandcontext.getSource(), Collections.singleton(((CommandSourceStack) commandcontext.getSource()).getEntityOrException()), ((CommandSourceStack) commandcontext.getSource()).getLevel(), Vec3Argument.getCoordinates(commandcontext, "location"), WorldCoordinates.current(), (TeleportCommand.LookAt) null); ++ }))).then(net.minecraft.commands.Commands.argument("destination", EntityArgument.entity()).executes((commandcontext) -> { ++ return teleportToEntity((CommandSourceStack) commandcontext.getSource(), Collections.singleton(((CommandSourceStack) commandcontext.getSource()).getEntityOrException()), EntityArgument.getEntity(commandcontext, "destination")); ++ }))).then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("targets", EntityArgument.entities()).then(((RequiredArgumentBuilder) ((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("location", Vec3Argument.vec3()).executes((commandcontext) -> { ++ return teleportToPos((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ((CommandSourceStack) commandcontext.getSource()).getLevel(), Vec3Argument.getCoordinates(commandcontext, "location"), (Coordinates) null, (TeleportCommand.LookAt) null); ++ })).then(net.minecraft.commands.Commands.argument("rotation", RotationArgument.rotation()).executes((commandcontext) -> { ++ return teleportToPos((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ((CommandSourceStack) commandcontext.getSource()).getLevel(), Vec3Argument.getCoordinates(commandcontext, "location"), RotationArgument.getRotation(commandcontext, "rotation"), (TeleportCommand.LookAt) null); ++ }))).then(((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("facing").then(net.minecraft.commands.Commands.literal("entity").then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("facingEntity", EntityArgument.entity()).executes((commandcontext) -> { ++ return teleportToPos((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ((CommandSourceStack) commandcontext.getSource()).getLevel(), Vec3Argument.getCoordinates(commandcontext, "location"), (Coordinates) null, new TeleportCommand.LookAt(EntityArgument.getEntity(commandcontext, "facingEntity"), EntityAnchorArgument.Anchor.FEET)); ++ })).then(net.minecraft.commands.Commands.argument("facingAnchor", EntityAnchorArgument.anchor()).executes((commandcontext) -> { ++ return teleportToPos((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ((CommandSourceStack) commandcontext.getSource()).getLevel(), Vec3Argument.getCoordinates(commandcontext, "location"), (Coordinates) null, new TeleportCommand.LookAt(EntityArgument.getEntity(commandcontext, "facingEntity"), EntityAnchorArgument.getAnchor(commandcontext, "facingAnchor"))); ++ }))))).then(net.minecraft.commands.Commands.argument("facingLocation", Vec3Argument.vec3()).executes((commandcontext) -> { ++ return teleportToPos((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), ((CommandSourceStack) commandcontext.getSource()).getLevel(), Vec3Argument.getCoordinates(commandcontext, "location"), (Coordinates) null, new TeleportCommand.LookAt(Vec3Argument.getVec3(commandcontext, "facingLocation"))); ++ }))))).then(net.minecraft.commands.Commands.argument("destination", EntityArgument.entity()).executes((commandcontext) -> { ++ return teleportToEntity((CommandSourceStack) commandcontext.getSource(), EntityArgument.getEntities(commandcontext, "targets"), EntityArgument.getEntity(commandcontext, "destination")); ++ })))); ++ ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("tp").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).redirect(literalcommandnode)); + } + + private static int teleportToEntity(CommandSourceStack source, Collection targets, Entity destination) throws CommandSyntaxException { +- for (Entity entity : targets) { +- performTeleport( +- source, +- entity, +- (ServerLevel)destination.level(), +- destination.getX(), +- destination.getY(), +- destination.getZ(), +- EnumSet.noneOf(RelativeMovement.class), +- destination.getYRot(), +- destination.getXRot(), +- null +- ); ++ Iterator iterator = targets.iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity1 = (Entity) iterator.next(); ++ ++ performTeleport(source, entity1, (ServerLevel) destination.level(), destination.getX(), destination.getY(), destination.getZ(), EnumSet.noneOf(RelativeMovement.class), destination.getYRot(), destination.getXRot(), (TeleportCommand.LookAt) null); + } + + if (targets.size() == 1) { +- source.sendSuccess( +- () -> Component.translatable( +- "commands.teleport.success.entity.single", targets.iterator().next().getDisplayName(), destination.getDisplayName() +- ), +- true +- ); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.teleport.success.entity.single", ((Entity) targets.iterator().next()).getDisplayName(), destination.getDisplayName()); ++ }, true); + } else { +- source.sendSuccess(() -> Component.translatable("commands.teleport.success.entity.multiple", targets.size(), destination.getDisplayName()), true); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.teleport.success.entity.multiple", targets.size(), destination.getDisplayName()); ++ }, true); + } + + return targets.size(); + } + +- private static int teleportToPos( +- CommandSourceStack source, +- Collection targets, +- ServerLevel level, +- Coordinates position, +- @Nullable Coordinates rotation, +- @Nullable TeleportCommand.LookAt facing +- ) throws CommandSyntaxException { +- Vec3 position1 = position.getPosition(source); +- Vec2 vec2 = rotation == null ? null : rotation.getRotation(source); ++ private static int teleportToPos(CommandSourceStack source, Collection targets, ServerLevel level, Coordinates position, @Nullable Coordinates rotation, @Nullable TeleportCommand.LookAt facing) throws CommandSyntaxException { ++ Vec3 vec3d = position.getPosition(source); ++ Vec2 vec2f = rotation == null ? null : rotation.getRotation(source); + Set set = EnumSet.noneOf(RelativeMovement.class); ++ + if (position.isXRelative()) { + set.add(RelativeMovement.X); + } +@@ -223,36 +123,26 @@ + } + } + +- for (Entity entity : targets) { ++ Iterator iterator = targets.iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ + if (rotation == null) { +- performTeleport(source, entity, level, position1.x, position1.y, position1.z, set, entity.getYRot(), entity.getXRot(), facing); ++ performTeleport(source, entity, level, vec3d.x, vec3d.y, vec3d.z, set, entity.getYRot(), entity.getXRot(), facing); + } else { +- performTeleport(source, entity, level, position1.x, position1.y, position1.z, set, vec2.y, vec2.x, facing); ++ performTeleport(source, entity, level, vec3d.x, vec3d.y, vec3d.z, set, vec2f.y, vec2f.x, facing); + } + } + + if (targets.size() == 1) { +- source.sendSuccess( +- () -> Component.translatable( +- "commands.teleport.success.location.single", +- targets.iterator().next().getDisplayName(), +- formatDouble(position1.x), +- formatDouble(position1.y), +- formatDouble(position1.z) +- ), +- true +- ); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.teleport.success.location.single", ((Entity) targets.iterator().next()).getDisplayName(), formatDouble(vec3d.x), formatDouble(vec3d.y), formatDouble(vec3d.z)); ++ }, true); + } else { +- source.sendSuccess( +- () -> Component.translatable( +- "commands.teleport.success.location.multiple", +- targets.size(), +- formatDouble(position1.x), +- formatDouble(position1.y), +- formatDouble(position1.z) +- ), +- true +- ); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.teleport.success.location.multiple", targets.size(), formatDouble(vec3d.x), formatDouble(vec3d.y), formatDouble(vec3d.z)); ++ }, true); + } + + return targets.size(); +@@ -262,42 +152,69 @@ + return String.format(Locale.ROOT, "%f", value); + } + +- private static void performTeleport( +- CommandSourceStack source, +- Entity entity, +- ServerLevel level, +- double x, +- double y, +- double z, +- Set relativeList, +- float yaw, +- float pitch, +- @Nullable TeleportCommand.LookAt facing +- ) throws CommandSyntaxException { +- BlockPos blockPos = BlockPos.containing(x, y, z); +- if (!Level.isInSpawnableBounds(blockPos)) { +- throw INVALID_POSITION.create(); ++ private static void performTeleport(CommandSourceStack source, Entity entity, ServerLevel level, double x, double d1, double y, Set set, float z, float f1, @Nullable TeleportCommand.LookAt relativeList) throws CommandSyntaxException { ++ BlockPos blockposition = BlockPos.containing(x, d1, y); ++ ++ if (!Level.isInSpawnableBounds(blockposition)) { ++ throw TeleportCommand.INVALID_POSITION.create(); + } else { +- float f = Mth.wrapDegrees(yaw); +- float f1 = Mth.wrapDegrees(pitch); +- if (entity.teleportTo(level, x, y, z, relativeList, f, f1)) { +- if (facing != null) { +- facing.perform(source, entity); ++ float f2 = Mth.wrapDegrees(z); ++ float f3 = Mth.wrapDegrees(f1); ++ ++ // CraftBukkit start - Teleport event ++ boolean result; ++ if (entity instanceof ServerPlayer player) { ++ result = player.teleportTo(level, x, d1, y, set, f2, f3, PlayerTeleportEvent.TeleportCause.COMMAND); ++ } else { ++ Location to = new Location(level.getWorld(), x, d1, y, f2, f3); ++ EntityTeleportEvent event = new EntityTeleportEvent(entity.getBukkitEntity(), entity.getBukkitEntity().getLocation(), to); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; + } + +- if (!(entity instanceof LivingEntity livingEntity) || !livingEntity.isFallFlying()) { +- entity.setDeltaMovement(entity.getDeltaMovement().multiply(1.0, 0.0, 1.0)); ++ x = to.getX(); ++ d1 = to.getY(); ++ y = to.getZ(); ++ f2 = to.getYaw(); ++ f3 = to.getPitch(); ++ level = ((CraftWorld) to.getWorld()).getHandle(); ++ ++ result = entity.teleportTo(level, x, d1, y, set, f2, f3); ++ } ++ ++ if (result) { ++ // CraftBukkit end ++ if (relativeList != null) { ++ relativeList.perform(source, entity); ++ } ++ ++ label23: ++ { ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ if (entityliving.isFallFlying()) { ++ break label23; ++ } ++ } ++ ++ entity.setDeltaMovement(entity.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D)); + entity.setOnGround(true); + } + +- if (entity instanceof PathfinderMob pathfinderMob) { +- pathfinderMob.getNavigation().stop(); ++ if (entity instanceof PathfinderMob) { ++ PathfinderMob entitycreature = (PathfinderMob) entity; ++ ++ entitycreature.getNavigation().stop(); + } ++ + } + } + } + +- static class LookAt { ++ private static class LookAt { ++ + private final Vec3 position; + private final Entity entity; + private final EntityAnchorArgument.Anchor anchor; +@@ -317,13 +234,14 @@ + public void perform(CommandSourceStack source, Entity entity) { + if (this.entity != null) { + if (entity instanceof ServerPlayer) { +- ((ServerPlayer)entity).lookAt(source.getAnchor(), this.entity, this.anchor); ++ ((ServerPlayer) entity).lookAt(source.getAnchor(), this.entity, this.anchor); + } else { + entity.lookAt(source.getAnchor(), this.position); + } + } else { + entity.lookAt(source.getAnchor(), this.position); + } ++ + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/commands/TimeCommand.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/commands/TimeCommand.java.patch new file mode 100644 index 0000000000..21d1052b9d --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/commands/TimeCommand.java.patch @@ -0,0 +1,146 @@ +--- a/net/minecraft/server/commands/TimeCommand.java ++++ b/net/minecraft/server/commands/TimeCommand.java +@@ -2,76 +2,97 @@ + + import com.mojang.brigadier.CommandDispatcher; + import com.mojang.brigadier.arguments.IntegerArgumentType; +-import com.mojang.brigadier.context.CommandContext; ++import com.mojang.brigadier.builder.LiteralArgumentBuilder; ++import java.util.Iterator; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.arguments.TimeArgument; + import net.minecraft.network.chat.Component; + import net.minecraft.server.level.ServerLevel; ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.event.world.TimeSkipEvent; ++// CraftBukkit end + + public class TimeCommand { ++ ++ public TimeCommand() {} ++ + public static void register(CommandDispatcher dispatcher) { +- dispatcher.register( +- Commands.literal("time") +- .requires(source -> source.hasPermission(2)) +- .then( +- Commands.literal("set") +- .then(Commands.literal("day").executes(context -> setTime(context.getSource(), 1000))) +- .then(Commands.literal("noon").executes(context -> setTime(context.getSource(), 6000))) +- .then(Commands.literal("night").executes(context -> setTime(context.getSource(), 13000))) +- .then(Commands.literal("midnight").executes(context -> setTime(context.getSource(), 18000))) +- .then( +- Commands.argument("time", TimeArgument.time()) +- .executes(context -> setTime(context.getSource(), IntegerArgumentType.getInteger(context, "time"))) +- ) +- ) +- .then( +- Commands.literal("add") +- .then( +- Commands.argument("time", TimeArgument.time()) +- .executes(context -> addTime(context.getSource(), IntegerArgumentType.getInteger(context, "time"))) +- ) +- ) +- .then( +- Commands.literal("query") +- .then(Commands.literal("daytime").executes(context -> queryTime(context.getSource(), getDayTime(context.getSource().getLevel())))) +- .then( +- Commands.literal("gametime") +- .executes(context -> queryTime(context.getSource(), (int)(context.getSource().getLevel().getGameTime() % 2147483647L))) +- ) +- .then( +- Commands.literal("day") +- .executes(context -> queryTime(context.getSource(), (int)(context.getSource().getLevel().getDayTime() / 24000L % 2147483647L))) +- ) +- ) +- ); ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("time").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).then(((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("set").then(net.minecraft.commands.Commands.literal("day").executes((commandcontext) -> { ++ return setTime((CommandSourceStack) commandcontext.getSource(), 1000); ++ }))).then(net.minecraft.commands.Commands.literal("noon").executes((commandcontext) -> { ++ return setTime((CommandSourceStack) commandcontext.getSource(), 6000); ++ }))).then(net.minecraft.commands.Commands.literal("night").executes((commandcontext) -> { ++ return setTime((CommandSourceStack) commandcontext.getSource(), 13000); ++ }))).then(net.minecraft.commands.Commands.literal("midnight").executes((commandcontext) -> { ++ return setTime((CommandSourceStack) commandcontext.getSource(), 18000); ++ }))).then(net.minecraft.commands.Commands.argument("time", TimeArgument.time()).executes((commandcontext) -> { ++ return setTime((CommandSourceStack) commandcontext.getSource(), IntegerArgumentType.getInteger(commandcontext, "time")); ++ })))).then(net.minecraft.commands.Commands.literal("add").then(net.minecraft.commands.Commands.argument("time", TimeArgument.time()).executes((commandcontext) -> { ++ return addTime((CommandSourceStack) commandcontext.getSource(), IntegerArgumentType.getInteger(commandcontext, "time")); ++ })))).then(((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("query").then(net.minecraft.commands.Commands.literal("daytime").executes((commandcontext) -> { ++ return queryTime((CommandSourceStack) commandcontext.getSource(), getDayTime(((CommandSourceStack) commandcontext.getSource()).getLevel())); ++ }))).then(net.minecraft.commands.Commands.literal("gametime").executes((commandcontext) -> { ++ return queryTime((CommandSourceStack) commandcontext.getSource(), (int) (((CommandSourceStack) commandcontext.getSource()).getLevel().getGameTime() % 2147483647L)); ++ }))).then(net.minecraft.commands.Commands.literal("day").executes((commandcontext) -> { ++ return queryTime((CommandSourceStack) commandcontext.getSource(), (int) (((CommandSourceStack) commandcontext.getSource()).getLevel().getDayTime() / 24000L % 2147483647L)); ++ })))); + } + + private static int getDayTime(ServerLevel level) { +- return (int)(level.getDayTime() % 24000L); ++ return (int) (level.getDayTime() % 24000L); + } + + private static int queryTime(CommandSourceStack source, int time) { +- source.sendSuccess(() -> Component.translatable("commands.time.query", time), false); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.time.query", time); ++ }, false); + return time; + } + + public static int setTime(CommandSourceStack source, int time) { +- for (ServerLevel serverLevel : source.getServer().getAllLevels()) { +- serverLevel.setDayTime((long)time); ++ Iterator iterator = com.google.common.collect.Iterators.singletonIterator(source.getLevel()); // CraftBukkit - SPIGOT-6496: Only set the time for the world the command originates in ++ ++ while (iterator.hasNext()) { ++ ServerLevel worldserver = (ServerLevel) iterator.next(); ++ ++ // CraftBukkit start ++ TimeSkipEvent event = new TimeSkipEvent(worldserver.getWorld(), TimeSkipEvent.SkipReason.COMMAND, time - worldserver.getDayTime()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ worldserver.setDayTime((long) worldserver.getDayTime() + event.getSkipAmount()); ++ } ++ // CraftBukkit end + } + +- source.sendSuccess(() -> Component.translatable("commands.time.set", time), true); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.time.set", time); ++ }, true); + return getDayTime(source.getLevel()); + } + + public static int addTime(CommandSourceStack source, int amount) { +- for (ServerLevel serverLevel : source.getServer().getAllLevels()) { +- serverLevel.setDayTime(serverLevel.getDayTime() + (long)amount); ++ Iterator iterator = com.google.common.collect.Iterators.singletonIterator(source.getLevel()); // CraftBukkit - SPIGOT-6496: Only set the time for the world the command originates in ++ ++ while (iterator.hasNext()) { ++ ServerLevel worldserver = (ServerLevel) iterator.next(); ++ ++ // CraftBukkit start ++ TimeSkipEvent event = new TimeSkipEvent(worldserver.getWorld(), TimeSkipEvent.SkipReason.COMMAND, amount); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ worldserver.setDayTime(worldserver.getDayTime() + event.getSkipAmount()); ++ } ++ // CraftBukkit end + } + +- int dayTime = getDayTime(source.getLevel()); +- source.sendSuccess(() -> Component.translatable("commands.time.set", dayTime), true); +- return dayTime; ++ int j = getDayTime(source.getLevel()); ++ ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.time.set", j); ++ }, true); ++ return j; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/commands/WorldBorderCommand.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/commands/WorldBorderCommand.java.patch new file mode 100644 index 0000000000..addc8865a7 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/commands/WorldBorderCommand.java.patch @@ -0,0 +1,353 @@ +--- a/net/minecraft/server/commands/WorldBorderCommand.java ++++ b/net/minecraft/server/commands/WorldBorderCommand.java +@@ -4,12 +4,12 @@ + import com.mojang.brigadier.arguments.DoubleArgumentType; + import com.mojang.brigadier.arguments.FloatArgumentType; + import com.mojang.brigadier.arguments.IntegerArgumentType; +-import com.mojang.brigadier.context.CommandContext; ++import com.mojang.brigadier.builder.LiteralArgumentBuilder; ++import com.mojang.brigadier.builder.RequiredArgumentBuilder; + import com.mojang.brigadier.exceptions.CommandSyntaxException; + import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; + import java.util.Locale; + import net.minecraft.commands.CommandSourceStack; +-import net.minecraft.commands.Commands; + import net.minecraft.commands.arguments.coordinates.Vec2Argument; + import net.minecraft.network.chat.Component; + import net.minecraft.util.Mth; +@@ -17,226 +17,156 @@ + import net.minecraft.world.phys.Vec2; + + public class WorldBorderCommand { +- private static final SimpleCommandExceptionType ERROR_SAME_CENTER = new SimpleCommandExceptionType( +- Component.translatable("commands.worldborder.center.failed") +- ); +- private static final SimpleCommandExceptionType ERROR_SAME_SIZE = new SimpleCommandExceptionType( +- Component.translatable("commands.worldborder.set.failed.nochange") +- ); +- private static final SimpleCommandExceptionType ERROR_TOO_SMALL = new SimpleCommandExceptionType( +- Component.translatable("commands.worldborder.set.failed.small") +- ); +- private static final SimpleCommandExceptionType ERROR_TOO_BIG = new SimpleCommandExceptionType( +- Component.translatable("commands.worldborder.set.failed.big", 5.999997E7F) +- ); +- private static final SimpleCommandExceptionType ERROR_TOO_FAR_OUT = new SimpleCommandExceptionType( +- Component.translatable("commands.worldborder.set.failed.far", 2.9999984E7) +- ); +- private static final SimpleCommandExceptionType ERROR_SAME_WARNING_TIME = new SimpleCommandExceptionType( +- Component.translatable("commands.worldborder.warning.time.failed") +- ); +- private static final SimpleCommandExceptionType ERROR_SAME_WARNING_DISTANCE = new SimpleCommandExceptionType( +- Component.translatable("commands.worldborder.warning.distance.failed") +- ); +- private static final SimpleCommandExceptionType ERROR_SAME_DAMAGE_BUFFER = new SimpleCommandExceptionType( +- Component.translatable("commands.worldborder.damage.buffer.failed") +- ); +- private static final SimpleCommandExceptionType ERROR_SAME_DAMAGE_AMOUNT = new SimpleCommandExceptionType( +- Component.translatable("commands.worldborder.damage.amount.failed") +- ); + ++ private static final SimpleCommandExceptionType ERROR_SAME_CENTER = new SimpleCommandExceptionType(Component.translatable("commands.worldborder.center.failed")); ++ private static final SimpleCommandExceptionType ERROR_SAME_SIZE = new SimpleCommandExceptionType(Component.translatable("commands.worldborder.set.failed.nochange")); ++ private static final SimpleCommandExceptionType ERROR_TOO_SMALL = new SimpleCommandExceptionType(Component.translatable("commands.worldborder.set.failed.small")); ++ private static final SimpleCommandExceptionType ERROR_TOO_BIG = new SimpleCommandExceptionType(Component.translatable("commands.worldborder.set.failed.big", 5.9999968E7D)); ++ private static final SimpleCommandExceptionType ERROR_TOO_FAR_OUT = new SimpleCommandExceptionType(Component.translatable("commands.worldborder.set.failed.far", 2.9999984E7D)); ++ private static final SimpleCommandExceptionType ERROR_SAME_WARNING_TIME = new SimpleCommandExceptionType(Component.translatable("commands.worldborder.warning.time.failed")); ++ private static final SimpleCommandExceptionType ERROR_SAME_WARNING_DISTANCE = new SimpleCommandExceptionType(Component.translatable("commands.worldborder.warning.distance.failed")); ++ private static final SimpleCommandExceptionType ERROR_SAME_DAMAGE_BUFFER = new SimpleCommandExceptionType(Component.translatable("commands.worldborder.damage.buffer.failed")); ++ private static final SimpleCommandExceptionType ERROR_SAME_DAMAGE_AMOUNT = new SimpleCommandExceptionType(Component.translatable("commands.worldborder.damage.amount.failed")); ++ ++ public WorldBorderCommand() {} ++ + public static void register(CommandDispatcher dispatcher) { +- dispatcher.register( +- Commands.literal("worldborder") +- .requires(source -> source.hasPermission(2)) +- .then( +- Commands.literal("add") +- .then( +- Commands.argument("distance", DoubleArgumentType.doubleArg(-5.999997E7F, 5.999997E7F)) +- .executes( +- context -> setSize( +- context.getSource(), +- context.getSource().getLevel().getWorldBorder().getSize() + DoubleArgumentType.getDouble(context, "distance"), +- 0L +- ) +- ) +- .then( +- Commands.argument("time", IntegerArgumentType.integer(0)) +- .executes( +- context -> setSize( +- context.getSource(), +- context.getSource().getLevel().getWorldBorder().getSize() +- + DoubleArgumentType.getDouble(context, "distance"), +- context.getSource().getLevel().getWorldBorder().getLerpRemainingTime() +- + (long)IntegerArgumentType.getInteger(context, "time") * 1000L +- ) +- ) +- ) +- ) +- ) +- .then( +- Commands.literal("set") +- .then( +- Commands.argument("distance", DoubleArgumentType.doubleArg(-5.999997E7F, 5.999997E7F)) +- .executes(context -> setSize(context.getSource(), DoubleArgumentType.getDouble(context, "distance"), 0L)) +- .then( +- Commands.argument("time", IntegerArgumentType.integer(0)) +- .executes( +- context -> setSize( +- context.getSource(), +- DoubleArgumentType.getDouble(context, "distance"), +- (long)IntegerArgumentType.getInteger(context, "time") * 1000L +- ) +- ) +- ) +- ) +- ) +- .then( +- Commands.literal("center") +- .then( +- Commands.argument("pos", Vec2Argument.vec2()) +- .executes(context -> setCenter(context.getSource(), Vec2Argument.getVec2(context, "pos"))) +- ) +- ) +- .then( +- Commands.literal("damage") +- .then( +- Commands.literal("amount") +- .then( +- Commands.argument("damagePerBlock", FloatArgumentType.floatArg(0.0F)) +- .executes(context -> setDamageAmount(context.getSource(), FloatArgumentType.getFloat(context, "damagePerBlock"))) +- ) +- ) +- .then( +- Commands.literal("buffer") +- .then( +- Commands.argument("distance", FloatArgumentType.floatArg(0.0F)) +- .executes(context -> setDamageBuffer(context.getSource(), FloatArgumentType.getFloat(context, "distance"))) +- ) +- ) +- ) +- .then(Commands.literal("get").executes(context -> getSize(context.getSource()))) +- .then( +- Commands.literal("warning") +- .then( +- Commands.literal("distance") +- .then( +- Commands.argument("distance", IntegerArgumentType.integer(0)) +- .executes(context -> setWarningDistance(context.getSource(), IntegerArgumentType.getInteger(context, "distance"))) +- ) +- ) +- .then( +- Commands.literal("time") +- .then( +- Commands.argument("time", IntegerArgumentType.integer(0)) +- .executes(context -> setWarningTime(context.getSource(), IntegerArgumentType.getInteger(context, "time"))) +- ) +- ) +- ) +- ); ++ dispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("worldborder").requires((commandlistenerwrapper) -> { ++ return commandlistenerwrapper.hasPermission(2); ++ })).then(net.minecraft.commands.Commands.literal("add").then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("distance", DoubleArgumentType.doubleArg(-5.9999968E7D, 5.9999968E7D)).executes((commandcontext) -> { ++ return setSize((CommandSourceStack) commandcontext.getSource(), ((CommandSourceStack) commandcontext.getSource()).getLevel().getWorldBorder().getSize() + DoubleArgumentType.getDouble(commandcontext, "distance"), 0L); ++ })).then(net.minecraft.commands.Commands.argument("time", IntegerArgumentType.integer(0)).executes((commandcontext) -> { ++ return setSize((CommandSourceStack) commandcontext.getSource(), ((CommandSourceStack) commandcontext.getSource()).getLevel().getWorldBorder().getSize() + DoubleArgumentType.getDouble(commandcontext, "distance"), ((CommandSourceStack) commandcontext.getSource()).getLevel().getWorldBorder().getLerpRemainingTime() + (long) IntegerArgumentType.getInteger(commandcontext, "time") * 1000L); ++ }))))).then(net.minecraft.commands.Commands.literal("set").then(((RequiredArgumentBuilder) net.minecraft.commands.Commands.argument("distance", DoubleArgumentType.doubleArg(-5.9999968E7D, 5.9999968E7D)).executes((commandcontext) -> { ++ return setSize((CommandSourceStack) commandcontext.getSource(), DoubleArgumentType.getDouble(commandcontext, "distance"), 0L); ++ })).then(net.minecraft.commands.Commands.argument("time", IntegerArgumentType.integer(0)).executes((commandcontext) -> { ++ return setSize((CommandSourceStack) commandcontext.getSource(), DoubleArgumentType.getDouble(commandcontext, "distance"), (long) IntegerArgumentType.getInteger(commandcontext, "time") * 1000L); ++ }))))).then(net.minecraft.commands.Commands.literal("center").then(net.minecraft.commands.Commands.argument("pos", Vec2Argument.vec2()).executes((commandcontext) -> { ++ return setCenter((CommandSourceStack) commandcontext.getSource(), Vec2Argument.getVec2(commandcontext, "pos")); ++ })))).then(((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("damage").then(net.minecraft.commands.Commands.literal("amount").then(net.minecraft.commands.Commands.argument("damagePerBlock", FloatArgumentType.floatArg(0.0F)).executes((commandcontext) -> { ++ return setDamageAmount((CommandSourceStack) commandcontext.getSource(), FloatArgumentType.getFloat(commandcontext, "damagePerBlock")); ++ })))).then(net.minecraft.commands.Commands.literal("buffer").then(net.minecraft.commands.Commands.argument("distance", FloatArgumentType.floatArg(0.0F)).executes((commandcontext) -> { ++ return setDamageBuffer((CommandSourceStack) commandcontext.getSource(), FloatArgumentType.getFloat(commandcontext, "distance")); ++ }))))).then(net.minecraft.commands.Commands.literal("get").executes((commandcontext) -> { ++ return getSize((CommandSourceStack) commandcontext.getSource()); ++ }))).then(((LiteralArgumentBuilder) net.minecraft.commands.Commands.literal("warning").then(net.minecraft.commands.Commands.literal("distance").then(net.minecraft.commands.Commands.argument("distance", IntegerArgumentType.integer(0)).executes((commandcontext) -> { ++ return setWarningDistance((CommandSourceStack) commandcontext.getSource(), IntegerArgumentType.getInteger(commandcontext, "distance")); ++ })))).then(net.minecraft.commands.Commands.literal("time").then(net.minecraft.commands.Commands.argument("time", IntegerArgumentType.integer(0)).executes((commandcontext) -> { ++ return setWarningTime((CommandSourceStack) commandcontext.getSource(), IntegerArgumentType.getInteger(commandcontext, "time")); ++ }))))); + } + + private static int setDamageBuffer(CommandSourceStack source, float distance) throws CommandSyntaxException { +- WorldBorder worldBorder = source.getServer().overworld().getWorldBorder(); +- if (worldBorder.getDamageSafeZone() == (double)distance) { +- throw ERROR_SAME_DAMAGE_BUFFER.create(); ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit ++ ++ if (worldborder.getDamageSafeZone() == (double) distance) { ++ throw WorldBorderCommand.ERROR_SAME_DAMAGE_BUFFER.create(); + } else { +- worldBorder.setDamageSafeZone((double)distance); +- source.sendSuccess(() -> Component.translatable("commands.worldborder.damage.buffer.success", String.format(Locale.ROOT, "%.2f", distance)), true); +- return (int)distance; ++ worldborder.setDamageSafeZone((double) distance); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.worldborder.damage.buffer.success", String.format(Locale.ROOT, "%.2f", distance)); ++ }, true); ++ return (int) distance; + } + } + + private static int setDamageAmount(CommandSourceStack source, float damagePerBlock) throws CommandSyntaxException { +- WorldBorder worldBorder = source.getServer().overworld().getWorldBorder(); +- if (worldBorder.getDamagePerBlock() == (double)damagePerBlock) { +- throw ERROR_SAME_DAMAGE_AMOUNT.create(); ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit ++ ++ if (worldborder.getDamagePerBlock() == (double) damagePerBlock) { ++ throw WorldBorderCommand.ERROR_SAME_DAMAGE_AMOUNT.create(); + } else { +- worldBorder.setDamagePerBlock((double)damagePerBlock); +- source.sendSuccess( +- () -> Component.translatable("commands.worldborder.damage.amount.success", String.format(Locale.ROOT, "%.2f", damagePerBlock)), true +- ); +- return (int)damagePerBlock; ++ worldborder.setDamagePerBlock((double) damagePerBlock); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.worldborder.damage.amount.success", String.format(Locale.ROOT, "%.2f", damagePerBlock)); ++ }, true); ++ return (int) damagePerBlock; + } + } + + private static int setWarningTime(CommandSourceStack source, int time) throws CommandSyntaxException { +- WorldBorder worldBorder = source.getServer().overworld().getWorldBorder(); +- if (worldBorder.getWarningTime() == time) { +- throw ERROR_SAME_WARNING_TIME.create(); ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit ++ ++ if (worldborder.getWarningTime() == time) { ++ throw WorldBorderCommand.ERROR_SAME_WARNING_TIME.create(); + } else { +- worldBorder.setWarningTime(time); +- source.sendSuccess(() -> Component.translatable("commands.worldborder.warning.time.success", time), true); ++ worldborder.setWarningTime(time); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.worldborder.warning.time.success", time); ++ }, true); + return time; + } + } + + private static int setWarningDistance(CommandSourceStack source, int distance) throws CommandSyntaxException { +- WorldBorder worldBorder = source.getServer().overworld().getWorldBorder(); +- if (worldBorder.getWarningBlocks() == distance) { +- throw ERROR_SAME_WARNING_DISTANCE.create(); ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit ++ ++ if (worldborder.getWarningBlocks() == distance) { ++ throw WorldBorderCommand.ERROR_SAME_WARNING_DISTANCE.create(); + } else { +- worldBorder.setWarningBlocks(distance); +- source.sendSuccess(() -> Component.translatable("commands.worldborder.warning.distance.success", distance), true); ++ worldborder.setWarningBlocks(distance); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.worldborder.warning.distance.success", distance); ++ }, true); + return distance; + } + } + + private static int getSize(CommandSourceStack source) { +- double size = source.getServer().overworld().getWorldBorder().getSize(); +- source.sendSuccess(() -> Component.translatable("commands.worldborder.get", String.format(Locale.ROOT, "%.0f", size)), false); +- return Mth.floor(size + 0.5); ++ double d0 = source.getLevel().getWorldBorder().getSize(); // CraftBukkit ++ ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.worldborder.get", String.format(Locale.ROOT, "%.0f", d0)); ++ }, false); ++ return Mth.floor(d0 + 0.5D); + } + + private static int setCenter(CommandSourceStack source, Vec2 pos) throws CommandSyntaxException { +- WorldBorder worldBorder = source.getServer().overworld().getWorldBorder(); +- if (worldBorder.getCenterX() == (double)pos.x && worldBorder.getCenterZ() == (double)pos.y) { +- throw ERROR_SAME_CENTER.create(); +- } else if (!((double)Math.abs(pos.x) > 2.9999984E7) && !((double)Math.abs(pos.y) > 2.9999984E7)) { +- worldBorder.setCenter((double)pos.x, (double)pos.y); +- source.sendSuccess( +- () -> Component.translatable( +- "commands.worldborder.center.success", String.format(Locale.ROOT, "%.2f", pos.x), String.format(Locale.ROOT, "%.2f", pos.y) +- ), +- true +- ); ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit ++ ++ if (worldborder.getCenterX() == (double) pos.x && worldborder.getCenterZ() == (double) pos.y) { ++ throw WorldBorderCommand.ERROR_SAME_CENTER.create(); ++ } else if ((double) Math.abs(pos.x) <= 2.9999984E7D && (double) Math.abs(pos.y) <= 2.9999984E7D) { ++ worldborder.setCenter((double) pos.x, (double) pos.y); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.worldborder.center.success", String.format(Locale.ROOT, "%.2f", pos.x), String.format(Locale.ROOT, "%.2f", pos.y)); ++ }, true); + return 0; + } else { +- throw ERROR_TOO_FAR_OUT.create(); ++ throw WorldBorderCommand.ERROR_TOO_FAR_OUT.create(); + } + } + +- private static int setSize(CommandSourceStack source, double newSize, long time) throws CommandSyntaxException { +- WorldBorder worldBorder = source.getServer().overworld().getWorldBorder(); +- double size = worldBorder.getSize(); +- if (size == newSize) { +- throw ERROR_SAME_SIZE.create(); +- } else if (newSize < 1.0) { +- throw ERROR_TOO_SMALL.create(); +- } else if (newSize > 5.999997E7F) { +- throw ERROR_TOO_BIG.create(); ++ private static int setSize(CommandSourceStack source, double newSize, long i) throws CommandSyntaxException { ++ WorldBorder worldborder = source.getLevel().getWorldBorder(); // CraftBukkit ++ double d1 = worldborder.getSize(); ++ ++ if (d1 == newSize) { ++ throw WorldBorderCommand.ERROR_SAME_SIZE.create(); ++ } else if (newSize < 1.0D) { ++ throw WorldBorderCommand.ERROR_TOO_SMALL.create(); ++ } else if (newSize > 5.9999968E7D) { ++ throw WorldBorderCommand.ERROR_TOO_BIG.create(); + } else { +- if (time > 0L) { +- worldBorder.lerpSizeBetween(size, newSize, time); +- if (newSize > size) { +- source.sendSuccess( +- () -> Component.translatable("commands.worldborder.set.grow", String.format(Locale.ROOT, "%.1f", newSize), Long.toString(time / 1000L)), +- true +- ); ++ if (i > 0L) { ++ worldborder.lerpSizeBetween(d1, newSize, i); ++ if (newSize > d1) { ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.worldborder.set.grow", String.format(Locale.ROOT, "%.1f", newSize), Long.toString(i / 1000L)); ++ }, true); + } else { +- source.sendSuccess( +- () -> Component.translatable( +- "commands.worldborder.set.shrink", String.format(Locale.ROOT, "%.1f", newSize), Long.toString(time / 1000L) +- ), +- true +- ); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.worldborder.set.shrink", String.format(Locale.ROOT, "%.1f", newSize), Long.toString(i / 1000L)); ++ }, true); + } + } else { +- worldBorder.setSize(newSize); +- source.sendSuccess(() -> Component.translatable("commands.worldborder.set.immediate", String.format(Locale.ROOT, "%.1f", newSize)), true); ++ worldborder.setSize(newSize); ++ source.sendSuccess(() -> { ++ return Component.translatable("commands.worldborder.set.immediate", String.format(Locale.ROOT, "%.1f", newSize)); ++ }, true); + } + +- return (int)(newSize - size); ++ return (int) (newSize - d1); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/dedicated/DedicatedServer.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/dedicated/DedicatedServer.java.patch new file mode 100644 index 0000000000..452cf0ce70 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/dedicated/DedicatedServer.java.patch @@ -0,0 +1,624 @@ +--- a/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/net/minecraft/server/dedicated/DedicatedServer.java +@@ -5,9 +5,9 @@ + import com.mojang.datafixers.DataFixer; + import com.mojang.logging.LogUtils; + import java.io.BufferedReader; ++import java.io.BufferedWriter; + import java.io.IOException; + import java.io.InputStreamReader; +-import java.io.Writer; + import java.net.InetAddress; + import java.net.Proxy; + import java.nio.charset.StandardCharsets; +@@ -48,113 +48,176 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.GameType; +-import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.SkullBlockEntity; + import net.minecraft.world.level.storage.LevelStorageSource; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.server.WorldLoader; ++import org.apache.logging.log4j.Level; ++import org.apache.logging.log4j.LogManager; ++import org.apache.logging.log4j.io.IoBuilder; ++import org.bukkit.command.CommandSender; ++import org.bukkit.event.server.ServerCommandEvent; ++import org.bukkit.event.server.RemoteServerCommandEvent; ++// CraftBukkit end ++ + public class DedicatedServer extends MinecraftServer implements ServerInterface { ++ + static final Logger LOGGER = LogUtils.getLogger(); + private static final int CONVERSION_RETRY_DELAY_MS = 5000; + private static final int CONVERSION_RETRIES = 2; + private final List consoleInput = Collections.synchronizedList(Lists.newArrayList()); + @Nullable + private QueryThreadGs4 queryThreadGs4; +- private final RconConsoleSource rconConsoleSource; ++ // private final RemoteControlCommandListener rconConsoleSource; // CraftBukkit - remove field + @Nullable + private RconThread rconThread; +- private final DedicatedServerSettings settings; ++ public DedicatedServerSettings settings; + @Nullable + private MinecraftServerGui gui; + @Nullable + private final TextFilterClient textFilterClient; + +- public DedicatedServer( +- Thread serverThread, +- LevelStorageSource.LevelStorageAccess storageSource, +- PackRepository packRepository, +- WorldStem worldStem, +- DedicatedServerSettings settings, +- DataFixer fixerUpper, +- Services services, +- ChunkProgressListenerFactory progressListenerFactory +- ) { +- super(serverThread, storageSource, packRepository, worldStem, Proxy.NO_PROXY, fixerUpper, services, progressListenerFactory); +- this.settings = settings; +- this.rconConsoleSource = new RconConsoleSource(this); +- this.textFilterClient = TextFilterClient.createFromConfig(settings.getProperties().textFilteringConfig); ++ // CraftBukkit start - Signature changed ++ public DedicatedServer(joptsimple.OptionSet options, WorldLoader.a worldLoader, Thread thread, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PackRepository resourcepackrepository, WorldStem worldstem, DedicatedServerSettings dedicatedserversettings, DataFixer datafixer, Services services, ChunkProgressListenerFactory worldloadlistenerfactory) { ++ super(options, worldLoader, thread, convertable_conversionsession, resourcepackrepository, worldstem, Proxy.NO_PROXY, datafixer, services, worldloadlistenerfactory); ++ // CraftBukkit end ++ this.settings = dedicatedserversettings; ++ // this.rconConsoleSource = new RemoteControlCommandListener(this); // CraftBukkit - remove field ++ this.textFilterClient = TextFilterClient.createFromConfig(dedicatedserversettings.getProperties().textFilteringConfig); + } + + @Override + public boolean initServer() throws IOException { + Thread thread = new Thread("Server console handler") { +- @Override + public void run() { +- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8)); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.Main.useConsole) { ++ return; ++ } ++ jline.console.ConsoleReader bufferedreader = reader; + +- String string1; ++ // MC-33041, SPIGOT-5538: if System.in is not valid due to javaw, then return + try { +- while (!DedicatedServer.this.isStopped() && DedicatedServer.this.isRunning() && (string1 = bufferedReader.readLine()) != null) { +- DedicatedServer.this.handleConsoleInput(string1, DedicatedServer.this.createCommandSourceStack()); ++ System.in.available(); ++ } catch (IOException ex) { ++ return; ++ } ++ // CraftBukkit end ++ ++ String s; ++ ++ try { ++ // CraftBukkit start - JLine disabling compatibility ++ while (!DedicatedServer.this.isStopped() && DedicatedServer.this.isRunning()) { ++ if (org.bukkit.craftbukkit.Main.useJline) { ++ s = bufferedreader.readLine(">", null); ++ } else { ++ s = bufferedreader.readLine(); ++ } ++ ++ // SPIGOT-5220: Throttle if EOF (ctrl^d) or stdin is /dev/null ++ if (s == null) { ++ try { ++ Thread.sleep(50L); ++ } catch (InterruptedException ex) { ++ Thread.currentThread().interrupt(); ++ } ++ continue; ++ } ++ if (s.trim().length() > 0) { // Trim to filter lines which are just spaces ++ DedicatedServer.this.handleConsoleInput(s, DedicatedServer.this.createCommandSourceStack()); ++ } ++ // CraftBukkit end + } +- } catch (IOException var4) { +- DedicatedServer.LOGGER.error("Exception handling console input", (Throwable)var4); ++ } catch (IOException ioexception) { ++ DedicatedServer.LOGGER.error("Exception handling console input", ioexception); + } ++ + } + }; ++ ++ // CraftBukkit start - TODO: handle command-line logging arguments ++ java.util.logging.Logger global = java.util.logging.Logger.getLogger(""); ++ global.setUseParentHandlers(false); ++ for (java.util.logging.Handler handler : global.getHandlers()) { ++ global.removeHandler(handler); ++ } ++ global.addHandler(new org.bukkit.craftbukkit.util.ForwardLogHandler()); ++ ++ final org.apache.logging.log4j.core.Logger logger = ((org.apache.logging.log4j.core.Logger) LogManager.getRootLogger()); ++ for (org.apache.logging.log4j.core.Appender appender : logger.getAppenders().values()) { ++ if (appender instanceof org.apache.logging.log4j.core.appender.ConsoleAppender) { ++ logger.removeAppender(appender); ++ } ++ } ++ ++ new org.bukkit.craftbukkit.util.TerminalConsoleWriterThread(System.out, this.reader).start(); ++ ++ System.setOut(IoBuilder.forLogger(logger).setLevel(Level.INFO).buildPrintStream()); ++ System.setErr(IoBuilder.forLogger(logger).setLevel(Level.WARN).buildPrintStream()); ++ // CraftBukkit end ++ + thread.setDaemon(true); +- thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER)); ++ thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(DedicatedServer.LOGGER)); + thread.start(); +- LOGGER.info("Starting minecraft server version {}", SharedConstants.getCurrentVersion().getName()); ++ DedicatedServer.LOGGER.info("Starting minecraft server version {}", SharedConstants.getCurrentVersion().getName()); + if (Runtime.getRuntime().maxMemory() / 1024L / 1024L < 512L) { +- LOGGER.warn("To start the server with more ram, launch it as \"java -Xmx1024M -Xms1024M -jar minecraft_server.jar\""); ++ DedicatedServer.LOGGER.warn("To start the server with more ram, launch it as \"java -Xmx1024M -Xms1024M -jar minecraft_server.jar\""); + } + +- LOGGER.info("Loading properties"); +- DedicatedServerProperties properties = this.settings.getProperties(); ++ DedicatedServer.LOGGER.info("Loading properties"); ++ DedicatedServerProperties dedicatedserverproperties = this.settings.getProperties(); ++ + if (this.isSingleplayer()) { + this.setLocalIp("127.0.0.1"); + } else { +- this.setUsesAuthentication(properties.onlineMode); +- this.setPreventProxyConnections(properties.preventProxyConnections); +- this.setLocalIp(properties.serverIp); ++ this.setUsesAuthentication(dedicatedserverproperties.onlineMode); ++ this.setPreventProxyConnections(dedicatedserverproperties.preventProxyConnections); ++ this.setLocalIp(dedicatedserverproperties.serverIp); + } + +- this.setPvpAllowed(properties.pvp); +- this.setFlightAllowed(properties.allowFlight); +- this.setMotd(properties.motd); +- super.setPlayerIdleTimeout(properties.playerIdleTimeout.get()); +- this.setEnforceWhitelist(properties.enforceWhitelist); +- this.worldData.setGameType(properties.gamemode); +- LOGGER.info("Default game type: {}", properties.gamemode); +- InetAddress inetAddress = null; ++ this.setPvpAllowed(dedicatedserverproperties.pvp); ++ this.setFlightAllowed(dedicatedserverproperties.allowFlight); ++ this.setMotd(dedicatedserverproperties.motd); ++ super.setPlayerIdleTimeout((Integer) dedicatedserverproperties.playerIdleTimeout.get()); ++ this.setEnforceWhitelist(dedicatedserverproperties.enforceWhitelist); ++ // this.worldData.setGameType(dedicatedserverproperties.gamemode); // CraftBukkit - moved to world loading ++ DedicatedServer.LOGGER.info("Default game type: {}", dedicatedserverproperties.gamemode); ++ InetAddress inetaddress = null; ++ + if (!this.getLocalIp().isEmpty()) { +- inetAddress = InetAddress.getByName(this.getLocalIp()); ++ inetaddress = InetAddress.getByName(this.getLocalIp()); + } + + if (this.getPort() < 0) { +- this.setPort(properties.serverPort); ++ this.setPort(dedicatedserverproperties.serverPort); + } + + this.initializeKeyPair(); +- LOGGER.info("Starting Minecraft server on {}:{}", this.getLocalIp().isEmpty() ? "*" : this.getLocalIp(), this.getPort()); ++ DedicatedServer.LOGGER.info("Starting Minecraft server on {}:{}", this.getLocalIp().isEmpty() ? "*" : this.getLocalIp(), this.getPort()); + + try { +- this.getConnection().startTcpServerListener(inetAddress, this.getPort()); +- } catch (IOException var10) { +- LOGGER.warn("**** FAILED TO BIND TO PORT!"); +- LOGGER.warn("The exception was: {}", var10.toString()); +- LOGGER.warn("Perhaps a server is already running on that port?"); ++ this.getConnection().startTcpServerListener(inetaddress, this.getPort()); ++ } catch (IOException ioexception) { ++ DedicatedServer.LOGGER.warn("**** FAILED TO BIND TO PORT!"); ++ DedicatedServer.LOGGER.warn("The exception was: {}", ioexception.toString()); ++ DedicatedServer.LOGGER.warn("Perhaps a server is already running on that port?"); + return false; + } + ++ // CraftBukkit start ++ this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); ++ server.loadPlugins(); ++ server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.STARTUP); ++ // CraftBukkit end ++ + if (!this.usesAuthentication()) { +- LOGGER.warn("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!"); +- LOGGER.warn("The server will make no attempt to authenticate usernames. Beware."); +- LOGGER.warn( +- "While this makes the game possible to play without internet access, it also opens up the ability for hackers to connect with any username they choose." +- ); +- LOGGER.warn("To change this, set \"online-mode\" to \"true\" in the server.properties file."); ++ DedicatedServer.LOGGER.warn("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!"); ++ DedicatedServer.LOGGER.warn("The server will make no attempt to authenticate usernames. Beware."); ++ DedicatedServer.LOGGER.warn("While this makes the game possible to play without internet access, it also opens up the ability for hackers to connect with any username they choose."); ++ DedicatedServer.LOGGER.warn("To change this, set \"online-mode\" to \"true\" in the server.properties file."); + } + + if (this.convertOldUsers()) { +@@ -164,40 +227,43 @@ + if (!OldUsersConverter.serverReadyAfterUserconversion(this)) { + return false; + } else { +- this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); +- long nanos = Util.getNanos(); ++ // this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); // CraftBukkit - moved up ++ long i = Util.getNanos(); ++ + SkullBlockEntity.setup(this.services, this); + GameProfileCache.setUsesAuthentication(this.usesAuthentication()); +- LOGGER.info("Preparing level \"{}\"", this.getLevelIdName()); +- this.loadLevel(); +- long l = Util.getNanos() - nanos; +- String string = String.format(Locale.ROOT, "%.3fs", (double)l / 1.0E9); +- LOGGER.info("Done ({})! For help, type \"help\"", string); +- if (properties.announcePlayerAchievements != null) { +- this.getGameRules().getRule(GameRules.RULE_ANNOUNCE_ADVANCEMENTS).set(properties.announcePlayerAchievements, this); ++ DedicatedServer.LOGGER.info("Preparing level \"{}\"", this.getLevelIdName()); ++ this.loadLevel(storageSource.getLevelId()); // CraftBukkit ++ long j = Util.getNanos() - i; ++ String s = String.format(Locale.ROOT, "%.3fs", (double) j / 1.0E9D); ++ ++ DedicatedServer.LOGGER.info("Done ({})! For help, type \"help\"", s); ++ if (dedicatedserverproperties.announcePlayerAchievements != null) { ++ ((GameRules.BooleanValue) this.getGameRules().getRule(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)).set(dedicatedserverproperties.announcePlayerAchievements, this); + } + +- if (properties.enableQuery) { +- LOGGER.info("Starting GS4 status listener"); ++ if (dedicatedserverproperties.enableQuery) { ++ DedicatedServer.LOGGER.info("Starting GS4 status listener"); + this.queryThreadGs4 = QueryThreadGs4.create(this); + } + +- if (properties.enableRcon) { +- LOGGER.info("Starting remote control listener"); ++ if (dedicatedserverproperties.enableRcon) { ++ DedicatedServer.LOGGER.info("Starting remote control listener"); + this.rconThread = RconThread.create(this); + } + + if (this.getMaxTickLength() > 0L) { + Thread thread1 = new Thread(new ServerWatchdog(this)); +- thread1.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandlerWithName(LOGGER)); ++ ++ thread1.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandlerWithName(DedicatedServer.LOGGER)); + thread1.setName("Server Watchdog"); + thread1.setDaemon(true); + thread1.start(); + } + +- if (properties.enableJmxMonitoring) { ++ if (dedicatedserverproperties.enableJmxMonitoring) { + MinecraftServerStatistics.registerJmxMonitoring(this); +- LOGGER.info("JMX monitoring enabled"); ++ DedicatedServer.LOGGER.info("JMX monitoring enabled"); + } + + return true; +@@ -236,29 +302,49 @@ + + @Override + public SystemReport fillServerSystemReport(SystemReport report) { +- report.setDetail("Is Modded", () -> this.getModdedStatus().fullDescription()); +- report.setDetail("Type", () -> "Dedicated Server (map_server.txt)"); ++ report.setDetail("Is Modded", () -> { ++ return this.getModdedStatus().fullDescription(); ++ }); ++ report.setDetail("Type", () -> { ++ return "Dedicated Server (map_server.txt)"; ++ }); + return report; + } + + @Override + public void dumpServerProperties(Path path) throws IOException { +- DedicatedServerProperties properties = this.getProperties(); ++ DedicatedServerProperties dedicatedserverproperties = this.getProperties(); ++ BufferedWriter bufferedwriter = Files.newBufferedWriter(path); + +- try (Writer bufferedWriter = Files.newBufferedWriter(path)) { +- bufferedWriter.write(String.format(Locale.ROOT, "sync-chunk-writes=%s%n", properties.syncChunkWrites)); +- bufferedWriter.write(String.format(Locale.ROOT, "gamemode=%s%n", properties.gamemode)); +- bufferedWriter.write(String.format(Locale.ROOT, "spawn-monsters=%s%n", properties.spawnMonsters)); +- bufferedWriter.write(String.format(Locale.ROOT, "entity-broadcast-range-percentage=%d%n", properties.entityBroadcastRangePercentage)); +- bufferedWriter.write(String.format(Locale.ROOT, "max-world-size=%d%n", properties.maxWorldSize)); +- bufferedWriter.write(String.format(Locale.ROOT, "spawn-npcs=%s%n", properties.spawnNpcs)); +- bufferedWriter.write(String.format(Locale.ROOT, "view-distance=%d%n", properties.viewDistance)); +- bufferedWriter.write(String.format(Locale.ROOT, "simulation-distance=%d%n", properties.simulationDistance)); +- bufferedWriter.write(String.format(Locale.ROOT, "spawn-animals=%s%n", properties.spawnAnimals)); +- bufferedWriter.write(String.format(Locale.ROOT, "generate-structures=%s%n", properties.worldOptions.generateStructures())); +- bufferedWriter.write(String.format(Locale.ROOT, "use-native=%s%n", properties.useNativeTransport)); +- bufferedWriter.write(String.format(Locale.ROOT, "rate-limit=%d%n", properties.rateLimitPacketsPerSecond)); ++ try { ++ bufferedwriter.write(String.format(Locale.ROOT, "sync-chunk-writes=%s%n", dedicatedserverproperties.syncChunkWrites)); ++ bufferedwriter.write(String.format(Locale.ROOT, "gamemode=%s%n", dedicatedserverproperties.gamemode)); ++ bufferedwriter.write(String.format(Locale.ROOT, "spawn-monsters=%s%n", dedicatedserverproperties.spawnMonsters)); ++ bufferedwriter.write(String.format(Locale.ROOT, "entity-broadcast-range-percentage=%d%n", dedicatedserverproperties.entityBroadcastRangePercentage)); ++ bufferedwriter.write(String.format(Locale.ROOT, "max-world-size=%d%n", dedicatedserverproperties.maxWorldSize)); ++ bufferedwriter.write(String.format(Locale.ROOT, "spawn-npcs=%s%n", dedicatedserverproperties.spawnNpcs)); ++ bufferedwriter.write(String.format(Locale.ROOT, "view-distance=%d%n", dedicatedserverproperties.viewDistance)); ++ bufferedwriter.write(String.format(Locale.ROOT, "simulation-distance=%d%n", dedicatedserverproperties.simulationDistance)); ++ bufferedwriter.write(String.format(Locale.ROOT, "spawn-animals=%s%n", dedicatedserverproperties.spawnAnimals)); ++ bufferedwriter.write(String.format(Locale.ROOT, "generate-structures=%s%n", dedicatedserverproperties.worldOptions.generateStructures())); ++ bufferedwriter.write(String.format(Locale.ROOT, "use-native=%s%n", dedicatedserverproperties.useNativeTransport)); ++ bufferedwriter.write(String.format(Locale.ROOT, "rate-limit=%d%n", dedicatedserverproperties.rateLimitPacketsPerSecond)); ++ } catch (Throwable throwable) { ++ if (bufferedwriter != null) { ++ try { ++ bufferedwriter.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } ++ ++ if (bufferedwriter != null) { ++ bufferedwriter.close(); ++ } ++ + } + + @Override +@@ -278,6 +364,8 @@ + if (this.queryThreadGs4 != null) { + this.queryThreadGs4.stop(); + } ++ ++ System.exit(0); // CraftBukkit + } + + @Override +@@ -297,9 +385,19 @@ + + public void handleConsoleInputs() { + while (!this.consoleInput.isEmpty()) { +- ConsoleInput consoleInput = this.consoleInput.remove(0); +- this.getCommands().performPrefixedCommand(consoleInput.source, consoleInput.msg); ++ ConsoleInput servercommand = (ConsoleInput) this.consoleInput.remove(0); ++ ++ // CraftBukkit start - ServerCommand for preprocessing ++ ServerCommandEvent event = new ServerCommandEvent(console, servercommand.msg); ++ server.getPluginManager().callEvent(event); ++ if (event.isCancelled()) continue; ++ servercommand = new ConsoleInput(event.getCommand(), servercommand.source); ++ ++ // this.getCommands().performPrefixedCommand(servercommand.source, servercommand.msg); // Called in dispatchServerCommand ++ server.dispatchServerCommand(console, servercommand); ++ // CraftBukkit end + } ++ + } + + @Override +@@ -319,7 +417,7 @@ + + @Override + public DedicatedPlayerList getPlayerList() { +- return (DedicatedPlayerList)super.getPlayerList(); ++ return (DedicatedPlayerList) super.getPlayerList(); + } + + @Override +@@ -346,6 +444,7 @@ + if (this.gui == null) { + this.gui = MinecraftServerGui.showFrameFor(this); + } ++ + } + + @Override +@@ -365,7 +464,7 @@ + + @Override + public boolean isUnderSpawnProtection(ServerLevel level, BlockPos pos, Player player) { +- if (level.dimension() != Level.OVERWORLD) { ++ if (level.dimension() != net.minecraft.world.level.Level.OVERWORLD) { + return false; + } else if (this.getPlayerList().getOps().isEmpty()) { + return false; +@@ -374,11 +473,12 @@ + } else if (this.getSpawnProtectionRadius() <= 0) { + return false; + } else { +- BlockPos sharedSpawnPos = level.getSharedSpawnPos(); +- int abs = Mth.abs(pos.getX() - sharedSpawnPos.getX()); +- int abs1 = Mth.abs(pos.getZ() - sharedSpawnPos.getZ()); +- int max = Math.max(abs, abs1); +- return max <= this.getSpawnProtectionRadius(); ++ BlockPos blockposition1 = level.getSharedSpawnPos(); ++ int i = Mth.abs(pos.getX() - blockposition1.getX()); ++ int j = Mth.abs(pos.getZ() - blockposition1.getZ()); ++ int k = Math.max(i, j); ++ ++ return k <= this.getSpawnProtectionRadius(); + } + } + +@@ -405,7 +505,9 @@ + @Override + public void setPlayerIdleTimeout(int idleTimeout) { + super.setPlayerIdleTimeout(idleTimeout); +- this.settings.update(dedicatedServerProperties -> dedicatedServerProperties.playerIdleTimeout.update(this.registryAccess(), idleTimeout)); ++ this.settings.update((dedicatedserverproperties) -> { ++ return (DedicatedServerProperties) dedicatedserverproperties.playerIdleTimeout.update(this.registryAccess(), idleTimeout); ++ }); + } + + @Override +@@ -430,8 +532,9 @@ + + @Override + public boolean enforceSecureProfile() { +- DedicatedServerProperties properties = this.getProperties(); +- return properties.enforceSecureProfile && properties.onlineMode && this.services.canValidateProfileKeys(); ++ DedicatedServerProperties dedicatedserverproperties = this.getProperties(); ++ ++ return dedicatedserverproperties.enforceSecureProfile && dedicatedserverproperties.onlineMode && this.services.canValidateProfileKeys(); + } + + @Override +@@ -442,9 +545,11 @@ + protected boolean convertOldUsers() { + boolean flag = false; + +- for (int i = 0; !flag && i <= 2; i++) { ++ int i; ++ ++ for (i = 0; !flag && i <= 2; ++i) { + if (i > 0) { +- LOGGER.warn("Encountered a problem while converting the user banlist, retrying in a few seconds"); ++ DedicatedServer.LOGGER.warn("Encountered a problem while converting the user banlist, retrying in a few seconds"); + this.waitForRetry(); + } + +@@ -453,9 +558,9 @@ + + boolean flag1 = false; + +- for (int var7 = 0; !flag1 && var7 <= 2; var7++) { +- if (var7 > 0) { +- LOGGER.warn("Encountered a problem while converting the ip banlist, retrying in a few seconds"); ++ for (i = 0; !flag1 && i <= 2; ++i) { ++ if (i > 0) { ++ DedicatedServer.LOGGER.warn("Encountered a problem while converting the ip banlist, retrying in a few seconds"); + this.waitForRetry(); + } + +@@ -464,9 +569,9 @@ + + boolean flag2 = false; + +- for (int var8 = 0; !flag2 && var8 <= 2; var8++) { +- if (var8 > 0) { +- LOGGER.warn("Encountered a problem while converting the op list, retrying in a few seconds"); ++ for (i = 0; !flag2 && i <= 2; ++i) { ++ if (i > 0) { ++ DedicatedServer.LOGGER.warn("Encountered a problem while converting the op list, retrying in a few seconds"); + this.waitForRetry(); + } + +@@ -475,9 +580,9 @@ + + boolean flag3 = false; + +- for (int var9 = 0; !flag3 && var9 <= 2; var9++) { +- if (var9 > 0) { +- LOGGER.warn("Encountered a problem while converting the whitelist, retrying in a few seconds"); ++ for (i = 0; !flag3 && i <= 2; ++i) { ++ if (i > 0) { ++ DedicatedServer.LOGGER.warn("Encountered a problem while converting the whitelist, retrying in a few seconds"); + this.waitForRetry(); + } + +@@ -486,9 +591,9 @@ + + boolean flag4 = false; + +- for (int var10 = 0; !flag4 && var10 <= 2; var10++) { +- if (var10 > 0) { +- LOGGER.warn("Encountered a problem while converting the player save files, retrying in a few seconds"); ++ for (i = 0; !flag4 && i <= 2; ++i) { ++ if (i > 0) { ++ DedicatedServer.LOGGER.warn("Encountered a problem while converting the player save files, retrying in a few seconds"); + this.waitForRetry(); + } + +@@ -501,7 +606,8 @@ + private void waitForRetry() { + try { + Thread.sleep(5000L); +- } catch (InterruptedException var2) { ++ } catch (InterruptedException interruptedexception) { ++ ; + } + } + +@@ -516,18 +622,58 @@ + + @Override + public String getPluginNames() { +- return ""; ++ // CraftBukkit start - Whole method ++ StringBuilder result = new StringBuilder(); ++ org.bukkit.plugin.Plugin[] plugins = server.getPluginManager().getPlugins(); ++ ++ result.append(server.getName()); ++ result.append(" on Bukkit "); ++ result.append(server.getBukkitVersion()); ++ ++ if (plugins.length > 0 && server.getQueryPlugins()) { ++ result.append(": "); ++ ++ for (int i = 0; i < plugins.length; i++) { ++ if (i > 0) { ++ result.append("; "); ++ } ++ ++ result.append(plugins[i].getDescription().getName()); ++ result.append(" "); ++ result.append(plugins[i].getDescription().getVersion().replaceAll(";", ",")); ++ } ++ } ++ ++ return result.toString(); ++ // CraftBukkit end + } + + @Override + public String runCommand(String command) { +- this.rconConsoleSource.prepareForCommand(); +- this.executeBlocking(() -> this.getCommands().performPrefixedCommand(this.rconConsoleSource.createCommandSourceStack(), command)); +- return this.rconConsoleSource.getCommandResponse(); ++ // CraftBukkit start - fire RemoteServerCommandEvent ++ throw new UnsupportedOperationException("Not supported - remote source required."); + } + ++ public String runCommand(RconConsoleSource rconConsoleSource, String s) { ++ rconConsoleSource.prepareForCommand(); ++ this.executeBlocking(() -> { ++ CommandSourceStack wrapper = rconConsoleSource.createCommandSourceStack(); ++ RemoteServerCommandEvent event = new RemoteServerCommandEvent(rconConsoleSource.getBukkitSender(wrapper), s); ++ server.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ ConsoleInput serverCommand = new ConsoleInput(event.getCommand(), wrapper); ++ server.dispatchServerCommand(event.getSender(), serverCommand); ++ }); ++ return rconConsoleSource.getCommandResponse(); ++ // CraftBukkit end ++ } ++ + public void storeUsingWhiteList(boolean isStoreUsingWhiteList) { +- this.settings.update(dedicatedServerProperties -> dedicatedServerProperties.whiteList.update(this.registryAccess(), isStoreUsingWhiteList)); ++ this.settings.update((dedicatedserverproperties) -> { ++ return (DedicatedServerProperties) dedicatedserverproperties.whiteList.update(this.registryAccess(), isStoreUsingWhiteList); ++ }); + } + + @Override +@@ -572,4 +718,15 @@ + public Optional getServerResourcePack() { + return this.settings.getProperties().serverResourcePackInfo; + } ++ ++ // CraftBukkit start ++ public boolean isDebugging() { ++ return this.getProperties().debug; ++ } ++ ++ @Override ++ public CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return console; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/dedicated/DedicatedServerProperties.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/dedicated/DedicatedServerProperties.java.patch new file mode 100644 index 0000000000..0cdd374cd3 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/dedicated/DedicatedServerProperties.java.patch @@ -0,0 +1,392 @@ +--- a/net/minecraft/server/dedicated/DedicatedServerProperties.java ++++ b/net/minecraft/server/dedicated/DedicatedServerProperties.java +@@ -5,6 +5,7 @@ + import com.google.gson.JsonElement; + import com.google.gson.JsonObject; + import com.mojang.logging.LogUtils; ++import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; + import com.mojang.serialization.JsonOps; + import java.nio.charset.StandardCharsets; +@@ -12,6 +13,7 @@ + import java.util.List; + import java.util.Locale; + import java.util.Map; ++import java.util.Objects; + import java.util.Optional; + import java.util.Properties; + import java.util.UUID; +@@ -19,6 +21,7 @@ + import java.util.regex.Pattern; + import javax.annotation.Nullable; + import net.minecraft.core.Holder; ++import net.minecraft.core.HolderLookup; + import net.minecraft.core.Registry; + import net.minecraft.core.RegistryAccess; + import net.minecraft.core.registries.Registries; +@@ -41,10 +44,16 @@ + import net.minecraft.world.level.levelgen.presets.WorldPresets; + import org.slf4j.Logger; + ++// CraftBukkit start ++import joptsimple.OptionSet; ++// CraftBukkit end ++ + public class DedicatedServerProperties extends Settings { ++ + static final Logger LOGGER = LogUtils.getLogger(); + private static final Pattern SHA1 = Pattern.compile("^[a-fA-F0-9]{40}$"); + private static final Splitter COMMA_SPLITTER = Splitter.on(',').trimResults(); ++ public final boolean debug = this.get("debug", false); // CraftBukkit + public final boolean onlineMode = this.get("online-mode", true); + public final boolean preventProxyConnections = this.get("prevent-proxy-connections", false); + public final String serverIp = this.get("server-ip", ""); +@@ -55,83 +64,119 @@ + public final String motd = this.get("motd", "A Minecraft Server"); + public final boolean forceGameMode = this.get("force-gamemode", false); + public final boolean enforceWhitelist = this.get("enforce-whitelist", false); +- public final Difficulty difficulty = this.get( +- "difficulty", dispatchNumberOrString(Difficulty::byId, Difficulty::byName), Difficulty::getKey, Difficulty.EASY +- ); +- public final GameType gamemode = this.get("gamemode", dispatchNumberOrString(GameType::byId, GameType::byName), GameType::getName, GameType.SURVIVAL); +- public final String levelName = this.get("level-name", "world"); +- public final int serverPort = this.get("server-port", 25565); ++ public final Difficulty difficulty; ++ public final GameType gamemode; ++ public final String levelName; ++ public final int serverPort; + @Nullable +- public final Boolean announcePlayerAchievements = this.getLegacyBoolean("announce-player-achievements"); +- public final boolean enableQuery = this.get("enable-query", false); +- public final int queryPort = this.get("query.port", 25565); +- public final boolean enableRcon = this.get("enable-rcon", false); +- public final int rconPort = this.get("rcon.port", 25575); +- public final String rconPassword = this.get("rcon.password", ""); +- public final boolean hardcore = this.get("hardcore", false); +- public final boolean allowNether = this.get("allow-nether", true); +- public final boolean spawnMonsters = this.get("spawn-monsters", true); +- public final boolean useNativeTransport = this.get("use-native-transport", true); +- public final boolean enableCommandBlock = this.get("enable-command-block", false); +- public final int spawnProtection = this.get("spawn-protection", 16); +- public final int opPermissionLevel = this.get("op-permission-level", 4); +- public final int functionPermissionLevel = this.get("function-permission-level", 2); +- public final long maxTickTime = this.get("max-tick-time", TimeUnit.MINUTES.toMillis(1L)); +- public final int maxChainedNeighborUpdates = this.get("max-chained-neighbor-updates", 1000000); +- public final int rateLimitPacketsPerSecond = this.get("rate-limit", 0); +- public final int viewDistance = this.get("view-distance", 10); +- public final int simulationDistance = this.get("simulation-distance", 10); +- public final int maxPlayers = this.get("max-players", 20); +- public final int networkCompressionThreshold = this.get("network-compression-threshold", 256); +- public final boolean broadcastRconToOps = this.get("broadcast-rcon-to-ops", true); +- public final boolean broadcastConsoleToOps = this.get("broadcast-console-to-ops", true); +- public final int maxWorldSize = this.get("max-world-size", integer -> Mth.clamp(integer, 1, 29999984), 29999984); +- public final boolean syncChunkWrites = this.get("sync-chunk-writes", true); +- public final boolean enableJmxMonitoring = this.get("enable-jmx-monitoring", false); +- public final boolean enableStatus = this.get("enable-status", true); +- public final boolean hideOnlinePlayers = this.get("hide-online-players", false); +- public final int entityBroadcastRangePercentage = this.get("entity-broadcast-range-percentage", integer -> Mth.clamp(integer, 10, 1000), 100); +- public final String textFilteringConfig = this.get("text-filtering-config", ""); ++ public final Boolean announcePlayerAchievements; ++ public final boolean enableQuery; ++ public final int queryPort; ++ public final boolean enableRcon; ++ public final int rconPort; ++ public final String rconPassword; ++ public final boolean hardcore; ++ public final boolean allowNether; ++ public final boolean spawnMonsters; ++ public final boolean useNativeTransport; ++ public final boolean enableCommandBlock; ++ public final int spawnProtection; ++ public final int opPermissionLevel; ++ public final int functionPermissionLevel; ++ public final long maxTickTime; ++ public final int maxChainedNeighborUpdates; ++ public final int rateLimitPacketsPerSecond; ++ public final int viewDistance; ++ public final int simulationDistance; ++ public final int maxPlayers; ++ public final int networkCompressionThreshold; ++ public final boolean broadcastRconToOps; ++ public final boolean broadcastConsoleToOps; ++ public final int maxWorldSize; ++ public final boolean syncChunkWrites; ++ public final boolean enableJmxMonitoring; ++ public final boolean enableStatus; ++ public final boolean hideOnlinePlayers; ++ public final int entityBroadcastRangePercentage; ++ public final String textFilteringConfig; + public final Optional serverResourcePackInfo; + public final DataPackConfig initialDataPackConfiguration; +- public final Settings.MutableValue playerIdleTimeout = this.getMutable("player-idle-timeout", 0); +- public final Settings.MutableValue whiteList = this.getMutable("white-list", false); +- public final boolean enforceSecureProfile = this.get("enforce-secure-profile", true); +- public final boolean logIPs = this.get("log-ips", true); ++ public final Settings.MutableValue playerIdleTimeout; ++ public final Settings.MutableValue whiteList; ++ public final boolean enforceSecureProfile; ++ public final boolean logIPs; + private final DedicatedServerProperties.WorldDimensionData worldDimensionData; + public final WorldOptions worldOptions; + +- public DedicatedServerProperties(Properties properties) { +- super(properties); +- String string = this.get("level-seed", ""); ++ // CraftBukkit start ++ public DedicatedServerProperties(Properties properties, OptionSet optionset) { ++ super(properties, optionset); ++ // CraftBukkit end ++ this.difficulty = (Difficulty) this.get("difficulty", dispatchNumberOrString(Difficulty::byId, Difficulty::byName), Difficulty::getKey, Difficulty.EASY); ++ this.gamemode = (GameType) this.get("gamemode", dispatchNumberOrString(GameType::byId, GameType::byName), GameType::getName, GameType.SURVIVAL); ++ this.levelName = this.get("level-name", "world"); ++ this.serverPort = this.get("server-port", 25565); ++ this.announcePlayerAchievements = this.getLegacyBoolean("announce-player-achievements"); ++ this.enableQuery = this.get("enable-query", false); ++ this.queryPort = this.get("query.port", 25565); ++ this.enableRcon = this.get("enable-rcon", false); ++ this.rconPort = this.get("rcon.port", 25575); ++ this.rconPassword = this.get("rcon.password", ""); ++ this.hardcore = this.get("hardcore", false); ++ this.allowNether = this.get("allow-nether", true); ++ this.spawnMonsters = this.get("spawn-monsters", true); ++ this.useNativeTransport = this.get("use-native-transport", true); ++ this.enableCommandBlock = this.get("enable-command-block", false); ++ this.spawnProtection = this.get("spawn-protection", 16); ++ this.opPermissionLevel = this.get("op-permission-level", 4); ++ this.functionPermissionLevel = this.get("function-permission-level", 2); ++ this.maxTickTime = this.get("max-tick-time", TimeUnit.MINUTES.toMillis(1L)); ++ this.maxChainedNeighborUpdates = this.get("max-chained-neighbor-updates", 1000000); ++ this.rateLimitPacketsPerSecond = this.get("rate-limit", 0); ++ this.viewDistance = this.get("view-distance", 10); ++ this.simulationDistance = this.get("simulation-distance", 10); ++ this.maxPlayers = this.get("max-players", 20); ++ this.networkCompressionThreshold = this.get("network-compression-threshold", 256); ++ this.broadcastRconToOps = this.get("broadcast-rcon-to-ops", true); ++ this.broadcastConsoleToOps = this.get("broadcast-console-to-ops", true); ++ this.maxWorldSize = this.get("max-world-size", (integer) -> { ++ return Mth.clamp(integer, 1, 29999984); ++ }, 29999984); ++ this.syncChunkWrites = this.get("sync-chunk-writes", true); ++ this.enableJmxMonitoring = this.get("enable-jmx-monitoring", false); ++ this.enableStatus = this.get("enable-status", true); ++ this.hideOnlinePlayers = this.get("hide-online-players", false); ++ this.entityBroadcastRangePercentage = this.get("entity-broadcast-range-percentage", (integer) -> { ++ return Mth.clamp(integer, 10, 1000); ++ }, 100); ++ this.textFilteringConfig = this.get("text-filtering-config", ""); ++ this.playerIdleTimeout = this.getMutable("player-idle-timeout", 0); ++ this.whiteList = this.getMutable("white-list", false); ++ this.enforceSecureProfile = this.get("enforce-secure-profile", true); ++ this.logIPs = this.get("log-ips", true); ++ String s = this.get("level-seed", ""); + boolean flag = this.get("generate-structures", true); +- long l = WorldOptions.parseSeed(string).orElse(WorldOptions.randomSeed()); +- this.worldOptions = new WorldOptions(l, flag, false); +- this.worldDimensionData = new DedicatedServerProperties.WorldDimensionData( +- this.get("generator-settings", string1 -> GsonHelper.parse(!string1.isEmpty() ? string1 : "{}"), new JsonObject()), +- this.get("level-type", string1 -> string1.toLowerCase(Locale.ROOT), WorldPresets.NORMAL.location().toString()) +- ); +- this.serverResourcePackInfo = getServerPackInfo( +- this.get("resource-pack-id", ""), +- this.get("resource-pack", ""), +- this.get("resource-pack-sha1", ""), +- this.getLegacyString("resource-pack-hash"), +- this.get("require-resource-pack", false), +- this.get("resource-pack-prompt", "") +- ); +- this.initialDataPackConfiguration = getDatapackConfig( +- this.get("initial-enabled-packs", String.join(",", WorldDataConfiguration.DEFAULT.dataPacks().getEnabled())), +- this.get("initial-disabled-packs", String.join(",", WorldDataConfiguration.DEFAULT.dataPacks().getDisabled())) +- ); ++ long i = WorldOptions.parseSeed(s).orElse(WorldOptions.randomSeed()); ++ ++ this.worldOptions = new WorldOptions(i, flag, false); ++ this.worldDimensionData = new DedicatedServerProperties.WorldDimensionData((JsonObject) this.get("generator-settings", (s1) -> { ++ return GsonHelper.parse(!s1.isEmpty() ? s1 : "{}"); ++ }, new JsonObject()), (String) this.get("level-type", (s1) -> { ++ return s1.toLowerCase(Locale.ROOT); ++ }, WorldPresets.NORMAL.location().toString())); ++ this.serverResourcePackInfo = getServerPackInfo(this.get("resource-pack-id", ""), this.get("resource-pack", ""), this.get("resource-pack-sha1", ""), this.getLegacyString("resource-pack-hash"), this.get("require-resource-pack", false), this.get("resource-pack-prompt", "")); ++ this.initialDataPackConfiguration = getDatapackConfig(this.get("initial-enabled-packs", String.join(",", WorldDataConfiguration.DEFAULT.dataPacks().getEnabled())), this.get("initial-disabled-packs", String.join(",", WorldDataConfiguration.DEFAULT.dataPacks().getDisabled()))); + } + +- public static DedicatedServerProperties fromFile(Path path) { +- return new DedicatedServerProperties(loadFromFile(path)); ++ // CraftBukkit start ++ public static DedicatedServerProperties fromFile(Path path, OptionSet optionset) { ++ return new DedicatedServerProperties(loadFromFile(path), optionset); + } + + @Override +- protected DedicatedServerProperties reload(RegistryAccess registryAccess, Properties properties) { +- return new DedicatedServerProperties(properties); ++ protected DedicatedServerProperties reload(RegistryAccess iregistrycustom, Properties properties, OptionSet optionset) { ++ return new DedicatedServerProperties(properties, optionset); ++ // CraftBukkit end + } + + @Nullable +@@ -139,99 +184,106 @@ + if (!Strings.isNullOrEmpty(json)) { + try { + return Component.Serializer.fromJson(json); +- } catch (Exception var2) { +- LOGGER.warn("Failed to parse resource pack prompt '{}'", json, var2); ++ } catch (Exception exception) { ++ DedicatedServerProperties.LOGGER.warn("Failed to parse resource pack prompt '{}'", json, exception); + } + } + + return null; + } + +- private static Optional getServerPackInfo( +- String string, String string1, String string2, @Nullable String string3, boolean flag, String string4 +- ) { +- if (string1.isEmpty()) { ++ private static Optional getServerPackInfo(String s, String s1, String s2, @Nullable String s3, boolean flag, String s4) { ++ if (s1.isEmpty()) { + return Optional.empty(); + } else { +- String string5; +- if (!string2.isEmpty()) { +- string5 = string2; +- if (!Strings.isNullOrEmpty(string3)) { +- LOGGER.warn("resource-pack-hash is deprecated and found along side resource-pack-sha1. resource-pack-hash will be ignored."); ++ String s5; ++ ++ if (!s2.isEmpty()) { ++ s5 = s2; ++ if (!Strings.isNullOrEmpty(s3)) { ++ DedicatedServerProperties.LOGGER.warn("resource-pack-hash is deprecated and found along side resource-pack-sha1. resource-pack-hash will be ignored."); + } +- } else if (!Strings.isNullOrEmpty(string3)) { +- LOGGER.warn("resource-pack-hash is deprecated. Please use resource-pack-sha1 instead."); +- string5 = string3; ++ } else if (!Strings.isNullOrEmpty(s3)) { ++ DedicatedServerProperties.LOGGER.warn("resource-pack-hash is deprecated. Please use resource-pack-sha1 instead."); ++ s5 = s3; + } else { +- string5 = ""; ++ s5 = ""; + } + +- if (string5.isEmpty()) { +- LOGGER.warn( +- "You specified a resource pack without providing a sha1 hash. Pack will be updated on the client only if you change the name of the pack." +- ); +- } else if (!SHA1.matcher(string5).matches()) { +- LOGGER.warn("Invalid sha1 for resource-pack-sha1"); ++ if (s5.isEmpty()) { ++ DedicatedServerProperties.LOGGER.warn("You specified a resource pack without providing a sha1 hash. Pack will be updated on the client only if you change the name of the pack."); ++ } else if (!DedicatedServerProperties.SHA1.matcher(s5).matches()) { ++ DedicatedServerProperties.LOGGER.warn("Invalid sha1 for resource-pack-sha1"); + } + +- Component component = parseResourcePackPrompt(string4); +- UUID uUID; +- if (string.isEmpty()) { +- uUID = UUID.nameUUIDFromBytes(string1.getBytes(StandardCharsets.UTF_8)); +- LOGGER.warn("resource-pack-id missing, using default of {}", uUID); ++ Component ichatbasecomponent = parseResourcePackPrompt(s4); ++ UUID uuid; ++ ++ if (s.isEmpty()) { ++ uuid = UUID.nameUUIDFromBytes(s1.getBytes(StandardCharsets.UTF_8)); ++ DedicatedServerProperties.LOGGER.warn("resource-pack-id missing, using default of {}", uuid); + } else { + try { +- uUID = UUID.fromString(string); +- } catch (IllegalArgumentException var10) { +- LOGGER.warn("Failed to parse '{}' into UUID", string); ++ uuid = UUID.fromString(s); ++ } catch (IllegalArgumentException illegalargumentexception) { ++ DedicatedServerProperties.LOGGER.warn("Failed to parse '{}' into UUID", s); + return Optional.empty(); + } + } + +- return Optional.of(new MinecraftServer.ServerResourcePackInfo(uUID, string1, string5, flag, component)); ++ return Optional.of(new MinecraftServer.ServerResourcePackInfo(uuid, s1, s5, flag, ichatbasecomponent)); + } + } + + private static DataPackConfig getDatapackConfig(String initalEnabledPacks, String initialDisabledPacks) { +- List parts = COMMA_SPLITTER.splitToList(initalEnabledPacks); +- List parts1 = COMMA_SPLITTER.splitToList(initialDisabledPacks); +- return new DataPackConfig(parts, parts1); ++ List list = DedicatedServerProperties.COMMA_SPLITTER.splitToList(initalEnabledPacks); ++ List list1 = DedicatedServerProperties.COMMA_SPLITTER.splitToList(initialDisabledPacks); ++ ++ return new DataPackConfig(list, list1); + } + + public WorldDimensions createDimensions(RegistryAccess registryAccess) { + return this.worldDimensionData.create(registryAccess); + } + +- static record WorldDimensionData(JsonObject generatorSettings, String levelType) { +- private static final Map> LEGACY_PRESET_NAMES = Map.of( +- "default", WorldPresets.NORMAL, "largebiomes", WorldPresets.LARGE_BIOMES +- ); ++ public static record WorldDimensionData(JsonObject generatorSettings, String levelType) { + ++ private static final Map> LEGACY_PRESET_NAMES = Map.of("default", WorldPresets.NORMAL, "largebiomes", WorldPresets.LARGE_BIOMES); ++ + public WorldDimensions create(RegistryAccess registryAccess) { +- Registry registry = registryAccess.registryOrThrow(Registries.WORLD_PRESET); +- Holder.Reference reference = registry.getHolder(WorldPresets.NORMAL) +- .or(() -> registry.holders().findAny()) +- .orElseThrow(() -> new IllegalStateException("Invalid datapack contents: can't find default preset")); +- Holder holder = Optional.ofNullable(ResourceLocation.tryParse(this.levelType)) +- .map(resourceLocation -> ResourceKey.create(Registries.WORLD_PRESET, resourceLocation)) +- .or(() -> Optional.ofNullable(LEGACY_PRESET_NAMES.get(this.levelType))) +- .flatMap(registry::getHolder) +- .orElseGet(() -> { +- DedicatedServerProperties.LOGGER.warn("Failed to parse level-type {}, defaulting to {}", this.levelType, reference.key().location()); +- return reference; +- }); +- WorldDimensions worldDimensions = holder.value().createWorldDimensions(); ++ Registry iregistry = registryAccess.registryOrThrow(Registries.WORLD_PRESET); ++ Holder.Reference holder_c = (Holder.Reference) iregistry.getHolder(WorldPresets.NORMAL).or(() -> { ++ return iregistry.holders().findAny(); ++ }).orElseThrow(() -> { ++ return new IllegalStateException("Invalid datapack contents: can't find default preset"); ++ }); ++ Optional> optional = Optional.ofNullable(ResourceLocation.tryParse(this.levelType)).map((minecraftkey) -> { // CraftBukkit - decompile error ++ return ResourceKey.create(Registries.WORLD_PRESET, minecraftkey); ++ }).or(() -> { ++ return Optional.ofNullable(DedicatedServerProperties.WorldDimensionData.LEGACY_PRESET_NAMES.get(this.levelType)); // CraftBukkit - decompile error ++ }); ++ ++ Objects.requireNonNull(iregistry); ++ Holder holder = (Holder) optional.flatMap(iregistry::getHolder).orElseGet(() -> { ++ DedicatedServerProperties.LOGGER.warn("Failed to parse level-type {}, defaulting to {}", this.levelType, holder_c.key().location()); ++ return holder_c; ++ }); ++ WorldDimensions worlddimensions = ((WorldPreset) holder.value()).createWorldDimensions(); ++ + if (holder.is(WorldPresets.FLAT)) { +- RegistryOps registryOps = RegistryOps.create(JsonOps.INSTANCE, registryAccess); +- Optional optional = FlatLevelGeneratorSettings.CODEC +- .parse(new Dynamic<>(registryOps, this.generatorSettings())) +- .resultOrPartial(DedicatedServerProperties.LOGGER::error); +- if (optional.isPresent()) { +- return worldDimensions.replaceOverworldGenerator(registryAccess, new FlatLevelSource(optional.get())); ++ RegistryOps registryops = RegistryOps.create(JsonOps.INSTANCE, (HolderLookup.Provider) registryAccess); ++ DataResult dataresult = FlatLevelGeneratorSettings.CODEC.parse(new Dynamic(registryops, this.generatorSettings())); // CraftBukkit - decompile error ++ Logger logger = DedicatedServerProperties.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ Optional optional1 = dataresult.resultOrPartial(logger::error); ++ ++ if (optional1.isPresent()) { ++ return worlddimensions.replaceOverworldGenerator(registryAccess, new FlatLevelSource((FlatLevelGeneratorSettings) optional1.get())); + } + } + +- return worldDimensions; ++ return worlddimensions; + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/dedicated/DedicatedServerSettings.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/dedicated/DedicatedServerSettings.java.patch new file mode 100644 index 0000000000..81979f63f3 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/dedicated/DedicatedServerSettings.java.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/server/dedicated/DedicatedServerSettings.java ++++ b/net/minecraft/server/dedicated/DedicatedServerSettings.java +@@ -3,13 +3,21 @@ + import java.nio.file.Path; + import java.util.function.UnaryOperator; + ++// CraftBukkit start ++import java.io.File; ++import joptsimple.OptionSet; ++// CraftBukkit end ++ + public class DedicatedServerSettings { ++ + private final Path source; + private DedicatedServerProperties properties; + +- public DedicatedServerSettings(Path source) { +- this.source = source; +- this.properties = DedicatedServerProperties.fromFile(source); ++ // CraftBukkit start ++ public DedicatedServerSettings(OptionSet optionset) { ++ this.source = ((File) optionset.valueOf("config")).toPath(); ++ this.properties = DedicatedServerProperties.fromFile(source, optionset); ++ // CraftBukkit end + } + + public DedicatedServerProperties getProperties() { +@@ -21,7 +29,7 @@ + } + + public DedicatedServerSettings update(UnaryOperator propertiesOperator) { +- (this.properties = propertiesOperator.apply(this.properties)).store(this.source); ++ (this.properties = (DedicatedServerProperties) propertiesOperator.apply(this.properties)).store(this.source); + return this; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/dedicated/Settings.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/dedicated/Settings.java.patch new file mode 100644 index 0000000000..1cc8380859 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/dedicated/Settings.java.patch @@ -0,0 +1,361 @@ +--- a/net/minecraft/server/dedicated/Settings.java ++++ b/net/minecraft/server/dedicated/Settings.java +@@ -2,11 +2,11 @@ + + import com.google.common.base.MoreObjects; + import com.mojang.logging.LogUtils; ++import java.io.BufferedReader; ++import java.io.BufferedWriter; + import java.io.IOException; + import java.io.InputStream; + import java.io.InputStreamReader; +-import java.io.Reader; +-import java.io.Writer; + import java.nio.charset.CharacterCodingException; + import java.nio.charset.CharsetDecoder; + import java.nio.charset.CodingErrorAction; +@@ -20,112 +20,201 @@ + import java.util.function.Supplier; + import java.util.function.UnaryOperator; + import javax.annotation.Nullable; +-import net.minecraft.core.RegistryAccess; + import org.slf4j.Logger; + ++import joptsimple.OptionSet; // CraftBukkit ++import net.minecraft.core.RegistryAccess; ++ + public abstract class Settings> { ++ + private static final Logger LOGGER = LogUtils.getLogger(); +- protected final Properties properties; ++ public final Properties properties; ++ // CraftBukkit start ++ private OptionSet options = null; + +- public Settings(Properties properties) { ++ public Settings(Properties properties, final OptionSet options) { + this.properties = properties; ++ ++ this.options = options; + } + ++ private String getOverride(String name, String value) { ++ if ((this.options != null) && (this.options.has(name))) { ++ return String.valueOf(this.options.valueOf(name)); ++ } ++ ++ return value; ++ // CraftBukkit end ++ } ++ + public static Properties loadFromFile(Path path) { + try { ++ // CraftBukkit start - SPIGOT-7465, MC-264979: Don't load if file doesn't exist ++ if (!path.toFile().exists()) { ++ return new Properties(); ++ } ++ // CraftBukkit end ++ Properties properties; ++ Properties properties1; ++ + try { +- Properties var13; +- try (InputStream inputStream = Files.newInputStream(path)) { +- CharsetDecoder charsetDecoder = StandardCharsets.UTF_8 +- .newDecoder() +- .onMalformedInput(CodingErrorAction.REPORT) +- .onUnmappableCharacter(CodingErrorAction.REPORT); +- Properties map = new Properties(); +- map.load(new InputStreamReader(inputStream, charsetDecoder)); +- var13 = map; ++ InputStream inputstream = Files.newInputStream(path); ++ ++ try { ++ CharsetDecoder charsetdecoder = StandardCharsets.UTF_8.newDecoder().onMalformedInput(CodingErrorAction.REPORT).onUnmappableCharacter(CodingErrorAction.REPORT); ++ ++ properties = new Properties(); ++ properties.load(new InputStreamReader(inputstream, charsetdecoder)); ++ properties1 = properties; ++ } catch (Throwable throwable) { ++ if (inputstream != null) { ++ try { ++ inputstream.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } + +- return var13; +- } catch (CharacterCodingException var9) { +- LOGGER.info("Failed to load properties as UTF-8 from file {}, trying ISO_8859_1", path); ++ if (inputstream != null) { ++ inputstream.close(); ++ } + +- Properties var4; +- try (Reader bufferedReader = Files.newBufferedReader(path, StandardCharsets.ISO_8859_1)) { +- Properties map = new Properties(); +- map.load(bufferedReader); +- var4 = map; ++ return properties1; ++ } catch (CharacterCodingException charactercodingexception) { ++ Settings.LOGGER.info("Failed to load properties as UTF-8 from file {}, trying ISO_8859_1", path); ++ BufferedReader bufferedreader = Files.newBufferedReader(path, StandardCharsets.ISO_8859_1); ++ ++ try { ++ properties = new Properties(); ++ properties.load(bufferedreader); ++ properties1 = properties; ++ } catch (Throwable throwable2) { ++ if (bufferedreader != null) { ++ try { ++ bufferedreader.close(); ++ } catch (Throwable throwable3) { ++ throwable2.addSuppressed(throwable3); ++ } ++ } ++ ++ throw throwable2; + } + +- return var4; ++ if (bufferedreader != null) { ++ bufferedreader.close(); ++ } ++ ++ return properties1; + } +- } catch (IOException var10) { +- LOGGER.error("Failed to load properties from file: {}", path, var10); ++ } catch (IOException ioexception) { ++ Settings.LOGGER.error("Failed to load properties from file: {}", path, ioexception); + return new Properties(); + } + } + + public void store(Path path) { +- try (Writer bufferedWriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) { +- this.properties.store(bufferedWriter, "Minecraft server properties"); +- } catch (IOException var7) { +- LOGGER.error("Failed to store properties to file: {}", path); ++ try { ++ // CraftBukkit start - Don't attempt writing to file if it's read only ++ if (path.toFile().exists() && !path.toFile().canWrite()) { ++ return; ++ } ++ // CraftBukkit end ++ BufferedWriter bufferedwriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8); ++ ++ try { ++ this.properties.store(bufferedwriter, "Minecraft server properties"); ++ } catch (Throwable throwable) { ++ if (bufferedwriter != null) { ++ try { ++ bufferedwriter.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; ++ } ++ ++ if (bufferedwriter != null) { ++ bufferedwriter.close(); ++ } ++ } catch (IOException ioexception) { ++ Settings.LOGGER.error("Failed to store properties to file: {}", path); + } ++ + } + + private static Function wrapNumberDeserializer(Function parseFunc) { +- return string -> { ++ return (s) -> { + try { +- return parseFunc.apply(string); +- } catch (NumberFormatException var3) { ++ return (V) parseFunc.apply(s); // CraftBukkit - decompile error ++ } catch (NumberFormatException numberformatexception) { + return null; + } + }; + } + + protected static Function dispatchNumberOrString(IntFunction byId, Function byName) { +- return string -> { ++ return (s) -> { + try { +- return byId.apply(Integer.parseInt(string)); +- } catch (NumberFormatException var4) { +- return byName.apply(string); ++ return byId.apply(Integer.parseInt(s)); ++ } catch (NumberFormatException numberformatexception) { ++ return byName.apply(s); + } + }; + } + + @Nullable + private String getStringRaw(String key) { +- return (String)this.properties.get(key); ++ return (String) getOverride(key, this.properties.getProperty(key)); // CraftBukkit + } + + @Nullable + protected V getLegacy(String key, Function mapper) { +- String stringRaw = this.getStringRaw(key); +- if (stringRaw == null) { ++ String s1 = this.getStringRaw(key); ++ ++ if (s1 == null) { + return null; + } else { + this.properties.remove(key); +- return mapper.apply(stringRaw); ++ return mapper.apply(s1); + } + } + + protected V get(String key, Function mapper, Function toString, V value) { +- String stringRaw = this.getStringRaw(key); +- V object = MoreObjects.firstNonNull(stringRaw != null ? mapper.apply(stringRaw) : null, value); +- this.properties.put(key, toString.apply(object)); +- return object; ++ // CraftBukkit start ++ try { ++ return get0(key, mapper, toString, value); ++ } catch (Exception ex) { ++ throw new RuntimeException("Could not load invalidly configured property '" + key + "'", ex); ++ } + } + ++ private V get0(String s, Function function, Function function1, V v0) { ++ // CraftBukkit end ++ String s1 = this.getStringRaw(s); ++ V v1 = MoreObjects.firstNonNull(s1 != null ? function.apply(s1) : null, v0); ++ ++ this.properties.put(s, function1.apply(v1)); ++ return v1; ++ } ++ + protected Settings.MutableValue getMutable(String key, Function mapper, Function toString, V value) { +- String stringRaw = this.getStringRaw(key); +- V object = MoreObjects.firstNonNull(stringRaw != null ? mapper.apply(stringRaw) : null, value); +- this.properties.put(key, toString.apply(object)); +- return new Settings.MutableValue<>(key, object, toString); ++ String s1 = this.getStringRaw(key); ++ V v1 = MoreObjects.firstNonNull(s1 != null ? mapper.apply(s1) : null, value); ++ ++ this.properties.put(key, toString.apply(v1)); ++ return new Settings.MutableValue(key, v1, toString); // CraftBukkit - decompile error + } + +- protected V get(String key, Function mapper, UnaryOperator unaryOperator, Function toString, V value) { +- return this.get(key, string -> { +- V object = mapper.apply(string); +- return object != null ? unaryOperator.apply(object) : null; ++ protected V get(String key, Function mapper, UnaryOperator unaryoperator, Function toString, V value) { ++ return this.get(key, (s1) -> { ++ V v1 = mapper.apply(s1); ++ ++ return v1 != null ? unaryoperator.apply(v1) : null; + }, toString, value); + } + +@@ -138,32 +227,32 @@ + } + + protected String get(String key, String value) { +- return this.get(key, Function.identity(), Function.identity(), value); ++ return (String) this.get(key, Function.identity(), Function.identity(), value); + } + + @Nullable + protected String getLegacyString(String key) { +- return this.getLegacy(key, Function.identity()); ++ return (String) this.getLegacy(key, Function.identity()); + } + + protected int get(String key, int value) { +- return this.get(key, wrapNumberDeserializer(Integer::parseInt), Integer.valueOf(value)); ++ return (Integer) this.get(key, wrapNumberDeserializer(Integer::parseInt), value); + } + + protected Settings.MutableValue getMutable(String key, int value) { + return this.getMutable(key, wrapNumberDeserializer(Integer::parseInt), value); + } + +- protected int get(String key, UnaryOperator unaryOperator, int value) { +- return this.get(key, wrapNumberDeserializer(Integer::parseInt), unaryOperator, Objects::toString, value); ++ protected int get(String key, UnaryOperator unaryoperator, int value) { ++ return (Integer) this.get(key, wrapNumberDeserializer(Integer::parseInt), unaryoperator, Objects::toString, value); + } + + protected long get(String key, long value) { +- return this.get(key, wrapNumberDeserializer(Long::parseLong), value); ++ return (Long) this.get(key, wrapNumberDeserializer(Long::parseLong), value); + } + + protected boolean get(String key, boolean value) { +- return this.get(key, Boolean::valueOf, value); ++ return (Boolean) this.get(key, Boolean::valueOf, value); + } + + protected Settings.MutableValue getMutable(String key, boolean value) { +@@ -172,37 +261,39 @@ + + @Nullable + protected Boolean getLegacyBoolean(String key) { +- return this.getLegacy(key, Boolean::valueOf); ++ return (Boolean) this.getLegacy(key, Boolean::valueOf); + } + + protected Properties cloneProperties() { +- Properties map = new Properties(); +- map.putAll(this.properties); +- return map; ++ Properties properties = new Properties(); ++ ++ properties.putAll(this.properties); ++ return properties; + } + +- protected abstract T reload(RegistryAccess registryAccess, Properties properties); ++ protected abstract T reload(RegistryAccess iregistrycustom, Properties properties, OptionSet optionset); // CraftBukkit + + public class MutableValue implements Supplier { ++ + private final String key; + private final V value; + private final Function serializer; + +- MutableValue(String key, V value, Function serializer) { +- this.key = key; +- this.value = value; +- this.serializer = serializer; ++ MutableValue(String s, V object, Function function) { // CraftBukkit - decompile error ++ this.key = s; ++ this.value = object; ++ this.serializer = function; + } + +- @Override + public V get() { + return this.value; + } + + public T update(RegistryAccess registryAccess, V newValue) { +- Properties map = Settings.this.cloneProperties(); +- map.put(this.key, this.serializer.apply(newValue)); +- return Settings.this.reload(registryAccess, map); ++ Properties properties = Settings.this.cloneProperties(); ++ ++ properties.put(this.key, this.serializer.apply(newValue)); ++ return Settings.this.reload(registryAccess, properties, Settings.this.options); // CraftBukkit + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/gui/MinecraftServerGui.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/gui/MinecraftServerGui.java.patch new file mode 100644 index 0000000000..e176bc1c0d --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/gui/MinecraftServerGui.java.patch @@ -0,0 +1,240 @@ +--- a/net/minecraft/server/gui/MinecraftServerGui.java ++++ b/net/minecraft/server/gui/MinecraftServerGui.java +@@ -4,14 +4,15 @@ + import com.mojang.logging.LogQueues; + import com.mojang.logging.LogUtils; + import java.awt.BorderLayout; ++import java.awt.Component; + import java.awt.Dimension; + import java.awt.Font; +-import java.awt.event.ActionEvent; + import java.awt.event.FocusAdapter; + import java.awt.event.FocusEvent; + import java.awt.event.WindowAdapter; + import java.awt.event.WindowEvent; + import java.util.Collection; ++import java.util.Objects; + import java.util.concurrent.atomic.AtomicBoolean; + import javax.swing.JComponent; + import javax.swing.JFrame; +@@ -25,6 +26,7 @@ + import javax.swing.UIManager; + import javax.swing.border.EtchedBorder; + import javax.swing.border.TitledBorder; ++import javax.swing.text.AttributeSet; + import javax.swing.text.BadLocationException; + import javax.swing.text.Document; + import net.minecraft.DefaultUncaughtExceptionHandler; +@@ -32,6 +34,7 @@ + import org.slf4j.Logger; + + public class MinecraftServerGui extends JComponent { ++ + private static final Font MONOSPACED = new Font("Monospaced", 0, 12); + private static final Logger LOGGER = LogUtils.getLogger(); + private static final String TITLE = "Minecraft server"; +@@ -44,29 +47,32 @@ + public static MinecraftServerGui showFrameFor(final DedicatedServer server) { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); +- } catch (Exception var3) { ++ } catch (Exception exception) { ++ ; + } + +- final JFrame jFrame = new JFrame("Minecraft server"); +- final MinecraftServerGui minecraftServerGui = new MinecraftServerGui(server); +- jFrame.setDefaultCloseOperation(2); +- jFrame.add(minecraftServerGui); +- jFrame.pack(); +- jFrame.setLocationRelativeTo(null); +- jFrame.setVisible(true); +- jFrame.addWindowListener(new WindowAdapter() { +- @Override +- public void windowClosing(WindowEvent event) { +- if (!minecraftServerGui.isClosing.getAndSet(true)) { +- jFrame.setTitle("Minecraft server - shutting down!"); ++ final JFrame jframe = new JFrame("Minecraft server"); ++ final MinecraftServerGui servergui = new MinecraftServerGui(server); ++ ++ jframe.setDefaultCloseOperation(2); ++ jframe.add(servergui); ++ jframe.pack(); ++ jframe.setLocationRelativeTo((Component) null); ++ jframe.setVisible(true); ++ jframe.addWindowListener(new WindowAdapter() { ++ public void windowClosing(WindowEvent windowevent) { ++ if (!servergui.isClosing.getAndSet(true)) { ++ jframe.setTitle("Minecraft server - shutting down!"); + server.halt(true); +- minecraftServerGui.runFinalizers(); ++ servergui.runFinalizers(); + } ++ + } + }); +- minecraftServerGui.addFinalizer(jFrame::dispose); +- minecraftServerGui.start(); +- return minecraftServerGui; ++ Objects.requireNonNull(jframe); ++ servergui.addFinalizer(jframe::dispose); ++ servergui.start(); ++ return servergui; + } + + private MinecraftServerGui(DedicatedServer server) { +@@ -77,9 +83,10 @@ + try { + this.add(this.buildChatPanel(), "Center"); + this.add(this.buildInfoPanel(), "West"); +- } catch (Exception var3) { +- LOGGER.error("Couldn't build server GUI", (Throwable)var3); ++ } catch (Exception exception) { ++ MinecraftServerGui.LOGGER.error("Couldn't build server GUI", exception); + } ++ + } + + public void addFinalizer(Runnable finalizer) { +@@ -87,54 +94,61 @@ + } + + private JComponent buildInfoPanel() { +- JPanel jPanel = new JPanel(new BorderLayout()); +- StatsComponent statsComponent = new StatsComponent(this.server); +- this.finalizers.add(statsComponent::close); +- jPanel.add(statsComponent, "North"); +- jPanel.add(this.buildPlayerPanel(), "Center"); +- jPanel.setBorder(new TitledBorder(new EtchedBorder(), "Stats")); +- return jPanel; ++ JPanel jpanel = new JPanel(new BorderLayout()); ++ StatsComponent guistatscomponent = new StatsComponent(this.server); ++ Collection collection = this.finalizers; // CraftBukkit - decompile error ++ ++ Objects.requireNonNull(guistatscomponent); ++ collection.add(guistatscomponent::close); ++ jpanel.add(guistatscomponent, "North"); ++ jpanel.add(this.buildPlayerPanel(), "Center"); ++ jpanel.setBorder(new TitledBorder(new EtchedBorder(), "Stats")); ++ return jpanel; + } + + private JComponent buildPlayerPanel() { +- JList jList = new PlayerListComponent(this.server); +- JScrollPane jScrollPane = new JScrollPane(jList, 22, 30); +- jScrollPane.setBorder(new TitledBorder(new EtchedBorder(), "Players")); +- return jScrollPane; ++ JList jlist = new PlayerListComponent(this.server); ++ JScrollPane jscrollpane = new JScrollPane(jlist, 22, 30); ++ ++ jscrollpane.setBorder(new TitledBorder(new EtchedBorder(), "Players")); ++ return jscrollpane; + } + + private JComponent buildChatPanel() { +- JPanel jPanel = new JPanel(new BorderLayout()); +- JTextArea jTextArea = new JTextArea(); +- JScrollPane jScrollPane = new JScrollPane(jTextArea, 22, 30); +- jTextArea.setEditable(false); +- jTextArea.setFont(MONOSPACED); +- JTextField jTextField = new JTextField(); +- jTextField.addActionListener(actionEvent -> { +- String trimmed = jTextField.getText().trim(); +- if (!trimmed.isEmpty()) { +- this.server.handleConsoleInput(trimmed, this.server.createCommandSourceStack()); ++ JPanel jpanel = new JPanel(new BorderLayout()); ++ JTextArea jtextarea = new JTextArea(); ++ JScrollPane jscrollpane = new JScrollPane(jtextarea, 22, 30); ++ ++ jtextarea.setEditable(false); ++ jtextarea.setFont(MinecraftServerGui.MONOSPACED); ++ JTextField jtextfield = new JTextField(); ++ ++ jtextfield.addActionListener((actionevent) -> { ++ String s = jtextfield.getText().trim(); ++ ++ if (!s.isEmpty()) { ++ this.server.handleConsoleInput(s, this.server.createCommandSourceStack()); + } + +- jTextField.setText(""); ++ jtextfield.setText(""); + }); +- jTextArea.addFocusListener(new FocusAdapter() { +- @Override +- public void focusGained(FocusEvent event) { +- } ++ jtextarea.addFocusListener(new FocusAdapter() { ++ public void focusGained(FocusEvent focusevent) {} + }); +- jPanel.add(jScrollPane, "Center"); +- jPanel.add(jTextField, "South"); +- jPanel.setBorder(new TitledBorder(new EtchedBorder(), "Log and chat")); ++ jpanel.add(jscrollpane, "Center"); ++ jpanel.add(jtextfield, "South"); ++ jpanel.setBorder(new TitledBorder(new EtchedBorder(), "Log and chat")); + this.logAppenderThread = new Thread(() -> { +- String string; +- while ((string = LogQueues.getNextLogEvent("ServerGuiConsole")) != null) { +- this.print(jTextArea, jScrollPane, string); ++ String s; ++ ++ while ((s = LogQueues.getNextLogEvent("ServerGuiConsole")) != null) { ++ this.print(jtextarea, jscrollpane, s); + } ++ + }); +- this.logAppenderThread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER)); ++ this.logAppenderThread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(MinecraftServerGui.LOGGER)); + this.logAppenderThread.setDaemon(true); +- return jPanel; ++ return jpanel; + } + + public void start() { +@@ -145,32 +159,38 @@ + if (!this.isClosing.getAndSet(true)) { + this.runFinalizers(); + } ++ + } + + void runFinalizers() { + this.finalizers.forEach(Runnable::run); + } + ++ private static final java.util.regex.Pattern ANSI = java.util.regex.Pattern.compile("\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})*)?[m|K]"); // CraftBukkit + public void print(JTextArea textArea, JScrollPane scrollPane, String line) { + if (!SwingUtilities.isEventDispatchThread()) { +- SwingUtilities.invokeLater(() -> this.print(textArea, scrollPane, line)); ++ SwingUtilities.invokeLater(() -> { ++ this.print(textArea, scrollPane, line); ++ }); + } else { + Document document = textArea.getDocument(); +- JScrollBar verticalScrollBar = scrollPane.getVerticalScrollBar(); ++ JScrollBar jscrollbar = scrollPane.getVerticalScrollBar(); + boolean flag = false; ++ + if (scrollPane.getViewport().getView() == textArea) { +- flag = (double)verticalScrollBar.getValue() + verticalScrollBar.getSize().getHeight() + (double)(MONOSPACED.getSize() * 4) +- > (double)verticalScrollBar.getMaximum(); ++ flag = (double) jscrollbar.getValue() + jscrollbar.getSize().getHeight() + (double) (MinecraftServerGui.MONOSPACED.getSize() * 4) > (double) jscrollbar.getMaximum(); + } + + try { +- document.insertString(document.getLength(), line, null); +- } catch (BadLocationException var8) { ++ document.insertString(document.getLength(), ANSI.matcher(line).replaceAll(""), (AttributeSet) null); // CraftBukkit ++ } catch (BadLocationException badlocationexception) { ++ ; + } + + if (flag) { +- verticalScrollBar.setValue(Integer.MAX_VALUE); ++ jscrollbar.setValue(Integer.MAX_VALUE); + } ++ + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/level/ChunkHolder.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/level/ChunkHolder.java.patch new file mode 100644 index 0000000000..96da1be143 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/level/ChunkHolder.java.patch @@ -0,0 +1,753 @@ +--- a/net/minecraft/server/level/ChunkHolder.java ++++ b/net/minecraft/server/level/ChunkHolder.java +@@ -9,7 +9,6 @@ + import java.util.List; + import java.util.Optional; + import java.util.concurrent.CompletableFuture; +-import java.util.concurrent.CompletionStage; + import java.util.concurrent.Executor; + import java.util.concurrent.atomic.AtomicReferenceArray; + import java.util.function.IntConsumer; +@@ -24,11 +23,11 @@ + import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket; + import net.minecraft.util.DebugBuffer; + import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.EnumSkyBlock; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelHeightAccessor; +-import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.level.chunk.ImposterProtoChunk; +@@ -37,50 +36,52 @@ + import net.minecraft.world.level.chunk.ProtoChunk; + import net.minecraft.world.level.lighting.LevelLightEngine; + ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++// CraftBukkit end ++ + public class ChunkHolder { +- public static final Either UNLOADED_CHUNK = Either.right(ChunkHolder.ChunkLoadingFailure.UNLOADED); +- public static final CompletableFuture> UNLOADED_CHUNK_FUTURE = CompletableFuture.completedFuture( +- UNLOADED_CHUNK +- ); +- public static final Either UNLOADED_LEVEL_CHUNK = Either.right(ChunkHolder.ChunkLoadingFailure.UNLOADED); +- private static final Either NOT_DONE_YET = Either.right(ChunkHolder.ChunkLoadingFailure.UNLOADED); +- private static final CompletableFuture> UNLOADED_LEVEL_CHUNK_FUTURE = CompletableFuture.completedFuture( +- UNLOADED_LEVEL_CHUNK +- ); ++ ++ public static final Either UNLOADED_CHUNK = Either.right(ChunkHolder.Failure.UNLOADED); ++ public static final CompletableFuture> UNLOADED_CHUNK_FUTURE = CompletableFuture.completedFuture(ChunkHolder.UNLOADED_CHUNK); ++ public static final Either UNLOADED_LEVEL_CHUNK = Either.right(ChunkHolder.Failure.UNLOADED); ++ private static final Either NOT_DONE_YET = Either.right(ChunkHolder.Failure.UNLOADED); ++ private static final CompletableFuture> UNLOADED_LEVEL_CHUNK_FUTURE = CompletableFuture.completedFuture(ChunkHolder.UNLOADED_LEVEL_CHUNK); + private static final List CHUNK_STATUSES = ChunkStatus.getStatusList(); +- private final AtomicReferenceArray>> futures = new AtomicReferenceArray<>( +- CHUNK_STATUSES.size() +- ); ++ private final AtomicReferenceArray>> futures; + private final LevelHeightAccessor levelHeightAccessor; +- private volatile CompletableFuture> fullChunkFuture = UNLOADED_LEVEL_CHUNK_FUTURE; +- private volatile CompletableFuture> tickingChunkFuture = UNLOADED_LEVEL_CHUNK_FUTURE; +- private volatile CompletableFuture> entityTickingChunkFuture = UNLOADED_LEVEL_CHUNK_FUTURE; +- private CompletableFuture chunkToSave = CompletableFuture.completedFuture(null); ++ private volatile CompletableFuture> fullChunkFuture; ++ private volatile CompletableFuture> tickingChunkFuture; ++ private volatile CompletableFuture> entityTickingChunkFuture; ++ private CompletableFuture chunkToSave; + @Nullable +- private final DebugBuffer chunkToSaveHistory = null; +- private int oldTicketLevel; ++ private final DebugBuffer chunkToSaveHistory; ++ public int oldTicketLevel; + private int ticketLevel; + private int queueLevel; + final ChunkPos pos; + private boolean hasChangedSections; + private final ShortSet[] changedBlocksPerSection; +- private final BitSet blockChangedLightSectionFilter = new BitSet(); +- private final BitSet skyChangedLightSectionFilter = new BitSet(); ++ private final BitSet blockChangedLightSectionFilter; ++ private final BitSet skyChangedLightSectionFilter; + private final LevelLightEngine lightEngine; + private final ChunkHolder.LevelChangeListener onLevelChange; +- private final ChunkHolder.PlayerProvider playerProvider; ++ public final ChunkHolder.PlayerProvider playerProvider; + private boolean wasAccessibleSinceLastSave; +- private CompletableFuture pendingFullStateConfirmation = CompletableFuture.completedFuture(null); +- private CompletableFuture sendSync = CompletableFuture.completedFuture(null); ++ private CompletableFuture pendingFullStateConfirmation; ++ private CompletableFuture sendSync; + +- public ChunkHolder( +- ChunkPos pos, +- int ticketLevel, +- LevelHeightAccessor levelHeightAccessor, +- LevelLightEngine lightEngine, +- ChunkHolder.LevelChangeListener onLevelChange, +- ChunkHolder.PlayerProvider playerProvider +- ) { ++ public ChunkHolder(ChunkPos pos, int ticketLevel, LevelHeightAccessor levelHeightAccessor, LevelLightEngine lightEngine, ChunkHolder.LevelChangeListener onLevelChange, ChunkHolder.PlayerProvider playerProvider) { ++ this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); ++ this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; ++ this.tickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; ++ this.entityTickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; ++ this.chunkToSave = CompletableFuture.completedFuture(null); // CraftBukkit - decompile error ++ this.chunkToSaveHistory = null; ++ this.blockChangedLightSectionFilter = new BitSet(); ++ this.skyChangedLightSectionFilter = new BitSet(); ++ this.pendingFullStateConfirmation = CompletableFuture.completedFuture(null); // CraftBukkit - decompile error ++ this.sendSync = CompletableFuture.completedFuture(null); // CraftBukkit - decompile error + this.pos = pos; + this.levelHeightAccessor = levelHeightAccessor; + this.lightEngine = lightEngine; +@@ -93,32 +94,48 @@ + this.changedBlocksPerSection = new ShortSet[levelHeightAccessor.getSectionsCount()]; + } + +- public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus chunkStatus) { +- CompletableFuture> completableFuture = this.futures.get(chunkStatus.getIndex()); +- return completableFuture == null ? UNLOADED_CHUNK_FUTURE : completableFuture; ++ // CraftBukkit start ++ public LevelChunk getFullChunkNow() { ++ // Note: We use the oldTicketLevel for isLoaded checks. ++ if (!ChunkLevel.fullStatus(this.oldTicketLevel).isOrAfter(FullChunkStatus.FULL)) return null; ++ return this.getFullChunkNowUnchecked(); + } + +- public CompletableFuture> getFutureIfPresent(ChunkStatus chunkStatus) { +- return ChunkLevel.generationStatus(this.ticketLevel).isOrAfter(chunkStatus) ? this.getFutureIfPresentUnchecked(chunkStatus) : UNLOADED_CHUNK_FUTURE; ++ public LevelChunk getFullChunkNowUnchecked() { ++ CompletableFuture> statusFuture = this.getFutureIfPresentUnchecked(ChunkStatus.FULL); ++ Either either = (Either) statusFuture.getNow(null); ++ return (either == null) ? null : (LevelChunk) either.left().orElse(null); + } ++ // CraftBukkit end + +- public CompletableFuture> getTickingChunkFuture() { ++ public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus chunkStatus) { ++ CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(chunkStatus.getIndex()); ++ ++ return completablefuture == null ? ChunkHolder.UNLOADED_CHUNK_FUTURE : completablefuture; ++ } ++ ++ public CompletableFuture> getFutureIfPresent(ChunkStatus chunkStatus) { ++ return ChunkLevel.generationStatus(this.ticketLevel).isOrAfter(chunkStatus) ? this.getFutureIfPresentUnchecked(chunkStatus) : ChunkHolder.UNLOADED_CHUNK_FUTURE; ++ } ++ ++ public CompletableFuture> getTickingChunkFuture() { + return this.tickingChunkFuture; + } + +- public CompletableFuture> getEntityTickingChunkFuture() { ++ public CompletableFuture> getEntityTickingChunkFuture() { + return this.entityTickingChunkFuture; + } + +- public CompletableFuture> getFullChunkFuture() { ++ public CompletableFuture> getFullChunkFuture() { + return this.fullChunkFuture; + } + + @Nullable + public LevelChunk getTickingChunk() { +- CompletableFuture> tickingChunkFuture = this.getTickingChunkFuture(); +- Either either = tickingChunkFuture.getNow(null); +- return either == null ? null : either.left().orElse(null); ++ CompletableFuture> completablefuture = this.getTickingChunkFuture(); ++ Either either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error ++ ++ return either == null ? null : (LevelChunk) either.left().orElse(null); // CraftBukkit - decompile error + } + + public CompletableFuture getChunkSendSyncFuture() { +@@ -132,18 +149,20 @@ + + @Nullable + public LevelChunk getFullChunk() { +- CompletableFuture> fullChunkFuture = this.getFullChunkFuture(); +- Either either = fullChunkFuture.getNow(null); +- return either == null ? null : either.left().orElse(null); ++ CompletableFuture> completablefuture = this.getFullChunkFuture(); ++ Either either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error ++ ++ return either == null ? null : (LevelChunk) either.left().orElse(null); // CraftBukkit - decompile error + } + + @Nullable + public ChunkStatus getLastAvailableStatus() { +- for (int i = CHUNK_STATUSES.size() - 1; i >= 0; i--) { +- ChunkStatus chunkStatus = CHUNK_STATUSES.get(i); +- CompletableFuture> futureIfPresentUnchecked = this.getFutureIfPresentUnchecked(chunkStatus); +- if (futureIfPresentUnchecked.getNow(UNLOADED_CHUNK).left().isPresent()) { +- return chunkStatus; ++ for (int i = ChunkHolder.CHUNK_STATUSES.size() - 1; i >= 0; --i) { ++ ChunkStatus chunkstatus = (ChunkStatus) ChunkHolder.CHUNK_STATUSES.get(i); ++ CompletableFuture> completablefuture = this.getFutureIfPresentUnchecked(chunkstatus); ++ ++ if (((Either) completablefuture.getNow(ChunkHolder.UNLOADED_CHUNK)).left().isPresent()) { ++ return chunkstatus; + } + } + +@@ -152,13 +171,15 @@ + + @Nullable + public ChunkAccess getLastAvailable() { +- for (int i = CHUNK_STATUSES.size() - 1; i >= 0; i--) { +- ChunkStatus chunkStatus = CHUNK_STATUSES.get(i); +- CompletableFuture> futureIfPresentUnchecked = this.getFutureIfPresentUnchecked(chunkStatus); +- if (!futureIfPresentUnchecked.isCompletedExceptionally()) { +- Optional optional = futureIfPresentUnchecked.getNow(UNLOADED_CHUNK).left(); ++ for (int i = ChunkHolder.CHUNK_STATUSES.size() - 1; i >= 0; --i) { ++ ChunkStatus chunkstatus = (ChunkStatus) ChunkHolder.CHUNK_STATUSES.get(i); ++ CompletableFuture> completablefuture = this.getFutureIfPresentUnchecked(chunkstatus); ++ ++ if (!completablefuture.isCompletedExceptionally()) { ++ Optional optional = ((Either) completablefuture.getNow(ChunkHolder.UNLOADED_CHUNK)).left(); ++ + if (optional.isPresent()) { +- return optional.get(); ++ return (ChunkAccess) optional.get(); + } + } + } +@@ -171,35 +192,44 @@ + } + + public void blockChanged(BlockPos pos) { +- LevelChunk tickingChunk = this.getTickingChunk(); +- if (tickingChunk != null) { +- int sectionIndex = this.levelHeightAccessor.getSectionIndex(pos.getY()); +- if (this.changedBlocksPerSection[sectionIndex] == null) { ++ LevelChunk chunk = this.getTickingChunk(); ++ ++ if (chunk != null) { ++ int i = this.levelHeightAccessor.getSectionIndex(pos.getY()); ++ ++ if (i < 0 || i >= this.changedBlocksPerSection.length) return; // CraftBukkit - SPIGOT-6086, SPIGOT-6296 ++ if (this.changedBlocksPerSection[i] == null) { + this.hasChangedSections = true; +- this.changedBlocksPerSection[sectionIndex] = new ShortOpenHashSet(); ++ this.changedBlocksPerSection[i] = new ShortOpenHashSet(); + } + +- this.changedBlocksPerSection[sectionIndex].add(SectionPos.sectionRelativePos(pos)); ++ this.changedBlocksPerSection[i].add(SectionPos.sectionRelativePos(pos)); + } + } + +- public void sectionLightChanged(LightLayer type, int sectionY) { +- Either either = this.getFutureIfPresent(ChunkStatus.INITIALIZE_LIGHT).getNow(null); ++ public void sectionLightChanged(EnumSkyBlock type, int sectionY) { ++ Either either = (Either) this.getFutureIfPresent(ChunkStatus.INITIALIZE_LIGHT).getNow(null); // CraftBukkit - decompile error ++ + if (either != null) { +- ChunkAccess chunkAccess = either.left().orElse(null); +- if (chunkAccess != null) { +- chunkAccess.setUnsaved(true); +- LevelChunk tickingChunk = this.getTickingChunk(); +- if (tickingChunk != null) { +- int minLightSection = this.lightEngine.getMinLightSection(); +- int maxLightSection = this.lightEngine.getMaxLightSection(); +- if (sectionY >= minLightSection && sectionY <= maxLightSection) { +- int i = sectionY - minLightSection; +- if (type == LightLayer.SKY) { +- this.skyChangedLightSectionFilter.set(i); ++ ChunkAccess ichunkaccess = (ChunkAccess) either.left().orElse(null); // CraftBukkit - decompile error ++ ++ if (ichunkaccess != null) { ++ ichunkaccess.setUnsaved(true); ++ LevelChunk chunk = this.getTickingChunk(); ++ ++ if (chunk != null) { ++ int j = this.lightEngine.getMinLightSection(); ++ int k = this.lightEngine.getMaxLightSection(); ++ ++ if (sectionY >= j && sectionY <= k) { ++ int l = sectionY - j; ++ ++ if (type == EnumSkyBlock.SKY) { ++ this.skyChangedLightSectionFilter.set(l); + } else { +- this.blockChangedLightSectionFilter.set(i); ++ this.blockChangedLightSectionFilter.set(l); + } ++ + } + } + } +@@ -208,14 +238,15 @@ + + public void broadcastChanges(LevelChunk chunk) { + if (this.hasChangedSections || !this.skyChangedLightSectionFilter.isEmpty() || !this.blockChangedLightSectionFilter.isEmpty()) { +- Level level = chunk.getLevel(); ++ Level world = chunk.getLevel(); ++ List list; ++ + if (!this.skyChangedLightSectionFilter.isEmpty() || !this.blockChangedLightSectionFilter.isEmpty()) { +- List players = this.playerProvider.getPlayers(this.pos, true); +- if (!players.isEmpty()) { +- ClientboundLightUpdatePacket clientboundLightUpdatePacket = new ClientboundLightUpdatePacket( +- chunk.getPos(), this.lightEngine, this.skyChangedLightSectionFilter, this.blockChangedLightSectionFilter +- ); +- this.broadcast(players, clientboundLightUpdatePacket); ++ list = this.playerProvider.getPlayers(this.pos, true); ++ if (!list.isEmpty()) { ++ ClientboundLightUpdatePacket packetplayoutlightupdate = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, this.skyChangedLightSectionFilter, this.blockChangedLightSectionFilter); ++ ++ this.broadcast(list, packetplayoutlightupdate); + } + + this.skyChangedLightSectionFilter.clear(); +@@ -223,29 +254,34 @@ + } + + if (this.hasChangedSections) { +- List players = this.playerProvider.getPlayers(this.pos, false); ++ list = this.playerProvider.getPlayers(this.pos, false); + +- for (int i = 0; i < this.changedBlocksPerSection.length; i++) { +- ShortSet set = this.changedBlocksPerSection[i]; +- if (set != null) { ++ for (int i = 0; i < this.changedBlocksPerSection.length; ++i) { ++ ShortSet shortset = this.changedBlocksPerSection[i]; ++ ++ if (shortset != null) { + this.changedBlocksPerSection[i] = null; +- if (!players.isEmpty()) { +- int sectionYFromSectionIndex = this.levelHeightAccessor.getSectionYFromSectionIndex(i); +- SectionPos sectionPos = SectionPos.of(chunk.getPos(), sectionYFromSectionIndex); +- if (set.size() == 1) { +- BlockPos blockPos = sectionPos.relativeToBlockPos(set.iterator().nextShort()); +- BlockState blockState = level.getBlockState(blockPos); +- this.broadcast(players, new ClientboundBlockUpdatePacket(blockPos, blockState)); +- this.broadcastBlockEntityIfNeeded(players, level, blockPos, blockState); ++ if (!list.isEmpty()) { ++ int j = this.levelHeightAccessor.getSectionYFromSectionIndex(i); ++ SectionPos sectionposition = SectionPos.of(chunk.getPos(), j); ++ ++ if (shortset.size() == 1) { ++ BlockPos blockposition = sectionposition.relativeToBlockPos(shortset.iterator().nextShort()); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ ++ this.broadcast(list, new ClientboundBlockUpdatePacket(blockposition, iblockdata)); ++ this.broadcastBlockEntityIfNeeded(list, world, blockposition, iblockdata); + } else { +- LevelChunkSection section = chunk.getSection(i); +- ClientboundSectionBlocksUpdatePacket clientboundSectionBlocksUpdatePacket = new ClientboundSectionBlocksUpdatePacket( +- sectionPos, set, section +- ); +- this.broadcast(players, clientboundSectionBlocksUpdatePacket); +- clientboundSectionBlocksUpdatePacket.runUpdates( +- (blockPos1, blockState1) -> this.broadcastBlockEntityIfNeeded(players, level, blockPos1, blockState1) +- ); ++ LevelChunkSection chunksection = chunk.getSection(i); ++ ClientboundSectionBlocksUpdatePacket packetplayoutmultiblockchange = new ClientboundSectionBlocksUpdatePacket(sectionposition, shortset, chunksection); ++ ++ this.broadcast(list, packetplayoutmultiblockchange); ++ // CraftBukkit start ++ List finalList = list; ++ packetplayoutmultiblockchange.runUpdates((blockposition1, iblockdata1) -> { ++ this.broadcastBlockEntityIfNeeded(finalList, world, blockposition1, iblockdata1); ++ // CraftBukkit end ++ }); + } + } + } +@@ -256,48 +292,58 @@ + } + } + +- private void broadcastBlockEntityIfNeeded(List players, Level level, BlockPos pos, BlockState state) { ++ private void broadcastBlockEntityIfNeeded(List players, Level level, BlockPos pos, IBlockData state) { + if (state.hasBlockEntity()) { + this.broadcastBlockEntity(players, level, pos); + } ++ + } + + private void broadcastBlockEntity(List players, Level level, BlockPos pox) { +- BlockEntity blockEntity = level.getBlockEntity(pox); +- if (blockEntity != null) { +- Packet updatePacket = blockEntity.getUpdatePacket(); +- if (updatePacket != null) { +- this.broadcast(players, updatePacket); ++ BlockEntity tileentity = level.getBlockEntity(pox); ++ ++ if (tileentity != null) { ++ Packet packet = tileentity.getUpdatePacket(); ++ ++ if (packet != null) { ++ this.broadcast(players, packet); + } + } ++ + } + + private void broadcast(List players, Packet packet) { +- players.forEach(serverPlayer -> serverPlayer.connection.send(packet)); ++ players.forEach((entityplayer) -> { ++ entityplayer.connection.send(packet); ++ }); + } + +- public CompletableFuture> getOrScheduleFuture(ChunkStatus status, ChunkMap map) { +- int index = status.getIndex(); +- CompletableFuture> completableFuture = this.futures.get(index); +- if (completableFuture != null) { +- Either either = completableFuture.getNow(NOT_DONE_YET); ++ public CompletableFuture> getOrScheduleFuture(ChunkStatus status, ChunkMap map) { ++ int i = status.getIndex(); ++ CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(i); ++ ++ if (completablefuture != null) { ++ Either either = (Either) completablefuture.getNow(ChunkHolder.NOT_DONE_YET); ++ + if (either == null) { +- String string = "value in future for status: " + status + " was incorrectly set to null at chunk: " + this.pos; +- throw map.debugFuturesAndCreateReportedException(new IllegalStateException("null value previously set for chunk status"), string); ++ String s = "value in future for status: " + status + " was incorrectly set to null at chunk: " + this.pos; ++ ++ throw map.debugFuturesAndCreateReportedException(new IllegalStateException("null value previously set for chunk status"), s); + } + +- if (either == NOT_DONE_YET || either.right().isEmpty()) { +- return completableFuture; ++ if (either == ChunkHolder.NOT_DONE_YET || either.right().isEmpty()) { ++ return completablefuture; + } + } + + if (ChunkLevel.generationStatus(this.ticketLevel).isOrAfter(status)) { +- CompletableFuture> completableFuture1 = map.schedule(this, status); +- this.updateChunkToSave(completableFuture1, "schedule " + status); +- this.futures.set(index, completableFuture1); +- return completableFuture1; ++ CompletableFuture> completablefuture1 = map.schedule(this, status); ++ ++ this.updateChunkToSave(completablefuture1, "schedule " + status); ++ this.futures.set(i, completablefuture1); ++ return completablefuture1; + } else { +- return completableFuture == null ? UNLOADED_CHUNK_FUTURE : completableFuture; ++ return completablefuture == null ? ChunkHolder.UNLOADED_CHUNK_FUTURE : completablefuture; + } + } + +@@ -306,26 +352,34 @@ + this.chunkToSaveHistory.push(new ChunkHolder.ChunkSaveDebug(Thread.currentThread(), future, source)); + } + +- this.chunkToSave = this.chunkToSave.thenCombine((CompletionStage)future, (chunkAccess, object) -> (ChunkAccess)chunkAccess); ++ this.chunkToSave = this.chunkToSave.thenCombine(future, (ichunkaccess, object) -> { ++ return ichunkaccess; ++ }); + } + +- private void updateChunkToSave(CompletableFuture> feature, String source) { ++ private void updateChunkToSave(CompletableFuture> feature, String source) { + if (this.chunkToSaveHistory != null) { + this.chunkToSaveHistory.push(new ChunkHolder.ChunkSaveDebug(Thread.currentThread(), feature, source)); + } + +- this.chunkToSave = this.chunkToSave +- .thenCombine( +- feature, (chunkAccess, either) -> either.map(chunkAccess1 -> (ChunkAccess)chunkAccess1, chunkLoadingFailure -> (ChunkAccess)chunkAccess) +- ); ++ this.chunkToSave = this.chunkToSave.thenCombine(feature, (ichunkaccess, either) -> { ++ return (ChunkAccess) either.map((ichunkaccess1) -> { ++ return ichunkaccess1; ++ }, (playerchunk_failure) -> { ++ return ichunkaccess; ++ }); ++ }); + } + +- public void addSendDependency(CompletableFuture completableFuture) { ++ public void addSendDependency(CompletableFuture completablefuture) { + if (this.sendSync.isDone()) { +- this.sendSync = completableFuture; ++ this.sendSync = completablefuture; + } else { +- this.sendSync = this.sendSync.thenCombine((CompletionStage)completableFuture, (object, object1) -> null); ++ this.sendSync = this.sendSync.thenCombine(completablefuture, (object, object1) -> { ++ return null; ++ }); + } ++ + } + + public FullChunkStatus getFullStatus() { +@@ -352,14 +406,19 @@ + this.ticketLevel = level; + } + +- private void scheduleFullChunkPromotion( +- ChunkMap chunkMap, CompletableFuture> future, Executor executor, FullChunkStatus fullChunkStatus +- ) { ++ private void scheduleFullChunkPromotion(ChunkMap chunkMap, CompletableFuture> future, Executor executor, FullChunkStatus fullChunkStatus) { + this.pendingFullStateConfirmation.cancel(false); +- CompletableFuture completableFuture = new CompletableFuture<>(); +- completableFuture.thenRunAsync(() -> chunkMap.onFullChunkStatusChange(this.pos, fullChunkStatus), executor); +- this.pendingFullStateConfirmation = completableFuture; +- future.thenAccept(either -> either.ifLeft(levelChunk -> completableFuture.complete(null))); ++ CompletableFuture completablefuture1 = new CompletableFuture(); ++ ++ completablefuture1.thenRunAsync(() -> { ++ chunkMap.onFullChunkStatusChange(this.pos, fullChunkStatus); ++ }, executor); ++ this.pendingFullStateConfirmation = completablefuture1; ++ future.thenAccept((either) -> { ++ either.ifLeft((chunk) -> { ++ completablefuture1.complete(null); // CraftBukkit - decompile error ++ }); ++ }); + } + + private void demoteFullChunk(ChunkMap chunkMap, FullChunkStatus fullChunkStatus) { +@@ -368,60 +427,88 @@ + } + + protected void updateFutures(ChunkMap chunkMap, Executor executor) { +- ChunkStatus chunkStatus = ChunkLevel.generationStatus(this.oldTicketLevel); +- ChunkStatus chunkStatus1 = ChunkLevel.generationStatus(this.ticketLevel); +- boolean isLoaded = ChunkLevel.isLoaded(this.oldTicketLevel); +- boolean isLoaded1 = ChunkLevel.isLoaded(this.ticketLevel); +- FullChunkStatus fullChunkStatus = ChunkLevel.fullStatus(this.oldTicketLevel); +- FullChunkStatus fullChunkStatus1 = ChunkLevel.fullStatus(this.ticketLevel); +- if (isLoaded) { +- Either either = Either.right(new ChunkHolder.ChunkLoadingFailure() { +- @Override ++ ChunkStatus chunkstatus = ChunkLevel.generationStatus(this.oldTicketLevel); ++ ChunkStatus chunkstatus1 = ChunkLevel.generationStatus(this.ticketLevel); ++ boolean flag = ChunkLevel.isLoaded(this.oldTicketLevel); ++ boolean flag1 = ChunkLevel.isLoaded(this.ticketLevel); ++ FullChunkStatus fullchunkstatus = ChunkLevel.fullStatus(this.oldTicketLevel); ++ FullChunkStatus fullchunkstatus1 = ChunkLevel.fullStatus(this.ticketLevel); ++ // CraftBukkit start ++ // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins. ++ if (fullchunkstatus.isOrAfter(FullChunkStatus.FULL) && !fullchunkstatus1.isOrAfter(FullChunkStatus.FULL)) { ++ this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { ++ LevelChunk chunk = (LevelChunk)either.left().orElse(null); ++ if (chunk != null) { ++ chunkMap.callbackExecutor.execute(() -> { ++ // Minecraft will apply the chunks tick lists to the world once the chunk got loaded, and then store the tick ++ // lists again inside the chunk once the chunk becomes inaccessible and set the chunk's needsSaving flag. ++ // These actions may however happen deferred, so we manually set the needsSaving flag already here. ++ chunk.setUnsaved(true); ++ chunk.unloadCallback(); ++ }); ++ } ++ }).exceptionally((throwable) -> { ++ // ensure exceptions are printed, by default this is not the case ++ MinecraftServer.LOGGER.error("Failed to schedule unload callback for chunk " + ChunkHolder.this.pos, throwable); ++ return null; ++ }); ++ ++ // Run callback right away if the future was already done ++ chunkMap.callbackExecutor.run(); ++ } ++ // CraftBukkit end ++ ++ if (flag) { ++ Either either = Either.right(new ChunkHolder.Failure() { + public String toString() { + return "Unloaded ticket level " + ChunkHolder.this.pos; + } + }); + +- for (int i = isLoaded1 ? chunkStatus1.getIndex() + 1 : 0; i <= chunkStatus.getIndex(); i++) { +- CompletableFuture> completableFuture = this.futures.get(i); +- if (completableFuture == null) { ++ for (int i = flag1 ? chunkstatus1.getIndex() + 1 : 0; i <= chunkstatus.getIndex(); ++i) { ++ CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(i); ++ ++ if (completablefuture == null) { + this.futures.set(i, CompletableFuture.completedFuture(either)); + } + } + } + +- boolean isOrAfter = fullChunkStatus.isOrAfter(FullChunkStatus.FULL); +- boolean isOrAfter1 = fullChunkStatus1.isOrAfter(FullChunkStatus.FULL); +- this.wasAccessibleSinceLastSave |= isOrAfter1; +- if (!isOrAfter && isOrAfter1) { ++ boolean flag2 = fullchunkstatus.isOrAfter(FullChunkStatus.FULL); ++ boolean flag3 = fullchunkstatus1.isOrAfter(FullChunkStatus.FULL); ++ ++ this.wasAccessibleSinceLastSave |= flag3; ++ if (!flag2 && flag3) { + this.fullChunkFuture = chunkMap.prepareAccessibleChunk(this); + this.scheduleFullChunkPromotion(chunkMap, this.fullChunkFuture, executor, FullChunkStatus.FULL); + this.updateChunkToSave(this.fullChunkFuture, "full"); + } + +- if (isOrAfter && !isOrAfter1) { +- this.fullChunkFuture.complete(UNLOADED_LEVEL_CHUNK); +- this.fullChunkFuture = UNLOADED_LEVEL_CHUNK_FUTURE; ++ if (flag2 && !flag3) { ++ this.fullChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); ++ this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; + } + +- boolean isOrAfter2 = fullChunkStatus.isOrAfter(FullChunkStatus.BLOCK_TICKING); +- boolean isOrAfter3 = fullChunkStatus1.isOrAfter(FullChunkStatus.BLOCK_TICKING); +- if (!isOrAfter2 && isOrAfter3) { ++ boolean flag4 = fullchunkstatus.isOrAfter(FullChunkStatus.BLOCK_TICKING); ++ boolean flag5 = fullchunkstatus1.isOrAfter(FullChunkStatus.BLOCK_TICKING); ++ ++ if (!flag4 && flag5) { + this.tickingChunkFuture = chunkMap.prepareTickingChunk(this); + this.scheduleFullChunkPromotion(chunkMap, this.tickingChunkFuture, executor, FullChunkStatus.BLOCK_TICKING); + this.updateChunkToSave(this.tickingChunkFuture, "ticking"); + } + +- if (isOrAfter2 && !isOrAfter3) { +- this.tickingChunkFuture.complete(UNLOADED_LEVEL_CHUNK); +- this.tickingChunkFuture = UNLOADED_LEVEL_CHUNK_FUTURE; ++ if (flag4 && !flag5) { ++ this.tickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); ++ this.tickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; + } + +- boolean isOrAfter4 = fullChunkStatus.isOrAfter(FullChunkStatus.ENTITY_TICKING); +- boolean isOrAfter5 = fullChunkStatus1.isOrAfter(FullChunkStatus.ENTITY_TICKING); +- if (!isOrAfter4 && isOrAfter5) { +- if (this.entityTickingChunkFuture != UNLOADED_LEVEL_CHUNK_FUTURE) { +- throw (IllegalStateException)Util.pauseInIde(new IllegalStateException()); ++ boolean flag6 = fullchunkstatus.isOrAfter(FullChunkStatus.ENTITY_TICKING); ++ boolean flag7 = fullchunkstatus1.isOrAfter(FullChunkStatus.ENTITY_TICKING); ++ ++ if (!flag6 && flag7) { ++ if (this.entityTickingChunkFuture != ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE) { ++ throw (IllegalStateException) Util.pauseInIde(new IllegalStateException()); + } + + this.entityTickingChunkFuture = chunkMap.prepareEntityTickingChunk(this); +@@ -429,17 +516,37 @@ + this.updateChunkToSave(this.entityTickingChunkFuture, "entity ticking"); + } + +- if (isOrAfter4 && !isOrAfter5) { +- this.entityTickingChunkFuture.complete(UNLOADED_LEVEL_CHUNK); +- this.entityTickingChunkFuture = UNLOADED_LEVEL_CHUNK_FUTURE; ++ if (flag6 && !flag7) { ++ this.entityTickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); ++ this.entityTickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; + } + +- if (!fullChunkStatus1.isOrAfter(fullChunkStatus)) { +- this.demoteFullChunk(chunkMap, fullChunkStatus1); ++ if (!fullchunkstatus1.isOrAfter(fullchunkstatus)) { ++ this.demoteFullChunk(chunkMap, fullchunkstatus1); + } + + this.onLevelChange.onLevelChange(this.pos, this::getQueueLevel, this.ticketLevel, this::setQueueLevel); + this.oldTicketLevel = this.ticketLevel; ++ // CraftBukkit start ++ // ChunkLoadEvent: Called after the chunk is loaded: isChunkLoaded returns true and chunk is ready to be modified by plugins. ++ if (!fullchunkstatus.isOrAfter(FullChunkStatus.FULL) && fullchunkstatus1.isOrAfter(FullChunkStatus.FULL)) { ++ this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { ++ LevelChunk chunk = (LevelChunk)either.left().orElse(null); ++ if (chunk != null) { ++ chunkMap.callbackExecutor.execute(() -> { ++ chunk.loadCallback(); ++ }); ++ } ++ }).exceptionally((throwable) -> { ++ // ensure exceptions are printed, by default this is not the case ++ MinecraftServer.LOGGER.error("Failed to schedule load callback for chunk " + ChunkHolder.this.pos, throwable); ++ return null; ++ }); ++ ++ // Run callback right away if the future was already done ++ chunkMap.callbackExecutor.run(); ++ } ++ // CraftBukkit end + } + + public boolean wasAccessibleSinceLastSave() { +@@ -451,10 +558,12 @@ + } + + public void replaceProtoChunk(ImposterProtoChunk imposter) { +- for (int i = 0; i < this.futures.length(); i++) { +- CompletableFuture> completableFuture = this.futures.get(i); +- if (completableFuture != null) { +- Optional optional = completableFuture.getNow(UNLOADED_CHUNK).left(); ++ for (int i = 0; i < this.futures.length(); ++i) { ++ CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(i); ++ ++ if (completablefuture != null) { ++ Optional optional = ((Either) completablefuture.getNow(ChunkHolder.UNLOADED_CHUNK)).left(); ++ + if (!optional.isEmpty() && optional.get() instanceof ProtoChunk) { + this.futures.set(i, CompletableFuture.completedFuture(Either.left(imposter))); + } +@@ -464,26 +573,29 @@ + this.updateChunkToSave(CompletableFuture.completedFuture(Either.left(imposter.getWrapped())), "replaceProto"); + } + +- public List>>> getAllFutures() { +- List>>> list = new ArrayList<>(); ++ public List>>> getAllFutures() { ++ List>>> list = new ArrayList(); + +- for (int i = 0; i < CHUNK_STATUSES.size(); i++) { +- list.add(Pair.of(CHUNK_STATUSES.get(i), this.futures.get(i))); ++ for (int i = 0; i < ChunkHolder.CHUNK_STATUSES.size(); ++i) { ++ list.add(Pair.of((ChunkStatus) ChunkHolder.CHUNK_STATUSES.get(i), (CompletableFuture) this.futures.get(i))); + } + + return list; + } + +- public interface ChunkLoadingFailure { +- ChunkHolder.ChunkLoadingFailure UNLOADED = new ChunkHolder.ChunkLoadingFailure() { +- @Override +- public String toString() { +- return "UNLOADED"; +- } +- }; ++ @FunctionalInterface ++ public interface LevelChangeListener { ++ ++ void onLevelChange(ChunkPos chunkPos, IntSupplier intsupplier, int i, IntConsumer intconsumer); + } + +- static final class ChunkSaveDebug { ++ public interface PlayerProvider { ++ ++ List getPlayers(ChunkPos pos, boolean boundaryOnly); ++ } ++ ++ private static final class ChunkSaveDebug { ++ + private final Thread thread; + private final CompletableFuture future; + private final String source; +@@ -495,12 +607,12 @@ + } + } + +- @FunctionalInterface +- public interface LevelChangeListener { +- void onLevelChange(ChunkPos chunkPos, IntSupplier intSupplier, int i, IntConsumer intConsumer); +- } ++ public interface Failure { + +- public interface PlayerProvider { +- List getPlayers(ChunkPos pos, boolean boundaryOnly); ++ ChunkHolder.Failure UNLOADED = new ChunkHolder.Failure() { ++ public String toString() { ++ return "UNLOADED"; ++ } ++ }; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/level/ChunkMap.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/level/ChunkMap.java.patch new file mode 100644 index 0000000000..3d94df9abc --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/level/ChunkMap.java.patch @@ -0,0 +1,2150 @@ +--- a/net/minecraft/server/level/ChunkMap.java ++++ b/net/minecraft/server/level/ChunkMap.java +@@ -1,15 +1,14 @@ + package net.minecraft.server.level; + + import com.google.common.collect.ImmutableList; ++import com.google.common.collect.ImmutableList.Builder; + import com.google.common.collect.Iterables; + import com.google.common.collect.Lists; + import com.google.common.collect.Queues; + import com.google.common.collect.Sets; +-import com.google.common.collect.ImmutableList.Builder; + import com.google.gson.JsonElement; + import com.mojang.datafixers.DataFixer; + import com.mojang.datafixers.util.Either; +-import com.mojang.datafixers.util.Pair; + import com.mojang.logging.LogUtils; + import com.mojang.serialization.DataResult; + import com.mojang.serialization.JsonOps; +@@ -20,16 +19,18 @@ + import it.unimi.dsi.fastutil.longs.Long2LongMap; + import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap; + import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; ++import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; + import it.unimi.dsi.fastutil.longs.LongIterator; + import it.unimi.dsi.fastutil.longs.LongOpenHashSet; + import it.unimi.dsi.fastutil.longs.LongSet; +-import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; ++import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator; + import it.unimi.dsi.fastutil.objects.ObjectIterator; + import java.io.IOException; + import java.io.Writer; + import java.nio.file.Path; + import java.util.ArrayList; + import java.util.HashMap; ++import java.util.Iterator; + import java.util.List; + import java.util.Locale; + import java.util.Map; +@@ -40,6 +41,7 @@ + import java.util.concurrent.CancellationException; + import java.util.concurrent.CompletableFuture; + import java.util.concurrent.CompletionException; ++import java.util.concurrent.CompletionStage; + import java.util.concurrent.Executor; + import java.util.concurrent.atomic.AtomicInteger; + import java.util.function.BooleanSupplier; +@@ -52,6 +54,7 @@ + import net.minecraft.CrashReportCategory; + import net.minecraft.ReportedException; + import net.minecraft.Util; ++import net.minecraft.core.HolderGetter; + import net.minecraft.core.RegistryAccess; + import net.minecraft.core.SectionPos; + import net.minecraft.core.registries.Registries; +@@ -85,9 +88,11 @@ + import net.minecraft.world.level.chunk.storage.ChunkSerializer; + import net.minecraft.world.level.chunk.storage.ChunkStorage; + import net.minecraft.world.level.entity.ChunkStatusUpdateListener; ++import net.minecraft.world.level.entity.EntityAccess; + import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; + import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; + import net.minecraft.world.level.levelgen.RandomState; ++import net.minecraft.world.level.levelgen.blending.BlendingData; + import net.minecraft.world.level.levelgen.structure.StructureStart; + import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; + import net.minecraft.world.level.storage.DimensionDataStorage; +@@ -95,8 +100,12 @@ + import net.minecraft.world.phys.Vec3; + import org.apache.commons.lang3.mutable.MutableBoolean; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.generator.CustomChunkGenerator; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider { ++ + private static final byte CHUNK_TYPE_REPLACEABLE = -1; + private static final byte CHUNK_TYPE_UNKNOWN = 0; + private static final byte CHUNK_TYPE_FULL = 1; +@@ -107,83 +116,109 @@ + public static final int MIN_VIEW_DISTANCE = 2; + public static final int MAX_VIEW_DISTANCE = 32; + public static final int FORCED_TICKET_LEVEL = ChunkLevel.byStatus(FullChunkStatus.ENTITY_TICKING); +- private final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap<>(); +- private volatile Long2ObjectLinkedOpenHashMap visibleChunkMap = this.updatingChunkMap.clone(); +- private final Long2ObjectLinkedOpenHashMap pendingUnloads = new Long2ObjectLinkedOpenHashMap<>(); +- private final LongSet entitiesInLevel = new LongOpenHashSet(); +- final ServerLevel level; ++ public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); ++ public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; ++ private final Long2ObjectLinkedOpenHashMap pendingUnloads; ++ private final LongSet entitiesInLevel; ++ public final ServerLevel level; + private final ThreadedLevelLightEngine lightEngine; + private final BlockableEventLoop mainThreadExecutor; +- private ChunkGenerator generator; ++ public ChunkGenerator generator; + private final RandomState randomState; + private final ChunkGeneratorStructureState chunkGeneratorState; + private final Supplier overworldDataStorage; + private final PoiManager poiManager; +- final LongSet toDrop = new LongOpenHashSet(); ++ public final LongSet toDrop; + private boolean modified; + private final ChunkTaskPriorityQueueSorter queueSorter; + private final ProcessorHandle> worldgenMailbox; + private final ProcessorHandle> mainThreadMailbox; +- private final ChunkProgressListener progressListener; ++ public final ChunkProgressListener progressListener; + private final ChunkStatusUpdateListener chunkStatusListener; +- private final ChunkMap.DistanceManager distanceManager; +- private final AtomicInteger tickingGenerated = new AtomicInteger(); ++ public final ChunkMap.DistanceManager distanceManager; ++ private final AtomicInteger tickingGenerated; + private final StructureTemplateManager structureTemplateManager; + private final String storageName; +- private final PlayerMap playerMap = new PlayerMap(); +- private final Int2ObjectMap entityMap = new Int2ObjectOpenHashMap<>(); +- private final Long2ByteMap chunkTypeCache = new Long2ByteOpenHashMap(); +- private final Long2LongMap chunkSaveCooldowns = new Long2LongOpenHashMap(); +- private final Queue unloadQueue = Queues.newConcurrentLinkedQueue(); ++ private final PlayerMap playerMap; ++ public final Int2ObjectMap entityMap; ++ private final Long2ByteMap chunkTypeCache; ++ private final Long2LongMap chunkSaveCooldowns; ++ private final Queue unloadQueue; + private int serverViewDistance; + +- public ChunkMap( +- ServerLevel level, +- LevelStorageSource.LevelStorageAccess levelStorageAccess, +- DataFixer fixerUpper, +- StructureTemplateManager structureManager, +- Executor dispatcher, +- BlockableEventLoop mainThreadExecutor, +- LightChunkGetter lightChunk, +- ChunkGenerator generator, +- ChunkProgressListener progressListener, +- ChunkStatusUpdateListener chunkStatusListener, +- Supplier overworldDataStorage, +- int viewDistance, +- boolean sync +- ) { ++ // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() ++ public final CallbackExecutor callbackExecutor = new CallbackExecutor(); ++ public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable { ++ ++ private final java.util.Queue queue = new java.util.ArrayDeque<>(); ++ ++ @Override ++ public void execute(Runnable runnable) { ++ queue.add(runnable); ++ } ++ ++ @Override ++ public void run() { ++ Runnable task; ++ while ((task = queue.poll()) != null) { ++ task.run(); ++ } ++ } ++ }; ++ // CraftBukkit end ++ ++ public ChunkMap(ServerLevel level, LevelStorageSource.LevelStorageAccess levelStorageAccess, DataFixer fixerUpper, StructureTemplateManager structureManager, Executor dispatcher, BlockableEventLoop mainThreadExecutor, LightChunkGetter lightChunk, ChunkGenerator generator, ChunkProgressListener progressListener, ChunkStatusUpdateListener chunkStatusListener, Supplier overworldDataStorage, int viewDistance, boolean sync) { + super(levelStorageAccess.getDimensionPath(level.dimension()).resolve("region"), fixerUpper, sync); ++ this.visibleChunkMap = this.updatingChunkMap.clone(); ++ this.pendingUnloads = new Long2ObjectLinkedOpenHashMap(); ++ this.entitiesInLevel = new LongOpenHashSet(); ++ this.toDrop = new LongOpenHashSet(); ++ this.tickingGenerated = new AtomicInteger(); ++ this.playerMap = new PlayerMap(); ++ this.entityMap = new Int2ObjectOpenHashMap(); ++ this.chunkTypeCache = new Long2ByteOpenHashMap(); ++ this.chunkSaveCooldowns = new Long2LongOpenHashMap(); ++ this.unloadQueue = Queues.newConcurrentLinkedQueue(); + this.structureTemplateManager = structureManager; +- Path dimensionPath = levelStorageAccess.getDimensionPath(level.dimension()); +- this.storageName = dimensionPath.getFileName().toString(); ++ Path path = levelStorageAccess.getDimensionPath(level.dimension()); ++ ++ this.storageName = path.getFileName().toString(); + this.level = level; + this.generator = generator; +- RegistryAccess registryAccess = level.registryAccess(); +- long seed = level.getSeed(); +- if (generator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) { +- this.randomState = RandomState.create(noiseBasedChunkGenerator.generatorSettings().value(), registryAccess.lookupOrThrow(Registries.NOISE), seed); ++ // CraftBukkit start - SPIGOT-7051: It's a rigged game! Use delegate for random state creation, otherwise it is not so random. ++ if (generator instanceof CustomChunkGenerator) { ++ generator = ((CustomChunkGenerator) generator).getDelegate(); ++ } ++ // CraftBukkit end ++ RegistryAccess iregistrycustom = level.registryAccess(); ++ long j = level.getSeed(); ++ ++ if (generator instanceof NoiseBasedChunkGenerator) { ++ NoiseBasedChunkGenerator chunkgeneratorabstract = (NoiseBasedChunkGenerator) generator; ++ ++ this.randomState = RandomState.create((NoiseGeneratorSettings) chunkgeneratorabstract.generatorSettings().value(), (HolderGetter) iregistrycustom.lookupOrThrow(Registries.NOISE), j); + } else { +- this.randomState = RandomState.create(NoiseGeneratorSettings.dummy(), registryAccess.lookupOrThrow(Registries.NOISE), seed); ++ this.randomState = RandomState.create(NoiseGeneratorSettings.dummy(), (HolderGetter) iregistrycustom.lookupOrThrow(Registries.NOISE), j); + } + +- this.chunkGeneratorState = generator.createState(registryAccess.lookupOrThrow(Registries.STRUCTURE_SET), this.randomState, seed); ++ this.chunkGeneratorState = generator.createState(iregistrycustom.lookupOrThrow(Registries.STRUCTURE_SET), this.randomState, j); + this.mainThreadExecutor = mainThreadExecutor; +- ProcessorMailbox processorMailbox = ProcessorMailbox.create(dispatcher, "worldgen"); +- ProcessorHandle processorHandle = ProcessorHandle.of("main", mainThreadExecutor::tell); ++ ProcessorMailbox threadedmailbox = ProcessorMailbox.create(dispatcher, "worldgen"); ++ ++ Objects.requireNonNull(mainThreadExecutor); ++ ProcessorHandle mailbox = ProcessorHandle.of("main", mainThreadExecutor::tell); ++ + this.progressListener = progressListener; + this.chunkStatusListener = chunkStatusListener; +- ProcessorMailbox processorMailbox1 = ProcessorMailbox.create(dispatcher, "light"); +- this.queueSorter = new ChunkTaskPriorityQueueSorter( +- ImmutableList.of(processorMailbox, processorHandle, processorMailbox1), dispatcher, Integer.MAX_VALUE +- ); +- this.worldgenMailbox = this.queueSorter.getProcessor(processorMailbox, false); +- this.mainThreadMailbox = this.queueSorter.getProcessor(processorHandle, false); +- this.lightEngine = new ThreadedLevelLightEngine( +- lightChunk, this, this.level.dimensionType().hasSkyLight(), processorMailbox1, this.queueSorter.getProcessor(processorMailbox1, false) +- ); ++ ProcessorMailbox threadedmailbox1 = ProcessorMailbox.create(dispatcher, "light"); ++ ++ this.queueSorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), dispatcher, Integer.MAX_VALUE); ++ this.worldgenMailbox = this.queueSorter.getProcessor(threadedmailbox, false); ++ this.mainThreadMailbox = this.queueSorter.getProcessor(mailbox, false); ++ this.lightEngine = new ThreadedLevelLightEngine(lightChunk, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false)); + this.distanceManager = new ChunkMap.DistanceManager(dispatcher, mainThreadExecutor); + this.overworldDataStorage = overworldDataStorage; +- this.poiManager = new PoiManager(dimensionPath.resolve("poi"), fixerUpper, sync, registryAccess, level); ++ this.poiManager = new PoiManager(path.resolve("poi"), fixerUpper, sync, iregistrycustom, level); + this.setServerViewDistance(viewDistance); + } + +@@ -200,30 +235,36 @@ + } + + public void debugReloadGenerator() { +- DataResult dataResult = ChunkGenerator.CODEC.encodeStart(JsonOps.INSTANCE, this.generator); +- DataResult dataResult1 = dataResult.flatMap(jsonElement -> ChunkGenerator.CODEC.parse(JsonOps.INSTANCE, jsonElement)); +- dataResult1.result().ifPresent(generator -> this.generator = generator); ++ DataResult dataresult = ChunkGenerator.CODEC.encodeStart(JsonOps.INSTANCE, this.generator); ++ DataResult dataresult1 = dataresult.flatMap((jsonelement) -> { ++ return ChunkGenerator.CODEC.parse(JsonOps.INSTANCE, jsonelement); ++ }); ++ ++ dataresult1.result().ifPresent((chunkgenerator) -> { ++ this.generator = chunkgenerator; ++ }); + } + + private static double euclideanDistanceSquared(ChunkPos chunkPos, Entity entity) { +- double d = (double)SectionPos.sectionToBlockCoord(chunkPos.x, 8); +- double d1 = (double)SectionPos.sectionToBlockCoord(chunkPos.z, 8); +- double d2 = d - entity.getX(); ++ double d0 = (double) SectionPos.sectionToBlockCoord(chunkPos.x, 8); ++ double d1 = (double) SectionPos.sectionToBlockCoord(chunkPos.z, 8); ++ double d2 = d0 - entity.getX(); + double d3 = d1 - entity.getZ(); ++ + return d2 * d2 + d3 * d3; + } + +- boolean isChunkTracked(ServerPlayer serverPlayer, int i, int i1) { +- return serverPlayer.getChunkTrackingView().contains(i, i1) && !serverPlayer.connection.chunkSender.isPending(ChunkPos.asLong(i, i1)); ++ boolean isChunkTracked(ServerPlayer entityplayer, int i, int j) { ++ return entityplayer.getChunkTrackingView().contains(i, j) && !entityplayer.connection.chunkSender.isPending(ChunkPos.asLong(i, j)); + } + +- private boolean isChunkOnTrackedBorder(ServerPlayer serverPlayer, int i, int i1) { +- if (!this.isChunkTracked(serverPlayer, i, i1)) { ++ private boolean isChunkOnTrackedBorder(ServerPlayer entityplayer, int i, int j) { ++ if (!this.isChunkTracked(entityplayer, i, j)) { + return false; + } else { +- for (int i2 = -1; i2 <= 1; i2++) { +- for (int i3 = -1; i3 <= 1; i3++) { +- if ((i2 != 0 || i3 != 0) && !this.isChunkTracked(serverPlayer, i + i2, i1 + i3)) { ++ for (int k = -1; k <= 1; ++k) { ++ for (int l = -1; l <= 1; ++l) { ++ if ((k != 0 || l != 0) && !this.isChunkTracked(entityplayer, i + k, j + l)) { + return true; + } + } +@@ -239,181 +280,194 @@ + + @Nullable + protected ChunkHolder getUpdatingChunkIfPresent(long chunkPos) { +- return this.updatingChunkMap.get(chunkPos); ++ return (ChunkHolder) this.updatingChunkMap.get(chunkPos); + } + + @Nullable + protected ChunkHolder getVisibleChunkIfPresent(long chunkPos) { +- return this.visibleChunkMap.get(chunkPos); ++ return (ChunkHolder) this.visibleChunkMap.get(chunkPos); + } + + protected IntSupplier getChunkQueueLevel(long chunkPos) { + return () -> { +- ChunkHolder visibleChunkIfPresent = this.getVisibleChunkIfPresent(chunkPos); +- return visibleChunkIfPresent == null +- ? ChunkTaskPriorityQueue.PRIORITY_LEVEL_COUNT - 1 +- : Math.min(visibleChunkIfPresent.getQueueLevel(), ChunkTaskPriorityQueue.PRIORITY_LEVEL_COUNT - 1); ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(chunkPos); ++ ++ return playerchunk == null ? ChunkTaskPriorityQueue.PRIORITY_LEVEL_COUNT - 1 : Math.min(playerchunk.getQueueLevel(), ChunkTaskPriorityQueue.PRIORITY_LEVEL_COUNT - 1); + }; + } + + public String getChunkDebugData(ChunkPos pos) { +- ChunkHolder visibleChunkIfPresent = this.getVisibleChunkIfPresent(pos.toLong()); +- if (visibleChunkIfPresent == null) { ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos.toLong()); ++ ++ if (playerchunk == null) { + return "null"; + } else { +- String string = visibleChunkIfPresent.getTicketLevel() + "\n"; +- ChunkStatus lastAvailableStatus = visibleChunkIfPresent.getLastAvailableStatus(); +- ChunkAccess lastAvailable = visibleChunkIfPresent.getLastAvailable(); +- if (lastAvailableStatus != null) { +- string = string + "St: §" + lastAvailableStatus.getIndex() + lastAvailableStatus + "§r\n"; ++ String s = playerchunk.getTicketLevel() + "\n"; ++ ChunkStatus chunkstatus = playerchunk.getLastAvailableStatus(); ++ ChunkAccess ichunkaccess = playerchunk.getLastAvailable(); ++ ++ if (chunkstatus != null) { ++ s = s + "St: \u00a7" + chunkstatus.getIndex() + chunkstatus + "\u00a7r\n"; + } + +- if (lastAvailable != null) { +- string = string + "Ch: §" + lastAvailable.getStatus().getIndex() + lastAvailable.getStatus() + "§r\n"; ++ if (ichunkaccess != null) { ++ s = s + "Ch: \u00a7" + ichunkaccess.getStatus().getIndex() + ichunkaccess.getStatus() + "\u00a7r\n"; + } + +- FullChunkStatus fullStatus = visibleChunkIfPresent.getFullStatus(); +- string = string + '§' + fullStatus.ordinal() + fullStatus; +- return string + "§r"; ++ FullChunkStatus fullchunkstatus = playerchunk.getFullStatus(); ++ ++ s = s + String.valueOf('\u00a7') + fullchunkstatus.ordinal() + fullchunkstatus; ++ return s + "\u00a7r"; + } + } + +- private CompletableFuture, ChunkHolder.ChunkLoadingFailure>> getChunkRangeFuture( +- ChunkHolder chunkHolder, int range, IntFunction statusGetter +- ) { ++ private CompletableFuture, ChunkHolder.Failure>> getChunkRangeFuture(ChunkHolder chunkHolder, int range, IntFunction statusGetter) { + if (range == 0) { +- ChunkStatus chunkStatus = statusGetter.apply(0); +- return chunkHolder.getOrScheduleFuture(chunkStatus, this).thenApply(either -> either.mapLeft(List::of)); ++ ChunkStatus chunkstatus = (ChunkStatus) statusGetter.apply(0); ++ ++ return chunkHolder.getOrScheduleFuture(chunkstatus, this).thenApply((either) -> { ++ return either.mapLeft(List::of); ++ }); + } else { +- List>> list = new ArrayList<>(); +- List list1 = new ArrayList<>(); +- ChunkPos pos = chunkHolder.getPos(); +- int i = pos.x; +- int i1 = pos.z; ++ List>> list = new ArrayList(); ++ List list1 = new ArrayList(); ++ ChunkPos chunkcoordintpair = chunkHolder.getPos(); ++ int j = chunkcoordintpair.x; ++ int k = chunkcoordintpair.z; + +- for (int i2 = -range; i2 <= range; i2++) { +- for (int i3 = -range; i3 <= range; i3++) { +- int max = Math.max(Math.abs(i3), Math.abs(i2)); +- final ChunkPos chunkPos = new ChunkPos(i + i3, i1 + i2); +- long l = chunkPos.toLong(); +- ChunkHolder updatingChunkIfPresent = this.getUpdatingChunkIfPresent(l); +- if (updatingChunkIfPresent == null) { +- return CompletableFuture.completedFuture(Either.right(new ChunkHolder.ChunkLoadingFailure() { +- @Override ++ for (int l = -range; l <= range; ++l) { ++ for (int i1 = -range; i1 <= range; ++i1) { ++ int j1 = Math.max(Math.abs(i1), Math.abs(l)); ++ final ChunkPos chunkcoordintpair1 = new ChunkPos(j + i1, k + l); ++ long k1 = chunkcoordintpair1.toLong(); ++ ChunkHolder playerchunk1 = this.getUpdatingChunkIfPresent(k1); ++ ++ if (playerchunk1 == null) { ++ return CompletableFuture.completedFuture(Either.right(new ChunkHolder.Failure() { + public String toString() { +- return "Unloaded " + chunkPos; ++ return "Unloaded " + chunkcoordintpair1; + } + })); + } + +- ChunkStatus chunkStatus1 = statusGetter.apply(max); +- CompletableFuture> orScheduleFuture = updatingChunkIfPresent.getOrScheduleFuture( +- chunkStatus1, this +- ); +- list1.add(updatingChunkIfPresent); +- list.add(orScheduleFuture); ++ ChunkStatus chunkstatus1 = (ChunkStatus) statusGetter.apply(j1); ++ CompletableFuture> completablefuture = playerchunk1.getOrScheduleFuture(chunkstatus1, this); ++ ++ list1.add(playerchunk1); ++ list.add(completablefuture); + } + } + +- CompletableFuture>> completableFuture = Util.sequence(list); +- CompletableFuture, ChunkHolder.ChunkLoadingFailure>> completableFuture1 = completableFuture.thenApply(list2 -> { ++ CompletableFuture>> completablefuture1 = Util.sequence(list); ++ CompletableFuture, ChunkHolder.Failure>> completablefuture2 = completablefuture1.thenApply((list2) -> { + List list3 = Lists.newArrayList(); +- int i4 = 0; ++ // CraftBukkit start - decompile error ++ int cnt = 0; + +- for (final Either either : list2) { ++ for (Iterator iterator = list2.iterator(); iterator.hasNext(); ++cnt) { ++ final int l1 = cnt; ++ // CraftBukkit end ++ final Either either = (Either) iterator.next(); ++ + if (either == null) { + throw this.debugFuturesAndCreateReportedException(new IllegalStateException("At least one of the chunk futures were null"), "n/a"); + } + + Optional optional = either.left(); ++ + if (optional.isEmpty()) { +- final int i5 = i4; +- return Either.right(new ChunkHolder.ChunkLoadingFailure() { +- @Override ++ return Either.right(new ChunkHolder.Failure() { + public String toString() { +- return "Unloaded " + new ChunkPos(i + i5 % (range * 2 + 1), i1 + i5 / (range * 2 + 1)) + " " + either.right().get(); ++ ChunkPos chunkcoordintpair2 = new ChunkPos(j + l1 % (range * 2 + 1), k + l1 / (range * 2 + 1)); ++ ++ return "Unloaded " + chunkcoordintpair2 + " " + either.right().get(); + } + }); + } + +- list3.add(optional.get()); +- i4++; ++ list3.add((ChunkAccess) optional.get()); + } + + return Either.left(list3); + }); ++ Iterator iterator = list1.iterator(); + +- for (ChunkHolder chunkHolder1 : list1) { +- chunkHolder1.addSaveDependency("getChunkRangeFuture " + pos + " " + range, completableFuture1); ++ while (iterator.hasNext()) { ++ ChunkHolder playerchunk2 = (ChunkHolder) iterator.next(); ++ ++ playerchunk2.addSaveDependency("getChunkRangeFuture " + chunkcoordintpair + " " + range, completablefuture2); + } + +- return completableFuture1; ++ return completablefuture2; + } + } + + public ReportedException debugFuturesAndCreateReportedException(IllegalStateException exception, String details) { +- StringBuilder stringBuilder = new StringBuilder(); +- Consumer consumer = chunkHolder -> chunkHolder.getAllFutures() +- .forEach( +- pair -> { +- ChunkStatus chunkStatus = pair.getFirst(); +- CompletableFuture> completableFuture = pair.getSecond(); +- if (completableFuture != null && completableFuture.isDone() && completableFuture.join() == null) { +- stringBuilder.append(chunkHolder.getPos()) +- .append(" - status: ") +- .append(chunkStatus) +- .append(" future: ") +- .append(completableFuture) +- .append(System.lineSeparator()); +- } +- } +- ); +- stringBuilder.append("Updating:").append(System.lineSeparator()); ++ StringBuilder stringbuilder = new StringBuilder(); ++ Consumer consumer = (playerchunk) -> { ++ playerchunk.getAllFutures().forEach((pair) -> { ++ ChunkStatus chunkstatus = (ChunkStatus) pair.getFirst(); ++ CompletableFuture> completablefuture = (CompletableFuture) pair.getSecond(); ++ ++ if (completablefuture != null && completablefuture.isDone() && completablefuture.join() == null) { ++ stringbuilder.append(playerchunk.getPos()).append(" - status: ").append(chunkstatus).append(" future: ").append(completablefuture).append(System.lineSeparator()); ++ } ++ ++ }); ++ }; ++ ++ stringbuilder.append("Updating:").append(System.lineSeparator()); + this.updatingChunkMap.values().forEach(consumer); +- stringBuilder.append("Visible:").append(System.lineSeparator()); ++ stringbuilder.append("Visible:").append(System.lineSeparator()); + this.visibleChunkMap.values().forEach(consumer); +- CrashReport crashReport = CrashReport.forThrowable(exception, "Chunk loading"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Chunk loading"); +- crashReportCategory.setDetail("Details", details); +- crashReportCategory.setDetail("Futures", stringBuilder); +- return new ReportedException(crashReport); ++ CrashReport crashreport = CrashReport.forThrowable(exception, "Chunk loading"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Chunk loading"); ++ ++ crashreportsystemdetails.setDetail("Details", (Object) details); ++ crashreportsystemdetails.setDetail("Futures", (Object) stringbuilder); ++ return new ReportedException(crashreport); + } + +- public CompletableFuture> prepareEntityTickingChunk(ChunkHolder chunk) { +- return this.getChunkRangeFuture(chunk, 2, i -> ChunkStatus.FULL) +- .thenApplyAsync(either -> either.mapLeft(list -> (LevelChunk)list.get(list.size() / 2)), this.mainThreadExecutor); ++ public CompletableFuture> prepareEntityTickingChunk(ChunkHolder chunk) { ++ return this.getChunkRangeFuture(chunk, 2, (i) -> { ++ return ChunkStatus.FULL; ++ }).thenApplyAsync((either) -> { ++ return either.mapLeft((list) -> { ++ return (LevelChunk) list.get(list.size() / 2); ++ }); ++ }, this.mainThreadExecutor); + } + + @Nullable +- ChunkHolder updateChunkScheduling(long chunkPos, int newLevel, @Nullable ChunkHolder holder, int oldLevel) { +- if (!ChunkLevel.isLoaded(oldLevel) && !ChunkLevel.isLoaded(newLevel)) { +- return holder; ++ ChunkHolder updateChunkScheduling(long chunkPos, int j, @Nullable ChunkHolder newLevel, int holder) { ++ if (!ChunkLevel.isLoaded(holder) && !ChunkLevel.isLoaded(j)) { ++ return newLevel; + } else { +- if (holder != null) { +- holder.setTicketLevel(newLevel); ++ if (newLevel != null) { ++ newLevel.setTicketLevel(j); + } + +- if (holder != null) { +- if (!ChunkLevel.isLoaded(newLevel)) { ++ if (newLevel != null) { ++ if (!ChunkLevel.isLoaded(j)) { + this.toDrop.add(chunkPos); + } else { + this.toDrop.remove(chunkPos); + } + } + +- if (ChunkLevel.isLoaded(newLevel) && holder == null) { +- holder = this.pendingUnloads.remove(chunkPos); +- if (holder != null) { +- holder.setTicketLevel(newLevel); ++ if (ChunkLevel.isLoaded(j) && newLevel == null) { ++ newLevel = (ChunkHolder) this.pendingUnloads.remove(chunkPos); ++ if (newLevel != null) { ++ newLevel.setTicketLevel(j); + } else { +- holder = new ChunkHolder(new ChunkPos(chunkPos), newLevel, this.level, this.lightEngine, this.queueSorter, this); ++ newLevel = new ChunkHolder(new ChunkPos(chunkPos), j, this.level, this.lightEngine, this.queueSorter, this); + } + +- this.updatingChunkMap.put(chunkPos, holder); ++ this.updatingChunkMap.put(chunkPos, newLevel); + this.modified = true; + } + +- return holder; ++ return newLevel; + } + } + +@@ -425,124 +479,133 @@ + } finally { + super.close(); + } ++ + } + + protected void saveAllChunks(boolean flush) { + if (flush) { +- List list = this.visibleChunkMap +- .values() +- .stream() +- .filter(ChunkHolder::wasAccessibleSinceLastSave) +- .peek(ChunkHolder::refreshAccessibility) +- .toList(); +- MutableBoolean mutableBoolean = new MutableBoolean(); ++ List list = this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).toList(); ++ MutableBoolean mutableboolean = new MutableBoolean(); + + do { +- mutableBoolean.setFalse(); +- list.stream() +- .map(chunkHolder -> { +- CompletableFuture chunkToSave; +- do { +- chunkToSave = chunkHolder.getChunkToSave(); +- this.mainThreadExecutor.managedBlock(chunkToSave::isDone); +- } while (chunkToSave != chunkHolder.getChunkToSave()); +- +- return chunkToSave.join(); +- }) +- .filter(chunkAccess -> chunkAccess instanceof ImposterProtoChunk || chunkAccess instanceof LevelChunk) +- .filter(this::save) +- .forEach(chunkAccess -> mutableBoolean.setTrue()); +- } while (mutableBoolean.isTrue()); ++ mutableboolean.setFalse(); ++ list.stream().map((playerchunk) -> { ++ CompletableFuture completablefuture; + +- this.processUnloads(() -> true); ++ do { ++ completablefuture = playerchunk.getChunkToSave(); ++ BlockableEventLoop iasynctaskhandler = this.mainThreadExecutor; ++ ++ Objects.requireNonNull(completablefuture); ++ iasynctaskhandler.managedBlock(completablefuture::isDone); ++ } while (completablefuture != playerchunk.getChunkToSave()); ++ ++ return (ChunkAccess) completablefuture.join(); ++ }).filter((ichunkaccess) -> { ++ return ichunkaccess instanceof ImposterProtoChunk || ichunkaccess instanceof LevelChunk; ++ }).filter(this::save).forEach((ichunkaccess) -> { ++ mutableboolean.setTrue(); ++ }); ++ } while (mutableboolean.isTrue()); ++ ++ this.processUnloads(() -> { ++ return true; ++ }); + this.flushWorker(); + } else { + this.visibleChunkMap.values().forEach(this::saveChunkIfNeeded); + } ++ + } + + protected void tick(BooleanSupplier hasMoreTime) { +- ProfilerFiller profiler = this.level.getProfiler(); +- profiler.push("poi"); ++ ProfilerFiller gameprofilerfiller = this.level.getProfiler(); ++ ++ gameprofilerfiller.push("poi"); + this.poiManager.tick(hasMoreTime); +- profiler.popPush("chunk_unload"); ++ gameprofilerfiller.popPush("chunk_unload"); + if (!this.level.noSave()) { + this.processUnloads(hasMoreTime); + } + +- profiler.pop(); ++ gameprofilerfiller.pop(); + } + + public boolean hasWork() { +- return this.lightEngine.hasLightWork() +- || !this.pendingUnloads.isEmpty() +- || !this.updatingChunkMap.isEmpty() +- || this.poiManager.hasWork() +- || !this.toDrop.isEmpty() +- || !this.unloadQueue.isEmpty() +- || this.queueSorter.hasWork() +- || this.distanceManager.hasTickets(); ++ return this.lightEngine.hasLightWork() || !this.pendingUnloads.isEmpty() || !this.updatingChunkMap.isEmpty() || this.poiManager.hasWork() || !this.toDrop.isEmpty() || !this.unloadQueue.isEmpty() || this.queueSorter.hasWork() || this.distanceManager.hasTickets(); + } + + private void processUnloads(BooleanSupplier hasMoreTime) { +- LongIterator longIterator = this.toDrop.iterator(); ++ LongIterator longiterator = this.toDrop.iterator(); + +- for (int i = 0; longIterator.hasNext() && (hasMoreTime.getAsBoolean() || i < 200 || this.toDrop.size() > 2000); longIterator.remove()) { +- long l = longIterator.nextLong(); +- ChunkHolder chunkHolder = this.updatingChunkMap.remove(l); +- if (chunkHolder != null) { +- this.pendingUnloads.put(l, chunkHolder); ++ for (int i = 0; longiterator.hasNext() && (hasMoreTime.getAsBoolean() || i < 200 || this.toDrop.size() > 2000); longiterator.remove()) { ++ long j = longiterator.nextLong(); ++ ChunkHolder playerchunk = (ChunkHolder) this.updatingChunkMap.remove(j); ++ ++ if (playerchunk != null) { ++ this.pendingUnloads.put(j, playerchunk); + this.modified = true; +- i++; +- this.scheduleUnload(l, chunkHolder); ++ ++i; ++ this.scheduleUnload(j, playerchunk); + } + } + +- int max = Math.max(0, this.unloadQueue.size() - 2000); ++ int k = Math.max(0, this.unloadQueue.size() - 2000); + + Runnable runnable; +- while ((hasMoreTime.getAsBoolean() || max > 0) && (runnable = this.unloadQueue.poll()) != null) { +- max--; ++ ++ while ((hasMoreTime.getAsBoolean() || k > 0) && (runnable = (Runnable) this.unloadQueue.poll()) != null) { ++ --k; + runnable.run(); + } + +- int i1 = 0; +- ObjectIterator objectIterator = this.visibleChunkMap.values().iterator(); ++ int l = 0; ++ ObjectIterator objectiterator = this.visibleChunkMap.values().iterator(); + +- while (i1 < 20 && hasMoreTime.getAsBoolean() && objectIterator.hasNext()) { +- if (this.saveChunkIfNeeded(objectIterator.next())) { +- i1++; ++ while (l < 20 && hasMoreTime.getAsBoolean() && objectiterator.hasNext()) { ++ if (this.saveChunkIfNeeded((ChunkHolder) objectiterator.next())) { ++ ++l; + } + } ++ + } + +- private void scheduleUnload(long chunkPos, ChunkHolder chunkHolder) { +- CompletableFuture chunkToSave = chunkHolder.getChunkToSave(); +- chunkToSave.thenAcceptAsync(chunkAccess -> { +- CompletableFuture chunkToSave1 = chunkHolder.getChunkToSave(); +- if (chunkToSave1 != chunkToSave) { +- this.scheduleUnload(chunkPos, chunkHolder); ++ private void scheduleUnload(long chunkPos, ChunkHolder playerchunk) { ++ CompletableFuture completablefuture = playerchunk.getChunkToSave(); ++ Consumer consumer = (ichunkaccess) -> { // CraftBukkit - decompile error ++ CompletableFuture completablefuture1 = playerchunk.getChunkToSave(); ++ ++ if (completablefuture1 != completablefuture) { ++ this.scheduleUnload(chunkPos, playerchunk); + } else { +- if (this.pendingUnloads.remove(chunkPos, chunkHolder) && chunkAccess != null) { +- if (chunkAccess instanceof LevelChunk) { +- ((LevelChunk)chunkAccess).setLoaded(false); ++ if (this.pendingUnloads.remove(chunkPos, playerchunk) && ichunkaccess != null) { ++ if (ichunkaccess instanceof LevelChunk) { ++ ((LevelChunk) ichunkaccess).setLoaded(false); + } + +- this.save(chunkAccess); +- if (this.entitiesInLevel.remove(chunkPos) && chunkAccess instanceof LevelChunk levelChunk) { +- this.level.unload(levelChunk); ++ this.save(ichunkaccess); ++ if (this.entitiesInLevel.remove(chunkPos) && ichunkaccess instanceof LevelChunk) { ++ LevelChunk chunk = (LevelChunk) ichunkaccess; ++ ++ this.level.unload(chunk); + } + +- this.lightEngine.updateChunkStatus(chunkAccess.getPos()); ++ this.lightEngine.updateChunkStatus(ichunkaccess.getPos()); + this.lightEngine.tryScheduleUpdate(); +- this.progressListener.onStatusChange(chunkAccess.getPos(), null); +- this.chunkSaveCooldowns.remove(chunkAccess.getPos().toLong()); ++ this.progressListener.onStatusChange(ichunkaccess.getPos(), (ChunkStatus) null); ++ this.chunkSaveCooldowns.remove(ichunkaccess.getPos().toLong()); + } ++ + } +- }, this.unloadQueue::add).whenComplete((_void, throwable) -> { ++ }; ++ Queue queue = this.unloadQueue; ++ ++ Objects.requireNonNull(this.unloadQueue); ++ completablefuture.thenAcceptAsync(consumer, queue::add).whenComplete((ovoid, throwable) -> { + if (throwable != null) { +- LOGGER.error("Failed to save chunk {}", chunkHolder.getPos(), throwable); ++ ChunkMap.LOGGER.error("Failed to save chunk {}", playerchunk.getPos(), throwable); + } ++ + }); + } + +@@ -556,23 +619,26 @@ + } + } + +- public CompletableFuture> schedule(ChunkHolder holder, ChunkStatus status) { +- ChunkPos pos = holder.getPos(); ++ public CompletableFuture> schedule(ChunkHolder holder, ChunkStatus status) { ++ ChunkPos chunkcoordintpair = holder.getPos(); ++ + if (status == ChunkStatus.EMPTY) { +- return this.scheduleChunkLoad(pos); ++ return this.scheduleChunkLoad(chunkcoordintpair); + } else { + if (status == ChunkStatus.LIGHT) { +- this.distanceManager.addTicket(TicketType.LIGHT, pos, ChunkLevel.byStatus(ChunkStatus.LIGHT), pos); ++ this.distanceManager.addTicket(TicketType.LIGHT, chunkcoordintpair, ChunkLevel.byStatus(ChunkStatus.LIGHT), chunkcoordintpair); + } + + if (!status.hasLoadDependencies()) { +- Optional optional = holder.getOrScheduleFuture(status.getParent(), this).getNow(ChunkHolder.UNLOADED_CHUNK).left(); +- if (optional.isPresent() && optional.get().getStatus().isOrAfter(status)) { +- CompletableFuture> completableFuture = status.load( +- this.level, this.structureTemplateManager, this.lightEngine, chunkAccess -> this.protoChunkToFullChunk(holder), optional.get() +- ); +- this.progressListener.onStatusChange(pos, status); +- return completableFuture; ++ Optional optional = ((Either) holder.getOrScheduleFuture(status.getParent(), this).getNow(ChunkHolder.UNLOADED_CHUNK)).left(); ++ ++ if (optional.isPresent() && ((ChunkAccess) optional.get()).getStatus().isOrAfter(status)) { ++ CompletableFuture> completablefuture = status.load(this.level, this.structureTemplateManager, this.lightEngine, (ichunkaccess) -> { ++ return this.protoChunkToFullChunk(holder); ++ }, (ChunkAccess) optional.get()); ++ ++ this.progressListener.onStatusChange(chunkcoordintpair, status); ++ return completablefuture; + } + } + +@@ -580,41 +646,49 @@ + } + } + +- private CompletableFuture> scheduleChunkLoad(ChunkPos chunkPos) { +- return this.readChunk(chunkPos).thenApply(optional -> optional.filter(compoundTag -> { +- boolean isChunkDataValid = isChunkDataValid(compoundTag); +- if (!isChunkDataValid) { +- LOGGER.error("Chunk file at {} is missing level data, skipping", chunkPos); ++ private CompletableFuture> scheduleChunkLoad(ChunkPos chunkPos) { ++ return this.readChunk(chunkPos).thenApply((optional) -> { ++ return optional.filter((nbttagcompound) -> { ++ boolean flag = isChunkDataValid(nbttagcompound); ++ ++ if (!flag) { ++ ChunkMap.LOGGER.error("Chunk file at {} is missing level data, skipping", chunkPos); + } + +- return isChunkDataValid; +- })).>thenApplyAsync(optional -> { ++ return flag; ++ }); ++ }).thenApplyAsync((optional) -> { + this.level.getProfiler().incrementCounter("chunkLoad"); + if (optional.isPresent()) { +- ChunkAccess chunkAccess = ChunkSerializer.read(this.level, this.poiManager, chunkPos, optional.get()); +- this.markPosition(chunkPos, chunkAccess.getStatus().getChunkType()); +- return Either.left(chunkAccess); ++ ProtoChunk protochunk = ChunkSerializer.read(this.level, this.poiManager, chunkPos, (CompoundTag) optional.get()); ++ ++ this.markPosition(chunkPos, protochunk.getStatus().getChunkType()); ++ return Either.left(protochunk); // CraftBukkit - decompile error + } else { +- return Either.left(this.createEmptyChunk(chunkPos)); ++ return Either.left(this.createEmptyChunk(chunkPos)); // CraftBukkit - decompile error + } +- }, this.mainThreadExecutor).exceptionallyAsync(throwable -> this.handleChunkLoadFailure(throwable, chunkPos), this.mainThreadExecutor); ++ }, this.mainThreadExecutor).exceptionallyAsync((throwable) -> { ++ return this.handleChunkLoadFailure(throwable, chunkPos); ++ }, this.mainThreadExecutor); + } + + private static boolean isChunkDataValid(CompoundTag tag) { + return tag.contains("Status", 8); + } + +- private Either handleChunkLoadFailure(Throwable exception, ChunkPos chunkPos) { +- if (exception instanceof ReportedException reportedException) { +- Throwable cause = reportedException.getCause(); +- if (!(cause instanceof IOException)) { ++ private Either handleChunkLoadFailure(Throwable exception, ChunkPos chunkPos) { ++ if (exception instanceof ReportedException) { ++ ReportedException reportedexception = (ReportedException) exception; ++ Throwable throwable1 = reportedexception.getCause(); ++ ++ if (!(throwable1 instanceof IOException)) { + this.markPositionReplaceable(chunkPos); +- throw reportedException; ++ throw reportedexception; + } + +- LOGGER.error("Couldn't load chunk {}", chunkPos, cause); ++ ChunkMap.LOGGER.error("Couldn't load chunk {}", chunkPos, throwable1); + } else if (exception instanceof IOException) { +- LOGGER.error("Couldn't load chunk {}", chunkPos, exception); ++ ChunkMap.LOGGER.error("Couldn't load chunk {}", chunkPos, exception); + } + + return Either.left(this.createEmptyChunk(chunkPos)); +@@ -622,172 +696,206 @@ + + private ChunkAccess createEmptyChunk(ChunkPos chunkPos) { + this.markPositionReplaceable(chunkPos); +- return new ProtoChunk(chunkPos, UpgradeData.EMPTY, this.level, this.level.registryAccess().registryOrThrow(Registries.BIOME), null); ++ return new ProtoChunk(chunkPos, UpgradeData.EMPTY, this.level, this.level.registryAccess().registryOrThrow(Registries.BIOME), (BlendingData) null); + } + + private void markPositionReplaceable(ChunkPos chunkPos) { +- this.chunkTypeCache.put(chunkPos.toLong(), (byte)-1); ++ this.chunkTypeCache.put(chunkPos.toLong(), (byte) -1); + } + +- private byte markPosition(ChunkPos chunkPos, ChunkStatus.ChunkType chunkType) { +- return this.chunkTypeCache.put(chunkPos.toLong(), (byte)(chunkType == ChunkStatus.ChunkType.PROTOCHUNK ? -1 : 1)); ++ private byte markPosition(ChunkPos chunkPos, ChunkStatus.Type chunkType) { ++ return this.chunkTypeCache.put(chunkPos.toLong(), (byte) (chunkType == ChunkStatus.Type.PROTOCHUNK ? -1 : 1)); + } + +- private CompletableFuture> scheduleChunkGeneration(ChunkHolder chunkHolder, ChunkStatus chunkStatus) { +- ChunkPos pos = chunkHolder.getPos(); +- CompletableFuture, ChunkHolder.ChunkLoadingFailure>> chunkRangeFuture = this.getChunkRangeFuture( +- chunkHolder, chunkStatus.getRange(), i -> this.getDependencyStatus(chunkStatus, i) +- ); +- this.level.getProfiler().incrementCounter(() -> "chunkGenerate " + chunkStatus); +- Executor executor = runnable -> this.worldgenMailbox.tell(ChunkTaskPriorityQueueSorter.message(chunkHolder, runnable)); +- return chunkRangeFuture.thenComposeAsync( +- either -> either.map( +- list -> { +- try { +- ChunkAccess chunkAccess = list.get(list.size() / 2); +- CompletableFuture> completableFuture; +- if (chunkAccess.getStatus().isOrAfter(chunkStatus)) { +- completableFuture = chunkStatus.load( +- this.level, +- this.structureTemplateManager, +- this.lightEngine, +- chunkAccess1 -> this.protoChunkToFullChunk(chunkHolder), +- chunkAccess +- ); +- } else { +- completableFuture = chunkStatus.generate( +- executor, +- this.level, +- this.generator, +- this.structureTemplateManager, +- this.lightEngine, +- chunkAccess1 -> this.protoChunkToFullChunk(chunkHolder), +- (List)list +- ); +- } +- +- this.progressListener.onStatusChange(pos, chunkStatus); +- return completableFuture; +- } catch (Exception var9) { +- var9.getStackTrace(); +- CrashReport crashReport = CrashReport.forThrowable(var9, "Exception generating new chunk"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Chunk to be generated"); +- crashReportCategory.setDetail("Location", String.format(Locale.ROOT, "%d,%d", pos.x, pos.z)); +- crashReportCategory.setDetail("Position hash", ChunkPos.asLong(pos.x, pos.z)); +- crashReportCategory.setDetail("Generator", this.generator); +- this.mainThreadExecutor.execute(() -> { +- throw new ReportedException(crashReport); +- }); +- throw new ReportedException(crashReport); +- } +- }, +- chunkLoadingFailure -> { +- this.releaseLightTicket(pos); +- return CompletableFuture.completedFuture(Either.right(chunkLoadingFailure)); ++ private CompletableFuture> scheduleChunkGeneration(ChunkHolder chunkHolder, ChunkStatus chunkStatus) { ++ ChunkPos chunkcoordintpair = chunkHolder.getPos(); ++ CompletableFuture, ChunkHolder.Failure>> completablefuture = this.getChunkRangeFuture(chunkHolder, chunkStatus.getRange(), (i) -> { ++ return this.getDependencyStatus(chunkStatus, i); ++ }); ++ ++ this.level.getProfiler().incrementCounter(() -> { ++ return "chunkGenerate " + chunkStatus; ++ }); ++ Executor executor = (runnable) -> { ++ this.worldgenMailbox.tell(ChunkTaskPriorityQueueSorter.message(chunkHolder, runnable)); ++ }; ++ ++ return completablefuture.thenComposeAsync((either) -> { ++ return (CompletionStage) either.map((list) -> { ++ try { ++ ChunkAccess ichunkaccess = (ChunkAccess) list.get(list.size() / 2); ++ CompletableFuture completablefuture1; ++ ++ if (ichunkaccess.getStatus().isOrAfter(chunkStatus)) { ++ completablefuture1 = chunkStatus.load(this.level, this.structureTemplateManager, this.lightEngine, (ichunkaccess1) -> { ++ return this.protoChunkToFullChunk(chunkHolder); ++ }, ichunkaccess); ++ } else { ++ completablefuture1 = chunkStatus.generate(executor, this.level, this.generator, this.structureTemplateManager, this.lightEngine, (ichunkaccess1) -> { ++ return this.protoChunkToFullChunk(chunkHolder); ++ }, list); + } +- ), +- executor +- ); ++ ++ this.progressListener.onStatusChange(chunkcoordintpair, chunkStatus); ++ return completablefuture1; ++ } catch (Exception exception) { ++ exception.getStackTrace(); ++ CrashReport crashreport = CrashReport.forThrowable(exception, "Exception generating new chunk"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Chunk to be generated"); ++ ++ crashreportsystemdetails.setDetail("Location", (Object) String.format(Locale.ROOT, "%d,%d", chunkcoordintpair.x, chunkcoordintpair.z)); ++ crashreportsystemdetails.setDetail("Position hash", (Object) ChunkPos.asLong(chunkcoordintpair.x, chunkcoordintpair.z)); ++ crashreportsystemdetails.setDetail("Generator", (Object) this.generator); ++ this.mainThreadExecutor.execute(() -> { ++ throw new ReportedException(crashreport); ++ }); ++ throw new ReportedException(crashreport); ++ } ++ }, (playerchunk_failure) -> { ++ this.releaseLightTicket(chunkcoordintpair); ++ return CompletableFuture.completedFuture(Either.right(playerchunk_failure)); ++ }); ++ }, executor); + } + + protected void releaseLightTicket(ChunkPos chunkPos) { +- this.mainThreadExecutor +- .tell( +- Util.name( +- () -> this.distanceManager.removeTicket(TicketType.LIGHT, chunkPos, ChunkLevel.byStatus(ChunkStatus.LIGHT), chunkPos), +- () -> "release light ticket " + chunkPos +- ) +- ); ++ this.mainThreadExecutor.tell(Util.name(() -> { ++ this.distanceManager.removeTicket(TicketType.LIGHT, chunkPos, ChunkLevel.byStatus(ChunkStatus.LIGHT), chunkPos); ++ }, () -> { ++ return "release light ticket " + chunkPos; ++ })); + } + + private ChunkStatus getDependencyStatus(ChunkStatus chunkStatus, int i) { +- ChunkStatus parent; ++ ChunkStatus chunkstatus1; ++ + if (i == 0) { +- parent = chunkStatus.getParent(); ++ chunkstatus1 = chunkStatus.getParent(); + } else { +- parent = ChunkStatus.getStatusAroundFullChunk(ChunkStatus.getDistance(chunkStatus) + i); ++ chunkstatus1 = ChunkStatus.getStatusAroundFullChunk(ChunkStatus.getDistance(chunkStatus) + i); + } + +- return parent; ++ return chunkstatus1; + } + + private static void postLoadProtoChunk(ServerLevel level, List tags) { + if (!tags.isEmpty()) { +- level.addWorldGenChunkEntities(EntityType.loadEntitiesRecursive(tags, level)); ++ // CraftBukkit start - these are spawned serialized (DefinedStructure) and we don't call an add event below at the moment due to ordering complexities ++ level.addWorldGenChunkEntities(EntityType.loadEntitiesRecursive(tags, level).filter((entity) -> { ++ boolean needsRemoval = false; ++ net.minecraft.server.dedicated.DedicatedServer server = level.getCraftServer().getServer(); ++ if (!server.areNpcsEnabled() && entity instanceof net.minecraft.world.entity.npc.NPC) { ++ entity.discard(); ++ needsRemoval = true; ++ } ++ if (!server.isSpawningAnimals() && (entity instanceof net.minecraft.world.entity.animal.Animal || entity instanceof net.minecraft.world.entity.animal.WaterAnimal)) { ++ entity.discard(); ++ needsRemoval = true; ++ } ++ return !needsRemoval; ++ })); ++ // CraftBukkit end + } ++ + } + +- private CompletableFuture> protoChunkToFullChunk(ChunkHolder holder) { +- CompletableFuture> futureIfPresentUnchecked = holder.getFutureIfPresentUnchecked( +- ChunkStatus.FULL.getParent() +- ); +- return futureIfPresentUnchecked.thenApplyAsync(either -> { +- ChunkStatus chunkStatus = ChunkLevel.generationStatus(holder.getTicketLevel()); +- return !chunkStatus.isOrAfter(ChunkStatus.FULL) ? ChunkHolder.UNLOADED_CHUNK : either.mapLeft(chunkAccess -> { +- ChunkPos pos = holder.getPos(); +- ProtoChunk protoChunk = (ProtoChunk)chunkAccess; +- LevelChunk wrapped; +- if (protoChunk instanceof ImposterProtoChunk) { +- wrapped = ((ImposterProtoChunk)protoChunk).getWrapped(); ++ private CompletableFuture> protoChunkToFullChunk(ChunkHolder holder) { ++ CompletableFuture> completablefuture = holder.getFutureIfPresentUnchecked(ChunkStatus.FULL.getParent()); ++ ++ return completablefuture.thenApplyAsync((either) -> { ++ ChunkStatus chunkstatus = ChunkLevel.generationStatus(holder.getTicketLevel()); ++ ++ return !chunkstatus.isOrAfter(ChunkStatus.FULL) ? ChunkHolder.UNLOADED_CHUNK : either.mapLeft((ichunkaccess) -> { ++ ChunkPos chunkcoordintpair = holder.getPos(); ++ ProtoChunk protochunk = (ProtoChunk) ichunkaccess; ++ LevelChunk chunk; ++ ++ if (protochunk instanceof ImposterProtoChunk) { ++ chunk = ((ImposterProtoChunk) protochunk).getWrapped(); + } else { +- wrapped = new LevelChunk(this.level, protoChunk, chunk -> postLoadProtoChunk(this.level, protoChunk.getEntities())); +- holder.replaceProtoChunk(new ImposterProtoChunk(wrapped, false)); ++ chunk = new LevelChunk(this.level, protochunk, (chunk1) -> { ++ postLoadProtoChunk(this.level, protochunk.getEntities()); ++ }); ++ holder.replaceProtoChunk(new ImposterProtoChunk(chunk, false)); + } + +- wrapped.setFullStatus(() -> ChunkLevel.fullStatus(holder.getTicketLevel())); +- wrapped.runPostLoad(); +- if (this.entitiesInLevel.add(pos.toLong())) { +- wrapped.setLoaded(true); +- wrapped.registerAllBlockEntitiesAfterLevelLoad(); +- wrapped.registerTickContainerInLevel(this.level); ++ chunk.setFullStatus(() -> { ++ return ChunkLevel.fullStatus(holder.getTicketLevel()); ++ }); ++ chunk.runPostLoad(); ++ if (this.entitiesInLevel.add(chunkcoordintpair.toLong())) { ++ chunk.setLoaded(true); ++ chunk.registerAllBlockEntitiesAfterLevelLoad(); ++ chunk.registerTickContainerInLevel(this.level); + } + +- return wrapped; ++ return chunk; + }); +- }, runnable -> this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(runnable, holder.getPos().toLong(), holder::getTicketLevel))); ++ }, (runnable) -> { ++ ProcessorHandle mailbox = this.mainThreadMailbox; ++ long i = holder.getPos().toLong(); ++ ++ Objects.requireNonNull(holder); ++ mailbox.tell(ChunkTaskPriorityQueueSorter.message(runnable, i, holder::getTicketLevel)); ++ }); + } + +- public CompletableFuture> prepareTickingChunk(ChunkHolder holder) { +- CompletableFuture, ChunkHolder.ChunkLoadingFailure>> chunkRangeFuture = this.getChunkRangeFuture( +- holder, 1, i -> ChunkStatus.FULL +- ); +- CompletableFuture> completableFuture = chunkRangeFuture.>thenApplyAsync( +- either -> either.mapLeft(list -> (LevelChunk)list.get(list.size() / 2)), +- runnable -> this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)) +- ) +- .thenApplyAsync(either -> either.ifLeft(levelChunk -> { +- levelChunk.postProcessGeneration(); +- this.level.startTickingChunk(levelChunk); +- CompletableFuture chunkSendSyncFuture = holder.getChunkSendSyncFuture(); +- if (chunkSendSyncFuture.isDone()) { +- this.onChunkReadyToSend(levelChunk); +- } else { +- chunkSendSyncFuture.thenAcceptAsync(object -> this.onChunkReadyToSend(levelChunk), this.mainThreadExecutor); +- } +- }), this.mainThreadExecutor); +- completableFuture.handle((either, throwable) -> { ++ public CompletableFuture> prepareTickingChunk(ChunkHolder holder) { ++ CompletableFuture, ChunkHolder.Failure>> completablefuture = this.getChunkRangeFuture(holder, 1, (i) -> { ++ return ChunkStatus.FULL; ++ }); ++ CompletableFuture> completablefuture1 = completablefuture.thenApplyAsync((either) -> { ++ return either.mapLeft((list) -> { ++ return (LevelChunk) list.get(list.size() / 2); ++ }); ++ }, (runnable) -> { ++ this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); ++ }).thenApplyAsync((either) -> { ++ return either.ifLeft((chunk) -> { ++ chunk.postProcessGeneration(); ++ this.level.startTickingChunk(chunk); ++ CompletableFuture completablefuture2 = holder.getChunkSendSyncFuture(); ++ ++ if (completablefuture2.isDone()) { ++ this.onChunkReadyToSend(chunk); ++ } else { ++ completablefuture2.thenAcceptAsync((object) -> { ++ this.onChunkReadyToSend(chunk); ++ }, this.mainThreadExecutor); ++ } ++ ++ }); ++ }, this.mainThreadExecutor); ++ ++ completablefuture1.handle((either, throwable) -> { + this.tickingGenerated.getAndIncrement(); + return null; + }); +- return completableFuture; ++ return completablefuture1; + } + +- private void onChunkReadyToSend(LevelChunk levelChunk) { +- ChunkPos pos = levelChunk.getPos(); ++ private void onChunkReadyToSend(LevelChunk chunk) { ++ ChunkPos chunkcoordintpair = chunk.getPos(); ++ Iterator iterator = this.playerMap.getAllPlayers().iterator(); + +- for (ServerPlayer serverPlayer : this.playerMap.getAllPlayers()) { +- if (serverPlayer.getChunkTrackingView().contains(pos)) { +- markChunkPendingToSend(serverPlayer, levelChunk); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ if (entityplayer.getChunkTrackingView().contains(chunkcoordintpair)) { ++ markChunkPendingToSend(entityplayer, chunk); + } + } ++ + } + +- public CompletableFuture> prepareAccessibleChunk(ChunkHolder holder) { +- return this.getChunkRangeFuture(holder, 1, ChunkStatus::getStatusAroundFullChunk) +- .thenApplyAsync( +- either -> either.mapLeft(list -> (LevelChunk)list.get(list.size() / 2)), +- runnable -> this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)) +- ); ++ public CompletableFuture> prepareAccessibleChunk(ChunkHolder holder) { ++ return this.getChunkRangeFuture(holder, 1, ChunkStatus::getStatusAroundFullChunk).thenApplyAsync((either) -> { ++ return either.mapLeft((list) -> { ++ return (LevelChunk) list.get(list.size() / 2); ++ }); ++ }, (runnable) -> { ++ this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); ++ }); + } + + public int getTickingGenerated() { +@@ -798,20 +906,23 @@ + if (!holder.wasAccessibleSinceLastSave()) { + return false; + } else { +- ChunkAccess chunkAccess = holder.getChunkToSave().getNow(null); +- if (!(chunkAccess instanceof ImposterProtoChunk) && !(chunkAccess instanceof LevelChunk)) { ++ ChunkAccess ichunkaccess = (ChunkAccess) holder.getChunkToSave().getNow(null); // CraftBukkit - decompile error ++ ++ if (!(ichunkaccess instanceof ImposterProtoChunk) && !(ichunkaccess instanceof LevelChunk)) { + return false; + } else { +- long l = chunkAccess.getPos().toLong(); +- long orDefault = this.chunkSaveCooldowns.getOrDefault(l, -1L); +- long l1 = System.currentTimeMillis(); +- if (l1 < orDefault) { ++ long i = ichunkaccess.getPos().toLong(); ++ long j = this.chunkSaveCooldowns.getOrDefault(i, -1L); ++ long k = System.currentTimeMillis(); ++ ++ if (k < j) { + return false; + } else { +- boolean flag = this.save(chunkAccess); ++ boolean flag = this.save(ichunkaccess); ++ + holder.refreshAccessibility(); + if (flag) { +- this.chunkSaveCooldowns.put(l, l1 + 10000L); ++ this.chunkSaveCooldowns.put(i, k + 10000L); + } + + return flag; +@@ -820,103 +931,116 @@ + } + } + +- private boolean save(ChunkAccess chunk) { ++ public boolean save(ChunkAccess chunk) { + this.poiManager.flush(chunk.getPos()); + if (!chunk.isUnsaved()) { + return false; + } else { + chunk.setUnsaved(false); +- ChunkPos pos = chunk.getPos(); ++ ChunkPos chunkcoordintpair = chunk.getPos(); + + try { +- ChunkStatus status = chunk.getStatus(); +- if (status.getChunkType() != ChunkStatus.ChunkType.LEVELCHUNK) { +- if (this.isExistingChunkFull(pos)) { ++ ChunkStatus chunkstatus = chunk.getStatus(); ++ ++ if (chunkstatus.getChunkType() != ChunkStatus.Type.LEVELCHUNK) { ++ if (this.isExistingChunkFull(chunkcoordintpair)) { + return false; + } + +- if (status == ChunkStatus.EMPTY && chunk.getAllStarts().values().stream().noneMatch(StructureStart::isValid)) { ++ if (chunkstatus == ChunkStatus.EMPTY && chunk.getAllStarts().values().stream().noneMatch(StructureStart::isValid)) { + return false; + } + } + + this.level.getProfiler().incrementCounter("chunkSave"); +- CompoundTag compoundTag = ChunkSerializer.write(this.level, chunk); +- this.write(pos, compoundTag); +- this.markPosition(pos, status.getChunkType()); ++ CompoundTag nbttagcompound = ChunkSerializer.write(this.level, chunk); ++ ++ this.write(chunkcoordintpair, nbttagcompound); ++ this.markPosition(chunkcoordintpair, chunkstatus.getChunkType()); + return true; +- } catch (Exception var5) { +- LOGGER.error("Failed to save chunk {},{}", pos.x, pos.z, var5); ++ } catch (Exception exception) { ++ ChunkMap.LOGGER.error("Failed to save chunk {},{}", new Object[]{chunkcoordintpair.x, chunkcoordintpair.z, exception}); + return false; + } + } + } + + private boolean isExistingChunkFull(ChunkPos chunkPos) { +- byte b = this.chunkTypeCache.get(chunkPos.toLong()); +- if (b != 0) { +- return b == 1; ++ byte b0 = this.chunkTypeCache.get(chunkPos.toLong()); ++ ++ if (b0 != 0) { ++ return b0 == 1; + } else { +- CompoundTag compoundTag; ++ CompoundTag nbttagcompound; ++ + try { +- compoundTag = this.readChunk(chunkPos).join().orElse(null); +- if (compoundTag == null) { ++ nbttagcompound = (CompoundTag) ((Optional) this.readChunk(chunkPos).join()).orElse((Object) null); ++ if (nbttagcompound == null) { + this.markPositionReplaceable(chunkPos); + return false; + } +- } catch (Exception var5) { +- LOGGER.error("Failed to read chunk {}", chunkPos, var5); ++ } catch (Exception exception) { ++ ChunkMap.LOGGER.error("Failed to read chunk {}", chunkPos, exception); + this.markPositionReplaceable(chunkPos); + return false; + } + +- ChunkStatus.ChunkType chunkTypeFromTag = ChunkSerializer.getChunkTypeFromTag(compoundTag); +- return this.markPosition(chunkPos, chunkTypeFromTag) == 1; ++ ChunkStatus.Type chunkstatus_type = ChunkSerializer.getChunkTypeFromTag(nbttagcompound); ++ ++ return this.markPosition(chunkPos, chunkstatus_type) == 1; + } + } + + protected void setServerViewDistance(int i) { +- int i1 = Mth.clamp(i, 2, 32); +- if (i1 != this.serverViewDistance) { +- this.serverViewDistance = i1; ++ int j = Mth.clamp(i, 2, 32); ++ ++ if (j != this.serverViewDistance) { ++ this.serverViewDistance = j; + this.distanceManager.updatePlayerTickets(this.serverViewDistance); ++ Iterator iterator = this.playerMap.getAllPlayers().iterator(); + +- for (ServerPlayer serverPlayer : this.playerMap.getAllPlayers()) { +- this.updateChunkTracking(serverPlayer); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ this.updateChunkTracking(entityplayer); + } + } ++ + } + +- int getPlayerViewDistance(ServerPlayer serverPlayer) { +- return Mth.clamp(serverPlayer.requestedViewDistance(), 2, this.serverViewDistance); ++ int getPlayerViewDistance(ServerPlayer entityplayer) { ++ return Mth.clamp(entityplayer.requestedViewDistance(), 2, this.serverViewDistance); + } + +- private void markChunkPendingToSend(ServerPlayer serverPlayer, ChunkPos chunkPos) { +- LevelChunk chunkToSend = this.getChunkToSend(chunkPos.toLong()); +- if (chunkToSend != null) { +- markChunkPendingToSend(serverPlayer, chunkToSend); ++ private void markChunkPendingToSend(ServerPlayer entityplayer, ChunkPos chunkcoordintpair) { ++ LevelChunk chunk = this.getChunkToSend(chunkcoordintpair.toLong()); ++ ++ if (chunk != null) { ++ markChunkPendingToSend(entityplayer, chunk); + } ++ + } + +- private static void markChunkPendingToSend(ServerPlayer serverPlayer, LevelChunk levelChunk) { +- serverPlayer.connection.chunkSender.markChunkPendingToSend(levelChunk); ++ private static void markChunkPendingToSend(ServerPlayer entityplayer, LevelChunk chunk) { ++ entityplayer.connection.chunkSender.markChunkPendingToSend(chunk); + } + +- private static void dropChunk(ServerPlayer serverPlayer, ChunkPos chunkPos) { +- serverPlayer.connection.chunkSender.dropChunk(serverPlayer, chunkPos); ++ private static void dropChunk(ServerPlayer entityplayer, ChunkPos chunkcoordintpair) { ++ entityplayer.connection.chunkSender.dropChunk(entityplayer, chunkcoordintpair); + } + + @Nullable +- public LevelChunk getChunkToSend(long l) { +- ChunkHolder visibleChunkIfPresent = this.getVisibleChunkIfPresent(l); +- return visibleChunkIfPresent == null ? null : visibleChunkIfPresent.getChunkToSend(); ++ public LevelChunk getChunkToSend(long i) { ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(i); ++ ++ return playerchunk == null ? null : playerchunk.getChunkToSend(); + } + + public int size() { + return this.visibleChunkMap.size(); + } + +- public net.minecraft.server.level.DistanceManager getDistanceManager() { ++ public DistanceManager getDistanceManager() { + return this.distanceManager; + } + +@@ -925,98 +1049,94 @@ + } + + void dumpChunks(Writer writer) throws IOException { +- CsvOutput csvOutput = CsvOutput.builder() +- .addColumn("x") +- .addColumn("z") +- .addColumn("level") +- .addColumn("in_memory") +- .addColumn("status") +- .addColumn("full_status") +- .addColumn("accessible_ready") +- .addColumn("ticking_ready") +- .addColumn("entity_ticking_ready") +- .addColumn("ticket") +- .addColumn("spawning") +- .addColumn("block_entity_count") +- .addColumn("ticking_ticket") +- .addColumn("ticking_level") +- .addColumn("block_ticks") +- .addColumn("fluid_ticks") +- .build(writer); +- TickingTracker tickingTracker = this.distanceManager.tickingTracker(); ++ CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("z").addColumn("level").addColumn("in_memory").addColumn("status").addColumn("full_status").addColumn("accessible_ready").addColumn("ticking_ready").addColumn("entity_ticking_ready").addColumn("ticket").addColumn("spawning").addColumn("block_entity_count").addColumn("ticking_ticket").addColumn("ticking_level").addColumn("block_ticks").addColumn("fluid_ticks").build(writer); ++ TickingTracker tickingtracker = this.distanceManager.tickingTracker(); ++ ObjectBidirectionalIterator objectbidirectionaliterator = this.visibleChunkMap.long2ObjectEntrySet().iterator(); + +- for (Entry entry : this.visibleChunkMap.long2ObjectEntrySet()) { +- long longKey = entry.getLongKey(); +- ChunkPos chunkPos = new ChunkPos(longKey); +- ChunkHolder chunkHolder = entry.getValue(); +- Optional optional = Optional.ofNullable(chunkHolder.getLastAvailable()); +- Optional optional1 = optional.flatMap( +- chunkAccess -> chunkAccess instanceof LevelChunk ? Optional.of((LevelChunk)chunkAccess) : Optional.empty() +- ); +- csvOutput.writeRow( +- chunkPos.x, +- chunkPos.z, +- chunkHolder.getTicketLevel(), +- optional.isPresent(), +- optional.map(ChunkAccess::getStatus).orElse(null), +- optional1.map(LevelChunk::getFullStatus).orElse(null), +- printFuture(chunkHolder.getFullChunkFuture()), +- printFuture(chunkHolder.getTickingChunkFuture()), +- printFuture(chunkHolder.getEntityTickingChunkFuture()), +- this.distanceManager.getTicketDebugString(longKey), +- this.anyPlayerCloseEnoughForSpawning(chunkPos), +- optional1.map(levelChunk -> levelChunk.getBlockEntities().size()).orElse(0), +- tickingTracker.getTicketDebugString(longKey), +- tickingTracker.getLevel(longKey), +- optional1.map(levelChunk -> levelChunk.getBlockTicks().count()).orElse(0), +- optional1.map(levelChunk -> levelChunk.getFluidTicks().count()).orElse(0) +- ); ++ while (objectbidirectionaliterator.hasNext()) { ++ Entry entry = (Entry) objectbidirectionaliterator.next(); ++ long i = entry.getLongKey(); ++ ChunkPos chunkcoordintpair = new ChunkPos(i); ++ ChunkHolder playerchunk = (ChunkHolder) entry.getValue(); ++ Optional optional = Optional.ofNullable(playerchunk.getLastAvailable()); ++ Optional optional1 = optional.flatMap((ichunkaccess) -> { ++ return ichunkaccess instanceof LevelChunk ? Optional.of((LevelChunk) ichunkaccess) : Optional.empty(); ++ }); ++ ++ // CraftBukkit - decompile error ++ csvwriter.writeRow(chunkcoordintpair.x, chunkcoordintpair.z, playerchunk.getTicketLevel(), optional.isPresent(), optional.map(ChunkAccess::getStatus).orElse(null), optional1.map(LevelChunk::getFullStatus).orElse(null), printFuture(playerchunk.getFullChunkFuture()), printFuture(playerchunk.getTickingChunkFuture()), printFuture(playerchunk.getEntityTickingChunkFuture()), this.distanceManager.getTicketDebugString(i), this.anyPlayerCloseEnoughForSpawning(chunkcoordintpair), optional1.map((chunk) -> { ++ return chunk.getBlockEntities().size(); ++ }).orElse(0), tickingtracker.getTicketDebugString(i), tickingtracker.getLevel(i), optional1.map((chunk) -> { ++ return chunk.getBlockTicks().count(); ++ }).orElse(0), optional1.map((chunk) -> { ++ return chunk.getFluidTicks().count(); ++ }).orElse(0)); + } ++ + } + +- private static String printFuture(CompletableFuture> future) { ++ private static String printFuture(CompletableFuture> future) { + try { +- Either either = future.getNow(null); +- return either != null ? either.map(levelChunk -> "done", chunkLoadingFailure -> "unloaded") : "not completed"; +- } catch (CompletionException var2) { +- return "failed " + var2.getCause().getMessage(); +- } catch (CancellationException var3) { ++ Either either = (Either) future.getNow(null); // CraftBukkit - decompile error ++ ++ return either != null ? (String) either.map((chunk) -> { ++ return "done"; ++ }, (playerchunk_failure) -> { ++ return "unloaded"; ++ }) : "not completed"; ++ } catch (CompletionException completionexception) { ++ return "failed " + completionexception.getCause().getMessage(); ++ } catch (CancellationException cancellationexception) { + return "cancelled"; + } + } + + private CompletableFuture> readChunk(ChunkPos pos) { +- return this.read(pos).thenApplyAsync(optional -> optional.map(this::upgradeChunkTag), Util.backgroundExecutor()); ++ return this.read(pos).thenApplyAsync((optional) -> { ++ return optional.map((nbttagcompound) -> upgradeChunkTag(nbttagcompound, pos)); // CraftBukkit ++ }, Util.backgroundExecutor()); + } + +- private CompoundTag upgradeChunkTag(CompoundTag tag) { +- return this.upgradeChunkTag(this.level.dimension(), this.overworldDataStorage, tag, this.generator.getTypeNameForDataFixer()); ++ // CraftBukkit start ++ private CompoundTag upgradeChunkTag(CompoundTag nbttagcompound, ChunkPos chunkcoordintpair) { ++ return this.upgradeChunkTag(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, this.generator.getTypeNameForDataFixer(), chunkcoordintpair, level); ++ // CraftBukkit end + } + + boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkPos) { + if (!this.distanceManager.hasPlayersNearby(chunkPos.toLong())) { + return false; + } else { +- for (ServerPlayer serverPlayer : this.playerMap.getAllPlayers()) { +- if (this.playerIsCloseEnoughForSpawning(serverPlayer, chunkPos)) { +- return true; ++ Iterator iterator = this.playerMap.getAllPlayers().iterator(); ++ ++ ServerPlayer entityplayer; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return false; + } +- } + +- return false; ++ entityplayer = (ServerPlayer) iterator.next(); ++ } while (!this.playerIsCloseEnoughForSpawning(entityplayer, chunkPos)); ++ ++ return true; + } + } + + public List getPlayersCloseForSpawning(ChunkPos chunkPos) { +- long l = chunkPos.toLong(); +- if (!this.distanceManager.hasPlayersNearby(l)) { ++ long i = chunkPos.toLong(); ++ ++ if (!this.distanceManager.hasPlayersNearby(i)) { + return List.of(); + } else { + Builder builder = ImmutableList.builder(); ++ Iterator iterator = this.playerMap.getAllPlayers().iterator(); + +- for (ServerPlayer serverPlayer : this.playerMap.getAllPlayers()) { +- if (this.playerIsCloseEnoughForSpawning(serverPlayer, chunkPos)) { +- builder.add(serverPlayer); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ if (this.playerIsCloseEnoughForSpawning(entityplayer, chunkPos)) { ++ builder.add(entityplayer); + } + } + +@@ -1028,8 +1148,9 @@ + if (player.isSpectator()) { + return false; + } else { +- double d = euclideanDistanceSquared(chunkPos, player); +- return d < 16384.0; ++ double d0 = euclideanDistanceSquared(chunkPos, player); ++ ++ return d0 < 16384.0D; + } + } + +@@ -1038,55 +1159,64 @@ + } + + void updatePlayerStatus(ServerPlayer player, boolean track) { +- boolean flag = this.skipPlayer(player); +- boolean flag1 = this.playerMap.ignoredOrUnknown(player); ++ boolean flag1 = this.skipPlayer(player); ++ boolean flag2 = this.playerMap.ignoredOrUnknown(player); ++ + if (track) { +- this.playerMap.addPlayer(player, flag); ++ this.playerMap.addPlayer(player, flag1); + this.updatePlayerPos(player); +- if (!flag) { +- this.distanceManager.addPlayer(SectionPos.of(player), player); ++ if (!flag1) { ++ this.distanceManager.addPlayer(SectionPos.of((EntityAccess) player), player); + } + + player.setChunkTrackingView(ChunkTrackingView.EMPTY); + this.updateChunkTracking(player); + } else { +- SectionPos lastSectionPos = player.getLastSectionPos(); ++ SectionPos sectionposition = player.getLastSectionPos(); ++ + this.playerMap.removePlayer(player); +- if (!flag1) { +- this.distanceManager.removePlayer(lastSectionPos, player); ++ if (!flag2) { ++ this.distanceManager.removePlayer(sectionposition, player); + } + + this.applyChunkTrackingView(player, ChunkTrackingView.EMPTY); + } ++ + } + +- private void updatePlayerPos(ServerPlayer serverPlayer) { +- SectionPos sectionPos = SectionPos.of(serverPlayer); +- serverPlayer.setLastSectionPos(sectionPos); ++ private void updatePlayerPos(ServerPlayer entityplayer) { ++ SectionPos sectionposition = SectionPos.of((EntityAccess) entityplayer); ++ ++ entityplayer.setLastSectionPos(sectionposition); + } + + public void move(ServerPlayer player) { +- for (ChunkMap.TrackedEntity trackedEntity : this.entityMap.values()) { +- if (trackedEntity.entity == player) { +- trackedEntity.updatePlayers(this.level.players()); ++ ObjectIterator objectiterator = this.entityMap.values().iterator(); ++ ++ while (objectiterator.hasNext()) { ++ ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); ++ ++ if (playerchunkmap_entitytracker.entity == player) { ++ playerchunkmap_entitytracker.updatePlayers(this.level.players()); + } else { +- trackedEntity.updatePlayer(player); ++ playerchunkmap_entitytracker.updatePlayer(player); + } + } + +- SectionPos lastSectionPos = player.getLastSectionPos(); +- SectionPos sectionPos = SectionPos.of(player); ++ SectionPos sectionposition = player.getLastSectionPos(); ++ SectionPos sectionposition1 = SectionPos.of((EntityAccess) player); + boolean flag = this.playerMap.ignored(player); + boolean flag1 = this.skipPlayer(player); +- boolean flag2 = lastSectionPos.asLong() != sectionPos.asLong(); ++ boolean flag2 = sectionposition.asLong() != sectionposition1.asLong(); ++ + if (flag2 || flag != flag1) { + this.updatePlayerPos(player); + if (!flag) { +- this.distanceManager.removePlayer(lastSectionPos, player); ++ this.distanceManager.removePlayer(sectionposition, player); + } + + if (!flag1) { +- this.distanceManager.addPlayer(sectionPos, player); ++ this.distanceManager.addPlayer(sectionposition1, player); + } + + if (!flag && flag1) { +@@ -1099,46 +1229,66 @@ + + this.updateChunkTracking(player); + } ++ + } + +- private void updateChunkTracking(ServerPlayer serverPlayer) { +- ChunkPos chunkPos = serverPlayer.chunkPosition(); +- int playerViewDistance = this.getPlayerViewDistance(serverPlayer); +- if (serverPlayer.getChunkTrackingView() instanceof ChunkTrackingView.Positioned positioned +- && positioned.center().equals(chunkPos) +- && positioned.viewDistance() == playerViewDistance) { +- return; ++ private void updateChunkTracking(ServerPlayer entityplayer) { ++ ChunkPos chunkcoordintpair = entityplayer.chunkPosition(); ++ int i = this.getPlayerViewDistance(entityplayer); ++ ChunkTrackingView chunktrackingview = entityplayer.getChunkTrackingView(); ++ ++ if (chunktrackingview instanceof ChunkTrackingView.a) { ++ ChunkTrackingView.a chunktrackingview_a = (ChunkTrackingView.a) chunktrackingview; ++ ++ if (chunktrackingview_a.center().equals(chunkcoordintpair) && chunktrackingview_a.viewDistance() == i) { ++ return; ++ } + } + +- this.applyChunkTrackingView(serverPlayer, ChunkTrackingView.of(chunkPos, playerViewDistance)); ++ this.applyChunkTrackingView(entityplayer, ChunkTrackingView.of(chunkcoordintpair, i)); + } + +- private void applyChunkTrackingView(ServerPlayer serverPlayer, ChunkTrackingView chunkTrackingView) { +- if (serverPlayer.level() == this.level) { +- ChunkTrackingView chunkTrackingView1 = serverPlayer.getChunkTrackingView(); +- if (chunkTrackingView instanceof ChunkTrackingView.Positioned positioned +- && (!(chunkTrackingView1 instanceof ChunkTrackingView.Positioned positioned1) || !positioned1.center().equals(positioned.center()))) { +- serverPlayer.connection.send(new ClientboundSetChunkCacheCenterPacket(positioned.center().x, positioned.center().z)); ++ private void applyChunkTrackingView(ServerPlayer entityplayer, ChunkTrackingView chunktrackingview) { ++ if (entityplayer.level() == this.level) { ++ ChunkTrackingView chunktrackingview1 = entityplayer.getChunkTrackingView(); ++ ++ if (chunktrackingview instanceof ChunkTrackingView.a) { ++ label15: ++ { ++ ChunkTrackingView.a chunktrackingview_a = (ChunkTrackingView.a) chunktrackingview; ++ ++ if (chunktrackingview1 instanceof ChunkTrackingView.a) { ++ ChunkTrackingView.a chunktrackingview_a1 = (ChunkTrackingView.a) chunktrackingview1; ++ ++ if (chunktrackingview_a1.center().equals(chunktrackingview_a.center())) { ++ break label15; ++ } ++ } ++ ++ entityplayer.connection.send(new ClientboundSetChunkCacheCenterPacket(chunktrackingview_a.center().x, chunktrackingview_a.center().z)); ++ } + } + +- ChunkTrackingView.difference( +- chunkTrackingView1, +- chunkTrackingView, +- chunkPos -> this.markChunkPendingToSend(serverPlayer, chunkPos), +- chunkPos -> dropChunk(serverPlayer, chunkPos) +- ); +- serverPlayer.setChunkTrackingView(chunkTrackingView); ++ ChunkTrackingView.difference(chunktrackingview1, chunktrackingview, (chunkcoordintpair) -> { ++ this.markChunkPendingToSend(entityplayer, chunkcoordintpair); ++ }, (chunkcoordintpair) -> { ++ dropChunk(entityplayer, chunkcoordintpair); ++ }); ++ entityplayer.setChunkTrackingView(chunktrackingview); + } + } + + @Override + public List getPlayers(ChunkPos pos, boolean boundaryOnly) { +- Set allPlayers = this.playerMap.getAllPlayers(); ++ Set set = this.playerMap.getAllPlayers(); + Builder builder = ImmutableList.builder(); ++ Iterator iterator = set.iterator(); + +- for (ServerPlayer serverPlayer : allPlayers) { +- if (boundaryOnly && this.isChunkOnTrackedBorder(serverPlayer, pos.x, pos.z) || !boundaryOnly && this.isChunkTracked(serverPlayer, pos.x, pos.z)) { +- builder.add(serverPlayer); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ if (boundaryOnly && this.isChunkOnTrackedBorder(entityplayer, pos.x, pos.z) || !boundaryOnly && this.isChunkTracked(entityplayer, pos.x, pos.z)) { ++ builder.add(entityplayer); + } + } + +@@ -1147,111 +1297,158 @@ + + protected void addEntity(Entity entity) { + if (!(entity instanceof EnderDragonPart)) { +- EntityType type = entity.getType(); +- int i = type.clientTrackingRange() * 16; ++ EntityType entitytypes = entity.getType(); ++ int i = entitytypes.clientTrackingRange() * 16; ++ + if (i != 0) { +- int i1 = type.updateInterval(); ++ int j = entitytypes.updateInterval(); ++ + if (this.entityMap.containsKey(entity.getId())) { +- throw (IllegalStateException)Util.pauseInIde(new IllegalStateException("Entity is already tracked!")); ++ throw (IllegalStateException) Util.pauseInIde(new IllegalStateException("Entity is already tracked!")); + } else { +- ChunkMap.TrackedEntity trackedEntity = new ChunkMap.TrackedEntity(entity, i, i1, type.trackDeltas()); +- this.entityMap.put(entity.getId(), trackedEntity); +- trackedEntity.updatePlayers(this.level.players()); +- if (entity instanceof ServerPlayer serverPlayer) { +- this.updatePlayerStatus(serverPlayer, true); ++ ChunkMap.TrackedEntity playerchunkmap_entitytracker = new ChunkMap.TrackedEntity(entity, i, j, entitytypes.trackDeltas()); + +- for (ChunkMap.TrackedEntity trackedEntity1 : this.entityMap.values()) { +- if (trackedEntity1.entity != serverPlayer) { +- trackedEntity1.updatePlayer(serverPlayer); ++ this.entityMap.put(entity.getId(), playerchunkmap_entitytracker); ++ playerchunkmap_entitytracker.updatePlayers(this.level.players()); ++ if (entity instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entity; ++ ++ this.updatePlayerStatus(entityplayer, true); ++ ObjectIterator objectiterator = this.entityMap.values().iterator(); ++ ++ while (objectiterator.hasNext()) { ++ ChunkMap.TrackedEntity playerchunkmap_entitytracker1 = (ChunkMap.TrackedEntity) objectiterator.next(); ++ ++ if (playerchunkmap_entitytracker1.entity != entityplayer) { ++ playerchunkmap_entitytracker1.updatePlayer(entityplayer); + } + } + } ++ + } + } + } + } + + protected void removeEntity(Entity entity) { +- if (entity instanceof ServerPlayer serverPlayer) { +- this.updatePlayerStatus(serverPlayer, false); ++ if (entity instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entity; + +- for (ChunkMap.TrackedEntity trackedEntity : this.entityMap.values()) { +- trackedEntity.removePlayer(serverPlayer); ++ this.updatePlayerStatus(entityplayer, false); ++ ObjectIterator objectiterator = this.entityMap.values().iterator(); ++ ++ while (objectiterator.hasNext()) { ++ ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); ++ ++ playerchunkmap_entitytracker.removePlayer(entityplayer); + } + } + +- ChunkMap.TrackedEntity trackedEntity1 = this.entityMap.remove(entity.getId()); +- if (trackedEntity1 != null) { +- trackedEntity1.broadcastRemoved(); ++ ChunkMap.TrackedEntity playerchunkmap_entitytracker1 = (ChunkMap.TrackedEntity) this.entityMap.remove(entity.getId()); ++ ++ if (playerchunkmap_entitytracker1 != null) { ++ playerchunkmap_entitytracker1.broadcastRemoved(); + } ++ + } + + protected void tick() { +- for (ServerPlayer serverPlayer : this.playerMap.getAllPlayers()) { +- this.updateChunkTracking(serverPlayer); ++ Iterator iterator = this.playerMap.getAllPlayers().iterator(); ++ ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ this.updateChunkTracking(entityplayer); + } + + List list = Lists.newArrayList(); + List list1 = this.level.players(); ++ ObjectIterator objectiterator = this.entityMap.values().iterator(); + +- for (ChunkMap.TrackedEntity trackedEntity : this.entityMap.values()) { +- SectionPos sectionPos = trackedEntity.lastSectionPos; +- SectionPos sectionPos1 = SectionPos.of(trackedEntity.entity); +- boolean flag = !Objects.equals(sectionPos, sectionPos1); ++ ChunkMap.TrackedEntity playerchunkmap_entitytracker; ++ ++ while (objectiterator.hasNext()) { ++ playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); ++ SectionPos sectionposition = playerchunkmap_entitytracker.lastSectionPos; ++ SectionPos sectionposition1 = SectionPos.of((EntityAccess) playerchunkmap_entitytracker.entity); ++ boolean flag = !Objects.equals(sectionposition, sectionposition1); ++ + if (flag) { +- trackedEntity.updatePlayers(list1); +- Entity entity = trackedEntity.entity; ++ playerchunkmap_entitytracker.updatePlayers(list1); ++ Entity entity = playerchunkmap_entitytracker.entity; ++ + if (entity instanceof ServerPlayer) { +- list.add((ServerPlayer)entity); ++ list.add((ServerPlayer) entity); + } + +- trackedEntity.lastSectionPos = sectionPos1; ++ playerchunkmap_entitytracker.lastSectionPos = sectionposition1; + } + +- if (flag || this.distanceManager.inEntityTickingRange(sectionPos1.chunk().toLong())) { +- trackedEntity.serverEntity.sendChanges(); ++ if (flag || this.distanceManager.inEntityTickingRange(sectionposition1.chunk().toLong())) { ++ playerchunkmap_entitytracker.serverEntity.sendChanges(); + } + } + + if (!list.isEmpty()) { +- for (ChunkMap.TrackedEntity trackedEntity : this.entityMap.values()) { +- trackedEntity.updatePlayers(list); ++ objectiterator = this.entityMap.values().iterator(); ++ ++ while (objectiterator.hasNext()) { ++ playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); ++ playerchunkmap_entitytracker.updatePlayers(list); + } + } ++ + } + + public void broadcast(Entity entity, Packet packet) { +- ChunkMap.TrackedEntity trackedEntity = this.entityMap.get(entity.getId()); +- if (trackedEntity != null) { +- trackedEntity.broadcast(packet); ++ ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) this.entityMap.get(entity.getId()); ++ ++ if (playerchunkmap_entitytracker != null) { ++ playerchunkmap_entitytracker.broadcast(packet); + } ++ + } + + protected void broadcastAndSend(Entity entity, Packet packet) { +- ChunkMap.TrackedEntity trackedEntity = this.entityMap.get(entity.getId()); +- if (trackedEntity != null) { +- trackedEntity.broadcastAndSend(packet); ++ ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) this.entityMap.get(entity.getId()); ++ ++ if (playerchunkmap_entitytracker != null) { ++ playerchunkmap_entitytracker.broadcastAndSend(packet); + } ++ + } + + public void resendBiomesForChunks(List chunks) { +- Map> map = new HashMap<>(); ++ Map> map = new HashMap(); ++ Iterator iterator = chunks.iterator(); + +- for (ChunkAccess chunkAccess : chunks) { +- ChunkPos pos = chunkAccess.getPos(); +- LevelChunk levelChunk1; +- if (chunkAccess instanceof LevelChunk levelChunk) { +- levelChunk1 = levelChunk; ++ while (iterator.hasNext()) { ++ ChunkAccess ichunkaccess = (ChunkAccess) iterator.next(); ++ ChunkPos chunkcoordintpair = ichunkaccess.getPos(); ++ LevelChunk chunk; ++ ++ if (ichunkaccess instanceof LevelChunk) { ++ LevelChunk chunk1 = (LevelChunk) ichunkaccess; ++ ++ chunk = chunk1; + } else { +- levelChunk1 = this.level.getChunk(pos.x, pos.z); ++ chunk = this.level.getChunk(chunkcoordintpair.x, chunkcoordintpair.z); + } + +- for (ServerPlayer serverPlayer : this.getPlayers(pos, false)) { +- map.computeIfAbsent(serverPlayer, serverPlayer1 -> new ArrayList<>()).add(levelChunk1); ++ Iterator iterator1 = this.getPlayers(chunkcoordintpair, false).iterator(); ++ ++ while (iterator1.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator1.next(); ++ ++ ((List) map.computeIfAbsent(entityplayer, (entityplayer1) -> { ++ return new ArrayList(); ++ })).add(chunk); + } + } + +- map.forEach((serverPlayer1, list) -> serverPlayer1.connection.send(ClientboundChunksBiomesPacket.forChunks((List)list))); ++ map.forEach((entityplayer1, list1) -> { ++ entityplayer1.connection.send(ClientboundChunksBiomesPacket.forChunks(list1)); ++ }); + } + + protected PoiManager getPoiManager() { +@@ -1266,17 +1463,21 @@ + this.chunkStatusListener.onChunkStatusChange(chunkPos, fullChunkStatus); + } + +- public void waitForLightBeforeSending(ChunkPos chunkPos, int i) { +- int i1 = i + 1; +- ChunkPos.rangeClosed(chunkPos, i1).forEach(chunkPos1 -> { +- ChunkHolder visibleChunkIfPresent = this.getVisibleChunkIfPresent(chunkPos1.toLong()); +- if (visibleChunkIfPresent != null) { +- visibleChunkIfPresent.addSendDependency(this.lightEngine.waitForPendingTasks(chunkPos1.x, chunkPos1.z)); ++ public void waitForLightBeforeSending(ChunkPos chunkcoordintpair, int i) { ++ int j = i + 1; ++ ++ ChunkPos.rangeClosed(chunkcoordintpair, j).forEach((chunkcoordintpair1) -> { ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(chunkcoordintpair1.toLong()); ++ ++ if (playerchunk != null) { ++ playerchunk.addSendDependency(this.lightEngine.waitForPendingTasks(chunkcoordintpair1.x, chunkcoordintpair1.z)); + } ++ + }); + } + +- class DistanceManager extends net.minecraft.server.level.DistanceManager { ++ private class DistanceManager extends DistanceManager { ++ + protected DistanceManager(Executor dispatcher, Executor mainThreadExecutor) { + super(dispatcher, mainThreadExecutor); + } +@@ -1294,70 +1495,85 @@ + + @Nullable + @Override +- protected ChunkHolder updateChunkScheduling(long chunkPos, int newLevel, @Nullable ChunkHolder holder, int oldLevel) { +- return ChunkMap.this.updateChunkScheduling(chunkPos, newLevel, holder, oldLevel); ++ protected ChunkHolder updateChunkScheduling(long chunkPos, int j, @Nullable ChunkHolder newLevel, int holder) { ++ return ChunkMap.this.updateChunkScheduling(chunkPos, j, newLevel, holder); + } + } + +- class TrackedEntity { ++ public class TrackedEntity { ++ + final ServerEntity serverEntity; + final Entity entity; + private final int range; + SectionPos lastSectionPos; +- private final Set seenBy = Sets.newIdentityHashSet(); ++ public final Set seenBy = Sets.newIdentityHashSet(); + +- public TrackedEntity(Entity entity, int range, int updateInterval, boolean trackDelta) { +- this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast); ++ public TrackedEntity(Entity entity, int i, int j, boolean flag) { ++ this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, seenBy); // CraftBukkit + this.entity = entity; +- this.range = range; +- this.lastSectionPos = SectionPos.of(entity); ++ this.range = i; ++ this.lastSectionPos = SectionPos.of((EntityAccess) entity); + } + +- @Override +- public boolean equals(Object other) { +- return other instanceof ChunkMap.TrackedEntity && ((ChunkMap.TrackedEntity)other).entity.getId() == this.entity.getId(); ++ public boolean equals(Object object) { ++ return object instanceof ChunkMap.TrackedEntity ? ((ChunkMap.TrackedEntity) object).entity.getId() == this.entity.getId() : false; + } + +- @Override + public int hashCode() { + return this.entity.getId(); + } + + public void broadcast(Packet packet) { +- for (ServerPlayerConnection serverPlayerConnection : this.seenBy) { +- serverPlayerConnection.send(packet); ++ Iterator iterator = this.seenBy.iterator(); ++ ++ while (iterator.hasNext()) { ++ ServerPlayerConnection serverplayerconnection = (ServerPlayerConnection) iterator.next(); ++ ++ serverplayerconnection.send(packet); + } ++ + } + + public void broadcastAndSend(Packet packet) { + this.broadcast(packet); + if (this.entity instanceof ServerPlayer) { +- ((ServerPlayer)this.entity).connection.send(packet); ++ ((ServerPlayer) this.entity).connection.send(packet); + } ++ + } + + public void broadcastRemoved() { +- for (ServerPlayerConnection serverPlayerConnection : this.seenBy) { +- this.serverEntity.removePairing(serverPlayerConnection.getPlayer()); ++ Iterator iterator = this.seenBy.iterator(); ++ ++ while (iterator.hasNext()) { ++ ServerPlayerConnection serverplayerconnection = (ServerPlayerConnection) iterator.next(); ++ ++ this.serverEntity.removePairing(serverplayerconnection.getPlayer()); + } ++ + } + + public void removePlayer(ServerPlayer player) { + if (this.seenBy.remove(player.connection)) { + this.serverEntity.removePairing(player); + } ++ + } + + public void updatePlayer(ServerPlayer player) { + if (player != this.entity) { +- Vec3 vec3 = player.position().subtract(this.entity.position()); +- int playerViewDistance = ChunkMap.this.getPlayerViewDistance(player); +- double d = (double)Math.min(this.getEffectiveRange(), playerViewDistance * 16); +- double d1 = vec3.x * vec3.x + vec3.z * vec3.z; +- double d2 = d * d; +- boolean flag = d1 <= d2 +- && this.entity.broadcastToPlayer(player) +- && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z); ++ Vec3 vec3d = player.position().subtract(this.entity.position()); ++ int i = ChunkMap.this.getPlayerViewDistance(player); ++ double d0 = (double) Math.min(this.getEffectiveRange(), i * 16); ++ double d1 = vec3d.x * vec3d.x + vec3d.z * vec3d.z; ++ double d2 = d0 * d0; ++ boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(player) && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z); ++ ++ // CraftBukkit start - respect vanish API ++ if (!player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { ++ flag = false; ++ } ++ // CraftBukkit end + if (flag) { + if (this.seenBy.add(player.connection)) { + this.serverEntity.addPairing(player); +@@ -1365,6 +1581,7 @@ + } else if (this.seenBy.remove(player.connection)) { + this.serverEntity.removePairing(player); + } ++ + } + } + +@@ -1374,11 +1591,14 @@ + + private int getEffectiveRange() { + int i = this.range; ++ Iterator iterator = this.entity.getIndirectPassengers().iterator(); + +- for (Entity entity : this.entity.getIndirectPassengers()) { +- int i1 = entity.getType().clientTrackingRange() * 16; +- if (i1 > i) { +- i = i1; ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ int j = entity.getType().clientTrackingRange() * 16; ++ ++ if (j > i) { ++ i = j; + } + } + +@@ -1386,9 +1606,14 @@ + } + + public void updatePlayers(List playersList) { +- for (ServerPlayer serverPlayer : playersList) { +- this.updatePlayer(serverPlayer); ++ Iterator iterator = playersList.iterator(); ++ ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ this.updatePlayer(entityplayer); + } ++ + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/level/DistanceManager.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/level/DistanceManager.java.patch new file mode 100644 index 0000000000..c6fb0bc68a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/level/DistanceManager.java.patch @@ -0,0 +1,776 @@ +--- a/net/minecraft/server/level/DistanceManager.java ++++ b/net/minecraft/server/level/DistanceManager.java +@@ -12,11 +12,11 @@ + import it.unimi.dsi.fastutil.longs.Long2IntMaps; + import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; + import it.unimi.dsi.fastutil.longs.Long2ObjectMap; ++import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; + import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; + import it.unimi.dsi.fastutil.longs.LongIterator; + import it.unimi.dsi.fastutil.longs.LongOpenHashSet; + import it.unimi.dsi.fastutil.longs.LongSet; +-import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; + import it.unimi.dsi.fastutil.objects.ObjectIterator; + import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + import it.unimi.dsi.fastutil.objects.ObjectSet; +@@ -25,6 +25,7 @@ + import java.io.IOException; + import java.nio.charset.StandardCharsets; + import java.util.Iterator; ++import java.util.Objects; + import java.util.Set; + import java.util.concurrent.CompletableFuture; + import java.util.concurrent.Executor; +@@ -37,11 +38,12 @@ + import org.slf4j.Logger; + + public abstract class DistanceManager { ++ + static final Logger LOGGER = LogUtils.getLogger(); + static final int PLAYER_TICKET_LEVEL = ChunkLevel.byStatus(FullChunkStatus.ENTITY_TICKING); + private static final int INITIAL_TICKET_LIST_CAPACITY = 4; +- final Long2ObjectMap> playersPerChunk = new Long2ObjectOpenHashMap<>(); +- final Long2ObjectOpenHashMap>> tickets = new Long2ObjectOpenHashMap<>(); ++ final Long2ObjectMap> playersPerChunk = new Long2ObjectOpenHashMap(); ++ public final Long2ObjectOpenHashMap>> tickets = new Long2ObjectOpenHashMap(); + private final DistanceManager.ChunkTicketTracker ticketTracker = new DistanceManager.ChunkTicketTracker(); + private final DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter = new DistanceManager.FixedPlayerDistanceChunkTracker(8); + private final TickingTracker tickingTicketsTracker = new TickingTracker(); +@@ -56,25 +58,28 @@ + private int simulationDistance = 10; + + protected DistanceManager(Executor dispatcher, Executor mainThreadExecutor) { +- ProcessorHandle processorHandle = ProcessorHandle.of("player ticket throttler", mainThreadExecutor::execute); +- ChunkTaskPriorityQueueSorter chunkTaskPriorityQueueSorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(processorHandle), dispatcher, 4); +- this.ticketThrottler = chunkTaskPriorityQueueSorter; +- this.ticketThrottlerInput = chunkTaskPriorityQueueSorter.getProcessor(processorHandle, true); +- this.ticketThrottlerReleaser = chunkTaskPriorityQueueSorter.getReleaseProcessor(processorHandle); ++ Objects.requireNonNull(mainThreadExecutor); ++ ProcessorHandle mailbox = ProcessorHandle.of("player ticket throttler", mainThreadExecutor::execute); ++ ChunkTaskPriorityQueueSorter chunktaskqueuesorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(mailbox), dispatcher, 4); ++ ++ this.ticketThrottler = chunktaskqueuesorter; ++ this.ticketThrottlerInput = chunktaskqueuesorter.getProcessor(mailbox, true); ++ this.ticketThrottlerReleaser = chunktaskqueuesorter.getReleaseProcessor(mailbox); + this.mainThreadExecutor = mainThreadExecutor; + } + + protected void purgeStaleTickets() { +- this.ticketTickCounter++; +- ObjectIterator>>> objectIterator = this.tickets.long2ObjectEntrySet().fastIterator(); ++ ++this.ticketTickCounter; ++ ObjectIterator objectiterator = this.tickets.long2ObjectEntrySet().fastIterator(); + +- while (objectIterator.hasNext()) { +- Entry>> entry = objectIterator.next(); +- Iterator> iterator = entry.getValue().iterator(); ++ while (objectiterator.hasNext()) { ++ Entry>> entry = (Entry) objectiterator.next(); ++ Iterator> iterator = ((SortedArraySet) entry.getValue()).iterator(); + boolean flag = false; + + while (iterator.hasNext()) { +- Ticket ticket = iterator.next(); ++ Ticket ticket = (Ticket) iterator.next(); ++ + if (ticket.timedOut(this.ticketTickCounter)) { + iterator.remove(); + flag = true; +@@ -83,17 +88,18 @@ + } + + if (flag) { +- this.ticketTracker.update(entry.getLongKey(), getTicketLevelAt(entry.getValue()), false); ++ this.ticketTracker.update(entry.getLongKey(), getTicketLevelAt((SortedArraySet) entry.getValue()), false); + } + +- if (entry.getValue().isEmpty()) { +- objectIterator.remove(); ++ if (((SortedArraySet) entry.getValue()).isEmpty()) { ++ objectiterator.remove(); + } + } ++ + } + + private static int getTicketLevelAt(SortedArraySet> tickets) { +- return !tickets.isEmpty() ? tickets.first().getTicketLevel() : ChunkLevel.MAX_LEVEL + 1; ++ return !tickets.isEmpty() ? ((Ticket) tickets.first()).getTicketLevel() : ChunkLevel.MAX_LEVEL + 1; + } + + protected abstract boolean isChunkToRemove(long chunkPos); +@@ -102,7 +108,7 @@ + protected abstract ChunkHolder getChunk(long chunkPos); + + @Nullable +- protected abstract ChunkHolder updateChunkScheduling(long chunkPos, int i, @Nullable ChunkHolder newLevel, int holder); ++ protected abstract ChunkHolder updateChunkScheduling(long chunkPos, int j, @Nullable ChunkHolder newLevel, int holder); + + public boolean runAllUpdates(ChunkMap chunkManager) { + this.naturalSpawnChunkCounter.runAllUpdates(); +@@ -110,32 +116,56 @@ + this.playerTicketManager.runAllUpdates(); + int i = Integer.MAX_VALUE - this.ticketTracker.runDistanceUpdates(Integer.MAX_VALUE); + boolean flag = i != 0; ++ + if (flag) { ++ ; + } + + if (!this.chunksToUpdateFutures.isEmpty()) { +- this.chunksToUpdateFutures.forEach(chunkHolder -> chunkHolder.updateFutures(chunkManager, this.mainThreadExecutor)); +- this.chunksToUpdateFutures.clear(); ++ // CraftBukkit start ++ // Iterate pending chunk updates with protection against concurrent modification exceptions ++ java.util.Iterator iter = this.chunksToUpdateFutures.iterator(); ++ int expectedSize = this.chunksToUpdateFutures.size(); ++ do { ++ ChunkHolder playerchunk = iter.next(); ++ iter.remove(); ++ expectedSize--; ++ ++ playerchunk.updateFutures(chunkManager, this.mainThreadExecutor); ++ ++ // Reset iterator if set was modified using add() ++ if (this.chunksToUpdateFutures.size() != expectedSize) { ++ expectedSize = this.chunksToUpdateFutures.size(); ++ iter = this.chunksToUpdateFutures.iterator(); ++ } ++ } while (iter.hasNext()); ++ // CraftBukkit end ++ + return true; + } else { + if (!this.ticketsToRelease.isEmpty()) { +- LongIterator longIterator = this.ticketsToRelease.iterator(); ++ LongIterator longiterator = this.ticketsToRelease.iterator(); + +- while (longIterator.hasNext()) { +- long l = longIterator.nextLong(); +- if (this.getTickets(l).stream().anyMatch(ticket -> ticket.getType() == TicketType.PLAYER)) { +- ChunkHolder updatingChunkIfPresent = chunkManager.getUpdatingChunkIfPresent(l); +- if (updatingChunkIfPresent == null) { ++ while (longiterator.hasNext()) { ++ long j = longiterator.nextLong(); ++ ++ if (this.getTickets(j).stream().anyMatch((ticket) -> { ++ return ticket.getType() == TicketType.PLAYER; ++ })) { ++ ChunkHolder playerchunk = chunkManager.getUpdatingChunkIfPresent(j); ++ ++ if (playerchunk == null) { + throw new IllegalStateException(); + } + +- CompletableFuture> entityTickingChunkFuture = updatingChunkIfPresent.getEntityTickingChunkFuture( +- +- ); +- entityTickingChunkFuture.thenAccept( +- either -> this.mainThreadExecutor.execute(() -> this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { +- }, l, false))) +- ); ++ CompletableFuture> completablefuture = playerchunk.getEntityTickingChunkFuture(); ++ ++ completablefuture.thenAccept((either) -> { ++ this.mainThreadExecutor.execute(() -> { ++ this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { ++ }, j, false)); ++ }); ++ }); + } + } + +@@ -146,26 +176,33 @@ + } + } + +- void addTicket(long chunkPos, Ticket ticket) { +- SortedArraySet> tickets = this.getTickets(chunkPos); +- int ticketLevelAt = getTicketLevelAt(tickets); +- Ticket ticket1 = tickets.addOrGet(ticket); ++ boolean addTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean ++ SortedArraySet> arraysetsorted = this.getTickets(i); ++ int j = getTicketLevelAt(arraysetsorted); ++ Ticket ticket1 = (Ticket) arraysetsorted.addOrGet(ticket); ++ + ticket1.setCreatedTick(this.ticketTickCounter); +- if (ticket.getTicketLevel() < ticketLevelAt) { +- this.ticketTracker.update(chunkPos, ticket.getTicketLevel(), true); ++ if (ticket.getTicketLevel() < j) { ++ this.ticketTracker.update(i, ticket.getTicketLevel(), true); + } ++ ++ return ticket == ticket1; // CraftBukkit + } + +- void removeTicket(long chunkPos, Ticket ticket) { +- SortedArraySet> tickets = this.getTickets(chunkPos); +- if (tickets.remove(ticket)) { ++ boolean removeTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean ++ SortedArraySet> arraysetsorted = this.getTickets(i); ++ ++ boolean removed = false; // CraftBukkit ++ if (arraysetsorted.remove(ticket)) { ++ removed = true; // CraftBukkit + } + +- if (tickets.isEmpty()) { +- this.tickets.remove(chunkPos); ++ if (arraysetsorted.isEmpty()) { ++ this.tickets.remove(i); + } + +- this.ticketTracker.update(chunkPos, getTicketLevelAt(tickets), false); ++ this.ticketTracker.update(i, getTicketLevelAt(arraysetsorted), false); ++ return removed; // CraftBukkit + } + + public void addTicket(TicketType type, ChunkPos pos, int level, T value) { +@@ -174,59 +211,86 @@ + + public void removeTicket(TicketType type, ChunkPos pos, int level, T value) { + Ticket ticket = new Ticket<>(type, level, value); ++ + this.removeTicket(pos.toLong(), ticket); + } + + public void addRegionTicket(TicketType type, ChunkPos pos, int distance, T value) { +- Ticket ticket = new Ticket<>(type, ChunkLevel.byStatus(FullChunkStatus.FULL) - distance, value); +- long l = pos.toLong(); +- this.addTicket(l, ticket); +- this.tickingTicketsTracker.addTicket(l, ticket); ++ // CraftBukkit start ++ addRegionTicketAtDistance(type, pos, distance, value); + } + ++ public boolean addRegionTicketAtDistance(TicketType tickettype, ChunkPos chunkcoordintpair, int i, T t0) { ++ // CraftBukkit end ++ Ticket ticket = new Ticket<>(tickettype, ChunkLevel.byStatus(FullChunkStatus.FULL) - i, t0); ++ long j = chunkcoordintpair.toLong(); ++ ++ boolean added = this.addTicket(j, ticket); // CraftBukkit ++ this.tickingTicketsTracker.addTicket(j, ticket); ++ return added; // CraftBukkit ++ } ++ + public void removeRegionTicket(TicketType type, ChunkPos pos, int distance, T value) { +- Ticket ticket = new Ticket<>(type, ChunkLevel.byStatus(FullChunkStatus.FULL) - distance, value); +- long l = pos.toLong(); +- this.removeTicket(l, ticket); +- this.tickingTicketsTracker.removeTicket(l, ticket); ++ // CraftBukkit start ++ removeRegionTicketAtDistance(type, pos, distance, value); + } + ++ public boolean removeRegionTicketAtDistance(TicketType tickettype, ChunkPos chunkcoordintpair, int i, T t0) { ++ // CraftBukkit end ++ Ticket ticket = new Ticket<>(tickettype, ChunkLevel.byStatus(FullChunkStatus.FULL) - i, t0); ++ long j = chunkcoordintpair.toLong(); ++ ++ boolean removed = this.removeTicket(j, ticket); // CraftBukkit ++ this.tickingTicketsTracker.removeTicket(j, ticket); ++ return removed; // CraftBukkit ++ } ++ + private SortedArraySet> getTickets(long chunkPos) { +- return this.tickets.computeIfAbsent(chunkPos, l -> SortedArraySet.create(4)); ++ return (SortedArraySet) this.tickets.computeIfAbsent(chunkPos, (j) -> { ++ return SortedArraySet.create(4); ++ }); + } + + protected void updateChunkForced(ChunkPos pos, boolean add) { + Ticket ticket = new Ticket<>(TicketType.FORCED, ChunkMap.FORCED_TICKET_LEVEL, pos); +- long l = pos.toLong(); ++ long i = pos.toLong(); ++ + if (add) { +- this.addTicket(l, ticket); +- this.tickingTicketsTracker.addTicket(l, ticket); ++ this.addTicket(i, ticket); ++ this.tickingTicketsTracker.addTicket(i, ticket); + } else { +- this.removeTicket(l, ticket); +- this.tickingTicketsTracker.removeTicket(l, ticket); ++ this.removeTicket(i, ticket); ++ this.tickingTicketsTracker.removeTicket(i, ticket); + } ++ + } + + public void addPlayer(SectionPos sectionPos, ServerPlayer player) { +- ChunkPos chunkPos = sectionPos.chunk(); +- long l = chunkPos.toLong(); +- this.playersPerChunk.computeIfAbsent(l, l1 -> new ObjectOpenHashSet<>()).add(player); +- this.naturalSpawnChunkCounter.update(l, 0, true); +- this.playerTicketManager.update(l, 0, true); +- this.tickingTicketsTracker.addTicket(TicketType.PLAYER, chunkPos, this.getPlayerTicketLevel(), chunkPos); ++ ChunkPos chunkcoordintpair = sectionPos.chunk(); ++ long i = chunkcoordintpair.toLong(); ++ ++ ((ObjectSet) this.playersPerChunk.computeIfAbsent(i, (j) -> { ++ return new ObjectOpenHashSet(); ++ })).add(player); ++ this.naturalSpawnChunkCounter.update(i, 0, true); ++ this.playerTicketManager.update(i, 0, true); ++ this.tickingTicketsTracker.addTicket(TicketType.PLAYER, chunkcoordintpair, this.getPlayerTicketLevel(), chunkcoordintpair); + } + + public void removePlayer(SectionPos sectionPos, ServerPlayer player) { +- ChunkPos chunkPos = sectionPos.chunk(); +- long l = chunkPos.toLong(); +- ObjectSet set = this.playersPerChunk.get(l); +- set.remove(player); +- if (set.isEmpty()) { +- this.playersPerChunk.remove(l); +- this.naturalSpawnChunkCounter.update(l, Integer.MAX_VALUE, false); +- this.playerTicketManager.update(l, Integer.MAX_VALUE, false); +- this.tickingTicketsTracker.removeTicket(TicketType.PLAYER, chunkPos, this.getPlayerTicketLevel(), chunkPos); ++ ChunkPos chunkcoordintpair = sectionPos.chunk(); ++ long i = chunkcoordintpair.toLong(); ++ ObjectSet objectset = (ObjectSet) this.playersPerChunk.get(i); ++ if (objectset == null) return; // CraftBukkit - SPIGOT-6208 ++ ++ objectset.remove(player); ++ if (objectset.isEmpty()) { ++ this.playersPerChunk.remove(i); ++ this.naturalSpawnChunkCounter.update(i, Integer.MAX_VALUE, false); ++ this.playerTicketManager.update(i, Integer.MAX_VALUE, false); ++ this.tickingTicketsTracker.removeTicket(TicketType.PLAYER, chunkcoordintpair, this.getPlayerTicketLevel(), chunkcoordintpair); + } ++ + } + + private int getPlayerTicketLevel() { +@@ -242,8 +306,9 @@ + } + + protected String getTicketDebugString(long chunkPos) { +- SortedArraySet> set = this.tickets.get(chunkPos); +- return set != null && !set.isEmpty() ? set.first().toString() : "no_ticket"; ++ SortedArraySet> arraysetsorted = (SortedArraySet) this.tickets.get(chunkPos); ++ ++ return arraysetsorted != null && !arraysetsorted.isEmpty() ? ((Ticket) arraysetsorted.first()).toString() : "no_ticket"; + } + + protected void updatePlayerTickets(int viewDistance) { +@@ -255,6 +320,7 @@ + this.simulationDistance = simulationDistance; + this.tickingTicketsTracker.replacePlayerTicketsLevel(this.getPlayerTicketLevel()); + } ++ + } + + public int getNaturalSpawnChunkCount() { +@@ -272,19 +338,38 @@ + } + + private void dumpTickets(String filename) { +- try (FileOutputStream fileOutputStream = new FileOutputStream(new File(filename))) { +- for (Entry>> entry : this.tickets.long2ObjectEntrySet()) { +- ChunkPos chunkPos = new ChunkPos(entry.getLongKey()); ++ try { ++ FileOutputStream fileoutputstream = new FileOutputStream(new File(filename)); + +- for (Ticket ticket : entry.getValue()) { +- fileOutputStream.write( +- (chunkPos.x + "\t" + chunkPos.z + "\t" + ticket.getType() + "\t" + ticket.getTicketLevel() + "\t\n").getBytes(StandardCharsets.UTF_8) +- ); ++ try { ++ ObjectIterator objectiterator = this.tickets.long2ObjectEntrySet().iterator(); ++ ++ while (objectiterator.hasNext()) { ++ Entry>> entry = (Entry) objectiterator.next(); ++ ChunkPos chunkcoordintpair = new ChunkPos(entry.getLongKey()); ++ Iterator iterator = ((SortedArraySet) entry.getValue()).iterator(); ++ ++ while (iterator.hasNext()) { ++ Ticket ticket = (Ticket) iterator.next(); ++ ++ fileoutputstream.write((chunkcoordintpair.x + "\t" + chunkcoordintpair.z + "\t" + ticket.getType() + "\t" + ticket.getTicketLevel() + "\t\n").getBytes(StandardCharsets.UTF_8)); ++ } + } ++ } catch (Throwable throwable) { ++ try { ++ fileoutputstream.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ ++ throw throwable; + } +- } catch (IOException var10) { +- LOGGER.error("Failed to dump tickets to {}", filename, var10); ++ ++ fileoutputstream.close(); ++ } catch (IOException ioexception) { ++ DistanceManager.LOGGER.error("Failed to dump tickets to {}", filename, ioexception); + } ++ + } + + @VisibleForTesting +@@ -293,17 +378,18 @@ + } + + public void removeTicketsOnClosing() { +- ImmutableSet> set = ImmutableSet.of(TicketType.UNKNOWN, TicketType.POST_TELEPORT, TicketType.LIGHT); +- ObjectIterator>>> objectIterator = this.tickets.long2ObjectEntrySet().fastIterator(); ++ ImmutableSet> immutableset = ImmutableSet.of(TicketType.UNKNOWN, TicketType.POST_TELEPORT, TicketType.LIGHT); ++ ObjectIterator objectiterator = this.tickets.long2ObjectEntrySet().fastIterator(); + +- while (objectIterator.hasNext()) { +- Entry>> entry = objectIterator.next(); +- Iterator> iterator = entry.getValue().iterator(); ++ while (objectiterator.hasNext()) { ++ Entry>> entry = (Entry) objectiterator.next(); ++ Iterator> iterator = ((SortedArraySet) entry.getValue()).iterator(); + boolean flag = false; + + while (iterator.hasNext()) { +- Ticket ticket = iterator.next(); +- if (!set.contains(ticket.getType())) { ++ Ticket ticket = (Ticket) iterator.next(); ++ ++ if (!immutableset.contains(ticket.getType())) { + iterator.remove(); + flag = true; + this.tickingTicketsTracker.removeTicket(entry.getLongKey(), ticket); +@@ -311,57 +397,79 @@ + } + + if (flag) { +- this.ticketTracker.update(entry.getLongKey(), getTicketLevelAt(entry.getValue()), false); ++ this.ticketTracker.update(entry.getLongKey(), getTicketLevelAt((SortedArraySet) entry.getValue()), false); + } + +- if (entry.getValue().isEmpty()) { +- objectIterator.remove(); ++ if (((SortedArraySet) entry.getValue()).isEmpty()) { ++ objectiterator.remove(); + } + } ++ + } + + public boolean hasTickets() { + return !this.tickets.isEmpty(); + } + +- class ChunkTicketTracker extends ChunkTracker { ++ // CraftBukkit start ++ public void removeAllTicketsFor(TicketType ticketType, int ticketLevel, T ticketIdentifier) { ++ Ticket target = new Ticket<>(ticketType, ticketLevel, ticketIdentifier); ++ ++ for (java.util.Iterator>>> iterator = this.tickets.long2ObjectEntrySet().fastIterator(); iterator.hasNext();) { ++ Entry>> entry = iterator.next(); ++ SortedArraySet> tickets = entry.getValue(); ++ if (tickets.remove(target)) { ++ // copied from removeTicket ++ this.ticketTracker.update(entry.getLongKey(), getTicketLevelAt(tickets), false); ++ ++ // can't use entry after it's removed ++ if (tickets.isEmpty()) { ++ iterator.remove(); ++ } ++ } ++ } ++ } ++ // CraftBukkit end ++ ++ private class ChunkTicketTracker extends ChunkTracker { ++ + private static final int MAX_LEVEL = ChunkLevel.MAX_LEVEL + 1; + + public ChunkTicketTracker() { +- super(MAX_LEVEL + 1, 16, 256); ++ super(DistanceManager.ChunkTicketTracker.MAX_LEVEL + 1, 16, 256); + } + + @Override + protected int getLevelFromSource(long pos) { +- SortedArraySet> set = DistanceManager.this.tickets.get(pos); +- if (set == null) { +- return Integer.MAX_VALUE; +- } else { +- return set.isEmpty() ? Integer.MAX_VALUE : set.first().getTicketLevel(); +- } ++ SortedArraySet> arraysetsorted = (SortedArraySet) DistanceManager.this.tickets.get(pos); ++ ++ return arraysetsorted == null ? Integer.MAX_VALUE : (arraysetsorted.isEmpty() ? Integer.MAX_VALUE : ((Ticket) arraysetsorted.first()).getTicketLevel()); + } + + @Override + protected int getLevel(long sectionPos) { + if (!DistanceManager.this.isChunkToRemove(sectionPos)) { +- ChunkHolder chunk = DistanceManager.this.getChunk(sectionPos); +- if (chunk != null) { +- return chunk.getTicketLevel(); ++ ChunkHolder playerchunk = DistanceManager.this.getChunk(sectionPos); ++ ++ if (playerchunk != null) { ++ return playerchunk.getTicketLevel(); + } + } + +- return MAX_LEVEL; ++ return DistanceManager.ChunkTicketTracker.MAX_LEVEL; + } + + @Override +- protected void setLevel(long sectionPos, int level) { +- ChunkHolder chunk = DistanceManager.this.getChunk(sectionPos); +- int i = chunk == null ? MAX_LEVEL : chunk.getTicketLevel(); +- if (i != level) { +- ChunkHolder var6 = DistanceManager.this.updateChunkScheduling(sectionPos, level, chunk, i); +- if (var6 != null) { +- DistanceManager.this.chunksToUpdateFutures.add(var6); ++ protected void setLevel(long sectionPos, int j) { ++ ChunkHolder playerchunk = DistanceManager.this.getChunk(sectionPos); ++ int k = playerchunk == null ? DistanceManager.ChunkTicketTracker.MAX_LEVEL : playerchunk.getTicketLevel(); ++ ++ if (k != j) { ++ playerchunk = DistanceManager.this.updateChunkScheduling(sectionPos, j, playerchunk, k); ++ if (playerchunk != null) { ++ DistanceManager.this.chunksToUpdateFutures.add(playerchunk); + } ++ + } + } + +@@ -370,14 +478,15 @@ + } + } + +- class FixedPlayerDistanceChunkTracker extends ChunkTracker { ++ private class FixedPlayerDistanceChunkTracker extends ChunkTracker { ++ + protected final Long2ByteMap chunks = new Long2ByteOpenHashMap(); + protected final int maxDistance; + +- protected FixedPlayerDistanceChunkTracker(int maxDistance) { +- super(maxDistance + 2, 16, 256); +- this.maxDistance = maxDistance; +- this.chunks.defaultReturnValue((byte)(maxDistance + 2)); ++ protected FixedPlayerDistanceChunkTracker(int i) { ++ super(i + 2, 16, 256); ++ this.maxDistance = i; ++ this.chunks.defaultReturnValue((byte) (i + 2)); + } + + @Override +@@ -386,19 +495,19 @@ + } + + @Override +- protected void setLevel(long sectionPos, int level) { +- byte b; +- if (level > this.maxDistance) { +- b = this.chunks.remove(sectionPos); ++ protected void setLevel(long sectionPos, int j) { ++ byte b0; ++ ++ if (j > this.maxDistance) { ++ b0 = this.chunks.remove(sectionPos); + } else { +- b = this.chunks.put(sectionPos, (byte)level); ++ b0 = this.chunks.put(sectionPos, (byte) j); + } + +- this.onLevelChange(sectionPos, b, level); ++ this.onLevelChange(sectionPos, b0, j); + } + +- protected void onLevelChange(long chunkPos, int oldLevel, int newLevel) { +- } ++ protected void onLevelChange(long chunkPos, int j, int oldLevel) {} + + @Override + protected int getLevelFromSource(long pos) { +@@ -406,8 +515,9 @@ + } + + private boolean havePlayer(long chunkPos) { +- ObjectSet set = DistanceManager.this.playersPerChunk.get(chunkPos); +- return set != null && !set.isEmpty(); ++ ObjectSet objectset = (ObjectSet) DistanceManager.this.playersPerChunk.get(chunkPos); ++ ++ return objectset != null && !objectset.isEmpty(); + } + + public void runAllUpdates() { +@@ -415,95 +525,126 @@ + } + + private void dumpChunks(String filename) { +- try (FileOutputStream fileOutputStream = new FileOutputStream(new File(filename))) { +- for (it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry entry : this.chunks.long2ByteEntrySet()) { +- ChunkPos chunkPos = new ChunkPos(entry.getLongKey()); +- String string = Byte.toString(entry.getByteValue()); +- fileOutputStream.write((chunkPos.x + "\t" + chunkPos.z + "\t" + string + "\n").getBytes(StandardCharsets.UTF_8)); ++ try { ++ FileOutputStream fileoutputstream = new FileOutputStream(new File(filename)); ++ ++ try { ++ ObjectIterator objectiterator = this.chunks.long2ByteEntrySet().iterator(); ++ ++ while (objectiterator.hasNext()) { ++ it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry) objectiterator.next(); ++ ChunkPos chunkcoordintpair = new ChunkPos(it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey()); ++ String s1 = Byte.toString(it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue()); ++ ++ fileoutputstream.write((chunkcoordintpair.x + "\t" + chunkcoordintpair.z + "\t" + s1 + "\n").getBytes(StandardCharsets.UTF_8)); ++ } ++ } catch (Throwable throwable) { ++ try { ++ fileoutputstream.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ ++ throw throwable; + } +- } catch (IOException var9) { +- DistanceManager.LOGGER.error("Failed to dump chunks to {}", filename, var9); ++ ++ fileoutputstream.close(); ++ } catch (IOException ioexception) { ++ DistanceManager.LOGGER.error("Failed to dump chunks to {}", filename, ioexception); + } ++ + } + } + +- class PlayerTicketTracker extends DistanceManager.FixedPlayerDistanceChunkTracker { +- private int viewDistance; ++ private class PlayerTicketTracker extends DistanceManager.FixedPlayerDistanceChunkTracker { ++ ++ private int viewDistance = 0; + private final Long2IntMap queueLevels = Long2IntMaps.synchronize(new Long2IntOpenHashMap()); + private final LongSet toUpdate = new LongOpenHashSet(); + +- protected PlayerTicketTracker(int maxDistance) { +- super(maxDistance); +- this.viewDistance = 0; +- this.queueLevels.defaultReturnValue(maxDistance + 2); ++ protected PlayerTicketTracker(int i) { ++ super(i); ++ this.queueLevels.defaultReturnValue(i + 2); + } + + @Override +- protected void onLevelChange(long chunkPos, int oldLevel, int newLevel) { ++ protected void onLevelChange(long chunkPos, int j, int oldLevel) { + this.toUpdate.add(chunkPos); + } + + public void updateViewDistance(int viewDistance) { +- for (it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry entry : this.chunks.long2ByteEntrySet()) { +- byte byteValue = entry.getByteValue(); +- long longKey = entry.getLongKey(); +- this.onLevelChange(longKey, byteValue, this.haveTicketFor(byteValue), byteValue <= viewDistance); ++ ObjectIterator objectiterator = this.chunks.long2ByteEntrySet().iterator(); ++ ++ while (objectiterator.hasNext()) { ++ it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry) objectiterator.next(); ++ byte b0 = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue(); ++ long j = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey(); ++ ++ this.onLevelChange(j, b0, this.haveTicketFor(b0), b0 <= viewDistance); + } + + this.viewDistance = viewDistance; + } + +- private void onLevelChange(long chunkPos, int i, boolean flag, boolean flag1) { ++ private void onLevelChange(long chunkPos, int j, boolean flag, boolean flag1) { + if (flag != flag1) { + Ticket ticket = new Ticket<>(TicketType.PLAYER, DistanceManager.PLAYER_TICKET_LEVEL, new ChunkPos(chunkPos)); ++ + if (flag1) { +- DistanceManager.this.ticketThrottlerInput +- .tell(ChunkTaskPriorityQueueSorter.message(() -> DistanceManager.this.mainThreadExecutor.execute(() -> { +- if (this.haveTicketFor(this.getLevel(chunkPos))) { +- DistanceManager.this.addTicket(chunkPos, ticket); +- DistanceManager.this.ticketsToRelease.add(chunkPos); +- } else { +- DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { +- }, chunkPos, false)); +- } +- }), chunkPos, () -> i)); ++ DistanceManager.this.ticketThrottlerInput.tell(ChunkTaskPriorityQueueSorter.message(() -> { ++ DistanceManager.this.mainThreadExecutor.execute(() -> { ++ if (this.haveTicketFor(this.getLevel(chunkPos))) { ++ DistanceManager.this.addTicket(chunkPos, ticket); ++ DistanceManager.this.ticketsToRelease.add(chunkPos); ++ } else { ++ DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { ++ }, chunkPos, false)); ++ } ++ ++ }); ++ }, chunkPos, () -> { ++ return j; ++ })); + } else { +- DistanceManager.this.ticketThrottlerReleaser +- .tell( +- ChunkTaskPriorityQueueSorter.release( +- () -> DistanceManager.this.mainThreadExecutor.execute(() -> DistanceManager.this.removeTicket(chunkPos, ticket)), +- chunkPos, +- true +- ) +- ); ++ DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { ++ DistanceManager.this.mainThreadExecutor.execute(() -> { ++ DistanceManager.this.removeTicket(chunkPos, ticket); ++ }); ++ }, chunkPos, true)); + } + } ++ + } + + @Override + public void runAllUpdates() { + super.runAllUpdates(); + if (!this.toUpdate.isEmpty()) { +- LongIterator longIterator = this.toUpdate.iterator(); ++ LongIterator longiterator = this.toUpdate.iterator(); + +- while (longIterator.hasNext()) { +- long l = longIterator.nextLong(); +- int i = this.queueLevels.get(l); +- int level = this.getLevel(l); +- if (i != level) { +- DistanceManager.this.ticketThrottler.onLevelChange(new ChunkPos(l), () -> this.queueLevels.get(l), level, i1 -> { +- if (i1 >= this.queueLevels.defaultReturnValue()) { +- this.queueLevels.remove(l); ++ while (longiterator.hasNext()) { ++ long i = longiterator.nextLong(); ++ int j = this.queueLevels.get(i); ++ int k = this.getLevel(i); ++ ++ if (j != k) { ++ DistanceManager.this.ticketThrottler.onLevelChange(new ChunkPos(i), () -> { ++ return this.queueLevels.get(i); ++ }, k, (l) -> { ++ if (l >= this.queueLevels.defaultReturnValue()) { ++ this.queueLevels.remove(i); + } else { +- this.queueLevels.put(l, i1); ++ this.queueLevels.put(i, l); + } ++ + }); +- this.onLevelChange(l, level, this.haveTicketFor(i), this.haveTicketFor(level)); ++ this.onLevelChange(i, k, this.haveTicketFor(j), this.haveTicketFor(k)); + } + } + + this.toUpdate.clear(); + } ++ + } + + private boolean haveTicketFor(int level) { diff --git a/patch-remap/mache-vineflower/net/minecraft/server/level/ServerChunkCache.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/level/ServerChunkCache.java.patch new file mode 100644 index 0000000000..1f70a0e9ed --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/level/ServerChunkCache.java.patch @@ -0,0 +1,644 @@ +--- a/net/minecraft/server/level/ServerChunkCache.java ++++ b/net/minecraft/server/level/ServerChunkCache.java +@@ -7,10 +7,11 @@ + import java.io.File; + import java.io.IOException; + import java.util.Arrays; ++import java.util.Iterator; + import java.util.List; ++import java.util.Objects; + import java.util.Optional; + import java.util.concurrent.CompletableFuture; +-import java.util.concurrent.CompletionStage; + import java.util.concurrent.Executor; + import java.util.function.BooleanSupplier; + import java.util.function.Consumer; +@@ -27,9 +28,9 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.ai.village.poi.PoiManager; + import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.EnumSkyBlock; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.LocalMobCapCalculator; + import net.minecraft.world.level.NaturalSpawner; + import net.minecraft.world.level.chunk.ChunkAccess; +@@ -47,6 +48,7 @@ + import net.minecraft.world.level.storage.LevelStorageSource; + + public class ServerChunkCache extends ChunkSource { ++ + private static final List CHUNK_STATUSES = ChunkStatus.getStatusList(); + private final DistanceManager distanceManager; + final ServerLevel level; +@@ -56,8 +58,8 @@ + public final ChunkMap chunkMap; + private final DimensionDataStorage dataStorage; + private long lastInhabitedUpdate; +- private boolean spawnEnemies = true; +- private boolean spawnFriendlies = true; ++ public boolean spawnEnemies = true; ++ public boolean spawnFriendlies = true; + private static final int CACHE_SIZE = 4; + private final long[] lastChunkPos = new long[4]; + private final ChunkStatus[] lastChunkStatus = new ChunkStatus[4]; +@@ -66,47 +68,31 @@ + @VisibleForDebug + private NaturalSpawner.SpawnState lastSpawnState; + +- public ServerChunkCache( +- ServerLevel level, +- LevelStorageSource.LevelStorageAccess levelStorageAccess, +- DataFixer fixerUpper, +- StructureTemplateManager structureManager, +- Executor dispatcher, +- ChunkGenerator generator, +- int viewDistance, +- int simulationDistance, +- boolean sync, +- ChunkProgressListener progressListener, +- ChunkStatusUpdateListener chunkStatusListener, +- Supplier overworldDataStorage +- ) { ++ public ServerChunkCache(ServerLevel level, LevelStorageSource.LevelStorageAccess levelStorageAccess, DataFixer fixerUpper, StructureTemplateManager structureManager, Executor dispatcher, ChunkGenerator generator, int viewDistance, int simulationDistance, boolean sync, ChunkProgressListener progressListener, ChunkStatusUpdateListener chunkStatusListener, Supplier overworldDataStorage) { + this.level = level; + this.mainThreadProcessor = new ServerChunkCache.MainThreadExecutor(level); + this.mainThread = Thread.currentThread(); + File file = levelStorageAccess.getDimensionPath(level.dimension()).resolve("data").toFile(); ++ + file.mkdirs(); + this.dataStorage = new DimensionDataStorage(file, fixerUpper); +- this.chunkMap = new ChunkMap( +- level, +- levelStorageAccess, +- fixerUpper, +- structureManager, +- dispatcher, +- this.mainThreadProcessor, +- this, +- generator, +- progressListener, +- chunkStatusListener, +- overworldDataStorage, +- viewDistance, +- sync +- ); ++ this.chunkMap = new ChunkMap(level, levelStorageAccess, fixerUpper, structureManager, dispatcher, this.mainThreadProcessor, this, generator, progressListener, chunkStatusListener, overworldDataStorage, viewDistance, sync); + this.lightEngine = this.chunkMap.getLightEngine(); + this.distanceManager = this.chunkMap.getDistanceManager(); + this.distanceManager.updateSimulationDistance(simulationDistance); + this.clearCache(); + } + ++ // CraftBukkit start - properly implement isChunkLoaded ++ public boolean isChunkLoaded(int chunkX, int chunkZ) { ++ ChunkHolder chunk = this.chunkMap.getUpdatingChunkIfPresent(ChunkPos.asLong(chunkX, chunkZ)); ++ if (chunk == null) { ++ return false; ++ } ++ return chunk.getFullChunkNow() != null; ++ } ++ // CraftBukkit end ++ + @Override + public ThreadedLevelLightEngine getLightEngine() { + return this.lightEngine; +@@ -121,51 +107,59 @@ + return this.chunkMap.getTickingGenerated(); + } + +- private void storeInCache(long chunkPos, ChunkAccess chunk, ChunkStatus chunkStatus) { +- for (int i = 3; i > 0; i--) { +- this.lastChunkPos[i] = this.lastChunkPos[i - 1]; +- this.lastChunkStatus[i] = this.lastChunkStatus[i - 1]; +- this.lastChunk[i] = this.lastChunk[i - 1]; ++ private void storeInCache(long chunkPos, ChunkAccess ichunkaccess, ChunkStatus chunk) { ++ for (int j = 3; j > 0; --j) { ++ this.lastChunkPos[j] = this.lastChunkPos[j - 1]; ++ this.lastChunkStatus[j] = this.lastChunkStatus[j - 1]; ++ this.lastChunk[j] = this.lastChunk[j - 1]; + } + + this.lastChunkPos[0] = chunkPos; +- this.lastChunkStatus[0] = chunkStatus; +- this.lastChunk[0] = chunk; ++ this.lastChunkStatus[0] = chunk; ++ this.lastChunk[0] = ichunkaccess; + } + + @Nullable + @Override + public ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus requiredStatus, boolean load) { + if (Thread.currentThread() != this.mainThread) { +- return CompletableFuture.supplyAsync(() -> this.getChunk(chunkX, chunkZ, requiredStatus, load), this.mainThreadProcessor).join(); ++ return (ChunkAccess) CompletableFuture.supplyAsync(() -> { ++ return this.getChunk(chunkX, chunkZ, requiredStatus, load); ++ }, this.mainThreadProcessor).join(); + } else { +- ProfilerFiller profiler = this.level.getProfiler(); +- profiler.incrementCounter("getChunk"); +- long _long = ChunkPos.asLong(chunkX, chunkZ); ++ ProfilerFiller gameprofilerfiller = this.level.getProfiler(); + +- for (int i = 0; i < 4; i++) { +- if (_long == this.lastChunkPos[i] && requiredStatus == this.lastChunkStatus[i]) { +- ChunkAccess chunkAccess = this.lastChunk[i]; +- if (chunkAccess != null || !load) { +- return chunkAccess; ++ gameprofilerfiller.incrementCounter("getChunk"); ++ long k = ChunkPos.asLong(chunkX, chunkZ); ++ ++ ChunkAccess ichunkaccess; ++ ++ for (int l = 0; l < 4; ++l) { ++ if (k == this.lastChunkPos[l] && requiredStatus == this.lastChunkStatus[l]) { ++ ichunkaccess = this.lastChunk[l]; ++ if (ichunkaccess != null) { // CraftBukkit - the chunk can become accessible in the meantime TODO for non-null chunks it might also make sense to check that the chunk's state hasn't changed in the meantime ++ return ichunkaccess; + } + } + } + +- profiler.incrementCounter("getChunkCacheMiss"); +- CompletableFuture> chunkFutureMainThread = this.getChunkFutureMainThread( +- chunkX, chunkZ, requiredStatus, load +- ); +- this.mainThreadProcessor.managedBlock(chunkFutureMainThread::isDone); +- ChunkAccess chunkAccess = chunkFutureMainThread.join().map(chunkAccess1 -> (ChunkAccess)chunkAccess1, chunkLoadingFailure -> { ++ gameprofilerfiller.incrementCounter("getChunkCacheMiss"); ++ CompletableFuture> completablefuture = this.getChunkFutureMainThread(chunkX, chunkZ, requiredStatus, load); ++ ServerChunkCache.MainThreadExecutor chunkproviderserver_b = this.mainThreadProcessor; ++ ++ Objects.requireNonNull(completablefuture); ++ chunkproviderserver_b.managedBlock(completablefuture::isDone); ++ ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { ++ return ichunkaccess1; ++ }, (playerchunk_failure) -> { + if (load) { +- throw (IllegalStateException)Util.pauseInIde(new IllegalStateException("Chunk not there when requested: " + chunkLoadingFailure)); ++ throw (IllegalStateException) Util.pauseInIde(new IllegalStateException("Chunk not there when requested: " + playerchunk_failure)); + } else { + return null; + } + }); +- this.storeInCache(_long, chunkAccess, requiredStatus); +- return chunkAccess; ++ this.storeInCache(k, ichunkaccess, requiredStatus); ++ return ichunkaccess; + } + } + +@@ -176,28 +170,32 @@ + return null; + } else { + this.level.getProfiler().incrementCounter("getChunkNow"); +- long _long = ChunkPos.asLong(chunkX, chunkZ); ++ long k = ChunkPos.asLong(chunkX, chunkZ); + +- for (int i = 0; i < 4; i++) { +- if (_long == this.lastChunkPos[i] && this.lastChunkStatus[i] == ChunkStatus.FULL) { +- ChunkAccess chunkAccess = this.lastChunk[i]; +- return chunkAccess instanceof LevelChunk ? (LevelChunk)chunkAccess : null; ++ for (int l = 0; l < 4; ++l) { ++ if (k == this.lastChunkPos[l] && this.lastChunkStatus[l] == ChunkStatus.FULL) { ++ ChunkAccess ichunkaccess = this.lastChunk[l]; ++ ++ return ichunkaccess instanceof LevelChunk ? (LevelChunk) ichunkaccess : null; + } + } + +- ChunkHolder visibleChunkIfPresent = this.getVisibleChunkIfPresent(_long); +- if (visibleChunkIfPresent == null) { ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(k); ++ ++ if (playerchunk == null) { + return null; + } else { +- Either either = visibleChunkIfPresent.getFutureIfPresent(ChunkStatus.FULL).getNow(null); ++ Either either = (Either) playerchunk.getFutureIfPresent(ChunkStatus.FULL).getNow(null); // CraftBukkit - decompile error ++ + if (either == null) { + return null; + } else { +- ChunkAccess chunkAccess1 = either.left().orElse(null); +- if (chunkAccess1 != null) { +- this.storeInCache(_long, chunkAccess1, ChunkStatus.FULL); +- if (chunkAccess1 instanceof LevelChunk) { +- return (LevelChunk)chunkAccess1; ++ ChunkAccess ichunkaccess1 = (ChunkAccess) either.left().orElse(null); // CraftBukkit - decompile error ++ ++ if (ichunkaccess1 != null) { ++ this.storeInCache(k, ichunkaccess1, ChunkStatus.FULL); ++ if (ichunkaccess1 instanceof LevelChunk) { ++ return (LevelChunk) ichunkaccess1; + } + } + +@@ -209,85 +207,99 @@ + + private void clearCache() { + Arrays.fill(this.lastChunkPos, ChunkPos.INVALID_CHUNK_POS); +- Arrays.fill(this.lastChunkStatus, null); +- Arrays.fill(this.lastChunk, null); ++ Arrays.fill(this.lastChunkStatus, (Object) null); ++ Arrays.fill(this.lastChunk, (Object) null); + } + +- public CompletableFuture> getChunkFuture(int x, int y, ChunkStatus chunkStatus, boolean load) { +- boolean flag = Thread.currentThread() == this.mainThread; +- CompletableFuture> chunkFutureMainThread; +- if (flag) { +- chunkFutureMainThread = this.getChunkFutureMainThread(x, y, chunkStatus, load); +- this.mainThreadProcessor.managedBlock(chunkFutureMainThread::isDone); ++ public CompletableFuture> getChunkFuture(int x, int y, ChunkStatus chunkStatus, boolean load) { ++ boolean flag1 = Thread.currentThread() == this.mainThread; ++ CompletableFuture completablefuture; ++ ++ if (flag1) { ++ completablefuture = this.getChunkFutureMainThread(x, y, chunkStatus, load); ++ ServerChunkCache.MainThreadExecutor chunkproviderserver_b = this.mainThreadProcessor; ++ ++ Objects.requireNonNull(completablefuture); ++ chunkproviderserver_b.managedBlock(completablefuture::isDone); + } else { +- chunkFutureMainThread = CompletableFuture.>>supplyAsync( +- () -> this.getChunkFutureMainThread(x, y, chunkStatus, load), this.mainThreadProcessor +- ) +- .thenCompose(completableFuture -> (CompletionStage>)completableFuture); ++ completablefuture = CompletableFuture.supplyAsync(() -> { ++ return this.getChunkFutureMainThread(x, y, chunkStatus, load); ++ }, this.mainThreadProcessor).thenCompose((completablefuture1) -> { ++ return completablefuture1; ++ }); + } + +- return chunkFutureMainThread; ++ return completablefuture; + } + +- private CompletableFuture> getChunkFutureMainThread( +- int x, int y, ChunkStatus chunkStatus, boolean load +- ) { +- ChunkPos chunkPos = new ChunkPos(x, y); +- long l = chunkPos.toLong(); +- int i = ChunkLevel.byStatus(chunkStatus); +- ChunkHolder visibleChunkIfPresent = this.getVisibleChunkIfPresent(l); +- if (load) { +- this.distanceManager.addTicket(TicketType.UNKNOWN, chunkPos, i, chunkPos); +- if (this.chunkAbsent(visibleChunkIfPresent, i)) { +- ProfilerFiller profiler = this.level.getProfiler(); +- profiler.push("chunkLoad"); ++ private CompletableFuture> getChunkFutureMainThread(int x, int y, ChunkStatus chunkStatus, boolean load) { ++ ChunkPos chunkcoordintpair = new ChunkPos(x, y); ++ long k = chunkcoordintpair.toLong(); ++ int l = ChunkLevel.byStatus(chunkStatus); ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(k); ++ ++ // CraftBukkit start - don't add new ticket for currently unloading chunk ++ boolean currentlyUnloading = false; ++ if (playerchunk != null) { ++ FullChunkStatus oldChunkState = ChunkLevel.fullStatus(playerchunk.oldTicketLevel); ++ FullChunkStatus currentChunkState = ChunkLevel.fullStatus(playerchunk.getTicketLevel()); ++ currentlyUnloading = (oldChunkState.isOrAfter(FullChunkStatus.FULL) && !currentChunkState.isOrAfter(FullChunkStatus.FULL)); ++ } ++ if (load && !currentlyUnloading) { ++ // CraftBukkit end ++ this.distanceManager.addTicket(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); ++ if (this.chunkAbsent(playerchunk, l)) { ++ ProfilerFiller gameprofilerfiller = this.level.getProfiler(); ++ ++ gameprofilerfiller.push("chunkLoad"); + this.runDistanceManagerUpdates(); +- visibleChunkIfPresent = this.getVisibleChunkIfPresent(l); +- profiler.pop(); +- if (this.chunkAbsent(visibleChunkIfPresent, i)) { +- throw (IllegalStateException)Util.pauseInIde(new IllegalStateException("No chunk holder after ticket has been added")); ++ playerchunk = this.getVisibleChunkIfPresent(k); ++ gameprofilerfiller.pop(); ++ if (this.chunkAbsent(playerchunk, l)) { ++ throw (IllegalStateException) Util.pauseInIde(new IllegalStateException("No chunk holder after ticket has been added")); + } + } + } + +- return this.chunkAbsent(visibleChunkIfPresent, i) +- ? ChunkHolder.UNLOADED_CHUNK_FUTURE +- : visibleChunkIfPresent.getOrScheduleFuture(chunkStatus, this.chunkMap); ++ return this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(chunkStatus, this.chunkMap); + } + + private boolean chunkAbsent(@Nullable ChunkHolder chunkHolder, int status) { +- return chunkHolder == null || chunkHolder.getTicketLevel() > status; ++ return chunkHolder == null || chunkHolder.oldTicketLevel > status; // CraftBukkit using oldTicketLevel for isLoaded checks + } + + @Override + public boolean hasChunk(int x, int z) { +- ChunkHolder visibleChunkIfPresent = this.getVisibleChunkIfPresent(new ChunkPos(x, z).toLong()); +- int i = ChunkLevel.byStatus(ChunkStatus.FULL); +- return !this.chunkAbsent(visibleChunkIfPresent, i); ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent((new ChunkPos(x, z)).toLong()); ++ int k = ChunkLevel.byStatus(ChunkStatus.FULL); ++ ++ return !this.chunkAbsent(playerchunk, k); + } + + @Nullable + @Override + public LightChunk getChunkForLighting(int chunkX, int chunkZ) { +- long _long = ChunkPos.asLong(chunkX, chunkZ); +- ChunkHolder visibleChunkIfPresent = this.getVisibleChunkIfPresent(_long); +- if (visibleChunkIfPresent == null) { ++ long k = ChunkPos.asLong(chunkX, chunkZ); ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(k); ++ ++ if (playerchunk == null) { + return null; + } else { +- int i = CHUNK_STATUSES.size() - 1; ++ int l = ServerChunkCache.CHUNK_STATUSES.size() - 1; + + while (true) { +- ChunkStatus chunkStatus = CHUNK_STATUSES.get(i); +- Optional optional = visibleChunkIfPresent.getFutureIfPresentUnchecked(chunkStatus).getNow(ChunkHolder.UNLOADED_CHUNK).left(); ++ ChunkStatus chunkstatus = (ChunkStatus) ServerChunkCache.CHUNK_STATUSES.get(l); ++ Optional optional = ((Either) playerchunk.getFutureIfPresentUnchecked(chunkstatus).getNow(ChunkHolder.UNLOADED_CHUNK)).left(); ++ + if (optional.isPresent()) { +- return optional.get(); ++ return (LightChunk) optional.get(); + } + +- if (chunkStatus == ChunkStatus.INITIALIZE_LIGHT.getParent()) { ++ if (chunkstatus == ChunkStatus.INITIALIZE_LIGHT.getParent()) { + return null; + } + +- i--; ++ --l; + } + } + } +@@ -304,6 +316,7 @@ + boolean runDistanceManagerUpdates() { + boolean flag = this.distanceManager.runAllUpdates(this.chunkMap); + boolean flag1 = this.chunkMap.promoteChunkMap(); ++ + if (!flag && !flag1) { + return false; + } else { +@@ -313,13 +326,15 @@ + } + + public boolean isPositionTicking(long chunkPos) { +- ChunkHolder visibleChunkIfPresent = this.getVisibleChunkIfPresent(chunkPos); +- if (visibleChunkIfPresent == null) { ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(chunkPos); ++ ++ if (playerchunk == null) { + return false; + } else if (!this.level.shouldTickBlocksAt(chunkPos)) { + return false; + } else { +- Either either = visibleChunkIfPresent.getTickingChunkFuture().getNow(null); ++ Either either = (Either) playerchunk.getTickingChunkFuture().getNow(null); // CraftBukkit - decompile error ++ + return either != null && either.left().isPresent(); + } + } +@@ -331,11 +346,31 @@ + + @Override + public void close() throws IOException { +- this.save(true); ++ // CraftBukkit start ++ close(true); ++ } ++ ++ public void close(boolean save) throws IOException { ++ if (save) { ++ this.save(true); ++ } ++ // CraftBukkit end + this.lightEngine.close(); + this.chunkMap.close(); + } + ++ // CraftBukkit start - modelled on below ++ public void purgeUnload() { ++ this.level.getProfiler().push("purge"); ++ this.distanceManager.purgeStaleTickets(); ++ this.runDistanceManagerUpdates(); ++ this.level.getProfiler().popPush("unload"); ++ this.chunkMap.tick(() -> true); ++ this.level.getProfiler().pop(); ++ this.clearCache(); ++ } ++ // CraftBukkit end ++ + @Override + public void tick(BooleanSupplier hasTimeLeft, boolean tickChunks) { + this.level.getProfiler().push("purge"); +@@ -354,68 +389,80 @@ + } + + private void tickChunks() { +- long gameTime = this.level.getGameTime(); +- long l = gameTime - this.lastInhabitedUpdate; +- this.lastInhabitedUpdate = gameTime; ++ long i = this.level.getGameTime(); ++ long j = i - this.lastInhabitedUpdate; ++ ++ this.lastInhabitedUpdate = i; + if (!this.level.isDebug()) { +- ProfilerFiller profiler = this.level.getProfiler(); +- profiler.push("pollingChunks"); +- profiler.push("filteringLoadedChunks"); +- List list = Lists.newArrayListWithCapacity(this.chunkMap.size()); ++ ProfilerFiller gameprofilerfiller = this.level.getProfiler(); + +- for (ChunkHolder chunkHolder : this.chunkMap.getChunks()) { +- LevelChunk tickingChunk = chunkHolder.getTickingChunk(); +- if (tickingChunk != null) { +- list.add(new ServerChunkCache.ChunkAndHolder(tickingChunk, chunkHolder)); ++ gameprofilerfiller.push("pollingChunks"); ++ gameprofilerfiller.push("filteringLoadedChunks"); ++ List list = Lists.newArrayListWithCapacity(this.chunkMap.size()); ++ Iterator iterator = this.chunkMap.getChunks().iterator(); ++ ++ while (iterator.hasNext()) { ++ ChunkHolder playerchunk = (ChunkHolder) iterator.next(); ++ LevelChunk chunk = playerchunk.getTickingChunk(); ++ ++ if (chunk != null) { ++ list.add(new ServerChunkCache.a(chunk, playerchunk)); + } + } + + if (this.level.getServer().tickRateManager().runsNormally()) { +- profiler.popPush("naturalSpawnCount"); +- int naturalSpawnChunkCount = this.distanceManager.getNaturalSpawnChunkCount(); +- NaturalSpawner.SpawnState spawnState = NaturalSpawner.createState( +- naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap) +- ); +- this.lastSpawnState = spawnState; +- profiler.popPush("spawnAndTick"); +- boolean _boolean = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING); ++ gameprofilerfiller.popPush("naturalSpawnCount"); ++ int k = this.distanceManager.getNaturalSpawnChunkCount(); ++ NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(k, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap)); ++ ++ this.lastSpawnState = spawnercreature_d; ++ gameprofilerfiller.popPush("spawnAndTick"); ++ boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit ++ + Util.shuffle(list, this.level.random); +- int _int = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); +- boolean flag = this.level.getLevelData().getGameTime() % 400L == 0L; ++ int l = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); ++ boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit ++ Iterator iterator1 = list.iterator(); + +- for (ServerChunkCache.ChunkAndHolder chunkAndHolder : list) { +- LevelChunk levelChunk = chunkAndHolder.chunk; +- ChunkPos pos = levelChunk.getPos(); +- if (this.level.isNaturalSpawningAllowed(pos) && this.chunkMap.anyPlayerCloseEnoughForSpawning(pos)) { +- levelChunk.incrementInhabitedTime(l); +- if (_boolean && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(pos)) { +- NaturalSpawner.spawnForChunk(this.level, levelChunk, spawnState, this.spawnFriendlies, this.spawnEnemies, flag); ++ while (iterator1.hasNext()) { ++ ServerChunkCache.a chunkproviderserver_a = (ServerChunkCache.a) iterator1.next(); ++ LevelChunk chunk1 = chunkproviderserver_a.chunk; ++ ChunkPos chunkcoordintpair = chunk1.getPos(); ++ ++ if (this.level.isNaturalSpawningAllowed(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair)) { ++ chunk1.incrementInhabitedTime(j); ++ if (flag && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair)) { ++ NaturalSpawner.spawnForChunk(this.level, chunk1, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1); + } + +- if (this.level.shouldTickBlocksAt(pos.toLong())) { +- this.level.tickChunk(levelChunk, _int); ++ if (this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) { ++ this.level.tickChunk(chunk1, l); + } + } + } + +- profiler.popPush("customSpawners"); +- if (_boolean) { ++ gameprofilerfiller.popPush("customSpawners"); ++ if (flag) { + this.level.tickCustomSpawners(this.spawnEnemies, this.spawnFriendlies); + } + } + +- profiler.popPush("broadcast"); +- list.forEach(chunkAndHolder1 -> chunkAndHolder1.holder.broadcastChanges(chunkAndHolder1.chunk)); +- profiler.pop(); +- profiler.pop(); ++ gameprofilerfiller.popPush("broadcast"); ++ list.forEach((chunkproviderserver_a1) -> { ++ chunkproviderserver_a1.holder.broadcastChanges(chunkproviderserver_a1.chunk); ++ }); ++ gameprofilerfiller.pop(); ++ gameprofilerfiller.pop(); + } + } + +- private void getFullChunk(long chunkPos, Consumer fullChunkGetter) { +- ChunkHolder visibleChunkIfPresent = this.getVisibleChunkIfPresent(chunkPos); +- if (visibleChunkIfPresent != null) { +- visibleChunkIfPresent.getFullChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK).left().ifPresent(fullChunkGetter); ++ private void getFullChunk(long chunkPos, Consumer consumer) { ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(chunkPos); ++ ++ if (playerchunk != null) { ++ ((Either) playerchunk.getFullChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left().ifPresent(consumer); + } ++ + } + + @Override +@@ -447,20 +494,24 @@ + + public void blockChanged(BlockPos pos) { + int i = SectionPos.blockToSectionCoord(pos.getX()); +- int i1 = SectionPos.blockToSectionCoord(pos.getZ()); +- ChunkHolder visibleChunkIfPresent = this.getVisibleChunkIfPresent(ChunkPos.asLong(i, i1)); +- if (visibleChunkIfPresent != null) { +- visibleChunkIfPresent.blockChanged(pos); ++ int j = SectionPos.blockToSectionCoord(pos.getZ()); ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(ChunkPos.asLong(i, j)); ++ ++ if (playerchunk != null) { ++ playerchunk.blockChanged(pos); + } ++ + } + + @Override +- public void onLightUpdate(LightLayer type, SectionPos pos) { ++ public void onLightUpdate(EnumSkyBlock type, SectionPos pos) { + this.mainThreadProcessor.execute(() -> { +- ChunkHolder visibleChunkIfPresent = this.getVisibleChunkIfPresent(pos.chunk().toLong()); +- if (visibleChunkIfPresent != null) { +- visibleChunkIfPresent.sectionLightChanged(type, pos.y()); ++ ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos.chunk().toLong()); ++ ++ if (playerchunk != null) { ++ playerchunk.sectionLightChanged(type, pos.y()); + } ++ + }); + } + +@@ -481,6 +532,7 @@ + if (!player.isRemoved()) { + this.chunkMap.move(player); + } ++ + } + + public void removeEntity(Entity entity) { +@@ -539,12 +591,10 @@ + this.distanceManager.removeTicketsOnClosing(); + } + +- static record ChunkAndHolder(LevelChunk chunk, ChunkHolder holder) { +- } ++ private final class MainThreadExecutor extends BlockableEventLoop { + +- final class MainThreadExecutor extends BlockableEventLoop { +- MainThreadExecutor(Level level) { +- super("Chunk source main thread executor for " + level.dimension().location()); ++ MainThreadExecutor(Level world) { ++ super("Chunk source main thread executor for " + world.dimension().location()); + } + + @Override +@@ -574,13 +624,23 @@ + } + + @Override ++ // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task + public boolean pollTask() { ++ try { + if (ServerChunkCache.this.runDistanceManagerUpdates()) { + return true; + } else { + ServerChunkCache.this.lightEngine.tryScheduleUpdate(); + return super.pollTask(); + } ++ } finally { ++ chunkMap.callbackExecutor.run(); + } ++ // CraftBukkit end ++ } + } ++ ++ private static record a(LevelChunk chunk, ChunkHolder holder) { ++ ++ } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/level/ServerEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/level/ServerEntity.java.patch new file mode 100644 index 0000000000..3329263599 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/level/ServerEntity.java.patch @@ -0,0 +1,485 @@ +--- a/net/minecraft/server/level/ServerEntity.java ++++ b/net/minecraft/server/level/ServerEntity.java +@@ -6,7 +6,9 @@ + import java.util.ArrayList; + import java.util.Collection; + import java.util.Collections; ++import java.util.Iterator; + import java.util.List; ++import java.util.Objects; + import java.util.Set; + import java.util.function.Consumer; + import java.util.stream.Stream; +@@ -26,7 +28,6 @@ + import net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket; + import net.minecraft.network.protocol.game.VecDeltaCodec; + import net.minecraft.network.syncher.SynchedEntityData; +-import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.LivingEntity; +@@ -40,10 +41,18 @@ + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.server.network.ServerPlayerConnection; ++import net.minecraft.util.Mth; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerVelocityEvent; ++// CraftBukkit end ++ + public class ServerEntity { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int TOLERANCE_LEVEL_ROTATION = 1; +- private static final double TOLERANCE_LEVEL_POSITION = 7.6293945E-6F; ++ private static final double TOLERANCE_LEVEL_POSITION = 7.62939453125E-6D; + public static final int FORCED_POS_UPDATE_PERIOD = 60; + private static final int FORCED_TELEPORT_PERIOD = 400; + private final ServerLevel level; +@@ -55,21 +64,27 @@ + private int yRotp; + private int xRotp; + private int yHeadRotp; +- private Vec3 ap = Vec3.ZERO; ++ private Vec3 ap; + private int tickCount; + private int teleportDelay; +- private List lastPassengers = Collections.emptyList(); ++ private List lastPassengers; + private boolean wasRiding; + private boolean wasOnGround; + @Nullable + private List> trackedDataValues; ++ // CraftBukkit start ++ private final Set trackedPlayers; + +- public ServerEntity(ServerLevel level, Entity entity, int updateInterval, boolean trackDelta, Consumer> broadcast) { +- this.level = level; +- this.broadcast = broadcast; ++ public ServerEntity(ServerLevel worldserver, Entity entity, int i, boolean flag, Consumer> consumer, Set trackedPlayers) { ++ this.trackedPlayers = trackedPlayers; ++ // CraftBukkit end ++ this.ap = Vec3.ZERO; ++ this.lastPassengers = Collections.emptyList(); ++ this.level = worldserver; ++ this.broadcast = consumer; + this.entity = entity; +- this.updateInterval = updateInterval; +- this.trackDelta = trackDelta; ++ this.updateInterval = i; ++ this.trackDelta = flag; + this.positionCodec.setBase(entity.trackingPosition()); + this.yRotp = Mth.floor(entity.getYRot() * 256.0F / 360.0F); + this.xRotp = Mth.floor(entity.getXRot() * 256.0F / 360.0F); +@@ -79,149 +94,191 @@ + } + + public void sendChanges() { +- List passengers = this.entity.getPassengers(); +- if (!passengers.equals(this.lastPassengers)) { +- this.broadcast.accept(new ClientboundSetPassengersPacket(this.entity)); +- removedPassengers(passengers, this.lastPassengers) +- .forEach( +- entity -> { +- if (entity instanceof ServerPlayer serverPlayer1) { +- serverPlayer1.connection +- .teleport(serverPlayer1.getX(), serverPlayer1.getY(), serverPlayer1.getZ(), serverPlayer1.getYRot(), serverPlayer1.getXRot()); +- } +- } +- ); +- this.lastPassengers = passengers; ++ List list = this.entity.getPassengers(); ++ ++ if (!list.equals(this.lastPassengers)) { ++ this.broadcastAndSend(new ClientboundSetPassengersPacket(this.entity)); // CraftBukkit ++ removedPassengers(list, this.lastPassengers).forEach((entity) -> { ++ if (entity instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entity; ++ ++ entityplayer.connection.teleport(entityplayer.getX(), entityplayer.getY(), entityplayer.getZ(), entityplayer.getYRot(), entityplayer.getXRot()); ++ } ++ ++ }); ++ this.lastPassengers = list; + } + +- if (this.entity instanceof ItemFrame itemFrame && this.tickCount % 10 == 0) { +- ItemStack item = itemFrame.getItem(); +- if (item.getItem() instanceof MapItem) { +- Integer mapId = MapItem.getMapId(item); +- MapItemSavedData savedData = MapItem.getSavedData(mapId, this.level); +- if (savedData != null) { +- for (ServerPlayer serverPlayer : this.level.players()) { +- savedData.tickCarriedBy(serverPlayer, item); +- Packet updatePacket = savedData.getUpdatePacket(mapId, serverPlayer); +- if (updatePacket != null) { +- serverPlayer.connection.send(updatePacket); ++ Entity entity = this.entity; ++ ++ if (entity instanceof ItemFrame) { ++ ItemFrame entityitemframe = (ItemFrame) entity; ++ ++ if (true || this.tickCount % 10 == 0) { // CraftBukkit - Moved below, should always enter this block ++ ItemStack itemstack = entityitemframe.getItem(); ++ ++ if (this.tickCount % 10 == 0 && itemstack.getItem() instanceof MapItem) { // CraftBukkit - Moved this.tickCounter % 10 logic here so item frames do not enter the other blocks ++ Integer integer = MapItem.getMapId(itemstack); ++ MapItemSavedData worldmap = MapItem.getSavedData(integer, this.level); ++ ++ if (worldmap != null) { ++ Iterator iterator = this.trackedPlayers.iterator(); // CraftBukkit ++ ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = iterator.next().getPlayer(); // CraftBukkit ++ ++ worldmap.tickCarriedBy(entityplayer, itemstack); ++ Packet packet = worldmap.getUpdatePacket(integer, entityplayer); ++ ++ if (packet != null) { ++ entityplayer.connection.send(packet); ++ } + } + } + } +- } + +- this.sendDirtyEntityData(); ++ this.sendDirtyEntityData(); ++ } + } + + if (this.tickCount % this.updateInterval == 0 || this.entity.hasImpulse || this.entity.getEntityData().isDirty()) { ++ int i; ++ int j; ++ + if (this.entity.isPassenger()) { +- int floor = Mth.floor(this.entity.getYRot() * 256.0F / 360.0F); +- int floor1 = Mth.floor(this.entity.getXRot() * 256.0F / 360.0F); +- boolean flag = Math.abs(floor - this.yRotp) >= 1 || Math.abs(floor1 - this.xRotp) >= 1; ++ i = Mth.floor(this.entity.getYRot() * 256.0F / 360.0F); ++ j = Mth.floor(this.entity.getXRot() * 256.0F / 360.0F); ++ boolean flag = Math.abs(i - this.yRotp) >= 1 || Math.abs(j - this.xRotp) >= 1; ++ + if (flag) { +- this.broadcast.accept(new ClientboundMoveEntityPacket.Rot(this.entity.getId(), (byte)floor, (byte)floor1, this.entity.onGround())); +- this.yRotp = floor; +- this.xRotp = floor1; ++ this.broadcast.accept(new ClientboundMoveEntityPacket.Rot(this.entity.getId(), (byte) i, (byte) j, this.entity.onGround())); ++ this.yRotp = i; ++ this.xRotp = j; + } + + this.positionCodec.setBase(this.entity.trackingPosition()); + this.sendDirtyEntityData(); + this.wasRiding = true; + } else { +- this.teleportDelay++; +- int floor = Mth.floor(this.entity.getYRot() * 256.0F / 360.0F); +- int floor1 = Mth.floor(this.entity.getXRot() * 256.0F / 360.0F); +- Vec3 vec3 = this.entity.trackingPosition(); +- boolean flag1 = this.positionCodec.delta(vec3).lengthSqr() >= 7.6293945E-6F; +- Packet packet = null; ++ ++this.teleportDelay; ++ i = Mth.floor(this.entity.getYRot() * 256.0F / 360.0F); ++ j = Mth.floor(this.entity.getXRot() * 256.0F / 360.0F); ++ Vec3 vec3d = this.entity.trackingPosition(); ++ boolean flag1 = this.positionCodec.delta(vec3d).lengthSqr() >= 7.62939453125E-6D; ++ Packet packet1 = null; + boolean flag2 = flag1 || this.tickCount % 60 == 0; +- boolean flag3 = Math.abs(floor - this.yRotp) >= 1 || Math.abs(floor1 - this.xRotp) >= 1; ++ boolean flag3 = Math.abs(i - this.yRotp) >= 1 || Math.abs(j - this.xRotp) >= 1; + boolean flag4 = false; + boolean flag5 = false; ++ + if (this.tickCount > 0 || this.entity instanceof AbstractArrow) { +- long l = this.positionCodec.encodeX(vec3); +- long l1 = this.positionCodec.encodeY(vec3); +- long l2 = this.positionCodec.encodeZ(vec3); +- boolean flag6 = l < -32768L || l > 32767L || l1 < -32768L || l1 > 32767L || l2 < -32768L || l2 > 32767L; +- if (flag6 || this.teleportDelay > 400 || this.wasRiding || this.wasOnGround != this.entity.onGround()) { +- this.wasOnGround = this.entity.onGround(); +- this.teleportDelay = 0; +- packet = new ClientboundTeleportEntityPacket(this.entity); +- flag4 = true; +- flag5 = true; +- } else if ((!flag2 || !flag3) && !(this.entity instanceof AbstractArrow)) { +- if (flag2) { +- packet = new ClientboundMoveEntityPacket.Pos( +- this.entity.getId(), (short)((int)l), (short)((int)l1), (short)((int)l2), this.entity.onGround() +- ); ++ long k = this.positionCodec.encodeX(vec3d); ++ long l = this.positionCodec.encodeY(vec3d); ++ long i1 = this.positionCodec.encodeZ(vec3d); ++ boolean flag6 = k < -32768L || k > 32767L || l < -32768L || l > 32767L || i1 < -32768L || i1 > 32767L; ++ ++ if (!flag6 && this.teleportDelay <= 400 && !this.wasRiding && this.wasOnGround == this.entity.onGround()) { ++ if ((!flag2 || !flag3) && !(this.entity instanceof AbstractArrow)) { ++ if (flag2) { ++ packet1 = new ClientboundMoveEntityPacket.Pos(this.entity.getId(), (short) ((int) k), (short) ((int) l), (short) ((int) i1), this.entity.onGround()); ++ flag4 = true; ++ } else if (flag3) { ++ packet1 = new ClientboundMoveEntityPacket.Rot(this.entity.getId(), (byte) i, (byte) j, this.entity.onGround()); ++ flag5 = true; ++ } ++ } else { ++ packet1 = new ClientboundMoveEntityPacket.PosRot(this.entity.getId(), (short) ((int) k), (short) ((int) l), (short) ((int) i1), (byte) i, (byte) j, this.entity.onGround()); + flag4 = true; +- } else if (flag3) { +- packet = new ClientboundMoveEntityPacket.Rot(this.entity.getId(), (byte)floor, (byte)floor1, this.entity.onGround()); + flag5 = true; + } + } else { +- packet = new ClientboundMoveEntityPacket.PosRot( +- this.entity.getId(), (short)((int)l), (short)((int)l1), (short)((int)l2), (byte)floor, (byte)floor1, this.entity.onGround() +- ); ++ this.wasOnGround = this.entity.onGround(); ++ this.teleportDelay = 0; ++ packet1 = new ClientboundTeleportEntityPacket(this.entity); + flag4 = true; + flag5 = true; + } + } + +- if ((this.trackDelta || this.entity.hasImpulse || this.entity instanceof LivingEntity && ((LivingEntity)this.entity).isFallFlying()) +- && this.tickCount > 0) { +- Vec3 deltaMovement = this.entity.getDeltaMovement(); +- double d = deltaMovement.distanceToSqr(this.ap); +- if (d > 1.0E-7 || d > 0.0 && deltaMovement.lengthSqr() == 0.0) { +- this.ap = deltaMovement; ++ if ((this.trackDelta || this.entity.hasImpulse || this.entity instanceof LivingEntity && ((LivingEntity) this.entity).isFallFlying()) && this.tickCount > 0) { ++ Vec3 vec3d1 = this.entity.getDeltaMovement(); ++ double d0 = vec3d1.distanceToSqr(this.ap); ++ ++ if (d0 > 1.0E-7D || d0 > 0.0D && vec3d1.lengthSqr() == 0.0D) { ++ this.ap = vec3d1; + this.broadcast.accept(new ClientboundSetEntityMotionPacket(this.entity.getId(), this.ap)); + } + } + +- if (packet != null) { +- this.broadcast.accept(packet); ++ if (packet1 != null) { ++ this.broadcast.accept(packet1); + } + + this.sendDirtyEntityData(); + if (flag4) { +- this.positionCodec.setBase(vec3); ++ this.positionCodec.setBase(vec3d); + } + + if (flag5) { +- this.yRotp = floor; +- this.xRotp = floor1; ++ this.yRotp = i; ++ this.xRotp = j; + } + + this.wasRiding = false; + } + +- int floorx = Mth.floor(this.entity.getYHeadRot() * 256.0F / 360.0F); +- if (Math.abs(floorx - this.yHeadRotp) >= 1) { +- this.broadcast.accept(new ClientboundRotateHeadPacket(this.entity, (byte)floorx)); +- this.yHeadRotp = floorx; ++ i = Mth.floor(this.entity.getYHeadRot() * 256.0F / 360.0F); ++ if (Math.abs(i - this.yHeadRotp) >= 1) { ++ this.broadcast.accept(new ClientboundRotateHeadPacket(this.entity, (byte) i)); ++ this.yHeadRotp = i; + } + + this.entity.hasImpulse = false; + } + +- this.tickCount++; ++ ++this.tickCount; + if (this.entity.hurtMarked) { +- this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity)); ++ // CraftBukkit start - Create PlayerVelocity event ++ boolean cancelled = false; ++ ++ if (this.entity instanceof ServerPlayer) { ++ Player player = (Player) this.entity.getBukkitEntity(); ++ org.bukkit.util.Vector velocity = player.getVelocity(); ++ ++ PlayerVelocityEvent event = new PlayerVelocityEvent(player, velocity.clone()); ++ this.entity.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ cancelled = true; ++ } else if (!velocity.equals(event.getVelocity())) { ++ player.setVelocity(event.getVelocity()); ++ } ++ } ++ ++ if (!cancelled) { ++ this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity)); ++ } ++ // CraftBukkit end + this.entity.hurtMarked = false; + } ++ + } + + private static Stream removedPassengers(List initialPassengers, List currentPassengers) { +- return currentPassengers.stream().filter(entity -> !initialPassengers.contains(entity)); ++ return currentPassengers.stream().filter((entity) -> { ++ return !initialPassengers.contains(entity); ++ }); + } + + public void removePairing(ServerPlayer player) { + this.entity.stopSeenByPlayer(player); +- player.connection.send(new ClientboundRemoveEntitiesPacket(this.entity.getId())); ++ player.connection.send(new ClientboundRemoveEntitiesPacket(new int[]{this.entity.getId()})); + } + + public void addPairing(ServerPlayer player) { +- List> list = new ArrayList<>(); ++ List> list = new ArrayList(); ++ ++ Objects.requireNonNull(list); + this.sendPairingData(player, list::add); + player.connection.send(new ClientboundBundlePacket(list)); + this.entity.startSeenByPlayer(player); +@@ -229,24 +286,36 @@ + + public void sendPairingData(ServerPlayer player, Consumer> consumer) { + if (this.entity.isRemoved()) { +- LOGGER.warn("Fetching packet for removed entity {}", this.entity); ++ // CraftBukkit start - Remove useless error spam, just return ++ // EntityTrackerEntry.LOGGER.warn("Fetching packet for removed entity {}", this.entity); ++ return; ++ // CraftBukkit end + } + +- Packet addEntityPacket = this.entity.getAddEntityPacket(); ++ Packet packet = this.entity.getAddEntityPacket(); ++ + this.yHeadRotp = Mth.floor(this.entity.getYHeadRot() * 256.0F / 360.0F); +- consumer.accept(addEntityPacket); ++ consumer.accept(packet); + if (this.trackedDataValues != null) { + consumer.accept(new ClientboundSetEntityDataPacket(this.entity.getId(), this.trackedDataValues)); + } + + boolean flag = this.trackDelta; ++ + if (this.entity instanceof LivingEntity) { +- Collection syncableAttributes = ((LivingEntity)this.entity).getAttributes().getSyncableAttributes(); +- if (!syncableAttributes.isEmpty()) { +- consumer.accept(new ClientboundUpdateAttributesPacket(this.entity.getId(), syncableAttributes)); ++ Collection collection = ((LivingEntity) this.entity).getAttributes().getSyncableAttributes(); ++ ++ // CraftBukkit start - If sending own attributes send scaled health instead of current maximum health ++ if (this.entity.getId() == player.getId()) { ++ ((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(collection, false); + } ++ // CraftBukkit end + +- if (((LivingEntity)this.entity).isFallFlying()) { ++ if (!collection.isEmpty()) { ++ consumer.accept(new ClientboundUpdateAttributesPacket(this.entity.getId(), collection)); ++ } ++ ++ if (((LivingEntity) this.entity).isFallFlying()) { + flag = true; + } + } +@@ -258,19 +327,30 @@ + + if (this.entity instanceof LivingEntity) { + List> list = Lists.newArrayList(); ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ int i = aenumitemslot.length; + +- for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) { +- ItemStack itemBySlot = ((LivingEntity)this.entity).getItemBySlot(equipmentSlot); +- if (!itemBySlot.isEmpty()) { +- list.add(Pair.of(equipmentSlot, itemBySlot.copy())); ++ for (int j = 0; j < i; ++j) { ++ EquipmentSlot enumitemslot = aenumitemslot[j]; ++ ItemStack itemstack = ((LivingEntity) this.entity).getItemBySlot(enumitemslot); ++ ++ if (!itemstack.isEmpty()) { ++ list.add(Pair.of(enumitemslot, itemstack.copy())); + } + } + + if (!list.isEmpty()) { + consumer.accept(new ClientboundSetEquipmentPacket(this.entity.getId(), list)); + } ++ ((LivingEntity) this.entity).detectEquipmentUpdatesPublic(); // CraftBukkit - SPIGOT-3789: sync again immediately after sending + } + ++ // CraftBukkit start - MC-109346: Fix for nonsensical head yaw ++ if (this.entity instanceof ServerPlayer) { ++ consumer.accept(new ClientboundRotateHeadPacket(this.entity, (byte) Mth.floor(this.entity.getYHeadRot() * 256.0F / 360.0F))); ++ } ++ // CraftBukkit end ++ + if (!this.entity.getPassengers().isEmpty()) { + consumer.accept(new ClientboundSetPassengersPacket(this.entity)); + } +@@ -279,33 +359,49 @@ + consumer.accept(new ClientboundSetPassengersPacket(this.entity.getVehicle())); + } + +- if (this.entity instanceof Mob mob && mob.isLeashed()) { +- consumer.accept(new ClientboundSetEntityLinkPacket(mob, mob.getLeashHolder())); ++ Entity entity = this.entity; ++ ++ if (entity instanceof Mob) { ++ Mob entityinsentient = (Mob) entity; ++ ++ if (entityinsentient.isLeashed()) { ++ consumer.accept(new ClientboundSetEntityLinkPacket(entityinsentient, entityinsentient.getLeashHolder())); ++ } + } ++ + } + + private void sendDirtyEntityData() { +- SynchedEntityData entityData = this.entity.getEntityData(); +- List> list = entityData.packDirty(); ++ SynchedEntityData datawatcher = this.entity.getEntityData(); ++ List> list = datawatcher.packDirty(); ++ + if (list != null) { +- this.trackedDataValues = entityData.getNonDefaultValues(); ++ this.trackedDataValues = datawatcher.getNonDefaultValues(); + this.broadcastAndSend(new ClientboundSetEntityDataPacket(this.entity.getId(), list)); + } + + if (this.entity instanceof LivingEntity) { +- Set dirtyAttributes = ((LivingEntity)this.entity).getAttributes().getDirtyAttributes(); +- if (!dirtyAttributes.isEmpty()) { +- this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), dirtyAttributes)); ++ Set set = ((LivingEntity) this.entity).getAttributes().getDirtyAttributes(); ++ ++ if (!set.isEmpty()) { ++ // CraftBukkit start - Send scaled max health ++ if (this.entity instanceof ServerPlayer) { ++ ((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(set, false); ++ } ++ // CraftBukkit end ++ this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), set)); + } + +- dirtyAttributes.clear(); ++ set.clear(); + } ++ + } + + private void broadcastAndSend(Packet packet) { + this.broadcast.accept(packet); + if (this.entity instanceof ServerPlayer) { +- ((ServerPlayer)this.entity).connection.send(packet); ++ ((ServerPlayer) this.entity).connection.send(packet); + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/level/ServerLevel.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/level/ServerLevel.java.patch new file mode 100644 index 0000000000..7c5161a5ef --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/level/ServerLevel.java.patch @@ -0,0 +1,2379 @@ +--- a/net/minecraft/server/level/ServerLevel.java ++++ b/net/minecraft/server/level/ServerLevel.java +@@ -9,17 +9,20 @@ + import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + import it.unimi.dsi.fastutil.longs.LongSet; + import it.unimi.dsi.fastutil.longs.LongSets; ++import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; + import it.unimi.dsi.fastutil.objects.ObjectArrayList; ++import it.unimi.dsi.fastutil.objects.ObjectIterator; + import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; + import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +-import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; ++import java.io.BufferedWriter; + import java.io.IOException; + import java.io.Writer; + import java.nio.file.Files; + import java.nio.file.Path; + import java.util.ArrayList; + import java.util.Comparator; ++import java.util.Iterator; + import java.util.List; + import java.util.Locale; + import java.util.Objects; +@@ -46,13 +49,13 @@ + import net.minecraft.core.registries.BuiltInRegistries; + import net.minecraft.core.registries.Registries; + import net.minecraft.network.chat.Component; ++import net.minecraft.network.chat.MutableComponent; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientboundBlockDestructionPacket; + import net.minecraft.network.protocol.game.ClientboundBlockEventPacket; + import net.minecraft.network.protocol.game.ClientboundDamageEventPacket; + import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; + import net.minecraft.network.protocol.game.ClientboundExplodePacket; +-import net.minecraft.network.protocol.game.ClientboundGameEventPacket; + import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; + import net.minecraft.network.protocol.game.ClientboundLevelParticlesPacket; + import net.minecraft.network.protocol.game.ClientboundSetDefaultSpawnPositionPacket; +@@ -98,7 +101,7 @@ + import net.minecraft.world.entity.animal.horse.SkeletonHorse; + import net.minecraft.world.entity.boss.EnderDragonPart; + import net.minecraft.world.entity.boss.enderdragon.EnderDragon; +-import net.minecraft.world.entity.npc.Npc; ++import net.minecraft.world.entity.npc.NPC; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.raid.Raid; + import net.minecraft.world.entity.raid.Raids; +@@ -116,11 +119,12 @@ + import net.minecraft.world.level.StructureManager; + import net.minecraft.world.level.WorldGenLevel; + import net.minecraft.world.level.biome.Biome; ++import net.minecraft.world.level.biome.BiomeSource; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.SnowLayerBlock; + import net.minecraft.world.level.block.entity.TickingBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.chunk.LevelChunk; +@@ -138,7 +142,9 @@ + import net.minecraft.world.level.gameevent.DynamicGameEventListener; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.gameevent.GameEventDispatcher; ++import net.minecraft.world.level.levelgen.FlatLevelSource; + import net.minecraft.world.level.levelgen.Heightmap; ++import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; + import net.minecraft.world.level.levelgen.structure.BoundingBox; + import net.minecraft.world.level.levelgen.structure.Structure; + import net.minecraft.world.level.levelgen.structure.StructureCheck; +@@ -150,7 +156,7 @@ + import net.minecraft.world.level.saveddata.maps.MapItemSavedData; + import net.minecraft.world.level.storage.DimensionDataStorage; + import net.minecraft.world.level.storage.LevelStorageSource; +-import net.minecraft.world.level.storage.ServerLevelData; ++import net.minecraft.world.level.storage.PrimaryLevelData; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.BooleanOp; +@@ -158,8 +164,22 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.ticks.LevelTicks; + import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.WeatherType; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.generator.CustomWorldChunkManager; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.craftbukkit.util.WorldUUID; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.server.MapInitializeEvent; ++import org.bukkit.event.weather.LightningStrikeEvent; ++import org.bukkit.event.world.GenericGameEvent; ++import org.bukkit.event.world.TimeSkipEvent; ++// CraftBukkit end + + public class ServerLevel extends Level implements WorldGenLevel { ++ + public static final BlockPos END_SPAWN_POINT = new BlockPos(100, 50, 0); + public static final IntProvider RAIN_DELAY = UniformInt.of(12000, 180000); + public static final IntProvider RAIN_DURATION = UniformInt.of(12000, 24000); +@@ -168,121 +188,130 @@ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int EMPTY_TIME_NO_TICK = 300; + private static final int MAX_SCHEDULED_TICKS_PER_TICK = 65536; +- final List players = Lists.newArrayList(); ++ final List players; + private final ServerChunkCache chunkSource; + private final MinecraftServer server; +- private final ServerLevelData serverLevelData; +- final EntityTickList entityTickList = new EntityTickList(); +- private final PersistentEntitySectionManager entityManager; ++ public final PrimaryLevelData serverLevelData; // CraftBukkit - type ++ final EntityTickList entityTickList; ++ public final PersistentEntitySectionManager entityManager; + private final GameEventDispatcher gameEventDispatcher; + public boolean noSave; + private final SleepStatus sleepStatus; + private int emptyTime; + private final PortalForcer portalForcer; +- private final LevelTicks blockTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded, this.getProfilerSupplier()); +- private final LevelTicks fluidTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded, this.getProfilerSupplier()); +- final Set navigatingMobs = new ObjectOpenHashSet<>(); ++ private final LevelTicks blockTicks; ++ private final LevelTicks fluidTicks; ++ final Set navigatingMobs; + volatile boolean isUpdatingNavigations; + protected final Raids raids; +- private final ObjectLinkedOpenHashSet blockEvents = new ObjectLinkedOpenHashSet<>(); +- private final List blockEventsToReschedule = new ArrayList<>(64); ++ private final ObjectLinkedOpenHashSet blockEvents; ++ private final List blockEventsToReschedule; + private boolean handlingTick; + private final List customSpawners; + @Nullable + private EndDragonFight dragonFight; +- final Int2ObjectMap dragonParts = new Int2ObjectOpenHashMap<>(); ++ final Int2ObjectMap dragonParts; + private final StructureManager structureManager; + private final StructureCheck structureCheck; + private final boolean tickTime; + private final RandomSequences randomSequences; + +- public ServerLevel( +- MinecraftServer server, +- Executor dispatcher, +- LevelStorageSource.LevelStorageAccess levelStorageAccess, +- ServerLevelData serverLevelData, +- ResourceKey dimension, +- LevelStem levelStem, +- ChunkProgressListener progressListener, +- boolean isDebug, +- long biomeZoomSeed, +- List customSpawners, +- boolean tickTime, +- @Nullable RandomSequences randomSequences +- ) { +- super( +- serverLevelData, +- dimension, +- server.registryAccess(), +- levelStem.type(), +- server::getProfiler, +- false, +- isDebug, +- biomeZoomSeed, +- server.getMaxChainedNeighborUpdates() +- ); +- this.tickTime = tickTime; +- this.server = server; +- this.customSpawners = customSpawners; +- this.serverLevelData = serverLevelData; +- ChunkGenerator chunkGenerator = levelStem.generator(); +- boolean flag = server.forceSynchronousWrites(); +- DataFixer fixerUpper = server.getFixerUpper(); +- EntityPersistentStorage entityPersistentStorage = new EntityStorage( +- this, levelStorageAccess.getDimensionPath(dimension).resolve("entities"), fixerUpper, flag, server +- ); +- this.entityManager = new PersistentEntitySectionManager<>(Entity.class, new ServerLevel.EntityCallbacks(), entityPersistentStorage); +- this.chunkSource = new ServerChunkCache( +- this, +- levelStorageAccess, +- fixerUpper, +- server.getStructureManager(), +- dispatcher, +- chunkGenerator, +- server.getPlayerList().getViewDistance(), +- server.getPlayerList().getSimulationDistance(), +- flag, +- progressListener, +- this.entityManager::updateChunkStatus, +- () -> server.overworld().getDataStorage() +- ); ++ // CraftBukkit start ++ public final LevelStorageSource.LevelStorageAccess convertable; ++ public final UUID uuid; ++ ++ public LevelChunk getChunkIfLoaded(int x, int z) { ++ return this.chunkSource.getChunk(x, z, false); ++ } ++ ++ @Override ++ public ResourceKey getTypeKey() { ++ return convertable.dimensionType; ++ } ++ ++ // Add env and gen to constructor, IWorldDataServer -> WorldDataServer ++ public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List list, boolean flag1, @Nullable RandomSequences randomsequences, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) { ++ // IRegistryCustom.Dimension iregistrycustom_dimension = minecraftserver.registryAccess(); // CraftBukkit - decompile error ++ // Holder holder = worlddimension.type(); // CraftBukkit - decompile error ++ ++ // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error ++ super(iworlddataserver, resourcekey, minecraftserver.registryAccess(), worlddimension.type(), minecraftserver::getProfiler, false, flag, i, minecraftserver.getMaxChainedNeighborUpdates(), gen, biomeProvider, env); ++ this.pvpMode = minecraftserver.isPvpAllowed(); ++ convertable = convertable_conversionsession; ++ uuid = WorldUUID.getUUID(convertable_conversionsession.levelDirectory.path().toFile()); ++ // CraftBukkit end ++ this.players = Lists.newArrayList(); ++ this.entityTickList = new EntityTickList(); ++ this.blockTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded, this.getProfilerSupplier()); ++ this.fluidTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded, this.getProfilerSupplier()); ++ this.navigatingMobs = new ObjectOpenHashSet(); ++ this.blockEvents = new ObjectLinkedOpenHashSet(); ++ this.blockEventsToReschedule = new ArrayList(64); ++ this.dragonParts = new Int2ObjectOpenHashMap(); ++ this.tickTime = flag1; ++ this.server = minecraftserver; ++ this.customSpawners = list; ++ this.serverLevelData = iworlddataserver; ++ ChunkGenerator chunkgenerator = worlddimension.generator(); ++ // CraftBukkit start ++ serverLevelData.setWorld(this); ++ ++ if (biomeProvider != null) { ++ BiomeSource worldChunkManager = new CustomWorldChunkManager(getWorld(), biomeProvider, server.registryAccess().registryOrThrow(Registries.BIOME)); ++ if (chunkgenerator instanceof NoiseBasedChunkGenerator cga) { ++ chunkgenerator = new NoiseBasedChunkGenerator(worldChunkManager, cga.settings); ++ } else if (chunkgenerator instanceof FlatLevelSource cpf) { ++ chunkgenerator = new FlatLevelSource(cpf.settings(), worldChunkManager); ++ } ++ } ++ ++ if (gen != null) { ++ chunkgenerator = new org.bukkit.craftbukkit.generator.CustomChunkGenerator(this, chunkgenerator, gen); ++ } ++ // CraftBukkit end ++ boolean flag2 = minecraftserver.forceSynchronousWrites(); ++ DataFixer datafixer = minecraftserver.getFixerUpper(); ++ EntityPersistentStorage entitypersistentstorage = new EntityStorage(this, convertable_conversionsession.getDimensionPath(resourcekey).resolve("entities"), datafixer, flag2, minecraftserver); ++ ++ this.entityManager = new PersistentEntitySectionManager<>(Entity.class, new ServerLevel.a(), entitypersistentstorage); ++ StructureTemplateManager structuretemplatemanager = minecraftserver.getStructureManager(); ++ int j = minecraftserver.getPlayerList().getViewDistance(); ++ int k = minecraftserver.getPlayerList().getSimulationDistance(); ++ PersistentEntitySectionManager persistententitysectionmanager = this.entityManager; ++ ++ Objects.requireNonNull(this.entityManager); ++ this.chunkSource = new ServerChunkCache(this, convertable_conversionsession, datafixer, structuretemplatemanager, executor, chunkgenerator, j, k, flag2, worldloadlistener, persistententitysectionmanager::updateChunkStatus, () -> { ++ return minecraftserver.overworld().getDataStorage(); ++ }); + this.chunkSource.getGeneratorState().ensureStructuresGenerated(); + this.portalForcer = new PortalForcer(this); + this.updateSkyBrightness(); + this.prepareWeather(); +- this.getWorldBorder().setAbsoluteMaxSize(server.getAbsoluteMaxWorldSize()); +- this.raids = this.getDataStorage().computeIfAbsent(Raids.factory(this), Raids.getFileId(this.dimensionTypeRegistration())); +- if (!server.isSingleplayer()) { +- serverLevelData.setGameType(server.getDefaultGameType()); ++ this.getWorldBorder().setAbsoluteMaxSize(minecraftserver.getAbsoluteMaxWorldSize()); ++ this.raids = (Raids) this.getDataStorage().computeIfAbsent(Raids.factory(this), Raids.getFileId(this.dimensionTypeRegistration())); ++ if (!minecraftserver.isSingleplayer()) { ++ iworlddataserver.setGameType(minecraftserver.getDefaultGameType()); + } + +- long l = server.getWorldData().worldGenOptions().seed(); +- this.structureCheck = new StructureCheck( +- this.chunkSource.chunkScanner(), +- this.registryAccess(), +- server.getStructureManager(), +- dimension, +- chunkGenerator, +- this.chunkSource.randomState(), +- this, +- chunkGenerator.getBiomeSource(), +- l, +- fixerUpper +- ); +- this.structureManager = new StructureManager(this, server.getWorldData().worldGenOptions(), this.structureCheck); +- if (this.dimension() == Level.END && this.dimensionTypeRegistration().is(BuiltinDimensionTypes.END)) { +- this.dragonFight = new EndDragonFight(this, l, server.getWorldData().endDragonFightData()); ++ long l = minecraftserver.getWorldData().worldGenOptions().seed(); ++ ++ this.structureCheck = new StructureCheck(this.chunkSource.chunkScanner(), this.registryAccess(), minecraftserver.getStructureManager(), resourcekey, chunkgenerator, this.chunkSource.randomState(), this, chunkgenerator.getBiomeSource(), l, datafixer); ++ this.structureManager = new StructureManager(this, this.serverLevelData.worldGenOptions(), structureCheck); // CraftBukkit ++ if ((this.dimension() == Level.END && this.dimensionTypeRegistration().is(BuiltinDimensionTypes.END)) || env == org.bukkit.World.Environment.THE_END) { // CraftBukkit - Allow to create EnderDragonBattle in default and custom END ++ this.dragonFight = new EndDragonFight(this, this.serverLevelData.worldGenOptions().seed(), this.serverLevelData.endDragonFightData()); // CraftBukkit + } else { + this.dragonFight = null; + } + + this.sleepStatus = new SleepStatus(); + this.gameEventDispatcher = new GameEventDispatcher(this); +- this.randomSequences = Objects.requireNonNullElseGet( +- randomSequences, () -> this.getDataStorage().computeIfAbsent(RandomSequences.factory(l), "random_sequences") +- ); ++ this.randomSequences = (RandomSequences) Objects.requireNonNullElseGet(randomsequences, () -> { ++ return (RandomSequences) this.getDataStorage().computeIfAbsent(RandomSequences.factory(l), "random_sequences"); ++ }); ++ this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit + } + ++ /** @deprecated */ + @Deprecated + @VisibleForTesting + public void setDragonFight(@Nullable EndDragonFight dragonFight) { +@@ -307,25 +336,37 @@ + } + + public void tick(BooleanSupplier hasTimeLeft) { +- ProfilerFiller profiler = this.getProfiler(); ++ ProfilerFiller gameprofilerfiller = this.getProfiler(); ++ + this.handlingTick = true; +- TickRateManager tickRateManager = this.tickRateManager(); +- boolean flag = tickRateManager.runsNormally(); ++ TickRateManager tickratemanager = this.tickRateManager(); ++ boolean flag = tickratemanager.runsNormally(); ++ + if (flag) { +- profiler.push("world border"); ++ gameprofilerfiller.push("world border"); + this.getWorldBorder().tick(); +- profiler.popPush("weather"); ++ gameprofilerfiller.popPush("weather"); + this.advanceWeatherCycle(); + } + +- int _int = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE); +- if (this.sleepStatus.areEnoughSleeping(_int) && this.sleepStatus.areEnoughDeepSleeping(_int, this.players)) { ++ int i = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE); ++ long j; ++ ++ if (this.sleepStatus.areEnoughSleeping(i) && this.sleepStatus.areEnoughDeepSleeping(i, this.players)) { ++ // CraftBukkit start ++ j = this.levelData.getDayTime() + 24000L; ++ TimeSkipEvent event = new TimeSkipEvent(this.getWorld(), TimeSkipEvent.SkipReason.NIGHT_SKIP, (j - j % 24000L) - this.getDayTime()); + if (this.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { +- long l = this.levelData.getDayTime() + 24000L; +- this.setDayTime(l - l % 24000L); ++ getCraftServer().getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ this.setDayTime(this.getDayTime() + event.getSkipAmount()); ++ } + } + +- this.wakeUpAllPlayers(); ++ if (!event.isCancelled()) { ++ this.wakeUpAllPlayers(); ++ } ++ // CraftBukkit end + if (this.getGameRules().getBoolean(GameRules.RULE_WEATHER_CYCLE) && this.isRaining()) { + this.resetWeatherCycle(); + } +@@ -336,75 +377,77 @@ + this.tickTime(); + } + +- profiler.popPush("tickPending"); ++ gameprofilerfiller.popPush("tickPending"); + if (!this.isDebug() && flag) { +- long l = this.getGameTime(); +- profiler.push("blockTicks"); +- this.blockTicks.tick(l, 65536, this::tickBlock); +- profiler.popPush("fluidTicks"); +- this.fluidTicks.tick(l, 65536, this::tickFluid); +- profiler.pop(); ++ j = this.getGameTime(); ++ gameprofilerfiller.push("blockTicks"); ++ this.blockTicks.tick(j, 65536, this::tickBlock); ++ gameprofilerfiller.popPush("fluidTicks"); ++ this.fluidTicks.tick(j, 65536, this::tickFluid); ++ gameprofilerfiller.pop(); + } + +- profiler.popPush("raid"); ++ gameprofilerfiller.popPush("raid"); + if (flag) { + this.raids.tick(); + } + +- profiler.popPush("chunkSource"); ++ gameprofilerfiller.popPush("chunkSource"); + this.getChunkSource().tick(hasTimeLeft, true); +- profiler.popPush("blockEvents"); ++ gameprofilerfiller.popPush("blockEvents"); + if (flag) { + this.runBlockEvents(); + } + + this.handlingTick = false; +- profiler.pop(); +- boolean flag1 = !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); ++ gameprofilerfiller.pop(); ++ boolean flag1 = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players ++ + if (flag1) { + this.resetEmptyTime(); + } + + if (flag1 || this.emptyTime++ < 300) { +- profiler.push("entities"); ++ gameprofilerfiller.push("entities"); + if (this.dragonFight != null && flag) { +- profiler.push("dragonFight"); ++ gameprofilerfiller.push("dragonFight"); + this.dragonFight.tick(); +- profiler.pop(); ++ gameprofilerfiller.pop(); + } + +- this.entityTickList.forEach(entity -> { ++ this.entityTickList.forEach((entity) -> { + if (!entity.isRemoved()) { +- if (this.shouldDiscardEntity(entity)) { ++ if (false && this.shouldDiscardEntity(entity)) { // CraftBukkit - We prevent spawning in general, so this butchering is not needed + entity.discard(); +- } else if (!tickRateManager.isEntityFrozen(entity)) { +- profiler.push("checkDespawn"); ++ } else if (!tickratemanager.isEntityFrozen(entity)) { ++ gameprofilerfiller.push("checkDespawn"); + entity.checkDespawn(); +- profiler.pop(); ++ gameprofilerfiller.pop(); + if (this.chunkSource.chunkMap.getDistanceManager().inEntityTickingRange(entity.chunkPosition().toLong())) { +- Entity vehicle = entity.getVehicle(); +- if (vehicle != null) { +- if (!vehicle.isRemoved() && vehicle.hasPassenger(entity)) { ++ Entity entity1 = entity.getVehicle(); ++ ++ if (entity1 != null) { ++ if (!entity1.isRemoved() && entity1.hasPassenger(entity)) { + return; + } + + entity.stopRiding(); + } + +- profiler.push("tick"); ++ gameprofilerfiller.push("tick"); + this.guardEntityTick(this::tickNonPassenger, entity); +- profiler.pop(); ++ gameprofilerfiller.pop(); + } + } + } + }); +- profiler.pop(); ++ gameprofilerfiller.pop(); + this.tickBlockEntities(); + } + +- profiler.push("entityManagement"); ++ gameprofilerfiller.push("entityManagement"); + this.entityManager.tick(); +- profiler.pop(); ++ gameprofilerfiller.pop(); + } + + @Override +@@ -414,12 +457,14 @@ + + protected void tickTime() { + if (this.tickTime) { +- long l = this.levelData.getGameTime() + 1L; +- this.serverLevelData.setGameTime(l); +- this.serverLevelData.getScheduledEvents().tick(this.server, l); ++ long i = this.levelData.getGameTime() + 1L; ++ ++ this.serverLevelData.setGameTime(i); ++ this.serverLevelData.getScheduledEvents().tick(this.server, i); + if (this.levelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { + this.setDayTime(this.levelData.getDayTime() + 1L); + } ++ + } + } + +@@ -428,159 +473,180 @@ + } + + public void tickCustomSpawners(boolean spawnEnemies, boolean spawnFriendlies) { +- for (CustomSpawner customSpawner : this.customSpawners) { +- customSpawner.tick(this, spawnEnemies, spawnFriendlies); ++ Iterator iterator = this.customSpawners.iterator(); ++ ++ while (iterator.hasNext()) { ++ CustomSpawner mobspawner = (CustomSpawner) iterator.next(); ++ ++ mobspawner.tick(this, spawnEnemies, spawnFriendlies); + } ++ + } + + private boolean shouldDiscardEntity(Entity entity) { +- return !this.server.isSpawningAnimals() && (entity instanceof Animal || entity instanceof WaterAnimal) +- || !this.server.areNpcsEnabled() && entity instanceof Npc; ++ return !this.server.isSpawningAnimals() && (entity instanceof Animal || entity instanceof WaterAnimal) ? true : !this.server.areNpcsEnabled() && entity instanceof NPC; + } + + private void wakeUpAllPlayers() { + this.sleepStatus.removeAllSleepers(); +- this.players.stream().filter(LivingEntity::isSleeping).collect(Collectors.toList()).forEach(serverPlayer -> serverPlayer.stopSleepInBed(false, false)); ++ (this.players.stream().filter(LivingEntity::isSleeping).collect(Collectors.toList())).forEach((entityplayer) -> { // CraftBukkit - decompile error ++ entityplayer.stopSleepInBed(false, false); ++ }); + } + + public void tickChunk(LevelChunk chunk, int randomTickSpeed) { +- ChunkPos pos = chunk.getPos(); +- boolean isRaining = this.isRaining(); +- int minBlockX = pos.getMinBlockX(); +- int minBlockZ = pos.getMinBlockZ(); +- ProfilerFiller profiler = this.getProfiler(); +- profiler.push("thunder"); +- if (isRaining && this.isThundering() && this.random.nextInt(100000) == 0) { +- BlockPos blockPos = this.findLightningTargetAround(this.getBlockRandomPos(minBlockX, 0, minBlockZ, 15)); +- if (this.isRainingAt(blockPos)) { +- DifficultyInstance currentDifficultyAt = this.getCurrentDifficultyAt(blockPos); +- boolean flag = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) +- && this.random.nextDouble() < (double)currentDifficultyAt.getEffectiveDifficulty() * 0.01 +- && !this.getBlockState(blockPos.below()).is(Blocks.LIGHTNING_ROD); +- if (flag) { +- SkeletonHorse skeletonHorse = EntityType.SKELETON_HORSE.create(this); +- if (skeletonHorse != null) { +- skeletonHorse.setTrap(true); +- skeletonHorse.setAge(0); +- skeletonHorse.setPos((double)blockPos.getX(), (double)blockPos.getY(), (double)blockPos.getZ()); +- this.addFreshEntity(skeletonHorse); ++ ChunkPos chunkcoordintpair = chunk.getPos(); ++ boolean flag = this.isRaining(); ++ int j = chunkcoordintpair.getMinBlockX(); ++ int k = chunkcoordintpair.getMinBlockZ(); ++ ProfilerFiller gameprofilerfiller = this.getProfiler(); ++ ++ gameprofilerfiller.push("thunder"); ++ if (flag && this.isThundering() && this.random.nextInt(100000) == 0) { ++ BlockPos blockposition = this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15)); ++ ++ if (this.isRainingAt(blockposition)) { ++ DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); ++ boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * 0.01D && !this.getBlockState(blockposition.below()).is(Blocks.LIGHTNING_ROD); ++ ++ if (flag1) { ++ SkeletonHorse entityhorseskeleton = (SkeletonHorse) EntityType.SKELETON_HORSE.create(this); ++ ++ if (entityhorseskeleton != null) { ++ entityhorseskeleton.setTrap(true); ++ entityhorseskeleton.setAge(0); ++ entityhorseskeleton.setPos((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()); ++ this.addFreshEntity(entityhorseskeleton, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); // CraftBukkit + } + } + +- LightningBolt lightningBolt = EntityType.LIGHTNING_BOLT.create(this); +- if (lightningBolt != null) { +- lightningBolt.moveTo(Vec3.atBottomCenterOf(blockPos)); +- lightningBolt.setVisualOnly(flag); +- this.addFreshEntity(lightningBolt); ++ LightningBolt entitylightning = (LightningBolt) EntityType.LIGHTNING_BOLT.create(this); ++ ++ if (entitylightning != null) { ++ entitylightning.moveTo(Vec3.atBottomCenterOf(blockposition)); ++ entitylightning.setVisualOnly(flag1); ++ this.strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.WEATHER); // CraftBukkit + } + } + } + +- profiler.popPush("iceandsnow"); ++ gameprofilerfiller.popPush("iceandsnow"); + +- for (int i = 0; i < randomTickSpeed; i++) { ++ for (int l = 0; l < randomTickSpeed; ++l) { + if (this.random.nextInt(48) == 0) { +- this.tickPrecipitation(this.getBlockRandomPos(minBlockX, 0, minBlockZ, 15)); ++ this.tickPrecipitation(this.getBlockRandomPos(j, 0, k, 15)); + } + } + +- profiler.popPush("tickBlocks"); ++ gameprofilerfiller.popPush("tickBlocks"); + if (randomTickSpeed > 0) { +- LevelChunkSection[] sections = chunk.getSections(); ++ LevelChunkSection[] achunksection = chunk.getSections(); + +- for (int i1 = 0; i1 < sections.length; i1++) { +- LevelChunkSection levelChunkSection = sections[i1]; +- if (levelChunkSection.isRandomlyTicking()) { +- int sectionYFromSectionIndex = chunk.getSectionYFromSectionIndex(i1); +- int i2 = SectionPos.sectionToBlockCoord(sectionYFromSectionIndex); ++ for (int i1 = 0; i1 < achunksection.length; ++i1) { ++ LevelChunkSection chunksection = achunksection[i1]; + +- for (int i3 = 0; i3 < randomTickSpeed; i3++) { +- BlockPos blockRandomPos = this.getBlockRandomPos(minBlockX, i2, minBlockZ, 15); +- profiler.push("randomTick"); +- BlockState blockState = levelChunkSection.getBlockState( +- blockRandomPos.getX() - minBlockX, blockRandomPos.getY() - i2, blockRandomPos.getZ() - minBlockZ +- ); +- if (blockState.isRandomlyTicking()) { +- blockState.randomTick(this, blockRandomPos, this.random); ++ if (chunksection.isRandomlyTicking()) { ++ int j1 = chunk.getSectionYFromSectionIndex(i1); ++ int k1 = SectionPos.sectionToBlockCoord(j1); ++ ++ for (int l1 = 0; l1 < randomTickSpeed; ++l1) { ++ BlockPos blockposition1 = this.getBlockRandomPos(j, k1, k, 15); ++ ++ gameprofilerfiller.push("randomTick"); ++ IBlockData iblockdata = chunksection.getBlockState(blockposition1.getX() - j, blockposition1.getY() - k1, blockposition1.getZ() - k); ++ ++ if (iblockdata.isRandomlyTicking()) { ++ iblockdata.randomTick(this, blockposition1, this.random); + } + +- FluidState fluidState = blockState.getFluidState(); +- if (fluidState.isRandomlyTicking()) { +- fluidState.randomTick(this, blockRandomPos, this.random); ++ FluidState fluid = iblockdata.getFluidState(); ++ ++ if (fluid.isRandomlyTicking()) { ++ fluid.randomTick(this, blockposition1, this.random); + } + +- profiler.pop(); ++ gameprofilerfiller.pop(); + } + } + } + } + +- profiler.pop(); ++ gameprofilerfiller.pop(); + } + + @VisibleForTesting +- public void tickPrecipitation(BlockPos blockPos) { +- BlockPos heightmapPos = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, blockPos); +- BlockPos blockPos1 = heightmapPos.below(); +- Biome biome = this.getBiome(heightmapPos).value(); +- if (biome.shouldFreeze(this, blockPos1)) { +- this.setBlockAndUpdate(blockPos1, Blocks.ICE.defaultBlockState()); ++ public void tickPrecipitation(BlockPos blockposition) { ++ BlockPos blockposition1 = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, blockposition); ++ BlockPos blockposition2 = blockposition1.below(); ++ Biome biomebase = (Biome) this.getBiome(blockposition1).value(); ++ ++ if (biomebase.shouldFreeze(this, blockposition2)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition2, Blocks.ICE.defaultBlockState(), null); // CraftBukkit + } + + if (this.isRaining()) { +- int _int = this.getGameRules().getInt(GameRules.RULE_SNOW_ACCUMULATION_HEIGHT); +- if (_int > 0 && biome.shouldSnow(this, heightmapPos)) { +- BlockState blockState = this.getBlockState(heightmapPos); +- if (blockState.is(Blocks.SNOW)) { +- int i = blockState.getValue(SnowLayerBlock.LAYERS); +- if (i < Math.min(_int, 8)) { +- BlockState blockState1 = blockState.setValue(SnowLayerBlock.LAYERS, Integer.valueOf(i + 1)); +- Block.pushEntitiesUp(blockState, blockState1, this, heightmapPos); +- this.setBlockAndUpdate(heightmapPos, blockState1); ++ int i = this.getGameRules().getInt(GameRules.RULE_SNOW_ACCUMULATION_HEIGHT); ++ ++ if (i > 0 && biomebase.shouldSnow(this, blockposition1)) { ++ IBlockData iblockdata = this.getBlockState(blockposition1); ++ ++ if (iblockdata.is(Blocks.SNOW)) { ++ int j = (Integer) iblockdata.getValue(SnowLayerBlock.LAYERS); ++ ++ if (j < Math.min(i, 8)) { ++ IBlockData iblockdata1 = (IBlockData) iblockdata.setValue(SnowLayerBlock.LAYERS, j + 1); ++ ++ Block.pushEntitiesUp(iblockdata, iblockdata1, this, blockposition1); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, iblockdata1, null); // CraftBukkit + } + } else { +- this.setBlockAndUpdate(heightmapPos, Blocks.SNOW.defaultBlockState()); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, Blocks.SNOW.defaultBlockState(), null); // CraftBukkit + } + } + +- Biome.Precipitation precipitationAt = biome.getPrecipitationAt(blockPos1); +- if (precipitationAt != Biome.Precipitation.NONE) { +- BlockState blockState2 = this.getBlockState(blockPos1); +- blockState2.getBlock().handlePrecipitation(blockState2, this, blockPos1, precipitationAt); ++ Biome.Precipitation biomebase_precipitation = biomebase.getPrecipitationAt(blockposition2); ++ ++ if (biomebase_precipitation != Biome.Precipitation.NONE) { ++ IBlockData iblockdata2 = this.getBlockState(blockposition2); ++ ++ iblockdata2.getBlock().handlePrecipitation(iblockdata2, this, blockposition2, biomebase_precipitation); + } + } ++ + } + + private Optional findLightningRod(BlockPos pos) { +- Optional optional = this.getPoiManager() +- .findClosest( +- holder -> holder.is(PoiTypes.LIGHTNING_ROD), +- blockPos -> blockPos.getY() == this.getHeight(Heightmap.Types.WORLD_SURFACE, blockPos.getX(), blockPos.getZ()) - 1, +- pos, +- 128, +- PoiManager.Occupancy.ANY +- ); +- return optional.map(blockPos -> blockPos.above(1)); ++ Optional optional = this.getPoiManager().findClosest((holder) -> { ++ return holder.is(PoiTypes.LIGHTNING_ROD); ++ }, (blockposition1) -> { ++ return blockposition1.getY() == this.getHeight(Heightmap.Types.WORLD_SURFACE, blockposition1.getX(), blockposition1.getZ()) - 1; ++ }, pos, 128, PoiManager.Occupancy.ANY); ++ ++ return optional.map((blockposition1) -> { ++ return blockposition1.above(1); ++ }); + } + + protected BlockPos findLightningTargetAround(BlockPos pos) { +- BlockPos heightmapPos = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, pos); +- Optional optional = this.findLightningRod(heightmapPos); ++ BlockPos blockposition1 = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, pos); ++ Optional optional = this.findLightningRod(blockposition1); ++ + if (optional.isPresent()) { +- return optional.get(); ++ return (BlockPos) optional.get(); + } else { +- AABB aABB = AABB.encapsulatingFullBlocks(heightmapPos, new BlockPos(heightmapPos.atY(this.getMaxBuildHeight()))).inflate(3.0); +- List entitiesOfClass = this.getEntitiesOfClass( +- LivingEntity.class, aABB, livingEntity -> livingEntity != null && livingEntity.isAlive() && this.canSeeSky(livingEntity.blockPosition()) +- ); +- if (!entitiesOfClass.isEmpty()) { +- return entitiesOfClass.get(this.random.nextInt(entitiesOfClass.size())).blockPosition(); ++ AABB axisalignedbb = AABB.encapsulatingFullBlocks(blockposition1, new BlockPos(blockposition1.atY(this.getMaxBuildHeight()))).inflate(3.0D); ++ List list = this.getEntitiesOfClass(LivingEntity.class, axisalignedbb, (entityliving) -> { ++ return entityliving != null && entityliving.isAlive() && this.canSeeSky(entityliving.blockPosition()); ++ }); ++ ++ if (!list.isEmpty()) { ++ return ((LivingEntity) list.get(this.random.nextInt(list.size()))).blockPosition(); + } else { +- if (heightmapPos.getY() == this.getMinBuildHeight() - 1) { +- heightmapPos = heightmapPos.above(2); ++ if (blockposition1.getY() == this.getMinBuildHeight() - 1) { ++ blockposition1 = blockposition1.above(2); + } + +- return heightmapPos; ++ return blockposition1; + } + } + } +@@ -596,17 +662,23 @@ + private void announceSleepStatus() { + if (this.canSleepThroughNights()) { + if (!this.getServer().isSingleplayer() || this.getServer().isPublished()) { +- int _int = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE); +- Component component; +- if (this.sleepStatus.areEnoughSleeping(_int)) { +- component = Component.translatable("sleep.skipping_night"); ++ int i = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE); ++ MutableComponent ichatmutablecomponent; ++ ++ if (this.sleepStatus.areEnoughSleeping(i)) { ++ ichatmutablecomponent = Component.translatable("sleep.skipping_night"); + } else { +- component = Component.translatable("sleep.players_sleeping", this.sleepStatus.amountSleeping(), this.sleepStatus.sleepersNeeded(_int)); ++ ichatmutablecomponent = Component.translatable("sleep.players_sleeping", this.sleepStatus.amountSleeping(), this.sleepStatus.sleepersNeeded(i)); + } + +- for (ServerPlayer serverPlayer : this.players) { +- serverPlayer.displayClientMessage(component, true); ++ Iterator iterator = this.players.iterator(); ++ ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ entityplayer.displayClientMessage(ichatmutablecomponent, true); + } ++ + } + } + } +@@ -615,6 +687,7 @@ + if (!this.players.isEmpty() && this.sleepStatus.update(this.players)) { + this.announceSleepStatus(); + } ++ + } + + @Override +@@ -623,47 +696,51 @@ + } + + private void advanceWeatherCycle() { +- boolean isRaining = this.isRaining(); ++ boolean flag = this.isRaining(); ++ + if (this.dimensionType().hasSkyLight()) { + if (this.getGameRules().getBoolean(GameRules.RULE_WEATHER_CYCLE)) { +- int clearWeatherTime = this.serverLevelData.getClearWeatherTime(); +- int thunderTime = this.serverLevelData.getThunderTime(); +- int rainTime = this.serverLevelData.getRainTime(); +- boolean isThundering = this.levelData.isThundering(); +- boolean isRaining1 = this.levelData.isRaining(); +- if (clearWeatherTime > 0) { +- clearWeatherTime--; +- thunderTime = isThundering ? 0 : 1; +- rainTime = isRaining1 ? 0 : 1; +- isThundering = false; +- isRaining1 = false; ++ int i = this.serverLevelData.getClearWeatherTime(); ++ int j = this.serverLevelData.getThunderTime(); ++ int k = this.serverLevelData.getRainTime(); ++ boolean flag1 = this.levelData.isThundering(); ++ boolean flag2 = this.levelData.isRaining(); ++ ++ if (i > 0) { ++ --i; ++ j = flag1 ? 0 : 1; ++ k = flag2 ? 0 : 1; ++ flag1 = false; ++ flag2 = false; + } else { +- if (thunderTime > 0) { +- if (--thunderTime == 0) { +- isThundering = !isThundering; ++ if (j > 0) { ++ --j; ++ if (j == 0) { ++ flag1 = !flag1; + } +- } else if (isThundering) { +- thunderTime = THUNDER_DURATION.sample(this.random); ++ } else if (flag1) { ++ j = ServerLevel.THUNDER_DURATION.sample(this.random); + } else { +- thunderTime = THUNDER_DELAY.sample(this.random); ++ j = ServerLevel.THUNDER_DELAY.sample(this.random); + } + +- if (rainTime > 0) { +- if (--rainTime == 0) { +- isRaining1 = !isRaining1; ++ if (k > 0) { ++ --k; ++ if (k == 0) { ++ flag2 = !flag2; + } +- } else if (isRaining1) { +- rainTime = RAIN_DURATION.sample(this.random); ++ } else if (flag2) { ++ k = ServerLevel.RAIN_DURATION.sample(this.random); + } else { +- rainTime = RAIN_DELAY.sample(this.random); ++ k = ServerLevel.RAIN_DELAY.sample(this.random); + } + } + +- this.serverLevelData.setThunderTime(thunderTime); +- this.serverLevelData.setRainTime(rainTime); +- this.serverLevelData.setClearWeatherTime(clearWeatherTime); +- this.serverLevelData.setThundering(isThundering); +- this.serverLevelData.setRaining(isRaining1); ++ this.serverLevelData.setThunderTime(j); ++ this.serverLevelData.setRainTime(k); ++ this.serverLevelData.setClearWeatherTime(i); ++ this.serverLevelData.setThundering(flag1); ++ this.serverLevelData.setRaining(flag2); + } + + this.oThunderLevel = this.thunderLevel; +@@ -684,36 +761,67 @@ + this.rainLevel = Mth.clamp(this.rainLevel, 0.0F, 1.0F); + } + ++ /* CraftBukkit start + if (this.oRainLevel != this.rainLevel) { +- this.server +- .getPlayerList() +- .broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, this.rainLevel), this.dimension()); ++ this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.RAIN_LEVEL_CHANGE, this.rainLevel), this.dimension()); + } + + if (this.oThunderLevel != this.thunderLevel) { +- this.server +- .getPlayerList() +- .broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, this.thunderLevel), this.dimension()); ++ this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, this.thunderLevel), this.dimension()); + } + +- if (isRaining != this.isRaining()) { +- if (isRaining) { +- this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.STOP_RAINING, 0.0F)); ++ if (flag != this.isRaining()) { ++ if (flag) { ++ this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.STOP_RAINING, 0.0F)); + } else { +- this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.START_RAINING, 0.0F)); ++ this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.START_RAINING, 0.0F)); + } + +- this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, this.rainLevel)); +- this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, this.thunderLevel)); ++ this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.RAIN_LEVEL_CHANGE, this.rainLevel)); ++ this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, this.thunderLevel)); + } ++ // */ ++ for (int idx = 0; idx < this.players.size(); ++idx) { ++ if (((ServerPlayer) this.players.get(idx)).level() == this) { ++ ((ServerPlayer) this.players.get(idx)).tickWeather(); ++ } ++ } ++ ++ if (flag != this.isRaining()) { ++ // Only send weather packets to those affected ++ for (int idx = 0; idx < this.players.size(); ++idx) { ++ if (((ServerPlayer) this.players.get(idx)).level() == this) { ++ ((ServerPlayer) this.players.get(idx)).setPlayerWeather((!flag ? WeatherType.DOWNFALL : WeatherType.CLEAR), false); ++ } ++ } ++ } ++ for (int idx = 0; idx < this.players.size(); ++idx) { ++ if (((ServerPlayer) this.players.get(idx)).level() == this) { ++ ((ServerPlayer) this.players.get(idx)).updateWeather(this.oRainLevel, this.rainLevel, this.oThunderLevel, this.thunderLevel); ++ } ++ } ++ // CraftBukkit end ++ + } + + @VisibleForTesting + public void resetWeatherCycle() { +- this.serverLevelData.setRainTime(0); ++ // CraftBukkit start + this.serverLevelData.setRaining(false); +- this.serverLevelData.setThunderTime(0); ++ // If we stop due to everyone sleeping we should reset the weather duration to some other random value. ++ // Not that everyone ever manages to get the whole server to sleep at the same time.... ++ if (!this.serverLevelData.isRaining()) { ++ this.serverLevelData.setRainTime(0); ++ } ++ // CraftBukkit end + this.serverLevelData.setThundering(false); ++ // CraftBukkit start ++ // If we stop due to everyone sleeping we should reset the weather duration to some other random value. ++ // Not that everyone ever manages to get the whole server to sleep at the same time.... ++ if (!this.serverLevelData.isThundering()) { ++ this.serverLevelData.setThunderTime(0); ++ } ++ // CraftBukkit end + } + + public void resetEmptyTime() { +@@ -721,48 +829,70 @@ + } + + private void tickFluid(BlockPos pos, Fluid fluid) { +- FluidState fluidState = this.getFluidState(pos); +- if (fluidState.is(fluid)) { +- fluidState.tick(this, pos); ++ FluidState fluid = this.getFluidState(pos); ++ ++ if (fluid.is(fluid)) { ++ fluid.tick(this, pos); + } ++ + } + + private void tickBlock(BlockPos pos, Block block) { +- BlockState blockState = this.getBlockState(pos); +- if (blockState.is(block)) { +- blockState.tick(this, pos, this.random); ++ IBlockData iblockdata = this.getBlockState(pos); ++ ++ if (iblockdata.is(block)) { ++ iblockdata.tick(this, pos, this.random); + } ++ + } + + public void tickNonPassenger(Entity entity) { + entity.setOldPosAndRot(); +- ProfilerFiller profiler = this.getProfiler(); +- entity.tickCount++; +- this.getProfiler().push(() -> BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()).toString()); +- profiler.incrementCounter("tickNonPassenger"); ++ ProfilerFiller gameprofilerfiller = this.getProfiler(); ++ ++ ++entity.tickCount; ++ this.getProfiler().push(() -> { ++ return BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()).toString(); ++ }); ++ gameprofilerfiller.incrementCounter("tickNonPassenger"); + entity.tick(); ++ entity.postTick(); // CraftBukkit + this.getProfiler().pop(); ++ Iterator iterator = entity.getPassengers().iterator(); + +- for (Entity entity1 : entity.getPassengers()) { ++ while (iterator.hasNext()) { ++ Entity entity1 = (Entity) iterator.next(); ++ + this.tickPassenger(entity, entity1); + } ++ + } + + private void tickPassenger(Entity ridingEntity, Entity passengerEntity) { +- if (passengerEntity.isRemoved() || passengerEntity.getVehicle() != ridingEntity) { +- passengerEntity.stopRiding(); +- } else if (passengerEntity instanceof Player || this.entityTickList.contains(passengerEntity)) { +- passengerEntity.setOldPosAndRot(); +- passengerEntity.tickCount++; +- ProfilerFiller profiler = this.getProfiler(); +- profiler.push(() -> BuiltInRegistries.ENTITY_TYPE.getKey(passengerEntity.getType()).toString()); +- profiler.incrementCounter("tickPassenger"); +- passengerEntity.rideTick(); +- profiler.pop(); ++ if (!passengerEntity.isRemoved() && passengerEntity.getVehicle() == ridingEntity) { ++ if (passengerEntity instanceof Player || this.entityTickList.contains(passengerEntity)) { ++ passengerEntity.setOldPosAndRot(); ++ ++passengerEntity.tickCount; ++ ProfilerFiller gameprofilerfiller = this.getProfiler(); + +- for (Entity entity : passengerEntity.getPassengers()) { +- this.tickPassenger(passengerEntity, entity); ++ gameprofilerfiller.push(() -> { ++ return BuiltInRegistries.ENTITY_TYPE.getKey(passengerEntity.getType()).toString(); ++ }); ++ gameprofilerfiller.incrementCounter("tickPassenger"); ++ passengerEntity.rideTick(); ++ passengerEntity.postTick(); // CraftBukkit ++ gameprofilerfiller.pop(); ++ Iterator iterator = passengerEntity.getPassengers().iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity2 = (Entity) iterator.next(); ++ ++ this.tickPassenger(passengerEntity, entity2); ++ } ++ + } ++ } else { ++ passengerEntity.stopRiding(); + } + } + +@@ -772,8 +902,10 @@ + } + + public void save(@Nullable ProgressListener progress, boolean flush, boolean skipSave) { +- ServerChunkCache chunkSource = this.getChunkSource(); ++ ServerChunkCache chunkproviderserver = this.getChunkSource(); ++ + if (!skipSave) { ++ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit + if (progress != null) { + progress.progressStartNoAbort(Component.translatable("menu.savingLevel")); + } +@@ -783,18 +915,27 @@ + progress.progressStage(Component.translatable("menu.savingChunks")); + } + +- chunkSource.save(flush); ++ chunkproviderserver.save(flush); + if (flush) { + this.entityManager.saveAll(); + } else { + this.entityManager.autoSave(); + } ++ + } ++ ++ // CraftBukkit start - moved from MinecraftServer.saveChunks ++ ServerLevel worldserver1 = this; ++ ++ serverLevelData.setWorldBorder(worldserver1.getWorldBorder().createSettings()); ++ serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save()); ++ convertable.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData()); ++ // CraftBukkit end + } + + private void saveLevelData() { + if (this.dragonFight != null) { +- this.server.getWorldData().setEndDragonFightData(this.dragonFight.saveData()); ++ this.serverLevelData.setEndDragonFightData(this.dragonFight.saveData()); // CraftBukkit + } + + this.getChunkSource().getDataStorage().save(); +@@ -802,7 +943,8 @@ + + public List getEntities(EntityTypeTest typeTest, Predicate predicate) { + List list = Lists.newArrayList(); +- this.getEntities(typeTest, predicate, list); ++ ++ this.getEntities(typeTest, predicate, (List) list); + return list; + } + +@@ -811,20 +953,20 @@ + } + + public void getEntities(EntityTypeTest typeTest, Predicate predicate, List output, int maxResults) { +- this.getEntities().get(typeTest, value -> { +- if (predicate.test(value)) { +- output.add(value); ++ this.getEntities().get(typeTest, (entity) -> { ++ if (predicate.test(entity)) { ++ output.add(entity); + if (output.size() >= maxResults) { +- return AbortableIterationConsumer.Continuation.ABORT; ++ return AbortableIterationConsumer.a.ABORT; + } + } + +- return AbortableIterationConsumer.Continuation.CONTINUE; ++ return AbortableIterationConsumer.a.CONTINUE; + }); + } + + public List getDragons() { +- return this.getEntities(EntityType.ENDER_DRAGON, LivingEntity::isAlive); ++ return this.getEntities((EntityTypeTest) EntityType.ENDER_DRAGON, LivingEntity::isAlive); + } + + public List getPlayers(Predicate predicate) { +@@ -833,10 +975,13 @@ + + public List getPlayers(Predicate predicate, int maxResults) { + List list = Lists.newArrayList(); ++ Iterator iterator = this.players.iterator(); + +- for (ServerPlayer serverPlayer : this.players) { +- if (predicate.test(serverPlayer)) { +- list.add(serverPlayer); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ if (predicate.test(entityplayer)) { ++ list.add(entityplayer); + if (list.size() >= maxResults) { + return list; + } +@@ -848,23 +993,46 @@ + + @Nullable + public ServerPlayer getRandomPlayer() { +- List players = this.getPlayers(LivingEntity::isAlive); +- return players.isEmpty() ? null : players.get(this.random.nextInt(players.size())); ++ List list = this.getPlayers(LivingEntity::isAlive); ++ ++ return list.isEmpty() ? null : (ServerPlayer) list.get(this.random.nextInt(list.size())); + } + + @Override + public boolean addFreshEntity(Entity entity) { +- return this.addEntity(entity); ++ // CraftBukkit start ++ return this.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.DEFAULT); + } + ++ @Override ++ public boolean addFreshEntity(Entity entity, CreatureSpawnEvent.SpawnReason reason) { ++ return this.addEntity(entity, reason); ++ // CraftBukkit end ++ } ++ + public boolean addWithUUID(Entity entity) { +- return this.addEntity(entity); ++ // CraftBukkit start ++ return this.addWithUUID(entity, CreatureSpawnEvent.SpawnReason.DEFAULT); + } + ++ public boolean addWithUUID(Entity entity, CreatureSpawnEvent.SpawnReason reason) { ++ return this.addEntity(entity, reason); ++ // CraftBukkit end ++ } ++ + public void addDuringTeleport(Entity entity) { +- this.addEntity(entity); ++ // CraftBukkit start ++ // SPIGOT-6415: Don't call spawn event for entities which travel trough worlds, ++ // since it is only an implementation detail, that a new entity is created when ++ // they are traveling between worlds. ++ this.addDuringTeleport(entity, null); + } + ++ public void addDuringTeleport(Entity entity, CreatureSpawnEvent.SpawnReason reason) { ++ this.addEntity(entity, reason); ++ // CraftBukkit end ++ } ++ + public void addDuringCommandTeleport(ServerPlayer player) { + this.addPlayer(player); + } +@@ -882,30 +1050,48 @@ + } + + private void addPlayer(ServerPlayer player) { +- Entity entity = this.getEntities().get(player.getUUID()); ++ Entity entity = (Entity) this.getEntities().get(player.getUUID()); ++ + if (entity != null) { +- LOGGER.warn("Force-added player with duplicate UUID {}", player.getUUID()); ++ ServerLevel.LOGGER.warn("Force-added player with duplicate UUID {}", player.getUUID()); + entity.unRide(); +- this.removePlayerImmediately((ServerPlayer)entity, Entity.RemovalReason.DISCARDED); ++ this.removePlayerImmediately((ServerPlayer) entity, Entity.RemovalReason.DISCARDED); + } + + this.entityManager.addNewEntity(player); + } + +- private boolean addEntity(Entity entity) { ++ // CraftBukkit start ++ private boolean addEntity(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { + if (entity.isRemoved()) { +- LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityType.getKey(entity.getType())); ++ // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getKey(entity.getType())); // CraftBukkit + return false; + } else { ++ // SPIGOT-6415: Don't call spawn event when reason is null. For example when an entity teleports to a new world. ++ if (spawnReason != null && !CraftEventFactory.doEntityAddEventCalling(this, entity, spawnReason)) { ++ return false; ++ } ++ // CraftBukkit end ++ + return this.entityManager.addNewEntity(entity); + } + } + + public boolean tryAddFreshEntityWithPassengers(Entity entity) { +- if (entity.getSelfAndPassengers().map(Entity::getUUID).anyMatch(this.entityManager::isLoaded)) { ++ // CraftBukkit start ++ return this.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ public boolean tryAddFreshEntityWithPassengers(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ // CraftBukkit end ++ Stream stream = entity.getSelfAndPassengers().map(Entity::getUUID); // CraftBukkit - decompile error ++ PersistentEntitySectionManager persistententitysectionmanager = this.entityManager; ++ ++ Objects.requireNonNull(this.entityManager); ++ if (stream.anyMatch(persistententitysectionmanager::isLoaded)) { + return false; + } else { +- this.addFreshEntityWithPassengers(entity); ++ this.addFreshEntityWithPassengers(entity, reason); // CraftBukkit + return true; + } + } +@@ -919,50 +1105,62 @@ + player.remove(reason); + } + ++ // CraftBukkit start ++ public boolean strikeLightning(Entity entitylightning) { ++ return this.strikeLightning(entitylightning, LightningStrikeEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean strikeLightning(Entity entitylightning, LightningStrikeEvent.Cause cause) { ++ LightningStrikeEvent lightning = CraftEventFactory.callLightningStrikeEvent((org.bukkit.entity.LightningStrike) entitylightning.getBukkitEntity(), cause); ++ ++ if (lightning.isCancelled()) { ++ return false; ++ } ++ ++ return this.addFreshEntity(entitylightning); ++ } ++ // CraftBukkit end ++ + @Override + public void destroyBlockProgress(int breakerId, BlockPos pos, int progress) { +- for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) { +- if (serverPlayer != null && serverPlayer.level() == this && serverPlayer.getId() != breakerId) { +- double d = (double)pos.getX() - serverPlayer.getX(); +- double d1 = (double)pos.getY() - serverPlayer.getY(); +- double d2 = (double)pos.getZ() - serverPlayer.getZ(); +- if (d * d + d1 * d1 + d2 * d2 < 1024.0) { +- serverPlayer.connection.send(new ClientboundBlockDestructionPacket(breakerId, pos, progress)); ++ Iterator iterator = this.server.getPlayerList().getPlayers().iterator(); ++ ++ // CraftBukkit start ++ Player entityhuman = null; ++ Entity entity = this.getEntity(breakerId); ++ if (entity instanceof Player) entityhuman = (Player) entity; ++ // CraftBukkit end ++ ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ if (entityplayer != null && entityplayer.level() == this && entityplayer.getId() != breakerId) { ++ double d0 = (double) pos.getX() - entityplayer.getX(); ++ double d1 = (double) pos.getY() - entityplayer.getY(); ++ double d2 = (double) pos.getZ() - entityplayer.getZ(); ++ ++ // CraftBukkit start ++ if (entityhuman != null && !entityplayer.getBukkitEntity().canSee(entityhuman.getBukkitEntity())) { ++ continue; + } ++ // CraftBukkit end ++ ++ if (d0 * d0 + d1 * d1 + d2 * d2 < 1024.0D) { ++ entityplayer.connection.send(new ClientboundBlockDestructionPacket(breakerId, pos, progress)); ++ } + } + } ++ + } + + @Override +- public void playSeededSound( +- @Nullable Player player, double x, double y, double z, Holder sound, SoundSource source, float volume, float pitch, long seed +- ) { +- this.server +- .getPlayerList() +- .broadcast( +- player, +- x, +- y, +- z, +- (double)sound.value().getRange(volume), +- this.dimension(), +- new ClientboundSoundPacket(sound, source, x, y, z, volume, pitch, seed) +- ); ++ public void playSeededSound(@Nullable Player player, double x, double d1, double y, Holder holder, SoundSource z, float f, float sound, long source) { ++ this.server.getPlayerList().broadcast(player, x, d1, y, (double) ((SoundEvent) holder.value()).getRange(f), this.dimension(), new ClientboundSoundPacket(holder, z, x, d1, y, f, sound, source)); + } + + @Override + public void playSeededSound(@Nullable Player player, Entity entity, Holder sound, SoundSource category, float volume, float pitch, long seed) { +- this.server +- .getPlayerList() +- .broadcast( +- player, +- entity.getX(), +- entity.getY(), +- entity.getZ(), +- (double)sound.value().getRange(volume), +- this.dimension(), +- new ClientboundSoundEntityPacket(sound, category, entity, volume, pitch, seed) +- ); ++ this.server.getPlayerList().broadcast(player, entity.getX(), entity.getY(), entity.getZ(), (double) ((SoundEvent) sound.value()).getRange(volume), this.dimension(), new ClientboundSoundEntityPacket(sound, category, entity, volume, pitch, seed)); + } + + @Override +@@ -970,23 +1168,14 @@ + if (this.getGameRules().getBoolean(GameRules.RULE_GLOBAL_SOUND_EVENTS)) { + this.server.getPlayerList().broadcastAll(new ClientboundLevelEventPacket(id, pos, data, true)); + } else { +- this.levelEvent(null, id, pos, data); ++ this.levelEvent((Player) null, id, pos, data); + } ++ + } + + @Override + public void levelEvent(@Nullable Player player, int type, BlockPos pos, int data) { +- this.server +- .getPlayerList() +- .broadcast( +- player, +- (double)pos.getX(), +- (double)pos.getY(), +- (double)pos.getZ(), +- 64.0, +- this.dimension(), +- new ClientboundLevelEventPacket(type, pos, data, false) +- ); ++ this.server.getPlayerList().broadcast(player, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), 64.0D, this.dimension(), new ClientboundLevelEventPacket(type, pos, data, false)); + } + + public int getLogicalHeight() { +@@ -999,40 +1188,60 @@ + } + + @Override +- public void sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags) { ++ public void sendBlockUpdated(BlockPos pos, IBlockData oldState, IBlockData newState, int flags) { + if (this.isUpdatingNavigations) { +- String string = "recursive call to sendBlockUpdated"; ++ String s = "recursive call to sendBlockUpdated"; ++ + Util.logAndPauseIfInIde("recursive call to sendBlockUpdated", new IllegalStateException("recursive call to sendBlockUpdated")); + } + + this.getChunkSource().blockChanged(pos); +- VoxelShape collisionShape = oldState.getCollisionShape(this, pos); +- VoxelShape collisionShape1 = newState.getCollisionShape(this, pos); +- if (Shapes.joinIsNotEmpty(collisionShape, collisionShape1, BooleanOp.NOT_SAME)) { +- List list = new ObjectArrayList<>(); ++ VoxelShape voxelshape = oldState.getCollisionShape(this, pos); ++ VoxelShape voxelshape1 = newState.getCollisionShape(this, pos); + +- for (Mob mob : this.navigatingMobs) { +- PathNavigation navigation = mob.getNavigation(); +- if (navigation.shouldRecomputePath(pos)) { +- list.add(navigation); ++ if (Shapes.joinIsNotEmpty(voxelshape, voxelshape1, BooleanOp.NOT_SAME)) { ++ List list = new ObjectArrayList(); ++ Iterator iterator = this.navigatingMobs.iterator(); ++ ++ while (iterator.hasNext()) { ++ // CraftBukkit start - fix SPIGOT-6362 ++ Mob entityinsentient; ++ try { ++ entityinsentient = (Mob) iterator.next(); ++ } catch (java.util.ConcurrentModificationException ex) { ++ // This can happen because the pathfinder update below may trigger a chunk load, which in turn may cause more navigators to register ++ // In this case we just run the update again across all the iterators as the chunk will then be loaded ++ // As this is a relative edge case it is much faster than copying navigators (on either read or write) ++ sendBlockUpdated(pos, oldState, newState, flags); ++ return; + } ++ // CraftBukkit end ++ PathNavigation navigationabstract = entityinsentient.getNavigation(); ++ ++ if (navigationabstract.shouldRecomputePath(pos)) { ++ list.add(navigationabstract); ++ } + } + + try { + this.isUpdatingNavigations = true; ++ iterator = list.iterator(); + +- for (PathNavigation pathNavigation : list) { +- pathNavigation.recomputePath(); ++ while (iterator.hasNext()) { ++ PathNavigation navigationabstract1 = (PathNavigation) iterator.next(); ++ ++ navigationabstract1.recomputePath(); + } + } finally { + this.isUpdatingNavigations = false; + } ++ + } + } + + @Override + public void updateNeighborsAt(BlockPos pos, Block block) { +- this.neighborUpdater.updateNeighborsAtExceptFromFacing(pos, block, null); ++ this.neighborUpdater.updateNeighborsAtExceptFromFacing(pos, block, (Direction) null); + } + + @Override +@@ -1046,7 +1255,7 @@ + } + + @Override +- public void neighborChanged(BlockState state, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ public void neighborChanged(IBlockData state, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { + this.neighborUpdater.neighborChanged(state, pos, block, fromPos, isMoving); + } + +@@ -1066,44 +1275,25 @@ + } + + @Override +- public Explosion explode( +- @Nullable Entity entity, +- @Nullable DamageSource damageSource, +- @Nullable ExplosionDamageCalculator explosionDamageCalculator, +- double d, +- double d1, +- double d2, +- float f, +- boolean flag, +- Level.ExplosionInteraction explosionInteraction, +- ParticleOptions particleOptions, +- ParticleOptions particleOptions1, +- SoundEvent soundEvent +- ) { +- Explosion explosion = this.explode( +- entity, damageSource, explosionDamageCalculator, d, d1, d2, f, flag, explosionInteraction, false, particleOptions, particleOptions1, soundEvent +- ); ++ public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.a world_a, ParticleOptions particleparam, ParticleOptions particleparam1, SoundEvent soundeffect) { ++ Explosion explosion = this.explode(entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, world_a, false, particleparam, particleparam1, soundeffect); ++ // CraftBukkit start ++ if (explosion.wasCanceled) { ++ return explosion; ++ } ++ // CraftBukkit end ++ + if (!explosion.interactsWithBlocks()) { + explosion.clearToBlow(); + } + +- for (ServerPlayer serverPlayer : this.players) { +- if (serverPlayer.distanceToSqr(d, d1, d2) < 4096.0) { +- serverPlayer.connection +- .send( +- new ClientboundExplodePacket( +- d, +- d1, +- d2, +- f, +- explosion.getToBlow(), +- explosion.getHitPlayers().get(serverPlayer), +- explosion.getBlockInteraction(), +- explosion.getSmallExplosionParticles(), +- explosion.getLargeExplosionParticles(), +- explosion.getExplosionSound() +- ) +- ); ++ Iterator iterator = this.players.iterator(); ++ ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ if (entityplayer.distanceToSqr(d0, d1, d2) < 4096.0D) { ++ entityplayer.connection.send(new ClientboundExplodePacket(d0, d1, d2, f, explosion.getToBlow(), (Vec3) explosion.getHitPlayers().get(entityplayer), explosion.getBlockInteraction(), explosion.getSmallExplosionParticles(), explosion.getLargeExplosionParticles(), explosion.getExplosionSound())); + } + } + +@@ -1119,23 +1309,14 @@ + this.blockEventsToReschedule.clear(); + + while (!this.blockEvents.isEmpty()) { +- BlockEventData blockEventData = this.blockEvents.removeFirst(); +- if (this.shouldTickBlocksAt(blockEventData.pos())) { +- if (this.doBlockEvent(blockEventData)) { +- this.server +- .getPlayerList() +- .broadcast( +- null, +- (double)blockEventData.pos().getX(), +- (double)blockEventData.pos().getY(), +- (double)blockEventData.pos().getZ(), +- 64.0, +- this.dimension(), +- new ClientboundBlockEventPacket(blockEventData.pos(), blockEventData.block(), blockEventData.paramA(), blockEventData.paramB()) +- ); ++ BlockEventData blockactiondata = (BlockEventData) this.blockEvents.removeFirst(); ++ ++ if (this.shouldTickBlocksAt(blockactiondata.pos())) { ++ if (this.doBlockEvent(blockactiondata)) { ++ this.server.getPlayerList().broadcast((Player) null, (double) blockactiondata.pos().getX(), (double) blockactiondata.pos().getY(), (double) blockactiondata.pos().getZ(), 64.0D, this.dimension(), new ClientboundBlockEventPacket(blockactiondata.pos(), blockactiondata.block(), blockactiondata.paramA(), blockactiondata.paramB())); + } + } else { +- this.blockEventsToReschedule.add(blockEventData); ++ this.blockEventsToReschedule.add(blockactiondata); + } + } + +@@ -1143,8 +1324,9 @@ + } + + private boolean doBlockEvent(BlockEventData event) { +- BlockState blockState = this.getBlockState(event.pos()); +- return blockState.is(event.block()) && blockState.triggerEvent(this, event.pos(), event.paramA(), event.paramB()); ++ IBlockData iblockdata = this.getBlockState(event.pos()); ++ ++ return iblockdata.is(event.block()) ? iblockdata.triggerEvent(this, event.pos(), event.paramA(), event.paramB()) : false; + } + + @Override +@@ -1171,49 +1353,41 @@ + return this.server.getStructureManager(); + } + +- public int sendParticles( +- T type, double posX, double posY, double posZ, int particleCount, double xOffset, double yOffset, double zOffset, double speed +- ) { +- ClientboundLevelParticlesPacket clientboundLevelParticlesPacket = new ClientboundLevelParticlesPacket( +- type, false, posX, posY, posZ, (float)xOffset, (float)yOffset, (float)zOffset, (float)speed, particleCount +- ); +- int i = 0; ++ public int sendParticles(T type, double posX, double d1, double posY, int i, double posZ, double d4, double particleCount, double xOffset) { ++ // CraftBukkit - visibility api support ++ return sendParticles(null, type, posX, d1, posY, i, posZ, d4, particleCount, xOffset, false); ++ } + +- for (int i1 = 0; i1 < this.players.size(); i1++) { +- ServerPlayer serverPlayer = this.players.get(i1); +- if (this.sendParticles(serverPlayer, false, posX, posY, posZ, clientboundLevelParticlesPacket)) { +- i++; ++ public int sendParticles(ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { ++ ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(t0, force, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i); ++ // CraftBukkit end ++ int j = 0; ++ ++ for (int k = 0; k < this.players.size(); ++k) { ++ ServerPlayer entityplayer = (ServerPlayer) this.players.get(k); ++ if (sender != null && !entityplayer.getBukkitEntity().canSee(sender.getBukkitEntity())) continue; // CraftBukkit ++ ++ if (this.sendParticles(entityplayer, force, d0, d1, d2, packetplayoutworldparticles)) { // CraftBukkit ++ ++j; + } + } + +- return i; ++ return j; + } + +- public boolean sendParticles( +- ServerPlayer player, +- T type, +- boolean longDistance, +- double posX, +- double posY, +- double posZ, +- int particleCount, +- double xOffset, +- double yOffset, +- double zOffset, +- double speed +- ) { +- Packet packet = new ClientboundLevelParticlesPacket( +- type, longDistance, posX, posY, posZ, (float)xOffset, (float)yOffset, (float)zOffset, (float)speed, particleCount +- ); +- return this.sendParticles(player, longDistance, posX, posY, posZ, packet); ++ public boolean sendParticles(ServerPlayer player, T type, boolean longDistance, double posX, double d1, double posY, int i, double posZ, double d4, double particleCount, double xOffset) { ++ Packet packet = new ClientboundLevelParticlesPacket(type, longDistance, posX, d1, posY, (float) posZ, (float) d4, (float) particleCount, (float) xOffset, i); ++ ++ return this.sendParticles(player, longDistance, posX, d1, posY, packet); + } + +- private boolean sendParticles(ServerPlayer player, boolean longDistance, double posX, double posY, double posZ, Packet packet) { ++ private boolean sendParticles(ServerPlayer player, boolean longDistance, double posX, double d1, double posY, Packet packet) { + if (player.level() != this) { + return false; + } else { +- BlockPos blockPos = player.blockPosition(); +- if (blockPos.closerToCenterThan(new Vec3(posX, posY, posZ), longDistance ? 512.0 : 32.0)) { ++ BlockPos blockposition = player.blockPosition(); ++ ++ if (blockposition.closerToCenterThan(new Vec3(posX, d1, posY), longDistance ? 512.0D : 32.0D)) { + player.connection.send(packet); + return true; + } else { +@@ -1225,44 +1399,43 @@ + @Nullable + @Override + public Entity getEntity(int id) { +- return this.getEntities().get(id); ++ return (Entity) this.getEntities().get(id); + } + ++ /** @deprecated */ + @Deprecated + @Nullable + public Entity getEntityOrPart(int id) { +- Entity entity = this.getEntities().get(id); +- return entity != null ? entity : this.dragonParts.get(id); ++ Entity entity = (Entity) this.getEntities().get(id); ++ ++ return entity != null ? entity : (Entity) this.dragonParts.get(id); + } + + @Nullable + public Entity getEntity(UUID uniqueId) { +- return this.getEntities().get(uniqueId); ++ return (Entity) this.getEntities().get(uniqueId); + } + + @Nullable + public BlockPos findNearestMapStructure(TagKey structureTag, BlockPos pos, int radius, boolean skipExistingChunks) { +- if (!this.server.getWorldData().worldGenOptions().generateStructures()) { ++ if (!this.serverLevelData.worldGenOptions().generateStructures()) { // CraftBukkit + return null; + } else { +- Optional> tag = this.registryAccess().registryOrThrow(Registries.STRUCTURE).getTag(structureTag); +- if (tag.isEmpty()) { ++ Optional> optional = this.registryAccess().registryOrThrow(Registries.STRUCTURE).getTag(structureTag); ++ ++ if (optional.isEmpty()) { + return null; + } else { +- Pair> pair = this.getChunkSource() +- .getGenerator() +- .findNearestMapStructure(this, tag.get(), pos, radius, skipExistingChunks); +- return pair != null ? pair.getFirst() : null; ++ Pair> pair = this.getChunkSource().getGenerator().findNearestMapStructure(this, (HolderSet) optional.get(), pos, radius, skipExistingChunks); ++ ++ return pair != null ? (BlockPos) pair.getFirst() : null; + } + } + } + + @Nullable +- public Pair> findClosestBiome3d(Predicate> biomePredicate, BlockPos pos, int i, int i1, int i2) { +- return this.getChunkSource() +- .getGenerator() +- .getBiomeSource() +- .findClosestBiome3d(pos, i, i1, i2, biomePredicate, this.getChunkSource().randomState().sampler(), this); ++ public Pair> findClosestBiome3d(Predicate> biomePredicate, BlockPos pos, int i, int j, int k) { ++ return this.getChunkSource().getGenerator().getBiomeSource().findClosestBiome3d(pos, i, j, k, biomePredicate, this.getChunkSource().randomState().sampler(), this); + } + + @Override +@@ -1287,52 +1460,66 @@ + @Nullable + @Override + public MapItemSavedData getMapData(String mapName) { +- return this.getServer().overworld().getDataStorage().get(MapItemSavedData.factory(), mapName); ++ // CraftBukkit start ++ MapItemSavedData worldmap = (MapItemSavedData) this.getServer().overworld().getDataStorage().get(MapItemSavedData.factory(), mapName); ++ if (worldmap != null) { ++ worldmap.id = mapName; ++ } ++ return worldmap; ++ // CraftBukkit end + } + + @Override + public void setMapData(String mapName, MapItemSavedData data) { ++ // CraftBukkit start ++ data.id = mapName; ++ MapInitializeEvent event = new MapInitializeEvent(data.mapView); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ // CraftBukkit end + this.getServer().overworld().getDataStorage().set(mapName, data); + } + + @Override + public int getFreeMapId() { +- return this.getServer().overworld().getDataStorage().computeIfAbsent(MapIndex.factory(), "idcounts").getFreeAuxValueForMap(); ++ return ((MapIndex) this.getServer().overworld().getDataStorage().computeIfAbsent(MapIndex.factory(), "idcounts")).getFreeAuxValueForMap(); + } + + public void setDefaultSpawnPos(BlockPos pos, float angle) { +- ChunkPos chunkPos = new ChunkPos(new BlockPos(this.levelData.getXSpawn(), 0, this.levelData.getZSpawn())); ++ ChunkPos chunkcoordintpair = new ChunkPos(new BlockPos(this.levelData.getXSpawn(), 0, this.levelData.getZSpawn())); ++ + this.levelData.setSpawn(pos, angle); +- this.getChunkSource().removeRegionTicket(TicketType.START, chunkPos, 11, Unit.INSTANCE); ++ this.getChunkSource().removeRegionTicket(TicketType.START, chunkcoordintpair, 11, Unit.INSTANCE); + this.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(pos), 11, Unit.INSTANCE); + this.getServer().getPlayerList().broadcastAll(new ClientboundSetDefaultSpawnPositionPacket(pos, angle)); + } + + public LongSet getForcedChunks() { +- ForcedChunksSavedData forcedChunksSavedData = this.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks"); +- return (LongSet)(forcedChunksSavedData != null ? LongSets.unmodifiable(forcedChunksSavedData.getChunks()) : LongSets.EMPTY_SET); ++ ForcedChunksSavedData forcedchunk = (ForcedChunksSavedData) this.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks"); ++ ++ return (LongSet) (forcedchunk != null ? LongSets.unmodifiable(forcedchunk.getChunks()) : LongSets.EMPTY_SET); + } + + public boolean setChunkForced(int chunkX, int chunkZ, boolean add) { +- ForcedChunksSavedData forcedChunksSavedData = this.getDataStorage().computeIfAbsent(ForcedChunksSavedData.factory(), "chunks"); +- ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ); +- long l = chunkPos.toLong(); +- boolean flag; ++ ForcedChunksSavedData forcedchunk = (ForcedChunksSavedData) this.getDataStorage().computeIfAbsent(ForcedChunksSavedData.factory(), "chunks"); ++ ChunkPos chunkcoordintpair = new ChunkPos(chunkX, chunkZ); ++ long k = chunkcoordintpair.toLong(); ++ boolean flag1; ++ + if (add) { +- flag = forcedChunksSavedData.getChunks().add(l); +- if (flag) { ++ flag1 = forcedchunk.getChunks().add(k); ++ if (flag1) { + this.getChunk(chunkX, chunkZ); + } + } else { +- flag = forcedChunksSavedData.getChunks().remove(l); ++ flag1 = forcedchunk.getChunks().remove(k); + } + +- forcedChunksSavedData.setDirty(flag); +- if (flag) { +- this.getChunkSource().updateChunkForced(chunkPos, add); ++ forcedchunk.setDirty(flag1); ++ if (flag1) { ++ this.getChunkSource().updateChunkForced(chunkcoordintpair, add); + } + +- return flag; ++ return flag1; + } + + @Override +@@ -1341,19 +1528,25 @@ + } + + @Override +- public void onBlockStateChange(BlockPos pos, BlockState blockState, BlockState newState) { ++ public void onBlockStateChange(BlockPos pos, IBlockData blockState, IBlockData newState) { + Optional> optional = PoiTypes.forState(blockState); + Optional> optional1 = PoiTypes.forState(newState); ++ + if (!Objects.equals(optional, optional1)) { +- BlockPos blockPos = pos.immutable(); +- optional.ifPresent(holder -> this.getServer().execute(() -> { +- this.getPoiManager().remove(blockPos); +- DebugPackets.sendPoiRemovedPacket(this, blockPos); +- })); +- optional1.ifPresent(holder -> this.getServer().execute(() -> { +- this.getPoiManager().add(blockPos, (Holder)holder); +- DebugPackets.sendPoiAddedPacket(this, blockPos); +- })); ++ BlockPos blockposition1 = pos.immutable(); ++ ++ optional.ifPresent((holder) -> { ++ this.getServer().execute(() -> { ++ this.getPoiManager().remove(blockposition1); ++ DebugPackets.sendPoiRemovedPacket(this, blockposition1); ++ }); ++ }); ++ optional1.ifPresent((holder) -> { ++ this.getServer().execute(() -> { ++ this.getPoiManager().add(blockposition1, holder); ++ DebugPackets.sendPoiAddedPacket(this, blockposition1); ++ }); ++ }); + } + } + +@@ -1370,7 +1563,7 @@ + } + + public boolean isCloseToVillage(BlockPos pos, int sections) { +- return sections <= 6 && this.sectionsToVillage(SectionPos.of(pos)) <= sections; ++ return sections > 6 ? false : this.sectionsToVillage(SectionPos.of(pos)) <= sections; + } + + public int sectionsToVillage(SectionPos pos) { +@@ -1395,104 +1588,199 @@ + } + + public void saveDebugReport(Path path) throws IOException { +- ChunkMap chunkMap = this.getChunkSource().chunkMap; ++ ChunkMap playerchunkmap = this.getChunkSource().chunkMap; ++ BufferedWriter bufferedwriter = Files.newBufferedWriter(path.resolve("stats.txt")); + +- try (Writer bufferedWriter = Files.newBufferedWriter(path.resolve("stats.txt"))) { +- bufferedWriter.write(String.format(Locale.ROOT, "spawning_chunks: %d\n", chunkMap.getDistanceManager().getNaturalSpawnChunkCount())); +- NaturalSpawner.SpawnState lastSpawnState = this.getChunkSource().getLastSpawnState(); +- if (lastSpawnState != null) { +- for (Entry entry : lastSpawnState.getMobCategoryCounts().object2IntEntrySet()) { +- bufferedWriter.write(String.format(Locale.ROOT, "spawn_count.%s: %d\n", entry.getKey().getName(), entry.getIntValue())); ++ try { ++ bufferedwriter.write(String.format(Locale.ROOT, "spawning_chunks: %d\n", playerchunkmap.getDistanceManager().getNaturalSpawnChunkCount())); ++ NaturalSpawner.SpawnState spawnercreature_d = this.getChunkSource().getLastSpawnState(); ++ ++ if (spawnercreature_d != null) { ++ ObjectIterator objectiterator = spawnercreature_d.getMobCategoryCounts().object2IntEntrySet().iterator(); ++ ++ while (objectiterator.hasNext()) { ++ Entry entry = (Entry) objectiterator.next(); ++ ++ bufferedwriter.write(String.format(Locale.ROOT, "spawn_count.%s: %d\n", ((MobCategory) entry.getKey()).getName(), entry.getIntValue())); + } + } + +- bufferedWriter.write(String.format(Locale.ROOT, "entities: %s\n", this.entityManager.gatherStats())); +- bufferedWriter.write(String.format(Locale.ROOT, "block_entity_tickers: %d\n", this.blockEntityTickers.size())); +- bufferedWriter.write(String.format(Locale.ROOT, "block_ticks: %d\n", this.getBlockTicks().count())); +- bufferedWriter.write(String.format(Locale.ROOT, "fluid_ticks: %d\n", this.getFluidTicks().count())); +- bufferedWriter.write("distance_manager: " + chunkMap.getDistanceManager().getDebugStatus() + "\n"); +- bufferedWriter.write(String.format(Locale.ROOT, "pending_tasks: %d\n", this.getChunkSource().getPendingTasksCount())); ++ bufferedwriter.write(String.format(Locale.ROOT, "entities: %s\n", this.entityManager.gatherStats())); ++ bufferedwriter.write(String.format(Locale.ROOT, "block_entity_tickers: %d\n", this.blockEntityTickers.size())); ++ bufferedwriter.write(String.format(Locale.ROOT, "block_ticks: %d\n", this.getBlockTicks().count())); ++ bufferedwriter.write(String.format(Locale.ROOT, "fluid_ticks: %d\n", this.getFluidTicks().count())); ++ bufferedwriter.write("distance_manager: " + playerchunkmap.getDistanceManager().getDebugStatus() + "\n"); ++ bufferedwriter.write(String.format(Locale.ROOT, "pending_tasks: %d\n", this.getChunkSource().getPendingTasksCount())); ++ } catch (Throwable throwable) { ++ if (bufferedwriter != null) { ++ try { ++ bufferedwriter.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } + +- CrashReport crashReport = new CrashReport("Level dump", new Exception("dummy")); +- this.fillReportDetails(crashReport); ++ if (bufferedwriter != null) { ++ bufferedwriter.close(); ++ } + +- try (Writer bufferedWriter1 = Files.newBufferedWriter(path.resolve("example_crash.txt"))) { +- bufferedWriter1.write(crashReport.getFriendlyReport()); ++ CrashReport crashreport = new CrashReport("Level dump", new Exception("dummy")); ++ ++ this.fillReportDetails(crashreport); ++ BufferedWriter bufferedwriter1 = Files.newBufferedWriter(path.resolve("example_crash.txt")); ++ ++ try { ++ bufferedwriter1.write(crashreport.getFriendlyReport()); ++ } catch (Throwable throwable2) { ++ if (bufferedwriter1 != null) { ++ try { ++ bufferedwriter1.close(); ++ } catch (Throwable throwable3) { ++ throwable2.addSuppressed(throwable3); ++ } ++ } ++ ++ throw throwable2; + } + ++ if (bufferedwriter1 != null) { ++ bufferedwriter1.close(); ++ } ++ + Path path1 = path.resolve("chunks.csv"); ++ BufferedWriter bufferedwriter2 = Files.newBufferedWriter(path1); + +- try (Writer bufferedWriter2 = Files.newBufferedWriter(path1)) { +- chunkMap.dumpChunks(bufferedWriter2); ++ try { ++ playerchunkmap.dumpChunks(bufferedwriter2); ++ } catch (Throwable throwable4) { ++ if (bufferedwriter2 != null) { ++ try { ++ bufferedwriter2.close(); ++ } catch (Throwable throwable5) { ++ throwable4.addSuppressed(throwable5); ++ } ++ } ++ ++ throw throwable4; + } + ++ if (bufferedwriter2 != null) { ++ bufferedwriter2.close(); ++ } ++ + Path path2 = path.resolve("entity_chunks.csv"); ++ BufferedWriter bufferedwriter3 = Files.newBufferedWriter(path2); + +- try (Writer bufferedWriter3 = Files.newBufferedWriter(path2)) { +- this.entityManager.dumpSections(bufferedWriter3); ++ try { ++ this.entityManager.dumpSections(bufferedwriter3); ++ } catch (Throwable throwable6) { ++ if (bufferedwriter3 != null) { ++ try { ++ bufferedwriter3.close(); ++ } catch (Throwable throwable7) { ++ throwable6.addSuppressed(throwable7); ++ } ++ } ++ ++ throw throwable6; + } + ++ if (bufferedwriter3 != null) { ++ bufferedwriter3.close(); ++ } ++ + Path path3 = path.resolve("entities.csv"); ++ BufferedWriter bufferedwriter4 = Files.newBufferedWriter(path3); + +- try (Writer bufferedWriter4 = Files.newBufferedWriter(path3)) { +- dumpEntities(bufferedWriter4, this.getEntities().getAll()); ++ try { ++ dumpEntities(bufferedwriter4, this.getEntities().getAll()); ++ } catch (Throwable throwable8) { ++ if (bufferedwriter4 != null) { ++ try { ++ bufferedwriter4.close(); ++ } catch (Throwable throwable9) { ++ throwable8.addSuppressed(throwable9); ++ } ++ } ++ ++ throw throwable8; + } + ++ if (bufferedwriter4 != null) { ++ bufferedwriter4.close(); ++ } ++ + Path path4 = path.resolve("block_entities.csv"); ++ BufferedWriter bufferedwriter5 = Files.newBufferedWriter(path4); + +- try (Writer bufferedWriter5 = Files.newBufferedWriter(path4)) { +- this.dumpBlockEntityTickers(bufferedWriter5); ++ try { ++ this.dumpBlockEntityTickers(bufferedwriter5); ++ } catch (Throwable throwable10) { ++ if (bufferedwriter5 != null) { ++ try { ++ bufferedwriter5.close(); ++ } catch (Throwable throwable11) { ++ throwable10.addSuppressed(throwable11); ++ } ++ } ++ ++ throw throwable10; + } ++ ++ if (bufferedwriter5 != null) { ++ bufferedwriter5.close(); ++ } ++ + } + + private static void dumpEntities(Writer writer, Iterable entities) throws IOException { +- CsvOutput csvOutput = CsvOutput.builder() +- .addColumn("x") +- .addColumn("y") +- .addColumn("z") +- .addColumn("uuid") +- .addColumn("type") +- .addColumn("alive") +- .addColumn("display_name") +- .addColumn("custom_name") +- .build(writer); ++ CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("uuid").addColumn("type").addColumn("alive").addColumn("display_name").addColumn("custom_name").build(writer); ++ Iterator iterator = entities.iterator(); + +- for (Entity entity : entities) { +- Component customName = entity.getCustomName(); +- Component displayName = entity.getDisplayName(); +- csvOutput.writeRow( +- entity.getX(), +- entity.getY(), +- entity.getZ(), +- entity.getUUID(), +- BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()), +- entity.isAlive(), +- displayName.getString(), +- customName != null ? customName.getString() : null +- ); ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ Component ichatbasecomponent = entity.getCustomName(); ++ Component ichatbasecomponent1 = entity.getDisplayName(); ++ ++ csvwriter.writeRow(entity.getX(), entity.getY(), entity.getZ(), entity.getUUID(), BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()), entity.isAlive(), ichatbasecomponent1.getString(), ichatbasecomponent != null ? ichatbasecomponent.getString() : null); + } ++ + } + + private void dumpBlockEntityTickers(Writer output) throws IOException { +- CsvOutput csvOutput = CsvOutput.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("type").build(output); ++ CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("type").build(output); ++ Iterator iterator = this.blockEntityTickers.iterator(); + +- for (TickingBlockEntity tickingBlockEntity : this.blockEntityTickers) { +- BlockPos pos = tickingBlockEntity.getPos(); +- csvOutput.writeRow(pos.getX(), pos.getY(), pos.getZ(), tickingBlockEntity.getType()); ++ while (iterator.hasNext()) { ++ TickingBlockEntity tickingblockentity = (TickingBlockEntity) iterator.next(); ++ BlockPos blockposition = tickingblockentity.getPos(); ++ ++ csvwriter.writeRow(blockposition.getX(), blockposition.getY(), blockposition.getZ(), tickingblockentity.getType()); + } ++ + } + + @VisibleForTesting + public void clearBlockEvents(BoundingBox boundingBox) { +- this.blockEvents.removeIf(blockEventData -> boundingBox.isInside(blockEventData.pos())); ++ this.blockEvents.removeIf((blockactiondata) -> { ++ return boundingBox.isInside(blockactiondata.pos()); ++ }); + } + + @Override + public void blockUpdated(BlockPos pos, Block block) { + if (!this.isDebug()) { ++ // CraftBukkit start ++ if (populating) { ++ return; ++ } ++ // CraftBukkit end + this.updateNeighborsAt(pos, block); + } ++ + } + + @Override +@@ -1504,18 +1792,17 @@ + return this.getEntities().getAll(); + } + +- @Override + public String toString() { + return "ServerLevel[" + this.serverLevelData.getLevelName() + "]"; + } + + public boolean isFlat() { +- return this.server.getWorldData().isFlatWorld(); ++ return this.serverLevelData.isFlatWorld(); // CraftBukkit + } + + @Override + public long getSeed() { +- return this.server.getWorldData().worldGenOptions().seed(); ++ return this.serverLevelData.worldGenOptions().seed(); // CraftBukkit + } + + @Nullable +@@ -1530,53 +1817,65 @@ + + @VisibleForTesting + public String getWatchdogStats() { +- return String.format( +- Locale.ROOT, +- "players: %s, entities: %s [%s], block_entities: %d [%s], block_ticks: %d, fluid_ticks: %d, chunk_source: %s", +- this.players.size(), +- this.entityManager.gatherStats(), +- getTypeCount(this.entityManager.getEntityGetter().getAll(), entity -> BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()).toString()), +- this.blockEntityTickers.size(), +- getTypeCount(this.blockEntityTickers, TickingBlockEntity::getType), +- this.getBlockTicks().count(), +- this.getFluidTicks().count(), +- this.gatherChunkSourceStats() +- ); ++ return String.format(Locale.ROOT, "players: %s, entities: %s [%s], block_entities: %d [%s], block_ticks: %d, fluid_ticks: %d, chunk_source: %s", this.players.size(), this.entityManager.gatherStats(), getTypeCount(this.entityManager.getEntityGetter().getAll(), (entity) -> { ++ return BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()).toString(); ++ }), this.blockEntityTickers.size(), getTypeCount(this.blockEntityTickers, TickingBlockEntity::getType), this.getBlockTicks().count(), this.getFluidTicks().count(), this.gatherChunkSourceStats()); + } + + private static String getTypeCount(Iterable objects, Function typeGetter) { + try { +- Object2IntOpenHashMap map = new Object2IntOpenHashMap<>(); ++ Object2IntOpenHashMap object2intopenhashmap = new Object2IntOpenHashMap(); ++ Iterator iterator = objects.iterator(); // CraftBukkit - decompile error + +- for (T object : objects) { +- String string = typeGetter.apply(object); +- map.addTo(string, 1); ++ while (iterator.hasNext()) { ++ T t0 = iterator.next(); ++ String s = (String) typeGetter.apply(t0); ++ ++ object2intopenhashmap.addTo(s, 1); + } + +- return map.object2IntEntrySet() +- .stream() +- .sorted(Comparator., Integer>comparing(Entry::getIntValue).reversed()) +- .limit(5L) +- .map(entry -> entry.getKey() + ":" + entry.getIntValue()) +- .collect(Collectors.joining(",")); +- } catch (Exception var6) { ++ return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(Entry::getIntValue).reversed()).limit(5L).map((entry) -> { // CraftBukkit - decompile error ++ String s1 = (String) entry.getKey(); ++ ++ return s1 + ":" + entry.getIntValue(); ++ }).collect(Collectors.joining(",")); ++ } catch (Exception exception) { + return ""; + } + } + + public static void makeObsidianPlatform(ServerLevel serverLevel) { +- BlockPos blockPos = END_SPAWN_POINT; +- int x = blockPos.getX(); +- int i = blockPos.getY() - 2; +- int z = blockPos.getZ(); +- BlockPos.betweenClosed(x - 2, i + 1, z - 2, x + 2, i + 3, z + 2) +- .forEach(blockPos1 -> serverLevel.setBlockAndUpdate(blockPos1, Blocks.AIR.defaultBlockState())); +- BlockPos.betweenClosed(x - 2, i, z - 2, x + 2, i, z + 2) +- .forEach(blockPos1 -> serverLevel.setBlockAndUpdate(blockPos1, Blocks.OBSIDIAN.defaultBlockState())); ++ // CraftBukkit start ++ ServerLevel.makeObsidianPlatform(serverLevel, null); + } + ++ public static void makeObsidianPlatform(ServerLevel worldserver, Entity entity) { ++ // CraftBukkit end ++ BlockPos blockposition = ServerLevel.END_SPAWN_POINT; ++ int i = blockposition.getX(); ++ int j = blockposition.getY() - 2; ++ int k = blockposition.getZ(); ++ ++ // CraftBukkit start ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(worldserver); ++ BlockPos.betweenClosed(i - 2, j + 1, k - 2, i + 2, j + 3, k + 2).forEach((blockposition1) -> { ++ blockList.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3); ++ }); ++ BlockPos.betweenClosed(i - 2, j, k - 2, i + 2, j, k + 2).forEach((blockposition1) -> { ++ blockList.setBlock(blockposition1, Blocks.OBSIDIAN.defaultBlockState(), 3); ++ }); ++ org.bukkit.World bworld = worldserver.getWorld(); ++ org.bukkit.event.world.PortalCreateEvent portalEvent = new org.bukkit.event.world.PortalCreateEvent((List) (List) blockList.getList(), bworld, (entity == null) ? null : entity.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM); ++ ++ worldserver.getCraftServer().getPluginManager().callEvent(portalEvent); ++ if (!portalEvent.isCancelled()) { ++ blockList.updateList(); ++ } ++ // CraftBukkit end ++ } ++ + @Override +- protected LevelEntityGetter getEntities() { ++ public LevelEntityGetter getEntities() { + return this.entityManager.getEntityGetter(); + } + +@@ -1593,7 +1892,9 @@ + } + + public void onStructureStartsAvailable(ChunkAccess chunk) { +- this.server.execute(() -> this.structureCheck.onStructureLoad(chunk.getPos(), chunk.getAllStarts())); ++ this.server.execute(() -> { ++ this.structureCheck.onStructureLoad(chunk.getPos(), chunk.getAllStarts()); ++ }); + } + + @Override +@@ -1604,7 +1905,9 @@ + + @Override + public String gatherChunkSourceStats() { +- return "Chunks[S] W: " + this.chunkSource.gatherStats() + " E: " + this.entityManager.gatherStats(); ++ String s = this.chunkSource.gatherStats(); ++ ++ return "Chunks[S] W: " + s + " E: " + this.entityManager.gatherStats(); + } + + public boolean areEntitiesLoaded(long chunkPos) { +@@ -1642,88 +1945,114 @@ + + @Override + public CrashReportCategory fillReportDetails(CrashReport report) { +- CrashReportCategory crashReportCategory = super.fillReportDetails(report); +- crashReportCategory.setDetail("Loaded entity count", () -> String.valueOf(this.entityManager.count())); +- return crashReportCategory; ++ CrashReportCategory crashreportsystemdetails = super.fillReportDetails(report); ++ ++ crashreportsystemdetails.setDetail("Loaded entity count", () -> { ++ return String.valueOf(this.entityManager.count()); ++ }); ++ return crashreportsystemdetails; + } + +- final class EntityCallbacks implements LevelCallback { +- @Override +- public void onCreated(Entity entity) { +- } ++ private final class a implements LevelCallback { + +- @Override ++ a() {} ++ ++ public void onCreated(Entity entity) {} ++ + public void onDestroyed(Entity entity) { + ServerLevel.this.getScoreboard().entityRemoved(entity); + } + +- @Override + public void onTickingStart(Entity entity) { + ServerLevel.this.entityTickList.add(entity); + } + +- @Override + public void onTickingEnd(Entity entity) { + ServerLevel.this.entityTickList.remove(entity); + } + +- @Override + public void onTrackingStart(Entity entity) { + ServerLevel.this.getChunkSource().addEntity(entity); +- if (entity instanceof ServerPlayer serverPlayer) { +- ServerLevel.this.players.add(serverPlayer); ++ if (entity instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entity; ++ ++ ServerLevel.this.players.add(entityplayer); + ServerLevel.this.updateSleepingPlayerList(); + } + +- if (entity instanceof Mob mob) { ++ if (entity instanceof Mob) { ++ Mob entityinsentient = (Mob) entity; ++ + if (ServerLevel.this.isUpdatingNavigations) { +- String string = "onTrackingStart called during navigation iteration"; +- Util.logAndPauseIfInIde( +- "onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration") +- ); ++ String s = "onTrackingStart called during navigation iteration"; ++ ++ Util.logAndPauseIfInIde("onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")); + } + +- ServerLevel.this.navigatingMobs.add(mob); ++ ServerLevel.this.navigatingMobs.add(entityinsentient); + } + +- if (entity instanceof EnderDragon enderDragon) { +- for (EnderDragonPart enderDragonPart : enderDragon.getSubEntities()) { +- ServerLevel.this.dragonParts.put(enderDragonPart.getId(), enderDragonPart); ++ if (entity instanceof EnderDragon) { ++ EnderDragon entityenderdragon = (EnderDragon) entity; ++ EnderDragonPart[] aentitycomplexpart = entityenderdragon.getSubEntities(); ++ int i = aentitycomplexpart.length; ++ ++ for (int j = 0; j < i; ++j) { ++ EnderDragonPart entitycomplexpart = aentitycomplexpart[j]; ++ ++ ServerLevel.this.dragonParts.put(entitycomplexpart.getId(), entitycomplexpart); + } + } + + entity.updateDynamicGameEventListener(DynamicGameEventListener::add); ++ entity.inWorld = true; // CraftBukkit - Mark entity as in world ++ entity.valid = true; // CraftBukkit + } + +- @Override + public void onTrackingEnd(Entity entity) { + ServerLevel.this.getChunkSource().removeEntity(entity); +- if (entity instanceof ServerPlayer serverPlayer) { +- ServerLevel.this.players.remove(serverPlayer); ++ if (entity instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entity; ++ ++ ServerLevel.this.players.remove(entityplayer); + ServerLevel.this.updateSleepingPlayerList(); + } + +- if (entity instanceof Mob mob) { ++ if (entity instanceof Mob) { ++ Mob entityinsentient = (Mob) entity; ++ + if (ServerLevel.this.isUpdatingNavigations) { +- String string = "onTrackingStart called during navigation iteration"; +- Util.logAndPauseIfInIde( +- "onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration") +- ); ++ String s = "onTrackingStart called during navigation iteration"; ++ ++ Util.logAndPauseIfInIde("onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")); + } + +- ServerLevel.this.navigatingMobs.remove(mob); ++ ServerLevel.this.navigatingMobs.remove(entityinsentient); + } + +- if (entity instanceof EnderDragon enderDragon) { +- for (EnderDragonPart enderDragonPart : enderDragon.getSubEntities()) { +- ServerLevel.this.dragonParts.remove(enderDragonPart.getId()); ++ if (entity instanceof EnderDragon) { ++ EnderDragon entityenderdragon = (EnderDragon) entity; ++ EnderDragonPart[] aentitycomplexpart = entityenderdragon.getSubEntities(); ++ int i = aentitycomplexpart.length; ++ ++ for (int j = 0; j < i; ++j) { ++ EnderDragonPart entitycomplexpart = aentitycomplexpart[j]; ++ ++ ServerLevel.this.dragonParts.remove(entitycomplexpart.getId()); + } + } + + entity.updateDynamicGameEventListener(DynamicGameEventListener::remove); ++ // CraftBukkit start ++ entity.valid = false; ++ if (!(entity instanceof ServerPlayer)) { ++ for (ServerPlayer player : players) { ++ player.getBukkitEntity().onEntityRemove(entity); ++ } ++ } ++ // CraftBukkit end + } + +- @Override + public void onSectionChange(Entity entity) { + entity.updateDynamicGameEventListener(DynamicGameEventListener::move); + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/level/ServerPlayer.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/level/ServerPlayer.java.patch new file mode 100644 index 0000000000..349aee0517 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/level/ServerPlayer.java.patch @@ -0,0 +1,2591 @@ +--- a/net/minecraft/server/level/ServerPlayer.java ++++ b/net/minecraft/server/level/ServerPlayer.java +@@ -4,10 +4,14 @@ + import com.mojang.authlib.GameProfile; + import com.mojang.datafixers.util.Either; + import com.mojang.logging.LogUtils; ++import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; + import java.net.InetSocketAddress; ++import java.net.SocketAddress; + import java.util.Collection; ++import java.util.Iterator; + import java.util.List; ++import java.util.Objects; + import java.util.Optional; + import java.util.OptionalInt; + import java.util.Set; +@@ -35,9 +39,9 @@ + import net.minecraft.network.chat.CommonComponents; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.HoverEvent; ++import net.minecraft.network.chat.MutableComponent; + import net.minecraft.network.chat.OutgoingChatMessage; + import net.minecraft.network.chat.RemoteChatSession; +-import net.minecraft.network.chat.Style; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientboundAnimatePacket; + import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +@@ -91,8 +95,8 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.util.Unit; + import net.minecraft.world.Container; +-import net.minecraft.world.InteractionHand; +-import net.minecraft.world.MenuProvider; ++import net.minecraft.world.EnumHand; ++import net.minecraft.world.ITileInventory; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.effect.MobEffects; +@@ -115,6 +119,7 @@ + import net.minecraft.world.entity.projectile.AbstractArrow; + import net.minecraft.world.entity.vehicle.AbstractMinecart; + import net.minecraft.world.entity.vehicle.Boat; ++import net.minecraft.world.food.FoodData; + import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.inventory.ContainerListener; + import net.minecraft.world.inventory.ContainerSynchronizer; +@@ -128,6 +133,7 @@ + import net.minecraft.world.item.ServerItemCooldowns; + import net.minecraft.world.item.WrittenBookItem; + import net.minecraft.world.item.crafting.RecipeHolder; ++import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.item.trading.MerchantOffers; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.GameRules; +@@ -135,26 +141,53 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.ChestBlock; + import net.minecraft.world.level.block.HorizontalDirectionalBlock; + import net.minecraft.world.level.block.NetherPortalBlock; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.CommandBlockEntity; + import net.minecraft.world.level.block.entity.SignBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.border.WorldBorder; ++import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.portal.PortalInfo; +-import net.minecraft.world.level.storage.LevelData; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.scores.PlayerTeam; + import net.minecraft.world.scores.ScoreAccess; + import net.minecraft.world.scores.ScoreHolder; ++import org.slf4j.Logger; ++import net.minecraft.world.damagesource.CombatTracker; ++import net.minecraft.world.scores.Scoreboard; + import net.minecraft.world.scores.Team; + import net.minecraft.world.scores.criteria.ObjectiveCriteria; +-import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.WeatherType; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.CraftWorldBorder; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.event.CraftPortalEvent; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftDimensionUtil; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.entity.EntityExhaustionEvent; ++import org.bukkit.event.player.PlayerBedLeaveEvent; ++import org.bukkit.event.player.PlayerChangedMainHandEvent; ++import org.bukkit.event.player.PlayerChangedWorldEvent; ++import org.bukkit.event.player.PlayerLocaleChangeEvent; ++import org.bukkit.event.player.PlayerPortalEvent; ++import org.bukkit.event.player.PlayerSpawnChangeEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; ++import org.bukkit.event.player.PlayerToggleSneakEvent; ++import org.bukkit.inventory.MainHand; ++// CraftBukkit end + + public class ServerPlayer extends Player { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32; + private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10; +@@ -173,31 +206,31 @@ + private float lastSentHealth = -1.0E8F; + private int lastSentFood = -99999999; + private boolean lastFoodSaturationZero = true; +- private int lastSentExp = -99999999; +- private int spawnInvulnerableTime = 60; +- private ChatVisiblity chatVisibility = ChatVisiblity.FULL; +- private boolean canChatColor = true; +- private long lastActionTime = Util.getMillis(); ++ public int lastSentExp = -99999999; ++ public int spawnInvulnerableTime = 60; ++ private ChatVisiblity chatVisibility; ++ private boolean canChatColor; ++ private long lastActionTime; + @Nullable + private Entity camera; +- private boolean isChangingDimension; ++ public boolean isChangingDimension; + private boolean seenCredits; +- private final ServerRecipeBook recipeBook = new ServerRecipeBook(); ++ private final ServerRecipeBook recipeBook; + @Nullable + private Vec3 levitationStartPos; + private int levitationStartTime; + private boolean disconnected; +- private int requestedViewDistance = 2; +- private String language = "en_us"; ++ private int requestedViewDistance; ++ public String language = "en_us"; // CraftBukkit - default + @Nullable + private Vec3 startingToFallPosition; + @Nullable + private Vec3 enteredNetherPosition; + @Nullable + private Vec3 enteredLavaOnVehiclePosition; +- private SectionPos lastSectionPos = SectionPos.of(0, 0, 0); +- private ChunkTrackingView chunkTrackingView = ChunkTrackingView.EMPTY; +- private ResourceKey respawnDimension = Level.OVERWORLD; ++ private SectionPos lastSectionPos; ++ private ChunkTrackingView chunkTrackingView; ++ private ResourceKey respawnDimension; + @Nullable + private BlockPos respawnPosition; + private boolean respawnForced; +@@ -205,109 +238,182 @@ + private final TextFilter textFilter; + private boolean textFilteringEnabled; + private boolean allowsListing; +- private WardenSpawnTracker wardenSpawnTracker = new WardenSpawnTracker(0, 0, 0); +- private final ContainerSynchronizer containerSynchronizer = new ContainerSynchronizer() { +- @Override +- public void sendInitialData(AbstractContainerMenu container, NonNullList items, ItemStack carriedItem, int[] initialData) { +- ServerPlayer.this.connection +- .send(new ClientboundContainerSetContentPacket(container.containerId, container.incrementStateId(), items, carriedItem)); ++ private WardenSpawnTracker wardenSpawnTracker; ++ private final ContainerSynchronizer containerSynchronizer; ++ private final ContainerListener containerListener; ++ @Nullable ++ private RemoteChatSession chatSession; ++ private int containerCounter; ++ public boolean wonGame; + +- for (int i = 0; i < initialData.length; i++) { +- this.broadcastDataValue(container, i, initialData[i]); ++ // CraftBukkit start ++ public String displayName; ++ public Component listName; ++ public org.bukkit.Location compassTarget; ++ public int newExp = 0; ++ public int newLevel = 0; ++ public int newTotalExp = 0; ++ public boolean keepLevel = false; ++ public double maxHealthCache; ++ public boolean joining = true; ++ public boolean sentListPacket = false; ++ public String kickLeaveMessage = null; // SPIGOT-3034: Forward leave message to PlayerQuitEvent ++ // CraftBukkit end ++ ++ public ServerPlayer(MinecraftServer minecraftserver, ServerLevel worldserver, GameProfile gameprofile, ClientInformation clientinformation) { ++ super(worldserver, worldserver.getSharedSpawnPos(), worldserver.getSharedSpawnAngle(), gameprofile); ++ this.chatVisibility = ChatVisiblity.FULL; ++ this.canChatColor = true; ++ this.lastActionTime = Util.getMillis(); ++ this.recipeBook = new ServerRecipeBook(); ++ this.requestedViewDistance = 2; ++ this.language = "en_us"; ++ this.lastSectionPos = SectionPos.of(0, 0, 0); ++ this.chunkTrackingView = ChunkTrackingView.EMPTY; ++ this.respawnDimension = Level.OVERWORLD; ++ this.wardenSpawnTracker = new WardenSpawnTracker(0, 0, 0); ++ this.containerSynchronizer = new ContainerSynchronizer() { ++ @Override ++ public void sendInitialData(AbstractContainerMenu container, NonNullList items, ItemStack carriedItem, int[] initialData) { ++ ServerPlayer.this.connection.send(new ClientboundContainerSetContentPacket(container.containerId, container.incrementStateId(), items, carriedItem)); ++ ++ for (int i = 0; i < initialData.length; ++i) { ++ this.broadcastDataValue(container, i, initialData[i]); ++ } ++ + } +- } + +- @Override +- public void sendSlotChange(AbstractContainerMenu container, int slot, ItemStack itemStack) { +- ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(container.containerId, container.incrementStateId(), slot, itemStack)); +- } ++ @Override ++ public void sendSlotChange(AbstractContainerMenu container, int slot, ItemStack itemStack) { ++ ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(container.containerId, container.incrementStateId(), slot, itemStack)); ++ } + +- @Override +- public void sendCarriedChange(AbstractContainerMenu containerMenu, ItemStack stack) { +- ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(-1, containerMenu.incrementStateId(), -1, stack)); +- } ++ @Override ++ public void sendCarriedChange(AbstractContainerMenu containerMenu, ItemStack stack) { ++ ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(-1, containerMenu.incrementStateId(), -1, stack)); ++ } + +- @Override +- public void sendDataChange(AbstractContainerMenu container, int id, int value) { +- this.broadcastDataValue(container, id, value); +- } ++ @Override ++ public void sendDataChange(AbstractContainerMenu container, int id, int value) { ++ this.broadcastDataValue(container, id, value); ++ } + +- private void broadcastDataValue(AbstractContainerMenu container, int id, int value) { +- ServerPlayer.this.connection.send(new ClientboundContainerSetDataPacket(container.containerId, id, value)); +- } +- }; +- private final ContainerListener containerListener = new ContainerListener() { +- @Override +- public void slotChanged(AbstractContainerMenu containerToSend, int dataSlotIndex, ItemStack stack) { +- Slot slot = containerToSend.getSlot(dataSlotIndex); +- if (!(slot instanceof ResultSlot)) { +- if (slot.container == ServerPlayer.this.getInventory()) { +- CriteriaTriggers.INVENTORY_CHANGED.trigger(ServerPlayer.this, ServerPlayer.this.getInventory(), stack); ++ private void broadcastDataValue(AbstractContainerMenu container, int id, int value) { ++ ServerPlayer.this.connection.send(new ClientboundContainerSetDataPacket(container.containerId, id, value)); ++ } ++ }; ++ this.containerListener = new ContainerListener() { ++ @Override ++ public void slotChanged(AbstractContainerMenu containerToSend, int dataSlotIndex, ItemStack stack) { ++ Slot slot = containerToSend.getSlot(dataSlotIndex); ++ ++ if (!(slot instanceof ResultSlot)) { ++ if (slot.container == ServerPlayer.this.getInventory()) { ++ CriteriaTriggers.INVENTORY_CHANGED.trigger(ServerPlayer.this, ServerPlayer.this.getInventory(), stack); ++ } ++ + } + } +- } + +- @Override +- public void dataChanged(AbstractContainerMenu containerMenu, int dataSlotIndex, int value) { ++ @Override ++ public void dataChanged(AbstractContainerMenu containerMenu, int dataSlotIndex, int value) {} ++ }; ++ this.textFilter = minecraftserver.createTextFilterForPlayer(this); ++ this.gameMode = minecraftserver.createGameModeForPlayer(this); ++ this.server = minecraftserver; ++ this.stats = minecraftserver.getPlayerList().getPlayerStats(this); ++ this.advancements = minecraftserver.getPlayerList().getPlayerAdvancements(this); ++ this.setMaxUpStep(1.0F); ++ this.fudgeSpawnLocation(worldserver); ++ this.updateOptions(clientinformation); ++ ++ // CraftBukkit start ++ this.displayName = this.getScoreboardName(); ++ this.bukkitPickUpLoot = true; ++ this.maxHealthCache = this.getMaxHealth(); ++ } ++ ++ // Yes, this doesn't match Vanilla, but it's the best we can do for now. ++ // If this is an issue, PRs are welcome ++ public final BlockPos getSpawnPoint(ServerLevel worldserver) { ++ BlockPos blockposition = worldserver.getSharedSpawnPos(); ++ ++ if (worldserver.dimensionType().hasSkyLight() && worldserver.serverLevelData.getGameType() != GameType.ADVENTURE) { ++ int i = Math.max(0, this.server.getSpawnRadius(worldserver)); ++ int j = Mth.floor(worldserver.getWorldBorder().getDistanceToBorder((double) blockposition.getX(), (double) blockposition.getZ())); ++ ++ if (j < i) { ++ i = j; ++ } ++ ++ if (j <= 1) { ++ i = 1; ++ } ++ ++ long k = (long) (i * 2 + 1); ++ long l = k * k; ++ int i1 = l > 2147483647L ? Integer.MAX_VALUE : (int) l; ++ int j1 = this.getCoprime(i1); ++ int k1 = RandomSource.create().nextInt(i1); ++ ++ for (int l1 = 0; l1 < i1; ++l1) { ++ int i2 = (k1 + j1 * l1) % i1; ++ int j2 = i2 % (i * 2 + 1); ++ int k2 = i2 / (i * 2 + 1); ++ BlockPos blockposition1 = PlayerRespawnLogic.getOverworldRespawnPos(worldserver, blockposition.getX() + j2 - i, blockposition.getZ() + k2 - i); ++ ++ if (blockposition1 != null) { ++ return blockposition1; ++ } ++ } + } +- }; +- @Nullable +- private RemoteChatSession chatSession; +- private int containerCounter; +- public boolean wonGame; + +- public ServerPlayer(MinecraftServer minecraftServer, ServerLevel level, GameProfile gameProfile, ClientInformation clientInformation) { +- super(level, level.getSharedSpawnPos(), level.getSharedSpawnAngle(), gameProfile); +- this.textFilter = minecraftServer.createTextFilterForPlayer(this); +- this.gameMode = minecraftServer.createGameModeForPlayer(this); +- this.server = minecraftServer; +- this.stats = minecraftServer.getPlayerList().getPlayerStats(this); +- this.advancements = minecraftServer.getPlayerList().getPlayerAdvancements(this); +- this.setMaxUpStep(1.0F); +- this.fudgeSpawnLocation(level); +- this.updateOptions(clientInformation); ++ return blockposition; + } ++ // CraftBukkit end + + private void fudgeSpawnLocation(ServerLevel level) { +- BlockPos sharedSpawnPos = level.getSharedSpawnPos(); +- if (level.dimensionType().hasSkyLight() && level.getServer().getWorldData().getGameType() != GameType.ADVENTURE) { +- int max = Math.max(0, this.server.getSpawnRadius(level)); +- int floor = Mth.floor(level.getWorldBorder().getDistanceToBorder((double)sharedSpawnPos.getX(), (double)sharedSpawnPos.getZ())); +- if (floor < max) { +- max = floor; ++ BlockPos blockposition = level.getSharedSpawnPos(); ++ ++ if (level.dimensionType().hasSkyLight() && level.serverLevelData.getGameType() != GameType.ADVENTURE) { // CraftBukkit ++ int i = Math.max(0, this.server.getSpawnRadius(level)); ++ int j = Mth.floor(level.getWorldBorder().getDistanceToBorder((double) blockposition.getX(), (double) blockposition.getZ())); ++ ++ if (j < i) { ++ i = j; + } + +- if (floor <= 1) { +- max = 1; ++ if (j <= 1) { ++ i = 1; + } + +- long l = (long)(max * 2 + 1); +- long l1 = l * l; +- int i = l1 > 2147483647L ? Integer.MAX_VALUE : (int)l1; +- int coprime = this.getCoprime(i); +- int randomInt = RandomSource.create().nextInt(i); ++ long k = (long) (i * 2 + 1); ++ long l = k * k; ++ int i1 = l > 2147483647L ? Integer.MAX_VALUE : (int) l; ++ int j1 = this.getCoprime(i1); ++ int k1 = RandomSource.create().nextInt(i1); + +- for (int i1 = 0; i1 < i; i1++) { +- int i2 = (randomInt + coprime * i1) % i; +- int i3 = i2 % (max * 2 + 1); +- int i4 = i2 / (max * 2 + 1); +- BlockPos overworldRespawnPos = PlayerRespawnLogic.getOverworldRespawnPos( +- level, sharedSpawnPos.getX() + i3 - max, sharedSpawnPos.getZ() + i4 - max +- ); +- if (overworldRespawnPos != null) { +- this.moveTo(overworldRespawnPos, 0.0F, 0.0F); +- if (level.noCollision(this)) { ++ for (int l1 = 0; l1 < i1; ++l1) { ++ int i2 = (k1 + j1 * l1) % i1; ++ int j2 = i2 % (i * 2 + 1); ++ int k2 = i2 / (i * 2 + 1); ++ BlockPos blockposition1 = PlayerRespawnLogic.getOverworldRespawnPos(level, blockposition.getX() + j2 - i, blockposition.getZ() + k2 - i); ++ ++ if (blockposition1 != null) { ++ this.moveTo(blockposition1, 0.0F, 0.0F); ++ if (level.noCollision((Entity) this)) { + break; + } + } + } + } else { +- this.moveTo(sharedSpawnPos, 0.0F, 0.0F); ++ this.moveTo(blockposition, 0.0F, 0.0F); + +- while (!level.noCollision(this) && this.getY() < (double)(level.getMaxBuildHeight() - 1)) { +- this.setPos(this.getX(), this.getY() + 1.0, this.getZ()); ++ while (!level.noCollision((Entity) this) && this.getY() < (double) (level.getMaxBuildHeight() - 1)) { ++ this.setPos(this.getX(), this.getY() + 1.0D, this.getZ()); + } + } ++ + } + + private int getCoprime(int spawnArea) { +@@ -318,67 +424,101 @@ + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); + if (compound.contains("warden_spawn_tracker", 10)) { +- WardenSpawnTracker.CODEC +- .parse(new Dynamic<>(NbtOps.INSTANCE, compound.get("warden_spawn_tracker"))) +- .resultOrPartial(LOGGER::error) +- .ifPresent(wardenSpawnTracker -> this.wardenSpawnTracker = wardenSpawnTracker); ++ DataResult dataresult = WardenSpawnTracker.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compound.get("warden_spawn_tracker"))); // CraftBukkit - decompile error ++ Logger logger = ServerPlayer.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((wardenspawntracker) -> { ++ this.wardenSpawnTracker = wardenspawntracker; ++ }); + } + + if (compound.contains("enteredNetherPosition", 10)) { +- CompoundTag compound1 = compound.getCompound("enteredNetherPosition"); +- this.enteredNetherPosition = new Vec3(compound1.getDouble("x"), compound1.getDouble("y"), compound1.getDouble("z")); ++ CompoundTag nbttagcompound1 = compound.getCompound("enteredNetherPosition"); ++ ++ this.enteredNetherPosition = new Vec3(nbttagcompound1.getDouble("x"), nbttagcompound1.getDouble("y"), nbttagcompound1.getDouble("z")); + } + + this.seenCredits = compound.getBoolean("seenCredits"); + if (compound.contains("recipeBook", 10)) { + this.recipeBook.fromNbt(compound.getCompound("recipeBook"), this.server.getRecipeManager()); + } ++ this.getBukkitEntity().readExtraData(compound); // CraftBukkit + + if (this.isSleeping()) { + this.stopSleeping(); + } + ++ // CraftBukkit start ++ String spawnWorld = compound.getString("SpawnWorld"); ++ CraftWorld oldWorld = (CraftWorld) Bukkit.getWorld(spawnWorld); ++ if (oldWorld != null) { ++ this.respawnDimension = oldWorld.getHandle().dimension(); ++ } ++ // CraftBukkit end ++ + if (compound.contains("SpawnX", 99) && compound.contains("SpawnY", 99) && compound.contains("SpawnZ", 99)) { + this.respawnPosition = new BlockPos(compound.getInt("SpawnX"), compound.getInt("SpawnY"), compound.getInt("SpawnZ")); + this.respawnForced = compound.getBoolean("SpawnForced"); + this.respawnAngle = compound.getFloat("SpawnAngle"); + if (compound.contains("SpawnDimension")) { +- this.respawnDimension = Level.RESOURCE_KEY_CODEC +- .parse(NbtOps.INSTANCE, compound.get("SpawnDimension")) +- .resultOrPartial(LOGGER::error) +- .orElse(Level.OVERWORLD); ++ DataResult> dataresult1 = Level.RESOURCE_KEY_CODEC.parse(NbtOps.INSTANCE, compound.get("SpawnDimension")); // CraftBukkit - decompile error ++ Logger logger1 = ServerPlayer.LOGGER; ++ ++ Objects.requireNonNull(logger1); ++ this.respawnDimension = (ResourceKey) dataresult1.resultOrPartial(logger1::error).orElse(Level.OVERWORLD); + } + } ++ + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- WardenSpawnTracker.CODEC +- .encodeStart(NbtOps.INSTANCE, this.wardenSpawnTracker) +- .resultOrPartial(LOGGER::error) +- .ifPresent(tag -> compound.put("warden_spawn_tracker", tag)); ++ DataResult dataresult = WardenSpawnTracker.CODEC.encodeStart(NbtOps.INSTANCE, this.wardenSpawnTracker); // CraftBukkit - decompile error ++ Logger logger = ServerPlayer.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("warden_spawn_tracker", nbtbase); ++ }); + this.storeGameTypes(compound); + compound.putBoolean("seenCredits", this.seenCredits); + if (this.enteredNetherPosition != null) { +- CompoundTag compoundTag = new CompoundTag(); +- compoundTag.putDouble("x", this.enteredNetherPosition.x); +- compoundTag.putDouble("y", this.enteredNetherPosition.y); +- compoundTag.putDouble("z", this.enteredNetherPosition.z); +- compound.put("enteredNetherPosition", compoundTag); ++ CompoundTag nbttagcompound1 = new CompoundTag(); ++ ++ nbttagcompound1.putDouble("x", this.enteredNetherPosition.x); ++ nbttagcompound1.putDouble("y", this.enteredNetherPosition.y); ++ nbttagcompound1.putDouble("z", this.enteredNetherPosition.z); ++ compound.put("enteredNetherPosition", nbttagcompound1); + } + +- Entity rootVehicle = this.getRootVehicle(); +- Entity vehicle = this.getVehicle(); +- if (vehicle != null && rootVehicle != this && rootVehicle.hasExactlyOnePlayerPassenger()) { +- CompoundTag compoundTag1 = new CompoundTag(); +- CompoundTag compoundTag2 = new CompoundTag(); +- rootVehicle.save(compoundTag2); +- compoundTag1.putUUID("Attach", vehicle.getUUID()); +- compoundTag1.put("Entity", compoundTag2); +- compound.put("RootVehicle", compoundTag1); ++ Entity entity = this.getRootVehicle(); ++ Entity entity1 = this.getVehicle(); ++ ++ // CraftBukkit start - handle non-persistent vehicles ++ boolean persistVehicle = true; ++ if (entity1 != null) { ++ Entity vehicle; ++ for (vehicle = entity1; vehicle != null; vehicle = vehicle.getVehicle()) { ++ if (!vehicle.persist) { ++ persistVehicle = false; ++ break; ++ } ++ } + } + ++ if (persistVehicle && entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger()) { ++ // CraftBukkit end ++ CompoundTag nbttagcompound2 = new CompoundTag(); ++ CompoundTag nbttagcompound3 = new CompoundTag(); ++ ++ entity.save(nbttagcompound3); ++ nbttagcompound2.putUUID("Attach", entity1.getUUID()); ++ nbttagcompound2.put("Entity", nbttagcompound3); ++ compound.put("RootVehicle", nbttagcompound2); ++ } ++ + compound.put("recipeBook", this.recipeBook.toNbt()); + compound.putString("Dimension", this.level().dimension().location().toString()); + if (this.respawnPosition != null) { +@@ -387,17 +527,45 @@ + compound.putInt("SpawnZ", this.respawnPosition.getZ()); + compound.putBoolean("SpawnForced", this.respawnForced); + compound.putFloat("SpawnAngle", this.respawnAngle); +- ResourceLocation.CODEC +- .encodeStart(NbtOps.INSTANCE, this.respawnDimension.location()) +- .resultOrPartial(LOGGER::error) +- .ifPresent(tag -> compound.put("SpawnDimension", tag)); ++ dataresult = ResourceLocation.CODEC.encodeStart(NbtOps.INSTANCE, this.respawnDimension.location()); ++ logger = ServerPlayer.LOGGER; ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("SpawnDimension", nbtbase); ++ }); + } ++ this.getBukkitEntity().setExtraData(compound); // CraftBukkit ++ + } + ++ // CraftBukkit start - World fallback code, either respawn location or global spawn ++ public void spawnIn(Level world) { ++ this.setLevel(world); ++ if (world == null) { ++ this.unsetRemoved(); ++ Vec3 position = null; ++ if (this.respawnDimension != null) { ++ world = this.server.getLevel(this.respawnDimension); ++ if (world != null && this.getRespawnPosition() != null) { ++ position = Player.findRespawnPositionAndUseSpawnBlock((ServerLevel) world, this.getRespawnPosition(), this.getRespawnAngle(), false, false).orElse(null); ++ } ++ } ++ if (world == null || position == null) { ++ world = ((CraftWorld) Bukkit.getServer().getWorlds().get(0)).getHandle(); ++ position = Vec3.atCenterOf(world.getSharedSpawnPos()); ++ } ++ this.setLevel(world); ++ this.setPos(position); ++ } ++ this.gameMode.setLevel((ServerLevel) world); ++ } ++ // CraftBukkit end ++ + public void setExperiencePoints(int experiencePoints) { +- float f = (float)this.getXpNeededForNextLevel(); ++ float f = (float) this.getXpNeededForNextLevel(); + float f1 = (f - 1.0F) / f; +- this.experienceProgress = Mth.clamp((float)experiencePoints / f, 0.0F, f1); ++ ++ this.experienceProgress = Mth.clamp((float) experiencePoints / f, 0.0F, f1); + this.lastSentExp = -1; + } + +@@ -418,7 +586,7 @@ + this.lastSentExp = -1; + } + +- private void initMenu(AbstractContainerMenu menu) { ++ public void initMenu(AbstractContainerMenu menu) { + menu.addSlotListener(this.containerListener); + menu.setSynchronizer(this.containerSynchronizer); + } +@@ -440,7 +608,7 @@ + } + + @Override +- protected void onInsideBlock(BlockState state) { ++ protected void onInsideBlock(IBlockData state) { + CriteriaTriggers.ENTER_BLOCK.trigger(this, state); + } + +@@ -451,11 +619,16 @@ + + @Override + public void tick() { ++ // CraftBukkit start ++ if (this.joining) { ++ this.joining = false; ++ } ++ // CraftBukkit end + this.gameMode.tick(); + this.wardenSpawnTracker.tick(); +- this.spawnInvulnerableTime--; ++ --this.spawnInvulnerableTime; + if (this.invulnerableTime > 0) { +- this.invulnerableTime--; ++ --this.invulnerableTime; + } + + this.containerMenu.broadcastChanges(); +@@ -464,10 +637,11 @@ + this.containerMenu = this.inventoryMenu; + } + +- Entity camera = this.getCamera(); +- if (camera != this) { +- if (camera.isAlive()) { +- this.absMoveTo(camera.getX(), camera.getY(), camera.getZ(), camera.getYRot(), camera.getXRot()); ++ Entity entity = this.getCamera(); ++ ++ if (entity != this) { ++ if (entity.isAlive()) { ++ this.absMoveTo(entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot()); + this.serverLevel().getChunkSource().move(this); + if (this.wantsToStopRiding()) { + this.setCamera(this); +@@ -493,20 +667,20 @@ + super.tick(); + } + +- for (int i = 0; i < this.getInventory().getContainerSize(); i++) { +- ItemStack item = this.getInventory().getItem(i); +- if (item.getItem().isComplex()) { +- Packet updatePacket = ((ComplexItem)item.getItem()).getUpdatePacket(item, this.level(), this); +- if (updatePacket != null) { +- this.connection.send(updatePacket); ++ for (int i = 0; i < this.getInventory().getContainerSize(); ++i) { ++ ItemStack itemstack = this.getInventory().getItem(i); ++ ++ if (itemstack.getItem().isComplex()) { ++ Packet packet = ((ComplexItem) itemstack.getItem()).getUpdatePacket(itemstack, this.level(), this); ++ ++ if (packet != null) { ++ this.connection.send(packet); + } + } + } + +- if (this.getHealth() != this.lastSentHealth +- || this.lastSentFood != this.foodData.getFoodLevel() +- || this.foodData.getSaturationLevel() == 0.0F != this.lastFoodSaturationZero) { +- this.connection.send(new ClientboundSetHealthPacket(this.getHealth(), this.foodData.getFoodLevel(), this.foodData.getSaturationLevel())); ++ if (this.getHealth() != this.lastSentHealth || this.lastSentFood != this.foodData.getFoodLevel() || this.foodData.getSaturationLevel() == 0.0F != this.lastFoodSaturationZero) { ++ this.connection.send(new ClientboundSetHealthPacket(this.getBukkitEntity().getScaledHealth(), this.foodData.getFoodLevel(), this.foodData.getSaturationLevel())); // CraftBukkit + this.lastSentHealth = this.getHealth(); + this.lastSentFood = this.foodData.getFoodLevel(); + this.lastFoodSaturationZero = this.foodData.getSaturationLevel() == 0.0F; +@@ -519,27 +693,33 @@ + + if (this.foodData.getFoodLevel() != this.lastRecordedFoodLevel) { + this.lastRecordedFoodLevel = this.foodData.getFoodLevel(); +- this.updateScoreForCriteria(ObjectiveCriteria.FOOD, Mth.ceil((float)this.lastRecordedFoodLevel)); ++ this.updateScoreForCriteria(ObjectiveCriteria.FOOD, Mth.ceil((float) this.lastRecordedFoodLevel)); + } + + if (this.getAirSupply() != this.lastRecordedAirLevel) { + this.lastRecordedAirLevel = this.getAirSupply(); +- this.updateScoreForCriteria(ObjectiveCriteria.AIR, Mth.ceil((float)this.lastRecordedAirLevel)); ++ this.updateScoreForCriteria(ObjectiveCriteria.AIR, Mth.ceil((float) this.lastRecordedAirLevel)); + } + + if (this.getArmorValue() != this.lastRecordedArmor) { + this.lastRecordedArmor = this.getArmorValue(); +- this.updateScoreForCriteria(ObjectiveCriteria.ARMOR, Mth.ceil((float)this.lastRecordedArmor)); ++ this.updateScoreForCriteria(ObjectiveCriteria.ARMOR, Mth.ceil((float) this.lastRecordedArmor)); + } + + if (this.totalExperience != this.lastRecordedExperience) { + this.lastRecordedExperience = this.totalExperience; +- this.updateScoreForCriteria(ObjectiveCriteria.EXPERIENCE, Mth.ceil((float)this.lastRecordedExperience)); ++ this.updateScoreForCriteria(ObjectiveCriteria.EXPERIENCE, Mth.ceil((float) this.lastRecordedExperience)); + } + ++ // CraftBukkit start - Force max health updates ++ if (this.maxHealthCache != this.getMaxHealth()) { ++ this.getBukkitEntity().updateScaledHealth(); ++ } ++ // CraftBukkit end ++ + if (this.experienceLevel != this.lastRecordedLevel) { + this.lastRecordedLevel = this.experienceLevel; +- this.updateScoreForCriteria(ObjectiveCriteria.LEVEL, Mth.ceil((float)this.lastRecordedLevel)); ++ this.updateScoreForCriteria(ObjectiveCriteria.LEVEL, Mth.ceil((float) this.lastRecordedLevel)); + } + + if (this.totalExperience != this.lastSentExp) { +@@ -550,11 +730,27 @@ + if (this.tickCount % 20 == 0) { + CriteriaTriggers.LOCATION.trigger(this); + } +- } catch (Throwable var4) { +- CrashReport crashReport = CrashReport.forThrowable(var4, "Ticking player"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Player being ticked"); +- this.fillCrashReportCategory(crashReportCategory); +- throw new ReportedException(crashReport); ++ ++ // CraftBukkit start - initialize oldLevel, fire PlayerLevelChangeEvent, and tick client-sided world border ++ if (this.oldLevel == -1) { ++ this.oldLevel = this.experienceLevel; ++ } ++ ++ if (this.oldLevel != this.experienceLevel) { ++ CraftEventFactory.callPlayerLevelChangeEvent(this.getBukkitEntity(), this.oldLevel, this.experienceLevel); ++ this.oldLevel = this.experienceLevel; ++ } ++ ++ if (this.getBukkitEntity().hasClientWorldBorder()) { ++ ((CraftWorldBorder) this.getBukkitEntity().getWorldBorder()).getHandle().tick(); ++ } ++ // CraftBukkit end ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking player"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Player being ticked"); ++ ++ this.fillCrashReportCategory(crashreportsystemdetails); ++ throw new ReportedException(crashreport); + } + } + +@@ -572,6 +768,7 @@ + if (this.fallDistance > 0.0F && this.startingToFallPosition == null) { + this.startingToFallPosition = this.position(); + } ++ + } + + public void trackEnteredOrExitedLavaOnVehicle() { +@@ -586,42 +783,83 @@ + if (this.enteredLavaOnVehiclePosition != null && (this.getVehicle() == null || !this.getVehicle().isInLava())) { + this.enteredLavaOnVehiclePosition = null; + } ++ + } + + private void updateScoreForCriteria(ObjectiveCriteria criteria, int points) { +- this.getScoreboard().forAllObjectives(criteria, this, scoreAccess -> scoreAccess.set(points)); ++ // CraftBukkit - Use our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(criteria, this, (scoreaccess) -> { ++ scoreaccess.set(points); ++ }); + } + + @Override + public void die(DamageSource cause) { + this.gameEvent(GameEvent.ENTITY_DIE); +- boolean _boolean = this.level().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); +- if (_boolean) { +- Component deathMessage = this.getCombatTracker().getDeathMessage(); +- this.connection +- .send( +- new ClientboundPlayerCombatKillPacket(this.getId(), deathMessage), +- PacketSendListener.exceptionallySend( +- () -> { +- int i = 256; +- String string = deathMessage.getString(256); +- Component component = Component.translatable( +- "death.attack.message_too_long", Component.literal(string).withStyle(ChatFormatting.YELLOW) +- ); +- Component component1 = Component.translatable("death.attack.even_more_magic", this.getDisplayName()) +- .withStyle(style -> style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, component))); +- return new ClientboundPlayerCombatKillPacket(this.getId(), component1); +- } +- ) +- ); +- Team team = this.getTeam(); +- if (team == null || team.getDeathMessageVisibility() == Team.Visibility.ALWAYS) { +- this.server.getPlayerList().broadcastSystemMessage(deathMessage, false); +- } else if (team.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OTHER_TEAMS) { +- this.server.getPlayerList().broadcastSystemToTeam(this, deathMessage); +- } else if (team.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OWN_TEAM) { +- this.server.getPlayerList().broadcastSystemToAllExceptTeam(this, deathMessage); ++ boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); ++ // CraftBukkit start - fire PlayerDeathEvent ++ if (this.isRemoved()) { ++ return; ++ } ++ java.util.List loot = new java.util.ArrayList(this.getInventory().getContainerSize()); ++ boolean keepInventory = this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || this.isSpectator(); ++ ++ if (!keepInventory) { ++ for (ItemStack item : this.getInventory().getContents()) { ++ if (!item.isEmpty() && !EnchantmentHelper.hasVanishingCurse(item)) { ++ loot.add(CraftItemStack.asCraftMirror(item)); ++ } + } ++ } ++ // SPIGOT-5071: manually add player loot tables (SPIGOT-5195 - ignores keepInventory rule) ++ this.dropFromLootTable(cause, this.lastHurtByPlayerTime > 0); ++ for (org.bukkit.inventory.ItemStack item : this.drops) { ++ loot.add(item); ++ } ++ this.drops.clear(); // SPIGOT-5188: make sure to clear ++ ++ Component defaultMessage = this.getCombatTracker().getDeathMessage(); ++ ++ String deathmessage = defaultMessage.getString(); ++ keepLevel = keepInventory; // SPIGOT-2222: pre-set keepLevel ++ org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, deathmessage, keepInventory); ++ ++ // SPIGOT-943 - only call if they have an inventory open ++ if (this.containerMenu != this.inventoryMenu) { ++ this.closeContainer(); ++ } ++ ++ String deathMessage = event.getDeathMessage(); ++ ++ if (deathMessage != null && deathMessage.length() > 0 && flag) { // TODO: allow plugins to override? ++ Component ichatbasecomponent; ++ if (deathMessage.equals(deathmessage)) { ++ ichatbasecomponent = this.getCombatTracker().getDeathMessage(); ++ } else { ++ ichatbasecomponent = org.bukkit.craftbukkit.util.CraftChatMessage.fromStringOrNull(deathMessage); ++ } ++ ++ this.connection.send(new ClientboundPlayerCombatKillPacket(this.getId(), ichatbasecomponent), PacketSendListener.exceptionallySend(() -> { ++ boolean flag1 = true; ++ String s = ichatbasecomponent.getString(256); ++ MutableComponent ichatmutablecomponent = Component.translatable("death.attack.message_too_long", Component.literal(s).withStyle(ChatFormatting.YELLOW)); ++ MutableComponent ichatmutablecomponent1 = Component.translatable("death.attack.even_more_magic", this.getDisplayName()).withStyle((chatmodifier) -> { ++ return chatmodifier.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, ichatmutablecomponent)); ++ }); ++ ++ return new ClientboundPlayerCombatKillPacket(this.getId(), ichatmutablecomponent1); ++ })); ++ PlayerTeam scoreboardteam = this.getTeam(); ++ ++ if (scoreboardteam != null && scoreboardteam.getDeathMessageVisibility() != Team.Visibility.ALWAYS) { ++ if (scoreboardteam.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OTHER_TEAMS) { ++ this.server.getPlayerList().broadcastSystemToTeam(this, ichatbasecomponent); ++ } else if (scoreboardteam.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OWN_TEAM) { ++ this.server.getPlayerList().broadcastSystemToAllExceptTeam(this, ichatbasecomponent); ++ } ++ } else { ++ this.server.getPlayerList().broadcastSystemMessage(ichatbasecomponent, false); ++ } + } else { + this.connection.send(new ClientboundPlayerCombatKillPacket(this.getId(), CommonComponents.EMPTY)); + } +@@ -630,20 +868,27 @@ + if (this.level().getGameRules().getBoolean(GameRules.RULE_FORGIVE_DEAD_PLAYERS)) { + this.tellNeutralMobsThatIDied(); + } +- +- if (!this.isSpectator()) { +- this.dropAllDeathLoot(cause); ++ // SPIGOT-5478 must be called manually now ++ this.dropExperience(); ++ // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. ++ if (!event.getKeepInventory()) { ++ this.getInventory().clearContent(); + } + +- this.getScoreboard().forAllObjectives(ObjectiveCriteria.DEATH_COUNT, this, ScoreAccess::increment); +- LivingEntity killCredit = this.getKillCredit(); +- if (killCredit != null) { +- this.awardStat(Stats.ENTITY_KILLED_BY.get(killCredit.getType())); +- killCredit.awardKillScore(this, this.deathScore, cause); +- this.createWitherRose(killCredit); ++ this.setCamera(this); // Remove spectated target ++ // CraftBukkit end ++ ++ // CraftBukkit - Get our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(ObjectiveCriteria.DEATH_COUNT, this, ScoreAccess::increment); ++ LivingEntity entityliving = this.getKillCredit(); ++ ++ if (entityliving != null) { ++ this.awardStat(Stats.ENTITY_KILLED_BY.get(entityliving.getType())); ++ entityliving.awardKillScore(this, this.deathScore, cause); ++ this.createWitherRose(entityliving); + } + +- this.level().broadcastEntityEvent(this, (byte)3); ++ this.level().broadcastEntityEvent(this, (byte) 3); + this.awardStat(Stats.DEATHS); + this.resetStat(Stats.CUSTOM.get(Stats.TIME_SINCE_DEATH)); + this.resetStat(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)); +@@ -655,12 +900,13 @@ + } + + private void tellNeutralMobsThatIDied() { +- AABB aABB = new AABB(this.blockPosition()).inflate(32.0, 10.0, 32.0); +- this.level() +- .getEntitiesOfClass(Mob.class, aABB, EntitySelector.NO_SPECTATORS) +- .stream() +- .filter(mob -> mob instanceof NeutralMob) +- .forEach(mob -> ((NeutralMob)mob).playerDied(this)); ++ AABB axisalignedbb = (new AABB(this.blockPosition())).inflate(32.0D, 10.0D, 32.0D); ++ ++ this.level().getEntitiesOfClass(Mob.class, axisalignedbb, EntitySelector.NO_SPECTATORS).stream().filter((entityinsentient) -> { ++ return entityinsentient instanceof NeutralMob; ++ }).forEach((entityinsentient) -> { ++ ((NeutralMob) entityinsentient).playerDied(this); ++ }); + } + + @Override +@@ -668,10 +914,12 @@ + if (killed != this) { + super.awardKillScore(killed, scoreValue, damageSource); + this.increaseScore(scoreValue); +- this.getScoreboard().forAllObjectives(ObjectiveCriteria.KILL_COUNT_ALL, this, ScoreAccess::increment); ++ // CraftBukkit - Get our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(ObjectiveCriteria.KILL_COUNT_ALL, this, ScoreAccess::increment); + if (killed instanceof Player) { + this.awardStat(Stats.PLAYER_KILLS); +- this.getScoreboard().forAllObjectives(ObjectiveCriteria.KILL_COUNT_PLAYERS, this, ScoreAccess::increment); ++ // CraftBukkit - Get our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(ObjectiveCriteria.KILL_COUNT_PLAYERS, this, ScoreAccess::increment); + } else { + this.awardStat(Stats.MOB_KILLS); + } +@@ -682,14 +930,18 @@ + } + } + +- private void handleTeamKill(ScoreHolder scoreHolder, ScoreHolder scoreHolder1, ObjectiveCriteria[] objectiveCriterias) { +- PlayerTeam playersTeam = this.getScoreboard().getPlayersTeam(scoreHolder1.getScoreboardName()); +- if (playersTeam != null) { +- int id = playersTeam.getColor().getId(); +- if (id >= 0 && id < objectiveCriterias.length) { +- this.getScoreboard().forAllObjectives(objectiveCriterias[id], scoreHolder, ScoreAccess::increment); ++ private void handleTeamKill(ScoreHolder scoreholder, ScoreHolder scoreholder1, ObjectiveCriteria[] aiscoreboardcriteria) { ++ PlayerTeam scoreboardteam = this.getScoreboard().getPlayersTeam(scoreholder1.getScoreboardName()); ++ ++ if (scoreboardteam != null) { ++ int i = scoreboardteam.getColor().getId(); ++ ++ if (i >= 0 && i < aiscoreboardcriteria.length) { ++ // CraftBukkit - Get our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(aiscoreboardcriteria[i], scoreholder, ScoreAccess::increment); + } + } ++ + } + + @Override +@@ -698,16 +950,31 @@ + return false; + } else { + boolean flag = this.server.isDedicatedServer() && this.isPvpAllowed() && source.is(DamageTypeTags.IS_FALL); ++ + if (!flag && this.spawnInvulnerableTime > 0 && !source.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { + return false; + } else { + Entity entity = source.getEntity(); +- if (entity instanceof Player player && !this.canHarmPlayer(player)) { +- return false; ++ ++ if (entity instanceof Player) { ++ Player entityhuman = (Player) entity; ++ ++ if (!this.canHarmPlayer(entityhuman)) { ++ return false; ++ } + } + +- if (entity instanceof AbstractArrow abstractArrow && abstractArrow.getOwner() instanceof Player player1 && !this.canHarmPlayer(player1)) { +- return false; ++ if (entity instanceof AbstractArrow) { ++ AbstractArrow entityarrow = (AbstractArrow) entity; ++ Entity entity1 = entityarrow.getOwner(); ++ ++ if (entity1 instanceof Player) { ++ Player entityhuman1 = (Player) entity1; ++ ++ if (!this.canHarmPlayer(entityhuman1)) { ++ return false; ++ } ++ } + } + + return super.hurt(source, amount); +@@ -717,32 +984,46 @@ + + @Override + public boolean canHarmPlayer(Player other) { +- return this.isPvpAllowed() && super.canHarmPlayer(other); ++ return !this.isPvpAllowed() ? false : super.canHarmPlayer(other); + } + + private boolean isPvpAllowed() { +- return this.server.isPvpAllowed(); ++ // CraftBukkit - this.server.isPvpAllowed() -> this.world.pvpMode ++ return this.level().pvpMode; + } + + @Nullable + @Override + protected PortalInfo findDimensionEntryPoint(ServerLevel destination) { +- PortalInfo portalInfo = super.findDimensionEntryPoint(destination); +- if (portalInfo != null && this.level().dimension() == Level.OVERWORLD && destination.dimension() == Level.END) { +- Vec3 vec3 = portalInfo.pos.add(0.0, -1.0, 0.0); +- return new PortalInfo(vec3, Vec3.ZERO, 90.0F, 0.0F); ++ PortalInfo shapedetectorshape = super.findDimensionEntryPoint(destination); ++ destination = (shapedetectorshape == null) ? destination : shapedetectorshape.world; // CraftBukkit ++ ++ if (shapedetectorshape != null && this.level().getTypeKey() == LevelStem.OVERWORLD && destination != null && destination.getTypeKey() == LevelStem.END) { // CraftBukkit ++ Vec3 vec3d = shapedetectorshape.pos.add(0.0D, -1.0D, 0.0D); ++ ++ return new PortalInfo(vec3d, Vec3.ZERO, 90.0F, 0.0F, destination, shapedetectorshape.portalEventInfo); // CraftBukkit + } else { +- return portalInfo; ++ return shapedetectorshape; + } + } + + @Nullable + @Override + public Entity changeDimension(ServerLevel server) { +- this.isChangingDimension = true; +- ServerLevel serverLevel = this.serverLevel(); +- ResourceKey resourceKey = serverLevel.dimension(); +- if (resourceKey == Level.END && server.dimension() == Level.OVERWORLD) { ++ // CraftBukkit start ++ return changeDimension(server, TeleportCause.UNKNOWN); ++ } ++ ++ @Nullable ++ public Entity changeDimension(ServerLevel worldserver, PlayerTeleportEvent.TeleportCause cause) { ++ // CraftBukkit end ++ if (this.isSleeping()) return this; // CraftBukkit - SPIGOT-3154 ++ // this.isChangingDimension = true; // CraftBukkit - Moved down and into PlayerList#changeDimension ++ ServerLevel worldserver1 = this.serverLevel(); ++ ResourceKey resourcekey = worldserver1.getTypeKey(); // CraftBukkit ++ ++ if (resourcekey == LevelStem.END && worldserver != null && worldserver.getTypeKey() == LevelStem.OVERWORLD) { // CraftBukkit ++ this.isChangingDimension = true; // CraftBukkit - Moved down from above + this.unRide(); + this.serverLevel().removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); + if (!this.wonGame) { +@@ -753,93 +1034,172 @@ + + return this; + } else { +- LevelData levelData = server.getLevelData(); +- this.connection.send(new ClientboundRespawnPacket(this.createCommonSpawnInfo(server), (byte)3)); +- this.connection.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked())); +- PlayerList playerList = this.server.getPlayerList(); +- playerList.sendPlayerPermissionLevel(this); +- serverLevel.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); ++ // CraftBukkit start ++ /* ++ WorldData worlddata = worldserver.getLevelData(); ++ ++ this.connection.send(new PacketPlayOutRespawn(this.createCommonSpawnInfo(worldserver), (byte) 3)); ++ this.connection.send(new PacketPlayOutServerDifficulty(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); ++ PlayerList playerlist = this.server.getPlayerList(); ++ ++ playerlist.sendPlayerPermissionLevel(this); ++ worldserver1.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); + this.unsetRemoved(); +- PortalInfo portalInfo = this.findDimensionEntryPoint(server); +- if (portalInfo != null) { +- serverLevel.getProfiler().push("moving"); +- if (resourceKey == Level.OVERWORLD && server.dimension() == Level.NETHER) { ++ */ ++ // CraftBukkit end ++ PortalInfo shapedetectorshape = this.findDimensionEntryPoint(worldserver); ++ ++ if (shapedetectorshape != null) { ++ worldserver1.getProfiler().push("moving"); ++ worldserver = shapedetectorshape.world; // CraftBukkit ++ if (worldserver == null) { } else // CraftBukkit - empty to fall through to null to event ++ if (resourcekey == LevelStem.OVERWORLD && worldserver.getTypeKey() == LevelStem.NETHER) { // CraftBukkit + this.enteredNetherPosition = this.position(); +- } else if (server.dimension() == Level.END) { +- this.createEndPlatform(server, BlockPos.containing(portalInfo.pos)); ++ } else if (worldserver.getTypeKey() == LevelStem.END && shapedetectorshape.portalEventInfo != null && shapedetectorshape.portalEventInfo.getCanCreatePortal()) { // CraftBukkit ++ this.createEndPlatform(worldserver, BlockPos.containing(shapedetectorshape.pos)); + } ++ // CraftBukkit start ++ } else { ++ return null; ++ } ++ Location enter = this.getBukkitEntity().getLocation(); ++ Location exit = (worldserver == null) ? null : CraftLocation.toBukkit(shapedetectorshape.pos, worldserver.getWorld(), shapedetectorshape.yRot, shapedetectorshape.xRot); ++ PlayerTeleportEvent tpEvent = new PlayerTeleportEvent(this.getBukkitEntity(), enter, exit, cause); ++ Bukkit.getServer().getPluginManager().callEvent(tpEvent); ++ if (tpEvent.isCancelled() || tpEvent.getTo() == null) { ++ return null; ++ } ++ exit = tpEvent.getTo(); ++ worldserver = ((CraftWorld) exit.getWorld()).getHandle(); ++ // CraftBukkit end + +- serverLevel.getProfiler().pop(); +- serverLevel.getProfiler().push("placing"); +- this.setServerLevel(server); +- this.connection.teleport(portalInfo.pos.x, portalInfo.pos.y, portalInfo.pos.z, portalInfo.yRot, portalInfo.xRot); ++ worldserver1.getProfiler().pop(); ++ worldserver1.getProfiler().push("placing"); ++ if (true) { // CraftBukkit ++ this.isChangingDimension = true; // CraftBukkit - Set teleport invulnerability only if player changing worlds ++ ++ this.connection.send(new ClientboundRespawnPacket(this.createCommonSpawnInfo(worldserver), (byte) 3)); ++ this.connection.send(new ClientboundChangeDifficultyPacket(this.level().getDifficulty(), this.level().getLevelData().isDifficultyLocked())); ++ PlayerList playerlist = this.server.getPlayerList(); ++ ++ playerlist.sendPlayerPermissionLevel(this); ++ worldserver1.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); ++ this.unsetRemoved(); ++ ++ // CraftBukkit end ++ this.setServerLevel(worldserver); ++ this.connection.teleport(exit); // CraftBukkit - use internal teleport without event + this.connection.resetPosition(); +- server.addDuringPortalTeleport(this); +- serverLevel.getProfiler().pop(); +- this.triggerDimensionChangeTriggers(serverLevel); ++ worldserver.addDuringPortalTeleport(this); ++ worldserver1.getProfiler().pop(); ++ this.triggerDimensionChangeTriggers(worldserver1); + this.connection.send(new ClientboundPlayerAbilitiesPacket(this.getAbilities())); +- playerList.sendLevelInfo(this, server); +- playerList.sendAllPlayerInfo(this); ++ playerlist.sendLevelInfo(this, worldserver); ++ playerlist.sendAllPlayerInfo(this); ++ Iterator iterator = this.getActiveEffects().iterator(); + +- for (MobEffectInstance mobEffectInstance : this.getActiveEffects()) { +- this.connection.send(new ClientboundUpdateMobEffectPacket(this.getId(), mobEffectInstance)); ++ while (iterator.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); ++ ++ this.connection.send(new ClientboundUpdateMobEffectPacket(this.getId(), mobeffect)); + } + + this.connection.send(new ClientboundLevelEventPacket(1032, BlockPos.ZERO, 0, false)); + this.lastSentExp = -1; + this.lastSentHealth = -1.0F; + this.lastSentFood = -1; ++ ++ // CraftBukkit start ++ PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.getBukkitEntity(), worldserver1.getWorld()); ++ this.level().getCraftServer().getPluginManager().callEvent(changeEvent); ++ // CraftBukkit end + } + + return this; + } + } + ++ // CraftBukkit start ++ @Override ++ protected CraftPortalEvent callPortalEvent(Entity entity, ServerLevel exitWorldServer, Vec3 exitPosition, TeleportCause cause, int searchRadius, int creationRadius) { ++ Location enter = this.getBukkitEntity().getLocation(); ++ Location exit = CraftLocation.toBukkit(exitPosition, exitWorldServer.getWorld(), getYRot(), getXRot()); ++ PlayerPortalEvent event = new PlayerPortalEvent(this.getBukkitEntity(), enter, exit, cause, searchRadius, true, creationRadius); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null) { ++ return null; ++ } ++ return new CraftPortalEvent(event); ++ } ++ // CraftBukkit end ++ + private void createEndPlatform(ServerLevel level, BlockPos pos) { +- BlockPos.MutableBlockPos mutableBlockPos = pos.mutable(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(level); // CraftBukkit + +- for (int i = -2; i <= 2; i++) { +- for (int i1 = -2; i1 <= 2; i1++) { +- for (int i2 = -1; i2 < 3; i2++) { +- BlockState blockState = i2 == -1 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); +- level.setBlockAndUpdate(mutableBlockPos.set(pos).move(i1, i2, i), blockState); ++ for (int i = -2; i <= 2; ++i) { ++ for (int j = -2; j <= 2; ++j) { ++ for (int k = -1; k < 3; ++k) { ++ IBlockData iblockdata = k == -1 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); ++ ++ blockList.setBlock(blockposition_mutableblockposition.set(pos).move(j, k, i), iblockdata, 3); // CraftBukkit + } + } + } ++ // CraftBukkit start - call portal event ++ org.bukkit.event.world.PortalCreateEvent portalEvent = new org.bukkit.event.world.PortalCreateEvent((List) (List) blockList.getList(), level.getWorld(), this.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM); ++ level.getCraftServer().getPluginManager().callEvent(portalEvent); ++ if (!portalEvent.isCancelled()) { ++ blockList.updateList(); ++ } ++ // CraftBukkit end ++ + } + + @Override +- protected Optional getExitPortal(ServerLevel destination, BlockPos findFrom, boolean isToNether, WorldBorder worldBorder) { +- Optional optional = super.getExitPortal(destination, findFrom, isToNether, worldBorder); +- if (optional.isPresent()) { ++ protected Optional getExitPortal(ServerLevel worldserver, BlockPos blockposition, boolean flag, WorldBorder worldborder, int searchRadius, boolean canCreatePortal, int createRadius) { // CraftBukkit ++ Optional optional = super.getExitPortal(worldserver, blockposition, flag, worldborder, searchRadius, canCreatePortal, createRadius); // CraftBukkit ++ ++ if (optional.isPresent() || !canCreatePortal) { // CraftBukkit + return optional; + } else { +- Direction.Axis axis = this.level().getBlockState(this.portalEntrancePos).getOptionalValue(NetherPortalBlock.AXIS).orElse(Direction.Axis.X); +- Optional optional1 = destination.getPortalForcer().createPortal(findFrom, axis); ++ Direction.Axis enumdirection_enumaxis = (Direction.Axis) this.level().getBlockState(this.portalEntrancePos).getOptionalValue(NetherPortalBlock.AXIS).orElse(Direction.Axis.X); ++ Optional optional1 = worldserver.getPortalForcer().createPortal(blockposition, enumdirection_enumaxis, this, createRadius); // CraftBukkit ++ + if (optional1.isEmpty()) { +- LOGGER.error("Unable to create a portal, likely target out of worldborder"); ++ // EntityPlayer.LOGGER.error("Unable to create a portal, likely target out of worldborder"); // CraftBukkit + } + + return optional1; + } + } + +- private void triggerDimensionChangeTriggers(ServerLevel level) { +- ResourceKey resourceKey = level.dimension(); +- ResourceKey resourceKey1 = this.level().dimension(); +- CriteriaTriggers.CHANGED_DIMENSION.trigger(this, resourceKey, resourceKey1); +- if (resourceKey == Level.NETHER && resourceKey1 == Level.OVERWORLD && this.enteredNetherPosition != null) { ++ public void triggerDimensionChangeTriggers(ServerLevel level) { ++ ResourceKey resourcekey = level.dimension(); ++ ResourceKey resourcekey1 = this.level().dimension(); ++ // CraftBukkit start ++ ResourceKey maindimensionkey = CraftDimensionUtil.getMainDimensionKey(level); ++ ResourceKey maindimensionkey1 = CraftDimensionUtil.getMainDimensionKey(this.level()); ++ ++ CriteriaTriggers.CHANGED_DIMENSION.trigger(this, maindimensionkey, maindimensionkey1); ++ if (maindimensionkey != resourcekey || maindimensionkey1 != resourcekey1) { ++ CriteriaTriggers.CHANGED_DIMENSION.trigger(this, resourcekey, resourcekey1); ++ } ++ ++ if (maindimensionkey == Level.NETHER && maindimensionkey1 == Level.OVERWORLD && this.enteredNetherPosition != null) { ++ // CraftBukkit end + CriteriaTriggers.NETHER_TRAVEL.trigger(this, this.enteredNetherPosition); + } + +- if (resourceKey1 != Level.NETHER) { ++ if (maindimensionkey1 != Level.NETHER) { // CraftBukkit + this.enteredNetherPosition = null; + } ++ + } + + @Override + public boolean broadcastToPlayer(ServerPlayer player) { +- return player.isSpectator() ? this.getCamera() == this : !this.isSpectator() && super.broadcastToPlayer(player); ++ return player.isSpectator() ? this.getCamera() == this : (this.isSpectator() ? false : super.broadcastToPlayer(player)); + } + + @Override +@@ -848,49 +1208,77 @@ + this.containerMenu.broadcastChanges(); + } + +- @Override +- public Either startSleepInBed(BlockPos at) { +- Direction direction = this.level().getBlockState(at).getValue(HorizontalDirectionalBlock.FACING); +- if (this.isSleeping() || !this.isAlive()) { +- return Either.left(Player.BedSleepingProblem.OTHER_PROBLEM); +- } else if (!this.level().dimensionType().natural()) { +- return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_HERE); +- } else if (!this.bedInRange(at, direction)) { +- return Either.left(Player.BedSleepingProblem.TOO_FAR_AWAY); +- } else if (this.bedBlocked(at, direction)) { +- return Either.left(Player.BedSleepingProblem.OBSTRUCTED); +- } else { +- this.setRespawnPosition(this.level().dimension(), at, this.getYRot(), false, true); +- if (this.level().isDay()) { +- return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_NOW); ++ // CraftBukkit start - moved bed result checks from below into separate method ++ private Either getBedResult(BlockPos blockposition, Direction enumdirection) { ++ if (!this.isSleeping() && this.isAlive()) { ++ if (!this.level().dimensionType().natural() || !this.level().dimensionType().bedWorks()) { ++ return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_HERE); ++ } else if (!this.bedInRange(blockposition, enumdirection)) { ++ return Either.left(Player.BedSleepingProblem.TOO_FAR_AWAY); ++ } else if (this.bedBlocked(blockposition, enumdirection)) { ++ return Either.left(Player.BedSleepingProblem.OBSTRUCTED); + } else { +- if (!this.isCreative()) { +- double d = 8.0; +- double d1 = 5.0; +- Vec3 vec3 = Vec3.atBottomCenterOf(at); +- List entitiesOfClass = this.level() +- .getEntitiesOfClass( +- Monster.class, +- new AABB(vec3.x() - 8.0, vec3.y() - 5.0, vec3.z() - 8.0, vec3.x() + 8.0, vec3.y() + 5.0, vec3.z() + 8.0), +- monster -> monster.isPreventingPlayerRest(this) +- ); +- if (!entitiesOfClass.isEmpty()) { +- return Either.left(Player.BedSleepingProblem.NOT_SAFE); ++ this.setRespawnPosition(this.level().dimension(), blockposition, this.getYRot(), false, true, PlayerSpawnChangeEvent.Cause.BED); // CraftBukkit ++ if (this.level().isDay()) { ++ return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_NOW); ++ } else { ++ if (!this.isCreative()) { ++ double d0 = 8.0D; ++ double d1 = 5.0D; ++ Vec3 vec3d = Vec3.atBottomCenterOf(blockposition); ++ List list = this.level().getEntitiesOfClass(Monster.class, new AABB(vec3d.x() - 8.0D, vec3d.y() - 5.0D, vec3d.z() - 8.0D, vec3d.x() + 8.0D, vec3d.y() + 5.0D, vec3d.z() + 8.0D), (entitymonster) -> { ++ return entitymonster.isPreventingPlayerRest(this); ++ }); ++ ++ if (!list.isEmpty()) { ++ return Either.left(Player.BedSleepingProblem.NOT_SAFE); ++ } + } +- } + +- Either either = super.startSleepInBed(at).ifRight(unit -> { +- this.awardStat(Stats.SLEEP_IN_BED); +- CriteriaTriggers.SLEPT_IN_BED.trigger(this); +- }); +- if (!this.serverLevel().canSleepThroughNights()) { +- this.displayClientMessage(Component.translatable("sleep.not_possible"), true); ++ return Either.right(Unit.INSTANCE); + } ++ } ++ } else { ++ return Either.left(Player.BedSleepingProblem.OTHER_PROBLEM); ++ } ++ } + +- ((ServerLevel)this.level()).updateSleepingPlayerList(); +- return either; ++ @Override ++ public Either startSleepInBed(BlockPos blockposition, boolean force) { ++ Direction enumdirection = (Direction) this.level().getBlockState(blockposition).getValue(HorizontalDirectionalBlock.FACING); ++ Either bedResult = this.getBedResult(blockposition, enumdirection); ++ ++ if (bedResult.left().orElse(null) == Player.BedSleepingProblem.OTHER_PROBLEM) { ++ return bedResult; // return immediately if the result is not bypassable by plugins ++ } ++ ++ if (force) { ++ bedResult = Either.right(Unit.INSTANCE); ++ } ++ ++ bedResult = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBedEnterEvent(this, blockposition, bedResult); ++ if (bedResult.left().isPresent()) { ++ return bedResult; ++ } ++ ++ { ++ { ++ { ++ Either either = super.startSleepInBed(blockposition, force).ifRight((unit) -> { ++ this.awardStat(Stats.SLEEP_IN_BED); ++ CriteriaTriggers.SLEPT_IN_BED.trigger(this); ++ }); ++ ++ if (!this.serverLevel().canSleepThroughNights()) { ++ this.displayClientMessage(Component.translatable("sleep.not_possible"), true); ++ } ++ ++ ((ServerLevel) this.level()).updateSleepingPlayerList(); ++ return either; ++ } + } + } ++ // CraftBukkit end + } + + @Override +@@ -904,31 +1292,52 @@ + } + + private boolean isReachableBedBlock(BlockPos pos) { +- Vec3 vec3 = Vec3.atBottomCenterOf(pos); +- return Math.abs(this.getX() - vec3.x()) <= 3.0 && Math.abs(this.getY() - vec3.y()) <= 2.0 && Math.abs(this.getZ() - vec3.z()) <= 3.0; ++ Vec3 vec3d = Vec3.atBottomCenterOf(pos); ++ ++ return Math.abs(this.getX() - vec3d.x()) <= 3.0D && Math.abs(this.getY() - vec3d.y()) <= 2.0D && Math.abs(this.getZ() - vec3d.z()) <= 3.0D; + } + + private boolean bedBlocked(BlockPos pos, Direction direction) { +- BlockPos blockPos = pos.above(); +- return !this.freeAt(blockPos) || !this.freeAt(blockPos.relative(direction.getOpposite())); ++ BlockPos blockposition1 = pos.above(); ++ ++ return !this.freeAt(blockposition1) || !this.freeAt(blockposition1.relative(direction.getOpposite())); + } + + @Override + public void stopSleepInBed(boolean wakeImmediately, boolean updateLevelForSleepingPlayers) { ++ if (!this.isSleeping()) return; // CraftBukkit - Can't leave bed if not in one! ++ // CraftBukkit start - fire PlayerBedLeaveEvent ++ CraftPlayer player = this.getBukkitEntity(); ++ BlockPos bedPosition = this.getSleepingPos().orElse(null); ++ ++ org.bukkit.block.Block bed; ++ if (bedPosition != null) { ++ bed = this.level().getWorld().getBlockAt(bedPosition.getX(), bedPosition.getY(), bedPosition.getZ()); ++ } else { ++ bed = this.level().getWorld().getBlockAt(player.getLocation()); ++ } ++ ++ PlayerBedLeaveEvent event = new PlayerBedLeaveEvent(player, bed, true); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + if (this.isSleeping()) { + this.serverLevel().getChunkSource().broadcastAndSend(this, new ClientboundAnimatePacket(this, 2)); + } + + super.stopSleepInBed(wakeImmediately, updateLevelForSleepingPlayers); + if (this.connection != null) { +- this.connection.teleport(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); ++ this.connection.teleport(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot(), TeleportCause.EXIT_BED); // CraftBukkit + } ++ + } + + @Override +- public void dismountTo(double x, double y, double z) { ++ public void dismountTo(double x, double d1, double y) { + this.removeVehicle(); +- this.setPos(x, y, z); ++ this.setPos(x, d1, y); + } + + @Override +@@ -937,21 +1346,22 @@ + } + + @Override +- protected void checkFallDamage(double y, boolean onGround, BlockState state, BlockPos pos) { +- } ++ protected void checkFallDamage(double y, boolean flag, IBlockData onGround, BlockPos state) {} + + @Override + protected void onChangedBlock(BlockPos pos) { + if (!this.isSpectator()) { + super.onChangedBlock(pos); + } ++ + } + +- public void doCheckFallDamage(double movementX, double movementY, double movementZ, boolean onGround) { ++ public void doCheckFallDamage(double movementX, double d1, double movementY, boolean flag) { + if (!this.touchingUnloadedChunk()) { +- this.checkSupportingBlock(onGround, new Vec3(movementX, movementY, movementZ)); +- BlockPos onPosLegacy = this.getOnPosLegacy(); +- super.checkFallDamage(movementY, onGround, this.level().getBlockState(onPosLegacy), onPosLegacy); ++ this.checkSupportingBlock(flag, new Vec3(movementX, d1, movementY)); ++ BlockPos blockposition = this.getOnPosLegacy(); ++ ++ super.checkFallDamage(d1, flag, this.level().getBlockState(blockposition), blockposition); + } + } + +@@ -960,6 +1370,7 @@ + if (this.level().tickRateManager().runsNormally()) { + super.pushEntities(); + } ++ + } + + @Override +@@ -968,32 +1379,57 @@ + this.connection.send(new ClientboundOpenSignEditorPacket(signEntity.getBlockPos(), isFrontText)); + } + +- private void nextContainerCounter() { ++ public int nextContainerCounter() { // CraftBukkit - void -> int + this.containerCounter = this.containerCounter % 100 + 1; ++ return containerCounter; // CraftBukkit + } + + @Override +- public OptionalInt openMenu(@Nullable MenuProvider menu) { ++ public OptionalInt openMenu(@Nullable ITileInventory menu) { + if (menu == null) { + return OptionalInt.empty(); + } else { ++ // CraftBukkit start - SPIGOT-6552: Handle inventory closing in CraftEventFactory#callInventoryOpenEvent(...) ++ /* + if (this.containerMenu != this.inventoryMenu) { + this.closeContainer(); + } ++ */ ++ // CraftBukkit end + + this.nextContainerCounter(); +- AbstractContainerMenu abstractContainerMenu = menu.createMenu(this.containerCounter, this.getInventory(), this); +- if (abstractContainerMenu == null) { ++ AbstractContainerMenu container = menu.createMenu(this.containerCounter, this.getInventory(), this); ++ ++ // CraftBukkit start - Inventory open hook ++ if (container != null) { ++ container.setTitle(menu.getDisplayName()); ++ ++ boolean cancelled = false; ++ container = CraftEventFactory.callInventoryOpenEvent(this, container, cancelled); ++ if (container == null && !cancelled) { // Let pre-cancelled events fall through ++ // SPIGOT-5263 - close chest if cancelled ++ if (menu instanceof Container) { ++ ((Container) menu).stopOpen(this); ++ } else if (menu instanceof ChestBlock.DoubleInventory) { ++ // SPIGOT-5355 - double chests too :( ++ ((ChestBlock.DoubleInventory) menu).inventorylargechest.stopOpen(this); ++ } ++ return OptionalInt.empty(); ++ } ++ } ++ // CraftBukkit end ++ if (container == null) { + if (this.isSpectator()) { + this.displayClientMessage(Component.translatable("container.spectatorCantOpen").withStyle(ChatFormatting.RED), true); + } + + return OptionalInt.empty(); + } else { +- this.connection +- .send(new ClientboundOpenScreenPacket(abstractContainerMenu.containerId, abstractContainerMenu.getType(), menu.getDisplayName())); +- this.initMenu(abstractContainerMenu); +- this.containerMenu = abstractContainerMenu; ++ // CraftBukkit start ++ this.containerMenu = container; ++ this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); ++ // CraftBukkit end ++ this.initMenu(container); + return OptionalInt.of(this.containerCounter); + } + } +@@ -1006,18 +1442,29 @@ + + @Override + public void openHorseInventory(AbstractHorse horse, Container inventory) { ++ // CraftBukkit start - Inventory open hook ++ this.nextContainerCounter(); ++ AbstractContainerMenu container = new HorseInventoryMenu(this.containerCounter, this.getInventory(), inventory, horse); ++ container.setTitle(horse.getDisplayName()); ++ container = CraftEventFactory.callInventoryOpenEvent(this, container); ++ ++ if (container == null) { ++ inventory.stopOpen(this); ++ return; ++ } ++ // CraftBukkit end + if (this.containerMenu != this.inventoryMenu) { + this.closeContainer(); + } + +- this.nextContainerCounter(); ++ // this.nextContainerCounter(); // CraftBukkit - moved up + this.connection.send(new ClientboundHorseScreenOpenPacket(this.containerCounter, inventory.getContainerSize(), horse.getId())); +- this.containerMenu = new HorseInventoryMenu(this.containerCounter, this.getInventory(), inventory, horse); ++ this.containerMenu = container; // CraftBukkit + this.initMenu(this.containerMenu); + } + + @Override +- public void openItemGui(ItemStack stack, InteractionHand hand) { ++ public void openItemGui(ItemStack stack, EnumHand hand) { + if (stack.is(Items.WRITTEN_BOOK)) { + if (WrittenBookItem.resolveBookComponents(stack, this.createCommandSourceStack(), this)) { + this.containerMenu.broadcastChanges(); +@@ -1025,6 +1472,7 @@ + + this.connection.send(new ClientboundOpenBookPacket(hand)); + } ++ + } + + @Override +@@ -1034,6 +1482,7 @@ + + @Override + public void closeContainer() { ++ CraftEventFactory.handleInventoryCloseEvent(this); // CraftBukkit + this.connection.send(new ClientboundContainerClosePacket(this.containerMenu.containerId)); + this.doCloseContainer(); + } +@@ -1056,110 +1505,130 @@ + } + + this.jumping = jumping; ++ // CraftBukkit start ++ if (sneaking != this.isShiftKeyDown()) { ++ PlayerToggleSneakEvent event = new PlayerToggleSneakEvent(this.getBukkitEntity(), sneaking); ++ this.server.server.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + this.setShiftKeyDown(sneaking); + } ++ + } + + @Override + public void travel(Vec3 travelVector) { +- double x = this.getX(); +- double y = this.getY(); +- double z = this.getZ(); ++ double d0 = this.getX(); ++ double d1 = this.getY(); ++ double d2 = this.getZ(); ++ + super.travel(travelVector); +- this.checkMovementStatistics(this.getX() - x, this.getY() - y, this.getZ() - z); ++ this.checkMovementStatistics(this.getX() - d0, this.getY() - d1, this.getZ() - d2); + } + + @Override + public void rideTick() { +- double x = this.getX(); +- double y = this.getY(); +- double z = this.getZ(); ++ double d0 = this.getX(); ++ double d1 = this.getY(); ++ double d2 = this.getZ(); ++ + super.rideTick(); +- this.checkRidingStatistics(this.getX() - x, this.getY() - y, this.getZ() - z); ++ this.checkRidingStatistics(this.getX() - d0, this.getY() - d1, this.getZ() - d2); + } + +- public void checkMovementStatistics(double d, double d1, double d2) { +- if (!this.isPassenger() && !didNotMove(d, d1, d2)) { ++ public void checkMovementStatistics(double d0, double d1, double d2) { ++ if (!this.isPassenger() && !didNotMove(d0, d1, d2)) { ++ int i; ++ + if (this.isSwimming()) { +- int rounded = Math.round((float)Math.sqrt(d * d + d1 * d1 + d2 * d2) * 100.0F); +- if (rounded > 0) { +- this.awardStat(Stats.SWIM_ONE_CM, rounded); +- this.causeFoodExhaustion(0.01F * (float)rounded * 0.01F); ++ i = Math.round((float) Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2) * 100.0F); ++ if (i > 0) { ++ this.awardStat(Stats.SWIM_ONE_CM, i); ++ this.causeFoodExhaustion(0.01F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.SWIM); // CraftBukkit - EntityExhaustionEvent + } + } else if (this.isEyeInFluid(FluidTags.WATER)) { +- int rounded = Math.round((float)Math.sqrt(d * d + d1 * d1 + d2 * d2) * 100.0F); +- if (rounded > 0) { +- this.awardStat(Stats.WALK_UNDER_WATER_ONE_CM, rounded); +- this.causeFoodExhaustion(0.01F * (float)rounded * 0.01F); ++ i = Math.round((float) Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2) * 100.0F); ++ if (i > 0) { ++ this.awardStat(Stats.WALK_UNDER_WATER_ONE_CM, i); ++ this.causeFoodExhaustion(0.01F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.WALK_UNDERWATER); // CraftBukkit - EntityExhaustionEvent + } + } else if (this.isInWater()) { +- int rounded = Math.round((float)Math.sqrt(d * d + d2 * d2) * 100.0F); +- if (rounded > 0) { +- this.awardStat(Stats.WALK_ON_WATER_ONE_CM, rounded); +- this.causeFoodExhaustion(0.01F * (float)rounded * 0.01F); ++ i = Math.round((float) Math.sqrt(d0 * d0 + d2 * d2) * 100.0F); ++ if (i > 0) { ++ this.awardStat(Stats.WALK_ON_WATER_ONE_CM, i); ++ this.causeFoodExhaustion(0.01F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.WALK_ON_WATER); // CraftBukkit - EntityExhaustionEvent + } + } else if (this.onClimbable()) { +- if (d1 > 0.0) { +- this.awardStat(Stats.CLIMB_ONE_CM, (int)Math.round(d1 * 100.0)); ++ if (d1 > 0.0D) { ++ this.awardStat(Stats.CLIMB_ONE_CM, (int) Math.round(d1 * 100.0D)); + } + } else if (this.onGround()) { +- int rounded = Math.round((float)Math.sqrt(d * d + d2 * d2) * 100.0F); +- if (rounded > 0) { ++ i = Math.round((float) Math.sqrt(d0 * d0 + d2 * d2) * 100.0F); ++ if (i > 0) { + if (this.isSprinting()) { +- this.awardStat(Stats.SPRINT_ONE_CM, rounded); +- this.causeFoodExhaustion(0.1F * (float)rounded * 0.01F); ++ this.awardStat(Stats.SPRINT_ONE_CM, i); ++ this.causeFoodExhaustion(0.1F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.SPRINT); // CraftBukkit - EntityExhaustionEvent + } else if (this.isCrouching()) { +- this.awardStat(Stats.CROUCH_ONE_CM, rounded); +- this.causeFoodExhaustion(0.0F * (float)rounded * 0.01F); ++ this.awardStat(Stats.CROUCH_ONE_CM, i); ++ this.causeFoodExhaustion(0.0F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.CROUCH); // CraftBukkit - EntityExhaustionEvent + } else { +- this.awardStat(Stats.WALK_ONE_CM, rounded); +- this.causeFoodExhaustion(0.0F * (float)rounded * 0.01F); ++ this.awardStat(Stats.WALK_ONE_CM, i); ++ this.causeFoodExhaustion(0.0F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.WALK); // CraftBukkit - EntityExhaustionEvent + } + } + } else if (this.isFallFlying()) { +- int rounded = Math.round((float)Math.sqrt(d * d + d1 * d1 + d2 * d2) * 100.0F); +- this.awardStat(Stats.AVIATE_ONE_CM, rounded); ++ i = Math.round((float) Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2) * 100.0F); ++ this.awardStat(Stats.AVIATE_ONE_CM, i); + } else { +- int rounded = Math.round((float)Math.sqrt(d * d + d2 * d2) * 100.0F); +- if (rounded > 25) { +- this.awardStat(Stats.FLY_ONE_CM, rounded); ++ i = Math.round((float) Math.sqrt(d0 * d0 + d2 * d2) * 100.0F); ++ if (i > 25) { ++ this.awardStat(Stats.FLY_ONE_CM, i); + } + } ++ + } + } + +- private void checkRidingStatistics(double d, double d1, double d2) { +- if (this.isPassenger() && !didNotMove(d, d1, d2)) { +- int rounded = Math.round((float)Math.sqrt(d * d + d1 * d1 + d2 * d2) * 100.0F); +- Entity vehicle = this.getVehicle(); +- if (vehicle instanceof AbstractMinecart) { +- this.awardStat(Stats.MINECART_ONE_CM, rounded); +- } else if (vehicle instanceof Boat) { +- this.awardStat(Stats.BOAT_ONE_CM, rounded); +- } else if (vehicle instanceof Pig) { +- this.awardStat(Stats.PIG_ONE_CM, rounded); +- } else if (vehicle instanceof AbstractHorse) { +- this.awardStat(Stats.HORSE_ONE_CM, rounded); +- } else if (vehicle instanceof Strider) { +- this.awardStat(Stats.STRIDER_ONE_CM, rounded); ++ private void checkRidingStatistics(double d0, double d1, double d2) { ++ if (this.isPassenger() && !didNotMove(d0, d1, d2)) { ++ int i = Math.round((float) Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2) * 100.0F); ++ Entity entity = this.getVehicle(); ++ ++ if (entity instanceof AbstractMinecart) { ++ this.awardStat(Stats.MINECART_ONE_CM, i); ++ } else if (entity instanceof Boat) { ++ this.awardStat(Stats.BOAT_ONE_CM, i); ++ } else if (entity instanceof Pig) { ++ this.awardStat(Stats.PIG_ONE_CM, i); ++ } else if (entity instanceof AbstractHorse) { ++ this.awardStat(Stats.HORSE_ONE_CM, i); ++ } else if (entity instanceof Strider) { ++ this.awardStat(Stats.STRIDER_ONE_CM, i); + } ++ + } + } + +- private static boolean didNotMove(double d, double d1, double d2) { +- return d == 0.0 && d1 == 0.0 && d2 == 0.0; ++ private static boolean didNotMove(double d0, double d1, double d2) { ++ return d0 == 0.0D && d1 == 0.0D && d2 == 0.0D; + } + + @Override + public void awardStat(Stat stat, int amount) { + this.stats.increment(this, stat, amount); +- this.getScoreboard().forAllObjectives(stat, this, scoreAccess -> scoreAccess.add(amount)); ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(stat, this, (scoreaccess) -> { ++ scoreaccess.add(amount); ++ }); + } + + @Override + public void resetStat(Stat stat) { + this.stats.setValue(this, stat, 0); +- this.getScoreboard().forAllObjectives(stat, this, ScoreAccess::reset); ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(stat, this, ScoreAccess::reset); // CraftBukkit - Get our scores instead + } + + @Override +@@ -1168,15 +1637,16 @@ + } + + @Override +- public void triggerRecipeCrafted(RecipeHolder recipeHolder, List list) { +- CriteriaTriggers.RECIPE_CRAFTED.trigger(this, recipeHolder.id(), list); ++ public void triggerRecipeCrafted(RecipeHolder recipeholder, List list) { ++ CriteriaTriggers.RECIPE_CRAFTED.trigger(this, recipeholder.id(), list); + } + + @Override + public void awardRecipesByKey(List list) { +- List> list1 = list.stream() +- .flatMap(resourceLocation -> this.server.getRecipeManager().byKey(resourceLocation).stream()) +- .collect(Collectors.toList()); ++ List> list1 = (List) list.stream().flatMap((minecraftkey) -> { ++ return this.server.getRecipeManager().byKey(minecraftkey).stream(); ++ }).collect(Collectors.toList()); ++ + this.awardRecipes(list1); + } + +@@ -1197,6 +1667,7 @@ + if (this.isSleeping()) { + this.stopSleepInBed(true, false); + } ++ + } + + public boolean hasDisconnected() { +@@ -1205,6 +1676,7 @@ + + public void resetSentInfo() { + this.lastSentHealth = -1.0E8F; ++ this.lastSentExp = -1; // CraftBukkit - Added to reset + } + + @Override +@@ -1215,9 +1687,10 @@ + @Override + protected void completeUsingItem() { + if (!this.useItem.isEmpty() && this.isUsingItem()) { +- this.connection.send(new ClientboundEntityEventPacket(this, (byte)9)); ++ this.connection.send(new ClientboundEntityEventPacket(this, (byte) 9)); + super.completeUsingItem(); + } ++ + } + + @Override +@@ -1227,8 +1700,9 @@ + } + + public void lookAt(EntityAnchorArgument.Anchor fromAnchor, Entity entity, EntityAnchorArgument.Anchor toAnchor) { +- Vec3 vec3 = toAnchor.apply(entity); +- super.lookAt(fromAnchor, vec3); ++ Vec3 vec3d = toAnchor.apply(entity); ++ ++ super.lookAt(fromAnchor, vec3d); + this.connection.send(new ClientboundPlayerLookAtPacket(fromAnchor, entity, toAnchor)); + } + +@@ -1256,11 +1730,11 @@ + + this.enchantmentSeed = that.enchantmentSeed; + this.enderChestInventory = that.enderChestInventory; +- this.getEntityData().set(DATA_PLAYER_MODE_CUSTOMISATION, that.getEntityData().get(DATA_PLAYER_MODE_CUSTOMISATION)); ++ this.getEntityData().set(ServerPlayer.DATA_PLAYER_MODE_CUSTOMISATION, (Byte) that.getEntityData().get(ServerPlayer.DATA_PLAYER_MODE_CUSTOMISATION)); + this.lastSentExp = -1; + this.lastSentHealth = -1.0F; + this.lastSentFood = -1; +- this.recipeBook.copyOverData(that.recipeBook); ++ // this.recipeBook.copyOverData(entityplayer.recipeBook); // CraftBukkit + this.seenCredits = that.seenCredits; + this.enteredNetherPosition = that.enteredNetherPosition; + this.chunkTrackingView = that.chunkTrackingView; +@@ -1296,41 +1770,48 @@ + this.levitationStartPos = null; + } + +- CriteriaTriggers.EFFECTS_CHANGED.trigger(this, null); ++ CriteriaTriggers.EFFECTS_CHANGED.trigger(this, (Entity) null); + } + + @Override +- public void teleportTo(double x, double y, double z) { +- this.connection.teleport(x, y, z, this.getYRot(), this.getXRot(), RelativeMovement.ROTATION); ++ public void teleportTo(double x, double d1, double y) { ++ this.connection.teleport(x, d1, y, this.getYRot(), this.getXRot(), RelativeMovement.ROTATION); + } + + @Override +- public void teleportRelative(double dx, double dy, double dz) { +- this.connection.teleport(this.getX() + dx, this.getY() + dy, this.getZ() + dz, this.getYRot(), this.getXRot(), RelativeMovement.ALL); ++ public void teleportRelative(double dx, double d1, double dy) { ++ this.connection.teleport(this.getX() + dx, this.getY() + d1, this.getZ() + dy, this.getYRot(), this.getXRot(), RelativeMovement.ALL); + } + + @Override +- public boolean teleportTo(ServerLevel level, double x, double y, double z, Set relativeMovements, float yRot, float xRot) { +- ChunkPos chunkPos = new ChunkPos(BlockPos.containing(x, y, z)); +- level.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, chunkPos, 1, this.getId()); ++ public boolean teleportTo(ServerLevel level, double x, double d1, double y, Set set, float z, float f1) { ++ // CraftBukkit start ++ return teleportTo(level, x, d1, y, set, z, f1, TeleportCause.UNKNOWN); ++ } ++ ++ public boolean teleportTo(ServerLevel worldserver, double d0, double d1, double d2, Set set, float f, float f1, TeleportCause cause) { ++ // CraftBukkit end ++ ChunkPos chunkcoordintpair = new ChunkPos(BlockPos.containing(d0, d1, d2)); ++ ++ worldserver.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, chunkcoordintpair, 1, this.getId()); + this.stopRiding(); + if (this.isSleeping()) { + this.stopSleepInBed(true, true); + } + +- if (level == this.level()) { +- this.connection.teleport(x, y, z, yRot, xRot, relativeMovements); ++ if (worldserver == this.level()) { ++ this.connection.teleport(d0, d1, d2, f, f1, set, cause); // CraftBukkit + } else { +- this.teleportTo(level, x, y, z, yRot, xRot); ++ this.teleportTo(worldserver, d0, d1, d2, f, f1, cause); // CraftBukkit + } + +- this.setYHeadRot(yRot); ++ this.setYHeadRot(f); + return true; + } + + @Override +- public void moveTo(double x, double y, double z) { +- super.moveTo(x, y, z); ++ public void moveTo(double x, double d1, double y) { ++ super.moveTo(x, d1, y); + this.connection.resetPosition(); + } + +@@ -1353,14 +1834,14 @@ + } + + public ServerLevel serverLevel() { +- return (ServerLevel)this.level(); ++ return (ServerLevel) this.level(); + } + + public boolean setGameMode(GameType gameMode) { + if (!this.gameMode.changeGameModeForPlayer(gameMode)) { + return false; + } else { +- this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, (float)gameMode.getId())); ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, (float) gameMode.getId())); + if (gameMode == GameType.SPECTATOR) { + this.removeEntitiesOnShoulder(); + this.stopRiding(); +@@ -1391,24 +1872,17 @@ + + public void sendSystemMessage(Component component, boolean bypassHiddenChat) { + if (this.acceptsSystemMessages(bypassHiddenChat)) { +- this.connection +- .send( +- new ClientboundSystemChatPacket(component, bypassHiddenChat), +- PacketSendListener.exceptionallySend( +- () -> { +- if (this.acceptsSystemMessages(false)) { +- int i = 256; +- String string = component.getString(256); +- Component component1 = Component.literal(string).withStyle(ChatFormatting.YELLOW); +- return new ClientboundSystemChatPacket( +- Component.translatable("multiplayer.message_not_delivered", component1).withStyle(ChatFormatting.RED), false +- ); +- } else { +- return null; +- } +- } +- ) +- ); ++ this.connection.send(new ClientboundSystemChatPacket(component, bypassHiddenChat), PacketSendListener.exceptionallySend(() -> { ++ if (this.acceptsSystemMessages(false)) { ++ boolean flag1 = true; ++ String s = component.getString(256); ++ MutableComponent ichatmutablecomponent = Component.literal(s).withStyle(ChatFormatting.YELLOW); ++ ++ return new ClientboundSystemChatPacket(Component.translatable("multiplayer.message_not_delivered", ichatmutablecomponent).withStyle(ChatFormatting.RED), false); ++ } else { ++ return null; ++ } ++ })); + } + } + +@@ -1416,31 +1890,47 @@ + if (this.acceptsChatMessages()) { + message.sendToPlayer(this, filtered, boundType); + } ++ + } + + public String getIpAddress() { +- return this.connection.getRemoteAddress() instanceof InetSocketAddress inetSocketAddress +- ? InetAddresses.toAddrString(inetSocketAddress.getAddress()) +- : ""; ++ SocketAddress socketaddress = this.connection.getRemoteAddress(); ++ ++ if (socketaddress instanceof InetSocketAddress) { ++ InetSocketAddress inetsocketaddress = (InetSocketAddress) socketaddress; ++ ++ return InetAddresses.toAddrString(inetsocketaddress.getAddress()); ++ } else { ++ return ""; ++ } + } + +- public void updateOptions(ClientInformation clientInformation) { +- this.language = clientInformation.language(); +- this.requestedViewDistance = clientInformation.viewDistance(); +- this.chatVisibility = clientInformation.chatVisibility(); +- this.canChatColor = clientInformation.chatColors(); +- this.textFilteringEnabled = clientInformation.textFilteringEnabled(); +- this.allowsListing = clientInformation.allowsListing(); +- this.getEntityData().set(DATA_PLAYER_MODE_CUSTOMISATION, (byte)clientInformation.modelCustomisation()); +- this.getEntityData().set(DATA_PLAYER_MAIN_HAND, (byte)clientInformation.mainHand().getId()); ++ public void updateOptions(ClientInformation clientinformation) { ++ // CraftBukkit start ++ if (getMainArm() != clientinformation.mainHand()) { ++ PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(getBukkitEntity(), getMainArm() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT); ++ this.server.server.getPluginManager().callEvent(event); ++ } ++ if (!this.language.equals(clientinformation.language())) { ++ PlayerLocaleChangeEvent event = new PlayerLocaleChangeEvent(getBukkitEntity(), clientinformation.language()); ++ this.server.server.getPluginManager().callEvent(event); ++ } ++ // CraftBukkit end ++ this.language = clientinformation.language(); ++ this.requestedViewDistance = clientinformation.viewDistance(); ++ this.chatVisibility = clientinformation.chatVisibility(); ++ this.canChatColor = clientinformation.chatColors(); ++ this.textFilteringEnabled = clientinformation.textFilteringEnabled(); ++ this.allowsListing = clientinformation.allowsListing(); ++ this.getEntityData().set(ServerPlayer.DATA_PLAYER_MODE_CUSTOMISATION, (byte) clientinformation.modelCustomisation()); ++ this.getEntityData().set(ServerPlayer.DATA_PLAYER_MAIN_HAND, (byte) clientinformation.mainHand().getId()); + } + + public ClientInformation clientInformation() { +- int i = this.getEntityData().get(DATA_PLAYER_MODE_CUSTOMISATION); +- HumanoidArm humanoidArm = HumanoidArm.BY_ID.apply(this.getEntityData().get(DATA_PLAYER_MAIN_HAND)); +- return new ClientInformation( +- this.language, this.requestedViewDistance, this.chatVisibility, this.canChatColor, i, humanoidArm, this.textFilteringEnabled, this.allowsListing +- ); ++ byte b0 = (Byte) this.getEntityData().get(ServerPlayer.DATA_PLAYER_MODE_CUSTOMISATION); ++ HumanoidArm enummainhand = (HumanoidArm) HumanoidArm.BY_ID.apply((Byte) this.getEntityData().get(ServerPlayer.DATA_PLAYER_MAIN_HAND)); ++ ++ return new ClientInformation(this.language, this.requestedViewDistance, this.chatVisibility, this.canChatColor, b0, enummainhand, this.textFilteringEnabled, this.allowsListing); + } + + public boolean canChatInColor() { +@@ -1452,7 +1942,7 @@ + } + + private boolean acceptsSystemMessages(boolean bypassHiddenChat) { +- return this.chatVisibility != ChatVisiblity.HIDDEN || bypassHiddenChat; ++ return this.chatVisibility == ChatVisiblity.HIDDEN ? bypassHiddenChat : true; + } + + private boolean acceptsChatMessages() { +@@ -1464,12 +1954,7 @@ + } + + public void sendServerStatus(ServerStatus serverStatus) { +- this.connection +- .send( +- new ClientboundServerDataPacket( +- serverStatus.description(), serverStatus.favicon().map(ServerStatus.Favicon::iconBytes), serverStatus.enforcesSecureChat() +- ) +- ); ++ this.connection.send(new ClientboundServerDataPacket(serverStatus.description(), serverStatus.favicon().map(ServerStatus.a::iconBytes), serverStatus.enforcesSecureChat())); + } + + @Override +@@ -1497,18 +1982,24 @@ + } else { + super.updateInvisibilityStatus(); + } ++ + } + + public Entity getCamera() { +- return (Entity)(this.camera == null ? this : this.camera); ++ return (Entity) (this.camera == null ? this : this.camera); + } + + public void setCamera(@Nullable Entity entityToSpectate) { +- Entity camera = this.getCamera(); +- this.camera = (Entity)(entityToSpectate == null ? this : entityToSpectate); +- if (camera != this.camera) { +- if (this.camera.level() instanceof ServerLevel serverLevel) { +- this.teleportTo(serverLevel, this.camera.getX(), this.camera.getY(), this.camera.getZ(), Set.of(), this.getYRot(), this.getXRot()); ++ Entity entity1 = this.getCamera(); ++ ++ this.camera = (Entity) (entityToSpectate == null ? this : entityToSpectate); ++ if (entity1 != this.camera) { ++ Level world = this.camera.level(); ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ ++ this.teleportTo(worldserver, this.camera.getX(), this.camera.getY(), this.camera.getZ(), Set.of(), this.getYRot(), this.getXRot(), TeleportCause.SPECTATE); // CraftBukkit + } + + if (entityToSpectate != null) { +@@ -1518,6 +2009,7 @@ + this.connection.send(new ClientboundSetCameraPacket(this.camera)); + this.connection.resetPosition(); + } ++ + } + + @Override +@@ -1525,6 +2017,7 @@ + if (!this.isChangingDimension) { + super.processPortalCooldown(); + } ++ + } + + @Override +@@ -1534,6 +2027,7 @@ + } else { + super.attack(targetEntity); + } ++ + } + + public long getLastActionTime() { +@@ -1542,11 +2036,11 @@ + + @Nullable + public Component getTabListDisplayName() { +- return null; ++ return listName; // CraftBukkit + } + + @Override +- public void swing(InteractionHand hand) { ++ public void swing(EnumHand hand) { + super.swing(hand); + this.resetAttackStrengthTicker(); + } +@@ -1563,27 +2057,39 @@ + return this.advancements; + } + +- public void teleportTo(ServerLevel newLevel, double x, double y, double z, float yaw, float pitch) { ++ // CraftBukkit start ++ public void teleportTo(ServerLevel newLevel, double x, double d1, double y, float f, float z) { ++ this.teleportTo(newLevel, x, d1, y, f, z, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.UNKNOWN); ++ } ++ ++ public void teleportTo(ServerLevel worldserver, double d0, double d1, double d2, float f, float f1, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { ++ // CraftBukkit end + this.setCamera(this); + this.stopRiding(); +- if (newLevel == this.level()) { +- this.connection.teleport(x, y, z, yaw, pitch); ++ /* CraftBukkit start - replace with bukkit handling for multi-world ++ if (worldserver == this.level()) { ++ this.connection.teleport(d0, d1, d2, f, f1); + } else { +- ServerLevel serverLevel = this.serverLevel(); +- LevelData levelData = newLevel.getLevelData(); +- this.connection.send(new ClientboundRespawnPacket(this.createCommonSpawnInfo(newLevel), (byte)3)); +- this.connection.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked())); ++ WorldServer worldserver1 = this.serverLevel(); ++ WorldData worlddata = worldserver.getLevelData(); ++ ++ this.connection.send(new PacketPlayOutRespawn(this.createCommonSpawnInfo(worldserver), (byte) 3)); ++ this.connection.send(new PacketPlayOutServerDifficulty(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); + this.server.getPlayerList().sendPlayerPermissionLevel(this); +- serverLevel.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); ++ worldserver1.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); + this.unsetRemoved(); +- this.moveTo(x, y, z, yaw, pitch); +- this.setServerLevel(newLevel); +- newLevel.addDuringCommandTeleport(this); +- this.triggerDimensionChangeTriggers(serverLevel); +- this.connection.teleport(x, y, z, yaw, pitch); +- this.server.getPlayerList().sendLevelInfo(this, newLevel); ++ this.moveTo(d0, d1, d2, f, f1); ++ this.setServerLevel(worldserver); ++ worldserver.addDuringCommandTeleport(this); ++ this.triggerDimensionChangeTriggers(worldserver1); ++ this.connection.teleport(d0, d1, d2, f, f1); ++ this.server.getPlayerList().sendLevelInfo(this, worldserver); + this.server.getPlayerList().sendAllPlayerInfo(this); + } ++ */ ++ this.getBukkitEntity().teleport(new Location(worldserver.getWorld(), d0, d1, d2, f, f1), cause); ++ // CraftBukkit end ++ + } + + @Nullable +@@ -1604,22 +2110,50 @@ + } + + public void setRespawnPosition(ResourceKey dimension, @Nullable BlockPos position, float angle, boolean forced, boolean sendMessage) { +- if (position != null) { +- boolean flag = position.equals(this.respawnPosition) && dimension.equals(this.respawnDimension); +- if (sendMessage && !flag) { ++ // CraftBukkit start ++ this.setRespawnPosition(dimension, position, angle, forced, sendMessage, PlayerSpawnChangeEvent.Cause.UNKNOWN); ++ } ++ ++ public void setRespawnPosition(ResourceKey resourcekey, @Nullable BlockPos blockposition, float f, boolean flag, boolean flag1, PlayerSpawnChangeEvent.Cause cause) { ++ ServerLevel newWorld = this.server.getLevel(resourcekey); ++ Location newSpawn = (blockposition != null) ? CraftLocation.toBukkit(blockposition, newWorld.getWorld(), f, 0) : null; ++ ++ PlayerSpawnChangeEvent event = new PlayerSpawnChangeEvent(this.getBukkitEntity(), newSpawn, flag, cause); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ newSpawn = event.getNewSpawn(); ++ flag = event.isForced(); ++ ++ if (newSpawn != null) { ++ resourcekey = ((CraftWorld) newSpawn.getWorld()).getHandle().dimension(); ++ blockposition = BlockPos.containing(newSpawn.getX(), newSpawn.getY(), newSpawn.getZ()); ++ f = newSpawn.getYaw(); ++ } else { ++ resourcekey = Level.OVERWORLD; ++ blockposition = null; ++ f = 0.0F; ++ } ++ // CraftBukkit end ++ if (blockposition != null) { ++ boolean flag2 = blockposition.equals(this.respawnPosition) && resourcekey.equals(this.respawnDimension); ++ ++ if (flag1 && !flag2) { + this.sendSystemMessage(Component.translatable("block.minecraft.set_spawn")); + } + +- this.respawnPosition = position; +- this.respawnDimension = dimension; +- this.respawnAngle = angle; +- this.respawnForced = forced; ++ this.respawnPosition = blockposition; ++ this.respawnDimension = resourcekey; ++ this.respawnAngle = f; ++ this.respawnForced = flag; + } else { + this.respawnPosition = null; + this.respawnDimension = Level.OVERWORLD; + this.respawnAngle = 0.0F; + this.respawnForced = false; + } ++ + } + + public SectionPos getLastSectionPos() { +@@ -1634,37 +2168,34 @@ + return this.chunkTrackingView; + } + +- public void setChunkTrackingView(ChunkTrackingView chunkTrackingView) { +- this.chunkTrackingView = chunkTrackingView; ++ public void setChunkTrackingView(ChunkTrackingView chunktrackingview) { ++ this.chunkTrackingView = chunktrackingview; + } + + @Override + public void playNotifySound(SoundEvent sound, SoundSource source, float volume, float pitch) { +- this.connection +- .send( +- new ClientboundSoundPacket( +- BuiltInRegistries.SOUND_EVENT.wrapAsHolder(sound), source, this.getX(), this.getY(), this.getZ(), volume, pitch, this.random.nextLong() +- ) +- ); ++ this.connection.send(new ClientboundSoundPacket(BuiltInRegistries.SOUND_EVENT.wrapAsHolder(sound), source, this.getX(), this.getY(), this.getZ(), volume, pitch, this.random.nextLong())); + } + + @Override + public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean traceItem) { +- ItemEntity itemEntity = super.drop(droppedItem, dropAround, traceItem); +- if (itemEntity == null) { ++ ItemEntity entityitem = super.drop(droppedItem, dropAround, traceItem); ++ ++ if (entityitem == null) { + return null; + } else { +- this.level().addFreshEntity(itemEntity); +- ItemStack item = itemEntity.getItem(); ++ this.level().addFreshEntity(entityitem); ++ ItemStack itemstack1 = entityitem.getItem(); ++ + if (traceItem) { +- if (!item.isEmpty()) { +- this.awardStat(Stats.ITEM_DROPPED.get(item.getItem()), droppedItem.getCount()); ++ if (!itemstack1.isEmpty()) { ++ this.awardStat(Stats.ITEM_DROPPED.get(itemstack1.getItem()), droppedItem.getCount()); + } + + this.awardStat(Stats.DROP); + } + +- return itemEntity; ++ return entityitem; + } + } + +@@ -1683,25 +2214,23 @@ + } + + private GameType calculateGameModeForNewPlayer(@Nullable GameType gameType) { +- GameType forcedGameType = this.server.getForcedGameType(); +- if (forcedGameType != null) { +- return forcedGameType; +- } else { +- return gameType != null ? gameType : this.server.getDefaultGameType(); +- } ++ GameType enumgamemode1 = this.server.getForcedGameType(); ++ ++ return enumgamemode1 != null ? enumgamemode1 : (gameType != null ? gameType : this.server.getDefaultGameType()); + } + + public void loadGameTypes(@Nullable CompoundTag tag) { +- this.gameMode +- .setGameModeForPlayer(this.calculateGameModeForNewPlayer(readPlayerMode(tag, "playerGameType")), readPlayerMode(tag, "previousPlayerGameType")); ++ this.gameMode.setGameModeForPlayer(this.calculateGameModeForNewPlayer(readPlayerMode(tag, "playerGameType")), readPlayerMode(tag, "previousPlayerGameType")); + } + + private void storeGameTypes(CompoundTag tag) { + tag.putInt("playerGameType", this.gameMode.getGameModeForPlayer().getId()); +- GameType previousGameModeForPlayer = this.gameMode.getPreviousGameModeForPlayer(); +- if (previousGameModeForPlayer != null) { +- tag.putInt("previousPlayerGameType", previousGameModeForPlayer.getId()); ++ GameType enumgamemode = this.gameMode.getPreviousGameModeForPlayer(); ++ ++ if (enumgamemode != null) { ++ tag.putInt("previousPlayerGameType", enumgamemode.getId()); + } ++ + } + + @Override +@@ -1710,7 +2239,7 @@ + } + + public boolean shouldFilterMessageTo(ServerPlayer player) { +- return player != this && (this.textFilteringEnabled || player.textFilteringEnabled); ++ return player == this ? false : this.textFilteringEnabled || player.textFilteringEnabled; + } + + @Override +@@ -1725,10 +2254,13 @@ + } + + public boolean drop(boolean dropStack) { +- Inventory inventory = this.getInventory(); +- ItemStack itemStack = inventory.removeFromSelected(dropStack); +- this.containerMenu.findSlot(inventory, inventory.selected).ifPresent(i -> this.containerMenu.setRemoteSlot(i, inventory.getSelected())); +- return this.drop(itemStack, false, true) != null; ++ Inventory playerinventory = this.getInventory(); ++ ItemStack itemstack = playerinventory.removeFromSelected(dropStack); ++ ++ this.containerMenu.findSlot(playerinventory, playerinventory.selected).ifPresent((i) -> { ++ this.containerMenu.setRemoteSlot(i, playerinventory.getSelected()); ++ }); ++ return this.drop(itemstack, false, true) != null; + } + + public boolean allowsListing() { +@@ -1743,10 +2275,12 @@ + @Override + public void onItemPickup(ItemEntity itemEntity) { + super.onItemPickup(itemEntity); +- Entity owner = itemEntity.getOwner(); +- if (owner != null) { +- CriteriaTriggers.THROWN_ITEM_PICKED_UP_BY_PLAYER.trigger(this, itemEntity.getItem(), owner); ++ Entity entity = itemEntity.getOwner(); ++ ++ if (entity != null) { ++ CriteriaTriggers.THROWN_ITEM_PICKED_UP_BY_PLAYER.trigger(this, itemEntity.getItem(), entity); + } ++ + } + + public void setChatSession(RemoteChatSession chatSession) { +@@ -1759,8 +2293,8 @@ + } + + @Override +- public void indicateDamage(double xDistance, double zDistance) { +- this.hurtDir = (float)(Mth.atan2(zDistance, xDistance) * 180.0F / (float)Math.PI - (double)this.getYRot()); ++ public void indicateDamage(double xDistance, double d1) { ++ this.hurtDir = (float) (Mth.atan2(d1, xDistance) * 57.2957763671875D - (double) this.getYRot()); + this.connection.send(new ClientboundHurtAnimationPacket(this)); + } + +@@ -1771,9 +2305,14 @@ + } else { + vehicle.positionRider(this); + this.connection.teleport(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); +- if (vehicle instanceof LivingEntity livingEntity) { +- for (MobEffectInstance mobEffectInstance : livingEntity.getActiveEffects()) { +- this.connection.send(new ClientboundUpdateMobEffectPacket(vehicle.getId(), mobEffectInstance)); ++ if (vehicle instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) vehicle; ++ Iterator iterator = entityliving.getActiveEffects().iterator(); ++ ++ while (iterator.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); ++ ++ this.connection.send(new ClientboundUpdateMobEffectPacket(vehicle.getId(), mobeffect)); + } + } + +@@ -1783,26 +2322,165 @@ + + @Override + public void stopRiding() { +- Entity vehicle = this.getVehicle(); ++ Entity entity = this.getVehicle(); ++ + super.stopRiding(); +- if (vehicle instanceof LivingEntity livingEntity) { +- for (MobEffectInstance mobEffectInstance : livingEntity.getActiveEffects()) { +- this.connection.send(new ClientboundRemoveMobEffectPacket(vehicle.getId(), mobEffectInstance.getEffect())); ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ Iterator iterator = entityliving.getActiveEffects().iterator(); ++ ++ while (iterator.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); ++ ++ this.connection.send(new ClientboundRemoveMobEffectPacket(entity.getId(), mobeffect.getEffect())); + } + } ++ + } + +- public CommonPlayerSpawnInfo createCommonSpawnInfo(ServerLevel serverLevel) { +- return new CommonPlayerSpawnInfo( +- serverLevel.dimensionTypeId(), +- serverLevel.dimension(), +- BiomeManager.obfuscateSeed(serverLevel.getSeed()), +- this.gameMode.getGameModeForPlayer(), +- this.gameMode.getPreviousGameModeForPlayer(), +- serverLevel.isDebug(), +- serverLevel.isFlat(), +- this.getLastDeathLocation(), +- this.getPortalCooldown() +- ); ++ public CommonPlayerSpawnInfo createCommonSpawnInfo(ServerLevel worldserver) { ++ return new CommonPlayerSpawnInfo(worldserver.dimensionTypeId(), worldserver.dimension(), BiomeManager.obfuscateSeed(worldserver.getSeed()), this.gameMode.getGameModeForPlayer(), this.gameMode.getPreviousGameModeForPlayer(), worldserver.isDebug(), worldserver.isFlat(), this.getLastDeathLocation(), this.getPortalCooldown()); + } ++ ++ // CraftBukkit start - Add per-player time and weather. ++ public long timeOffset = 0; ++ public boolean relativeTime = true; ++ ++ public long getPlayerTime() { ++ if (this.relativeTime) { ++ // Adds timeOffset to the current server time. ++ return this.level().getDayTime() + this.timeOffset; ++ } else { ++ // Adds timeOffset to the beginning of this day. ++ return this.level().getDayTime() - (this.level().getDayTime() % 24000) + this.timeOffset; ++ } ++ } ++ ++ public WeatherType weather = null; ++ ++ public WeatherType getPlayerWeather() { ++ return this.weather; ++ } ++ ++ public void setPlayerWeather(WeatherType type, boolean plugin) { ++ if (!plugin && this.weather != null) { ++ return; ++ } ++ ++ if (plugin) { ++ this.weather = type; ++ } ++ ++ if (type == WeatherType.DOWNFALL) { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.STOP_RAINING, 0)); ++ } else { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.START_RAINING, 0)); ++ } ++ } ++ ++ private float pluginRainPosition; ++ private float pluginRainPositionPrevious; ++ ++ public void updateWeather(float oldRain, float newRain, float oldThunder, float newThunder) { ++ if (this.weather == null) { ++ // Vanilla ++ if (oldRain != newRain) { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, newRain)); ++ } ++ } else { ++ // Plugin ++ if (pluginRainPositionPrevious != pluginRainPosition) { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, pluginRainPosition)); ++ } ++ } ++ ++ if (oldThunder != newThunder) { ++ if (weather == WeatherType.DOWNFALL || weather == null) { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, newThunder)); ++ } else { ++ this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, 0)); ++ } ++ } ++ } ++ ++ public void tickWeather() { ++ if (this.weather == null) return; ++ ++ pluginRainPositionPrevious = pluginRainPosition; ++ if (weather == WeatherType.DOWNFALL) { ++ pluginRainPosition += 0.01; ++ } else { ++ pluginRainPosition -= 0.01; ++ } ++ ++ pluginRainPosition = Mth.clamp(pluginRainPosition, 0.0F, 1.0F); ++ } ++ ++ public void resetPlayerWeather() { ++ this.weather = null; ++ this.setPlayerWeather(this.level().getLevelData().isRaining() ? WeatherType.DOWNFALL : WeatherType.CLEAR, false); ++ } ++ ++ @Override ++ public String toString() { ++ return super.toString() + "(" + this.getScoreboardName() + " at " + this.getX() + "," + this.getY() + "," + this.getZ() + ")"; ++ } ++ ++ // SPIGOT-1903, MC-98153 ++ public void forceSetPositionRotation(double x, double y, double z, float yaw, float pitch) { ++ this.moveTo(x, y, z, yaw, pitch); ++ this.connection.resetPosition(); ++ } ++ ++ @Override ++ public boolean isImmobile() { ++ return super.isImmobile() || !getBukkitEntity().isOnline(); ++ } ++ ++ @Override ++ public Scoreboard getScoreboard() { ++ return getBukkitEntity().getScoreboard().getHandle(); ++ } ++ ++ public void reset() { ++ float exp = 0; ++ boolean keepInventory = this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY); ++ ++ if (this.keepLevel) { // CraftBukkit - SPIGOT-6687: Only use keepLevel (was pre-set with RULE_KEEPINVENTORY value in PlayerDeathEvent) ++ exp = this.experienceProgress; ++ this.newTotalExp = this.totalExperience; ++ this.newLevel = this.experienceLevel; ++ } ++ ++ this.setHealth(this.getMaxHealth()); ++ this.stopUsingItem(); // CraftBukkit - SPIGOT-6682: Clear active item on reset ++ this.setRemainingFireTicks(0); ++ this.fallDistance = 0; ++ this.foodData = new FoodData(this); ++ this.experienceLevel = this.newLevel; ++ this.totalExperience = this.newTotalExp; ++ this.experienceProgress = 0; ++ this.deathTime = 0; ++ this.setArrowCount(0, true); // CraftBukkit - ArrowBodyCountChangeEvent ++ this.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.DEATH); ++ this.effectsDirty = true; ++ this.containerMenu = this.inventoryMenu; ++ this.lastHurtByPlayer = null; ++ this.lastHurtByMob = null; ++ this.combatTracker = new CombatTracker(this); ++ this.lastSentExp = -1; ++ if (this.keepLevel) { // CraftBukkit - SPIGOT-6687: Only use keepLevel (was pre-set with RULE_KEEPINVENTORY value in PlayerDeathEvent) ++ this.experienceProgress = exp; ++ } else { ++ this.giveExperiencePoints(this.newExp); ++ } ++ this.keepLevel = false; ++ this.setDeltaMovement(0, 0, 0); // CraftBukkit - SPIGOT-6948: Reset velocity on death ++ } ++ ++ @Override ++ public CraftPlayer getBukkitEntity() { ++ return (CraftPlayer) super.getBukkitEntity(); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/level/ServerPlayerGameMode.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/level/ServerPlayerGameMode.java.patch new file mode 100644 index 0000000000..c2f18c5797 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/level/ServerPlayerGameMode.java.patch @@ -0,0 +1,617 @@ +--- a/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -9,40 +9,65 @@ + import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; + import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; + import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; +-import net.minecraft.server.network.ServerGamePacketListenerImpl; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; ++import net.minecraft.world.ITileInventory; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; +-import net.minecraft.world.MenuProvider; ++import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.item.DoubleHighBlockItem; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.GameType; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.GameMasterBlock; ++import net.minecraft.world.level.block.TrapDoorBlock; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; ++import org.slf4j.Logger; ++ ++// CraftBukkit start ++import java.util.ArrayList; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.network.ServerGamePacketListenerImpl; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.CakeBlock; ++import net.minecraft.world.level.block.DoorBlock; ++import net.minecraft.world.level.block.state.properties.BlockPropertyDoubleBlockHalf; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; +-import org.slf4j.Logger; ++import org.bukkit.GameMode; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockBreakEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.Event; ++import org.bukkit.event.block.Action; ++import org.bukkit.event.player.PlayerGameModeChangeEvent; ++import org.bukkit.event.player.PlayerInteractEvent; ++// CraftBukkit end + + public class ServerPlayerGameMode { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + protected ServerLevel level; + protected final ServerPlayer player; +- private GameType gameModeForPlayer = GameType.DEFAULT_MODE; ++ private GameType gameModeForPlayer; + @Nullable + private GameType previousGameModeForPlayer; + private boolean isDestroyingBlock; + private int destroyProgressStart; +- private BlockPos destroyPos = BlockPos.ZERO; ++ private BlockPos destroyPos; + private int gameTicks; + private boolean hasDelayedDestroy; +- private BlockPos delayedDestroyPos = BlockPos.ZERO; ++ private BlockPos delayedDestroyPos; + private int delayedTickStart; +- private int lastSentState = -1; ++ private int lastSentState; + + public ServerPlayerGameMode(ServerPlayer player) { ++ this.gameModeForPlayer = GameType.DEFAULT_MODE; ++ this.destroyPos = BlockPos.ZERO; ++ this.delayedDestroyPos = BlockPos.ZERO; ++ this.lastSentState = -1; + this.player = player; + this.level = player.serverLevel(); + } +@@ -51,12 +76,16 @@ + if (gameModeForPlayer == this.gameModeForPlayer) { + return false; + } else { ++ // CraftBukkit start ++ PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(player.getBukkitEntity(), GameMode.getByValue(gameModeForPlayer.getId())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end + this.setGameModeForPlayer(gameModeForPlayer, this.previousGameModeForPlayer); + this.player.onUpdateAbilities(); +- this.player +- .server +- .getPlayerList() +- .broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player)); ++ this.player.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player), this.player); // CraftBukkit + this.level.updateSleepingPlayerList(); + return true; + } +@@ -86,59 +115,87 @@ + } + + public void tick() { +- this.gameTicks++; ++ this.gameTicks = MinecraftServer.currentTick; // CraftBukkit; ++ IBlockData iblockdata; ++ + if (this.hasDelayedDestroy) { +- BlockState blockState = this.level.getBlockState(this.delayedDestroyPos); +- if (blockState.isAir()) { ++ iblockdata = this.level.getBlockState(this.delayedDestroyPos); ++ if (iblockdata.isAir()) { + this.hasDelayedDestroy = false; + } else { +- float f = this.incrementDestroyProgress(blockState, this.delayedDestroyPos, this.delayedTickStart); ++ float f = this.incrementDestroyProgress(iblockdata, this.delayedDestroyPos, this.delayedTickStart); ++ + if (f >= 1.0F) { + this.hasDelayedDestroy = false; + this.destroyBlock(this.delayedDestroyPos); + } + } + } else if (this.isDestroyingBlock) { +- BlockState blockState = this.level.getBlockState(this.destroyPos); +- if (blockState.isAir()) { ++ iblockdata = this.level.getBlockState(this.destroyPos); ++ if (iblockdata.isAir()) { + this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); + this.lastSentState = -1; + this.isDestroyingBlock = false; + } else { +- this.incrementDestroyProgress(blockState, this.destroyPos, this.destroyProgressStart); ++ this.incrementDestroyProgress(iblockdata, this.destroyPos, this.destroyProgressStart); + } + } ++ + } + +- private float incrementDestroyProgress(BlockState state, BlockPos pos, int startTick) { +- int i = this.gameTicks - startTick; +- float f = state.getDestroyProgress(this.player, this.player.level(), pos) * (float)(i + 1); +- int i1 = (int)(f * 10.0F); +- if (i1 != this.lastSentState) { +- this.level.destroyBlockProgress(this.player.getId(), pos, i1); +- this.lastSentState = i1; ++ private float incrementDestroyProgress(IBlockData state, BlockPos pos, int startTick) { ++ int j = this.gameTicks - startTick; ++ float f = state.getDestroyProgress(this.player, this.player.level(), pos) * (float) (j + 1); ++ int k = (int) (f * 10.0F); ++ ++ if (k != this.lastSentState) { ++ this.level.destroyBlockProgress(this.player.getId(), pos, k); ++ this.lastSentState = k; + } + + return f; + } + +- private void debugLogging(BlockPos pos, boolean flag, int sequence, String message) { +- } ++ private void debugLogging(BlockPos pos, boolean flag, int sequence, String message) {} + +- public void handleBlockBreakAction(BlockPos pos, ServerboundPlayerActionPacket.Action action, Direction face, int maxBuildHeight, int sequence) { ++ public void handleBlockBreakAction(BlockPos pos, ServerboundPlayerActionPacket.EnumPlayerDigType action, Direction face, int maxBuildHeight, int sequence) { + if (this.player.getEyePosition().distanceToSqr(Vec3.atCenterOf(pos)) > ServerGamePacketListenerImpl.MAX_INTERACTION_DISTANCE) { + this.debugLogging(pos, false, sequence, "too far"); + } else if (pos.getY() >= maxBuildHeight) { + this.player.connection.send(new ClientboundBlockUpdatePacket(pos, this.level.getBlockState(pos))); + this.debugLogging(pos, false, sequence, "too high"); + } else { +- if (action == ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK) { ++ IBlockData iblockdata; ++ ++ if (action == ServerboundPlayerActionPacket.EnumPlayerDigType.START_DESTROY_BLOCK) { + if (!this.level.mayInteract(this.player, pos)) { ++ // CraftBukkit start - fire PlayerInteractEvent ++ CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, pos, face, this.player.getInventory().getSelected(), EnumHand.MAIN_HAND); + this.player.connection.send(new ClientboundBlockUpdatePacket(pos, this.level.getBlockState(pos))); + this.debugLogging(pos, false, sequence, "may not interact"); ++ // Update any tile entity data for this block ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ if (tileentity != null) { ++ this.player.connection.send(tileentity.getUpdatePacket()); ++ } ++ // CraftBukkit end + return; + } + ++ // CraftBukkit start ++ PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, pos, face, this.player.getInventory().getSelected(), EnumHand.MAIN_HAND); ++ if (event.isCancelled()) { ++ // Let the client know the block still exists ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ // Update any tile entity data for this block ++ BlockEntity tileentity = this.level.getBlockEntity(pos); ++ if (tileentity != null) { ++ this.player.connection.send(tileentity.getUpdatePacket()); ++ } ++ return; ++ } ++ // CraftBukkit end ++ + if (this.isCreative()) { + this.destroyAndAck(pos, sequence, "creative destroy"); + return; +@@ -152,13 +209,46 @@ + + this.destroyProgressStart = this.gameTicks; + float f = 1.0F; +- BlockState blockState = this.level.getBlockState(pos); +- if (!blockState.isAir()) { +- blockState.attack(this.level, pos, this.player); +- f = blockState.getDestroyProgress(this.player, this.player.level(), pos); ++ ++ iblockdata = this.level.getBlockState(pos); ++ // CraftBukkit start - Swings at air do *NOT* exist. ++ if (event.useInteractedBlock() == Event.Result.DENY) { ++ // If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door. ++ IBlockData data = this.level.getBlockState(pos); ++ if (data.getBlock() instanceof DoorBlock) { ++ // For some reason *BOTH* the bottom/top part have to be marked updated. ++ boolean bottom = data.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER; ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, bottom ? pos.above() : pos.below())); ++ } else if (data.getBlock() instanceof TrapDoorBlock) { ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ } ++ } else if (!iblockdata.isAir()) { ++ iblockdata.attack(this.level, pos, this.player); ++ f = iblockdata.getDestroyProgress(this.player, this.player.level(), pos); + } + +- if (!blockState.isAir() && f >= 1.0F) { ++ if (event.useItemInHand() == Event.Result.DENY) { ++ // If we 'insta destroyed' then the client needs to be informed. ++ if (f > 1.0f) { ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ } ++ return; ++ } ++ org.bukkit.event.block.BlockDamageEvent blockEvent = CraftEventFactory.callBlockDamageEvent(this.player, pos, this.player.getInventory().getSelected(), f >= 1.0f); ++ ++ if (blockEvent.isCancelled()) { ++ // Let the client know the block still exists ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ return; ++ } ++ ++ if (blockEvent.getInstaBreak()) { ++ f = 2.0f; ++ } ++ // CraftBukkit end ++ ++ if (!iblockdata.isAir() && f >= 1.0F) { + this.destroyAndAck(pos, sequence, "insta mine"); + } else { + if (this.isDestroyingBlock) { +@@ -168,17 +258,20 @@ + + this.isDestroyingBlock = true; + this.destroyPos = pos.immutable(); +- int i = (int)(f * 10.0F); +- this.level.destroyBlockProgress(this.player.getId(), pos, i); ++ int k = (int) (f * 10.0F); ++ ++ this.level.destroyBlockProgress(this.player.getId(), pos, k); + this.debugLogging(pos, true, sequence, "actual start of destroying"); +- this.lastSentState = i; ++ this.lastSentState = k; + } +- } else if (action == ServerboundPlayerActionPacket.Action.STOP_DESTROY_BLOCK) { ++ } else if (action == ServerboundPlayerActionPacket.EnumPlayerDigType.STOP_DESTROY_BLOCK) { + if (pos.equals(this.destroyPos)) { +- int i1 = this.gameTicks - this.destroyProgressStart; +- BlockState blockStatex = this.level.getBlockState(pos); +- if (!blockStatex.isAir()) { +- float f1 = blockStatex.getDestroyProgress(this.player, this.player.level(), pos) * (float)(i1 + 1); ++ int l = this.gameTicks - this.destroyProgressStart; ++ ++ iblockdata = this.level.getBlockState(pos); ++ if (!iblockdata.isAir()) { ++ float f1 = iblockdata.getDestroyProgress(this.player, this.player.level(), pos) * (float) (l + 1); ++ + if (f1 >= 0.7F) { + this.isDestroyingBlock = false; + this.level.destroyBlockProgress(this.player.getId(), pos, -1); +@@ -196,17 +289,20 @@ + } + + this.debugLogging(pos, true, sequence, "stopped destroying"); +- } else if (action == ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK) { ++ } else if (action == ServerboundPlayerActionPacket.EnumPlayerDigType.ABORT_DESTROY_BLOCK) { + this.isDestroyingBlock = false; + if (!Objects.equals(this.destroyPos, pos)) { +- LOGGER.warn("Mismatch in destroy block pos: {} {}", this.destroyPos, pos); ++ ServerPlayerGameMode.LOGGER.debug("Mismatch in destroy block pos: {} {}", this.destroyPos, pos); // CraftBukkit - SPIGOT-5457 sent by client when interact event cancelled + this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); + this.debugLogging(pos, true, sequence, "aborted mismatched destroying"); + } + + this.level.destroyBlockProgress(this.player.getId(), pos, -1); + this.debugLogging(pos, true, sequence, "aborted destroying"); ++ ++ CraftEventFactory.callBlockDamageAbortEvent(this.player, pos, this.player.getInventory().getSelected()); // CraftBukkit + } ++ + } + } + +@@ -217,71 +313,149 @@ + this.player.connection.send(new ClientboundBlockUpdatePacket(pos, this.level.getBlockState(pos))); + this.debugLogging(pos, false, sequence, message); + } ++ + } + + public boolean destroyBlock(BlockPos pos) { +- BlockState blockState = this.level.getBlockState(pos); +- if (!this.player.getMainHandItem().getItem().canAttackBlock(blockState, this.level, pos, this.player)) { ++ IBlockData iblockdata = this.level.getBlockState(pos); ++ // CraftBukkit start - fire BlockBreakEvent ++ org.bukkit.block.Block bblock = CraftBlock.at(level, pos); ++ BlockBreakEvent event = null; ++ ++ if (this.player instanceof ServerPlayer) { ++ // Sword + Creative mode pre-cancel ++ boolean isSwordNoBreak = !this.player.getMainHandItem().getItem().canAttackBlock(iblockdata, this.level, pos, this.player); ++ ++ // Tell client the block is gone immediately then process events ++ // Don't tell the client if its a creative sword break because its not broken! ++ if (level.getBlockEntity(pos) == null && !isSwordNoBreak) { ++ ClientboundBlockUpdatePacket packet = new ClientboundBlockUpdatePacket(pos, Blocks.AIR.defaultBlockState()); ++ this.player.connection.send(packet); ++ } ++ ++ event = new BlockBreakEvent(bblock, this.player.getBukkitEntity()); ++ ++ // Sword + Creative mode pre-cancel ++ event.setCancelled(isSwordNoBreak); ++ ++ // Calculate default block experience ++ IBlockData nmsData = this.level.getBlockState(pos); ++ Block nmsBlock = nmsData.getBlock(); ++ ++ ItemStack itemstack = this.player.getItemBySlot(EquipmentSlot.MAINHAND); ++ ++ if (nmsBlock != null && !event.isCancelled() && !this.isCreative() && this.player.hasCorrectToolForDrops(nmsBlock.defaultBlockState())) { ++ event.setExpToDrop(nmsBlock.getExpDrop(nmsData, this.level, pos, itemstack, true)); ++ } ++ ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ if (isSwordNoBreak) { ++ return false; ++ } ++ // Let the client know the block still exists ++ this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); ++ ++ // Brute force all possible updates ++ for (Direction dir : Direction.values()) { ++ this.player.connection.send(new ClientboundBlockUpdatePacket(level, pos.relative(dir))); ++ } ++ ++ // Update any tile entity data for this block ++ BlockEntity tileentity = this.level.getBlockEntity(pos); ++ if (tileentity != null) { ++ this.player.connection.send(tileentity.getUpdatePacket()); ++ } ++ return false; ++ } ++ } ++ // CraftBukkit end ++ ++ if (false && !this.player.getMainHandItem().getItem().canAttackBlock(iblockdata, this.level, pos, this.player)) { // CraftBukkit - false + return false; + } else { +- BlockEntity blockEntity = this.level.getBlockEntity(pos); +- Block block = blockState.getBlock(); ++ iblockdata = this.level.getBlockState(pos); // CraftBukkit - update state from plugins ++ if (iblockdata.isAir()) return false; // CraftBukkit - A plugin set block to air without cancelling ++ BlockEntity tileentity = this.level.getBlockEntity(pos); ++ Block block = iblockdata.getBlock(); ++ + if (block instanceof GameMasterBlock && !this.player.canUseGameMasterBlocks()) { +- this.level.sendBlockUpdated(pos, blockState, blockState, 3); ++ this.level.sendBlockUpdated(pos, iblockdata, iblockdata, 3); + return false; + } else if (this.player.blockActionRestricted(this.level, pos, this.gameModeForPlayer)) { + return false; + } else { +- BlockState blockState1 = block.playerWillDestroy(this.level, pos, blockState, this.player); ++ // CraftBukkit start ++ org.bukkit.block.BlockState state = bblock.getState(); ++ level.captureDrops = new ArrayList<>(); ++ // CraftBukkit end ++ IBlockData iblockdata1 = block.playerWillDestroy(this.level, pos, iblockdata, this.player); + boolean flag = this.level.removeBlock(pos, false); ++ + if (flag) { +- block.destroy(this.level, pos, blockState1); ++ block.destroy(this.level, pos, iblockdata1); + } + + if (this.isCreative()) { +- return true; ++ // return true; // CraftBukkit + } else { +- ItemStack mainHandItem = this.player.getMainHandItem(); +- ItemStack itemStack = mainHandItem.copy(); +- boolean hasCorrectToolForDrops = this.player.hasCorrectToolForDrops(blockState1); +- mainHandItem.mineBlock(this.level, blockState1, pos, this.player); +- if (flag && hasCorrectToolForDrops) { +- block.playerDestroy(this.level, this.player, pos, blockState1, blockEntity, itemStack); ++ ItemStack itemstack = this.player.getMainHandItem(); ++ ItemStack itemstack1 = itemstack.copy(); ++ boolean flag1 = this.player.hasCorrectToolForDrops(iblockdata1); ++ ++ itemstack.mineBlock(this.level, iblockdata1, pos, this.player); ++ if (flag && flag1 && event.isDropItems()) { // CraftBukkit - Check if block should drop items ++ block.playerDestroy(this.level, this.player, pos, iblockdata1, tileentity, itemstack1); + } + +- return true; ++ // return true; // CraftBukkit + } ++ // CraftBukkit start ++ if (event.isDropItems()) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, level.captureDrops); ++ } ++ level.captureDrops = null; ++ ++ // Drop event experience ++ if (flag && event != null) { ++ iblockdata.getBlock().popExperience(this.level, pos, event.getExpToDrop()); ++ } ++ ++ return true; ++ // CraftBukkit end + } + } + } + +- public InteractionResult useItem(ServerPlayer player, Level level, ItemStack stack, InteractionHand hand) { ++ public InteractionResult useItem(ServerPlayer player, Level level, ItemStack stack, EnumHand hand) { + if (this.gameModeForPlayer == GameType.SPECTATOR) { + return InteractionResult.PASS; + } else if (player.getCooldowns().isOnCooldown(stack.getItem())) { + return InteractionResult.PASS; + } else { +- int count = stack.getCount(); +- int damageValue = stack.getDamageValue(); +- InteractionResultHolder interactionResultHolder = stack.use(level, player, hand); +- ItemStack itemStack = interactionResultHolder.getObject(); +- if (itemStack == stack && itemStack.getCount() == count && itemStack.getUseDuration() <= 0 && itemStack.getDamageValue() == damageValue) { +- return interactionResultHolder.getResult(); +- } else if (interactionResultHolder.getResult() == InteractionResult.FAIL && itemStack.getUseDuration() > 0 && !player.isUsingItem()) { +- return interactionResultHolder.getResult(); ++ int i = stack.getCount(); ++ int j = stack.getDamageValue(); ++ InteractionResultHolder interactionresultwrapper = stack.use(level, player, hand); ++ ItemStack itemstack1 = (ItemStack) interactionresultwrapper.getObject(); ++ ++ if (itemstack1 == stack && itemstack1.getCount() == i && itemstack1.getUseDuration() <= 0 && itemstack1.getDamageValue() == j) { ++ return interactionresultwrapper.getResult(); ++ } else if (interactionresultwrapper.getResult() == InteractionResult.FAIL && itemstack1.getUseDuration() > 0 && !player.isUsingItem()) { ++ return interactionresultwrapper.getResult(); + } else { +- if (stack != itemStack) { +- player.setItemInHand(hand, itemStack); ++ if (stack != itemstack1) { ++ player.setItemInHand(hand, itemstack1); + } + +- if (this.isCreative() && itemStack != ItemStack.EMPTY) { +- itemStack.setCount(count); +- if (itemStack.isDamageableItem() && itemStack.getDamageValue() != damageValue) { +- itemStack.setDamageValue(damageValue); ++ if (this.isCreative() && itemstack1 != ItemStack.EMPTY) { ++ itemstack1.setCount(i); ++ if (itemstack1.isDamageableItem() && itemstack1.getDamageValue() != j) { ++ itemstack1.setDamageValue(j); + } + } + +- if (itemStack.isEmpty()) { ++ if (itemstack1.isEmpty()) { + player.setItemInHand(hand, ItemStack.EMPTY); + } + +@@ -289,20 +463,62 @@ + player.inventoryMenu.sendAllDataToRemote(); + } + +- return interactionResultHolder.getResult(); ++ return interactionresultwrapper.getResult(); + } + } + } + +- public InteractionResult useItemOn(ServerPlayer player, Level level, ItemStack stack, InteractionHand hand, BlockHitResult hitResult) { +- BlockPos blockPos = hitResult.getBlockPos(); +- BlockState blockState = level.getBlockState(blockPos); +- if (!blockState.getBlock().isEnabled(level.enabledFeatures())) { ++ // CraftBukkit start - whole method ++ public boolean interactResult = false; ++ public boolean firedInteract = false; ++ public BlockPos interactPosition; ++ public EnumHand interactHand; ++ public ItemStack interactItemStack; ++ public InteractionResult useItemOn(ServerPlayer player, Level level, ItemStack stack, EnumHand hand, BlockHitResult hitResult) { ++ BlockPos blockposition = hitResult.getBlockPos(); ++ IBlockData iblockdata = level.getBlockState(blockposition); ++ InteractionResult enuminteractionresult = InteractionResult.PASS; ++ boolean cancelledBlock = false; ++ ++ if (!iblockdata.getBlock().isEnabled(level.enabledFeatures())) { + return InteractionResult.FAIL; + } else if (this.gameModeForPlayer == GameType.SPECTATOR) { +- MenuProvider menuProvider = blockState.getMenuProvider(level, blockPos); +- if (menuProvider != null) { +- player.openMenu(menuProvider); ++ ITileInventory itileinventory = iblockdata.getMenuProvider(level, blockposition); ++ cancelledBlock = !(itileinventory instanceof ITileInventory); ++ } ++ ++ if (player.getCooldowns().isOnCooldown(stack.getItem())) { ++ cancelledBlock = true; ++ } ++ ++ PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, blockposition, hitResult.getDirection(), stack, cancelledBlock, hand, hitResult.getLocation()); ++ firedInteract = true; ++ interactResult = event.useItemInHand() == Event.Result.DENY; ++ interactPosition = blockposition.immutable(); ++ interactHand = hand; ++ interactItemStack = stack.copy(); ++ ++ if (event.useInteractedBlock() == Event.Result.DENY) { ++ // If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door. ++ if (iblockdata.getBlock() instanceof DoorBlock) { ++ boolean bottom = iblockdata.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER; ++ player.connection.send(new ClientboundBlockUpdatePacket(level, bottom ? blockposition.above() : blockposition.below())); ++ } else if (iblockdata.getBlock() instanceof CakeBlock) { ++ player.getBukkitEntity().sendHealthUpdate(); // SPIGOT-1341 - reset health for cake ++ } else if (interactItemStack.getItem() instanceof DoubleHighBlockItem) { ++ // send a correcting update to the client, as it already placed the upper half of the bisected item ++ player.connection.send(new ClientboundBlockUpdatePacket(level, blockposition.relative(hitResult.getDirection()).above())); ++ ++ // send a correcting update to the client for the block above as well, this because of replaceable blocks (such as grass, sea grass etc) ++ player.connection.send(new ClientboundBlockUpdatePacket(level, blockposition.above())); ++ } ++ player.getBukkitEntity().updateInventory(); // SPIGOT-2867 ++ enuminteractionresult = (event.useItemInHand() != Event.Result.ALLOW) ? InteractionResult.SUCCESS : InteractionResult.PASS; ++ } else if (this.gameModeForPlayer == GameType.SPECTATOR) { ++ ITileInventory itileinventory = iblockdata.getMenuProvider(level, blockposition); ++ ++ if (itileinventory != null) { ++ player.openMenu(itileinventory); + return InteractionResult.SUCCESS; + } else { + return InteractionResult.PASS; +@@ -310,35 +526,39 @@ + } else { + boolean flag = !player.getMainHandItem().isEmpty() || !player.getOffhandItem().isEmpty(); + boolean flag1 = player.isSecondaryUseActive() && flag; +- ItemStack itemStack = stack.copy(); ++ ItemStack itemstack1 = stack.copy(); ++ + if (!flag1) { +- InteractionResult interactionResult = blockState.use(level, player, hand, hitResult); +- if (interactionResult.consumesAction()) { +- CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(player, blockPos, itemStack); +- return interactionResult; ++ enuminteractionresult = iblockdata.use(level, player, hand, hitResult); ++ ++ if (enuminteractionresult.consumesAction()) { ++ CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(player, blockposition, itemstack1); ++ return enuminteractionresult; + } + } + +- if (!stack.isEmpty() && !player.getCooldowns().isOnCooldown(stack.getItem())) { +- UseOnContext useOnContext = new UseOnContext(player, hand, hitResult); +- InteractionResult interactionResult1; ++ if (!stack.isEmpty() && enuminteractionresult != InteractionResult.SUCCESS && !interactResult) { // add !interactResult SPIGOT-764 ++ UseOnContext itemactioncontext = new UseOnContext(player, hand, hitResult); ++ InteractionResult enuminteractionresult1; ++ + if (this.isCreative()) { +- int count = stack.getCount(); +- interactionResult1 = stack.useOn(useOnContext); +- stack.setCount(count); ++ int i = stack.getCount(); ++ ++ enuminteractionresult1 = stack.useOn(itemactioncontext); ++ stack.setCount(i); + } else { +- interactionResult1 = stack.useOn(useOnContext); ++ enuminteractionresult1 = stack.useOn(itemactioncontext); + } + +- if (interactionResult1.consumesAction()) { +- CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(player, blockPos, itemStack); ++ if (enuminteractionresult1.consumesAction()) { ++ CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(player, blockposition, itemstack1); + } + +- return interactionResult1; +- } else { +- return InteractionResult.PASS; ++ return enuminteractionresult1; + } + } ++ return enuminteractionresult; ++ // CraftBukkit end + } + + public void setLevel(ServerLevel serverLevel) { diff --git a/patch-remap/mache-vineflower/net/minecraft/server/level/TicketType.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/level/TicketType.java.patch new file mode 100644 index 0000000000..d2e69d04a2 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/level/TicketType.java.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/server/level/TicketType.java ++++ b/net/minecraft/server/level/TicketType.java +@@ -7,24 +7,31 @@ + import net.minecraft.world.level.ChunkPos; + + public class TicketType { ++ + private final String name; + private final Comparator comparator; +- private final long timeout; +- public static final TicketType START = create("start", (unit, unit1) -> 0); +- public static final TicketType DRAGON = create("dragon", (unit, unit1) -> 0); ++ public long timeout; ++ public static final TicketType START = create("start", (unit, unit1) -> { ++ return 0; ++ }); ++ public static final TicketType DRAGON = create("dragon", (unit, unit1) -> { ++ return 0; ++ }); + public static final TicketType PLAYER = create("player", Comparator.comparingLong(ChunkPos::toLong)); + public static final TicketType FORCED = create("forced", Comparator.comparingLong(ChunkPos::toLong)); + public static final TicketType LIGHT = create("light", Comparator.comparingLong(ChunkPos::toLong)); + public static final TicketType PORTAL = create("portal", Vec3i::compareTo, 300); + public static final TicketType POST_TELEPORT = create("post_teleport", Integer::compareTo, 5); + public static final TicketType UNKNOWN = create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1); ++ public static final TicketType PLUGIN = create("plugin", (a, b) -> 0); // CraftBukkit ++ public static final TicketType PLUGIN_TICKET = create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit + + public static TicketType create(String name, Comparator comparator) { + return new TicketType<>(name, comparator, 0L); + } + + public static TicketType create(String name, Comparator comparator, int lifespan) { +- return new TicketType<>(name, comparator, (long)lifespan); ++ return new TicketType<>(name, comparator, (long) lifespan); + } + + protected TicketType(String name, Comparator comparator, long timeout) { +@@ -33,7 +40,6 @@ + this.timeout = timeout; + } + +- @Override + public String toString() { + return this.name; + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/level/WorldGenRegion.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/level/WorldGenRegion.java.patch new file mode 100644 index 0000000000..bf9c0c46d9 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/level/WorldGenRegion.java.patch @@ -0,0 +1,363 @@ +--- a/net/minecraft/server/level/WorldGenRegion.java ++++ b/net/minecraft/server/level/WorldGenRegion.java +@@ -37,7 +37,7 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.EntityBlock; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.border.WorldBorder; + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkSource; +@@ -57,6 +57,7 @@ + import org.slf4j.Logger; + + public class WorldGenRegion implements WorldGenLevel { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private final List cache; + private final ChunkAccess center; +@@ -66,8 +67,12 @@ + private final LevelData levelData; + private final RandomSource random; + private final DimensionType dimensionType; +- private final WorldGenTickAccess blockTicks = new WorldGenTickAccess<>(blockPos -> this.getChunk(blockPos).getBlockTicks()); +- private final WorldGenTickAccess fluidTicks = new WorldGenTickAccess<>(blockPos -> this.getChunk(blockPos).getFluidTicks()); ++ private final WorldGenTickAccess blockTicks = new WorldGenTickAccess<>((blockposition) -> { ++ return this.getChunk(blockposition).getBlockTicks(); ++ }); ++ private final WorldGenTickAccess fluidTicks = new WorldGenTickAccess<>((blockposition) -> { ++ return this.getChunk(blockposition).getFluidTicks(); ++ }); + private final BiomeManager biomeManager; + private final ChunkPos firstPos; + private final ChunkPos lastPos; +@@ -82,21 +87,22 @@ + public WorldGenRegion(ServerLevel level, List cache, ChunkStatus generatingStatus, int writeRadiusCutoff) { + this.generatingStatus = generatingStatus; + this.writeRadiusCutoff = writeRadiusCutoff; +- int floor = Mth.floor(Math.sqrt((double)cache.size())); +- if (floor * floor != cache.size()) { +- throw (IllegalStateException)Util.pauseInIde(new IllegalStateException("Cache size is not a square.")); ++ int j = Mth.floor(Math.sqrt((double) cache.size())); ++ ++ if (j * j != cache.size()) { ++ throw (IllegalStateException) Util.pauseInIde(new IllegalStateException("Cache size is not a square.")); + } else { + this.cache = cache; +- this.center = cache.get(cache.size() / 2); +- this.size = floor; ++ this.center = (ChunkAccess) cache.get(cache.size() / 2); ++ this.size = j; + this.level = level; + this.seed = level.getSeed(); + this.levelData = level.getLevelData(); +- this.random = level.getChunkSource().randomState().getOrCreateRandomFactory(WORLDGEN_REGION_RANDOM).at(this.center.getPos().getWorldPosition()); ++ this.random = level.getChunkSource().randomState().getOrCreateRandomFactory(WorldGenRegion.WORLDGEN_REGION_RANDOM).at(this.center.getPos().getWorldPosition()); + this.dimensionType = level.dimensionType(); + this.biomeManager = new BiomeManager(this, BiomeManager.obfuscateSeed(this.seed)); +- this.firstPos = cache.get(0).getPos(); +- this.lastPos = cache.get(cache.size() - 1).getPos(); ++ this.firstPos = ((ChunkAccess) cache.get(0)).getPos(); ++ this.lastPos = ((ChunkAccess) cache.get(cache.size() - 1)).getPos(); + this.structureManager = level.structureManager().forWorldGenRegion(this); + } + } +@@ -122,35 +128,29 @@ + @Nullable + @Override + public ChunkAccess getChunk(int x, int z, ChunkStatus requiredStatus, boolean nonnull) { +- ChunkAccess chunkAccess; ++ ChunkAccess ichunkaccess; ++ + if (this.hasChunk(x, z)) { +- int i = x - this.firstPos.x; +- int i1 = z - this.firstPos.z; +- chunkAccess = this.cache.get(i + i1 * this.size); +- if (chunkAccess.getStatus().isOrAfter(requiredStatus)) { +- return chunkAccess; ++ int k = x - this.firstPos.x; ++ int l = z - this.firstPos.z; ++ ++ ichunkaccess = (ChunkAccess) this.cache.get(k + l * this.size); ++ if (ichunkaccess.getStatus().isOrAfter(requiredStatus)) { ++ return ichunkaccess; + } + } else { +- chunkAccess = null; ++ ichunkaccess = null; + } + + if (!nonnull) { + return null; + } else { +- LOGGER.error("Requested chunk : {} {}", x, z); +- LOGGER.error("Region bounds : {} {} | {} {}", this.firstPos.x, this.firstPos.z, this.lastPos.x, this.lastPos.z); +- if (chunkAccess != null) { +- throw (RuntimeException)Util.pauseInIde( +- new RuntimeException( +- String.format( +- Locale.ROOT, "Chunk is not of correct status. Expecting %s, got %s | %s %s", requiredStatus, chunkAccess.getStatus(), x, z +- ) +- ) +- ); ++ WorldGenRegion.LOGGER.error("Requested chunk : {} {}", x, z); ++ WorldGenRegion.LOGGER.error("Region bounds : {} {} | {} {}", new Object[]{this.firstPos.x, this.firstPos.z, this.lastPos.x, this.lastPos.z}); ++ if (ichunkaccess != null) { ++ throw (RuntimeException) Util.pauseInIde(new RuntimeException(String.format(Locale.ROOT, "Chunk is not of correct status. Expecting %s, got %s | %s %s", requiredStatus, ichunkaccess.getStatus(), x, z))); + } else { +- throw (RuntimeException)Util.pauseInIde( +- new RuntimeException(String.format(Locale.ROOT, "We are asking a region for a chunk out of bound | %s %s", x, z)) +- ); ++ throw (RuntimeException) Util.pauseInIde(new RuntimeException(String.format(Locale.ROOT, "We are asking a region for a chunk out of bound | %s %s", x, z))); + } + } + } +@@ -161,7 +161,7 @@ + } + + @Override +- public BlockState getBlockState(BlockPos pos) { ++ public IBlockData getBlockState(BlockPos pos) { + return this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())).getBlockState(pos); + } + +@@ -172,7 +172,7 @@ + + @Nullable + @Override +- public Player getNearestPlayer(double x, double y, double z, double distance, Predicate predicate) { ++ public Player getNearestPlayer(double x, double d1, double y, double d3, Predicate z) { + return null; + } + +@@ -203,13 +203,15 @@ + + @Override + public boolean destroyBlock(BlockPos pos, boolean dropBlock, @Nullable Entity entity, int recursionLeft) { +- BlockState blockState = this.getBlockState(pos); +- if (blockState.isAir()) { ++ IBlockData iblockdata = this.getBlockState(pos); ++ ++ if (iblockdata.isAir()) { + return false; + } else { +- if (dropBlock) { +- BlockEntity blockEntity = blockState.hasBlockEntity() ? this.getBlockEntity(pos) : null; +- Block.dropResources(blockState, this.level, pos, blockEntity, entity, ItemStack.EMPTY); ++ if (false) { // CraftBukkit - SPIGOT-6833: Do not drop during world generation ++ BlockEntity tileentity = iblockdata.hasBlockEntity() ? this.getBlockEntity(pos) : null; ++ ++ Block.dropResources(iblockdata, this.level, pos, tileentity, entity, ItemStack.EMPTY); + } + + return this.setBlock(pos, Blocks.AIR.defaultBlockState(), 3, recursionLeft); +@@ -219,32 +221,34 @@ + @Nullable + @Override + public BlockEntity getBlockEntity(BlockPos pos) { +- ChunkAccess chunk = this.getChunk(pos); +- BlockEntity blockEntity = chunk.getBlockEntity(pos); +- if (blockEntity != null) { +- return blockEntity; ++ ChunkAccess ichunkaccess = this.getChunk(pos); ++ BlockEntity tileentity = ichunkaccess.getBlockEntity(pos); ++ ++ if (tileentity != null) { ++ return tileentity; + } else { +- CompoundTag blockEntityNbt = chunk.getBlockEntityNbt(pos); +- BlockState blockState = chunk.getBlockState(pos); +- if (blockEntityNbt != null) { +- if ("DUMMY".equals(blockEntityNbt.getString("id"))) { +- if (!blockState.hasBlockEntity()) { ++ CompoundTag nbttagcompound = ichunkaccess.getBlockEntityNbt(pos); ++ IBlockData iblockdata = ichunkaccess.getBlockState(pos); ++ ++ if (nbttagcompound != null) { ++ if ("DUMMY".equals(nbttagcompound.getString("id"))) { ++ if (!iblockdata.hasBlockEntity()) { + return null; + } + +- blockEntity = ((EntityBlock)blockState.getBlock()).newBlockEntity(pos, blockState); ++ tileentity = ((EntityBlock) iblockdata.getBlock()).newBlockEntity(pos, iblockdata); + } else { +- blockEntity = BlockEntity.loadStatic(pos, blockState, blockEntityNbt); ++ tileentity = BlockEntity.loadStatic(pos, iblockdata, nbttagcompound); + } + +- if (blockEntity != null) { +- chunk.setBlockEntity(blockEntity); +- return blockEntity; ++ if (tileentity != null) { ++ ichunkaccess.setBlockEntity(tileentity); ++ return tileentity; + } + } + +- if (blockState.hasBlockEntity()) { +- LOGGER.warn("Tried to access a block entity before it was created. {}", pos); ++ if (iblockdata.hasBlockEntity()) { ++ WorldGenRegion.LOGGER.warn("Tried to access a block entity before it was created. {}", pos); + } + + return null; +@@ -254,64 +258,59 @@ + @Override + public boolean ensureCanWrite(BlockPos pos) { + int i = SectionPos.blockToSectionCoord(pos.getX()); +- int i1 = SectionPos.blockToSectionCoord(pos.getZ()); +- ChunkPos center = this.getCenter(); +- int abs = Math.abs(center.x - i); +- int abs1 = Math.abs(center.z - i1); +- if (abs <= this.writeRadiusCutoff && abs1 <= this.writeRadiusCutoff) { ++ int j = SectionPos.blockToSectionCoord(pos.getZ()); ++ ChunkPos chunkcoordintpair = this.getCenter(); ++ int k = Math.abs(chunkcoordintpair.x - i); ++ int l = Math.abs(chunkcoordintpair.z - j); ++ ++ if (k <= this.writeRadiusCutoff && l <= this.writeRadiusCutoff) { + if (this.center.isUpgrading()) { +- LevelHeightAccessor heightAccessorForGeneration = this.center.getHeightAccessorForGeneration(); +- if (pos.getY() < heightAccessorForGeneration.getMinBuildHeight() || pos.getY() >= heightAccessorForGeneration.getMaxBuildHeight()) { ++ LevelHeightAccessor levelheightaccessor = this.center.getHeightAccessorForGeneration(); ++ ++ if (pos.getY() < levelheightaccessor.getMinBuildHeight() || pos.getY() >= levelheightaccessor.getMaxBuildHeight()) { + return false; + } + } + + return true; + } else { +- Util.logAndPauseIfInIde( +- "Detected setBlock in a far chunk [" +- + i +- + ", " +- + i1 +- + "], pos: " +- + pos +- + ", status: " +- + this.generatingStatus +- + (this.currentlyGenerating == null ? "" : ", currently generating: " + this.currentlyGenerating.get()) +- ); ++ Util.logAndPauseIfInIde("Detected setBlock in a far chunk [" + i + ", " + j + "], pos: " + pos + ", status: " + this.generatingStatus + (this.currentlyGenerating == null ? "" : ", currently generating: " + (String) this.currentlyGenerating.get())); + return false; + } + } + + @Override +- public boolean setBlock(BlockPos pos, BlockState state, int flags, int recursionLeft) { ++ public boolean setBlock(BlockPos pos, IBlockData state, int flags, int recursionLeft) { + if (!this.ensureCanWrite(pos)) { + return false; + } else { +- ChunkAccess chunk = this.getChunk(pos); +- BlockState blockState = chunk.setBlockState(pos, state, false); +- if (blockState != null) { +- this.level.onBlockStateChange(pos, blockState, state); ++ ChunkAccess ichunkaccess = this.getChunk(pos); ++ IBlockData iblockdata1 = ichunkaccess.setBlockState(pos, state, false); ++ ++ if (iblockdata1 != null) { ++ this.level.onBlockStateChange(pos, iblockdata1, state); + } + + if (state.hasBlockEntity()) { +- if (chunk.getStatus().getChunkType() == ChunkStatus.ChunkType.LEVELCHUNK) { +- BlockEntity blockEntity = ((EntityBlock)state.getBlock()).newBlockEntity(pos, state); +- if (blockEntity != null) { +- chunk.setBlockEntity(blockEntity); ++ if (ichunkaccess.getStatus().getChunkType() == ChunkStatus.Type.LEVELCHUNK) { ++ BlockEntity tileentity = ((EntityBlock) state.getBlock()).newBlockEntity(pos, state); ++ ++ if (tileentity != null) { ++ ichunkaccess.setBlockEntity(tileentity); + } else { +- chunk.removeBlockEntity(pos); ++ ichunkaccess.removeBlockEntity(pos); + } + } else { +- CompoundTag compoundTag = new CompoundTag(); +- compoundTag.putInt("x", pos.getX()); +- compoundTag.putInt("y", pos.getY()); +- compoundTag.putInt("z", pos.getZ()); +- compoundTag.putString("id", "DUMMY"); +- chunk.setBlockEntityNbt(compoundTag); ++ CompoundTag nbttagcompound = new CompoundTag(); ++ ++ nbttagcompound.putInt("x", pos.getX()); ++ nbttagcompound.putInt("y", pos.getY()); ++ nbttagcompound.putInt("z", pos.getZ()); ++ nbttagcompound.putString("id", "DUMMY"); ++ ichunkaccess.setBlockEntityNbt(nbttagcompound); + } +- } else if (blockState != null && blockState.hasBlockEntity()) { +- chunk.removeBlockEntity(pos); ++ } else if (iblockdata1 != null && iblockdata1.hasBlockEntity()) { ++ ichunkaccess.removeBlockEntity(pos); + } + + if (state.hasPostProcess(this, pos)) { +@@ -328,9 +327,17 @@ + + @Override + public boolean addFreshEntity(Entity entity) { ++ // CraftBukkit start ++ return addFreshEntity(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ @Override ++ public boolean addFreshEntity(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ // CraftBukkit end + int i = SectionPos.blockToSectionCoord(entity.getBlockX()); +- int i1 = SectionPos.blockToSectionCoord(entity.getBlockZ()); +- this.getChunk(i, i1).addEntity(entity); ++ int j = SectionPos.blockToSectionCoord(entity.getBlockZ()); ++ ++ this.getChunk(i, j).addEntity(entity); + return true; + } + +@@ -349,6 +356,7 @@ + return false; + } + ++ /** @deprecated */ + @Deprecated + @Override + public ServerLevel getLevel() { +@@ -421,20 +429,16 @@ + } + + @Override +- public void playSound(@Nullable Player player, BlockPos pos, SoundEvent sound, SoundSource category, float volume, float pitch) { +- } ++ public void playSound(@Nullable Player player, BlockPos pos, SoundEvent sound, SoundSource category, float volume, float pitch) {} + + @Override +- public void addParticle(ParticleOptions particleData, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { +- } ++ public void addParticle(ParticleOptions particleData, double x, double d1, double y, double d3, double z, double d5) {} + + @Override +- public void levelEvent(@Nullable Player player, int type, BlockPos pos, int data) { +- } ++ public void levelEvent(@Nullable Player player, int type, BlockPos pos, int data) {} + + @Override +- public void gameEvent(GameEvent event, Vec3 position, GameEvent.Context context) { +- } ++ public void gameEvent(GameEvent event, Vec3 position, GameEvent.Context context) {} + + @Override + public DimensionType dimensionType() { +@@ -442,7 +446,7 @@ + } + + @Override +- public boolean isStateAtPosition(BlockPos pos, Predicate state) { ++ public boolean isStateAtPosition(BlockPos pos, Predicate state) { + return state.test(this.getBlockState(pos)); + } + diff --git a/patch-remap/mache-vineflower/net/minecraft/server/network/LegacyQueryHandler.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/network/LegacyQueryHandler.java.patch new file mode 100644 index 0000000000..360dfca374 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/network/LegacyQueryHandler.java.patch @@ -0,0 +1,180 @@ +--- a/net/minecraft/server/network/LegacyQueryHandler.java ++++ b/net/minecraft/server/network/LegacyQueryHandler.java +@@ -12,113 +12,122 @@ + import org.slf4j.Logger; + + public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private final ServerInfo server; + +- public LegacyQueryHandler(ServerInfo serverInfo) { +- this.server = serverInfo; ++ public LegacyQueryHandler(ServerInfo serverinfo) { ++ this.server = serverinfo; + } + +- @Override +- public void channelRead(ChannelHandlerContext context, Object message) { +- ByteBuf byteBuf = (ByteBuf)message; +- byteBuf.markReaderIndex(); ++ public void channelRead(ChannelHandlerContext channelhandlercontext, Object object) { ++ ByteBuf bytebuf = (ByteBuf) object; ++ ++ bytebuf.markReaderIndex(); + boolean flag = true; + + try { + try { +- if (byteBuf.readUnsignedByte() != 254) { ++ if (bytebuf.readUnsignedByte() != 254) { + return; + } + +- SocketAddress socketAddress = context.channel().remoteAddress(); +- int i = byteBuf.readableBytes(); ++ SocketAddress socketaddress = channelhandlercontext.channel().remoteAddress(); ++ int i = bytebuf.readableBytes(); ++ String s; ++ org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(socketaddress, server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); // CraftBukkit ++ + if (i == 0) { +- LOGGER.debug("Ping: (<1.3.x) from {}", socketAddress); +- String string = createVersion0Response(this.server); +- sendFlushAndClose(context, createLegacyDisconnectPacket(context.alloc(), string)); ++ LegacyQueryHandler.LOGGER.debug("Ping: (<1.3.x) from {}", socketaddress); ++ s = createVersion0Response(this.server, event); // CraftBukkit ++ sendFlushAndClose(channelhandlercontext, createLegacyDisconnectPacket(channelhandlercontext.alloc(), s)); + } else { +- if (byteBuf.readUnsignedByte() != 1) { ++ if (bytebuf.readUnsignedByte() != 1) { + return; + } + +- if (byteBuf.isReadable()) { +- if (!readCustomPayloadPacket(byteBuf)) { ++ if (bytebuf.isReadable()) { ++ if (!readCustomPayloadPacket(bytebuf)) { + return; + } + +- LOGGER.debug("Ping: (1.6) from {}", socketAddress); ++ LegacyQueryHandler.LOGGER.debug("Ping: (1.6) from {}", socketaddress); + } else { +- LOGGER.debug("Ping: (1.4-1.5.x) from {}", socketAddress); ++ LegacyQueryHandler.LOGGER.debug("Ping: (1.4-1.5.x) from {}", socketaddress); + } + +- String string = createVersion1Response(this.server); +- sendFlushAndClose(context, createLegacyDisconnectPacket(context.alloc(), string)); ++ s = createVersion1Response(this.server, event); // CraftBukkit ++ sendFlushAndClose(channelhandlercontext, createLegacyDisconnectPacket(channelhandlercontext.alloc(), s)); + } + +- byteBuf.release(); ++ bytebuf.release(); + flag = false; +- } catch (RuntimeException var11) { ++ } catch (RuntimeException runtimeexception) { ++ ; + } ++ + } finally { + if (flag) { +- byteBuf.resetReaderIndex(); +- context.channel().pipeline().remove(this); +- context.fireChannelRead(message); ++ bytebuf.resetReaderIndex(); ++ channelhandlercontext.channel().pipeline().remove(this); ++ channelhandlercontext.fireChannelRead(object); + } ++ + } + } + +- private static boolean readCustomPayloadPacket(ByteBuf byteBuf) { +- short unsignedByte = byteBuf.readUnsignedByte(); +- if (unsignedByte != 250) { ++ private static boolean readCustomPayloadPacket(ByteBuf bytebuf) { ++ short short0 = bytebuf.readUnsignedByte(); ++ ++ if (short0 != 250) { + return false; + } else { +- String legacyString = LegacyProtocolUtils.readLegacyString(byteBuf); +- if (!"MC|PingHost".equals(legacyString)) { ++ String s = LegacyProtocolUtils.readLegacyString(bytebuf); ++ ++ if (!"MC|PingHost".equals(s)) { + return false; + } else { +- int unsignedShort = byteBuf.readUnsignedShort(); +- if (byteBuf.readableBytes() != unsignedShort) { ++ int i = bytebuf.readUnsignedShort(); ++ ++ if (bytebuf.readableBytes() != i) { + return false; + } else { +- short unsignedByte1 = byteBuf.readUnsignedByte(); +- if (unsignedByte1 < 73) { ++ short short1 = bytebuf.readUnsignedByte(); ++ ++ if (short1 < 73) { + return false; + } else { +- String legacyString1 = LegacyProtocolUtils.readLegacyString(byteBuf); +- int _int = byteBuf.readInt(); +- return _int <= 65535; ++ String s1 = LegacyProtocolUtils.readLegacyString(bytebuf); ++ int j = bytebuf.readInt(); ++ ++ return j <= 65535; + } + } + } + } + } + +- private static String createVersion0Response(ServerInfo serverInfo) { +- return String.format(Locale.ROOT, "%s§%d§%d", serverInfo.getMotd(), serverInfo.getPlayerCount(), serverInfo.getMaxPlayers()); ++ // CraftBukkit start ++ private static String createVersion0Response(ServerInfo serverinfo, org.bukkit.event.server.ServerListPingEvent event) { ++ return String.format(Locale.ROOT, "%s\u00a7%d\u00a7%d", event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); ++ // CraftBukkit end + } + +- private static String createVersion1Response(ServerInfo serverInfo) { +- return String.format( +- Locale.ROOT, +- "§1\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", +- 127, +- serverInfo.getServerVersion(), +- serverInfo.getMotd(), +- serverInfo.getPlayerCount(), +- serverInfo.getMaxPlayers() +- ); ++ // CraftBukkit start ++ private static String createVersion1Response(ServerInfo serverinfo, org.bukkit.event.server.ServerListPingEvent event) { ++ return String.format(Locale.ROOT, "\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, serverinfo.getServerVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); ++ // CraftBukkit end + } + +- private static void sendFlushAndClose(ChannelHandlerContext channelHandlerContext, ByteBuf context) { +- channelHandlerContext.pipeline().firstContext().writeAndFlush(context).addListener(ChannelFutureListener.CLOSE); ++ private static void sendFlushAndClose(ChannelHandlerContext channelhandlercontext, ByteBuf context) { ++ channelhandlercontext.pipeline().firstContext().writeAndFlush(context).addListener(ChannelFutureListener.CLOSE); + } + +- private static ByteBuf createLegacyDisconnectPacket(ByteBufAllocator byteBufAllocator, String string) { +- ByteBuf byteBuf = byteBufAllocator.buffer(); +- byteBuf.writeByte(255); +- LegacyProtocolUtils.writeLegacyString(byteBuf, string); +- return byteBuf; ++ private static ByteBuf createLegacyDisconnectPacket(ByteBufAllocator bytebufallocator, String s) { ++ ByteBuf bytebuf = bytebufallocator.buffer(); ++ ++ bytebuf.writeByte(255); ++ LegacyProtocolUtils.writeLegacyString(bytebuf, s); ++ return bytebuf; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/network/ServerCommonPacketListenerImpl.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/network/ServerCommonPacketListenerImpl.java.patch new file mode 100644 index 0000000000..b57f1e0744 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/network/ServerCommonPacketListenerImpl.java.patch @@ -0,0 +1,302 @@ +--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java +@@ -2,7 +2,9 @@ + + import com.mojang.authlib.GameProfile; + import com.mojang.logging.LogUtils; ++import java.util.Objects; + import javax.annotation.Nullable; ++import net.minecraft.ChatFormatting; + import net.minecraft.CrashReport; + import net.minecraft.CrashReportCategory; + import net.minecraft.ReportedException; +@@ -19,12 +21,28 @@ + import net.minecraft.network.protocol.common.ServerboundKeepAlivePacket; + import net.minecraft.network.protocol.common.ServerboundPongPacket; + import net.minecraft.network.protocol.common.ServerboundResourcePackPacket; ++import net.minecraft.network.protocol.game.ClientboundSetDefaultSpawnPositionPacket; ++import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ClientInformation; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.VisibleForDebug; ++import net.minecraft.util.thread.BlockableEventLoop; + import org.slf4j.Logger; + ++// CraftBukkit start ++import io.netty.buffer.ByteBuf; ++import java.util.concurrent.ExecutionException; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.bukkit.event.player.PlayerKickEvent; ++import org.bukkit.event.player.PlayerResourcePackStatusEvent; ++// CraftBukkit end ++ + public abstract class ServerCommonPacketListenerImpl implements ServerCommonPacketListener { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + public static final int LATENCY_CHECK_INTERVAL = 15000; + private static final Component TIMEOUT_DISCONNECTION_MESSAGE = Component.translatable("disconnect.timeout"); +@@ -36,59 +54,123 @@ + private int latency; + private volatile boolean suspendFlushingOnServerThread = false; + +- public ServerCommonPacketListenerImpl(MinecraftServer minecraftServer, Connection connection, CommonListenerCookie commonListenerCookie) { +- this.server = minecraftServer; +- this.connection = connection; ++ public ServerCommonPacketListenerImpl(MinecraftServer minecraftserver, Connection networkmanager, CommonListenerCookie commonlistenercookie, ServerPlayer player) { // CraftBukkit ++ this.server = minecraftserver; ++ this.connection = networkmanager; + this.keepAliveTime = Util.getMillis(); +- this.latency = commonListenerCookie.latency(); ++ this.latency = commonlistenercookie.latency(); ++ // CraftBukkit start - add fields and methods ++ this.player = player; ++ this.cserver = minecraftserver.server; + } ++ protected final ServerPlayer player; ++ protected final org.bukkit.craftbukkit.CraftServer cserver; ++ public boolean processedDisconnect; + ++ public CraftPlayer getCraftPlayer() { ++ return (this.player == null) ? null : (CraftPlayer) this.player.getBukkitEntity(); ++ // CraftBukkit end ++ } ++ + @Override + public void onDisconnect(Component reason) { + if (this.isSingleplayerOwner()) { +- LOGGER.info("Stopping singleplayer server as player logged out"); ++ ServerCommonPacketListenerImpl.LOGGER.info("Stopping singleplayer server as player logged out"); + this.server.halt(false); + } ++ + } + + @Override +- public void handleKeepAlive(ServerboundKeepAlivePacket serverboundKeepAlivePacket) { +- if (this.keepAlivePending && serverboundKeepAlivePacket.getId() == this.keepAliveChallenge) { +- int i = (int)(Util.getMillis() - this.keepAliveTime); ++ public void handleKeepAlive(ServerboundKeepAlivePacket serverboundkeepalivepacket) { ++ PacketUtils.ensureRunningOnSameThread(serverboundkeepalivepacket, this, this.player.serverLevel()); // CraftBukkit ++ if (this.keepAlivePending && serverboundkeepalivepacket.getId() == this.keepAliveChallenge) { ++ int i = (int) (Util.getMillis() - this.keepAliveTime); ++ + this.latency = (this.latency * 3 + i) / 4; + this.keepAlivePending = false; + } else if (!this.isSingleplayerOwner()) { +- this.disconnect(TIMEOUT_DISCONNECTION_MESSAGE); ++ this.disconnect(ServerCommonPacketListenerImpl.TIMEOUT_DISCONNECTION_MESSAGE); + } ++ + } + + @Override +- public void handlePong(ServerboundPongPacket serverboundPongPacket) { +- } ++ public void handlePong(ServerboundPongPacket serverboundpongpacket) {} + ++ // CraftBukkit start ++ private static final ResourceLocation CUSTOM_REGISTER = new ResourceLocation("register"); ++ private static final ResourceLocation CUSTOM_UNREGISTER = new ResourceLocation("unregister"); ++ + @Override +- public void handleCustomPayload(ServerboundCustomPayloadPacket serverboundCustomPayloadPacket) { ++ public void handleCustomPayload(ServerboundCustomPayloadPacket serverboundcustompayloadpacket) { ++ if (!(serverboundcustompayloadpacket.payload() instanceof ServerboundCustomPayloadPacket.UnknownPayload)) { ++ return; ++ } ++ PacketUtils.ensureRunningOnSameThread(serverboundcustompayloadpacket, this, this.player.serverLevel()); ++ ResourceLocation identifier = serverboundcustompayloadpacket.payload().id(); ++ ByteBuf payload = ((ServerboundCustomPayloadPacket.UnknownPayload)serverboundcustompayloadpacket.payload()).data(); ++ ++ if (identifier.equals(CUSTOM_REGISTER)) { ++ try { ++ String channels = payload.toString(com.google.common.base.Charsets.UTF_8); ++ for (String channel : channels.split("\0")) { ++ getCraftPlayer().addChannel(channel); ++ } ++ } catch (Exception ex) { ++ ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t register custom payload", ex); ++ this.disconnect("Invalid payload REGISTER!"); ++ } ++ } else if (identifier.equals(CUSTOM_UNREGISTER)) { ++ try { ++ String channels = payload.toString(com.google.common.base.Charsets.UTF_8); ++ for (String channel : channels.split("\0")) { ++ getCraftPlayer().removeChannel(channel); ++ } ++ } catch (Exception ex) { ++ ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t unregister custom payload", ex); ++ this.disconnect("Invalid payload UNREGISTER!"); ++ } ++ } else { ++ try { ++ byte[] data = new byte[payload.readableBytes()]; ++ payload.readBytes(data); ++ cserver.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), identifier.toString(), data); ++ } catch (Exception ex) { ++ ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t dispatch custom payload", ex); ++ this.disconnect("Invalid custom payload!"); ++ } ++ } ++ + } + ++ public final boolean isDisconnected() { ++ return !this.player.joining && !this.connection.isConnected(); ++ } ++ // CraftBukkit end ++ + @Override +- public void handleResourcePackResponse(ServerboundResourcePackPacket serverboundResourcePackPacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundResourcePackPacket, this, this.server); +- if (serverboundResourcePackPacket.action() == ServerboundResourcePackPacket.Action.DECLINED && this.server.isResourcePackRequired()) { +- LOGGER.info("Disconnecting {} due to resource pack {} rejection", this.playerProfile().getName(), serverboundResourcePackPacket.id()); ++ public void handleResourcePackResponse(ServerboundResourcePackPacket serverboundresourcepackpacket) { ++ PacketUtils.ensureRunningOnSameThread(serverboundresourcepackpacket, this, (BlockableEventLoop) this.server); ++ if (serverboundresourcepackpacket.action() == ServerboundResourcePackPacket.a.DECLINED && this.server.isResourcePackRequired()) { ++ ServerCommonPacketListenerImpl.LOGGER.info("Disconnecting {} due to resource pack {} rejection", this.playerProfile().getName(), serverboundresourcepackpacket.id()); + this.disconnect(Component.translatable("multiplayer.requiredTexturePrompt.disconnect")); + } ++ this.cserver.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getCraftPlayer(), serverboundresourcepackpacket.id(), PlayerResourcePackStatusEvent.Status.values()[serverboundresourcepackpacket.action().ordinal()])); // CraftBukkit ++ + } + + protected void keepConnectionAlive() { + this.server.getProfiler().push("keepAlive"); +- long millis = Util.getMillis(); +- if (millis - this.keepAliveTime >= 15000L) { ++ long i = Util.getMillis(); ++ ++ if (i - this.keepAliveTime >= 25000L) { // CraftBukkit + if (this.keepAlivePending) { +- this.disconnect(TIMEOUT_DISCONNECTION_MESSAGE); ++ this.disconnect(ServerCommonPacketListenerImpl.TIMEOUT_DISCONNECTION_MESSAGE); + } else { + this.keepAlivePending = true; +- this.keepAliveTime = millis; +- this.keepAliveChallenge = millis; ++ this.keepAliveTime = i; ++ this.keepAliveChallenge = i; + this.send(new ClientboundKeepAlivePacket(this.keepAliveChallenge)); + } + } +@@ -106,26 +188,94 @@ + } + + public void send(Packet packet) { +- this.send(packet, null); ++ this.send(packet, (PacketSendListener) null); + } + +- public void send(Packet packet, @Nullable PacketSendListener packetSendListener) { ++ public void send(Packet packet, @Nullable PacketSendListener packetsendlistener) { ++ // CraftBukkit start ++ if (packet == null) { ++ return; ++ } else if (packet instanceof ClientboundSetDefaultSpawnPositionPacket) { ++ ClientboundSetDefaultSpawnPositionPacket packet6 = (ClientboundSetDefaultSpawnPositionPacket) packet; ++ this.player.compassTarget = CraftLocation.toBukkit(packet6.pos, this.getCraftPlayer().getWorld()); ++ } ++ // CraftBukkit end + boolean flag = !this.suspendFlushingOnServerThread || !this.server.isSameThread(); + + try { +- this.connection.send(packet, packetSendListener, flag); +- } catch (Throwable var7) { +- CrashReport crashReport = CrashReport.forThrowable(var7, "Sending packet"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Packet being sent"); +- crashReportCategory.setDetail("Packet class", () -> packet.getClass().getCanonicalName()); +- throw new ReportedException(crashReport); ++ this.connection.send(packet, packetsendlistener, flag); ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Sending packet"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Packet being sent"); ++ ++ crashreportsystemdetails.setDetail("Packet class", () -> { ++ return packet.getClass().getCanonicalName(); ++ }); ++ throw new ReportedException(crashreport); + } + } + +- public void disconnect(Component component) { +- this.connection.send(new ClientboundDisconnectPacket(component), PacketSendListener.thenRun(() -> this.connection.disconnect(component))); ++ // CraftBukkit start ++ @Deprecated ++ public void disconnect(Component ichatbasecomponent) { ++ disconnect(CraftChatMessage.fromComponent(ichatbasecomponent)); ++ } ++ // CraftBukkit end ++ ++ public void disconnect(String s) { ++ // CraftBukkit start - fire PlayerKickEvent ++ if (this.processedDisconnect) { ++ return; ++ } ++ if (!this.cserver.isPrimaryThread()) { ++ Waitable waitable = new Waitable() { ++ @Override ++ protected Object evaluate() { ++ ServerCommonPacketListenerImpl.this.disconnect(s); ++ return null; ++ } ++ }; ++ ++ this.server.processQueue.add(waitable); ++ ++ try { ++ waitable.get(); ++ } catch (InterruptedException e) { ++ Thread.currentThread().interrupt(); ++ } catch (ExecutionException e) { ++ throw new RuntimeException(e); ++ } ++ return; ++ } ++ ++ String leaveMessage = ChatFormatting.YELLOW + this.player.getScoreboardName() + " left the game."; ++ ++ PlayerKickEvent event = new PlayerKickEvent(this.player.getBukkitEntity(), s, leaveMessage); ++ ++ if (this.cserver.getServer().isRunning()) { ++ this.cserver.getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ // Do not kick the player ++ return; ++ } ++ this.player.kickLeaveMessage = event.getLeaveMessage(); // CraftBukkit - SPIGOT-3034: Forward leave message to PlayerQuitEvent ++ // Send the possibly modified leave message ++ final Component ichatbasecomponent = CraftChatMessage.fromString(event.getReason(), true)[0]; ++ // CraftBukkit end ++ ++ this.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), PacketSendListener.thenRun(() -> { ++ this.connection.disconnect(ichatbasecomponent); ++ })); ++ this.onDisconnect(ichatbasecomponent); // CraftBukkit - fire quit instantly + this.connection.setReadOnly(); +- this.server.executeBlocking(this.connection::handleDisconnection); ++ MinecraftServer minecraftserver = this.server; ++ Connection networkmanager = this.connection; ++ ++ Objects.requireNonNull(this.connection); ++ // CraftBukkit - Don't wait ++ minecraftserver.wrapRunnable(networkmanager::handleDisconnection); + } + + protected boolean isSingleplayerOwner() { +@@ -143,7 +293,7 @@ + return this.latency; + } + +- protected CommonListenerCookie createCookie(ClientInformation clientInformation) { +- return new CommonListenerCookie(this.playerProfile(), this.latency, clientInformation); ++ protected CommonListenerCookie createCookie(ClientInformation clientinformation) { ++ return new CommonListenerCookie(this.playerProfile(), this.latency, clientinformation); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java.patch new file mode 100644 index 0000000000..9f0bda5f8d --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java.patch @@ -0,0 +1,168 @@ +--- a/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java +@@ -30,22 +30,24 @@ + import net.minecraft.server.network.config.ServerResourcePackConfigurationTask; + import net.minecraft.server.players.PlayerList; + import net.minecraft.tags.TagNetworkSerialization; ++import net.minecraft.util.thread.BlockableEventLoop; + import net.minecraft.world.flag.FeatureFlags; + import org.slf4j.Logger; + + public class ServerConfigurationPacketListenerImpl extends ServerCommonPacketListenerImpl implements TickablePacketListener, ServerConfigurationPacketListener { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final Component DISCONNECT_REASON_INVALID_DATA = Component.translatable("multiplayer.disconnect.invalid_player_data"); + private final GameProfile gameProfile; +- private final Queue configurationTasks = new ConcurrentLinkedQueue<>(); ++ private final Queue configurationTasks = new ConcurrentLinkedQueue(); + @Nullable + private ConfigurationTask currentTask; + private ClientInformation clientInformation; + +- public ServerConfigurationPacketListenerImpl(MinecraftServer minecraftServer, Connection connection, CommonListenerCookie commonListenerCookie) { +- super(minecraftServer, connection, commonListenerCookie); +- this.gameProfile = commonListenerCookie.gameProfile(); +- this.clientInformation = commonListenerCookie.clientInformation(); ++ public ServerConfigurationPacketListenerImpl(MinecraftServer minecraftserver, Connection networkmanager, CommonListenerCookie commonlistenercookie, ServerPlayer player) { // CraftBukkit ++ super(minecraftserver, networkmanager, commonlistenercookie, player); // CraftBukkit ++ this.gameProfile = commonlistenercookie.gameProfile(); ++ this.clientInformation = commonlistenercookie.clientInformation(); + } + + @Override +@@ -55,7 +57,7 @@ + + @Override + public void onDisconnect(Component reason) { +- LOGGER.info("{} lost connection: {}", this.gameProfile, reason.getString()); ++ ServerConfigurationPacketListenerImpl.LOGGER.info("{} lost connection: {}", this.gameProfile, reason.getString()); + super.onDisconnect(reason); + } + +@@ -66,14 +68,11 @@ + + public void startConfiguration() { + this.send(new ClientboundCustomPayloadPacket(new BrandPayload(this.server.getServerModName()))); +- LayeredRegistryAccess layeredRegistryAccess = this.server.registries(); ++ LayeredRegistryAccess layeredregistryaccess = this.server.registries(); ++ + this.send(new ClientboundUpdateEnabledFeaturesPacket(FeatureFlags.REGISTRY.toNames(this.server.getWorldData().enabledFeatures()))); +- this.send( +- new ClientboundRegistryDataPacket( +- new RegistryAccess.ImmutableRegistryAccess(RegistrySynchronization.networkedRegistries(layeredRegistryAccess)).freeze() +- ) +- ); +- this.send(new ClientboundUpdateTagsPacket(TagNetworkSerialization.serializeTagsToNetwork(layeredRegistryAccess))); ++ this.send(new ClientboundRegistryDataPacket((new RegistryAccess.ImmutableRegistryAccess(RegistrySynchronization.networkedRegistries(layeredregistryaccess))).freeze())); ++ this.send(new ClientboundUpdateTagsPacket(TagNetworkSerialization.serializeTagsToNetwork(layeredregistryaccess))); + this.addOptionalTasks(); + this.configurationTasks.add(new JoinWorldTask()); + this.startNextTask(); +@@ -85,51 +84,56 @@ + } + + private void addOptionalTasks() { +- this.server +- .getServerResourcePack() +- .ifPresent(serverResourcePackInfo -> this.configurationTasks.add(new ServerResourcePackConfigurationTask(serverResourcePackInfo))); ++ this.server.getServerResourcePack().ifPresent((minecraftserver_serverresourcepackinfo) -> { ++ this.configurationTasks.add(new ServerResourcePackConfigurationTask(minecraftserver_serverresourcepackinfo)); ++ }); + } + + @Override +- public void handleClientInformation(ServerboundClientInformationPacket serverboundClientInformationPacket) { +- this.clientInformation = serverboundClientInformationPacket.information(); ++ public void handleClientInformation(ServerboundClientInformationPacket serverboundclientinformationpacket) { ++ this.clientInformation = serverboundclientinformationpacket.information(); + } + + @Override +- public void handleResourcePackResponse(ServerboundResourcePackPacket serverboundResourcePackPacket) { +- super.handleResourcePackResponse(serverboundResourcePackPacket); +- if (serverboundResourcePackPacket.action().isTerminal()) { ++ public void handleResourcePackResponse(ServerboundResourcePackPacket serverboundresourcepackpacket) { ++ super.handleResourcePackResponse(serverboundresourcepackpacket); ++ if (serverboundresourcepackpacket.action().isTerminal()) { + this.finishCurrentTask(ServerResourcePackConfigurationTask.TYPE); + } ++ + } + + @Override +- public void handleConfigurationFinished(ServerboundFinishConfigurationPacket serverboundFinishConfigurationPacket) { ++ public void handleConfigurationFinished(ServerboundFinishConfigurationPacket serverboundfinishconfigurationpacket) { + this.connection.suspendInboundAfterProtocolChange(); +- PacketUtils.ensureRunningOnSameThread(serverboundFinishConfigurationPacket, this, this.server); ++ PacketUtils.ensureRunningOnSameThread(serverboundfinishconfigurationpacket, this, (BlockableEventLoop) this.server); + this.finishCurrentTask(JoinWorldTask.TYPE); + + try { +- PlayerList playerList = this.server.getPlayerList(); +- if (playerList.getPlayer(this.gameProfile.getId()) != null) { ++ PlayerList playerlist = this.server.getPlayerList(); ++ ++ if (playerlist.getPlayer(this.gameProfile.getId()) != null) { + this.disconnect(PlayerList.DUPLICATE_LOGIN_DISCONNECT_MESSAGE); + return; + } + +- Component component = playerList.canPlayerLogin(this.connection.getRemoteAddress(), this.gameProfile); +- if (component != null) { +- this.disconnect(component); ++ Component ichatbasecomponent = null; // CraftBukkit - login checks already completed ++ ++ if (ichatbasecomponent != null) { ++ this.disconnect(ichatbasecomponent); + return; + } + +- ServerPlayer playerForLogin = playerList.getPlayerForLogin(this.gameProfile, this.clientInformation); +- playerList.placeNewPlayer(this.connection, playerForLogin, this.createCookie(this.clientInformation)); ++ ServerPlayer entityplayer = playerlist.getPlayerForLogin(this.gameProfile, this.clientInformation, this.player); // CraftBukkit ++ ++ playerlist.placeNewPlayer(this.connection, entityplayer, this.createCookie(this.clientInformation)); + this.connection.resumeInboundAfterProtocolChange(); +- } catch (Exception var5) { +- LOGGER.error("Couldn't place player in world", (Throwable)var5); +- this.connection.send(new ClientboundDisconnectPacket(DISCONNECT_REASON_INVALID_DATA)); +- this.connection.disconnect(DISCONNECT_REASON_INVALID_DATA); ++ } catch (Exception exception) { ++ ServerConfigurationPacketListenerImpl.LOGGER.error("Couldn't place player in world", exception); ++ this.connection.send(new ClientboundDisconnectPacket(ServerConfigurationPacketListenerImpl.DISCONNECT_REASON_INVALID_DATA)); ++ this.connection.disconnect(ServerConfigurationPacketListenerImpl.DISCONNECT_REASON_INVALID_DATA); + } ++ + } + + @Override +@@ -141,18 +145,21 @@ + if (this.currentTask != null) { + throw new IllegalStateException("Task " + this.currentTask.type().id() + " has not finished yet"); + } else if (this.isAcceptingMessages()) { +- ConfigurationTask configurationTask = this.configurationTasks.poll(); +- if (configurationTask != null) { +- this.currentTask = configurationTask; +- configurationTask.start(this::send); ++ ConfigurationTask configurationtask = (ConfigurationTask) this.configurationTasks.poll(); ++ ++ if (configurationtask != null) { ++ this.currentTask = configurationtask; ++ configurationtask.start(this::send); + } ++ + } + } + +- private void finishCurrentTask(ConfigurationTask.Type type) { +- ConfigurationTask.Type type1 = this.currentTask != null ? this.currentTask.type() : null; +- if (!type.equals(type1)) { +- throw new IllegalStateException("Unexpected request for task finish, current task: " + type1 + ", requested: " + type); ++ private void finishCurrentTask(ConfigurationTask.a configurationtask_a) { ++ ConfigurationTask.a configurationtask_a1 = this.currentTask != null ? this.currentTask.type() : null; ++ ++ if (!configurationtask_a.equals(configurationtask_a1)) { ++ throw new IllegalStateException("Unexpected request for task finish, current task: " + configurationtask_a1 + ", requested: " + configurationtask_a); + } else { + this.currentTask = null; + this.startNextTask(); diff --git a/patch-remap/mache-vineflower/net/minecraft/server/network/ServerConnectionListener.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/network/ServerConnectionListener.java.patch new file mode 100644 index 0000000000..fb489e3bc1 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/network/ServerConnectionListener.java.patch @@ -0,0 +1,304 @@ +--- a/net/minecraft/server/network/ServerConnectionListener.java ++++ b/net/minecraft/server/network/ServerConnectionListener.java +@@ -37,23 +37,26 @@ + import javax.annotation.Nullable; + import net.minecraft.CrashReport; + import net.minecraft.ReportedException; ++import net.minecraft.network.BandwidthDebugMonitor; + import net.minecraft.network.Connection; + import net.minecraft.network.PacketSendListener; + import net.minecraft.network.RateKickingConnection; + import net.minecraft.network.chat.Component; ++import net.minecraft.network.chat.MutableComponent; + import net.minecraft.network.protocol.PacketFlow; + import net.minecraft.network.protocol.common.ClientboundDisconnectPacket; + import net.minecraft.server.MinecraftServer; + import org.slf4j.Logger; + + public class ServerConnectionListener { ++ + private static final Logger LOGGER = LogUtils.getLogger(); +- public static final Supplier SERVER_EVENT_GROUP = Suppliers.memoize( +- () -> new NioEventLoopGroup(0, new ThreadFactoryBuilder().setNameFormat("Netty Server IO #%d").setDaemon(true).build()) +- ); +- public static final Supplier SERVER_EPOLL_EVENT_GROUP = Suppliers.memoize( +- () -> new EpollEventLoopGroup(0, new ThreadFactoryBuilder().setNameFormat("Netty Epoll Server IO #%d").setDaemon(true).build()) +- ); ++ public static final Supplier SERVER_EVENT_GROUP = Suppliers.memoize(() -> { ++ return new NioEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Server IO #%d").setDaemon(true).build()); ++ }); ++ public static final Supplier SERVER_EPOLL_EVENT_GROUP = Suppliers.memoize(() -> { ++ return new EpollEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Epoll Server IO #%d").setDaemon(true).build()); ++ }); + final MinecraftServer server; + public volatile boolean running; + private final List channels = Collections.synchronizedList(Lists.newArrayList()); +@@ -65,127 +68,129 @@ + } + + public void startTcpServerListener(@Nullable InetAddress address, int port) throws IOException { ++ List list = this.channels; ++ + synchronized (this.channels) { +- Class clazz; +- EventLoopGroup eventLoopGroup; ++ Class oclass; ++ EventLoopGroup eventloopgroup; ++ + if (Epoll.isAvailable() && this.server.isEpollEnabled()) { +- clazz = EpollServerSocketChannel.class; +- eventLoopGroup = SERVER_EPOLL_EVENT_GROUP.get(); +- LOGGER.info("Using epoll channel type"); ++ oclass = EpollServerSocketChannel.class; ++ eventloopgroup = (EventLoopGroup) ServerConnectionListener.SERVER_EPOLL_EVENT_GROUP.get(); ++ ServerConnectionListener.LOGGER.info("Using epoll channel type"); + } else { +- clazz = NioServerSocketChannel.class; +- eventLoopGroup = SERVER_EVENT_GROUP.get(); +- LOGGER.info("Using default channel type"); ++ oclass = NioServerSocketChannel.class; ++ eventloopgroup = (EventLoopGroup) ServerConnectionListener.SERVER_EVENT_GROUP.get(); ++ ServerConnectionListener.LOGGER.info("Using default channel type"); + } + +- this.channels +- .add( +- new ServerBootstrap() +- .channel(clazz) +- .childHandler( +- new ChannelInitializer() { +- @Override +- protected void initChannel(Channel channel) { +- Connection.setInitialProtocolAttributes(channel); +- +- try { +- channel.config().setOption(ChannelOption.TCP_NODELAY, true); +- } catch (ChannelException var5) { +- } +- +- ChannelPipeline channelPipeline = channel.pipeline() +- .addLast("timeout", new ReadTimeoutHandler(30)) +- .addLast("legacy_query", new LegacyQueryHandler(ServerConnectionListener.this.getServer())); +- Connection.configureSerialization(channelPipeline, PacketFlow.SERVERBOUND, null); +- int rateLimitPacketsPerSecond = ServerConnectionListener.this.server.getRateLimitPacketsPerSecond(); +- Connection connection = (Connection)(rateLimitPacketsPerSecond > 0 +- ? new RateKickingConnection(rateLimitPacketsPerSecond) +- : new Connection(PacketFlow.SERVERBOUND)); +- ServerConnectionListener.this.connections.add(connection); +- connection.configurePacketHandler(channelPipeline); +- connection.setListenerForServerboundHandshake( +- new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, connection) +- ); +- } +- } +- ) +- .group(eventLoopGroup) +- .localAddress(address, port) +- .bind() +- .syncUninterruptibly() +- ); ++ this.channels.add(((ServerBootstrap) ((ServerBootstrap) (new ServerBootstrap()).channel(oclass)).childHandler(new ChannelInitializer() { ++ protected void initChannel(Channel channel) { ++ Connection.setInitialProtocolAttributes(channel); ++ ++ try { ++ channel.config().setOption(ChannelOption.TCP_NODELAY, true); ++ } catch (ChannelException channelexception) { ++ ; ++ } ++ ++ ChannelPipeline channelpipeline = channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("legacy_query", new LegacyQueryHandler(ServerConnectionListener.this.getServer())); ++ ++ Connection.configureSerialization(channelpipeline, PacketFlow.SERVERBOUND, (BandwidthDebugMonitor) null); ++ int j = ServerConnectionListener.this.server.getRateLimitPacketsPerSecond(); ++ Connection object = j > 0 ? new RateKickingConnection(j) : new Connection(PacketFlow.SERVERBOUND); // CraftBukkit - decompile error ++ ++ ServerConnectionListener.this.connections.add(object); ++ ((Connection) object).configurePacketHandler(channelpipeline); ++ ((Connection) object).setListenerForServerboundHandshake(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object)); ++ } ++ }).group(eventloopgroup).localAddress(address, port)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit + } + } + ++ // CraftBukkit start ++ public void acceptConnections() { ++ synchronized (this.channels) { ++ for (ChannelFuture future : this.channels) { ++ future.channel().config().setAutoRead(true); ++ } ++ } ++ } ++ // CraftBukkit end ++ + public SocketAddress startMemoryChannel() { +- ChannelFuture channelFuture; ++ List list = this.channels; ++ ChannelFuture channelfuture; ++ + synchronized (this.channels) { +- channelFuture = new ServerBootstrap() +- .channel(LocalServerChannel.class) +- .childHandler( +- new ChannelInitializer() { +- @Override +- protected void initChannel(Channel channel) { +- Connection.setInitialProtocolAttributes(channel); +- Connection connection = new Connection(PacketFlow.SERVERBOUND); +- connection.setListenerForServerboundHandshake( +- new MemoryServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, connection) +- ); +- ServerConnectionListener.this.connections.add(connection); +- ChannelPipeline channelPipeline = channel.pipeline(); +- Connection.configureInMemoryPipeline(channelPipeline, PacketFlow.SERVERBOUND); +- connection.configurePacketHandler(channelPipeline); +- } +- } +- ) +- .group(SERVER_EVENT_GROUP.get()) +- .localAddress(LocalAddress.ANY) +- .bind() +- .syncUninterruptibly(); +- this.channels.add(channelFuture); ++ channelfuture = ((ServerBootstrap) ((ServerBootstrap) (new ServerBootstrap()).channel(LocalServerChannel.class)).childHandler(new ChannelInitializer() { ++ protected void initChannel(Channel channel) { ++ Connection.setInitialProtocolAttributes(channel); ++ Connection networkmanager = new Connection(PacketFlow.SERVERBOUND); ++ ++ networkmanager.setListenerForServerboundHandshake(new MemoryServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, networkmanager)); ++ ServerConnectionListener.this.connections.add(networkmanager); ++ ChannelPipeline channelpipeline = channel.pipeline(); ++ ++ Connection.configureInMemoryPipeline(channelpipeline, PacketFlow.SERVERBOUND); ++ networkmanager.configurePacketHandler(channelpipeline); ++ } ++ }).group((EventLoopGroup) ServerConnectionListener.SERVER_EVENT_GROUP.get()).localAddress(LocalAddress.ANY)).bind().syncUninterruptibly(); ++ this.channels.add(channelfuture); + } + +- return channelFuture.channel().localAddress(); ++ return channelfuture.channel().localAddress(); + } + + public void stop() { + this.running = false; ++ Iterator iterator = this.channels.iterator(); + +- for (ChannelFuture channelFuture : this.channels) { ++ while (iterator.hasNext()) { ++ ChannelFuture channelfuture = (ChannelFuture) iterator.next(); ++ + try { +- channelFuture.channel().close().sync(); +- } catch (InterruptedException var4) { +- LOGGER.error("Interrupted whilst closing channel"); ++ channelfuture.channel().close().sync(); ++ } catch (InterruptedException interruptedexception) { ++ ServerConnectionListener.LOGGER.error("Interrupted whilst closing channel"); + } + } ++ + } + + public void tick() { ++ List list = this.connections; ++ + synchronized (this.connections) { +- Iterator iterator = this.connections.iterator(); ++ Iterator iterator = this.connections.iterator(); + + while (iterator.hasNext()) { +- Connection connection = iterator.next(); +- if (!connection.isConnecting()) { +- if (connection.isConnected()) { ++ Connection networkmanager = (Connection) iterator.next(); ++ ++ if (!networkmanager.isConnecting()) { ++ if (networkmanager.isConnected()) { + try { +- connection.tick(); +- } catch (Exception var7) { +- if (connection.isMemoryConnection()) { +- throw new ReportedException(CrashReport.forThrowable(var7, "Ticking memory connection")); ++ networkmanager.tick(); ++ } catch (Exception exception) { ++ if (networkmanager.isMemoryConnection()) { ++ throw new ReportedException(CrashReport.forThrowable(exception, "Ticking memory connection")); + } + +- LOGGER.warn("Failed to handle packet for {}", connection.getLoggableAddress(this.server.logIPs()), var7); +- Component component = Component.literal("Internal server error"); +- connection.send(new ClientboundDisconnectPacket(component), PacketSendListener.thenRun(() -> connection.disconnect(component))); +- connection.setReadOnly(); ++ ServerConnectionListener.LOGGER.warn("Failed to handle packet for {}", networkmanager.getLoggableAddress(this.server.logIPs()), exception); ++ MutableComponent ichatmutablecomponent = Component.literal("Internal server error"); ++ ++ networkmanager.send(new ClientboundDisconnectPacket(ichatmutablecomponent), PacketSendListener.thenRun(() -> { ++ networkmanager.disconnect(ichatmutablecomponent); ++ })); ++ networkmanager.setReadOnly(); + } + } else { + iterator.remove(); +- connection.handleDisconnection(); ++ networkmanager.handleDisconnection(); + } + } + } ++ + } + } + +@@ -197,7 +202,8 @@ + return this.connections; + } + +- static class LatencySimulator extends ChannelInboundHandlerAdapter { ++ private static class LatencySimulator extends ChannelInboundHandlerAdapter { ++ + private static final Timer TIMER = new HashedWheelTimer(); + private final int delay; + private final int jitter; +@@ -208,29 +214,31 @@ + this.jitter = jitter; + } + +- @Override +- public void channelRead(ChannelHandlerContext ctx, Object msg) { +- this.delayDownstream(ctx, msg); ++ public void channelRead(ChannelHandlerContext channelhandlercontext, Object object) { ++ this.delayDownstream(channelhandlercontext, object); + } + + private void delayDownstream(ChannelHandlerContext ctx, Object msg) { +- int i = this.delay + (int)(Math.random() * (double)this.jitter); ++ int i = this.delay + (int) (Math.random() * (double) this.jitter); ++ + this.queuedMessages.add(new ServerConnectionListener.LatencySimulator.DelayedMessage(ctx, msg)); +- TIMER.newTimeout(this::onTimeout, (long)i, TimeUnit.MILLISECONDS); ++ ServerConnectionListener.LatencySimulator.TIMER.newTimeout(this::onTimeout, (long) i, TimeUnit.MILLISECONDS); + } + + private void onTimeout(Timeout timeout) { +- ServerConnectionListener.LatencySimulator.DelayedMessage delayedMessage = this.queuedMessages.remove(0); +- delayedMessage.ctx.fireChannelRead(delayedMessage.msg); ++ ServerConnectionListener.LatencySimulator.DelayedMessage serverconnection_latencysimulator_delayedmessage = (ServerConnectionListener.LatencySimulator.DelayedMessage) this.queuedMessages.remove(0); ++ ++ serverconnection_latencysimulator_delayedmessage.ctx.fireChannelRead(serverconnection_latencysimulator_delayedmessage.msg); + } + +- static class DelayedMessage { ++ private static class DelayedMessage { ++ + public final ChannelHandlerContext ctx; + public final Object msg; + +- public DelayedMessage(ChannelHandlerContext ctx, Object msg) { +- this.ctx = ctx; +- this.msg = msg; ++ public DelayedMessage(ChannelHandlerContext channelhandlercontext, Object object) { ++ this.ctx = channelhandlercontext; ++ this.msg = object; + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch new file mode 100644 index 0000000000..6798cc9bc9 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch @@ -0,0 +1,3309 @@ +--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -3,22 +3,23 @@ + import com.google.common.collect.Lists; + import com.google.common.primitives.Floats; + import com.mojang.authlib.GameProfile; +-import com.mojang.brigadier.CommandDispatcher; + import com.mojang.brigadier.ParseResults; + import com.mojang.brigadier.StringReader; +-import com.mojang.brigadier.suggestion.Suggestions; + import com.mojang.logging.LogUtils; +-import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; + import it.unimi.dsi.fastutil.ints.Int2ObjectMap.Entry; ++import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; + import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectIterator; + import java.net.SocketAddress; + import java.util.Collections; + import java.util.EnumSet; ++import java.util.Iterator; + import java.util.List; + import java.util.Map; + import java.util.Objects; + import java.util.Optional; + import java.util.Set; ++import java.util.UUID; + import java.util.concurrent.CancellationException; + import java.util.concurrent.CompletableFuture; + import java.util.function.BiFunction; +@@ -49,6 +50,7 @@ + import net.minecraft.network.chat.LastSeenMessagesValidator; + import net.minecraft.network.chat.MessageSignature; + import net.minecraft.network.chat.MessageSignatureCache; ++import net.minecraft.network.chat.MutableComponent; + import net.minecraft.network.chat.PlayerChatMessage; + import net.minecraft.network.chat.RemoteChatSession; + import net.minecraft.network.chat.SignableCommand; +@@ -57,6 +59,7 @@ + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.PacketUtils; + import net.minecraft.network.protocol.common.ServerboundClientInformationPacket; ++import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; + import net.minecraft.network.protocol.game.ClientboundBlockChangedAckPacket; + import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; + import net.minecraft.network.protocol.game.ClientboundCommandSuggestionsPacket; +@@ -67,6 +70,8 @@ + import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; + import net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket; + import net.minecraft.network.protocol.game.ClientboundSetCarriedItemPacket; ++import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; ++import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket; + import net.minecraft.network.protocol.game.ClientboundStartConfigurationPacket; + import net.minecraft.network.protocol.game.ClientboundSystemChatPacket; + import net.minecraft.network.protocol.game.ClientboundTagQueryPacket; +@@ -124,39 +129,39 @@ + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.stats.ServerRecipeBook; + import net.minecraft.util.FutureChain; + import net.minecraft.util.Mth; + import net.minecraft.util.SignatureValidator; + import net.minecraft.util.StringUtil; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.Container; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.ExperienceOrb; + import net.minecraft.world.entity.HasCustomInventoryScreen; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MoverType; ++import net.minecraft.world.entity.Mob; + import net.minecraft.world.entity.PlayerRideableJumping; + import net.minecraft.world.entity.RelativeMovement; +-import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.ChatVisiblity; + import net.minecraft.world.entity.player.Inventory; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.player.ProfilePublicKey; + import net.minecraft.world.entity.projectile.AbstractArrow; + import net.minecraft.world.entity.vehicle.Boat; ++import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.inventory.AnvilMenu; + import net.minecraft.world.inventory.BeaconMenu; + import net.minecraft.world.inventory.CrafterMenu; +-import net.minecraft.world.inventory.MerchantMenu; +-import net.minecraft.world.inventory.RecipeBookMenu; + import net.minecraft.world.item.BlockItem; + import net.minecraft.world.item.BucketItem; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +-import net.minecraft.world.item.crafting.RecipeHolder; + import net.minecraft.world.level.BaseCommandBlock; ++import net.minecraft.world.level.ClipContext; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.GameType; + import net.minecraft.world.level.Level; +@@ -170,22 +175,76 @@ + import net.minecraft.world.level.block.entity.SignBlockEntity; + import net.minecraft.world.level.block.entity.StructureBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.BlockHitResult; ++import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; + import org.slf4j.Logger; + +-public class ServerGamePacketListenerImpl +- extends ServerCommonPacketListenerImpl +- implements ServerGamePacketListener, +- ServerPlayerConnection, +- TickablePacketListener { ++// CraftBukkit start ++import com.mojang.datafixers.util.Pair; ++import java.util.Arrays; ++import java.util.concurrent.ExecutionException; ++import java.util.concurrent.atomic.AtomicInteger; ++import java.util.function.Function; ++import net.minecraft.network.chat.OutgoingChatMessage; ++import net.minecraft.world.entity.animal.Bucketable; ++import net.minecraft.world.entity.animal.allay.Allay; ++import net.minecraft.world.entity.item.ItemEntity; ++import net.minecraft.world.inventory.InventoryClickType; ++import net.minecraft.world.inventory.MerchantMenu; ++import net.minecraft.world.inventory.RecipeBookMenu; ++import net.minecraft.world.inventory.Slot; ++import net.minecraft.world.item.crafting.RecipeHolder; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftEntity; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.craftbukkit.util.LazyPlayerSet; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Event; ++import org.bukkit.event.block.Action; ++import org.bukkit.event.inventory.ClickType; ++import org.bukkit.event.inventory.CraftItemEvent; ++import org.bukkit.event.inventory.InventoryAction; ++import org.bukkit.event.inventory.InventoryClickEvent; ++import org.bukkit.event.inventory.InventoryCreativeEvent; ++import org.bukkit.event.inventory.InventoryType.SlotType; ++import org.bukkit.event.inventory.SmithItemEvent; ++import org.bukkit.event.player.AsyncPlayerChatEvent; ++import org.bukkit.event.player.PlayerAnimationEvent; ++import org.bukkit.event.player.PlayerAnimationType; ++import org.bukkit.event.player.PlayerChatEvent; ++import org.bukkit.event.player.PlayerCommandPreprocessEvent; ++import org.bukkit.event.player.PlayerInteractAtEntityEvent; ++import org.bukkit.event.player.PlayerInteractEntityEvent; ++import org.bukkit.event.player.PlayerItemHeldEvent; ++import org.bukkit.event.player.PlayerMoveEvent; ++import org.bukkit.event.player.PlayerRespawnEvent.RespawnReason; ++import org.bukkit.event.player.PlayerSwapHandItemsEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++import org.bukkit.event.player.PlayerToggleFlightEvent; ++import org.bukkit.event.player.PlayerToggleSneakEvent; ++import org.bukkit.event.player.PlayerToggleSprintEvent; ++import org.bukkit.inventory.CraftingInventory; ++import org.bukkit.inventory.EquipmentSlot; ++import org.bukkit.inventory.InventoryView; ++import org.bukkit.inventory.SmithingInventory; ++// CraftBukkit end ++ ++public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl implements ServerGamePacketListener, ServerPlayerConnection, TickablePacketListener { ++ + static final Logger LOGGER = LogUtils.getLogger(); +- public static final double MAX_INTERACTION_DISTANCE = Mth.square(6.0); ++ public static final double MAX_INTERACTION_DISTANCE = Mth.square(6.0D); + private static final int NO_BLOCK_UPDATES_TO_ACK = -1; + private static final int TRACKED_MESSAGE_DISCONNECT_THRESHOLD = 4096; + private static final Component CHAT_VALIDATION_FAILED = Component.translatable("multiplayer.disconnect.chat_validation_failed"); +@@ -193,7 +252,9 @@ + public final PlayerChunkSender chunkSender; + private int tickCount; + private int ackBlockChangesUpTo = -1; +- private int chatSpamTickCount; ++ // CraftBukkit start - multithreaded fields ++ private final AtomicInteger chatSpamTickCount = new AtomicInteger(); ++ // CraftBukkit end + private int dropSpamTickCount; + private double firstGoodX; + private double firstGoodY; +@@ -227,19 +288,36 @@ + private final FutureChain chatMessageChain; + private boolean waitingForSwitchToConfig; + +- public ServerGamePacketListenerImpl( +- MinecraftServer minecraftServer, Connection connection, ServerPlayer serverPlayer, CommonListenerCookie commonListenerCookie +- ) { +- super(minecraftServer, connection, commonListenerCookie); +- this.chunkSender = new PlayerChunkSender(connection.isMemoryConnection()); +- connection.setListener(this); +- this.player = serverPlayer; +- serverPlayer.connection = this; +- serverPlayer.getTextFilter().join(); +- this.signedMessageDecoder = SignedMessageChain.Decoder.unsigned(serverPlayer.getUUID(), minecraftServer::enforceSecureProfile); +- this.chatMessageChain = new FutureChain(minecraftServer); ++ public ServerGamePacketListenerImpl(MinecraftServer minecraftserver, Connection networkmanager, ServerPlayer entityplayer, CommonListenerCookie commonlistenercookie) { ++ super(minecraftserver, networkmanager, commonlistenercookie, entityplayer); // CraftBukkit ++ this.chunkSender = new PlayerChunkSender(networkmanager.isMemoryConnection()); ++ networkmanager.setListener(this); ++ this.player = entityplayer; ++ entityplayer.connection = this; ++ entityplayer.getTextFilter().join(); ++ UUID uuid = entityplayer.getUUID(); ++ ++ Objects.requireNonNull(minecraftserver); ++ this.signedMessageDecoder = SignedMessageChain.Decoder.unsigned(uuid, minecraftserver::enforceSecureProfile); ++ this.chatMessageChain = new FutureChain(minecraftserver.chatExecutor); // CraftBukkit - async chat + } + ++ // CraftBukkit start - add fields ++ private int lastTick = MinecraftServer.currentTick; ++ private int allowedPlayerTicks = 1; ++ private int lastDropTick = MinecraftServer.currentTick; ++ private int lastBookTick = MinecraftServer.currentTick; ++ private int dropCount = 0; ++ ++ // Get position of last block hit for BlockDamageLevel.STOPPED ++ private double lastPosX = Double.MAX_VALUE; ++ private double lastPosY = Double.MAX_VALUE; ++ private double lastPosZ = Double.MAX_VALUE; ++ private float lastPitch = Float.MAX_VALUE; ++ private float lastYaw = Float.MAX_VALUE; ++ private boolean justTeleported = false; ++ // CraftBukkit end ++ + @Override + public void tick() { + if (this.ackBlockChangesUpTo > -1) { +@@ -253,11 +331,11 @@ + this.player.zo = this.player.getZ(); + this.player.doTick(); + this.player.absMoveTo(this.firstGoodX, this.firstGoodY, this.firstGoodZ, this.player.getYRot(), this.player.getXRot()); +- this.tickCount++; ++ ++this.tickCount; + this.knownMovePacketCount = this.receivedMovePacketCount; + if (this.clientIsFloating && !this.player.isSleeping() && !this.player.isPassenger() && !this.player.isDeadOrDying()) { + if (++this.aboveGroundTickCount > 80) { +- LOGGER.warn("{} was kicked for floating too long!", this.player.getName().getString()); ++ ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating too long!", this.player.getName().getString()); + this.disconnect(Component.translatable("multiplayer.disconnect.flying")); + return; + } +@@ -276,7 +354,7 @@ + this.vehicleLastGoodZ = this.lastVehicle.getZ(); + if (this.clientVehicleIsFloating && this.player.getRootVehicle().getControllingPassenger() == this.player) { + if (++this.aboveGroundVehicleTickCount > 80) { +- LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getName().getString()); ++ ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getName().getString()); + this.disconnect(Component.translatable("multiplayer.disconnect.flying")); + return; + } +@@ -291,19 +369,24 @@ + } + + this.keepConnectionAlive(); ++ // CraftBukkit start ++ for (int spam; (spam = this.chatSpamTickCount.get()) > 0 && !chatSpamTickCount.compareAndSet(spam, spam - 1); ) ; ++ /* Use thread-safe field access instead + if (this.chatSpamTickCount > 0) { +- this.chatSpamTickCount--; ++ --this.chatSpamTickCount; + } ++ */ ++ // CraftBukkit end + + if (this.dropSpamTickCount > 0) { +- this.dropSpamTickCount--; ++ --this.dropSpamTickCount; + } + +- if (this.player.getLastActionTime() > 0L +- && this.server.getPlayerIdleTimeout() > 0 +- && Util.getMillis() - this.player.getLastActionTime() > (long)this.server.getPlayerIdleTimeout() * 1000L * 60L) { ++ if (this.player.getLastActionTime() > 0L && this.server.getPlayerIdleTimeout() > 0 && Util.getMillis() - this.player.getLastActionTime() > (long) this.server.getPlayerIdleTimeout() * 1000L * 60L) { ++ this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 + this.disconnect(Component.translatable("multiplayer.disconnect.idling")); + } ++ + } + + public void resetPosition() { +@@ -322,8 +405,7 @@ + + @Override + public boolean shouldHandleMessage(Packet packet) { +- return super.shouldHandleMessage(packet) +- || this.waitingForSwitchToConfig && this.connection.isConnected() && packet instanceof ServerboundConfigurationAcknowledgedPacket; ++ return super.shouldHandleMessage(packet) ? true : this.waitingForSwitchToConfig && this.connection.isConnected() && packet instanceof ServerboundConfigurationAcknowledgedPacket; + } + + @Override +@@ -332,12 +414,12 @@ + } + + private CompletableFuture filterTextPacket(T message, BiFunction> processor) { +- return processor.apply(this.player.getTextFilter(), message).thenApply(object -> { ++ return ((CompletableFuture) processor.apply(this.player.getTextFilter(), message)).thenApply((object) -> { + if (!this.isAcceptingMessages()) { +- LOGGER.debug("Ignoring packet due to disconnection"); ++ ServerGamePacketListenerImpl.LOGGER.debug("Ignoring packet due to disconnection"); + throw new CancellationException("disconnected"); + } else { +- return (R)object; ++ return object; + } + }); + } +@@ -356,16 +438,16 @@ + this.player.setPlayerInput(packet.getXxa(), packet.getZza(), packet.isJumping(), packet.isShiftKeyDown()); + } + +- private static boolean containsInvalidValues(double x, double y, double z, float yRot, float xRot) { +- return Double.isNaN(x) || Double.isNaN(y) || Double.isNaN(z) || !Floats.isFinite(xRot) || !Floats.isFinite(yRot); ++ private static boolean containsInvalidValues(double x, double d1, double y, float f, float z) { ++ return Double.isNaN(x) || Double.isNaN(d1) || Double.isNaN(y) || !Floats.isFinite(z) || !Floats.isFinite(f); + } + + private static double clampHorizontal(double value) { +- return Mth.clamp(value, -3.0E7, 3.0E7); ++ return Mth.clamp(value, -3.0E7D, 3.0E7D); + } + + private static double clampVertical(double value) { +- return Mth.clamp(value, -2.0E7, 2.0E7); ++ return Mth.clamp(value, -2.0E7D, 2.0E7D); + } + + @Override +@@ -374,80 +456,170 @@ + if (containsInvalidValues(packet.getX(), packet.getY(), packet.getZ(), packet.getYRot(), packet.getXRot())) { + this.disconnect(Component.translatable("multiplayer.disconnect.invalid_vehicle_movement")); + } else { +- Entity rootVehicle = this.player.getRootVehicle(); +- if (rootVehicle != this.player && rootVehicle.getControllingPassenger() == this.player && rootVehicle == this.lastVehicle) { +- ServerLevel serverLevel = this.player.serverLevel(); +- double x = rootVehicle.getX(); +- double y = rootVehicle.getY(); +- double z = rootVehicle.getZ(); +- double d = clampHorizontal(packet.getX()); +- double d1 = clampVertical(packet.getY()); +- double d2 = clampHorizontal(packet.getZ()); ++ Entity entity = this.player.getRootVehicle(); ++ ++ if (entity != this.player && entity.getControllingPassenger() == this.player && entity == this.lastVehicle) { ++ ServerLevel worldserver = this.player.serverLevel(); ++ double d0 = entity.getX(); ++ double d1 = entity.getY(); ++ double d2 = entity.getZ(); ++ double d3 = clampHorizontal(packet.getX()); ++ double d4 = clampVertical(packet.getY()); ++ double d5 = clampHorizontal(packet.getZ()); + float f = Mth.wrapDegrees(packet.getYRot()); + float f1 = Mth.wrapDegrees(packet.getXRot()); +- double d3 = d - this.vehicleFirstGoodX; +- double d4 = d1 - this.vehicleFirstGoodY; +- double d5 = d2 - this.vehicleFirstGoodZ; +- double d6 = rootVehicle.getDeltaMovement().lengthSqr(); +- double d7 = d3 * d3 + d4 * d4 + d5 * d5; +- if (d7 - d6 > 100.0 && !this.isSingleplayerOwner()) { +- LOGGER.warn( +- "{} (vehicle of {}) moved too quickly! {},{},{}", rootVehicle.getName().getString(), this.player.getName().getString(), d3, d4, d5 +- ); +- this.send(new ClientboundMoveVehiclePacket(rootVehicle)); ++ double d6 = d3 - this.vehicleFirstGoodX; ++ double d7 = d4 - this.vehicleFirstGoodY; ++ double d8 = d5 - this.vehicleFirstGoodZ; ++ double d9 = entity.getDeltaMovement().lengthSqr(); ++ double d10 = d6 * d6 + d7 * d7 + d8 * d8; ++ ++ ++ // CraftBukkit start - handle custom speeds and skipped ticks ++ this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick; ++ this.allowedPlayerTicks = Math.max(this.allowedPlayerTicks, 1); ++ this.lastTick = (int) (System.currentTimeMillis() / 50); ++ ++ ++this.receivedMovePacketCount; ++ int i = this.receivedMovePacketCount - this.knownMovePacketCount; ++ if (i > Math.max(this.allowedPlayerTicks, 5)) { ++ ServerGamePacketListenerImpl.LOGGER.debug(this.player.getScoreboardName() + " is sending move packets too frequently (" + i + " packets since last tick)"); ++ i = 1; ++ } ++ ++ if (d10 > 0) { ++ allowedPlayerTicks -= 1; ++ } else { ++ allowedPlayerTicks = 20; ++ } ++ double speed; ++ if (player.getAbilities().flying) { ++ speed = player.getAbilities().flyingSpeed * 20f; ++ } else { ++ speed = player.getAbilities().walkingSpeed * 10f; ++ } ++ speed *= 2f; // TODO: Get the speed of the vehicle instead of the player ++ ++ if (d10 - d9 > Math.max(100.0D, Math.pow((double) (10.0F * (float) i * speed), 2)) && !this.isSingleplayerOwner()) { ++ // CraftBukkit end ++ ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", new Object[]{entity.getName().getString(), this.player.getName().getString(), d6, d7, d8}); ++ this.send(new ClientboundMoveVehiclePacket(entity)); + return; + } + +- boolean flag = serverLevel.noCollision(rootVehicle, rootVehicle.getBoundingBox().deflate(0.0625)); +- d3 = d - this.vehicleLastGoodX; +- d4 = d1 - this.vehicleLastGoodY - 1.0E-6; +- d5 = d2 - this.vehicleLastGoodZ; +- boolean flag1 = rootVehicle.verticalCollisionBelow; +- if (rootVehicle instanceof LivingEntity livingEntity && livingEntity.onClimbable()) { +- livingEntity.resetFallDistance(); ++ boolean flag = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D)); ++ ++ d6 = d3 - this.vehicleLastGoodX; ++ d7 = d4 - this.vehicleLastGoodY - 1.0E-6D; ++ d8 = d5 - this.vehicleLastGoodZ; ++ boolean flag1 = entity.verticalCollisionBelow; ++ ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ if (entityliving.onClimbable()) { ++ entityliving.resetFallDistance(); ++ } + } + +- rootVehicle.move(MoverType.PLAYER, new Vec3(d3, d4, d5)); +- d3 = d - rootVehicle.getX(); +- double var37 = d1 - rootVehicle.getY(); +- if (var37 > -0.5 || var37 < 0.5) { +- var37 = 0.0; ++ entity.move(EnumMoveType.PLAYER, new Vec3(d6, d7, d8)); ++ double d11 = d7; ++ ++ d6 = d3 - entity.getX(); ++ d7 = d4 - entity.getY(); ++ if (d7 > -0.5D || d7 < 0.5D) { ++ d7 = 0.0D; + } + +- d5 = d2 - rootVehicle.getZ(); +- d7 = d3 * d3 + var37 * var37 + d5 * d5; ++ d8 = d5 - entity.getZ(); ++ d10 = d6 * d6 + d7 * d7 + d8 * d8; + boolean flag2 = false; +- if (d7 > 0.0625) { ++ ++ if (d10 > 0.0625D) { + flag2 = true; +- LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", rootVehicle.getName().getString(), this.player.getName().getString(), Math.sqrt(d7)); ++ ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", new Object[]{entity.getName().getString(), this.player.getName().getString(), Math.sqrt(d10)}); + } + +- rootVehicle.absMoveTo(d, d1, d2, f, f1); +- boolean flag3 = serverLevel.noCollision(rootVehicle, rootVehicle.getBoundingBox().deflate(0.0625)); ++ entity.absMoveTo(d3, d4, d5, f, f1); ++ player.absMoveTo(d3, d4, d5, this.player.getYRot(), this.player.getXRot()); // CraftBukkit ++ boolean flag3 = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D)); ++ + if (flag && (flag2 || !flag3)) { +- rootVehicle.absMoveTo(x, y, z, f, f1); +- this.send(new ClientboundMoveVehiclePacket(rootVehicle)); ++ entity.absMoveTo(d0, d1, d2, f, f1); ++ player.absMoveTo(d0, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit ++ this.send(new ClientboundMoveVehiclePacket(entity)); + return; + } + ++ // CraftBukkit start - fire PlayerMoveEvent ++ Player player = this.getCraftPlayer(); ++ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. ++ Location to = player.getLocation().clone(); // Start off the To location as the Players current location. ++ ++ // If the packet contains movement information then we update the To location with the correct XYZ. ++ to.setX(packet.getX()); ++ to.setY(packet.getY()); ++ to.setZ(packet.getZ()); ++ ++ ++ // If the packet contains look information then we update the To location with the correct Yaw & Pitch. ++ to.setYaw(packet.getYRot()); ++ to.setPitch(packet.getXRot()); ++ ++ // Prevent 40 event-calls for less than a single pixel of movement >.> ++ double delta = Math.pow(this.lastPosX - to.getX(), 2) + Math.pow(this.lastPosY - to.getY(), 2) + Math.pow(this.lastPosZ - to.getZ(), 2); ++ float deltaAngle = Math.abs(this.lastYaw - to.getYaw()) + Math.abs(this.lastPitch - to.getPitch()); ++ ++ if ((delta > 1f / 256 || deltaAngle > 10f) && !this.player.isImmobile()) { ++ this.lastPosX = to.getX(); ++ this.lastPosY = to.getY(); ++ this.lastPosZ = to.getZ(); ++ this.lastYaw = to.getYaw(); ++ this.lastPitch = to.getPitch(); ++ ++ // Skip the first time we do this ++ if (from.getX() != Double.MAX_VALUE) { ++ Location oldTo = to.clone(); ++ PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ // If the event is cancelled we move the player back to their old location. ++ if (event.isCancelled()) { ++ teleport(from); ++ return; ++ } ++ ++ // If a Plugin has changed the To destination then we teleport the Player ++ // there to avoid any 'Moved wrongly' or 'Moved too quickly' errors. ++ // We only do this if the Event was not cancelled. ++ if (!oldTo.equals(event.getTo()) && !event.isCancelled()) { ++ this.player.getBukkitEntity().teleport(event.getTo(), PlayerTeleportEvent.TeleportCause.PLUGIN); ++ return; ++ } ++ ++ // Check to see if the Players Location has some how changed during the call of the event. ++ // This can happen due to a plugin teleporting the player instead of using .setTo() ++ if (!from.equals(this.getCraftPlayer().getLocation()) && this.justTeleported) { ++ this.justTeleported = false; ++ return; ++ } ++ } ++ } ++ // CraftBukkit end ++ + this.player.serverLevel().getChunkSource().move(this.player); +- this.player.checkMovementStatistics(this.player.getX() - x, this.player.getY() - y, this.player.getZ() - z); +- this.clientVehicleIsFloating = d4 >= -0.03125 +- && !flag1 +- && !this.server.isFlightAllowed() +- && !rootVehicle.isNoGravity() +- && this.noBlocksAround(rootVehicle); +- this.vehicleLastGoodX = rootVehicle.getX(); +- this.vehicleLastGoodY = rootVehicle.getY(); +- this.vehicleLastGoodZ = rootVehicle.getZ(); ++ this.player.checkMovementStatistics(this.player.getX() - d0, this.player.getY() - d1, this.player.getZ() - d2); ++ this.clientVehicleIsFloating = d11 >= -0.03125D && !flag1 && !this.server.isFlightAllowed() && !entity.isNoGravity() && this.noBlocksAround(entity); ++ this.vehicleLastGoodX = entity.getX(); ++ this.vehicleLastGoodY = entity.getY(); ++ this.vehicleLastGoodZ = entity.getZ(); + } ++ + } + } + + private boolean noBlocksAround(Entity entity) { +- return entity.level() +- .getBlockStates(entity.getBoundingBox().inflate(0.0625).expandTowards(0.0, -0.55, 0.0)) +- .allMatch(BlockBehaviour.BlockStateBase::isAir); ++ return entity.level().getBlockStates(entity.getBoundingBox().inflate(0.0625D).expandTowards(0.0D, -0.55D, 0.0D)).allMatch(BlockBehaviour.BlockStateBase::isAir); + } + + @Override +@@ -459,14 +631,7 @@ + return; + } + +- this.player +- .absMoveTo( +- this.awaitingPositionFromClient.x, +- this.awaitingPositionFromClient.y, +- this.awaitingPositionFromClient.z, +- this.player.getYRot(), +- this.player.getXRot() +- ); ++ this.player.absMoveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); + this.lastGoodX = this.awaitingPositionFromClient.x; + this.lastGoodY = this.awaitingPositionFromClient.y; + this.lastGoodZ = this.awaitingPositionFromClient.z; +@@ -475,47 +640,63 @@ + } + + this.awaitingPositionFromClient = null; ++ this.player.serverLevel().getChunkSource().move(this.player); // CraftBukkit + } ++ + } + + @Override + public void handleRecipeBookSeenRecipePacket(ServerboundRecipeBookSeenRecipePacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); +- this.server.getRecipeManager().byKey(packet.getRecipe()).ifPresent(this.player.getRecipeBook()::removeHighlight); ++ Optional> optional = this.server.getRecipeManager().byKey(packet.getRecipe()); // CraftBukkit - decompile error ++ ServerRecipeBook recipebookserver = this.player.getRecipeBook(); ++ ++ Objects.requireNonNull(recipebookserver); ++ optional.ifPresent(recipebookserver::removeHighlight); + } + + @Override + public void handleRecipeBookChangeSettingsPacket(ServerboundRecipeBookChangeSettingsPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ CraftEventFactory.callRecipeBookSettingsEvent(this.player, packet.getBookType(), packet.isOpen(), packet.isFiltering()); // CraftBukkit + this.player.getRecipeBook().setBookSetting(packet.getBookType(), packet.isOpen(), packet.isFiltering()); + } + + @Override + public void handleSeenAdvancements(ServerboundSeenAdvancementsPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); +- if (packet.getAction() == ServerboundSeenAdvancementsPacket.Action.OPENED_TAB) { +- ResourceLocation resourceLocation = Objects.requireNonNull(packet.getTab()); +- AdvancementHolder advancementHolder = this.server.getAdvancements().get(resourceLocation); +- if (advancementHolder != null) { +- this.player.getAdvancements().setSelectedTab(advancementHolder); ++ if (packet.getAction() == ServerboundSeenAdvancementsPacket.Status.OPENED_TAB) { ++ ResourceLocation minecraftkey = (ResourceLocation) Objects.requireNonNull(packet.getTab()); ++ AdvancementHolder advancementholder = this.server.getAdvancements().get(minecraftkey); ++ ++ if (advancementholder != null) { ++ this.player.getAdvancements().setSelectedTab(advancementholder); + } + } ++ + } + + @Override + public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); +- StringReader stringReader = new StringReader(packet.getCommand()); +- if (stringReader.canRead() && stringReader.peek() == '/') { +- stringReader.skip(); ++ // CraftBukkit start ++ if (chatSpamTickCount.addAndGet(1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { ++ this.disconnect(Component.translatable("disconnect.spam")); ++ return; + } ++ // CraftBukkit end ++ StringReader stringreader = new StringReader(packet.getCommand()); + +- ParseResults parseResults = this.server.getCommands().getDispatcher().parse(stringReader, this.player.createCommandSourceStack()); +- this.server +- .getCommands() +- .getDispatcher() +- .getCompletionSuggestions(parseResults) +- .thenAccept(suggestions -> this.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions))); ++ if (stringreader.canRead() && stringreader.peek() == '/') { ++ stringreader.skip(); ++ } ++ ++ ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); ++ ++ this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { ++ if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer ++ this.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions)); ++ }); + } + + @Override +@@ -526,49 +707,62 @@ + } else if (!this.player.canUseGameMasterBlocks()) { + this.player.sendSystemMessage(Component.translatable("advMode.notAllowed")); + } else { +- BaseCommandBlock baseCommandBlock = null; +- CommandBlockEntity commandBlockEntity = null; +- BlockPos pos = packet.getPos(); +- BlockEntity blockEntity = this.player.level().getBlockEntity(pos); +- if (blockEntity instanceof CommandBlockEntity) { +- commandBlockEntity = (CommandBlockEntity)blockEntity; +- baseCommandBlock = commandBlockEntity.getCommandBlock(); ++ BaseCommandBlock commandblocklistenerabstract = null; ++ CommandBlockEntity tileentitycommand = null; ++ BlockPos blockposition = packet.getPos(); ++ BlockEntity tileentity = this.player.level().getBlockEntity(blockposition); ++ ++ if (tileentity instanceof CommandBlockEntity) { ++ tileentitycommand = (CommandBlockEntity) tileentity; ++ commandblocklistenerabstract = tileentitycommand.getCommandBlock(); + } + +- String command = packet.getCommand(); +- boolean isTrackOutput = packet.isTrackOutput(); +- if (baseCommandBlock != null) { +- CommandBlockEntity.Mode mode = commandBlockEntity.getMode(); +- BlockState blockState = this.player.level().getBlockState(pos); +- Direction direction = blockState.getValue(CommandBlock.FACING); ++ String s = packet.getCommand(); ++ boolean flag = packet.isTrackOutput(); + +- BlockState blockState2 = (switch (packet.getMode()) { +- case SEQUENCE -> Blocks.CHAIN_COMMAND_BLOCK.defaultBlockState(); +- case AUTO -> Blocks.REPEATING_COMMAND_BLOCK.defaultBlockState(); +- default -> Blocks.COMMAND_BLOCK.defaultBlockState(); +- }).setValue(CommandBlock.FACING, direction).setValue(CommandBlock.CONDITIONAL, Boolean.valueOf(packet.isConditional())); +- if (blockState2 != blockState) { +- this.player.level().setBlock(pos, blockState2, 2); +- blockEntity.setBlockState(blockState2); +- this.player.level().getChunkAt(pos).setBlockEntity(blockEntity); ++ if (commandblocklistenerabstract != null) { ++ CommandBlockEntity.Type tileentitycommand_type = tileentitycommand.getMode(); ++ IBlockData iblockdata = this.player.level().getBlockState(blockposition); ++ Direction enumdirection = (Direction) iblockdata.getValue(CommandBlock.FACING); ++ IBlockData iblockdata1; ++ ++ switch (packet.getMode()) { ++ case SEQUENCE: ++ iblockdata1 = Blocks.CHAIN_COMMAND_BLOCK.defaultBlockState(); ++ break; ++ case AUTO: ++ iblockdata1 = Blocks.REPEATING_COMMAND_BLOCK.defaultBlockState(); ++ break; ++ case REDSTONE: ++ default: ++ iblockdata1 = Blocks.COMMAND_BLOCK.defaultBlockState(); + } + +- baseCommandBlock.setCommand(command); +- baseCommandBlock.setTrackOutput(isTrackOutput); +- if (!isTrackOutput) { +- baseCommandBlock.setLastOutput(null); ++ IBlockData iblockdata2 = (IBlockData) ((IBlockData) iblockdata1.setValue(CommandBlock.FACING, enumdirection)).setValue(CommandBlock.CONDITIONAL, packet.isConditional()); ++ ++ if (iblockdata2 != iblockdata) { ++ this.player.level().setBlock(blockposition, iblockdata2, 2); ++ tileentity.setBlockState(iblockdata2); ++ this.player.level().getChunkAt(blockposition).setBlockEntity(tileentity); + } + +- commandBlockEntity.setAutomatic(packet.isAutomatic()); +- if (mode != packet.getMode()) { +- commandBlockEntity.onModeSwitch(); ++ commandblocklistenerabstract.setCommand(s); ++ commandblocklistenerabstract.setTrackOutput(flag); ++ if (!flag) { ++ commandblocklistenerabstract.setLastOutput((Component) null); + } + +- baseCommandBlock.onUpdated(); +- if (!StringUtil.isNullOrEmpty(command)) { +- this.player.sendSystemMessage(Component.translatable("advMode.setCommand.success", command)); ++ tileentitycommand.setAutomatic(packet.isAutomatic()); ++ if (tileentitycommand_type != packet.getMode()) { ++ tileentitycommand.onModeSwitch(); + } ++ ++ commandblocklistenerabstract.onUpdated(); ++ if (!StringUtil.isNullOrEmpty(s)) { ++ this.player.sendSystemMessage(Component.translatable("advMode.setCommand.success", s)); ++ } + } ++ + } + } + +@@ -580,17 +774,19 @@ + } else if (!this.player.canUseGameMasterBlocks()) { + this.player.sendSystemMessage(Component.translatable("advMode.notAllowed")); + } else { +- BaseCommandBlock commandBlock = packet.getCommandBlock(this.player.level()); +- if (commandBlock != null) { +- commandBlock.setCommand(packet.getCommand()); +- commandBlock.setTrackOutput(packet.isTrackOutput()); ++ BaseCommandBlock commandblocklistenerabstract = packet.getCommandBlock(this.player.level()); ++ ++ if (commandblocklistenerabstract != null) { ++ commandblocklistenerabstract.setCommand(packet.getCommand()); ++ commandblocklistenerabstract.setTrackOutput(packet.isTrackOutput()); + if (!packet.isTrackOutput()) { +- commandBlock.setLastOutput(null); ++ commandblocklistenerabstract.setLastOutput((Component) null); + } + +- commandBlock.onUpdated(); ++ commandblocklistenerabstract.onUpdated(); + this.player.sendSystemMessage(Component.translatable("advMode.setCommand.success", packet.getCommand())); + } ++ + } + } + +@@ -598,13 +794,7 @@ + public void handlePickItem(ServerboundPickItemPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + this.player.getInventory().pickSlot(packet.getSlot()); +- this.player +- .connection +- .send( +- new ClientboundContainerSetSlotPacket( +- -2, 0, this.player.getInventory().selected, this.player.getInventory().getItem(this.player.getInventory().selected) +- ) +- ); ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, 0, this.player.getInventory().selected, this.player.getInventory().getItem(this.player.getInventory().selected))); + this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, 0, packet.getSlot(), this.player.getInventory().getItem(packet.getSlot()))); + this.player.connection.send(new ClientboundSetCarriedItemPacket(this.player.getInventory().selected)); + } +@@ -612,67 +802,82 @@ + @Override + public void handleRenameItem(ServerboundRenameItemPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); +- if (this.player.containerMenu instanceof AnvilMenu anvilMenu) { +- if (!anvilMenu.stillValid(this.player)) { +- LOGGER.debug("Player {} interacted with invalid menu {}", this.player, anvilMenu); ++ AbstractContainerMenu container = this.player.containerMenu; ++ ++ if (container instanceof AnvilMenu) { ++ AnvilMenu containeranvil = (AnvilMenu) container; ++ ++ if (!containeranvil.stillValid(this.player)) { ++ ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, containeranvil); + return; + } + +- anvilMenu.setItemName(packet.getName()); ++ containeranvil.setItemName(packet.getName()); + } ++ + } + + @Override + public void handleSetBeaconPacket(ServerboundSetBeaconPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); +- if (this.player.containerMenu instanceof BeaconMenu beaconMenu) { ++ AbstractContainerMenu container = this.player.containerMenu; ++ ++ if (container instanceof BeaconMenu) { ++ BeaconMenu containerbeacon = (BeaconMenu) container; ++ + if (!this.player.containerMenu.stillValid(this.player)) { +- LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu); ++ ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu); + return; + } + +- beaconMenu.updateEffects(packet.getPrimary(), packet.getSecondary()); ++ containerbeacon.updateEffects(packet.getPrimary(), packet.getSecondary()); + } ++ + } + + @Override + public void handleSetStructureBlock(ServerboundSetStructureBlockPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + if (this.player.canUseGameMasterBlocks()) { +- BlockPos pos = packet.getPos(); +- BlockState blockState = this.player.level().getBlockState(pos); +- if (this.player.level().getBlockEntity(pos) instanceof StructureBlockEntity structureBlockEntity) { +- structureBlockEntity.setMode(packet.getMode()); +- structureBlockEntity.setStructureName(packet.getName()); +- structureBlockEntity.setStructurePos(packet.getOffset()); +- structureBlockEntity.setStructureSize(packet.getSize()); +- structureBlockEntity.setMirror(packet.getMirror()); +- structureBlockEntity.setRotation(packet.getRotation()); +- structureBlockEntity.setMetaData(packet.getData()); +- structureBlockEntity.setIgnoreEntities(packet.isIgnoreEntities()); +- structureBlockEntity.setShowAir(packet.isShowAir()); +- structureBlockEntity.setShowBoundingBox(packet.isShowBoundingBox()); +- structureBlockEntity.setIntegrity(packet.getIntegrity()); +- structureBlockEntity.setSeed(packet.getSeed()); +- if (structureBlockEntity.hasStructureName()) { +- String structureName = structureBlockEntity.getStructureName(); ++ BlockPos blockposition = packet.getPos(); ++ IBlockData iblockdata = this.player.level().getBlockState(blockposition); ++ BlockEntity tileentity = this.player.level().getBlockEntity(blockposition); ++ ++ if (tileentity instanceof StructureBlockEntity) { ++ StructureBlockEntity tileentitystructure = (StructureBlockEntity) tileentity; ++ ++ tileentitystructure.setMode(packet.getMode()); ++ tileentitystructure.setStructureName(packet.getName()); ++ tileentitystructure.setStructurePos(packet.getOffset()); ++ tileentitystructure.setStructureSize(packet.getSize()); ++ tileentitystructure.setMirror(packet.getMirror()); ++ tileentitystructure.setRotation(packet.getRotation()); ++ tileentitystructure.setMetaData(packet.getData()); ++ tileentitystructure.setIgnoreEntities(packet.isIgnoreEntities()); ++ tileentitystructure.setShowAir(packet.isShowAir()); ++ tileentitystructure.setShowBoundingBox(packet.isShowBoundingBox()); ++ tileentitystructure.setIntegrity(packet.getIntegrity()); ++ tileentitystructure.setSeed(packet.getSeed()); ++ if (tileentitystructure.hasStructureName()) { ++ String s = tileentitystructure.getStructureName(); ++ + if (packet.getUpdateType() == StructureBlockEntity.UpdateType.SAVE_AREA) { +- if (structureBlockEntity.saveStructure()) { +- this.player.displayClientMessage(Component.translatable("structure_block.save_success", structureName), false); ++ if (tileentitystructure.saveStructure()) { ++ this.player.displayClientMessage(Component.translatable("structure_block.save_success", s), false); + } else { +- this.player.displayClientMessage(Component.translatable("structure_block.save_failure", structureName), false); ++ this.player.displayClientMessage(Component.translatable("structure_block.save_failure", s), false); + } + } else if (packet.getUpdateType() == StructureBlockEntity.UpdateType.LOAD_AREA) { +- if (!structureBlockEntity.isStructureLoadable()) { +- this.player.displayClientMessage(Component.translatable("structure_block.load_not_found", structureName), false); +- } else if (structureBlockEntity.placeStructureIfSameSize(this.player.serverLevel())) { +- this.player.displayClientMessage(Component.translatable("structure_block.load_success", structureName), false); ++ if (!tileentitystructure.isStructureLoadable()) { ++ this.player.displayClientMessage(Component.translatable("structure_block.load_not_found", s), false); ++ } else if (tileentitystructure.placeStructureIfSameSize(this.player.serverLevel())) { ++ this.player.displayClientMessage(Component.translatable("structure_block.load_success", s), false); + } else { +- this.player.displayClientMessage(Component.translatable("structure_block.load_prepare", structureName), false); ++ this.player.displayClientMessage(Component.translatable("structure_block.load_prepare", s), false); + } + } else if (packet.getUpdateType() == StructureBlockEntity.UpdateType.SCAN_AREA) { +- if (structureBlockEntity.detectSize()) { +- this.player.displayClientMessage(Component.translatable("structure_block.size_success", structureName), false); ++ if (tileentitystructure.detectSize()) { ++ this.player.displayClientMessage(Component.translatable("structure_block.size_success", s), false); + } else { + this.player.displayClientMessage(Component.translatable("structure_block.size_failure"), false); + } +@@ -681,9 +886,10 @@ + this.player.displayClientMessage(Component.translatable("structure_block.invalid_structure_name", packet.getName()), false); + } + +- structureBlockEntity.setChanged(); +- this.player.level().sendBlockUpdated(pos, blockState, blockState, 3); ++ tileentitystructure.setChanged(); ++ this.player.level().sendBlockUpdated(blockposition, iblockdata, iblockdata, 3); + } ++ + } + } + +@@ -691,19 +897,24 @@ + public void handleSetJigsawBlock(ServerboundSetJigsawBlockPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + if (this.player.canUseGameMasterBlocks()) { +- BlockPos pos = packet.getPos(); +- BlockState blockState = this.player.level().getBlockState(pos); +- if (this.player.level().getBlockEntity(pos) instanceof JigsawBlockEntity jigsawBlockEntity) { +- jigsawBlockEntity.setName(packet.getName()); +- jigsawBlockEntity.setTarget(packet.getTarget()); +- jigsawBlockEntity.setPool(ResourceKey.create(Registries.TEMPLATE_POOL, packet.getPool())); +- jigsawBlockEntity.setFinalState(packet.getFinalState()); +- jigsawBlockEntity.setJoint(packet.getJoint()); +- jigsawBlockEntity.setPlacementPriority(packet.getPlacementPriority()); +- jigsawBlockEntity.setSelectionPriority(packet.getSelectionPriority()); +- jigsawBlockEntity.setChanged(); +- this.player.level().sendBlockUpdated(pos, blockState, blockState, 3); ++ BlockPos blockposition = packet.getPos(); ++ IBlockData iblockdata = this.player.level().getBlockState(blockposition); ++ BlockEntity tileentity = this.player.level().getBlockEntity(blockposition); ++ ++ if (tileentity instanceof JigsawBlockEntity) { ++ JigsawBlockEntity tileentityjigsaw = (JigsawBlockEntity) tileentity; ++ ++ tileentityjigsaw.setName(packet.getName()); ++ tileentityjigsaw.setTarget(packet.getTarget()); ++ tileentityjigsaw.setPool(ResourceKey.create(Registries.TEMPLATE_POOL, packet.getPool())); ++ tileentityjigsaw.setFinalState(packet.getFinalState()); ++ tileentityjigsaw.setJoint(packet.getJoint()); ++ tileentityjigsaw.setPlacementPriority(packet.getPlacementPriority()); ++ tileentityjigsaw.setSelectionPriority(packet.getSelectionPriority()); ++ tileentityjigsaw.setChanged(); ++ this.player.level().sendBlockUpdated(blockposition, iblockdata, iblockdata, 3); + } ++ + } + } + +@@ -711,95 +922,141 @@ + public void handleJigsawGenerate(ServerboundJigsawGeneratePacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + if (this.player.canUseGameMasterBlocks()) { +- BlockPos pos = packet.getPos(); +- if (this.player.level().getBlockEntity(pos) instanceof JigsawBlockEntity jigsawBlockEntity) { +- jigsawBlockEntity.generate(this.player.serverLevel(), packet.levels(), packet.keepJigsaws()); ++ BlockPos blockposition = packet.getPos(); ++ BlockEntity tileentity = this.player.level().getBlockEntity(blockposition); ++ ++ if (tileentity instanceof JigsawBlockEntity) { ++ JigsawBlockEntity tileentityjigsaw = (JigsawBlockEntity) tileentity; ++ ++ tileentityjigsaw.generate(this.player.serverLevel(), packet.levels(), packet.keepJigsaws()); + } ++ + } + } + + @Override + public void handleSelectTrade(ServerboundSelectTradePacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); +- int item = packet.getItem(); +- if (this.player.containerMenu instanceof MerchantMenu merchantMenu) { +- if (!merchantMenu.stillValid(this.player)) { +- LOGGER.debug("Player {} interacted with invalid menu {}", this.player, merchantMenu); ++ int i = packet.getItem(); ++ AbstractContainerMenu container = this.player.containerMenu; ++ ++ if (container instanceof MerchantMenu) { ++ MerchantMenu containermerchant = (MerchantMenu) container; ++ // CraftBukkit start ++ final org.bukkit.event.inventory.TradeSelectEvent tradeSelectEvent = CraftEventFactory.callTradeSelectEvent(this.player, i, containermerchant); ++ if (tradeSelectEvent.isCancelled()) { ++ this.player.getBukkitEntity().updateInventory(); + return; + } ++ // CraftBukkit end + +- merchantMenu.setSelectionHint(item); +- merchantMenu.tryMoveItems(item); ++ if (!containermerchant.stillValid(this.player)) { ++ ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, containermerchant); ++ return; ++ } ++ ++ containermerchant.setSelectionHint(i); ++ containermerchant.tryMoveItems(i); + } ++ + } + + @Override + public void handleEditBook(ServerboundEditBookPacket packet) { +- int slot = packet.getSlot(); +- if (Inventory.isHotbarSlot(slot) || slot == 40) { ++ // CraftBukkit start ++ if (this.lastBookTick + 20 > MinecraftServer.currentTick) { ++ this.disconnect("Book edited too quickly!"); ++ return; ++ } ++ this.lastBookTick = MinecraftServer.currentTick; ++ // CraftBukkit end ++ int i = packet.getSlot(); ++ ++ if (Inventory.isHotbarSlot(i) || i == 40) { + List list = Lists.newArrayList(); +- Optional title = packet.getTitle(); +- title.ifPresent(list::add); +- packet.getPages().stream().limit(100L).forEach(list::add); +- Consumer> consumer = title.isPresent() +- ? list1 -> this.signBook(list1.get(0), list1.subList(1, list1.size()), slot) +- : list1 -> this.updateBookContents(list1, slot); +- this.filterTextPacket(list).thenAcceptAsync(consumer, this.server); ++ Optional optional = packet.getTitle(); ++ ++ Objects.requireNonNull(list); ++ optional.ifPresent(list::add); ++ Stream stream = packet.getPages().stream().limit(100L); // CraftBukkit - decompile error ++ ++ Objects.requireNonNull(list); ++ stream.forEach(list::add); ++ Consumer> consumer = optional.isPresent() ? (list1) -> { ++ this.signBook((FilteredText) list1.get(0), list1.subList(1, list1.size()), i); ++ } : (list1) -> { ++ this.updateBookContents(list1, i); ++ }; ++ ++ this.filterTextPacket((List) list).thenAcceptAsync(consumer, this.server); + } + } + + private void updateBookContents(List pages, int index) { +- ItemStack item = this.player.getInventory().getItem(index); +- if (item.is(Items.WRITABLE_BOOK)) { +- this.updateBookPages(pages, UnaryOperator.identity(), item); ++ ItemStack itemstack = this.player.getInventory().getItem(index); ++ ++ if (itemstack.is(Items.WRITABLE_BOOK)) { ++ this.updateBookPages(pages, UnaryOperator.identity(), itemstack.copy(), index, itemstack); // CraftBukkit + } + } + + private void signBook(FilteredText title, List pages, int index) { +- ItemStack item = this.player.getInventory().getItem(index); +- if (item.is(Items.WRITABLE_BOOK)) { +- ItemStack itemStack = new ItemStack(Items.WRITTEN_BOOK); +- CompoundTag tag = item.getTag(); +- if (tag != null) { +- itemStack.setTag(tag.copy()); ++ ItemStack itemstack = this.player.getInventory().getItem(index); ++ ++ if (itemstack.is(Items.WRITABLE_BOOK)) { ++ ItemStack itemstack1 = new ItemStack(Items.WRITTEN_BOOK); ++ CompoundTag nbttagcompound = itemstack.getTag(); ++ ++ if (nbttagcompound != null) { ++ itemstack1.setTag(nbttagcompound.copy()); + } + +- itemStack.addTagElement("author", StringTag.valueOf(this.player.getName().getString())); ++ itemstack1.addTagElement("author", StringTag.valueOf(this.player.getName().getString())); + if (this.player.isTextFilteringEnabled()) { +- itemStack.addTagElement("title", StringTag.valueOf(title.filteredOrEmpty())); ++ itemstack1.addTagElement("title", StringTag.valueOf(title.filteredOrEmpty())); + } else { +- itemStack.addTagElement("filtered_title", StringTag.valueOf(title.filteredOrEmpty())); +- itemStack.addTagElement("title", StringTag.valueOf(title.raw())); ++ itemstack1.addTagElement("filtered_title", StringTag.valueOf(title.filteredOrEmpty())); ++ itemstack1.addTagElement("title", StringTag.valueOf(title.raw())); + } + +- this.updateBookPages(pages, string -> Component.Serializer.toJson(Component.literal(string)), itemStack); +- this.player.getInventory().setItem(index, itemStack); ++ this.updateBookPages(pages, (s) -> { ++ return Component.Serializer.toJson(Component.literal(s)); ++ }, itemstack1, index, itemstack); // CraftBukkit ++ this.player.getInventory().setItem(index, itemstack); // CraftBukkit - event factory updates the hand book + } + } + +- private void updateBookPages(List pages, UnaryOperator updater, ItemStack book) { +- ListTag list = new ListTag(); ++ private void updateBookPages(List list, UnaryOperator unaryoperator, ItemStack itemstack, int slot, ItemStack handItem) { // CraftBukkit ++ ListTag nbttaglist = new ListTag(); ++ + if (this.player.isTextFilteringEnabled()) { +- pages.stream().map(filteredText1 -> StringTag.valueOf(updater.apply(filteredText1.filteredOrEmpty()))).forEach(list::add); ++ Stream stream = list.stream().map((filteredtext) -> { // CraftBukkit - decompile error ++ return StringTag.valueOf((String) unaryoperator.apply(filteredtext.filteredOrEmpty())); ++ }); ++ ++ Objects.requireNonNull(nbttaglist); ++ stream.forEach(nbttaglist::add); + } else { +- CompoundTag compoundTag = new CompoundTag(); ++ CompoundTag nbttagcompound = new CompoundTag(); + int i = 0; + +- for (int size = pages.size(); i < size; i++) { +- FilteredText filteredText = pages.get(i); +- String string = filteredText.raw(); +- list.add(StringTag.valueOf(updater.apply(string))); +- if (filteredText.isFiltered()) { +- compoundTag.putString(String.valueOf(i), updater.apply(filteredText.filteredOrEmpty())); ++ for (int j = list.size(); i < j; ++i) { ++ FilteredText filteredtext = (FilteredText) list.get(i); ++ String s = filteredtext.raw(); ++ ++ nbttaglist.add(StringTag.valueOf((String) unaryoperator.apply(s))); ++ if (filteredtext.isFiltered()) { ++ nbttagcompound.putString(String.valueOf(i), (String) unaryoperator.apply(filteredtext.filteredOrEmpty())); + } + } + +- if (!compoundTag.isEmpty()) { +- book.addTagElement("filtered_pages", compoundTag); ++ if (!nbttagcompound.isEmpty()) { ++ itemstack.addTagElement("filtered_pages", nbttagcompound); + } + } + +- book.addTagElement("pages", list); ++ itemstack.addTagElement("pages", nbttaglist); ++ CraftEventFactory.handleEditBookEvent(player, slot, handItem, itemstack); // CraftBukkit + } + + @Override +@@ -807,20 +1064,33 @@ + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + if (this.player.hasPermissions(2)) { + Entity entity = this.player.level().getEntity(packet.getEntityId()); ++ + if (entity != null) { +- CompoundTag compoundTag = entity.saveWithoutId(new CompoundTag()); +- this.player.connection.send(new ClientboundTagQueryPacket(packet.getTransactionId(), compoundTag)); ++ CompoundTag nbttagcompound = entity.saveWithoutId(new CompoundTag()); ++ ++ this.player.connection.send(new ClientboundTagQueryPacket(packet.getTransactionId(), nbttagcompound)); + } ++ + } + } + + @Override +- public void handleContainerSlotStateChanged(ServerboundContainerSlotStateChangedPacket serverboundContainerSlotStateChangedPacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundContainerSlotStateChangedPacket, this, this.player.serverLevel()); +- if (!this.player.isSpectator() && serverboundContainerSlotStateChangedPacket.containerId() == this.player.containerMenu.containerId) { +- if (this.player.containerMenu instanceof CrafterMenu crafterMenu && crafterMenu.getContainer() instanceof CrafterBlockEntity crafterBlockEntity) { +- crafterBlockEntity.setSlotState(serverboundContainerSlotStateChangedPacket.slotId(), serverboundContainerSlotStateChangedPacket.newState()); ++ public void handleContainerSlotStateChanged(ServerboundContainerSlotStateChangedPacket serverboundcontainerslotstatechangedpacket) { ++ PacketUtils.ensureRunningOnSameThread(serverboundcontainerslotstatechangedpacket, this, this.player.serverLevel()); ++ if (!this.player.isSpectator() && serverboundcontainerslotstatechangedpacket.containerId() == this.player.containerMenu.containerId) { ++ AbstractContainerMenu container = this.player.containerMenu; ++ ++ if (container instanceof CrafterMenu) { ++ CrafterMenu craftermenu = (CrafterMenu) container; ++ Container iinventory = craftermenu.getContainer(); ++ ++ if (iinventory instanceof CrafterBlockEntity) { ++ CrafterBlockEntity crafterblockentity = (CrafterBlockEntity) iinventory; ++ ++ crafterblockentity.setSlotState(serverboundcontainerslotstatechangedpacket.slotId(), serverboundcontainerslotstatechangedpacket.newState()); ++ } + } ++ + } + } + +@@ -828,20 +1098,22 @@ + public void handleBlockEntityTagQuery(ServerboundBlockEntityTagQuery packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + if (this.player.hasPermissions(2)) { +- BlockEntity blockEntity = this.player.level().getBlockEntity(packet.getPos()); +- CompoundTag compoundTag = blockEntity != null ? blockEntity.saveWithoutMetadata() : null; +- this.player.connection.send(new ClientboundTagQueryPacket(packet.getTransactionId(), compoundTag)); ++ BlockEntity tileentity = this.player.level().getBlockEntity(packet.getPos()); ++ CompoundTag nbttagcompound = tileentity != null ? tileentity.saveWithoutMetadata() : null; ++ ++ this.player.connection.send(new ClientboundTagQueryPacket(packet.getTransactionId(), nbttagcompound)); + } + } + + @Override + public void handleMovePlayer(ServerboundMovePlayerPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); +- if (containsInvalidValues(packet.getX(0.0), packet.getY(0.0), packet.getZ(0.0), packet.getYRot(0.0F), packet.getXRot(0.0F))) { ++ if (containsInvalidValues(packet.getX(0.0D), packet.getY(0.0D), packet.getZ(0.0D), packet.getYRot(0.0F), packet.getXRot(0.0F))) { + this.disconnect(Component.translatable("multiplayer.disconnect.invalid_player_movement")); + } else { +- ServerLevel serverLevel = this.player.serverLevel(); +- if (!this.player.wonGame) { ++ ServerLevel worldserver = this.player.serverLevel(); ++ ++ if (!this.player.wonGame && !this.player.isImmobile()) { // CraftBukkit + if (this.tickCount == 0) { + this.resetPosition(); + } +@@ -849,120 +1121,192 @@ + if (this.awaitingPositionFromClient != null) { + if (this.tickCount - this.awaitingTeleportTime > 20) { + this.awaitingTeleportTime = this.tickCount; +- this.teleport( +- this.awaitingPositionFromClient.x, +- this.awaitingPositionFromClient.y, +- this.awaitingPositionFromClient.z, +- this.player.getYRot(), +- this.player.getXRot() +- ); ++ this.teleport(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); + } ++ this.allowedPlayerTicks = 20; // CraftBukkit + } else { + this.awaitingTeleportTime = this.tickCount; +- double d = clampHorizontal(packet.getX(this.player.getX())); ++ double d0 = clampHorizontal(packet.getX(this.player.getX())); + double d1 = clampVertical(packet.getY(this.player.getY())); + double d2 = clampHorizontal(packet.getZ(this.player.getZ())); + float f = Mth.wrapDegrees(packet.getYRot(this.player.getYRot())); + float f1 = Mth.wrapDegrees(packet.getXRot(this.player.getXRot())); ++ + if (this.player.isPassenger()) { + this.player.absMoveTo(this.player.getX(), this.player.getY(), this.player.getZ(), f, f1); + this.player.serverLevel().getChunkSource().move(this.player); ++ this.allowedPlayerTicks = 20; // CraftBukkit + } else { +- double x = this.player.getX(); +- double y = this.player.getY(); +- double z = this.player.getZ(); +- double d3 = d - this.firstGoodX; +- double d4 = d1 - this.firstGoodY; +- double d5 = d2 - this.firstGoodZ; +- double d6 = this.player.getDeltaMovement().lengthSqr(); +- double d7 = d3 * d3 + d4 * d4 + d5 * d5; ++ // CraftBukkit - Make sure the move is valid but then reset it for plugins to modify ++ double prevX = player.getX(); ++ double prevY = player.getY(); ++ double prevZ = player.getZ(); ++ float prevYaw = player.getYRot(); ++ float prevPitch = player.getXRot(); ++ // CraftBukkit end ++ double d3 = this.player.getX(); ++ double d4 = this.player.getY(); ++ double d5 = this.player.getZ(); ++ double d6 = d0 - this.firstGoodX; ++ double d7 = d1 - this.firstGoodY; ++ double d8 = d2 - this.firstGoodZ; ++ double d9 = this.player.getDeltaMovement().lengthSqr(); ++ double d10 = d6 * d6 + d7 * d7 + d8 * d8; ++ + if (this.player.isSleeping()) { +- if (d7 > 1.0) { ++ if (d10 > 1.0D) { + this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), f, f1); + } ++ + } else { +- if (serverLevel.tickRateManager().runsNormally()) { +- this.receivedMovePacketCount++; ++ if (worldserver.tickRateManager().runsNormally()) { ++ ++this.receivedMovePacketCount; + int i = this.receivedMovePacketCount - this.knownMovePacketCount; +- if (i > 5) { +- LOGGER.debug("{} is sending move packets too frequently ({} packets since last tick)", this.player.getName().getString(), i); ++ ++ // CraftBukkit start - handle custom speeds and skipped ticks ++ this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick; ++ this.allowedPlayerTicks = Math.max(this.allowedPlayerTicks, 1); ++ this.lastTick = (int) (System.currentTimeMillis() / 50); ++ ++ if (i > Math.max(this.allowedPlayerTicks, 5)) { ++ ServerGamePacketListenerImpl.LOGGER.debug("{} is sending move packets too frequently ({} packets since last tick)", this.player.getName().getString(), i); + i = 1; + } + +- if (!this.player.isChangingDimension() +- && ( +- !this.player.level().getGameRules().getBoolean(GameRules.RULE_DISABLE_ELYTRA_MOVEMENT_CHECK) +- || !this.player.isFallFlying() +- )) { ++ if (packet.hasRot || d10 > 0) { ++ allowedPlayerTicks -= 1; ++ } else { ++ allowedPlayerTicks = 20; ++ } ++ double speed; ++ if (player.getAbilities().flying) { ++ speed = player.getAbilities().flyingSpeed * 20f; ++ } else { ++ speed = player.getAbilities().walkingSpeed * 10f; ++ } ++ ++ if (!this.player.isChangingDimension() && (!this.player.level().getGameRules().getBoolean(GameRules.RULE_DISABLE_ELYTRA_MOVEMENT_CHECK) || !this.player.isFallFlying())) { + float f2 = this.player.isFallFlying() ? 300.0F : 100.0F; +- if (d7 - d6 > (double)(f2 * (float)i) && !this.isSingleplayerOwner()) { +- LOGGER.warn("{} moved too quickly! {},{},{}", this.player.getName().getString(), d3, d4, d5); ++ ++ if (d10 - d9 > Math.max(f2, Math.pow((double) (10.0F * (float) i * speed), 2)) && !this.isSingleplayerOwner()) { ++ // CraftBukkit end ++ ServerGamePacketListenerImpl.LOGGER.warn("{} moved too quickly! {},{},{}", new Object[]{this.player.getName().getString(), d6, d7, d8}); + this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot()); + return; + } + } + } + +- AABB boundingBox = this.player.getBoundingBox(); +- d3 = d - this.lastGoodX; +- d4 = d1 - this.lastGoodY; +- d5 = d2 - this.lastGoodZ; +- boolean flag = d4 > 0.0; ++ AABB axisalignedbb = this.player.getBoundingBox(); ++ ++ d6 = d0 - this.lastGoodX; ++ d7 = d1 - this.lastGoodY; ++ d8 = d2 - this.lastGoodZ; ++ boolean flag = d7 > 0.0D; ++ + if (this.player.onGround() && !packet.isOnGround() && flag) { + this.player.jumpFromGround(); + } + + boolean flag1 = this.player.verticalCollisionBelow; +- this.player.move(MoverType.PLAYER, new Vec3(d3, d4, d5)); +- d3 = d - this.player.getX(); +- double var36 = d1 - this.player.getY(); +- if (var36 > -0.5 || var36 < 0.5) { +- var36 = 0.0; ++ ++ this.player.move(EnumMoveType.PLAYER, new Vec3(d6, d7, d8)); ++ this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move ++ double d11 = d7; ++ ++ d6 = d0 - this.player.getX(); ++ d7 = d1 - this.player.getY(); ++ if (d7 > -0.5D || d7 < 0.5D) { ++ d7 = 0.0D; + } + +- d5 = d2 - this.player.getZ(); +- d7 = d3 * d3 + var36 * var36 + d5 * d5; ++ d8 = d2 - this.player.getZ(); ++ d10 = d6 * d6 + d7 * d7 + d8 * d8; + boolean flag2 = false; +- if (!this.player.isChangingDimension() +- && d7 > 0.0625 +- && !this.player.isSleeping() +- && !this.player.gameMode.isCreative() +- && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR) { ++ ++ if (!this.player.isChangingDimension() && d10 > 0.0625D && !this.player.isSleeping() && !this.player.gameMode.isCreative() && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR) { + flag2 = true; +- LOGGER.warn("{} moved wrongly!", this.player.getName().getString()); ++ ServerGamePacketListenerImpl.LOGGER.warn("{} moved wrongly!", this.player.getName().getString()); + } + +- if (this.player.noPhysics +- || this.player.isSleeping() +- || (!flag2 || !serverLevel.noCollision(this.player, boundingBox)) +- && !this.isPlayerCollidingWithAnythingNew(serverLevel, boundingBox, d, d1, d2)) { +- this.player.absMoveTo(d, d1, d2, f, f1); +- this.clientIsFloating = d4 >= -0.03125 +- && !flag1 +- && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR +- && !this.server.isFlightAllowed() +- && !this.player.getAbilities().mayfly +- && !this.player.hasEffect(MobEffects.LEVITATION) +- && !this.player.isFallFlying() +- && !this.player.isAutoSpinAttack() +- && this.noBlocksAround(this.player); ++ if (!this.player.noPhysics && !this.player.isSleeping() && (flag2 && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb, d0, d1, d2))) { ++ this.internalTeleport(d3, d4, d5, f, f1, Collections.emptySet()); // CraftBukkit - SPIGOT-1807: Don't call teleport event, when the client thinks the player is falling, because the chunks are not loaded on the client yet. ++ this.player.doCheckFallDamage(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5, packet.isOnGround()); ++ } else { ++ // CraftBukkit start - fire PlayerMoveEvent ++ // Reset to old location first ++ this.player.absMoveTo(prevX, prevY, prevZ, prevYaw, prevPitch); ++ ++ Player player = this.getCraftPlayer(); ++ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. ++ Location to = player.getLocation().clone(); // Start off the To location as the Players current location. ++ ++ // If the packet contains movement information then we update the To location with the correct XYZ. ++ if (packet.hasPos) { ++ to.setX(packet.x); ++ to.setY(packet.y); ++ to.setZ(packet.z); ++ } ++ ++ // If the packet contains look information then we update the To location with the correct Yaw & Pitch. ++ if (packet.hasRot) { ++ to.setYaw(packet.yRot); ++ to.setPitch(packet.xRot); ++ } ++ ++ // Prevent 40 event-calls for less than a single pixel of movement >.> ++ double delta = Math.pow(this.lastPosX - to.getX(), 2) + Math.pow(this.lastPosY - to.getY(), 2) + Math.pow(this.lastPosZ - to.getZ(), 2); ++ float deltaAngle = Math.abs(this.lastYaw - to.getYaw()) + Math.abs(this.lastPitch - to.getPitch()); ++ ++ if ((delta > 1f / 256 || deltaAngle > 10f) && !this.player.isImmobile()) { ++ this.lastPosX = to.getX(); ++ this.lastPosY = to.getY(); ++ this.lastPosZ = to.getZ(); ++ this.lastYaw = to.getYaw(); ++ this.lastPitch = to.getPitch(); ++ ++ // Skip the first time we do this ++ if (from.getX() != Double.MAX_VALUE) { ++ Location oldTo = to.clone(); ++ PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ // If the event is cancelled we move the player back to their old location. ++ if (event.isCancelled()) { ++ teleport(from); ++ return; ++ } ++ ++ // If a Plugin has changed the To destination then we teleport the Player ++ // there to avoid any 'Moved wrongly' or 'Moved too quickly' errors. ++ // We only do this if the Event was not cancelled. ++ if (!oldTo.equals(event.getTo()) && !event.isCancelled()) { ++ this.player.getBukkitEntity().teleport(event.getTo(), PlayerTeleportEvent.TeleportCause.PLUGIN); ++ return; ++ } ++ ++ // Check to see if the Players Location has some how changed during the call of the event. ++ // This can happen due to a plugin teleporting the player instead of using .setTo() ++ if (!from.equals(this.getCraftPlayer().getLocation()) && this.justTeleported) { ++ this.justTeleported = false; ++ return; ++ } ++ } ++ } ++ // CraftBukkit end ++ this.player.absMoveTo(d0, d1, d2, f, f1); ++ this.clientIsFloating = d11 >= -0.03125D && !flag1 && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR && !this.server.isFlightAllowed() && !this.player.getAbilities().mayfly && !this.player.hasEffect(MobEffects.LEVITATION) && !this.player.isFallFlying() && !this.player.isAutoSpinAttack() && this.noBlocksAround(this.player); + this.player.serverLevel().getChunkSource().move(this.player); +- this.player.doCheckFallDamage(this.player.getX() - x, this.player.getY() - y, this.player.getZ() - z, packet.isOnGround()); +- this.player +- .setOnGroundWithKnownMovement( +- packet.isOnGround(), new Vec3(this.player.getX() - x, this.player.getY() - y, this.player.getZ() - z) +- ); ++ this.player.doCheckFallDamage(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5, packet.isOnGround()); ++ this.player.setOnGroundWithKnownMovement(packet.isOnGround(), new Vec3(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5)); + if (flag) { + this.player.resetFallDistance(); + } + +- this.player.checkMovementStatistics(this.player.getX() - x, this.player.getY() - y, this.player.getZ() - z); ++ this.player.checkMovementStatistics(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5); + this.lastGoodX = this.player.getX(); + this.lastGoodY = this.player.getY(); + this.lastGoodZ = this.player.getZ(); +- } else { +- this.teleport(x, y, z, f, f1); +- this.player.doCheckFallDamage(this.player.getX() - x, this.player.getY() - y, this.player.getZ() - z, packet.isOnGround()); + } + } + } +@@ -971,58 +1315,165 @@ + } + } + +- private boolean isPlayerCollidingWithAnythingNew(LevelReader level, AABB box, double x, double y, double z) { +- AABB aABB = this.player.getBoundingBox().move(x - this.player.getX(), y - this.player.getY(), z - this.player.getZ()); +- Iterable collisions = level.getCollisions(this.player, aABB.deflate(1.0E-5F)); +- VoxelShape voxelShape = Shapes.create(box.deflate(1.0E-5F)); ++ private boolean isPlayerCollidingWithAnythingNew(LevelReader level, AABB box, double x, double d1, double y) { ++ AABB axisalignedbb1 = this.player.getBoundingBox().move(x - this.player.getX(), d1 - this.player.getY(), y - this.player.getZ()); ++ Iterable iterable = level.getCollisions(this.player, axisalignedbb1.deflate(9.999999747378752E-6D)); ++ VoxelShape voxelshape = Shapes.create(box.deflate(9.999999747378752E-6D)); ++ Iterator iterator = iterable.iterator(); + +- for (VoxelShape voxelShape1 : collisions) { +- if (!Shapes.joinIsNotEmpty(voxelShape1, voxelShape, BooleanOp.AND)) { +- return true; ++ VoxelShape voxelshape1; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return false; + } ++ ++ voxelshape1 = (VoxelShape) iterator.next(); ++ } while (Shapes.joinIsNotEmpty(voxelshape1, voxelshape, BooleanOp.AND)); ++ ++ return true; ++ } ++ ++ // CraftBukkit start - Delegate to teleport(Location) ++ public void teleport(double x, double d1, double y, float f, float z) { ++ this.teleport(x, d1, y, f, z, PlayerTeleportEvent.TeleportCause.UNKNOWN); ++ } ++ ++ public void teleport(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { ++ this.teleport(d0, d1, d2, f, f1, Collections.emptySet(), cause); ++ } ++ ++ public void teleport(double x, double d1, double y, float f, float z, Set set) { ++ this.teleport(x, d1, y, f, z, set, PlayerTeleportEvent.TeleportCause.UNKNOWN); ++ } ++ ++ public boolean teleport(double d0, double d1, double d2, float f, float f1, Set set, PlayerTeleportEvent.TeleportCause cause) { // CraftBukkit - Return event status ++ Player player = this.getCraftPlayer(); ++ Location from = player.getLocation(); ++ ++ double x = d0; ++ double y = d1; ++ double z = d2; ++ float yaw = f; ++ float pitch = f1; ++ ++ Location to = new Location(this.getCraftPlayer().getWorld(), x, y, z, yaw, pitch); ++ // SPIGOT-5171: Triggered on join ++ if (from.equals(to)) { ++ this.internalTeleport(d0, d1, d2, f, f1, set); ++ return false; // CraftBukkit - Return event status + } + +- return false; ++ PlayerTeleportEvent event = new PlayerTeleportEvent(player, from.clone(), to.clone(), cause); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled() || !to.equals(event.getTo())) { ++ set.clear(); // Can't relative teleport ++ to = event.isCancelled() ? event.getFrom() : event.getTo(); ++ d0 = to.getX(); ++ d1 = to.getY(); ++ d2 = to.getZ(); ++ f = to.getYaw(); ++ f1 = to.getPitch(); ++ } ++ ++ this.internalTeleport(d0, d1, d2, f, f1, set); ++ return event.isCancelled(); // CraftBukkit - Return event status + } + +- public void teleport(double x, double y, double z, float yaw, float pitch) { +- this.teleport(x, y, z, yaw, pitch, Collections.emptySet()); ++ public void teleport(Location dest) { ++ internalTeleport(dest.getX(), dest.getY(), dest.getZ(), dest.getYaw(), dest.getPitch(), Collections.emptySet()); + } + +- public void teleport(double x, double y, double z, float yaw, float pitch, Set relativeSet) { +- double d = relativeSet.contains(RelativeMovement.X) ? this.player.getX() : 0.0; +- double d1 = relativeSet.contains(RelativeMovement.Y) ? this.player.getY() : 0.0; +- double d2 = relativeSet.contains(RelativeMovement.Z) ? this.player.getZ() : 0.0; +- float f = relativeSet.contains(RelativeMovement.Y_ROT) ? this.player.getYRot() : 0.0F; +- float f1 = relativeSet.contains(RelativeMovement.X_ROT) ? this.player.getXRot() : 0.0F; +- this.awaitingPositionFromClient = new Vec3(x, y, z); ++ private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set set) { ++ // CraftBukkit start ++ if (Float.isNaN(f)) { ++ f = 0; ++ } ++ if (Float.isNaN(f1)) { ++ f1 = 0; ++ } ++ ++ this.justTeleported = true; ++ // CraftBukkit end ++ double d3 = set.contains(RelativeMovement.X) ? this.player.getX() : 0.0D; ++ double d4 = set.contains(RelativeMovement.Y) ? this.player.getY() : 0.0D; ++ double d5 = set.contains(RelativeMovement.Z) ? this.player.getZ() : 0.0D; ++ float f2 = set.contains(RelativeMovement.Y_ROT) ? this.player.getYRot() : 0.0F; ++ float f3 = set.contains(RelativeMovement.X_ROT) ? this.player.getXRot() : 0.0F; ++ ++ this.awaitingPositionFromClient = new Vec3(d0, d1, d2); + if (++this.awaitingTeleport == Integer.MAX_VALUE) { + this.awaitingTeleport = 0; + } + ++ // CraftBukkit start - update last location ++ this.lastPosX = this.awaitingPositionFromClient.x; ++ this.lastPosY = this.awaitingPositionFromClient.y; ++ this.lastPosZ = this.awaitingPositionFromClient.z; ++ this.lastYaw = f; ++ this.lastPitch = f1; ++ // CraftBukkit end ++ + this.awaitingTeleportTime = this.tickCount; +- this.player.absMoveTo(x, y, z, yaw, pitch); +- this.player.connection.send(new ClientboundPlayerPositionPacket(x - d, y - d1, z - d2, yaw - f, pitch - f1, relativeSet, this.awaitingTeleport)); ++ this.player.absMoveTo(d0, d1, d2, f, f1); ++ this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport)); + } + + @Override + public void handlePlayerAction(ServerboundPlayerActionPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); +- BlockPos pos = packet.getPos(); ++ if (this.player.isImmobile()) return; // CraftBukkit ++ BlockPos blockposition = packet.getPos(); ++ + this.player.resetLastActionTime(); +- ServerboundPlayerActionPacket.Action action = packet.getAction(); +- switch (action) { ++ ServerboundPlayerActionPacket.EnumPlayerDigType packetplayinblockdig_enumplayerdigtype = packet.getAction(); ++ ++ switch (packetplayinblockdig_enumplayerdigtype) { + case SWAP_ITEM_WITH_OFFHAND: + if (!this.player.isSpectator()) { +- ItemStack itemInHand = this.player.getItemInHand(InteractionHand.OFF_HAND); +- this.player.setItemInHand(InteractionHand.OFF_HAND, this.player.getItemInHand(InteractionHand.MAIN_HAND)); +- this.player.setItemInHand(InteractionHand.MAIN_HAND, itemInHand); ++ ItemStack itemstack = this.player.getItemInHand(EnumHand.OFF_HAND); ++ ++ // CraftBukkit start - inspiration taken from DispenserRegistry (See SpigotCraft#394) ++ CraftItemStack mainHand = CraftItemStack.asCraftMirror(itemstack); ++ CraftItemStack offHand = CraftItemStack.asCraftMirror(this.player.getItemInHand(EnumHand.MAIN_HAND)); ++ PlayerSwapHandItemsEvent swapItemsEvent = new PlayerSwapHandItemsEvent(getCraftPlayer(), mainHand.clone(), offHand.clone()); ++ this.cserver.getPluginManager().callEvent(swapItemsEvent); ++ if (swapItemsEvent.isCancelled()) { ++ return; ++ } ++ if (swapItemsEvent.getOffHandItem().equals(offHand)) { ++ this.player.setItemInHand(EnumHand.OFF_HAND, this.player.getItemInHand(EnumHand.MAIN_HAND)); ++ } else { ++ this.player.setItemInHand(EnumHand.OFF_HAND, CraftItemStack.asNMSCopy(swapItemsEvent.getOffHandItem())); ++ } ++ if (swapItemsEvent.getMainHandItem().equals(mainHand)) { ++ this.player.setItemInHand(EnumHand.MAIN_HAND, itemstack); ++ } else { ++ this.player.setItemInHand(EnumHand.MAIN_HAND, CraftItemStack.asNMSCopy(swapItemsEvent.getMainHandItem())); ++ } ++ // CraftBukkit end + this.player.stopUsingItem(); + } + + return; + case DROP_ITEM: + if (!this.player.isSpectator()) { ++ // limit how quickly items can be dropped ++ // If the ticks aren't the same then the count starts from 0 and we update the lastDropTick. ++ if (this.lastDropTick != MinecraftServer.currentTick) { ++ this.dropCount = 0; ++ this.lastDropTick = MinecraftServer.currentTick; ++ } else { ++ // Else we increment the drop count and check the amount. ++ this.dropCount++; ++ if (this.dropCount >= 20) { ++ LOGGER.warn(this.player.getScoreboardName() + " dropped their items too quickly!"); ++ this.disconnect("You dropped your items too quickly (Hacking?)"); ++ return; ++ } ++ } ++ // CraftBukkit end + this.player.drop(false); + } + +@@ -1039,7 +1490,7 @@ + case START_DESTROY_BLOCK: + case ABORT_DESTROY_BLOCK: + case STOP_DESTROY_BLOCK: +- this.player.gameMode.handleBlockBreakAction(pos, action, packet.getDirection(), this.player.level().getMaxBuildHeight(), packet.getSequence()); ++ this.player.gameMode.handleBlockBreakAction(blockposition, packetplayinblockdig_enumplayerdigtype, packet.getDirection(), this.player.level().getMaxBuildHeight(), packet.getSequence()); + this.player.connection.ackBlockChangesUpTo(packet.getSequence()); + return; + default: +@@ -1052,6 +1503,7 @@ + return false; + } else { + Item item = stack.getItem(); ++ + return (item instanceof BlockItem || item instanceof BucketItem) && !player.getCooldowns().isOnCooldown(item); + } + } +@@ -1059,51 +1511,51 @@ + @Override + public void handleUseItemOn(ServerboundUseItemOnPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.connection.ackBlockChangesUpTo(packet.getSequence()); +- ServerLevel serverLevel = this.player.serverLevel(); +- InteractionHand hand = packet.getHand(); +- ItemStack itemInHand = this.player.getItemInHand(hand); +- if (itemInHand.isItemEnabled(serverLevel.enabledFeatures())) { +- BlockHitResult hitResult = packet.getHitResult(); +- Vec3 location = hitResult.getLocation(); +- BlockPos blockPos = hitResult.getBlockPos(); +- Vec3 vec3 = Vec3.atCenterOf(blockPos); +- if (!(this.player.getEyePosition().distanceToSqr(vec3) > MAX_INTERACTION_DISTANCE)) { +- Vec3 vec31 = location.subtract(vec3); +- double d = 1.0000001; +- if (Math.abs(vec31.x()) < 1.0000001 && Math.abs(vec31.y()) < 1.0000001 && Math.abs(vec31.z()) < 1.0000001) { +- Direction direction = hitResult.getDirection(); ++ ServerLevel worldserver = this.player.serverLevel(); ++ EnumHand enumhand = packet.getHand(); ++ ItemStack itemstack = this.player.getItemInHand(enumhand); ++ ++ if (itemstack.isItemEnabled(worldserver.enabledFeatures())) { ++ BlockHitResult movingobjectpositionblock = packet.getHitResult(); ++ Vec3 vec3d = movingobjectpositionblock.getLocation(); ++ BlockPos blockposition = movingobjectpositionblock.getBlockPos(); ++ Vec3 vec3d1 = Vec3.atCenterOf(blockposition); ++ ++ if (this.player.getEyePosition().distanceToSqr(vec3d1) <= ServerGamePacketListenerImpl.MAX_INTERACTION_DISTANCE) { ++ Vec3 vec3d2 = vec3d.subtract(vec3d1); ++ double d0 = 1.0000001D; ++ ++ if (Math.abs(vec3d2.x()) < 1.0000001D && Math.abs(vec3d2.y()) < 1.0000001D && Math.abs(vec3d2.z()) < 1.0000001D) { ++ Direction enumdirection = movingobjectpositionblock.getDirection(); ++ + this.player.resetLastActionTime(); +- int maxBuildHeight = this.player.level().getMaxBuildHeight(); +- if (blockPos.getY() < maxBuildHeight) { +- if (this.awaitingPositionFromClient == null +- && this.player.distanceToSqr((double)blockPos.getX() + 0.5, (double)blockPos.getY() + 0.5, (double)blockPos.getZ() + 0.5) < 64.0 +- && serverLevel.mayInteract(this.player, blockPos)) { +- InteractionResult interactionResult = this.player.gameMode.useItemOn(this.player, serverLevel, itemInHand, hand, hitResult); +- if (direction == Direction.UP +- && !interactionResult.consumesAction() +- && blockPos.getY() >= maxBuildHeight - 1 +- && wasBlockPlacementAttempt(this.player, itemInHand)) { +- Component component = Component.translatable("build.tooHigh", maxBuildHeight - 1).withStyle(ChatFormatting.RED); +- this.player.sendSystemMessage(component, true); +- } else if (interactionResult.shouldSwing()) { +- this.player.swing(hand, true); ++ int i = this.player.level().getMaxBuildHeight(); ++ ++ if (blockposition.getY() < i) { ++ if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.mayInteract(this.player, blockposition)) { ++ this.player.stopUsingItem(); // CraftBukkit - SPIGOT-4706 ++ InteractionResult enuminteractionresult = this.player.gameMode.useItemOn(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock); ++ ++ if (enumdirection == Direction.UP && !enuminteractionresult.consumesAction() && blockposition.getY() >= i - 1 && wasBlockPlacementAttempt(this.player, itemstack)) { ++ MutableComponent ichatmutablecomponent = Component.translatable("build.tooHigh", i - 1).withStyle(ChatFormatting.RED); ++ ++ this.player.sendSystemMessage(ichatmutablecomponent, true); ++ } else if (enuminteractionresult.shouldSwing()) { ++ this.player.swing(enumhand, true); + } + } + } else { +- Component component1 = Component.translatable("build.tooHigh", maxBuildHeight - 1).withStyle(ChatFormatting.RED); +- this.player.sendSystemMessage(component1, true); ++ MutableComponent ichatmutablecomponent1 = Component.translatable("build.tooHigh", i - 1).withStyle(ChatFormatting.RED); ++ ++ this.player.sendSystemMessage(ichatmutablecomponent1, true); + } + +- this.player.connection.send(new ClientboundBlockUpdatePacket(serverLevel, blockPos)); +- this.player.connection.send(new ClientboundBlockUpdatePacket(serverLevel, blockPos.relative(direction))); ++ this.player.connection.send(new ClientboundBlockUpdatePacket(worldserver, blockposition)); ++ this.player.connection.send(new ClientboundBlockUpdatePacket(worldserver, blockposition.relative(enumdirection))); + } else { +- LOGGER.warn( +- "Rejecting UseItemOnPacket from {}: Location {} too far away from hit block {}.", +- this.player.getGameProfile().getName(), +- location, +- blockPos +- ); ++ ServerGamePacketListenerImpl.LOGGER.warn("Rejecting UseItemOnPacket from {}: Location {} too far away from hit block {}.", new Object[]{this.player.getGameProfile().getName(), vec3d, blockposition}); + } + } + } +@@ -1112,16 +1564,63 @@ + @Override + public void handleUseItem(ServerboundUseItemPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.ackBlockChangesUpTo(packet.getSequence()); +- ServerLevel serverLevel = this.player.serverLevel(); +- InteractionHand hand = packet.getHand(); +- ItemStack itemInHand = this.player.getItemInHand(hand); ++ ServerLevel worldserver = this.player.serverLevel(); ++ EnumHand enumhand = packet.getHand(); ++ ItemStack itemstack = this.player.getItemInHand(enumhand); ++ + this.player.resetLastActionTime(); +- if (!itemInHand.isEmpty() && itemInHand.isItemEnabled(serverLevel.enabledFeatures())) { +- InteractionResult interactionResult = this.player.gameMode.useItem(this.player, serverLevel, itemInHand, hand); +- if (interactionResult.shouldSwing()) { +- this.player.swing(hand, true); ++ if (!itemstack.isEmpty() && itemstack.isItemEnabled(worldserver.enabledFeatures())) { ++ // CraftBukkit start ++ // Raytrace to look for 'rogue armswings' ++ float f1 = this.player.getXRot(); ++ float f2 = this.player.getYRot(); ++ double d0 = this.player.getX(); ++ double d1 = this.player.getY() + (double) this.player.getEyeHeight(); ++ double d2 = this.player.getZ(); ++ Vec3 vec3d = new Vec3(d0, d1, d2); ++ ++ float f3 = Mth.cos(-f2 * 0.017453292F - 3.1415927F); ++ float f4 = Mth.sin(-f2 * 0.017453292F - 3.1415927F); ++ float f5 = -Mth.cos(-f1 * 0.017453292F); ++ float f6 = Mth.sin(-f1 * 0.017453292F); ++ float f7 = f4 * f5; ++ float f8 = f3 * f5; ++ double d3 = player.gameMode.getGameModeForPlayer()== GameType.CREATIVE ? 5.0D : 4.5D; ++ Vec3 vec3d1 = vec3d.add((double) f7 * d3, (double) f6 * d3, (double) f8 * d3); ++ HitResult movingobjectposition = this.player.level().clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)); ++ ++ boolean cancelled; ++ if (movingobjectposition == null || movingobjectposition.getType() != HitResult.EnumMovingObjectType.BLOCK) { ++ org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.RIGHT_CLICK_AIR, itemstack, enumhand); ++ cancelled = event.useItemInHand() == Event.Result.DENY; ++ } else { ++ BlockHitResult movingobjectpositionblock = (BlockHitResult) movingobjectposition; ++ if (player.gameMode.firedInteract && player.gameMode.interactPosition.equals(movingobjectpositionblock.getBlockPos()) && player.gameMode.interactHand == enumhand && ItemStack.isSameItemSameTags(player.gameMode.interactItemStack, itemstack)) { ++ cancelled = player.gameMode.interactResult; ++ } else { ++ org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), itemstack, true, enumhand, movingobjectpositionblock.getLocation()); ++ cancelled = event.useItemInHand() == Event.Result.DENY; ++ } ++ player.gameMode.firedInteract = false; + } ++ ++ if (cancelled) { ++ this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524 ++ return; ++ } ++ itemstack = this.player.getItemInHand(enumhand); // Update in case it was changed in the event ++ if (itemstack.isEmpty()) { ++ return; ++ } ++ // CraftBukkit end ++ InteractionResult enuminteractionresult = this.player.gameMode.useItem(this.player, worldserver, itemstack, enumhand); ++ ++ if (enuminteractionresult.shouldSwing()) { ++ this.player.swing(enumhand, true); ++ } ++ + } + } + +@@ -1129,39 +1628,62 @@ + public void handleTeleportToEntityPacket(ServerboundTeleportToEntityPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + if (this.player.isSpectator()) { +- for (ServerLevel serverLevel : this.server.getAllLevels()) { +- Entity entity = packet.getEntity(serverLevel); ++ Iterator iterator = this.server.getAllLevels().iterator(); ++ ++ while (iterator.hasNext()) { ++ ServerLevel worldserver = (ServerLevel) iterator.next(); ++ Entity entity = packet.getEntity(worldserver); ++ + if (entity != null) { +- this.player.teleportTo(serverLevel, entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot()); ++ this.player.teleportTo(worldserver, entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot(), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.SPECTATE); // CraftBukkit + return; + } + } + } ++ + } + + @Override + public void handlePaddleBoat(ServerboundPaddleBoatPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); +- if (this.player.getControlledVehicle() instanceof Boat boat) { +- boat.setPaddleState(packet.getLeft(), packet.getRight()); ++ Entity entity = this.player.getControlledVehicle(); ++ ++ if (entity instanceof Boat) { ++ Boat entityboat = (Boat) entity; ++ ++ entityboat.setPaddleState(packet.getLeft(), packet.getRight()); + } ++ + } + + @Override + public void onDisconnect(Component reason) { +- LOGGER.info("{} lost connection: {}", this.player.getName().getString(), reason.getString()); ++ // CraftBukkit start - Rarely it would send a disconnect line twice ++ if (this.processedDisconnect) { ++ return; ++ } else { ++ this.processedDisconnect = true; ++ } ++ // CraftBukkit end ++ ServerGamePacketListenerImpl.LOGGER.info("{} lost connection: {}", this.player.getName().getString(), reason.getString()); + this.removePlayerFromWorld(); + super.onDisconnect(reason); + } + + private void removePlayerFromWorld() { + this.chatMessageChain.close(); ++ // CraftBukkit start - Replace vanilla quit message handling with our own. ++ /* + this.server.invalidateStatus(); +- this.server +- .getPlayerList() +- .broadcastSystemMessage(Component.translatable("multiplayer.player.left", this.player.getDisplayName()).withStyle(ChatFormatting.YELLOW), false); ++ this.server.getPlayerList().broadcastSystemMessage(IChatBaseComponent.translatable("multiplayer.player.left", this.player.getDisplayName()).withStyle(EnumChatFormat.YELLOW), false); ++ */ ++ + this.player.disconnect(); +- this.server.getPlayerList().remove(this.player); ++ String quitMessage = this.server.getPlayerList().remove(this.player); ++ if ((quitMessage != null) && (quitMessage.length() > 0)) { ++ this.server.getPlayerList().broadcastMessage(CraftChatMessage.fromString(quitMessage)); ++ } ++ // CraftBukkit end + this.player.getTextFilter().leave(); + } + +@@ -1176,42 +1698,63 @@ + @Override + public void handleSetCarriedItem(ServerboundSetCarriedItemPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + if (packet.getSlot() >= 0 && packet.getSlot() < Inventory.getSelectionSize()) { +- if (this.player.getInventory().selected != packet.getSlot() && this.player.getUsedItemHand() == InteractionHand.MAIN_HAND) { ++ PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getCraftPlayer(), this.player.getInventory().selected, packet.getSlot()); ++ this.cserver.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ this.send(new ClientboundSetCarriedItemPacket(this.player.getInventory().selected)); ++ this.player.resetLastActionTime(); ++ return; ++ } ++ // CraftBukkit end ++ if (this.player.getInventory().selected != packet.getSlot() && this.player.getUsedItemHand() == EnumHand.MAIN_HAND) { + this.player.stopUsingItem(); + } + + this.player.getInventory().selected = packet.getSlot(); + this.player.resetLastActionTime(); + } else { +- LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); ++ ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); ++ this.disconnect("Invalid hotbar selection (Hacking?)"); // CraftBukkit + } + } + + @Override + public void handleChat(ServerboundChatPacket packet) { ++ // CraftBukkit start - async chat ++ // SPIGOT-3638 ++ if (this.server.isStopped()) { ++ return; ++ } ++ // CraftBukkit end + if (isChatMessageIllegal(packet.message())) { + this.disconnect(Component.translatable("multiplayer.disconnect.illegal_characters")); + } else { + Optional optional = this.tryHandleChat(packet.lastSeenMessages()); ++ + if (optional.isPresent()) { +- this.server.submit(() -> { +- PlayerChatMessage signedMessage; ++ // this.server.submit(() -> { // CraftBukkit - async chat ++ PlayerChatMessage playerchatmessage; ++ + try { +- signedMessage = this.getSignedMessage(packet, optional.get()); +- } catch (SignedMessageChain.DecodeException var6) { +- this.handleMessageDecodeFailure(var6); ++ playerchatmessage = this.getSignedMessage(packet, (LastSeenMessages) optional.get()); ++ } catch (SignedMessageChain.DecodeException signedmessagechain_a) { ++ this.handleMessageDecodeFailure(signedmessagechain_a); + return; + } + +- CompletableFuture completableFuture = this.filterTextPacket(signedMessage.signedContent()); +- Component component = this.server.getChatDecorator().decorate(this.player, signedMessage.decoratedContent()); +- this.chatMessageChain.append(completableFuture, filteredText -> { +- PlayerChatMessage playerChatMessage = signedMessage.withUnsignedContent(component).filter(filteredText.mask()); +- this.broadcastChatMessage(playerChatMessage); ++ CompletableFuture completablefuture = this.filterTextPacket(playerchatmessage.signedContent()).thenApplyAsync(Function.identity(), this.server.chatExecutor); // CraftBukkit - async chat ++ Component ichatbasecomponent = this.server.getChatDecorator().decorate(this.player, playerchatmessage.decoratedContent()); ++ ++ this.chatMessageChain.append(completablefuture, (filteredtext) -> { ++ PlayerChatMessage playerchatmessage1 = playerchatmessage.withUnsignedContent(ichatbasecomponent).filter(filteredtext.mask()); ++ ++ this.broadcastChatMessage(playerchatmessage1); + }); +- }); ++ // }); // CraftBukkit - async chat + } ++ + } + } + +@@ -1221,64 +1764,91 @@ + this.disconnect(Component.translatable("multiplayer.disconnect.illegal_characters")); + } else { + Optional optional = this.tryHandleChat(packet.lastSeenMessages()); ++ + if (optional.isPresent()) { + this.server.submit(() -> { +- this.performChatCommand(packet, optional.get()); ++ // CraftBukkit start - SPIGOT-7346: Prevent disconnected players from executing commands ++ if (player.hasDisconnected()) { ++ return; ++ } ++ // CraftBukkit end ++ ++ this.performChatCommand(packet, (LastSeenMessages) optional.get()); + this.detectRateSpam(); + }); + } ++ + } + } + + private void performChatCommand(ServerboundChatCommandPacket packet, LastSeenMessages lastSeenMessages) { +- ParseResults parseResults = this.parseCommand(packet.command()); ++ // CraftBukkit start ++ String command = "/" + packet.command(); ++ ServerGamePacketListenerImpl.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + command); + +- Map map; ++ PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(getCraftPlayer(), command, new LazyPlayerSet(server)); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ command = event.getMessage().substring(1); ++ ++ ParseResults parseresults = this.parseCommand(command); ++ // CraftBukkit end ++ ++ Map map; ++ + try { +- map = this.collectSignedArguments(packet, SignableCommand.of(parseResults), lastSeenMessages); +- } catch (SignedMessageChain.DecodeException var6) { +- this.handleMessageDecodeFailure(var6); ++ map = (packet.command().equals(command)) ? this.collectSignedArguments(packet, SignableCommand.of(parseresults), lastSeenMessages) : Collections.emptyMap(); // CraftBukkit ++ } catch (SignedMessageChain.DecodeException signedmessagechain_a) { ++ this.handleMessageDecodeFailure(signedmessagechain_a); + return; + } + +- CommandSigningContext commandSigningContext = new CommandSigningContext.SignedArguments(map); +- parseResults = Commands.mapSource( +- parseResults, commandSourceStack -> commandSourceStack.withSigningContext(commandSigningContext, this.chatMessageChain) +- ); +- this.server.getCommands().performCommand(parseResults, packet.command()); ++ CommandSigningContext.a commandsigningcontext_a = new CommandSigningContext.a(map); ++ ++ parseresults = Commands.mapSource(parseresults, (commandlistenerwrapper) -> { // CraftBukkit - decompile error ++ return commandlistenerwrapper.withSigningContext(commandsigningcontext_a, this.chatMessageChain); ++ }); ++ this.server.getCommands().performCommand(parseresults, command); // CraftBukkit + } + + private void handleMessageDecodeFailure(SignedMessageChain.DecodeException exception) { +- LOGGER.warn("Failed to update secure chat state for {}: '{}'", this.player.getGameProfile().getName(), exception.getComponent().getString()); ++ ServerGamePacketListenerImpl.LOGGER.warn("Failed to update secure chat state for {}: '{}'", this.player.getGameProfile().getName(), exception.getComponent().getString()); + if (exception.shouldDisconnect()) { + this.disconnect(exception.getComponent()); + } else { + this.player.sendSystemMessage(exception.getComponent().copy().withStyle(ChatFormatting.RED)); + } ++ + } + +- private Map collectSignedArguments( +- ServerboundChatCommandPacket packet, SignableCommand command, LastSeenMessages lastSeenMessages +- ) throws SignedMessageChain.DecodeException { +- Map map = new Object2ObjectOpenHashMap<>(); ++ private Map collectSignedArguments(ServerboundChatCommandPacket packet, SignableCommand command, LastSeenMessages lastSeenMessages) throws SignedMessageChain.DecodeException { ++ Map map = new Object2ObjectOpenHashMap(); ++ Iterator iterator = command.arguments().iterator(); + +- for (SignableCommand.Argument argument : command.arguments()) { +- MessageSignature messageSignature = packet.argumentSignatures().get(argument.name()); +- SignedMessageBody signedMessageBody = new SignedMessageBody(argument.value(), packet.timeStamp(), packet.salt(), lastSeenMessages); +- map.put(argument.name(), this.signedMessageDecoder.unpack(messageSignature, signedMessageBody)); ++ while (iterator.hasNext()) { ++ SignableCommand.a signablecommand_a = (SignableCommand.a) iterator.next(); ++ MessageSignature messagesignature = packet.argumentSignatures().get(signablecommand_a.name()); ++ SignedMessageBody signedmessagebody = new SignedMessageBody(signablecommand_a.value(), packet.timeStamp(), packet.salt(), lastSeenMessages); ++ ++ map.put(signablecommand_a.name(), this.signedMessageDecoder.unpack(messagesignature, signedmessagebody)); + } + + return map; + } + + private ParseResults parseCommand(String command) { +- CommandDispatcher dispatcher = this.server.getCommands().getDispatcher(); +- return dispatcher.parse(command, this.player.createCommandSourceStack()); ++ com.mojang.brigadier.CommandDispatcher com_mojang_brigadier_commanddispatcher = this.server.getCommands().getDispatcher(); ++ ++ return com_mojang_brigadier_commanddispatcher.parse(command, this.player.createCommandSourceStack()); + } + +- private Optional tryHandleChat(LastSeenMessages.Update update) { +- Optional optional = this.unpackAndApplyLastSeen(update); +- if (this.player.getChatVisibility() == ChatVisiblity.HIDDEN) { ++ private Optional tryHandleChat(LastSeenMessages.Update lastseenmessages_b) { ++ Optional optional = this.unpackAndApplyLastSeen(lastseenmessages_b); ++ ++ if (this.player.isRemoved() || this.player.getChatVisibility() == ChatVisiblity.HIDDEN) { // CraftBukkit - dead men tell no tales + this.send(new ClientboundSystemChatPacket(Component.translatable("chat.disabled.options").withStyle(ChatFormatting.RED), false)); + return Optional.empty(); + } else { +@@ -1288,11 +1858,14 @@ + } + + private Optional unpackAndApplyLastSeen(LastSeenMessages.Update update) { ++ LastSeenMessagesValidator lastseenmessagesvalidator = this.lastSeenMessages; ++ + synchronized (this.lastSeenMessages) { + Optional optional = this.lastSeenMessages.applyUpdate(update); ++ + if (optional.isEmpty()) { +- LOGGER.warn("Failed to validate message acknowledgements from {}", this.player.getName().getString()); +- this.disconnect(CHAT_VALIDATION_FAILED); ++ ServerGamePacketListenerImpl.LOGGER.warn("Failed to validate message acknowledgements from {}", this.player.getName().getString()); ++ this.disconnect(ServerGamePacketListenerImpl.CHAT_VALIDATION_FAILED); + } + + return optional; +@@ -1300,7 +1873,7 @@ + } + + private static boolean isChatMessageIllegal(String message) { +- for (int i = 0; i < message.length(); i++) { ++ for (int i = 0; i < message.length(); ++i) { + if (!SharedConstants.isAllowedChatCharacter(message.charAt(i))) { + return true; + } +@@ -1309,44 +1882,231 @@ + return false; + } + ++ // CraftBukkit start - add method ++ public void chat(String s, PlayerChatMessage original, boolean async) { ++ if (s.isEmpty() || this.player.getChatVisibility() == ChatVisiblity.HIDDEN) { ++ return; ++ } ++ OutgoingChatMessage outgoing = OutgoingChatMessage.create(original); ++ ++ if (!async && s.startsWith("/")) { ++ this.handleCommand(s); ++ } else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { ++ // Do nothing, this is coming from a plugin ++ } else { ++ Player player = this.getCraftPlayer(); ++ AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(server)); ++ String originalFormat = event.getFormat(), originalMessage = event.getMessage(); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (PlayerChatEvent.getHandlerList().getRegisteredListeners().length != 0) { ++ // Evil plugins still listening to deprecated event ++ final PlayerChatEvent queueEvent = new PlayerChatEvent(player, event.getMessage(), event.getFormat(), event.getRecipients()); ++ queueEvent.setCancelled(event.isCancelled()); ++ Waitable waitable = new Waitable() { ++ @Override ++ protected Object evaluate() { ++ org.bukkit.Bukkit.getPluginManager().callEvent(queueEvent); ++ ++ if (queueEvent.isCancelled()) { ++ return null; ++ } ++ ++ String message = String.format(queueEvent.getFormat(), queueEvent.getPlayer().getDisplayName(), queueEvent.getMessage()); ++ if (((LazyPlayerSet) queueEvent.getRecipients()).isLazy()) { ++ if (originalFormat.equals(queueEvent.getFormat()) && originalMessage.equals(queueEvent.getMessage()) && queueEvent.getPlayer().getName().equalsIgnoreCase(queueEvent.getPlayer().getDisplayName())) { ++ ServerGamePacketListenerImpl.this.server.getPlayerList().broadcastChatMessage(original, ServerGamePacketListenerImpl.this.player, ChatType.bind(ChatType.CHAT, (Entity) ServerGamePacketListenerImpl.this.player)); ++ return null; ++ } ++ ++ for (ServerPlayer recipient : server.getPlayerList().players) { ++ recipient.getBukkitEntity().sendMessage(ServerGamePacketListenerImpl.this.player.getUUID(), message); ++ } ++ } else { ++ for (Player player : queueEvent.getRecipients()) { ++ player.sendMessage(ServerGamePacketListenerImpl.this.player.getUUID(), message); ++ } ++ } ++ ServerGamePacketListenerImpl.this.server.console.sendMessage(message); ++ ++ return null; ++ }}; ++ if (async) { ++ server.processQueue.add(waitable); ++ } else { ++ waitable.run(); ++ } ++ try { ++ waitable.get(); ++ } catch (InterruptedException e) { ++ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on! ++ } catch (ExecutionException e) { ++ throw new RuntimeException("Exception processing chat event", e.getCause()); ++ } ++ } else { ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ s = String.format(event.getFormat(), event.getPlayer().getDisplayName(), event.getMessage()); ++ if (((LazyPlayerSet) event.getRecipients()).isLazy()) { ++ if (originalFormat.equals(event.getFormat()) && originalMessage.equals(event.getMessage()) && event.getPlayer().getName().equalsIgnoreCase(event.getPlayer().getDisplayName())) { ++ ServerGamePacketListenerImpl.this.server.getPlayerList().broadcastChatMessage(original, ServerGamePacketListenerImpl.this.player, ChatType.bind(ChatType.CHAT, (Entity) ServerGamePacketListenerImpl.this.player)); ++ return; ++ } ++ ++ for (ServerPlayer recipient : server.getPlayerList().players) { ++ recipient.getBukkitEntity().sendMessage(ServerGamePacketListenerImpl.this.player.getUUID(), s); ++ } ++ } else { ++ for (Player recipient : event.getRecipients()) { ++ recipient.sendMessage(ServerGamePacketListenerImpl.this.player.getUUID(), s); ++ } ++ } ++ server.console.sendMessage(s); ++ } ++ } ++ } ++ ++ private void handleCommand(String s) { ++ this.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + s); ++ ++ CraftPlayer player = this.getCraftPlayer(); ++ ++ PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(player, s, new LazyPlayerSet(server)); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ try { ++ if (this.cserver.dispatchCommand(event.getPlayer(), event.getMessage().substring(1))) { ++ return; ++ } ++ } catch (org.bukkit.command.CommandException ex) { ++ player.sendMessage(org.bukkit.ChatColor.RED + "An internal error occurred while attempting to perform this command"); ++ java.util.logging.Logger.getLogger(ServerGamePacketListenerImpl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); ++ return; ++ } ++ } ++ // CraftBukkit end ++ + private PlayerChatMessage getSignedMessage(ServerboundChatPacket packet, LastSeenMessages lastSeenMessages) throws SignedMessageChain.DecodeException { +- SignedMessageBody signedMessageBody = new SignedMessageBody(packet.message(), packet.timeStamp(), packet.salt(), lastSeenMessages); +- return this.signedMessageDecoder.unpack(packet.signature(), signedMessageBody); ++ SignedMessageBody signedmessagebody = new SignedMessageBody(packet.message(), packet.timeStamp(), packet.salt(), lastSeenMessages); ++ ++ return this.signedMessageDecoder.unpack(packet.signature(), signedmessagebody); + } + + private void broadcastChatMessage(PlayerChatMessage message) { +- this.server.getPlayerList().broadcastChatMessage(message, this.player, ChatType.bind(ChatType.CHAT, this.player)); ++ // CraftBukkit start ++ String s = message.signedContent(); ++ if (s.isEmpty()) { ++ LOGGER.warn(this.player.getScoreboardName() + " tried to send an empty message"); ++ } else if (getCraftPlayer().isConversing()) { ++ final String conversationInput = s; ++ this.server.processQueue.add(new Runnable() { ++ @Override ++ public void run() { ++ getCraftPlayer().acceptConversationInput(conversationInput); ++ } ++ }); ++ } else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { // Re-add "Command Only" flag check ++ this.send(new ClientboundSystemChatPacket(Component.translatable("chat.cannotSend").withStyle(ChatFormatting.RED), false)); ++ } else { ++ this.chat(s, message, true); ++ } ++ // this.server.getPlayerList().broadcastChatMessage(playerchatmessage, this.player, ChatMessageType.bind(ChatMessageType.CHAT, (Entity) this.player)); ++ // CraftBukkit end + this.detectRateSpam(); + } + + private void detectRateSpam() { +- this.chatSpamTickCount += 20; +- if (this.chatSpamTickCount > 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { ++ // CraftBukkit start - replaced with thread safe throttle ++ // this.chatSpamTickCount += 20; ++ if (this.chatSpamTickCount.addAndGet(20) > 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { ++ // CraftBukkit end + this.disconnect(Component.translatable("disconnect.spam")); + } ++ + } + + @Override + public void handleChatAck(ServerboundChatAckPacket packet) { ++ LastSeenMessagesValidator lastseenmessagesvalidator = this.lastSeenMessages; ++ + synchronized (this.lastSeenMessages) { + if (!this.lastSeenMessages.applyOffset(packet.offset())) { +- LOGGER.warn("Failed to validate message acknowledgements from {}", this.player.getName().getString()); +- this.disconnect(CHAT_VALIDATION_FAILED); ++ ServerGamePacketListenerImpl.LOGGER.warn("Failed to validate message acknowledgements from {}", this.player.getName().getString()); ++ this.disconnect(ServerGamePacketListenerImpl.CHAT_VALIDATION_FAILED); + } ++ + } + } + + @Override + public void handleAnimate(ServerboundSwingPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.resetLastActionTime(); ++ // CraftBukkit start - Raytrace to look for 'rogue armswings' ++ float f1 = this.player.getXRot(); ++ float f2 = this.player.getYRot(); ++ double d0 = this.player.getX(); ++ double d1 = this.player.getY() + (double) this.player.getEyeHeight(); ++ double d2 = this.player.getZ(); ++ Location origin = new Location(this.player.level().getWorld(), d0, d1, d2, f2, f1); ++ ++ double d3 = player.gameMode.getGameModeForPlayer() == GameType.CREATIVE ? 5.0D : 4.5D; ++ // SPIGOT-5607: Only call interact event if no block or entity is being clicked. Use bukkit ray trace method, because it handles blocks and entities at the same time ++ // SPIGOT-7429: Make sure to call PlayerInteractEvent for spectators and non-pickable entities ++ org.bukkit.util.RayTraceResult result = this.player.level().getWorld().rayTrace(origin, origin.getDirection(), d3, org.bukkit.FluidCollisionMode.NEVER, false, 0.1, entity -> { ++ Entity handle = ((CraftEntity) entity).getHandle(); ++ return entity != this.player.getBukkitEntity() && this.player.getBukkitEntity().canSee(entity) && !handle.isSpectator() && handle.isPickable() && !handle.isPassengerOfSameVehicle(player); ++ }); ++ if (result == null) { ++ CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_AIR, this.player.getInventory().getSelected(), EnumHand.MAIN_HAND); ++ } ++ ++ // Arm swing animation ++ PlayerAnimationEvent event = new PlayerAnimationEvent(this.getCraftPlayer(), (packet.getHand() == EnumHand.MAIN_HAND) ? PlayerAnimationType.ARM_SWING : PlayerAnimationType.OFF_ARM_SWING); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) return; ++ // CraftBukkit end + this.player.swing(packet.getHand()); + } + + @Override + public void handlePlayerCommand(ServerboundPlayerCommandPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ // CraftBukkit start ++ if (this.player.isRemoved()) return; ++ switch (packet.getAction()) { ++ case PRESS_SHIFT_KEY: ++ case RELEASE_SHIFT_KEY: ++ PlayerToggleSneakEvent event = new PlayerToggleSneakEvent(this.getCraftPlayer(), packet.getAction() == ServerboundPlayerCommandPacket.EnumPlayerAction.PRESS_SHIFT_KEY); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ break; ++ case START_SPRINTING: ++ case STOP_SPRINTING: ++ PlayerToggleSprintEvent e2 = new PlayerToggleSprintEvent(this.getCraftPlayer(), packet.getAction() == ServerboundPlayerCommandPacket.EnumPlayerAction.START_SPRINTING); ++ this.cserver.getPluginManager().callEvent(e2); ++ ++ if (e2.isCancelled()) { ++ return; ++ } ++ break; ++ } ++ // CraftBukkit end + this.player.resetLastActionTime(); ++ Entity entity; ++ PlayerRideableJumping ijumpable; ++ + switch (packet.getAction()) { + case PRESS_SHIFT_KEY: + this.player.setShiftKeyDown(true); +@@ -1367,21 +2127,29 @@ + } + break; + case START_RIDING_JUMP: +- if (this.player.getControlledVehicle() instanceof PlayerRideableJumping playerRideableJumping) { +- int data = packet.getData(); +- if (playerRideableJumping.canJump() && data > 0) { +- playerRideableJumping.handleStartJump(data); ++ entity = this.player.getControlledVehicle(); ++ if (entity instanceof PlayerRideableJumping) { ++ ijumpable = (PlayerRideableJumping) entity; ++ int i = packet.getData(); ++ ++ if (ijumpable.canJump() && i > 0) { ++ ijumpable.handleStartJump(i); + } + } + break; + case STOP_RIDING_JUMP: +- if (this.player.getControlledVehicle() instanceof PlayerRideableJumping playerRideableJumping) { +- playerRideableJumping.handleStopJump(); ++ entity = this.player.getControlledVehicle(); ++ if (entity instanceof PlayerRideableJumping) { ++ ijumpable = (PlayerRideableJumping) entity; ++ ijumpable.handleStopJump(); + } + break; + case OPEN_INVENTORY: +- if (this.player.getVehicle() instanceof HasCustomInventoryScreen hasCustomInventoryScreen) { +- hasCustomInventoryScreen.openCustomInventoryScreen(this.player); ++ entity = this.player.getVehicle(); ++ if (entity instanceof HasCustomInventoryScreen) { ++ HasCustomInventoryScreen hascustominventoryscreen = (HasCustomInventoryScreen) entity; ++ ++ hascustominventoryscreen.openCustomInventoryScreen(this.player); + } + break; + case START_FALL_FLYING: +@@ -1392,36 +2160,37 @@ + default: + throw new IllegalArgumentException("Invalid client command!"); + } ++ + } + + public void addPendingMessage(PlayerChatMessage message) { +- MessageSignature messageSignature = message.signature(); +- if (messageSignature != null) { ++ MessageSignature messagesignature = message.signature(); ++ ++ if (messagesignature != null) { + this.messageSignatureCache.push(message.signedBody(), message.signature()); ++ LastSeenMessagesValidator lastseenmessagesvalidator = this.lastSeenMessages; + int i; ++ + synchronized (this.lastSeenMessages) { +- this.lastSeenMessages.addPending(messageSignature); ++ this.lastSeenMessages.addPending(messagesignature); + i = this.lastSeenMessages.trackedMessagesCount(); + } + + if (i > 4096) { + this.disconnect(Component.translatable("multiplayer.disconnect.too_many_pending_chats")); + } ++ + } + } + + public void sendPlayerChatMessage(PlayerChatMessage chatMessage, ChatType.Bound boundType) { +- this.send( +- new ClientboundPlayerChatPacket( +- chatMessage.link().sender(), +- chatMessage.link().index(), +- chatMessage.signature(), +- chatMessage.signedBody().pack(this.messageSignatureCache), +- chatMessage.unsignedContent(), +- chatMessage.filterMask(), +- boundType.toNetwork(this.player.level().registryAccess()) +- ) +- ); ++ // CraftBukkit start - SPIGOT-7262: if hidden we have to send as disguised message. Query whether we should send at all (but changing this may not be expected). ++ if (!getCraftPlayer().canSee(chatMessage.link().sender())) { ++ sendDisguisedChatMessage(chatMessage.decoratedContent(), boundType); ++ return; ++ } ++ // CraftBukkit end ++ this.send(new ClientboundPlayerChatPacket(chatMessage.link().sender(), chatMessage.link().index(), chatMessage.signature(), chatMessage.signedBody().pack(this.messageSignatureCache), chatMessage.unsignedContent(), chatMessage.filterMask(), boundType.toNetwork(this.player.level().registryAccess()))); + this.addPendingMessage(chatMessage); + } + +@@ -1440,130 +2209,466 @@ + } + + @Override +- public void handlePingRequest(ServerboundPingRequestPacket serverboundPingRequestPacket) { +- this.connection.send(new ClientboundPongResponsePacket(serverboundPingRequestPacket.getTime())); ++ public void handlePingRequest(ServerboundPingRequestPacket packetstatusinping) { ++ this.connection.send(new ClientboundPongResponsePacket(packetstatusinping.getTime())); + } + + @Override + public void handleInteract(ServerboundInteractPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); +- final ServerLevel serverLevel = this.player.serverLevel(); +- final Entity target = packet.getTarget(serverLevel); ++ if (this.player.isImmobile()) return; // CraftBukkit ++ final ServerLevel worldserver = this.player.serverLevel(); ++ final Entity entity = packet.getTarget(worldserver); ++ + this.player.resetLastActionTime(); + this.player.setShiftKeyDown(packet.isUsingSecondaryAction()); +- if (target != null) { +- if (!serverLevel.getWorldBorder().isWithinBounds(target.blockPosition())) { ++ if (entity != null) { ++ if (!worldserver.getWorldBorder().isWithinBounds(entity.blockPosition())) { + return; + } + +- AABB boundingBox = target.getBoundingBox(); +- if (boundingBox.distanceToSqr(this.player.getEyePosition()) < MAX_INTERACTION_DISTANCE) { +- packet.dispatch( +- new ServerboundInteractPacket.Handler() { +- private void performInteraction(InteractionHand hand, ServerGamePacketListenerImpl.EntityInteraction entityInteraction) { +- ItemStack itemInHand = ServerGamePacketListenerImpl.this.player.getItemInHand(hand); +- if (itemInHand.isItemEnabled(serverLevel.enabledFeatures())) { +- ItemStack itemStack = itemInHand.copy(); +- InteractionResult interactionResult = entityInteraction.run(ServerGamePacketListenerImpl.this.player, target, hand); +- if (interactionResult.consumesAction()) { +- CriteriaTriggers.PLAYER_INTERACTED_WITH_ENTITY.trigger(ServerGamePacketListenerImpl.this.player, itemStack, target); +- if (interactionResult.shouldSwing()) { +- ServerGamePacketListenerImpl.this.player.swing(hand, true); +- } ++ AABB axisalignedbb = entity.getBoundingBox(); ++ ++ if (axisalignedbb.distanceToSqr(this.player.getEyePosition()) < ServerGamePacketListenerImpl.MAX_INTERACTION_DISTANCE) { ++ packet.dispatch(new ServerboundInteractPacket.Handler() { ++ private void performInteraction(EnumHand enumhand, ServerGamePacketListenerImpl.EntityInteraction playerconnection_a, PlayerInteractEntityEvent event) { // CraftBukkit ++ ItemStack itemstack = ServerGamePacketListenerImpl.this.player.getItemInHand(enumhand); ++ ++ if (itemstack.isItemEnabled(worldserver.enabledFeatures())) { ++ ItemStack itemstack1 = itemstack.copy(); ++ // CraftBukkit start ++ ItemStack itemInHand = ServerGamePacketListenerImpl.this.player.getItemInHand(enumhand); ++ boolean triggerLeashUpdate = itemInHand != null && itemInHand.getItem() == Items.LEAD && entity instanceof Mob; ++ Item origItem = player.getInventory().getSelected() == null ? null : player.getInventory().getSelected().getItem(); ++ ++ cserver.getPluginManager().callEvent(event); ++ ++ // Entity in bucket - SPIGOT-4048 and SPIGOT-6859a ++ if ((entity instanceof Bucketable && entity instanceof LivingEntity && origItem != null && origItem.asItem() == Items.WATER_BUCKET) && (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem)) { ++ send(new ClientboundAddEntityPacket(entity)); ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ ++ if (triggerLeashUpdate && (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem)) { ++ // Refresh the current leash state ++ send(new ClientboundSetEntityLinkPacket(entity, ((Mob) entity).getLeashHolder())); ++ } ++ ++ if (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem) { ++ // Refresh the current entity metadata ++ entity.getEntityData().refresh(player); ++ // SPIGOT-7136 - Allays ++ if (entity instanceof Allay) { ++ send(new ClientboundSetEquipmentPacket(entity.getId(), Arrays.stream(net.minecraft.world.entity.EquipmentSlot.values()).map((slot) -> Pair.of(slot, ((LivingEntity) entity).getItemBySlot(slot).copy())).collect(Collectors.toList()))); ++ player.containerMenu.sendAllDataToRemote(); + } + } ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ InteractionResult enuminteractionresult = playerconnection_a.run(ServerGamePacketListenerImpl.this.player, entity, enumhand); ++ ++ // CraftBukkit start ++ if (!itemInHand.isEmpty() && itemInHand.getCount() <= -1) { ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ // CraftBukkit end ++ ++ if (enuminteractionresult.consumesAction()) { ++ CriteriaTriggers.PLAYER_INTERACTED_WITH_ENTITY.trigger(ServerGamePacketListenerImpl.this.player, itemstack1, entity); ++ if (enuminteractionresult.shouldSwing()) { ++ ServerGamePacketListenerImpl.this.player.swing(enumhand, true); ++ } ++ } ++ + } +- +- @Override +- public void onInteraction(InteractionHand hand) { +- this.performInteraction(hand, Player::interactOn); +- } +- +- @Override +- public void onInteraction(InteractionHand hand, Vec3 interactionLocation) { +- this.performInteraction(hand, (player, entity, hand1) -> entity.interactAt(player, interactionLocation, hand1)); +- } +- +- @Override +- public void onAttack() { +- if (!(target instanceof ItemEntity) +- && !(target instanceof ExperienceOrb) +- && !(target instanceof AbstractArrow) +- && target != ServerGamePacketListenerImpl.this.player) { +- ItemStack itemInHand = ServerGamePacketListenerImpl.this.player.getItemInHand(InteractionHand.MAIN_HAND); +- if (itemInHand.isItemEnabled(serverLevel.enabledFeatures())) { +- ServerGamePacketListenerImpl.this.player.attack(target); ++ } ++ ++ @Override ++ public void onInteraction(EnumHand hand) { ++ this.performInteraction(hand, net.minecraft.world.entity.player.Player::interactOn, new PlayerInteractEntityEvent(getCraftPlayer(), entity.getBukkitEntity(), (hand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); // CraftBukkit ++ } ++ ++ @Override ++ public void onInteraction(EnumHand hand, Vec3 interactionLocation) { ++ this.performInteraction(hand, (entityplayer, entity1, enumhand1) -> { ++ return entity1.interactAt(entityplayer, interactionLocation, enumhand1); ++ }, new PlayerInteractAtEntityEvent(getCraftPlayer(), entity.getBukkitEntity(), new org.bukkit.util.Vector(interactionLocation.x, interactionLocation.y, interactionLocation.z), (hand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); // CraftBukkit ++ } ++ ++ @Override ++ public void onAttack() { ++ // CraftBukkit ++ if (!(entity instanceof ItemEntity) && !(entity instanceof ExperienceOrb) && !(entity instanceof AbstractArrow) && (entity != ServerGamePacketListenerImpl.this.player || player.isSpectator())) { ++ ItemStack itemstack = ServerGamePacketListenerImpl.this.player.getItemInHand(EnumHand.MAIN_HAND); ++ ++ if (itemstack.isItemEnabled(worldserver.enabledFeatures())) { ++ ServerGamePacketListenerImpl.this.player.attack(entity); ++ // CraftBukkit start ++ if (!itemstack.isEmpty() && itemstack.getCount() <= -1) { ++ player.containerMenu.sendAllDataToRemote(); + } +- } else { +- ServerGamePacketListenerImpl.this.disconnect(Component.translatable("multiplayer.disconnect.invalid_entity_attacked")); +- ServerGamePacketListenerImpl.LOGGER +- .warn("Player {} tried to attack an invalid entity", ServerGamePacketListenerImpl.this.player.getName().getString()); ++ // CraftBukkit end + } ++ } else { ++ ServerGamePacketListenerImpl.this.disconnect(Component.translatable("multiplayer.disconnect.invalid_entity_attacked")); ++ ServerGamePacketListenerImpl.LOGGER.warn("Player {} tried to attack an invalid entity", ServerGamePacketListenerImpl.this.player.getName().getString()); + } + } +- ); ++ }); + } + } ++ + } + + @Override + public void handleClientCommand(ServerboundClientCommandPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + this.player.resetLastActionTime(); +- ServerboundClientCommandPacket.Action action = packet.getAction(); +- switch (action) { ++ ServerboundClientCommandPacket.EnumClientCommand packetplayinclientcommand_enumclientcommand = packet.getAction(); ++ ++ switch (packetplayinclientcommand_enumclientcommand) { + case PERFORM_RESPAWN: + if (this.player.wonGame) { + this.player.wonGame = false; +- this.player = this.server.getPlayerList().respawn(this.player, true); ++ this.player = this.server.getPlayerList().respawn(this.player, true, RespawnReason.END_PORTAL); + CriteriaTriggers.CHANGED_DIMENSION.trigger(this.player, Level.END, Level.OVERWORLD); + } else { + if (this.player.getHealth() > 0.0F) { + return; + } + +- this.player = this.server.getPlayerList().respawn(this.player, false); ++ this.player = this.server.getPlayerList().respawn(this.player, false, RespawnReason.DEATH); + if (this.server.isHardcore()) { + this.player.setGameMode(GameType.SPECTATOR); +- this.player.level().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS).set(false, this.server); ++ ((GameRules.BooleanValue) this.player.level().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS)).set(false, this.server); + } + } + break; + case REQUEST_STATS: + this.player.getStats().sendStats(this.player); + } ++ + } + + @Override + public void handleContainerClose(ServerboundContainerClosePacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ ++ if (this.player.isImmobile()) return; // CraftBukkit ++ CraftEventFactory.handleInventoryCloseEvent(this.player); // CraftBukkit ++ + this.player.doCloseContainer(); + } + + @Override + public void handleContainerClick(ServerboundContainerClickPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.resetLastActionTime(); +- if (this.player.containerMenu.containerId == packet.getContainerId()) { +- if (this.player.isSpectator()) { ++ if (this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu.stillValid(this.player)) { // CraftBukkit ++ boolean cancelled = this.player.isSpectator(); // CraftBukkit - see below if ++ if (false/*this.player.isSpectator()*/) { // CraftBukkit + this.player.containerMenu.sendAllDataToRemote(); + } else if (!this.player.containerMenu.stillValid(this.player)) { +- LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu); ++ ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu); + } else { +- int slotNum = packet.getSlotNum(); +- if (!this.player.containerMenu.isValidSlotIndex(slotNum)) { +- LOGGER.debug( +- "Player {} clicked invalid slot index: {}, available slots: {}", this.player.getName(), slotNum, this.player.containerMenu.slots.size() +- ); ++ int i = packet.getSlotNum(); ++ ++ if (!this.player.containerMenu.isValidSlotIndex(i)) { ++ ServerGamePacketListenerImpl.LOGGER.debug("Player {} clicked invalid slot index: {}, available slots: {}", new Object[]{this.player.getName(), i, this.player.containerMenu.slots.size()}); + } else { + boolean flag = packet.getStateId() != this.player.containerMenu.getStateId(); ++ + this.player.containerMenu.suppressRemoteUpdates(); +- this.player.containerMenu.clicked(slotNum, packet.getButtonNum(), packet.getClickType(), this.player); ++ // CraftBukkit start - Call InventoryClickEvent ++ if (packet.getSlotNum() < -1 && packet.getSlotNum() != -999) { ++ return; ++ } + +- for (Entry entry : Int2ObjectMaps.fastIterable(packet.getChangedSlots())) { +- this.player.containerMenu.setRemoteSlotNoCopy(entry.getIntKey(), entry.getValue()); ++ InventoryView inventory = this.player.containerMenu.getBukkitView(); ++ SlotType type = inventory.getSlotType(packet.getSlotNum()); ++ ++ InventoryClickEvent event; ++ ClickType click = ClickType.UNKNOWN; ++ InventoryAction action = InventoryAction.UNKNOWN; ++ ++ ItemStack itemstack = ItemStack.EMPTY; ++ ++ switch (packet.getClickType()) { ++ case PICKUP: ++ if (packet.getButtonNum() == 0) { ++ click = ClickType.LEFT; ++ } else if (packet.getButtonNum() == 1) { ++ click = ClickType.RIGHT; ++ } ++ if (packet.getButtonNum() == 0 || packet.getButtonNum() == 1) { ++ action = InventoryAction.NOTHING; // Don't want to repeat ourselves ++ if (packet.getSlotNum() == -999) { ++ if (!player.containerMenu.getCarried().isEmpty()) { ++ action = packet.getButtonNum() == 0 ? InventoryAction.DROP_ALL_CURSOR : InventoryAction.DROP_ONE_CURSOR; ++ } ++ } else if (packet.getSlotNum() < 0) { ++ action = InventoryAction.NOTHING; ++ } else { ++ Slot slot = this.player.containerMenu.getSlot(packet.getSlotNum()); ++ if (slot != null) { ++ ItemStack clickedItem = slot.getItem(); ++ ItemStack cursor = player.containerMenu.getCarried(); ++ if (clickedItem.isEmpty()) { ++ if (!cursor.isEmpty()) { ++ action = packet.getButtonNum() == 0 ? InventoryAction.PLACE_ALL : InventoryAction.PLACE_ONE; ++ } ++ } else if (slot.mayPickup(player)) { ++ if (cursor.isEmpty()) { ++ action = packet.getButtonNum() == 0 ? InventoryAction.PICKUP_ALL : InventoryAction.PICKUP_HALF; ++ } else if (slot.mayPlace(cursor)) { ++ if (ItemStack.isSameItemSameTags(clickedItem, cursor)) { ++ int toPlace = packet.getButtonNum() == 0 ? cursor.getCount() : 1; ++ toPlace = Math.min(toPlace, clickedItem.getMaxStackSize() - clickedItem.getCount()); ++ toPlace = Math.min(toPlace, slot.container.getMaxStackSize() - clickedItem.getCount()); ++ if (toPlace == 1) { ++ action = InventoryAction.PLACE_ONE; ++ } else if (toPlace == cursor.getCount()) { ++ action = InventoryAction.PLACE_ALL; ++ } else if (toPlace < 0) { ++ action = toPlace != -1 ? InventoryAction.PICKUP_SOME : InventoryAction.PICKUP_ONE; // this happens with oversized stacks ++ } else if (toPlace != 0) { ++ action = InventoryAction.PLACE_SOME; ++ } ++ } else if (cursor.getCount() <= slot.getMaxStackSize()) { ++ action = InventoryAction.SWAP_WITH_CURSOR; ++ } ++ } else if (ItemStack.isSameItemSameTags(cursor, clickedItem)) { ++ if (clickedItem.getCount() >= 0) { ++ if (clickedItem.getCount() + cursor.getCount() <= cursor.getMaxStackSize()) { ++ // As of 1.5, this is result slots only ++ action = InventoryAction.PICKUP_ALL; ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ break; ++ // TODO check on updates ++ case QUICK_MOVE: ++ if (packet.getButtonNum() == 0) { ++ click = ClickType.SHIFT_LEFT; ++ } else if (packet.getButtonNum() == 1) { ++ click = ClickType.SHIFT_RIGHT; ++ } ++ if (packet.getButtonNum() == 0 || packet.getButtonNum() == 1) { ++ if (packet.getSlotNum() < 0) { ++ action = InventoryAction.NOTHING; ++ } else { ++ Slot slot = this.player.containerMenu.getSlot(packet.getSlotNum()); ++ if (slot != null && slot.mayPickup(this.player) && slot.hasItem()) { ++ action = InventoryAction.MOVE_TO_OTHER_INVENTORY; ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } ++ } ++ break; ++ case SWAP: ++ if ((packet.getButtonNum() >= 0 && packet.getButtonNum() < 9) || packet.getButtonNum() == 40) { ++ click = (packet.getButtonNum() == 40) ? ClickType.SWAP_OFFHAND : ClickType.NUMBER_KEY; ++ Slot clickedSlot = this.player.containerMenu.getSlot(packet.getSlotNum()); ++ if (clickedSlot.mayPickup(player)) { ++ ItemStack hotbar = this.player.getInventory().getItem(packet.getButtonNum()); ++ boolean canCleanSwap = hotbar.isEmpty() || (clickedSlot.container == player.getInventory() && clickedSlot.mayPlace(hotbar)); // the slot will accept the hotbar item ++ if (clickedSlot.hasItem()) { ++ if (canCleanSwap) { ++ action = InventoryAction.HOTBAR_SWAP; ++ } else { ++ action = InventoryAction.HOTBAR_MOVE_AND_READD; ++ } ++ } else if (!clickedSlot.hasItem() && !hotbar.isEmpty() && clickedSlot.mayPlace(hotbar)) { ++ action = InventoryAction.HOTBAR_SWAP; ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } ++ break; ++ case CLONE: ++ if (packet.getButtonNum() == 2) { ++ click = ClickType.MIDDLE; ++ if (packet.getSlotNum() < 0) { ++ action = InventoryAction.NOTHING; ++ } else { ++ Slot slot = this.player.containerMenu.getSlot(packet.getSlotNum()); ++ if (slot != null && slot.hasItem() && player.getAbilities().instabuild && player.containerMenu.getCarried().isEmpty()) { ++ action = InventoryAction.CLONE_STACK; ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } ++ } else { ++ click = ClickType.UNKNOWN; ++ action = InventoryAction.UNKNOWN; ++ } ++ break; ++ case THROW: ++ if (packet.getSlotNum() >= 0) { ++ if (packet.getButtonNum() == 0) { ++ click = ClickType.DROP; ++ Slot slot = this.player.containerMenu.getSlot(packet.getSlotNum()); ++ if (slot != null && slot.hasItem() && slot.mayPickup(player) && !slot.getItem().isEmpty() && slot.getItem().getItem() != Item.byBlock(Blocks.AIR)) { ++ action = InventoryAction.DROP_ONE_SLOT; ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } else if (packet.getButtonNum() == 1) { ++ click = ClickType.CONTROL_DROP; ++ Slot slot = this.player.containerMenu.getSlot(packet.getSlotNum()); ++ if (slot != null && slot.hasItem() && slot.mayPickup(player) && !slot.getItem().isEmpty() && slot.getItem().getItem() != Item.byBlock(Blocks.AIR)) { ++ action = InventoryAction.DROP_ALL_SLOT; ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } ++ } else { ++ // Sane default (because this happens when they are holding nothing. Don't ask why.) ++ click = ClickType.LEFT; ++ if (packet.getButtonNum() == 1) { ++ click = ClickType.RIGHT; ++ } ++ action = InventoryAction.NOTHING; ++ } ++ break; ++ case QUICK_CRAFT: ++ this.player.containerMenu.clicked(packet.getSlotNum(), packet.getButtonNum(), packet.getClickType(), this.player); ++ break; ++ case PICKUP_ALL: ++ click = ClickType.DOUBLE_CLICK; ++ action = InventoryAction.NOTHING; ++ if (packet.getSlotNum() >= 0 && !this.player.containerMenu.getCarried().isEmpty()) { ++ ItemStack cursor = this.player.containerMenu.getCarried(); ++ action = InventoryAction.NOTHING; ++ // Quick check for if we have any of the item ++ if (inventory.getTopInventory().contains(CraftMagicNumbers.getMaterial(cursor.getItem())) || inventory.getBottomInventory().contains(CraftMagicNumbers.getMaterial(cursor.getItem()))) { ++ action = InventoryAction.COLLECT_TO_CURSOR; ++ } ++ } ++ break; ++ default: ++ break; + } + ++ if (packet.getClickType() != InventoryClickType.QUICK_CRAFT) { ++ if (click == ClickType.NUMBER_KEY) { ++ event = new InventoryClickEvent(inventory, type, packet.getSlotNum(), click, action, packet.getButtonNum()); ++ } else { ++ event = new InventoryClickEvent(inventory, type, packet.getSlotNum(), click, action); ++ } ++ ++ org.bukkit.inventory.Inventory top = inventory.getTopInventory(); ++ if (packet.getSlotNum() == 0 && top instanceof CraftingInventory) { ++ org.bukkit.inventory.Recipe recipe = ((CraftingInventory) top).getRecipe(); ++ if (recipe != null) { ++ if (click == ClickType.NUMBER_KEY) { ++ event = new CraftItemEvent(recipe, inventory, type, packet.getSlotNum(), click, action, packet.getButtonNum()); ++ } else { ++ event = new CraftItemEvent(recipe, inventory, type, packet.getSlotNum(), click, action); ++ } ++ } ++ } ++ ++ if (packet.getSlotNum() == 3 && top instanceof SmithingInventory) { ++ org.bukkit.inventory.ItemStack result = ((SmithingInventory) top).getResult(); ++ if (result != null) { ++ if (click == ClickType.NUMBER_KEY) { ++ event = new SmithItemEvent(inventory, type, packet.getSlotNum(), click, action, packet.getButtonNum()); ++ } else { ++ event = new SmithItemEvent(inventory, type, packet.getSlotNum(), click, action); ++ } ++ } ++ } ++ ++ event.setCancelled(cancelled); ++ AbstractContainerMenu oldContainer = this.player.containerMenu; // SPIGOT-1224 ++ cserver.getPluginManager().callEvent(event); ++ if (this.player.containerMenu != oldContainer) { ++ return; ++ } ++ ++ switch (event.getResult()) { ++ case ALLOW: ++ case DEFAULT: ++ this.player.containerMenu.clicked(i, packet.getButtonNum(), packet.getClickType(), this.player); ++ break; ++ case DENY: ++ /* Needs enum constructor in InventoryAction ++ if (action.modifiesOtherSlots()) { ++ ++ } else { ++ if (action.modifiesCursor()) { ++ this.player.playerConnection.sendPacket(new Packet103SetSlot(-1, -1, this.player.inventory.getCarried())); ++ } ++ if (action.modifiesClicked()) { ++ this.player.playerConnection.sendPacket(new Packet103SetSlot(this.player.activeContainer.windowId, packet102windowclick.slot, this.player.activeContainer.getSlot(packet102windowclick.slot).getItem())); ++ } ++ }*/ ++ switch (action) { ++ // Modified other slots ++ case PICKUP_ALL: ++ case MOVE_TO_OTHER_INVENTORY: ++ case HOTBAR_MOVE_AND_READD: ++ case HOTBAR_SWAP: ++ case COLLECT_TO_CURSOR: ++ case UNKNOWN: ++ this.player.containerMenu.sendAllDataToRemote(); ++ break; ++ // Modified cursor and clicked ++ case PICKUP_SOME: ++ case PICKUP_HALF: ++ case PICKUP_ONE: ++ case PLACE_ALL: ++ case PLACE_SOME: ++ case PLACE_ONE: ++ case SWAP_WITH_CURSOR: ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(-1, -1, this.player.inventoryMenu.incrementStateId(), this.player.containerMenu.getCarried())); ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(this.player.containerMenu.containerId, this.player.inventoryMenu.incrementStateId(), packet.getSlotNum(), this.player.containerMenu.getSlot(packet.getSlotNum()).getItem())); ++ break; ++ // Modified clicked only ++ case DROP_ALL_SLOT: ++ case DROP_ONE_SLOT: ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(this.player.containerMenu.containerId, this.player.inventoryMenu.incrementStateId(), packet.getSlotNum(), this.player.containerMenu.getSlot(packet.getSlotNum()).getItem())); ++ break; ++ // Modified cursor only ++ case DROP_ALL_CURSOR: ++ case DROP_ONE_CURSOR: ++ case CLONE_STACK: ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(-1, -1, this.player.inventoryMenu.incrementStateId(), this.player.containerMenu.getCarried())); ++ break; ++ // Nothing ++ case NOTHING: ++ break; ++ } ++ } ++ ++ if (event instanceof CraftItemEvent || event instanceof SmithItemEvent) { ++ // Need to update the inventory on crafting to ++ // correctly support custom recipes ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ } ++ // CraftBukkit end ++ ObjectIterator objectiterator = Int2ObjectMaps.fastIterable(packet.getChangedSlots()).iterator(); ++ ++ while (objectiterator.hasNext()) { ++ Entry entry = (Entry) objectiterator.next(); ++ ++ this.player.containerMenu.setRemoteSlotNoCopy(entry.getIntKey(), (ItemStack) entry.getValue()); ++ } ++ + this.player.containerMenu.setRemoteCarried(packet.getCarriedItem()); + this.player.containerMenu.resumeRemoteUpdates(); + if (flag) { +@@ -1571,6 +2676,7 @@ + } else { + this.player.containerMenu.broadcastChanges(); + } ++ + } + } + } +@@ -1580,19 +2686,22 @@ + public void handlePlaceRecipe(ServerboundPlaceRecipePacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + this.player.resetLastActionTime(); +- if (!this.player.isSpectator() +- && this.player.containerMenu.containerId == packet.getContainerId() +- && this.player.containerMenu instanceof RecipeBookMenu) { ++ if (!this.player.isSpectator() && this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu instanceof RecipeBookMenu) { + if (!this.player.containerMenu.stillValid(this.player)) { +- LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu); ++ ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu); + } else { +- this.server +- .getRecipeManager() +- .byKey(packet.getRecipe()) +- .ifPresent( +- recipeHolder -> ((RecipeBookMenu)this.player.containerMenu) +- .handlePlacement(packet.isShiftDown(), (RecipeHolder)recipeHolder, this.player) +- ); ++ // CraftBukkit start - implement PlayerRecipeBookClickEvent ++ org.bukkit.inventory.Recipe recipe = this.cserver.getRecipe(CraftNamespacedKey.fromMinecraft(packet.getRecipe())); ++ if (recipe == null) { ++ return; ++ } ++ org.bukkit.event.player.PlayerRecipeBookClickEvent event = CraftEventFactory.callRecipeBookClickEvent(this.player, recipe, packet.isShiftDown()); ++ ++ // Cast to keyed should be safe as the recipe will never be a MerchantRecipe. ++ this.server.getRecipeManager().byKey(CraftNamespacedKey.toMinecraft(((org.bukkit.Keyed) event.getRecipe()).getKey())).ifPresent((recipeholder) -> { ++ ((RecipeBookMenu) this.player.containerMenu).handlePlacement(event.isShiftClick(), recipeholder, this.player); ++ }); ++ // CraftBukkit end + } + } + } +@@ -1600,15 +2709,18 @@ + @Override + public void handleContainerButtonClick(ServerboundContainerButtonClickPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.resetLastActionTime(); + if (this.player.containerMenu.containerId == packet.getContainerId() && !this.player.isSpectator()) { + if (!this.player.containerMenu.stillValid(this.player)) { +- LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu); ++ ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu); + } else { + boolean flag = this.player.containerMenu.clickMenuButton(this.player, packet.getButtonId()); ++ + if (flag) { + this.player.containerMenu.broadcastChanges(); + } ++ + } + } + } +@@ -1618,63 +2730,126 @@ + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); + if (this.player.gameMode.isCreative()) { + boolean flag = packet.getSlotNum() < 0; +- ItemStack item = packet.getItem(); +- if (!item.isItemEnabled(this.player.level().enabledFeatures())) { ++ ItemStack itemstack = packet.getItem(); ++ ++ if (!itemstack.isItemEnabled(this.player.level().enabledFeatures())) { + return; + } + +- CompoundTag blockEntityData = BlockItem.getBlockEntityData(item); +- if (!item.isEmpty() && blockEntityData != null && blockEntityData.contains("x") && blockEntityData.contains("y") && blockEntityData.contains("z")) { +- BlockPos posFromTag = BlockEntity.getPosFromTag(blockEntityData); +- if (this.player.level().isLoaded(posFromTag)) { +- BlockEntity blockEntity = this.player.level().getBlockEntity(posFromTag); +- if (blockEntity != null) { +- blockEntity.saveToItem(item); ++ CompoundTag nbttagcompound = BlockItem.getBlockEntityData(itemstack); ++ ++ if (!itemstack.isEmpty() && nbttagcompound != null && nbttagcompound.contains("x") && nbttagcompound.contains("y") && nbttagcompound.contains("z")) { ++ BlockPos blockposition = BlockEntity.getPosFromTag(nbttagcompound); ++ ++ if (this.player.level().isLoaded(blockposition)) { ++ BlockEntity tileentity = this.player.level().getBlockEntity(blockposition); ++ ++ if (tileentity != null) { ++ tileentity.saveToItem(itemstack); + } + } + } + + boolean flag1 = packet.getSlotNum() >= 1 && packet.getSlotNum() <= 45; +- boolean flag2 = item.isEmpty() || item.getDamageValue() >= 0 && item.getCount() <= 64 && !item.isEmpty(); ++ boolean flag2 = itemstack.isEmpty() || itemstack.getDamageValue() >= 0 && itemstack.getCount() <= 64 && !itemstack.isEmpty(); ++ if (flag || (flag1 && !ItemStack.matches(this.player.inventoryMenu.getSlot(packet.getSlotNum()).getItem(), packet.getItem()))) { // Insist on valid slot ++ // CraftBukkit start - Call click event ++ InventoryView inventory = this.player.inventoryMenu.getBukkitView(); ++ org.bukkit.inventory.ItemStack item = CraftItemStack.asBukkitCopy(packet.getItem()); ++ ++ SlotType type = SlotType.QUICKBAR; ++ if (flag) { ++ type = SlotType.OUTSIDE; ++ } else if (packet.getSlotNum() < 36) { ++ if (packet.getSlotNum() >= 5 && packet.getSlotNum() < 9) { ++ type = SlotType.ARMOR; ++ } else { ++ type = SlotType.CONTAINER; ++ } ++ } ++ InventoryCreativeEvent event = new InventoryCreativeEvent(inventory, type, flag ? -999 : packet.getSlotNum(), item); ++ cserver.getPluginManager().callEvent(event); ++ ++ itemstack = CraftItemStack.asNMSCopy(event.getCursor()); ++ ++ switch (event.getResult()) { ++ case ALLOW: ++ // Plugin cleared the id / stacksize checks ++ flag2 = true; ++ break; ++ case DEFAULT: ++ break; ++ case DENY: ++ // Reset the slot ++ if (packet.getSlotNum() >= 0) { ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(this.player.inventoryMenu.containerId, this.player.inventoryMenu.incrementStateId(), packet.getSlotNum(), this.player.inventoryMenu.getSlot(packet.getSlotNum()).getItem())); ++ this.player.connection.send(new ClientboundContainerSetSlotPacket(-1, this.player.inventoryMenu.incrementStateId(), -1, ItemStack.EMPTY)); ++ } ++ return; ++ } ++ } ++ // CraftBukkit end ++ + if (flag1 && flag2) { +- this.player.inventoryMenu.getSlot(packet.getSlotNum()).setByPlayer(item); ++ this.player.inventoryMenu.getSlot(packet.getSlotNum()).setByPlayer(itemstack); + this.player.inventoryMenu.broadcastChanges(); + } else if (flag && flag2 && this.dropSpamTickCount < 200) { + this.dropSpamTickCount += 20; +- this.player.drop(item, true); ++ this.player.drop(itemstack, true); + } + } ++ + } + + @Override + public void handleSignUpdate(ServerboundSignUpdatePacket packet) { +- List list = Stream.of(packet.getLines()).map(ChatFormatting::stripFormatting).collect(Collectors.toList()); +- this.filterTextPacket(list).thenAcceptAsync(list1 -> this.updateSignText(packet, (List)list1), this.server); ++ List list = (List) Stream.of(packet.getLines()).map(ChatFormatting::stripFormatting).collect(Collectors.toList()); ++ ++ this.filterTextPacket(list).thenAcceptAsync((list1) -> { ++ this.updateSignText(packet, list1); ++ }, this.server); + } + + private void updateSignText(ServerboundSignUpdatePacket packet, List filteredText) { ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.resetLastActionTime(); +- ServerLevel serverLevel = this.player.serverLevel(); +- BlockPos pos = packet.getPos(); +- if (serverLevel.hasChunkAt(pos)) { +- if (!(serverLevel.getBlockEntity(pos) instanceof SignBlockEntity signBlockEntity)) { ++ ServerLevel worldserver = this.player.serverLevel(); ++ BlockPos blockposition = packet.getPos(); ++ ++ if (worldserver.hasChunkAt(blockposition)) { ++ BlockEntity tileentity = worldserver.getBlockEntity(blockposition); ++ ++ if (!(tileentity instanceof SignBlockEntity)) { + return; + } + +- signBlockEntity.updateSignText(this.player, packet.isFrontText(), filteredText); ++ SignBlockEntity tileentitysign = (SignBlockEntity) tileentity; ++ ++ tileentitysign.updateSignText(this.player, packet.isFrontText(), filteredText); + } ++ + } + + @Override + public void handlePlayerAbilities(ServerboundPlayerAbilitiesPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); +- this.player.getAbilities().flying = packet.isFlying() && this.player.getAbilities().mayfly; ++ // CraftBukkit start ++ if (this.player.getAbilities().mayfly && this.player.getAbilities().flying != packet.isFlying()) { ++ PlayerToggleFlightEvent event = new PlayerToggleFlightEvent(this.player.getBukkitEntity(), packet.isFlying()); ++ this.cserver.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ this.player.getAbilities().flying = packet.isFlying(); // Actually set the player's flying status ++ } else { ++ this.player.onUpdateAbilities(); // Tell the player their ability was reverted ++ } ++ } ++ // CraftBukkit end + } + + @Override +- public void handleClientInformation(ServerboundClientInformationPacket serverboundClientInformationPacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundClientInformationPacket, this, this.player.serverLevel()); +- this.player.updateOptions(serverboundClientInformationPacket.information()); ++ public void handleClientInformation(ServerboundClientInformationPacket serverboundclientinformationpacket) { ++ PacketUtils.ensureRunningOnSameThread(serverboundclientinformationpacket, this, this.player.serverLevel()); ++ this.player.updateOptions(serverboundclientinformationpacket.information()); + } + + @Override +@@ -1696,59 +2871,54 @@ + @Override + public void handleChatSessionUpdate(ServerboundChatSessionUpdatePacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); +- RemoteChatSession.Data data = packet.chatSession(); +- ProfilePublicKey.Data data1 = this.chatSession != null ? this.chatSession.profilePublicKey().data() : null; +- ProfilePublicKey.Data data2 = data.profilePublicKey(); +- if (!Objects.equals(data1, data2)) { +- if (data1 != null && data2.expiresAt().isBefore(data1.expiresAt())) { ++ RemoteChatSession.Data remotechatsession_a = packet.chatSession(); ++ ProfilePublicKey.Data profilepublickey_a = this.chatSession != null ? this.chatSession.profilePublicKey().data() : null; ++ ProfilePublicKey.Data profilepublickey_a1 = remotechatsession_a.profilePublicKey(); ++ ++ if (!Objects.equals(profilepublickey_a, profilepublickey_a1)) { ++ if (profilepublickey_a != null && profilepublickey_a1.expiresAt().isBefore(profilepublickey_a.expiresAt())) { + this.disconnect(ProfilePublicKey.EXPIRED_PROFILE_PUBLIC_KEY); + } else { + try { +- SignatureValidator profileKeySignatureValidator = this.server.getProfileKeySignatureValidator(); +- if (profileKeySignatureValidator == null) { +- LOGGER.warn("Ignoring chat session from {} due to missing Services public key", this.player.getGameProfile().getName()); ++ SignatureValidator signaturevalidator = this.server.getProfileKeySignatureValidator(); ++ ++ if (signaturevalidator == null) { ++ ServerGamePacketListenerImpl.LOGGER.warn("Ignoring chat session from {} due to missing Services public key", this.player.getGameProfile().getName()); + return; + } + +- this.resetPlayerChatState(data.validate(this.player.getGameProfile(), profileKeySignatureValidator)); +- } catch (ProfilePublicKey.ValidationException var6) { +- LOGGER.error("Failed to validate profile key: {}", var6.getMessage()); +- this.disconnect(var6.getComponent()); ++ this.resetPlayerChatState(remotechatsession_a.validate(this.player.getGameProfile(), signaturevalidator)); ++ } catch (ProfilePublicKey.b profilepublickey_b) { ++ ServerGamePacketListenerImpl.LOGGER.error("Failed to validate profile key: {}", profilepublickey_b.getMessage()); ++ this.disconnect(profilepublickey_b.getComponent()); + } ++ + } + } + } + + @Override +- public void handleConfigurationAcknowledged(ServerboundConfigurationAcknowledgedPacket serverboundConfigurationAcknowledgedPacket) { ++ public void handleConfigurationAcknowledged(ServerboundConfigurationAcknowledgedPacket serverboundconfigurationacknowledgedpacket) { + if (!this.waitingForSwitchToConfig) { + throw new IllegalStateException("Client acknowledged config, but none was requested"); + } else { +- this.connection +- .setListener(new ServerConfigurationPacketListenerImpl(this.server, this.connection, this.createCookie(this.player.clientInformation()))); ++ this.connection.setListener(new ServerConfigurationPacketListenerImpl(this.server, this.connection, this.createCookie(this.player.clientInformation()), this.player)); // CraftBukkit + } + } + + @Override +- public void handleChunkBatchReceived(ServerboundChunkBatchReceivedPacket serverboundChunkBatchReceivedPacket) { +- PacketUtils.ensureRunningOnSameThread(serverboundChunkBatchReceivedPacket, this, this.player.serverLevel()); +- this.chunkSender.onChunkBatchReceivedByClient(serverboundChunkBatchReceivedPacket.desiredChunksPerTick()); ++ public void handleChunkBatchReceived(ServerboundChunkBatchReceivedPacket serverboundchunkbatchreceivedpacket) { ++ PacketUtils.ensureRunningOnSameThread(serverboundchunkbatchreceivedpacket, this, this.player.serverLevel()); ++ this.chunkSender.onChunkBatchReceivedByClient(serverboundchunkbatchreceivedpacket.desiredChunksPerTick()); + } + + private void resetPlayerChatState(RemoteChatSession chatSession) { + this.chatSession = chatSession; + this.signedMessageDecoder = chatSession.createMessageDecoder(this.player.getUUID()); +- this.chatMessageChain +- .append( +- () -> { +- this.player.setChatSession(chatSession); +- this.server +- .getPlayerList() +- .broadcastAll( +- new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.INITIALIZE_CHAT), List.of(this.player)) +- ); +- } +- ); ++ this.chatMessageChain.append(() -> { ++ this.player.setChatSession(chatSession); ++ this.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.INITIALIZE_CHAT), List.of(this.player))); ++ }); + } + + @Override +@@ -1757,7 +2927,8 @@ + } + + @FunctionalInterface +- interface EntityInteraction { +- InteractionResult run(ServerPlayer player, Entity entity, InteractionHand hand); ++ private interface EntityInteraction { ++ ++ InteractionResult run(ServerPlayer player, Entity entity, EnumHand hand); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java.patch new file mode 100644 index 0000000000..c16756bc46 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java.patch @@ -0,0 +1,117 @@ +--- a/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +@@ -3,6 +3,7 @@ + import net.minecraft.SharedConstants; + import net.minecraft.network.Connection; + import net.minecraft.network.chat.Component; ++import net.minecraft.network.chat.MutableComponent; + import net.minecraft.network.protocol.handshake.ClientIntent; + import net.minecraft.network.protocol.handshake.ClientIntentionPacket; + import net.minecraft.network.protocol.handshake.ServerHandshakePacketListener; +@@ -10,7 +11,17 @@ + import net.minecraft.network.protocol.status.ServerStatus; + import net.minecraft.server.MinecraftServer; + ++// CraftBukkit start ++import java.net.InetAddress; ++import java.util.HashMap; ++// CraftBukkit end ++ + public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketListener { ++ ++ // CraftBukkit start - add fields ++ private static final HashMap throttleTracker = new HashMap(); ++ private static int throttleCounter = 0; ++ // CraftBukkit end + private static final Component IGNORE_STATUS_REASON = Component.translatable("disconnect.ignoring_status_request"); + private final MinecraftServer server; + private final Connection connection; +@@ -22,40 +33,77 @@ + + @Override + public void handleIntention(ClientIntentionPacket packet) { ++ this.connection.hostname = packet.hostName() + ":" + packet.port(); // CraftBukkit - set hostname + switch (packet.intention()) { + case LOGIN: + this.connection.setClientboundProtocolAfterHandshake(ClientIntent.LOGIN); ++ // CraftBukkit start - Connection throttle ++ try { ++ long currentTime = System.currentTimeMillis(); ++ long connectionThrottle = this.server.server.getConnectionThrottle(); ++ InetAddress address = ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getAddress(); ++ ++ synchronized (throttleTracker) { ++ if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { ++ throttleTracker.put(address, currentTime); ++ MutableComponent chatmessage = Component.literal("Connection throttled! Please wait before reconnecting."); ++ this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); ++ this.connection.disconnect(chatmessage); ++ return; ++ } ++ ++ throttleTracker.put(address, currentTime); ++ throttleCounter++; ++ if (throttleCounter > 200) { ++ throttleCounter = 0; ++ ++ // Cleanup stale entries ++ java.util.Iterator iter = throttleTracker.entrySet().iterator(); ++ while (iter.hasNext()) { ++ java.util.Map.Entry entry = (java.util.Map.Entry) iter.next(); ++ if (entry.getValue() > connectionThrottle) { ++ iter.remove(); ++ } ++ } ++ } ++ } ++ } catch (Throwable t) { ++ org.apache.logging.log4j.LogManager.getLogger().debug("Failed to check connection throttle", t); ++ } ++ // CraftBukkit end + if (packet.protocolVersion() != SharedConstants.getCurrentVersion().getProtocolVersion()) { +- Component component; ++ MutableComponent ichatmutablecomponent; ++ + if (packet.protocolVersion() < 754) { +- component = Component.translatable("multiplayer.disconnect.outdated_client", SharedConstants.getCurrentVersion().getName()); ++ ichatmutablecomponent = Component.translatable("multiplayer.disconnect.outdated_client", SharedConstants.getCurrentVersion().getName()); + } else { +- component = Component.translatable("multiplayer.disconnect.incompatible", SharedConstants.getCurrentVersion().getName()); ++ ichatmutablecomponent = Component.translatable("multiplayer.disconnect.incompatible", SharedConstants.getCurrentVersion().getName()); + } + +- this.connection.send(new ClientboundLoginDisconnectPacket(component)); +- this.connection.disconnect(component); ++ this.connection.send(new ClientboundLoginDisconnectPacket(ichatmutablecomponent)); ++ this.connection.disconnect(ichatmutablecomponent); + } else { + this.connection.setListener(new ServerLoginPacketListenerImpl(this.server, this.connection)); + } + break; + case STATUS: +- ServerStatus status = this.server.getStatus(); +- if (this.server.repliesToStatus() && status != null) { ++ ServerStatus serverping = this.server.getStatus(); ++ ++ if (this.server.repliesToStatus() && serverping != null) { + this.connection.setClientboundProtocolAfterHandshake(ClientIntent.STATUS); +- this.connection.setListener(new ServerStatusPacketListenerImpl(status, this.connection)); ++ this.connection.setListener(new ServerStatusPacketListenerImpl(serverping, this.connection)); + } else { +- this.connection.disconnect(IGNORE_STATUS_REASON); ++ this.connection.disconnect(ServerHandshakePacketListenerImpl.IGNORE_STATUS_REASON); + } + break; + default: + throw new UnsupportedOperationException("Invalid intention " + packet.intention()); + } ++ + } + + @Override +- public void onDisconnect(Component reason) { +- } ++ public void onDisconnect(Component reason) {} + + @Override + public boolean isAcceptingMessages() { diff --git a/patch-remap/mache-vineflower/net/minecraft/server/network/ServerLoginPacketListenerImpl.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/network/ServerLoginPacketListenerImpl.java.patch new file mode 100644 index 0000000000..59abfc47f0 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/network/ServerLoginPacketListenerImpl.java.patch @@ -0,0 +1,386 @@ +--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -32,6 +32,7 @@ + import net.minecraft.network.protocol.login.ServerboundKeyPacket; + import net.minecraft.network.protocol.login.ServerboundLoginAcknowledgedPacket; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.players.PlayerList; + import net.minecraft.util.Crypt; + import net.minecraft.util.CryptException; +@@ -39,24 +40,32 @@ + import net.minecraft.world.entity.player.Player; + import org.apache.commons.lang3.Validate; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.bukkit.event.player.AsyncPlayerPreLoginEvent; ++import org.bukkit.event.player.PlayerPreLoginEvent; ++// CraftBukkit end + + public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, TickablePacketListener { ++ + private static final AtomicInteger UNIQUE_THREAD_ID = new AtomicInteger(0); + static final Logger LOGGER = LogUtils.getLogger(); + private static final int MAX_TICKS_BEFORE_LOGIN = 600; + private static final Component DISCONNECT_UNEXPECTED_QUERY = Component.translatable("multiplayer.disconnect.unexpected_query_response"); + private final byte[] challenge; + final MinecraftServer server; +- final Connection connection; +- private volatile ServerLoginPacketListenerImpl.State state = ServerLoginPacketListenerImpl.State.HELLO; ++ public final Connection connection; ++ private volatile ServerLoginPacketListenerImpl.EnumProtocolState state; + private int tick; + @Nullable + String requestedUsername; + @Nullable + private GameProfile authenticatedProfile; +- private final String serverId = ""; ++ private final String serverId; ++ private ServerPlayer player; // CraftBukkit + + public ServerLoginPacketListenerImpl(MinecraftServer server, Connection connection) { ++ this.state = ServerLoginPacketListenerImpl.EnumProtocolState.HELLO; ++ this.serverId = ""; + this.server = server; + this.connection = connection; + this.challenge = Ints.toByteArray(RandomSource.create().nextInt()); +@@ -64,20 +73,27 @@ + + @Override + public void tick() { +- if (this.state == ServerLoginPacketListenerImpl.State.VERIFYING) { +- this.verifyLoginAndFinishConnectionSetup(Objects.requireNonNull(this.authenticatedProfile)); ++ if (this.state == ServerLoginPacketListenerImpl.EnumProtocolState.VERIFYING) { ++ this.verifyLoginAndFinishConnectionSetup((GameProfile) Objects.requireNonNull(this.authenticatedProfile)); + } + +- if (this.state == ServerLoginPacketListenerImpl.State.WAITING_FOR_DUPE_DISCONNECT +- && !this.isPlayerAlreadyInWorld(Objects.requireNonNull(this.authenticatedProfile))) { ++ if (this.state == ServerLoginPacketListenerImpl.EnumProtocolState.WAITING_FOR_DUPE_DISCONNECT && !this.isPlayerAlreadyInWorld((GameProfile) Objects.requireNonNull(this.authenticatedProfile))) { + this.finishLoginAndWaitForClient(this.authenticatedProfile); + } + + if (this.tick++ == 600) { + this.disconnect(Component.translatable("multiplayer.disconnect.slow_login")); + } ++ + } + ++ // CraftBukkit start ++ @Deprecated ++ public void disconnect(String s) { ++ disconnect(Component.literal(s)); ++ } ++ // CraftBukkit end ++ + @Override + public boolean isAcceptingMessages() { + return this.connection.isConnected(); +@@ -85,173 +101,222 @@ + + public void disconnect(Component reason) { + try { +- LOGGER.info("Disconnecting {}: {}", this.getUserName(), reason.getString()); ++ ServerLoginPacketListenerImpl.LOGGER.info("Disconnecting {}: {}", this.getUserName(), reason.getString()); + this.connection.send(new ClientboundLoginDisconnectPacket(reason)); + this.connection.disconnect(reason); +- } catch (Exception var3) { +- LOGGER.error("Error whilst disconnecting player", (Throwable)var3); ++ } catch (Exception exception) { ++ ServerLoginPacketListenerImpl.LOGGER.error("Error whilst disconnecting player", exception); + } ++ + } + +- private boolean isPlayerAlreadyInWorld(GameProfile gameProfile) { +- return this.server.getPlayerList().getPlayer(gameProfile.getId()) != null; ++ private boolean isPlayerAlreadyInWorld(GameProfile gameprofile) { ++ return this.server.getPlayerList().getPlayer(gameprofile.getId()) != null; + } + + @Override + public void onDisconnect(Component reason) { +- LOGGER.info("{} lost connection: {}", this.getUserName(), reason.getString()); ++ ServerLoginPacketListenerImpl.LOGGER.info("{} lost connection: {}", this.getUserName(), reason.getString()); + } + + public String getUserName() { +- String loggableAddress = this.connection.getLoggableAddress(this.server.logIPs()); +- return this.requestedUsername != null ? this.requestedUsername + " (" + loggableAddress + ")" : loggableAddress; ++ String s = this.connection.getLoggableAddress(this.server.logIPs()); ++ ++ return this.requestedUsername != null ? this.requestedUsername + " (" + s + ")" : s; + } + + @Override + public void handleHello(ServerboundHelloPacket packet) { +- Validate.validState(this.state == ServerLoginPacketListenerImpl.State.HELLO, "Unexpected hello packet"); +- Validate.validState(Player.isValidUsername(packet.name()), "Invalid characters in username"); ++ Validate.validState(this.state == ServerLoginPacketListenerImpl.EnumProtocolState.HELLO, "Unexpected hello packet", new Object[0]); ++ Validate.validState(Player.isValidUsername(packet.name()), "Invalid characters in username", new Object[0]); + this.requestedUsername = packet.name(); +- GameProfile singleplayerProfile = this.server.getSingleplayerProfile(); +- if (singleplayerProfile != null && this.requestedUsername.equalsIgnoreCase(singleplayerProfile.getName())) { +- this.startClientVerification(singleplayerProfile); ++ GameProfile gameprofile = this.server.getSingleplayerProfile(); ++ ++ if (gameprofile != null && this.requestedUsername.equalsIgnoreCase(gameprofile.getName())) { ++ this.startClientVerification(gameprofile); + } else { + if (this.server.usesAuthentication() && !this.connection.isMemoryConnection()) { +- this.state = ServerLoginPacketListenerImpl.State.KEY; ++ this.state = ServerLoginPacketListenerImpl.EnumProtocolState.KEY; + this.connection.send(new ClientboundHelloPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.challenge)); + } else { + this.startClientVerification(UUIDUtil.createOfflineProfile(this.requestedUsername)); + } ++ + } + } + +- void startClientVerification(GameProfile gameProfile) { +- this.authenticatedProfile = gameProfile; +- this.state = ServerLoginPacketListenerImpl.State.VERIFYING; ++ void startClientVerification(GameProfile gameprofile) { ++ this.authenticatedProfile = gameprofile; ++ this.state = ServerLoginPacketListenerImpl.EnumProtocolState.VERIFYING; + } + +- private void verifyLoginAndFinishConnectionSetup(GameProfile gameProfile) { +- PlayerList playerList = this.server.getPlayerList(); +- Component component = playerList.canPlayerLogin(this.connection.getRemoteAddress(), gameProfile); +- if (component != null) { +- this.disconnect(component); ++ private void verifyLoginAndFinishConnectionSetup(GameProfile gameprofile) { ++ PlayerList playerlist = this.server.getPlayerList(); ++ // CraftBukkit start - fire PlayerLoginEvent ++ this.player = playerlist.canPlayerLogin(this, gameprofile); // CraftBukkit ++ ++ if (this.player == null) { ++ // this.disconnect(ichatbasecomponent); ++ // CraftBukkit end + } else { + if (this.server.getCompressionThreshold() >= 0 && !this.connection.isMemoryConnection()) { +- this.connection +- .send( +- new ClientboundLoginCompressionPacket(this.server.getCompressionThreshold()), +- PacketSendListener.thenRun(() -> this.connection.setupCompression(this.server.getCompressionThreshold(), true)) +- ); ++ this.connection.send(new ClientboundLoginCompressionPacket(this.server.getCompressionThreshold()), PacketSendListener.thenRun(() -> { ++ this.connection.setupCompression(this.server.getCompressionThreshold(), true); ++ })); + } + +- boolean flag = playerList.disconnectAllPlayersWithProfile(gameProfile); ++ boolean flag = playerlist.disconnectAllPlayersWithProfile(gameprofile, this.player); // CraftBukkit - add player reference ++ + if (flag) { +- this.state = ServerLoginPacketListenerImpl.State.WAITING_FOR_DUPE_DISCONNECT; ++ this.state = ServerLoginPacketListenerImpl.EnumProtocolState.WAITING_FOR_DUPE_DISCONNECT; + } else { +- this.finishLoginAndWaitForClient(gameProfile); ++ this.finishLoginAndWaitForClient(gameprofile); + } + } ++ + } + +- private void finishLoginAndWaitForClient(GameProfile gameProfile) { +- this.state = ServerLoginPacketListenerImpl.State.PROTOCOL_SWITCHING; +- this.connection.send(new ClientboundGameProfilePacket(gameProfile)); ++ private void finishLoginAndWaitForClient(GameProfile gameprofile) { ++ this.state = ServerLoginPacketListenerImpl.EnumProtocolState.PROTOCOL_SWITCHING; ++ this.connection.send(new ClientboundGameProfilePacket(gameprofile)); + } + + @Override + public void handleKey(ServerboundKeyPacket packet) { +- Validate.validState(this.state == ServerLoginPacketListenerImpl.State.KEY, "Unexpected key packet"); ++ Validate.validState(this.state == ServerLoginPacketListenerImpl.EnumProtocolState.KEY, "Unexpected key packet", new Object[0]); + +- final String string; ++ final String s; ++ + try { +- PrivateKey _private = this.server.getKeyPair().getPrivate(); +- if (!packet.isChallengeValid(this.challenge, _private)) { ++ PrivateKey privatekey = this.server.getKeyPair().getPrivate(); ++ ++ if (!packet.isChallengeValid(this.challenge, privatekey)) { + throw new IllegalStateException("Protocol error"); + } + +- SecretKey secretKey = packet.getSecretKey(_private); +- Cipher cipher = Crypt.getCipher(2, secretKey); +- Cipher cipher1 = Crypt.getCipher(1, secretKey); +- string = new BigInteger(Crypt.digestData("", this.server.getKeyPair().getPublic(), secretKey)).toString(16); +- this.state = ServerLoginPacketListenerImpl.State.AUTHENTICATING; ++ SecretKey secretkey = packet.getSecretKey(privatekey); ++ Cipher cipher = Crypt.getCipher(2, secretkey); ++ Cipher cipher1 = Crypt.getCipher(1, secretkey); ++ ++ s = (new BigInteger(Crypt.digestData("", this.server.getKeyPair().getPublic(), secretkey))).toString(16); ++ this.state = ServerLoginPacketListenerImpl.EnumProtocolState.AUTHENTICATING; + this.connection.setEncryptionKey(cipher, cipher1); +- } catch (CryptException var7) { +- throw new IllegalStateException("Protocol error", var7); ++ } catch (CryptException cryptographyexception) { ++ throw new IllegalStateException("Protocol error", cryptographyexception); + } + +- Thread thread = new Thread("User Authenticator #" + UNIQUE_THREAD_ID.incrementAndGet()) { +- @Override ++ Thread thread = new Thread("User Authenticator #" + ServerLoginPacketListenerImpl.UNIQUE_THREAD_ID.incrementAndGet()) { + public void run() { +- String string1 = Objects.requireNonNull(ServerLoginPacketListenerImpl.this.requestedUsername, "Player name not initialized"); ++ String s1 = (String) Objects.requireNonNull(ServerLoginPacketListenerImpl.this.requestedUsername, "Player name not initialized"); + + try { +- ProfileResult profileResult = ServerLoginPacketListenerImpl.this.server +- .getSessionService() +- .hasJoinedServer(string1, string, this.getAddress()); +- if (profileResult != null) { +- GameProfile gameProfile = profileResult.profile(); +- ServerLoginPacketListenerImpl.LOGGER.info("UUID of player {} is {}", gameProfile.getName(), gameProfile.getId()); +- ServerLoginPacketListenerImpl.this.startClientVerification(gameProfile); ++ ProfileResult profileresult = ServerLoginPacketListenerImpl.this.server.getSessionService().hasJoinedServer(s1, s, this.getAddress()); ++ ++ if (profileresult != null) { ++ GameProfile gameprofile = profileresult.profile(); ++ ++ // CraftBukkit start - fire PlayerPreLoginEvent ++ if (!connection.isConnected()) { ++ return; ++ } ++ ++ String playerName = gameprofile.getName(); ++ java.net.InetAddress address = ((java.net.InetSocketAddress) connection.getRemoteAddress()).getAddress(); ++ java.util.UUID uniqueId = gameprofile.getId(); ++ final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server; ++ ++ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId); ++ server.getPluginManager().callEvent(asyncEvent); ++ ++ if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { ++ final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); ++ if (asyncEvent.getResult() != PlayerPreLoginEvent.Result.ALLOWED) { ++ event.disallow(asyncEvent.getResult(), asyncEvent.getKickMessage()); ++ } ++ Waitable waitable = new Waitable() { ++ @Override ++ protected PlayerPreLoginEvent.Result evaluate() { ++ server.getPluginManager().callEvent(event); ++ return event.getResult(); ++ }}; ++ ++ ServerLoginPacketListenerImpl.this.server.processQueue.add(waitable); ++ if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) { ++ disconnect(event.getKickMessage()); ++ return; ++ } ++ } else { ++ if (asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { ++ disconnect(asyncEvent.getKickMessage()); ++ return; ++ } ++ } ++ // CraftBukkit end ++ ServerLoginPacketListenerImpl.LOGGER.info("UUID of player {} is {}", gameprofile.getName(), gameprofile.getId()); ++ ServerLoginPacketListenerImpl.this.startClientVerification(gameprofile); + } else if (ServerLoginPacketListenerImpl.this.server.isSingleplayer()) { + ServerLoginPacketListenerImpl.LOGGER.warn("Failed to verify username but will let them in anyway!"); +- ServerLoginPacketListenerImpl.this.startClientVerification(UUIDUtil.createOfflineProfile(string1)); ++ ServerLoginPacketListenerImpl.this.startClientVerification(UUIDUtil.createOfflineProfile(s1)); + } else { + ServerLoginPacketListenerImpl.this.disconnect(Component.translatable("multiplayer.disconnect.unverified_username")); +- ServerLoginPacketListenerImpl.LOGGER.error("Username '{}' tried to join with an invalid session", string1); ++ ServerLoginPacketListenerImpl.LOGGER.error("Username '{}' tried to join with an invalid session", s1); + } +- } catch (AuthenticationUnavailableException var4) { ++ } catch (AuthenticationUnavailableException authenticationunavailableexception) { + if (ServerLoginPacketListenerImpl.this.server.isSingleplayer()) { + ServerLoginPacketListenerImpl.LOGGER.warn("Authentication servers are down but will let them in anyway!"); +- ServerLoginPacketListenerImpl.this.startClientVerification(UUIDUtil.createOfflineProfile(string1)); ++ ServerLoginPacketListenerImpl.this.startClientVerification(UUIDUtil.createOfflineProfile(s1)); + } else { + ServerLoginPacketListenerImpl.this.disconnect(Component.translatable("multiplayer.disconnect.authservers_down")); + ServerLoginPacketListenerImpl.LOGGER.error("Couldn't verify username because servers are unavailable"); + } ++ // CraftBukkit start - catch all exceptions ++ } catch (Exception exception) { ++ disconnect("Failed to verify username!"); ++ server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + s1, exception); ++ // CraftBukkit end + } ++ + } + + @Nullable + private InetAddress getAddress() { +- SocketAddress remoteAddress = ServerLoginPacketListenerImpl.this.connection.getRemoteAddress(); +- return ServerLoginPacketListenerImpl.this.server.getPreventProxyConnections() && remoteAddress instanceof InetSocketAddress +- ? ((InetSocketAddress)remoteAddress).getAddress() +- : null; ++ SocketAddress socketaddress = ServerLoginPacketListenerImpl.this.connection.getRemoteAddress(); ++ ++ return ServerLoginPacketListenerImpl.this.server.getPreventProxyConnections() && socketaddress instanceof InetSocketAddress ? ((InetSocketAddress) socketaddress).getAddress() : null; + } + }; +- thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER)); ++ ++ thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(ServerLoginPacketListenerImpl.LOGGER)); + thread.start(); + } + + @Override +- public void handleCustomQueryPacket(ServerboundCustomQueryAnswerPacket serverboundCustomQueryAnswerPacket) { +- this.disconnect(DISCONNECT_UNEXPECTED_QUERY); ++ public void handleCustomQueryPacket(ServerboundCustomQueryAnswerPacket serverboundcustomqueryanswerpacket) { ++ this.disconnect(ServerLoginPacketListenerImpl.DISCONNECT_UNEXPECTED_QUERY); + } + + @Override +- public void handleLoginAcknowledgement(ServerboundLoginAcknowledgedPacket serverboundLoginAcknowledgedPacket) { +- Validate.validState(this.state == ServerLoginPacketListenerImpl.State.PROTOCOL_SWITCHING, "Unexpected login acknowledgement packet"); +- CommonListenerCookie commonListenerCookie = CommonListenerCookie.createInitial(Objects.requireNonNull(this.authenticatedProfile)); +- ServerConfigurationPacketListenerImpl serverConfigurationPacketListenerImpl = new ServerConfigurationPacketListenerImpl( +- this.server, this.connection, commonListenerCookie +- ); +- this.connection.setListener(serverConfigurationPacketListenerImpl); +- serverConfigurationPacketListenerImpl.startConfiguration(); +- this.state = ServerLoginPacketListenerImpl.State.ACCEPTED; ++ public void handleLoginAcknowledgement(ServerboundLoginAcknowledgedPacket serverboundloginacknowledgedpacket) { ++ Validate.validState(this.state == ServerLoginPacketListenerImpl.EnumProtocolState.PROTOCOL_SWITCHING, "Unexpected login acknowledgement packet", new Object[0]); ++ CommonListenerCookie commonlistenercookie = CommonListenerCookie.createInitial((GameProfile) Objects.requireNonNull(this.authenticatedProfile)); ++ ServerConfigurationPacketListenerImpl serverconfigurationpacketlistenerimpl = new ServerConfigurationPacketListenerImpl(this.server, this.connection, commonlistenercookie, this.player); // CraftBukkit ++ ++ this.connection.setListener(serverconfigurationpacketlistenerimpl); ++ serverconfigurationpacketlistenerimpl.startConfiguration(); ++ this.state = ServerLoginPacketListenerImpl.EnumProtocolState.ACCEPTED; + } + + @Override +- public void fillListenerSpecificCrashDetails(CrashReportCategory crashReportCategory) { +- crashReportCategory.setDetail("Login phase", () -> this.state.toString()); ++ public void fillListenerSpecificCrashDetails(CrashReportCategory crashreportsystemdetails) { ++ crashreportsystemdetails.setDetail("Login phase", () -> { ++ return this.state.toString(); ++ }); + } + +- static enum State { +- HELLO, +- KEY, +- AUTHENTICATING, +- NEGOTIATING, +- VERIFYING, +- WAITING_FOR_DUPE_DISCONNECT, +- PROTOCOL_SWITCHING, +- ACCEPTED; ++ private static enum EnumProtocolState { ++ ++ HELLO, KEY, AUTHENTICATING, NEGOTIATING, VERIFYING, WAITING_FOR_DUPE_DISCONNECT, PROTOCOL_SWITCHING, ACCEPTED; ++ ++ private EnumProtocolState() {} + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/network/ServerStatusPacketListenerImpl.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/network/ServerStatusPacketListenerImpl.java.patch new file mode 100644 index 0000000000..939fba2992 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/network/ServerStatusPacketListenerImpl.java.patch @@ -0,0 +1,155 @@ +--- a/net/minecraft/server/network/ServerStatusPacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerStatusPacketListenerImpl.java +@@ -1,5 +1,12 @@ + package net.minecraft.server.network; + ++// CraftBukkit start ++import com.mojang.authlib.GameProfile; ++import java.net.InetSocketAddress; ++import java.util.Collections; ++import java.util.Iterator; ++import java.util.Optional; ++import net.minecraft.SharedConstants; + import net.minecraft.network.Connection; + import net.minecraft.network.chat.Component; + import net.minecraft.network.protocol.status.ClientboundPongResponsePacket; +@@ -8,8 +15,15 @@ + import net.minecraft.network.protocol.status.ServerStatusPacketListener; + import net.minecraft.network.protocol.status.ServerboundPingRequestPacket; + import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerPlayer; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.craftbukkit.util.CraftIconCache; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class ServerStatusPacketListenerImpl implements ServerStatusPacketListener { ++ + private static final Component DISCONNECT_REASON = Component.translatable("multiplayer.status.request_handled"); + private final ServerStatus status; + private final Connection connection; +@@ -21,8 +35,7 @@ + } + + @Override +- public void onDisconnect(Component reason) { +- } ++ public void onDisconnect(Component reason) {} + + @Override + public boolean isAcceptingMessages() { +@@ -32,16 +45,110 @@ + @Override + public void handleStatusRequest(ServerboundStatusRequestPacket packet) { + if (this.hasRequestedStatus) { +- this.connection.disconnect(DISCONNECT_REASON); ++ this.connection.disconnect(ServerStatusPacketListenerImpl.DISCONNECT_REASON); + } else { + this.hasRequestedStatus = true; +- this.connection.send(new ClientboundStatusResponsePacket(this.status)); ++ // CraftBukkit start ++ // this.connection.send(new PacketStatusOutServerInfo(this.status)); ++ MinecraftServer server = MinecraftServer.getServer(); ++ final Object[] players = server.getPlayerList().players.toArray(); ++ class ServerListPingEvent extends org.bukkit.event.server.ServerListPingEvent { ++ ++ CraftIconCache icon = server.server.getServerIcon(); ++ ++ ServerListPingEvent() { ++ super(connection.hostname, ((InetSocketAddress) connection.getRemoteAddress()).getAddress(), server.getMotd(), server.getPlayerList().getMaxPlayers()); ++ } ++ ++ @Override ++ public void setServerIcon(org.bukkit.util.CachedServerIcon icon) { ++ if (!(icon instanceof CraftIconCache)) { ++ throw new IllegalArgumentException(icon + " was not created by " + org.bukkit.craftbukkit.CraftServer.class); ++ } ++ this.icon = (CraftIconCache) icon; ++ } ++ ++ @Override ++ public Iterator iterator() throws UnsupportedOperationException { ++ return new Iterator() { ++ int i; ++ int ret = Integer.MIN_VALUE; ++ ServerPlayer player; ++ ++ @Override ++ public boolean hasNext() { ++ if (player != null) { ++ return true; ++ } ++ final Object[] currentPlayers = players; ++ for (int length = currentPlayers.length, i = this.i; i < length; i++) { ++ final ServerPlayer player = (ServerPlayer) currentPlayers[i]; ++ if (player != null) { ++ this.i = i + 1; ++ this.player = player; ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ @Override ++ public Player next() { ++ if (!hasNext()) { ++ throw new java.util.NoSuchElementException(); ++ } ++ final ServerPlayer player = this.player; ++ this.player = null; ++ this.ret = this.i - 1; ++ return player.getBukkitEntity(); ++ } ++ ++ @Override ++ public void remove() { ++ final Object[] currentPlayers = players; ++ final int i = this.ret; ++ if (i < 0 || currentPlayers[i] == null) { ++ throw new IllegalStateException(); ++ } ++ currentPlayers[i] = null; ++ } ++ }; ++ } ++ } ++ ++ ServerListPingEvent event = new ServerListPingEvent(); ++ server.server.getPluginManager().callEvent(event); ++ ++ java.util.List profiles = new java.util.ArrayList(players.length); ++ for (Object player : players) { ++ if (player != null) { ++ ServerPlayer entityPlayer = ((ServerPlayer) player); ++ if (entityPlayer.allowsListing()) { ++ profiles.add(entityPlayer.getGameProfile()); ++ } else { ++ profiles.add(MinecraftServer.ANONYMOUS_PLAYER_PROFILE); ++ } ++ } ++ } ++ ++ ServerStatus.ServerPingPlayerSample playerSample = new ServerStatus.ServerPingPlayerSample(event.getMaxPlayers(), profiles.size(), (server.hidesOnlinePlayers()) ? Collections.emptyList() : profiles); ++ ++ ServerStatus ping = new ServerStatus( ++ CraftChatMessage.fromString(event.getMotd(), true)[0], ++ Optional.of(playerSample), ++ Optional.of(new ServerStatus.Version(server.getServerModName() + " " + server.getServerVersion(), SharedConstants.getCurrentVersion().getProtocolVersion())), ++ (event.icon.value != null) ? Optional.of(new ServerStatus.a(event.icon.value)) : Optional.empty(), ++ server.enforceSecureProfile() ++ ); ++ ++ this.connection.send(new ClientboundStatusResponsePacket(ping)); ++ // CraftBukkit end + } + } + + @Override + public void handlePingRequest(ServerboundPingRequestPacket packet) { + this.connection.send(new ClientboundPongResponsePacket(packet.getTime())); +- this.connection.disconnect(DISCONNECT_REASON); ++ this.connection.disconnect(ServerStatusPacketListenerImpl.DISCONNECT_REASON); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/players/BanListEntry.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/players/BanListEntry.java.patch new file mode 100644 index 0000000000..03a5be51dd --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/players/BanListEntry.java.patch @@ -0,0 +1,76 @@ +--- a/net/minecraft/server/players/BanListEntry.java ++++ b/net/minecraft/server/players/BanListEntry.java +@@ -9,6 +9,7 @@ + import net.minecraft.network.chat.Component; + + public abstract class BanListEntry extends StoredUserEntry { ++ + public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z", Locale.ROOT); + public static final String EXPIRES_NEVER = "forever"; + protected final Date created; +@@ -26,12 +27,13 @@ + } + + protected BanListEntry(@Nullable T user, JsonObject entryData) { +- super(user); ++ super(checkExpiry(user, entryData)); // CraftBukkit + + Date date; ++ + try { +- date = entryData.has("created") ? DATE_FORMAT.parse(entryData.get("created").getAsString()) : new Date(); +- } catch (ParseException var7) { ++ date = entryData.has("created") ? BanListEntry.DATE_FORMAT.parse(entryData.get("created").getAsString()) : new Date(); ++ } catch (ParseException parseexception) { + date = new Date(); + } + +@@ -39,9 +41,10 @@ + this.source = entryData.has("source") ? entryData.get("source").getAsString() : "(Unknown)"; + + Date date1; ++ + try { +- date1 = entryData.has("expires") ? DATE_FORMAT.parse(entryData.get("expires").getAsString()) : null; +- } catch (ParseException var6) { ++ date1 = entryData.has("expires") ? BanListEntry.DATE_FORMAT.parse(entryData.get("expires").getAsString()) : null; ++ } catch (ParseException parseexception1) { + date1 = null; + } + +@@ -70,14 +73,32 @@ + + @Override + boolean hasExpired() { +- return this.expires != null && this.expires.before(new Date()); ++ return this.expires == null ? false : this.expires.before(new Date()); + } + + @Override + protected void serialize(JsonObject data) { +- data.addProperty("created", DATE_FORMAT.format(this.created)); ++ data.addProperty("created", BanListEntry.DATE_FORMAT.format(this.created)); + data.addProperty("source", this.source); +- data.addProperty("expires", this.expires == null ? "forever" : DATE_FORMAT.format(this.expires)); ++ data.addProperty("expires", this.expires == null ? "forever" : BanListEntry.DATE_FORMAT.format(this.expires)); + data.addProperty("reason", this.reason); + } ++ ++ // CraftBukkit start ++ private static T checkExpiry(T object, JsonObject jsonobject) { ++ Date expires = null; ++ ++ try { ++ expires = jsonobject.has("expires") ? DATE_FORMAT.parse(jsonobject.get("expires").getAsString()) : null; ++ } catch (ParseException ex) { ++ // Guess we don't have a date ++ } ++ ++ if (expires == null || expires.after(new Date())) { ++ return object; ++ } else { ++ return null; ++ } ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/players/GameProfileCache.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/players/GameProfileCache.java.patch new file mode 100644 index 0000000000..2181de7a61 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/players/GameProfileCache.java.patch @@ -0,0 +1,416 @@ +--- a/net/minecraft/server/players/GameProfileCache.java ++++ b/net/minecraft/server/players/GameProfileCache.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.server.players; + + import com.google.common.collect.ImmutableList; +@@ -14,21 +15,23 @@ + import com.mojang.authlib.GameProfileRepository; + import com.mojang.authlib.ProfileLookupCallback; + import com.mojang.logging.LogUtils; ++import java.io.BufferedReader; ++import java.io.BufferedWriter; + import java.io.File; + import java.io.FileNotFoundException; + import java.io.IOException; +-import java.io.Reader; +-import java.io.Writer; + import java.nio.charset.StandardCharsets; + import java.text.DateFormat; + import java.text.ParseException; + import java.text.SimpleDateFormat; ++import java.util.ArrayList; + import java.util.Calendar; + import java.util.Comparator; + import java.util.Date; + import java.util.List; + import java.util.Locale; + import java.util.Map; ++import java.util.Objects; + import java.util.Optional; + import java.util.UUID; + import java.util.concurrent.CompletableFuture; +@@ -43,6 +46,7 @@ + import org.slf4j.Logger; + + public class GameProfileCache { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int GAMEPROFILES_MRU_LIMIT = 1000; + private static final int GAMEPROFILES_EXPIRATION_MONTHS = 1; +@@ -51,7 +55,7 @@ + private final Map profilesByUUID = Maps.newConcurrentMap(); + private final Map>> requests = Maps.newConcurrentMap(); + private final GameProfileRepository profileRepository; +- private final Gson gson = new GsonBuilder().create(); ++ private final Gson gson = (new GsonBuilder()).create(); + private final File file; + private final AtomicLong operationCount = new AtomicLong(); + @Nullable +@@ -64,53 +68,56 @@ + } + + private void safeAdd(GameProfileCache.GameProfileInfo profile) { +- GameProfile profile1 = profile.getProfile(); ++ GameProfile gameprofile = profile.getProfile(); ++ + profile.setLastAccess(this.getNextOperation()); +- this.profilesByName.put(profile1.getName().toLowerCase(Locale.ROOT), profile); +- this.profilesByUUID.put(profile1.getId(), profile); ++ this.profilesByName.put(gameprofile.getName().toLowerCase(Locale.ROOT), profile); ++ this.profilesByUUID.put(gameprofile.getId(), profile); + } + + private static Optional lookupGameProfile(GameProfileRepository profileRepo, String name) { + if (!Player.isValidUsername(name)) { + return createUnknownProfile(name); + } else { +- final AtomicReference atomicReference = new AtomicReference<>(); +- ProfileLookupCallback profileLookupCallback = new ProfileLookupCallback() { +- @Override +- public void onProfileLookupSucceeded(GameProfile profile) { +- atomicReference.set(profile); ++ final AtomicReference atomicreference = new AtomicReference(); ++ ProfileLookupCallback profilelookupcallback = new ProfileLookupCallback() { ++ public void onProfileLookupSucceeded(GameProfile gameprofile) { ++ atomicreference.set(gameprofile); + } + +- @Override +- public void onProfileLookupFailed(String string, Exception exception) { +- atomicReference.set(null); ++ public void onProfileLookupFailed(String s1, Exception exception) { ++ atomicreference.set(null); // CraftBukkit - decompile error + } + }; +- profileRepo.findProfilesByNames(new String[]{name}, profileLookupCallback); +- GameProfile gameProfile = atomicReference.get(); +- return gameProfile != null ? Optional.of(gameProfile) : createUnknownProfile(name); ++ ++ profileRepo.findProfilesByNames(new String[]{name}, profilelookupcallback); ++ GameProfile gameprofile = (GameProfile) atomicreference.get(); ++ ++ return gameprofile != null ? Optional.of(gameprofile) : createUnknownProfile(name); + } + } + +- private static Optional createUnknownProfile(String string) { +- return usesAuthentication() ? Optional.empty() : Optional.of(UUIDUtil.createOfflineProfile(string)); ++ private static Optional createUnknownProfile(String s) { ++ return usesAuthentication() ? Optional.empty() : Optional.of(UUIDUtil.createOfflineProfile(s)); + } + + public static void setUsesAuthentication(boolean onlineMode) { +- usesAuthentication = onlineMode; ++ GameProfileCache.usesAuthentication = onlineMode; + } + + private static boolean usesAuthentication() { +- return usesAuthentication; ++ return GameProfileCache.usesAuthentication; + } + + public void add(GameProfile gameProfile) { +- Calendar instance = Calendar.getInstance(); +- instance.setTime(new Date()); +- instance.add(2, 1); +- Date time = instance.getTime(); +- GameProfileCache.GameProfileInfo gameProfileInfo = new GameProfileCache.GameProfileInfo(gameProfile, time); +- this.safeAdd(gameProfileInfo); ++ Calendar calendar = Calendar.getInstance(); ++ ++ calendar.setTime(new Date()); ++ calendar.add(2, 1); ++ Date date = calendar.getTime(); ++ GameProfileCache.GameProfileInfo usercache_usercacheentry = new GameProfileCache.GameProfileInfo(gameProfile, date); ++ ++ this.safeAdd(usercache_usercacheentry); + this.save(); + } + +@@ -119,24 +126,26 @@ + } + + public Optional get(String name) { +- String string = name.toLowerCase(Locale.ROOT); +- GameProfileCache.GameProfileInfo gameProfileInfo = this.profilesByName.get(string); ++ String s1 = name.toLowerCase(Locale.ROOT); ++ GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByName.get(s1); + boolean flag = false; +- if (gameProfileInfo != null && new Date().getTime() >= gameProfileInfo.expirationDate.getTime()) { +- this.profilesByUUID.remove(gameProfileInfo.getProfile().getId()); +- this.profilesByName.remove(gameProfileInfo.getProfile().getName().toLowerCase(Locale.ROOT)); ++ ++ if (usercache_usercacheentry != null && (new Date()).getTime() >= usercache_usercacheentry.expirationDate.getTime()) { ++ this.profilesByUUID.remove(usercache_usercacheentry.getProfile().getId()); ++ this.profilesByName.remove(usercache_usercacheentry.getProfile().getName().toLowerCase(Locale.ROOT)); + flag = true; +- gameProfileInfo = null; ++ usercache_usercacheentry = null; + } + +- Optional optional; +- if (gameProfileInfo != null) { +- gameProfileInfo.setLastAccess(this.getNextOperation()); +- optional = Optional.of(gameProfileInfo.getProfile()); ++ Optional optional; ++ ++ if (usercache_usercacheentry != null) { ++ usercache_usercacheentry.setLastAccess(this.getNextOperation()); ++ optional = Optional.of(usercache_usercacheentry.getProfile()); + } else { +- optional = lookupGameProfile(this.profileRepository, string); ++ optional = lookupGameProfile(this.profileRepository, s1); + if (optional.isPresent()) { +- this.add(optional.get()); ++ this.add((GameProfile) optional.get()); + flag = false; + } + } +@@ -148,31 +157,35 @@ + return optional; + } + +- public CompletableFuture> getAsync(String string) { ++ public CompletableFuture> getAsync(String s) { + if (this.executor == null) { + throw new IllegalStateException("No executor"); + } else { +- CompletableFuture> completableFuture = this.requests.get(string); +- if (completableFuture != null) { +- return completableFuture; ++ CompletableFuture> completablefuture = (CompletableFuture) this.requests.get(s); ++ ++ if (completablefuture != null) { ++ return completablefuture; + } else { +- CompletableFuture> completableFuture1 = CompletableFuture.>supplyAsync( +- () -> this.get(string), Util.backgroundExecutor() +- ) +- .whenCompleteAsync((optional, throwable) -> this.requests.remove(string), this.executor); +- this.requests.put(string, completableFuture1); +- return completableFuture1; ++ CompletableFuture> completablefuture1 = CompletableFuture.supplyAsync(() -> { ++ return this.get(s); ++ }, Util.backgroundExecutor()).whenCompleteAsync((optional, throwable) -> { ++ this.requests.remove(s); ++ }, this.executor); ++ ++ this.requests.put(s, completablefuture1); ++ return completablefuture1; + } + } + } + + public Optional get(UUID uuid) { +- GameProfileCache.GameProfileInfo gameProfileInfo = this.profilesByUUID.get(uuid); +- if (gameProfileInfo == null) { ++ GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByUUID.get(uuid); ++ ++ if (usercache_usercacheentry == null) { + return Optional.empty(); + } else { +- gameProfileInfo.setLastAccess(this.getNextOperation()); +- return Optional.of(gameProfileInfo.getProfile()); ++ usercache_usercacheentry.setLastAccess(this.getNextOperation()); ++ return Optional.of(usercache_usercacheentry.getProfile()); + } + } + +@@ -189,83 +202,140 @@ + } + + public List load() { +- List list = Lists.newArrayList(); ++ ArrayList arraylist = Lists.newArrayList(); + + try { +- Object var9; +- try (Reader reader = Files.newReader(this.file, StandardCharsets.UTF_8)) { +- JsonArray jsonArray = this.gson.fromJson(reader, JsonArray.class); +- if (jsonArray != null) { +- DateFormat dateFormat = createDateFormat(); +- jsonArray.forEach(jsonElement -> readGameProfile(jsonElement, dateFormat).ifPresent(list::add)); +- return list; ++ BufferedReader bufferedreader = Files.newReader(this.file, StandardCharsets.UTF_8); ++ ++ label54: ++ { ++ ArrayList arraylist1; ++ ++ try { ++ JsonArray jsonarray = (JsonArray) this.gson.fromJson(bufferedreader, JsonArray.class); ++ ++ if (jsonarray != null) { ++ DateFormat dateformat = createDateFormat(); ++ ++ jsonarray.forEach((jsonelement) -> { ++ Optional optional = readGameProfile(jsonelement, dateformat); ++ ++ Objects.requireNonNull(arraylist); ++ optional.ifPresent(arraylist::add); ++ }); ++ break label54; ++ } ++ ++ arraylist1 = arraylist; ++ } catch (Throwable throwable) { ++ if (bufferedreader != null) { ++ try { ++ bufferedreader.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } + +- var9 = list; ++ if (bufferedreader != null) { ++ bufferedreader.close(); ++ } ++ ++ return arraylist1; + } + +- return (List)var9; +- } catch (FileNotFoundException var7) { +- } catch (JsonParseException | IOException var8) { +- LOGGER.warn("Failed to load profile cache {}", this.file, var8); ++ if (bufferedreader != null) { ++ bufferedreader.close(); ++ } ++ } catch (FileNotFoundException filenotfoundexception) { ++ ; ++ } catch (JsonParseException | IOException ioexception) { ++ GameProfileCache.LOGGER.warn("Failed to load profile cache {}", this.file, ioexception); + } + +- return list; ++ return arraylist; + } + + public void save() { +- JsonArray jsonArray = new JsonArray(); +- DateFormat dateFormat = createDateFormat(); +- this.getTopMRUProfiles(1000).forEach(gameProfileInfo -> jsonArray.add(writeGameProfile(gameProfileInfo, dateFormat))); +- String string = this.gson.toJson((JsonElement)jsonArray); ++ JsonArray jsonarray = new JsonArray(); ++ DateFormat dateformat = createDateFormat(); + +- try (Writer writer = Files.newWriter(this.file, StandardCharsets.UTF_8)) { +- writer.write(string); +- } catch (IOException var9) { ++ this.getTopMRUProfiles(1000).forEach((usercache_usercacheentry) -> { ++ jsonarray.add(writeGameProfile(usercache_usercacheentry, dateformat)); ++ }); ++ String s = this.gson.toJson(jsonarray); ++ ++ try { ++ BufferedWriter bufferedwriter = Files.newWriter(this.file, StandardCharsets.UTF_8); ++ ++ try { ++ bufferedwriter.write(s); ++ } catch (Throwable throwable) { ++ if (bufferedwriter != null) { ++ try { ++ bufferedwriter.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; ++ } ++ ++ if (bufferedwriter != null) { ++ bufferedwriter.close(); ++ } ++ } catch (IOException ioexception) { ++ ; + } ++ + } + + private Stream getTopMRUProfiles(int limit) { +- return ImmutableList.copyOf(this.profilesByUUID.values()) +- .stream() +- .sorted(Comparator.comparing(GameProfileCache.GameProfileInfo::getLastAccess).reversed()) +- .limit((long)limit); ++ return ImmutableList.copyOf(this.profilesByUUID.values()).stream().sorted(Comparator.comparing(GameProfileCache.GameProfileInfo::getLastAccess).reversed()).limit((long) limit); + } + + private static JsonElement writeGameProfile(GameProfileCache.GameProfileInfo profileInfo, DateFormat dateFormat) { +- JsonObject jsonObject = new JsonObject(); +- jsonObject.addProperty("name", profileInfo.getProfile().getName()); +- jsonObject.addProperty("uuid", profileInfo.getProfile().getId().toString()); +- jsonObject.addProperty("expiresOn", dateFormat.format(profileInfo.getExpirationDate())); +- return jsonObject; ++ JsonObject jsonobject = new JsonObject(); ++ ++ jsonobject.addProperty("name", profileInfo.getProfile().getName()); ++ jsonobject.addProperty("uuid", profileInfo.getProfile().getId().toString()); ++ jsonobject.addProperty("expiresOn", dateFormat.format(profileInfo.getExpirationDate())); ++ return jsonobject; + } + + private static Optional readGameProfile(JsonElement json, DateFormat dateFormat) { + if (json.isJsonObject()) { +- JsonObject asJsonObject = json.getAsJsonObject(); +- JsonElement jsonElement = asJsonObject.get("name"); +- JsonElement jsonElement1 = asJsonObject.get("uuid"); +- JsonElement jsonElement2 = asJsonObject.get("expiresOn"); +- if (jsonElement != null && jsonElement1 != null) { +- String asString = jsonElement1.getAsString(); +- String asString1 = jsonElement.getAsString(); ++ JsonObject jsonobject = json.getAsJsonObject(); ++ JsonElement jsonelement1 = jsonobject.get("name"); ++ JsonElement jsonelement2 = jsonobject.get("uuid"); ++ JsonElement jsonelement3 = jsonobject.get("expiresOn"); ++ ++ if (jsonelement1 != null && jsonelement2 != null) { ++ String s = jsonelement2.getAsString(); ++ String s1 = jsonelement1.getAsString(); + Date date = null; +- if (jsonElement2 != null) { ++ ++ if (jsonelement3 != null) { + try { +- date = dateFormat.parse(jsonElement2.getAsString()); +- } catch (ParseException var12) { ++ date = dateFormat.parse(jsonelement3.getAsString()); ++ } catch (ParseException parseexception) { ++ ; + } + } + +- if (asString1 != null && asString != null && date != null) { +- UUID uUID; ++ if (s1 != null && s != null && date != null) { ++ UUID uuid; ++ + try { +- uUID = UUID.fromString(asString); +- } catch (Throwable var11) { ++ uuid = UUID.fromString(s); ++ } catch (Throwable throwable) { + return Optional.empty(); + } + +- return Optional.of(new GameProfileCache.GameProfileInfo(new GameProfile(uUID, asString1), date)); ++ return Optional.of(new GameProfileCache.GameProfileInfo(new GameProfile(uuid, s1), date)); + } else { + return Optional.empty(); + } +@@ -277,7 +347,8 @@ + } + } + +- static class GameProfileInfo { ++ private static class GameProfileInfo { ++ + private final GameProfile profile; + final Date expirationDate; + private volatile long lastAccess; diff --git a/patch-remap/mache-vineflower/net/minecraft/server/players/OldUsersConverter.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/players/OldUsersConverter.java.patch new file mode 100644 index 0000000000..d2b7cb7299 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/players/OldUsersConverter.java.patch @@ -0,0 +1,678 @@ +--- a/net/minecraft/server/players/OldUsersConverter.java ++++ b/net/minecraft/server/players/OldUsersConverter.java +@@ -13,6 +13,7 @@ + import java.text.ParseException; + import java.util.Collection; + import java.util.Date; ++import java.util.Iterator; + import java.util.List; + import java.util.Locale; + import java.util.Map; +@@ -20,6 +21,9 @@ + import java.util.UUID; + import javax.annotation.Nullable; + import net.minecraft.core.UUIDUtil; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.NbtAccounter; ++import net.minecraft.nbt.NbtIo; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.dedicated.DedicatedServer; + import net.minecraft.util.StringUtil; +@@ -27,85 +31,106 @@ + import org.slf4j.Logger; + + public class OldUsersConverter { ++ + static final Logger LOGGER = LogUtils.getLogger(); + public static final File OLD_IPBANLIST = new File("banned-ips.txt"); + public static final File OLD_USERBANLIST = new File("banned-players.txt"); + public static final File OLD_OPLIST = new File("ops.txt"); + public static final File OLD_WHITELIST = new File("white-list.txt"); + ++ public OldUsersConverter() {} ++ + static List readOldListFormat(File inFile, Map read) throws IOException { +- List lines = Files.readLines(inFile, StandardCharsets.UTF_8); ++ List list = Files.readLines(inFile, StandardCharsets.UTF_8); ++ Iterator iterator = list.iterator(); + +- for (String string : lines) { +- String var6 = string.trim(); +- if (!var6.startsWith("#") && var6.length() >= 1) { +- String[] parts = var6.split("\\|"); +- read.put(parts[0].toLowerCase(Locale.ROOT), parts); ++ while (iterator.hasNext()) { ++ String s = (String) iterator.next(); ++ ++ s = s.trim(); ++ if (!s.startsWith("#") && s.length() >= 1) { ++ String[] astring = s.split("\\|"); ++ ++ read.put(astring[0].toLowerCase(Locale.ROOT), astring); + } + } + +- return lines; ++ return list; + } + + private static void lookupPlayers(MinecraftServer server, Collection names, ProfileLookupCallback callback) { +- String[] strings = names.stream().filter(string1 -> !StringUtil.isNullOrEmpty(string1)).toArray(String[]::new); ++ String[] astring = (String[]) names.stream().filter((s) -> { ++ return !StringUtil.isNullOrEmpty(s); ++ }).toArray((i) -> { ++ return new String[i]; ++ }); ++ + if (server.usesAuthentication()) { +- server.getProfileRepository().findProfilesByNames(strings, callback); ++ server.getProfileRepository().findProfilesByNames(astring, callback); + } else { +- for (String string : strings) { +- callback.onProfileLookupSucceeded(UUIDUtil.createOfflineProfile(string)); ++ String[] astring1 = astring; ++ int i = astring.length; ++ ++ for (int j = 0; j < i; ++j) { ++ String s = astring1[j]; ++ ++ callback.onProfileLookupSucceeded(UUIDUtil.createOfflineProfile(s)); + } + } ++ + } + + public static boolean convertUserBanlist(final MinecraftServer server) { +- final UserBanList userBanList = new UserBanList(PlayerList.USERBANLIST_FILE); +- if (OLD_USERBANLIST.exists() && OLD_USERBANLIST.isFile()) { +- if (userBanList.getFile().exists()) { ++ final UserBanList gameprofilebanlist = new UserBanList(PlayerList.USERBANLIST_FILE); ++ ++ if (OldUsersConverter.OLD_USERBANLIST.exists() && OldUsersConverter.OLD_USERBANLIST.isFile()) { ++ if (gameprofilebanlist.getFile().exists()) { + try { +- userBanList.load(); +- } catch (IOException var6) { +- LOGGER.warn("Could not load existing file {}", userBanList.getFile().getName(), var6); ++ gameprofilebanlist.load(); ++ } catch (IOException ioexception) { ++ OldUsersConverter.LOGGER.warn("Could not load existing file {}", gameprofilebanlist.getFile().getName()); // CraftBukkit - don't print stacktrace + } + } + + try { + final Map map = Maps.newHashMap(); +- readOldListFormat(OLD_USERBANLIST, map); +- ProfileLookupCallback profileLookupCallback = new ProfileLookupCallback() { +- @Override +- public void onProfileLookupSucceeded(GameProfile gameProfile) { +- server.getProfileCache().add(gameProfile); +- String[] strings = map.get(gameProfile.getName().toLowerCase(Locale.ROOT)); +- if (strings == null) { +- OldUsersConverter.LOGGER.warn("Could not convert user banlist entry for {}", gameProfile.getName()); ++ ++ readOldListFormat(OldUsersConverter.OLD_USERBANLIST, map); ++ ProfileLookupCallback profilelookupcallback = new ProfileLookupCallback() { ++ public void onProfileLookupSucceeded(GameProfile gameprofile) { ++ server.getProfileCache().add(gameprofile); ++ String[] astring = (String[]) map.get(gameprofile.getName().toLowerCase(Locale.ROOT)); ++ ++ if (astring == null) { ++ OldUsersConverter.LOGGER.warn("Could not convert user banlist entry for {}", gameprofile.getName()); + throw new OldUsersConverter.ConversionError("Profile not in the conversionlist"); + } else { +- Date date = strings.length > 1 ? OldUsersConverter.parseDate(strings[1], null) : null; +- String string = strings.length > 2 ? strings[2] : null; +- Date date1 = strings.length > 3 ? OldUsersConverter.parseDate(strings[3], null) : null; +- String string1 = strings.length > 4 ? strings[4] : null; +- userBanList.add(new UserBanListEntry(gameProfile, date, string, date1, string1)); ++ Date date = astring.length > 1 ? OldUsersConverter.parseDate(astring[1], (Date) null) : null; ++ String s = astring.length > 2 ? astring[2] : null; ++ Date date1 = astring.length > 3 ? OldUsersConverter.parseDate(astring[3], (Date) null) : null; ++ String s1 = astring.length > 4 ? astring[4] : null; ++ ++ gameprofilebanlist.add(new UserBanListEntry(gameprofile, date, s, date1, s1)); + } + } + +- @Override +- public void onProfileLookupFailed(String string, Exception exception) { +- OldUsersConverter.LOGGER.warn("Could not lookup user banlist entry for {}", string, exception); ++ public void onProfileLookupFailed(String s, Exception exception) { ++ OldUsersConverter.LOGGER.warn("Could not lookup user banlist entry for {}", s, exception); + if (!(exception instanceof ProfileNotFoundException)) { +- throw new OldUsersConverter.ConversionError("Could not request user " + string + " from backend systems", exception); ++ throw new OldUsersConverter.ConversionError("Could not request user " + s + " from backend systems", exception); + } + } + }; +- lookupPlayers(server, map.keySet(), profileLookupCallback); +- userBanList.save(); +- renameOldFile(OLD_USERBANLIST); ++ ++ lookupPlayers(server, map.keySet(), profilelookupcallback); ++ gameprofilebanlist.save(); ++ renameOldFile(OldUsersConverter.OLD_USERBANLIST); + return true; +- } catch (IOException var4) { +- LOGGER.warn("Could not read old user banlist to convert it!", (Throwable)var4); ++ } catch (IOException ioexception1) { ++ OldUsersConverter.LOGGER.warn("Could not read old user banlist to convert it!", ioexception1); + return false; +- } catch (OldUsersConverter.ConversionError var5) { +- LOGGER.error("Conversion failed, please try again later", (Throwable)var5); ++ } catch (OldUsersConverter.ConversionError namereferencingfileconverter_fileconversionexception) { ++ OldUsersConverter.LOGGER.error("Conversion failed, please try again later", namereferencingfileconverter_fileconversionexception); + return false; + } + } else { +@@ -114,34 +139,39 @@ + } + + public static boolean convertIpBanlist(MinecraftServer server) { +- IpBanList ipBanList = new IpBanList(PlayerList.IPBANLIST_FILE); +- if (OLD_IPBANLIST.exists() && OLD_IPBANLIST.isFile()) { +- if (ipBanList.getFile().exists()) { ++ IpBanList ipbanlist = new IpBanList(PlayerList.IPBANLIST_FILE); ++ ++ if (OldUsersConverter.OLD_IPBANLIST.exists() && OldUsersConverter.OLD_IPBANLIST.isFile()) { ++ if (ipbanlist.getFile().exists()) { + try { +- ipBanList.load(); +- } catch (IOException var11) { +- LOGGER.warn("Could not load existing file {}", ipBanList.getFile().getName(), var11); ++ ipbanlist.load(); ++ } catch (IOException ioexception) { ++ OldUsersConverter.LOGGER.warn("Could not load existing file {}", ipbanlist.getFile().getName()); // CraftBukkit - don't print stacktrace + } + } + + try { + Map map = Maps.newHashMap(); +- readOldListFormat(OLD_IPBANLIST, map); + +- for (String string : map.keySet()) { +- String[] strings = map.get(string); +- Date date = strings.length > 1 ? parseDate(strings[1], null) : null; +- String string1 = strings.length > 2 ? strings[2] : null; +- Date date1 = strings.length > 3 ? parseDate(strings[3], null) : null; +- String string2 = strings.length > 4 ? strings[4] : null; +- ipBanList.add(new IpBanListEntry(string, date, string1, date1, string2)); ++ readOldListFormat(OldUsersConverter.OLD_IPBANLIST, map); ++ Iterator iterator = map.keySet().iterator(); ++ ++ while (iterator.hasNext()) { ++ String s = (String) iterator.next(); ++ String[] astring = (String[]) map.get(s); ++ Date date = astring.length > 1 ? parseDate(astring[1], (Date) null) : null; ++ String s1 = astring.length > 2 ? astring[2] : null; ++ Date date1 = astring.length > 3 ? parseDate(astring[3], (Date) null) : null; ++ String s2 = astring.length > 4 ? astring[4] : null; ++ ++ ipbanlist.add(new IpBanListEntry(s, date, s1, date1, s2)); + } + +- ipBanList.save(); +- renameOldFile(OLD_IPBANLIST); ++ ipbanlist.save(); ++ renameOldFile(OldUsersConverter.OLD_IPBANLIST); + return true; +- } catch (IOException var10) { +- LOGGER.warn("Could not parse old ip banlist to convert it!", (Throwable)var10); ++ } catch (IOException ioexception1) { ++ OldUsersConverter.LOGGER.warn("Could not parse old ip banlist to convert it!", ioexception1); + return false; + } + } else { +@@ -150,42 +180,42 @@ + } + + public static boolean convertOpsList(final MinecraftServer server) { +- final ServerOpList serverOpList = new ServerOpList(PlayerList.OPLIST_FILE); +- if (OLD_OPLIST.exists() && OLD_OPLIST.isFile()) { +- if (serverOpList.getFile().exists()) { ++ final ServerOpList oplist = new ServerOpList(PlayerList.OPLIST_FILE); ++ ++ if (OldUsersConverter.OLD_OPLIST.exists() && OldUsersConverter.OLD_OPLIST.isFile()) { ++ if (oplist.getFile().exists()) { + try { +- serverOpList.load(); +- } catch (IOException var6) { +- LOGGER.warn("Could not load existing file {}", serverOpList.getFile().getName(), var6); ++ oplist.load(); ++ } catch (IOException ioexception) { ++ OldUsersConverter.LOGGER.warn("Could not load existing file {}", oplist.getFile().getName()); // CraftBukkit - don't print stacktrace + } + } + + try { +- List lines = Files.readLines(OLD_OPLIST, StandardCharsets.UTF_8); +- ProfileLookupCallback profileLookupCallback = new ProfileLookupCallback() { +- @Override +- public void onProfileLookupSucceeded(GameProfile gameProfile) { +- server.getProfileCache().add(gameProfile); +- serverOpList.add(new ServerOpListEntry(gameProfile, server.getOperatorUserPermissionLevel(), false)); ++ List list = Files.readLines(OldUsersConverter.OLD_OPLIST, StandardCharsets.UTF_8); ++ ProfileLookupCallback profilelookupcallback = new ProfileLookupCallback() { ++ public void onProfileLookupSucceeded(GameProfile gameprofile) { ++ server.getProfileCache().add(gameprofile); ++ oplist.add(new ServerOpListEntry(gameprofile, server.getOperatorUserPermissionLevel(), false)); + } + +- @Override +- public void onProfileLookupFailed(String string, Exception exception) { +- OldUsersConverter.LOGGER.warn("Could not lookup oplist entry for {}", string, exception); ++ public void onProfileLookupFailed(String s, Exception exception) { ++ OldUsersConverter.LOGGER.warn("Could not lookup oplist entry for {}", s, exception); + if (!(exception instanceof ProfileNotFoundException)) { +- throw new OldUsersConverter.ConversionError("Could not request user " + string + " from backend systems", exception); ++ throw new OldUsersConverter.ConversionError("Could not request user " + s + " from backend systems", exception); + } + } + }; +- lookupPlayers(server, lines, profileLookupCallback); +- serverOpList.save(); +- renameOldFile(OLD_OPLIST); ++ ++ lookupPlayers(server, list, profilelookupcallback); ++ oplist.save(); ++ renameOldFile(OldUsersConverter.OLD_OPLIST); + return true; +- } catch (IOException var4) { +- LOGGER.warn("Could not read old oplist to convert it!", (Throwable)var4); ++ } catch (IOException ioexception1) { ++ OldUsersConverter.LOGGER.warn("Could not read old oplist to convert it!", ioexception1); + return false; +- } catch (OldUsersConverter.ConversionError var5) { +- LOGGER.error("Conversion failed, please try again later", (Throwable)var5); ++ } catch (OldUsersConverter.ConversionError namereferencingfileconverter_fileconversionexception) { ++ OldUsersConverter.LOGGER.error("Conversion failed, please try again later", namereferencingfileconverter_fileconversionexception); + return false; + } + } else { +@@ -194,42 +224,42 @@ + } + + public static boolean convertWhiteList(final MinecraftServer server) { +- final UserWhiteList userWhiteList = new UserWhiteList(PlayerList.WHITELIST_FILE); +- if (OLD_WHITELIST.exists() && OLD_WHITELIST.isFile()) { +- if (userWhiteList.getFile().exists()) { ++ final UserWhiteList whitelist = new UserWhiteList(PlayerList.WHITELIST_FILE); ++ ++ if (OldUsersConverter.OLD_WHITELIST.exists() && OldUsersConverter.OLD_WHITELIST.isFile()) { ++ if (whitelist.getFile().exists()) { + try { +- userWhiteList.load(); +- } catch (IOException var6) { +- LOGGER.warn("Could not load existing file {}", userWhiteList.getFile().getName(), var6); ++ whitelist.load(); ++ } catch (IOException ioexception) { ++ OldUsersConverter.LOGGER.warn("Could not load existing file {}", whitelist.getFile().getName()); // CraftBukkit - don't print stacktrace + } + } + + try { +- List lines = Files.readLines(OLD_WHITELIST, StandardCharsets.UTF_8); +- ProfileLookupCallback profileLookupCallback = new ProfileLookupCallback() { +- @Override +- public void onProfileLookupSucceeded(GameProfile gameProfile) { +- server.getProfileCache().add(gameProfile); +- userWhiteList.add(new UserWhiteListEntry(gameProfile)); ++ List list = Files.readLines(OldUsersConverter.OLD_WHITELIST, StandardCharsets.UTF_8); ++ ProfileLookupCallback profilelookupcallback = new ProfileLookupCallback() { ++ public void onProfileLookupSucceeded(GameProfile gameprofile) { ++ server.getProfileCache().add(gameprofile); ++ whitelist.add(new UserWhiteListEntry(gameprofile)); + } + +- @Override +- public void onProfileLookupFailed(String string, Exception exception) { +- OldUsersConverter.LOGGER.warn("Could not lookup user whitelist entry for {}", string, exception); ++ public void onProfileLookupFailed(String s, Exception exception) { ++ OldUsersConverter.LOGGER.warn("Could not lookup user whitelist entry for {}", s, exception); + if (!(exception instanceof ProfileNotFoundException)) { +- throw new OldUsersConverter.ConversionError("Could not request user " + string + " from backend systems", exception); ++ throw new OldUsersConverter.ConversionError("Could not request user " + s + " from backend systems", exception); + } + } + }; +- lookupPlayers(server, lines, profileLookupCallback); +- userWhiteList.save(); +- renameOldFile(OLD_WHITELIST); ++ ++ lookupPlayers(server, list, profilelookupcallback); ++ whitelist.save(); ++ renameOldFile(OldUsersConverter.OLD_WHITELIST); + return true; +- } catch (IOException var4) { +- LOGGER.warn("Could not read old whitelist to convert it!", (Throwable)var4); ++ } catch (IOException ioexception1) { ++ OldUsersConverter.LOGGER.warn("Could not read old whitelist to convert it!", ioexception1); + return false; +- } catch (OldUsersConverter.ConversionError var5) { +- LOGGER.error("Conversion failed, please try again later", (Throwable)var5); ++ } catch (OldUsersConverter.ConversionError namereferencingfileconverter_fileconversionexception) { ++ OldUsersConverter.LOGGER.error("Conversion failed, please try again later", namereferencingfileconverter_fileconversionexception); + return false; + } + } else { +@@ -241,105 +271,141 @@ + public static UUID convertMobOwnerIfNecessary(final MinecraftServer server, String username) { + if (!StringUtil.isNullOrEmpty(username) && username.length() <= 16) { + Optional optional = server.getProfileCache().get(username).map(GameProfile::getId); ++ + if (optional.isPresent()) { +- return optional.get(); ++ return (UUID) optional.get(); + } else if (!server.isSingleplayer() && server.usesAuthentication()) { + final List list = Lists.newArrayList(); +- ProfileLookupCallback profileLookupCallback = new ProfileLookupCallback() { +- @Override +- public void onProfileLookupSucceeded(GameProfile gameProfile) { +- server.getProfileCache().add(gameProfile); +- list.add(gameProfile); ++ ProfileLookupCallback profilelookupcallback = new ProfileLookupCallback() { ++ public void onProfileLookupSucceeded(GameProfile gameprofile) { ++ server.getProfileCache().add(gameprofile); ++ list.add(gameprofile); + } + +- @Override +- public void onProfileLookupFailed(String string, Exception exception) { +- OldUsersConverter.LOGGER.warn("Could not lookup user whitelist entry for {}", string, exception); ++ public void onProfileLookupFailed(String s1, Exception exception) { ++ OldUsersConverter.LOGGER.warn("Could not lookup user whitelist entry for {}", s1, exception); + } + }; +- lookupPlayers(server, Lists.newArrayList(username), profileLookupCallback); +- return !list.isEmpty() ? list.get(0).getId() : null; ++ ++ lookupPlayers(server, Lists.newArrayList(new String[]{username}), profilelookupcallback); ++ return !list.isEmpty() ? ((GameProfile) list.get(0)).getId() : null; + } else { + return UUIDUtil.createOfflinePlayerUUID(username); + } + } else { + try { + return UUID.fromString(username); +- } catch (IllegalArgumentException var5) { ++ } catch (IllegalArgumentException illegalargumentexception) { + return null; + } + } + } + + public static boolean convertPlayers(final DedicatedServer server) { +- final File worldPlayersDirectory = getWorldPlayersDirectory(server); +- final File file = new File(worldPlayersDirectory.getParentFile(), "playerdata"); +- final File file1 = new File(worldPlayersDirectory.getParentFile(), "unknownplayers"); +- if (worldPlayersDirectory.exists() && worldPlayersDirectory.isDirectory()) { +- File[] files = worldPlayersDirectory.listFiles(); ++ final File file = getWorldPlayersDirectory(server); ++ final File file1 = new File(file.getParentFile(), "playerdata"); ++ final File file2 = new File(file.getParentFile(), "unknownplayers"); ++ ++ if (file.exists() && file.isDirectory()) { ++ File[] afile = file.listFiles(); + List list = Lists.newArrayList(); ++ File[] afile1 = afile; ++ int i = afile.length; + +- for (File file2 : files) { +- String name = file2.getName(); +- if (name.toLowerCase(Locale.ROOT).endsWith(".dat")) { +- String sub = name.substring(0, name.length() - ".dat".length()); +- if (!sub.isEmpty()) { +- list.add(sub); ++ for (int j = 0; j < i; ++j) { ++ File file3 = afile1[j]; ++ String s = file3.getName(); ++ ++ if (s.toLowerCase(Locale.ROOT).endsWith(".dat")) { ++ String s1 = s.substring(0, s.length() - ".dat".length()); ++ ++ if (!s1.isEmpty()) { ++ list.add(s1); + } + } + } + + try { +- final String[] strings = list.toArray(new String[list.size()]); +- ProfileLookupCallback profileLookupCallback = new ProfileLookupCallback() { +- @Override +- public void onProfileLookupSucceeded(GameProfile gameProfile) { +- server.getProfileCache().add(gameProfile); +- UUID id = gameProfile.getId(); +- this.movePlayerFile(file, this.getFileNameForProfile(gameProfile.getName()), id.toString()); ++ final String[] astring = (String[]) list.toArray(new String[list.size()]); ++ ProfileLookupCallback profilelookupcallback = new ProfileLookupCallback() { ++ public void onProfileLookupSucceeded(GameProfile gameprofile) { ++ server.getProfileCache().add(gameprofile); ++ UUID uuid = gameprofile.getId(); ++ ++ this.movePlayerFile(file1, this.getFileNameForProfile(gameprofile.getName()), uuid.toString()); + } + +- @Override +- public void onProfileLookupFailed(String string, Exception exception) { +- OldUsersConverter.LOGGER.warn("Could not lookup user uuid for {}", string, exception); ++ public void onProfileLookupFailed(String s2, Exception exception) { ++ OldUsersConverter.LOGGER.warn("Could not lookup user uuid for {}", s2, exception); + if (exception instanceof ProfileNotFoundException) { +- String fileNameForProfile = this.getFileNameForProfile(string); +- this.movePlayerFile(file1, fileNameForProfile, fileNameForProfile); ++ String s3 = this.getFileNameForProfile(s2); ++ ++ this.movePlayerFile(file2, s3, s3); + } else { +- throw new OldUsersConverter.ConversionError("Could not request user " + string + " from backend systems", exception); ++ throw new OldUsersConverter.ConversionError("Could not request user " + s2 + " from backend systems", exception); + } + } + +- private void movePlayerFile(File file3, String oldFileName, String newFileName) { +- File file4 = new File(worldPlayersDirectory, oldFileName + ".dat"); +- File file5 = new File(file3, newFileName + ".dat"); +- OldUsersConverter.ensureDirectoryExists(file3); +- if (!file4.renameTo(file5)) { ++ private void movePlayerFile(File file, String oldFileName, String newFileName) { ++ File file5 = new File(file, oldFileName + ".dat"); ++ File file6 = new File(file, newFileName + ".dat"); ++ ++ // CraftBukkit start - Use old file name to seed lastKnownName ++ CompoundTag root = null; ++ ++ try { ++ root = NbtIo.readCompressed(new java.io.FileInputStream(file5), NbtAccounter.unlimitedHeap()); ++ } catch (Exception exception) { ++ exception.printStackTrace(); ++ } ++ ++ if (root != null) { ++ if (!root.contains("bukkit")) { ++ root.put("bukkit", new CompoundTag()); ++ } ++ CompoundTag data = root.getCompound("bukkit"); ++ data.putString("lastKnownName", oldFileName); ++ ++ try { ++ NbtIo.writeCompressed(root, new java.io.FileOutputStream(file2)); ++ } catch (Exception exception) { ++ exception.printStackTrace(); ++ } ++ } ++ // CraftBukkit end ++ ++ OldUsersConverter.ensureDirectoryExists(file); ++ if (!file5.renameTo(file6)) { + throw new OldUsersConverter.ConversionError("Could not convert file for " + oldFileName); + } + } + +- private String getFileNameForProfile(String string) { +- String string1 = null; ++ private String getFileNameForProfile(String s2) { ++ String s3 = null; ++ String[] astring1 = astring; ++ int k = astring1.length; + +- for (String string2 : strings) { +- if (string2 != null && string2.equalsIgnoreCase(string)) { +- string1 = string2; ++ for (int l = 0; l < k; ++l) { ++ String s4 = astring1[l]; ++ ++ if (s4 != null && s4.equalsIgnoreCase(s2)) { ++ s3 = s4; + break; + } + } + +- if (string1 == null) { +- throw new OldUsersConverter.ConversionError("Could not find the filename for " + string + " anymore"); ++ if (s3 == null) { ++ throw new OldUsersConverter.ConversionError("Could not find the filename for " + s2 + " anymore"); + } else { +- return string1; ++ return s3; + } + } + }; +- lookupPlayers(server, Lists.newArrayList(strings), profileLookupCallback); ++ ++ lookupPlayers(server, Lists.newArrayList(astring), profilelookupcallback); + return true; +- } catch (OldUsersConverter.ConversionError var12) { +- LOGGER.error("Conversion failed, please try again later", (Throwable)var12); ++ } catch (OldUsersConverter.ConversionError namereferencingfileconverter_fileconversionexception) { ++ OldUsersConverter.LOGGER.error("Conversion failed, please try again later", namereferencingfileconverter_fileconversionexception); + return false; + } + } else { +@@ -359,49 +425,55 @@ + + public static boolean serverReadyAfterUserconversion(MinecraftServer server) { + boolean flag = areOldUserlistsRemoved(); +- return flag && areOldPlayersConverted(server); ++ ++ flag = flag && areOldPlayersConverted(server); ++ return flag; + } + + private static boolean areOldUserlistsRemoved() { + boolean flag = false; +- if (OLD_USERBANLIST.exists() && OLD_USERBANLIST.isFile()) { ++ ++ if (OldUsersConverter.OLD_USERBANLIST.exists() && OldUsersConverter.OLD_USERBANLIST.isFile()) { + flag = true; + } + + boolean flag1 = false; +- if (OLD_IPBANLIST.exists() && OLD_IPBANLIST.isFile()) { ++ ++ if (OldUsersConverter.OLD_IPBANLIST.exists() && OldUsersConverter.OLD_IPBANLIST.isFile()) { + flag1 = true; + } + + boolean flag2 = false; +- if (OLD_OPLIST.exists() && OLD_OPLIST.isFile()) { ++ ++ if (OldUsersConverter.OLD_OPLIST.exists() && OldUsersConverter.OLD_OPLIST.isFile()) { + flag2 = true; + } + + boolean flag3 = false; +- if (OLD_WHITELIST.exists() && OLD_WHITELIST.isFile()) { ++ ++ if (OldUsersConverter.OLD_WHITELIST.exists() && OldUsersConverter.OLD_WHITELIST.isFile()) { + flag3 = true; + } + + if (!flag && !flag1 && !flag2 && !flag3) { + return true; + } else { +- LOGGER.warn("**** FAILED TO START THE SERVER AFTER ACCOUNT CONVERSION!"); +- LOGGER.warn("** please remove the following files and restart the server:"); ++ OldUsersConverter.LOGGER.warn("**** FAILED TO START THE SERVER AFTER ACCOUNT CONVERSION!"); ++ OldUsersConverter.LOGGER.warn("** please remove the following files and restart the server:"); + if (flag) { +- LOGGER.warn("* {}", OLD_USERBANLIST.getName()); ++ OldUsersConverter.LOGGER.warn("* {}", OldUsersConverter.OLD_USERBANLIST.getName()); + } + + if (flag1) { +- LOGGER.warn("* {}", OLD_IPBANLIST.getName()); ++ OldUsersConverter.LOGGER.warn("* {}", OldUsersConverter.OLD_IPBANLIST.getName()); + } + + if (flag2) { +- LOGGER.warn("* {}", OLD_OPLIST.getName()); ++ OldUsersConverter.LOGGER.warn("* {}", OldUsersConverter.OLD_OPLIST.getName()); + } + + if (flag3) { +- LOGGER.warn("* {}", OLD_WHITELIST.getName()); ++ OldUsersConverter.LOGGER.warn("* {}", OldUsersConverter.OLD_WHITELIST.getName()); + } + + return false; +@@ -409,16 +481,15 @@ + } + + private static boolean areOldPlayersConverted(MinecraftServer server) { +- File worldPlayersDirectory = getWorldPlayersDirectory(server); +- if (!worldPlayersDirectory.exists() +- || !worldPlayersDirectory.isDirectory() +- || worldPlayersDirectory.list().length <= 0 && worldPlayersDirectory.delete()) { +- return true; +- } else { +- LOGGER.warn("**** DETECTED OLD PLAYER DIRECTORY IN THE WORLD SAVE"); +- LOGGER.warn("**** THIS USUALLY HAPPENS WHEN THE AUTOMATIC CONVERSION FAILED IN SOME WAY"); +- LOGGER.warn("** please restart the server and if the problem persists, remove the directory '{}'", worldPlayersDirectory.getPath()); ++ File file = getWorldPlayersDirectory(server); ++ ++ if (file.exists() && file.isDirectory() && (file.list().length > 0 || !file.delete())) { ++ OldUsersConverter.LOGGER.warn("**** DETECTED OLD PLAYER DIRECTORY IN THE WORLD SAVE"); ++ OldUsersConverter.LOGGER.warn("**** THIS USUALLY HAPPENS WHEN THE AUTOMATIC CONVERSION FAILED IN SOME WAY"); ++ OldUsersConverter.LOGGER.warn("** please restart the server and if the problem persists, remove the directory '{}'", file.getPath()); + return false; ++ } else { ++ return true; + } + } + +@@ -427,22 +498,25 @@ + } + + private static void renameOldFile(File convertedFile) { +- File file = new File(convertedFile.getName() + ".converted"); +- convertedFile.renameTo(file); ++ File file1 = new File(convertedFile.getName() + ".converted"); ++ ++ convertedFile.renameTo(file1); + } + + static Date parseDate(String input, Date defaultValue) { +- Date date; ++ Date date1; ++ + try { +- date = BanListEntry.DATE_FORMAT.parse(input); +- } catch (ParseException var4) { +- date = defaultValue; ++ date1 = BanListEntry.DATE_FORMAT.parse(input); ++ } catch (ParseException parseexception) { ++ date1 = defaultValue; + } + +- return date; ++ return date1; + } + +- static class ConversionError extends RuntimeException { ++ private static class ConversionError extends RuntimeException { ++ + ConversionError(String message, Throwable cause) { + super(message, cause); + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/players/PlayerList.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/players/PlayerList.java.patch new file mode 100644 index 0000000000..1db65bcf21 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/players/PlayerList.java.patch @@ -0,0 +1,1599 @@ +--- a/net/minecraft/server/players/PlayerList.java ++++ b/net/minecraft/server/players/PlayerList.java +@@ -5,15 +5,19 @@ + import com.google.common.collect.Sets; + import com.mojang.authlib.GameProfile; + import com.mojang.logging.LogUtils; ++import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; + import java.io.File; + import java.net.SocketAddress; + import java.nio.file.Path; + import java.text.SimpleDateFormat; + import java.time.Instant; ++import java.util.Collection; + import java.util.EnumSet; ++import java.util.Iterator; + import java.util.List; + import java.util.Map; ++import java.util.Objects; + import java.util.Optional; + import java.util.Set; + import java.util.UUID; +@@ -70,6 +74,7 @@ + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.network.CommonListenerCookie; + import net.minecraft.server.network.ServerGamePacketListenerImpl; ++import net.minecraft.server.network.ServerLoginPacketListenerImpl; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.ServerStatsCounter; +@@ -80,11 +85,10 @@ + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.border.BorderChangeListener; + import net.minecraft.world.level.border.WorldBorder; + import net.minecraft.world.level.dimension.DimensionType; +@@ -95,10 +99,29 @@ + import net.minecraft.world.scores.DisplaySlot; + import net.minecraft.world.scores.Objective; + import net.minecraft.world.scores.PlayerTeam; +-import net.minecraft.world.scores.Team; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.stream.Collectors; ++import net.minecraft.server.dedicated.DedicatedServer; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerChangedWorldEvent; ++import org.bukkit.event.player.PlayerJoinEvent; ++import org.bukkit.event.player.PlayerLoginEvent; ++import org.bukkit.event.player.PlayerQuitEvent; ++import org.bukkit.event.player.PlayerRespawnEvent; ++import org.bukkit.event.player.PlayerRespawnEvent.RespawnReason; ++import org.bukkit.event.player.PlayerSpawnChangeEvent; ++// CraftBukkit end ++ + public abstract class PlayerList { ++ + public static final File USERBANLIST_FILE = new File("banned-players.json"); + public static final File IPBANLIST_FILE = new File("banned-ips.json"); + public static final File OPLIST_FILE = new File("ops.json"); +@@ -109,478 +132,801 @@ + private static final int SEND_PLAYER_INFO_INTERVAL = 600; + private static final SimpleDateFormat BAN_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z"); + private final MinecraftServer server; +- private final List players = Lists.newArrayList(); ++ public final List players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety + private final Map playersByUUID = Maps.newHashMap(); +- private final UserBanList bans = new UserBanList(USERBANLIST_FILE); +- private final IpBanList ipBans = new IpBanList(IPBANLIST_FILE); +- private final ServerOpList ops = new ServerOpList(OPLIST_FILE); +- private final UserWhiteList whitelist = new UserWhiteList(WHITELIST_FILE); +- private final Map stats = Maps.newHashMap(); +- private final Map advancements = Maps.newHashMap(); +- private final PlayerDataStorage playerIo; ++ private final UserBanList bans; ++ private final IpBanList ipBans; ++ private final ServerOpList ops; ++ private final UserWhiteList whitelist; ++ // CraftBukkit start ++ // private final Map stats; ++ // private final Map advancements; ++ // CraftBukkit end ++ public final PlayerDataStorage playerIo; + private boolean doWhiteList; + private final LayeredRegistryAccess registries; +- protected final int maxPlayers; ++ public int maxPlayers; + private int viewDistance; + private int simulationDistance; + private boolean allowCheatsForAllPlayers; + private static final boolean ALLOW_LOGOUTIVATOR = false; + private int sendAllPlayerInfoIn; + ++ // CraftBukkit start ++ private CraftServer cserver; ++ + public PlayerList(MinecraftServer server, LayeredRegistryAccess registries, PlayerDataStorage playerIo, int maxPlayers) { ++ this.cserver = server.server = new CraftServer((DedicatedServer) server, this); ++ server.console = org.bukkit.craftbukkit.command.ColouredConsoleSender.getInstance(); ++ server.reader.addCompleter(new org.bukkit.craftbukkit.command.ConsoleCommandCompleter(server.server)); ++ // CraftBukkit end ++ ++ this.bans = new UserBanList(PlayerList.USERBANLIST_FILE); ++ this.ipBans = new IpBanList(PlayerList.IPBANLIST_FILE); ++ this.ops = new ServerOpList(PlayerList.OPLIST_FILE); ++ this.whitelist = new UserWhiteList(PlayerList.WHITELIST_FILE); ++ // CraftBukkit start ++ // this.stats = Maps.newHashMap(); ++ // this.advancements = Maps.newHashMap(); ++ // CraftBukkit end + this.server = server; + this.registries = registries; + this.maxPlayers = maxPlayers; + this.playerIo = playerIo; + } + +- public void placeNewPlayer(Connection connection, ServerPlayer serverPlayer, CommonListenerCookie commonListenerCookie) { +- GameProfile gameProfile = serverPlayer.getGameProfile(); +- GameProfileCache profileCache = this.server.getProfileCache(); +- String string; +- if (profileCache != null) { +- Optional optional = profileCache.get(gameProfile.getId()); +- string = optional.map(GameProfile::getName).orElse(gameProfile.getName()); +- profileCache.add(gameProfile); ++ public void placeNewPlayer(Connection networkmanager, ServerPlayer entityplayer, CommonListenerCookie commonlistenercookie) { ++ GameProfile gameprofile = entityplayer.getGameProfile(); ++ GameProfileCache usercache = this.server.getProfileCache(); ++ String s; ++ ++ if (usercache != null) { ++ Optional optional = usercache.get(gameprofile.getId()); ++ ++ s = (String) optional.map(GameProfile::getName).orElse(gameprofile.getName()); ++ usercache.add(gameprofile); + } else { +- string = gameProfile.getName(); ++ s = gameprofile.getName(); + } + +- CompoundTag compoundTag = this.load(serverPlayer); +- ResourceKey resourceKey = compoundTag != null +- ? DimensionType.parseLegacy(new Dynamic<>(NbtOps.INSTANCE, compoundTag.get("Dimension"))).resultOrPartial(LOGGER::error).orElse(Level.OVERWORLD) +- : Level.OVERWORLD; +- ServerLevel level = this.server.getLevel(resourceKey); +- ServerLevel serverLevel; +- if (level == null) { +- LOGGER.warn("Unknown respawn dimension {}, defaulting to overworld", resourceKey); +- serverLevel = this.server.overworld(); ++ CompoundTag nbttagcompound = this.load(entityplayer); ++ ResourceKey resourcekey; ++ // CraftBukkit start - Better rename detection ++ if (nbttagcompound != null && nbttagcompound.contains("bukkit")) { ++ CompoundTag bukkit = nbttagcompound.getCompound("bukkit"); ++ s = bukkit.contains("lastKnownName", 8) ? bukkit.getString("lastKnownName") : s; ++ } ++ // CraftBukkit end ++ ++ if (nbttagcompound != null) { ++ DataResult> dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, nbttagcompound.get("Dimension"))); // CraftBukkit - decompile error ++ Logger logger = PlayerList.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ resourcekey = (ResourceKey) dataresult.resultOrPartial(logger::error).orElse(entityplayer.serverLevel().dimension()); // CraftBukkit - SPIGOT-7507: If no dimension, fall back to existing dimension loaded from "WorldUUID", which in turn defaults to World.OVERWORLD + } else { +- serverLevel = level; ++ resourcekey = entityplayer.serverLevel().dimension(); // CraftBukkit - SPIGOT-7507: If no dimension, fall back to existing dimension loaded from "WorldUUID", which in turn defaults to World.OVERWORLD + } + +- serverPlayer.setServerLevel(serverLevel); +- String loggableAddress = connection.getLoggableAddress(this.server.logIPs()); +- LOGGER.info( +- "{}[{}] logged in with entity id {} at ({}, {}, {})", +- serverPlayer.getName().getString(), +- loggableAddress, +- serverPlayer.getId(), +- serverPlayer.getX(), +- serverPlayer.getY(), +- serverPlayer.getZ() +- ); +- LevelData levelData = serverLevel.getLevelData(); +- serverPlayer.loadGameTypes(compoundTag); +- ServerGamePacketListenerImpl serverGamePacketListenerImpl = new ServerGamePacketListenerImpl( +- this.server, connection, serverPlayer, commonListenerCookie +- ); +- GameRules gameRules = serverLevel.getGameRules(); +- boolean _boolean = gameRules.getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN); +- boolean _boolean1 = gameRules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO); +- boolean _boolean2 = gameRules.getBoolean(GameRules.RULE_LIMITED_CRAFTING); +- serverGamePacketListenerImpl.send( +- new ClientboundLoginPacket( +- serverPlayer.getId(), +- levelData.isHardcore(), +- this.server.levelKeys(), +- this.getMaxPlayers(), +- this.viewDistance, +- this.simulationDistance, +- _boolean1, +- !_boolean, +- _boolean2, +- serverPlayer.createCommonSpawnInfo(serverLevel) +- ) +- ); +- serverGamePacketListenerImpl.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked())); +- serverGamePacketListenerImpl.send(new ClientboundPlayerAbilitiesPacket(serverPlayer.getAbilities())); +- serverGamePacketListenerImpl.send(new ClientboundSetCarriedItemPacket(serverPlayer.getInventory().selected)); +- serverGamePacketListenerImpl.send(new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes())); +- this.sendPlayerPermissionLevel(serverPlayer); +- serverPlayer.getStats().markAllDirty(); +- serverPlayer.getRecipeBook().sendInitialRecipeBook(serverPlayer); +- this.updateEntireScoreboard(serverLevel.getScoreboard(), serverPlayer); ++ ResourceKey resourcekey1 = resourcekey; ++ ServerLevel worldserver = this.server.getLevel(resourcekey1); ++ ServerLevel worldserver1; ++ ++ if (worldserver == null) { ++ PlayerList.LOGGER.warn("Unknown respawn dimension {}, defaulting to overworld", resourcekey1); ++ worldserver1 = this.server.overworld(); ++ } else { ++ worldserver1 = worldserver; ++ } ++ ++ entityplayer.setServerLevel(worldserver1); ++ String s1 = networkmanager.getLoggableAddress(this.server.logIPs()); ++ ++ // CraftBukkit - Moved message to after join ++ // PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ({}, {}, {})", new Object[]{entityplayer.getName().getString(), s1, entityplayer.getId(), entityplayer.getX(), entityplayer.getY(), entityplayer.getZ()}); ++ LevelData worlddata = worldserver1.getLevelData(); ++ ++ entityplayer.loadGameTypes(nbttagcompound); ++ ServerGamePacketListenerImpl playerconnection = new ServerGamePacketListenerImpl(this.server, networkmanager, entityplayer, commonlistenercookie); ++ GameRules gamerules = worldserver1.getGameRules(); ++ boolean flag = gamerules.getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN); ++ boolean flag1 = gamerules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO); ++ boolean flag2 = gamerules.getBoolean(GameRules.RULE_LIMITED_CRAFTING); ++ ++ playerconnection.send(new ClientboundLoginPacket(entityplayer.getId(), worlddata.isHardcore(), this.server.levelKeys(), this.getMaxPlayers(), this.viewDistance, this.simulationDistance, flag1, !flag, flag2, entityplayer.createCommonSpawnInfo(worldserver1))); ++ entityplayer.getBukkitEntity().sendSupportedChannels(); // CraftBukkit ++ playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); ++ playerconnection.send(new ClientboundPlayerAbilitiesPacket(entityplayer.getAbilities())); ++ playerconnection.send(new ClientboundSetCarriedItemPacket(entityplayer.getInventory().selected)); ++ playerconnection.send(new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes())); ++ this.sendPlayerPermissionLevel(entityplayer); ++ entityplayer.getStats().markAllDirty(); ++ entityplayer.getRecipeBook().sendInitialRecipeBook(entityplayer); ++ this.updateEntireScoreboard(worldserver1.getScoreboard(), entityplayer); + this.server.invalidateStatus(); +- MutableComponent mutableComponent; +- if (serverPlayer.getGameProfile().getName().equalsIgnoreCase(string)) { +- mutableComponent = Component.translatable("multiplayer.player.joined", serverPlayer.getDisplayName()); ++ MutableComponent ichatmutablecomponent; ++ ++ if (entityplayer.getGameProfile().getName().equalsIgnoreCase(s)) { ++ ichatmutablecomponent = Component.translatable("multiplayer.player.joined", entityplayer.getDisplayName()); + } else { +- mutableComponent = Component.translatable("multiplayer.player.joined.renamed", serverPlayer.getDisplayName(), string); ++ ichatmutablecomponent = Component.translatable("multiplayer.player.joined.renamed", entityplayer.getDisplayName(), s); + } ++ // CraftBukkit start ++ ichatmutablecomponent.withStyle(ChatFormatting.YELLOW); ++ String joinMessage = CraftChatMessage.fromComponent(ichatmutablecomponent); + +- this.broadcastSystemMessage(mutableComponent.withStyle(ChatFormatting.YELLOW), false); +- serverGamePacketListenerImpl.teleport(serverPlayer.getX(), serverPlayer.getY(), serverPlayer.getZ(), serverPlayer.getYRot(), serverPlayer.getXRot()); +- ServerStatus status = this.server.getStatus(); +- if (status != null) { +- serverPlayer.sendServerStatus(status); ++ playerconnection.teleport(entityplayer.getX(), entityplayer.getY(), entityplayer.getZ(), entityplayer.getYRot(), entityplayer.getXRot()); ++ ServerStatus serverping = this.server.getStatus(); ++ ++ if (serverping != null) { ++ entityplayer.sendServerStatus(serverping); + } + +- serverPlayer.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); +- this.players.add(serverPlayer); +- this.playersByUUID.put(serverPlayer.getUUID(), serverPlayer); +- this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(serverPlayer))); +- this.sendLevelInfo(serverPlayer, serverLevel); +- serverLevel.addNewPlayer(serverPlayer); +- this.server.getCustomBossEvents().onPlayerConnect(serverPlayer); ++ // entityplayer.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below ++ this.players.add(entityplayer); ++ this.playersByUUID.put(entityplayer.getUUID(), entityplayer); ++ // this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer))); // CraftBukkit - replaced with loop below + +- for (MobEffectInstance mobEffectInstance : serverPlayer.getActiveEffects()) { +- serverGamePacketListenerImpl.send(new ClientboundUpdateMobEffectPacket(serverPlayer.getId(), mobEffectInstance)); ++ // CraftBukkit start ++ CraftPlayer bukkitPlayer = entityplayer.getBukkitEntity(); ++ ++ // Ensure that player inventory is populated with its viewer ++ entityplayer.containerMenu.transferTo(entityplayer.containerMenu, bukkitPlayer); ++ ++ PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(bukkitPlayer, joinMessage); ++ cserver.getPluginManager().callEvent(playerJoinEvent); ++ ++ if (!entityplayer.connection.isAcceptingMessages()) { ++ return; + } + +- if (compoundTag != null && compoundTag.contains("RootVehicle", 10)) { +- CompoundTag compound = compoundTag.getCompound("RootVehicle"); +- Entity entity = EntityType.loadEntityRecursive( +- compound.getCompound("Entity"), serverLevel, entity2 -> !serverLevel.addWithUUID(entity2) ? null : entity2 +- ); ++ joinMessage = playerJoinEvent.getJoinMessage(); ++ ++ if (joinMessage != null && joinMessage.length() > 0) { ++ for (Component line : org.bukkit.craftbukkit.util.CraftChatMessage.fromString(joinMessage)) { ++ server.getPlayerList().broadcastSystemMessage(line, false); ++ } ++ } ++ // CraftBukkit end ++ ++ // CraftBukkit start - sendAll above replaced with this loop ++ ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer)); ++ ++ for (int i = 0; i < this.players.size(); ++i) { ++ ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i); ++ ++ if (entityplayer1.getBukkitEntity().canSee(bukkitPlayer)) { ++ entityplayer1.connection.send(packet); ++ } ++ ++ if (!bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { ++ continue; ++ } ++ ++ entityplayer.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer1))); ++ } ++ entityplayer.sentListPacket = true; ++ // CraftBukkit end ++ ++ entityplayer.getEntityData().refresh(entityplayer); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn ++ ++ this.sendLevelInfo(entityplayer, worldserver1); ++ ++ // CraftBukkit start - Only add if the player wasn't moved in the event ++ if (entityplayer.level() == worldserver1 && !worldserver1.players().contains(entityplayer)) { ++ worldserver1.addNewPlayer(entityplayer); ++ this.server.getCustomBossEvents().onPlayerConnect(entityplayer); ++ } ++ ++ worldserver1 = entityplayer.serverLevel(); // CraftBukkit - Update in case join event changed it ++ // CraftBukkit end ++ Iterator iterator = entityplayer.getActiveEffects().iterator(); ++ ++ while (iterator.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); ++ ++ playerconnection.send(new ClientboundUpdateMobEffectPacket(entityplayer.getId(), mobeffect)); ++ } ++ ++ if (nbttagcompound != null && nbttagcompound.contains("RootVehicle", 10)) { ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("RootVehicle"); ++ // CraftBukkit start ++ ServerLevel finalWorldServer = worldserver1; ++ Entity entity = EntityType.loadEntityRecursive(nbttagcompound1.getCompound("Entity"), finalWorldServer, (entity1) -> { ++ return !finalWorldServer.addWithUUID(entity1) ? null : entity1; ++ // CraftBukkit end ++ }); ++ + if (entity != null) { +- UUID uUID; +- if (compound.hasUUID("Attach")) { +- uUID = compound.getUUID("Attach"); ++ UUID uuid; ++ ++ if (nbttagcompound1.hasUUID("Attach")) { ++ uuid = nbttagcompound1.getUUID("Attach"); + } else { +- uUID = null; ++ uuid = null; + } + +- if (entity.getUUID().equals(uUID)) { +- serverPlayer.startRiding(entity, true); ++ Iterator iterator1; ++ Entity entity1; ++ ++ if (entity.getUUID().equals(uuid)) { ++ entityplayer.startRiding(entity, true); + } else { +- for (Entity entity1 : entity.getIndirectPassengers()) { +- if (entity1.getUUID().equals(uUID)) { +- serverPlayer.startRiding(entity1, true); ++ iterator1 = entity.getIndirectPassengers().iterator(); ++ ++ while (iterator1.hasNext()) { ++ entity1 = (Entity) iterator1.next(); ++ if (entity1.getUUID().equals(uuid)) { ++ entityplayer.startRiding(entity1, true); + break; + } + } + } + +- if (!serverPlayer.isPassenger()) { +- LOGGER.warn("Couldn't reattach entity to player"); ++ if (!entityplayer.isPassenger()) { ++ PlayerList.LOGGER.warn("Couldn't reattach entity to player"); + entity.discard(); ++ iterator1 = entity.getIndirectPassengers().iterator(); + +- for (Entity entity1x : entity.getIndirectPassengers()) { +- entity1x.discard(); ++ while (iterator1.hasNext()) { ++ entity1 = (Entity) iterator1.next(); ++ entity1.discard(); + } + } + } + } + +- serverPlayer.initInventoryMenu(); ++ entityplayer.initInventoryMenu(); ++ // CraftBukkit - Moved from above, added world ++ PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", entityplayer.getName().getString(), s1, entityplayer.getId(), worldserver1.serverLevelData.getLevelName(), entityplayer.getX(), entityplayer.getY(), entityplayer.getZ()); + } + +- protected void updateEntireScoreboard(ServerScoreboard scoreboard, ServerPlayer player) { ++ public void updateEntireScoreboard(ServerScoreboard scoreboard, ServerPlayer player) { + Set set = Sets.newHashSet(); ++ Iterator iterator = scoreboard.getPlayerTeams().iterator(); + +- for (PlayerTeam playerTeam : scoreboard.getPlayerTeams()) { +- player.connection.send(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, true)); ++ while (iterator.hasNext()) { ++ PlayerTeam scoreboardteam = (PlayerTeam) iterator.next(); ++ ++ player.connection.send(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(scoreboardteam, true)); + } + +- for (DisplaySlot displaySlot : DisplaySlot.values()) { +- Objective displayObjective = scoreboard.getDisplayObjective(displaySlot); +- if (displayObjective != null && !set.contains(displayObjective)) { +- for (Packet packet : scoreboard.getStartTrackingPackets(displayObjective)) { ++ DisplaySlot[] adisplayslot = DisplaySlot.values(); ++ int i = adisplayslot.length; ++ ++ for (int j = 0; j < i; ++j) { ++ DisplaySlot displayslot = adisplayslot[j]; ++ Objective scoreboardobjective = scoreboard.getDisplayObjective(displayslot); ++ ++ if (scoreboardobjective != null && !set.contains(scoreboardobjective)) { ++ List> list = scoreboard.getStartTrackingPackets(scoreboardobjective); ++ Iterator iterator1 = list.iterator(); ++ ++ while (iterator1.hasNext()) { ++ Packet packet = (Packet) iterator1.next(); ++ + player.connection.send(packet); + } + +- set.add(displayObjective); ++ set.add(scoreboardobjective); + } + } ++ + } + + public void addWorldborderListener(ServerLevel level) { ++ if (playerIo != null) return; // CraftBukkit + level.getWorldBorder().addListener(new BorderChangeListener() { + @Override + public void onBorderSizeSet(WorldBorder border, double size) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderSizePacket(border)); ++ PlayerList.this.broadcastAll(new ClientboundSetBorderSizePacket(border), border.world); // CraftBukkit + } + + @Override +- public void onBorderSizeLerping(WorldBorder border, double oldSize, double newSize, long time) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderLerpSizePacket(border)); ++ public void onBorderSizeLerping(WorldBorder border, double oldSize, double d1, long newSize) { ++ PlayerList.this.broadcastAll(new ClientboundSetBorderLerpSizePacket(border), border.world); // CraftBukkit + } + + @Override +- public void onBorderCenterSet(WorldBorder border, double x, double z) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderCenterPacket(border)); ++ public void onBorderCenterSet(WorldBorder border, double x, double d1) { ++ PlayerList.this.broadcastAll(new ClientboundSetBorderCenterPacket(border), border.world); // CraftBukkit + } + + @Override + public void onBorderSetWarningTime(WorldBorder border, int warningTime) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDelayPacket(border)); ++ PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDelayPacket(border), border.world); // CraftBukkit + } + + @Override + public void onBorderSetWarningBlocks(WorldBorder border, int warningBlocks) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDistancePacket(border)); ++ PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDistancePacket(border), border.world); // CraftBukkit + } + + @Override +- public void onBorderSetDamagePerBlock(WorldBorder border, double damagePerBlock) { +- } ++ public void onBorderSetDamagePerBlock(WorldBorder border, double damagePerBlock) {} + + @Override +- public void onBorderSetDamageSafeZOne(WorldBorder border, double damageSafeZone) { +- } ++ public void onBorderSetDamageSafeZOne(WorldBorder border, double damageSafeZone) {} + }); + } + + @Nullable + public CompoundTag load(ServerPlayer player) { +- CompoundTag loadedPlayerTag = this.server.getWorldData().getLoadedPlayerTag(); +- CompoundTag compoundTag; +- if (this.server.isSingleplayerOwner(player.getGameProfile()) && loadedPlayerTag != null) { +- compoundTag = loadedPlayerTag; +- player.load(loadedPlayerTag); +- LOGGER.debug("loading single player"); ++ CompoundTag nbttagcompound = this.server.getWorldData().getLoadedPlayerTag(); ++ CompoundTag nbttagcompound1; ++ ++ if (this.server.isSingleplayerOwner(player.getGameProfile()) && nbttagcompound != null) { ++ nbttagcompound1 = nbttagcompound; ++ player.load(nbttagcompound); ++ PlayerList.LOGGER.debug("loading single player"); + } else { +- compoundTag = this.playerIo.load(player); ++ nbttagcompound1 = this.playerIo.load(player); + } + +- return compoundTag; ++ return nbttagcompound1; + } + + protected void save(ServerPlayer player) { ++ if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit + this.playerIo.save(player); +- ServerStatsCounter serverStatsCounter = this.stats.get(player.getUUID()); +- if (serverStatsCounter != null) { +- serverStatsCounter.save(); ++ ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit ++ ++ if (serverstatisticmanager != null) { ++ serverstatisticmanager.save(); + } + +- PlayerAdvancements playerAdvancements = this.advancements.get(player.getUUID()); +- if (playerAdvancements != null) { +- playerAdvancements.save(); ++ PlayerAdvancements advancementdataplayer = (PlayerAdvancements) player.getAdvancements(); // CraftBukkit ++ ++ if (advancementdataplayer != null) { ++ advancementdataplayer.save(); + } ++ + } + +- public void remove(ServerPlayer player) { +- ServerLevel serverLevel = player.serverLevel(); +- player.awardStat(Stats.LEAVE_GAME); +- this.save(player); +- if (player.isPassenger()) { +- Entity rootVehicle = player.getRootVehicle(); +- if (rootVehicle.hasExactlyOnePlayerPassenger()) { +- LOGGER.debug("Removing player mount"); +- player.stopRiding(); +- rootVehicle.getPassengersAndSelf().forEach(entity -> entity.setRemoved(Entity.RemovalReason.UNLOADED_WITH_PLAYER)); ++ public String remove(ServerPlayer entityplayer) { // CraftBukkit - return string ++ ServerLevel worldserver = entityplayer.serverLevel(); ++ ++ entityplayer.awardStat(Stats.LEAVE_GAME); ++ ++ // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it ++ // See SPIGOT-5799, SPIGOT-6145 ++ if (entityplayer.containerMenu != entityplayer.inventoryMenu) { ++ entityplayer.closeContainer(); ++ } ++ ++ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(entityplayer.getBukkitEntity(), entityplayer.kickLeaveMessage != null ? entityplayer.kickLeaveMessage : "\u00A7e" + entityplayer.getScoreboardName() + " left the game"); ++ cserver.getPluginManager().callEvent(playerQuitEvent); ++ entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); ++ ++ entityplayer.doTick(); // SPIGOT-924 ++ // CraftBukkit end ++ ++ this.save(entityplayer); ++ if (entityplayer.isPassenger()) { ++ Entity entity = entityplayer.getRootVehicle(); ++ ++ if (entity.hasExactlyOnePlayerPassenger()) { ++ PlayerList.LOGGER.debug("Removing player mount"); ++ entityplayer.stopRiding(); ++ entity.getPassengersAndSelf().forEach((entity1) -> { ++ entity1.setRemoved(Entity.RemovalReason.UNLOADED_WITH_PLAYER); ++ }); + } + } + +- player.unRide(); +- serverLevel.removePlayerImmediately(player, Entity.RemovalReason.UNLOADED_WITH_PLAYER); +- player.getAdvancements().stopListening(); +- this.players.remove(player); +- this.server.getCustomBossEvents().onPlayerDisconnect(player); +- UUID uUID = player.getUUID(); +- ServerPlayer serverPlayer = this.playersByUUID.get(uUID); +- if (serverPlayer == player) { +- this.playersByUUID.remove(uUID); +- this.stats.remove(uUID); +- this.advancements.remove(uUID); ++ entityplayer.unRide(); ++ worldserver.removePlayerImmediately(entityplayer, Entity.RemovalReason.UNLOADED_WITH_PLAYER); ++ entityplayer.getAdvancements().stopListening(); ++ this.players.remove(entityplayer); ++ this.server.getCustomBossEvents().onPlayerDisconnect(entityplayer); ++ UUID uuid = entityplayer.getUUID(); ++ ServerPlayer entityplayer1 = (ServerPlayer) this.playersByUUID.get(uuid); ++ ++ if (entityplayer1 == entityplayer) { ++ this.playersByUUID.remove(uuid); ++ // CraftBukkit start ++ // this.stats.remove(uuid); ++ // this.advancements.remove(uuid); ++ // CraftBukkit end + } + +- this.broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(player.getUUID()))); ++ // CraftBukkit start ++ // this.broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID()))); ++ ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID())); ++ for (int i = 0; i < players.size(); i++) { ++ ServerPlayer entityplayer2 = (ServerPlayer) this.players.get(i); ++ ++ if (entityplayer2.getBukkitEntity().canSee(entityplayer.getBukkitEntity())) { ++ entityplayer2.connection.send(packet); ++ } else { ++ entityplayer2.getBukkitEntity().onEntityRemove(entityplayer); ++ } ++ } ++ // This removes the scoreboard (and player reference) for the specific player in the manager ++ cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); ++ // CraftBukkit end ++ ++ return playerQuitEvent.getQuitMessage(); // CraftBukkit + } + +- @Nullable +- public Component canPlayerLogin(SocketAddress socketAddress, GameProfile gameProfile) { +- if (this.bans.isBanned(gameProfile)) { +- UserBanListEntry userBanListEntry = this.bans.get(gameProfile); +- MutableComponent mutableComponent = Component.translatable("multiplayer.disconnect.banned.reason", userBanListEntry.getReason()); +- if (userBanListEntry.getExpires() != null) { +- mutableComponent.append( +- Component.translatable("multiplayer.disconnect.banned.expiration", BAN_DATE_FORMAT.format(userBanListEntry.getExpires())) +- ); ++ // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer ++ public ServerPlayer canPlayerLogin(ServerLoginPacketListenerImpl loginlistener, GameProfile gameprofile) { ++ MutableComponent ichatmutablecomponent; ++ ++ // Moved from processLogin ++ UUID uuid = gameprofile.getId(); ++ List list = Lists.newArrayList(); ++ ++ ServerPlayer entityplayer; ++ ++ for (int i = 0; i < this.players.size(); ++i) { ++ entityplayer = (ServerPlayer) this.players.get(i); ++ if (entityplayer.getUUID().equals(uuid)) { ++ list.add(entityplayer); + } ++ } + +- return mutableComponent; +- } else if (!this.isWhiteListed(gameProfile)) { +- return Component.translatable("multiplayer.disconnect.not_whitelisted"); +- } else if (this.ipBans.isBanned(socketAddress)) { +- IpBanListEntry ipBanListEntry = this.ipBans.get(socketAddress); +- MutableComponent mutableComponent = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipBanListEntry.getReason()); +- if (ipBanListEntry.getExpires() != null) { +- mutableComponent.append( +- Component.translatable("multiplayer.disconnect.banned_ip.expiration", BAN_DATE_FORMAT.format(ipBanListEntry.getExpires())) +- ); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ entityplayer = (ServerPlayer) iterator.next(); ++ save(entityplayer); // CraftBukkit - Force the player's inventory to be saved ++ entityplayer.connection.disconnect(Component.translatable("multiplayer.disconnect.duplicate_login")); ++ } ++ ++ // Instead of kicking then returning, we need to store the kick reason ++ // in the event, check with plugins to see if it's ok, and THEN kick ++ // depending on the outcome. ++ SocketAddress socketaddress = loginlistener.connection.getRemoteAddress(); ++ ++ ServerPlayer entity = new ServerPlayer(this.server, this.server.getLevel(Level.OVERWORLD), gameprofile, ClientInformation.createDefault()); ++ Player player = entity.getBukkitEntity(); ++ PlayerLoginEvent event = new PlayerLoginEvent(player, loginlistener.connection.hostname, ((java.net.InetSocketAddress) socketaddress).getAddress()); ++ ++ if (getBans().isBanned(gameprofile) && !getBans().get(gameprofile).hasExpired()) { ++ UserBanListEntry gameprofilebanentry = (UserBanListEntry) this.bans.get(gameprofile); ++ ++ ichatmutablecomponent = Component.translatable("multiplayer.disconnect.banned.reason", gameprofilebanentry.getReason()); ++ if (gameprofilebanentry.getExpires() != null) { ++ ichatmutablecomponent.append((Component) Component.translatable("multiplayer.disconnect.banned.expiration", PlayerList.BAN_DATE_FORMAT.format(gameprofilebanentry.getExpires()))); + } + +- return mutableComponent; ++ // return chatmessage; ++ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(ichatmutablecomponent)); ++ } else if (!this.isWhiteListed(gameprofile)) { ++ ichatmutablecomponent = Component.translatable("multiplayer.disconnect.not_whitelisted"); ++ event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, CraftChatMessage.fromComponent(ichatmutablecomponent)); ++ } else if (getIpBans().isBanned(socketaddress) && !getIpBans().get(socketaddress).hasExpired()) { ++ IpBanListEntry ipbanentry = this.ipBans.get(socketaddress); ++ ++ ichatmutablecomponent = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipbanentry.getReason()); ++ if (ipbanentry.getExpires() != null) { ++ ichatmutablecomponent.append((Component) Component.translatable("multiplayer.disconnect.banned_ip.expiration", PlayerList.BAN_DATE_FORMAT.format(ipbanentry.getExpires()))); ++ } ++ ++ // return chatmessage; ++ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(ichatmutablecomponent)); + } else { +- return this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameProfile) +- ? Component.translatable("multiplayer.disconnect.server_full") +- : null; ++ // return this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile) ? IChatBaseComponent.translatable("multiplayer.disconnect.server_full") : null; ++ if (this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile)) { ++ event.disallow(PlayerLoginEvent.Result.KICK_FULL, "The server is full"); ++ } + } ++ ++ cserver.getPluginManager().callEvent(event); ++ if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) { ++ loginlistener.disconnect(event.getKickMessage()); ++ return null; ++ } ++ return entity; + } + +- public ServerPlayer getPlayerForLogin(GameProfile gameProfile, ClientInformation clientInformation) { +- return new ServerPlayer(this.server, this.server.overworld(), gameProfile, clientInformation); ++ // CraftBukkit start - added EntityPlayer ++ public ServerPlayer getPlayerForLogin(GameProfile gameprofile, ClientInformation clientinformation, ServerPlayer player) { ++ player.updateOptions(clientinformation); ++ return player; ++ // CraftBukkit end + } + +- public boolean disconnectAllPlayersWithProfile(GameProfile gameProfile) { +- UUID id = gameProfile.getId(); +- Set set = Sets.newIdentityHashSet(); ++ public boolean disconnectAllPlayersWithProfile(GameProfile gameprofile, ServerPlayer player) { // CraftBukkit - added EntityPlayer ++ /* CraftBukkit startMoved up ++ UUID uuid = gameprofile.getId(); ++ Set set = Sets.newIdentityHashSet(); ++ Iterator iterator = this.players.iterator(); + +- for (ServerPlayer serverPlayer : this.players) { +- if (serverPlayer.getUUID().equals(id)) { +- set.add(serverPlayer); ++ while (iterator.hasNext()) { ++ EntityPlayer entityplayer = (EntityPlayer) iterator.next(); ++ ++ if (entityplayer.getUUID().equals(uuid)) { ++ set.add(entityplayer); + } + } + +- ServerPlayer serverPlayer1 = this.playersByUUID.get(gameProfile.getId()); +- if (serverPlayer1 != null) { +- set.add(serverPlayer1); ++ EntityPlayer entityplayer1 = (EntityPlayer) this.playersByUUID.get(gameprofile.getId()); ++ ++ if (entityplayer1 != null) { ++ set.add(entityplayer1); + } + +- for (ServerPlayer serverPlayer2 : set) { +- serverPlayer2.connection.disconnect(DUPLICATE_LOGIN_DISCONNECT_MESSAGE); ++ Iterator iterator1 = set.iterator(); ++ ++ while (iterator1.hasNext()) { ++ EntityPlayer entityplayer2 = (EntityPlayer) iterator1.next(); ++ ++ entityplayer2.connection.disconnect(PlayerList.DUPLICATE_LOGIN_DISCONNECT_MESSAGE); + } + + return !set.isEmpty(); ++ */ ++ return player == null; ++ // CraftBukkit end + } + +- public ServerPlayer respawn(ServerPlayer player, boolean keepEverything) { +- this.players.remove(player); +- player.serverLevel().removePlayerImmediately(player, Entity.RemovalReason.DISCARDED); +- BlockPos respawnPosition = player.getRespawnPosition(); +- float respawnAngle = player.getRespawnAngle(); +- boolean isRespawnForced = player.isRespawnForced(); +- ServerLevel level = this.server.getLevel(player.getRespawnDimension()); +- Optional optional; +- if (level != null && respawnPosition != null) { +- optional = Player.findRespawnPositionAndUseSpawnBlock(level, respawnPosition, respawnAngle, isRespawnForced, keepEverything); ++ // CraftBukkit start ++ public ServerPlayer respawn(ServerPlayer entityplayer, boolean flag, RespawnReason reason) { ++ return this.respawn(entityplayer, this.server.getLevel(entityplayer.getRespawnDimension()), flag, null, true, reason); ++ } ++ ++ public ServerPlayer respawn(ServerPlayer entityplayer, ServerLevel worldserver, boolean flag, Location location, boolean avoidSuffocation, RespawnReason reason) { ++ entityplayer.stopRiding(); // CraftBukkit ++ this.players.remove(entityplayer); ++ entityplayer.serverLevel().removePlayerImmediately(entityplayer, Entity.RemovalReason.DISCARDED); ++ BlockPos blockposition = entityplayer.getRespawnPosition(); ++ float f = entityplayer.getRespawnAngle(); ++ boolean flag1 = entityplayer.isRespawnForced(); ++ /* CraftBukkit start ++ WorldServer worldserver = this.server.getLevel(entityplayer.getRespawnDimension()); ++ Optional optional; ++ ++ if (worldserver != null && blockposition != null) { ++ optional = EntityHuman.findRespawnPositionAndUseSpawnBlock(worldserver, blockposition, f, flag1, flag); + } else { + optional = Optional.empty(); + } + +- ServerLevel serverLevel = level != null && optional.isPresent() ? level : this.server.overworld(); +- ServerPlayer serverPlayer = new ServerPlayer(this.server, serverLevel, player.getGameProfile(), player.clientInformation()); +- serverPlayer.connection = player.connection; +- serverPlayer.restoreFrom(player, keepEverything); +- serverPlayer.setId(player.getId()); +- serverPlayer.setMainArm(player.getMainArm()); ++ WorldServer worldserver1 = worldserver != null && optional.isPresent() ? worldserver : this.server.overworld(); ++ EntityPlayer entityplayer1 = new EntityPlayer(this.server, worldserver1, entityplayer.getGameProfile(), entityplayer.clientInformation()); ++ // */ ++ ServerPlayer entityplayer1 = entityplayer; ++ org.bukkit.World fromWorld = entityplayer.getBukkitEntity().getWorld(); ++ entityplayer.wonGame = false; ++ // CraftBukkit end + +- for (String string : player.getTags()) { +- serverPlayer.addTag(string); ++ entityplayer1.connection = entityplayer.connection; ++ entityplayer1.restoreFrom(entityplayer, flag); ++ entityplayer1.setId(entityplayer.getId()); ++ entityplayer1.setMainArm(entityplayer.getMainArm()); ++ Iterator iterator = entityplayer.getTags().iterator(); ++ ++ while (iterator.hasNext()) { ++ String s = (String) iterator.next(); ++ ++ entityplayer1.addTag(s); + } + +- boolean flag = false; +- if (optional.isPresent()) { +- BlockState blockState = serverLevel.getBlockState(respawnPosition); +- boolean isRespawnAnchor = blockState.is(Blocks.RESPAWN_ANCHOR); +- Vec3 vec3 = optional.get(); +- float f; +- if (!blockState.is(BlockTags.BEDS) && !isRespawnAnchor) { +- f = respawnAngle; +- } else { +- Vec3 vec31 = Vec3.atBottomCenterOf(respawnPosition).subtract(vec3).normalize(); +- f = (float)Mth.wrapDegrees(Mth.atan2(vec31.z, vec31.x) * 180.0F / (float)Math.PI - 90.0); ++ boolean flag2 = false; ++ ++ // CraftBukkit start - fire PlayerRespawnEvent ++ if (location == null) { ++ boolean isBedSpawn = false; ++ ServerLevel worldserver1 = this.server.getLevel(entityplayer.getRespawnDimension()); ++ if (worldserver1 != null) { ++ Optional optional; ++ ++ if (blockposition != null) { ++ optional = net.minecraft.world.entity.player.Player.findRespawnPositionAndUseSpawnBlock(worldserver1, blockposition, f, flag1, flag); ++ } else { ++ optional = Optional.empty(); ++ } ++ ++ if (optional.isPresent()) { ++ IBlockData iblockdata = worldserver1.getBlockState(blockposition); ++ boolean flag3 = iblockdata.is(Blocks.RESPAWN_ANCHOR); ++ Vec3 vec3d = (Vec3) optional.get(); ++ float f1; ++ ++ if (!iblockdata.is(BlockTags.BEDS) && !flag3) { ++ f1 = f; ++ } else { ++ Vec3 vec3d1 = Vec3.atBottomCenterOf(blockposition).subtract(vec3d).normalize(); ++ ++ f1 = (float) Mth.wrapDegrees(Mth.atan2(vec3d1.z, vec3d1.x) * 57.2957763671875D - 90.0D); ++ } ++ ++ // entityplayer1.setRespawnPosition(worldserver1.dimension(), blockposition, f, flag1, false); // CraftBukkit - not required, just copies old location into reused entity ++ flag2 = !flag && flag3; ++ isBedSpawn = true; ++ location = CraftLocation.toBukkit(vec3d, worldserver1.getWorld(), f1, 0.0F); ++ } else if (blockposition != null) { ++ entityplayer1.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F)); ++ entityplayer1.setRespawnPosition(null, null, 0f, false, false, PlayerSpawnChangeEvent.Cause.RESET); // CraftBukkit - SPIGOT-5988: Clear respawn location when obstructed ++ } + } + +- serverPlayer.moveTo(vec3.x, vec3.y, vec3.z, f, 0.0F); +- serverPlayer.setRespawnPosition(serverLevel.dimension(), respawnPosition, respawnAngle, isRespawnForced, false); +- flag = !keepEverything && isRespawnAnchor; +- } else if (respawnPosition != null) { +- serverPlayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F)); ++ if (location == null) { ++ worldserver1 = this.server.getLevel(Level.OVERWORLD); ++ blockposition = entityplayer1.getSpawnPoint(worldserver1); ++ location = CraftLocation.toBukkit(blockposition, worldserver1.getWorld()).add(0.5F, 0.1F, 0.5F); ++ } ++ ++ Player respawnPlayer = entityplayer1.getBukkitEntity(); ++ PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !flag2, flag2, reason); ++ cserver.getPluginManager().callEvent(respawnEvent); ++ ++ location = respawnEvent.getRespawnLocation(); ++ if (!flag) entityplayer.reset(); // SPIGOT-4785 ++ } else { ++ location.setWorld(worldserver.getWorld()); + } ++ ServerLevel worldserver1 = ((CraftWorld) location.getWorld()).getHandle(); ++ entityplayer1.spawnIn(worldserver1); ++ entityplayer1.unsetRemoved(); ++ entityplayer1.setShiftKeyDown(false); ++ entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + +- while (!serverLevel.noCollision(serverPlayer) && serverPlayer.getY() < (double)serverLevel.getMaxBuildHeight()) { +- serverPlayer.setPos(serverPlayer.getX(), serverPlayer.getY() + 1.0, serverPlayer.getZ()); ++ while (avoidSuffocation && !worldserver1.noCollision((Entity) entityplayer1) && entityplayer1.getY() < (double) worldserver1.getMaxBuildHeight()) { ++ // CraftBukkit end ++ entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); + } + +- byte b = (byte)(keepEverything ? 1 : 0); +- ServerLevel serverLevel1 = serverPlayer.serverLevel(); +- LevelData levelData = serverLevel1.getLevelData(); +- serverPlayer.connection.send(new ClientboundRespawnPacket(serverPlayer.createCommonSpawnInfo(serverLevel1), b)); +- serverPlayer.connection.teleport(serverPlayer.getX(), serverPlayer.getY(), serverPlayer.getZ(), serverPlayer.getYRot(), serverPlayer.getXRot()); +- serverPlayer.connection.send(new ClientboundSetDefaultSpawnPositionPacket(serverLevel.getSharedSpawnPos(), serverLevel.getSharedSpawnAngle())); +- serverPlayer.connection.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked())); +- serverPlayer.connection +- .send(new ClientboundSetExperiencePacket(serverPlayer.experienceProgress, serverPlayer.totalExperience, serverPlayer.experienceLevel)); +- this.sendLevelInfo(serverPlayer, serverLevel); +- this.sendPlayerPermissionLevel(serverPlayer); +- serverLevel.addRespawnedPlayer(serverPlayer); +- this.players.add(serverPlayer); +- this.playersByUUID.put(serverPlayer.getUUID(), serverPlayer); +- serverPlayer.initInventoryMenu(); +- serverPlayer.setHealth(serverPlayer.getHealth()); +- if (flag) { +- serverPlayer.connection +- .send( +- new ClientboundSoundPacket( +- SoundEvents.RESPAWN_ANCHOR_DEPLETE, +- SoundSource.BLOCKS, +- (double)respawnPosition.getX(), +- (double)respawnPosition.getY(), +- (double)respawnPosition.getZ(), +- 1.0F, +- 1.0F, +- serverLevel.getRandom().nextLong() +- ) +- ); ++ int i = flag ? 1 : 0; ++ ServerLevel worldserver2 = entityplayer1.serverLevel(); ++ LevelData worlddata = worldserver2.getLevelData(); ++ ++ entityplayer1.connection.send(new ClientboundRespawnPacket(entityplayer1.createCommonSpawnInfo(worldserver2), (byte) i)); ++ entityplayer1.connection.teleport(CraftLocation.toBukkit(entityplayer1.position(), worldserver2.getWorld(), entityplayer1.getYRot(), entityplayer1.getXRot())); // CraftBukkit ++ entityplayer1.connection.send(new ClientboundSetDefaultSpawnPositionPacket(worldserver1.getSharedSpawnPos(), worldserver1.getSharedSpawnAngle())); ++ entityplayer1.connection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); ++ entityplayer1.connection.send(new ClientboundSetExperiencePacket(entityplayer1.experienceProgress, entityplayer1.totalExperience, entityplayer1.experienceLevel)); ++ this.sendLevelInfo(entityplayer1, worldserver1); ++ this.sendPlayerPermissionLevel(entityplayer1); ++ if (!entityplayer.connection.isDisconnected()) { ++ worldserver1.addRespawnedPlayer(entityplayer1); ++ this.players.add(entityplayer1); ++ this.playersByUUID.put(entityplayer1.getUUID(), entityplayer1); + } ++ // entityplayer1.initInventoryMenu(); ++ entityplayer1.setHealth(entityplayer1.getHealth()); ++ if (flag2) { ++ entityplayer1.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), 1.0F, 1.0F, worldserver1.getRandom().nextLong())); ++ } ++ // Added from changeDimension ++ sendAllPlayerInfo(entityplayer); // Update health, etc... ++ entityplayer.onUpdateAbilities(); ++ for (MobEffectInstance mobEffect : entityplayer.getActiveEffects()) { ++ entityplayer.connection.send(new ClientboundUpdateMobEffectPacket(entityplayer.getId(), mobEffect)); ++ } + +- return serverPlayer; ++ // Fire advancement trigger ++ entityplayer.triggerDimensionChangeTriggers(((CraftWorld) fromWorld).getHandle()); ++ ++ // Don't fire on respawn ++ if (fromWorld != location.getWorld()) { ++ PlayerChangedWorldEvent event = new PlayerChangedWorldEvent(entityplayer.getBukkitEntity(), fromWorld); ++ server.server.getPluginManager().callEvent(event); ++ } ++ ++ // Save player file again if they were disconnected ++ if (entityplayer.connection.isDisconnected()) { ++ this.save(entityplayer); ++ } ++ // CraftBukkit end ++ return entityplayer1; + } + + public void sendPlayerPermissionLevel(ServerPlayer player) { +- GameProfile gameProfile = player.getGameProfile(); +- int profilePermissions = this.server.getProfilePermissions(gameProfile); +- this.sendPlayerPermissionLevel(player, profilePermissions); ++ GameProfile gameprofile = player.getGameProfile(); ++ int i = this.server.getProfilePermissions(gameprofile); ++ ++ this.sendPlayerPermissionLevel(player, i); + } + + public void tick() { + if (++this.sendAllPlayerInfoIn > 600) { +- this.broadcastAll(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY), this.players)); ++ // CraftBukkit start ++ for (int i = 0; i < this.players.size(); ++i) { ++ final ServerPlayer target = (ServerPlayer) this.players.get(i); ++ ++ target.connection.send(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY), this.players.stream().filter(new Predicate() { ++ @Override ++ public boolean test(ServerPlayer input) { ++ return target.getBukkitEntity().canSee(input.getBukkitEntity()); ++ } ++ }).collect(Collectors.toList()))); ++ } ++ // CraftBukkit end + this.sendAllPlayerInfoIn = 0; + } ++ + } + + public void broadcastAll(Packet packet) { +- for (ServerPlayer serverPlayer : this.players) { +- serverPlayer.connection.send(packet); ++ Iterator iterator = this.players.iterator(); ++ ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ entityplayer.connection.send(packet); + } ++ + } + ++ // CraftBukkit start - add a world/entity limited version ++ public void broadcastAll(Packet packet, net.minecraft.world.entity.player.Player entityhuman) { ++ for (int i = 0; i < this.players.size(); ++i) { ++ ServerPlayer entityplayer = this.players.get(i); ++ if (entityhuman != null && !entityplayer.getBukkitEntity().canSee(entityhuman.getBukkitEntity())) { ++ continue; ++ } ++ ((ServerPlayer) this.players.get(i)).connection.send(packet); ++ } ++ } ++ ++ public void broadcastAll(Packet packet, Level world) { ++ for (int i = 0; i < world.players().size(); ++i) { ++ ((ServerPlayer) world.players().get(i)).connection.send(packet); ++ } ++ ++ } ++ // CraftBukkit end ++ + public void broadcastAll(Packet packet, ResourceKey dimension) { +- for (ServerPlayer serverPlayer : this.players) { +- if (serverPlayer.level().dimension() == dimension) { +- serverPlayer.connection.send(packet); ++ Iterator iterator = this.players.iterator(); ++ ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ if (entityplayer.level().dimension() == dimension) { ++ entityplayer.connection.send(packet); + } + } ++ + } + +- public void broadcastSystemToTeam(Player player, Component message) { +- Team team = player.getTeam(); +- if (team != null) { +- for (String string : team.getPlayers()) { +- ServerPlayer playerByName = this.getPlayerByName(string); +- if (playerByName != null && playerByName != player) { +- playerByName.sendSystemMessage(message); ++ public void broadcastSystemToTeam(net.minecraft.world.entity.player.Player player, Component message) { ++ PlayerTeam scoreboardteam = player.getTeam(); ++ ++ if (scoreboardteam != null) { ++ Collection collection = scoreboardteam.getPlayers(); ++ Iterator iterator = collection.iterator(); ++ ++ while (iterator.hasNext()) { ++ String s = (String) iterator.next(); ++ ServerPlayer entityplayer = this.getPlayerByName(s); ++ ++ if (entityplayer != null && entityplayer != player) { ++ entityplayer.sendSystemMessage(message); + } + } ++ + } + } + +- public void broadcastSystemToAllExceptTeam(Player player, Component message) { +- Team team = player.getTeam(); +- if (team == null) { ++ public void broadcastSystemToAllExceptTeam(net.minecraft.world.entity.player.Player player, Component message) { ++ PlayerTeam scoreboardteam = player.getTeam(); ++ ++ if (scoreboardteam == null) { + this.broadcastSystemMessage(message, false); + } else { +- for (int i = 0; i < this.players.size(); i++) { +- ServerPlayer serverPlayer = this.players.get(i); +- if (serverPlayer.getTeam() != team) { +- serverPlayer.sendSystemMessage(message); ++ for (int i = 0; i < this.players.size(); ++i) { ++ ServerPlayer entityplayer = (ServerPlayer) this.players.get(i); ++ ++ if (entityplayer.getTeam() != scoreboardteam) { ++ entityplayer.sendSystemMessage(message); + } + } ++ + } + } + + public String[] getPlayerNamesArray() { +- String[] strings = new String[this.players.size()]; ++ String[] astring = new String[this.players.size()]; + +- for (int i = 0; i < this.players.size(); i++) { +- strings[i] = this.players.get(i).getGameProfile().getName(); ++ for (int i = 0; i < this.players.size(); ++i) { ++ astring[i] = ((ServerPlayer) this.players.get(i)).getGameProfile().getName(); + } + +- return strings; ++ return astring; + } + + public UserBanList getBans() { +@@ -593,34 +939,40 @@ + + public void op(GameProfile profile) { + this.ops.add(new ServerOpListEntry(profile, this.server.getOperatorUserPermissionLevel(), this.ops.canBypassPlayerLimit(profile))); +- ServerPlayer player = this.getPlayer(profile.getId()); +- if (player != null) { +- this.sendPlayerPermissionLevel(player); ++ ServerPlayer entityplayer = this.getPlayer(profile.getId()); ++ ++ if (entityplayer != null) { ++ this.sendPlayerPermissionLevel(entityplayer); + } ++ + } + + public void deop(GameProfile profile) { +- this.ops.remove(profile); +- ServerPlayer player = this.getPlayer(profile.getId()); +- if (player != null) { +- this.sendPlayerPermissionLevel(player); ++ this.ops.remove(profile); // CraftBukkit - decompile error ++ ServerPlayer entityplayer = this.getPlayer(profile.getId()); ++ ++ if (entityplayer != null) { ++ this.sendPlayerPermissionLevel(entityplayer); + } ++ + } + + private void sendPlayerPermissionLevel(ServerPlayer player, int permLevel) { + if (player.connection != null) { +- byte b; ++ byte b0; ++ + if (permLevel <= 0) { +- b = 24; ++ b0 = 24; + } else if (permLevel >= 4) { +- b = 28; ++ b0 = 28; + } else { +- b = (byte)(24 + permLevel); ++ b0 = (byte) (24 + permLevel); + } + +- player.connection.send(new ClientboundEntityEventPacket(player, b)); ++ player.connection.send(new ClientboundEntityEventPacket(player, b0)); + } + ++ player.getBukkitEntity().recalculatePermissions(); // CraftBukkit + this.server.getCommands().sendCommands(player); + } + +@@ -629,43 +981,52 @@ + } + + public boolean isOp(GameProfile profile) { +- return this.ops.contains(profile) +- || this.server.isSingleplayerOwner(profile) && this.server.getWorldData().getAllowCommands() +- || this.allowCheatsForAllPlayers; ++ return this.ops.contains(profile) || this.server.isSingleplayerOwner(profile) && this.server.getWorldData().getAllowCommands() || this.allowCheatsForAllPlayers; + } + + @Nullable + public ServerPlayer getPlayerByName(String username) { +- int size = this.players.size(); ++ int i = this.players.size(); + +- for (int i = 0; i < size; i++) { +- ServerPlayer serverPlayer = this.players.get(i); +- if (serverPlayer.getGameProfile().getName().equalsIgnoreCase(username)) { +- return serverPlayer; ++ for (int j = 0; j < i; ++j) { ++ ServerPlayer entityplayer = (ServerPlayer) this.players.get(j); ++ ++ if (entityplayer.getGameProfile().getName().equalsIgnoreCase(username)) { ++ return entityplayer; + } + } + + return null; + } + +- public void broadcast(@Nullable Player except, double x, double y, double z, double radius, ResourceKey dimension, Packet packet) { +- for (int i = 0; i < this.players.size(); i++) { +- ServerPlayer serverPlayer = this.players.get(i); +- if (serverPlayer != except && serverPlayer.level().dimension() == dimension) { +- double d = x - serverPlayer.getX(); +- double d1 = y - serverPlayer.getY(); +- double d2 = z - serverPlayer.getZ(); +- if (d * d + d1 * d1 + d2 * d2 < radius * radius) { +- serverPlayer.connection.send(packet); ++ public void broadcast(@Nullable net.minecraft.world.entity.player.Player except, double x, double d1, double y, double d3, ResourceKey z, Packet packet) { ++ for (int i = 0; i < this.players.size(); ++i) { ++ ServerPlayer entityplayer = (ServerPlayer) this.players.get(i); ++ ++ // CraftBukkit start - Test if player receiving packet can see the source of the packet ++ if (except != null && !entityplayer.getBukkitEntity().canSee(except.getBukkitEntity())) { ++ continue; ++ } ++ // CraftBukkit end ++ ++ if (entityplayer != except && entityplayer.level().dimension() == z) { ++ double d4 = x - entityplayer.getX(); ++ double d5 = d1 - entityplayer.getY(); ++ double d6 = y - entityplayer.getZ(); ++ ++ if (d4 * d4 + d5 * d5 + d6 * d6 < d3 * d3) { ++ entityplayer.connection.send(packet); + } + } + } ++ + } + + public void saveAll() { +- for (int i = 0; i < this.players.size(); i++) { +- this.save(this.players.get(i)); ++ for (int i = 0; i < this.players.size(); ++i) { ++ this.save((ServerPlayer) this.players.get(i)); + } ++ + } + + public UserWhiteList getWhiteList() { +@@ -684,18 +1045,22 @@ + return this.ops.getUserList(); + } + +- public void reloadWhiteList() { +- } ++ public void reloadWhiteList() {} + + public void sendLevelInfo(ServerPlayer player, ServerLevel level) { +- WorldBorder worldBorder = this.server.overworld().getWorldBorder(); +- player.connection.send(new ClientboundInitializeBorderPacket(worldBorder)); ++ WorldBorder worldborder = player.level().getWorldBorder(); // CraftBukkit ++ ++ player.connection.send(new ClientboundInitializeBorderPacket(worldborder)); + player.connection.send(new ClientboundSetTimePacket(level.getGameTime(), level.getDayTime(), level.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); + player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(level.getSharedSpawnPos(), level.getSharedSpawnAngle())); + if (level.isRaining()) { +- player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.START_RAINING, 0.0F)); +- player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, level.getRainLevel(1.0F))); +- player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, level.getThunderLevel(1.0F))); ++ // CraftBukkit start - handle player weather ++ // entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.START_RAINING, 0.0F)); ++ // entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.RAIN_LEVEL_CHANGE, worldserver.getRainLevel(1.0F))); ++ // entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, worldserver.getThunderLevel(1.0F))); ++ player.setPlayerWeather(org.bukkit.WeatherType.DOWNFALL, false); ++ player.updateWeather(-level.rainLevel, level.rainLevel, -level.thunderLevel, level.thunderLevel); ++ // CraftBukkit end + } + + player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LEVEL_CHUNKS_LOAD_START, 0.0F)); +@@ -704,8 +1069,16 @@ + + public void sendAllPlayerInfo(ServerPlayer player) { + player.inventoryMenu.sendAllDataToRemote(); +- player.resetSentInfo(); ++ // entityplayer.resetSentInfo(); ++ player.getBukkitEntity().updateScaledHealth(); // CraftBukkit - Update scaled health on respawn and worldchange ++ player.getEntityData().refresh(player); // CraftBukkkit - SPIGOT-7218: sync metadata + player.connection.send(new ClientboundSetCarriedItemPacket(player.getInventory().selected)); ++ // CraftBukkit start - from GameRules ++ int i = player.level().getGameRules().getBoolean(GameRules.RULE_REDUCEDDEBUGINFO) ? 22 : 23; ++ player.connection.send(new ClientboundEntityEventPacket(player, (byte) i)); ++ float immediateRespawn = player.level().getGameRules().getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN) ? 1.0F: 0.0F; ++ player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.IMMEDIATE_RESPAWN, immediateRespawn)); ++ // CraftBukkit end + } + + public int getPlayerCount() { +@@ -726,10 +1099,13 @@ + + public List getPlayersWithAddress(String address) { + List list = Lists.newArrayList(); ++ Iterator iterator = this.players.iterator(); + +- for (ServerPlayer serverPlayer : this.players) { +- if (serverPlayer.getIpAddress().equals(address)) { +- list.add(serverPlayer); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ if (entityplayer.getIpAddress().equals(address)) { ++ list.add(entityplayer); + } + } + +@@ -758,111 +1134,153 @@ + } + + public void removeAll() { +- for (int i = 0; i < this.players.size(); i++) { +- this.players.get(i).connection.disconnect(Component.translatable("multiplayer.disconnect.server_shutdown")); ++ // CraftBukkit start - disconnect safely ++ for (ServerPlayer player : this.players) { ++ player.connection.disconnect(this.server.server.getShutdownMessage()); // CraftBukkit - add custom shutdown message + } ++ // CraftBukkit end ++ + } + ++ // CraftBukkit start ++ public void broadcastMessage(Component[] iChatBaseComponents) { ++ for (Component component : iChatBaseComponents) { ++ broadcastSystemMessage(component, false); ++ } ++ } ++ // CraftBukkit end ++ + public void broadcastSystemMessage(Component message, boolean bypassHiddenChat) { +- this.broadcastSystemMessage(message, serverPlayer -> message, bypassHiddenChat); ++ this.broadcastSystemMessage(message, (entityplayer) -> { ++ return message; ++ }, bypassHiddenChat); + } + + public void broadcastSystemMessage(Component serverMessage, Function playerMessageFactory, boolean bypassHiddenChat) { + this.server.sendSystemMessage(serverMessage); ++ Iterator iterator = this.players.iterator(); + +- for (ServerPlayer serverPlayer : this.players) { +- Component component = playerMessageFactory.apply(serverPlayer); +- if (component != null) { +- serverPlayer.sendSystemMessage(component, bypassHiddenChat); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ Component ichatbasecomponent1 = (Component) playerMessageFactory.apply(entityplayer); ++ ++ if (ichatbasecomponent1 != null) { ++ entityplayer.sendSystemMessage(ichatbasecomponent1, bypassHiddenChat); + } + } ++ + } + + public void broadcastChatMessage(PlayerChatMessage message, CommandSourceStack sender, ChatType.Bound boundChatType) { ++ Objects.requireNonNull(sender); + this.broadcastChatMessage(message, sender::shouldFilterMessageTo, sender.getPlayer(), boundChatType); + } + + public void broadcastChatMessage(PlayerChatMessage message, ServerPlayer sender, ChatType.Bound boundChatType) { ++ Objects.requireNonNull(sender); + this.broadcastChatMessage(message, sender::shouldFilterMessageTo, sender, boundChatType); + } + +- private void broadcastChatMessage( +- PlayerChatMessage message, Predicate shouldFilterMessageTo, @Nullable ServerPlayer sender, ChatType.Bound boundChatType +- ) { ++ private void broadcastChatMessage(PlayerChatMessage message, Predicate shouldFilterMessageTo, @Nullable ServerPlayer sender, ChatType.Bound boundChatType) { + boolean flag = this.verifyChatTrusted(message); ++ + this.server.logChatMessage(message.decoratedContent(), boundChatType, flag ? null : "Not Secure"); +- OutgoingChatMessage outgoingChatMessage = OutgoingChatMessage.create(message); ++ OutgoingChatMessage outgoingchatmessage = OutgoingChatMessage.create(message); + boolean flag1 = false; + +- for (ServerPlayer serverPlayer : this.players) { +- boolean flag2 = shouldFilterMessageTo.test(serverPlayer); +- serverPlayer.sendChatMessage(outgoingChatMessage, flag2, boundChatType); +- flag1 |= flag2 && message.isFullyFiltered(); ++ boolean flag2; ++ ++ for (Iterator iterator = this.players.iterator(); iterator.hasNext(); flag1 |= flag2 && message.isFullyFiltered()) { ++ ServerPlayer entityplayer1 = (ServerPlayer) iterator.next(); ++ ++ flag2 = shouldFilterMessageTo.test(entityplayer1); ++ entityplayer1.sendChatMessage(outgoingchatmessage, flag2, boundChatType); + } + + if (flag1 && sender != null) { +- sender.sendSystemMessage(CHAT_FILTERED_FULL); ++ sender.sendSystemMessage(PlayerList.CHAT_FILTERED_FULL); + } ++ + } + + private boolean verifyChatTrusted(PlayerChatMessage message) { + return message.hasSignature() && !message.hasExpiredServer(Instant.now()); + } + +- public ServerStatsCounter getPlayerStats(Player player) { +- UUID uUID = player.getUUID(); +- ServerStatsCounter serverStatsCounter = this.stats.get(uUID); +- if (serverStatsCounter == null) { ++ // CraftBukkit start ++ public ServerStatsCounter getPlayerStats(ServerPlayer entityhuman) { ++ ServerStatsCounter serverstatisticmanager = entityhuman.getStats(); ++ return serverstatisticmanager == null ? getPlayerStats(entityhuman.getUUID(), entityhuman.getDisplayName().getString()) : serverstatisticmanager; ++ } ++ ++ public ServerStatsCounter getPlayerStats(UUID uuid, String displayName) { ++ ServerPlayer entityhuman = this.getPlayer(uuid); ++ ServerStatsCounter serverstatisticmanager = entityhuman == null ? null : (ServerStatsCounter) entityhuman.getStats(); ++ // CraftBukkit end ++ ++ if (serverstatisticmanager == null) { + File file = this.server.getWorldPath(LevelResource.PLAYER_STATS_DIR).toFile(); +- File file1 = new File(file, uUID + ".json"); ++ File file1 = new File(file, uuid + ".json"); ++ + if (!file1.exists()) { +- File file2 = new File(file, player.getName().getString() + ".json"); ++ File file2 = new File(file, displayName + ".json"); // CraftBukkit + Path path = file2.toPath(); ++ + if (FileUtil.isPathNormalized(path) && FileUtil.isPathPortable(path) && path.startsWith(file.getPath()) && file2.isFile()) { + file2.renameTo(file1); + } + } + +- serverStatsCounter = new ServerStatsCounter(this.server, file1); +- this.stats.put(uUID, serverStatsCounter); ++ serverstatisticmanager = new ServerStatsCounter(this.server, file1); ++ // this.stats.put(uuid, serverstatisticmanager); // CraftBukkit + } + +- return serverStatsCounter; ++ return serverstatisticmanager; + } + + public PlayerAdvancements getPlayerAdvancements(ServerPlayer player) { +- UUID uUID = player.getUUID(); +- PlayerAdvancements playerAdvancements = this.advancements.get(uUID); +- if (playerAdvancements == null) { +- Path path = this.server.getWorldPath(LevelResource.PLAYER_ADVANCEMENTS_DIR).resolve(uUID + ".json"); +- playerAdvancements = new PlayerAdvancements(this.server.getFixerUpper(), this, this.server.getAdvancements(), path, player); +- this.advancements.put(uUID, playerAdvancements); ++ UUID uuid = player.getUUID(); ++ PlayerAdvancements advancementdataplayer = (PlayerAdvancements) player.getAdvancements(); // CraftBukkit ++ ++ if (advancementdataplayer == null) { ++ Path path = this.server.getWorldPath(LevelResource.PLAYER_ADVANCEMENTS_DIR).resolve(uuid + ".json"); ++ ++ advancementdataplayer = new PlayerAdvancements(this.server.getFixerUpper(), this, this.server.getAdvancements(), path, player); ++ // this.advancements.put(uuid, advancementdataplayer); // CraftBukkit + } + +- playerAdvancements.setPlayer(player); +- return playerAdvancements; ++ advancementdataplayer.setPlayer(player); ++ return advancementdataplayer; + } + + public void setViewDistance(int viewDistance) { + this.viewDistance = viewDistance; + this.broadcastAll(new ClientboundSetChunkCacheRadiusPacket(viewDistance)); ++ Iterator iterator = this.server.getAllLevels().iterator(); + +- for (ServerLevel serverLevel : this.server.getAllLevels()) { +- if (serverLevel != null) { +- serverLevel.getChunkSource().setViewDistance(viewDistance); ++ while (iterator.hasNext()) { ++ ServerLevel worldserver = (ServerLevel) iterator.next(); ++ ++ if (worldserver != null) { ++ worldserver.getChunkSource().setViewDistance(viewDistance); + } + } ++ + } + + public void setSimulationDistance(int simulationDistance) { + this.simulationDistance = simulationDistance; + this.broadcastAll(new ClientboundSetSimulationDistancePacket(simulationDistance)); ++ Iterator iterator = this.server.getAllLevels().iterator(); + +- for (ServerLevel serverLevel : this.server.getAllLevels()) { +- if (serverLevel != null) { +- serverLevel.getChunkSource().setSimulationDistance(simulationDistance); ++ while (iterator.hasNext()) { ++ ServerLevel worldserver = (ServerLevel) iterator.next(); ++ ++ if (worldserver != null) { ++ worldserver.getChunkSource().setSimulationDistance(simulationDistance); + } + } ++ + } + + public List getPlayers() { +@@ -871,7 +1289,7 @@ + + @Nullable + public ServerPlayer getPlayer(UUID playerUUID) { +- return this.playersByUUID.get(playerUUID); ++ return (ServerPlayer) this.playersByUUID.get(playerUUID); + } + + public boolean canBypassPlayerLimit(GameProfile profile) { +@@ -879,17 +1297,32 @@ + } + + public void reloadResources() { +- for (PlayerAdvancements playerAdvancements : this.advancements.values()) { +- playerAdvancements.reload(this.server.getAdvancements()); ++ // CraftBukkit start ++ /*Iterator iterator = this.advancements.values().iterator(); ++ ++ while (iterator.hasNext()) { ++ AdvancementDataPlayer advancementdataplayer = (AdvancementDataPlayer) iterator.next(); ++ ++ advancementdataplayer.reload(this.server.getAdvancements()); ++ }*/ ++ ++ for (ServerPlayer player : players) { ++ player.getAdvancements().reload(this.server.getAdvancements()); ++ player.getAdvancements().flushDirty(player); // CraftBukkit - trigger immediate flush of advancements + } ++ // CraftBukkit end + + this.broadcastAll(new ClientboundUpdateTagsPacket(TagNetworkSerialization.serializeTagsToNetwork(this.registries))); +- ClientboundUpdateRecipesPacket clientboundUpdateRecipesPacket = new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes()); ++ ClientboundUpdateRecipesPacket packetplayoutrecipeupdate = new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes()); ++ Iterator iterator1 = this.players.iterator(); + +- for (ServerPlayer serverPlayer : this.players) { +- serverPlayer.connection.send(clientboundUpdateRecipesPacket); +- serverPlayer.getRecipeBook().sendInitialRecipeBook(serverPlayer); ++ while (iterator1.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator1.next(); ++ ++ entityplayer.connection.send(packetplayoutrecipeupdate); ++ entityplayer.getRecipeBook().sendInitialRecipeBook(entityplayer); + } ++ + } + + public boolean isAllowCheatsForAllPlayers() { diff --git a/patch-remap/mache-vineflower/net/minecraft/server/players/SleepStatus.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/players/SleepStatus.java.patch new file mode 100644 index 0000000000..3c9f6b9baf --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/players/SleepStatus.java.patch @@ -0,0 +1,76 @@ +--- a/net/minecraft/server/players/SleepStatus.java ++++ b/net/minecraft/server/players/SleepStatus.java +@@ -1,25 +1,33 @@ + package net.minecraft.server.players; + ++import java.util.Iterator; + import java.util.List; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.player.Player; + + public class SleepStatus { ++ + private int activePlayers; + private int sleepingPlayers; + ++ public SleepStatus() {} ++ + public boolean areEnoughSleeping(int requiredSleepPercentage) { + return this.sleepingPlayers >= this.sleepersNeeded(requiredSleepPercentage); + } + + public boolean areEnoughDeepSleeping(int requiredSleepPercentage, List sleepingPlayers) { +- int i = (int)sleepingPlayers.stream().filter(Player::isSleepingLongEnough).count(); +- return i >= this.sleepersNeeded(requiredSleepPercentage); ++ // CraftBukkit start ++ int j = (int) sleepingPlayers.stream().filter((eh) -> { return eh.isSleepingLongEnough() || eh.fauxSleeping; }).count(); ++ boolean anyDeepSleep = sleepingPlayers.stream().anyMatch(Player::isSleepingLongEnough); ++ ++ return anyDeepSleep && j >= this.sleepersNeeded(requiredSleepPercentage); ++ // CraftBukkit end + } + + public int sleepersNeeded(int requiredSleepPercentage) { +- return Math.max(1, Mth.ceil((float)(this.activePlayers * requiredSleepPercentage) / 100.0F)); ++ return Math.max(1, Mth.ceil((float) (this.activePlayers * requiredSleepPercentage) / 100.0F)); + } + + public void removeAllSleepers() { +@@ -32,19 +40,29 @@ + + public boolean update(List players) { + int i = this.activePlayers; +- int i1 = this.sleepingPlayers; ++ int j = this.sleepingPlayers; ++ + this.activePlayers = 0; + this.sleepingPlayers = 0; ++ Iterator iterator = players.iterator(); ++ boolean anySleep = false; // CraftBukkit + +- for (ServerPlayer serverPlayer : players) { +- if (!serverPlayer.isSpectator()) { +- this.activePlayers++; +- if (serverPlayer.isSleeping()) { +- this.sleepingPlayers++; ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ if (!entityplayer.isSpectator()) { ++ ++this.activePlayers; ++ if (entityplayer.isSleeping() || entityplayer.fauxSleeping) { // CraftBukkit ++ ++this.sleepingPlayers; + } ++ // CraftBukkit start ++ if (entityplayer.isSleeping()) { ++ anySleep = true; ++ } ++ // CraftBukkit end + } + } + +- return (i1 > 0 || this.sleepingPlayers > 0) && (i != this.activePlayers || i1 != this.sleepingPlayers); ++ return anySleep && (j > 0 || this.sleepingPlayers > 0) && (i != this.activePlayers || j != this.sleepingPlayers); // CraftBukkit + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/players/StoredUserList.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/players/StoredUserList.java.patch new file mode 100644 index 0000000000..d400ee2672 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/players/StoredUserList.java.patch @@ -0,0 +1,203 @@ +--- a/net/minecraft/server/players/StoredUserList.java ++++ b/net/minecraft/server/players/StoredUserList.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.server.players; + + import com.google.common.collect.Lists; +@@ -15,16 +16,20 @@ + import java.io.IOException; + import java.nio.charset.StandardCharsets; + import java.util.Collection; ++import java.util.Iterator; + import java.util.List; + import java.util.Map; ++import java.util.Objects; ++import java.util.stream.Stream; + import javax.annotation.Nullable; + import net.minecraft.Util; + import net.minecraft.util.GsonHelper; + import org.slf4j.Logger; + + public abstract class StoredUserList> { ++ + private static final Logger LOGGER = LogUtils.getLogger(); +- private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); ++ private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create(); + private final File file; + private final Map map = Maps.newHashMap(); + +@@ -41,15 +46,16 @@ + + try { + this.save(); +- } catch (IOException var3) { +- LOGGER.warn("Could not save the list after adding a user.", (Throwable)var3); ++ } catch (IOException ioexception) { ++ StoredUserList.LOGGER.warn("Could not save the list after adding a user.", ioexception); + } ++ + } + + @Nullable + public V get(K obj) { + this.removeExpired(); +- return this.map.get(this.getKeyForUser(obj)); ++ return (V) this.map.get(this.getKeyForUser(obj)); // CraftBukkit - fix decompile error + } + + public void remove(K user) { +@@ -57,9 +63,10 @@ + + try { + this.save(); +- } catch (IOException var3) { +- LOGGER.warn("Could not save the list after removing a user.", (Throwable)var3); ++ } catch (IOException ioexception) { ++ StoredUserList.LOGGER.warn("Could not save the list after removing a user.", ioexception); + } ++ + } + + public void remove(StoredUserEntry entry) { +@@ -67,7 +74,7 @@ + } + + public String[] getUserList() { +- return this.map.keySet().toArray(new String[0]); ++ return (String[]) this.map.keySet().toArray(new String[0]); + } + + public boolean isEmpty() { +@@ -84,16 +91,24 @@ + + private void removeExpired() { + List list = Lists.newArrayList(); ++ Iterator iterator = this.map.values().iterator(); + +- for (V storedUserEntry : this.map.values()) { +- if (storedUserEntry.hasExpired()) { +- list.add(storedUserEntry.getUser()); ++ while (iterator.hasNext()) { ++ V v0 = (V) iterator.next(); // CraftBukkit - decompile error ++ ++ if (v0.hasExpired()) { ++ list.add(v0.getUser()); + } + } + +- for (K object : list) { +- this.map.remove(this.getKeyForUser(object)); ++ iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ K k0 = (K) iterator.next(); // CraftBukkit - decompile error ++ ++ this.map.remove(this.getKeyForUser(k0)); + } ++ + } + + protected abstract StoredUserEntry createEntry(JsonObject entryData); +@@ -103,31 +118,86 @@ + } + + public void save() throws IOException { +- JsonArray jsonArray = new JsonArray(); +- this.map.values().stream().map(storedUserEntry -> Util.make(new JsonObject(), storedUserEntry::serialize)).forEach(jsonArray::add); ++ JsonArray jsonarray = new JsonArray(); ++ Stream stream = this.map.values().stream().map((jsonlistentry) -> { // CraftBukkit - decompile error ++ JsonObject jsonobject = new JsonObject(); + +- try (BufferedWriter writer = Files.newWriter(this.file, StandardCharsets.UTF_8)) { +- GSON.toJson((JsonElement)jsonArray, writer); ++ Objects.requireNonNull(jsonlistentry); ++ return (JsonObject) Util.make(jsonobject, jsonlistentry::serialize); ++ }); ++ ++ Objects.requireNonNull(jsonarray); ++ stream.forEach(jsonarray::add); ++ BufferedWriter bufferedwriter = Files.newWriter(this.file, StandardCharsets.UTF_8); ++ ++ try { ++ StoredUserList.GSON.toJson(jsonarray, bufferedwriter); ++ } catch (Throwable throwable) { ++ if (bufferedwriter != null) { ++ try { ++ bufferedwriter.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } ++ ++ if (bufferedwriter != null) { ++ bufferedwriter.close(); ++ } ++ + } + + public void load() throws IOException { + if (this.file.exists()) { +- try (BufferedReader reader = Files.newReader(this.file, StandardCharsets.UTF_8)) { +- this.map.clear(); +- JsonArray jsonArray = GSON.fromJson(reader, JsonArray.class); +- if (jsonArray == null) { +- return; +- } ++ BufferedReader bufferedreader = Files.newReader(this.file, StandardCharsets.UTF_8); + +- for (JsonElement jsonElement : jsonArray) { +- JsonObject jsonObject = GsonHelper.convertToJsonObject(jsonElement, "entry"); +- StoredUserEntry storedUserEntry = this.createEntry(jsonObject); +- if (storedUserEntry.getUser() != null) { +- this.map.put(this.getKeyForUser(storedUserEntry.getUser()), (V)storedUserEntry); ++ label54: ++ { ++ try { ++ this.map.clear(); ++ JsonArray jsonarray = (JsonArray) StoredUserList.GSON.fromJson(bufferedreader, JsonArray.class); ++ ++ if (jsonarray == null) { ++ break label54; + } ++ ++ Iterator iterator = jsonarray.iterator(); ++ ++ while (iterator.hasNext()) { ++ JsonElement jsonelement = (JsonElement) iterator.next(); ++ JsonObject jsonobject = GsonHelper.convertToJsonObject(jsonelement, "entry"); ++ StoredUserEntry jsonlistentry = this.createEntry(jsonobject); ++ ++ if (jsonlistentry.getUser() != null) { ++ this.map.put(this.getKeyForUser(jsonlistentry.getUser()), (V) jsonlistentry); // CraftBukkit - decompile error ++ } ++ } ++ } catch (Throwable throwable) { ++ if (bufferedreader != null) { ++ try { ++ bufferedreader.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } ++ ++ if (bufferedreader != null) { ++ bufferedreader.close(); ++ } ++ ++ return; + } ++ ++ if (bufferedreader != null) { ++ bufferedreader.close(); ++ } ++ + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/players/UserBanListEntry.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/players/UserBanListEntry.java.patch new file mode 100644 index 0000000000..2afa53de2b --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/players/UserBanListEntry.java.patch @@ -0,0 +1,61 @@ +--- a/net/minecraft/server/players/UserBanListEntry.java ++++ b/net/minecraft/server/players/UserBanListEntry.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.server.players; + + import com.google.gson.JsonObject; +@@ -8,8 +9,9 @@ + import net.minecraft.network.chat.Component; + + public class UserBanListEntry extends BanListEntry { ++ + public UserBanListEntry(@Nullable GameProfile user) { +- this(user, null, null, null, null); ++ this(user, (Date) null, (String) null, (Date) null, (String) null); + } + + public UserBanListEntry(@Nullable GameProfile profile, @Nullable Date created, @Nullable String source, @Nullable Date expires, @Nullable String reason) { +@@ -23,31 +25,33 @@ + @Override + protected void serialize(JsonObject data) { + if (this.getUser() != null) { +- data.addProperty("uuid", this.getUser().getId().toString()); +- data.addProperty("name", this.getUser().getName()); ++ data.addProperty("uuid", ((GameProfile) this.getUser()).getId().toString()); ++ data.addProperty("name", ((GameProfile) this.getUser()).getName()); + super.serialize(data); + } + } + + @Override + public Component getDisplayName() { +- GameProfile gameProfile = this.getUser(); +- return gameProfile != null ? Component.literal(gameProfile.getName()) : Component.translatable("commands.banlist.entry.unknown"); ++ GameProfile gameprofile = (GameProfile) this.getUser(); ++ ++ return gameprofile != null ? Component.literal(gameprofile.getName()) : Component.translatable("commands.banlist.entry.unknown"); + } + + @Nullable + private static GameProfile createGameProfile(JsonObject json) { + if (json.has("uuid") && json.has("name")) { +- String asString = json.get("uuid").getAsString(); ++ String s = json.get("uuid").getAsString(); + +- UUID uUID; ++ UUID uuid; ++ + try { +- uUID = UUID.fromString(asString); +- } catch (Throwable var4) { ++ uuid = UUID.fromString(s); ++ } catch (Throwable throwable) { + return null; + } + +- return new GameProfile(uUID, json.get("name").getAsString()); ++ return new GameProfile(uuid, json.get("name").getAsString()); + } else { + return null; + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/rcon/RconConsoleSource.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/rcon/RconConsoleSource.java.patch new file mode 100644 index 0000000000..02e3da3298 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/rcon/RconConsoleSource.java.patch @@ -0,0 +1,61 @@ +--- a/net/minecraft/server/rcon/RconConsoleSource.java ++++ b/net/minecraft/server/rcon/RconConsoleSource.java +@@ -5,17 +5,27 @@ + import net.minecraft.network.chat.Component; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; +- ++// CraftBukkit start ++import java.net.SocketAddress; ++import org.bukkit.craftbukkit.command.CraftRemoteConsoleCommandSender; ++// CraftBukkit end + public class RconConsoleSource implements CommandSource { ++ + private static final String RCON = "Rcon"; + private static final Component RCON_COMPONENT = Component.literal("Rcon"); + private final StringBuffer buffer = new StringBuffer(); + private final MinecraftServer server; ++ // CraftBukkit start ++ public final SocketAddress socketAddress; ++ private final CraftRemoteConsoleCommandSender remoteConsole = new CraftRemoteConsoleCommandSender(this); + +- public RconConsoleSource(MinecraftServer server) { +- this.server = server; ++ public RconConsoleSource(MinecraftServer minecraftserver, SocketAddress socketAddress) { ++ this.socketAddress = socketAddress; ++ // CraftBukkit end ++ this.server = minecraftserver; + } + + public void prepareForCommand() { +@@ -27,13 +37,23 @@ + } + + public CommandSourceStack createCommandSourceStack() { +- ServerLevel serverLevel = this.server.overworld(); +- return new CommandSourceStack( +- this, Vec3.atLowerCornerOf(serverLevel.getSharedSpawnPos()), Vec2.ZERO, serverLevel, 4, "Rcon", RCON_COMPONENT, this.server, null +- ); ++ ServerLevel worldserver = this.server.overworld(); ++ ++ return new CommandSourceStack(this, Vec3.atLowerCornerOf(worldserver.getSharedSpawnPos()), Vec2.ZERO, worldserver, 4, "Rcon", RconConsoleSource.RCON_COMPONENT, this.server, (Entity) null); + } + ++ // CraftBukkit start - Send a String ++ public void sendMessage(String message) { ++ this.buffer.append(message); ++ } ++ + @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return this.remoteConsole; ++ } ++ // CraftBukkit end ++ ++ @Override + public void sendSystemMessage(Component component) { + this.buffer.append(component.getString()); + } diff --git a/patch-remap/mache-vineflower/net/minecraft/server/rcon/thread/RconClient.java.patch b/patch-remap/mache-vineflower/net/minecraft/server/rcon/thread/RconClient.java.patch new file mode 100644 index 0000000000..8c571cd718 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/server/rcon/thread/RconClient.java.patch @@ -0,0 +1,226 @@ +--- a/net/minecraft/server/rcon/thread/RconClient.java ++++ b/net/minecraft/server/rcon/thread/RconClient.java +@@ -8,11 +8,15 @@ + import java.net.Socket; + import java.nio.charset.StandardCharsets; + import java.util.Locale; ++import org.slf4j.Logger; + import net.minecraft.server.ServerInterface; ++// CraftBukkit start ++import net.minecraft.server.dedicated.DedicatedServer; + import net.minecraft.server.rcon.PktUtils; +-import org.slf4j.Logger; ++import net.minecraft.server.rcon.RconConsoleSource; + + public class RconClient extends GenericThread { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int SERVERDATA_AUTH = 3; + private static final int SERVERDATA_EXECCOMMAND = 2; +@@ -23,99 +27,116 @@ + private final Socket client; + private final byte[] buf = new byte[1460]; + private final String rconPassword; +- private final ServerInterface serverInterface; ++ // CraftBukkit start ++ private final DedicatedServer serverInterface; ++ private final RconConsoleSource rconConsoleSource; ++ // CraftBukkit end + + RconClient(ServerInterface serverInterface, String rconPassword, Socket client) { + super("RCON Client " + client.getInetAddress()); +- this.serverInterface = serverInterface; ++ this.serverInterface = (DedicatedServer) serverInterface; // CraftBukkit + this.client = client; + + try { + this.client.setSoTimeout(0); +- } catch (Exception var5) { ++ } catch (Exception exception) { + this.running = false; + } + + this.rconPassword = rconPassword; ++ this.rconConsoleSource = new net.minecraft.server.rcon.RconConsoleSource(this.serverInterface, client.getRemoteSocketAddress()); // CraftBukkit + } + +- @Override + public void run() { ++ // CraftBukkit start - decompile error: switch try / while statement + try { +- try { +- while (this.running) { +- BufferedInputStream bufferedInputStream = new BufferedInputStream(this.client.getInputStream()); +- int i = bufferedInputStream.read(this.buf, 0, 1460); +- if (10 > i) { +- return; +- } ++ while (true) { ++ // CraftBukkit end ++ if (!this.running) { ++ return; ++ } + +- int i1 = 0; +- int i2 = PktUtils.intFromByteArray(this.buf, 0, i); +- if (i2 != i - 4) { +- return; +- } ++ BufferedInputStream bufferedinputstream = new BufferedInputStream(this.client.getInputStream()); ++ int i = bufferedinputstream.read(this.buf, 0, 1460); + +- i1 += 4; +- int i3 = PktUtils.intFromByteArray(this.buf, i1, i); +- i1 += 4; +- int i4 = PktUtils.intFromByteArray(this.buf, i1); +- int var21 = i1 + 4; +- switch (i4) { ++ if (10 > i) { ++ return; ++ } ++ ++ byte b0 = 0; ++ int j = PktUtils.intFromByteArray(this.buf, 0, i); ++ ++ if (j == i - 4) { ++ int k = b0 + 4; ++ int l = PktUtils.intFromByteArray(this.buf, k, i); ++ ++ k += 4; ++ int i1 = PktUtils.intFromByteArray(this.buf, k); ++ ++ k += 4; ++ switch (i1) { + case 2: + if (this.authed) { +- String string1 = PktUtils.stringFromByteArray(this.buf, var21, i); ++ String s = PktUtils.stringFromByteArray(this.buf, k, i); + + try { +- this.sendCmdResponse(i3, this.serverInterface.runCommand(string1)); +- } catch (Exception var15) { +- this.sendCmdResponse(i3, "Error executing: " + string1 + " (" + var15.getMessage() + ")"); ++ this.sendCmdResponse(l, this.serverInterface.runCommand(this.rconConsoleSource, s)); // CraftBukkit ++ } catch (Exception exception) { ++ this.sendCmdResponse(l, "Error executing: " + s + " (" + exception.getMessage() + ")"); + } +- break; ++ continue; + } + + this.sendAuthFailure(); +- break; ++ continue; + case 3: +- String string = PktUtils.stringFromByteArray(this.buf, var21, i); +- i1 = var21 + string.length(); +- if (!string.isEmpty() && string.equals(this.rconPassword)) { ++ String s1 = PktUtils.stringFromByteArray(this.buf, k, i); ++ int j1 = k + s1.length(); ++ ++ if (!s1.isEmpty() && s1.equals(this.rconPassword)) { + this.authed = true; +- this.send(i3, 2, ""); +- break; ++ this.send(l, 2, ""); ++ continue; + } + + this.authed = false; + this.sendAuthFailure(); +- break; ++ continue; + default: +- this.sendCmdResponse(i3, String.format(Locale.ROOT, "Unknown request %s", Integer.toHexString(i4))); ++ this.sendCmdResponse(l, String.format(Locale.ROOT, "Unknown request %s", Integer.toHexString(i1))); ++ continue; + } + } +- ++ } // CraftBukkit - decompile error: switch try / while statement ++ } catch (IOException ioexception) { + return; +- } catch (IOException var16) { +- } catch (Exception var17) { +- LOGGER.error("Exception whilst parsing RCON input", (Throwable)var17); ++ } catch (Exception exception1) { ++ RconClient.LOGGER.error("Exception whilst parsing RCON input", exception1); ++ return; ++ } finally { ++ this.closeSocket(); ++ RconClient.LOGGER.info("Thread {} shutting down", this.name); ++ this.running = false; + } +- } finally { +- this.closeSocket(); +- LOGGER.info("Thread {} shutting down", this.name); +- this.running = false; +- } ++ ++ // CraftBukkit start - decompile error: switch try / while statement ++ // return; ++ // } ++ // CraftBukkit end + } + +- private void send(int id, int i, String message) throws IOException { +- ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1248); +- DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream); +- byte[] bytes = message.getBytes(StandardCharsets.UTF_8); +- dataOutputStream.writeInt(Integer.reverseBytes(bytes.length + 10)); +- dataOutputStream.writeInt(Integer.reverseBytes(id)); +- dataOutputStream.writeInt(Integer.reverseBytes(i)); +- dataOutputStream.write(bytes); +- dataOutputStream.write(0); +- dataOutputStream.write(0); +- this.client.getOutputStream().write(byteArrayOutputStream.toByteArray()); ++ private void send(int id, int j, String message) throws IOException { ++ ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(1248); ++ DataOutputStream dataoutputstream = new DataOutputStream(bytearrayoutputstream); ++ byte[] abyte = message.getBytes(StandardCharsets.UTF_8); ++ ++ dataoutputstream.writeInt(Integer.reverseBytes(abyte.length + 10)); ++ dataoutputstream.writeInt(Integer.reverseBytes(id)); ++ dataoutputstream.writeInt(Integer.reverseBytes(j)); ++ dataoutputstream.write(abyte); ++ dataoutputstream.write(0); ++ dataoutputstream.write(0); ++ this.client.getOutputStream().write(bytearrayoutputstream.toByteArray()); + } + + private void sendAuthFailure() throws IOException { +@@ -123,14 +144,16 @@ + } + + private void sendCmdResponse(int id, String message) throws IOException { +- int len = message.length(); ++ int j = message.length(); + + do { +- int i = 4096 <= len ? 4096 : len; +- this.send(id, 0, message.substring(0, i)); +- message = message.substring(i); +- len = message.length(); +- } while (0 != len); ++ int k = 4096 <= j ? 4096 : j; ++ ++ this.send(id, 0, message.substring(0, k)); ++ message = message.substring(k); ++ j = message.length(); ++ } while (0 != j); ++ + } + + @Override +@@ -143,8 +166,9 @@ + private void closeSocket() { + try { + this.client.close(); +- } catch (IOException var2) { +- LOGGER.warn("Failed to close socket", (Throwable)var2); ++ } catch (IOException ioexception) { ++ RconClient.LOGGER.warn("Failed to close socket", ioexception); + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/stats/ServerRecipeBook.java.patch b/patch-remap/mache-vineflower/net/minecraft/stats/ServerRecipeBook.java.patch new file mode 100644 index 0000000000..77bd371be5 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/stats/ServerRecipeBook.java.patch @@ -0,0 +1,174 @@ +--- a/net/minecraft/stats/ServerRecipeBook.java ++++ b/net/minecraft/stats/ServerRecipeBook.java +@@ -4,6 +4,7 @@ + import com.mojang.logging.LogUtils; + import java.util.Collection; + import java.util.Collections; ++import java.util.Iterator; + import java.util.List; + import java.util.Optional; + import java.util.function.Consumer; +@@ -19,27 +20,35 @@ + import net.minecraft.world.item.crafting.RecipeManager; + import org.slf4j.Logger; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public class ServerRecipeBook extends RecipeBook { ++ + public static final String RECIPE_BOOK_TAG = "recipeBook"; + private static final Logger LOGGER = LogUtils.getLogger(); + ++ public ServerRecipeBook() {} ++ + public int addRecipes(Collection> recipes, ServerPlayer player) { + List list = Lists.newArrayList(); + int i = 0; ++ Iterator iterator = recipes.iterator(); + +- for (RecipeHolder recipeHolder : recipes) { +- ResourceLocation resourceLocation = recipeHolder.id(); +- if (!this.known.contains(resourceLocation) && !recipeHolder.value().isSpecial()) { +- this.add(resourceLocation); +- this.addHighlight(resourceLocation); +- list.add(resourceLocation); +- CriteriaTriggers.RECIPE_UNLOCKED.trigger(player, recipeHolder); +- i++; ++ while (iterator.hasNext()) { ++ RecipeHolder recipeholder = (RecipeHolder) iterator.next(); ++ ResourceLocation minecraftkey = recipeholder.id(); ++ ++ if (!this.known.contains(minecraftkey) && !recipeholder.value().isSpecial() && CraftEventFactory.handlePlayerRecipeListUpdateEvent(player, minecraftkey)) { // CraftBukkit ++ this.add(minecraftkey); ++ this.addHighlight(minecraftkey); ++ list.add(minecraftkey); ++ CriteriaTriggers.RECIPE_UNLOCKED.trigger(player, recipeholder); ++ ++i; + } + } + + if (list.size() > 0) { +- this.sendRecipes(ClientboundRecipePacket.State.ADD, player, list); ++ this.sendRecipes(ClientboundRecipePacket.Action.ADD, player, list); + } + + return i; +@@ -48,71 +57,86 @@ + public int removeRecipes(Collection> recipes, ServerPlayer player) { + List list = Lists.newArrayList(); + int i = 0; ++ Iterator iterator = recipes.iterator(); + +- for (RecipeHolder recipeHolder : recipes) { +- ResourceLocation resourceLocation = recipeHolder.id(); +- if (this.known.contains(resourceLocation)) { +- this.remove(resourceLocation); +- list.add(resourceLocation); +- i++; ++ while (iterator.hasNext()) { ++ RecipeHolder recipeholder = (RecipeHolder) iterator.next(); ++ ResourceLocation minecraftkey = recipeholder.id(); ++ ++ if (this.known.contains(minecraftkey)) { ++ this.remove(minecraftkey); ++ list.add(minecraftkey); ++ ++i; + } + } + +- this.sendRecipes(ClientboundRecipePacket.State.REMOVE, player, list); ++ this.sendRecipes(ClientboundRecipePacket.Action.REMOVE, player, list); + return i; + } + +- private void sendRecipes(ClientboundRecipePacket.State state, ServerPlayer player, List recipes) { ++ private void sendRecipes(ClientboundRecipePacket.Action state, ServerPlayer player, List recipes) { ++ if (player.connection == null) return; // SPIGOT-4478 during PlayerLoginEvent + player.connection.send(new ClientboundRecipePacket(state, recipes, Collections.emptyList(), this.getBookSettings())); + } + + public CompoundTag toNbt() { +- CompoundTag compoundTag = new CompoundTag(); +- this.getBookSettings().write(compoundTag); +- ListTag list = new ListTag(); ++ CompoundTag nbttagcompound = new CompoundTag(); + +- for (ResourceLocation resourceLocation : this.known) { +- list.add(StringTag.valueOf(resourceLocation.toString())); ++ this.getBookSettings().write(nbttagcompound); ++ ListTag nbttaglist = new ListTag(); ++ Iterator iterator = this.known.iterator(); ++ ++ while (iterator.hasNext()) { ++ ResourceLocation minecraftkey = (ResourceLocation) iterator.next(); ++ ++ nbttaglist.add(StringTag.valueOf(minecraftkey.toString())); + } + +- compoundTag.put("recipes", list); +- ListTag list1 = new ListTag(); ++ nbttagcompound.put("recipes", nbttaglist); ++ ListTag nbttaglist1 = new ListTag(); ++ Iterator iterator1 = this.highlight.iterator(); + +- for (ResourceLocation resourceLocation1 : this.highlight) { +- list1.add(StringTag.valueOf(resourceLocation1.toString())); ++ while (iterator1.hasNext()) { ++ ResourceLocation minecraftkey1 = (ResourceLocation) iterator1.next(); ++ ++ nbttaglist1.add(StringTag.valueOf(minecraftkey1.toString())); + } + +- compoundTag.put("toBeDisplayed", list1); +- return compoundTag; ++ nbttagcompound.put("toBeDisplayed", nbttaglist1); ++ return nbttagcompound; + } + + public void fromNbt(CompoundTag tag, RecipeManager recipeManager) { + this.setBookSettings(RecipeBookSettings.read(tag)); +- ListTag list = tag.getList("recipes", 8); +- this.loadRecipes(list, this::add, recipeManager); +- ListTag list1 = tag.getList("toBeDisplayed", 8); +- this.loadRecipes(list1, this::addHighlight, recipeManager); ++ ListTag nbttaglist = tag.getList("recipes", 8); ++ ++ this.loadRecipes(nbttaglist, this::add, recipeManager); ++ ListTag nbttaglist1 = tag.getList("toBeDisplayed", 8); ++ ++ this.loadRecipes(nbttaglist1, this::addHighlight, recipeManager); + } + + private void loadRecipes(ListTag tags, Consumer> recipeConsumer, RecipeManager recipeManager) { +- for (int i = 0; i < tags.size(); i++) { +- String string = tags.getString(i); ++ for (int i = 0; i < tags.size(); ++i) { ++ String s = tags.getString(i); + + try { +- ResourceLocation resourceLocation = new ResourceLocation(string); +- Optional> optional = recipeManager.byKey(resourceLocation); ++ ResourceLocation minecraftkey = new ResourceLocation(s); ++ Optional> optional = recipeManager.byKey(minecraftkey); ++ + if (optional.isEmpty()) { +- LOGGER.error("Tried to load unrecognized recipe: {} removed now.", resourceLocation); ++ ServerRecipeBook.LOGGER.error("Tried to load unrecognized recipe: {} removed now.", minecraftkey); + } else { +- recipeConsumer.accept(optional.get()); ++ recipeConsumer.accept((RecipeHolder) optional.get()); + } +- } catch (ResourceLocationException var8) { +- LOGGER.error("Tried to load improperly formatted recipe: {} removed now.", string); ++ } catch (ResourceLocationException resourcekeyinvalidexception) { ++ ServerRecipeBook.LOGGER.error("Tried to load improperly formatted recipe: {} removed now.", s); + } + } ++ + } + + public void sendInitialRecipeBook(ServerPlayer player) { +- player.connection.send(new ClientboundRecipePacket(ClientboundRecipePacket.State.INIT, this.known, this.highlight, this.getBookSettings())); ++ player.connection.send(new ClientboundRecipePacket(ClientboundRecipePacket.Action.INIT, this.known, this.highlight, this.getBookSettings())); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/stats/ServerStatsCounter.java.patch b/patch-remap/mache-vineflower/net/minecraft/stats/ServerStatsCounter.java.patch new file mode 100644 index 0000000000..95b96a5065 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/stats/ServerStatsCounter.java.patch @@ -0,0 +1,286 @@ +--- a/net/minecraft/stats/ServerStatsCounter.java ++++ b/net/minecraft/stats/ServerStatsCounter.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.stats; + + import com.google.common.collect.Maps; +@@ -12,15 +13,19 @@ + import com.mojang.logging.LogUtils; + import it.unimi.dsi.fastutil.objects.Object2IntMap; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectIterator; + import java.io.File; + import java.io.IOException; + import java.io.StringReader; ++import java.util.Iterator; + import java.util.Map; ++import java.util.Map.Entry; ++import java.util.Objects; + import java.util.Optional; + import java.util.Set; +-import java.util.Map.Entry; + import net.minecraft.SharedConstants; + import net.minecraft.Util; ++import net.minecraft.core.Registry; + import net.minecraft.core.registries.BuiltInRegistries; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtUtils; +@@ -34,6 +39,7 @@ + import org.slf4j.Logger; + + public class ServerStatsCounter extends StatsCounter { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private final MinecraftServer server; + private final File file; +@@ -45,20 +51,22 @@ + if (file.isFile()) { + try { + this.parseLocal(server.getFixerUpper(), FileUtils.readFileToString(file)); +- } catch (IOException var4) { +- LOGGER.error("Couldn't read statistics file {}", file, var4); +- } catch (JsonParseException var5) { +- LOGGER.error("Couldn't parse statistics file {}", file, var5); ++ } catch (IOException ioexception) { ++ ServerStatsCounter.LOGGER.error("Couldn't read statistics file {}", file, ioexception); ++ } catch (JsonParseException jsonparseexception) { ++ ServerStatsCounter.LOGGER.error("Couldn't parse statistics file {}", file, jsonparseexception); + } + } ++ + } + + public void save() { + try { + FileUtils.writeStringToFile(this.file, this.toJson()); +- } catch (IOException var2) { +- LOGGER.error("Couldn't save stats", (Throwable)var2); ++ } catch (IOException ioexception) { ++ ServerStatsCounter.LOGGER.error("Couldn't save stats", ioexception); + } ++ + } + + @Override +@@ -69,100 +77,145 @@ + + private Set> getDirty() { + Set> set = Sets.newHashSet(this.dirty); ++ + this.dirty.clear(); + return set; + } + + public void parseLocal(DataFixer fixerUpper, String json) { + try { +- try (JsonReader jsonReader = new JsonReader(new StringReader(json))) { +- jsonReader.setLenient(false); +- JsonElement jsonElement = Streams.parse(jsonReader); +- if (!jsonElement.isJsonNull()) { +- CompoundTag compoundTag = fromJson(jsonElement.getAsJsonObject()); +- CompoundTag var12 = DataFixTypes.STATS.updateToCurrentVersion(fixerUpper, compoundTag, NbtUtils.getDataVersion(compoundTag, 1343)); +- if (!var12.contains("stats", 10)) { +- return; +- } ++ JsonReader jsonreader = new JsonReader(new StringReader(json)); + +- CompoundTag compound = var12.getCompound("stats"); ++ label48: ++ { ++ try { ++ jsonreader.setLenient(false); ++ JsonElement jsonelement = Streams.parse(jsonreader); + +- for (String string : compound.getAllKeys()) { +- if (compound.contains(string, 10)) { +- Util.ifElse( +- BuiltInRegistries.STAT_TYPE.getOptional(new ResourceLocation(string)), +- type -> { +- CompoundTag compound1 = compound.getCompound(string); +- +- for (String string1 : compound1.getAllKeys()) { +- if (compound1.contains(string1, 99)) { +- Util.ifElse( +- this.getStat(type, string1), +- stat -> this.stats.put(stat, compound1.getInt(string1)), +- () -> LOGGER.warn("Invalid statistic in {}: Don't know what {} is", this.file, string1) +- ); ++ if (!jsonelement.isJsonNull()) { ++ CompoundTag nbttagcompound = fromJson(jsonelement.getAsJsonObject()); ++ ++ nbttagcompound = DataFixTypes.STATS.updateToCurrentVersion(fixerUpper, nbttagcompound, NbtUtils.getDataVersion(nbttagcompound, 1343)); ++ if (!nbttagcompound.contains("stats", 10)) { ++ break label48; ++ } ++ ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("stats"); ++ Iterator iterator = nbttagcompound1.getAllKeys().iterator(); ++ ++ while (true) { ++ if (!iterator.hasNext()) { ++ break label48; ++ } ++ ++ String s1 = (String) iterator.next(); ++ ++ if (nbttagcompound1.contains(s1, 10)) { ++ Util.ifElse(BuiltInRegistries.STAT_TYPE.getOptional(new ResourceLocation(s1)), (statisticwrapper) -> { ++ CompoundTag nbttagcompound2 = nbttagcompound1.getCompound(s1); ++ Iterator iterator1 = nbttagcompound2.getAllKeys().iterator(); ++ ++ while (iterator1.hasNext()) { ++ String s2 = (String) iterator1.next(); ++ ++ if (nbttagcompound2.contains(s2, 99)) { ++ Util.ifElse(this.getStat(statisticwrapper, s2), (statistic) -> { ++ this.stats.put(statistic, nbttagcompound2.getInt(s2)); ++ }, () -> { ++ ServerStatsCounter.LOGGER.warn("Invalid statistic in {}: Don't know what {} is", this.file, s2); ++ }); + } else { +- LOGGER.warn( +- "Invalid statistic value in {}: Don't know what {} is for key {}", this.file, compound1.get(string1), string1 +- ); ++ ServerStatsCounter.LOGGER.warn("Invalid statistic value in {}: Don't know what {} is for key {}", new Object[]{this.file, nbttagcompound2.get(s2), s2}); + } + } +- }, +- () -> LOGGER.warn("Invalid statistic type in {}: Don't know what {} is", this.file, string) +- ); ++ ++ }, () -> { ++ ServerStatsCounter.LOGGER.warn("Invalid statistic type in {}: Don't know what {} is", this.file, s1); ++ }); ++ } + } + } + +- return; ++ ServerStatsCounter.LOGGER.error("Unable to parse Stat data from {}", this.file); ++ } catch (Throwable throwable) { ++ try { ++ jsonreader.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ ++ throw throwable; + } + +- LOGGER.error("Unable to parse Stat data from {}", this.file); ++ jsonreader.close(); ++ return; + } +- } catch (IOException | JsonParseException var11) { +- LOGGER.error("Unable to parse Stat data from {}", this.file, var11); ++ ++ jsonreader.close(); ++ } catch (IOException | JsonParseException jsonparseexception) { ++ ServerStatsCounter.LOGGER.error("Unable to parse Stat data from {}", this.file, jsonparseexception); + } ++ + } + + private Optional> getStat(StatType type, String location) { +- return Optional.ofNullable(ResourceLocation.tryParse(location)).flatMap(type.getRegistry()::getOptional).map(type::get); ++ // CraftBukkit - decompile error start ++ Optional optional = Optional.ofNullable(ResourceLocation.tryParse(location)); ++ Registry iregistry = type.getRegistry(); ++ ++ return optional.flatMap(iregistry::getOptional).map(type::get); ++ // CraftBukkit - decompile error end + } + + private static CompoundTag fromJson(JsonObject json) { +- CompoundTag compoundTag = new CompoundTag(); ++ CompoundTag nbttagcompound = new CompoundTag(); ++ Iterator iterator = json.entrySet().iterator(); + +- for (Entry entry : json.entrySet()) { +- JsonElement jsonElement = entry.getValue(); +- if (jsonElement.isJsonObject()) { +- compoundTag.put(entry.getKey(), fromJson(jsonElement.getAsJsonObject())); +- } else if (jsonElement.isJsonPrimitive()) { +- JsonPrimitive asJsonPrimitive = jsonElement.getAsJsonPrimitive(); +- if (asJsonPrimitive.isNumber()) { +- compoundTag.putInt(entry.getKey(), asJsonPrimitive.getAsInt()); ++ while (iterator.hasNext()) { ++ Entry entry = (Entry) iterator.next(); ++ JsonElement jsonelement = (JsonElement) entry.getValue(); ++ ++ if (jsonelement.isJsonObject()) { ++ nbttagcompound.put((String) entry.getKey(), fromJson(jsonelement.getAsJsonObject())); ++ } else if (jsonelement.isJsonPrimitive()) { ++ JsonPrimitive jsonprimitive = jsonelement.getAsJsonPrimitive(); ++ ++ if (jsonprimitive.isNumber()) { ++ nbttagcompound.putInt((String) entry.getKey(), jsonprimitive.getAsInt()); + } + } + } + +- return compoundTag; ++ return nbttagcompound; + } + + protected String toJson() { + Map, JsonObject> map = Maps.newHashMap(); ++ ObjectIterator objectiterator = this.stats.object2IntEntrySet().iterator(); + +- for (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry> entry : this.stats.object2IntEntrySet()) { +- Stat stat = entry.getKey(); +- map.computeIfAbsent(stat.getType(), type -> new JsonObject()).addProperty(getKey(stat).toString(), entry.getIntValue()); ++ while (objectiterator.hasNext()) { ++ it.unimi.dsi.fastutil.objects.Object2IntMap.Entry> it_unimi_dsi_fastutil_objects_object2intmap_entry = (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry) objectiterator.next(); ++ Stat statistic = (Stat) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey(); ++ ++ ((JsonObject) map.computeIfAbsent(statistic.getType(), (statisticwrapper) -> { ++ return new JsonObject(); ++ })).addProperty(getKey(statistic).toString(), it_unimi_dsi_fastutil_objects_object2intmap_entry.getIntValue()); + } + +- JsonObject jsonObject = new JsonObject(); ++ JsonObject jsonobject = new JsonObject(); ++ Iterator iterator = map.entrySet().iterator(); + +- for (Entry, JsonObject> entry1 : map.entrySet()) { +- jsonObject.add(BuiltInRegistries.STAT_TYPE.getKey(entry1.getKey()).toString(), entry1.getValue()); ++ while (iterator.hasNext()) { ++ Entry, JsonObject> entry = (Entry) iterator.next(); ++ ++ jsonobject.add(BuiltInRegistries.STAT_TYPE.getKey((StatType) entry.getKey()).toString(), (JsonElement) entry.getValue()); + } + +- JsonObject jsonObject1 = new JsonObject(); +- jsonObject1.add("stats", jsonObject); +- jsonObject1.addProperty("DataVersion", SharedConstants.getCurrentVersion().getDataVersion().getVersion()); +- return jsonObject1.toString(); ++ JsonObject jsonobject1 = new JsonObject(); ++ ++ jsonobject1.add("stats", jsonobject); ++ jsonobject1.addProperty("DataVersion", SharedConstants.getCurrentVersion().getDataVersion().getVersion()); ++ return jsonobject1.toString(); + } + + private static ResourceLocation getKey(Stat stat) { +@@ -174,12 +227,15 @@ + } + + public void sendStats(ServerPlayer player) { +- Object2IntMap> map = new Object2IntOpenHashMap<>(); ++ Object2IntMap> object2intmap = new Object2IntOpenHashMap(); ++ Iterator iterator = this.getDirty().iterator(); + +- for (Stat stat : this.getDirty()) { +- map.put(stat, this.getValue(stat)); ++ while (iterator.hasNext()) { ++ Stat statistic = (Stat) iterator.next(); ++ ++ object2intmap.put(statistic, this.getValue(statistic)); + } + +- player.connection.send(new ClientboundAwardStatsPacket(map)); ++ player.connection.send(new ClientboundAwardStatsPacket(object2intmap)); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/stats/StatsCounter.java.patch b/patch-remap/mache-vineflower/net/minecraft/stats/StatsCounter.java.patch new file mode 100644 index 0000000000..f7e16d4bb6 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/stats/StatsCounter.java.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/stats/StatsCounter.java ++++ b/net/minecraft/stats/StatsCounter.java +@@ -6,15 +6,23 @@ + import net.minecraft.world.entity.player.Player; + + public class StatsCounter { +- protected final Object2IntMap> stats = Object2IntMaps.synchronize(new Object2IntOpenHashMap<>()); + ++ protected final Object2IntMap> stats = Object2IntMaps.synchronize(new Object2IntOpenHashMap()); ++ + public StatsCounter() { + this.stats.defaultReturnValue(0); + } + + public void increment(Player player, Stat stat, int amount) { +- int i = (int)Math.min((long)this.getValue(stat) + (long)amount, 2147483647L); +- this.setValue(player, stat, i); ++ int j = (int) Math.min((long) this.getValue(stat) + (long) amount, 2147483647L); ++ ++ // CraftBukkit start - fire Statistic events ++ org.bukkit.event.Cancellable cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.handleStatisticsIncrease(player, stat, this.getValue(stat), j); ++ if (cancellable != null && cancellable.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ this.setValue(player, stat, j); + } + + public void setValue(Player player, Stat stat, int value) { diff --git a/patch-remap/mache-vineflower/net/minecraft/util/SpawnUtil.java.patch b/patch-remap/mache-vineflower/net/minecraft/util/SpawnUtil.java.patch new file mode 100644 index 0000000000..5694f2b9ae --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/util/SpawnUtil.java.patch @@ -0,0 +1,134 @@ +--- a/net/minecraft/util/SpawnUtil.java ++++ b/net/minecraft/util/SpawnUtil.java +@@ -1,38 +1,49 @@ + package net.minecraft.util; + + import java.util.Optional; ++import java.util.function.Consumer; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; ++import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.LeavesBlock; + import net.minecraft.world.level.block.StainedGlassBlock; + import net.minecraft.world.level.block.StainedGlassPaneBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public class SpawnUtil { +- public static Optional trySpawnMob( +- EntityType entityType, MobSpawnType spawnType, ServerLevel level, BlockPos pos, int attempts, int i, int yOffset, SpawnUtil.Strategy strategy +- ) { +- BlockPos.MutableBlockPos mutableBlockPos = pos.mutable(); + +- for (int i1 = 0; i1 < attempts; i1++) { +- int i2 = Mth.randomBetweenInclusive(level.random, -i, i); +- int i3 = Mth.randomBetweenInclusive(level.random, -i, i); +- mutableBlockPos.setWithOffset(pos, i2, yOffset, i3); +- if (level.getWorldBorder().isWithinBounds(mutableBlockPos) && moveToPossibleSpawnPosition(level, yOffset, mutableBlockPos, strategy)) { +- T mob = (T)entityType.create(level, null, null, mutableBlockPos, spawnType, false, false); +- if (mob != null) { +- if (mob.checkSpawnRules(level, spawnType) && mob.checkSpawnObstruction(level)) { +- level.addFreshEntityWithPassengers(mob); +- return Optional.of(mob); ++ public SpawnUtil() {} ++ ++ public static Optional trySpawnMob(EntityType entityType, EnumMobSpawn spawnType, ServerLevel level, BlockPos pos, int attempts, int j, int yOffset, SpawnUtil.Strategy strategy) { ++ // CraftBukkit start ++ return trySpawnMob(entityType, spawnType, level, pos, attempts, j, yOffset, strategy, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ public static Optional trySpawnMob(EntityType entitytypes, EnumMobSpawn enummobspawn, ServerLevel worldserver, BlockPos blockposition, int i, int j, int k, SpawnUtil.Strategy spawnutil_a, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ // CraftBukkit end ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = blockposition.mutable(); ++ ++ for (int l = 0; l < i; ++l) { ++ int i1 = Mth.randomBetweenInclusive(worldserver.random, -j, j); ++ int j1 = Mth.randomBetweenInclusive(worldserver.random, -j, j); ++ ++ blockposition_mutableblockposition.setWithOffset(blockposition, i1, k, j1); ++ if (worldserver.getWorldBorder().isWithinBounds((BlockPos) blockposition_mutableblockposition) && moveToPossibleSpawnPosition(worldserver, k, blockposition_mutableblockposition, spawnutil_a)) { ++ T t0 = entitytypes.create(worldserver, (CompoundTag) null, null, blockposition_mutableblockposition, enummobspawn, false, false); // CraftBukkit - decompile error ++ ++ if (t0 != null) { ++ if (t0.checkSpawnRules(worldserver, enummobspawn) && t0.checkSpawnObstruction(worldserver)) { ++ worldserver.addFreshEntityWithPassengers(t0, reason); // CraftBukkit ++ return Optional.of(t0); + } + +- mob.discard(); ++ t0.discard(); + } + } + } +@@ -41,47 +52,36 @@ + } + + private static boolean moveToPossibleSpawnPosition(ServerLevel level, int yOffset, BlockPos.MutableBlockPos pos, SpawnUtil.Strategy strategy) { +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos().set(pos); +- BlockState blockState = level.getBlockState(mutableBlockPos); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition1 = (new BlockPos.MutableBlockPos()).set(pos); ++ IBlockData iblockdata = level.getBlockState(blockposition_mutableblockposition1); + +- for (int i = yOffset; i >= -yOffset; i--) { ++ for (int j = yOffset; j >= -yOffset; --j) { + pos.move(Direction.DOWN); +- mutableBlockPos.setWithOffset(pos, Direction.UP); +- BlockState blockState1 = level.getBlockState(pos); +- if (strategy.canSpawnOn(level, pos, blockState1, mutableBlockPos, blockState)) { ++ blockposition_mutableblockposition1.setWithOffset(pos, Direction.UP); ++ IBlockData iblockdata1 = level.getBlockState(pos); ++ ++ if (strategy.canSpawnOn(level, pos, iblockdata1, blockposition_mutableblockposition1, iblockdata)) { + pos.move(Direction.UP); + return true; + } + +- blockState = blockState1; ++ iblockdata = iblockdata1; + } + + return false; + } + + public interface Strategy { ++ ++ /** @deprecated */ + @Deprecated +- SpawnUtil.Strategy LEGACY_IRON_GOLEM = (level, blockPos, blockState, blockPos1, blockState1) -> !blockState.is(Blocks.COBWEB) +- && !blockState.is(Blocks.CACTUS) +- && !blockState.is(Blocks.GLASS_PANE) +- && !(blockState.getBlock() instanceof StainedGlassPaneBlock) +- && !(blockState.getBlock() instanceof StainedGlassBlock) +- && !(blockState.getBlock() instanceof LeavesBlock) +- && !blockState.is(Blocks.CONDUIT) +- && !blockState.is(Blocks.ICE) +- && !blockState.is(Blocks.TNT) +- && !blockState.is(Blocks.GLOWSTONE) +- && !blockState.is(Blocks.BEACON) +- && !blockState.is(Blocks.SEA_LANTERN) +- && !blockState.is(Blocks.FROSTED_ICE) +- && !blockState.is(Blocks.TINTED_GLASS) +- && !blockState.is(Blocks.GLASS) +- && (blockState1.isAir() || blockState1.liquid()) +- && (blockState.isSolid() || blockState.is(Blocks.POWDER_SNOW)); +- SpawnUtil.Strategy ON_TOP_OF_COLLIDER = (level, blockPos, blockState, blockPos1, blockState1) -> blockState1.getCollisionShape(level, blockPos1) +- .isEmpty() +- && Block.isFaceFull(blockState.getCollisionShape(level, blockPos), Direction.UP); ++ SpawnUtil.Strategy LEGACY_IRON_GOLEM = (worldserver, blockposition, iblockdata, blockposition1, iblockdata1) -> { ++ return !iblockdata.is(Blocks.COBWEB) && !iblockdata.is(Blocks.CACTUS) && !iblockdata.is(Blocks.GLASS_PANE) && !(iblockdata.getBlock() instanceof StainedGlassPaneBlock) && !(iblockdata.getBlock() instanceof StainedGlassBlock) && !(iblockdata.getBlock() instanceof LeavesBlock) && !iblockdata.is(Blocks.CONDUIT) && !iblockdata.is(Blocks.ICE) && !iblockdata.is(Blocks.TNT) && !iblockdata.is(Blocks.GLOWSTONE) && !iblockdata.is(Blocks.BEACON) && !iblockdata.is(Blocks.SEA_LANTERN) && !iblockdata.is(Blocks.FROSTED_ICE) && !iblockdata.is(Blocks.TINTED_GLASS) && !iblockdata.is(Blocks.GLASS) ? (iblockdata1.isAir() || iblockdata1.liquid()) && (iblockdata.isSolid() || iblockdata.is(Blocks.POWDER_SNOW)) : false; ++ }; ++ SpawnUtil.Strategy ON_TOP_OF_COLLIDER = (worldserver, blockposition, iblockdata, blockposition1, iblockdata1) -> { ++ return iblockdata1.getCollisionShape(worldserver, blockposition1).isEmpty() && Block.isFaceFull(iblockdata.getCollisionShape(worldserver, blockposition), Direction.UP); ++ }; + +- boolean canSpawnOn(ServerLevel level, BlockPos blockPos, BlockState blockState, BlockPos blockPos1, BlockState blockState1); ++ boolean canSpawnOn(ServerLevel level, BlockPos blockposition, IBlockData iblockdata, BlockPos blockposition1, IBlockData iblockdata1); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/util/datafix/DataFixers.java.patch b/patch-remap/mache-vineflower/net/minecraft/util/datafix/DataFixers.java.patch new file mode 100644 index 0000000000..a459409353 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/util/datafix/DataFixers.java.patch @@ -0,0 +1,1677 @@ +--- a/net/minecraft/util/datafix/DataFixers.java ++++ b/net/minecraft/util/datafix/DataFixers.java +@@ -3,16 +3,16 @@ + import com.google.common.collect.ImmutableMap; + import com.google.common.util.concurrent.ThreadFactoryBuilder; + import com.mojang.datafixers.DSL; ++import com.mojang.datafixers.DSL.TypeReference; + import com.mojang.datafixers.DataFixer; + import com.mojang.datafixers.DataFixerBuilder; + import com.mojang.datafixers.Typed; +-import com.mojang.datafixers.DSL.TypeReference; + import com.mojang.datafixers.schemas.Schema; + import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + import java.util.Map; + import java.util.Objects; + import java.util.Set; +-import java.util.concurrent.Executor; ++import java.util.concurrent.ExecutorService; + import java.util.concurrent.Executors; + import java.util.function.BiFunction; + import java.util.function.Function; +@@ -21,183 +21,7 @@ + import java.util.stream.Stream; + import net.minecraft.SharedConstants; + import net.minecraft.Util; +-import net.minecraft.util.datafix.fixes.AbstractArrowPickupFix; +-import net.minecraft.util.datafix.fixes.AddFlagIfNotPresentFix; +-import net.minecraft.util.datafix.fixes.AddNewChoices; +-import net.minecraft.util.datafix.fixes.AdvancementsFix; +-import net.minecraft.util.datafix.fixes.AdvancementsRenameFix; +-import net.minecraft.util.datafix.fixes.AttributesRename; +-import net.minecraft.util.datafix.fixes.BedItemColorFix; +-import net.minecraft.util.datafix.fixes.BiomeFix; +-import net.minecraft.util.datafix.fixes.BitStorageAlignFix; +-import net.minecraft.util.datafix.fixes.BlendingDataFix; +-import net.minecraft.util.datafix.fixes.BlendingDataRemoveFromNetherEndFix; +-import net.minecraft.util.datafix.fixes.BlockEntityBannerColorFix; +-import net.minecraft.util.datafix.fixes.BlockEntityBlockStateFix; +-import net.minecraft.util.datafix.fixes.BlockEntityCustomNameToComponentFix; +-import net.minecraft.util.datafix.fixes.BlockEntityIdFix; +-import net.minecraft.util.datafix.fixes.BlockEntityJukeboxFix; +-import net.minecraft.util.datafix.fixes.BlockEntityKeepPacked; +-import net.minecraft.util.datafix.fixes.BlockEntityRenameFix; +-import net.minecraft.util.datafix.fixes.BlockEntityShulkerBoxColorFix; +-import net.minecraft.util.datafix.fixes.BlockEntitySignDoubleSidedEditableTextFix; +-import net.minecraft.util.datafix.fixes.BlockEntitySignTextStrictJsonFix; +-import net.minecraft.util.datafix.fixes.BlockEntityUUIDFix; +-import net.minecraft.util.datafix.fixes.BlockNameFlatteningFix; +-import net.minecraft.util.datafix.fixes.BlockRenameFix; +-import net.minecraft.util.datafix.fixes.BlockRenameFixWithJigsaw; +-import net.minecraft.util.datafix.fixes.BlockStateStructureTemplateFix; +-import net.minecraft.util.datafix.fixes.CatTypeFix; +-import net.minecraft.util.datafix.fixes.CauldronRenameFix; +-import net.minecraft.util.datafix.fixes.CavesAndCliffsRenames; +-import net.minecraft.util.datafix.fixes.ChunkBedBlockEntityInjecterFix; +-import net.minecraft.util.datafix.fixes.ChunkBiomeFix; +-import net.minecraft.util.datafix.fixes.ChunkDeleteIgnoredLightDataFix; +-import net.minecraft.util.datafix.fixes.ChunkDeleteLightFix; +-import net.minecraft.util.datafix.fixes.ChunkHeightAndBiomeFix; +-import net.minecraft.util.datafix.fixes.ChunkLightRemoveFix; +-import net.minecraft.util.datafix.fixes.ChunkPalettedStorageFix; +-import net.minecraft.util.datafix.fixes.ChunkProtoTickListFix; +-import net.minecraft.util.datafix.fixes.ChunkRenamesFix; +-import net.minecraft.util.datafix.fixes.ChunkStatusFix; +-import net.minecraft.util.datafix.fixes.ChunkStatusFix2; +-import net.minecraft.util.datafix.fixes.ChunkStructuresTemplateRenameFix; +-import net.minecraft.util.datafix.fixes.ChunkToProtochunkFix; +-import net.minecraft.util.datafix.fixes.ColorlessShulkerEntityFix; +-import net.minecraft.util.datafix.fixes.CriteriaRenameFix; +-import net.minecraft.util.datafix.fixes.DecoratedPotFieldRenameFix; +-import net.minecraft.util.datafix.fixes.DropInvalidSignDataFix; +-import net.minecraft.util.datafix.fixes.DyeItemRenameFix; +-import net.minecraft.util.datafix.fixes.EffectDurationFix; +-import net.minecraft.util.datafix.fixes.EntityArmorStandSilentFix; +-import net.minecraft.util.datafix.fixes.EntityBlockStateFix; +-import net.minecraft.util.datafix.fixes.EntityBrushableBlockFieldsRenameFix; +-import net.minecraft.util.datafix.fixes.EntityCatSplitFix; +-import net.minecraft.util.datafix.fixes.EntityCodSalmonFix; +-import net.minecraft.util.datafix.fixes.EntityCustomNameToComponentFix; +-import net.minecraft.util.datafix.fixes.EntityElderGuardianSplitFix; +-import net.minecraft.util.datafix.fixes.EntityEquipmentToArmorAndHandFix; +-import net.minecraft.util.datafix.fixes.EntityGoatMissingStateFix; +-import net.minecraft.util.datafix.fixes.EntityHealthFix; +-import net.minecraft.util.datafix.fixes.EntityHorseSaddleFix; +-import net.minecraft.util.datafix.fixes.EntityHorseSplitFix; +-import net.minecraft.util.datafix.fixes.EntityIdFix; +-import net.minecraft.util.datafix.fixes.EntityItemFrameDirectionFix; +-import net.minecraft.util.datafix.fixes.EntityMinecartIdentifiersFix; +-import net.minecraft.util.datafix.fixes.EntityPaintingFieldsRenameFix; +-import net.minecraft.util.datafix.fixes.EntityPaintingItemFrameDirectionFix; +-import net.minecraft.util.datafix.fixes.EntityPaintingMotiveFix; +-import net.minecraft.util.datafix.fixes.EntityProjectileOwnerFix; +-import net.minecraft.util.datafix.fixes.EntityPufferfishRenameFix; +-import net.minecraft.util.datafix.fixes.EntityRavagerRenameFix; +-import net.minecraft.util.datafix.fixes.EntityRedundantChanceTagsFix; +-import net.minecraft.util.datafix.fixes.EntityRidingToPassengersFix; +-import net.minecraft.util.datafix.fixes.EntityShulkerColorFix; +-import net.minecraft.util.datafix.fixes.EntityShulkerRotationFix; +-import net.minecraft.util.datafix.fixes.EntitySkeletonSplitFix; +-import net.minecraft.util.datafix.fixes.EntityStringUuidFix; +-import net.minecraft.util.datafix.fixes.EntityTheRenameningFix; +-import net.minecraft.util.datafix.fixes.EntityTippedArrowFix; +-import net.minecraft.util.datafix.fixes.EntityUUIDFix; +-import net.minecraft.util.datafix.fixes.EntityVariantFix; +-import net.minecraft.util.datafix.fixes.EntityWolfColorFix; +-import net.minecraft.util.datafix.fixes.EntityZombieSplitFix; +-import net.minecraft.util.datafix.fixes.EntityZombieVillagerTypeFix; +-import net.minecraft.util.datafix.fixes.EntityZombifiedPiglinRenameFix; +-import net.minecraft.util.datafix.fixes.FeatureFlagRemoveFix; +-import net.minecraft.util.datafix.fixes.FilteredBooksFix; +-import net.minecraft.util.datafix.fixes.FilteredSignsFix; +-import net.minecraft.util.datafix.fixes.FixProjectileStoredItem; +-import net.minecraft.util.datafix.fixes.ForcePoiRebuild; +-import net.minecraft.util.datafix.fixes.FurnaceRecipeFix; +-import net.minecraft.util.datafix.fixes.GoatHornIdFix; +-import net.minecraft.util.datafix.fixes.GossipUUIDFix; +-import net.minecraft.util.datafix.fixes.HeightmapRenamingFix; +-import net.minecraft.util.datafix.fixes.IglooMetadataRemovalFix; +-import net.minecraft.util.datafix.fixes.ItemBannerColorFix; +-import net.minecraft.util.datafix.fixes.ItemCustomNameToComponentFix; +-import net.minecraft.util.datafix.fixes.ItemIdFix; +-import net.minecraft.util.datafix.fixes.ItemLoreFix; +-import net.minecraft.util.datafix.fixes.ItemPotionFix; +-import net.minecraft.util.datafix.fixes.ItemRemoveBlockEntityTagFix; +-import net.minecraft.util.datafix.fixes.ItemRenameFix; +-import net.minecraft.util.datafix.fixes.ItemShulkerBoxColorFix; +-import net.minecraft.util.datafix.fixes.ItemSpawnEggFix; +-import net.minecraft.util.datafix.fixes.ItemStackEnchantmentNamesFix; +-import net.minecraft.util.datafix.fixes.ItemStackMapIdFix; +-import net.minecraft.util.datafix.fixes.ItemStackSpawnEggFix; +-import net.minecraft.util.datafix.fixes.ItemStackTheFlatteningFix; +-import net.minecraft.util.datafix.fixes.ItemStackUUIDFix; +-import net.minecraft.util.datafix.fixes.ItemWaterPotionFix; +-import net.minecraft.util.datafix.fixes.ItemWrittenBookPagesStrictJsonFix; +-import net.minecraft.util.datafix.fixes.JigsawPropertiesFix; +-import net.minecraft.util.datafix.fixes.JigsawRotationFix; +-import net.minecraft.util.datafix.fixes.LeavesFix; +-import net.minecraft.util.datafix.fixes.LegacyDragonFightFix; +-import net.minecraft.util.datafix.fixes.LevelDataGeneratorOptionsFix; +-import net.minecraft.util.datafix.fixes.LevelFlatGeneratorInfoFix; +-import net.minecraft.util.datafix.fixes.LevelLegacyWorldGenSettingsFix; +-import net.minecraft.util.datafix.fixes.LevelUUIDFix; +-import net.minecraft.util.datafix.fixes.MapIdFix; +-import net.minecraft.util.datafix.fixes.MemoryExpiryDataFix; +-import net.minecraft.util.datafix.fixes.MissingDimensionFix; +-import net.minecraft.util.datafix.fixes.MobEffectIdFix; +-import net.minecraft.util.datafix.fixes.MobSpawnerEntityIdentifiersFix; +-import net.minecraft.util.datafix.fixes.NamedEntityFix; +-import net.minecraft.util.datafix.fixes.NamespacedTypeRenameFix; +-import net.minecraft.util.datafix.fixes.NewVillageFix; +-import net.minecraft.util.datafix.fixes.ObjectiveDisplayNameFix; +-import net.minecraft.util.datafix.fixes.ObjectiveRenderTypeFix; +-import net.minecraft.util.datafix.fixes.OminousBannerBlockEntityRenameFix; +-import net.minecraft.util.datafix.fixes.OminousBannerRenameFix; +-import net.minecraft.util.datafix.fixes.OptionsAccessibilityOnboardFix; +-import net.minecraft.util.datafix.fixes.OptionsAddTextBackgroundFix; +-import net.minecraft.util.datafix.fixes.OptionsAmbientOcclusionFix; +-import net.minecraft.util.datafix.fixes.OptionsForceVBOFix; +-import net.minecraft.util.datafix.fixes.OptionsKeyLwjgl3Fix; +-import net.minecraft.util.datafix.fixes.OptionsKeyTranslationFix; +-import net.minecraft.util.datafix.fixes.OptionsLowerCaseLanguageFix; +-import net.minecraft.util.datafix.fixes.OptionsProgrammerArtFix; +-import net.minecraft.util.datafix.fixes.OptionsRenameFieldFix; +-import net.minecraft.util.datafix.fixes.OverreachingTickFix; +-import net.minecraft.util.datafix.fixes.PlayerUUIDFix; +-import net.minecraft.util.datafix.fixes.PoiTypeRemoveFix; +-import net.minecraft.util.datafix.fixes.PoiTypeRenameFix; +-import net.minecraft.util.datafix.fixes.PrimedTntBlockStateFixer; +-import net.minecraft.util.datafix.fixes.RandomSequenceSettingsFix; +-import net.minecraft.util.datafix.fixes.RecipesFix; +-import net.minecraft.util.datafix.fixes.RecipesRenameningFix; +-import net.minecraft.util.datafix.fixes.RedstoneWireConnectionsFix; +-import net.minecraft.util.datafix.fixes.References; +-import net.minecraft.util.datafix.fixes.RemapChunkStatusFix; +-import net.minecraft.util.datafix.fixes.RemoveGolemGossipFix; +-import net.minecraft.util.datafix.fixes.RenamedCoralFansFix; +-import net.minecraft.util.datafix.fixes.RenamedCoralFix; +-import net.minecraft.util.datafix.fixes.ReorganizePoi; +-import net.minecraft.util.datafix.fixes.SavedDataFeaturePoolElementFix; +-import net.minecraft.util.datafix.fixes.SavedDataUUIDFix; +-import net.minecraft.util.datafix.fixes.ScoreboardDisplaySlotFix; +-import net.minecraft.util.datafix.fixes.SpawnerDataFix; +-import net.minecraft.util.datafix.fixes.StatsCounterFix; +-import net.minecraft.util.datafix.fixes.StatsRenameFix; +-import net.minecraft.util.datafix.fixes.StriderGravityFix; +-import net.minecraft.util.datafix.fixes.StructureReferenceCountFix; +-import net.minecraft.util.datafix.fixes.StructureSettingsFlattenFix; +-import net.minecraft.util.datafix.fixes.StructuresBecomeConfiguredFix; +-import net.minecraft.util.datafix.fixes.TeamDisplayNameFix; +-import net.minecraft.util.datafix.fixes.TrappedChestBlockEntityFix; +-import net.minecraft.util.datafix.fixes.VariantRenameFix; +-import net.minecraft.util.datafix.fixes.VillagerDataFix; +-import net.minecraft.util.datafix.fixes.VillagerFollowRangeFix; +-import net.minecraft.util.datafix.fixes.VillagerRebuildLevelAndXpFix; +-import net.minecraft.util.datafix.fixes.VillagerTradeFix; +-import net.minecraft.util.datafix.fixes.WallPropertyFix; +-import net.minecraft.util.datafix.fixes.WeaponSmithChestLootTableFix; +-import net.minecraft.util.datafix.fixes.WorldGenSettingsDisallowOldCustomWorldsFix; +-import net.minecraft.util.datafix.fixes.WorldGenSettingsFix; +-import net.minecraft.util.datafix.fixes.WorldGenSettingsHeightAndBiomeFix; +-import net.minecraft.util.datafix.fixes.WriteAndReadFix; +-import net.minecraft.util.datafix.fixes.ZombieVillagerRebuildXpFix; ++import net.minecraft.util.datafix.fixes.*; + import net.minecraft.util.datafix.schemas.NamespacedSchema; + import net.minecraft.util.datafix.schemas.V100; + import net.minecraft.util.datafix.schemas.V102; +@@ -277,951 +101,795 @@ + import net.minecraft.util.datafix.schemas.V99; + + public class DataFixers { ++ + private static final BiFunction SAME = Schema::new; + private static final BiFunction SAME_NAMESPACED = NamespacedSchema::new; + private static final DataFixer dataFixer = createFixerUpper(SharedConstants.DATA_FIX_TYPES_TO_OPTIMIZE); + public static final int BLENDING_VERSION = 3441; + +- private DataFixers() { +- } ++ private DataFixers() {} + + public static DataFixer getDataFixer() { +- return dataFixer; ++ return DataFixers.dataFixer; + } + + private static synchronized DataFixer createFixerUpper(Set typeReferences) { +- DataFixerBuilder dataFixerBuilder = new DataFixerBuilder(SharedConstants.getCurrentVersion().getDataVersion().getVersion()); +- addFixers(dataFixerBuilder); ++ DataFixerBuilder datafixerbuilder = new DataFixerBuilder(SharedConstants.getCurrentVersion().getDataVersion().getVersion()); ++ ++ addFixers(datafixerbuilder); + if (typeReferences.isEmpty()) { +- return dataFixerBuilder.buildUnoptimized(); ++ return datafixerbuilder.buildUnoptimized(); + } else { +- Executor singleThreadExecutor = Executors.newSingleThreadExecutor( +- new ThreadFactoryBuilder().setNameFormat("Datafixer Bootstrap").setDaemon(true).setPriority(1).build() +- ); +- return dataFixerBuilder.buildOptimized(typeReferences, singleThreadExecutor); ++ ExecutorService executorservice = Executors.newSingleThreadExecutor((new ThreadFactoryBuilder()).setNameFormat("Datafixer Bootstrap").setDaemon(true).setPriority(1).build()); ++ ++ return datafixerbuilder.buildOptimized(typeReferences, executorservice); + } + } + + private static void addFixers(DataFixerBuilder builder) { + builder.addSchema(99, V99::new); + Schema schema = builder.addSchema(100, V100::new); ++ + builder.addFixer(new EntityEquipmentToArmorAndHandFix(schema, true)); +- Schema schema1 = builder.addSchema(101, SAME); ++ Schema schema1 = builder.addSchema(101, DataFixers.SAME); ++ + builder.addFixer(new BlockEntitySignTextStrictJsonFix(schema1, false)); + Schema schema2 = builder.addSchema(102, V102::new); ++ + builder.addFixer(new ItemIdFix(schema2, true)); + builder.addFixer(new ItemPotionFix(schema2, false)); +- Schema schema3 = builder.addSchema(105, SAME); ++ Schema schema3 = builder.addSchema(105, DataFixers.SAME); ++ + builder.addFixer(new ItemSpawnEggFix(schema3, true)); + Schema schema4 = builder.addSchema(106, V106::new); ++ + builder.addFixer(new MobSpawnerEntityIdentifiersFix(schema4, true)); + Schema schema5 = builder.addSchema(107, V107::new); ++ + builder.addFixer(new EntityMinecartIdentifiersFix(schema5, true)); +- Schema schema6 = builder.addSchema(108, SAME); ++ Schema schema6 = builder.addSchema(108, DataFixers.SAME); ++ + builder.addFixer(new EntityStringUuidFix(schema6, true)); +- Schema schema7 = builder.addSchema(109, SAME); ++ Schema schema7 = builder.addSchema(109, DataFixers.SAME); ++ + builder.addFixer(new EntityHealthFix(schema7, true)); +- Schema schema8 = builder.addSchema(110, SAME); ++ Schema schema8 = builder.addSchema(110, DataFixers.SAME); ++ + builder.addFixer(new EntityHorseSaddleFix(schema8, true)); +- Schema schema9 = builder.addSchema(111, SAME); ++ Schema schema9 = builder.addSchema(111, DataFixers.SAME); ++ + builder.addFixer(new EntityPaintingItemFrameDirectionFix(schema9, true)); +- Schema schema10 = builder.addSchema(113, SAME); ++ Schema schema10 = builder.addSchema(113, DataFixers.SAME); ++ + builder.addFixer(new EntityRedundantChanceTagsFix(schema10, true)); + Schema schema11 = builder.addSchema(135, V135::new); ++ + builder.addFixer(new EntityRidingToPassengersFix(schema11, true)); + Schema schema12 = builder.addSchema(143, V143::new); ++ + builder.addFixer(new EntityTippedArrowFix(schema12, true)); +- Schema schema13 = builder.addSchema(147, SAME); ++ Schema schema13 = builder.addSchema(147, DataFixers.SAME); ++ + builder.addFixer(new EntityArmorStandSilentFix(schema13, true)); +- Schema schema14 = builder.addSchema(165, SAME); ++ Schema schema14 = builder.addSchema(165, DataFixers.SAME); ++ + builder.addFixer(new ItemWrittenBookPagesStrictJsonFix(schema14, true)); + Schema schema15 = builder.addSchema(501, V501::new); +- builder.addFixer(new AddNewChoices(schema15, "Add 1.10 entities fix", References.ENTITY)); +- Schema schema16 = builder.addSchema(502, SAME); +- builder.addFixer( +- ItemRenameFix.create( +- schema16, +- "cooked_fished item renamer", +- string -> Objects.equals(NamespacedSchema.ensureNamespaced(string), "minecraft:cooked_fished") ? "minecraft:cooked_fish" : string +- ) +- ); ++ ++ builder.addFixer(new AddNewChoices(schema15, "Add 1.10 entities fix", DataConverterTypes.ENTITY)); ++ Schema schema16 = builder.addSchema(502, DataFixers.SAME); ++ ++ builder.addFixer(ItemRenameFix.create(schema16, "cooked_fished item renamer", (s) -> { ++ return Objects.equals(NamespacedSchema.ensureNamespaced(s), "minecraft:cooked_fished") ? "minecraft:cooked_fish" : s; ++ })); + builder.addFixer(new EntityZombieVillagerTypeFix(schema16, false)); +- Schema schema17 = builder.addSchema(505, SAME); ++ Schema schema17 = builder.addSchema(505, DataFixers.SAME); ++ + builder.addFixer(new OptionsForceVBOFix(schema17, false)); + Schema schema18 = builder.addSchema(700, V700::new); ++ + builder.addFixer(new EntityElderGuardianSplitFix(schema18, true)); + Schema schema19 = builder.addSchema(701, V701::new); ++ + builder.addFixer(new EntitySkeletonSplitFix(schema19, true)); + Schema schema20 = builder.addSchema(702, V702::new); ++ + builder.addFixer(new EntityZombieSplitFix(schema20, true)); + Schema schema21 = builder.addSchema(703, V703::new); ++ + builder.addFixer(new EntityHorseSplitFix(schema21, true)); + Schema schema22 = builder.addSchema(704, V704::new); ++ + builder.addFixer(new BlockEntityIdFix(schema22, true)); + Schema schema23 = builder.addSchema(705, V705::new); ++ + builder.addFixer(new EntityIdFix(schema23, true)); +- Schema schema24 = builder.addSchema(804, SAME_NAMESPACED); ++ Schema schema24 = builder.addSchema(804, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new ItemBannerColorFix(schema24, true)); +- Schema schema25 = builder.addSchema(806, SAME_NAMESPACED); ++ Schema schema25 = builder.addSchema(806, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new ItemWaterPotionFix(schema25, false)); + Schema schema26 = builder.addSchema(808, V808::new); +- builder.addFixer(new AddNewChoices(schema26, "added shulker box", References.BLOCK_ENTITY)); +- Schema schema27 = builder.addSchema(808, 1, SAME_NAMESPACED); ++ ++ builder.addFixer(new AddNewChoices(schema26, "added shulker box", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema27 = builder.addSchema(808, 1, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new EntityShulkerColorFix(schema27, false)); +- Schema schema28 = builder.addSchema(813, SAME_NAMESPACED); ++ Schema schema28 = builder.addSchema(813, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new ItemShulkerBoxColorFix(schema28, false)); + builder.addFixer(new BlockEntityShulkerBoxColorFix(schema28, false)); +- Schema schema29 = builder.addSchema(816, SAME_NAMESPACED); ++ Schema schema29 = builder.addSchema(816, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new OptionsLowerCaseLanguageFix(schema29, false)); +- Schema schema30 = builder.addSchema(820, SAME_NAMESPACED); ++ Schema schema30 = builder.addSchema(820, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(ItemRenameFix.create(schema30, "totem item renamer", createRenamer("minecraft:totem", "minecraft:totem_of_undying"))); + Schema schema31 = builder.addSchema(1022, V1022::new); +- builder.addFixer(new WriteAndReadFix(schema31, "added shoulder entities to players", References.PLAYER)); ++ ++ builder.addFixer(new WriteAndReadFix(schema31, "added shoulder entities to players", DataConverterTypes.PLAYER)); + Schema schema32 = builder.addSchema(1125, V1125::new); ++ + builder.addFixer(new ChunkBedBlockEntityInjecterFix(schema32, true)); + builder.addFixer(new BedItemColorFix(schema32, false)); +- Schema schema33 = builder.addSchema(1344, SAME_NAMESPACED); ++ Schema schema33 = builder.addSchema(1344, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new OptionsKeyLwjgl3Fix(schema33, false)); +- Schema schema34 = builder.addSchema(1446, SAME_NAMESPACED); ++ Schema schema34 = builder.addSchema(1446, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new OptionsKeyTranslationFix(schema34, false)); +- Schema schema35 = builder.addSchema(1450, SAME_NAMESPACED); ++ Schema schema35 = builder.addSchema(1450, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new BlockStateStructureTemplateFix(schema35, false)); + Schema schema36 = builder.addSchema(1451, V1451::new); +- builder.addFixer(new AddNewChoices(schema36, "AddTrappedChestFix", References.BLOCK_ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema36, "AddTrappedChestFix", DataConverterTypes.BLOCK_ENTITY)); + Schema schema37 = builder.addSchema(1451, 1, V1451_1::new); ++ + builder.addFixer(new ChunkPalettedStorageFix(schema37, true)); + Schema schema38 = builder.addSchema(1451, 2, V1451_2::new); ++ + builder.addFixer(new BlockEntityBlockStateFix(schema38, true)); + Schema schema39 = builder.addSchema(1451, 3, V1451_3::new); ++ + builder.addFixer(new EntityBlockStateFix(schema39, true)); + builder.addFixer(new ItemStackMapIdFix(schema39, false)); + Schema schema40 = builder.addSchema(1451, 4, V1451_4::new); ++ + builder.addFixer(new BlockNameFlatteningFix(schema40, true)); + builder.addFixer(new ItemStackTheFlatteningFix(schema40, false)); + Schema schema41 = builder.addSchema(1451, 5, V1451_5::new); +- builder.addFixer( +- new ItemRemoveBlockEntityTagFix( +- schema41, +- false, +- Set.of( +- "minecraft:note_block", +- "minecraft:flower_pot", +- "minecraft:dandelion", +- "minecraft:poppy", +- "minecraft:blue_orchid", +- "minecraft:allium", +- "minecraft:azure_bluet", +- "minecraft:red_tulip", +- "minecraft:orange_tulip", +- "minecraft:white_tulip", +- "minecraft:pink_tulip", +- "minecraft:oxeye_daisy", +- "minecraft:cactus", +- "minecraft:brown_mushroom", +- "minecraft:red_mushroom", +- "minecraft:oak_sapling", +- "minecraft:spruce_sapling", +- "minecraft:birch_sapling", +- "minecraft:jungle_sapling", +- "minecraft:acacia_sapling", +- "minecraft:dark_oak_sapling", +- "minecraft:dead_bush", +- "minecraft:fern" +- ) +- ) +- ); +- builder.addFixer(new AddNewChoices(schema41, "RemoveNoteBlockFlowerPotFix", References.BLOCK_ENTITY)); ++ ++ builder.addFixer(new ItemRemoveBlockEntityTagFix(schema41, false, Set.of("minecraft:note_block", "minecraft:flower_pot", "minecraft:dandelion", "minecraft:poppy", "minecraft:blue_orchid", "minecraft:allium", "minecraft:azure_bluet", "minecraft:red_tulip", "minecraft:orange_tulip", "minecraft:white_tulip", "minecraft:pink_tulip", "minecraft:oxeye_daisy", "minecraft:cactus", "minecraft:brown_mushroom", "minecraft:red_mushroom", "minecraft:oak_sapling", "minecraft:spruce_sapling", "minecraft:birch_sapling", "minecraft:jungle_sapling", "minecraft:acacia_sapling", "minecraft:dark_oak_sapling", "minecraft:dead_bush", "minecraft:fern"))); ++ builder.addFixer(new AddNewChoices(schema41, "RemoveNoteBlockFlowerPotFix", DataConverterTypes.BLOCK_ENTITY)); + builder.addFixer(new ItemStackSpawnEggFix(schema41, false, "minecraft:spawn_egg")); + builder.addFixer(new EntityWolfColorFix(schema41, false)); + builder.addFixer(new BlockEntityBannerColorFix(schema41, false)); + builder.addFixer(new LevelFlatGeneratorInfoFix(schema41, false)); + Schema schema42 = builder.addSchema(1451, 6, V1451_6::new); ++ + builder.addFixer(new StatsCounterFix(schema42, true)); + builder.addFixer(new BlockEntityJukeboxFix(schema42, false)); +- Schema schema43 = builder.addSchema(1451, 7, SAME_NAMESPACED); ++ Schema schema43 = builder.addSchema(1451, 7, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new VillagerTradeFix(schema43, false)); +- Schema schema44 = builder.addSchema(1456, SAME_NAMESPACED); ++ Schema schema44 = builder.addSchema(1456, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new EntityItemFrameDirectionFix(schema44, false)); +- Schema schema45 = builder.addSchema(1458, SAME_NAMESPACED); ++ Schema schema45 = builder.addSchema(1458, DataFixers.SAME_NAMESPACED); ++ ++ // CraftBukkit start ++ builder.addFixer(new com.mojang.datafixers.DataFix(schema45, false) { ++ @Override ++ protected com.mojang.datafixers.TypeRewriteRule makeRule() { ++ return this.fixTypeEverywhereTyped("Player CustomName", this.getInputSchema().getType(DataConverterTypes.PLAYER), (typed) -> { ++ return typed.update(DSL.remainderFinder(), (dynamic) -> { ++ return EntityCustomNameToComponentFix.fixTagCustomName(dynamic); ++ }); ++ }); ++ } ++ }); ++ // CraftBukkit end + builder.addFixer(new EntityCustomNameToComponentFix(schema45, false)); + builder.addFixer(new ItemCustomNameToComponentFix(schema45, false)); + builder.addFixer(new BlockEntityCustomNameToComponentFix(schema45, false)); + Schema schema46 = builder.addSchema(1460, V1460::new); ++ + builder.addFixer(new EntityPaintingMotiveFix(schema46, false)); + Schema schema47 = builder.addSchema(1466, V1466::new); +- builder.addFixer(new AddNewChoices(schema47, "Add DUMMY block entity", References.BLOCK_ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema47, "Add DUMMY block entity", DataConverterTypes.BLOCK_ENTITY)); + builder.addFixer(new ChunkToProtochunkFix(schema47, true)); + Schema schema48 = builder.addSchema(1470, V1470::new); +- builder.addFixer(new AddNewChoices(schema48, "Add 1.13 entities fix", References.ENTITY)); +- Schema schema49 = builder.addSchema(1474, SAME_NAMESPACED); ++ ++ builder.addFixer(new AddNewChoices(schema48, "Add 1.13 entities fix", DataConverterTypes.ENTITY)); ++ Schema schema49 = builder.addSchema(1474, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new ColorlessShulkerEntityFix(schema49, false)); +- builder.addFixer( +- BlockRenameFix.create( +- schema49, +- "Colorless shulker block fixer", +- string -> Objects.equals(NamespacedSchema.ensureNamespaced(string), "minecraft:purple_shulker_box") ? "minecraft:shulker_box" : string +- ) +- ); +- builder.addFixer( +- ItemRenameFix.create( +- schema49, +- "Colorless shulker item fixer", +- string -> Objects.equals(NamespacedSchema.ensureNamespaced(string), "minecraft:purple_shulker_box") ? "minecraft:shulker_box" : string +- ) +- ); +- Schema schema50 = builder.addSchema(1475, SAME_NAMESPACED); +- builder.addFixer( +- BlockRenameFix.create( +- schema50, +- "Flowing fixer", +- createRenamer(ImmutableMap.of("minecraft:flowing_water", "minecraft:water", "minecraft:flowing_lava", "minecraft:lava")) +- ) +- ); +- Schema schema51 = builder.addSchema(1480, SAME_NAMESPACED); +- builder.addFixer(BlockRenameFix.create(schema51, "Rename coral blocks", createRenamer(RenamedCoralFix.RENAMED_IDS))); +- builder.addFixer(ItemRenameFix.create(schema51, "Rename coral items", createRenamer(RenamedCoralFix.RENAMED_IDS))); ++ builder.addFixer(BlockRenameFix.create(schema49, "Colorless shulker block fixer", (s) -> { ++ return Objects.equals(NamespacedSchema.ensureNamespaced(s), "minecraft:purple_shulker_box") ? "minecraft:shulker_box" : s; ++ })); ++ builder.addFixer(ItemRenameFix.create(schema49, "Colorless shulker item fixer", (s) -> { ++ return Objects.equals(NamespacedSchema.ensureNamespaced(s), "minecraft:purple_shulker_box") ? "minecraft:shulker_box" : s; ++ })); ++ Schema schema50 = builder.addSchema(1475, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(BlockRenameFix.create(schema50, "Flowing fixer", createRenamer(ImmutableMap.of("minecraft:flowing_water", "minecraft:water", "minecraft:flowing_lava", "minecraft:lava")))); ++ Schema schema51 = builder.addSchema(1480, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(BlockRenameFix.create(schema51, "Rename coral blocks", createRenamer(DataConverterCoral.RENAMED_IDS))); ++ builder.addFixer(ItemRenameFix.create(schema51, "Rename coral items", createRenamer(DataConverterCoral.RENAMED_IDS))); + Schema schema52 = builder.addSchema(1481, V1481::new); +- builder.addFixer(new AddNewChoices(schema52, "Add conduit", References.BLOCK_ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema52, "Add conduit", DataConverterTypes.BLOCK_ENTITY)); + Schema schema53 = builder.addSchema(1483, V1483::new); ++ + builder.addFixer(new EntityPufferfishRenameFix(schema53, true)); + builder.addFixer(ItemRenameFix.create(schema53, "Rename pufferfish egg item", createRenamer(EntityPufferfishRenameFix.RENAMED_IDS))); +- Schema schema54 = builder.addSchema(1484, SAME_NAMESPACED); +- builder.addFixer( +- ItemRenameFix.create( +- schema54, +- "Rename seagrass items", +- createRenamer(ImmutableMap.of("minecraft:sea_grass", "minecraft:seagrass", "minecraft:tall_sea_grass", "minecraft:tall_seagrass")) +- ) +- ); +- builder.addFixer( +- BlockRenameFix.create( +- schema54, +- "Rename seagrass blocks", +- createRenamer(ImmutableMap.of("minecraft:sea_grass", "minecraft:seagrass", "minecraft:tall_sea_grass", "minecraft:tall_seagrass")) +- ) +- ); ++ Schema schema54 = builder.addSchema(1484, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(ItemRenameFix.create(schema54, "Rename seagrass items", createRenamer(ImmutableMap.of("minecraft:sea_grass", "minecraft:seagrass", "minecraft:tall_sea_grass", "minecraft:tall_seagrass")))); ++ builder.addFixer(BlockRenameFix.create(schema54, "Rename seagrass blocks", createRenamer(ImmutableMap.of("minecraft:sea_grass", "minecraft:seagrass", "minecraft:tall_sea_grass", "minecraft:tall_seagrass")))); + builder.addFixer(new HeightmapRenamingFix(schema54, false)); + Schema schema55 = builder.addSchema(1486, V1486::new); ++ + builder.addFixer(new EntityCodSalmonFix(schema55, true)); + builder.addFixer(ItemRenameFix.create(schema55, "Rename cod/salmon egg items", createRenamer(EntityCodSalmonFix.RENAMED_EGG_IDS))); +- Schema schema56 = builder.addSchema(1487, SAME_NAMESPACED); +- builder.addFixer( +- ItemRenameFix.create( +- schema56, +- "Rename prismarine_brick(s)_* blocks", +- createRenamer( +- ImmutableMap.of( +- "minecraft:prismarine_bricks_slab", +- "minecraft:prismarine_brick_slab", +- "minecraft:prismarine_bricks_stairs", +- "minecraft:prismarine_brick_stairs" +- ) +- ) +- ) +- ); +- builder.addFixer( +- BlockRenameFix.create( +- schema56, +- "Rename prismarine_brick(s)_* items", +- createRenamer( +- ImmutableMap.of( +- "minecraft:prismarine_bricks_slab", +- "minecraft:prismarine_brick_slab", +- "minecraft:prismarine_bricks_stairs", +- "minecraft:prismarine_brick_stairs" +- ) +- ) +- ) +- ); +- Schema schema57 = builder.addSchema(1488, SAME_NAMESPACED); +- builder.addFixer( +- BlockRenameFix.create( +- schema57, +- "Rename kelp/kelptop", +- createRenamer(ImmutableMap.of("minecraft:kelp_top", "minecraft:kelp", "minecraft:kelp", "minecraft:kelp_plant")) +- ) +- ); ++ Schema schema56 = builder.addSchema(1487, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(ItemRenameFix.create(schema56, "Rename prismarine_brick(s)_* blocks", createRenamer(ImmutableMap.of("minecraft:prismarine_bricks_slab", "minecraft:prismarine_brick_slab", "minecraft:prismarine_bricks_stairs", "minecraft:prismarine_brick_stairs")))); ++ builder.addFixer(BlockRenameFix.create(schema56, "Rename prismarine_brick(s)_* items", createRenamer(ImmutableMap.of("minecraft:prismarine_bricks_slab", "minecraft:prismarine_brick_slab", "minecraft:prismarine_bricks_stairs", "minecraft:prismarine_brick_stairs")))); ++ Schema schema57 = builder.addSchema(1488, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(BlockRenameFix.create(schema57, "Rename kelp/kelptop", createRenamer(ImmutableMap.of("minecraft:kelp_top", "minecraft:kelp", "minecraft:kelp", "minecraft:kelp_plant")))); + builder.addFixer(ItemRenameFix.create(schema57, "Rename kelptop", createRenamer("minecraft:kelp_top", "minecraft:kelp"))); +- builder.addFixer( +- new NamedEntityFix(schema57, false, "Command block block entity custom name fix", References.BLOCK_ENTITY, "minecraft:command_block") { +- @Override +- protected Typed fix(Typed typed) { +- return typed.update(DSL.remainderFinder(), EntityCustomNameToComponentFix::fixTagCustomName); +- } ++ builder.addFixer(new NamedEntityFix(schema57, false, "Command block block entity custom name fix", DataConverterTypes.BLOCK_ENTITY, "minecraft:command_block") { ++ @Override ++ protected Typed fix(Typed typed) { ++ return typed.update(DSL.remainderFinder(), EntityCustomNameToComponentFix::fixTagCustomName); + } +- ); +- builder.addFixer(new NamedEntityFix(schema57, false, "Command block minecart custom name fix", References.ENTITY, "minecraft:commandblock_minecart") { ++ }); ++ builder.addFixer(new NamedEntityFix(schema57, false, "Command block minecart custom name fix", DataConverterTypes.ENTITY, "minecraft:commandblock_minecart") { + @Override + protected Typed fix(Typed typed) { + return typed.update(DSL.remainderFinder(), EntityCustomNameToComponentFix::fixTagCustomName); + } + }); + builder.addFixer(new IglooMetadataRemovalFix(schema57, false)); +- Schema schema58 = builder.addSchema(1490, SAME_NAMESPACED); ++ Schema schema58 = builder.addSchema(1490, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(BlockRenameFix.create(schema58, "Rename melon_block", createRenamer("minecraft:melon_block", "minecraft:melon"))); +- builder.addFixer( +- ItemRenameFix.create( +- schema58, +- "Rename melon_block/melon/speckled_melon", +- createRenamer( +- ImmutableMap.of( +- "minecraft:melon_block", +- "minecraft:melon", +- "minecraft:melon", +- "minecraft:melon_slice", +- "minecraft:speckled_melon", +- "minecraft:glistering_melon_slice" +- ) +- ) +- ) +- ); +- Schema schema59 = builder.addSchema(1492, SAME_NAMESPACED); ++ builder.addFixer(ItemRenameFix.create(schema58, "Rename melon_block/melon/speckled_melon", createRenamer(ImmutableMap.of("minecraft:melon_block", "minecraft:melon", "minecraft:melon", "minecraft:melon_slice", "minecraft:speckled_melon", "minecraft:glistering_melon_slice")))); ++ Schema schema59 = builder.addSchema(1492, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new ChunkStructuresTemplateRenameFix(schema59, false)); +- Schema schema60 = builder.addSchema(1494, SAME_NAMESPACED); ++ Schema schema60 = builder.addSchema(1494, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new ItemStackEnchantmentNamesFix(schema60, false)); +- Schema schema61 = builder.addSchema(1496, SAME_NAMESPACED); ++ Schema schema61 = builder.addSchema(1496, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new LeavesFix(schema61, false)); +- Schema schema62 = builder.addSchema(1500, SAME_NAMESPACED); ++ Schema schema62 = builder.addSchema(1500, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new BlockEntityKeepPacked(schema62, false)); +- Schema schema63 = builder.addSchema(1501, SAME_NAMESPACED); ++ Schema schema63 = builder.addSchema(1501, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new AdvancementsFix(schema63, false)); +- Schema schema64 = builder.addSchema(1502, SAME_NAMESPACED); +- builder.addFixer(new NamespacedTypeRenameFix(schema64, "Recipes fix", References.RECIPE, createRenamer(RecipesFix.RECIPES))); +- Schema schema65 = builder.addSchema(1506, SAME_NAMESPACED); ++ Schema schema64 = builder.addSchema(1502, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(new NamespacedTypeRenameFix(schema64, "Recipes fix", DataConverterTypes.RECIPE, createRenamer(DataConverterRecipes.RECIPES))); ++ Schema schema65 = builder.addSchema(1506, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new LevelDataGeneratorOptionsFix(schema65, false)); + Schema schema66 = builder.addSchema(1510, V1510::new); ++ + builder.addFixer(BlockRenameFix.create(schema66, "Block renamening fix", createRenamer(EntityTheRenameningFix.RENAMED_BLOCKS))); + builder.addFixer(ItemRenameFix.create(schema66, "Item renamening fix", createRenamer(EntityTheRenameningFix.RENAMED_ITEMS))); +- builder.addFixer(new NamespacedTypeRenameFix(schema66, "Recipes renamening fix", References.RECIPE, createRenamer(RecipesRenameningFix.RECIPES))); ++ builder.addFixer(new NamespacedTypeRenameFix(schema66, "Recipes renamening fix", DataConverterTypes.RECIPE, createRenamer(DataConverterRecipeRename.RECIPES))); + builder.addFixer(new EntityTheRenameningFix(schema66, true)); +- builder.addFixer( +- new StatsRenameFix( +- schema66, +- "SwimStatsRenameFix", +- ImmutableMap.of("minecraft:swim_one_cm", "minecraft:walk_on_water_one_cm", "minecraft:dive_one_cm", "minecraft:walk_under_water_one_cm") +- ) +- ); +- Schema schema67 = builder.addSchema(1514, SAME_NAMESPACED); ++ builder.addFixer(new StatsRenameFix(schema66, "SwimStatsRenameFix", ImmutableMap.of("minecraft:swim_one_cm", "minecraft:walk_on_water_one_cm", "minecraft:dive_one_cm", "minecraft:walk_under_water_one_cm"))); ++ Schema schema67 = builder.addSchema(1514, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new ObjectiveDisplayNameFix(schema67, false)); + builder.addFixer(new TeamDisplayNameFix(schema67, false)); + builder.addFixer(new ObjectiveRenderTypeFix(schema67, false)); +- Schema schema68 = builder.addSchema(1515, SAME_NAMESPACED); +- builder.addFixer(BlockRenameFix.create(schema68, "Rename coral fan blocks", createRenamer(RenamedCoralFansFix.RENAMED_IDS))); +- Schema schema69 = builder.addSchema(1624, SAME_NAMESPACED); ++ Schema schema68 = builder.addSchema(1515, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(BlockRenameFix.create(schema68, "Rename coral fan blocks", createRenamer(DataConverterCoralFan.RENAMED_IDS))); ++ Schema schema69 = builder.addSchema(1624, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new TrappedChestBlockEntityFix(schema69, false)); + Schema schema70 = builder.addSchema(1800, V1800::new); +- builder.addFixer(new AddNewChoices(schema70, "Added 1.14 mobs fix", References.ENTITY)); +- builder.addFixer(ItemRenameFix.create(schema70, "Rename dye items", createRenamer(DyeItemRenameFix.RENAMED_IDS))); ++ ++ builder.addFixer(new AddNewChoices(schema70, "Added 1.14 mobs fix", DataConverterTypes.ENTITY)); ++ builder.addFixer(ItemRenameFix.create(schema70, "Rename dye items", createRenamer(DataConverterDye.RENAMED_IDS))); + Schema schema71 = builder.addSchema(1801, V1801::new); +- builder.addFixer(new AddNewChoices(schema71, "Added Illager Beast", References.ENTITY)); +- Schema schema72 = builder.addSchema(1802, SAME_NAMESPACED); +- builder.addFixer( +- BlockRenameFix.create( +- schema72, +- "Rename sign blocks & stone slabs", +- createRenamer( +- ImmutableMap.of( +- "minecraft:stone_slab", +- "minecraft:smooth_stone_slab", +- "minecraft:sign", +- "minecraft:oak_sign", +- "minecraft:wall_sign", +- "minecraft:oak_wall_sign" +- ) +- ) +- ) +- ); +- builder.addFixer( +- ItemRenameFix.create( +- schema72, +- "Rename sign item & stone slabs", +- createRenamer(ImmutableMap.of("minecraft:stone_slab", "minecraft:smooth_stone_slab", "minecraft:sign", "minecraft:oak_sign")) +- ) +- ); +- Schema schema73 = builder.addSchema(1803, SAME_NAMESPACED); ++ ++ builder.addFixer(new AddNewChoices(schema71, "Added Illager Beast", DataConverterTypes.ENTITY)); ++ Schema schema72 = builder.addSchema(1802, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(BlockRenameFix.create(schema72, "Rename sign blocks & stone slabs", createRenamer(ImmutableMap.of("minecraft:stone_slab", "minecraft:smooth_stone_slab", "minecraft:sign", "minecraft:oak_sign", "minecraft:wall_sign", "minecraft:oak_wall_sign")))); ++ builder.addFixer(ItemRenameFix.create(schema72, "Rename sign item & stone slabs", createRenamer(ImmutableMap.of("minecraft:stone_slab", "minecraft:smooth_stone_slab", "minecraft:sign", "minecraft:oak_sign")))); ++ Schema schema73 = builder.addSchema(1803, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new ItemLoreFix(schema73, false)); + Schema schema74 = builder.addSchema(1904, V1904::new); +- builder.addFixer(new AddNewChoices(schema74, "Added Cats", References.ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema74, "Added Cats", DataConverterTypes.ENTITY)); + builder.addFixer(new EntityCatSplitFix(schema74, false)); +- Schema schema75 = builder.addSchema(1905, SAME_NAMESPACED); ++ Schema schema75 = builder.addSchema(1905, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new ChunkStatusFix(schema75, false)); + Schema schema76 = builder.addSchema(1906, V1906::new); +- builder.addFixer(new AddNewChoices(schema76, "Add POI Blocks", References.BLOCK_ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema76, "Add POI Blocks", DataConverterTypes.BLOCK_ENTITY)); + Schema schema77 = builder.addSchema(1909, V1909::new); +- builder.addFixer(new AddNewChoices(schema77, "Add jigsaw", References.BLOCK_ENTITY)); +- Schema schema78 = builder.addSchema(1911, SAME_NAMESPACED); ++ ++ builder.addFixer(new AddNewChoices(schema77, "Add jigsaw", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema78 = builder.addSchema(1911, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new ChunkStatusFix2(schema78, false)); +- Schema schema79 = builder.addSchema(1914, SAME_NAMESPACED); ++ Schema schema79 = builder.addSchema(1914, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new WeaponSmithChestLootTableFix(schema79, false)); +- Schema schema80 = builder.addSchema(1917, SAME_NAMESPACED); ++ Schema schema80 = builder.addSchema(1917, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new CatTypeFix(schema80, false)); +- Schema schema81 = builder.addSchema(1918, SAME_NAMESPACED); ++ Schema schema81 = builder.addSchema(1918, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new VillagerDataFix(schema81, "minecraft:villager")); + builder.addFixer(new VillagerDataFix(schema81, "minecraft:zombie_villager")); + Schema schema82 = builder.addSchema(1920, V1920::new); ++ + builder.addFixer(new NewVillageFix(schema82, false)); +- builder.addFixer(new AddNewChoices(schema82, "Add campfire", References.BLOCK_ENTITY)); +- Schema schema83 = builder.addSchema(1925, SAME_NAMESPACED); ++ builder.addFixer(new AddNewChoices(schema82, "Add campfire", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema83 = builder.addSchema(1925, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new MapIdFix(schema83, false)); + Schema schema84 = builder.addSchema(1928, V1928::new); ++ + builder.addFixer(new EntityRavagerRenameFix(schema84, true)); + builder.addFixer(ItemRenameFix.create(schema84, "Rename ravager egg item", createRenamer(EntityRavagerRenameFix.RENAMED_IDS))); + Schema schema85 = builder.addSchema(1929, V1929::new); +- builder.addFixer(new AddNewChoices(schema85, "Add Wandering Trader and Trader Llama", References.ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema85, "Add Wandering Trader and Trader Llama", DataConverterTypes.ENTITY)); + Schema schema86 = builder.addSchema(1931, V1931::new); +- builder.addFixer(new AddNewChoices(schema86, "Added Fox", References.ENTITY)); +- Schema schema87 = builder.addSchema(1936, SAME_NAMESPACED); ++ ++ builder.addFixer(new AddNewChoices(schema86, "Added Fox", DataConverterTypes.ENTITY)); ++ Schema schema87 = builder.addSchema(1936, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new OptionsAddTextBackgroundFix(schema87, false)); +- Schema schema88 = builder.addSchema(1946, SAME_NAMESPACED); ++ Schema schema88 = builder.addSchema(1946, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new ReorganizePoi(schema88, false)); +- Schema schema89 = builder.addSchema(1948, SAME_NAMESPACED); ++ Schema schema89 = builder.addSchema(1948, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new OminousBannerRenameFix(schema89)); +- Schema schema90 = builder.addSchema(1953, SAME_NAMESPACED); ++ Schema schema90 = builder.addSchema(1953, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new OminousBannerBlockEntityRenameFix(schema90, false)); +- Schema schema91 = builder.addSchema(1955, SAME_NAMESPACED); ++ Schema schema91 = builder.addSchema(1955, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new VillagerRebuildLevelAndXpFix(schema91, false)); + builder.addFixer(new ZombieVillagerRebuildXpFix(schema91, false)); +- Schema schema92 = builder.addSchema(1961, SAME_NAMESPACED); ++ Schema schema92 = builder.addSchema(1961, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new ChunkLightRemoveFix(schema92, false)); +- Schema schema93 = builder.addSchema(1963, SAME_NAMESPACED); ++ Schema schema93 = builder.addSchema(1963, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new RemoveGolemGossipFix(schema93, false)); + Schema schema94 = builder.addSchema(2100, V2100::new); +- builder.addFixer(new AddNewChoices(schema94, "Added Bee and Bee Stinger", References.ENTITY)); +- builder.addFixer(new AddNewChoices(schema94, "Add beehive", References.BLOCK_ENTITY)); +- builder.addFixer( +- new NamespacedTypeRenameFix(schema94, "Rename sugar recipe", References.RECIPE, createRenamer("minecraft:sugar", "sugar_from_sugar_cane")) +- ); +- builder.addFixer( +- new AdvancementsRenameFix( +- schema94, +- false, +- "Rename sugar recipe advancement", +- createRenamer("minecraft:recipes/misc/sugar", "minecraft:recipes/misc/sugar_from_sugar_cane") +- ) +- ); +- Schema schema95 = builder.addSchema(2202, SAME_NAMESPACED); ++ ++ builder.addFixer(new AddNewChoices(schema94, "Added Bee and Bee Stinger", DataConverterTypes.ENTITY)); ++ builder.addFixer(new AddNewChoices(schema94, "Add beehive", DataConverterTypes.BLOCK_ENTITY)); ++ builder.addFixer(new NamespacedTypeRenameFix(schema94, "Rename sugar recipe", DataConverterTypes.RECIPE, createRenamer("minecraft:sugar", "sugar_from_sugar_cane"))); ++ builder.addFixer(new AdvancementsRenameFix(schema94, false, "Rename sugar recipe advancement", createRenamer("minecraft:recipes/misc/sugar", "minecraft:recipes/misc/sugar_from_sugar_cane"))); ++ Schema schema95 = builder.addSchema(2202, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new ChunkBiomeFix(schema95, false)); +- Schema schema96 = builder.addSchema(2209, SAME_NAMESPACED); +- UnaryOperator unaryOperator = createRenamer("minecraft:bee_hive", "minecraft:beehive"); +- builder.addFixer(ItemRenameFix.create(schema96, "Rename bee_hive item to beehive", unaryOperator)); +- builder.addFixer(new PoiTypeRenameFix(schema96, "Rename bee_hive poi to beehive", unaryOperator)); +- builder.addFixer(BlockRenameFix.create(schema96, "Rename bee_hive block to beehive", unaryOperator)); +- Schema schema97 = builder.addSchema(2211, SAME_NAMESPACED); ++ Schema schema96 = builder.addSchema(2209, DataFixers.SAME_NAMESPACED); ++ UnaryOperator unaryoperator = createRenamer("minecraft:bee_hive", "minecraft:beehive"); ++ ++ builder.addFixer(ItemRenameFix.create(schema96, "Rename bee_hive item to beehive", unaryoperator)); ++ builder.addFixer(new PoiTypeRenameFix(schema96, "Rename bee_hive poi to beehive", unaryoperator)); ++ builder.addFixer(BlockRenameFix.create(schema96, "Rename bee_hive block to beehive", unaryoperator)); ++ Schema schema97 = builder.addSchema(2211, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new StructureReferenceCountFix(schema97, false)); +- Schema schema98 = builder.addSchema(2218, SAME_NAMESPACED); ++ Schema schema98 = builder.addSchema(2218, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new ForcePoiRebuild(schema98, false)); + Schema schema99 = builder.addSchema(2501, V2501::new); ++ + builder.addFixer(new FurnaceRecipeFix(schema99, true)); + Schema schema100 = builder.addSchema(2502, V2502::new); +- builder.addFixer(new AddNewChoices(schema100, "Added Hoglin", References.ENTITY)); +- Schema schema101 = builder.addSchema(2503, SAME_NAMESPACED); ++ ++ builder.addFixer(new AddNewChoices(schema100, "Added Hoglin", DataConverterTypes.ENTITY)); ++ Schema schema101 = builder.addSchema(2503, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new WallPropertyFix(schema101, false)); +- builder.addFixer( +- new AdvancementsRenameFix( +- schema101, false, "Composter category change", createRenamer("minecraft:recipes/misc/composter", "minecraft:recipes/decorations/composter") +- ) +- ); ++ builder.addFixer(new AdvancementsRenameFix(schema101, false, "Composter category change", createRenamer("minecraft:recipes/misc/composter", "minecraft:recipes/decorations/composter"))); + Schema schema102 = builder.addSchema(2505, V2505::new); +- builder.addFixer(new AddNewChoices(schema102, "Added Piglin", References.ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema102, "Added Piglin", DataConverterTypes.ENTITY)); + builder.addFixer(new MemoryExpiryDataFix(schema102, "minecraft:villager")); +- Schema schema103 = builder.addSchema(2508, SAME_NAMESPACED); +- builder.addFixer( +- ItemRenameFix.create( +- schema103, +- "Renamed fungi items to fungus", +- createRenamer(ImmutableMap.of("minecraft:warped_fungi", "minecraft:warped_fungus", "minecraft:crimson_fungi", "minecraft:crimson_fungus")) +- ) +- ); +- builder.addFixer( +- BlockRenameFix.create( +- schema103, +- "Renamed fungi blocks to fungus", +- createRenamer(ImmutableMap.of("minecraft:warped_fungi", "minecraft:warped_fungus", "minecraft:crimson_fungi", "minecraft:crimson_fungus")) +- ) +- ); ++ Schema schema103 = builder.addSchema(2508, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(ItemRenameFix.create(schema103, "Renamed fungi items to fungus", createRenamer(ImmutableMap.of("minecraft:warped_fungi", "minecraft:warped_fungus", "minecraft:crimson_fungi", "minecraft:crimson_fungus")))); ++ builder.addFixer(BlockRenameFix.create(schema103, "Renamed fungi blocks to fungus", createRenamer(ImmutableMap.of("minecraft:warped_fungi", "minecraft:warped_fungus", "minecraft:crimson_fungi", "minecraft:crimson_fungus")))); + Schema schema104 = builder.addSchema(2509, V2509::new); ++ + builder.addFixer(new EntityZombifiedPiglinRenameFix(schema104)); + builder.addFixer(ItemRenameFix.create(schema104, "Rename zombie pigman egg item", createRenamer(EntityZombifiedPiglinRenameFix.RENAMED_IDS))); +- Schema schema105 = builder.addSchema(2511, SAME_NAMESPACED); ++ Schema schema105 = builder.addSchema(2511, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new EntityProjectileOwnerFix(schema105)); +- Schema schema106 = builder.addSchema(2514, SAME_NAMESPACED); ++ Schema schema106 = builder.addSchema(2514, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new EntityUUIDFix(schema106)); + builder.addFixer(new BlockEntityUUIDFix(schema106)); + builder.addFixer(new PlayerUUIDFix(schema106)); + builder.addFixer(new LevelUUIDFix(schema106)); + builder.addFixer(new SavedDataUUIDFix(schema106)); + builder.addFixer(new ItemStackUUIDFix(schema106)); +- Schema schema107 = builder.addSchema(2516, SAME_NAMESPACED); ++ Schema schema107 = builder.addSchema(2516, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new GossipUUIDFix(schema107, "minecraft:villager")); + builder.addFixer(new GossipUUIDFix(schema107, "minecraft:zombie_villager")); +- Schema schema108 = builder.addSchema(2518, SAME_NAMESPACED); ++ Schema schema108 = builder.addSchema(2518, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new JigsawPropertiesFix(schema108, false)); + builder.addFixer(new JigsawRotationFix(schema108, false)); + Schema schema109 = builder.addSchema(2519, V2519::new); +- builder.addFixer(new AddNewChoices(schema109, "Added Strider", References.ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema109, "Added Strider", DataConverterTypes.ENTITY)); + Schema schema110 = builder.addSchema(2522, V2522::new); +- builder.addFixer(new AddNewChoices(schema110, "Added Zoglin", References.ENTITY)); +- Schema schema111 = builder.addSchema(2523, SAME_NAMESPACED); ++ ++ builder.addFixer(new AddNewChoices(schema110, "Added Zoglin", DataConverterTypes.ENTITY)); ++ Schema schema111 = builder.addSchema(2523, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new AttributesRename(schema111)); +- Schema schema112 = builder.addSchema(2527, SAME_NAMESPACED); ++ Schema schema112 = builder.addSchema(2527, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new BitStorageAlignFix(schema112)); +- Schema schema113 = builder.addSchema(2528, SAME_NAMESPACED); +- builder.addFixer( +- ItemRenameFix.create( +- schema113, +- "Rename soul fire torch and soul fire lantern", +- createRenamer(ImmutableMap.of("minecraft:soul_fire_torch", "minecraft:soul_torch", "minecraft:soul_fire_lantern", "minecraft:soul_lantern")) +- ) +- ); +- builder.addFixer( +- BlockRenameFix.create( +- schema113, +- "Rename soul fire torch and soul fire lantern", +- createRenamer( +- ImmutableMap.of( +- "minecraft:soul_fire_torch", +- "minecraft:soul_torch", +- "minecraft:soul_fire_wall_torch", +- "minecraft:soul_wall_torch", +- "minecraft:soul_fire_lantern", +- "minecraft:soul_lantern" +- ) +- ) +- ) +- ); +- Schema schema114 = builder.addSchema(2529, SAME_NAMESPACED); ++ Schema schema113 = builder.addSchema(2528, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(ItemRenameFix.create(schema113, "Rename soul fire torch and soul fire lantern", createRenamer(ImmutableMap.of("minecraft:soul_fire_torch", "minecraft:soul_torch", "minecraft:soul_fire_lantern", "minecraft:soul_lantern")))); ++ builder.addFixer(BlockRenameFix.create(schema113, "Rename soul fire torch and soul fire lantern", createRenamer(ImmutableMap.of("minecraft:soul_fire_torch", "minecraft:soul_torch", "minecraft:soul_fire_wall_torch", "minecraft:soul_wall_torch", "minecraft:soul_fire_lantern", "minecraft:soul_lantern")))); ++ Schema schema114 = builder.addSchema(2529, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new StriderGravityFix(schema114, false)); +- Schema schema115 = builder.addSchema(2531, SAME_NAMESPACED); ++ Schema schema115 = builder.addSchema(2531, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new RedstoneWireConnectionsFix(schema115)); +- Schema schema116 = builder.addSchema(2533, SAME_NAMESPACED); ++ Schema schema116 = builder.addSchema(2533, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new VillagerFollowRangeFix(schema116)); +- Schema schema117 = builder.addSchema(2535, SAME_NAMESPACED); ++ Schema schema117 = builder.addSchema(2535, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new EntityShulkerRotationFix(schema117)); +- Schema schema118 = builder.addSchema(2538, SAME_NAMESPACED); ++ Schema schema118 = builder.addSchema(2538, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new LevelLegacyWorldGenSettingsFix(schema118)); +- Schema schema119 = builder.addSchema(2550, SAME_NAMESPACED); ++ Schema schema119 = builder.addSchema(2550, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new WorldGenSettingsFix(schema119)); + Schema schema120 = builder.addSchema(2551, V2551::new); +- builder.addFixer(new WriteAndReadFix(schema120, "add types to WorldGenData", References.WORLD_GEN_SETTINGS)); +- Schema schema121 = builder.addSchema(2552, SAME_NAMESPACED); +- builder.addFixer( +- new NamespacedTypeRenameFix(schema121, "Nether biome rename", References.BIOME, createRenamer("minecraft:nether", "minecraft:nether_wastes")) +- ); +- Schema schema122 = builder.addSchema(2553, SAME_NAMESPACED); +- builder.addFixer(new NamespacedTypeRenameFix(schema122, "Biomes fix", References.BIOME, createRenamer(BiomeFix.BIOMES))); +- Schema schema123 = builder.addSchema(2558, SAME_NAMESPACED); ++ ++ builder.addFixer(new WriteAndReadFix(schema120, "add types to WorldGenData", DataConverterTypes.WORLD_GEN_SETTINGS)); ++ Schema schema121 = builder.addSchema(2552, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(new NamespacedTypeRenameFix(schema121, "Nether biome rename", DataConverterTypes.BIOME, createRenamer("minecraft:nether", "minecraft:nether_wastes"))); ++ Schema schema122 = builder.addSchema(2553, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(new NamespacedTypeRenameFix(schema122, "Biomes fix", DataConverterTypes.BIOME, createRenamer(DataConverterBiome.BIOMES))); ++ Schema schema123 = builder.addSchema(2558, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new MissingDimensionFix(schema123, false)); + builder.addFixer(new OptionsRenameFieldFix(schema123, false, "Rename swapHands setting", "key_key.swapHands", "key_key.swapOffhand")); + Schema schema124 = builder.addSchema(2568, V2568::new); +- builder.addFixer(new AddNewChoices(schema124, "Added Piglin Brute", References.ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema124, "Added Piglin Brute", DataConverterTypes.ENTITY)); + Schema schema125 = builder.addSchema(2571, V2571::new); +- builder.addFixer(new AddNewChoices(schema125, "Added Goat", References.ENTITY)); +- Schema schema126 = builder.addSchema(2679, SAME_NAMESPACED); ++ ++ builder.addFixer(new AddNewChoices(schema125, "Added Goat", DataConverterTypes.ENTITY)); ++ Schema schema126 = builder.addSchema(2679, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new CauldronRenameFix(schema126, false)); +- Schema schema127 = builder.addSchema(2680, SAME_NAMESPACED); ++ Schema schema127 = builder.addSchema(2680, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(ItemRenameFix.create(schema127, "Renamed grass path item to dirt path", createRenamer("minecraft:grass_path", "minecraft:dirt_path"))); +- builder.addFixer( +- BlockRenameFixWithJigsaw.create(schema127, "Renamed grass path block to dirt path", createRenamer("minecraft:grass_path", "minecraft:dirt_path")) +- ); ++ builder.addFixer(BlockRenameFixWithJigsaw.create(schema127, "Renamed grass path block to dirt path", createRenamer("minecraft:grass_path", "minecraft:dirt_path"))); + Schema schema128 = builder.addSchema(2684, V2684::new); +- builder.addFixer(new AddNewChoices(schema128, "Added Sculk Sensor", References.BLOCK_ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema128, "Added Sculk Sensor", DataConverterTypes.BLOCK_ENTITY)); + Schema schema129 = builder.addSchema(2686, V2686::new); +- builder.addFixer(new AddNewChoices(schema129, "Added Axolotl", References.ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema129, "Added Axolotl", DataConverterTypes.ENTITY)); + Schema schema130 = builder.addSchema(2688, V2688::new); +- builder.addFixer(new AddNewChoices(schema130, "Added Glow Squid", References.ENTITY)); +- builder.addFixer(new AddNewChoices(schema130, "Added Glow Item Frame", References.ENTITY)); +- Schema schema131 = builder.addSchema(2690, SAME_NAMESPACED); +- ImmutableMap map = ImmutableMap.builder() +- .put("minecraft:weathered_copper_block", "minecraft:oxidized_copper_block") +- .put("minecraft:semi_weathered_copper_block", "minecraft:weathered_copper_block") +- .put("minecraft:lightly_weathered_copper_block", "minecraft:exposed_copper_block") +- .put("minecraft:weathered_cut_copper", "minecraft:oxidized_cut_copper") +- .put("minecraft:semi_weathered_cut_copper", "minecraft:weathered_cut_copper") +- .put("minecraft:lightly_weathered_cut_copper", "minecraft:exposed_cut_copper") +- .put("minecraft:weathered_cut_copper_stairs", "minecraft:oxidized_cut_copper_stairs") +- .put("minecraft:semi_weathered_cut_copper_stairs", "minecraft:weathered_cut_copper_stairs") +- .put("minecraft:lightly_weathered_cut_copper_stairs", "minecraft:exposed_cut_copper_stairs") +- .put("minecraft:weathered_cut_copper_slab", "minecraft:oxidized_cut_copper_slab") +- .put("minecraft:semi_weathered_cut_copper_slab", "minecraft:weathered_cut_copper_slab") +- .put("minecraft:lightly_weathered_cut_copper_slab", "minecraft:exposed_cut_copper_slab") +- .put("minecraft:waxed_semi_weathered_copper", "minecraft:waxed_weathered_copper") +- .put("minecraft:waxed_lightly_weathered_copper", "minecraft:waxed_exposed_copper") +- .put("minecraft:waxed_semi_weathered_cut_copper", "minecraft:waxed_weathered_cut_copper") +- .put("minecraft:waxed_lightly_weathered_cut_copper", "minecraft:waxed_exposed_cut_copper") +- .put("minecraft:waxed_semi_weathered_cut_copper_stairs", "minecraft:waxed_weathered_cut_copper_stairs") +- .put("minecraft:waxed_lightly_weathered_cut_copper_stairs", "minecraft:waxed_exposed_cut_copper_stairs") +- .put("minecraft:waxed_semi_weathered_cut_copper_slab", "minecraft:waxed_weathered_cut_copper_slab") +- .put("minecraft:waxed_lightly_weathered_cut_copper_slab", "minecraft:waxed_exposed_cut_copper_slab") +- .build(); +- builder.addFixer(ItemRenameFix.create(schema131, "Renamed copper block items to new oxidized terms", createRenamer(map))); +- builder.addFixer(BlockRenameFixWithJigsaw.create(schema131, "Renamed copper blocks to new oxidized terms", createRenamer(map))); +- Schema schema132 = builder.addSchema(2691, SAME_NAMESPACED); +- ImmutableMap map1 = ImmutableMap.builder() +- .put("minecraft:waxed_copper", "minecraft:waxed_copper_block") +- .put("minecraft:oxidized_copper_block", "minecraft:oxidized_copper") +- .put("minecraft:weathered_copper_block", "minecraft:weathered_copper") +- .put("minecraft:exposed_copper_block", "minecraft:exposed_copper") +- .build(); +- builder.addFixer(ItemRenameFix.create(schema132, "Rename copper item suffixes", createRenamer(map1))); +- builder.addFixer(BlockRenameFixWithJigsaw.create(schema132, "Rename copper blocks suffixes", createRenamer(map1))); +- Schema schema133 = builder.addSchema(2693, SAME_NAMESPACED); +- builder.addFixer(new AddFlagIfNotPresentFix(schema133, References.WORLD_GEN_SETTINGS, "has_increased_height_already", false)); +- Schema schema134 = builder.addSchema(2696, SAME_NAMESPACED); +- ImmutableMap map2 = ImmutableMap.builder() +- .put("minecraft:grimstone", "minecraft:deepslate") +- .put("minecraft:grimstone_slab", "minecraft:cobbled_deepslate_slab") +- .put("minecraft:grimstone_stairs", "minecraft:cobbled_deepslate_stairs") +- .put("minecraft:grimstone_wall", "minecraft:cobbled_deepslate_wall") +- .put("minecraft:polished_grimstone", "minecraft:polished_deepslate") +- .put("minecraft:polished_grimstone_slab", "minecraft:polished_deepslate_slab") +- .put("minecraft:polished_grimstone_stairs", "minecraft:polished_deepslate_stairs") +- .put("minecraft:polished_grimstone_wall", "minecraft:polished_deepslate_wall") +- .put("minecraft:grimstone_tiles", "minecraft:deepslate_tiles") +- .put("minecraft:grimstone_tile_slab", "minecraft:deepslate_tile_slab") +- .put("minecraft:grimstone_tile_stairs", "minecraft:deepslate_tile_stairs") +- .put("minecraft:grimstone_tile_wall", "minecraft:deepslate_tile_wall") +- .put("minecraft:grimstone_bricks", "minecraft:deepslate_bricks") +- .put("minecraft:grimstone_brick_slab", "minecraft:deepslate_brick_slab") +- .put("minecraft:grimstone_brick_stairs", "minecraft:deepslate_brick_stairs") +- .put("minecraft:grimstone_brick_wall", "minecraft:deepslate_brick_wall") +- .put("minecraft:chiseled_grimstone", "minecraft:chiseled_deepslate") +- .build(); +- builder.addFixer(ItemRenameFix.create(schema134, "Renamed grimstone block items to deepslate", createRenamer(map2))); +- builder.addFixer(BlockRenameFixWithJigsaw.create(schema134, "Renamed grimstone blocks to deepslate", createRenamer(map2))); +- Schema schema135 = builder.addSchema(2700, SAME_NAMESPACED); +- builder.addFixer( +- BlockRenameFixWithJigsaw.create( +- schema135, +- "Renamed cave vines blocks", +- createRenamer(ImmutableMap.of("minecraft:cave_vines_head", "minecraft:cave_vines", "minecraft:cave_vines_body", "minecraft:cave_vines_plant")) +- ) +- ); +- Schema schema136 = builder.addSchema(2701, SAME_NAMESPACED); ++ ++ builder.addFixer(new AddNewChoices(schema130, "Added Glow Squid", DataConverterTypes.ENTITY)); ++ builder.addFixer(new AddNewChoices(schema130, "Added Glow Item Frame", DataConverterTypes.ENTITY)); ++ Schema schema131 = builder.addSchema(2690, DataFixers.SAME_NAMESPACED); ++ // CraftBukkit - decompile error ++ ImmutableMap immutablemap = ImmutableMap.builder().put("minecraft:weathered_copper_block", "minecraft:oxidized_copper_block").put("minecraft:semi_weathered_copper_block", "minecraft:weathered_copper_block").put("minecraft:lightly_weathered_copper_block", "minecraft:exposed_copper_block").put("minecraft:weathered_cut_copper", "minecraft:oxidized_cut_copper").put("minecraft:semi_weathered_cut_copper", "minecraft:weathered_cut_copper").put("minecraft:lightly_weathered_cut_copper", "minecraft:exposed_cut_copper").put("minecraft:weathered_cut_copper_stairs", "minecraft:oxidized_cut_copper_stairs").put("minecraft:semi_weathered_cut_copper_stairs", "minecraft:weathered_cut_copper_stairs").put("minecraft:lightly_weathered_cut_copper_stairs", "minecraft:exposed_cut_copper_stairs").put("minecraft:weathered_cut_copper_slab", "minecraft:oxidized_cut_copper_slab").put("minecraft:semi_weathered_cut_copper_slab", "minecraft:weathered_cut_copper_slab").put("minecraft:lightly_weathered_cut_copper_slab", "minecraft:exposed_cut_copper_slab").put("minecraft:waxed_semi_weathered_copper", "minecraft:waxed_weathered_copper").put("minecraft:waxed_lightly_weathered_copper", "minecraft:waxed_exposed_copper").put("minecraft:waxed_semi_weathered_cut_copper", "minecraft:waxed_weathered_cut_copper").put("minecraft:waxed_lightly_weathered_cut_copper", "minecraft:waxed_exposed_cut_copper").put("minecraft:waxed_semi_weathered_cut_copper_stairs", "minecraft:waxed_weathered_cut_copper_stairs").put("minecraft:waxed_lightly_weathered_cut_copper_stairs", "minecraft:waxed_exposed_cut_copper_stairs").put("minecraft:waxed_semi_weathered_cut_copper_slab", "minecraft:waxed_weathered_cut_copper_slab").put("minecraft:waxed_lightly_weathered_cut_copper_slab", "minecraft:waxed_exposed_cut_copper_slab").build(); ++ ++ builder.addFixer(ItemRenameFix.create(schema131, "Renamed copper block items to new oxidized terms", createRenamer(immutablemap))); ++ builder.addFixer(BlockRenameFixWithJigsaw.create(schema131, "Renamed copper blocks to new oxidized terms", createRenamer(immutablemap))); ++ Schema schema132 = builder.addSchema(2691, DataFixers.SAME_NAMESPACED); ++ // CraftBukkit - decompile error ++ ImmutableMap immutablemap1 = ImmutableMap.builder().put("minecraft:waxed_copper", "minecraft:waxed_copper_block").put("minecraft:oxidized_copper_block", "minecraft:oxidized_copper").put("minecraft:weathered_copper_block", "minecraft:weathered_copper").put("minecraft:exposed_copper_block", "minecraft:exposed_copper").build(); ++ ++ builder.addFixer(ItemRenameFix.create(schema132, "Rename copper item suffixes", createRenamer(immutablemap1))); ++ builder.addFixer(BlockRenameFixWithJigsaw.create(schema132, "Rename copper blocks suffixes", createRenamer(immutablemap1))); ++ Schema schema133 = builder.addSchema(2693, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(new AddFlagIfNotPresentFix(schema133, DataConverterTypes.WORLD_GEN_SETTINGS, "has_increased_height_already", false)); ++ Schema schema134 = builder.addSchema(2696, DataFixers.SAME_NAMESPACED); ++ // CraftBukkit - decompile error ++ ImmutableMap immutablemap2 = ImmutableMap.builder().put("minecraft:grimstone", "minecraft:deepslate").put("minecraft:grimstone_slab", "minecraft:cobbled_deepslate_slab").put("minecraft:grimstone_stairs", "minecraft:cobbled_deepslate_stairs").put("minecraft:grimstone_wall", "minecraft:cobbled_deepslate_wall").put("minecraft:polished_grimstone", "minecraft:polished_deepslate").put("minecraft:polished_grimstone_slab", "minecraft:polished_deepslate_slab").put("minecraft:polished_grimstone_stairs", "minecraft:polished_deepslate_stairs").put("minecraft:polished_grimstone_wall", "minecraft:polished_deepslate_wall").put("minecraft:grimstone_tiles", "minecraft:deepslate_tiles").put("minecraft:grimstone_tile_slab", "minecraft:deepslate_tile_slab").put("minecraft:grimstone_tile_stairs", "minecraft:deepslate_tile_stairs").put("minecraft:grimstone_tile_wall", "minecraft:deepslate_tile_wall").put("minecraft:grimstone_bricks", "minecraft:deepslate_bricks").put("minecraft:grimstone_brick_slab", "minecraft:deepslate_brick_slab").put("minecraft:grimstone_brick_stairs", "minecraft:deepslate_brick_stairs").put("minecraft:grimstone_brick_wall", "minecraft:deepslate_brick_wall").put("minecraft:chiseled_grimstone", "minecraft:chiseled_deepslate").build(); ++ ++ builder.addFixer(ItemRenameFix.create(schema134, "Renamed grimstone block items to deepslate", createRenamer(immutablemap2))); ++ builder.addFixer(BlockRenameFixWithJigsaw.create(schema134, "Renamed grimstone blocks to deepslate", createRenamer(immutablemap2))); ++ Schema schema135 = builder.addSchema(2700, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(BlockRenameFixWithJigsaw.create(schema135, "Renamed cave vines blocks", createRenamer(ImmutableMap.of("minecraft:cave_vines_head", "minecraft:cave_vines", "minecraft:cave_vines_body", "minecraft:cave_vines_plant")))); ++ Schema schema136 = builder.addSchema(2701, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new SavedDataFeaturePoolElementFix(schema136)); +- Schema schema137 = builder.addSchema(2702, SAME_NAMESPACED); ++ Schema schema137 = builder.addSchema(2702, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new AbstractArrowPickupFix(schema137)); + Schema schema138 = builder.addSchema(2704, V2704::new); +- builder.addFixer(new AddNewChoices(schema138, "Added Goat", References.ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema138, "Added Goat", DataConverterTypes.ENTITY)); + Schema schema139 = builder.addSchema(2707, V2707::new); +- builder.addFixer(new AddNewChoices(schema139, "Added Marker", References.ENTITY)); +- builder.addFixer(new AddFlagIfNotPresentFix(schema139, References.WORLD_GEN_SETTINGS, "has_increased_height_already", true)); +- Schema schema140 = builder.addSchema(2710, SAME_NAMESPACED); +- builder.addFixer( +- new StatsRenameFix(schema140, "Renamed play_one_minute stat to play_time", ImmutableMap.of("minecraft:play_one_minute", "minecraft:play_time")) +- ); +- Schema schema141 = builder.addSchema(2717, SAME_NAMESPACED); +- builder.addFixer( +- ItemRenameFix.create( +- schema141, +- "Rename azalea_leaves_flowers", +- createRenamer(ImmutableMap.of("minecraft:azalea_leaves_flowers", "minecraft:flowering_azalea_leaves")) +- ) +- ); +- builder.addFixer( +- BlockRenameFix.create( +- schema141, +- "Rename azalea_leaves_flowers items", +- createRenamer(ImmutableMap.of("minecraft:azalea_leaves_flowers", "minecraft:flowering_azalea_leaves")) +- ) +- ); +- Schema schema142 = builder.addSchema(2825, SAME_NAMESPACED); +- builder.addFixer(new AddFlagIfNotPresentFix(schema142, References.WORLD_GEN_SETTINGS, "has_increased_height_already", false)); ++ ++ builder.addFixer(new AddNewChoices(schema139, "Added Marker", DataConverterTypes.ENTITY)); ++ builder.addFixer(new AddFlagIfNotPresentFix(schema139, DataConverterTypes.WORLD_GEN_SETTINGS, "has_increased_height_already", true)); ++ Schema schema140 = builder.addSchema(2710, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(new StatsRenameFix(schema140, "Renamed play_one_minute stat to play_time", ImmutableMap.of("minecraft:play_one_minute", "minecraft:play_time"))); ++ Schema schema141 = builder.addSchema(2717, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(ItemRenameFix.create(schema141, "Rename azalea_leaves_flowers", createRenamer(ImmutableMap.of("minecraft:azalea_leaves_flowers", "minecraft:flowering_azalea_leaves")))); ++ builder.addFixer(BlockRenameFix.create(schema141, "Rename azalea_leaves_flowers items", createRenamer(ImmutableMap.of("minecraft:azalea_leaves_flowers", "minecraft:flowering_azalea_leaves")))); ++ Schema schema142 = builder.addSchema(2825, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(new AddFlagIfNotPresentFix(schema142, DataConverterTypes.WORLD_GEN_SETTINGS, "has_increased_height_already", false)); + Schema schema143 = builder.addSchema(2831, V2831::new); ++ + builder.addFixer(new SpawnerDataFix(schema143)); + Schema schema144 = builder.addSchema(2832, V2832::new); ++ + builder.addFixer(new WorldGenSettingsHeightAndBiomeFix(schema144)); + builder.addFixer(new ChunkHeightAndBiomeFix(schema144)); +- Schema schema145 = builder.addSchema(2833, SAME_NAMESPACED); ++ Schema schema145 = builder.addSchema(2833, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new WorldGenSettingsDisallowOldCustomWorldsFix(schema145)); +- Schema schema146 = builder.addSchema(2838, SAME_NAMESPACED); +- builder.addFixer( +- new NamespacedTypeRenameFix(schema146, "Caves and Cliffs biome renames", References.BIOME, createRenamer(CavesAndCliffsRenames.RENAMES)) +- ); +- Schema schema147 = builder.addSchema(2841, SAME_NAMESPACED); ++ Schema schema146 = builder.addSchema(2838, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(new NamespacedTypeRenameFix(schema146, "Caves and Cliffs biome renames", DataConverterTypes.BIOME, createRenamer(CavesAndCliffsRenames.RENAMES))); ++ Schema schema147 = builder.addSchema(2841, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new ChunkProtoTickListFix(schema147)); + Schema schema148 = builder.addSchema(2842, V2842::new); ++ + builder.addFixer(new ChunkRenamesFix(schema148)); +- Schema schema149 = builder.addSchema(2843, SAME_NAMESPACED); ++ Schema schema149 = builder.addSchema(2843, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new OverreachingTickFix(schema149)); +- builder.addFixer( +- new NamespacedTypeRenameFix( +- schema149, "Remove Deep Warm Ocean", References.BIOME, createRenamer("minecraft:deep_warm_ocean", "minecraft:warm_ocean") +- ) +- ); +- Schema schema150 = builder.addSchema(2846, SAME_NAMESPACED); +- builder.addFixer( +- new AdvancementsRenameFix( +- schema150, +- false, +- "Rename some C&C part 2 advancements", +- createRenamer( +- ImmutableMap.of( +- "minecraft:husbandry/play_jukebox_in_meadows", +- "minecraft:adventure/play_jukebox_in_meadows", +- "minecraft:adventure/caves_and_cliff", +- "minecraft:adventure/fall_from_world_height", +- "minecraft:adventure/ride_strider_in_overworld_lava", +- "minecraft:nether/ride_strider_in_overworld_lava" +- ) +- ) +- ) +- ); +- Schema schema151 = builder.addSchema(2852, SAME_NAMESPACED); ++ builder.addFixer(new NamespacedTypeRenameFix(schema149, "Remove Deep Warm Ocean", DataConverterTypes.BIOME, createRenamer("minecraft:deep_warm_ocean", "minecraft:warm_ocean"))); ++ Schema schema150 = builder.addSchema(2846, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(new AdvancementsRenameFix(schema150, false, "Rename some C&C part 2 advancements", createRenamer(ImmutableMap.of("minecraft:husbandry/play_jukebox_in_meadows", "minecraft:adventure/play_jukebox_in_meadows", "minecraft:adventure/caves_and_cliff", "minecraft:adventure/fall_from_world_height", "minecraft:adventure/ride_strider_in_overworld_lava", "minecraft:nether/ride_strider_in_overworld_lava")))); ++ Schema schema151 = builder.addSchema(2852, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new WorldGenSettingsDisallowOldCustomWorldsFix(schema151)); +- Schema schema152 = builder.addSchema(2967, SAME_NAMESPACED); ++ Schema schema152 = builder.addSchema(2967, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new StructureSettingsFlattenFix(schema152)); +- Schema schema153 = builder.addSchema(2970, SAME_NAMESPACED); ++ Schema schema153 = builder.addSchema(2970, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new StructuresBecomeConfiguredFix(schema153)); + Schema schema154 = builder.addSchema(3076, V3076::new); +- builder.addFixer(new AddNewChoices(schema154, "Added Sculk Catalyst", References.BLOCK_ENTITY)); +- Schema schema155 = builder.addSchema(3077, SAME_NAMESPACED); ++ ++ builder.addFixer(new AddNewChoices(schema154, "Added Sculk Catalyst", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema155 = builder.addSchema(3077, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new ChunkDeleteIgnoredLightDataFix(schema155)); + Schema schema156 = builder.addSchema(3078, V3078::new); +- builder.addFixer(new AddNewChoices(schema156, "Added Frog", References.ENTITY)); +- builder.addFixer(new AddNewChoices(schema156, "Added Tadpole", References.ENTITY)); +- builder.addFixer(new AddNewChoices(schema156, "Added Sculk Shrieker", References.BLOCK_ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema156, "Added Frog", DataConverterTypes.ENTITY)); ++ builder.addFixer(new AddNewChoices(schema156, "Added Tadpole", DataConverterTypes.ENTITY)); ++ builder.addFixer(new AddNewChoices(schema156, "Added Sculk Shrieker", DataConverterTypes.BLOCK_ENTITY)); + Schema schema157 = builder.addSchema(3081, V3081::new); +- builder.addFixer(new AddNewChoices(schema157, "Added Warden", References.ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema157, "Added Warden", DataConverterTypes.ENTITY)); + Schema schema158 = builder.addSchema(3082, V3082::new); +- builder.addFixer(new AddNewChoices(schema158, "Added Chest Boat", References.ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema158, "Added Chest Boat", DataConverterTypes.ENTITY)); + Schema schema159 = builder.addSchema(3083, V3083::new); +- builder.addFixer(new AddNewChoices(schema159, "Added Allay", References.ENTITY)); +- Schema schema160 = builder.addSchema(3084, SAME_NAMESPACED); +- builder.addFixer( +- new NamespacedTypeRenameFix( +- schema160, +- "game_event_renames_3084", +- References.GAME_EVENT_NAME, +- createRenamer( +- ImmutableMap.builder() +- .put("minecraft:block_press", "minecraft:block_activate") +- .put("minecraft:block_switch", "minecraft:block_activate") +- .put("minecraft:block_unpress", "minecraft:block_deactivate") +- .put("minecraft:block_unswitch", "minecraft:block_deactivate") +- .put("minecraft:drinking_finish", "minecraft:drink") +- .put("minecraft:elytra_free_fall", "minecraft:elytra_glide") +- .put("minecraft:entity_damaged", "minecraft:entity_damage") +- .put("minecraft:entity_dying", "minecraft:entity_die") +- .put("minecraft:entity_killed", "minecraft:entity_die") +- .put("minecraft:mob_interact", "minecraft:entity_interact") +- .put("minecraft:ravager_roar", "minecraft:entity_roar") +- .put("minecraft:ring_bell", "minecraft:block_change") +- .put("minecraft:shulker_close", "minecraft:container_close") +- .put("minecraft:shulker_open", "minecraft:container_open") +- .put("minecraft:wolf_shaking", "minecraft:entity_shake") +- .build() +- ) +- ) +- ); +- Schema schema161 = builder.addSchema(3086, SAME_NAMESPACED); +- builder.addFixer( +- new EntityVariantFix( +- schema161, "Change cat variant type", References.ENTITY, "minecraft:cat", "CatType", Util.make(new Int2ObjectOpenHashMap(), map5 -> { +- map5.defaultReturnValue("minecraft:tabby"); +- map5.put(0, "minecraft:tabby"); +- map5.put(1, "minecraft:black"); +- map5.put(2, "minecraft:red"); +- map5.put(3, "minecraft:siamese"); +- map5.put(4, "minecraft:british"); +- map5.put(5, "minecraft:calico"); +- map5.put(6, "minecraft:persian"); +- map5.put(7, "minecraft:ragdoll"); +- map5.put(8, "minecraft:white"); +- map5.put(9, "minecraft:jellie"); +- map5.put(10, "minecraft:all_black"); +- })::get +- ) +- ); +- ImmutableMap map3 = ImmutableMap.builder() +- .put("textures/entity/cat/tabby.png", "minecraft:tabby") +- .put("textures/entity/cat/black.png", "minecraft:black") +- .put("textures/entity/cat/red.png", "minecraft:red") +- .put("textures/entity/cat/siamese.png", "minecraft:siamese") +- .put("textures/entity/cat/british_shorthair.png", "minecraft:british") +- .put("textures/entity/cat/calico.png", "minecraft:calico") +- .put("textures/entity/cat/persian.png", "minecraft:persian") +- .put("textures/entity/cat/ragdoll.png", "minecraft:ragdoll") +- .put("textures/entity/cat/white.png", "minecraft:white") +- .put("textures/entity/cat/jellie.png", "minecraft:jellie") +- .put("textures/entity/cat/all_black.png", "minecraft:all_black") +- .build(); +- builder.addFixer( +- new CriteriaRenameFix( +- schema161, "Migrate cat variant advancement", "minecraft:husbandry/complete_catalogue", string -> map3.getOrDefault(string, string) +- ) +- ); +- Schema schema162 = builder.addSchema(3087, SAME_NAMESPACED); +- builder.addFixer( +- new EntityVariantFix( +- schema162, "Change frog variant type", References.ENTITY, "minecraft:frog", "Variant", Util.make(new Int2ObjectOpenHashMap(), map5 -> { +- map5.put(0, "minecraft:temperate"); +- map5.put(1, "minecraft:warm"); +- map5.put(2, "minecraft:cold"); +- })::get +- ) +- ); +- Schema schema163 = builder.addSchema(3090, SAME_NAMESPACED); ++ ++ builder.addFixer(new AddNewChoices(schema159, "Added Allay", DataConverterTypes.ENTITY)); ++ Schema schema160 = builder.addSchema(3084, DataFixers.SAME_NAMESPACED); ++ ++ // CraftBukkit - decompile error ++ builder.addFixer(new NamespacedTypeRenameFix(schema160, "game_event_renames_3084", DataConverterTypes.GAME_EVENT_NAME, createRenamer(ImmutableMap.builder().put("minecraft:block_press", "minecraft:block_activate").put("minecraft:block_switch", "minecraft:block_activate").put("minecraft:block_unpress", "minecraft:block_deactivate").put("minecraft:block_unswitch", "minecraft:block_deactivate").put("minecraft:drinking_finish", "minecraft:drink").put("minecraft:elytra_free_fall", "minecraft:elytra_glide").put("minecraft:entity_damaged", "minecraft:entity_damage").put("minecraft:entity_dying", "minecraft:entity_die").put("minecraft:entity_killed", "minecraft:entity_die").put("minecraft:mob_interact", "minecraft:entity_interact").put("minecraft:ravager_roar", "minecraft:entity_roar").put("minecraft:ring_bell", "minecraft:block_change").put("minecraft:shulker_close", "minecraft:container_close").put("minecraft:shulker_open", "minecraft:container_open").put("minecraft:wolf_shaking", "minecraft:entity_shake").build()))); ++ Schema schema161 = builder.addSchema(3086, DataFixers.SAME_NAMESPACED); ++ TypeReference typereference = DataConverterTypes.ENTITY; ++ Int2ObjectOpenHashMap int2objectopenhashmap = (Int2ObjectOpenHashMap) Util.make(new Int2ObjectOpenHashMap(), (int2objectopenhashmap1) -> { // CraftBukkit - decompile error ++ int2objectopenhashmap1.defaultReturnValue("minecraft:tabby"); ++ int2objectopenhashmap1.put(0, "minecraft:tabby"); ++ int2objectopenhashmap1.put(1, "minecraft:black"); ++ int2objectopenhashmap1.put(2, "minecraft:red"); ++ int2objectopenhashmap1.put(3, "minecraft:siamese"); ++ int2objectopenhashmap1.put(4, "minecraft:british"); ++ int2objectopenhashmap1.put(5, "minecraft:calico"); ++ int2objectopenhashmap1.put(6, "minecraft:persian"); ++ int2objectopenhashmap1.put(7, "minecraft:ragdoll"); ++ int2objectopenhashmap1.put(8, "minecraft:white"); ++ int2objectopenhashmap1.put(9, "minecraft:jellie"); ++ int2objectopenhashmap1.put(10, "minecraft:all_black"); ++ }); ++ ++ Objects.requireNonNull(int2objectopenhashmap); ++ builder.addFixer(new EntityVariantFix(schema161, "Change cat variant type", typereference, "minecraft:cat", "CatType", int2objectopenhashmap::get)); ++ // CraftBukkit - decompile error ++ ImmutableMap immutablemap3 = ImmutableMap.builder().put("textures/entity/cat/tabby.png", "minecraft:tabby").put("textures/entity/cat/black.png", "minecraft:black").put("textures/entity/cat/red.png", "minecraft:red").put("textures/entity/cat/siamese.png", "minecraft:siamese").put("textures/entity/cat/british_shorthair.png", "minecraft:british").put("textures/entity/cat/calico.png", "minecraft:calico").put("textures/entity/cat/persian.png", "minecraft:persian").put("textures/entity/cat/ragdoll.png", "minecraft:ragdoll").put("textures/entity/cat/white.png", "minecraft:white").put("textures/entity/cat/jellie.png", "minecraft:jellie").put("textures/entity/cat/all_black.png", "minecraft:all_black").build(); ++ ++ builder.addFixer(new CriteriaRenameFix(schema161, "Migrate cat variant advancement", "minecraft:husbandry/complete_catalogue", (s) -> { ++ return (String) immutablemap3.getOrDefault(s, s); ++ })); ++ Schema schema162 = builder.addSchema(3087, DataFixers.SAME_NAMESPACED); ++ ++ typereference = DataConverterTypes.ENTITY; ++ int2objectopenhashmap = (Int2ObjectOpenHashMap) Util.make(new Int2ObjectOpenHashMap(), (int2objectopenhashmap1) -> { ++ int2objectopenhashmap1.put(0, "minecraft:temperate"); ++ int2objectopenhashmap1.put(1, "minecraft:warm"); ++ int2objectopenhashmap1.put(2, "minecraft:cold"); ++ }); ++ Objects.requireNonNull(int2objectopenhashmap); ++ builder.addFixer(new EntityVariantFix(schema162, "Change frog variant type", typereference, "minecraft:frog", "Variant", int2objectopenhashmap::get)); ++ Schema schema163 = builder.addSchema(3090, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new EntityPaintingFieldsRenameFix(schema163)); +- Schema schema164 = builder.addSchema(3093, SAME_NAMESPACED); ++ Schema schema164 = builder.addSchema(3093, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new EntityGoatMissingStateFix(schema164)); +- Schema schema165 = builder.addSchema(3094, SAME_NAMESPACED); ++ Schema schema165 = builder.addSchema(3094, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new GoatHornIdFix(schema165)); +- Schema schema166 = builder.addSchema(3097, SAME_NAMESPACED); ++ Schema schema166 = builder.addSchema(3097, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new FilteredBooksFix(schema166)); + builder.addFixer(new FilteredSignsFix(schema166)); +- Map map4 = Map.of("minecraft:british", "minecraft:british_shorthair"); +- builder.addFixer(new VariantRenameFix(schema166, "Rename british shorthair", References.ENTITY, "minecraft:cat", map4)); +- builder.addFixer( +- new CriteriaRenameFix( +- schema166, +- "Migrate cat variant advancement for british shorthair", +- "minecraft:husbandry/complete_catalogue", +- string -> map4.getOrDefault(string, string) +- ) +- ); +- builder.addFixer(new PoiTypeRemoveFix(schema166, "Remove unpopulated villager PoI types", Set.of("minecraft:unemployed", "minecraft:nitwit")::contains)); +- Schema schema167 = builder.addSchema(3108, SAME_NAMESPACED); ++ Map map = Map.of("minecraft:british", "minecraft:british_shorthair"); ++ ++ builder.addFixer(new VariantRenameFix(schema166, "Rename british shorthair", DataConverterTypes.ENTITY, "minecraft:cat", map)); ++ builder.addFixer(new CriteriaRenameFix(schema166, "Migrate cat variant advancement for british shorthair", "minecraft:husbandry/complete_catalogue", (s) -> { ++ return (String) map.getOrDefault(s, s); ++ })); ++ Set set = Set.of("minecraft:unemployed", "minecraft:nitwit"); ++ ++ Objects.requireNonNull(set); ++ builder.addFixer(new PoiTypeRemoveFix(schema166, "Remove unpopulated villager PoI types", set::contains)); ++ Schema schema167 = builder.addSchema(3108, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new BlendingDataRemoveFromNetherEndFix(schema167)); +- Schema schema168 = builder.addSchema(3201, SAME_NAMESPACED); ++ Schema schema168 = builder.addSchema(3201, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new OptionsProgrammerArtFix(schema168)); + Schema schema169 = builder.addSchema(3202, V3202::new); +- builder.addFixer(new AddNewChoices(schema169, "Added Hanging Sign", References.BLOCK_ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema169, "Added Hanging Sign", DataConverterTypes.BLOCK_ENTITY)); + Schema schema170 = builder.addSchema(3203, V3203::new); +- builder.addFixer(new AddNewChoices(schema170, "Added Camel", References.ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema170, "Added Camel", DataConverterTypes.ENTITY)); + Schema schema171 = builder.addSchema(3204, V3204::new); +- builder.addFixer(new AddNewChoices(schema171, "Added Chiseled Bookshelf", References.BLOCK_ENTITY)); +- Schema schema172 = builder.addSchema(3209, SAME_NAMESPACED); ++ ++ builder.addFixer(new AddNewChoices(schema171, "Added Chiseled Bookshelf", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema172 = builder.addSchema(3209, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new ItemStackSpawnEggFix(schema172, false, "minecraft:pig_spawn_egg")); +- Schema schema173 = builder.addSchema(3214, SAME_NAMESPACED); ++ Schema schema173 = builder.addSchema(3214, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new OptionsAmbientOcclusionFix(schema173)); +- Schema schema174 = builder.addSchema(3319, SAME_NAMESPACED); ++ Schema schema174 = builder.addSchema(3319, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new OptionsAccessibilityOnboardFix(schema174)); +- Schema schema175 = builder.addSchema(3322, SAME_NAMESPACED); ++ Schema schema175 = builder.addSchema(3322, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new EffectDurationFix(schema175)); + Schema schema176 = builder.addSchema(3325, V3325::new); +- builder.addFixer(new AddNewChoices(schema176, "Added displays", References.ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema176, "Added displays", DataConverterTypes.ENTITY)); + Schema schema177 = builder.addSchema(3326, V3326::new); +- builder.addFixer(new AddNewChoices(schema177, "Added Sniffer", References.ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema177, "Added Sniffer", DataConverterTypes.ENTITY)); + Schema schema178 = builder.addSchema(3327, V3327::new); +- builder.addFixer(new AddNewChoices(schema178, "Archaeology", References.BLOCK_ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema178, "Archaeology", DataConverterTypes.BLOCK_ENTITY)); + Schema schema179 = builder.addSchema(3328, V3328::new); +- builder.addFixer(new AddNewChoices(schema179, "Added interaction", References.ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema179, "Added interaction", DataConverterTypes.ENTITY)); + Schema schema180 = builder.addSchema(3438, V3438::new); +- builder.addFixer( +- BlockEntityRenameFix.create( +- schema180, "Rename Suspicious Sand to Brushable Block", createRenamer("minecraft:suspicious_sand", "minecraft:brushable_block") +- ) +- ); ++ ++ builder.addFixer(BlockEntityRenameFix.create(schema180, "Rename Suspicious Sand to Brushable Block", createRenamer("minecraft:suspicious_sand", "minecraft:brushable_block"))); + builder.addFixer(new EntityBrushableBlockFieldsRenameFix(schema180)); +- builder.addFixer( +- ItemRenameFix.create( +- schema180, +- "Pottery shard renaming", +- createRenamer( +- ImmutableMap.of( +- "minecraft:pottery_shard_archer", +- "minecraft:archer_pottery_shard", +- "minecraft:pottery_shard_prize", +- "minecraft:prize_pottery_shard", +- "minecraft:pottery_shard_arms_up", +- "minecraft:arms_up_pottery_shard", +- "minecraft:pottery_shard_skull", +- "minecraft:skull_pottery_shard" +- ) +- ) +- ) +- ); +- builder.addFixer(new AddNewChoices(schema180, "Added calibrated sculk sensor", References.BLOCK_ENTITY)); +- Schema schema181 = builder.addSchema(3439, SAME_NAMESPACED); ++ builder.addFixer(ItemRenameFix.create(schema180, "Pottery shard renaming", createRenamer(ImmutableMap.of("minecraft:pottery_shard_archer", "minecraft:archer_pottery_shard", "minecraft:pottery_shard_prize", "minecraft:prize_pottery_shard", "minecraft:pottery_shard_arms_up", "minecraft:arms_up_pottery_shard", "minecraft:pottery_shard_skull", "minecraft:skull_pottery_shard")))); ++ builder.addFixer(new AddNewChoices(schema180, "Added calibrated sculk sensor", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema181 = builder.addSchema(3439, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new BlockEntitySignDoubleSidedEditableTextFix(schema181, "Updated sign text format for Signs", "minecraft:sign")); + builder.addFixer(new BlockEntitySignDoubleSidedEditableTextFix(schema181, "Updated sign text format for Hanging Signs", "minecraft:hanging_sign")); +- Schema schema182 = builder.addSchema(3440, SAME_NAMESPACED); +- builder.addFixer( +- new NamespacedTypeRenameFix( +- schema182, +- "Replace experimental 1.20 overworld", +- References.MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST, +- createRenamer("minecraft:overworld_update_1_20", "minecraft:overworld") +- ) +- ); ++ Schema schema182 = builder.addSchema(3440, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(new NamespacedTypeRenameFix(schema182, "Replace experimental 1.20 overworld", DataConverterTypes.MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST, createRenamer("minecraft:overworld_update_1_20", "minecraft:overworld"))); + builder.addFixer(new FeatureFlagRemoveFix(schema182, "Remove 1.20 feature toggle", Set.of("minecraft:update_1_20"))); +- Schema schema183 = builder.addSchema(3441, SAME_NAMESPACED); ++ Schema schema183 = builder.addSchema(3441, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new BlendingDataFix(schema183)); +- Schema schema184 = builder.addSchema(3447, SAME_NAMESPACED); +- builder.addFixer( +- ItemRenameFix.create( +- schema184, +- "Pottery shard item renaming to Pottery sherd", +- createRenamer( +- Stream.of( +- "minecraft:angler_pottery_shard", +- "minecraft:archer_pottery_shard", +- "minecraft:arms_up_pottery_shard", +- "minecraft:blade_pottery_shard", +- "minecraft:brewer_pottery_shard", +- "minecraft:burn_pottery_shard", +- "minecraft:danger_pottery_shard", +- "minecraft:explorer_pottery_shard", +- "minecraft:friend_pottery_shard", +- "minecraft:heart_pottery_shard", +- "minecraft:heartbreak_pottery_shard", +- "minecraft:howl_pottery_shard", +- "minecraft:miner_pottery_shard", +- "minecraft:mourner_pottery_shard", +- "minecraft:plenty_pottery_shard", +- "minecraft:prize_pottery_shard", +- "minecraft:sheaf_pottery_shard", +- "minecraft:shelter_pottery_shard", +- "minecraft:skull_pottery_shard", +- "minecraft:snort_pottery_shard" +- ) +- .collect(Collectors.toMap(Function.identity(), string -> string.replace("_pottery_shard", "_pottery_sherd"))) +- ) +- ) +- ); ++ Schema schema184 = builder.addSchema(3447, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(ItemRenameFix.create(schema184, "Pottery shard item renaming to Pottery sherd", createRenamer((Map) Stream.of("minecraft:angler_pottery_shard", "minecraft:archer_pottery_shard", "minecraft:arms_up_pottery_shard", "minecraft:blade_pottery_shard", "minecraft:brewer_pottery_shard", "minecraft:burn_pottery_shard", "minecraft:danger_pottery_shard", "minecraft:explorer_pottery_shard", "minecraft:friend_pottery_shard", "minecraft:heart_pottery_shard", "minecraft:heartbreak_pottery_shard", "minecraft:howl_pottery_shard", "minecraft:miner_pottery_shard", "minecraft:mourner_pottery_shard", "minecraft:plenty_pottery_shard", "minecraft:prize_pottery_shard", "minecraft:sheaf_pottery_shard", "minecraft:shelter_pottery_shard", "minecraft:skull_pottery_shard", "minecraft:snort_pottery_shard").collect(Collectors.toMap(Function.identity(), (s) -> { ++ return s.replace("_pottery_shard", "_pottery_sherd"); ++ }))))); + Schema schema185 = builder.addSchema(3448, V3448::new); ++ + builder.addFixer(new DecoratedPotFieldRenameFix(schema185)); +- Schema schema186 = builder.addSchema(3450, SAME_NAMESPACED); +- builder.addFixer( +- new RemapChunkStatusFix( +- schema186, +- "Remove liquid_carvers and heightmap chunk statuses", +- createRenamer(Map.of("minecraft:liquid_carvers", "minecraft:carvers", "minecraft:heightmaps", "minecraft:spawn")) +- ) +- ); +- Schema schema187 = builder.addSchema(3451, SAME_NAMESPACED); ++ Schema schema186 = builder.addSchema(3450, DataFixers.SAME_NAMESPACED); ++ ++ builder.addFixer(new RemapChunkStatusFix(schema186, "Remove liquid_carvers and heightmap chunk statuses", createRenamer(Map.of("minecraft:liquid_carvers", "minecraft:carvers", "minecraft:heightmaps", "minecraft:spawn")))); ++ Schema schema187 = builder.addSchema(3451, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new ChunkDeleteLightFix(schema187)); +- Schema schema188 = builder.addSchema(3459, SAME_NAMESPACED); ++ Schema schema188 = builder.addSchema(3459, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new LegacyDragonFightFix(schema188)); +- Schema schema189 = builder.addSchema(3564, SAME_NAMESPACED); ++ Schema schema189 = builder.addSchema(3564, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new DropInvalidSignDataFix(schema189, "Drop invalid sign datafix data", "minecraft:sign")); + builder.addFixer(new DropInvalidSignDataFix(schema189, "Drop invalid hanging sign datafix data", "minecraft:hanging_sign")); +- Schema schema190 = builder.addSchema(3565, SAME_NAMESPACED); ++ Schema schema190 = builder.addSchema(3565, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new RandomSequenceSettingsFix(schema190)); +- Schema schema191 = builder.addSchema(3566, SAME_NAMESPACED); ++ Schema schema191 = builder.addSchema(3566, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new ScoreboardDisplaySlotFix(schema191)); +- Schema schema192 = builder.addSchema(3568, SAME_NAMESPACED); ++ Schema schema192 = builder.addSchema(3568, DataFixers.SAME_NAMESPACED); ++ + builder.addFixer(new MobEffectIdFix(schema192)); + Schema schema193 = builder.addSchema(3682, V3682::new); +- builder.addFixer(new AddNewChoices(schema193, "Added Crafter", References.BLOCK_ENTITY)); ++ ++ builder.addFixer(new AddNewChoices(schema193, "Added Crafter", DataConverterTypes.BLOCK_ENTITY)); + Schema schema194 = builder.addSchema(3683, V3683::new); ++ + builder.addFixer(new PrimedTntBlockStateFixer(schema194)); + Schema schema195 = builder.addSchema(3685, V3685::new); ++ + builder.addFixer(new FixProjectileStoredItem(schema195)); + Schema schema196 = builder.addSchema(3689, V3689::new); +- builder.addFixer(new AddNewChoices(schema196, "Added Breeze", References.ENTITY)); +- builder.addFixer(new AddNewChoices(schema196, "Added Trial Spawner", References.BLOCK_ENTITY)); +- Schema schema197 = builder.addSchema(3692, SAME_NAMESPACED); +- UnaryOperator unaryOperator1 = createRenamer(Map.of("minecraft:grass", "minecraft:short_grass")); +- builder.addFixer(BlockRenameFixWithJigsaw.create(schema197, "Rename grass block to short_grass", unaryOperator1)); +- builder.addFixer(ItemRenameFix.create(schema197, "Rename grass item to short_grass", unaryOperator1)); ++ ++ builder.addFixer(new AddNewChoices(schema196, "Added Breeze", DataConverterTypes.ENTITY)); ++ builder.addFixer(new AddNewChoices(schema196, "Added Trial Spawner", DataConverterTypes.BLOCK_ENTITY)); ++ Schema schema197 = builder.addSchema(3692, DataFixers.SAME_NAMESPACED); ++ UnaryOperator unaryoperator1 = createRenamer(Map.of("minecraft:grass", "minecraft:short_grass")); ++ ++ builder.addFixer(BlockRenameFixWithJigsaw.create(schema197, "Rename grass block to short_grass", unaryoperator1)); ++ builder.addFixer(ItemRenameFix.create(schema197, "Rename grass item to short_grass", unaryoperator1)); + } + + private static UnaryOperator createRenamer(Map renameMap) { +- return string -> renameMap.getOrDefault(string, string); ++ return (s) -> { ++ return (String) renameMap.getOrDefault(s, s); ++ }; + } + + private static UnaryOperator createRenamer(String oldName, String newName) { +- return string -> Objects.equals(string, oldName) ? newName : string; ++ return (s2) -> { ++ return Objects.equals(s2, oldName) ? newName : s2; ++ }; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java.patch b/patch-remap/mache-vineflower/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java.patch new file mode 100644 index 0000000000..c34e6c784c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java.patch @@ -0,0 +1,41 @@ +--- a/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java ++++ b/net/minecraft/util/datafix/fixes/ItemStackMapIdFix.java +@@ -14,23 +14,26 @@ + import net.minecraft.util.datafix.schemas.NamespacedSchema; + + public class ItemStackMapIdFix extends DataFix { ++ + public ItemStackMapIdFix(Schema outputSchema, boolean changesType) { + super(outputSchema, changesType); + } + +- @Override + public TypeRewriteRule makeRule() { +- Type type = this.getInputSchema().getType(References.ITEM_STACK); +- OpticFinder> opticFinder = DSL.fieldFinder("id", DSL.named(References.ITEM_NAME.typeName(), NamespacedSchema.namespacedString())); +- OpticFinder opticFinder1 = type.findField("tag"); +- return this.fixTypeEverywhereTyped("ItemInstanceMapIdFix", type, typed -> { +- Optional> optional = typed.getOptional(opticFinder); +- if (optional.isPresent() && Objects.equals(optional.get().getSecond(), "minecraft:filled_map")) { +- Dynamic dynamic = typed.get(DSL.remainderFinder()); +- Typed typed1 = typed.getOrCreateTyped(opticFinder1); +- Dynamic dynamic1 = typed1.get(DSL.remainderFinder()); +- dynamic1 = dynamic1.set("map", dynamic1.createInt(dynamic.get("Damage").asInt(0))); +- return typed.set(opticFinder1, typed1.set(DSL.remainderFinder(), dynamic1)); ++ Type type = this.getInputSchema().getType(DataConverterTypes.ITEM_STACK); ++ OpticFinder> opticfinder = DSL.fieldFinder("id", DSL.named(DataConverterTypes.ITEM_NAME.typeName(), NamespacedSchema.namespacedString())); ++ OpticFinder opticfinder1 = type.findField("tag"); ++ ++ return this.fixTypeEverywhereTyped("ItemInstanceMapIdFix", type, (typed) -> { ++ Optional> optional = typed.getOptional(opticfinder); ++ ++ if (optional.isPresent() && Objects.equals(((Pair) optional.get()).getSecond(), "minecraft:filled_map")) { ++ Dynamic dynamic = (Dynamic) typed.get(DSL.remainderFinder()); ++ Typed typed1 = typed.getOrCreateTyped(opticfinder1); ++ Dynamic dynamic1 = (Dynamic) typed1.get(DSL.remainderFinder()); ++ ++ if (!dynamic1.getElement("map").result().isPresent()) dynamic1 = dynamic1.set("map", dynamic1.createInt(dynamic.get("Damage").asInt(0))); // CraftBukkit ++ return typed.set(opticfinder1, typed1.set(DSL.remainderFinder(), dynamic1)); + } else { + return typed; + } diff --git a/patch-remap/mache-vineflower/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java.patch b/patch-remap/mache-vineflower/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java.patch new file mode 100644 index 0000000000..5ab57727d9 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java.patch @@ -0,0 +1,785 @@ +--- a/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java ++++ b/net/minecraft/util/datafix/fixes/ItemStackTheFlatteningFix.java +@@ -12,7 +12,6 @@ + import com.mojang.datafixers.types.Type; + import com.mojang.datafixers.util.Pair; + import com.mojang.serialization.Dynamic; +-import java.util.HashMap; + import java.util.Map; + import java.util.Optional; + import java.util.Set; +@@ -21,423 +20,378 @@ + import net.minecraft.util.datafix.schemas.NamespacedSchema; + + public class ItemStackTheFlatteningFix extends DataFix { +- private static final Map MAP = DataFixUtils.make(Maps.newHashMap(), map -> { +- map.put("minecraft:stone.0", "minecraft:stone"); +- map.put("minecraft:stone.1", "minecraft:granite"); +- map.put("minecraft:stone.2", "minecraft:polished_granite"); +- map.put("minecraft:stone.3", "minecraft:diorite"); +- map.put("minecraft:stone.4", "minecraft:polished_diorite"); +- map.put("minecraft:stone.5", "minecraft:andesite"); +- map.put("minecraft:stone.6", "minecraft:polished_andesite"); +- map.put("minecraft:dirt.0", "minecraft:dirt"); +- map.put("minecraft:dirt.1", "minecraft:coarse_dirt"); +- map.put("minecraft:dirt.2", "minecraft:podzol"); +- map.put("minecraft:leaves.0", "minecraft:oak_leaves"); +- map.put("minecraft:leaves.1", "minecraft:spruce_leaves"); +- map.put("minecraft:leaves.2", "minecraft:birch_leaves"); +- map.put("minecraft:leaves.3", "minecraft:jungle_leaves"); +- map.put("minecraft:leaves2.0", "minecraft:acacia_leaves"); +- map.put("minecraft:leaves2.1", "minecraft:dark_oak_leaves"); +- map.put("minecraft:log.0", "minecraft:oak_log"); +- map.put("minecraft:log.1", "minecraft:spruce_log"); +- map.put("minecraft:log.2", "minecraft:birch_log"); +- map.put("minecraft:log.3", "minecraft:jungle_log"); +- map.put("minecraft:log2.0", "minecraft:acacia_log"); +- map.put("minecraft:log2.1", "minecraft:dark_oak_log"); +- map.put("minecraft:sapling.0", "minecraft:oak_sapling"); +- map.put("minecraft:sapling.1", "minecraft:spruce_sapling"); +- map.put("minecraft:sapling.2", "minecraft:birch_sapling"); +- map.put("minecraft:sapling.3", "minecraft:jungle_sapling"); +- map.put("minecraft:sapling.4", "minecraft:acacia_sapling"); +- map.put("minecraft:sapling.5", "minecraft:dark_oak_sapling"); +- map.put("minecraft:planks.0", "minecraft:oak_planks"); +- map.put("minecraft:planks.1", "minecraft:spruce_planks"); +- map.put("minecraft:planks.2", "minecraft:birch_planks"); +- map.put("minecraft:planks.3", "minecraft:jungle_planks"); +- map.put("minecraft:planks.4", "minecraft:acacia_planks"); +- map.put("minecraft:planks.5", "minecraft:dark_oak_planks"); +- map.put("minecraft:sand.0", "minecraft:sand"); +- map.put("minecraft:sand.1", "minecraft:red_sand"); +- map.put("minecraft:quartz_block.0", "minecraft:quartz_block"); +- map.put("minecraft:quartz_block.1", "minecraft:chiseled_quartz_block"); +- map.put("minecraft:quartz_block.2", "minecraft:quartz_pillar"); +- map.put("minecraft:anvil.0", "minecraft:anvil"); +- map.put("minecraft:anvil.1", "minecraft:chipped_anvil"); +- map.put("minecraft:anvil.2", "minecraft:damaged_anvil"); +- map.put("minecraft:wool.0", "minecraft:white_wool"); +- map.put("minecraft:wool.1", "minecraft:orange_wool"); +- map.put("minecraft:wool.2", "minecraft:magenta_wool"); +- map.put("minecraft:wool.3", "minecraft:light_blue_wool"); +- map.put("minecraft:wool.4", "minecraft:yellow_wool"); +- map.put("minecraft:wool.5", "minecraft:lime_wool"); +- map.put("minecraft:wool.6", "minecraft:pink_wool"); +- map.put("minecraft:wool.7", "minecraft:gray_wool"); +- map.put("minecraft:wool.8", "minecraft:light_gray_wool"); +- map.put("minecraft:wool.9", "minecraft:cyan_wool"); +- map.put("minecraft:wool.10", "minecraft:purple_wool"); +- map.put("minecraft:wool.11", "minecraft:blue_wool"); +- map.put("minecraft:wool.12", "minecraft:brown_wool"); +- map.put("minecraft:wool.13", "minecraft:green_wool"); +- map.put("minecraft:wool.14", "minecraft:red_wool"); +- map.put("minecraft:wool.15", "minecraft:black_wool"); +- map.put("minecraft:carpet.0", "minecraft:white_carpet"); +- map.put("minecraft:carpet.1", "minecraft:orange_carpet"); +- map.put("minecraft:carpet.2", "minecraft:magenta_carpet"); +- map.put("minecraft:carpet.3", "minecraft:light_blue_carpet"); +- map.put("minecraft:carpet.4", "minecraft:yellow_carpet"); +- map.put("minecraft:carpet.5", "minecraft:lime_carpet"); +- map.put("minecraft:carpet.6", "minecraft:pink_carpet"); +- map.put("minecraft:carpet.7", "minecraft:gray_carpet"); +- map.put("minecraft:carpet.8", "minecraft:light_gray_carpet"); +- map.put("minecraft:carpet.9", "minecraft:cyan_carpet"); +- map.put("minecraft:carpet.10", "minecraft:purple_carpet"); +- map.put("minecraft:carpet.11", "minecraft:blue_carpet"); +- map.put("minecraft:carpet.12", "minecraft:brown_carpet"); +- map.put("minecraft:carpet.13", "minecraft:green_carpet"); +- map.put("minecraft:carpet.14", "minecraft:red_carpet"); +- map.put("minecraft:carpet.15", "minecraft:black_carpet"); +- map.put("minecraft:hardened_clay.0", "minecraft:terracotta"); +- map.put("minecraft:stained_hardened_clay.0", "minecraft:white_terracotta"); +- map.put("minecraft:stained_hardened_clay.1", "minecraft:orange_terracotta"); +- map.put("minecraft:stained_hardened_clay.2", "minecraft:magenta_terracotta"); +- map.put("minecraft:stained_hardened_clay.3", "minecraft:light_blue_terracotta"); +- map.put("minecraft:stained_hardened_clay.4", "minecraft:yellow_terracotta"); +- map.put("minecraft:stained_hardened_clay.5", "minecraft:lime_terracotta"); +- map.put("minecraft:stained_hardened_clay.6", "minecraft:pink_terracotta"); +- map.put("minecraft:stained_hardened_clay.7", "minecraft:gray_terracotta"); +- map.put("minecraft:stained_hardened_clay.8", "minecraft:light_gray_terracotta"); +- map.put("minecraft:stained_hardened_clay.9", "minecraft:cyan_terracotta"); +- map.put("minecraft:stained_hardened_clay.10", "minecraft:purple_terracotta"); +- map.put("minecraft:stained_hardened_clay.11", "minecraft:blue_terracotta"); +- map.put("minecraft:stained_hardened_clay.12", "minecraft:brown_terracotta"); +- map.put("minecraft:stained_hardened_clay.13", "minecraft:green_terracotta"); +- map.put("minecraft:stained_hardened_clay.14", "minecraft:red_terracotta"); +- map.put("minecraft:stained_hardened_clay.15", "minecraft:black_terracotta"); +- map.put("minecraft:silver_glazed_terracotta.0", "minecraft:light_gray_glazed_terracotta"); +- map.put("minecraft:stained_glass.0", "minecraft:white_stained_glass"); +- map.put("minecraft:stained_glass.1", "minecraft:orange_stained_glass"); +- map.put("minecraft:stained_glass.2", "minecraft:magenta_stained_glass"); +- map.put("minecraft:stained_glass.3", "minecraft:light_blue_stained_glass"); +- map.put("minecraft:stained_glass.4", "minecraft:yellow_stained_glass"); +- map.put("minecraft:stained_glass.5", "minecraft:lime_stained_glass"); +- map.put("minecraft:stained_glass.6", "minecraft:pink_stained_glass"); +- map.put("minecraft:stained_glass.7", "minecraft:gray_stained_glass"); +- map.put("minecraft:stained_glass.8", "minecraft:light_gray_stained_glass"); +- map.put("minecraft:stained_glass.9", "minecraft:cyan_stained_glass"); +- map.put("minecraft:stained_glass.10", "minecraft:purple_stained_glass"); +- map.put("minecraft:stained_glass.11", "minecraft:blue_stained_glass"); +- map.put("minecraft:stained_glass.12", "minecraft:brown_stained_glass"); +- map.put("minecraft:stained_glass.13", "minecraft:green_stained_glass"); +- map.put("minecraft:stained_glass.14", "minecraft:red_stained_glass"); +- map.put("minecraft:stained_glass.15", "minecraft:black_stained_glass"); +- map.put("minecraft:stained_glass_pane.0", "minecraft:white_stained_glass_pane"); +- map.put("minecraft:stained_glass_pane.1", "minecraft:orange_stained_glass_pane"); +- map.put("minecraft:stained_glass_pane.2", "minecraft:magenta_stained_glass_pane"); +- map.put("minecraft:stained_glass_pane.3", "minecraft:light_blue_stained_glass_pane"); +- map.put("minecraft:stained_glass_pane.4", "minecraft:yellow_stained_glass_pane"); +- map.put("minecraft:stained_glass_pane.5", "minecraft:lime_stained_glass_pane"); +- map.put("minecraft:stained_glass_pane.6", "minecraft:pink_stained_glass_pane"); +- map.put("minecraft:stained_glass_pane.7", "minecraft:gray_stained_glass_pane"); +- map.put("minecraft:stained_glass_pane.8", "minecraft:light_gray_stained_glass_pane"); +- map.put("minecraft:stained_glass_pane.9", "minecraft:cyan_stained_glass_pane"); +- map.put("minecraft:stained_glass_pane.10", "minecraft:purple_stained_glass_pane"); +- map.put("minecraft:stained_glass_pane.11", "minecraft:blue_stained_glass_pane"); +- map.put("minecraft:stained_glass_pane.12", "minecraft:brown_stained_glass_pane"); +- map.put("minecraft:stained_glass_pane.13", "minecraft:green_stained_glass_pane"); +- map.put("minecraft:stained_glass_pane.14", "minecraft:red_stained_glass_pane"); +- map.put("minecraft:stained_glass_pane.15", "minecraft:black_stained_glass_pane"); +- map.put("minecraft:prismarine.0", "minecraft:prismarine"); +- map.put("minecraft:prismarine.1", "minecraft:prismarine_bricks"); +- map.put("minecraft:prismarine.2", "minecraft:dark_prismarine"); +- map.put("minecraft:concrete.0", "minecraft:white_concrete"); +- map.put("minecraft:concrete.1", "minecraft:orange_concrete"); +- map.put("minecraft:concrete.2", "minecraft:magenta_concrete"); +- map.put("minecraft:concrete.3", "minecraft:light_blue_concrete"); +- map.put("minecraft:concrete.4", "minecraft:yellow_concrete"); +- map.put("minecraft:concrete.5", "minecraft:lime_concrete"); +- map.put("minecraft:concrete.6", "minecraft:pink_concrete"); +- map.put("minecraft:concrete.7", "minecraft:gray_concrete"); +- map.put("minecraft:concrete.8", "minecraft:light_gray_concrete"); +- map.put("minecraft:concrete.9", "minecraft:cyan_concrete"); +- map.put("minecraft:concrete.10", "minecraft:purple_concrete"); +- map.put("minecraft:concrete.11", "minecraft:blue_concrete"); +- map.put("minecraft:concrete.12", "minecraft:brown_concrete"); +- map.put("minecraft:concrete.13", "minecraft:green_concrete"); +- map.put("minecraft:concrete.14", "minecraft:red_concrete"); +- map.put("minecraft:concrete.15", "minecraft:black_concrete"); +- map.put("minecraft:concrete_powder.0", "minecraft:white_concrete_powder"); +- map.put("minecraft:concrete_powder.1", "minecraft:orange_concrete_powder"); +- map.put("minecraft:concrete_powder.2", "minecraft:magenta_concrete_powder"); +- map.put("minecraft:concrete_powder.3", "minecraft:light_blue_concrete_powder"); +- map.put("minecraft:concrete_powder.4", "minecraft:yellow_concrete_powder"); +- map.put("minecraft:concrete_powder.5", "minecraft:lime_concrete_powder"); +- map.put("minecraft:concrete_powder.6", "minecraft:pink_concrete_powder"); +- map.put("minecraft:concrete_powder.7", "minecraft:gray_concrete_powder"); +- map.put("minecraft:concrete_powder.8", "minecraft:light_gray_concrete_powder"); +- map.put("minecraft:concrete_powder.9", "minecraft:cyan_concrete_powder"); +- map.put("minecraft:concrete_powder.10", "minecraft:purple_concrete_powder"); +- map.put("minecraft:concrete_powder.11", "minecraft:blue_concrete_powder"); +- map.put("minecraft:concrete_powder.12", "minecraft:brown_concrete_powder"); +- map.put("minecraft:concrete_powder.13", "minecraft:green_concrete_powder"); +- map.put("minecraft:concrete_powder.14", "minecraft:red_concrete_powder"); +- map.put("minecraft:concrete_powder.15", "minecraft:black_concrete_powder"); +- map.put("minecraft:cobblestone_wall.0", "minecraft:cobblestone_wall"); +- map.put("minecraft:cobblestone_wall.1", "minecraft:mossy_cobblestone_wall"); +- map.put("minecraft:sandstone.0", "minecraft:sandstone"); +- map.put("minecraft:sandstone.1", "minecraft:chiseled_sandstone"); +- map.put("minecraft:sandstone.2", "minecraft:cut_sandstone"); +- map.put("minecraft:red_sandstone.0", "minecraft:red_sandstone"); +- map.put("minecraft:red_sandstone.1", "minecraft:chiseled_red_sandstone"); +- map.put("minecraft:red_sandstone.2", "minecraft:cut_red_sandstone"); +- map.put("minecraft:stonebrick.0", "minecraft:stone_bricks"); +- map.put("minecraft:stonebrick.1", "minecraft:mossy_stone_bricks"); +- map.put("minecraft:stonebrick.2", "minecraft:cracked_stone_bricks"); +- map.put("minecraft:stonebrick.3", "minecraft:chiseled_stone_bricks"); +- map.put("minecraft:monster_egg.0", "minecraft:infested_stone"); +- map.put("minecraft:monster_egg.1", "minecraft:infested_cobblestone"); +- map.put("minecraft:monster_egg.2", "minecraft:infested_stone_bricks"); +- map.put("minecraft:monster_egg.3", "minecraft:infested_mossy_stone_bricks"); +- map.put("minecraft:monster_egg.4", "minecraft:infested_cracked_stone_bricks"); +- map.put("minecraft:monster_egg.5", "minecraft:infested_chiseled_stone_bricks"); +- map.put("minecraft:yellow_flower.0", "minecraft:dandelion"); +- map.put("minecraft:red_flower.0", "minecraft:poppy"); +- map.put("minecraft:red_flower.1", "minecraft:blue_orchid"); +- map.put("minecraft:red_flower.2", "minecraft:allium"); +- map.put("minecraft:red_flower.3", "minecraft:azure_bluet"); +- map.put("minecraft:red_flower.4", "minecraft:red_tulip"); +- map.put("minecraft:red_flower.5", "minecraft:orange_tulip"); +- map.put("minecraft:red_flower.6", "minecraft:white_tulip"); +- map.put("minecraft:red_flower.7", "minecraft:pink_tulip"); +- map.put("minecraft:red_flower.8", "minecraft:oxeye_daisy"); +- map.put("minecraft:double_plant.0", "minecraft:sunflower"); +- map.put("minecraft:double_plant.1", "minecraft:lilac"); +- map.put("minecraft:double_plant.2", "minecraft:tall_grass"); +- map.put("minecraft:double_plant.3", "minecraft:large_fern"); +- map.put("minecraft:double_plant.4", "minecraft:rose_bush"); +- map.put("minecraft:double_plant.5", "minecraft:peony"); +- map.put("minecraft:deadbush.0", "minecraft:dead_bush"); +- map.put("minecraft:tallgrass.0", "minecraft:dead_bush"); +- map.put("minecraft:tallgrass.1", "minecraft:grass"); +- map.put("minecraft:tallgrass.2", "minecraft:fern"); +- map.put("minecraft:sponge.0", "minecraft:sponge"); +- map.put("minecraft:sponge.1", "minecraft:wet_sponge"); +- map.put("minecraft:purpur_slab.0", "minecraft:purpur_slab"); +- map.put("minecraft:stone_slab.0", "minecraft:stone_slab"); +- map.put("minecraft:stone_slab.1", "minecraft:sandstone_slab"); +- map.put("minecraft:stone_slab.2", "minecraft:petrified_oak_slab"); +- map.put("minecraft:stone_slab.3", "minecraft:cobblestone_slab"); +- map.put("minecraft:stone_slab.4", "minecraft:brick_slab"); +- map.put("minecraft:stone_slab.5", "minecraft:stone_brick_slab"); +- map.put("minecraft:stone_slab.6", "minecraft:nether_brick_slab"); +- map.put("minecraft:stone_slab.7", "minecraft:quartz_slab"); +- map.put("minecraft:stone_slab2.0", "minecraft:red_sandstone_slab"); +- map.put("minecraft:wooden_slab.0", "minecraft:oak_slab"); +- map.put("minecraft:wooden_slab.1", "minecraft:spruce_slab"); +- map.put("minecraft:wooden_slab.2", "minecraft:birch_slab"); +- map.put("minecraft:wooden_slab.3", "minecraft:jungle_slab"); +- map.put("minecraft:wooden_slab.4", "minecraft:acacia_slab"); +- map.put("minecraft:wooden_slab.5", "minecraft:dark_oak_slab"); +- map.put("minecraft:coal.0", "minecraft:coal"); +- map.put("minecraft:coal.1", "minecraft:charcoal"); +- map.put("minecraft:fish.0", "minecraft:cod"); +- map.put("minecraft:fish.1", "minecraft:salmon"); +- map.put("minecraft:fish.2", "minecraft:clownfish"); +- map.put("minecraft:fish.3", "minecraft:pufferfish"); +- map.put("minecraft:cooked_fish.0", "minecraft:cooked_cod"); +- map.put("minecraft:cooked_fish.1", "minecraft:cooked_salmon"); +- map.put("minecraft:skull.0", "minecraft:skeleton_skull"); +- map.put("minecraft:skull.1", "minecraft:wither_skeleton_skull"); +- map.put("minecraft:skull.2", "minecraft:zombie_head"); +- map.put("minecraft:skull.3", "minecraft:player_head"); +- map.put("minecraft:skull.4", "minecraft:creeper_head"); +- map.put("minecraft:skull.5", "minecraft:dragon_head"); +- map.put("minecraft:golden_apple.0", "minecraft:golden_apple"); +- map.put("minecraft:golden_apple.1", "minecraft:enchanted_golden_apple"); +- map.put("minecraft:fireworks.0", "minecraft:firework_rocket"); +- map.put("minecraft:firework_charge.0", "minecraft:firework_star"); +- map.put("minecraft:dye.0", "minecraft:ink_sac"); +- map.put("minecraft:dye.1", "minecraft:rose_red"); +- map.put("minecraft:dye.2", "minecraft:cactus_green"); +- map.put("minecraft:dye.3", "minecraft:cocoa_beans"); +- map.put("minecraft:dye.4", "minecraft:lapis_lazuli"); +- map.put("minecraft:dye.5", "minecraft:purple_dye"); +- map.put("minecraft:dye.6", "minecraft:cyan_dye"); +- map.put("minecraft:dye.7", "minecraft:light_gray_dye"); +- map.put("minecraft:dye.8", "minecraft:gray_dye"); +- map.put("minecraft:dye.9", "minecraft:pink_dye"); +- map.put("minecraft:dye.10", "minecraft:lime_dye"); +- map.put("minecraft:dye.11", "minecraft:dandelion_yellow"); +- map.put("minecraft:dye.12", "minecraft:light_blue_dye"); +- map.put("minecraft:dye.13", "minecraft:magenta_dye"); +- map.put("minecraft:dye.14", "minecraft:orange_dye"); +- map.put("minecraft:dye.15", "minecraft:bone_meal"); +- map.put("minecraft:silver_shulker_box.0", "minecraft:light_gray_shulker_box"); +- map.put("minecraft:fence.0", "minecraft:oak_fence"); +- map.put("minecraft:fence_gate.0", "minecraft:oak_fence_gate"); +- map.put("minecraft:wooden_door.0", "minecraft:oak_door"); +- map.put("minecraft:boat.0", "minecraft:oak_boat"); +- map.put("minecraft:lit_pumpkin.0", "minecraft:jack_o_lantern"); +- map.put("minecraft:pumpkin.0", "minecraft:carved_pumpkin"); +- map.put("minecraft:trapdoor.0", "minecraft:oak_trapdoor"); +- map.put("minecraft:nether_brick.0", "minecraft:nether_bricks"); +- map.put("minecraft:red_nether_brick.0", "minecraft:red_nether_bricks"); +- map.put("minecraft:netherbrick.0", "minecraft:nether_brick"); +- map.put("minecraft:wooden_button.0", "minecraft:oak_button"); +- map.put("minecraft:wooden_pressure_plate.0", "minecraft:oak_pressure_plate"); +- map.put("minecraft:noteblock.0", "minecraft:note_block"); +- map.put("minecraft:bed.0", "minecraft:white_bed"); +- map.put("minecraft:bed.1", "minecraft:orange_bed"); +- map.put("minecraft:bed.2", "minecraft:magenta_bed"); +- map.put("minecraft:bed.3", "minecraft:light_blue_bed"); +- map.put("minecraft:bed.4", "minecraft:yellow_bed"); +- map.put("minecraft:bed.5", "minecraft:lime_bed"); +- map.put("minecraft:bed.6", "minecraft:pink_bed"); +- map.put("minecraft:bed.7", "minecraft:gray_bed"); +- map.put("minecraft:bed.8", "minecraft:light_gray_bed"); +- map.put("minecraft:bed.9", "minecraft:cyan_bed"); +- map.put("minecraft:bed.10", "minecraft:purple_bed"); +- map.put("minecraft:bed.11", "minecraft:blue_bed"); +- map.put("minecraft:bed.12", "minecraft:brown_bed"); +- map.put("minecraft:bed.13", "minecraft:green_bed"); +- map.put("minecraft:bed.14", "minecraft:red_bed"); +- map.put("minecraft:bed.15", "minecraft:black_bed"); +- map.put("minecraft:banner.15", "minecraft:white_banner"); +- map.put("minecraft:banner.14", "minecraft:orange_banner"); +- map.put("minecraft:banner.13", "minecraft:magenta_banner"); +- map.put("minecraft:banner.12", "minecraft:light_blue_banner"); +- map.put("minecraft:banner.11", "minecraft:yellow_banner"); +- map.put("minecraft:banner.10", "minecraft:lime_banner"); +- map.put("minecraft:banner.9", "minecraft:pink_banner"); +- map.put("minecraft:banner.8", "minecraft:gray_banner"); +- map.put("minecraft:banner.7", "minecraft:light_gray_banner"); +- map.put("minecraft:banner.6", "minecraft:cyan_banner"); +- map.put("minecraft:banner.5", "minecraft:purple_banner"); +- map.put("minecraft:banner.4", "minecraft:blue_banner"); +- map.put("minecraft:banner.3", "minecraft:brown_banner"); +- map.put("minecraft:banner.2", "minecraft:green_banner"); +- map.put("minecraft:banner.1", "minecraft:red_banner"); +- map.put("minecraft:banner.0", "minecraft:black_banner"); +- map.put("minecraft:grass.0", "minecraft:grass_block"); +- map.put("minecraft:brick_block.0", "minecraft:bricks"); +- map.put("minecraft:end_bricks.0", "minecraft:end_stone_bricks"); +- map.put("minecraft:golden_rail.0", "minecraft:powered_rail"); +- map.put("minecraft:magma.0", "minecraft:magma_block"); +- map.put("minecraft:quartz_ore.0", "minecraft:nether_quartz_ore"); +- map.put("minecraft:reeds.0", "minecraft:sugar_cane"); +- map.put("minecraft:slime.0", "minecraft:slime_block"); +- map.put("minecraft:stone_stairs.0", "minecraft:cobblestone_stairs"); +- map.put("minecraft:waterlily.0", "minecraft:lily_pad"); +- map.put("minecraft:web.0", "minecraft:cobweb"); +- map.put("minecraft:snow.0", "minecraft:snow_block"); +- map.put("minecraft:snow_layer.0", "minecraft:snow"); +- map.put("minecraft:record_11.0", "minecraft:music_disc_11"); +- map.put("minecraft:record_13.0", "minecraft:music_disc_13"); +- map.put("minecraft:record_blocks.0", "minecraft:music_disc_blocks"); +- map.put("minecraft:record_cat.0", "minecraft:music_disc_cat"); +- map.put("minecraft:record_chirp.0", "minecraft:music_disc_chirp"); +- map.put("minecraft:record_far.0", "minecraft:music_disc_far"); +- map.put("minecraft:record_mall.0", "minecraft:music_disc_mall"); +- map.put("minecraft:record_mellohi.0", "minecraft:music_disc_mellohi"); +- map.put("minecraft:record_stal.0", "minecraft:music_disc_stal"); +- map.put("minecraft:record_strad.0", "minecraft:music_disc_strad"); +- map.put("minecraft:record_wait.0", "minecraft:music_disc_wait"); +- map.put("minecraft:record_ward.0", "minecraft:music_disc_ward"); ++ ++ private static final Map MAP = (Map) DataFixUtils.make(Maps.newHashMap(), (hashmap) -> { ++ hashmap.put("minecraft:stone.0", "minecraft:stone"); ++ hashmap.put("minecraft:stone.1", "minecraft:granite"); ++ hashmap.put("minecraft:stone.2", "minecraft:polished_granite"); ++ hashmap.put("minecraft:stone.3", "minecraft:diorite"); ++ hashmap.put("minecraft:stone.4", "minecraft:polished_diorite"); ++ hashmap.put("minecraft:stone.5", "minecraft:andesite"); ++ hashmap.put("minecraft:stone.6", "minecraft:polished_andesite"); ++ hashmap.put("minecraft:dirt.0", "minecraft:dirt"); ++ hashmap.put("minecraft:dirt.1", "minecraft:coarse_dirt"); ++ hashmap.put("minecraft:dirt.2", "minecraft:podzol"); ++ hashmap.put("minecraft:leaves.0", "minecraft:oak_leaves"); ++ hashmap.put("minecraft:leaves.1", "minecraft:spruce_leaves"); ++ hashmap.put("minecraft:leaves.2", "minecraft:birch_leaves"); ++ hashmap.put("minecraft:leaves.3", "minecraft:jungle_leaves"); ++ hashmap.put("minecraft:leaves2.0", "minecraft:acacia_leaves"); ++ hashmap.put("minecraft:leaves2.1", "minecraft:dark_oak_leaves"); ++ hashmap.put("minecraft:log.0", "minecraft:oak_log"); ++ hashmap.put("minecraft:log.1", "minecraft:spruce_log"); ++ hashmap.put("minecraft:log.2", "minecraft:birch_log"); ++ hashmap.put("minecraft:log.3", "minecraft:jungle_log"); ++ hashmap.put("minecraft:log2.0", "minecraft:acacia_log"); ++ hashmap.put("minecraft:log2.1", "minecraft:dark_oak_log"); ++ hashmap.put("minecraft:sapling.0", "minecraft:oak_sapling"); ++ hashmap.put("minecraft:sapling.1", "minecraft:spruce_sapling"); ++ hashmap.put("minecraft:sapling.2", "minecraft:birch_sapling"); ++ hashmap.put("minecraft:sapling.3", "minecraft:jungle_sapling"); ++ hashmap.put("minecraft:sapling.4", "minecraft:acacia_sapling"); ++ hashmap.put("minecraft:sapling.5", "minecraft:dark_oak_sapling"); ++ hashmap.put("minecraft:planks.0", "minecraft:oak_planks"); ++ hashmap.put("minecraft:planks.1", "minecraft:spruce_planks"); ++ hashmap.put("minecraft:planks.2", "minecraft:birch_planks"); ++ hashmap.put("minecraft:planks.3", "minecraft:jungle_planks"); ++ hashmap.put("minecraft:planks.4", "minecraft:acacia_planks"); ++ hashmap.put("minecraft:planks.5", "minecraft:dark_oak_planks"); ++ hashmap.put("minecraft:sand.0", "minecraft:sand"); ++ hashmap.put("minecraft:sand.1", "minecraft:red_sand"); ++ hashmap.put("minecraft:quartz_block.0", "minecraft:quartz_block"); ++ hashmap.put("minecraft:quartz_block.1", "minecraft:chiseled_quartz_block"); ++ hashmap.put("minecraft:quartz_block.2", "minecraft:quartz_pillar"); ++ hashmap.put("minecraft:anvil.0", "minecraft:anvil"); ++ hashmap.put("minecraft:anvil.1", "minecraft:chipped_anvil"); ++ hashmap.put("minecraft:anvil.2", "minecraft:damaged_anvil"); ++ hashmap.put("minecraft:wool.0", "minecraft:white_wool"); ++ hashmap.put("minecraft:wool.1", "minecraft:orange_wool"); ++ hashmap.put("minecraft:wool.2", "minecraft:magenta_wool"); ++ hashmap.put("minecraft:wool.3", "minecraft:light_blue_wool"); ++ hashmap.put("minecraft:wool.4", "minecraft:yellow_wool"); ++ hashmap.put("minecraft:wool.5", "minecraft:lime_wool"); ++ hashmap.put("minecraft:wool.6", "minecraft:pink_wool"); ++ hashmap.put("minecraft:wool.7", "minecraft:gray_wool"); ++ hashmap.put("minecraft:wool.8", "minecraft:light_gray_wool"); ++ hashmap.put("minecraft:wool.9", "minecraft:cyan_wool"); ++ hashmap.put("minecraft:wool.10", "minecraft:purple_wool"); ++ hashmap.put("minecraft:wool.11", "minecraft:blue_wool"); ++ hashmap.put("minecraft:wool.12", "minecraft:brown_wool"); ++ hashmap.put("minecraft:wool.13", "minecraft:green_wool"); ++ hashmap.put("minecraft:wool.14", "minecraft:red_wool"); ++ hashmap.put("minecraft:wool.15", "minecraft:black_wool"); ++ hashmap.put("minecraft:carpet.0", "minecraft:white_carpet"); ++ hashmap.put("minecraft:carpet.1", "minecraft:orange_carpet"); ++ hashmap.put("minecraft:carpet.2", "minecraft:magenta_carpet"); ++ hashmap.put("minecraft:carpet.3", "minecraft:light_blue_carpet"); ++ hashmap.put("minecraft:carpet.4", "minecraft:yellow_carpet"); ++ hashmap.put("minecraft:carpet.5", "minecraft:lime_carpet"); ++ hashmap.put("minecraft:carpet.6", "minecraft:pink_carpet"); ++ hashmap.put("minecraft:carpet.7", "minecraft:gray_carpet"); ++ hashmap.put("minecraft:carpet.8", "minecraft:light_gray_carpet"); ++ hashmap.put("minecraft:carpet.9", "minecraft:cyan_carpet"); ++ hashmap.put("minecraft:carpet.10", "minecraft:purple_carpet"); ++ hashmap.put("minecraft:carpet.11", "minecraft:blue_carpet"); ++ hashmap.put("minecraft:carpet.12", "minecraft:brown_carpet"); ++ hashmap.put("minecraft:carpet.13", "minecraft:green_carpet"); ++ hashmap.put("minecraft:carpet.14", "minecraft:red_carpet"); ++ hashmap.put("minecraft:carpet.15", "minecraft:black_carpet"); ++ hashmap.put("minecraft:hardened_clay.0", "minecraft:terracotta"); ++ hashmap.put("minecraft:stained_hardened_clay.0", "minecraft:white_terracotta"); ++ hashmap.put("minecraft:stained_hardened_clay.1", "minecraft:orange_terracotta"); ++ hashmap.put("minecraft:stained_hardened_clay.2", "minecraft:magenta_terracotta"); ++ hashmap.put("minecraft:stained_hardened_clay.3", "minecraft:light_blue_terracotta"); ++ hashmap.put("minecraft:stained_hardened_clay.4", "minecraft:yellow_terracotta"); ++ hashmap.put("minecraft:stained_hardened_clay.5", "minecraft:lime_terracotta"); ++ hashmap.put("minecraft:stained_hardened_clay.6", "minecraft:pink_terracotta"); ++ hashmap.put("minecraft:stained_hardened_clay.7", "minecraft:gray_terracotta"); ++ hashmap.put("minecraft:stained_hardened_clay.8", "minecraft:light_gray_terracotta"); ++ hashmap.put("minecraft:stained_hardened_clay.9", "minecraft:cyan_terracotta"); ++ hashmap.put("minecraft:stained_hardened_clay.10", "minecraft:purple_terracotta"); ++ hashmap.put("minecraft:stained_hardened_clay.11", "minecraft:blue_terracotta"); ++ hashmap.put("minecraft:stained_hardened_clay.12", "minecraft:brown_terracotta"); ++ hashmap.put("minecraft:stained_hardened_clay.13", "minecraft:green_terracotta"); ++ hashmap.put("minecraft:stained_hardened_clay.14", "minecraft:red_terracotta"); ++ hashmap.put("minecraft:stained_hardened_clay.15", "minecraft:black_terracotta"); ++ hashmap.put("minecraft:silver_glazed_terracotta.0", "minecraft:light_gray_glazed_terracotta"); ++ hashmap.put("minecraft:stained_glass.0", "minecraft:white_stained_glass"); ++ hashmap.put("minecraft:stained_glass.1", "minecraft:orange_stained_glass"); ++ hashmap.put("minecraft:stained_glass.2", "minecraft:magenta_stained_glass"); ++ hashmap.put("minecraft:stained_glass.3", "minecraft:light_blue_stained_glass"); ++ hashmap.put("minecraft:stained_glass.4", "minecraft:yellow_stained_glass"); ++ hashmap.put("minecraft:stained_glass.5", "minecraft:lime_stained_glass"); ++ hashmap.put("minecraft:stained_glass.6", "minecraft:pink_stained_glass"); ++ hashmap.put("minecraft:stained_glass.7", "minecraft:gray_stained_glass"); ++ hashmap.put("minecraft:stained_glass.8", "minecraft:light_gray_stained_glass"); ++ hashmap.put("minecraft:stained_glass.9", "minecraft:cyan_stained_glass"); ++ hashmap.put("minecraft:stained_glass.10", "minecraft:purple_stained_glass"); ++ hashmap.put("minecraft:stained_glass.11", "minecraft:blue_stained_glass"); ++ hashmap.put("minecraft:stained_glass.12", "minecraft:brown_stained_glass"); ++ hashmap.put("minecraft:stained_glass.13", "minecraft:green_stained_glass"); ++ hashmap.put("minecraft:stained_glass.14", "minecraft:red_stained_glass"); ++ hashmap.put("minecraft:stained_glass.15", "minecraft:black_stained_glass"); ++ hashmap.put("minecraft:stained_glass_pane.0", "minecraft:white_stained_glass_pane"); ++ hashmap.put("minecraft:stained_glass_pane.1", "minecraft:orange_stained_glass_pane"); ++ hashmap.put("minecraft:stained_glass_pane.2", "minecraft:magenta_stained_glass_pane"); ++ hashmap.put("minecraft:stained_glass_pane.3", "minecraft:light_blue_stained_glass_pane"); ++ hashmap.put("minecraft:stained_glass_pane.4", "minecraft:yellow_stained_glass_pane"); ++ hashmap.put("minecraft:stained_glass_pane.5", "minecraft:lime_stained_glass_pane"); ++ hashmap.put("minecraft:stained_glass_pane.6", "minecraft:pink_stained_glass_pane"); ++ hashmap.put("minecraft:stained_glass_pane.7", "minecraft:gray_stained_glass_pane"); ++ hashmap.put("minecraft:stained_glass_pane.8", "minecraft:light_gray_stained_glass_pane"); ++ hashmap.put("minecraft:stained_glass_pane.9", "minecraft:cyan_stained_glass_pane"); ++ hashmap.put("minecraft:stained_glass_pane.10", "minecraft:purple_stained_glass_pane"); ++ hashmap.put("minecraft:stained_glass_pane.11", "minecraft:blue_stained_glass_pane"); ++ hashmap.put("minecraft:stained_glass_pane.12", "minecraft:brown_stained_glass_pane"); ++ hashmap.put("minecraft:stained_glass_pane.13", "minecraft:green_stained_glass_pane"); ++ hashmap.put("minecraft:stained_glass_pane.14", "minecraft:red_stained_glass_pane"); ++ hashmap.put("minecraft:stained_glass_pane.15", "minecraft:black_stained_glass_pane"); ++ hashmap.put("minecraft:prismarine.0", "minecraft:prismarine"); ++ hashmap.put("minecraft:prismarine.1", "minecraft:prismarine_bricks"); ++ hashmap.put("minecraft:prismarine.2", "minecraft:dark_prismarine"); ++ hashmap.put("minecraft:concrete.0", "minecraft:white_concrete"); ++ hashmap.put("minecraft:concrete.1", "minecraft:orange_concrete"); ++ hashmap.put("minecraft:concrete.2", "minecraft:magenta_concrete"); ++ hashmap.put("minecraft:concrete.3", "minecraft:light_blue_concrete"); ++ hashmap.put("minecraft:concrete.4", "minecraft:yellow_concrete"); ++ hashmap.put("minecraft:concrete.5", "minecraft:lime_concrete"); ++ hashmap.put("minecraft:concrete.6", "minecraft:pink_concrete"); ++ hashmap.put("minecraft:concrete.7", "minecraft:gray_concrete"); ++ hashmap.put("minecraft:concrete.8", "minecraft:light_gray_concrete"); ++ hashmap.put("minecraft:concrete.9", "minecraft:cyan_concrete"); ++ hashmap.put("minecraft:concrete.10", "minecraft:purple_concrete"); ++ hashmap.put("minecraft:concrete.11", "minecraft:blue_concrete"); ++ hashmap.put("minecraft:concrete.12", "minecraft:brown_concrete"); ++ hashmap.put("minecraft:concrete.13", "minecraft:green_concrete"); ++ hashmap.put("minecraft:concrete.14", "minecraft:red_concrete"); ++ hashmap.put("minecraft:concrete.15", "minecraft:black_concrete"); ++ hashmap.put("minecraft:concrete_powder.0", "minecraft:white_concrete_powder"); ++ hashmap.put("minecraft:concrete_powder.1", "minecraft:orange_concrete_powder"); ++ hashmap.put("minecraft:concrete_powder.2", "minecraft:magenta_concrete_powder"); ++ hashmap.put("minecraft:concrete_powder.3", "minecraft:light_blue_concrete_powder"); ++ hashmap.put("minecraft:concrete_powder.4", "minecraft:yellow_concrete_powder"); ++ hashmap.put("minecraft:concrete_powder.5", "minecraft:lime_concrete_powder"); ++ hashmap.put("minecraft:concrete_powder.6", "minecraft:pink_concrete_powder"); ++ hashmap.put("minecraft:concrete_powder.7", "minecraft:gray_concrete_powder"); ++ hashmap.put("minecraft:concrete_powder.8", "minecraft:light_gray_concrete_powder"); ++ hashmap.put("minecraft:concrete_powder.9", "minecraft:cyan_concrete_powder"); ++ hashmap.put("minecraft:concrete_powder.10", "minecraft:purple_concrete_powder"); ++ hashmap.put("minecraft:concrete_powder.11", "minecraft:blue_concrete_powder"); ++ hashmap.put("minecraft:concrete_powder.12", "minecraft:brown_concrete_powder"); ++ hashmap.put("minecraft:concrete_powder.13", "minecraft:green_concrete_powder"); ++ hashmap.put("minecraft:concrete_powder.14", "minecraft:red_concrete_powder"); ++ hashmap.put("minecraft:concrete_powder.15", "minecraft:black_concrete_powder"); ++ hashmap.put("minecraft:cobblestone_wall.0", "minecraft:cobblestone_wall"); ++ hashmap.put("minecraft:cobblestone_wall.1", "minecraft:mossy_cobblestone_wall"); ++ hashmap.put("minecraft:sandstone.0", "minecraft:sandstone"); ++ hashmap.put("minecraft:sandstone.1", "minecraft:chiseled_sandstone"); ++ hashmap.put("minecraft:sandstone.2", "minecraft:cut_sandstone"); ++ hashmap.put("minecraft:red_sandstone.0", "minecraft:red_sandstone"); ++ hashmap.put("minecraft:red_sandstone.1", "minecraft:chiseled_red_sandstone"); ++ hashmap.put("minecraft:red_sandstone.2", "minecraft:cut_red_sandstone"); ++ hashmap.put("minecraft:stonebrick.0", "minecraft:stone_bricks"); ++ hashmap.put("minecraft:stonebrick.1", "minecraft:mossy_stone_bricks"); ++ hashmap.put("minecraft:stonebrick.2", "minecraft:cracked_stone_bricks"); ++ hashmap.put("minecraft:stonebrick.3", "minecraft:chiseled_stone_bricks"); ++ hashmap.put("minecraft:monster_egg.0", "minecraft:infested_stone"); ++ hashmap.put("minecraft:monster_egg.1", "minecraft:infested_cobblestone"); ++ hashmap.put("minecraft:monster_egg.2", "minecraft:infested_stone_bricks"); ++ hashmap.put("minecraft:monster_egg.3", "minecraft:infested_mossy_stone_bricks"); ++ hashmap.put("minecraft:monster_egg.4", "minecraft:infested_cracked_stone_bricks"); ++ hashmap.put("minecraft:monster_egg.5", "minecraft:infested_chiseled_stone_bricks"); ++ hashmap.put("minecraft:yellow_flower.0", "minecraft:dandelion"); ++ hashmap.put("minecraft:red_flower.0", "minecraft:poppy"); ++ hashmap.put("minecraft:red_flower.1", "minecraft:blue_orchid"); ++ hashmap.put("minecraft:red_flower.2", "minecraft:allium"); ++ hashmap.put("minecraft:red_flower.3", "minecraft:azure_bluet"); ++ hashmap.put("minecraft:red_flower.4", "minecraft:red_tulip"); ++ hashmap.put("minecraft:red_flower.5", "minecraft:orange_tulip"); ++ hashmap.put("minecraft:red_flower.6", "minecraft:white_tulip"); ++ hashmap.put("minecraft:red_flower.7", "minecraft:pink_tulip"); ++ hashmap.put("minecraft:red_flower.8", "minecraft:oxeye_daisy"); ++ hashmap.put("minecraft:double_plant.0", "minecraft:sunflower"); ++ hashmap.put("minecraft:double_plant.1", "minecraft:lilac"); ++ hashmap.put("minecraft:double_plant.2", "minecraft:tall_grass"); ++ hashmap.put("minecraft:double_plant.3", "minecraft:large_fern"); ++ hashmap.put("minecraft:double_plant.4", "minecraft:rose_bush"); ++ hashmap.put("minecraft:double_plant.5", "minecraft:peony"); ++ hashmap.put("minecraft:deadbush.0", "minecraft:dead_bush"); ++ hashmap.put("minecraft:tallgrass.0", "minecraft:dead_bush"); ++ hashmap.put("minecraft:tallgrass.1", "minecraft:grass"); ++ hashmap.put("minecraft:tallgrass.2", "minecraft:fern"); ++ hashmap.put("minecraft:sponge.0", "minecraft:sponge"); ++ hashmap.put("minecraft:sponge.1", "minecraft:wet_sponge"); ++ hashmap.put("minecraft:purpur_slab.0", "minecraft:purpur_slab"); ++ hashmap.put("minecraft:stone_slab.0", "minecraft:stone_slab"); ++ hashmap.put("minecraft:stone_slab.1", "minecraft:sandstone_slab"); ++ hashmap.put("minecraft:stone_slab.2", "minecraft:petrified_oak_slab"); ++ hashmap.put("minecraft:stone_slab.3", "minecraft:cobblestone_slab"); ++ hashmap.put("minecraft:stone_slab.4", "minecraft:brick_slab"); ++ hashmap.put("minecraft:stone_slab.5", "minecraft:stone_brick_slab"); ++ hashmap.put("minecraft:stone_slab.6", "minecraft:nether_brick_slab"); ++ hashmap.put("minecraft:stone_slab.7", "minecraft:quartz_slab"); ++ hashmap.put("minecraft:stone_slab2.0", "minecraft:red_sandstone_slab"); ++ hashmap.put("minecraft:wooden_slab.0", "minecraft:oak_slab"); ++ hashmap.put("minecraft:wooden_slab.1", "minecraft:spruce_slab"); ++ hashmap.put("minecraft:wooden_slab.2", "minecraft:birch_slab"); ++ hashmap.put("minecraft:wooden_slab.3", "minecraft:jungle_slab"); ++ hashmap.put("minecraft:wooden_slab.4", "minecraft:acacia_slab"); ++ hashmap.put("minecraft:wooden_slab.5", "minecraft:dark_oak_slab"); ++ hashmap.put("minecraft:coal.0", "minecraft:coal"); ++ hashmap.put("minecraft:coal.1", "minecraft:charcoal"); ++ hashmap.put("minecraft:fish.0", "minecraft:cod"); ++ hashmap.put("minecraft:fish.1", "minecraft:salmon"); ++ hashmap.put("minecraft:fish.2", "minecraft:clownfish"); ++ hashmap.put("minecraft:fish.3", "minecraft:pufferfish"); ++ hashmap.put("minecraft:cooked_fish.0", "minecraft:cooked_cod"); ++ hashmap.put("minecraft:cooked_fish.1", "minecraft:cooked_salmon"); ++ hashmap.put("minecraft:skull.0", "minecraft:skeleton_skull"); ++ hashmap.put("minecraft:skull.1", "minecraft:wither_skeleton_skull"); ++ hashmap.put("minecraft:skull.2", "minecraft:zombie_head"); ++ hashmap.put("minecraft:skull.3", "minecraft:player_head"); ++ hashmap.put("minecraft:skull.4", "minecraft:creeper_head"); ++ hashmap.put("minecraft:skull.5", "minecraft:dragon_head"); ++ hashmap.put("minecraft:golden_apple.0", "minecraft:golden_apple"); ++ hashmap.put("minecraft:golden_apple.1", "minecraft:enchanted_golden_apple"); ++ hashmap.put("minecraft:fireworks.0", "minecraft:firework_rocket"); ++ hashmap.put("minecraft:firework_charge.0", "minecraft:firework_star"); ++ hashmap.put("minecraft:dye.0", "minecraft:ink_sac"); ++ hashmap.put("minecraft:dye.1", "minecraft:rose_red"); ++ hashmap.put("minecraft:dye.2", "minecraft:cactus_green"); ++ hashmap.put("minecraft:dye.3", "minecraft:cocoa_beans"); ++ hashmap.put("minecraft:dye.4", "minecraft:lapis_lazuli"); ++ hashmap.put("minecraft:dye.5", "minecraft:purple_dye"); ++ hashmap.put("minecraft:dye.6", "minecraft:cyan_dye"); ++ hashmap.put("minecraft:dye.7", "minecraft:light_gray_dye"); ++ hashmap.put("minecraft:dye.8", "minecraft:gray_dye"); ++ hashmap.put("minecraft:dye.9", "minecraft:pink_dye"); ++ hashmap.put("minecraft:dye.10", "minecraft:lime_dye"); ++ hashmap.put("minecraft:dye.11", "minecraft:dandelion_yellow"); ++ hashmap.put("minecraft:dye.12", "minecraft:light_blue_dye"); ++ hashmap.put("minecraft:dye.13", "minecraft:magenta_dye"); ++ hashmap.put("minecraft:dye.14", "minecraft:orange_dye"); ++ hashmap.put("minecraft:dye.15", "minecraft:bone_meal"); ++ hashmap.put("minecraft:silver_shulker_box.0", "minecraft:light_gray_shulker_box"); ++ hashmap.put("minecraft:fence.0", "minecraft:oak_fence"); ++ hashmap.put("minecraft:fence_gate.0", "minecraft:oak_fence_gate"); ++ hashmap.put("minecraft:wooden_door.0", "minecraft:oak_door"); ++ hashmap.put("minecraft:boat.0", "minecraft:oak_boat"); ++ hashmap.put("minecraft:lit_pumpkin.0", "minecraft:jack_o_lantern"); ++ hashmap.put("minecraft:pumpkin.0", "minecraft:carved_pumpkin"); ++ hashmap.put("minecraft:trapdoor.0", "minecraft:oak_trapdoor"); ++ hashmap.put("minecraft:nether_brick.0", "minecraft:nether_bricks"); ++ hashmap.put("minecraft:red_nether_brick.0", "minecraft:red_nether_bricks"); ++ hashmap.put("minecraft:netherbrick.0", "minecraft:nether_brick"); ++ hashmap.put("minecraft:wooden_button.0", "minecraft:oak_button"); ++ hashmap.put("minecraft:wooden_pressure_plate.0", "minecraft:oak_pressure_plate"); ++ hashmap.put("minecraft:noteblock.0", "minecraft:note_block"); ++ hashmap.put("minecraft:bed.0", "minecraft:white_bed"); ++ hashmap.put("minecraft:bed.1", "minecraft:orange_bed"); ++ hashmap.put("minecraft:bed.2", "minecraft:magenta_bed"); ++ hashmap.put("minecraft:bed.3", "minecraft:light_blue_bed"); ++ hashmap.put("minecraft:bed.4", "minecraft:yellow_bed"); ++ hashmap.put("minecraft:bed.5", "minecraft:lime_bed"); ++ hashmap.put("minecraft:bed.6", "minecraft:pink_bed"); ++ hashmap.put("minecraft:bed.7", "minecraft:gray_bed"); ++ hashmap.put("minecraft:bed.8", "minecraft:light_gray_bed"); ++ hashmap.put("minecraft:bed.9", "minecraft:cyan_bed"); ++ hashmap.put("minecraft:bed.10", "minecraft:purple_bed"); ++ hashmap.put("minecraft:bed.11", "minecraft:blue_bed"); ++ hashmap.put("minecraft:bed.12", "minecraft:brown_bed"); ++ hashmap.put("minecraft:bed.13", "minecraft:green_bed"); ++ hashmap.put("minecraft:bed.14", "minecraft:red_bed"); ++ hashmap.put("minecraft:bed.15", "minecraft:black_bed"); ++ hashmap.put("minecraft:banner.15", "minecraft:white_banner"); ++ hashmap.put("minecraft:banner.14", "minecraft:orange_banner"); ++ hashmap.put("minecraft:banner.13", "minecraft:magenta_banner"); ++ hashmap.put("minecraft:banner.12", "minecraft:light_blue_banner"); ++ hashmap.put("minecraft:banner.11", "minecraft:yellow_banner"); ++ hashmap.put("minecraft:banner.10", "minecraft:lime_banner"); ++ hashmap.put("minecraft:banner.9", "minecraft:pink_banner"); ++ hashmap.put("minecraft:banner.8", "minecraft:gray_banner"); ++ hashmap.put("minecraft:banner.7", "minecraft:light_gray_banner"); ++ hashmap.put("minecraft:banner.6", "minecraft:cyan_banner"); ++ hashmap.put("minecraft:banner.5", "minecraft:purple_banner"); ++ hashmap.put("minecraft:banner.4", "minecraft:blue_banner"); ++ hashmap.put("minecraft:banner.3", "minecraft:brown_banner"); ++ hashmap.put("minecraft:banner.2", "minecraft:green_banner"); ++ hashmap.put("minecraft:banner.1", "minecraft:red_banner"); ++ hashmap.put("minecraft:banner.0", "minecraft:black_banner"); ++ hashmap.put("minecraft:grass.0", "minecraft:grass_block"); ++ hashmap.put("minecraft:brick_block.0", "minecraft:bricks"); ++ hashmap.put("minecraft:end_bricks.0", "minecraft:end_stone_bricks"); ++ hashmap.put("minecraft:golden_rail.0", "minecraft:powered_rail"); ++ hashmap.put("minecraft:magma.0", "minecraft:magma_block"); ++ hashmap.put("minecraft:quartz_ore.0", "minecraft:nether_quartz_ore"); ++ hashmap.put("minecraft:reeds.0", "minecraft:sugar_cane"); ++ hashmap.put("minecraft:slime.0", "minecraft:slime_block"); ++ hashmap.put("minecraft:stone_stairs.0", "minecraft:cobblestone_stairs"); ++ hashmap.put("minecraft:waterlily.0", "minecraft:lily_pad"); ++ hashmap.put("minecraft:web.0", "minecraft:cobweb"); ++ hashmap.put("minecraft:snow.0", "minecraft:snow_block"); ++ hashmap.put("minecraft:snow_layer.0", "minecraft:snow"); ++ hashmap.put("minecraft:record_11.0", "minecraft:music_disc_11"); ++ hashmap.put("minecraft:record_13.0", "minecraft:music_disc_13"); ++ hashmap.put("minecraft:record_blocks.0", "minecraft:music_disc_blocks"); ++ hashmap.put("minecraft:record_cat.0", "minecraft:music_disc_cat"); ++ hashmap.put("minecraft:record_chirp.0", "minecraft:music_disc_chirp"); ++ hashmap.put("minecraft:record_far.0", "minecraft:music_disc_far"); ++ hashmap.put("minecraft:record_mall.0", "minecraft:music_disc_mall"); ++ hashmap.put("minecraft:record_mellohi.0", "minecraft:music_disc_mellohi"); ++ hashmap.put("minecraft:record_stal.0", "minecraft:music_disc_stal"); ++ hashmap.put("minecraft:record_strad.0", "minecraft:music_disc_strad"); ++ hashmap.put("minecraft:record_wait.0", "minecraft:music_disc_wait"); ++ hashmap.put("minecraft:record_ward.0", "minecraft:music_disc_ward"); + }); +- private static final Set IDS = MAP.keySet().stream().map(string -> string.substring(0, string.indexOf(46))).collect(Collectors.toSet()); +- private static final Set DAMAGE_IDS = Sets.newHashSet( +- "minecraft:bow", +- "minecraft:carrot_on_a_stick", +- "minecraft:chainmail_boots", +- "minecraft:chainmail_chestplate", +- "minecraft:chainmail_helmet", +- "minecraft:chainmail_leggings", +- "minecraft:diamond_axe", +- "minecraft:diamond_boots", +- "minecraft:diamond_chestplate", +- "minecraft:diamond_helmet", +- "minecraft:diamond_hoe", +- "minecraft:diamond_leggings", +- "minecraft:diamond_pickaxe", +- "minecraft:diamond_shovel", +- "minecraft:diamond_sword", +- "minecraft:elytra", +- "minecraft:fishing_rod", +- "minecraft:flint_and_steel", +- "minecraft:golden_axe", +- "minecraft:golden_boots", +- "minecraft:golden_chestplate", +- "minecraft:golden_helmet", +- "minecraft:golden_hoe", +- "minecraft:golden_leggings", +- "minecraft:golden_pickaxe", +- "minecraft:golden_shovel", +- "minecraft:golden_sword", +- "minecraft:iron_axe", +- "minecraft:iron_boots", +- "minecraft:iron_chestplate", +- "minecraft:iron_helmet", +- "minecraft:iron_hoe", +- "minecraft:iron_leggings", +- "minecraft:iron_pickaxe", +- "minecraft:iron_shovel", +- "minecraft:iron_sword", +- "minecraft:leather_boots", +- "minecraft:leather_chestplate", +- "minecraft:leather_helmet", +- "minecraft:leather_leggings", +- "minecraft:shears", +- "minecraft:shield", +- "minecraft:stone_axe", +- "minecraft:stone_hoe", +- "minecraft:stone_pickaxe", +- "minecraft:stone_shovel", +- "minecraft:stone_sword", +- "minecraft:wooden_axe", +- "minecraft:wooden_hoe", +- "minecraft:wooden_pickaxe", +- "minecraft:wooden_shovel", +- "minecraft:wooden_sword" +- ); ++ private static final Set IDS = (Set) ItemStackTheFlatteningFix.MAP.keySet().stream().map((s) -> { ++ return s.substring(0, s.indexOf(46)); ++ }).collect(Collectors.toSet()); ++ private static final Set DAMAGE_IDS = Sets.newHashSet(new String[]{"minecraft:bow", "minecraft:carrot_on_a_stick", "minecraft:chainmail_boots", "minecraft:chainmail_chestplate", "minecraft:chainmail_helmet", "minecraft:chainmail_leggings", "minecraft:diamond_axe", "minecraft:diamond_boots", "minecraft:diamond_chestplate", "minecraft:diamond_helmet", "minecraft:diamond_hoe", "minecraft:diamond_leggings", "minecraft:diamond_pickaxe", "minecraft:diamond_shovel", "minecraft:diamond_sword", "minecraft:elytra", "minecraft:fishing_rod", "minecraft:flint_and_steel", "minecraft:golden_axe", "minecraft:golden_boots", "minecraft:golden_chestplate", "minecraft:golden_helmet", "minecraft:golden_hoe", "minecraft:golden_leggings", "minecraft:golden_pickaxe", "minecraft:golden_shovel", "minecraft:golden_sword", "minecraft:iron_axe", "minecraft:iron_boots", "minecraft:iron_chestplate", "minecraft:iron_helmet", "minecraft:iron_hoe", "minecraft:iron_leggings", "minecraft:iron_pickaxe", "minecraft:iron_shovel", "minecraft:iron_sword", "minecraft:leather_boots", "minecraft:leather_chestplate", "minecraft:leather_helmet", "minecraft:leather_leggings", "minecraft:shears", "minecraft:shield", "minecraft:stone_axe", "minecraft:stone_hoe", "minecraft:stone_pickaxe", "minecraft:stone_shovel", "minecraft:stone_sword", "minecraft:wooden_axe", "minecraft:wooden_hoe", "minecraft:wooden_pickaxe", "minecraft:wooden_shovel", "minecraft:wooden_sword"}); + + public ItemStackTheFlatteningFix(Schema outputSchema, boolean changesType) { + super(outputSchema, changesType); + } + +- @Override + public TypeRewriteRule makeRule() { +- Type type = this.getInputSchema().getType(References.ITEM_STACK); +- OpticFinder> opticFinder = DSL.fieldFinder("id", DSL.named(References.ITEM_NAME.typeName(), NamespacedSchema.namespacedString())); +- OpticFinder opticFinder1 = type.findField("tag"); +- return this.fixTypeEverywhereTyped("ItemInstanceTheFlatteningFix", type, typed -> { +- Optional> optional = typed.getOptional(opticFinder); ++ Type type = this.getInputSchema().getType(DataConverterTypes.ITEM_STACK); ++ OpticFinder> opticfinder = DSL.fieldFinder("id", DSL.named(DataConverterTypes.ITEM_NAME.typeName(), NamespacedSchema.namespacedString())); ++ OpticFinder opticfinder1 = type.findField("tag"); ++ ++ return this.fixTypeEverywhereTyped("ItemInstanceTheFlatteningFix", type, (typed) -> { ++ Optional> optional = typed.getOptional(opticfinder); ++ + if (optional.isEmpty()) { + return typed; + } else { + Typed typed1 = typed; +- Dynamic dynamic = typed.get(DSL.remainderFinder()); +- int _int = dynamic.get("Damage").asInt(0); +- String string = updateItem(optional.get().getSecond(), _int); +- if (string != null) { +- typed1 = typed.set(opticFinder, Pair.of(References.ITEM_NAME.typeName(), string)); ++ Dynamic dynamic = (Dynamic) typed.get(DSL.remainderFinder()); ++ int i = dynamic.get("Damage").asInt(0); ++ String s = updateItem((String) ((Pair) optional.get()).getSecond(), i); ++ ++ if (s != null) { ++ typed1 = typed.set(opticfinder, Pair.of(DataConverterTypes.ITEM_NAME.typeName(), s)); + } + +- if (DAMAGE_IDS.contains(optional.get().getSecond())) { +- Typed typed2 = typed.getOrCreateTyped(opticFinder1); +- Dynamic dynamic1 = typed2.get(DSL.remainderFinder()); +- dynamic1 = dynamic1.set("Damage", dynamic1.createInt(_int)); +- typed1 = typed1.set(opticFinder1, typed2.set(DSL.remainderFinder(), dynamic1)); ++ if (ItemStackTheFlatteningFix.DAMAGE_IDS.contains(((Pair) optional.get()).getSecond())) { ++ Typed typed2 = typed.getOrCreateTyped(opticfinder1); ++ Dynamic dynamic1 = (Dynamic) typed2.get(DSL.remainderFinder()); ++ ++ if (i != 0) dynamic1 = dynamic1.set("Damage", dynamic1.createInt(i)); // CraftBukkit ++ typed1 = typed1.set(opticfinder1, typed2.set(DSL.remainderFinder(), dynamic1)); + } + +- return typed1.set(DSL.remainderFinder(), dynamic.remove("Damage")); ++ typed1 = typed1.set(DSL.remainderFinder(), dynamic.remove("Damage")); ++ return typed1; + } + }); + } + + @Nullable + public static String updateItem(@Nullable String item, int dataValue) { +- if (IDS.contains(item)) { +- String string = MAP.get(item + "." + dataValue); +- return string == null ? MAP.get(item + ".0") : string; ++ if (ItemStackTheFlatteningFix.IDS.contains(item)) { ++ String s1 = (String) ItemStackTheFlatteningFix.MAP.get(item + "." + dataValue); ++ ++ return s1 == null ? (String) ItemStackTheFlatteningFix.MAP.get(item + ".0") : s1; + } else { + return null; + } diff --git a/patch-remap/mache-vineflower/net/minecraft/util/worldupdate/WorldUpgrader.java.patch b/patch-remap/mache-vineflower/net/minecraft/util/worldupdate/WorldUpgrader.java.patch new file mode 100644 index 0000000000..11f5e0881e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/util/worldupdate/WorldUpgrader.java.patch @@ -0,0 +1,325 @@ +--- a/net/minecraft/util/worldupdate/WorldUpgrader.java ++++ b/net/minecraft/util/worldupdate/WorldUpgrader.java +@@ -2,8 +2,9 @@ + + import com.google.common.collect.ImmutableList; + import com.google.common.collect.ImmutableMap; +-import com.google.common.collect.Lists; + import com.google.common.collect.ImmutableMap.Builder; ++import com.google.common.collect.Lists; ++import com.google.common.collect.UnmodifiableIterator; + import com.google.common.util.concurrent.ThreadFactoryBuilder; + import com.mojang.datafixers.DataFixer; + import com.mojang.logging.LogUtils; +@@ -13,8 +14,10 @@ + import java.io.File; + import java.io.IOException; + import java.nio.file.Path; ++import java.util.Iterator; + import java.util.List; + import java.util.ListIterator; ++import java.util.Optional; + import java.util.Set; + import java.util.concurrent.CompletionException; + import java.util.concurrent.ThreadFactory; +@@ -41,8 +44,9 @@ + import org.slf4j.Logger; + + public class WorldUpgrader { ++ + private static final Logger LOGGER = LogUtils.getLogger(); +- private static final ThreadFactory THREAD_FACTORY = new ThreadFactoryBuilder().setDaemon(true).build(); ++ private static final ThreadFactory THREAD_FACTORY = (new ThreadFactoryBuilder()).setDaemon(true).build(); + private final Registry dimensions; + private final Set> levels; + private final boolean eraseCache; +@@ -55,21 +59,21 @@ + private volatile int totalChunks; + private volatile int converted; + private volatile int skipped; +- private final Reference2FloatMap> progressMap = Reference2FloatMaps.synchronize(new Reference2FloatOpenHashMap<>()); ++ private final Reference2FloatMap> progressMap = Reference2FloatMaps.synchronize(new Reference2FloatOpenHashMap()); + private volatile Component status = Component.translatable("optimizeWorld.stage.counting"); + private static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$"); + private final DimensionDataStorage overworldDataStorage; + + public WorldUpgrader(LevelStorageSource.LevelStorageAccess levelStoarge, DataFixer dataFixer, Registry dimensions, boolean eraseCache) { + this.dimensions = dimensions; +- this.levels = dimensions.registryKeySet().stream().map(Registries::levelStemToLevel).collect(Collectors.toUnmodifiableSet()); ++ this.levels = (Set) java.util.stream.Stream.of(levelStoarge.dimensionType).map(Registries::levelStemToLevel).collect(Collectors.toUnmodifiableSet()); // CraftBukkit + this.eraseCache = eraseCache; + this.dataFixer = dataFixer; + this.levelStorage = levelStoarge; + this.overworldDataStorage = new DimensionDataStorage(this.levelStorage.getDimensionPath(Level.OVERWORLD).resolve("data").toFile(), dataFixer); +- this.thread = THREAD_FACTORY.newThread(this::work); ++ this.thread = WorldUpgrader.THREAD_FACTORY.newThread(this::work); + this.thread.setUncaughtExceptionHandler((thread, throwable) -> { +- LOGGER.error("Error upgrading world", throwable); ++ WorldUpgrader.LOGGER.error("Error upgrading world", throwable); + this.status = Component.translatable("optimizeWorld.stage.failed"); + this.finished = true; + }); +@@ -81,103 +85,120 @@ + + try { + this.thread.join(); +- } catch (InterruptedException var2) { ++ } catch (InterruptedException interruptedexception) { ++ ; + } ++ + } + + private void work() { + this.totalChunks = 0; + Builder, ListIterator> builder = ImmutableMap.builder(); + +- for (ResourceKey resourceKey : this.levels) { +- List allChunkPos = this.getAllChunkPos(resourceKey); +- builder.put(resourceKey, allChunkPos.listIterator()); +- this.totalChunks = this.totalChunks + allChunkPos.size(); ++ List list; ++ ++ for (Iterator iterator = this.levels.iterator(); iterator.hasNext(); this.totalChunks += list.size()) { ++ ResourceKey resourcekey = (ResourceKey) iterator.next(); ++ ++ list = this.getAllChunkPos(resourcekey); ++ builder.put(resourcekey, list.listIterator()); + } + + if (this.totalChunks == 0) { + this.finished = true; + } else { +- float f = (float)this.totalChunks; +- ImmutableMap, ListIterator> map = builder.build(); ++ float f = (float) this.totalChunks; ++ ImmutableMap, ListIterator> immutablemap = builder.build(); + Builder, ChunkStorage> builder1 = ImmutableMap.builder(); ++ Iterator iterator1 = this.levels.iterator(); + +- for (ResourceKey resourceKey1 : this.levels) { +- Path dimensionPath = this.levelStorage.getDimensionPath(resourceKey1); +- builder1.put(resourceKey1, new ChunkStorage(dimensionPath.resolve("region"), this.dataFixer, true)); ++ while (iterator1.hasNext()) { ++ ResourceKey resourcekey1 = (ResourceKey) iterator1.next(); ++ Path path = this.levelStorage.getDimensionPath(resourcekey1); ++ ++ builder1.put(resourcekey1, new ChunkStorage(path.resolve("region"), this.dataFixer, true)); + } + +- ImmutableMap, ChunkStorage> map1 = builder1.build(); +- long millis = Util.getMillis(); ++ ImmutableMap, ChunkStorage> immutablemap1 = builder1.build(); ++ long i = Util.getMillis(); ++ + this.status = Component.translatable("optimizeWorld.stage.upgrading"); + + while (this.running) { + boolean flag = false; + float f1 = 0.0F; + +- for (ResourceKey resourceKey2 : this.levels) { +- ListIterator listIterator = map.get(resourceKey2); +- ChunkStorage chunkStorage = map1.get(resourceKey2); +- if (listIterator.hasNext()) { +- ChunkPos chunkPos = listIterator.next(); ++ float f2; ++ ++ for (Iterator iterator2 = this.levels.iterator(); iterator2.hasNext(); f1 += f2) { ++ ResourceKey resourcekey2 = (ResourceKey) iterator2.next(); ++ ListIterator listiterator = (ListIterator) immutablemap.get(resourcekey2); ++ ChunkStorage ichunkloader = (ChunkStorage) immutablemap1.get(resourcekey2); ++ ++ if (listiterator.hasNext()) { ++ ChunkPos chunkcoordintpair = (ChunkPos) listiterator.next(); + boolean flag1 = false; + + try { +- CompoundTag compoundTag = chunkStorage.read(chunkPos).join().orElse(null); +- if (compoundTag != null) { +- int version = ChunkStorage.getVersion(compoundTag); +- ChunkGenerator chunkGenerator = this.dimensions.getOrThrow(Registries.levelToLevelStem(resourceKey2)).generator(); +- CompoundTag compoundTag1 = chunkStorage.upgradeChunkTag( +- resourceKey2, () -> this.overworldDataStorage, compoundTag, chunkGenerator.getTypeNameForDataFixer() +- ); +- ChunkPos chunkPos1 = new ChunkPos(compoundTag1.getInt("xPos"), compoundTag1.getInt("zPos")); +- if (!chunkPos1.equals(chunkPos)) { +- LOGGER.warn("Chunk {} has invalid position {}", chunkPos, chunkPos1); ++ CompoundTag nbttagcompound = (CompoundTag) ((Optional) ichunkloader.read(chunkcoordintpair).join()).orElse((Object) null); ++ ++ if (nbttagcompound != null) { ++ int j = ChunkStorage.getVersion(nbttagcompound); ++ ChunkGenerator chunkgenerator = ((LevelStem) this.dimensions.getOrThrow(Registries.levelToLevelStem(resourcekey2))).generator(); ++ CompoundTag nbttagcompound1 = ichunkloader.upgradeChunkTag(Registries.levelToLevelStem(resourcekey2), () -> { // CraftBukkit ++ return this.overworldDataStorage; ++ }, nbttagcompound, chunkgenerator.getTypeNameForDataFixer(), chunkcoordintpair, null); // CraftBukkit ++ ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); ++ ++ if (!chunkcoordintpair1.equals(chunkcoordintpair)) { ++ WorldUpgrader.LOGGER.warn("Chunk {} has invalid position {}", chunkcoordintpair, chunkcoordintpair1); + } + +- boolean flag2 = version < SharedConstants.getCurrentVersion().getDataVersion().getVersion(); ++ boolean flag2 = j < SharedConstants.getCurrentVersion().getDataVersion().getVersion(); ++ + if (this.eraseCache) { +- flag2 = flag2 || compoundTag1.contains("Heightmaps"); +- compoundTag1.remove("Heightmaps"); +- flag2 = flag2 || compoundTag1.contains("isLightOn"); +- compoundTag1.remove("isLightOn"); +- ListTag list = compoundTag1.getList("sections", 10); ++ flag2 = flag2 || nbttagcompound1.contains("Heightmaps"); ++ nbttagcompound1.remove("Heightmaps"); ++ flag2 = flag2 || nbttagcompound1.contains("isLightOn"); ++ nbttagcompound1.remove("isLightOn"); ++ ListTag nbttaglist = nbttagcompound1.getList("sections", 10); + +- for (int i = 0; i < list.size(); i++) { +- CompoundTag compound = list.getCompound(i); +- flag2 = flag2 || compound.contains("BlockLight"); +- compound.remove("BlockLight"); +- flag2 = flag2 || compound.contains("SkyLight"); +- compound.remove("SkyLight"); ++ for (int k = 0; k < nbttaglist.size(); ++k) { ++ CompoundTag nbttagcompound2 = nbttaglist.getCompound(k); ++ ++ flag2 = flag2 || nbttagcompound2.contains("BlockLight"); ++ nbttagcompound2.remove("BlockLight"); ++ flag2 = flag2 || nbttagcompound2.contains("SkyLight"); ++ nbttagcompound2.remove("SkyLight"); + } + } + + if (flag2) { +- chunkStorage.write(chunkPos, compoundTag1); ++ ichunkloader.write(chunkcoordintpair, nbttagcompound1); + flag1 = true; + } + } +- } catch (CompletionException | ReportedException var26) { +- Throwable cause = var26.getCause(); +- if (!(cause instanceof IOException)) { +- throw var26; ++ } catch (CompletionException | ReportedException reportedexception) { ++ Throwable throwable = reportedexception.getCause(); ++ ++ if (!(throwable instanceof IOException)) { ++ throw reportedexception; + } + +- LOGGER.error("Error upgrading chunk {}", chunkPos, cause); ++ WorldUpgrader.LOGGER.error("Error upgrading chunk {}", chunkcoordintpair, throwable); + } + + if (flag1) { +- this.converted++; ++ ++this.converted; + } else { +- this.skipped++; ++ ++this.skipped; + } + + flag = true; + } + +- float f2 = (float)listIterator.nextIndex() / f; +- this.progressMap.put(resourceKey2, f2); +- f1 += f2; ++ f2 = (float) listiterator.nextIndex() / f; ++ this.progressMap.put(resourcekey2, f2); + } + + this.progress = f1; +@@ -187,18 +208,21 @@ + } + + this.status = Component.translatable("optimizeWorld.stage.finished"); ++ UnmodifiableIterator unmodifiableiterator = immutablemap1.values().iterator(); + +- for (ChunkStorage chunkStorage1 : map1.values()) { ++ while (unmodifiableiterator.hasNext()) { ++ ChunkStorage ichunkloader1 = (ChunkStorage) unmodifiableiterator.next(); ++ + try { +- chunkStorage1.close(); +- } catch (IOException var25) { +- LOGGER.error("Error upgrading chunk", (Throwable)var25); ++ ichunkloader1.close(); ++ } catch (IOException ioexception) { ++ WorldUpgrader.LOGGER.error("Error upgrading chunk", ioexception); + } + } + + this.overworldDataStorage.save(); +- millis = Util.getMillis() - millis; +- LOGGER.info("World optimizaton finished after {} ms", millis); ++ i = Util.getMillis() - i; ++ WorldUpgrader.LOGGER.info("World optimizaton finished after {} ms", i); + this.finished = true; + } + } +@@ -206,28 +230,51 @@ + private List getAllChunkPos(ResourceKey level) { + File file = this.levelStorage.getDimensionPath(level).toFile(); + File file1 = new File(file, "region"); +- File[] files = file1.listFiles((file3, string) -> string.endsWith(".mca")); +- if (files == null) { ++ File[] afile = file1.listFiles((file2, s) -> { ++ return s.endsWith(".mca"); ++ }); ++ ++ if (afile == null) { + return ImmutableList.of(); + } else { + List list = Lists.newArrayList(); ++ File[] afile1 = afile; ++ int i = afile.length; + +- for (File file2 : files) { +- Matcher matcher = REGEX.matcher(file2.getName()); ++ for (int j = 0; j < i; ++j) { ++ File file2 = afile1[j]; ++ Matcher matcher = WorldUpgrader.REGEX.matcher(file2.getName()); ++ + if (matcher.matches()) { +- int i = Integer.parseInt(matcher.group(1)) << 5; +- int i1 = Integer.parseInt(matcher.group(2)) << 5; ++ int k = Integer.parseInt(matcher.group(1)) << 5; ++ int l = Integer.parseInt(matcher.group(2)) << 5; + +- try (RegionFile regionFile = new RegionFile(file2.toPath(), file1.toPath(), true)) { +- for (int i2 = 0; i2 < 32; i2++) { +- for (int i3 = 0; i3 < 32; i3++) { +- ChunkPos chunkPos = new ChunkPos(i2 + i, i3 + i1); +- if (regionFile.doesChunkExist(chunkPos)) { +- list.add(chunkPos); ++ try { ++ RegionFile regionfile = new RegionFile(file2.toPath(), file1.toPath(), true); ++ ++ try { ++ for (int i1 = 0; i1 < 32; ++i1) { ++ for (int j1 = 0; j1 < 32; ++j1) { ++ ChunkPos chunkcoordintpair = new ChunkPos(i1 + k, j1 + l); ++ ++ if (regionfile.doesChunkExist(chunkcoordintpair)) { ++ list.add(chunkcoordintpair); ++ } + } + } ++ } catch (Throwable throwable) { ++ try { ++ regionfile.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ ++ throw throwable; + } +- } catch (Throwable var19) { ++ ++ regionfile.close(); ++ } catch (Throwable throwable2) { ++ ; + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/CompoundContainer.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/CompoundContainer.java.patch new file mode 100644 index 0000000000..e7ef6fbff5 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/CompoundContainer.java.patch @@ -0,0 +1,119 @@ +--- a/net/minecraft/world/CompoundContainer.java ++++ b/net/minecraft/world/CompoundContainer.java +@@ -3,10 +3,62 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import org.bukkit.Location; ++ ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class CompoundContainer implements Container { +- private final Container container1; +- private final Container container2; + ++ public final Container container1; ++ public final Container container2; ++ ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ ++ public List getContents() { ++ List result = new ArrayList(this.getContainerSize()); ++ for (int i = 0; i < this.getContainerSize(); i++) { ++ result.add(this.getItem(i)); ++ } ++ return result; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ this.container1.onOpen(who); ++ this.container2.onOpen(who); ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ this.container1.onClose(who); ++ this.container2.onClose(who); ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return null; // This method won't be called since CraftInventoryDoubleChest doesn't defer to here ++ } ++ ++ public void setMaxStackSize(int size) { ++ this.container1.setMaxStackSize(size); ++ this.container2.setMaxStackSize(size); ++ } ++ ++ @Override ++ public Location getLocation() { ++ return container1.getLocation(); // TODO: right? ++ } ++ // CraftBukkit end ++ + public CompoundContainer(Container container1, Container container2) { + this.container1 = container1; + this.container2 = container2; +@@ -28,23 +80,17 @@ + + @Override + public ItemStack getItem(int index) { +- return index >= this.container1.getContainerSize() +- ? this.container2.getItem(index - this.container1.getContainerSize()) +- : this.container1.getItem(index); ++ return index >= this.container1.getContainerSize() ? this.container2.getItem(index - this.container1.getContainerSize()) : this.container1.getItem(index); + } + + @Override + public ItemStack removeItem(int index, int count) { +- return index >= this.container1.getContainerSize() +- ? this.container2.removeItem(index - this.container1.getContainerSize(), count) +- : this.container1.removeItem(index, count); ++ return index >= this.container1.getContainerSize() ? this.container2.removeItem(index - this.container1.getContainerSize(), count) : this.container1.removeItem(index, count); + } + + @Override + public ItemStack removeItemNoUpdate(int index) { +- return index >= this.container1.getContainerSize() +- ? this.container2.removeItemNoUpdate(index - this.container1.getContainerSize()) +- : this.container1.removeItemNoUpdate(index); ++ return index >= this.container1.getContainerSize() ? this.container2.removeItemNoUpdate(index - this.container1.getContainerSize()) : this.container1.removeItemNoUpdate(index); + } + + @Override +@@ -54,11 +100,12 @@ + } else { + this.container1.setItem(index, stack); + } ++ + } + + @Override + public int getMaxStackSize() { +- return this.container1.getMaxStackSize(); ++ return Math.min(this.container1.getMaxStackSize(), this.container2.getMaxStackSize()); // CraftBukkit - check both sides + } + + @Override +@@ -86,9 +133,7 @@ + + @Override + public boolean canPlaceItem(int index, ItemStack stack) { +- return index >= this.container1.getContainerSize() +- ? this.container2.canPlaceItem(index - this.container1.getContainerSize(), stack) +- : this.container1.canPlaceItem(index, stack); ++ return index >= this.container1.getContainerSize() ? this.container2.canPlaceItem(index - this.container1.getContainerSize(), stack) : this.container1.canPlaceItem(index, stack); + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/Container.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/Container.java.patch new file mode 100644 index 0000000000..a1120efc62 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/Container.java.patch @@ -0,0 +1,119 @@ +--- a/net/minecraft/world/Container.java ++++ b/net/minecraft/world/Container.java +@@ -6,10 +6,15 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; ++// CraftBukkit start ++import net.minecraft.world.item.crafting.RecipeHolder; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.BlockEntity; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++// CraftBukkit end + + public interface Container extends Clearable { ++ + int LARGE_MAX_STACK_SIZE = 64; + int DEFAULT_DISTANCE_LIMIT = 8; + +@@ -25,19 +30,15 @@ + + void setItem(int slot, ItemStack stack); + +- default int getMaxStackSize() { +- return 64; +- } ++ int getMaxStackSize(); // CraftBukkit + + void setChanged(); + + boolean stillValid(Player player); + +- default void startOpen(Player player) { +- } ++ default void startOpen(Player player) {} + +- default void stopOpen(Player player) { +- } ++ default void stopOpen(Player player) {} + + default boolean canPlaceItem(int index, ItemStack stack) { + return true; +@@ -50,10 +51,11 @@ + default int countItem(Item item) { + int i = 0; + +- for (int i1 = 0; i1 < this.getContainerSize(); i1++) { +- ItemStack item1 = this.getItem(i1); +- if (item1.getItem().equals(item)) { +- i += item1.getCount(); ++ for (int j = 0; j < this.getContainerSize(); ++j) { ++ ItemStack itemstack = this.getItem(j); ++ ++ if (itemstack.getItem().equals(item)) { ++ i += itemstack.getCount(); + } + } + +@@ -61,13 +63,16 @@ + } + + default boolean hasAnyOf(Set set) { +- return this.hasAnyMatching(item -> !item.isEmpty() && set.contains(item.getItem())); ++ return this.hasAnyMatching((itemstack) -> { ++ return !itemstack.isEmpty() && set.contains(itemstack.getItem()); ++ }); + } + + default boolean hasAnyMatching(Predicate predicate) { +- for (int i = 0; i < this.getContainerSize(); i++) { +- ItemStack item = this.getItem(i); +- if (predicate.test(item)) { ++ for (int i = 0; i < this.getContainerSize(); ++i) { ++ ItemStack itemstack = this.getItem(i); ++ ++ if (predicate.test(itemstack)) { + return true; + } + } +@@ -80,11 +85,34 @@ + } + + static boolean stillValidBlockEntity(BlockEntity blockEntity, Player player, int maxDistance) { +- Level level = blockEntity.getLevel(); +- BlockPos blockPos = blockEntity.getBlockPos(); +- return level != null +- && level.getBlockEntity(blockPos) == blockEntity +- && player.distanceToSqr((double)blockPos.getX() + 0.5, (double)blockPos.getY() + 0.5, (double)blockPos.getZ() + 0.5) +- <= (double)(maxDistance * maxDistance); ++ Level world = blockEntity.getLevel(); ++ BlockPos blockposition = blockEntity.getBlockPos(); ++ ++ return world == null ? false : (world.getBlockEntity(blockposition) != blockEntity ? false : player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) <= (double) (maxDistance * maxDistance)); + } ++ ++ // CraftBukkit start ++ java.util.List getContents(); ++ ++ void onOpen(CraftHumanEntity who); ++ ++ void onClose(CraftHumanEntity who); ++ ++ java.util.List getViewers(); ++ ++ org.bukkit.inventory.InventoryHolder getOwner(); ++ ++ void setMaxStackSize(int size); ++ ++ org.bukkit.Location getLocation(); ++ ++ default RecipeHolder getCurrentRecipe() { ++ return null; ++ } ++ ++ default void setCurrentRecipe(RecipeHolder recipe) { ++ } ++ ++ int MAX_STACK = 64; ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/LockCode.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/LockCode.java.patch new file mode 100644 index 0000000000..46a119eeb5 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/LockCode.java.patch @@ -0,0 +1,52 @@ +--- a/net/minecraft/world/LockCode.java ++++ b/net/minecraft/world/LockCode.java +@@ -4,27 +4,46 @@ + import net.minecraft.nbt.CompoundTag; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.ChatColor; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++// CraftBukkit end ++ + @Immutable + public class LockCode { ++ + public static final LockCode NO_LOCK = new LockCode(""); + public static final String TAG_LOCK = "Lock"; +- private final String key; ++ public final String key; + + public LockCode(String key) { + this.key = key; + } + + public boolean unlocksWith(ItemStack stack) { +- return this.key.isEmpty() || !stack.isEmpty() && stack.hasCustomHoverName() && this.key.equals(stack.getHoverName().getString()); ++ // CraftBukkit start - SPIGOT-6307: Check for color codes if the lock contains color codes ++ if (this.key.isEmpty()) return true; ++ if (!stack.isEmpty() && stack.hasCustomHoverName()) { ++ if (this.key.indexOf(ChatColor.COLOR_CHAR) == -1) { ++ // The lock key contains no color codes, so let's ignore colors in the item display name (vanilla Minecraft behavior): ++ return this.key.equals(stack.getHoverName().getString()); ++ } else { ++ // The lock key contains color codes, so let's take them into account: ++ return this.key.equals(CraftChatMessage.fromComponent(stack.getHoverName())); ++ } ++ } ++ return false; ++ // CraftBukkit end + } + + public void addToTag(CompoundTag nbt) { + if (!this.key.isEmpty()) { + nbt.putString("Lock", this.key); + } ++ + } + + public static LockCode fromTag(CompoundTag nbt) { +- return nbt.contains("Lock", 8) ? new LockCode(nbt.getString("Lock")) : NO_LOCK; ++ return nbt.contains("Lock", 8) ? new LockCode(nbt.getString("Lock")) : LockCode.NO_LOCK; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/SimpleContainer.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/SimpleContainer.java.patch new file mode 100644 index 0000000000..788edcea8f --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/SimpleContainer.java.patch @@ -0,0 +1,365 @@ +--- a/net/minecraft/world/SimpleContainer.java ++++ b/net/minecraft/world/SimpleContainer.java +@@ -1,6 +1,7 @@ + package net.minecraft.world; + + import com.google.common.collect.Lists; ++import java.util.Iterator; + import java.util.List; + import java.util.stream.Collectors; + import javax.annotation.Nullable; +@@ -13,17 +14,76 @@ + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class SimpleContainer implements Container, StackedContentsCompatible { ++ + private final int size; +- private final NonNullList items; ++ public final NonNullList items; + @Nullable + private List listeners; + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ protected org.bukkit.inventory.InventoryHolder bukkitOwner; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return bukkitOwner; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return null; ++ } ++ ++ public SimpleContainer(SimpleContainer original) { ++ this(original.size); ++ for (int slot = 0; slot < original.size; slot++) { ++ this.items.set(slot, original.items.get(slot).copy()); ++ } ++ } ++ + public SimpleContainer(int size) { +- this.size = size; +- this.items = NonNullList.withSize(size, ItemStack.EMPTY); ++ this(size, null); + } + ++ public SimpleContainer(int i, org.bukkit.inventory.InventoryHolder owner) { ++ this.bukkitOwner = owner; ++ // CraftBukkit end ++ this.size = i; ++ this.items = NonNullList.withSize(i, ItemStack.EMPTY); ++ } ++ + public SimpleContainer(ItemStack... items) { + this.size = items.length; + this.items = NonNullList.of(ItemStack.EMPTY, items); +@@ -41,71 +101,82 @@ + if (this.listeners != null) { + this.listeners.remove(listener); + } ++ + } + + @Override + public ItemStack getItem(int index) { +- return index >= 0 && index < this.items.size() ? this.items.get(index) : ItemStack.EMPTY; ++ return index >= 0 && index < this.items.size() ? (ItemStack) this.items.get(index) : ItemStack.EMPTY; + } + + public List removeAllItems() { +- List list = this.items.stream().filter(stack -> !stack.isEmpty()).collect(Collectors.toList()); ++ List list = (List) this.items.stream().filter((itemstack) -> { ++ return !itemstack.isEmpty(); ++ }).collect(Collectors.toList()); ++ + this.clearContent(); + return list; + } + + @Override + public ItemStack removeItem(int index, int count) { +- ItemStack itemStack = ContainerHelper.removeItem(this.items, index, count); +- if (!itemStack.isEmpty()) { ++ ItemStack itemstack = ContainerHelper.removeItem(this.items, index, count); ++ ++ if (!itemstack.isEmpty()) { + this.setChanged(); + } + +- return itemStack; ++ return itemstack; + } + + public ItemStack removeItemType(Item item, int amount) { +- ItemStack itemStack = new ItemStack(item, 0); ++ ItemStack itemstack = new ItemStack(item, 0); + +- for (int i = this.size - 1; i >= 0; i--) { +- ItemStack item1 = this.getItem(i); +- if (item1.getItem().equals(item)) { +- int i1 = amount - itemStack.getCount(); +- ItemStack itemStack1 = item1.split(i1); +- itemStack.grow(itemStack1.getCount()); +- if (itemStack.getCount() == amount) { ++ for (int j = this.size - 1; j >= 0; --j) { ++ ItemStack itemstack1 = this.getItem(j); ++ ++ if (itemstack1.getItem().equals(item)) { ++ int k = amount - itemstack.getCount(); ++ ItemStack itemstack2 = itemstack1.split(k); ++ ++ itemstack.grow(itemstack2.getCount()); ++ if (itemstack.getCount() == amount) { + break; + } + } + } + +- if (!itemStack.isEmpty()) { ++ if (!itemstack.isEmpty()) { + this.setChanged(); + } + +- return itemStack; ++ return itemstack; + } + + public ItemStack addItem(ItemStack stack) { + if (stack.isEmpty()) { + return ItemStack.EMPTY; + } else { +- ItemStack itemStack = stack.copy(); +- this.moveItemToOccupiedSlotsWithSameType(itemStack); +- if (itemStack.isEmpty()) { ++ ItemStack itemstack1 = stack.copy(); ++ ++ this.moveItemToOccupiedSlotsWithSameType(itemstack1); ++ if (itemstack1.isEmpty()) { + return ItemStack.EMPTY; + } else { +- this.moveItemToEmptySlots(itemStack); +- return itemStack.isEmpty() ? ItemStack.EMPTY : itemStack; ++ this.moveItemToEmptySlots(itemstack1); ++ return itemstack1.isEmpty() ? ItemStack.EMPTY : itemstack1; + } + } + } + + public boolean canAddItem(ItemStack stack) { + boolean flag = false; ++ Iterator iterator = this.items.iterator(); + +- for (ItemStack itemStack : this.items) { +- if (itemStack.isEmpty() || ItemStack.isSameItemSameTags(itemStack, stack) && itemStack.getCount() < itemStack.getMaxStackSize()) { ++ while (iterator.hasNext()) { ++ ItemStack itemstack1 = (ItemStack) iterator.next(); ++ ++ if (itemstack1.isEmpty() || ItemStack.isSameItemSameTags(itemstack1, stack) && itemstack1.getCount() < itemstack1.getMaxStackSize()) { + flag = true; + break; + } +@@ -116,12 +187,13 @@ + + @Override + public ItemStack removeItemNoUpdate(int index) { +- ItemStack itemStack = this.items.get(index); +- if (itemStack.isEmpty()) { ++ ItemStack itemstack = (ItemStack) this.items.get(index); ++ ++ if (itemstack.isEmpty()) { + return ItemStack.EMPTY; + } else { + this.items.set(index, ItemStack.EMPTY); +- return itemStack; ++ return itemstack; + } + } + +@@ -142,22 +214,33 @@ + + @Override + public boolean isEmpty() { +- for (ItemStack itemStack : this.items) { +- if (!itemStack.isEmpty()) { +- return false; ++ Iterator iterator = this.items.iterator(); ++ ++ ItemStack itemstack; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return true; + } +- } + +- return true; ++ itemstack = (ItemStack) iterator.next(); ++ } while (itemstack.isEmpty()); ++ ++ return false; + } + + @Override + public void setChanged() { + if (this.listeners != null) { +- for (ContainerListener containerListener : this.listeners) { +- containerListener.containerChanged(this); ++ Iterator iterator = this.listeners.iterator(); ++ ++ while (iterator.hasNext()) { ++ ContainerListener iinventorylistener = (ContainerListener) iterator.next(); ++ ++ iinventorylistener.containerChanged(this); + } + } ++ + } + + @Override +@@ -173,70 +256,85 @@ + + @Override + public void fillStackedContents(StackedContents helper) { +- for (ItemStack itemStack : this.items) { +- helper.accountStack(itemStack); ++ Iterator iterator = this.items.iterator(); ++ ++ while (iterator.hasNext()) { ++ ItemStack itemstack = (ItemStack) iterator.next(); ++ ++ helper.accountStack(itemstack); + } ++ + } + +- @Override + public String toString() { +- return this.items.stream().filter(stack -> !stack.isEmpty()).collect(Collectors.toList()).toString(); ++ return ((List) this.items.stream().filter((itemstack) -> { ++ return !itemstack.isEmpty(); ++ }).collect(Collectors.toList())).toString(); + } + + private void moveItemToEmptySlots(ItemStack stack) { +- for (int i = 0; i < this.size; i++) { +- ItemStack item = this.getItem(i); +- if (item.isEmpty()) { ++ for (int i = 0; i < this.size; ++i) { ++ ItemStack itemstack1 = this.getItem(i); ++ ++ if (itemstack1.isEmpty()) { + this.setItem(i, stack.copyAndClear()); + return; + } + } ++ + } + + private void moveItemToOccupiedSlotsWithSameType(ItemStack stack) { +- for (int i = 0; i < this.size; i++) { +- ItemStack item = this.getItem(i); +- if (ItemStack.isSameItemSameTags(item, stack)) { +- this.moveItemsBetweenStacks(stack, item); ++ for (int i = 0; i < this.size; ++i) { ++ ItemStack itemstack1 = this.getItem(i); ++ ++ if (ItemStack.isSameItemSameTags(itemstack1, stack)) { ++ this.moveItemsBetweenStacks(stack, itemstack1); + if (stack.isEmpty()) { + return; + } + } + } ++ + } + + private void moveItemsBetweenStacks(ItemStack stack, ItemStack other) { +- int min = Math.min(this.getMaxStackSize(), other.getMaxStackSize()); +- int min1 = Math.min(stack.getCount(), min - other.getCount()); +- if (min1 > 0) { +- other.grow(min1); +- stack.shrink(min1); ++ int i = Math.min(this.getMaxStackSize(), other.getMaxStackSize()); ++ int j = Math.min(stack.getCount(), i - other.getCount()); ++ ++ if (j > 0) { ++ other.grow(j); ++ stack.shrink(j); + this.setChanged(); + } ++ + } + + public void fromTag(ListTag containerNbt) { + this.clearContent(); + +- for (int i = 0; i < containerNbt.size(); i++) { +- ItemStack itemStack = ItemStack.of(containerNbt.getCompound(i)); +- if (!itemStack.isEmpty()) { +- this.addItem(itemStack); ++ for (int i = 0; i < containerNbt.size(); ++i) { ++ ItemStack itemstack = ItemStack.of(containerNbt.getCompound(i)); ++ ++ if (!itemstack.isEmpty()) { ++ this.addItem(itemstack); + } + } ++ + } + + public ListTag createTag() { +- ListTag list = new ListTag(); ++ ListTag nbttaglist = new ListTag(); + +- for (int i = 0; i < this.getContainerSize(); i++) { +- ItemStack item = this.getItem(i); +- if (!item.isEmpty()) { +- list.add(item.save(new CompoundTag())); ++ for (int i = 0; i < this.getContainerSize(); ++i) { ++ ItemStack itemstack = this.getItem(i); ++ ++ if (!itemstack.isEmpty()) { ++ nbttaglist.add(itemstack.save(new CompoundTag())); + } + } + +- return list; ++ return nbttaglist; + } + + public NonNullList getItems() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/damagesource/DamageSource.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/damagesource/DamageSource.java.patch new file mode 100644 index 0000000000..131e2a4a8d --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/damagesource/DamageSource.java.patch @@ -0,0 +1,183 @@ +--- a/net/minecraft/world/damagesource/DamageSource.java ++++ b/net/minecraft/world/damagesource/DamageSource.java +@@ -12,6 +12,7 @@ + import net.minecraft.world.phys.Vec3; + + public class DamageSource { ++ + private final Holder type; + @Nullable + private final Entity causingEntity; +@@ -19,8 +20,39 @@ + private final Entity directEntity; + @Nullable + private final Vec3 damageSourcePosition; ++ // CraftBukkit start ++ private boolean sweep; ++ private boolean melting; ++ private boolean poison; + +- @Override ++ public boolean isSweep() { ++ return sweep; ++ } ++ ++ public DamageSource sweep() { ++ this.sweep = true; ++ return this; ++ } ++ ++ public boolean isMelting() { ++ return melting; ++ } ++ ++ public DamageSource melting() { ++ this.melting = true; ++ return this; ++ } ++ ++ public boolean isPoison() { ++ return poison; ++ } ++ ++ public DamageSource poison() { ++ this.poison = true; ++ return this; ++ } ++ // CraftBukkit end ++ + public String toString() { + return "DamageSource (" + this.type().msgId() + ")"; + } +@@ -41,11 +73,11 @@ + } + + public DamageSource(Holder type, @Nullable Entity directEntity, @Nullable Entity causingEntity) { +- this(type, directEntity, causingEntity, null); ++ this(type, directEntity, causingEntity, (Vec3) null); + } + + public DamageSource(Holder type, Vec3 damageSourcePosition) { +- this(type, null, null, damageSourcePosition); ++ this(type, (Entity) null, (Entity) null, damageSourcePosition); + } + + public DamageSource(Holder type, @Nullable Entity entity) { +@@ -53,7 +85,7 @@ + } + + public DamageSource(Holder type) { +- this(type, null, null, null); ++ this(type, (Entity) null, (Entity) null, (Vec3) null); + } + + @Nullable +@@ -67,19 +99,29 @@ + } + + public Component getLocalizedDeathMessage(LivingEntity livingEntity) { +- String string = "death.attack." + this.type().msgId(); ++ String s = "death.attack." + this.type().msgId(); ++ + if (this.causingEntity == null && this.directEntity == null) { +- LivingEntity killCredit = livingEntity.getKillCredit(); +- String string1 = string + ".player"; +- return killCredit != null +- ? Component.translatable(string1, livingEntity.getDisplayName(), killCredit.getDisplayName()) +- : Component.translatable(string, livingEntity.getDisplayName()); ++ LivingEntity entityliving1 = livingEntity.getKillCredit(); ++ String s1 = s + ".player"; ++ ++ return entityliving1 != null ? Component.translatable(s1, livingEntity.getDisplayName(), entityliving1.getDisplayName()) : Component.translatable(s, livingEntity.getDisplayName()); + } else { +- Component component = this.causingEntity == null ? this.directEntity.getDisplayName() : this.causingEntity.getDisplayName(); +- ItemStack itemStack = this.causingEntity instanceof LivingEntity livingEntity1 ? livingEntity1.getMainHandItem() : ItemStack.EMPTY; +- return !itemStack.isEmpty() && itemStack.hasCustomHoverName() +- ? Component.translatable(string + ".item", livingEntity.getDisplayName(), component, itemStack.getDisplayName()) +- : Component.translatable(string, livingEntity.getDisplayName(), component); ++ Component ichatbasecomponent = this.causingEntity == null ? this.directEntity.getDisplayName() : this.causingEntity.getDisplayName(); ++ Entity entity = this.causingEntity; ++ ItemStack itemstack; ++ ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving2 = (LivingEntity) entity; ++ ++ itemstack = entityliving2.getMainHandItem(); ++ } else { ++ itemstack = ItemStack.EMPTY; ++ } ++ ++ ItemStack itemstack1 = itemstack; ++ ++ return !itemstack1.isEmpty() && itemstack1.hasCustomHoverName() ? Component.translatable(s + ".item", livingEntity.getDisplayName(), ichatbasecomponent, itemstack1.getDisplayName()) : Component.translatable(s, livingEntity.getDisplayName(), ichatbasecomponent); + } + } + +@@ -88,28 +130,45 @@ + } + + public boolean scalesWithDifficulty() { +- return switch (this.type().scaling()) { +- case NEVER -> false; +- case WHEN_CAUSED_BY_LIVING_NON_PLAYER -> this.causingEntity instanceof LivingEntity && !(this.causingEntity instanceof Player); +- case ALWAYS -> true; +- }; ++ boolean flag; ++ ++ switch (this.type().scaling()) { ++ case NEVER: ++ flag = false; ++ break; ++ case WHEN_CAUSED_BY_LIVING_NON_PLAYER: ++ flag = this.causingEntity instanceof LivingEntity && !(this.causingEntity instanceof Player); ++ break; ++ case ALWAYS: ++ flag = true; ++ break; ++ default: ++ throw new IncompatibleClassChangeError(); ++ } ++ ++ return flag; + } + + public boolean isCreativePlayer() { +- if (this.getEntity() instanceof Player player && player.getAbilities().instabuild) { +- return true; ++ Entity entity = this.getEntity(); ++ boolean flag; ++ ++ if (entity instanceof Player) { ++ Player entityhuman = (Player) entity; ++ ++ if (entityhuman.getAbilities().instabuild) { ++ flag = true; ++ return flag; ++ } + } + +- return false; ++ flag = false; ++ return flag; + } + + @Nullable + public Vec3 getSourcePosition() { +- if (this.damageSourcePosition != null) { +- return this.damageSourcePosition; +- } else { +- return this.directEntity != null ? this.directEntity.position() : null; +- } ++ return this.damageSourcePosition != null ? this.damageSourcePosition : (this.directEntity != null ? this.directEntity.position() : null); + } + + @Nullable +@@ -126,7 +185,7 @@ + } + + public DamageType type() { +- return this.type.value(); ++ return (DamageType) this.type.value(); + } + + public Holder typeHolder() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/damagesource/DamageSources.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/damagesource/DamageSources.java.patch new file mode 100644 index 0000000000..bfcf24b00e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/damagesource/DamageSources.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/damagesource/DamageSources.java ++++ b/net/minecraft/world/damagesource/DamageSources.java +@@ -16,6 +16,7 @@ + import net.minecraft.world.phys.Vec3; + + public class DamageSources { ++ + private final Registry damageTypes; + private final DamageSource inFire; + private final DamageSource lightningBolt; +@@ -40,9 +41,15 @@ + private final DamageSource stalagmite; + private final DamageSource outsideBorder; + private final DamageSource genericKill; ++ // CraftBukkit start ++ public final DamageSource melting; ++ public final DamageSource poison; + + public DamageSources(RegistryAccess registry) { + this.damageTypes = registry.registryOrThrow(Registries.DAMAGE_TYPE); ++ this.melting = this.source(DamageTypes.ON_FIRE).melting(); ++ this.poison = this.source(DamageTypes.MAGIC).poison(); ++ // CraftBukkit end + this.inFire = this.source(DamageTypes.IN_FIRE); + this.lightningBolt = this.source(DamageTypes.LIGHTNING_BOLT); + this.onFire = this.source(DamageTypes.ON_FIRE); +@@ -229,7 +236,7 @@ + } + + public DamageSource explosion(@Nullable Explosion explosion) { +- return explosion != null ? this.explosion(explosion.getDirectSourceEntity(), explosion.getIndirectSourceEntity()) : this.explosion(null, null); ++ return explosion != null ? this.explosion(explosion.getDirectSourceEntity(), explosion.getIndirectSourceEntity()) : this.explosion((Entity) null, (Entity) null); + } + + public DamageSource explosion(@Nullable Entity causingEntity, @Nullable Entity directEntity) { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/effect/HealOrHarmMobEffect.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/effect/HealOrHarmMobEffect.java.patch new file mode 100644 index 0000000000..b8c1a1f2d2 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/effect/HealOrHarmMobEffect.java.patch @@ -0,0 +1,52 @@ +--- a/net/minecraft/world/effect/HealOrHarmMobEffect.java ++++ b/net/minecraft/world/effect/HealOrHarmMobEffect.java +@@ -5,10 +5,11 @@ + import net.minecraft.world.entity.LivingEntity; + + class HealOrHarmMobEffect extends InstantenousMobEffect { ++ + private final boolean isHarm; + +- public HealOrHarmMobEffect(MobEffectCategory category, int color, boolean flag) { +- super(category, color); ++ public HealOrHarmMobEffect(MobEffectCategory mobeffectinfo, int i, boolean flag) { ++ super(mobeffectinfo, i); + this.isHarm = flag; + } + +@@ -16,24 +17,28 @@ + public void applyEffectTick(LivingEntity livingEntity, int amplifier) { + super.applyEffectTick(livingEntity, amplifier); + if (this.isHarm == livingEntity.isInvertedHealAndHarm()) { +- livingEntity.heal((float)Math.max(4 << amplifier, 0)); ++ livingEntity.heal((float) Math.max(4 << amplifier, 0), org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.MAGIC); // CraftBukkit + } else { +- livingEntity.hurt(livingEntity.damageSources().magic(), (float)(6 << amplifier)); ++ livingEntity.hurt(livingEntity.damageSources().magic(), (float) (6 << amplifier)); + } ++ + } + + @Override + public void applyInstantenousEffect(@Nullable Entity source, @Nullable Entity indirectSource, LivingEntity livingEntity, int amplifier, double health) { ++ int j; ++ + if (this.isHarm == livingEntity.isInvertedHealAndHarm()) { +- int i = (int)(health * (double)(4 << amplifier) + 0.5); +- livingEntity.heal((float)i); ++ j = (int) (health * (double) (4 << amplifier) + 0.5D); ++ livingEntity.heal((float) j, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.MAGIC); // CraftBukkit + } else { +- int i = (int)(health * (double)(6 << amplifier) + 0.5); ++ j = (int) (health * (double) (6 << amplifier) + 0.5D); + if (source == null) { +- livingEntity.hurt(livingEntity.damageSources().magic(), (float)i); ++ livingEntity.hurt(livingEntity.damageSources().magic(), (float) j); + } else { +- livingEntity.hurt(livingEntity.damageSources().indirectMagic(source, indirectSource), (float)i); ++ livingEntity.hurt(livingEntity.damageSources().indirectMagic(source, indirectSource), (float) j); + } + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/effect/HungerMobEffect.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/effect/HungerMobEffect.java.patch new file mode 100644 index 0000000000..7876e12e8c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/effect/HungerMobEffect.java.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/effect/HungerMobEffect.java ++++ b/net/minecraft/world/effect/HungerMobEffect.java +@@ -4,6 +4,7 @@ + import net.minecraft.world.entity.player.Player; + + class HungerMobEffect extends MobEffect { ++ + protected HungerMobEffect(MobEffectCategory category, int color) { + super(category, color); + } +@@ -11,13 +12,16 @@ + @Override + public void applyEffectTick(LivingEntity livingEntity, int amplifier) { + super.applyEffectTick(livingEntity, amplifier); +- if (livingEntity instanceof Player player) { +- player.causeFoodExhaustion(0.005F * (float)(amplifier + 1)); ++ if (livingEntity instanceof Player) { ++ Player entityhuman = (Player) livingEntity; ++ ++ entityhuman.causeFoodExhaustion(0.005F * (float) (amplifier + 1), org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.HUNGER_EFFECT); // CraftBukkit - EntityExhaustionEvent + } ++ + } + + @Override +- public boolean shouldApplyEffectTickThisTick(int i, int i1) { ++ public boolean shouldApplyEffectTickThisTick(int i, int j) { + return true; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/effect/MobEffectUtil.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/effect/MobEffectUtil.java.patch new file mode 100644 index 0000000000..29abdb70a3 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/effect/MobEffectUtil.java.patch @@ -0,0 +1,81 @@ +--- a/net/minecraft/world/effect/MobEffectUtil.java ++++ b/net/minecraft/world/effect/MobEffectUtil.java +@@ -12,12 +12,16 @@ + import net.minecraft.world.phys.Vec3; + + public final class MobEffectUtil { +- public static Component formatDuration(MobEffectInstance mobEffectInstance, float f, float f1) { +- if (mobEffectInstance.isInfiniteDuration()) { ++ ++ public MobEffectUtil() {} ++ ++ public static Component formatDuration(MobEffectInstance mobeffect, float f, float f1) { ++ if (mobeffect.isInfiniteDuration()) { + return Component.translatable("effect.duration.infinite"); + } else { +- int floor = Mth.floor((float)mobEffectInstance.getDuration() * f); +- return Component.literal(StringUtil.formatTickDuration(floor, f1)); ++ int i = Mth.floor((float) mobeffect.getDuration() * f); ++ ++ return Component.literal(StringUtil.formatTickDuration(i, f1)); + } + } + +@@ -27,37 +31,38 @@ + + public static int getDigSpeedAmplification(LivingEntity entity) { + int i = 0; +- int i1 = 0; ++ int j = 0; ++ + if (entity.hasEffect(MobEffects.DIG_SPEED)) { + i = entity.getEffect(MobEffects.DIG_SPEED).getAmplifier(); + } + + if (entity.hasEffect(MobEffects.CONDUIT_POWER)) { +- i1 = entity.getEffect(MobEffects.CONDUIT_POWER).getAmplifier(); ++ j = entity.getEffect(MobEffects.CONDUIT_POWER).getAmplifier(); + } + +- return Math.max(i, i1); ++ return Math.max(i, j); + } + + public static boolean hasWaterBreathing(LivingEntity entity) { + return entity.hasEffect(MobEffects.WATER_BREATHING) || entity.hasEffect(MobEffects.CONDUIT_POWER); + } + +- public static List addEffectToPlayersAround( +- ServerLevel level, @Nullable Entity source, Vec3 pos, double radius, MobEffectInstance effect, int duration +- ) { +- MobEffect effect1 = effect.getEffect(); +- List players = level.getPlayers( +- serverPlayer -> serverPlayer.gameMode.isSurvival() +- && (source == null || !source.isAlliedTo(serverPlayer)) +- && pos.closerThan(serverPlayer.position(), radius) +- && ( +- !serverPlayer.hasEffect(effect1) +- || serverPlayer.getEffect(effect1).getAmplifier() < effect.getAmplifier() +- || serverPlayer.getEffect(effect1).endsWithin(duration - 1) +- ) +- ); +- players.forEach(serverPlayer -> serverPlayer.addEffect(new MobEffectInstance(effect), source)); +- return players; ++ public static List addEffectToPlayersAround(ServerLevel level, @Nullable Entity source, Vec3 pos, double radius, MobEffectInstance mobeffect, int effect) { ++ // CraftBukkit start ++ return addEffectToPlayersAround(level, source, pos, radius, mobeffect, effect, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); + } ++ ++ public static List addEffectToPlayersAround(ServerLevel worldserver, @Nullable Entity entity, Vec3 vec3d, double d0, MobEffectInstance mobeffect, int i, org.bukkit.event.entity.EntityPotionEffectEvent.Cause cause) { ++ // CraftBukkit end ++ MobEffect mobeffectlist = mobeffect.getEffect(); ++ List list = worldserver.getPlayers((entityplayer) -> { ++ return entityplayer.gameMode.isSurvival() && (entity == null || !entity.isAlliedTo((Entity) entityplayer)) && vec3d.closerThan(entityplayer.position(), d0) && (!entityplayer.hasEffect(mobeffectlist) || entityplayer.getEffect(mobeffectlist).getAmplifier() < mobeffect.getAmplifier() || entityplayer.getEffect(mobeffectlist).endsWithin(i - 1)); ++ }); ++ ++ list.forEach((entityplayer) -> { ++ entityplayer.addEffect(new MobEffectInstance(mobeffect), entity, cause); // CraftBukkit ++ }); ++ return list; ++ } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/effect/PoisonMobEffect.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/effect/PoisonMobEffect.java.patch new file mode 100644 index 0000000000..ad997537d9 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/effect/PoisonMobEffect.java.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/effect/PoisonMobEffect.java ++++ b/net/minecraft/world/effect/PoisonMobEffect.java +@@ -3,6 +3,7 @@ + import net.minecraft.world.entity.LivingEntity; + + class PoisonMobEffect extends MobEffect { ++ + protected PoisonMobEffect(MobEffectCategory category, int color) { + super(category, color); + } +@@ -11,13 +12,15 @@ + public void applyEffectTick(LivingEntity livingEntity, int amplifier) { + super.applyEffectTick(livingEntity, amplifier); + if (livingEntity.getHealth() > 1.0F) { +- livingEntity.hurt(livingEntity.damageSources().magic(), 1.0F); ++ livingEntity.hurt(livingEntity.damageSources().poison, 1.0F); // CraftBukkit - DamageSource.MAGIC -> CraftEventFactory.POISON + } ++ + } + + @Override +- public boolean shouldApplyEffectTickThisTick(int i, int i1) { +- int i2 = 25 >> i1; +- return i2 <= 0 || i % i2 == 0; ++ public boolean shouldApplyEffectTickThisTick(int i, int j) { ++ int k = 25 >> j; ++ ++ return k > 0 ? i % k == 0 : true; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/effect/RegenerationMobEffect.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/effect/RegenerationMobEffect.java.patch new file mode 100644 index 0000000000..564cd4fa0f --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/effect/RegenerationMobEffect.java.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/effect/RegenerationMobEffect.java ++++ b/net/minecraft/world/effect/RegenerationMobEffect.java +@@ -3,6 +3,7 @@ + import net.minecraft.world.entity.LivingEntity; + + class RegenerationMobEffect extends MobEffect { ++ + protected RegenerationMobEffect(MobEffectCategory category, int color) { + super(category, color); + } +@@ -11,13 +12,15 @@ + public void applyEffectTick(LivingEntity livingEntity, int amplifier) { + super.applyEffectTick(livingEntity, amplifier); + if (livingEntity.getHealth() < livingEntity.getMaxHealth()) { +- livingEntity.heal(1.0F); ++ livingEntity.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.MAGIC_REGEN); // CraftBukkit + } ++ + } + + @Override +- public boolean shouldApplyEffectTickThisTick(int i, int i1) { +- int i2 = 50 >> i1; +- return i2 <= 0 || i % i2 == 0; ++ public boolean shouldApplyEffectTickThisTick(int i, int j) { ++ int k = 50 >> j; ++ ++ return k > 0 ? i % k == 0 : true; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/effect/SaturationMobEffect.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/effect/SaturationMobEffect.java.patch new file mode 100644 index 0000000000..d7d8d14345 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/effect/SaturationMobEffect.java.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/world/effect/SaturationMobEffect.java ++++ b/net/minecraft/world/effect/SaturationMobEffect.java +@@ -2,8 +2,13 @@ + + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.player.Player; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + class SaturationMobEffect extends InstantenousMobEffect { ++ + protected SaturationMobEffect(MobEffectCategory category, int color) { + super(category, color); + } +@@ -11,8 +16,19 @@ + @Override + public void applyEffectTick(LivingEntity livingEntity, int amplifier) { + super.applyEffectTick(livingEntity, amplifier); +- if (!livingEntity.level().isClientSide && livingEntity instanceof Player player) { +- player.getFoodData().eat(amplifier + 1, 1.0F); ++ if (!livingEntity.level().isClientSide && livingEntity instanceof Player) { ++ Player entityhuman = (Player) livingEntity; ++ ++ // CraftBukkit start ++ int oldFoodLevel = entityhuman.getFoodData().foodLevel; ++ org.bukkit.event.entity.FoodLevelChangeEvent event = CraftEventFactory.callFoodLevelChangeEvent(entityhuman, amplifier + 1 + oldFoodLevel); ++ if (!event.isCancelled()) { ++ entityhuman.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, 1.0F); ++ } ++ ++ ((CraftPlayer) entityhuman.getBukkitEntity()).sendHealthUpdate(); ++ // CraftBukkit end + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/AgeableMob.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/AgeableMob.java.patch new file mode 100644 index 0000000000..2251d746cd --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/AgeableMob.java.patch @@ -0,0 +1,213 @@ +--- a/net/minecraft/world/entity/AgeableMob.java ++++ b/net/minecraft/world/entity/AgeableMob.java +@@ -13,34 +13,33 @@ + import net.minecraft.world.level.ServerLevelAccessor; + + public abstract class AgeableMob extends PathfinderMob { ++ + private static final EntityDataAccessor DATA_BABY_ID = SynchedEntityData.defineId(AgeableMob.class, EntityDataSerializers.BOOLEAN); + public static final int BABY_START_AGE = -24000; + private static final int FORCED_AGE_PARTICLE_TICKS = 40; + protected int age; + protected int forcedAge; + protected int forcedAgeTimer; ++ public boolean ageLocked; // CraftBukkit + + protected AgeableMob(EntityType entityType, Level level) { + super(entityType, level); + } + + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + if (spawnData == null) { + spawnData = new AgeableMob.AgeableMobGroupData(true); + } + +- AgeableMob.AgeableMobGroupData ageableMobGroupData = (AgeableMob.AgeableMobGroupData)spawnData; +- if (ageableMobGroupData.isShouldSpawnBaby() +- && ageableMobGroupData.getGroupSize() > 0 +- && level.getRandom().nextFloat() <= ageableMobGroupData.getBabySpawnChance()) { ++ AgeableMob.AgeableMobGroupData entityageable_a = (AgeableMob.AgeableMobGroupData) spawnData; ++ ++ if (entityageable_a.isShouldSpawnBaby() && entityageable_a.getGroupSize() > 0 && level.getRandom().nextFloat() <= entityageable_a.getBabySpawnChance()) { + this.setAge(-24000); + } + +- ageableMobGroupData.increaseGroupSizeByOne(); +- return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ entityageable_a.increaseGroupSizeByOne(); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + + @Nullable +@@ -49,7 +48,7 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_BABY_ID, false); ++ this.entityData.define(AgeableMob.DATA_BABY_ID, false); + } + + public boolean canBreed() { +@@ -57,24 +56,23 @@ + } + + public int getAge() { +- if (this.level().isClientSide) { +- return this.entityData.get(DATA_BABY_ID) ? -1 : 1; +- } else { +- return this.age; +- } ++ return this.level().isClientSide ? ((Boolean) this.entityData.get(AgeableMob.DATA_BABY_ID) ? -1 : 1) : this.age; + } + + public void ageUp(int amount, boolean forced) { +- int age = this.getAge(); +- int var6 = age + amount * 20; +- if (var6 > 0) { +- var6 = 0; ++ int j = this.getAge(); ++ int k = j; ++ ++ j += amount * 20; ++ if (j > 0) { ++ j = 0; + } + +- int i1 = var6 - age; +- this.setAge(var6); ++ int l = j - k; ++ ++ this.setAge(j); + if (forced) { +- this.forcedAge += i1; ++ this.forcedAge += l; + if (this.forcedAgeTimer == 0) { + this.forcedAgeTimer = 40; + } +@@ -83,6 +81,7 @@ + if (this.getAge() == 0) { + this.setAge(this.forcedAge); + } ++ + } + + public void ageUp(int amount) { +@@ -90,12 +89,14 @@ + } + + public void setAge(int age) { +- int age1 = this.getAge(); ++ int j = this.getAge(); ++ + this.age = age; +- if (age1 < 0 && age >= 0 || age1 >= 0 && age < 0) { +- this.entityData.set(DATA_BABY_ID, age < 0); ++ if (j < 0 && age >= 0 || j >= 0 && age < 0) { ++ this.entityData.set(AgeableMob.DATA_BABY_ID, age < 0); + this.ageBoundaryReached(); + } ++ + } + + @Override +@@ -103,6 +104,7 @@ + super.addAdditionalSaveData(compound); + compound.putInt("Age", this.getAge()); + compound.putInt("ForcedAge", this.forcedAge); ++ compound.putBoolean("AgeLocked", this.ageLocked); // CraftBukkit + } + + @Override +@@ -110,11 +112,12 @@ + super.readAdditionalSaveData(compound); + this.setAge(compound.getInt("Age")); + this.forcedAge = compound.getInt("ForcedAge"); ++ this.ageLocked = compound.getBoolean("AgeLocked"); // CraftBukkit + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { +- if (DATA_BABY_ID.equals(key)) { ++ if (AgeableMob.DATA_BABY_ID.equals(key)) { + this.refreshDimensions(); + } + +@@ -124,28 +127,41 @@ + @Override + public void aiStep() { + super.aiStep(); +- if (this.level().isClientSide) { ++ if (this.level().isClientSide || ageLocked) { // CraftBukkit + if (this.forcedAgeTimer > 0) { + if (this.forcedAgeTimer % 4 == 0) { +- this.level().addParticle(ParticleTypes.HAPPY_VILLAGER, this.getRandomX(1.0), this.getRandomY() + 0.5, this.getRandomZ(1.0), 0.0, 0.0, 0.0); ++ this.level().addParticle(ParticleTypes.HAPPY_VILLAGER, this.getRandomX(1.0D), this.getRandomY() + 0.5D, this.getRandomZ(1.0D), 0.0D, 0.0D, 0.0D); + } + +- this.forcedAgeTimer--; ++ --this.forcedAgeTimer; + } + } else if (this.isAlive()) { +- int age = this.getAge(); +- if (age < 0) { +- this.setAge(++age); +- } else if (age > 0) { +- this.setAge(--age); ++ int i = this.getAge(); ++ ++ if (i < 0) { ++ ++i; ++ this.setAge(i); ++ } else if (i > 0) { ++ --i; ++ this.setAge(i); + } + } ++ + } + + protected void ageBoundaryReached() { +- if (!this.isBaby() && this.isPassenger() && this.getVehicle() instanceof Boat boat && !boat.hasEnoughSpaceFor(this)) { +- this.stopRiding(); ++ if (!this.isBaby() && this.isPassenger()) { ++ Entity entity = this.getVehicle(); ++ ++ if (entity instanceof Boat) { ++ Boat entityboat = (Boat) entity; ++ ++ if (!entityboat.hasEnoughSpaceFor(this)) { ++ this.stopRiding(); ++ } ++ } + } ++ + } + + @Override +@@ -159,10 +175,11 @@ + } + + public static int getSpeedUpSecondsWhenFeeding(int ticksUntilAdult) { +- return (int)((float)(ticksUntilAdult / 20) * 0.1F); ++ return (int) ((float) (ticksUntilAdult / 20) * 0.1F); + } + +- public static class AgeableMobGroupData implements SpawnGroupData { ++ public static class AgeableMobGroupData implements GroupDataEntity { ++ + private int groupSize; + private final boolean shouldSpawnBaby; + private final float babySpawnChance; +@@ -185,7 +202,7 @@ + } + + public void increaseGroupSizeByOne() { +- this.groupSize++; ++ ++this.groupSize; + } + + public boolean isShouldSpawnBaby() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/AreaEffectCloud.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/AreaEffectCloud.java.patch new file mode 100644 index 0000000000..5313efa7c3 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/AreaEffectCloud.java.patch @@ -0,0 +1,512 @@ +--- a/net/minecraft/world/entity/AreaEffectCloud.java ++++ b/net/minecraft/world/entity/AreaEffectCloud.java +@@ -5,12 +5,14 @@ + import com.mojang.brigadier.StringReader; + import com.mojang.brigadier.exceptions.CommandSyntaxException; + import com.mojang.logging.LogUtils; ++import java.util.Collection; ++import java.util.Iterator; + import java.util.List; + import java.util.Map; + import java.util.UUID; +-import java.util.Map.Entry; + import javax.annotation.Nullable; + import net.minecraft.commands.arguments.ParticleArgument; ++import net.minecraft.core.HolderLookup; + import net.minecraft.core.particles.ParticleOptions; + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.core.registries.BuiltInRegistries; +@@ -26,10 +28,14 @@ + import net.minecraft.world.item.alchemy.PotionUtils; + import net.minecraft.world.item.alchemy.Potions; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.material.PushReaction; ++import net.minecraft.world.level.material.EnumPistonReaction; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.entity.LivingEntity; ++// CraftBukkit end + + public class AreaEffectCloud extends Entity implements TraceableEntity { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int TIME_BETWEEN_APPLICATIONS = 5; + private static final EntityDataAccessor DATA_RADIUS = SynchedEntityData.defineId(AreaEffectCloud.class, EntityDataSerializers.FLOAT); +@@ -42,56 +48,64 @@ + public static final float DEFAULT_WIDTH = 6.0F; + public static final float HEIGHT = 0.5F; + private static final String TAG_EFFECTS = "effects"; +- private Potion potion = Potions.EMPTY; +- private final List effects = Lists.newArrayList(); +- private final Map victims = Maps.newHashMap(); +- private int duration = 600; +- private int waitTime = 20; +- private int reapplicationDelay = 20; ++ public Potion potion; ++ public List effects; ++ private final Map victims; ++ private int duration; ++ public int waitTime; ++ public int reapplicationDelay; + private boolean fixedColor; +- private int durationOnUse; +- private float radiusOnUse; +- private float radiusPerTick; ++ public int durationOnUse; ++ public float radiusOnUse; ++ public float radiusPerTick; + @Nullable +- private LivingEntity owner; ++ private net.minecraft.world.entity.LivingEntity owner; + @Nullable + private UUID ownerUUID; + + public AreaEffectCloud(EntityType entityType, Level level) { + super(entityType, level); ++ this.potion = Potions.EMPTY; ++ this.effects = Lists.newArrayList(); ++ this.victims = Maps.newHashMap(); ++ this.duration = 600; ++ this.waitTime = 20; ++ this.reapplicationDelay = 20; + this.noPhysics = true; + } + +- public AreaEffectCloud(Level level, double x, double y, double z) { ++ public AreaEffectCloud(Level level, double x, double d1, double y) { + this(EntityType.AREA_EFFECT_CLOUD, level); +- this.setPos(x, y, z); ++ this.setPos(x, d1, y); + } + + @Override + protected void defineSynchedData() { +- this.getEntityData().define(DATA_COLOR, 0); +- this.getEntityData().define(DATA_RADIUS, 3.0F); +- this.getEntityData().define(DATA_WAITING, false); +- this.getEntityData().define(DATA_PARTICLE, ParticleTypes.ENTITY_EFFECT); ++ this.getEntityData().define(AreaEffectCloud.DATA_COLOR, 0); ++ this.getEntityData().define(AreaEffectCloud.DATA_RADIUS, 3.0F); ++ this.getEntityData().define(AreaEffectCloud.DATA_WAITING, false); ++ this.getEntityData().define(AreaEffectCloud.DATA_PARTICLE, ParticleTypes.ENTITY_EFFECT); + } + + public void setRadius(float radius) { + if (!this.level().isClientSide) { +- this.getEntityData().set(DATA_RADIUS, Mth.clamp(radius, 0.0F, 32.0F)); ++ this.getEntityData().set(AreaEffectCloud.DATA_RADIUS, Mth.clamp(radius, 0.0F, 32.0F)); + } ++ + } + + @Override + public void refreshDimensions() { +- double x = this.getX(); +- double y = this.getY(); +- double z = this.getZ(); ++ double d0 = this.getX(); ++ double d1 = this.getY(); ++ double d2 = this.getZ(); ++ + super.refreshDimensions(); +- this.setPos(x, y, z); ++ this.setPos(d0, d1, d2); + } + + public float getRadius() { +- return this.getEntityData().get(DATA_RADIUS); ++ return (Float) this.getEntityData().get(AreaEffectCloud.DATA_RADIUS); + } + + public void setPotion(Potion potion) { +@@ -99,14 +113,16 @@ + if (!this.fixedColor) { + this.updateColor(); + } ++ + } + +- private void updateColor() { ++ public void updateColor() { + if (this.potion == Potions.EMPTY && this.effects.isEmpty()) { +- this.getEntityData().set(DATA_COLOR, 0); ++ this.getEntityData().set(AreaEffectCloud.DATA_COLOR, 0); + } else { +- this.getEntityData().set(DATA_COLOR, PotionUtils.getColor(PotionUtils.getAllEffects(this.potion, this.effects))); ++ this.getEntityData().set(AreaEffectCloud.DATA_COLOR, PotionUtils.getColor((Collection) PotionUtils.getAllEffects(this.potion, this.effects))); + } ++ + } + + public void addEffect(MobEffectInstance effectInstance) { +@@ -114,31 +130,32 @@ + if (!this.fixedColor) { + this.updateColor(); + } ++ + } + + public int getColor() { +- return this.getEntityData().get(DATA_COLOR); ++ return (Integer) this.getEntityData().get(AreaEffectCloud.DATA_COLOR); + } + + public void setFixedColor(int color) { + this.fixedColor = true; +- this.getEntityData().set(DATA_COLOR, color); ++ this.getEntityData().set(AreaEffectCloud.DATA_COLOR, color); + } + + public ParticleOptions getParticle() { +- return this.getEntityData().get(DATA_PARTICLE); ++ return (ParticleOptions) this.getEntityData().get(AreaEffectCloud.DATA_PARTICLE); + } + + public void setParticle(ParticleOptions particleOption) { +- this.getEntityData().set(DATA_PARTICLE, particleOption); ++ this.getEntityData().set(AreaEffectCloud.DATA_PARTICLE, particleOption); + } + + protected void setWaiting(boolean waiting) { +- this.getEntityData().set(DATA_WAITING, waiting); ++ this.getEntityData().set(AreaEffectCloud.DATA_WAITING, waiting); + } + + public boolean isWaiting() { +- return this.getEntityData().get(DATA_WAITING); ++ return (Boolean) this.getEntityData().get(AreaEffectCloud.DATA_WAITING); + } + + public int getDuration() { +@@ -152,49 +169,53 @@ + @Override + public void tick() { + super.tick(); +- boolean isWaiting = this.isWaiting(); +- float radius = this.getRadius(); ++ boolean flag = this.isWaiting(); ++ float f = this.getRadius(); ++ + if (this.level().isClientSide) { +- if (isWaiting && this.random.nextBoolean()) { ++ if (flag && this.random.nextBoolean()) { + return; + } + +- ParticleOptions particle = this.getParticle(); ++ ParticleOptions particleparam = this.getParticle(); + int i; +- float f; +- if (isWaiting) { ++ float f1; ++ ++ if (flag) { + i = 2; +- f = 0.2F; ++ f1 = 0.2F; + } else { +- i = Mth.ceil((float) Math.PI * radius * radius); +- f = radius; ++ i = Mth.ceil(3.1415927F * f * f); ++ f1 = f; + } + +- for (int i1 = 0; i1 < i; i1++) { +- float f1 = this.random.nextFloat() * (float) (Math.PI * 2); +- float f2 = Mth.sqrt(this.random.nextFloat()) * f; +- double d = this.getX() + (double)(Mth.cos(f1) * f2); +- double y = this.getY(); +- double d1 = this.getZ() + (double)(Mth.sin(f1) * f2); +- double d2; ++ for (int j = 0; j < i; ++j) { ++ float f2 = this.random.nextFloat() * 6.2831855F; ++ float f3 = Mth.sqrt(this.random.nextFloat()) * f1; ++ double d0 = this.getX() + (double) (Mth.cos(f2) * f3); ++ double d1 = this.getY(); ++ double d2 = this.getZ() + (double) (Mth.sin(f2) * f3); + double d3; + double d4; +- if (particle.getType() == ParticleTypes.ENTITY_EFFECT) { +- int i2 = isWaiting && this.random.nextBoolean() ? 16777215 : this.getColor(); +- d2 = (double)((float)(i2 >> 16 & 0xFF) / 255.0F); +- d3 = (double)((float)(i2 >> 8 & 0xFF) / 255.0F); +- d4 = (double)((float)(i2 & 0xFF) / 255.0F); +- } else if (isWaiting) { +- d2 = 0.0; +- d3 = 0.0; +- d4 = 0.0; ++ double d5; ++ ++ if (particleparam.getType() == ParticleTypes.ENTITY_EFFECT) { ++ int k = flag && this.random.nextBoolean() ? 16777215 : this.getColor(); ++ ++ d3 = (double) ((float) (k >> 16 & 255) / 255.0F); ++ d4 = (double) ((float) (k >> 8 & 255) / 255.0F); ++ d5 = (double) ((float) (k & 255) / 255.0F); ++ } else if (flag) { ++ d3 = 0.0D; ++ d4 = 0.0D; ++ d5 = 0.0D; + } else { +- d2 = (0.5 - this.random.nextDouble()) * 0.15; +- d3 = 0.01F; +- d4 = (0.5 - this.random.nextDouble()) * 0.15; ++ d3 = (0.5D - this.random.nextDouble()) * 0.15D; ++ d4 = 0.009999999776482582D; ++ d5 = (0.5D - this.random.nextDouble()) * 0.15D; + } + +- this.level().addAlwaysVisibleParticle(particle, d, y, d1, d2, d3, d4); ++ this.level().addAlwaysVisibleParticle(particleparam, d0, d1, d2, d3, d4, d5); + } + } else { + if (this.tickCount >= this.waitTime + this.duration) { +@@ -202,76 +223,96 @@ + return; + } + +- boolean flag = this.tickCount < this.waitTime; +- if (isWaiting != flag) { +- this.setWaiting(flag); ++ boolean flag1 = this.tickCount < this.waitTime; ++ ++ if (flag != flag1) { ++ this.setWaiting(flag1); + } + +- if (flag) { ++ if (flag1) { + return; + } + + if (this.radiusPerTick != 0.0F) { +- radius += this.radiusPerTick; +- if (radius < 0.5F) { ++ f += this.radiusPerTick; ++ if (f < 0.5F) { + this.discard(); + return; + } + +- this.setRadius(radius); ++ this.setRadius(f); + } + + if (this.tickCount % 5 == 0) { +- this.victims.entrySet().removeIf(victim -> this.tickCount >= victim.getValue()); ++ this.victims.entrySet().removeIf((entry) -> { ++ return this.tickCount >= (Integer) entry.getValue(); ++ }); + List list = Lists.newArrayList(); ++ Iterator iterator = this.potion.getEffects().iterator(); + +- for (MobEffectInstance mobEffectInstance : this.potion.getEffects()) { +- list.add( +- new MobEffectInstance( +- mobEffectInstance.getEffect(), +- mobEffectInstance.mapDuration(i3 -> i3 / 4), +- mobEffectInstance.getAmplifier(), +- mobEffectInstance.isAmbient(), +- mobEffectInstance.isVisible() +- ) +- ); ++ while (iterator.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); ++ ++ list.add(new MobEffectInstance(mobeffect.getEffect(), mobeffect.mapDuration((l) -> { ++ return l / 4; ++ }), mobeffect.getAmplifier(), mobeffect.isAmbient(), mobeffect.isVisible())); + } + + list.addAll(this.effects); + if (list.isEmpty()) { + this.victims.clear(); + } else { +- List entitiesOfClass = this.level().getEntitiesOfClass(LivingEntity.class, this.getBoundingBox()); +- if (!entitiesOfClass.isEmpty()) { +- for (LivingEntity livingEntity : entitiesOfClass) { +- if (!this.victims.containsKey(livingEntity) && livingEntity.isAffectedByPotions()) { +- double d5 = livingEntity.getX() - this.getX(); +- double d6 = livingEntity.getZ() - this.getZ(); +- double d7 = d5 * d5 + d6 * d6; +- if (d7 <= (double)(radius * radius)) { +- this.victims.put(livingEntity, this.tickCount + this.reapplicationDelay); ++ List list1 = this.level().getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, this.getBoundingBox()); + +- for (MobEffectInstance mobEffectInstance1 : list) { +- if (mobEffectInstance1.getEffect().isInstantenous()) { +- mobEffectInstance1.getEffect() +- .applyInstantenousEffect(this, this.getOwner(), livingEntity, mobEffectInstance1.getAmplifier(), 0.5); ++ if (!list1.isEmpty()) { ++ Iterator iterator1 = list1.iterator(); ++ ++ List entities = new java.util.ArrayList(); // CraftBukkit ++ while (iterator1.hasNext()) { ++ net.minecraft.world.entity.LivingEntity entityliving = (net.minecraft.world.entity.LivingEntity) iterator1.next(); ++ ++ if (!this.victims.containsKey(entityliving) && entityliving.isAffectedByPotions()) { ++ double d6 = entityliving.getX() - this.getX(); ++ double d7 = entityliving.getZ() - this.getZ(); ++ double d8 = d6 * d6 + d7 * d7; ++ ++ if (d8 <= (double) (f * f)) { ++ // CraftBukkit start ++ entities.add((LivingEntity) entityliving.getBukkitEntity()); ++ } ++ } ++ } ++ org.bukkit.event.entity.AreaEffectCloudApplyEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callAreaEffectCloudApplyEvent(this, entities); ++ if (!event.isCancelled()) { ++ for (LivingEntity entity : event.getAffectedEntities()) { ++ if (entity instanceof CraftLivingEntity) { ++ net.minecraft.world.entity.LivingEntity entityliving = ((CraftLivingEntity) entity).getHandle(); ++ // CraftBukkit end ++ this.victims.put(entityliving, this.tickCount + this.reapplicationDelay); ++ Iterator iterator2 = list.iterator(); ++ ++ while (iterator2.hasNext()) { ++ MobEffectInstance mobeffect1 = (MobEffectInstance) iterator2.next(); ++ ++ if (mobeffect1.getEffect().isInstantenous()) { ++ mobeffect1.getEffect().applyInstantenousEffect(this, this.getOwner(), entityliving, mobeffect1.getAmplifier(), 0.5D); + } else { +- livingEntity.addEffect(new MobEffectInstance(mobEffectInstance1), this); ++ entityliving.addEffect(new MobEffectInstance(mobeffect1), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AREA_EFFECT_CLOUD); // CraftBukkit + } + } + + if (this.radiusOnUse != 0.0F) { +- radius += this.radiusOnUse; +- if (radius < 0.5F) { ++ f += this.radiusOnUse; ++ if (f < 0.5F) { + this.discard(); + return; + } + +- this.setRadius(radius); ++ this.setRadius(f); + } + + if (this.durationOnUse != 0) { +- this.duration = this.duration + this.durationOnUse; ++ this.duration += this.durationOnUse; + if (this.duration <= 0) { + this.discard(); + return; +@@ -284,6 +325,7 @@ + } + } + } ++ + } + + public float getRadiusOnUse() { +@@ -318,18 +360,19 @@ + this.waitTime = waitTime; + } + +- public void setOwner(@Nullable LivingEntity owner) { ++ public void setOwner(@Nullable net.minecraft.world.entity.LivingEntity owner) { + this.owner = owner; + this.ownerUUID = owner == null ? null : owner.getUUID(); + } + + @Nullable + @Override +- public LivingEntity getOwner() { ++ public net.minecraft.world.entity.LivingEntity getOwner() { + if (this.owner == null && this.ownerUUID != null && this.level() instanceof ServerLevel) { +- Entity entity = ((ServerLevel)this.level()).getEntity(this.ownerUUID); +- if (entity instanceof LivingEntity) { +- this.owner = (LivingEntity)entity; ++ Entity entity = ((ServerLevel) this.level()).getEntity(this.ownerUUID); ++ ++ if (entity instanceof net.minecraft.world.entity.LivingEntity) { ++ this.owner = (net.minecraft.world.entity.LivingEntity) entity; + } + } + +@@ -352,9 +395,9 @@ + + if (compound.contains("Particle", 8)) { + try { +- this.setParticle(ParticleArgument.readParticle(new StringReader(compound.getString("Particle")), BuiltInRegistries.PARTICLE_TYPE.asLookup())); +- } catch (CommandSyntaxException var5) { +- LOGGER.warn("Couldn't load custom particle {}", compound.getString("Particle"), var5); ++ this.setParticle(ParticleArgument.readParticle(new StringReader(compound.getString("Particle")), (HolderLookup) BuiltInRegistries.PARTICLE_TYPE.asLookup())); ++ } catch (CommandSyntaxException commandsyntaxexception) { ++ AreaEffectCloud.LOGGER.warn("Couldn't load custom particle {}", compound.getString("Particle"), commandsyntaxexception); + } + } + +@@ -367,16 +410,19 @@ + } + + if (compound.contains("effects", 9)) { +- ListTag list = compound.getList("effects", 10); ++ ListTag nbttaglist = compound.getList("effects", 10); ++ + this.effects.clear(); + +- for (int i = 0; i < list.size(); i++) { +- MobEffectInstance mobEffectInstance = MobEffectInstance.load(list.getCompound(i)); +- if (mobEffectInstance != null) { +- this.addEffect(mobEffectInstance); ++ for (int i = 0; i < nbttaglist.size(); ++i) { ++ MobEffectInstance mobeffect = MobEffectInstance.load(nbttaglist.getCompound(i)); ++ ++ if (mobeffect != null) { ++ this.addEffect(mobeffect); + } + } + } ++ + } + + @Override +@@ -403,19 +449,23 @@ + } + + if (!this.effects.isEmpty()) { +- ListTag list = new ListTag(); ++ ListTag nbttaglist = new ListTag(); ++ Iterator iterator = this.effects.iterator(); + +- for (MobEffectInstance mobEffectInstance : this.effects) { +- list.add(mobEffectInstance.save(new CompoundTag())); ++ while (iterator.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); ++ ++ nbttaglist.add(mobeffect.save(new CompoundTag())); + } + +- compound.put("effects", list); ++ compound.put("effects", nbttaglist); + } ++ + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { +- if (DATA_RADIUS.equals(key)) { ++ if (AreaEffectCloud.DATA_RADIUS.equals(key)) { + this.refreshDimensions(); + } + +@@ -427,12 +477,12 @@ + } + + @Override +- public PushReaction getPistonPushReaction() { +- return PushReaction.IGNORE; ++ public EnumPistonReaction getPistonPushReaction() { ++ return EnumPistonReaction.IGNORE; + } + + @Override +- public EntityDimensions getDimensions(Pose pose) { ++ public EntityDimensions getDimensions(EntityPose pose) { + return EntityDimensions.scalable(this.getRadius() * 2.0F, 0.5F); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/Entity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/Entity.java.patch new file mode 100644 index 0000000000..83caa6d7d9 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/Entity.java.patch @@ -0,0 +1,4402 @@ +--- a/net/minecraft/world/entity/Entity.java ++++ b/net/minecraft/world/entity/Entity.java +@@ -1,16 +1,18 @@ + package net.minecraft.world.entity; + + import com.google.common.collect.ImmutableList; ++import com.google.common.collect.ImmutableList.Builder; + import com.google.common.collect.Iterables; + import com.google.common.collect.Lists; + import com.google.common.collect.Sets; +-import com.google.common.collect.ImmutableList.Builder; ++import com.google.common.collect.UnmodifiableIterator; + import com.mojang.logging.LogUtils; + import it.unimi.dsi.fastutil.objects.Object2DoubleArrayMap; + import it.unimi.dsi.fastutil.objects.Object2DoubleMap; + import java.util.Arrays; + import java.util.Collections; + import java.util.HashSet; ++import java.util.Iterator; + import java.util.List; + import java.util.Locale; + import java.util.Objects; +@@ -41,10 +43,10 @@ + import net.minecraft.nbt.FloatTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.StringTag; ++import net.minecraft.network.chat.ClickEvent; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.HoverEvent; + import net.minecraft.network.chat.MutableComponent; +-import net.minecraft.network.chat.Style; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientGamePacketListener; + import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; +@@ -68,9 +70,9 @@ + import net.minecraft.tags.TagKey; + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; ++import net.minecraft.world.INamableTileEntity; + import net.minecraft.world.InteractionResult; +-import net.minecraft.world.Nameable; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.damagesource.DamageSources; + import net.minecraft.world.entity.item.ItemEntity; +@@ -85,28 +87,29 @@ + import net.minecraft.world.level.ClipContext; + import net.minecraft.world.level.Explosion; + import net.minecraft.world.level.GameRules; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.EnumRenderType; + import net.minecraft.world.level.block.FenceGateBlock; + import net.minecraft.world.level.block.HoneyBlock; + import net.minecraft.world.level.block.Mirror; +-import net.minecraft.world.level.block.RenderShape; + import net.minecraft.world.level.block.Rotation; + import net.minecraft.world.level.block.SoundType; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.border.WorldBorder; + import net.minecraft.world.level.dimension.DimensionType; ++import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.entity.EntityAccess; + import net.minecraft.world.level.entity.EntityInLevelCallback; + import net.minecraft.world.level.gameevent.DynamicGameEventListener; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.levelgen.Heightmap; ++import net.minecraft.world.level.material.EnumPistonReaction; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; +-import net.minecraft.world.level.material.PushReaction; + import net.minecraft.world.level.portal.PortalInfo; + import net.minecraft.world.level.portal.PortalShape; + import net.minecraft.world.phys.AABB; +@@ -123,8 +126,63 @@ + import net.minecraft.world.scores.Team; + import org.joml.Vector3f; + import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.Server; ++import org.bukkit.block.BlockFace; ++import org.bukkit.command.CommandSender; ++import org.bukkit.craftbukkit.event.CraftPortalEvent; ++import org.bukkit.entity.Hanging; ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.entity.Vehicle; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.hanging.HangingBreakByEntityEvent; ++import org.bukkit.event.vehicle.VehicleBlockCollisionEvent; ++import org.bukkit.event.vehicle.VehicleEnterEvent; ++import org.bukkit.event.vehicle.VehicleExitEvent; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.entity.CraftEntity; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.Pose; ++import org.bukkit.event.entity.EntityAirChangeEvent; ++import org.bukkit.event.entity.EntityCombustEvent; ++import org.bukkit.event.entity.EntityDropItemEvent; ++import org.bukkit.event.entity.EntityPortalEvent; ++import org.bukkit.event.entity.EntityPoseChangeEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++import org.bukkit.plugin.PluginManager; ++// CraftBukkit end + +-public abstract class Entity implements Nameable, EntityAccess, CommandSource, ScoreHolder { ++public abstract class Entity implements INamableTileEntity, EntityAccess, CommandSource, ScoreHolder { ++ ++ // CraftBukkit start ++ private static final int CURRENT_LEVEL = 2; ++ static boolean isLevelAtLeast(CompoundTag tag, int level) { ++ return tag.contains("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; ++ } ++ ++ private CraftEntity bukkitEntity; ++ ++ public CraftEntity getBukkitEntity() { ++ if (bukkitEntity == null) { ++ bukkitEntity = CraftEntity.getEntity(level.getCraftServer(), this); ++ } ++ return bukkitEntity; ++ } ++ ++ @Override ++ public CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return getBukkitEntity(); ++ } ++ ++ // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ public int getDefaultMaxAirSupply() { ++ return TOTAL_AIR_SUPPLY; ++ } ++ // CraftBukkit end ++ + private static final Logger LOGGER = LogUtils.getLogger(); + public static final String ID_TAG = "id"; + public static final String PASSENGERS_TAG = "Passengers"; +@@ -134,21 +192,21 @@ + public static final int TOTAL_AIR_SUPPLY = 300; + public static final int MAX_ENTITY_TAG_COUNT = 1024; + public static final float DELTA_AFFECTED_BY_BLOCKS_BELOW_0_2 = 0.2F; +- public static final double DELTA_AFFECTED_BY_BLOCKS_BELOW_0_5 = 0.500001; +- public static final double DELTA_AFFECTED_BY_BLOCKS_BELOW_1_0 = 0.999999; ++ public static final double DELTA_AFFECTED_BY_BLOCKS_BELOW_0_5 = 0.500001D; ++ public static final double DELTA_AFFECTED_BY_BLOCKS_BELOW_1_0 = 0.999999D; + public static final float BREATHING_DISTANCE_BELOW_EYES = 0.11111111F; + public static final int BASE_TICKS_REQUIRED_TO_FREEZE = 140; + public static final int FREEZE_HURT_FREQUENCY = 40; +- private static final AABB INITIAL_AABB = new AABB(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); +- private static final double WATER_FLOW_SCALE = 0.014; +- private static final double LAVA_FAST_FLOW_SCALE = 0.007; +- private static final double LAVA_SLOW_FLOW_SCALE = 0.0023333333333333335; ++ private static final AABB INITIAL_AABB = new AABB(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D); ++ private static final double WATER_FLOW_SCALE = 0.014D; ++ private static final double LAVA_FAST_FLOW_SCALE = 0.007D; ++ private static final double LAVA_SLOW_FLOW_SCALE = 0.0023333333333333335D; + public static final String UUID_TAG = "UUID"; +- private static double viewScale = 1.0; ++ private static double viewScale = 1.0D; + private final EntityType type; +- private int id = ENTITY_COUNTER.incrementAndGet(); ++ private int id; + public boolean blocksBuilding; +- private ImmutableList passengers = ImmutableList.of(); ++ public ImmutableList passengers; + protected int boardingCooldown; + @Nullable + private Entity vehicle; +@@ -159,19 +217,19 @@ + private Vec3 position; + private BlockPos blockPosition; + private ChunkPos chunkPosition; +- private Vec3 deltaMovement = Vec3.ZERO; ++ private Vec3 deltaMovement; + private float yRot; + private float xRot; + public float yRotO; + public float xRotO; +- private AABB bb = INITIAL_AABB; +- private boolean onGround; ++ private AABB bb; ++ public boolean onGround; + public boolean horizontalCollision; + public boolean verticalCollision; + public boolean verticalCollisionBelow; + public boolean minorHorizontalCollision; + public boolean hurtMarked; +- protected Vec3 stuckSpeedMultiplier = Vec3.ZERO; ++ protected Vec3 stuckSpeedMultiplier; + @Nullable + private Entity.RemovalReason removalReason; + public static final float DEFAULT_BB_WIDTH = 0.6F; +@@ -181,21 +239,21 @@ + public float moveDist; + public float flyDist; + public float fallDistance; +- private float nextStep = 1.0F; ++ private float nextStep; + public double xOld; + public double yOld; + public double zOld; + private float maxUpStep; + public boolean noPhysics; +- protected final RandomSource random = RandomSource.create(); ++ public final RandomSource random; + public int tickCount; +- private int remainingFireTicks = -this.getFireImmuneTicks(); +- protected boolean wasTouchingWater; +- protected Object2DoubleMap> fluidHeight = new Object2DoubleArrayMap<>(2); ++ private int remainingFireTicks; ++ public boolean wasTouchingWater; ++ protected Object2DoubleMap> fluidHeight; + protected boolean wasEyeInWater; +- private final Set> fluidOnEyes = new HashSet<>(); ++ private final Set> fluidOnEyes; + public int invulnerableTime; +- protected boolean firstTick = true; ++ protected boolean firstTick; + protected final SynchedEntityData entityData; + protected static final EntityDataAccessor DATA_SHARED_FLAGS_ID = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.BYTE); + protected static final int FLAG_ONFIRE = 0; +@@ -206,43 +264,84 @@ + protected static final int FLAG_GLOWING = 6; + protected static final int FLAG_FALL_FLYING = 7; + private static final EntityDataAccessor DATA_AIR_SUPPLY_ID = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.INT); +- private static final EntityDataAccessor> DATA_CUSTOM_NAME = SynchedEntityData.defineId( +- Entity.class, EntityDataSerializers.OPTIONAL_COMPONENT +- ); ++ private static final EntityDataAccessor> DATA_CUSTOM_NAME = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.OPTIONAL_COMPONENT); + private static final EntityDataAccessor DATA_CUSTOM_NAME_VISIBLE = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_SILENT = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_NO_GRAVITY = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.BOOLEAN); +- protected static final EntityDataAccessor DATA_POSE = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.POSE); ++ protected static final EntityDataAccessor DATA_POSE = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.POSE); + private static final EntityDataAccessor DATA_TICKS_FROZEN = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.INT); +- private EntityInLevelCallback levelCallback = EntityInLevelCallback.NULL; +- private final VecDeltaCodec packetPositionCodec = new VecDeltaCodec(); ++ private EntityInLevelCallback levelCallback; ++ private final VecDeltaCodec packetPositionCodec; + public boolean noCulling; + public boolean hasImpulse; +- private int portalCooldown; ++ public int portalCooldown; + protected boolean isInsidePortal; + protected int portalTime; + protected BlockPos portalEntrancePos; + private boolean invulnerable; +- protected UUID uuid = Mth.createInsecureUUID(this.random); +- protected String stringUUID = this.uuid.toString(); ++ protected UUID uuid; ++ protected String stringUUID; + private boolean hasGlowingTag; +- private final Set tags = Sets.newHashSet(); +- private final double[] pistonDeltas = new double[]{0.0, 0.0, 0.0}; ++ private final Set tags; ++ private final double[] pistonDeltas; + private long pistonDeltasGameTime; + private EntityDimensions dimensions; + private float eyeHeight; + public boolean isInPowderSnow; + public boolean wasInPowderSnow; + public boolean wasOnFire; +- public Optional mainSupportingBlockPos = Optional.empty(); +- private boolean onGroundNoBlocks = false; ++ public Optional mainSupportingBlockPos; ++ private boolean onGroundNoBlocks; + private float crystalSoundIntensity; + private int lastCrystalSoundPlayTick; +- private boolean hasVisualFire; ++ public boolean hasVisualFire; + @Nullable +- private BlockState feetBlockState = null; ++ private IBlockData feetBlockState; ++ // CraftBukkit start ++ public boolean persist = true; ++ public boolean visibleByDefault = true; ++ public boolean valid; ++ public boolean inWorld = false; ++ public boolean generation; ++ public int maxAirTicks = getDefaultMaxAirSupply(); // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only ++ public boolean lastDamageCancelled; // SPIGOT-5339, SPIGOT-6252, SPIGOT-6777: Keep track if the event was canceled ++ public boolean persistentInvisibility = false; ++ public BlockPos lastLavaContact; ++ // Marks an entity, that it was removed by a plugin via Entity#remove ++ // Main use case currently is for SPIGOT-7487, preventing dropping of leash when leash is removed ++ public boolean pluginRemoved = false; + ++ public float getBukkitYaw() { ++ return this.yRot; ++ } ++ ++ public boolean isChunkLoaded() { ++ return level.hasChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); ++ } ++ // CraftBukkit end ++ + public Entity(EntityType entityType, Level level) { ++ this.id = Entity.ENTITY_COUNTER.incrementAndGet(); ++ this.passengers = ImmutableList.of(); ++ this.deltaMovement = Vec3.ZERO; ++ this.bb = Entity.INITIAL_AABB; ++ this.stuckSpeedMultiplier = Vec3.ZERO; ++ this.nextStep = 1.0F; ++ this.random = RandomSource.create(); ++ this.remainingFireTicks = -this.getFireImmuneTicks(); ++ this.fluidHeight = new Object2DoubleArrayMap(2); ++ this.fluidOnEyes = new HashSet(); ++ this.firstTick = true; ++ this.levelCallback = EntityInLevelCallback.NULL; ++ this.packetPositionCodec = new VecDeltaCodec(); ++ this.uuid = Mth.createInsecureUUID(this.random); ++ this.stringUUID = this.uuid.toString(); ++ this.tags = Sets.newHashSet(); ++ this.pistonDeltas = new double[]{0.0D, 0.0D, 0.0D}; ++ this.mainSupportingBlockPos = Optional.empty(); ++ this.onGroundNoBlocks = false; ++ this.feetBlockState = null; + this.type = entityType; + this.level = level; + this.dimensions = entityType.getDimensions(); +@@ -250,28 +349,30 @@ + this.blockPosition = BlockPos.ZERO; + this.chunkPosition = ChunkPos.ZERO; + this.entityData = new SynchedEntityData(this); +- this.entityData.define(DATA_SHARED_FLAGS_ID, (byte)0); +- this.entityData.define(DATA_AIR_SUPPLY_ID, this.getMaxAirSupply()); +- this.entityData.define(DATA_CUSTOM_NAME_VISIBLE, false); +- this.entityData.define(DATA_CUSTOM_NAME, Optional.empty()); +- this.entityData.define(DATA_SILENT, false); +- this.entityData.define(DATA_NO_GRAVITY, false); +- this.entityData.define(DATA_POSE, Pose.STANDING); +- this.entityData.define(DATA_TICKS_FROZEN, 0); ++ this.entityData.define(Entity.DATA_SHARED_FLAGS_ID, (byte) 0); ++ this.entityData.define(Entity.DATA_AIR_SUPPLY_ID, this.getMaxAirSupply()); ++ this.entityData.define(Entity.DATA_CUSTOM_NAME_VISIBLE, false); ++ this.entityData.define(Entity.DATA_CUSTOM_NAME, Optional.empty()); ++ this.entityData.define(Entity.DATA_SILENT, false); ++ this.entityData.define(Entity.DATA_NO_GRAVITY, false); ++ this.entityData.define(Entity.DATA_POSE, EntityPose.STANDING); ++ this.entityData.define(Entity.DATA_TICKS_FROZEN, 0); + this.defineSynchedData(); +- this.setPos(0.0, 0.0, 0.0); +- this.eyeHeight = this.getEyeHeight(Pose.STANDING, this.dimensions); ++ this.setPos(0.0D, 0.0D, 0.0D); ++ this.eyeHeight = this.getEyeHeight(EntityPose.STANDING, this.dimensions); + } + +- public boolean isColliding(BlockPos pos, BlockState state) { +- VoxelShape collisionShape = state.getCollisionShape(this.level(), pos, CollisionContext.of(this)); +- VoxelShape voxelShape = collisionShape.move((double)pos.getX(), (double)pos.getY(), (double)pos.getZ()); +- return Shapes.joinIsNotEmpty(voxelShape, Shapes.create(this.getBoundingBox()), BooleanOp.AND); ++ public boolean isColliding(BlockPos pos, IBlockData state) { ++ VoxelShape voxelshape = state.getCollisionShape(this.level(), pos, CollisionContext.of(this)); ++ VoxelShape voxelshape1 = voxelshape.move((double) pos.getX(), (double) pos.getY(), (double) pos.getZ()); ++ ++ return Shapes.joinIsNotEmpty(voxelshape1, Shapes.create(this.getBoundingBox()), BooleanOp.AND); + } + + public int getTeamColor() { +- Team team = this.getTeam(); +- return team != null && team.getColor().getColor() != null ? team.getColor().getColor() : 16777215; ++ PlayerTeam scoreboardteam = this.getTeam(); ++ ++ return scoreboardteam != null && scoreboardteam.getColor().getColor() != null ? scoreboardteam.getColor().getColor() : 16777215; + } + + public boolean isSpectator() { +@@ -286,10 +387,11 @@ + if (this.isPassenger()) { + this.stopRiding(); + } ++ + } + +- public void syncPacketPositionCodec(double x, double y, double z) { +- this.packetPositionCodec.setBase(new Vec3(x, y, z)); ++ public void syncPacketPositionCodec(double x, double d1, double y) { ++ this.packetPositionCodec.setBase(new Vec3(x, d1, y)); + } + + public VecDeltaCodec getPositionCodec() { +@@ -314,7 +416,7 @@ + } + + public boolean addTag(String tag) { +- return this.tags.size() < 1024 && this.tags.add(tag); ++ return this.tags.size() >= 1024 ? false : this.tags.add(tag); + } + + public boolean removeTag(String tag) { +@@ -336,12 +438,10 @@ + return this.entityData; + } + +- @Override + public boolean equals(Object object) { +- return object instanceof Entity && ((Entity)object).id == this.id; ++ return object instanceof Entity ? ((Entity) object).id == this.id : false; + } + +- @Override + public int hashCode() { + return this.id; + } +@@ -350,18 +450,23 @@ + this.setRemoved(reason); + } + +- public void onClientRemoval() { +- } ++ public void onClientRemoval() {} + +- public void setPose(Pose pose) { +- this.entityData.set(DATA_POSE, pose); ++ public void setPose(EntityPose pose) { ++ // CraftBukkit start ++ if (pose == this.getPose()) { ++ return; ++ } ++ this.level.getCraftServer().getPluginManager().callEvent(new EntityPoseChangeEvent(this.getBukkitEntity(), Pose.values()[pose.ordinal()])); ++ // CraftBukkit end ++ this.entityData.set(Entity.DATA_POSE, pose); + } + +- public Pose getPose() { +- return this.entityData.get(DATA_POSE); ++ public EntityPose getPose() { ++ return (EntityPose) this.entityData.get(Entity.DATA_POSE); + } + +- public boolean hasPose(Pose pose) { ++ public boolean hasPose(EntityPose pose) { + return this.getPose() == pose; + } + +@@ -369,14 +474,42 @@ + return this.position().closerThan(entity.position(), distance); + } + +- public boolean closerThan(Entity entity, double horizontalDistance, double verticalDistance) { +- double d = entity.getX() - this.getX(); +- double d1 = entity.getY() - this.getY(); +- double d2 = entity.getZ() - this.getZ(); +- return Mth.lengthSquared(d, d2) < Mth.square(horizontalDistance) && Mth.square(d1) < Mth.square(verticalDistance); ++ public boolean closerThan(Entity entity, double horizontalDistance, double d1) { ++ double d2 = entity.getX() - this.getX(); ++ double d3 = entity.getY() - this.getY(); ++ double d4 = entity.getZ() - this.getZ(); ++ ++ return Mth.lengthSquared(d2, d4) < Mth.square(horizontalDistance) && Mth.square(d3) < Mth.square(d1); + } + + protected void setRot(float yRot, float xRot) { ++ // CraftBukkit start - yaw was sometimes set to NaN, so we need to set it back to 0 ++ if (Float.isNaN(yRot)) { ++ yRot = 0; ++ } ++ ++ if (yRot == Float.POSITIVE_INFINITY || yRot == Float.NEGATIVE_INFINITY) { ++ if (this instanceof ServerPlayer) { ++ this.level.getCraftServer().getLogger().warning(this.getScoreboardName() + " was caught trying to crash the server with an invalid yaw"); ++ ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Infinite yaw (Hacking?)"); ++ } ++ yRot = 0; ++ } ++ ++ // pitch was sometimes set to NaN, so we need to set it back to 0 ++ if (Float.isNaN(xRot)) { ++ xRot = 0; ++ } ++ ++ if (xRot == Float.POSITIVE_INFINITY || xRot == Float.NEGATIVE_INFINITY) { ++ if (this instanceof ServerPlayer) { ++ this.level.getCraftServer().getLogger().warning(this.getScoreboardName() + " was caught trying to crash the server with an invalid pitch"); ++ ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Infinite pitch (Hacking?)"); ++ } ++ xRot = 0; ++ } ++ // CraftBukkit end ++ + this.setYRot(yRot % 360.0F); + this.setXRot(xRot % 360.0F); + } +@@ -385,8 +518,8 @@ + this.setPos(pos.x(), pos.y(), pos.z()); + } + +- public void setPos(double x, double y, double z) { +- this.setPosRaw(x, y, z); ++ public void setPos(double x, double d1, double y) { ++ this.setPosRaw(x, d1, y); + this.setBoundingBox(this.makeBoundingBox()); + } + +@@ -398,9 +531,10 @@ + this.setPos(this.position.x, this.position.y, this.position.z); + } + +- public void turn(double yRot, double xRot) { +- float f = (float)xRot * 0.15F; +- float f1 = (float)yRot * 0.15F; ++ public void turn(double yRot, double d1) { ++ float f = (float) d1 * 0.15F; ++ float f1 = (float) yRot * 0.15F; ++ + this.setXRot(this.getXRot() + f); + this.setYRot(this.getYRot() + f1); + this.setXRot(Mth.clamp(this.getXRot(), -90.0F, 90.0F)); +@@ -410,12 +544,22 @@ + if (this.vehicle != null) { + this.vehicle.onPassengerTurned(this); + } ++ + } + + public void tick() { + this.baseTick(); + } + ++ // CraftBukkit start ++ public void postTick() { ++ // No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle ++ if (!(this instanceof ServerPlayer)) { ++ this.handleNetherPortal(); ++ } ++ } ++ // CraftBukkit end ++ + public void baseTick() { + this.level().getProfiler().push("entityBaseTick"); + this.feetBlockState = null; +@@ -424,13 +568,13 @@ + } + + if (this.boardingCooldown > 0) { +- this.boardingCooldown--; ++ --this.boardingCooldown; + } + + this.walkDistO = this.walkDist; + this.xRotO = this.getXRot(); + this.yRotO = this.getYRot(); +- this.handleNetherPortal(); ++ if (this instanceof ServerPlayer) this.handleNetherPortal(); // CraftBukkit - // Moved up to postTick + if (this.canSpawnSprintParticle()) { + this.spawnSprintParticle(); + } +@@ -458,13 +602,17 @@ + + if (this.getTicksFrozen() > 0) { + this.setTicksFrozen(0); +- this.level().levelEvent(null, 1009, this.blockPosition, 1); ++ this.level().levelEvent((Player) null, 1009, this.blockPosition, 1); + } + } + + if (this.isInLava()) { + this.lavaHurt(); + this.fallDistance *= 0.5F; ++ // CraftBukkit start ++ } else { ++ this.lastLavaContact = null; ++ // CraftBukkit end + } + + this.checkBelowWorld(); +@@ -481,9 +629,10 @@ + } + + public void checkBelowWorld() { +- if (this.getY() < (double)(this.level().getMinBuildHeight() - 64)) { ++ if (this.getY() < (double) (this.level().getMinBuildHeight() - 64)) { + this.onBelowWorld(); + } ++ + } + + public void setPortalCooldown() { +@@ -504,8 +653,9 @@ + + protected void processPortalCooldown() { + if (this.isOnPortalCooldown()) { +- this.portalCooldown--; ++ --this.portalCooldown; + } ++ + } + + public int getPortalWaitTime() { +@@ -514,22 +664,58 @@ + + public void lavaHurt() { + if (!this.fireImmune()) { +- this.setSecondsOnFire(15); ++ // CraftBukkit start - Fallen in lava TODO: this event spams! ++ if (this instanceof net.minecraft.world.entity.LivingEntity && remainingFireTicks <= 0) { ++ // not on fire yet ++ org.bukkit.block.Block damager = (lastLavaContact == null) ? null : org.bukkit.craftbukkit.block.CraftBlock.at(level, lastLavaContact); ++ org.bukkit.entity.Entity damagee = this.getBukkitEntity(); ++ EntityCombustEvent combustEvent = new org.bukkit.event.entity.EntityCombustByBlockEvent(damager, damagee, 15); ++ this.level.getCraftServer().getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ this.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ } else { ++ // This will be called every single tick the entity is in lava, so don't throw an event ++ this.setSecondsOnFire(15, false); ++ } ++ CraftEventFactory.blockDamage = (lastLavaContact) == null ? null : org.bukkit.craftbukkit.block.CraftBlock.at(level, lastLavaContact); + if (this.hurt(this.damageSources().lava(), 4.0F)) { + this.playSound(SoundEvents.GENERIC_BURN, 0.4F, 2.0F + this.random.nextFloat() * 0.4F); + } ++ CraftEventFactory.blockDamage = null; ++ // CraftBukkit end - we also don't throw an event unless the object in lava is living, to save on some event calls ++ + } + } + + public void setSecondsOnFire(int seconds) { +- int i = seconds * 20; +- if (this instanceof LivingEntity) { +- i = ProtectionEnchantment.getFireAfterDampener((LivingEntity)this, i); ++ // CraftBukkit start ++ this.setSecondsOnFire(seconds, true); ++ } ++ ++ public void setSecondsOnFire(int i, boolean callEvent) { ++ if (callEvent) { ++ EntityCombustEvent event = new EntityCombustEvent(this.getBukkitEntity(), i); ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ i = event.getDuration(); + } ++ // CraftBukkit end ++ int j = i * 20; + +- if (this.remainingFireTicks < i) { +- this.setRemainingFireTicks(i); ++ if (this instanceof net.minecraft.world.entity.LivingEntity) { ++ j = ProtectionEnchantment.getFireAfterDampener((net.minecraft.world.entity.LivingEntity) this, j); + } ++ ++ if (this.remainingFireTicks < j) { ++ this.setRemainingFireTicks(j); ++ } ++ + } + + public void setRemainingFireTicks(int remainingFireTicks) { +@@ -548,8 +734,8 @@ + this.discard(); + } + +- public boolean isFree(double x, double y, double z) { +- return this.isFree(this.getBoundingBox().move(x, y, z)); ++ public boolean isFree(double x, double d1, double y) { ++ return this.isFree(this.getBoundingBox().move(x, d1, y)); + } + + private boolean isFree(AABB box) { +@@ -558,7 +744,7 @@ + + public void setOnGround(boolean onGround) { + this.onGround = onGround; +- this.checkSupportingBlock(onGround, null); ++ this.checkSupportingBlock(onGround, (Vec3) null); + } + + public void setOnGroundWithKnownMovement(boolean onGround, Vec3 movement) { +@@ -567,20 +753,24 @@ + } + + public boolean isSupportedBy(BlockPos pos) { +- return this.mainSupportingBlockPos.isPresent() && this.mainSupportingBlockPos.get().equals(pos); ++ return this.mainSupportingBlockPos.isPresent() && ((BlockPos) this.mainSupportingBlockPos.get()).equals(pos); + } + + protected void checkSupportingBlock(boolean onGround, @Nullable Vec3 movement) { + if (onGround) { +- AABB boundingBox = this.getBoundingBox(); +- AABB aABB = new AABB(boundingBox.minX, boundingBox.minY - 1.0E-6, boundingBox.minZ, boundingBox.maxX, boundingBox.minY, boundingBox.maxZ); +- Optional optional = this.level.findSupportingBlock(this, aABB); +- if (optional.isPresent() || this.onGroundNoBlocks) { ++ AABB axisalignedbb = this.getBoundingBox(); ++ AABB axisalignedbb1 = new AABB(axisalignedbb.minX, axisalignedbb.minY - 1.0E-6D, axisalignedbb.minZ, axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.maxZ); ++ Optional optional = this.level.findSupportingBlock(this, axisalignedbb1); ++ ++ if (!optional.isPresent() && !this.onGroundNoBlocks) { ++ if (movement != null) { ++ AABB axisalignedbb2 = axisalignedbb1.move(-movement.x, 0.0D, -movement.z); ++ ++ optional = this.level.findSupportingBlock(this, axisalignedbb2); ++ this.mainSupportingBlockPos = optional; ++ } ++ } else { + this.mainSupportingBlockPos = optional; +- } else if (movement != null) { +- AABB aABB1 = aABB.move(-movement.x, 0.0, -movement.z); +- optional = this.level.findSupportingBlock(this, aABB1); +- this.mainSupportingBlockPos = optional; + } + + this.onGroundNoBlocks = optional.isEmpty(); +@@ -590,18 +780,19 @@ + this.mainSupportingBlockPos = Optional.empty(); + } + } ++ + } + + public boolean onGround() { + return this.onGround; + } + +- public void move(MoverType type, Vec3 pos) { ++ public void move(EnumMoveType type, Vec3 pos) { + if (this.noPhysics) { + this.setPos(this.getX() + pos.x, this.getY() + pos.y, this.getZ() + pos.z); + } else { + this.wasOnFire = this.isOnFire(); +- if (type == MoverType.PISTON) { ++ if (type == EnumMoveType.PISTON) { + pos = this.limitPistonMovement(pos); + if (pos.equals(Vec3.ZERO)) { + return; +@@ -609,108 +800,138 @@ + } + + this.level().getProfiler().push("move"); +- if (this.stuckSpeedMultiplier.lengthSqr() > 1.0E-7) { ++ if (this.stuckSpeedMultiplier.lengthSqr() > 1.0E-7D) { + pos = pos.multiply(this.stuckSpeedMultiplier); + this.stuckSpeedMultiplier = Vec3.ZERO; + this.setDeltaMovement(Vec3.ZERO); + } + +- Vec3 var23 = this.maybeBackOffFromEdge(pos, type); +- Vec3 vec3 = this.collide(var23); +- double d = vec3.lengthSqr(); +- if (d > 1.0E-7) { +- if (this.fallDistance != 0.0F && d >= 1.0) { +- BlockHitResult blockHitResult = this.level() +- .clip( +- new ClipContext(this.position(), this.position().add(vec3), ClipContext.Block.FALLDAMAGE_RESETTING, ClipContext.Fluid.WATER, this) +- ); +- if (blockHitResult.getType() != HitResult.Type.MISS) { ++ pos = this.maybeBackOffFromEdge(pos, type); ++ Vec3 vec3d1 = this.collide(pos); ++ double d0 = vec3d1.lengthSqr(); ++ ++ if (d0 > 1.0E-7D) { ++ if (this.fallDistance != 0.0F && d0 >= 1.0D) { ++ BlockHitResult movingobjectpositionblock = this.level().clip(new ClipContext(this.position(), this.position().add(vec3d1), ClipContext.Block.FALLDAMAGE_RESETTING, ClipContext.Fluid.WATER, this)); ++ ++ if (movingobjectpositionblock.getType() != HitResult.EnumMovingObjectType.MISS) { + this.resetFallDistance(); + } + } + +- this.setPos(this.getX() + vec3.x, this.getY() + vec3.y, this.getZ() + vec3.z); ++ this.setPos(this.getX() + vec3d1.x, this.getY() + vec3d1.y, this.getZ() + vec3d1.z); + } + + this.level().getProfiler().pop(); + this.level().getProfiler().push("rest"); +- boolean flag = !Mth.equal(var23.x, vec3.x); +- boolean flag1 = !Mth.equal(var23.z, vec3.z); ++ boolean flag = !Mth.equal(pos.x, vec3d1.x); ++ boolean flag1 = !Mth.equal(pos.z, vec3d1.z); ++ + this.horizontalCollision = flag || flag1; +- this.verticalCollision = var23.y != vec3.y; +- this.verticalCollisionBelow = this.verticalCollision && var23.y < 0.0; ++ this.verticalCollision = pos.y != vec3d1.y; ++ this.verticalCollisionBelow = this.verticalCollision && pos.y < 0.0D; + if (this.horizontalCollision) { +- this.minorHorizontalCollision = this.isHorizontalCollisionMinor(vec3); ++ this.minorHorizontalCollision = this.isHorizontalCollisionMinor(vec3d1); + } else { + this.minorHorizontalCollision = false; + } + +- this.setOnGroundWithKnownMovement(this.verticalCollisionBelow, vec3); +- BlockPos onPosLegacy = this.getOnPosLegacy(); +- BlockState blockState = this.level().getBlockState(onPosLegacy); +- this.checkFallDamage(vec3.y, this.onGround(), blockState, onPosLegacy); ++ this.setOnGroundWithKnownMovement(this.verticalCollisionBelow, vec3d1); ++ BlockPos blockposition = this.getOnPosLegacy(); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); ++ ++ this.checkFallDamage(vec3d1.y, this.onGround(), iblockdata, blockposition); + if (this.isRemoved()) { + this.level().getProfiler().pop(); + } else { + if (this.horizontalCollision) { +- Vec3 deltaMovement = this.getDeltaMovement(); +- this.setDeltaMovement(flag ? 0.0 : deltaMovement.x, deltaMovement.y, flag1 ? 0.0 : deltaMovement.z); ++ Vec3 vec3d2 = this.getDeltaMovement(); ++ ++ this.setDeltaMovement(flag ? 0.0D : vec3d2.x, vec3d2.y, flag1 ? 0.0D : vec3d2.z); + } + +- Block block = blockState.getBlock(); +- if (var23.y != vec3.y) { ++ Block block = iblockdata.getBlock(); ++ ++ if (pos.y != vec3d1.y) { + block.updateEntityAfterFallOn(this.level(), this); + } + ++ // CraftBukkit start ++ if (horizontalCollision && getBukkitEntity() instanceof Vehicle) { ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ org.bukkit.block.Block bl = this.level.getWorld().getBlockAt(Mth.floor(this.getX()), Mth.floor(this.getY()), Mth.floor(this.getZ())); ++ ++ if (pos.x > vec3d1.x) { ++ bl = bl.getRelative(BlockFace.EAST); ++ } else if (pos.x < vec3d1.x) { ++ bl = bl.getRelative(BlockFace.WEST); ++ } else if (pos.z > vec3d1.z) { ++ bl = bl.getRelative(BlockFace.SOUTH); ++ } else if (pos.z < vec3d1.z) { ++ bl = bl.getRelative(BlockFace.NORTH); ++ } ++ ++ if (!bl.getType().isAir()) { ++ VehicleBlockCollisionEvent event = new VehicleBlockCollisionEvent(vehicle, bl); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ } ++ } ++ // CraftBukkit end ++ + if (this.onGround()) { +- block.stepOn(this.level(), onPosLegacy, blockState, this); ++ block.stepOn(this.level(), blockposition, iblockdata, this); + } + +- Entity.MovementEmission movementEmission = this.getMovementEmission(); +- if (movementEmission.emitsAnything() && !this.isPassenger()) { +- double d1 = vec3.x; +- double d2 = vec3.y; +- double d3 = vec3.z; +- this.flyDist = this.flyDist + (float)(vec3.length() * 0.6); +- BlockPos onPos = this.getOnPos(); +- BlockState blockState1 = this.level().getBlockState(onPos); +- boolean isStateClimbable = this.isStateClimbable(blockState1); +- if (!isStateClimbable) { +- d2 = 0.0; ++ Entity.MovementEmission entity_movementemission = this.getMovementEmission(); ++ ++ if (entity_movementemission.emitsAnything() && !this.isPassenger()) { ++ double d1 = vec3d1.x; ++ double d2 = vec3d1.y; ++ double d3 = vec3d1.z; ++ ++ this.flyDist += (float) (vec3d1.length() * 0.6D); ++ BlockPos blockposition1 = this.getOnPos(); ++ IBlockData iblockdata1 = this.level().getBlockState(blockposition1); ++ boolean flag2 = this.isStateClimbable(iblockdata1); ++ ++ if (!flag2) { ++ d2 = 0.0D; + } + +- this.walkDist = this.walkDist + (float)vec3.horizontalDistance() * 0.6F; +- this.moveDist = this.moveDist + (float)Math.sqrt(d1 * d1 + d2 * d2 + d3 * d3) * 0.6F; +- if (this.moveDist > this.nextStep && !blockState1.isAir()) { +- boolean flag2 = onPos.equals(onPosLegacy); +- boolean flag3 = this.vibrationAndSoundEffectsFromBlock(onPosLegacy, blockState, movementEmission.emitsSounds(), flag2, var23); +- if (!flag2) { +- flag3 |= this.vibrationAndSoundEffectsFromBlock(onPos, blockState1, false, movementEmission.emitsEvents(), var23); ++ this.walkDist += (float) vec3d1.horizontalDistance() * 0.6F; ++ this.moveDist += (float) Math.sqrt(d1 * d1 + d2 * d2 + d3 * d3) * 0.6F; ++ if (this.moveDist > this.nextStep && !iblockdata1.isAir()) { ++ boolean flag3 = blockposition1.equals(blockposition); ++ boolean flag4 = this.vibrationAndSoundEffectsFromBlock(blockposition, iblockdata, entity_movementemission.emitsSounds(), flag3, pos); ++ ++ if (!flag3) { ++ flag4 |= this.vibrationAndSoundEffectsFromBlock(blockposition1, iblockdata1, false, entity_movementemission.emitsEvents(), pos); + } + +- if (flag3) { ++ if (flag4) { + this.nextStep = this.nextStep(); + } else if (this.isInWater()) { + this.nextStep = this.nextStep(); +- if (movementEmission.emitsSounds()) { ++ if (entity_movementemission.emitsSounds()) { + this.waterSwimSound(); + } + +- if (movementEmission.emitsEvents()) { ++ if (entity_movementemission.emitsEvents()) { + this.gameEvent(GameEvent.SWIM); + } + } +- } else if (blockState1.isAir()) { ++ } else if (iblockdata1.isAir()) { + this.processFlappingMovement(); + } + } + + this.tryCheckInsideBlocks(); +- float blockSpeedFactor = this.getBlockSpeedFactor(); +- this.setDeltaMovement(this.getDeltaMovement().multiply((double)blockSpeedFactor, 1.0, (double)blockSpeedFactor)); +- if (this.level() +- .getBlockStatesIfLoaded(this.getBoundingBox().deflate(1.0E-6)) +- .noneMatch(loadedState -> loadedState.is(BlockTags.FIRE) || loadedState.is(Blocks.LAVA))) { ++ float f = this.getBlockSpeedFactor(); ++ ++ this.setDeltaMovement(this.getDeltaMovement().multiply((double) f, 1.0D, (double) f)); ++ if (this.level().getBlockStatesIfLoaded(this.getBoundingBox().deflate(1.0E-6D)).noneMatch((iblockdata2) -> { ++ return iblockdata2.is(BlockTags.FIRE) || iblockdata2.is(Blocks.LAVA); ++ })) { + if (this.remainingFireTicks <= 0) { + this.setRemainingFireTicks(-this.getFireImmuneTicks()); + } +@@ -729,16 +950,17 @@ + } + } + +- private boolean isStateClimbable(BlockState state) { ++ private boolean isStateClimbable(IBlockData state) { + return state.is(BlockTags.CLIMBABLE) || state.is(Blocks.POWDER_SNOW); + } + +- private boolean vibrationAndSoundEffectsFromBlock(BlockPos pos, BlockState state, boolean playStepSound, boolean broadcastGameEvent, Vec3 vec3) { ++ private boolean vibrationAndSoundEffectsFromBlock(BlockPos pos, IBlockData state, boolean playStepSound, boolean broadcastGameEvent, Vec3 vec3d) { + if (state.isAir()) { + return false; + } else { +- boolean isStateClimbable = this.isStateClimbable(state); +- if ((this.onGround() || isStateClimbable || this.isCrouching() && vec3.y == 0.0 || this.isOnRails()) && !this.isSwimming()) { ++ boolean flag2 = this.isStateClimbable(state); ++ ++ if ((this.onGround() || flag2 || this.isCrouching() && vec3d.y == 0.0D || this.isOnRails()) && !this.isSwimming()) { + if (playStepSound) { + this.walkingStepSound(pos, state); + } +@@ -761,11 +983,12 @@ + protected void tryCheckInsideBlocks() { + try { + this.checkInsideBlocks(); +- } catch (Throwable var4) { +- CrashReport crashReport = CrashReport.forThrowable(var4, "Checking entity block collision"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Entity being checked for collision"); +- this.fillCrashReportCategory(crashReportCategory); +- throw new ReportedException(crashReport); ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Checking entity block collision"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being checked for collision"); ++ ++ this.fillCrashReportCategory(crashreportsystemdetails); ++ throw new ReportedException(crashreport); + } + } + +@@ -788,8 +1011,10 @@ + this.gameEvent(GameEvent.FLAP); + } + } ++ + } + ++ /** @deprecated */ + @Deprecated + public BlockPos getOnPosLegacy() { + return this.getOnPos(0.2F); +@@ -805,66 +1030,64 @@ + + protected BlockPos getOnPos(float yOffset) { + if (this.mainSupportingBlockPos.isPresent()) { +- BlockPos blockPos = this.mainSupportingBlockPos.get(); +- if (!(yOffset > 1.0E-5F)) { +- return blockPos; ++ BlockPos blockposition = (BlockPos) this.mainSupportingBlockPos.get(); ++ ++ if (yOffset <= 1.0E-5F) { ++ return blockposition; + } else { +- BlockState blockState = this.level().getBlockState(blockPos); +- return (!((double)yOffset <= 0.5) || !blockState.is(BlockTags.FENCES)) +- && !blockState.is(BlockTags.WALLS) +- && !(blockState.getBlock() instanceof FenceGateBlock) +- ? blockPos.atY(Mth.floor(this.position.y - (double)yOffset)) +- : blockPos; ++ IBlockData iblockdata = this.level().getBlockState(blockposition); ++ ++ return ((double) yOffset > 0.5D || !iblockdata.is(BlockTags.FENCES)) && !iblockdata.is(BlockTags.WALLS) && !(iblockdata.getBlock() instanceof FenceGateBlock) ? blockposition.atY(Mth.floor(this.position.y - (double) yOffset)) : blockposition; + } + } else { +- int floor = Mth.floor(this.position.x); +- int floor1 = Mth.floor(this.position.y - (double)yOffset); +- int floor2 = Mth.floor(this.position.z); +- return new BlockPos(floor, floor1, floor2); ++ int i = Mth.floor(this.position.x); ++ int j = Mth.floor(this.position.y - (double) yOffset); ++ int k = Mth.floor(this.position.z); ++ ++ return new BlockPos(i, j, k); + } + } + + protected float getBlockJumpFactor() { +- float jumpFactor = this.level().getBlockState(this.blockPosition()).getBlock().getJumpFactor(); +- float jumpFactor1 = this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getJumpFactor(); +- return (double)jumpFactor == 1.0 ? jumpFactor1 : jumpFactor; ++ float f = this.level().getBlockState(this.blockPosition()).getBlock().getJumpFactor(); ++ float f1 = this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getJumpFactor(); ++ ++ return (double) f == 1.0D ? f1 : f; + } + + protected float getBlockSpeedFactor() { +- BlockState blockState = this.level().getBlockState(this.blockPosition()); +- float speedFactor = blockState.getBlock().getSpeedFactor(); +- if (!blockState.is(Blocks.WATER) && !blockState.is(Blocks.BUBBLE_COLUMN)) { +- return (double)speedFactor == 1.0 +- ? this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getSpeedFactor() +- : speedFactor; +- } else { +- return speedFactor; +- } ++ IBlockData iblockdata = this.level().getBlockState(this.blockPosition()); ++ float f = iblockdata.getBlock().getSpeedFactor(); ++ ++ return !iblockdata.is(Blocks.WATER) && !iblockdata.is(Blocks.BUBBLE_COLUMN) ? ((double) f == 1.0D ? this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getSpeedFactor() : f) : f; + } + +- protected Vec3 maybeBackOffFromEdge(Vec3 vec, MoverType mover) { ++ protected Vec3 maybeBackOffFromEdge(Vec3 vec, EnumMoveType mover) { + return vec; + } + + protected Vec3 limitPistonMovement(Vec3 pos) { +- if (pos.lengthSqr() <= 1.0E-7) { ++ if (pos.lengthSqr() <= 1.0E-7D) { + return pos; + } else { +- long gameTime = this.level().getGameTime(); +- if (gameTime != this.pistonDeltasGameTime) { +- Arrays.fill(this.pistonDeltas, 0.0); +- this.pistonDeltasGameTime = gameTime; ++ long i = this.level().getGameTime(); ++ ++ if (i != this.pistonDeltasGameTime) { ++ Arrays.fill(this.pistonDeltas, 0.0D); ++ this.pistonDeltasGameTime = i; + } + +- if (pos.x != 0.0) { +- double d = this.applyPistonMovementRestriction(Direction.Axis.X, pos.x); +- return Math.abs(d) <= 1.0E-5F ? Vec3.ZERO : new Vec3(d, 0.0, 0.0); +- } else if (pos.y != 0.0) { +- double d = this.applyPistonMovementRestriction(Direction.Axis.Y, pos.y); +- return Math.abs(d) <= 1.0E-5F ? Vec3.ZERO : new Vec3(0.0, d, 0.0); +- } else if (pos.z != 0.0) { +- double d = this.applyPistonMovementRestriction(Direction.Axis.Z, pos.z); +- return Math.abs(d) <= 1.0E-5F ? Vec3.ZERO : new Vec3(0.0, 0.0, d); ++ double d0; ++ ++ if (pos.x != 0.0D) { ++ d0 = this.applyPistonMovementRestriction(Direction.Axis.X, pos.x); ++ return Math.abs(d0) <= 9.999999747378752E-6D ? Vec3.ZERO : new Vec3(d0, 0.0D, 0.0D); ++ } else if (pos.y != 0.0D) { ++ d0 = this.applyPistonMovementRestriction(Direction.Axis.Y, pos.y); ++ return Math.abs(d0) <= 9.999999747378752E-6D ? Vec3.ZERO : new Vec3(0.0D, d0, 0.0D); ++ } else if (pos.z != 0.0D) { ++ d0 = this.applyPistonMovementRestriction(Direction.Axis.Z, pos.z); ++ return Math.abs(d0) <= 9.999999747378752E-6D ? Vec3.ZERO : new Vec3(0.0D, 0.0D, d0); + } else { + return Vec3.ZERO; + } +@@ -873,50 +1096,54 @@ + + private double applyPistonMovementRestriction(Direction.Axis axis, double distance) { + int i = axis.ordinal(); +- double d = Mth.clamp(distance + this.pistonDeltas[i], -0.51, 0.51); +- distance = d - this.pistonDeltas[i]; +- this.pistonDeltas[i] = d; ++ double d1 = Mth.clamp(distance + this.pistonDeltas[i], -0.51D, 0.51D); ++ ++ distance = d1 - this.pistonDeltas[i]; ++ this.pistonDeltas[i] = d1; + return distance; + } + + private Vec3 collide(Vec3 vec) { +- AABB boundingBox = this.getBoundingBox(); +- List entityCollisions = this.level().getEntityCollisions(this, boundingBox.expandTowards(vec)); +- Vec3 vec3 = vec.lengthSqr() == 0.0 ? vec : collideBoundingBox(this, vec, boundingBox, this.level(), entityCollisions); +- boolean flag = vec.x != vec3.x; +- boolean flag1 = vec.y != vec3.y; +- boolean flag2 = vec.z != vec3.z; +- boolean flag3 = this.onGround() || flag1 && vec.y < 0.0; ++ AABB axisalignedbb = this.getBoundingBox(); ++ List list = this.level().getEntityCollisions(this, axisalignedbb.expandTowards(vec)); ++ Vec3 vec3d1 = vec.lengthSqr() == 0.0D ? vec : collideBoundingBox(this, vec, axisalignedbb, this.level(), list); ++ boolean flag = vec.x != vec3d1.x; ++ boolean flag1 = vec.y != vec3d1.y; ++ boolean flag2 = vec.z != vec3d1.z; ++ boolean flag3 = this.onGround() || flag1 && vec.y < 0.0D; ++ + if (this.maxUpStep() > 0.0F && flag3 && (flag || flag2)) { +- Vec3 vec31 = collideBoundingBox(this, new Vec3(vec.x, (double)this.maxUpStep(), vec.z), boundingBox, this.level(), entityCollisions); +- Vec3 vec32 = collideBoundingBox( +- this, new Vec3(0.0, (double)this.maxUpStep(), 0.0), boundingBox.expandTowards(vec.x, 0.0, vec.z), this.level(), entityCollisions +- ); +- if (vec32.y < (double)this.maxUpStep()) { +- Vec3 vec33 = collideBoundingBox(this, new Vec3(vec.x, 0.0, vec.z), boundingBox.move(vec32), this.level(), entityCollisions).add(vec32); +- if (vec33.horizontalDistanceSqr() > vec31.horizontalDistanceSqr()) { +- vec31 = vec33; ++ Vec3 vec3d2 = collideBoundingBox(this, new Vec3(vec.x, (double) this.maxUpStep(), vec.z), axisalignedbb, this.level(), list); ++ Vec3 vec3d3 = collideBoundingBox(this, new Vec3(0.0D, (double) this.maxUpStep(), 0.0D), axisalignedbb.expandTowards(vec.x, 0.0D, vec.z), this.level(), list); ++ ++ if (vec3d3.y < (double) this.maxUpStep()) { ++ Vec3 vec3d4 = collideBoundingBox(this, new Vec3(vec.x, 0.0D, vec.z), axisalignedbb.move(vec3d3), this.level(), list).add(vec3d3); ++ ++ if (vec3d4.horizontalDistanceSqr() > vec3d2.horizontalDistanceSqr()) { ++ vec3d2 = vec3d4; + } + } + +- if (vec31.horizontalDistanceSqr() > vec3.horizontalDistanceSqr()) { +- return vec31.add(collideBoundingBox(this, new Vec3(0.0, -vec31.y + vec.y, 0.0), boundingBox.move(vec31), this.level(), entityCollisions)); ++ if (vec3d2.horizontalDistanceSqr() > vec3d1.horizontalDistanceSqr()) { ++ return vec3d2.add(collideBoundingBox(this, new Vec3(0.0D, -vec3d2.y + vec.y, 0.0D), axisalignedbb.move(vec3d2), this.level(), list)); + } + } + +- return vec3; ++ return vec3d1; + } + + public static Vec3 collideBoundingBox(@Nullable Entity entity, Vec3 vec, AABB collisionBox, Level level, List potentialHits) { + Builder builder = ImmutableList.builderWithExpectedSize(potentialHits.size() + 1); ++ + if (!potentialHits.isEmpty()) { + builder.addAll(potentialHits); + } + +- WorldBorder worldBorder = level.getWorldBorder(); +- boolean flag = entity != null && worldBorder.isInsideCloseToBorder(entity, collisionBox.expandTowards(vec)); ++ WorldBorder worldborder = level.getWorldBorder(); ++ boolean flag = entity != null && worldborder.isInsideCloseToBorder(entity, collisionBox.expandTowards(vec)); ++ + if (flag) { +- builder.add(worldBorder.getCollisionShape()); ++ builder.add(worldborder.getCollisionShape()); + } + + builder.addAll(level.getBlockCollisions(entity, collisionBox.expandTowards(vec))); +@@ -927,41 +1154,43 @@ + if (shapes.isEmpty()) { + return deltaMovement; + } else { +- double d = deltaMovement.x; ++ double d0 = deltaMovement.x; + double d1 = deltaMovement.y; + double d2 = deltaMovement.z; +- if (d1 != 0.0) { ++ ++ if (d1 != 0.0D) { + d1 = Shapes.collide(Direction.Axis.Y, entityBB, shapes, d1); +- if (d1 != 0.0) { +- entityBB = entityBB.move(0.0, d1, 0.0); ++ if (d1 != 0.0D) { ++ entityBB = entityBB.move(0.0D, d1, 0.0D); + } + } + +- boolean flag = Math.abs(d) < Math.abs(d2); +- if (flag && d2 != 0.0) { ++ boolean flag = Math.abs(d0) < Math.abs(d2); ++ ++ if (flag && d2 != 0.0D) { + d2 = Shapes.collide(Direction.Axis.Z, entityBB, shapes, d2); +- if (d2 != 0.0) { +- entityBB = entityBB.move(0.0, 0.0, d2); ++ if (d2 != 0.0D) { ++ entityBB = entityBB.move(0.0D, 0.0D, d2); + } + } + +- if (d != 0.0) { +- d = Shapes.collide(Direction.Axis.X, entityBB, shapes, d); +- if (!flag && d != 0.0) { +- entityBB = entityBB.move(d, 0.0, 0.0); ++ if (d0 != 0.0D) { ++ d0 = Shapes.collide(Direction.Axis.X, entityBB, shapes, d0); ++ if (!flag && d0 != 0.0D) { ++ entityBB = entityBB.move(d0, 0.0D, 0.0D); + } + } + +- if (!flag && d2 != 0.0) { ++ if (!flag && d2 != 0.0D) { + d2 = Shapes.collide(Direction.Axis.Z, entityBB, shapes, d2); + } + +- return new Vec3(d, d1, d2); ++ return new Vec3(d0, d1, d2); + } + } + + protected float nextStep() { +- return (float)((int)this.moveDist + 1); ++ return (float) ((int) this.moveDist + 1); + } + + protected SoundEvent getSwimSound() { +@@ -976,41 +1205,57 @@ + return SoundEvents.GENERIC_SPLASH; + } + ++ // CraftBukkit start - Add delegate methods ++ public SoundEvent getSwimSound0() { ++ return getSwimSound(); ++ } ++ ++ public SoundEvent getSwimSplashSound0() { ++ return getSwimSplashSound(); ++ } ++ ++ public SoundEvent getSwimHighSpeedSplashSound0() { ++ return getSwimHighSpeedSplashSound(); ++ } ++ // CraftBukkit end ++ + protected void checkInsideBlocks() { +- AABB boundingBox = this.getBoundingBox(); +- BlockPos blockPos = BlockPos.containing(boundingBox.minX + 1.0E-7, boundingBox.minY + 1.0E-7, boundingBox.minZ + 1.0E-7); +- BlockPos blockPos1 = BlockPos.containing(boundingBox.maxX - 1.0E-7, boundingBox.maxY - 1.0E-7, boundingBox.maxZ - 1.0E-7); +- if (this.level().hasChunksAt(blockPos, blockPos1)) { +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ AABB axisalignedbb = this.getBoundingBox(); ++ BlockPos blockposition = BlockPos.containing(axisalignedbb.minX + 1.0E-7D, axisalignedbb.minY + 1.0E-7D, axisalignedbb.minZ + 1.0E-7D); ++ BlockPos blockposition1 = BlockPos.containing(axisalignedbb.maxX - 1.0E-7D, axisalignedbb.maxY - 1.0E-7D, axisalignedbb.maxZ - 1.0E-7D); + +- for (int x = blockPos.getX(); x <= blockPos1.getX(); x++) { +- for (int y = blockPos.getY(); y <= blockPos1.getY(); y++) { +- for (int z = blockPos.getZ(); z <= blockPos1.getZ(); z++) { ++ if (this.level().hasChunksAt(blockposition, blockposition1)) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ ++ for (int i = blockposition.getX(); i <= blockposition1.getX(); ++i) { ++ for (int j = blockposition.getY(); j <= blockposition1.getY(); ++j) { ++ for (int k = blockposition.getZ(); k <= blockposition1.getZ(); ++k) { + if (!this.isAlive()) { + return; + } + +- mutableBlockPos.set(x, y, z); +- BlockState blockState = this.level().getBlockState(mutableBlockPos); ++ blockposition_mutableblockposition.set(i, j, k); ++ IBlockData iblockdata = this.level().getBlockState(blockposition_mutableblockposition); + + try { +- blockState.entityInside(this.level(), mutableBlockPos, this); +- this.onInsideBlock(blockState); +- } catch (Throwable var12) { +- CrashReport crashReport = CrashReport.forThrowable(var12, "Colliding entity with block"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Block being collided with"); +- CrashReportCategory.populateBlockDetails(crashReportCategory, this.level(), mutableBlockPos, blockState); +- throw new ReportedException(crashReport); ++ iblockdata.entityInside(this.level(), blockposition_mutableblockposition, this); ++ this.onInsideBlock(iblockdata); ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Colliding entity with block"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being collided with"); ++ ++ CrashReportCategory.populateBlockDetails(crashreportsystemdetails, this.level(), blockposition_mutableblockposition, iblockdata); ++ throw new ReportedException(crashreport); + } + } + } + } + } +- } + +- protected void onInsideBlock(BlockState state) { + } + ++ protected void onInsideBlock(IBlockData state) {} ++ + public void gameEvent(GameEvent event, @Nullable Entity entity) { + this.level().gameEvent(entity, event, this.position); + } +@@ -1019,54 +1264,59 @@ + this.gameEvent(event, this); + } + +- private void walkingStepSound(BlockPos pos, BlockState state) { ++ private void walkingStepSound(BlockPos pos, IBlockData state) { + this.playStepSound(pos, state); + if (this.shouldPlayAmethystStepSound(state)) { + this.playAmethystStepSound(); + } ++ + } + + protected void waterSwimSound() { +- Entity entity = Objects.requireNonNullElse(this.getControllingPassenger(), this); ++ Entity entity = (Entity) Objects.requireNonNullElse(this.getControllingPassenger(), this); + float f = entity == this ? 0.35F : 0.4F; +- Vec3 deltaMovement = entity.getDeltaMovement(); +- float min = Math.min( +- 1.0F, (float)Math.sqrt(deltaMovement.x * deltaMovement.x * 0.2F + deltaMovement.y * deltaMovement.y + deltaMovement.z * deltaMovement.z * 0.2F) * f +- ); +- this.playSwimSound(min); ++ Vec3 vec3d = entity.getDeltaMovement(); ++ float f1 = Math.min(1.0F, (float) Math.sqrt(vec3d.x * vec3d.x * 0.20000000298023224D + vec3d.y * vec3d.y + vec3d.z * vec3d.z * 0.20000000298023224D) * f); ++ ++ this.playSwimSound(f1); + } + + protected BlockPos getPrimaryStepSoundBlockPos(BlockPos pos) { +- BlockPos blockPos = pos.above(); +- BlockState blockState = this.level().getBlockState(blockPos); +- return !blockState.is(BlockTags.INSIDE_STEP_SOUND_BLOCKS) && !blockState.is(BlockTags.COMBINATION_STEP_SOUND_BLOCKS) ? pos : blockPos; ++ BlockPos blockposition1 = pos.above(); ++ IBlockData iblockdata = this.level().getBlockState(blockposition1); ++ ++ return !iblockdata.is(BlockTags.INSIDE_STEP_SOUND_BLOCKS) && !iblockdata.is(BlockTags.COMBINATION_STEP_SOUND_BLOCKS) ? pos : blockposition1; + } + +- protected void playCombinationStepSounds(BlockState primaryState, BlockState secondaryState) { +- SoundType soundType = primaryState.getSoundType(); +- this.playSound(soundType.getStepSound(), soundType.getVolume() * 0.15F, soundType.getPitch()); ++ protected void playCombinationStepSounds(IBlockData primaryState, IBlockData secondaryState) { ++ SoundType soundeffecttype = primaryState.getSoundType(); ++ ++ this.playSound(soundeffecttype.getStepSound(), soundeffecttype.getVolume() * 0.15F, soundeffecttype.getPitch()); + this.playMuffledStepSound(secondaryState); + } + +- protected void playMuffledStepSound(BlockState state) { +- SoundType soundType = state.getSoundType(); +- this.playSound(soundType.getStepSound(), soundType.getVolume() * 0.05F, soundType.getPitch() * 0.8F); ++ protected void playMuffledStepSound(IBlockData state) { ++ SoundType soundeffecttype = state.getSoundType(); ++ ++ this.playSound(soundeffecttype.getStepSound(), soundeffecttype.getVolume() * 0.05F, soundeffecttype.getPitch() * 0.8F); + } + +- protected void playStepSound(BlockPos pos, BlockState state) { +- SoundType soundType = state.getSoundType(); +- this.playSound(soundType.getStepSound(), soundType.getVolume() * 0.15F, soundType.getPitch()); ++ protected void playStepSound(BlockPos pos, IBlockData state) { ++ SoundType soundeffecttype = state.getSoundType(); ++ ++ this.playSound(soundeffecttype.getStepSound(), soundeffecttype.getVolume() * 0.15F, soundeffecttype.getPitch()); + } + +- private boolean shouldPlayAmethystStepSound(BlockState state) { ++ private boolean shouldPlayAmethystStepSound(IBlockData state) { + return state.is(BlockTags.CRYSTAL_SOUND_BLOCKS) && this.tickCount >= this.lastCrystalSoundPlayTick + 20; + } + + private void playAmethystStepSound() { +- this.crystalSoundIntensity = this.crystalSoundIntensity * (float)Math.pow(0.997, (double)(this.tickCount - this.lastCrystalSoundPlayTick)); ++ this.crystalSoundIntensity *= (float) Math.pow(0.997D, (double) (this.tickCount - this.lastCrystalSoundPlayTick)); + this.crystalSoundIntensity = Math.min(1.0F, this.crystalSoundIntensity + 0.07F); + float f = 0.5F + this.crystalSoundIntensity * this.random.nextFloat() * 1.2F; + float f1 = 0.1F + this.crystalSoundIntensity * 1.2F; ++ + this.playSound(SoundEvents.AMETHYST_BLOCK_CHIME, f1, f); + this.lastCrystalSoundPlayTick = this.tickCount; + } +@@ -1075,8 +1325,7 @@ + this.playSound(this.getSwimSound(), volume, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); + } + +- protected void onFlap() { +- } ++ protected void onFlap() {} + + protected boolean isFlapping() { + return false; +@@ -1084,30 +1333,32 @@ + + public void playSound(SoundEvent sound, float volume, float pitch) { + if (!this.isSilent()) { +- this.level().playSound(null, this.getX(), this.getY(), this.getZ(), sound, this.getSoundSource(), volume, pitch); ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), sound, this.getSoundSource(), volume, pitch); + } ++ + } + + public void playSound(SoundEvent sound) { + if (!this.isSilent()) { + this.playSound(sound, 1.0F, 1.0F); + } ++ + } + + public boolean isSilent() { +- return this.entityData.get(DATA_SILENT); ++ return (Boolean) this.entityData.get(Entity.DATA_SILENT); + } + + public void setSilent(boolean isSilent) { +- this.entityData.set(DATA_SILENT, isSilent); ++ this.entityData.set(Entity.DATA_SILENT, isSilent); + } + + public boolean isNoGravity() { +- return this.entityData.get(DATA_NO_GRAVITY); ++ return (Boolean) this.entityData.get(Entity.DATA_NO_GRAVITY); + } + + public void setNoGravity(boolean noGravity) { +- this.entityData.set(DATA_NO_GRAVITY, noGravity); ++ this.entityData.set(Entity.DATA_NO_GRAVITY, noGravity); + } + + protected Entity.MovementEmission getMovementEmission() { +@@ -1118,22 +1369,20 @@ + return false; + } + +- protected void checkFallDamage(double y, boolean onGround, BlockState state, BlockPos pos) { +- if (onGround) { ++ protected void checkFallDamage(double y, boolean flag, IBlockData onGround, BlockPos state) { ++ if (flag) { + if (this.fallDistance > 0.0F) { +- state.getBlock().fallOn(this.level(), state, pos, this, this.fallDistance); +- this.level() +- .gameEvent( +- GameEvent.HIT_GROUND, +- this.position, +- GameEvent.Context.of(this, this.mainSupportingBlockPos.map(blockPos -> this.level().getBlockState(blockPos)).orElse(state)) +- ); ++ onGround.getBlock().fallOn(this.level(), onGround, state, this, this.fallDistance); ++ this.level().gameEvent(GameEvent.HIT_GROUND, this.position, GameEvent.Context.of(this, (IBlockData) this.mainSupportingBlockPos.map((blockposition1) -> { ++ return this.level().getBlockState(blockposition1); ++ }).orElse(onGround))); + } + + this.resetFallDistance(); +- } else if (y < 0.0) { +- this.fallDistance -= (float)y; ++ } else if (y < 0.0D) { ++ this.fallDistance -= (float) y; + } ++ + } + + public boolean fireImmune() { +@@ -1145,7 +1394,11 @@ + return false; + } else { + if (this.isVehicle()) { +- for (Entity entity : this.getPassengers()) { ++ Iterator iterator = this.getPassengers().iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ + entity.causeFallDamage(fallDistance, multiplier, source); + } + } +@@ -1159,9 +1412,9 @@ + } + + private boolean isInRain() { +- BlockPos blockPos = this.blockPosition(); +- return this.level().isRainingAt(blockPos) +- || this.level().isRainingAt(BlockPos.containing((double)blockPos.getX(), this.getBoundingBox().maxY, (double)blockPos.getZ())); ++ BlockPos blockposition = this.blockPosition(); ++ ++ return this.level().isRainingAt(blockposition) || this.level().isRainingAt(BlockPos.containing((double) blockposition.getX(), this.getBoundingBox().maxY, (double) blockposition.getZ())); + } + + private boolean isInBubbleColumn() { +@@ -1192,27 +1445,33 @@ + if (this.isSwimming()) { + this.setSwimming(this.isSprinting() && this.isInWater() && !this.isPassenger()); + } else { +- this.setSwimming( +- this.isSprinting() && this.isUnderWater() && !this.isPassenger() && this.level().getFluidState(this.blockPosition).is(FluidTags.WATER) +- ); ++ this.setSwimming(this.isSprinting() && this.isUnderWater() && !this.isPassenger() && this.level().getFluidState(this.blockPosition).is(FluidTags.WATER)); + } ++ + } + + protected boolean updateInWaterStateAndDoFluidPushing() { + this.fluidHeight.clear(); + this.updateInWaterStateAndDoWaterCurrentPushing(); +- double d = this.level().dimensionType().ultraWarm() ? 0.007 : 0.0023333333333333335; +- boolean flag = this.updateFluidHeightAndDoFluidPushing(FluidTags.LAVA, d); ++ double d0 = this.level().dimensionType().ultraWarm() ? 0.007D : 0.0023333333333333335D; ++ boolean flag = this.updateFluidHeightAndDoFluidPushing(FluidTags.LAVA, d0); ++ + return this.isInWater() || flag; + } + + void updateInWaterStateAndDoWaterCurrentPushing() { +- if (this.getVehicle() instanceof Boat boat && !boat.isUnderWater()) { +- this.wasTouchingWater = false; +- return; ++ Entity entity = this.getVehicle(); ++ ++ if (entity instanceof Boat) { ++ Boat entityboat = (Boat) entity; ++ ++ if (!entityboat.isUnderWater()) { ++ this.wasTouchingWater = false; ++ return; ++ } + } + +- if (this.updateFluidHeightAndDoFluidPushing(FluidTags.WATER, 0.014)) { ++ if (this.updateFluidHeightAndDoFluidPushing(FluidTags.WATER, 0.014D)) { + if (!this.wasTouchingWater && !this.firstTick) { + this.doWaterSplashEffect(); + } +@@ -1223,70 +1482,77 @@ + } else { + this.wasTouchingWater = false; + } ++ + } + + private void updateFluidOnEyes() { + this.wasEyeInWater = this.isEyeInFluid(FluidTags.WATER); + this.fluidOnEyes.clear(); +- double d = this.getEyeY() - 0.11111111F; +- if (this.getVehicle() instanceof Boat boat && !boat.isUnderWater() && boat.getBoundingBox().maxY >= d && boat.getBoundingBox().minY <= d) { +- return; ++ double d0 = this.getEyeY() - 0.1111111119389534D; ++ Entity entity = this.getVehicle(); ++ ++ if (entity instanceof Boat) { ++ Boat entityboat = (Boat) entity; ++ ++ if (!entityboat.isUnderWater() && entityboat.getBoundingBox().maxY >= d0 && entityboat.getBoundingBox().minY <= d0) { ++ return; ++ } + } + +- BlockPos blockPos = BlockPos.containing(this.getX(), d, this.getZ()); +- FluidState fluidState = this.level().getFluidState(blockPos); +- double d1 = (double)((float)blockPos.getY() + fluidState.getHeight(this.level(), blockPos)); +- if (d1 > d) { +- fluidState.getTags().forEach(this.fluidOnEyes::add); ++ BlockPos blockposition = BlockPos.containing(this.getX(), d0, this.getZ()); ++ FluidState fluid = this.level().getFluidState(blockposition); ++ double d1 = (double) ((float) blockposition.getY() + fluid.getHeight(this.level(), blockposition)); ++ ++ if (d1 > d0) { ++ Stream stream = fluid.getTags(); ++ Set set = this.fluidOnEyes; ++ ++ Objects.requireNonNull(this.fluidOnEyes); ++ stream.forEach(set::add); + } ++ + } + + protected void doWaterSplashEffect() { +- Entity entity = Objects.requireNonNullElse(this.getControllingPassenger(), this); ++ Entity entity = (Entity) Objects.requireNonNullElse(this.getControllingPassenger(), this); + float f = entity == this ? 0.2F : 0.9F; +- Vec3 deltaMovement = entity.getDeltaMovement(); +- float min = Math.min( +- 1.0F, (float)Math.sqrt(deltaMovement.x * deltaMovement.x * 0.2F + deltaMovement.y * deltaMovement.y + deltaMovement.z * deltaMovement.z * 0.2F) * f +- ); +- if (min < 0.25F) { +- this.playSound(this.getSwimSplashSound(), min, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); ++ Vec3 vec3d = entity.getDeltaMovement(); ++ float f1 = Math.min(1.0F, (float) Math.sqrt(vec3d.x * vec3d.x * 0.20000000298023224D + vec3d.y * vec3d.y + vec3d.z * vec3d.z * 0.20000000298023224D) * f); ++ ++ if (f1 < 0.25F) { ++ this.playSound(this.getSwimSplashSound(), f1, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); + } else { +- this.playSound(this.getSwimHighSpeedSplashSound(), min, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); ++ this.playSound(this.getSwimHighSpeedSplashSound(), f1, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); + } + +- float f1 = (float)Mth.floor(this.getY()); ++ float f2 = (float) Mth.floor(this.getY()); + +- for (int i = 0; (float)i < 1.0F + this.dimensions.width * 20.0F; i++) { +- double d = (this.random.nextDouble() * 2.0 - 1.0) * (double)this.dimensions.width; +- double d1 = (this.random.nextDouble() * 2.0 - 1.0) * (double)this.dimensions.width; +- this.level() +- .addParticle( +- ParticleTypes.BUBBLE, +- this.getX() + d, +- (double)(f1 + 1.0F), +- this.getZ() + d1, +- deltaMovement.x, +- deltaMovement.y - this.random.nextDouble() * 0.2F, +- deltaMovement.z +- ); ++ double d0; ++ double d1; ++ int i; ++ ++ for (i = 0; (float) i < 1.0F + this.dimensions.width * 20.0F; ++i) { ++ d0 = (this.random.nextDouble() * 2.0D - 1.0D) * (double) this.dimensions.width; ++ d1 = (this.random.nextDouble() * 2.0D - 1.0D) * (double) this.dimensions.width; ++ this.level().addParticle(ParticleTypes.BUBBLE, this.getX() + d0, (double) (f2 + 1.0F), this.getZ() + d1, vec3d.x, vec3d.y - this.random.nextDouble() * 0.20000000298023224D, vec3d.z); + } + +- for (int i = 0; (float)i < 1.0F + this.dimensions.width * 20.0F; i++) { +- double d = (this.random.nextDouble() * 2.0 - 1.0) * (double)this.dimensions.width; +- double d1 = (this.random.nextDouble() * 2.0 - 1.0) * (double)this.dimensions.width; +- this.level() +- .addParticle(ParticleTypes.SPLASH, this.getX() + d, (double)(f1 + 1.0F), this.getZ() + d1, deltaMovement.x, deltaMovement.y, deltaMovement.z); ++ for (i = 0; (float) i < 1.0F + this.dimensions.width * 20.0F; ++i) { ++ d0 = (this.random.nextDouble() * 2.0D - 1.0D) * (double) this.dimensions.width; ++ d1 = (this.random.nextDouble() * 2.0D - 1.0D) * (double) this.dimensions.width; ++ this.level().addParticle(ParticleTypes.SPLASH, this.getX() + d0, (double) (f2 + 1.0F), this.getZ() + d1, vec3d.x, vec3d.y, vec3d.z); + } + + this.gameEvent(GameEvent.SPLASH); + } + ++ /** @deprecated */ + @Deprecated +- protected BlockState getBlockStateOnLegacy() { ++ protected IBlockData getBlockStateOnLegacy() { + return this.level().getBlockState(this.getOnPosLegacy()); + } + +- public BlockState getBlockStateOn() { ++ public IBlockData getBlockStateOn() { + return this.level().getBlockState(this.getOnPos()); + } + +@@ -1295,26 +1561,26 @@ + } + + protected void spawnSprintParticle() { +- BlockPos onPosLegacy = this.getOnPosLegacy(); +- BlockState blockState = this.level().getBlockState(onPosLegacy); +- if (blockState.getRenderShape() != RenderShape.INVISIBLE) { +- Vec3 deltaMovement = this.getDeltaMovement(); +- BlockPos blockPos = this.blockPosition(); +- double d = this.getX() + (this.random.nextDouble() - 0.5) * (double)this.dimensions.width; +- double d1 = this.getZ() + (this.random.nextDouble() - 0.5) * (double)this.dimensions.width; +- if (blockPos.getX() != onPosLegacy.getX()) { +- d = Mth.clamp(d, (double)onPosLegacy.getX(), (double)onPosLegacy.getX() + 1.0); ++ BlockPos blockposition = this.getOnPosLegacy(); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); ++ ++ if (iblockdata.getRenderShape() != EnumRenderType.INVISIBLE) { ++ Vec3 vec3d = this.getDeltaMovement(); ++ BlockPos blockposition1 = this.blockPosition(); ++ double d0 = this.getX() + (this.random.nextDouble() - 0.5D) * (double) this.dimensions.width; ++ double d1 = this.getZ() + (this.random.nextDouble() - 0.5D) * (double) this.dimensions.width; ++ ++ if (blockposition1.getX() != blockposition.getX()) { ++ d0 = Mth.clamp(d0, (double) blockposition.getX(), (double) blockposition.getX() + 1.0D); + } + +- if (blockPos.getZ() != onPosLegacy.getZ()) { +- d1 = Mth.clamp(d1, (double)onPosLegacy.getZ(), (double)onPosLegacy.getZ() + 1.0); ++ if (blockposition1.getZ() != blockposition.getZ()) { ++ d1 = Mth.clamp(d1, (double) blockposition.getZ(), (double) blockposition.getZ() + 1.0D); + } + +- this.level() +- .addParticle( +- new BlockParticleOption(ParticleTypes.BLOCK, blockState), d, this.getY() + 0.1, d1, deltaMovement.x * -4.0, 1.5, deltaMovement.z * -4.0 +- ); ++ this.level().addParticle(new BlockParticleOption(ParticleTypes.BLOCK, iblockdata), d0, this.getY() + 0.1D, d1, vec3d.x * -4.0D, 1.5D, vec3d.z * -4.0D); + } ++ + } + + public boolean isEyeInFluid(TagKey fluidTag) { +@@ -1322,96 +1588,103 @@ + } + + public boolean isInLava() { +- return !this.firstTick && this.fluidHeight.getDouble(FluidTags.LAVA) > 0.0; ++ return !this.firstTick && this.fluidHeight.getDouble(FluidTags.LAVA) > 0.0D; + } + + public void moveRelative(float amount, Vec3 relative) { +- Vec3 inputVector = getInputVector(relative, amount, this.getYRot()); +- this.setDeltaMovement(this.getDeltaMovement().add(inputVector)); ++ Vec3 vec3d1 = getInputVector(relative, amount, this.getYRot()); ++ ++ this.setDeltaMovement(this.getDeltaMovement().add(vec3d1)); + } + + private static Vec3 getInputVector(Vec3 relative, float motionScaler, float facing) { +- double d = relative.lengthSqr(); +- if (d < 1.0E-7) { ++ double d0 = relative.lengthSqr(); ++ ++ if (d0 < 1.0E-7D) { + return Vec3.ZERO; + } else { +- Vec3 vec3 = (d > 1.0 ? relative.normalize() : relative).scale((double)motionScaler); +- float sin = Mth.sin(facing * (float) (Math.PI / 180.0)); +- float cos = Mth.cos(facing * (float) (Math.PI / 180.0)); +- return new Vec3(vec3.x * (double)cos - vec3.z * (double)sin, vec3.y, vec3.z * (double)cos + vec3.x * (double)sin); ++ Vec3 vec3d1 = (d0 > 1.0D ? relative.normalize() : relative).scale((double) motionScaler); ++ float f2 = Mth.sin(facing * 0.017453292F); ++ float f3 = Mth.cos(facing * 0.017453292F); ++ ++ return new Vec3(vec3d1.x * (double) f3 - vec3d1.z * (double) f2, vec3d1.y, vec3d1.z * (double) f3 + vec3d1.x * (double) f2); + } + } + ++ /** @deprecated */ + @Deprecated + public float getLightLevelDependentMagicValue() { +- return this.level().hasChunkAt(this.getBlockX(), this.getBlockZ()) +- ? this.level().getLightLevelDependentMagicValue(BlockPos.containing(this.getX(), this.getEyeY(), this.getZ())) +- : 0.0F; ++ return this.level().hasChunkAt(this.getBlockX(), this.getBlockZ()) ? this.level().getLightLevelDependentMagicValue(BlockPos.containing(this.getX(), this.getEyeY(), this.getZ())) : 0.0F; + } + +- public void absMoveTo(double x, double y, double z, float yRot, float xRot) { +- this.absMoveTo(x, y, z); +- this.setYRot(yRot % 360.0F); +- this.setXRot(Mth.clamp(xRot, -90.0F, 90.0F) % 360.0F); ++ public void absMoveTo(double x, double d1, double y, float f, float z) { ++ this.absMoveTo(x, d1, y); ++ this.setYRot(f % 360.0F); ++ this.setXRot(Mth.clamp(z, -90.0F, 90.0F) % 360.0F); + this.yRotO = this.getYRot(); + this.xRotO = this.getXRot(); + } + +- public void absMoveTo(double x, double y, double z) { +- double d = Mth.clamp(x, -3.0E7, 3.0E7); +- double d1 = Mth.clamp(z, -3.0E7, 3.0E7); +- this.xo = d; +- this.yo = y; +- this.zo = d1; +- this.setPos(d, y, d1); ++ public void absMoveTo(double x, double d1, double y) { ++ double d3 = Mth.clamp(x, -3.0E7D, 3.0E7D); ++ double d4 = Mth.clamp(y, -3.0E7D, 3.0E7D); ++ ++ this.xo = d3; ++ this.yo = d1; ++ this.zo = d4; ++ this.setPos(d3, d1, d4); ++ if (valid) level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit + } + + public void moveTo(Vec3 vec) { + this.moveTo(vec.x, vec.y, vec.z); + } + +- public void moveTo(double x, double y, double z) { +- this.moveTo(x, y, z, this.getYRot(), this.getXRot()); ++ public void moveTo(double x, double d1, double y) { ++ this.moveTo(x, d1, y, this.getYRot(), this.getXRot()); + } + + public void moveTo(BlockPos pos, float yRot, float xRot) { +- this.moveTo((double)pos.getX() + 0.5, (double)pos.getY(), (double)pos.getZ() + 0.5, yRot, xRot); ++ this.moveTo((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, yRot, xRot); + } + +- public void moveTo(double x, double y, double z, float yRot, float xRot) { +- this.setPosRaw(x, y, z); +- this.setYRot(yRot); +- this.setXRot(xRot); ++ public void moveTo(double x, double d1, double y, float f, float z) { ++ this.setPosRaw(x, d1, y); ++ this.setYRot(f); ++ this.setXRot(z); + this.setOldPosAndRot(); + this.reapplyPosition(); + } + + public final void setOldPosAndRot() { +- double x = this.getX(); +- double y = this.getY(); +- double z = this.getZ(); +- this.xo = x; +- this.yo = y; +- this.zo = z; +- this.xOld = x; +- this.yOld = y; +- this.zOld = z; ++ double d0 = this.getX(); ++ double d1 = this.getY(); ++ double d2 = this.getZ(); ++ ++ this.xo = d0; ++ this.yo = d1; ++ this.zo = d2; ++ this.xOld = d0; ++ this.yOld = d1; ++ this.zOld = d2; + this.yRotO = this.getYRot(); + this.xRotO = this.getXRot(); + } + + public float distanceTo(Entity entity) { +- float f = (float)(this.getX() - entity.getX()); +- float f1 = (float)(this.getY() - entity.getY()); +- float f2 = (float)(this.getZ() - entity.getZ()); ++ float f = (float) (this.getX() - entity.getX()); ++ float f1 = (float) (this.getY() - entity.getY()); ++ float f2 = (float) (this.getZ() - entity.getZ()); ++ + return Mth.sqrt(f * f + f1 * f1 + f2 * f2); + } + +- public double distanceToSqr(double x, double y, double z) { +- double d = this.getX() - x; +- double d1 = this.getY() - y; +- double d2 = this.getZ() - z; +- return d * d + d1 * d1 + d2 * d2; ++ public double distanceToSqr(double x, double d1, double y) { ++ double d3 = this.getX() - x; ++ double d4 = this.getY() - d1; ++ double d5 = this.getZ() - y; ++ ++ return d3 * d3 + d4 * d4 + d5 * d5; + } + + public double distanceToSqr(Entity entity) { +@@ -1419,48 +1692,51 @@ + } + + public double distanceToSqr(Vec3 vec) { +- double d = this.getX() - vec.x; ++ double d0 = this.getX() - vec.x; + double d1 = this.getY() - vec.y; + double d2 = this.getZ() - vec.z; +- return d * d + d1 * d1 + d2 * d2; +- } + +- public void playerTouch(Player player) { ++ return d0 * d0 + d1 * d1 + d2 * d2; + } + ++ public void playerTouch(Player player) {} ++ + public void push(Entity entity) { + if (!this.isPassengerOfSameVehicle(entity)) { + if (!entity.noPhysics && !this.noPhysics) { +- double d = entity.getX() - this.getX(); ++ double d0 = entity.getX() - this.getX(); + double d1 = entity.getZ() - this.getZ(); +- double max = Mth.absMax(d, d1); +- if (max >= 0.01F) { +- max = Math.sqrt(max); +- double var10 = d / max; +- double var13 = d1 / max; +- double d2 = 1.0 / max; +- if (d2 > 1.0) { +- d2 = 1.0; ++ double d2 = Mth.absMax(d0, d1); ++ ++ if (d2 >= 0.009999999776482582D) { ++ d2 = Math.sqrt(d2); ++ d0 /= d2; ++ d1 /= d2; ++ double d3 = 1.0D / d2; ++ ++ if (d3 > 1.0D) { ++ d3 = 1.0D; + } + +- d = var10 * d2; +- d1 = var13 * d2; +- double var12 = d * 0.05F; +- double var15 = d1 * 0.05F; ++ d0 *= d3; ++ d1 *= d3; ++ d0 *= 0.05000000074505806D; ++ d1 *= 0.05000000074505806D; + if (!this.isVehicle() && this.isPushable()) { +- this.push(-var12, 0.0, -var15); ++ this.push(-d0, 0.0D, -d1); + } + + if (!entity.isVehicle() && entity.isPushable()) { +- entity.push(var12, 0.0, var15); ++ entity.push(d0, 0.0D, d1); + } + } ++ + } + } + } + +- public void push(double x, double y, double z) { +- this.setDeltaMovement(this.getDeltaMovement().add(x, y, z)); ++ public void push(double x, double d1, double y) { ++ this.setDeltaMovement(this.getDeltaMovement().add(x, d1, y)); + this.hasImpulse = true; + } + +@@ -1490,13 +1766,14 @@ + } + + protected final Vec3 calculateViewVector(float xRot, float yRot) { +- float f = xRot * (float) (Math.PI / 180.0); +- float f1 = -yRot * (float) (Math.PI / 180.0); +- float cos = Mth.cos(f1); +- float sin = Mth.sin(f1); +- float cos1 = Mth.cos(f); +- float sin1 = Mth.sin(f); +- return new Vec3((double)(sin * cos1), (double)(-sin1), (double)(cos * cos1)); ++ float f2 = xRot * 0.017453292F; ++ float f3 = -yRot * 0.017453292F; ++ float f4 = Mth.cos(f3); ++ float f5 = Mth.sin(f3); ++ float f6 = Mth.cos(f2); ++ float f7 = Mth.sin(f2); ++ ++ return new Vec3((double) (f5 * f6), (double) (-f7), (double) (f4 * f6)); + } + + public final Vec3 getUpVector(float partialTicks) { +@@ -1512,10 +1789,11 @@ + } + + public final Vec3 getEyePosition(float partialTicks) { +- double d = Mth.lerp((double)partialTicks, this.xo, this.getX()); +- double d1 = Mth.lerp((double)partialTicks, this.yo, this.getY()) + (double)this.getEyeHeight(); +- double d2 = Mth.lerp((double)partialTicks, this.zo, this.getZ()); +- return new Vec3(d, d1, d2); ++ double d0 = Mth.lerp((double) partialTicks, this.xo, this.getX()); ++ double d1 = Mth.lerp((double) partialTicks, this.yo, this.getY()) + (double) this.getEyeHeight(); ++ double d2 = Mth.lerp((double) partialTicks, this.zo, this.getZ()); ++ ++ return new Vec3(d0, d1, d2); + } + + public Vec3 getLightProbePosition(float partialTicks) { +@@ -1523,18 +1801,19 @@ + } + + public final Vec3 getPosition(float partialTicks) { +- double d = Mth.lerp((double)partialTicks, this.xo, this.getX()); +- double d1 = Mth.lerp((double)partialTicks, this.yo, this.getY()); +- double d2 = Mth.lerp((double)partialTicks, this.zo, this.getZ()); +- return new Vec3(d, d1, d2); ++ double d0 = Mth.lerp((double) partialTicks, this.xo, this.getX()); ++ double d1 = Mth.lerp((double) partialTicks, this.yo, this.getY()); ++ double d2 = Mth.lerp((double) partialTicks, this.zo, this.getZ()); ++ ++ return new Vec3(d0, d1, d2); + } + +- public HitResult pick(double hitDistance, float partialTicks, boolean hitFluids) { +- Vec3 eyePosition = this.getEyePosition(partialTicks); +- Vec3 viewVector = this.getViewVector(partialTicks); +- Vec3 vec3 = eyePosition.add(viewVector.x * hitDistance, viewVector.y * hitDistance, viewVector.z * hitDistance); +- return this.level() +- .clip(new ClipContext(eyePosition, vec3, ClipContext.Block.OUTLINE, hitFluids ? ClipContext.Fluid.ANY : ClipContext.Fluid.NONE, this)); ++ public HitResult pick(double hitDistance, float f, boolean partialTicks) { ++ Vec3 vec3d = this.getEyePosition(f); ++ Vec3 vec3d1 = this.getViewVector(f); ++ Vec3 vec3d2 = vec3d.add(vec3d1.x * hitDistance, vec3d1.y * hitDistance, vec3d1.z * hitDistance); ++ ++ return this.level().clip(new ClipContext(vec3d, vec3d2, ClipContext.Block.OUTLINE, partialTicks ? ClipContext.Fluid.ANY : ClipContext.Fluid.NONE, this)); + } + + public boolean canBeHitByProjectile() { +@@ -1549,151 +1828,224 @@ + return false; + } + ++ // CraftBukkit start - collidable API ++ public boolean canCollideWithBukkit(Entity entity) { ++ return isPushable(); ++ } ++ // CraftBukkit end ++ + public void awardKillScore(Entity killed, int scoreValue, DamageSource source) { + if (killed instanceof ServerPlayer) { +- CriteriaTriggers.ENTITY_KILLED_PLAYER.trigger((ServerPlayer)killed, this, source); ++ CriteriaTriggers.ENTITY_KILLED_PLAYER.trigger((ServerPlayer) killed, this, source); + } ++ + } + +- public boolean shouldRender(double x, double y, double z) { +- double d = this.getX() - x; +- double d1 = this.getY() - y; +- double d2 = this.getZ() - z; +- double d3 = d * d + d1 * d1 + d2 * d2; +- return this.shouldRenderAtSqrDistance(d3); ++ public boolean shouldRender(double x, double d1, double y) { ++ double d3 = this.getX() - x; ++ double d4 = this.getY() - d1; ++ double d5 = this.getZ() - y; ++ double d6 = d3 * d3 + d4 * d4 + d5 * d5; ++ ++ return this.shouldRenderAtSqrDistance(d6); + } + + public boolean shouldRenderAtSqrDistance(double distance) { +- double size = this.getBoundingBox().getSize(); +- if (Double.isNaN(size)) { +- size = 1.0; ++ double d1 = this.getBoundingBox().getSize(); ++ ++ if (Double.isNaN(d1)) { ++ d1 = 1.0D; + } + +- size *= 64.0 * viewScale; +- return distance < size * size; ++ d1 *= 64.0D * Entity.viewScale; ++ return distance < d1 * d1; + } + + public boolean saveAsPassenger(CompoundTag compound) { ++ // CraftBukkit start - allow excluding certain data when saving ++ return saveAsPassenger(compound, true); ++ } ++ ++ public boolean saveAsPassenger(CompoundTag nbttagcompound, boolean includeAll) { ++ // CraftBukkit end + if (this.removalReason != null && !this.removalReason.shouldSave()) { + return false; + } else { +- String encodeId = this.getEncodeId(); +- if (encodeId == null) { ++ String s = this.getEncodeId(); ++ ++ if (!this.persist || s == null) { // CraftBukkit - persist flag + return false; + } else { +- compound.putString("id", encodeId); +- this.saveWithoutId(compound); ++ nbttagcompound.putString("id", s); ++ this.saveWithoutId(nbttagcompound, includeAll); // CraftBukkit - pass on includeAll + return true; + } + } + } + + public boolean save(CompoundTag compound) { +- return !this.isPassenger() && this.saveAsPassenger(compound); ++ return this.isPassenger() ? false : this.saveAsPassenger(compound); + } + + public CompoundTag saveWithoutId(CompoundTag compound) { ++ // CraftBukkit start - allow excluding certain data when saving ++ return saveWithoutId(compound, true); ++ } ++ ++ public CompoundTag saveWithoutId(CompoundTag nbttagcompound, boolean includeAll) { ++ // CraftBukkit end + try { +- if (this.vehicle != null) { +- compound.put("Pos", this.newDoubleList(this.vehicle.getX(), this.getY(), this.vehicle.getZ())); +- } else { +- compound.put("Pos", this.newDoubleList(this.getX(), this.getY(), this.getZ())); ++ // CraftBukkit start - selectively save position ++ if (includeAll) { ++ if (this.vehicle != null) { ++ nbttagcompound.put("Pos", this.newDoubleList(this.vehicle.getX(), this.getY(), this.vehicle.getZ())); ++ } else { ++ nbttagcompound.put("Pos", this.newDoubleList(this.getX(), this.getY(), this.getZ())); ++ } + } ++ // CraftBukkit end + +- Vec3 deltaMovement = this.getDeltaMovement(); +- compound.put("Motion", this.newDoubleList(deltaMovement.x, deltaMovement.y, deltaMovement.z)); +- compound.put("Rotation", this.newFloatList(this.getYRot(), this.getXRot())); +- compound.putFloat("FallDistance", this.fallDistance); +- compound.putShort("Fire", (short)this.remainingFireTicks); +- compound.putShort("Air", (short)this.getAirSupply()); +- compound.putBoolean("OnGround", this.onGround()); +- compound.putBoolean("Invulnerable", this.invulnerable); +- compound.putInt("PortalCooldown", this.portalCooldown); +- compound.putUUID("UUID", this.getUUID()); +- Component customName = this.getCustomName(); +- if (customName != null) { +- compound.putString("CustomName", Component.Serializer.toJson(customName)); ++ Vec3 vec3d = this.getDeltaMovement(); ++ ++ nbttagcompound.put("Motion", this.newDoubleList(vec3d.x, vec3d.y, vec3d.z)); ++ ++ // CraftBukkit start - Checking for NaN pitch/yaw and resetting to zero ++ // TODO: make sure this is the best way to address this. ++ if (Float.isNaN(this.yRot)) { ++ this.yRot = 0; + } + ++ if (Float.isNaN(this.xRot)) { ++ this.xRot = 0; ++ } ++ // CraftBukkit end ++ ++ nbttagcompound.put("Rotation", this.newFloatList(this.getYRot(), this.getXRot())); ++ nbttagcompound.putFloat("FallDistance", this.fallDistance); ++ nbttagcompound.putShort("Fire", (short) this.remainingFireTicks); ++ nbttagcompound.putShort("Air", (short) this.getAirSupply()); ++ nbttagcompound.putBoolean("OnGround", this.onGround()); ++ nbttagcompound.putBoolean("Invulnerable", this.invulnerable); ++ nbttagcompound.putInt("PortalCooldown", this.portalCooldown); ++ // CraftBukkit start - selectively save uuid and world ++ if (includeAll) { ++ nbttagcompound.putUUID("UUID", this.getUUID()); ++ // PAIL: Check above UUID reads 1.8 properly, ie: UUIDMost / UUIDLeast ++ nbttagcompound.putLong("WorldUUIDLeast", ((ServerLevel) this.level).getWorld().getUID().getLeastSignificantBits()); ++ nbttagcompound.putLong("WorldUUIDMost", ((ServerLevel) this.level).getWorld().getUID().getMostSignificantBits()); ++ } ++ nbttagcompound.putInt("Bukkit.updateLevel", CURRENT_LEVEL); ++ if (!this.persist) { ++ nbttagcompound.putBoolean("Bukkit.persist", this.persist); ++ } ++ if (!this.visibleByDefault) { ++ nbttagcompound.putBoolean("Bukkit.visibleByDefault", this.visibleByDefault); ++ } ++ if (this.persistentInvisibility) { ++ nbttagcompound.putBoolean("Bukkit.invisible", this.persistentInvisibility); ++ } ++ // SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ if (maxAirTicks != getDefaultMaxAirSupply()) { ++ nbttagcompound.putInt("Bukkit.MaxAirSupply", getMaxAirSupply()); ++ } ++ // CraftBukkit end ++ Component ichatbasecomponent = this.getCustomName(); ++ ++ if (ichatbasecomponent != null) { ++ nbttagcompound.putString("CustomName", Component.Serializer.toJson(ichatbasecomponent)); ++ } ++ + if (this.isCustomNameVisible()) { +- compound.putBoolean("CustomNameVisible", this.isCustomNameVisible()); ++ nbttagcompound.putBoolean("CustomNameVisible", this.isCustomNameVisible()); + } + + if (this.isSilent()) { +- compound.putBoolean("Silent", this.isSilent()); ++ nbttagcompound.putBoolean("Silent", this.isSilent()); + } + + if (this.isNoGravity()) { +- compound.putBoolean("NoGravity", this.isNoGravity()); ++ nbttagcompound.putBoolean("NoGravity", this.isNoGravity()); + } + + if (this.hasGlowingTag) { +- compound.putBoolean("Glowing", true); ++ nbttagcompound.putBoolean("Glowing", true); + } + +- int ticksFrozen = this.getTicksFrozen(); +- if (ticksFrozen > 0) { +- compound.putInt("TicksFrozen", this.getTicksFrozen()); ++ int i = this.getTicksFrozen(); ++ ++ if (i > 0) { ++ nbttagcompound.putInt("TicksFrozen", this.getTicksFrozen()); + } + + if (this.hasVisualFire) { +- compound.putBoolean("HasVisualFire", this.hasVisualFire); ++ nbttagcompound.putBoolean("HasVisualFire", this.hasVisualFire); + } + ++ ListTag nbttaglist; ++ Iterator iterator; ++ + if (!this.tags.isEmpty()) { +- ListTag list = new ListTag(); ++ nbttaglist = new ListTag(); ++ iterator = this.tags.iterator(); + +- for (String string : this.tags) { +- list.add(StringTag.valueOf(string)); ++ while (iterator.hasNext()) { ++ String s = (String) iterator.next(); ++ ++ nbttaglist.add(StringTag.valueOf(s)); + } + +- compound.put("Tags", list); ++ nbttagcompound.put("Tags", nbttaglist); + } + +- this.addAdditionalSaveData(compound); ++ this.addAdditionalSaveData(nbttagcompound, includeAll); // CraftBukkit - pass on includeAll + if (this.isVehicle()) { +- ListTag list = new ListTag(); ++ nbttaglist = new ListTag(); ++ iterator = this.getPassengers().iterator(); + +- for (Entity entity : this.getPassengers()) { +- CompoundTag compoundTag = new CompoundTag(); +- if (entity.saveAsPassenger(compoundTag)) { +- list.add(compoundTag); ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ CompoundTag nbttagcompound1 = new CompoundTag(); ++ ++ if (entity.saveAsPassenger(nbttagcompound1, includeAll)) { // CraftBukkit - pass on includeAll ++ nbttaglist.add(nbttagcompound1); + } + } + +- if (!list.isEmpty()) { +- compound.put("Passengers", list); ++ if (!nbttaglist.isEmpty()) { ++ nbttagcompound.put("Passengers", nbttaglist); + } + } + +- return compound; +- } catch (Throwable var9) { +- CrashReport crashReport = CrashReport.forThrowable(var9, "Saving entity NBT"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Entity being saved"); +- this.fillCrashReportCategory(crashReportCategory); +- throw new ReportedException(crashReport); ++ // CraftBukkit start - stores eventually existing bukkit values ++ if (this.bukkitEntity != null) { ++ this.bukkitEntity.storeBukkitValues(nbttagcompound); ++ } ++ // CraftBukkit end ++ return nbttagcompound; ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being saved"); ++ ++ this.fillCrashReportCategory(crashreportsystemdetails); ++ throw new ReportedException(crashreport); + } + } + + public void load(CompoundTag compound) { + try { +- ListTag list = compound.getList("Pos", 6); +- ListTag list1 = compound.getList("Motion", 6); +- ListTag list2 = compound.getList("Rotation", 5); +- double _double = list1.getDouble(0); +- double _double1 = list1.getDouble(1); +- double _double2 = list1.getDouble(2); +- this.setDeltaMovement( +- Math.abs(_double) > 10.0 ? 0.0 : _double, Math.abs(_double1) > 10.0 ? 0.0 : _double1, Math.abs(_double2) > 10.0 ? 0.0 : _double2 +- ); +- double d = 3.0000512E7; +- this.setPosRaw( +- Mth.clamp(list.getDouble(0), -3.0000512E7, 3.0000512E7), +- Mth.clamp(list.getDouble(1), -2.0E7, 2.0E7), +- Mth.clamp(list.getDouble(2), -3.0000512E7, 3.0000512E7) +- ); +- this.setYRot(list2.getFloat(0)); +- this.setXRot(list2.getFloat(1)); ++ ListTag nbttaglist = compound.getList("Pos", 6); ++ ListTag nbttaglist1 = compound.getList("Motion", 6); ++ ListTag nbttaglist2 = compound.getList("Rotation", 5); ++ double d0 = nbttaglist1.getDouble(0); ++ double d1 = nbttaglist1.getDouble(1); ++ double d2 = nbttaglist1.getDouble(2); ++ ++ this.setDeltaMovement(Math.abs(d0) > 10.0D ? 0.0D : d0, Math.abs(d1) > 10.0D ? 0.0D : d1, Math.abs(d2) > 10.0D ? 0.0D : d2); ++ double d3 = 3.0000512E7D; ++ ++ this.setPosRaw(Mth.clamp(nbttaglist.getDouble(0), -3.0000512E7D, 3.0000512E7D), Mth.clamp(nbttaglist.getDouble(1), -2.0E7D, 2.0E7D), Mth.clamp(nbttaglist.getDouble(2), -3.0000512E7D, 3.0000512E7D)); ++ this.setYRot(nbttaglist2.getFloat(0)); ++ this.setXRot(nbttaglist2.getFloat(1)); + this.setOldPosAndRot(); + this.setYHeadRot(this.getYRot()); + this.setYBodyRot(this.getYRot()); +@@ -1711,49 +2063,92 @@ + this.stringUUID = this.uuid.toString(); + } + +- if (!Double.isFinite(this.getX()) || !Double.isFinite(this.getY()) || !Double.isFinite(this.getZ())) { +- throw new IllegalStateException("Entity has invalid position"); +- } else if (Double.isFinite((double)this.getYRot()) && Double.isFinite((double)this.getXRot())) { +- this.reapplyPosition(); +- this.setRot(this.getYRot(), this.getXRot()); +- if (compound.contains("CustomName", 8)) { +- String string = compound.getString("CustomName"); ++ if (Double.isFinite(this.getX()) && Double.isFinite(this.getY()) && Double.isFinite(this.getZ())) { ++ if (Double.isFinite((double) this.getYRot()) && Double.isFinite((double) this.getXRot())) { ++ this.reapplyPosition(); ++ this.setRot(this.getYRot(), this.getXRot()); ++ if (compound.contains("CustomName", 8)) { ++ String s = compound.getString("CustomName"); + +- try { +- this.setCustomName(Component.Serializer.fromJson(string)); +- } catch (Exception var16) { +- LOGGER.warn("Failed to parse entity custom name {}", string, var16); ++ try { ++ this.setCustomName(Component.Serializer.fromJson(s)); ++ } catch (Exception exception) { ++ Entity.LOGGER.warn("Failed to parse entity custom name {}", s, exception); ++ } + } +- } + +- this.setCustomNameVisible(compound.getBoolean("CustomNameVisible")); +- this.setSilent(compound.getBoolean("Silent")); +- this.setNoGravity(compound.getBoolean("NoGravity")); +- this.setGlowingTag(compound.getBoolean("Glowing")); +- this.setTicksFrozen(compound.getInt("TicksFrozen")); +- this.hasVisualFire = compound.getBoolean("HasVisualFire"); +- if (compound.contains("Tags", 9)) { +- this.tags.clear(); +- ListTag list3 = compound.getList("Tags", 8); +- int min = Math.min(list3.size(), 1024); ++ this.setCustomNameVisible(compound.getBoolean("CustomNameVisible")); ++ this.setSilent(compound.getBoolean("Silent")); ++ this.setNoGravity(compound.getBoolean("NoGravity")); ++ this.setGlowingTag(compound.getBoolean("Glowing")); ++ this.setTicksFrozen(compound.getInt("TicksFrozen")); ++ this.hasVisualFire = compound.getBoolean("HasVisualFire"); ++ if (compound.contains("Tags", 9)) { ++ this.tags.clear(); ++ ListTag nbttaglist3 = compound.getList("Tags", 8); ++ int i = Math.min(nbttaglist3.size(), 1024); + +- for (int i = 0; i < min; i++) { +- this.tags.add(list3.getString(i)); ++ for (int j = 0; j < i; ++j) { ++ this.tags.add(nbttaglist3.getString(j)); ++ } + } +- } + +- this.readAdditionalSaveData(compound); +- if (this.repositionEntityAfterLoad()) { +- this.reapplyPosition(); ++ this.readAdditionalSaveData(compound); ++ if (this.repositionEntityAfterLoad()) { ++ this.reapplyPosition(); ++ } ++ ++ } else { ++ throw new IllegalStateException("Entity has invalid rotation"); + } + } else { +- throw new IllegalStateException("Entity has invalid rotation"); ++ throw new IllegalStateException("Entity has invalid position"); + } +- } catch (Throwable var17) { +- CrashReport crashReport = CrashReport.forThrowable(var17, "Loading entity NBT"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Entity being loaded"); +- this.fillCrashReportCategory(crashReportCategory); +- throw new ReportedException(crashReport); ++ ++ // CraftBukkit start ++ this.persist = !compound.contains("Bukkit.persist") || compound.getBoolean("Bukkit.persist"); ++ this.visibleByDefault = !compound.contains("Bukkit.visibleByDefault") || compound.getBoolean("Bukkit.visibleByDefault"); ++ // SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ if (compound.contains("Bukkit.MaxAirSupply")) { ++ maxAirTicks = compound.getInt("Bukkit.MaxAirSupply"); ++ } ++ // CraftBukkit end ++ ++ // CraftBukkit start - Reset world ++ if (this instanceof ServerPlayer) { ++ Server server = Bukkit.getServer(); ++ org.bukkit.World bworld = null; ++ ++ // TODO: Remove World related checks, replaced with WorldUID ++ String worldName = compound.getString("world"); ++ ++ if (compound.contains("WorldUUIDMost") && compound.contains("WorldUUIDLeast")) { ++ UUID uid = new UUID(compound.getLong("WorldUUIDMost"), compound.getLong("WorldUUIDLeast")); ++ bworld = server.getWorld(uid); ++ } else { ++ bworld = server.getWorld(worldName); ++ } ++ ++ if (bworld == null) { ++ bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getLevel(Level.OVERWORLD).getWorld(); ++ } ++ ++ ((ServerPlayer) this).setLevel(bworld == null ? null : ((CraftWorld) bworld).getHandle()); ++ } ++ this.getBukkitEntity().readBukkitValues(compound); ++ if (compound.contains("Bukkit.invisible")) { ++ boolean bukkitInvisible = compound.getBoolean("Bukkit.invisible"); ++ this.setInvisible(bukkitInvisible); ++ this.persistentInvisibility = bukkitInvisible; ++ } ++ // CraftBukkit end ++ ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being loaded"); ++ ++ this.fillCrashReportCategory(crashreportsystemdetails); ++ throw new ReportedException(crashreport); + } + } + +@@ -1762,44 +2157,59 @@ + } + + @Nullable +- protected final String getEncodeId() { +- EntityType type = this.getType(); +- ResourceLocation key = EntityType.getKey(type); +- return type.canSerialize() && key != null ? key.toString() : null; ++ public final String getEncodeId() { ++ EntityType entitytypes = this.getType(); ++ ResourceLocation minecraftkey = EntityType.getKey(entitytypes); ++ ++ return entitytypes.canSerialize() && minecraftkey != null ? minecraftkey.toString() : null; + } + ++ // CraftBukkit start - allow excluding certain data when saving ++ protected void addAdditionalSaveData(CompoundTag nbttagcompound, boolean includeAll) { ++ addAdditionalSaveData(nbttagcompound); ++ } ++ // CraftBukkit end ++ + protected abstract void readAdditionalSaveData(CompoundTag compound); + + protected abstract void addAdditionalSaveData(CompoundTag compound); + + protected ListTag newDoubleList(double... numbers) { +- ListTag list = new ListTag(); ++ ListTag nbttaglist = new ListTag(); ++ double[] adouble1 = numbers; ++ int i = numbers.length; + +- for (double d : numbers) { +- list.add(DoubleTag.valueOf(d)); ++ for (int j = 0; j < i; ++j) { ++ double d0 = adouble1[j]; ++ ++ nbttaglist.add(DoubleTag.valueOf(d0)); + } + +- return list; ++ return nbttaglist; + } + + protected ListTag newFloatList(float... numbers) { +- ListTag list = new ListTag(); ++ ListTag nbttaglist = new ListTag(); ++ float[] afloat1 = numbers; ++ int i = numbers.length; + +- for (float f : numbers) { +- list.add(FloatTag.valueOf(f)); ++ for (int j = 0; j < i; ++j) { ++ float f = afloat1[j]; ++ ++ nbttaglist.add(FloatTag.valueOf(f)); + } + +- return list; ++ return nbttaglist; + } + + @Nullable +- public ItemEntity spawnAtLocation(ItemLike item) { ++ public ItemEntity spawnAtLocation(IMaterial item) { + return this.spawnAtLocation(item, 0); + } + + @Nullable +- public ItemEntity spawnAtLocation(ItemLike item, int offsetY) { +- return this.spawnAtLocation(new ItemStack(item), (float)offsetY); ++ public ItemEntity spawnAtLocation(IMaterial item, int offsetY) { ++ return this.spawnAtLocation(new ItemStack(item), (float) offsetY); + } + + @Nullable +@@ -1814,10 +2224,24 @@ + } else if (this.level().isClientSide) { + return null; + } else { +- ItemEntity itemEntity = new ItemEntity(this.level(), this.getX(), this.getY() + (double)offsetY, this.getZ(), stack); +- itemEntity.setDefaultPickUpDelay(); +- this.level().addFreshEntity(itemEntity); +- return itemEntity; ++ // CraftBukkit start - Capture drops for death event ++ if (this instanceof net.minecraft.world.entity.LivingEntity && !((net.minecraft.world.entity.LivingEntity) this).forceDrops) { ++ ((net.minecraft.world.entity.LivingEntity) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(stack)); ++ return null; ++ } ++ // CraftBukkit end ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY() + (double) offsetY, this.getZ(), stack); ++ ++ entityitem.setDefaultPickUpDelay(); ++ // CraftBukkit start ++ EntityDropItemEvent event = new EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return null; ++ } ++ // CraftBukkit end ++ this.level().addFreshEntity(entityitem); ++ return entityitem; + } + } + +@@ -1830,25 +2254,17 @@ + return false; + } else { + float f = this.dimensions.width * 0.8F; +- AABB aABB = AABB.ofSize(this.getEyePosition(), (double)f, 1.0E-6, (double)f); +- return BlockPos.betweenClosedStream(aABB) +- .anyMatch( +- blockPos -> { +- BlockState blockState = this.level().getBlockState(blockPos); +- return !blockState.isAir() +- && blockState.isSuffocating(this.level(), blockPos) +- && Shapes.joinIsNotEmpty( +- blockState.getCollisionShape(this.level(), blockPos) +- .move((double)blockPos.getX(), (double)blockPos.getY(), (double)blockPos.getZ()), +- Shapes.create(aABB), +- BooleanOp.AND +- ); +- } +- ); ++ AABB axisalignedbb = AABB.ofSize(this.getEyePosition(), (double) f, 1.0E-6D, (double) f); ++ ++ return BlockPos.betweenClosedStream(axisalignedbb).anyMatch((blockposition) -> { ++ IBlockData iblockdata = this.level().getBlockState(blockposition); ++ ++ return !iblockdata.isAir() && iblockdata.isSuffocating(this.level(), blockposition) && Shapes.joinIsNotEmpty(iblockdata.getCollisionShape(this.level(), blockposition).move((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()), Shapes.create(axisalignedbb), BooleanOp.AND); ++ }); + } + } + +- public InteractionResult interact(Player player, InteractionHand hand) { ++ public InteractionResult interact(Player player, EnumHand hand) { + return InteractionResult.PASS; + } + +@@ -1875,13 +2291,13 @@ + } + + protected void positionRider(Entity passenger, Entity.MoveFunction callback) { +- Vec3 passengerRidingPosition = this.getPassengerRidingPosition(passenger); +- callback.accept(passenger, passengerRidingPosition.x, passengerRidingPosition.y + (double)passenger.getMyRidingOffset(this), passengerRidingPosition.z); +- } ++ Vec3 vec3d = this.getPassengerRidingPosition(passenger); + +- public void onPassengerTurned(Entity entityToUpdate) { ++ callback.accept(passenger, vec3d.x, vec3d.y + (double) passenger.getMyRidingOffset(this), vec3d.z); + } + ++ public void onPassengerTurned(Entity entityToUpdate) {} ++ + public float getMyRidingOffset(Entity entity) { + return this.ridingOffset(entity); + } +@@ -1891,11 +2307,11 @@ + } + + public Vec3 getPassengerRidingPosition(Entity entity) { +- return new Vec3(this.getPassengerAttachmentPoint(entity, this.dimensions, 1.0F).rotateY(-this.yRot * (float) (Math.PI / 180.0))).add(this.position()); ++ return (new Vec3(this.getPassengerAttachmentPoint(entity, this.dimensions, 1.0F).rotateY(-this.yRot * 0.017453292F))).add(this.position()); + } + +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height, 0.0F); + } + + public boolean startRiding(Entity vehicle) { +@@ -1903,7 +2319,7 @@ + } + + public boolean showVehicleHealth() { +- return this instanceof LivingEntity; ++ return this instanceof net.minecraft.world.entity.LivingEntity; + } + + public boolean startRiding(Entity vehicle, boolean force) { +@@ -1912,26 +2328,40 @@ + } else if (!vehicle.couldAcceptPassenger()) { + return false; + } else { +- for (Entity entity = vehicle; entity.vehicle != null; entity = entity.vehicle) { +- if (entity.vehicle == this) { ++ for (Entity entity1 = vehicle; entity1.vehicle != null; entity1 = entity1.vehicle) { ++ if (entity1.vehicle == this) { + return false; + } + } + +- if (force || this.canRide(vehicle) && vehicle.canAddPassenger(this)) { ++ if (!force && (!this.canRide(vehicle) || !vehicle.canAddPassenger(this))) { ++ return false; ++ } else { ++ // CraftBukkit start ++ if (vehicle.getBukkitEntity() instanceof Vehicle && this.getBukkitEntity() instanceof LivingEntity) { ++ VehicleEnterEvent event = new VehicleEnterEvent((Vehicle) vehicle.getBukkitEntity(), this.getBukkitEntity()); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ if (event.isCancelled()) { ++ return false; ++ } ++ } ++ // CraftBukkit end + if (this.isPassenger()) { + this.stopRiding(); + } + +- this.setPose(Pose.STANDING); ++ this.setPose(EntityPose.STANDING); + this.vehicle = vehicle; + this.vehicle.addPassenger(this); +- vehicle.getIndirectPassengersStream() +- .filter(entity1 -> entity1 instanceof ServerPlayer) +- .forEach(entity1 -> CriteriaTriggers.START_RIDING_TRIGGER.trigger((ServerPlayer)entity1)); ++ vehicle.getIndirectPassengersStream().filter((entity2) -> { ++ return entity2 instanceof ServerPlayer; ++ }).forEach((entity2) -> { ++ CriteriaTriggers.START_RIDING_TRIGGER.trigger((ServerPlayer) entity2); ++ }); + return true; +- } else { +- return false; + } + } + } +@@ -1941,17 +2371,20 @@ + } + + public void ejectPassengers() { +- for (int i = this.passengers.size() - 1; i >= 0; i--) { +- this.passengers.get(i).stopRiding(); ++ for (int i = this.passengers.size() - 1; i >= 0; --i) { ++ ((Entity) this.passengers.get(i)).stopRiding(); + } ++ + } + + public void removeVehicle() { + if (this.vehicle != null) { + Entity entity = this.vehicle; ++ + this.vehicle = null; +- entity.removePassenger(this); ++ if (!entity.removePassenger(this)) this.vehicle = entity; // CraftBukkit + } ++ + } + + public void stopRiding() { +@@ -1966,6 +2399,7 @@ + this.passengers = ImmutableList.of(passenger); + } else { + List list = Lists.newArrayList(this.passengers); ++ + if (!this.level().isClientSide && passenger instanceof Player && !(this.getFirstPassenger() instanceof Player)) { + list.add(0, passenger); + } else { +@@ -1979,19 +2413,41 @@ + } + } + +- protected void removePassenger(Entity passenger) { +- if (passenger.getVehicle() == this) { ++ protected boolean removePassenger(Entity entity) { // CraftBukkit ++ if (entity.getVehicle() == this) { + throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); + } else { +- if (this.passengers.size() == 1 && this.passengers.get(0) == passenger) { ++ // CraftBukkit start ++ CraftEntity craft = (CraftEntity) entity.getBukkitEntity().getVehicle(); ++ Entity orig = craft == null ? null : craft.getHandle(); ++ if (getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { ++ VehicleExitEvent event = new VehicleExitEvent( ++ (Vehicle) getBukkitEntity(), ++ (LivingEntity) entity.getBukkitEntity() ++ ); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ CraftEntity craftn = (CraftEntity) entity.getBukkitEntity().getVehicle(); ++ Entity n = craftn == null ? null : craftn.getHandle(); ++ if (event.isCancelled() || n != orig) { ++ return false; ++ } ++ } ++ // CraftBukkit end ++ if (this.passengers.size() == 1 && this.passengers.get(0) == entity) { + this.passengers = ImmutableList.of(); + } else { +- this.passengers = this.passengers.stream().filter(entity -> entity != passenger).collect(ImmutableList.toImmutableList()); ++ this.passengers = (ImmutableList) this.passengers.stream().filter((entity1) -> { ++ return entity1 != entity; ++ }).collect(ImmutableList.toImmutableList()); + } + +- passenger.boardingCooldown = 60; +- this.gameEvent(GameEvent.ENTITY_DISMOUNT, passenger); ++ entity.boardingCooldown = 60; ++ this.gameEvent(GameEvent.ENTITY_DISMOUNT, entity); + } ++ return true; // CraftBukkit + } + + protected boolean canAddPassenger(Entity passenger) { +@@ -2002,8 +2458,8 @@ + return true; + } + +- public void lerpTo(double d, double d1, double d2, float f, float f1, int i) { +- this.setPos(d, d1, d2); ++ public void lerpTo(double d0, double d1, double d2, float f, float f1, int i) { ++ this.setPos(d0, d1, d2); + this.setRot(f, f1); + } + +@@ -2040,12 +2496,14 @@ + } + + public Vec3 getHandHoldingItemAngle(Item item) { +- if (!(this instanceof Player player)) { ++ if (!(this instanceof Player)) { + return Vec3.ZERO; + } else { +- boolean flag = player.getOffhandItem().is(item) && !player.getMainHandItem().is(item); +- HumanoidArm humanoidArm = flag ? player.getMainArm().getOpposite() : player.getMainArm(); +- return this.calculateViewVector(0.0F, this.getYRot() + (float)(humanoidArm == HumanoidArm.RIGHT ? 80 : -80)).scale(0.5); ++ Player entityhuman = (Player) this; ++ boolean flag = entityhuman.getOffhandItem().is(item) && !entityhuman.getMainHandItem().is(item); ++ HumanoidArm enummainhand = flag ? entityhuman.getMainArm().getOpposite() : entityhuman.getMainArm(); ++ ++ return this.calculateViewVector(0.0F, this.getYRot() + (float) (enummainhand == HumanoidArm.RIGHT ? 80 : -80)).scale(0.5D); + } + } + +@@ -2071,17 +2529,25 @@ + + protected void handleNetherPortal() { + if (this.level() instanceof ServerLevel) { +- int portalWaitTime = this.getPortalWaitTime(); +- ServerLevel serverLevel = (ServerLevel)this.level(); ++ int i = this.getPortalWaitTime(); ++ ServerLevel worldserver = (ServerLevel) this.level(); ++ + if (this.isInsidePortal) { +- MinecraftServer server = serverLevel.getServer(); +- ResourceKey resourceKey = this.level().dimension() == Level.NETHER ? Level.OVERWORLD : Level.NETHER; +- ServerLevel level = server.getLevel(resourceKey); +- if (level != null && server.isNetherEnabled() && !this.isPassenger() && this.portalTime++ >= portalWaitTime) { ++ MinecraftServer minecraftserver = worldserver.getServer(); ++ ResourceKey resourcekey = this.level().getTypeKey() == LevelStem.NETHER ? Level.OVERWORLD : Level.NETHER; // CraftBukkit ++ ServerLevel worldserver1 = minecraftserver.getLevel(resourcekey); ++ ++ if (true && !this.isPassenger() && this.portalTime++ >= i) { // CraftBukkit + this.level().getProfiler().push("portal"); +- this.portalTime = portalWaitTime; ++ this.portalTime = i; + this.setPortalCooldown(); +- this.changeDimension(level); ++ // CraftBukkit start ++ if (this instanceof ServerPlayer) { ++ ((ServerPlayer) this).changeDimension(worldserver1, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL); ++ } else { ++ this.changeDimension(worldserver1); ++ } ++ // CraftBukkit end + this.level().getProfiler().pop(); + } + +@@ -2104,40 +2570,39 @@ + return 300; + } + +- public void lerpMotion(double x, double y, double z) { +- this.setDeltaMovement(x, y, z); ++ public void lerpMotion(double x, double d1, double y) { ++ this.setDeltaMovement(x, d1, y); + } + +- public void handleDamageEvent(DamageSource damageSource) { +- } ++ public void handleDamageEvent(DamageSource damageSource) {} + + public void handleEntityEvent(byte id) { + switch (id) { + case 53: + HoneyBlock.showSlideParticles(this); ++ default: + } + } + +- public void animateHurt(float yaw) { +- } ++ public void animateHurt(float yaw) {} + + public Iterable getHandSlots() { +- return EMPTY_LIST; ++ return Entity.EMPTY_LIST; + } + + public Iterable getArmorSlots() { +- return EMPTY_LIST; ++ return Entity.EMPTY_LIST; + } + + public Iterable getAllSlots() { + return Iterables.concat(this.getHandSlots(), this.getArmorSlots()); + } + +- public void setItemSlot(EquipmentSlot slot, ItemStack stack) { +- } ++ public void setItemSlot(EquipmentSlot slot, ItemStack stack) {} + + public boolean isOnFire() { + boolean flag = this.level() != null && this.level().isClientSide; ++ + return !this.fireImmune() && (this.remainingFireTicks > 0 || flag && this.getSharedFlag(0)); + } + +@@ -2182,7 +2647,7 @@ + } + + public boolean isCrouching() { +- return this.hasPose(Pose.CROUCHING); ++ return this.hasPose(EntityPose.CROUCHING); + } + + public boolean isSprinting() { +@@ -2198,7 +2663,7 @@ + } + + public boolean isVisuallySwimming() { +- return this.hasPose(Pose.SWIMMING); ++ return this.hasPose(EntityPose.SWIMMING); + } + + public boolean isVisuallyCrawling() { +@@ -2206,6 +2671,13 @@ + } + + public void setSwimming(boolean swimming) { ++ // CraftBukkit start ++ if (valid && this.isSwimming() != swimming && this instanceof net.minecraft.world.entity.LivingEntity) { ++ if (CraftEventFactory.callToggleSwimEvent((net.minecraft.world.entity.LivingEntity) this, swimming).isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + this.setSharedFlag(4, swimming); + } + +@@ -2230,8 +2702,9 @@ + if (player.isSpectator()) { + return false; + } else { +- Team team = this.getTeam(); +- return (team == null || player == null || player.getTeam() != team || !team.canSeeFriendlyInvisibles()) && this.isInvisible(); ++ PlayerTeam scoreboardteam = this.getTeam(); ++ ++ return scoreboardteam != null && player != null && player.getTeam() == scoreboardteam && scoreboardteam.canSeeFriendlyInvisibles() ? false : this.isInvisible(); + } + } + +@@ -2239,8 +2712,7 @@ + return false; + } + +- public void updateDynamicGameEventListener(BiConsumer, ServerLevel> listenerConsumer) { +- } ++ public void updateDynamicGameEventListener(BiConsumer, ServerLevel> listenerConsumer) {} + + @Nullable + public PlayerTeam getTeam() { +@@ -2248,53 +2720,71 @@ + } + + public boolean isAlliedTo(Entity entity) { +- return this.isAlliedTo(entity.getTeam()); ++ return this.isAlliedTo((Team) entity.getTeam()); + } + + public boolean isAlliedTo(Team team) { +- return this.getTeam() != null && this.getTeam().isAlliedTo(team); ++ return this.getTeam() != null ? this.getTeam().isAlliedTo(team) : false; + } + ++ // CraftBukkit - start + public void setInvisible(boolean invisible) { +- this.setSharedFlag(5, invisible); ++ if (!this.persistentInvisibility) { // Prevent Minecraft from removing our invisibility flag ++ this.setSharedFlag(5, invisible); ++ } ++ // CraftBukkit - end + } + +- protected boolean getSharedFlag(int flag) { +- return (this.entityData.get(DATA_SHARED_FLAGS_ID) & 1 << flag) != 0; ++ public boolean getSharedFlag(int flag) { ++ return ((Byte) this.entityData.get(Entity.DATA_SHARED_FLAGS_ID) & 1 << flag) != 0; + } + +- protected void setSharedFlag(int flag, boolean set) { +- byte b = this.entityData.get(DATA_SHARED_FLAGS_ID); ++ public void setSharedFlag(int flag, boolean set) { ++ byte b0 = (Byte) this.entityData.get(Entity.DATA_SHARED_FLAGS_ID); ++ + if (set) { +- this.entityData.set(DATA_SHARED_FLAGS_ID, (byte)(b | 1 << flag)); ++ this.entityData.set(Entity.DATA_SHARED_FLAGS_ID, (byte) (b0 | 1 << flag)); + } else { +- this.entityData.set(DATA_SHARED_FLAGS_ID, (byte)(b & ~(1 << flag))); ++ this.entityData.set(Entity.DATA_SHARED_FLAGS_ID, (byte) (b0 & ~(1 << flag))); + } ++ + } + + public int getMaxAirSupply() { +- return 300; ++ return maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() + } + + public int getAirSupply() { +- return this.entityData.get(DATA_AIR_SUPPLY_ID); ++ return (Integer) this.entityData.get(Entity.DATA_AIR_SUPPLY_ID); + } + + public void setAirSupply(int air) { +- this.entityData.set(DATA_AIR_SUPPLY_ID, air); ++ // CraftBukkit start ++ EntityAirChangeEvent event = new EntityAirChangeEvent(this.getBukkitEntity(), air); ++ // Suppress during worldgen ++ if (this.valid) { ++ event.getEntity().getServer().getPluginManager().callEvent(event); ++ } ++ if (event.isCancelled() && this.getAirSupply() != air) { ++ this.entityData.markDirty(Entity.DATA_AIR_SUPPLY_ID); ++ return; ++ } ++ this.entityData.set(Entity.DATA_AIR_SUPPLY_ID, event.getAmount()); ++ // CraftBukkit end + } + + public int getTicksFrozen() { +- return this.entityData.get(DATA_TICKS_FROZEN); ++ return (Integer) this.entityData.get(Entity.DATA_TICKS_FROZEN); + } + + public void setTicksFrozen(int ticksFrozen) { +- this.entityData.set(DATA_TICKS_FROZEN, ticksFrozen); ++ this.entityData.set(Entity.DATA_TICKS_FROZEN, ticksFrozen); + } + + public float getPercentFrozen() { +- int ticksRequiredToFreeze = this.getTicksRequiredToFreeze(); +- return (float)Math.min(this.getTicksFrozen(), ticksRequiredToFreeze) / (float)ticksRequiredToFreeze; ++ int i = this.getTicksRequiredToFreeze(); ++ ++ return (float) Math.min(this.getTicksFrozen(), i) / (float) i; + } + + public boolean isFullyFrozen() { +@@ -2307,102 +2797,146 @@ + + public void thunderHit(ServerLevel level, LightningBolt lightning) { + this.setRemainingFireTicks(this.remainingFireTicks + 1); ++ // CraftBukkit start ++ final org.bukkit.entity.Entity thisBukkitEntity = this.getBukkitEntity(); ++ final org.bukkit.entity.Entity stormBukkitEntity = lightning.getBukkitEntity(); ++ final PluginManager pluginManager = Bukkit.getPluginManager(); ++ // CraftBukkit end ++ + if (this.remainingFireTicks == 0) { +- this.setSecondsOnFire(8); ++ // CraftBukkit start - Call a combust event when lightning strikes ++ EntityCombustByEntityEvent entityCombustEvent = new EntityCombustByEntityEvent(stormBukkitEntity, thisBukkitEntity, 8); ++ pluginManager.callEvent(entityCombustEvent); ++ if (!entityCombustEvent.isCancelled()) { ++ this.setSecondsOnFire(entityCombustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + +- this.hurt(this.damageSources().lightningBolt(), 5.0F); ++ // CraftBukkit start ++ if (thisBukkitEntity instanceof Hanging) { ++ HangingBreakByEntityEvent hangingEvent = new HangingBreakByEntityEvent((Hanging) thisBukkitEntity, stormBukkitEntity); ++ pluginManager.callEvent(hangingEvent); ++ ++ if (hangingEvent.isCancelled()) { ++ return; ++ } ++ } ++ ++ if (this.fireImmune()) { ++ return; ++ } ++ CraftEventFactory.entityDamage = lightning; ++ if (!this.hurt(this.damageSources().lightningBolt(), 5.0F)) { ++ CraftEventFactory.entityDamage = null; ++ return; ++ } ++ // CraftBukkit end + } + + public void onAboveBubbleCol(boolean downwards) { +- Vec3 deltaMovement = this.getDeltaMovement(); +- double max; ++ Vec3 vec3d = this.getDeltaMovement(); ++ double d0; ++ + if (downwards) { +- max = Math.max(-0.9, deltaMovement.y - 0.03); ++ d0 = Math.max(-0.9D, vec3d.y - 0.03D); + } else { +- max = Math.min(1.8, deltaMovement.y + 0.1); ++ d0 = Math.min(1.8D, vec3d.y + 0.1D); + } + +- this.setDeltaMovement(deltaMovement.x, max, deltaMovement.z); ++ this.setDeltaMovement(vec3d.x, d0, vec3d.z); + } + + public void onInsideBubbleColumn(boolean downwards) { +- Vec3 deltaMovement = this.getDeltaMovement(); +- double max; ++ Vec3 vec3d = this.getDeltaMovement(); ++ double d0; ++ + if (downwards) { +- max = Math.max(-0.3, deltaMovement.y - 0.03); ++ d0 = Math.max(-0.3D, vec3d.y - 0.03D); + } else { +- max = Math.min(0.7, deltaMovement.y + 0.06); ++ d0 = Math.min(0.7D, vec3d.y + 0.06D); + } + +- this.setDeltaMovement(deltaMovement.x, max, deltaMovement.z); ++ this.setDeltaMovement(vec3d.x, d0, vec3d.z); + this.resetFallDistance(); + } + +- public boolean killedEntity(ServerLevel level, LivingEntity entity) { ++ public boolean killedEntity(ServerLevel level, net.minecraft.world.entity.LivingEntity entity) { + return true; + } + + public void checkSlowFallDistance() { +- if (this.getDeltaMovement().y() > -0.5 && this.fallDistance > 1.0F) { ++ if (this.getDeltaMovement().y() > -0.5D && this.fallDistance > 1.0F) { + this.fallDistance = 1.0F; + } ++ + } + + public void resetFallDistance() { + this.fallDistance = 0.0F; + } + +- protected void moveTowardsClosestSpace(double x, double y, double z) { +- BlockPos blockPos = BlockPos.containing(x, y, z); +- Vec3 vec3 = new Vec3(x - (double)blockPos.getX(), y - (double)blockPos.getY(), z - (double)blockPos.getZ()); +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); +- Direction direction = Direction.UP; +- double d = Double.MAX_VALUE; ++ protected void moveTowardsClosestSpace(double x, double d1, double y) { ++ BlockPos blockposition = BlockPos.containing(x, d1, y); ++ Vec3 vec3d = new Vec3(x - (double) blockposition.getX(), d1 - (double) blockposition.getY(), y - (double) blockposition.getZ()); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ Direction enumdirection = Direction.UP; ++ double d3 = Double.MAX_VALUE; ++ Direction[] aenumdirection = new Direction[]{Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST, Direction.UP}; ++ int i = aenumdirection.length; + +- for (Direction direction1 : new Direction[]{Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST, Direction.UP}) { +- mutableBlockPos.setWithOffset(blockPos, direction1); +- if (!this.level().getBlockState(mutableBlockPos).isCollisionShapeFullBlock(this.level(), mutableBlockPos)) { +- double d1 = vec3.get(direction1.getAxis()); +- double d2 = direction1.getAxisDirection() == Direction.AxisDirection.POSITIVE ? 1.0 - d1 : d1; +- if (d2 < d) { +- d = d2; +- direction = direction1; ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection1 = aenumdirection[j]; ++ ++ blockposition_mutableblockposition.setWithOffset(blockposition, enumdirection1); ++ if (!this.level().getBlockState(blockposition_mutableblockposition).isCollisionShapeFullBlock(this.level(), blockposition_mutableblockposition)) { ++ double d4 = vec3d.get(enumdirection1.getAxis()); ++ double d5 = enumdirection1.getAxisDirection() == Direction.AxisDirection.POSITIVE ? 1.0D - d4 : d4; ++ ++ if (d5 < d3) { ++ d3 = d5; ++ enumdirection = enumdirection1; + } + } + } + + float f = this.random.nextFloat() * 0.2F + 0.1F; +- float f1 = (float)direction.getAxisDirection().getStep(); +- Vec3 vec31 = this.getDeltaMovement().scale(0.75); +- if (direction.getAxis() == Direction.Axis.X) { +- this.setDeltaMovement((double)(f1 * f), vec31.y, vec31.z); +- } else if (direction.getAxis() == Direction.Axis.Y) { +- this.setDeltaMovement(vec31.x, (double)(f1 * f), vec31.z); +- } else if (direction.getAxis() == Direction.Axis.Z) { +- this.setDeltaMovement(vec31.x, vec31.y, (double)(f1 * f)); ++ float f1 = (float) enumdirection.getAxisDirection().getStep(); ++ Vec3 vec3d1 = this.getDeltaMovement().scale(0.75D); ++ ++ if (enumdirection.getAxis() == Direction.Axis.X) { ++ this.setDeltaMovement((double) (f1 * f), vec3d1.y, vec3d1.z); ++ } else if (enumdirection.getAxis() == Direction.Axis.Y) { ++ this.setDeltaMovement(vec3d1.x, (double) (f1 * f), vec3d1.z); ++ } else if (enumdirection.getAxis() == Direction.Axis.Z) { ++ this.setDeltaMovement(vec3d1.x, vec3d1.y, (double) (f1 * f)); + } ++ + } + +- public void makeStuckInBlock(BlockState state, Vec3 motionMultiplier) { ++ public void makeStuckInBlock(IBlockData state, Vec3 motionMultiplier) { + this.resetFallDistance(); + this.stuckSpeedMultiplier = motionMultiplier; + } + + private static Component removeAction(Component name) { +- MutableComponent mutableComponent = name.plainCopy().setStyle(name.getStyle().withClickEvent(null)); ++ MutableComponent ichatmutablecomponent = name.plainCopy().setStyle(name.getStyle().withClickEvent((ClickEvent) null)); ++ Iterator iterator = name.getSiblings().iterator(); + +- for (Component component : name.getSiblings()) { +- mutableComponent.append(removeAction(component)); ++ while (iterator.hasNext()) { ++ Component ichatbasecomponent1 = (Component) iterator.next(); ++ ++ ichatmutablecomponent.append(removeAction(ichatbasecomponent1)); + } + +- return mutableComponent; ++ return ichatmutablecomponent; + } + + @Override + public Component getName() { +- Component customName = this.getCustomName(); +- return customName != null ? removeAction(customName) : this.getTypeName(); ++ Component ichatbasecomponent = this.getCustomName(); ++ ++ return ichatbasecomponent != null ? removeAction(ichatbasecomponent) : this.getTypeName(); + } + + protected Component getTypeName() { +@@ -2417,11 +2951,9 @@ + return 0.0F; + } + +- public void setYHeadRot(float yHeadRot) { +- } ++ public void setYHeadRot(float yHeadRot) {} + +- public void setYBodyRot(float yBodyRot) { +- } ++ public void setYBodyRot(float yBodyRot) {} + + public boolean isAttackable() { + return true; +@@ -2431,40 +2963,14 @@ + return false; + } + +- @Override + public String toString() { +- String string = this.level() == null ? "~NULL~" : this.level().toString(); +- return this.removalReason != null +- ? String.format( +- Locale.ROOT, +- "%s['%s'/%d, l='%s', x=%.2f, y=%.2f, z=%.2f, removed=%s]", +- this.getClass().getSimpleName(), +- this.getName().getString(), +- this.id, +- string, +- this.getX(), +- this.getY(), +- this.getZ(), +- this.removalReason +- ) +- : String.format( +- Locale.ROOT, +- "%s['%s'/%d, l='%s', x=%.2f, y=%.2f, z=%.2f]", +- this.getClass().getSimpleName(), +- this.getName().getString(), +- this.id, +- string, +- this.getX(), +- this.getY(), +- this.getZ() +- ); ++ String s = this.level() == null ? "~NULL~" : this.level().toString(); ++ ++ return this.removalReason != null ? String.format(Locale.ROOT, "%s['%s'/%d, l='%s', x=%.2f, y=%.2f, z=%.2f, removed=%s]", this.getClass().getSimpleName(), this.getName().getString(), this.id, s, this.getX(), this.getY(), this.getZ(), this.removalReason) : String.format(Locale.ROOT, "%s['%s'/%d, l='%s', x=%.2f, y=%.2f, z=%.2f]", this.getClass().getSimpleName(), this.getName().getString(), this.id, s, this.getX(), this.getY(), this.getZ()); + } + + public boolean isInvulnerableTo(DamageSource source) { +- return this.isRemoved() +- || this.invulnerable && !source.is(DamageTypeTags.BYPASSES_INVULNERABILITY) && !source.isCreativePlayer() +- || source.is(DamageTypeTags.IS_FIRE) && this.fireImmune() +- || source.is(DamageTypeTags.IS_FALL) && this.getType().is(EntityTypeTags.FALL_DAMAGE_IMMUNE); ++ return this.isRemoved() || this.invulnerable && !source.is(DamageTypeTags.BYPASSES_INVULNERABILITY) && !source.isCreativePlayer() || source.is(DamageTypeTags.IS_FIRE) && this.fireImmune() || source.is(DamageTypeTags.IS_FALL) && this.getType().is(EntityTypeTags.FALL_DAMAGE_IMMUNE); + } + + public boolean isInvulnerable() { +@@ -2480,39 +2986,77 @@ + } + + public void restoreFrom(Entity entity) { +- CompoundTag compoundTag = entity.saveWithoutId(new CompoundTag()); +- compoundTag.remove("Dimension"); +- this.load(compoundTag); ++ CompoundTag nbttagcompound = entity.saveWithoutId(new CompoundTag()); ++ ++ nbttagcompound.remove("Dimension"); ++ this.load(nbttagcompound); + this.portalCooldown = entity.portalCooldown; + this.portalEntrancePos = entity.portalEntrancePos; + } + + @Nullable + public Entity changeDimension(ServerLevel destination) { ++ // CraftBukkit start ++ return teleportTo(destination, null); ++ } ++ ++ @Nullable ++ public Entity teleportTo(ServerLevel worldserver, Vec3 location) { ++ // CraftBukkit end + if (this.level() instanceof ServerLevel && !this.isRemoved()) { + this.level().getProfiler().push("changeDimension"); +- this.unRide(); ++ // CraftBukkit start ++ // this.unRide(); ++ if (worldserver == null) { ++ return null; ++ } ++ // CraftBukkit end + this.level().getProfiler().push("reposition"); +- PortalInfo portalInfo = this.findDimensionEntryPoint(destination); +- if (portalInfo == null) { ++ PortalInfo shapedetectorshape = (location == null) ? this.findDimensionEntryPoint(worldserver) : new PortalInfo(new Vec3(location.x(), location.y(), location.z()), Vec3.ZERO, this.yRot, this.xRot, worldserver, null); // CraftBukkit ++ ++ if (shapedetectorshape == null) { + return null; + } else { ++ // CraftBukkit start ++ worldserver = shapedetectorshape.world; ++ if (worldserver == level) { ++ // SPIGOT-6782: Just move the entity if a plugin changed the world to the one the entity is already in ++ moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, shapedetectorshape.xRot); ++ setDeltaMovement(shapedetectorshape.speed); ++ return this; ++ } ++ this.unRide(); ++ // CraftBukkit end ++ + this.level().getProfiler().popPush("reloading"); +- Entity entity = this.getType().create(destination); ++ Entity entity = this.getType().create(worldserver); ++ + if (entity != null) { + entity.restoreFrom(this); +- entity.moveTo(portalInfo.pos.x, portalInfo.pos.y, portalInfo.pos.z, portalInfo.yRot, entity.getXRot()); +- entity.setDeltaMovement(portalInfo.speed); +- destination.addDuringTeleport(entity); +- if (destination.dimension() == Level.END) { +- ServerLevel.makeObsidianPlatform(destination); ++ entity.moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, entity.getXRot()); ++ entity.setDeltaMovement(shapedetectorshape.speed); ++ // CraftBukkit start - Don't spawn the new entity if the current entity isn't spawned ++ if (this.inWorld) { ++ worldserver.addDuringTeleport(entity); ++ if (worldserver.getTypeKey() == LevelStem.END) { // CraftBukkit ++ ServerLevel.makeObsidianPlatform(worldserver, this); // CraftBukkit ++ } + } ++ // CraftBukkit end ++ // CraftBukkit start - Forward the CraftEntity to the new entity ++ this.getBukkitEntity().setHandle(entity); ++ entity.bukkitEntity = this.getBukkitEntity(); ++ ++ if (this instanceof Mob) { ++ ((Mob) this).dropLeash(true, false); // Unleash to prevent duping of leads. ++ } ++ // CraftBukkit end + } + + this.removeAfterChangingDimensions(); + this.level().getProfiler().pop(); +- ((ServerLevel)this.level()).resetEmptyTime(); +- destination.resetEmptyTime(); ++ ((ServerLevel) this.level()).resetEmptyTime(); ++ worldserver.resetEmptyTime(); + this.level().getProfiler().pop(); + return entity; + } +@@ -2527,54 +3071,69 @@ + + @Nullable + protected PortalInfo findDimensionEntryPoint(ServerLevel destination) { +- boolean flag = this.level().dimension() == Level.END && destination.dimension() == Level.OVERWORLD; +- boolean flag1 = destination.dimension() == Level.END; ++ // CraftBukkit start ++ if (destination == null) { ++ return null; ++ } ++ boolean flag = this.level().getTypeKey() == LevelStem.END && destination.getTypeKey() == LevelStem.OVERWORLD; // fromEndToOverworld ++ boolean flag1 = destination.getTypeKey() == LevelStem.END; // targetIsEnd ++ // CraftBukkit end ++ + if (!flag && !flag1) { +- boolean flag2 = destination.dimension() == Level.NETHER; +- if (this.level().dimension() != Level.NETHER && !flag2) { ++ boolean flag2 = destination.getTypeKey() == LevelStem.NETHER; // CraftBukkit ++ ++ if (this.level().getTypeKey() != LevelStem.NETHER && !flag2) { // CraftBukkit + return null; + } else { +- WorldBorder worldBorder = destination.getWorldBorder(); +- double teleportationScale = DimensionType.getTeleportationScale(this.level().dimensionType(), destination.dimensionType()); +- BlockPos blockPos1 = worldBorder.clampToBounds(this.getX() * teleportationScale, this.getY(), this.getZ() * teleportationScale); +- return this.getExitPortal(destination, blockPos1, flag2, worldBorder) +- .map( +- foundRectangle -> { +- BlockState blockState = this.level().getBlockState(this.portalEntrancePos); +- Direction.Axis axis; +- Vec3 relativePortalPosition; +- if (blockState.hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) { +- axis = blockState.getValue(BlockStateProperties.HORIZONTAL_AXIS); +- BlockUtil.FoundRectangle largestRectangleAround = BlockUtil.getLargestRectangleAround( +- this.portalEntrancePos, axis, 21, Direction.Axis.Y, 21, blockPos2 -> this.level().getBlockState(blockPos2) == blockState +- ); +- relativePortalPosition = this.getRelativePortalPosition(axis, largestRectangleAround); +- } else { +- axis = Direction.Axis.X; +- relativePortalPosition = new Vec3(0.5, 0.0, 0.0); +- } +- +- return PortalShape.createPortalInfo( +- destination, foundRectangle, axis, relativePortalPosition, this, this.getDeltaMovement(), this.getYRot(), this.getXRot() +- ); +- } +- ) +- .orElse(null); ++ WorldBorder worldborder = destination.getWorldBorder(); ++ double d0 = DimensionType.getTeleportationScale(this.level().dimensionType(), destination.dimensionType()); ++ BlockPos blockposition = worldborder.clampToBounds(this.getX() * d0, this.getY(), this.getZ() * d0); ++ // CraftBukkit start ++ CraftPortalEvent event = callPortalEvent(this, destination, new Vec3(blockposition.getX(), blockposition.getY(), blockposition.getZ()), PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, flag2 ? 16 : 128, 16); ++ if (event == null) { ++ return null; ++ } ++ final ServerLevel worldserverFinal = destination = ((CraftWorld) event.getTo().getWorld()).getHandle(); ++ worldborder = worldserverFinal.getWorldBorder(); ++ blockposition = worldborder.clampToBounds(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); ++ ++ return (PortalInfo) this.getExitPortal(destination, blockposition, flag2, worldborder, event.getSearchRadius(), event.getCanCreatePortal(), event.getCreationRadius()).map((blockutil_rectangle) -> { ++ // CraftBukkit end ++ IBlockData iblockdata = this.level().getBlockState(this.portalEntrancePos); ++ Direction.Axis enumdirection_enumaxis; ++ Vec3 vec3d; ++ ++ if (iblockdata.hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) { ++ enumdirection_enumaxis = (Direction.Axis) iblockdata.getValue(BlockStateProperties.HORIZONTAL_AXIS); ++ BlockUtil.FoundRectangle blockutil_rectangle1 = BlockUtil.getLargestRectangleAround(this.portalEntrancePos, enumdirection_enumaxis, 21, Direction.Axis.Y, 21, (blockposition1) -> { ++ return this.level().getBlockState(blockposition1) == iblockdata; ++ }); ++ ++ vec3d = this.getRelativePortalPosition(enumdirection_enumaxis, blockutil_rectangle1); ++ } else { ++ enumdirection_enumaxis = Direction.Axis.X; ++ vec3d = new Vec3(0.5D, 0.0D, 0.0D); ++ } ++ ++ return PortalShape.createPortalInfo(worldserverFinal, blockutil_rectangle, enumdirection_enumaxis, vec3d, this, this.getDeltaMovement(), this.getYRot(), this.getXRot(), event); // CraftBukkit ++ }).orElse(null); // CraftBukkit - decompile error + } + } else { +- BlockPos blockPos; ++ BlockPos blockposition1; ++ + if (flag1) { +- blockPos = ServerLevel.END_SPAWN_POINT; ++ blockposition1 = ServerLevel.END_SPAWN_POINT; + } else { +- blockPos = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSharedSpawnPos()); ++ blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSharedSpawnPos()); + } ++ // CraftBukkit start ++ CraftPortalEvent event = callPortalEvent(this, destination, new Vec3(blockposition1.getX() + 0.5D, blockposition1.getY(), blockposition1.getZ() + 0.5D), PlayerTeleportEvent.TeleportCause.END_PORTAL, 0, 0); ++ if (event == null) { ++ return null; ++ } + +- return new PortalInfo( +- new Vec3((double)blockPos.getX() + 0.5, (double)blockPos.getY(), (double)blockPos.getZ() + 0.5), +- this.getDeltaMovement(), +- this.getYRot(), +- this.getXRot() +- ); ++ return new PortalInfo(new Vec3(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()), this.getDeltaMovement(), this.getYRot(), this.getXRot(), ((CraftWorld) event.getTo().getWorld()).getHandle(), event); ++ // CraftBukkit end + } + } + +@@ -2582,21 +3141,34 @@ + return PortalShape.getRelativePosition(portal, axis, this.position(), this.getDimensions(this.getPose())); + } + +- protected Optional getExitPortal(ServerLevel destination, BlockPos findFrom, boolean isToNether, WorldBorder worldBorder) { +- return destination.getPortalForcer().findPortalAround(findFrom, isToNether, worldBorder); ++ // CraftBukkit start ++ protected CraftPortalEvent callPortalEvent(Entity entity, ServerLevel exitWorldServer, Vec3 exitPosition, PlayerTeleportEvent.TeleportCause cause, int searchRadius, int creationRadius) { ++ org.bukkit.entity.Entity bukkitEntity = entity.getBukkitEntity(); ++ Location enter = bukkitEntity.getLocation(); ++ Location exit = CraftLocation.toBukkit(exitPosition, exitWorldServer.getWorld()); ++ ++ EntityPortalEvent event = new EntityPortalEvent(bukkitEntity, enter, exit, searchRadius); ++ event.getEntity().getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null || !entity.isAlive()) { ++ return null; ++ } ++ return new CraftPortalEvent(event); + } + ++ protected Optional getExitPortal(ServerLevel worldserver, BlockPos blockposition, boolean flag, WorldBorder worldborder, int searchRadius, boolean canCreatePortal, int createRadius) { ++ return worldserver.getPortalForcer().findPortalAround(blockposition, worldborder, searchRadius); ++ // CraftBukkit end ++ } ++ + public boolean canChangeDimensions() { + return !this.isPassenger() && !this.isVehicle(); + } + +- public float getBlockExplosionResistance( +- Explosion explosion, BlockGetter level, BlockPos pos, BlockState blockState, FluidState fluidState, float explosionPower +- ) { ++ public float getBlockExplosionResistance(Explosion explosion, BlockGetter level, BlockPos pos, IBlockData blockState, FluidState fluidState, float explosionPower) { + return explosionPower; + } + +- public boolean shouldBlockExplode(Explosion explosion, BlockGetter level, BlockPos pos, BlockState blockState, float explosionPower) { ++ public boolean shouldBlockExplode(Explosion explosion, BlockGetter level, BlockPos pos, IBlockData blockState, float explosionPower) { + return true; + } + +@@ -2609,17 +3181,26 @@ + } + + public void fillCrashReportCategory(CrashReportCategory category) { +- category.setDetail("Entity Type", () -> EntityType.getKey(this.getType()) + " (" + this.getClass().getCanonicalName() + ")"); +- category.setDetail("Entity ID", this.id); +- category.setDetail("Entity Name", () -> this.getName().getString()); +- category.setDetail("Entity's Exact location", String.format(Locale.ROOT, "%.2f, %.2f, %.2f", this.getX(), this.getY(), this.getZ())); +- category.setDetail( +- "Entity's Block location", CrashReportCategory.formatLocation(this.level(), Mth.floor(this.getX()), Mth.floor(this.getY()), Mth.floor(this.getZ())) +- ); +- Vec3 deltaMovement = this.getDeltaMovement(); +- category.setDetail("Entity's Momentum", String.format(Locale.ROOT, "%.2f, %.2f, %.2f", deltaMovement.x, deltaMovement.y, deltaMovement.z)); +- category.setDetail("Entity's Passengers", () -> this.getPassengers().toString()); +- category.setDetail("Entity's Vehicle", () -> String.valueOf(this.getVehicle())); ++ category.setDetail("Entity Type", () -> { ++ ResourceLocation minecraftkey = EntityType.getKey(this.getType()); ++ ++ return minecraftkey + " (" + this.getClass().getCanonicalName() + ")"; ++ }); ++ category.setDetail("Entity ID", (Object) this.id); ++ category.setDetail("Entity Name", () -> { ++ return this.getName().getString(); ++ }); ++ category.setDetail("Entity's Exact location", (Object) String.format(Locale.ROOT, "%.2f, %.2f, %.2f", this.getX(), this.getY(), this.getZ())); ++ category.setDetail("Entity's Block location", (Object) CrashReportCategory.formatLocation(this.level(), Mth.floor(this.getX()), Mth.floor(this.getY()), Mth.floor(this.getZ()))); ++ Vec3 vec3d = this.getDeltaMovement(); ++ ++ category.setDetail("Entity's Momentum", (Object) String.format(Locale.ROOT, "%.2f, %.2f, %.2f", vec3d.x, vec3d.y, vec3d.z)); ++ category.setDetail("Entity's Passengers", () -> { ++ return this.getPassengers().toString(); ++ }); ++ category.setDetail("Entity's Vehicle", () -> { ++ return String.valueOf(this.getVehicle()); ++ }); + } + + public boolean displayFireAnimation() { +@@ -2650,144 +3231,164 @@ + } + + public static double getViewScale() { +- return viewScale; ++ return Entity.viewScale; + } + + public static void setViewScale(double renderDistWeight) { +- viewScale = renderDistWeight; ++ Entity.viewScale = renderDistWeight; + } + + @Override + public Component getDisplayName() { +- return PlayerTeam.formatNameForTeam(this.getTeam(), this.getName()) +- .withStyle(style -> style.withHoverEvent(this.createHoverEvent()).withInsertion(this.getStringUUID())); ++ return PlayerTeam.formatNameForTeam(this.getTeam(), this.getName()).withStyle((chatmodifier) -> { ++ return chatmodifier.withHoverEvent(this.createHoverEvent()).withInsertion(this.getStringUUID()); ++ }); + } + + public void setCustomName(@Nullable Component name) { +- this.entityData.set(DATA_CUSTOM_NAME, Optional.ofNullable(name)); ++ this.entityData.set(Entity.DATA_CUSTOM_NAME, Optional.ofNullable(name)); + } + + @Nullable + @Override + public Component getCustomName() { +- return this.entityData.get(DATA_CUSTOM_NAME).orElse(null); ++ return (Component) ((Optional) this.entityData.get(Entity.DATA_CUSTOM_NAME)).orElse((Object) null); + } + + @Override + public boolean hasCustomName() { +- return this.entityData.get(DATA_CUSTOM_NAME).isPresent(); ++ return ((Optional) this.entityData.get(Entity.DATA_CUSTOM_NAME)).isPresent(); + } + + public void setCustomNameVisible(boolean alwaysRenderNameTag) { +- this.entityData.set(DATA_CUSTOM_NAME_VISIBLE, alwaysRenderNameTag); ++ this.entityData.set(Entity.DATA_CUSTOM_NAME_VISIBLE, alwaysRenderNameTag); + } + + public boolean isCustomNameVisible() { +- return this.entityData.get(DATA_CUSTOM_NAME_VISIBLE); ++ return (Boolean) this.entityData.get(Entity.DATA_CUSTOM_NAME_VISIBLE); + } + +- public final void teleportToWithTicket(double x, double y, double z) { ++ public final void teleportToWithTicket(double x, double d1, double y) { + if (this.level() instanceof ServerLevel) { +- ChunkPos chunkPos = new ChunkPos(BlockPos.containing(x, y, z)); +- ((ServerLevel)this.level()).getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, chunkPos, 0, this.getId()); +- this.level().getChunk(chunkPos.x, chunkPos.z); +- this.teleportTo(x, y, z); ++ ChunkPos chunkcoordintpair = new ChunkPos(BlockPos.containing(x, d1, y)); ++ ++ ((ServerLevel) this.level()).getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, chunkcoordintpair, 0, this.getId()); ++ this.level().getChunk(chunkcoordintpair.x, chunkcoordintpair.z); ++ this.teleportTo(x, d1, y); + } + } + +- public boolean teleportTo(ServerLevel level, double x, double y, double z, Set relativeMovements, float yRot, float xRot) { +- float f = Mth.clamp(xRot, -90.0F, 90.0F); ++ // CraftBukkit start ++ public boolean teleportTo(ServerLevel worldserver, double d0, double d1, double d2, Set set, float f, float f1, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { ++ return this.teleportTo(worldserver, d0, d1, d2, set, f, f1); ++ } ++ // CraftBukkit end ++ ++ public boolean teleportTo(ServerLevel level, double x, double d1, double y, Set set, float z, float f1) { ++ float f2 = Mth.clamp(f1, -90.0F, 90.0F); ++ + if (level == this.level()) { +- this.moveTo(x, y, z, yRot, f); ++ this.moveTo(x, d1, y, z, f2); + this.teleportPassengers(); +- this.setYHeadRot(yRot); ++ this.setYHeadRot(z); + } else { + this.unRide(); + Entity entity = this.getType().create(level); ++ + if (entity == null) { + return false; + } + + entity.restoreFrom(this); +- entity.moveTo(x, y, z, yRot, f); +- entity.setYHeadRot(yRot); ++ entity.moveTo(x, d1, y, z, f2); ++ entity.setYHeadRot(z); + this.setRemoved(Entity.RemovalReason.CHANGED_DIMENSION); +- level.addDuringTeleport(entity); ++ // CraftBukkit start - Don't spawn the new entity if the current entity isn't spawned ++ if (inWorld) { ++ level.addDuringTeleport(entity); ++ } ++ // CraftBukkit end + } + + return true; + } + +- public void dismountTo(double x, double y, double z) { +- this.teleportTo(x, y, z); ++ public void dismountTo(double x, double d1, double y) { ++ this.teleportTo(x, d1, y); + } + +- public void teleportTo(double x, double y, double z) { ++ public void teleportTo(double x, double d1, double y) { + if (this.level() instanceof ServerLevel) { +- this.moveTo(x, y, z, this.getYRot(), this.getXRot()); ++ this.moveTo(x, d1, y, this.getYRot(), this.getXRot()); + this.teleportPassengers(); + } + } + + private void teleportPassengers() { +- this.getSelfAndPassengers().forEach(entity -> { +- for (Entity entity1 : entity.passengers) { ++ this.getSelfAndPassengers().forEach((entity) -> { ++ UnmodifiableIterator unmodifiableiterator = entity.passengers.iterator(); ++ ++ while (unmodifiableiterator.hasNext()) { ++ Entity entity1 = (Entity) unmodifiableiterator.next(); ++ + entity.positionRider(entity1, Entity::moveTo); + } ++ + }); + } + +- public void teleportRelative(double dx, double dy, double dz) { +- this.teleportTo(this.getX() + dx, this.getY() + dy, this.getZ() + dz); ++ public void teleportRelative(double dx, double d1, double dy) { ++ this.teleportTo(this.getX() + dx, this.getY() + d1, this.getZ() + dy); + } + + public boolean shouldShowName() { + return this.isCustomNameVisible(); + } + +- public void onSyncedDataUpdated(List> dataValues) { +- } ++ public void onSyncedDataUpdated(List> dataValues) {} + + public void onSyncedDataUpdated(EntityDataAccessor key) { +- if (DATA_POSE.equals(key)) { ++ if (Entity.DATA_POSE.equals(key)) { + this.refreshDimensions(); + } ++ + } + ++ /** @deprecated */ + @Deprecated + protected void fixupDimensions() { +- Pose pose = this.getPose(); +- EntityDimensions dimensions = this.getDimensions(pose); +- this.dimensions = dimensions; +- this.eyeHeight = this.getEyeHeight(pose, dimensions); ++ EntityPose entitypose = this.getPose(); ++ EntityDimensions entitysize = this.getDimensions(entitypose); ++ ++ this.dimensions = entitysize; ++ this.eyeHeight = this.getEyeHeight(entitypose, entitysize); + } + + public void refreshDimensions() { +- EntityDimensions entityDimensions = this.dimensions; +- Pose pose = this.getPose(); +- EntityDimensions dimensions = this.getDimensions(pose); +- this.dimensions = dimensions; +- this.eyeHeight = this.getEyeHeight(pose, dimensions); ++ EntityDimensions entitysize = this.dimensions; ++ EntityPose entitypose = this.getPose(); ++ EntityDimensions entitysize1 = this.getDimensions(entitypose); ++ ++ this.dimensions = entitysize1; ++ this.eyeHeight = this.getEyeHeight(entitypose, entitysize1); + this.reapplyPosition(); +- boolean flag = (double)dimensions.width <= 4.0 && (double)dimensions.height <= 4.0; +- if (!this.level().isClientSide +- && !this.firstTick +- && !this.noPhysics +- && flag +- && (dimensions.width > entityDimensions.width || dimensions.height > entityDimensions.height) +- && !(this instanceof Player)) { +- Vec3 vec3 = this.position().add(0.0, (double)entityDimensions.height / 2.0, 0.0); +- double d = (double)Math.max(0.0F, dimensions.width - entityDimensions.width) + 1.0E-6; +- double d1 = (double)Math.max(0.0F, dimensions.height - entityDimensions.height) + 1.0E-6; +- VoxelShape voxelShape = Shapes.create(AABB.ofSize(vec3, d, d1, d)); +- this.level() +- .findFreePosition(this, voxelShape, vec3, (double)dimensions.width, (double)dimensions.height, (double)dimensions.width) +- .ifPresent(vec31 -> this.setPos(vec31.add(0.0, (double)(-dimensions.height) / 2.0, 0.0))); ++ boolean flag = (double) entitysize1.width <= 4.0D && (double) entitysize1.height <= 4.0D; ++ ++ if (!this.level().isClientSide && !this.firstTick && !this.noPhysics && flag && (entitysize1.width > entitysize.width || entitysize1.height > entitysize.height) && !(this instanceof Player)) { ++ Vec3 vec3d = this.position().add(0.0D, (double) entitysize.height / 2.0D, 0.0D); ++ double d0 = (double) Math.max(0.0F, entitysize1.width - entitysize.width) + 1.0E-6D; ++ double d1 = (double) Math.max(0.0F, entitysize1.height - entitysize.height) + 1.0E-6D; ++ VoxelShape voxelshape = Shapes.create(AABB.ofSize(vec3d, d0, d1, d0)); ++ ++ this.level().findFreePosition(this, voxelshape, vec3d, (double) entitysize1.width, (double) entitysize1.height, (double) entitysize1.width).ifPresent((vec3d1) -> { ++ this.setPos(vec3d1.add(0.0D, (double) (-entitysize1.height) / 2.0D, 0.0D)); ++ }); + } ++ + } + + public Direction getDirection() { +- return Direction.fromYRot((double)this.getYRot()); ++ return Direction.fromYRot((double) this.getYRot()); + } + + public Direction getMotionDirection() { +@@ -2812,14 +3413,33 @@ + } + + public final void setBoundingBox(AABB bb) { +- this.bb = bb; ++ // CraftBukkit start - block invalid bounding boxes ++ double minX = bb.minX, ++ minY = bb.minY, ++ minZ = bb.minZ, ++ maxX = bb.maxX, ++ maxY = bb.maxY, ++ maxZ = bb.maxZ; ++ double len = bb.maxX - bb.minX; ++ if (len < 0) maxX = minX; ++ if (len > 64) maxX = minX + 64.0; ++ ++ len = bb.maxY - bb.minY; ++ if (len < 0) maxY = minY; ++ if (len > 64) maxY = minY + 64.0; ++ ++ len = bb.maxZ - bb.minZ; ++ if (len < 0) maxZ = minZ; ++ if (len > 64) maxZ = minZ + 64.0; ++ this.bb = new AABB(minX, minY, minZ, maxX, maxY, maxZ); ++ // CraftBukkit end + } + +- protected float getEyeHeight(Pose pose, EntityDimensions dimensions) { ++ protected float getEyeHeight(EntityPose pose, EntityDimensions dimensions) { + return dimensions.height * 0.85F; + } + +- public float getEyeHeight(Pose pose) { ++ public float getEyeHeight(EntityPose pose) { + return this.getEyeHeight(pose, this.getDimensions(pose)); + } + +@@ -2832,7 +3452,7 @@ + } + + protected Vec3 getLeashOffset() { +- return new Vec3(0.0, (double)this.getEyeHeight(), (double)(this.getBbWidth() * 0.4F)); ++ return new Vec3(0.0D, (double) this.getEyeHeight(), (double) (this.getBbWidth() * 0.4F)); + } + + public SlotAccess getSlot(int slot) { +@@ -2840,8 +3460,7 @@ + } + + @Override +- public void sendSystemMessage(Component component) { +- } ++ public void sendSystemMessage(Component component) {} + + public Level getCommandSenderWorld() { + return this.level(); +@@ -2852,7 +3471,7 @@ + return this.level().getServer(); + } + +- public InteractionResult interactAt(Player player, Vec3 vec, InteractionHand hand) { ++ public InteractionResult interactAt(Player player, Vec3 vec, EnumHand hand) { + return InteractionResult.PASS; + } + +@@ -2860,22 +3479,21 @@ + return false; + } + +- public void doEnchantDamageEffects(LivingEntity attacker, Entity target) { +- if (target instanceof LivingEntity) { +- EnchantmentHelper.doPostHurtEffects((LivingEntity)target, attacker); ++ public void doEnchantDamageEffects(net.minecraft.world.entity.LivingEntity attacker, Entity target) { ++ if (target instanceof net.minecraft.world.entity.LivingEntity) { ++ EnchantmentHelper.doPostHurtEffects((net.minecraft.world.entity.LivingEntity) target, attacker); + } + + EnchantmentHelper.doPostDamageEffects(attacker, target); + } + +- public void startSeenByPlayer(ServerPlayer serverPlayer) { +- } ++ public void startSeenByPlayer(ServerPlayer serverPlayer) {} + +- public void stopSeenByPlayer(ServerPlayer serverPlayer) { +- } ++ public void stopSeenByPlayer(ServerPlayer serverPlayer) {} + + public float rotate(Rotation transformRotation) { + float f = Mth.wrapDegrees(this.getYRot()); ++ + switch (transformRotation) { + case CLOCKWISE_180: + return f + 180.0F; +@@ -2890,6 +3508,7 @@ + + public float mirror(Mirror transformMirror) { + float f = Mth.wrapDegrees(this.getYRot()); ++ + switch (transformMirror) { + case FRONT_BACK: + return -f; +@@ -2905,7 +3524,7 @@ + } + + @Nullable +- public LivingEntity getControllingPassenger() { ++ public net.minecraft.world.entity.LivingEntity getControllingPassenger() { + return null; + } + +@@ -2919,7 +3538,7 @@ + + @Nullable + public Entity getFirstPassenger() { +- return this.passengers.isEmpty() ? null : this.passengers.get(0); ++ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); + } + + public boolean hasPassenger(Entity entity) { +@@ -2927,13 +3546,19 @@ + } + + public boolean hasPassenger(Predicate predicate) { +- for (Entity entity : this.passengers) { +- if (predicate.test(entity)) { +- return true; ++ UnmodifiableIterator unmodifiableiterator = this.passengers.iterator(); ++ ++ Entity entity; ++ ++ do { ++ if (!unmodifiableiterator.hasNext()) { ++ return false; + } +- } + +- return false; ++ entity = (Entity) unmodifiableiterator.next(); ++ } while (!predicate.test(entity)); ++ ++ return true; + } + + private Stream getIndirectPassengersStream() { +@@ -2951,11 +3576,15 @@ + } + + public Iterable getIndirectPassengers() { +- return () -> this.getIndirectPassengersStream().iterator(); ++ return () -> { ++ return this.getIndirectPassengersStream().iterator(); ++ }; + } + + public int countPlayerPassengers() { +- return (int)this.getIndirectPassengersStream().filter(entity -> entity instanceof Player).count(); ++ return (int) this.getIndirectPassengersStream().filter((entity) -> { ++ return entity instanceof Player; ++ }).count(); + } + + public boolean hasExactlyOnePlayerPassenger() { +@@ -2963,10 +3592,10 @@ + } + + public Entity getRootVehicle() { +- Entity entity = this; ++ Entity entity; + +- while (entity.isPassenger()) { +- entity = entity.getVehicle(); ++ for (entity = this; entity.isPassenger(); entity = entity.getVehicle()) { ++ ; + } + + return entity; +@@ -2980,28 +3609,38 @@ + if (!entity.isPassenger()) { + return false; + } else { +- Entity vehicle = entity.getVehicle(); +- return vehicle == this || this.hasIndirectPassenger(vehicle); ++ Entity entity1 = entity.getVehicle(); ++ ++ return entity1 == this ? true : this.hasIndirectPassenger(entity1); + } + } + + public boolean isControlledByLocalInstance() { +- return this.getControllingPassenger() instanceof Player player ? player.isLocalPlayer() : this.isEffectiveAi(); ++ net.minecraft.world.entity.LivingEntity entityliving = this.getControllingPassenger(); ++ ++ if (entityliving instanceof Player) { ++ Player entityhuman = (Player) entityliving; ++ ++ return entityhuman.isLocalPlayer(); ++ } else { ++ return this.isEffectiveAi(); ++ } + } + + public boolean isEffectiveAi() { + return !this.level().isClientSide; + } + +- protected static Vec3 getCollisionHorizontalEscapeVector(double vehicleWidth, double passengerWidth, float yRot) { +- double d = (vehicleWidth + passengerWidth + 1.0E-5F) / 2.0; +- float f = -Mth.sin(yRot * (float) (Math.PI / 180.0)); +- float cos = Mth.cos(yRot * (float) (Math.PI / 180.0)); +- float max = Math.max(Math.abs(f), Math.abs(cos)); +- return new Vec3((double)f * d / (double)max, 0.0, (double)cos * d / (double)max); ++ protected static Vec3 getCollisionHorizontalEscapeVector(double vehicleWidth, double d1, float passengerWidth) { ++ double d2 = (vehicleWidth + d1 + 9.999999747378752E-6D) / 2.0D; ++ float f1 = -Mth.sin(passengerWidth * 0.017453292F); ++ float f2 = Mth.cos(passengerWidth * 0.017453292F); ++ float f3 = Math.max(Math.abs(f1), Math.abs(f2)); ++ ++ return new Vec3((double) f1 * d2 / (double) f3, 0.0D, (double) f2 * d2 / (double) f3); + } + +- public Vec3 getDismountLocationForPassenger(LivingEntity passenger) { ++ public Vec3 getDismountLocationForPassenger(net.minecraft.world.entity.LivingEntity passenger) { + return new Vec3(this.getX(), this.getBoundingBox().maxY, this.getZ()); + } + +@@ -3015,30 +3654,20 @@ + return this.vehicle != null && this.vehicle.getControllingPassenger() == this ? this.vehicle : null; + } + +- public PushReaction getPistonPushReaction() { +- return PushReaction.NORMAL; ++ public EnumPistonReaction getPistonPushReaction() { ++ return EnumPistonReaction.NORMAL; + } + + public SoundSource getSoundSource() { + return SoundSource.NEUTRAL; + } + +- protected int getFireImmuneTicks() { ++ public int getFireImmuneTicks() { + return 1; + } + + public CommandSourceStack createCommandSourceStack() { +- return new CommandSourceStack( +- this, +- this.position(), +- this.getRotationVector(), +- this.level() instanceof ServerLevel ? (ServerLevel)this.level() : null, +- this.getPermissionLevel(), +- this.getName().getString(), +- this.getDisplayName(), +- this.level().getServer(), +- this +- ); ++ return new CommandSourceStack(this, this.position(), this.getRotationVector(), this.level() instanceof ServerLevel ? (ServerLevel) this.level() : null, this.getPermissionLevel(), this.getName().getString(), this.getDisplayName(), this.level().getServer(), this); + } + + protected int getPermissionLevel() { +@@ -3065,13 +3694,14 @@ + } + + public void lookAt(EntityAnchorArgument.Anchor anchor, Vec3 target) { +- Vec3 vec3 = anchor.apply(this); +- double d = target.x - vec3.x; +- double d1 = target.y - vec3.y; +- double d2 = target.z - vec3.z; +- double squareRoot = Math.sqrt(d * d + d2 * d2); +- this.setXRot(Mth.wrapDegrees((float)(-(Mth.atan2(d1, squareRoot) * 180.0F / (float)Math.PI)))); +- this.setYRot(Mth.wrapDegrees((float)(Mth.atan2(d2, d) * 180.0F / (float)Math.PI) - 90.0F)); ++ Vec3 vec3d1 = anchor.apply(this); ++ double d0 = target.x - vec3d1.x; ++ double d1 = target.y - vec3d1.y; ++ double d2 = target.z - vec3d1.z; ++ double d3 = Math.sqrt(d0 * d0 + d2 * d2); ++ ++ this.setXRot(Mth.wrapDegrees((float) (-(Mth.atan2(d1, d3) * 57.2957763671875D)))); ++ this.setYRot(Mth.wrapDegrees((float) (Mth.atan2(d2, d0) * 57.2957763671875D) - 90.0F)); + this.setYHeadRot(this.getYRot()); + this.xRotO = this.getXRot(); + this.yRotO = this.getYRot(); +@@ -3081,76 +3711,87 @@ + if (this.touchingUnloadedChunk()) { + return false; + } else { +- AABB aABB = this.getBoundingBox().deflate(0.001); +- int floor = Mth.floor(aABB.minX); +- int ceil = Mth.ceil(aABB.maxX); +- int floor1 = Mth.floor(aABB.minY); +- int ceil1 = Mth.ceil(aABB.maxY); +- int floor2 = Mth.floor(aABB.minZ); +- int ceil2 = Mth.ceil(aABB.maxZ); +- double d = 0.0; +- boolean isPushedByFluid = this.isPushedByFluid(); +- boolean flag = false; +- Vec3 vec3 = Vec3.ZERO; +- int i = 0; +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ AABB axisalignedbb = this.getBoundingBox().deflate(0.001D); ++ int i = Mth.floor(axisalignedbb.minX); ++ int j = Mth.ceil(axisalignedbb.maxX); ++ int k = Mth.floor(axisalignedbb.minY); ++ int l = Mth.ceil(axisalignedbb.maxY); ++ int i1 = Mth.floor(axisalignedbb.minZ); ++ int j1 = Mth.ceil(axisalignedbb.maxZ); ++ double d1 = 0.0D; ++ boolean flag = this.isPushedByFluid(); ++ boolean flag1 = false; ++ Vec3 vec3d = Vec3.ZERO; ++ int k1 = 0; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + +- for (int i1 = floor; i1 < ceil; i1++) { +- for (int i2 = floor1; i2 < ceil1; i2++) { +- for (int i3 = floor2; i3 < ceil2; i3++) { +- mutableBlockPos.set(i1, i2, i3); +- FluidState fluidState = this.level().getFluidState(mutableBlockPos); +- if (fluidState.is(fluidTag)) { +- double d1 = (double)((float)i2 + fluidState.getHeight(this.level(), mutableBlockPos)); +- if (d1 >= aABB.minY) { +- flag = true; +- d = Math.max(d1 - aABB.minY, d); +- if (isPushedByFluid) { +- Vec3 flow = fluidState.getFlow(this.level(), mutableBlockPos); +- if (d < 0.4) { +- flow = flow.scale(d); ++ for (int l1 = i; l1 < j; ++l1) { ++ for (int i2 = k; i2 < l; ++i2) { ++ for (int j2 = i1; j2 < j1; ++j2) { ++ blockposition_mutableblockposition.set(l1, i2, j2); ++ FluidState fluid = this.level().getFluidState(blockposition_mutableblockposition); ++ ++ if (fluid.is(fluidTag)) { ++ double d2 = (double) ((float) i2 + fluid.getHeight(this.level(), blockposition_mutableblockposition)); ++ ++ if (d2 >= axisalignedbb.minY) { ++ flag1 = true; ++ d1 = Math.max(d2 - axisalignedbb.minY, d1); ++ if (flag) { ++ Vec3 vec3d1 = fluid.getFlow(this.level(), blockposition_mutableblockposition); ++ ++ if (d1 < 0.4D) { ++ vec3d1 = vec3d1.scale(d1); + } + +- vec3 = vec3.add(flow); +- i++; ++ vec3d = vec3d.add(vec3d1); ++ ++k1; + } ++ // CraftBukkit start - store last lava contact location ++ if (fluidTag == FluidTags.LAVA) { ++ this.lastLavaContact = blockposition_mutableblockposition.immutable(); ++ } ++ // CraftBukkit end + } + } + } + } + } + +- if (vec3.length() > 0.0) { +- if (i > 0) { +- vec3 = vec3.scale(1.0 / (double)i); ++ if (vec3d.length() > 0.0D) { ++ if (k1 > 0) { ++ vec3d = vec3d.scale(1.0D / (double) k1); + } + + if (!(this instanceof Player)) { +- vec3 = vec3.normalize(); ++ vec3d = vec3d.normalize(); + } + +- Vec3 deltaMovement = this.getDeltaMovement(); +- Vec3 var25 = vec3.scale(motionScale * 1.0); +- double d2 = 0.003; +- if (Math.abs(deltaMovement.x) < 0.003 && Math.abs(deltaMovement.z) < 0.003 && var25.length() < 0.0045000000000000005) { +- var25 = var25.normalize().scale(0.0045000000000000005); ++ Vec3 vec3d2 = this.getDeltaMovement(); ++ ++ vec3d = vec3d.scale(motionScale * 1.0D); ++ double d3 = 0.003D; ++ ++ if (Math.abs(vec3d2.x) < 0.003D && Math.abs(vec3d2.z) < 0.003D && vec3d.length() < 0.0045000000000000005D) { ++ vec3d = vec3d.normalize().scale(0.0045000000000000005D); + } + +- this.setDeltaMovement(this.getDeltaMovement().add(var25)); ++ this.setDeltaMovement(this.getDeltaMovement().add(vec3d)); + } + +- this.fluidHeight.put(fluidTag, d); +- return flag; ++ this.fluidHeight.put(fluidTag, d1); ++ return flag1; + } + } + + public boolean touchingUnloadedChunk() { +- AABB aABB = this.getBoundingBox().inflate(1.0); +- int floor = Mth.floor(aABB.minX); +- int ceil = Mth.ceil(aABB.maxX); +- int floor1 = Mth.floor(aABB.minZ); +- int ceil1 = Mth.ceil(aABB.maxZ); +- return !this.level().hasChunksAt(floor, floor1, ceil, ceil1); ++ AABB axisalignedbb = this.getBoundingBox().inflate(1.0D); ++ int i = Mth.floor(axisalignedbb.minX); ++ int j = Mth.ceil(axisalignedbb.maxX); ++ int k = Mth.floor(axisalignedbb.minZ); ++ int l = Mth.ceil(axisalignedbb.maxZ); ++ ++ return !this.level().hasChunksAt(i, k, j, l); + } + + public double getFluidHeight(TagKey fluidTag) { +@@ -3158,7 +3799,7 @@ + } + + public double getFluidJumpThreshold() { +- return (double)this.getEyeHeight() < 0.4 ? 0.0 : 0.4; ++ return (double) this.getEyeHeight() < 0.4D ? 0.0D : 0.4D; + } + + public final float getBbWidth() { +@@ -3177,7 +3818,7 @@ + return new ClientboundAddEntityPacket(this); + } + +- public EntityDimensions getDimensions(Pose pose) { ++ public EntityDimensions getDimensions(EntityPose pose) { + return this.type.getDimensions(); + } + +@@ -3194,7 +3835,7 @@ + return this.blockPosition; + } + +- public BlockState getFeetBlockState() { ++ public IBlockData getFeetBlockState() { + if (this.feetBlockState == null) { + this.feetBlockState = this.level().getBlockState(this.blockPosition()); + } +@@ -3218,8 +3859,8 @@ + this.setDeltaMovement(this.getDeltaMovement().add(addend)); + } + +- public void setDeltaMovement(double x, double y, double z) { +- this.setDeltaMovement(new Vec3(x, y, z)); ++ public void setDeltaMovement(double x, double d1, double y) { ++ this.setDeltaMovement(new Vec3(x, d1, y)); + } + + public final int getBlockX() { +@@ -3231,11 +3872,11 @@ + } + + public double getX(double scale) { +- return this.position.x + (double)this.getBbWidth() * scale; ++ return this.position.x + (double) this.getBbWidth() * scale; + } + + public double getRandomX(double scale) { +- return this.getX((2.0 * this.random.nextDouble() - 1.0) * scale); ++ return this.getX((2.0D * this.random.nextDouble() - 1.0D) * scale); + } + + public final int getBlockY() { +@@ -3247,7 +3888,7 @@ + } + + public double getY(double scale) { +- return this.position.y + (double)this.getBbHeight() * scale; ++ return this.position.y + (double) this.getBbHeight() * scale; + } + + public double getRandomY() { +@@ -3255,7 +3896,7 @@ + } + + public double getEyeY() { +- return this.position.y + (double)this.eyeHeight; ++ return this.position.y + (double) this.eyeHeight; + } + + public final int getBlockZ() { +@@ -3267,48 +3908,50 @@ + } + + public double getZ(double scale) { +- return this.position.z + (double)this.getBbWidth() * scale; ++ return this.position.z + (double) this.getBbWidth() * scale; + } + + public double getRandomZ(double scale) { +- return this.getZ((2.0 * this.random.nextDouble() - 1.0) * scale); ++ return this.getZ((2.0D * this.random.nextDouble() - 1.0D) * scale); + } + +- public final void setPosRaw(double x, double y, double z) { +- if (this.position.x != x || this.position.y != y || this.position.z != z) { +- this.position = new Vec3(x, y, z); +- int floor = Mth.floor(x); +- int floor1 = Mth.floor(y); +- int floor2 = Mth.floor(z); +- if (floor != this.blockPosition.getX() || floor1 != this.blockPosition.getY() || floor2 != this.blockPosition.getZ()) { +- this.blockPosition = new BlockPos(floor, floor1, floor2); ++ public final void setPosRaw(double x, double d1, double y) { ++ if (this.position.x != x || this.position.y != d1 || this.position.z != y) { ++ this.position = new Vec3(x, d1, y); ++ int i = Mth.floor(x); ++ int j = Mth.floor(d1); ++ int k = Mth.floor(y); ++ ++ if (i != this.blockPosition.getX() || j != this.blockPosition.getY() || k != this.blockPosition.getZ()) { ++ this.blockPosition = new BlockPos(i, j, k); + this.feetBlockState = null; +- if (SectionPos.blockToSectionCoord(floor) != this.chunkPosition.x || SectionPos.blockToSectionCoord(floor2) != this.chunkPosition.z) { ++ if (SectionPos.blockToSectionCoord(i) != this.chunkPosition.x || SectionPos.blockToSectionCoord(k) != this.chunkPosition.z) { + this.chunkPosition = new ChunkPos(this.blockPosition); + } + } + + this.levelCallback.onMove(); + } +- } + +- public void checkDespawn() { + } + ++ public void checkDespawn() {} ++ + public Vec3 getRopeHoldPosition(float partialTicks) { +- return this.getPosition(partialTicks).add(0.0, (double)this.eyeHeight * 0.7, 0.0); ++ return this.getPosition(partialTicks).add(0.0D, (double) this.eyeHeight * 0.7D, 0.0D); + } + + public void recreateFromPacket(ClientboundAddEntityPacket packet) { +- int id = packet.getId(); +- double x = packet.getX(); +- double y = packet.getY(); +- double z = packet.getZ(); +- this.syncPacketPositionCodec(x, y, z); +- this.moveTo(x, y, z); ++ int i = packet.getId(); ++ double d0 = packet.getX(); ++ double d1 = packet.getY(); ++ double d2 = packet.getZ(); ++ ++ this.syncPacketPositionCodec(d0, d1, d2); ++ this.moveTo(d0, d1, d2); + this.setXRot(packet.getXRot()); + this.setYRot(packet.getYRot()); +- this.setId(id); ++ this.setId(i); + this.setUUID(packet.getUUID()); + } + +@@ -3392,7 +4035,7 @@ + this.levelCallback.onRemove(removalReason); + } + +- protected void unsetRemoved() { ++ public void unsetRemoved() { + this.removalReason = null; + } + +@@ -3403,9 +4046,7 @@ + + @Override + public boolean shouldBeSaved() { +- return (this.removalReason == null || this.removalReason.shouldSave()) +- && !this.isPassenger() +- && (!this.isVehicle() || !this.hasExactlyOnePlayerPassenger()); ++ return this.removalReason != null && !this.removalReason.shouldSave() ? false : (this.isPassenger() ? false : !this.isVehicle() || !this.hasExactlyOnePlayerPassenger()); + } + + @Override +@@ -3429,34 +4070,49 @@ + return this.level().damageSources(); + } + +- protected void lerpPositionAndRotationStep(int i, double d, double d1, double d2, double d3, double d4) { +- double d5 = 1.0 / (double)i; +- double d6 = Mth.lerp(d5, this.getX(), d); ++ protected void lerpPositionAndRotationStep(int i, double d0, double d1, double d2, double d3, double d4) { ++ double d5 = 1.0D / (double) i; ++ double d6 = Mth.lerp(d5, this.getX(), d0); + double d7 = Mth.lerp(d5, this.getY(), d1); + double d8 = Mth.lerp(d5, this.getZ(), d2); +- float f = (float)Mth.rotLerp(d5, (double)this.getYRot(), d3); +- float f1 = (float)Mth.lerp(d5, (double)this.getXRot(), d4); ++ float f = (float) Mth.rotLerp(d5, (double) this.getYRot(), d3); ++ float f1 = (float) Mth.lerp(d5, (double) this.getXRot(), d4); ++ + this.setPos(d6, d7, d8); + this.setRot(f, f1); + } + +- @FunctionalInterface +- public interface MoveFunction { +- void accept(Entity entity, double x, double d, double y); ++ public static enum RemovalReason { ++ ++ KILLED(true, false), DISCARDED(true, false), UNLOADED_TO_CHUNK(false, true), UNLOADED_WITH_PLAYER(false, false), CHANGED_DIMENSION(false, false); ++ ++ private final boolean destroy; ++ private final boolean save; ++ ++ private RemovalReason(boolean flag, boolean flag1) { ++ this.destroy = flag; ++ this.save = flag1; ++ } ++ ++ public boolean shouldDestroy() { ++ return this.destroy; ++ } ++ ++ public boolean shouldSave() { ++ return this.save; ++ } + } + + public static enum MovementEmission { +- NONE(false, false), +- SOUNDS(true, false), +- EVENTS(false, true), +- ALL(true, true); + ++ NONE(false, false), SOUNDS(true, false), EVENTS(false, true), ALL(true, true); ++ + final boolean sounds; + final boolean events; + +- private MovementEmission(boolean sounds, boolean events) { +- this.sounds = sounds; +- this.events = events; ++ private MovementEmission(boolean flag, boolean flag1) { ++ this.sounds = flag; ++ this.events = flag1; + } + + public boolean emitsAnything() { +@@ -3472,27 +4128,9 @@ + } + } + +- public static enum RemovalReason { +- KILLED(true, false), +- DISCARDED(true, false), +- UNLOADED_TO_CHUNK(false, true), +- UNLOADED_WITH_PLAYER(false, false), +- CHANGED_DIMENSION(false, false); ++ @FunctionalInterface ++ public interface MoveFunction { + +- private final boolean destroy; +- private final boolean save; +- +- private RemovalReason(boolean destroy, boolean save) { +- this.destroy = destroy; +- this.save = save; +- } +- +- public boolean shouldDestroy() { +- return this.destroy; +- } +- +- public boolean shouldSave() { +- return this.save; +- } ++ void accept(Entity entity, double x, double d1, double y); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/EntitySelector.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/EntitySelector.java.patch new file mode 100644 index 0000000000..8de0056976 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/EntitySelector.java.patch @@ -0,0 +1,143 @@ +--- a/net/minecraft/world/entity/EntitySelector.java ++++ b/net/minecraft/world/entity/EntitySelector.java +@@ -6,75 +6,98 @@ + import net.minecraft.world.Container; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.scores.PlayerTeam; + import net.minecraft.world.scores.Team; + + public final class EntitySelector { ++ + public static final Predicate ENTITY_STILL_ALIVE = Entity::isAlive; +- public static final Predicate LIVING_ENTITY_STILL_ALIVE = entity -> entity.isAlive() && entity instanceof LivingEntity; +- public static final Predicate ENTITY_NOT_BEING_RIDDEN = entity -> entity.isAlive() && !entity.isVehicle() && !entity.isPassenger(); +- public static final Predicate CONTAINER_ENTITY_SELECTOR = entity -> entity instanceof Container && entity.isAlive(); +- public static final Predicate NO_CREATIVE_OR_SPECTATOR = entity -> !(entity instanceof Player) +- || !entity.isSpectator() && !((Player)entity).isCreative(); +- public static final Predicate NO_SPECTATORS = entity -> !entity.isSpectator(); +- public static final Predicate CAN_BE_COLLIDED_WITH = NO_SPECTATORS.and(Entity::canBeCollidedWith); ++ public static final Predicate LIVING_ENTITY_STILL_ALIVE = (entity) -> { ++ return entity.isAlive() && entity instanceof LivingEntity; ++ }; ++ public static final Predicate ENTITY_NOT_BEING_RIDDEN = (entity) -> { ++ return entity.isAlive() && !entity.isVehicle() && !entity.isPassenger(); ++ }; ++ public static final Predicate CONTAINER_ENTITY_SELECTOR = (entity) -> { ++ return entity instanceof Container && entity.isAlive(); ++ }; ++ public static final Predicate NO_CREATIVE_OR_SPECTATOR = (entity) -> { ++ return !(entity instanceof Player) || !entity.isSpectator() && !((Player) entity).isCreative(); ++ }; ++ public static final Predicate NO_SPECTATORS = (entity) -> { ++ return !entity.isSpectator(); ++ }; ++ public static final Predicate CAN_BE_COLLIDED_WITH = EntitySelector.NO_SPECTATORS.and(Entity::canBeCollidedWith); + +- private EntitySelector() { +- } ++ private EntitySelector() {} + +- public static Predicate withinDistance(double x, double y, double z, double range) { +- double d = range * range; +- return entity -> entity != null && entity.distanceToSqr(x, y, z) <= d; ++ public static Predicate withinDistance(double x, double d1, double y, double d3) { ++ double d4 = d3 * d3; ++ ++ return (entity) -> { ++ return entity != null && entity.distanceToSqr(x, d1, y) <= d4; ++ }; + } + + public static Predicate pushableBy(Entity entity) { +- Team team = entity.getTeam(); +- Team.CollisionRule collisionRule = team == null ? Team.CollisionRule.ALWAYS : team.getCollisionRule(); +- return (Predicate)(collisionRule == Team.CollisionRule.NEVER +- ? Predicates.alwaysFalse() +- : NO_SPECTATORS.and( +- pushedEntity -> { +- if (!pushedEntity.isPushable()) { +- return false; +- } else if (!entity.level().isClientSide || pushedEntity instanceof Player && ((Player)pushedEntity).isLocalPlayer()) { +- Team team1 = pushedEntity.getTeam(); +- Team.CollisionRule collisionRule1 = team1 == null ? Team.CollisionRule.ALWAYS : team1.getCollisionRule(); +- if (collisionRule1 == Team.CollisionRule.NEVER) { +- return false; +- } else { +- boolean flag = team != null && team.isAlliedTo(team1); +- return (collisionRule != Team.CollisionRule.PUSH_OWN_TEAM && collisionRule1 != Team.CollisionRule.PUSH_OWN_TEAM || !flag) +- && (collisionRule != Team.CollisionRule.PUSH_OTHER_TEAMS && collisionRule1 != Team.CollisionRule.PUSH_OTHER_TEAMS || flag); +- } +- } else { +- return false; +- } ++ PlayerTeam scoreboardteam = entity.getTeam(); ++ Team.CollisionRule scoreboardteambase_enumteampush = scoreboardteam == null ? Team.CollisionRule.ALWAYS : scoreboardteam.getCollisionRule(); ++ ++ return (Predicate) (scoreboardteambase_enumteampush == Team.CollisionRule.NEVER ? Predicates.alwaysFalse() : EntitySelector.NO_SPECTATORS.and((entity1) -> { ++ if (!entity1.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(entity1)) { // CraftBukkit - collidable API ++ return false; ++ } else if (entity.level().isClientSide && (!(entity1 instanceof Player) || !((Player) entity1).isLocalPlayer())) { ++ return false; ++ } else { ++ PlayerTeam scoreboardteam1 = entity1.getTeam(); ++ Team.CollisionRule scoreboardteambase_enumteampush1 = scoreboardteam1 == null ? Team.CollisionRule.ALWAYS : scoreboardteam1.getCollisionRule(); ++ ++ if (scoreboardteambase_enumteampush1 == Team.CollisionRule.NEVER) { ++ return false; ++ } else { ++ boolean flag = scoreboardteam != null && scoreboardteam.isAlliedTo(scoreboardteam1); ++ ++ return (scoreboardteambase_enumteampush == Team.CollisionRule.PUSH_OWN_TEAM || scoreboardteambase_enumteampush1 == Team.CollisionRule.PUSH_OWN_TEAM) && flag ? false : scoreboardteambase_enumteampush != Team.CollisionRule.PUSH_OTHER_TEAMS && scoreboardteambase_enumteampush1 != Team.CollisionRule.PUSH_OTHER_TEAMS || flag; + } +- )); ++ } ++ })); + } + + public static Predicate notRiding(Entity entity) { +- return passenger -> { +- while (passenger.isPassenger()) { +- passenger = passenger.getVehicle(); +- if (passenger == entity) { ++ return (entity1) -> { ++ while (true) { ++ if (entity1.isPassenger()) { ++ entity1 = entity1.getVehicle(); ++ if (entity1 != entity) { ++ continue; ++ } ++ + return false; + } +- } + +- return true; ++ return true; ++ } + }; + } + + public static class MobCanWearArmorEntitySelector implements Predicate { ++ + private final ItemStack itemStack; + + public MobCanWearArmorEntitySelector(ItemStack stack) { + this.itemStack = stack; + } + +- @Override + public boolean test(@Nullable Entity entity) { +- return entity.isAlive() && entity instanceof LivingEntity livingEntity && livingEntity.canTakeItem(this.itemStack); ++ if (!entity.isAlive()) { ++ return false; ++ } else if (!(entity instanceof LivingEntity)) { ++ return false; ++ } else { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ return entityliving.canTakeItem(this.itemStack); ++ } + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/EntityType.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/EntityType.java.patch new file mode 100644 index 0000000000..66ca0a0f07 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/EntityType.java.patch @@ -0,0 +1,1056 @@ +--- a/net/minecraft/world/entity/EntityType.java ++++ b/net/minecraft/world/entity/EntityType.java +@@ -27,7 +27,7 @@ + import net.minecraft.server.level.ServerLevel; + import net.minecraft.tags.TagKey; + import net.minecraft.util.Mth; +-import net.minecraft.util.datafix.fixes.References; ++import net.minecraft.util.datafix.fixes.DataConverterTypes; + import net.minecraft.world.entity.ambient.Bat; + import net.minecraft.world.entity.animal.Bee; + import net.minecraft.world.entity.animal.Cat; +@@ -154,422 +154,148 @@ + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.entity.EntityTypeTest; + import net.minecraft.world.level.pathfinder.WalkNodeEvaluator; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.entity.CreatureSpawnEvent; + import org.slf4j.Logger; + + public class EntityType implements FeatureElement, EntityTypeTest { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + public static final String ENTITY_TAG = "EntityTag"; +- private final Holder.Reference> builtInRegistryHolder = BuiltInRegistries.ENTITY_TYPE.createIntrusiveHolder(this); ++ private final Holder.Reference> builtInRegistryHolder; + private static final float MAGIC_HORSE_WIDTH = 1.3964844F; + private static final int DISPLAY_TRACKING_RANGE = 10; +- public static final EntityType ALLAY = register( +- "allay", EntityType.Builder.of(Allay::new, MobCategory.CREATURE).sized(0.35F, 0.6F).clientTrackingRange(8).updateInterval(2) +- ); +- public static final EntityType AREA_EFFECT_CLOUD = register( +- "area_effect_cloud", +- EntityType.Builder.of(AreaEffectCloud::new, MobCategory.MISC) +- .fireImmune() +- .sized(6.0F, 0.5F) +- .clientTrackingRange(10) +- .updateInterval(Integer.MAX_VALUE) +- ); +- public static final EntityType ARMOR_STAND = register( +- "armor_stand", EntityType.Builder.of(ArmorStand::new, MobCategory.MISC).sized(0.5F, 1.975F).clientTrackingRange(10) +- ); +- public static final EntityType ARROW = register( +- "arrow", EntityType.Builder.of(Arrow::new, MobCategory.MISC).sized(0.5F, 0.5F).clientTrackingRange(4).updateInterval(20) +- ); +- public static final EntityType AXOLOTL = register( +- "axolotl", EntityType.Builder.of(Axolotl::new, MobCategory.AXOLOTLS).sized(0.75F, 0.42F).clientTrackingRange(10) +- ); ++ public static final EntityType ALLAY = register("allay", EntityType.Builder.of(Allay::new, MobCategory.CREATURE).sized(0.35F, 0.6F).clientTrackingRange(8).updateInterval(2)); ++ public static final EntityType AREA_EFFECT_CLOUD = register("area_effect_cloud", EntityType.Builder.of(AreaEffectCloud::new, MobCategory.MISC).fireImmune().sized(6.0F, 0.5F).clientTrackingRange(10).updateInterval(10)); // CraftBukkit - SPIGOT-3729: track area effect clouds ++ public static final EntityType ARMOR_STAND = register("armor_stand", EntityType.Builder.of(ArmorStand::new, MobCategory.MISC).sized(0.5F, 1.975F).clientTrackingRange(10)); ++ public static final EntityType ARROW = register("arrow", EntityType.Builder.of(Arrow::new, MobCategory.MISC).sized(0.5F, 0.5F).clientTrackingRange(4).updateInterval(20)); ++ public static final EntityType AXOLOTL = register("axolotl", EntityType.Builder.of(Axolotl::new, MobCategory.AXOLOTLS).sized(0.75F, 0.42F).clientTrackingRange(10)); + public static final EntityType BAT = register("bat", EntityType.Builder.of(Bat::new, MobCategory.AMBIENT).sized(0.5F, 0.9F).clientTrackingRange(5)); + public static final EntityType BEE = register("bee", EntityType.Builder.of(Bee::new, MobCategory.CREATURE).sized(0.7F, 0.6F).clientTrackingRange(8)); +- public static final EntityType BLAZE = register( +- "blaze", EntityType.Builder.of(Blaze::new, MobCategory.MONSTER).fireImmune().sized(0.6F, 1.8F).clientTrackingRange(8) +- ); +- public static final EntityType BLOCK_DISPLAY = register( +- "block_display", EntityType.Builder.of(Display.BlockDisplay::new, MobCategory.MISC).sized(0.0F, 0.0F).clientTrackingRange(10).updateInterval(1) +- ); +- public static final EntityType BOAT = register( +- "boat", EntityType.Builder.of(Boat::new, MobCategory.MISC).sized(1.375F, 0.5625F).clientTrackingRange(10) +- ); +- public static final EntityType BREEZE = register( +- "breeze", EntityType.Builder.of(Breeze::new, MobCategory.MONSTER).sized(0.6F, 1.7F).clientTrackingRange(10).requiredFeatures(FeatureFlags.UPDATE_1_21) +- ); +- public static final EntityType CAMEL = register( +- "camel", EntityType.Builder.of(Camel::new, MobCategory.CREATURE).sized(1.7F, 2.375F).clientTrackingRange(10) +- ); ++ public static final EntityType BLAZE = register("blaze", EntityType.Builder.of(Blaze::new, MobCategory.MONSTER).fireImmune().sized(0.6F, 1.8F).clientTrackingRange(8)); ++ public static final EntityType BLOCK_DISPLAY = register("block_display", EntityType.Builder.of(Display.BlockDisplay::new, MobCategory.MISC).sized(0.0F, 0.0F).clientTrackingRange(10).updateInterval(1)); ++ public static final EntityType BOAT = register("boat", EntityType.Builder.of(Boat::new, MobCategory.MISC).sized(1.375F, 0.5625F).clientTrackingRange(10)); ++ public static final EntityType BREEZE = register("breeze", EntityType.Builder.of(Breeze::new, MobCategory.MONSTER).sized(0.6F, 1.7F).clientTrackingRange(10).requiredFeatures(FeatureFlags.UPDATE_1_21)); ++ public static final EntityType CAMEL = register("camel", EntityType.Builder.of(Camel::new, MobCategory.CREATURE).sized(1.7F, 2.375F).clientTrackingRange(10)); + public static final EntityType CAT = register("cat", EntityType.Builder.of(Cat::new, MobCategory.CREATURE).sized(0.6F, 0.7F).clientTrackingRange(8)); +- public static final EntityType CAVE_SPIDER = register( +- "cave_spider", EntityType.Builder.of(CaveSpider::new, MobCategory.MONSTER).sized(0.7F, 0.5F).clientTrackingRange(8) +- ); +- public static final EntityType CHEST_BOAT = register( +- "chest_boat", EntityType.Builder.of(ChestBoat::new, MobCategory.MISC).sized(1.375F, 0.5625F).clientTrackingRange(10) +- ); +- public static final EntityType CHEST_MINECART = register( +- "chest_minecart", EntityType.Builder.of(MinecartChest::new, MobCategory.MISC).sized(0.98F, 0.7F).clientTrackingRange(8) +- ); +- public static final EntityType CHICKEN = register( +- "chicken", EntityType.Builder.of(Chicken::new, MobCategory.CREATURE).sized(0.4F, 0.7F).clientTrackingRange(10) +- ); +- public static final EntityType COD = register( +- "cod", EntityType.Builder.of(Cod::new, MobCategory.WATER_AMBIENT).sized(0.5F, 0.3F).clientTrackingRange(4) +- ); +- public static final EntityType COMMAND_BLOCK_MINECART = register( +- "command_block_minecart", +- EntityType.Builder.of(MinecartCommandBlock::new, MobCategory.MISC).sized(0.98F, 0.7F).clientTrackingRange(8) +- ); ++ public static final EntityType CAVE_SPIDER = register("cave_spider", EntityType.Builder.of(CaveSpider::new, MobCategory.MONSTER).sized(0.7F, 0.5F).clientTrackingRange(8)); ++ public static final EntityType CHEST_BOAT = register("chest_boat", EntityType.Builder.of(ChestBoat::new, MobCategory.MISC).sized(1.375F, 0.5625F).clientTrackingRange(10)); ++ public static final EntityType CHEST_MINECART = register("chest_minecart", EntityType.Builder.of(MinecartChest::new, MobCategory.MISC).sized(0.98F, 0.7F).clientTrackingRange(8)); ++ public static final EntityType CHICKEN = register("chicken", EntityType.Builder.of(Chicken::new, MobCategory.CREATURE).sized(0.4F, 0.7F).clientTrackingRange(10)); ++ public static final EntityType COD = register("cod", EntityType.Builder.of(Cod::new, MobCategory.WATER_AMBIENT).sized(0.5F, 0.3F).clientTrackingRange(4)); ++ public static final EntityType COMMAND_BLOCK_MINECART = register("command_block_minecart", EntityType.Builder.of(MinecartCommandBlock::new, MobCategory.MISC).sized(0.98F, 0.7F).clientTrackingRange(8)); + public static final EntityType COW = register("cow", EntityType.Builder.of(Cow::new, MobCategory.CREATURE).sized(0.9F, 1.4F).clientTrackingRange(10)); +- public static final EntityType CREEPER = register( +- "creeper", EntityType.Builder.of(Creeper::new, MobCategory.MONSTER).sized(0.6F, 1.7F).clientTrackingRange(8) +- ); ++ public static final EntityType CREEPER = register("creeper", EntityType.Builder.of(Creeper::new, MobCategory.MONSTER).sized(0.6F, 1.7F).clientTrackingRange(8)); + public static final EntityType DOLPHIN = register("dolphin", EntityType.Builder.of(Dolphin::new, MobCategory.WATER_CREATURE).sized(0.9F, 0.6F)); +- public static final EntityType DONKEY = register( +- "donkey", EntityType.Builder.of(Donkey::new, MobCategory.CREATURE).sized(1.3964844F, 1.5F).clientTrackingRange(10) +- ); +- public static final EntityType DRAGON_FIREBALL = register( +- "dragon_fireball", +- EntityType.Builder.of(DragonFireball::new, MobCategory.MISC).sized(1.0F, 1.0F).clientTrackingRange(4).updateInterval(10) +- ); +- public static final EntityType DROWNED = register( +- "drowned", EntityType.Builder.of(Drowned::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8) +- ); +- public static final EntityType EGG = register( +- "egg", EntityType.Builder.of(ThrownEgg::new, MobCategory.MISC).sized(0.25F, 0.25F).clientTrackingRange(4).updateInterval(10) +- ); +- public static final EntityType ELDER_GUARDIAN = register( +- "elder_guardian", EntityType.Builder.of(ElderGuardian::new, MobCategory.MONSTER).sized(1.9975F, 1.9975F).clientTrackingRange(10) +- ); +- public static final EntityType END_CRYSTAL = register( +- "end_crystal", +- EntityType.Builder.of(EndCrystal::new, MobCategory.MISC).sized(2.0F, 2.0F).clientTrackingRange(16).updateInterval(Integer.MAX_VALUE) +- ); +- public static final EntityType ENDER_DRAGON = register( +- "ender_dragon", EntityType.Builder.of(EnderDragon::new, MobCategory.MONSTER).fireImmune().sized(16.0F, 8.0F).clientTrackingRange(10) +- ); +- public static final EntityType ENDER_PEARL = register( +- "ender_pearl", +- EntityType.Builder.of(ThrownEnderpearl::new, MobCategory.MISC).sized(0.25F, 0.25F).clientTrackingRange(4).updateInterval(10) +- ); +- public static final EntityType ENDERMAN = register( +- "enderman", EntityType.Builder.of(EnderMan::new, MobCategory.MONSTER).sized(0.6F, 2.9F).clientTrackingRange(8) +- ); +- public static final EntityType ENDERMITE = register( +- "endermite", EntityType.Builder.of(Endermite::new, MobCategory.MONSTER).sized(0.4F, 0.3F).clientTrackingRange(8) +- ); +- public static final EntityType EVOKER = register( +- "evoker", EntityType.Builder.of(Evoker::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8) +- ); +- public static final EntityType EVOKER_FANGS = register( +- "evoker_fangs", EntityType.Builder.of(EvokerFangs::new, MobCategory.MISC).sized(0.5F, 0.8F).clientTrackingRange(6).updateInterval(2) +- ); +- public static final EntityType EXPERIENCE_BOTTLE = register( +- "experience_bottle", +- EntityType.Builder.of(ThrownExperienceBottle::new, MobCategory.MISC) +- .sized(0.25F, 0.25F) +- .clientTrackingRange(4) +- .updateInterval(10) +- ); +- public static final EntityType EXPERIENCE_ORB = register( +- "experience_orb", +- EntityType.Builder.of(ExperienceOrb::new, MobCategory.MISC).sized(0.5F, 0.5F).clientTrackingRange(6).updateInterval(20) +- ); +- public static final EntityType EYE_OF_ENDER = register( +- "eye_of_ender", EntityType.Builder.of(EyeOfEnder::new, MobCategory.MISC).sized(0.25F, 0.25F).clientTrackingRange(4).updateInterval(4) +- ); +- public static final EntityType FALLING_BLOCK = register( +- "falling_block", +- EntityType.Builder.of(FallingBlockEntity::new, MobCategory.MISC).sized(0.98F, 0.98F).clientTrackingRange(10).updateInterval(20) +- ); +- public static final EntityType FIREWORK_ROCKET = register( +- "firework_rocket", +- EntityType.Builder.of(FireworkRocketEntity::new, MobCategory.MISC).sized(0.25F, 0.25F).clientTrackingRange(4).updateInterval(10) +- ); +- public static final EntityType FOX = register( +- "fox", EntityType.Builder.of(Fox::new, MobCategory.CREATURE).sized(0.6F, 0.7F).clientTrackingRange(8).immuneTo(Blocks.SWEET_BERRY_BUSH) +- ); +- public static final EntityType FROG = register( +- "frog", EntityType.Builder.of(Frog::new, MobCategory.CREATURE).sized(0.5F, 0.5F).clientTrackingRange(10) +- ); +- public static final EntityType FURNACE_MINECART = register( +- "furnace_minecart", EntityType.Builder.of(MinecartFurnace::new, MobCategory.MISC).sized(0.98F, 0.7F).clientTrackingRange(8) +- ); +- public static final EntityType GHAST = register( +- "ghast", EntityType.Builder.of(Ghast::new, MobCategory.MONSTER).fireImmune().sized(4.0F, 4.0F).clientTrackingRange(10) +- ); +- public static final EntityType GIANT = register( +- "giant", EntityType.Builder.of(Giant::new, MobCategory.MONSTER).sized(3.6F, 12.0F).clientTrackingRange(10) +- ); +- public static final EntityType GLOW_ITEM_FRAME = register( +- "glow_item_frame", +- EntityType.Builder.of(GlowItemFrame::new, MobCategory.MISC).sized(0.5F, 0.5F).clientTrackingRange(10).updateInterval(Integer.MAX_VALUE) +- ); +- public static final EntityType GLOW_SQUID = register( +- "glow_squid", EntityType.Builder.of(GlowSquid::new, MobCategory.UNDERGROUND_WATER_CREATURE).sized(0.8F, 0.8F).clientTrackingRange(10) +- ); +- public static final EntityType GOAT = register( +- "goat", EntityType.Builder.of(Goat::new, MobCategory.CREATURE).sized(0.9F, 1.3F).clientTrackingRange(10) +- ); +- public static final EntityType GUARDIAN = register( +- "guardian", EntityType.Builder.of(Guardian::new, MobCategory.MONSTER).sized(0.85F, 0.85F).clientTrackingRange(8) +- ); +- public static final EntityType HOGLIN = register( +- "hoglin", EntityType.Builder.of(Hoglin::new, MobCategory.MONSTER).sized(1.3964844F, 1.4F).clientTrackingRange(8) +- ); +- public static final EntityType HOPPER_MINECART = register( +- "hopper_minecart", EntityType.Builder.of(MinecartHopper::new, MobCategory.MISC).sized(0.98F, 0.7F).clientTrackingRange(8) +- ); +- public static final EntityType HORSE = register( +- "horse", EntityType.Builder.of(Horse::new, MobCategory.CREATURE).sized(1.3964844F, 1.6F).clientTrackingRange(10) +- ); +- public static final EntityType HUSK = register( +- "husk", EntityType.Builder.of(Husk::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8) +- ); +- public static final EntityType ILLUSIONER = register( +- "illusioner", EntityType.Builder.of(Illusioner::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8) +- ); +- public static final EntityType INTERACTION = register( +- "interaction", EntityType.Builder.of(Interaction::new, MobCategory.MISC).sized(0.0F, 0.0F).clientTrackingRange(10) +- ); +- public static final EntityType IRON_GOLEM = register( +- "iron_golem", EntityType.Builder.of(IronGolem::new, MobCategory.MISC).sized(1.4F, 2.7F).clientTrackingRange(10) +- ); +- public static final EntityType ITEM = register( +- "item", EntityType.Builder.of(ItemEntity::new, MobCategory.MISC).sized(0.25F, 0.25F).clientTrackingRange(6).updateInterval(20) +- ); +- public static final EntityType ITEM_DISPLAY = register( +- "item_display", EntityType.Builder.of(Display.ItemDisplay::new, MobCategory.MISC).sized(0.0F, 0.0F).clientTrackingRange(10).updateInterval(1) +- ); +- public static final EntityType ITEM_FRAME = register( +- "item_frame", +- EntityType.Builder.of(ItemFrame::new, MobCategory.MISC).sized(0.5F, 0.5F).clientTrackingRange(10).updateInterval(Integer.MAX_VALUE) +- ); +- public static final EntityType FIREBALL = register( +- "fireball", EntityType.Builder.of(LargeFireball::new, MobCategory.MISC).sized(1.0F, 1.0F).clientTrackingRange(4).updateInterval(10) +- ); +- public static final EntityType LEASH_KNOT = register( +- "leash_knot", +- EntityType.Builder.of(LeashFenceKnotEntity::new, MobCategory.MISC) +- .noSave() +- .sized(0.375F, 0.5F) +- .clientTrackingRange(10) +- .updateInterval(Integer.MAX_VALUE) +- ); +- public static final EntityType LIGHTNING_BOLT = register( +- "lightning_bolt", +- EntityType.Builder.of(LightningBolt::new, MobCategory.MISC).noSave().sized(0.0F, 0.0F).clientTrackingRange(16).updateInterval(Integer.MAX_VALUE) +- ); +- public static final EntityType LLAMA = register( +- "llama", EntityType.Builder.of(Llama::new, MobCategory.CREATURE).sized(0.9F, 1.87F).clientTrackingRange(10) +- ); +- public static final EntityType LLAMA_SPIT = register( +- "llama_spit", EntityType.Builder.of(LlamaSpit::new, MobCategory.MISC).sized(0.25F, 0.25F).clientTrackingRange(4).updateInterval(10) +- ); +- public static final EntityType MAGMA_CUBE = register( +- "magma_cube", EntityType.Builder.of(MagmaCube::new, MobCategory.MONSTER).fireImmune().sized(2.04F, 2.04F).clientTrackingRange(8) +- ); +- public static final EntityType MARKER = register( +- "marker", EntityType.Builder.of(Marker::new, MobCategory.MISC).sized(0.0F, 0.0F).clientTrackingRange(0) +- ); +- public static final EntityType MINECART = register( +- "minecart", EntityType.Builder.of(Minecart::new, MobCategory.MISC).sized(0.98F, 0.7F).clientTrackingRange(8) +- ); +- public static final EntityType MOOSHROOM = register( +- "mooshroom", EntityType.Builder.of(MushroomCow::new, MobCategory.CREATURE).sized(0.9F, 1.4F).clientTrackingRange(10) +- ); +- public static final EntityType MULE = register( +- "mule", EntityType.Builder.of(Mule::new, MobCategory.CREATURE).sized(1.3964844F, 1.6F).clientTrackingRange(8) +- ); +- public static final EntityType OCELOT = register( +- "ocelot", EntityType.Builder.of(Ocelot::new, MobCategory.CREATURE).sized(0.6F, 0.7F).clientTrackingRange(10) +- ); +- public static final EntityType PAINTING = register( +- "painting", +- EntityType.Builder.of(Painting::new, MobCategory.MISC).sized(0.5F, 0.5F).clientTrackingRange(10).updateInterval(Integer.MAX_VALUE) +- ); +- public static final EntityType PANDA = register( +- "panda", EntityType.Builder.of(Panda::new, MobCategory.CREATURE).sized(1.3F, 1.25F).clientTrackingRange(10) +- ); +- public static final EntityType PARROT = register( +- "parrot", EntityType.Builder.of(Parrot::new, MobCategory.CREATURE).sized(0.5F, 0.9F).clientTrackingRange(8) +- ); +- public static final EntityType PHANTOM = register( +- "phantom", EntityType.Builder.of(Phantom::new, MobCategory.MONSTER).sized(0.9F, 0.5F).clientTrackingRange(8) +- ); ++ public static final EntityType DONKEY = register("donkey", EntityType.Builder.of(Donkey::new, MobCategory.CREATURE).sized(1.3964844F, 1.5F).clientTrackingRange(10)); ++ public static final EntityType DRAGON_FIREBALL = register("dragon_fireball", EntityType.Builder.of(DragonFireball::new, MobCategory.MISC).sized(1.0F, 1.0F).clientTrackingRange(4).updateInterval(10)); ++ public static final EntityType DROWNED = register("drowned", EntityType.Builder.of(Drowned::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8)); ++ public static final EntityType EGG = register("egg", EntityType.Builder.of(ThrownEgg::new, MobCategory.MISC).sized(0.25F, 0.25F).clientTrackingRange(4).updateInterval(10)); ++ public static final EntityType ELDER_GUARDIAN = register("elder_guardian", EntityType.Builder.of(ElderGuardian::new, MobCategory.MONSTER).sized(1.9975F, 1.9975F).clientTrackingRange(10)); ++ public static final EntityType END_CRYSTAL = register("end_crystal", EntityType.Builder.of(EndCrystal::new, MobCategory.MISC).sized(2.0F, 2.0F).clientTrackingRange(16).updateInterval(Integer.MAX_VALUE)); ++ public static final EntityType ENDER_DRAGON = register("ender_dragon", EntityType.Builder.of(EnderDragon::new, MobCategory.MONSTER).fireImmune().sized(16.0F, 8.0F).clientTrackingRange(10)); ++ public static final EntityType ENDER_PEARL = register("ender_pearl", EntityType.Builder.of(ThrownEnderpearl::new, MobCategory.MISC).sized(0.25F, 0.25F).clientTrackingRange(4).updateInterval(10)); ++ public static final EntityType ENDERMAN = register("enderman", EntityType.Builder.of(EnderMan::new, MobCategory.MONSTER).sized(0.6F, 2.9F).clientTrackingRange(8)); ++ public static final EntityType ENDERMITE = register("endermite", EntityType.Builder.of(Endermite::new, MobCategory.MONSTER).sized(0.4F, 0.3F).clientTrackingRange(8)); ++ public static final EntityType EVOKER = register("evoker", EntityType.Builder.of(Evoker::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8)); ++ public static final EntityType EVOKER_FANGS = register("evoker_fangs", EntityType.Builder.of(EvokerFangs::new, MobCategory.MISC).sized(0.5F, 0.8F).clientTrackingRange(6).updateInterval(2)); ++ public static final EntityType EXPERIENCE_BOTTLE = register("experience_bottle", EntityType.Builder.of(ThrownExperienceBottle::new, MobCategory.MISC).sized(0.25F, 0.25F).clientTrackingRange(4).updateInterval(10)); ++ public static final EntityType EXPERIENCE_ORB = register("experience_orb", EntityType.Builder.of(ExperienceOrb::new, MobCategory.MISC).sized(0.5F, 0.5F).clientTrackingRange(6).updateInterval(20)); ++ public static final EntityType EYE_OF_ENDER = register("eye_of_ender", EntityType.Builder.of(EyeOfEnder::new, MobCategory.MISC).sized(0.25F, 0.25F).clientTrackingRange(4).updateInterval(4)); ++ public static final EntityType FALLING_BLOCK = register("falling_block", EntityType.Builder.of(FallingBlockEntity::new, MobCategory.MISC).sized(0.98F, 0.98F).clientTrackingRange(10).updateInterval(20)); ++ public static final EntityType FIREWORK_ROCKET = register("firework_rocket", EntityType.Builder.of(FireworkRocketEntity::new, MobCategory.MISC).sized(0.25F, 0.25F).clientTrackingRange(4).updateInterval(10)); ++ public static final EntityType FOX = register("fox", EntityType.Builder.of(Fox::new, MobCategory.CREATURE).sized(0.6F, 0.7F).clientTrackingRange(8).immuneTo(Blocks.SWEET_BERRY_BUSH)); ++ public static final EntityType FROG = register("frog", EntityType.Builder.of(Frog::new, MobCategory.CREATURE).sized(0.5F, 0.5F).clientTrackingRange(10)); ++ public static final EntityType FURNACE_MINECART = register("furnace_minecart", EntityType.Builder.of(MinecartFurnace::new, MobCategory.MISC).sized(0.98F, 0.7F).clientTrackingRange(8)); ++ public static final EntityType GHAST = register("ghast", EntityType.Builder.of(Ghast::new, MobCategory.MONSTER).fireImmune().sized(4.0F, 4.0F).clientTrackingRange(10)); ++ public static final EntityType GIANT = register("giant", EntityType.Builder.of(Giant::new, MobCategory.MONSTER).sized(3.6F, 12.0F).clientTrackingRange(10)); ++ public static final EntityType GLOW_ITEM_FRAME = register("glow_item_frame", EntityType.Builder.of(GlowItemFrame::new, MobCategory.MISC).sized(0.5F, 0.5F).clientTrackingRange(10).updateInterval(Integer.MAX_VALUE)); ++ public static final EntityType GLOW_SQUID = register("glow_squid", EntityType.Builder.of(GlowSquid::new, MobCategory.UNDERGROUND_WATER_CREATURE).sized(0.8F, 0.8F).clientTrackingRange(10)); ++ public static final EntityType GOAT = register("goat", EntityType.Builder.of(Goat::new, MobCategory.CREATURE).sized(0.9F, 1.3F).clientTrackingRange(10)); ++ public static final EntityType GUARDIAN = register("guardian", EntityType.Builder.of(Guardian::new, MobCategory.MONSTER).sized(0.85F, 0.85F).clientTrackingRange(8)); ++ public static final EntityType HOGLIN = register("hoglin", EntityType.Builder.of(Hoglin::new, MobCategory.MONSTER).sized(1.3964844F, 1.4F).clientTrackingRange(8)); ++ public static final EntityType HOPPER_MINECART = register("hopper_minecart", EntityType.Builder.of(MinecartHopper::new, MobCategory.MISC).sized(0.98F, 0.7F).clientTrackingRange(8)); ++ public static final EntityType HORSE = register("horse", EntityType.Builder.of(Horse::new, MobCategory.CREATURE).sized(1.3964844F, 1.6F).clientTrackingRange(10)); ++ public static final EntityType HUSK = register("husk", EntityType.Builder.of(Husk::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8)); ++ public static final EntityType ILLUSIONER = register("illusioner", EntityType.Builder.of(Illusioner::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8)); ++ public static final EntityType INTERACTION = register("interaction", EntityType.Builder.of(Interaction::new, MobCategory.MISC).sized(0.0F, 0.0F).clientTrackingRange(10)); ++ public static final EntityType IRON_GOLEM = register("iron_golem", EntityType.Builder.of(IronGolem::new, MobCategory.MISC).sized(1.4F, 2.7F).clientTrackingRange(10)); ++ public static final EntityType ITEM = register("item", EntityType.Builder.of(ItemEntity::new, MobCategory.MISC).sized(0.25F, 0.25F).clientTrackingRange(6).updateInterval(20)); ++ public static final EntityType ITEM_DISPLAY = register("item_display", EntityType.Builder.of(Display.ItemDisplay::new, MobCategory.MISC).sized(0.0F, 0.0F).clientTrackingRange(10).updateInterval(1)); ++ public static final EntityType ITEM_FRAME = register("item_frame", EntityType.Builder.of(ItemFrame::new, MobCategory.MISC).sized(0.5F, 0.5F).clientTrackingRange(10).updateInterval(Integer.MAX_VALUE)); ++ public static final EntityType FIREBALL = register("fireball", EntityType.Builder.of(LargeFireball::new, MobCategory.MISC).sized(1.0F, 1.0F).clientTrackingRange(4).updateInterval(10)); ++ public static final EntityType LEASH_KNOT = register("leash_knot", EntityType.Builder.of(LeashFenceKnotEntity::new, MobCategory.MISC).noSave().sized(0.375F, 0.5F).clientTrackingRange(10).updateInterval(Integer.MAX_VALUE)); ++ public static final EntityType LIGHTNING_BOLT = register("lightning_bolt", EntityType.Builder.of(LightningBolt::new, MobCategory.MISC).noSave().sized(0.0F, 0.0F).clientTrackingRange(16).updateInterval(Integer.MAX_VALUE)); ++ public static final EntityType LLAMA = register("llama", EntityType.Builder.of(Llama::new, MobCategory.CREATURE).sized(0.9F, 1.87F).clientTrackingRange(10)); ++ public static final EntityType LLAMA_SPIT = register("llama_spit", EntityType.Builder.of(LlamaSpit::new, MobCategory.MISC).sized(0.25F, 0.25F).clientTrackingRange(4).updateInterval(10)); ++ public static final EntityType MAGMA_CUBE = register("magma_cube", EntityType.Builder.of(MagmaCube::new, MobCategory.MONSTER).fireImmune().sized(2.04F, 2.04F).clientTrackingRange(8)); ++ public static final EntityType MARKER = register("marker", EntityType.Builder.of(Marker::new, MobCategory.MISC).sized(0.0F, 0.0F).clientTrackingRange(0)); ++ public static final EntityType MINECART = register("minecart", EntityType.Builder.of(Minecart::new, MobCategory.MISC).sized(0.98F, 0.7F).clientTrackingRange(8)); ++ public static final EntityType MOOSHROOM = register("mooshroom", EntityType.Builder.of(MushroomCow::new, MobCategory.CREATURE).sized(0.9F, 1.4F).clientTrackingRange(10)); ++ public static final EntityType MULE = register("mule", EntityType.Builder.of(Mule::new, MobCategory.CREATURE).sized(1.3964844F, 1.6F).clientTrackingRange(8)); ++ public static final EntityType OCELOT = register("ocelot", EntityType.Builder.of(Ocelot::new, MobCategory.CREATURE).sized(0.6F, 0.7F).clientTrackingRange(10)); ++ public static final EntityType PAINTING = register("painting", EntityType.Builder.of(Painting::new, MobCategory.MISC).sized(0.5F, 0.5F).clientTrackingRange(10).updateInterval(Integer.MAX_VALUE)); ++ public static final EntityType PANDA = register("panda", EntityType.Builder.of(Panda::new, MobCategory.CREATURE).sized(1.3F, 1.25F).clientTrackingRange(10)); ++ public static final EntityType PARROT = register("parrot", EntityType.Builder.of(Parrot::new, MobCategory.CREATURE).sized(0.5F, 0.9F).clientTrackingRange(8)); ++ public static final EntityType PHANTOM = register("phantom", EntityType.Builder.of(Phantom::new, MobCategory.MONSTER).sized(0.9F, 0.5F).clientTrackingRange(8)); + public static final EntityType PIG = register("pig", EntityType.Builder.of(Pig::new, MobCategory.CREATURE).sized(0.9F, 0.9F).clientTrackingRange(10)); +- public static final EntityType PIGLIN = register( +- "piglin", EntityType.Builder.of(Piglin::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8) +- ); +- public static final EntityType PIGLIN_BRUTE = register( +- "piglin_brute", EntityType.Builder.of(PiglinBrute::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8) +- ); +- public static final EntityType PILLAGER = register( +- "pillager", EntityType.Builder.of(Pillager::new, MobCategory.MONSTER).canSpawnFarFromPlayer().sized(0.6F, 1.95F).clientTrackingRange(8) +- ); +- public static final EntityType POLAR_BEAR = register( +- "polar_bear", EntityType.Builder.of(PolarBear::new, MobCategory.CREATURE).immuneTo(Blocks.POWDER_SNOW).sized(1.4F, 1.4F).clientTrackingRange(10) +- ); +- public static final EntityType POTION = register( +- "potion", EntityType.Builder.of(ThrownPotion::new, MobCategory.MISC).sized(0.25F, 0.25F).clientTrackingRange(4).updateInterval(10) +- ); +- public static final EntityType PUFFERFISH = register( +- "pufferfish", EntityType.Builder.of(Pufferfish::new, MobCategory.WATER_AMBIENT).sized(0.7F, 0.7F).clientTrackingRange(4) +- ); +- public static final EntityType RABBIT = register( +- "rabbit", EntityType.Builder.of(Rabbit::new, MobCategory.CREATURE).sized(0.4F, 0.5F).clientTrackingRange(8) +- ); +- public static final EntityType RAVAGER = register( +- "ravager", EntityType.Builder.of(Ravager::new, MobCategory.MONSTER).sized(1.95F, 2.2F).clientTrackingRange(10) +- ); +- public static final EntityType SALMON = register( +- "salmon", EntityType.Builder.of(Salmon::new, MobCategory.WATER_AMBIENT).sized(0.7F, 0.4F).clientTrackingRange(4) +- ); +- public static final EntityType SHEEP = register( +- "sheep", EntityType.Builder.of(Sheep::new, MobCategory.CREATURE).sized(0.9F, 1.3F).clientTrackingRange(10) +- ); +- public static final EntityType SHULKER = register( +- "shulker", EntityType.Builder.of(Shulker::new, MobCategory.MONSTER).fireImmune().canSpawnFarFromPlayer().sized(1.0F, 1.0F).clientTrackingRange(10) +- ); +- public static final EntityType SHULKER_BULLET = register( +- "shulker_bullet", EntityType.Builder.of(ShulkerBullet::new, MobCategory.MISC).sized(0.3125F, 0.3125F).clientTrackingRange(8) +- ); +- public static final EntityType SILVERFISH = register( +- "silverfish", EntityType.Builder.of(Silverfish::new, MobCategory.MONSTER).sized(0.4F, 0.3F).clientTrackingRange(8) +- ); +- public static final EntityType SKELETON = register( +- "skeleton", EntityType.Builder.of(Skeleton::new, MobCategory.MONSTER).sized(0.6F, 1.99F).clientTrackingRange(8) +- ); +- public static final EntityType SKELETON_HORSE = register( +- "skeleton_horse", EntityType.Builder.of(SkeletonHorse::new, MobCategory.CREATURE).sized(1.3964844F, 1.6F).clientTrackingRange(10) +- ); +- public static final EntityType SLIME = register( +- "slime", EntityType.Builder.of(Slime::new, MobCategory.MONSTER).sized(2.04F, 2.04F).clientTrackingRange(10) +- ); +- public static final EntityType SMALL_FIREBALL = register( +- "small_fireball", +- EntityType.Builder.of(SmallFireball::new, MobCategory.MISC).sized(0.3125F, 0.3125F).clientTrackingRange(4).updateInterval(10) +- ); +- public static final EntityType SNIFFER = register( +- "sniffer", EntityType.Builder.of(Sniffer::new, MobCategory.CREATURE).sized(1.9F, 1.75F).clientTrackingRange(10) +- ); +- public static final EntityType SNOW_GOLEM = register( +- "snow_golem", EntityType.Builder.of(SnowGolem::new, MobCategory.MISC).immuneTo(Blocks.POWDER_SNOW).sized(0.7F, 1.9F).clientTrackingRange(8) +- ); +- public static final EntityType SNOWBALL = register( +- "snowball", EntityType.Builder.of(Snowball::new, MobCategory.MISC).sized(0.25F, 0.25F).clientTrackingRange(4).updateInterval(10) +- ); +- public static final EntityType SPAWNER_MINECART = register( +- "spawner_minecart", EntityType.Builder.of(MinecartSpawner::new, MobCategory.MISC).sized(0.98F, 0.7F).clientTrackingRange(8) +- ); +- public static final EntityType SPECTRAL_ARROW = register( +- "spectral_arrow", +- EntityType.Builder.of(SpectralArrow::new, MobCategory.MISC).sized(0.5F, 0.5F).clientTrackingRange(4).updateInterval(20) +- ); +- public static final EntityType SPIDER = register( +- "spider", EntityType.Builder.of(Spider::new, MobCategory.MONSTER).sized(1.4F, 0.9F).clientTrackingRange(8) +- ); +- public static final EntityType SQUID = register( +- "squid", EntityType.Builder.of(Squid::new, MobCategory.WATER_CREATURE).sized(0.8F, 0.8F).clientTrackingRange(8) +- ); +- public static final EntityType STRAY = register( +- "stray", EntityType.Builder.of(Stray::new, MobCategory.MONSTER).sized(0.6F, 1.99F).immuneTo(Blocks.POWDER_SNOW).clientTrackingRange(8) +- ); +- public static final EntityType STRIDER = register( +- "strider", EntityType.Builder.of(Strider::new, MobCategory.CREATURE).fireImmune().sized(0.9F, 1.7F).clientTrackingRange(10) +- ); +- public static final EntityType TADPOLE = register( +- "tadpole", EntityType.Builder.of(Tadpole::new, MobCategory.CREATURE).sized(Tadpole.HITBOX_WIDTH, Tadpole.HITBOX_HEIGHT).clientTrackingRange(10) +- ); +- public static final EntityType TEXT_DISPLAY = register( +- "text_display", EntityType.Builder.of(Display.TextDisplay::new, MobCategory.MISC).sized(0.0F, 0.0F).clientTrackingRange(10).updateInterval(1) +- ); +- public static final EntityType TNT = register( +- "tnt", EntityType.Builder.of(PrimedTnt::new, MobCategory.MISC).fireImmune().sized(0.98F, 0.98F).clientTrackingRange(10).updateInterval(10) +- ); +- public static final EntityType TNT_MINECART = register( +- "tnt_minecart", EntityType.Builder.of(MinecartTNT::new, MobCategory.MISC).sized(0.98F, 0.7F).clientTrackingRange(8) +- ); +- public static final EntityType TRADER_LLAMA = register( +- "trader_llama", EntityType.Builder.of(TraderLlama::new, MobCategory.CREATURE).sized(0.9F, 1.87F).clientTrackingRange(10) +- ); +- public static final EntityType TRIDENT = register( +- "trident", EntityType.Builder.of(ThrownTrident::new, MobCategory.MISC).sized(0.5F, 0.5F).clientTrackingRange(4).updateInterval(20) +- ); +- public static final EntityType TROPICAL_FISH = register( +- "tropical_fish", EntityType.Builder.of(TropicalFish::new, MobCategory.WATER_AMBIENT).sized(0.5F, 0.4F).clientTrackingRange(4) +- ); +- public static final EntityType TURTLE = register( +- "turtle", EntityType.Builder.of(Turtle::new, MobCategory.CREATURE).sized(1.2F, 0.4F).clientTrackingRange(10) +- ); +- public static final EntityType VEX = register( +- "vex", EntityType.Builder.of(Vex::new, MobCategory.MONSTER).fireImmune().sized(0.4F, 0.8F).clientTrackingRange(8) +- ); +- public static final EntityType VILLAGER = register( +- "villager", EntityType.Builder.of(Villager::new, MobCategory.MISC).sized(0.6F, 1.95F).clientTrackingRange(10) +- ); +- public static final EntityType VINDICATOR = register( +- "vindicator", EntityType.Builder.of(Vindicator::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8) +- ); +- public static final EntityType WANDERING_TRADER = register( +- "wandering_trader", EntityType.Builder.of(WanderingTrader::new, MobCategory.CREATURE).sized(0.6F, 1.95F).clientTrackingRange(10) +- ); +- public static final EntityType WARDEN = register( +- "warden", EntityType.Builder.of(Warden::new, MobCategory.MONSTER).sized(0.9F, 2.9F).clientTrackingRange(16).fireImmune() +- ); +- public static final EntityType WIND_CHARGE = register( +- "wind_charge", +- EntityType.Builder.of(WindCharge::new, MobCategory.MISC) +- .sized(0.3125F, 0.3125F) +- .clientTrackingRange(4) +- .updateInterval(10) +- .requiredFeatures(FeatureFlags.UPDATE_1_21) +- ); +- public static final EntityType WITCH = register( +- "witch", EntityType.Builder.of(Witch::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8) +- ); +- public static final EntityType WITHER = register( +- "wither", +- EntityType.Builder.of(WitherBoss::new, MobCategory.MONSTER).fireImmune().immuneTo(Blocks.WITHER_ROSE).sized(0.9F, 3.5F).clientTrackingRange(10) +- ); +- public static final EntityType WITHER_SKELETON = register( +- "wither_skeleton", +- EntityType.Builder.of(WitherSkeleton::new, MobCategory.MONSTER).fireImmune().immuneTo(Blocks.WITHER_ROSE).sized(0.7F, 2.4F).clientTrackingRange(8) +- ); +- public static final EntityType WITHER_SKULL = register( +- "wither_skull", +- EntityType.Builder.of(WitherSkull::new, MobCategory.MISC).sized(0.3125F, 0.3125F).clientTrackingRange(4).updateInterval(10) +- ); +- public static final EntityType WOLF = register( +- "wolf", EntityType.Builder.of(Wolf::new, MobCategory.CREATURE).sized(0.6F, 0.85F).clientTrackingRange(10) +- ); +- public static final EntityType ZOGLIN = register( +- "zoglin", EntityType.Builder.of(Zoglin::new, MobCategory.MONSTER).fireImmune().sized(1.3964844F, 1.4F).clientTrackingRange(8) +- ); +- public static final EntityType ZOMBIE = register( +- "zombie", EntityType.Builder.of(Zombie::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8) +- ); +- public static final EntityType ZOMBIE_HORSE = register( +- "zombie_horse", EntityType.Builder.of(ZombieHorse::new, MobCategory.CREATURE).sized(1.3964844F, 1.6F).clientTrackingRange(10) +- ); +- public static final EntityType ZOMBIE_VILLAGER = register( +- "zombie_villager", EntityType.Builder.of(ZombieVillager::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8) +- ); +- public static final EntityType ZOMBIFIED_PIGLIN = register( +- "zombified_piglin", EntityType.Builder.of(ZombifiedPiglin::new, MobCategory.MONSTER).fireImmune().sized(0.6F, 1.95F).clientTrackingRange(8) +- ); +- public static final EntityType PLAYER = register( +- "player", EntityType.Builder.createNothing(MobCategory.MISC).noSave().noSummon().sized(0.6F, 1.8F).clientTrackingRange(32).updateInterval(2) +- ); +- public static final EntityType FISHING_BOBBER = register( +- "fishing_bobber", +- EntityType.Builder.of(FishingHook::new, MobCategory.MISC).noSave().noSummon().sized(0.25F, 0.25F).clientTrackingRange(4).updateInterval(5) +- ); ++ public static final EntityType PIGLIN = register("piglin", EntityType.Builder.of(Piglin::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8)); ++ public static final EntityType PIGLIN_BRUTE = register("piglin_brute", EntityType.Builder.of(PiglinBrute::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8)); ++ public static final EntityType PILLAGER = register("pillager", EntityType.Builder.of(Pillager::new, MobCategory.MONSTER).canSpawnFarFromPlayer().sized(0.6F, 1.95F).clientTrackingRange(8)); ++ public static final EntityType POLAR_BEAR = register("polar_bear", EntityType.Builder.of(PolarBear::new, MobCategory.CREATURE).immuneTo(Blocks.POWDER_SNOW).sized(1.4F, 1.4F).clientTrackingRange(10)); ++ public static final EntityType POTION = register("potion", EntityType.Builder.of(ThrownPotion::new, MobCategory.MISC).sized(0.25F, 0.25F).clientTrackingRange(4).updateInterval(10)); ++ public static final EntityType PUFFERFISH = register("pufferfish", EntityType.Builder.of(Pufferfish::new, MobCategory.WATER_AMBIENT).sized(0.7F, 0.7F).clientTrackingRange(4)); ++ public static final EntityType RABBIT = register("rabbit", EntityType.Builder.of(Rabbit::new, MobCategory.CREATURE).sized(0.4F, 0.5F).clientTrackingRange(8)); ++ public static final EntityType RAVAGER = register("ravager", EntityType.Builder.of(Ravager::new, MobCategory.MONSTER).sized(1.95F, 2.2F).clientTrackingRange(10)); ++ public static final EntityType SALMON = register("salmon", EntityType.Builder.of(Salmon::new, MobCategory.WATER_AMBIENT).sized(0.7F, 0.4F).clientTrackingRange(4)); ++ public static final EntityType SHEEP = register("sheep", EntityType.Builder.of(Sheep::new, MobCategory.CREATURE).sized(0.9F, 1.3F).clientTrackingRange(10)); ++ public static final EntityType SHULKER = register("shulker", EntityType.Builder.of(Shulker::new, MobCategory.MONSTER).fireImmune().canSpawnFarFromPlayer().sized(1.0F, 1.0F).clientTrackingRange(10)); ++ public static final EntityType SHULKER_BULLET = register("shulker_bullet", EntityType.Builder.of(ShulkerBullet::new, MobCategory.MISC).sized(0.3125F, 0.3125F).clientTrackingRange(8)); ++ public static final EntityType SILVERFISH = register("silverfish", EntityType.Builder.of(Silverfish::new, MobCategory.MONSTER).sized(0.4F, 0.3F).clientTrackingRange(8)); ++ public static final EntityType SKELETON = register("skeleton", EntityType.Builder.of(Skeleton::new, MobCategory.MONSTER).sized(0.6F, 1.99F).clientTrackingRange(8)); ++ public static final EntityType SKELETON_HORSE = register("skeleton_horse", EntityType.Builder.of(SkeletonHorse::new, MobCategory.CREATURE).sized(1.3964844F, 1.6F).clientTrackingRange(10)); ++ public static final EntityType SLIME = register("slime", EntityType.Builder.of(Slime::new, MobCategory.MONSTER).sized(2.04F, 2.04F).clientTrackingRange(10)); ++ public static final EntityType SMALL_FIREBALL = register("small_fireball", EntityType.Builder.of(SmallFireball::new, MobCategory.MISC).sized(0.3125F, 0.3125F).clientTrackingRange(4).updateInterval(10)); ++ public static final EntityType SNIFFER = register("sniffer", EntityType.Builder.of(Sniffer::new, MobCategory.CREATURE).sized(1.9F, 1.75F).clientTrackingRange(10)); ++ public static final EntityType SNOW_GOLEM = register("snow_golem", EntityType.Builder.of(SnowGolem::new, MobCategory.MISC).immuneTo(Blocks.POWDER_SNOW).sized(0.7F, 1.9F).clientTrackingRange(8)); ++ public static final EntityType SNOWBALL = register("snowball", EntityType.Builder.of(Snowball::new, MobCategory.MISC).sized(0.25F, 0.25F).clientTrackingRange(4).updateInterval(10)); ++ public static final EntityType SPAWNER_MINECART = register("spawner_minecart", EntityType.Builder.of(MinecartSpawner::new, MobCategory.MISC).sized(0.98F, 0.7F).clientTrackingRange(8)); ++ public static final EntityType SPECTRAL_ARROW = register("spectral_arrow", EntityType.Builder.of(SpectralArrow::new, MobCategory.MISC).sized(0.5F, 0.5F).clientTrackingRange(4).updateInterval(20)); ++ public static final EntityType SPIDER = register("spider", EntityType.Builder.of(Spider::new, MobCategory.MONSTER).sized(1.4F, 0.9F).clientTrackingRange(8)); ++ public static final EntityType SQUID = register("squid", EntityType.Builder.of(Squid::new, MobCategory.WATER_CREATURE).sized(0.8F, 0.8F).clientTrackingRange(8)); ++ public static final EntityType STRAY = register("stray", EntityType.Builder.of(Stray::new, MobCategory.MONSTER).sized(0.6F, 1.99F).immuneTo(Blocks.POWDER_SNOW).clientTrackingRange(8)); ++ public static final EntityType STRIDER = register("strider", EntityType.Builder.of(Strider::new, MobCategory.CREATURE).fireImmune().sized(0.9F, 1.7F).clientTrackingRange(10)); ++ public static final EntityType TADPOLE = register("tadpole", EntityType.Builder.of(Tadpole::new, MobCategory.CREATURE).sized(Tadpole.HITBOX_WIDTH, Tadpole.HITBOX_HEIGHT).clientTrackingRange(10)); ++ public static final EntityType TEXT_DISPLAY = register("text_display", EntityType.Builder.of(Display.TextDisplay::new, MobCategory.MISC).sized(0.0F, 0.0F).clientTrackingRange(10).updateInterval(1)); ++ public static final EntityType TNT = register("tnt", EntityType.Builder.of(PrimedTnt::new, MobCategory.MISC).fireImmune().sized(0.98F, 0.98F).clientTrackingRange(10).updateInterval(10)); ++ public static final EntityType TNT_MINECART = register("tnt_minecart", EntityType.Builder.of(MinecartTNT::new, MobCategory.MISC).sized(0.98F, 0.7F).clientTrackingRange(8)); ++ public static final EntityType TRADER_LLAMA = register("trader_llama", EntityType.Builder.of(TraderLlama::new, MobCategory.CREATURE).sized(0.9F, 1.87F).clientTrackingRange(10)); ++ public static final EntityType TRIDENT = register("trident", EntityType.Builder.of(ThrownTrident::new, MobCategory.MISC).sized(0.5F, 0.5F).clientTrackingRange(4).updateInterval(20)); ++ public static final EntityType TROPICAL_FISH = register("tropical_fish", EntityType.Builder.of(TropicalFish::new, MobCategory.WATER_AMBIENT).sized(0.5F, 0.4F).clientTrackingRange(4)); ++ public static final EntityType TURTLE = register("turtle", EntityType.Builder.of(Turtle::new, MobCategory.CREATURE).sized(1.2F, 0.4F).clientTrackingRange(10)); ++ public static final EntityType VEX = register("vex", EntityType.Builder.of(Vex::new, MobCategory.MONSTER).fireImmune().sized(0.4F, 0.8F).clientTrackingRange(8)); ++ public static final EntityType VILLAGER = register("villager", EntityType.Builder.of(Villager::new, MobCategory.MISC).sized(0.6F, 1.95F).clientTrackingRange(10)); ++ public static final EntityType VINDICATOR = register("vindicator", EntityType.Builder.of(Vindicator::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8)); ++ public static final EntityType WANDERING_TRADER = register("wandering_trader", EntityType.Builder.of(WanderingTrader::new, MobCategory.CREATURE).sized(0.6F, 1.95F).clientTrackingRange(10)); ++ public static final EntityType WARDEN = register("warden", EntityType.Builder.of(Warden::new, MobCategory.MONSTER).sized(0.9F, 2.9F).clientTrackingRange(16).fireImmune()); ++ public static final EntityType WIND_CHARGE = register("wind_charge", EntityType.Builder.of(WindCharge::new, MobCategory.MISC).sized(0.3125F, 0.3125F).clientTrackingRange(4).updateInterval(10).requiredFeatures(FeatureFlags.UPDATE_1_21)); ++ public static final EntityType WITCH = register("witch", EntityType.Builder.of(Witch::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8)); ++ public static final EntityType WITHER = register("wither", EntityType.Builder.of(WitherBoss::new, MobCategory.MONSTER).fireImmune().immuneTo(Blocks.WITHER_ROSE).sized(0.9F, 3.5F).clientTrackingRange(10)); ++ public static final EntityType WITHER_SKELETON = register("wither_skeleton", EntityType.Builder.of(WitherSkeleton::new, MobCategory.MONSTER).fireImmune().immuneTo(Blocks.WITHER_ROSE).sized(0.7F, 2.4F).clientTrackingRange(8)); ++ public static final EntityType WITHER_SKULL = register("wither_skull", EntityType.Builder.of(WitherSkull::new, MobCategory.MISC).sized(0.3125F, 0.3125F).clientTrackingRange(4).updateInterval(10)); ++ public static final EntityType WOLF = register("wolf", EntityType.Builder.of(Wolf::new, MobCategory.CREATURE).sized(0.6F, 0.85F).clientTrackingRange(10)); ++ public static final EntityType ZOGLIN = register("zoglin", EntityType.Builder.of(Zoglin::new, MobCategory.MONSTER).fireImmune().sized(1.3964844F, 1.4F).clientTrackingRange(8)); ++ public static final EntityType ZOMBIE = register("zombie", EntityType.Builder.of(Zombie::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8)); ++ public static final EntityType ZOMBIE_HORSE = register("zombie_horse", EntityType.Builder.of(ZombieHorse::new, MobCategory.CREATURE).sized(1.3964844F, 1.6F).clientTrackingRange(10)); ++ public static final EntityType ZOMBIE_VILLAGER = register("zombie_villager", EntityType.Builder.of(ZombieVillager::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8)); ++ public static final EntityType ZOMBIFIED_PIGLIN = register("zombified_piglin", EntityType.Builder.of(ZombifiedPiglin::new, MobCategory.MONSTER).fireImmune().sized(0.6F, 1.95F).clientTrackingRange(8)); ++ public static final EntityType PLAYER = register("player", EntityType.Builder.createNothing(MobCategory.MISC).noSave().noSummon().sized(0.6F, 1.8F).clientTrackingRange(32).updateInterval(2)); ++ public static final EntityType FISHING_BOBBER = register("fishing_bobber", EntityType.Builder.of(FishingHook::new, MobCategory.MISC).noSave().noSummon().sized(0.25F, 0.25F).clientTrackingRange(4).updateInterval(5)); + private final EntityType.EntityFactory factory; + private final MobCategory category; + private final ImmutableSet immuneTo; +@@ -588,8 +314,8 @@ + private final EntityDimensions dimensions; + private final FeatureFlagSet requiredFeatures; + +- private static EntityType register(String key, EntityType.Builder builder) { +- return Registry.register(BuiltInRegistries.ENTITY_TYPE, key, builder.build(key)); ++ private static EntityType register(String key, EntityType.Builder builder) { // CraftBukkit - decompile error ++ return (EntityType) Registry.register(BuiltInRegistries.ENTITY_TYPE, key, (EntityType) builder.build(key)); // CraftBukkit - decompile error + } + + public static ResourceLocation getKey(EntityType entityType) { +@@ -600,19 +326,8 @@ + return BuiltInRegistries.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(key)); + } + +- public EntityType( +- EntityType.EntityFactory factory, +- MobCategory category, +- boolean serialize, +- boolean summon, +- boolean fireImmune, +- boolean canSpawnFarFromPlayer, +- ImmutableSet immuneTo, +- EntityDimensions dimensions, +- int clientTrackingRange, +- int updateInterval, +- FeatureFlagSet requiredFeatures +- ) { ++ public EntityType(EntityType.EntityFactory factory, MobCategory category, boolean serialize, boolean summon, boolean fireImmune, boolean canSpawnFarFromPlayer, ImmutableSet immuneTo, EntityDimensions dimensions, int clientTrackingRange, int updateInterval, FeatureFlagSet requiredFeatures) { ++ this.builtInRegistryHolder = BuiltInRegistries.ENTITY_TYPE.createIntrusiveHolder(this); + this.factory = factory; + this.category = category; + this.canSpawnFarFromPlayer = canSpawnFarFromPlayer; +@@ -627,134 +342,142 @@ + } + + @Nullable +- public T spawn( +- ServerLevel serverLevel, +- @Nullable ItemStack stack, +- @Nullable Player player, +- BlockPos pos, +- MobSpawnType spawnType, +- boolean shouldOffsetY, +- boolean shouldOffsetYMore +- ) { +- Consumer consumer; +- CompoundTag tag; +- if (stack != null) { +- tag = stack.getTag(); +- consumer = createDefaultStackConfig(serverLevel, stack, player); ++ public T spawn(ServerLevel serverLevel, @Nullable ItemStack stack, @Nullable Player player, BlockPos pos, EnumMobSpawn spawnType, boolean shouldOffsetY, boolean shouldOffsetYMore) { ++ // CraftBukkit start ++ return this.spawn(serverLevel, stack, player, pos, spawnType, shouldOffsetY, shouldOffsetYMore, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG); ++ } ++ ++ @Nullable ++ public T spawn(ServerLevel worldserver, @Nullable ItemStack itemstack, @Nullable Player entityhuman, BlockPos blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end ++ CompoundTag nbttagcompound; ++ Consumer consumer; // CraftBukkit - decompile error ++ ++ if (itemstack != null) { ++ nbttagcompound = itemstack.getTag(); ++ consumer = createDefaultStackConfig(worldserver, itemstack, entityhuman); + } else { +- consumer = entity -> { ++ consumer = (entity) -> { + }; +- tag = null; ++ nbttagcompound = null; + } + +- return this.spawn(serverLevel, tag, consumer, pos, spawnType, shouldOffsetY, shouldOffsetYMore); ++ return this.spawn(worldserver, nbttagcompound, consumer, blockposition, enummobspawn, flag, flag1, spawnReason); // CraftBukkit + } + + public static Consumer createDefaultStackConfig(ServerLevel serverLevel, ItemStack stack, @Nullable Player player) { +- return appendDefaultStackConfig(entity -> { ++ return appendDefaultStackConfig((entity) -> { + }, serverLevel, stack, player); + } + +- public static Consumer appendDefaultStackConfig( +- Consumer consumer, ServerLevel serverLevel, ItemStack stack, @Nullable Player player +- ) { ++ public static Consumer appendDefaultStackConfig(Consumer consumer, ServerLevel serverLevel, ItemStack stack, @Nullable Player player) { + return appendCustomEntityStackConfig(appendCustomNameConfig(consumer, stack), serverLevel, stack, player); + } + + public static Consumer appendCustomNameConfig(Consumer consumer, ItemStack stack) { +- return stack.hasCustomHoverName() ? consumer.andThen(entity -> entity.setCustomName(stack.getHoverName())) : consumer; ++ return stack.hasCustomHoverName() ? consumer.andThen((entity) -> { ++ entity.setCustomName(stack.getHoverName()); ++ }) : consumer; + } + +- public static Consumer appendCustomEntityStackConfig( +- Consumer consumer, ServerLevel level, ItemStack stack, @Nullable Player player +- ) { +- CompoundTag tag = stack.getTag(); +- return tag != null ? consumer.andThen(spawnedEntity -> updateCustomEntityTag(level, player, spawnedEntity, tag)) : consumer; ++ public static Consumer appendCustomEntityStackConfig(Consumer consumer, ServerLevel level, ItemStack stack, @Nullable Player player) { ++ CompoundTag nbttagcompound = stack.getTag(); ++ ++ return nbttagcompound != null ? consumer.andThen((entity) -> { ++ try { updateCustomEntityTag(level, player, entity, nbttagcompound); } catch (Throwable t) { LOGGER.warn("Error loading spawn egg NBT", t); } // CraftBukkit - SPIGOT-5665 ++ }) : consumer; + } + + @Nullable +- public T spawn(ServerLevel level, BlockPos pos, MobSpawnType spawnType) { +- return this.spawn(level, (CompoundTag)null, null, pos, spawnType, false, false); ++ public T spawn(ServerLevel level, BlockPos pos, EnumMobSpawn spawnType) { ++ // CraftBukkit start ++ return this.spawn(level, pos, spawnType, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); + } + + @Nullable +- public T spawn( +- ServerLevel level, +- @Nullable CompoundTag compound, +- @Nullable Consumer consumer, +- BlockPos pos, +- MobSpawnType spawnType, +- boolean shouldOffsetY, +- boolean shouldOffsetYMore +- ) { +- T entity = this.create(level, compound, consumer, pos, spawnType, shouldOffsetY, shouldOffsetYMore); +- if (entity != null) { +- level.addFreshEntityWithPassengers(entity); ++ public T spawn(ServerLevel worldserver, BlockPos blockposition, EnumMobSpawn enummobspawn, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ return this.spawn(worldserver, (CompoundTag) null, null, blockposition, enummobspawn, false, false, spawnReason); // CraftBukkit - decompile error ++ // CraftBukkit end ++ } ++ ++ @Nullable ++ public T spawn(ServerLevel level, @Nullable CompoundTag compound, @Nullable Consumer consumer, BlockPos pos, EnumMobSpawn spawnType, boolean shouldOffsetY, boolean shouldOffsetYMore) { ++ // CraftBukkit start ++ return this.spawn(level, compound, consumer, pos, spawnType, shouldOffsetY, shouldOffsetYMore, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ @Nullable ++ public T spawn(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Consumer consumer, BlockPos blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end ++ T t0 = this.create(worldserver, nbttagcompound, consumer, blockposition, enummobspawn, flag, flag1); ++ ++ if (t0 != null) { ++ worldserver.addFreshEntityWithPassengers(t0, spawnReason); ++ return !t0.isRemoved() ? t0 : null; // Don't return an entity when CreatureSpawnEvent is canceled ++ // CraftBukkit end + } + +- return entity; ++ return t0; + } + + @Nullable +- public T create( +- ServerLevel level, +- @Nullable CompoundTag nbt, +- @Nullable Consumer consumer, +- BlockPos pos, +- MobSpawnType spawnType, +- boolean shouldOffsetY, +- boolean shouldOffsetYMore +- ) { +- T entity = this.create(level); +- if (entity == null) { ++ public T create(ServerLevel level, @Nullable CompoundTag nbt, @Nullable Consumer consumer, BlockPos pos, EnumMobSpawn spawnType, boolean shouldOffsetY, boolean shouldOffsetYMore) { ++ T t0 = this.create(level); ++ ++ if (t0 == null) { + return null; + } else { +- double yOffset; ++ double d0; ++ + if (shouldOffsetY) { +- entity.setPos((double)pos.getX() + 0.5, (double)(pos.getY() + 1), (double)pos.getZ() + 0.5); +- yOffset = getYOffset(level, pos, shouldOffsetYMore, entity.getBoundingBox()); ++ t0.setPos((double) pos.getX() + 0.5D, (double) (pos.getY() + 1), (double) pos.getZ() + 0.5D); ++ d0 = getYOffset(level, pos, shouldOffsetYMore, t0.getBoundingBox()); + } else { +- yOffset = 0.0; ++ d0 = 0.0D; + } + +- entity.moveTo( +- (double)pos.getX() + 0.5, (double)pos.getY() + yOffset, (double)pos.getZ() + 0.5, Mth.wrapDegrees(level.random.nextFloat() * 360.0F), 0.0F +- ); +- if (entity instanceof Mob mob) { +- mob.yHeadRot = mob.getYRot(); +- mob.yBodyRot = mob.getYRot(); +- mob.finalizeSpawn(level, level.getCurrentDifficultyAt(mob.blockPosition()), spawnType, null, nbt); +- mob.playAmbientSound(); ++ t0.moveTo((double) pos.getX() + 0.5D, (double) pos.getY() + d0, (double) pos.getZ() + 0.5D, Mth.wrapDegrees(level.random.nextFloat() * 360.0F), 0.0F); ++ if (t0 instanceof Mob) { ++ Mob entityinsentient = (Mob) t0; ++ ++ entityinsentient.yHeadRot = entityinsentient.getYRot(); ++ entityinsentient.yBodyRot = entityinsentient.getYRot(); ++ entityinsentient.finalizeSpawn(level, level.getCurrentDifficultyAt(entityinsentient.blockPosition()), spawnType, (GroupDataEntity) null, nbt); ++ entityinsentient.playAmbientSound(); + } + + if (consumer != null) { +- consumer.accept(entity); ++ consumer.accept(t0); + } + +- return entity; ++ return t0; + } + } + + protected static double getYOffset(LevelReader level, BlockPos pos, boolean shouldOffsetYMore, AABB box) { +- AABB aABB = new AABB(pos); ++ AABB axisalignedbb1 = new AABB(pos); ++ + if (shouldOffsetYMore) { +- aABB = aABB.expandTowards(0.0, -1.0, 0.0); ++ axisalignedbb1 = axisalignedbb1.expandTowards(0.0D, -1.0D, 0.0D); + } + +- Iterable collisions = level.getCollisions(null, aABB); +- return 1.0 + Shapes.collide(Direction.Axis.Y, box, collisions, shouldOffsetYMore ? -2.0 : -1.0); ++ Iterable iterable = level.getCollisions((Entity) null, axisalignedbb1); ++ ++ return 1.0D + Shapes.collide(Direction.Axis.Y, box, iterable, shouldOffsetYMore ? -2.0D : -1.0D); + } + + public static void updateCustomEntityTag(Level level, @Nullable Player player, @Nullable Entity spawnedEntity, @Nullable CompoundTag itemNBT) { + if (itemNBT != null && itemNBT.contains("EntityTag", 10)) { +- MinecraftServer server = level.getServer(); +- if (server != null && spawnedEntity != null) { +- if (level.isClientSide || !spawnedEntity.onlyOpCanSetNbt() || player != null && server.getPlayerList().isOp(player.getGameProfile())) { +- CompoundTag compoundTag = spawnedEntity.saveWithoutId(new CompoundTag()); +- UUID uUID = spawnedEntity.getUUID(); +- compoundTag.merge(itemNBT.getCompound("EntityTag")); +- spawnedEntity.setUUID(uUID); +- spawnedEntity.load(compoundTag); ++ MinecraftServer minecraftserver = level.getServer(); ++ ++ if (minecraftserver != null && spawnedEntity != null) { ++ if (level.isClientSide || !spawnedEntity.onlyOpCanSetNbt() || player != null && minecraftserver.getPlayerList().isOp(player.getGameProfile())) { ++ CompoundTag nbttagcompound1 = spawnedEntity.saveWithoutId(new CompoundTag()); ++ UUID uuid = spawnedEntity.getUUID(); ++ ++ nbttagcompound1.merge(itemNBT.getCompound("EntityTag")); ++ spawnedEntity.setUUID(uuid); ++ spawnedEntity.load(nbttagcompound1); + } + } + } +@@ -796,20 +519,21 @@ + return this.description; + } + +- @Override + public String toString() { + return this.getDescriptionId(); + } + + public String toShortString() { +- int index = this.getDescriptionId().lastIndexOf(46); +- return index == -1 ? this.getDescriptionId() : this.getDescriptionId().substring(index + 1); ++ int i = this.getDescriptionId().lastIndexOf(46); ++ ++ return i == -1 ? this.getDescriptionId() : this.getDescriptionId().substring(i + 1); + } + + public ResourceLocation getDefaultLootTable() { + if (this.lootTable == null) { +- ResourceLocation key = BuiltInRegistries.ENTITY_TYPE.getKey(this); +- this.lootTable = key.withPrefix("entities/"); ++ ResourceLocation minecraftkey = BuiltInRegistries.ENTITY_TYPE.getKey(this); ++ ++ this.lootTable = minecraftkey.withPrefix("entities/"); + } + + return this.lootTable; +@@ -834,27 +558,23 @@ + } + + public static Optional create(CompoundTag tag, Level level) { +- return Util.ifElse( +- by(tag).map(entityType -> entityType.create(level)), +- entity -> entity.load(tag), +- () -> LOGGER.warn("Skipping Entity with id {}", tag.getString("id")) +- ); ++ return Util.ifElse(by(tag).map((entitytypes) -> { ++ return entitytypes.create(level); ++ }), (entity) -> { ++ entity.load(tag); ++ }, () -> { ++ EntityType.LOGGER.warn("Skipping Entity with id {}", tag.getString("id")); ++ }); + } + +- public AABB getAABB(double x, double y, double z) { ++ public AABB getAABB(double x, double d1, double y) { + float f = this.getWidth() / 2.0F; +- return new AABB(x - (double)f, y, z - (double)f, x + (double)f, y + (double)this.getHeight(), z + (double)f); ++ ++ return new AABB(x - (double) f, d1, y - (double) f, x + (double) f, d1 + (double) this.getHeight(), y + (double) f); + } + +- public boolean isBlockDangerous(BlockState state) { +- return !this.immuneTo.contains(state.getBlock()) +- && ( +- !this.fireImmune && WalkNodeEvaluator.isBurningBlock(state) +- || state.is(Blocks.WITHER_ROSE) +- || state.is(Blocks.SWEET_BERRY_BUSH) +- || state.is(Blocks.CACTUS) +- || state.is(Blocks.POWDER_SNOW) +- ); ++ public boolean isBlockDangerous(IBlockData state) { ++ return this.immuneTo.contains(state.getBlock()) ? false : (!this.fireImmune && WalkNodeEvaluator.isBurningBlock(state) ? true : state.is(Blocks.WITHER_ROSE) || state.is(Blocks.SWEET_BERRY_BUSH) || state.is(Blocks.CACTUS) || state.is(Blocks.POWDER_SNOW)); + } + + public EntityDimensions getDimensions() { +@@ -867,44 +587,44 @@ + + @Nullable + public static Entity loadEntityRecursive(CompoundTag compound, Level level, Function entityFunction) { +- return loadStaticEntity(compound, level).map(entityFunction).map(entity -> { ++ return (Entity) loadStaticEntity(compound, level).map(entityFunction).map((entity) -> { + if (compound.contains("Passengers", 9)) { +- ListTag list = compound.getList("Passengers", 10); ++ ListTag nbttaglist = compound.getList("Passengers", 10); + +- for (int i = 0; i < list.size(); i++) { +- Entity entity1 = loadEntityRecursive(list.getCompound(i), level, entityFunction); ++ for (int i = 0; i < nbttaglist.size(); ++i) { ++ Entity entity1 = loadEntityRecursive(nbttaglist.getCompound(i), level, entityFunction); ++ + if (entity1 != null) { + entity1.startRiding(entity, true); + } + } + } + +- return (Entity)entity; +- }).orElse(null); ++ return entity; ++ }).orElse(null); // CraftBukkit - decompile error + } + + public static Stream loadEntitiesRecursive(final List tags, final Level level) { + final Spliterator spliterator = tags.spliterator(); ++ + return StreamSupport.stream(new Spliterator() { +- @Override + public boolean tryAdvance(Consumer consumer) { +- return spliterator.tryAdvance(tag -> EntityType.loadEntityRecursive((CompoundTag)tag, level, entity -> { ++ return spliterator.tryAdvance((nbtbase) -> { ++ EntityType.loadEntityRecursive((CompoundTag) nbtbase, level, (entity) -> { + consumer.accept(entity); + return entity; +- })); ++ }); ++ }); + } + +- @Override + public Spliterator trySplit() { + return null; + } + +- @Override + public long estimateSize() { +- return (long)tags.size(); ++ return (long) tags.size(); + } + +- @Override + public int characteristics() { + return 1297; + } +@@ -914,8 +634,8 @@ + private static Optional loadStaticEntity(CompoundTag compound, Level level) { + try { + return create(compound, level); +- } catch (RuntimeException var3) { +- LOGGER.warn("Exception loading entity: ", (Throwable)var3); ++ } catch (RuntimeException runtimeexception) { ++ EntityType.LOGGER.warn("Exception loading entity: ", runtimeexception); + return Optional.empty(); + } + } +@@ -929,30 +649,20 @@ + } + + public boolean trackDeltas() { +- return this != PLAYER +- && this != LLAMA_SPIT +- && this != WITHER +- && this != BAT +- && this != ITEM_FRAME +- && this != GLOW_ITEM_FRAME +- && this != LEASH_KNOT +- && this != PAINTING +- && this != END_CRYSTAL +- && this != EVOKER_FANGS; ++ return this != EntityType.PLAYER && this != EntityType.LLAMA_SPIT && this != EntityType.WITHER && this != EntityType.BAT && this != EntityType.ITEM_FRAME && this != EntityType.GLOW_ITEM_FRAME && this != EntityType.LEASH_KNOT && this != EntityType.PAINTING && this != EntityType.END_CRYSTAL && this != EntityType.EVOKER_FANGS; + } + + public boolean is(TagKey> tag) { + return this.builtInRegistryHolder.is(tag); + } + +- public boolean is(HolderSet> holderSet) { +- return holderSet.contains(this.builtInRegistryHolder); ++ public boolean is(HolderSet> holderset) { ++ return holderset.contains(this.builtInRegistryHolder); + } + + @Nullable +- @Override + public T tryCast(Entity entity) { +- return (T)(entity.getType() == this ? entity : null); ++ return entity.getType() == this ? (T) entity : null; // CraftBukkit - decompile error + } + + @Override +@@ -960,12 +670,14 @@ + return Entity.class; + } + ++ /** @deprecated */ + @Deprecated + public Holder.Reference> builtInRegistryHolder() { + return this.builtInRegistryHolder; + } + + public static class Builder { ++ + private final EntityType.EntityFactory factory; + private final MobCategory category; + private ImmutableSet immuneTo = ImmutableSet.of(); +@@ -976,20 +688,23 @@ + private int clientTrackingRange = 5; + private int updateInterval = 3; + private EntityDimensions dimensions = EntityDimensions.scalable(0.6F, 1.8F); +- private FeatureFlagSet requiredFeatures = FeatureFlags.VANILLA_SET; ++ private FeatureFlagSet requiredFeatures; + + private Builder(EntityType.EntityFactory factory, MobCategory category) { ++ this.requiredFeatures = FeatureFlags.VANILLA_SET; + this.factory = factory; + this.category = category; + this.canSpawnFarFromPlayer = category == MobCategory.CREATURE || category == MobCategory.MISC; + } + +- public static EntityType.Builder of(EntityType.EntityFactory factory, MobCategory category) { ++ public static EntityType.Builder of(EntityType.EntityFactory factory, MobCategory category) { // CraftBukkit - decompile error + return new EntityType.Builder<>(factory, category); + } + + public static EntityType.Builder createNothing(MobCategory category) { +- return new EntityType.Builder<>((entityType, level) -> null, category); ++ return new EntityType.Builder<>((entitytypes, world) -> { ++ return null; ++ }, category); + } + + public EntityType.Builder sized(float width, float height) { +@@ -1039,26 +754,15 @@ + + public EntityType build(String key) { + if (this.serialize) { +- Util.fetchChoiceType(References.ENTITY_TREE, key); ++ Util.fetchChoiceType(DataConverterTypes.ENTITY_TREE, key); + } + +- return new EntityType<>( +- this.factory, +- this.category, +- this.serialize, +- this.summon, +- this.fireImmune, +- this.canSpawnFarFromPlayer, +- this.immuneTo, +- this.dimensions, +- this.clientTrackingRange, +- this.updateInterval, +- this.requiredFeatures +- ); ++ return new EntityType<>(this.factory, this.category, this.serialize, this.summon, this.fireImmune, this.canSpawnFarFromPlayer, this.immuneTo, this.dimensions, this.clientTrackingRange, this.updateInterval, this.requiredFeatures); + } + } + + public interface EntityFactory { ++ + T create(EntityType entityType, Level level); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ExperienceOrb.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ExperienceOrb.java.patch new file mode 100644 index 0000000000..099f58032d --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ExperienceOrb.java.patch @@ -0,0 +1,396 @@ +--- a/net/minecraft/world/entity/ExperienceOrb.java ++++ b/net/minecraft/world/entity/ExperienceOrb.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.entity; + ++import java.util.Iterator; + import java.util.List; + import java.util.Map.Entry; + import net.minecraft.core.BlockPos; +@@ -19,31 +20,38 @@ + import net.minecraft.world.level.entity.EntityTypeTest; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.player.PlayerExpCooldownChangeEvent; ++// CraftBukkit end + + public class ExperienceOrb extends Entity { ++ + private static final int LIFETIME = 6000; + private static final int ENTITY_SCAN_PERIOD = 20; + private static final int MAX_FOLLOW_DIST = 8; + private static final int ORB_GROUPS_PER_AREA = 40; +- private static final double ORB_MERGE_DISTANCE = 0.5; ++ private static final double ORB_MERGE_DISTANCE = 0.5D; + private int age; +- private int health = 5; +- private int value; +- private int count = 1; ++ private int health; ++ public int value; ++ private int count; + private Player followingPlayer; + +- public ExperienceOrb(Level level, double x, double y, double z, int value) { ++ public ExperienceOrb(Level level, double x, double d1, double y, int i) { + this(EntityType.EXPERIENCE_ORB, level); +- this.setPos(x, y, z); +- this.setYRot((float)(this.random.nextDouble() * 360.0)); +- this.setDeltaMovement( +- (this.random.nextDouble() * 0.2F - 0.1F) * 2.0, this.random.nextDouble() * 0.2 * 2.0, (this.random.nextDouble() * 0.2F - 0.1F) * 2.0 +- ); +- this.value = value; ++ this.setPos(x, d1, y); ++ this.setYRot((float) (this.random.nextDouble() * 360.0D)); ++ this.setDeltaMovement((this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D, this.random.nextDouble() * 0.2D * 2.0D, (this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D); ++ this.value = i; + } + + public ExperienceOrb(EntityType entityType, Level level) { + super(entityType, level); ++ this.health = 5; ++ this.count = 1; + } + + @Override +@@ -52,31 +60,27 @@ + } + + @Override +- protected void defineSynchedData() { +- } ++ protected void defineSynchedData() {} + + @Override + public void tick() { + super.tick(); ++ Player prevTarget = this.followingPlayer;// CraftBukkit - store old target + this.xo = this.getX(); + this.yo = this.getY(); + this.zo = this.getZ(); + if (this.isEyeInFluid(FluidTags.WATER)) { + this.setUnderwaterMovement(); + } else if (!this.isNoGravity()) { +- this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.03, 0.0)); ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.03D, 0.0D)); + } + + if (this.level().getFluidState(this.blockPosition()).is(FluidTags.LAVA)) { +- this.setDeltaMovement( +- (double)((this.random.nextFloat() - this.random.nextFloat()) * 0.2F), +- 0.2F, +- (double)((this.random.nextFloat() - this.random.nextFloat()) * 0.2F) +- ); ++ this.setDeltaMovement((double) ((this.random.nextFloat() - this.random.nextFloat()) * 0.2F), 0.20000000298023224D, (double) ((this.random.nextFloat() - this.random.nextFloat()) * 0.2F)); + } + + if (!this.level().noCollision(this.getBoundingBox())) { +- this.moveTowardsClosestSpace(this.getX(), (this.getBoundingBox().minY + this.getBoundingBox().maxY) / 2.0, this.getZ()); ++ this.moveTowardsClosestSpace(this.getX(), (this.getBoundingBox().minY + this.getBoundingBox().maxY) / 2.0D, this.getZ()); + } + + if (this.tickCount % 20 == 1) { +@@ -87,34 +91,49 @@ + this.followingPlayer = null; + } + +- if (this.followingPlayer != null) { +- Vec3 vec3 = new Vec3( +- this.followingPlayer.getX() - this.getX(), +- this.followingPlayer.getY() + (double)this.followingPlayer.getEyeHeight() / 2.0 - this.getY(), +- this.followingPlayer.getZ() - this.getZ() +- ); +- double d = vec3.lengthSqr(); +- if (d < 64.0) { +- double d1 = 1.0 - Math.sqrt(d) / 8.0; +- this.setDeltaMovement(this.getDeltaMovement().add(vec3.normalize().scale(d1 * d1 * 0.1))); ++ // CraftBukkit start ++ boolean cancelled = false; ++ if (this.followingPlayer != prevTarget) { ++ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(this, followingPlayer, (followingPlayer != null) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.FORGOT_TARGET); ++ LivingEntity target = (event.getTarget() == null) ? null : ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getTarget()).getHandle(); ++ cancelled = event.isCancelled(); ++ ++ if (cancelled) { ++ followingPlayer = prevTarget; ++ } else { ++ followingPlayer = (target instanceof Player) ? (Player) target : null; + } + } + +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ if (this.followingPlayer != null && !cancelled) { ++ // CraftBukkit end ++ Vec3 vec3d = new Vec3(this.followingPlayer.getX() - this.getX(), this.followingPlayer.getY() + (double) this.followingPlayer.getEyeHeight() / 2.0D - this.getY(), this.followingPlayer.getZ() - this.getZ()); ++ double d0 = vec3d.lengthSqr(); ++ ++ if (d0 < 64.0D) { ++ double d1 = 1.0D - Math.sqrt(d0) / 8.0D; ++ ++ this.setDeltaMovement(this.getDeltaMovement().add(vec3d.normalize().scale(d1 * d1 * 0.1D))); ++ } ++ } ++ ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + float f = 0.98F; ++ + if (this.onGround()) { + f = this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getFriction() * 0.98F; + } + +- this.setDeltaMovement(this.getDeltaMovement().multiply((double)f, 0.98, (double)f)); ++ this.setDeltaMovement(this.getDeltaMovement().multiply((double) f, 0.98D, (double) f)); + if (this.onGround()) { +- this.setDeltaMovement(this.getDeltaMovement().multiply(1.0, -0.9, 1.0)); ++ this.setDeltaMovement(this.getDeltaMovement().multiply(1.0D, -0.9D, 1.0D)); + } + +- this.age++; ++ ++this.age; + if (this.age >= 6000) { + this.discard(); + } ++ + } + + @Override +@@ -123,36 +142,47 @@ + } + + private void scanForEntities() { +- if (this.followingPlayer == null || this.followingPlayer.distanceToSqr(this) > 64.0) { +- this.followingPlayer = this.level().getNearestPlayer(this, 8.0); ++ if (this.followingPlayer == null || this.followingPlayer.distanceToSqr((Entity) this) > 64.0D) { ++ this.followingPlayer = this.level().getNearestPlayer(this, 8.0D); + } + + if (this.level() instanceof ServerLevel) { +- for (ExperienceOrb experienceOrb : this.level() +- .getEntities(EntityTypeTest.forClass(ExperienceOrb.class), this.getBoundingBox().inflate(0.5), this::canMerge)) { +- this.merge(experienceOrb); ++ List list = this.level().getEntities(EntityTypeTest.forClass(ExperienceOrb.class), this.getBoundingBox().inflate(0.5D), this::canMerge); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ ExperienceOrb entityexperienceorb = (ExperienceOrb) iterator.next(); ++ ++ this.merge(entityexperienceorb); + } + } ++ + } + + public static void award(ServerLevel level, Vec3 pos, int amount) { + while (amount > 0) { +- int experienceValue = getExperienceValue(amount); +- amount -= experienceValue; +- if (!tryMergeToExisting(level, pos, experienceValue)) { +- level.addFreshEntity(new ExperienceOrb(level, pos.x(), pos.y(), pos.z(), experienceValue)); ++ int j = getExperienceValue(amount); ++ ++ amount -= j; ++ if (!tryMergeToExisting(level, pos, j)) { ++ level.addFreshEntity(new ExperienceOrb(level, pos.x(), pos.y(), pos.z(), j)); + } + } ++ + } + + private static boolean tryMergeToExisting(ServerLevel level, Vec3 pos, int amount) { +- AABB aABB = AABB.ofSize(pos, 1.0, 1.0, 1.0); +- int randomInt = level.getRandom().nextInt(40); +- List entities = level.getEntities(EntityTypeTest.forClass(ExperienceOrb.class), aABB, orb -> canMerge(orb, randomInt, amount)); +- if (!entities.isEmpty()) { +- ExperienceOrb experienceOrb = entities.get(0); +- experienceOrb.count++; +- experienceOrb.age = 0; ++ AABB axisalignedbb = AABB.ofSize(pos, 1.0D, 1.0D, 1.0D); ++ int j = level.getRandom().nextInt(40); ++ List list = level.getEntities(EntityTypeTest.forClass(ExperienceOrb.class), axisalignedbb, (entityexperienceorb) -> { ++ return canMerge(entityexperienceorb, j, amount); ++ }); ++ ++ if (!list.isEmpty()) { ++ ExperienceOrb entityexperienceorb = (ExperienceOrb) list.get(0); ++ ++ ++entityexperienceorb.count; ++ entityexperienceorb.age = 0; + return true; + } else { + return false; +@@ -168,19 +198,19 @@ + } + + private void merge(ExperienceOrb orb) { +- this.count = this.count + orb.count; ++ this.count += orb.count; + this.age = Math.min(this.age, orb.age); + orb.discard(); + } + + private void setUnderwaterMovement() { +- Vec3 deltaMovement = this.getDeltaMovement(); +- this.setDeltaMovement(deltaMovement.x * 0.99F, Math.min(deltaMovement.y + 5.0E-4F, 0.06F), deltaMovement.z * 0.99F); ++ Vec3 vec3d = this.getDeltaMovement(); ++ ++ this.setDeltaMovement(vec3d.x * 0.9900000095367432D, Math.min(vec3d.y + 5.000000237487257E-4D, 0.05999999865889549D), vec3d.z * 0.9900000095367432D); + } + + @Override +- protected void doWaterSplashEffect() { +- } ++ protected void doWaterSplashEffect() {} + + @Override + public boolean hurt(DamageSource source, float amount) { +@@ -190,7 +220,7 @@ + return true; + } else { + this.markHurt(); +- this.health = (int)((float)this.health - amount); ++ this.health = (int) ((float) this.health - amount); + if (this.health <= 0) { + this.discard(); + } +@@ -201,9 +231,9 @@ + + @Override + public void addAdditionalSaveData(CompoundTag compound) { +- compound.putShort("Health", (short)this.health); +- compound.putShort("Age", (short)this.age); +- compound.putShort("Value", (short)this.value); ++ compound.putShort("Health", (short) this.health); ++ compound.putShort("Age", (short) this.age); ++ compound.putShort("Value", (short) this.value); + compound.putInt("Count", this.count); + } + +@@ -219,29 +249,42 @@ + public void playerTouch(Player entity) { + if (!this.level().isClientSide) { + if (entity.takeXpDelay == 0) { +- entity.takeXpDelay = 2; ++ entity.takeXpDelay = CraftEventFactory.callPlayerXpCooldownEvent(entity, 2, PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2; + entity.take(this, 1); + int i = this.repairPlayerItems(entity, this.value); ++ + if (i > 0) { +- entity.giveExperiencePoints(i); ++ entity.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(entity, i).getAmount()); // CraftBukkit - this.value -> event.getAmount() + } + +- this.count--; ++ --this.count; + if (this.count == 0) { + this.discard(); + } + } ++ + } + } + + private int repairPlayerItems(Player player, int repairAmount) { +- Entry randomItemWith = EnchantmentHelper.getRandomItemWith(Enchantments.MENDING, player, ItemStack::isDamaged); +- if (randomItemWith != null) { +- ItemStack itemStack = randomItemWith.getValue(); +- int min = Math.min(this.xpToDurability(repairAmount), itemStack.getDamageValue()); +- itemStack.setDamageValue(itemStack.getDamageValue() - min); +- int i = repairAmount - this.durabilityToXp(min); +- return i > 0 ? this.repairPlayerItems(player, i) : 0; ++ Entry entry = EnchantmentHelper.getRandomItemWith(Enchantments.MENDING, player, ItemStack::isDamaged); ++ ++ if (entry != null) { ++ ItemStack itemstack = (ItemStack) entry.getValue(); ++ int j = Math.min(this.xpToDurability(repairAmount), itemstack.getDamageValue()); ++ // CraftBukkit start ++ org.bukkit.event.player.PlayerItemMendEvent event = CraftEventFactory.callPlayerItemMendEvent(player, this, itemstack, entry.getKey(), j); ++ j = event.getRepairAmount(); ++ if (event.isCancelled()) { ++ return repairAmount; ++ } ++ // CraftBukkit end ++ ++ itemstack.setDamageValue(itemstack.getDamageValue() - j); ++ int k = repairAmount - this.durabilityToXp(j); ++ this.value = k; // CraftBukkit - update exp value of orb for PlayerItemMendEvent calls ++ ++ return k > 0 ? this.repairPlayerItems(player, k) : 0; + } else { + return repairAmount; + } +@@ -260,51 +303,29 @@ + } + + public int getIcon() { +- if (this.value >= 2477) { +- return 10; +- } else if (this.value >= 1237) { +- return 9; +- } else if (this.value >= 617) { +- return 8; +- } else if (this.value >= 307) { +- return 7; +- } else if (this.value >= 149) { +- return 6; +- } else if (this.value >= 73) { +- return 5; +- } else if (this.value >= 37) { +- return 4; +- } else if (this.value >= 17) { +- return 3; +- } else if (this.value >= 7) { +- return 2; +- } else { +- return this.value >= 3 ? 1 : 0; +- } ++ return this.value >= 2477 ? 10 : (this.value >= 1237 ? 9 : (this.value >= 617 ? 8 : (this.value >= 307 ? 7 : (this.value >= 149 ? 6 : (this.value >= 73 ? 5 : (this.value >= 37 ? 4 : (this.value >= 17 ? 3 : (this.value >= 7 ? 2 : (this.value >= 3 ? 1 : 0))))))))); + } + + public static int getExperienceValue(int expValue) { +- if (expValue >= 2477) { +- return 2477; +- } else if (expValue >= 1237) { +- return 1237; +- } else if (expValue >= 617) { +- return 617; +- } else if (expValue >= 307) { +- return 307; +- } else if (expValue >= 149) { +- return 149; +- } else if (expValue >= 73) { +- return 73; +- } else if (expValue >= 37) { +- return 37; +- } else if (expValue >= 17) { +- return 17; +- } else if (expValue >= 7) { +- return 7; +- } else { +- return expValue >= 3 ? 3 : 1; +- } ++ // CraftBukkit start ++ if (expValue > 162670129) return expValue - 100000; ++ if (expValue > 81335063) return 81335063; ++ if (expValue > 40667527) return 40667527; ++ if (expValue > 20333759) return 20333759; ++ if (expValue > 10166857) return 10166857; ++ if (expValue > 5083423) return 5083423; ++ if (expValue > 2541701) return 2541701; ++ if (expValue > 1270849) return 1270849; ++ if (expValue > 635413) return 635413; ++ if (expValue > 317701) return 317701; ++ if (expValue > 158849) return 158849; ++ if (expValue > 79423) return 79423; ++ if (expValue > 39709) return 39709; ++ if (expValue > 19853) return 19853; ++ if (expValue > 9923) return 9923; ++ if (expValue > 4957) return 4957; ++ // CraftBukkit end ++ return expValue >= 2477 ? 2477 : (expValue >= 1237 ? 1237 : (expValue >= 617 ? 617 : (expValue >= 307 ? 307 : (expValue >= 149 ? 149 : (expValue >= 73 ? 73 : (expValue >= 37 ? 37 : (expValue >= 17 ? 17 : (expValue >= 7 ? 7 : (expValue >= 3 ? 3 : 1))))))))); + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/Interaction.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/Interaction.java.patch new file mode 100644 index 0000000000..0d0972b193 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/Interaction.java.patch @@ -0,0 +1,264 @@ +--- a/net/minecraft/world/entity/Interaction.java ++++ b/net/minecraft/world/entity/Interaction.java +@@ -1,10 +1,10 @@ + package net.minecraft.world.entity; + +-import com.mojang.datafixers.util.Pair; + import com.mojang.logging.LogUtils; + import com.mojang.serialization.Codec; ++import com.mojang.serialization.DataResult; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; ++import java.util.Objects; + import java.util.UUID; + import javax.annotation.Nullable; + import net.minecraft.Util; +@@ -12,20 +12,26 @@ + import net.minecraft.core.UUIDUtil; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtOps; +-import net.minecraft.nbt.Tag; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; + import net.minecraft.server.level.ServerPlayer; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.material.PushReaction; ++import net.minecraft.world.level.material.EnumPistonReaction; + import net.minecraft.world.phys.AABB; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.world.damagesource.DamageSource; ++import net.minecraft.world.entity.player.Player; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityDamageEvent; ++// CraftBukkit end ++ + public class Interaction extends Entity implements Attackable, Targeting { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final EntityDataAccessor DATA_WIDTH_ID = SynchedEntityData.defineId(Interaction.class, EntityDataSerializers.FLOAT); + private static final EntityDataAccessor DATA_HEIGHT_ID = SynchedEntityData.defineId(Interaction.class, EntityDataSerializers.FLOAT); +@@ -36,9 +42,9 @@ + private static final String TAG_INTERACTION = "interaction"; + private static final String TAG_RESPONSE = "response"; + @Nullable +- private Interaction.PlayerAction attack; ++ public Interaction.PlayerAction attack; + @Nullable +- private Interaction.PlayerAction interaction; ++ public Interaction.PlayerAction interaction; + + public Interaction(EntityType entityType, Level level) { + super(entityType, level); +@@ -47,9 +53,9 @@ + + @Override + protected void defineSynchedData() { +- this.entityData.define(DATA_WIDTH_ID, 1.0F); +- this.entityData.define(DATA_HEIGHT_ID, 1.0F); +- this.entityData.define(DATA_RESPONSE_ID, false); ++ this.entityData.define(Interaction.DATA_WIDTH_ID, 1.0F); ++ this.entityData.define(Interaction.DATA_HEIGHT_ID, 1.0F); ++ this.entityData.define(Interaction.DATA_RESPONSE_ID, false); + } + + @Override +@@ -62,20 +68,27 @@ + this.setHeight(compound.getFloat("height")); + } + ++ DataResult> dataresult; // CraftBukkit - decompile error ++ Logger logger; ++ + if (compound.contains("attack")) { +- Interaction.PlayerAction.CODEC +- .decode(NbtOps.INSTANCE, compound.get("attack")) +- .resultOrPartial(Util.prefix("Interaction entity", LOGGER::error)) +- .ifPresent(pair -> this.attack = pair.getFirst()); ++ dataresult = Interaction.PlayerAction.CODEC.decode(NbtOps.INSTANCE, compound.get("attack")); ++ logger = Interaction.LOGGER; ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(Util.prefix("Interaction entity", logger::error)).ifPresent((pair) -> { ++ this.attack = (Interaction.PlayerAction) pair.getFirst(); ++ }); + } else { + this.attack = null; + } + + if (compound.contains("interaction")) { +- Interaction.PlayerAction.CODEC +- .decode(NbtOps.INSTANCE, compound.get("interaction")) +- .resultOrPartial(Util.prefix("Interaction entity", LOGGER::error)) +- .ifPresent(pair -> this.interaction = pair.getFirst()); ++ dataresult = Interaction.PlayerAction.CODEC.decode(NbtOps.INSTANCE, compound.get("interaction")); ++ logger = Interaction.LOGGER; ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(Util.prefix("Interaction entity", logger::error)).ifPresent((pair) -> { ++ this.interaction = (Interaction.PlayerAction) pair.getFirst(); ++ }); + } else { + this.interaction = null; + } +@@ -89,11 +102,15 @@ + compound.putFloat("width", this.getWidth()); + compound.putFloat("height", this.getHeight()); + if (this.attack != null) { +- Interaction.PlayerAction.CODEC.encodeStart(NbtOps.INSTANCE, this.attack).result().ifPresent(tag -> compound.put("attack", tag)); ++ Interaction.PlayerAction.CODEC.encodeStart(NbtOps.INSTANCE, this.attack).result().ifPresent((nbtbase) -> { ++ compound.put("attack", nbtbase); ++ }); + } + + if (this.interaction != null) { +- Interaction.PlayerAction.CODEC.encodeStart(NbtOps.INSTANCE, this.interaction).result().ifPresent(tag -> compound.put("interaction", tag)); ++ Interaction.PlayerAction.CODEC.encodeStart(NbtOps.INSTANCE, this.interaction).result().ifPresent((nbtbase) -> { ++ compound.put("interaction", nbtbase); ++ }); + } + + compound.putBoolean("response", this.getResponse()); +@@ -102,9 +119,10 @@ + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { + super.onSyncedDataUpdated(key); +- if (DATA_HEIGHT_ID.equals(key) || DATA_WIDTH_ID.equals(key)) { ++ if (Interaction.DATA_HEIGHT_ID.equals(key) || Interaction.DATA_WIDTH_ID.equals(key)) { + this.setBoundingBox(this.makeBoundingBox()); + } ++ + } + + @Override +@@ -118,8 +136,8 @@ + } + + @Override +- public PushReaction getPistonPushReaction() { +- return PushReaction.IGNORE; ++ public EnumPistonReaction getPistonPushReaction() { ++ return EnumPistonReaction.IGNORE; + } + + @Override +@@ -129,12 +147,23 @@ + + @Override + public boolean skipAttackInteraction(Entity entity) { +- if (entity instanceof Player player) { +- this.attack = new Interaction.PlayerAction(player.getUUID(), this.level().getGameTime()); +- if (player instanceof ServerPlayer serverPlayer) { +- CriteriaTriggers.PLAYER_HURT_ENTITY.trigger(serverPlayer, this, player.damageSources().generic(), 1.0F, 1.0F, false); ++ if (entity instanceof Player) { ++ Player entityhuman = (Player) entity; ++ // CraftBukkit start ++ DamageSource source = entityhuman.damageSources().playerAttack(entityhuman); ++ EntityDamageEvent event = CraftEventFactory.callNonLivingEntityDamageEvent(this, source, 1.0F, false); ++ if (event.isCancelled()) { ++ return true; + } ++ // CraftBukkit end + ++ this.attack = new Interaction.PlayerAction(entityhuman.getUUID(), this.level().getGameTime()); ++ if (entityhuman instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entityhuman; ++ ++ CriteriaTriggers.PLAYER_HURT_ENTITY.trigger(entityplayer, this, source, (float) event.getFinalDamage(), 1.0F, false); // CraftBukkit ++ } ++ + return !this.getResponse(); + } else { + return false; +@@ -142,7 +171,7 @@ + } + + @Override +- public InteractionResult interact(Player player, InteractionHand hand) { ++ public InteractionResult interact(Player player, EnumHand hand) { + if (this.level().isClientSide) { + return this.getResponse() ? InteractionResult.SUCCESS : InteractionResult.CONSUME; + } else { +@@ -152,8 +181,7 @@ + } + + @Override +- public void tick() { +- } ++ public void tick() {} + + @Nullable + @Override +@@ -167,28 +195,28 @@ + return this.interaction != null ? this.level().getPlayerByUUID(this.interaction.player()) : null; + } + +- private void setWidth(float width) { +- this.entityData.set(DATA_WIDTH_ID, width); ++ public void setWidth(float width) { ++ this.entityData.set(Interaction.DATA_WIDTH_ID, width); + } + +- private float getWidth() { +- return this.entityData.get(DATA_WIDTH_ID); ++ public float getWidth() { ++ return (Float) this.entityData.get(Interaction.DATA_WIDTH_ID); + } + +- private void setHeight(float height) { +- this.entityData.set(DATA_HEIGHT_ID, height); ++ public void setHeight(float height) { ++ this.entityData.set(Interaction.DATA_HEIGHT_ID, height); + } + +- private float getHeight() { +- return this.entityData.get(DATA_HEIGHT_ID); ++ public float getHeight() { ++ return (Float) this.entityData.get(Interaction.DATA_HEIGHT_ID); + } + +- private void setResponse(boolean response) { +- this.entityData.set(DATA_RESPONSE_ID, response); ++ public void setResponse(boolean response) { ++ this.entityData.set(Interaction.DATA_RESPONSE_ID, response); + } + +- private boolean getResponse() { +- return this.entityData.get(DATA_RESPONSE_ID); ++ public boolean getResponse() { ++ return (Boolean) this.entityData.get(Interaction.DATA_RESPONSE_ID); + } + + private EntityDimensions getDimensions() { +@@ -196,7 +224,7 @@ + } + + @Override +- public EntityDimensions getDimensions(Pose pose) { ++ public EntityDimensions getDimensions(EntityPose pose) { + return this.getDimensions(); + } + +@@ -205,13 +233,10 @@ + return this.getDimensions().makeBoundingBox(this.position()); + } + +- static record PlayerAction(UUID player, long timestamp) { +- public static final Codec CODEC = RecordCodecBuilder.create( +- instance -> instance.group( +- UUIDUtil.CODEC.fieldOf("player").forGetter(Interaction.PlayerAction::player), +- Codec.LONG.fieldOf("timestamp").forGetter(Interaction.PlayerAction::timestamp) +- ) +- .apply(instance, Interaction.PlayerAction::new) +- ); ++ public static record PlayerAction(UUID player, long timestamp) { ++ ++ public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(UUIDUtil.CODEC.fieldOf("player").forGetter(Interaction.PlayerAction::player), Codec.LONG.fieldOf("timestamp").forGetter(Interaction.PlayerAction::timestamp)).apply(instance, Interaction.PlayerAction::new); ++ }); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ItemBasedSteering.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ItemBasedSteering.java.patch new file mode 100644 index 0000000000..e070baaf32 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ItemBasedSteering.java.patch @@ -0,0 +1,56 @@ +--- a/net/minecraft/world/entity/ItemBasedSteering.java ++++ b/net/minecraft/world/entity/ItemBasedSteering.java +@@ -7,13 +7,14 @@ + import net.minecraft.util.RandomSource; + + public class ItemBasedSteering { ++ + private static final int MIN_BOOST_TIME = 140; + private static final int MAX_BOOST_TIME = 700; + private final SynchedEntityData entityData; + private final EntityDataAccessor boostTimeAccessor; + private final EntityDataAccessor hasSaddleAccessor; +- private boolean boosting; +- private int boostTime; ++ public boolean boosting; ++ public int boostTime; + + public ItemBasedSteering(SynchedEntityData entityData, EntityDataAccessor boostTimeAccessor, EntityDataAccessor hasSaddleAccessor) { + this.entityData = entityData; +@@ -41,16 +42,25 @@ + if (this.boosting && this.boostTime++ > this.boostTimeTotal()) { + this.boosting = false; + } ++ + } + + public float boostFactor() { +- return this.boosting ? 1.0F + 1.15F * Mth.sin((float)this.boostTime / (float)this.boostTimeTotal() * (float) Math.PI) : 1.0F; ++ return this.boosting ? 1.0F + 1.15F * Mth.sin((float) this.boostTime / (float) this.boostTimeTotal() * 3.1415927F) : 1.0F; + } + +- private int boostTimeTotal() { +- return this.entityData.get(this.boostTimeAccessor); ++ public int boostTimeTotal() { ++ return (Integer) this.entityData.get(this.boostTimeAccessor); + } + ++ // CraftBukkit add setBoostTicks(int) ++ public void setBoostTicks(int ticks) { ++ this.boosting = true; ++ this.boostTime = 0; ++ this.entityData.set(this.boostTimeAccessor, ticks); ++ } ++ // CraftBukkit end ++ + public void addAdditionalSaveData(CompoundTag nbt) { + nbt.putBoolean("Saddle", this.hasSaddle()); + } +@@ -64,6 +74,6 @@ + } + + public boolean hasSaddle() { +- return this.entityData.get(this.hasSaddleAccessor); ++ return (Boolean) this.entityData.get(this.hasSaddleAccessor); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/LightningBolt.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/LightningBolt.java.patch new file mode 100644 index 0000000000..316571091b --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/LightningBolt.java.patch @@ -0,0 +1,349 @@ +--- a/net/minecraft/world/entity/LightningBolt.java ++++ b/net/minecraft/world/entity/LightningBolt.java +@@ -1,6 +1,8 @@ + package net.minecraft.world.entity; + + import com.google.common.collect.Sets; ++import java.util.Collection; ++import java.util.Iterator; + import java.util.List; + import java.util.Optional; + import java.util.Set; +@@ -8,6 +10,8 @@ + import javax.annotation.Nullable; + import net.minecraft.advancements.CriteriaTriggers; + import net.minecraft.core.BlockPos; ++import net.minecraft.core.Direction; ++import net.minecraft.core.Vec3i; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; +@@ -20,19 +24,23 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.LightningRodBlock; + import net.minecraft.world.level.block.WeatheringCopper; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class LightningBolt extends Entity { ++ + private static final int START_LIFE = 2; +- private static final double DAMAGE_RADIUS = 3.0; +- private static final double DETECTION_RADIUS = 15.0; +- private int life; ++ private static final double DAMAGE_RADIUS = 3.0D; ++ private static final double DETECTION_RADIUS = 15.0D; ++ public int life; + public long seed; +- private int flashes; +- private boolean visualOnly; ++ public int flashes; ++ public boolean visualOnly; + @Nullable + private ServerPlayer cause; + private final Set hitEntities = Sets.newHashSet(); +@@ -65,11 +73,13 @@ + } + + private void powerLightningRod() { +- BlockPos strikePosition = this.getStrikePosition(); +- BlockState blockState = this.level().getBlockState(strikePosition); +- if (blockState.is(Blocks.LIGHTNING_ROD)) { +- ((LightningRodBlock)blockState.getBlock()).onLightningStrike(blockState, this.level(), strikePosition); ++ BlockPos blockposition = this.getStrikePosition(); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); ++ ++ if (iblockdata.is(Blocks.LIGHTNING_ROD)) { ++ ((LightningRodBlock) iblockdata.getBlock()).onLightningStrike(iblockdata, this.level(), blockposition); + } ++ + } + + @Override +@@ -77,31 +87,12 @@ + super.tick(); + if (this.life == 2) { + if (this.level().isClientSide()) { +- this.level() +- .playLocalSound( +- this.getX(), +- this.getY(), +- this.getZ(), +- SoundEvents.LIGHTNING_BOLT_THUNDER, +- SoundSource.WEATHER, +- 10000.0F, +- 0.8F + this.random.nextFloat() * 0.2F, +- false +- ); +- this.level() +- .playLocalSound( +- this.getX(), +- this.getY(), +- this.getZ(), +- SoundEvents.LIGHTNING_BOLT_IMPACT, +- SoundSource.WEATHER, +- 2.0F, +- 0.5F + this.random.nextFloat() * 0.2F, +- false +- ); ++ this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.LIGHTNING_BOLT_THUNDER, SoundSource.WEATHER, 10000.0F, 0.8F + this.random.nextFloat() * 0.2F, false); ++ this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.LIGHTNING_BOLT_IMPACT, SoundSource.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F, false); + } else { +- Difficulty difficulty = this.level().getDifficulty(); +- if (difficulty == Difficulty.NORMAL || difficulty == Difficulty.HARD) { ++ Difficulty enumdifficulty = this.level().getDifficulty(); ++ ++ if (enumdifficulty == Difficulty.NORMAL || enumdifficulty == Difficulty.HARD) { + this.spawnFire(4); + } + +@@ -111,148 +102,175 @@ + } + } + +- this.life--; ++ --this.life; ++ List list; ++ Iterator iterator; ++ + if (this.life < 0) { + if (this.flashes == 0) { + if (this.level() instanceof ServerLevel) { +- List entities = this.level() +- .getEntities( +- this, +- new AABB( +- this.getX() - 15.0, this.getY() - 15.0, this.getZ() - 15.0, this.getX() + 15.0, this.getY() + 6.0 + 15.0, this.getZ() + 15.0 +- ), +- entity1 -> entity1.isAlive() && !this.hitEntities.contains(entity1) +- ); ++ list = this.level().getEntities((Entity) this, new AABB(this.getX() - 15.0D, this.getY() - 15.0D, this.getZ() - 15.0D, this.getX() + 15.0D, this.getY() + 6.0D + 15.0D, this.getZ() + 15.0D), (entity) -> { ++ return entity.isAlive() && !this.hitEntities.contains(entity); ++ }); ++ iterator = ((ServerLevel) this.level()).getPlayers((entityplayer) -> { ++ return entityplayer.distanceTo(this) < 256.0F; ++ }).iterator(); + +- for (ServerPlayer serverPlayer : ((ServerLevel)this.level()).getPlayers(player -> player.distanceTo(this) < 256.0F)) { +- CriteriaTriggers.LIGHTNING_STRIKE.trigger(serverPlayer, this, entities); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ CriteriaTriggers.LIGHTNING_STRIKE.trigger(entityplayer, this, list); + } + } + + this.discard(); + } else if (this.life < -this.random.nextInt(10)) { +- this.flashes--; ++ --this.flashes; + this.life = 1; + this.seed = this.random.nextLong(); + this.spawnFire(0); + } + } + +- if (this.life >= 0) { ++ if (this.life >= 0 && !this.visualOnly) { // CraftBukkit - add !this.visualOnly + if (!(this.level() instanceof ServerLevel)) { + this.level().setSkyFlashTime(2); + } else if (!this.visualOnly) { +- List entities = this.level() +- .getEntities( +- this, +- new AABB(this.getX() - 3.0, this.getY() - 3.0, this.getZ() - 3.0, this.getX() + 3.0, this.getY() + 6.0 + 3.0, this.getZ() + 3.0), +- Entity::isAlive +- ); ++ list = this.level().getEntities((Entity) this, new AABB(this.getX() - 3.0D, this.getY() - 3.0D, this.getZ() - 3.0D, this.getX() + 3.0D, this.getY() + 6.0D + 3.0D, this.getZ() + 3.0D), Entity::isAlive); ++ iterator = list.iterator(); + +- for (Entity entity : entities) { +- entity.thunderHit((ServerLevel)this.level(), this); ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ ++ entity.thunderHit((ServerLevel) this.level(), this); + } + +- this.hitEntities.addAll(entities); ++ this.hitEntities.addAll(list); + if (this.cause != null) { +- CriteriaTriggers.CHANNELED_LIGHTNING.trigger(this.cause, entities); ++ CriteriaTriggers.CHANNELED_LIGHTNING.trigger(this.cause, (Collection) list); + } + } + } ++ + } + + private BlockPos getStrikePosition() { +- Vec3 vec3 = this.position(); +- return BlockPos.containing(vec3.x, vec3.y - 1.0E-6, vec3.z); ++ Vec3 vec3d = this.position(); ++ ++ return BlockPos.containing(vec3d.x, vec3d.y - 1.0E-6D, vec3d.z); + } + + private void spawnFire(int extraIgnitions) { + if (!this.visualOnly && !this.level().isClientSide && this.level().getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) { +- BlockPos blockPos = this.blockPosition(); +- BlockState state = BaseFireBlock.getState(this.level(), blockPos); +- if (this.level().getBlockState(blockPos).isAir() && state.canSurvive(this.level(), blockPos)) { +- this.level().setBlockAndUpdate(blockPos, state); +- this.blocksSetOnFire++; ++ BlockPos blockposition = this.blockPosition(); ++ IBlockData iblockdata = BaseFireBlock.getState(this.level(), blockposition); ++ ++ if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) { ++ // CraftBukkit start - add "!visualOnly" ++ if (!visualOnly && !CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition, this).isCancelled()) { ++ this.level().setBlockAndUpdate(blockposition, iblockdata); ++ ++this.blocksSetOnFire; ++ } ++ // CraftBukkit end + } + +- for (int i = 0; i < extraIgnitions; i++) { +- BlockPos blockPos1 = blockPos.offset(this.random.nextInt(3) - 1, this.random.nextInt(3) - 1, this.random.nextInt(3) - 1); +- state = BaseFireBlock.getState(this.level(), blockPos1); +- if (this.level().getBlockState(blockPos1).isAir() && state.canSurvive(this.level(), blockPos1)) { +- this.level().setBlockAndUpdate(blockPos1, state); +- this.blocksSetOnFire++; ++ for (int j = 0; j < extraIgnitions; ++j) { ++ BlockPos blockposition1 = blockposition.offset(this.random.nextInt(3) - 1, this.random.nextInt(3) - 1, this.random.nextInt(3) - 1); ++ ++ iblockdata = BaseFireBlock.getState(this.level(), blockposition1); ++ if (this.level().getBlockState(blockposition1).isAir() && iblockdata.canSurvive(this.level(), blockposition1)) { ++ // CraftBukkit start - add "!visualOnly" ++ if (!visualOnly && !CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition1, this).isCancelled()) { ++ this.level().setBlockAndUpdate(blockposition1, iblockdata); ++ ++this.blocksSetOnFire; ++ } ++ // CraftBukkit end + } + } ++ + } + } + + private static void clearCopperOnLightningStrike(Level level, BlockPos pos) { +- BlockState blockState = level.getBlockState(pos); +- BlockPos blockPos; +- BlockState blockState1; +- if (blockState.is(Blocks.LIGHTNING_ROD)) { +- blockPos = pos.relative(blockState.getValue(LightningRodBlock.FACING).getOpposite()); +- blockState1 = level.getBlockState(blockPos); ++ IBlockData iblockdata = level.getBlockState(pos); ++ BlockPos blockposition1; ++ IBlockData iblockdata1; ++ ++ if (iblockdata.is(Blocks.LIGHTNING_ROD)) { ++ blockposition1 = pos.relative(((Direction) iblockdata.getValue(LightningRodBlock.FACING)).getOpposite()); ++ iblockdata1 = level.getBlockState(blockposition1); + } else { +- blockPos = pos; +- blockState1 = blockState; ++ blockposition1 = pos; ++ iblockdata1 = iblockdata; + } + +- if (blockState1.getBlock() instanceof WeatheringCopper) { +- level.setBlockAndUpdate(blockPos, WeatheringCopper.getFirst(level.getBlockState(blockPos))); +- BlockPos.MutableBlockPos mutableBlockPos = pos.mutable(); ++ if (iblockdata1.getBlock() instanceof WeatheringCopper) { ++ level.setBlockAndUpdate(blockposition1, WeatheringCopper.getFirst(level.getBlockState(blockposition1))); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); + int i = level.random.nextInt(3) + 3; + +- for (int i1 = 0; i1 < i; i1++) { +- int i2 = level.random.nextInt(8) + 1; +- randomWalkCleaningCopper(level, blockPos, mutableBlockPos, i2); ++ for (int j = 0; j < i; ++j) { ++ int k = level.random.nextInt(8) + 1; ++ ++ randomWalkCleaningCopper(level, blockposition1, blockposition_mutableblockposition, k); + } ++ + } + } + + private static void randomWalkCleaningCopper(Level level, BlockPos pos, BlockPos.MutableBlockPos mutable, int steps) { + mutable.set(pos); + +- for (int i = 0; i < steps; i++) { ++ for (int j = 0; j < steps; ++j) { + Optional optional = randomStepCleaningCopper(level, mutable); ++ + if (optional.isEmpty()) { + break; + } + +- mutable.set(optional.get()); ++ mutable.set((Vec3i) optional.get()); + } ++ + } + + private static Optional randomStepCleaningCopper(Level level, BlockPos pos) { +- for (BlockPos blockPos : BlockPos.randomInCube(level.random, 10, pos, 1)) { +- BlockState blockState = level.getBlockState(blockPos); +- if (blockState.getBlock() instanceof WeatheringCopper) { +- WeatheringCopper.getPrevious(blockState).ifPresent(blockState1 -> level.setBlockAndUpdate(blockPos, blockState1)); +- level.levelEvent(3002, blockPos, -1); +- return Optional.of(blockPos); ++ Iterator iterator = BlockPos.randomInCube(level.random, 10, pos, 1).iterator(); ++ ++ BlockPos blockposition1; ++ IBlockData iblockdata; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return Optional.empty(); + } +- } + +- return Optional.empty(); ++ blockposition1 = (BlockPos) iterator.next(); ++ iblockdata = level.getBlockState(blockposition1); ++ } while (!(iblockdata.getBlock() instanceof WeatheringCopper)); ++ ++ BlockPos blockposition1Final = blockposition1; // CraftBukkit - decompile error ++ WeatheringCopper.getPrevious(iblockdata).ifPresent((iblockdata1) -> { ++ level.setBlockAndUpdate(blockposition1Final, iblockdata1); // CraftBukkit - decompile error ++ }); ++ level.levelEvent(3002, blockposition1, -1); ++ return Optional.of(blockposition1); + } + + @Override + public boolean shouldRenderAtSqrDistance(double distance) { +- double d = 64.0 * getViewScale(); +- return distance < d * d; ++ double d1 = 64.0D * getViewScale(); ++ ++ return distance < d1 * d1; + } + + @Override +- protected void defineSynchedData() { +- } ++ protected void defineSynchedData() {} + + @Override +- protected void readAdditionalSaveData(CompoundTag compound) { +- } ++ protected void readAdditionalSaveData(CompoundTag compound) {} + + @Override +- protected void addAdditionalSaveData(CompoundTag compound) { +- } ++ protected void addAdditionalSaveData(CompoundTag compound) {} + + public int getBlocksSetOnFire() { + return this.blocksSetOnFire; diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/LivingEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/LivingEntity.java.patch new file mode 100644 index 0000000000..658d8616c5 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/LivingEntity.java.patch @@ -0,0 +1,4535 @@ +--- a/net/minecraft/world/entity/LivingEntity.java ++++ b/net/minecraft/world/entity/LivingEntity.java +@@ -29,6 +29,8 @@ + import net.minecraft.core.particles.ItemParticleOption; + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.FloatTag; ++import net.minecraft.nbt.IntTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtOps; + import net.minecraft.nbt.Tag; +@@ -59,7 +61,7 @@ + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.world.Difficulty; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.damagesource.CombatRules; + import net.minecraft.world.damagesource.CombatTracker; + import net.minecraft.world.damagesource.DamageSource; +@@ -76,20 +78,19 @@ + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.attributes.DefaultAttributes; + import net.minecraft.world.entity.ai.targeting.TargetingConditions; +-import net.minecraft.world.entity.animal.FlyingAnimal; ++import net.minecraft.world.entity.animal.EntityBird; + import net.minecraft.world.entity.animal.Wolf; + import net.minecraft.world.entity.boss.wither.WitherBoss; + import net.minecraft.world.entity.item.ItemEntity; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.AbstractArrow; + import net.minecraft.world.food.FoodProperties; + import net.minecraft.world.item.AxeItem; + import net.minecraft.world.item.ElytraItem; ++import net.minecraft.world.item.EnumAnimation; + import net.minecraft.world.item.Equipable; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +-import net.minecraft.world.item.UseAnim; + import net.minecraft.world.item.alchemy.PotionUtils; + import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.item.enchantment.Enchantments; +@@ -104,7 +105,7 @@ + import net.minecraft.world.level.block.PowderSnowBlock; + import net.minecraft.world.level.block.SoundType; + import net.minecraft.world.level.block.TrapDoorBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.entity.EntityTypeTest; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.Fluid; +@@ -119,14 +120,33 @@ + import net.minecraft.world.scores.PlayerTeam; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.HashSet; ++import java.util.Set; ++import com.google.common.base.Function; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.attribute.CraftAttributeMap; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.Player; ++import org.bukkit.event.entity.ArrowBodyCountChangeEvent; ++import org.bukkit.event.entity.EntityDamageEvent; ++import org.bukkit.event.entity.EntityDamageEvent.DamageModifier; ++import org.bukkit.event.entity.EntityPotionEffectEvent; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++import org.bukkit.event.entity.EntityResurrectEvent; ++import org.bukkit.event.entity.EntityTeleportEvent; ++import org.bukkit.event.player.PlayerItemConsumeEvent; ++// CraftBukkit end ++ + public abstract class LivingEntity extends Entity implements Attackable { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final String TAG_ACTIVE_EFFECTS = "active_effects"; + private static final UUID SPEED_MODIFIER_SOUL_SPEED_UUID = UUID.fromString("87f46a96-686f-4796-b035-22e16ee9e038"); + private static final UUID SPEED_MODIFIER_POWDER_SNOW_UUID = UUID.fromString("1eaf83ff-7207-4596-b37a-d7a07b3ec4ce"); +- private static final AttributeModifier SPEED_MODIFIER_SPRINTING = new AttributeModifier( +- UUID.fromString("662A6B8D-DA3E-4C1C-8813-96EA6097278D"), "Sprinting speed boost", 0.3F, AttributeModifier.Operation.MULTIPLY_TOTAL +- ); ++ private static final AttributeModifier SPEED_MODIFIER_SPRINTING = new AttributeModifier(UUID.fromString("662A6B8D-DA3E-4C1C-8813-96EA6097278D"), "Sprinting speed boost", 0.30000001192092896D, AttributeModifier.Operation.MULTIPLY_TOTAL); + public static final int HAND_SLOTS = 2; + public static final int ARMOR_SLOTS = 4; + public static final int EQUIPMENT_SLOT_OFFSET = 98; +@@ -134,38 +154,36 @@ + public static final int SWING_DURATION = 6; + public static final int PLAYER_HURT_EXPERIENCE_TIME = 100; + private static final int DAMAGE_SOURCE_TIMEOUT = 40; +- public static final double MIN_MOVEMENT_DISTANCE = 0.003; +- public static final double DEFAULT_BASE_GRAVITY = 0.08; ++ public static final double MIN_MOVEMENT_DISTANCE = 0.003D; ++ public static final double DEFAULT_BASE_GRAVITY = 0.08D; + public static final int DEATH_DURATION = 20; + private static final int WAIT_TICKS_BEFORE_ITEM_USE_EFFECTS = 7; + private static final int TICKS_PER_ELYTRA_FREE_FALL_EVENT = 10; + private static final int FREE_FALL_EVENTS_PER_ELYTRA_BREAK = 2; + public static final int USE_ITEM_INTERVAL = 4; + private static final float BASE_JUMP_POWER = 0.42F; +- private static final double MAX_LINE_OF_SIGHT_TEST_RANGE = 128.0; ++ private static final double MAX_LINE_OF_SIGHT_TEST_RANGE = 128.0D; + protected static final int LIVING_ENTITY_FLAG_IS_USING = 1; + protected static final int LIVING_ENTITY_FLAG_OFF_HAND = 2; + protected static final int LIVING_ENTITY_FLAG_SPIN_ATTACK = 4; + protected static final EntityDataAccessor DATA_LIVING_ENTITY_FLAGS = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.BYTE); +- private static final EntityDataAccessor DATA_HEALTH_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.FLOAT); ++ public static final EntityDataAccessor DATA_HEALTH_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.FLOAT); + private static final EntityDataAccessor DATA_EFFECT_COLOR_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_EFFECT_AMBIENCE_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.BOOLEAN); +- private static final EntityDataAccessor DATA_ARROW_COUNT_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.INT); ++ public static final EntityDataAccessor DATA_ARROW_COUNT_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_STINGER_COUNT_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.INT); +- private static final EntityDataAccessor> SLEEPING_POS_ID = SynchedEntityData.defineId( +- LivingEntity.class, EntityDataSerializers.OPTIONAL_BLOCK_POS +- ); ++ private static final EntityDataAccessor> SLEEPING_POS_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.OPTIONAL_BLOCK_POS); + protected static final float DEFAULT_EYE_HEIGHT = 1.74F; + protected static final EntityDimensions SLEEPING_DIMENSIONS = EntityDimensions.fixed(0.2F, 0.2F); + public static final float EXTRA_RENDER_CULLING_SIZE_WITH_BIG_HAT = 0.5F; + private final AttributeMap attributes; +- private final CombatTracker combatTracker = new CombatTracker(this); +- private final Map activeEffects = Maps.newHashMap(); +- private final NonNullList lastHandItemStacks = NonNullList.withSize(2, ItemStack.EMPTY); +- private final NonNullList lastArmorItemStacks = NonNullList.withSize(4, ItemStack.EMPTY); ++ public CombatTracker combatTracker = new CombatTracker(this); ++ public final Map activeEffects = Maps.newHashMap(); ++ private final NonNullList lastHandItemStacks; ++ private final NonNullList lastArmorItemStacks; + public boolean swinging; +- private boolean discardFriction = false; +- public InteractionHand swingingArm; ++ private boolean discardFriction; ++ public EnumHand swingingArm; + public int swingTime; + public int removeArrowTime; + public int removeStingerTime; +@@ -175,8 +193,8 @@ + public float oAttackAnim; + public float attackAnim; + protected int attackStrengthTicker; +- public final WalkAnimationState walkAnimation = new WalkAnimationState(); +- public final int invulnerableDuration = 20; ++ public final WalkAnimationState walkAnimation; ++ public int invulnerableDuration; + public final float timeOffs; + public final float rotA; + public float yBodyRot; +@@ -184,7 +202,7 @@ + public float yHeadRot; + public float yHeadRotO; + @Nullable +- protected Player lastHurtByPlayer; ++ public net.minecraft.world.entity.player.Player lastHurtByPlayer; + protected int lastHurtByPlayerTime; + protected boolean dead; + protected int noActionTime; +@@ -194,7 +212,7 @@ + protected float animStepO; + protected float rotOffs; + protected int deathScore; +- protected float lastHurt; ++ public float lastHurt; + protected boolean jumping; + public float xxa; + public float yya; +@@ -207,20 +225,20 @@ + protected double lerpXRot; + protected double lerpYHeadRot; + protected int lerpHeadSteps; +- private boolean effectsDirty = true; ++ public boolean effectsDirty; + @Nullable +- private LivingEntity lastHurtByMob; +- private int lastHurtByMobTimestamp; ++ public LivingEntity lastHurtByMob; ++ public int lastHurtByMobTimestamp; + private LivingEntity lastHurtMob; + private int lastHurtMobTimestamp; + private float speed; + private int noJumpDelay; + private float absorptionAmount; +- protected ItemStack useItem = ItemStack.EMPTY; ++ protected ItemStack useItem; + protected int useItemRemaining; + protected int fallFlyTicks; + private BlockPos lastPos; +- private Optional lastClimbablePos = Optional.empty(); ++ private Optional lastClimbablePos; + @Nullable + private DamageSource lastDamageSource; + private long lastDamageStamp; +@@ -229,20 +247,45 @@ + private float swimAmountO; + protected Brain brain; + private boolean skipDropExperience; ++ // CraftBukkit start ++ public int expToDrop; ++ public boolean forceDrops; ++ public ArrayList drops = new ArrayList(); ++ public final org.bukkit.craftbukkit.attribute.CraftAttributeMap craftAttributes; ++ public boolean collides = true; ++ public Set collidableExemptions = new HashSet<>(); ++ public boolean bukkitPickUpLoot; + ++ @Override ++ public float getBukkitYaw() { ++ return getYHeadRot(); ++ } ++ // CraftBukkit end ++ + protected LivingEntity(EntityType entityType, Level level) { + super(entityType, level); ++ this.lastHandItemStacks = NonNullList.withSize(2, ItemStack.EMPTY); ++ this.lastArmorItemStacks = NonNullList.withSize(4, ItemStack.EMPTY); ++ this.discardFriction = false; ++ this.walkAnimation = new WalkAnimationState(); ++ this.invulnerableDuration = 20; ++ this.effectsDirty = true; ++ this.useItem = ItemStack.EMPTY; ++ this.lastClimbablePos = Optional.empty(); + this.attributes = new AttributeMap(DefaultAttributes.getSupplier(entityType)); +- this.setHealth(this.getMaxHealth()); ++ this.craftAttributes = new CraftAttributeMap(attributes); // CraftBukkit ++ // CraftBukkit - setHealth(getMaxHealth()) inlined and simplified to skip the instanceof check for EntityPlayer, as getBukkitEntity() is not initialized in constructor ++ this.entityData.set(LivingEntity.DATA_HEALTH_ID, (float) this.getAttribute(Attributes.MAX_HEALTH).getValue()); + this.blocksBuilding = true; +- this.rotA = (float)((Math.random() + 1.0) * 0.01F); ++ this.rotA = (float) ((Math.random() + 1.0D) * 0.009999999776482582D); + this.reapplyPosition(); +- this.timeOffs = (float)Math.random() * 12398.0F; +- this.setYRot((float)(Math.random() * (float) (Math.PI * 2))); ++ this.timeOffs = (float) Math.random() * 12398.0F; ++ this.setYRot((float) (Math.random() * 6.2831854820251465D)); + this.yHeadRot = this.getYRot(); + this.setMaxUpStep(0.6F); +- NbtOps nbtOps = NbtOps.INSTANCE; +- this.brain = this.makeBrain(new Dynamic<>(nbtOps, nbtOps.createMap(ImmutableMap.of(nbtOps.createString("memories"), nbtOps.emptyMap())))); ++ NbtOps dynamicopsnbt = NbtOps.INSTANCE; ++ ++ this.brain = this.makeBrain(new Dynamic(dynamicopsnbt, (Tag) dynamicopsnbt.createMap((Map) ImmutableMap.of(dynamicopsnbt.createString("memories"), (Tag) dynamicopsnbt.emptyMap())))); + } + + public Brain getBrain() { +@@ -268,59 +311,63 @@ + + @Override + protected void defineSynchedData() { +- this.entityData.define(DATA_LIVING_ENTITY_FLAGS, (byte)0); +- this.entityData.define(DATA_EFFECT_COLOR_ID, 0); +- this.entityData.define(DATA_EFFECT_AMBIENCE_ID, false); +- this.entityData.define(DATA_ARROW_COUNT_ID, 0); +- this.entityData.define(DATA_STINGER_COUNT_ID, 0); +- this.entityData.define(DATA_HEALTH_ID, 1.0F); +- this.entityData.define(SLEEPING_POS_ID, Optional.empty()); ++ this.entityData.define(LivingEntity.DATA_LIVING_ENTITY_FLAGS, (byte) 0); ++ this.entityData.define(LivingEntity.DATA_EFFECT_COLOR_ID, 0); ++ this.entityData.define(LivingEntity.DATA_EFFECT_AMBIENCE_ID, false); ++ this.entityData.define(LivingEntity.DATA_ARROW_COUNT_ID, 0); ++ this.entityData.define(LivingEntity.DATA_STINGER_COUNT_ID, 0); ++ this.entityData.define(LivingEntity.DATA_HEALTH_ID, 1.0F); ++ this.entityData.define(LivingEntity.SLEEPING_POS_ID, Optional.empty()); + } + + public static AttributeSupplier.Builder createLivingAttributes() { +- return AttributeSupplier.builder() +- .add(Attributes.MAX_HEALTH) +- .add(Attributes.KNOCKBACK_RESISTANCE) +- .add(Attributes.MOVEMENT_SPEED) +- .add(Attributes.ARMOR) +- .add(Attributes.ARMOR_TOUGHNESS) +- .add(Attributes.MAX_ABSORPTION); ++ return AttributeSupplier.builder().add(Attributes.MAX_HEALTH).add(Attributes.KNOCKBACK_RESISTANCE).add(Attributes.MOVEMENT_SPEED).add(Attributes.ARMOR).add(Attributes.ARMOR_TOUGHNESS).add(Attributes.MAX_ABSORPTION); + } + + @Override +- protected void checkFallDamage(double y, boolean onGround, BlockState state, BlockPos pos) { ++ protected void checkFallDamage(double y, boolean flag, IBlockData onGround, BlockPos state) { + if (!this.isInWater()) { + this.updateInWaterStateAndDoWaterCurrentPushing(); + } + +- if (!this.level().isClientSide && onGround && this.fallDistance > 0.0F) { ++ if (!this.level().isClientSide && flag && this.fallDistance > 0.0F) { + this.removeSoulSpeed(); + this.tryAddSoulSpeed(); + } + +- if (!this.level().isClientSide && this.fallDistance > 3.0F && onGround && !state.isAir()) { +- double x = this.getX(); +- double y1 = this.getY(); +- double z = this.getZ(); +- BlockPos blockPos = this.blockPosition(); +- if (pos.getX() != blockPos.getX() || pos.getZ() != blockPos.getZ()) { +- double d = x - (double)pos.getX() - 0.5; +- double d1 = z - (double)pos.getZ() - 0.5; +- double max = Math.max(Math.abs(d), Math.abs(d1)); +- x = (double)pos.getX() + 0.5 + d / max * 0.5; +- z = (double)pos.getZ() + 0.5 + d1 / max * 0.5; ++ if (!this.level().isClientSide && this.fallDistance > 3.0F && flag && !onGround.isAir()) { ++ double d1 = this.getX(); ++ double d2 = this.getY(); ++ double d3 = this.getZ(); ++ BlockPos blockposition1 = this.blockPosition(); ++ ++ if (state.getX() != blockposition1.getX() || state.getZ() != blockposition1.getZ()) { ++ double d4 = d1 - (double) state.getX() - 0.5D; ++ double d5 = d3 - (double) state.getZ() - 0.5D; ++ double d6 = Math.max(Math.abs(d4), Math.abs(d5)); ++ ++ d1 = (double) state.getX() + 0.5D + d4 / d6 * 0.5D; ++ d3 = (double) state.getZ() + 0.5D + d5 / d6 * 0.5D; + } + +- float f = (float)Mth.ceil(this.fallDistance - 3.0F); +- double min = Math.min((double)(0.2F + f / 15.0F), 2.5); +- int i = (int)(150.0 * min); +- ((ServerLevel)this.level()).sendParticles(new BlockParticleOption(ParticleTypes.BLOCK, state), x, y1, z, i, 0.0, 0.0, 0.0, 0.15F); ++ float f = (float) Mth.ceil(this.fallDistance - 3.0F); ++ double d7 = Math.min((double) (0.2F + f / 15.0F), 2.5D); ++ int i = (int) (150.0D * d7); ++ ++ // CraftBukkit start - visiblity api ++ if (this instanceof ServerPlayer) { ++ ((ServerLevel) this.level()).sendParticles((ServerPlayer) this, new BlockParticleOption(ParticleTypes.BLOCK, onGround), this.getX(), this.getY(), this.getZ(), i, 0.0D, 0.0D, 0.0D, 0.15000000596046448D, false); ++ } else { ++ ((ServerLevel) this.level()).sendParticles(new BlockParticleOption(ParticleTypes.BLOCK, onGround), d1, d2, d3, i, 0.0D, 0.0D, 0.0D, 0.15000000596046448D); ++ } ++ // CraftBukkit end + } + +- super.checkFallDamage(y, onGround, state, pos); +- if (onGround) { ++ super.checkFallDamage(y, flag, onGround, state); ++ if (flag) { + this.lastClimbablePos = Optional.empty(); + } ++ + } + + public final boolean canBreatheUnderwater() { +@@ -349,46 +396,39 @@ + } + + if (this.isAlive()) { +- boolean flag = this instanceof Player; ++ boolean flag = this instanceof net.minecraft.world.entity.player.Player; ++ + if (!this.level().isClientSide) { + if (this.isInWall()) { + this.hurt(this.damageSources().inWall(), 1.0F); + } else if (flag && !this.level().getWorldBorder().isWithinBounds(this.getBoundingBox())) { +- double d = this.level().getWorldBorder().getDistanceToBorder(this) + this.level().getWorldBorder().getDamageSafeZone(); +- if (d < 0.0) { +- double damagePerBlock = this.level().getWorldBorder().getDamagePerBlock(); +- if (damagePerBlock > 0.0) { +- this.hurt(this.damageSources().outOfBorder(), (float)Math.max(1, Mth.floor(-d * damagePerBlock))); ++ double d0 = this.level().getWorldBorder().getDistanceToBorder(this) + this.level().getWorldBorder().getDamageSafeZone(); ++ ++ if (d0 < 0.0D) { ++ double d1 = this.level().getWorldBorder().getDamagePerBlock(); ++ ++ if (d1 > 0.0D) { ++ this.hurt(this.damageSources().outOfBorder(), (float) Math.max(1, Mth.floor(-d0 * d1))); + } + } + } + } + +- if (this.isEyeInFluid(FluidTags.WATER) +- && !this.level().getBlockState(BlockPos.containing(this.getX(), this.getEyeY(), this.getZ())).is(Blocks.BUBBLE_COLUMN)) { +- boolean flag1 = !this.canBreatheUnderwater() +- && !MobEffectUtil.hasWaterBreathing(this) +- && (!flag || !((Player)this).getAbilities().invulnerable); ++ if (this.isEyeInFluid(FluidTags.WATER) && !this.level().getBlockState(BlockPos.containing(this.getX(), this.getEyeY(), this.getZ())).is(Blocks.BUBBLE_COLUMN)) { ++ boolean flag1 = !this.canBreatheUnderwater() && !MobEffectUtil.hasWaterBreathing(this) && (!flag || !((net.minecraft.world.entity.player.Player) this).getAbilities().invulnerable); ++ + if (flag1) { + this.setAirSupply(this.decreaseAirSupply(this.getAirSupply())); + if (this.getAirSupply() == -20) { + this.setAirSupply(0); +- Vec3 deltaMovement = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + +- for (int i = 0; i < 8; i++) { +- double d1 = this.random.nextDouble() - this.random.nextDouble(); ++ for (int i = 0; i < 8; ++i) { + double d2 = this.random.nextDouble() - this.random.nextDouble(); + double d3 = this.random.nextDouble() - this.random.nextDouble(); +- this.level() +- .addParticle( +- ParticleTypes.BUBBLE, +- this.getX() + d1, +- this.getY() + d2, +- this.getZ() + d3, +- deltaMovement.x, +- deltaMovement.y, +- deltaMovement.z +- ); ++ double d4 = this.random.nextDouble() - this.random.nextDouble(); ++ ++ this.level().addParticle(ParticleTypes.BUBBLE, this.getX() + d2, this.getY() + d3, this.getZ() + d4, vec3d.x, vec3d.y, vec3d.z); + } + + this.hurt(this.damageSources().drown(), 2.0F); +@@ -403,10 +443,11 @@ + } + + if (!this.level().isClientSide) { +- BlockPos blockPos = this.blockPosition(); +- if (!Objects.equal(this.lastPos, blockPos)) { +- this.lastPos = blockPos; +- this.onChangedBlock(blockPos); ++ BlockPos blockposition = this.blockPosition(); ++ ++ if (!Objects.equal(this.lastPos, blockposition)) { ++ this.lastPos = blockposition; ++ this.onChangedBlock(blockposition); + } + } + } +@@ -416,11 +457,11 @@ + } + + if (this.hurtTime > 0) { +- this.hurtTime--; ++ --this.hurtTime; + } + + if (this.invulnerableTime > 0 && !(this instanceof ServerPlayer)) { +- this.invulnerableTime--; ++ --this.invulnerableTime; + } + + if (this.isDeadOrDying() && this.level().shouldTickDeath(this)) { +@@ -428,7 +469,7 @@ + } + + if (this.lastHurtByPlayerTime > 0) { +- this.lastHurtByPlayerTime--; ++ --this.lastHurtByPlayerTime; + } else { + this.lastHurtByPlayer = null; + } +@@ -439,9 +480,9 @@ + + if (this.lastHurtByMob != null) { + if (!this.lastHurtByMob.isAlive()) { +- this.setLastHurtByMob(null); ++ this.setLastHurtByMob((LivingEntity) null); + } else if (this.tickCount - this.lastHurtByMobTimestamp > 100) { +- this.setLastHurtByMob(null); ++ this.setLastHurtByMob((LivingEntity) null); + } + } + +@@ -455,27 +496,15 @@ + } + + public boolean canSpawnSoulSpeedParticle() { +- return this.tickCount % 5 == 0 +- && this.getDeltaMovement().x != 0.0 +- && this.getDeltaMovement().z != 0.0 +- && !this.isSpectator() +- && EnchantmentHelper.hasSoulSpeed(this) +- && this.onSoulSpeedBlock(); ++ return this.tickCount % 5 == 0 && this.getDeltaMovement().x != 0.0D && this.getDeltaMovement().z != 0.0D && !this.isSpectator() && EnchantmentHelper.hasSoulSpeed(this) && this.onSoulSpeedBlock(); + } + + protected void spawnSoulSpeedParticle() { +- Vec3 deltaMovement = this.getDeltaMovement(); +- this.level() +- .addParticle( +- ParticleTypes.SOUL, +- this.getX() + (this.random.nextDouble() - 0.5) * (double)this.getBbWidth(), +- this.getY() + 0.1, +- this.getZ() + (this.random.nextDouble() - 0.5) * (double)this.getBbWidth(), +- deltaMovement.x * -0.2, +- 0.1, +- deltaMovement.z * -0.2 +- ); ++ Vec3 vec3d = this.getDeltaMovement(); ++ ++ this.level().addParticle(ParticleTypes.SOUL, this.getX() + (this.random.nextDouble() - 0.5D) * (double) this.getBbWidth(), this.getY() + 0.1D, this.getZ() + (this.random.nextDouble() - 0.5D) * (double) this.getBbWidth(), vec3d.x * -0.2D, 0.1D, vec3d.z * -0.2D); + float f = this.random.nextFloat() * 0.4F + this.random.nextFloat() > 0.9F ? 0.6F : 0.0F; ++ + this.playSound(SoundEvents.SOUL_ESCAPE, f, 0.6F + this.random.nextFloat() * 0.4F); + } + +@@ -488,74 +517,80 @@ + return this.onSoulSpeedBlock() && EnchantmentHelper.getEnchantmentLevel(Enchantments.SOUL_SPEED, this) > 0 ? 1.0F : super.getBlockSpeedFactor(); + } + +- protected boolean shouldRemoveSoulSpeed(BlockState state) { ++ protected boolean shouldRemoveSoulSpeed(IBlockData state) { + return !state.isAir() || this.isFallFlying(); + } + + protected void removeSoulSpeed() { +- AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED); +- if (attribute != null) { +- if (attribute.getModifier(SPEED_MODIFIER_SOUL_SPEED_UUID) != null) { +- attribute.removeModifier(SPEED_MODIFIER_SOUL_SPEED_UUID); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ ++ if (attributemodifiable != null) { ++ if (attributemodifiable.getModifier(LivingEntity.SPEED_MODIFIER_SOUL_SPEED_UUID) != null) { ++ attributemodifiable.removeModifier(LivingEntity.SPEED_MODIFIER_SOUL_SPEED_UUID); + } ++ + } + } + + protected void tryAddSoulSpeed() { + if (!this.getBlockStateOnLegacy().isAir()) { +- int enchantmentLevel = EnchantmentHelper.getEnchantmentLevel(Enchantments.SOUL_SPEED, this); +- if (enchantmentLevel > 0 && this.onSoulSpeedBlock()) { +- AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED); +- if (attribute == null) { ++ int i = EnchantmentHelper.getEnchantmentLevel(Enchantments.SOUL_SPEED, this); ++ ++ if (i > 0 && this.onSoulSpeedBlock()) { ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ ++ if (attributemodifiable == null) { + return; + } + +- attribute.addTransientModifier( +- new AttributeModifier( +- SPEED_MODIFIER_SOUL_SPEED_UUID, +- "Soul speed boost", +- (double)(0.03F * (1.0F + (float)enchantmentLevel * 0.35F)), +- AttributeModifier.Operation.ADDITION +- ) +- ); ++ attributemodifiable.addTransientModifier(new AttributeModifier(LivingEntity.SPEED_MODIFIER_SOUL_SPEED_UUID, "Soul speed boost", (double) (0.03F * (1.0F + (float) i * 0.35F)), AttributeModifier.Operation.ADDITION)); + if (this.getRandom().nextFloat() < 0.04F) { +- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.FEET); +- itemBySlot.hurtAndBreak(1, this, entity -> entity.broadcastBreakEvent(EquipmentSlot.FEET)); ++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.FEET); ++ ++ itemstack.hurtAndBreak(1, this, (entityliving) -> { ++ entityliving.broadcastBreakEvent(EquipmentSlot.FEET); ++ }); + } + } + } ++ + } + + protected void removeFrost() { +- AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED); +- if (attribute != null) { +- if (attribute.getModifier(SPEED_MODIFIER_POWDER_SNOW_UUID) != null) { +- attribute.removeModifier(SPEED_MODIFIER_POWDER_SNOW_UUID); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ ++ if (attributemodifiable != null) { ++ if (attributemodifiable.getModifier(LivingEntity.SPEED_MODIFIER_POWDER_SNOW_UUID) != null) { ++ attributemodifiable.removeModifier(LivingEntity.SPEED_MODIFIER_POWDER_SNOW_UUID); + } ++ + } + } + + protected void tryAddFrost() { + if (!this.getBlockStateOnLegacy().isAir()) { +- int ticksFrozen = this.getTicksFrozen(); +- if (ticksFrozen > 0) { +- AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED); +- if (attribute == null) { ++ int i = this.getTicksFrozen(); ++ ++ if (i > 0) { ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ ++ if (attributemodifiable == null) { + return; + } + + float f = -0.05F * this.getPercentFrozen(); +- attribute.addTransientModifier( +- new AttributeModifier(SPEED_MODIFIER_POWDER_SNOW_UUID, "Powder snow slow", (double)f, AttributeModifier.Operation.ADDITION) +- ); ++ ++ attributemodifiable.addTransientModifier(new AttributeModifier(LivingEntity.SPEED_MODIFIER_POWDER_SNOW_UUID, "Powder snow slow", (double) f, AttributeModifier.Operation.ADDITION)); + } + } ++ + } + + protected void onChangedBlock(BlockPos pos) { +- int enchantmentLevel = EnchantmentHelper.getEnchantmentLevel(Enchantments.FROST_WALKER, this); +- if (enchantmentLevel > 0) { +- FrostWalkerEnchantment.onEntityMoved(this, this.level(), pos, enchantmentLevel); ++ int i = EnchantmentHelper.getEnchantmentLevel(Enchantments.FROST_WALKER, this); ++ ++ if (i > 0) { ++ FrostWalkerEnchantment.onEntityMoved(this, this.level(), pos, i); + } + + if (this.shouldRemoveSoulSpeed(this.getBlockStateOnLegacy())) { +@@ -578,11 +613,12 @@ + } + + protected void tickDeath() { +- this.deathTime++; ++ ++this.deathTime; + if (this.deathTime >= 20 && !this.level().isClientSide() && !this.isRemoved()) { +- this.level().broadcastEntityEvent(this, (byte)60); ++ this.level().broadcastEntityEvent(this, (byte) 60); + this.remove(Entity.RemovalReason.KILLED); + } ++ + } + + public boolean shouldDropExperience() { +@@ -594,8 +630,9 @@ + } + + protected int decreaseAirSupply(int currentAir) { +- int respiration = EnchantmentHelper.getRespiration(this); +- return respiration > 0 && this.random.nextInt(respiration + 1) > 0 ? currentAir : currentAir - 1; ++ int j = EnchantmentHelper.getRespiration(this); ++ ++ return j > 0 && this.random.nextInt(j + 1) > 0 ? currentAir : currentAir - 1; + } + + protected int increaseAirSupply(int currentAir) { +@@ -628,7 +665,7 @@ + return this.lastHurtByMobTimestamp; + } + +- public void setLastHurtByPlayer(@Nullable Player player) { ++ public void setLastHurtByPlayer(@Nullable net.minecraft.world.entity.player.Player player) { + this.lastHurtByPlayer = player; + this.lastHurtByPlayerTime = this.tickCount; + } +@@ -649,7 +686,7 @@ + + public void setLastHurtMob(Entity entity) { + if (entity instanceof LivingEntity) { +- this.lastHurtMob = (LivingEntity)entity; ++ this.lastHurtMob = (LivingEntity) entity; + } else { + this.lastHurtMob = null; + } +@@ -678,18 +715,27 @@ + } + + public void onEquipItem(EquipmentSlot slot, ItemStack oldItem, ItemStack newItem) { +- boolean flag = newItem.isEmpty() && oldItem.isEmpty(); +- if (!flag && !ItemStack.isSameItemSameTags(oldItem, newItem) && !this.firstTick) { +- Equipable equipable = Equipable.get(newItem); ++ // CraftBukkit start ++ onEquipItem(slot, oldItem, newItem, false); ++ } ++ ++ public void onEquipItem(EquipmentSlot enumitemslot, ItemStack itemstack, ItemStack itemstack1, boolean silent) { ++ // CraftBukkit end ++ boolean flag = itemstack1.isEmpty() && itemstack.isEmpty(); ++ ++ if (!flag && !ItemStack.isSameItemSameTags(itemstack, itemstack1) && !this.firstTick) { ++ Equipable equipable = Equipable.get(itemstack1); ++ + if (!this.level().isClientSide() && !this.isSpectator()) { +- if (!this.isSilent() && equipable != null && equipable.getEquipmentSlot() == slot) { +- this.level().playSound(null, this.getX(), this.getY(), this.getZ(), equipable.getEquipSound(), this.getSoundSource(), 1.0F, 1.0F); ++ if (!this.isSilent() && equipable != null && equipable.getEquipmentSlot() == enumitemslot && !silent) { // CraftBukkit ++ this.level().playSound((net.minecraft.world.entity.player.Player) null, this.getX(), this.getY(), this.getZ(), equipable.getEquipSound(), this.getSoundSource(), 1.0F, 1.0F); + } + +- if (this.doesEmitEquipEvent(slot)) { ++ if (this.doesEmitEquipEvent(enumitemslot)) { + this.gameEvent(equipable != null ? GameEvent.EQUIP : GameEvent.UNEQUIP); + } + } ++ + } + } + +@@ -702,29 +748,37 @@ + @Override + public void addAdditionalSaveData(CompoundTag compound) { + compound.putFloat("Health", this.getHealth()); +- compound.putShort("HurtTime", (short)this.hurtTime); ++ compound.putShort("HurtTime", (short) this.hurtTime); + compound.putInt("HurtByTimestamp", this.lastHurtByMobTimestamp); +- compound.putShort("DeathTime", (short)this.deathTime); ++ compound.putShort("DeathTime", (short) this.deathTime); + compound.putFloat("AbsorptionAmount", this.getAbsorptionAmount()); + compound.put("Attributes", this.getAttributes().save()); + if (!this.activeEffects.isEmpty()) { +- ListTag list = new ListTag(); ++ ListTag nbttaglist = new ListTag(); ++ Iterator iterator = this.activeEffects.values().iterator(); + +- for (MobEffectInstance mobEffectInstance : this.activeEffects.values()) { +- list.add(mobEffectInstance.save(new CompoundTag())); ++ while (iterator.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); ++ ++ nbttaglist.add(mobeffect.save(new CompoundTag())); + } + +- compound.put("active_effects", list); ++ compound.put("active_effects", nbttaglist); + } + + compound.putBoolean("FallFlying", this.isFallFlying()); +- this.getSleepingPos().ifPresent(pos -> { +- compound.putInt("SleepingX", pos.getX()); +- compound.putInt("SleepingY", pos.getY()); +- compound.putInt("SleepingZ", pos.getZ()); ++ this.getSleepingPos().ifPresent((blockposition) -> { ++ compound.putInt("SleepingX", blockposition.getX()); ++ compound.putInt("SleepingY", blockposition.getY()); ++ compound.putInt("SleepingZ", blockposition.getZ()); + }); +- DataResult dataResult = this.brain.serializeStart(NbtOps.INSTANCE); +- dataResult.resultOrPartial(LOGGER::error).ifPresent(nbt -> compound.put("Brain", nbt)); ++ DataResult dataresult = this.brain.serializeStart(NbtOps.INSTANCE); ++ Logger logger = LivingEntity.LOGGER; ++ ++ java.util.Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("Brain", nbtbase); ++ }); + } + + @Override +@@ -735,17 +789,29 @@ + } + + if (compound.contains("active_effects", 9)) { +- ListTag list = compound.getList("active_effects", 10); ++ ListTag nbttaglist = compound.getList("active_effects", 10); + +- for (int i = 0; i < list.size(); i++) { +- CompoundTag compound1 = list.getCompound(i); +- MobEffectInstance mobEffectInstance = MobEffectInstance.load(compound1); +- if (mobEffectInstance != null) { +- this.activeEffects.put(mobEffectInstance.getEffect(), mobEffectInstance); ++ for (int i = 0; i < nbttaglist.size(); ++i) { ++ CompoundTag nbttagcompound1 = nbttaglist.getCompound(i); ++ MobEffectInstance mobeffect = MobEffectInstance.load(nbttagcompound1); ++ ++ if (mobeffect != null) { ++ this.activeEffects.put(mobeffect.getEffect(), mobeffect); + } + } + } + ++ // CraftBukkit start ++ if (compound.contains("Bukkit.MaxHealth")) { ++ Tag nbtbase = compound.get("Bukkit.MaxHealth"); ++ if (nbtbase.getId() == 5) { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(((FloatTag) nbtbase).getAsDouble()); ++ } else if (nbtbase.getId() == 3) { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(((IntTag) nbtbase).getAsDouble()); ++ } ++ } ++ // CraftBukkit end ++ + if (compound.contains("Health", 99)) { + this.setHealth(compound.getFloat("Health")); + } +@@ -754,11 +820,12 @@ + this.deathTime = compound.getShort("DeathTime"); + this.lastHurtByMobTimestamp = compound.getInt("HurtByTimestamp"); + if (compound.contains("Team", 8)) { +- String string = compound.getString("Team"); +- PlayerTeam playerTeam = this.level().getScoreboard().getPlayerTeam(string); +- boolean flag = playerTeam != null && this.level().getScoreboard().addPlayerToTeam(this.getStringUUID(), playerTeam); ++ String s = compound.getString("Team"); ++ PlayerTeam scoreboardteam = this.level().getScoreboard().getPlayerTeam(s); ++ boolean flag = scoreboardteam != null && this.level().getScoreboard().addPlayerToTeam(this.getStringUUID(), scoreboardteam); ++ + if (!flag) { +- LOGGER.warn("Unable to add mob to team \"{}\" (that team probably doesn't exist)", string); ++ LivingEntity.LOGGER.warn("Unable to add mob to team \"{}\" (that team probably doesn't exist)", s); + } + } + +@@ -767,37 +834,83 @@ + } + + if (compound.contains("SleepingX", 99) && compound.contains("SleepingY", 99) && compound.contains("SleepingZ", 99)) { +- BlockPos blockPos = new BlockPos(compound.getInt("SleepingX"), compound.getInt("SleepingY"), compound.getInt("SleepingZ")); +- this.setSleepingPos(blockPos); +- this.entityData.set(DATA_POSE, Pose.SLEEPING); ++ BlockPos blockposition = new BlockPos(compound.getInt("SleepingX"), compound.getInt("SleepingY"), compound.getInt("SleepingZ")); ++ ++ this.setSleepingPos(blockposition); ++ this.entityData.set(LivingEntity.DATA_POSE, EntityPose.SLEEPING); + if (!this.firstTick) { +- this.setPosToBed(blockPos); ++ this.setPosToBed(blockposition); + } + } + + if (compound.contains("Brain", 10)) { +- this.brain = this.makeBrain(new Dynamic<>(NbtOps.INSTANCE, compound.get("Brain"))); ++ this.brain = this.makeBrain(new Dynamic(NbtOps.INSTANCE, compound.get("Brain"))); + } ++ + } + ++ // CraftBukkit start ++ private boolean isTickingEffects = false; ++ private List effectsToProcess = Lists.newArrayList(); ++ ++ private static class ProcessableEffect { ++ ++ private MobEffect type; ++ private MobEffectInstance effect; ++ private final EntityPotionEffectEvent.Cause cause; ++ ++ private ProcessableEffect(MobEffectInstance effect, EntityPotionEffectEvent.Cause cause) { ++ this.effect = effect; ++ this.cause = cause; ++ } ++ ++ private ProcessableEffect(MobEffect type, EntityPotionEffectEvent.Cause cause) { ++ this.type = type; ++ this.cause = cause; ++ } ++ } ++ // CraftBukkit end ++ + protected void tickEffects() { +- Iterator iterator = this.activeEffects.keySet().iterator(); ++ Iterator iterator = this.activeEffects.keySet().iterator(); + ++ isTickingEffects = true; // CraftBukkit + try { + while (iterator.hasNext()) { +- MobEffect mobEffect = iterator.next(); +- MobEffectInstance mobEffectInstance = this.activeEffects.get(mobEffect); +- if (!mobEffectInstance.tick(this, () -> this.onEffectUpdated(mobEffectInstance, true, null))) { ++ MobEffect mobeffectlist = (MobEffect) iterator.next(); ++ MobEffectInstance mobeffect = (MobEffectInstance) this.activeEffects.get(mobeffectlist); ++ ++ if (!mobeffect.tick(this, () -> { ++ this.onEffectUpdated(mobeffect, true, (Entity) null); ++ })) { + if (!this.level().isClientSide) { ++ // CraftBukkit start ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, mobeffect, null, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.EXPIRATION); ++ if (event.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end + iterator.remove(); +- this.onEffectRemoved(mobEffectInstance); ++ this.onEffectRemoved(mobeffect); + } +- } else if (mobEffectInstance.getDuration() % 600 == 0) { +- this.onEffectUpdated(mobEffectInstance, false, null); ++ } else if (mobeffect.getDuration() % 600 == 0) { ++ this.onEffectUpdated(mobeffect, false, (Entity) null); + } + } +- } catch (ConcurrentModificationException var11) { ++ } catch (ConcurrentModificationException concurrentmodificationexception) { ++ ; + } ++ // CraftBukkit start ++ isTickingEffects = false; ++ for (ProcessableEffect e : effectsToProcess) { ++ if (e.effect != null) { ++ addEffect(e.effect, e.cause); ++ } else { ++ removeEffect(e.type, e.cause); ++ } ++ } ++ effectsToProcess.clear(); ++ // CraftBukkit end + + if (this.effectsDirty) { + if (!this.level().isClientSide) { +@@ -808,10 +921,12 @@ + this.effectsDirty = false; + } + +- int i = this.entityData.get(DATA_EFFECT_COLOR_ID); +- boolean flag = this.entityData.get(DATA_EFFECT_AMBIENCE_ID); ++ int i = (Integer) this.entityData.get(LivingEntity.DATA_EFFECT_COLOR_ID); ++ boolean flag = (Boolean) this.entityData.get(LivingEntity.DATA_EFFECT_AMBIENCE_ID); ++ + if (i > 0) { + boolean flag1; ++ + if (this.isInvisible()) { + flag1 = this.random.nextInt(15) == 0; + } else { +@@ -823,21 +938,14 @@ + } + + if (flag1 && i > 0) { +- double d = (double)(i >> 16 & 0xFF) / 255.0; +- double d1 = (double)(i >> 8 & 0xFF) / 255.0; +- double d2 = (double)(i >> 0 & 0xFF) / 255.0; +- this.level() +- .addParticle( +- flag ? ParticleTypes.AMBIENT_ENTITY_EFFECT : ParticleTypes.ENTITY_EFFECT, +- this.getRandomX(0.5), +- this.getRandomY(), +- this.getRandomZ(0.5), +- d, +- d1, +- d2 +- ); ++ double d0 = (double) (i >> 16 & 255) / 255.0D; ++ double d1 = (double) (i >> 8 & 255) / 255.0D; ++ double d2 = (double) (i >> 0 & 255) / 255.0D; ++ ++ this.level().addParticle(flag ? ParticleTypes.AMBIENT_ENTITY_EFFECT : ParticleTypes.ENTITY_EFFECT, this.getRandomX(0.5D), this.getRandomY(), this.getRandomZ(0.5D), d0, d1, d2); + } + } ++ + } + + protected void updateInvisibilityStatus() { +@@ -846,51 +954,54 @@ + this.setInvisible(false); + } else { + Collection collection = this.activeEffects.values(); +- this.entityData.set(DATA_EFFECT_AMBIENCE_ID, areAllEffectsAmbient(collection)); +- this.entityData.set(DATA_EFFECT_COLOR_ID, PotionUtils.getColor(collection)); ++ ++ this.entityData.set(LivingEntity.DATA_EFFECT_AMBIENCE_ID, areAllEffectsAmbient(collection)); ++ this.entityData.set(LivingEntity.DATA_EFFECT_COLOR_ID, PotionUtils.getColor(collection)); + this.setInvisible(this.hasEffect(MobEffects.INVISIBILITY)); + } ++ + } + + private void updateGlowingStatus() { +- boolean isCurrentlyGlowing = this.isCurrentlyGlowing(); +- if (this.getSharedFlag(6) != isCurrentlyGlowing) { +- this.setSharedFlag(6, isCurrentlyGlowing); ++ boolean flag = this.isCurrentlyGlowing(); ++ ++ if (this.getSharedFlag(6) != flag) { ++ this.setSharedFlag(6, flag); + } ++ + } + + public double getVisibilityPercent(@Nullable Entity lookingEntity) { +- double d = 1.0; ++ double d0 = 1.0D; ++ + if (this.isDiscrete()) { +- d *= 0.8; ++ d0 *= 0.8D; + } + + if (this.isInvisible()) { +- float armorCoverPercentage = this.getArmorCoverPercentage(); +- if (armorCoverPercentage < 0.1F) { +- armorCoverPercentage = 0.1F; ++ float f = this.getArmorCoverPercentage(); ++ ++ if (f < 0.1F) { ++ f = 0.1F; + } + +- d *= 0.7 * (double)armorCoverPercentage; ++ d0 *= 0.7D * (double) f; + } + + if (lookingEntity != null) { +- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.HEAD); +- EntityType type = lookingEntity.getType(); +- if (type == EntityType.SKELETON && itemBySlot.is(Items.SKELETON_SKULL) +- || type == EntityType.ZOMBIE && itemBySlot.is(Items.ZOMBIE_HEAD) +- || type == EntityType.PIGLIN && itemBySlot.is(Items.PIGLIN_HEAD) +- || type == EntityType.PIGLIN_BRUTE && itemBySlot.is(Items.PIGLIN_HEAD) +- || type == EntityType.CREEPER && itemBySlot.is(Items.CREEPER_HEAD)) { +- d *= 0.5; ++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); ++ EntityType entitytypes = lookingEntity.getType(); ++ ++ if (entitytypes == EntityType.SKELETON && itemstack.is(Items.SKELETON_SKULL) || entitytypes == EntityType.ZOMBIE && itemstack.is(Items.ZOMBIE_HEAD) || entitytypes == EntityType.PIGLIN && itemstack.is(Items.PIGLIN_HEAD) || entitytypes == EntityType.PIGLIN_BRUTE && itemstack.is(Items.PIGLIN_HEAD) || entitytypes == EntityType.CREEPER && itemstack.is(Items.CREEPER_HEAD)) { ++ d0 *= 0.5D; + } + } + +- return d; ++ return d0; + } + + public boolean canAttack(LivingEntity target) { +- return (!(target instanceof Player) || this.level().getDifficulty() != Difficulty.PEACEFUL) && target.canBeSeenAsEnemy(); ++ return target instanceof net.minecraft.world.entity.player.Player && this.level().getDifficulty() == Difficulty.PEACEFUL ? false : target.canBeSeenAsEnemy(); + } + + public boolean canAttack(LivingEntity livingentity, TargetingConditions condition) { +@@ -906,29 +1017,49 @@ + } + + public static boolean areAllEffectsAmbient(Collection potionEffects) { +- for (MobEffectInstance mobEffectInstance : potionEffects) { +- if (mobEffectInstance.isVisible() && !mobEffectInstance.isAmbient()) { +- return false; ++ Iterator iterator = potionEffects.iterator(); ++ ++ MobEffectInstance mobeffect; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return true; + } +- } + +- return true; ++ mobeffect = (MobEffectInstance) iterator.next(); ++ } while (!mobeffect.isVisible() || mobeffect.isAmbient()); ++ ++ return false; + } + + protected void removeEffectParticles() { +- this.entityData.set(DATA_EFFECT_AMBIENCE_ID, false); +- this.entityData.set(DATA_EFFECT_COLOR_ID, 0); ++ this.entityData.set(LivingEntity.DATA_EFFECT_AMBIENCE_ID, false); ++ this.entityData.set(LivingEntity.DATA_EFFECT_COLOR_ID, 0); + } + ++ // CraftBukkit start + public boolean removeAllEffects() { ++ return removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean removeAllEffects(EntityPotionEffectEvent.Cause cause) { ++ // CraftBukkit end + if (this.level().isClientSide) { + return false; + } else { + Iterator iterator = this.activeEffects.values().iterator(); + + boolean flag; ++ + for (flag = false; iterator.hasNext(); flag = true) { +- this.onEffectRemoved(iterator.next()); ++ // CraftBukkit start ++ MobEffectInstance effect = (MobEffectInstance) iterator.next(); ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, effect, null, cause, EntityPotionEffectEvent.Action.CLEARED); ++ if (event.isCancelled()) { ++ continue; ++ } ++ this.onEffectRemoved(effect); ++ // CraftBukkit end + iterator.remove(); + } + +@@ -950,37 +1081,69 @@ + + @Nullable + public MobEffectInstance getEffect(MobEffect effect) { +- return this.activeEffects.get(effect); ++ return (MobEffectInstance) this.activeEffects.get(effect); + } + + public final boolean addEffect(MobEffectInstance effectInstance) { +- return this.addEffect(effectInstance, null); ++ return this.addEffect(effectInstance, (Entity) null); + } + ++ // CraftBukkit start ++ public boolean addEffect(MobEffectInstance mobeffect, EntityPotionEffectEvent.Cause cause) { ++ return this.addEffect(mobeffect, (Entity) null, cause); ++ } ++ + public boolean addEffect(MobEffectInstance effectInstance, @Nullable Entity entity) { +- if (!this.canBeAffected(effectInstance)) { ++ return this.addEffect(effectInstance, entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean addEffect(MobEffectInstance mobeffect, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause) { ++ if (isTickingEffects) { ++ effectsToProcess.add(new ProcessableEffect(mobeffect, cause)); ++ return true; ++ } ++ // CraftBukkit end ++ ++ if (!this.canBeAffected(mobeffect)) { + return false; + } else { +- MobEffectInstance mobEffectInstance = this.activeEffects.get(effectInstance.getEffect()); ++ MobEffectInstance mobeffect1 = (MobEffectInstance) this.activeEffects.get(mobeffect.getEffect()); + boolean flag = false; +- if (mobEffectInstance == null) { +- this.activeEffects.put(effectInstance.getEffect(), effectInstance); +- this.onEffectAdded(effectInstance, entity); ++ ++ // CraftBukkit start ++ boolean override = false; ++ if (mobeffect1 != null) { ++ override = new MobEffectInstance(mobeffect1).update(mobeffect); ++ } ++ ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, mobeffect1, mobeffect, cause, override); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ ++ if (mobeffect1 == null) { ++ this.activeEffects.put(mobeffect.getEffect(), mobeffect); ++ this.onEffectAdded(mobeffect, entity); + flag = true; +- } else if (mobEffectInstance.update(effectInstance)) { +- this.onEffectUpdated(mobEffectInstance, true, entity); ++ // CraftBukkit start ++ } else if (event.isOverride()) { ++ mobeffect1.update(mobeffect); ++ this.onEffectUpdated(mobeffect1, true, entity); ++ // CraftBukkit end + flag = true; + } + +- effectInstance.onEffectStarted(this); ++ mobeffect.onEffectStarted(this); + return flag; + } + } + + public boolean canBeAffected(MobEffectInstance effectInstance) { +- if (this.getMobType() == MobType.UNDEAD) { +- MobEffect effect = effectInstance.getEffect(); +- if (effect == MobEffects.REGENERATION || effect == MobEffects.POISON) { ++ if (this.getMobType() == EnumMonsterType.UNDEAD) { ++ MobEffect mobeffectlist = effectInstance.getEffect(); ++ ++ if (mobeffectlist == MobEffects.REGENERATION || mobeffectlist == MobEffects.POISON) { + return false; + } + } +@@ -990,28 +1153,57 @@ + + public void forceAddEffect(MobEffectInstance instance, @Nullable Entity entity) { + if (this.canBeAffected(instance)) { +- MobEffectInstance mobEffectInstance = this.activeEffects.put(instance.getEffect(), instance); +- if (mobEffectInstance == null) { ++ MobEffectInstance mobeffect1 = (MobEffectInstance) this.activeEffects.put(instance.getEffect(), instance); ++ ++ if (mobeffect1 == null) { + this.onEffectAdded(instance, entity); + } else { + this.onEffectUpdated(instance, true, entity); + } ++ + } + } + + public boolean isInvertedHealAndHarm() { +- return this.getMobType() == MobType.UNDEAD; ++ return this.getMobType() == EnumMonsterType.UNDEAD; + } + ++ // CraftBukkit start + @Nullable + public MobEffectInstance removeEffectNoUpdate(@Nullable MobEffect effect) { +- return this.activeEffects.remove(effect); ++ return c(effect, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); + } + ++ @Nullable ++ public MobEffectInstance c(@Nullable MobEffect mobeffectlist, EntityPotionEffectEvent.Cause cause) { ++ if (isTickingEffects) { ++ effectsToProcess.add(new ProcessableEffect(mobeffectlist, cause)); ++ return null; ++ } ++ ++ MobEffectInstance effect = this.activeEffects.get(mobeffectlist); ++ if (effect == null) { ++ return null; ++ } ++ ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, effect, null, cause); ++ if (event.isCancelled()) { ++ return null; ++ } ++ ++ return (MobEffectInstance) this.activeEffects.remove(mobeffectlist); ++ } ++ + public boolean removeEffect(MobEffect effect) { +- MobEffectInstance mobEffectInstance = this.removeEffectNoUpdate(effect); +- if (mobEffectInstance != null) { +- this.onEffectRemoved(mobEffectInstance); ++ return removeEffect(effect, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean removeEffect(MobEffect mobeffectlist, EntityPotionEffectEvent.Cause cause) { ++ MobEffectInstance mobeffect = this.c(mobeffectlist, cause); ++ // CraftBukkit end ++ ++ if (mobeffect != null) { ++ this.onEffectRemoved(mobeffect); + return true; + } else { + return false; +@@ -1024,28 +1216,38 @@ + effectInstance.getEffect().addAttributeModifiers(this.getAttributes(), effectInstance.getAmplifier()); + this.sendEffectToPassengers(effectInstance); + } ++ + } + + public void sendEffectToPassengers(MobEffectInstance effectInstance) { +- for (Entity entity : this.getPassengers()) { +- if (entity instanceof ServerPlayer serverPlayer) { +- serverPlayer.connection.send(new ClientboundUpdateMobEffectPacket(this.getId(), effectInstance)); ++ Iterator iterator = this.getPassengers().iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ ++ if (entity instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entity; ++ ++ entityplayer.connection.send(new ClientboundUpdateMobEffectPacket(this.getId(), effectInstance)); + } + } ++ + } + + protected void onEffectUpdated(MobEffectInstance effectInstance, boolean forced, @Nullable Entity entity) { + this.effectsDirty = true; + if (forced && !this.level().isClientSide) { +- MobEffect effect = effectInstance.getEffect(); +- effect.removeAttributeModifiers(this.getAttributes()); +- effect.addAttributeModifiers(this.getAttributes(), effectInstance.getAmplifier()); ++ MobEffect mobeffectlist = effectInstance.getEffect(); ++ ++ mobeffectlist.removeAttributeModifiers(this.getAttributes()); ++ mobeffectlist.addAttributeModifiers(this.getAttributes(), effectInstance.getAmplifier()); + this.refreshDirtyAttributes(); + } + + if (!this.level().isClientSide) { + this.sendEffectToPassengers(effectInstance); + } ++ + } + + protected void onEffectRemoved(MobEffectInstance effectInstance) { +@@ -1053,48 +1255,99 @@ + if (!this.level().isClientSide) { + effectInstance.getEffect().removeAttributeModifiers(this.getAttributes()); + this.refreshDirtyAttributes(); ++ Iterator iterator = this.getPassengers().iterator(); + +- for (Entity entity : this.getPassengers()) { +- if (entity instanceof ServerPlayer serverPlayer) { +- serverPlayer.connection.send(new ClientboundRemoveMobEffectPacket(this.getId(), effectInstance.getEffect())); ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ ++ if (entity instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entity; ++ ++ entityplayer.connection.send(new ClientboundRemoveMobEffectPacket(this.getId(), effectInstance.getEffect())); + } + } + } ++ + } + + private void refreshDirtyAttributes() { +- for (AttributeInstance attributeInstance : this.getAttributes().getDirtyAttributes()) { +- this.onAttributeUpdated(attributeInstance.getAttribute()); ++ Iterator iterator = this.getAttributes().getDirtyAttributes().iterator(); ++ ++ while (iterator.hasNext()) { ++ AttributeInstance attributemodifiable = (AttributeInstance) iterator.next(); ++ ++ this.onAttributeUpdated(attributemodifiable.getAttribute()); + } ++ + } + +- private void onAttributeUpdated(Attribute attribute) { +- if (attribute == Attributes.MAX_HEALTH) { +- float maxHealth = this.getMaxHealth(); +- if (this.getHealth() > maxHealth) { +- this.setHealth(maxHealth); ++ private void onAttributeUpdated(Attribute attributebase) { ++ float f; ++ ++ if (attributebase == Attributes.MAX_HEALTH) { ++ f = this.getMaxHealth(); ++ if (this.getHealth() > f) { ++ this.setHealth(f); + } +- } else if (attribute == Attributes.MAX_ABSORPTION) { +- float maxHealth = this.getMaxAbsorption(); +- if (this.getAbsorptionAmount() > maxHealth) { +- this.setAbsorptionAmount(maxHealth); ++ } else if (attributebase == Attributes.MAX_ABSORPTION) { ++ f = this.getMaxAbsorption(); ++ if (this.getAbsorptionAmount() > f) { ++ this.setAbsorptionAmount(f); + } + } ++ + } + ++ // CraftBukkit start - Delegate so we can handle providing a reason for health being regained + public void heal(float healAmount) { +- float health = this.getHealth(); +- if (health > 0.0F) { +- this.setHealth(health + healAmount); ++ heal(healAmount, EntityRegainHealthEvent.RegainReason.CUSTOM); ++ } ++ ++ public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason) { ++ float f1 = this.getHealth(); ++ ++ if (f1 > 0.0F) { ++ EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason); ++ // Suppress during worldgen ++ if (this.valid) { ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (!event.isCancelled()) { ++ this.setHealth((float) (this.getHealth() + event.getAmount())); ++ } ++ // CraftBukkit end + } ++ + } + + public float getHealth() { +- return this.entityData.get(DATA_HEALTH_ID); ++ // CraftBukkit start - Use unscaled health ++ if (this instanceof ServerPlayer) { ++ return (float) ((ServerPlayer) this).getBukkitEntity().getHealth(); ++ } ++ // CraftBukkit end ++ return (Float) this.entityData.get(LivingEntity.DATA_HEALTH_ID); + } + + public void setHealth(float health) { +- this.entityData.set(DATA_HEALTH_ID, Mth.clamp(health, 0.0F, this.getMaxHealth())); ++ // CraftBukkit start - Handle scaled health ++ if (this instanceof ServerPlayer) { ++ org.bukkit.craftbukkit.entity.CraftPlayer player = ((ServerPlayer) this).getBukkitEntity(); ++ // Squeeze ++ if (health < 0.0F) { ++ player.setRealHealth(0.0D); ++ } else if (health > player.getMaxHealth()) { ++ player.setRealHealth(player.getMaxHealth()); ++ } else { ++ player.setRealHealth(health); ++ } ++ ++ player.updateScaledHealth(false); ++ return; ++ } ++ // CraftBukkit end ++ this.entityData.set(LivingEntity.DATA_HEALTH_ID, Mth.clamp(health, 0.0F, this.getMaxHealth())); + } + + public boolean isDeadOrDying() { +@@ -1107,7 +1360,7 @@ + return false; + } else if (this.level().isClientSide) { + return false; +- } else if (this.isDeadOrDying()) { ++ } else if (this.isRemoved() || this.dead || this.getHealth() <= 0.0F) { // CraftBukkit - Don't allow entities that got set to dead/killed elsewhere to get damaged and die + return false; + } else if (source.is(DamageTypeTags.IS_FIRE) && this.hasEffect(MobEffects.FIRE_RESISTANCE)) { + return false; +@@ -1117,15 +1370,23 @@ + } + + this.noActionTime = 0; +- float f = amount; +- boolean flag = false; +- float f1 = 0.0F; +- if (amount > 0.0F && this.isDamageSourceBlocked(source)) { ++ float f1 = amount; ++ boolean flag = amount > 0.0F && this.isDamageSourceBlocked(source); // Copied from below ++ float f2 = 0.0F; ++ ++ // CraftBukkit - Moved into damageEntity0(DamageSource, float) ++ if (false && amount > 0.0F && this.isDamageSourceBlocked(source)) { + this.hurtCurrentlyUsedShield(amount); +- f1 = amount; ++ f2 = amount; + amount = 0.0F; +- if (!source.is(DamageTypeTags.IS_PROJECTILE) && source.getDirectEntity() instanceof LivingEntity livingEntity) { +- this.blockUsingShield(livingEntity); ++ if (!source.is(DamageTypeTags.IS_PROJECTILE)) { ++ Entity entity = source.getDirectEntity(); ++ ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ this.blockUsingShield(entityliving); ++ } + } + + flag = true; +@@ -1137,49 +1398,75 @@ + + this.walkAnimation.setSpeed(1.5F); + boolean flag1 = true; +- if ((float)this.invulnerableTime > 10.0F && !source.is(DamageTypeTags.BYPASSES_COOLDOWN)) { ++ ++ if ((float) this.invulnerableTime > (float) this.invulnerableDuration / 2.0F && !source.is(DamageTypeTags.BYPASSES_COOLDOWN)) { // CraftBukkit - restore use of maxNoDamageTicks + if (amount <= this.lastHurt) { + return false; + } + +- this.actuallyHurt(source, amount - this.lastHurt); ++ // CraftBukkit start ++ if (!this.damageEntity0(source, amount - this.lastHurt)) { ++ return false; ++ } ++ // CraftBukkit end + this.lastHurt = amount; + flag1 = false; + } else { ++ // CraftBukkit start ++ if (!this.damageEntity0(source, amount)) { ++ return false; ++ } + this.lastHurt = amount; +- this.invulnerableTime = 20; +- this.actuallyHurt(source, amount); ++ this.invulnerableTime = this.invulnerableDuration; // CraftBukkit - restore use of maxNoDamageTicks ++ // this.damageEntity0(damagesource, f); ++ // CraftBukkit end + this.hurtDuration = 10; + this.hurtTime = this.hurtDuration; + } + +- if (source.is(DamageTypeTags.DAMAGES_HELMET) && !this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { ++ // CraftBukkit - Moved into damageEntity0(DamageSource, float) ++ if (false && source.is(DamageTypeTags.DAMAGES_HELMET) && !this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { + this.hurtHelmet(source, amount); + amount *= 0.75F; + } + +- Entity entity = source.getEntity(); +- if (entity != null) { +- if (entity instanceof LivingEntity livingEntity1 && !source.is(DamageTypeTags.NO_ANGER)) { +- this.setLastHurtByMob(livingEntity1); ++ Entity entity1 = source.getEntity(); ++ ++ if (entity1 != null) { ++ if (entity1 instanceof LivingEntity) { ++ LivingEntity entityliving1 = (LivingEntity) entity1; ++ ++ if (!source.is(DamageTypeTags.NO_ANGER)) { ++ this.setLastHurtByMob(entityliving1); ++ } + } + +- if (entity instanceof Player player) { ++ if (entity1 instanceof net.minecraft.world.entity.player.Player) { ++ net.minecraft.world.entity.player.Player entityhuman = (net.minecraft.world.entity.player.Player) entity1; ++ + this.lastHurtByPlayerTime = 100; +- this.lastHurtByPlayer = player; +- } else if (entity instanceof Wolf wolf && wolf.isTame()) { +- this.lastHurtByPlayerTime = 100; +- if (wolf.getOwner() instanceof Player player1) { +- this.lastHurtByPlayer = player1; +- } else { +- this.lastHurtByPlayer = null; ++ this.lastHurtByPlayer = entityhuman; ++ } else if (entity1 instanceof Wolf) { ++ Wolf entitywolf = (Wolf) entity1; ++ ++ if (entitywolf.isTame()) { ++ this.lastHurtByPlayerTime = 100; ++ LivingEntity entityliving2 = entitywolf.getOwner(); ++ ++ if (entityliving2 instanceof net.minecraft.world.entity.player.Player) { ++ net.minecraft.world.entity.player.Player entityhuman1 = (net.minecraft.world.entity.player.Player) entityliving2; ++ ++ this.lastHurtByPlayer = entityhuman1; ++ } else { ++ this.lastHurtByPlayer = null; ++ } + } + } + } + + if (flag1) { + if (flag) { +- this.level().broadcastEntityEvent(this, (byte)29); ++ this.level().broadcastEntityEvent(this, (byte) 29); + } else { + this.level().broadcastDamageEvent(this, source); + } +@@ -1188,26 +1475,28 @@ + this.markHurt(); + } + +- if (entity != null && !source.is(DamageTypeTags.NO_KNOCKBACK)) { +- double d = entity.getX() - this.getX(); ++ if (entity1 != null && !source.is(DamageTypeTags.NO_KNOCKBACK)) { ++ double d0 = entity1.getX() - this.getX(); + + double d1; +- for (d1 = entity.getZ() - this.getZ(); d * d + d1 * d1 < 1.0E-4; d1 = (Math.random() - Math.random()) * 0.01) { +- d = (Math.random() - Math.random()) * 0.01; ++ ++ for (d1 = entity1.getZ() - this.getZ(); d0 * d0 + d1 * d1 < 1.0E-4D; d1 = (Math.random() - Math.random()) * 0.01D) { ++ d0 = (Math.random() - Math.random()) * 0.01D; + } + +- this.knockback(0.4F, d, d1); ++ this.knockback(0.4000000059604645D, d0, d1); + if (!flag) { +- this.indicateDamage(d, d1); ++ this.indicateDamage(d0, d1); + } + } + } + + if (this.isDeadOrDying()) { + if (!this.checkTotemDeathProtection(source)) { +- SoundEvent deathSound = this.getDeathSound(); +- if (flag1 && deathSound != null) { +- this.playSound(deathSound, this.getSoundVolume(), this.getVoicePitch()); ++ SoundEvent soundeffect = this.getDeathSound(); ++ ++ if (flag1 && soundeffect != null) { ++ this.playSound(soundeffect, this.getSoundVolume(), this.getVoicePitch()); + } + + this.die(source); +@@ -1217,20 +1506,21 @@ + } + + boolean flag2 = !flag || amount > 0.0F; ++ + if (flag2) { + this.lastDamageSource = source; + this.lastDamageStamp = this.level().getGameTime(); + } + + if (this instanceof ServerPlayer) { +- CriteriaTriggers.ENTITY_HURT_PLAYER.trigger((ServerPlayer)this, source, f, amount, flag); +- if (f1 > 0.0F && f1 < 3.4028235E37F) { +- ((ServerPlayer)this).awardStat(Stats.DAMAGE_BLOCKED_BY_SHIELD, Math.round(f1 * 10.0F)); ++ CriteriaTriggers.ENTITY_HURT_PLAYER.trigger((ServerPlayer) this, source, f1, amount, flag); ++ if (f2 > 0.0F && f2 < 3.4028235E37F) { ++ ((ServerPlayer) this).awardStat(Stats.DAMAGE_BLOCKED_BY_SHIELD, Math.round(f2 * 10.0F)); + } + } + +- if (entity instanceof ServerPlayer) { +- CriteriaTriggers.PLAYER_HURT_ENTITY.trigger((ServerPlayer)entity, this, source, f, amount, flag); ++ if (entity1 instanceof ServerPlayer) { ++ CriteriaTriggers.PLAYER_HURT_ENTITY.trigger((ServerPlayer) entity1, this, source, f1, amount, flag); + } + + return flag2; +@@ -1242,40 +1532,61 @@ + } + + protected void blockedByShield(LivingEntity defender) { +- defender.knockback(0.5, defender.getX() - this.getX(), defender.getZ() - this.getZ()); ++ defender.knockback(0.5D, defender.getX() - this.getX(), defender.getZ() - this.getZ()); + } + + private boolean checkTotemDeathProtection(DamageSource damageSource) { + if (damageSource.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { + return false; + } else { +- ItemStack itemStack = null; ++ ItemStack itemstack = null; ++ EnumHand[] aenumhand = EnumHand.values(); ++ int i = aenumhand.length; + +- for (InteractionHand interactionHand : InteractionHand.values()) { +- ItemStack itemInHand = this.getItemInHand(interactionHand); +- if (itemInHand.is(Items.TOTEM_OF_UNDYING)) { +- itemStack = itemInHand.copy(); +- itemInHand.shrink(1); ++ // CraftBukkit start ++ EnumHand hand = null; ++ ItemStack itemstack1 = ItemStack.EMPTY; ++ for (int j = 0; j < i; ++j) { ++ EnumHand enumhand = aenumhand[j]; ++ itemstack1 = this.getItemInHand(enumhand); ++ ++ if (itemstack1.is(Items.TOTEM_OF_UNDYING)) { ++ hand = enumhand; // CraftBukkit ++ itemstack = itemstack1.copy(); ++ // itemstack1.subtract(1); // CraftBukkit + break; + } + } + +- if (itemStack != null) { +- if (this instanceof ServerPlayer serverPlayer) { +- serverPlayer.awardStat(Stats.ITEM_USED.get(Items.TOTEM_OF_UNDYING)); +- CriteriaTriggers.USED_TOTEM.trigger(serverPlayer, itemStack); ++ org.bukkit.inventory.EquipmentSlot handSlot = (hand != null) ? org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand) : null; ++ EntityResurrectEvent event = new EntityResurrectEvent((org.bukkit.entity.LivingEntity) this.getBukkitEntity(), handSlot); ++ event.setCancelled(itemstack == null); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ if (!itemstack1.isEmpty()) { ++ itemstack1.shrink(1); ++ } ++ if (itemstack != null && this instanceof ServerPlayer) { ++ // CraftBukkit end ++ ServerPlayer entityplayer = (ServerPlayer) this; ++ ++ entityplayer.awardStat(Stats.ITEM_USED.get(Items.TOTEM_OF_UNDYING)); ++ CriteriaTriggers.USED_TOTEM.trigger(entityplayer, itemstack); + this.gameEvent(GameEvent.ITEM_INTERACT_FINISH); + } + + this.setHealth(1.0F); +- this.removeAllEffects(); +- this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 900, 1)); +- this.addEffect(new MobEffectInstance(MobEffects.ABSORPTION, 100, 1)); +- this.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 800, 0)); +- this.level().broadcastEntityEvent(this, (byte)35); ++ // CraftBukkit start ++ this.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 900, 1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ this.addEffect(new MobEffectInstance(MobEffects.ABSORPTION, 100, 1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ this.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 800, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ // CraftBukkit end ++ this.level().broadcastEntityEvent(this, (byte) 35); + } + +- return itemStack != null; ++ return !event.isCancelled(); + } + } + +@@ -1289,26 +1600,35 @@ + } + + protected void playHurtSound(DamageSource source) { +- SoundEvent hurtSound = this.getHurtSound(source); +- if (hurtSound != null) { +- this.playSound(hurtSound, this.getSoundVolume(), this.getVoicePitch()); ++ SoundEvent soundeffect = this.getHurtSound(source); ++ ++ if (soundeffect != null) { ++ this.playSound(soundeffect, this.getSoundVolume(), this.getVoicePitch()); + } ++ + } + + public boolean isDamageSourceBlocked(DamageSource damageSource) { +- Entity directEntity = damageSource.getDirectEntity(); ++ Entity entity = damageSource.getDirectEntity(); + boolean flag = false; +- if (directEntity instanceof AbstractArrow abstractArrow && abstractArrow.getPierceLevel() > 0) { +- flag = true; ++ ++ if (entity instanceof AbstractArrow) { ++ AbstractArrow entityarrow = (AbstractArrow) entity; ++ ++ if (entityarrow.getPierceLevel() > 0) { ++ flag = true; ++ } + } + + if (!damageSource.is(DamageTypeTags.BYPASSES_SHIELD) && this.isBlocking() && !flag) { +- Vec3 sourcePosition = damageSource.getSourcePosition(); +- if (sourcePosition != null) { +- Vec3 vec3 = this.calculateViewVector(0.0F, this.getYHeadRot()); +- Vec3 vec31 = sourcePosition.vectorTo(this.position()); +- vec31 = new Vec3(vec31.x, 0.0, vec31.z).normalize(); +- return vec31.dot(vec3) < 0.0; ++ Vec3 vec3d = damageSource.getSourcePosition(); ++ ++ if (vec3d != null) { ++ Vec3 vec3d1 = this.calculateViewVector(0.0F, this.getYHeadRot()); ++ Vec3 vec3d2 = vec3d.vectorTo(this.position()); ++ ++ vec3d2 = (new Vec3(vec3d2.x, 0.0D, vec3d2.z)).normalize(); ++ return vec3d2.dot(vec3d1) < 0.0D; + } + } + +@@ -1318,29 +1638,21 @@ + private void breakItem(ItemStack stack) { + if (!stack.isEmpty()) { + if (!this.isSilent()) { +- this.level() +- .playLocalSound( +- this.getX(), +- this.getY(), +- this.getZ(), +- SoundEvents.ITEM_BREAK, +- this.getSoundSource(), +- 0.8F, +- 0.8F + this.level().random.nextFloat() * 0.4F, +- false +- ); ++ this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.ITEM_BREAK, this.getSoundSource(), 0.8F, 0.8F + this.level().random.nextFloat() * 0.4F, false); + } + + this.spawnItemParticles(stack, 5); + } ++ + } + + public void die(DamageSource damageSource) { + if (!this.isRemoved() && !this.dead) { + Entity entity = damageSource.getEntity(); +- LivingEntity killCredit = this.getKillCredit(); +- if (this.deathScore >= 0 && killCredit != null) { +- killCredit.awardKillScore(this, this.deathScore, damageSource); ++ LivingEntity entityliving = this.getKillCredit(); ++ ++ if (this.deathScore >= 0 && entityliving != null) { ++ entityliving.awardKillScore(this, this.deathScore, damageSource); + } + + if (this.isSleeping()) { +@@ -1348,82 +1660,113 @@ + } + + if (!this.level().isClientSide && this.hasCustomName()) { +- LOGGER.info("Named entity {} died: {}", this, this.getCombatTracker().getDeathMessage().getString()); ++ LivingEntity.LOGGER.info("Named entity {} died: {}", this, this.getCombatTracker().getDeathMessage().getString()); + } + + this.dead = true; + this.getCombatTracker().recheckStatus(); +- if (this.level() instanceof ServerLevel serverLevel) { +- if (entity == null || entity.killedEntity(serverLevel, this)) { ++ Level world = this.level(); ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ ++ if (entity == null || entity.killedEntity(worldserver, this)) { + this.gameEvent(GameEvent.ENTITY_DIE); + this.dropAllDeathLoot(damageSource); +- this.createWitherRose(killCredit); ++ this.createWitherRose(entityliving); + } + +- this.level().broadcastEntityEvent(this, (byte)3); ++ this.level().broadcastEntityEvent(this, (byte) 3); + } + +- this.setPose(Pose.DYING); ++ this.setPose(EntityPose.DYING); + } + } + + protected void createWitherRose(@Nullable LivingEntity entitySource) { + if (!this.level().isClientSide) { + boolean flag = false; ++ + if (entitySource instanceof WitherBoss) { + if (this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- BlockPos blockPos = this.blockPosition(); +- BlockState blockState = Blocks.WITHER_ROSE.defaultBlockState(); +- if (this.level().getBlockState(blockPos).isAir() && blockState.canSurvive(this.level(), blockPos)) { +- this.level().setBlock(blockPos, blockState, 3); +- flag = true; ++ BlockPos blockposition = this.blockPosition(); ++ IBlockData iblockdata = Blocks.WITHER_ROSE.defaultBlockState(); ++ ++ if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) { ++ // CraftBukkit start - call EntityBlockFormEvent for Wither Rose ++ flag = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this.level(), blockposition, iblockdata, 3, this); ++ // CraftBukkit end + } + } + + if (!flag) { +- ItemEntity itemEntity = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), new ItemStack(Items.WITHER_ROSE)); +- this.level().addFreshEntity(itemEntity); ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), new ItemStack(Items.WITHER_ROSE)); ++ ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ CraftEventFactory.callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ this.level().addFreshEntity(entityitem); + } + } ++ + } + } + + protected void dropAllDeathLoot(DamageSource damageSource) { + Entity entity = damageSource.getEntity(); +- int mobLooting; +- if (entity instanceof Player) { +- mobLooting = EnchantmentHelper.getMobLooting((LivingEntity)entity); ++ int i; ++ ++ if (entity instanceof net.minecraft.world.entity.player.Player) { ++ i = EnchantmentHelper.getMobLooting((LivingEntity) entity); + } else { +- mobLooting = 0; ++ i = 0; + } + + boolean flag = this.lastHurtByPlayerTime > 0; ++ ++ this.dropEquipment(); // CraftBukkit - from below + if (this.shouldDropLoot() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { + this.dropFromLootTable(damageSource, flag); +- this.dropCustomDeathLoot(damageSource, mobLooting, flag); ++ this.dropCustomDeathLoot(damageSource, i, flag); + } ++ // CraftBukkit start - Call death event ++ CraftEventFactory.callEntityDeathEvent(this, this.drops); ++ this.drops = new ArrayList<>(); ++ // CraftBukkit end + +- this.dropEquipment(); ++ // this.dropInventory();// CraftBukkit - moved up + this.dropExperience(); + } + +- protected void dropEquipment() { ++ protected void dropEquipment() {} ++ ++ // CraftBukkit start ++ public int getExpReward() { ++ if (this.level() instanceof ServerLevel && !this.wasExperienceConsumed() && (this.isAlwaysExperienceDropper() || this.lastHurtByPlayerTime > 0 && this.shouldDropExperience() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT))) { ++ int i = this.getExperienceReward(); ++ return i; ++ } else { ++ return 0; ++ } + } ++ // CraftBukkit end + + protected void dropExperience() { +- if (this.level() instanceof ServerLevel +- && !this.wasExperienceConsumed() +- && ( +- this.isAlwaysExperienceDropper() +- || this.lastHurtByPlayerTime > 0 && this.shouldDropExperience() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT) +- )) { +- ExperienceOrb.award((ServerLevel)this.level(), this.position(), this.getExperienceReward()); ++ // CraftBukkit start - Update getExpReward() above if the removed if() changes! ++ if (true && !(this instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon)) { // CraftBukkit - SPIGOT-2420: Special case ender dragon will drop the xp over time ++ ExperienceOrb.award((ServerLevel) this.level(), this.position(), this.expToDrop); ++ this.expToDrop = 0; + } +- } ++ // CraftBukkit end + +- protected void dropCustomDeathLoot(DamageSource damageSource, int looting, boolean hitByPlayer) { + } + ++ protected void dropCustomDeathLoot(DamageSource damageSource, int looting, boolean hitByPlayer) {} ++ + public ResourceLocation getLootTable() { + return this.getType().getDefaultLootTable(); + } +@@ -1433,36 +1776,31 @@ + } + + protected void dropFromLootTable(DamageSource damageSource, boolean hitByPlayer) { +- ResourceLocation lootTable = this.getLootTable(); +- LootTable lootTable1 = this.level().getServer().getLootData().getLootTable(lootTable); +- LootParams.Builder builder = new LootParams.Builder((ServerLevel)this.level()) +- .withParameter(LootContextParams.THIS_ENTITY, this) +- .withParameter(LootContextParams.ORIGIN, this.position()) +- .withParameter(LootContextParams.DAMAGE_SOURCE, damageSource) +- .withOptionalParameter(LootContextParams.KILLER_ENTITY, damageSource.getEntity()) +- .withOptionalParameter(LootContextParams.DIRECT_KILLER_ENTITY, damageSource.getDirectEntity()); ++ ResourceLocation minecraftkey = this.getLootTable(); ++ LootTable loottable = this.level().getServer().getLootData().getLootTable(minecraftkey); ++ LootParams.Builder lootparams_a = (new LootParams.Builder((ServerLevel) this.level())).withParameter(LootContextParams.THIS_ENTITY, this).withParameter(LootContextParams.ORIGIN, this.position()).withParameter(LootContextParams.DAMAGE_SOURCE, damageSource).withOptionalParameter(LootContextParams.KILLER_ENTITY, damageSource.getEntity()).withOptionalParameter(LootContextParams.DIRECT_KILLER_ENTITY, damageSource.getDirectEntity()); ++ + if (hitByPlayer && this.lastHurtByPlayer != null) { +- builder = builder.withParameter(LootContextParams.LAST_DAMAGE_PLAYER, this.lastHurtByPlayer).withLuck(this.lastHurtByPlayer.getLuck()); ++ lootparams_a = lootparams_a.withParameter(LootContextParams.LAST_DAMAGE_PLAYER, this.lastHurtByPlayer).withLuck(this.lastHurtByPlayer.getLuck()); + } + +- LootParams lootParams = builder.create(LootContextParamSets.ENTITY); +- lootTable1.getRandomItems(lootParams, this.getLootTableSeed(), this::spawnAtLocation); ++ LootParams lootparams = lootparams_a.create(LootContextParamSets.ENTITY); ++ ++ loottable.getRandomItems(lootparams, this.getLootTableSeed(), this::spawnAtLocation); + } + +- public void knockback(double strength, double x, double z) { +- double var9 = strength * (1.0 - this.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE)); +- if (!(var9 <= 0.0)) { ++ public void knockback(double strength, double d1, double x) { ++ strength *= 1.0D - this.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE); ++ if (strength > 0.0D) { + this.hasImpulse = true; +- Vec3 deltaMovement = this.getDeltaMovement(); +- Vec3 vec3 = new Vec3(x, 0.0, z).normalize().scale(var9); +- this.setDeltaMovement( +- deltaMovement.x / 2.0 - vec3.x, this.onGround() ? Math.min(0.4, deltaMovement.y / 2.0 + var9) : deltaMovement.y, deltaMovement.z / 2.0 - vec3.z +- ); ++ Vec3 vec3d = this.getDeltaMovement(); ++ Vec3 vec3d1 = (new Vec3(d1, 0.0D, x)).normalize().scale(strength); ++ ++ this.setDeltaMovement(vec3d.x / 2.0D - vec3d1.x, this.onGround() ? Math.min(0.4D, vec3d.y / 2.0D + strength) : vec3d.y, vec3d.z / 2.0D - vec3d1.z); + } + } + +- public void indicateDamage(double xDistance, double zDistance) { +- } ++ public void indicateDamage(double xDistance, double d1) {} + + @Nullable + protected SoundEvent getHurtSound(DamageSource damageSource) { +@@ -1491,18 +1829,20 @@ + } + + protected AABB getHitbox() { +- AABB boundingBox = this.getBoundingBox(); +- Entity vehicle = this.getVehicle(); +- if (vehicle != null) { +- Vec3 passengerRidingPosition = vehicle.getPassengerRidingPosition(this); +- return boundingBox.setMinY(Math.max(passengerRidingPosition.y, boundingBox.minY)); ++ AABB axisalignedbb = this.getBoundingBox(); ++ Entity entity = this.getVehicle(); ++ ++ if (entity != null) { ++ Vec3 vec3d = entity.getPassengerRidingPosition(this); ++ ++ return axisalignedbb.setMinY(Math.max(vec3d.y, axisalignedbb.minY)); + } else { +- return boundingBox; ++ return axisalignedbb; + } + } + +- public LivingEntity.Fallsounds getFallSounds() { +- return new LivingEntity.Fallsounds(SoundEvents.GENERIC_SMALL_FALL, SoundEvents.GENERIC_BIG_FALL); ++ public LivingEntity.a getFallSounds() { ++ return new LivingEntity.a(SoundEvents.GENERIC_SMALL_FALL, SoundEvents.GENERIC_BIG_FALL); + } + + protected SoundEvent getDrinkingSound(ItemStack stack) { +@@ -1513,6 +1853,28 @@ + return stack.getEatingSound(); + } + ++ // CraftBukkit start - Add delegate methods ++ public SoundEvent getHurtSound0(DamageSource damagesource) { ++ return getHurtSound(damagesource); ++ } ++ ++ public SoundEvent getDeathSound0() { ++ return getDeathSound(); ++ } ++ ++ public SoundEvent getFallDamageSound0(int fallHeight) { ++ return getFallDamageSound(fallHeight); ++ } ++ ++ public SoundEvent getDrinkingSound0(ItemStack itemstack) { ++ return getDrinkingSound(itemstack); ++ } ++ ++ public SoundEvent getEatingSound0(ItemStack itemstack) { ++ return getEatingSound(itemstack); ++ } ++ // CraftBukkit end ++ + public Optional getLastClimbablePos() { + return this.lastClimbablePos; + } +@@ -1521,13 +1883,14 @@ + if (this.isSpectator()) { + return false; + } else { +- BlockPos blockPos = this.blockPosition(); +- BlockState feetBlockState = this.getFeetBlockState(); +- if (feetBlockState.is(BlockTags.CLIMBABLE)) { +- this.lastClimbablePos = Optional.of(blockPos); ++ BlockPos blockposition = this.blockPosition(); ++ IBlockData iblockdata = this.getFeetBlockState(); ++ ++ if (iblockdata.is(BlockTags.CLIMBABLE)) { ++ this.lastClimbablePos = Optional.of(blockposition); + return true; +- } else if (feetBlockState.getBlock() instanceof TrapDoorBlock && this.trapdoorUsableAsLadder(blockPos, feetBlockState)) { +- this.lastClimbablePos = Optional.of(blockPos); ++ } else if (iblockdata.getBlock() instanceof TrapDoorBlock && this.trapdoorUsableAsLadder(blockposition, iblockdata)) { ++ this.lastClimbablePos = Optional.of(blockposition); + return true; + } else { + return false; +@@ -1535,10 +1898,11 @@ + } + } + +- private boolean trapdoorUsableAsLadder(BlockPos pos, BlockState state) { +- if (state.getValue(TrapDoorBlock.OPEN)) { +- BlockState blockState = this.level().getBlockState(pos.below()); +- if (blockState.is(Blocks.LADDER) && blockState.getValue(LadderBlock.FACING) == state.getValue(TrapDoorBlock.FACING)) { ++ private boolean trapdoorUsableAsLadder(BlockPos pos, IBlockData state) { ++ if ((Boolean) state.getValue(TrapDoorBlock.OPEN)) { ++ IBlockData iblockdata1 = this.level().getBlockState(pos.below()); ++ ++ if (iblockdata1.is(Blocks.LADDER) && iblockdata1.getValue(LadderBlock.FACING) == state.getValue(TrapDoorBlock.FACING)) { + return true; + } + } +@@ -1555,10 +1919,16 @@ + public boolean causeFallDamage(float fallDistance, float multiplier, DamageSource source) { + boolean flag = super.causeFallDamage(fallDistance, multiplier, source); + int i = this.calculateFallDamage(fallDistance, multiplier); ++ + if (i > 0) { ++ // CraftBukkit start ++ if (!this.hurt(source, (float) i)) { ++ return true; ++ } ++ // CraftBukkit end + this.playSound(this.getFallDamageSound(i), 1.0F, 1.0F); + this.playBlockFallSound(); +- this.hurt(source, (float)i); ++ // this.damageEntity(damagesource, (float) i); // CraftBukkit - moved up + return true; + } else { + return flag; +@@ -1569,22 +1939,26 @@ + if (this.getType().is(EntityTypeTags.FALL_DAMAGE_IMMUNE)) { + return 0; + } else { +- MobEffectInstance effect = this.getEffect(MobEffects.JUMP); +- float f = effect == null ? 0.0F : (float)(effect.getAmplifier() + 1); +- return Mth.ceil((fallDistance - 3.0F - f) * damageMultiplier); ++ MobEffectInstance mobeffect = this.getEffect(MobEffects.JUMP); ++ float f2 = mobeffect == null ? 0.0F : (float) (mobeffect.getAmplifier() + 1); ++ ++ return Mth.ceil((fallDistance - 3.0F - f2) * damageMultiplier); + } + } + + protected void playBlockFallSound() { + if (!this.isSilent()) { +- int floor = Mth.floor(this.getX()); +- int floor1 = Mth.floor(this.getY() - 0.2F); +- int floor2 = Mth.floor(this.getZ()); +- BlockState blockState = this.level().getBlockState(new BlockPos(floor, floor1, floor2)); +- if (!blockState.isAir()) { +- SoundType soundType = blockState.getSoundType(); +- this.playSound(soundType.getFallSound(), soundType.getVolume() * 0.5F, soundType.getPitch() * 0.75F); ++ int i = Mth.floor(this.getX()); ++ int j = Mth.floor(this.getY() - 0.20000000298023224D); ++ int k = Mth.floor(this.getZ()); ++ IBlockData iblockdata = this.level().getBlockState(new BlockPos(i, j, k)); ++ ++ if (!iblockdata.isAir()) { ++ SoundType soundeffecttype = iblockdata.getSoundType(); ++ ++ this.playSound(soundeffecttype.getFallSound(), soundeffecttype.getVolume() * 0.5F, soundeffecttype.getPitch() * 0.75F); + } ++ + } + } + +@@ -1598,21 +1972,16 @@ + return Mth.floor(this.getAttributeValue(Attributes.ARMOR)); + } + +- protected void hurtArmor(DamageSource damageSource, float damageAmount) { +- } ++ protected void hurtArmor(DamageSource damageSource, float damageAmount) {} + +- protected void hurtHelmet(DamageSource damageSource, float damageAmount) { +- } ++ protected void hurtHelmet(DamageSource damageSource, float damageAmount) {} + +- protected void hurtCurrentlyUsedShield(float damageAmount) { +- } ++ protected void hurtCurrentlyUsedShield(float damageAmount) {} + + protected float getDamageAfterArmorAbsorb(DamageSource damageSource, float damageAmount) { + if (!damageSource.is(DamageTypeTags.BYPASSES_ARMOR)) { +- this.hurtArmor(damageSource, damageAmount); +- damageAmount = CombatRules.getDamageAfterAbsorb( +- damageAmount, (float)this.getArmorValue(), (float)this.getAttributeValue(Attributes.ARMOR_TOUGHNESS) +- ); ++ // this.hurtArmor(damagesource, f); // CraftBukkit - Moved into damageEntity0(DamageSource, float) ++ damageAmount = CombatRules.getDamageAfterAbsorb(damageAmount, (float) this.getArmorValue(), (float) this.getAttributeValue(Attributes.ARMOR_TOUGHNESS)); + } + + return damageAmount; +@@ -1622,18 +1991,23 @@ + if (damageSource.is(DamageTypeTags.BYPASSES_EFFECTS)) { + return damageAmount; + } else { +- if (this.hasEffect(MobEffects.DAMAGE_RESISTANCE) && !damageSource.is(DamageTypeTags.BYPASSES_RESISTANCE)) { +- int i = (this.getEffect(MobEffects.DAMAGE_RESISTANCE).getAmplifier() + 1) * 5; +- int i1 = 25 - i; +- float f = damageAmount * (float)i1; +- float f1 = damageAmount; +- damageAmount = Math.max(f / 25.0F, 0.0F); +- float f2 = f1 - damageAmount; +- if (f2 > 0.0F && f2 < 3.4028235E37F) { ++ int i; ++ ++ // CraftBukkit - Moved to damageEntity0(DamageSource, float) ++ if (false && this.hasEffect(MobEffects.DAMAGE_RESISTANCE) && !damageSource.is(DamageTypeTags.BYPASSES_RESISTANCE)) { ++ i = (this.getEffect(MobEffects.DAMAGE_RESISTANCE).getAmplifier() + 1) * 5; ++ int j = 25 - i; ++ float f1 = damageAmount * (float) j; ++ float f2 = damageAmount; ++ ++ damageAmount = Math.max(f1 / 25.0F, 0.0F); ++ float f3 = f2 - damageAmount; ++ ++ if (f3 > 0.0F && f3 < 3.4028235E37F) { + if (this instanceof ServerPlayer) { +- ((ServerPlayer)this).awardStat(Stats.DAMAGE_RESISTED, Math.round(f2 * 10.0F)); ++ ((ServerPlayer) this).awardStat(Stats.DAMAGE_RESISTED, Math.round(f3 * 10.0F)); + } else if (damageSource.getEntity() instanceof ServerPlayer) { +- ((ServerPlayer)damageSource.getEntity()).awardStat(Stats.DAMAGE_DEALT_RESISTED, Math.round(f2 * 10.0F)); ++ ((ServerPlayer) damageSource.getEntity()).awardStat(Stats.DAMAGE_DEALT_RESISTED, Math.round(f3 * 10.0F)); + } + } + } +@@ -1643,9 +2017,9 @@ + } else if (damageSource.is(DamageTypeTags.BYPASSES_ENCHANTMENTS)) { + return damageAmount; + } else { +- int i = EnchantmentHelper.getDamageProtection(this.getArmorSlots(), damageSource); ++ i = EnchantmentHelper.getDamageProtection(this.getArmorSlots(), damageSource); + if (i > 0) { +- damageAmount = CombatRules.getDamageAfterMagicAbsorb(damageAmount, (float)i); ++ damageAmount = CombatRules.getDamageAfterMagicAbsorb(damageAmount, (float) i); + } + + return damageAmount; +@@ -1653,24 +2027,176 @@ + } + } + +- protected void actuallyHurt(DamageSource damageSource, float damageAmount) { +- if (!this.isInvulnerableTo(damageSource)) { +- damageAmount = this.getDamageAfterArmorAbsorb(damageSource, damageAmount); +- damageAmount = this.getDamageAfterMagicAbsorb(damageSource, damageAmount); +- float var9 = Math.max(damageAmount - this.getAbsorptionAmount(), 0.0F); +- this.setAbsorptionAmount(this.getAbsorptionAmount() - (damageAmount - var9)); +- float f1 = damageAmount - var9; +- if (f1 > 0.0F && f1 < 3.4028235E37F && damageSource.getEntity() instanceof ServerPlayer serverPlayer) { +- serverPlayer.awardStat(Stats.DAMAGE_DEALT_ABSORBED, Math.round(f1 * 10.0F)); ++ // CraftBukkit start ++ protected boolean damageEntity0(final DamageSource damagesource, float f) { // void -> boolean, add final ++ if (!this.isInvulnerableTo(damagesource)) { ++ final boolean human = this instanceof net.minecraft.world.entity.player.Player; ++ float originalDamage = f; ++ Function hardHat = new Function() { ++ @Override ++ public Double apply(Double f) { ++ if (damagesource.is(DamageTypeTags.DAMAGES_HELMET) && !LivingEntity.this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { ++ return -(f - (f * 0.75F)); ++ ++ } ++ return -0.0; ++ } ++ }; ++ float hardHatModifier = hardHat.apply((double) f).floatValue(); ++ f += hardHatModifier; ++ ++ Function blocking = new Function() { ++ @Override ++ public Double apply(Double f) { ++ return -((LivingEntity.this.isDamageSourceBlocked(damagesource)) ? f : 0.0); ++ } ++ }; ++ float blockingModifier = blocking.apply((double) f).floatValue(); ++ f += blockingModifier; ++ ++ Function armor = new Function() { ++ @Override ++ public Double apply(Double f) { ++ return -(f - LivingEntity.this.getDamageAfterArmorAbsorb(damagesource, f.floatValue())); ++ } ++ }; ++ float armorModifier = armor.apply((double) f).floatValue(); ++ f += armorModifier; ++ ++ Function resistance = new Function() { ++ @Override ++ public Double apply(Double f) { ++ if (!damagesource.is(DamageTypeTags.BYPASSES_EFFECTS) && LivingEntity.this.hasEffect(MobEffects.DAMAGE_RESISTANCE) && !damagesource.is(DamageTypeTags.BYPASSES_RESISTANCE)) { ++ int i = (LivingEntity.this.getEffect(MobEffects.DAMAGE_RESISTANCE).getAmplifier() + 1) * 5; ++ int j = 25 - i; ++ float f1 = f.floatValue() * (float) j; ++ return -(f - (f1 / 25.0F)); ++ } ++ return -0.0; ++ } ++ }; ++ float resistanceModifier = resistance.apply((double) f).floatValue(); ++ f += resistanceModifier; ++ ++ Function magic = new Function() { ++ @Override ++ public Double apply(Double f) { ++ return -(f - LivingEntity.this.getDamageAfterMagicAbsorb(damagesource, f.floatValue())); ++ } ++ }; ++ float magicModifier = magic.apply((double) f).floatValue(); ++ f += magicModifier; ++ ++ Function absorption = new Function() { ++ @Override ++ public Double apply(Double f) { ++ return -(Math.max(f - Math.max(f - LivingEntity.this.getAbsorptionAmount(), 0.0F), 0.0F)); ++ } ++ }; ++ float absorptionModifier = absorption.apply((double) f).floatValue(); ++ ++ EntityDamageEvent event = CraftEventFactory.handleLivingEntityDamageEvent(this, damagesource, originalDamage, hardHatModifier, blockingModifier, armorModifier, resistanceModifier, magicModifier, absorptionModifier, hardHat, blocking, armor, resistance, magic, absorption); ++ if (damagesource.getEntity() instanceof net.minecraft.world.entity.player.Player) { ++ ((net.minecraft.world.entity.player.Player) damagesource.getEntity()).resetAttackStrengthTicker(); // Moved from EntityHuman in order to make the cooldown reset get called after the damage event is fired + } ++ if (event.isCancelled()) { ++ return false; ++ } + +- if (var9 != 0.0F) { +- this.getCombatTracker().recordDamage(damageSource, var9); +- this.setHealth(this.getHealth() - var9); +- this.setAbsorptionAmount(this.getAbsorptionAmount() - var9); ++ f = (float) event.getFinalDamage(); ++ ++ // Resistance ++ if (event.getDamage(DamageModifier.RESISTANCE) < 0) { ++ float f3 = (float) -event.getDamage(DamageModifier.RESISTANCE); ++ if (f3 > 0.0F && f3 < 3.4028235E37F) { ++ if (this instanceof ServerPlayer) { ++ ((ServerPlayer) this).awardStat(Stats.DAMAGE_RESISTED, Math.round(f3 * 10.0F)); ++ } else if (damagesource.getEntity() instanceof ServerPlayer) { ++ ((ServerPlayer) damagesource.getEntity()).awardStat(Stats.DAMAGE_DEALT_RESISTED, Math.round(f3 * 10.0F)); ++ } ++ } ++ } ++ ++ // Apply damage to helmet ++ if (damagesource.is(DamageTypeTags.DAMAGES_HELMET) && !this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { ++ this.hurtHelmet(damagesource, f); ++ } ++ ++ // Apply damage to armor ++ if (!damagesource.is(DamageTypeTags.BYPASSES_ARMOR)) { ++ float armorDamage = (float) (event.getDamage() + event.getDamage(DamageModifier.BLOCKING) + event.getDamage(DamageModifier.HARD_HAT)); ++ this.hurtArmor(damagesource, armorDamage); ++ } ++ ++ // Apply blocking code // PAIL: steal from above ++ if (event.getDamage(DamageModifier.BLOCKING) < 0) { ++ this.level().broadcastEntityEvent(this, (byte) 29); // SPIGOT-4635 - shield damage sound ++ this.hurtCurrentlyUsedShield((float) -event.getDamage(DamageModifier.BLOCKING)); ++ Entity entity = damagesource.getDirectEntity(); ++ ++ if (entity instanceof LivingEntity) { ++ this.blockUsingShield((LivingEntity) entity); ++ } ++ } ++ ++ absorptionModifier = (float) -event.getDamage(DamageModifier.ABSORPTION); ++ this.setAbsorptionAmount(Math.max(this.getAbsorptionAmount() - absorptionModifier, 0.0F)); ++ float f2 = absorptionModifier; ++ ++ if (f2 > 0.0F && f2 < 3.4028235E37F && this instanceof net.minecraft.world.entity.player.Player) { ++ ((net.minecraft.world.entity.player.Player) this).awardStat(Stats.DAMAGE_ABSORBED, Math.round(f2 * 10.0F)); ++ } ++ if (f2 > 0.0F && f2 < 3.4028235E37F) { ++ Entity entity = damagesource.getEntity(); ++ ++ if (entity instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entity; ++ ++ entityplayer.awardStat(Stats.DAMAGE_DEALT_ABSORBED, Math.round(f2 * 10.0F)); ++ } ++ } ++ ++ if (f > 0 || !human) { ++ if (human) { ++ // PAIL: Be sure to drag all this code from the EntityHuman subclass each update. ++ ((net.minecraft.world.entity.player.Player) this).causeFoodExhaustion(damagesource.getFoodExhaustion(), org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.DAMAGED); // CraftBukkit - EntityExhaustionEvent ++ if (f < 3.4028235E37F) { ++ ((net.minecraft.world.entity.player.Player) this).awardStat(Stats.DAMAGE_TAKEN, Math.round(f * 10.0F)); ++ } ++ } ++ // CraftBukkit end ++ this.getCombatTracker().recordDamage(damagesource, f); ++ this.setHealth(this.getHealth() - f); ++ // CraftBukkit start ++ if (!human) { ++ this.setAbsorptionAmount(this.getAbsorptionAmount() - f); ++ } + this.gameEvent(GameEvent.ENTITY_DAMAGE); ++ ++ return true; ++ } else { ++ // Duplicate triggers if blocking ++ if (event.getDamage(DamageModifier.BLOCKING) < 0) { ++ if (this instanceof ServerPlayer) { ++ CriteriaTriggers.ENTITY_HURT_PLAYER.trigger((ServerPlayer) this, damagesource, f, originalDamage, true); ++ f2 = (float) -event.getDamage(DamageModifier.BLOCKING); ++ if (f2 > 0.0F && f2 < 3.4028235E37F) { ++ ((ServerPlayer) this).awardStat(Stats.DAMAGE_BLOCKED_BY_SHIELD, Math.round(originalDamage * 10.0F)); ++ } ++ } ++ ++ if (damagesource.getEntity() instanceof ServerPlayer) { ++ CriteriaTriggers.PLAYER_HURT_ENTITY.trigger((ServerPlayer) damagesource.getEntity(), this, damagesource, f, originalDamage, true); ++ } ++ ++ return false; ++ } else { ++ return originalDamage > 0; ++ } ++ // CraftBukkit end + } + } ++ return false; // CraftBukkit + } + + public CombatTracker getCombatTracker() { +@@ -1679,64 +2205,68 @@ + + @Nullable + public LivingEntity getKillCredit() { +- if (this.lastHurtByPlayer != null) { +- return this.lastHurtByPlayer; +- } else { +- return this.lastHurtByMob != null ? this.lastHurtByMob : null; +- } ++ return (LivingEntity) (this.lastHurtByPlayer != null ? this.lastHurtByPlayer : (this.lastHurtByMob != null ? this.lastHurtByMob : null)); + } + + public final float getMaxHealth() { +- return (float)this.getAttributeValue(Attributes.MAX_HEALTH); ++ return (float) this.getAttributeValue(Attributes.MAX_HEALTH); + } + + public final float getMaxAbsorption() { +- return (float)this.getAttributeValue(Attributes.MAX_ABSORPTION); ++ return (float) this.getAttributeValue(Attributes.MAX_ABSORPTION); + } + + public final int getArrowCount() { +- return this.entityData.get(DATA_ARROW_COUNT_ID); ++ return (Integer) this.entityData.get(LivingEntity.DATA_ARROW_COUNT_ID); + } + + public final void setArrowCount(int count) { +- this.entityData.set(DATA_ARROW_COUNT_ID, count); ++ // CraftBukkit start ++ setArrowCount(count, false); + } + ++ public final void setArrowCount(int i, boolean flag) { ++ ArrowBodyCountChangeEvent event = CraftEventFactory.callArrowBodyCountChangeEvent(this, getArrowCount(), i, flag); ++ if (event.isCancelled()) { ++ return; ++ } ++ this.entityData.set(LivingEntity.DATA_ARROW_COUNT_ID, event.getNewAmount()); ++ } ++ // CraftBukkit end ++ + public final int getStingerCount() { +- return this.entityData.get(DATA_STINGER_COUNT_ID); ++ return (Integer) this.entityData.get(LivingEntity.DATA_STINGER_COUNT_ID); + } + + public final void setStingerCount(int stingerCount) { +- this.entityData.set(DATA_STINGER_COUNT_ID, stingerCount); ++ this.entityData.set(LivingEntity.DATA_STINGER_COUNT_ID, stingerCount); + } + + private int getCurrentSwingDuration() { +- if (MobEffectUtil.hasDigSpeed(this)) { +- return 6 - (1 + MobEffectUtil.getDigSpeedAmplification(this)); +- } else { +- return this.hasEffect(MobEffects.DIG_SLOWDOWN) ? 6 + (1 + this.getEffect(MobEffects.DIG_SLOWDOWN).getAmplifier()) * 2 : 6; +- } ++ return MobEffectUtil.hasDigSpeed(this) ? 6 - (1 + MobEffectUtil.getDigSpeedAmplification(this)) : (this.hasEffect(MobEffects.DIG_SLOWDOWN) ? 6 + (1 + this.getEffect(MobEffects.DIG_SLOWDOWN).getAmplifier()) * 2 : 6); + } + +- public void swing(InteractionHand hand) { ++ public void swing(EnumHand hand) { + this.swing(hand, false); + } + +- public void swing(InteractionHand hand, boolean updateSelf) { ++ public void swing(EnumHand hand, boolean updateSelf) { + if (!this.swinging || this.swingTime >= this.getCurrentSwingDuration() / 2 || this.swingTime < 0) { + this.swingTime = -1; + this.swinging = true; + this.swingingArm = hand; + if (this.level() instanceof ServerLevel) { +- ClientboundAnimatePacket clientboundAnimatePacket = new ClientboundAnimatePacket(this, hand == InteractionHand.MAIN_HAND ? 0 : 3); +- ServerChunkCache chunkSource = ((ServerLevel)this.level()).getChunkSource(); ++ ClientboundAnimatePacket packetplayoutanimation = new ClientboundAnimatePacket(this, hand == EnumHand.MAIN_HAND ? 0 : 3); ++ ServerChunkCache chunkproviderserver = ((ServerLevel) this.level()).getChunkSource(); ++ + if (updateSelf) { +- chunkSource.broadcastAndSend(this, clientboundAnimatePacket); ++ chunkproviderserver.broadcastAndSend(this, packetplayoutanimation); + } else { +- chunkSource.broadcast(this, clientboundAnimatePacket); ++ chunkproviderserver.broadcast(this, packetplayoutanimation); + } + } + } ++ + } + + @Override +@@ -1745,9 +2275,10 @@ + this.invulnerableTime = 20; + this.hurtDuration = 10; + this.hurtTime = this.hurtDuration; +- SoundEvent hurtSound = this.getHurtSound(damageSource); +- if (hurtSound != null) { +- this.playSound(hurtSound, this.getSoundVolume(), (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); ++ SoundEvent soundeffect = this.getHurtSound(damageSource); ++ ++ if (soundeffect != null) { ++ this.playSound(soundeffect, this.getSoundVolume(), (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); + } + + this.hurt(this.damageSources().generic(), 0.0F); +@@ -1759,12 +2290,13 @@ + public void handleEntityEvent(byte id) { + switch (id) { + case 3: +- SoundEvent deathSound = this.getDeathSound(); +- if (deathSound != null) { +- this.playSound(deathSound, this.getSoundVolume(), (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); ++ SoundEvent soundeffect = this.getDeathSound(); ++ ++ if (soundeffect != null) { ++ this.playSound(soundeffect, this.getSoundVolume(), (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); + } + +- if (!(this instanceof Player)) { ++ if (!(this instanceof net.minecraft.world.entity.player.Player)) { + this.setHealth(0.0F); + this.die(this.damageSources().generic()); + } +@@ -1776,19 +2308,21 @@ + this.playSound(SoundEvents.SHIELD_BREAK, 0.8F, 0.8F + this.level().random.nextFloat() * 0.4F); + break; + case 46: +- int i = 128; ++ boolean flag = true; + +- for (int i1 = 0; i1 < 128; i1++) { +- double d = (double)i1 / 127.0; ++ for (int i = 0; i < 128; ++i) { ++ double d0 = (double) i / 127.0D; + float f = (this.random.nextFloat() - 0.5F) * 0.2F; + float f1 = (this.random.nextFloat() - 0.5F) * 0.2F; + float f2 = (this.random.nextFloat() - 0.5F) * 0.2F; +- double d1 = Mth.lerp(d, this.xo, this.getX()) + (this.random.nextDouble() - 0.5) * (double)this.getBbWidth() * 2.0; +- double d2 = Mth.lerp(d, this.yo, this.getY()) + this.random.nextDouble() * (double)this.getBbHeight(); +- double d3 = Mth.lerp(d, this.zo, this.getZ()) + (this.random.nextDouble() - 0.5) * (double)this.getBbWidth() * 2.0; +- this.level().addParticle(ParticleTypes.PORTAL, d1, d2, d3, (double)f, (double)f1, (double)f2); ++ double d1 = Mth.lerp(d0, this.xo, this.getX()) + (this.random.nextDouble() - 0.5D) * (double) this.getBbWidth() * 2.0D; ++ double d2 = Mth.lerp(d0, this.yo, this.getY()) + this.random.nextDouble() * (double) this.getBbHeight(); ++ double d3 = Mth.lerp(d0, this.zo, this.getZ()) + (this.random.nextDouble() - 0.5D) * (double) this.getBbWidth() * 2.0D; ++ ++ this.level().addParticle(ParticleTypes.PORTAL, d1, d2, d3, (double) f, (double) f1, (double) f2); + } +- break; ++ ++ return; + case 47: + this.breakItem(this.getItemBySlot(EquipmentSlot.MAINHAND)); + break; +@@ -1819,21 +2353,25 @@ + default: + super.handleEntityEvent(id); + } ++ + } + + private void makePoofParticles() { +- for (int i = 0; i < 20; i++) { +- double d = this.random.nextGaussian() * 0.02; +- double d1 = this.random.nextGaussian() * 0.02; +- double d2 = this.random.nextGaussian() * 0.02; +- this.level().addParticle(ParticleTypes.POOF, this.getRandomX(1.0), this.getRandomY(), this.getRandomZ(1.0), d, d1, d2); ++ for (int i = 0; i < 20; ++i) { ++ double d0 = this.random.nextGaussian() * 0.02D; ++ double d1 = this.random.nextGaussian() * 0.02D; ++ double d2 = this.random.nextGaussian() * 0.02D; ++ ++ this.level().addParticle(ParticleTypes.POOF, this.getRandomX(1.0D), this.getRandomY(), this.getRandomZ(1.0D), d0, d1, d2); + } ++ + } + + private void swapHandItems() { +- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.OFFHAND); ++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.OFFHAND); ++ + this.setItemSlot(EquipmentSlot.OFFHAND, this.getItemBySlot(EquipmentSlot.MAINHAND)); +- this.setItemSlot(EquipmentSlot.MAINHAND, itemBySlot); ++ this.setItemSlot(EquipmentSlot.MAINHAND, itemstack); + } + + @Override +@@ -1842,10 +2380,11 @@ + } + + protected void updateSwingTime() { +- int currentSwingDuration = this.getCurrentSwingDuration(); ++ int i = this.getCurrentSwingDuration(); ++ + if (this.swinging) { +- this.swingTime++; +- if (this.swingTime >= currentSwingDuration) { ++ ++this.swingTime; ++ if (this.swingTime >= i) { + this.swingTime = 0; + this.swinging = false; + } +@@ -1853,7 +2392,7 @@ + this.swingTime = 0; + } + +- this.attackAnim = (float)this.swingTime / (float)currentSwingDuration; ++ this.attackAnim = (float) this.swingTime / (float) i; + } + + @Nullable +@@ -1862,7 +2401,7 @@ + } + + public double getAttributeValue(Holder attribute) { +- return this.getAttributeValue(attribute.value()); ++ return this.getAttributeValue((Attribute) attribute.value()); + } + + public double getAttributeValue(Attribute attribute) { +@@ -1870,7 +2409,7 @@ + } + + public double getAttributeBaseValue(Holder attribute) { +- return this.getAttributeBaseValue(attribute.value()); ++ return this.getAttributeBaseValue((Attribute) attribute.value()); + } + + public double getAttributeBaseValue(Attribute attribute) { +@@ -1881,8 +2420,8 @@ + return this.attributes; + } + +- public MobType getMobType() { +- return MobType.UNDEFINED; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.UNDEFINED; + } + + public ItemStack getMainHandItem() { +@@ -1894,33 +2433,36 @@ + } + + public boolean isHolding(Item item) { +- return this.isHolding(stack -> stack.is(item)); ++ return this.isHolding((itemstack) -> { ++ return itemstack.is(item); ++ }); + } + + public boolean isHolding(Predicate predicate) { + return predicate.test(this.getMainHandItem()) || predicate.test(this.getOffhandItem()); + } + +- public ItemStack getItemInHand(InteractionHand hand) { +- if (hand == InteractionHand.MAIN_HAND) { ++ public ItemStack getItemInHand(EnumHand hand) { ++ if (hand == EnumHand.MAIN_HAND) { + return this.getItemBySlot(EquipmentSlot.MAINHAND); +- } else if (hand == InteractionHand.OFF_HAND) { ++ } else if (hand == EnumHand.OFF_HAND) { + return this.getItemBySlot(EquipmentSlot.OFFHAND); + } else { + throw new IllegalArgumentException("Invalid hand " + hand); + } + } + +- public void setItemInHand(InteractionHand hand, ItemStack stack) { +- if (hand == InteractionHand.MAIN_HAND) { ++ public void setItemInHand(EnumHand hand, ItemStack stack) { ++ if (hand == EnumHand.MAIN_HAND) { + this.setItemSlot(EquipmentSlot.MAINHAND, stack); + } else { +- if (hand != InteractionHand.OFF_HAND) { ++ if (hand != EnumHand.OFF_HAND) { + throw new IllegalArgumentException("Invalid hand " + hand); + } + + this.setItemSlot(EquipmentSlot.OFFHAND, stack); + } ++ + } + + public boolean hasItemInSlot(EquipmentSlot slot) { +@@ -1932,40 +2474,50 @@ + + public abstract ItemStack getItemBySlot(EquipmentSlot slot); + ++ // CraftBukkit start ++ public void setItemSlot(EquipmentSlot enumitemslot, ItemStack itemstack, boolean silent) { ++ this.setItemSlot(enumitemslot, itemstack); ++ } ++ // CraftBukkit end ++ + @Override + public abstract void setItemSlot(EquipmentSlot slot, ItemStack stack); + + protected void verifyEquippedItem(ItemStack stack) { +- CompoundTag tag = stack.getTag(); +- if (tag != null) { +- stack.getItem().verifyTagAfterLoad(tag); ++ CompoundTag nbttagcompound = stack.getTag(); ++ ++ if (nbttagcompound != null) { ++ stack.getItem().verifyTagAfterLoad(nbttagcompound); + } ++ + } + + public float getArmorCoverPercentage() { +- Iterable armorSlots = this.getArmorSlots(); ++ Iterable iterable = this.getArmorSlots(); + int i = 0; +- int i1 = 0; ++ int j = 0; + +- for (ItemStack itemStack : armorSlots) { +- if (!itemStack.isEmpty()) { +- i1++; +- } ++ for (Iterator iterator = iterable.iterator(); iterator.hasNext(); ++i) { ++ ItemStack itemstack = (ItemStack) iterator.next(); + +- i++; ++ if (!itemstack.isEmpty()) { ++ ++j; ++ } + } + +- return i > 0 ? (float)i1 / (float)i : 0.0F; ++ return i > 0 ? (float) j / (float) i : 0.0F; + } + + @Override + public void setSprinting(boolean sprinting) { + super.setSprinting(sprinting); +- AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED); +- attribute.removeModifier(SPEED_MODIFIER_SPRINTING.getId()); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ ++ attributemodifiable.removeModifier(LivingEntity.SPEED_MODIFIER_SPRINTING.getId()); + if (sprinting) { +- attribute.addTransientModifier(SPEED_MODIFIER_SPRINTING); ++ attributemodifiable.addTransientModifier(LivingEntity.SPEED_MODIFIER_SPRINTING); + } ++ + } + + protected float getSoundVolume() { +@@ -1973,9 +2525,7 @@ + } + + public float getVoicePitch() { +- return this.isBaby() +- ? (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.5F +- : (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F; ++ return this.isBaby() ? (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.5F : (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F; + } + + protected boolean isImmobile() { +@@ -1987,20 +2537,23 @@ + if (!this.isSleeping()) { + super.push(entity); + } ++ + } + + private void dismountVehicle(Entity vehicle) { +- Vec3 vec3; ++ Vec3 vec3d; ++ + if (this.isRemoved()) { +- vec3 = this.position(); ++ vec3d = this.position(); + } else if (!vehicle.isRemoved() && !this.level().getBlockState(vehicle.blockPosition()).is(BlockTags.PORTALS)) { +- vec3 = vehicle.getDismountLocationForPassenger(this); ++ vec3d = vehicle.getDismountLocationForPassenger(this); + } else { +- double max = Math.max(this.getY(), vehicle.getY()); +- vec3 = new Vec3(this.getX(), max, this.getZ()); ++ double d0 = Math.max(this.getY(), vehicle.getY()); ++ ++ vec3d = new Vec3(this.getX(), d0, this.getZ()); + } + +- this.dismountTo(vec3.x, vec3.y, vec3.z); ++ this.dismountTo(vec3d.x, vec3d.y, vec3d.z); + } + + @Override +@@ -2013,26 +2566,28 @@ + } + + public float getJumpBoostPower() { +- return this.hasEffect(MobEffects.JUMP) ? 0.1F * ((float)this.getEffect(MobEffects.JUMP).getAmplifier() + 1.0F) : 0.0F; ++ return this.hasEffect(MobEffects.JUMP) ? 0.1F * ((float) this.getEffect(MobEffects.JUMP).getAmplifier() + 1.0F) : 0.0F; + } + + protected void jumpFromGround() { +- Vec3 deltaMovement = this.getDeltaMovement(); +- this.setDeltaMovement(deltaMovement.x, (double)this.getJumpPower(), deltaMovement.z); ++ Vec3 vec3d = this.getDeltaMovement(); ++ ++ this.setDeltaMovement(vec3d.x, (double) this.getJumpPower(), vec3d.z); + if (this.isSprinting()) { +- float f = this.getYRot() * (float) (Math.PI / 180.0); +- this.setDeltaMovement(this.getDeltaMovement().add((double)(-Mth.sin(f) * 0.2F), 0.0, (double)(Mth.cos(f) * 0.2F))); ++ float f = this.getYRot() * 0.017453292F; ++ ++ this.setDeltaMovement(this.getDeltaMovement().add((double) (-Mth.sin(f) * 0.2F), 0.0D, (double) (Mth.cos(f) * 0.2F))); + } + + this.hasImpulse = true; + } + + protected void goDownInWater() { +- this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.04F, 0.0)); ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.03999999910593033D, 0.0D)); + } + + protected void jumpInLiquid(TagKey fluidTag) { +- this.setDeltaMovement(this.getDeltaMovement().add(0.0, 0.04F, 0.0)); ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, 0.03999999910593033D, 0.0D)); + } + + protected float getWaterSlowDown() { +@@ -2045,18 +2600,23 @@ + + public void travel(Vec3 travelVector) { + if (this.isControlledByLocalInstance()) { +- double d = 0.08; +- boolean flag = this.getDeltaMovement().y <= 0.0; ++ double d0 = 0.08D; ++ boolean flag = this.getDeltaMovement().y <= 0.0D; ++ + if (flag && this.hasEffect(MobEffects.SLOW_FALLING)) { +- d = 0.01; ++ d0 = 0.01D; + } + +- FluidState fluidState = this.level().getFluidState(this.blockPosition()); +- if (this.isInWater() && this.isAffectedByFluids() && !this.canStandOnFluid(fluidState)) { +- double y = this.getY(); +- float f = this.isSprinting() ? 0.9F : this.getWaterSlowDown(); ++ FluidState fluid = this.level().getFluidState(this.blockPosition()); ++ double d1; ++ float f; ++ ++ if (this.isInWater() && this.isAffectedByFluids() && !this.canStandOnFluid(fluid)) { ++ d1 = this.getY(); ++ f = this.isSprinting() ? 0.9F : this.getWaterSlowDown(); + float f1 = 0.02F; +- float f2 = (float)EnchantmentHelper.getDepthStrider(this); ++ float f2 = (float) EnchantmentHelper.getDepthStrider(this); ++ + if (f2 > 3.0F) { + f2 = 3.0F; + } +@@ -2075,170 +2635,182 @@ + } + + this.moveRelative(f1, travelVector); +- this.move(MoverType.SELF, this.getDeltaMovement()); +- Vec3 deltaMovement = this.getDeltaMovement(); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); ++ Vec3 vec3d1 = this.getDeltaMovement(); ++ + if (this.horizontalCollision && this.onClimbable()) { +- deltaMovement = new Vec3(deltaMovement.x, 0.2, deltaMovement.z); ++ vec3d1 = new Vec3(vec3d1.x, 0.2D, vec3d1.z); + } + +- this.setDeltaMovement(deltaMovement.multiply((double)f, 0.8F, (double)f)); +- Vec3 fluidFallingAdjustedMovement = this.getFluidFallingAdjustedMovement(d, flag, this.getDeltaMovement()); +- this.setDeltaMovement(fluidFallingAdjustedMovement); +- if (this.horizontalCollision +- && this.isFree(fluidFallingAdjustedMovement.x, fluidFallingAdjustedMovement.y + 0.6F - this.getY() + y, fluidFallingAdjustedMovement.z)) { +- this.setDeltaMovement(fluidFallingAdjustedMovement.x, 0.3F, fluidFallingAdjustedMovement.z); ++ this.setDeltaMovement(vec3d1.multiply((double) f, 0.800000011920929D, (double) f)); ++ Vec3 vec3d2 = this.getFluidFallingAdjustedMovement(d0, flag, this.getDeltaMovement()); ++ ++ this.setDeltaMovement(vec3d2); ++ if (this.horizontalCollision && this.isFree(vec3d2.x, vec3d2.y + 0.6000000238418579D - this.getY() + d1, vec3d2.z)) { ++ this.setDeltaMovement(vec3d2.x, 0.30000001192092896D, vec3d2.z); + } +- } else if (this.isInLava() && this.isAffectedByFluids() && !this.canStandOnFluid(fluidState)) { +- double yx = this.getY(); ++ } else if (this.isInLava() && this.isAffectedByFluids() && !this.canStandOnFluid(fluid)) { ++ d1 = this.getY(); + this.moveRelative(0.02F, travelVector); +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); ++ Vec3 vec3d3; ++ + if (this.getFluidHeight(FluidTags.LAVA) <= this.getFluidJumpThreshold()) { +- this.setDeltaMovement(this.getDeltaMovement().multiply(0.5, 0.8F, 0.5)); +- Vec3 fluidFallingAdjustedMovement1 = this.getFluidFallingAdjustedMovement(d, flag, this.getDeltaMovement()); +- this.setDeltaMovement(fluidFallingAdjustedMovement1); ++ this.setDeltaMovement(this.getDeltaMovement().multiply(0.5D, 0.800000011920929D, 0.5D)); ++ vec3d3 = this.getFluidFallingAdjustedMovement(d0, flag, this.getDeltaMovement()); ++ this.setDeltaMovement(vec3d3); + } else { +- this.setDeltaMovement(this.getDeltaMovement().scale(0.5)); ++ this.setDeltaMovement(this.getDeltaMovement().scale(0.5D)); + } + + if (!this.isNoGravity()) { +- this.setDeltaMovement(this.getDeltaMovement().add(0.0, -d / 4.0, 0.0)); ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -d0 / 4.0D, 0.0D)); + } + +- Vec3 fluidFallingAdjustedMovement1 = this.getDeltaMovement(); +- if (this.horizontalCollision +- && this.isFree(fluidFallingAdjustedMovement1.x, fluidFallingAdjustedMovement1.y + 0.6F - this.getY() + yx, fluidFallingAdjustedMovement1.z) +- ) +- { +- this.setDeltaMovement(fluidFallingAdjustedMovement1.x, 0.3F, fluidFallingAdjustedMovement1.z); ++ vec3d3 = this.getDeltaMovement(); ++ if (this.horizontalCollision && this.isFree(vec3d3.x, vec3d3.y + 0.6000000238418579D - this.getY() + d1, vec3d3.z)) { ++ this.setDeltaMovement(vec3d3.x, 0.30000001192092896D, vec3d3.z); + } + } else if (this.isFallFlying()) { + this.checkSlowFallDistance(); +- Vec3 deltaMovement1 = this.getDeltaMovement(); +- Vec3 lookAngle = this.getLookAngle(); +- float fx = this.getXRot() * (float) (Math.PI / 180.0); +- double squareRoot = Math.sqrt(lookAngle.x * lookAngle.x + lookAngle.z * lookAngle.z); +- double d1 = deltaMovement1.horizontalDistance(); +- double len = lookAngle.length(); +- double cos = Math.cos((double)fx); +- double var35 = cos * cos * Math.min(1.0, len / 0.4); +- Vec3 var22 = this.getDeltaMovement().add(0.0, d * (-1.0 + var35 * 0.75), 0.0); +- if (var22.y < 0.0 && squareRoot > 0.0) { +- double d2 = var22.y * -0.1 * var35; +- var22 = var22.add(lookAngle.x * d2 / squareRoot, d2, lookAngle.z * d2 / squareRoot); ++ Vec3 vec3d4 = this.getDeltaMovement(); ++ Vec3 vec3d5 = this.getLookAngle(); ++ ++ f = this.getXRot() * 0.017453292F; ++ double d2 = Math.sqrt(vec3d5.x * vec3d5.x + vec3d5.z * vec3d5.z); ++ double d3 = vec3d4.horizontalDistance(); ++ double d4 = vec3d5.length(); ++ double d5 = Math.cos((double) f); ++ ++ d5 = d5 * d5 * Math.min(1.0D, d4 / 0.4D); ++ vec3d4 = this.getDeltaMovement().add(0.0D, d0 * (-1.0D + d5 * 0.75D), 0.0D); ++ double d6; ++ ++ if (vec3d4.y < 0.0D && d2 > 0.0D) { ++ d6 = vec3d4.y * -0.1D * d5; ++ vec3d4 = vec3d4.add(vec3d5.x * d6 / d2, d6, vec3d5.z * d6 / d2); + } + +- if (fx < 0.0F && squareRoot > 0.0) { +- double d2 = d1 * (double)(-Mth.sin(fx)) * 0.04; +- var22 = var22.add(-lookAngle.x * d2 / squareRoot, d2 * 3.2, -lookAngle.z * d2 / squareRoot); ++ if (f < 0.0F && d2 > 0.0D) { ++ d6 = d3 * (double) (-Mth.sin(f)) * 0.04D; ++ vec3d4 = vec3d4.add(-vec3d5.x * d6 / d2, d6 * 3.2D, -vec3d5.z * d6 / d2); + } + +- if (squareRoot > 0.0) { +- var22 = var22.add((lookAngle.x / squareRoot * d1 - var22.x) * 0.1, 0.0, (lookAngle.z / squareRoot * d1 - var22.z) * 0.1); ++ if (d2 > 0.0D) { ++ vec3d4 = vec3d4.add((vec3d5.x / d2 * d3 - vec3d4.x) * 0.1D, 0.0D, (vec3d5.z / d2 * d3 - vec3d4.z) * 0.1D); + } + +- this.setDeltaMovement(var22.multiply(0.99F, 0.98F, 0.99F)); +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.setDeltaMovement(vec3d4.multiply(0.9900000095367432D, 0.9800000190734863D, 0.9900000095367432D)); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + if (this.horizontalCollision && !this.level().isClientSide) { +- double d2 = this.getDeltaMovement().horizontalDistance(); +- double d3 = d1 - d2; +- float f3 = (float)(d3 * 10.0 - 3.0); ++ d6 = this.getDeltaMovement().horizontalDistance(); ++ double d7 = d3 - d6; ++ float f3 = (float) (d7 * 10.0D - 3.0D); ++ + if (f3 > 0.0F) { +- this.playSound(this.getFallDamageSound((int)f3), 1.0F, 1.0F); ++ this.playSound(this.getFallDamageSound((int) f3), 1.0F, 1.0F); + this.hurt(this.damageSources().flyIntoWall(), f3); + } + } + + if (this.onGround() && !this.level().isClientSide) { ++ if (getSharedFlag(7) && !CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) // CraftBukkit + this.setSharedFlag(7, false); + } + } else { +- BlockPos blockPosBelowThatAffectsMyMovement = this.getBlockPosBelowThatAffectsMyMovement(); +- float friction = this.level().getBlockState(blockPosBelowThatAffectsMyMovement).getBlock().getFriction(); +- float fxx = this.onGround() ? friction * 0.91F : 0.91F; +- Vec3 vec3 = this.handleRelativeFrictionAndCalculateMovement(travelVector, friction); +- double d4 = vec3.y; ++ BlockPos blockposition = this.getBlockPosBelowThatAffectsMyMovement(); ++ float f4 = this.level().getBlockState(blockposition).getBlock().getFriction(); ++ ++ f = this.onGround() ? f4 * 0.91F : 0.91F; ++ Vec3 vec3d6 = this.handleRelativeFrictionAndCalculateMovement(travelVector, f4); ++ double d8 = vec3d6.y; ++ + if (this.hasEffect(MobEffects.LEVITATION)) { +- d4 += (0.05 * (double)(this.getEffect(MobEffects.LEVITATION).getAmplifier() + 1) - vec3.y) * 0.2; +- } else if (this.level().isClientSide && !this.level().hasChunkAt(blockPosBelowThatAffectsMyMovement)) { +- if (this.getY() > (double)this.level().getMinBuildHeight()) { +- d4 = -0.1; ++ d8 += (0.05D * (double) (this.getEffect(MobEffects.LEVITATION).getAmplifier() + 1) - vec3d6.y) * 0.2D; ++ } else if (this.level().isClientSide && !this.level().hasChunkAt(blockposition)) { ++ if (this.getY() > (double) this.level().getMinBuildHeight()) { ++ d8 = -0.1D; + } else { +- d4 = 0.0; ++ d8 = 0.0D; + } + } else if (!this.isNoGravity()) { +- d4 -= d; ++ d8 -= d0; + } + + if (this.shouldDiscardFriction()) { +- this.setDeltaMovement(vec3.x, d4, vec3.z); ++ this.setDeltaMovement(vec3d6.x, d8, vec3d6.z); + } else { +- this.setDeltaMovement(vec3.x * (double)fxx, d4 * 0.98F, vec3.z * (double)fxx); ++ this.setDeltaMovement(vec3d6.x * (double) f, d8 * 0.9800000190734863D, vec3d6.z * (double) f); + } + } + } + +- this.calculateEntityAnimation(this instanceof FlyingAnimal); ++ this.calculateEntityAnimation(this instanceof EntityBird); + } + +- private void travelRidden(Player player, Vec3 travelVector) { +- Vec3 riddenInput = this.getRiddenInput(player, travelVector); +- this.tickRidden(player, riddenInput); ++ private void travelRidden(net.minecraft.world.entity.player.Player player, Vec3 travelVector) { ++ Vec3 vec3d1 = this.getRiddenInput(player, travelVector); ++ ++ this.tickRidden(player, vec3d1); + if (this.isControlledByLocalInstance()) { + this.setSpeed(this.getRiddenSpeed(player)); +- this.travel(riddenInput); ++ this.travel(vec3d1); + } else { + this.calculateEntityAnimation(false); + this.setDeltaMovement(Vec3.ZERO); + this.tryCheckInsideBlocks(); + } +- } + +- protected void tickRidden(Player player, Vec3 travelVector) { + } + +- protected Vec3 getRiddenInput(Player player, Vec3 travelVector) { ++ protected void tickRidden(net.minecraft.world.entity.player.Player player, Vec3 travelVector) {} ++ ++ protected Vec3 getRiddenInput(net.minecraft.world.entity.player.Player player, Vec3 travelVector) { + return travelVector; + } + +- protected float getRiddenSpeed(Player player) { ++ protected float getRiddenSpeed(net.minecraft.world.entity.player.Player player) { + return this.getSpeed(); + } + + public void calculateEntityAnimation(boolean includeHeight) { +- float f = (float)Mth.length(this.getX() - this.xo, includeHeight ? this.getY() - this.yo : 0.0, this.getZ() - this.zo); ++ float f = (float) Mth.length(this.getX() - this.xo, includeHeight ? this.getY() - this.yo : 0.0D, this.getZ() - this.zo); ++ + this.updateWalkAnimation(f); + } + + protected void updateWalkAnimation(float partialTick) { +- float min = Math.min(partialTick * 4.0F, 1.0F); +- this.walkAnimation.update(min, 0.4F); ++ float f1 = Math.min(partialTick * 4.0F, 1.0F); ++ ++ this.walkAnimation.update(f1, 0.4F); + } + + public Vec3 handleRelativeFrictionAndCalculateMovement(Vec3 deltaMovement, float friction) { + this.moveRelative(this.getFrictionInfluencedSpeed(friction), deltaMovement); + this.setDeltaMovement(this.handleOnClimbable(this.getDeltaMovement())); +- this.move(MoverType.SELF, this.getDeltaMovement()); +- Vec3 deltaMovement1 = this.getDeltaMovement(); +- if ((this.horizontalCollision || this.jumping) +- && (this.onClimbable() || this.getFeetBlockState().is(Blocks.POWDER_SNOW) && PowderSnowBlock.canEntityWalkOnPowderSnow(this))) { +- deltaMovement1 = new Vec3(deltaMovement1.x, 0.2, deltaMovement1.z); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); ++ Vec3 vec3d1 = this.getDeltaMovement(); ++ ++ if ((this.horizontalCollision || this.jumping) && (this.onClimbable() || this.getFeetBlockState().is(Blocks.POWDER_SNOW) && PowderSnowBlock.canEntityWalkOnPowderSnow(this))) { ++ vec3d1 = new Vec3(vec3d1.x, 0.2D, vec3d1.z); + } + +- return deltaMovement1; ++ return vec3d1; + } + +- public Vec3 getFluidFallingAdjustedMovement(double gravity, boolean isFalling, Vec3 deltaMovement) { ++ public Vec3 getFluidFallingAdjustedMovement(double gravity, boolean flag, Vec3 isFalling) { + if (!this.isNoGravity() && !this.isSprinting()) { +- double d; +- if (isFalling && Math.abs(deltaMovement.y - 0.005) >= 0.003 && Math.abs(deltaMovement.y - gravity / 16.0) < 0.003) { +- d = -0.003; ++ double d1; ++ ++ if (flag && Math.abs(isFalling.y - 0.005D) >= 0.003D && Math.abs(isFalling.y - gravity / 16.0D) < 0.003D) { ++ d1 = -0.003D; + } else { +- d = deltaMovement.y - gravity / 16.0; ++ d1 = isFalling.y - gravity / 16.0D; + } + +- return new Vec3(deltaMovement.x, d, deltaMovement.z); ++ return new Vec3(isFalling.x, d1, isFalling.z); + } else { +- return deltaMovement; ++ return isFalling; + } + } + +@@ -2246,14 +2818,15 @@ + if (this.onClimbable()) { + this.resetFallDistance(); + float f = 0.15F; +- double d = Mth.clamp(deltaMovement.x, -0.15F, 0.15F); +- double d1 = Mth.clamp(deltaMovement.z, -0.15F, 0.15F); +- double max = Math.max(deltaMovement.y, -0.15F); +- if (max < 0.0 && !this.getFeetBlockState().is(Blocks.SCAFFOLDING) && this.isSuppressingSlidingDownLadder() && this instanceof Player) { +- max = 0.0; ++ double d0 = Mth.clamp(deltaMovement.x, -0.15000000596046448D, 0.15000000596046448D); ++ double d1 = Mth.clamp(deltaMovement.z, -0.15000000596046448D, 0.15000000596046448D); ++ double d2 = Math.max(deltaMovement.y, -0.15000000596046448D); ++ ++ if (d2 < 0.0D && !this.getFeetBlockState().is(Blocks.SCAFFOLDING) && this.isSuppressingSlidingDownLadder() && this instanceof net.minecraft.world.entity.player.Player) { ++ d2 = 0.0D; + } + +- deltaMovement = new Vec3(d, max, d1); ++ deltaMovement = new Vec3(d0, d2, d1); + } + + return deltaMovement; +@@ -2264,7 +2837,7 @@ + } + + protected float getFlyingSpeed() { +- return this.getControllingPassenger() instanceof Player ? this.getSpeed() * 0.1F : 0.02F; ++ return this.getControllingPassenger() instanceof net.minecraft.world.entity.player.Player ? this.getSpeed() * 0.1F : 0.02F; + } + + public float getSpeed() { +@@ -2286,31 +2859,33 @@ + this.updatingUsingItem(); + this.updateSwimAmount(); + if (!this.level().isClientSide) { +- int arrowCount = this.getArrowCount(); +- if (arrowCount > 0) { ++ int i = this.getArrowCount(); ++ ++ if (i > 0) { + if (this.removeArrowTime <= 0) { +- this.removeArrowTime = 20 * (30 - arrowCount); ++ this.removeArrowTime = 20 * (30 - i); + } + +- this.removeArrowTime--; ++ --this.removeArrowTime; + if (this.removeArrowTime <= 0) { +- this.setArrowCount(arrowCount - 1); ++ this.setArrowCount(i - 1); + } + } + +- int stingerCount = this.getStingerCount(); +- if (stingerCount > 0) { ++ int j = this.getStingerCount(); ++ ++ if (j > 0) { + if (this.removeStingerTime <= 0) { +- this.removeStingerTime = 20 * (30 - stingerCount); ++ this.removeStingerTime = 20 * (30 - j); + } + +- this.removeStingerTime--; ++ --this.removeStingerTime; + if (this.removeStingerTime <= 0) { +- this.setStingerCount(stingerCount - 1); ++ this.setStingerCount(j - 1); + } + } + +- this.detectEquipmentUpdates(); ++ this.detectEquipmentUpdatesPublic(); // CraftBukkit + if (this.tickCount % 20 == 0) { + this.getCombatTracker().recheckStatus(); + } +@@ -2324,19 +2899,22 @@ + this.aiStep(); + } + +- double d = this.getX() - this.xo; ++ double d0 = this.getX() - this.xo; + double d1 = this.getZ() - this.zo; +- float f = (float)(d * d + d1 * d1); ++ float f = (float) (d0 * d0 + d1 * d1); + float f1 = this.yBodyRot; + float f2 = 0.0F; ++ + this.oRun = this.run; + float f3 = 0.0F; ++ + if (f > 0.0025000002F) { + f3 = 1.0F; +- f2 = (float)Math.sqrt((double)f) * 3.0F; +- float f4 = (float)Mth.atan2(d1, d) * (180.0F / (float)Math.PI) - 90.0F; +- float abs = Mth.abs(Mth.wrapDegrees(this.getYRot()) - f4); +- if (95.0F < abs && abs < 265.0F) { ++ f2 = (float) Math.sqrt((double) f) * 3.0F; ++ float f4 = (float) Mth.atan2(d1, d0) * 57.295776F - 90.0F; ++ float f5 = Mth.abs(Mth.wrapDegrees(this.getYRot()) - f4); ++ ++ if (95.0F < f5 && f5 < 265.0F) { + f1 = f4 - 180.0F; + } else { + f1 = f4; +@@ -2351,9 +2929,9 @@ + f3 = 0.0F; + } + +- this.run = this.run + (f3 - this.run) * 0.3F; ++ this.run += (f3 - this.run) * 0.3F; + this.level().getProfiler().push("headTurn"); +- float var12 = this.tickHeadTurn(f1, f2); ++ f2 = this.tickHeadTurn(f1, f2); + this.level().getProfiler().pop(); + this.level().getProfiler().push("rangeChecks"); + +@@ -2390,9 +2968,9 @@ + } + + this.level().getProfiler().pop(); +- this.animStep += var12; ++ this.animStep += f2; + if (this.isFallFlying()) { +- this.fallFlyTicks++; ++ ++this.fallFlyTicks; + } else { + this.fallFlyTicks = 0; + } +@@ -2404,46 +2982,53 @@ + this.refreshDirtyAttributes(); + } + +- private void detectEquipmentUpdates() { ++ public void detectEquipmentUpdatesPublic() { // CraftBukkit + Map map = this.collectEquipmentChanges(); ++ + if (map != null) { + this.handleHandSwap(map); + if (!map.isEmpty()) { + this.handleEquipmentChanges(map); + } + } ++ + } + + @Nullable + private Map collectEquipmentChanges() { + Map map = null; ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ int i = aenumitemslot.length; + +- for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) { +- ItemStack lastHandItem; +- switch (equipmentSlot.getType()) { ++ for (int j = 0; j < i; ++j) { ++ EquipmentSlot enumitemslot = aenumitemslot[j]; ++ ItemStack itemstack; ++ ++ switch (enumitemslot.getType()) { + case HAND: +- lastHandItem = this.getLastHandItem(equipmentSlot); ++ itemstack = this.getLastHandItem(enumitemslot); + break; + case ARMOR: +- lastHandItem = this.getLastArmorItem(equipmentSlot); ++ itemstack = this.getLastArmorItem(enumitemslot); + break; + default: + continue; + } + +- ItemStack itemBySlot = this.getItemBySlot(equipmentSlot); +- if (this.equipmentHasChanged(lastHandItem, itemBySlot)) { ++ ItemStack itemstack1 = this.getItemBySlot(enumitemslot); ++ ++ if (this.equipmentHasChanged(itemstack, itemstack1)) { + if (map == null) { + map = Maps.newEnumMap(EquipmentSlot.class); + } + +- map.put(equipmentSlot, itemBySlot); +- if (!lastHandItem.isEmpty()) { +- this.getAttributes().removeAttributeModifiers(lastHandItem.getAttributeModifiers(equipmentSlot)); ++ map.put(enumitemslot, itemstack1); ++ if (!itemstack.isEmpty()) { ++ this.getAttributes().removeAttributeModifiers(itemstack.getAttributeModifiers(enumitemslot)); + } + +- if (!itemBySlot.isEmpty()) { +- this.getAttributes().addTransientAttributeModifiers(itemBySlot.getAttributeModifiers(equipmentSlot)); ++ if (!itemstack1.isEmpty()) { ++ this.getAttributes().addTransientAttributeModifiers(itemstack1.getAttributeModifiers(enumitemslot)); + } + } + } +@@ -2456,38 +3041,40 @@ + } + + private void handleHandSwap(Map hands) { +- ItemStack itemStack = hands.get(EquipmentSlot.MAINHAND); +- ItemStack itemStack1 = hands.get(EquipmentSlot.OFFHAND); +- if (itemStack != null +- && itemStack1 != null +- && ItemStack.matches(itemStack, this.getLastHandItem(EquipmentSlot.OFFHAND)) +- && ItemStack.matches(itemStack1, this.getLastHandItem(EquipmentSlot.MAINHAND))) { +- ((ServerLevel)this.level()).getChunkSource().broadcast(this, new ClientboundEntityEventPacket(this, (byte)55)); ++ ItemStack itemstack = (ItemStack) hands.get(EquipmentSlot.MAINHAND); ++ ItemStack itemstack1 = (ItemStack) hands.get(EquipmentSlot.OFFHAND); ++ ++ if (itemstack != null && itemstack1 != null && ItemStack.matches(itemstack, this.getLastHandItem(EquipmentSlot.OFFHAND)) && ItemStack.matches(itemstack1, this.getLastHandItem(EquipmentSlot.MAINHAND))) { ++ ((ServerLevel) this.level()).getChunkSource().broadcast(this, new ClientboundEntityEventPacket(this, (byte) 55)); + hands.remove(EquipmentSlot.MAINHAND); + hands.remove(EquipmentSlot.OFFHAND); +- this.setLastHandItem(EquipmentSlot.MAINHAND, itemStack.copy()); +- this.setLastHandItem(EquipmentSlot.OFFHAND, itemStack1.copy()); ++ this.setLastHandItem(EquipmentSlot.MAINHAND, itemstack.copy()); ++ this.setLastHandItem(EquipmentSlot.OFFHAND, itemstack1.copy()); + } ++ + } + + private void handleEquipmentChanges(Map equipments) { + List> list = Lists.newArrayListWithCapacity(equipments.size()); +- equipments.forEach((slot, stack) -> { +- ItemStack itemStack = stack.copy(); +- list.add(Pair.of(slot, itemStack)); +- switch (slot.getType()) { ++ ++ equipments.forEach((enumitemslot, itemstack) -> { ++ ItemStack itemstack1 = itemstack.copy(); ++ ++ list.add(Pair.of(enumitemslot, itemstack1)); ++ switch (enumitemslot.getType()) { + case HAND: +- this.setLastHandItem(slot, itemStack); ++ this.setLastHandItem(enumitemslot, itemstack1); + break; + case ARMOR: +- this.setLastArmorItem(slot, itemStack); ++ this.setLastArmorItem(enumitemslot, itemstack1); + } ++ + }); +- ((ServerLevel)this.level()).getChunkSource().broadcast(this, new ClientboundSetEquipmentPacket(this.getId(), list)); ++ ((ServerLevel) this.level()).getChunkSource().broadcast(this, new ClientboundSetEquipmentPacket(this.getId(), list)); + } + + private ItemStack getLastArmorItem(EquipmentSlot slot) { +- return this.lastArmorItemStacks.get(slot.getIndex()); ++ return (ItemStack) this.lastArmorItemStacks.get(slot.getIndex()); + } + + private void setLastArmorItem(EquipmentSlot slot, ItemStack stack) { +@@ -2495,7 +3082,7 @@ + } + + private ItemStack getLastHandItem(EquipmentSlot slot) { +- return this.lastHandItemStacks.get(slot.getIndex()); ++ return (ItemStack) this.lastHandItemStacks.get(slot.getIndex()); + } + + private void setLastHandItem(EquipmentSlot slot, ItemStack stack) { +@@ -2503,15 +3090,18 @@ + } + + protected float tickHeadTurn(float yRot, float animStep) { +- float f = Mth.wrapDegrees(yRot - this.yBodyRot); +- this.yBodyRot += f * 0.3F; +- float f1 = Mth.wrapDegrees(this.getYRot() - this.yBodyRot); +- float maxHeadRotationRelativeToBody = this.getMaxHeadRotationRelativeToBody(); +- if (Math.abs(f1) > maxHeadRotationRelativeToBody) { +- this.yBodyRot = this.yBodyRot + (f1 - (float)Mth.sign((double)f1) * maxHeadRotationRelativeToBody); ++ float f2 = Mth.wrapDegrees(yRot - this.yBodyRot); ++ ++ this.yBodyRot += f2 * 0.3F; ++ float f3 = Mth.wrapDegrees(this.getYRot() - this.yBodyRot); ++ float f4 = this.getMaxHeadRotationRelativeToBody(); ++ ++ if (Math.abs(f3) > f4) { ++ this.yBodyRot += f3 - (float) Mth.sign((double) f3) * f4; + } + +- boolean flag = f1 < -90.0F || f1 >= 90.0F; ++ boolean flag = f3 < -90.0F || f3 >= 90.0F; ++ + if (flag) { + animStep *= -1.0F; + } +@@ -2525,7 +3115,7 @@ + + public void aiStep() { + if (this.noJumpDelay > 0) { +- this.noJumpDelay--; ++ --this.noJumpDelay; + } + + if (this.isControlledByLocalInstance()) { +@@ -2535,33 +3125,34 @@ + + if (this.lerpSteps > 0) { + this.lerpPositionAndRotationStep(this.lerpSteps, this.lerpX, this.lerpY, this.lerpZ, this.lerpYRot, this.lerpXRot); +- this.lerpSteps--; ++ --this.lerpSteps; + } else if (!this.isEffectiveAi()) { +- this.setDeltaMovement(this.getDeltaMovement().scale(0.98)); ++ this.setDeltaMovement(this.getDeltaMovement().scale(0.98D)); + } + + if (this.lerpHeadSteps > 0) { + this.lerpHeadRotationStep(this.lerpHeadSteps, this.lerpYHeadRot); +- this.lerpHeadSteps--; ++ --this.lerpHeadSteps; + } + +- Vec3 deltaMovement = this.getDeltaMovement(); +- double d = deltaMovement.x; +- double d1 = deltaMovement.y; +- double d2 = deltaMovement.z; +- if (Math.abs(deltaMovement.x) < 0.003) { +- d = 0.0; ++ Vec3 vec3d = this.getDeltaMovement(); ++ double d0 = vec3d.x; ++ double d1 = vec3d.y; ++ double d2 = vec3d.z; ++ ++ if (Math.abs(vec3d.x) < 0.003D) { ++ d0 = 0.0D; + } + +- if (Math.abs(deltaMovement.y) < 0.003) { +- d1 = 0.0; ++ if (Math.abs(vec3d.y) < 0.003D) { ++ d1 = 0.0D; + } + +- if (Math.abs(deltaMovement.z) < 0.003) { +- d2 = 0.0; ++ if (Math.abs(vec3d.z) < 0.003D) { ++ d2 = 0.0D; + } + +- this.setDeltaMovement(d, d1, d2); ++ this.setDeltaMovement(d0, d1, d2); + this.level().getProfiler().push("ai"); + if (this.isImmobile()) { + this.jumping = false; +@@ -2576,26 +3167,24 @@ + this.level().getProfiler().pop(); + this.level().getProfiler().push("jump"); + if (this.jumping && this.isAffectedByFluids()) { +- double fluidHeight; ++ double d3; ++ + if (this.isInLava()) { +- fluidHeight = this.getFluidHeight(FluidTags.LAVA); ++ d3 = this.getFluidHeight(FluidTags.LAVA); + } else { +- fluidHeight = this.getFluidHeight(FluidTags.WATER); ++ d3 = this.getFluidHeight(FluidTags.WATER); + } + +- boolean flag = this.isInWater() && fluidHeight > 0.0; +- double fluidJumpThreshold = this.getFluidJumpThreshold(); +- if (!flag || this.onGround() && !(fluidHeight > fluidJumpThreshold)) { +- if (!this.isInLava() || this.onGround() && !(fluidHeight > fluidJumpThreshold)) { +- if ((this.onGround() || flag && fluidHeight <= fluidJumpThreshold) && this.noJumpDelay == 0) { +- this.jumpFromGround(); +- this.noJumpDelay = 10; +- } +- } else { +- this.jumpInLiquid(FluidTags.LAVA); +- } +- } else { ++ boolean flag = this.isInWater() && d3 > 0.0D; ++ double d4 = this.getFluidJumpThreshold(); ++ ++ if (flag && (!this.onGround() || d3 > d4)) { + this.jumpInLiquid(FluidTags.WATER); ++ } else if (this.isInLava() && (!this.onGround() || d3 > d4)) { ++ this.jumpInLiquid(FluidTags.LAVA); ++ } else if ((this.onGround() || flag && d3 <= d4) && this.noJumpDelay == 0) { ++ this.jumpFromGround(); ++ this.noJumpDelay = 10; + } + } else { + this.noJumpDelay = 0; +@@ -2606,29 +3195,38 @@ + this.xxa *= 0.98F; + this.zza *= 0.98F; + this.updateFallFlying(); +- AABB boundingBox = this.getBoundingBox(); +- Vec3 vec3 = new Vec3((double)this.xxa, (double)this.yya, (double)this.zza); ++ AABB axisalignedbb = this.getBoundingBox(); ++ Vec3 vec3d1 = new Vec3((double) this.xxa, (double) this.yya, (double) this.zza); ++ + if (this.hasEffect(MobEffects.SLOW_FALLING) || this.hasEffect(MobEffects.LEVITATION)) { + this.resetFallDistance(); + } + +- label104: { +- if (this.getControllingPassenger() instanceof Player player && this.isAlive()) { +- this.travelRidden(player, vec3); +- break label104; ++ label104: ++ { ++ LivingEntity entityliving = this.getControllingPassenger(); ++ ++ if (entityliving instanceof net.minecraft.world.entity.player.Player) { ++ net.minecraft.world.entity.player.Player entityhuman = (net.minecraft.world.entity.player.Player) entityliving; ++ ++ if (this.isAlive()) { ++ this.travelRidden(entityhuman, vec3d1); ++ break label104; ++ } + } + +- this.travel(vec3); ++ this.travel(vec3d1); + } + + this.level().getProfiler().pop(); + this.level().getProfiler().push("freezing"); + if (!this.level().isClientSide && !this.isDeadOrDying()) { +- int ticksFrozen = this.getTicksFrozen(); ++ int i = this.getTicksFrozen(); ++ + if (this.isInPowderSnow && this.canFreeze()) { +- this.setTicksFrozen(Math.min(this.getTicksRequiredToFreeze(), ticksFrozen + 1)); ++ this.setTicksFrozen(Math.min(this.getTicksRequiredToFreeze(), i + 1)); + } else { +- this.setTicksFrozen(Math.max(0, ticksFrozen - 2)); ++ this.setTicksFrozen(Math.max(0, i - 2)); + } + } + +@@ -2641,8 +3239,8 @@ + this.level().getProfiler().pop(); + this.level().getProfiler().push("push"); + if (this.autoSpinAttackTicks > 0) { +- this.autoSpinAttackTicks--; +- this.checkAutoSpinAttack(boundingBox, this.getBoundingBox()); ++ --this.autoSpinAttackTicks; ++ this.checkAutoSpinAttack(axisalignedbb, this.getBoundingBox()); + } + + this.pushEntities(); +@@ -2650,6 +3248,7 @@ + if (!this.level().isClientSide && this.isSensitiveToWater() && this.isInWaterRainOrBubble()) { + this.hurt(this.damageSources().drown(), 1.0F); + } ++ + } + + public boolean isSensitiveToWater() { +@@ -2657,72 +3256,94 @@ + } + + private void updateFallFlying() { +- boolean sharedFlag = this.getSharedFlag(7); +- if (sharedFlag && !this.onGround() && !this.isPassenger() && !this.hasEffect(MobEffects.LEVITATION)) { +- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.CHEST); +- if (itemBySlot.is(Items.ELYTRA) && ElytraItem.isFlyEnabled(itemBySlot)) { +- sharedFlag = true; ++ boolean flag = this.getSharedFlag(7); ++ ++ if (flag && !this.onGround() && !this.isPassenger() && !this.hasEffect(MobEffects.LEVITATION)) { ++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.CHEST); ++ ++ if (itemstack.is(Items.ELYTRA) && ElytraItem.isFlyEnabled(itemstack)) { ++ flag = true; + int i = this.fallFlyTicks + 1; ++ + if (!this.level().isClientSide && i % 10 == 0) { +- int i1 = i / 10; +- if (i1 % 2 == 0) { +- itemBySlot.hurtAndBreak(1, this, entity -> entity.broadcastBreakEvent(EquipmentSlot.CHEST)); ++ int j = i / 10; ++ ++ if (j % 2 == 0) { ++ itemstack.hurtAndBreak(1, this, (entityliving) -> { ++ entityliving.broadcastBreakEvent(EquipmentSlot.CHEST); ++ }); + } + + this.gameEvent(GameEvent.ELYTRA_GLIDE); + } + } else { +- sharedFlag = false; ++ flag = false; + } + } else { +- sharedFlag = false; ++ flag = false; + } + + if (!this.level().isClientSide) { +- this.setSharedFlag(7, sharedFlag); ++ if (flag != this.getSharedFlag(7) && !CraftEventFactory.callToggleGlideEvent(this, flag).isCancelled()) // CraftBukkit ++ this.setSharedFlag(7, flag); + } +- } + +- protected void serverAiStep() { + } + ++ protected void serverAiStep() {} ++ + protected void pushEntities() { + if (this.level().isClientSide()) { +- this.level().getEntities(EntityTypeTest.forClass(Player.class), this.getBoundingBox(), EntitySelector.pushableBy(this)).forEach(this::doPush); ++ this.level().getEntities(EntityTypeTest.forClass(net.minecraft.world.entity.player.Player.class), this.getBoundingBox(), EntitySelector.pushableBy(this)).forEach(this::doPush); + } else { +- List entities = this.level().getEntities(this, this.getBoundingBox(), EntitySelector.pushableBy(this)); +- if (!entities.isEmpty()) { +- int _int = this.level().getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING); +- if (_int > 0 && entities.size() > _int - 1 && this.random.nextInt(4) == 0) { +- int i = 0; ++ List list = this.level().getEntities((Entity) this, this.getBoundingBox(), EntitySelector.pushableBy(this)); + +- for (Entity entity : entities) { ++ if (!list.isEmpty()) { ++ int i = this.level().getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING); ++ ++ if (i > 0 && list.size() > i - 1 && this.random.nextInt(4) == 0) { ++ int j = 0; ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ + if (!entity.isPassenger()) { +- i++; ++ ++j; + } + } + +- if (i > _int - 1) { ++ if (j > i - 1) { + this.hurt(this.damageSources().cramming(), 6.0F); + } + } + +- for (Entity entity1 : entities) { ++ Iterator iterator1 = list.iterator(); ++ ++ while (iterator1.hasNext()) { ++ Entity entity1 = (Entity) iterator1.next(); ++ + this.doPush(entity1); + } + } ++ + } + } + + protected void checkAutoSpinAttack(AABB boundingBoxBeforeSpin, AABB boundingBoxAfterSpin) { +- AABB aABB = boundingBoxBeforeSpin.minmax(boundingBoxAfterSpin); +- List entities = this.level().getEntities(this, aABB); +- if (!entities.isEmpty()) { +- for (Entity entity : entities) { ++ AABB axisalignedbb2 = boundingBoxBeforeSpin.minmax(boundingBoxAfterSpin); ++ List list = this.level().getEntities(this, axisalignedbb2); ++ ++ if (!list.isEmpty()) { ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ + if (entity instanceof LivingEntity) { +- this.doAutoAttackOnTouch((LivingEntity)entity); ++ this.doAutoAttackOnTouch((LivingEntity) entity); + this.autoSpinAttackTicks = 0; +- this.setDeltaMovement(this.getDeltaMovement().scale(-0.2)); ++ this.setDeltaMovement(this.getDeltaMovement().scale(-0.2D)); + break; + } + } +@@ -2733,26 +3354,28 @@ + if (!this.level().isClientSide && this.autoSpinAttackTicks <= 0) { + this.setLivingEntityFlag(4, false); + } ++ + } + + protected void doPush(Entity entity) { + entity.push(this); + } + +- protected void doAutoAttackOnTouch(LivingEntity target) { +- } ++ protected void doAutoAttackOnTouch(LivingEntity target) {} + + public boolean isAutoSpinAttack() { +- return (this.entityData.get(DATA_LIVING_ENTITY_FLAGS) & 4) != 0; ++ return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 4) != 0; + } + + @Override + public void stopRiding() { +- Entity vehicle = this.getVehicle(); ++ Entity entity = this.getVehicle(); ++ + super.stopRiding(); +- if (vehicle != null && vehicle != this.getVehicle() && !this.level().isClientSide) { +- this.dismountVehicle(vehicle); ++ if (entity != null && entity != this.getVehicle() && !this.level().isClientSide) { ++ this.dismountVehicle(entity); + } ++ + } + + @Override +@@ -2764,12 +3387,12 @@ + } + + @Override +- public void lerpTo(double d, double d1, double d2, float f, float f1, int i) { +- this.lerpX = d; ++ public void lerpTo(double d0, double d1, double d2, float f, float f1, int i) { ++ this.lerpX = d0; + this.lerpY = d1; + this.lerpZ = d2; +- this.lerpYRot = (double)f; +- this.lerpXRot = (double)f1; ++ this.lerpYRot = (double) f; ++ this.lerpXRot = (double) f1; + this.lerpSteps = i; + } + +@@ -2790,17 +3413,17 @@ + + @Override + public float lerpTargetXRot() { +- return this.lerpSteps > 0 ? (float)this.lerpXRot : this.getXRot(); ++ return this.lerpSteps > 0 ? (float) this.lerpXRot : this.getXRot(); + } + + @Override + public float lerpTargetYRot() { +- return this.lerpSteps > 0 ? (float)this.lerpYRot : this.getYRot(); ++ return this.lerpSteps > 0 ? (float) this.lerpYRot : this.getYRot(); + } + + @Override + public void lerpHeadTo(float yaw, int pitch) { +- this.lerpYHeadRot = (double)yaw; ++ this.lerpYHeadRot = (double) yaw; + this.lerpHeadSteps = pitch; + } + +@@ -2809,28 +3432,29 @@ + } + + public void onItemPickup(ItemEntity itemEntity) { +- Entity owner = itemEntity.getOwner(); +- if (owner instanceof ServerPlayer) { +- CriteriaTriggers.THROWN_ITEM_PICKED_UP_BY_ENTITY.trigger((ServerPlayer)owner, itemEntity.getItem(), this); ++ Entity entity = itemEntity.getOwner(); ++ ++ if (entity instanceof ServerPlayer) { ++ CriteriaTriggers.THROWN_ITEM_PICKED_UP_BY_ENTITY.trigger((ServerPlayer) entity, itemEntity.getItem(), this); + } ++ + } + + public void take(Entity entity, int amount) { +- if (!entity.isRemoved() +- && !this.level().isClientSide +- && (entity instanceof ItemEntity || entity instanceof AbstractArrow || entity instanceof ExperienceOrb)) { +- ((ServerLevel)this.level()).getChunkSource().broadcast(entity, new ClientboundTakeItemEntityPacket(entity.getId(), this.getId(), amount)); ++ if (!entity.isRemoved() && !this.level().isClientSide && (entity instanceof ItemEntity || entity instanceof AbstractArrow || entity instanceof ExperienceOrb)) { ++ ((ServerLevel) this.level()).getChunkSource().broadcast(entity, new ClientboundTakeItemEntityPacket(entity.getId(), this.getId(), amount)); + } ++ + } + + public boolean hasLineOfSight(Entity entity) { + if (entity.level() != this.level()) { + return false; + } else { +- Vec3 vec3 = new Vec3(this.getX(), this.getEyeY(), this.getZ()); +- Vec3 vec31 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); +- return !(vec31.distanceTo(vec3) > 128.0) +- && this.level().clip(new ClipContext(vec3, vec31, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() == HitResult.Type.MISS; ++ Vec3 vec3d = new Vec3(this.getX(), this.getEyeY(), this.getZ()); ++ Vec3 vec3d1 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); ++ ++ return vec3d1.distanceTo(vec3d) > 128.0D ? false : this.level().clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() == HitResult.EnumMovingObjectType.MISS; + } + } + +@@ -2840,25 +3464,33 @@ + } + + public float getAttackAnim(float partialTick) { +- float f = this.attackAnim - this.oAttackAnim; +- if (f < 0.0F) { +- f++; ++ float f1 = this.attackAnim - this.oAttackAnim; ++ ++ if (f1 < 0.0F) { ++ ++f1; + } + +- return this.oAttackAnim + f * partialTick; ++ return this.oAttackAnim + f1 * partialTick; + } + + @Override + public boolean isPickable() { +- return !this.isRemoved(); ++ return !this.isRemoved() && this.collides; // CraftBukkit + } + + @Override + public boolean isPushable() { +- return this.isAlive() && !this.isSpectator() && !this.onClimbable(); ++ return this.isAlive() && !this.isSpectator() && !this.onClimbable() && this.collides; // CraftBukkit + } + ++ // CraftBukkit start - collidable API + @Override ++ public boolean canCollideWithBukkit(Entity entity) { ++ return isPushable() && this.collides != this.collidableExemptions.contains(entity.getUUID()); ++ } ++ // CraftBukkit end ++ ++ @Override + public float getYHeadRot() { + return this.yHeadRot; + } +@@ -2879,7 +3511,7 @@ + } + + public static Vec3 resetForwardDirectionOfRelativePortalPosition(Vec3 relativePortalPosition) { +- return new Vec3(relativePortalPosition.x, relativePortalPosition.y, 0.0); ++ return new Vec3(relativePortalPosition.x, relativePortalPosition.y, 0.0D); + } + + public float getAbsorptionAmount() { +@@ -2894,11 +3526,9 @@ + this.absorptionAmount = f; + } + +- public void onEnterCombat() { +- } ++ public void onEnterCombat() {} + +- public void onLeaveCombat() { +- } ++ public void onLeaveCombat() {} + + protected void updateEffectVisibility() { + this.effectsDirty = true; +@@ -2907,11 +3537,11 @@ + public abstract HumanoidArm getMainArm(); + + public boolean isUsingItem() { +- return (this.entityData.get(DATA_LIVING_ENTITY_FLAGS) & 1) > 0; ++ return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 1) > 0; + } + +- public InteractionHand getUsedItemHand() { +- return (this.entityData.get(DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND; ++ public EnumHand getUsedItemHand() { ++ return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? EnumHand.OFF_HAND : EnumHand.MAIN_HAND; + } + + private void updatingUsingItem() { +@@ -2923,6 +3553,7 @@ + this.stopUsingItem(); + } + } ++ + } + + protected void updateUsingItem(ItemStack usingItem) { +@@ -2934,14 +3565,16 @@ + if (--this.useItemRemaining == 0 && !this.level().isClientSide && !usingItem.useOnRelease()) { + this.completeUsingItem(); + } ++ + } + + private boolean shouldTriggerItemUseEffects() { +- int useItemRemainingTicks = this.getUseItemRemainingTicks(); +- FoodProperties foodProperties = this.useItem.getItem().getFoodProperties(); +- boolean flag = foodProperties != null && foodProperties.isFastFood(); +- flag |= useItemRemainingTicks <= this.useItem.getUseDuration() - 7; +- return flag && useItemRemainingTicks % 4 == 0; ++ int i = this.getUseItemRemainingTicks(); ++ FoodProperties foodinfo = this.useItem.getItem().getFoodProperties(); ++ boolean flag = foodinfo != null && foodinfo.isFastFood(); ++ ++ flag |= i <= this.useItem.getUseDuration() - 7; ++ return flag && i % 4 == 0; + } + + private void updateSwimAmount() { +@@ -2951,40 +3584,45 @@ + } else { + this.swimAmount = Math.max(0.0F, this.swimAmount - 0.09F); + } ++ + } + + protected void setLivingEntityFlag(int key, boolean value) { +- int i = this.entityData.get(DATA_LIVING_ENTITY_FLAGS); ++ byte b0 = (Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS); ++ int j; ++ + if (value) { +- i |= key; ++ j = b0 | key; + } else { +- i &= ~key; ++ j = b0 & ~key; + } + +- this.entityData.set(DATA_LIVING_ENTITY_FLAGS, (byte)i); ++ this.entityData.set(LivingEntity.DATA_LIVING_ENTITY_FLAGS, (byte) j); + } + +- public void startUsingItem(InteractionHand hand) { +- ItemStack itemInHand = this.getItemInHand(hand); +- if (!itemInHand.isEmpty() && !this.isUsingItem()) { +- this.useItem = itemInHand; +- this.useItemRemaining = itemInHand.getUseDuration(); ++ public void startUsingItem(EnumHand hand) { ++ ItemStack itemstack = this.getItemInHand(hand); ++ ++ if (!itemstack.isEmpty() && !this.isUsingItem()) { ++ this.useItem = itemstack; ++ this.useItemRemaining = itemstack.getUseDuration(); + if (!this.level().isClientSide) { + this.setLivingEntityFlag(1, true); +- this.setLivingEntityFlag(2, hand == InteractionHand.OFF_HAND); ++ this.setLivingEntityFlag(2, hand == EnumHand.OFF_HAND); + this.gameEvent(GameEvent.ITEM_INTERACT_START); + } ++ + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { + super.onSyncedDataUpdated(key); +- if (SLEEPING_POS_ID.equals(key)) { ++ if (LivingEntity.SLEEPING_POS_ID.equals(key)) { + if (this.level().isClientSide) { + this.getSleepingPos().ifPresent(this::setPosToBed); + } +- } else if (DATA_LIVING_ENTITY_FLAGS.equals(key) && this.level().isClientSide) { ++ } else if (LivingEntity.DATA_LIVING_ENTITY_FLAGS.equals(key) && this.level().isClientSide) { + if (this.isUsingItem() && this.useItem.isEmpty()) { + this.useItem = this.getItemInHand(this.getUsedItemHand()); + if (!this.useItem.isEmpty()) { +@@ -2995,6 +3633,7 @@ + this.useItemRemaining = 0; + } + } ++ + } + + @Override +@@ -3007,48 +3646,72 @@ + + protected void triggerItemUseEffects(ItemStack stack, int amount) { + if (!stack.isEmpty() && this.isUsingItem()) { +- if (stack.getUseAnimation() == UseAnim.DRINK) { ++ if (stack.getUseAnimation() == EnumAnimation.DRINK) { + this.playSound(this.getDrinkingSound(stack), 0.5F, this.level().random.nextFloat() * 0.1F + 0.9F); + } + +- if (stack.getUseAnimation() == UseAnim.EAT) { ++ if (stack.getUseAnimation() == EnumAnimation.EAT) { + this.spawnItemParticles(stack, amount); +- this.playSound( +- this.getEatingSound(stack), 0.5F + 0.5F * (float)this.random.nextInt(2), (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F +- ); ++ this.playSound(this.getEatingSound(stack), 0.5F + 0.5F * (float) this.random.nextInt(2), (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); + } ++ + } + } + + private void spawnItemParticles(ItemStack stack, int amount) { +- for (int i = 0; i < amount; i++) { +- Vec3 vec3 = new Vec3(((double)this.random.nextFloat() - 0.5) * 0.1, Math.random() * 0.1 + 0.1, 0.0); +- vec3 = vec3.xRot(-this.getXRot() * (float) (Math.PI / 180.0)); +- vec3 = vec3.yRot(-this.getYRot() * (float) (Math.PI / 180.0)); +- double d = (double)(-this.random.nextFloat()) * 0.6 - 0.3; +- Vec3 vec31 = new Vec3(((double)this.random.nextFloat() - 0.5) * 0.3, d, 0.6); +- vec31 = vec31.xRot(-this.getXRot() * (float) (Math.PI / 180.0)); +- vec31 = vec31.yRot(-this.getYRot() * (float) (Math.PI / 180.0)); +- vec31 = vec31.add(this.getX(), this.getEyeY(), this.getZ()); +- this.level().addParticle(new ItemParticleOption(ParticleTypes.ITEM, stack), vec31.x, vec31.y, vec31.z, vec3.x, vec3.y + 0.05, vec3.z); ++ for (int j = 0; j < amount; ++j) { ++ Vec3 vec3d = new Vec3(((double) this.random.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, 0.0D); ++ ++ vec3d = vec3d.xRot(-this.getXRot() * 0.017453292F); ++ vec3d = vec3d.yRot(-this.getYRot() * 0.017453292F); ++ double d0 = (double) (-this.random.nextFloat()) * 0.6D - 0.3D; ++ Vec3 vec3d1 = new Vec3(((double) this.random.nextFloat() - 0.5D) * 0.3D, d0, 0.6D); ++ ++ vec3d1 = vec3d1.xRot(-this.getXRot() * 0.017453292F); ++ vec3d1 = vec3d1.yRot(-this.getYRot() * 0.017453292F); ++ vec3d1 = vec3d1.add(this.getX(), this.getEyeY(), this.getZ()); ++ this.level().addParticle(new ItemParticleOption(ParticleTypes.ITEM, stack), vec3d1.x, vec3d1.y, vec3d1.z, vec3d.x, vec3d.y + 0.05D, vec3d.z); + } ++ + } + + protected void completeUsingItem() { + if (!this.level().isClientSide || this.isUsingItem()) { +- InteractionHand usedItemHand = this.getUsedItemHand(); +- if (!this.useItem.equals(this.getItemInHand(usedItemHand))) { ++ EnumHand enumhand = this.getUsedItemHand(); ++ ++ if (!this.useItem.equals(this.getItemInHand(enumhand))) { + this.releaseUsingItem(); + } else { + if (!this.useItem.isEmpty() && this.isUsingItem()) { + this.triggerItemUseEffects(this.useItem, 16); +- ItemStack itemStack = this.useItem.finishUsingItem(this.level(), this); +- if (itemStack != this.useItem) { +- this.setItemInHand(usedItemHand, itemStack); ++ // CraftBukkit start - fire PlayerItemConsumeEvent ++ ItemStack itemstack; ++ if (this instanceof ServerPlayer) { ++ org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(this.useItem); ++ org.bukkit.inventory.EquipmentSlot hand = org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(enumhand); ++ PlayerItemConsumeEvent event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem, hand); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ // Update client ++ ((ServerPlayer) this).getBukkitEntity().updateInventory(); ++ ((ServerPlayer) this).getBukkitEntity().updateScaledHealth(); ++ return; ++ } ++ ++ itemstack = (craftItem.equals(event.getItem())) ? this.useItem.finishUsingItem(this.level(), this) : CraftItemStack.asNMSCopy(event.getItem()).finishUsingItem(this.level(), this); ++ } else { ++ itemstack = this.useItem.finishUsingItem(this.level(), this); + } ++ // CraftBukkit end + ++ if (itemstack != this.useItem) { ++ this.setItemInHand(enumhand, itemstack); ++ } ++ + this.stopUsingItem(); + } ++ + } + } + } +@@ -3078,9 +3741,10 @@ + + public void stopUsingItem() { + if (!this.level().isClientSide) { +- boolean isUsingItem = this.isUsingItem(); ++ boolean flag = this.isUsingItem(); ++ + this.setLivingEntityFlag(1, false); +- if (isUsingItem) { ++ if (flag) { + this.gameEvent(GameEvent.ITEM_INTERACT_FINISH); + } + } +@@ -3092,7 +3756,8 @@ + public boolean isBlocking() { + if (this.isUsingItem() && !this.useItem.isEmpty()) { + Item item = this.useItem.getItem(); +- return item.getUseAnimation(this.useItem) == UseAnim.BLOCK && item.getUseDuration(this.useItem) - this.useItemRemaining >= 5; ++ ++ return item.getUseAnimation(this.useItem) != EnumAnimation.BLOCK ? false : item.getUseDuration(this.useItem) - this.useItemRemaining >= 5; + } else { + return false; + } +@@ -3108,56 +3773,91 @@ + + @Override + public boolean isVisuallySwimming() { +- return super.isVisuallySwimming() || !this.isFallFlying() && this.hasPose(Pose.FALL_FLYING); ++ return super.isVisuallySwimming() || !this.isFallFlying() && this.hasPose(EntityPose.FALL_FLYING); + } + + public int getFallFlyingTicks() { + return this.fallFlyTicks; + } + +- public boolean randomTeleport(double x, double y, double z, boolean broadcastTeleport) { +- double x1 = this.getX(); +- double y1 = this.getY(); +- double z1 = this.getZ(); +- double d = y; +- boolean flag = false; +- BlockPos blockPos = BlockPos.containing(x, y, z); +- Level level = this.level(); +- if (level.hasChunkAt(blockPos)) { +- boolean flag1 = false; ++ public boolean randomTeleport(double x, double d1, double y, boolean flag) { ++ // CraftBukkit start ++ return randomTeleport(x, d1, y, flag, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.UNKNOWN).orElse(false); ++ } + +- while (!flag1 && blockPos.getY() > level.getMinBuildHeight()) { +- BlockPos blockPos1 = blockPos.below(); +- BlockState blockState = level.getBlockState(blockPos1); +- if (blockState.blocksMotion()) { +- flag1 = true; ++ public Optional randomTeleport(double d0, double d1, double d2, boolean flag, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { ++ // CraftBukkit end ++ double d3 = this.getX(); ++ double d4 = this.getY(); ++ double d5 = this.getZ(); ++ double d6 = d1; ++ boolean flag1 = false; ++ BlockPos blockposition = BlockPos.containing(d0, d1, d2); ++ Level world = this.level(); ++ ++ if (world.hasChunkAt(blockposition)) { ++ boolean flag2 = false; ++ ++ while (!flag2 && blockposition.getY() > world.getMinBuildHeight()) { ++ BlockPos blockposition1 = blockposition.below(); ++ IBlockData iblockdata = world.getBlockState(blockposition1); ++ ++ if (iblockdata.blocksMotion()) { ++ flag2 = true; + } else { +- d--; +- blockPos = blockPos1; ++ --d6; ++ blockposition = blockposition1; + } + } + +- if (flag1) { +- this.teleportTo(x, d, z); +- if (level.noCollision(this) && !level.containsAnyLiquid(this.getBoundingBox())) { +- flag = true; ++ if (flag2) { ++ // CraftBukkit start - Teleport event ++ // this.teleportTo(d0, d6, d2); ++ ++ // first set position, to check if the place to teleport is valid ++ this.setPos(d0, d6, d2); ++ if (world.noCollision((Entity) this) && !world.containsAnyLiquid(this.getBoundingBox())) { ++ flag1 = true; + } ++ // now revert and call event if the teleport place is valid ++ this.setPos(d3, d4, d5); ++ ++ if (flag1) { ++ if (!(this instanceof ServerPlayer)) { ++ EntityTeleportEvent teleport = new EntityTeleportEvent(this.getBukkitEntity(), new Location(this.level().getWorld(), d3, d4, d5), new Location(this.level().getWorld(), d0, d6, d2)); ++ this.level().getCraftServer().getPluginManager().callEvent(teleport); ++ if (!teleport.isCancelled()) { ++ Location to = teleport.getTo(); ++ this.teleportTo(to.getX(), to.getY(), to.getZ()); ++ } else { ++ return Optional.empty(); ++ } ++ } else { ++ // player teleport event is called in the underlining code ++ if (((ServerPlayer) this).connection.teleport(d0, d6, d2, this.getYRot(), this.getXRot(), java.util.Collections.emptySet(), cause)) { ++ return Optional.empty(); ++ } ++ } ++ } ++ // CraftBukkit end + } + } + +- if (!flag) { +- this.teleportTo(x1, y1, z1); +- return false; ++ if (!flag1) { ++ // this.enderTeleportTo(d3, d4, d5); // CraftBukkit - already set the location back ++ return Optional.of(false); // CraftBukkit + } else { +- if (broadcastTeleport) { +- level.broadcastEntityEvent(this, (byte)46); ++ if (flag) { ++ world.broadcastEntityEvent(this, (byte) 46); + } + +- if (this instanceof PathfinderMob pathfinderMob) { +- pathfinderMob.getNavigation().stop(); ++ if (this instanceof PathfinderMob) { ++ PathfinderMob entitycreature = (PathfinderMob) this; ++ ++ entitycreature.getNavigation().stop(); + } + +- return true; ++ return Optional.of(true); // CraftBukkit + } + } + +@@ -3169,37 +3869,31 @@ + return true; + } + +- public void setRecordPlayingNearby(BlockPos jukebox, boolean partyParrot) { +- } ++ public void setRecordPlayingNearby(BlockPos jukebox, boolean partyParrot) {} + + public boolean canTakeItem(ItemStack stack) { + return false; + } + + @Override +- public EntityDimensions getDimensions(Pose pose) { +- return pose == Pose.SLEEPING ? SLEEPING_DIMENSIONS : super.getDimensions(pose).scale(this.getScale()); ++ public EntityDimensions getDimensions(EntityPose pose) { ++ return pose == EntityPose.SLEEPING ? LivingEntity.SLEEPING_DIMENSIONS : super.getDimensions(pose).scale(this.getScale()); + } + +- public ImmutableList getDismountPoses() { +- return ImmutableList.of(Pose.STANDING); ++ public ImmutableList getDismountPoses() { ++ return ImmutableList.of(EntityPose.STANDING); + } + +- public AABB getLocalBoundsForPose(Pose pose) { +- EntityDimensions dimensions = this.getDimensions(pose); +- return new AABB( +- (double)(-dimensions.width / 2.0F), +- 0.0, +- (double)(-dimensions.width / 2.0F), +- (double)(dimensions.width / 2.0F), +- (double)dimensions.height, +- (double)(dimensions.width / 2.0F) +- ); ++ public AABB getLocalBoundsForPose(EntityPose pose) { ++ EntityDimensions entitysize = this.getDimensions(pose); ++ ++ return new AABB((double) (-entitysize.width / 2.0F), 0.0D, (double) (-entitysize.width / 2.0F), (double) (entitysize.width / 2.0F), (double) entitysize.height, (double) (entitysize.width / 2.0F)); + } + +- protected boolean wouldNotSuffocateAtTargetPose(Pose pose) { +- AABB aABB = this.getDimensions(pose).makeBoundingBox(this.position()); +- return this.level().noBlockCollision(this, aABB); ++ protected boolean wouldNotSuffocateAtTargetPose(EntityPose entitypose) { ++ AABB axisalignedbb = this.getDimensions(entitypose).makeBoundingBox(this.position()); ++ ++ return this.level().noBlockCollision(this, axisalignedbb); + } + + @Override +@@ -3208,15 +3902,15 @@ + } + + public Optional getSleepingPos() { +- return this.entityData.get(SLEEPING_POS_ID); ++ return (Optional) this.entityData.get(LivingEntity.SLEEPING_POS_ID); + } + + public void setSleepingPos(BlockPos pos) { +- this.entityData.set(SLEEPING_POS_ID, Optional.of(pos)); ++ this.entityData.set(LivingEntity.SLEEPING_POS_ID, Optional.of(pos)); + } + + public void clearSleepingPos() { +- this.entityData.set(SLEEPING_POS_ID, Optional.empty()); ++ this.entityData.set(LivingEntity.SLEEPING_POS_ID, Optional.empty()); + } + + public boolean isSleeping() { +@@ -3228,12 +3922,13 @@ + this.stopRiding(); + } + +- BlockState blockState = this.level().getBlockState(pos); +- if (blockState.getBlock() instanceof BedBlock) { +- this.level().setBlock(pos, blockState.setValue(BedBlock.OCCUPIED, Boolean.valueOf(true)), 3); ++ IBlockData iblockdata = this.level().getBlockState(pos); ++ ++ if (iblockdata.getBlock() instanceof BedBlock) { ++ this.level().setBlock(pos, (IBlockData) iblockdata.setValue(BedBlock.OCCUPIED, true), 3); + } + +- this.setPose(Pose.SLEEPING); ++ this.setPose(EntityPose.SLEEPING); + this.setPosToBed(pos); + this.setSleepingPos(pos); + this.setDeltaMovement(Vec3.ZERO); +@@ -3241,40 +3936,53 @@ + } + + private void setPosToBed(BlockPos pos) { +- this.setPos((double)pos.getX() + 0.5, (double)pos.getY() + 0.6875, (double)pos.getZ() + 0.5); ++ this.setPos((double) pos.getX() + 0.5D, (double) pos.getY() + 0.6875D, (double) pos.getZ() + 0.5D); + } + + private boolean checkBedExists() { +- return this.getSleepingPos().map(blockPos -> this.level().getBlockState(blockPos).getBlock() instanceof BedBlock).orElse(false); ++ return (Boolean) this.getSleepingPos().map((blockposition) -> { ++ return this.level().getBlockState(blockposition).getBlock() instanceof BedBlock; ++ }).orElse(false); + } + + public void stopSleeping() { +- this.getSleepingPos().filter(this.level()::hasChunkAt).ifPresent(blockPos -> { +- BlockState blockState = this.level().getBlockState(blockPos); +- if (blockState.getBlock() instanceof BedBlock) { +- Direction direction = blockState.getValue(BedBlock.FACING); +- this.level().setBlock(blockPos, blockState.setValue(BedBlock.OCCUPIED, Boolean.valueOf(false)), 3); +- Vec3 vec31 = BedBlock.findStandUpPosition(this.getType(), this.level(), blockPos, direction, this.getYRot()).orElseGet(() -> { +- BlockPos blockPos1 = blockPos.above(); +- return new Vec3((double)blockPos1.getX() + 0.5, (double)blockPos1.getY() + 0.1, (double)blockPos1.getZ() + 0.5); ++ Optional optional = this.getSleepingPos(); // CraftBukkit - decompile error ++ Level world = this.level(); ++ ++ java.util.Objects.requireNonNull(world); ++ optional.filter(world::hasChunkAt).ifPresent((blockposition) -> { ++ IBlockData iblockdata = this.level().getBlockState(blockposition); ++ ++ if (iblockdata.getBlock() instanceof BedBlock) { ++ Direction enumdirection = (Direction) iblockdata.getValue(BedBlock.FACING); ++ ++ this.level().setBlock(blockposition, (IBlockData) iblockdata.setValue(BedBlock.OCCUPIED, false), 3); ++ Vec3 vec3d = (Vec3) BedBlock.findStandUpPosition(this.getType(), this.level(), blockposition, enumdirection, this.getYRot()).orElseGet(() -> { ++ BlockPos blockposition1 = blockposition.above(); ++ ++ return new Vec3((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.1D, (double) blockposition1.getZ() + 0.5D); + }); +- Vec3 vec32 = Vec3.atBottomCenterOf(blockPos).subtract(vec31).normalize(); +- float f = (float)Mth.wrapDegrees(Mth.atan2(vec32.z, vec32.x) * 180.0F / (float)Math.PI - 90.0); +- this.setPos(vec31.x, vec31.y, vec31.z); ++ Vec3 vec3d1 = Vec3.atBottomCenterOf(blockposition).subtract(vec3d).normalize(); ++ float f = (float) Mth.wrapDegrees(Mth.atan2(vec3d1.z, vec3d1.x) * 57.2957763671875D - 90.0D); ++ ++ this.setPos(vec3d.x, vec3d.y, vec3d.z); + this.setYRot(f); + this.setXRot(0.0F); + } ++ + }); +- Vec3 vec3 = this.position(); +- this.setPose(Pose.STANDING); +- this.setPos(vec3.x, vec3.y, vec3.z); ++ Vec3 vec3d = this.position(); ++ ++ this.setPose(EntityPose.STANDING); ++ this.setPos(vec3d.x, vec3d.y, vec3d.z); + this.clearSleepingPos(); + } + + @Nullable + public Direction getBedOrientation() { +- BlockPos blockPos = this.getSleepingPos().orElse(null); +- return blockPos != null ? BedBlock.getBedOrientation(this.level(), blockPos) : null; ++ BlockPos blockposition = (BlockPos) this.getSleepingPos().orElse(null); // CraftBukkit - decompile error ++ ++ return blockposition != null ? BedBlock.getBedOrientation(this.level(), blockposition) : null; + } + + @Override +@@ -3283,11 +3991,11 @@ + } + + @Override +- protected final float getEyeHeight(Pose pose, EntityDimensions size) { +- return pose == Pose.SLEEPING ? 0.2F : this.getStandingEyeHeight(pose, size); ++ protected final float getEyeHeight(EntityPose pose, EntityDimensions size) { ++ return pose == EntityPose.SLEEPING ? 0.2F : this.getStandingEyeHeight(pose, size); + } + +- protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions dimensions) { + return super.getEyeHeight(pose, dimensions); + } + +@@ -3297,18 +4005,9 @@ + + public ItemStack eat(Level level, ItemStack food) { + if (food.isEdible()) { +- level.playSound( +- null, +- this.getX(), +- this.getY(), +- this.getZ(), +- this.getEatingSound(food), +- SoundSource.NEUTRAL, +- 1.0F, +- 1.0F + (level.random.nextFloat() - level.random.nextFloat()) * 0.4F +- ); ++ level.playSound((net.minecraft.world.entity.player.Player) null, this.getX(), this.getY(), this.getZ(), this.getEatingSound(food), SoundSource.NEUTRAL, 1.0F, 1.0F + (level.random.nextFloat() - level.random.nextFloat()) * 0.4F); + this.addEatEffect(food, level, this); +- if (!(this instanceof Player) || !((Player)this).getAbilities().instabuild) { ++ if (!(this instanceof net.minecraft.world.entity.player.Player) || !((net.minecraft.world.entity.player.Player) this).getAbilities().instabuild) { + food.shrink(1); + } + +@@ -3320,13 +4019,20 @@ + + private void addEatEffect(ItemStack food, Level level, LivingEntity livingEntity) { + Item item = food.getItem(); ++ + if (item.isEdible()) { +- for (Pair pair : item.getFoodProperties().getEffects()) { +- if (!level.isClientSide && pair.getFirst() != null && level.random.nextFloat() < pair.getSecond()) { +- livingEntity.addEffect(new MobEffectInstance(pair.getFirst())); ++ List> list = item.getFoodProperties().getEffects(); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Pair pair = (Pair) iterator.next(); ++ ++ if (!level.isClientSide && pair.getFirst() != null && level.random.nextFloat() < (Float) pair.getSecond()) { ++ livingEntity.addEffect(new MobEffectInstance((MobEffectInstance) pair.getFirst()), EntityPotionEffectEvent.Cause.FOOD); // CraftBukkit + } + } + } ++ + } + + private static byte entityEventForEquipmentBreak(EquipmentSlot slot) { +@@ -3352,15 +4058,16 @@ + this.level().broadcastEntityEvent(this, entityEventForEquipmentBreak(slot)); + } + +- public void broadcastBreakEvent(InteractionHand hand) { +- this.broadcastBreakEvent(hand == InteractionHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND); ++ public void broadcastBreakEvent(EnumHand hand) { ++ this.broadcastBreakEvent(hand == EnumHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND); + } + + @Override + public AABB getBoundingBoxForCulling() { + if (this.getItemBySlot(EquipmentSlot.HEAD).is(Items.DRAGON_HEAD)) { + float f = 0.5F; +- return this.getBoundingBox().inflate(0.5, 0.5, 0.5); ++ ++ return this.getBoundingBox().inflate(0.5D, 0.5D, 0.5D); + } else { + return super.getBoundingBoxForCulling(); + } +@@ -3368,36 +4075,26 @@ + + public static EquipmentSlot getEquipmentSlotForItem(ItemStack item) { + Equipable equipable = Equipable.get(item); ++ + return equipable != null ? equipable.getEquipmentSlot() : EquipmentSlot.MAINHAND; + } + + private static SlotAccess createEquipmentSlotAccess(LivingEntity entity, EquipmentSlot slot) { +- return slot != EquipmentSlot.HEAD && slot != EquipmentSlot.MAINHAND && slot != EquipmentSlot.OFFHAND +- ? SlotAccess.forEquipmentSlot(entity, slot, itemStack -> itemStack.isEmpty() || Mob.getEquipmentSlotForItem(itemStack) == slot) +- : SlotAccess.forEquipmentSlot(entity, slot); ++ return slot != EquipmentSlot.HEAD && slot != EquipmentSlot.MAINHAND && slot != EquipmentSlot.OFFHAND ? SlotAccess.forEquipmentSlot(entity, slot, (itemstack) -> { ++ return itemstack.isEmpty() || Mob.getEquipmentSlotForItem(itemstack) == slot; ++ }) : SlotAccess.forEquipmentSlot(entity, slot); + } + + @Nullable + private static EquipmentSlot getEquipmentSlot(int index) { +- if (index == 100 + EquipmentSlot.HEAD.getIndex()) { +- return EquipmentSlot.HEAD; +- } else if (index == 100 + EquipmentSlot.CHEST.getIndex()) { +- return EquipmentSlot.CHEST; +- } else if (index == 100 + EquipmentSlot.LEGS.getIndex()) { +- return EquipmentSlot.LEGS; +- } else if (index == 100 + EquipmentSlot.FEET.getIndex()) { +- return EquipmentSlot.FEET; +- } else if (index == 98) { +- return EquipmentSlot.MAINHAND; +- } else { +- return index == 99 ? EquipmentSlot.OFFHAND : null; +- } ++ return index == 100 + EquipmentSlot.HEAD.getIndex() ? EquipmentSlot.HEAD : (index == 100 + EquipmentSlot.CHEST.getIndex() ? EquipmentSlot.CHEST : (index == 100 + EquipmentSlot.LEGS.getIndex() ? EquipmentSlot.LEGS : (index == 100 + EquipmentSlot.FEET.getIndex() ? EquipmentSlot.FEET : (index == 98 ? EquipmentSlot.MAINHAND : (index == 99 ? EquipmentSlot.OFFHAND : null))))); + } + + @Override + public SlotAccess getSlot(int slot) { +- EquipmentSlot equipmentSlot = getEquipmentSlot(slot); +- return equipmentSlot != null ? createEquipmentSlotAccess(this, equipmentSlot) : super.getSlot(slot); ++ EquipmentSlot enumitemslot = getEquipmentSlot(slot); ++ ++ return enumitemslot != null ? createEquipmentSlotAccess(this, enumitemslot) : super.getSlot(slot); + } + + @Override +@@ -3405,10 +4102,8 @@ + if (this.isSpectator()) { + return false; + } else { +- boolean flag = !this.getItemBySlot(EquipmentSlot.HEAD).is(ItemTags.FREEZE_IMMUNE_WEARABLES) +- && !this.getItemBySlot(EquipmentSlot.CHEST).is(ItemTags.FREEZE_IMMUNE_WEARABLES) +- && !this.getItemBySlot(EquipmentSlot.LEGS).is(ItemTags.FREEZE_IMMUNE_WEARABLES) +- && !this.getItemBySlot(EquipmentSlot.FEET).is(ItemTags.FREEZE_IMMUNE_WEARABLES); ++ boolean flag = !this.getItemBySlot(EquipmentSlot.HEAD).is(ItemTags.FREEZE_IMMUNE_WEARABLES) && !this.getItemBySlot(EquipmentSlot.CHEST).is(ItemTags.FREEZE_IMMUNE_WEARABLES) && !this.getItemBySlot(EquipmentSlot.LEGS).is(ItemTags.FREEZE_IMMUNE_WEARABLES) && !this.getItemBySlot(EquipmentSlot.FEET).is(ItemTags.FREEZE_IMMUNE_WEARABLES); ++ + return flag && super.canFreeze(); + } + } +@@ -3425,19 +4120,20 @@ + + @Override + public void recreateFromPacket(ClientboundAddEntityPacket packet) { +- double x = packet.getX(); +- double y = packet.getY(); +- double z = packet.getZ(); +- float yRot = packet.getYRot(); +- float xRot = packet.getXRot(); +- this.syncPacketPositionCodec(x, y, z); ++ double d0 = packet.getX(); ++ double d1 = packet.getY(); ++ double d2 = packet.getZ(); ++ float f = packet.getYRot(); ++ float f1 = packet.getXRot(); ++ ++ this.syncPacketPositionCodec(d0, d1, d2); + this.yBodyRot = packet.getYHeadRot(); + this.yHeadRot = packet.getYHeadRot(); + this.yBodyRotO = this.yBodyRot; + this.yHeadRotO = this.yHeadRot; + this.setId(packet.getId()); + this.setUUID(packet.getUUID()); +- this.absMoveTo(x, y, z, yRot, xRot); ++ this.absMoveTo(d0, d1, d2, f, f1); + this.setDeltaMovement(packet.getXa(), packet.getYa(), packet.getZa()); + } + +@@ -3448,16 +4144,13 @@ + @Override + public float maxUpStep() { + float f = super.maxUpStep(); +- return this.getControllingPassenger() instanceof Player ? Math.max(f, 1.0F) : f; ++ ++ return this.getControllingPassenger() instanceof net.minecraft.world.entity.player.Player ? Math.max(f, 1.0F) : f; + } + + @Override + public Vec3 getPassengerRidingPosition(Entity entity) { +- return new Vec3( +- this.getPassengerAttachmentPoint(entity, this.getDimensions(this.getPose()), this.getScale()) +- .rotateY(-this.yBodyRot * (float) (Math.PI / 180.0)) +- ) +- .add(this.position()); ++ return (new Vec3(this.getPassengerAttachmentPoint(entity, this.getDimensions(this.getPose()), this.getScale()).rotateY(-this.yBodyRot * 0.017453292F))).add(this.position()); + } + + @Override +@@ -3465,10 +4158,11 @@ + return this.ridingOffset(entity) * this.getScale(); + } + +- protected void lerpHeadRotationStep(int i, double d) { +- this.yHeadRot = (float)Mth.rotLerp(1.0 / (double)i, (double)this.yHeadRot, d); ++ protected void lerpHeadRotationStep(int i, double d0) { ++ this.yHeadRot = (float) Mth.rotLerp(1.0D / (double) i, (double) this.yHeadRot, d0); + } + +- public static record Fallsounds(SoundEvent small, SoundEvent big) { ++ public static record a(SoundEvent small, SoundEvent big) { ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/Mob.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/Mob.java.patch new file mode 100644 index 0000000000..143349d38a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/Mob.java.patch @@ -0,0 +1,1732 @@ +--- a/net/minecraft/world/entity/Mob.java ++++ b/net/minecraft/world/entity/Mob.java +@@ -3,6 +3,8 @@ + import com.google.common.annotations.VisibleForTesting; + import com.google.common.collect.Maps; + import java.util.Arrays; ++import java.util.Iterator; ++import java.util.List; + import java.util.Map; + import java.util.Optional; + import java.util.UUID; +@@ -23,13 +25,14 @@ + import net.minecraft.network.syncher.SynchedEntityData; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.tags.TagKey; + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.world.Difficulty; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; +@@ -47,7 +50,7 @@ + import net.minecraft.world.entity.decoration.HangingEntity; + import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; + import net.minecraft.world.entity.item.ItemEntity; +-import net.minecraft.world.entity.monster.Enemy; ++import net.minecraft.world.entity.monster.IMonster; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.vehicle.Boat; + import net.minecraft.world.item.ArmorItem; +@@ -64,6 +67,7 @@ + import net.minecraft.world.item.SwordItem; + import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.level.GameRules; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; +@@ -72,8 +76,19 @@ + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.AABB; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++import org.bukkit.event.entity.EntityUnleashEvent; ++import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; ++// CraftBukkit end + + public abstract class Mob extends LivingEntity implements Targeting { ++ + private static final EntityDataAccessor DATA_MOB_FLAGS_ID = SynchedEntityData.defineId(Mob.class, EntityDataSerializers.BYTE); + private static final int MOB_FLAG_NO_AI = 1; + private static final int MOB_FLAG_LEFTHANDED = 2; +@@ -88,7 +103,7 @@ + public static final float DEFAULT_EQUIPMENT_DROP_CHANCE = 0.085F; + public static final int PRESERVE_ITEM_DROP_CHANCE = 2; + public static final int UPDATE_GOAL_SELECTOR_EVERY_N_TICKS = 2; +- private static final double DEFAULT_ATTACK_REACH = Math.sqrt(2.04F) - 0.6F; ++ private static final double DEFAULT_ATTACK_REACH = Math.sqrt(2.0399999618530273D) - 0.6000000238418579D; + public int ambientSoundTime; + protected int xpReward; + protected LookControl lookControl; +@@ -96,31 +111,40 @@ + protected JumpControl jumpControl; + private final BodyRotationControl bodyRotationControl; + protected PathNavigation navigation; +- protected final GoalSelector goalSelector; +- protected final GoalSelector targetSelector; ++ public GoalSelector goalSelector; ++ public GoalSelector targetSelector; + @Nullable + private LivingEntity target; + private final Sensing sensing; +- private final NonNullList handItems = NonNullList.withSize(2, ItemStack.EMPTY); +- protected final float[] handDropChances = new float[2]; +- private final NonNullList armorItems = NonNullList.withSize(4, ItemStack.EMPTY); +- protected final float[] armorDropChances = new float[4]; ++ private final NonNullList handItems; ++ public final float[] handDropChances; ++ private final NonNullList armorItems; ++ public final float[] armorDropChances; + private boolean canPickUpLoot; + private boolean persistenceRequired; +- private final Map pathfindingMalus = Maps.newEnumMap(BlockPathTypes.class); ++ private final Map pathfindingMalus; + @Nullable +- private ResourceLocation lootTable; +- private long lootTableSeed; ++ public ResourceLocation lootTable; ++ public long lootTableSeed; + @Nullable + private Entity leashHolder; + private int delayedLeashHolderId; + @Nullable + private CompoundTag leashInfoTag; +- private BlockPos restrictCenter = BlockPos.ZERO; +- private float restrictRadius = -1.0F; ++ private BlockPos restrictCenter; ++ private float restrictRadius; + ++ public boolean aware = true; // CraftBukkit ++ + protected Mob(EntityType entityType, Level level) { + super(entityType, level); ++ this.handItems = NonNullList.withSize(2, ItemStack.EMPTY); ++ this.handDropChances = new float[2]; ++ this.armorItems = NonNullList.withSize(4, ItemStack.EMPTY); ++ this.armorDropChances = new float[4]; ++ this.pathfindingMalus = Maps.newEnumMap(BlockPathTypes.class); ++ this.restrictCenter = BlockPos.ZERO; ++ this.restrictRadius = -1.0F; + this.goalSelector = new GoalSelector(level.getProfilerSupplier()); + this.targetSelector = new GoalSelector(level.getProfilerSupplier()); + this.lookControl = new LookControl(this); +@@ -134,13 +158,19 @@ + if (level != null && !level.isClientSide) { + this.registerGoals(); + } ++ + } + +- protected void registerGoals() { ++ // CraftBukkit start ++ public void setPersistenceRequired(boolean persistenceRequired) { ++ this.persistenceRequired = persistenceRequired; + } ++ // CraftBukkit end + ++ protected void registerGoals() {} ++ + public static AttributeSupplier.Builder createMobAttributes() { +- return LivingEntity.createLivingAttributes().add(Attributes.FOLLOW_RANGE, 16.0).add(Attributes.ATTACK_KNOCKBACK); ++ return LivingEntity.createLivingAttributes().add(Attributes.FOLLOW_RANGE, 16.0D).add(Attributes.ATTACK_KNOCKBACK); + } + + protected PathNavigation createNavigation(Level level) { +@@ -152,29 +182,35 @@ + } + + public float getPathfindingMalus(BlockPathTypes nodeType) { +- Mob mob1; +- label17: { +- if (this.getControlledVehicle() instanceof Mob mob && mob.shouldPassengersInheritMalus()) { +- mob1 = mob; +- break label17; ++ Mob entityinsentient; ++ label17: ++ { ++ Entity entity = this.getControlledVehicle(); ++ ++ if (entity instanceof Mob) { ++ Mob entityinsentient1 = (Mob) entity; ++ ++ if (entityinsentient1.shouldPassengersInheritMalus()) { ++ entityinsentient = entityinsentient1; ++ break label17; ++ } + } + +- mob1 = this; ++ entityinsentient = this; + } + +- Float _float = mob1.pathfindingMalus.get(nodeType); +- return _float == null ? nodeType.getMalus() : _float; ++ Float ofloat = (Float) entityinsentient.pathfindingMalus.get(nodeType); ++ ++ return ofloat == null ? nodeType.getMalus() : ofloat; + } + + public void setPathfindingMalus(BlockPathTypes nodeType, float malus) { + this.pathfindingMalus.put(nodeType, malus); + } + +- public void onPathfindingStart() { +- } ++ public void onPathfindingStart() {} + +- public void onPathfindingDone() { +- } ++ public void onPathfindingDone() {} + + protected BodyRotationControl createBodyControl() { + return new BodyRotationControl(this); +@@ -185,7 +221,15 @@ + } + + public MoveControl getMoveControl() { +- return this.getControlledVehicle() instanceof Mob mob ? mob.getMoveControl() : this.moveControl; ++ Entity entity = this.getControlledVehicle(); ++ ++ if (entity instanceof Mob) { ++ Mob entityinsentient = (Mob) entity; ++ ++ return entityinsentient.getMoveControl(); ++ } else { ++ return this.moveControl; ++ } + } + + public JumpControl getJumpControl() { +@@ -193,18 +237,34 @@ + } + + public PathNavigation getNavigation() { +- return this.getControlledVehicle() instanceof Mob mob ? mob.getNavigation() : this.navigation; ++ Entity entity = this.getControlledVehicle(); ++ ++ if (entity instanceof Mob) { ++ Mob entityinsentient = (Mob) entity; ++ ++ return entityinsentient.getNavigation(); ++ } else { ++ return this.navigation; ++ } + } + + @Nullable + @Override + public LivingEntity getControllingPassenger() { +- Entity firstPassenger = this.getFirstPassenger(); +- if (!this.isNoAi() && firstPassenger instanceof Mob mob && firstPassenger.canControlVehicle()) { +- return mob; ++ Entity entity = this.getFirstPassenger(); ++ Mob entityinsentient; ++ ++ if (!this.isNoAi() && entity instanceof Mob) { ++ Mob entityinsentient1 = (Mob) entity; ++ ++ if (entity.canControlVehicle()) { ++ entityinsentient = entityinsentient1; ++ return entityinsentient; ++ } + } + +- return null; ++ entityinsentient = null; ++ return entityinsentient; + } + + public Sensing getSensing() { +@@ -218,9 +278,40 @@ + } + + public void setTarget(@Nullable LivingEntity target) { +- this.target = target; ++ // CraftBukkit start - fire event ++ setTarget(target, EntityTargetEvent.TargetReason.UNKNOWN, true); + } + ++ public boolean setTarget(LivingEntity entityliving, EntityTargetEvent.TargetReason reason, boolean fireEvent) { ++ if (getTarget() == entityliving) return false; ++ if (fireEvent) { ++ if (reason == EntityTargetEvent.TargetReason.UNKNOWN && getTarget() != null && entityliving == null) { ++ reason = getTarget().isAlive() ? EntityTargetEvent.TargetReason.FORGOT_TARGET : EntityTargetEvent.TargetReason.TARGET_DIED; ++ } ++ if (reason == EntityTargetEvent.TargetReason.UNKNOWN) { ++ this.level().getCraftServer().getLogger().log(java.util.logging.Level.WARNING, "Unknown target reason, please report on the issue tracker", new Exception()); ++ } ++ CraftLivingEntity ctarget = null; ++ if (entityliving != null) { ++ ctarget = (CraftLivingEntity) entityliving.getBukkitEntity(); ++ } ++ EntityTargetLivingEntityEvent event = new EntityTargetLivingEntityEvent(this.getBukkitEntity(), ctarget, reason); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ if (event.getTarget() != null) { ++ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ } else { ++ entityliving = null; ++ } ++ } ++ this.target = entityliving; ++ return true; ++ // CraftBukkit end ++ } ++ + @Override + public boolean canAttackType(EntityType type) { + return type != EntityType.GHAST; +@@ -237,7 +328,7 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_MOB_FLAGS_ID, (byte)0); ++ this.entityData.define(Mob.DATA_MOB_FLAGS_ID, (byte) 0); + } + + public int getAmbientSoundInterval() { +@@ -245,10 +336,12 @@ + } + + public void playAmbientSound() { +- SoundEvent ambientSound = this.getAmbientSound(); +- if (ambientSound != null) { +- this.playSound(ambientSound, this.getSoundVolume(), this.getVoicePitch()); ++ SoundEvent soundeffect = this.getAmbientSound(); ++ ++ if (soundeffect != null) { ++ this.playSound(soundeffect, this.getSoundVolume(), this.getVoicePitch()); + } ++ + } + + @Override +@@ -278,14 +371,16 @@ + if (this.xpReward > 0) { + int i = this.xpReward; + +- for (int i1 = 0; i1 < this.armorItems.size(); i1++) { +- if (!this.armorItems.get(i1).isEmpty() && this.armorDropChances[i1] <= 1.0F) { ++ int j; ++ ++ for (j = 0; j < this.armorItems.size(); ++j) { ++ if (!((ItemStack) this.armorItems.get(j)).isEmpty() && this.armorDropChances[j] <= 1.0F) { + i += 1 + this.random.nextInt(3); + } + } + +- for (int i1x = 0; i1x < this.handItems.size(); i1x++) { +- if (!this.handItems.get(i1x).isEmpty() && this.handDropChances[i1x] <= 1.0F) { ++ for (j = 0; j < this.handItems.size(); ++j) { ++ if (!((ItemStack) this.handItems.get(j)).isEmpty() && this.handDropChances[j] <= 1.0F) { + i += 1 + this.random.nextInt(3); + } + } +@@ -298,17 +393,18 @@ + + public void spawnAnim() { + if (this.level().isClientSide) { +- for (int i = 0; i < 20; i++) { +- double d = this.random.nextGaussian() * 0.02; +- double d1 = this.random.nextGaussian() * 0.02; +- double d2 = this.random.nextGaussian() * 0.02; +- double d3 = 10.0; +- this.level() +- .addParticle(ParticleTypes.POOF, this.getX(1.0) - d * 10.0, this.getRandomY() - d1 * 10.0, this.getRandomZ(1.0) - d2 * 10.0, d, d1, d2); ++ for (int i = 0; i < 20; ++i) { ++ double d0 = this.random.nextGaussian() * 0.02D; ++ double d1 = this.random.nextGaussian() * 0.02D; ++ double d2 = this.random.nextGaussian() * 0.02D; ++ double d3 = 10.0D; ++ ++ this.level().addParticle(ParticleTypes.POOF, this.getX(1.0D) - d0 * 10.0D, this.getRandomY() - d1 * 10.0D, this.getRandomZ(1.0D) - d2 * 10.0D, d0, d1, d2); + } + } else { +- this.level().broadcastEntityEvent(this, (byte)20); ++ this.level().broadcastEntityEvent(this, (byte) 20); + } ++ + } + + @Override +@@ -318,6 +414,7 @@ + } else { + super.handleEntityEvent(id); + } ++ + } + + @Override +@@ -329,14 +426,16 @@ + this.updateControlFlags(); + } + } ++ + } + + protected void updateControlFlags() { + boolean flag = !(this.getControllingPassenger() instanceof Mob); + boolean flag1 = !(this.getVehicle() instanceof Boat); +- this.goalSelector.setControlFlag(Goal.Flag.MOVE, flag); +- this.goalSelector.setControlFlag(Goal.Flag.JUMP, flag && flag1); +- this.goalSelector.setControlFlag(Goal.Flag.LOOK, flag); ++ ++ this.goalSelector.setControlFlag(Goal.Type.MOVE, flag); ++ this.goalSelector.setControlFlag(Goal.Type.JUMP, flag && flag1); ++ this.goalSelector.setControlFlag(Goal.Type.LOOK, flag); + } + + @Override +@@ -350,62 +449,85 @@ + return null; + } + ++ // CraftBukkit start - Add delegate method ++ public SoundEvent getAmbientSound0() { ++ return getAmbientSound(); ++ } ++ // CraftBukkit end ++ + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); + compound.putBoolean("CanPickUpLoot", this.canPickUpLoot()); + compound.putBoolean("PersistenceRequired", this.persistenceRequired); +- ListTag list = new ListTag(); ++ ListTag nbttaglist = new ListTag(); + +- for (ItemStack itemStack : this.armorItems) { +- CompoundTag compoundTag = new CompoundTag(); +- if (!itemStack.isEmpty()) { +- itemStack.save(compoundTag); +- } ++ CompoundTag nbttagcompound1; + +- list.add(compoundTag); ++ for (Iterator iterator = this.armorItems.iterator(); iterator.hasNext(); nbttaglist.add(nbttagcompound1)) { ++ ItemStack itemstack = (ItemStack) iterator.next(); ++ ++ nbttagcompound1 = new CompoundTag(); ++ if (!itemstack.isEmpty()) { ++ itemstack.save(nbttagcompound1); ++ } + } + +- compound.put("ArmorItems", list); +- ListTag list1 = new ListTag(); ++ compound.put("ArmorItems", nbttaglist); ++ ListTag nbttaglist1 = new ListTag(); + +- for (ItemStack itemStack1 : this.handItems) { +- CompoundTag compoundTag1 = new CompoundTag(); +- if (!itemStack1.isEmpty()) { +- itemStack1.save(compoundTag1); +- } ++ CompoundTag nbttagcompound2; + +- list1.add(compoundTag1); ++ for (Iterator iterator1 = this.handItems.iterator(); iterator1.hasNext(); nbttaglist1.add(nbttagcompound2)) { ++ ItemStack itemstack1 = (ItemStack) iterator1.next(); ++ ++ nbttagcompound2 = new CompoundTag(); ++ if (!itemstack1.isEmpty()) { ++ itemstack1.save(nbttagcompound2); ++ } + } + +- compound.put("HandItems", list1); +- ListTag list2 = new ListTag(); ++ compound.put("HandItems", nbttaglist1); ++ ListTag nbttaglist2 = new ListTag(); ++ float[] afloat = this.armorDropChances; ++ int i = afloat.length; + +- for (float f : this.armorDropChances) { +- list2.add(FloatTag.valueOf(f)); ++ int j; ++ ++ for (j = 0; j < i; ++j) { ++ float f = afloat[j]; ++ ++ nbttaglist2.add(FloatTag.valueOf(f)); + } + +- compound.put("ArmorDropChances", list2); +- ListTag list3 = new ListTag(); ++ compound.put("ArmorDropChances", nbttaglist2); ++ ListTag nbttaglist3 = new ListTag(); ++ float[] afloat1 = this.handDropChances; + +- for (float f1 : this.handDropChances) { +- list3.add(FloatTag.valueOf(f1)); ++ j = afloat1.length; ++ ++ for (int k = 0; k < j; ++k) { ++ float f1 = afloat1[k]; ++ ++ nbttaglist3.add(FloatTag.valueOf(f1)); + } + +- compound.put("HandDropChances", list3); +- if (this.leashHolder != null) { +- CompoundTag compoundTag1 = new CompoundTag(); ++ compound.put("HandDropChances", nbttaglist3); ++ if (this.leashHolder != null && !this.leashHolder.pluginRemoved) { // CraftBukkit - SPIGOT-7487: Don't save (and possible drop) leash, when the holder was removed by a plugin ++ nbttagcompound2 = new CompoundTag(); + if (this.leashHolder instanceof LivingEntity) { +- UUID uUID = this.leashHolder.getUUID(); +- compoundTag1.putUUID("UUID", uUID); ++ UUID uuid = this.leashHolder.getUUID(); ++ ++ nbttagcompound2.putUUID("UUID", uuid); + } else if (this.leashHolder instanceof HangingEntity) { +- BlockPos pos = ((HangingEntity)this.leashHolder).getPos(); +- compoundTag1.putInt("X", pos.getX()); +- compoundTag1.putInt("Y", pos.getY()); +- compoundTag1.putInt("Z", pos.getZ()); ++ BlockPos blockposition = ((HangingEntity) this.leashHolder).getPos(); ++ ++ nbttagcompound2.putInt("X", blockposition.getX()); ++ nbttagcompound2.putInt("Y", blockposition.getY()); ++ nbttagcompound2.putInt("Z", blockposition.getZ()); + } + +- compound.put("Leash", compoundTag1); ++ compound.put("Leash", nbttagcompound2); + } else if (this.leashInfoTag != null) { + compound.put("Leash", this.leashInfoTag.copy()); + } +@@ -421,45 +543,59 @@ + if (this.isNoAi()) { + compound.putBoolean("NoAI", this.isNoAi()); + } ++ ++ compound.putBoolean("Bukkit.Aware", this.aware); // CraftBukkit + } + + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); ++ ++ // CraftBukkit start - If looting or persistence is false only use it if it was set after we started using it + if (compound.contains("CanPickUpLoot", 1)) { +- this.setCanPickUpLoot(compound.getBoolean("CanPickUpLoot")); ++ boolean data = compound.getBoolean("CanPickUpLoot"); ++ if (isLevelAtLeast(compound, 1) || data) { ++ this.setCanPickUpLoot(data); ++ } + } + +- this.persistenceRequired = compound.getBoolean("PersistenceRequired"); ++ boolean data = compound.getBoolean("PersistenceRequired"); ++ if (isLevelAtLeast(compound, 1) || data) { ++ this.persistenceRequired = data; ++ } ++ // CraftBukkit end ++ ListTag nbttaglist; ++ int i; ++ + if (compound.contains("ArmorItems", 9)) { +- ListTag list = compound.getList("ArmorItems", 10); ++ nbttaglist = compound.getList("ArmorItems", 10); + +- for (int i = 0; i < this.armorItems.size(); i++) { +- this.armorItems.set(i, ItemStack.of(list.getCompound(i))); ++ for (i = 0; i < this.armorItems.size(); ++i) { ++ this.armorItems.set(i, ItemStack.of(nbttaglist.getCompound(i))); + } + } + + if (compound.contains("HandItems", 9)) { +- ListTag list = compound.getList("HandItems", 10); ++ nbttaglist = compound.getList("HandItems", 10); + +- for (int i = 0; i < this.handItems.size(); i++) { +- this.handItems.set(i, ItemStack.of(list.getCompound(i))); ++ for (i = 0; i < this.handItems.size(); ++i) { ++ this.handItems.set(i, ItemStack.of(nbttaglist.getCompound(i))); + } + } + + if (compound.contains("ArmorDropChances", 9)) { +- ListTag list = compound.getList("ArmorDropChances", 5); ++ nbttaglist = compound.getList("ArmorDropChances", 5); + +- for (int i = 0; i < list.size(); i++) { +- this.armorDropChances[i] = list.getFloat(i); ++ for (i = 0; i < nbttaglist.size(); ++i) { ++ this.armorDropChances[i] = nbttaglist.getFloat(i); + } + } + + if (compound.contains("HandDropChances", 9)) { +- ListTag list = compound.getList("HandDropChances", 5); ++ nbttaglist = compound.getList("HandDropChances", 5); + +- for (int i = 0; i < list.size(); i++) { +- this.handDropChances[i] = list.getFloat(i); ++ for (i = 0; i < nbttaglist.size(); ++i) { ++ this.handDropChances[i] = nbttaglist.getFloat(i); + } + } + +@@ -474,6 +610,11 @@ + } + + this.setNoAi(compound.getBoolean("NoAI")); ++ // CraftBukkit start ++ if (compound.contains("Bukkit.Aware")) { ++ this.aware = compound.getBoolean("Bukkit.Aware"); ++ } ++ // CraftBukkit end + } + + @Override +@@ -487,7 +628,7 @@ + return this.lootTable == null ? this.getDefaultLootTable() : this.lootTable; + } + +- protected ResourceLocation getDefaultLootTable() { ++ public ResourceLocation getDefaultLootTable() { + return super.getLootTable(); + } + +@@ -518,19 +659,16 @@ + public void aiStep() { + super.aiStep(); + this.level().getProfiler().push("looting"); +- if (!this.level().isClientSide +- && this.canPickUpLoot() +- && this.isAlive() +- && !this.dead +- && this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- Vec3i pickupReach = this.getPickupReach(); ++ if (!this.level().isClientSide && this.canPickUpLoot() && this.isAlive() && !this.dead && this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ Vec3i baseblockposition = this.getPickupReach(); ++ List list = this.level().getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate((double) baseblockposition.getX(), (double) baseblockposition.getY(), (double) baseblockposition.getZ())); ++ Iterator iterator = list.iterator(); + +- for (ItemEntity itemEntity : this.level() +- .getEntitiesOfClass( +- ItemEntity.class, this.getBoundingBox().inflate((double)pickupReach.getX(), (double)pickupReach.getY(), (double)pickupReach.getZ()) +- )) { +- if (!itemEntity.isRemoved() && !itemEntity.getItem().isEmpty() && !itemEntity.hasPickUpDelay() && this.wantsToPickUp(itemEntity.getItem())) { +- this.pickUpItem(itemEntity); ++ while (iterator.hasNext()) { ++ ItemEntity entityitem = (ItemEntity) iterator.next(); ++ ++ if (!entityitem.isRemoved() && !entityitem.getItem().isEmpty() && !entityitem.hasPickUpDelay() && this.wantsToPickUp(entityitem.getItem())) { ++ this.pickUpItem(entityitem); + } + } + } +@@ -539,45 +677,64 @@ + } + + protected Vec3i getPickupReach() { +- return ITEM_PICKUP_REACH; ++ return Mob.ITEM_PICKUP_REACH; + } + + protected void pickUpItem(ItemEntity itemEntity) { +- ItemStack item = itemEntity.getItem(); +- ItemStack itemStack = this.equipItemIfPossible(item.copy()); +- if (!itemStack.isEmpty()) { ++ ItemStack itemstack = itemEntity.getItem(); ++ ItemStack itemstack1 = this.equipItemIfPossible(itemstack.copy(), itemEntity); // CraftBukkit - add item ++ ++ if (!itemstack1.isEmpty()) { + this.onItemPickup(itemEntity); +- this.take(itemEntity, itemStack.getCount()); +- item.shrink(itemStack.getCount()); +- if (item.isEmpty()) { ++ this.take(itemEntity, itemstack1.getCount()); ++ itemstack.shrink(itemstack1.getCount()); ++ if (itemstack.isEmpty()) { + itemEntity.discard(); + } + } ++ + } + + public ItemStack equipItemIfPossible(ItemStack stack) { +- EquipmentSlot equipmentSlotForItem = getEquipmentSlotForItem(stack); +- ItemStack itemBySlot = this.getItemBySlot(equipmentSlotForItem); +- boolean canReplaceCurrentItem = this.canReplaceCurrentItem(stack, itemBySlot); +- if (equipmentSlotForItem.isArmor() && !canReplaceCurrentItem) { +- equipmentSlotForItem = EquipmentSlot.MAINHAND; +- itemBySlot = this.getItemBySlot(equipmentSlotForItem); +- canReplaceCurrentItem = itemBySlot.isEmpty(); ++ // CraftBukkit start - add item ++ return this.equipItemIfPossible(stack, null); ++ } ++ ++ public ItemStack equipItemIfPossible(ItemStack itemstack, ItemEntity entityitem) { ++ // CraftBukkit end ++ EquipmentSlot enumitemslot = getEquipmentSlotForItem(itemstack); ++ ItemStack itemstack1 = this.getItemBySlot(enumitemslot); ++ boolean flag = this.canReplaceCurrentItem(itemstack, itemstack1); ++ ++ if (enumitemslot.isArmor() && !flag) { ++ enumitemslot = EquipmentSlot.MAINHAND; ++ itemstack1 = this.getItemBySlot(enumitemslot); ++ flag = itemstack1.isEmpty(); + } + +- if (canReplaceCurrentItem && this.canHoldItem(stack)) { +- double d = (double)this.getEquipmentDropChance(equipmentSlotForItem); +- if (!itemBySlot.isEmpty() && (double)Math.max(this.random.nextFloat() - 0.1F, 0.0F) < d) { +- this.spawnAtLocation(itemBySlot); ++ // CraftBukkit start ++ boolean canPickup = flag && this.canHoldItem(itemstack); ++ if (entityitem != null) { ++ canPickup = !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, entityitem, 0, !canPickup).isCancelled(); ++ } ++ if (canPickup) { ++ // CraftBukkit end ++ double d0 = (double) this.getEquipmentDropChance(enumitemslot); ++ ++ if (!itemstack1.isEmpty() && (double) Math.max(this.random.nextFloat() - 0.1F, 0.0F) < d0) { ++ this.forceDrops = true; // CraftBukkit ++ this.spawnAtLocation(itemstack1); ++ this.forceDrops = false; // CraftBukkit + } + +- if (equipmentSlotForItem.isArmor() && stack.getCount() > 1) { +- ItemStack itemStack = stack.copyWithCount(1); +- this.setItemSlotAndDropWhenKilled(equipmentSlotForItem, itemStack); +- return itemStack; ++ if (enumitemslot.isArmor() && itemstack.getCount() > 1) { ++ ItemStack itemstack2 = itemstack.copyWithCount(1); ++ ++ this.setItemSlotAndDropWhenKilled(enumitemslot, itemstack2); ++ return itemstack2; + } else { +- this.setItemSlotAndDropWhenKilled(equipmentSlotForItem, stack); +- return stack; ++ this.setItemSlotAndDropWhenKilled(enumitemslot, itemstack); ++ return itemstack; + } + } else { + return ItemStack.EMPTY; +@@ -598,6 +755,7 @@ + case ARMOR: + this.armorDropChances[slot.getIndex()] = 2.0F; + } ++ + } + + protected boolean canReplaceCurrentItem(ItemStack candidate, ItemStack existing) { +@@ -607,58 +765,61 @@ + if (!(existing.getItem() instanceof SwordItem)) { + return true; + } else { +- SwordItem swordItem = (SwordItem)candidate.getItem(); +- SwordItem swordItem1 = (SwordItem)existing.getItem(); +- return swordItem.getDamage() != swordItem1.getDamage() +- ? swordItem.getDamage() > swordItem1.getDamage() +- : this.canReplaceEqualItem(candidate, existing); ++ SwordItem itemsword = (SwordItem) candidate.getItem(); ++ SwordItem itemsword1 = (SwordItem) existing.getItem(); ++ ++ return itemsword.getDamage() != itemsword1.getDamage() ? itemsword.getDamage() > itemsword1.getDamage() : this.canReplaceEqualItem(candidate, existing); + } + } else if (candidate.getItem() instanceof BowItem && existing.getItem() instanceof BowItem) { + return this.canReplaceEqualItem(candidate, existing); + } else if (candidate.getItem() instanceof CrossbowItem && existing.getItem() instanceof CrossbowItem) { + return this.canReplaceEqualItem(candidate, existing); +- } else if (candidate.getItem() instanceof ArmorItem armorItem) { +- if (EnchantmentHelper.hasBindingCurse(existing)) { +- return false; +- } else if (!(existing.getItem() instanceof ArmorItem)) { +- return true; +- } else { +- ArmorItem armorItem1 = (ArmorItem)existing.getItem(); +- if (armorItem.getDefense() != armorItem1.getDefense()) { +- return armorItem.getDefense() > armorItem1.getDefense(); +- } else { +- return armorItem.getToughness() != armorItem1.getToughness() +- ? armorItem.getToughness() > armorItem1.getToughness() +- : this.canReplaceEqualItem(candidate, existing); +- } +- } + } else { +- if (candidate.getItem() instanceof DiggerItem) { +- if (existing.getItem() instanceof BlockItem) { ++ Item item = candidate.getItem(); ++ ++ if (item instanceof ArmorItem) { ++ ArmorItem itemarmor = (ArmorItem) item; ++ ++ if (EnchantmentHelper.hasBindingCurse(existing)) { ++ return false; ++ } else if (!(existing.getItem() instanceof ArmorItem)) { + return true; +- } ++ } else { ++ ArmorItem itemarmor1 = (ArmorItem) existing.getItem(); + +- if (existing.getItem() instanceof DiggerItem diggerItem) { +- DiggerItem diggerItem1 = (DiggerItem)candidate.getItem(); +- if (diggerItem1.getAttackDamage() != diggerItem.getAttackDamage()) { +- return diggerItem1.getAttackDamage() > diggerItem.getAttackDamage(); ++ return itemarmor.getDefense() != itemarmor1.getDefense() ? itemarmor.getDefense() > itemarmor1.getDefense() : (itemarmor.getToughness() != itemarmor1.getToughness() ? itemarmor.getToughness() > itemarmor1.getToughness() : this.canReplaceEqualItem(candidate, existing)); ++ } ++ } else { ++ if (candidate.getItem() instanceof DiggerItem) { ++ if (existing.getItem() instanceof BlockItem) { ++ return true; + } + +- return this.canReplaceEqualItem(candidate, existing); ++ Item item1 = existing.getItem(); ++ ++ if (item1 instanceof DiggerItem) { ++ DiggerItem itemtool = (DiggerItem) item1; ++ DiggerItem itemtool1 = (DiggerItem) candidate.getItem(); ++ ++ if (itemtool1.getAttackDamage() != itemtool.getAttackDamage()) { ++ return itemtool1.getAttackDamage() > itemtool.getAttackDamage(); ++ } ++ ++ return this.canReplaceEqualItem(candidate, existing); ++ } + } +- } + +- return false; ++ return false; ++ } + } + } + + public boolean canReplaceEqualItem(ItemStack candidate, ItemStack existing) { +- return candidate.getDamageValue() < existing.getDamageValue() +- || candidate.hasTag() && !existing.hasTag() +- || candidate.hasTag() +- && existing.hasTag() +- && candidate.getTag().getAllKeys().stream().anyMatch(stack -> !stack.equals("Damage")) +- && !existing.getTag().getAllKeys().stream().anyMatch(stack -> !stack.equals("Damage")); ++ return candidate.getDamageValue() >= existing.getDamageValue() && (!candidate.hasTag() || existing.hasTag()) ? (candidate.hasTag() && existing.hasTag() ? candidate.getTag().getAllKeys().stream().anyMatch((s) -> { ++ return !s.equals("Damage"); ++ }) && !existing.getTag().getAllKeys().stream().anyMatch((s) -> { ++ return !s.equals("Damage"); ++ }) : false) : true; + } + + public boolean canHoldItem(ItemStack stack) { +@@ -686,23 +847,27 @@ + if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.shouldDespawnInPeaceful()) { + this.discard(); + } else if (!this.isPersistenceRequired() && !this.requiresCustomPersistence()) { +- Entity nearestPlayer = this.level().getNearestPlayer(this, -1.0); +- if (nearestPlayer != null) { +- double d = nearestPlayer.distanceToSqr(this); +- int despawnDistance = this.getType().getCategory().getDespawnDistance(); +- int i = despawnDistance * despawnDistance; +- if (d > (double)i && this.removeWhenFarAway(d)) { ++ Player entityhuman = this.level().getNearestPlayer(this, -1.0D); ++ ++ if (entityhuman != null) { ++ double d0 = entityhuman.distanceToSqr((Entity) this); ++ int i = this.getType().getCategory().getDespawnDistance(); ++ int j = i * i; ++ ++ if (d0 > (double) j && this.removeWhenFarAway(d0)) { + this.discard(); + } + +- int noDespawnDistance = this.getType().getCategory().getNoDespawnDistance(); +- int i1 = noDespawnDistance * noDespawnDistance; +- if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d > (double)i1 && this.removeWhenFarAway(d)) { ++ int k = this.getType().getCategory().getNoDespawnDistance(); ++ int l = k * k; ++ ++ if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d0 > (double) l && this.removeWhenFarAway(d0)) { + this.discard(); +- } else if (d < (double)i1) { ++ } else if (d0 < (double) l) { + this.noActionTime = 0; + } + } ++ + } else { + this.noActionTime = 0; + } +@@ -710,11 +875,13 @@ + + @Override + protected final void serverAiStep() { +- this.noActionTime++; ++ ++this.noActionTime; ++ if (!this.aware) return; // CraftBukkit + this.level().getProfiler().push("sensing"); + this.sensing.tick(); + this.level().getProfiler().pop(); + int i = this.level().getServer().getTickCount() + this.getId(); ++ + if (i % 2 != 0 && this.tickCount > 1) { + this.level().getProfiler().push("targetSelector"); + this.targetSelector.tickRunningGoals(false); +@@ -753,8 +920,7 @@ + DebugPackets.sendGoalSelector(this.level(), this, this.goalSelector); + } + +- protected void customServerAiStep() { +- } ++ protected void customServerAiStep() {} + + public int getMaxHeadXRot() { + return 40; +@@ -769,41 +935,47 @@ + } + + public void lookAt(Entity entity, float maxYRotIncrease, float maxXRotIncrease) { +- double d = entity.getX() - this.getX(); ++ double d0 = entity.getX() - this.getX(); + double d1 = entity.getZ() - this.getZ(); + double d2; +- if (entity instanceof LivingEntity livingEntity) { +- d2 = livingEntity.getEyeY() - this.getEyeY(); ++ ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ d2 = entityliving.getEyeY() - this.getEyeY(); + } else { +- d2 = (entity.getBoundingBox().minY + entity.getBoundingBox().maxY) / 2.0 - this.getEyeY(); ++ d2 = (entity.getBoundingBox().minY + entity.getBoundingBox().maxY) / 2.0D - this.getEyeY(); + } + +- double squareRoot = Math.sqrt(d * d + d1 * d1); +- float f = (float)(Mth.atan2(d1, d) * 180.0F / (float)Math.PI) - 90.0F; +- float f1 = (float)(-(Mth.atan2(d2, squareRoot) * 180.0F / (float)Math.PI)); +- this.setXRot(this.rotlerp(this.getXRot(), f1, maxXRotIncrease)); +- this.setYRot(this.rotlerp(this.getYRot(), f, maxYRotIncrease)); ++ double d3 = Math.sqrt(d0 * d0 + d1 * d1); ++ float f2 = (float) (Mth.atan2(d1, d0) * 57.2957763671875D) - 90.0F; ++ float f3 = (float) (-(Mth.atan2(d2, d3) * 57.2957763671875D)); ++ ++ this.setXRot(this.rotlerp(this.getXRot(), f3, maxXRotIncrease)); ++ this.setYRot(this.rotlerp(this.getYRot(), f2, maxYRotIncrease)); + } + + private float rotlerp(float angle, float targetAngle, float maxIncrease) { +- float f = Mth.wrapDegrees(targetAngle - angle); +- if (f > maxIncrease) { +- f = maxIncrease; ++ float f3 = Mth.wrapDegrees(targetAngle - angle); ++ ++ if (f3 > maxIncrease) { ++ f3 = maxIncrease; + } + +- if (f < -maxIncrease) { +- f = -maxIncrease; ++ if (f3 < -maxIncrease) { ++ f3 = -maxIncrease; + } + +- return angle + f; ++ return angle + f3; + } + +- public static boolean checkMobSpawnRules(EntityType type, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) { +- BlockPos blockPos = pos.below(); +- return spawnType == MobSpawnType.SPAWNER || level.getBlockState(blockPos).isValidSpawn(level, blockPos, type); ++ public static boolean checkMobSpawnRules(EntityType type, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ BlockPos blockposition1 = pos.below(); ++ ++ return spawnType == EnumMobSpawn.SPAWNER || level.getBlockState(blockposition1).isValidSpawn(level, blockposition1, type); + } + +- public boolean checkSpawnRules(LevelAccessor level, MobSpawnType reason) { ++ public boolean checkSpawnRules(LevelAccessor level, EnumMobSpawn reason) { + return true; + } + +@@ -824,13 +996,14 @@ + if (this.getTarget() == null) { + return 3; + } else { +- int i = (int)(this.getHealth() - this.getMaxHealth() * 0.33F); +- int var2 = i - (3 - this.level().getDifficulty().getId()) * 4; +- if (var2 < 0) { +- var2 = 0; ++ int i = (int) (this.getHealth() - this.getMaxHealth() * 0.33F); ++ ++ i -= (3 - this.level().getDifficulty().getId()) * 4; ++ if (i < 0) { ++ i = 0; + } + +- return var2 + 3; ++ return i + 3; + } + } + +@@ -848,9 +1021,9 @@ + public ItemStack getItemBySlot(EquipmentSlot slot) { + switch (slot.getType()) { + case HAND: +- return this.handItems.get(slot.getIndex()); ++ return (ItemStack) this.handItems.get(slot.getIndex()); + case ARMOR: +- return this.armorItems.get(slot.getIndex()); ++ return (ItemStack) this.armorItems.get(slot.getIndex()); + default: + return ItemStack.EMPTY; + } +@@ -861,80 +1034,98 @@ + this.verifyEquippedItem(stack); + switch (slot.getType()) { + case HAND: +- this.onEquipItem(slot, this.handItems.set(slot.getIndex(), stack), stack); ++ this.onEquipItem(slot, (ItemStack) this.handItems.set(slot.getIndex(), stack), stack); + break; + case ARMOR: +- this.onEquipItem(slot, this.armorItems.set(slot.getIndex(), stack), stack); ++ this.onEquipItem(slot, (ItemStack) this.armorItems.set(slot.getIndex(), stack), stack); + } ++ + } + + @Override + protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { + super.dropCustomDeathLoot(source, looting, recentlyHit); ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ int j = aenumitemslot.length; + +- for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) { +- ItemStack itemBySlot = this.getItemBySlot(equipmentSlot); +- float equipmentDropChance = this.getEquipmentDropChance(equipmentSlot); +- boolean flag = equipmentDropChance > 1.0F; +- if (!itemBySlot.isEmpty() +- && !EnchantmentHelper.hasVanishingCurse(itemBySlot) +- && (recentlyHit || flag) +- && Math.max(this.random.nextFloat() - (float)looting * 0.01F, 0.0F) < equipmentDropChance) { +- if (!flag && itemBySlot.isDamageableItem()) { +- itemBySlot.setDamageValue( +- itemBySlot.getMaxDamage() - this.random.nextInt(1 + this.random.nextInt(Math.max(itemBySlot.getMaxDamage() - 3, 1))) +- ); ++ for (int k = 0; k < j; ++k) { ++ EquipmentSlot enumitemslot = aenumitemslot[k]; ++ ItemStack itemstack = this.getItemBySlot(enumitemslot); ++ float f = this.getEquipmentDropChance(enumitemslot); ++ boolean flag1 = f > 1.0F; ++ ++ if (!itemstack.isEmpty() && !EnchantmentHelper.hasVanishingCurse(itemstack) && (recentlyHit || flag1) && Math.max(this.random.nextFloat() - (float) looting * 0.01F, 0.0F) < f) { ++ if (!flag1 && itemstack.isDamageableItem()) { ++ itemstack.setDamageValue(itemstack.getMaxDamage() - this.random.nextInt(1 + this.random.nextInt(Math.max(itemstack.getMaxDamage() - 3, 1)))); + } + +- this.spawnAtLocation(itemBySlot); +- this.setItemSlot(equipmentSlot, ItemStack.EMPTY); ++ this.spawnAtLocation(itemstack); ++ this.setItemSlot(enumitemslot, ItemStack.EMPTY); + } + } ++ + } + + protected float getEquipmentDropChance(EquipmentSlot slot) { +- return switch (slot.getType()) { +- case HAND -> this.handDropChances[slot.getIndex()]; +- case ARMOR -> this.armorDropChances[slot.getIndex()]; +- default -> 0.0F; +- }; ++ float f; ++ ++ switch (slot.getType()) { ++ case HAND: ++ f = this.handDropChances[slot.getIndex()]; ++ break; ++ case ARMOR: ++ f = this.armorDropChances[slot.getIndex()]; ++ break; ++ default: ++ f = 0.0F; ++ } ++ ++ return f; + } + + protected void populateDefaultEquipmentSlots(RandomSource random, DifficultyInstance difficulty) { + if (random.nextFloat() < 0.15F * difficulty.getSpecialMultiplier()) { +- int randomInt = random.nextInt(2); ++ int i = random.nextInt(2); + float f = this.level().getDifficulty() == Difficulty.HARD ? 0.1F : 0.25F; ++ + if (random.nextFloat() < 0.095F) { +- randomInt++; ++ ++i; + } + + if (random.nextFloat() < 0.095F) { +- randomInt++; ++ ++i; + } + + if (random.nextFloat() < 0.095F) { +- randomInt++; ++ ++i; + } + + boolean flag = true; ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ int j = aenumitemslot.length; + +- for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) { +- if (equipmentSlot.getType() == EquipmentSlot.Type.ARMOR) { +- ItemStack itemBySlot = this.getItemBySlot(equipmentSlot); ++ for (int k = 0; k < j; ++k) { ++ EquipmentSlot enumitemslot = aenumitemslot[k]; ++ ++ if (enumitemslot.getType() == EquipmentSlot.Function.ARMOR) { ++ ItemStack itemstack = this.getItemBySlot(enumitemslot); ++ + if (!flag && random.nextFloat() < f) { + break; + } + + flag = false; +- if (itemBySlot.isEmpty()) { +- Item equipmentForSlot = getEquipmentForSlot(equipmentSlot, randomInt); +- if (equipmentForSlot != null) { +- this.setItemSlot(equipmentSlot, new ItemStack(equipmentForSlot)); ++ if (itemstack.isEmpty()) { ++ Item item = getEquipmentForSlot(enumitemslot, i); ++ ++ if (item != null) { ++ this.setItemSlot(enumitemslot, new ItemStack(item)); + } + } + } + } + } ++ + } + + @Nullable +@@ -994,42 +1185,44 @@ + } + + protected void populateDefaultEquipmentEnchantments(RandomSource random, DifficultyInstance difficulty) { +- float specialMultiplier = difficulty.getSpecialMultiplier(); +- this.enchantSpawnedWeapon(random, specialMultiplier); ++ float f = difficulty.getSpecialMultiplier(); + +- for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) { +- if (equipmentSlot.getType() == EquipmentSlot.Type.ARMOR) { +- this.enchantSpawnedArmor(random, specialMultiplier, equipmentSlot); ++ this.enchantSpawnedWeapon(random, f); ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ int i = aenumitemslot.length; ++ ++ for (int j = 0; j < i; ++j) { ++ EquipmentSlot enumitemslot = aenumitemslot[j]; ++ ++ if (enumitemslot.getType() == EquipmentSlot.Function.ARMOR) { ++ this.enchantSpawnedArmor(random, f, enumitemslot); + } + } ++ + } + + protected void enchantSpawnedWeapon(RandomSource random, float chanceMultiplier) { + if (!this.getMainHandItem().isEmpty() && random.nextFloat() < 0.25F * chanceMultiplier) { +- this.setItemSlot( +- EquipmentSlot.MAINHAND, +- EnchantmentHelper.enchantItem(random, this.getMainHandItem(), (int)(5.0F + chanceMultiplier * (float)random.nextInt(18)), false) +- ); ++ this.setItemSlot(EquipmentSlot.MAINHAND, EnchantmentHelper.enchantItem(random, this.getMainHandItem(), (int) (5.0F + chanceMultiplier * (float) random.nextInt(18)), false)); + } ++ + } + + protected void enchantSpawnedArmor(RandomSource random, float chanceMultiplier, EquipmentSlot slot) { +- ItemStack itemBySlot = this.getItemBySlot(slot); +- if (!itemBySlot.isEmpty() && random.nextFloat() < 0.5F * chanceMultiplier) { +- this.setItemSlot(slot, EnchantmentHelper.enchantItem(random, itemBySlot, (int)(5.0F + chanceMultiplier * (float)random.nextInt(18)), false)); ++ ItemStack itemstack = this.getItemBySlot(slot); ++ ++ if (!itemstack.isEmpty() && random.nextFloat() < 0.5F * chanceMultiplier) { ++ this.setItemSlot(slot, EnchantmentHelper.enchantItem(random, itemstack, (int) (5.0F + chanceMultiplier * (float) random.nextInt(18)), false)); + } ++ + } + + @Nullable +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- RandomSource random = level.getRandom(); +- this.getAttribute(Attributes.FOLLOW_RANGE) +- .addPermanentModifier( +- new AttributeModifier("Random spawn bonus", random.triangle(0.0, 0.11485000000000001), AttributeModifier.Operation.MULTIPLY_BASE) +- ); +- if (random.nextFloat() < 0.05F) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ RandomSource randomsource = level.getRandom(); ++ ++ this.getAttribute(Attributes.FOLLOW_RANGE).addPermanentModifier(new AttributeModifier("Random spawn bonus", randomsource.triangle(0.0D, 0.11485000000000001D), AttributeModifier.Operation.MULTIPLY_BASE)); ++ if (randomsource.nextFloat() < 0.05F) { + this.setLeftHanded(true); + } else { + this.setLeftHanded(false); +@@ -1050,6 +1243,7 @@ + case ARMOR: + this.armorDropChances[slot.getIndex()] = chance; + } ++ + } + + public boolean canPickUpLoot() { +@@ -1062,8 +1256,9 @@ + + @Override + public boolean canTakeItem(ItemStack itemstack) { +- EquipmentSlot equipmentSlotForItem = getEquipmentSlotForItem(itemstack); +- return this.getItemBySlot(equipmentSlotForItem).isEmpty() && this.canPickUpLoot(); ++ EquipmentSlot enumitemslot = getEquipmentSlotForItem(itemstack); ++ ++ return this.getItemBySlot(enumitemslot).isEmpty() && this.canPickUpLoot(); + } + + public boolean isPersistenceRequired() { +@@ -1071,23 +1266,30 @@ + } + + @Override +- public final InteractionResult interact(Player player, InteractionHand hand) { ++ public final InteractionResult interact(Player player, EnumHand hand) { + if (!this.isAlive()) { + return InteractionResult.PASS; + } else if (this.getLeashHolder() == player) { ++ // CraftBukkit start - fire PlayerUnleashEntityEvent ++ if (CraftEventFactory.callPlayerUnleashEntityEvent(this, player, hand).isCancelled()) { ++ ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, this.getLeashHolder())); ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.dropLeash(true, !player.getAbilities().instabuild); + this.gameEvent(GameEvent.ENTITY_INTERACT, player); + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { +- InteractionResult interactionResult = this.checkAndHandleImportantInteractions(player, hand); +- if (interactionResult.consumesAction()) { ++ InteractionResult enuminteractionresult = this.checkAndHandleImportantInteractions(player, hand); ++ ++ if (enuminteractionresult.consumesAction()) { + this.gameEvent(GameEvent.ENTITY_INTERACT, player); +- return interactionResult; ++ return enuminteractionresult; + } else { +- interactionResult = this.mobInteract(player, hand); +- if (interactionResult.consumesAction()) { ++ enuminteractionresult = this.mobInteract(player, hand); ++ if (enuminteractionresult.consumesAction()) { + this.gameEvent(GameEvent.ENTITY_INTERACT, player); +- return interactionResult; ++ return enuminteractionresult; + } else { + return super.interact(player, hand); + } +@@ -1095,27 +1297,36 @@ + } + } + +- private InteractionResult checkAndHandleImportantInteractions(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (itemInHand.is(Items.LEAD) && this.canBeLeashed(player)) { ++ private InteractionResult checkAndHandleImportantInteractions(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (itemstack.is(Items.LEAD) && this.canBeLeashed(player)) { ++ // CraftBukkit start - fire PlayerLeashEntityEvent ++ if (CraftEventFactory.callPlayerLeashEntityEvent(this, player, player, hand).isCancelled()) { ++ ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, this.getLeashHolder())); ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.setLeashedTo(player, true); +- itemInHand.shrink(1); ++ itemstack.shrink(1); + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { +- if (itemInHand.is(Items.NAME_TAG)) { +- InteractionResult interactionResult = itemInHand.interactLivingEntity(player, this, hand); +- if (interactionResult.consumesAction()) { +- return interactionResult; ++ if (itemstack.is(Items.NAME_TAG)) { ++ InteractionResult enuminteractionresult = itemstack.interactLivingEntity(player, this, hand); ++ ++ if (enuminteractionresult.consumesAction()) { ++ return enuminteractionresult; + } + } + +- if (itemInHand.getItem() instanceof SpawnEggItem) { ++ if (itemstack.getItem() instanceof SpawnEggItem) { + if (this.level() instanceof ServerLevel) { +- SpawnEggItem spawnEggItem = (SpawnEggItem)itemInHand.getItem(); +- Optional optional = spawnEggItem.spawnOffspringFromSpawnEgg( +- player, this, (EntityType)this.getType(), (ServerLevel)this.level(), this.position(), itemInHand +- ); +- optional.ifPresent(mob -> this.onOffspringSpawnedFromEgg(player, mob)); ++ SpawnEggItem itemmonsteregg = (SpawnEggItem) itemstack.getItem(); ++ Optional optional = itemmonsteregg.spawnOffspringFromSpawnEgg(player, this, (EntityType) this.getType(), (ServerLevel) this.level(), this.position(), itemstack); // CraftBukkit - decompile error ++ ++ optional.ifPresent((entityinsentient) -> { ++ this.onOffspringSpawnedFromEgg(player, entityinsentient); ++ }); + return optional.isPresent() ? InteractionResult.SUCCESS : InteractionResult.PASS; + } else { + return InteractionResult.CONSUME; +@@ -1126,10 +1337,9 @@ + } + } + +- protected void onOffspringSpawnedFromEgg(Player player, Mob child) { +- } ++ protected void onOffspringSpawnedFromEgg(Player player, Mob child) {} + +- protected InteractionResult mobInteract(Player player, InteractionHand hand) { ++ protected InteractionResult mobInteract(Player player, EnumHand hand) { + return InteractionResult.PASS; + } + +@@ -1138,12 +1348,12 @@ + } + + public boolean isWithinRestriction(BlockPos pos) { +- return this.restrictRadius == -1.0F || this.restrictCenter.distSqr(pos) < (double)(this.restrictRadius * this.restrictRadius); ++ return this.restrictRadius == -1.0F ? true : this.restrictCenter.distSqr(pos) < (double) (this.restrictRadius * this.restrictRadius); + } + + public void restrictTo(BlockPos pos, int distance) { + this.restrictCenter = pos; +- this.restrictRadius = (float)distance; ++ this.restrictRadius = (float) distance; + } + + public BlockPos getRestrictCenter() { +@@ -1162,49 +1372,67 @@ + return this.restrictRadius != -1.0F; + } + ++ // CraftBukkit start + @Nullable + public T convertTo(EntityType entityType, boolean transferInventory) { ++ return this.convertTo(entityType, transferInventory, EntityTransformEvent.TransformReason.UNKNOWN, CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ @Nullable ++ public T convertTo(EntityType entitytypes, boolean flag, EntityTransformEvent.TransformReason transformReason, CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end + if (this.isRemoved()) { + return null; + } else { +- T mob = (T)entityType.create(this.level()); +- if (mob == null) { ++ T t0 = entitytypes.create(this.level()); // CraftBukkit - decompile error ++ ++ if (t0 == null) { + return null; + } else { +- mob.copyPosition(this); +- mob.setBaby(this.isBaby()); +- mob.setNoAi(this.isNoAi()); ++ t0.copyPosition(this); ++ t0.setBaby(this.isBaby()); ++ t0.setNoAi(this.isNoAi()); + if (this.hasCustomName()) { +- mob.setCustomName(this.getCustomName()); +- mob.setCustomNameVisible(this.isCustomNameVisible()); ++ t0.setCustomName(this.getCustomName()); ++ t0.setCustomNameVisible(this.isCustomNameVisible()); + } + + if (this.isPersistenceRequired()) { +- mob.setPersistenceRequired(); ++ t0.setPersistenceRequired(); + } + +- mob.setInvulnerable(this.isInvulnerable()); +- if (transferInventory) { +- mob.setCanPickUpLoot(this.canPickUpLoot()); ++ t0.setInvulnerable(this.isInvulnerable()); ++ if (flag) { ++ t0.setCanPickUpLoot(this.canPickUpLoot()); ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ int i = aenumitemslot.length; + +- for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) { +- ItemStack itemBySlot = this.getItemBySlot(equipmentSlot); +- if (!itemBySlot.isEmpty()) { +- mob.setItemSlot(equipmentSlot, itemBySlot.copyAndClear()); +- mob.setDropChance(equipmentSlot, this.getEquipmentDropChance(equipmentSlot)); ++ for (int j = 0; j < i; ++j) { ++ EquipmentSlot enumitemslot = aenumitemslot[j]; ++ ItemStack itemstack = this.getItemBySlot(enumitemslot); ++ ++ if (!itemstack.isEmpty()) { ++ t0.setItemSlot(enumitemslot, itemstack.copyAndClear()); ++ t0.setDropChance(enumitemslot, this.getEquipmentDropChance(enumitemslot)); + } + } + } + +- this.level().addFreshEntity(mob); ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, t0, transformReason).isCancelled()) { ++ return null; ++ } ++ this.level().addFreshEntity(t0, spawnReason); ++ // CraftBukkit end + if (this.isPassenger()) { +- Entity vehicle = this.getVehicle(); ++ Entity entity = this.getVehicle(); ++ + this.stopRiding(); +- mob.startRiding(vehicle, true); ++ t0.startRiding(entity, true); + } + + this.discard(); +- return mob; ++ return t0; + } + } + } +@@ -1216,8 +1444,10 @@ + + if (this.leashHolder != null) { + if (!this.isAlive() || !this.leashHolder.isAlive()) { +- this.dropLeash(true, true); ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE)); // CraftBukkit ++ this.dropLeash(true, !this.leashHolder.pluginRemoved);// CraftBukkit - SPIGOT-7487: Don't drop leash, when the holder was removed by a plugin + } ++ + } + } + +@@ -1226,17 +1456,20 @@ + this.leashHolder = null; + this.leashInfoTag = null; + if (!this.level().isClientSide && dropLeash) { +- this.spawnAtLocation(Items.LEAD); ++ this.forceDrops = true; // CraftBukkit ++ this.spawnAtLocation((IMaterial) Items.LEAD); ++ this.forceDrops = false; // CraftBukkit + } + + if (!this.level().isClientSide && broadcastPacket && this.level() instanceof ServerLevel) { +- ((ServerLevel)this.level()).getChunkSource().broadcast(this, new ClientboundSetEntityLinkPacket(this, null)); ++ ((ServerLevel) this.level()).getChunkSource().broadcast(this, new ClientboundSetEntityLinkPacket(this, (Entity) null)); + } + } ++ + } + + public boolean canBeLeashed(Player player) { +- return !this.isLeashed() && !(this instanceof Enemy); ++ return !this.isLeashed() && !(this instanceof IMonster); + } + + public boolean isLeashed() { +@@ -1256,12 +1489,13 @@ + this.leashHolder = leashHolder; + this.leashInfoTag = null; + if (!this.level().isClientSide && broadcastPacket && this.level() instanceof ServerLevel) { +- ((ServerLevel)this.level()).getChunkSource().broadcast(this, new ClientboundSetEntityLinkPacket(this, this.leashHolder)); ++ ((ServerLevel) this.level()).getChunkSource().broadcast(this, new ClientboundSetEntityLinkPacket(this, this.leashHolder)); + } + + if (this.isPassenger()) { + this.stopRiding(); + } ++ + } + + public void setDelayedLeashHolderId(int leashHolderID) { +@@ -1271,34 +1505,41 @@ + + @Override + public boolean startRiding(Entity entity, boolean force) { +- boolean flag = super.startRiding(entity, force); +- if (flag && this.isLeashed()) { ++ boolean flag1 = super.startRiding(entity, force); ++ ++ if (flag1 && this.isLeashed()) { ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit + this.dropLeash(true, true); + } + +- return flag; ++ return flag1; + } + + private void restoreLeashFromSave() { + if (this.leashInfoTag != null && this.level() instanceof ServerLevel) { + if (this.leashInfoTag.hasUUID("UUID")) { +- UUID uUID = this.leashInfoTag.getUUID("UUID"); +- Entity entity = ((ServerLevel)this.level()).getEntity(uUID); ++ UUID uuid = this.leashInfoTag.getUUID("UUID"); ++ Entity entity = ((ServerLevel) this.level()).getEntity(uuid); ++ + if (entity != null) { + this.setLeashedTo(entity, true); + return; + } + } else if (this.leashInfoTag.contains("X", 99) && this.leashInfoTag.contains("Y", 99) && this.leashInfoTag.contains("Z", 99)) { +- BlockPos blockPos = NbtUtils.readBlockPos(this.leashInfoTag); +- this.setLeashedTo(LeashFenceKnotEntity.getOrCreateKnot(this.level(), blockPos), true); ++ BlockPos blockposition = NbtUtils.readBlockPos(this.leashInfoTag); ++ ++ this.setLeashedTo(LeashFenceKnotEntity.getOrCreateKnot(this.level(), blockposition), true); + return; + } + + if (this.tickCount > 100) { +- this.spawnAtLocation(Items.LEAD); ++ this.forceDrops = true; // CraftBukkit ++ this.spawnAtLocation((IMaterial) Items.LEAD); ++ this.forceDrops = false; // CraftBukkit + this.leashInfoTag = null; + } + } ++ + } + + @Override +@@ -1307,34 +1548,36 @@ + } + + public void setNoAi(boolean noAi) { +- byte b = this.entityData.get(DATA_MOB_FLAGS_ID); +- this.entityData.set(DATA_MOB_FLAGS_ID, noAi ? (byte)(b | 1) : (byte)(b & -2)); ++ byte b0 = (Byte) this.entityData.get(Mob.DATA_MOB_FLAGS_ID); ++ ++ this.entityData.set(Mob.DATA_MOB_FLAGS_ID, noAi ? (byte) (b0 | 1) : (byte) (b0 & -2)); + } + + public void setLeftHanded(boolean leftHanded) { +- byte b = this.entityData.get(DATA_MOB_FLAGS_ID); +- this.entityData.set(DATA_MOB_FLAGS_ID, leftHanded ? (byte)(b | 2) : (byte)(b & -3)); ++ byte b0 = (Byte) this.entityData.get(Mob.DATA_MOB_FLAGS_ID); ++ ++ this.entityData.set(Mob.DATA_MOB_FLAGS_ID, leftHanded ? (byte) (b0 | 2) : (byte) (b0 & -3)); + } + + public void setAggressive(boolean aggressive) { +- byte b = this.entityData.get(DATA_MOB_FLAGS_ID); +- this.entityData.set(DATA_MOB_FLAGS_ID, aggressive ? (byte)(b | 4) : (byte)(b & -5)); ++ byte b0 = (Byte) this.entityData.get(Mob.DATA_MOB_FLAGS_ID); ++ ++ this.entityData.set(Mob.DATA_MOB_FLAGS_ID, aggressive ? (byte) (b0 | 4) : (byte) (b0 & -5)); + } + + public boolean isNoAi() { +- return (this.entityData.get(DATA_MOB_FLAGS_ID) & 1) != 0; ++ return ((Byte) this.entityData.get(Mob.DATA_MOB_FLAGS_ID) & 1) != 0; + } + + public boolean isLeftHanded() { +- return (this.entityData.get(DATA_MOB_FLAGS_ID) & 2) != 0; ++ return ((Byte) this.entityData.get(Mob.DATA_MOB_FLAGS_ID) & 2) != 0; + } + + public boolean isAggressive() { +- return (this.entityData.get(DATA_MOB_FLAGS_ID) & 4) != 0; ++ return ((Byte) this.entityData.get(Mob.DATA_MOB_FLAGS_ID) & 4) != 0; + } + +- public void setBaby(boolean baby) { +- } ++ public void setBaby(boolean baby) {} + + @Override + public HumanoidArm getMainArm() { +@@ -1346,54 +1589,56 @@ + } + + protected AABB getAttackBoundingBox() { +- Entity vehicle = this.getVehicle(); +- AABB aABB; +- if (vehicle != null) { +- AABB boundingBox = vehicle.getBoundingBox(); +- AABB boundingBox1 = this.getBoundingBox(); +- aABB = new AABB( +- Math.min(boundingBox1.minX, boundingBox.minX), +- boundingBox1.minY, +- Math.min(boundingBox1.minZ, boundingBox.minZ), +- Math.max(boundingBox1.maxX, boundingBox.maxX), +- boundingBox1.maxY, +- Math.max(boundingBox1.maxZ, boundingBox.maxZ) +- ); ++ Entity entity = this.getVehicle(); ++ AABB axisalignedbb; ++ ++ if (entity != null) { ++ AABB axisalignedbb1 = entity.getBoundingBox(); ++ AABB axisalignedbb2 = this.getBoundingBox(); ++ ++ axisalignedbb = new AABB(Math.min(axisalignedbb2.minX, axisalignedbb1.minX), axisalignedbb2.minY, Math.min(axisalignedbb2.minZ, axisalignedbb1.minZ), Math.max(axisalignedbb2.maxX, axisalignedbb1.maxX), axisalignedbb2.maxY, Math.max(axisalignedbb2.maxZ, axisalignedbb1.maxZ)); + } else { +- aABB = this.getBoundingBox(); ++ axisalignedbb = this.getBoundingBox(); + } + +- return aABB.inflate(DEFAULT_ATTACK_REACH, 0.0, DEFAULT_ATTACK_REACH); ++ return axisalignedbb.inflate(Mob.DEFAULT_ATTACK_REACH, 0.0D, Mob.DEFAULT_ATTACK_REACH); + } + + @Override + public boolean doHurtTarget(Entity entity) { +- float f = (float)this.getAttributeValue(Attributes.ATTACK_DAMAGE); +- float f1 = (float)this.getAttributeValue(Attributes.ATTACK_KNOCKBACK); ++ float f = (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE); ++ float f1 = (float) this.getAttributeValue(Attributes.ATTACK_KNOCKBACK); ++ + if (entity instanceof LivingEntity) { +- f += EnchantmentHelper.getDamageBonus(this.getMainHandItem(), ((LivingEntity)entity).getMobType()); +- f1 += (float)EnchantmentHelper.getKnockbackBonus(this); ++ f += EnchantmentHelper.getDamageBonus(this.getMainHandItem(), ((LivingEntity) entity).getMobType()); ++ f1 += (float) EnchantmentHelper.getKnockbackBonus(this); + } + +- int fireAspect = EnchantmentHelper.getFireAspect(this); +- if (fireAspect > 0) { +- entity.setSecondsOnFire(fireAspect * 4); ++ int i = EnchantmentHelper.getFireAspect(this); ++ ++ if (i > 0) { ++ // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), i * 4); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ entity.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + + boolean flag = entity.hurt(this.damageSources().mobAttack(this), f); ++ + if (flag) { + if (f1 > 0.0F && entity instanceof LivingEntity) { +- ((LivingEntity)entity) +- .knockback( +- (double)(f1 * 0.5F), +- (double)Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)), +- (double)(-Mth.cos(this.getYRot() * (float) (Math.PI / 180.0))) +- ); +- this.setDeltaMovement(this.getDeltaMovement().multiply(0.6, 1.0, 0.6)); ++ ((LivingEntity) entity).knockback((double) (f1 * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F))); ++ this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D)); + } + +- if (entity instanceof Player player) { +- this.maybeDisableShield(player, this.getMainHandItem(), player.isUsingItem() ? player.getUseItem() : ItemStack.EMPTY); ++ if (entity instanceof Player) { ++ Player entityhuman = (Player) entity; ++ ++ this.maybeDisableShield(entityhuman, this.getMainHandItem(), entityhuman.isUsingItem() ? entityhuman.getUseItem() : ItemStack.EMPTY); + } + + this.doEnchantDamageEffects(this, entity); +@@ -1405,23 +1650,23 @@ + + private void maybeDisableShield(Player player, ItemStack mobItemStack, ItemStack playerItemStack) { + if (!mobItemStack.isEmpty() && !playerItemStack.isEmpty() && mobItemStack.getItem() instanceof AxeItem && playerItemStack.is(Items.SHIELD)) { +- float f = 0.25F + (float)EnchantmentHelper.getBlockEfficiency(this) * 0.05F; ++ float f = 0.25F + (float) EnchantmentHelper.getBlockEfficiency(this) * 0.05F; ++ + if (this.random.nextFloat() < f) { + player.getCooldowns().addCooldown(Items.SHIELD, 100); +- this.level().broadcastEntityEvent(player, (byte)30); ++ this.level().broadcastEntityEvent(player, (byte) 30); + } + } ++ + } + + protected boolean isSunBurnTick() { + if (this.level().isDay() && !this.level().isClientSide) { +- float lightLevelDependentMagicValue = this.getLightLevelDependentMagicValue(); +- BlockPos blockPos = BlockPos.containing(this.getX(), this.getEyeY(), this.getZ()); ++ float f = this.getLightLevelDependentMagicValue(); ++ BlockPos blockposition = BlockPos.containing(this.getX(), this.getEyeY(), this.getZ()); + boolean flag = this.isInWaterRainOrBubble() || this.isInPowderSnow || this.wasInPowderSnow; +- if (lightLevelDependentMagicValue > 0.5F +- && this.random.nextFloat() * 30.0F < (lightLevelDependentMagicValue - 0.4F) * 2.0F +- && !flag +- && this.level().canSeeSky(blockPos)) { ++ ++ if (f > 0.5F && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && !flag && this.level().canSeeSky(blockposition)) { + return true; + } + } +@@ -1434,13 +1679,16 @@ + if (this.getNavigation().canFloat()) { + super.jumpInLiquid(fluidTag); + } else { +- this.setDeltaMovement(this.getDeltaMovement().add(0.0, 0.3, 0.0)); ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, 0.3D, 0.0D)); + } ++ + } + + @VisibleForTesting + public void removeFreeWill() { +- this.removeAllGoals(goal -> true); ++ this.removeAllGoals((pathfindergoal) -> { ++ return true; ++ }); + this.getBrain().removeAllBehaviors(); + } + +@@ -1451,18 +1699,21 @@ + @Override + protected void removeAfterChangingDimensions() { + super.removeAfterChangingDimensions(); ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit + this.dropLeash(true, false); +- this.getAllSlots().forEach(slot -> { +- if (!slot.isEmpty()) { +- slot.setCount(0); ++ this.getAllSlots().forEach((itemstack) -> { ++ if (!itemstack.isEmpty()) { ++ itemstack.setCount(0); + } ++ + }); + } + + @Nullable + @Override + public ItemStack getPickResult() { +- SpawnEggItem spawnEggItem = SpawnEggItem.byId(this.getType()); +- return spawnEggItem == null ? null : new ItemStack(spawnEggItem); ++ SpawnEggItem itemmonsteregg = SpawnEggItem.byId(this.getType()); ++ ++ return itemmonsteregg == null ? null : new ItemStack(itemmonsteregg); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/NeutralMob.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/NeutralMob.java.patch new file mode 100644 index 0000000000..9af1f21b52 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/NeutralMob.java.patch @@ -0,0 +1,105 @@ +--- a/net/minecraft/world/entity/NeutralMob.java ++++ b/net/minecraft/world/entity/NeutralMob.java +@@ -10,6 +10,7 @@ + import net.minecraft.world.level.Level; + + public interface NeutralMob { ++ + String TAG_ANGER_TIME = "AngerTime"; + String TAG_ANGRY_AT = "AngryAt"; + +@@ -29,53 +30,58 @@ + if (this.getPersistentAngerTarget() != null) { + nbt.putUUID("AngryAt", this.getPersistentAngerTarget()); + } ++ + } + + default void readPersistentAngerSaveData(Level level, CompoundTag tag) { + this.setRemainingPersistentAngerTime(tag.getInt("AngerTime")); + if (level instanceof ServerLevel) { + if (!tag.hasUUID("AngryAt")) { +- this.setPersistentAngerTarget(null); ++ this.setPersistentAngerTarget((UUID) null); + } else { +- UUID uUID = tag.getUUID("AngryAt"); +- this.setPersistentAngerTarget(uUID); +- Entity entity = ((ServerLevel)level).getEntity(uUID); ++ UUID uuid = tag.getUUID("AngryAt"); ++ ++ this.setPersistentAngerTarget(uuid); ++ Entity entity = ((ServerLevel) level).getEntity(uuid); ++ + if (entity != null) { + if (entity instanceof Mob) { +- this.setLastHurtByMob((Mob)entity); ++ this.setLastHurtByMob((Mob) entity); + } + + if (entity.getType() == EntityType.PLAYER) { +- this.setLastHurtByPlayer((Player)entity); ++ this.setLastHurtByPlayer((Player) entity); + } ++ + } + } + } + } + + default void updatePersistentAnger(ServerLevel serverLevel, boolean updateAnger) { +- LivingEntity target = this.getTarget(); +- UUID persistentAngerTarget = this.getPersistentAngerTarget(); +- if ((target == null || target.isDeadOrDying()) && persistentAngerTarget != null && serverLevel.getEntity(persistentAngerTarget) instanceof Mob) { ++ LivingEntity entityliving = this.getTarget(); ++ UUID uuid = this.getPersistentAngerTarget(); ++ ++ if ((entityliving == null || entityliving.isDeadOrDying()) && uuid != null && serverLevel.getEntity(uuid) instanceof Mob) { + this.stopBeingAngry(); + } else { +- if (target != null && !Objects.equals(persistentAngerTarget, target.getUUID())) { +- this.setPersistentAngerTarget(target.getUUID()); ++ if (entityliving != null && !Objects.equals(uuid, entityliving.getUUID())) { ++ this.setPersistentAngerTarget(entityliving.getUUID()); + this.startPersistentAngerTimer(); + } + +- if (this.getRemainingPersistentAngerTime() > 0 && (target == null || target.getType() != EntityType.PLAYER || !updateAnger)) { ++ if (this.getRemainingPersistentAngerTime() > 0 && (entityliving == null || entityliving.getType() != EntityType.PLAYER || !updateAnger)) { + this.setRemainingPersistentAngerTime(this.getRemainingPersistentAngerTime() - 1); + if (this.getRemainingPersistentAngerTime() == 0) { + this.stopBeingAngry(); + } + } ++ + } + } + + default boolean isAngryAt(LivingEntity target) { +- return this.canAttack(target) +- && (target.getType() == EntityType.PLAYER && this.isAngryAtAllPlayers(target.level()) || target.getUUID().equals(this.getPersistentAngerTarget())); ++ return !this.canAttack(target) ? false : (target.getType() == EntityType.PLAYER && this.isAngryAtAllPlayers(target.level()) ? true : target.getUUID().equals(this.getPersistentAngerTarget())); + } + + default boolean isAngryAtAllPlayers(Level level) { +@@ -100,9 +106,9 @@ + } + + default void stopBeingAngry() { +- this.setLastHurtByMob(null); +- this.setPersistentAngerTarget(null); +- this.setTarget(null); ++ this.setLastHurtByMob((LivingEntity) null); ++ this.setPersistentAngerTarget((UUID) null); ++ this.setTarget((LivingEntity) null, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET, true); // CraftBukkit + this.setRemainingPersistentAngerTime(0); + } + +@@ -115,6 +121,8 @@ + + void setTarget(@Nullable LivingEntity livingEntity); + ++ boolean setTarget(@Nullable LivingEntity entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent); // CraftBukkit ++ + boolean canAttack(LivingEntity entity); + + @Nullable diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/PathfinderMob.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/PathfinderMob.java.patch new file mode 100644 index 0000000000..73b537e4e4 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/PathfinderMob.java.patch @@ -0,0 +1,112 @@ +--- a/net/minecraft/world/entity/PathfinderMob.java ++++ b/net/minecraft/world/entity/PathfinderMob.java +@@ -3,14 +3,17 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.world.entity.ai.goal.Goal; + import net.minecraft.world.entity.ai.goal.PanicGoal; +-import net.minecraft.world.entity.ai.goal.WrappedGoal; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.event.entity.EntityUnleashEvent; ++// CraftBukkit end + + public abstract class PathfinderMob extends Mob { ++ + protected static final float DEFAULT_WALK_TARGET_VALUE = 0.0F; + + protected PathfinderMob(EntityType entityType, Level level) { +@@ -26,7 +29,7 @@ + } + + @Override +- public boolean checkSpawnRules(LevelAccessor level, MobSpawnType spawnReason) { ++ public boolean checkSpawnRules(LevelAccessor level, EnumMobSpawn spawnReason) { + return this.getWalkTargetValue(this.blockPosition(), level) >= 0.0F; + } + +@@ -35,20 +38,23 @@ + } + + public boolean isPanicking() { +- return this.brain.hasMemoryValue(MemoryModuleType.IS_PANICKING) +- ? this.brain.getMemory(MemoryModuleType.IS_PANICKING).isPresent() +- : this.goalSelector.getRunningGoals().anyMatch(wrappedGoal -> wrappedGoal.getGoal() instanceof PanicGoal); ++ return this.brain.hasMemoryValue(MemoryModuleType.IS_PANICKING) ? this.brain.getMemory(MemoryModuleType.IS_PANICKING).isPresent() : this.goalSelector.getRunningGoals().anyMatch((pathfindergoalwrapped) -> { ++ return pathfindergoalwrapped.getGoal() instanceof PanicGoal; ++ }); + } + + @Override + protected void tickLeash() { + super.tickLeash(); +- Entity leashHolder = this.getLeashHolder(); +- if (leashHolder != null && leashHolder.level() == this.level()) { +- this.restrictTo(leashHolder.blockPosition(), 5); +- float f = this.distanceTo(leashHolder); +- if (this instanceof TamableAnimal && ((TamableAnimal)this).isInSittingPose()) { ++ Entity entity = this.getLeashHolder(); ++ ++ if (entity != null && entity.level() == this.level()) { ++ this.restrictTo(entity.blockPosition(), 5); ++ float f = this.distanceTo(entity); ++ ++ if (this instanceof TamableAnimal && ((TamableAnimal) this).isInSittingPose()) { + if (f > 10.0F) { ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit + this.dropLeash(true, true); + } + +@@ -57,25 +63,25 @@ + + this.onLeashDistance(f); + if (f > 10.0F) { ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit + this.dropLeash(true, true); +- this.goalSelector.disableControlFlag(Goal.Flag.MOVE); ++ this.goalSelector.disableControlFlag(Goal.Type.MOVE); + } else if (f > 6.0F) { +- double d = (leashHolder.getX() - this.getX()) / (double)f; +- double d1 = (leashHolder.getY() - this.getY()) / (double)f; +- double d2 = (leashHolder.getZ() - this.getZ()) / (double)f; +- this.setDeltaMovement( +- this.getDeltaMovement().add(Math.copySign(d * d * 0.4, d), Math.copySign(d1 * d1 * 0.4, d1), Math.copySign(d2 * d2 * 0.4, d2)) +- ); ++ double d0 = (entity.getX() - this.getX()) / (double) f; ++ double d1 = (entity.getY() - this.getY()) / (double) f; ++ double d2 = (entity.getZ() - this.getZ()) / (double) f; ++ ++ this.setDeltaMovement(this.getDeltaMovement().add(Math.copySign(d0 * d0 * 0.4D, d0), Math.copySign(d1 * d1 * 0.4D, d1), Math.copySign(d2 * d2 * 0.4D, d2))); + this.checkSlowFallDistance(); + } else if (this.shouldStayCloseToLeashHolder() && !this.isPanicking()) { +- this.goalSelector.enableControlFlag(Goal.Flag.MOVE); ++ this.goalSelector.enableControlFlag(Goal.Type.MOVE); + float f1 = 2.0F; +- Vec3 vec3 = new Vec3(leashHolder.getX() - this.getX(), leashHolder.getY() - this.getY(), leashHolder.getZ() - this.getZ()) +- .normalize() +- .scale((double)Math.max(f - 2.0F, 0.0F)); +- this.getNavigation().moveTo(this.getX() + vec3.x, this.getY() + vec3.y, this.getZ() + vec3.z, this.followLeashSpeed()); ++ Vec3 vec3d = (new Vec3(entity.getX() - this.getX(), entity.getY() - this.getY(), entity.getZ() - this.getZ())).normalize().scale((double) Math.max(f - 2.0F, 0.0F)); ++ ++ this.getNavigation().moveTo(this.getX() + vec3d.x, this.getY() + vec3d.y, this.getZ() + vec3d.z, this.followLeashSpeed()); + } + } ++ + } + + protected boolean shouldStayCloseToLeashHolder() { +@@ -83,9 +89,8 @@ + } + + protected double followLeashSpeed() { +- return 1.0; ++ return 1.0D; + } + +- protected void onLeashDistance(float distance) { +- } ++ protected void onLeashDistance(float distance) {} + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/attributes/Attributes.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/attributes/Attributes.java.patch new file mode 100644 index 0000000000..ce7c0810f8 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/attributes/Attributes.java.patch @@ -0,0 +1,70 @@ +--- a/net/minecraft/world/entity/ai/attributes/Attributes.java ++++ b/net/minecraft/world/entity/ai/attributes/Attributes.java +@@ -1,48 +1,29 @@ ++// mc-dev import + package net.minecraft.world.entity.ai.attributes; + + import net.minecraft.core.Registry; + import net.minecraft.core.registries.BuiltInRegistries; + + public class Attributes { +- public static final Attribute ARMOR = register("generic.armor", new RangedAttribute("attribute.name.generic.armor", 0.0, 0.0, 30.0).setSyncable(true)); +- public static final Attribute ARMOR_TOUGHNESS = register( +- "generic.armor_toughness", new RangedAttribute("attribute.name.generic.armor_toughness", 0.0, 0.0, 20.0).setSyncable(true) +- ); +- public static final Attribute ATTACK_DAMAGE = register( +- "generic.attack_damage", new RangedAttribute("attribute.name.generic.attack_damage", 2.0, 0.0, 2048.0) +- ); +- public static final Attribute ATTACK_KNOCKBACK = register( +- "generic.attack_knockback", new RangedAttribute("attribute.name.generic.attack_knockback", 0.0, 0.0, 5.0) +- ); +- public static final Attribute ATTACK_SPEED = register( +- "generic.attack_speed", new RangedAttribute("attribute.name.generic.attack_speed", 4.0, 0.0, 1024.0).setSyncable(true) +- ); +- public static final Attribute FLYING_SPEED = register( +- "generic.flying_speed", new RangedAttribute("attribute.name.generic.flying_speed", 0.4F, 0.0, 1024.0).setSyncable(true) +- ); +- public static final Attribute FOLLOW_RANGE = register("generic.follow_range", new RangedAttribute("attribute.name.generic.follow_range", 32.0, 0.0, 2048.0)); +- public static final Attribute JUMP_STRENGTH = register( +- "horse.jump_strength", new RangedAttribute("attribute.name.horse.jump_strength", 0.7, 0.0, 2.0).setSyncable(true) +- ); +- public static final Attribute KNOCKBACK_RESISTANCE = register( +- "generic.knockback_resistance", new RangedAttribute("attribute.name.generic.knockback_resistance", 0.0, 0.0, 1.0) +- ); +- public static final Attribute LUCK = register("generic.luck", new RangedAttribute("attribute.name.generic.luck", 0.0, -1024.0, 1024.0).setSyncable(true)); +- public static final Attribute MAX_ABSORPTION = register( +- "generic.max_absorption", new RangedAttribute("attribute.name.generic.max_absorption", 0.0, 0.0, 2048.0) +- ) +- .setSyncable(true); +- public static final Attribute MAX_HEALTH = register( +- "generic.max_health", new RangedAttribute("attribute.name.generic.max_health", 20.0, 1.0, 1024.0).setSyncable(true) +- ); +- public static final Attribute MOVEMENT_SPEED = register( +- "generic.movement_speed", new RangedAttribute("attribute.name.generic.movement_speed", 0.7F, 0.0, 1024.0).setSyncable(true) +- ); +- public static final Attribute SPAWN_REINFORCEMENTS_CHANCE = register( +- "zombie.spawn_reinforcements", new RangedAttribute("attribute.name.zombie.spawn_reinforcements", 0.0, 0.0, 1.0) +- ); + ++ public static final Attribute ARMOR = register("generic.armor", (new RangedAttribute("attribute.name.generic.armor", 0.0D, 0.0D, 30.0D)).setSyncable(true)); ++ public static final Attribute ARMOR_TOUGHNESS = register("generic.armor_toughness", (new RangedAttribute("attribute.name.generic.armor_toughness", 0.0D, 0.0D, 20.0D)).setSyncable(true)); ++ public static final Attribute ATTACK_DAMAGE = register("generic.attack_damage", new RangedAttribute("attribute.name.generic.attack_damage", 2.0D, 0.0D, 2048.0D)); ++ public static final Attribute ATTACK_KNOCKBACK = register("generic.attack_knockback", new RangedAttribute("attribute.name.generic.attack_knockback", 0.0D, 0.0D, 5.0D)); ++ public static final Attribute ATTACK_SPEED = register("generic.attack_speed", (new RangedAttribute("attribute.name.generic.attack_speed", 4.0D, 0.0D, 1024.0D)).setSyncable(true)); ++ public static final Attribute FLYING_SPEED = register("generic.flying_speed", (new RangedAttribute("attribute.name.generic.flying_speed", 0.4000000059604645D, 0.0D, 1024.0D)).setSyncable(true)); ++ public static final Attribute FOLLOW_RANGE = register("generic.follow_range", new RangedAttribute("attribute.name.generic.follow_range", 32.0D, 0.0D, 2048.0D)); ++ public static final Attribute JUMP_STRENGTH = register("horse.jump_strength", (new RangedAttribute("attribute.name.horse.jump_strength", 0.7D, 0.0D, 2.0D)).setSyncable(true)); ++ public static final Attribute KNOCKBACK_RESISTANCE = register("generic.knockback_resistance", new RangedAttribute("attribute.name.generic.knockback_resistance", 0.0D, 0.0D, 1.0D)); ++ public static final Attribute LUCK = register("generic.luck", (new RangedAttribute("attribute.name.generic.luck", 0.0D, -1024.0D, 1024.0D)).setSyncable(true)); ++ public static final Attribute MAX_ABSORPTION = register("generic.max_absorption", new RangedAttribute("attribute.name.generic.max_absorption", 0.0D, 0.0D, 2048.0D)).setSyncable(true); ++ public static final Attribute MAX_HEALTH = register("generic.max_health", (new RangedAttribute("attribute.name.generic.max_health", 20.0D, 1.0D, 1024.0D)).setSyncable(true)); ++ public static final Attribute MOVEMENT_SPEED = register("generic.movement_speed", (new RangedAttribute("attribute.name.generic.movement_speed", 0.699999988079071D, 0.0D, 1024.0D)).setSyncable(true)); ++ public static final Attribute SPAWN_REINFORCEMENTS_CHANCE = register("zombie.spawn_reinforcements", new RangedAttribute("attribute.name.zombie.spawn_reinforcements", 0.0D, 0.0D, 1.0D)); ++ ++ public Attributes() {} ++ + private static Attribute register(String id, Attribute attribute) { +- return Registry.register(BuiltInRegistries.ATTRIBUTE, id, attribute); ++ return (Attribute) Registry.register(BuiltInRegistries.ATTRIBUTE, id, attribute); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java.patch new file mode 100644 index 0000000000..3637dff665 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java.patch @@ -0,0 +1,102 @@ +--- a/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java ++++ b/net/minecraft/world/entity/ai/behavior/AssignProfessionFromJobSite.java +@@ -2,52 +2,62 @@ + + import java.util.Optional; + import net.minecraft.core.GlobalPos; +-import net.minecraft.core.Holder; + import net.minecraft.core.registries.BuiltInRegistries; + import net.minecraft.server.MinecraftServer; +-import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder; +-import net.minecraft.world.entity.ai.behavior.declarative.MemoryAccessor; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; +-import net.minecraft.world.entity.ai.village.poi.PoiType; + import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.entity.npc.VillagerProfession; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftVillager; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.VillagerCareerChangeEvent; ++// CraftBukkit end ++ + public class AssignProfessionFromJobSite { ++ ++ public AssignProfessionFromJobSite() {} ++ + public static BehaviorControl create() { +- return BehaviorBuilder.create( +- instance -> instance.group(instance.present(MemoryModuleType.POTENTIAL_JOB_SITE), instance.registered(MemoryModuleType.JOB_SITE)) +- .apply( +- instance, +- (potentialJobSite, jobSite) -> (level, villager, gameTime) -> { +- GlobalPos globalPos = instance.get(potentialJobSite); +- if (!globalPos.pos().closerToCenterThan(villager.position(), 2.0) && !villager.assignProfessionWhenSpawned()) { +- return false; +- } else { +- potentialJobSite.erase(); +- jobSite.set(globalPos); +- level.broadcastEntityEvent(villager, (byte)14); +- if (villager.getVillagerData().getProfession() != VillagerProfession.NONE) { +- return true; +- } else { +- MinecraftServer server = level.getServer(); +- Optional.ofNullable(server.getLevel(globalPos.dimension())) +- .flatMap(posLevel -> posLevel.getPoiManager().getType(globalPos.pos())) +- .flatMap( +- poi -> BuiltInRegistries.VILLAGER_PROFESSION +- .stream() +- .filter(profession -> profession.heldJobSite().test((Holder)poi)) +- .findFirst() +- ) +- .ifPresent(profession -> { +- villager.setVillagerData(villager.getVillagerData().setProfession(profession)); +- villager.refreshBrain(level); +- }); +- return true; +- } ++ return BehaviorBuilder.create((behaviorbuilder_b) -> { ++ return behaviorbuilder_b.group(behaviorbuilder_b.present(MemoryModuleType.POTENTIAL_JOB_SITE), behaviorbuilder_b.registered(MemoryModuleType.JOB_SITE)).apply(behaviorbuilder_b, (memoryaccessor, memoryaccessor1) -> { ++ return (worldserver, entityvillager, i) -> { ++ GlobalPos globalpos = (GlobalPos) behaviorbuilder_b.get(memoryaccessor); ++ ++ if (!globalpos.pos().closerToCenterThan(entityvillager.position(), 2.0D) && !entityvillager.assignProfessionWhenSpawned()) { ++ return false; ++ } else { ++ memoryaccessor.erase(); ++ memoryaccessor1.set(globalpos); ++ worldserver.broadcastEntityEvent(entityvillager, (byte) 14); ++ if (entityvillager.getVillagerData().getProfession() != VillagerProfession.NONE) { ++ return true; ++ } else { ++ MinecraftServer minecraftserver = worldserver.getServer(); ++ ++ Optional.ofNullable(minecraftserver.getLevel(globalpos.dimension())).flatMap((worldserver1) -> { ++ return worldserver1.getPoiManager().getType(globalpos.pos()); ++ }).flatMap((holder) -> { ++ return BuiltInRegistries.VILLAGER_PROFESSION.stream().filter((villagerprofession) -> { ++ return villagerprofession.heldJobSite().test(holder); ++ }).findFirst(); ++ }).ifPresent((villagerprofession) -> { ++ // CraftBukkit start - Fire VillagerCareerChangeEvent where Villager gets employed ++ VillagerCareerChangeEvent event = CraftEventFactory.callVillagerCareerChangeEvent(entityvillager, CraftVillager.CraftProfession.minecraftToBukkit(villagerprofession), VillagerCareerChangeEvent.ChangeReason.EMPLOYED); ++ if (event.isCancelled()) { ++ return; + } +- } +- ) +- ); ++ ++ entityvillager.setVillagerData(entityvillager.getVillagerData().setProfession(CraftVillager.CraftProfession.bukkitToMinecraft(event.getProfession()))); ++ // CraftBukkit end ++ entityvillager.refreshBrain(worldserver); ++ }); ++ return true; ++ } ++ } ++ }; ++ }); ++ }); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java.patch new file mode 100644 index 0000000000..c096e8aaa8 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java.patch @@ -0,0 +1,94 @@ +--- a/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java ++++ b/net/minecraft/world/entity/ai/behavior/BabyFollowAdult.java +@@ -1,48 +1,61 @@ + package net.minecraft.world.entity.ai.behavior; + + import java.util.function.Function; +-import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.valueproviders.UniformInt; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder; +-import net.minecraft.world.entity.ai.behavior.declarative.MemoryAccessor; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + import net.minecraft.world.entity.ai.memory.WalkTarget; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++// CraftBukkit end + + public class BabyFollowAdult { ++ ++ public BabyFollowAdult() {} ++ + public static OneShot create(UniformInt followRange, float speedModifier) { +- return create(followRange, entity -> speedModifier); ++ return create(followRange, (entityliving) -> { ++ return speedModifier; ++ }); + } + + public static OneShot create(UniformInt followRange, Function speedModifier) { +- return BehaviorBuilder.create( +- instance -> instance.group( +- instance.present(MemoryModuleType.NEAREST_VISIBLE_ADULT), +- instance.registered(MemoryModuleType.LOOK_TARGET), +- instance.absent(MemoryModuleType.WALK_TARGET) +- ) +- .apply( +- instance, +- (nearestVisibleAdult, lookTarget, walkTarget) -> (level, mob, gameTime) -> { +- if (!mob.isBaby()) { +- return false; +- } else { +- AgeableMob ageableMob = instance.get(nearestVisibleAdult); +- if (mob.closerThan(ageableMob, (double)(followRange.getMaxValue() + 1)) +- && !mob.closerThan(ageableMob, (double)followRange.getMinValue())) { +- WalkTarget walkTarget1 = new WalkTarget( +- new EntityTracker(ageableMob, false), speedModifier.apply(mob), followRange.getMinValue() - 1 +- ); +- lookTarget.set(new EntityTracker(ageableMob, true)); +- walkTarget.set(walkTarget1); +- return true; +- } else { +- return false; +- } +- } ++ return BehaviorBuilder.create((behaviorbuilder_b) -> { ++ return behaviorbuilder_b.group(behaviorbuilder_b.present(MemoryModuleType.NEAREST_VISIBLE_ADULT), behaviorbuilder_b.registered(MemoryModuleType.LOOK_TARGET), behaviorbuilder_b.absent(MemoryModuleType.WALK_TARGET)).apply(behaviorbuilder_b, (memoryaccessor, memoryaccessor1, memoryaccessor2) -> { ++ return (worldserver, entityageable, i) -> { ++ if (!entityageable.isBaby()) { ++ return false; ++ } else { ++ LivingEntity entityageable1 = (AgeableMob) behaviorbuilder_b.get(memoryaccessor); // CraftBukkit - type ++ ++ if (entityageable.closerThan(entityageable1, (double) (followRange.getMaxValue() + 1)) && !entityageable.closerThan(entityageable1, (double) followRange.getMinValue())) { ++ // CraftBukkit start ++ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(entityageable, entityageable1, EntityTargetEvent.TargetReason.FOLLOW_LEADER); ++ if (event.isCancelled()) { ++ return false; + } +- ) +- ); ++ if (event.getTarget() == null) { ++ memoryaccessor.erase(); ++ return true; ++ } ++ entityageable1 = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ // CraftBukkit end ++ WalkTarget memorytarget = new WalkTarget(new EntityTracker(entityageable1, false), (Float) speedModifier.apply(entityageable), followRange.getMinValue() - 1); ++ ++ memoryaccessor1.set(new EntityTracker(entityageable1, true)); ++ memoryaccessor2.set(memorytarget); ++ return true; ++ } else { ++ return false; ++ } ++ } ++ }; ++ }); ++ }); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java.patch new file mode 100644 index 0000000000..ffeef36317 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java.patch @@ -0,0 +1,256 @@ +--- a/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java ++++ b/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java +@@ -1,9 +1,11 @@ + package net.minecraft.world.entity.ai.behavior; + + import java.util.Comparator; ++import java.util.Objects; + import java.util.Optional; + import java.util.UUID; + import java.util.function.Predicate; ++import java.util.stream.Stream; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.SectionPos; +@@ -19,31 +21,37 @@ + import net.minecraft.world.entity.ai.memory.WalkTarget; + import net.minecraft.world.entity.ai.util.DefaultRandomPos; + import net.minecraft.world.entity.item.ItemEntity; ++import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.ProjectileWeaponItem; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.Vec3; + + public class BehaviorUtils { +- private BehaviorUtils() { +- } + ++ private BehaviorUtils() {} ++ + public static void lockGazeAndWalkToEachOther(LivingEntity firstEntity, LivingEntity secondEntity, float speed) { + lookAtEachOther(firstEntity, secondEntity); + setWalkAndLookTargetMemoriesToEachOther(firstEntity, secondEntity, speed); + } + + public static boolean entityIsVisible(Brain brain, LivingEntity target) { +- Optional memory = brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES); +- return memory.isPresent() && memory.get().contains(target); ++ Optional optional = brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES); ++ ++ return optional.isPresent() && ((NearestVisibleLivingEntities) optional.get()).contains(target); + } + + public static boolean targetIsValid(Brain brains, MemoryModuleType memorymodule, EntityType entityType) { +- return targetIsValid(brains, memorymodule, entity -> entity.getType() == entityType); ++ return targetIsValid(brains, memorymodule, (entityliving) -> { ++ return entityliving.getType() == entityType; ++ }); + } + + private static boolean targetIsValid(Brain brain, MemoryModuleType memoryType, Predicate livingPredicate) { +- return brain.getMemory(memoryType).filter(livingPredicate).filter(LivingEntity::isAlive).filter(entity -> entityIsVisible(brain, entity)).isPresent(); ++ return brain.getMemory(memoryType).filter(livingPredicate).filter(LivingEntity::isAlive).filter((entityliving) -> { ++ return entityIsVisible(brain, entityliving); ++ }).isPresent(); + } + + private static void lookAtEachOther(LivingEntity firstEntity, LivingEntity secondEntity) { +@@ -52,111 +60,143 @@ + } + + public static void lookAtEntity(LivingEntity entity, LivingEntity target) { +- entity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, new EntityTracker(target, true)); ++ entity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (new EntityTracker(target, true))); // CraftBukkit - decompile error + } + + private static void setWalkAndLookTargetMemoriesToEachOther(LivingEntity firstEntity, LivingEntity secondEntity, float speed) { +- int i = 2; +- setWalkAndLookTargetMemories(firstEntity, secondEntity, speed, 2); +- setWalkAndLookTargetMemories(secondEntity, firstEntity, speed, 2); ++ boolean flag = true; ++ ++ setWalkAndLookTargetMemories(firstEntity, (Entity) secondEntity, speed, 2); ++ setWalkAndLookTargetMemories(secondEntity, (Entity) firstEntity, speed, 2); + } + + public static void setWalkAndLookTargetMemories(LivingEntity livingEntity, Entity target, float speed, int distance) { +- setWalkAndLookTargetMemories(livingEntity, new EntityTracker(target, true), speed, distance); ++ setWalkAndLookTargetMemories(livingEntity, (PositionTracker) (new EntityTracker(target, true)), speed, distance); + } + + public static void setWalkAndLookTargetMemories(LivingEntity livingEntity, BlockPos pos, float speed, int distance) { +- setWalkAndLookTargetMemories(livingEntity, new BlockPosTracker(pos), speed, distance); ++ setWalkAndLookTargetMemories(livingEntity, (PositionTracker) (new BlockPosTracker(pos)), speed, distance); + } + + public static void setWalkAndLookTargetMemories(LivingEntity entity, PositionTracker positionTracker, float speedModifier, int closeEnoughDist) { +- WalkTarget walkTarget = new WalkTarget(positionTracker, speedModifier, closeEnoughDist); +- entity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, positionTracker); +- entity.getBrain().setMemory(MemoryModuleType.WALK_TARGET, walkTarget); ++ WalkTarget memorytarget = new WalkTarget(positionTracker, speedModifier, closeEnoughDist); ++ ++ entity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, positionTracker); // CraftBukkit - decompile error ++ entity.getBrain().setMemory(MemoryModuleType.WALK_TARGET, memorytarget); // CraftBukkit - decompile error + } + + public static void throwItem(LivingEntity livingEntity, ItemStack stack, Vec3 offset) { +- Vec3 vec3 = new Vec3(0.3F, 0.3F, 0.3F); +- throwItem(livingEntity, stack, offset, vec3, 0.3F); ++ Vec3 vec3d1 = new Vec3(0.30000001192092896D, 0.30000001192092896D, 0.30000001192092896D); ++ ++ throwItem(livingEntity, stack, offset, vec3d1, 0.3F); + } + + public static void throwItem(LivingEntity entity, ItemStack stack, Vec3 offset, Vec3 speedMultiplier, float yOffset) { +- double d = entity.getEyeY() - (double)yOffset; +- ItemEntity itemEntity = new ItemEntity(entity.level(), entity.getX(), d, entity.getZ(), stack); +- itemEntity.setThrower(entity); +- Vec3 vec3 = offset.subtract(entity.position()); +- vec3 = vec3.normalize().multiply(speedMultiplier.x, speedMultiplier.y, speedMultiplier.z); +- itemEntity.setDeltaMovement(vec3); +- itemEntity.setDefaultPickUpDelay(); +- entity.level().addFreshEntity(itemEntity); ++ if (stack.isEmpty()) return; // CraftBukkit - SPIGOT-4940: no empty loot ++ double d0 = entity.getEyeY() - (double) yOffset; ++ ItemEntity entityitem = new ItemEntity(entity.level(), entity.getX(), d0, entity.getZ(), stack); ++ ++ entityitem.setThrower(entity); ++ Vec3 vec3d2 = offset.subtract(entity.position()); ++ ++ vec3d2 = vec3d2.normalize().multiply(speedMultiplier.x, speedMultiplier.y, speedMultiplier.z); ++ entityitem.setDeltaMovement(vec3d2); ++ entityitem.setDefaultPickUpDelay(); ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(entity.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ entityitem.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ entity.level().addFreshEntity(entityitem); + } + + public static SectionPos findSectionClosestToVillage(ServerLevel serverLevel, SectionPos sectionPos, int radius) { +- int i = serverLevel.sectionsToVillage(sectionPos); +- return SectionPos.cube(sectionPos, radius) +- .filter(pos -> serverLevel.sectionsToVillage(pos) < i) +- .min(Comparator.comparingInt(serverLevel::sectionsToVillage)) +- .orElse(sectionPos); ++ int j = serverLevel.sectionsToVillage(sectionPos); ++ Stream stream = SectionPos.cube(sectionPos, radius).filter((sectionposition1) -> { // CraftBukkit - decompile error ++ return serverLevel.sectionsToVillage(sectionposition1) < j; ++ }); ++ ++ Objects.requireNonNull(serverLevel); ++ return (SectionPos) stream.min(Comparator.comparingInt(serverLevel::sectionsToVillage)).orElse(sectionPos); + } + + public static boolean isWithinAttackRange(Mob mob, LivingEntity target, int cooldown) { +- if (mob.getMainHandItem().getItem() instanceof ProjectileWeaponItem projectileWeaponItem && mob.canFireProjectileWeapon(projectileWeaponItem)) { +- int i = projectileWeaponItem.getDefaultProjectileRange() - cooldown; +- return mob.closerThan(target, (double)i); ++ Item item = mob.getMainHandItem().getItem(); ++ ++ if (item instanceof ProjectileWeaponItem) { ++ ProjectileWeaponItem itemprojectileweapon = (ProjectileWeaponItem) item; ++ ++ if (mob.canFireProjectileWeapon(itemprojectileweapon)) { ++ int j = itemprojectileweapon.getDefaultProjectileRange() - cooldown; ++ ++ return mob.closerThan(target, (double) j); ++ } + } + + return mob.isWithinMeleeAttackRange(target); + } + + public static boolean isOtherTargetMuchFurtherAwayThanCurrentAttackTarget(LivingEntity livingEntity, LivingEntity target, double distance) { +- Optional memory = livingEntity.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET); +- if (memory.isEmpty()) { ++ Optional optional = livingEntity.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET); ++ ++ if (optional.isEmpty()) { + return false; + } else { +- double d = livingEntity.distanceToSqr(memory.get().position()); +- double d1 = livingEntity.distanceToSqr(target.position()); +- return d1 > d + distance * distance; ++ double d1 = livingEntity.distanceToSqr(((LivingEntity) optional.get()).position()); ++ double d2 = livingEntity.distanceToSqr(target.position()); ++ ++ return d2 > d1 + distance * distance; + } + } + + public static boolean canSee(LivingEntity livingEntity, LivingEntity target) { +- Brain brain = livingEntity.getBrain(); +- return brain.hasMemoryValue(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES) +- && brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES).get().contains(target); ++ Brain behaviorcontroller = livingEntity.getBrain(); ++ ++ return !behaviorcontroller.hasMemoryValue(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES) ? false : ((NearestVisibleLivingEntities) behaviorcontroller.getMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES).get()).contains(target); + } + + public static LivingEntity getNearestTarget(LivingEntity centerEntity, Optional optionalEntity, LivingEntity livingEntity) { +- return optionalEntity.isEmpty() ? livingEntity : getTargetNearestMe(centerEntity, optionalEntity.get(), livingEntity); ++ return optionalEntity.isEmpty() ? livingEntity : getTargetNearestMe(centerEntity, (LivingEntity) optionalEntity.get(), livingEntity); + } + + public static LivingEntity getTargetNearestMe(LivingEntity centerEntity, LivingEntity livingEntity1, LivingEntity livingEntity2) { +- Vec3 vec3 = livingEntity1.position(); +- Vec3 vec31 = livingEntity2.position(); +- return centerEntity.distanceToSqr(vec3) < centerEntity.distanceToSqr(vec31) ? livingEntity1 : livingEntity2; ++ Vec3 vec3d = livingEntity1.position(); ++ Vec3 vec3d1 = livingEntity2.position(); ++ ++ return centerEntity.distanceToSqr(vec3d) < centerEntity.distanceToSqr(vec3d1) ? livingEntity1 : livingEntity2; + } + + public static Optional getLivingEntityFromUUIDMemory(LivingEntity livingEntity, MemoryModuleType targetMemory) { +- Optional memory = livingEntity.getBrain().getMemory(targetMemory); +- return memory.map(identifier -> ((ServerLevel)livingEntity.level()).getEntity(identifier)) +- .map(entity -> entity instanceof LivingEntity livingEntity1 ? livingEntity1 : null); ++ Optional optional = livingEntity.getBrain().getMemory(targetMemory); ++ ++ return optional.map((uuid) -> { ++ return ((ServerLevel) livingEntity.level()).getEntity(uuid); ++ }).map((entity) -> { ++ LivingEntity entityliving1; ++ ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving2 = (LivingEntity) entity; ++ ++ entityliving1 = entityliving2; ++ } else { ++ entityliving1 = null; ++ } ++ ++ return entityliving1; ++ }); + } + + @Nullable + public static Vec3 getRandomSwimmablePos(PathfinderMob pathfinder, int radius, int verticalDistance) { +- Vec3 pos = DefaultRandomPos.getPos(pathfinder, radius, verticalDistance); +- int i = 0; ++ Vec3 vec3d = DefaultRandomPos.getPos(pathfinder, radius, verticalDistance); + +- while ( +- pos != null +- && !pathfinder.level() +- .getBlockState(BlockPos.containing(pos)) +- .isPathfindable(pathfinder.level(), BlockPos.containing(pos), PathComputationType.WATER) +- && i++ < 10 +- ) { +- pos = DefaultRandomPos.getPos(pathfinder, radius, verticalDistance); ++ for (int k = 0; vec3d != null && !pathfinder.level().getBlockState(BlockPos.containing(vec3d)).isPathfindable(pathfinder.level(), BlockPos.containing(vec3d), PathMode.WATER) && k++ < 10; vec3d = DefaultRandomPos.getPos(pathfinder, radius, verticalDistance)) { ++ ; + } + +- return pos; ++ return vec3d; + } + + public static boolean isBreeding(LivingEntity entity) { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java.patch new file mode 100644 index 0000000000..6a1ac33dd0 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java.patch @@ -0,0 +1,89 @@ +--- a/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java ++++ b/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java +@@ -2,7 +2,6 @@ + + import com.mojang.datafixers.kinds.K1; + import java.util.function.Predicate; +-import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder; + import net.minecraft.world.entity.ai.behavior.declarative.MemoryAccessor; +@@ -11,40 +10,48 @@ + import net.minecraft.world.entity.item.ItemEntity; + + public class GoToWantedItem { ++ ++ public GoToWantedItem() {} ++ + public static BehaviorControl create(float speedModifier, boolean hasTarget, int maxDistToWalk) { +- return create(entity -> true, speedModifier, hasTarget, maxDistToWalk); ++ return create((entityliving) -> { ++ return true; ++ }, speedModifier, hasTarget, maxDistToWalk); + } + + public static BehaviorControl create(Predicate canWalkToItem, float speedModifier, boolean hasTarget, int maxDistToWalk) { +- return BehaviorBuilder.create( +- instance -> { +- BehaviorBuilder> behaviorBuilder = hasTarget +- ? instance.registered(MemoryModuleType.WALK_TARGET) +- : instance.absent(MemoryModuleType.WALK_TARGET); +- return instance.group( +- instance.registered(MemoryModuleType.LOOK_TARGET), +- behaviorBuilder, +- instance.present(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM), +- instance.registered(MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS) +- ) +- .apply( +- instance, +- (lookTarget, walkTarget, nearestVisibleWantedItem, itemPickupCooldownTicks) -> (level, entity, gameTime) -> { +- ItemEntity itemEntity = instance.get(nearestVisibleWantedItem); +- if (instance.tryGet(itemPickupCooldownTicks).isEmpty() +- && canWalkToItem.test(entity) +- && itemEntity.closerThan(entity, (double)maxDistToWalk) +- && entity.level().getWorldBorder().isWithinBounds(itemEntity.blockPosition())) { +- WalkTarget walkTarget1 = new WalkTarget(new EntityTracker(itemEntity, false), speedModifier, 0); +- lookTarget.set(new EntityTracker(itemEntity, true)); +- walkTarget.set(walkTarget1); +- return true; +- } else { +- return false; +- } ++ return BehaviorBuilder.create((behaviorbuilder_b) -> { ++ BehaviorBuilder> behaviorbuilder = hasTarget ? behaviorbuilder_b.registered(MemoryModuleType.WALK_TARGET) : behaviorbuilder_b.absent(MemoryModuleType.WALK_TARGET); ++ ++ return behaviorbuilder_b.group(behaviorbuilder_b.registered(MemoryModuleType.LOOK_TARGET), behaviorbuilder, behaviorbuilder_b.present(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM), behaviorbuilder_b.registered(MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS)).apply(behaviorbuilder_b, (memoryaccessor, memoryaccessor1, memoryaccessor2, memoryaccessor3) -> { ++ return (worldserver, entityliving, j) -> { ++ ItemEntity entityitem = (ItemEntity) behaviorbuilder_b.get(memoryaccessor2); ++ ++ if (behaviorbuilder_b.tryGet(memoryaccessor3).isEmpty() && canWalkToItem.test(entityliving) && entityitem.closerThan(entityliving, (double) maxDistToWalk) && entityliving.level().getWorldBorder().isWithinBounds(entityitem.blockPosition())) { ++ // CraftBukkit start ++ if (entityliving instanceof net.minecraft.world.entity.animal.allay.Allay) { ++ org.bukkit.event.entity.EntityTargetEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTargetEvent(entityliving, entityitem, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_ENTITY); ++ ++ if (event.isCancelled()) { ++ return false; + } +- ); +- } +- ); ++ if (!(event.getTarget() instanceof ItemEntity)) { ++ memoryaccessor2.erase(); ++ } ++ ++ entityitem = (ItemEntity) ((org.bukkit.craftbukkit.entity.CraftEntity) event.getTarget()).getHandle(); ++ } ++ // CraftBukkit end ++ WalkTarget memorytarget = new WalkTarget(new EntityTracker(entityitem, false), speedModifier, 0); ++ ++ memoryaccessor.set(new EntityTracker(entityitem, true)); ++ memoryaccessor1.set(memorytarget); ++ return true; ++ } else { ++ return false; ++ } ++ }; ++ }); ++ }); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java.patch new file mode 100644 index 0000000000..f0474e6032 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java.patch @@ -0,0 +1,209 @@ +--- a/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java ++++ b/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java +@@ -15,16 +15,24 @@ + import net.minecraft.world.entity.ai.memory.WalkTarget; + import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.entity.npc.VillagerProfession; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.BlockItem; ++import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.gameevent.GameEvent; ++ ++// CraftBukkit start ++import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.CropBlock; + import net.minecraft.world.level.block.FarmBlock; +-import net.minecraft.world.level.block.state.BlockState; +-import net.minecraft.world.level.gameevent.GameEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class HarvestFarmland extends Behavior { ++ + private static final int HARVEST_DURATION = 200; + public static final float SPEED_MODIFIER = 0.5F; + @Nullable +@@ -34,34 +42,25 @@ + private final List validFarmlandAroundVillager = Lists.newArrayList(); + + public HarvestFarmland() { +- super( +- ImmutableMap.of( +- MemoryModuleType.LOOK_TARGET, +- MemoryStatus.VALUE_ABSENT, +- MemoryModuleType.WALK_TARGET, +- MemoryStatus.VALUE_ABSENT, +- MemoryModuleType.SECONDARY_JOB_SITE, +- MemoryStatus.VALUE_PRESENT +- ) +- ); ++ super(ImmutableMap.of(MemoryModuleType.LOOK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.SECONDARY_JOB_SITE, MemoryStatus.VALUE_PRESENT)); + } + +- @Override + protected boolean checkExtraStartConditions(ServerLevel level, Villager owner) { + if (!level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { + return false; + } else if (owner.getVillagerData().getProfession() != VillagerProfession.FARMER) { + return false; + } else { +- BlockPos.MutableBlockPos mutableBlockPos = owner.blockPosition().mutable(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = owner.blockPosition().mutable(); ++ + this.validFarmlandAroundVillager.clear(); + +- for (int i = -1; i <= 1; i++) { +- for (int i1 = -1; i1 <= 1; i1++) { +- for (int i2 = -1; i2 <= 1; i2++) { +- mutableBlockPos.set(owner.getX() + (double)i, owner.getY() + (double)i1, owner.getZ() + (double)i2); +- if (this.validPos(mutableBlockPos, level)) { +- this.validFarmlandAroundVillager.add(new BlockPos(mutableBlockPos)); ++ for (int i = -1; i <= 1; ++i) { ++ for (int j = -1; j <= 1; ++j) { ++ for (int k = -1; k <= 1; ++k) { ++ blockposition_mutableblockposition.set(owner.getX() + (double) i, owner.getY() + (double) j, owner.getZ() + (double) k); ++ if (this.validPos(blockposition_mutableblockposition, level)) { ++ this.validFarmlandAroundVillager.add(new BlockPos(blockposition_mutableblockposition)); + } + } + } +@@ -74,27 +73,25 @@ + + @Nullable + private BlockPos getValidFarmland(ServerLevel serverLevel) { +- return this.validFarmlandAroundVillager.isEmpty() +- ? null +- : this.validFarmlandAroundVillager.get(serverLevel.getRandom().nextInt(this.validFarmlandAroundVillager.size())); ++ return this.validFarmlandAroundVillager.isEmpty() ? null : (BlockPos) this.validFarmlandAroundVillager.get(serverLevel.getRandom().nextInt(this.validFarmlandAroundVillager.size())); + } + + private boolean validPos(BlockPos pos, ServerLevel serverLevel) { +- BlockState blockState = serverLevel.getBlockState(pos); +- Block block = blockState.getBlock(); ++ IBlockData iblockdata = serverLevel.getBlockState(pos); ++ Block block = iblockdata.getBlock(); + Block block1 = serverLevel.getBlockState(pos.below()).getBlock(); +- return block instanceof CropBlock && ((CropBlock)block).isMaxAge(blockState) || blockState.isAir() && block1 instanceof FarmBlock; ++ ++ return block instanceof CropBlock && ((CropBlock) block).isMaxAge(iblockdata) || iblockdata.isAir() && block1 instanceof FarmBlock; + } + +- @Override + protected void start(ServerLevel level, Villager entity, long gameTime) { + if (gameTime > this.nextOkStartTime && this.aboveFarmlandPos != null) { +- entity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, new BlockPosTracker(this.aboveFarmlandPos)); +- entity.getBrain().setMemory(MemoryModuleType.WALK_TARGET, new WalkTarget(new BlockPosTracker(this.aboveFarmlandPos), 0.5F, 1)); ++ entity.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (new BlockPosTracker(this.aboveFarmlandPos))); // CraftBukkit - decompile error ++ entity.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (new WalkTarget(new BlockPosTracker(this.aboveFarmlandPos), 0.5F, 1))); // CraftBukkit - decompile error + } ++ + } + +- @Override + protected void stop(ServerLevel level, Villager entity, long gameTime) { + entity.getBrain().eraseMemory(MemoryModuleType.LOOK_TARGET); + entity.getBrain().eraseMemory(MemoryModuleType.WALK_TARGET); +@@ -102,66 +99,67 @@ + this.nextOkStartTime = gameTime + 40L; + } + +- @Override + protected void tick(ServerLevel level, Villager owner, long gameTime) { +- if (this.aboveFarmlandPos == null || this.aboveFarmlandPos.closerToCenterThan(owner.position(), 1.0)) { ++ if (this.aboveFarmlandPos == null || this.aboveFarmlandPos.closerToCenterThan(owner.position(), 1.0D)) { + if (this.aboveFarmlandPos != null && gameTime > this.nextOkStartTime) { +- BlockState blockState = level.getBlockState(this.aboveFarmlandPos); +- Block block = blockState.getBlock(); ++ IBlockData iblockdata = level.getBlockState(this.aboveFarmlandPos); ++ Block block = iblockdata.getBlock(); + Block block1 = level.getBlockState(this.aboveFarmlandPos.below()).getBlock(); +- if (block instanceof CropBlock && ((CropBlock)block).isMaxAge(blockState)) { ++ ++ if (block instanceof CropBlock && ((CropBlock) block).isMaxAge(iblockdata)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(owner, this.aboveFarmlandPos, Blocks.AIR.defaultBlockState())) { // CraftBukkit + level.destroyBlock(this.aboveFarmlandPos, true, owner); ++ } // CraftBukkit + } + +- if (blockState.isAir() && block1 instanceof FarmBlock && owner.hasFarmSeeds()) { +- SimpleContainer inventory = owner.getInventory(); ++ if (iblockdata.isAir() && block1 instanceof FarmBlock && owner.hasFarmSeeds()) { ++ SimpleContainer inventorysubcontainer = owner.getInventory(); + +- for (int i = 0; i < inventory.getContainerSize(); i++) { +- ItemStack item = inventory.getItem(i); ++ for (int j = 0; j < inventorysubcontainer.getContainerSize(); ++j) { ++ ItemStack itemstack = inventorysubcontainer.getItem(j); + boolean flag = false; +- if (!item.isEmpty() && item.is(ItemTags.VILLAGER_PLANTABLE_SEEDS) && item.getItem() instanceof BlockItem blockItem) { +- BlockState blockState1 = blockItem.getBlock().defaultBlockState(); +- level.setBlockAndUpdate(this.aboveFarmlandPos, blockState1); +- level.gameEvent(GameEvent.BLOCK_PLACE, this.aboveFarmlandPos, GameEvent.Context.of(owner, blockState1)); +- flag = true; ++ ++ if (!itemstack.isEmpty() && itemstack.is(ItemTags.VILLAGER_PLANTABLE_SEEDS)) { ++ Item item = itemstack.getItem(); ++ ++ if (item instanceof BlockItem) { ++ BlockItem itemblock = (BlockItem) item; ++ IBlockData iblockdata1 = itemblock.getBlock().defaultBlockState(); ++ ++ if (CraftEventFactory.callEntityChangeBlockEvent(owner, this.aboveFarmlandPos, iblockdata1)) { // CraftBukkit ++ level.setBlockAndUpdate(this.aboveFarmlandPos, iblockdata1); ++ level.gameEvent(GameEvent.BLOCK_PLACE, this.aboveFarmlandPos, GameEvent.Context.of(owner, iblockdata1)); ++ flag = true; ++ } // CraftBukkit ++ } + } + + if (flag) { +- level.playSound( +- null, +- (double)this.aboveFarmlandPos.getX(), +- (double)this.aboveFarmlandPos.getY(), +- (double)this.aboveFarmlandPos.getZ(), +- SoundEvents.CROP_PLANTED, +- SoundSource.BLOCKS, +- 1.0F, +- 1.0F +- ); +- item.shrink(1); +- if (item.isEmpty()) { +- inventory.setItem(i, ItemStack.EMPTY); ++ level.playSound((Player) null, (double) this.aboveFarmlandPos.getX(), (double) this.aboveFarmlandPos.getY(), (double) this.aboveFarmlandPos.getZ(), SoundEvents.CROP_PLANTED, SoundSource.BLOCKS, 1.0F, 1.0F); ++ itemstack.shrink(1); ++ if (itemstack.isEmpty()) { ++ inventorysubcontainer.setItem(j, ItemStack.EMPTY); + } + break; + } + } + } + +- if (block instanceof CropBlock && !((CropBlock)block).isMaxAge(blockState)) { ++ if (block instanceof CropBlock && !((CropBlock) block).isMaxAge(iblockdata)) { + this.validFarmlandAroundVillager.remove(this.aboveFarmlandPos); + this.aboveFarmlandPos = this.getValidFarmland(level); + if (this.aboveFarmlandPos != null) { + this.nextOkStartTime = gameTime + 20L; +- owner.getBrain().setMemory(MemoryModuleType.WALK_TARGET, new WalkTarget(new BlockPosTracker(this.aboveFarmlandPos), 0.5F, 1)); +- owner.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, new BlockPosTracker(this.aboveFarmlandPos)); ++ owner.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (new WalkTarget(new BlockPosTracker(this.aboveFarmlandPos), 0.5F, 1))); // CraftBukkit - decompile error ++ owner.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (new BlockPosTracker(this.aboveFarmlandPos))); // CraftBukkit - decompile error + } + } + } + +- this.timeWorkedSoFar++; ++ ++this.timeWorkedSoFar; + } + } + +- @Override + protected boolean canStillUse(ServerLevel level, Villager entity, long gameTime) { + return this.timeWorkedSoFar < 200; + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java.patch new file mode 100644 index 0000000000..31cb8856a1 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java.patch @@ -0,0 +1,274 @@ +--- a/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java ++++ b/net/minecraft/world/entity/ai/behavior/InteractWithDoor.java +@@ -18,154 +18,175 @@ + import net.minecraft.world.entity.ai.behavior.declarative.MemoryAccessor; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + import net.minecraft.world.level.block.DoorBlock; +-import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.pathfinder.Node; + import net.minecraft.world.level.pathfinder.Path; + import org.apache.commons.lang3.mutable.MutableInt; + import org.apache.commons.lang3.mutable.MutableObject; + + public class InteractWithDoor { ++ + private static final int COOLDOWN_BEFORE_RERUNNING_IN_SAME_NODE = 20; +- private static final double SKIP_CLOSING_DOOR_IF_FURTHER_AWAY_THAN = 3.0; +- private static final double MAX_DISTANCE_TO_HOLD_DOOR_OPEN_FOR_OTHER_MOBS = 2.0; ++ private static final double SKIP_CLOSING_DOOR_IF_FURTHER_AWAY_THAN = 3.0D; ++ private static final double MAX_DISTANCE_TO_HOLD_DOOR_OPEN_FOR_OTHER_MOBS = 2.0D; + ++ public InteractWithDoor() {} ++ + public static BehaviorControl create() { +- MutableObject mutableObject = new MutableObject<>(null); +- MutableInt mutableInt = new MutableInt(0); +- return BehaviorBuilder.create( +- instance -> instance.group( +- instance.present(MemoryModuleType.PATH), +- instance.registered(MemoryModuleType.DOORS_TO_CLOSE), +- instance.registered(MemoryModuleType.NEAREST_LIVING_ENTITIES) +- ) +- .apply( +- instance, +- (navigationPath, doorsToClose, nearestLivingEntities) -> (level, entity, gameTime) -> { +- Path path = instance.get(navigationPath); +- Optional> optional = instance.tryGet(doorsToClose); +- if (!path.notStarted() && !path.isDone()) { +- if (Objects.equals(mutableObject.getValue(), path.getNextNode())) { +- mutableInt.setValue(20); +- } else if (mutableInt.decrementAndGet() > 0) { +- return false; +- } +- +- mutableObject.setValue(path.getNextNode()); +- Node previousNode = path.getPreviousNode(); +- Node nextNode = path.getNextNode(); +- BlockPos blockPos = previousNode.asBlockPos(); +- BlockState blockState = level.getBlockState(blockPos); +- if (blockState.is(BlockTags.WOODEN_DOORS, state -> state.getBlock() instanceof DoorBlock)) { +- DoorBlock doorBlock = (DoorBlock)blockState.getBlock(); +- if (!doorBlock.isOpen(blockState)) { +- doorBlock.setOpen(entity, level, blockState, blockPos, true); +- } +- +- optional = rememberDoorToClose(doorsToClose, optional, level, blockPos); +- } +- +- BlockPos blockPos1 = nextNode.asBlockPos(); +- BlockState blockState1 = level.getBlockState(blockPos1); +- if (blockState1.is(BlockTags.WOODEN_DOORS, state -> state.getBlock() instanceof DoorBlock)) { +- DoorBlock doorBlock1 = (DoorBlock)blockState1.getBlock(); +- if (!doorBlock1.isOpen(blockState1)) { +- doorBlock1.setOpen(entity, level, blockState1, blockPos1, true); +- optional = rememberDoorToClose(doorsToClose, optional, level, blockPos1); +- } +- } +- +- optional.ifPresent( +- doorPositions -> closeDoorsThatIHaveOpenedOrPassedThrough( +- level, entity, previousNode, nextNode, (Set)doorPositions, instance.tryGet(nearestLivingEntities) +- ) +- ); +- return true; +- } else { ++ MutableObject mutableobject = new MutableObject((Object) null); ++ MutableInt mutableint = new MutableInt(0); ++ ++ return BehaviorBuilder.create((behaviorbuilder_b) -> { ++ return behaviorbuilder_b.group(behaviorbuilder_b.present(MemoryModuleType.PATH), behaviorbuilder_b.registered(MemoryModuleType.DOORS_TO_CLOSE), behaviorbuilder_b.registered(MemoryModuleType.NEAREST_LIVING_ENTITIES)).apply(behaviorbuilder_b, (memoryaccessor, memoryaccessor1, memoryaccessor2) -> { ++ return (worldserver, entityliving, i) -> { ++ Path pathentity = (Path) behaviorbuilder_b.get(memoryaccessor); ++ Optional> optional = behaviorbuilder_b.tryGet(memoryaccessor1); ++ ++ if (!pathentity.notStarted() && !pathentity.isDone()) { ++ if (Objects.equals(mutableobject.getValue(), pathentity.getNextNode())) { ++ mutableint.setValue(20); ++ } else if (mutableint.decrementAndGet() > 0) { ++ return false; ++ } ++ ++ mutableobject.setValue(pathentity.getNextNode()); ++ Node pathpoint = pathentity.getPreviousNode(); ++ Node pathpoint1 = pathentity.getNextNode(); ++ BlockPos blockposition = pathpoint.asBlockPos(); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ ++ if (iblockdata.is(BlockTags.WOODEN_DOORS, (blockbase_blockdata) -> { ++ return blockbase_blockdata.getBlock() instanceof DoorBlock; ++ })) { ++ DoorBlock blockdoor = (DoorBlock) iblockdata.getBlock(); ++ ++ if (!blockdoor.isOpen(iblockdata)) { ++ // CraftBukkit start - entities opening doors ++ org.bukkit.event.entity.EntityInteractEvent event = new org.bukkit.event.entity.EntityInteractEvent(entityliving.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(entityliving.level(), blockposition)); ++ entityliving.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { + return false; + } ++ // CraftBukkit end ++ blockdoor.setOpen(entityliving, worldserver, iblockdata, blockposition, true); + } +- ) +- ); ++ ++ optional = rememberDoorToClose(memoryaccessor1, optional, worldserver, blockposition); ++ } ++ ++ BlockPos blockposition1 = pathpoint1.asBlockPos(); ++ IBlockData iblockdata1 = worldserver.getBlockState(blockposition1); ++ ++ if (iblockdata1.is(BlockTags.WOODEN_DOORS, (blockbase_blockdata) -> { ++ return blockbase_blockdata.getBlock() instanceof DoorBlock; ++ })) { ++ DoorBlock blockdoor1 = (DoorBlock) iblockdata1.getBlock(); ++ ++ if (!blockdoor1.isOpen(iblockdata1)) { ++ // CraftBukkit start - entities opening doors ++ org.bukkit.event.entity.EntityInteractEvent event = new org.bukkit.event.entity.EntityInteractEvent(entityliving.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(entityliving.level(), blockposition1)); ++ entityliving.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ blockdoor1.setOpen(entityliving, worldserver, iblockdata1, blockposition1, true); ++ optional = rememberDoorToClose(memoryaccessor1, optional, worldserver, blockposition1); ++ } ++ } ++ ++ optional.ifPresent((set) -> { ++ closeDoorsThatIHaveOpenedOrPassedThrough(worldserver, entityliving, pathpoint, pathpoint1, set, behaviorbuilder_b.tryGet(memoryaccessor2)); ++ }); ++ return true; ++ } else { ++ return false; ++ } ++ }; ++ }); ++ }); + } + +- public static void closeDoorsThatIHaveOpenedOrPassedThrough( +- ServerLevel level, +- LivingEntity entity, +- @Nullable Node previous, +- @Nullable Node next, +- Set doorPositions, +- Optional> nearestLivingEntities +- ) { +- Iterator iterator = doorPositions.iterator(); ++ public static void closeDoorsThatIHaveOpenedOrPassedThrough(ServerLevel level, LivingEntity entity, @Nullable Node previous, @Nullable Node next, Set doorPositions, Optional> nearestLivingEntities) { ++ Iterator iterator = doorPositions.iterator(); + + while (iterator.hasNext()) { +- GlobalPos globalPos = iterator.next(); +- BlockPos blockPos = globalPos.pos(); +- if ((previous == null || !previous.asBlockPos().equals(blockPos)) && (next == null || !next.asBlockPos().equals(blockPos))) { +- if (isDoorTooFarAway(level, entity, globalPos)) { ++ GlobalPos globalpos = (GlobalPos) iterator.next(); ++ BlockPos blockposition = globalpos.pos(); ++ ++ if ((previous == null || !previous.asBlockPos().equals(blockposition)) && (next == null || !next.asBlockPos().equals(blockposition))) { ++ if (isDoorTooFarAway(level, entity, globalpos)) { + iterator.remove(); + } else { +- BlockState blockState = level.getBlockState(blockPos); +- if (!blockState.is(BlockTags.WOODEN_DOORS, state -> state.getBlock() instanceof DoorBlock)) { ++ IBlockData iblockdata = level.getBlockState(blockposition); ++ ++ if (!iblockdata.is(BlockTags.WOODEN_DOORS, (blockbase_blockdata) -> { ++ return blockbase_blockdata.getBlock() instanceof DoorBlock; ++ })) { + iterator.remove(); + } else { +- DoorBlock doorBlock = (DoorBlock)blockState.getBlock(); +- if (!doorBlock.isOpen(blockState)) { ++ DoorBlock blockdoor = (DoorBlock) iblockdata.getBlock(); ++ ++ if (!blockdoor.isOpen(iblockdata)) { + iterator.remove(); +- } else if (areOtherMobsComingThroughDoor(entity, blockPos, nearestLivingEntities)) { ++ } else if (areOtherMobsComingThroughDoor(entity, blockposition, nearestLivingEntities)) { + iterator.remove(); + } else { +- doorBlock.setOpen(entity, level, blockState, blockPos, false); ++ blockdoor.setOpen(entity, level, iblockdata, blockposition, false); + iterator.remove(); + } + } + } + } + } ++ + } + + private static boolean areOtherMobsComingThroughDoor(LivingEntity entity, BlockPos pos, Optional> nearestLivingEntities) { +- return !nearestLivingEntities.isEmpty() +- && nearestLivingEntities.get() +- .stream() +- .filter(nearEntity -> nearEntity.getType() == entity.getType()) +- .filter(nearEntity -> pos.closerToCenterThan(nearEntity.position(), 2.0)) +- .anyMatch(nearEntity -> isMobComingThroughDoor(nearEntity.getBrain(), pos)); ++ return nearestLivingEntities.isEmpty() ? false : (nearestLivingEntities.get()).stream().filter((entityliving1) -> { // CraftBukkit - decompile error ++ return entityliving1.getType() == entity.getType(); ++ }).filter((entityliving1) -> { ++ return pos.closerToCenterThan(entityliving1.position(), 2.0D); ++ }).anyMatch((entityliving1) -> { ++ return isMobComingThroughDoor(entityliving1.getBrain(), pos); ++ }); + } + + private static boolean isMobComingThroughDoor(Brain brain, BlockPos pos) { + if (!brain.hasMemoryValue(MemoryModuleType.PATH)) { + return false; + } else { +- Path path = brain.getMemory(MemoryModuleType.PATH).get(); +- if (path.isDone()) { ++ Path pathentity = (Path) brain.getMemory(MemoryModuleType.PATH).get(); ++ ++ if (pathentity.isDone()) { + return false; + } else { +- Node previousNode = path.getPreviousNode(); +- if (previousNode == null) { ++ Node pathpoint = pathentity.getPreviousNode(); ++ ++ if (pathpoint == null) { + return false; + } else { +- Node nextNode = path.getNextNode(); +- return pos.equals(previousNode.asBlockPos()) || pos.equals(nextNode.asBlockPos()); ++ Node pathpoint1 = pathentity.getNextNode(); ++ ++ return pos.equals(pathpoint.asBlockPos()) || pos.equals(pathpoint1.asBlockPos()); + } + } + } + } + + private static boolean isDoorTooFarAway(ServerLevel level, LivingEntity entity, GlobalPos pos) { +- return pos.dimension() != level.dimension() || !pos.pos().closerToCenterThan(entity.position(), 3.0); ++ return pos.dimension() != level.dimension() || !pos.pos().closerToCenterThan(entity.position(), 3.0D); + } + +- private static Optional> rememberDoorToClose( +- MemoryAccessor> doorsToClose, Optional> doorPositions, ServerLevel level, BlockPos pos +- ) { +- GlobalPos globalPos = GlobalPos.of(level.dimension(), pos); +- return Optional.of(doorPositions.>map(set -> { +- set.add(globalPos); ++ private static Optional> rememberDoorToClose(MemoryAccessor> doorsToClose, Optional> doorPositions, ServerLevel level, BlockPos pos) { ++ GlobalPos globalpos = GlobalPos.of(level.dimension(), pos); ++ ++ return Optional.of((Set) doorPositions.map((set) -> { ++ set.add(globalpos); + return set; + }).orElseGet(() -> { +- Set set = Sets.newHashSet(globalPos); ++ Set set = Sets.newHashSet(new GlobalPos[]{globalpos}); ++ + doorsToClose.set(set); + return set; + })); diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java.patch new file mode 100644 index 0000000000..906ee57d0e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java.patch @@ -0,0 +1,260 @@ +--- a/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java ++++ b/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java +@@ -3,30 +3,40 @@ + import com.google.common.collect.ImmutableMap; + import com.google.common.collect.Lists; + import java.util.Comparator; ++import java.util.Iterator; + import java.util.List; ++import java.util.Objects; + import java.util.Optional; + import java.util.function.Function; + import java.util.function.ToIntFunction; ++import java.util.stream.Stream; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundSource; + import net.minecraft.util.Mth; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.PathfinderMob; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + import net.minecraft.world.entity.ai.memory.MemoryStatus; +-import net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities; + import net.minecraft.world.entity.ai.memory.WalkTarget; + import net.minecraft.world.entity.ai.navigation.PathNavigation; + import net.minecraft.world.entity.ai.targeting.TargetingConditions; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.pathfinder.Path; + import net.minecraft.world.level.pathfinder.WalkNodeEvaluator; + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end + + public class PrepareRamNearestTarget extends Behavior { ++ + public static final int TIME_OUT_DURATION = 160; + private final ToIntFunction getCooldownOnFail; + private final int minRamDistance; +@@ -38,28 +48,8 @@ + private Optional reachedRamPositionTimestamp = Optional.empty(); + private Optional ramCandidate = Optional.empty(); + +- public PrepareRamNearestTarget( +- ToIntFunction getCooldownOnFall, +- int minRamDistance, +- int maxRamDistance, +- float walkSpeed, +- TargetingConditions ramTargeting, +- int ramPrepareTime, +- Function getPrepareRamSound +- ) { +- super( +- ImmutableMap.of( +- MemoryModuleType.LOOK_TARGET, +- MemoryStatus.REGISTERED, +- MemoryModuleType.RAM_COOLDOWN_TICKS, +- MemoryStatus.VALUE_ABSENT, +- MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, +- MemoryStatus.VALUE_PRESENT, +- MemoryModuleType.RAM_TARGET, +- MemoryStatus.VALUE_ABSENT +- ), +- 160 +- ); ++ public PrepareRamNearestTarget(ToIntFunction getCooldownOnFall, int minRamDistance, int maxRamDistance, float walkSpeed, TargetingConditions ramTargeting, int ramPrepareTime, Function getPrepareRamSound) { ++ super(ImmutableMap.of(MemoryModuleType.LOOK_TARGET, MemoryStatus.REGISTERED, MemoryModuleType.RAM_COOLDOWN_TICKS, MemoryStatus.VALUE_ABSENT, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryStatus.VALUE_PRESENT, MemoryModuleType.RAM_TARGET, MemoryStatus.VALUE_ABSENT), 160); + this.getCooldownOnFail = getCooldownOnFall; + this.minRamDistance = minRamDistance; + this.maxRamDistance = maxRamDistance; +@@ -69,106 +59,136 @@ + this.getPrepareRamSound = getPrepareRamSound; + } + +- @Override + protected void start(ServerLevel level, PathfinderMob entity, long gameTime) { +- Brain brain = entity.getBrain(); +- brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES) +- .flatMap(memory -> memory.findClosest(entity1 -> this.ramTargeting.test(entity, entity1))) +- .ifPresent(entity1 -> this.chooseRamPosition(entity, entity1)); ++ Brain behaviorcontroller = entity.getBrain(); ++ ++ behaviorcontroller.getMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES).flatMap((nearestvisiblelivingentities) -> { ++ return nearestvisiblelivingentities.findClosest((entityliving) -> { ++ return this.ramTargeting.test(entity, entityliving); ++ }); ++ }).ifPresent((entityliving) -> { ++ // CraftBukkit start ++ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entity, entityliving, (entityliving instanceof ServerPlayer) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.CLOSEST_ENTITY); ++ if (event.isCancelled() || event.getTarget() == null) { ++ return; ++ } ++ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ // CraftBukkit end ++ this.chooseRamPosition(entity, entityliving); ++ }); + } + +- @Override + protected void stop(ServerLevel level, E entity, long gameTime) { +- Brain brain = entity.getBrain(); +- if (!brain.hasMemoryValue(MemoryModuleType.RAM_TARGET)) { +- level.broadcastEntityEvent(entity, (byte)59); +- brain.setMemory(MemoryModuleType.RAM_COOLDOWN_TICKS, this.getCooldownOnFail.applyAsInt(entity)); ++ Brain behaviorcontroller = entity.getBrain(); ++ ++ if (!behaviorcontroller.hasMemoryValue(MemoryModuleType.RAM_TARGET)) { ++ level.broadcastEntityEvent(entity, (byte) 59); ++ behaviorcontroller.setMemory(MemoryModuleType.RAM_COOLDOWN_TICKS, this.getCooldownOnFail.applyAsInt(entity)); // CraftBukkit - decompile error + } ++ + } + +- @Override + protected boolean canStillUse(ServerLevel level, PathfinderMob entity, long gameTime) { +- return this.ramCandidate.isPresent() && this.ramCandidate.get().getTarget().isAlive(); ++ return this.ramCandidate.isPresent() && ((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getTarget().isAlive(); + } + +- @Override + protected void tick(ServerLevel level, E owner, long gameTime) { + if (!this.ramCandidate.isEmpty()) { +- owner.getBrain().setMemory(MemoryModuleType.WALK_TARGET, new WalkTarget(this.ramCandidate.get().getStartPosition(), this.walkSpeed, 0)); +- owner.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, new EntityTracker(this.ramCandidate.get().getTarget(), true)); +- boolean flag = !this.ramCandidate.get().getTarget().blockPosition().equals(this.ramCandidate.get().getTargetPosition()); ++ owner.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (new WalkTarget(((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getStartPosition(), this.walkSpeed, 0))); // CraftBukkit - decompile error ++ owner.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (new EntityTracker(((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getTarget(), true))); // CraftBukkit - decompile error ++ boolean flag = !((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getTarget().blockPosition().equals(((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getTargetPosition()); ++ + if (flag) { +- level.broadcastEntityEvent(owner, (byte)59); ++ level.broadcastEntityEvent(owner, (byte) 59); + owner.getNavigation().stop(); +- this.chooseRamPosition(owner, this.ramCandidate.get().target); ++ this.chooseRamPosition(owner, ((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).target); + } else { +- BlockPos blockPos = owner.blockPosition(); +- if (blockPos.equals(this.ramCandidate.get().getStartPosition())) { +- level.broadcastEntityEvent(owner, (byte)58); ++ BlockPos blockposition = owner.blockPosition(); ++ ++ if (blockposition.equals(((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getStartPosition())) { ++ level.broadcastEntityEvent(owner, (byte) 58); + if (this.reachedRamPositionTimestamp.isEmpty()) { + this.reachedRamPositionTimestamp = Optional.of(gameTime); + } + +- if (gameTime - this.reachedRamPositionTimestamp.get() >= (long)this.ramPrepareTime) { +- owner.getBrain().setMemory(MemoryModuleType.RAM_TARGET, this.getEdgeOfBlock(blockPos, this.ramCandidate.get().getTargetPosition())); +- level.playSound(null, owner, this.getPrepareRamSound.apply(owner), SoundSource.NEUTRAL, 1.0F, owner.getVoicePitch()); ++ if (gameTime - (Long) this.reachedRamPositionTimestamp.get() >= (long) this.ramPrepareTime) { ++ owner.getBrain().setMemory(MemoryModuleType.RAM_TARGET, this.getEdgeOfBlock(blockposition, ((PrepareRamNearestTarget.RamCandidate) this.ramCandidate.get()).getTargetPosition())); // CraftBukkit - decompile error ++ level.playSound((Player) null, (Entity) owner, (SoundEvent) this.getPrepareRamSound.apply(owner), SoundSource.NEUTRAL, 1.0F, owner.getVoicePitch()); + this.ramCandidate = Optional.empty(); + } + } + } ++ + } + } + + private Vec3 getEdgeOfBlock(BlockPos pos, BlockPos other) { +- double d = 0.5; +- double d1 = 0.5 * (double)Mth.sign((double)(other.getX() - pos.getX())); +- double d2 = 0.5 * (double)Mth.sign((double)(other.getZ() - pos.getZ())); +- return Vec3.atBottomCenterOf(other).add(d1, 0.0, d2); ++ double d0 = 0.5D; ++ double d1 = 0.5D * (double) Mth.sign((double) (other.getX() - pos.getX())); ++ double d2 = 0.5D * (double) Mth.sign((double) (other.getZ() - pos.getZ())); ++ ++ return Vec3.atBottomCenterOf(other).add(d1, 0.0D, d2); + } + + private Optional calculateRammingStartPosition(PathfinderMob pathfinder, LivingEntity entity) { +- BlockPos blockPos = entity.blockPosition(); +- if (!this.isWalkableBlock(pathfinder, blockPos)) { ++ BlockPos blockposition = entity.blockPosition(); ++ ++ if (!this.isWalkableBlock(pathfinder, blockposition)) { + return Optional.empty(); + } else { + List list = Lists.newArrayList(); +- BlockPos.MutableBlockPos mutableBlockPos = blockPos.mutable(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = blockposition.mutable(); ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- mutableBlockPos.set(blockPos); ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); + +- for (int i = 0; i < this.maxRamDistance; i++) { +- if (!this.isWalkableBlock(pathfinder, mutableBlockPos.move(direction))) { +- mutableBlockPos.move(direction.getOpposite()); +- break; ++ blockposition_mutableblockposition.set(blockposition); ++ int i = 0; ++ ++ while (true) { ++ if (i < this.maxRamDistance) { ++ if (this.isWalkableBlock(pathfinder, blockposition_mutableblockposition.move(enumdirection))) { ++ ++i; ++ continue; ++ } ++ ++ blockposition_mutableblockposition.move(enumdirection.getOpposite()); + } +- } + +- if (mutableBlockPos.distManhattan(blockPos) >= this.minRamDistance) { +- list.add(mutableBlockPos.immutable()); ++ if (blockposition_mutableblockposition.distManhattan(blockposition) >= this.minRamDistance) { ++ list.add(blockposition_mutableblockposition.immutable()); ++ } ++ break; + } + } + +- PathNavigation navigation = pathfinder.getNavigation(); +- return list.stream().sorted(Comparator.comparingDouble(pathfinder.blockPosition()::distSqr)).filter(pos -> { +- Path path = navigation.createPath(pos, 0); +- return path != null && path.canReach(); ++ PathNavigation navigationabstract = pathfinder.getNavigation(); ++ Stream stream = list.stream(); // CraftBukkit - decompile error ++ BlockPos blockposition1 = pathfinder.blockPosition(); ++ ++ Objects.requireNonNull(blockposition1); ++ return stream.sorted(Comparator.comparingDouble(blockposition1::distSqr)).filter((blockposition2) -> { ++ Path pathentity = navigationabstract.createPath(blockposition2, 0); ++ ++ return pathentity != null && pathentity.canReach(); + }).findFirst(); + } + } + + private boolean isWalkableBlock(PathfinderMob pathfinder, BlockPos pos) { +- return pathfinder.getNavigation().isStableDestination(pos) +- && pathfinder.getPathfindingMalus(WalkNodeEvaluator.getBlockPathTypeStatic(pathfinder.level(), pos.mutable())) == 0.0F; ++ return pathfinder.getNavigation().isStableDestination(pos) && pathfinder.getPathfindingMalus(WalkNodeEvaluator.getBlockPathTypeStatic(pathfinder.level(), pos.mutable())) == 0.0F; + } + + private void chooseRamPosition(PathfinderMob pathfinder, LivingEntity entity) { + this.reachedRamPositionTimestamp = Optional.empty(); +- this.ramCandidate = this.calculateRammingStartPosition(pathfinder, entity) +- .map(blockPos -> new PrepareRamNearestTarget.RamCandidate(blockPos, entity.blockPosition(), entity)); ++ this.ramCandidate = this.calculateRammingStartPosition(pathfinder, entity).map((blockposition) -> { ++ return new PrepareRamNearestTarget.RamCandidate(blockposition, entity.blockPosition(), entity); ++ }); + } + + public static class RamCandidate { ++ + private final BlockPos startPosition; + private final BlockPos targetPosition; + final LivingEntity target; diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/ResetProfession.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/ResetProfession.java.patch new file mode 100644 index 0000000000..25ed43b2c3 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/ResetProfession.java.patch @@ -0,0 +1,67 @@ +--- a/net/minecraft/world/entity/ai/behavior/ResetProfession.java ++++ b/net/minecraft/world/entity/ai/behavior/ResetProfession.java +@@ -1,33 +1,43 @@ + package net.minecraft.world.entity.ai.behavior; + +-import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder; +-import net.minecraft.world.entity.ai.behavior.declarative.MemoryAccessor; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.entity.npc.VillagerData; + import net.minecraft.world.entity.npc.VillagerProfession; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftVillager; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.VillagerCareerChangeEvent; ++// CraftBukkit end ++ + public class ResetProfession { ++ ++ public ResetProfession() {} ++ + public static BehaviorControl create() { +- return BehaviorBuilder.create( +- instance -> instance.group(instance.absent(MemoryModuleType.JOB_SITE)) +- .apply( +- instance, +- jobSite -> (level, villager, gameTime) -> { +- VillagerData villagerData = villager.getVillagerData(); +- if (villagerData.getProfession() != VillagerProfession.NONE +- && villagerData.getProfession() != VillagerProfession.NITWIT +- && villager.getVillagerXp() == 0 +- && villagerData.getLevel() <= 1) { +- villager.setVillagerData(villager.getVillagerData().setProfession(VillagerProfession.NONE)); +- villager.refreshBrain(level); +- return true; +- } else { +- return false; +- } +- } +- ) +- ); ++ return BehaviorBuilder.create((behaviorbuilder_b) -> { ++ return behaviorbuilder_b.group(behaviorbuilder_b.absent(MemoryModuleType.JOB_SITE)).apply(behaviorbuilder_b, (memoryaccessor) -> { ++ return (worldserver, entityvillager, i) -> { ++ VillagerData villagerdata = entityvillager.getVillagerData(); ++ ++ if (villagerdata.getProfession() != VillagerProfession.NONE && villagerdata.getProfession() != VillagerProfession.NITWIT && entityvillager.getVillagerXp() == 0 && villagerdata.getLevel() <= 1) { ++ // CraftBukkit start ++ VillagerCareerChangeEvent event = CraftEventFactory.callVillagerCareerChangeEvent(entityvillager, CraftVillager.CraftProfession.minecraftToBukkit(VillagerProfession.NONE), VillagerCareerChangeEvent.ChangeReason.LOSING_JOB); ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ entityvillager.setVillagerData(entityvillager.getVillagerData().setProfession(CraftVillager.CraftProfession.bukkitToMinecraft(event.getProfession()))); ++ // CraftBukkit end ++ entityvillager.refreshBrain(worldserver); ++ return true; ++ } else { ++ return false; ++ } ++ }; ++ }); ++ }); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/StartAttacking.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/StartAttacking.java.patch new file mode 100644 index 0000000000..9fdaa2c7fa --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/StartAttacking.java.patch @@ -0,0 +1,85 @@ +--- a/net/minecraft/world/entity/ai/behavior/StartAttacking.java ++++ b/net/minecraft/world/entity/ai/behavior/StartAttacking.java +@@ -3,40 +3,62 @@ + import java.util.Optional; + import java.util.function.Function; + import java.util.function.Predicate; +-import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; + import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder; +-import net.minecraft.world.entity.ai.behavior.declarative.MemoryAccessor; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end + + public class StartAttacking { ++ ++ public StartAttacking() {} ++ + public static BehaviorControl create(Function> targetFinder) { +- return create(entity -> true, targetFinder); ++ return create((entityinsentient) -> { ++ return true; ++ }, targetFinder); + } + + public static BehaviorControl create(Predicate canAttack, Function> targetFinder) { +- return BehaviorBuilder.create( +- instance -> instance.group(instance.absent(MemoryModuleType.ATTACK_TARGET), instance.registered(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)) +- .apply(instance, (attackTarget, cantReachWalkTargetSince) -> (level, mob, gameTime) -> { +- if (!canAttack.test(mob)) { ++ return BehaviorBuilder.create((behaviorbuilder_b) -> { ++ return behaviorbuilder_b.group(behaviorbuilder_b.absent(MemoryModuleType.ATTACK_TARGET), behaviorbuilder_b.registered(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)).apply(behaviorbuilder_b, (memoryaccessor, memoryaccessor1) -> { ++ return (worldserver, entityinsentient, i) -> { ++ if (!canAttack.test(entityinsentient)) { ++ return false; ++ } else { ++ Optional optional = (Optional) targetFinder.apply(entityinsentient); ++ ++ if (optional.isEmpty()) { ++ return false; ++ } else { ++ LivingEntity entityliving = (LivingEntity) optional.get(); ++ ++ if (!entityinsentient.canAttack(entityliving)) { + return false; + } else { +- Optional optional = targetFinder.apply(mob); +- if (optional.isEmpty()) { ++ // CraftBukkit start ++ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entityinsentient, entityliving, (entityliving instanceof ServerPlayer) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.CLOSEST_ENTITY); ++ if (event.isCancelled()) { + return false; +- } else { +- LivingEntity livingEntity = optional.get(); +- if (!mob.canAttack(livingEntity)) { +- return false; +- } else { +- attackTarget.set(livingEntity); +- cantReachWalkTargetSince.erase(); +- return true; +- } + } ++ if (event.getTarget() == null) { ++ memoryaccessor.erase(); ++ return true; ++ } ++ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ // CraftBukkit end ++ memoryaccessor.set(entityliving); ++ memoryaccessor1.erase(); ++ return true; + } +- }) +- ); ++ } ++ } ++ }; ++ }); ++ }); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java.patch new file mode 100644 index 0000000000..5c6963c45c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java.patch @@ -0,0 +1,104 @@ +--- a/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java ++++ b/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java +@@ -3,56 +3,72 @@ + import java.util.Optional; + import java.util.function.BiConsumer; + import java.util.function.Predicate; +-import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; + import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder; +-import net.minecraft.world.entity.ai.behavior.declarative.MemoryAccessor; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end ++ + public class StopAttackingIfTargetInvalid { ++ + private static final int TIMEOUT_TO_GET_WITHIN_ATTACK_RANGE = 200; + ++ public StopAttackingIfTargetInvalid() {} ++ + public static BehaviorControl create(BiConsumer onStopAttacking) { +- return create(entity -> false, onStopAttacking, true); ++ return create((entityliving) -> { ++ return false; ++ }, onStopAttacking, true); + } + + public static BehaviorControl create(Predicate canStopAttacking) { +- return create(canStopAttacking, (entity, target) -> { ++ return create(canStopAttacking, (entityinsentient, entityliving) -> { + }, true); + } + + public static BehaviorControl create() { +- return create(entity -> false, (entity, target) -> { ++ return create((entityliving) -> { ++ return false; ++ }, (entityinsentient, entityliving) -> { + }, true); + } + +- public static BehaviorControl create( +- Predicate canStopAttacking, BiConsumer onStopAttacking, boolean canGrowTiredOfTryingToReachTarget +- ) { +- return BehaviorBuilder.create( +- instance -> instance.group(instance.present(MemoryModuleType.ATTACK_TARGET), instance.registered(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)) +- .apply( +- instance, +- (attackTarget, cantReachWalkTargetSince) -> (level, mob, gameTime) -> { +- LivingEntity livingEntity = instance.get(attackTarget); +- if (mob.canAttack(livingEntity) +- && (!canGrowTiredOfTryingToReachTarget || !isTiredOfTryingToReachTarget(mob, instance.tryGet(cantReachWalkTargetSince))) +- && livingEntity.isAlive() +- && livingEntity.level() == mob.level() +- && !canStopAttacking.test(livingEntity)) { +- return true; +- } else { +- onStopAttacking.accept(mob, livingEntity); +- attackTarget.erase(); +- return true; +- } +- } +- ) +- ); ++ public static BehaviorControl create(Predicate canStopAttacking, BiConsumer onStopAttacking, boolean canGrowTiredOfTryingToReachTarget) { ++ return BehaviorBuilder.create((behaviorbuilder_b) -> { ++ return behaviorbuilder_b.group(behaviorbuilder_b.present(MemoryModuleType.ATTACK_TARGET), behaviorbuilder_b.registered(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)).apply(behaviorbuilder_b, (memoryaccessor, memoryaccessor1) -> { ++ return (worldserver, entityinsentient, i) -> { ++ LivingEntity entityliving = (LivingEntity) behaviorbuilder_b.get(memoryaccessor); ++ ++ if (entityinsentient.canAttack(entityliving) && (!canGrowTiredOfTryingToReachTarget || !isTiredOfTryingToReachTarget(entityinsentient, behaviorbuilder_b.tryGet(memoryaccessor1))) && entityliving.isAlive() && entityliving.level() == entityinsentient.level() && !canStopAttacking.test(entityliving)) { ++ return true; ++ } else { ++ // CraftBukkit start ++ LivingEntity old = entityinsentient.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); ++ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entityinsentient, null, (old != null && !old.isAlive()) ? EntityTargetEvent.TargetReason.TARGET_DIED : EntityTargetEvent.TargetReason.FORGOT_TARGET); ++ if (event.isCancelled()) { ++ return false; ++ } ++ if (event.getTarget() == null) { ++ memoryaccessor.erase(); ++ return true; ++ } ++ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ // CraftBukkit end ++ onStopAttacking.accept(entityinsentient, entityliving); ++ memoryaccessor.erase(); ++ return true; ++ } ++ }; ++ }); ++ }); + } + + private static boolean isTiredOfTryingToReachTarget(LivingEntity entity, Optional timeSinceInvalidTarget) { +- return timeSinceInvalidTarget.isPresent() && entity.level().getGameTime() - timeSinceInvalidTarget.get() > 200L; ++ return timeSinceInvalidTarget.isPresent() && entity.level().getGameTime() - (Long) timeSinceInvalidTarget.get() > 200L; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java.patch new file mode 100644 index 0000000000..5969cbf516 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java.patch @@ -0,0 +1,188 @@ +--- a/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java ++++ b/net/minecraft/world/entity/ai/behavior/VillagerMakeLove.java +@@ -8,6 +8,7 @@ + import net.minecraft.network.protocol.game.DebugPackets; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.AgeableMob; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; +@@ -16,115 +17,128 @@ + import net.minecraft.world.entity.ai.village.poi.PoiTypes; + import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.level.pathfinder.Path; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++// CraftBukkit end + + public class VillagerMakeLove extends Behavior { ++ + private static final int INTERACT_DIST_SQR = 5; + private static final float SPEED_MODIFIER = 0.5F; + private long birthTimestamp; + + public VillagerMakeLove() { +- super( +- ImmutableMap.of( +- MemoryModuleType.BREED_TARGET, MemoryStatus.VALUE_PRESENT, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryStatus.VALUE_PRESENT +- ), +- 350, +- 350 +- ); ++ super(ImmutableMap.of(MemoryModuleType.BREED_TARGET, MemoryStatus.VALUE_PRESENT, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryStatus.VALUE_PRESENT), 350, 350); + } + +- @Override + protected boolean checkExtraStartConditions(ServerLevel level, Villager owner) { + return this.isBreedingPossible(owner); + } + +- @Override + protected boolean canStillUse(ServerLevel level, Villager entity, long gameTime) { + return gameTime <= this.birthTimestamp && this.isBreedingPossible(entity); + } + +- @Override + protected void start(ServerLevel level, Villager entity, long gameTime) { +- AgeableMob ageableMob = entity.getBrain().getMemory(MemoryModuleType.BREED_TARGET).get(); +- BehaviorUtils.lockGazeAndWalkToEachOther(entity, ageableMob, 0.5F); +- level.broadcastEntityEvent(ageableMob, (byte)18); +- level.broadcastEntityEvent(entity, (byte)18); +- int i = 275 + entity.getRandom().nextInt(50); +- this.birthTimestamp = gameTime + (long)i; ++ AgeableMob entityageable = (AgeableMob) entity.getBrain().getMemory(MemoryModuleType.BREED_TARGET).get(); ++ ++ BehaviorUtils.lockGazeAndWalkToEachOther(entity, entityageable, 0.5F); ++ level.broadcastEntityEvent(entityageable, (byte) 18); ++ level.broadcastEntityEvent(entity, (byte) 18); ++ int j = 275 + entity.getRandom().nextInt(50); ++ ++ this.birthTimestamp = gameTime + (long) j; + } + +- @Override + protected void tick(ServerLevel level, Villager owner, long gameTime) { +- Villager villager = (Villager)owner.getBrain().getMemory(MemoryModuleType.BREED_TARGET).get(); +- if (!(owner.distanceToSqr(villager) > 5.0)) { +- BehaviorUtils.lockGazeAndWalkToEachOther(owner, villager, 0.5F); ++ Villager entityvillager1 = (Villager) owner.getBrain().getMemory(MemoryModuleType.BREED_TARGET).get(); ++ ++ if (owner.distanceToSqr((Entity) entityvillager1) <= 5.0D) { ++ BehaviorUtils.lockGazeAndWalkToEachOther(owner, entityvillager1, 0.5F); + if (gameTime >= this.birthTimestamp) { + owner.eatAndDigestFood(); +- villager.eatAndDigestFood(); +- this.tryToGiveBirth(level, owner, villager); ++ entityvillager1.eatAndDigestFood(); ++ this.tryToGiveBirth(level, owner, entityvillager1); + } else if (owner.getRandom().nextInt(35) == 0) { +- level.broadcastEntityEvent(villager, (byte)12); +- level.broadcastEntityEvent(owner, (byte)12); ++ level.broadcastEntityEvent(entityvillager1, (byte) 12); ++ level.broadcastEntityEvent(owner, (byte) 12); + } ++ + } + } + + private void tryToGiveBirth(ServerLevel level, Villager parent, Villager partner) { + Optional optional = this.takeVacantBed(level, parent); ++ + if (optional.isEmpty()) { +- level.broadcastEntityEvent(partner, (byte)13); +- level.broadcastEntityEvent(parent, (byte)13); ++ level.broadcastEntityEvent(partner, (byte) 13); ++ level.broadcastEntityEvent(parent, (byte) 13); + } else { + Optional optional1 = this.breed(level, parent, partner); ++ + if (optional1.isPresent()) { +- this.giveBedToChild(level, optional1.get(), optional.get()); ++ this.giveBedToChild(level, (Villager) optional1.get(), (BlockPos) optional.get()); + } else { +- level.getPoiManager().release(optional.get()); +- DebugPackets.sendPoiTicketCountPacket(level, optional.get()); ++ level.getPoiManager().release((BlockPos) optional.get()); ++ DebugPackets.sendPoiTicketCountPacket(level, (BlockPos) optional.get()); + } + } ++ + } + +- @Override + protected void stop(ServerLevel level, Villager entity, long gameTime) { + entity.getBrain().eraseMemory(MemoryModuleType.BREED_TARGET); + } + + private boolean isBreedingPossible(Villager villager) { +- Brain brain = villager.getBrain(); +- Optional optional = brain.getMemory(MemoryModuleType.BREED_TARGET).filter(entity -> entity.getType() == EntityType.VILLAGER); +- return !optional.isEmpty() +- && BehaviorUtils.targetIsValid(brain, MemoryModuleType.BREED_TARGET, EntityType.VILLAGER) +- && villager.canBreed() +- && optional.get().canBreed(); ++ Brain behaviorcontroller = villager.getBrain(); ++ Optional optional = behaviorcontroller.getMemory(MemoryModuleType.BREED_TARGET).filter((entityageable) -> { ++ return entityageable.getType() == EntityType.VILLAGER; ++ }); ++ ++ return optional.isEmpty() ? false : BehaviorUtils.targetIsValid(behaviorcontroller, MemoryModuleType.BREED_TARGET, EntityType.VILLAGER) && villager.canBreed() && ((AgeableMob) optional.get()).canBreed(); + } + + private Optional takeVacantBed(ServerLevel level, Villager villager) { +- return level.getPoiManager() +- .take(holder -> holder.is(PoiTypes.HOME), (holder, blockPos) -> this.canReach(villager, blockPos, holder), villager.blockPosition(), 48); ++ return level.getPoiManager().take((holder) -> { ++ return holder.is(PoiTypes.HOME); ++ }, (holder, blockposition) -> { ++ return this.canReach(villager, blockposition, holder); ++ }, villager.blockPosition(), 48); + } + + private boolean canReach(Villager villager, BlockPos pos, Holder poiType) { +- Path path = villager.getNavigation().createPath(pos, poiType.value().validRange()); +- return path != null && path.canReach(); ++ Path pathentity = villager.getNavigation().createPath(pos, ((PoiType) poiType.value()).validRange()); ++ ++ return pathentity != null && pathentity.canReach(); + } + + private Optional breed(ServerLevel level, Villager parent, Villager partner) { +- Villager breedOffspring = parent.getBreedOffspring(level, partner); +- if (breedOffspring == null) { ++ Villager entityvillager2 = parent.getBreedOffspring(level, partner); ++ ++ if (entityvillager2 == null) { + return Optional.empty(); + } else { ++ entityvillager2.setAge(-24000); ++ entityvillager2.moveTo(parent.getX(), parent.getY(), parent.getZ(), 0.0F, 0.0F); ++ // CraftBukkit start - call EntityBreedEvent ++ if (CraftEventFactory.callEntityBreedEvent(entityvillager2, parent, partner, null, null, 0).isCancelled()) { ++ return Optional.empty(); ++ } ++ // Move age setting down + parent.setAge(6000); + partner.setAge(6000); +- breedOffspring.setAge(-24000); +- breedOffspring.moveTo(parent.getX(), parent.getY(), parent.getZ(), 0.0F, 0.0F); +- level.addFreshEntityWithPassengers(breedOffspring); +- level.broadcastEntityEvent(breedOffspring, (byte)12); +- return Optional.of(breedOffspring); ++ level.addFreshEntityWithPassengers(entityvillager2, CreatureSpawnEvent.SpawnReason.BREEDING); ++ // CraftBukkit end ++ level.broadcastEntityEvent(entityvillager2, (byte) 12); ++ return Optional.of(entityvillager2); + } + } + + private void giveBedToChild(ServerLevel level, Villager villager, BlockPos pos) { +- GlobalPos globalPos = GlobalPos.of(level.dimension(), pos); +- villager.getBrain().setMemory(MemoryModuleType.HOME, globalPos); ++ GlobalPos globalpos = GlobalPos.of(level.dimension(), pos); ++ ++ villager.getBrain().setMemory(MemoryModuleType.HOME, globalpos); // CraftBukkit - decompile error + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java.patch new file mode 100644 index 0000000000..508ac1ba97 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java.patch @@ -0,0 +1,75 @@ +--- a/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java ++++ b/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java +@@ -7,14 +7,17 @@ + import net.minecraft.world.level.block.Block; + + public class BreakDoorGoal extends DoorInteractGoal { ++ + private static final int DEFAULT_DOOR_BREAK_TIME = 240; + private final Predicate validDifficulties; + protected int breakTime; +- protected int lastBreakProgress = -1; +- protected int doorBreakTime = -1; ++ protected int lastBreakProgress; ++ protected int doorBreakTime; + + public BreakDoorGoal(Mob mob, Predicate validDifficulties) { + super(mob); ++ this.lastBreakProgress = -1; ++ this.doorBreakTime = -1; + this.validDifficulties = validDifficulties; + } + +@@ -29,10 +32,7 @@ + + @Override + public boolean canUse() { +- return super.canUse() +- && this.mob.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) +- && this.isValidDifficulty(this.mob.level().getDifficulty()) +- && !this.isOpen(); ++ return !super.canUse() ? false : (!this.mob.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? false : this.isValidDifficulty(this.mob.level().getDifficulty()) && !this.isOpen()); + } + + @Override +@@ -43,10 +43,7 @@ + + @Override + public boolean canContinueToUse() { +- return this.breakTime <= this.getDoorBreakTime() +- && !this.isOpen() +- && this.doorPos.closerToCenterThan(this.mob.position(), 2.0) +- && this.isValidDifficulty(this.mob.level().getDifficulty()); ++ return this.breakTime <= this.getDoorBreakTime() && !this.isOpen() && this.doorPos.closerToCenterThan(this.mob.position(), 2.0D) && this.isValidDifficulty(this.mob.level().getDifficulty()); + } + + @Override +@@ -65,18 +62,26 @@ + } + } + +- this.breakTime++; +- int i = (int)((float)this.breakTime / (float)this.getDoorBreakTime() * 10.0F); ++ ++this.breakTime; ++ int i = (int) ((float) this.breakTime / (float) this.getDoorBreakTime() * 10.0F); ++ + if (i != this.lastBreakProgress) { + this.mob.level().destroyBlockProgress(this.mob.getId(), this.doorPos, i); + this.lastBreakProgress = i; + } + + if (this.breakTime == this.getDoorBreakTime() && this.isValidDifficulty(this.mob.level().getDifficulty())) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreakDoorEvent(this.mob, this.doorPos).isCancelled()) { ++ this.start(); ++ return; ++ } ++ // CraftBukkit end + this.mob.level().removeBlock(this.doorPos, false); + this.mob.level().levelEvent(1021, this.doorPos, 0); + this.mob.level().levelEvent(2001, this.doorPos, Block.getId(this.mob.level().getBlockState(this.doorPos))); + } ++ + } + + private boolean isValidDifficulty(Difficulty difficulty) { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/EatBlockGoal.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/EatBlockGoal.java.patch new file mode 100644 index 0000000000..d8a80446fa --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/EatBlockGoal.java.patch @@ -0,0 +1,88 @@ +--- a/net/minecraft/world/entity/ai/goal/EatBlockGoal.java ++++ b/net/minecraft/world/entity/ai/goal/EatBlockGoal.java +@@ -8,12 +8,17 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.predicate.BlockStatePredicate; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class EatBlockGoal extends Goal { ++ + private static final int EAT_ANIMATION_TICKS = 40; +- private static final Predicate IS_TALL_GRASS = BlockStatePredicate.forBlock(Blocks.SHORT_GRASS); ++ private static final Predicate IS_TALL_GRASS = BlockStatePredicate.forBlock(Blocks.SHORT_GRASS); + private final Mob mob; + private final Level level; + private int eatAnimationTick; +@@ -21,7 +26,7 @@ + public EatBlockGoal(Mob mob) { + this.mob = mob; + this.level = mob.level(); +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK, Goal.Flag.JUMP)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK, Goal.Type.JUMP)); + } + + @Override +@@ -29,15 +34,16 @@ + if (this.mob.getRandom().nextInt(this.mob.isBaby() ? 50 : 1000) != 0) { + return false; + } else { +- BlockPos blockPos = this.mob.blockPosition(); +- return IS_TALL_GRASS.test(this.level.getBlockState(blockPos)) || this.level.getBlockState(blockPos.below()).is(Blocks.GRASS_BLOCK); ++ BlockPos blockposition = this.mob.blockPosition(); ++ ++ return EatBlockGoal.IS_TALL_GRASS.test(this.level.getBlockState(blockposition)) ? true : this.level.getBlockState(blockposition.below()).is(Blocks.GRASS_BLOCK); + } + } + + @Override + public void start() { + this.eatAnimationTick = this.adjustedTickDelay(40); +- this.level.broadcastEntityEvent(this.mob, (byte)10); ++ this.level.broadcastEntityEvent(this.mob, (byte) 10); + this.mob.getNavigation().stop(); + } + +@@ -59,24 +65,27 @@ + public void tick() { + this.eatAnimationTick = Math.max(0, this.eatAnimationTick - 1); + if (this.eatAnimationTick == this.adjustedTickDelay(4)) { +- BlockPos blockPos = this.mob.blockPosition(); +- if (IS_TALL_GRASS.test(this.level.getBlockState(blockPos))) { +- if (this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- this.level.destroyBlock(blockPos, false); ++ BlockPos blockposition = this.mob.blockPosition(); ++ ++ if (EatBlockGoal.IS_TALL_GRASS.test(this.level.getBlockState(blockposition))) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition, Blocks.AIR.defaultBlockState(), !this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit ++ this.level.destroyBlock(blockposition, false); + } + + this.mob.ate(); + } else { +- BlockPos blockPos1 = blockPos.below(); +- if (this.level.getBlockState(blockPos1).is(Blocks.GRASS_BLOCK)) { +- if (this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- this.level.levelEvent(2001, blockPos1, Block.getId(Blocks.GRASS_BLOCK.defaultBlockState())); +- this.level.setBlock(blockPos1, Blocks.DIRT.defaultBlockState(), 2); ++ BlockPos blockposition1 = blockposition.below(); ++ ++ if (this.level.getBlockState(blockposition1).is(Blocks.GRASS_BLOCK)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition1, Blocks.AIR.defaultBlockState(), !this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit ++ this.level.levelEvent(2001, blockposition1, Block.getId(Blocks.GRASS_BLOCK.defaultBlockState())); ++ this.level.setBlock(blockposition1, Blocks.DIRT.defaultBlockState(), 2); + } + + this.mob.ate(); + } + } ++ + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java.patch new file mode 100644 index 0000000000..d829cd9778 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java.patch @@ -0,0 +1,169 @@ +--- a/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java ++++ b/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java +@@ -2,6 +2,7 @@ + + import java.util.EnumSet; + import net.minecraft.core.BlockPos; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.TamableAnimal; + import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation; +@@ -9,11 +10,17 @@ + import net.minecraft.world.entity.ai.navigation.PathNavigation; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.LeavesBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.level.pathfinder.WalkNodeEvaluator; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTeleportEvent; ++// CraftBukkit end + + public class FollowOwnerGoal extends Goal { ++ + public static final int TELEPORT_WHEN_DISTANCE_IS = 12; + private static final int MIN_HORIZONTAL_DISTANCE_FROM_PLAYER_WHEN_TELEPORTING = 2; + private static final int MAX_HORIZONTAL_DISTANCE_FROM_PLAYER_WHEN_TELEPORTING = 3; +@@ -29,15 +36,15 @@ + private float oldWaterCost; + private final boolean canFly; + +- public FollowOwnerGoal(TamableAnimal tamable, double speedModifier, float startDistance, float stopDistance, boolean canFly) { ++ public FollowOwnerGoal(TamableAnimal tamable, double speedModifier, float f, float startDistance, boolean stopDistance) { + this.tamable = tamable; + this.level = tamable.level(); + this.speedModifier = speedModifier; + this.navigation = tamable.getNavigation(); +- this.startDistance = startDistance; +- this.stopDistance = stopDistance; +- this.canFly = canFly; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ this.startDistance = f; ++ this.stopDistance = startDistance; ++ this.canFly = stopDistance; ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + if (!(tamable.getNavigation() instanceof GroundPathNavigation) && !(tamable.getNavigation() instanceof FlyingPathNavigation)) { + throw new IllegalArgumentException("Unsupported mob type for FollowOwnerGoal"); + } +@@ -45,26 +52,25 @@ + + @Override + public boolean canUse() { +- LivingEntity owner = this.tamable.getOwner(); +- if (owner == null) { ++ LivingEntity entityliving = this.tamable.getOwner(); ++ ++ if (entityliving == null) { + return false; +- } else if (owner.isSpectator()) { ++ } else if (entityliving.isSpectator()) { + return false; + } else if (this.unableToMove()) { + return false; +- } else if (this.tamable.distanceToSqr(owner) < (double)(this.startDistance * this.startDistance)) { ++ } else if (this.tamable.distanceToSqr((Entity) entityliving) < (double) (this.startDistance * this.startDistance)) { + return false; + } else { +- this.owner = owner; ++ this.owner = entityliving; + return true; + } + } + + @Override + public boolean canContinueToUse() { +- return !this.navigation.isDone() +- && !this.unableToMove() +- && !(this.tamable.distanceToSqr(this.owner) <= (double)(this.stopDistance * this.stopDistance)); ++ return this.navigation.isDone() ? false : (this.unableToMove() ? false : this.tamable.distanceToSqr((Entity) this.owner) > (double) (this.stopDistance * this.stopDistance)); + } + + private boolean unableToMove() { +@@ -87,54 +93,67 @@ + + @Override + public void tick() { +- this.tamable.getLookControl().setLookAt(this.owner, 10.0F, (float)this.tamable.getMaxHeadXRot()); ++ this.tamable.getLookControl().setLookAt(this.owner, 10.0F, (float) this.tamable.getMaxHeadXRot()); + if (--this.timeToRecalcPath <= 0) { + this.timeToRecalcPath = this.adjustedTickDelay(10); +- if (this.tamable.distanceToSqr(this.owner) >= 144.0) { ++ if (this.tamable.distanceToSqr((Entity) this.owner) >= 144.0D) { + this.teleportToOwner(); + } else { +- this.navigation.moveTo(this.owner, this.speedModifier); ++ this.navigation.moveTo((Entity) this.owner, this.speedModifier); + } ++ + } + } + + private void teleportToOwner() { +- BlockPos blockPos = this.owner.blockPosition(); ++ BlockPos blockposition = this.owner.blockPosition(); + +- for (int i = 0; i < 10; i++) { +- int i1 = this.randomIntInclusive(-3, 3); +- int i2 = this.randomIntInclusive(-1, 1); +- int i3 = this.randomIntInclusive(-3, 3); +- boolean flag = this.maybeTeleportTo(blockPos.getX() + i1, blockPos.getY() + i2, blockPos.getZ() + i3); ++ for (int i = 0; i < 10; ++i) { ++ int j = this.randomIntInclusive(-3, 3); ++ int k = this.randomIntInclusive(-1, 1); ++ int l = this.randomIntInclusive(-3, 3); ++ boolean flag = this.maybeTeleportTo(blockposition.getX() + j, blockposition.getY() + k, blockposition.getZ() + l); ++ + if (flag) { + return; + } + } ++ + } + + private boolean maybeTeleportTo(int x, int y, int z) { +- if (Math.abs((double)x - this.owner.getX()) < 2.0 && Math.abs((double)z - this.owner.getZ()) < 2.0) { ++ if (Math.abs((double) x - this.owner.getX()) < 2.0D && Math.abs((double) z - this.owner.getZ()) < 2.0D) { + return false; + } else if (!this.canTeleportTo(new BlockPos(x, y, z))) { + return false; + } else { +- this.tamable.moveTo((double)x + 0.5, (double)y, (double)z + 0.5, this.tamable.getYRot(), this.tamable.getXRot()); ++ // CraftBukkit start ++ EntityTeleportEvent event = CraftEventFactory.callEntityTeleportEvent(this.tamable, (double) x + 0.5D, (double) y, (double) z + 0.5D); ++ if (event.isCancelled()) { ++ return false; ++ } ++ Location to = event.getTo(); ++ this.tamable.moveTo(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch()); ++ // CraftBukkit end + this.navigation.stop(); + return true; + } + } + + private boolean canTeleportTo(BlockPos pos) { +- BlockPathTypes blockPathTypeStatic = WalkNodeEvaluator.getBlockPathTypeStatic(this.level, pos.mutable()); +- if (blockPathTypeStatic != BlockPathTypes.WALKABLE) { ++ BlockPathTypes pathtype = WalkNodeEvaluator.getBlockPathTypeStatic(this.level, pos.mutable()); ++ ++ if (pathtype != BlockPathTypes.WALKABLE) { + return false; + } else { +- BlockState blockState = this.level.getBlockState(pos.below()); +- if (!this.canFly && blockState.getBlock() instanceof LeavesBlock) { ++ IBlockData iblockdata = this.level.getBlockState(pos.below()); ++ ++ if (!this.canFly && iblockdata.getBlock() instanceof LeavesBlock) { + return false; + } else { +- BlockPos blockPos = pos.subtract(this.tamable.blockPosition()); +- return this.level.noCollision(this.tamable, this.tamable.getBoundingBox().move(blockPos)); ++ BlockPos blockposition1 = pos.subtract(this.tamable.blockPosition()); ++ ++ return this.level.noCollision(this.tamable, this.tamable.getBoundingBox().move(blockposition1)); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java.patch new file mode 100644 index 0000000000..ae8b553630 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java.patch @@ -0,0 +1,179 @@ +--- a/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java ++++ b/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java +@@ -20,15 +20,20 @@ + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class RemoveBlockGoal extends MoveToBlockGoal { ++ + private final Block blockToRemove; + private final Mob removerMob; + private int ticksSinceReachedGoal; + private static final int WAIT_AFTER_BLOCK_FOUND = 20; + +- public RemoveBlockGoal(Block blockToRemove, PathfinderMob removerMob, double speedModifier, int searchRange) { +- super(removerMob, speedModifier, 24, searchRange); ++ public RemoveBlockGoal(Block blockToRemove, PathfinderMob removerMob, double speedModifier, int i) { ++ super(removerMob, speedModifier, 24, i); + this.blockToRemove = blockToRemove; + this.removerMob = removerMob; + } +@@ -38,7 +43,7 @@ + if (!this.removerMob.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { + return false; + } else if (this.nextStartTick > 0) { +- this.nextStartTick--; ++ --this.nextStartTick; + return false; + } else if (this.findNearestBlock()) { + this.nextStartTick = reducedTickDelay(20); +@@ -61,75 +66,62 @@ + this.ticksSinceReachedGoal = 0; + } + +- public void playDestroyProgressSound(LevelAccessor level, BlockPos pos) { +- } ++ public void playDestroyProgressSound(LevelAccessor level, BlockPos pos) {} + +- public void playBreakSound(Level level, BlockPos pos) { +- } ++ public void playBreakSound(Level level, BlockPos pos) {} + + @Override + public void tick() { + super.tick(); +- Level level = this.removerMob.level(); +- BlockPos blockPos = this.removerMob.blockPosition(); +- BlockPos posWithBlock = this.getPosWithBlock(blockPos, level); +- RandomSource random = this.removerMob.getRandom(); +- if (this.isReachedTarget() && posWithBlock != null) { ++ Level world = this.removerMob.level(); ++ BlockPos blockposition = this.removerMob.blockPosition(); ++ BlockPos blockposition1 = this.getPosWithBlock(blockposition, world); ++ RandomSource randomsource = this.removerMob.getRandom(); ++ ++ if (this.isReachedTarget() && blockposition1 != null) { ++ Vec3 vec3d; ++ double d0; ++ + if (this.ticksSinceReachedGoal > 0) { +- Vec3 deltaMovement = this.removerMob.getDeltaMovement(); +- this.removerMob.setDeltaMovement(deltaMovement.x, 0.3, deltaMovement.z); +- if (!level.isClientSide) { +- double d = 0.08; +- ((ServerLevel)level) +- .sendParticles( +- new ItemParticleOption(ParticleTypes.ITEM, new ItemStack(Items.EGG)), +- (double)posWithBlock.getX() + 0.5, +- (double)posWithBlock.getY() + 0.7, +- (double)posWithBlock.getZ() + 0.5, +- 3, +- ((double)random.nextFloat() - 0.5) * 0.08, +- ((double)random.nextFloat() - 0.5) * 0.08, +- ((double)random.nextFloat() - 0.5) * 0.08, +- 0.15F +- ); ++ vec3d = this.removerMob.getDeltaMovement(); ++ this.removerMob.setDeltaMovement(vec3d.x, 0.3D, vec3d.z); ++ if (!world.isClientSide) { ++ d0 = 0.08D; ++ ((ServerLevel) world).sendParticles(new ItemParticleOption(ParticleTypes.ITEM, new ItemStack(Items.EGG)), (double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.7D, (double) blockposition1.getZ() + 0.5D, 3, ((double) randomsource.nextFloat() - 0.5D) * 0.08D, ((double) randomsource.nextFloat() - 0.5D) * 0.08D, ((double) randomsource.nextFloat() - 0.5D) * 0.08D, 0.15000000596046448D); + } + } + + if (this.ticksSinceReachedGoal % 2 == 0) { +- Vec3 deltaMovement = this.removerMob.getDeltaMovement(); +- this.removerMob.setDeltaMovement(deltaMovement.x, -0.3, deltaMovement.z); ++ vec3d = this.removerMob.getDeltaMovement(); ++ this.removerMob.setDeltaMovement(vec3d.x, -0.3D, vec3d.z); + if (this.ticksSinceReachedGoal % 6 == 0) { +- this.playDestroyProgressSound(level, this.blockPos); ++ this.playDestroyProgressSound(world, this.blockPos); + } + } + + if (this.ticksSinceReachedGoal > 60) { +- level.removeBlock(posWithBlock, false); +- if (!level.isClientSide) { +- for (int i = 0; i < 20; i++) { +- double d = random.nextGaussian() * 0.02; +- double d1 = random.nextGaussian() * 0.02; +- double d2 = random.nextGaussian() * 0.02; +- ((ServerLevel)level) +- .sendParticles( +- ParticleTypes.POOF, +- (double)posWithBlock.getX() + 0.5, +- (double)posWithBlock.getY(), +- (double)posWithBlock.getZ() + 0.5, +- 1, +- d, +- d1, +- d2, +- 0.15F +- ); ++ // CraftBukkit start - Step on eggs ++ if (!CraftEventFactory.callEntityInteractEvent(this.removerMob, CraftBlock.at(world, blockposition1))) { ++ return; ++ } ++ // CraftBukkit end ++ world.removeBlock(blockposition1, false); ++ if (!world.isClientSide) { ++ for (int i = 0; i < 20; ++i) { ++ d0 = randomsource.nextGaussian() * 0.02D; ++ double d1 = randomsource.nextGaussian() * 0.02D; ++ double d2 = randomsource.nextGaussian() * 0.02D; ++ ++ ((ServerLevel) world).sendParticles(ParticleTypes.POOF, (double) blockposition1.getX() + 0.5D, (double) blockposition1.getY(), (double) blockposition1.getZ() + 0.5D, 1, d0, d1, d2, 0.15000000596046448D); + } + +- this.playBreakSound(level, posWithBlock); ++ this.playBreakSound(world, blockposition1); + } + } + +- this.ticksSinceReachedGoal++; ++ ++this.ticksSinceReachedGoal; + } ++ + } + + @Nullable +@@ -137,11 +129,15 @@ + if (level.getBlockState(pos).is(this.blockToRemove)) { + return pos; + } else { +- BlockPos[] blockPoss = new BlockPos[]{pos.below(), pos.west(), pos.east(), pos.north(), pos.south(), pos.below().below()}; ++ BlockPos[] ablockposition = new BlockPos[]{pos.below(), pos.west(), pos.east(), pos.north(), pos.south(), pos.below().below()}; ++ BlockPos[] ablockposition1 = ablockposition; ++ int i = ablockposition.length; + +- for (BlockPos blockPos : blockPoss) { +- if (level.getBlockState(blockPos).is(this.blockToRemove)) { +- return blockPos; ++ for (int j = 0; j < i; ++j) { ++ BlockPos blockposition1 = ablockposition1[j]; ++ ++ if (level.getBlockState(blockposition1).is(this.blockToRemove)) { ++ return blockposition1; + } + } + +@@ -151,10 +147,8 @@ + + @Override + protected boolean isValidTarget(LevelReader level, BlockPos pos) { +- ChunkAccess chunk = level.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()), ChunkStatus.FULL, false); +- return chunk != null +- && chunk.getBlockState(pos).is(this.blockToRemove) +- && chunk.getBlockState(pos.above()).isAir() +- && chunk.getBlockState(pos.above(2)).isAir(); ++ ChunkAccess ichunkaccess = level.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()), ChunkStatus.FULL, false); ++ ++ return ichunkaccess == null ? false : ichunkaccess.getBlockState(pos).is(this.blockToRemove) && ichunkaccess.getBlockState(pos.above()).isAir() && ichunkaccess.getBlockState(pos.above(2)).isAir(); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java.patch new file mode 100644 index 0000000000..687e66fb08 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java.patch @@ -0,0 +1,80 @@ +--- a/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java ++++ b/net/minecraft/world/entity/ai/goal/RunAroundLikeCrazyGoal.java +@@ -6,8 +6,13 @@ + import net.minecraft.world.entity.animal.horse.AbstractHorse; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class RunAroundLikeCrazyGoal extends Goal { ++ + private final AbstractHorse horse; + private final double speedModifier; + private double posX; +@@ -17,19 +22,20 @@ + public RunAroundLikeCrazyGoal(AbstractHorse horse, double speedModifier) { + this.horse = horse; + this.speedModifier = speedModifier; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override + public boolean canUse() { + if (!this.horse.isTamed() && this.horse.isVehicle()) { +- Vec3 pos = DefaultRandomPos.getPos(this.horse, 5, 4); +- if (pos == null) { ++ Vec3 vec3d = DefaultRandomPos.getPos(this.horse, 5, 4); ++ ++ if (vec3d == null) { + return false; + } else { +- this.posX = pos.x; +- this.posY = pos.y; +- this.posZ = pos.z; ++ this.posX = vec3d.x; ++ this.posY = vec3d.y; ++ this.posZ = vec3d.z; + return true; + } + } else { +@@ -50,16 +56,19 @@ + @Override + public void tick() { + if (!this.horse.isTamed() && this.horse.getRandom().nextInt(this.adjustedTickDelay(50)) == 0) { +- Entity firstPassenger = this.horse.getFirstPassenger(); +- if (firstPassenger == null) { ++ Entity entity = this.horse.getFirstPassenger(); ++ ++ if (entity == null) { + return; + } + +- if (firstPassenger instanceof Player player) { +- int temper = this.horse.getTemper(); +- int maxTemper = this.horse.getMaxTemper(); +- if (maxTemper > 0 && this.horse.getRandom().nextInt(maxTemper) < temper) { +- this.horse.tameWithName(player); ++ if (entity instanceof Player) { ++ Player entityhuman = (Player) entity; ++ int i = this.horse.getTemper(); ++ int j = this.horse.getMaxTemper(); ++ ++ if (j > 0 && this.horse.getRandom().nextInt(j) < i && !CraftEventFactory.callEntityTameEvent(this.horse, ((CraftHumanEntity) this.horse.getBukkitEntity().getPassenger()).getHandle()).isCancelled()) { // CraftBukkit - fire EntityTameEvent ++ this.horse.tameWithName(entityhuman); + return; + } + +@@ -68,7 +77,8 @@ + + this.horse.ejectPassengers(); + this.horse.makeMad(); +- this.horse.level().broadcastEntityEvent(this.horse, (byte)6); ++ this.horse.level().broadcastEntityEvent(this.horse, (byte) 6); + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java.patch new file mode 100644 index 0000000000..d5850466e5 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java ++++ b/net/minecraft/world/entity/ai/goal/SitWhenOrderedToGoal.java +@@ -1,15 +1,17 @@ + package net.minecraft.world.entity.ai.goal; + + import java.util.EnumSet; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.TamableAnimal; + + public class SitWhenOrderedToGoal extends Goal { ++ + private final TamableAnimal mob; + + public SitWhenOrderedToGoal(TamableAnimal mob) { + this.mob = mob; +- this.setFlags(EnumSet.of(Goal.Flag.JUMP, Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.JUMP, Goal.Type.MOVE)); + } + + @Override +@@ -20,14 +22,15 @@ + @Override + public boolean canUse() { + if (!this.mob.isTame()) { +- return false; ++ return this.mob.isOrderedToSit() && this.mob.getTarget() == null; // CraftBukkit - Allow sitting for wild animals + } else if (this.mob.isInWaterOrBubble()) { + return false; + } else if (!this.mob.onGround()) { + return false; + } else { +- LivingEntity owner = this.mob.getOwner(); +- return owner == null || (!(this.mob.distanceToSqr(owner) < 144.0) || owner.getLastHurtByMob() == null) && this.mob.isOrderedToSit(); ++ LivingEntity entityliving = this.mob.getOwner(); ++ ++ return entityliving == null ? true : (this.mob.distanceToSqr((Entity) entityliving) < 144.0D && entityliving.getLastHurtByMob() != null ? false : this.mob.isOrderedToSit()); + } + } + diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/TemptGoal.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/TemptGoal.java.patch new file mode 100644 index 0000000000..eb738ecf64 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/goal/TemptGoal.java.patch @@ -0,0 +1,115 @@ +--- a/net/minecraft/world/entity/ai/goal/TemptGoal.java ++++ b/net/minecraft/world/entity/ai/goal/TemptGoal.java +@@ -2,14 +2,21 @@ + + import java.util.EnumSet; + import javax.annotation.Nullable; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.PathfinderMob; + import net.minecraft.world.entity.ai.targeting.TargetingConditions; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.crafting.Ingredient; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++// CraftBukkit end + + public class TemptGoal extends Goal { +- private static final TargetingConditions TEMP_TARGETING = TargetingConditions.forNonCombat().range(10.0).ignoreLineOfSight(); ++ ++ private static final TargetingConditions TEMP_TARGETING = TargetingConditions.forNonCombat().range(10.0D).ignoreLineOfSight(); + private final TargetingConditions targetingConditions; + protected final PathfinderMob mob; + private final double speedModifier; +@@ -19,28 +26,37 @@ + private double pRotX; + private double pRotY; + @Nullable +- protected Player player; ++ protected LivingEntity player; // CraftBukkit + private int calmDown; + private boolean isRunning; + private final Ingredient items; + private final boolean canScare; + +- public TemptGoal(PathfinderMob mob, double speedModifier, Ingredient items, boolean canScare) { ++ public TemptGoal(PathfinderMob mob, double speedModifier, Ingredient recipeitemstack, boolean items) { + this.mob = mob; + this.speedModifier = speedModifier; +- this.items = items; +- this.canScare = canScare; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); +- this.targetingConditions = TEMP_TARGETING.copy().selector(this::shouldFollow); ++ this.items = recipeitemstack; ++ this.canScare = items; ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); ++ this.targetingConditions = TemptGoal.TEMP_TARGETING.copy().selector(this::shouldFollow); + } + + @Override + public boolean canUse() { + if (this.calmDown > 0) { +- this.calmDown--; ++ --this.calmDown; + return false; + } else { + this.player = this.mob.level().getNearestPlayer(this.targetingConditions, this.mob); ++ // CraftBukkit start ++ if (this.player != null) { ++ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(this.mob, this.player, EntityTargetEvent.TargetReason.TEMPT); ++ if (event.isCancelled()) { ++ return false; ++ } ++ this.player = (event.getTarget() == null) ? null : ((CraftLivingEntity) event.getTarget()).getHandle(); ++ } ++ // CraftBukkit end + return this.player != null; + } + } +@@ -52,12 +68,12 @@ + @Override + public boolean canContinueToUse() { + if (this.canScare()) { +- if (this.mob.distanceToSqr(this.player) < 36.0) { +- if (this.player.distanceToSqr(this.px, this.py, this.pz) > 0.010000000000000002) { ++ if (this.mob.distanceToSqr((Entity) this.player) < 36.0D) { ++ if (this.player.distanceToSqr(this.px, this.py, this.pz) > 0.010000000000000002D) { + return false; + } + +- if (Math.abs((double)this.player.getXRot() - this.pRotX) > 5.0 || Math.abs((double)this.player.getYRot() - this.pRotY) > 5.0) { ++ if (Math.abs((double) this.player.getXRot() - this.pRotX) > 5.0D || Math.abs((double) this.player.getYRot() - this.pRotY) > 5.0D) { + return false; + } + } else { +@@ -66,8 +82,8 @@ + this.pz = this.player.getZ(); + } + +- this.pRotX = (double)this.player.getXRot(); +- this.pRotY = (double)this.player.getYRot(); ++ this.pRotX = (double) this.player.getXRot(); ++ this.pRotY = (double) this.player.getYRot(); + } + + return this.canUse(); +@@ -95,12 +111,13 @@ + + @Override + public void tick() { +- this.mob.getLookControl().setLookAt(this.player, (float)(this.mob.getMaxHeadYRot() + 20), (float)this.mob.getMaxHeadXRot()); +- if (this.mob.distanceToSqr(this.player) < 6.25) { ++ this.mob.getLookControl().setLookAt(this.player, (float) (this.mob.getMaxHeadYRot() + 20), (float) this.mob.getMaxHeadXRot()); ++ if (this.mob.distanceToSqr((Entity) this.player) < 6.25D) { + this.mob.getNavigation().stop(); + } else { +- this.mob.getNavigation().moveTo(this.player, this.speedModifier); ++ this.mob.getNavigation().moveTo((Entity) this.player, this.speedModifier); + } ++ + } + + public boolean isRunning() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/sensing/TemptingSensor.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/sensing/TemptingSensor.java.patch new file mode 100644 index 0000000000..e1f1369c16 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/sensing/TemptingSensor.java.patch @@ -0,0 +1,87 @@ +--- a/net/minecraft/world/entity/ai/sensing/TemptingSensor.java ++++ b/net/minecraft/world/entity/ai/sensing/TemptingSensor.java +@@ -3,10 +3,12 @@ + import com.google.common.collect.ImmutableSet; + import java.util.Comparator; + import java.util.List; ++import java.util.Objects; + import java.util.Set; + import java.util.stream.Collectors; ++import java.util.stream.Stream; + import net.minecraft.server.level.ServerLevel; +-import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.PathfinderMob; + import net.minecraft.world.entity.ai.Brain; +@@ -15,34 +17,55 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.crafting.Ingredient; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++// CraftBukkit end + + public class TemptingSensor extends Sensor { ++ + public static final int TEMPTATION_RANGE = 10; +- private static final TargetingConditions TEMPT_TARGETING = TargetingConditions.forNonCombat().range(10.0).ignoreLineOfSight(); ++ private static final TargetingConditions TEMPT_TARGETING = TargetingConditions.forNonCombat().range(10.0D).ignoreLineOfSight(); + private final Ingredient temptations; + + public TemptingSensor(Ingredient temptations) { + this.temptations = temptations; + } + +- @Override + protected void doTick(ServerLevel level, PathfinderMob entity) { +- Brain brain = entity.getBrain(); +- List list = level.players() +- .stream() +- .filter(EntitySelector.NO_SPECTATORS) +- .filter(player1 -> TEMPT_TARGETING.test(entity, player1)) +- .filter(serverPlayer -> entity.closerThan(serverPlayer, 10.0)) +- .filter(this::playerHoldingTemptation) +- .filter(serverPlayer -> !entity.hasPassenger(serverPlayer)) +- .sorted(Comparator.comparingDouble(entity::distanceToSqr)) +- .collect(Collectors.toList()); ++ Brain behaviorcontroller = entity.getBrain(); ++ Stream stream = level.players().stream().filter(EntitySelector.NO_SPECTATORS).filter((entityplayer) -> { // CraftBukkit - decompile error ++ return TemptingSensor.TEMPT_TARGETING.test(entity, entityplayer); ++ }).filter((entityplayer) -> { ++ return entity.closerThan(entityplayer, 10.0D); ++ }).filter(this::playerHoldingTemptation).filter((entityplayer) -> { ++ return !entity.hasPassenger((Entity) entityplayer); ++ }); ++ ++ Objects.requireNonNull(entity); ++ List list = (List) stream.sorted(Comparator.comparingDouble(entity::distanceToSqr)).collect(Collectors.toList()); ++ + if (!list.isEmpty()) { +- Player player = list.get(0); +- brain.setMemory(MemoryModuleType.TEMPTING_PLAYER, player); ++ Player entityhuman = (Player) list.get(0); ++ ++ // CraftBukkit start ++ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(entity, entityhuman, EntityTargetEvent.TargetReason.TEMPT); ++ if (event.isCancelled()) { ++ return; ++ } ++ if (event.getTarget() instanceof HumanEntity) { ++ behaviorcontroller.setMemory(MemoryModuleType.TEMPTING_PLAYER, ((CraftHumanEntity) event.getTarget()).getHandle()); ++ } else { ++ behaviorcontroller.eraseMemory(MemoryModuleType.TEMPTING_PLAYER); ++ } ++ // CraftBukkit end + } else { +- brain.eraseMemory(MemoryModuleType.TEMPTING_PLAYER); ++ behaviorcontroller.eraseMemory(MemoryModuleType.TEMPTING_PLAYER); + } ++ + } + + private boolean playerHoldingTemptation(Player player) { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/village/VillageSiege.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/village/VillageSiege.java.patch new file mode 100644 index 0000000000..edfb2cbcad --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ai/village/VillageSiege.java.patch @@ -0,0 +1,162 @@ +--- a/net/minecraft/world/entity/ai/village/VillageSiege.java ++++ b/net/minecraft/world/entity/ai/village/VillageSiege.java +@@ -1,13 +1,16 @@ + package net.minecraft.world.entity.ai.village; + + import com.mojang.logging.LogUtils; ++import java.util.Iterator; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; ++import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.tags.BiomeTags; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.monster.Monster; + import net.minecraft.world.entity.monster.Zombie; + import net.minecraft.world.entity.player.Player; +@@ -17,20 +20,26 @@ + import org.slf4j.Logger; + + public class VillageSiege implements CustomSpawner { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private boolean hasSetupSiege; +- private VillageSiege.State siegeState = VillageSiege.State.SIEGE_DONE; ++ private VillageSiege.State siegeState; + private int zombiesToSpawn; + private int nextSpawnTime; + private int spawnX; + private int spawnY; + private int spawnZ; + ++ public VillageSiege() { ++ this.siegeState = VillageSiege.State.SIEGE_DONE; ++ } ++ + @Override + public int tick(ServerLevel level, boolean spawnHostiles, boolean spawnPassives) { + if (!level.isDay() && spawnHostiles) { +- float timeOfDay = level.getTimeOfDay(0.0F); +- if ((double)timeOfDay == 0.5) { ++ float f = level.getTimeOfDay(0.0F); ++ ++ if ((double) f == 0.5D) { + this.siegeState = level.random.nextInt(10) == 0 ? VillageSiege.State.SIEGE_TONIGHT : VillageSiege.State.SIEGE_DONE; + } + +@@ -46,13 +55,13 @@ + } + + if (this.nextSpawnTime > 0) { +- this.nextSpawnTime--; ++ --this.nextSpawnTime; + return 0; + } else { + this.nextSpawnTime = 2; + if (this.zombiesToSpawn > 0) { + this.trySpawn(level); +- this.zombiesToSpawn--; ++ --this.zombiesToSpawn; + } else { + this.siegeState = VillageSiege.State.SIEGE_DONE; + } +@@ -68,15 +77,21 @@ + } + + private boolean tryToSetupSiege(ServerLevel level) { +- for (Player player : level.players()) { +- if (!player.isSpectator()) { +- BlockPos blockPos = player.blockPosition(); +- if (level.isVillage(blockPos) && !level.getBiome(blockPos).is(BiomeTags.WITHOUT_ZOMBIE_SIEGES)) { +- for (int i = 0; i < 10; i++) { +- float f = level.random.nextFloat() * (float) (Math.PI * 2); +- this.spawnX = blockPos.getX() + Mth.floor(Mth.cos(f) * 32.0F); +- this.spawnY = blockPos.getY(); +- this.spawnZ = blockPos.getZ() + Mth.floor(Mth.sin(f) * 32.0F); ++ Iterator iterator = level.players().iterator(); ++ ++ while (iterator.hasNext()) { ++ Player entityhuman = (Player) iterator.next(); ++ ++ if (!entityhuman.isSpectator()) { ++ BlockPos blockposition = entityhuman.blockPosition(); ++ ++ if (level.isVillage(blockposition) && !level.getBiome(blockposition).is(BiomeTags.WITHOUT_ZOMBIE_SIEGES)) { ++ for (int i = 0; i < 10; ++i) { ++ float f = level.random.nextFloat() * 6.2831855F; ++ ++ this.spawnX = blockposition.getX() + Mth.floor(Mth.cos(f) * 32.0F); ++ this.spawnY = blockposition.getY(); ++ this.spawnZ = blockposition.getZ() + Mth.floor(Mth.sin(f) * 32.0F); + if (this.findRandomSpawnPos(level, new BlockPos(this.spawnX, this.spawnY, this.spawnZ)) != null) { + this.nextSpawnTime = 0; + this.zombiesToSpawn = 20; +@@ -93,40 +108,44 @@ + } + + private void trySpawn(ServerLevel level) { +- Vec3 vec3 = this.findRandomSpawnPos(level, new BlockPos(this.spawnX, this.spawnY, this.spawnZ)); +- if (vec3 != null) { +- Zombie zombie; ++ Vec3 vec3d = this.findRandomSpawnPos(level, new BlockPos(this.spawnX, this.spawnY, this.spawnZ)); ++ ++ if (vec3d != null) { ++ Zombie entityzombie; ++ + try { +- zombie = new Zombie(level); +- zombie.finalizeSpawn(level, level.getCurrentDifficultyAt(zombie.blockPosition()), MobSpawnType.EVENT, null, null); +- } catch (Exception var5) { +- LOGGER.warn("Failed to create zombie for village siege at {}", vec3, var5); ++ entityzombie = new Zombie(level); ++ entityzombie.finalizeSpawn(level, level.getCurrentDifficultyAt(entityzombie.blockPosition()), EnumMobSpawn.EVENT, (GroupDataEntity) null, (CompoundTag) null); ++ } catch (Exception exception) { ++ VillageSiege.LOGGER.warn("Failed to create zombie for village siege at {}", vec3d, exception); + return; + } + +- zombie.moveTo(vec3.x, vec3.y, vec3.z, level.random.nextFloat() * 360.0F, 0.0F); +- level.addFreshEntityWithPassengers(zombie); ++ entityzombie.moveTo(vec3d.x, vec3d.y, vec3d.z, level.random.nextFloat() * 360.0F, 0.0F); ++ level.addFreshEntityWithPassengers(entityzombie, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_INVASION); // CraftBukkit + } + } + + @Nullable + private Vec3 findRandomSpawnPos(ServerLevel level, BlockPos pos) { +- for (int i = 0; i < 10; i++) { +- int i1 = pos.getX() + level.random.nextInt(16) - 8; +- int i2 = pos.getZ() + level.random.nextInt(16) - 8; +- int height = level.getHeight(Heightmap.Types.WORLD_SURFACE, i1, i2); +- BlockPos blockPos = new BlockPos(i1, height, i2); +- if (level.isVillage(blockPos) && Monster.checkMonsterSpawnRules(EntityType.ZOMBIE, level, MobSpawnType.EVENT, blockPos, level.random)) { +- return Vec3.atBottomCenterOf(blockPos); ++ for (int i = 0; i < 10; ++i) { ++ int j = pos.getX() + level.random.nextInt(16) - 8; ++ int k = pos.getZ() + level.random.nextInt(16) - 8; ++ int l = level.getHeight(Heightmap.Types.WORLD_SURFACE, j, k); ++ BlockPos blockposition1 = new BlockPos(j, l, k); ++ ++ if (level.isVillage(blockposition1) && Monster.checkMonsterSpawnRules(EntityType.ZOMBIE, level, EnumMobSpawn.EVENT, blockposition1, level.random)) { ++ return Vec3.atBottomCenterOf(blockposition1); + } + } + + return null; + } + +- static enum State { +- SIEGE_CAN_ACTIVATE, +- SIEGE_TONIGHT, +- SIEGE_DONE; ++ private static enum State { ++ ++ SIEGE_CAN_ACTIVATE, SIEGE_TONIGHT, SIEGE_DONE; ++ ++ private State() {} + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/ambient/Bat.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/ambient/Bat.java.patch new file mode 100644 index 0000000000..0132ee9d78 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/ambient/Bat.java.patch @@ -0,0 +1,275 @@ +--- a/net/minecraft/world/entity/ambient/Bat.java ++++ b/net/minecraft/world/entity/ambient/Bat.java +@@ -16,24 +16,29 @@ + import net.minecraft.world.entity.AnimationState; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.targeting.TargetingConditions; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class Bat extends AmbientCreature { ++ + public static final float FLAP_LENGTH_SECONDS = 0.5F; + public static final float TICKS_PER_FLAP = 10.0F; + private static final EntityDataAccessor DATA_ID_FLAGS = SynchedEntityData.defineId(Bat.class, EntityDataSerializers.BYTE); + private static final int FLAG_RESTING = 1; +- private static final TargetingConditions BAT_RESTING_TARGETING = TargetingConditions.forNonCombat().range(4.0); ++ private static final TargetingConditions BAT_RESTING_TARGETING = TargetingConditions.forNonCombat().range(4.0D); + public final AnimationState flyAnimationState = new AnimationState(); + public final AnimationState restAnimationState = new AnimationState(); + @Nullable +@@ -44,17 +49,18 @@ + if (!level.isClientSide) { + this.setResting(true); + } ++ + } + + @Override + public boolean isFlapping() { +- return !this.isResting() && (float)this.tickCount % 10.0F == 0.0F; ++ return !this.isResting() && (float) this.tickCount % 10.0F == 0.0F; + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_ID_FLAGS, (byte)0); ++ this.entityData.define(Bat.DATA_ID_FLAGS, (byte) 0); + } + + @Override +@@ -89,28 +95,28 @@ + } + + @Override +- protected void doPush(Entity entity) { +- } ++ protected void doPush(Entity entity) {} + + @Override +- protected void pushEntities() { +- } ++ protected void pushEntities() {} + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 6.0); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 6.0D); + } + + public boolean isResting() { +- return (this.entityData.get(DATA_ID_FLAGS) & 1) != 0; ++ return ((Byte) this.entityData.get(Bat.DATA_ID_FLAGS) & 1) != 0; + } + + public void setResting(boolean isResting) { +- byte b = this.entityData.get(DATA_ID_FLAGS); ++ byte b0 = (Byte) this.entityData.get(Bat.DATA_ID_FLAGS); ++ + if (isResting) { +- this.entityData.set(DATA_ID_FLAGS, (byte)(b | 1)); ++ this.entityData.set(Bat.DATA_ID_FLAGS, (byte) (b0 | 1)); + } else { +- this.entityData.set(DATA_ID_FLAGS, (byte)(b & -2)); ++ this.entityData.set(Bat.DATA_ID_FLAGS, (byte) (b0 & -2)); + } ++ + } + + @Override +@@ -118,9 +124,9 @@ + super.tick(); + if (this.isResting()) { + this.setDeltaMovement(Vec3.ZERO); +- this.setPosRaw(this.getX(), (double)Mth.floor(this.getY()) + 1.0 - (double)this.getBbHeight(), this.getZ()); ++ this.setPosRaw(this.getX(), (double) Mth.floor(this.getY()) + 1.0D - (double) this.getBbHeight(), this.getZ()); + } else { +- this.setDeltaMovement(this.getDeltaMovement().multiply(1.0, 0.6, 1.0)); ++ this.setDeltaMovement(this.getDeltaMovement().multiply(1.0D, 0.6D, 1.0D)); + } + + this.setupAnimationStates(); +@@ -129,59 +135,55 @@ + @Override + protected void customServerAiStep() { + super.customServerAiStep(); +- BlockPos blockPos = this.blockPosition(); +- BlockPos blockPos1 = blockPos.above(); ++ BlockPos blockposition = this.blockPosition(); ++ BlockPos blockposition1 = blockposition.above(); ++ + if (this.isResting()) { +- boolean isSilent = this.isSilent(); +- if (this.level().getBlockState(blockPos1).isRedstoneConductor(this.level(), blockPos)) { ++ boolean flag = this.isSilent(); ++ ++ if (this.level().getBlockState(blockposition1).isRedstoneConductor(this.level(), blockposition)) { + if (this.random.nextInt(200) == 0) { +- this.yHeadRot = (float)this.random.nextInt(360); ++ this.yHeadRot = (float) this.random.nextInt(360); + } + +- if (this.level().getNearestPlayer(BAT_RESTING_TARGETING, this) != null) { ++ if (this.level().getNearestPlayer(Bat.BAT_RESTING_TARGETING, this) != null && CraftEventFactory.handleBatToggleSleepEvent(this, true)) { // CraftBukkit - Call BatToggleSleepEvent + this.setResting(false); +- if (!isSilent) { +- this.level().levelEvent(null, 1025, blockPos, 0); ++ if (!flag) { ++ this.level().levelEvent((Player) null, 1025, blockposition, 0); + } + } +- } else { ++ } else if (CraftEventFactory.handleBatToggleSleepEvent(this, true)) { // CraftBukkit - Call BatToggleSleepEvent + this.setResting(false); +- if (!isSilent) { +- this.level().levelEvent(null, 1025, blockPos, 0); ++ if (!flag) { ++ this.level().levelEvent((Player) null, 1025, blockposition, 0); + } + } + } else { +- if (this.targetPosition != null +- && (!this.level().isEmptyBlock(this.targetPosition) || this.targetPosition.getY() <= this.level().getMinBuildHeight())) { ++ if (this.targetPosition != null && (!this.level().isEmptyBlock(this.targetPosition) || this.targetPosition.getY() <= this.level().getMinBuildHeight())) { + this.targetPosition = null; + } + +- if (this.targetPosition == null || this.random.nextInt(30) == 0 || this.targetPosition.closerToCenterThan(this.position(), 2.0)) { +- this.targetPosition = BlockPos.containing( +- this.getX() + (double)this.random.nextInt(7) - (double)this.random.nextInt(7), +- this.getY() + (double)this.random.nextInt(6) - 2.0, +- this.getZ() + (double)this.random.nextInt(7) - (double)this.random.nextInt(7) +- ); ++ if (this.targetPosition == null || this.random.nextInt(30) == 0 || this.targetPosition.closerToCenterThan(this.position(), 2.0D)) { ++ this.targetPosition = BlockPos.containing(this.getX() + (double) this.random.nextInt(7) - (double) this.random.nextInt(7), this.getY() + (double) this.random.nextInt(6) - 2.0D, this.getZ() + (double) this.random.nextInt(7) - (double) this.random.nextInt(7)); + } + +- double d = (double)this.targetPosition.getX() + 0.5 - this.getX(); +- double d1 = (double)this.targetPosition.getY() + 0.1 - this.getY(); +- double d2 = (double)this.targetPosition.getZ() + 0.5 - this.getZ(); +- Vec3 deltaMovement = this.getDeltaMovement(); +- Vec3 vec3 = deltaMovement.add( +- (Math.signum(d) * 0.5 - deltaMovement.x) * 0.1F, +- (Math.signum(d1) * 0.7F - deltaMovement.y) * 0.1F, +- (Math.signum(d2) * 0.5 - deltaMovement.z) * 0.1F +- ); +- this.setDeltaMovement(vec3); +- float f = (float)(Mth.atan2(vec3.z, vec3.x) * 180.0F / (float)Math.PI) - 90.0F; ++ double d0 = (double) this.targetPosition.getX() + 0.5D - this.getX(); ++ double d1 = (double) this.targetPosition.getY() + 0.1D - this.getY(); ++ double d2 = (double) this.targetPosition.getZ() + 0.5D - this.getZ(); ++ Vec3 vec3d = this.getDeltaMovement(); ++ Vec3 vec3d1 = vec3d.add((Math.signum(d0) * 0.5D - vec3d.x) * 0.10000000149011612D, (Math.signum(d1) * 0.699999988079071D - vec3d.y) * 0.10000000149011612D, (Math.signum(d2) * 0.5D - vec3d.z) * 0.10000000149011612D); ++ ++ this.setDeltaMovement(vec3d1); ++ float f = (float) (Mth.atan2(vec3d1.z, vec3d1.x) * 57.2957763671875D) - 90.0F; + float f1 = Mth.wrapDegrees(f - this.getYRot()); ++ + this.zza = 0.5F; + this.setYRot(this.getYRot() + f1); +- if (this.random.nextInt(100) == 0 && this.level().getBlockState(blockPos1).isRedstoneConductor(this.level(), blockPos1)) { ++ if (this.random.nextInt(100) == 0 && this.level().getBlockState(blockposition1).isRedstoneConductor(this.level(), blockposition1) && CraftEventFactory.handleBatToggleSleepEvent(this, false)) { // CraftBukkit - Call BatToggleSleepEvent + this.setResting(true); + } + } ++ + } + + @Override +@@ -190,8 +192,7 @@ + } + + @Override +- protected void checkFallDamage(double y, boolean onGround, BlockState state, BlockPos pos) { +- } ++ protected void checkFallDamage(double y, boolean flag, IBlockData onGround, BlockPos state) {} + + @Override + public boolean isIgnoringBlockTriggers() { +@@ -203,7 +204,7 @@ + if (this.isInvulnerableTo(source)) { + return false; + } else { +- if (!this.level().isClientSide && this.isResting()) { ++ if (!this.level().isClientSide && this.isResting() && CraftEventFactory.handleBatToggleSleepEvent(this, true)) { // CraftBukkit - Call BatToggleSleepEvent + this.setResting(false); + } + +@@ -214,40 +215,42 @@ + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); +- this.entityData.set(DATA_ID_FLAGS, compound.getByte("BatFlags")); ++ this.entityData.set(Bat.DATA_ID_FLAGS, compound.getByte("BatFlags")); + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- compound.putByte("BatFlags", this.entityData.get(DATA_ID_FLAGS)); ++ compound.putByte("BatFlags", (Byte) this.entityData.get(Bat.DATA_ID_FLAGS)); + } + +- public static boolean checkBatSpawnRules(EntityType bat, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) { ++ public static boolean checkBatSpawnRules(EntityType bat, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { + if (pos.getY() >= level.getSeaLevel()) { + return false; + } else { +- int maxLocalRawBrightness = level.getMaxLocalRawBrightness(pos); +- int i = 4; ++ int i = level.getMaxLocalRawBrightness(pos); ++ byte b0 = 4; ++ + if (isHalloween()) { +- i = 7; ++ b0 = 7; + } else if (random.nextBoolean()) { + return false; + } + +- return maxLocalRawBrightness <= random.nextInt(i) && checkMobSpawnRules(bat, level, spawnType, pos, random); ++ return i > random.nextInt(b0) ? false : checkMobSpawnRules(bat, level, spawnType, pos, random); + } + } + + private static boolean isHalloween() { +- LocalDate localDate = LocalDate.now(); +- int i = localDate.get(ChronoField.DAY_OF_MONTH); +- int i1 = localDate.get(ChronoField.MONTH_OF_YEAR); +- return i1 == 10 && i >= 20 || i1 == 11 && i <= 3; ++ LocalDate localdate = LocalDate.now(); ++ int i = localdate.get(ChronoField.DAY_OF_MONTH); ++ int j = localdate.get(ChronoField.MONTH_OF_YEAR); ++ ++ return j == 10 && i >= 20 || j == 11 && i <= 3; + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return size.height / 2.0F; + } + +@@ -259,5 +262,6 @@ + this.restAnimationState.stop(); + this.flyAnimationState.startIfStopped(this.tickCount); + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Animal.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Animal.java.patch new file mode 100644 index 0000000000..92d0f6be99 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Animal.java.patch @@ -0,0 +1,269 @@ +--- a/net/minecraft/world/entity/animal/Animal.java ++++ b/net/minecraft/world/entity/animal/Animal.java +@@ -12,13 +12,13 @@ + import net.minecraft.stats.Stats; + import net.minecraft.tags.BlockTags; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.ExperienceOrb; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +@@ -29,12 +29,19 @@ + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.pathfinder.BlockPathTypes; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityBreedEvent; ++import org.bukkit.event.entity.EntityEnterLoveModeEvent; ++// CraftBukkit end + + public abstract class Animal extends AgeableMob { ++ + protected static final int PARENT_AGE_AFTER_BREEDING = 6000; +- private int inLove; ++ public int inLove; + @Nullable +- private UUID loveCause; ++ public UUID loveCause; ++ public ItemStack breedItem; // CraftBukkit - Add breedItem variable + + protected Animal(EntityType entityType, Level level) { + super(entityType, level); +@@ -59,14 +66,16 @@ + } + + if (this.inLove > 0) { +- this.inLove--; ++ --this.inLove; + if (this.inLove % 10 == 0) { +- double d = this.random.nextGaussian() * 0.02; +- double d1 = this.random.nextGaussian() * 0.02; +- double d2 = this.random.nextGaussian() * 0.02; +- this.level().addParticle(ParticleTypes.HEART, this.getRandomX(1.0), this.getRandomY() + 0.5, this.getRandomZ(1.0), d, d1, d2); ++ double d0 = this.random.nextGaussian() * 0.02D; ++ double d1 = this.random.nextGaussian() * 0.02D; ++ double d2 = this.random.nextGaussian() * 0.02D; ++ ++ this.level().addParticle(ParticleTypes.HEART, this.getRandomX(1.0D), this.getRandomY() + 0.5D, this.getRandomZ(1.0D), d0, d1, d2); + } + } ++ + } + + @Override +@@ -74,8 +83,13 @@ + if (this.isInvulnerableTo(source)) { + return false; + } else { ++ // CraftBukkit start ++ boolean result = super.hurt(source, amount); ++ if (result) { + this.inLove = 0; +- return super.hurt(source, amount); ++ } ++ return result; ++ // CraftBukkit end + } + } + +@@ -91,6 +105,7 @@ + if (this.loveCause != null) { + compound.putUUID("LoveCause", this.loveCause); + } ++ + } + + @Override +@@ -100,10 +115,9 @@ + this.loveCause = compound.hasUUID("LoveCause") ? compound.getUUID("LoveCause") : null; + } + +- public static boolean checkAnimalSpawnRules( +- EntityType animal, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random +- ) { +- boolean flag = MobSpawnType.ignoresLightRequirements(spawnType) || isBrightEnoughToSpawn(level, pos); ++ public static boolean checkAnimalSpawnRules(EntityType animal, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ boolean flag = EnumMobSpawn.ignoresLightRequirements(spawnType) || isBrightEnoughToSpawn(level, pos); ++ + return level.getBlockState(pos.below()).is(BlockTags.ANIMALS_SPAWNABLE_ON) && flag; + } + +@@ -131,19 +145,21 @@ + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (this.isFood(itemInHand)) { +- int age = this.getAge(); +- if (!this.level().isClientSide && age == 0 && this.canFallInLove()) { +- this.usePlayerItem(player, hand, itemInHand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (this.isFood(itemstack)) { ++ int i = this.getAge(); ++ ++ if (!this.level().isClientSide && i == 0 && this.canFallInLove()) { ++ this.usePlayerItem(player, hand, itemstack); + this.setInLove(player); + return InteractionResult.SUCCESS; + } + + if (this.isBaby()) { +- this.usePlayerItem(player, hand, itemInHand); +- this.ageUp(getSpeedUpSecondsWhenFeeding(-age), true); ++ this.usePlayerItem(player, hand, itemstack); ++ this.ageUp(getSpeedUpSecondsWhenFeeding(-i), true); + return InteractionResult.sidedSuccess(this.level().isClientSide); + } + +@@ -155,10 +171,11 @@ + return super.mobInteract(player, hand); + } + +- protected void usePlayerItem(Player player, InteractionHand hand, ItemStack stack) { ++ protected void usePlayerItem(Player player, EnumHand hand, ItemStack stack) { + if (!player.getAbilities().instabuild) { + stack.shrink(1); + } ++ + } + + public boolean canFallInLove() { +@@ -166,12 +183,19 @@ + } + + public void setInLove(@Nullable Player player) { +- this.inLove = 600; ++ // CraftBukkit start ++ EntityEnterLoveModeEvent entityEnterLoveModeEvent = CraftEventFactory.callEntityEnterLoveModeEvent(player, this, 600); ++ if (entityEnterLoveModeEvent.isCancelled()) { ++ return; ++ } ++ this.inLove = entityEnterLoveModeEvent.getTicksInLove(); ++ // CraftBukkit end + if (player != null) { + this.loveCause = player.getUUID(); + } ++ this.breedItem = player.getInventory().getSelected(); // CraftBukkit + +- this.level().broadcastEntityEvent(this, (byte)18); ++ this.level().broadcastEntityEvent(this, (byte) 18); + } + + public void setInLoveTime(int inLove) { +@@ -187,8 +211,9 @@ + if (this.loveCause == null) { + return null; + } else { +- Player playerByUUID = this.level().getPlayerByUUID(this.loveCause); +- return playerByUUID instanceof ServerPlayer ? (ServerPlayer)playerByUUID : null; ++ Player entityhuman = this.level().getPlayerByUUID(this.loveCause); ++ ++ return entityhuman instanceof ServerPlayer ? (ServerPlayer) entityhuman : null; + } + } + +@@ -201,45 +226,72 @@ + } + + public boolean canMate(Animal otherAnimal) { +- return otherAnimal != this && otherAnimal.getClass() == this.getClass() && this.isInLove() && otherAnimal.isInLove(); ++ return otherAnimal == this ? false : (otherAnimal.getClass() != this.getClass() ? false : this.isInLove() && otherAnimal.isInLove()); + } + + public void spawnChildFromBreeding(ServerLevel level, Animal mate) { +- AgeableMob breedOffspring = this.getBreedOffspring(level, mate); +- if (breedOffspring != null) { +- breedOffspring.setBaby(true); +- breedOffspring.moveTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F); +- this.finalizeSpawnChildFromBreeding(level, mate, breedOffspring); +- level.addFreshEntityWithPassengers(breedOffspring); ++ AgeableMob entityageable = this.getBreedOffspring(level, mate); ++ ++ if (entityageable != null) { ++ entityageable.setBaby(true); ++ entityageable.moveTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F); ++ // CraftBukkit start - call EntityBreedEvent ++ ServerPlayer breeder = Optional.ofNullable(this.getLoveCause()).or(() -> { ++ return Optional.ofNullable(mate.getLoveCause()); ++ }).orElse(null); ++ int experience = this.getRandom().nextInt(7) + 1; ++ EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(entityageable, this, mate, breeder, this.breedItem, experience); ++ if (entityBreedEvent.isCancelled()) { ++ return; ++ } ++ experience = entityBreedEvent.getExperience(); ++ this.finalizeSpawnChildFromBreeding(level, mate, entityageable, experience); ++ level.addFreshEntityWithPassengers(entityageable, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); ++ // CraftBukkit end + } + } + + public void finalizeSpawnChildFromBreeding(ServerLevel level, Animal animal, @Nullable AgeableMob baby) { +- Optional.ofNullable(this.getLoveCause()).or(() -> Optional.ofNullable(animal.getLoveCause())).ifPresent(player -> { +- player.awardStat(Stats.ANIMALS_BRED); +- CriteriaTriggers.BRED_ANIMALS.trigger(player, this, animal, baby); ++ // CraftBukkit start ++ this.finalizeSpawnChildFromBreeding(level, animal, baby, this.getRandom().nextInt(7) + 1); ++ } ++ ++ public void finalizeSpawnChildFromBreeding(ServerLevel worldserver, Animal entityanimal, @Nullable AgeableMob entityageable, int experience) { ++ // CraftBukkit end ++ Optional.ofNullable(this.getLoveCause()).or(() -> { ++ return Optional.ofNullable(entityanimal.getLoveCause()); ++ }).ifPresent((entityplayer) -> { ++ entityplayer.awardStat(Stats.ANIMALS_BRED); ++ CriteriaTriggers.BRED_ANIMALS.trigger(entityplayer, this, entityanimal, entityageable); + }); + this.setAge(6000); +- animal.setAge(6000); ++ entityanimal.setAge(6000); + this.resetLove(); +- animal.resetLove(); +- level.broadcastEntityEvent(this, (byte)18); +- if (level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +- level.addFreshEntity(new ExperienceOrb(level, this.getX(), this.getY(), this.getZ(), this.getRandom().nextInt(7) + 1)); ++ entityanimal.resetLove(); ++ worldserver.broadcastEntityEvent(this, (byte) 18); ++ if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { ++ // CraftBukkit start - use event experience ++ if (experience > 0) { ++ worldserver.addFreshEntity(new ExperienceOrb(worldserver, this.getX(), this.getY(), this.getZ(), experience)); ++ } ++ // CraftBukkit end + } ++ + } + + @Override + public void handleEntityEvent(byte id) { + if (id == 18) { +- for (int i = 0; i < 7; i++) { +- double d = this.random.nextGaussian() * 0.02; +- double d1 = this.random.nextGaussian() * 0.02; +- double d2 = this.random.nextGaussian() * 0.02; +- this.level().addParticle(ParticleTypes.HEART, this.getRandomX(1.0), this.getRandomY() + 0.5, this.getRandomZ(1.0), d, d1, d2); ++ for (int i = 0; i < 7; ++i) { ++ double d0 = this.random.nextGaussian() * 0.02D; ++ double d1 = this.random.nextGaussian() * 0.02D; ++ double d2 = this.random.nextGaussian() * 0.02D; ++ ++ this.level().addParticle(ParticleTypes.HEART, this.getRandomX(1.0D), this.getRandomY() + 0.5D, this.getRandomZ(1.0D), d0, d1, d2); + } + } else { + super.handleEntityEvent(id); + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Bee.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Bee.java.patch new file mode 100644 index 0000000000..aeb2d13642 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Bee.java.patch @@ -0,0 +1,1484 @@ +--- a/net/minecraft/world/entity/animal/Bee.java ++++ b/net/minecraft/world/entity/animal/Bee.java +@@ -3,7 +3,9 @@ + import com.google.common.collect.Lists; + import java.util.Comparator; + import java.util.EnumSet; ++import java.util.Iterator; + import java.util.List; ++import java.util.Objects; + import java.util.Optional; + import java.util.UUID; + import java.util.function.Predicate; +@@ -11,7 +13,6 @@ + import java.util.stream.Stream; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +-import net.minecraft.core.Holder; + import net.minecraft.core.particles.ParticleOptions; + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.nbt.CompoundTag; +@@ -38,13 +39,13 @@ + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobType; + import net.minecraft.world.entity.NeutralMob; + import net.minecraft.world.entity.PathfinderMob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.FlyingMoveControl; +@@ -81,15 +82,21 @@ + import net.minecraft.world.level.block.entity.BeehiveBlockEntity; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BlockEntityType; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.block.state.properties.BlockPropertyDoubleBlockHalf; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; +-import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.level.pathfinder.Path; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityPotionEffectEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end + +-public class Bee extends Animal implements NeutralMob, FlyingAnimal { ++public class Bee extends Animal implements NeutralMob, EntityBird { ++ + public static final float FLAP_DEGREES_PER_TICK = 120.32113F; + public static final int TICKS_PER_FLAP = Mth.ceil(1.4959966F); + private static final EntityDataAccessor DATA_FLAGS_ID = SynchedEntityData.defineId(Bee.class, EntityDataSerializers.BYTE); +@@ -122,16 +129,16 @@ + private float rollAmountO; + private int timeSinceSting; + int ticksWithoutNectarSinceExitingHive; +- private int stayOutOfHiveCountdown; ++ public int stayOutOfHiveCountdown; + private int numCropsGrownSincePollination; + private static final int COOLDOWN_BEFORE_LOCATING_NEW_HIVE = 200; + int remainingCooldownBeforeLocatingNewHive; + private static final int COOLDOWN_BEFORE_LOCATING_NEW_FLOWER = 200; +- int remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(this.random, 20, 60); ++ int remainingCooldownBeforeLocatingNewFlower; + @Nullable + BlockPos savedFlowerPos; + @Nullable +- BlockPos hivePos; ++ public BlockPos hivePos; + Bee.BeePollinateGoal beePollinateGoal; + Bee.BeeGoToHiveGoal goToHiveGoal; + private Bee.BeeGoToKnownFlowerGoal goToKnownFlowerGoal; +@@ -139,6 +146,7 @@ + + public Bee(EntityType entityType, Level level) { + super(entityType, level); ++ this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(this.random, 20, 60); + this.moveControl = new FlyingMoveControl(this, 20, true); + this.lookControl = new Bee.BeeLookControl(this); + this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F); +@@ -151,8 +159,8 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_FLAGS_ID, (byte)0); +- this.entityData.define(DATA_REMAINING_ANGER_TIME, 0); ++ this.entityData.define(Bee.DATA_FLAGS_ID, (byte) 0); ++ this.entityData.define(Bee.DATA_REMAINING_ANGER_TIME, 0); + } + + @Override +@@ -162,13 +170,13 @@ + + @Override + protected void registerGoals() { +- this.goalSelector.addGoal(0, new Bee.BeeAttackGoal(this, 1.4F, true)); ++ this.goalSelector.addGoal(0, new Bee.BeeAttackGoal(this, 1.399999976158142D, true)); + this.goalSelector.addGoal(1, new Bee.BeeEnterHiveGoal()); +- this.goalSelector.addGoal(2, new BreedGoal(this, 1.0)); +- this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, Ingredient.of(ItemTags.FLOWERS), false)); ++ this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); ++ this.goalSelector.addGoal(3, new TemptGoal(this, 1.25D, Ingredient.of(ItemTags.FLOWERS), false)); + this.beePollinateGoal = new Bee.BeePollinateGoal(); + this.goalSelector.addGoal(4, this.beePollinateGoal); +- this.goalSelector.addGoal(5, new FollowParentGoal(this, 1.25)); ++ this.goalSelector.addGoal(5, new FollowParentGoal(this, 1.25D)); + this.goalSelector.addGoal(5, new Bee.BeeLocateHiveGoal()); + this.goToHiveGoal = new Bee.BeeGoToHiveGoal(); + this.goalSelector.addGoal(5, this.goToHiveGoal); +@@ -177,28 +185,35 @@ + this.goalSelector.addGoal(7, new Bee.BeeGrowCropGoal()); + this.goalSelector.addGoal(8, new Bee.BeeWanderGoal()); + this.goalSelector.addGoal(9, new FloatGoal(this)); +- this.targetSelector.addGoal(1, new Bee.BeeHurtByOtherGoal(this).setAlertOthers(new Class[0])); ++ this.targetSelector.addGoal(1, (new Bee.BeeHurtByOtherGoal(this)).setAlertOthers(new Class[0])); + this.targetSelector.addGoal(2, new Bee.BeeBecomeAngryTargetGoal(this)); + this.targetSelector.addGoal(3, new ResetUniversalAngerTargetGoal<>(this, true)); + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { +- super.addAdditionalSaveData(compound); +- if (this.hasHive()) { +- compound.put("HivePos", NbtUtils.writeBlockPos(this.getHivePos())); ++ // CraftBukkit start - selectively save data ++ addAdditionalSaveData(compound, true); ++ } ++ ++ @Override ++ public void addAdditionalSaveData(CompoundTag nbttagcompound, boolean includeAll) { ++ // CraftBukkit end ++ super.addAdditionalSaveData(nbttagcompound); ++ if (includeAll && this.hasHive()) { // CraftBukkit - selectively save hive ++ nbttagcompound.put("HivePos", NbtUtils.writeBlockPos(this.getHivePos())); + } + +- if (this.hasSavedFlowerPos()) { +- compound.put("FlowerPos", NbtUtils.writeBlockPos(this.getSavedFlowerPos())); ++ if (includeAll && this.hasSavedFlowerPos()) { // CraftBukkit - selectively save flower ++ nbttagcompound.put("FlowerPos", NbtUtils.writeBlockPos(this.getSavedFlowerPos())); + } + +- compound.putBoolean("HasNectar", this.hasNectar()); +- compound.putBoolean("HasStung", this.hasStung()); +- compound.putInt("TicksSincePollination", this.ticksWithoutNectarSinceExitingHive); +- compound.putInt("CannotEnterHiveTicks", this.stayOutOfHiveCountdown); +- compound.putInt("CropsGrownSincePollination", this.numCropsGrownSincePollination); +- this.addPersistentAngerSaveData(compound); ++ nbttagcompound.putBoolean("HasNectar", this.hasNectar()); ++ nbttagcompound.putBoolean("HasStung", this.hasStung()); ++ nbttagcompound.putInt("TicksSincePollination", this.ticksWithoutNectarSinceExitingHive); ++ nbttagcompound.putInt("CannotEnterHiveTicks", this.stayOutOfHiveCountdown); ++ nbttagcompound.putInt("CropsGrownSincePollination", this.numCropsGrownSincePollination); ++ this.addPersistentAngerSaveData(nbttagcompound); + } + + @Override +@@ -224,20 +239,22 @@ + + @Override + public boolean doHurtTarget(Entity entity) { +- boolean flag = entity.hurt(this.damageSources().sting(this), (float)((int)this.getAttributeValue(Attributes.ATTACK_DAMAGE))); ++ boolean flag = entity.hurt(this.damageSources().sting(this), (float) ((int) this.getAttributeValue(Attributes.ATTACK_DAMAGE))); ++ + if (flag) { + this.doEnchantDamageEffects(this, entity); + if (entity instanceof LivingEntity) { +- ((LivingEntity)entity).setStingerCount(((LivingEntity)entity).getStingerCount() + 1); +- int i = 0; ++ ((LivingEntity) entity).setStingerCount(((LivingEntity) entity).getStingerCount() + 1); ++ byte b0 = 0; ++ + if (this.level().getDifficulty() == Difficulty.NORMAL) { +- i = 10; ++ b0 = 10; + } else if (this.level().getDifficulty() == Difficulty.HARD) { +- i = 18; ++ b0 = 18; + } + +- if (i > 0) { +- ((LivingEntity)entity).addEffect(new MobEffectInstance(MobEffects.POISON, i * 20, 0), this); ++ if (b0 > 0) { ++ ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.POISON, b0 * 20, 0), this, EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + +@@ -253,45 +270,44 @@ + public void tick() { + super.tick(); + if (this.hasNectar() && this.getCropsGrownSincePollination() < 10 && this.random.nextFloat() < 0.05F) { +- for (int i = 0; i < this.random.nextInt(2) + 1; i++) { +- this.spawnFluidParticle( +- this.level(), this.getX() - 0.3F, this.getX() + 0.3F, this.getZ() - 0.3F, this.getZ() + 0.3F, this.getY(0.5), ParticleTypes.FALLING_NECTAR +- ); ++ for (int i = 0; i < this.random.nextInt(2) + 1; ++i) { ++ this.spawnFluidParticle(this.level(), this.getX() - 0.30000001192092896D, this.getX() + 0.30000001192092896D, this.getZ() - 0.30000001192092896D, this.getZ() + 0.30000001192092896D, this.getY(0.5D), ParticleTypes.FALLING_NECTAR); + } + } + + this.updateRollAmount(); + } + +- private void spawnFluidParticle(Level level, double startX, double endX, double startZ, double endZ, double posY, ParticleOptions particleOption) { +- level.addParticle( +- particleOption, Mth.lerp(level.random.nextDouble(), startX, endX), posY, Mth.lerp(level.random.nextDouble(), startZ, endZ), 0.0, 0.0, 0.0 +- ); ++ private void spawnFluidParticle(Level level, double startX, double d1, double endX, double d3, double startZ, ParticleOptions particleparam) { ++ level.addParticle(particleparam, Mth.lerp(level.random.nextDouble(), startX, d1), startZ, Mth.lerp(level.random.nextDouble(), endX, d3), 0.0D, 0.0D, 0.0D); + } + + void pathfindRandomlyTowards(BlockPos pos) { +- Vec3 vec3 = Vec3.atBottomCenterOf(pos); +- int i = 0; +- BlockPos blockPos = this.blockPosition(); +- int i1 = (int)vec3.y - blockPos.getY(); +- if (i1 > 2) { +- i = 4; +- } else if (i1 < -2) { +- i = -4; ++ Vec3 vec3d = Vec3.atBottomCenterOf(pos); ++ byte b0 = 0; ++ BlockPos blockposition1 = this.blockPosition(); ++ int i = (int) vec3d.y - blockposition1.getY(); ++ ++ if (i > 2) { ++ b0 = 4; ++ } else if (i < -2) { ++ b0 = -4; + } + +- int i2 = 6; +- int i3 = 8; +- int i4 = blockPos.distManhattan(pos); +- if (i4 < 15) { +- i2 = i4 / 2; +- i3 = i4 / 2; ++ int j = 6; ++ int k = 8; ++ int l = blockposition1.distManhattan(pos); ++ ++ if (l < 15) { ++ j = l / 2; ++ k = l / 2; + } + +- Vec3 posTowards = AirRandomPos.getPosTowards(this, i2, i3, i, vec3, (float) (Math.PI / 10)); +- if (posTowards != null) { ++ Vec3 vec3d1 = AirRandomPos.getPosTowards(this, j, k, b0, vec3d, 0.3141592741012573D); ++ ++ if (vec3d1 != null) { + this.navigation.setMaxVisitedNodesMultiplier(0.5F); +- this.navigation.moveTo(posTowards.x, posTowards.y, posTowards.z, 1.0); ++ this.navigation.moveTo(vec3d1.x, vec3d1.y, vec3d1.z, 1.0D); + } + } + +@@ -325,6 +341,7 @@ + boolean wantsToEnterHive() { + if (this.stayOutOfHiveCountdown <= 0 && !this.beePollinateGoal.isPollinating() && !this.hasStung() && this.getTarget() == null) { + boolean flag = this.isTiredOfLookingForNectar() || this.level().isRaining() || this.level().isNight() || this.hasNectar(); ++ + return flag && !this.isHiveNearFire(); + } else { + return false; +@@ -346,13 +363,15 @@ + } else { + this.rollAmount = Math.max(0.0F, this.rollAmount - 0.24F); + } ++ + } + + @Override + protected void customServerAiStep() { +- boolean hasStung = this.hasStung(); ++ boolean flag = this.hasStung(); ++ + if (this.isInWaterOrBubble()) { +- this.underWaterTicks++; ++ ++this.underWaterTicks; + } else { + this.underWaterTicks = 0; + } +@@ -361,20 +380,21 @@ + this.hurt(this.damageSources().drown(), 1.0F); + } + +- if (hasStung) { +- this.timeSinceSting++; ++ if (flag) { ++ ++this.timeSinceSting; + if (this.timeSinceSting % 5 == 0 && this.random.nextInt(Mth.clamp(1200 - this.timeSinceSting, 1, 1200)) == 0) { + this.hurt(this.damageSources().generic(), this.getHealth()); + } + } + + if (!this.hasNectar()) { +- this.ticksWithoutNectarSinceExitingHive++; ++ ++this.ticksWithoutNectarSinceExitingHive; + } + + if (!this.level().isClientSide) { +- this.updatePersistentAnger((ServerLevel)this.level(), false); ++ this.updatePersistentAnger((ServerLevel) this.level(), false); + } ++ + } + + public void resetTicksWithoutNectarSinceExitingHive() { +@@ -385,19 +405,20 @@ + if (this.hivePos == null) { + return false; + } else { +- BlockEntity blockEntity = this.level().getBlockEntity(this.hivePos); +- return blockEntity instanceof BeehiveBlockEntity && ((BeehiveBlockEntity)blockEntity).isFireNearby(); ++ BlockEntity tileentity = this.level().getBlockEntity(this.hivePos); ++ ++ return tileentity instanceof BeehiveBlockEntity && ((BeehiveBlockEntity) tileentity).isFireNearby(); + } + } + + @Override + public int getRemainingPersistentAngerTime() { +- return this.entityData.get(DATA_REMAINING_ANGER_TIME); ++ return (Integer) this.entityData.get(Bee.DATA_REMAINING_ANGER_TIME); + } + + @Override + public void setRemainingPersistentAngerTime(int time) { +- this.entityData.set(DATA_REMAINING_ANGER_TIME, time); ++ this.entityData.set(Bee.DATA_REMAINING_ANGER_TIME, time); + } + + @Nullable +@@ -413,12 +434,13 @@ + + @Override + public void startPersistentAngerTimer() { +- this.setRemainingPersistentAngerTime(PERSISTENT_ANGER_TIME.sample(this.random)); ++ this.setRemainingPersistentAngerTime(Bee.PERSISTENT_ANGER_TIME.sample(this.random)); + } + + private boolean doesHiveHaveSpace(BlockPos hivePos) { +- BlockEntity blockEntity = this.level().getBlockEntity(hivePos); +- return blockEntity instanceof BeehiveBlockEntity && !((BeehiveBlockEntity)blockEntity).isFull(); ++ BlockEntity tileentity = this.level().getBlockEntity(hivePos); ++ ++ return tileentity instanceof BeehiveBlockEntity ? !((BeehiveBlockEntity) tileentity).isFull() : false; + } + + @VisibleForDebug +@@ -452,7 +474,7 @@ + } + + void incrementNumCropsGrownSincePollination() { +- this.numCropsGrownSincePollination++; ++ ++this.numCropsGrownSincePollination; + } + + @Override +@@ -460,23 +482,25 @@ + super.aiStep(); + if (!this.level().isClientSide) { + if (this.stayOutOfHiveCountdown > 0) { +- this.stayOutOfHiveCountdown--; ++ --this.stayOutOfHiveCountdown; + } + + if (this.remainingCooldownBeforeLocatingNewHive > 0) { +- this.remainingCooldownBeforeLocatingNewHive--; ++ --this.remainingCooldownBeforeLocatingNewHive; + } + + if (this.remainingCooldownBeforeLocatingNewFlower > 0) { +- this.remainingCooldownBeforeLocatingNewFlower--; ++ --this.remainingCooldownBeforeLocatingNewFlower; + } + +- boolean flag = this.isAngry() && !this.hasStung() && this.getTarget() != null && this.getTarget().distanceToSqr(this) < 4.0; ++ boolean flag = this.isAngry() && !this.hasStung() && this.getTarget() != null && this.getTarget().distanceToSqr((Entity) this) < 4.0D; ++ + this.setRolling(flag); + if (this.tickCount % 20 == 0 && !this.isHiveValid()) { + this.hivePos = null; + } + } ++ + } + + boolean isHiveValid() { +@@ -485,8 +509,9 @@ + } else if (this.isTooFarAway(this.hivePos)) { + return false; + } else { +- BlockEntity blockEntity = this.level().getBlockEntity(this.hivePos); +- return blockEntity != null && blockEntity.getType() == BlockEntityType.BEEHIVE; ++ BlockEntity tileentity = this.level().getBlockEntity(this.hivePos); ++ ++ return tileentity != null && tileentity.getType() == BlockEntityType.BEEHIVE; + } + } + +@@ -494,7 +519,7 @@ + return this.getFlag(8); + } + +- void setHasNectar(boolean hasNectar) { ++ public void setHasNectar(boolean hasNectar) { + if (hasNectar) { + this.resetTicksWithoutNectarSinceExitingHive(); + } +@@ -506,7 +531,7 @@ + return this.getFlag(4); + } + +- private void setHasStung(boolean hasStung) { ++ public void setHasStung(boolean hasStung) { + this.setFlag(4, hasStung); + } + +@@ -524,28 +549,24 @@ + + private void setFlag(int flagId, boolean value) { + if (value) { +- this.entityData.set(DATA_FLAGS_ID, (byte)(this.entityData.get(DATA_FLAGS_ID) | flagId)); ++ this.entityData.set(Bee.DATA_FLAGS_ID, (byte) ((Byte) this.entityData.get(Bee.DATA_FLAGS_ID) | flagId)); + } else { +- this.entityData.set(DATA_FLAGS_ID, (byte)(this.entityData.get(DATA_FLAGS_ID) & ~flagId)); ++ this.entityData.set(Bee.DATA_FLAGS_ID, (byte) ((Byte) this.entityData.get(Bee.DATA_FLAGS_ID) & ~flagId)); + } ++ + } + + private boolean getFlag(int flagId) { +- return (this.entityData.get(DATA_FLAGS_ID) & flagId) != 0; ++ return ((Byte) this.entityData.get(Bee.DATA_FLAGS_ID) & flagId) != 0; + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes() +- .add(Attributes.MAX_HEALTH, 10.0) +- .add(Attributes.FLYING_SPEED, 0.6F) +- .add(Attributes.MOVEMENT_SPEED, 0.3F) +- .add(Attributes.ATTACK_DAMAGE, 2.0) +- .add(Attributes.FOLLOW_RANGE, 48.0); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.FLYING_SPEED, 0.6000000238418579D).add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D).add(Attributes.ATTACK_DAMAGE, 2.0D).add(Attributes.FOLLOW_RANGE, 48.0D); + } + + @Override + protected PathNavigation createNavigation(Level level) { +- FlyingPathNavigation flyingPathNavigation = new FlyingPathNavigation(this, level) { ++ FlyingPathNavigation navigationflying = new FlyingPathNavigation(this, level) { + @Override + public boolean isStableDestination(BlockPos pos) { + return !this.level.getBlockState(pos.below()).isAir(); +@@ -558,10 +579,11 @@ + } + } + }; +- flyingPathNavigation.setCanOpenDoors(false); +- flyingPathNavigation.setCanFloat(false); +- flyingPathNavigation.setCanPassDoors(true); +- return flyingPathNavigation; ++ ++ navigationflying.setCanOpenDoors(false); ++ navigationflying.setCanFloat(false); ++ navigationflying.setCanPassDoors(true); ++ return navigationflying; + } + + @Override +@@ -574,8 +596,7 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { +- } ++ protected void playStepSound(BlockPos pos, IBlockData block) {} + + @Override + protected SoundEvent getAmbientSound() { +@@ -600,21 +621,20 @@ + @Nullable + @Override + public Bee getBreedOffspring(ServerLevel level, AgeableMob otherParent) { +- return EntityType.BEE.create(level); ++ return (Bee) EntityType.BEE.create(level); + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return this.isBaby() ? size.height * 0.5F : size.height * 0.5F; + } + + @Override +- protected void checkFallDamage(double y, boolean onGround, BlockState state, BlockPos pos) { +- } ++ protected void checkFallDamage(double y, boolean flag, IBlockData onGround, BlockPos state) {} + + @Override + public boolean isFlapping() { +- return this.isFlying() && this.tickCount % TICKS_PER_FLAP == 0; ++ return this.isFlying() && this.tickCount % Bee.TICKS_PER_FLAP == 0; + } + + @Override +@@ -632,104 +652,278 @@ + if (this.isInvulnerableTo(source)) { + return false; + } else { +- if (!this.level().isClientSide) { ++ // CraftBukkit start - Only stop pollinating if entity was damaged ++ boolean result = super.hurt(source, amount); ++ if (result && !this.level().isClientSide) { ++ // CraftBukkit end + this.beePollinateGoal.stopPollinating(); + } + +- return super.hurt(source, amount); ++ return result; // CraftBukkit + } + } + + @Override +- public MobType getMobType() { +- return MobType.ARTHROPOD; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.ARTHROPOD; + } + + @Override + protected void jumpInLiquid(TagKey fluidTag) { +- this.setDeltaMovement(this.getDeltaMovement().add(0.0, 0.01, 0.0)); ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, 0.01D, 0.0D)); + } + + @Override + public Vec3 getLeashOffset() { +- return new Vec3(0.0, (double)(0.5F * this.getEyeHeight()), (double)(this.getBbWidth() * 0.2F)); ++ return new Vec3(0.0D, (double) (0.5F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.2F)); + } + + boolean closerThan(BlockPos pos, int distance) { +- return pos.closerThan(this.blockPosition(), (double)distance); ++ return pos.closerThan(this.blockPosition(), (double) distance); + } + +- abstract class BaseBeeGoal extends Goal { +- public abstract boolean canBeeUse(); ++ private class BeePollinateGoal extends Bee.BaseBeeGoal { + +- public abstract boolean canBeeContinueToUse(); ++ private static final int MIN_POLLINATION_TICKS = 400; ++ private static final int MIN_FIND_FLOWER_RETRY_COOLDOWN = 20; ++ private static final int MAX_FIND_FLOWER_RETRY_COOLDOWN = 60; ++ private final Predicate VALID_POLLINATION_BLOCKS = (iblockdata) -> { ++ return iblockdata.hasProperty(BlockStateProperties.WATERLOGGED) && (Boolean) iblockdata.getValue(BlockStateProperties.WATERLOGGED) ? false : (iblockdata.is(BlockTags.FLOWERS) ? (iblockdata.is(Blocks.SUNFLOWER) ? iblockdata.getValue(DoublePlantBlock.HALF) == BlockPropertyDoubleBlockHalf.UPPER : true) : false); ++ }; ++ private static final double ARRIVAL_THRESHOLD = 0.1D; ++ private static final int POSITION_CHANGE_CHANCE = 25; ++ private static final float SPEED_MODIFIER = 0.35F; ++ private static final float HOVER_HEIGHT_WITHIN_FLOWER = 0.6F; ++ private static final float HOVER_POS_OFFSET = 0.33333334F; ++ private int successfulPollinatingTicks; ++ private int lastSoundPlayedTick; ++ private boolean pollinating; ++ @Nullable ++ private Vec3 hoverPos; ++ private int pollinatingTicks; ++ private static final int MAX_POLLINATING_TICKS = 600; + ++ BeePollinateGoal() { ++ super(); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); ++ } ++ + @Override +- public boolean canUse() { +- return this.canBeeUse() && !Bee.this.isAngry(); ++ public boolean canBeeUse() { ++ if (Bee.this.remainingCooldownBeforeLocatingNewFlower > 0) { ++ return false; ++ } else if (Bee.this.hasNectar()) { ++ return false; ++ } else if (Bee.this.level().isRaining()) { ++ return false; ++ } else { ++ Optional optional = this.findNearbyFlower(); ++ ++ if (optional.isPresent()) { ++ Bee.this.savedFlowerPos = (BlockPos) optional.get(); ++ Bee.this.navigation.moveTo((double) Bee.this.savedFlowerPos.getX() + 0.5D, (double) Bee.this.savedFlowerPos.getY() + 0.5D, (double) Bee.this.savedFlowerPos.getZ() + 0.5D, 1.2000000476837158D); ++ return true; ++ } else { ++ Bee.this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(Bee.this.random, 20, 60); ++ return false; ++ } ++ } + } + + @Override +- public boolean canContinueToUse() { +- return this.canBeeContinueToUse() && !Bee.this.isAngry(); ++ public boolean canBeeContinueToUse() { ++ if (!this.pollinating) { ++ return false; ++ } else if (!Bee.this.hasSavedFlowerPos()) { ++ return false; ++ } else if (Bee.this.level().isRaining()) { ++ return false; ++ } else if (this.hasPollinatedLongEnough()) { ++ return Bee.this.random.nextFloat() < 0.2F; ++ } else if (Bee.this.tickCount % 20 == 0 && !Bee.this.isFlowerValid(Bee.this.savedFlowerPos)) { ++ Bee.this.savedFlowerPos = null; ++ return false; ++ } else { ++ return true; ++ } + } ++ ++ private boolean hasPollinatedLongEnough() { ++ return this.successfulPollinatingTicks > 400; ++ } ++ ++ boolean isPollinating() { ++ return this.pollinating; ++ } ++ ++ void stopPollinating() { ++ this.pollinating = false; ++ } ++ ++ @Override ++ public void start() { ++ this.successfulPollinatingTicks = 0; ++ this.pollinatingTicks = 0; ++ this.lastSoundPlayedTick = 0; ++ this.pollinating = true; ++ Bee.this.resetTicksWithoutNectarSinceExitingHive(); ++ } ++ ++ @Override ++ public void stop() { ++ if (this.hasPollinatedLongEnough()) { ++ Bee.this.setHasNectar(true); ++ } ++ ++ this.pollinating = false; ++ Bee.this.navigation.stop(); ++ Bee.this.remainingCooldownBeforeLocatingNewFlower = 200; ++ } ++ ++ @Override ++ public boolean requiresUpdateEveryTick() { ++ return true; ++ } ++ ++ @Override ++ public void tick() { ++ ++this.pollinatingTicks; ++ if (this.pollinatingTicks > 600) { ++ Bee.this.savedFlowerPos = null; ++ } else { ++ Vec3 vec3d = Vec3.atBottomCenterOf(Bee.this.savedFlowerPos).add(0.0D, 0.6000000238418579D, 0.0D); ++ ++ if (vec3d.distanceTo(Bee.this.position()) > 1.0D) { ++ this.hoverPos = vec3d; ++ this.setWantedPos(); ++ } else { ++ if (this.hoverPos == null) { ++ this.hoverPos = vec3d; ++ } ++ ++ boolean flag = Bee.this.position().distanceTo(this.hoverPos) <= 0.1D; ++ boolean flag1 = true; ++ ++ if (!flag && this.pollinatingTicks > 600) { ++ Bee.this.savedFlowerPos = null; ++ } else { ++ if (flag) { ++ boolean flag2 = Bee.this.random.nextInt(25) == 0; ++ ++ if (flag2) { ++ this.hoverPos = new Vec3(vec3d.x() + (double) this.getOffset(), vec3d.y(), vec3d.z() + (double) this.getOffset()); ++ Bee.this.navigation.stop(); ++ } else { ++ flag1 = false; ++ } ++ ++ Bee.this.getLookControl().setLookAt(vec3d.x(), vec3d.y(), vec3d.z()); ++ } ++ ++ if (flag1) { ++ this.setWantedPos(); ++ } ++ ++ ++this.successfulPollinatingTicks; ++ if (Bee.this.random.nextFloat() < 0.05F && this.successfulPollinatingTicks > this.lastSoundPlayedTick + 60) { ++ this.lastSoundPlayedTick = this.successfulPollinatingTicks; ++ Bee.this.playSound(SoundEvents.BEE_POLLINATE, 1.0F, 1.0F); ++ } ++ ++ } ++ } ++ } ++ } ++ ++ private void setWantedPos() { ++ Bee.this.getMoveControl().setWantedPosition(this.hoverPos.x(), this.hoverPos.y(), this.hoverPos.z(), 0.3499999940395355D); ++ } ++ ++ private float getOffset() { ++ return (Bee.this.random.nextFloat() * 2.0F - 1.0F) * 0.33333334F; ++ } ++ ++ private Optional findNearbyFlower() { ++ return this.findNearestBlock(this.VALID_POLLINATION_BLOCKS, 5.0D); ++ } ++ ++ private Optional findNearestBlock(Predicate predicate, double distance) { ++ BlockPos blockposition = Bee.this.blockPosition(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ ++ for (int i = 0; (double) i <= distance; i = i > 0 ? -i : 1 - i) { ++ for (int j = 0; (double) j < distance; ++j) { ++ for (int k = 0; k <= j; k = k > 0 ? -k : 1 - k) { ++ for (int l = k < j && k > -j ? j : 0; l <= j; l = l > 0 ? -l : 1 - l) { ++ blockposition_mutableblockposition.setWithOffset(blockposition, k, i - 1, l); ++ if (blockposition.closerThan(blockposition_mutableblockposition, distance) && predicate.test(Bee.this.level().getBlockState(blockposition_mutableblockposition))) { ++ return Optional.of(blockposition_mutableblockposition); ++ } ++ } ++ } ++ } ++ } ++ ++ return Optional.empty(); ++ } + } + +- class BeeAttackGoal extends MeleeAttackGoal { +- BeeAttackGoal(PathfinderMob mob, double speedModifier, boolean followingTargetEvenIfNotSeen) { +- super(mob, speedModifier, followingTargetEvenIfNotSeen); ++ private class BeeLookControl extends LookControl { ++ ++ BeeLookControl(Mob mob) { ++ super(mob); + } + + @Override +- public boolean canUse() { +- return super.canUse() && Bee.this.isAngry() && !Bee.this.hasStung(); ++ public void tick() { ++ if (!Bee.this.isAngry()) { ++ super.tick(); ++ } + } + + @Override +- public boolean canContinueToUse() { +- return super.canContinueToUse() && Bee.this.isAngry() && !Bee.this.hasStung(); ++ protected boolean resetXRotOnTick() { ++ return !Bee.this.beePollinateGoal.isPollinating(); + } + } + +- static class BeeBecomeAngryTargetGoal extends NearestAttackableTargetGoal { +- BeeBecomeAngryTargetGoal(Bee mob) { +- super(mob, Player.class, 10, true, false, mob::isAngryAt); ++ private class BeeAttackGoal extends MeleeAttackGoal { ++ ++ BeeAttackGoal(PathfinderMob mob, double speedModifier, boolean flag) { ++ super(mob, speedModifier, flag); + } + + @Override + public boolean canUse() { +- return this.beeCanTarget() && super.canUse(); ++ return super.canUse() && Bee.this.isAngry() && !Bee.this.hasStung(); + } + + @Override + public boolean canContinueToUse() { +- boolean flag = this.beeCanTarget(); +- if (flag && this.mob.getTarget() != null) { +- return super.canContinueToUse(); +- } else { +- this.targetMob = null; +- return false; +- } ++ return super.canContinueToUse() && Bee.this.isAngry() && !Bee.this.hasStung(); + } ++ } + +- private boolean beeCanTarget() { +- Bee bee = (Bee)this.mob; +- return bee.isAngry() && !bee.hasStung(); ++ private class BeeEnterHiveGoal extends Bee.BaseBeeGoal { ++ ++ BeeEnterHiveGoal() { ++ super(); + } +- } + +- class BeeEnterHiveGoal extends Bee.BaseBeeGoal { + @Override + public boolean canBeeUse() { +- if (Bee.this.hasHive() +- && Bee.this.wantsToEnterHive() +- && Bee.this.hivePos.closerToCenterThan(Bee.this.position(), 2.0) +- && Bee.this.level().getBlockEntity(Bee.this.hivePos) instanceof BeehiveBlockEntity beehiveBlockEntity) { +- if (!beehiveBlockEntity.isFull()) { +- return true; +- } ++ if (Bee.this.hasHive() && Bee.this.wantsToEnterHive() && Bee.this.hivePos.closerToCenterThan(Bee.this.position(), 2.0D)) { ++ BlockEntity tileentity = Bee.this.level().getBlockEntity(Bee.this.hivePos); + +- Bee.this.hivePos = null; ++ if (tileentity instanceof BeehiveBlockEntity) { ++ BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) tileentity; ++ ++ if (!tileentitybeehive.isFull()) { ++ return true; ++ } ++ ++ Bee.this.hivePos = null; ++ } + } + + return false; +@@ -742,34 +936,92 @@ + + @Override + public void start() { +- if (Bee.this.level().getBlockEntity(Bee.this.hivePos) instanceof BeehiveBlockEntity beehiveBlockEntity) { +- beehiveBlockEntity.addOccupant(Bee.this, Bee.this.hasNectar()); ++ BlockEntity tileentity = Bee.this.level().getBlockEntity(Bee.this.hivePos); ++ ++ if (tileentity instanceof BeehiveBlockEntity) { ++ BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) tileentity; ++ ++ tileentitybeehive.addOccupant(Bee.this, Bee.this.hasNectar()); + } ++ + } + } + ++ private class BeeLocateHiveGoal extends Bee.BaseBeeGoal { ++ ++ BeeLocateHiveGoal() { ++ super(); ++ } ++ ++ @Override ++ public boolean canBeeUse() { ++ return Bee.this.remainingCooldownBeforeLocatingNewHive == 0 && !Bee.this.hasHive() && Bee.this.wantsToEnterHive(); ++ } ++ ++ @Override ++ public boolean canBeeContinueToUse() { ++ return false; ++ } ++ ++ @Override ++ public void start() { ++ Bee.this.remainingCooldownBeforeLocatingNewHive = 200; ++ List list = this.findNearbyHivesWithSpace(); ++ ++ if (!list.isEmpty()) { ++ Iterator iterator = list.iterator(); ++ ++ BlockPos blockposition; ++ ++ do { ++ if (!iterator.hasNext()) { ++ Bee.this.goToHiveGoal.clearBlacklist(); ++ Bee.this.hivePos = (BlockPos) list.get(0); ++ return; ++ } ++ ++ blockposition = (BlockPos) iterator.next(); ++ } while (Bee.this.goToHiveGoal.isTargetBlacklisted(blockposition)); ++ ++ Bee.this.hivePos = blockposition; ++ } ++ } ++ ++ private List findNearbyHivesWithSpace() { ++ BlockPos blockposition = Bee.this.blockPosition(); ++ PoiManager villageplace = ((ServerLevel) Bee.this.level()).getPoiManager(); ++ Stream stream = villageplace.getInRange((holder) -> { ++ return holder.is(PoiTypeTags.BEE_HOME); ++ }, blockposition, 20, PoiManager.Occupancy.ANY); ++ ++ return (List) stream.map(PoiRecord::getPos).filter(Bee.this::doesHiveHaveSpace).sorted(Comparator.comparingDouble((blockposition1) -> { ++ return blockposition1.distSqr(blockposition); ++ })).collect(Collectors.toList()); ++ } ++ } ++ + @VisibleForDebug + public class BeeGoToHiveGoal extends Bee.BaseBeeGoal { ++ + public static final int MAX_TRAVELLING_TICKS = 600; +- int travellingTicks = Bee.this.level().random.nextInt(10); ++ int travellingTicks; + private static final int MAX_BLACKLISTED_TARGETS = 3; +- final List blacklistedTargets = Lists.newArrayList(); ++ final List blacklistedTargets; + @Nullable + private Path lastPath; + private static final int TICKS_BEFORE_HIVE_DROP = 60; + private int ticksStuck; + + BeeGoToHiveGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ super(); ++ this.travellingTicks = Bee.this.random.nextInt(10); // CraftBukkit - SPIGOT-7495: Give Bees another chance and let them use their own random, avoid concurrency issues ++ this.blacklistedTargets = Lists.newArrayList(); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override + public boolean canBeeUse() { +- return Bee.this.hivePos != null +- && !Bee.this.hasRestriction() +- && Bee.this.wantsToEnterHive() +- && !this.hasReachedTarget(Bee.this.hivePos) +- && Bee.this.level().getBlockState(Bee.this.hivePos).is(BlockTags.BEEHIVES); ++ return Bee.this.hivePos != null && !Bee.this.hasRestriction() && Bee.this.wantsToEnterHive() && !this.hasReachedTarget(Bee.this.hivePos) && Bee.this.level().getBlockState(Bee.this.hivePos).is(BlockTags.BEEHIVES); + } + + @Override +@@ -795,7 +1047,7 @@ + @Override + public void tick() { + if (Bee.this.hivePos != null) { +- this.travellingTicks++; ++ ++this.travellingTicks; + if (this.travellingTicks > this.adjustedTickDelay(600)) { + this.dropAndBlacklistHive(); + } else if (!Bee.this.navigation.isInProgress()) { +@@ -807,10 +1059,11 @@ + } + } else { + boolean flag = this.pathfindDirectlyTowards(Bee.this.hivePos); ++ + if (!flag) { + this.dropAndBlacklistHive(); + } else if (this.lastPath != null && Bee.this.navigation.getPath().sameAs(this.lastPath)) { +- this.ticksStuck++; ++ ++this.ticksStuck; + if (this.ticksStuck > 60) { + this.dropHive(); + this.ticksStuck = 0; +@@ -818,6 +1071,7 @@ + } else { + this.lastPath = Bee.this.navigation.getPath(); + } ++ + } + } + } +@@ -825,7 +1079,7 @@ + + private boolean pathfindDirectlyTowards(BlockPos pos) { + Bee.this.navigation.setMaxVisitedNodesMultiplier(10.0F); +- Bee.this.navigation.moveTo((double)pos.getX(), (double)pos.getY(), (double)pos.getZ(), 1.0); ++ Bee.this.navigation.moveTo((double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), 1.0D); + return Bee.this.navigation.getPath() != null && Bee.this.navigation.getPath().canReach(); + } + +@@ -839,6 +1093,7 @@ + while (this.blacklistedTargets.size() > 3) { + this.blacklistedTargets.remove(0); + } ++ + } + + void clearBlacklist() { +@@ -862,27 +1117,27 @@ + if (Bee.this.closerThan(pos, 2)) { + return true; + } else { +- Path path = Bee.this.navigation.getPath(); +- return path != null && path.getTarget().equals(pos) && path.canReach() && path.isDone(); ++ Path pathentity = Bee.this.navigation.getPath(); ++ ++ return pathentity != null && pathentity.getTarget().equals(pos) && pathentity.canReach() && pathentity.isDone(); + } + } + } + + public class BeeGoToKnownFlowerGoal extends Bee.BaseBeeGoal { ++ + private static final int MAX_TRAVELLING_TICKS = 600; +- int travellingTicks = Bee.this.level().random.nextInt(10); ++ int travellingTicks; + + BeeGoToKnownFlowerGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ super(); ++ this.travellingTicks = Bee.this.random.nextInt(10); // CraftBukkit - SPIGOT-7495: Give Bees another chance and let them use their own random, avoid concurrency issues ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override + public boolean canBeeUse() { +- return Bee.this.savedFlowerPos != null +- && !Bee.this.hasRestriction() +- && this.wantsToGoToKnownFlower() +- && Bee.this.isFlowerValid(Bee.this.savedFlowerPos) +- && !Bee.this.closerThan(Bee.this.savedFlowerPos, 2); ++ return Bee.this.savedFlowerPos != null && !Bee.this.hasRestriction() && this.wantsToGoToKnownFlower() && Bee.this.isFlowerValid(Bee.this.savedFlowerPos) && !Bee.this.closerThan(Bee.this.savedFlowerPos, 2); + } + + @Override +@@ -906,7 +1161,7 @@ + @Override + public void tick() { + if (Bee.this.savedFlowerPos != null) { +- this.travellingTicks++; ++ ++this.travellingTicks; + if (this.travellingTicks > this.adjustedTickDelay(600)) { + Bee.this.savedFlowerPos = null; + } else if (!Bee.this.navigation.isInProgress()) { +@@ -924,12 +1179,17 @@ + } + } + +- class BeeGrowCropGoal extends Bee.BaseBeeGoal { ++ private class BeeGrowCropGoal extends Bee.BaseBeeGoal { ++ + static final int GROW_CHANCE = 30; + ++ BeeGrowCropGoal() { ++ super(); ++ } ++ + @Override + public boolean canBeeUse() { +- return Bee.this.getCropsGrownSincePollination() < 10 && !(Bee.this.random.nextFloat() < 0.3F) && Bee.this.hasNectar() && Bee.this.isHiveValid(); ++ return Bee.this.getCropsGrownSincePollination() >= 10 ? false : (Bee.this.random.nextFloat() < 0.3F ? false : Bee.this.hasNectar() && Bee.this.isHiveValid()); + } + + @Override +@@ -940,342 +1200,163 @@ + @Override + public void tick() { + if (Bee.this.random.nextInt(this.adjustedTickDelay(30)) == 0) { +- for (int i = 1; i <= 2; i++) { +- BlockPos blockPos = Bee.this.blockPosition().below(i); +- BlockState blockState = Bee.this.level().getBlockState(blockPos); +- Block block = blockState.getBlock(); +- BlockState blockState1 = null; +- if (blockState.is(BlockTags.BEE_GROWABLES)) { ++ for (int i = 1; i <= 2; ++i) { ++ BlockPos blockposition = Bee.this.blockPosition().below(i); ++ IBlockData iblockdata = Bee.this.level().getBlockState(blockposition); ++ Block block = iblockdata.getBlock(); ++ IBlockData iblockdata1 = null; ++ ++ if (iblockdata.is(BlockTags.BEE_GROWABLES)) { + if (block instanceof CropBlock) { +- CropBlock cropBlock = (CropBlock)block; +- if (!cropBlock.isMaxAge(blockState)) { +- blockState1 = cropBlock.getStateForAge(cropBlock.getAge(blockState) + 1); ++ CropBlock blockcrops = (CropBlock) block; ++ ++ if (!blockcrops.isMaxAge(iblockdata)) { ++ iblockdata1 = blockcrops.getStateForAge(blockcrops.getAge(iblockdata) + 1); + } +- } else if (block instanceof StemBlock) { +- int i1 = blockState.getValue(StemBlock.AGE); +- if (i1 < 7) { +- blockState1 = blockState.setValue(StemBlock.AGE, Integer.valueOf(i1 + 1)); ++ } else { ++ int j; ++ ++ if (block instanceof StemBlock) { ++ j = (Integer) iblockdata.getValue(StemBlock.AGE); ++ if (j < 7) { ++ iblockdata1 = (IBlockData) iblockdata.setValue(StemBlock.AGE, j + 1); ++ } ++ } else if (iblockdata.is(Blocks.SWEET_BERRY_BUSH)) { ++ j = (Integer) iblockdata.getValue(SweetBerryBushBlock.AGE); ++ if (j < 3) { ++ iblockdata1 = (IBlockData) iblockdata.setValue(SweetBerryBushBlock.AGE, j + 1); ++ } ++ } else if (iblockdata.is(Blocks.CAVE_VINES) || iblockdata.is(Blocks.CAVE_VINES_PLANT)) { ++ ((BonemealableBlock) iblockdata.getBlock()).performBonemeal((ServerLevel) Bee.this.level(), Bee.this.random, blockposition, iblockdata); + } +- } else if (blockState.is(Blocks.SWEET_BERRY_BUSH)) { +- int i1 = blockState.getValue(SweetBerryBushBlock.AGE); +- if (i1 < 3) { +- blockState1 = blockState.setValue(SweetBerryBushBlock.AGE, Integer.valueOf(i1 + 1)); +- } +- } else if (blockState.is(Blocks.CAVE_VINES) || blockState.is(Blocks.CAVE_VINES_PLANT)) { +- ((BonemealableBlock)blockState.getBlock()).performBonemeal((ServerLevel)Bee.this.level(), Bee.this.random, blockPos, blockState); + } + +- if (blockState1 != null) { +- Bee.this.level().levelEvent(2005, blockPos, 0); +- Bee.this.level().setBlockAndUpdate(blockPos, blockState1); ++ if (iblockdata1 != null && CraftEventFactory.callEntityChangeBlockEvent(Bee.this, blockposition, iblockdata1)) { // CraftBukkit ++ Bee.this.level().levelEvent(2005, blockposition, 0); ++ Bee.this.level().setBlockAndUpdate(blockposition, iblockdata1); + Bee.this.incrementNumCropsGrownSincePollination(); + } + } + } ++ + } + } + } + +- class BeeHurtByOtherGoal extends HurtByTargetGoal { +- BeeHurtByOtherGoal(Bee mob) { +- super(mob); +- } ++ private class BeeWanderGoal extends Goal { + +- @Override +- public boolean canContinueToUse() { +- return Bee.this.isAngry() && super.canContinueToUse(); +- } ++ private static final int WANDER_THRESHOLD = 22; + +- @Override +- protected void alertOther(Mob mob, LivingEntity target) { +- if (mob instanceof Bee && this.mob.hasLineOfSight(target)) { +- mob.setTarget(target); +- } ++ BeeWanderGoal() { ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } +- } + +- class BeeLocateHiveGoal extends Bee.BaseBeeGoal { + @Override +- public boolean canBeeUse() { +- return Bee.this.remainingCooldownBeforeLocatingNewHive == 0 && !Bee.this.hasHive() && Bee.this.wantsToEnterHive(); ++ public boolean canUse() { ++ return Bee.this.navigation.isDone() && Bee.this.random.nextInt(10) == 0; + } + + @Override +- public boolean canBeeContinueToUse() { +- return false; ++ public boolean canContinueToUse() { ++ return Bee.this.navigation.isInProgress(); + } + + @Override + public void start() { +- Bee.this.remainingCooldownBeforeLocatingNewHive = 200; +- List list = this.findNearbyHivesWithSpace(); +- if (!list.isEmpty()) { +- for (BlockPos blockPos : list) { +- if (!Bee.this.goToHiveGoal.isTargetBlacklisted(blockPos)) { +- Bee.this.hivePos = blockPos; +- return; +- } +- } ++ Vec3 vec3d = this.findPos(); + +- Bee.this.goToHiveGoal.clearBlacklist(); +- Bee.this.hivePos = list.get(0); ++ if (vec3d != null) { ++ Bee.this.navigation.moveTo(Bee.this.navigation.createPath(BlockPos.containing(vec3d), 1), 1.0D); + } +- } + +- private List findNearbyHivesWithSpace() { +- BlockPos blockPos = Bee.this.blockPosition(); +- PoiManager poiManager = ((ServerLevel)Bee.this.level()).getPoiManager(); +- Stream inRange = poiManager.getInRange(holder -> holder.is(PoiTypeTags.BEE_HOME), blockPos, 20, PoiManager.Occupancy.ANY); +- return inRange.map(PoiRecord::getPos) +- .filter(Bee.this::doesHiveHaveSpace) +- .sorted(Comparator.comparingDouble(pos -> pos.distSqr(blockPos))) +- .collect(Collectors.toList()); + } +- } + +- class BeeLookControl extends LookControl { +- BeeLookControl(Mob mob) { +- super(mob); +- } ++ @Nullable ++ private Vec3 findPos() { ++ Vec3 vec3d; + +- @Override +- public void tick() { +- if (!Bee.this.isAngry()) { +- super.tick(); ++ if (Bee.this.isHiveValid() && !Bee.this.closerThan(Bee.this.hivePos, 22)) { ++ Vec3 vec3d1 = Vec3.atCenterOf(Bee.this.hivePos); ++ ++ vec3d = vec3d1.subtract(Bee.this.position()).normalize(); ++ } else { ++ vec3d = Bee.this.getViewVector(0.0F); + } +- } + +- @Override +- protected boolean resetXRotOnTick() { +- return !Bee.this.beePollinateGoal.isPollinating(); ++ boolean flag = true; ++ Vec3 vec3d2 = HoverRandomPos.getPos(Bee.this, 8, 7, vec3d.x, vec3d.z, 1.5707964F, 3, 1); ++ ++ return vec3d2 != null ? vec3d2 : AirAndWaterRandomPos.getPos(Bee.this, 8, 4, -2, vec3d.x, vec3d.z, 1.5707963705062866D); + } + } + +- class BeePollinateGoal extends Bee.BaseBeeGoal { +- private static final int MIN_POLLINATION_TICKS = 400; +- private static final int MIN_FIND_FLOWER_RETRY_COOLDOWN = 20; +- private static final int MAX_FIND_FLOWER_RETRY_COOLDOWN = 60; +- private final Predicate VALID_POLLINATION_BLOCKS = state -> ( +- !state.hasProperty(BlockStateProperties.WATERLOGGED) || !state.getValue(BlockStateProperties.WATERLOGGED) +- ) +- && state.is(BlockTags.FLOWERS) +- && (!state.is(Blocks.SUNFLOWER) || state.getValue(DoublePlantBlock.HALF) == DoubleBlockHalf.UPPER); +- private static final double ARRIVAL_THRESHOLD = 0.1; +- private static final int POSITION_CHANGE_CHANCE = 25; +- private static final float SPEED_MODIFIER = 0.35F; +- private static final float HOVER_HEIGHT_WITHIN_FLOWER = 0.6F; +- private static final float HOVER_POS_OFFSET = 0.33333334F; +- private int successfulPollinatingTicks; +- private int lastSoundPlayedTick; +- private boolean pollinating; +- @Nullable +- private Vec3 hoverPos; +- private int pollinatingTicks; +- private static final int MAX_POLLINATING_TICKS = 600; ++ private class BeeHurtByOtherGoal extends HurtByTargetGoal { + +- BeePollinateGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ BeeHurtByOtherGoal(Bee entitybee) { ++ super(entitybee); + } + + @Override +- public boolean canBeeUse() { +- if (Bee.this.remainingCooldownBeforeLocatingNewFlower > 0) { +- return false; +- } else if (Bee.this.hasNectar()) { +- return false; +- } else if (Bee.this.level().isRaining()) { +- return false; +- } else { +- Optional optional = this.findNearbyFlower(); +- if (optional.isPresent()) { +- Bee.this.savedFlowerPos = optional.get(); +- Bee.this.navigation +- .moveTo( +- (double)Bee.this.savedFlowerPos.getX() + 0.5, +- (double)Bee.this.savedFlowerPos.getY() + 0.5, +- (double)Bee.this.savedFlowerPos.getZ() + 0.5, +- 1.2F +- ); +- return true; +- } else { +- Bee.this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(Bee.this.random, 20, 60); +- return false; +- } +- } ++ public boolean canContinueToUse() { ++ return Bee.this.isAngry() && super.canContinueToUse(); + } + + @Override +- public boolean canBeeContinueToUse() { +- if (!this.pollinating) { +- return false; +- } else if (!Bee.this.hasSavedFlowerPos()) { +- return false; +- } else if (Bee.this.level().isRaining()) { +- return false; +- } else if (this.hasPollinatedLongEnough()) { +- return Bee.this.random.nextFloat() < 0.2F; +- } else if (Bee.this.tickCount % 20 == 0 && !Bee.this.isFlowerValid(Bee.this.savedFlowerPos)) { +- Bee.this.savedFlowerPos = null; +- return false; +- } else { +- return true; ++ protected void alertOther(Mob mob, LivingEntity target) { ++ if (mob instanceof Bee && this.mob.hasLineOfSight(target)) { ++ mob.setTarget(target, EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY, true); // CraftBukkit - reason + } +- } + +- private boolean hasPollinatedLongEnough() { +- return this.successfulPollinatingTicks > 400; + } ++ } + +- boolean isPollinating() { +- return this.pollinating; +- } ++ private static class BeeBecomeAngryTargetGoal extends NearestAttackableTargetGoal { + +- void stopPollinating() { +- this.pollinating = false; ++ BeeBecomeAngryTargetGoal(Bee mob) { ++ // Objects.requireNonNull(entitybee); // CraftBukkit - decompile error ++ super(mob, Player.class, 10, true, false, mob::isAngryAt); + } + + @Override +- public void start() { +- this.successfulPollinatingTicks = 0; +- this.pollinatingTicks = 0; +- this.lastSoundPlayedTick = 0; +- this.pollinating = true; +- Bee.this.resetTicksWithoutNectarSinceExitingHive(); ++ public boolean canUse() { ++ return this.beeCanTarget() && super.canUse(); + } + + @Override +- public void stop() { +- if (this.hasPollinatedLongEnough()) { +- Bee.this.setHasNectar(true); +- } ++ public boolean canContinueToUse() { ++ boolean flag = this.beeCanTarget(); + +- this.pollinating = false; +- Bee.this.navigation.stop(); +- Bee.this.remainingCooldownBeforeLocatingNewFlower = 200; +- } +- +- @Override +- public boolean requiresUpdateEveryTick() { +- return true; +- } +- +- @Override +- public void tick() { +- this.pollinatingTicks++; +- if (this.pollinatingTicks > 600) { +- Bee.this.savedFlowerPos = null; ++ if (flag && this.mob.getTarget() != null) { ++ return super.canContinueToUse(); + } else { +- Vec3 vec3 = Vec3.atBottomCenterOf(Bee.this.savedFlowerPos).add(0.0, 0.6F, 0.0); +- if (vec3.distanceTo(Bee.this.position()) > 1.0) { +- this.hoverPos = vec3; +- this.setWantedPos(); +- } else { +- if (this.hoverPos == null) { +- this.hoverPos = vec3; +- } +- +- boolean flag = Bee.this.position().distanceTo(this.hoverPos) <= 0.1; +- boolean flag1 = true; +- if (!flag && this.pollinatingTicks > 600) { +- Bee.this.savedFlowerPos = null; +- } else { +- if (flag) { +- boolean flag2 = Bee.this.random.nextInt(25) == 0; +- if (flag2) { +- this.hoverPos = new Vec3(vec3.x() + (double)this.getOffset(), vec3.y(), vec3.z() + (double)this.getOffset()); +- Bee.this.navigation.stop(); +- } else { +- flag1 = false; +- } +- +- Bee.this.getLookControl().setLookAt(vec3.x(), vec3.y(), vec3.z()); +- } +- +- if (flag1) { +- this.setWantedPos(); +- } +- +- this.successfulPollinatingTicks++; +- if (Bee.this.random.nextFloat() < 0.05F && this.successfulPollinatingTicks > this.lastSoundPlayedTick + 60) { +- this.lastSoundPlayedTick = this.successfulPollinatingTicks; +- Bee.this.playSound(SoundEvents.BEE_POLLINATE, 1.0F, 1.0F); +- } +- } +- } ++ this.targetMob = null; ++ return false; + } + } + +- private void setWantedPos() { +- Bee.this.getMoveControl().setWantedPosition(this.hoverPos.x(), this.hoverPos.y(), this.hoverPos.z(), 0.35F); +- } ++ private boolean beeCanTarget() { ++ Bee entitybee = (Bee) this.mob; + +- private float getOffset() { +- return (Bee.this.random.nextFloat() * 2.0F - 1.0F) * 0.33333334F; ++ return entitybee.isAngry() && !entitybee.hasStung(); + } ++ } + +- private Optional findNearbyFlower() { +- return this.findNearestBlock(this.VALID_POLLINATION_BLOCKS, 5.0); +- } ++ private abstract class BaseBeeGoal extends Goal { + +- private Optional findNearestBlock(Predicate predicate, double distance) { +- BlockPos blockPos = Bee.this.blockPosition(); +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ BaseBeeGoal() {} + +- for (int i = 0; (double)i <= distance; i = i > 0 ? -i : 1 - i) { +- for (int i1 = 0; (double)i1 < distance; i1++) { +- for (int i2 = 0; i2 <= i1; i2 = i2 > 0 ? -i2 : 1 - i2) { +- for (int i3 = i2 < i1 && i2 > -i1 ? i1 : 0; i3 <= i1; i3 = i3 > 0 ? -i3 : 1 - i3) { +- mutableBlockPos.setWithOffset(blockPos, i2, i - 1, i3); +- if (blockPos.closerThan(mutableBlockPos, distance) && predicate.test(Bee.this.level().getBlockState(mutableBlockPos))) { +- return Optional.of(mutableBlockPos); +- } +- } +- } +- } +- } ++ public abstract boolean canBeeUse(); + +- return Optional.empty(); +- } +- } ++ public abstract boolean canBeeContinueToUse(); + +- class BeeWanderGoal extends Goal { +- private static final int WANDER_THRESHOLD = 22; +- +- BeeWanderGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); +- } +- + @Override + public boolean canUse() { +- return Bee.this.navigation.isDone() && Bee.this.random.nextInt(10) == 0; ++ return this.canBeeUse() && !Bee.this.isAngry(); + } + + @Override + public boolean canContinueToUse() { +- return Bee.this.navigation.isInProgress(); ++ return this.canBeeContinueToUse() && !Bee.this.isAngry(); + } +- +- @Override +- public void start() { +- Vec3 vec3 = this.findPos(); +- if (vec3 != null) { +- Bee.this.navigation.moveTo(Bee.this.navigation.createPath(BlockPos.containing(vec3), 1), 1.0); +- } +- } +- +- @Nullable +- private Vec3 findPos() { +- Vec3 vec31; +- if (Bee.this.isHiveValid() && !Bee.this.closerThan(Bee.this.hivePos, 22)) { +- Vec3 vec3 = Vec3.atCenterOf(Bee.this.hivePos); +- vec31 = vec3.subtract(Bee.this.position()).normalize(); +- } else { +- vec31 = Bee.this.getViewVector(0.0F); +- } +- +- int i = 8; +- Vec3 pos = HoverRandomPos.getPos(Bee.this, 8, 7, vec31.x, vec31.z, (float) (Math.PI / 2), 3, 1); +- return pos != null ? pos : AirAndWaterRandomPos.getPos(Bee.this, 8, 4, -2, vec31.x, vec31.z, (float) (Math.PI / 2)); +- } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Bucketable.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Bucketable.java.patch new file mode 100644 index 0000000000..45d0710924 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Bucketable.java.patch @@ -0,0 +1,128 @@ +--- a/net/minecraft/world/entity/animal/Bucketable.java ++++ b/net/minecraft/world/entity/animal/Bucketable.java +@@ -3,9 +3,10 @@ + import java.util.Optional; + import net.minecraft.advancements.CriteriaTriggers; + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +@@ -14,8 +15,13 @@ + import net.minecraft.world.item.ItemUtils; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerBucketEntityEvent; ++// CraftBukkit end + + public interface Bucketable { ++ + boolean fromBucket(); + + void setFromBucket(boolean fromBucket); +@@ -28,36 +34,39 @@ + + SoundEvent getPickupSound(); + ++ /** @deprecated */ + @Deprecated + static void saveDefaultDataToBucketTag(Mob mob, ItemStack bucket) { +- CompoundTag tag = bucket.getOrCreateTag(); ++ CompoundTag nbttagcompound = bucket.getOrCreateTag(); ++ + if (mob.hasCustomName()) { + bucket.setHoverName(mob.getCustomName()); + } + + if (mob.isNoAi()) { +- tag.putBoolean("NoAI", mob.isNoAi()); ++ nbttagcompound.putBoolean("NoAI", mob.isNoAi()); + } + + if (mob.isSilent()) { +- tag.putBoolean("Silent", mob.isSilent()); ++ nbttagcompound.putBoolean("Silent", mob.isSilent()); + } + + if (mob.isNoGravity()) { +- tag.putBoolean("NoGravity", mob.isNoGravity()); ++ nbttagcompound.putBoolean("NoGravity", mob.isNoGravity()); + } + + if (mob.hasGlowingTag()) { +- tag.putBoolean("Glowing", mob.hasGlowingTag()); ++ nbttagcompound.putBoolean("Glowing", mob.hasGlowingTag()); + } + + if (mob.isInvulnerable()) { +- tag.putBoolean("Invulnerable", mob.isInvulnerable()); ++ nbttagcompound.putBoolean("Invulnerable", mob.isInvulnerable()); + } + +- tag.putFloat("Health", mob.getHealth()); ++ nbttagcompound.putFloat("Health", mob.getHealth()); + } + ++ /** @deprecated */ + @Deprecated + static void loadDefaultDataFromBucketTag(Mob mob, CompoundTag tag) { + if (tag.contains("NoAI")) { +@@ -83,23 +92,40 @@ + if (tag.contains("Health", 99)) { + mob.setHealth(tag.getFloat("Health")); + } ++ + } + +- static Optional bucketMobPickup(Player player, InteractionHand hand, T entity) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (itemInHand.getItem() == Items.WATER_BUCKET && entity.isAlive()) { +- entity.playSound(entity.getPickupSound(), 1.0F, 1.0F); +- ItemStack bucketItemStack = entity.getBucketItemStack(); +- entity.saveToBucketTag(bucketItemStack); +- ItemStack itemStack = ItemUtils.createFilledResult(itemInHand, player, bucketItemStack, false); +- player.setItemInHand(hand, itemStack); +- Level level = entity.level(); +- if (!level.isClientSide) { +- CriteriaTriggers.FILLED_BUCKET.trigger((ServerPlayer)player, bucketItemStack); ++ static Optional bucketMobPickup(Player player, EnumHand hand, T entity) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (itemstack.getItem() == Items.WATER_BUCKET && entity.isAlive()) { ++ // CraftBukkit start ++ // t0.playSound(((Bucketable) t0).getPickupSound(), 1.0F, 1.0F); // CraftBukkit - moved down ++ ItemStack itemstack1 = ((Bucketable) entity).getBucketItemStack(); ++ ++ ((Bucketable) entity).saveToBucketTag(itemstack1); ++ ++ PlayerBucketEntityEvent playerBucketFishEvent = CraftEventFactory.callPlayerFishBucketEvent(entity, player, itemstack, itemstack1, hand); ++ itemstack1 = CraftItemStack.asNMSCopy(playerBucketFishEvent.getEntityBucket()); ++ if (playerBucketFishEvent.isCancelled()) { ++ ((ServerPlayer) player).containerMenu.sendAllDataToRemote(); // We need to update inventory to resync client's bucket ++ ((ServerPlayer) player).connection.send(new ClientboundAddEntityPacket(entity)); // We need to play out these packets as the client assumes the fish is gone ++ entity.getEntityData().refresh((ServerPlayer) player); // Need to send data such as the display name to client ++ return Optional.of(InteractionResult.FAIL); + } ++ entity.playSound(((Bucketable) entity).getPickupSound(), 1.0F, 1.0F); ++ // CraftBukkit end ++ ItemStack itemstack2 = ItemUtils.createFilledResult(itemstack, player, itemstack1, false); + ++ player.setItemInHand(hand, itemstack2); ++ Level world = entity.level(); ++ ++ if (!world.isClientSide) { ++ CriteriaTriggers.FILLED_BUCKET.trigger((ServerPlayer) player, itemstack1); ++ } ++ + entity.discard(); +- return Optional.of(InteractionResult.sidedSuccess(level.isClientSide)); ++ return Optional.of(InteractionResult.sidedSuccess(world.isClientSide)); + } else { + return Optional.empty(); + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Cat.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Cat.java.patch new file mode 100644 index 0000000000..9b89e0ff35 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Cat.java.patch @@ -0,0 +1,744 @@ +--- a/net/minecraft/world/entity/animal/Cat.java ++++ b/net/minecraft/world/entity/animal/Cat.java +@@ -1,10 +1,11 @@ + package net.minecraft.world.entity.animal; + ++import java.util.Iterator; ++import java.util.List; ++import java.util.Objects; ++import java.util.function.Predicate; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +-import net.minecraft.core.Direction; +-import net.minecraft.core.Holder; +-import net.minecraft.core.HolderSet; + import net.minecraft.core.registries.BuiltInRegistries; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.syncher.EntityDataAccessor; +@@ -21,19 +22,19 @@ + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.TamableAnimal; + import net.minecraft.world.entity.VariantHolder; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -64,7 +65,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.BedBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.storage.loot.BuiltInLootTables; + import net.minecraft.world.level.storage.loot.LootParams; + import net.minecraft.world.level.storage.loot.LootTable; +@@ -74,9 +75,10 @@ + import org.joml.Vector3f; + + public class Cat extends TamableAnimal implements VariantHolder { +- public static final double TEMPT_SPEED_MOD = 0.6; +- public static final double WALK_SPEED_MOD = 0.8; +- public static final double SPRINT_SPEED_MOD = 1.33; ++ ++ public static final double TEMPT_SPEED_MOD = 0.6D; ++ public static final double WALK_SPEED_MOD = 0.8D; ++ public static final double SPRINT_SPEED_MOD = 1.33D; + private static final Ingredient TEMPT_INGREDIENT = Ingredient.of(Items.COD, Items.SALMON); + private static final EntityDataAccessor DATA_VARIANT_ID = SynchedEntityData.defineId(Cat.class, EntityDataSerializers.CAT_VARIANT); + private static final EntityDataAccessor IS_LYING = SynchedEntityData.defineId(Cat.class, EntityDataSerializers.BOOLEAN); +@@ -102,119 +104,114 @@ + + @Override + protected void registerGoals() { +- this.temptGoal = new Cat.CatTemptGoal(this, 0.6, TEMPT_INGREDIENT, true); ++ this.temptGoal = new Cat.CatTemptGoal(this, 0.6D, Cat.TEMPT_INGREDIENT, true); + this.goalSelector.addGoal(1, new FloatGoal(this)); +- this.goalSelector.addGoal(1, new PanicGoal(this, 1.5)); ++ this.goalSelector.addGoal(1, new PanicGoal(this, 1.5D)); + this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this)); + this.goalSelector.addGoal(3, new Cat.CatRelaxOnOwnerGoal(this)); + this.goalSelector.addGoal(4, this.temptGoal); +- this.goalSelector.addGoal(5, new CatLieOnBedGoal(this, 1.1, 8)); +- this.goalSelector.addGoal(6, new FollowOwnerGoal(this, 1.0, 10.0F, 5.0F, false)); +- this.goalSelector.addGoal(7, new CatSitOnBlockGoal(this, 0.8)); ++ this.goalSelector.addGoal(5, new CatLieOnBedGoal(this, 1.1D, 8)); ++ this.goalSelector.addGoal(6, new FollowOwnerGoal(this, 1.0D, 10.0F, 5.0F, false)); ++ this.goalSelector.addGoal(7, new CatSitOnBlockGoal(this, 0.8D)); + this.goalSelector.addGoal(8, new LeapAtTargetGoal(this, 0.3F)); + this.goalSelector.addGoal(9, new OcelotAttackGoal(this)); +- this.goalSelector.addGoal(10, new BreedGoal(this, 0.8)); +- this.goalSelector.addGoal(11, new WaterAvoidingRandomStrollGoal(this, 0.8, 1.0000001E-5F)); ++ this.goalSelector.addGoal(10, new BreedGoal(this, 0.8D)); ++ this.goalSelector.addGoal(11, new WaterAvoidingRandomStrollGoal(this, 0.8D, 1.0000001E-5F)); + this.goalSelector.addGoal(12, new LookAtPlayerGoal(this, Player.class, 10.0F)); +- this.targetSelector.addGoal(1, new NonTameRandomTargetGoal<>(this, Rabbit.class, false, null)); ++ this.targetSelector.addGoal(1, new NonTameRandomTargetGoal<>(this, Rabbit.class, false, (Predicate) null)); + this.targetSelector.addGoal(1, new NonTameRandomTargetGoal<>(this, Turtle.class, false, Turtle.BABY_ON_LAND_SELECTOR)); + } + + @Override + public CatVariant getVariant() { +- return this.entityData.get(DATA_VARIANT_ID); ++ return (CatVariant) this.entityData.get(Cat.DATA_VARIANT_ID); + } + +- @Override + public void setVariant(CatVariant variant) { +- this.entityData.set(DATA_VARIANT_ID, variant); ++ this.entityData.set(Cat.DATA_VARIANT_ID, variant); + } + + public void setLying(boolean lying) { +- this.entityData.set(IS_LYING, lying); ++ this.entityData.set(Cat.IS_LYING, lying); + } + + public boolean isLying() { +- return this.entityData.get(IS_LYING); ++ return (Boolean) this.entityData.get(Cat.IS_LYING); + } + + public void setRelaxStateOne(boolean relaxStateOne) { +- this.entityData.set(RELAX_STATE_ONE, relaxStateOne); ++ this.entityData.set(Cat.RELAX_STATE_ONE, relaxStateOne); + } + + public boolean isRelaxStateOne() { +- return this.entityData.get(RELAX_STATE_ONE); ++ return (Boolean) this.entityData.get(Cat.RELAX_STATE_ONE); + } + + public DyeColor getCollarColor() { +- return DyeColor.byId(this.entityData.get(DATA_COLLAR_COLOR)); ++ return DyeColor.byId((Integer) this.entityData.get(Cat.DATA_COLLAR_COLOR)); + } + + public void setCollarColor(DyeColor color) { +- this.entityData.set(DATA_COLLAR_COLOR, color.getId()); ++ this.entityData.set(Cat.DATA_COLLAR_COLOR, color.getId()); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_VARIANT_ID, BuiltInRegistries.CAT_VARIANT.getOrThrow(CatVariant.BLACK)); +- this.entityData.define(IS_LYING, false); +- this.entityData.define(RELAX_STATE_ONE, false); +- this.entityData.define(DATA_COLLAR_COLOR, DyeColor.RED.getId()); ++ this.entityData.define(Cat.DATA_VARIANT_ID, (CatVariant) BuiltInRegistries.CAT_VARIANT.getOrThrow(CatVariant.BLACK)); ++ this.entityData.define(Cat.IS_LYING, false); ++ this.entityData.define(Cat.RELAX_STATE_ONE, false); ++ this.entityData.define(Cat.DATA_COLLAR_COLOR, DyeColor.RED.getId()); + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); + compound.putString("variant", BuiltInRegistries.CAT_VARIANT.getKey(this.getVariant()).toString()); +- compound.putByte("CollarColor", (byte)this.getCollarColor().getId()); ++ compound.putByte("CollarColor", (byte) this.getCollarColor().getId()); + } + + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); +- CatVariant catVariant = BuiltInRegistries.CAT_VARIANT.get(ResourceLocation.tryParse(compound.getString("variant"))); +- if (catVariant != null) { +- this.setVariant(catVariant); ++ CatVariant catvariant = (CatVariant) BuiltInRegistries.CAT_VARIANT.get(ResourceLocation.tryParse(compound.getString("variant"))); ++ ++ if (catvariant != null) { ++ this.setVariant(catvariant); + } + + if (compound.contains("CollarColor", 99)) { + this.setCollarColor(DyeColor.byId(compound.getInt("CollarColor"))); + } ++ + } + + @Override + public void customServerAiStep() { + if (this.getMoveControl().hasWanted()) { +- double speedModifier = this.getMoveControl().getSpeedModifier(); +- if (speedModifier == 0.6) { +- this.setPose(Pose.CROUCHING); ++ double d0 = this.getMoveControl().getSpeedModifier(); ++ ++ if (d0 == 0.6D) { ++ this.setPose(EntityPose.CROUCHING); + this.setSprinting(false); +- } else if (speedModifier == 1.33) { +- this.setPose(Pose.STANDING); ++ } else if (d0 == 1.33D) { ++ this.setPose(EntityPose.STANDING); + this.setSprinting(true); + } else { +- this.setPose(Pose.STANDING); ++ this.setPose(EntityPose.STANDING); + this.setSprinting(false); + } + } else { +- this.setPose(Pose.STANDING); ++ this.setPose(EntityPose.STANDING); + this.setSprinting(false); + } ++ + } + + @Nullable + @Override + protected SoundEvent getAmbientSound() { +- if (this.isTame()) { +- if (this.isInLove()) { +- return SoundEvents.CAT_PURR; +- } else { +- return this.random.nextInt(4) == 0 ? SoundEvents.CAT_PURREOW : SoundEvents.CAT_AMBIENT; +- } +- } else { +- return SoundEvents.CAT_STRAY_AMBIENT; +- } ++ return this.isTame() ? (this.isInLove() ? SoundEvents.CAT_PURR : (this.random.nextInt(4) == 0 ? SoundEvents.CAT_PURREOW : SoundEvents.CAT_AMBIENT)) : SoundEvents.CAT_STRAY_AMBIENT; + } + + @Override +@@ -237,11 +234,11 @@ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0).add(Attributes.MOVEMENT_SPEED, 0.3F).add(Attributes.ATTACK_DAMAGE, 3.0); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D).add(Attributes.ATTACK_DAMAGE, 3.0D); + } + + @Override +- protected void usePlayerItem(Player player, InteractionHand hand, ItemStack stack) { ++ protected void usePlayerItem(Player player, EnumHand hand, ItemStack stack) { + if (this.isFood(stack)) { + this.playSound(SoundEvents.CAT_EAT, 1.0F, 1.0F); + } +@@ -250,7 +247,7 @@ + } + + private float getAttackDamage() { +- return (float)this.getAttributeValue(Attributes.ATTACK_DAMAGE); ++ return (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE); + } + + @Override +@@ -287,6 +284,7 @@ + this.lieDownAmount = Math.max(0.0F, this.lieDownAmount - 0.22F); + this.lieDownAmountTail = Math.max(0.0F, this.lieDownAmountTail - 0.13F); + } ++ + } + + private void updateRelaxStateOneAmount() { +@@ -296,6 +294,7 @@ + } else { + this.relaxStateOneAmount = Math.max(0.0F, this.relaxStateOneAmount - 0.13F); + } ++ + } + + public float getLieDownAmount(float partialTicks) { +@@ -313,125 +312,135 @@ + @Nullable + @Override + public Cat getBreedOffspring(ServerLevel level, AgeableMob otherParent) { +- Cat cat = EntityType.CAT.create(level); +- if (cat != null && otherParent instanceof Cat cat1) { ++ Cat entitycat = (Cat) EntityType.CAT.create(level); ++ ++ if (entitycat != null && otherParent instanceof Cat) { ++ Cat entitycat1 = (Cat) otherParent; ++ + if (this.random.nextBoolean()) { +- cat.setVariant(this.getVariant()); ++ entitycat.setVariant(this.getVariant()); + } else { +- cat.setVariant(cat1.getVariant()); ++ entitycat.setVariant(entitycat1.getVariant()); + } + + if (this.isTame()) { +- cat.setOwnerUUID(this.getOwnerUUID()); +- cat.setTame(true); ++ entitycat.setOwnerUUID(this.getOwnerUUID()); ++ entitycat.setTame(true); + if (this.random.nextBoolean()) { +- cat.setCollarColor(this.getCollarColor()); ++ entitycat.setCollarColor(this.getCollarColor()); + } else { +- cat.setCollarColor(cat1.getCollarColor()); ++ entitycat.setCollarColor(entitycat1.getCollarColor()); + } + } + } + +- return cat; ++ return entitycat; + } + + @Override + public boolean canMate(Animal otherAnimal) { +- return this.isTame() && otherAnimal instanceof Cat cat && cat.isTame() && super.canMate(otherAnimal); ++ if (!this.isTame()) { ++ return false; ++ } else if (!(otherAnimal instanceof Cat)) { ++ return false; ++ } else { ++ Cat entitycat = (Cat) otherAnimal; ++ ++ return entitycat.isTame() && super.canMate(otherAnimal); ++ } + } + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- SpawnGroupData var9 = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ spawnData = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + boolean flag = level.getMoonBrightness() > 0.9F; +- TagKey tagKey = flag ? CatVariantTags.FULL_MOON_SPAWNS : CatVariantTags.DEFAULT_SPAWNS; +- BuiltInRegistries.CAT_VARIANT +- .getTag(tagKey) +- .flatMap(named -> named.getRandomElement(level.getRandom())) +- .ifPresent(holder -> this.setVariant(holder.value())); +- ServerLevel level1 = level.getLevel(); +- if (level1.structureManager().getStructureWithPieceAt(this.blockPosition(), StructureTags.CATS_SPAWN_AS_BLACK).isValid()) { +- this.setVariant(BuiltInRegistries.CAT_VARIANT.getOrThrow(CatVariant.ALL_BLACK)); ++ TagKey tagkey = flag ? CatVariantTags.FULL_MOON_SPAWNS : CatVariantTags.DEFAULT_SPAWNS; ++ ++ BuiltInRegistries.CAT_VARIANT.getTag(tagkey).flatMap((holderset_named) -> { ++ return holderset_named.getRandomElement(level.getRandom()); ++ }).ifPresent((holder) -> { ++ this.setVariant((CatVariant) holder.value()); ++ }); ++ ServerLevel worldserver = level.getLevel(); ++ ++ if (worldserver.structureManager().getStructureWithPieceAt(this.blockPosition(), StructureTags.CATS_SPAWN_AS_BLACK).isValid()) { ++ this.setVariant((CatVariant) BuiltInRegistries.CAT_VARIANT.getOrThrow(CatVariant.ALL_BLACK)); + this.setPersistenceRequired(); + } + +- return var9; ++ return spawnData; + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- Item item = itemInHand.getItem(); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ Item item = itemstack.getItem(); ++ + if (this.level().isClientSide) { +- if (this.isTame() && this.isOwnedBy(player)) { +- return InteractionResult.SUCCESS; +- } else { +- return !this.isFood(itemInHand) || !(this.getHealth() < this.getMaxHealth()) && this.isTame() +- ? InteractionResult.PASS +- : InteractionResult.SUCCESS; +- } ++ return this.isTame() && this.isOwnedBy(player) ? InteractionResult.SUCCESS : (this.isFood(itemstack) && (this.getHealth() < this.getMaxHealth() || !this.isTame()) ? InteractionResult.SUCCESS : InteractionResult.PASS); + } else { ++ InteractionResult enuminteractionresult; ++ + if (this.isTame()) { + if (this.isOwnedBy(player)) { + if (!(item instanceof DyeItem)) { +- if (item.isEdible() && this.isFood(itemInHand) && this.getHealth() < this.getMaxHealth()) { +- this.usePlayerItem(player, hand, itemInHand); +- this.heal((float)item.getFoodProperties().getNutrition()); ++ if (item.isEdible() && this.isFood(itemstack) && this.getHealth() < this.getMaxHealth()) { ++ this.usePlayerItem(player, hand, itemstack); ++ this.heal((float) item.getFoodProperties().getNutrition()); + return InteractionResult.CONSUME; + } + +- InteractionResult interactionResult = super.mobInteract(player, hand); +- if (!interactionResult.consumesAction() || this.isBaby()) { ++ enuminteractionresult = super.mobInteract(player, hand); ++ if (!enuminteractionresult.consumesAction() || this.isBaby()) { + this.setOrderedToSit(!this.isOrderedToSit()); + } + +- return interactionResult; ++ return enuminteractionresult; + } + +- DyeColor dyeColor = ((DyeItem)item).getDyeColor(); +- if (dyeColor != this.getCollarColor()) { +- this.setCollarColor(dyeColor); ++ DyeColor enumcolor = ((DyeItem) item).getDyeColor(); ++ ++ if (enumcolor != this.getCollarColor()) { ++ this.setCollarColor(enumcolor); + if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + + this.setPersistenceRequired(); + return InteractionResult.CONSUME; + } + } +- } else if (this.isFood(itemInHand)) { +- this.usePlayerItem(player, hand, itemInHand); +- if (this.random.nextInt(3) == 0) { ++ } else if (this.isFood(itemstack)) { ++ this.usePlayerItem(player, hand, itemstack); ++ if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit + this.tame(player); + this.setOrderedToSit(true); +- this.level().broadcastEntityEvent(this, (byte)7); ++ this.level().broadcastEntityEvent(this, (byte) 7); + } else { +- this.level().broadcastEntityEvent(this, (byte)6); ++ this.level().broadcastEntityEvent(this, (byte) 6); + } + + this.setPersistenceRequired(); + return InteractionResult.CONSUME; + } + +- InteractionResult interactionResult = super.mobInteract(player, hand); +- if (interactionResult.consumesAction()) { ++ enuminteractionresult = super.mobInteract(player, hand); ++ if (enuminteractionresult.consumesAction()) { + this.setPersistenceRequired(); + } + +- return interactionResult; ++ return enuminteractionresult; + } + } + + @Override + public boolean isFood(ItemStack stack) { +- return TEMPT_INGREDIENT.test(stack); ++ return Cat.TEMPT_INGREDIENT.test(stack); + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return size.height * 0.5F; + } + +@@ -443,13 +452,14 @@ + @Override + protected void reassessTameGoals() { + if (this.avoidPlayersGoal == null) { +- this.avoidPlayersGoal = new Cat.CatAvoidEntityGoal<>(this, Player.class, 16.0F, 0.8, 1.33); ++ this.avoidPlayersGoal = new Cat.CatAvoidEntityGoal<>(this, Player.class, 16.0F, 0.8D, 1.33D); + } + + this.goalSelector.removeGoal(this.avoidPlayersGoal); + if (!this.isTame()) { + this.goalSelector.addGoal(4, this.avoidPlayersGoal); + } ++ + } + + @Override +@@ -458,30 +468,45 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height - 0.1875F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.1875F * f, 0.0F); + } + +- static class CatAvoidEntityGoal extends AvoidEntityGoal { ++ private static class CatTemptGoal extends TemptGoal { ++ ++ @Nullable ++ private LivingEntity selectedPlayer; // CraftBukkit + private final Cat cat; + +- public CatAvoidEntityGoal(Cat cat, Class entityClassToAvoid, float maxDist, double walkSpeedModifier, double sprintSpeedModifier) { +- super(cat, entityClassToAvoid, maxDist, walkSpeedModifier, sprintSpeedModifier, EntitySelector.NO_CREATIVE_OR_SPECTATOR::test); ++ public CatTemptGoal(Cat cat, double speedModifier, Ingredient recipeitemstack, boolean items) { ++ super(cat, speedModifier, recipeitemstack, items); + this.cat = cat; + } + + @Override +- public boolean canUse() { +- return !this.cat.isTame() && super.canUse(); ++ public void tick() { ++ super.tick(); ++ if (this.selectedPlayer == null && this.mob.getRandom().nextInt(this.adjustedTickDelay(600)) == 0) { ++ this.selectedPlayer = this.player; ++ } else if (this.mob.getRandom().nextInt(this.adjustedTickDelay(500)) == 0) { ++ this.selectedPlayer = null; ++ } ++ + } + + @Override +- public boolean canContinueToUse() { +- return !this.cat.isTame() && super.canContinueToUse(); ++ protected boolean canScare() { ++ return this.selectedPlayer != null && this.selectedPlayer.equals(this.player) ? false : super.canScare(); + } ++ ++ @Override ++ public boolean canUse() { ++ return super.canUse() && !this.cat.isTame(); ++ } + } + +- static class CatRelaxOnOwnerGoal extends Goal { ++ private static class CatRelaxOnOwnerGoal extends Goal { ++ + private final Cat cat; + @Nullable + private Player ownerPlayer; +@@ -500,23 +525,27 @@ + } else if (this.cat.isOrderedToSit()) { + return false; + } else { +- LivingEntity owner = this.cat.getOwner(); +- if (owner instanceof Player) { +- this.ownerPlayer = (Player)owner; +- if (!owner.isSleeping()) { ++ LivingEntity entityliving = this.cat.getOwner(); ++ ++ if (entityliving instanceof Player) { ++ this.ownerPlayer = (Player) entityliving; ++ if (!entityliving.isSleeping()) { + return false; + } + +- if (this.cat.distanceToSqr(this.ownerPlayer) > 100.0) { ++ if (this.cat.distanceToSqr((Entity) this.ownerPlayer) > 100.0D) { + return false; + } + +- BlockPos blockPos = this.ownerPlayer.blockPosition(); +- BlockState blockState = this.cat.level().getBlockState(blockPos); +- if (blockState.is(BlockTags.BEDS)) { +- this.goalPos = blockState.getOptionalValue(BedBlock.FACING) +- .map(pos -> blockPos.relative(pos.getOpposite())) +- .orElseGet(() -> new BlockPos(blockPos)); ++ BlockPos blockposition = this.ownerPlayer.blockPosition(); ++ IBlockData iblockdata = this.cat.level().getBlockState(blockposition); ++ ++ if (iblockdata.is(BlockTags.BEDS)) { ++ this.goalPos = (BlockPos) iblockdata.getOptionalValue(BedBlock.FACING).map((enumdirection) -> { ++ return blockposition.relative(enumdirection.getOpposite()); ++ }).orElseGet(() -> { ++ return new BlockPos(blockposition); ++ }); + return !this.spaceIsOccupied(); + } + } +@@ -526,41 +555,44 @@ + } + + private boolean spaceIsOccupied() { +- for (Cat cat : this.cat.level().getEntitiesOfClass(Cat.class, new AABB(this.goalPos).inflate(2.0))) { +- if (cat != this.cat && (cat.isLying() || cat.isRelaxStateOne())) { +- return true; +- } +- } ++ List list = this.cat.level().getEntitiesOfClass(Cat.class, (new AABB(this.goalPos)).inflate(2.0D)); ++ Iterator iterator = list.iterator(); + +- return false; ++ Cat entitycat; ++ ++ do { ++ do { ++ if (!iterator.hasNext()) { ++ return false; ++ } ++ ++ entitycat = (Cat) iterator.next(); ++ } while (entitycat == this.cat); ++ } while (!entitycat.isLying() && !entitycat.isRelaxStateOne()); ++ ++ return true; + } + + @Override + public boolean canContinueToUse() { +- return this.cat.isTame() +- && !this.cat.isOrderedToSit() +- && this.ownerPlayer != null +- && this.ownerPlayer.isSleeping() +- && this.goalPos != null +- && !this.spaceIsOccupied(); ++ return this.cat.isTame() && !this.cat.isOrderedToSit() && this.ownerPlayer != null && this.ownerPlayer.isSleeping() && this.goalPos != null && !this.spaceIsOccupied(); + } + + @Override + public void start() { + if (this.goalPos != null) { + this.cat.setInSittingPose(false); +- this.cat.getNavigation().moveTo((double)this.goalPos.getX(), (double)this.goalPos.getY(), (double)this.goalPos.getZ(), 1.1F); ++ this.cat.getNavigation().moveTo((double) this.goalPos.getX(), (double) this.goalPos.getY(), (double) this.goalPos.getZ(), 1.100000023841858D); + } ++ + } + + @Override + public void stop() { + this.cat.setLying(false); +- float timeOfDay = this.cat.level().getTimeOfDay(1.0F); +- if (this.ownerPlayer.getSleepTimer() >= 100 +- && (double)timeOfDay > 0.77 +- && (double)timeOfDay < 0.8 +- && (double)this.cat.level().getRandom().nextFloat() < 0.7) { ++ float f = this.cat.level().getTimeOfDay(1.0F); ++ ++ if (this.ownerPlayer.getSleepTimer() >= 100 && (double) f > 0.77D && (double) f < 0.8D && (double) this.cat.level().getRandom().nextFloat() < 0.7D) { + this.giveMorningGift(); + } + +@@ -570,45 +602,40 @@ + } + + private void giveMorningGift() { +- RandomSource random = this.cat.getRandom(); +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); +- mutableBlockPos.set(this.cat.isLeashed() ? this.cat.getLeashHolder().blockPosition() : this.cat.blockPosition()); +- this.cat +- .randomTeleport( +- (double)(mutableBlockPos.getX() + random.nextInt(11) - 5), +- (double)(mutableBlockPos.getY() + random.nextInt(5) - 2), +- (double)(mutableBlockPos.getZ() + random.nextInt(11) - 5), +- false +- ); +- mutableBlockPos.set(this.cat.blockPosition()); +- LootTable lootTable = this.cat.level().getServer().getLootData().getLootTable(BuiltInLootTables.CAT_MORNING_GIFT); +- LootParams lootParams = new LootParams.Builder((ServerLevel)this.cat.level()) +- .withParameter(LootContextParams.ORIGIN, this.cat.position()) +- .withParameter(LootContextParams.THIS_ENTITY, this.cat) +- .create(LootContextParamSets.GIFT); ++ RandomSource randomsource = this.cat.getRandom(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + +- for (ItemStack itemStack : lootTable.getRandomItems(lootParams)) { +- this.cat +- .level() +- .addFreshEntity( +- new ItemEntity( +- this.cat.level(), +- (double)mutableBlockPos.getX() - (double)Mth.sin(this.cat.yBodyRot * (float) (Math.PI / 180.0)), +- (double)mutableBlockPos.getY(), +- (double)mutableBlockPos.getZ() + (double)Mth.cos(this.cat.yBodyRot * (float) (Math.PI / 180.0)), +- itemStack +- ) +- ); ++ blockposition_mutableblockposition.set(this.cat.isLeashed() ? this.cat.getLeashHolder().blockPosition() : this.cat.blockPosition()); ++ this.cat.randomTeleport((double) (blockposition_mutableblockposition.getX() + randomsource.nextInt(11) - 5), (double) (blockposition_mutableblockposition.getY() + randomsource.nextInt(5) - 2), (double) (blockposition_mutableblockposition.getZ() + randomsource.nextInt(11) - 5), false); ++ blockposition_mutableblockposition.set(this.cat.blockPosition()); ++ LootTable loottable = this.cat.level().getServer().getLootData().getLootTable(BuiltInLootTables.CAT_MORNING_GIFT); ++ LootParams lootparams = (new LootParams.Builder((ServerLevel) this.cat.level())).withParameter(LootContextParams.ORIGIN, this.cat.position()).withParameter(LootContextParams.THIS_ENTITY, this.cat).create(LootContextParamSets.GIFT); ++ List list = loottable.getRandomItems(lootparams); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ ItemStack itemstack = (ItemStack) iterator.next(); ++ ++ // CraftBukkit start ++ ItemEntity entityitem = new ItemEntity(this.cat.level(), (double) blockposition_mutableblockposition.getX() - (double) Mth.sin(this.cat.yBodyRot * 0.017453292F), (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + (double) Mth.cos(this.cat.yBodyRot * 0.017453292F), itemstack); ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.cat.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ entityitem.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ continue; ++ } ++ this.cat.level().addFreshEntity(entityitem); ++ // CraftBukkit end + } ++ + } + + @Override + public void tick() { + if (this.ownerPlayer != null && this.goalPos != null) { + this.cat.setInSittingPose(false); +- this.cat.getNavigation().moveTo((double)this.goalPos.getX(), (double)this.goalPos.getY(), (double)this.goalPos.getZ(), 1.1F); +- if (this.cat.distanceToSqr(this.ownerPlayer) < 2.5) { +- this.onBedTicks++; ++ this.cat.getNavigation().moveTo((double) this.goalPos.getX(), (double) this.goalPos.getY(), (double) this.goalPos.getZ(), 1.100000023841858D); ++ if (this.cat.distanceToSqr((Entity) this.ownerPlayer) < 2.5D) { ++ ++this.onBedTicks; + if (this.onBedTicks > this.adjustedTickDelay(16)) { + this.cat.setLying(true); + this.cat.setRelaxStateOne(false); +@@ -620,37 +647,30 @@ + this.cat.setLying(false); + } + } ++ + } + } + +- static class CatTemptGoal extends TemptGoal { +- @Nullable +- private Player selectedPlayer; ++ private static class CatAvoidEntityGoal extends AvoidEntityGoal { ++ + private final Cat cat; + +- public CatTemptGoal(Cat cat, double speedModifier, Ingredient items, boolean canScare) { +- super(cat, speedModifier, items, canScare); ++ public CatAvoidEntityGoal(Cat cat, Class entityClassToAvoid, float maxDist, double walkSpeedModifier, double d1) { ++ // Predicate predicate = IEntitySelector.NO_CREATIVE_OR_SPECTATOR; // CraftBukkit - decompile error ++ ++ // Objects.requireNonNull(predicate); // CraftBukkit - decompile error ++ super(cat, entityClassToAvoid, maxDist, walkSpeedModifier, d1, EntitySelector.NO_CREATIVE_OR_SPECTATOR::test); // CraftBukkit - decompile error + this.cat = cat; + } + + @Override +- public void tick() { +- super.tick(); +- if (this.selectedPlayer == null && this.mob.getRandom().nextInt(this.adjustedTickDelay(600)) == 0) { +- this.selectedPlayer = this.player; +- } else if (this.mob.getRandom().nextInt(this.adjustedTickDelay(500)) == 0) { +- this.selectedPlayer = null; +- } ++ public boolean canUse() { ++ return !this.cat.isTame() && super.canUse(); + } + + @Override +- protected boolean canScare() { +- return (this.selectedPlayer == null || !this.selectedPlayer.equals(this.player)) && super.canScare(); ++ public boolean canContinueToUse() { ++ return !this.cat.isTame() && super.canContinueToUse(); + } +- +- @Override +- public boolean canUse() { +- return super.canUse() && !this.cat.isTame(); +- } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Chicken.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Chicken.java.patch new file mode 100644 index 0000000000..c87e7de667 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Chicken.java.patch @@ -0,0 +1,163 @@ +--- a/net/minecraft/world/entity/animal/Chicken.java ++++ b/net/minecraft/world/entity/animal/Chicken.java +@@ -11,10 +11,10 @@ + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.BreedGoal; +@@ -29,50 +29,51 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.item.crafting.Ingredient; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + + public class Chicken extends Animal { +- private static final Ingredient FOOD_ITEMS = Ingredient.of( +- Items.WHEAT_SEEDS, Items.MELON_SEEDS, Items.PUMPKIN_SEEDS, Items.BEETROOT_SEEDS, Items.TORCHFLOWER_SEEDS, Items.PITCHER_POD +- ); ++ ++ private static final Ingredient FOOD_ITEMS = Ingredient.of(Items.WHEAT_SEEDS, Items.MELON_SEEDS, Items.PUMPKIN_SEEDS, Items.BEETROOT_SEEDS, Items.TORCHFLOWER_SEEDS, Items.PITCHER_POD); + public float flap; + public float flapSpeed; + public float oFlapSpeed; + public float oFlap; + public float flapping = 1.0F; + private float nextFlap = 1.0F; +- public int eggTime = this.random.nextInt(6000) + 6000; ++ public int eggTime; + public boolean isChickenJockey; + + public Chicken(EntityType entityType, Level level) { + super(entityType, level); ++ this.eggTime = this.random.nextInt(6000) + 6000; + this.setPathfindingMalus(BlockPathTypes.WATER, 0.0F); + } + + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); +- this.goalSelector.addGoal(1, new PanicGoal(this, 1.4)); +- this.goalSelector.addGoal(2, new BreedGoal(this, 1.0)); +- this.goalSelector.addGoal(3, new TemptGoal(this, 1.0, FOOD_ITEMS, false)); +- this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.1)); +- this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0)); ++ this.goalSelector.addGoal(1, new PanicGoal(this, 1.4D)); ++ this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); ++ this.goalSelector.addGoal(3, new TemptGoal(this, 1.0D, Chicken.FOOD_ITEMS, false)); ++ this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.1D)); ++ this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(7, new RandomLookAroundGoal(this)); + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return this.isBaby() ? size.height * 0.85F : size.height * 0.92F; + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 4.0).add(Attributes.MOVEMENT_SPEED, 0.25); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 4.0D).add(Attributes.MOVEMENT_SPEED, 0.25D); + } + + @Override +@@ -80,25 +81,29 @@ + super.aiStep(); + this.oFlap = this.flap; + this.oFlapSpeed = this.flapSpeed; +- this.flapSpeed = this.flapSpeed + (this.onGround() ? -1.0F : 4.0F) * 0.3F; ++ this.flapSpeed += (this.onGround() ? -1.0F : 4.0F) * 0.3F; + this.flapSpeed = Mth.clamp(this.flapSpeed, 0.0F, 1.0F); + if (!this.onGround() && this.flapping < 1.0F) { + this.flapping = 1.0F; + } + + this.flapping *= 0.9F; +- Vec3 deltaMovement = this.getDeltaMovement(); +- if (!this.onGround() && deltaMovement.y < 0.0) { +- this.setDeltaMovement(deltaMovement.multiply(1.0, 0.6, 1.0)); ++ Vec3 vec3d = this.getDeltaMovement(); ++ ++ if (!this.onGround() && vec3d.y < 0.0D) { ++ this.setDeltaMovement(vec3d.multiply(1.0D, 0.6D, 1.0D)); + } + +- this.flap = this.flap + this.flapping * 2.0F; ++ this.flap += this.flapping * 2.0F; + if (!this.level().isClientSide && this.isAlive() && !this.isBaby() && !this.isChickenJockey() && --this.eggTime <= 0) { + this.playSound(SoundEvents.CHICKEN_EGG, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); +- this.spawnAtLocation(Items.EGG); ++ this.forceDrops = true; // CraftBukkit ++ this.spawnAtLocation((IMaterial) Items.EGG); ++ this.forceDrops = false; // CraftBukkit + this.gameEvent(GameEvent.ENTITY_PLACE); + this.eggTime = this.random.nextInt(6000) + 6000; + } ++ + } + + @Override +@@ -127,19 +132,19 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.CHICKEN_STEP, 0.15F, 1.0F); + } + + @Nullable + @Override + public Chicken getBreedOffspring(ServerLevel level, AgeableMob otherParent) { +- return EntityType.CHICKEN.create(level); ++ return (Chicken) EntityType.CHICKEN.create(level); + } + + @Override + public boolean isFood(ItemStack stack) { +- return FOOD_ITEMS.test(stack); ++ return Chicken.FOOD_ITEMS.test(stack); + } + + @Override +@@ -154,6 +159,7 @@ + if (compound.contains("EggLayTime")) { + this.eggTime = compound.getInt("EggLayTime"); + } ++ + } + + @Override +@@ -172,13 +178,14 @@ + protected void positionRider(Entity passenger, Entity.MoveFunction callback) { + super.positionRider(passenger, callback); + if (passenger instanceof LivingEntity) { +- ((LivingEntity)passenger).yBodyRot = this.yBodyRot; ++ ((LivingEntity) passenger).yBodyRot = this.yBodyRot; + } ++ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height, -0.1F * f); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height, -0.1F * f); + } + + public boolean isChickenJockey() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Cow.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Cow.java.patch new file mode 100644 index 0000000000..3e9076107c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Cow.java.patch @@ -0,0 +1,121 @@ +--- a/net/minecraft/world/entity/animal/Cow.java ++++ b/net/minecraft/world/entity/animal/Cow.java +@@ -5,15 +5,15 @@ + import net.minecraft.server.level.ServerLevel; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.BreedGoal; +@@ -30,10 +30,17 @@ + import net.minecraft.world.item.Items; + import net.minecraft.world.item.crafting.Ingredient; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerBucketFillEvent; ++// CraftBukkit end ++ + public class Cow extends Animal { ++ + public Cow(EntityType entityType, Level level) { + super(entityType, level); + } +@@ -41,17 +48,17 @@ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); +- this.goalSelector.addGoal(1, new PanicGoal(this, 2.0)); +- this.goalSelector.addGoal(2, new BreedGoal(this, 1.0)); +- this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, Ingredient.of(Items.WHEAT), false)); +- this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.25)); +- this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0)); ++ this.goalSelector.addGoal(1, new PanicGoal(this, 2.0D)); ++ this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); ++ this.goalSelector.addGoal(3, new TemptGoal(this, 1.25D, Ingredient.of(Items.WHEAT), false)); ++ this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.25D)); ++ this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(7, new RandomLookAroundGoal(this)); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0).add(Attributes.MOVEMENT_SPEED, 0.2F); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.MOVEMENT_SPEED, 0.20000000298023224D); + } + + @Override +@@ -70,7 +77,7 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.COW_STEP, 0.15F, 1.0F); + } + +@@ -80,12 +87,22 @@ + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (itemInHand.is(Items.BUCKET) && !this.isBaby()) { ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (itemstack.is(Items.BUCKET) && !this.isBaby()) { ++ // CraftBukkit start - Got milk? ++ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level(), player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand); ++ ++ if (event.isCancelled()) { ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end ++ + player.playSound(SoundEvents.COW_MILK, 1.0F, 1.0F); +- ItemStack itemStack = ItemUtils.createFilledResult(itemInHand, player, Items.MILK_BUCKET.getDefaultInstance()); +- player.setItemInHand(hand, itemStack); ++ ItemStack itemstack1 = ItemUtils.createFilledResult(itemstack, player, CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit ++ ++ player.setItemInHand(hand, itemstack1); + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { + return super.mobInteract(player, hand); +@@ -95,16 +112,16 @@ + @Nullable + @Override + public Cow getBreedOffspring(ServerLevel level, AgeableMob otherParent) { +- return EntityType.COW.create(level); ++ return (Cow) EntityType.COW.create(level); + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return this.isBaby() ? size.height * 0.95F : 1.3F; + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height - 0.03125F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.03125F * f, 0.0F); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Dolphin.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Dolphin.java.patch new file mode 100644 index 0000000000..5460efbb50 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Dolphin.java.patch @@ -0,0 +1,650 @@ +--- a/net/minecraft/world/entity/animal/Dolphin.java ++++ b/net/minecraft/world/entity/animal/Dolphin.java +@@ -19,20 +19,20 @@ + import net.minecraft.tags.StructureTags; + import net.minecraft.util.Mth; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.SmoothSwimmingLookControl; +@@ -44,8 +44,8 @@ + import net.minecraft.world.entity.ai.goal.Goal; + import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; + import net.minecraft.world.entity.ai.goal.MeleeAttackGoal; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalRandomSwim; + import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal; +-import net.minecraft.world.entity.ai.goal.RandomSwimmingGoal; + import net.minecraft.world.entity.ai.goal.TryFindWaterGoal; + import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal; + import net.minecraft.world.entity.ai.navigation.PathNavigation; +@@ -58,17 +58,30 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityPotionEffectEvent; ++// CraftBukkit end + + public class Dolphin extends WaterAnimal { ++ ++ // CraftBukkit start - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ @Override ++ public int getDefaultMaxAirSupply() { ++ return TOTAL_AIR_SUPPLY; ++ } ++ // CraftBukkit end + private static final EntityDataAccessor TREASURE_POS = SynchedEntityData.defineId(Dolphin.class, EntityDataSerializers.BLOCK_POS); + private static final EntityDataAccessor GOT_FISH = SynchedEntityData.defineId(Dolphin.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor MOISTNESS_LEVEL = SynchedEntityData.defineId(Dolphin.class, EntityDataSerializers.INT); +- static final TargetingConditions SWIM_WITH_PLAYER_TARGETING = TargetingConditions.forNonCombat().range(10.0).ignoreLineOfSight(); ++ static final TargetingConditions SWIM_WITH_PLAYER_TARGETING = TargetingConditions.forNonCombat().range(10.0D).ignoreLineOfSight(); + public static final int TOTAL_AIR_SUPPLY = 4800; + private static final int TOTAL_MOISTNESS_LEVEL = 2400; +- public static final Predicate ALLOWED_ITEMS = itemEntity -> !itemEntity.hasPickUpDelay() && itemEntity.isAlive() && itemEntity.isInWater(); ++ public static final Predicate ALLOWED_ITEMS = (entityitem) -> { ++ return !entityitem.hasPickUpDelay() && entityitem.isAlive() && entityitem.isInWater(); ++ }; + + public Dolphin(EntityType entityType, Level level) { + super(entityType, level); +@@ -79,48 +92,45 @@ + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + this.setAirSupply(this.getMaxAirSupply()); + this.setXRot(0.0F); + return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + + @Override +- protected void handleAirSupply(int airSupply) { +- } ++ protected void handleAirSupply(int airSupply) {} + + public void setTreasurePos(BlockPos pos) { +- this.entityData.set(TREASURE_POS, pos); ++ this.entityData.set(Dolphin.TREASURE_POS, pos); + } + + public BlockPos getTreasurePos() { +- return this.entityData.get(TREASURE_POS); ++ return (BlockPos) this.entityData.get(Dolphin.TREASURE_POS); + } + + public boolean gotFish() { +- return this.entityData.get(GOT_FISH); ++ return (Boolean) this.entityData.get(Dolphin.GOT_FISH); + } + + public void setGotFish(boolean gotFish) { +- this.entityData.set(GOT_FISH, gotFish); ++ this.entityData.set(Dolphin.GOT_FISH, gotFish); + } + + public int getMoistnessLevel() { +- return this.entityData.get(MOISTNESS_LEVEL); ++ return (Integer) this.entityData.get(Dolphin.MOISTNESS_LEVEL); + } + + public void setMoisntessLevel(int moistnessLevel) { +- this.entityData.set(MOISTNESS_LEVEL, moistnessLevel); ++ this.entityData.set(Dolphin.MOISTNESS_LEVEL, moistnessLevel); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(TREASURE_POS, BlockPos.ZERO); +- this.entityData.define(GOT_FISH, false); +- this.entityData.define(MOISTNESS_LEVEL, 2400); ++ this.entityData.define(Dolphin.TREASURE_POS, BlockPos.ZERO); ++ this.entityData.define(Dolphin.GOT_FISH, false); ++ this.entityData.define(Dolphin.MOISTNESS_LEVEL, 2400); + } + + @Override +@@ -135,10 +145,11 @@ + + @Override + public void readAdditionalSaveData(CompoundTag compound) { +- int _int = compound.getInt("TreasurePosX"); +- int _int1 = compound.getInt("TreasurePosY"); +- int _int2 = compound.getInt("TreasurePosZ"); +- this.setTreasurePos(new BlockPos(_int, _int1, _int2)); ++ int i = compound.getInt("TreasurePosX"); ++ int j = compound.getInt("TreasurePosY"); ++ int k = compound.getInt("TreasurePosZ"); ++ ++ this.setTreasurePos(new BlockPos(i, j, k)); + super.readAdditionalSaveData(compound); + this.setGotFish(compound.getBoolean("GotFish")); + this.setMoisntessLevel(compound.getInt("Moistness")); +@@ -149,20 +160,20 @@ + this.goalSelector.addGoal(0, new BreathAirGoal(this)); + this.goalSelector.addGoal(0, new TryFindWaterGoal(this)); + this.goalSelector.addGoal(1, new Dolphin.DolphinSwimToTreasureGoal(this)); +- this.goalSelector.addGoal(2, new Dolphin.DolphinSwimWithPlayerGoal(this, 4.0)); +- this.goalSelector.addGoal(4, new RandomSwimmingGoal(this, 1.0, 10)); ++ this.goalSelector.addGoal(2, new Dolphin.DolphinSwimWithPlayerGoal(this, 4.0D)); ++ this.goalSelector.addGoal(4, new PathfinderGoalRandomSwim(this, 1.0D, 10)); + this.goalSelector.addGoal(4, new RandomLookAroundGoal(this)); + this.goalSelector.addGoal(5, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(5, new DolphinJumpGoal(this, 10)); +- this.goalSelector.addGoal(6, new MeleeAttackGoal(this, 1.2F, true)); ++ this.goalSelector.addGoal(6, new MeleeAttackGoal(this, 1.2000000476837158D, true)); + this.goalSelector.addGoal(8, new Dolphin.PlayWithItemsGoal()); + this.goalSelector.addGoal(8, new FollowBoatGoal(this)); +- this.goalSelector.addGoal(9, new AvoidEntityGoal<>(this, Guardian.class, 8.0F, 1.0, 1.0)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Guardian.class).setAlertOthers()); ++ this.goalSelector.addGoal(9, new AvoidEntityGoal<>(this, Guardian.class, 8.0F, 1.0D, 1.0D)); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Guardian.class})).setAlertOthers()); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0).add(Attributes.MOVEMENT_SPEED, 1.2F).add(Attributes.ATTACK_DAMAGE, 3.0); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.MOVEMENT_SPEED, 1.2000000476837158D).add(Attributes.ATTACK_DAMAGE, 3.0D); + } + + @Override +@@ -172,7 +183,8 @@ + + @Override + public boolean doHurtTarget(Entity entity) { +- boolean flag = entity.hurt(this.damageSources().mobAttack(this), (float)((int)this.getAttributeValue(Attributes.ATTACK_DAMAGE))); ++ boolean flag = entity.hurt(this.damageSources().mobAttack(this), (float) ((int) this.getAttributeValue(Attributes.ATTACK_DAMAGE))); ++ + if (flag) { + this.doEnchantDamageEffects(this, entity); + this.playSound(SoundEvents.DOLPHIN_ATTACK, 1.0F, 1.0F); +@@ -183,7 +195,7 @@ + + @Override + public int getMaxAirSupply() { +- return 4800; ++ return maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() + } + + @Override +@@ -192,7 +204,7 @@ + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.3F; + } + +@@ -213,22 +225,31 @@ + + @Override + public boolean canTakeItem(ItemStack itemstack) { +- EquipmentSlot equipmentSlotForItem = Mob.getEquipmentSlotForItem(itemstack); +- return this.getItemBySlot(equipmentSlotForItem).isEmpty() && equipmentSlotForItem == EquipmentSlot.MAINHAND && super.canTakeItem(itemstack); ++ EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(itemstack); ++ ++ return !this.getItemBySlot(enumitemslot).isEmpty() ? false : enumitemslot == EquipmentSlot.MAINHAND && super.canTakeItem(itemstack); + } + + @Override + protected void pickUpItem(ItemEntity itemEntity) { + if (this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty()) { +- ItemStack item = itemEntity.getItem(); +- if (this.canHoldItem(item)) { ++ ItemStack itemstack = itemEntity.getItem(); ++ ++ if (this.canHoldItem(itemstack)) { ++ // CraftBukkit start - call EntityPickupItemEvent ++ if (CraftEventFactory.callEntityPickupItemEvent(this, itemEntity, 0, false).isCancelled()) { ++ return; ++ } ++ itemstack = itemEntity.getItem(); // CraftBukkit- update ItemStack from event ++ // CraftBukkit start + this.onItemPickup(itemEntity); +- this.setItemSlot(EquipmentSlot.MAINHAND, item); ++ this.setItemSlot(EquipmentSlot.MAINHAND, itemstack); + this.setGuaranteedDrop(EquipmentSlot.MAINHAND); +- this.take(itemEntity, item.getCount()); ++ this.take(itemEntity, itemstack.getCount()); + itemEntity.discard(); + } + } ++ + } + + @Override +@@ -246,45 +267,25 @@ + } + + if (this.onGround()) { +- this.setDeltaMovement( +- this.getDeltaMovement() +- .add((double)((this.random.nextFloat() * 2.0F - 1.0F) * 0.2F), 0.5, (double)((this.random.nextFloat() * 2.0F - 1.0F) * 0.2F)) +- ); ++ this.setDeltaMovement(this.getDeltaMovement().add((double) ((this.random.nextFloat() * 2.0F - 1.0F) * 0.2F), 0.5D, (double) ((this.random.nextFloat() * 2.0F - 1.0F) * 0.2F))); + this.setYRot(this.random.nextFloat() * 360.0F); + this.setOnGround(false); + this.hasImpulse = true; + } + } + +- if (this.level().isClientSide && this.isInWater() && this.getDeltaMovement().lengthSqr() > 0.03) { +- Vec3 viewVector = this.getViewVector(0.0F); +- float f = Mth.cos(this.getYRot() * (float) (Math.PI / 180.0)) * 0.3F; +- float f1 = Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)) * 0.3F; ++ if (this.level().isClientSide && this.isInWater() && this.getDeltaMovement().lengthSqr() > 0.03D) { ++ Vec3 vec3d = this.getViewVector(0.0F); ++ float f = Mth.cos(this.getYRot() * 0.017453292F) * 0.3F; ++ float f1 = Mth.sin(this.getYRot() * 0.017453292F) * 0.3F; + float f2 = 1.2F - this.random.nextFloat() * 0.7F; + +- for (int i = 0; i < 2; i++) { +- this.level() +- .addParticle( +- ParticleTypes.DOLPHIN, +- this.getX() - viewVector.x * (double)f2 + (double)f, +- this.getY() - viewVector.y, +- this.getZ() - viewVector.z * (double)f2 + (double)f1, +- 0.0, +- 0.0, +- 0.0 +- ); +- this.level() +- .addParticle( +- ParticleTypes.DOLPHIN, +- this.getX() - viewVector.x * (double)f2 - (double)f, +- this.getY() - viewVector.y, +- this.getZ() - viewVector.z * (double)f2 - (double)f1, +- 0.0, +- 0.0, +- 0.0 +- ); ++ for (int i = 0; i < 2; ++i) { ++ this.level().addParticle(ParticleTypes.DOLPHIN, this.getX() - vec3d.x * (double) f2 + (double) f, this.getY() - vec3d.y, this.getZ() - vec3d.z * (double) f2 + (double) f1, 0.0D, 0.0D, 0.0D); ++ this.level().addParticle(ParticleTypes.DOLPHIN, this.getX() - vec3d.x * (double) f2 - (double) f, this.getY() - vec3d.y, this.getZ() - vec3d.z * (double) f2 - (double) f1, 0.0D, 0.0D, 0.0D); + } + } ++ + } + } + +@@ -295,28 +296,32 @@ + } else { + super.handleEntityEvent(id); + } ++ + } + + private void addParticlesAroundSelf(ParticleOptions particleOption) { +- for (int i = 0; i < 7; i++) { +- double d = this.random.nextGaussian() * 0.01; +- double d1 = this.random.nextGaussian() * 0.01; +- double d2 = this.random.nextGaussian() * 0.01; +- this.level().addParticle(particleOption, this.getRandomX(1.0), this.getRandomY() + 0.2, this.getRandomZ(1.0), d, d1, d2); ++ for (int i = 0; i < 7; ++i) { ++ double d0 = this.random.nextGaussian() * 0.01D; ++ double d1 = this.random.nextGaussian() * 0.01D; ++ double d2 = this.random.nextGaussian() * 0.01D; ++ ++ this.level().addParticle(particleOption, this.getRandomX(1.0D), this.getRandomY() + 0.2D, this.getRandomZ(1.0D), d0, d1, d2); + } ++ + } + + @Override +- protected InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (!itemInHand.isEmpty() && itemInHand.is(ItemTags.FISHES)) { ++ protected InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (!itemstack.isEmpty() && itemstack.is(ItemTags.FISHES)) { + if (!this.level().isClientSide) { + this.playSound(SoundEvents.DOLPHIN_EAT, 1.0F, 1.0F); + } + + this.setGotFish(true); + if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + + return InteractionResult.sidedSuccess(this.level().isClientSide); +@@ -353,22 +358,24 @@ + } + + protected boolean closeToNextPos() { +- BlockPos targetPos = this.getNavigation().getTargetPos(); +- return targetPos != null && targetPos.closerToCenterThan(this.position(), 12.0); ++ BlockPos blockposition = this.getNavigation().getTargetPos(); ++ ++ return blockposition != null ? blockposition.closerToCenterThan(this.position(), 12.0D) : false; + } + + @Override + public void travel(Vec3 travelVector) { + if (this.isEffectiveAi() && this.isInWater()) { + this.moveRelative(this.getSpeed(), travelVector); +- this.move(MoverType.SELF, this.getDeltaMovement()); +- this.setDeltaMovement(this.getDeltaMovement().scale(0.9)); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); ++ this.setDeltaMovement(this.getDeltaMovement().scale(0.9D)); + if (this.getTarget() == null) { +- this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.005, 0.0)); ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.005D, 0.0D)); + } + } else { + super.travel(travelVector); + } ++ + } + + @Override +@@ -376,13 +383,14 @@ + return true; + } + +- static class DolphinSwimToTreasureGoal extends Goal { ++ private static class DolphinSwimToTreasureGoal extends Goal { ++ + private final Dolphin dolphin; + private boolean stuck; + + DolphinSwimToTreasureGoal(Dolphin dolphin) { + this.dolphin = dolphin; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + } + + @Override +@@ -397,24 +405,24 @@ + + @Override + public boolean canContinueToUse() { +- BlockPos treasurePos = this.dolphin.getTreasurePos(); +- return !BlockPos.containing((double)treasurePos.getX(), this.dolphin.getY(), (double)treasurePos.getZ()) +- .closerToCenterThan(this.dolphin.position(), 4.0) +- && !this.stuck +- && this.dolphin.getAirSupply() >= 100; ++ BlockPos blockposition = this.dolphin.getTreasurePos(); ++ ++ return !BlockPos.containing((double) blockposition.getX(), this.dolphin.getY(), (double) blockposition.getZ()).closerToCenterThan(this.dolphin.position(), 4.0D) && !this.stuck && this.dolphin.getAirSupply() >= 100; + } + + @Override + public void start() { + if (this.dolphin.level() instanceof ServerLevel) { +- ServerLevel serverLevel = (ServerLevel)this.dolphin.level(); ++ ServerLevel worldserver = (ServerLevel) this.dolphin.level(); ++ + this.stuck = false; + this.dolphin.getNavigation().stop(); +- BlockPos blockPos = this.dolphin.blockPosition(); +- BlockPos blockPos1 = serverLevel.findNearestMapStructure(StructureTags.DOLPHIN_LOCATED, blockPos, 50, false); +- if (blockPos1 != null) { +- this.dolphin.setTreasurePos(blockPos1); +- serverLevel.broadcastEntityEvent(this.dolphin, (byte)38); ++ BlockPos blockposition = this.dolphin.blockPosition(); ++ BlockPos blockposition1 = worldserver.findNearestMapStructure(StructureTags.DOLPHIN_LOCATED, blockposition, 50, false); ++ ++ if (blockposition1 != null) { ++ this.dolphin.setTreasurePos(blockposition1); ++ worldserver.broadcastEntityEvent(this.dolphin, (byte) 38); + } else { + this.stuck = true; + } +@@ -423,49 +431,51 @@ + + @Override + public void stop() { +- BlockPos treasurePos = this.dolphin.getTreasurePos(); +- if (BlockPos.containing((double)treasurePos.getX(), this.dolphin.getY(), (double)treasurePos.getZ()) +- .closerToCenterThan(this.dolphin.position(), 4.0) +- || this.stuck) { ++ BlockPos blockposition = this.dolphin.getTreasurePos(); ++ ++ if (BlockPos.containing((double) blockposition.getX(), this.dolphin.getY(), (double) blockposition.getZ()).closerToCenterThan(this.dolphin.position(), 4.0D) || this.stuck) { + this.dolphin.setGotFish(false); + } ++ + } + + @Override + public void tick() { +- Level level = this.dolphin.level(); ++ Level world = this.dolphin.level(); ++ + if (this.dolphin.closeToNextPos() || this.dolphin.getNavigation().isDone()) { +- Vec3 vec3 = Vec3.atCenterOf(this.dolphin.getTreasurePos()); +- Vec3 posTowards = DefaultRandomPos.getPosTowards(this.dolphin, 16, 1, vec3, (float) (Math.PI / 8)); +- if (posTowards == null) { +- posTowards = DefaultRandomPos.getPosTowards(this.dolphin, 8, 4, vec3, (float) (Math.PI / 2)); ++ Vec3 vec3d = Vec3.atCenterOf(this.dolphin.getTreasurePos()); ++ Vec3 vec3d1 = DefaultRandomPos.getPosTowards(this.dolphin, 16, 1, vec3d, 0.39269909262657166D); ++ ++ if (vec3d1 == null) { ++ vec3d1 = DefaultRandomPos.getPosTowards(this.dolphin, 8, 4, vec3d, 1.5707963705062866D); + } + +- if (posTowards != null) { +- BlockPos blockPos = BlockPos.containing(posTowards); +- if (!level.getFluidState(blockPos).is(FluidTags.WATER) +- || !level.getBlockState(blockPos).isPathfindable(level, blockPos, PathComputationType.WATER)) { +- posTowards = DefaultRandomPos.getPosTowards(this.dolphin, 8, 5, vec3, (float) (Math.PI / 2)); ++ if (vec3d1 != null) { ++ BlockPos blockposition = BlockPos.containing(vec3d1); ++ ++ if (!world.getFluidState(blockposition).is(FluidTags.WATER) || !world.getBlockState(blockposition).isPathfindable(world, blockposition, PathMode.WATER)) { ++ vec3d1 = DefaultRandomPos.getPosTowards(this.dolphin, 8, 5, vec3d, 1.5707963705062866D); + } + } + +- if (posTowards == null) { ++ if (vec3d1 == null) { + this.stuck = true; + return; + } + +- this.dolphin +- .getLookControl() +- .setLookAt(posTowards.x, posTowards.y, posTowards.z, (float)(this.dolphin.getMaxHeadYRot() + 20), (float)this.dolphin.getMaxHeadXRot()); +- this.dolphin.getNavigation().moveTo(posTowards.x, posTowards.y, posTowards.z, 1.3); +- if (level.random.nextInt(this.adjustedTickDelay(80)) == 0) { +- level.broadcastEntityEvent(this.dolphin, (byte)38); ++ this.dolphin.getLookControl().setLookAt(vec3d1.x, vec3d1.y, vec3d1.z, (float) (this.dolphin.getMaxHeadYRot() + 20), (float) this.dolphin.getMaxHeadXRot()); ++ this.dolphin.getNavigation().moveTo(vec3d1.x, vec3d1.y, vec3d1.z, 1.3D); ++ if (world.random.nextInt(this.adjustedTickDelay(80)) == 0) { ++ world.broadcastEntityEvent(this.dolphin, (byte) 38); + } + } ++ + } + } + +- static class DolphinSwimWithPlayerGoal extends Goal { ++ private static class DolphinSwimWithPlayerGoal extends Goal { ++ + private final Dolphin dolphin; + private final double speedModifier; + @Nullable +@@ -474,23 +484,23 @@ + DolphinSwimWithPlayerGoal(Dolphin dolphin, double speedModifier) { + this.dolphin = dolphin; + this.speedModifier = speedModifier; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + } + + @Override + public boolean canUse() { + this.player = this.dolphin.level().getNearestPlayer(Dolphin.SWIM_WITH_PLAYER_TARGETING, this.dolphin); +- return this.player != null && this.player.isSwimming() && this.dolphin.getTarget() != this.player; ++ return this.player == null ? false : this.player.isSwimming() && this.dolphin.getTarget() != this.player; + } + + @Override + public boolean canContinueToUse() { +- return this.player != null && this.player.isSwimming() && this.dolphin.distanceToSqr(this.player) < 256.0; ++ return this.player != null && this.player.isSwimming() && this.dolphin.distanceToSqr((Entity) this.player) < 256.0D; + } + + @Override + public void start() { +- this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin); ++ this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin, EntityPotionEffectEvent.Cause.DOLPHIN); // CraftBukkit + } + + @Override +@@ -501,39 +511,43 @@ + + @Override + public void tick() { +- this.dolphin.getLookControl().setLookAt(this.player, (float)(this.dolphin.getMaxHeadYRot() + 20), (float)this.dolphin.getMaxHeadXRot()); +- if (this.dolphin.distanceToSqr(this.player) < 6.25) { ++ this.dolphin.getLookControl().setLookAt(this.player, (float) (this.dolphin.getMaxHeadYRot() + 20), (float) this.dolphin.getMaxHeadXRot()); ++ if (this.dolphin.distanceToSqr((Entity) this.player) < 6.25D) { + this.dolphin.getNavigation().stop(); + } else { +- this.dolphin.getNavigation().moveTo(this.player, this.speedModifier); ++ this.dolphin.getNavigation().moveTo((Entity) this.player, this.speedModifier); + } + + if (this.player.isSwimming() && this.player.level().random.nextInt(6) == 0) { +- this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin); ++ this.player.addEffect(new MobEffectInstance(MobEffects.DOLPHINS_GRACE, 100), this.dolphin, EntityPotionEffectEvent.Cause.DOLPHIN); // CraftBukkit + } ++ + } + } + +- class PlayWithItemsGoal extends Goal { ++ private class PlayWithItemsGoal extends Goal { ++ + private int cooldown; + ++ PlayWithItemsGoal() {} ++ + @Override + public boolean canUse() { + if (this.cooldown > Dolphin.this.tickCount) { + return false; + } else { +- List entitiesOfClass = Dolphin.this.level() +- .getEntitiesOfClass(ItemEntity.class, Dolphin.this.getBoundingBox().inflate(8.0, 8.0, 8.0), Dolphin.ALLOWED_ITEMS); +- return !entitiesOfClass.isEmpty() || !Dolphin.this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty(); ++ List list = Dolphin.this.level().getEntitiesOfClass(ItemEntity.class, Dolphin.this.getBoundingBox().inflate(8.0D, 8.0D, 8.0D), Dolphin.ALLOWED_ITEMS); ++ ++ return !list.isEmpty() || !Dolphin.this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty(); + } + } + + @Override + public void start() { +- List entitiesOfClass = Dolphin.this.level() +- .getEntitiesOfClass(ItemEntity.class, Dolphin.this.getBoundingBox().inflate(8.0, 8.0, 8.0), Dolphin.ALLOWED_ITEMS); +- if (!entitiesOfClass.isEmpty()) { +- Dolphin.this.getNavigation().moveTo(entitiesOfClass.get(0), 1.2F); ++ List list = Dolphin.this.level().getEntitiesOfClass(ItemEntity.class, Dolphin.this.getBoundingBox().inflate(8.0D, 8.0D, 8.0D), Dolphin.ALLOWED_ITEMS); ++ ++ if (!list.isEmpty()) { ++ Dolphin.this.getNavigation().moveTo((Entity) list.get(0), 1.2000000476837158D); + Dolphin.this.playSound(SoundEvents.DOLPHIN_PLAY, 1.0F, 1.0F); + } + +@@ -542,48 +556,43 @@ + + @Override + public void stop() { +- ItemStack itemBySlot = Dolphin.this.getItemBySlot(EquipmentSlot.MAINHAND); +- if (!itemBySlot.isEmpty()) { +- this.drop(itemBySlot); ++ ItemStack itemstack = Dolphin.this.getItemBySlot(EquipmentSlot.MAINHAND); ++ ++ if (!itemstack.isEmpty()) { ++ this.drop(itemstack); + Dolphin.this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); + this.cooldown = Dolphin.this.tickCount + Dolphin.this.random.nextInt(100); + } ++ + } + + @Override + public void tick() { +- List entitiesOfClass = Dolphin.this.level() +- .getEntitiesOfClass(ItemEntity.class, Dolphin.this.getBoundingBox().inflate(8.0, 8.0, 8.0), Dolphin.ALLOWED_ITEMS); +- ItemStack itemBySlot = Dolphin.this.getItemBySlot(EquipmentSlot.MAINHAND); +- if (!itemBySlot.isEmpty()) { +- this.drop(itemBySlot); ++ List list = Dolphin.this.level().getEntitiesOfClass(ItemEntity.class, Dolphin.this.getBoundingBox().inflate(8.0D, 8.0D, 8.0D), Dolphin.ALLOWED_ITEMS); ++ ItemStack itemstack = Dolphin.this.getItemBySlot(EquipmentSlot.MAINHAND); ++ ++ if (!itemstack.isEmpty()) { ++ this.drop(itemstack); + Dolphin.this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); +- } else if (!entitiesOfClass.isEmpty()) { +- Dolphin.this.getNavigation().moveTo(entitiesOfClass.get(0), 1.2F); ++ } else if (!list.isEmpty()) { ++ Dolphin.this.getNavigation().moveTo((Entity) list.get(0), 1.2000000476837158D); + } ++ + } + + private void drop(ItemStack stack) { + if (!stack.isEmpty()) { +- double d = Dolphin.this.getEyeY() - 0.3F; +- ItemEntity itemEntity = new ItemEntity(Dolphin.this.level(), Dolphin.this.getX(), d, Dolphin.this.getZ(), stack); +- itemEntity.setPickUpDelay(40); +- itemEntity.setThrower(Dolphin.this); ++ double d0 = Dolphin.this.getEyeY() - 0.30000001192092896D; ++ ItemEntity entityitem = new ItemEntity(Dolphin.this.level(), Dolphin.this.getX(), d0, Dolphin.this.getZ(), stack); ++ ++ entityitem.setPickUpDelay(40); ++ entityitem.setThrower(Dolphin.this); + float f = 0.3F; +- float f1 = Dolphin.this.random.nextFloat() * (float) (Math.PI * 2); ++ float f1 = Dolphin.this.random.nextFloat() * 6.2831855F; + float f2 = 0.02F * Dolphin.this.random.nextFloat(); +- itemEntity.setDeltaMovement( +- (double)( +- 0.3F * -Mth.sin(Dolphin.this.getYRot() * (float) (Math.PI / 180.0)) * Mth.cos(Dolphin.this.getXRot() * (float) (Math.PI / 180.0)) +- + Mth.cos(f1) * f2 +- ), +- (double)(0.3F * Mth.sin(Dolphin.this.getXRot() * (float) (Math.PI / 180.0)) * 1.5F), +- (double)( +- 0.3F * Mth.cos(Dolphin.this.getYRot() * (float) (Math.PI / 180.0)) * Mth.cos(Dolphin.this.getXRot() * (float) (Math.PI / 180.0)) +- + Mth.sin(f1) * f2 +- ) +- ); +- Dolphin.this.level().addFreshEntity(itemEntity); ++ ++ entityitem.setDeltaMovement((double) (0.3F * -Mth.sin(Dolphin.this.getYRot() * 0.017453292F) * Mth.cos(Dolphin.this.getXRot() * 0.017453292F) + Mth.cos(f1) * f2), (double) (0.3F * Mth.sin(Dolphin.this.getXRot() * 0.017453292F) * 1.5F), (double) (0.3F * Mth.cos(Dolphin.this.getYRot() * 0.017453292F) * Mth.cos(Dolphin.this.getXRot() * 0.017453292F) + Mth.sin(f1) * f2)); ++ Dolphin.this.level().addFreshEntity(entityitem); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Fox.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Fox.java.patch new file mode 100644 index 0000000000..7411d9d32a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Fox.java.patch @@ -0,0 +1,2004 @@ +--- a/net/minecraft/world/entity/animal/Fox.java ++++ b/net/minecraft/world/entity/animal/Fox.java +@@ -2,6 +2,7 @@ + + import com.google.common.collect.Lists; + import java.util.EnumSet; ++import java.util.Iterator; + import java.util.List; + import java.util.Optional; + import java.util.UUID; +@@ -34,20 +35,20 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.util.StringRepresentable; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.ExperienceOrb; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.TamableAnimal; + import net.minecraft.world.entity.VariantHolder; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -61,12 +62,12 @@ + import net.minecraft.world.entity.ai.goal.FloatGoal; + import net.minecraft.world.entity.ai.goal.FollowParentGoal; + import net.minecraft.world.entity.ai.goal.Goal; +-import net.minecraft.world.entity.ai.goal.JumpGoal; + import net.minecraft.world.entity.ai.goal.LeapAtTargetGoal; + import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; + import net.minecraft.world.entity.ai.goal.MeleeAttackGoal; + import net.minecraft.world.entity.ai.goal.MoveToBlockGoal; + import net.minecraft.world.entity.ai.goal.PanicGoal; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalWaterJumpAbstract; + import net.minecraft.world.entity.ai.goal.StrollThroughVillageGoal; + import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal; + import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; +@@ -87,13 +88,14 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.CaveVines; + import net.minecraft.world.level.block.SweetBerryBushBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + + public class Fox extends Animal implements VariantHolder { ++ + private static final EntityDataAccessor DATA_TYPE_ID = SynchedEntityData.defineId(Fox.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_FLAGS_ID = SynchedEntityData.defineId(Fox.class, EntityDataSerializers.BYTE); + private static final int FLAG_SITTING = 1; +@@ -103,14 +105,26 @@ + private static final int FLAG_SLEEPING = 32; + private static final int FLAG_FACEPLANTED = 64; + private static final int FLAG_DEFENDING = 128; +- private static final EntityDataAccessor> DATA_TRUSTED_ID_0 = SynchedEntityData.defineId(Fox.class, EntityDataSerializers.OPTIONAL_UUID); +- private static final EntityDataAccessor> DATA_TRUSTED_ID_1 = SynchedEntityData.defineId(Fox.class, EntityDataSerializers.OPTIONAL_UUID); +- static final Predicate ALLOWED_ITEMS = item -> !item.hasPickUpDelay() && item.isAlive(); +- private static final Predicate TRUSTED_TARGET_SELECTOR = entity -> entity instanceof LivingEntity livingEntity +- && livingEntity.getLastHurtMob() != null +- && livingEntity.getLastHurtMobTimestamp() < livingEntity.tickCount + 600; +- static final Predicate STALKABLE_PREY = entity -> entity instanceof Chicken || entity instanceof Rabbit; +- private static final Predicate AVOID_PLAYERS = entity -> !entity.isDiscrete() && EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(entity); ++ public static final EntityDataAccessor> DATA_TRUSTED_ID_0 = SynchedEntityData.defineId(Fox.class, EntityDataSerializers.OPTIONAL_UUID); ++ public static final EntityDataAccessor> DATA_TRUSTED_ID_1 = SynchedEntityData.defineId(Fox.class, EntityDataSerializers.OPTIONAL_UUID); ++ static final Predicate ALLOWED_ITEMS = (entityitem) -> { ++ return !entityitem.hasPickUpDelay() && entityitem.isAlive(); ++ }; ++ private static final Predicate TRUSTED_TARGET_SELECTOR = (entity) -> { ++ if (!(entity instanceof LivingEntity)) { ++ return false; ++ } else { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ return entityliving.getLastHurtMob() != null && entityliving.getLastHurtMobTimestamp() < entityliving.tickCount + 600; ++ } ++ }; ++ static final Predicate STALKABLE_PREY = (entity) -> { ++ return entity instanceof Chicken || entity instanceof Rabbit; ++ }; ++ private static final Predicate AVOID_PLAYERS = (entity) -> { ++ return !entity.isDiscrete() && EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(entity); ++ }; + private static final int MIN_TICKS_BEFORE_EAT = 600; + private Goal landTargetGoal; + private Goal turtleEggTargetGoal; +@@ -124,7 +138,7 @@ + public Fox(EntityType entityType, Level level) { + super(entityType, level); + this.lookControl = new Fox.FoxLookControl(); +- this.moveControl = new Fox.FoxMoveControl(); ++ this.moveControl = new Fox.m(); + this.setPathfindingMalus(BlockPathTypes.DANGER_OTHER, 0.0F); + this.setPathfindingMalus(BlockPathTypes.DAMAGE_OTHER, 0.0F); + this.setCanPickUpLoot(true); +@@ -133,61 +147,51 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_TRUSTED_ID_0, Optional.empty()); +- this.entityData.define(DATA_TRUSTED_ID_1, Optional.empty()); +- this.entityData.define(DATA_TYPE_ID, 0); +- this.entityData.define(DATA_FLAGS_ID, (byte)0); ++ this.entityData.define(Fox.DATA_TRUSTED_ID_0, Optional.empty()); ++ this.entityData.define(Fox.DATA_TRUSTED_ID_1, Optional.empty()); ++ this.entityData.define(Fox.DATA_TYPE_ID, 0); ++ this.entityData.define(Fox.DATA_FLAGS_ID, (byte) 0); + } + + @Override + protected void registerGoals() { +- this.landTargetGoal = new NearestAttackableTargetGoal<>( +- this, Animal.class, 10, false, false, livingEntity -> livingEntity instanceof Chicken || livingEntity instanceof Rabbit +- ); ++ this.landTargetGoal = new NearestAttackableTargetGoal<>(this, Animal.class, 10, false, false, (entityliving) -> { ++ return entityliving instanceof Chicken || entityliving instanceof Rabbit; ++ }); + this.turtleEggTargetGoal = new NearestAttackableTargetGoal<>(this, Turtle.class, 10, false, false, Turtle.BABY_ON_LAND_SELECTOR); +- this.fishTargetGoal = new NearestAttackableTargetGoal<>( +- this, AbstractFish.class, 20, false, false, livingEntity -> livingEntity instanceof AbstractSchoolingFish +- ); ++ this.fishTargetGoal = new NearestAttackableTargetGoal<>(this, AbstractFish.class, 20, false, false, (entityliving) -> { ++ return entityliving instanceof AbstractSchoolingFish; ++ }); + this.goalSelector.addGoal(0, new Fox.FoxFloatGoal()); + this.goalSelector.addGoal(0, new ClimbOnTopOfPowderSnowGoal(this, this.level())); + this.goalSelector.addGoal(1, new Fox.FaceplantGoal()); +- this.goalSelector.addGoal(2, new Fox.FoxPanicGoal(2.2)); +- this.goalSelector.addGoal(3, new Fox.FoxBreedGoal(1.0)); +- this.goalSelector +- .addGoal( +- 4, +- new AvoidEntityGoal<>( +- this, +- Player.class, +- 16.0F, +- 1.6, +- 1.4, +- livingEntity -> AVOID_PLAYERS.test(livingEntity) && !this.trusts(livingEntity.getUUID()) && !this.isDefending() +- ) +- ); +- this.goalSelector +- .addGoal(4, new AvoidEntityGoal<>(this, Wolf.class, 8.0F, 1.6, 1.4, livingEntity -> !((Wolf)livingEntity).isTame() && !this.isDefending())); +- this.goalSelector.addGoal(4, new AvoidEntityGoal<>(this, PolarBear.class, 8.0F, 1.6, 1.4, livingEntity -> !this.isDefending())); ++ this.goalSelector.addGoal(2, new Fox.FoxPanicGoal(2.2D)); ++ this.goalSelector.addGoal(3, new Fox.FoxBreedGoal(1.0D)); ++ this.goalSelector.addGoal(4, new AvoidEntityGoal<>(this, Player.class, 16.0F, 1.6D, 1.4D, (entityliving) -> { ++ return Fox.AVOID_PLAYERS.test(entityliving) && !this.trusts(entityliving.getUUID()) && !this.isDefending(); ++ })); ++ this.goalSelector.addGoal(4, new AvoidEntityGoal<>(this, Wolf.class, 8.0F, 1.6D, 1.4D, (entityliving) -> { ++ return !((Wolf) entityliving).isTame() && !this.isDefending(); ++ })); ++ this.goalSelector.addGoal(4, new AvoidEntityGoal<>(this, PolarBear.class, 8.0F, 1.6D, 1.4D, (entityliving) -> { ++ return !this.isDefending(); ++ })); + this.goalSelector.addGoal(5, new Fox.StalkPreyGoal()); + this.goalSelector.addGoal(6, new Fox.FoxPounceGoal()); +- this.goalSelector.addGoal(6, new Fox.SeekShelterGoal(1.25)); +- this.goalSelector.addGoal(7, new Fox.FoxMeleeAttackGoal(1.2F, true)); ++ this.goalSelector.addGoal(6, new Fox.SeekShelterGoal(1.25D)); ++ this.goalSelector.addGoal(7, new Fox.FoxMeleeAttackGoal(1.2000000476837158D, true)); + this.goalSelector.addGoal(7, new Fox.SleepGoal()); +- this.goalSelector.addGoal(8, new Fox.FoxFollowParentGoal(this, 1.25)); ++ this.goalSelector.addGoal(8, new Fox.FoxFollowParentGoal(this, 1.25D)); + this.goalSelector.addGoal(9, new Fox.FoxStrollThroughVillageGoal(32, 200)); +- this.goalSelector.addGoal(10, new Fox.FoxEatBerriesGoal(1.2F, 12, 1)); ++ this.goalSelector.addGoal(10, new Fox.FoxEatBerriesGoal(1.2000000476837158D, 12, 1)); + this.goalSelector.addGoal(10, new LeapAtTargetGoal(this, 0.4F)); +- this.goalSelector.addGoal(11, new WaterAvoidingRandomStrollGoal(this, 1.0)); ++ this.goalSelector.addGoal(11, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.goalSelector.addGoal(11, new Fox.FoxSearchForItemsGoal()); + this.goalSelector.addGoal(12, new Fox.FoxLookAtPlayerGoal(this, Player.class, 24.0F)); + this.goalSelector.addGoal(13, new Fox.PerchAndSearchGoal()); +- this.targetSelector +- .addGoal( +- 3, +- new Fox.DefendTrustedTargetGoal( +- LivingEntity.class, false, false, livingEntity -> TRUSTED_TARGET_SELECTOR.test(livingEntity) && !this.trusts(livingEntity.getUUID()) +- ) +- ); ++ this.targetSelector.addGoal(3, new Fox.DefendTrustedTargetGoal(LivingEntity.class, false, false, (entityliving) -> { ++ return Fox.TRUSTED_TARGET_SELECTOR.test(entityliving) && !this.trusts(entityliving.getUUID()); ++ })); + } + + @Override +@@ -198,24 +202,27 @@ + @Override + public void aiStep() { + if (!this.level().isClientSide && this.isAlive() && this.isEffectiveAi()) { +- this.ticksSinceEaten++; +- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.MAINHAND); +- if (this.canEat(itemBySlot)) { ++ ++this.ticksSinceEaten; ++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND); ++ ++ if (this.canEat(itemstack)) { + if (this.ticksSinceEaten > 600) { +- ItemStack itemStack = itemBySlot.finishUsingItem(this.level(), this); +- if (!itemStack.isEmpty()) { +- this.setItemSlot(EquipmentSlot.MAINHAND, itemStack); ++ ItemStack itemstack1 = itemstack.finishUsingItem(this.level(), this); ++ ++ if (!itemstack1.isEmpty()) { ++ this.setItemSlot(EquipmentSlot.MAINHAND, itemstack1); + } + + this.ticksSinceEaten = 0; + } else if (this.ticksSinceEaten > 560 && this.random.nextFloat() < 0.1F) { +- this.playSound(this.getEatingSound(itemBySlot), 1.0F, 1.0F); +- this.level().broadcastEntityEvent(this, (byte)45); ++ this.playSound(this.getEatingSound(itemstack), 1.0F, 1.0F); ++ this.level().broadcastEntityEvent(this, (byte) 45); + } + } + +- LivingEntity target = this.getTarget(); +- if (target == null || !target.isAlive()) { ++ LivingEntity entityliving = this.getTarget(); ++ ++ if (entityliving == null || !entityliving.isAlive()) { + this.setIsCrouching(false); + this.setIsInterested(false); + } +@@ -231,6 +238,7 @@ + if (this.isDefending() && this.random.nextFloat() < 0.05F) { + this.playSound(SoundEvents.FOX_AGGRO, 1.0F, 1.0F); + } ++ + } + + @Override +@@ -245,93 +253,85 @@ + @Override + protected void populateDefaultEquipmentSlots(RandomSource random, DifficultyInstance difficulty) { + if (random.nextFloat() < 0.2F) { +- float randomFloat = random.nextFloat(); +- ItemStack itemStack; +- if (randomFloat < 0.05F) { +- itemStack = new ItemStack(Items.EMERALD); +- } else if (randomFloat < 0.2F) { +- itemStack = new ItemStack(Items.EGG); +- } else if (randomFloat < 0.4F) { +- itemStack = random.nextBoolean() ? new ItemStack(Items.RABBIT_FOOT) : new ItemStack(Items.RABBIT_HIDE); +- } else if (randomFloat < 0.6F) { +- itemStack = new ItemStack(Items.WHEAT); +- } else if (randomFloat < 0.8F) { +- itemStack = new ItemStack(Items.LEATHER); ++ float f = random.nextFloat(); ++ ItemStack itemstack; ++ ++ if (f < 0.05F) { ++ itemstack = new ItemStack(Items.EMERALD); ++ } else if (f < 0.2F) { ++ itemstack = new ItemStack(Items.EGG); ++ } else if (f < 0.4F) { ++ itemstack = random.nextBoolean() ? new ItemStack(Items.RABBIT_FOOT) : new ItemStack(Items.RABBIT_HIDE); ++ } else if (f < 0.6F) { ++ itemstack = new ItemStack(Items.WHEAT); ++ } else if (f < 0.8F) { ++ itemstack = new ItemStack(Items.LEATHER); + } else { +- itemStack = new ItemStack(Items.FEATHER); ++ itemstack = new ItemStack(Items.FEATHER); + } + +- this.setItemSlot(EquipmentSlot.MAINHAND, itemStack); ++ this.setItemSlot(EquipmentSlot.MAINHAND, itemstack); + } ++ + } + + @Override + public void handleEntityEvent(byte id) { + if (id == 45) { +- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.MAINHAND); +- if (!itemBySlot.isEmpty()) { +- for (int i = 0; i < 8; i++) { +- Vec3 vec3 = new Vec3(((double)this.random.nextFloat() - 0.5) * 0.1, Math.random() * 0.1 + 0.1, 0.0) +- .xRot(-this.getXRot() * (float) (Math.PI / 180.0)) +- .yRot(-this.getYRot() * (float) (Math.PI / 180.0)); +- this.level() +- .addParticle( +- new ItemParticleOption(ParticleTypes.ITEM, itemBySlot), +- this.getX() + this.getLookAngle().x / 2.0, +- this.getY(), +- this.getZ() + this.getLookAngle().z / 2.0, +- vec3.x, +- vec3.y + 0.05, +- vec3.z +- ); ++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND); ++ ++ if (!itemstack.isEmpty()) { ++ for (int i = 0; i < 8; ++i) { ++ Vec3 vec3d = (new Vec3(((double) this.random.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, 0.0D)).xRot(-this.getXRot() * 0.017453292F).yRot(-this.getYRot() * 0.017453292F); ++ ++ this.level().addParticle(new ItemParticleOption(ParticleTypes.ITEM, itemstack), this.getX() + this.getLookAngle().x / 2.0D, this.getY(), this.getZ() + this.getLookAngle().z / 2.0D, vec3d.x, vec3d.y + 0.05D, vec3d.z); + } + } + } else { + super.handleEntityEvent(id); + } ++ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes() +- .add(Attributes.MOVEMENT_SPEED, 0.3F) +- .add(Attributes.MAX_HEALTH, 10.0) +- .add(Attributes.FOLLOW_RANGE, 32.0) +- .add(Attributes.ATTACK_DAMAGE, 2.0); ++ return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D).add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.FOLLOW_RANGE, 32.0D).add(Attributes.ATTACK_DAMAGE, 2.0D); + } + + @Nullable + @Override + public Fox getBreedOffspring(ServerLevel level, AgeableMob otherParent) { +- Fox fox = EntityType.FOX.create(level); +- if (fox != null) { +- fox.setVariant(this.random.nextBoolean() ? this.getVariant() : ((Fox)otherParent).getVariant()); ++ Fox entityfox = (Fox) EntityType.FOX.create(level); ++ ++ if (entityfox != null) { ++ entityfox.setVariant(this.random.nextBoolean() ? this.getVariant() : ((Fox) otherParent).getVariant()); + } + +- return fox; ++ return entityfox; + } + +- public static boolean checkFoxSpawnRules(EntityType fox, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) { ++ public static boolean checkFoxSpawnRules(EntityType fox, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { + return level.getBlockState(pos.below()).is(BlockTags.FOXES_SPAWNABLE_ON) && isBrightEnoughToSpawn(level, pos); + } + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- Holder biome = level.getBiome(this.blockPosition()); +- Fox.Type type = Fox.Type.byBiome(biome); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ Holder holder = level.getBiome(this.blockPosition()); ++ Fox.Type entityfox_type = Fox.Type.byBiome(holder); + boolean flag = false; +- if (spawnData instanceof Fox.FoxGroupData foxGroupData) { +- type = foxGroupData.type; +- if (foxGroupData.getGroupSize() >= 2) { ++ ++ if (spawnData instanceof Fox.FoxGroupData) { ++ Fox.FoxGroupData entityfox_i = (Fox.FoxGroupData) spawnData; ++ ++ entityfox_type = entityfox_i.type; ++ if (entityfox_i.getGroupSize() >= 2) { + flag = true; + } + } else { +- spawnData = new Fox.FoxGroupData(type); ++ spawnData = new Fox.FoxGroupData(entityfox_type); + } + +- this.setVariant(type); ++ this.setVariant(entityfox_type); + if (flag) { + this.setAge(-24000); + } +@@ -341,7 +341,7 @@ + } + + this.populateDefaultEquipmentSlots(level.getRandom(), difficulty); +- return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + + private void setTargetGoals() { +@@ -354,10 +354,11 @@ + this.targetSelector.addGoal(6, this.landTargetGoal); + this.targetSelector.addGoal(6, this.turtleEggTargetGoal); + } ++ + } + + @Override +- protected void usePlayerItem(Player player, InteractionHand hand, ItemStack stack) { ++ protected void usePlayerItem(Player player, EnumHand hand, ItemStack stack) { + if (this.isFood(stack)) { + this.playSound(this.getEatingSound(stack), 1.0F, 1.0F); + } +@@ -366,48 +367,52 @@ + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return this.isBaby() ? size.height * 0.85F : 0.4F; + } + + @Override + public Fox.Type getVariant() { +- return Fox.Type.byId(this.entityData.get(DATA_TYPE_ID)); ++ return Fox.Type.byId((Integer) this.entityData.get(Fox.DATA_TYPE_ID)); + } + +- @Override + public void setVariant(Fox.Type variant) { +- this.entityData.set(DATA_TYPE_ID, variant.getId()); ++ this.entityData.set(Fox.DATA_TYPE_ID, variant.getId()); + } + + List getTrustedUUIDs() { + List list = Lists.newArrayList(); +- list.add(this.entityData.get(DATA_TRUSTED_ID_0).orElse(null)); +- list.add(this.entityData.get(DATA_TRUSTED_ID_1).orElse(null)); ++ ++ list.add((UUID) ((Optional) this.entityData.get(Fox.DATA_TRUSTED_ID_0)).orElse((Object) null)); ++ list.add((UUID) ((Optional) this.entityData.get(Fox.DATA_TRUSTED_ID_1)).orElse((Object) null)); + return list; + } + + void addTrustedUUID(@Nullable UUID uuid) { +- if (this.entityData.get(DATA_TRUSTED_ID_0).isPresent()) { +- this.entityData.set(DATA_TRUSTED_ID_1, Optional.ofNullable(uuid)); ++ if (((Optional) this.entityData.get(Fox.DATA_TRUSTED_ID_0)).isPresent()) { ++ this.entityData.set(Fox.DATA_TRUSTED_ID_1, Optional.ofNullable(uuid)); + } else { +- this.entityData.set(DATA_TRUSTED_ID_0, Optional.ofNullable(uuid)); ++ this.entityData.set(Fox.DATA_TRUSTED_ID_0, Optional.ofNullable(uuid)); + } ++ + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- List trustedUUIDs = this.getTrustedUUIDs(); +- ListTag list = new ListTag(); ++ List list = this.getTrustedUUIDs(); ++ ListTag nbttaglist = new ListTag(); ++ Iterator iterator = list.iterator(); + +- for (UUID uUID : trustedUUIDs) { +- if (uUID != null) { +- list.add(NbtUtils.createUUID(uUID)); ++ while (iterator.hasNext()) { ++ UUID uuid = (UUID) iterator.next(); ++ ++ if (uuid != null) { ++ nbttaglist.add(NbtUtils.createUUID(uuid)); + } + } + +- compound.put("Trusted", list); ++ compound.put("Trusted", nbttaglist); + compound.putBoolean("Sleeping", this.isSleeping()); + compound.putString("Type", this.getVariant().getSerializedName()); + compound.putBoolean("Sitting", this.isSitting()); +@@ -417,9 +422,13 @@ + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); ++ ListTag nbttaglist = compound.getList("Trusted", 11); ++ Iterator iterator = nbttaglist.iterator(); + +- for (Tag tag : compound.getList("Trusted", 11)) { +- this.addTrustedUUID(NbtUtils.loadUUID(tag)); ++ while (iterator.hasNext()) { ++ Tag nbtbase = (Tag) iterator.next(); ++ ++ this.addTrustedUUID(NbtUtils.loadUUID(nbtbase)); + } + + this.setSleeping(compound.getBoolean("Sleeping")); +@@ -429,6 +438,7 @@ + if (this.level() instanceof ServerLevel) { + this.setTargetGoals(); + } ++ + } + + public boolean isSitting() { +@@ -460,96 +470,105 @@ + return this.getFlag(32); + } + +- void setSleeping(boolean sleeping) { ++ public void setSleeping(boolean sleeping) { + this.setFlag(32, sleeping); + } + + private void setFlag(int flagId, boolean value) { + if (value) { +- this.entityData.set(DATA_FLAGS_ID, (byte)(this.entityData.get(DATA_FLAGS_ID) | flagId)); ++ this.entityData.set(Fox.DATA_FLAGS_ID, (byte) ((Byte) this.entityData.get(Fox.DATA_FLAGS_ID) | flagId)); + } else { +- this.entityData.set(DATA_FLAGS_ID, (byte)(this.entityData.get(DATA_FLAGS_ID) & ~flagId)); ++ this.entityData.set(Fox.DATA_FLAGS_ID, (byte) ((Byte) this.entityData.get(Fox.DATA_FLAGS_ID) & ~flagId)); + } ++ + } + + private boolean getFlag(int flagId) { +- return (this.entityData.get(DATA_FLAGS_ID) & flagId) != 0; ++ return ((Byte) this.entityData.get(Fox.DATA_FLAGS_ID) & flagId) != 0; + } + + @Override + public boolean canTakeItem(ItemStack itemstack) { +- EquipmentSlot equipmentSlotForItem = Mob.getEquipmentSlotForItem(itemstack); +- return this.getItemBySlot(equipmentSlotForItem).isEmpty() && equipmentSlotForItem == EquipmentSlot.MAINHAND && super.canTakeItem(itemstack); ++ EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(itemstack); ++ ++ return !this.getItemBySlot(enumitemslot).isEmpty() ? false : enumitemslot == EquipmentSlot.MAINHAND && super.canTakeItem(itemstack); + } + + @Override + public boolean canHoldItem(ItemStack stack) { + Item item = stack.getItem(); +- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.MAINHAND); +- return itemBySlot.isEmpty() || this.ticksSinceEaten > 0 && item.isEdible() && !itemBySlot.getItem().isEdible(); ++ ItemStack itemstack1 = this.getItemBySlot(EquipmentSlot.MAINHAND); ++ ++ return itemstack1.isEmpty() || this.ticksSinceEaten > 0 && item.isEdible() && !itemstack1.getItem().isEdible(); + } + + private void spitOutItem(ItemStack stack) { + if (!stack.isEmpty() && !this.level().isClientSide) { +- ItemEntity itemEntity = new ItemEntity( +- this.level(), this.getX() + this.getLookAngle().x, this.getY() + 1.0, this.getZ() + this.getLookAngle().z, stack +- ); +- itemEntity.setPickUpDelay(40); +- itemEntity.setThrower(this); ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX() + this.getLookAngle().x, this.getY() + 1.0D, this.getZ() + this.getLookAngle().z, stack); ++ ++ entityitem.setPickUpDelay(40); ++ entityitem.setThrower(this); + this.playSound(SoundEvents.FOX_SPIT, 1.0F, 1.0F); +- this.level().addFreshEntity(itemEntity); ++ this.level().addFreshEntity(entityitem); + } + } + + private void dropItemStack(ItemStack stack) { +- ItemEntity itemEntity = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), stack); +- this.level().addFreshEntity(itemEntity); ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), stack); ++ ++ this.level().addFreshEntity(entityitem); + } + + @Override + protected void pickUpItem(ItemEntity itemEntity) { +- ItemStack item = itemEntity.getItem(); +- if (this.canHoldItem(item)) { +- int count = item.getCount(); +- if (count > 1) { +- this.dropItemStack(item.split(count - 1)); ++ ItemStack itemstack = itemEntity.getItem(); ++ ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, itemEntity, itemstack.getCount() - 1, !this.canHoldItem(itemstack)).isCancelled()) { // CraftBukkit - call EntityPickupItemEvent ++ itemstack = itemEntity.getItem(); // CraftBukkit - update ItemStack from event ++ int i = itemstack.getCount(); ++ ++ if (i > 1) { ++ this.dropItemStack(itemstack.split(i - 1)); + } + + this.spitOutItem(this.getItemBySlot(EquipmentSlot.MAINHAND)); + this.onItemPickup(itemEntity); +- this.setItemSlot(EquipmentSlot.MAINHAND, item.split(1)); ++ this.setItemSlot(EquipmentSlot.MAINHAND, itemstack.split(1)); + this.setGuaranteedDrop(EquipmentSlot.MAINHAND); +- this.take(itemEntity, item.getCount()); ++ this.take(itemEntity, itemstack.getCount()); + itemEntity.discard(); + this.ticksSinceEaten = 0; + } ++ + } + + @Override + public void tick() { + super.tick(); + if (this.isEffectiveAi()) { +- boolean isInWater = this.isInWater(); +- if (isInWater || this.getTarget() != null || this.level().isThundering()) { ++ boolean flag = this.isInWater(); ++ ++ if (flag || this.getTarget() != null || this.level().isThundering()) { + this.wakeUp(); + } + +- if (isInWater || this.isSleeping()) { ++ if (flag || this.isSleeping()) { + this.setSitting(false); + } + + if (this.isFaceplanted() && this.level().random.nextFloat() < 0.2F) { +- BlockPos blockPos = this.blockPosition(); +- BlockState blockState = this.level().getBlockState(blockPos); +- this.level().levelEvent(2001, blockPos, Block.getId(blockState)); ++ BlockPos blockposition = this.blockPosition(); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); ++ ++ this.level().levelEvent(2001, blockposition, Block.getId(iblockdata)); + } + } + + this.interestedAngleO = this.interestedAngle; + if (this.isInterested()) { +- this.interestedAngle = this.interestedAngle + (1.0F - this.interestedAngle) * 0.4F; ++ this.interestedAngle += (1.0F - this.interestedAngle) * 0.4F; + } else { +- this.interestedAngle = this.interestedAngle + (0.0F - this.interestedAngle) * 0.4F; ++ this.interestedAngle += (0.0F - this.interestedAngle) * 0.4F; + } + + this.crouchAmountO = this.crouchAmount; +@@ -561,6 +580,7 @@ + } else { + this.crouchAmount = 0.0F; + } ++ + } + + @Override +@@ -570,7 +590,7 @@ + + @Override + protected void onOffspringSpawnedFromEgg(Player player, Mob child) { +- ((Fox)child).addTrustedUUID(player.getUUID()); ++ ((Fox) child).addTrustedUUID(player.getUUID()); + } + + public boolean isPouncing() { +@@ -607,7 +627,7 @@ + } + + public float getHeadRollAngle(float partialTick) { +- return Mth.lerp(partialTick, this.interestedAngleO, this.interestedAngle) * 0.11F * (float) Math.PI; ++ return Mth.lerp(partialTick, this.interestedAngleO, this.interestedAngle) * 0.11F * 3.1415927F; + } + + public float getCrouchAmount(float partialTick) { +@@ -647,12 +667,14 @@ + + @Override + public void playAmbientSound() { +- SoundEvent ambientSound = this.getAmbientSound(); +- if (ambientSound == SoundEvents.FOX_SCREECH) { +- this.playSound(ambientSound, 2.0F, this.getVoicePitch()); ++ SoundEvent soundeffect = this.getAmbientSound(); ++ ++ if (soundeffect == SoundEvents.FOX_SCREECH) { ++ this.playSound(soundeffect, 2.0F, this.getVoicePitch()); + } else { + super.playAmbientSound(); + } ++ + } + + @Nullable +@@ -662,9 +684,9 @@ + return SoundEvents.FOX_SLEEP; + } else { + if (!this.level().isDay() && this.random.nextFloat() < 0.1F) { +- List entitiesOfClass = this.level() +- .getEntitiesOfClass(Player.class, this.getBoundingBox().inflate(16.0, 16.0, 16.0), EntitySelector.NO_SPECTATORS); +- if (entitiesOfClass.isEmpty()) { ++ List list = this.level().getEntitiesOfClass(Player.class, this.getBoundingBox().inflate(16.0D, 16.0D, 16.0D), EntitySelector.NO_SPECTATORS); ++ ++ if (list.isEmpty()) { + return SoundEvents.FOX_SCREECH; + } + } +@@ -691,9 +713,10 @@ + + @Override + protected void dropAllDeathLoot(DamageSource damageSource) { +- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.MAINHAND); +- if (!itemBySlot.isEmpty()) { +- this.spawnAtLocation(itemBySlot); ++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND); ++ ++ if (!itemstack.isEmpty()) { ++ this.spawnAtLocation(itemstack); + this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); + } + +@@ -701,22 +724,22 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + -0.0625F * f, -0.25F * f); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + -0.0625F * f, -0.25F * f); + } + + public static boolean isPathClear(Fox fox, LivingEntity livingEntity) { +- double d = livingEntity.getZ() - fox.getZ(); ++ double d0 = livingEntity.getZ() - fox.getZ(); + double d1 = livingEntity.getX() - fox.getX(); +- double d2 = d / d1; +- int i = 6; ++ double d2 = d0 / d1; ++ boolean flag = true; + +- for (int i1 = 0; i1 < 6; i1++) { +- double d3 = d2 == 0.0 ? 0.0 : d * (double)((float)i1 / 6.0F); +- double d4 = d2 == 0.0 ? d1 * (double)((float)i1 / 6.0F) : d3 / d2; ++ for (int i = 0; i < 6; ++i) { ++ double d3 = d2 == 0.0D ? 0.0D : d0 * (double) ((float) i / 6.0F); ++ double d4 = d2 == 0.0D ? d1 * (double) ((float) i / 6.0F) : d3 / d2; + +- for (int i2 = 1; i2 < 4; i2++) { +- if (!fox.level().getBlockState(BlockPos.containing(fox.getX() + d4, fox.getY() + (double)i2, fox.getZ() + d3)).canBeReplaced()) { ++ for (int j = 1; j < 4; ++j) { ++ if (!fox.level().getBlockState(BlockPos.containing(fox.getX() + d4, fox.getY() + (double) j, fox.getZ() + d3)).canBeReplaced()) { + return false; + } + } +@@ -727,60 +750,68 @@ + + @Override + public Vec3 getLeashOffset() { +- return new Vec3(0.0, (double)(0.55F * this.getEyeHeight()), (double)(this.getBbWidth() * 0.4F)); ++ return new Vec3(0.0D, (double) (0.55F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); + } + +- class DefendTrustedTargetGoal extends NearestAttackableTargetGoal { +- @Nullable +- private LivingEntity trustedLastHurtBy; +- @Nullable +- private LivingEntity trustedLastHurt; +- private int timestamp; ++ public class FoxLookControl extends LookControl { + +- public DefendTrustedTargetGoal(Class targetType, boolean mustSee, boolean mustReach, @Nullable Predicate predicate) { +- super(Fox.this, targetType, 10, mustSee, mustReach, predicate); ++ public FoxLookControl() { ++ super(Fox.this); + } + + @Override +- public boolean canUse() { +- if (this.randomInterval > 0 && this.mob.getRandom().nextInt(this.randomInterval) != 0) { +- return false; +- } else { +- for (UUID uUID : Fox.this.getTrustedUUIDs()) { +- if (uUID != null +- && Fox.this.level() instanceof ServerLevel +- && ((ServerLevel)Fox.this.level()).getEntity(uUID) instanceof LivingEntity livingEntity) { +- this.trustedLastHurt = livingEntity; +- this.trustedLastHurtBy = livingEntity.getLastHurtByMob(); +- int lastHurtByMobTimestamp = livingEntity.getLastHurtByMobTimestamp(); +- return lastHurtByMobTimestamp != this.timestamp && this.canAttack(this.trustedLastHurtBy, this.targetConditions); +- } +- } +- +- return false; ++ public void tick() { ++ if (!Fox.this.isSleeping()) { ++ super.tick(); + } ++ + } + + @Override +- public void start() { +- this.setTarget(this.trustedLastHurtBy); +- this.target = this.trustedLastHurtBy; +- if (this.trustedLastHurt != null) { +- this.timestamp = this.trustedLastHurt.getLastHurtByMobTimestamp(); ++ protected boolean resetXRotOnTick() { ++ return !Fox.this.isPouncing() && !Fox.this.isCrouching() && !Fox.this.isInterested() && !Fox.this.isFaceplanted(); ++ } ++ } ++ ++ private class m extends MoveControl { ++ ++ public m() { ++ super(Fox.this); ++ } ++ ++ @Override ++ public void tick() { ++ if (Fox.this.canMove()) { ++ super.tick(); + } + +- Fox.this.playSound(SoundEvents.FOX_AGGRO, 1.0F, 1.0F); +- Fox.this.setDefending(true); +- Fox.this.wakeUp(); ++ } ++ } ++ ++ private class FoxFloatGoal extends FloatGoal { ++ ++ public FoxFloatGoal() { ++ super(Fox.this); ++ } ++ ++ @Override ++ public void start() { + super.start(); ++ Fox.this.clearStates(); + } ++ ++ @Override ++ public boolean canUse() { ++ return Fox.this.isInWater() && Fox.this.getFluidHeight(FluidTags.WATER) > 0.25D || Fox.this.isInLava(); ++ } + } + +- class FaceplantGoal extends Goal { ++ private class FaceplantGoal extends Goal { ++ + int countdown; + + public FaceplantGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.LOOK, Goal.Flag.JUMP, Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.LOOK, Goal.Type.JUMP, Goal.Type.MOVE)); + } + + @Override +@@ -805,505 +836,591 @@ + + @Override + public void tick() { +- this.countdown--; ++ --this.countdown; + } + } + +- public class FoxAlertableEntitiesSelector implements Predicate { +- @Override +- public boolean test(LivingEntity entity) { +- if (entity instanceof Fox) { +- return false; +- } else if (entity instanceof Chicken || entity instanceof Rabbit || entity instanceof Monster) { +- return true; +- } else { +- return entity instanceof TamableAnimal +- ? !((TamableAnimal)entity).isTame() +- : (!(entity instanceof Player) || !entity.isSpectator() && !((Player)entity).isCreative()) +- && !Fox.this.trusts(entity.getUUID()) +- && !entity.isSleeping() +- && !entity.isDiscrete(); +- } +- } +- } ++ private class FoxPanicGoal extends PanicGoal { + +- abstract class FoxBehaviorGoal extends Goal { +- private final TargetingConditions alertableTargeting = TargetingConditions.forCombat() +- .range(12.0) +- .ignoreLineOfSight() +- .selector(Fox.this.new FoxAlertableEntitiesSelector()); +- +- protected boolean hasShelter() { +- BlockPos blockPos = BlockPos.containing(Fox.this.getX(), Fox.this.getBoundingBox().maxY, Fox.this.getZ()); +- return !Fox.this.level().canSeeSky(blockPos) && Fox.this.getWalkTargetValue(blockPos) >= 0.0F; ++ public FoxPanicGoal(double d0) { ++ super(Fox.this, d0); + } + +- protected boolean alertable() { +- return !Fox.this.level() +- .getNearbyEntities(LivingEntity.class, this.alertableTargeting, Fox.this, Fox.this.getBoundingBox().inflate(12.0, 6.0, 12.0)) +- .isEmpty(); ++ @Override ++ public boolean shouldPanic() { ++ return !Fox.this.isDefending() && super.shouldPanic(); + } + } + +- class FoxBreedGoal extends BreedGoal { +- public FoxBreedGoal(double speedModifier) { +- super(Fox.this, speedModifier); ++ private class FoxBreedGoal extends BreedGoal { ++ ++ public FoxBreedGoal(double d0) { ++ super(Fox.this, d0); + } + + @Override + public void start() { +- ((Fox)this.animal).clearStates(); +- ((Fox)this.partner).clearStates(); ++ ((Fox) this.animal).clearStates(); ++ ((Fox) this.partner).clearStates(); + super.start(); + } + + @Override + protected void breed() { +- ServerLevel serverLevel = (ServerLevel)this.level; +- Fox fox = (Fox)this.animal.getBreedOffspring(serverLevel, this.partner); +- if (fox != null) { +- ServerPlayer loveCause = this.animal.getLoveCause(); +- ServerPlayer loveCause1 = this.partner.getLoveCause(); +- ServerPlayer serverPlayer = loveCause; +- if (loveCause != null) { +- fox.addTrustedUUID(loveCause.getUUID()); ++ ServerLevel worldserver = (ServerLevel) this.level; ++ Fox entityfox = (Fox) this.animal.getBreedOffspring(worldserver, this.partner); ++ ++ if (entityfox != null) { ++ ServerPlayer entityplayer = this.animal.getLoveCause(); ++ ServerPlayer entityplayer1 = this.partner.getLoveCause(); ++ ServerPlayer entityplayer2 = entityplayer; ++ ++ if (entityplayer != null) { ++ entityfox.addTrustedUUID(entityplayer.getUUID()); + } else { +- serverPlayer = loveCause1; ++ entityplayer2 = entityplayer1; + } + +- if (loveCause1 != null && loveCause != loveCause1) { +- fox.addTrustedUUID(loveCause1.getUUID()); ++ if (entityplayer1 != null && entityplayer != entityplayer1) { ++ entityfox.addTrustedUUID(entityplayer1.getUUID()); + } ++ // CraftBukkit start - call EntityBreedEvent ++ entityfox.setAge(-24000); ++ entityfox.moveTo(this.animal.getX(), this.animal.getY(), this.animal.getZ(), 0.0F, 0.0F); ++ int experience = this.animal.getRandom().nextInt(7) + 1; ++ org.bukkit.event.entity.EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(entityfox, animal, partner, entityplayer, this.animal.breedItem, experience); ++ if (entityBreedEvent.isCancelled()) { ++ return; ++ } ++ experience = entityBreedEvent.getExperience(); ++ // CraftBukkit end + +- if (serverPlayer != null) { +- serverPlayer.awardStat(Stats.ANIMALS_BRED); +- CriteriaTriggers.BRED_ANIMALS.trigger(serverPlayer, this.animal, this.partner, fox); ++ if (entityplayer2 != null) { ++ entityplayer2.awardStat(Stats.ANIMALS_BRED); ++ CriteriaTriggers.BRED_ANIMALS.trigger(entityplayer2, this.animal, this.partner, entityfox); + } + + this.animal.setAge(6000); + this.partner.setAge(6000); + this.animal.resetLove(); + this.partner.resetLove(); +- fox.setAge(-24000); +- fox.moveTo(this.animal.getX(), this.animal.getY(), this.animal.getZ(), 0.0F, 0.0F); +- serverLevel.addFreshEntityWithPassengers(fox); +- this.level.broadcastEntityEvent(this.animal, (byte)18); ++ worldserver.addFreshEntityWithPassengers(entityfox, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - added SpawnReason ++ this.level.broadcastEntityEvent(this.animal, (byte) 18); + if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +- this.level +- .addFreshEntity( +- new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), this.animal.getRandom().nextInt(7) + 1) +- ); ++ // CraftBukkit start - use event experience ++ if (experience > 0) { ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience)); ++ } ++ // CraftBukkit end + } ++ + } + } + } + +- public class FoxEatBerriesGoal extends MoveToBlockGoal { +- private static final int WAIT_TICKS = 40; +- protected int ticksWaited; ++ private class StalkPreyGoal extends Goal { + +- public FoxEatBerriesGoal(double speedModifier, int searchRange, int verticalSearchRange) { +- super(Fox.this, speedModifier, searchRange, verticalSearchRange); ++ public StalkPreyGoal() { ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + } + + @Override +- public double acceptedDistance() { +- return 2.0; ++ public boolean canUse() { ++ if (Fox.this.isSleeping()) { ++ return false; ++ } else { ++ LivingEntity entityliving = Fox.this.getTarget(); ++ ++ return entityliving != null && entityliving.isAlive() && Fox.STALKABLE_PREY.test(entityliving) && Fox.this.distanceToSqr((Entity) entityliving) > 36.0D && !Fox.this.isCrouching() && !Fox.this.isInterested() && !Fox.this.jumping; ++ } + } + + @Override +- public boolean shouldRecalculatePath() { +- return this.tryTicks % 100 == 0; ++ public void start() { ++ Fox.this.setSitting(false); ++ Fox.this.setFaceplanted(false); + } + + @Override +- protected boolean isValidTarget(LevelReader level, BlockPos pos) { +- BlockState blockState = level.getBlockState(pos); +- return blockState.is(Blocks.SWEET_BERRY_BUSH) && blockState.getValue(SweetBerryBushBlock.AGE) >= 2 || CaveVines.hasGlowBerries(blockState); ++ public void stop() { ++ LivingEntity entityliving = Fox.this.getTarget(); ++ ++ if (entityliving != null && Fox.isPathClear(Fox.this, entityliving)) { ++ Fox.this.setIsInterested(true); ++ Fox.this.setIsCrouching(true); ++ Fox.this.getNavigation().stop(); ++ Fox.this.getLookControl().setLookAt(entityliving, (float) Fox.this.getMaxHeadYRot(), (float) Fox.this.getMaxHeadXRot()); ++ } else { ++ Fox.this.setIsInterested(false); ++ Fox.this.setIsCrouching(false); ++ } ++ + } + + @Override + public void tick() { +- if (this.isReachedTarget()) { +- if (this.ticksWaited >= 40) { +- this.onReachedTarget(); ++ LivingEntity entityliving = Fox.this.getTarget(); ++ ++ if (entityliving != null) { ++ Fox.this.getLookControl().setLookAt(entityliving, (float) Fox.this.getMaxHeadYRot(), (float) Fox.this.getMaxHeadXRot()); ++ if (Fox.this.distanceToSqr((Entity) entityliving) <= 36.0D) { ++ Fox.this.setIsInterested(true); ++ Fox.this.setIsCrouching(true); ++ Fox.this.getNavigation().stop(); + } else { +- this.ticksWaited++; ++ Fox.this.getNavigation().moveTo((Entity) entityliving, 1.5D); + } +- } else if (!this.isReachedTarget() && Fox.this.random.nextFloat() < 0.05F) { +- Fox.this.playSound(SoundEvents.FOX_SNIFF, 1.0F, 1.0F); +- } + +- super.tick(); ++ } + } ++ } + +- protected void onReachedTarget() { +- if (Fox.this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- BlockState blockState = Fox.this.level().getBlockState(this.blockPos); +- if (blockState.is(Blocks.SWEET_BERRY_BUSH)) { +- this.pickSweetBerries(blockState); +- } else if (CaveVines.hasGlowBerries(blockState)) { +- this.pickGlowBerry(blockState); ++ public class FoxPounceGoal extends PathfinderGoalWaterJumpAbstract { ++ ++ public FoxPounceGoal() {} ++ ++ @Override ++ public boolean canUse() { ++ if (!Fox.this.isFullyCrouched()) { ++ return false; ++ } else { ++ LivingEntity entityliving = Fox.this.getTarget(); ++ ++ if (entityliving != null && entityliving.isAlive()) { ++ if (entityliving.getMotionDirection() != entityliving.getDirection()) { ++ return false; ++ } else { ++ boolean flag = Fox.isPathClear(Fox.this, entityliving); ++ ++ if (!flag) { ++ Fox.this.getNavigation().createPath((Entity) entityliving, 0); ++ Fox.this.setIsCrouching(false); ++ Fox.this.setIsInterested(false); ++ } ++ ++ return flag; ++ } ++ } else { ++ return false; + } + } + } + +- private void pickGlowBerry(BlockState state) { +- CaveVines.use(Fox.this, state, Fox.this.level(), this.blockPos); +- } ++ @Override ++ public boolean canContinueToUse() { ++ LivingEntity entityliving = Fox.this.getTarget(); + +- private void pickSweetBerries(BlockState state) { +- int i = state.getValue(SweetBerryBushBlock.AGE); +- state.setValue(SweetBerryBushBlock.AGE, Integer.valueOf(1)); +- int i1 = 1 + Fox.this.level().random.nextInt(2) + (i == 3 ? 1 : 0); +- ItemStack itemBySlot = Fox.this.getItemBySlot(EquipmentSlot.MAINHAND); +- if (itemBySlot.isEmpty()) { +- Fox.this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.SWEET_BERRIES)); +- i1--; +- } ++ if (entityliving != null && entityliving.isAlive()) { ++ double d0 = Fox.this.getDeltaMovement().y; + +- if (i1 > 0) { +- Block.popResource(Fox.this.level(), this.blockPos, new ItemStack(Items.SWEET_BERRIES, i1)); ++ return (d0 * d0 >= 0.05000000074505806D || Math.abs(Fox.this.getXRot()) >= 15.0F || !Fox.this.onGround()) && !Fox.this.isFaceplanted(); ++ } else { ++ return false; + } +- +- Fox.this.playSound(SoundEvents.SWEET_BERRY_BUSH_PICK_BERRIES, 1.0F, 1.0F); +- Fox.this.level().setBlock(this.blockPos, state.setValue(SweetBerryBushBlock.AGE, Integer.valueOf(1)), 2); +- Fox.this.level().gameEvent(GameEvent.BLOCK_CHANGE, this.blockPos, GameEvent.Context.of(Fox.this)); + } + + @Override +- public boolean canUse() { +- return !Fox.this.isSleeping() && super.canUse(); ++ public boolean isInterruptable() { ++ return false; + } + + @Override + public void start() { +- this.ticksWaited = 0; +- Fox.this.setSitting(false); +- super.start(); +- } +- } ++ Fox.this.setJumping(true); ++ Fox.this.setIsPouncing(true); ++ Fox.this.setIsInterested(false); ++ LivingEntity entityliving = Fox.this.getTarget(); + +- class FoxFloatGoal extends FloatGoal { +- public FoxFloatGoal() { +- super(Fox.this); ++ if (entityliving != null) { ++ Fox.this.getLookControl().setLookAt(entityliving, 60.0F, 30.0F); ++ Vec3 vec3d = (new Vec3(entityliving.getX() - Fox.this.getX(), entityliving.getY() - Fox.this.getY(), entityliving.getZ() - Fox.this.getZ())).normalize(); ++ ++ Fox.this.setDeltaMovement(Fox.this.getDeltaMovement().add(vec3d.x * 0.8D, 0.9D, vec3d.z * 0.8D)); ++ } ++ ++ Fox.this.getNavigation().stop(); + } + + @Override +- public void start() { +- super.start(); +- Fox.this.clearStates(); ++ public void stop() { ++ Fox.this.setIsCrouching(false); ++ Fox.this.crouchAmount = 0.0F; ++ Fox.this.crouchAmountO = 0.0F; ++ Fox.this.setIsInterested(false); ++ Fox.this.setIsPouncing(false); + } + + @Override +- public boolean canUse() { +- return Fox.this.isInWater() && Fox.this.getFluidHeight(FluidTags.WATER) > 0.25 || Fox.this.isInLava(); ++ public void tick() { ++ LivingEntity entityliving = Fox.this.getTarget(); ++ ++ if (entityliving != null) { ++ Fox.this.getLookControl().setLookAt(entityliving, 60.0F, 30.0F); ++ } ++ ++ if (!Fox.this.isFaceplanted()) { ++ Vec3 vec3d = Fox.this.getDeltaMovement(); ++ ++ if (vec3d.y * vec3d.y < 0.029999999329447746D && Fox.this.getXRot() != 0.0F) { ++ Fox.this.setXRot(Mth.rotLerp(0.2F, Fox.this.getXRot(), 0.0F)); ++ } else { ++ double d0 = vec3d.horizontalDistance(); ++ double d1 = Math.signum(-vec3d.y) * Math.acos(d0 / vec3d.length()) * 57.2957763671875D; ++ ++ Fox.this.setXRot((float) d1); ++ } ++ } ++ ++ if (entityliving != null && Fox.this.distanceTo(entityliving) <= 2.0F) { ++ Fox.this.doHurtTarget(entityliving); ++ } else if (Fox.this.getXRot() > 0.0F && Fox.this.onGround() && (float) Fox.this.getDeltaMovement().y != 0.0F && Fox.this.level().getBlockState(Fox.this.blockPosition()).is(Blocks.SNOW)) { ++ Fox.this.setXRot(60.0F); ++ Fox.this.setTarget((LivingEntity) null); ++ Fox.this.setFaceplanted(true); ++ } ++ + } + } + +- class FoxFollowParentGoal extends FollowParentGoal { +- private final Fox fox; ++ private class SeekShelterGoal extends FleeSunGoal { + +- public FoxFollowParentGoal(Fox animal, double speedModifier) { +- super(animal, speedModifier); +- this.fox = animal; ++ private int interval = reducedTickDelay(100); ++ ++ public SeekShelterGoal(double d0) { ++ super(Fox.this, d0); + } + + @Override + public boolean canUse() { +- return !this.fox.isDefending() && super.canUse(); +- } ++ if (!Fox.this.isSleeping() && this.mob.getTarget() == null) { ++ if (Fox.this.level().isThundering() && Fox.this.level().canSeeSky(this.mob.blockPosition())) { ++ return this.setWantedPos(); ++ } else if (this.interval > 0) { ++ --this.interval; ++ return false; ++ } else { ++ this.interval = 100; ++ BlockPos blockposition = this.mob.blockPosition(); + +- @Override +- public boolean canContinueToUse() { +- return !this.fox.isDefending() && super.canContinueToUse(); ++ return Fox.this.level().isDay() && Fox.this.level().canSeeSky(blockposition) && !((ServerLevel) Fox.this.level()).isVillage(blockposition) && this.setWantedPos(); ++ } ++ } else { ++ return false; ++ } + } + + @Override + public void start() { +- this.fox.clearStates(); ++ Fox.this.clearStates(); + super.start(); + } + } + +- public static class FoxGroupData extends AgeableMob.AgeableMobGroupData { +- public final Fox.Type type; ++ private class FoxMeleeAttackGoal extends MeleeAttackGoal { + +- public FoxGroupData(Fox.Type type) { +- super(false); +- this.type = type; ++ public FoxMeleeAttackGoal(double d0, boolean flag) { ++ super(Fox.this, d0, flag); + } +- } + +- class FoxLookAtPlayerGoal extends LookAtPlayerGoal { +- public FoxLookAtPlayerGoal(Mob mob, Class lookAtType, float lookDistance) { +- super(mob, lookAtType, lookDistance); ++ @Override ++ protected void checkAndPerformAttack(LivingEntity entityliving) { ++ if (this.canPerformAttack(entityliving)) { ++ this.resetAttackCooldown(); ++ this.mob.doHurtTarget(entityliving); ++ Fox.this.playSound(SoundEvents.FOX_BITE, 1.0F, 1.0F); ++ } ++ + } + + @Override +- public boolean canUse() { +- return super.canUse() && !Fox.this.isFaceplanted() && !Fox.this.isInterested(); ++ public void start() { ++ Fox.this.setIsInterested(false); ++ super.start(); + } + + @Override +- public boolean canContinueToUse() { +- return super.canContinueToUse() && !Fox.this.isFaceplanted() && !Fox.this.isInterested(); ++ public boolean canUse() { ++ return !Fox.this.isSitting() && !Fox.this.isSleeping() && !Fox.this.isCrouching() && !Fox.this.isFaceplanted() && super.canUse(); + } + } + +- public class FoxLookControl extends LookControl { +- public FoxLookControl() { +- super(Fox.this); ++ private class SleepGoal extends Fox.d { ++ ++ private static final int WAIT_TIME_BEFORE_SLEEP = reducedTickDelay(140); ++ private int countdown; ++ ++ public SleepGoal() { ++ super(); ++ this.countdown = Fox.this.random.nextInt(Fox.SleepGoal.WAIT_TIME_BEFORE_SLEEP); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK, Goal.Type.JUMP)); + } + + @Override +- public void tick() { +- if (!Fox.this.isSleeping()) { +- super.tick(); +- } ++ public boolean canUse() { ++ return Fox.this.xxa == 0.0F && Fox.this.yya == 0.0F && Fox.this.zza == 0.0F ? this.canSleep() || Fox.this.isSleeping() : false; + } + + @Override +- protected boolean resetXRotOnTick() { +- return !Fox.this.isPouncing() && !Fox.this.isCrouching() && !Fox.this.isInterested() && !Fox.this.isFaceplanted(); ++ public boolean canContinueToUse() { ++ return this.canSleep(); + } +- } + +- class FoxMeleeAttackGoal extends MeleeAttackGoal { +- public FoxMeleeAttackGoal(double speedModifier, boolean followingTargetEvenIfNotSeen) { +- super(Fox.this, speedModifier, followingTargetEvenIfNotSeen); ++ private boolean canSleep() { ++ if (this.countdown > 0) { ++ --this.countdown; ++ return false; ++ } else { ++ return Fox.this.level().isDay() && this.hasShelter() && !this.alertable() && !Fox.this.isInPowderSnow; ++ } + } + + @Override +- protected void checkAndPerformAttack(LivingEntity livingEntity) { +- if (this.canPerformAttack(livingEntity)) { +- this.resetAttackCooldown(); +- this.mob.doHurtTarget(livingEntity); +- Fox.this.playSound(SoundEvents.FOX_BITE, 1.0F, 1.0F); +- } ++ public void stop() { ++ this.countdown = Fox.this.random.nextInt(Fox.SleepGoal.WAIT_TIME_BEFORE_SLEEP); ++ Fox.this.clearStates(); + } + + @Override + public void start() { ++ Fox.this.setSitting(false); ++ Fox.this.setIsCrouching(false); + Fox.this.setIsInterested(false); +- super.start(); ++ Fox.this.setJumping(false); ++ Fox.this.setSleeping(true); ++ Fox.this.getNavigation().stop(); ++ Fox.this.getMoveControl().setWantedPosition(Fox.this.getX(), Fox.this.getY(), Fox.this.getZ(), 0.0D); + } ++ } + ++ private class FoxFollowParentGoal extends FollowParentGoal { ++ ++ private final Fox fox; ++ ++ public FoxFollowParentGoal(Fox entityfox, double d0) { ++ super(entityfox, d0); ++ this.fox = entityfox; ++ } ++ + @Override + public boolean canUse() { +- return !Fox.this.isSitting() && !Fox.this.isSleeping() && !Fox.this.isCrouching() && !Fox.this.isFaceplanted() && super.canUse(); ++ return !this.fox.isDefending() && super.canUse(); + } +- } + +- class FoxMoveControl extends MoveControl { +- public FoxMoveControl() { +- super(Fox.this); ++ @Override ++ public boolean canContinueToUse() { ++ return !this.fox.isDefending() && super.canContinueToUse(); + } + + @Override +- public void tick() { +- if (Fox.this.canMove()) { +- super.tick(); +- } ++ public void start() { ++ this.fox.clearStates(); ++ super.start(); + } + } + +- class FoxPanicGoal extends PanicGoal { +- public FoxPanicGoal(double speedModifier) { +- super(Fox.this, speedModifier); ++ private class FoxStrollThroughVillageGoal extends StrollThroughVillageGoal { ++ ++ public FoxStrollThroughVillageGoal(int i, int j) { ++ super(Fox.this, j); + } + + @Override +- public boolean shouldPanic() { +- return !Fox.this.isDefending() && super.shouldPanic(); ++ public void start() { ++ Fox.this.clearStates(); ++ super.start(); + } +- } + +- public class FoxPounceGoal extends JumpGoal { + @Override + public boolean canUse() { +- if (!Fox.this.isFullyCrouched()) { +- return false; +- } else { +- LivingEntity target = Fox.this.getTarget(); +- if (target != null && target.isAlive()) { +- if (target.getMotionDirection() != target.getDirection()) { +- return false; +- } else { +- boolean isPathClear = Fox.isPathClear(Fox.this, target); +- if (!isPathClear) { +- Fox.this.getNavigation().createPath(target, 0); +- Fox.this.setIsCrouching(false); +- Fox.this.setIsInterested(false); +- } +- +- return isPathClear; +- } +- } else { +- return false; +- } +- } ++ return super.canUse() && this.canFoxMove(); + } + + @Override + public boolean canContinueToUse() { +- LivingEntity target = Fox.this.getTarget(); +- if (target != null && target.isAlive()) { +- double d = Fox.this.getDeltaMovement().y; +- return (!(d * d < 0.05F) || !(Math.abs(Fox.this.getXRot()) < 15.0F) || !Fox.this.onGround()) && !Fox.this.isFaceplanted(); +- } else { +- return false; +- } ++ return super.canContinueToUse() && this.canFoxMove(); + } + +- @Override +- public boolean isInterruptable() { +- return false; ++ private boolean canFoxMove() { ++ return !Fox.this.isSleeping() && !Fox.this.isSitting() && !Fox.this.isDefending() && Fox.this.getTarget() == null; + } ++ } + ++ public class FoxEatBerriesGoal extends MoveToBlockGoal { ++ ++ private static final int WAIT_TICKS = 40; ++ protected int ticksWaited; ++ ++ public FoxEatBerriesGoal(double d0, int i, int j) { ++ super(Fox.this, d0, i, j); ++ } ++ + @Override +- public void start() { +- Fox.this.setJumping(true); +- Fox.this.setIsPouncing(true); +- Fox.this.setIsInterested(false); +- LivingEntity target = Fox.this.getTarget(); +- if (target != null) { +- Fox.this.getLookControl().setLookAt(target, 60.0F, 30.0F); +- Vec3 vec3 = new Vec3(target.getX() - Fox.this.getX(), target.getY() - Fox.this.getY(), target.getZ() - Fox.this.getZ()).normalize(); +- Fox.this.setDeltaMovement(Fox.this.getDeltaMovement().add(vec3.x * 0.8, 0.9, vec3.z * 0.8)); +- } ++ public double acceptedDistance() { ++ return 2.0D; ++ } + +- Fox.this.getNavigation().stop(); ++ @Override ++ public boolean shouldRecalculatePath() { ++ return this.tryTicks % 100 == 0; + } + + @Override +- public void stop() { +- Fox.this.setIsCrouching(false); +- Fox.this.crouchAmount = 0.0F; +- Fox.this.crouchAmountO = 0.0F; +- Fox.this.setIsInterested(false); +- Fox.this.setIsPouncing(false); ++ protected boolean isValidTarget(LevelReader level, BlockPos pos) { ++ IBlockData iblockdata = level.getBlockState(pos); ++ ++ return iblockdata.is(Blocks.SWEET_BERRY_BUSH) && (Integer) iblockdata.getValue(SweetBerryBushBlock.AGE) >= 2 || CaveVines.hasGlowBerries(iblockdata); + } + + @Override + public void tick() { +- LivingEntity target = Fox.this.getTarget(); +- if (target != null) { +- Fox.this.getLookControl().setLookAt(target, 60.0F, 30.0F); ++ if (this.isReachedTarget()) { ++ if (this.ticksWaited >= 40) { ++ this.onReachedTarget(); ++ } else { ++ ++this.ticksWaited; ++ } ++ } else if (!this.isReachedTarget() && Fox.this.random.nextFloat() < 0.05F) { ++ Fox.this.playSound(SoundEvents.FOX_SNIFF, 1.0F, 1.0F); + } + +- if (!Fox.this.isFaceplanted()) { +- Vec3 deltaMovement = Fox.this.getDeltaMovement(); +- if (deltaMovement.y * deltaMovement.y < 0.03F && Fox.this.getXRot() != 0.0F) { +- Fox.this.setXRot(Mth.rotLerp(0.2F, Fox.this.getXRot(), 0.0F)); +- } else { +- double d = deltaMovement.horizontalDistance(); +- double d1 = Math.signum(-deltaMovement.y) * Math.acos(d / deltaMovement.length()) * 180.0F / (float)Math.PI; +- Fox.this.setXRot((float)d1); ++ super.tick(); ++ } ++ ++ protected void onReachedTarget() { ++ if (Fox.this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ IBlockData iblockdata = Fox.this.level().getBlockState(this.blockPos); ++ ++ if (iblockdata.is(Blocks.SWEET_BERRY_BUSH)) { ++ this.pickSweetBerries(iblockdata); ++ } else if (CaveVines.hasGlowBerries(iblockdata)) { ++ this.pickGlowBerry(iblockdata); + } ++ + } ++ } + +- if (target != null && Fox.this.distanceTo(target) <= 2.0F) { +- Fox.this.doHurtTarget(target); +- } else if (Fox.this.getXRot() > 0.0F +- && Fox.this.onGround() +- && (float)Fox.this.getDeltaMovement().y != 0.0F +- && Fox.this.level().getBlockState(Fox.this.blockPosition()).is(Blocks.SNOW)) { +- Fox.this.setXRot(60.0F); +- Fox.this.setTarget(null); +- Fox.this.setFaceplanted(true); ++ private void pickGlowBerry(IBlockData state) { ++ CaveVines.use(Fox.this, state, Fox.this.level(), this.blockPos); ++ } ++ ++ private void pickSweetBerries(IBlockData state) { ++ int i = (Integer) state.getValue(SweetBerryBushBlock.AGE); ++ ++ state.setValue(SweetBerryBushBlock.AGE, 1); ++ // CraftBukkit start - call EntityChangeBlockEvent ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(Fox.this, this.blockPos, state.setValue(SweetBerryBushBlock.AGE, 1))) { ++ return; + } ++ // CraftBukkit end ++ int j = 1 + Fox.this.level().random.nextInt(2) + (i == 3 ? 1 : 0); ++ ItemStack itemstack = Fox.this.getItemBySlot(EquipmentSlot.MAINHAND); ++ ++ if (itemstack.isEmpty()) { ++ Fox.this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.SWEET_BERRIES)); ++ --j; ++ } ++ ++ if (j > 0) { ++ Block.popResource(Fox.this.level(), this.blockPos, new ItemStack(Items.SWEET_BERRIES, j)); ++ } ++ ++ Fox.this.playSound(SoundEvents.SWEET_BERRY_BUSH_PICK_BERRIES, 1.0F, 1.0F); ++ Fox.this.level().setBlock(this.blockPos, (IBlockData) state.setValue(SweetBerryBushBlock.AGE, 1), 2); ++ Fox.this.level().gameEvent(GameEvent.BLOCK_CHANGE, this.blockPos, GameEvent.Context.of((Entity) Fox.this)); + } ++ ++ @Override ++ public boolean canUse() { ++ return !Fox.this.isSleeping() && super.canUse(); ++ } ++ ++ @Override ++ public void start() { ++ this.ticksWaited = 0; ++ Fox.this.setSitting(false); ++ super.start(); ++ } + } + +- class FoxSearchForItemsGoal extends Goal { ++ private class FoxSearchForItemsGoal extends Goal { ++ + public FoxSearchForItemsGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override + public boolean canUse() { + if (!Fox.this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty()) { + return false; +- } else if (Fox.this.getTarget() != null || Fox.this.getLastHurtByMob() != null) { +- return false; +- } else if (!Fox.this.canMove()) { +- return false; +- } else if (Fox.this.getRandom().nextInt(reducedTickDelay(10)) != 0) { +- return false; ++ } else if (Fox.this.getTarget() == null && Fox.this.getLastHurtByMob() == null) { ++ if (!Fox.this.canMove()) { ++ return false; ++ } else if (Fox.this.getRandom().nextInt(reducedTickDelay(10)) != 0) { ++ return false; ++ } else { ++ List list = Fox.this.level().getEntitiesOfClass(ItemEntity.class, Fox.this.getBoundingBox().inflate(8.0D, 8.0D, 8.0D), Fox.ALLOWED_ITEMS); ++ ++ return !list.isEmpty() && Fox.this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty(); ++ } + } else { +- List entitiesOfClass = Fox.this.level() +- .getEntitiesOfClass(ItemEntity.class, Fox.this.getBoundingBox().inflate(8.0, 8.0, 8.0), Fox.ALLOWED_ITEMS); +- return !entitiesOfClass.isEmpty() && Fox.this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty(); ++ return false; + } + } + + @Override + public void tick() { +- List entitiesOfClass = Fox.this.level() +- .getEntitiesOfClass(ItemEntity.class, Fox.this.getBoundingBox().inflate(8.0, 8.0, 8.0), Fox.ALLOWED_ITEMS); +- ItemStack itemBySlot = Fox.this.getItemBySlot(EquipmentSlot.MAINHAND); +- if (itemBySlot.isEmpty() && !entitiesOfClass.isEmpty()) { +- Fox.this.getNavigation().moveTo(entitiesOfClass.get(0), 1.2F); ++ List list = Fox.this.level().getEntitiesOfClass(ItemEntity.class, Fox.this.getBoundingBox().inflate(8.0D, 8.0D, 8.0D), Fox.ALLOWED_ITEMS); ++ ItemStack itemstack = Fox.this.getItemBySlot(EquipmentSlot.MAINHAND); ++ ++ if (itemstack.isEmpty() && !list.isEmpty()) { ++ Fox.this.getNavigation().moveTo((Entity) list.get(0), 1.2000000476837158D); + } ++ + } + + @Override + public void start() { +- List entitiesOfClass = Fox.this.level() +- .getEntitiesOfClass(ItemEntity.class, Fox.this.getBoundingBox().inflate(8.0, 8.0, 8.0), Fox.ALLOWED_ITEMS); +- if (!entitiesOfClass.isEmpty()) { +- Fox.this.getNavigation().moveTo(entitiesOfClass.get(0), 1.2F); ++ List list = Fox.this.level().getEntitiesOfClass(ItemEntity.class, Fox.this.getBoundingBox().inflate(8.0D, 8.0D, 8.0D), Fox.ALLOWED_ITEMS); ++ ++ if (!list.isEmpty()) { ++ Fox.this.getNavigation().moveTo((Entity) list.get(0), 1.2000000476837158D); + } ++ + } + } + +- class FoxStrollThroughVillageGoal extends StrollThroughVillageGoal { +- public FoxStrollThroughVillageGoal(int unused32, int interval) { +- super(Fox.this, interval); +- } ++ private class FoxLookAtPlayerGoal extends LookAtPlayerGoal { + +- @Override +- public void start() { +- Fox.this.clearStates(); +- super.start(); ++ public FoxLookAtPlayerGoal(Mob mob, Class lookAtType, float lookDistance) { ++ super(mob, lookAtType, lookDistance); + } + + @Override + public boolean canUse() { +- return super.canUse() && this.canFoxMove(); ++ return super.canUse() && !Fox.this.isFaceplanted() && !Fox.this.isInterested(); + } + + @Override + public boolean canContinueToUse() { +- return super.canContinueToUse() && this.canFoxMove(); ++ return super.canContinueToUse() && !Fox.this.isFaceplanted() && !Fox.this.isInterested(); + } +- +- private boolean canFoxMove() { +- return !Fox.this.isSleeping() && !Fox.this.isSitting() && !Fox.this.isDefending() && Fox.this.getTarget() == null; +- } + } + +- class PerchAndSearchGoal extends Fox.FoxBehaviorGoal { ++ private class PerchAndSearchGoal extends Fox.d { ++ + private double relX; + private double relZ; + private int lookTime; + private int looksRemaining; + + public PerchAndSearchGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ super(); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + } + + @Override + public boolean canUse() { +- return Fox.this.getLastHurtByMob() == null +- && Fox.this.getRandom().nextFloat() < 0.02F +- && !Fox.this.isSleeping() +- && Fox.this.getTarget() == null +- && Fox.this.getNavigation().isDone() +- && !this.alertable() +- && !Fox.this.isPouncing() +- && !Fox.this.isCrouching(); ++ return Fox.this.getLastHurtByMob() == null && Fox.this.getRandom().nextFloat() < 0.02F && !Fox.this.isSleeping() && Fox.this.getTarget() == null && Fox.this.getNavigation().isDone() && !this.alertable() && !Fox.this.isPouncing() && !Fox.this.isCrouching(); + } + + @Override +@@ -1326,179 +1443,92 @@ + + @Override + public void tick() { +- this.lookTime--; ++ --this.lookTime; + if (this.lookTime <= 0) { +- this.looksRemaining--; ++ --this.looksRemaining; + this.resetLook(); + } + +- Fox.this.getLookControl() +- .setLookAt( +- Fox.this.getX() + this.relX, +- Fox.this.getEyeY(), +- Fox.this.getZ() + this.relZ, +- (float)Fox.this.getMaxHeadYRot(), +- (float)Fox.this.getMaxHeadXRot() +- ); ++ Fox.this.getLookControl().setLookAt(Fox.this.getX() + this.relX, Fox.this.getEyeY(), Fox.this.getZ() + this.relZ, (float) Fox.this.getMaxHeadYRot(), (float) Fox.this.getMaxHeadXRot()); + } + + private void resetLook() { +- double d = (Math.PI * 2) * Fox.this.getRandom().nextDouble(); +- this.relX = Math.cos(d); +- this.relZ = Math.sin(d); ++ double d0 = 6.283185307179586D * Fox.this.getRandom().nextDouble(); ++ ++ this.relX = Math.cos(d0); ++ this.relZ = Math.sin(d0); + this.lookTime = this.adjustedTickDelay(80 + Fox.this.getRandom().nextInt(20)); + } + } + +- class SeekShelterGoal extends FleeSunGoal { +- private int interval = reducedTickDelay(100); ++ private class DefendTrustedTargetGoal extends NearestAttackableTargetGoal { + +- public SeekShelterGoal(double speedModifier) { +- super(Fox.this, speedModifier); ++ @Nullable ++ private LivingEntity trustedLastHurtBy; ++ @Nullable ++ private LivingEntity trustedLastHurt; ++ private int timestamp; ++ ++ public DefendTrustedTargetGoal(Class oclass, boolean flag, boolean flag1, @Nullable Predicate predicate) { // CraftBukkit - decompile error ++ super(Fox.this, oclass, 10, flag, flag1, predicate); + } + + @Override + public boolean canUse() { +- if (!Fox.this.isSleeping() && this.mob.getTarget() == null) { +- if (Fox.this.level().isThundering() && Fox.this.level().canSeeSky(this.mob.blockPosition())) { +- return this.setWantedPos(); +- } else if (this.interval > 0) { +- this.interval--; +- return false; +- } else { +- this.interval = 100; +- BlockPos blockPos = this.mob.blockPosition(); +- return Fox.this.level().isDay() +- && Fox.this.level().canSeeSky(blockPos) +- && !((ServerLevel)Fox.this.level()).isVillage(blockPos) +- && this.setWantedPos(); +- } +- } else { ++ if (this.randomInterval > 0 && this.mob.getRandom().nextInt(this.randomInterval) != 0) { + return false; +- } +- } ++ } else { ++ Iterator iterator = Fox.this.getTrustedUUIDs().iterator(); + +- @Override +- public void start() { +- Fox.this.clearStates(); +- super.start(); +- } +- } ++ while (iterator.hasNext()) { ++ UUID uuid = (UUID) iterator.next(); + +- class SleepGoal extends Fox.FoxBehaviorGoal { +- private static final int WAIT_TIME_BEFORE_SLEEP = reducedTickDelay(140); +- private int countdown = Fox.this.random.nextInt(WAIT_TIME_BEFORE_SLEEP); ++ if (uuid != null && Fox.this.level() instanceof ServerLevel) { ++ Entity entity = ((ServerLevel) Fox.this.level()).getEntity(uuid); + +- public SleepGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK, Goal.Flag.JUMP)); +- } ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; + +- @Override +- public boolean canUse() { +- return Fox.this.xxa == 0.0F && Fox.this.yya == 0.0F && Fox.this.zza == 0.0F && (this.canSleep() || Fox.this.isSleeping()); +- } ++ this.trustedLastHurt = entityliving; ++ this.trustedLastHurtBy = entityliving.getLastHurtByMob(); ++ int i = entityliving.getLastHurtByMobTimestamp(); + +- @Override +- public boolean canContinueToUse() { +- return this.canSleep(); +- } ++ return i != this.timestamp && this.canAttack(this.trustedLastHurtBy, this.targetConditions); ++ } ++ } ++ } + +- private boolean canSleep() { +- if (this.countdown > 0) { +- this.countdown--; + return false; +- } else { +- return Fox.this.level().isDay() && this.hasShelter() && !this.alertable() && !Fox.this.isInPowderSnow; + } + } + + @Override +- public void stop() { +- this.countdown = Fox.this.random.nextInt(WAIT_TIME_BEFORE_SLEEP); +- Fox.this.clearStates(); +- } +- +- @Override + public void start() { +- Fox.this.setSitting(false); +- Fox.this.setIsCrouching(false); +- Fox.this.setIsInterested(false); +- Fox.this.setJumping(false); +- Fox.this.setSleeping(true); +- Fox.this.getNavigation().stop(); +- Fox.this.getMoveControl().setWantedPosition(Fox.this.getX(), Fox.this.getY(), Fox.this.getZ(), 0.0); +- } +- } +- +- class StalkPreyGoal extends Goal { +- public StalkPreyGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); +- } +- +- @Override +- public boolean canUse() { +- if (Fox.this.isSleeping()) { +- return false; +- } else { +- LivingEntity target = Fox.this.getTarget(); +- return target != null +- && target.isAlive() +- && Fox.STALKABLE_PREY.test(target) +- && Fox.this.distanceToSqr(target) > 36.0 +- && !Fox.this.isCrouching() +- && !Fox.this.isInterested() +- && !Fox.this.jumping; ++ this.setTarget(this.trustedLastHurtBy); ++ this.target = this.trustedLastHurtBy; ++ if (this.trustedLastHurt != null) { ++ this.timestamp = this.trustedLastHurt.getLastHurtByMobTimestamp(); + } +- } + +- @Override +- public void start() { +- Fox.this.setSitting(false); +- Fox.this.setFaceplanted(false); ++ Fox.this.playSound(SoundEvents.FOX_AGGRO, 1.0F, 1.0F); ++ Fox.this.setDefending(true); ++ Fox.this.wakeUp(); ++ super.start(); + } +- +- @Override +- public void stop() { +- LivingEntity target = Fox.this.getTarget(); +- if (target != null && Fox.isPathClear(Fox.this, target)) { +- Fox.this.setIsInterested(true); +- Fox.this.setIsCrouching(true); +- Fox.this.getNavigation().stop(); +- Fox.this.getLookControl().setLookAt(target, (float)Fox.this.getMaxHeadYRot(), (float)Fox.this.getMaxHeadXRot()); +- } else { +- Fox.this.setIsInterested(false); +- Fox.this.setIsCrouching(false); +- } +- } +- +- @Override +- public void tick() { +- LivingEntity target = Fox.this.getTarget(); +- if (target != null) { +- Fox.this.getLookControl().setLookAt(target, (float)Fox.this.getMaxHeadYRot(), (float)Fox.this.getMaxHeadXRot()); +- if (Fox.this.distanceToSqr(target) <= 36.0) { +- Fox.this.setIsInterested(true); +- Fox.this.setIsCrouching(true); +- Fox.this.getNavigation().stop(); +- } else { +- Fox.this.getNavigation().moveTo(target, 1.5); +- } +- } +- } + } + + public static enum Type implements StringRepresentable { +- RED(0, "red"), +- SNOW(1, "snow"); + ++ RED(0, "red"), SNOW(1, "snow"); ++ + public static final StringRepresentable.EnumCodec CODEC = StringRepresentable.fromEnum(Fox.Type::values); +- private static final IntFunction BY_ID = ByIdMap.continuous(Fox.Type::getId, values(), ByIdMap.OutOfBoundsStrategy.ZERO); ++ private static final IntFunction BY_ID = ByIdMap.continuous(Fox.Type::getId, values(), ByIdMap.a.ZERO); + private final int id; + private final String name; + +- private Type(int id, String name) { +- this.id = id; +- this.name = name; ++ private Type(int i, String s) { ++ this.id = i; ++ this.name = s; + } + + @Override +@@ -1511,15 +1541,51 @@ + } + + public static Fox.Type byName(String name) { +- return CODEC.byName(name, RED); ++ return (Fox.Type) Fox.Type.CODEC.byName(name, Fox.Type.RED); + } + + public static Fox.Type byId(int index) { +- return BY_ID.apply(index); ++ return (Fox.Type) Fox.Type.BY_ID.apply(index); + } + + public static Fox.Type byBiome(Holder biome) { +- return biome.is(BiomeTags.SPAWNS_SNOW_FOXES) ? SNOW : RED; ++ return biome.is(BiomeTags.SPAWNS_SNOW_FOXES) ? Fox.Type.SNOW : Fox.Type.RED; + } + } ++ ++ public static class FoxGroupData extends AgeableMob.AgeableMobGroupData { ++ ++ public final Fox.Type type; ++ ++ public FoxGroupData(Fox.Type type) { ++ super(false); ++ this.type = type; ++ } ++ } ++ ++ private abstract class d extends Goal { ++ ++ private final TargetingConditions alertableTargeting = TargetingConditions.forCombat().range(12.0D).ignoreLineOfSight().selector(Fox.this.new FoxAlertableEntitiesSelector()); ++ ++ d() {} ++ ++ protected boolean hasShelter() { ++ BlockPos blockposition = BlockPos.containing(Fox.this.getX(), Fox.this.getBoundingBox().maxY, Fox.this.getZ()); ++ ++ return !Fox.this.level().canSeeSky(blockposition) && Fox.this.getWalkTargetValue(blockposition) >= 0.0F; ++ } ++ ++ protected boolean alertable() { ++ return !Fox.this.level().getNearbyEntities(LivingEntity.class, this.alertableTargeting, Fox.this, Fox.this.getBoundingBox().inflate(12.0D, 6.0D, 12.0D)).isEmpty(); ++ } ++ } ++ ++ public class FoxAlertableEntitiesSelector implements Predicate { ++ ++ public FoxAlertableEntitiesSelector() {} ++ ++ public boolean test(LivingEntity entity) { ++ return entity instanceof Fox ? false : (!(entity instanceof Chicken) && !(entity instanceof Rabbit) && !(entity instanceof Monster) ? (entity instanceof TamableAnimal ? !((TamableAnimal) entity).isTame() : (entity instanceof Player && (entity.isSpectator() || ((Player) entity).isCreative()) ? false : (Fox.this.trusts(entity.getUUID()) ? false : !entity.isSleeping() && !entity.isDiscrete()))) : true); ++ } ++ } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/IronGolem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/IronGolem.java.patch new file mode 100644 index 0000000000..fb29fc60f9 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/IronGolem.java.patch @@ -0,0 +1,365 @@ +--- a/net/minecraft/world/entity/animal/IronGolem.java ++++ b/net/minecraft/world/entity/animal/IronGolem.java +@@ -2,6 +2,7 @@ + + import com.google.common.collect.ImmutableList; + import java.util.Comparator; ++import java.util.Iterator; + import java.util.List; + import java.util.UUID; + import java.util.stream.Stream; +@@ -16,7 +17,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.util.TimeUtil; + import net.minecraft.util.valueproviders.UniformInt; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; +@@ -38,18 +39,19 @@ + import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; + import net.minecraft.world.entity.ai.goal.target.ResetUniversalAngerTargetGoal; + import net.minecraft.world.entity.monster.Creeper; +-import net.minecraft.world.entity.monster.Enemy; ++import net.minecraft.world.entity.monster.IMonster; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.NaturalSpawner; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.Vec3; + + public class IronGolem extends AbstractGolem implements NeutralMob { ++ + protected static final EntityDataAccessor DATA_FLAGS_ID = SynchedEntityData.defineId(IronGolem.class, EntityDataSerializers.BYTE); + private static final int IRON_INGOT_HEAL_AMOUNT = 25; + private int attackAnimationTick; +@@ -66,33 +68,30 @@ + + @Override + protected void registerGoals() { +- this.goalSelector.addGoal(1, new MeleeAttackGoal(this, 1.0, true)); +- this.goalSelector.addGoal(2, new MoveTowardsTargetGoal(this, 0.9, 32.0F)); +- this.goalSelector.addGoal(2, new MoveBackToVillageGoal(this, 0.6, false)); +- this.goalSelector.addGoal(4, new GolemRandomStrollInVillageGoal(this, 0.6)); ++ this.goalSelector.addGoal(1, new MeleeAttackGoal(this, 1.0D, true)); ++ this.goalSelector.addGoal(2, new MoveTowardsTargetGoal(this, 0.9D, 32.0F)); ++ this.goalSelector.addGoal(2, new MoveBackToVillageGoal(this, 0.6D, false)); ++ this.goalSelector.addGoal(4, new GolemRandomStrollInVillageGoal(this, 0.6D)); + this.goalSelector.addGoal(5, new OfferFlowerGoal(this)); + this.goalSelector.addGoal(7, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); + this.targetSelector.addGoal(1, new DefendVillageTargetGoal(this)); +- this.targetSelector.addGoal(2, new HurtByTargetGoal(this)); ++ this.targetSelector.addGoal(2, new HurtByTargetGoal(this, new Class[0])); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt)); +- this.targetSelector +- .addGoal(3, new NearestAttackableTargetGoal<>(this, Mob.class, 5, false, false, entity -> entity instanceof Enemy && !(entity instanceof Creeper))); ++ this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Mob.class, 5, false, false, (entityliving) -> { ++ return entityliving instanceof IMonster && !(entityliving instanceof Creeper); ++ })); + this.targetSelector.addGoal(4, new ResetUniversalAngerTargetGoal<>(this, false)); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_FLAGS_ID, (byte)0); ++ this.entityData.define(IronGolem.DATA_FLAGS_ID, (byte) 0); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes() +- .add(Attributes.MAX_HEALTH, 100.0) +- .add(Attributes.MOVEMENT_SPEED, 0.25) +- .add(Attributes.KNOCKBACK_RESISTANCE, 1.0) +- .add(Attributes.ATTACK_DAMAGE, 15.0); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 100.0D).add(Attributes.MOVEMENT_SPEED, 0.25D).add(Attributes.KNOCKBACK_RESISTANCE, 1.0D).add(Attributes.ATTACK_DAMAGE, 15.0D); + } + + @Override +@@ -102,8 +101,8 @@ + + @Override + protected void doPush(Entity entity) { +- if (entity instanceof Enemy && !(entity instanceof Creeper) && this.getRandom().nextInt(20) == 0) { +- this.setTarget((LivingEntity)entity); ++ if (entity instanceof IMonster && !(entity instanceof Creeper) && this.getRandom().nextInt(20) == 0) { ++ this.setTarget((LivingEntity) entity, org.bukkit.event.entity.EntityTargetLivingEntityEvent.TargetReason.COLLISION, true); // CraftBukkit - set reason + } + + super.doPush(entity); +@@ -113,26 +112,27 @@ + public void aiStep() { + super.aiStep(); + if (this.attackAnimationTick > 0) { +- this.attackAnimationTick--; ++ --this.attackAnimationTick; + } + + if (this.offerFlowerTick > 0) { +- this.offerFlowerTick--; ++ --this.offerFlowerTick; + } + + if (!this.level().isClientSide) { +- this.updatePersistentAnger((ServerLevel)this.level(), true); ++ this.updatePersistentAnger((ServerLevel) this.level(), true); + } ++ + } + + @Override + public boolean canSpawnSprintParticle() { +- return this.getDeltaMovement().horizontalDistanceSqr() > 2.5000003E-7F && this.random.nextInt(5) == 0; ++ return this.getDeltaMovement().horizontalDistanceSqr() > 2.500000277905201E-7D && this.random.nextInt(5) == 0; + } + + @Override + public boolean canAttackType(EntityType type) { +- return (!this.isPlayerCreated() || type != EntityType.PLAYER) && type != EntityType.CREEPER && super.canAttackType(type); ++ return this.isPlayerCreated() && type == EntityType.PLAYER ? false : (type == EntityType.CREEPER ? false : super.canAttackType(type)); + } + + @Override +@@ -151,7 +151,7 @@ + + @Override + public void startPersistentAngerTimer() { +- this.setRemainingPersistentAngerTime(PERSISTENT_ANGER_TIME.sample(this.random)); ++ this.setRemainingPersistentAngerTime(IronGolem.PERSISTENT_ANGER_TIME.sample(this.random)); + } + + @Override +@@ -176,20 +176,32 @@ + } + + private float getAttackDamage() { +- return (float)this.getAttributeValue(Attributes.ATTACK_DAMAGE); ++ return (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE); + } + + @Override + public boolean doHurtTarget(Entity entity) { + this.attackAnimationTick = 10; +- this.level().broadcastEntityEvent(this, (byte)4); +- float attackDamage = this.getAttackDamage(); +- float f = (int)attackDamage > 0 ? attackDamage / 2.0F + (float)this.random.nextInt((int)attackDamage) : attackDamage; +- boolean flag = entity.hurt(this.damageSources().mobAttack(this), f); ++ this.level().broadcastEntityEvent(this, (byte) 4); ++ float f = this.getAttackDamage(); ++ float f1 = (int) f > 0 ? f / 2.0F + (float) this.random.nextInt((int) f) : f; ++ boolean flag = entity.hurt(this.damageSources().mobAttack(this), f1); ++ + if (flag) { +- double d = entity instanceof LivingEntity livingEntity ? livingEntity.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE) : 0.0; +- double max = Math.max(0.0, 1.0 - d); +- entity.setDeltaMovement(entity.getDeltaMovement().add(0.0, 0.4F * max, 0.0)); ++ double d0; ++ ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ d0 = entityliving.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE); ++ } else { ++ d0 = 0.0D; ++ } ++ ++ double d1 = d0; ++ double d2 = Math.max(0.0D, 1.0D - d1); ++ ++ entity.setDeltaMovement(entity.getDeltaMovement().add(0.0D, 0.4000000059604645D * d2, 0.0D)); + this.doEnchantDamageEffects(this, entity); + } + +@@ -199,9 +211,10 @@ + + @Override + public boolean hurt(DamageSource source, float amount) { +- IronGolem.Crackiness crackiness = this.getCrackiness(); ++ IronGolem.Crackiness entityirongolem_cracklevel = this.getCrackiness(); + boolean flag = super.hurt(source, amount); +- if (flag && this.getCrackiness() != crackiness) { ++ ++ if (flag && this.getCrackiness() != entityirongolem_cracklevel) { + this.playSound(SoundEvents.IRON_GOLEM_DAMAGE, 1.0F, 1.0F); + } + +@@ -224,6 +237,7 @@ + } else { + super.handleEntityEvent(id); + } ++ + } + + public int getAttackAnimationTick() { +@@ -233,11 +247,12 @@ + public void offerFlower(boolean offeringFlower) { + if (offeringFlower) { + this.offerFlowerTick = 400; +- this.level().broadcastEntityEvent(this, (byte)11); ++ this.level().broadcastEntityEvent(this, (byte) 11); + } else { + this.offerFlowerTick = 0; +- this.level().broadcastEntityEvent(this, (byte)34); ++ this.level().broadcastEntityEvent(this, (byte) 34); + } ++ + } + + @Override +@@ -251,20 +266,23 @@ + } + + @Override +- protected InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (!itemInHand.is(Items.IRON_INGOT)) { ++ protected InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (!itemstack.is(Items.IRON_INGOT)) { + return InteractionResult.PASS; + } else { +- float health = this.getHealth(); ++ float f = this.getHealth(); ++ + this.heal(25.0F); +- if (this.getHealth() == health) { ++ if (this.getHealth() == f) { + return InteractionResult.PASS; + } else { +- float f = 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F; +- this.playSound(SoundEvents.IRON_GOLEM_REPAIR, 1.0F, f); ++ float f1 = 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F; ++ ++ this.playSound(SoundEvents.IRON_GOLEM_REPAIR, 1.0F, f1); + if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + + return InteractionResult.sidedSuccess(this.level().isClientSide); +@@ -273,7 +291,7 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.IRON_GOLEM_STEP, 1.0F, 1.0F); + } + +@@ -282,16 +300,18 @@ + } + + public boolean isPlayerCreated() { +- return (this.entityData.get(DATA_FLAGS_ID) & 1) != 0; ++ return ((Byte) this.entityData.get(IronGolem.DATA_FLAGS_ID) & 1) != 0; + } + + public void setPlayerCreated(boolean playerCreated) { +- byte b = this.entityData.get(DATA_FLAGS_ID); ++ byte b0 = (Byte) this.entityData.get(IronGolem.DATA_FLAGS_ID); ++ + if (playerCreated) { +- this.entityData.set(DATA_FLAGS_ID, (byte)(b | 1)); ++ this.entityData.set(IronGolem.DATA_FLAGS_ID, (byte) (b0 | 1)); + } else { +- this.entityData.set(DATA_FLAGS_ID, (byte)(b & -2)); ++ this.entityData.set(IronGolem.DATA_FLAGS_ID, (byte) (b0 & -2)); + } ++ + } + + @Override +@@ -301,55 +321,58 @@ + + @Override + public boolean checkSpawnObstruction(LevelReader level) { +- BlockPos blockPos = this.blockPosition(); +- BlockPos blockPos1 = blockPos.below(); +- BlockState blockState = level.getBlockState(blockPos1); +- if (!blockState.entityCanStandOn(level, blockPos1, this)) { ++ BlockPos blockposition = this.blockPosition(); ++ BlockPos blockposition1 = blockposition.below(); ++ IBlockData iblockdata = level.getBlockState(blockposition1); ++ ++ if (!iblockdata.entityCanStandOn(level, blockposition1, this)) { + return false; + } else { +- for (int i = 1; i < 3; i++) { +- BlockPos blockPos2 = blockPos.above(i); +- BlockState blockState1 = level.getBlockState(blockPos2); +- if (!NaturalSpawner.isValidEmptySpawnBlock(level, blockPos2, blockState1, blockState1.getFluidState(), EntityType.IRON_GOLEM)) { ++ for (int i = 1; i < 3; ++i) { ++ BlockPos blockposition2 = blockposition.above(i); ++ IBlockData iblockdata1 = level.getBlockState(blockposition2); ++ ++ if (!NaturalSpawner.isValidEmptySpawnBlock(level, blockposition2, iblockdata1, iblockdata1.getFluidState(), EntityType.IRON_GOLEM)) { + return false; + } + } + +- return NaturalSpawner.isValidEmptySpawnBlock( +- level, blockPos, level.getBlockState(blockPos), Fluids.EMPTY.defaultFluidState(), EntityType.IRON_GOLEM +- ) +- && level.isUnobstructed(this); ++ return NaturalSpawner.isValidEmptySpawnBlock(level, blockposition, level.getBlockState(blockposition), Fluids.EMPTY.defaultFluidState(), EntityType.IRON_GOLEM) && level.isUnobstructed(this); + } + } + + @Override + public Vec3 getLeashOffset() { +- return new Vec3(0.0, (double)(0.875F * this.getEyeHeight()), (double)(this.getBbWidth() * 0.4F)); ++ return new Vec3(0.0D, (double) (0.875F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); + } + + public static enum Crackiness { +- NONE(1.0F), +- LOW(0.75F), +- MEDIUM(0.5F), +- HIGH(0.25F); + +- private static final List BY_DAMAGE = Stream.of(values()) +- .sorted(Comparator.comparingDouble(crack -> (double)crack.fraction)) +- .collect(ImmutableList.toImmutableList()); ++ NONE(1.0F), LOW(0.75F), MEDIUM(0.5F), HIGH(0.25F); ++ ++ private static final List BY_DAMAGE = (List) Stream.of(values()).sorted(Comparator.comparingDouble((entityirongolem_cracklevel) -> { ++ return (double) entityirongolem_cracklevel.fraction; ++ })).collect(ImmutableList.toImmutableList()); + private final float fraction; + +- private Crackiness(float fraction) { +- this.fraction = fraction; ++ private Crackiness(float f) { ++ this.fraction = f; + } + + public static IronGolem.Crackiness byFraction(float fraction) { +- for (IronGolem.Crackiness crackiness : BY_DAMAGE) { +- if (fraction < crackiness.fraction) { +- return crackiness; ++ Iterator iterator = IronGolem.Crackiness.BY_DAMAGE.iterator(); ++ ++ IronGolem.Crackiness entityirongolem_cracklevel; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return IronGolem.Crackiness.NONE; + } +- } + +- return NONE; ++ entityirongolem_cracklevel = (IronGolem.Crackiness) iterator.next(); ++ } while (fraction >= entityirongolem_cracklevel.fraction); ++ ++ return entityirongolem_cracklevel; + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/MushroomCow.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/MushroomCow.java.patch new file mode 100644 index 0000000000..3852161892 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/MushroomCow.java.patch @@ -0,0 +1,386 @@ +--- a/net/minecraft/world/entity/animal/MushroomCow.java ++++ b/net/minecraft/world/entity/animal/MushroomCow.java +@@ -8,7 +8,6 @@ + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtOps; +-import net.minecraft.nbt.Tag; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; +@@ -20,12 +19,13 @@ + import net.minecraft.tags.ItemTags; + import net.minecraft.util.RandomSource; + import net.minecraft.util.StringRepresentable; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.AgeableMob; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.LightningBolt; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.Shearable; + import net.minecraft.world.entity.VariantHolder; + import net.minecraft.world.entity.item.ItemEntity; +@@ -39,15 +39,23 @@ + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.SuspiciousEffectHolder; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityDropItemEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++// CraftBukkit end ++ + public class MushroomCow extends Cow implements Shearable, VariantHolder { ++ + private static final EntityDataAccessor DATA_TYPE = SynchedEntityData.defineId(MushroomCow.class, EntityDataSerializers.STRING); + private static final int MUTATE_CHANCE = 1024; + private static final String TAG_STEW_EFFECTS = "stew_effects"; + @Nullable +- private List stewEffects; ++ private List stewEffects; + @Nullable + private UUID lastLightningBoltUUID; + +@@ -60,100 +68,94 @@ + return level.getBlockState(pos.below()).is(Blocks.MYCELIUM) ? 10.0F : level.getPathfindingCostFromLightLevels(pos); + } + +- public static boolean checkMushroomSpawnRules( +- EntityType mushroomCow, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource randomSource +- ) { ++ public static boolean checkMushroomSpawnRules(EntityType mushroomCow, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource randomSource) { + return level.getBlockState(pos.below()).is(BlockTags.MOOSHROOMS_SPAWNABLE_ON) && isBrightEnoughToSpawn(level, pos); + } + + @Override + public void thunderHit(ServerLevel level, LightningBolt lightning) { +- UUID uUID = lightning.getUUID(); +- if (!uUID.equals(this.lastLightningBoltUUID)) { ++ UUID uuid = lightning.getUUID(); ++ ++ if (!uuid.equals(this.lastLightningBoltUUID)) { + this.setVariant(this.getVariant() == MushroomCow.MushroomType.RED ? MushroomCow.MushroomType.BROWN : MushroomCow.MushroomType.RED); +- this.lastLightningBoltUUID = uUID; ++ this.lastLightningBoltUUID = uuid; + this.playSound(SoundEvents.MOOSHROOM_CONVERT, 2.0F, 1.0F); + } ++ + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_TYPE, MushroomCow.MushroomType.RED.type); ++ this.entityData.define(MushroomCow.DATA_TYPE, MushroomCow.MushroomType.RED.type); + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (itemInHand.is(Items.BOWL) && !this.isBaby()) { ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (itemstack.is(Items.BOWL) && !this.isBaby()) { + boolean flag = false; +- ItemStack itemStack; ++ ItemStack itemstack1; ++ + if (this.stewEffects != null) { + flag = true; +- itemStack = new ItemStack(Items.SUSPICIOUS_STEW); +- SuspiciousStewItem.saveMobEffects(itemStack, this.stewEffects); ++ itemstack1 = new ItemStack(Items.SUSPICIOUS_STEW); ++ SuspiciousStewItem.saveMobEffects(itemstack1, this.stewEffects); + this.stewEffects = null; + } else { +- itemStack = new ItemStack(Items.MUSHROOM_STEW); ++ itemstack1 = new ItemStack(Items.MUSHROOM_STEW); + } + +- ItemStack itemStack1 = ItemUtils.createFilledResult(itemInHand, player, itemStack, false); +- player.setItemInHand(hand, itemStack1); +- SoundEvent soundEvent; ++ ItemStack itemstack2 = ItemUtils.createFilledResult(itemstack, player, itemstack1, false); ++ ++ player.setItemInHand(hand, itemstack2); ++ SoundEvent soundeffect; ++ + if (flag) { +- soundEvent = SoundEvents.MOOSHROOM_MILK_SUSPICIOUSLY; ++ soundeffect = SoundEvents.MOOSHROOM_MILK_SUSPICIOUSLY; + } else { +- soundEvent = SoundEvents.MOOSHROOM_MILK; ++ soundeffect = SoundEvents.MOOSHROOM_MILK; + } + +- this.playSound(soundEvent, 1.0F, 1.0F); ++ this.playSound(soundeffect, 1.0F, 1.0F); + return InteractionResult.sidedSuccess(this.level().isClientSide); +- } else if (itemInHand.is(Items.SHEARS) && this.readyForShearing()) { ++ } else if (itemstack.is(Items.SHEARS) && this.readyForShearing()) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) { ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.shear(SoundSource.PLAYERS); + this.gameEvent(GameEvent.SHEAR, player); + if (!this.level().isClientSide) { +- itemInHand.hurtAndBreak(1, player, entity -> entity.broadcastBreakEvent(hand)); ++ itemstack.hurtAndBreak(1, player, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(hand); ++ }); + } + + return InteractionResult.sidedSuccess(this.level().isClientSide); +- } else if (this.getVariant() == MushroomCow.MushroomType.BROWN && itemInHand.is(ItemTags.SMALL_FLOWERS)) { ++ } else if (this.getVariant() == MushroomCow.MushroomType.BROWN && itemstack.is(ItemTags.SMALL_FLOWERS)) { + if (this.stewEffects != null) { +- for (int i = 0; i < 2; i++) { +- this.level() +- .addParticle( +- ParticleTypes.SMOKE, +- this.getX() + this.random.nextDouble() / 2.0, +- this.getY(0.5), +- this.getZ() + this.random.nextDouble() / 2.0, +- 0.0, +- this.random.nextDouble() / 5.0, +- 0.0 +- ); ++ for (int i = 0; i < 2; ++i) { ++ this.level().addParticle(ParticleTypes.SMOKE, this.getX() + this.random.nextDouble() / 2.0D, this.getY(0.5D), this.getZ() + this.random.nextDouble() / 2.0D, 0.0D, this.random.nextDouble() / 5.0D, 0.0D); + } + } else { +- Optional> effectsFromItemStack = this.getEffectsFromItemStack(itemInHand); +- if (effectsFromItemStack.isEmpty()) { ++ Optional> optional = this.getEffectsFromItemStack(itemstack); ++ ++ if (optional.isEmpty()) { + return InteractionResult.PASS; + } + + if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + +- for (int i1 = 0; i1 < 4; i1++) { +- this.level() +- .addParticle( +- ParticleTypes.EFFECT, +- this.getX() + this.random.nextDouble() / 2.0, +- this.getY(0.5), +- this.getZ() + this.random.nextDouble() / 2.0, +- 0.0, +- this.random.nextDouble() / 5.0, +- 0.0 +- ); ++ for (int j = 0; j < 4; ++j) { ++ this.level().addParticle(ParticleTypes.EFFECT, this.getX() + this.random.nextDouble() / 2.0D, this.getY(0.5D), this.getZ() + this.random.nextDouble() / 2.0D, 0.0D, this.random.nextDouble() / 5.0D, 0.0D); + } + +- this.stewEffects = effectsFromItemStack.get(); ++ this.stewEffects = (List) optional.get(); + this.playSound(SoundEvents.MOOSHROOM_EAT, 2.0F, 1.0F); + } + +@@ -165,35 +167,49 @@ + + @Override + public void shear(SoundSource category) { +- this.level().playSound(null, this, SoundEvents.MOOSHROOM_SHEAR, category, 1.0F, 1.0F); ++ this.level().playSound((Player) null, (Entity) this, SoundEvents.MOOSHROOM_SHEAR, category, 1.0F, 1.0F); + if (!this.level().isClientSide()) { +- Cow cow = EntityType.COW.create(this.level()); +- if (cow != null) { +- ((ServerLevel)this.level()).sendParticles(ParticleTypes.EXPLOSION, this.getX(), this.getY(0.5), this.getZ(), 1, 0.0, 0.0, 0.0, 0.0); +- this.discard(); +- cow.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); +- cow.setHealth(this.getHealth()); +- cow.yBodyRot = this.yBodyRot; ++ Cow entitycow = (Cow) EntityType.COW.create(this.level()); ++ ++ if (entitycow != null) { ++ ((ServerLevel) this.level()).sendParticles(ParticleTypes.EXPLOSION, this.getX(), this.getY(0.5D), this.getZ(), 1, 0.0D, 0.0D, 0.0D, 0.0D); ++ // this.discard(); // CraftBukkit - moved down ++ entitycow.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); ++ entitycow.setHealth(this.getHealth()); ++ entitycow.yBodyRot = this.yBodyRot; + if (this.hasCustomName()) { +- cow.setCustomName(this.getCustomName()); +- cow.setCustomNameVisible(this.isCustomNameVisible()); ++ entitycow.setCustomName(this.getCustomName()); ++ entitycow.setCustomNameVisible(this.isCustomNameVisible()); + } + + if (this.isPersistenceRequired()) { +- cow.setPersistenceRequired(); ++ entitycow.setPersistenceRequired(); + } + +- cow.setInvulnerable(this.isInvulnerable()); +- this.level().addFreshEntity(cow); ++ entitycow.setInvulnerable(this.isInvulnerable()); ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, entitycow, EntityTransformEvent.TransformReason.SHEARED).isCancelled()) { ++ return; ++ } ++ this.level().addFreshEntity(entitycow, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SHEARED); + +- for (int i = 0; i < 5; i++) { +- this.level() +- .addFreshEntity( +- new ItemEntity(this.level(), this.getX(), this.getY(1.0), this.getZ(), new ItemStack(this.getVariant().blockState.getBlock())) +- ); ++ this.discard(); // CraftBukkit - from above ++ // CraftBukkit end ++ ++ for (int i = 0; i < 5; ++i) { ++ // CraftBukkit start ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY(1.0D), this.getZ(), new ItemStack(this.getVariant().blockState.getBlock())); ++ EntityDropItemEvent event = new EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ continue; ++ } ++ this.level().addFreshEntity(entityitem); ++ // CraftBukkit end + } + } + } ++ + } + + @Override +@@ -206,11 +222,11 @@ + super.addAdditionalSaveData(compound); + compound.putString("Type", this.getVariant().getSerializedName()); + if (this.stewEffects != null) { +- SuspiciousEffectHolder.EffectEntry.LIST_CODEC +- .encodeStart(NbtOps.INSTANCE, this.stewEffects) +- .result() +- .ifPresent(tag -> compound.put("stew_effects", tag)); ++ SuspiciousEffectHolder.a.LIST_CODEC.encodeStart(NbtOps.INSTANCE, this.stewEffects).result().ifPresent((nbtbase) -> { ++ compound.put("stew_effects", nbtbase); ++ }); + } ++ + } + + @Override +@@ -218,66 +234,68 @@ + super.readAdditionalSaveData(compound); + this.setVariant(MushroomCow.MushroomType.byType(compound.getString("Type"))); + if (compound.contains("stew_effects", 9)) { +- SuspiciousEffectHolder.EffectEntry.LIST_CODEC +- .parse(NbtOps.INSTANCE, compound.get("stew_effects")) +- .result() +- .ifPresent(list -> this.stewEffects = (List)list); ++ SuspiciousEffectHolder.a.LIST_CODEC.parse(NbtOps.INSTANCE, compound.get("stew_effects")).result().ifPresent((list) -> { ++ this.stewEffects = list; ++ }); + } ++ + } + +- private Optional> getEffectsFromItemStack(ItemStack itemStack) { +- SuspiciousEffectHolder suspiciousEffectHolder = SuspiciousEffectHolder.tryGet(itemStack.getItem()); +- return suspiciousEffectHolder != null ? Optional.of(suspiciousEffectHolder.getSuspiciousEffects()) : Optional.empty(); ++ private Optional> getEffectsFromItemStack(ItemStack itemstack) { ++ SuspiciousEffectHolder suspiciouseffectholder = SuspiciousEffectHolder.tryGet(itemstack.getItem()); ++ ++ return suspiciouseffectholder != null ? Optional.of(suspiciouseffectholder.getSuspiciousEffects()) : Optional.empty(); + } + +- @Override + public void setVariant(MushroomCow.MushroomType variant) { +- this.entityData.set(DATA_TYPE, variant.type); ++ this.entityData.set(MushroomCow.DATA_TYPE, variant.type); + } + + @Override + public MushroomCow.MushroomType getVariant() { +- return MushroomCow.MushroomType.byType(this.entityData.get(DATA_TYPE)); ++ return MushroomCow.MushroomType.byType((String) this.entityData.get(MushroomCow.DATA_TYPE)); + } + + @Nullable + @Override + public MushroomCow getBreedOffspring(ServerLevel level, AgeableMob otherParent) { +- MushroomCow mushroomCow = EntityType.MOOSHROOM.create(level); +- if (mushroomCow != null) { +- mushroomCow.setVariant(this.getOffspringType((MushroomCow)otherParent)); ++ MushroomCow entitymushroomcow = (MushroomCow) EntityType.MOOSHROOM.create(level); ++ ++ if (entitymushroomcow != null) { ++ entitymushroomcow.setVariant(this.getOffspringType((MushroomCow) otherParent)); + } + +- return mushroomCow; ++ return entitymushroomcow; + } + + private MushroomCow.MushroomType getOffspringType(MushroomCow mate) { +- MushroomCow.MushroomType variant = this.getVariant(); +- MushroomCow.MushroomType variant1 = mate.getVariant(); +- MushroomCow.MushroomType mushroomType; +- if (variant == variant1 && this.random.nextInt(1024) == 0) { +- mushroomType = variant == MushroomCow.MushroomType.BROWN ? MushroomCow.MushroomType.RED : MushroomCow.MushroomType.BROWN; ++ MushroomCow.MushroomType entitymushroomcow_type = this.getVariant(); ++ MushroomCow.MushroomType entitymushroomcow_type1 = mate.getVariant(); ++ MushroomCow.MushroomType entitymushroomcow_type2; ++ ++ if (entitymushroomcow_type == entitymushroomcow_type1 && this.random.nextInt(1024) == 0) { ++ entitymushroomcow_type2 = entitymushroomcow_type == MushroomCow.MushroomType.BROWN ? MushroomCow.MushroomType.RED : MushroomCow.MushroomType.BROWN; + } else { +- mushroomType = this.random.nextBoolean() ? variant : variant1; ++ entitymushroomcow_type2 = this.random.nextBoolean() ? entitymushroomcow_type : entitymushroomcow_type1; + } + +- return mushroomType; ++ return entitymushroomcow_type2; + } + + public static enum MushroomType implements StringRepresentable { +- RED("red", Blocks.RED_MUSHROOM.defaultBlockState()), +- BROWN("brown", Blocks.BROWN_MUSHROOM.defaultBlockState()); + ++ RED("red", Blocks.RED_MUSHROOM.defaultBlockState()), BROWN("brown", Blocks.BROWN_MUSHROOM.defaultBlockState()); ++ + public static final StringRepresentable.EnumCodec CODEC = StringRepresentable.fromEnum(MushroomCow.MushroomType::values); + final String type; +- final BlockState blockState; ++ final IBlockData blockState; + +- private MushroomType(String type, BlockState blockState) { +- this.type = type; +- this.blockState = blockState; ++ private MushroomType(String s, IBlockData iblockdata) { ++ this.type = s; ++ this.blockState = iblockdata; + } + +- public BlockState getBlockState() { ++ public IBlockData getBlockState() { + return this.blockState; + } + +@@ -287,7 +305,7 @@ + } + + static MushroomCow.MushroomType byType(String name) { +- return CODEC.byName(name, RED); ++ return (MushroomCow.MushroomType) MushroomCow.MushroomType.CODEC.byName(name, MushroomCow.MushroomType.RED); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Ocelot.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Ocelot.java.patch new file mode 100644 index 0000000000..cc9e027272 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Ocelot.java.patch @@ -0,0 +1,342 @@ +--- a/net/minecraft/world/entity/animal/Ocelot.java ++++ b/net/minecraft/world/entity/animal/Ocelot.java +@@ -1,9 +1,11 @@ + package net.minecraft.world.entity.animal; + ++import java.util.Objects; ++import java.util.function.Predicate; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +-import net.minecraft.core.particles.ParticleOptions; + import net.minecraft.core.particles.ParticleTypes; ++import net.minecraft.core.particles.SimpleParticleType; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; +@@ -14,19 +16,19 @@ + import net.minecraft.tags.BlockTags; + import net.minecraft.util.RandomSource; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.AvoidEntityGoal; +@@ -47,14 +49,15 @@ + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + + public class Ocelot extends Animal { +- public static final double CROUCH_SPEED_MOD = 0.6; +- public static final double WALK_SPEED_MOD = 0.8; +- public static final double SPRINT_SPEED_MOD = 1.33; ++ ++ public static final double CROUCH_SPEED_MOD = 0.6D; ++ public static final double WALK_SPEED_MOD = 0.8D; ++ public static final double SPRINT_SPEED_MOD = 1.33D; + private static final Ingredient TEMPT_INGREDIENT = Ingredient.of(Items.COD, Items.SALMON); + private static final EntityDataAccessor DATA_TRUSTING = SynchedEntityData.defineId(Ocelot.class, EntityDataSerializers.BOOLEAN); + @Nullable +@@ -67,12 +70,12 @@ + this.reassessTrustingGoals(); + } + +- boolean isTrusting() { +- return this.entityData.get(DATA_TRUSTING); ++ public boolean isTrusting() { ++ return (Boolean) this.entityData.get(Ocelot.DATA_TRUSTING); + } + +- private void setTrusting(boolean trusting) { +- this.entityData.set(DATA_TRUSTING, trusting); ++ public void setTrusting(boolean trusting) { ++ this.entityData.set(Ocelot.DATA_TRUSTING, trusting); + this.reassessTrustingGoals(); + } + +@@ -91,18 +94,18 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_TRUSTING, false); ++ this.entityData.define(Ocelot.DATA_TRUSTING, false); + } + + @Override + protected void registerGoals() { +- this.temptGoal = new Ocelot.OcelotTemptGoal(this, 0.6, TEMPT_INGREDIENT, true); ++ this.temptGoal = new Ocelot.OcelotTemptGoal(this, 0.6D, Ocelot.TEMPT_INGREDIENT, true); + this.goalSelector.addGoal(1, new FloatGoal(this)); + this.goalSelector.addGoal(3, this.temptGoal); + this.goalSelector.addGoal(7, new LeapAtTargetGoal(this, 0.3F)); + this.goalSelector.addGoal(8, new OcelotAttackGoal(this)); +- this.goalSelector.addGoal(9, new BreedGoal(this, 0.8)); +- this.goalSelector.addGoal(10, new WaterAvoidingRandomStrollGoal(this, 0.8, 1.0000001E-5F)); ++ this.goalSelector.addGoal(9, new BreedGoal(this, 0.8D)); ++ this.goalSelector.addGoal(10, new WaterAvoidingRandomStrollGoal(this, 0.8D, 1.0000001E-5F)); + this.goalSelector.addGoal(11, new LookAtPlayerGoal(this, Player.class, 10.0F)); + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Chicken.class, false)); + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, false, false, Turtle.BABY_ON_LAND_SELECTOR)); +@@ -111,21 +114,23 @@ + @Override + public void customServerAiStep() { + if (this.getMoveControl().hasWanted()) { +- double speedModifier = this.getMoveControl().getSpeedModifier(); +- if (speedModifier == 0.6) { +- this.setPose(Pose.CROUCHING); ++ double d0 = this.getMoveControl().getSpeedModifier(); ++ ++ if (d0 == 0.6D) { ++ this.setPose(EntityPose.CROUCHING); + this.setSprinting(false); +- } else if (speedModifier == 1.33) { +- this.setPose(Pose.STANDING); ++ } else if (d0 == 1.33D) { ++ this.setPose(EntityPose.STANDING); + this.setSprinting(true); + } else { +- this.setPose(Pose.STANDING); ++ this.setPose(EntityPose.STANDING); + this.setSprinting(false); + } + } else { +- this.setPose(Pose.STANDING); ++ this.setPose(EntityPose.STANDING); + this.setSprinting(false); + } ++ + } + + @Override +@@ -134,7 +139,7 @@ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0).add(Attributes.MOVEMENT_SPEED, 0.3F).add(Attributes.ATTACK_DAMAGE, 3.0); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D).add(Attributes.ATTACK_DAMAGE, 3.0D); + } + + @Nullable +@@ -159,7 +164,7 @@ + } + + private float getAttackDamage() { +- return (float)this.getAttributeValue(Attributes.ATTACK_DAMAGE); ++ return (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE); + } + + @Override +@@ -168,18 +173,19 @@ + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if ((this.temptGoal == null || this.temptGoal.isRunning()) && !this.isTrusting() && this.isFood(itemInHand) && player.distanceToSqr(this) < 9.0) { +- this.usePlayerItem(player, hand, itemInHand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if ((this.temptGoal == null || this.temptGoal.isRunning()) && !this.isTrusting() && this.isFood(itemstack) && player.distanceToSqr((Entity) this) < 9.0D) { ++ this.usePlayerItem(player, hand, itemstack); + if (!this.level().isClientSide) { +- if (this.random.nextInt(3) == 0) { ++ if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit - added event call and isCancelled check + this.setTrusting(true); + this.spawnTrustingParticles(true); +- this.level().broadcastEntityEvent(this, (byte)41); ++ this.level().broadcastEntityEvent(this, (byte) 41); + } else { + this.spawnTrustingParticles(false); +- this.level().broadcastEntityEvent(this, (byte)40); ++ this.level().broadcastEntityEvent(this, (byte) 40); + } + } + +@@ -198,58 +204,65 @@ + } else { + super.handleEntityEvent(id); + } ++ + } + + private void spawnTrustingParticles(boolean isTrusted) { +- ParticleOptions particleOptions = ParticleTypes.HEART; ++ SimpleParticleType particletype = ParticleTypes.HEART; ++ + if (!isTrusted) { +- particleOptions = ParticleTypes.SMOKE; ++ particletype = ParticleTypes.SMOKE; + } + +- for (int i = 0; i < 7; i++) { +- double d = this.random.nextGaussian() * 0.02; +- double d1 = this.random.nextGaussian() * 0.02; +- double d2 = this.random.nextGaussian() * 0.02; +- this.level().addParticle(particleOptions, this.getRandomX(1.0), this.getRandomY() + 0.5, this.getRandomZ(1.0), d, d1, d2); ++ for (int i = 0; i < 7; ++i) { ++ double d0 = this.random.nextGaussian() * 0.02D; ++ double d1 = this.random.nextGaussian() * 0.02D; ++ double d2 = this.random.nextGaussian() * 0.02D; ++ ++ this.level().addParticle(particletype, this.getRandomX(1.0D), this.getRandomY() + 0.5D, this.getRandomZ(1.0D), d0, d1, d2); + } ++ + } + + protected void reassessTrustingGoals() { + if (this.ocelotAvoidPlayersGoal == null) { +- this.ocelotAvoidPlayersGoal = new Ocelot.OcelotAvoidEntityGoal<>(this, Player.class, 16.0F, 0.8, 1.33); ++ this.ocelotAvoidPlayersGoal = new Ocelot.OcelotAvoidEntityGoal<>(this, Player.class, 16.0F, 0.8D, 1.33D); + } + + this.goalSelector.removeGoal(this.ocelotAvoidPlayersGoal); + if (!this.isTrusting()) { + this.goalSelector.addGoal(4, this.ocelotAvoidPlayersGoal); + } ++ + } + + @Nullable + @Override + public Ocelot getBreedOffspring(ServerLevel level, AgeableMob otherParent) { +- return EntityType.OCELOT.create(level); ++ return (Ocelot) EntityType.OCELOT.create(level); + } + + @Override + public boolean isFood(ItemStack stack) { +- return TEMPT_INGREDIENT.test(stack); ++ return Ocelot.TEMPT_INGREDIENT.test(stack); + } + +- public static boolean checkOcelotSpawnRules(EntityType ocelot, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) { ++ public static boolean checkOcelotSpawnRules(EntityType ocelot, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { + return random.nextInt(3) != 0; + } + + @Override + public boolean checkSpawnObstruction(LevelReader level) { + if (level.isUnobstructed(this) && !level.containsAnyLiquid(this.getBoundingBox())) { +- BlockPos blockPos = this.blockPosition(); +- if (blockPos.getY() < level.getSeaLevel()) { ++ BlockPos blockposition = this.blockPosition(); ++ ++ if (blockposition.getY() < level.getSeaLevel()) { + return false; + } + +- BlockState blockState = level.getBlockState(blockPos.below()); +- if (blockState.is(Blocks.GRASS_BLOCK) || blockState.is(BlockTags.LEAVES)) { ++ IBlockData iblockdata = level.getBlockState(blockposition.below()); ++ ++ if (iblockdata.is(Blocks.GRASS_BLOCK) || iblockdata.is(BlockTags.LEAVES)) { + return true; + } + } +@@ -259,19 +272,17 @@ + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + if (spawnData == null) { + spawnData = new AgeableMob.AgeableMobGroupData(1.0F); + } + +- return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + + @Override + public Vec3 getLeashOffset() { +- return new Vec3(0.0, (double)(0.5F * this.getEyeHeight()), (double)(this.getBbWidth() * 0.4F)); ++ return new Vec3(0.0D, (double) (0.5F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); + } + + @Override +@@ -280,40 +291,45 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height - 0.0625F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.0625F * f, 0.0F); + } + +- static class OcelotAvoidEntityGoal extends AvoidEntityGoal { ++ private static class OcelotTemptGoal extends TemptGoal { ++ + private final Ocelot ocelot; + +- public OcelotAvoidEntityGoal(Ocelot ocelot, Class entityClassToAvoid, float maxDist, double walkSpeedModifier, double sprintSpeedModifier) { +- super(ocelot, entityClassToAvoid, maxDist, walkSpeedModifier, sprintSpeedModifier, EntitySelector.NO_CREATIVE_OR_SPECTATOR::test); ++ public OcelotTemptGoal(Ocelot ocelot, double speedModifier, Ingredient recipeitemstack, boolean items) { ++ super(ocelot, speedModifier, recipeitemstack, items); + this.ocelot = ocelot; + } + + @Override +- public boolean canUse() { +- return !this.ocelot.isTrusting() && super.canUse(); ++ protected boolean canScare() { ++ return super.canScare() && !this.ocelot.isTrusting(); + } +- +- @Override +- public boolean canContinueToUse() { +- return !this.ocelot.isTrusting() && super.canContinueToUse(); +- } + } + +- static class OcelotTemptGoal extends TemptGoal { ++ private static class OcelotAvoidEntityGoal extends AvoidEntityGoal { ++ + private final Ocelot ocelot; + +- public OcelotTemptGoal(Ocelot ocelot, double speedModifier, Ingredient items, boolean canScare) { +- super(ocelot, speedModifier, items, canScare); ++ public OcelotAvoidEntityGoal(Ocelot ocelot, Class entityClassToAvoid, float maxDist, double walkSpeedModifier, double d1) { ++ // Predicate predicate = IEntitySelector.NO_CREATIVE_OR_SPECTATOR; // CraftBukkit - decompile error ++ ++ // Objects.requireNonNull(predicate); // CraftBukkit - decompile error ++ super(ocelot, entityClassToAvoid, maxDist, walkSpeedModifier, d1, EntitySelector.NO_CREATIVE_OR_SPECTATOR::test); // CraftBukkit - decompile error + this.ocelot = ocelot; + } + + @Override +- protected boolean canScare() { +- return super.canScare() && !this.ocelot.isTrusting(); ++ public boolean canUse() { ++ return !this.ocelot.isTrusting() && super.canUse(); + } ++ ++ @Override ++ public boolean canContinueToUse() { ++ return !this.ocelot.isTrusting() && super.canContinueToUse(); ++ } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Panda.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Panda.java.patch new file mode 100644 index 0000000000..4fbfab1d22 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Panda.java.patch @@ -0,0 +1,1169 @@ +--- a/net/minecraft/world/entity/animal/Panda.java ++++ b/net/minecraft/world/entity/animal/Panda.java +@@ -1,7 +1,9 @@ + package net.minecraft.world.entity.animal; + + import java.util.EnumSet; ++import java.util.Iterator; + import java.util.List; ++import java.util.Objects; + import java.util.function.IntFunction; + import java.util.function.Predicate; + import javax.annotation.Nullable; +@@ -20,7 +22,7 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.util.StringRepresentable; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; +@@ -28,11 +30,11 @@ + import net.minecraft.world.entity.EntityDimensions; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.MoveControl; +@@ -56,22 +58,29 @@ + import net.minecraft.world.item.Items; + import net.minecraft.world.item.crafting.Ingredient; + import net.minecraft.world.level.GameRules; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end ++ + public class Panda extends Animal { ++ + private static final EntityDataAccessor UNHAPPY_COUNTER = SynchedEntityData.defineId(Panda.class, EntityDataSerializers.INT); + private static final EntityDataAccessor SNEEZE_COUNTER = SynchedEntityData.defineId(Panda.class, EntityDataSerializers.INT); + private static final EntityDataAccessor EAT_COUNTER = SynchedEntityData.defineId(Panda.class, EntityDataSerializers.INT); + private static final EntityDataAccessor MAIN_GENE_ID = SynchedEntityData.defineId(Panda.class, EntityDataSerializers.BYTE); + private static final EntityDataAccessor HIDDEN_GENE_ID = SynchedEntityData.defineId(Panda.class, EntityDataSerializers.BYTE); + private static final EntityDataAccessor DATA_ID_FLAGS = SynchedEntityData.defineId(Panda.class, EntityDataSerializers.BYTE); +- static final TargetingConditions BREED_TARGETING = TargetingConditions.forNonCombat().range(8.0); ++ static final TargetingConditions BREED_TARGETING = TargetingConditions.forNonCombat().range(8.0D); + private static final int FLAG_SNEEZE = 2; + private static final int FLAG_ROLL = 4; + private static final int FLAG_SIT = 8; +@@ -90,9 +99,10 @@ + private float rollAmount; + private float rollAmountO; + Panda.PandaLookAtPlayerGoal lookAtPlayerGoal; +- static final Predicate PANDA_ITEMS = itemEntity -> { +- ItemStack item = itemEntity.getItem(); +- return (item.is(Blocks.BAMBOO.asItem()) || item.is(Blocks.CAKE.asItem())) && itemEntity.isAlive() && !itemEntity.hasPickUpDelay(); ++ static final Predicate PANDA_ITEMS = (entityitem) -> { ++ ItemStack itemstack = entityitem.getItem(); ++ ++ return (itemstack.is(Blocks.BAMBOO.asItem()) || itemstack.is(Blocks.CAKE.asItem())) && entityitem.isAlive() && !entityitem.hasPickUpDelay(); + }; + + public Panda(EntityType entityType, Level level) { +@@ -101,20 +111,22 @@ + if (!this.isBaby()) { + this.setCanPickUpLoot(true); + } ++ + } + + @Override + public boolean canTakeItem(ItemStack itemstack) { +- EquipmentSlot equipmentSlotForItem = Mob.getEquipmentSlotForItem(itemstack); +- return this.getItemBySlot(equipmentSlotForItem).isEmpty() && equipmentSlotForItem == EquipmentSlot.MAINHAND && super.canTakeItem(itemstack); ++ EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(itemstack); ++ ++ return !this.getItemBySlot(enumitemslot).isEmpty() ? false : enumitemslot == EquipmentSlot.MAINHAND && super.canTakeItem(itemstack); + } + + public int getUnhappyCounter() { +- return this.entityData.get(UNHAPPY_COUNTER); ++ return (Integer) this.entityData.get(Panda.UNHAPPY_COUNTER); + } + + public void setUnhappyCounter(int unhappyCounter) { +- this.entityData.set(UNHAPPY_COUNTER, unhappyCounter); ++ this.entityData.set(Panda.UNHAPPY_COUNTER, unhappyCounter); + } + + public boolean isSneezing() { +@@ -138,19 +150,19 @@ + } + + public boolean isEating() { +- return this.entityData.get(EAT_COUNTER) > 0; ++ return (Integer) this.entityData.get(Panda.EAT_COUNTER) > 0; + } + + public void eat(boolean eating) { +- this.entityData.set(EAT_COUNTER, eating ? 1 : 0); ++ this.entityData.set(Panda.EAT_COUNTER, eating ? 1 : 0); + } + + private int getEatCounter() { +- return this.entityData.get(EAT_COUNTER); ++ return (Integer) this.entityData.get(Panda.EAT_COUNTER); + } + + private void setEatCounter(int eatCounter) { +- this.entityData.set(EAT_COUNTER, eatCounter); ++ this.entityData.set(Panda.EAT_COUNTER, eatCounter); + } + + public void sneeze(boolean sneezing) { +@@ -158,18 +170,19 @@ + if (!sneezing) { + this.setSneezeCounter(0); + } ++ + } + + public int getSneezeCounter() { +- return this.entityData.get(SNEEZE_COUNTER); ++ return (Integer) this.entityData.get(Panda.SNEEZE_COUNTER); + } + + public void setSneezeCounter(int sneezeCounter) { +- this.entityData.set(SNEEZE_COUNTER, sneezeCounter); ++ this.entityData.set(Panda.SNEEZE_COUNTER, sneezeCounter); + } + + public Panda.Gene getMainGene() { +- return Panda.Gene.byId(this.entityData.get(MAIN_GENE_ID)); ++ return Panda.Gene.byId((Byte) this.entityData.get(Panda.MAIN_GENE_ID)); + } + + public void setMainGene(Panda.Gene pandaType) { +@@ -177,11 +190,11 @@ + pandaType = Panda.Gene.getRandom(this.random); + } + +- this.entityData.set(MAIN_GENE_ID, (byte)pandaType.getId()); ++ this.entityData.set(Panda.MAIN_GENE_ID, (byte) pandaType.getId()); + } + + public Panda.Gene getHiddenGene() { +- return Panda.Gene.byId(this.entityData.get(HIDDEN_GENE_ID)); ++ return Panda.Gene.byId((Byte) this.entityData.get(Panda.HIDDEN_GENE_ID)); + } + + public void setHiddenGene(Panda.Gene pandaType) { +@@ -189,7 +202,7 @@ + pandaType = Panda.Gene.getRandom(this.random); + } + +- this.entityData.set(HIDDEN_GENE_ID, (byte)pandaType.getId()); ++ this.entityData.set(Panda.HIDDEN_GENE_ID, (byte) pandaType.getId()); + } + + public boolean isRolling() { +@@ -203,25 +216,27 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(UNHAPPY_COUNTER, 0); +- this.entityData.define(SNEEZE_COUNTER, 0); +- this.entityData.define(MAIN_GENE_ID, (byte)0); +- this.entityData.define(HIDDEN_GENE_ID, (byte)0); +- this.entityData.define(DATA_ID_FLAGS, (byte)0); +- this.entityData.define(EAT_COUNTER, 0); ++ this.entityData.define(Panda.UNHAPPY_COUNTER, 0); ++ this.entityData.define(Panda.SNEEZE_COUNTER, 0); ++ this.entityData.define(Panda.MAIN_GENE_ID, (byte) 0); ++ this.entityData.define(Panda.HIDDEN_GENE_ID, (byte) 0); ++ this.entityData.define(Panda.DATA_ID_FLAGS, (byte) 0); ++ this.entityData.define(Panda.EAT_COUNTER, 0); + } + + private boolean getFlag(int flag) { +- return (this.entityData.get(DATA_ID_FLAGS) & flag) != 0; ++ return ((Byte) this.entityData.get(Panda.DATA_ID_FLAGS) & flag) != 0; + } + + private void setFlag(int flagId, boolean value) { +- byte b = this.entityData.get(DATA_ID_FLAGS); ++ byte b0 = (Byte) this.entityData.get(Panda.DATA_ID_FLAGS); ++ + if (value) { +- this.entityData.set(DATA_ID_FLAGS, (byte)(b | flagId)); ++ this.entityData.set(Panda.DATA_ID_FLAGS, (byte) (b0 | flagId)); + } else { +- this.entityData.set(DATA_ID_FLAGS, (byte)(b & ~flagId)); ++ this.entityData.set(Panda.DATA_ID_FLAGS, (byte) (b0 & ~flagId)); + } ++ + } + + @Override +@@ -241,27 +256,30 @@ + @Nullable + @Override + public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob otherParent) { +- Panda panda = EntityType.PANDA.create(level); +- if (panda != null) { +- if (otherParent instanceof Panda panda1) { +- panda.setGeneFromParents(this, panda1); ++ Panda entitypanda = (Panda) EntityType.PANDA.create(level); ++ ++ if (entitypanda != null) { ++ if (otherParent instanceof Panda) { ++ Panda entitypanda1 = (Panda) otherParent; ++ ++ entitypanda.setGeneFromParents(this, entitypanda1); + } + +- panda.setAttributes(); ++ entitypanda.setAttributes(); + } + +- return panda; ++ return entitypanda; + } + + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); +- this.goalSelector.addGoal(2, new Panda.PandaPanicGoal(this, 2.0)); +- this.goalSelector.addGoal(2, new Panda.PandaBreedGoal(this, 1.0)); +- this.goalSelector.addGoal(3, new Panda.PandaAttackGoal(this, 1.2F, true)); +- this.goalSelector.addGoal(4, new TemptGoal(this, 1.0, Ingredient.of(Blocks.BAMBOO.asItem()), false)); +- this.goalSelector.addGoal(6, new Panda.PandaAvoidGoal<>(this, Player.class, 8.0F, 2.0, 2.0)); +- this.goalSelector.addGoal(6, new Panda.PandaAvoidGoal<>(this, Monster.class, 4.0F, 2.0, 2.0)); ++ this.goalSelector.addGoal(2, new Panda.PandaPanicGoal(this, 2.0D)); ++ this.goalSelector.addGoal(2, new Panda.PandaBreedGoal(this, 1.0D)); ++ this.goalSelector.addGoal(3, new Panda.PandaAttackGoal(this, 1.2000000476837158D, true)); ++ this.goalSelector.addGoal(4, new TemptGoal(this, 1.0D, Ingredient.of(Blocks.BAMBOO.asItem()), false)); ++ this.goalSelector.addGoal(6, new Panda.PandaAvoidGoal<>(this, Player.class, 8.0F, 2.0D, 2.0D)); ++ this.goalSelector.addGoal(6, new Panda.PandaAvoidGoal<>(this, Monster.class, 4.0F, 2.0D, 2.0D)); + this.goalSelector.addGoal(7, new Panda.PandaSitGoal()); + this.goalSelector.addGoal(8, new Panda.PandaLieOnBackGoal(this)); + this.goalSelector.addGoal(8, new Panda.PandaSneezeGoal(this)); +@@ -269,13 +287,13 @@ + this.goalSelector.addGoal(9, this.lookAtPlayerGoal); + this.goalSelector.addGoal(10, new RandomLookAroundGoal(this)); + this.goalSelector.addGoal(12, new Panda.PandaRollGoal(this)); +- this.goalSelector.addGoal(13, new FollowParentGoal(this, 1.25)); +- this.goalSelector.addGoal(14, new WaterAvoidingRandomStrollGoal(this, 1.0)); +- this.targetSelector.addGoal(1, new Panda.PandaHurtByTargetGoal(this).setAlertOthers(new Class[0])); ++ this.goalSelector.addGoal(13, new FollowParentGoal(this, 1.25D)); ++ this.goalSelector.addGoal(14, new WaterAvoidingRandomStrollGoal(this, 1.0D)); ++ this.targetSelector.addGoal(1, (new Panda.PandaHurtByTargetGoal(this, new Class[0])).setAlertOthers(new Class[0])); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.15F).add(Attributes.ATTACK_DAMAGE, 6.0); ++ return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.15000000596046448D).add(Attributes.ATTACK_DAMAGE, 6.0D); + } + + public Panda.Gene getVariant() { +@@ -334,15 +352,16 @@ + } + } + +- LivingEntity target = this.getTarget(); +- if (target == null) { ++ LivingEntity entityliving = this.getTarget(); ++ ++ if (entityliving == null) { + this.gotBamboo = false; + this.didBite = false; + } + + if (this.getUnhappyCounter() > 0) { +- if (target != null) { +- this.lookAt(target, 90.0F, 90.0F); ++ if (entityliving != null) { ++ this.lookAt(entityliving, 90.0F, 90.0F); + } + + if (this.getUnhappyCounter() == 29 || this.getUnhappyCounter() == 14) { +@@ -407,34 +426,27 @@ + + this.setEatCounter(this.getEatCounter() + 1); + } ++ + } + + private void addEatingParticles() { + if (this.getEatCounter() % 5 == 0) { +- this.playSound( +- SoundEvents.PANDA_EAT, 0.5F + 0.5F * (float)this.random.nextInt(2), (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F +- ); ++ this.playSound(SoundEvents.PANDA_EAT, 0.5F + 0.5F * (float) this.random.nextInt(2), (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); + +- for (int i = 0; i < 6; i++) { +- Vec3 vec3 = new Vec3(((double)this.random.nextFloat() - 0.5) * 0.1, Math.random() * 0.1 + 0.1, ((double)this.random.nextFloat() - 0.5) * 0.1); +- vec3 = vec3.xRot(-this.getXRot() * (float) (Math.PI / 180.0)); +- vec3 = vec3.yRot(-this.getYRot() * (float) (Math.PI / 180.0)); +- double d = (double)(-this.random.nextFloat()) * 0.6 - 0.3; +- Vec3 vec31 = new Vec3(((double)this.random.nextFloat() - 0.5) * 0.8, d, 1.0 + ((double)this.random.nextFloat() - 0.5) * 0.4); +- vec31 = vec31.yRot(-this.yBodyRot * (float) (Math.PI / 180.0)); +- vec31 = vec31.add(this.getX(), this.getEyeY() + 1.0, this.getZ()); +- this.level() +- .addParticle( +- new ItemParticleOption(ParticleTypes.ITEM, this.getItemBySlot(EquipmentSlot.MAINHAND)), +- vec31.x, +- vec31.y, +- vec31.z, +- vec3.x, +- vec3.y + 0.05, +- vec3.z +- ); ++ for (int i = 0; i < 6; ++i) { ++ Vec3 vec3d = new Vec3(((double) this.random.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, ((double) this.random.nextFloat() - 0.5D) * 0.1D); ++ ++ vec3d = vec3d.xRot(-this.getXRot() * 0.017453292F); ++ vec3d = vec3d.yRot(-this.getYRot() * 0.017453292F); ++ double d0 = (double) (-this.random.nextFloat()) * 0.6D - 0.3D; ++ Vec3 vec3d1 = new Vec3(((double) this.random.nextFloat() - 0.5D) * 0.8D, d0, 1.0D + ((double) this.random.nextFloat() - 0.5D) * 0.4D); ++ ++ vec3d1 = vec3d1.yRot(-this.yBodyRot * 0.017453292F); ++ vec3d1 = vec3d1.add(this.getX(), this.getEyeY() + 1.0D, this.getZ()); ++ this.level().addParticle(new ItemParticleOption(ParticleTypes.ITEM, this.getItemBySlot(EquipmentSlot.MAINHAND)), vec3d1.x, vec3d1.y, vec3d1.z, vec3d.x, vec3d.y + 0.05D, vec3d.z); + } + } ++ + } + + private void updateSitAmount() { +@@ -444,6 +456,7 @@ + } else { + this.sitAmount = Math.max(0.0F, this.sitAmount - 0.19F); + } ++ + } + + private void updateOnBackAnimation() { +@@ -453,6 +466,7 @@ + } else { + this.onBackAmount = Math.max(0.0F, this.onBackAmount - 0.19F); + } ++ + } + + private void updateRollAmount() { +@@ -462,6 +476,7 @@ + } else { + this.rollAmount = Math.max(0.0F, this.rollAmount - 0.19F); + } ++ + } + + public float getSitAmount(float partialTick) { +@@ -477,61 +492,63 @@ + } + + private void handleRoll() { +- this.rollCounter++; ++ ++this.rollCounter; + if (this.rollCounter > 32) { + this.roll(false); + } else { + if (!this.level().isClientSide) { +- Vec3 deltaMovement = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); ++ + if (this.rollCounter == 1) { +- float f = this.getYRot() * (float) (Math.PI / 180.0); ++ float f = this.getYRot() * 0.017453292F; + float f1 = this.isBaby() ? 0.1F : 0.2F; +- this.rollDelta = new Vec3(deltaMovement.x + (double)(-Mth.sin(f) * f1), 0.0, deltaMovement.z + (double)(Mth.cos(f) * f1)); +- this.setDeltaMovement(this.rollDelta.add(0.0, 0.27, 0.0)); +- } else if ((float)this.rollCounter != 7.0F && (float)this.rollCounter != 15.0F && (float)this.rollCounter != 23.0F) { +- this.setDeltaMovement(this.rollDelta.x, deltaMovement.y, this.rollDelta.z); ++ ++ this.rollDelta = new Vec3(vec3d.x + (double) (-Mth.sin(f) * f1), 0.0D, vec3d.z + (double) (Mth.cos(f) * f1)); ++ this.setDeltaMovement(this.rollDelta.add(0.0D, 0.27D, 0.0D)); ++ } else if ((float) this.rollCounter != 7.0F && (float) this.rollCounter != 15.0F && (float) this.rollCounter != 23.0F) { ++ this.setDeltaMovement(this.rollDelta.x, vec3d.y, this.rollDelta.z); + } else { +- this.setDeltaMovement(0.0, this.onGround() ? 0.27 : deltaMovement.y, 0.0); ++ this.setDeltaMovement(0.0D, this.onGround() ? 0.27D : vec3d.y, 0.0D); + } + } ++ + } + } + + private void afterSneeze() { +- Vec3 deltaMovement = this.getDeltaMovement(); +- this.level() +- .addParticle( +- ParticleTypes.SNEEZE, +- this.getX() - (double)(this.getBbWidth() + 1.0F) * 0.5 * (double)Mth.sin(this.yBodyRot * (float) (Math.PI / 180.0)), +- this.getEyeY() - 0.1F, +- this.getZ() + (double)(this.getBbWidth() + 1.0F) * 0.5 * (double)Mth.cos(this.yBodyRot * (float) (Math.PI / 180.0)), +- deltaMovement.x, +- 0.0, +- deltaMovement.z +- ); ++ Vec3 vec3d = this.getDeltaMovement(); ++ ++ this.level().addParticle(ParticleTypes.SNEEZE, this.getX() - (double) (this.getBbWidth() + 1.0F) * 0.5D * (double) Mth.sin(this.yBodyRot * 0.017453292F), this.getEyeY() - 0.10000000149011612D, this.getZ() + (double) (this.getBbWidth() + 1.0F) * 0.5D * (double) Mth.cos(this.yBodyRot * 0.017453292F), vec3d.x, 0.0D, vec3d.z); + this.playSound(SoundEvents.PANDA_SNEEZE, 1.0F, 1.0F); ++ List list = this.level().getEntitiesOfClass(Panda.class, this.getBoundingBox().inflate(10.0D)); ++ Iterator iterator = list.iterator(); + +- for (Panda panda : this.level().getEntitiesOfClass(Panda.class, this.getBoundingBox().inflate(10.0))) { +- if (!panda.isBaby() && panda.onGround() && !panda.isInWater() && panda.canPerformAction()) { +- panda.jumpFromGround(); ++ while (iterator.hasNext()) { ++ Panda entitypanda = (Panda) iterator.next(); ++ ++ if (!entitypanda.isBaby() && entitypanda.onGround() && !entitypanda.isInWater() && entitypanda.canPerformAction()) { ++ entitypanda.jumpFromGround(); + } + } + + if (!this.level().isClientSide() && this.random.nextInt(700) == 0 && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +- this.spawnAtLocation(Items.SLIME_BALL); ++ this.spawnAtLocation((IMaterial) Items.SLIME_BALL); + } ++ + } + + @Override + protected void pickUpItem(ItemEntity itemEntity) { +- if (this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty() && PANDA_ITEMS.test(itemEntity)) { ++ if (!CraftEventFactory.callEntityPickupItemEvent(this, itemEntity, 0, !(this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty() && Panda.PANDA_ITEMS.test(itemEntity))).isCancelled()) { // CraftBukkit + this.onItemPickup(itemEntity); +- ItemStack item = itemEntity.getItem(); +- this.setItemSlot(EquipmentSlot.MAINHAND, item); ++ ItemStack itemstack = itemEntity.getItem(); ++ ++ this.setItemSlot(EquipmentSlot.MAINHAND, itemstack); + this.setGuaranteedDrop(EquipmentSlot.MAINHAND); +- this.take(itemEntity, item.getCount()); ++ this.take(itemEntity, itemstack.getCount()); + itemEntity.discard(); + } ++ + } + + @Override +@@ -545,18 +562,17 @@ + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- RandomSource random = level.getRandom(); +- this.setMainGene(Panda.Gene.getRandom(random)); +- this.setHiddenGene(Panda.Gene.getRandom(random)); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ RandomSource randomsource = level.getRandom(); ++ ++ this.setMainGene(Panda.Gene.getRandom(randomsource)); ++ this.setHiddenGene(Panda.Gene.getRandom(randomsource)); + this.setAttributes(); + if (spawnData == null) { + spawnData = new AgeableMob.AgeableMobGroupData(0.2F); + } + +- return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + + public void setGeneFromParents(Panda father, @Nullable Panda mother) { +@@ -583,6 +599,7 @@ + if (this.random.nextInt(32) == 0) { + this.setHiddenGene(Panda.Gene.getRandom(this.random)); + } ++ + } + + private Panda.Gene getOneOfGenesRandomly() { +@@ -591,12 +608,13 @@ + + public void setAttributes() { + if (this.isWeak()) { +- this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(10.0); ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(10.0D); + } + + if (this.isLazy()) { +- this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.07F); ++ this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.07000000029802322D); + } ++ + } + + void tryToSit() { +@@ -605,26 +623,28 @@ + this.getNavigation().stop(); + this.sit(true); + } ++ + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ + if (this.isScared()) { + return InteractionResult.PASS; + } else if (this.isOnBack()) { + this.setOnBack(false); + return InteractionResult.sidedSuccess(this.level().isClientSide); +- } else if (this.isFood(itemInHand)) { ++ } else if (this.isFood(itemstack)) { + if (this.getTarget() != null) { + this.gotBamboo = true; + } + + if (this.isBaby()) { +- this.usePlayerItem(player, hand, itemInHand); +- this.ageUp((int)((float)(-this.getAge() / 20) * 0.1F), true); ++ this.usePlayerItem(player, hand, itemstack); ++ this.ageUp((int) ((float) (-this.getAge() / 20) * 0.1F), true); + } else if (!this.level().isClientSide && this.getAge() == 0 && this.canFallInLove()) { +- this.usePlayerItem(player, hand, itemInHand); ++ this.usePlayerItem(player, hand, itemstack); + this.setInLove(player); + } else { + if (this.level().isClientSide || this.isSitting() || this.isInWater()) { +@@ -633,13 +653,14 @@ + + this.tryToSit(); + this.eat(true); +- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.MAINHAND); +- if (!itemBySlot.isEmpty() && !player.getAbilities().instabuild) { +- this.spawnAtLocation(itemBySlot); ++ ItemStack itemstack1 = this.getItemBySlot(EquipmentSlot.MAINHAND); ++ ++ if (!itemstack1.isEmpty() && !player.getAbilities().instabuild) { ++ this.spawnAtLocation(itemstack1); + } + +- this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(itemInHand.getItem(), 1)); +- this.usePlayerItem(player, hand, itemInHand); ++ this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(itemstack.getItem(), 1)); ++ this.usePlayerItem(player, hand, itemstack); + } + + return InteractionResult.SUCCESS; +@@ -651,15 +672,11 @@ + @Nullable + @Override + protected SoundEvent getAmbientSound() { +- if (this.isAggressive()) { +- return SoundEvents.PANDA_AGGRESSIVE_AMBIENT; +- } else { +- return this.isWorried() ? SoundEvents.PANDA_WORRIED_AMBIENT : SoundEvents.PANDA_AMBIENT; +- } ++ return this.isAggressive() ? SoundEvents.PANDA_AGGRESSIVE_AMBIENT : (this.isWorried() ? SoundEvents.PANDA_WORRIED_AMBIENT : SoundEvents.PANDA_AMBIENT); + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.PANDA_STEP, 0.15F, 1.0F); + } + +@@ -689,30 +706,42 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height - (this.isBaby() ? 0.4375F : 0.0F) * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - (this.isBaby() ? 0.4375F : 0.0F) * f, 0.0F); + } + ++ private static class PandaMoveControl extends MoveControl { ++ ++ private final Panda panda; ++ ++ public PandaMoveControl(Panda panda) { ++ super(panda); ++ this.panda = panda; ++ } ++ ++ @Override ++ public void tick() { ++ if (this.panda.canPerformAction()) { ++ super.tick(); ++ } ++ } ++ } ++ + public static enum Gene implements StringRepresentable { +- NORMAL(0, "normal", false), +- LAZY(1, "lazy", false), +- WORRIED(2, "worried", false), +- PLAYFUL(3, "playful", false), +- BROWN(4, "brown", true), +- WEAK(5, "weak", true), +- AGGRESSIVE(6, "aggressive", false); + ++ NORMAL(0, "normal", false), LAZY(1, "lazy", false), WORRIED(2, "worried", false), PLAYFUL(3, "playful", false), BROWN(4, "brown", true), WEAK(5, "weak", true), AGGRESSIVE(6, "aggressive", false); ++ + public static final StringRepresentable.EnumCodec CODEC = StringRepresentable.fromEnum(Panda.Gene::values); +- private static final IntFunction BY_ID = ByIdMap.continuous(Panda.Gene::getId, values(), ByIdMap.OutOfBoundsStrategy.ZERO); ++ private static final IntFunction BY_ID = ByIdMap.continuous(Panda.Gene::getId, values(), ByIdMap.a.ZERO); + private static final int MAX_GENE = 6; + private final int id; + private final String name; + private final boolean isRecessive; + +- private Gene(int id, String name, boolean isRecessive) { +- this.id = id; +- this.name = name; +- this.isRecessive = isRecessive; ++ private Gene(int i, String s, boolean flag) { ++ this.id = i; ++ this.name = s; ++ this.isRecessive = flag; + } + + public int getId() { +@@ -729,68 +758,51 @@ + } + + static Panda.Gene getVariantFromGenes(Panda.Gene mainGene, Panda.Gene hiddenGene) { +- if (mainGene.isRecessive()) { +- return mainGene == hiddenGene ? mainGene : NORMAL; +- } else { +- return mainGene; +- } ++ return mainGene.isRecessive() ? (mainGene == hiddenGene ? mainGene : Panda.Gene.NORMAL) : mainGene; + } + + public static Panda.Gene byId(int index) { +- return BY_ID.apply(index); ++ return (Panda.Gene) Panda.Gene.BY_ID.apply(index); + } + + public static Panda.Gene byName(String name) { +- return CODEC.byName(name, NORMAL); ++ return (Panda.Gene) Panda.Gene.CODEC.byName(name, Panda.Gene.NORMAL); + } + + public static Panda.Gene getRandom(RandomSource random) { +- int randomInt = random.nextInt(16); +- if (randomInt == 0) { +- return LAZY; +- } else if (randomInt == 1) { +- return WORRIED; +- } else if (randomInt == 2) { +- return PLAYFUL; +- } else if (randomInt == 4) { +- return AGGRESSIVE; +- } else if (randomInt < 9) { +- return WEAK; +- } else { +- return randomInt < 11 ? BROWN : NORMAL; +- } ++ int i = random.nextInt(16); ++ ++ return i == 0 ? Panda.Gene.LAZY : (i == 1 ? Panda.Gene.WORRIED : (i == 2 ? Panda.Gene.PLAYFUL : (i == 4 ? Panda.Gene.AGGRESSIVE : (i < 9 ? Panda.Gene.WEAK : (i < 11 ? Panda.Gene.BROWN : Panda.Gene.NORMAL))))); + } + } + +- static class PandaAttackGoal extends MeleeAttackGoal { ++ private static class PandaPanicGoal extends PanicGoal { ++ + private final Panda panda; + +- public PandaAttackGoal(Panda panda, double speedModifier, boolean followingTargetEvenIfNotSeen) { +- super(panda, speedModifier, followingTargetEvenIfNotSeen); ++ public PandaPanicGoal(Panda panda, double speedModifier) { ++ super(panda, speedModifier); + this.panda = panda; + } + + @Override +- public boolean canUse() { +- return this.panda.canPerformAction() && super.canUse(); ++ protected boolean shouldPanic() { ++ return this.mob.isFreezing() || this.mob.isOnFire(); + } +- } + +- static class PandaAvoidGoal extends AvoidEntityGoal { +- private final Panda panda; +- +- public PandaAvoidGoal(Panda panda, Class entityClassToAvoid, float maxDist, double walkSpeedModifier, double sprintSpeedModifier) { +- super(panda, entityClassToAvoid, maxDist, walkSpeedModifier, sprintSpeedModifier, EntitySelector.NO_SPECTATORS::test); +- this.panda = panda; +- } +- + @Override +- public boolean canUse() { +- return this.panda.isWorried() && this.panda.canPerformAction() && super.canUse(); ++ public boolean canContinueToUse() { ++ if (this.panda.isSitting()) { ++ this.panda.getNavigation().stop(); ++ return false; ++ } else { ++ return super.canContinueToUse(); ++ } + } + } + +- static class PandaBreedGoal extends BreedGoal { ++ private static class PandaBreedGoal extends BreedGoal { ++ + private final Panda panda; + private int unhappyCooldown; + +@@ -801,34 +813,37 @@ + + @Override + public boolean canUse() { +- if (!super.canUse() || this.panda.getUnhappyCounter() != 0) { +- return false; +- } else if (!this.canFindBamboo()) { +- if (this.unhappyCooldown <= this.panda.tickCount) { +- this.panda.setUnhappyCounter(32); +- this.unhappyCooldown = this.panda.tickCount + 600; +- if (this.panda.isEffectiveAi()) { +- Player nearestPlayer = this.level.getNearestPlayer(Panda.BREED_TARGETING, this.panda); +- this.panda.lookAtPlayerGoal.setTarget(nearestPlayer); ++ if (super.canUse() && this.panda.getUnhappyCounter() == 0) { ++ if (!this.canFindBamboo()) { ++ if (this.unhappyCooldown <= this.panda.tickCount) { ++ this.panda.setUnhappyCounter(32); ++ this.unhappyCooldown = this.panda.tickCount + 600; ++ if (this.panda.isEffectiveAi()) { ++ Player entityhuman = this.level.getNearestPlayer(Panda.BREED_TARGETING, this.panda); ++ ++ this.panda.lookAtPlayerGoal.setTarget(entityhuman); ++ } + } +- } + +- return false; ++ return false; ++ } else { ++ return true; ++ } + } else { +- return true; ++ return false; + } + } + + private boolean canFindBamboo() { +- BlockPos blockPos = this.panda.blockPosition(); +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ BlockPos blockposition = this.panda.blockPosition(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + +- for (int i = 0; i < 3; i++) { +- for (int i1 = 0; i1 < 8; i1++) { +- for (int i2 = 0; i2 <= i1; i2 = i2 > 0 ? -i2 : 1 - i2) { +- for (int i3 = i2 < i1 && i2 > -i1 ? i1 : 0; i3 <= i1; i3 = i3 > 0 ? -i3 : 1 - i3) { +- mutableBlockPos.setWithOffset(blockPos, i2, i, i3); +- if (this.level.getBlockState(mutableBlockPos).is(Blocks.BAMBOO)) { ++ for (int i = 0; i < 3; ++i) { ++ for (int j = 0; j < 8; ++j) { ++ for (int k = 0; k <= j; k = k > 0 ? -k : 1 - k) { ++ for (int l = k < j && k > -j ? j : 0; l <= j; l = l > 0 ? -l : 1 - l) { ++ blockposition_mutableblockposition.setWithOffset(blockposition, k, i, l); ++ if (this.level.getBlockState(blockposition_mutableblockposition).is(Blocks.BAMBOO)) { + return true; + } + } +@@ -840,33 +855,102 @@ + } + } + +- static class PandaHurtByTargetGoal extends HurtByTargetGoal { ++ private static class PandaAttackGoal extends MeleeAttackGoal { ++ + private final Panda panda; + +- public PandaHurtByTargetGoal(Panda panda, Class... entityClassToIgnoreDamage) { +- super(panda, entityClassToIgnoreDamage); ++ public PandaAttackGoal(Panda panda, double speedModifier, boolean flag) { ++ super(panda, speedModifier, flag); + this.panda = panda; + } + + @Override +- public boolean canContinueToUse() { +- if (!this.panda.gotBamboo && !this.panda.didBite) { +- return super.canContinueToUse(); ++ public boolean canUse() { ++ return this.panda.canPerformAction() && super.canUse(); ++ } ++ } ++ ++ private static class PandaAvoidGoal extends AvoidEntityGoal { ++ ++ private final Panda panda; ++ ++ public PandaAvoidGoal(Panda panda, Class entityClassToAvoid, float maxDist, double walkSpeedModifier, double d1) { ++ // Predicate predicate = IEntitySelector.NO_SPECTATORS; ++ ++ // Objects.requireNonNull(predicate); ++ super(panda, entityClassToAvoid, maxDist, walkSpeedModifier, d1, EntitySelector.NO_SPECTATORS::test); ++ this.panda = panda; ++ } ++ ++ @Override ++ public boolean canUse() { ++ return this.panda.isWorried() && this.panda.canPerformAction() && super.canUse(); ++ } ++ } ++ ++ private class PandaSitGoal extends Goal { ++ ++ private int cooldown; ++ ++ public PandaSitGoal() { ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); ++ } ++ ++ @Override ++ public boolean canUse() { ++ if (this.cooldown <= Panda.this.tickCount && !Panda.this.isBaby() && !Panda.this.isInWater() && Panda.this.canPerformAction() && Panda.this.getUnhappyCounter() <= 0) { ++ List list = Panda.this.level().getEntitiesOfClass(ItemEntity.class, Panda.this.getBoundingBox().inflate(6.0D, 6.0D, 6.0D), Panda.PANDA_ITEMS); ++ ++ return !list.isEmpty() || !Panda.this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty(); + } else { +- this.panda.setTarget(null); + return false; + } + } + + @Override +- protected void alertOther(Mob mob, LivingEntity target) { +- if (mob instanceof Panda && mob.isAggressive()) { +- mob.setTarget(target); ++ public boolean canContinueToUse() { ++ return !Panda.this.isInWater() && (Panda.this.isLazy() || Panda.this.random.nextInt(reducedTickDelay(600)) != 1) ? Panda.this.random.nextInt(reducedTickDelay(2000)) != 1 : false; ++ } ++ ++ @Override ++ public void tick() { ++ if (!Panda.this.isSitting() && !Panda.this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty()) { ++ Panda.this.tryToSit(); + } ++ + } ++ ++ @Override ++ public void start() { ++ List list = Panda.this.level().getEntitiesOfClass(ItemEntity.class, Panda.this.getBoundingBox().inflate(8.0D, 8.0D, 8.0D), Panda.PANDA_ITEMS); ++ ++ if (!list.isEmpty() && Panda.this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty()) { ++ Panda.this.getNavigation().moveTo((Entity) list.get(0), 1.2000000476837158D); ++ } else if (!Panda.this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty()) { ++ Panda.this.tryToSit(); ++ } ++ ++ this.cooldown = 0; ++ } ++ ++ @Override ++ public void stop() { ++ ItemStack itemstack = Panda.this.getItemBySlot(EquipmentSlot.MAINHAND); ++ ++ if (!itemstack.isEmpty()) { ++ Panda.this.spawnAtLocation(itemstack); ++ Panda.this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); ++ int i = Panda.this.isLazy() ? Panda.this.random.nextInt(50) + 10 : Panda.this.random.nextInt(150) + 10; ++ ++ this.cooldown = Panda.this.tickCount + i * 20; ++ } ++ ++ Panda.this.sit(false); ++ } + } + +- static class PandaLieOnBackGoal extends Goal { ++ private static class PandaLieOnBackGoal extends Goal { ++ + private final Panda panda; + private int cooldown; + +@@ -876,17 +960,12 @@ + + @Override + public boolean canUse() { +- return this.cooldown < this.panda.tickCount +- && this.panda.isLazy() +- && this.panda.canPerformAction() +- && this.panda.random.nextInt(reducedTickDelay(400)) == 1; ++ return this.cooldown < this.panda.tickCount && this.panda.isLazy() && this.panda.canPerformAction() && this.panda.random.nextInt(reducedTickDelay(400)) == 1; + } + + @Override + public boolean canContinueToUse() { +- return !this.panda.isInWater() +- && (this.panda.isLazy() || this.panda.random.nextInt(reducedTickDelay(600)) != 1) +- && this.panda.random.nextInt(reducedTickDelay(2000)) != 1; ++ return !this.panda.isInWater() && (this.panda.isLazy() || this.panda.random.nextInt(reducedTickDelay(600)) != 1) ? this.panda.random.nextInt(reducedTickDelay(2000)) != 1 : false; + } + + @Override +@@ -902,9 +981,34 @@ + } + } + +- static class PandaLookAtPlayerGoal extends LookAtPlayerGoal { ++ private static class PandaSneezeGoal extends Goal { ++ + private final Panda panda; + ++ public PandaSneezeGoal(Panda panda) { ++ this.panda = panda; ++ } ++ ++ @Override ++ public boolean canUse() { ++ return this.panda.isBaby() && this.panda.canPerformAction() ? (this.panda.isWeak() && this.panda.random.nextInt(reducedTickDelay(500)) == 1 ? true : this.panda.random.nextInt(reducedTickDelay(6000)) == 1) : false; ++ } ++ ++ @Override ++ public boolean canContinueToUse() { ++ return false; ++ } ++ ++ @Override ++ public void start() { ++ this.panda.sneeze(true); ++ } ++ } ++ ++ private static class PandaLookAtPlayerGoal extends LookAtPlayerGoal { ++ ++ private final Panda panda; ++ + public PandaLookAtPlayerGoal(Panda panda, Class lookAtType, float lookDistance) { + super(panda, lookAtType, lookDistance); + this.panda = panda; +@@ -928,22 +1032,9 @@ + if (this.lookAtType == Player.class) { + this.lookAt = this.mob.level().getNearestPlayer(this.lookAtContext, this.mob, this.mob.getX(), this.mob.getEyeY(), this.mob.getZ()); + } else { +- this.lookAt = this.mob +- .level() +- .getNearestEntity( +- this.mob +- .level() +- .getEntitiesOfClass( +- this.lookAtType, +- this.mob.getBoundingBox().inflate((double)this.lookDistance, 3.0, (double)this.lookDistance), +- livingEntity -> true +- ), +- this.lookAtContext, +- this.mob, +- this.mob.getX(), +- this.mob.getEyeY(), +- this.mob.getZ() +- ); ++ this.lookAt = this.mob.level().getNearestEntity(this.mob.level().getEntitiesOfClass(this.lookAtType, this.mob.getBoundingBox().inflate((double) this.lookDistance, 3.0D, (double) this.lookDistance), (entityliving) -> { ++ return true; ++ }), this.lookAtContext, this.mob, this.mob.getX(), this.mob.getEyeY(), this.mob.getZ()); + } + } + +@@ -956,55 +1047,17 @@ + if (this.lookAt != null) { + super.tick(); + } +- } +- } + +- static class PandaMoveControl extends MoveControl { +- private final Panda panda; +- +- public PandaMoveControl(Panda mob) { +- super(mob); +- this.panda = mob; + } +- +- @Override +- public void tick() { +- if (this.panda.canPerformAction()) { +- super.tick(); +- } +- } + } + +- static class PandaPanicGoal extends PanicGoal { +- private final Panda panda; ++ private static class PandaRollGoal extends Goal { + +- public PandaPanicGoal(Panda panda, double speedModifier) { +- super(panda, speedModifier); +- this.panda = panda; +- } +- +- @Override +- protected boolean shouldPanic() { +- return this.mob.isFreezing() || this.mob.isOnFire(); +- } +- +- @Override +- public boolean canContinueToUse() { +- if (this.panda.isSitting()) { +- this.panda.getNavigation().stop(); +- return false; +- } else { +- return super.canContinueToUse(); +- } +- } +- } +- +- static class PandaRollGoal extends Goal { + private final Panda panda; + + public PandaRollGoal(Panda panda) { + this.panda = panda; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK, Goal.Flag.JUMP)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK, Goal.Type.JUMP)); + } + + @Override +@@ -1013,14 +1066,13 @@ + if (!this.panda.canPerformAction()) { + return false; + } else { +- float f = this.panda.getYRot() * (float) (Math.PI / 180.0); ++ float f = this.panda.getYRot() * 0.017453292F; + float f1 = -Mth.sin(f); +- float cos = Mth.cos(f); +- int i = (double)Math.abs(f1) > 0.5 ? Mth.sign((double)f1) : 0; +- int i1 = (double)Math.abs(cos) > 0.5 ? Mth.sign((double)cos) : 0; +- return this.panda.level().getBlockState(this.panda.blockPosition().offset(i, -1, i1)).isAir() +- || this.panda.isPlayful() && this.panda.random.nextInt(reducedTickDelay(60)) == 1 +- || this.panda.random.nextInt(reducedTickDelay(500)) == 1; ++ float f2 = Mth.cos(f); ++ int i = (double) Math.abs(f1) > 0.5D ? Mth.sign((double) f1) : 0; ++ int j = (double) Math.abs(f2) > 0.5D ? Mth.sign((double) f2) : 0; ++ ++ return this.panda.level().getBlockState(this.panda.blockPosition().offset(i, -1, j)).isAir() ? true : (this.panda.isPlayful() && this.panda.random.nextInt(reducedTickDelay(60)) == 1 ? true : this.panda.random.nextInt(reducedTickDelay(500)) == 1); + } + } else { + return false; +@@ -1043,91 +1095,31 @@ + } + } + +- class PandaSitGoal extends Goal { +- private int cooldown; ++ private static class PandaHurtByTargetGoal extends HurtByTargetGoal { + +- public PandaSitGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ private final Panda panda; ++ ++ public PandaHurtByTargetGoal(Panda panda, Class... entityClassToIgnoreDamage) { ++ super(panda, entityClassToIgnoreDamage); ++ this.panda = panda; + } + + @Override +- public boolean canUse() { +- if (this.cooldown <= Panda.this.tickCount +- && !Panda.this.isBaby() +- && !Panda.this.isInWater() +- && Panda.this.canPerformAction() +- && Panda.this.getUnhappyCounter() <= 0) { +- List entitiesOfClass = Panda.this.level() +- .getEntitiesOfClass(ItemEntity.class, Panda.this.getBoundingBox().inflate(6.0, 6.0, 6.0), Panda.PANDA_ITEMS); +- return !entitiesOfClass.isEmpty() || !Panda.this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty(); ++ public boolean canContinueToUse() { ++ if (!this.panda.gotBamboo && !this.panda.didBite) { ++ return super.canContinueToUse(); + } else { ++ this.panda.setTarget((LivingEntity) null); + return false; + } + } + + @Override +- public boolean canContinueToUse() { +- return !Panda.this.isInWater() +- && (Panda.this.isLazy() || Panda.this.random.nextInt(reducedTickDelay(600)) != 1) +- && Panda.this.random.nextInt(reducedTickDelay(2000)) != 1; +- } +- +- @Override +- public void tick() { +- if (!Panda.this.isSitting() && !Panda.this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty()) { +- Panda.this.tryToSit(); ++ protected void alertOther(Mob mob, LivingEntity target) { ++ if (mob instanceof Panda && mob.isAggressive()) { ++ mob.setTarget(target, EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY, true); // CraftBukkit + } +- } + +- @Override +- public void start() { +- List entitiesOfClass = Panda.this.level() +- .getEntitiesOfClass(ItemEntity.class, Panda.this.getBoundingBox().inflate(8.0, 8.0, 8.0), Panda.PANDA_ITEMS); +- if (!entitiesOfClass.isEmpty() && Panda.this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty()) { +- Panda.this.getNavigation().moveTo(entitiesOfClass.get(0), 1.2F); +- } else if (!Panda.this.getItemBySlot(EquipmentSlot.MAINHAND).isEmpty()) { +- Panda.this.tryToSit(); +- } +- +- this.cooldown = 0; + } +- +- @Override +- public void stop() { +- ItemStack itemBySlot = Panda.this.getItemBySlot(EquipmentSlot.MAINHAND); +- if (!itemBySlot.isEmpty()) { +- Panda.this.spawnAtLocation(itemBySlot); +- Panda.this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); +- int i = Panda.this.isLazy() ? Panda.this.random.nextInt(50) + 10 : Panda.this.random.nextInt(150) + 10; +- this.cooldown = Panda.this.tickCount + i * 20; +- } +- +- Panda.this.sit(false); +- } + } +- +- static class PandaSneezeGoal extends Goal { +- private final Panda panda; +- +- public PandaSneezeGoal(Panda panda) { +- this.panda = panda; +- } +- +- @Override +- public boolean canUse() { +- return this.panda.isBaby() +- && this.panda.canPerformAction() +- && (this.panda.isWeak() && this.panda.random.nextInt(reducedTickDelay(500)) == 1 || this.panda.random.nextInt(reducedTickDelay(6000)) == 1); +- } +- +- @Override +- public boolean canContinueToUse() { +- return false; +- } +- +- @Override +- public void start() { +- this.panda.sneeze(true); +- } +- } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Parrot.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Parrot.java.patch new file mode 100644 index 0000000000..9df47fb787 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Parrot.java.patch @@ -0,0 +1,553 @@ +--- a/net/minecraft/world/entity/animal/Parrot.java ++++ b/net/minecraft/world/entity/animal/Parrot.java +@@ -4,7 +4,7 @@ + import com.google.common.collect.Maps; + import com.google.common.collect.Sets; + import com.mojang.serialization.Codec; +-import java.util.HashMap; ++import java.util.Iterator; + import java.util.List; + import java.util.Map; + import java.util.Set; +@@ -29,7 +29,7 @@ + import net.minecraft.util.StringRepresentable; + import net.minecraft.world.Difficulty; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffectInstance; +@@ -37,12 +37,12 @@ + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.PathfinderMob; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.VariantHolder; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -53,8 +53,8 @@ + import net.minecraft.world.entity.ai.goal.LandOnOwnersShoulderGoal; + import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; + import net.minecraft.world.entity.ai.goal.PanicGoal; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalRandomFly; + import net.minecraft.world.entity.ai.goal.SitWhenOrderedToGoal; +-import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomFlyingGoal; + import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation; + import net.minecraft.world.entity.ai.navigation.PathNavigation; + import net.minecraft.world.entity.ai.util.LandRandomPos; +@@ -67,59 +67,57 @@ + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.LeavesBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Parrot extends ShoulderRidingEntity implements VariantHolder, FlyingAnimal { ++public class Parrot extends ShoulderRidingEntity implements VariantHolder, EntityBird { ++ + private static final EntityDataAccessor DATA_VARIANT_ID = SynchedEntityData.defineId(Parrot.class, EntityDataSerializers.INT); + private static final Predicate NOT_PARROT_PREDICATE = new Predicate() { +- @Override + public boolean test(@Nullable Mob mob) { + return mob != null && Parrot.MOB_SOUND_MAP.containsKey(mob.getType()); + } + }; + private static final Item POISONOUS_FOOD = Items.COOKIE; +- private static final Set TAME_FOOD = Sets.newHashSet( +- Items.WHEAT_SEEDS, Items.MELON_SEEDS, Items.PUMPKIN_SEEDS, Items.BEETROOT_SEEDS, Items.TORCHFLOWER_SEEDS, Items.PITCHER_POD +- ); +- static final Map, SoundEvent> MOB_SOUND_MAP = Util.make(Maps.newHashMap(), map -> { +- map.put(EntityType.BLAZE, SoundEvents.PARROT_IMITATE_BLAZE); +- map.put(EntityType.BREEZE, SoundEvents.PARROT_IMITATE_BREEZE); +- map.put(EntityType.CAVE_SPIDER, SoundEvents.PARROT_IMITATE_SPIDER); +- map.put(EntityType.CREEPER, SoundEvents.PARROT_IMITATE_CREEPER); +- map.put(EntityType.DROWNED, SoundEvents.PARROT_IMITATE_DROWNED); +- map.put(EntityType.ELDER_GUARDIAN, SoundEvents.PARROT_IMITATE_ELDER_GUARDIAN); +- map.put(EntityType.ENDER_DRAGON, SoundEvents.PARROT_IMITATE_ENDER_DRAGON); +- map.put(EntityType.ENDERMITE, SoundEvents.PARROT_IMITATE_ENDERMITE); +- map.put(EntityType.EVOKER, SoundEvents.PARROT_IMITATE_EVOKER); +- map.put(EntityType.GHAST, SoundEvents.PARROT_IMITATE_GHAST); +- map.put(EntityType.GUARDIAN, SoundEvents.PARROT_IMITATE_GUARDIAN); +- map.put(EntityType.HOGLIN, SoundEvents.PARROT_IMITATE_HOGLIN); +- map.put(EntityType.HUSK, SoundEvents.PARROT_IMITATE_HUSK); +- map.put(EntityType.ILLUSIONER, SoundEvents.PARROT_IMITATE_ILLUSIONER); +- map.put(EntityType.MAGMA_CUBE, SoundEvents.PARROT_IMITATE_MAGMA_CUBE); +- map.put(EntityType.PHANTOM, SoundEvents.PARROT_IMITATE_PHANTOM); +- map.put(EntityType.PIGLIN, SoundEvents.PARROT_IMITATE_PIGLIN); +- map.put(EntityType.PIGLIN_BRUTE, SoundEvents.PARROT_IMITATE_PIGLIN_BRUTE); +- map.put(EntityType.PILLAGER, SoundEvents.PARROT_IMITATE_PILLAGER); +- map.put(EntityType.RAVAGER, SoundEvents.PARROT_IMITATE_RAVAGER); +- map.put(EntityType.SHULKER, SoundEvents.PARROT_IMITATE_SHULKER); +- map.put(EntityType.SILVERFISH, SoundEvents.PARROT_IMITATE_SILVERFISH); +- map.put(EntityType.SKELETON, SoundEvents.PARROT_IMITATE_SKELETON); +- map.put(EntityType.SLIME, SoundEvents.PARROT_IMITATE_SLIME); +- map.put(EntityType.SPIDER, SoundEvents.PARROT_IMITATE_SPIDER); +- map.put(EntityType.STRAY, SoundEvents.PARROT_IMITATE_STRAY); +- map.put(EntityType.VEX, SoundEvents.PARROT_IMITATE_VEX); +- map.put(EntityType.VINDICATOR, SoundEvents.PARROT_IMITATE_VINDICATOR); +- map.put(EntityType.WARDEN, SoundEvents.PARROT_IMITATE_WARDEN); +- map.put(EntityType.WITCH, SoundEvents.PARROT_IMITATE_WITCH); +- map.put(EntityType.WITHER, SoundEvents.PARROT_IMITATE_WITHER); +- map.put(EntityType.WITHER_SKELETON, SoundEvents.PARROT_IMITATE_WITHER_SKELETON); +- map.put(EntityType.ZOGLIN, SoundEvents.PARROT_IMITATE_ZOGLIN); +- map.put(EntityType.ZOMBIE, SoundEvents.PARROT_IMITATE_ZOMBIE); +- map.put(EntityType.ZOMBIE_VILLAGER, SoundEvents.PARROT_IMITATE_ZOMBIE_VILLAGER); ++ private static final Set TAME_FOOD = Sets.newHashSet(new Item[]{Items.WHEAT_SEEDS, Items.MELON_SEEDS, Items.PUMPKIN_SEEDS, Items.BEETROOT_SEEDS, Items.TORCHFLOWER_SEEDS, Items.PITCHER_POD}); ++ static final Map, SoundEvent> MOB_SOUND_MAP = (Map) Util.make(Maps.newHashMap(), (hashmap) -> { ++ hashmap.put(EntityType.BLAZE, SoundEvents.PARROT_IMITATE_BLAZE); ++ hashmap.put(EntityType.BREEZE, SoundEvents.PARROT_IMITATE_BREEZE); ++ hashmap.put(EntityType.CAVE_SPIDER, SoundEvents.PARROT_IMITATE_SPIDER); ++ hashmap.put(EntityType.CREEPER, SoundEvents.PARROT_IMITATE_CREEPER); ++ hashmap.put(EntityType.DROWNED, SoundEvents.PARROT_IMITATE_DROWNED); ++ hashmap.put(EntityType.ELDER_GUARDIAN, SoundEvents.PARROT_IMITATE_ELDER_GUARDIAN); ++ hashmap.put(EntityType.ENDER_DRAGON, SoundEvents.PARROT_IMITATE_ENDER_DRAGON); ++ hashmap.put(EntityType.ENDERMITE, SoundEvents.PARROT_IMITATE_ENDERMITE); ++ hashmap.put(EntityType.EVOKER, SoundEvents.PARROT_IMITATE_EVOKER); ++ hashmap.put(EntityType.GHAST, SoundEvents.PARROT_IMITATE_GHAST); ++ hashmap.put(EntityType.GUARDIAN, SoundEvents.PARROT_IMITATE_GUARDIAN); ++ hashmap.put(EntityType.HOGLIN, SoundEvents.PARROT_IMITATE_HOGLIN); ++ hashmap.put(EntityType.HUSK, SoundEvents.PARROT_IMITATE_HUSK); ++ hashmap.put(EntityType.ILLUSIONER, SoundEvents.PARROT_IMITATE_ILLUSIONER); ++ hashmap.put(EntityType.MAGMA_CUBE, SoundEvents.PARROT_IMITATE_MAGMA_CUBE); ++ hashmap.put(EntityType.PHANTOM, SoundEvents.PARROT_IMITATE_PHANTOM); ++ hashmap.put(EntityType.PIGLIN, SoundEvents.PARROT_IMITATE_PIGLIN); ++ hashmap.put(EntityType.PIGLIN_BRUTE, SoundEvents.PARROT_IMITATE_PIGLIN_BRUTE); ++ hashmap.put(EntityType.PILLAGER, SoundEvents.PARROT_IMITATE_PILLAGER); ++ hashmap.put(EntityType.RAVAGER, SoundEvents.PARROT_IMITATE_RAVAGER); ++ hashmap.put(EntityType.SHULKER, SoundEvents.PARROT_IMITATE_SHULKER); ++ hashmap.put(EntityType.SILVERFISH, SoundEvents.PARROT_IMITATE_SILVERFISH); ++ hashmap.put(EntityType.SKELETON, SoundEvents.PARROT_IMITATE_SKELETON); ++ hashmap.put(EntityType.SLIME, SoundEvents.PARROT_IMITATE_SLIME); ++ hashmap.put(EntityType.SPIDER, SoundEvents.PARROT_IMITATE_SPIDER); ++ hashmap.put(EntityType.STRAY, SoundEvents.PARROT_IMITATE_STRAY); ++ hashmap.put(EntityType.VEX, SoundEvents.PARROT_IMITATE_VEX); ++ hashmap.put(EntityType.VINDICATOR, SoundEvents.PARROT_IMITATE_VINDICATOR); ++ hashmap.put(EntityType.WARDEN, SoundEvents.PARROT_IMITATE_WARDEN); ++ hashmap.put(EntityType.WITCH, SoundEvents.PARROT_IMITATE_WITCH); ++ hashmap.put(EntityType.WITHER, SoundEvents.PARROT_IMITATE_WITHER); ++ hashmap.put(EntityType.WITHER_SKELETON, SoundEvents.PARROT_IMITATE_WITHER_SKELETON); ++ hashmap.put(EntityType.ZOGLIN, SoundEvents.PARROT_IMITATE_ZOGLIN); ++ hashmap.put(EntityType.ZOMBIE, SoundEvents.PARROT_IMITATE_ZOMBIE); ++ hashmap.put(EntityType.ZOMBIE_VILLAGER, SoundEvents.PARROT_IMITATE_ZOMBIE_VILLAGER); + }); + public float flap; + public float flapSpeed; +@@ -141,15 +139,13 @@ + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- this.setVariant(Util.getRandom(Parrot.Variant.values(), level.getRandom())); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ this.setVariant((Parrot.Variant) Util.getRandom((Object[]) Parrot.Variant.values(), level.getRandom())); + if (spawnData == null) { + spawnData = new AgeableMob.AgeableMobGroupData(false); + } + +- return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + + @Override +@@ -159,37 +155,38 @@ + + @Override + protected void registerGoals() { +- this.goalSelector.addGoal(0, new PanicGoal(this, 1.25)); ++ this.goalSelector.addGoal(0, new PanicGoal(this, 1.25D)); + this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(1, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this)); +- this.goalSelector.addGoal(2, new FollowOwnerGoal(this, 1.0, 5.0F, 1.0F, true)); +- this.goalSelector.addGoal(2, new Parrot.ParrotWanderGoal(this, 1.0)); ++ this.goalSelector.addGoal(2, new FollowOwnerGoal(this, 1.0D, 5.0F, 1.0F, true)); ++ this.goalSelector.addGoal(2, new Parrot.a(this, 1.0D)); + this.goalSelector.addGoal(3, new LandOnOwnersShoulderGoal(this)); +- this.goalSelector.addGoal(3, new FollowMobGoal(this, 1.0, 3.0F, 7.0F)); ++ this.goalSelector.addGoal(3, new FollowMobGoal(this, 1.0D, 3.0F, 7.0F)); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 6.0).add(Attributes.FLYING_SPEED, 0.4F).add(Attributes.MOVEMENT_SPEED, 0.2F); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 6.0D).add(Attributes.FLYING_SPEED, 0.4000000059604645D).add(Attributes.MOVEMENT_SPEED, 0.20000000298023224D); + } + + @Override + protected PathNavigation createNavigation(Level level) { +- FlyingPathNavigation flyingPathNavigation = new FlyingPathNavigation(this, level); +- flyingPathNavigation.setCanOpenDoors(false); +- flyingPathNavigation.setCanFloat(true); +- flyingPathNavigation.setCanPassDoors(true); +- return flyingPathNavigation; ++ FlyingPathNavigation navigationflying = new FlyingPathNavigation(this, level); ++ ++ navigationflying.setCanOpenDoors(false); ++ navigationflying.setCanFloat(true); ++ navigationflying.setCanPassDoors(true); ++ return navigationflying; + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return size.height * 0.6F; + } + + @Override + public void aiStep() { +- if (this.jukebox == null || !this.jukebox.closerToCenterThan(this.position(), 3.46) || !this.level().getBlockState(this.jukebox).is(Blocks.JUKEBOX)) { ++ if (this.jukebox == null || !this.jukebox.closerToCenterThan(this.position(), 3.46D) || !this.level().getBlockState(this.jukebox).is(Blocks.JUKEBOX)) { + this.partyParrot = false; + this.jukebox = null; + } +@@ -215,29 +212,33 @@ + private void calculateFlapping() { + this.oFlap = this.flap; + this.oFlapSpeed = this.flapSpeed; +- this.flapSpeed = this.flapSpeed + (float)(!this.onGround() && !this.isPassenger() ? 4 : -1) * 0.3F; ++ this.flapSpeed += (float) (!this.onGround() && !this.isPassenger() ? 4 : -1) * 0.3F; + this.flapSpeed = Mth.clamp(this.flapSpeed, 0.0F, 1.0F); + if (!this.onGround() && this.flapping < 1.0F) { + this.flapping = 1.0F; + } + + this.flapping *= 0.9F; +- Vec3 deltaMovement = this.getDeltaMovement(); +- if (!this.onGround() && deltaMovement.y < 0.0) { +- this.setDeltaMovement(deltaMovement.multiply(1.0, 0.6, 1.0)); ++ Vec3 vec3d = this.getDeltaMovement(); ++ ++ if (!this.onGround() && vec3d.y < 0.0D) { ++ this.setDeltaMovement(vec3d.multiply(1.0D, 0.6D, 1.0D)); + } + +- this.flap = this.flap + this.flapping * 2.0F; ++ this.flap += this.flapping * 2.0F; + } + + public static boolean imitateNearbyMobs(Level level, Entity parrot) { + if (parrot.isAlive() && !parrot.isSilent() && level.random.nextInt(2) == 0) { +- List entitiesOfClass = level.getEntitiesOfClass(Mob.class, parrot.getBoundingBox().inflate(20.0), NOT_PARROT_PREDICATE); +- if (!entitiesOfClass.isEmpty()) { +- Mob mob = entitiesOfClass.get(level.random.nextInt(entitiesOfClass.size())); +- if (!mob.isSilent()) { +- SoundEvent imitatedSound = getImitatedSound(mob.getType()); +- level.playSound(null, parrot.getX(), parrot.getY(), parrot.getZ(), imitatedSound, parrot.getSoundSource(), 0.7F, getPitch(level.random)); ++ List list = level.getEntitiesOfClass(Mob.class, parrot.getBoundingBox().inflate(20.0D), Parrot.NOT_PARROT_PREDICATE); ++ ++ if (!list.isEmpty()) { ++ Mob entityinsentient = (Mob) list.get(level.random.nextInt(list.size())); ++ ++ if (!entityinsentient.isSilent()) { ++ SoundEvent soundeffect = getImitatedSound(entityinsentient.getType()); ++ ++ level.playSound((Player) null, parrot.getX(), parrot.getY(), parrot.getZ(), soundeffect, parrot.getSoundSource(), 0.7F, getPitch(level.random)); + return true; + } + } +@@ -249,43 +250,34 @@ + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (!this.isTame() && TAME_FOOD.contains(itemInHand.getItem())) { ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (!this.isTame() && Parrot.TAME_FOOD.contains(itemstack.getItem())) { + if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + + if (!this.isSilent()) { +- this.level() +- .playSound( +- null, +- this.getX(), +- this.getY(), +- this.getZ(), +- SoundEvents.PARROT_EAT, +- this.getSoundSource(), +- 1.0F, +- 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F +- ); ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PARROT_EAT, this.getSoundSource(), 1.0F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F); + } + + if (!this.level().isClientSide) { +- if (this.random.nextInt(10) == 0) { ++ if (this.random.nextInt(10) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { // CraftBukkit + this.tame(player); +- this.level().broadcastEntityEvent(this, (byte)7); ++ this.level().broadcastEntityEvent(this, (byte) 7); + } else { +- this.level().broadcastEntityEvent(this, (byte)6); ++ this.level().broadcastEntityEvent(this, (byte) 6); + } + } + + return InteractionResult.sidedSuccess(this.level().isClientSide); +- } else if (itemInHand.is(POISONOUS_FOOD)) { ++ } else if (itemstack.is(Parrot.POISONOUS_FOOD)) { + if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + +- this.addEffect(new MobEffectInstance(MobEffects.POISON, 900)); ++ this.addEffect(new MobEffectInstance(MobEffects.POISON, 900), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.FOOD); // CraftBukkit + if (player.isCreative() || !this.isInvulnerable()) { + this.hurt(this.damageSources().playerAttack(player), Float.MAX_VALUE); + } +@@ -307,13 +299,12 @@ + return false; + } + +- public static boolean checkParrotSpawnRules(EntityType parrot, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) { ++ public static boolean checkParrotSpawnRules(EntityType parrot, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { + return level.getBlockState(pos.below()).is(BlockTags.PARROTS_SPAWNABLE_ON) && isBrightEnoughToSpawn(level, pos); + } + + @Override +- protected void checkFallDamage(double y, boolean onGround, BlockState state, BlockPos pos) { +- } ++ protected void checkFallDamage(double y, boolean flag, IBlockData onGround, BlockPos state) {} + + @Override + public boolean canMate(Animal otherAnimal) { +@@ -339,15 +330,16 @@ + + public static SoundEvent getAmbient(Level level, RandomSource random) { + if (level.getDifficulty() != Difficulty.PEACEFUL && random.nextInt(1000) == 0) { +- List> list = Lists.newArrayList(MOB_SOUND_MAP.keySet()); +- return getImitatedSound(list.get(random.nextInt(list.size()))); ++ List> list = Lists.newArrayList(Parrot.MOB_SOUND_MAP.keySet()); ++ ++ return getImitatedSound((EntityType) list.get(random.nextInt(list.size()))); + } else { + return SoundEvents.PARROT_AMBIENT; + } + } + + private static SoundEvent getImitatedSound(EntityType type) { +- return MOB_SOUND_MAP.getOrDefault(type, SoundEvents.PARROT_AMBIENT); ++ return (SoundEvent) Parrot.MOB_SOUND_MAP.getOrDefault(type, SoundEvents.PARROT_AMBIENT); + } + + @Override +@@ -361,7 +353,7 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.PARROT_STEP, 0.15F, 1.0F); + } + +@@ -392,7 +384,7 @@ + + @Override + public boolean isPushable() { +- return true; ++ return super.isPushable(); // CraftBukkit - collidable API + } + + @Override +@@ -407,28 +399,30 @@ + if (this.isInvulnerableTo(source)) { + return false; + } else { +- if (!this.level().isClientSide) { ++ // CraftBukkit start ++ boolean result = super.hurt(source, amount); ++ if (!this.level().isClientSide && result) { ++ // CraftBukkit end + this.setOrderedToSit(false); + } + +- return super.hurt(source, amount); ++ return result; // CraftBukkit + } + } + + @Override + public Parrot.Variant getVariant() { +- return Parrot.Variant.byId(this.entityData.get(DATA_VARIANT_ID)); ++ return Parrot.Variant.byId((Integer) this.entityData.get(Parrot.DATA_VARIANT_ID)); + } + +- @Override + public void setVariant(Parrot.Variant variant) { +- this.entityData.set(DATA_VARIANT_ID, variant.id); ++ this.entityData.set(Parrot.DATA_VARIANT_ID, variant.id); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_VARIANT_ID, 0); ++ this.entityData.define(Parrot.DATA_VARIANT_ID, 0); + } + + @Override +@@ -450,55 +444,81 @@ + + @Override + public Vec3 getLeashOffset() { +- return new Vec3(0.0, (double)(0.5F * this.getEyeHeight()), (double)(this.getBbWidth() * 0.4F)); ++ return new Vec3(0.0D, (double) (0.5F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height - 0.4375F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.4375F * f, 0.0F); + } + +- static class ParrotWanderGoal extends WaterAvoidingRandomFlyingGoal { +- public ParrotWanderGoal(PathfinderMob mob, double speedModifier) { ++ public static enum Variant implements StringRepresentable { ++ ++ RED_BLUE(0, "red_blue"), BLUE(1, "blue"), GREEN(2, "green"), YELLOW_BLUE(3, "yellow_blue"), GRAY(4, "gray"); ++ ++ public static final Codec CODEC = StringRepresentable.fromEnum(Parrot.Variant::values); ++ private static final IntFunction BY_ID = ByIdMap.continuous(Parrot.Variant::getId, values(), ByIdMap.a.CLAMP); ++ final int id; ++ private final String name; ++ ++ private Variant(int i, String s) { ++ this.id = i; ++ this.name = s; ++ } ++ ++ public int getId() { ++ return this.id; ++ } ++ ++ public static Parrot.Variant byId(int id) { ++ return (Parrot.Variant) Parrot.Variant.BY_ID.apply(id); ++ } ++ ++ @Override ++ public String getSerializedName() { ++ return this.name; ++ } ++ } ++ ++ private static class a extends PathfinderGoalRandomFly { ++ ++ public a(PathfinderMob mob, double speedModifier) { + super(mob, speedModifier); + } + + @Nullable + @Override + protected Vec3 getPosition() { +- Vec3 vec3 = null; ++ Vec3 vec3d = null; ++ + if (this.mob.isInWater()) { +- vec3 = LandRandomPos.getPos(this.mob, 15, 15); ++ vec3d = LandRandomPos.getPos(this.mob, 15, 15); + } + + if (this.mob.getRandom().nextFloat() >= this.probability) { +- vec3 = this.getTreePos(); ++ vec3d = this.getTreePos(); + } + +- return vec3 == null ? super.getPosition() : vec3; ++ return vec3d == null ? super.getPosition() : vec3d; + } + + @Nullable + private Vec3 getTreePos() { +- BlockPos blockPos = this.mob.blockPosition(); +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); +- BlockPos.MutableBlockPos mutableBlockPos1 = new BlockPos.MutableBlockPos(); ++ BlockPos blockposition = this.mob.blockPosition(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition1 = new BlockPos.MutableBlockPos(); ++ Iterable iterable = BlockPos.betweenClosed(Mth.floor(this.mob.getX() - 3.0D), Mth.floor(this.mob.getY() - 6.0D), Mth.floor(this.mob.getZ() - 3.0D), Mth.floor(this.mob.getX() + 3.0D), Mth.floor(this.mob.getY() + 6.0D), Mth.floor(this.mob.getZ() + 3.0D)); ++ Iterator iterator = iterable.iterator(); + +- for (BlockPos blockPos1 : BlockPos.betweenClosed( +- Mth.floor(this.mob.getX() - 3.0), +- Mth.floor(this.mob.getY() - 6.0), +- Mth.floor(this.mob.getZ() - 3.0), +- Mth.floor(this.mob.getX() + 3.0), +- Mth.floor(this.mob.getY() + 6.0), +- Mth.floor(this.mob.getZ() + 3.0) +- )) { +- if (!blockPos.equals(blockPos1)) { +- BlockState blockState = this.mob.level().getBlockState(mutableBlockPos1.setWithOffset(blockPos1, Direction.DOWN)); +- boolean flag = blockState.getBlock() instanceof LeavesBlock || blockState.is(BlockTags.LOGS); +- if (flag +- && this.mob.level().isEmptyBlock(blockPos1) +- && this.mob.level().isEmptyBlock(mutableBlockPos.setWithOffset(blockPos1, Direction.UP))) { +- return Vec3.atBottomCenterOf(blockPos1); ++ while (iterator.hasNext()) { ++ BlockPos blockposition1 = (BlockPos) iterator.next(); ++ ++ if (!blockposition.equals(blockposition1)) { ++ IBlockData iblockdata = this.mob.level().getBlockState(blockposition_mutableblockposition1.setWithOffset(blockposition1, Direction.DOWN)); ++ boolean flag = iblockdata.getBlock() instanceof LeavesBlock || iblockdata.is(BlockTags.LOGS); ++ ++ if (flag && this.mob.level().isEmptyBlock(blockposition1) && this.mob.level().isEmptyBlock(blockposition_mutableblockposition.setWithOffset(blockposition1, Direction.UP))) { ++ return Vec3.atBottomCenterOf(blockposition1); + } + } + } +@@ -506,35 +526,4 @@ + return null; + } + } +- +- public static enum Variant implements StringRepresentable { +- RED_BLUE(0, "red_blue"), +- BLUE(1, "blue"), +- GREEN(2, "green"), +- YELLOW_BLUE(3, "yellow_blue"), +- GRAY(4, "gray"); +- +- public static final Codec CODEC = StringRepresentable.fromEnum(Parrot.Variant::values); +- private static final IntFunction BY_ID = ByIdMap.continuous(Parrot.Variant::getId, values(), ByIdMap.OutOfBoundsStrategy.CLAMP); +- final int id; +- private final String name; +- +- private Variant(int id, String name) { +- this.id = id; +- this.name = name; +- } +- +- public int getId() { +- return this.id; +- } +- +- public static Parrot.Variant byId(int id) { +- return BY_ID.apply(id); +- } +- +- @Override +- public String getSerializedName() { +- return this.name; +- } +- } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Pig.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Pig.java.patch new file mode 100644 index 0000000000..1739a3f1ed --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Pig.java.patch @@ -0,0 +1,321 @@ +--- a/net/minecraft/world/entity/animal/Pig.java ++++ b/net/minecraft/world/entity/animal/Pig.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.entity.animal; + ++import com.google.common.collect.UnmodifiableIterator; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +@@ -12,20 +13,20 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.Difficulty; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.ISteerable; + import net.minecraft.world.entity.ItemBasedSteering; +-import net.minecraft.world.entity.ItemSteerable; + import net.minecraft.world.entity.LightningBolt; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.Saddleable; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -43,50 +44,67 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.item.crafting.Ingredient; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Pig extends Animal implements ItemSteerable, Saddleable { ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ ++public class Pig extends Animal implements ISteerable, Saddleable { ++ + private static final EntityDataAccessor DATA_SADDLE_ID = SynchedEntityData.defineId(Pig.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_BOOST_TIME = SynchedEntityData.defineId(Pig.class, EntityDataSerializers.INT); + private static final Ingredient FOOD_ITEMS = Ingredient.of(Items.CARROT, Items.POTATO, Items.BEETROOT); +- private final ItemBasedSteering steering = new ItemBasedSteering(this.entityData, DATA_BOOST_TIME, DATA_SADDLE_ID); ++ public final ItemBasedSteering steering; + + public Pig(EntityType entityType, Level level) { + super(entityType, level); ++ this.steering = new ItemBasedSteering(this.entityData, Pig.DATA_BOOST_TIME, Pig.DATA_SADDLE_ID); + } + + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); +- this.goalSelector.addGoal(1, new PanicGoal(this, 1.25)); +- this.goalSelector.addGoal(3, new BreedGoal(this, 1.0)); +- this.goalSelector.addGoal(4, new TemptGoal(this, 1.2, Ingredient.of(Items.CARROT_ON_A_STICK), false)); +- this.goalSelector.addGoal(4, new TemptGoal(this, 1.2, FOOD_ITEMS, false)); +- this.goalSelector.addGoal(5, new FollowParentGoal(this, 1.1)); +- this.goalSelector.addGoal(6, new WaterAvoidingRandomStrollGoal(this, 1.0)); ++ this.goalSelector.addGoal(1, new PanicGoal(this, 1.25D)); ++ this.goalSelector.addGoal(3, new BreedGoal(this, 1.0D)); ++ this.goalSelector.addGoal(4, new TemptGoal(this, 1.2D, Ingredient.of(Items.CARROT_ON_A_STICK), false)); ++ this.goalSelector.addGoal(4, new TemptGoal(this, 1.2D, Pig.FOOD_ITEMS, false)); ++ this.goalSelector.addGoal(5, new FollowParentGoal(this, 1.1D)); ++ this.goalSelector.addGoal(6, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.goalSelector.addGoal(7, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0).add(Attributes.MOVEMENT_SPEED, 0.25); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.MOVEMENT_SPEED, 0.25D); + } + + @Nullable + @Override + public LivingEntity getControllingPassenger() { +- return (LivingEntity)(this.isSaddled() && this.getFirstPassenger() instanceof Player player && player.isHolding(Items.CARROT_ON_A_STICK) +- ? player +- : super.getControllingPassenger()); ++ if (this.isSaddled()) { ++ Entity entity = this.getFirstPassenger(); ++ ++ if (entity instanceof Player) { ++ Player entityhuman = (Player) entity; ++ ++ if (entityhuman.isHolding(Items.CARROT_ON_A_STICK)) { ++ return entityhuman; ++ } ++ } ++ } ++ ++ return super.getControllingPassenger(); + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { +- if (DATA_BOOST_TIME.equals(key) && this.level().isClientSide) { ++ if (Pig.DATA_BOOST_TIME.equals(key) && this.level().isClientSide) { + this.steering.onSynced(); + } + +@@ -96,8 +114,8 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_SADDLE_ID, false); +- this.entityData.define(DATA_BOOST_TIME, 0); ++ this.entityData.define(Pig.DATA_SADDLE_ID, false); ++ this.entityData.define(Pig.DATA_BOOST_TIME, 0); + } + + @Override +@@ -128,26 +146,29 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.PIG_STEP, 0.15F, 1.0F); + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- boolean isFood = this.isFood(player.getItemInHand(hand)); +- if (!isFood && this.isSaddled() && !this.isVehicle() && !player.isSecondaryUseActive()) { ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ boolean flag = this.isFood(player.getItemInHand(hand)); ++ ++ if (!flag && this.isSaddled() && !this.isVehicle() && !player.isSecondaryUseActive()) { + if (!this.level().isClientSide) { + player.startRiding(this); + } + + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { +- InteractionResult interactionResult = super.mobInteract(player, hand); +- if (!interactionResult.consumesAction()) { +- ItemStack itemInHand = player.getItemInHand(hand); +- return itemInHand.is(Items.SADDLE) ? itemInHand.interactLivingEntity(player, this, hand) : InteractionResult.PASS; ++ InteractionResult enuminteractionresult = super.mobInteract(player, hand); ++ ++ if (!enuminteractionresult.consumesAction()) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ return itemstack.is(Items.SADDLE) ? itemstack.interactLivingEntity(player, this, hand) : InteractionResult.PASS; + } else { +- return interactionResult; ++ return enuminteractionresult; + } + } + } +@@ -161,8 +182,9 @@ + protected void dropEquipment() { + super.dropEquipment(); + if (this.isSaddled()) { +- this.spawnAtLocation(Items.SADDLE); ++ this.spawnAtLocation((IMaterial) Items.SADDLE); + } ++ + } + + @Override +@@ -174,31 +196,41 @@ + public void equipSaddle(@Nullable SoundSource source) { + this.steering.setSaddle(true); + if (source != null) { +- this.level().playSound(null, this, SoundEvents.PIG_SADDLE, source, 0.5F, 1.0F); ++ this.level().playSound((Player) null, (Entity) this, SoundEvents.PIG_SADDLE, source, 0.5F, 1.0F); + } ++ + } + + @Override + public Vec3 getDismountLocationForPassenger(LivingEntity livingEntity) { +- Direction motionDirection = this.getMotionDirection(); +- if (motionDirection.getAxis() == Direction.Axis.Y) { ++ Direction enumdirection = this.getMotionDirection(); ++ ++ if (enumdirection.getAxis() == Direction.Axis.Y) { + return super.getDismountLocationForPassenger(livingEntity); + } else { +- int[][] ints = DismountHelper.offsetsForDirection(motionDirection); +- BlockPos blockPos = this.blockPosition(); +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ int[][] aint = DismountHelper.offsetsForDirection(enumdirection); ++ BlockPos blockposition = this.blockPosition(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ UnmodifiableIterator unmodifiableiterator = livingEntity.getDismountPoses().iterator(); + +- for (Pose pose : livingEntity.getDismountPoses()) { +- AABB localBoundsForPose = livingEntity.getLocalBoundsForPose(pose); ++ while (unmodifiableiterator.hasNext()) { ++ EntityPose entitypose = (EntityPose) unmodifiableiterator.next(); ++ AABB axisalignedbb = livingEntity.getLocalBoundsForPose(entitypose); ++ int[][] aint1 = aint; ++ int i = aint.length; + +- for (int[] ints1 : ints) { +- mutableBlockPos.set(blockPos.getX() + ints1[0], blockPos.getY(), blockPos.getZ() + ints1[1]); +- double blockFloorHeight = this.level().getBlockFloorHeight(mutableBlockPos); +- if (DismountHelper.isBlockFloorValid(blockFloorHeight)) { +- Vec3 vec3 = Vec3.upFromBottomCenterOf(mutableBlockPos, blockFloorHeight); +- if (DismountHelper.canDismountTo(this.level(), livingEntity, localBoundsForPose.move(vec3))) { +- livingEntity.setPose(pose); +- return vec3; ++ for (int j = 0; j < i; ++j) { ++ int[] aint2 = aint1[j]; ++ ++ blockposition_mutableblockposition.set(blockposition.getX() + aint2[0], blockposition.getY(), blockposition.getZ() + aint2[1]); ++ double d0 = this.level().getBlockFloorHeight(blockposition_mutableblockposition); ++ ++ if (DismountHelper.isBlockFloorValid(d0)) { ++ Vec3 vec3d = Vec3.upFromBottomCenterOf(blockposition_mutableblockposition, d0); ++ ++ if (DismountHelper.canDismountTo(this.level(), livingEntity, axisalignedbb.move(vec3d))) { ++ livingEntity.setPose(entitypose); ++ return vec3d; + } + } + } +@@ -211,19 +243,26 @@ + @Override + public void thunderHit(ServerLevel level, LightningBolt lightning) { + if (level.getDifficulty() != Difficulty.PEACEFUL) { +- ZombifiedPiglin zombifiedPiglin = EntityType.ZOMBIFIED_PIGLIN.create(level); +- if (zombifiedPiglin != null) { +- zombifiedPiglin.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.GOLDEN_SWORD)); +- zombifiedPiglin.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); +- zombifiedPiglin.setNoAi(this.isNoAi()); +- zombifiedPiglin.setBaby(this.isBaby()); ++ ZombifiedPiglin entitypigzombie = (ZombifiedPiglin) EntityType.ZOMBIFIED_PIGLIN.create(level); ++ ++ if (entitypigzombie != null) { ++ entitypigzombie.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.GOLDEN_SWORD)); ++ entitypigzombie.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); ++ entitypigzombie.setNoAi(this.isNoAi()); ++ entitypigzombie.setBaby(this.isBaby()); + if (this.hasCustomName()) { +- zombifiedPiglin.setCustomName(this.getCustomName()); +- zombifiedPiglin.setCustomNameVisible(this.isCustomNameVisible()); ++ entitypigzombie.setCustomName(this.getCustomName()); ++ entitypigzombie.setCustomNameVisible(this.isCustomNameVisible()); + } + +- zombifiedPiglin.setPersistenceRequired(); +- level.addFreshEntity(zombifiedPiglin); ++ entitypigzombie.setPersistenceRequired(); ++ // CraftBukkit start ++ if (CraftEventFactory.callPigZapEvent(this, lightning, entitypigzombie).isCancelled()) { ++ return; ++ } ++ // CraftBukkit - added a reason for spawning this creature ++ level.addFreshEntity(entitypigzombie, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); ++ // CraftBukkit end + this.discard(); + } else { + super.thunderHit(level, lightning); +@@ -231,6 +270,7 @@ + } else { + super.thunderHit(level, lightning); + } ++ + } + + @Override +@@ -243,12 +283,12 @@ + + @Override + protected Vec3 getRiddenInput(Player player, Vec3 travelVector) { +- return new Vec3(0.0, 0.0, 1.0); ++ return new Vec3(0.0D, 0.0D, 1.0D); + } + + @Override + protected float getRiddenSpeed(Player player) { +- return (float)(this.getAttributeValue(Attributes.MOVEMENT_SPEED) * 0.225 * (double)this.steering.boostFactor()); ++ return (float) (this.getAttributeValue(Attributes.MOVEMENT_SPEED) * 0.225D * (double) this.steering.boostFactor()); + } + + @Override +@@ -259,21 +299,21 @@ + @Nullable + @Override + public Pig getBreedOffspring(ServerLevel level, AgeableMob otherParent) { +- return EntityType.PIG.create(level); ++ return (Pig) EntityType.PIG.create(level); + } + + @Override + public boolean isFood(ItemStack stack) { +- return FOOD_ITEMS.test(stack); ++ return Pig.FOOD_ITEMS.test(stack); + } + + @Override + public Vec3 getLeashOffset() { +- return new Vec3(0.0, (double)(0.6F * this.getEyeHeight()), (double)(this.getBbWidth() * 0.4F)); ++ return new Vec3(0.0D, (double) (0.6F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height - 0.03125F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.03125F * f, 0.0F); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Pufferfish.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Pufferfish.java.patch new file mode 100644 index 0000000000..105bd6b9c1 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Pufferfish.java.patch @@ -0,0 +1,179 @@ +--- a/net/minecraft/world/entity/animal/Pufferfish.java ++++ b/net/minecraft/world/entity/animal/Pufferfish.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.entity.animal; + ++import java.util.Iterator; + import java.util.List; + import java.util.function.Predicate; + import net.minecraft.nbt.CompoundTag; +@@ -14,11 +15,11 @@ + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.goal.Goal; + import net.minecraft.world.entity.ai.targeting.TargetingConditions; + import net.minecraft.world.entity.player.Player; +@@ -27,15 +28,14 @@ + import net.minecraft.world.level.Level; + + public class Pufferfish extends AbstractFish { ++ + private static final EntityDataAccessor PUFF_STATE = SynchedEntityData.defineId(Pufferfish.class, EntityDataSerializers.INT); + int inflateCounter; + int deflateTimer; +- private static final Predicate SCARY_MOB = entity -> (!(entity instanceof Player) || !((Player)entity).isCreative()) +- && (entity.getType() == EntityType.AXOLOTL || entity.getMobType() != MobType.WATER); +- static final TargetingConditions targetingConditions = TargetingConditions.forNonCombat() +- .ignoreInvisibilityTesting() +- .ignoreLineOfSight() +- .selector(SCARY_MOB); ++ private static final Predicate SCARY_MOB = (entityliving) -> { ++ return entityliving instanceof Player && ((Player) entityliving).isCreative() ? false : entityliving.getType() == EntityType.AXOLOTL || entityliving.getMobType() != EnumMonsterType.WATER; ++ }; ++ static final TargetingConditions targetingConditions = TargetingConditions.forNonCombat().ignoreInvisibilityTesting().ignoreLineOfSight().selector(Pufferfish.SCARY_MOB); + public static final int STATE_SMALL = 0; + public static final int STATE_MID = 1; + public static final int STATE_FULL = 2; +@@ -48,20 +48,20 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(PUFF_STATE, 0); ++ this.entityData.define(Pufferfish.PUFF_STATE, 0); + } + + public int getPuffState() { +- return this.entityData.get(PUFF_STATE); ++ return (Integer) this.entityData.get(Pufferfish.PUFF_STATE); + } + + public void setPuffState(int puffState) { +- this.entityData.set(PUFF_STATE, puffState); ++ this.entityData.set(Pufferfish.PUFF_STATE, puffState); + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { +- if (PUFF_STATE.equals(key)) { ++ if (Pufferfish.PUFF_STATE.equals(key)) { + this.refreshDimensions(); + } + +@@ -103,7 +103,7 @@ + this.setPuffState(2); + } + +- this.inflateCounter++; ++ ++this.inflateCounter; + } else if (this.getPuffState() != 0) { + if (this.deflateTimer > 60 && this.getPuffState() == 2) { + this.playSound(SoundEvents.PUFFER_FISH_BLOW_OUT, this.getSoundVolume(), this.getVoicePitch()); +@@ -113,7 +113,7 @@ + this.setPuffState(0); + } + +- this.deflateTimer++; ++ ++this.deflateTimer; + } + } + +@@ -124,32 +124,44 @@ + public void aiStep() { + super.aiStep(); + if (this.isAlive() && this.getPuffState() > 0) { +- for (Mob mob : this.level().getEntitiesOfClass(Mob.class, this.getBoundingBox().inflate(0.3), entity -> targetingConditions.test(this, entity))) { +- if (mob.isAlive()) { +- this.touch(mob); ++ List list = this.level().getEntitiesOfClass(Mob.class, this.getBoundingBox().inflate(0.3D), (entityinsentient) -> { ++ return Pufferfish.targetingConditions.test(this, entityinsentient); ++ }); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Mob entityinsentient = (Mob) iterator.next(); ++ ++ if (entityinsentient.isAlive()) { ++ this.touch(entityinsentient); + } + } + } ++ + } + + private void touch(Mob mob) { +- int puffState = this.getPuffState(); +- if (mob.hurt(this.damageSources().mobAttack(this), (float)(1 + puffState))) { +- mob.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * puffState, 0), this); ++ int i = this.getPuffState(); ++ ++ if (mob.hurt(this.damageSources().mobAttack(this), (float) (1 + i))) { ++ mob.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * i, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + this.playSound(SoundEvents.PUFFER_FISH_STING, 1.0F, 1.0F); + } ++ + } + + @Override + public void playerTouch(Player entity) { +- int puffState = this.getPuffState(); +- if (entity instanceof ServerPlayer && puffState > 0 && entity.hurt(this.damageSources().mobAttack(this), (float)(1 + puffState))) { ++ int i = this.getPuffState(); ++ ++ if (entity instanceof ServerPlayer && i > 0 && entity.hurt(this.damageSources().mobAttack(this), (float) (1 + i))) { + if (!this.isSilent()) { +- ((ServerPlayer)entity).connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.PUFFER_FISH_STING, 0.0F)); ++ ((ServerPlayer) entity).connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.PUFFER_FISH_STING, 0.0F)); + } + +- entity.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * puffState, 0), this); ++ entity.addEffect(new MobEffectInstance(MobEffects.POISON, 60 * i, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } ++ + } + + @Override +@@ -173,7 +185,7 @@ + } + + @Override +- public EntityDimensions getDimensions(Pose pose) { ++ public EntityDimensions getDimensions(EntityPose pose) { + return super.getDimensions(pose).scale(getScale(this.getPuffState())); + } + +@@ -188,7 +200,8 @@ + } + } + +- static class PufferfishPuffGoal extends Goal { ++ private static class PufferfishPuffGoal extends Goal { ++ + private final Pufferfish fish; + + public PufferfishPuffGoal(Pufferfish fish) { +@@ -197,12 +210,11 @@ + + @Override + public boolean canUse() { +- List entitiesOfClass = this.fish +- .level() +- .getEntitiesOfClass( +- LivingEntity.class, this.fish.getBoundingBox().inflate(2.0), livingEntity -> Pufferfish.targetingConditions.test(this.fish, livingEntity) +- ); +- return !entitiesOfClass.isEmpty(); ++ List list = this.fish.level().getEntitiesOfClass(LivingEntity.class, this.fish.getBoundingBox().inflate(2.0D), (entityliving) -> { ++ return Pufferfish.targetingConditions.test(this.fish, entityliving); ++ }); ++ ++ return !list.isEmpty(); + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Rabbit.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Rabbit.java.patch new file mode 100644 index 0000000000..0e30aea3e3 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Rabbit.java.patch @@ -0,0 +1,637 @@ +--- a/net/minecraft/world/entity/animal/Rabbit.java ++++ b/net/minecraft/world/entity/animal/Rabbit.java +@@ -27,10 +27,10 @@ + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.VariantHolder; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -62,17 +62,21 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.CarrotBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.pathfinder.Path; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class Rabbit extends Animal implements VariantHolder { +- public static final double STROLL_SPEED_MOD = 0.6; +- public static final double BREED_SPEED_MOD = 0.8; +- public static final double FOLLOW_SPEED_MOD = 1.0; +- public static final double FLEE_SPEED_MOD = 2.2; +- public static final double ATTACK_SPEED_MOD = 1.4; ++ ++ public static final double STROLL_SPEED_MOD = 0.6D; ++ public static final double BREED_SPEED_MOD = 0.8D; ++ public static final double FOLLOW_SPEED_MOD = 1.0D; ++ public static final double FLEE_SPEED_MOD = 2.2D; ++ public static final double ATTACK_SPEED_MOD = 1.4D; + private static final EntityDataAccessor DATA_TYPE_ID = SynchedEntityData.defineId(Rabbit.class, EntityDataSerializers.INT); + private static final ResourceLocation KILLER_BUNNY = new ResourceLocation("killer_bunny"); + public static final int EVIL_ATTACK_POWER = 8; +@@ -88,40 +92,42 @@ + super(entityType, level); + this.jumpControl = new Rabbit.RabbitJumpControl(this); + this.moveControl = new Rabbit.RabbitMoveControl(this); +- this.setSpeedModifier(0.0); + } + + @Override +- protected void registerGoals() { ++ public void registerGoals() { + this.goalSelector.addGoal(1, new FloatGoal(this)); + this.goalSelector.addGoal(1, new ClimbOnTopOfPowderSnowGoal(this, this.level())); +- this.goalSelector.addGoal(1, new Rabbit.RabbitPanicGoal(this, 2.2)); +- this.goalSelector.addGoal(2, new BreedGoal(this, 0.8)); +- this.goalSelector.addGoal(3, new TemptGoal(this, 1.0, Ingredient.of(Items.CARROT, Items.GOLDEN_CARROT, Blocks.DANDELION), false)); +- this.goalSelector.addGoal(4, new Rabbit.RabbitAvoidEntityGoal<>(this, Player.class, 8.0F, 2.2, 2.2)); +- this.goalSelector.addGoal(4, new Rabbit.RabbitAvoidEntityGoal<>(this, Wolf.class, 10.0F, 2.2, 2.2)); +- this.goalSelector.addGoal(4, new Rabbit.RabbitAvoidEntityGoal<>(this, Monster.class, 4.0F, 2.2, 2.2)); ++ this.goalSelector.addGoal(1, new Rabbit.RabbitPanicGoal(this, 2.2D)); ++ this.goalSelector.addGoal(2, new BreedGoal(this, 0.8D)); ++ this.goalSelector.addGoal(3, new TemptGoal(this, 1.0D, Ingredient.of(Items.CARROT, Items.GOLDEN_CARROT, Blocks.DANDELION), false)); ++ this.goalSelector.addGoal(4, new Rabbit.RabbitAvoidEntityGoal<>(this, Player.class, 8.0F, 2.2D, 2.2D)); ++ this.goalSelector.addGoal(4, new Rabbit.RabbitAvoidEntityGoal<>(this, Wolf.class, 10.0F, 2.2D, 2.2D)); ++ this.goalSelector.addGoal(4, new Rabbit.RabbitAvoidEntityGoal<>(this, Monster.class, 4.0F, 2.2D, 2.2D)); + this.goalSelector.addGoal(5, new Rabbit.RaidGardenGoal(this)); +- this.goalSelector.addGoal(6, new WaterAvoidingRandomStrollGoal(this, 0.6)); ++ this.goalSelector.addGoal(6, new WaterAvoidingRandomStrollGoal(this, 0.6D)); + this.goalSelector.addGoal(11, new LookAtPlayerGoal(this, Player.class, 10.0F)); + } + + @Override + protected float getJumpPower() { + float f = 0.3F; +- if (this.horizontalCollision || this.moveControl.hasWanted() && this.moveControl.getWantedY() > this.getY() + 0.5) { ++ ++ if (this.horizontalCollision || this.moveControl.hasWanted() && this.moveControl.getWantedY() > this.getY() + 0.5D) { + f = 0.5F; + } + +- Path path = this.navigation.getPath(); +- if (path != null && !path.isDone()) { +- Vec3 nextEntityPos = path.getNextEntityPos(this); +- if (nextEntityPos.y > this.getY() + 0.5) { ++ Path pathentity = this.navigation.getPath(); ++ ++ if (pathentity != null && !pathentity.isDone()) { ++ Vec3 vec3d = pathentity.getNextEntityPos(this); ++ ++ if (vec3d.y > this.getY() + 0.5D) { + f = 0.5F; + } + } + +- if (this.moveControl.getSpeedModifier() <= 0.6) { ++ if (this.moveControl.getSpeedModifier() <= 0.6D) { + f = 0.2F; + } + +@@ -131,21 +137,24 @@ + @Override + protected void jumpFromGround() { + super.jumpFromGround(); +- double speedModifier = this.moveControl.getSpeedModifier(); +- if (speedModifier > 0.0) { +- double d = this.getDeltaMovement().horizontalDistanceSqr(); +- if (d < 0.01) { +- this.moveRelative(0.1F, new Vec3(0.0, 0.0, 1.0)); ++ double d0 = this.moveControl.getSpeedModifier(); ++ ++ if (d0 > 0.0D) { ++ double d1 = this.getDeltaMovement().horizontalDistanceSqr(); ++ ++ if (d1 < 0.01D) { ++ this.moveRelative(0.1F, new Vec3(0.0D, 0.0D, 1.0D)); + } + } + + if (!this.level().isClientSide) { +- this.level().broadcastEntityEvent(this, (byte)1); ++ this.level().broadcastEntityEvent(this, (byte) 1); + } ++ + } + + public float getJumpCompletion(float partialTick) { +- return this.jumpDuration == 0 ? 0.0F : ((float)this.jumpTicks + partialTick) / (float)this.jumpDuration; ++ return this.jumpDuration == 0 ? 0.0F : ((float) this.jumpTicks + partialTick) / (float) this.jumpDuration; + } + + public void setSpeedModifier(double speedModifier) { +@@ -159,6 +168,7 @@ + if (jumping) { + this.playSound(this.getJumpSound(), this.getSoundVolume(), ((this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F) * 0.8F); + } ++ + } + + public void startJumping() { +@@ -170,17 +180,17 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_TYPE_ID, Rabbit.Variant.BROWN.id); ++ this.entityData.define(Rabbit.DATA_TYPE_ID, Rabbit.Variant.BROWN.id); + } + + @Override + public void customServerAiStep() { + if (this.jumpDelayTicks > 0) { +- this.jumpDelayTicks--; ++ --this.jumpDelayTicks; + } + + if (this.moreCarrotTicks > 0) { +- this.moreCarrotTicks = this.moreCarrotTicks - this.random.nextInt(3); ++ this.moreCarrotTicks -= this.random.nextInt(3); + if (this.moreCarrotTicks < 0) { + this.moreCarrotTicks = 0; + } +@@ -193,28 +203,31 @@ + } + + if (this.getVariant() == Rabbit.Variant.EVIL && this.jumpDelayTicks == 0) { +- LivingEntity target = this.getTarget(); +- if (target != null && this.distanceToSqr(target) < 16.0) { +- this.facePoint(target.getX(), target.getZ()); +- this.moveControl.setWantedPosition(target.getX(), target.getY(), target.getZ(), this.moveControl.getSpeedModifier()); ++ LivingEntity entityliving = this.getTarget(); ++ ++ if (entityliving != null && this.distanceToSqr((Entity) entityliving) < 16.0D) { ++ this.facePoint(entityliving.getX(), entityliving.getZ()); ++ this.moveControl.setWantedPosition(entityliving.getX(), entityliving.getY(), entityliving.getZ(), this.moveControl.getSpeedModifier()); + this.startJumping(); + this.wasOnGround = true; + } + } + +- Rabbit.RabbitJumpControl rabbitJumpControl = (Rabbit.RabbitJumpControl)this.jumpControl; +- if (!rabbitJumpControl.wantJump()) { ++ Rabbit.RabbitJumpControl entityrabbit_controllerjumprabbit = (Rabbit.RabbitJumpControl) this.jumpControl; ++ ++ if (!entityrabbit_controllerjumprabbit.wantJump()) { + if (this.moveControl.hasWanted() && this.jumpDelayTicks == 0) { +- Path path = this.navigation.getPath(); +- Vec3 vec3 = new Vec3(this.moveControl.getWantedX(), this.moveControl.getWantedY(), this.moveControl.getWantedZ()); +- if (path != null && !path.isDone()) { +- vec3 = path.getNextEntityPos(this); ++ Path pathentity = this.navigation.getPath(); ++ Vec3 vec3d = new Vec3(this.moveControl.getWantedX(), this.moveControl.getWantedY(), this.moveControl.getWantedZ()); ++ ++ if (pathentity != null && !pathentity.isDone()) { ++ vec3d = pathentity.getNextEntityPos(this); + } + +- this.facePoint(vec3.x, vec3.z); ++ this.facePoint(vec3d.x, vec3d.z); + this.startJumping(); + } +- } else if (!rabbitJumpControl.canJump()) { ++ } else if (!entityrabbit_controllerjumprabbit.canJump()) { + this.enableJumpControl(); + } + } +@@ -227,24 +240,25 @@ + return false; + } + +- private void facePoint(double x, double z) { +- this.setYRot((float)(Mth.atan2(z - this.getZ(), x - this.getX()) * 180.0F / (float)Math.PI) - 90.0F); ++ private void facePoint(double x, double d1) { ++ this.setYRot((float) (Mth.atan2(d1 - this.getZ(), x - this.getX()) * 57.2957763671875D) - 90.0F); + } + + private void enableJumpControl() { +- ((Rabbit.RabbitJumpControl)this.jumpControl).setCanJump(true); ++ ((Rabbit.RabbitJumpControl) this.jumpControl).setCanJump(true); + } + + private void disableJumpControl() { +- ((Rabbit.RabbitJumpControl)this.jumpControl).setCanJump(false); ++ ((Rabbit.RabbitJumpControl) this.jumpControl).setCanJump(false); + } + + private void setLandingDelay() { +- if (this.moveControl.getSpeedModifier() < 2.2) { ++ if (this.moveControl.getSpeedModifier() < 2.2D) { + this.jumpDelayTicks = 10; + } else { + this.jumpDelayTicks = 1; + } ++ + } + + private void checkLandingDelay() { +@@ -256,16 +270,17 @@ + public void aiStep() { + super.aiStep(); + if (this.jumpTicks != this.jumpDuration) { +- this.jumpTicks++; ++ ++this.jumpTicks; + } else if (this.jumpDuration != 0) { + this.jumpTicks = 0; + this.jumpDuration = 0; + this.setJumping(false); + } ++ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 3.0).add(Attributes.MOVEMENT_SPEED, 0.3F); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 3.0D).add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D); + } + + @Override +@@ -323,24 +338,31 @@ + @Nullable + @Override + public Rabbit getBreedOffspring(ServerLevel level, AgeableMob otherParent) { +- Rabbit rabbit = EntityType.RABBIT.create(level); +- if (rabbit != null) { +- Rabbit.Variant randomRabbitVariant; +- randomRabbitVariant = getRandomRabbitVariant(level, this.blockPosition()); +- label16: ++ Rabbit entityrabbit = (Rabbit) EntityType.RABBIT.create(level); ++ ++ if (entityrabbit != null) { ++ Rabbit.Variant entityrabbit_variant = getRandomRabbitVariant(level, this.blockPosition()); ++ + if (this.random.nextInt(20) != 0) { +- if (otherParent instanceof Rabbit rabbit1 && this.random.nextBoolean()) { +- randomRabbitVariant = rabbit1.getVariant(); +- break label16; +- } ++ label15: ++ { ++ if (otherParent instanceof Rabbit) { ++ Rabbit entityrabbit1 = (Rabbit) otherParent; + +- randomRabbitVariant = this.getVariant(); ++ if (this.random.nextBoolean()) { ++ entityrabbit_variant = entityrabbit1.getVariant(); ++ break label15; ++ } ++ } ++ ++ entityrabbit_variant = this.getVariant(); ++ } + } + +- rabbit.setVariant(randomRabbitVariant); ++ entityrabbit.setVariant(entityrabbit_variant); + } + +- return rabbit; ++ return entityrabbit; + } + + @Override +@@ -350,54 +372,47 @@ + + @Override + public Rabbit.Variant getVariant() { +- return Rabbit.Variant.byId(this.entityData.get(DATA_TYPE_ID)); ++ return Rabbit.Variant.byId((Integer) this.entityData.get(Rabbit.DATA_TYPE_ID)); + } + +- @Override + public void setVariant(Rabbit.Variant variant) { + if (variant == Rabbit.Variant.EVIL) { +- this.getAttribute(Attributes.ARMOR).setBaseValue(8.0); +- this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.4, true)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers()); ++ this.getAttribute(Attributes.ARMOR).setBaseValue(8.0D); ++ this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.4D, true)); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[0])).setAlertOthers()); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Wolf.class, true)); + if (!this.hasCustomName()) { +- this.setCustomName(Component.translatable(Util.makeDescriptionId("entity", KILLER_BUNNY))); ++ this.setCustomName(Component.translatable(Util.makeDescriptionId("entity", Rabbit.KILLER_BUNNY))); + } + } + +- this.entityData.set(DATA_TYPE_ID, variant.id); ++ this.entityData.set(Rabbit.DATA_TYPE_ID, variant.id); + } + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- Rabbit.Variant randomRabbitVariant = getRandomRabbitVariant(level, this.blockPosition()); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ Rabbit.Variant entityrabbit_variant = getRandomRabbitVariant(level, this.blockPosition()); ++ + if (spawnData instanceof Rabbit.RabbitGroupData) { +- randomRabbitVariant = ((Rabbit.RabbitGroupData)spawnData).variant; ++ entityrabbit_variant = ((Rabbit.RabbitGroupData) spawnData).variant; + } else { +- spawnData = new Rabbit.RabbitGroupData(randomRabbitVariant); ++ spawnData = new Rabbit.RabbitGroupData(entityrabbit_variant); + } + +- this.setVariant(randomRabbitVariant); +- return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ this.setVariant(entityrabbit_variant); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + + private static Rabbit.Variant getRandomRabbitVariant(LevelAccessor level, BlockPos pos) { +- Holder biome = level.getBiome(pos); +- int randomInt = level.getRandom().nextInt(100); +- if (biome.is(BiomeTags.SPAWNS_WHITE_RABBITS)) { +- return randomInt < 80 ? Rabbit.Variant.WHITE : Rabbit.Variant.WHITE_SPLOTCHED; +- } else if (biome.is(BiomeTags.SPAWNS_GOLD_RABBITS)) { +- return Rabbit.Variant.GOLD; +- } else { +- return randomInt < 50 ? Rabbit.Variant.BROWN : (randomInt < 90 ? Rabbit.Variant.SALT : Rabbit.Variant.BLACK); +- } ++ Holder holder = level.getBiome(pos); ++ int i = level.getRandom().nextInt(100); ++ ++ return holder.is(BiomeTags.SPAWNS_WHITE_RABBITS) ? (i < 80 ? Rabbit.Variant.WHITE : Rabbit.Variant.WHITE_SPLOTCHED) : (holder.is(BiomeTags.SPAWNS_GOLD_RABBITS) ? Rabbit.Variant.GOLD : (i < 50 ? Rabbit.Variant.BROWN : (i < 90 ? Rabbit.Variant.SALT : Rabbit.Variant.BLACK))); + } + +- public static boolean checkRabbitSpawnRules(EntityType rabbit, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) { ++ public static boolean checkRabbitSpawnRules(EntityType rabbit, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { + return level.getBlockState(pos.below()).is(BlockTags.RABBITS_SPAWNABLE_ON) && isBrightEnoughToSpawn(level, pos); + } + +@@ -414,43 +429,22 @@ + } else { + super.handleEntityEvent(id); + } ++ + } + + @Override + public Vec3 getLeashOffset() { +- return new Vec3(0.0, (double)(0.6F * this.getEyeHeight()), (double)(this.getBbWidth() * 0.4F)); ++ return new Vec3(0.0D, (double) (0.6F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); + } + +- static class RabbitAvoidEntityGoal extends AvoidEntityGoal { +- private final Rabbit rabbit; +- +- public RabbitAvoidEntityGoal(Rabbit rabbit, Class entityClassToAvoid, float maxDist, double walkSpeedModifier, double sprintSpeedModifier) { +- super(rabbit, entityClassToAvoid, maxDist, walkSpeedModifier, sprintSpeedModifier); +- this.rabbit = rabbit; +- } +- +- @Override +- public boolean canUse() { +- return this.rabbit.getVariant() != Rabbit.Variant.EVIL && super.canUse(); +- } +- } +- +- public static class RabbitGroupData extends AgeableMob.AgeableMobGroupData { +- public final Rabbit.Variant variant; +- +- public RabbitGroupData(Rabbit.Variant variant) { +- super(1.0F); +- this.variant = variant; +- } +- } +- + public static class RabbitJumpControl extends JumpControl { ++ + private final Rabbit rabbit; + private boolean canJump; + +- public RabbitJumpControl(Rabbit mob) { +- super(mob); +- this.rabbit = mob; ++ public RabbitJumpControl(Rabbit rabbit) { ++ super(rabbit); ++ this.rabbit = rabbit; + } + + public boolean wantJump() { +@@ -471,22 +465,24 @@ + this.rabbit.startJumping(); + this.jump = false; + } ++ + } + } + +- static class RabbitMoveControl extends MoveControl { ++ private static class RabbitMoveControl extends MoveControl { ++ + private final Rabbit rabbit; + private double nextJumpSpeed; + +- public RabbitMoveControl(Rabbit mob) { +- super(mob); +- this.rabbit = mob; ++ public RabbitMoveControl(Rabbit rabbit) { ++ super(rabbit); ++ this.rabbit = rabbit; + } + + @Override + public void tick() { +- if (this.rabbit.onGround() && !this.rabbit.jumping && !((Rabbit.RabbitJumpControl)this.rabbit.jumpControl).wantJump()) { +- this.rabbit.setSpeedModifier(0.0); ++ if (this.rabbit.onGround() && !this.rabbit.jumping && !((Rabbit.RabbitJumpControl) this.rabbit.jumpControl).wantJump()) { ++ this.rabbit.setSpeedModifier(0.0D); + } else if (this.hasWanted()) { + this.rabbit.setSpeedModifier(this.nextJumpSpeed); + } +@@ -495,19 +491,21 @@ + } + + @Override +- public void setWantedPosition(double x, double y, double z, double speed) { ++ public void setWantedPosition(double x, double d1, double y, double d3) { + if (this.rabbit.isInWater()) { +- speed = 1.5; ++ d3 = 1.5D; + } + +- super.setWantedPosition(x, y, z, speed); +- if (speed > 0.0) { +- this.nextJumpSpeed = speed; ++ super.setWantedPosition(x, d1, y, d3); ++ if (d3 > 0.0D) { ++ this.nextJumpSpeed = d3; + } ++ + } + } + +- static class RabbitPanicGoal extends PanicGoal { ++ private static class RabbitPanicGoal extends PanicGoal { ++ + private final Rabbit rabbit; + + public RabbitPanicGoal(Rabbit rabbit, double speedModifier) { +@@ -522,13 +520,29 @@ + } + } + +- static class RaidGardenGoal extends MoveToBlockGoal { ++ private static class RabbitAvoidEntityGoal extends AvoidEntityGoal { ++ + private final Rabbit rabbit; ++ ++ public RabbitAvoidEntityGoal(Rabbit rabbit, Class entityClassToAvoid, float maxDist, double walkSpeedModifier, double d1) { ++ super(rabbit, entityClassToAvoid, maxDist, walkSpeedModifier, d1); ++ this.rabbit = rabbit; ++ } ++ ++ @Override ++ public boolean canUse() { ++ return this.rabbit.getVariant() != Rabbit.Variant.EVIL && super.canUse(); ++ } ++ } ++ ++ private static class RaidGardenGoal extends MoveToBlockGoal { ++ ++ private final Rabbit rabbit; + private boolean wantsToRaid; + private boolean canRaid; + + public RaidGardenGoal(Rabbit rabbit) { +- super(rabbit, 0.7F, 16); ++ super(rabbit, 0.699999988079071D, 16); + this.rabbit = rabbit; + } + +@@ -554,29 +568,33 @@ + @Override + public void tick() { + super.tick(); +- this.rabbit +- .getLookControl() +- .setLookAt( +- (double)this.blockPos.getX() + 0.5, +- (double)(this.blockPos.getY() + 1), +- (double)this.blockPos.getZ() + 0.5, +- 10.0F, +- (float)this.rabbit.getMaxHeadXRot() +- ); ++ this.rabbit.getLookControl().setLookAt((double) this.blockPos.getX() + 0.5D, (double) (this.blockPos.getY() + 1), (double) this.blockPos.getZ() + 0.5D, 10.0F, (float) this.rabbit.getMaxHeadXRot()); + if (this.isReachedTarget()) { +- Level level = this.rabbit.level(); +- BlockPos blockPos = this.blockPos.above(); +- BlockState blockState = level.getBlockState(blockPos); +- Block block = blockState.getBlock(); ++ Level world = this.rabbit.level(); ++ BlockPos blockposition = this.blockPos.above(); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ Block block = iblockdata.getBlock(); ++ + if (this.canRaid && block instanceof CarrotBlock) { +- int i = blockState.getValue(CarrotBlock.AGE); ++ int i = (Integer) iblockdata.getValue(CarrotBlock.AGE); ++ + if (i == 0) { +- level.setBlock(blockPos, Blocks.AIR.defaultBlockState(), 2); +- level.destroyBlock(blockPos, true, this.rabbit); ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.rabbit, blockposition, Blocks.AIR.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end ++ world.setBlock(blockposition, Blocks.AIR.defaultBlockState(), 2); ++ world.destroyBlock(blockposition, true, this.rabbit); + } else { +- level.setBlock(blockPos, blockState.setValue(CarrotBlock.AGE, Integer.valueOf(i - 1)), 2); +- level.gameEvent(GameEvent.BLOCK_CHANGE, blockPos, GameEvent.Context.of(this.rabbit)); +- level.levelEvent(2001, blockPos, Block.getId(blockState)); ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.rabbit, blockposition, iblockdata.setValue(CarrotBlock.AGE, i - 1))) { ++ return; ++ } ++ // CraftBukkit end ++ world.setBlock(blockposition, (IBlockData) iblockdata.setValue(CarrotBlock.AGE, i - 1), 2); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of((Entity) this.rabbit)); ++ world.levelEvent(2001, blockposition, Block.getId(iblockdata)); + } + + this.rabbit.moreCarrotTicks = 40; +@@ -585,14 +603,16 @@ + this.canRaid = false; + this.nextStartTick = 10; + } ++ + } + + @Override + protected boolean isValidTarget(LevelReader level, BlockPos pos) { +- BlockState blockState = level.getBlockState(pos); +- if (blockState.is(Blocks.FARMLAND) && this.wantsToRaid && !this.canRaid) { +- blockState = level.getBlockState(pos.above()); +- if (blockState.getBlock() instanceof CarrotBlock && ((CarrotBlock)blockState.getBlock()).isMaxAge(blockState)) { ++ IBlockData iblockdata = level.getBlockState(pos); ++ ++ if (iblockdata.is(Blocks.FARMLAND) && this.wantsToRaid && !this.canRaid) { ++ iblockdata = level.getBlockState(pos.above()); ++ if (iblockdata.getBlock() instanceof CarrotBlock && ((CarrotBlock) iblockdata.getBlock()).isMaxAge(iblockdata)) { + this.canRaid = true; + return true; + } +@@ -603,22 +623,17 @@ + } + + public static enum Variant implements StringRepresentable { +- BROWN(0, "brown"), +- WHITE(1, "white"), +- BLACK(2, "black"), +- WHITE_SPLOTCHED(3, "white_splotched"), +- GOLD(4, "gold"), +- SALT(5, "salt"), +- EVIL(99, "evil"); + +- private static final IntFunction BY_ID = ByIdMap.sparse(Rabbit.Variant::id, values(), BROWN); ++ BROWN(0, "brown"), WHITE(1, "white"), BLACK(2, "black"), WHITE_SPLOTCHED(3, "white_splotched"), GOLD(4, "gold"), SALT(5, "salt"), EVIL(99, "evil"); ++ ++ private static final IntFunction BY_ID = ByIdMap.sparse(Rabbit.Variant::id, values(), Rabbit.Variant.BROWN); + public static final Codec CODEC = StringRepresentable.fromEnum(Rabbit.Variant::values); + final int id; + private final String name; + +- private Variant(int id, String name) { +- this.id = id; +- this.name = name; ++ private Variant(int i, String s) { ++ this.id = i; ++ this.name = s; + } + + @Override +@@ -631,7 +646,17 @@ + } + + public static Rabbit.Variant byId(int id) { +- return BY_ID.apply(id); ++ return (Rabbit.Variant) Rabbit.Variant.BY_ID.apply(id); + } + } ++ ++ public static class RabbitGroupData extends AgeableMob.AgeableMobGroupData { ++ ++ public final Rabbit.Variant variant; ++ ++ public RabbitGroupData(Rabbit.Variant variant) { ++ super(1.0F); ++ this.variant = variant; ++ } ++ } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Sheep.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Sheep.java.patch new file mode 100644 index 0000000000..ba8f3e8afe --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Sheep.java.patch @@ -0,0 +1,522 @@ +--- a/net/minecraft/world/entity/animal/Sheep.java ++++ b/net/minecraft/world/entity/animal/Sheep.java +@@ -2,8 +2,9 @@ + + import com.google.common.collect.Maps; + import java.util.Arrays; +-import java.util.EnumMap; + import java.util.Map; ++import java.util.Objects; ++import java.util.Optional; + import java.util.stream.Collectors; + import javax.annotation.Nullable; + import net.minecraft.Util; +@@ -20,18 +21,18 @@ + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.Shearable; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.BreedGoal; +@@ -46,49 +47,56 @@ + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.inventory.AbstractContainerMenu; +-import net.minecraft.world.inventory.CraftingContainer; ++import net.minecraft.world.inventory.InventoryCrafting; + import net.minecraft.world.inventory.MenuType; ++import net.minecraft.world.inventory.ResultContainer; + import net.minecraft.world.inventory.TransientCraftingContainer; +-import net.minecraft.world.item.DyeColor; +-import net.minecraft.world.item.DyeItem; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.item.crafting.Ingredient; +-import net.minecraft.world.item.crafting.RecipeHolder; ++import net.minecraft.world.item.crafting.RecipeCrafting; + import net.minecraft.world.item.crafting.RecipeType; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.storage.loot.BuiltInLootTables; + import org.joml.Vector3f; ++import net.minecraft.world.item.DyeColor; ++import net.minecraft.world.item.DyeItem; ++import net.minecraft.world.item.Item; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.SheepRegrowWoolEvent; ++import org.bukkit.inventory.InventoryView; ++// CraftBukkit end + + public class Sheep extends Animal implements Shearable { ++ + private static final int EAT_ANIMATION_TICKS = 40; + private static final EntityDataAccessor DATA_WOOL_ID = SynchedEntityData.defineId(Sheep.class, EntityDataSerializers.BYTE); +- private static final Map ITEM_BY_DYE = Util.make(Maps.newEnumMap(DyeColor.class), map -> { +- map.put(DyeColor.WHITE, Blocks.WHITE_WOOL); +- map.put(DyeColor.ORANGE, Blocks.ORANGE_WOOL); +- map.put(DyeColor.MAGENTA, Blocks.MAGENTA_WOOL); +- map.put(DyeColor.LIGHT_BLUE, Blocks.LIGHT_BLUE_WOOL); +- map.put(DyeColor.YELLOW, Blocks.YELLOW_WOOL); +- map.put(DyeColor.LIME, Blocks.LIME_WOOL); +- map.put(DyeColor.PINK, Blocks.PINK_WOOL); +- map.put(DyeColor.GRAY, Blocks.GRAY_WOOL); +- map.put(DyeColor.LIGHT_GRAY, Blocks.LIGHT_GRAY_WOOL); +- map.put(DyeColor.CYAN, Blocks.CYAN_WOOL); +- map.put(DyeColor.PURPLE, Blocks.PURPLE_WOOL); +- map.put(DyeColor.BLUE, Blocks.BLUE_WOOL); +- map.put(DyeColor.BROWN, Blocks.BROWN_WOOL); +- map.put(DyeColor.GREEN, Blocks.GREEN_WOOL); +- map.put(DyeColor.RED, Blocks.RED_WOOL); +- map.put(DyeColor.BLACK, Blocks.BLACK_WOOL); ++ private static final Map ITEM_BY_DYE = (Map) Util.make(Maps.newEnumMap(DyeColor.class), (enummap) -> { ++ enummap.put(DyeColor.WHITE, Blocks.WHITE_WOOL); ++ enummap.put(DyeColor.ORANGE, Blocks.ORANGE_WOOL); ++ enummap.put(DyeColor.MAGENTA, Blocks.MAGENTA_WOOL); ++ enummap.put(DyeColor.LIGHT_BLUE, Blocks.LIGHT_BLUE_WOOL); ++ enummap.put(DyeColor.YELLOW, Blocks.YELLOW_WOOL); ++ enummap.put(DyeColor.LIME, Blocks.LIME_WOOL); ++ enummap.put(DyeColor.PINK, Blocks.PINK_WOOL); ++ enummap.put(DyeColor.GRAY, Blocks.GRAY_WOOL); ++ enummap.put(DyeColor.LIGHT_GRAY, Blocks.LIGHT_GRAY_WOOL); ++ enummap.put(DyeColor.CYAN, Blocks.CYAN_WOOL); ++ enummap.put(DyeColor.PURPLE, Blocks.PURPLE_WOOL); ++ enummap.put(DyeColor.BLUE, Blocks.BLUE_WOOL); ++ enummap.put(DyeColor.BROWN, Blocks.BROWN_WOOL); ++ enummap.put(DyeColor.GREEN, Blocks.GREEN_WOOL); ++ enummap.put(DyeColor.RED, Blocks.RED_WOOL); ++ enummap.put(DyeColor.BLACK, Blocks.BLACK_WOOL); + }); +- private static final Map COLORARRAY_BY_COLOR = Maps.newEnumMap( +- Arrays.stream(DyeColor.values()).collect(Collectors.toMap(color -> (DyeColor)color, Sheep::createSheepColor)) +- ); ++ private static final Map COLORARRAY_BY_COLOR = Maps.newEnumMap((Map) Arrays.stream(DyeColor.values()).collect(Collectors.toMap((enumcolor) -> { ++ return enumcolor; ++ }, Sheep::createSheepColor))); + private int eatAnimationTick; + private EatBlockGoal eatBlockGoal; + +@@ -96,14 +104,15 @@ + if (dyeColor == DyeColor.WHITE) { + return new float[]{0.9019608F, 0.9019608F, 0.9019608F}; + } else { +- float[] textureDiffuseColors = dyeColor.getTextureDiffuseColors(); ++ float[] afloat = dyeColor.getTextureDiffuseColors(); + float f = 0.75F; +- return new float[]{textureDiffuseColors[0] * 0.75F, textureDiffuseColors[1] * 0.75F, textureDiffuseColors[2] * 0.75F}; ++ ++ return new float[]{afloat[0] * 0.75F, afloat[1] * 0.75F, afloat[2] * 0.75F}; + } + } + + public static float[] getColorArray(DyeColor dyeColor) { +- return COLORARRAY_BY_COLOR.get(dyeColor); ++ return (float[]) Sheep.COLORARRAY_BY_COLOR.get(dyeColor); + } + + public Sheep(EntityType entityType, Level level) { +@@ -114,12 +123,12 @@ + protected void registerGoals() { + this.eatBlockGoal = new EatBlockGoal(this); + this.goalSelector.addGoal(0, new FloatGoal(this)); +- this.goalSelector.addGoal(1, new PanicGoal(this, 1.25)); +- this.goalSelector.addGoal(2, new BreedGoal(this, 1.0)); +- this.goalSelector.addGoal(3, new TemptGoal(this, 1.1, Ingredient.of(Items.WHEAT), false)); +- this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.1)); ++ this.goalSelector.addGoal(1, new PanicGoal(this, 1.25D)); ++ this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); ++ this.goalSelector.addGoal(3, new TemptGoal(this, 1.1D, Ingredient.of(Items.WHEAT), false)); ++ this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.1D)); + this.goalSelector.addGoal(5, this.eatBlockGoal); +- this.goalSelector.addGoal(6, new WaterAvoidingRandomStrollGoal(this, 1.0)); ++ this.goalSelector.addGoal(6, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.goalSelector.addGoal(7, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); + } +@@ -140,13 +149,13 @@ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 8.0).add(Attributes.MOVEMENT_SPEED, 0.23F); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 8.0D).add(Attributes.MOVEMENT_SPEED, 0.23000000417232513D); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_WOOL_ID, (byte)0); ++ this.entityData.define(Sheep.DATA_WOOL_ID, (byte) 0); + } + + @Override +@@ -154,24 +163,62 @@ + if (this.isSheared()) { + return this.getType().getDefaultLootTable(); + } else { +- return switch (this.getColor()) { +- case WHITE -> BuiltInLootTables.SHEEP_WHITE; +- case ORANGE -> BuiltInLootTables.SHEEP_ORANGE; +- case MAGENTA -> BuiltInLootTables.SHEEP_MAGENTA; +- case LIGHT_BLUE -> BuiltInLootTables.SHEEP_LIGHT_BLUE; +- case YELLOW -> BuiltInLootTables.SHEEP_YELLOW; +- case LIME -> BuiltInLootTables.SHEEP_LIME; +- case PINK -> BuiltInLootTables.SHEEP_PINK; +- case GRAY -> BuiltInLootTables.SHEEP_GRAY; +- case LIGHT_GRAY -> BuiltInLootTables.SHEEP_LIGHT_GRAY; +- case CYAN -> BuiltInLootTables.SHEEP_CYAN; +- case PURPLE -> BuiltInLootTables.SHEEP_PURPLE; +- case BLUE -> BuiltInLootTables.SHEEP_BLUE; +- case BROWN -> BuiltInLootTables.SHEEP_BROWN; +- case GREEN -> BuiltInLootTables.SHEEP_GREEN; +- case RED -> BuiltInLootTables.SHEEP_RED; +- case BLACK -> BuiltInLootTables.SHEEP_BLACK; +- }; ++ ResourceLocation minecraftkey; ++ ++ switch (this.getColor()) { ++ case WHITE: ++ minecraftkey = BuiltInLootTables.SHEEP_WHITE; ++ break; ++ case ORANGE: ++ minecraftkey = BuiltInLootTables.SHEEP_ORANGE; ++ break; ++ case MAGENTA: ++ minecraftkey = BuiltInLootTables.SHEEP_MAGENTA; ++ break; ++ case LIGHT_BLUE: ++ minecraftkey = BuiltInLootTables.SHEEP_LIGHT_BLUE; ++ break; ++ case YELLOW: ++ minecraftkey = BuiltInLootTables.SHEEP_YELLOW; ++ break; ++ case LIME: ++ minecraftkey = BuiltInLootTables.SHEEP_LIME; ++ break; ++ case PINK: ++ minecraftkey = BuiltInLootTables.SHEEP_PINK; ++ break; ++ case GRAY: ++ minecraftkey = BuiltInLootTables.SHEEP_GRAY; ++ break; ++ case LIGHT_GRAY: ++ minecraftkey = BuiltInLootTables.SHEEP_LIGHT_GRAY; ++ break; ++ case CYAN: ++ minecraftkey = BuiltInLootTables.SHEEP_CYAN; ++ break; ++ case PURPLE: ++ minecraftkey = BuiltInLootTables.SHEEP_PURPLE; ++ break; ++ case BLUE: ++ minecraftkey = BuiltInLootTables.SHEEP_BLUE; ++ break; ++ case BROWN: ++ minecraftkey = BuiltInLootTables.SHEEP_BROWN; ++ break; ++ case GREEN: ++ minecraftkey = BuiltInLootTables.SHEEP_GREEN; ++ break; ++ case RED: ++ minecraftkey = BuiltInLootTables.SHEEP_RED; ++ break; ++ case BLACK: ++ minecraftkey = BuiltInLootTables.SHEEP_BLACK; ++ break; ++ default: ++ throw new IncompatibleClassChangeError(); ++ } ++ ++ return minecraftkey; + } + } + +@@ -182,37 +229,39 @@ + } else { + super.handleEntityEvent(id); + } ++ + } + + public float getHeadEatPositionScale(float partialTick) { +- if (this.eatAnimationTick <= 0) { +- return 0.0F; +- } else if (this.eatAnimationTick >= 4 && this.eatAnimationTick <= 36) { +- return 1.0F; +- } else { +- return this.eatAnimationTick < 4 +- ? ((float)this.eatAnimationTick - partialTick) / 4.0F +- : -((float)(this.eatAnimationTick - 40) - partialTick) / 4.0F; +- } ++ return this.eatAnimationTick <= 0 ? 0.0F : (this.eatAnimationTick >= 4 && this.eatAnimationTick <= 36 ? 1.0F : (this.eatAnimationTick < 4 ? ((float) this.eatAnimationTick - partialTick) / 4.0F : -((float) (this.eatAnimationTick - 40) - partialTick) / 4.0F)); + } + + public float getHeadEatAngleScale(float partialTick) { + if (this.eatAnimationTick > 4 && this.eatAnimationTick <= 36) { +- float f = ((float)(this.eatAnimationTick - 4) - partialTick) / 32.0F; +- return (float) (Math.PI / 5) + 0.21991149F * Mth.sin(f * 28.7F); ++ float f1 = ((float) (this.eatAnimationTick - 4) - partialTick) / 32.0F; ++ ++ return 0.62831855F + 0.21991149F * Mth.sin(f1 * 28.7F); + } else { +- return this.eatAnimationTick > 0 ? (float) (Math.PI / 5) : this.getXRot() * (float) (Math.PI / 180.0); ++ return this.eatAnimationTick > 0 ? 0.62831855F : this.getXRot() * 0.017453292F; + } + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (itemInHand.is(Items.SHEARS)) { ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (itemstack.is(Items.SHEARS)) { + if (!this.level().isClientSide && this.readyForShearing()) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) { ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.shear(SoundSource.PLAYERS); + this.gameEvent(GameEvent.SHEAR, player); +- itemInHand.hurtAndBreak(1, player, entity -> entity.broadcastBreakEvent(hand)); ++ itemstack.hurtAndBreak(1, player, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(hand); ++ }); + return InteractionResult.SUCCESS; + } else { + return InteractionResult.CONSUME; +@@ -224,23 +273,20 @@ + + @Override + public void shear(SoundSource category) { +- this.level().playSound(null, this, SoundEvents.SHEEP_SHEAR, category, 1.0F, 1.0F); ++ this.level().playSound((Player) null, (Entity) this, SoundEvents.SHEEP_SHEAR, category, 1.0F, 1.0F); + this.setSheared(true); + int i = 1 + this.random.nextInt(3); + +- for (int i1 = 0; i1 < i; i1++) { +- ItemEntity itemEntity = this.spawnAtLocation(ITEM_BY_DYE.get(this.getColor()), 1); +- if (itemEntity != null) { +- itemEntity.setDeltaMovement( +- itemEntity.getDeltaMovement() +- .add( +- (double)((this.random.nextFloat() - this.random.nextFloat()) * 0.1F), +- (double)(this.random.nextFloat() * 0.05F), +- (double)((this.random.nextFloat() - this.random.nextFloat()) * 0.1F) +- ) +- ); ++ for (int j = 0; j < i; ++j) { ++ this.forceDrops = true; // CraftBukkit ++ ItemEntity entityitem = this.spawnAtLocation((IMaterial) Sheep.ITEM_BY_DYE.get(this.getColor()), 1); ++ this.forceDrops = false; // CraftBukkit ++ ++ if (entityitem != null) { ++ entityitem.setDeltaMovement(entityitem.getDeltaMovement().add((double) ((this.random.nextFloat() - this.random.nextFloat()) * 0.1F), (double) (this.random.nextFloat() * 0.05F), (double) ((this.random.nextFloat() - this.random.nextFloat()) * 0.1F))); + } + } ++ + } + + @Override +@@ -252,7 +298,7 @@ + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); + compound.putBoolean("Sheared", this.isSheared()); +- compound.putByte("Color", (byte)this.getColor().getId()); ++ compound.putByte("Color", (byte) this.getColor().getId()); + } + + @Override +@@ -278,93 +324,94 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.SHEEP_STEP, 0.15F, 1.0F); + } + + public DyeColor getColor() { +- return DyeColor.byId(this.entityData.get(DATA_WOOL_ID) & 15); ++ return DyeColor.byId((Byte) this.entityData.get(Sheep.DATA_WOOL_ID) & 15); + } + + public void setColor(DyeColor dyeColor) { +- byte b = this.entityData.get(DATA_WOOL_ID); +- this.entityData.set(DATA_WOOL_ID, (byte)(b & 240 | dyeColor.getId() & 15)); ++ byte b0 = (Byte) this.entityData.get(Sheep.DATA_WOOL_ID); ++ ++ this.entityData.set(Sheep.DATA_WOOL_ID, (byte) (b0 & 240 | dyeColor.getId() & 15)); + } + + public boolean isSheared() { +- return (this.entityData.get(DATA_WOOL_ID) & 16) != 0; ++ return ((Byte) this.entityData.get(Sheep.DATA_WOOL_ID) & 16) != 0; + } + + public void setSheared(boolean sheared) { +- byte b = this.entityData.get(DATA_WOOL_ID); ++ byte b0 = (Byte) this.entityData.get(Sheep.DATA_WOOL_ID); ++ + if (sheared) { +- this.entityData.set(DATA_WOOL_ID, (byte)(b | 16)); ++ this.entityData.set(Sheep.DATA_WOOL_ID, (byte) (b0 | 16)); + } else { +- this.entityData.set(DATA_WOOL_ID, (byte)(b & -17)); ++ this.entityData.set(Sheep.DATA_WOOL_ID, (byte) (b0 & -17)); + } ++ + } + + public static DyeColor getRandomSheepColor(RandomSource random) { +- int randomInt = random.nextInt(100); +- if (randomInt < 5) { +- return DyeColor.BLACK; +- } else if (randomInt < 10) { +- return DyeColor.GRAY; +- } else if (randomInt < 15) { +- return DyeColor.LIGHT_GRAY; +- } else if (randomInt < 18) { +- return DyeColor.BROWN; +- } else { +- return random.nextInt(500) == 0 ? DyeColor.PINK : DyeColor.WHITE; +- } ++ int i = random.nextInt(100); ++ ++ return i < 5 ? DyeColor.BLACK : (i < 10 ? DyeColor.GRAY : (i < 15 ? DyeColor.LIGHT_GRAY : (i < 18 ? DyeColor.BROWN : (random.nextInt(500) == 0 ? DyeColor.PINK : DyeColor.WHITE)))); + } + + @Nullable + @Override + public Sheep getBreedOffspring(ServerLevel level, AgeableMob otherParent) { +- Sheep sheep = EntityType.SHEEP.create(level); +- if (sheep != null) { +- sheep.setColor(this.getOffspringColor(this, (Sheep)otherParent)); ++ Sheep entitysheep = (Sheep) EntityType.SHEEP.create(level); ++ ++ if (entitysheep != null) { ++ entitysheep.setColor(this.getOffspringColor(this, (Sheep) otherParent)); + } + +- return sheep; ++ return entitysheep; + } + + @Override + public void ate() { ++ // CraftBukkit start ++ SheepRegrowWoolEvent event = new SheepRegrowWoolEvent((org.bukkit.entity.Sheep) this.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) return; ++ // CraftBukkit end + super.ate(); + this.setSheared(false); + if (this.isBaby()) { + this.ageUp(60); + } ++ + } + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + this.setColor(getRandomSheepColor(level.getRandom())); + return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + + private DyeColor getOffspringColor(Animal father, Animal mother) { +- DyeColor color = ((Sheep)father).getColor(); +- DyeColor color1 = ((Sheep)mother).getColor(); +- CraftingContainer craftingContainer = makeContainer(color, color1); +- return this.level() +- .getRecipeManager() +- .getRecipeFor(RecipeType.CRAFTING, craftingContainer, this.level()) +- .map(recipeHolder -> recipeHolder.value().assemble(craftingContainer, this.level().registryAccess())) +- .map(ItemStack::getItem) +- .filter(DyeItem.class::isInstance) +- .map(DyeItem.class::cast) +- .map(DyeItem::getDyeColor) +- .orElseGet(() -> this.level().random.nextBoolean() ? color : color1); ++ DyeColor enumcolor = ((Sheep) father).getColor(); ++ DyeColor enumcolor1 = ((Sheep) mother).getColor(); ++ InventoryCrafting inventorycrafting = makeContainer(enumcolor, enumcolor1); ++ Optional optional = this.level().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, inventorycrafting, this.level()).map((recipeholder) -> { // CraftBukkit - decompile error ++ return ((RecipeCrafting) recipeholder.value()).assemble(inventorycrafting, this.level().registryAccess()); ++ }).map(ItemStack::getItem); ++ ++ Objects.requireNonNull(DyeItem.class); ++ optional = optional.filter(DyeItem.class::isInstance); ++ Objects.requireNonNull(DyeItem.class); ++ return (DyeColor) optional.map(DyeItem.class::cast).map(DyeItem::getDyeColor).orElseGet(() -> { ++ return this.level().random.nextBoolean() ? enumcolor : enumcolor1; ++ }); + } + +- private static CraftingContainer makeContainer(DyeColor fatherColor, DyeColor motherColor) { +- CraftingContainer craftingContainer = new TransientCraftingContainer(new AbstractContainerMenu(null, -1) { ++ private static InventoryCrafting makeContainer(DyeColor fatherColor, DyeColor motherColor) { ++ TransientCraftingContainer transientcraftingcontainer = new TransientCraftingContainer(new AbstractContainerMenu((MenuType) null, -1) { + @Override + public ItemStack quickMoveStack(Player player, int index) { + return ItemStack.EMPTY; +@@ -374,19 +421,28 @@ + public boolean stillValid(Player player) { + return false; + } ++ ++ // CraftBukkit start ++ @Override ++ public InventoryView getBukkitView() { ++ return null; // TODO: O.O ++ } ++ // CraftBukkit end + }, 2, 1); +- craftingContainer.setItem(0, new ItemStack(DyeItem.byColor(fatherColor))); +- craftingContainer.setItem(1, new ItemStack(DyeItem.byColor(motherColor))); +- return craftingContainer; ++ ++ transientcraftingcontainer.setItem(0, new ItemStack(DyeItem.byColor(fatherColor))); ++ transientcraftingcontainer.setItem(1, new ItemStack(DyeItem.byColor(motherColor))); ++ transientcraftingcontainer.resultInventory = new ResultContainer(); // CraftBukkit - add result slot for event ++ return transientcraftingcontainer; + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.95F * size.height; + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height - 0.0625F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.0625F * f, 0.0F); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/SnowGolem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/SnowGolem.java.patch new file mode 100644 index 0000000000..5c5fc33cb6 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/SnowGolem.java.patch @@ -0,0 +1,221 @@ +--- a/net/minecraft/world/entity/animal/SnowGolem.java ++++ b/net/minecraft/world/entity/animal/SnowGolem.java +@@ -11,14 +11,15 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.tags.BiomeTags; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.Shearable; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -27,7 +28,7 @@ + import net.minecraft.world.entity.ai.goal.RangedAttackGoal; + import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal; + import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; +-import net.minecraft.world.entity.monster.Enemy; ++import net.minecraft.world.entity.monster.IMonster; + import net.minecraft.world.entity.monster.RangedAttackMob; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.Snowball; +@@ -36,11 +37,15 @@ + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackMob { ++ + private static final EntityDataAccessor DATA_PUMPKIN_ID = SynchedEntityData.defineId(SnowGolem.class, EntityDataSerializers.BYTE); + private static final byte PUMPKIN_FLAG = 16; + private static final float EYE_HEIGHT = 1.7F; +@@ -51,21 +56,23 @@ + + @Override + protected void registerGoals() { +- this.goalSelector.addGoal(1, new RangedAttackGoal(this, 1.25, 20, 10.0F)); +- this.goalSelector.addGoal(2, new WaterAvoidingRandomStrollGoal(this, 1.0, 1.0000001E-5F)); ++ this.goalSelector.addGoal(1, new RangedAttackGoal(this, 1.25D, 20, 10.0F)); ++ this.goalSelector.addGoal(2, new WaterAvoidingRandomStrollGoal(this, 1.0D, 1.0000001E-5F)); + this.goalSelector.addGoal(3, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(4, new RandomLookAroundGoal(this)); +- this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Mob.class, 10, true, false, entity -> entity instanceof Enemy)); ++ this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Mob.class, 10, true, false, (entityliving) -> { ++ return entityliving instanceof IMonster; ++ })); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 4.0).add(Attributes.MOVEMENT_SPEED, 0.2F); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 4.0D).add(Attributes.MOVEMENT_SPEED, 0.20000000298023224D); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_PUMPKIN_ID, (byte)16); ++ this.entityData.define(SnowGolem.DATA_PUMPKIN_ID, (byte) 16); + } + + @Override +@@ -80,6 +87,7 @@ + if (compound.contains("Pumpkin")) { + this.setPumpkin(compound.getBoolean("Pumpkin")); + } ++ + } + + @Override +@@ -92,54 +100,69 @@ + super.aiStep(); + if (!this.level().isClientSide) { + if (this.level().getBiome(this.blockPosition()).is(BiomeTags.SNOW_GOLEM_MELTS)) { +- this.hurt(this.damageSources().onFire(), 1.0F); ++ this.hurt(this.damageSources().melting, 1.0F); // CraftBukkit - DamageSource.BURN -> CraftEventFactory.MELTING + } + + if (!this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { + return; + } + +- BlockState blockState = Blocks.SNOW.defaultBlockState(); ++ IBlockData iblockdata = Blocks.SNOW.defaultBlockState(); + +- for (int i = 0; i < 4; i++) { +- int floor = Mth.floor(this.getX() + (double)((float)(i % 2 * 2 - 1) * 0.25F)); +- int floor1 = Mth.floor(this.getY()); +- int floor2 = Mth.floor(this.getZ() + (double)((float)(i / 2 % 2 * 2 - 1) * 0.25F)); +- BlockPos blockPos = new BlockPos(floor, floor1, floor2); +- if (this.level().getBlockState(blockPos).isAir() && blockState.canSurvive(this.level(), blockPos)) { +- this.level().setBlockAndUpdate(blockPos, blockState); +- this.level().gameEvent(GameEvent.BLOCK_PLACE, blockPos, GameEvent.Context.of(this, blockState)); ++ for (int i = 0; i < 4; ++i) { ++ int j = Mth.floor(this.getX() + (double) ((float) (i % 2 * 2 - 1) * 0.25F)); ++ int k = Mth.floor(this.getY()); ++ int l = Mth.floor(this.getZ() + (double) ((float) (i / 2 % 2 * 2 - 1) * 0.25F)); ++ BlockPos blockposition = new BlockPos(j, k, l); ++ ++ if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handleBlockFormEvent(this.level(), blockposition, iblockdata, this)) { ++ continue; ++ } ++ // CraftBukkit end ++ this.level().gameEvent(GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(this, iblockdata)); + } + } + } ++ + } + + @Override + public void performRangedAttack(LivingEntity target, float distanceFactor) { +- Snowball snowball = new Snowball(this.level(), this); +- double d = target.getEyeY() - 1.1F; ++ Snowball entitysnowball = new Snowball(this.level(), this); ++ double d0 = target.getEyeY() - 1.100000023841858D; + double d1 = target.getX() - this.getX(); +- double d2 = d - snowball.getY(); ++ double d2 = d0 - entitysnowball.getY(); + double d3 = target.getZ() - this.getZ(); +- double d4 = Math.sqrt(d1 * d1 + d3 * d3) * 0.2F; +- snowball.shoot(d1, d2 + d4, d3, 1.6F, 12.0F); ++ double d4 = Math.sqrt(d1 * d1 + d3 * d3) * 0.20000000298023224D; ++ ++ entitysnowball.shoot(d1, d2 + d4, d3, 1.6F, 12.0F); + this.playSound(SoundEvents.SNOW_GOLEM_SHOOT, 1.0F, 0.4F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); +- this.level().addFreshEntity(snowball); ++ this.level().addFreshEntity(entitysnowball); + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 1.7F; + } + + @Override +- protected InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (itemInHand.is(Items.SHEARS) && this.readyForShearing()) { ++ protected InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (itemstack.is(Items.SHEARS) && this.readyForShearing()) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) { ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.shear(SoundSource.PLAYERS); + this.gameEvent(GameEvent.SHEAR, player); + if (!this.level().isClientSide) { +- itemInHand.hurtAndBreak(1, player, entity -> entity.broadcastBreakEvent(hand)); ++ itemstack.hurtAndBreak(1, player, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(hand); ++ }); + } + + return InteractionResult.sidedSuccess(this.level().isClientSide); +@@ -150,11 +173,14 @@ + + @Override + public void shear(SoundSource category) { +- this.level().playSound(null, this, SoundEvents.SNOW_GOLEM_SHEAR, category, 1.0F, 1.0F); ++ this.level().playSound((Player) null, (Entity) this, SoundEvents.SNOW_GOLEM_SHEAR, category, 1.0F, 1.0F); + if (!this.level().isClientSide()) { + this.setPumpkin(false); ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation(new ItemStack(Items.CARVED_PUMPKIN), 1.7F); ++ this.forceDrops = false; // CraftBukkit + } ++ + } + + @Override +@@ -163,16 +189,18 @@ + } + + public boolean hasPumpkin() { +- return (this.entityData.get(DATA_PUMPKIN_ID) & 16) != 0; ++ return ((Byte) this.entityData.get(SnowGolem.DATA_PUMPKIN_ID) & 16) != 0; + } + + public void setPumpkin(boolean pumpkinEquipped) { +- byte b = this.entityData.get(DATA_PUMPKIN_ID); ++ byte b0 = (Byte) this.entityData.get(SnowGolem.DATA_PUMPKIN_ID); ++ + if (pumpkinEquipped) { +- this.entityData.set(DATA_PUMPKIN_ID, (byte)(b | 16)); ++ this.entityData.set(SnowGolem.DATA_PUMPKIN_ID, (byte) (b0 | 16)); + } else { +- this.entityData.set(DATA_PUMPKIN_ID, (byte)(b & -17)); ++ this.entityData.set(SnowGolem.DATA_PUMPKIN_ID, (byte) (b0 & -17)); + } ++ + } + + @Nullable +@@ -195,6 +223,6 @@ + + @Override + public Vec3 getLeashOffset() { +- return new Vec3(0.0, (double)(0.75F * this.getEyeHeight()), (double)(this.getBbWidth() * 0.4F)); ++ return new Vec3(0.0D, (double) (0.75F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Turtle.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Turtle.java.patch new file mode 100644 index 0000000000..3963921386 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Turtle.java.patch @@ -0,0 +1,869 @@ +--- a/net/minecraft/world/entity/animal/Turtle.java ++++ b/net/minecraft/world/entity/animal/Turtle.java +@@ -23,14 +23,14 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.ExperienceOrb; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LightningBolt; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.MoveControl; +@@ -56,13 +56,14 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.TurtleEggBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + + public class Turtle extends Animal { ++ + private static final EntityDataAccessor HOME_POS = SynchedEntityData.defineId(Turtle.class, EntityDataSerializers.BLOCK_POS); + private static final EntityDataAccessor HAS_EGG = SynchedEntityData.defineId(Turtle.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor LAYING_EGG = SynchedEntityData.defineId(Turtle.class, EntityDataSerializers.BOOLEAN); +@@ -71,7 +72,9 @@ + private static final EntityDataAccessor TRAVELLING = SynchedEntityData.defineId(Turtle.class, EntityDataSerializers.BOOLEAN); + public static final Ingredient FOOD_ITEMS = Ingredient.of(Blocks.SEAGRASS.asItem()); + int layEggCounter; +- public static final Predicate BABY_ON_LAND_SELECTOR = livingEntity -> livingEntity.isBaby() && !livingEntity.isInWater(); ++ public static final Predicate BABY_ON_LAND_SELECTOR = (entityliving) -> { ++ return entityliving.isBaby() && !entityliving.isInWater(); ++ }; + + public Turtle(EntityType entityType, Level level) { + super(entityType, level); +@@ -84,63 +87,63 @@ + } + + public void setHomePos(BlockPos homePos) { +- this.entityData.set(HOME_POS, homePos); ++ this.entityData.set(Turtle.HOME_POS, homePos); + } + + BlockPos getHomePos() { +- return this.entityData.get(HOME_POS); ++ return (BlockPos) this.entityData.get(Turtle.HOME_POS); + } + + void setTravelPos(BlockPos travelPos) { +- this.entityData.set(TRAVEL_POS, travelPos); ++ this.entityData.set(Turtle.TRAVEL_POS, travelPos); + } + + BlockPos getTravelPos() { +- return this.entityData.get(TRAVEL_POS); ++ return (BlockPos) this.entityData.get(Turtle.TRAVEL_POS); + } + + public boolean hasEgg() { +- return this.entityData.get(HAS_EGG); ++ return (Boolean) this.entityData.get(Turtle.HAS_EGG); + } + + void setHasEgg(boolean hasEgg) { +- this.entityData.set(HAS_EGG, hasEgg); ++ this.entityData.set(Turtle.HAS_EGG, hasEgg); + } + + public boolean isLayingEgg() { +- return this.entityData.get(LAYING_EGG); ++ return (Boolean) this.entityData.get(Turtle.LAYING_EGG); + } + + void setLayingEgg(boolean isLayingEgg) { + this.layEggCounter = isLayingEgg ? 1 : 0; +- this.entityData.set(LAYING_EGG, isLayingEgg); ++ this.entityData.set(Turtle.LAYING_EGG, isLayingEgg); + } + + boolean isGoingHome() { +- return this.entityData.get(GOING_HOME); ++ return (Boolean) this.entityData.get(Turtle.GOING_HOME); + } + + void setGoingHome(boolean isGoingHome) { +- this.entityData.set(GOING_HOME, isGoingHome); ++ this.entityData.set(Turtle.GOING_HOME, isGoingHome); + } + + boolean isTravelling() { +- return this.entityData.get(TRAVELLING); ++ return (Boolean) this.entityData.get(Turtle.TRAVELLING); + } + + void setTravelling(boolean isTravelling) { +- this.entityData.set(TRAVELLING, isTravelling); ++ this.entityData.set(Turtle.TRAVELLING, isTravelling); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(HOME_POS, BlockPos.ZERO); +- this.entityData.define(HAS_EGG, false); +- this.entityData.define(TRAVEL_POS, BlockPos.ZERO); +- this.entityData.define(GOING_HOME, false); +- this.entityData.define(TRAVELLING, false); +- this.entityData.define(LAYING_EGG, false); ++ this.entityData.define(Turtle.HOME_POS, BlockPos.ZERO); ++ this.entityData.define(Turtle.HAS_EGG, false); ++ this.entityData.define(Turtle.TRAVEL_POS, BlockPos.ZERO); ++ this.entityData.define(Turtle.GOING_HOME, false); ++ this.entityData.define(Turtle.TRAVELLING, false); ++ this.entityData.define(Turtle.LAYING_EGG, false); + } + + @Override +@@ -157,47 +160,47 @@ + + @Override + public void readAdditionalSaveData(CompoundTag compound) { +- int _int = compound.getInt("HomePosX"); +- int _int1 = compound.getInt("HomePosY"); +- int _int2 = compound.getInt("HomePosZ"); +- this.setHomePos(new BlockPos(_int, _int1, _int2)); ++ int i = compound.getInt("HomePosX"); ++ int j = compound.getInt("HomePosY"); ++ int k = compound.getInt("HomePosZ"); ++ ++ this.setHomePos(new BlockPos(i, j, k)); + super.readAdditionalSaveData(compound); + this.setHasEgg(compound.getBoolean("HasEgg")); +- int _int3 = compound.getInt("TravelPosX"); +- int _int4 = compound.getInt("TravelPosY"); +- int _int5 = compound.getInt("TravelPosZ"); +- this.setTravelPos(new BlockPos(_int3, _int4, _int5)); ++ int l = compound.getInt("TravelPosX"); ++ int i1 = compound.getInt("TravelPosY"); ++ int j1 = compound.getInt("TravelPosZ"); ++ ++ this.setTravelPos(new BlockPos(l, i1, j1)); + } + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + this.setHomePos(this.blockPosition()); + this.setTravelPos(BlockPos.ZERO); + return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + +- public static boolean checkTurtleSpawnRules(EntityType turtle, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) { ++ public static boolean checkTurtleSpawnRules(EntityType turtle, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { + return pos.getY() < level.getSeaLevel() + 4 && TurtleEggBlock.onSand(level, pos) && isBrightEnoughToSpawn(level, pos); + } + + @Override + protected void registerGoals() { +- this.goalSelector.addGoal(0, new Turtle.TurtlePanicGoal(this, 1.2)); +- this.goalSelector.addGoal(1, new Turtle.TurtleBreedGoal(this, 1.0)); +- this.goalSelector.addGoal(1, new Turtle.TurtleLayEggGoal(this, 1.0)); +- this.goalSelector.addGoal(2, new TemptGoal(this, 1.1, FOOD_ITEMS, false)); +- this.goalSelector.addGoal(3, new Turtle.TurtleGoToWaterGoal(this, 1.0)); +- this.goalSelector.addGoal(4, new Turtle.TurtleGoHomeGoal(this, 1.0)); +- this.goalSelector.addGoal(7, new Turtle.TurtleTravelGoal(this, 1.0)); ++ this.goalSelector.addGoal(0, new Turtle.TurtlePanicGoal(this, 1.2D)); ++ this.goalSelector.addGoal(1, new Turtle.TurtleBreedGoal(this, 1.0D)); ++ this.goalSelector.addGoal(1, new Turtle.TurtleLayEggGoal(this, 1.0D)); ++ this.goalSelector.addGoal(2, new TemptGoal(this, 1.1D, Turtle.FOOD_ITEMS, false)); ++ this.goalSelector.addGoal(3, new Turtle.TurtleGoToWaterGoal(this, 1.0D)); ++ this.goalSelector.addGoal(4, new Turtle.TurtleGoHomeGoal(this, 1.0D)); ++ this.goalSelector.addGoal(7, new Turtle.TurtleTravelGoal(this, 1.0D)); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); +- this.goalSelector.addGoal(9, new Turtle.TurtleRandomStrollGoal(this, 1.0, 100)); ++ this.goalSelector.addGoal(9, new Turtle.TurtleRandomStrollGoal(this, 1.0D, 100)); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 30.0).add(Attributes.MOVEMENT_SPEED, 0.25); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 30.0D).add(Attributes.MOVEMENT_SPEED, 0.25D); + } + + @Override +@@ -206,8 +209,8 @@ + } + + @Override +- public MobType getMobType() { +- return MobType.WATER; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.WATER; + } + + @Override +@@ -244,9 +247,10 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { +- SoundEvent soundEvent = this.isBaby() ? SoundEvents.TURTLE_SHAMBLE_BABY : SoundEvents.TURTLE_SHAMBLE; +- this.playSound(soundEvent, 0.15F, 1.0F); ++ protected void playStepSound(BlockPos pos, IBlockData block) { ++ SoundEvent soundeffect = this.isBaby() ? SoundEvents.TURTLE_SHAMBLE_BABY : SoundEvents.TURTLE_SHAMBLE; ++ ++ this.playSound(soundeffect, 0.15F, 1.0F); + } + + @Override +@@ -272,7 +276,7 @@ + @Nullable + @Override + public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob otherParent) { +- return EntityType.TURTLE.create(level); ++ return (AgeableMob) EntityType.TURTLE.create(level); + } + + @Override +@@ -282,45 +286,47 @@ + + @Override + public float getWalkTargetValue(BlockPos pos, LevelReader level) { +- if (!this.isGoingHome() && level.getFluidState(pos).is(FluidTags.WATER)) { +- return 10.0F; +- } else { +- return TurtleEggBlock.onSand(level, pos) ? 10.0F : level.getPathfindingCostFromLightLevels(pos); +- } ++ return !this.isGoingHome() && level.getFluidState(pos).is(FluidTags.WATER) ? 10.0F : (TurtleEggBlock.onSand(level, pos) ? 10.0F : level.getPathfindingCostFromLightLevels(pos)); + } + + @Override + public void aiStep() { + super.aiStep(); + if (this.isAlive() && this.isLayingEgg() && this.layEggCounter >= 1 && this.layEggCounter % 5 == 0) { +- BlockPos blockPos = this.blockPosition(); +- if (TurtleEggBlock.onSand(this.level(), blockPos)) { +- this.level().levelEvent(2001, blockPos, Block.getId(this.level().getBlockState(blockPos.below()))); ++ BlockPos blockposition = this.blockPosition(); ++ ++ if (TurtleEggBlock.onSand(this.level(), blockposition)) { ++ this.level().levelEvent(2001, blockposition, Block.getId(this.level().getBlockState(blockposition.below()))); + this.gameEvent(GameEvent.ENTITY_ACTION); + } + } ++ + } + + @Override + protected void ageBoundaryReached() { + super.ageBoundaryReached(); + if (!this.isBaby() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation(Items.SCUTE, 1); ++ this.forceDrops = false; // CraftBukkit + } ++ + } + + @Override + public void travel(Vec3 travelVector) { + if (this.isControlledByLocalInstance() && this.isInWater()) { + this.moveRelative(0.1F, travelVector); +- this.move(MoverType.SELF, this.getDeltaMovement()); +- this.setDeltaMovement(this.getDeltaMovement().scale(0.9)); +- if (this.getTarget() == null && (!this.isGoingHome() || !this.getHomePos().closerToCenterThan(this.position(), 20.0))) { +- this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.005, 0.0)); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); ++ this.setDeltaMovement(this.getDeltaMovement().scale(0.9D)); ++ if (this.getTarget() == null && (!this.isGoingHome() || !this.getHomePos().closerToCenterThan(this.position(), 20.0D))) { ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.005D, 0.0D)); + } + } else { + super.travel(travelVector); + } ++ + } + + @Override +@@ -330,17 +336,98 @@ + + @Override + public void thunderHit(ServerLevel level, LightningBolt lightning) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = lightning; // CraftBukkit + this.hurt(this.damageSources().lightningBolt(), Float.MAX_VALUE); ++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = null; // CraftBukkit + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + (this.isBaby() ? 0.0F : 0.15625F) * f, -0.25F * f); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + (this.isBaby() ? 0.0F : 0.15625F) * f, -0.25F * f); + } + +- static class TurtleBreedGoal extends BreedGoal { ++ private static class TurtleMoveControl extends MoveControl { ++ + private final Turtle turtle; + ++ TurtleMoveControl(Turtle turtle) { ++ super(turtle); ++ this.turtle = turtle; ++ } ++ ++ private void updateSpeed() { ++ if (this.turtle.isInWater()) { ++ this.turtle.setDeltaMovement(this.turtle.getDeltaMovement().add(0.0D, 0.005D, 0.0D)); ++ if (!this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 16.0D)) { ++ this.turtle.setSpeed(Math.max(this.turtle.getSpeed() / 2.0F, 0.08F)); ++ } ++ ++ if (this.turtle.isBaby()) { ++ this.turtle.setSpeed(Math.max(this.turtle.getSpeed() / 3.0F, 0.06F)); ++ } ++ } else if (this.turtle.onGround()) { ++ this.turtle.setSpeed(Math.max(this.turtle.getSpeed() / 2.0F, 0.06F)); ++ } ++ ++ } ++ ++ @Override ++ public void tick() { ++ this.updateSpeed(); ++ if (this.operation == MoveControl.Operation.MOVE_TO && !this.turtle.getNavigation().isDone()) { ++ double d0 = this.wantedX - this.turtle.getX(); ++ double d1 = this.wantedY - this.turtle.getY(); ++ double d2 = this.wantedZ - this.turtle.getZ(); ++ double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2); ++ ++ if (d3 < 9.999999747378752E-6D) { ++ this.mob.setSpeed(0.0F); ++ } else { ++ d1 /= d3; ++ float f = (float) (Mth.atan2(d2, d0) * 57.2957763671875D) - 90.0F; ++ ++ this.turtle.setYRot(this.rotlerp(this.turtle.getYRot(), f, 90.0F)); ++ this.turtle.yBodyRot = this.turtle.getYRot(); ++ float f1 = (float) (this.speedModifier * this.turtle.getAttributeValue(Attributes.MOVEMENT_SPEED)); ++ ++ this.turtle.setSpeed(Mth.lerp(0.125F, this.turtle.getSpeed(), f1)); ++ this.turtle.setDeltaMovement(this.turtle.getDeltaMovement().add(0.0D, (double) this.turtle.getSpeed() * d1 * 0.1D, 0.0D)); ++ } ++ } else { ++ this.turtle.setSpeed(0.0F); ++ } ++ } ++ } ++ ++ private static class TurtlePanicGoal extends PanicGoal { ++ ++ TurtlePanicGoal(Turtle turtle, double speedModifier) { ++ super(turtle, speedModifier); ++ } ++ ++ @Override ++ public boolean canUse() { ++ if (!this.shouldPanic()) { ++ return false; ++ } else { ++ BlockPos blockposition = this.lookForWater(this.mob.level(), this.mob, 7); ++ ++ if (blockposition != null) { ++ this.posX = (double) blockposition.getX(); ++ this.posY = (double) blockposition.getY(); ++ this.posZ = (double) blockposition.getZ(); ++ return true; ++ } else { ++ return this.findRandomPosition(); ++ } ++ } ++ } ++ } ++ ++ private static class TurtleBreedGoal extends BreedGoal { ++ ++ private final Turtle turtle; ++ + TurtleBreedGoal(Turtle turtle, double speedModifier) { + super(turtle, speedModifier); + this.turtle = turtle; +@@ -353,14 +440,15 @@ + + @Override + protected void breed() { +- ServerPlayer loveCause = this.animal.getLoveCause(); +- if (loveCause == null && this.partner.getLoveCause() != null) { +- loveCause = this.partner.getLoveCause(); ++ ServerPlayer entityplayer = this.animal.getLoveCause(); ++ ++ if (entityplayer == null && this.partner.getLoveCause() != null) { ++ entityplayer = this.partner.getLoveCause(); + } + +- if (loveCause != null) { +- loveCause.awardStat(Stats.ANIMALS_BRED); +- CriteriaTriggers.BRED_ANIMALS.trigger(loveCause, this.animal, this.partner, null); ++ if (entityplayer != null) { ++ entityplayer.awardStat(Stats.ANIMALS_BRED); ++ CriteriaTriggers.BRED_ANIMALS.trigger(entityplayer, this.animal, this.partner, (AgeableMob) null); + } + + this.turtle.setHasEgg(true); +@@ -368,89 +456,78 @@ + this.partner.setAge(6000); + this.animal.resetLove(); + this.partner.resetLove(); +- RandomSource random = this.animal.getRandom(); ++ RandomSource randomsource = this.animal.getRandom(); ++ + if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), random.nextInt(7) + 1)); ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), randomsource.nextInt(7) + 1)); + } ++ + } + } + +- static class TurtleGoHomeGoal extends Goal { ++ private static class TurtleLayEggGoal extends MoveToBlockGoal { ++ + private final Turtle turtle; +- private final double speedModifier; +- private boolean stuck; +- private int closeToHomeTryTicks; +- private static final int GIVE_UP_TICKS = 600; + +- TurtleGoHomeGoal(Turtle turtle, double speedModifier) { ++ TurtleLayEggGoal(Turtle turtle, double speedModifier) { ++ super(turtle, speedModifier, 16); + this.turtle = turtle; +- this.speedModifier = speedModifier; + } + + @Override + public boolean canUse() { +- return !this.turtle.isBaby() +- && ( +- this.turtle.hasEgg() +- || this.turtle.getRandom().nextInt(reducedTickDelay(700)) == 0 +- && !this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 64.0) +- ); ++ return this.turtle.hasEgg() && this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 9.0D) ? super.canUse() : false; + } + + @Override +- public void start() { +- this.turtle.setGoingHome(true); +- this.stuck = false; +- this.closeToHomeTryTicks = 0; +- } +- +- @Override +- public void stop() { +- this.turtle.setGoingHome(false); +- } +- +- @Override + public boolean canContinueToUse() { +- return !this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 7.0) +- && !this.stuck +- && this.closeToHomeTryTicks <= this.adjustedTickDelay(600); ++ return super.canContinueToUse() && this.turtle.hasEgg() && this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 9.0D); + } + + @Override + public void tick() { +- BlockPos homePos = this.turtle.getHomePos(); +- boolean flag = homePos.closerToCenterThan(this.turtle.position(), 16.0); +- if (flag) { +- this.closeToHomeTryTicks++; +- } ++ super.tick(); ++ BlockPos blockposition = this.turtle.blockPosition(); + +- if (this.turtle.getNavigation().isDone()) { +- Vec3 vec3 = Vec3.atBottomCenterOf(homePos); +- Vec3 posTowards = DefaultRandomPos.getPosTowards(this.turtle, 16, 3, vec3, (float) (Math.PI / 10)); +- if (posTowards == null) { +- posTowards = DefaultRandomPos.getPosTowards(this.turtle, 8, 7, vec3, (float) (Math.PI / 2)); +- } ++ if (!this.turtle.isInWater() && this.isReachedTarget()) { ++ if (this.turtle.layEggCounter < 1) { ++ this.turtle.setLayingEgg(true); ++ } else if (this.turtle.layEggCounter > this.adjustedTickDelay(200)) { ++ Level world = this.turtle.level(); + +- if (posTowards != null && !flag && !this.turtle.level().getBlockState(BlockPos.containing(posTowards)).is(Blocks.WATER)) { +- posTowards = DefaultRandomPos.getPosTowards(this.turtle, 16, 5, vec3, (float) (Math.PI / 2)); +- } ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.turtle, this.blockPos.above(), (IBlockData) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1))) { // CraftBukkit ++ world.playSound((Player) null, blockposition, SoundEvents.TURTLE_LAY_EGG, SoundSource.BLOCKS, 0.3F, 0.9F + world.random.nextFloat() * 0.2F); ++ BlockPos blockposition1 = this.blockPos.above(); ++ IBlockData iblockdata = (IBlockData) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1); + +- if (posTowards == null) { +- this.stuck = true; +- return; ++ world.setBlock(blockposition1, iblockdata, 3); ++ world.gameEvent(GameEvent.BLOCK_PLACE, blockposition1, GameEvent.Context.of(this.turtle, iblockdata)); ++ } // CraftBukkit ++ this.turtle.setHasEgg(false); ++ this.turtle.setLayingEgg(false); ++ this.turtle.setInLoveTime(600); + } + +- this.turtle.getNavigation().moveTo(posTowards.x, posTowards.y, posTowards.z, this.speedModifier); ++ if (this.turtle.isLayingEgg()) { ++ ++this.turtle.layEggCounter; ++ } + } ++ + } ++ ++ @Override ++ protected boolean isValidTarget(LevelReader level, BlockPos pos) { ++ return !level.isEmptyBlock(pos.above()) ? false : TurtleEggBlock.isSand(level, pos); ++ } + } + +- static class TurtleGoToWaterGoal extends MoveToBlockGoal { ++ private static class TurtleGoToWaterGoal extends MoveToBlockGoal { ++ + private static final int GIVE_UP_TICKS = 1200; + private final Turtle turtle; + + TurtleGoToWaterGoal(Turtle turtle, double speedModifier) { +- super(turtle, turtle.isBaby() ? 2.0 : speedModifier, 24); ++ super(turtle, turtle.isBaby() ? 2.0D : speedModifier, 24); + this.turtle = turtle; + this.verticalSearchStart = -1; + } +@@ -462,9 +539,7 @@ + + @Override + public boolean canUse() { +- return this.turtle.isBaby() && !this.turtle.isInWater() +- ? super.canUse() +- : !this.turtle.isGoingHome() && !this.turtle.isInWater() && !this.turtle.hasEgg() && super.canUse(); ++ return this.turtle.isBaby() && !this.turtle.isInWater() ? super.canUse() : (!this.turtle.isGoingHome() && !this.turtle.isInWater() && !this.turtle.hasEgg() ? super.canUse() : false); + } + + @Override +@@ -478,158 +553,75 @@ + } + } + +- static class TurtleLayEggGoal extends MoveToBlockGoal { ++ private static class TurtleGoHomeGoal extends Goal { ++ + private final Turtle turtle; ++ private final double speedModifier; ++ private boolean stuck; ++ private int closeToHomeTryTicks; ++ private static final int GIVE_UP_TICKS = 600; + +- TurtleLayEggGoal(Turtle turtle, double speedModifier) { +- super(turtle, speedModifier, 16); ++ TurtleGoHomeGoal(Turtle turtle, double speedModifier) { + this.turtle = turtle; ++ this.speedModifier = speedModifier; + } + + @Override + public boolean canUse() { +- return this.turtle.hasEgg() && this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 9.0) && super.canUse(); ++ return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(reducedTickDelay(700)) != 0 ? false : !this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 64.0D))); + } + + @Override +- public boolean canContinueToUse() { +- return super.canContinueToUse() && this.turtle.hasEgg() && this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 9.0); ++ public void start() { ++ this.turtle.setGoingHome(true); ++ this.stuck = false; ++ this.closeToHomeTryTicks = 0; + } + + @Override +- public void tick() { +- super.tick(); +- BlockPos blockPos = this.turtle.blockPosition(); +- if (!this.turtle.isInWater() && this.isReachedTarget()) { +- if (this.turtle.layEggCounter < 1) { +- this.turtle.setLayingEgg(true); +- } else if (this.turtle.layEggCounter > this.adjustedTickDelay(200)) { +- Level level = this.turtle.level(); +- level.playSound(null, blockPos, SoundEvents.TURTLE_LAY_EGG, SoundSource.BLOCKS, 0.3F, 0.9F + level.random.nextFloat() * 0.2F); +- BlockPos blockPos1 = this.blockPos.above(); +- BlockState blockState = Blocks.TURTLE_EGG +- .defaultBlockState() +- .setValue(TurtleEggBlock.EGGS, Integer.valueOf(this.turtle.random.nextInt(4) + 1)); +- level.setBlock(blockPos1, blockState, 3); +- level.gameEvent(GameEvent.BLOCK_PLACE, blockPos1, GameEvent.Context.of(this.turtle, blockState)); +- this.turtle.setHasEgg(false); +- this.turtle.setLayingEgg(false); +- this.turtle.setInLoveTime(600); +- } +- +- if (this.turtle.isLayingEgg()) { +- this.turtle.layEggCounter++; +- } +- } ++ public void stop() { ++ this.turtle.setGoingHome(false); + } + + @Override +- protected boolean isValidTarget(LevelReader level, BlockPos pos) { +- return level.isEmptyBlock(pos.above()) && TurtleEggBlock.isSand(level, pos); ++ public boolean canContinueToUse() { ++ return !this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 7.0D) && !this.stuck && this.closeToHomeTryTicks <= this.adjustedTickDelay(600); + } +- } + +- static class TurtleMoveControl extends MoveControl { +- private final Turtle turtle; ++ @Override ++ public void tick() { ++ BlockPos blockposition = this.turtle.getHomePos(); ++ boolean flag = blockposition.closerToCenterThan(this.turtle.position(), 16.0D); + +- TurtleMoveControl(Turtle mob) { +- super(mob); +- this.turtle = mob; +- } ++ if (flag) { ++ ++this.closeToHomeTryTicks; ++ } + +- private void updateSpeed() { +- if (this.turtle.isInWater()) { +- this.turtle.setDeltaMovement(this.turtle.getDeltaMovement().add(0.0, 0.005, 0.0)); +- if (!this.turtle.getHomePos().closerToCenterThan(this.turtle.position(), 16.0)) { +- this.turtle.setSpeed(Math.max(this.turtle.getSpeed() / 2.0F, 0.08F)); +- } ++ if (this.turtle.getNavigation().isDone()) { ++ Vec3 vec3d = Vec3.atBottomCenterOf(blockposition); ++ Vec3 vec3d1 = DefaultRandomPos.getPosTowards(this.turtle, 16, 3, vec3d, 0.3141592741012573D); + +- if (this.turtle.isBaby()) { +- this.turtle.setSpeed(Math.max(this.turtle.getSpeed() / 3.0F, 0.06F)); ++ if (vec3d1 == null) { ++ vec3d1 = DefaultRandomPos.getPosTowards(this.turtle, 8, 7, vec3d, 1.5707963705062866D); + } +- } else if (this.turtle.onGround()) { +- this.turtle.setSpeed(Math.max(this.turtle.getSpeed() / 2.0F, 0.06F)); +- } +- } + +- @Override +- public void tick() { +- this.updateSpeed(); +- if (this.operation == MoveControl.Operation.MOVE_TO && !this.turtle.getNavigation().isDone()) { +- double d = this.wantedX - this.turtle.getX(); +- double d1 = this.wantedY - this.turtle.getY(); +- double d2 = this.wantedZ - this.turtle.getZ(); +- double squareRoot = Math.sqrt(d * d + d1 * d1 + d2 * d2); +- if (squareRoot < 1.0E-5F) { +- this.mob.setSpeed(0.0F); +- } else { +- d1 /= squareRoot; +- float f = (float)(Mth.atan2(d2, d) * 180.0F / (float)Math.PI) - 90.0F; +- this.turtle.setYRot(this.rotlerp(this.turtle.getYRot(), f, 90.0F)); +- this.turtle.yBodyRot = this.turtle.getYRot(); +- float f1 = (float)(this.speedModifier * this.turtle.getAttributeValue(Attributes.MOVEMENT_SPEED)); +- this.turtle.setSpeed(Mth.lerp(0.125F, this.turtle.getSpeed(), f1)); +- this.turtle.setDeltaMovement(this.turtle.getDeltaMovement().add(0.0, (double)this.turtle.getSpeed() * d1 * 0.1, 0.0)); ++ if (vec3d1 != null && !flag && !this.turtle.level().getBlockState(BlockPos.containing(vec3d1)).is(Blocks.WATER)) { ++ vec3d1 = DefaultRandomPos.getPosTowards(this.turtle, 16, 5, vec3d, 1.5707963705062866D); + } +- } else { +- this.turtle.setSpeed(0.0F); +- } +- } +- } + +- static class TurtlePanicGoal extends PanicGoal { +- TurtlePanicGoal(Turtle turtle, double speedModifier) { +- super(turtle, speedModifier); +- } +- +- @Override +- public boolean canUse() { +- if (!this.shouldPanic()) { +- return false; +- } else { +- BlockPos blockPos = this.lookForWater(this.mob.level(), this.mob, 7); +- if (blockPos != null) { +- this.posX = (double)blockPos.getX(); +- this.posY = (double)blockPos.getY(); +- this.posZ = (double)blockPos.getZ(); +- return true; +- } else { +- return this.findRandomPosition(); ++ if (vec3d1 == null) { ++ this.stuck = true; ++ return; + } +- } +- } +- } + +- static class TurtlePathNavigation extends AmphibiousPathNavigation { +- TurtlePathNavigation(Turtle turtle, Level level) { +- super(turtle, level); +- } +- +- @Override +- public boolean isStableDestination(BlockPos pos) { +- if (this.mob instanceof Turtle turtle && turtle.isTravelling()) { +- return this.level.getBlockState(pos).is(Blocks.WATER); ++ this.turtle.getNavigation().moveTo(vec3d1.x, vec3d1.y, vec3d1.z, this.speedModifier); + } + +- return !this.level.getBlockState(pos.below()).isAir(); + } + } + +- static class TurtleRandomStrollGoal extends RandomStrollGoal { +- private final Turtle turtle; ++ private static class TurtleTravelGoal extends Goal { + +- TurtleRandomStrollGoal(Turtle turtle, double speedModifier, int interval) { +- super(turtle, speedModifier, interval); +- this.turtle = turtle; +- } +- +- @Override +- public boolean canUse() { +- return !this.mob.isInWater() && !this.turtle.isGoingHome() && !this.turtle.hasEgg() && super.canUse(); +- } +- } +- +- static class TurtleTravelGoal extends Goal { + private final Turtle turtle; + private final double speedModifier; + private boolean stuck; +@@ -646,18 +638,20 @@ + + @Override + public void start() { +- int i = 512; +- int i1 = 4; +- RandomSource randomSource = this.turtle.random; +- int i2 = randomSource.nextInt(1025) - 512; +- int i3 = randomSource.nextInt(9) - 4; +- int i4 = randomSource.nextInt(1025) - 512; +- if ((double)i3 + this.turtle.getY() > (double)(this.turtle.level().getSeaLevel() - 1)) { +- i3 = 0; ++ boolean flag = true; ++ boolean flag1 = true; ++ RandomSource randomsource = this.turtle.random; ++ int i = randomsource.nextInt(1025) - 512; ++ int j = randomsource.nextInt(9) - 4; ++ int k = randomsource.nextInt(1025) - 512; ++ ++ if ((double) j + this.turtle.getY() > (double) (this.turtle.level().getSeaLevel() - 1)) { ++ j = 0; + } + +- BlockPos blockPos = BlockPos.containing((double)i2 + this.turtle.getX(), (double)i3 + this.turtle.getY(), (double)i4 + this.turtle.getZ()); +- this.turtle.setTravelPos(blockPos); ++ BlockPos blockposition = BlockPos.containing((double) i + this.turtle.getX(), (double) j + this.turtle.getY(), (double) k + this.turtle.getZ()); ++ ++ this.turtle.setTravelPos(blockposition); + this.turtle.setTravelling(true); + this.stuck = false; + } +@@ -665,28 +659,31 @@ + @Override + public void tick() { + if (this.turtle.getNavigation().isDone()) { +- Vec3 vec3 = Vec3.atBottomCenterOf(this.turtle.getTravelPos()); +- Vec3 posTowards = DefaultRandomPos.getPosTowards(this.turtle, 16, 3, vec3, (float) (Math.PI / 10)); +- if (posTowards == null) { +- posTowards = DefaultRandomPos.getPosTowards(this.turtle, 8, 7, vec3, (float) (Math.PI / 2)); ++ Vec3 vec3d = Vec3.atBottomCenterOf(this.turtle.getTravelPos()); ++ Vec3 vec3d1 = DefaultRandomPos.getPosTowards(this.turtle, 16, 3, vec3d, 0.3141592741012573D); ++ ++ if (vec3d1 == null) { ++ vec3d1 = DefaultRandomPos.getPosTowards(this.turtle, 8, 7, vec3d, 1.5707963705062866D); + } + +- if (posTowards != null) { +- int floor = Mth.floor(posTowards.x); +- int floor1 = Mth.floor(posTowards.z); +- int i = 34; +- if (!this.turtle.level().hasChunksAt(floor - 34, floor1 - 34, floor + 34, floor1 + 34)) { +- posTowards = null; ++ if (vec3d1 != null) { ++ int i = Mth.floor(vec3d1.x); ++ int j = Mth.floor(vec3d1.z); ++ boolean flag = true; ++ ++ if (!this.turtle.level().hasChunksAt(i - 34, j - 34, i + 34, j + 34)) { ++ vec3d1 = null; + } + } + +- if (posTowards == null) { ++ if (vec3d1 == null) { + this.stuck = true; + return; + } + +- this.turtle.getNavigation().moveTo(posTowards.x, posTowards.y, posTowards.z, this.speedModifier); ++ this.turtle.getNavigation().moveTo(vec3d1.x, vec3d1.y, vec3d1.z, this.speedModifier); + } ++ + } + + @Override +@@ -700,4 +697,41 @@ + super.stop(); + } + } ++ ++ private static class TurtleRandomStrollGoal extends RandomStrollGoal { ++ ++ private final Turtle turtle; ++ ++ TurtleRandomStrollGoal(Turtle turtle, double speedModifier, int i) { ++ super(turtle, speedModifier, i); ++ this.turtle = turtle; ++ } ++ ++ @Override ++ public boolean canUse() { ++ return !this.mob.isInWater() && !this.turtle.isGoingHome() && !this.turtle.hasEgg() ? super.canUse() : false; ++ } ++ } ++ ++ private static class TurtlePathNavigation extends AmphibiousPathNavigation { ++ ++ TurtlePathNavigation(Turtle turtle, Level level) { ++ super(turtle, level); ++ } ++ ++ @Override ++ public boolean isStableDestination(BlockPos pos) { ++ Mob entityinsentient = this.mob; ++ ++ if (entityinsentient instanceof Turtle) { ++ Turtle entityturtle = (Turtle) entityinsentient; ++ ++ if (entityturtle.isTravelling()) { ++ return this.level.getBlockState(pos).is(Blocks.WATER); ++ } ++ } ++ ++ return !this.level.getBlockState(pos.below()).isAir(); ++ } ++ } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Wolf.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Wolf.java.patch new file mode 100644 index 0000000000..0b586a49a0 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Wolf.java.patch @@ -0,0 +1,592 @@ +--- a/net/minecraft/world/entity/animal/Wolf.java ++++ b/net/minecraft/world/entity/animal/Wolf.java +@@ -17,18 +17,18 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.util.TimeUtil; + import net.minecraft.util.valueproviders.UniformInt; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.NeutralMob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.TamableAnimal; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -64,19 +64,27 @@ + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class Wolf extends TamableAnimal implements NeutralMob { ++ + private static final EntityDataAccessor DATA_INTERESTED_ID = SynchedEntityData.defineId(Wolf.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_COLLAR_COLOR = SynchedEntityData.defineId(Wolf.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_REMAINING_ANGER_TIME = SynchedEntityData.defineId(Wolf.class, EntityDataSerializers.INT); +- public static final Predicate PREY_SELECTOR = entity -> { +- EntityType type = entity.getType(); +- return type == EntityType.SHEEP || type == EntityType.RABBIT || type == EntityType.FOX; ++ public static final Predicate PREY_SELECTOR = (entityliving) -> { ++ EntityType entitytypes = entityliving.getType(); ++ ++ return entitytypes == EntityType.SHEEP || entitytypes == EntityType.RABBIT || entitytypes == EntityType.FOX; + }; + private static final float START_HEALTH = 8.0F; + private static final float TAME_HEALTH = 20.0F; +@@ -100,48 +108,48 @@ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new FloatGoal(this)); +- this.goalSelector.addGoal(1, new Wolf.WolfPanicGoal(1.5)); ++ this.goalSelector.addGoal(1, new Wolf.WolfPanicGoal(1.5D)); + this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this)); +- this.goalSelector.addGoal(3, new Wolf.WolfAvoidEntityGoal<>(this, Llama.class, 24.0F, 1.5, 1.5)); ++ this.goalSelector.addGoal(3, new Wolf.WolfAvoidEntityGoal<>(this, Llama.class, 24.0F, 1.5D, 1.5D)); + this.goalSelector.addGoal(4, new LeapAtTargetGoal(this, 0.4F)); +- this.goalSelector.addGoal(5, new MeleeAttackGoal(this, 1.0, true)); +- this.goalSelector.addGoal(6, new FollowOwnerGoal(this, 1.0, 10.0F, 2.0F, false)); +- this.goalSelector.addGoal(7, new BreedGoal(this, 1.0)); +- this.goalSelector.addGoal(8, new WaterAvoidingRandomStrollGoal(this, 1.0)); ++ this.goalSelector.addGoal(5, new MeleeAttackGoal(this, 1.0D, true)); ++ this.goalSelector.addGoal(6, new FollowOwnerGoal(this, 1.0D, 10.0F, 2.0F, false)); ++ this.goalSelector.addGoal(7, new BreedGoal(this, 1.0D)); ++ this.goalSelector.addGoal(8, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.goalSelector.addGoal(9, new BegGoal(this, 8.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(10, new RandomLookAroundGoal(this)); + this.targetSelector.addGoal(1, new OwnerHurtByTargetGoal(this)); + this.targetSelector.addGoal(2, new OwnerHurtTargetGoal(this)); +- this.targetSelector.addGoal(3, new HurtByTargetGoal(this).setAlertOthers()); ++ this.targetSelector.addGoal(3, (new HurtByTargetGoal(this, new Class[0])).setAlertOthers()); + this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt)); +- this.targetSelector.addGoal(5, new NonTameRandomTargetGoal<>(this, Animal.class, false, PREY_SELECTOR)); ++ this.targetSelector.addGoal(5, new NonTameRandomTargetGoal<>(this, Animal.class, false, Wolf.PREY_SELECTOR)); + this.targetSelector.addGoal(6, new NonTameRandomTargetGoal<>(this, Turtle.class, false, Turtle.BABY_ON_LAND_SELECTOR)); + this.targetSelector.addGoal(7, new NearestAttackableTargetGoal<>(this, AbstractSkeleton.class, false)); + this.targetSelector.addGoal(8, new ResetUniversalAngerTargetGoal<>(this, true)); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.3F).add(Attributes.MAX_HEALTH, 8.0).add(Attributes.ATTACK_DAMAGE, 2.0); ++ return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D).add(Attributes.MAX_HEALTH, 8.0D).add(Attributes.ATTACK_DAMAGE, 2.0D); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_INTERESTED_ID, false); +- this.entityData.define(DATA_COLLAR_COLOR, DyeColor.RED.getId()); +- this.entityData.define(DATA_REMAINING_ANGER_TIME, 0); ++ this.entityData.define(Wolf.DATA_INTERESTED_ID, false); ++ this.entityData.define(Wolf.DATA_COLLAR_COLOR, DyeColor.RED.getId()); ++ this.entityData.define(Wolf.DATA_REMAINING_ANGER_TIME, 0); + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.WOLF_STEP, 0.15F, 1.0F); + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- compound.putByte("CollarColor", (byte)this.getCollarColor().getId()); ++ compound.putByte("CollarColor", (byte) this.getCollarColor().getId()); + this.addPersistentAngerSaveData(compound); + } + +@@ -157,13 +165,7 @@ + + @Override + protected SoundEvent getAmbientSound() { +- if (this.isAngry()) { +- return SoundEvents.WOLF_GROWL; +- } else if (this.random.nextInt(3) == 0) { +- return this.isTame() && this.getHealth() < 10.0F ? SoundEvents.WOLF_WHINE : SoundEvents.WOLF_PANT; +- } else { +- return SoundEvents.WOLF_AMBIENT; +- } ++ return this.isAngry() ? SoundEvents.WOLF_GROWL : (this.random.nextInt(3) == 0 ? (this.isTame() && this.getHealth() < 10.0F ? SoundEvents.WOLF_WHINE : SoundEvents.WOLF_PANT) : SoundEvents.WOLF_AMBIENT); + } + + @Override +@@ -188,12 +190,13 @@ + this.isShaking = true; + this.shakeAnim = 0.0F; + this.shakeAnimO = 0.0F; +- this.level().broadcastEntityEvent(this, (byte)8); ++ this.level().broadcastEntityEvent(this, (byte) 8); + } + + if (!this.level().isClientSide) { +- this.updatePersistentAnger((ServerLevel)this.level(), true); ++ this.updatePersistentAnger((ServerLevel) this.level(), true); + } ++ + } + + @Override +@@ -202,15 +205,15 @@ + if (this.isAlive()) { + this.interestedAngleO = this.interestedAngle; + if (this.isInterested()) { +- this.interestedAngle = this.interestedAngle + (1.0F - this.interestedAngle) * 0.4F; ++ this.interestedAngle += (1.0F - this.interestedAngle) * 0.4F; + } else { +- this.interestedAngle = this.interestedAngle + (0.0F - this.interestedAngle) * 0.4F; ++ this.interestedAngle += (0.0F - this.interestedAngle) * 0.4F; + } + + if (this.isInWaterRainOrBubble()) { + this.isWet = true; + if (this.isShaking && !this.level().isClientSide) { +- this.level().broadcastEntityEvent(this, (byte)56); ++ this.level().broadcastEntityEvent(this, (byte) 56); + this.cancelShake(); + } + } else if ((this.isWet || this.isShaking) && this.isShaking) { +@@ -229,26 +232,19 @@ + } + + if (this.shakeAnim > 0.4F) { +- float f = (float)this.getY(); +- int i = (int)(Mth.sin((this.shakeAnim - 0.4F) * (float) Math.PI) * 7.0F); +- Vec3 deltaMovement = this.getDeltaMovement(); ++ float f = (float) this.getY(); ++ int i = (int) (Mth.sin((this.shakeAnim - 0.4F) * 3.1415927F) * 7.0F); ++ Vec3 vec3d = this.getDeltaMovement(); + +- for (int i1 = 0; i1 < i; i1++) { ++ for (int j = 0; j < i; ++j) { + float f1 = (this.random.nextFloat() * 2.0F - 1.0F) * this.getBbWidth() * 0.5F; + float f2 = (this.random.nextFloat() * 2.0F - 1.0F) * this.getBbWidth() * 0.5F; +- this.level() +- .addParticle( +- ParticleTypes.SPLASH, +- this.getX() + (double)f1, +- (double)(f + 0.8F), +- this.getZ() + (double)f2, +- deltaMovement.x, +- deltaMovement.y, +- deltaMovement.z +- ); ++ ++ this.level().addParticle(ParticleTypes.SPLASH, this.getX() + (double) f1, (double) (f + 0.8F), this.getZ() + (double) f2, vec3d.x, vec3d.y, vec3d.z); + } + } + } ++ + } + } + +@@ -276,22 +272,23 @@ + } + + public float getBodyRollAngle(float partialTicks, float offset) { +- float f = (Mth.lerp(partialTicks, this.shakeAnimO, this.shakeAnim) + offset) / 1.8F; +- if (f < 0.0F) { +- f = 0.0F; +- } else if (f > 1.0F) { +- f = 1.0F; ++ float f2 = (Mth.lerp(partialTicks, this.shakeAnimO, this.shakeAnim) + offset) / 1.8F; ++ ++ if (f2 < 0.0F) { ++ f2 = 0.0F; ++ } else if (f2 > 1.0F) { ++ f2 = 1.0F; + } + +- return Mth.sin(f * (float) Math.PI) * Mth.sin(f * (float) Math.PI * 11.0F) * 0.15F * (float) Math.PI; ++ return Mth.sin(f2 * 3.1415927F) * Mth.sin(f2 * 3.1415927F * 11.0F) * 0.15F * 3.1415927F; + } + + public float getHeadRollAngle(float partialTicks) { +- return Mth.lerp(partialTicks, this.interestedAngleO, this.interestedAngle) * 0.15F * (float) Math.PI; ++ return Mth.lerp(partialTicks, this.interestedAngleO, this.interestedAngle) * 0.15F * 3.1415927F; + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return size.height * 0.8F; + } + +@@ -306,21 +303,27 @@ + return false; + } else { + Entity entity = source.getEntity(); +- if (!this.level().isClientSide) { +- this.setOrderedToSit(false); +- } + ++ // CraftBukkit - move diff down ++ + if (entity != null && !(entity instanceof Player) && !(entity instanceof AbstractArrow)) { + amount = (amount + 1.0F) / 2.0F; + } + +- return super.hurt(source, amount); ++ // CraftBukkit start ++ boolean result = super.hurt(source, amount); ++ if (!this.level().isClientSide && result) { ++ this.setOrderedToSit(false); ++ } ++ return result; ++ // CraftBukkit end + } + } + + @Override + public boolean doHurtTarget(Entity entity) { +- boolean flag = entity.hurt(this.damageSources().mobAttack(this), (float)((int)this.getAttributeValue(Attributes.ATTACK_DAMAGE))); ++ boolean flag = entity.hurt(this.damageSources().mobAttack(this), (float) ((int) this.getAttributeValue(Attributes.ATTACK_DAMAGE))); ++ + if (flag) { + this.doEnchantDamageEffects(this, entity); + } +@@ -332,69 +335,78 @@ + public void setTame(boolean tamed) { + super.setTame(tamed); + if (tamed) { +- this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(20.0); +- this.setHealth(20.0F); ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(20.0D); ++ this.setHealth(this.getMaxHealth()); // CraftBukkit - 20.0 -> getMaxHealth() + } else { +- this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(8.0); ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(8.0D); + } + +- this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(4.0); ++ this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(4.0D); + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- Item item = itemInHand.getItem(); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ Item item = itemstack.getItem(); ++ + if (this.level().isClientSide) { +- boolean flag = this.isOwnedBy(player) || this.isTame() || itemInHand.is(Items.BONE) && !this.isTame() && !this.isAngry(); ++ boolean flag = this.isOwnedBy(player) || this.isTame() || itemstack.is(Items.BONE) && !this.isTame() && !this.isAngry(); ++ + return flag ? InteractionResult.CONSUME : InteractionResult.PASS; + } else if (this.isTame()) { +- if (this.isFood(itemInHand) && this.getHealth() < this.getMaxHealth()) { ++ if (this.isFood(itemstack) && this.getHealth() < this.getMaxHealth()) { + if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + +- this.heal((float)item.getFoodProperties().getNutrition()); ++ this.heal((float) item.getFoodProperties().getNutrition(), EntityRegainHealthEvent.RegainReason.EATING); // CraftBukkit + return InteractionResult.SUCCESS; + } else { +- if (item instanceof DyeItem dyeItem && this.isOwnedBy(player)) { +- DyeColor dyeColor = dyeItem.getDyeColor(); +- if (dyeColor != this.getCollarColor()) { +- this.setCollarColor(dyeColor); +- if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ if (item instanceof DyeItem) { ++ DyeItem itemdye = (DyeItem) item; ++ ++ if (this.isOwnedBy(player)) { ++ DyeColor enumcolor = itemdye.getDyeColor(); ++ ++ if (enumcolor != this.getCollarColor()) { ++ this.setCollarColor(enumcolor); ++ if (!player.getAbilities().instabuild) { ++ itemstack.shrink(1); ++ } ++ ++ return InteractionResult.SUCCESS; + } + +- return InteractionResult.SUCCESS; ++ return super.mobInteract(player, hand); + } +- +- return super.mobInteract(player, hand); + } + +- InteractionResult interactionResult = super.mobInteract(player, hand); +- if ((!interactionResult.consumesAction() || this.isBaby()) && this.isOwnedBy(player)) { ++ InteractionResult enuminteractionresult = super.mobInteract(player, hand); ++ ++ if ((!enuminteractionresult.consumesAction() || this.isBaby()) && this.isOwnedBy(player)) { + this.setOrderedToSit(!this.isOrderedToSit()); + this.jumping = false; + this.navigation.stop(); +- this.setTarget(null); ++ this.setTarget((LivingEntity) null, EntityTargetEvent.TargetReason.FORGOT_TARGET, true); // CraftBukkit - reason + return InteractionResult.SUCCESS; + } else { +- return interactionResult; ++ return enuminteractionresult; + } + } +- } else if (itemInHand.is(Items.BONE) && !this.isAngry()) { ++ } else if (itemstack.is(Items.BONE) && !this.isAngry()) { + if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + +- if (this.random.nextInt(3) == 0) { ++ // CraftBukkit - added event call and isCancelled check. ++ if (this.random.nextInt(3) == 0 && !CraftEventFactory.callEntityTameEvent(this, player).isCancelled()) { + this.tame(player); + this.navigation.stop(); +- this.setTarget(null); ++ this.setTarget((LivingEntity) null); + this.setOrderedToSit(true); +- this.level().broadcastEntityEvent(this, (byte)7); ++ this.level().broadcastEntityEvent(this, (byte) 7); + } else { +- this.level().broadcastEntityEvent(this, (byte)6); ++ this.level().broadcastEntityEvent(this, (byte) 6); + } + + return InteractionResult.SUCCESS; +@@ -414,19 +426,17 @@ + } else { + super.handleEntityEvent(id); + } ++ + } + + public float getTailAngle() { +- if (this.isAngry()) { +- return 1.5393804F; +- } else { +- return this.isTame() ? (0.55F - (this.getMaxHealth() - this.getHealth()) * 0.02F) * (float) Math.PI : (float) (Math.PI / 5); +- } ++ return this.isAngry() ? 1.5393804F : (this.isTame() ? (0.55F - (this.getMaxHealth() - this.getHealth()) * 0.02F) * 3.1415927F : 0.62831855F); + } + + @Override + public boolean isFood(ItemStack stack) { + Item item = stack.getItem(); ++ + return item.isEdible() && item.getFoodProperties().isMeat(); + } + +@@ -437,17 +447,17 @@ + + @Override + public int getRemainingPersistentAngerTime() { +- return this.entityData.get(DATA_REMAINING_ANGER_TIME); ++ return (Integer) this.entityData.get(Wolf.DATA_REMAINING_ANGER_TIME); + } + + @Override + public void setRemainingPersistentAngerTime(int time) { +- this.entityData.set(DATA_REMAINING_ANGER_TIME, time); ++ this.entityData.set(Wolf.DATA_REMAINING_ANGER_TIME, time); + } + + @Override + public void startPersistentAngerTimer() { +- this.setRemainingPersistentAngerTime(PERSISTENT_ANGER_TIME.sample(this.random)); ++ this.setRemainingPersistentAngerTime(Wolf.PERSISTENT_ANGER_TIME.sample(this.random)); + } + + @Nullable +@@ -462,57 +472,65 @@ + } + + public DyeColor getCollarColor() { +- return DyeColor.byId(this.entityData.get(DATA_COLLAR_COLOR)); ++ return DyeColor.byId((Integer) this.entityData.get(Wolf.DATA_COLLAR_COLOR)); + } + + public void setCollarColor(DyeColor collarColor) { +- this.entityData.set(DATA_COLLAR_COLOR, collarColor.getId()); ++ this.entityData.set(Wolf.DATA_COLLAR_COLOR, collarColor.getId()); + } + + @Nullable + @Override + public Wolf getBreedOffspring(ServerLevel level, AgeableMob otherParent) { +- Wolf wolf = EntityType.WOLF.create(level); +- if (wolf != null) { +- UUID ownerUUID = this.getOwnerUUID(); +- if (ownerUUID != null) { +- wolf.setOwnerUUID(ownerUUID); +- wolf.setTame(true); ++ Wolf entitywolf = (Wolf) EntityType.WOLF.create(level); ++ ++ if (entitywolf != null) { ++ UUID uuid = this.getOwnerUUID(); ++ ++ if (uuid != null) { ++ entitywolf.setOwnerUUID(uuid); ++ entitywolf.setTame(true); + } + } + +- return wolf; ++ return entitywolf; + } + + public void setIsInterested(boolean isInterested) { +- this.entityData.set(DATA_INTERESTED_ID, isInterested); ++ this.entityData.set(Wolf.DATA_INTERESTED_ID, isInterested); + } + + @Override + public boolean canMate(Animal otherAnimal) { +- return otherAnimal != this +- && this.isTame() +- && otherAnimal instanceof Wolf wolf +- && wolf.isTame() +- && !wolf.isInSittingPose() +- && this.isInLove() +- && wolf.isInLove(); ++ if (otherAnimal == this) { ++ return false; ++ } else if (!this.isTame()) { ++ return false; ++ } else if (!(otherAnimal instanceof Wolf)) { ++ return false; ++ } else { ++ Wolf entitywolf = (Wolf) otherAnimal; ++ ++ return !entitywolf.isTame() ? false : (entitywolf.isInSittingPose() ? false : this.isInLove() && entitywolf.isInLove()); ++ } + } + + public boolean isInterested() { +- return this.entityData.get(DATA_INTERESTED_ID); ++ return (Boolean) this.entityData.get(Wolf.DATA_INTERESTED_ID); + } + + @Override + public boolean wantsToAttack(LivingEntity target, LivingEntity owner) { +- if (target instanceof Creeper || target instanceof Ghast) { +- return false; ++ if (!(target instanceof Creeper) && !(target instanceof Ghast)) { ++ if (target instanceof Wolf) { ++ Wolf entitywolf = (Wolf) target; ++ ++ return !entitywolf.isTame() || entitywolf.getOwner() != owner; ++ } else { ++ return target instanceof Player && owner instanceof Player && !((Player) owner).canHarmPlayer((Player) target) ? false : (target instanceof AbstractHorse && ((AbstractHorse) target).isTamed() ? false : !(target instanceof TamableAnimal) || !((TamableAnimal) target).isTame()); ++ } + } else { +- return target instanceof Wolf wolf +- ? !wolf.isTame() || wolf.getOwner() != owner +- : (!(target instanceof Player) || !(owner instanceof Player) || ((Player)owner).canHarmPlayer((Player)target)) +- && (!(target instanceof AbstractHorse) || !((AbstractHorse)target).isTamed()) +- && (!(target instanceof TamableAnimal) || !((TamableAnimal)target).isTame()); ++ return false; + } + } + +@@ -523,29 +541,42 @@ + + @Override + public Vec3 getLeashOffset() { +- return new Vec3(0.0, (double)(0.6F * this.getEyeHeight()), (double)(this.getBbWidth() * 0.4F)); ++ return new Vec3(0.0D, (double) (0.6F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height - 0.03125F * f, -0.0625F * f); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.03125F * f, -0.0625F * f); + } + +- public static boolean checkWolfSpawnRules(EntityType wolf, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) { ++ public static boolean checkWolfSpawnRules(EntityType wolf, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { + return level.getBlockState(pos.below()).is(BlockTags.WOLVES_SPAWNABLE_ON) && isBrightEnoughToSpawn(level, pos); + } + +- class WolfAvoidEntityGoal extends AvoidEntityGoal { ++ private class WolfPanicGoal extends PanicGoal { ++ ++ public WolfPanicGoal(double d0) { ++ super(Wolf.this, d0); ++ } ++ ++ @Override ++ protected boolean shouldPanic() { ++ return this.mob.isFreezing() || this.mob.isOnFire(); ++ } ++ } ++ ++ private class WolfAvoidEntityGoal extends AvoidEntityGoal { ++ + private final Wolf wolf; + +- public WolfAvoidEntityGoal(Wolf wolf, Class entityClassToAvoid, float maxDist, double walkSpeedModifier, double sprintSpeedModifier) { +- super(wolf, entityClassToAvoid, maxDist, walkSpeedModifier, sprintSpeedModifier); +- this.wolf = wolf; ++ public WolfAvoidEntityGoal(Wolf entitywolf, Class oclass, float f, double d0, double d1) { ++ super(entitywolf, oclass, f, d0, d1); ++ this.wolf = entitywolf; + } + + @Override + public boolean canUse() { +- return super.canUse() && this.toAvoid instanceof Llama && !this.wolf.isTame() && this.avoidLlama((Llama)this.toAvoid); ++ return super.canUse() && this.toAvoid instanceof Llama ? !this.wolf.isTame() && this.avoidLlama((Llama) this.toAvoid) : false; + } + + private boolean avoidLlama(Llama llama) { +@@ -554,25 +585,14 @@ + + @Override + public void start() { +- Wolf.this.setTarget(null); ++ Wolf.this.setTarget((LivingEntity) null); + super.start(); + } + + @Override + public void tick() { +- Wolf.this.setTarget(null); ++ Wolf.this.setTarget((LivingEntity) null); + super.tick(); + } + } +- +- class WolfPanicGoal extends PanicGoal { +- public WolfPanicGoal(double speedModifier) { +- super(Wolf.this, speedModifier); +- } +- +- @Override +- protected boolean shouldPanic() { +- return this.mob.isFreezing() || this.mob.isOnFire(); +- } +- } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/allay/Allay.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/allay/Allay.java.patch new file mode 100644 index 0000000000..f203d4eab8 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/allay/Allay.java.patch @@ -0,0 +1,721 @@ +--- a/net/minecraft/world/entity/animal/allay/Allay.java ++++ b/net/minecraft/world/entity/animal/allay/Allay.java +@@ -2,7 +2,10 @@ + + import com.google.common.collect.ImmutableList; + import com.mojang.logging.LogUtils; ++import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; ++import java.util.Iterator; ++import java.util.Objects; + import java.util.Optional; + import java.util.UUID; + import java.util.function.BiConsumer; +@@ -25,18 +28,18 @@ + import net.minecraft.tags.GameEventTags; + import net.minecraft.tags.TagKey; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.PathfinderMob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -58,7 +61,7 @@ + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.DynamicGameEventListener; + import net.minecraft.world.level.gameevent.EntityPositionSource; + import net.minecraft.world.level.gameevent.GameEvent; +@@ -69,6 +72,7 @@ + import org.slf4j.Logger; + + public class Allay extends PathfinderMob implements InventoryCarrier, VibrationSystem { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final Vec3i ITEM_PICKUP_REACH = new Vec3i(1, 1, 1); + private static final int LIFTING_ITEM_ANIMATION_DURATION = 5; +@@ -79,55 +83,43 @@ + private static final int NUM_OF_DUPLICATION_HEARTS = 3; + private static final EntityDataAccessor DATA_DANCING = SynchedEntityData.defineId(Allay.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_CAN_DUPLICATE = SynchedEntityData.defineId(Allay.class, EntityDataSerializers.BOOLEAN); +- protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of( +- SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.HURT_BY, SensorType.NEAREST_ITEMS +- ); +- protected static final ImmutableList> MEMORY_TYPES = ImmutableList.of( +- MemoryModuleType.PATH, +- MemoryModuleType.LOOK_TARGET, +- MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, +- MemoryModuleType.WALK_TARGET, +- MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, +- MemoryModuleType.HURT_BY, +- MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, +- MemoryModuleType.LIKED_PLAYER, +- MemoryModuleType.LIKED_NOTEBLOCK_POSITION, +- MemoryModuleType.LIKED_NOTEBLOCK_COOLDOWN_TICKS, +- MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS, +- MemoryModuleType.IS_PANICKING +- ); +- public static final ImmutableList THROW_SOUND_PITCHES = ImmutableList.of( +- 0.5625F, 0.625F, 0.75F, 0.9375F, 1.0F, 1.0F, 1.125F, 1.25F, 1.5F, 1.875F, 2.0F, 2.25F, 2.5F, 3.0F, 3.75F, 4.0F +- ); ++ protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.HURT_BY, SensorType.NEAREST_ITEMS); ++ protected static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.PATH, MemoryModuleType.LOOK_TARGET, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.HURT_BY, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.LIKED_PLAYER, MemoryModuleType.LIKED_NOTEBLOCK_POSITION, MemoryModuleType.LIKED_NOTEBLOCK_COOLDOWN_TICKS, MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS, MemoryModuleType.IS_PANICKING, new MemoryModuleType[0]); ++ public static final ImmutableList THROW_SOUND_PITCHES = ImmutableList.of(0.5625F, 0.625F, 0.75F, 0.9375F, 1.0F, 1.0F, 1.125F, 1.25F, 1.5F, 1.875F, 2.0F, 2.25F, new Float[]{2.5F, 3.0F, 3.75F, 4.0F}); + private final DynamicGameEventListener dynamicVibrationListener; + private VibrationSystem.Data vibrationData; + private final VibrationSystem.User vibrationUser; + private final DynamicGameEventListener dynamicJukeboxListener; + private final SimpleContainer inventory = new SimpleContainer(1); + @Nullable +- private BlockPos jukeboxPos; +- private long duplicationCooldown; ++ public BlockPos jukeboxPos; ++ public long duplicationCooldown; + private float holdingItemAnimationTicks; + private float holdingItemAnimationTicks0; + private float dancingAnimationTicks; + private float spinningAnimationTicks; + private float spinningAnimationTicks0; ++ public boolean forceDancing = false; // CraftBukkit + + public Allay(EntityType entityType, Level level) { + super(entityType, level); + this.moveControl = new FlyingMoveControl(this, 20, true); + this.setCanPickUpLoot(this.canPickUpLoot()); +- this.vibrationUser = new Allay.VibrationUser(); ++ this.vibrationUser = new Allay.b(); + this.vibrationData = new VibrationSystem.Data(); + this.dynamicVibrationListener = new DynamicGameEventListener<>(new VibrationSystem.Listener(this)); +- this.dynamicJukeboxListener = new DynamicGameEventListener<>( +- new Allay.JukeboxListener(this.vibrationUser.getPositionSource(), GameEvent.JUKEBOX_PLAY.getNotificationRadius()) +- ); ++ this.dynamicJukeboxListener = new DynamicGameEventListener<>(new Allay.JukeboxListener(this.vibrationUser.getPositionSource(), GameEvent.JUKEBOX_PLAY.getNotificationRadius())); + } + ++ // CraftBukkit start ++ public void setCanDuplicate(boolean canDuplicate) { ++ this.entityData.set(Allay.DATA_CAN_DUPLICATE, canDuplicate); ++ } ++ // CraftBukkit end ++ + @Override + protected Brain.Provider brainProvider() { +- return Brain.provider(MEMORY_TYPES, SENSOR_TYPES); ++ return Brain.provider(Allay.MEMORY_TYPES, Allay.SENSOR_TYPES); + } + + @Override +@@ -137,32 +129,28 @@ + + @Override + public Brain getBrain() { +- return (Brain)super.getBrain(); ++ return (Brain) super.getBrain(); // CraftBukkit - decompile error + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes() +- .add(Attributes.MAX_HEALTH, 20.0) +- .add(Attributes.FLYING_SPEED, 0.1F) +- .add(Attributes.MOVEMENT_SPEED, 0.1F) +- .add(Attributes.ATTACK_DAMAGE, 2.0) +- .add(Attributes.FOLLOW_RANGE, 48.0); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 20.0D).add(Attributes.FLYING_SPEED, 0.10000000149011612D).add(Attributes.MOVEMENT_SPEED, 0.10000000149011612D).add(Attributes.ATTACK_DAMAGE, 2.0D).add(Attributes.FOLLOW_RANGE, 48.0D); + } + + @Override + protected PathNavigation createNavigation(Level level) { +- FlyingPathNavigation flyingPathNavigation = new FlyingPathNavigation(this, level); +- flyingPathNavigation.setCanOpenDoors(false); +- flyingPathNavigation.setCanFloat(true); +- flyingPathNavigation.setCanPassDoors(true); +- return flyingPathNavigation; ++ FlyingPathNavigation navigationflying = new FlyingPathNavigation(this, level); ++ ++ navigationflying.setCanOpenDoors(false); ++ navigationflying.setCanFloat(true); ++ navigationflying.setCanPassDoors(true); ++ return navigationflying; + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_DANCING, false); +- this.entityData.define(DATA_CAN_DUPLICATE, true); ++ this.entityData.define(Allay.DATA_DANCING, false); ++ this.entityData.define(Allay.DATA_CAN_DUPLICATE, true); + } + + @Override +@@ -170,16 +158,16 @@ + if (this.isControlledByLocalInstance()) { + if (this.isInWater()) { + this.moveRelative(0.02F, travelVector); +- this.move(MoverType.SELF, this.getDeltaMovement()); +- this.setDeltaMovement(this.getDeltaMovement().scale(0.8F)); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); ++ this.setDeltaMovement(this.getDeltaMovement().scale(0.800000011920929D)); + } else if (this.isInLava()) { + this.moveRelative(0.02F, travelVector); +- this.move(MoverType.SELF, this.getDeltaMovement()); +- this.setDeltaMovement(this.getDeltaMovement().scale(0.5)); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); ++ this.setDeltaMovement(this.getDeltaMovement().scale(0.5D)); + } else { + this.moveRelative(this.getSpeed(), travelVector); +- this.move(MoverType.SELF, this.getDeltaMovement()); +- this.setDeltaMovement(this.getDeltaMovement().scale(0.91F)); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); ++ this.setDeltaMovement(this.getDeltaMovement().scale(0.9100000262260437D)); + } + } + +@@ -187,15 +175,19 @@ + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions dimensions) { + return dimensions.height * 0.6F; + } + + @Override + public boolean hurt(DamageSource source, float amount) { +- if (source.getEntity() instanceof Player player) { +- Optional memory = this.getBrain().getMemory(MemoryModuleType.LIKED_PLAYER); +- if (memory.isPresent() && player.getUUID().equals(memory.get())) { ++ Entity entity = source.getEntity(); ++ ++ if (entity instanceof Player) { ++ Player entityhuman = (Player) entity; ++ Optional optional = this.getBrain().getMemory(MemoryModuleType.LIKED_PLAYER); ++ ++ if (optional.isPresent() && entityhuman.getUUID().equals(optional.get())) { + return false; + } + } +@@ -204,12 +196,10 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState state) { +- } ++ protected void playStepSound(BlockPos pos, IBlockData state) {} + + @Override +- protected void checkFallDamage(double y, boolean onGround, BlockState state, BlockPos pos) { +- } ++ protected void checkFallDamage(double y, boolean flag, IBlockData onGround, BlockPos state) {} + + @Override + protected SoundEvent getAmbientSound() { +@@ -234,7 +224,7 @@ + @Override + protected void customServerAiStep() { + this.level().getProfiler().push("allayBrain"); +- this.getBrain().tick((ServerLevel)this.level(), this); ++ this.getBrain().tick((ServerLevel) this.level(), this); + this.level().getProfiler().pop(); + this.level().getProfiler().push("allayActivityUpdate"); + AllayAi.updateActivity(this); +@@ -246,7 +236,7 @@ + public void aiStep() { + super.aiStep(); + if (!this.level().isClientSide && this.isAlive() && this.tickCount % 10 == 0) { +- this.heal(1.0F); ++ this.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit + } + + if (this.isDancing() && this.shouldStopDancing() && this.tickCount % 20 == 0) { +@@ -269,12 +259,12 @@ + } + + if (this.isDancing()) { +- this.dancingAnimationTicks++; ++ ++this.dancingAnimationTicks; + this.spinningAnimationTicks0 = this.spinningAnimationTicks; + if (this.isSpinning()) { +- this.spinningAnimationTicks++; ++ ++this.spinningAnimationTicks; + } else { +- this.spinningAnimationTicks--; ++ --this.spinningAnimationTicks; + } + + this.spinningAnimationTicks = Mth.clamp(this.spinningAnimationTicks, 0.0F, 15.0F); +@@ -289,6 +279,7 @@ + this.setDancing(false); + } + } ++ + } + + @Override +@@ -297,11 +288,11 @@ + } + + public boolean hasItemInHand() { +- return !this.getItemInHand(InteractionHand.MAIN_HAND).isEmpty(); ++ return !this.getItemInHand(EnumHand.MAIN_HAND).isEmpty(); + } + + @Override +- public boolean canTakeItem(ItemStack itemstack) { ++ public boolean canTakeItem(ItemStack stack) { + return false; + } + +@@ -310,33 +301,43 @@ + } + + @Override +- protected InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- ItemStack itemInHand1 = this.getItemInHand(InteractionHand.MAIN_HAND); +- if (this.isDancing() && this.isDuplicationItem(itemInHand) && this.canDuplicate()) { +- this.duplicateAllay(); +- this.level().broadcastEntityEvent(this, (byte)18); +- this.level().playSound(player, this, SoundEvents.AMETHYST_BLOCK_CHIME, SoundSource.NEUTRAL, 2.0F, 1.0F); +- this.removeInteractionItem(player, itemInHand); ++ protected InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ItemStack itemstack1 = this.getItemInHand(EnumHand.MAIN_HAND); ++ ++ if (this.isDancing() && this.isDuplicationItem(itemstack) && this.canDuplicate()) { ++ // CraftBukkit start - handle cancel duplication ++ Allay allay = this.duplicateAllay(); ++ if (allay == null) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ this.level().broadcastEntityEvent(this, (byte) 18); ++ this.level().playSound(player, (Entity) this, SoundEvents.AMETHYST_BLOCK_CHIME, SoundSource.NEUTRAL, 2.0F, 1.0F); ++ this.removeInteractionItem(player, itemstack); + return InteractionResult.SUCCESS; +- } else if (itemInHand1.isEmpty() && !itemInHand.isEmpty()) { +- ItemStack itemStack = itemInHand.copyWithCount(1); +- this.setItemInHand(InteractionHand.MAIN_HAND, itemStack); +- this.removeInteractionItem(player, itemInHand); +- this.level().playSound(player, this, SoundEvents.ALLAY_ITEM_GIVEN, SoundSource.NEUTRAL, 2.0F, 1.0F); +- this.getBrain().setMemory(MemoryModuleType.LIKED_PLAYER, player.getUUID()); ++ } else if (itemstack1.isEmpty() && !itemstack.isEmpty()) { ++ ItemStack itemstack2 = itemstack.copyWithCount(1); ++ ++ this.setItemInHand(EnumHand.MAIN_HAND, itemstack2); ++ this.removeInteractionItem(player, itemstack); ++ this.level().playSound(player, (Entity) this, SoundEvents.ALLAY_ITEM_GIVEN, SoundSource.NEUTRAL, 2.0F, 1.0F); ++ this.getBrain().setMemory(MemoryModuleType.LIKED_PLAYER, player.getUUID()); // CraftBukkit - decompile error + return InteractionResult.SUCCESS; +- } else if (!itemInHand1.isEmpty() && hand == InteractionHand.MAIN_HAND && itemInHand.isEmpty()) { ++ } else if (!itemstack1.isEmpty() && hand == EnumHand.MAIN_HAND && itemstack.isEmpty()) { + this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); +- this.level().playSound(player, this, SoundEvents.ALLAY_ITEM_TAKEN, SoundSource.NEUTRAL, 2.0F, 1.0F); +- this.swing(InteractionHand.MAIN_HAND); ++ this.level().playSound(player, (Entity) this, SoundEvents.ALLAY_ITEM_TAKEN, SoundSource.NEUTRAL, 2.0F, 1.0F); ++ this.swing(EnumHand.MAIN_HAND); ++ Iterator iterator = this.getInventory().removeAllItems().iterator(); + +- for (ItemStack itemStack1 : this.getInventory().removeAllItems()) { +- BehaviorUtils.throwItem(this, itemStack1, this.position()); ++ while (iterator.hasNext()) { ++ ItemStack itemstack3 = (ItemStack) iterator.next(); ++ ++ BehaviorUtils.throwItem(this, itemstack3, this.position()); + } + + this.getBrain().eraseMemory(MemoryModuleType.LIKED_PLAYER); +- player.addItem(itemInHand1); ++ player.addItem(itemstack1); + return InteractionResult.SUCCESS; + } else { + return super.mobInteract(player, hand); +@@ -353,6 +354,7 @@ + this.jukeboxPos = null; + this.setDancing(false); + } ++ + } + + @Override +@@ -362,16 +364,14 @@ + + @Override + protected Vec3i getPickupReach() { +- return ITEM_PICKUP_REACH; ++ return Allay.ITEM_PICKUP_REACH; + } + + @Override + public boolean wantsToPickUp(ItemStack stack) { +- ItemStack itemInHand = this.getItemInHand(InteractionHand.MAIN_HAND); +- return !itemInHand.isEmpty() +- && this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) +- && this.inventory.canAddItem(stack) +- && this.allayConsidersItemEqual(itemInHand, stack); ++ ItemStack itemstack1 = this.getItemInHand(EnumHand.MAIN_HAND); ++ ++ return !itemstack1.isEmpty() && this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && this.inventory.canAddItem(stack) && this.allayConsidersItemEqual(itemstack1, stack); + } + + private boolean allayConsidersItemEqual(ItemStack first, ItemStack second) { +@@ -379,19 +379,22 @@ + } + + private boolean hasNonMatchingPotion(ItemStack first, ItemStack second) { +- CompoundTag tag = first.getTag(); +- boolean flag = tag != null && tag.contains("Potion"); ++ CompoundTag nbttagcompound = first.getTag(); ++ boolean flag = nbttagcompound != null && nbttagcompound.contains("Potion"); ++ + if (!flag) { + return false; + } else { +- CompoundTag tag1 = second.getTag(); +- boolean flag1 = tag1 != null && tag1.contains("Potion"); ++ CompoundTag nbttagcompound1 = second.getTag(); ++ boolean flag1 = nbttagcompound1 != null && nbttagcompound1.contains("Potion"); ++ + if (!flag1) { + return true; + } else { +- Tag tag2 = tag.get("Potion"); +- Tag tag3 = tag1.get("Potion"); +- return tag2 != null && tag3 != null && !tag2.equals(tag3); ++ Tag nbtbase = nbttagcompound.get("Potion"); ++ Tag nbtbase1 = nbttagcompound1.get("Potion"); ++ ++ return nbtbase != null && nbtbase1 != null && !nbtbase.equals(nbtbase1); + } + } + } +@@ -414,26 +417,30 @@ + + @Override + public void updateDynamicGameEventListener(BiConsumer, ServerLevel> listenerConsumer) { +- if (this.level() instanceof ServerLevel serverLevel) { +- listenerConsumer.accept(this.dynamicVibrationListener, serverLevel); +- listenerConsumer.accept(this.dynamicJukeboxListener, serverLevel); ++ Level world = this.level(); ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ ++ listenerConsumer.accept(this.dynamicVibrationListener, worldserver); ++ listenerConsumer.accept(this.dynamicJukeboxListener, worldserver); + } ++ + } + + public boolean isDancing() { +- return this.entityData.get(DATA_DANCING); ++ return (Boolean) this.entityData.get(Allay.DATA_DANCING); + } + + public void setDancing(boolean dancing) { + if (!this.level().isClientSide && this.isEffectiveAi() && (!dancing || !this.isPanicking())) { +- this.entityData.set(DATA_DANCING, dancing); ++ this.entityData.set(Allay.DATA_DANCING, dancing); + } + } + + private boolean shouldStopDancing() { +- return this.jukeboxPos == null +- || !this.jukeboxPos.closerToCenterThan(this.position(), (double)GameEvent.JUKEBOX_PLAY.getNotificationRadius()) +- || !this.level().getBlockState(this.jukeboxPos).is(Blocks.JUKEBOX); ++ if (this.forceDancing) {return false;} // CraftBukkit ++ return this.jukeboxPos == null || !this.jukeboxPos.closerToCenterThan(this.position(), (double) GameEvent.JUKEBOX_PLAY.getNotificationRadius()) || !this.level().getBlockState(this.jukeboxPos).is(Blocks.JUKEBOX); + } + + public float getHoldingItemAnimationProgress(float partialTick) { +@@ -442,6 +449,7 @@ + + public boolean isSpinning() { + float f = this.dancingAnimationTicks % 55.0F; ++ + return f < 15.0F; + } + +@@ -458,11 +466,13 @@ + protected void dropEquipment() { + super.dropEquipment(); + this.inventory.removeAllItems().forEach(this::spawnAtLocation); +- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.MAINHAND); +- if (!itemBySlot.isEmpty() && !EnchantmentHelper.hasVanishingCurse(itemBySlot)) { +- this.spawnAtLocation(itemBySlot); ++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND); ++ ++ if (!itemstack.isEmpty() && !EnchantmentHelper.hasVanishingCurse(itemstack)) { ++ this.spawnAtLocation(itemstack); + this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); + } ++ + } + + @Override +@@ -474,10 +484,13 @@ + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); + this.writeInventoryToTag(compound); +- VibrationSystem.Data.CODEC +- .encodeStart(NbtOps.INSTANCE, this.vibrationData) +- .resultOrPartial(LOGGER::error) +- .ifPresent(tag -> compound.put("listener", tag)); ++ DataResult dataresult = VibrationSystem.Data.CODEC.encodeStart(NbtOps.INSTANCE, this.vibrationData); // CraftBukkit - decompile error ++ Logger logger = Allay.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("listener", nbtbase); ++ }); + compound.putLong("DuplicationCooldown", this.duplicationCooldown); + compound.putBoolean("CanDuplicate", this.canDuplicate()); + } +@@ -487,14 +500,17 @@ + super.readAdditionalSaveData(compound); + this.readInventoryFromTag(compound); + if (compound.contains("listener", 10)) { +- VibrationSystem.Data.CODEC +- .parse(new Dynamic<>(NbtOps.INSTANCE, compound.getCompound("listener"))) +- .resultOrPartial(LOGGER::error) +- .ifPresent(vibrationData -> this.vibrationData = vibrationData); ++ DataResult dataresult = VibrationSystem.Data.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compound.getCompound("listener"))); // CraftBukkit - decompile error ++ Logger logger = Allay.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((vibrationsystem_a) -> { ++ this.vibrationData = vibrationsystem_a; ++ }); + } + +- this.duplicationCooldown = (long)compound.getInt("DuplicationCooldown"); +- this.entityData.set(DATA_CAN_DUPLICATE, compound.getBoolean("CanDuplicate")); ++ this.duplicationCooldown = (long) compound.getInt("DuplicationCooldown"); ++ this.entityData.set(Allay.DATA_CAN_DUPLICATE, compound.getBoolean("CanDuplicate")); + } + + @Override +@@ -504,47 +520,51 @@ + + private void updateDuplicationCooldown() { + if (this.duplicationCooldown > 0L) { +- this.duplicationCooldown--; ++ --this.duplicationCooldown; + } + + if (!this.level().isClientSide() && this.duplicationCooldown == 0L && !this.canDuplicate()) { +- this.entityData.set(DATA_CAN_DUPLICATE, true); ++ this.entityData.set(Allay.DATA_CAN_DUPLICATE, true); + } ++ + } + + private boolean isDuplicationItem(ItemStack stack) { +- return DUPLICATION_ITEM.test(stack); ++ return Allay.DUPLICATION_ITEM.test(stack); + } + +- private void duplicateAllay() { +- Allay allay = EntityType.ALLAY.create(this.level()); ++ public Allay duplicateAllay() { // CraftBukkit - return allay ++ Allay allay = (Allay) EntityType.ALLAY.create(this.level()); ++ + if (allay != null) { + allay.moveTo(this.position()); + allay.setPersistenceRequired(); + allay.resetDuplicationCooldown(); + this.resetDuplicationCooldown(); +- this.level().addFreshEntity(allay); ++ this.level().addFreshEntity(allay, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DUPLICATION); // CraftBukkit - reason for duplicated allay + } ++ return allay; // CraftBukkit + } + +- private void resetDuplicationCooldown() { ++ public void resetDuplicationCooldown() { + this.duplicationCooldown = 6000L; +- this.entityData.set(DATA_CAN_DUPLICATE, false); ++ this.entityData.set(Allay.DATA_CAN_DUPLICATE, false); + } + +- private boolean canDuplicate() { +- return this.entityData.get(DATA_CAN_DUPLICATE); ++ public boolean canDuplicate() { ++ return (Boolean) this.entityData.get(Allay.DATA_CAN_DUPLICATE); + } + + private void removeInteractionItem(Player player, ItemStack stack) { + if (!player.getAbilities().instabuild) { + stack.shrink(1); + } ++ + } + + @Override + public Vec3 getLeashOffset() { +- return new Vec3(0.0, (double)this.getEyeHeight() * 0.6, (double)this.getBbWidth() * 0.1); ++ return new Vec3(0.0D, (double) this.getEyeHeight() * 0.6D, (double) this.getBbWidth() * 0.1D); + } + + @Override +@@ -555,19 +575,21 @@ + @Override + public void handleEntityEvent(byte id) { + if (id == 18) { +- for (int i = 0; i < 3; i++) { ++ for (int i = 0; i < 3; ++i) { + this.spawnHeartParticle(); + } + } else { + super.handleEntityEvent(id); + } ++ + } + + private void spawnHeartParticle() { +- double d = this.random.nextGaussian() * 0.02; +- double d1 = this.random.nextGaussian() * 0.02; +- double d2 = this.random.nextGaussian() * 0.02; +- this.level().addParticle(ParticleTypes.HEART, this.getRandomX(1.0), this.getRandomY() + 0.5, this.getRandomZ(1.0), d, d1, d2); ++ double d0 = this.random.nextGaussian() * 0.02D; ++ double d1 = this.random.nextGaussian() * 0.02D; ++ double d2 = this.random.nextGaussian() * 0.02D; ++ ++ this.level().addParticle(ParticleTypes.HEART, this.getRandomX(1.0D), this.getRandomY() + 0.5D, this.getRandomZ(1.0D), d0, d1, d2); + } + + @Override +@@ -580,43 +602,13 @@ + return this.vibrationUser; + } + +- class JukeboxListener implements GameEventListener { +- private final PositionSource listenerSource; +- private final int listenerRadius; ++ private class b implements VibrationSystem.User { + +- public JukeboxListener(PositionSource listenerSource, int listenerRadius) { +- this.listenerSource = listenerSource; +- this.listenerRadius = listenerRadius; +- } +- +- @Override +- public PositionSource getListenerSource() { +- return this.listenerSource; +- } +- +- @Override +- public int getListenerRadius() { +- return this.listenerRadius; +- } +- +- @Override +- public boolean handleGameEvent(ServerLevel level, GameEvent gameEvent, GameEvent.Context context, Vec3 pos) { +- if (gameEvent == GameEvent.JUKEBOX_PLAY) { +- Allay.this.setJukeboxPlaying(BlockPos.containing(pos), true); +- return true; +- } else if (gameEvent == GameEvent.JUKEBOX_STOP_PLAY) { +- Allay.this.setJukeboxPlaying(BlockPos.containing(pos), false); +- return true; +- } else { +- return false; +- } +- } +- } +- +- class VibrationUser implements VibrationSystem.User { + private static final int VIBRATION_EVENT_LISTENER_RANGE = 16; + private final PositionSource positionSource = new EntityPositionSource(Allay.this, Allay.this.getEyeHeight()); + ++ b() {} ++ + @Override + public int getListenerRadius() { + return 16; +@@ -632,23 +624,24 @@ + if (Allay.this.isNoAi()) { + return false; + } else { +- Optional memory = Allay.this.getBrain().getMemory(MemoryModuleType.LIKED_NOTEBLOCK_POSITION); +- if (memory.isEmpty()) { ++ Optional optional = Allay.this.getBrain().getMemory(MemoryModuleType.LIKED_NOTEBLOCK_POSITION); ++ ++ if (optional.isEmpty()) { + return true; + } else { +- GlobalPos globalPos = memory.get(); +- return globalPos.dimension().equals(level.dimension()) && globalPos.pos().equals(pos); ++ GlobalPos globalpos = (GlobalPos) optional.get(); ++ ++ return globalpos.dimension().equals(level.dimension()) && globalpos.pos().equals(pos); + } + } + } + + @Override +- public void onReceiveVibration( +- ServerLevel level, BlockPos pos, GameEvent gameEvent, @Nullable Entity entity, @Nullable Entity playerEntity, float distance +- ) { ++ public void onReceiveVibration(ServerLevel level, BlockPos pos, GameEvent gameEvent, @Nullable Entity entity, @Nullable Entity playerEntity, float distance) { + if (gameEvent == GameEvent.NOTE_BLOCK_PLAY) { + AllayAi.hearNoteblock(Allay.this, new BlockPos(pos)); + } ++ + } + + @Override +@@ -656,4 +649,38 @@ + return GameEventTags.ALLAY_CAN_LISTEN; + } + } ++ ++ private class JukeboxListener implements GameEventListener { ++ ++ private final PositionSource listenerSource; ++ private final int listenerRadius; ++ ++ public JukeboxListener(PositionSource positionsource, int i) { ++ this.listenerSource = positionsource; ++ this.listenerRadius = i; ++ } ++ ++ @Override ++ public PositionSource getListenerSource() { ++ return this.listenerSource; ++ } ++ ++ @Override ++ public int getListenerRadius() { ++ return this.listenerRadius; ++ } ++ ++ @Override ++ public boolean handleGameEvent(ServerLevel level, GameEvent gameEvent, GameEvent.Context context, Vec3 pos) { ++ if (gameEvent == GameEvent.JUKEBOX_PLAY) { ++ Allay.this.setJukeboxPlaying(BlockPos.containing(pos), true); ++ return true; ++ } else if (gameEvent == GameEvent.JUKEBOX_STOP_PLAY) { ++ Allay.this.setJukeboxPlaying(BlockPos.containing(pos), false); ++ return true; ++ } else { ++ return false; ++ } ++ } ++ } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/axolotl/Axolotl.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/axolotl/Axolotl.java.patch new file mode 100644 index 0000000000..37433a3dce --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/axolotl/Axolotl.java.patch @@ -0,0 +1,568 @@ +--- a/net/minecraft/world/entity/animal/axolotl/Axolotl.java ++++ b/net/minecraft/world/entity/animal/axolotl/Axolotl.java +@@ -26,7 +26,7 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.util.StringRepresentable; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffectInstance; +@@ -34,15 +34,15 @@ + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; ++import net.minecraft.world.entity.EnumMoveType; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LerpingModel; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.VariantHolder; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -67,36 +67,21 @@ + import org.joml.Vector3f; + + public class Axolotl extends Animal implements LerpingModel, VariantHolder, Bucketable { ++ ++ // CraftBukkit start - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ @Override ++ public int getDefaultMaxAirSupply() { ++ return AXOLOTL_TOTAL_AIR_SUPPLY; ++ } ++ // CraftBukkit end + public static final int TOTAL_PLAYDEAD_TIME = 200; +- protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of( +- SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_ADULT, SensorType.HURT_BY, SensorType.AXOLOTL_ATTACKABLES, SensorType.AXOLOTL_TEMPTATIONS +- ); +- protected static final ImmutableList> MEMORY_TYPES = ImmutableList.of( +- MemoryModuleType.BREED_TARGET, +- MemoryModuleType.NEAREST_LIVING_ENTITIES, +- MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, +- MemoryModuleType.NEAREST_VISIBLE_PLAYER, +- MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, +- MemoryModuleType.LOOK_TARGET, +- MemoryModuleType.WALK_TARGET, +- MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, +- MemoryModuleType.PATH, +- MemoryModuleType.ATTACK_TARGET, +- MemoryModuleType.ATTACK_COOLING_DOWN, +- MemoryModuleType.NEAREST_VISIBLE_ADULT, +- MemoryModuleType.HURT_BY_ENTITY, +- MemoryModuleType.PLAY_DEAD_TICKS, +- MemoryModuleType.NEAREST_ATTACKABLE, +- MemoryModuleType.TEMPTING_PLAYER, +- MemoryModuleType.TEMPTATION_COOLDOWN_TICKS, +- MemoryModuleType.IS_TEMPTED, +- MemoryModuleType.HAS_HUNTING_COOLDOWN, +- MemoryModuleType.IS_PANICKING +- ); ++ protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_ADULT, SensorType.HURT_BY, SensorType.AXOLOTL_ATTACKABLES, SensorType.AXOLOTL_TEMPTATIONS); ++ // CraftBukkit - decompile error ++ protected static final ImmutableList> MEMORY_TYPES = ImmutableList.>of(MemoryModuleType.BREED_TARGET, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.LOOK_TARGET, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.PATH, MemoryModuleType.ATTACK_TARGET, MemoryModuleType.ATTACK_COOLING_DOWN, MemoryModuleType.NEAREST_VISIBLE_ADULT, new MemoryModuleType[]{MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.PLAY_DEAD_TICKS, MemoryModuleType.NEAREST_ATTACKABLE, MemoryModuleType.TEMPTING_PLAYER, MemoryModuleType.TEMPTATION_COOLDOWN_TICKS, MemoryModuleType.IS_TEMPTED, MemoryModuleType.HAS_HUNTING_COOLDOWN, MemoryModuleType.IS_PANICKING}); + private static final EntityDataAccessor DATA_VARIANT = SynchedEntityData.defineId(Axolotl.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_PLAYING_DEAD = SynchedEntityData.defineId(Axolotl.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor FROM_BUCKET = SynchedEntityData.defineId(Axolotl.class, EntityDataSerializers.BOOLEAN); +- public static final double PLAYER_REGEN_DETECTION_RANGE = 20.0; ++ public static final double PLAYER_REGEN_DETECTION_RANGE = 20.0D; + public static final int RARE_VARIANT_CHANCE = 1200; + private static final int AXOLOTL_TOTAL_AIR_SUPPLY = 6000; + public static final String VARIANT_TAG = "Variant"; +@@ -126,9 +111,9 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_VARIANT, 0); +- this.entityData.define(DATA_PLAYING_DEAD, false); +- this.entityData.define(FROM_BUCKET, false); ++ this.entityData.define(Axolotl.DATA_VARIANT, 0); ++ this.entityData.define(Axolotl.DATA_PLAYING_DEAD, false); ++ this.entityData.define(Axolotl.FROM_BUCKET, false); + } + + @Override +@@ -153,38 +138,40 @@ + } + + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + boolean flag = false; +- if (reason == MobSpawnType.BUCKET) { +- return spawnData; ++ ++ if (reason == EnumMobSpawn.BUCKET) { ++ return (GroupDataEntity) spawnData; + } else { +- RandomSource random = level.getRandom(); ++ RandomSource randomsource = level.getRandom(); ++ + if (spawnData instanceof Axolotl.AxolotlGroupData) { +- if (((Axolotl.AxolotlGroupData)spawnData).getGroupSize() >= 2) { ++ if (((Axolotl.AxolotlGroupData) spawnData).getGroupSize() >= 2) { + flag = true; + } + } else { +- spawnData = new Axolotl.AxolotlGroupData(Axolotl.Variant.getCommonSpawnVariant(random), Axolotl.Variant.getCommonSpawnVariant(random)); ++ spawnData = new Axolotl.AxolotlGroupData(new Axolotl.Variant[]{Axolotl.Variant.getCommonSpawnVariant(randomsource), Axolotl.Variant.getCommonSpawnVariant(randomsource)}); + } + +- this.setVariant(((Axolotl.AxolotlGroupData)spawnData).getVariant(random)); ++ this.setVariant(((Axolotl.AxolotlGroupData) spawnData).getVariant(randomsource)); + if (flag) { + this.setAge(-24000); + } + +- return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + } + + @Override + public void baseTick() { +- int airSupply = this.getAirSupply(); ++ int i = this.getAirSupply(); ++ + super.baseTick(); + if (!this.isNoAi()) { +- this.handleAirSupply(airSupply); ++ this.handleAirSupply(i); + } ++ + } + + protected void handleAirSupply(int airSupply) { +@@ -197,26 +184,27 @@ + } else { + this.setAirSupply(this.getMaxAirSupply()); + } ++ + } + + public void rehydrate() { + int i = this.getAirSupply() + 1800; ++ + this.setAirSupply(Math.min(i, this.getMaxAirSupply())); + } + + @Override + public int getMaxAirSupply() { +- return 6000; ++ return maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() + } + + @Override + public Axolotl.Variant getVariant() { +- return Axolotl.Variant.byId(this.entityData.get(DATA_VARIANT)); ++ return Axolotl.Variant.byId((Integer) this.entityData.get(Axolotl.DATA_VARIANT)); + } + +- @Override +- public void setVariant(Axolotl.Variant variant) { +- this.entityData.set(DATA_VARIANT, variant.getId()); ++ public void setVariant(Axolotl.Variant axolotl_variant) { ++ this.entityData.set(Axolotl.DATA_VARIANT, axolotl_variant.getId()); + } + + private static boolean useRareVariant(RandomSource random) { +@@ -234,41 +222,43 @@ + } + + @Override +- public MobType getMobType() { +- return MobType.WATER; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.WATER; + } + + public void setPlayingDead(boolean playingDead) { +- this.entityData.set(DATA_PLAYING_DEAD, playingDead); ++ this.entityData.set(Axolotl.DATA_PLAYING_DEAD, playingDead); + } + + public boolean isPlayingDead() { +- return this.entityData.get(DATA_PLAYING_DEAD); ++ return (Boolean) this.entityData.get(Axolotl.DATA_PLAYING_DEAD); + } + + @Override + public boolean fromBucket() { +- return this.entityData.get(FROM_BUCKET); ++ return (Boolean) this.entityData.get(Axolotl.FROM_BUCKET); + } + + @Override + public void setFromBucket(boolean fromBucket) { +- this.entityData.set(FROM_BUCKET, fromBucket); ++ this.entityData.set(Axolotl.FROM_BUCKET, fromBucket); + } + + @Nullable + @Override + public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob otherParent) { +- Axolotl axolotl = EntityType.AXOLOTL.create(level); ++ Axolotl axolotl = (Axolotl) EntityType.AXOLOTL.create(level); ++ + if (axolotl != null) { +- Axolotl.Variant rareSpawnVariant; ++ Axolotl.Variant axolotl_variant; ++ + if (useRareVariant(this.random)) { +- rareSpawnVariant = Axolotl.Variant.getRareSpawnVariant(this.random); ++ axolotl_variant = Axolotl.Variant.getRareSpawnVariant(this.random); + } else { +- rareSpawnVariant = this.random.nextBoolean() ? this.getVariant() : ((Axolotl)otherParent).getVariant(); ++ axolotl_variant = this.random.nextBoolean() ? this.getVariant() : ((Axolotl) otherParent).getVariant(); + } + +- axolotl.setVariant(rareSpawnVariant); ++ axolotl.setVariant(axolotl_variant); + axolotl.setPersistenceRequired(); + } + +@@ -288,19 +278,21 @@ + @Override + protected void customServerAiStep() { + this.level().getProfiler().push("axolotlBrain"); +- this.getBrain().tick((ServerLevel)this.level(), this); ++ this.getBrain().tick((ServerLevel) this.level(), this); + this.level().getProfiler().pop(); + this.level().getProfiler().push("axolotlActivityUpdate"); + AxolotlAi.updateActivity(this); + this.level().getProfiler().pop(); + if (!this.isNoAi()) { +- Optional memory = this.getBrain().getMemory(MemoryModuleType.PLAY_DEAD_TICKS); +- this.setPlayingDead(memory.isPresent() && memory.get() > 0); ++ Optional optional = this.getBrain().getMemory(MemoryModuleType.PLAY_DEAD_TICKS); ++ ++ this.setPlayingDead(optional.isPresent() && (Integer) optional.get() > 0); + } ++ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 14.0).add(Attributes.MOVEMENT_SPEED, 1.0).add(Attributes.ATTACK_DAMAGE, 2.0); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 14.0D).add(Attributes.MOVEMENT_SPEED, 1.0D).add(Attributes.ATTACK_DAMAGE, 2.0D); + } + + @Override +@@ -309,10 +301,11 @@ + } + + @Override +- public boolean doHurtTarget(Entity entity) { +- boolean flag = entity.hurt(this.damageSources().mobAttack(this), (float)((int)this.getAttributeValue(Attributes.ATTACK_DAMAGE))); ++ public boolean doHurtTarget(Entity target) { ++ boolean flag = target.hurt(this.damageSources().mobAttack(this), (float) ((int) this.getAttributeValue(Attributes.ATTACK_DAMAGE))); ++ + if (flag) { +- this.doEnchantDamageEffects(this, entity); ++ this.doEnchantDamageEffects(this, target); + this.playSound(SoundEvents.AXOLOTL_ATTACK, 1.0F, 1.0F); + } + +@@ -321,23 +314,17 @@ + + @Override + public boolean hurt(DamageSource source, float amount) { +- float health = this.getHealth(); +- if (!this.level().isClientSide +- && !this.isNoAi() +- && this.level().random.nextInt(3) == 0 +- && ((float)this.level().random.nextInt(3) < amount || health / this.getMaxHealth() < 0.5F) +- && amount < health +- && this.isInWater() +- && (source.getEntity() != null || source.getDirectEntity() != null) +- && !this.isPlayingDead()) { +- this.brain.setMemory(MemoryModuleType.PLAY_DEAD_TICKS, 200); ++ float f1 = this.getHealth(); ++ ++ if (!this.level().isClientSide && !this.isNoAi() && this.level().random.nextInt(3) == 0 && ((float) this.level().random.nextInt(3) < amount || f1 / this.getMaxHealth() < 0.5F) && amount < f1 && this.isInWater() && (source.getEntity() != null || source.getDirectEntity() != null) && !this.isPlayingDead()) { ++ this.brain.setMemory(MemoryModuleType.PLAY_DEAD_TICKS, (int) 200); + } + + return super.hurt(source, amount); + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions dimensions) { + return dimensions.height * 0.655F; + } + +@@ -352,20 +339,23 @@ + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- return Bucketable.bucketMobPickup(player, hand, this).orElse(super.mobInteract(player, hand)); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ return (InteractionResult) Bucketable.bucketMobPickup(player, hand, this).orElse(super.mobInteract(player, hand)); + } + + @Override + public void saveToBucketTag(ItemStack stack) { + Bucketable.saveDefaultDataToBucketTag(this, stack); +- CompoundTag tag = stack.getOrCreateTag(); +- tag.putInt("Variant", this.getVariant().getId()); +- tag.putInt("Age", this.getAge()); +- Brain brain = this.getBrain(); +- if (brain.hasMemoryValue(MemoryModuleType.HAS_HUNTING_COOLDOWN)) { +- tag.putLong("HuntingCooldown", brain.getTimeUntilExpiry(MemoryModuleType.HAS_HUNTING_COOLDOWN)); ++ CompoundTag nbttagcompound = stack.getOrCreateTag(); ++ ++ nbttagcompound.putInt("Variant", this.getVariant().getId()); ++ nbttagcompound.putInt("Age", this.getAge()); ++ Brain behaviorcontroller = this.getBrain(); ++ ++ if (behaviorcontroller.hasMemoryValue(MemoryModuleType.HAS_HUNTING_COOLDOWN)) { ++ nbttagcompound.putLong("HuntingCooldown", behaviorcontroller.getTimeUntilExpiry(MemoryModuleType.HAS_HUNTING_COOLDOWN)); + } ++ + } + + @Override +@@ -379,6 +369,7 @@ + if (tag.contains("HuntingCooldown")) { + this.getBrain().setMemoryWithExpiry(MemoryModuleType.HAS_HUNTING_COOLDOWN, true, tag.getLong("HuntingCooldown")); + } ++ + } + + @Override +@@ -397,28 +388,35 @@ + } + + public static void onStopAttacking(Axolotl axolotl, LivingEntity target) { +- Level level = axolotl.level(); ++ Level world = axolotl.level(); ++ + if (target.isDeadOrDying()) { +- DamageSource lastDamageSource = target.getLastDamageSource(); +- if (lastDamageSource != null) { +- Entity entity = lastDamageSource.getEntity(); ++ DamageSource damagesource = target.getLastDamageSource(); ++ ++ if (damagesource != null) { ++ Entity entity = damagesource.getEntity(); ++ + if (entity != null && entity.getType() == EntityType.PLAYER) { +- Player player = (Player)entity; +- List entitiesOfClass = level.getEntitiesOfClass(Player.class, axolotl.getBoundingBox().inflate(20.0)); +- if (entitiesOfClass.contains(player)) { +- axolotl.applySupportingEffects(player); ++ Player entityhuman = (Player) entity; ++ List list = world.getEntitiesOfClass(Player.class, axolotl.getBoundingBox().inflate(20.0D)); ++ ++ if (list.contains(entityhuman)) { ++ axolotl.applySupportingEffects(entityhuman); + } + } + } + } ++ + } + + public void applySupportingEffects(Player player) { +- MobEffectInstance effect = player.getEffect(MobEffects.REGENERATION); +- if (effect == null || effect.endsWithin(2399)) { +- int i = effect != null ? effect.getDuration() : 0; +- int min = Math.min(2400, 100 + i); +- player.addEffect(new MobEffectInstance(MobEffects.REGENERATION, min, 0), this); ++ MobEffectInstance mobeffect = player.getEffect(MobEffects.REGENERATION); ++ ++ if (mobeffect == null || mobeffect.endsWithin(2399)) { ++ int i = mobeffect != null ? mobeffect.getDuration() : 0; ++ int j = Math.min(2400, 100 + i); ++ ++ player.addEffect(new MobEffectInstance(MobEffects.REGENERATION, j, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AXOLOTL); // CraftBukkit + } + + player.removeEffect(MobEffects.DIG_SLOWDOWN); +@@ -458,7 +456,7 @@ + + @Override + protected Brain.Provider brainProvider() { +- return Brain.provider(MEMORY_TYPES, SENSOR_TYPES); ++ return Brain.provider(Axolotl.MEMORY_TYPES, Axolotl.SENSOR_TYPES); + } + + @Override +@@ -468,7 +466,7 @@ + + @Override + public Brain getBrain() { +- return (Brain)super.getBrain(); ++ return (Brain) super.getBrain(); // CraftBukkit - decompile error + } + + @Override +@@ -481,20 +479,22 @@ + public void travel(Vec3 travelVector) { + if (this.isControlledByLocalInstance() && this.isInWater()) { + this.moveRelative(this.getSpeed(), travelVector); +- this.move(MoverType.SELF, this.getDeltaMovement()); +- this.setDeltaMovement(this.getDeltaMovement().scale(0.9)); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); ++ this.setDeltaMovement(this.getDeltaMovement().scale(0.9D)); + } else { + super.travel(travelVector); + } ++ + } + + @Override +- protected void usePlayerItem(Player player, InteractionHand hand, ItemStack stack) { ++ protected void usePlayerItem(Player player, EnumHand hand, ItemStack stack) { + if (stack.is(Items.TROPICAL_FISH_BUCKET)) { + player.setItemInHand(hand, new ItemStack(Items.WATER_BUCKET)); + } else { + super.usePlayerItem(player, hand, stack); + } ++ + } + + @Override +@@ -502,71 +502,57 @@ + return !this.fromBucket() && !this.hasCustomName(); + } + +- public static boolean checkAxolotlSpawnRules( +- EntityType axolotl, ServerLevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random +- ) { ++ public static boolean checkAxolotlSpawnRules(EntityType axolotl, ServerLevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { + return level.getBlockState(pos.below()).is(BlockTags.AXOLOTLS_SPAWNABLE_ON); + } + +- public static class AxolotlGroupData extends AgeableMob.AgeableMobGroupData { +- public final Axolotl.Variant[] types; ++ private static class AxolotlMoveControl extends SmoothSwimmingMoveControl { + +- public AxolotlGroupData(Axolotl.Variant... types) { +- super(false); +- this.types = types; +- } ++ private final Axolotl axolotl; + +- public Axolotl.Variant getVariant(RandomSource random) { +- return this.types[random.nextInt(this.types.length)]; ++ public AxolotlMoveControl(Axolotl axolotl) { ++ super(axolotl, 85, 10, 0.1F, 0.5F, false); ++ this.axolotl = axolotl; + } +- } + +- class AxolotlLookControl extends SmoothSwimmingLookControl { +- public AxolotlLookControl(Axolotl mob, int maxYRotFromCenter) { +- super(mob, maxYRotFromCenter); +- } +- + @Override + public void tick() { +- if (!Axolotl.this.isPlayingDead()) { ++ if (!this.axolotl.isPlayingDead()) { + super.tick(); + } ++ + } + } + +- static class AxolotlMoveControl extends SmoothSwimmingMoveControl { +- private final Axolotl axolotl; ++ private class AxolotlLookControl extends SmoothSwimmingLookControl { + +- public AxolotlMoveControl(Axolotl axolotl) { +- super(axolotl, 85, 10, 0.1F, 0.5F, false); +- this.axolotl = axolotl; ++ public AxolotlLookControl(Axolotl axolotl, int i) { ++ super(axolotl, i); + } + + @Override + public void tick() { +- if (!this.axolotl.isPlayingDead()) { ++ if (!Axolotl.this.isPlayingDead()) { + super.tick(); + } ++ + } + } + + public static enum Variant implements StringRepresentable { +- LUCY(0, "lucy", true), +- WILD(1, "wild", true), +- GOLD(2, "gold", true), +- CYAN(3, "cyan", true), +- BLUE(4, "blue", false); + +- private static final IntFunction BY_ID = ByIdMap.continuous(Axolotl.Variant::getId, values(), ByIdMap.OutOfBoundsStrategy.ZERO); ++ LUCY(0, "lucy", true), WILD(1, "wild", true), GOLD(2, "gold", true), CYAN(3, "cyan", true), BLUE(4, "blue", false); ++ ++ private static final IntFunction BY_ID = ByIdMap.continuous(Axolotl.Variant::getId, values(), ByIdMap.a.ZERO); + public static final Codec CODEC = StringRepresentable.fromEnum(Axolotl.Variant::values); + private final int id; + private final String name; + private final boolean common; + +- private Variant(int id, String name, boolean common) { +- this.id = id; +- this.name = name; +- this.common = common; ++ private Variant(int i, String s, boolean flag) { ++ this.id = i; ++ this.name = s; ++ this.common = flag; + } + + public int getId() { +@@ -583,7 +569,7 @@ + } + + public static Axolotl.Variant byId(int id) { +- return BY_ID.apply(id); ++ return (Axolotl.Variant) Axolotl.Variant.BY_ID.apply(id); + } + + public static Axolotl.Variant getCommonSpawnVariant(RandomSource random) { +@@ -595,8 +581,27 @@ + } + + private static Axolotl.Variant getSpawnVariant(RandomSource random, boolean common) { +- Axolotl.Variant[] variants = Arrays.stream(values()).filter(variant -> variant.common == common).toArray(Axolotl.Variant[]::new); +- return Util.getRandom(variants, random); ++ Axolotl.Variant[] aaxolotl_variant = (Axolotl.Variant[]) Arrays.stream(values()).filter((axolotl_variant) -> { ++ return axolotl_variant.common == common; ++ }).toArray((i) -> { ++ return new Axolotl.Variant[i]; ++ }); ++ ++ return (Axolotl.Variant) Util.getRandom((Object[]) aaxolotl_variant, random); + } + } ++ ++ public static class AxolotlGroupData extends AgeableMob.AgeableMobGroupData { ++ ++ public final Axolotl.Variant[] types; ++ ++ public AxolotlGroupData(Axolotl.Variant... types) { ++ super(false); ++ this.types = types; ++ } ++ ++ public Axolotl.Variant getVariant(RandomSource random) { ++ return this.types[random.nextInt(this.types.length)]; ++ } ++ } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/frog/Tadpole.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/frog/Tadpole.java.patch new file mode 100644 index 0000000000..002b4ffa7c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/frog/Tadpole.java.patch @@ -0,0 +1,210 @@ +--- a/net/minecraft/world/entity/animal/frog/Tadpole.java ++++ b/net/minecraft/world/entity/animal/frog/Tadpole.java +@@ -10,13 +10,14 @@ + import net.minecraft.server.level.ServerLevel; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -35,27 +36,14 @@ + import net.minecraft.world.level.Level; + + public class Tadpole extends AbstractFish { ++ + @VisibleForTesting + public static int ticksToBeFrog = Math.abs(-24000); + public static float HITBOX_WIDTH = 0.4F; + public static float HITBOX_HEIGHT = 0.3F; +- private int age; +- protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of( +- SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.HURT_BY, SensorType.FROG_TEMPTATIONS +- ); +- protected static final ImmutableList> MEMORY_TYPES = ImmutableList.of( +- MemoryModuleType.LOOK_TARGET, +- MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, +- MemoryModuleType.WALK_TARGET, +- MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, +- MemoryModuleType.PATH, +- MemoryModuleType.NEAREST_VISIBLE_ADULT, +- MemoryModuleType.TEMPTATION_COOLDOWN_TICKS, +- MemoryModuleType.IS_TEMPTED, +- MemoryModuleType.TEMPTING_PLAYER, +- MemoryModuleType.BREED_TARGET, +- MemoryModuleType.IS_PANICKING +- ); ++ public int age; ++ protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.HURT_BY, SensorType.FROG_TEMPTATIONS); ++ protected static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.LOOK_TARGET, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.PATH, MemoryModuleType.NEAREST_VISIBLE_ADULT, MemoryModuleType.TEMPTATION_COOLDOWN_TICKS, MemoryModuleType.IS_TEMPTED, MemoryModuleType.TEMPTING_PLAYER, MemoryModuleType.BREED_TARGET, MemoryModuleType.IS_PANICKING); + + public Tadpole(EntityType entityType, Level level) { + super(entityType, level); +@@ -70,7 +58,7 @@ + + @Override + protected Brain.Provider brainProvider() { +- return Brain.provider(MEMORY_TYPES, SENSOR_TYPES); ++ return Brain.provider(Tadpole.MEMORY_TYPES, Tadpole.SENSOR_TYPES); + } + + @Override +@@ -80,7 +68,7 @@ + + @Override + public Brain getBrain() { +- return (Brain)super.getBrain(); ++ return (Brain) super.getBrain(); // CraftBukkit - decompile error + } + + @Override +@@ -91,7 +79,7 @@ + @Override + protected void customServerAiStep() { + this.level().getProfiler().push("tadpoleBrain"); +- this.getBrain().tick((ServerLevel)this.level(), this); ++ this.getBrain().tick((ServerLevel) this.level(), this); + this.level().getProfiler().pop(); + this.level().getProfiler().push("tadpoleActivityUpdate"); + TadpoleAi.updateActivity(this); +@@ -100,7 +88,7 @@ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 1.0).add(Attributes.MAX_HEALTH, 6.0); ++ return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 1.0D).add(Attributes.MAX_HEALTH, 6.0D); + } + + @Override +@@ -109,6 +97,7 @@ + if (!this.level().isClientSide) { + this.setAge(this.age + 1); + } ++ + } + + @Override +@@ -142,13 +131,14 @@ + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (this.isFood(itemInHand)) { +- this.feed(player, itemInHand); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (this.isFood(itemstack)) { ++ this.feed(player, itemstack); + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { +- return Bucketable.bucketMobPickup(player, hand, this).orElse(super.mobInteract(player, hand)); ++ return (InteractionResult) Bucketable.bucketMobPickup(player, hand, this).orElse(super.mobInteract(player, hand)); + } + } + +@@ -164,14 +154,14 @@ + } + + @Override +- public void setFromBucket(boolean fromBucket) { +- } ++ public void setFromBucket(boolean fromBucket) {} + + @Override + public void saveToBucketTag(ItemStack stack) { + Bucketable.saveDefaultDataToBucketTag(this, stack); +- CompoundTag tag = stack.getOrCreateTag(); +- tag.putInt("Age", this.getAge()); ++ CompoundTag nbttagcompound = stack.getOrCreateTag(); ++ ++ nbttagcompound.putInt("Age", this.getAge()); + } + + @Override +@@ -180,6 +170,7 @@ + if (tag.contains("Age")) { + this.setAge(tag.getInt("Age")); + } ++ + } + + @Override +@@ -199,13 +190,14 @@ + private void feed(Player player, ItemStack stack) { + this.usePlayerItem(player, stack); + this.ageUp(AgeableMob.getSpeedUpSecondsWhenFeeding(this.getTicksLeftUntilAdult())); +- this.level().addParticle(ParticleTypes.HAPPY_VILLAGER, this.getRandomX(1.0), this.getRandomY() + 0.5, this.getRandomZ(1.0), 0.0, 0.0, 0.0); ++ this.level().addParticle(ParticleTypes.HAPPY_VILLAGER, this.getRandomX(1.0D), this.getRandomY() + 0.5D, this.getRandomZ(1.0D), 0.0D, 0.0D, 0.0D); + } + + private void usePlayerItem(Player player, ItemStack stack) { + if (!player.getAbilities().instabuild) { + stack.shrink(1); + } ++ + } + + private int getAge() { +@@ -218,17 +210,22 @@ + + private void setAge(int age) { + this.age = age; +- if (this.age >= ticksToBeFrog) { ++ if (this.age >= Tadpole.ticksToBeFrog) { + this.ageUp(); + } ++ + } + + private void ageUp() { +- if (this.level() instanceof ServerLevel serverLevel) { +- Frog frog = EntityType.FROG.create(this.level()); ++ Level world = this.level(); ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ Frog frog = (Frog) EntityType.FROG.create(this.level()); ++ + if (frog != null) { + frog.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); +- frog.finalizeSpawn(serverLevel, this.level().getCurrentDifficultyAt(frog.blockPosition()), MobSpawnType.CONVERSION, null, null); ++ frog.finalizeSpawn(worldserver, this.level().getCurrentDifficultyAt(frog.blockPosition()), EnumMobSpawn.CONVERSION, (GroupDataEntity) null, (CompoundTag) null); + frog.setNoAi(this.isNoAi()); + if (this.hasCustomName()) { + frog.setCustomName(this.getCustomName()); +@@ -236,15 +233,22 @@ + } + + frog.setPersistenceRequired(); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTransformEvent(this, frog, org.bukkit.event.entity.EntityTransformEvent.TransformReason.METAMORPHOSIS).isCancelled()) { ++ this.setAge(0); // Sets the age to 0 for avoid a loop if the event is canceled ++ return; ++ } ++ // CraftBukkit end + this.playSound(SoundEvents.TADPOLE_GROW_UP, 0.15F, 1.0F); +- serverLevel.addFreshEntityWithPassengers(frog); ++ worldserver.addFreshEntityWithPassengers(frog, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.METAMORPHOSIS); // CraftBukkit - add SpawnReason + this.discard(); + } + } ++ + } + + private int getTicksLeftUntilAdult() { +- return Math.max(0, ticksToBeFrog - this.age); ++ return Math.max(0, Tadpole.ticksToBeFrog - this.age); + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/goat/Goat.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/goat/Goat.java.patch new file mode 100644 index 0000000000..4bacb9d290 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/goat/Goat.java.patch @@ -0,0 +1,434 @@ +--- a/net/minecraft/world/entity/animal/goat/Goat.java ++++ b/net/minecraft/world/entity/animal/goat/Goat.java +@@ -4,6 +4,7 @@ + import com.mojang.serialization.Dynamic; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; ++import net.minecraft.core.Holder; + import net.minecraft.core.HolderSet; + import net.minecraft.core.registries.BuiltInRegistries; + import net.minecraft.nbt.CompoundTag; +@@ -21,17 +22,17 @@ + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -49,47 +50,30 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.ServerLevelAccessor; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerBucketFillEvent; ++// CraftBukkit end ++ + public class Goat extends Animal { ++ + public static final EntityDimensions LONG_JUMPING_DIMENSIONS = EntityDimensions.scalable(0.9F, 1.3F).scale(0.7F); + private static final int ADULT_ATTACK_DAMAGE = 2; + private static final int BABY_ATTACK_DAMAGE = 1; +- protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of( +- SensorType.NEAREST_LIVING_ENTITIES, +- SensorType.NEAREST_PLAYERS, +- SensorType.NEAREST_ITEMS, +- SensorType.NEAREST_ADULT, +- SensorType.HURT_BY, +- SensorType.GOAT_TEMPTATIONS +- ); +- protected static final ImmutableList> MEMORY_TYPES = ImmutableList.of( +- MemoryModuleType.LOOK_TARGET, +- MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, +- MemoryModuleType.WALK_TARGET, +- MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, +- MemoryModuleType.PATH, +- MemoryModuleType.ATE_RECENTLY, +- MemoryModuleType.BREED_TARGET, +- MemoryModuleType.LONG_JUMP_COOLDOWN_TICKS, +- MemoryModuleType.LONG_JUMP_MID_JUMP, +- MemoryModuleType.TEMPTING_PLAYER, +- MemoryModuleType.NEAREST_VISIBLE_ADULT, +- MemoryModuleType.TEMPTATION_COOLDOWN_TICKS, +- MemoryModuleType.IS_TEMPTED, +- MemoryModuleType.RAM_COOLDOWN_TICKS, +- MemoryModuleType.RAM_TARGET, +- MemoryModuleType.IS_PANICKING +- ); ++ protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.NEAREST_ITEMS, SensorType.NEAREST_ADULT, SensorType.HURT_BY, SensorType.GOAT_TEMPTATIONS); ++ protected static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.LOOK_TARGET, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.PATH, MemoryModuleType.ATE_RECENTLY, MemoryModuleType.BREED_TARGET, MemoryModuleType.LONG_JUMP_COOLDOWN_TICKS, MemoryModuleType.LONG_JUMP_MID_JUMP, MemoryModuleType.TEMPTING_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ADULT, MemoryModuleType.TEMPTATION_COOLDOWN_TICKS, new MemoryModuleType[]{MemoryModuleType.IS_TEMPTED, MemoryModuleType.RAM_COOLDOWN_TICKS, MemoryModuleType.RAM_TARGET, MemoryModuleType.IS_PANICKING}); + public static final int GOAT_FALL_DAMAGE_REDUCTION = 10; +- public static final double GOAT_SCREAMING_CHANCE = 0.02; +- public static final double UNIHORN_CHANCE = 0.1F; ++ public static final double GOAT_SCREAMING_CHANCE = 0.02D; ++ public static final double UNIHORN_CHANCE = 0.10000000149011612D; + private static final EntityDataAccessor DATA_IS_SCREAMING_GOAT = SynchedEntityData.defineId(Goat.class, EntityDataSerializers.BOOLEAN); +- private static final EntityDataAccessor DATA_HAS_LEFT_HORN = SynchedEntityData.defineId(Goat.class, EntityDataSerializers.BOOLEAN); +- private static final EntityDataAccessor DATA_HAS_RIGHT_HORN = SynchedEntityData.defineId(Goat.class, EntityDataSerializers.BOOLEAN); ++ public static final EntityDataAccessor DATA_HAS_LEFT_HORN = SynchedEntityData.defineId(Goat.class, EntityDataSerializers.BOOLEAN); ++ public static final EntityDataAccessor DATA_HAS_RIGHT_HORN = SynchedEntityData.defineId(Goat.class, EntityDataSerializers.BOOLEAN); + private boolean isLoweringHead; + private int lowerHeadTick; + +@@ -101,15 +85,16 @@ + } + + public ItemStack createHorn() { +- RandomSource randomSource = RandomSource.create((long)this.getUUID().hashCode()); +- TagKey tagKey = this.isScreamingGoat() ? InstrumentTags.SCREAMING_GOAT_HORNS : InstrumentTags.REGULAR_GOAT_HORNS; +- HolderSet tag = BuiltInRegistries.INSTRUMENT.getOrCreateTag(tagKey); +- return InstrumentItem.create(Items.GOAT_HORN, tag.getRandomElement(randomSource).get()); ++ RandomSource randomsource = RandomSource.create((long) this.getUUID().hashCode()); ++ TagKey tagkey = this.isScreamingGoat() ? InstrumentTags.SCREAMING_GOAT_HORNS : InstrumentTags.REGULAR_GOAT_HORNS; ++ HolderSet holderset = BuiltInRegistries.INSTRUMENT.getOrCreateTag(tagkey); ++ ++ return InstrumentItem.create(Items.GOAT_HORN, (Holder) holderset.getRandomElement(randomsource).get()); + } + + @Override + protected Brain.Provider brainProvider() { +- return Brain.provider(MEMORY_TYPES, SENSOR_TYPES); ++ return Brain.provider(Goat.MEMORY_TYPES, Goat.SENSOR_TYPES); + } + + @Override +@@ -118,18 +103,19 @@ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0).add(Attributes.MOVEMENT_SPEED, 0.2F).add(Attributes.ATTACK_DAMAGE, 2.0); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.MOVEMENT_SPEED, 0.20000000298023224D).add(Attributes.ATTACK_DAMAGE, 2.0D); + } + + @Override + protected void ageBoundaryReached() { + if (this.isBaby()) { +- this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(1.0); ++ this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(1.0D); + this.removeHorns(); + } else { +- this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(2.0); ++ this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(2.0D); + this.addHorns(); + } ++ + } + + @Override +@@ -153,7 +139,7 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState state) { ++ protected void playStepSound(BlockPos pos, IBlockData state) { + this.playSound(SoundEvents.GOAT_STEP, 0.15F, 1.0F); + } + +@@ -164,12 +150,37 @@ + @Nullable + @Override + public Goat getBreedOffspring(ServerLevel level, AgeableMob otherParent) { +- Goat goat = EntityType.GOAT.create(level); ++ Goat goat = (Goat) EntityType.GOAT.create(level); ++ + if (goat != null) { +- GoatAi.initMemories(goat, level.getRandom()); +- AgeableMob ageableMob = (AgeableMob)(level.getRandom().nextBoolean() ? this : otherParent); +- boolean flag = ageableMob instanceof Goat goat1 && goat1.isScreamingGoat() || level.getRandom().nextDouble() < 0.02; +- goat.setScreamingGoat(flag); ++ boolean flag; ++ label22: ++ { ++ label21: ++ { ++ GoatAi.initMemories(goat, level.getRandom()); ++ Object object = level.getRandom().nextBoolean() ? this : otherParent; ++ ++ if (object instanceof Goat) { ++ Goat goat1 = (Goat) object; ++ ++ if (goat1.isScreamingGoat()) { ++ break label21; ++ } ++ } ++ ++ if (level.getRandom().nextDouble() >= 0.02D) { ++ flag = false; ++ break label22; ++ } ++ } ++ ++ flag = true; ++ } ++ ++ boolean flag1 = flag; ++ ++ goat.setScreamingGoat(flag1); + } + + return goat; +@@ -177,13 +188,13 @@ + + @Override + public Brain getBrain() { +- return (Brain)super.getBrain(); ++ return (Brain) super.getBrain(); // CraftBukkit - decompile error + } + + @Override + protected void customServerAiStep() { + this.level().getProfiler().push("goatBrain"); +- this.getBrain().tick((ServerLevel)this.level(), this); ++ this.getBrain().tick((ServerLevel) this.level(), this); + this.level().getProfiler().pop(); + this.level().getProfiler().push("goatActivityUpdate"); + GoatAi.updateActivity(this); +@@ -198,10 +209,11 @@ + + @Override + public void setYHeadRot(float rotation) { +- int maxHeadYRot = this.getMaxHeadYRot(); +- float f = Mth.degreesDifference(this.yBodyRot, rotation); +- float f1 = Mth.clamp(f, (float)(-maxHeadYRot), (float)maxHeadYRot); +- super.setYHeadRot(this.yBodyRot + f1); ++ int i = this.getMaxHeadYRot(); ++ float f1 = Mth.degreesDifference(this.yBodyRot, rotation); ++ float f2 = Mth.clamp(f1, (float) (-i), (float) i); ++ ++ super.setYHeadRot(this.yBodyRot + f2); + } + + @Override +@@ -210,35 +222,44 @@ + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (itemInHand.is(Items.BUCKET) && !this.isBaby()) { ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (itemstack.is(Items.BUCKET) && !this.isBaby()) { ++ // CraftBukkit start - Got milk? ++ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level(), player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand); ++ ++ if (event.isCancelled()) { ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + player.playSound(this.getMilkingSound(), 1.0F, 1.0F); +- ItemStack itemStack = ItemUtils.createFilledResult(itemInHand, player, Items.MILK_BUCKET.getDefaultInstance()); +- player.setItemInHand(hand, itemStack); ++ ItemStack itemstack1 = ItemUtils.createFilledResult(itemstack, player, CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit ++ ++ player.setItemInHand(hand, itemstack1); + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { +- InteractionResult interactionResult = super.mobInteract(player, hand); +- if (interactionResult.consumesAction() && this.isFood(itemInHand)) { +- this.level() +- .playSound(null, this, this.getEatingSound(itemInHand), SoundSource.NEUTRAL, 1.0F, Mth.randomBetween(this.level().random, 0.8F, 1.2F)); ++ InteractionResult enuminteractionresult = super.mobInteract(player, hand); ++ ++ if (enuminteractionresult.consumesAction() && this.isFood(itemstack)) { ++ this.level().playSound((Player) null, (Entity) this, this.getEatingSound(itemstack), SoundSource.NEUTRAL, 1.0F, Mth.randomBetween(this.level().random, 0.8F, 1.2F)); + } + +- return interactionResult; ++ return enuminteractionresult; + } + } + + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- RandomSource random = level.getRandom(); +- GoatAi.initMemories(this, random); +- this.setScreamingGoat(random.nextDouble() < 0.02); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ RandomSource randomsource = level.getRandom(); ++ ++ GoatAi.initMemories(this, randomsource); ++ this.setScreamingGoat(randomsource.nextDouble() < 0.02D); + this.ageBoundaryReached(); +- if (!this.isBaby() && (double)random.nextFloat() < 0.1F) { +- EntityDataAccessor entityDataAccessor = random.nextBoolean() ? DATA_HAS_LEFT_HORN : DATA_HAS_RIGHT_HORN; +- this.entityData.set(entityDataAccessor, false); ++ if (!this.isBaby() && (double) randomsource.nextFloat() < 0.10000000149011612D) { ++ EntityDataAccessor datawatcherobject = randomsource.nextBoolean() ? Goat.DATA_HAS_LEFT_HORN : Goat.DATA_HAS_RIGHT_HORN; ++ ++ this.entityData.set(datawatcherobject, false); + } + + return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); +@@ -251,8 +272,8 @@ + } + + @Override +- public EntityDimensions getDimensions(Pose pose) { +- return pose == Pose.LONG_JUMPING ? LONG_JUMPING_DIMENSIONS.scale(this.getScale()) : super.getDimensions(pose); ++ public EntityDimensions getDimensions(EntityPose pose) { ++ return pose == EntityPose.LONG_JUMPING ? Goat.LONG_JUMPING_DIMENSIONS.scale(this.getScale()) : super.getDimensions(pose); + } + + @Override +@@ -267,8 +288,8 @@ + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); + this.setScreamingGoat(compound.getBoolean("IsScreamingGoat")); +- this.entityData.set(DATA_HAS_LEFT_HORN, compound.getBoolean("HasLeftHorn")); +- this.entityData.set(DATA_HAS_RIGHT_HORN, compound.getBoolean("HasRightHorn")); ++ this.entityData.set(Goat.DATA_HAS_LEFT_HORN, compound.getBoolean("HasLeftHorn")); ++ this.entityData.set(Goat.DATA_HAS_RIGHT_HORN, compound.getBoolean("HasRightHorn")); + } + + @Override +@@ -280,12 +301,13 @@ + } else { + super.handleEntityEvent(id); + } ++ + } + + @Override + public void aiStep() { + if (this.isLoweringHead) { +- this.lowerHeadTick++; ++ ++this.lowerHeadTick; + } else { + this.lowerHeadTick -= 2; + } +@@ -297,74 +319,77 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_IS_SCREAMING_GOAT, false); +- this.entityData.define(DATA_HAS_LEFT_HORN, true); +- this.entityData.define(DATA_HAS_RIGHT_HORN, true); ++ this.entityData.define(Goat.DATA_IS_SCREAMING_GOAT, false); ++ this.entityData.define(Goat.DATA_HAS_LEFT_HORN, true); ++ this.entityData.define(Goat.DATA_HAS_RIGHT_HORN, true); + } + + public boolean hasLeftHorn() { +- return this.entityData.get(DATA_HAS_LEFT_HORN); ++ return (Boolean) this.entityData.get(Goat.DATA_HAS_LEFT_HORN); + } + + public boolean hasRightHorn() { +- return this.entityData.get(DATA_HAS_RIGHT_HORN); ++ return (Boolean) this.entityData.get(Goat.DATA_HAS_RIGHT_HORN); + } + + public boolean dropHorn() { +- boolean hasLeftHorn = this.hasLeftHorn(); +- boolean hasRightHorn = this.hasRightHorn(); +- if (!hasLeftHorn && !hasRightHorn) { ++ boolean flag = this.hasLeftHorn(); ++ boolean flag1 = this.hasRightHorn(); ++ ++ if (!flag && !flag1) { + return false; + } else { +- EntityDataAccessor entityDataAccessor; +- if (!hasLeftHorn) { +- entityDataAccessor = DATA_HAS_RIGHT_HORN; +- } else if (!hasRightHorn) { +- entityDataAccessor = DATA_HAS_LEFT_HORN; ++ EntityDataAccessor datawatcherobject; ++ ++ if (!flag) { ++ datawatcherobject = Goat.DATA_HAS_RIGHT_HORN; ++ } else if (!flag1) { ++ datawatcherobject = Goat.DATA_HAS_LEFT_HORN; + } else { +- entityDataAccessor = this.random.nextBoolean() ? DATA_HAS_LEFT_HORN : DATA_HAS_RIGHT_HORN; ++ datawatcherobject = this.random.nextBoolean() ? Goat.DATA_HAS_LEFT_HORN : Goat.DATA_HAS_RIGHT_HORN; + } + +- this.entityData.set(entityDataAccessor, false); +- Vec3 vec3 = this.position(); +- ItemStack itemStack = this.createHorn(); +- double d = (double)Mth.randomBetween(this.random, -0.2F, 0.2F); +- double d1 = (double)Mth.randomBetween(this.random, 0.3F, 0.7F); +- double d2 = (double)Mth.randomBetween(this.random, -0.2F, 0.2F); +- ItemEntity itemEntity = new ItemEntity(this.level(), vec3.x(), vec3.y(), vec3.z(), itemStack, d, d1, d2); +- this.level().addFreshEntity(itemEntity); ++ this.entityData.set(datawatcherobject, false); ++ Vec3 vec3d = this.position(); ++ ItemStack itemstack = this.createHorn(); ++ double d0 = (double) Mth.randomBetween(this.random, -0.2F, 0.2F); ++ double d1 = (double) Mth.randomBetween(this.random, 0.3F, 0.7F); ++ double d2 = (double) Mth.randomBetween(this.random, -0.2F, 0.2F); ++ ItemEntity entityitem = new ItemEntity(this.level(), vec3d.x(), vec3d.y(), vec3d.z(), itemstack, d0, d1, d2); ++ ++ this.level().addFreshEntity(entityitem); + return true; + } + } + + public void addHorns() { +- this.entityData.set(DATA_HAS_LEFT_HORN, true); +- this.entityData.set(DATA_HAS_RIGHT_HORN, true); ++ this.entityData.set(Goat.DATA_HAS_LEFT_HORN, true); ++ this.entityData.set(Goat.DATA_HAS_RIGHT_HORN, true); + } + + public void removeHorns() { +- this.entityData.set(DATA_HAS_LEFT_HORN, false); +- this.entityData.set(DATA_HAS_RIGHT_HORN, false); ++ this.entityData.set(Goat.DATA_HAS_LEFT_HORN, false); ++ this.entityData.set(Goat.DATA_HAS_RIGHT_HORN, false); + } + + public boolean isScreamingGoat() { +- return this.entityData.get(DATA_IS_SCREAMING_GOAT); ++ return (Boolean) this.entityData.get(Goat.DATA_IS_SCREAMING_GOAT); + } + + public void setScreamingGoat(boolean isScreamingGoat) { +- this.entityData.set(DATA_IS_SCREAMING_GOAT, isScreamingGoat); ++ this.entityData.set(Goat.DATA_IS_SCREAMING_GOAT, isScreamingGoat); + } + + public float getRammingXHeadRot() { +- return (float)this.lowerHeadTick / 20.0F * 30.0F * (float) (Math.PI / 180.0); ++ return (float) this.lowerHeadTick / 20.0F * 30.0F * 0.017453292F; + } + +- public static boolean checkGoatSpawnRules(EntityType goat, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) { ++ public static boolean checkGoatSpawnRules(EntityType goat, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { + return level.getBlockState(pos.below()).is(BlockTags.GOATS_SPAWNABLE_ON) && isBrightEnoughToSpawn(level, pos); + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height - 0.1875F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.1875F * f, 0.0F); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/horse/AbstractHorse.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/horse/AbstractHorse.java.patch new file mode 100644 index 0000000000..7f203b23bf --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/horse/AbstractHorse.java.patch @@ -0,0 +1,1169 @@ +--- a/net/minecraft/world/entity/animal/horse/AbstractHorse.java ++++ b/net/minecraft/world/entity/animal/horse/AbstractHorse.java +@@ -1,5 +1,7 @@ + package net.minecraft.world.entity.animal.horse; + ++import com.google.common.collect.UnmodifiableIterator; ++import java.util.Iterator; + import java.util.UUID; + import java.util.function.DoubleSupplier; + import java.util.function.IntUnaryOperator; +@@ -8,8 +10,8 @@ + import net.minecraft.advancements.CriteriaTriggers; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.particles.ParticleOptions; + import net.minecraft.core.particles.ParticleTypes; ++import net.minecraft.core.particles.SimpleParticleType; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; +@@ -25,26 +27,26 @@ + import net.minecraft.world.Container; + import net.minecraft.world.ContainerListener; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.HasCustomInventoryScreen; + import net.minecraft.world.entity.HumanoidArm; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.OwnableEntity; + import net.minecraft.world.entity.PlayerRideableJumping; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.Saddleable; + import net.minecraft.world.entity.SlotAccess; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.Attribute; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -70,35 +72,49 @@ + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.SoundType; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++// CraftBukkit end ++ + public abstract class AbstractHorse extends Animal implements ContainerListener, HasCustomInventoryScreen, OwnableEntity, PlayerRideableJumping, Saddleable { ++ + public static final int EQUIPMENT_SLOT_OFFSET = 400; + public static final int CHEST_SLOT_OFFSET = 499; + public static final int INVENTORY_SLOT_OFFSET = 500; +- public static final double BREEDING_CROSS_FACTOR = 0.15; +- private static final float MIN_MOVEMENT_SPEED = (float)generateSpeed(() -> 0.0); +- private static final float MAX_MOVEMENT_SPEED = (float)generateSpeed(() -> 1.0); +- private static final float MIN_JUMP_STRENGTH = (float)generateJumpStrength(() -> 0.0); +- private static final float MAX_JUMP_STRENGTH = (float)generateJumpStrength(() -> 1.0); +- private static final float MIN_HEALTH = generateMaxHealth(i -> 0); +- private static final float MAX_HEALTH = generateMaxHealth(i -> i - 1); ++ public static final double BREEDING_CROSS_FACTOR = 0.15D; ++ private static final float MIN_MOVEMENT_SPEED = (float) generateSpeed(() -> { ++ return 0.0D; ++ }); ++ private static final float MAX_MOVEMENT_SPEED = (float) generateSpeed(() -> { ++ return 1.0D; ++ }); ++ private static final float MIN_JUMP_STRENGTH = (float) generateJumpStrength(() -> { ++ return 0.0D; ++ }); ++ private static final float MAX_JUMP_STRENGTH = (float) generateJumpStrength(() -> { ++ return 1.0D; ++ }); ++ private static final float MIN_HEALTH = generateMaxHealth((i) -> { ++ return 0; ++ }); ++ private static final float MAX_HEALTH = generateMaxHealth((i) -> { ++ return i - 1; ++ }); + private static final float BACKWARDS_MOVE_SPEED_FACTOR = 0.25F; + private static final float SIDEWAYS_MOVE_SPEED_FACTOR = 0.5F; +- private static final Predicate PARENT_HORSE_SELECTOR = livingEntity -> livingEntity instanceof AbstractHorse +- && ((AbstractHorse)livingEntity).isBred(); +- private static final TargetingConditions MOMMY_TARGETING = TargetingConditions.forNonCombat() +- .range(16.0) +- .ignoreLineOfSight() +- .selector(PARENT_HORSE_SELECTOR); +- private static final Ingredient FOOD_ITEMS = Ingredient.of( +- Items.WHEAT, Items.SUGAR, Blocks.HAY_BLOCK.asItem(), Items.APPLE, Items.GOLDEN_CARROT, Items.GOLDEN_APPLE, Items.ENCHANTED_GOLDEN_APPLE +- ); ++ private static final Predicate PARENT_HORSE_SELECTOR = (entityliving) -> { ++ return entityliving instanceof AbstractHorse && ((AbstractHorse) entityliving).isBred(); ++ }; ++ private static final TargetingConditions MOMMY_TARGETING = TargetingConditions.forNonCombat().range(16.0D).ignoreLineOfSight().selector(AbstractHorse.PARENT_HORSE_SELECTOR); ++ private static final Ingredient FOOD_ITEMS = Ingredient.of(Items.WHEAT, Items.SUGAR, Blocks.HAY_BLOCK.asItem(), Items.APPLE, Items.GOLDEN_CARROT, Items.GOLDEN_APPLE, Items.ENCHANTED_GOLDEN_APPLE); + private static final EntityDataAccessor DATA_ID_FLAGS = SynchedEntityData.defineId(AbstractHorse.class, EntityDataSerializers.BYTE); + private static final int FLAG_TAME = 2; + private static final int FLAG_SADDLE = 4; +@@ -115,7 +131,7 @@ + public int tailCounter; + public int sprintCounter; + protected boolean isJumping; +- protected SimpleContainer inventory; ++ public SimpleContainer inventory; + protected int temper; + protected float playerJumpPendingScale; + protected boolean allowStandSliding; +@@ -129,6 +145,7 @@ + protected int gallopSoundCounter; + @Nullable + private UUID owner; ++ public int maxDomestication = 100; // CraftBukkit - store max domestication value + + protected AbstractHorse(EntityType entityType, Level level) { + super(entityType, level); +@@ -138,11 +155,11 @@ + + @Override + protected void registerGoals() { +- this.goalSelector.addGoal(1, new PanicGoal(this, 1.2)); +- this.goalSelector.addGoal(1, new RunAroundLikeCrazyGoal(this, 1.2)); +- this.goalSelector.addGoal(2, new BreedGoal(this, 1.0, AbstractHorse.class)); +- this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.0)); +- this.goalSelector.addGoal(6, new WaterAvoidingRandomStrollGoal(this, 0.7)); ++ this.goalSelector.addGoal(1, new PanicGoal(this, 1.2D)); ++ this.goalSelector.addGoal(1, new RunAroundLikeCrazyGoal(this, 1.2D)); ++ this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D, AbstractHorse.class)); ++ this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.0D)); ++ this.goalSelector.addGoal(6, new WaterAvoidingRandomStrollGoal(this, 0.7D)); + this.goalSelector.addGoal(7, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); + if (this.canPerformRearing()) { +@@ -154,26 +171,28 @@ + + protected void addBehaviourGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); +- this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, Ingredient.of(Items.GOLDEN_CARROT, Items.GOLDEN_APPLE, Items.ENCHANTED_GOLDEN_APPLE), false)); ++ this.goalSelector.addGoal(3, new TemptGoal(this, 1.25D, Ingredient.of(Items.GOLDEN_CARROT, Items.GOLDEN_APPLE, Items.ENCHANTED_GOLDEN_APPLE), false)); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_ID_FLAGS, (byte)0); ++ this.entityData.define(AbstractHorse.DATA_ID_FLAGS, (byte) 0); + } + + protected boolean getFlag(int flagId) { +- return (this.entityData.get(DATA_ID_FLAGS) & flagId) != 0; ++ return ((Byte) this.entityData.get(AbstractHorse.DATA_ID_FLAGS) & flagId) != 0; + } + + protected void setFlag(int flagId, boolean value) { +- byte b = this.entityData.get(DATA_ID_FLAGS); ++ byte b0 = (Byte) this.entityData.get(AbstractHorse.DATA_ID_FLAGS); ++ + if (value) { +- this.entityData.set(DATA_ID_FLAGS, (byte)(b | flagId)); ++ this.entityData.set(AbstractHorse.DATA_ID_FLAGS, (byte) (b0 | flagId)); + } else { +- this.entityData.set(DATA_ID_FLAGS, (byte)(b & ~flagId)); ++ this.entityData.set(AbstractHorse.DATA_ID_FLAGS, (byte) (b0 & ~flagId)); + } ++ + } + + public boolean isTamed() { +@@ -207,6 +226,7 @@ + if (distance > 6.0F && this.isEating()) { + this.setEating(false); + } ++ + } + + public boolean isEating() { +@@ -242,6 +262,7 @@ + armor.shrink(1); + } + } ++ + } + + @Override +@@ -258,9 +279,10 @@ + } + + public int modifyTemper(int addedTemper) { +- int i = Mth.clamp(this.getTemper() + addedTemper, 0, this.getMaxTemper()); +- this.setTemper(i); +- return i; ++ int j = Mth.clamp(this.getTemper() + addedTemper, 0, this.getMaxTemper()); ++ ++ this.setTemper(j); ++ return j; + } + + @Override +@@ -271,21 +293,13 @@ + private void eating() { + this.openMouth(); + if (!this.isSilent()) { +- SoundEvent eatingSound = this.getEatingSound(); +- if (eatingSound != null) { +- this.level() +- .playSound( +- null, +- this.getX(), +- this.getY(), +- this.getZ(), +- eatingSound, +- this.getSoundSource(), +- 1.0F, +- 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F +- ); ++ SoundEvent soundeffect = this.getEatingSound(); ++ ++ if (soundeffect != null) { ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), soundeffect, this.getSoundSource(), 1.0F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F); + } + } ++ + } + + @Override +@@ -295,13 +309,18 @@ + } + + int i = this.calculateFallDamage(fallDistance, multiplier); ++ + if (i <= 0) { + return false; + } else { +- this.hurt(source, (float)i); ++ this.hurt(source, (float) i); + if (this.isVehicle()) { +- for (Entity entity : this.getIndirectPassengers()) { +- entity.hurt(source, (float)i); ++ Iterator iterator = this.getIndirectPassengers().iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ ++ entity.hurt(source, (float) i); + } + } + +@@ -319,17 +338,19 @@ + return 2; + } + +- protected void createInventory() { +- SimpleContainer simpleContainer = this.inventory; +- this.inventory = new SimpleContainer(this.getInventorySize()); +- if (simpleContainer != null) { +- simpleContainer.removeListener(this); +- int min = Math.min(simpleContainer.getContainerSize(), this.inventory.getContainerSize()); ++ public void createInventory() { ++ SimpleContainer inventorysubcontainer = this.inventory; + +- for (int i = 0; i < min; i++) { +- ItemStack item = simpleContainer.getItem(i); +- if (!item.isEmpty()) { +- this.inventory.setItem(i, item.copy()); ++ this.inventory = new SimpleContainer(this.getInventorySize(), (org.bukkit.entity.AbstractHorse) this.getBukkitEntity()); // CraftBukkit ++ if (inventorysubcontainer != null) { ++ inventorysubcontainer.removeListener(this); ++ int i = Math.min(inventorysubcontainer.getContainerSize(), this.inventory.getContainerSize()); ++ ++ for (int j = 0; j < i; ++j) { ++ ItemStack itemstack = inventorysubcontainer.getItem(j); ++ ++ if (!itemstack.isEmpty()) { ++ this.inventory.setItem(j, itemstack.copy()); + } + } + } +@@ -346,11 +367,13 @@ + + @Override + public void containerChanged(Container invBasic) { +- boolean isSaddled = this.isSaddled(); ++ boolean flag = this.isSaddled(); ++ + this.updateContainerEquipment(); +- if (this.tickCount > 20 && !isSaddled && this.isSaddled()) { ++ if (this.tickCount > 20 && !flag && this.isSaddled()) { + this.playSound(this.getSaddleSoundEvent(), 0.5F, 1.0F); + } ++ + } + + public double getCustomJump() { +@@ -360,6 +383,7 @@ + @Override + public boolean hurt(DamageSource source, float amount) { + boolean flag = super.hurt(source, amount); ++ + if (flag && this.random.nextInt(3) == 0) { + this.standIfPossible(); + } +@@ -382,35 +406,33 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + if (!block.liquid()) { +- BlockState blockState = this.level().getBlockState(pos.above()); +- SoundType soundType = block.getSoundType(); +- if (blockState.is(Blocks.SNOW)) { +- soundType = blockState.getSoundType(); ++ IBlockData iblockdata1 = this.level().getBlockState(pos.above()); ++ SoundType soundeffecttype = block.getSoundType(); ++ ++ if (iblockdata1.is(Blocks.SNOW)) { ++ soundeffecttype = iblockdata1.getSoundType(); + } + + if (this.isVehicle() && this.canGallop) { +- this.gallopSoundCounter++; ++ ++this.gallopSoundCounter; + if (this.gallopSoundCounter > 5 && this.gallopSoundCounter % 3 == 0) { +- this.playGallopSound(soundType); ++ this.playGallopSound(soundeffecttype); + } else if (this.gallopSoundCounter <= 5) { +- this.playSound(SoundEvents.HORSE_STEP_WOOD, soundType.getVolume() * 0.15F, soundType.getPitch()); ++ this.playSound(SoundEvents.HORSE_STEP_WOOD, soundeffecttype.getVolume() * 0.15F, soundeffecttype.getPitch()); + } +- } else if (this.isWoodSoundType(soundType)) { +- this.playSound(SoundEvents.HORSE_STEP_WOOD, soundType.getVolume() * 0.15F, soundType.getPitch()); ++ } else if (this.isWoodSoundType(soundeffecttype)) { ++ this.playSound(SoundEvents.HORSE_STEP_WOOD, soundeffecttype.getVolume() * 0.15F, soundeffecttype.getPitch()); + } else { +- this.playSound(SoundEvents.HORSE_STEP, soundType.getVolume() * 0.15F, soundType.getPitch()); ++ this.playSound(SoundEvents.HORSE_STEP, soundeffecttype.getVolume() * 0.15F, soundeffecttype.getPitch()); + } ++ + } + } + + private boolean isWoodSoundType(SoundType soundType) { +- return soundType == SoundType.WOOD +- || soundType == SoundType.NETHER_WOOD +- || soundType == SoundType.STEM +- || soundType == SoundType.CHERRY_WOOD +- || soundType == SoundType.BAMBOO_WOOD; ++ return soundType == SoundType.WOOD || soundType == SoundType.NETHER_WOOD || soundType == SoundType.STEM || soundType == SoundType.CHERRY_WOOD || soundType == SoundType.BAMBOO_WOOD; + } + + protected void playGallopSound(SoundType soundType) { +@@ -418,7 +440,7 @@ + } + + public static AttributeSupplier.Builder createBaseHorseAttributes() { +- return Mob.createMobAttributes().add(Attributes.JUMP_STRENGTH).add(Attributes.MAX_HEALTH, 53.0).add(Attributes.MOVEMENT_SPEED, 0.225F); ++ return Mob.createMobAttributes().add(Attributes.JUMP_STRENGTH).add(Attributes.MAX_HEALTH, 53.0D).add(Attributes.MOVEMENT_SPEED, 0.22499999403953552D); + } + + @Override +@@ -427,7 +449,7 @@ + } + + public int getMaxTemper() { +- return 100; ++ return this.maxDomestication; // CraftBukkit - return stored max domestication instead of 100 + } + + @Override +@@ -442,56 +464,55 @@ + + @Override + public void openCustomInventoryScreen(Player player) { +- if (!this.level().isClientSide && (!this.isVehicle() || this.hasPassenger(player)) && this.isTamed()) { ++ if (!this.level().isClientSide && (!this.isVehicle() || this.hasPassenger((Entity) player)) && this.isTamed()) { + player.openHorseInventory(this, this.inventory); + } ++ + } + + public InteractionResult fedFood(Player player, ItemStack stack) { + boolean flag = this.handleEating(player, stack); ++ + if (flag & !player.getAbilities().instabuild) { + stack.shrink(1); + } + +- if (this.level().isClientSide) { +- return InteractionResult.CONSUME; +- } else { +- return flag ? InteractionResult.SUCCESS : InteractionResult.PASS; +- } ++ return this.level().isClientSide ? InteractionResult.CONSUME : (flag ? InteractionResult.SUCCESS : InteractionResult.PASS); + } + + protected boolean handleEating(Player player, ItemStack stack) { + boolean flag = false; + float f = 0.0F; +- int i = 0; +- int i1 = 0; ++ short short0 = 0; ++ byte b0 = 0; ++ + if (stack.is(Items.WHEAT)) { + f = 2.0F; +- i = 20; +- i1 = 3; ++ short0 = 20; ++ b0 = 3; + } else if (stack.is(Items.SUGAR)) { + f = 1.0F; +- i = 30; +- i1 = 3; ++ short0 = 30; ++ b0 = 3; + } else if (stack.is(Blocks.HAY_BLOCK.asItem())) { + f = 20.0F; +- i = 180; ++ short0 = 180; + } else if (stack.is(Items.APPLE)) { + f = 3.0F; +- i = 60; +- i1 = 3; ++ short0 = 60; ++ b0 = 3; + } else if (stack.is(Items.GOLDEN_CARROT)) { + f = 4.0F; +- i = 60; +- i1 = 5; ++ short0 = 60; ++ b0 = 5; + if (!this.level().isClientSide && this.isTamed() && this.getAge() == 0 && !this.isInLove()) { + flag = true; + this.setInLove(player); + } + } else if (stack.is(Items.GOLDEN_APPLE) || stack.is(Items.ENCHANTED_GOLDEN_APPLE)) { + f = 10.0F; +- i = 240; +- i1 = 10; ++ short0 = 240; ++ b0 = 10; + if (!this.level().isClientSide && this.isTamed() && this.getAge() == 0 && !this.isInLove()) { + flag = true; + this.setInLove(player); +@@ -499,20 +520,20 @@ + } + + if (this.getHealth() < this.getMaxHealth() && f > 0.0F) { +- this.heal(f); ++ this.heal(f, EntityRegainHealthEvent.RegainReason.EATING); // CraftBukkit + flag = true; + } + +- if (this.isBaby() && i > 0) { +- this.level().addParticle(ParticleTypes.HAPPY_VILLAGER, this.getRandomX(1.0), this.getRandomY() + 0.5, this.getRandomZ(1.0), 0.0, 0.0, 0.0); ++ if (this.isBaby() && short0 > 0) { ++ this.level().addParticle(ParticleTypes.HAPPY_VILLAGER, this.getRandomX(1.0D), this.getRandomY() + 0.5D, this.getRandomZ(1.0D), 0.0D, 0.0D, 0.0D); + if (!this.level().isClientSide) { +- this.ageUp(i); ++ this.ageUp(short0); + flag = true; + } + } + +- if (i1 > 0 && (flag || !this.isTamed()) && this.getTemper() < this.getMaxTemper() && !this.level().isClientSide) { +- this.modifyTemper(i1); ++ if (b0 > 0 && (flag || !this.isTamed()) && this.getTemper() < this.getMaxTemper() && !this.level().isClientSide) { ++ this.modifyTemper(b0); + flag = true; + } + +@@ -532,6 +553,7 @@ + player.setXRot(this.getXRot()); + player.startRiding(this); + } ++ + } + + @Override +@@ -541,7 +563,7 @@ + + @Override + public boolean isFood(ItemStack stack) { +- return FOOD_ITEMS.test(stack); ++ return AbstractHorse.FOOD_ITEMS.test(stack); + } + + private void moveTail() { +@@ -552,12 +574,14 @@ + protected void dropEquipment() { + super.dropEquipment(); + if (this.inventory != null) { +- for (int i = 0; i < this.inventory.getContainerSize(); i++) { +- ItemStack item = this.inventory.getItem(i); +- if (!item.isEmpty() && !EnchantmentHelper.hasVanishingCurse(item)) { +- this.spawnAtLocation(item); ++ for (int i = 0; i < this.inventory.getContainerSize(); ++i) { ++ ItemStack itemstack = this.inventory.getItem(i); ++ ++ if (!itemstack.isEmpty() && !EnchantmentHelper.hasVanishingCurse(itemstack)) { ++ this.spawnAtLocation(itemstack); + } + } ++ + } + } + +@@ -570,14 +594,11 @@ + super.aiStep(); + if (!this.level().isClientSide && this.isAlive()) { + if (this.random.nextInt(900) == 0 && this.deathTime == 0) { +- this.heal(1.0F); ++ this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit + } + + if (this.canEatGrass()) { +- if (!this.isEating() +- && !this.isVehicle() +- && this.random.nextInt(300) == 0 +- && this.level().getBlockState(this.blockPosition().below()).is(Blocks.GRASS_BLOCK)) { ++ if (!this.isEating() && !this.isVehicle() && this.random.nextInt(300) == 0 && this.level().getBlockState(this.blockPosition().below()).is(Blocks.GRASS_BLOCK)) { + this.setEating(true); + } + +@@ -593,12 +614,13 @@ + + protected void followMommy() { + if (this.isBred() && this.isBaby() && !this.isEating()) { +- LivingEntity nearestEntity = this.level() +- .getNearestEntity(AbstractHorse.class, MOMMY_TARGETING, this, this.getX(), this.getY(), this.getZ(), this.getBoundingBox().inflate(16.0)); +- if (nearestEntity != null && this.distanceToSqr(nearestEntity) > 4.0) { +- this.navigation.createPath(nearestEntity, 0); ++ LivingEntity entityliving = this.level().getNearestEntity(AbstractHorse.class, AbstractHorse.MOMMY_TARGETING, this, this.getX(), this.getY(), this.getZ(), this.getBoundingBox().inflate(16.0D)); ++ ++ if (entityliving != null && this.distanceToSqr((Entity) entityliving) > 4.0D) { ++ this.navigation.createPath((Entity) entityliving, 0); + } + } ++ + } + + public boolean canEatGrass() { +@@ -623,7 +645,7 @@ + } + + if (this.sprintCounter > 0) { +- this.sprintCounter++; ++ ++this.sprintCounter; + if (this.sprintCounter > 300) { + this.sprintCounter = 0; + } +@@ -631,12 +653,12 @@ + + this.eatAnimO = this.eatAnim; + if (this.isEating()) { +- this.eatAnim = this.eatAnim + (1.0F - this.eatAnim) * 0.4F + 0.05F; ++ this.eatAnim += (1.0F - this.eatAnim) * 0.4F + 0.05F; + if (this.eatAnim > 1.0F) { + this.eatAnim = 1.0F; + } + } else { +- this.eatAnim = this.eatAnim + ((0.0F - this.eatAnim) * 0.4F - 0.05F); ++ this.eatAnim += (0.0F - this.eatAnim) * 0.4F - 0.05F; + if (this.eatAnim < 0.0F) { + this.eatAnim = 0.0F; + } +@@ -646,13 +668,13 @@ + if (this.isStanding()) { + this.eatAnim = 0.0F; + this.eatAnimO = this.eatAnim; +- this.standAnim = this.standAnim + (1.0F - this.standAnim) * 0.4F + 0.05F; ++ this.standAnim += (1.0F - this.standAnim) * 0.4F + 0.05F; + if (this.standAnim > 1.0F) { + this.standAnim = 1.0F; + } + } else { + this.allowStandSliding = false; +- this.standAnim = this.standAnim + ((0.8F * this.standAnim * this.standAnim * this.standAnim - this.standAnim) * 0.6F - 0.05F); ++ this.standAnim += (0.8F * this.standAnim * this.standAnim * this.standAnim - this.standAnim) * 0.6F - 0.05F; + if (this.standAnim < 0.0F) { + this.standAnim = 0.0F; + } +@@ -660,41 +682,46 @@ + + this.mouthAnimO = this.mouthAnim; + if (this.getFlag(64)) { +- this.mouthAnim = this.mouthAnim + (1.0F - this.mouthAnim) * 0.7F + 0.05F; ++ this.mouthAnim += (1.0F - this.mouthAnim) * 0.7F + 0.05F; + if (this.mouthAnim > 1.0F) { + this.mouthAnim = 1.0F; + } + } else { +- this.mouthAnim = this.mouthAnim + ((0.0F - this.mouthAnim) * 0.7F - 0.05F); ++ this.mouthAnim += (0.0F - this.mouthAnim) * 0.7F - 0.05F; + if (this.mouthAnim < 0.0F) { + this.mouthAnim = 0.0F; + } + } ++ + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- if (this.isVehicle() || this.isBaby()) { +- return super.mobInteract(player, hand); +- } else if (this.isTamed() && player.isSecondaryUseActive()) { +- this.openCustomInventoryScreen(player); +- return InteractionResult.sidedSuccess(this.level().isClientSide); +- } else { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (!itemInHand.isEmpty()) { +- InteractionResult interactionResult = itemInHand.interactLivingEntity(player, this, hand); +- if (interactionResult.consumesAction()) { +- return interactionResult; +- } ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ if (!this.isVehicle() && !this.isBaby()) { ++ if (this.isTamed() && player.isSecondaryUseActive()) { ++ this.openCustomInventoryScreen(player); ++ return InteractionResult.sidedSuccess(this.level().isClientSide); ++ } else { ++ ItemStack itemstack = player.getItemInHand(hand); + +- if (this.canWearArmor() && this.isArmor(itemInHand) && !this.isWearingArmor()) { +- this.equipArmor(player, itemInHand); +- return InteractionResult.sidedSuccess(this.level().isClientSide); ++ if (!itemstack.isEmpty()) { ++ InteractionResult enuminteractionresult = itemstack.interactLivingEntity(player, this, hand); ++ ++ if (enuminteractionresult.consumesAction()) { ++ return enuminteractionresult; ++ } ++ ++ if (this.canWearArmor() && this.isArmor(itemstack) && !this.isWearingArmor()) { ++ this.equipArmor(player, itemstack); ++ return InteractionResult.sidedSuccess(this.level().isClientSide); ++ } + } +- } + +- this.doPlayerRide(player); +- return InteractionResult.sidedSuccess(this.level().isClientSide); ++ this.doPlayerRide(player); ++ return InteractionResult.sidedSuccess(this.level().isClientSide); ++ } ++ } else { ++ return super.mobInteract(player, hand); + } + } + +@@ -703,6 +730,7 @@ + this.mouthCounter = 1; + this.setFlag(64, true); + } ++ + } + + public void setEating(boolean eating) { +@@ -727,37 +755,41 @@ + this.standCounter = 1; + this.setStanding(true); + } ++ + } + + public void makeMad() { + if (!this.isStanding()) { + this.standIfPossible(); +- SoundEvent angrySound = this.getAngrySound(); +- if (angrySound != null) { +- this.playSound(angrySound, this.getSoundVolume(), this.getVoicePitch()); ++ SoundEvent soundeffect = this.getAngrySound(); ++ ++ if (soundeffect != null) { ++ this.playSound(soundeffect, this.getSoundVolume(), this.getVoicePitch()); + } + } ++ + } + + public boolean tameWithName(Player player) { + this.setOwnerUUID(player.getUUID()); + this.setTamed(true); + if (player instanceof ServerPlayer) { +- CriteriaTriggers.TAME_ANIMAL.trigger((ServerPlayer)player, this); ++ CriteriaTriggers.TAME_ANIMAL.trigger((ServerPlayer) player, (Animal) this); + } + +- this.level().broadcastEntityEvent(this, (byte)7); ++ this.level().broadcastEntityEvent(this, (byte) 7); + return true; + } + + @Override + protected void tickRidden(Player player, Vec3 travelVector) { + super.tickRidden(player, travelVector); +- Vec2 riddenRotation = this.getRiddenRotation(player); +- this.setRot(riddenRotation.y, riddenRotation.x); ++ Vec2 vec2f = this.getRiddenRotation(player); ++ ++ this.setRot(vec2f.y, vec2f.x); + this.yRotO = this.yBodyRot = this.yHeadRot = this.getYRot(); + if (this.isControlledByLocalInstance()) { +- if (travelVector.z <= 0.0) { ++ if (travelVector.z <= 0.0D) { + this.gallopSoundCounter = 0; + } + +@@ -770,6 +802,7 @@ + this.playerJumpPendingScale = 0.0F; + } + } ++ + } + + protected Vec2 getRiddenRotation(LivingEntity entity) { +@@ -783,33 +816,35 @@ + } else { + float f = player.xxa * 0.5F; + float f1 = player.zza; ++ + if (f1 <= 0.0F) { + f1 *= 0.25F; + } + +- return new Vec3((double)f, 0.0, (double)f1); ++ return new Vec3((double) f, 0.0D, (double) f1); + } + } + + @Override + protected float getRiddenSpeed(Player player) { +- return (float)this.getAttributeValue(Attributes.MOVEMENT_SPEED); ++ return (float) this.getAttributeValue(Attributes.MOVEMENT_SPEED); + } + + protected void executeRidersJump(float playerJumpPendingScale, Vec3 travelVector) { +- double d = this.getCustomJump() * (double)playerJumpPendingScale * (double)this.getBlockJumpFactor(); +- double d1 = d + (double)this.getJumpBoostPower(); +- Vec3 deltaMovement = this.getDeltaMovement(); +- this.setDeltaMovement(deltaMovement.x, d1, deltaMovement.z); ++ double d0 = this.getCustomJump() * (double) playerJumpPendingScale * (double) this.getBlockJumpFactor(); ++ double d1 = d0 + (double) this.getJumpBoostPower(); ++ Vec3 vec3d1 = this.getDeltaMovement(); ++ ++ this.setDeltaMovement(vec3d1.x, d1, vec3d1.z); + this.setIsJumping(true); + this.hasImpulse = true; +- if (travelVector.z > 0.0) { +- float sin = Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)); +- float cos = Mth.cos(this.getYRot() * (float) (Math.PI / 180.0)); +- this.setDeltaMovement( +- this.getDeltaMovement().add((double)(-0.4F * sin * playerJumpPendingScale), 0.0, (double)(0.4F * cos * playerJumpPendingScale)) +- ); ++ if (travelVector.z > 0.0D) { ++ float f1 = Mth.sin(this.getYRot() * 0.017453292F); ++ float f2 = Mth.cos(this.getYRot() * 0.017453292F); ++ ++ this.setDeltaMovement(this.getDeltaMovement().add((double) (-0.4F * f1 * playerJumpPendingScale), 0.0D, (double) (0.4F * f2 * playerJumpPendingScale))); + } ++ + } + + protected void playJumpSound() { +@@ -826,10 +861,12 @@ + if (this.getOwnerUUID() != null) { + compound.putUUID("Owner", this.getOwnerUUID()); + } ++ compound.putInt("Bukkit.MaxDomestication", this.maxDomestication); // CraftBukkit + + if (!this.inventory.getItem(0).isEmpty()) { + compound.put("SaddleItem", this.inventory.getItem(0).save(new CompoundTag())); + } ++ + } + + @Override +@@ -839,22 +876,30 @@ + this.setBred(compound.getBoolean("Bred")); + this.setTemper(compound.getInt("Temper")); + this.setTamed(compound.getBoolean("Tame")); +- UUID uUID; ++ UUID uuid; ++ + if (compound.hasUUID("Owner")) { +- uUID = compound.getUUID("Owner"); ++ uuid = compound.getUUID("Owner"); + } else { +- String string = compound.getString("Owner"); +- uUID = OldUsersConverter.convertMobOwnerIfNecessary(this.getServer(), string); ++ String s = compound.getString("Owner"); ++ ++ uuid = OldUsersConverter.convertMobOwnerIfNecessary(this.getServer(), s); + } + +- if (uUID != null) { +- this.setOwnerUUID(uUID); ++ if (uuid != null) { ++ this.setOwnerUUID(uuid); + } ++ // CraftBukkit start ++ if (compound.contains("Bukkit.MaxDomestication")) { ++ this.maxDomestication = compound.getInt("Bukkit.MaxDomestication"); ++ } ++ // CraftBukkit end + + if (compound.contains("SaddleItem", 10)) { +- ItemStack itemStack = ItemStack.of(compound.getCompound("SaddleItem")); +- if (itemStack.is(Items.SADDLE)) { +- this.inventory.setItem(0, itemStack); ++ ItemStack itemstack = ItemStack.of(compound.getCompound("SaddleItem")); ++ ++ if (itemstack.is(Items.SADDLE)) { ++ this.inventory.setItem(0, itemstack); + } + } + +@@ -877,35 +922,38 @@ + } + + protected void setOffspringAttributes(AgeableMob parent, AbstractHorse child) { +- this.setOffspringAttribute(parent, child, Attributes.MAX_HEALTH, (double)MIN_HEALTH, (double)MAX_HEALTH); +- this.setOffspringAttribute(parent, child, Attributes.JUMP_STRENGTH, (double)MIN_JUMP_STRENGTH, (double)MAX_JUMP_STRENGTH); +- this.setOffspringAttribute(parent, child, Attributes.MOVEMENT_SPEED, (double)MIN_MOVEMENT_SPEED, (double)MAX_MOVEMENT_SPEED); ++ this.setOffspringAttribute(parent, child, Attributes.MAX_HEALTH, (double) AbstractHorse.MIN_HEALTH, (double) AbstractHorse.MAX_HEALTH); ++ this.setOffspringAttribute(parent, child, Attributes.JUMP_STRENGTH, (double) AbstractHorse.MIN_JUMP_STRENGTH, (double) AbstractHorse.MAX_JUMP_STRENGTH); ++ this.setOffspringAttribute(parent, child, Attributes.MOVEMENT_SPEED, (double) AbstractHorse.MIN_MOVEMENT_SPEED, (double) AbstractHorse.MAX_MOVEMENT_SPEED); + } + +- private void setOffspringAttribute(AgeableMob otherParent, AbstractHorse child, Attribute attribute, double min, double max) { +- double d = createOffspringAttribute(this.getAttributeBaseValue(attribute), otherParent.getAttributeBaseValue(attribute), min, max, this.random); +- child.getAttribute(attribute).setBaseValue(d); ++ private void setOffspringAttribute(AgeableMob otherParent, AbstractHorse child, Attribute attribute, double min, double d1) { ++ double d2 = createOffspringAttribute(this.getAttributeBaseValue(attribute), otherParent.getAttributeBaseValue(attribute), min, d1, this.random); ++ ++ child.getAttribute(attribute).setBaseValue(d2); + } + +- static double createOffspringAttribute(double value1, double value2, double min, double max, RandomSource random) { +- if (max <= min) { ++ static double createOffspringAttribute(double value1, double d1, double value2, double d3, RandomSource min) { ++ if (d3 <= value2) { + throw new IllegalArgumentException("Incorrect range for an attribute"); + } else { +- value1 = Mth.clamp(value1, min, max); +- value2 = Mth.clamp(value2, min, max); +- double d = 0.15 * (max - min); +- double d1 = Math.abs(value1 - value2) + d * 2.0; +- double d2 = (value1 + value2) / 2.0; +- double d3 = (random.nextDouble() + random.nextDouble() + random.nextDouble()) / 3.0 - 0.5; +- double d4 = d2 + d1 * d3; +- if (d4 > max) { +- double d5 = d4 - max; +- return max - d5; +- } else if (d4 < min) { +- double d5 = min - d4; +- return min + d5; ++ value1 = Mth.clamp(value1, value2, d3); ++ d1 = Mth.clamp(d1, value2, d3); ++ double d4 = 0.15D * (d3 - value2); ++ double d5 = Math.abs(value1 - d1) + d4 * 2.0D; ++ double d6 = (value1 + d1) / 2.0D; ++ double d7 = (min.nextDouble() + min.nextDouble() + min.nextDouble()) / 3.0D - 0.5D; ++ double d8 = d6 + d5 * d7; ++ double d9; ++ ++ if (d8 > d3) { ++ d9 = d8 - d3; ++ return d3 - d9; ++ } else if (d8 < value2) { ++ d9 = value2 - d8; ++ return value2 + d9; + } else { +- return d4; ++ return d8; + } + } + } +@@ -935,8 +983,9 @@ + if (jumpPower >= 90) { + this.playerJumpPendingScale = 1.0F; + } else { +- this.playerJumpPendingScale = 0.4F + 0.4F * (float)jumpPower / 90.0F; ++ this.playerJumpPendingScale = 0.4F + 0.4F * (float) jumpPower / 90.0F; + } ++ + } + } + +@@ -947,24 +996,36 @@ + + @Override + public void handleStartJump(int jumpPower) { ++ // CraftBukkit start ++ float power; ++ if (jumpPower >= 90) { ++ power = 1.0F; ++ } else { ++ power = 0.4F + 0.4F * (float) jumpPower / 90.0F; ++ } ++ if (!CraftEventFactory.callHorseJumpEvent(this, power)) { ++ return; ++ } ++ // CraftBukkit end + this.allowStandSliding = true; + this.standIfPossible(); + this.playJumpSound(); + } + + @Override +- public void handleStopJump() { +- } ++ public void handleStopJump() {} + + protected void spawnTamingParticles(boolean tamed) { +- ParticleOptions particleOptions = tamed ? ParticleTypes.HEART : ParticleTypes.SMOKE; ++ SimpleParticleType particletype = tamed ? ParticleTypes.HEART : ParticleTypes.SMOKE; + +- for (int i = 0; i < 7; i++) { +- double d = this.random.nextGaussian() * 0.02; +- double d1 = this.random.nextGaussian() * 0.02; +- double d2 = this.random.nextGaussian() * 0.02; +- this.level().addParticle(particleOptions, this.getRandomX(1.0), this.getRandomY() + 0.5, this.getRandomZ(1.0), d, d1, d2); ++ for (int i = 0; i < 7; ++i) { ++ double d0 = this.random.nextGaussian() * 0.02D; ++ double d1 = this.random.nextGaussian() * 0.02D; ++ double d2 = this.random.nextGaussian() * 0.02D; ++ ++ this.level().addParticle(particletype, this.getRandomX(1.0D), this.getRandomY() + 0.5D, this.getRandomZ(1.0D), d0, d1, d2); + } ++ + } + + @Override +@@ -976,26 +1037,28 @@ + } else { + super.handleEntityEvent(id); + } ++ + } + + @Override + protected void positionRider(Entity passenger, Entity.MoveFunction callback) { + super.positionRider(passenger, callback); + if (passenger instanceof LivingEntity) { +- ((LivingEntity)passenger).yBodyRot = this.yBodyRot; ++ ((LivingEntity) passenger).yBodyRot = this.yBodyRot; + } ++ + } + + protected static float generateMaxHealth(IntUnaryOperator operator) { +- return 15.0F + (float)operator.applyAsInt(8) + (float)operator.applyAsInt(9); ++ return 15.0F + (float) operator.applyAsInt(8) + (float) operator.applyAsInt(9); + } + + protected static double generateJumpStrength(DoubleSupplier supplier) { +- return 0.4F + supplier.getAsDouble() * 0.2 + supplier.getAsDouble() * 0.2 + supplier.getAsDouble() * 0.2; ++ return 0.4000000059604645D + supplier.getAsDouble() * 0.2D + supplier.getAsDouble() * 0.2D + supplier.getAsDouble() * 0.2D; + } + + protected static double generateSpeed(DoubleSupplier supplier) { +- return (0.45F + supplier.getAsDouble() * 0.3 + supplier.getAsDouble() * 0.3 + supplier.getAsDouble() * 0.3) * 0.25; ++ return (0.44999998807907104D + supplier.getAsDouble() * 0.3D + supplier.getAsDouble() * 0.3D + supplier.getAsDouble() * 0.3D) * 0.25D; + } + + @Override +@@ -1004,7 +1067,7 @@ + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return size.height * 0.95F; + } + +@@ -1042,32 +1105,41 @@ + + @Override + public SlotAccess getSlot(int slot) { +- int i = slot - 400; +- if (i >= 0 && i < 2 && i < this.inventory.getContainerSize()) { +- if (i == 0) { +- return this.createEquipmentSlotAccess(i, itemStack -> itemStack.isEmpty() || itemStack.is(Items.SADDLE)); ++ int j = slot - 400; ++ ++ if (j >= 0 && j < 2 && j < this.inventory.getContainerSize()) { ++ if (j == 0) { ++ return this.createEquipmentSlotAccess(j, (itemstack) -> { ++ return itemstack.isEmpty() || itemstack.is(Items.SADDLE); ++ }); + } + +- if (i == 1) { ++ if (j == 1) { + if (!this.canWearArmor()) { + return SlotAccess.NULL; + } + +- return this.createEquipmentSlotAccess(i, itemStack -> itemStack.isEmpty() || this.isArmor(itemStack)); ++ return this.createEquipmentSlotAccess(j, (itemstack) -> { ++ return itemstack.isEmpty() || this.isArmor(itemstack); ++ }); + } + } + +- int i1 = slot - 500 + 2; +- return i1 >= 2 && i1 < this.inventory.getContainerSize() ? SlotAccess.forContainer(this.inventory, i1) : super.getSlot(slot); ++ int k = slot - 500 + 2; ++ ++ return k >= 2 && k < this.inventory.getContainerSize() ? SlotAccess.forContainer(this.inventory, k) : super.getSlot(slot); + } + + @Nullable + @Override + public LivingEntity getControllingPassenger() { + if (this.isSaddled()) { +- Entity var2 = this.getFirstPassenger(); +- if (var2 instanceof Player) { +- return (Player)var2; ++ Entity entity = this.getFirstPassenger(); ++ ++ if (entity instanceof Player) { ++ Player entityhuman = (Player) entity; ++ ++ return entityhuman; + } + } + +@@ -1076,32 +1148,40 @@ + + @Nullable + private Vec3 getDismountLocationInDirection(Vec3 direction, LivingEntity passenger) { +- double d = this.getX() + direction.x; ++ double d0 = this.getX() + direction.x; + double d1 = this.getBoundingBox().minY; + double d2 = this.getZ() + direction.z; +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ UnmodifiableIterator unmodifiableiterator = passenger.getDismountPoses().iterator(); + +- for (Pose pose : passenger.getDismountPoses()) { +- mutableBlockPos.set(d, d1, d2); +- double d3 = this.getBoundingBox().maxY + 0.75; ++ while (unmodifiableiterator.hasNext()) { ++ EntityPose entitypose = (EntityPose) unmodifiableiterator.next(); + +- do { +- double blockFloorHeight = this.level().getBlockFloorHeight(mutableBlockPos); +- if ((double)mutableBlockPos.getY() + blockFloorHeight > d3) { ++ blockposition_mutableblockposition.set(d0, d1, d2); ++ double d3 = this.getBoundingBox().maxY + 0.75D; ++ ++ while (true) { ++ double d4 = this.level().getBlockFloorHeight(blockposition_mutableblockposition); ++ ++ if ((double) blockposition_mutableblockposition.getY() + d4 > d3) { + break; + } + +- if (DismountHelper.isBlockFloorValid(blockFloorHeight)) { +- AABB localBoundsForPose = passenger.getLocalBoundsForPose(pose); +- Vec3 vec3 = new Vec3(d, (double)mutableBlockPos.getY() + blockFloorHeight, d2); +- if (DismountHelper.canDismountTo(this.level(), passenger, localBoundsForPose.move(vec3))) { +- passenger.setPose(pose); +- return vec3; ++ if (DismountHelper.isBlockFloorValid(d4)) { ++ AABB axisalignedbb = passenger.getLocalBoundsForPose(entitypose); ++ Vec3 vec3d1 = new Vec3(d0, (double) blockposition_mutableblockposition.getY() + d4, d2); ++ ++ if (DismountHelper.canDismountTo(this.level(), passenger, axisalignedbb.move(vec3d1))) { ++ passenger.setPose(entitypose); ++ return vec3d1; + } + } + +- mutableBlockPos.move(Direction.UP); +- } while (!((double)mutableBlockPos.getY() < d3)); ++ blockposition_mutableblockposition.move(Direction.UP); ++ if ((double) blockposition_mutableblockposition.getY() >= d3) { ++ break; ++ } ++ } + } + + return null; +@@ -1109,35 +1189,30 @@ + + @Override + public Vec3 getDismountLocationForPassenger(LivingEntity livingEntity) { +- Vec3 collisionHorizontalEscapeVector = getCollisionHorizontalEscapeVector( +- (double)this.getBbWidth(), (double)livingEntity.getBbWidth(), this.getYRot() + (livingEntity.getMainArm() == HumanoidArm.RIGHT ? 90.0F : -90.0F) +- ); +- Vec3 dismountLocationInDirection = this.getDismountLocationInDirection(collisionHorizontalEscapeVector, livingEntity); +- if (dismountLocationInDirection != null) { +- return dismountLocationInDirection; ++ Vec3 vec3d = getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingEntity.getBbWidth(), this.getYRot() + (livingEntity.getMainArm() == HumanoidArm.RIGHT ? 90.0F : -90.0F)); ++ Vec3 vec3d1 = this.getDismountLocationInDirection(vec3d, livingEntity); ++ ++ if (vec3d1 != null) { ++ return vec3d1; + } else { +- Vec3 collisionHorizontalEscapeVector1 = getCollisionHorizontalEscapeVector( +- (double)this.getBbWidth(), (double)livingEntity.getBbWidth(), this.getYRot() + (livingEntity.getMainArm() == HumanoidArm.LEFT ? 90.0F : -90.0F) +- ); +- Vec3 dismountLocationInDirection1 = this.getDismountLocationInDirection(collisionHorizontalEscapeVector1, livingEntity); +- return dismountLocationInDirection1 != null ? dismountLocationInDirection1 : this.position(); ++ Vec3 vec3d2 = getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingEntity.getBbWidth(), this.getYRot() + (livingEntity.getMainArm() == HumanoidArm.LEFT ? 90.0F : -90.0F)); ++ Vec3 vec3d3 = this.getDismountLocationInDirection(vec3d2, livingEntity); ++ ++ return vec3d3 != null ? vec3d3 : this.position(); + } + } + +- protected void randomizeAttributes(RandomSource random) { +- } ++ protected void randomizeAttributes(RandomSource random) {} + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + if (spawnData == null) { + spawnData = new AgeableMob.AgeableMobGroupData(0.2F); + } + + this.randomizeAttributes(level.getRandom()); +- return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + + public boolean hasInventoryChanged(Container inventory) { +@@ -1149,11 +1224,11 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, this.getPassengersRidingOffsetY(entityDimensions, f) + 0.15F * this.standAnimO * f, -0.7F * this.standAnimO * f); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, this.getPassengersRidingOffsetY(entitysize, f) + 0.15F * this.standAnimO * f, -0.7F * this.standAnimO * f); + } + +- protected float getPassengersRidingOffsetY(EntityDimensions entityDimensions, float f) { +- return entityDimensions.height + (this.isBaby() ? 0.125F : -0.15625F) * f; ++ protected float getPassengersRidingOffsetY(EntityDimensions entitysize, float f) { ++ return entitysize.height + (this.isBaby() ? 0.125F : -0.15625F) * f; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/horse/Llama.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/horse/Llama.java.patch new file mode 100644 index 0000000000..a4cd6b7810 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/horse/Llama.java.patch @@ -0,0 +1,532 @@ +--- a/net/minecraft/world/entity/animal/horse/Llama.java ++++ b/net/minecraft/world/entity/animal/horse/Llama.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.entity.animal.horse; + + import com.mojang.serialization.Codec; ++import java.util.Iterator; + import java.util.function.IntFunction; + import javax.annotation.Nullable; + import net.minecraft.Util; +@@ -24,9 +25,10 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; ++import net.minecraft.world.entity.Mob; + import net.minecraft.world.entity.VariantHolder; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -57,11 +59,12 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.WoolCarpetBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + + public class Llama extends AbstractChestedHorse implements VariantHolder, RangedAttackMob { ++ + private static final int MAX_STRENGTH = 5; + private static final Ingredient FOOD_ITEMS = Ingredient.of(Items.WHEAT, Blocks.HAY_BLOCK.asItem()); + private static final EntityDataAccessor DATA_STRENGTH_ID = SynchedEntityData.defineId(Llama.class, EntityDataSerializers.INT); +@@ -81,17 +84,23 @@ + return false; + } + ++ // CraftBukkit start ++ public void setStrengthPublic(int i) { ++ this.setStrength(i); ++ } ++ // CraftBukkit end + private void setStrength(int strength) { +- this.entityData.set(DATA_STRENGTH_ID, Math.max(1, Math.min(5, strength))); ++ this.entityData.set(Llama.DATA_STRENGTH_ID, Math.max(1, Math.min(5, strength))); + } + + private void setRandomStrength(RandomSource random) { + int i = random.nextFloat() < 0.04F ? 5 : 3; ++ + this.setStrength(1 + random.nextInt(i)); + } + + public int getStrength() { +- return this.entityData.get(DATA_STRENGTH_ID); ++ return (Integer) this.entityData.get(Llama.DATA_STRENGTH_ID); + } + + @Override +@@ -102,6 +111,7 @@ + if (!this.inventory.getItem(1).isEmpty()) { + compound.put("DecorItem", this.inventory.getItem(1).save(new CompoundTag())); + } ++ + } + + @Override +@@ -119,14 +129,14 @@ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); +- this.goalSelector.addGoal(1, new RunAroundLikeCrazyGoal(this, 1.2)); +- this.goalSelector.addGoal(2, new LlamaFollowCaravanGoal(this, 2.1F)); +- this.goalSelector.addGoal(3, new RangedAttackGoal(this, 1.25, 40, 20.0F)); +- this.goalSelector.addGoal(3, new PanicGoal(this, 1.2)); +- this.goalSelector.addGoal(4, new BreedGoal(this, 1.0)); +- this.goalSelector.addGoal(5, new TemptGoal(this, 1.25, Ingredient.of(Items.HAY_BLOCK), false)); +- this.goalSelector.addGoal(6, new FollowParentGoal(this, 1.0)); +- this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 0.7)); ++ this.goalSelector.addGoal(1, new RunAroundLikeCrazyGoal(this, 1.2D)); ++ this.goalSelector.addGoal(2, new LlamaFollowCaravanGoal(this, 2.0999999046325684D)); ++ this.goalSelector.addGoal(3, new RangedAttackGoal(this, 1.25D, 40, 20.0F)); ++ this.goalSelector.addGoal(3, new PanicGoal(this, 1.2D)); ++ this.goalSelector.addGoal(4, new BreedGoal(this, 1.0D)); ++ this.goalSelector.addGoal(5, new TemptGoal(this, 1.25D, Ingredient.of(Items.HAY_BLOCK), false)); ++ this.goalSelector.addGoal(6, new FollowParentGoal(this, 1.0D)); ++ this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 0.7D)); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(9, new RandomLookAroundGoal(this)); + this.targetSelector.addGoal(1, new Llama.LlamaHurtByTargetGoal(this)); +@@ -134,25 +144,24 @@ + } + + public static AttributeSupplier.Builder createAttributes() { +- return createBaseChestedHorseAttributes().add(Attributes.FOLLOW_RANGE, 40.0); ++ return createBaseChestedHorseAttributes().add(Attributes.FOLLOW_RANGE, 40.0D); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_STRENGTH_ID, 0); +- this.entityData.define(DATA_SWAG_ID, -1); +- this.entityData.define(DATA_VARIANT_ID, 0); ++ this.entityData.define(Llama.DATA_STRENGTH_ID, 0); ++ this.entityData.define(Llama.DATA_SWAG_ID, -1); ++ this.entityData.define(Llama.DATA_VARIANT_ID, 0); + } + + @Override + public Llama.Variant getVariant() { +- return Llama.Variant.byId(this.entityData.get(DATA_VARIANT_ID)); ++ return Llama.Variant.byId((Integer) this.entityData.get(Llama.DATA_VARIANT_ID)); + } + +- @Override + public void setVariant(Llama.Variant variant) { +- this.entityData.set(DATA_VARIANT_ID, variant.id); ++ this.entityData.set(Llama.DATA_VARIANT_ID, variant.id); + } + + @Override +@@ -162,22 +171,23 @@ + + @Override + public boolean isFood(ItemStack stack) { +- return FOOD_ITEMS.test(stack); ++ return Llama.FOOD_ITEMS.test(stack); + } + + @Override + protected boolean handleEating(Player player, ItemStack stack) { +- int i = 0; +- int i1 = 0; ++ byte b0 = 0; ++ byte b1 = 0; + float f = 0.0F; + boolean flag = false; ++ + if (stack.is(Items.WHEAT)) { +- i = 10; +- i1 = 3; ++ b0 = 10; ++ b1 = 3; + f = 2.0F; + } else if (stack.is(Blocks.HAY_BLOCK.asItem())) { +- i = 90; +- i1 = 6; ++ b0 = 90; ++ b1 = 6; + f = 10.0F; + if (this.isTamed() && this.getAge() == 0 && this.canFallInLove()) { + flag = true; +@@ -190,36 +200,27 @@ + flag = true; + } + +- if (this.isBaby() && i > 0) { +- this.level().addParticle(ParticleTypes.HAPPY_VILLAGER, this.getRandomX(1.0), this.getRandomY() + 0.5, this.getRandomZ(1.0), 0.0, 0.0, 0.0); ++ if (this.isBaby() && b0 > 0) { ++ this.level().addParticle(ParticleTypes.HAPPY_VILLAGER, this.getRandomX(1.0D), this.getRandomY() + 0.5D, this.getRandomZ(1.0D), 0.0D, 0.0D, 0.0D); + if (!this.level().isClientSide) { +- this.ageUp(i); ++ this.ageUp(b0); + } + + flag = true; + } + +- if (i1 > 0 && (flag || !this.isTamed()) && this.getTemper() < this.getMaxTemper()) { ++ if (b1 > 0 && (flag || !this.isTamed()) && this.getTemper() < this.getMaxTemper()) { + flag = true; + if (!this.level().isClientSide) { +- this.modifyTemper(i1); ++ this.modifyTemper(b1); + } + } + + if (flag && !this.isSilent()) { +- SoundEvent eatingSound = this.getEatingSound(); +- if (eatingSound != null) { +- this.level() +- .playSound( +- null, +- this.getX(), +- this.getY(), +- this.getZ(), +- this.getEatingSound(), +- this.getSoundSource(), +- 1.0F, +- 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F +- ); ++ SoundEvent soundeffect = this.getEatingSound(); ++ ++ if (soundeffect != null) { ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), this.getEatingSound(), this.getSoundSource(), 1.0F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F); + } + } + +@@ -233,21 +234,21 @@ + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- RandomSource random = level.getRandom(); +- this.setRandomStrength(random); +- Llama.Variant variant; ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ RandomSource randomsource = level.getRandom(); ++ ++ this.setRandomStrength(randomsource); ++ Llama.Variant entityllama_variant; ++ + if (spawnData instanceof Llama.LlamaGroupData) { +- variant = ((Llama.LlamaGroupData)spawnData).variant; ++ entityllama_variant = ((Llama.LlamaGroupData) spawnData).variant; + } else { +- variant = Util.getRandom(Llama.Variant.values(), random); +- spawnData = new Llama.LlamaGroupData(variant); ++ entityllama_variant = (Llama.Variant) Util.getRandom((Object[]) Llama.Variant.values(), randomsource); ++ spawnData = new Llama.LlamaGroupData(entityllama_variant); + } + +- this.setVariant(variant); +- return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ this.setVariant(entityllama_variant); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + + @Override +@@ -282,7 +283,7 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.LLAMA_STEP, 0.15F, 1.0F); + } + +@@ -318,12 +319,15 @@ + + @Override + public void containerChanged(Container invBasic) { +- DyeColor swag = this.getSwag(); ++ DyeColor enumcolor = this.getSwag(); ++ + super.containerChanged(invBasic); +- DyeColor swag1 = this.getSwag(); +- if (this.tickCount > 20 && swag1 != null && swag1 != swag) { ++ DyeColor enumcolor1 = this.getSwag(); ++ ++ if (this.tickCount > 20 && enumcolor1 != null && enumcolor1 != enumcolor) { + this.playSound(SoundEvents.LLAMA_SWAG, 0.5F, 1.0F); + } ++ + } + + @Override +@@ -335,18 +339,20 @@ + } + + private void setSwag(@Nullable DyeColor color) { +- this.entityData.set(DATA_SWAG_ID, color == null ? -1 : color.getId()); ++ this.entityData.set(Llama.DATA_SWAG_ID, color == null ? -1 : color.getId()); + } + + @Nullable + private static DyeColor getDyeColor(ItemStack stack) { + Block block = Block.byItem(stack.getItem()); +- return block instanceof WoolCarpetBlock ? ((WoolCarpetBlock)block).getColor() : null; ++ ++ return block instanceof WoolCarpetBlock ? ((WoolCarpetBlock) block).getColor() : null; + } + + @Nullable + public DyeColor getSwag() { +- int i = this.entityData.get(DATA_SWAG_ID); ++ int i = (Integer) this.entityData.get(Llama.DATA_SWAG_ID); ++ + return i == -1 ? null : DyeColor.byId(i); + } + +@@ -357,55 +363,48 @@ + + @Override + public boolean canMate(Animal otherAnimal) { +- return otherAnimal != this && otherAnimal instanceof Llama && this.canParent() && ((Llama)otherAnimal).canParent(); ++ return otherAnimal != this && otherAnimal instanceof Llama && this.canParent() && ((Llama) otherAnimal).canParent(); + } + + @Nullable + @Override + public Llama getBreedOffspring(ServerLevel level, AgeableMob otherParent) { +- Llama llama = this.makeNewLlama(); +- if (llama != null) { +- this.setOffspringAttributes(otherParent, llama); +- Llama llama1 = (Llama)otherParent; +- int i = this.random.nextInt(Math.max(this.getStrength(), llama1.getStrength())) + 1; ++ Llama entityllama = this.makeNewLlama(); ++ ++ if (entityllama != null) { ++ this.setOffspringAttributes(otherParent, entityllama); ++ Llama entityllama1 = (Llama) otherParent; ++ int i = this.random.nextInt(Math.max(this.getStrength(), entityllama1.getStrength())) + 1; ++ + if (this.random.nextFloat() < 0.03F) { +- i++; ++ ++i; + } + +- llama.setStrength(i); +- llama.setVariant(this.random.nextBoolean() ? this.getVariant() : llama1.getVariant()); ++ entityllama.setStrength(i); ++ entityllama.setVariant(this.random.nextBoolean() ? this.getVariant() : entityllama1.getVariant()); + } + +- return llama; ++ return entityllama; + } + + @Nullable + protected Llama makeNewLlama() { +- return EntityType.LLAMA.create(this.level()); ++ return (Llama) EntityType.LLAMA.create(this.level()); + } + + private void spit(LivingEntity target) { +- LlamaSpit llamaSpit = new LlamaSpit(this.level(), this); +- double d = target.getX() - this.getX(); +- double d1 = target.getY(0.3333333333333333) - llamaSpit.getY(); ++ LlamaSpit entityllamaspit = new LlamaSpit(this.level(), this); ++ double d0 = target.getX() - this.getX(); ++ double d1 = target.getY(0.3333333333333333D) - entityllamaspit.getY(); + double d2 = target.getZ() - this.getZ(); +- double d3 = Math.sqrt(d * d + d2 * d2) * 0.2F; +- llamaSpit.shoot(d, d1 + d3, d2, 1.5F, 10.0F); ++ double d3 = Math.sqrt(d0 * d0 + d2 * d2) * 0.20000000298023224D; ++ ++ entityllamaspit.shoot(d0, d1 + d3, d2, 1.5F, 10.0F); + if (!this.isSilent()) { +- this.level() +- .playSound( +- null, +- this.getX(), +- this.getY(), +- this.getZ(), +- SoundEvents.LLAMA_SPIT, +- this.getSoundSource(), +- 1.0F, +- 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F +- ); ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.LLAMA_SPIT, this.getSoundSource(), 1.0F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F); + } + +- this.level().addFreshEntity(llamaSpit); ++ this.level().addFreshEntity(entityllamaspit); + this.didSpit = true; + } + +@@ -416,14 +415,19 @@ + @Override + public boolean causeFallDamage(float fallDistance, float multiplier, DamageSource source) { + int i = this.calculateFallDamage(fallDistance, multiplier); ++ + if (i <= 0) { + return false; + } else { + if (fallDistance >= 6.0F) { +- this.hurt(source, (float)i); ++ this.hurt(source, (float) i); + if (this.isVehicle()) { +- for (Entity entity : this.getIndirectPassengers()) { +- entity.hurt(source, (float)i); ++ Iterator iterator = this.getIndirectPassengers().iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ ++ entity.hurt(source, (float) i); + } + } + } +@@ -461,7 +465,7 @@ + + @Override + protected double followLeashSpeed() { +- return 2.0; ++ return 2.0D; + } + + @Override +@@ -469,6 +473,7 @@ + if (!this.inCaravan() && this.isBaby()) { + super.followMommy(); + } ++ + } + + @Override +@@ -483,77 +488,86 @@ + + @Override + public Vec3 getLeashOffset() { +- return new Vec3(0.0, 0.75 * (double)this.getEyeHeight(), (double)this.getBbWidth() * 0.5); ++ return new Vec3(0.0D, 0.75D * (double) this.getEyeHeight(), (double) this.getBbWidth() * 0.5D); + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height - (this.isBaby() ? 0.8125F : 0.5F) * f, -0.3F * f); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - (this.isBaby() ? 0.8125F : 0.5F) * f, -0.3F * f); + } + +- static class LlamaAttackWolfGoal extends NearestAttackableTargetGoal { +- public LlamaAttackWolfGoal(Llama llama) { +- super(llama, Wolf.class, 16, false, true, entity -> !((Wolf)entity).isTame()); ++ public static enum Variant implements StringRepresentable { ++ ++ CREAMY(0, "creamy"), WHITE(1, "white"), BROWN(2, "brown"), GRAY(3, "gray"); ++ ++ public static final Codec CODEC = StringRepresentable.fromEnum(Llama.Variant::values); ++ private static final IntFunction BY_ID = ByIdMap.continuous(Llama.Variant::getId, values(), ByIdMap.a.CLAMP); ++ final int id; ++ private final String name; ++ ++ private Variant(int i, String s) { ++ this.id = i; ++ this.name = s; + } + +- @Override +- protected double getFollowDistance() { +- return super.getFollowDistance() * 0.25; ++ public int getId() { ++ return this.id; + } +- } + +- static class LlamaGroupData extends AgeableMob.AgeableMobGroupData { +- public final Llama.Variant variant; ++ public static Llama.Variant byId(int id) { ++ return (Llama.Variant) Llama.Variant.BY_ID.apply(id); ++ } + +- LlamaGroupData(Llama.Variant variant) { +- super(true); +- this.variant = variant; ++ @Override ++ public String getSerializedName() { ++ return this.name; + } + } + +- static class LlamaHurtByTargetGoal extends HurtByTargetGoal { ++ private static class LlamaHurtByTargetGoal extends HurtByTargetGoal { ++ + public LlamaHurtByTargetGoal(Llama llama) { + super(llama); + } + + @Override + public boolean canContinueToUse() { +- if (this.mob instanceof Llama llama && llama.didSpit) { +- llama.setDidSpit(false); +- return false; ++ Mob entityinsentient = this.mob; ++ ++ if (entityinsentient instanceof Llama) { ++ Llama entityllama = (Llama) entityinsentient; ++ ++ if (entityllama.didSpit) { ++ entityllama.setDidSpit(false); ++ return false; ++ } + } + + return super.canContinueToUse(); + } + } + +- public static enum Variant implements StringRepresentable { +- CREAMY(0, "creamy"), +- WHITE(1, "white"), +- BROWN(2, "brown"), +- GRAY(3, "gray"); ++ private static class LlamaAttackWolfGoal extends NearestAttackableTargetGoal { + +- public static final Codec CODEC = StringRepresentable.fromEnum(Llama.Variant::values); +- private static final IntFunction BY_ID = ByIdMap.continuous(Llama.Variant::getId, values(), ByIdMap.OutOfBoundsStrategy.CLAMP); +- final int id; +- private final String name; +- +- private Variant(int id, String name) { +- this.id = id; +- this.name = name; ++ public LlamaAttackWolfGoal(Llama llama) { ++ super(llama, Wolf.class, 16, false, true, (entityliving) -> { ++ return !((Wolf) entityliving).isTame(); ++ }); + } + +- public int getId() { +- return this.id; ++ @Override ++ protected double getFollowDistance() { ++ return super.getFollowDistance() * 0.25D; + } ++ } + +- public static Llama.Variant byId(int id) { +- return BY_ID.apply(id); +- } ++ private static class LlamaGroupData extends AgeableMob.AgeableMobGroupData { + +- @Override +- public String getSerializedName() { +- return this.name; ++ public final Llama.Variant variant; ++ ++ LlamaGroupData(Llama.Variant variant) { ++ super(true); ++ this.variant = variant; + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java.patch new file mode 100644 index 0000000000..522f9e8144 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java.patch @@ -0,0 +1,164 @@ +--- a/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java ++++ b/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java +@@ -1,12 +1,14 @@ + package net.minecraft.world.entity.animal.horse; + + import javax.annotation.Nullable; ++import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.DifficultyInstance; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LightningBolt; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.ai.goal.Goal; + import net.minecraft.world.entity.monster.Skeleton; + import net.minecraft.world.item.ItemStack; +@@ -14,6 +16,7 @@ + import net.minecraft.world.item.enchantment.EnchantmentHelper; + + public class SkeletonTrapGoal extends Goal { ++ + private final SkeletonHorse horse; + + public SkeletonTrapGoal(SkeletonHorse horse) { +@@ -22,89 +25,81 @@ + + @Override + public boolean canUse() { +- return this.horse.level().hasNearbyAlivePlayer(this.horse.getX(), this.horse.getY(), this.horse.getZ(), 10.0); ++ return this.horse.level().hasNearbyAlivePlayer(this.horse.getX(), this.horse.getY(), this.horse.getZ(), 10.0D); + } + + @Override + public void tick() { +- ServerLevel serverLevel = (ServerLevel)this.horse.level(); +- DifficultyInstance currentDifficultyAt = serverLevel.getCurrentDifficultyAt(this.horse.blockPosition()); ++ ServerLevel worldserver = (ServerLevel) this.horse.level(); ++ DifficultyInstance difficultydamagescaler = worldserver.getCurrentDifficultyAt(this.horse.blockPosition()); ++ + this.horse.setTrap(false); + this.horse.setTamed(true); + this.horse.setAge(0); +- LightningBolt lightningBolt = EntityType.LIGHTNING_BOLT.create(serverLevel); +- if (lightningBolt != null) { +- lightningBolt.moveTo(this.horse.getX(), this.horse.getY(), this.horse.getZ()); +- lightningBolt.setVisualOnly(true); +- serverLevel.addFreshEntity(lightningBolt); +- Skeleton skeleton = this.createSkeleton(currentDifficultyAt, this.horse); +- if (skeleton != null) { +- skeleton.startRiding(this.horse); +- serverLevel.addFreshEntityWithPassengers(skeleton); ++ LightningBolt entitylightning = (LightningBolt) EntityType.LIGHTNING_BOLT.create(worldserver); + +- for (int i = 0; i < 3; i++) { +- AbstractHorse abstractHorse = this.createHorse(currentDifficultyAt); +- if (abstractHorse != null) { +- Skeleton skeleton1 = this.createSkeleton(currentDifficultyAt, abstractHorse); +- if (skeleton1 != null) { +- skeleton1.startRiding(abstractHorse); +- abstractHorse.push(this.horse.getRandom().triangle(0.0, 1.1485), 0.0, this.horse.getRandom().triangle(0.0, 1.1485)); +- serverLevel.addFreshEntityWithPassengers(abstractHorse); ++ if (entitylightning != null) { ++ entitylightning.moveTo(this.horse.getX(), this.horse.getY(), this.horse.getZ()); ++ entitylightning.setVisualOnly(true); ++ worldserver.strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.TRAP); // CraftBukkit ++ Skeleton entityskeleton = this.createSkeleton(difficultydamagescaler, this.horse); ++ ++ if (entityskeleton != null) { ++ entityskeleton.startRiding(this.horse); ++ worldserver.addFreshEntityWithPassengers(entityskeleton, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.TRAP); // CraftBukkit ++ ++ for (int i = 0; i < 3; ++i) { ++ AbstractHorse entityhorseabstract = this.createHorse(difficultydamagescaler); ++ ++ if (entityhorseabstract != null) { ++ Skeleton entityskeleton1 = this.createSkeleton(difficultydamagescaler, entityhorseabstract); ++ ++ if (entityskeleton1 != null) { ++ entityskeleton1.startRiding(entityhorseabstract); ++ entityhorseabstract.push(this.horse.getRandom().triangle(0.0D, 1.1485D), 0.0D, this.horse.getRandom().triangle(0.0D, 1.1485D)); ++ worldserver.addFreshEntityWithPassengers(entityhorseabstract, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.JOCKEY); // CraftBukkit + } + } + } ++ + } + } + } + + @Nullable + private AbstractHorse createHorse(DifficultyInstance difficulty) { +- SkeletonHorse skeletonHorse = EntityType.SKELETON_HORSE.create(this.horse.level()); +- if (skeletonHorse != null) { +- skeletonHorse.finalizeSpawn((ServerLevel)this.horse.level(), difficulty, MobSpawnType.TRIGGERED, null, null); +- skeletonHorse.setPos(this.horse.getX(), this.horse.getY(), this.horse.getZ()); +- skeletonHorse.invulnerableTime = 60; +- skeletonHorse.setPersistenceRequired(); +- skeletonHorse.setTamed(true); +- skeletonHorse.setAge(0); ++ SkeletonHorse entityhorseskeleton = (SkeletonHorse) EntityType.SKELETON_HORSE.create(this.horse.level()); ++ ++ if (entityhorseskeleton != null) { ++ entityhorseskeleton.finalizeSpawn((ServerLevel) this.horse.level(), difficulty, EnumMobSpawn.TRIGGERED, (GroupDataEntity) null, (CompoundTag) null); ++ entityhorseskeleton.setPos(this.horse.getX(), this.horse.getY(), this.horse.getZ()); ++ entityhorseskeleton.invulnerableTime = 60; ++ entityhorseskeleton.setPersistenceRequired(); ++ entityhorseskeleton.setTamed(true); ++ entityhorseskeleton.setAge(0); + } + +- return skeletonHorse; ++ return entityhorseskeleton; + } + + @Nullable + private Skeleton createSkeleton(DifficultyInstance difficulty, AbstractHorse horse) { +- Skeleton skeleton = EntityType.SKELETON.create(horse.level()); +- if (skeleton != null) { +- skeleton.finalizeSpawn((ServerLevel)horse.level(), difficulty, MobSpawnType.TRIGGERED, null, null); +- skeleton.setPos(horse.getX(), horse.getY(), horse.getZ()); +- skeleton.invulnerableTime = 60; +- skeleton.setPersistenceRequired(); +- if (skeleton.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { +- skeleton.setItemSlot(EquipmentSlot.HEAD, new ItemStack(Items.IRON_HELMET)); ++ Skeleton entityskeleton = (Skeleton) EntityType.SKELETON.create(horse.level()); ++ ++ if (entityskeleton != null) { ++ entityskeleton.finalizeSpawn((ServerLevel) horse.level(), difficulty, EnumMobSpawn.TRIGGERED, (GroupDataEntity) null, (CompoundTag) null); ++ entityskeleton.setPos(horse.getX(), horse.getY(), horse.getZ()); ++ entityskeleton.invulnerableTime = 60; ++ entityskeleton.setPersistenceRequired(); ++ if (entityskeleton.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { ++ entityskeleton.setItemSlot(EquipmentSlot.HEAD, new ItemStack(Items.IRON_HELMET)); + } + +- skeleton.setItemSlot( +- EquipmentSlot.MAINHAND, +- EnchantmentHelper.enchantItem( +- skeleton.getRandom(), +- this.disenchant(skeleton.getMainHandItem()), +- (int)(5.0F + difficulty.getSpecialMultiplier() * (float)skeleton.getRandom().nextInt(18)), +- false +- ) +- ); +- skeleton.setItemSlot( +- EquipmentSlot.HEAD, +- EnchantmentHelper.enchantItem( +- skeleton.getRandom(), +- this.disenchant(skeleton.getItemBySlot(EquipmentSlot.HEAD)), +- (int)(5.0F + difficulty.getSpecialMultiplier() * (float)skeleton.getRandom().nextInt(18)), +- false +- ) +- ); ++ entityskeleton.setItemSlot(EquipmentSlot.MAINHAND, EnchantmentHelper.enchantItem(entityskeleton.getRandom(), this.disenchant(entityskeleton.getMainHandItem()), (int) (5.0F + difficulty.getSpecialMultiplier() * (float) entityskeleton.getRandom().nextInt(18)), false)); ++ entityskeleton.setItemSlot(EquipmentSlot.HEAD, EnchantmentHelper.enchantItem(entityskeleton.getRandom(), this.disenchant(entityskeleton.getItemBySlot(EquipmentSlot.HEAD)), (int) (5.0F + difficulty.getSpecialMultiplier() * (float) entityskeleton.getRandom().nextInt(18)), false)); + } + +- return skeleton; ++ return entityskeleton; + } + + private ItemStack disenchant(ItemStack stack) { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/horse/TraderLlama.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/horse/TraderLlama.java.patch new file mode 100644 index 0000000000..1d96edcab5 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/horse/TraderLlama.java.patch @@ -0,0 +1,150 @@ +--- a/net/minecraft/world/entity/animal/horse/TraderLlama.java ++++ b/net/minecraft/world/entity/animal/horse/TraderLlama.java +@@ -7,9 +7,9 @@ + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.goal.Goal; + import net.minecraft.world.entity.ai.goal.PanicGoal; + import net.minecraft.world.entity.ai.goal.target.TargetGoal; +@@ -20,6 +20,7 @@ + import net.minecraft.world.level.ServerLevelAccessor; + + public class TraderLlama extends Llama { ++ + private int despawnDelay = 47999; + + public TraderLlama(EntityType entityType, Level level) { +@@ -34,7 +35,7 @@ + @Nullable + @Override + protected Llama makeNewLlama() { +- return EntityType.TRADER_LLAMA.create(this.level()); ++ return (Llama) EntityType.TRADER_LLAMA.create(this.level()); + } + + @Override +@@ -49,12 +50,13 @@ + if (compound.contains("DespawnDelay", 99)) { + this.despawnDelay = compound.getInt("DespawnDelay"); + } ++ + } + + @Override + protected void registerGoals() { + super.registerGoals(); +- this.goalSelector.addGoal(1, new PanicGoal(this, 2.0)); ++ this.goalSelector.addGoal(1, new PanicGoal(this, 2.0D)); + this.targetSelector.addGoal(1, new TraderLlama.TraderLlamaDefendWanderingTraderGoal(this)); + } + +@@ -64,8 +66,9 @@ + + @Override + protected void doPlayerRide(Player player) { +- Entity leashHolder = this.getLeashHolder(); +- if (!(leashHolder instanceof WanderingTrader)) { ++ Entity entity = this.getLeashHolder(); ++ ++ if (!(entity instanceof WanderingTrader)) { + super.doPlayerRide(player); + } + } +@@ -76,15 +79,17 @@ + if (!this.level().isClientSide) { + this.maybeDespawn(); + } ++ + } + + private void maybeDespawn() { + if (this.canDespawn()) { +- this.despawnDelay = this.isLeashedToWanderingTrader() ? ((WanderingTrader)this.getLeashHolder()).getDespawnDelay() - 1 : this.despawnDelay - 1; ++ this.despawnDelay = this.isLeashedToWanderingTrader() ? ((WanderingTrader) this.getLeashHolder()).getDespawnDelay() - 1 : this.despawnDelay - 1; + if (this.despawnDelay <= 0) { + this.dropLeash(true, false); + this.discard(); + } ++ + } + } + +@@ -102,10 +107,8 @@ + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- if (reason == MobSpawnType.EVENT) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ if (reason == EnumMobSpawn.EVENT) { + this.setAge(0); + } + +@@ -113,10 +116,11 @@ + spawnData = new AgeableMob.AgeableMobGroupData(false); + } + +- return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + + protected static class TraderLlamaDefendWanderingTraderGoal extends TargetGoal { ++ + private final Llama llama; + private LivingEntity ownerLastHurtBy; + private int timestamp; +@@ -124,28 +128,36 @@ + public TraderLlamaDefendWanderingTraderGoal(Llama llama) { + super(llama, false); + this.llama = llama; +- this.setFlags(EnumSet.of(Goal.Flag.TARGET)); ++ this.setFlags(EnumSet.of(Goal.Type.TARGET)); + } + + @Override + public boolean canUse() { + if (!this.llama.isLeashed()) { + return false; +- } else if (!(this.llama.getLeashHolder() instanceof WanderingTrader wanderingTrader)) { +- return false; + } else { +- this.ownerLastHurtBy = wanderingTrader.getLastHurtByMob(); +- int lastHurtByMobTimestamp = wanderingTrader.getLastHurtByMobTimestamp(); +- return lastHurtByMobTimestamp != this.timestamp && this.canAttack(this.ownerLastHurtBy, TargetingConditions.DEFAULT); ++ Entity entity = this.llama.getLeashHolder(); ++ ++ if (!(entity instanceof WanderingTrader)) { ++ return false; ++ } else { ++ WanderingTrader entityvillagertrader = (WanderingTrader) entity; ++ ++ this.ownerLastHurtBy = entityvillagertrader.getLastHurtByMob(); ++ int i = entityvillagertrader.getLastHurtByMobTimestamp(); ++ ++ return i != this.timestamp && this.canAttack(this.ownerLastHurtBy, TargetingConditions.DEFAULT); ++ } + } + } + + @Override + public void start() { +- this.mob.setTarget(this.ownerLastHurtBy); +- Entity leashHolder = this.llama.getLeashHolder(); +- if (leashHolder instanceof WanderingTrader) { +- this.timestamp = ((WanderingTrader)leashHolder).getLastHurtByMobTimestamp(); ++ this.mob.setTarget(this.ownerLastHurtBy, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_OWNER, true); // CraftBukkit ++ Entity entity = this.llama.getLeashHolder(); ++ ++ if (entity instanceof WanderingTrader) { ++ this.timestamp = ((WanderingTrader) entity).getLastHurtByMobTimestamp(); + } + + super.start(); diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/sniffer/Sniffer.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/sniffer/Sniffer.java.patch new file mode 100644 index 0000000000..992f78fc74 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/sniffer/Sniffer.java.patch @@ -0,0 +1,445 @@ +--- a/net/minecraft/world/entity/animal/sniffer/Sniffer.java ++++ b/net/minecraft/world/entity/animal/sniffer/Sniffer.java +@@ -2,6 +2,7 @@ + + import com.mojang.serialization.Dynamic; + import java.util.Collection; ++import java.util.Iterator; + import java.util.List; + import java.util.Objects; + import java.util.Optional; +@@ -24,16 +25,16 @@ + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.ItemTags; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.AnimationState; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -45,8 +46,8 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.RenderShape; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.EnumRenderType; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.level.pathfinder.Path; +@@ -60,6 +61,7 @@ + import org.joml.Vector3f; + + public class Sniffer extends Animal { ++ + private static final int DIGGING_PARTICLES_DELAY_TICKS = 1700; + private static final int DIGGING_PARTICLES_DURATION_TICKS = 6000; + private static final int DIGGING_PARTICLES_AMOUNT = 30; +@@ -76,21 +78,30 @@ + public final AnimationState risingAnimationState = new AnimationState(); + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.1F).add(Attributes.MAX_HEALTH, 14.0); ++ return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.10000000149011612D).add(Attributes.MAX_HEALTH, 14.0D); + } + + public Sniffer(EntityType entityType, Level level) { + super(entityType, level); +- this.entityData.define(DATA_STATE, Sniffer.State.IDLING); +- this.entityData.define(DATA_DROP_SEED_AT_TICK, 0); ++ // this.entityData.define(Sniffer.DATA_STATE, Sniffer.State.IDLING); // CraftBukkit - moved down to appropriate location ++ // this.entityData.define(Sniffer.DATA_DROP_SEED_AT_TICK, 0); // CraftBukkit - moved down to appropriate location + this.getNavigation().setCanFloat(true); + this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); + this.setPathfindingMalus(BlockPathTypes.DANGER_POWDER_SNOW, -1.0F); + this.setPathfindingMalus(BlockPathTypes.DAMAGE_CAUTIOUS, -1.0F); + } + ++ // CraftBukkit start - SPIGOT-7295: moved from constructor to appropriate location + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) { ++ protected void defineSynchedData() { ++ super.defineSynchedData(); ++ this.entityData.define(Sniffer.DATA_STATE, Sniffer.State.IDLING); ++ this.entityData.define(Sniffer.DATA_DROP_SEED_AT_TICK, 0); ++ } ++ // CraftBukkit end ++ ++ @Override ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions dimensions) { + return this.getDimensions(pose).height * 0.6F; + } + +@@ -100,6 +111,7 @@ + if (this.isOnFire() || this.isInWater()) { + this.setPathfindingMalus(BlockPathTypes.WATER, 0.0F); + } ++ + } + + @Override +@@ -108,10 +120,8 @@ + } + + @Override +- public EntityDimensions getDimensions(Pose pose) { +- return this.entityData.hasItem(DATA_STATE) && this.getState() == Sniffer.State.DIGGING +- ? DIGGING_DIMENSIONS.scale(this.getScale()) +- : super.getDimensions(pose); ++ public EntityDimensions getDimensions(EntityPose pose) { ++ return this.entityData.hasItem(Sniffer.DATA_STATE) && this.getState() == Sniffer.State.DIGGING ? Sniffer.DIGGING_DIMENSIONS.scale(this.getScale()) : super.getDimensions(pose); + } + + public boolean isSearching() { +@@ -119,7 +129,7 @@ + } + + public boolean isTempted() { +- return this.brain.getMemory(MemoryModuleType.IS_TEMPTED).orElse(false); ++ return (Boolean) this.brain.getMemory(MemoryModuleType.IS_TEMPTED).orElse(false); + } + + public boolean canSniff() { +@@ -131,29 +141,31 @@ + } + + private BlockPos getHeadBlock() { +- Vec3 headPosition = this.getHeadPosition(); +- return BlockPos.containing(headPosition.x(), this.getY() + 0.2F, headPosition.z()); ++ Vec3 vec3d = this.getHeadPosition(); ++ ++ return BlockPos.containing(vec3d.x(), this.getY() + 0.20000000298023224D, vec3d.z()); + } + + private Vec3 getHeadPosition() { +- return this.position().add(this.getForward().scale(2.25)); ++ return this.position().add(this.getForward().scale(2.25D)); + } + +- private Sniffer.State getState() { +- return this.entityData.get(DATA_STATE); ++ public Sniffer.State getState() { ++ return (Sniffer.State) this.entityData.get(Sniffer.DATA_STATE); + } + + private Sniffer setState(Sniffer.State state) { +- this.entityData.set(DATA_STATE, state); ++ this.entityData.set(Sniffer.DATA_STATE, state); + return this; + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { +- if (DATA_STATE.equals(key)) { +- Sniffer.State state = this.getState(); ++ if (Sniffer.DATA_STATE.equals(key)) { ++ Sniffer.State sniffer_state = this.getState(); ++ + this.resetAnimations(); +- switch (state) { ++ switch (sniffer_state) { + case SCENTING: + this.scentingAnimationState.startIfStopped(this.tickCount); + break; +@@ -220,8 +232,8 @@ + } + + private Sniffer onDiggingStart() { +- this.entityData.set(DATA_DROP_SEED_AT_TICK, this.tickCount + 120); +- this.level().broadcastEntityEvent(this, (byte)63); ++ this.entityData.set(Sniffer.DATA_DROP_SEED_AT_TICK, this.tickCount + 120); ++ this.level().broadcastEntityEvent(this, (byte) 63); + return this; + } + +@@ -233,48 +245,46 @@ + return this; + } + +- Optional calculateDigPosition() { +- return IntStream.range(0, 5) +- .mapToObj(i -> LandRandomPos.getPos(this, 10 + 2 * i, 3)) +- .filter(Objects::nonNull) +- .map(BlockPos::containing) +- .filter(blockPos -> this.level().getWorldBorder().isWithinBounds(blockPos)) +- .map(BlockPos::below) +- .filter(this::canDig) +- .findFirst(); ++ public Optional calculateDigPosition() { ++ return IntStream.range(0, 5).mapToObj((i) -> { ++ return LandRandomPos.getPos(this, 10 + 2 * i, 3); ++ }).filter(Objects::nonNull).map(BlockPos::containing).filter((blockposition) -> { ++ return this.level().getWorldBorder().isWithinBounds(blockposition); ++ }).map(BlockPos::below).filter(this::canDig).findFirst(); + } + +- boolean canDig() { +- return !this.isPanicking() +- && !this.isTempted() +- && !this.isBaby() +- && !this.isInWater() +- && this.onGround() +- && !this.isPassenger() +- && this.canDig(this.getHeadBlock().below()); ++ public boolean canDig() { ++ return !this.isPanicking() && !this.isTempted() && !this.isBaby() && !this.isInWater() && this.onGround() && !this.isPassenger() && this.canDig(this.getHeadBlock().below()); + } + + private boolean canDig(BlockPos pos) { +- return this.level().getBlockState(pos).is(BlockTags.SNIFFER_DIGGABLE_BLOCK) +- && this.getExploredPositions().noneMatch(globalPos -> GlobalPos.of(this.level().dimension(), pos).equals(globalPos)) +- && Optional.ofNullable(this.getNavigation().createPath(pos, 1)).map(Path::canReach).orElse(false); ++ return this.level().getBlockState(pos).is(BlockTags.SNIFFER_DIGGABLE_BLOCK) && this.getExploredPositions().noneMatch((globalpos) -> { ++ return GlobalPos.of(this.level().dimension(), pos).equals(globalpos); ++ }) && (Boolean) Optional.ofNullable(this.getNavigation().createPath(pos, 1)).map(Path::canReach).orElse(false); + } + + private void dropSeed() { +- if (!this.level().isClientSide() && this.entityData.get(DATA_DROP_SEED_AT_TICK) == this.tickCount) { +- ServerLevel serverLevel = (ServerLevel)this.level(); +- LootTable lootTable = serverLevel.getServer().getLootData().getLootTable(BuiltInLootTables.SNIFFER_DIGGING); +- LootParams lootParams = new LootParams.Builder(serverLevel) +- .withParameter(LootContextParams.ORIGIN, this.getHeadPosition()) +- .withParameter(LootContextParams.THIS_ENTITY, this) +- .create(LootContextParamSets.GIFT); +- List randomItems = lootTable.getRandomItems(lootParams); +- BlockPos headBlock = this.getHeadBlock(); ++ if (!this.level().isClientSide() && (Integer) this.entityData.get(Sniffer.DATA_DROP_SEED_AT_TICK) == this.tickCount) { ++ ServerLevel worldserver = (ServerLevel) this.level(); ++ LootTable loottable = worldserver.getServer().getLootData().getLootTable(BuiltInLootTables.SNIFFER_DIGGING); ++ LootParams lootparams = (new LootParams.Builder(worldserver)).withParameter(LootContextParams.ORIGIN, this.getHeadPosition()).withParameter(LootContextParams.THIS_ENTITY, this).create(LootContextParamSets.GIFT); ++ List list = loottable.getRandomItems(lootparams); ++ BlockPos blockposition = this.getHeadBlock(); ++ Iterator iterator = list.iterator(); + +- for (ItemStack itemStack : randomItems) { +- ItemEntity itemEntity = new ItemEntity(serverLevel, (double)headBlock.getX(), (double)headBlock.getY(), (double)headBlock.getZ(), itemStack); +- itemEntity.setDefaultPickUpDelay(); +- serverLevel.addFreshEntity(itemEntity); ++ while (iterator.hasNext()) { ++ ItemStack itemstack = (ItemStack) iterator.next(); ++ ItemEntity entityitem = new ItemEntity(worldserver, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), itemstack); ++ ++ // CraftBukkit start - handle EntityDropItemEvent ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end ++ entityitem.setDefaultPickUpDelay(); ++ worldserver.addFreshEntity(entityitem); + } + + this.playSound(SoundEvents.SNIFFER_DROP_SEED, 1.0F, 1.0F); +@@ -283,62 +293,67 @@ + + private Sniffer emitDiggingParticles(AnimationState animationState) { + boolean flag = animationState.getAccumulatedTime() > 1700L && animationState.getAccumulatedTime() < 6000L; ++ + if (flag) { +- BlockPos headBlock = this.getHeadBlock(); +- BlockState blockState = this.level().getBlockState(headBlock.below()); +- if (blockState.getRenderShape() != RenderShape.INVISIBLE) { +- for (int i = 0; i < 30; i++) { +- Vec3 vec3 = Vec3.atCenterOf(headBlock).add(0.0, -0.65F, 0.0); +- this.level().addParticle(new BlockParticleOption(ParticleTypes.BLOCK, blockState), vec3.x, vec3.y, vec3.z, 0.0, 0.0, 0.0); ++ BlockPos blockposition = this.getHeadBlock(); ++ IBlockData iblockdata = this.level().getBlockState(blockposition.below()); ++ ++ if (iblockdata.getRenderShape() != EnumRenderType.INVISIBLE) { ++ for (int i = 0; i < 30; ++i) { ++ Vec3 vec3d = Vec3.atCenterOf(blockposition).add(0.0D, -0.6499999761581421D, 0.0D); ++ ++ this.level().addParticle(new BlockParticleOption(ParticleTypes.BLOCK, iblockdata), vec3d.x, vec3d.y, vec3d.z, 0.0D, 0.0D, 0.0D); + } + + if (this.tickCount % 10 == 0) { +- this.level() +- .playLocalSound( +- this.getX(), this.getY(), this.getZ(), blockState.getSoundType().getHitSound(), this.getSoundSource(), 0.5F, 0.5F, false +- ); ++ this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), iblockdata.getSoundType().getHitSound(), this.getSoundSource(), 0.5F, 0.5F, false); + } + } + } + + if (this.tickCount % 10 == 0) { +- this.level().gameEvent(GameEvent.ENTITY_ACTION, this.getHeadBlock(), GameEvent.Context.of(this)); ++ this.level().gameEvent(GameEvent.ENTITY_ACTION, this.getHeadBlock(), GameEvent.Context.of((Entity) this)); + } + + return this; + } + +- private Sniffer storeExploredPosition(BlockPos pos) { +- List list = this.getExploredPositions().limit(20L).collect(Collectors.toList()); ++ public Sniffer storeExploredPosition(BlockPos pos) { ++ List list = (List) this.getExploredPositions().limit(20L).collect(Collectors.toList()); ++ + list.add(0, GlobalPos.of(this.level().dimension(), pos)); +- this.getBrain().setMemory(MemoryModuleType.SNIFFER_EXPLORED_POSITIONS, list); ++ this.getBrain().setMemory(MemoryModuleType.SNIFFER_EXPLORED_POSITIONS, list); // CraftBukkit - decompile error + return this; + } + +- private Stream getExploredPositions() { ++ public Stream getExploredPositions() { + return this.getBrain().getMemory(MemoryModuleType.SNIFFER_EXPLORED_POSITIONS).stream().flatMap(Collection::stream); + } + + @Override + protected void jumpFromGround() { + super.jumpFromGround(); +- double speedModifier = this.moveControl.getSpeedModifier(); +- if (speedModifier > 0.0) { +- double d = this.getDeltaMovement().horizontalDistanceSqr(); +- if (d < 0.01) { +- this.moveRelative(0.1F, new Vec3(0.0, 0.0, 1.0)); ++ double d0 = this.moveControl.getSpeedModifier(); ++ ++ if (d0 > 0.0D) { ++ double d1 = this.getDeltaMovement().horizontalDistanceSqr(); ++ ++ if (d1 < 0.01D) { ++ this.moveRelative(0.1F, new Vec3(0.0D, 0.0D, 1.0D)); + } + } ++ + } + + @Override + public void spawnChildFromBreeding(ServerLevel level, Animal mate) { +- ItemStack itemStack = new ItemStack(Items.SNIFFER_EGG); +- ItemEntity itemEntity = new ItemEntity(level, this.position().x(), this.position().y(), this.position().z(), itemStack); +- itemEntity.setDefaultPickUpDelay(); +- this.finalizeSpawnChildFromBreeding(level, mate, null); ++ ItemStack itemstack = new ItemStack(Items.SNIFFER_EGG); ++ ItemEntity entityitem = new ItemEntity(level, this.position().x(), this.position().y(), this.position().z(), itemstack); ++ ++ entityitem.setDefaultPickUpDelay(); ++ this.finalizeSpawnChildFromBreeding(level, mate, (AgeableMob) null); + this.playSound(SoundEvents.SNIFFER_EGG_PLOP, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 0.5F); +- level.addFreshEntity(itemEntity); ++ level.addFreshEntity(entityitem); + } + + @Override +@@ -361,20 +376,21 @@ + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- boolean isFood = this.isFood(itemInHand); +- InteractionResult interactionResult = super.mobInteract(player, hand); +- if (interactionResult.consumesAction() && isFood) { +- this.level().playSound(null, this, this.getEatingSound(itemInHand), SoundSource.NEUTRAL, 1.0F, Mth.randomBetween(this.level().random, 0.8F, 1.2F)); ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ boolean flag = this.isFood(itemstack); ++ InteractionResult enuminteractionresult = super.mobInteract(player, hand); ++ ++ if (enuminteractionresult.consumesAction() && flag) { ++ this.level().playSound((Player) null, (Entity) this, this.getEatingSound(itemstack), SoundSource.NEUTRAL, 1.0F, Mth.randomBetween(this.level().random, 0.8F, 1.2F)); + } + +- return interactionResult; ++ return enuminteractionresult; + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.34375F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.34375F * f, 0.0F); + } + + @Override +@@ -386,10 +402,11 @@ + if (this.level().isClientSide() && this.tickCount % 20 == 0) { + this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.SNIFFER_SEARCHING, this.getSoundSource(), 1.0F, 1.0F, false); + } ++ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState state) { ++ protected void playStepSound(BlockPos pos, IBlockData state) { + this.playSound(SoundEvents.SNIFFER_STEP, 0.15F, 1.0F); + } + +@@ -425,22 +442,24 @@ + + @Override + public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob otherParent) { +- return EntityType.SNIFFER.create(level); ++ return (AgeableMob) EntityType.SNIFFER.create(level); + } + + @Override + public boolean canMate(Animal otherAnimal) { +- if (!(otherAnimal instanceof Sniffer sniffer)) { ++ if (!(otherAnimal instanceof Sniffer)) { + return false; + } else { ++ Sniffer sniffer = (Sniffer) otherAnimal; + Set set = Set.of(Sniffer.State.IDLING, Sniffer.State.SCENTING, Sniffer.State.FEELING_HAPPY); ++ + return set.contains(this.getState()) && set.contains(sniffer.getState()) && super.canMate(otherAnimal); + } + } + + @Override + public AABB getBoundingBoxForCulling() { +- return super.getBoundingBoxForCulling().inflate(0.6F); ++ return super.getBoundingBoxForCulling().inflate(0.6000000238418579D); + } + + @Override +@@ -455,7 +474,7 @@ + + @Override + public Brain getBrain() { +- return (Brain)super.getBrain(); ++ return (Brain) super.getBrain(); // CraftBukkit - decompile error + } + + @Override +@@ -466,7 +485,7 @@ + @Override + protected void customServerAiStep() { + this.level().getProfiler().push("snifferBrain"); +- this.getBrain().tick((ServerLevel)this.level(), this); ++ this.getBrain().tick((ServerLevel) this.level(), this); + this.level().getProfiler().popPush("snifferActivityUpdate"); + SnifferAi.updateActivity(this); + this.level().getProfiler().pop(); +@@ -480,12 +499,9 @@ + } + + public static enum State { +- IDLING, +- FEELING_HAPPY, +- SCENTING, +- SNIFFING, +- SEARCHING, +- DIGGING, +- RISING; ++ ++ IDLING, FEELING_HAPPY, SCENTING, SNIFFING, SEARCHING, DIGGING, RISING; ++ ++ private State() {} + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java.patch new file mode 100644 index 0000000000..f6e7855b18 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java.patch @@ -0,0 +1,140 @@ +--- a/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java ++++ b/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java +@@ -15,14 +15,18 @@ + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; ++import net.minecraft.world.level.ExplosionDamageCalculator; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.BaseFireBlock; + import net.minecraft.world.level.dimension.end.EndDragonFight; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end + + public class EndCrystal extends Entity { +- private static final EntityDataAccessor> DATA_BEAM_TARGET = SynchedEntityData.defineId( +- EndCrystal.class, EntityDataSerializers.OPTIONAL_BLOCK_POS +- ); ++ ++ private static final EntityDataAccessor> DATA_BEAM_TARGET = SynchedEntityData.defineId(EndCrystal.class, EntityDataSerializers.OPTIONAL_BLOCK_POS); + private static final EntityDataAccessor DATA_SHOW_BOTTOM = SynchedEntityData.defineId(EndCrystal.class, EntityDataSerializers.BOOLEAN); + public int time; + +@@ -32,9 +36,9 @@ + this.time = this.random.nextInt(100000); + } + +- public EndCrystal(Level level, double x, double y, double z) { ++ public EndCrystal(Level level, double x, double d1, double y) { + this(EntityType.END_CRYSTAL, level); +- this.setPos(x, y, z); ++ this.setPos(x, d1, y); + } + + @Override +@@ -44,19 +48,25 @@ + + @Override + protected void defineSynchedData() { +- this.getEntityData().define(DATA_BEAM_TARGET, Optional.empty()); +- this.getEntityData().define(DATA_SHOW_BOTTOM, true); ++ this.getEntityData().define(EndCrystal.DATA_BEAM_TARGET, Optional.empty()); ++ this.getEntityData().define(EndCrystal.DATA_SHOW_BOTTOM, true); + } + + @Override + public void tick() { +- this.time++; ++ ++this.time; + if (this.level() instanceof ServerLevel) { +- BlockPos blockPos = this.blockPosition(); +- if (((ServerLevel)this.level()).getDragonFight() != null && this.level().getBlockState(blockPos).isAir()) { +- this.level().setBlockAndUpdate(blockPos, BaseFireBlock.getState(this.level(), blockPos)); ++ BlockPos blockposition = this.blockPosition(); ++ ++ if (((ServerLevel) this.level()).getDragonFight() != null && this.level().getBlockState(blockposition).isAir()) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition, this).isCancelled()) { ++ this.level().setBlockAndUpdate(blockposition, BaseFireBlock.getState(this.level(), blockposition)); ++ } ++ // CraftBukkit end + } + } ++ + } + + @Override +@@ -77,6 +87,7 @@ + if (compound.contains("ShowBottom", 1)) { + this.setShowBottom(compound.getBoolean("ShowBottom")); + } ++ + } + + @Override +@@ -92,10 +103,23 @@ + return false; + } else { + if (!this.isRemoved() && !this.level().isClientSide) { ++ // CraftBukkit start - All non-living entities need this ++ if (CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, false)) { ++ return false; ++ } ++ // CraftBukkit end + this.remove(Entity.RemovalReason.KILLED); + if (!source.is(DamageTypeTags.IS_EXPLOSION)) { +- DamageSource damageSource = source.getEntity() != null ? this.damageSources().explosion(this, source.getEntity()) : null; +- this.level().explode(this, damageSource, null, this.getX(), this.getY(), this.getZ(), 6.0F, false, Level.ExplosionInteraction.BLOCK); ++ DamageSource damagesource1 = source.getEntity() != null ? this.damageSources().explosion(this, source.getEntity()) : null; ++ ++ // CraftBukkit start ++ ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent(this, 6.0F, false); ++ if (event.isCancelled()) { ++ this.unsetRemoved(); ++ return false; ++ } ++ this.level().explode(this, damagesource1, (ExplosionDamageCalculator) null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.BLOCK); ++ // CraftBukkit end + } + + this.onDestroyedBy(source); +@@ -113,28 +137,30 @@ + + private void onDestroyedBy(DamageSource source) { + if (this.level() instanceof ServerLevel) { +- EndDragonFight dragonFight = ((ServerLevel)this.level()).getDragonFight(); +- if (dragonFight != null) { +- dragonFight.onCrystalDestroyed(this, source); ++ EndDragonFight enderdragonbattle = ((ServerLevel) this.level()).getDragonFight(); ++ ++ if (enderdragonbattle != null) { ++ enderdragonbattle.onCrystalDestroyed(this, source); + } + } ++ + } + + public void setBeamTarget(@Nullable BlockPos beamTarget) { +- this.getEntityData().set(DATA_BEAM_TARGET, Optional.ofNullable(beamTarget)); ++ this.getEntityData().set(EndCrystal.DATA_BEAM_TARGET, Optional.ofNullable(beamTarget)); + } + + @Nullable + public BlockPos getBeamTarget() { +- return this.getEntityData().get(DATA_BEAM_TARGET).orElse(null); ++ return (BlockPos) ((Optional) this.getEntityData().get(EndCrystal.DATA_BEAM_TARGET)).orElse((Object) null); + } + + public void setShowBottom(boolean showBottom) { +- this.getEntityData().set(DATA_SHOW_BOTTOM, showBottom); ++ this.getEntityData().set(EndCrystal.DATA_SHOW_BOTTOM, showBottom); + } + + public boolean showsBottom() { +- return this.getEntityData().get(DATA_SHOW_BOTTOM); ++ return (Boolean) this.getEntityData().get(EndCrystal.DATA_SHOW_BOTTOM); + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java.patch new file mode 100644 index 0000000000..1343fcc070 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java.patch @@ -0,0 +1,1290 @@ +--- a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java ++++ b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +@@ -2,6 +2,7 @@ + + import com.google.common.collect.Lists; + import com.mojang.logging.LogUtils; ++import java.util.Iterator; + import java.util.List; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +@@ -24,10 +25,10 @@ + import net.minecraft.world.entity.EntityDimensions; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.ExperienceOrb; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.targeting.TargetingConditions; +@@ -35,11 +36,11 @@ + import net.minecraft.world.entity.boss.enderdragon.phases.DragonPhaseInstance; + import net.minecraft.world.entity.boss.enderdragon.phases.EnderDragonPhase; + import net.minecraft.world.entity.boss.enderdragon.phases.EnderDragonPhaseManager; +-import net.minecraft.world.entity.monster.Enemy; ++import net.minecraft.world.entity.monster.IMonster; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.dimension.end.EndDragonFight; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.levelgen.Heightmap; +@@ -47,15 +48,28 @@ + import net.minecraft.world.level.pathfinder.BinaryHeap; + import net.minecraft.world.level.pathfinder.Node; + import net.minecraft.world.level.pathfinder.Path; +-import net.minecraft.world.phys.AABB; +-import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + import org.slf4j.Logger; + +-public class EnderDragon extends Mob implements Enemy { ++// CraftBukkit start ++import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.level.Explosion; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.entity.BlockEntity; ++import net.minecraft.world.level.storage.loot.LootParams; ++import net.minecraft.world.level.storage.loot.parameters.LootContextParams; ++import net.minecraft.world.phys.AABB; ++import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.entity.EntityExplodeEvent; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++// CraftBukkit end ++ ++public class EnderDragon extends Mob implements IMonster { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + public static final EntityDataAccessor DATA_PHASE = SynchedEntityData.defineId(EnderDragon.class, EntityDataSerializers.INT); +- private static final TargetingConditions CRYSTAL_DESTROY_TARGETING = TargetingConditions.forCombat().range(64.0); ++ private static final TargetingConditions CRYSTAL_DESTROY_TARGETING = TargetingConditions.forCombat().range(64.0D); + private static final int GROWL_INTERVAL_MIN = 200; + private static final int GROWL_INTERVAL_MAX = 400; + private static final float SITTING_ALLOWED_DAMAGE_PERCENTAGE = 0.25F; +@@ -63,7 +77,7 @@ + private static final String DRAGON_PHASE_KEY = "DragonPhase"; + public final double[][] positions = new double[64][3]; + public int posPointer = -1; +- private final EnderDragonPart[] subEntities; ++ public final EnderDragonPart[] subEntities; + public final EnderDragonPart head; + private final EnderDragonPart neck; + private final EnderDragonPart body; +@@ -81,16 +95,22 @@ + public EndCrystal nearestCrystal; + @Nullable + private EndDragonFight dragonFight; +- private BlockPos fightOrigin = BlockPos.ZERO; ++ private BlockPos fightOrigin; + private final EnderDragonPhaseManager phaseManager; +- private int growlTime = 100; ++ private int growlTime; + private float sittingDamageReceived; +- private final Node[] nodes = new Node[24]; +- private final int[] nodeAdjacency = new int[24]; +- private final BinaryHeap openSet = new BinaryHeap(); ++ private final Node[] nodes; ++ private final int[] nodeAdjacency; ++ private final BinaryHeap openSet; ++ private final Explosion explosionSource; // CraftBukkit - reusable source for CraftTNTPrimed.getSource() + + public EnderDragon(EntityType entityType, Level level) { + super(EntityType.ENDER_DRAGON, level); ++ this.fightOrigin = BlockPos.ZERO; ++ this.growlTime = 100; ++ this.nodes = new Node[24]; ++ this.nodeAdjacency = new int[24]; ++ this.openSet = new BinaryHeap(); + this.head = new EnderDragonPart(this, "head", 1.0F, 1.0F); + this.neck = new EnderDragonPart(this, "neck", 3.0F, 3.0F); + this.body = new EnderDragonPart(this, "body", 5.0F, 3.0F); +@@ -104,6 +124,7 @@ + this.noPhysics = true; + this.noCulling = true; + this.phaseManager = new EnderDragonPhaseManager(this); ++ this.explosionSource = new Explosion(level, this, null, null, Double.NaN, Double.NaN, Double.NaN, Float.NaN, true, Explosion.Effect.DESTROY, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); // CraftBukkit + } + + public void setDragonFight(EndDragonFight dragonFight) { +@@ -119,37 +140,29 @@ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 200.0); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 200.0D); + } + + @Override + public boolean isFlapping() { +- float cos = Mth.cos(this.flapTime * (float) (Math.PI * 2)); +- float cos1 = Mth.cos(this.oFlapTime * (float) (Math.PI * 2)); +- return cos1 <= -0.3F && cos >= -0.3F; ++ float f = Mth.cos(this.flapTime * 6.2831855F); ++ float f1 = Mth.cos(this.oFlapTime * 6.2831855F); ++ ++ return f1 <= -0.3F && f >= -0.3F; + } + + @Override + public void onFlap() { + if (this.level().isClientSide && !this.isSilent()) { +- this.level() +- .playLocalSound( +- this.getX(), +- this.getY(), +- this.getZ(), +- SoundEvents.ENDER_DRAGON_FLAP, +- this.getSoundSource(), +- 5.0F, +- 0.8F + this.random.nextFloat() * 0.3F, +- false +- ); ++ this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.ENDER_DRAGON_FLAP, this.getSoundSource(), 5.0F, 0.8F + this.random.nextFloat() * 0.3F, false); + } ++ + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.getEntityData().define(DATA_PHASE, EnderDragonPhase.HOVERING.getId()); ++ this.getEntityData().define(EnderDragon.DATA_PHASE, EnderDragonPhase.HOVERING.getId()); + } + + public double[] getLatencyPos(int bufferIndexOffset, float partialTicks) { +@@ -158,17 +171,18 @@ + } + + partialTicks = 1.0F - partialTicks; +- int i = this.posPointer - bufferIndexOffset & 63; +- int i1 = this.posPointer - bufferIndexOffset - 1 & 63; +- double[] doubles = new double[3]; +- double d = this.positions[i][0]; +- double d1 = Mth.wrapDegrees(this.positions[i1][0] - d); +- doubles[0] = d + d1 * (double)partialTicks; +- d = this.positions[i][1]; +- d1 = this.positions[i1][1] - d; +- doubles[1] = d + d1 * (double)partialTicks; +- doubles[2] = Mth.lerp((double)partialTicks, this.positions[i][2], this.positions[i1][2]); +- return doubles; ++ int j = this.posPointer - bufferIndexOffset & 63; ++ int k = this.posPointer - bufferIndexOffset - 1 & 63; ++ double[] adouble = new double[3]; ++ double d0 = this.positions[j][0]; ++ double d1 = Mth.wrapDegrees(this.positions[k][0] - d0); ++ ++ adouble[0] = d0 + d1 * (double) partialTicks; ++ d0 = this.positions[j][1]; ++ d1 = this.positions[k][1] - d0; ++ adouble[1] = d0 + d1 * (double) partialTicks; ++ adouble[2] = Mth.lerp((double) partialTicks, this.positions[j][2], this.positions[k][2]); ++ return adouble; + } + + @Override +@@ -177,45 +191,46 @@ + if (this.level().isClientSide) { + this.setHealth(this.getHealth()); + if (!this.isSilent() && !this.phaseManager.getCurrentPhase().isSitting() && --this.growlTime < 0) { +- this.level() +- .playLocalSound( +- this.getX(), +- this.getY(), +- this.getZ(), +- SoundEvents.ENDER_DRAGON_GROWL, +- this.getSoundSource(), +- 2.5F, +- 0.8F + this.random.nextFloat() * 0.3F, +- false +- ); ++ this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.ENDER_DRAGON_GROWL, this.getSoundSource(), 2.5F, 0.8F + this.random.nextFloat() * 0.3F, false); + this.growlTime = 200 + this.random.nextInt(200); + } + } + +- if (this.dragonFight == null && this.level() instanceof ServerLevel serverLevel) { +- EndDragonFight dragonFight = serverLevel.getDragonFight(); +- if (dragonFight != null && this.getUUID().equals(dragonFight.getDragonUUID())) { +- this.dragonFight = dragonFight; ++ if (this.dragonFight == null) { ++ Level world = this.level(); ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ EndDragonFight enderdragonbattle = worldserver.getDragonFight(); ++ ++ if (enderdragonbattle != null && this.getUUID().equals(enderdragonbattle.getDragonUUID())) { ++ this.dragonFight = enderdragonbattle; ++ } + } + } + + this.oFlapTime = this.flapTime; ++ float f; ++ + if (this.isDeadOrDying()) { +- float f = (this.random.nextFloat() - 0.5F) * 8.0F; +- float f1 = (this.random.nextFloat() - 0.5F) * 4.0F; ++ float f1 = (this.random.nextFloat() - 0.5F) * 8.0F; ++ ++ f = (this.random.nextFloat() - 0.5F) * 4.0F; + float f2 = (this.random.nextFloat() - 0.5F) * 8.0F; +- this.level().addParticle(ParticleTypes.EXPLOSION, this.getX() + (double)f, this.getY() + 2.0 + (double)f1, this.getZ() + (double)f2, 0.0, 0.0, 0.0); ++ ++ this.level().addParticle(ParticleTypes.EXPLOSION, this.getX() + (double) f1, this.getY() + 2.0D + (double) f, this.getZ() + (double) f2, 0.0D, 0.0D, 0.0D); + } else { + this.checkCrystals(); +- Vec3 deltaMovement = this.getDeltaMovement(); +- float f1 = 0.2F / ((float)deltaMovement.horizontalDistance() * 10.0F + 1.0F); +- float var28 = f1 * (float)Math.pow(2.0, deltaMovement.y); ++ Vec3 vec3d = this.getDeltaMovement(); ++ ++ f = 0.2F / ((float) vec3d.horizontalDistance() * 10.0F + 1.0F); ++ f *= (float) Math.pow(2.0D, vec3d.y); + if (this.phaseManager.getCurrentPhase().isSitting()) { + this.flapTime += 0.1F; + } else if (this.inWall) { +- this.flapTime += var28 * 0.5F; ++ this.flapTime += f * 0.5F; + } else { +- this.flapTime += var28; ++ this.flapTime += f; + } + + this.setYRot(Mth.wrapDegrees(this.getYRot())); +@@ -223,8 +238,8 @@ + this.flapTime = 0.5F; + } else { + if (this.posPointer < 0) { +- for (int i = 0; i < this.positions.length; i++) { +- this.positions[i][0] = (double)this.getYRot(); ++ for (int i = 0; i < this.positions.length; ++i) { ++ this.positions[i][0] = (double) this.getYRot(); + this.positions[i][1] = this.getY(); + } + } +@@ -233,163 +248,163 @@ + this.posPointer = 0; + } + +- this.positions[this.posPointer][0] = (double)this.getYRot(); ++ this.positions[this.posPointer][0] = (double) this.getYRot(); + this.positions[this.posPointer][1] = this.getY(); ++ float f3; ++ float f4; ++ float f5; ++ + if (this.level().isClientSide) { + if (this.lerpSteps > 0) { + this.lerpPositionAndRotationStep(this.lerpSteps, this.lerpX, this.lerpY, this.lerpZ, this.lerpYRot, this.lerpXRot); +- this.lerpSteps--; ++ --this.lerpSteps; + } + + this.phaseManager.getCurrentPhase().doClientTick(); + } else { +- DragonPhaseInstance currentPhase = this.phaseManager.getCurrentPhase(); +- currentPhase.doServerTick(); +- if (this.phaseManager.getCurrentPhase() != currentPhase) { +- currentPhase = this.phaseManager.getCurrentPhase(); +- currentPhase.doServerTick(); ++ DragonPhaseInstance idragoncontroller = this.phaseManager.getCurrentPhase(); ++ ++ idragoncontroller.doServerTick(); ++ if (this.phaseManager.getCurrentPhase() != idragoncontroller) { ++ idragoncontroller = this.phaseManager.getCurrentPhase(); ++ idragoncontroller.doServerTick(); + } + +- Vec3 flyTargetLocation = currentPhase.getFlyTargetLocation(); +- if (flyTargetLocation != null) { +- double d = flyTargetLocation.x - this.getX(); +- double d1 = flyTargetLocation.y - this.getY(); +- double d2 = flyTargetLocation.z - this.getZ(); +- double d3 = d * d + d1 * d1 + d2 * d2; +- float flySpeed = currentPhase.getFlySpeed(); +- double squareRoot = Math.sqrt(d * d + d2 * d2); +- if (squareRoot > 0.0) { +- d1 = Mth.clamp(d1 / squareRoot, (double)(-flySpeed), (double)flySpeed); ++ Vec3 vec3d1 = idragoncontroller.getFlyTargetLocation(); ++ ++ if (vec3d1 != null && idragoncontroller.getPhase() != EnderDragonPhase.HOVERING) { // CraftBukkit - Don't move when hovering ++ double d0 = vec3d1.x - this.getX(); ++ double d1 = vec3d1.y - this.getY(); ++ double d2 = vec3d1.z - this.getZ(); ++ double d3 = d0 * d0 + d1 * d1 + d2 * d2; ++ float f6 = idragoncontroller.getFlySpeed(); ++ double d4 = Math.sqrt(d0 * d0 + d2 * d2); ++ ++ if (d4 > 0.0D) { ++ d1 = Mth.clamp(d1 / d4, (double) (-f6), (double) f6); + } + +- this.setDeltaMovement(this.getDeltaMovement().add(0.0, d1 * 0.01, 0.0)); ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, d1 * 0.01D, 0.0D)); + this.setYRot(Mth.wrapDegrees(this.getYRot())); +- Vec3 vec3 = flyTargetLocation.subtract(this.getX(), this.getY(), this.getZ()).normalize(); +- Vec3 vec31 = new Vec3( +- (double)Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)), +- this.getDeltaMovement().y, +- (double)(-Mth.cos(this.getYRot() * (float) (Math.PI / 180.0))) +- ) +- .normalize(); +- float max = Math.max(((float)vec31.dot(vec3) + 0.5F) / 1.5F, 0.0F); +- if (Math.abs(d) > 1.0E-5F || Math.abs(d2) > 1.0E-5F) { +- float f3 = Mth.clamp(Mth.wrapDegrees(180.0F - (float)Mth.atan2(d, d2) * (180.0F / (float)Math.PI) - this.getYRot()), -50.0F, 50.0F); ++ Vec3 vec3d2 = vec3d1.subtract(this.getX(), this.getY(), this.getZ()).normalize(); ++ Vec3 vec3d3 = (new Vec3((double) Mth.sin(this.getYRot() * 0.017453292F), this.getDeltaMovement().y, (double) (-Mth.cos(this.getYRot() * 0.017453292F)))).normalize(); ++ ++ f3 = Math.max(((float) vec3d3.dot(vec3d2) + 0.5F) / 1.5F, 0.0F); ++ if (Math.abs(d0) > 9.999999747378752E-6D || Math.abs(d2) > 9.999999747378752E-6D) { ++ f4 = Mth.clamp(Mth.wrapDegrees(180.0F - (float) Mth.atan2(d0, d2) * 57.295776F - this.getYRot()), -50.0F, 50.0F); + this.yRotA *= 0.8F; +- this.yRotA = this.yRotA + f3 * currentPhase.getTurnSpeed(); ++ this.yRotA += f4 * idragoncontroller.getTurnSpeed(); + this.setYRot(this.getYRot() + this.yRotA * 0.1F); + } + +- float f3 = (float)(2.0 / (d3 + 1.0)); +- float f4 = 0.06F; +- this.moveRelative(0.06F * (max * f3 + (1.0F - f3)), new Vec3(0.0, 0.0, -1.0)); ++ f4 = (float) (2.0D / (d3 + 1.0D)); ++ f5 = 0.06F; ++ this.moveRelative(0.06F * (f3 * f4 + (1.0F - f4)), new Vec3(0.0D, 0.0D, -1.0D)); + if (this.inWall) { +- this.move(MoverType.SELF, this.getDeltaMovement().scale(0.8F)); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement().scale(0.800000011920929D)); + } else { +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + } + +- Vec3 vec32 = this.getDeltaMovement().normalize(); +- double d4 = 0.8 + 0.15 * (vec32.dot(vec31) + 1.0) / 2.0; +- this.setDeltaMovement(this.getDeltaMovement().multiply(d4, 0.91F, d4)); ++ Vec3 vec3d4 = this.getDeltaMovement().normalize(); ++ double d5 = 0.8D + 0.15D * (vec3d4.dot(vec3d3) + 1.0D) / 2.0D; ++ ++ this.setDeltaMovement(this.getDeltaMovement().multiply(d5, 0.9100000262260437D, d5)); + } + } + + this.yBodyRot = this.getYRot(); +- Vec3[] vec3s = new Vec3[this.subEntities.length]; ++ Vec3[] avec3d = new Vec3[this.subEntities.length]; + +- for (int i1 = 0; i1 < this.subEntities.length; i1++) { +- vec3s[i1] = new Vec3(this.subEntities[i1].getX(), this.subEntities[i1].getY(), this.subEntities[i1].getZ()); ++ for (int j = 0; j < this.subEntities.length; ++j) { ++ avec3d[j] = new Vec3(this.subEntities[j].getX(), this.subEntities[j].getY(), this.subEntities[j].getZ()); + } + +- float f5 = (float)(this.getLatencyPos(5, 1.0F)[1] - this.getLatencyPos(10, 1.0F)[1]) * 10.0F * (float) (Math.PI / 180.0); +- float cos = Mth.cos(f5); +- float sin = Mth.sin(f5); +- float f6 = this.getYRot() * (float) (Math.PI / 180.0); +- float sin1 = Mth.sin(f6); +- float cos1 = Mth.cos(f6); +- this.tickPart(this.body, (double)(sin1 * 0.5F), 0.0, (double)(-cos1 * 0.5F)); +- this.tickPart(this.wing1, (double)(cos1 * 4.5F), 2.0, (double)(sin1 * 4.5F)); +- this.tickPart(this.wing2, (double)(cos1 * -4.5F), 2.0, (double)(sin1 * -4.5F)); ++ float f7 = (float) (this.getLatencyPos(5, 1.0F)[1] - this.getLatencyPos(10, 1.0F)[1]) * 10.0F * 0.017453292F; ++ float f8 = Mth.cos(f7); ++ float f9 = Mth.sin(f7); ++ float f10 = this.getYRot() * 0.017453292F; ++ float f11 = Mth.sin(f10); ++ float f12 = Mth.cos(f10); ++ ++ this.tickPart(this.body, (double) (f11 * 0.5F), 0.0D, (double) (-f12 * 0.5F)); ++ this.tickPart(this.wing1, (double) (f12 * 4.5F), 2.0D, (double) (f11 * 4.5F)); ++ this.tickPart(this.wing2, (double) (f12 * -4.5F), 2.0D, (double) (f11 * -4.5F)); + if (!this.level().isClientSide && this.hurtTime == 0) { +- this.knockBack( +- this.level() +- .getEntities(this, this.wing1.getBoundingBox().inflate(4.0, 2.0, 4.0).move(0.0, -2.0, 0.0), EntitySelector.NO_CREATIVE_OR_SPECTATOR) +- ); +- this.knockBack( +- this.level() +- .getEntities(this, this.wing2.getBoundingBox().inflate(4.0, 2.0, 4.0).move(0.0, -2.0, 0.0), EntitySelector.NO_CREATIVE_OR_SPECTATOR) +- ); +- this.hurt(this.level().getEntities(this, this.head.getBoundingBox().inflate(1.0), EntitySelector.NO_CREATIVE_OR_SPECTATOR)); +- this.hurt(this.level().getEntities(this, this.neck.getBoundingBox().inflate(1.0), EntitySelector.NO_CREATIVE_OR_SPECTATOR)); ++ this.knockBack(this.level().getEntities((Entity) this, this.wing1.getBoundingBox().inflate(4.0D, 2.0D, 4.0D).move(0.0D, -2.0D, 0.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR)); ++ this.knockBack(this.level().getEntities((Entity) this, this.wing2.getBoundingBox().inflate(4.0D, 2.0D, 4.0D).move(0.0D, -2.0D, 0.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR)); ++ this.hurt(this.level().getEntities((Entity) this, this.head.getBoundingBox().inflate(1.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR)); ++ this.hurt(this.level().getEntities((Entity) this, this.neck.getBoundingBox().inflate(1.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR)); + } + +- float sin2 = Mth.sin(this.getYRot() * (float) (Math.PI / 180.0) - this.yRotA * 0.01F); +- float cos2 = Mth.cos(this.getYRot() * (float) (Math.PI / 180.0) - this.yRotA * 0.01F); +- float headYOffset = this.getHeadYOffset(); +- this.tickPart(this.head, (double)(sin2 * 6.5F * cos), (double)(headYOffset + sin * 6.5F), (double)(-cos2 * 6.5F * cos)); +- this.tickPart(this.neck, (double)(sin2 * 5.5F * cos), (double)(headYOffset + sin * 5.5F), (double)(-cos2 * 5.5F * cos)); +- double[] latencyPos = this.getLatencyPos(5, 1.0F); ++ float f13 = Mth.sin(this.getYRot() * 0.017453292F - this.yRotA * 0.01F); ++ float f14 = Mth.cos(this.getYRot() * 0.017453292F - this.yRotA * 0.01F); ++ float f15 = this.getHeadYOffset(); + +- for (int i2 = 0; i2 < 3; i2++) { +- EnderDragonPart enderDragonPart = null; +- if (i2 == 0) { +- enderDragonPart = this.tail1; ++ this.tickPart(this.head, (double) (f13 * 6.5F * f8), (double) (f15 + f9 * 6.5F), (double) (-f14 * 6.5F * f8)); ++ this.tickPart(this.neck, (double) (f13 * 5.5F * f8), (double) (f15 + f9 * 5.5F), (double) (-f14 * 5.5F * f8)); ++ double[] adouble = this.getLatencyPos(5, 1.0F); ++ ++ int k; ++ ++ for (k = 0; k < 3; ++k) { ++ EnderDragonPart entitycomplexpart = null; ++ ++ if (k == 0) { ++ entitycomplexpart = this.tail1; + } + +- if (i2 == 1) { +- enderDragonPart = this.tail2; ++ if (k == 1) { ++ entitycomplexpart = this.tail2; + } + +- if (i2 == 2) { +- enderDragonPart = this.tail3; ++ if (k == 2) { ++ entitycomplexpart = this.tail3; + } + +- double[] latencyPos1 = this.getLatencyPos(12 + i2 * 2, 1.0F); +- float f7 = this.getYRot() * (float) (Math.PI / 180.0) + this.rotWrap(latencyPos1[0] - latencyPos[0]) * (float) (Math.PI / 180.0); +- float maxx = Mth.sin(f7); +- float f3 = Mth.cos(f7); +- float f4 = 1.5F; +- float f8 = (float)(i2 + 1) * 2.0F; +- this.tickPart( +- enderDragonPart, +- (double)(-(sin1 * 1.5F + maxx * f8) * cos), +- latencyPos1[1] - latencyPos[1] - (double)((f8 + 1.5F) * sin) + 1.5, +- (double)((cos1 * 1.5F + f3 * f8) * cos) +- ); ++ double[] adouble1 = this.getLatencyPos(12 + k * 2, 1.0F); ++ float f16 = this.getYRot() * 0.017453292F + this.rotWrap(adouble1[0] - adouble[0]) * 0.017453292F; ++ ++ f3 = Mth.sin(f16); ++ f4 = Mth.cos(f16); ++ f5 = 1.5F; ++ float f17 = (float) (k + 1) * 2.0F; ++ ++ this.tickPart(entitycomplexpart, (double) (-(f11 * 1.5F + f3 * f17) * f8), adouble1[1] - adouble[1] - (double) ((f17 + 1.5F) * f9) + 1.5D, (double) ((f12 * 1.5F + f4 * f17) * f8)); + } + + if (!this.level().isClientSide) { +- this.inWall = this.checkWalls(this.head.getBoundingBox()) +- | this.checkWalls(this.neck.getBoundingBox()) +- | this.checkWalls(this.body.getBoundingBox()); ++ this.inWall = this.checkWalls(this.head.getBoundingBox()) | this.checkWalls(this.neck.getBoundingBox()) | this.checkWalls(this.body.getBoundingBox()); + if (this.dragonFight != null) { + this.dragonFight.updateDragon(this); + } + } + +- for (int i2 = 0; i2 < this.subEntities.length; i2++) { +- this.subEntities[i2].xo = vec3s[i2].x; +- this.subEntities[i2].yo = vec3s[i2].y; +- this.subEntities[i2].zo = vec3s[i2].z; +- this.subEntities[i2].xOld = vec3s[i2].x; +- this.subEntities[i2].yOld = vec3s[i2].y; +- this.subEntities[i2].zOld = vec3s[i2].z; ++ for (k = 0; k < this.subEntities.length; ++k) { ++ this.subEntities[k].xo = avec3d[k].x; ++ this.subEntities[k].yo = avec3d[k].y; ++ this.subEntities[k].zo = avec3d[k].z; ++ this.subEntities[k].xOld = avec3d[k].x; ++ this.subEntities[k].yOld = avec3d[k].y; ++ this.subEntities[k].zOld = avec3d[k].z; + } ++ + } + } + } + +- private void tickPart(EnderDragonPart part, double offsetX, double offsetY, double offsetZ) { +- part.setPos(this.getX() + offsetX, this.getY() + offsetY, this.getZ() + offsetZ); ++ private void tickPart(EnderDragonPart part, double offsetX, double d1, double offsetY) { ++ part.setPos(this.getX() + offsetX, this.getY() + d1, this.getZ() + offsetY); + } + + private float getHeadYOffset() { + if (this.phaseManager.getCurrentPhase().isSitting()) { + return -1.0F; + } else { +- double[] latencyPos = this.getLatencyPos(5, 1.0F); +- double[] latencyPos1 = this.getLatencyPos(0, 1.0F); +- return (float)(latencyPos[1] - latencyPos1[1]); ++ double[] adouble = this.getLatencyPos(5, 1.0F); ++ double[] adouble1 = this.getLatencyPos(0, 1.0F); ++ ++ return (float) (adouble[1] - adouble1[1]); + } + } + +@@ -398,76 +413,105 @@ + if (this.nearestCrystal.isRemoved()) { + this.nearestCrystal = null; + } else if (this.tickCount % 10 == 0 && this.getHealth() < this.getMaxHealth()) { +- this.setHealth(this.getHealth() + 1.0F); ++ // CraftBukkit start ++ EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), 1.0F, EntityRegainHealthEvent.RegainReason.ENDER_CRYSTAL); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ this.setHealth((float) (this.getHealth() + event.getAmount())); ++ } ++ // CraftBukkit end + } + } + + if (this.random.nextInt(10) == 0) { +- List entitiesOfClass = this.level().getEntitiesOfClass(EndCrystal.class, this.getBoundingBox().inflate(32.0)); +- EndCrystal endCrystal = null; +- double d = Double.MAX_VALUE; ++ List list = this.level().getEntitiesOfClass(EndCrystal.class, this.getBoundingBox().inflate(32.0D)); ++ EndCrystal entityendercrystal = null; ++ double d0 = Double.MAX_VALUE; ++ Iterator iterator = list.iterator(); + +- for (EndCrystal endCrystal1 : entitiesOfClass) { +- double d1 = endCrystal1.distanceToSqr(this); +- if (d1 < d) { +- d = d1; +- endCrystal = endCrystal1; ++ while (iterator.hasNext()) { ++ EndCrystal entityendercrystal1 = (EndCrystal) iterator.next(); ++ double d1 = entityendercrystal1.distanceToSqr((Entity) this); ++ ++ if (d1 < d0) { ++ d0 = d1; ++ entityendercrystal = entityendercrystal1; + } + } + +- this.nearestCrystal = endCrystal; ++ this.nearestCrystal = entityendercrystal; + } ++ + } + + private void knockBack(List entities) { +- double d = (this.body.getBoundingBox().minX + this.body.getBoundingBox().maxX) / 2.0; +- double d1 = (this.body.getBoundingBox().minZ + this.body.getBoundingBox().maxZ) / 2.0; ++ double d0 = (this.body.getBoundingBox().minX + this.body.getBoundingBox().maxX) / 2.0D; ++ double d1 = (this.body.getBoundingBox().minZ + this.body.getBoundingBox().maxZ) / 2.0D; ++ Iterator iterator = entities.iterator(); + +- for (Entity entity : entities) { ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ + if (entity instanceof LivingEntity) { +- double d2 = entity.getX() - d; ++ double d2 = entity.getX() - d0; + double d3 = entity.getZ() - d1; +- double max = Math.max(d2 * d2 + d3 * d3, 0.1); +- entity.push(d2 / max * 4.0, 0.2F, d3 / max * 4.0); +- if (!this.phaseManager.getCurrentPhase().isSitting() && ((LivingEntity)entity).getLastHurtByMobTimestamp() < entity.tickCount - 2) { ++ double d4 = Math.max(d2 * d2 + d3 * d3, 0.1D); ++ ++ entity.push(d2 / d4 * 4.0D, 0.20000000298023224D, d3 / d4 * 4.0D); ++ if (!this.phaseManager.getCurrentPhase().isSitting() && ((LivingEntity) entity).getLastHurtByMobTimestamp() < entity.tickCount - 2) { + entity.hurt(this.damageSources().mobAttack(this), 5.0F); + this.doEnchantDamageEffects(this, entity); + } + } + } ++ + } + + private void hurt(List entities) { +- for (Entity entity : entities) { ++ Iterator iterator = entities.iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ + if (entity instanceof LivingEntity) { + entity.hurt(this.damageSources().mobAttack(this), 10.0F); + this.doEnchantDamageEffects(this, entity); + } + } ++ + } + + private float rotWrap(double angle) { +- return (float)Mth.wrapDegrees(angle); ++ return (float) Mth.wrapDegrees(angle); + } + + private boolean checkWalls(AABB area) { +- int floor = Mth.floor(area.minX); +- int floor1 = Mth.floor(area.minY); +- int floor2 = Mth.floor(area.minZ); +- int floor3 = Mth.floor(area.maxX); +- int floor4 = Mth.floor(area.maxY); +- int floor5 = Mth.floor(area.maxZ); ++ int i = Mth.floor(area.minX); ++ int j = Mth.floor(area.minY); ++ int k = Mth.floor(area.minZ); ++ int l = Mth.floor(area.maxX); ++ int i1 = Mth.floor(area.maxY); ++ int j1 = Mth.floor(area.maxZ); + boolean flag = false; + boolean flag1 = false; ++ // CraftBukkit start - Create a list to hold all the destroyed blocks ++ List destroyedBlocks = new java.util.ArrayList(); ++ // CraftBukkit end + +- for (int i = floor; i <= floor3; i++) { +- for (int i1 = floor1; i1 <= floor4; i1++) { +- for (int i2 = floor2; i2 <= floor5; i2++) { +- BlockPos blockPos = new BlockPos(i, i1, i2); +- BlockState blockState = this.level().getBlockState(blockPos); +- if (!blockState.isAir() && !blockState.is(BlockTags.DRAGON_TRANSPARENT)) { +- if (this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && !blockState.is(BlockTags.DRAGON_IMMUNE)) { +- flag1 = this.level().removeBlock(blockPos, false) || flag1; ++ for (int k1 = i; k1 <= l; ++k1) { ++ for (int l1 = j; l1 <= i1; ++l1) { ++ for (int i2 = k; i2 <= j1; ++i2) { ++ BlockPos blockposition = new BlockPos(k1, l1, i2); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); ++ ++ if (!iblockdata.isAir() && !iblockdata.is(BlockTags.DRAGON_TRANSPARENT)) { ++ if (this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && !iblockdata.is(BlockTags.DRAGON_IMMUNE)) { ++ // CraftBukkit start - Add blocks to list rather than destroying them ++ // flag1 = this.level().removeBlock(blockposition, false) || flag1; ++ flag1 = true; ++ destroyedBlocks.add(CraftBlock.at(this.level(), blockposition)); ++ // CraftBukkit end + } else { + flag = true; + } +@@ -476,13 +520,55 @@ + } + } + ++ // CraftBukkit start - Set off an EntityExplodeEvent for the dragon exploding all these blocks ++ // SPIGOT-4882: don't fire event if nothing hit ++ if (!flag1) { ++ return flag; ++ } ++ ++ org.bukkit.entity.Entity bukkitEntity = this.getBukkitEntity(); ++ EntityExplodeEvent event = new EntityExplodeEvent(bukkitEntity, bukkitEntity.getLocation(), destroyedBlocks, 0F); ++ bukkitEntity.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ // This flag literally means 'Dragon hit something hard' (Obsidian, White Stone or Bedrock) and will cause the dragon to slow down. ++ // We should consider adding an event extension for it, or perhaps returning true if the event is cancelled. ++ return flag; ++ } else if (event.getYield() == 0F) { ++ // Yield zero ==> no drops ++ for (org.bukkit.block.Block block : event.blockList()) { ++ this.level().removeBlock(new BlockPos(block.getX(), block.getY(), block.getZ()), false); ++ } ++ } else { ++ for (org.bukkit.block.Block block : event.blockList()) { ++ org.bukkit.Material blockId = block.getType(); ++ if (blockId.isAir()) { ++ continue; ++ } ++ ++ CraftBlock craftBlock = ((CraftBlock) block); ++ BlockPos blockposition = craftBlock.getPosition(); ++ ++ Block nmsBlock = craftBlock.getNMS().getBlock(); ++ if (nmsBlock.dropFromExplosion(explosionSource)) { ++ BlockEntity tileentity = craftBlock.getNMS().hasBlockEntity() ? this.level().getBlockEntity(blockposition) : null; ++ LootParams.Builder loottableinfo_builder = (new LootParams.Builder((ServerLevel) this.level())).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockposition)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withParameter(LootContextParams.EXPLOSION_RADIUS, 1.0F / event.getYield()).withOptionalParameter(LootContextParams.BLOCK_ENTITY, tileentity); ++ ++ craftBlock.getNMS().getDrops(loottableinfo_builder).forEach((itemstack) -> { ++ Block.popResource(this.level(), blockposition, itemstack); ++ }); ++ craftBlock.getNMS().spawnAfterBreak((ServerLevel) this.level(), blockposition, ItemStack.EMPTY, false); ++ } ++ nmsBlock.wasExploded(this.level(), blockposition, explosionSource); ++ ++ this.level().removeBlock(blockposition, false); ++ } ++ } ++ // CraftBukkit end ++ + if (flag1) { +- BlockPos blockPos1 = new BlockPos( +- floor + this.random.nextInt(floor3 - floor + 1), +- floor1 + this.random.nextInt(floor4 - floor1 + 1), +- floor2 + this.random.nextInt(floor5 - floor2 + 1) +- ); +- this.level().levelEvent(2008, blockPos1, 0); ++ BlockPos blockposition1 = new BlockPos(i + this.random.nextInt(l - i + 1), j + this.random.nextInt(i1 - j + 1), k + this.random.nextInt(j1 - k + 1)); ++ ++ this.level().levelEvent(2008, blockposition1, 0); + } + + return flag; +@@ -492,24 +578,25 @@ + if (this.phaseManager.getCurrentPhase().getPhase() == EnderDragonPhase.DYING) { + return false; + } else { +- float var5 = this.phaseManager.getCurrentPhase().onHurt(source, damage); ++ damage = this.phaseManager.getCurrentPhase().onHurt(source, damage); + if (part != this.head) { +- var5 = var5 / 4.0F + Math.min(var5, 1.0F); ++ damage = damage / 4.0F + Math.min(damage, 1.0F); + } + +- if (var5 < 0.01F) { ++ if (damage < 0.01F) { + return false; + } else { + if (source.getEntity() instanceof Player || source.is(DamageTypeTags.ALWAYS_HURTS_ENDER_DRAGONS)) { +- float health = this.getHealth(); +- this.reallyHurt(source, var5); ++ float f1 = this.getHealth(); ++ ++ this.reallyHurt(source, damage); + if (this.isDeadOrDying() && !this.phaseManager.getCurrentPhase().isSitting()) { + this.setHealth(1.0F); + this.phaseManager.setPhase(EnderDragonPhase.DYING); + } + + if (this.phaseManager.getCurrentPhase().isSitting()) { +- this.sittingDamageReceived = this.sittingDamageReceived + health - this.getHealth(); ++ this.sittingDamageReceived = this.sittingDamageReceived + f1 - this.getHealth(); + if (this.sittingDamageReceived > 0.25F * this.getMaxHealth()) { + this.sittingDamageReceived = 0.0F; + this.phaseManager.setPhase(EnderDragonPhase.TAKEOFF); +@@ -524,7 +611,7 @@ + + @Override + public boolean hurt(DamageSource source, float amount) { +- return !this.level().isClientSide && this.hurt(this.body, source, amount); ++ return !this.level().isClientSide ? this.hurt(this.body, source, amount) : false; + } + + protected boolean reallyHurt(DamageSource damageSource, float amount) { +@@ -539,32 +626,54 @@ + this.dragonFight.updateDragon(this); + this.dragonFight.setDragonKilled(this); + } ++ + } + ++ // CraftBukkit start - SPIGOT-2420: Special case, the ender dragon drops 12000 xp for the first kill and 500 xp for every other kill and this over time. + @Override ++ public int getExpReward() { ++ // CraftBukkit - Moved from #tickDeath method ++ boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT); ++ short short0 = 500; ++ ++ if (this.dragonFight != null && !this.dragonFight.hasPreviouslyKilledDragon()) { ++ short0 = 12000; ++ } ++ ++ return flag ? short0 : 0; ++ } ++ // CraftBukkit end ++ ++ @Override + protected void tickDeath() { + if (this.dragonFight != null) { + this.dragonFight.updateDragon(this); + } + +- this.dragonDeathTime++; ++ ++this.dragonDeathTime; + if (this.dragonDeathTime >= 180 && this.dragonDeathTime <= 200) { + float f = (this.random.nextFloat() - 0.5F) * 8.0F; + float f1 = (this.random.nextFloat() - 0.5F) * 4.0F; + float f2 = (this.random.nextFloat() - 0.5F) * 8.0F; +- this.level() +- .addParticle(ParticleTypes.EXPLOSION_EMITTER, this.getX() + (double)f, this.getY() + 2.0 + (double)f1, this.getZ() + (double)f2, 0.0, 0.0, 0.0); ++ ++ this.level().addParticle(ParticleTypes.EXPLOSION_EMITTER, this.getX() + (double) f, this.getY() + 2.0D + (double) f1, this.getZ() + (double) f2, 0.0D, 0.0D, 0.0D); + } + +- boolean _boolean = this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT); +- int i = 500; ++ // CraftBukkit start - SPIGOT-2420: Moved up to #getExpReward method ++ /* ++ boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT); ++ short short0 = 500; ++ + if (this.dragonFight != null && !this.dragonFight.hasPreviouslyKilledDragon()) { +- i = 12000; ++ short0 = 12000; + } ++ */ ++ int short0 = expToDrop; ++ // CraftBukkit end + + if (this.level() instanceof ServerLevel) { +- if (this.dragonDeathTime > 150 && this.dragonDeathTime % 5 == 0 && _boolean) { +- ExperienceOrb.award((ServerLevel)this.level(), this.position(), Mth.floor((float)i * 0.08F)); ++ if (this.dragonDeathTime > 150 && this.dragonDeathTime % 5 == 0 && true) { // CraftBukkit - SPIGOT-2420: Already checked for the game rule when calculating the xp ++ ExperienceOrb.award((ServerLevel) this.level(), this.position(), Mth.floor((float) short0 * 0.08F)); + } + + if (this.dragonDeathTime == 1 && !this.isSilent()) { +@@ -572,10 +681,10 @@ + } + } + +- this.move(MoverType.SELF, new Vec3(0.0, 0.1F, 0.0)); ++ this.move(EnumMoveType.SELF, new Vec3(0.0D, 0.10000000149011612D, 0.0D)); + if (this.dragonDeathTime == 200 && this.level() instanceof ServerLevel) { +- if (_boolean) { +- ExperienceOrb.award((ServerLevel)this.level(), this.position(), Mth.floor((float)i * 0.2F)); ++ if (true) { // CraftBukkit - SPIGOT-2420: Already checked for the game rule when calculating the xp ++ ExperienceOrb.award((ServerLevel) this.level(), this.position(), Mth.floor((float) short0 * 0.2F)); + } + + if (this.dragonFight != null) { +@@ -585,33 +694,37 @@ + this.remove(Entity.RemovalReason.KILLED); + this.gameEvent(GameEvent.ENTITY_DIE); + } ++ + } + + public int findClosestNode() { + if (this.nodes[0] == null) { +- for (int i = 0; i < 24; i++) { +- int i1 = 5; +- int floor; +- int floor1; ++ for (int i = 0; i < 24; ++i) { ++ int j = 5; ++ int k; ++ int l; ++ + if (i < 12) { +- floor = Mth.floor(60.0F * Mth.cos(2.0F * ((float) -Math.PI + (float) (Math.PI / 12) * (float)i))); +- floor1 = Mth.floor(60.0F * Mth.sin(2.0F * ((float) -Math.PI + (float) (Math.PI / 12) * (float)i))); +- } else if (i < 20) { +- int i2 = i - 12; +- floor = Mth.floor(40.0F * Mth.cos(2.0F * ((float) -Math.PI + (float) (Math.PI / 8) * (float)i2))); +- floor1 = Mth.floor(40.0F * Mth.sin(2.0F * ((float) -Math.PI + (float) (Math.PI / 8) * (float)i2))); +- i1 += 10; ++ k = Mth.floor(60.0F * Mth.cos(2.0F * (-3.1415927F + 0.2617994F * (float) i))); ++ l = Mth.floor(60.0F * Mth.sin(2.0F * (-3.1415927F + 0.2617994F * (float) i))); + } else { +- int var7 = i - 20; +- floor = Mth.floor(20.0F * Mth.cos(2.0F * ((float) -Math.PI + (float) (Math.PI / 4) * (float)var7))); +- floor1 = Mth.floor(20.0F * Mth.sin(2.0F * ((float) -Math.PI + (float) (Math.PI / 4) * (float)var7))); ++ int i1; ++ ++ if (i < 20) { ++ i1 = i - 12; ++ k = Mth.floor(40.0F * Mth.cos(2.0F * (-3.1415927F + 0.3926991F * (float) i1))); ++ l = Mth.floor(40.0F * Mth.sin(2.0F * (-3.1415927F + 0.3926991F * (float) i1))); ++ j += 10; ++ } else { ++ i1 = i - 20; ++ k = Mth.floor(20.0F * Mth.cos(2.0F * (-3.1415927F + 0.7853982F * (float) i1))); ++ l = Mth.floor(20.0F * Mth.sin(2.0F * (-3.1415927F + 0.7853982F * (float) i1))); ++ } + } + +- int max = Math.max( +- this.level().getSeaLevel() + 10, +- this.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, new BlockPos(floor, 0, floor1)).getY() + i1 +- ); +- this.nodes[i] = new Node(floor, max, floor1); ++ int j1 = Math.max(this.level().getSeaLevel() + 10, this.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, new BlockPos(k, 0, l)).getY() + j); ++ ++ this.nodes[i] = new Node(k, j1, l); + } + + this.nodeAdjacency[0] = 6146; +@@ -643,21 +756,23 @@ + return this.findClosestNode(this.getX(), this.getY(), this.getZ()); + } + +- public int findClosestNode(double x, double y, double z) { ++ public int findClosestNode(double x, double d1, double y) { + float f = 10000.0F; + int i = 0; +- Node node = new Node(Mth.floor(x), Mth.floor(y), Mth.floor(z)); +- int i1 = 0; ++ Node pathpoint = new Node(Mth.floor(x), Mth.floor(d1), Mth.floor(y)); ++ byte b0 = 0; ++ + if (this.dragonFight == null || this.dragonFight.getCrystalsAlive() == 0) { +- i1 = 12; ++ b0 = 12; + } + +- for (int i2 = i1; i2 < 24; i2++) { +- if (this.nodes[i2] != null) { +- float f1 = this.nodes[i2].distanceToSqr(node); ++ for (int j = b0; j < 24; ++j) { ++ if (this.nodes[j] != null) { ++ float f1 = this.nodes[j].distanceToSqr(pathpoint); ++ + if (f1 < f) { + f = f1; +- i = i2; ++ i = j; + } + } + } +@@ -667,96 +782,118 @@ + + @Nullable + public Path findPath(int startIndex, int finishIndex, @Nullable Node andThen) { +- for (int i = 0; i < 24; i++) { +- Node node = this.nodes[i]; +- node.closed = false; +- node.f = 0.0F; +- node.g = 0.0F; +- node.h = 0.0F; +- node.cameFrom = null; +- node.heapIdx = -1; ++ Node pathpoint1; ++ ++ for (int k = 0; k < 24; ++k) { ++ pathpoint1 = this.nodes[k]; ++ pathpoint1.closed = false; ++ pathpoint1.f = 0.0F; ++ pathpoint1.g = 0.0F; ++ pathpoint1.h = 0.0F; ++ pathpoint1.cameFrom = null; ++ pathpoint1.heapIdx = -1; + } + +- Node node1 = this.nodes[startIndex]; +- Node node = this.nodes[finishIndex]; +- node1.g = 0.0F; +- node1.h = node1.distanceTo(node); +- node1.f = node1.h; ++ Node pathpoint2 = this.nodes[startIndex]; ++ ++ pathpoint1 = this.nodes[finishIndex]; ++ pathpoint2.g = 0.0F; ++ pathpoint2.h = pathpoint2.distanceTo(pathpoint1); ++ pathpoint2.f = pathpoint2.h; + this.openSet.clear(); +- this.openSet.insert(node1); +- Node node2 = node1; +- int i1 = 0; ++ this.openSet.insert(pathpoint2); ++ Node pathpoint3 = pathpoint2; ++ byte b0 = 0; ++ + if (this.dragonFight == null || this.dragonFight.getCrystalsAlive() == 0) { +- i1 = 12; ++ b0 = 12; + } + ++ label70: + while (!this.openSet.isEmpty()) { +- Node node3 = this.openSet.pop(); +- if (node3.equals(node)) { ++ Node pathpoint4 = this.openSet.pop(); ++ ++ if (pathpoint4.equals(pathpoint1)) { + if (andThen != null) { +- andThen.cameFrom = node; +- node = andThen; ++ andThen.cameFrom = pathpoint1; ++ pathpoint1 = andThen; + } + +- return this.reconstructPath(node1, node); ++ return this.reconstructPath(pathpoint2, pathpoint1); + } + +- if (node3.distanceTo(node) < node2.distanceTo(node)) { +- node2 = node3; ++ if (pathpoint4.distanceTo(pathpoint1) < pathpoint3.distanceTo(pathpoint1)) { ++ pathpoint3 = pathpoint4; + } + +- node3.closed = true; +- int i2 = 0; ++ pathpoint4.closed = true; ++ int l = 0; ++ int i1 = 0; + +- for (int i3 = 0; i3 < 24; i3++) { +- if (this.nodes[i3] == node3) { +- i2 = i3; +- break; ++ while (true) { ++ if (i1 < 24) { ++ if (this.nodes[i1] != pathpoint4) { ++ ++i1; ++ continue; ++ } ++ ++ l = i1; + } +- } + +- for (int i3x = i1; i3x < 24; i3x++) { +- if ((this.nodeAdjacency[i2] & 1 << i3x) > 0) { +- Node node4 = this.nodes[i3x]; +- if (!node4.closed) { +- float f = node3.g + node3.distanceTo(node4); +- if (!node4.inOpenSet() || f < node4.g) { +- node4.cameFrom = node3; +- node4.g = f; +- node4.h = node4.distanceTo(node); +- if (node4.inOpenSet()) { +- this.openSet.changeCost(node4, node4.g + node4.h); +- } else { +- node4.f = node4.g + node4.h; +- this.openSet.insert(node4); ++ i1 = b0; ++ ++ while (true) { ++ if (i1 >= 24) { ++ continue label70; ++ } ++ ++ if ((this.nodeAdjacency[l] & 1 << i1) > 0) { ++ Node pathpoint5 = this.nodes[i1]; ++ ++ if (!pathpoint5.closed) { ++ float f = pathpoint4.g + pathpoint4.distanceTo(pathpoint5); ++ ++ if (!pathpoint5.inOpenSet() || f < pathpoint5.g) { ++ pathpoint5.cameFrom = pathpoint4; ++ pathpoint5.g = f; ++ pathpoint5.h = pathpoint5.distanceTo(pathpoint1); ++ if (pathpoint5.inOpenSet()) { ++ this.openSet.changeCost(pathpoint5, pathpoint5.g + pathpoint5.h); ++ } else { ++ pathpoint5.f = pathpoint5.g + pathpoint5.h; ++ this.openSet.insert(pathpoint5); ++ } + } + } + } ++ ++ ++i1; + } + } + } + +- if (node2 == node1) { ++ if (pathpoint3 == pathpoint2) { + return null; + } else { +- LOGGER.debug("Failed to find path from {} to {}", startIndex, finishIndex); ++ EnderDragon.LOGGER.debug("Failed to find path from {} to {}", startIndex, finishIndex); + if (andThen != null) { +- andThen.cameFrom = node2; +- node2 = andThen; ++ andThen.cameFrom = pathpoint3; ++ pathpoint3 = andThen; + } + +- return this.reconstructPath(node1, node2); ++ return this.reconstructPath(pathpoint2, pathpoint3); + } + } + + private Path reconstructPath(Node start, Node finish) { + List list = Lists.newArrayList(); +- Node node = finish; ++ Node pathpoint2 = finish; ++ + list.add(0, finish); + +- while (node.cameFrom != null) { +- node = node.cameFrom; +- list.add(0, node); ++ while (pathpoint2.cameFrom != null) { ++ pathpoint2 = pathpoint2.cameFrom; ++ list.add(0, pathpoint2); + } + + return new Path(list, new BlockPos(finish.x, finish.y, finish.z), true); +@@ -767,6 +904,7 @@ + super.addAdditionalSaveData(compound); + compound.putInt("DragonPhase", this.phaseManager.getCurrentPhase().getPhase().getId()); + compound.putInt("DragonDeathTime", this.dragonDeathTime); ++ compound.putInt("Bukkit.expToDrop", expToDrop); // CraftBukkit - SPIGOT-2420: The ender dragon drops xp over time which can also happen between server starts + } + + @Override +@@ -779,11 +917,16 @@ + if (compound.contains("DragonDeathTime")) { + this.dragonDeathTime = compound.getInt("DragonDeathTime"); + } ++ ++ // CraftBukkit start - SPIGOT-2420: The ender dragon drops xp over time which can also happen between server starts ++ if (compound.contains("Bukkit.expToDrop")) { ++ this.expToDrop = compound.getInt("Bukkit.expToDrop"); ++ } ++ // CraftBukkit end + } + + @Override +- public void checkDespawn() { +- } ++ public void checkDespawn() {} + + public EnderDragonPart[] getSubEntities() { + return this.subEntities; +@@ -815,69 +958,81 @@ + } + + public float getHeadPartYOffset(int partIndex, double[] spineEndOffsets, double[] headPartOffsets) { +- DragonPhaseInstance currentPhase = this.phaseManager.getCurrentPhase(); +- EnderDragonPhase phase = currentPhase.getPhase(); +- double d; +- if (phase == EnderDragonPhase.LANDING || phase == EnderDragonPhase.TAKEOFF) { +- BlockPos heightmapPos = this.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.fightOrigin)); +- double max = Math.max(Math.sqrt(heightmapPos.distToCenterSqr(this.position())) / 4.0, 1.0); +- d = (double)partIndex / max; +- } else if (currentPhase.isSitting()) { +- d = (double)partIndex; +- } else if (partIndex == 6) { +- d = 0.0; ++ DragonPhaseInstance idragoncontroller = this.phaseManager.getCurrentPhase(); ++ EnderDragonPhase dragoncontrollerphase = idragoncontroller.getPhase(); ++ double d0; ++ ++ if (dragoncontrollerphase != EnderDragonPhase.LANDING && dragoncontrollerphase != EnderDragonPhase.TAKEOFF) { ++ if (idragoncontroller.isSitting()) { ++ d0 = (double) partIndex; ++ } else if (partIndex == 6) { ++ d0 = 0.0D; ++ } else { ++ d0 = headPartOffsets[1] - spineEndOffsets[1]; ++ } + } else { +- d = headPartOffsets[1] - spineEndOffsets[1]; ++ BlockPos blockposition = this.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.fightOrigin)); ++ double d1 = Math.max(Math.sqrt(blockposition.distToCenterSqr(this.position())) / 4.0D, 1.0D); ++ ++ d0 = (double) partIndex / d1; + } + +- return (float)d; ++ return (float) d0; + } + + public Vec3 getHeadLookVector(float partialTicks) { +- DragonPhaseInstance currentPhase = this.phaseManager.getCurrentPhase(); +- EnderDragonPhase phase = currentPhase.getPhase(); +- Vec3 viewVector; +- if (phase == EnderDragonPhase.LANDING || phase == EnderDragonPhase.TAKEOFF) { +- BlockPos heightmapPos = this.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.fightOrigin)); +- float max = Math.max((float)Math.sqrt(heightmapPos.distToCenterSqr(this.position())) / 4.0F, 1.0F); +- float f = 6.0F / max; +- float xRot = this.getXRot(); +- float f1 = 1.5F; +- this.setXRot(-f * 1.5F * 5.0F); +- viewVector = this.getViewVector(partialTicks); +- this.setXRot(xRot); +- } else if (currentPhase.isSitting()) { +- float xRot1 = this.getXRot(); +- float max = 1.5F; +- this.setXRot(-45.0F); +- viewVector = this.getViewVector(partialTicks); +- this.setXRot(xRot1); ++ DragonPhaseInstance idragoncontroller = this.phaseManager.getCurrentPhase(); ++ EnderDragonPhase dragoncontrollerphase = idragoncontroller.getPhase(); ++ float f1; ++ Vec3 vec3d; ++ ++ if (dragoncontrollerphase != EnderDragonPhase.LANDING && dragoncontrollerphase != EnderDragonPhase.TAKEOFF) { ++ if (idragoncontroller.isSitting()) { ++ float f2 = this.getXRot(); ++ ++ f1 = 1.5F; ++ this.setXRot(-45.0F); ++ vec3d = this.getViewVector(partialTicks); ++ this.setXRot(f2); ++ } else { ++ vec3d = this.getViewVector(partialTicks); ++ } + } else { +- viewVector = this.getViewVector(partialTicks); ++ BlockPos blockposition = this.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.fightOrigin)); ++ ++ f1 = Math.max((float) Math.sqrt(blockposition.distToCenterSqr(this.position())) / 4.0F, 1.0F); ++ float f3 = 6.0F / f1; ++ float f4 = this.getXRot(); ++ float f5 = 1.5F; ++ ++ this.setXRot(-f3 * 1.5F * 5.0F); ++ vec3d = this.getViewVector(partialTicks); ++ this.setXRot(f4); + } + +- return viewVector; ++ return vec3d; + } + + public void onCrystalDestroyed(EndCrystal crystal, BlockPos pos, DamageSource damageSource) { +- Player player; ++ Player entityhuman; ++ + if (damageSource.getEntity() instanceof Player) { +- player = (Player)damageSource.getEntity(); ++ entityhuman = (Player) damageSource.getEntity(); + } else { +- player = this.level().getNearestPlayer(CRYSTAL_DESTROY_TARGETING, (double)pos.getX(), (double)pos.getY(), (double)pos.getZ()); ++ entityhuman = this.level().getNearestPlayer(EnderDragon.CRYSTAL_DESTROY_TARGETING, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ()); + } + + if (crystal == this.nearestCrystal) { +- this.hurt(this.head, this.damageSources().explosion(crystal, player), 10.0F); ++ this.hurt(this.head, this.damageSources().explosion(crystal, entityhuman), 10.0F); + } + +- this.phaseManager.getCurrentPhase().onCrystalDestroyed(crystal, pos, damageSource, player); ++ this.phaseManager.getCurrentPhase().onCrystalDestroyed(crystal, pos, damageSource, entityhuman); + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { +- if (DATA_PHASE.equals(key) && this.level().isClientSide) { +- this.phaseManager.setPhase(EnderDragonPhase.getById(this.getEntityData().get(DATA_PHASE))); ++ if (EnderDragon.DATA_PHASE.equals(key) && this.level().isClientSide) { ++ this.phaseManager.setPhase(EnderDragonPhase.getById((Integer) this.getEntityData().get(EnderDragon.DATA_PHASE))); + } + + super.onSyncedDataUpdated(key); +@@ -910,11 +1065,12 @@ + @Override + public void recreateFromPacket(ClientboundAddEntityPacket packet) { + super.recreateFromPacket(packet); +- EnderDragonPart[] subEntities = this.getSubEntities(); ++ EnderDragonPart[] aentitycomplexpart = this.getSubEntities(); + +- for (int i = 0; i < subEntities.length; i++) { +- subEntities[i].setId(i + packet.getId()); ++ for (int i = 0; i < aentitycomplexpart.length; ++i) { ++ aentitycomplexpart[i].setId(i + packet.getId()); + } ++ + } + + @Override +@@ -923,7 +1079,7 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { + return new Vector3f(0.0F, this.body.getBbHeight(), 0.0F); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhaseManager.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhaseManager.java.patch new file mode 100644 index 0000000000..4ad1d55b07 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhaseManager.java.patch @@ -0,0 +1,61 @@ +--- a/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhaseManager.java ++++ b/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhaseManager.java +@@ -5,7 +5,13 @@ + import net.minecraft.world.entity.boss.enderdragon.EnderDragon; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftEnderDragon; ++import org.bukkit.event.entity.EnderDragonChangePhaseEvent; ++// CraftBukkit end ++ + public class EnderDragonPhaseManager { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private final EnderDragon dragon; + private final DragonPhaseInstance[] phases = new DragonPhaseInstance[EnderDragonPhase.getCount()]; +@@ -23,12 +29,25 @@ + this.currentPhase.end(); + } + +- this.currentPhase = this.getPhase((EnderDragonPhase)phase); ++ // CraftBukkit start - Call EnderDragonChangePhaseEvent ++ EnderDragonChangePhaseEvent event = new EnderDragonChangePhaseEvent( ++ (CraftEnderDragon) this.dragon.getBukkitEntity(), ++ (this.currentPhase == null) ? null : CraftEnderDragon.getBukkitPhase(this.currentPhase.getPhase()), ++ CraftEnderDragon.getBukkitPhase(phase) ++ ); ++ this.dragon.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ phase = CraftEnderDragon.getMinecraftPhase(event.getNewPhase()); ++ // CraftBukkit end ++ ++ this.currentPhase = this.getPhase(phase); + if (!this.dragon.level().isClientSide) { + this.dragon.getEntityData().set(EnderDragon.DATA_PHASE, phase.getId()); + } + +- LOGGER.debug("Dragon is now in phase {} on the {}", phase, this.dragon.level().isClientSide ? "client" : "server"); ++ EnderDragonPhaseManager.LOGGER.debug("Dragon is now in phase {} on the {}", phase, this.dragon.level().isClientSide ? "client" : "server"); + this.currentPhase.begin(); + } + } +@@ -38,11 +57,12 @@ + } + + public T getPhase(EnderDragonPhase phase) { +- int id = phase.getId(); +- if (this.phases[id] == null) { +- this.phases[id] = phase.createInstance(this.dragon); ++ int i = phase.getId(); ++ ++ if (this.phases[i] == null) { ++ this.phases[i] = phase.createInstance(this.dragon); + } + +- return (T)this.phases[id]; ++ return (T) this.phases[i]; // CraftBukkit - decompile error + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/boss/wither/WitherBoss.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/boss/wither/WitherBoss.java.patch new file mode 100644 index 0000000000..2d0d2afbca --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/boss/wither/WitherBoss.java.patch @@ -0,0 +1,751 @@ +--- a/net/minecraft/world/entity/boss/wither/WitherBoss.java ++++ b/net/minecraft/world/entity/boss/wither/WitherBoss.java +@@ -5,17 +5,6 @@ + import java.util.List; + import java.util.function.Predicate; + import javax.annotation.Nullable; +-import net.minecraft.core.BlockPos; +-import net.minecraft.core.particles.ParticleTypes; +-import net.minecraft.nbt.CompoundTag; +-import net.minecraft.network.chat.Component; +-import net.minecraft.network.syncher.EntityDataAccessor; +-import net.minecraft.network.syncher.EntityDataSerializers; +-import net.minecraft.network.syncher.SynchedEntityData; +-import net.minecraft.server.level.ServerBossEvent; +-import net.minecraft.server.level.ServerPlayer; +-import net.minecraft.sounds.SoundEvent; +-import net.minecraft.sounds.SoundEvents; + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.DamageTypeTags; + import net.minecraft.util.Mth; +@@ -26,17 +15,17 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobType; + import net.minecraft.world.entity.PowerableMob; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.FlyingMoveControl; + import net.minecraft.world.entity.ai.goal.Goal; + import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalRandomFly; + import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal; + import net.minecraft.world.entity.ai.goal.RangedAttackGoal; +-import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomFlyingGoal; + import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal; + import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; + import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation; +@@ -50,15 +39,37 @@ + import net.minecraft.world.entity.projectile.WitherSkull; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.GameRules; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.particles.ParticleTypes; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.network.chat.Component; ++import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; ++import net.minecraft.network.syncher.EntityDataAccessor; ++import net.minecraft.network.syncher.EntityDataSerializers; ++import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerBossEvent; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundEvents; ++import net.minecraft.world.level.block.Blocks; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end + + public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob { ++ + private static final EntityDataAccessor DATA_TARGET_A = SynchedEntityData.defineId(WitherBoss.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_TARGET_B = SynchedEntityData.defineId(WitherBoss.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_TARGET_C = SynchedEntityData.defineId(WitherBoss.class, EntityDataSerializers.INT); +- private static final List> DATA_TARGETS = ImmutableList.of(DATA_TARGET_A, DATA_TARGET_B, DATA_TARGET_C); ++ private static final List> DATA_TARGETS = ImmutableList.of(WitherBoss.DATA_TARGET_A, WitherBoss.DATA_TARGET_B, WitherBoss.DATA_TARGET_C); + private static final EntityDataAccessor DATA_ID_INV = SynchedEntityData.defineId(WitherBoss.class, EntityDataSerializers.INT); + private static final int INVULNERABLE_TICKS = 220; + private final float[] xRotHeads = new float[2]; +@@ -68,15 +79,15 @@ + private final int[] nextHeadUpdate = new int[2]; + private final int[] idleHeadUpdates = new int[2]; + private int destroyBlocksTick; +- private final ServerBossEvent bossEvent = (ServerBossEvent)new ServerBossEvent( +- this.getDisplayName(), BossEvent.BossBarColor.PURPLE, BossEvent.BossBarOverlay.PROGRESS +- ) +- .setDarkenScreen(true); +- private static final Predicate LIVING_ENTITY_SELECTOR = entity -> entity.getMobType() != MobType.UNDEAD && entity.attackable(); +- private static final TargetingConditions TARGETING_CONDITIONS = TargetingConditions.forCombat().range(20.0).selector(LIVING_ENTITY_SELECTOR); ++ public final ServerBossEvent bossEvent; ++ private static final Predicate LIVING_ENTITY_SELECTOR = (entityliving) -> { ++ return entityliving.getMobType() != EnumMonsterType.UNDEAD && entityliving.attackable(); ++ }; ++ private static final TargetingConditions TARGETING_CONDITIONS = TargetingConditions.forCombat().range(20.0D).selector(WitherBoss.LIVING_ENTITY_SELECTOR); + + public WitherBoss(EntityType entityType, Level level) { + super(entityType, level); ++ this.bossEvent = (ServerBossEvent) (new ServerBossEvent(this.getDisplayName(), BossEvent.BossBarColor.PURPLE, BossEvent.BossBarOverlay.PROGRESS)).setDarkenScreen(true); + this.moveControl = new FlyingMoveControl(this, 10, false); + this.setHealth(this.getMaxHealth()); + this.xpReward = 50; +@@ -84,31 +95,32 @@ + + @Override + protected PathNavigation createNavigation(Level level) { +- FlyingPathNavigation flyingPathNavigation = new FlyingPathNavigation(this, level); +- flyingPathNavigation.setCanOpenDoors(false); +- flyingPathNavigation.setCanFloat(true); +- flyingPathNavigation.setCanPassDoors(true); +- return flyingPathNavigation; ++ FlyingPathNavigation navigationflying = new FlyingPathNavigation(this, level); ++ ++ navigationflying.setCanOpenDoors(false); ++ navigationflying.setCanFloat(true); ++ navigationflying.setCanPassDoors(true); ++ return navigationflying; + } + + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new WitherBoss.WitherDoNothingGoal()); +- this.goalSelector.addGoal(2, new RangedAttackGoal(this, 1.0, 40, 20.0F)); +- this.goalSelector.addGoal(5, new WaterAvoidingRandomFlyingGoal(this, 1.0)); ++ this.goalSelector.addGoal(2, new RangedAttackGoal(this, 1.0D, 40, 20.0F)); ++ this.goalSelector.addGoal(5, new PathfinderGoalRandomFly(this, 1.0D)); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(7, new RandomLookAroundGoal(this)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this)); +- this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, LivingEntity.class, 0, false, false, LIVING_ENTITY_SELECTOR)); ++ this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0])); ++ this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, LivingEntity.class, 0, false, false, WitherBoss.LIVING_ENTITY_SELECTOR)); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_TARGET_A, 0); +- this.entityData.define(DATA_TARGET_B, 0); +- this.entityData.define(DATA_TARGET_C, 0); +- this.entityData.define(DATA_ID_INV, 0); ++ this.entityData.define(WitherBoss.DATA_TARGET_A, 0); ++ this.entityData.define(WitherBoss.DATA_TARGET_B, 0); ++ this.entityData.define(WitherBoss.DATA_TARGET_C, 0); ++ this.entityData.define(WitherBoss.DATA_ID_INV, 0); + } + + @Override +@@ -124,6 +136,7 @@ + if (this.hasCustomName()) { + this.bossEvent.setName(this.getDisplayName()); + } ++ + } + + @Override +@@ -149,54 +162,65 @@ + + @Override + public void aiStep() { +- Vec3 vec3 = this.getDeltaMovement().multiply(1.0, 0.6, 1.0); ++ Vec3 vec3d = this.getDeltaMovement().multiply(1.0D, 0.6D, 1.0D); ++ + if (!this.level().isClientSide && this.getAlternativeTarget(0) > 0) { + Entity entity = this.level().getEntity(this.getAlternativeTarget(0)); ++ + if (entity != null) { +- double d = vec3.y; +- if (this.getY() < entity.getY() || !this.isPowered() && this.getY() < entity.getY() + 5.0) { +- d = Math.max(0.0, d); +- d += 0.3 - d * 0.6F; ++ double d0 = vec3d.y; ++ ++ if (this.getY() < entity.getY() || !this.isPowered() && this.getY() < entity.getY() + 5.0D) { ++ d0 = Math.max(0.0D, d0); ++ d0 += 0.3D - d0 * 0.6000000238418579D; + } + +- vec3 = new Vec3(vec3.x, d, vec3.z); +- Vec3 vec31 = new Vec3(entity.getX() - this.getX(), 0.0, entity.getZ() - this.getZ()); +- if (vec31.horizontalDistanceSqr() > 9.0) { +- Vec3 vec32 = vec31.normalize(); +- vec3 = vec3.add(vec32.x * 0.3 - vec3.x * 0.6, 0.0, vec32.z * 0.3 - vec3.z * 0.6); ++ vec3d = new Vec3(vec3d.x, d0, vec3d.z); ++ Vec3 vec3d1 = new Vec3(entity.getX() - this.getX(), 0.0D, entity.getZ() - this.getZ()); ++ ++ if (vec3d1.horizontalDistanceSqr() > 9.0D) { ++ Vec3 vec3d2 = vec3d1.normalize(); ++ ++ vec3d = vec3d.add(vec3d2.x * 0.3D - vec3d.x * 0.6D, 0.0D, vec3d2.z * 0.3D - vec3d.z * 0.6D); + } + } + } + +- this.setDeltaMovement(vec3); +- if (vec3.horizontalDistanceSqr() > 0.05) { +- this.setYRot((float)Mth.atan2(vec3.z, vec3.x) * (180.0F / (float)Math.PI) - 90.0F); ++ this.setDeltaMovement(vec3d); ++ if (vec3d.horizontalDistanceSqr() > 0.05D) { ++ this.setYRot((float) Mth.atan2(vec3d.z, vec3d.x) * 57.295776F - 90.0F); + } + + super.aiStep(); + +- for (int i = 0; i < 2; i++) { ++ int i; ++ ++ for (i = 0; i < 2; ++i) { + this.yRotOHeads[i] = this.yRotHeads[i]; + this.xRotOHeads[i] = this.xRotHeads[i]; + } + +- for (int i = 0; i < 2; i++) { +- int alternativeTarget = this.getAlternativeTarget(i + 1); ++ int j; ++ ++ for (i = 0; i < 2; ++i) { ++ j = this.getAlternativeTarget(i + 1); + Entity entity1 = null; +- if (alternativeTarget > 0) { +- entity1 = this.level().getEntity(alternativeTarget); ++ ++ if (j > 0) { ++ entity1 = this.level().getEntity(j); + } + + if (entity1 != null) { +- double headX = this.getHeadX(i + 1); +- double headY = this.getHeadY(i + 1); +- double headZ = this.getHeadZ(i + 1); +- double d1 = entity1.getX() - headX; +- double d2 = entity1.getEyeY() - headY; +- double d3 = entity1.getZ() - headZ; +- double squareRoot = Math.sqrt(d1 * d1 + d3 * d3); +- float f = (float)(Mth.atan2(d3, d1) * 180.0F / (float)Math.PI) - 90.0F; +- float f1 = (float)(-(Mth.atan2(d2, squareRoot) * 180.0F / (float)Math.PI)); ++ double d1 = this.getHeadX(i + 1); ++ double d2 = this.getHeadY(i + 1); ++ double d3 = this.getHeadZ(i + 1); ++ double d4 = entity1.getX() - d1; ++ double d5 = entity1.getEyeY() - d2; ++ double d6 = entity1.getZ() - d3; ++ double d7 = Math.sqrt(d4 * d4 + d6 * d6); ++ float f = (float) (Mth.atan2(d6, d4) * 57.2957763671875D) - 90.0F; ++ float f1 = (float) (-(Mth.atan2(d5, d7) * 57.2957763671875D)); ++ + this.xRotHeads[i] = this.rotlerp(this.xRotHeads[i], f1, 40.0F); + this.yRotHeads[i] = this.rotlerp(this.yRotHeads[i], f, 10.0F); + } else { +@@ -204,104 +228,115 @@ + } + } + +- boolean isPowered = this.isPowered(); ++ boolean flag = this.isPowered(); + +- for (int alternativeTargetx = 0; alternativeTargetx < 3; alternativeTargetx++) { +- double headX1 = this.getHeadX(alternativeTargetx); +- double headY1 = this.getHeadY(alternativeTargetx); +- double headZ1 = this.getHeadZ(alternativeTargetx); +- this.level() +- .addParticle( +- ParticleTypes.SMOKE, +- headX1 + this.random.nextGaussian() * 0.3F, +- headY1 + this.random.nextGaussian() * 0.3F, +- headZ1 + this.random.nextGaussian() * 0.3F, +- 0.0, +- 0.0, +- 0.0 +- ); +- if (isPowered && this.level().random.nextInt(4) == 0) { +- this.level() +- .addParticle( +- ParticleTypes.ENTITY_EFFECT, +- headX1 + this.random.nextGaussian() * 0.3F, +- headY1 + this.random.nextGaussian() * 0.3F, +- headZ1 + this.random.nextGaussian() * 0.3F, +- 0.7F, +- 0.7F, +- 0.5 +- ); ++ for (j = 0; j < 3; ++j) { ++ double d8 = this.getHeadX(j); ++ double d9 = this.getHeadY(j); ++ double d10 = this.getHeadZ(j); ++ ++ this.level().addParticle(ParticleTypes.SMOKE, d8 + this.random.nextGaussian() * 0.30000001192092896D, d9 + this.random.nextGaussian() * 0.30000001192092896D, d10 + this.random.nextGaussian() * 0.30000001192092896D, 0.0D, 0.0D, 0.0D); ++ if (flag && this.level().random.nextInt(4) == 0) { ++ this.level().addParticle(ParticleTypes.ENTITY_EFFECT, d8 + this.random.nextGaussian() * 0.30000001192092896D, d9 + this.random.nextGaussian() * 0.30000001192092896D, d10 + this.random.nextGaussian() * 0.30000001192092896D, 0.699999988079071D, 0.699999988079071D, 0.5D); + } + } + + if (this.getInvulnerableTicks() > 0) { +- for (int alternativeTargetxx = 0; alternativeTargetxx < 3; alternativeTargetxx++) { +- this.level() +- .addParticle( +- ParticleTypes.ENTITY_EFFECT, +- this.getX() + this.random.nextGaussian(), +- this.getY() + (double)(this.random.nextFloat() * 3.3F), +- this.getZ() + this.random.nextGaussian(), +- 0.7F, +- 0.7F, +- 0.9F +- ); ++ for (j = 0; j < 3; ++j) { ++ this.level().addParticle(ParticleTypes.ENTITY_EFFECT, this.getX() + this.random.nextGaussian(), this.getY() + (double) (this.random.nextFloat() * 3.3F), this.getZ() + this.random.nextGaussian(), 0.699999988079071D, 0.699999988079071D, 0.8999999761581421D); + } + } ++ + } + + @Override + protected void customServerAiStep() { ++ int i; ++ + if (this.getInvulnerableTicks() > 0) { +- int i = this.getInvulnerableTicks() - 1; +- this.bossEvent.setProgress(1.0F - (float)i / 220.0F); ++ i = this.getInvulnerableTicks() - 1; ++ this.bossEvent.setProgress(1.0F - (float) i / 220.0F); + if (i <= 0) { +- this.level().explode(this, this.getX(), this.getEyeY(), this.getZ(), 7.0F, false, Level.ExplosionInteraction.MOB); ++ // CraftBukkit start ++ // this.level().explode(this, this.getX(), this.getEyeY(), this.getZ(), 7.0F, false, World.a.MOB); ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), 7.0F, false); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ this.level().explode(this, this.getX(), this.getEyeY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.MOB); ++ } ++ // CraftBukkit end ++ + if (!this.isSilent()) { +- this.level().globalLevelEvent(1023, this.blockPosition(), 0); ++ // CraftBukkit start - Use relative location for far away sounds ++ // this.level().globalLevelEvent(1023, new BlockPosition(this), 0); ++ int viewDistance = ((ServerLevel) this.level()).getCraftServer().getViewDistance() * 16; ++ for (ServerPlayer player : (List) MinecraftServer.getServer().getPlayerList().players) { ++ double deltaX = this.getX() - player.getX(); ++ double deltaZ = this.getZ() - player.getZ(); ++ double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; ++ if (distanceSquared > viewDistance * viewDistance) { ++ double deltaLength = Math.sqrt(distanceSquared); ++ double relativeX = player.getX() + (deltaX / deltaLength) * viewDistance; ++ double relativeZ = player.getZ() + (deltaZ / deltaLength) * viewDistance; ++ player.connection.send(new ClientboundLevelEventPacket(1023, new BlockPos((int) relativeX, (int) this.getY(), (int) relativeZ), 0, true)); ++ } else { ++ player.connection.send(new ClientboundLevelEventPacket(1023, this.blockPosition(), 0, true)); ++ } ++ } ++ // CraftBukkit end + } + } + + this.setInvulnerableTicks(i); + if (this.tickCount % 10 == 0) { +- this.heal(10.0F); ++ this.heal(10.0F, EntityRegainHealthEvent.RegainReason.WITHER_SPAWN); // CraftBukkit + } ++ + } else { + super.customServerAiStep(); + +- for (int ix = 1; ix < 3; ix++) { +- if (this.tickCount >= this.nextHeadUpdate[ix - 1]) { +- this.nextHeadUpdate[ix - 1] = this.tickCount + 10 + this.random.nextInt(10); +- if ((this.level().getDifficulty() == Difficulty.NORMAL || this.level().getDifficulty() == Difficulty.HARD) +- && this.idleHeadUpdates[ix - 1]++ > 15) { +- float f = 10.0F; +- float f1 = 5.0F; +- double randomDouble = Mth.nextDouble(this.random, this.getX() - 10.0, this.getX() + 10.0); +- double randomDouble1 = Mth.nextDouble(this.random, this.getY() - 5.0, this.getY() + 5.0); +- double randomDouble2 = Mth.nextDouble(this.random, this.getZ() - 10.0, this.getZ() + 10.0); +- this.performRangedAttack(ix + 1, randomDouble, randomDouble1, randomDouble2, true); +- this.idleHeadUpdates[ix - 1] = 0; ++ int j; ++ ++ for (i = 1; i < 3; ++i) { ++ if (this.tickCount >= this.nextHeadUpdate[i - 1]) { ++ this.nextHeadUpdate[i - 1] = this.tickCount + 10 + this.random.nextInt(10); ++ if (this.level().getDifficulty() == Difficulty.NORMAL || this.level().getDifficulty() == Difficulty.HARD) { ++ int k = i - 1; ++ int l = this.idleHeadUpdates[i - 1]; ++ ++ this.idleHeadUpdates[k] = this.idleHeadUpdates[i - 1] + 1; ++ if (l > 15) { ++ float f = 10.0F; ++ float f1 = 5.0F; ++ double d0 = Mth.nextDouble(this.random, this.getX() - 10.0D, this.getX() + 10.0D); ++ double d1 = Mth.nextDouble(this.random, this.getY() - 5.0D, this.getY() + 5.0D); ++ double d2 = Mth.nextDouble(this.random, this.getZ() - 10.0D, this.getZ() + 10.0D); ++ ++ this.performRangedAttack(i + 1, d0, d1, d2, true); ++ this.idleHeadUpdates[i - 1] = 0; ++ } + } + +- int alternativeTarget = this.getAlternativeTarget(ix); +- if (alternativeTarget > 0) { +- LivingEntity livingEntity = (LivingEntity)this.level().getEntity(alternativeTarget); +- if (livingEntity != null +- && this.canAttack(livingEntity) +- && !(this.distanceToSqr(livingEntity) > 900.0) +- && this.hasLineOfSight(livingEntity)) { +- this.performRangedAttack(ix + 1, livingEntity); +- this.nextHeadUpdate[ix - 1] = this.tickCount + 40 + this.random.nextInt(20); +- this.idleHeadUpdates[ix - 1] = 0; ++ j = this.getAlternativeTarget(i); ++ if (j > 0) { ++ LivingEntity entityliving = (LivingEntity) this.level().getEntity(j); ++ ++ if (entityliving != null && this.canAttack(entityliving) && this.distanceToSqr((Entity) entityliving) <= 900.0D && this.hasLineOfSight(entityliving)) { ++ this.performRangedAttack(i + 1, entityliving); ++ this.nextHeadUpdate[i - 1] = this.tickCount + 40 + this.random.nextInt(20); ++ this.idleHeadUpdates[i - 1] = 0; + } else { +- this.setAlternativeTarget(ix, 0); ++ this.setAlternativeTarget(i, 0); + } + } else { +- List nearbyEntities = this.level() +- .getNearbyEntities(LivingEntity.class, TARGETING_CONDITIONS, this, this.getBoundingBox().inflate(20.0, 8.0, 20.0)); +- if (!nearbyEntities.isEmpty()) { +- LivingEntity livingEntity1 = nearbyEntities.get(this.random.nextInt(nearbyEntities.size())); +- this.setAlternativeTarget(ix, livingEntity1.getId()); ++ List list = this.level().getNearbyEntities(LivingEntity.class, WitherBoss.TARGETING_CONDITIONS, this, this.getBoundingBox().inflate(20.0D, 8.0D, 20.0D)); ++ ++ if (!list.isEmpty()) { ++ LivingEntity entityliving1 = (LivingEntity) list.get(this.random.nextInt(list.size())); ++ ++ if (CraftEventFactory.callEntityTargetLivingEvent(this, entityliving1, EntityTargetEvent.TargetReason.CLOSEST_ENTITY).isCancelled()) continue; // CraftBukkit ++ this.setAlternativeTarget(i, entityliving1.getId()); + } + } + } +@@ -314,43 +349,49 @@ + } + + if (this.destroyBlocksTick > 0) { +- this.destroyBlocksTick--; ++ --this.destroyBlocksTick; + if (this.destroyBlocksTick == 0 && this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- int ixx = Mth.floor(this.getY()); +- int alternativeTarget = Mth.floor(this.getX()); +- int floor = Mth.floor(this.getZ()); ++ i = Mth.floor(this.getY()); ++ j = Mth.floor(this.getX()); ++ int i1 = Mth.floor(this.getZ()); + boolean flag = false; + +- for (int i1 = -1; i1 <= 1; i1++) { +- for (int i2 = -1; i2 <= 1; i2++) { +- for (int i3 = 0; i3 <= 3; i3++) { +- int i4 = alternativeTarget + i1; +- int i5 = ixx + i3; +- int i6 = floor + i2; +- BlockPos blockPos = new BlockPos(i4, i5, i6); +- BlockState blockState = this.level().getBlockState(blockPos); +- if (canDestroy(blockState)) { +- flag = this.level().destroyBlock(blockPos, true, this) || flag; ++ for (int j1 = -1; j1 <= 1; ++j1) { ++ for (int k1 = -1; k1 <= 1; ++k1) { ++ for (int l1 = 0; l1 <= 3; ++l1) { ++ int i2 = j + j1; ++ int j2 = i + l1; ++ int k2 = i1 + k1; ++ BlockPos blockposition = new BlockPos(i2, j2, k2); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); ++ ++ if (canDestroy(iblockdata)) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState())) { ++ continue; ++ } ++ // CraftBukkit end ++ flag = this.level().destroyBlock(blockposition, true, this) || flag; + } + } + } + } + + if (flag) { +- this.level().levelEvent(null, 1022, this.blockPosition(), 0); ++ this.level().levelEvent((Player) null, 1022, this.blockPosition(), 0); + } + } + } + + if (this.tickCount % 20 == 0) { +- this.heal(1.0F); ++ this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit + } + + this.bossEvent.setProgress(this.getHealth() / this.getMaxHealth()); + } + } + +- public static boolean canDestroy(BlockState state) { ++ public static boolean canDestroy(IBlockData state) { + return !state.isAir() && !state.is(BlockTags.WITHER_IMMUNE); + } + +@@ -361,8 +402,7 @@ + } + + @Override +- public void makeStuckInBlock(BlockState state, Vec3 motionMultiplier) { +- } ++ public void makeStuckInBlock(IBlockData state, Vec3 motionMultiplier) {} + + @Override + public void startSeenByPlayer(ServerPlayer player) { +@@ -380,64 +420,66 @@ + if (head <= 0) { + return this.getX(); + } else { +- float f = (this.yBodyRot + (float)(180 * (head - 1))) * (float) (Math.PI / 180.0); +- float cos = Mth.cos(f); +- return this.getX() + (double)cos * 1.3; ++ float f = (this.yBodyRot + (float) (180 * (head - 1))) * 0.017453292F; ++ float f1 = Mth.cos(f); ++ ++ return this.getX() + (double) f1 * 1.3D; + } + } + + private double getHeadY(int head) { +- return head <= 0 ? this.getY() + 3.0 : this.getY() + 2.2; ++ return head <= 0 ? this.getY() + 3.0D : this.getY() + 2.2D; + } + + private double getHeadZ(int head) { + if (head <= 0) { + return this.getZ(); + } else { +- float f = (this.yBodyRot + (float)(180 * (head - 1))) * (float) (Math.PI / 180.0); +- float sin = Mth.sin(f); +- return this.getZ() + (double)sin * 1.3; ++ float f = (this.yBodyRot + (float) (180 * (head - 1))) * 0.017453292F; ++ float f1 = Mth.sin(f); ++ ++ return this.getZ() + (double) f1 * 1.3D; + } + } + +- private float rotlerp(float angle, float f, float f1) { +- float f2 = Mth.wrapDegrees(f - angle); +- if (f2 > f1) { +- f2 = f1; ++ private float rotlerp(float angle, float f1, float f2) { ++ float f3 = Mth.wrapDegrees(f1 - angle); ++ ++ if (f3 > f2) { ++ f3 = f2; + } + +- if (f2 < -f1) { +- f2 = -f1; ++ if (f3 < -f2) { ++ f3 = -f2; + } + +- return angle + f2; ++ return angle + f3; + } + + private void performRangedAttack(int head, LivingEntity target) { +- this.performRangedAttack( +- head, target.getX(), target.getY() + (double)target.getEyeHeight() * 0.5, target.getZ(), head == 0 && this.random.nextFloat() < 0.001F +- ); ++ this.performRangedAttack(head, target.getX(), target.getY() + (double) target.getEyeHeight() * 0.5D, target.getZ(), head == 0 && this.random.nextFloat() < 0.001F); + } + +- private void performRangedAttack(int head, double x, double y, double z, boolean isDangerous) { ++ private void performRangedAttack(int head, double x, double d1, double y, boolean flag) { + if (!this.isSilent()) { +- this.level().levelEvent(null, 1024, this.blockPosition(), 0); ++ this.level().levelEvent((Player) null, 1024, this.blockPosition(), 0); + } + +- double headX = this.getHeadX(head); +- double headY = this.getHeadY(head); +- double headZ = this.getHeadZ(head); +- double d = x - headX; +- double d1 = y - headY; +- double d2 = z - headZ; +- WitherSkull witherSkull = new WitherSkull(this.level(), this, d, d1, d2); +- witherSkull.setOwner(this); +- if (isDangerous) { +- witherSkull.setDangerous(true); ++ double d3 = this.getHeadX(head); ++ double d4 = this.getHeadY(head); ++ double d5 = this.getHeadZ(head); ++ double d6 = x - d3; ++ double d7 = d1 - d4; ++ double d8 = y - d5; ++ WitherSkull entitywitherskull = new WitherSkull(this.level(), this, d6, d7, d8); ++ ++ entitywitherskull.setOwner(this); ++ if (flag) { ++ entitywitherskull.setDangerous(true); + } + +- witherSkull.setPosRaw(headX, headY, headZ); +- this.level().addFreshEntity(witherSkull); ++ entitywitherskull.setPosRaw(d3, d4, d5); ++ this.level().addFreshEntity(entitywitherskull); + } + + @Override +@@ -449,45 +491,48 @@ + public boolean hurt(DamageSource source, float amount) { + if (this.isInvulnerableTo(source)) { + return false; +- } else if (source.is(DamageTypeTags.WITHER_IMMUNE_TO) || source.getEntity() instanceof WitherBoss) { +- return false; +- } else if (this.getInvulnerableTicks() > 0 && !source.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { +- return false; +- } else { +- if (this.isPowered()) { +- Entity directEntity = source.getDirectEntity(); +- if (directEntity instanceof AbstractArrow) { +- return false; +- } +- } +- +- Entity directEntity = source.getEntity(); +- if (directEntity != null +- && !(directEntity instanceof Player) +- && directEntity instanceof LivingEntity +- && ((LivingEntity)directEntity).getMobType() == this.getMobType()) { ++ } else if (!source.is(DamageTypeTags.WITHER_IMMUNE_TO) && !(source.getEntity() instanceof WitherBoss)) { ++ if (this.getInvulnerableTicks() > 0 && !source.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { + return false; + } else { +- if (this.destroyBlocksTick <= 0) { +- this.destroyBlocksTick = 20; +- } ++ Entity entity; + +- for (int i = 0; i < this.idleHeadUpdates.length; i++) { +- this.idleHeadUpdates[i] = this.idleHeadUpdates[i] + 3; ++ if (this.isPowered()) { ++ entity = source.getDirectEntity(); ++ if (entity instanceof AbstractArrow) { ++ return false; ++ } + } + +- return super.hurt(source, amount); ++ entity = source.getEntity(); ++ if (entity != null && !(entity instanceof Player) && entity instanceof LivingEntity && ((LivingEntity) entity).getMobType() == this.getMobType()) { ++ return false; ++ } else { ++ if (this.destroyBlocksTick <= 0) { ++ this.destroyBlocksTick = 20; ++ } ++ ++ for (int i = 0; i < this.idleHeadUpdates.length; ++i) { ++ this.idleHeadUpdates[i] += 3; ++ } ++ ++ return super.hurt(source, amount); ++ } + } ++ } else { ++ return false; + } + } + + @Override + protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { + super.dropCustomDeathLoot(source, looting, recentlyHit); +- ItemEntity itemEntity = this.spawnAtLocation(Items.NETHER_STAR); +- if (itemEntity != null) { +- itemEntity.setExtendedLifetime(); ++ ItemEntity entityitem = this.spawnAtLocation((IMaterial) Items.NETHER_STAR); ++ ++ if (entityitem != null) { ++ entityitem.setExtendedLifetime(); + } ++ + } + + @Override +@@ -505,12 +550,7 @@ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes() +- .add(Attributes.MAX_HEALTH, 300.0) +- .add(Attributes.MOVEMENT_SPEED, 0.6F) +- .add(Attributes.FLYING_SPEED, 0.6F) +- .add(Attributes.FOLLOW_RANGE, 40.0) +- .add(Attributes.ARMOR, 4.0); ++ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 300.0D).add(Attributes.MOVEMENT_SPEED, 0.6000000238418579D).add(Attributes.FLYING_SPEED, 0.6000000238418579D).add(Attributes.FOLLOW_RANGE, 40.0D).add(Attributes.ARMOR, 4.0D); + } + + public float getHeadYRot(int head) { +@@ -522,19 +562,19 @@ + } + + public int getInvulnerableTicks() { +- return this.entityData.get(DATA_ID_INV); ++ return (Integer) this.entityData.get(WitherBoss.DATA_ID_INV); + } + + public void setInvulnerableTicks(int invulnerableTicks) { +- this.entityData.set(DATA_ID_INV, invulnerableTicks); ++ this.entityData.set(WitherBoss.DATA_ID_INV, invulnerableTicks); + } + + public int getAlternativeTarget(int head) { +- return this.entityData.get(DATA_TARGETS.get(head)); ++ return (Integer) this.entityData.get((EntityDataAccessor) WitherBoss.DATA_TARGETS.get(head)); + } + + public void setAlternativeTarget(int targetOffset, int newId) { +- this.entityData.set(DATA_TARGETS.get(targetOffset), newId); ++ this.entityData.set((EntityDataAccessor) WitherBoss.DATA_TARGETS.get(targetOffset), newId); + } + + @Override +@@ -543,8 +583,8 @@ + } + + @Override +- public MobType getMobType() { +- return MobType.UNDEAD; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.UNDEAD; + } + + @Override +@@ -559,12 +599,13 @@ + + @Override + public boolean canBeAffected(MobEffectInstance potioneffect) { +- return potioneffect.getEffect() != MobEffects.WITHER && super.canBeAffected(potioneffect); ++ return potioneffect.getEffect() == MobEffects.WITHER ? false : super.canBeAffected(potioneffect); + } + +- class WitherDoNothingGoal extends Goal { ++ private class WitherDoNothingGoal extends Goal { ++ + public WitherDoNothingGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.JUMP, Goal.Flag.LOOK)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.JUMP, Goal.Type.LOOK)); + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/decoration/ArmorStand.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/decoration/ArmorStand.java.patch new file mode 100644 index 0000000000..a1da23e549 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/decoration/ArmorStand.java.patch @@ -0,0 +1,1099 @@ +--- a/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -1,5 +1,7 @@ + package net.minecraft.world.entity.decoration; + ++import java.util.Iterator; ++import java.util.List; + import java.util.function.Predicate; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +@@ -16,33 +18,39 @@ + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.tags.DamageTypeTags; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.HumanoidArm; + import net.minecraft.world.entity.LightningBolt; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.vehicle.AbstractMinecart; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; ++import net.minecraft.world.level.EnumSkyBlock; + import net.minecraft.world.level.Explosion; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.gameevent.GameEvent; +-import net.minecraft.world.level.material.PushReaction; ++import net.minecraft.world.level.material.EnumPistonReaction; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.inventory.EquipmentSlot; ++import org.bukkit.craftbukkit.CraftEquipmentSlot; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerArmorStandManipulateEvent; ++// CraftBukkit end + + public class ArmorStand extends LivingEntity { ++ + public static final int WOBBLE_TIME = 5; + private static final boolean ENABLE_ARMS = true; + private static final Rotations DEFAULT_HEAD_POSE = new Rotations(0.0F, 0.0F, 0.0F); +@@ -53,10 +61,10 @@ + private static final Rotations DEFAULT_RIGHT_LEG_POSE = new Rotations(1.0F, 0.0F, 1.0F); + private static final EntityDimensions MARKER_DIMENSIONS = new EntityDimensions(0.0F, 0.0F, true); + private static final EntityDimensions BABY_DIMENSIONS = EntityType.ARMOR_STAND.getDimensions().scale(0.5F); +- private static final double FEET_OFFSET = 0.1; +- private static final double CHEST_OFFSET = 0.9; +- private static final double LEGS_OFFSET = 0.4; +- private static final double HEAD_OFFSET = 1.6; ++ private static final double FEET_OFFSET = 0.1D; ++ private static final double CHEST_OFFSET = 0.9D; ++ private static final double LEGS_OFFSET = 0.4D; ++ private static final double HEAD_OFFSET = 1.6D; + public static final int DISABLE_TAKING_OFFSET = 8; + public static final int DISABLE_PUTTING_OFFSET = 16; + public static final int CLIENT_FLAG_SMALL = 1; +@@ -70,37 +78,54 @@ + public static final EntityDataAccessor DATA_RIGHT_ARM_POSE = SynchedEntityData.defineId(ArmorStand.class, EntityDataSerializers.ROTATIONS); + public static final EntityDataAccessor DATA_LEFT_LEG_POSE = SynchedEntityData.defineId(ArmorStand.class, EntityDataSerializers.ROTATIONS); + public static final EntityDataAccessor DATA_RIGHT_LEG_POSE = SynchedEntityData.defineId(ArmorStand.class, EntityDataSerializers.ROTATIONS); +- private static final Predicate RIDABLE_MINECARTS = entity -> entity instanceof AbstractMinecart +- && ((AbstractMinecart)entity).getMinecartType() == AbstractMinecart.Type.RIDEABLE; +- private final NonNullList handItems = NonNullList.withSize(2, ItemStack.EMPTY); +- private final NonNullList armorItems = NonNullList.withSize(4, ItemStack.EMPTY); ++ private static final Predicate RIDABLE_MINECARTS = (entity) -> { ++ return entity instanceof AbstractMinecart && ((AbstractMinecart) entity).getMinecartType() == AbstractMinecart.EnumMinecartType.RIDEABLE; ++ }; ++ private final NonNullList handItems; ++ private final NonNullList armorItems; + private boolean invisible; + public long lastHit; +- private int disabledSlots; +- private Rotations headPose = DEFAULT_HEAD_POSE; +- private Rotations bodyPose = DEFAULT_BODY_POSE; +- private Rotations leftArmPose = DEFAULT_LEFT_ARM_POSE; +- private Rotations rightArmPose = DEFAULT_RIGHT_ARM_POSE; +- private Rotations leftLegPose = DEFAULT_LEFT_LEG_POSE; +- private Rotations rightLegPose = DEFAULT_RIGHT_LEG_POSE; ++ public int disabledSlots; ++ public Rotations headPose; ++ public Rotations bodyPose; ++ public Rotations leftArmPose; ++ public Rotations rightArmPose; ++ public Rotations leftLegPose; ++ public Rotations rightLegPose; + + public ArmorStand(EntityType entityType, Level level) { + super(entityType, level); ++ this.handItems = NonNullList.withSize(2, ItemStack.EMPTY); ++ this.armorItems = NonNullList.withSize(4, ItemStack.EMPTY); ++ this.headPose = ArmorStand.DEFAULT_HEAD_POSE; ++ this.bodyPose = ArmorStand.DEFAULT_BODY_POSE; ++ this.leftArmPose = ArmorStand.DEFAULT_LEFT_ARM_POSE; ++ this.rightArmPose = ArmorStand.DEFAULT_RIGHT_ARM_POSE; ++ this.leftLegPose = ArmorStand.DEFAULT_LEFT_LEG_POSE; ++ this.rightLegPose = ArmorStand.DEFAULT_RIGHT_LEG_POSE; + this.setMaxUpStep(0.0F); + } + +- public ArmorStand(Level level, double x, double y, double z) { ++ public ArmorStand(Level level, double x, double d1, double y) { + this(EntityType.ARMOR_STAND, level); +- this.setPos(x, y, z); ++ this.setPos(x, d1, y); + } + ++ // CraftBukkit start - SPIGOT-3607, SPIGOT-3637 + @Override ++ public float getBukkitYaw() { ++ return this.getYRot(); ++ } ++ // CraftBukkit end ++ ++ @Override + public void refreshDimensions() { +- double x = this.getX(); +- double y = this.getY(); +- double z = this.getZ(); ++ double d0 = this.getX(); ++ double d1 = this.getY(); ++ double d2 = this.getZ(); ++ + super.refreshDimensions(); +- this.setPos(x, y, z); ++ this.setPos(d0, d1, d2); + } + + private boolean hasPhysics() { +@@ -115,13 +140,13 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_CLIENT_FLAGS, (byte)0); +- this.entityData.define(DATA_HEAD_POSE, DEFAULT_HEAD_POSE); +- this.entityData.define(DATA_BODY_POSE, DEFAULT_BODY_POSE); +- this.entityData.define(DATA_LEFT_ARM_POSE, DEFAULT_LEFT_ARM_POSE); +- this.entityData.define(DATA_RIGHT_ARM_POSE, DEFAULT_RIGHT_ARM_POSE); +- this.entityData.define(DATA_LEFT_LEG_POSE, DEFAULT_LEFT_LEG_POSE); +- this.entityData.define(DATA_RIGHT_LEG_POSE, DEFAULT_RIGHT_LEG_POSE); ++ this.entityData.define(ArmorStand.DATA_CLIENT_FLAGS, (byte) 0); ++ this.entityData.define(ArmorStand.DATA_HEAD_POSE, ArmorStand.DEFAULT_HEAD_POSE); ++ this.entityData.define(ArmorStand.DATA_BODY_POSE, ArmorStand.DEFAULT_BODY_POSE); ++ this.entityData.define(ArmorStand.DATA_LEFT_ARM_POSE, ArmorStand.DEFAULT_LEFT_ARM_POSE); ++ this.entityData.define(ArmorStand.DATA_RIGHT_ARM_POSE, ArmorStand.DEFAULT_RIGHT_ARM_POSE); ++ this.entityData.define(ArmorStand.DATA_LEFT_LEG_POSE, ArmorStand.DEFAULT_LEFT_LEG_POSE); ++ this.entityData.define(ArmorStand.DATA_RIGHT_LEG_POSE, ArmorStand.DEFAULT_RIGHT_LEG_POSE); + } + + @Override +@@ -135,62 +160,75 @@ + } + + @Override +- public ItemStack getItemBySlot(EquipmentSlot slot) { ++ public ItemStack getItemBySlot(net.minecraft.world.entity.EquipmentSlot slot) { + switch (slot.getType()) { + case HAND: +- return this.handItems.get(slot.getIndex()); ++ return (ItemStack) this.handItems.get(slot.getIndex()); + case ARMOR: +- return this.armorItems.get(slot.getIndex()); ++ return (ItemStack) this.armorItems.get(slot.getIndex()); + default: + return ItemStack.EMPTY; + } + } + + @Override +- public void setItemSlot(EquipmentSlot slot, ItemStack stack) { +- this.verifyEquippedItem(stack); +- switch (slot.getType()) { ++ public void setItemSlot(net.minecraft.world.entity.EquipmentSlot slot, ItemStack stack) { ++ // CraftBukkit start ++ this.setItemSlot(slot, stack, false); ++ } ++ ++ @Override ++ public void setItemSlot(net.minecraft.world.entity.EquipmentSlot enumitemslot, ItemStack itemstack, boolean silent) { ++ // CraftBukkit end ++ this.verifyEquippedItem(itemstack); ++ switch (enumitemslot.getType()) { + case HAND: +- this.onEquipItem(slot, this.handItems.set(slot.getIndex(), stack), stack); ++ this.onEquipItem(enumitemslot, (ItemStack) this.handItems.set(enumitemslot.getIndex(), itemstack), itemstack, silent); // CraftBukkit + break; + case ARMOR: +- this.onEquipItem(slot, this.armorItems.set(slot.getIndex(), stack), stack); ++ this.onEquipItem(enumitemslot, (ItemStack) this.armorItems.set(enumitemslot.getIndex(), itemstack), itemstack, silent); // CraftBukkit + } ++ + } + + @Override + public boolean canTakeItem(ItemStack itemstack) { +- EquipmentSlot equipmentSlotForItem = Mob.getEquipmentSlotForItem(itemstack); +- return this.getItemBySlot(equipmentSlotForItem).isEmpty() && !this.isDisabled(equipmentSlotForItem); ++ net.minecraft.world.entity.EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(itemstack); ++ ++ return this.getItemBySlot(enumitemslot).isEmpty() && !this.isDisabled(enumitemslot); + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- ListTag list = new ListTag(); ++ ListTag nbttaglist = new ListTag(); + +- for (ItemStack itemStack : this.armorItems) { +- CompoundTag compoundTag = new CompoundTag(); +- if (!itemStack.isEmpty()) { +- itemStack.save(compoundTag); +- } ++ CompoundTag nbttagcompound1; + +- list.add(compoundTag); ++ for (Iterator iterator = this.armorItems.iterator(); iterator.hasNext(); nbttaglist.add(nbttagcompound1)) { ++ ItemStack itemstack = (ItemStack) iterator.next(); ++ ++ nbttagcompound1 = new CompoundTag(); ++ if (!itemstack.isEmpty()) { ++ itemstack.save(nbttagcompound1); ++ } + } + +- compound.put("ArmorItems", list); +- ListTag list1 = new ListTag(); ++ compound.put("ArmorItems", nbttaglist); ++ ListTag nbttaglist1 = new ListTag(); + +- for (ItemStack itemStack1 : this.handItems) { +- CompoundTag compoundTag1 = new CompoundTag(); +- if (!itemStack1.isEmpty()) { +- itemStack1.save(compoundTag1); +- } ++ CompoundTag nbttagcompound2; + +- list1.add(compoundTag1); ++ for (Iterator iterator1 = this.handItems.iterator(); iterator1.hasNext(); nbttaglist1.add(nbttagcompound2)) { ++ ItemStack itemstack1 = (ItemStack) iterator1.next(); ++ ++ nbttagcompound2 = new CompoundTag(); ++ if (!itemstack1.isEmpty()) { ++ itemstack1.save(nbttagcompound2); ++ } + } + +- compound.put("HandItems", list1); ++ compound.put("HandItems", nbttaglist1); + compound.putBoolean("Invisible", this.isInvisible()); + compound.putBoolean("Small", this.isSmall()); + compound.putBoolean("ShowArms", this.isShowArms()); +@@ -206,19 +244,22 @@ + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); ++ ListTag nbttaglist; ++ int i; ++ + if (compound.contains("ArmorItems", 9)) { +- ListTag list = compound.getList("ArmorItems", 10); ++ nbttaglist = compound.getList("ArmorItems", 10); + +- for (int i = 0; i < this.armorItems.size(); i++) { +- this.armorItems.set(i, ItemStack.of(list.getCompound(i))); ++ for (i = 0; i < this.armorItems.size(); ++i) { ++ this.armorItems.set(i, ItemStack.of(nbttaglist.getCompound(i))); + } + } + + if (compound.contains("HandItems", 9)) { +- ListTag list = compound.getList("HandItems", 10); ++ nbttaglist = compound.getList("HandItems", 10); + +- for (int i = 0; i < this.handItems.size(); i++) { +- this.handItems.set(i, ItemStack.of(list.getCompound(i))); ++ for (i = 0; i < this.handItems.size(); ++i) { ++ this.handItems.set(i, ItemStack.of(nbttaglist.getCompound(i))); + } + } + +@@ -229,52 +270,60 @@ + this.setNoBasePlate(compound.getBoolean("NoBasePlate")); + this.setMarker(compound.getBoolean("Marker")); + this.noPhysics = !this.hasPhysics(); +- CompoundTag compound1 = compound.getCompound("Pose"); +- this.readPose(compound1); ++ CompoundTag nbttagcompound1 = compound.getCompound("Pose"); ++ ++ this.readPose(nbttagcompound1); + } + + private void readPose(CompoundTag compound) { +- ListTag list = compound.getList("Head", 5); +- this.setHeadPose(list.isEmpty() ? DEFAULT_HEAD_POSE : new Rotations(list)); +- ListTag list1 = compound.getList("Body", 5); +- this.setBodyPose(list1.isEmpty() ? DEFAULT_BODY_POSE : new Rotations(list1)); +- ListTag list2 = compound.getList("LeftArm", 5); +- this.setLeftArmPose(list2.isEmpty() ? DEFAULT_LEFT_ARM_POSE : new Rotations(list2)); +- ListTag list3 = compound.getList("RightArm", 5); +- this.setRightArmPose(list3.isEmpty() ? DEFAULT_RIGHT_ARM_POSE : new Rotations(list3)); +- ListTag list4 = compound.getList("LeftLeg", 5); +- this.setLeftLegPose(list4.isEmpty() ? DEFAULT_LEFT_LEG_POSE : new Rotations(list4)); +- ListTag list5 = compound.getList("RightLeg", 5); +- this.setRightLegPose(list5.isEmpty() ? DEFAULT_RIGHT_LEG_POSE : new Rotations(list5)); ++ ListTag nbttaglist = compound.getList("Head", 5); ++ ++ this.setHeadPose(nbttaglist.isEmpty() ? ArmorStand.DEFAULT_HEAD_POSE : new Rotations(nbttaglist)); ++ ListTag nbttaglist1 = compound.getList("Body", 5); ++ ++ this.setBodyPose(nbttaglist1.isEmpty() ? ArmorStand.DEFAULT_BODY_POSE : new Rotations(nbttaglist1)); ++ ListTag nbttaglist2 = compound.getList("LeftArm", 5); ++ ++ this.setLeftArmPose(nbttaglist2.isEmpty() ? ArmorStand.DEFAULT_LEFT_ARM_POSE : new Rotations(nbttaglist2)); ++ ListTag nbttaglist3 = compound.getList("RightArm", 5); ++ ++ this.setRightArmPose(nbttaglist3.isEmpty() ? ArmorStand.DEFAULT_RIGHT_ARM_POSE : new Rotations(nbttaglist3)); ++ ListTag nbttaglist4 = compound.getList("LeftLeg", 5); ++ ++ this.setLeftLegPose(nbttaglist4.isEmpty() ? ArmorStand.DEFAULT_LEFT_LEG_POSE : new Rotations(nbttaglist4)); ++ ListTag nbttaglist5 = compound.getList("RightLeg", 5); ++ ++ this.setRightLegPose(nbttaglist5.isEmpty() ? ArmorStand.DEFAULT_RIGHT_LEG_POSE : new Rotations(nbttaglist5)); + } + + private CompoundTag writePose() { +- CompoundTag compoundTag = new CompoundTag(); +- if (!DEFAULT_HEAD_POSE.equals(this.headPose)) { +- compoundTag.put("Head", this.headPose.save()); ++ CompoundTag nbttagcompound = new CompoundTag(); ++ ++ if (!ArmorStand.DEFAULT_HEAD_POSE.equals(this.headPose)) { ++ nbttagcompound.put("Head", this.headPose.save()); + } + +- if (!DEFAULT_BODY_POSE.equals(this.bodyPose)) { +- compoundTag.put("Body", this.bodyPose.save()); ++ if (!ArmorStand.DEFAULT_BODY_POSE.equals(this.bodyPose)) { ++ nbttagcompound.put("Body", this.bodyPose.save()); + } + +- if (!DEFAULT_LEFT_ARM_POSE.equals(this.leftArmPose)) { +- compoundTag.put("LeftArm", this.leftArmPose.save()); ++ if (!ArmorStand.DEFAULT_LEFT_ARM_POSE.equals(this.leftArmPose)) { ++ nbttagcompound.put("LeftArm", this.leftArmPose.save()); + } + +- if (!DEFAULT_RIGHT_ARM_POSE.equals(this.rightArmPose)) { +- compoundTag.put("RightArm", this.rightArmPose.save()); ++ if (!ArmorStand.DEFAULT_RIGHT_ARM_POSE.equals(this.rightArmPose)) { ++ nbttagcompound.put("RightArm", this.rightArmPose.save()); + } + +- if (!DEFAULT_LEFT_LEG_POSE.equals(this.leftLegPose)) { +- compoundTag.put("LeftLeg", this.leftLegPose.save()); ++ if (!ArmorStand.DEFAULT_LEFT_LEG_POSE.equals(this.leftLegPose)) { ++ nbttagcompound.put("LeftLeg", this.leftLegPose.save()); + } + +- if (!DEFAULT_RIGHT_LEG_POSE.equals(this.rightLegPose)) { +- compoundTag.put("RightLeg", this.rightLegPose.save()); ++ if (!ArmorStand.DEFAULT_RIGHT_LEG_POSE.equals(this.rightLegPose)) { ++ nbttagcompound.put("RightLeg", this.rightLegPose.save()); + } + +- return compoundTag; ++ return nbttagcompound; + } + + @Override +@@ -283,152 +332,207 @@ + } + + @Override +- protected void doPush(Entity entity) { +- } ++ protected void doPush(Entity entity) {} + + @Override + protected void pushEntities() { +- for (Entity entity : this.level().getEntities(this, this.getBoundingBox(), RIDABLE_MINECARTS)) { +- if (this.distanceToSqr(entity) <= 0.2) { ++ List list = this.level().getEntities((Entity) this, this.getBoundingBox(), ArmorStand.RIDABLE_MINECARTS); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ ++ if (this.distanceToSqr(entity) <= 0.2D) { + entity.push(this); + } + } ++ + } + + @Override +- public InteractionResult interactAt(Player player, Vec3 vec, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (this.isMarker() || itemInHand.is(Items.NAME_TAG)) { +- return InteractionResult.PASS; +- } else if (player.isSpectator()) { +- return InteractionResult.SUCCESS; +- } else if (player.level().isClientSide) { +- return InteractionResult.CONSUME; +- } else { +- EquipmentSlot equipmentSlotForItem = Mob.getEquipmentSlotForItem(itemInHand); +- if (itemInHand.isEmpty()) { +- EquipmentSlot clickedSlot = this.getClickedSlot(vec); +- EquipmentSlot equipmentSlot = this.isDisabled(clickedSlot) ? equipmentSlotForItem : clickedSlot; +- if (this.hasItemInSlot(equipmentSlot) && this.swapItem(player, equipmentSlot, itemInHand, hand)) { +- return InteractionResult.SUCCESS; +- } ++ public InteractionResult interactAt(net.minecraft.world.entity.player.Player player, Vec3 vec, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (!this.isMarker() && !itemstack.is(Items.NAME_TAG)) { ++ if (player.isSpectator()) { ++ return InteractionResult.SUCCESS; ++ } else if (player.level().isClientSide) { ++ return InteractionResult.CONSUME; + } else { +- if (this.isDisabled(equipmentSlotForItem)) { +- return InteractionResult.FAIL; +- } ++ net.minecraft.world.entity.EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(itemstack); + +- if (equipmentSlotForItem.getType() == EquipmentSlot.Type.HAND && !this.isShowArms()) { +- return InteractionResult.FAIL; +- } ++ if (itemstack.isEmpty()) { ++ net.minecraft.world.entity.EquipmentSlot enumitemslot1 = this.getClickedSlot(vec); ++ net.minecraft.world.entity.EquipmentSlot enumitemslot2 = this.isDisabled(enumitemslot1) ? enumitemslot : enumitemslot1; + +- if (this.swapItem(player, equipmentSlotForItem, itemInHand, hand)) { +- return InteractionResult.SUCCESS; ++ if (this.hasItemInSlot(enumitemslot2) && this.swapItem(player, enumitemslot2, itemstack, hand)) { ++ return InteractionResult.SUCCESS; ++ } ++ } else { ++ if (this.isDisabled(enumitemslot)) { ++ return InteractionResult.FAIL; ++ } ++ ++ if (enumitemslot.getType() == net.minecraft.world.entity.EquipmentSlot.Function.HAND && !this.isShowArms()) { ++ return InteractionResult.FAIL; ++ } ++ ++ if (this.swapItem(player, enumitemslot, itemstack, hand)) { ++ return InteractionResult.SUCCESS; ++ } + } +- } + ++ return InteractionResult.PASS; ++ } ++ } else { + return InteractionResult.PASS; + } + } + +- private EquipmentSlot getClickedSlot(Vec3 vector) { +- EquipmentSlot equipmentSlot = EquipmentSlot.MAINHAND; +- boolean isSmall = this.isSmall(); +- double d = isSmall ? vector.y * 2.0 : vector.y; +- EquipmentSlot equipmentSlot1 = EquipmentSlot.FEET; +- if (d >= 0.1 && d < 0.1 + (isSmall ? 0.8 : 0.45) && this.hasItemInSlot(equipmentSlot1)) { +- equipmentSlot = EquipmentSlot.FEET; +- } else if (d >= 0.9 + (isSmall ? 0.3 : 0.0) && d < 0.9 + (isSmall ? 1.0 : 0.7) && this.hasItemInSlot(EquipmentSlot.CHEST)) { +- equipmentSlot = EquipmentSlot.CHEST; +- } else if (d >= 0.4 && d < 0.4 + (isSmall ? 1.0 : 0.8) && this.hasItemInSlot(EquipmentSlot.LEGS)) { +- equipmentSlot = EquipmentSlot.LEGS; +- } else if (d >= 1.6 && this.hasItemInSlot(EquipmentSlot.HEAD)) { +- equipmentSlot = EquipmentSlot.HEAD; +- } else if (!this.hasItemInSlot(EquipmentSlot.MAINHAND) && this.hasItemInSlot(EquipmentSlot.OFFHAND)) { +- equipmentSlot = EquipmentSlot.OFFHAND; ++ private net.minecraft.world.entity.EquipmentSlot getClickedSlot(Vec3 vector) { ++ net.minecraft.world.entity.EquipmentSlot enumitemslot = net.minecraft.world.entity.EquipmentSlot.MAINHAND; ++ boolean flag = this.isSmall(); ++ double d0 = flag ? vector.y * 2.0D : vector.y; ++ net.minecraft.world.entity.EquipmentSlot enumitemslot1 = net.minecraft.world.entity.EquipmentSlot.FEET; ++ ++ if (d0 >= 0.1D && d0 < 0.1D + (flag ? 0.8D : 0.45D) && this.hasItemInSlot(enumitemslot1)) { ++ enumitemslot = net.minecraft.world.entity.EquipmentSlot.FEET; ++ } else if (d0 >= 0.9D + (flag ? 0.3D : 0.0D) && d0 < 0.9D + (flag ? 1.0D : 0.7D) && this.hasItemInSlot(net.minecraft.world.entity.EquipmentSlot.CHEST)) { ++ enumitemslot = net.minecraft.world.entity.EquipmentSlot.CHEST; ++ } else if (d0 >= 0.4D && d0 < 0.4D + (flag ? 1.0D : 0.8D) && this.hasItemInSlot(net.minecraft.world.entity.EquipmentSlot.LEGS)) { ++ enumitemslot = net.minecraft.world.entity.EquipmentSlot.LEGS; ++ } else if (d0 >= 1.6D && this.hasItemInSlot(net.minecraft.world.entity.EquipmentSlot.HEAD)) { ++ enumitemslot = net.minecraft.world.entity.EquipmentSlot.HEAD; ++ } else if (!this.hasItemInSlot(net.minecraft.world.entity.EquipmentSlot.MAINHAND) && this.hasItemInSlot(net.minecraft.world.entity.EquipmentSlot.OFFHAND)) { ++ enumitemslot = net.minecraft.world.entity.EquipmentSlot.OFFHAND; + } + +- return equipmentSlot; ++ return enumitemslot; + } + +- private boolean isDisabled(EquipmentSlot slot) { +- return (this.disabledSlots & 1 << slot.getFilterFlag()) != 0 || slot.getType() == EquipmentSlot.Type.HAND && !this.isShowArms(); ++ private boolean isDisabled(net.minecraft.world.entity.EquipmentSlot slot) { ++ return (this.disabledSlots & 1 << slot.getFilterFlag()) != 0 || slot.getType() == net.minecraft.world.entity.EquipmentSlot.Function.HAND && !this.isShowArms(); + } + +- private boolean swapItem(Player player, EquipmentSlot slot, ItemStack stack, InteractionHand hand) { +- ItemStack itemBySlot = this.getItemBySlot(slot); +- if (!itemBySlot.isEmpty() && (this.disabledSlots & 1 << slot.getFilterFlag() + 8) != 0) { ++ private boolean swapItem(net.minecraft.world.entity.player.Player player, net.minecraft.world.entity.EquipmentSlot slot, ItemStack stack, EnumHand hand) { ++ ItemStack itemstack1 = this.getItemBySlot(slot); ++ ++ if (!itemstack1.isEmpty() && (this.disabledSlots & 1 << slot.getFilterFlag() + 8) != 0) { + return false; +- } else if (itemBySlot.isEmpty() && (this.disabledSlots & 1 << slot.getFilterFlag() + 16) != 0) { ++ } else if (itemstack1.isEmpty() && (this.disabledSlots & 1 << slot.getFilterFlag() + 16) != 0) { + return false; +- } else if (player.getAbilities().instabuild && itemBySlot.isEmpty() && !stack.isEmpty()) { ++ // CraftBukkit start ++ } else { ++ org.bukkit.inventory.ItemStack armorStandItem = CraftItemStack.asCraftMirror(itemstack1); ++ org.bukkit.inventory.ItemStack playerHeldItem = CraftItemStack.asCraftMirror(stack); ++ ++ Player player1 = (Player) player.getBukkitEntity(); ++ org.bukkit.entity.ArmorStand self = (org.bukkit.entity.ArmorStand) this.getBukkitEntity(); ++ ++ EquipmentSlot slot1 = CraftEquipmentSlot.getSlot(slot); ++ EquipmentSlot hand = CraftEquipmentSlot.getHand(hand); ++ PlayerArmorStandManipulateEvent armorStandManipulateEvent = new PlayerArmorStandManipulateEvent(player1, self, playerHeldItem, armorStandItem, slot1, hand); ++ this.level().getCraftServer().getPluginManager().callEvent(armorStandManipulateEvent); ++ ++ if (armorStandManipulateEvent.isCancelled()) { ++ return true; ++ } ++ ++ if (player.getAbilities().instabuild && itemstack1.isEmpty() && !stack.isEmpty()) { ++ // CraftBukkit end + this.setItemSlot(slot, stack.copyWithCount(1)); + return true; +- } else if (stack.isEmpty() || stack.getCount() <= 1) { ++ } else if (!stack.isEmpty() && stack.getCount() > 1) { ++ if (!itemstack1.isEmpty()) { ++ return false; ++ } else { ++ this.setItemSlot(slot, stack.split(1)); ++ return true; ++ } ++ } else { + this.setItemSlot(slot, stack); +- player.setItemInHand(hand, itemBySlot); ++ player.setItemInHand(hand, itemstack1); + return true; +- } else if (!itemBySlot.isEmpty()) { +- return false; +- } else { +- this.setItemSlot(slot, stack.split(1)); +- return true; + } ++ } // CraftBukkit + } + + @Override + public boolean hurt(DamageSource source, float amount) { +- if (this.level().isClientSide || this.isRemoved()) { +- return false; +- } else if (source.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { +- this.kill(); +- return false; +- } else if (this.isInvulnerableTo(source) || this.invisible || this.isMarker()) { +- return false; +- } else if (source.is(DamageTypeTags.IS_EXPLOSION)) { +- this.brokenByAnything(source); +- this.kill(); +- return false; +- } else if (source.is(DamageTypeTags.IGNITES_ARMOR_STANDS)) { +- if (this.isOnFire()) { +- this.causeDamage(source, 0.15F); +- } else { +- this.setSecondsOnFire(5); +- } +- +- return false; +- } else if (source.is(DamageTypeTags.BURNS_ARMOR_STANDS) && this.getHealth() > 0.5F) { +- this.causeDamage(source, 4.0F); +- return false; +- } else { +- boolean isCanBreakArmorStand = source.is(DamageTypeTags.CAN_BREAK_ARMOR_STAND); +- boolean isAlwaysKillsArmorStands = source.is(DamageTypeTags.ALWAYS_KILLS_ARMOR_STANDS); +- if (!isCanBreakArmorStand && !isAlwaysKillsArmorStands) { ++ if (!this.level().isClientSide && !this.isRemoved()) { ++ if (source.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount)) { ++ return false; ++ } ++ // CraftBukkit end ++ this.kill(); + return false; +- } else { +- if (source.getEntity() instanceof Player player && !player.getAbilities().mayBuild) { ++ } else if (!this.isInvulnerableTo(source) && (true || !this.invisible) && !this.isMarker()) { // CraftBukkit ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, true, this.invisible)) { + return false; + } +- +- if (source.isCreativePlayer()) { +- this.playBrokenSound(); +- this.showBreakingParticles(); ++ // CraftBukkit end ++ if (source.is(DamageTypeTags.IS_EXPLOSION)) { ++ this.brokenByAnything(source); + this.kill(); +- return true; +- } else { +- long gameTime = this.level().getGameTime(); +- if (gameTime - this.lastHit > 5L && !isAlwaysKillsArmorStands) { +- this.level().broadcastEntityEvent(this, (byte)32); +- this.gameEvent(GameEvent.ENTITY_DAMAGE, source.getEntity()); +- this.lastHit = gameTime; ++ return false; ++ } else if (source.is(DamageTypeTags.IGNITES_ARMOR_STANDS)) { ++ if (this.isOnFire()) { ++ this.causeDamage(source, 0.15F); + } else { +- this.brokenByPlayer(source); +- this.showBreakingParticles(); +- this.kill(); ++ this.setSecondsOnFire(5); + } + +- return true; ++ return false; ++ } else if (source.is(DamageTypeTags.BURNS_ARMOR_STANDS) && this.getHealth() > 0.5F) { ++ this.causeDamage(source, 4.0F); ++ return false; ++ } else { ++ boolean flag = source.is(DamageTypeTags.CAN_BREAK_ARMOR_STAND); ++ boolean flag1 = source.is(DamageTypeTags.ALWAYS_KILLS_ARMOR_STANDS); ++ ++ if (!flag && !flag1) { ++ return false; ++ } else { ++ Entity entity = source.getEntity(); ++ ++ if (entity instanceof net.minecraft.world.entity.player.Player) { ++ net.minecraft.world.entity.player.Player entityhuman = (net.minecraft.world.entity.player.Player) entity; ++ ++ if (!entityhuman.getAbilities().mayBuild) { ++ return false; ++ } ++ } ++ ++ if (source.isCreativePlayer()) { ++ this.playBrokenSound(); ++ this.showBreakingParticles(); ++ this.kill(); ++ return true; ++ } else { ++ long i = this.level().getGameTime(); ++ ++ if (i - this.lastHit > 5L && !flag1) { ++ this.level().broadcastEntityEvent(this, (byte) 32); ++ this.gameEvent(GameEvent.ENTITY_DAMAGE, source.getEntity()); ++ this.lastHit = i; ++ } else { ++ this.brokenByPlayer(source); ++ this.showBreakingParticles(); ++ this.discard(); // CraftBukkit - SPIGOT-4890: remain as this.discard() since above damagesource method will call death event ++ } ++ ++ return true; ++ } ++ } + } ++ } else { ++ return false; + } ++ } else { ++ return false; + } + } + +@@ -442,81 +546,81 @@ + } else { + super.handleEntityEvent(id); + } ++ + } + + @Override + public boolean shouldRenderAtSqrDistance(double distance) { +- double d = this.getBoundingBox().getSize() * 4.0; +- if (Double.isNaN(d) || d == 0.0) { +- d = 4.0; ++ double d1 = this.getBoundingBox().getSize() * 4.0D; ++ ++ if (Double.isNaN(d1) || d1 == 0.0D) { ++ d1 = 4.0D; + } + +- d *= 64.0; +- return distance < d * d; ++ d1 *= 64.0D; ++ return distance < d1 * d1; + } + + private void showBreakingParticles() { + if (this.level() instanceof ServerLevel) { +- ((ServerLevel)this.level()) +- .sendParticles( +- new BlockParticleOption(ParticleTypes.BLOCK, Blocks.OAK_PLANKS.defaultBlockState()), +- this.getX(), +- this.getY(0.6666666666666666), +- this.getZ(), +- 10, +- (double)(this.getBbWidth() / 4.0F), +- (double)(this.getBbHeight() / 4.0F), +- (double)(this.getBbWidth() / 4.0F), +- 0.05 +- ); ++ ((ServerLevel) this.level()).sendParticles(new BlockParticleOption(ParticleTypes.BLOCK, Blocks.OAK_PLANKS.defaultBlockState()), this.getX(), this.getY(0.6666666666666666D), this.getZ(), 10, (double) (this.getBbWidth() / 4.0F), (double) (this.getBbHeight() / 4.0F), (double) (this.getBbWidth() / 4.0F), 0.05D); + } ++ + } + + private void causeDamage(DamageSource damageSource, float amount) { +- float health = this.getHealth(); +- float var4 = health - amount; +- if (var4 <= 0.5F) { ++ float f1 = this.getHealth(); ++ ++ f1 -= amount; ++ if (f1 <= 0.5F) { + this.brokenByAnything(damageSource); + this.kill(); + } else { +- this.setHealth(var4); ++ this.setHealth(f1); + this.gameEvent(GameEvent.ENTITY_DAMAGE, damageSource.getEntity()); + } ++ + } + + private void brokenByPlayer(DamageSource damageSource) { +- ItemStack itemStack = new ItemStack(Items.ARMOR_STAND); ++ ItemStack itemstack = new ItemStack(Items.ARMOR_STAND); ++ + if (this.hasCustomName()) { +- itemStack.setHoverName(this.getCustomName()); ++ itemstack.setHoverName(this.getCustomName()); + } + +- Block.popResource(this.level(), this.blockPosition(), itemStack); ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops + this.brokenByAnything(damageSource); + } + + private void brokenByAnything(DamageSource damageSource) { + this.playBrokenSound(); +- this.dropAllDeathLoot(damageSource); ++ // this.dropAllDeathLoot(damagesource); // CraftBukkit - moved down + +- for (int i = 0; i < this.handItems.size(); i++) { +- ItemStack itemStack = this.handItems.get(i); +- if (!itemStack.isEmpty()) { +- Block.popResource(this.level(), this.blockPosition().above(), itemStack); ++ ItemStack itemstack; ++ int i; ++ ++ for (i = 0; i < this.handItems.size(); ++i) { ++ itemstack = (ItemStack) this.handItems.get(i); ++ if (!itemstack.isEmpty()) { ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops + this.handItems.set(i, ItemStack.EMPTY); + } + } + +- for (int ix = 0; ix < this.armorItems.size(); ix++) { +- ItemStack itemStack = this.armorItems.get(ix); +- if (!itemStack.isEmpty()) { +- Block.popResource(this.level(), this.blockPosition().above(), itemStack); +- this.armorItems.set(ix, ItemStack.EMPTY); ++ for (i = 0; i < this.armorItems.size(); ++i) { ++ itemstack = (ItemStack) this.armorItems.get(i); ++ if (!itemstack.isEmpty()) { ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops ++ this.armorItems.set(i, ItemStack.EMPTY); + } + } ++ this.dropAllDeathLoot(damageSource); // CraftBukkit - moved from above ++ + } + + private void playBrokenSound() { +- this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.ARMOR_STAND_BREAK, this.getSoundSource(), 1.0F, 1.0F); ++ this.level().playSound((net.minecraft.world.entity.player.Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.ARMOR_STAND_BREAK, this.getSoundSource(), 1.0F, 1.0F); + } + + @Override +@@ -527,7 +631,7 @@ + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return size.height * (this.isBaby() ? 0.5F : 0.9F); + } + +@@ -553,35 +657,42 @@ + @Override + public void tick() { + super.tick(); +- Rotations rotations = this.entityData.get(DATA_HEAD_POSE); +- if (!this.headPose.equals(rotations)) { +- this.setHeadPose(rotations); ++ Rotations vector3f = (Rotations) this.entityData.get(ArmorStand.DATA_HEAD_POSE); ++ ++ if (!this.headPose.equals(vector3f)) { ++ this.setHeadPose(vector3f); + } + +- Rotations rotations1 = this.entityData.get(DATA_BODY_POSE); +- if (!this.bodyPose.equals(rotations1)) { +- this.setBodyPose(rotations1); ++ Rotations vector3f1 = (Rotations) this.entityData.get(ArmorStand.DATA_BODY_POSE); ++ ++ if (!this.bodyPose.equals(vector3f1)) { ++ this.setBodyPose(vector3f1); + } + +- Rotations rotations2 = this.entityData.get(DATA_LEFT_ARM_POSE); +- if (!this.leftArmPose.equals(rotations2)) { +- this.setLeftArmPose(rotations2); ++ Rotations vector3f2 = (Rotations) this.entityData.get(ArmorStand.DATA_LEFT_ARM_POSE); ++ ++ if (!this.leftArmPose.equals(vector3f2)) { ++ this.setLeftArmPose(vector3f2); + } + +- Rotations rotations3 = this.entityData.get(DATA_RIGHT_ARM_POSE); +- if (!this.rightArmPose.equals(rotations3)) { +- this.setRightArmPose(rotations3); ++ Rotations vector3f3 = (Rotations) this.entityData.get(ArmorStand.DATA_RIGHT_ARM_POSE); ++ ++ if (!this.rightArmPose.equals(vector3f3)) { ++ this.setRightArmPose(vector3f3); + } + +- Rotations rotations4 = this.entityData.get(DATA_LEFT_LEG_POSE); +- if (!this.leftLegPose.equals(rotations4)) { +- this.setLeftLegPose(rotations4); ++ Rotations vector3f4 = (Rotations) this.entityData.get(ArmorStand.DATA_LEFT_LEG_POSE); ++ ++ if (!this.leftLegPose.equals(vector3f4)) { ++ this.setLeftLegPose(vector3f4); + } + +- Rotations rotations5 = this.entityData.get(DATA_RIGHT_LEG_POSE); +- if (!this.rightLegPose.equals(rotations5)) { +- this.setRightLegPose(rotations5); ++ Rotations vector3f5 = (Rotations) this.entityData.get(ArmorStand.DATA_RIGHT_LEG_POSE); ++ ++ if (!this.rightLegPose.equals(vector3f5)) { ++ this.setRightLegPose(vector3f5); + } ++ + } + + @Override +@@ -600,8 +711,16 @@ + return this.isSmall(); + } + ++ // CraftBukkit start + @Override ++ public boolean shouldDropExperience() { ++ return true; // MC-157395, SPIGOT-5193 even baby (small) armor stands should drop ++ } ++ // CraftBukkit end ++ ++ @Override + public void kill() { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event + this.remove(Entity.RemovalReason.KILLED); + this.gameEvent(GameEvent.ENTITY_DIE); + } +@@ -612,8 +731,8 @@ + } + + @Override +- public PushReaction getPistonPushReaction() { +- return this.isMarker() ? PushReaction.IGNORE : super.getPistonPushReaction(); ++ public EnumPistonReaction getPistonPushReaction() { ++ return this.isMarker() ? EnumPistonReaction.IGNORE : super.getPistonPushReaction(); + } + + @Override +@@ -621,43 +740,43 @@ + return this.isMarker(); + } + +- private void setSmall(boolean small) { +- this.entityData.set(DATA_CLIENT_FLAGS, this.setBit(this.entityData.get(DATA_CLIENT_FLAGS), 1, small)); ++ public void setSmall(boolean small) { ++ this.entityData.set(ArmorStand.DATA_CLIENT_FLAGS, this.setBit((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS), 1, small)); + } + + public boolean isSmall() { +- return (this.entityData.get(DATA_CLIENT_FLAGS) & 1) != 0; ++ return ((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS) & 1) != 0; + } + + public void setShowArms(boolean showArms) { +- this.entityData.set(DATA_CLIENT_FLAGS, this.setBit(this.entityData.get(DATA_CLIENT_FLAGS), 4, showArms)); ++ this.entityData.set(ArmorStand.DATA_CLIENT_FLAGS, this.setBit((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS), 4, showArms)); + } + + public boolean isShowArms() { +- return (this.entityData.get(DATA_CLIENT_FLAGS) & 4) != 0; ++ return ((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS) & 4) != 0; + } + + public void setNoBasePlate(boolean noBasePlate) { +- this.entityData.set(DATA_CLIENT_FLAGS, this.setBit(this.entityData.get(DATA_CLIENT_FLAGS), 8, noBasePlate)); ++ this.entityData.set(ArmorStand.DATA_CLIENT_FLAGS, this.setBit((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS), 8, noBasePlate)); + } + + public boolean isNoBasePlate() { +- return (this.entityData.get(DATA_CLIENT_FLAGS) & 8) != 0; ++ return ((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS) & 8) != 0; + } + +- private void setMarker(boolean marker) { +- this.entityData.set(DATA_CLIENT_FLAGS, this.setBit(this.entityData.get(DATA_CLIENT_FLAGS), 16, marker)); ++ public void setMarker(boolean marker) { ++ this.entityData.set(ArmorStand.DATA_CLIENT_FLAGS, this.setBit((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS), 16, marker)); + } + + public boolean isMarker() { +- return (this.entityData.get(DATA_CLIENT_FLAGS) & 16) != 0; ++ return ((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS) & 16) != 0; + } + + private byte setBit(byte oldBit, int offset, boolean value) { + if (value) { +- oldBit = (byte)(oldBit | offset); ++ oldBit = (byte) (oldBit | offset); + } else { +- oldBit = (byte)(oldBit & ~offset); ++ oldBit = (byte) (oldBit & ~offset); + } + + return oldBit; +@@ -665,32 +784,32 @@ + + public void setHeadPose(Rotations headPose) { + this.headPose = headPose; +- this.entityData.set(DATA_HEAD_POSE, headPose); ++ this.entityData.set(ArmorStand.DATA_HEAD_POSE, headPose); + } + + public void setBodyPose(Rotations bodyPose) { + this.bodyPose = bodyPose; +- this.entityData.set(DATA_BODY_POSE, bodyPose); ++ this.entityData.set(ArmorStand.DATA_BODY_POSE, bodyPose); + } + + public void setLeftArmPose(Rotations leftArmPose) { + this.leftArmPose = leftArmPose; +- this.entityData.set(DATA_LEFT_ARM_POSE, leftArmPose); ++ this.entityData.set(ArmorStand.DATA_LEFT_ARM_POSE, leftArmPose); + } + + public void setRightArmPose(Rotations rightArmPose) { + this.rightArmPose = rightArmPose; +- this.entityData.set(DATA_RIGHT_ARM_POSE, rightArmPose); ++ this.entityData.set(ArmorStand.DATA_RIGHT_ARM_POSE, rightArmPose); + } + + public void setLeftLegPose(Rotations leftLegPose) { + this.leftLegPose = leftLegPose; +- this.entityData.set(DATA_LEFT_LEG_POSE, leftLegPose); ++ this.entityData.set(ArmorStand.DATA_LEFT_LEG_POSE, leftLegPose); + } + + public void setRightLegPose(Rotations rightLegPose) { + this.rightLegPose = rightLegPose; +- this.entityData.set(DATA_RIGHT_LEG_POSE, rightLegPose); ++ this.entityData.set(ArmorStand.DATA_RIGHT_LEG_POSE, rightLegPose); + } + + public Rotations getHeadPose() { +@@ -724,7 +843,7 @@ + + @Override + public boolean skipAttackInteraction(Entity entity) { +- return entity instanceof Player && !this.level().mayInteract((Player)entity, this.blockPosition()); ++ return entity instanceof net.minecraft.world.entity.player.Player && !this.level().mayInteract((net.minecraft.world.entity.player.Player) entity, this.blockPosition()); + } + + @Override +@@ -733,8 +852,8 @@ + } + + @Override +- public LivingEntity.Fallsounds getFallSounds() { +- return new LivingEntity.Fallsounds(SoundEvents.ARMOR_STAND_FALL, SoundEvents.ARMOR_STAND_FALL); ++ public LivingEntity.a getFallSounds() { ++ return new LivingEntity.a(SoundEvents.ARMOR_STAND_FALL, SoundEvents.ARMOR_STAND_FALL); + } + + @Nullable +@@ -750,8 +869,7 @@ + } + + @Override +- public void thunderHit(ServerLevel level, LightningBolt lightning) { +- } ++ public void thunderHit(ServerLevel level, LightningBolt lightning) {} + + @Override + public boolean isAffectedByPotions() { +@@ -760,7 +878,7 @@ + + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { +- if (DATA_CLIENT_FLAGS.equals(key)) { ++ if (ArmorStand.DATA_CLIENT_FLAGS.equals(key)) { + this.refreshDimensions(); + this.blocksBuilding = !this.isMarker(); + } +@@ -774,40 +892,37 @@ + } + + @Override +- public EntityDimensions getDimensions(Pose pose) { ++ public EntityDimensions getDimensions(EntityPose pose) { + return this.getDimensionsMarker(this.isMarker()); + } + + private EntityDimensions getDimensionsMarker(boolean isMarker) { +- if (isMarker) { +- return MARKER_DIMENSIONS; +- } else { +- return this.isBaby() ? BABY_DIMENSIONS : this.getType().getDimensions(); +- } ++ return isMarker ? ArmorStand.MARKER_DIMENSIONS : (this.isBaby() ? ArmorStand.BABY_DIMENSIONS : this.getType().getDimensions()); + } + + @Override + public Vec3 getLightProbePosition(float partialTicks) { + if (this.isMarker()) { +- AABB aABB = this.getDimensionsMarker(false).makeBoundingBox(this.position()); +- BlockPos blockPos = this.blockPosition(); ++ AABB axisalignedbb = this.getDimensionsMarker(false).makeBoundingBox(this.position()); ++ BlockPos blockposition = this.blockPosition(); + int i = Integer.MIN_VALUE; ++ Iterator iterator = BlockPos.betweenClosed(BlockPos.containing(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.minZ), BlockPos.containing(axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.maxZ)).iterator(); + +- for (BlockPos blockPos1 : BlockPos.betweenClosed( +- BlockPos.containing(aABB.minX, aABB.minY, aABB.minZ), BlockPos.containing(aABB.maxX, aABB.maxY, aABB.maxZ) +- )) { +- int max = Math.max(this.level().getBrightness(LightLayer.BLOCK, blockPos1), this.level().getBrightness(LightLayer.SKY, blockPos1)); +- if (max == 15) { +- return Vec3.atCenterOf(blockPos1); ++ while (iterator.hasNext()) { ++ BlockPos blockposition1 = (BlockPos) iterator.next(); ++ int j = Math.max(this.level().getBrightness(EnumSkyBlock.BLOCK, blockposition1), this.level().getBrightness(EnumSkyBlock.SKY, blockposition1)); ++ ++ if (j == 15) { ++ return Vec3.atCenterOf(blockposition1); + } + +- if (max > i) { +- i = max; +- blockPos = blockPos1.immutable(); ++ if (j > i) { ++ i = j; ++ blockposition = blockposition1.immutable(); + } + } + +- return Vec3.atCenterOf(blockPos); ++ return Vec3.atCenterOf(blockposition); + } else { + return super.getLightProbePosition(partialTicks); + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/decoration/HangingEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/decoration/HangingEntity.java.patch new file mode 100644 index 0000000000..b85d9136ee --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/decoration/HangingEntity.java.patch @@ -0,0 +1,397 @@ +--- a/net/minecraft/world/entity/decoration/HangingEntity.java ++++ b/net/minecraft/world/entity/decoration/HangingEntity.java +@@ -3,16 +3,11 @@ + import com.mojang.logging.LogUtils; + import java.util.function.Predicate; + import javax.annotation.Nullable; +-import net.minecraft.core.BlockPos; +-import net.minecraft.core.Direction; +-import net.minecraft.nbt.CompoundTag; +-import net.minecraft.server.level.ServerLevel; +-import net.minecraft.util.Mth; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.LightningBolt; +-import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; +@@ -20,21 +15,36 @@ + import net.minecraft.world.level.block.DiodeBlock; + import net.minecraft.world.level.block.Mirror; + import net.minecraft.world.level.block.Rotation; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import org.apache.commons.lang3.Validate; + import org.slf4j.Logger; ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.Direction; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.server.level.ServerLevel; ++// CraftBukkit start ++import net.minecraft.tags.DamageTypeTags; ++import net.minecraft.util.Mth; ++import org.bukkit.entity.Hanging; ++import org.bukkit.event.hanging.HangingBreakByEntityEvent; ++import org.bukkit.event.hanging.HangingBreakEvent; ++// CraftBukkit end + + public abstract class HangingEntity extends Entity { ++ + private static final Logger LOGGER = LogUtils.getLogger(); +- protected static final Predicate HANGING_ENTITY = entity -> entity instanceof HangingEntity; ++ protected static final Predicate HANGING_ENTITY = (entity) -> { ++ return entity instanceof HangingEntity; ++ }; + private int checkInterval; +- protected BlockPos pos; +- protected Direction direction = Direction.SOUTH; ++ public BlockPos pos; ++ protected Direction direction; + + protected HangingEntity(EntityType entityType, Level level) { + super(entityType, level); ++ this.direction = Direction.SOUTH; + } + + protected HangingEntity(EntityType entityType, Level level, BlockPos pos) { +@@ -43,51 +53,65 @@ + } + + @Override +- protected void defineSynchedData() { +- } ++ protected void defineSynchedData() {} + +- protected void setDirection(Direction facingDirection) { ++ public void setDirection(Direction facingDirection) { + Validate.notNull(facingDirection); + Validate.isTrue(facingDirection.getAxis().isHorizontal()); + this.direction = facingDirection; +- this.setYRot((float)(this.direction.get2DDataValue() * 90)); ++ this.setYRot((float) (this.direction.get2DDataValue() * 90)); + this.yRotO = this.getYRot(); + this.recalculateBoundingBox(); + } + + protected void recalculateBoundingBox() { + if (this.direction != null) { +- double d = (double)this.pos.getX() + 0.5; +- double d1 = (double)this.pos.getY() + 0.5; +- double d2 = (double)this.pos.getZ() + 0.5; +- double d3 = 0.46875; +- double d4 = this.offs(this.getWidth()); +- double d5 = this.offs(this.getHeight()); +- d -= (double)this.direction.getStepX() * 0.46875; +- d2 -= (double)this.direction.getStepZ() * 0.46875; +- double var22 = d1 + d5; +- Direction counterClockWise = this.direction.getCounterClockWise(); +- double var21 = d + d4 * (double)counterClockWise.getStepX(); +- double var24 = d2 + d4 * (double)counterClockWise.getStepZ(); +- this.setPosRaw(var21, var22, var24); +- double d6 = (double)this.getWidth(); +- double d7 = (double)this.getHeight(); +- double d8 = (double)this.getWidth(); +- if (this.direction.getAxis() == Direction.Axis.Z) { +- d8 = 1.0; ++ // CraftBukkit start code moved in to calculateBoundingBox ++ this.setBoundingBox(calculateBoundingBox(this, this.pos, this.direction, this.getWidth(), this.getHeight())); ++ // CraftBukkit end ++ } ++ } ++ ++ // CraftBukkit start - break out BB calc into own method ++ public static AABB calculateBoundingBox(@Nullable Entity entity, BlockPos blockPosition, Direction direction, int width, int height) { ++ { ++ double d0 = (double) blockPosition.getX() + 0.5D; ++ double d1 = (double) blockPosition.getY() + 0.5D; ++ double d2 = (double) blockPosition.getZ() + 0.5D; ++ double d3 = 0.46875D; ++ double d4 = offs(width); ++ double d5 = offs(height); ++ ++ d0 -= (double) direction.getStepX() * 0.46875D; ++ d2 -= (double) direction.getStepZ() * 0.46875D; ++ d1 += d5; ++ Direction enumdirection = direction.getCounterClockWise(); ++ ++ d0 += d4 * (double) enumdirection.getStepX(); ++ d2 += d4 * (double) enumdirection.getStepZ(); ++ if (entity != null) { ++ entity.setPosRaw(d0, d1, d2); ++ } ++ double d6 = (double) width; ++ double d7 = (double) height; ++ double d8 = (double) width; ++ ++ if (direction.getAxis() == Direction.Axis.Z) { ++ d8 = 1.0D; + } else { +- d6 = 1.0; ++ d6 = 1.0D; + } + +- d6 /= 32.0; +- d7 /= 32.0; +- d8 /= 32.0; +- this.setBoundingBox(new AABB(var21 - d6, var22 - d7, var24 - d8, var21 + d6, var22 + d7, var24 + d8)); ++ d6 /= 32.0D; ++ d7 /= 32.0D; ++ d8 /= 32.0D; ++ return new AABB(d0 - d6, d1 - d7, d2 - d8, d0 + d6, d1 + d7, d2 + d8); + } + } ++ // CraftBukkit end + +- private double offs(int offset) { +- return offset % 32 == 0 ? 0.5 : 0.0; ++ private static double offs(int i) { // CraftBukkit - static ++ return i % 32 == 0 ? 0.5D : 0.0D; + } + + @Override +@@ -97,36 +121,57 @@ + if (this.checkInterval++ == 100) { + this.checkInterval = 0; + if (!this.isRemoved() && !this.survives()) { ++ // CraftBukkit start - fire break events ++ IBlockData material = this.level().getBlockState(this.blockPosition()); ++ HangingBreakEvent.RemoveCause cause; ++ ++ if (!material.isAir()) { ++ // TODO: This feels insufficient to catch 100% of suffocation cases ++ cause = HangingBreakEvent.RemoveCause.OBSTRUCTION; ++ } else { ++ cause = HangingBreakEvent.RemoveCause.PHYSICS; ++ } ++ ++ HangingBreakEvent event = new HangingBreakEvent((Hanging) this.getBukkitEntity(), cause); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (this.isRemoved() || event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.discard(); +- this.dropItem(null); ++ this.dropItem((Entity) null); + } + } + } ++ + } + + public boolean survives() { +- if (!this.level().noCollision(this)) { ++ if (!this.level().noCollision((Entity) this)) { + return false; + } else { +- int max = Math.max(1, this.getWidth() / 16); +- int max1 = Math.max(1, this.getHeight() / 16); +- BlockPos blockPos = this.pos.relative(this.direction.getOpposite()); +- Direction counterClockWise = this.direction.getCounterClockWise(); +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ int i = Math.max(1, this.getWidth() / 16); ++ int j = Math.max(1, this.getHeight() / 16); ++ BlockPos blockposition = this.pos.relative(this.direction.getOpposite()); ++ Direction enumdirection = this.direction.getCounterClockWise(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + +- for (int i = 0; i < max; i++) { +- for (int i1 = 0; i1 < max1; i1++) { +- int i2 = (max - 1) / -2; +- int i3 = (max1 - 1) / -2; +- mutableBlockPos.set(blockPos).move(counterClockWise, i + i2).move(Direction.UP, i1 + i3); +- BlockState blockState = this.level().getBlockState(mutableBlockPos); +- if (!blockState.isSolid() && !DiodeBlock.isDiode(blockState)) { ++ for (int k = 0; k < i; ++k) { ++ for (int l = 0; l < j; ++l) { ++ int i1 = (i - 1) / -2; ++ int j1 = (j - 1) / -2; ++ ++ blockposition_mutableblockposition.set(blockposition).move(enumdirection, k + i1).move(Direction.UP, l + j1); ++ IBlockData iblockdata = this.level().getBlockState(blockposition_mutableblockposition); ++ ++ if (!iblockdata.isSolid() && !DiodeBlock.isDiode(iblockdata)) { + return false; + } + } + } + +- return this.level().getEntities(this, this.getBoundingBox(), HANGING_ENTITY).isEmpty(); ++ return this.level().getEntities((Entity) this, this.getBoundingBox(), HangingEntity.HANGING_ENTITY).isEmpty(); + } + } + +@@ -137,7 +182,13 @@ + + @Override + public boolean skipAttackInteraction(Entity entity) { +- return entity instanceof Player player && (!this.level().mayInteract(player, this.pos) || this.hurt(this.damageSources().playerAttack(player), 0.0F)); ++ if (entity instanceof Player) { ++ Player entityhuman = (Player) entity; ++ ++ return !this.level().mayInteract(entityhuman, this.pos) ? true : this.hurt(this.damageSources().playerAttack(entityhuman), 0.0F); ++ } else { ++ return false; ++ } + } + + @Override +@@ -151,6 +202,22 @@ + return false; + } else { + if (!this.isRemoved() && !this.level().isClientSide) { ++ // CraftBukkit start - fire break events ++ Entity damager = (source.isIndirect()) ? source.getEntity() : source.getDirectEntity(); ++ HangingBreakEvent event; ++ if (damager != null) { ++ event = new HangingBreakByEntityEvent((Hanging) this.getBukkitEntity(), damager.getBukkitEntity(), source.is(DamageTypeTags.IS_EXPLOSION) ? HangingBreakEvent.RemoveCause.EXPLOSION : HangingBreakEvent.RemoveCause.ENTITY); ++ } else { ++ event = new HangingBreakEvent((Hanging) this.getBukkitEntity(), source.is(DamageTypeTags.IS_EXPLOSION) ? HangingBreakEvent.RemoveCause.EXPLOSION : HangingBreakEvent.RemoveCause.DEFAULT); ++ } ++ ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (this.isRemoved() || event.isCancelled()) { ++ return true; ++ } ++ // CraftBukkit end ++ + this.kill(); + this.markHurt(); + this.dropItem(source.getEntity()); +@@ -161,36 +228,61 @@ + } + + @Override +- public void move(MoverType type, Vec3 pos) { +- if (!this.level().isClientSide && !this.isRemoved() && pos.lengthSqr() > 0.0) { ++ public void move(EnumMoveType type, Vec3 pos) { ++ if (!this.level().isClientSide && !this.isRemoved() && pos.lengthSqr() > 0.0D) { ++ if (this.isRemoved()) return; // CraftBukkit ++ ++ // CraftBukkit start - fire break events ++ // TODO - Does this need its own cause? Seems to only be triggered by pistons ++ HangingBreakEvent event = new HangingBreakEvent((Hanging) this.getBukkitEntity(), HangingBreakEvent.RemoveCause.PHYSICS); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (this.isRemoved() || event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ + this.kill(); +- this.dropItem(null); ++ this.dropItem((Entity) null); + } ++ + } + + @Override +- public void push(double x, double y, double z) { +- if (!this.level().isClientSide && !this.isRemoved() && x * x + y * y + z * z > 0.0) { ++ public void push(double x, double d1, double y) { ++ if (false && !this.level().isClientSide && !this.isRemoved() && x * x + d1 * d1 + y * y > 0.0D) { // CraftBukkit - not needed + this.kill(); +- this.dropItem(null); ++ this.dropItem((Entity) null); + } ++ + } + ++ // CraftBukkit start - selectively save tile position + @Override ++ public void addAdditionalSaveData(CompoundTag nbttagcompound, boolean includeAll) { ++ if (includeAll) { ++ addAdditionalSaveData(nbttagcompound); ++ } ++ } ++ // CraftBukkit end ++ ++ @Override + public void addAdditionalSaveData(CompoundTag compound) { +- BlockPos pos = this.getPos(); +- compound.putInt("TileX", pos.getX()); +- compound.putInt("TileY", pos.getY()); +- compound.putInt("TileZ", pos.getZ()); ++ BlockPos blockposition = this.getPos(); ++ ++ compound.putInt("TileX", blockposition.getX()); ++ compound.putInt("TileY", blockposition.getY()); ++ compound.putInt("TileZ", blockposition.getZ()); + } + + @Override + public void readAdditionalSaveData(CompoundTag compound) { +- BlockPos blockPos = new BlockPos(compound.getInt("TileX"), compound.getInt("TileY"), compound.getInt("TileZ")); +- if (!blockPos.closerThan(this.blockPosition(), 16.0)) { +- LOGGER.error("Hanging entity at invalid position: {}", blockPos); ++ BlockPos blockposition = new BlockPos(compound.getInt("TileX"), compound.getInt("TileY"), compound.getInt("TileZ")); ++ ++ if (!blockposition.closerThan(this.blockPosition(), 16.0D)) { ++ HangingEntity.LOGGER.error("Hanging entity at invalid position: {}", blockposition); + } else { +- this.pos = blockPos; ++ this.pos = blockposition; + } + } + +@@ -204,16 +296,11 @@ + + @Override + public ItemEntity spawnAtLocation(ItemStack stack, float offsetY) { +- ItemEntity itemEntity = new ItemEntity( +- this.level(), +- this.getX() + (double)((float)this.direction.getStepX() * 0.15F), +- this.getY() + (double)offsetY, +- this.getZ() + (double)((float)this.direction.getStepZ() * 0.15F), +- stack +- ); +- itemEntity.setDefaultPickUpDelay(); +- this.level().addFreshEntity(itemEntity); +- return itemEntity; ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX() + (double) ((float) this.direction.getStepX() * 0.15F), this.getY() + (double) offsetY, this.getZ() + (double) ((float) this.direction.getStepZ() * 0.15F), stack); ++ ++ entityitem.setDefaultPickUpDelay(); ++ this.level().addFreshEntity(entityitem); ++ return entityitem; + } + + @Override +@@ -222,8 +309,8 @@ + } + + @Override +- public void setPos(double x, double y, double z) { +- this.pos = BlockPos.containing(x, y, z); ++ public void setPos(double x, double d1, double y) { ++ this.pos = BlockPos.containing(x, d1, y); + this.recalculateBoundingBox(); + this.hasImpulse = true; + } +@@ -248,6 +335,7 @@ + } + + float f = Mth.wrapDegrees(this.getYRot()); ++ + switch (transformRotation) { + case CLOCKWISE_180: + return f + 180.0F; +@@ -266,10 +354,8 @@ + } + + @Override +- public void thunderHit(ServerLevel level, LightningBolt lightning) { +- } ++ public void thunderHit(ServerLevel level, LightningBolt lightning) {} + + @Override +- public void refreshDimensions() { +- } ++ public void refreshDimensions() {} + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/decoration/ItemFrame.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/decoration/ItemFrame.java.patch new file mode 100644 index 0000000000..dc683da24d --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/decoration/ItemFrame.java.patch @@ -0,0 +1,481 @@ +--- a/net/minecraft/world/entity/decoration/ItemFrame.java ++++ b/net/minecraft/world/entity/decoration/ItemFrame.java +@@ -16,14 +16,14 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.tags.DamageTypeTags; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.SlotAccess; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; +@@ -33,7 +33,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.DiodeBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.saveddata.maps.MapItemSavedData; + import net.minecraft.world.phys.AABB; +@@ -42,15 +42,17 @@ + import org.slf4j.Logger; + + public class ItemFrame extends HangingEntity { ++ + private static final Logger LOGGER = LogUtils.getLogger(); +- private static final EntityDataAccessor DATA_ITEM = SynchedEntityData.defineId(ItemFrame.class, EntityDataSerializers.ITEM_STACK); +- private static final EntityDataAccessor DATA_ROTATION = SynchedEntityData.defineId(ItemFrame.class, EntityDataSerializers.INT); ++ public static final EntityDataAccessor DATA_ITEM = SynchedEntityData.defineId(ItemFrame.class, EntityDataSerializers.ITEM_STACK); ++ public static final EntityDataAccessor DATA_ROTATION = SynchedEntityData.defineId(ItemFrame.class, EntityDataSerializers.INT); + public static final int NUM_ROTATIONS = 8; +- private float dropChance = 1.0F; +- private boolean fixed; ++ public float dropChance; ++ public boolean fixed; + + public ItemFrame(EntityType entityType, Level level) { + super(entityType, level); ++ this.dropChance = 1.0F; + } + + public ItemFrame(Level level, BlockPos pos, Direction facingDirection) { +@@ -59,29 +61,30 @@ + + public ItemFrame(EntityType entityType, Level level, BlockPos pos, Direction direction) { + super(entityType, level, pos); ++ this.dropChance = 1.0F; + this.setDirection(direction); + } + + @Override +- protected float getEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.0F; + } + + @Override + protected void defineSynchedData() { +- this.getEntityData().define(DATA_ITEM, ItemStack.EMPTY); +- this.getEntityData().define(DATA_ROTATION, 0); ++ this.getEntityData().define(ItemFrame.DATA_ITEM, ItemStack.EMPTY); ++ this.getEntityData().define(ItemFrame.DATA_ROTATION, 0); + } + + @Override +- protected void setDirection(Direction facingDirection) { ++ public void setDirection(Direction facingDirection) { + Validate.notNull(facingDirection); + this.direction = facingDirection; + if (facingDirection.getAxis().isHorizontal()) { + this.setXRot(0.0F); +- this.setYRot((float)(this.direction.get2DDataValue() * 90)); ++ this.setYRot((float) (this.direction.get2DDataValue() * 90)); + } else { +- this.setXRot((float)(-90 * facingDirection.getAxisDirection().getStep())); ++ this.setXRot((float) (-90 * facingDirection.getAxisDirection().getStep())); + this.setYRot(0.0F); + } + +@@ -93,58 +96,74 @@ + @Override + protected void recalculateBoundingBox() { + if (this.direction != null) { +- double d = 0.46875; +- double d1 = (double)this.pos.getX() + 0.5 - (double)this.direction.getStepX() * 0.46875; +- double d2 = (double)this.pos.getY() + 0.5 - (double)this.direction.getStepY() * 0.46875; +- double d3 = (double)this.pos.getZ() + 0.5 - (double)this.direction.getStepZ() * 0.46875; +- this.setPosRaw(d1, d2, d3); +- double d4 = (double)this.getWidth(); +- double d5 = (double)this.getHeight(); +- double d6 = (double)this.getWidth(); +- Direction.Axis axis = this.direction.getAxis(); +- switch (axis) { ++ // CraftBukkit start code moved in to calculateBoundingBox ++ this.setBoundingBox(calculateBoundingBox(this, this.pos, this.direction, this.getWidth(), this.getHeight())); ++ // CraftBukkit end ++ } ++ } ++ ++ // CraftBukkit start - break out BB calc into own method ++ public static AABB calculateBoundingBox(@Nullable Entity entity, BlockPos blockPosition, Direction direction, int width, int height) { ++ { ++ double d0 = 0.46875D; ++ double d1 = (double) blockPosition.getX() + 0.5D - (double) direction.getStepX() * 0.46875D; ++ double d2 = (double) blockPosition.getY() + 0.5D - (double) direction.getStepY() * 0.46875D; ++ double d3 = (double) blockPosition.getZ() + 0.5D - (double) direction.getStepZ() * 0.46875D; ++ ++ if (entity != null) { ++ entity.setPosRaw(d1, d2, d3); ++ } ++ double d4 = (double) width; ++ double d5 = (double) height; ++ double d6 = (double) width; ++ Direction.Axis enumdirection_enumaxis = direction.getAxis(); ++ ++ switch (enumdirection_enumaxis) { + case X: +- d4 = 1.0; ++ d4 = 1.0D; + break; + case Y: +- d5 = 1.0; ++ d5 = 1.0D; + break; + case Z: +- d6 = 1.0; ++ d6 = 1.0D; + } + +- d4 /= 32.0; +- d5 /= 32.0; +- d6 /= 32.0; +- this.setBoundingBox(new AABB(d1 - d4, d2 - d5, d3 - d6, d1 + d4, d2 + d5, d3 + d6)); ++ d4 /= 32.0D; ++ d5 /= 32.0D; ++ d6 /= 32.0D; ++ return new AABB(d1 - d4, d2 - d5, d3 - d6, d1 + d4, d2 + d5, d3 + d6); + } + } ++ // CraftBukkit end + + @Override + public boolean survives() { + if (this.fixed) { + return true; +- } else if (!this.level().noCollision(this)) { ++ } else if (!this.level().noCollision((Entity) this)) { + return false; + } else { +- BlockState blockState = this.level().getBlockState(this.pos.relative(this.direction.getOpposite())); +- return (blockState.isSolid() || this.direction.getAxis().isHorizontal() && DiodeBlock.isDiode(blockState)) +- && this.level().getEntities(this, this.getBoundingBox(), HANGING_ENTITY).isEmpty(); ++ IBlockData iblockdata = this.level().getBlockState(this.pos.relative(this.direction.getOpposite())); ++ ++ return !iblockdata.isSolid() && (!this.direction.getAxis().isHorizontal() || !DiodeBlock.isDiode(iblockdata)) ? false : this.level().getEntities((Entity) this, this.getBoundingBox(), ItemFrame.HANGING_ENTITY).isEmpty(); + } + } + + @Override +- public void move(MoverType type, Vec3 pos) { ++ public void move(EnumMoveType type, Vec3 pos) { + if (!this.fixed) { + super.move(type, pos); + } ++ + } + + @Override +- public void push(double x, double y, double z) { ++ public void push(double x, double d1, double y) { + if (!this.fixed) { +- super.push(x, y, z); ++ super.push(x, d1, y); + } ++ + } + + @Override +@@ -156,11 +175,16 @@ + @Override + public boolean hurt(DamageSource source, float amount) { + if (this.fixed) { +- return (source.is(DamageTypeTags.BYPASSES_INVULNERABILITY) || source.isCreativePlayer()) && super.hurt(source, amount); ++ return !source.is(DamageTypeTags.BYPASSES_INVULNERABILITY) && !source.isCreativePlayer() ? false : super.hurt(source, amount); + } else if (this.isInvulnerableTo(source)) { + return false; + } else if (!source.is(DamageTypeTags.IS_EXPLOSION) && !this.getItem().isEmpty()) { + if (!this.level().isClientSide) { ++ // CraftBukkit start - fire EntityDamageEvent ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, false) || this.isRemoved()) { ++ return true; ++ } ++ // CraftBukkit end + this.dropItem(source.getEntity(), false); + this.gameEvent(GameEvent.BLOCK_CHANGE, source.getEntity()); + this.playSound(this.getRemoveItemSound(), 1.0F, 1.0F); +@@ -188,9 +212,10 @@ + + @Override + public boolean shouldRenderAtSqrDistance(double distance) { +- double d = 16.0; +- d *= 64.0 * getViewScale(); +- return distance < d * d; ++ double d1 = 16.0D; ++ ++ d1 *= 64.0D * getViewScale(); ++ return distance < d1 * d1; + } + + @Override +@@ -215,54 +240,65 @@ + + private void dropItem(@Nullable Entity entity, boolean dropSelf) { + if (!this.fixed) { +- ItemStack item = this.getItem(); ++ ItemStack itemstack = this.getItem(); ++ + this.setItem(ItemStack.EMPTY); + if (!this.level().getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { + if (entity == null) { +- this.removeFramedMap(item); ++ this.removeFramedMap(itemstack); + } ++ + } else { +- if (entity instanceof Player player && player.getAbilities().instabuild) { +- this.removeFramedMap(item); +- return; ++ if (entity instanceof Player) { ++ Player entityhuman = (Player) entity; ++ ++ if (entityhuman.getAbilities().instabuild) { ++ this.removeFramedMap(itemstack); ++ return; ++ } + } + + if (dropSelf) { + this.spawnAtLocation(this.getFrameItemStack()); + } + +- if (!item.isEmpty()) { +- ItemStack var5 = item.copy(); +- this.removeFramedMap(var5); ++ if (!itemstack.isEmpty()) { ++ itemstack = itemstack.copy(); ++ this.removeFramedMap(itemstack); + if (this.random.nextFloat() < this.dropChance) { +- this.spawnAtLocation(var5); ++ this.spawnAtLocation(itemstack); + } + } ++ + } + } + } + + private void removeFramedMap(ItemStack stack) { +- this.getFramedMapId().ifPresent(i -> { +- MapItemSavedData savedData = MapItem.getSavedData(i, this.level()); +- if (savedData != null) { +- savedData.removedFromFrame(this.pos, this.getId()); +- savedData.setDirty(true); ++ this.getFramedMapId().ifPresent((i) -> { ++ MapItemSavedData worldmap = MapItem.getSavedData(i, this.level()); ++ ++ if (worldmap != null) { ++ worldmap.removedFromFrame(this.pos, this.getId()); ++ worldmap.setDirty(true); + } ++ + }); +- stack.setEntityRepresentation(null); ++ stack.setEntityRepresentation((Entity) null); + } + + public ItemStack getItem() { +- return this.getEntityData().get(DATA_ITEM); ++ return (ItemStack) this.getEntityData().get(ItemFrame.DATA_ITEM); + } + + public OptionalInt getFramedMapId() { +- ItemStack item = this.getItem(); +- if (item.is(Items.FILLED_MAP)) { +- Integer mapId = MapItem.getMapId(item); +- if (mapId != null) { +- return OptionalInt.of(mapId); ++ ItemStack itemstack = this.getItem(); ++ ++ if (itemstack.is(Items.FILLED_MAP)) { ++ Integer integer = MapItem.getMapId(itemstack); ++ ++ if (integer != null) { ++ return OptionalInt.of(integer); + } + } + +@@ -278,19 +314,26 @@ + } + + public void setItem(ItemStack stack, boolean updateNeighbours) { +- if (!stack.isEmpty()) { +- stack = stack.copyWithCount(1); ++ // CraftBukkit start ++ this.setItem(stack, updateNeighbours, true); ++ } ++ ++ public void setItem(ItemStack itemstack, boolean flag, boolean playSound) { ++ // CraftBukkit end ++ if (!itemstack.isEmpty()) { ++ itemstack = itemstack.copyWithCount(1); + } + +- this.onItemChanged(stack); +- this.getEntityData().set(DATA_ITEM, stack); +- if (!stack.isEmpty()) { ++ this.onItemChanged(itemstack); ++ this.getEntityData().set(ItemFrame.DATA_ITEM, itemstack); ++ if (!itemstack.isEmpty() && playSound) { // CraftBukkit + this.playSound(this.getAddItemSound(), 1.0F, 1.0F); + } + +- if (updateNeighbours && this.pos != null) { ++ if (flag && this.pos != null) { + this.level().updateNeighbourForOutputSignal(this.pos, Blocks.AIR); + } ++ + } + + public SoundEvent getAddItemSound() { +@@ -315,9 +358,10 @@ + + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { +- if (key.equals(DATA_ITEM)) { ++ if (key.equals(ItemFrame.DATA_ITEM)) { + this.onItemChanged(this.getItem()); + } ++ + } + + private void onItemChanged(ItemStack item) { +@@ -329,7 +373,7 @@ + } + + public int getRotation() { +- return this.getEntityData().get(DATA_ROTATION); ++ return (Integer) this.getEntityData().get(ItemFrame.DATA_ROTATION); + } + + public void setRotation(int rotation) { +@@ -337,10 +381,11 @@ + } + + private void setRotation(int rotation, boolean updateNeighbours) { +- this.getEntityData().set(DATA_ROTATION, rotation % 8); ++ this.getEntityData().set(ItemFrame.DATA_ROTATION, rotation % 8); + if (updateNeighbours && this.pos != null) { + this.level().updateNeighbourForOutputSignal(this.pos, Blocks.AIR); + } ++ + } + + @Override +@@ -348,11 +393,11 @@ + super.addAdditionalSaveData(compound); + if (!this.getItem().isEmpty()) { + compound.put("Item", this.getItem().save(new CompoundTag())); +- compound.putByte("ItemRotation", (byte)this.getRotation()); ++ compound.putByte("ItemRotation", (byte) this.getRotation()); + compound.putFloat("ItemDropChance", this.dropChance); + } + +- compound.putByte("Facing", (byte)this.direction.get3DDataValue()); ++ compound.putByte("Facing", (byte) this.direction.get3DDataValue()); + compound.putBoolean("Invisible", this.isInvisible()); + compound.putBoolean("Fixed", this.fixed); + } +@@ -360,19 +405,22 @@ + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); +- CompoundTag compound1 = compound.getCompound("Item"); +- if (compound1 != null && !compound1.isEmpty()) { +- ItemStack itemStack = ItemStack.of(compound1); +- if (itemStack.isEmpty()) { +- LOGGER.warn("Unable to load item from: {}", compound1); ++ CompoundTag nbttagcompound1 = compound.getCompound("Item"); ++ ++ if (nbttagcompound1 != null && !nbttagcompound1.isEmpty()) { ++ ItemStack itemstack = ItemStack.of(nbttagcompound1); ++ ++ if (itemstack.isEmpty()) { ++ ItemFrame.LOGGER.warn("Unable to load item from: {}", nbttagcompound1); + } + +- ItemStack item = this.getItem(); +- if (!item.isEmpty() && !ItemStack.matches(itemStack, item)) { +- this.removeFramedMap(item); ++ ItemStack itemstack1 = this.getItem(); ++ ++ if (!itemstack1.isEmpty() && !ItemStack.matches(itemstack, itemstack1)) { ++ this.removeFramedMap(itemstack1); + } + +- this.setItem(itemStack, false); ++ this.setItem(itemstack, false); + this.setRotation(compound.getByte("ItemRotation"), false); + if (compound.contains("ItemDropChance", 99)) { + this.dropChance = compound.getFloat("ItemDropChance"); +@@ -385,26 +433,28 @@ + } + + @Override +- public InteractionResult interact(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); ++ public InteractionResult interact(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + boolean flag = !this.getItem().isEmpty(); +- boolean flag1 = !itemInHand.isEmpty(); ++ boolean flag1 = !itemstack.isEmpty(); ++ + if (this.fixed) { + return InteractionResult.PASS; + } else if (!this.level().isClientSide) { + if (!flag) { + if (flag1 && !this.isRemoved()) { +- if (itemInHand.is(Items.FILLED_MAP)) { +- MapItemSavedData savedData = MapItem.getSavedData(itemInHand, this.level()); +- if (savedData != null && savedData.isTrackedCountOverLimit(256)) { ++ if (itemstack.is(Items.FILLED_MAP)) { ++ MapItemSavedData worldmap = MapItem.getSavedData(itemstack, this.level()); ++ ++ if (worldmap != null && worldmap.isTrackedCountOverLimit(256)) { + return InteractionResult.FAIL; + } + } + +- this.setItem(itemInHand); ++ this.setItem(itemstack); + this.gameEvent(GameEvent.BLOCK_CHANGE, player); + if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + } + } else { +@@ -440,8 +490,9 @@ + + @Override + public ItemStack getPickResult() { +- ItemStack item = this.getItem(); +- return item.isEmpty() ? this.getFrameItemStack() : item.copy(); ++ ItemStack itemstack = this.getItem(); ++ ++ return itemstack.isEmpty() ? this.getFrameItemStack() : itemstack.copy(); + } + + protected ItemStack getFrameItemStack() { +@@ -450,8 +501,9 @@ + + @Override + public float getVisualRotationYInDegrees() { +- Direction direction = this.getDirection(); +- int i = direction.getAxis().isVertical() ? 90 * direction.getAxisDirection().getStep() : 0; +- return (float)Mth.wrapDegrees(180 + direction.get2DDataValue() * 90 + this.getRotation() * 45 + i); ++ Direction enumdirection = this.getDirection(); ++ int i = enumdirection.getAxis().isVertical() ? 90 * enumdirection.getAxisDirection().getStep() : 0; ++ ++ return (float) Mth.wrapDegrees(180 + enumdirection.get2DDataValue() * 90 + this.getRotation() * 45 + i); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java.patch new file mode 100644 index 0000000000..d6f2f0445b --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java.patch @@ -0,0 +1,219 @@ +--- a/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java ++++ b/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.entity.decoration; + ++import java.util.Iterator; + import java.util.List; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +@@ -8,15 +9,17 @@ + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientGamePacketListener; + import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; ++import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.tags.BlockTags; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +@@ -24,30 +27,33 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class LeashFenceKnotEntity extends HangingEntity { +- public static final double OFFSET_Y = 0.375; + ++ public static final double OFFSET_Y = 0.375D; ++ + public LeashFenceKnotEntity(EntityType entityType, Level level) { + super(entityType, level); + } + + public LeashFenceKnotEntity(Level level, BlockPos pos) { + super(EntityType.LEASH_KNOT, level, pos); +- this.setPos((double)pos.getX(), (double)pos.getY(), (double)pos.getZ()); ++ this.setPos((double) pos.getX(), (double) pos.getY(), (double) pos.getZ()); + } + + @Override + protected void recalculateBoundingBox() { +- this.setPosRaw((double)this.pos.getX() + 0.5, (double)this.pos.getY() + 0.375, (double)this.pos.getZ() + 0.5); +- double d = (double)this.getType().getWidth() / 2.0; +- double d1 = (double)this.getType().getHeight(); +- this.setBoundingBox(new AABB(this.getX() - d, this.getY(), this.getZ() - d, this.getX() + d, this.getY() + d1, this.getZ() + d)); ++ this.setPosRaw((double) this.pos.getX() + 0.5D, (double) this.pos.getY() + 0.375D, (double) this.pos.getZ() + 0.5D); ++ double d0 = (double) this.getType().getWidth() / 2.0D; ++ double d1 = (double) this.getType().getHeight(); ++ ++ this.setBoundingBox(new AABB(this.getX() - d0, this.getY(), this.getZ() - d0, this.getX() + d0, this.getY() + d1, this.getZ() + d0)); + } + + @Override +- public void setDirection(Direction facingDirection) { +- } ++ public void setDirection(Direction facingDirection) {} + + @Override + public int getWidth() { +@@ -60,13 +66,13 @@ + } + + @Override +- protected float getEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.0625F; + } + + @Override + public boolean shouldRenderAtSqrDistance(double distance) { +- return distance < 1024.0; ++ return distance < 1024.0D; + } + + @Override +@@ -75,42 +81,65 @@ + } + + @Override +- public void addAdditionalSaveData(CompoundTag compound) { +- } ++ public void addAdditionalSaveData(CompoundTag compound) {} + + @Override +- public void readAdditionalSaveData(CompoundTag compound) { +- } ++ public void readAdditionalSaveData(CompoundTag compound) {} + + @Override +- public InteractionResult interact(Player player, InteractionHand hand) { ++ public InteractionResult interact(Player player, EnumHand hand) { + if (this.level().isClientSide) { + return InteractionResult.SUCCESS; + } else { + boolean flag = false; +- double d = 7.0; +- List entitiesOfClass = this.level() +- .getEntitiesOfClass( +- Mob.class, new AABB(this.getX() - 7.0, this.getY() - 7.0, this.getZ() - 7.0, this.getX() + 7.0, this.getY() + 7.0, this.getZ() + 7.0) +- ); ++ double d0 = 7.0D; ++ List list = this.level().getEntitiesOfClass(Mob.class, new AABB(this.getX() - 7.0D, this.getY() - 7.0D, this.getZ() - 7.0D, this.getX() + 7.0D, this.getY() + 7.0D, this.getZ() + 7.0D)); ++ Iterator iterator = list.iterator(); + +- for (Mob mob : entitiesOfClass) { +- if (mob.getLeashHolder() == player) { +- mob.setLeashedTo(this, true); ++ while (iterator.hasNext()) { ++ Mob entityinsentient = (Mob) iterator.next(); ++ ++ if (entityinsentient.getLeashHolder() == player) { ++ // CraftBukkit start ++ if (CraftEventFactory.callPlayerLeashEntityEvent(entityinsentient, this, player, hand).isCancelled()) { ++ ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(entityinsentient, entityinsentient.getLeashHolder())); ++ continue; ++ } ++ // CraftBukkit end ++ entityinsentient.setLeashedTo(this, true); + flag = true; + } + } + + boolean flag1 = false; ++ + if (!flag) { +- this.discard(); +- if (player.getAbilities().instabuild) { +- for (Mob mob1 : entitiesOfClass) { +- if (mob1.isLeashed() && mob1.getLeashHolder() == this) { +- mob1.dropLeash(true, false); ++ // CraftBukkit start - Move below ++ // this.discard(); ++ boolean die = true; ++ // CraftBukkit end ++ if (true || player.getAbilities().instabuild) { // CraftBukkit - Process for non-creative as well ++ Iterator iterator1 = list.iterator(); ++ ++ while (iterator1.hasNext()) { ++ Mob entityinsentient1 = (Mob) iterator1.next(); ++ ++ if (entityinsentient1.isLeashed() && entityinsentient1.getLeashHolder() == this) { ++ // CraftBukkit start ++ if (CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient1, player, hand).isCancelled()) { ++ die = false; ++ continue; ++ } ++ entityinsentient1.dropLeash(true, !player.getAbilities().instabuild); // false -> survival mode boolean ++ // CraftBukkit end + flag1 = true; + } + } ++ // CraftBukkit start ++ if (die) { ++ this.discard(); ++ } ++ // CraftBukkit end + } + } + +@@ -128,21 +157,26 @@ + } + + public static LeashFenceKnotEntity getOrCreateKnot(Level level, BlockPos pos) { +- int x = pos.getX(); +- int y = pos.getY(); +- int z = pos.getZ(); ++ int i = pos.getX(); ++ int j = pos.getY(); ++ int k = pos.getZ(); ++ List list = level.getEntitiesOfClass(LeashFenceKnotEntity.class, new AABB((double) i - 1.0D, (double) j - 1.0D, (double) k - 1.0D, (double) i + 1.0D, (double) j + 1.0D, (double) k + 1.0D)); ++ Iterator iterator = list.iterator(); + +- for (LeashFenceKnotEntity leashFenceKnotEntity : level.getEntitiesOfClass( +- LeashFenceKnotEntity.class, new AABB((double)x - 1.0, (double)y - 1.0, (double)z - 1.0, (double)x + 1.0, (double)y + 1.0, (double)z + 1.0) +- )) { +- if (leashFenceKnotEntity.getPos().equals(pos)) { +- return leashFenceKnotEntity; ++ LeashFenceKnotEntity entityleash; ++ ++ do { ++ if (!iterator.hasNext()) { ++ LeashFenceKnotEntity entityleash1 = new LeashFenceKnotEntity(level, pos); ++ ++ level.addFreshEntity(entityleash1); ++ return entityleash1; + } +- } + +- LeashFenceKnotEntity leashFenceKnotEntity1 = new LeashFenceKnotEntity(level, pos); +- level.addFreshEntity(leashFenceKnotEntity1); +- return leashFenceKnotEntity1; ++ entityleash = (LeashFenceKnotEntity) iterator.next(); ++ } while (!entityleash.getPos().equals(pos)); ++ ++ return entityleash; + } + + @Override +@@ -157,7 +191,7 @@ + + @Override + public Vec3 getRopeHoldPosition(float partialTicks) { +- return this.getPosition(partialTicks).add(0.0, 0.2, 0.0); ++ return this.getPosition(partialTicks).add(0.0D, 0.2D, 0.0D); + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/item/FallingBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/item/FallingBlockEntity.java.patch new file mode 100644 index 0000000000..332c2a6ee2 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/item/FallingBlockEntity.java.patch @@ -0,0 +1,405 @@ +--- a/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.entity.item; + + import com.mojang.logging.LogUtils; ++import java.util.Iterator; + import java.util.function.Predicate; + import javax.annotation.Nullable; + import net.minecraft.CrashReportCategory; +@@ -25,11 +26,13 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MoverType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.item.context.BlockPlaceContext; + import net.minecraft.world.item.context.DirectionalPlaceContext; + import net.minecraft.world.level.ClipContext; + import net.minecraft.world.level.GameRules; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.AnvilBlock; + import net.minecraft.world.level.block.Block; +@@ -38,7 +41,7 @@ + import net.minecraft.world.level.block.Fallable; + import net.minecraft.world.level.block.FallingBlock; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.BlockHitResult; +@@ -46,61 +49,69 @@ + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class FallingBlockEntity extends Entity { ++ + private static final Logger LOGGER = LogUtils.getLogger(); +- private BlockState blockState = Blocks.SAND.defaultBlockState(); ++ private IBlockData blockState; + public int time; +- public boolean dropItem = true; +- private boolean cancelDrop; +- private boolean hurtEntities; +- private int fallDamageMax = 40; +- private float fallDamagePerDistance; ++ public boolean dropItem; ++ public boolean cancelDrop; ++ public boolean hurtEntities; ++ public int fallDamageMax; ++ public float fallDamagePerDistance; + @Nullable + public CompoundTag blockData; + protected static final EntityDataAccessor DATA_START_POS = SynchedEntityData.defineId(FallingBlockEntity.class, EntityDataSerializers.BLOCK_POS); + + public FallingBlockEntity(EntityType entityType, Level level) { + super(entityType, level); ++ this.blockState = Blocks.SAND.defaultBlockState(); ++ this.dropItem = true; ++ this.fallDamageMax = 40; + } + +- private FallingBlockEntity(Level level, double x, double y, double z, BlockState state) { ++ private FallingBlockEntity(Level level, double x, double d1, double y, IBlockData iblockdata) { + this(EntityType.FALLING_BLOCK, level); +- this.blockState = state; ++ this.blockState = iblockdata; + this.blocksBuilding = true; +- this.setPos(x, y, z); ++ this.setPos(x, d1, y); + this.setDeltaMovement(Vec3.ZERO); + this.xo = x; +- this.yo = y; +- this.zo = z; ++ this.yo = d1; ++ this.zo = y; + this.setStartPos(this.blockPosition()); + } + +- public static FallingBlockEntity fall(Level level, BlockPos pos, BlockState blockState) { +- FallingBlockEntity fallingBlockEntity = new FallingBlockEntity( +- level, +- (double)pos.getX() + 0.5, +- (double)pos.getY(), +- (double)pos.getZ() + 0.5, +- blockState.hasProperty(BlockStateProperties.WATERLOGGED) +- ? blockState.setValue(BlockStateProperties.WATERLOGGED, Boolean.valueOf(false)) +- : blockState +- ); +- level.setBlock(pos, blockState.getFluidState().createLegacyBlock(), 3); +- level.addFreshEntity(fallingBlockEntity); +- return fallingBlockEntity; ++ public static FallingBlockEntity fall(Level level, BlockPos pos, IBlockData blockState) { ++ // CraftBukkit start ++ return fall(level, pos, blockState, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); + } + ++ public static FallingBlockEntity fall(Level world, BlockPos blockposition, IBlockData iblockdata, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end ++ FallingBlockEntity entityfallingblock = new FallingBlockEntity(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, iblockdata.hasProperty(BlockStateProperties.WATERLOGGED) ? (IBlockData) iblockdata.setValue(BlockStateProperties.WATERLOGGED, false) : iblockdata); ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entityfallingblock, blockposition, iblockdata.getFluidState().createLegacyBlock())) return entityfallingblock; // CraftBukkit ++ ++ world.setBlock(blockposition, iblockdata.getFluidState().createLegacyBlock(), 3); ++ world.addFreshEntity(entityfallingblock, spawnReason); // CraftBukkit ++ return entityfallingblock; ++ } ++ + @Override + public boolean isAttackable() { + return false; + } + + public void setStartPos(BlockPos startPos) { +- this.entityData.set(DATA_START_POS, startPos); ++ this.entityData.set(FallingBlockEntity.DATA_START_POS, startPos); + } + + public BlockPos getStartPos() { +- return this.entityData.get(DATA_START_POS); ++ return (BlockPos) this.entityData.get(FallingBlockEntity.DATA_START_POS); + } + + @Override +@@ -110,7 +121,7 @@ + + @Override + protected void defineSynchedData() { +- this.entityData.define(DATA_START_POS, BlockPos.ZERO); ++ this.entityData.define(FallingBlockEntity.DATA_START_POS, BlockPos.ZERO); + } + + @Override +@@ -124,112 +135,115 @@ + this.discard(); + } else { + Block block = this.blockState.getBlock(); +- this.time++; ++ ++ ++this.time; + if (!this.isNoGravity()) { +- this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.04, 0.0)); ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.04D, 0.0D)); + } + +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + if (!this.level().isClientSide) { +- BlockPos blockPos = this.blockPosition(); ++ BlockPos blockposition = this.blockPosition(); + boolean flag = this.blockState.getBlock() instanceof ConcretePowderBlock; +- boolean flag1 = flag && this.level().getFluidState(blockPos).is(FluidTags.WATER); +- double d = this.getDeltaMovement().lengthSqr(); +- if (flag && d > 1.0) { +- BlockHitResult blockHitResult = this.level() +- .clip( +- new ClipContext( +- new Vec3(this.xo, this.yo, this.zo), this.position(), ClipContext.Block.COLLIDER, ClipContext.Fluid.SOURCE_ONLY, this +- ) +- ); +- if (blockHitResult.getType() != HitResult.Type.MISS && this.level().getFluidState(blockHitResult.getBlockPos()).is(FluidTags.WATER)) { +- blockPos = blockHitResult.getBlockPos(); ++ boolean flag1 = flag && this.level().getFluidState(blockposition).is(FluidTags.WATER); ++ double d0 = this.getDeltaMovement().lengthSqr(); ++ ++ if (flag && d0 > 1.0D) { ++ BlockHitResult movingobjectpositionblock = this.level().clip(new ClipContext(new Vec3(this.xo, this.yo, this.zo), this.position(), ClipContext.Block.COLLIDER, ClipContext.Fluid.SOURCE_ONLY, this)); ++ ++ if (movingobjectpositionblock.getType() != HitResult.EnumMovingObjectType.MISS && this.level().getFluidState(movingobjectpositionblock.getBlockPos()).is(FluidTags.WATER)) { ++ blockposition = movingobjectpositionblock.getBlockPos(); + flag1 = true; + } + } + +- if (this.onGround() || flag1) { +- BlockState blockState = this.level().getBlockState(blockPos); +- this.setDeltaMovement(this.getDeltaMovement().multiply(0.7, -0.5, 0.7)); +- if (!blockState.is(Blocks.MOVING_PISTON)) { ++ if (!this.onGround() && !flag1) { ++ if (!this.level().isClientSide && (this.time > 100 && (blockposition.getY() <= this.level().getMinBuildHeight() || blockposition.getY() > this.level().getMaxBuildHeight()) || this.time > 600)) { ++ if (this.dropItem && this.level().getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { ++ this.spawnAtLocation((IMaterial) block); ++ } ++ ++ this.discard(); ++ } ++ } else { ++ IBlockData iblockdata = this.level().getBlockState(blockposition); ++ ++ this.setDeltaMovement(this.getDeltaMovement().multiply(0.7D, -0.5D, 0.7D)); ++ if (!iblockdata.is(Blocks.MOVING_PISTON)) { + if (!this.cancelDrop) { +- boolean canBeReplaced = blockState.canBeReplaced( +- new DirectionalPlaceContext(this.level(), blockPos, Direction.DOWN, ItemStack.EMPTY, Direction.UP) +- ); +- boolean flag2 = FallingBlock.isFree(this.level().getBlockState(blockPos.below())) && (!flag || !flag1); +- boolean flag3 = this.blockState.canSurvive(this.level(), blockPos) && !flag2; +- if (canBeReplaced && flag3) { +- if (this.blockState.hasProperty(BlockStateProperties.WATERLOGGED) +- && this.level().getFluidState(blockPos).getType() == Fluids.WATER) { +- this.blockState = this.blockState.setValue(BlockStateProperties.WATERLOGGED, Boolean.valueOf(true)); ++ boolean flag2 = iblockdata.canBeReplaced((BlockPlaceContext) (new DirectionalPlaceContext(this.level(), blockposition, Direction.DOWN, ItemStack.EMPTY, Direction.UP))); ++ boolean flag3 = FallingBlock.isFree(this.level().getBlockState(blockposition.below())) && (!flag || !flag1); ++ boolean flag4 = this.blockState.canSurvive(this.level(), blockposition) && !flag3; ++ ++ if (flag2 && flag4) { ++ if (this.blockState.hasProperty(BlockStateProperties.WATERLOGGED) && this.level().getFluidState(blockposition).getType() == Fluids.WATER) { ++ this.blockState = (IBlockData) this.blockState.setValue(BlockStateProperties.WATERLOGGED, true); + } + +- if (this.level().setBlock(blockPos, this.blockState, 3)) { +- ((ServerLevel)this.level()) +- .getChunkSource() +- .chunkMap +- .broadcast(this, new ClientboundBlockUpdatePacket(blockPos, this.level().getBlockState(blockPos))); ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, this.blockState)) { ++ this.discard(); // SPIGOT-6586 called before the event in previous versions ++ return; ++ } ++ // CraftBukkit end ++ if (this.level().setBlock(blockposition, this.blockState, 3)) { ++ ((ServerLevel) this.level()).getChunkSource().chunkMap.broadcast(this, new ClientboundBlockUpdatePacket(blockposition, this.level().getBlockState(blockposition))); + this.discard(); + if (block instanceof Fallable) { +- ((Fallable)block).onLand(this.level(), blockPos, this.blockState, blockState, this); ++ ((Fallable) block).onLand(this.level(), blockposition, this.blockState, iblockdata, this); + } + + if (this.blockData != null && this.blockState.hasBlockEntity()) { +- BlockEntity blockEntity = this.level().getBlockEntity(blockPos); +- if (blockEntity != null) { +- CompoundTag compoundTag = blockEntity.saveWithoutMetadata(); ++ BlockEntity tileentity = this.level().getBlockEntity(blockposition); + +- for (String string : this.blockData.getAllKeys()) { +- compoundTag.put(string, this.blockData.get(string).copy()); ++ if (tileentity != null) { ++ CompoundTag nbttagcompound = tileentity.saveWithoutMetadata(); ++ Iterator iterator = this.blockData.getAllKeys().iterator(); ++ ++ while (iterator.hasNext()) { ++ String s = (String) iterator.next(); ++ ++ nbttagcompound.put(s, this.blockData.get(s).copy()); + } + + try { +- blockEntity.load(compoundTag); +- } catch (Exception var15) { +- LOGGER.error("Failed to load block entity from falling block", (Throwable)var15); ++ tileentity.load(nbttagcompound); ++ } catch (Exception exception) { ++ FallingBlockEntity.LOGGER.error("Failed to load block entity from falling block", exception); + } + +- blockEntity.setChanged(); ++ tileentity.setChanged(); + } + } + } else if (this.dropItem && this.level().getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { + this.discard(); +- this.callOnBrokenAfterFall(block, blockPos); +- this.spawnAtLocation(block); ++ this.callOnBrokenAfterFall(block, blockposition); ++ this.spawnAtLocation((IMaterial) block); + } + } else { + this.discard(); + if (this.dropItem && this.level().getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { +- this.callOnBrokenAfterFall(block, blockPos); +- this.spawnAtLocation(block); ++ this.callOnBrokenAfterFall(block, blockposition); ++ this.spawnAtLocation((IMaterial) block); + } + } + } else { + this.discard(); +- this.callOnBrokenAfterFall(block, blockPos); ++ this.callOnBrokenAfterFall(block, blockposition); + } + } +- } else if (!this.level().isClientSide +- && ( +- this.time > 100 && (blockPos.getY() <= this.level().getMinBuildHeight() || blockPos.getY() > this.level().getMaxBuildHeight()) +- || this.time > 600 +- )) { +- if (this.dropItem && this.level().getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { +- this.spawnAtLocation(block); +- } +- +- this.discard(); + } + } + +- this.setDeltaMovement(this.getDeltaMovement().scale(0.98)); ++ this.setDeltaMovement(this.getDeltaMovement().scale(0.98D)); + } + } + + public void callOnBrokenAfterFall(Block block, BlockPos pos) { + if (block instanceof Fallable) { +- ((Fallable)block).onBrokenAfterFall(this.level(), pos, this); ++ ((Fallable) block).onBrokenAfterFall(this.level(), pos, this); + } ++ + } + + @Override +@@ -237,23 +251,40 @@ + if (!this.hurtEntities) { + return false; + } else { +- int ceil = Mth.ceil(fallDistance - 1.0F); +- if (ceil < 0) { ++ int i = Mth.ceil(fallDistance - 1.0F); ++ ++ if (i < 0) { + return false; + } else { + Predicate predicate = EntitySelector.NO_CREATIVE_OR_SPECTATOR.and(EntitySelector.LIVING_ENTITY_STILL_ALIVE); +- DamageSource damageSource = this.blockState.getBlock() instanceof Fallable fallable +- ? fallable.getFallDamageSource(this) +- : this.damageSources().fallingBlock(this); +- float f = (float)Math.min(Mth.floor((float)ceil * this.fallDamagePerDistance), this.fallDamageMax); +- this.level().getEntities(this, this.getBoundingBox(), predicate).forEach(entity -> entity.hurt(damageSource, f)); +- boolean isAnvil = this.blockState.is(BlockTags.ANVIL); +- if (isAnvil && f > 0.0F && this.random.nextFloat() < 0.05F + (float)ceil * 0.05F) { +- BlockState blockState = AnvilBlock.damage(this.blockState); +- if (blockState == null) { ++ Block block = this.blockState.getBlock(); ++ DamageSource damagesource1; ++ ++ if (block instanceof Fallable) { ++ Fallable fallable = (Fallable) block; ++ ++ damagesource1 = fallable.getFallDamageSource(this); ++ } else { ++ damagesource1 = this.damageSources().fallingBlock(this); ++ } ++ ++ DamageSource damagesource2 = damagesource1; ++ float f2 = (float) Math.min(Mth.floor((float) i * this.fallDamagePerDistance), this.fallDamageMax); ++ ++ this.level().getEntities((Entity) this, this.getBoundingBox(), predicate).forEach((entity) -> { ++ CraftEventFactory.entityDamage = this; // CraftBukkit ++ entity.hurt(damagesource2, f2); ++ CraftEventFactory.entityDamage = null; // CraftBukkit ++ }); ++ boolean flag = this.blockState.is(BlockTags.ANVIL); ++ ++ if (flag && f2 > 0.0F && this.random.nextFloat() < 0.05F + (float) i * 0.05F) { ++ IBlockData iblockdata = AnvilBlock.damage(this.blockState); ++ ++ if (iblockdata == null) { + this.cancelDrop = true; + } else { +- this.blockState = blockState; ++ this.blockState = iblockdata; + } + } + +@@ -301,6 +332,7 @@ + if (this.blockState.isAir()) { + this.blockState = Blocks.SAND.defaultBlockState(); + } ++ + } + + public void setHurtsEntities(float fallDamagePerDistance, int fallDamageMax) { +@@ -321,10 +353,10 @@ + @Override + public void fillCrashReportCategory(CrashReportCategory category) { + super.fillCrashReportCategory(category); +- category.setDetail("Immitating BlockState", this.blockState.toString()); ++ category.setDetail("Immitating BlockState", (Object) this.blockState.toString()); + } + +- public BlockState getBlockState() { ++ public IBlockData getBlockState() { + return this.blockState; + } + +@@ -348,10 +380,11 @@ + super.recreateFromPacket(packet); + this.blockState = Block.stateById(packet.getData()); + this.blocksBuilding = true; +- double x = packet.getX(); +- double y = packet.getY(); +- double z = packet.getZ(); +- this.setPos(x, y, z); ++ double d0 = packet.getX(); ++ double d1 = packet.getY(); ++ double d2 = packet.getZ(); ++ ++ this.setPos(d0, d1, d2); + this.setStartPos(this.blockPosition()); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/item/ItemEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/item/ItemEntity.java.patch new file mode 100644 index 0000000000..15995cb5ea --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/item/ItemEntity.java.patch @@ -0,0 +1,560 @@ +--- a/net/minecraft/world/entity/item/ItemEntity.java ++++ b/net/minecraft/world/entity/item/ItemEntity.java +@@ -1,17 +1,10 @@ + package net.minecraft.world.entity.item; + ++import java.util.Iterator; ++import java.util.List; + import java.util.Objects; + import java.util.UUID; + import javax.annotation.Nullable; +-import net.minecraft.core.BlockPos; +-import net.minecraft.nbt.CompoundTag; +-import net.minecraft.network.chat.Component; +-import net.minecraft.network.syncher.EntityDataAccessor; +-import net.minecraft.network.syncher.EntityDataSerializers; +-import net.minecraft.network.syncher.SynchedEntityData; +-import net.minecraft.server.level.ServerLevel; +-import net.minecraft.sounds.SoundSource; +-import net.minecraft.stats.Stats; + import net.minecraft.tags.DamageTypeTags; + import net.minecraft.tags.FluidTags; + import net.minecraft.tags.ItemTags; +@@ -19,51 +12,70 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MoverType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.TraceableEntity; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3; ++import net.minecraft.core.BlockPos; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.network.chat.Component; ++import net.minecraft.network.syncher.EntityDataAccessor; ++import net.minecraft.network.syncher.EntityDataSerializers; ++import net.minecraft.network.syncher.SynchedEntityData; ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.sounds.SoundSource; ++import net.minecraft.stats.Stats; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.entity.Player; ++import org.bukkit.event.entity.EntityPickupItemEvent; ++import org.bukkit.event.player.PlayerPickupItemEvent; ++// CraftBukkit end + + public class ItemEntity extends Entity implements TraceableEntity { ++ + private static final EntityDataAccessor DATA_ITEM = SynchedEntityData.defineId(ItemEntity.class, EntityDataSerializers.ITEM_STACK); + private static final int LIFETIME = 6000; + private static final int INFINITE_PICKUP_DELAY = 32767; + private static final int INFINITE_LIFETIME = -32768; +- private int age; +- private int pickupDelay; +- private int health = 5; ++ public int age; ++ public int pickupDelay; ++ private int health; + @Nullable +- private UUID thrower; ++ public UUID thrower; + @Nullable + private Entity cachedThrower; + @Nullable +- private UUID target; ++ public UUID target; + public final float bobOffs; ++ private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit + + public ItemEntity(EntityType entityType, Level level) { + super(entityType, level); +- this.bobOffs = this.random.nextFloat() * (float) Math.PI * 2.0F; ++ this.health = 5; ++ this.bobOffs = this.random.nextFloat() * 3.1415927F * 2.0F; + this.setYRot(this.random.nextFloat() * 360.0F); + } + +- public ItemEntity(Level level, double posX, double posY, double posZ, ItemStack itemStack) { +- this(level, posX, posY, posZ, itemStack, level.random.nextDouble() * 0.2 - 0.1, 0.2, level.random.nextDouble() * 0.2 - 0.1); ++ public ItemEntity(Level level, double posX, double d1, double posY, ItemStack itemstack) { ++ this(level, posX, d1, posY, itemstack, level.random.nextDouble() * 0.2D - 0.1D, 0.2D, level.random.nextDouble() * 0.2D - 0.1D); + } + +- public ItemEntity(Level level, double posX, double posY, double posZ, ItemStack itemStack, double deltaX, double deltaY, double deltaZ) { ++ public ItemEntity(Level level, double posX, double d1, double posY, ItemStack itemstack, double posZ, double d4, double itemStack) { + this(EntityType.ITEM, level); +- this.setPos(posX, posY, posZ); +- this.setDeltaMovement(deltaX, deltaY, deltaZ); +- this.setItem(itemStack); ++ this.setPos(posX, d1, posY); ++ this.setDeltaMovement(posZ, d4, itemStack); ++ this.setItem(itemstack); + } + + private ItemEntity(ItemEntity other) { + super(other.getType(), other.level()); ++ this.health = 5; + this.setItem(other.getItem().copy()); + this.copyPosition(other); + this.age = other.age; +@@ -80,10 +92,18 @@ + public Entity getOwner() { + if (this.cachedThrower != null && !this.cachedThrower.isRemoved()) { + return this.cachedThrower; +- } else if (this.thrower != null && this.level() instanceof ServerLevel serverLevel) { +- this.cachedThrower = serverLevel.getEntity(this.thrower); +- return this.cachedThrower; + } else { ++ if (this.thrower != null) { ++ Level world = this.level(); ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ ++ this.cachedThrower = worldserver.getEntity(this.thrower); ++ return this.cachedThrower; ++ } ++ } ++ + return null; + } + } +@@ -91,9 +111,12 @@ + @Override + public void restoreFrom(Entity entity) { + super.restoreFrom(entity); +- if (entity instanceof ItemEntity itemEntity) { +- this.cachedThrower = itemEntity.cachedThrower; ++ if (entity instanceof ItemEntity) { ++ ItemEntity entityitem = (ItemEntity) entity; ++ ++ this.cachedThrower = entityitem.cachedThrower; + } ++ + } + + @Override +@@ -103,7 +126,7 @@ + + @Override + protected void defineSynchedData() { +- this.getEntityData().define(DATA_ITEM, ItemStack.EMPTY); ++ this.getEntityData().define(ItemEntity.DATA_ITEM, ItemStack.EMPTY); + } + + @Override +@@ -112,71 +135,86 @@ + this.discard(); + } else { + super.tick(); +- if (this.pickupDelay > 0 && this.pickupDelay != 32767) { +- this.pickupDelay--; +- } ++ // CraftBukkit start - Use wall time for pickup and despawn timers ++ int elapsedTicks = MinecraftServer.currentTick - this.lastTick; ++ if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; ++ if (this.age != -32768) this.age += elapsedTicks; ++ this.lastTick = MinecraftServer.currentTick; ++ // CraftBukkit end + + this.xo = this.getX(); + this.yo = this.getY(); + this.zo = this.getZ(); +- Vec3 deltaMovement = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); + float f = this.getEyeHeight() - 0.11111111F; +- if (this.isInWater() && this.getFluidHeight(FluidTags.WATER) > (double)f) { ++ ++ if (this.isInWater() && this.getFluidHeight(FluidTags.WATER) > (double) f) { + this.setUnderwaterMovement(); +- } else if (this.isInLava() && this.getFluidHeight(FluidTags.LAVA) > (double)f) { ++ } else if (this.isInLava() && this.getFluidHeight(FluidTags.LAVA) > (double) f) { + this.setUnderLavaMovement(); + } else if (!this.isNoGravity()) { +- this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.04, 0.0)); ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.04D, 0.0D)); + } + + if (this.level().isClientSide) { + this.noPhysics = false; + } else { +- this.noPhysics = !this.level().noCollision(this, this.getBoundingBox().deflate(1.0E-7)); ++ this.noPhysics = !this.level().noCollision(this, this.getBoundingBox().deflate(1.0E-7D)); + if (this.noPhysics) { +- this.moveTowardsClosestSpace(this.getX(), (this.getBoundingBox().minY + this.getBoundingBox().maxY) / 2.0, this.getZ()); ++ this.moveTowardsClosestSpace(this.getX(), (this.getBoundingBox().minY + this.getBoundingBox().maxY) / 2.0D, this.getZ()); + } + } + +- if (!this.onGround() || this.getDeltaMovement().horizontalDistanceSqr() > 1.0E-5F || (this.tickCount + this.getId()) % 4 == 0) { +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ if (!this.onGround() || this.getDeltaMovement().horizontalDistanceSqr() > 9.999999747378752E-6D || (this.tickCount + this.getId()) % 4 == 0) { ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + float f1 = 0.98F; ++ + if (this.onGround()) { + f1 = this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getFriction() * 0.98F; + } + +- this.setDeltaMovement(this.getDeltaMovement().multiply((double)f1, 0.98, (double)f1)); ++ this.setDeltaMovement(this.getDeltaMovement().multiply((double) f1, 0.98D, (double) f1)); + if (this.onGround()) { +- Vec3 deltaMovement1 = this.getDeltaMovement(); +- if (deltaMovement1.y < 0.0) { +- this.setDeltaMovement(deltaMovement1.multiply(1.0, -0.5, 1.0)); ++ Vec3 vec3d1 = this.getDeltaMovement(); ++ ++ if (vec3d1.y < 0.0D) { ++ this.setDeltaMovement(vec3d1.multiply(1.0D, -0.5D, 1.0D)); + } + } + } + +- boolean flag = Mth.floor(this.xo) != Mth.floor(this.getX()) +- || Mth.floor(this.yo) != Mth.floor(this.getY()) +- || Mth.floor(this.zo) != Mth.floor(this.getZ()); ++ boolean flag = Mth.floor(this.xo) != Mth.floor(this.getX()) || Mth.floor(this.yo) != Mth.floor(this.getY()) || Mth.floor(this.zo) != Mth.floor(this.getZ()); + int i = flag ? 2 : 40; ++ + if (this.tickCount % i == 0 && !this.level().isClientSide && this.isMergable()) { + this.mergeWithNeighbours(); + } + ++ /* CraftBukkit start - moved up + if (this.age != -32768) { +- this.age++; ++ ++this.age; + } ++ // CraftBukkit end */ + +- this.hasImpulse = this.hasImpulse | this.updateInWaterStateAndDoFluidPushing(); ++ this.hasImpulse |= this.updateInWaterStateAndDoFluidPushing(); + if (!this.level().isClientSide) { +- double d = this.getDeltaMovement().subtract(deltaMovement).lengthSqr(); +- if (d > 0.01) { ++ double d0 = this.getDeltaMovement().subtract(vec3d).lengthSqr(); ++ ++ if (d0 > 0.01D) { + this.hasImpulse = true; + } + } + + if (!this.level().isClientSide && this.age >= 6000) { ++ // CraftBukkit start - fire ItemDespawnEvent ++ if (CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { ++ this.age = 0; ++ return; ++ } ++ // CraftBukkit end + this.discard(); + } ++ + } + } + +@@ -186,72 +224,89 @@ + } + + private void setUnderwaterMovement() { +- Vec3 deltaMovement = this.getDeltaMovement(); +- this.setDeltaMovement(deltaMovement.x * 0.99F, deltaMovement.y + (double)(deltaMovement.y < 0.06F ? 5.0E-4F : 0.0F), deltaMovement.z * 0.99F); ++ Vec3 vec3d = this.getDeltaMovement(); ++ ++ this.setDeltaMovement(vec3d.x * 0.9900000095367432D, vec3d.y + (double) (vec3d.y < 0.05999999865889549D ? 5.0E-4F : 0.0F), vec3d.z * 0.9900000095367432D); + } + + private void setUnderLavaMovement() { +- Vec3 deltaMovement = this.getDeltaMovement(); +- this.setDeltaMovement(deltaMovement.x * 0.95F, deltaMovement.y + (double)(deltaMovement.y < 0.06F ? 5.0E-4F : 0.0F), deltaMovement.z * 0.95F); ++ Vec3 vec3d = this.getDeltaMovement(); ++ ++ this.setDeltaMovement(vec3d.x * 0.949999988079071D, vec3d.y + (double) (vec3d.y < 0.05999999865889549D ? 5.0E-4F : 0.0F), vec3d.z * 0.949999988079071D); + } + + private void mergeWithNeighbours() { + if (this.isMergable()) { +- for (ItemEntity itemEntity : this.level() +- .getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate(0.5, 0.0, 0.5), neighbour -> neighbour != this && neighbour.isMergable())) { +- if (itemEntity.isMergable()) { +- this.tryToMerge(itemEntity); ++ List list = this.level().getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate(0.5D, 0.0D, 0.5D), (entityitem) -> { ++ return entityitem != this && entityitem.isMergable(); ++ }); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ ItemEntity entityitem = (ItemEntity) iterator.next(); ++ ++ if (entityitem.isMergable()) { ++ this.tryToMerge(entityitem); + if (this.isRemoved()) { + break; + } + } + } ++ + } + } + + private boolean isMergable() { +- ItemStack item = this.getItem(); +- return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < 6000 && item.getCount() < item.getMaxStackSize(); ++ ItemStack itemstack = this.getItem(); ++ ++ return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < 6000 && itemstack.getCount() < itemstack.getMaxStackSize(); + } + + private void tryToMerge(ItemEntity itemEntity) { +- ItemStack item = this.getItem(); +- ItemStack item1 = itemEntity.getItem(); +- if (Objects.equals(this.target, itemEntity.target) && areMergable(item, item1)) { +- if (item1.getCount() < item.getCount()) { +- merge(this, item, itemEntity, item1); ++ ItemStack itemstack = this.getItem(); ++ ItemStack itemstack1 = itemEntity.getItem(); ++ ++ if (Objects.equals(this.target, itemEntity.target) && areMergable(itemstack, itemstack1)) { ++ if (itemstack1.getCount() < itemstack.getCount()) { ++ merge(this, itemstack, itemEntity, itemstack1); + } else { +- merge(itemEntity, item1, this, item); ++ merge(itemEntity, itemstack1, this, itemstack); + } ++ + } + } + + public static boolean areMergable(ItemStack destinationStack, ItemStack originStack) { +- return originStack.is(destinationStack.getItem()) +- && originStack.getCount() + destinationStack.getCount() <= originStack.getMaxStackSize() +- && !(originStack.hasTag() ^ destinationStack.hasTag()) +- && (!originStack.hasTag() || originStack.getTag().equals(destinationStack.getTag())); ++ return !originStack.is(destinationStack.getItem()) ? false : (originStack.getCount() + destinationStack.getCount() > originStack.getMaxStackSize() ? false : (originStack.hasTag() ^ destinationStack.hasTag() ? false : !originStack.hasTag() || originStack.getTag().equals(destinationStack.getTag()))); + } + + public static ItemStack merge(ItemStack destinationStack, ItemStack originStack, int amount) { +- int min = Math.min(Math.min(destinationStack.getMaxStackSize(), amount) - destinationStack.getCount(), originStack.getCount()); +- ItemStack itemStack = destinationStack.copyWithCount(destinationStack.getCount() + min); +- originStack.shrink(min); +- return itemStack; ++ int j = Math.min(Math.min(destinationStack.getMaxStackSize(), amount) - destinationStack.getCount(), originStack.getCount()); ++ ItemStack itemstack2 = destinationStack.copyWithCount(destinationStack.getCount() + j); ++ ++ originStack.shrink(j); ++ return itemstack2; + } + + private static void merge(ItemEntity destinationEntity, ItemStack destinationStack, ItemStack originStack) { +- ItemStack itemStack = merge(destinationStack, originStack, 64); +- destinationEntity.setItem(itemStack); ++ ItemStack itemstack2 = merge(destinationStack, originStack, 64); ++ ++ destinationEntity.setItem(itemstack2); + } + + private static void merge(ItemEntity destinationEntity, ItemStack destinationStack, ItemEntity originEntity, ItemStack originStack) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callItemMergeEvent(originEntity, destinationEntity)) { ++ return; ++ } ++ // CraftBukkit end + merge(destinationEntity, destinationStack, originStack); + destinationEntity.pickupDelay = Math.max(destinationEntity.pickupDelay, originEntity.pickupDelay); + destinationEntity.age = Math.min(destinationEntity.age, originEntity.age); + if (originStack.isEmpty()) { + originEntity.discard(); + } ++ + } + + @Override +@@ -270,8 +325,13 @@ + } else if (this.level().isClientSide) { + return true; + } else { ++ // CraftBukkit start ++ if (CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount)) { ++ return false; ++ } ++ // CraftBukkit end + this.markHurt(); +- this.health = (int)((float)this.health - amount); ++ this.health = (int) ((float) this.health - amount); + this.gameEvent(GameEvent.ENTITY_DAMAGE, source.getEntity()); + if (this.health <= 0) { + this.getItem().onDestroyed(this); +@@ -284,9 +344,9 @@ + + @Override + public void addAdditionalSaveData(CompoundTag compound) { +- compound.putShort("Health", (short)this.health); +- compound.putShort("Age", (short)this.age); +- compound.putShort("PickupDelay", (short)this.pickupDelay); ++ compound.putShort("Health", (short) this.health); ++ compound.putShort("Age", (short) this.age); ++ compound.putShort("PickupDelay", (short) this.pickupDelay); + if (this.thrower != null) { + compound.putUUID("Thrower", this.thrower); + } +@@ -298,6 +358,7 @@ + if (!this.getItem().isEmpty()) { + compound.put("Item", this.getItem().save(new CompoundTag())); + } ++ + } + + @Override +@@ -317,36 +378,81 @@ + this.cachedThrower = null; + } + +- CompoundTag compound1 = compound.getCompound("Item"); +- this.setItem(ItemStack.of(compound1)); ++ CompoundTag nbttagcompound1 = compound.getCompound("Item"); ++ ++ this.setItem(ItemStack.of(nbttagcompound1)); + if (this.getItem().isEmpty()) { + this.discard(); + } ++ + } + + @Override +- public void playerTouch(Player entity) { ++ public void playerTouch(net.minecraft.world.entity.player.Player entity) { + if (!this.level().isClientSide) { +- ItemStack item = this.getItem(); +- Item item1 = item.getItem(); +- int count = item.getCount(); +- if (this.pickupDelay == 0 && (this.target == null || this.target.equals(entity.getUUID())) && entity.getInventory().add(item)) { +- entity.take(this, count); +- if (item.isEmpty()) { ++ ItemStack itemstack = this.getItem(); ++ Item item = itemstack.getItem(); ++ int i = itemstack.getCount(); ++ ++ // CraftBukkit start - fire PlayerPickupItemEvent ++ int canHold = entity.getInventory().canHold(itemstack); ++ int remaining = i - canHold; ++ ++ if (this.pickupDelay <= 0 && canHold > 0) { ++ itemstack.setCount(canHold); ++ // Call legacy event ++ PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent((Player) entity.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); ++ playerEvent.setCancelled(!playerEvent.getPlayer().getCanPickupItems()); ++ this.level().getCraftServer().getPluginManager().callEvent(playerEvent); ++ if (playerEvent.isCancelled()) { ++ itemstack.setCount(i); // SPIGOT-5294 - restore count ++ return; ++ } ++ ++ // Call newer event afterwards ++ EntityPickupItemEvent entityEvent = new EntityPickupItemEvent((Player) entity.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); ++ entityEvent.setCancelled(!entityEvent.getEntity().getCanPickupItems()); ++ this.level().getCraftServer().getPluginManager().callEvent(entityEvent); ++ if (entityEvent.isCancelled()) { ++ itemstack.setCount(i); // SPIGOT-5294 - restore count ++ return; ++ } ++ ++ // Update the ItemStack if it was changed in the event ++ ItemStack current = this.getItem(); ++ if (!itemstack.equals(current)) { ++ itemstack = current; ++ } else { ++ itemstack.setCount(canHold + remaining); // = i ++ } ++ ++ // Possibly < 0; fix here so we do not have to modify code below ++ this.pickupDelay = 0; ++ } else if (this.pickupDelay == 0) { ++ // ensure that the code below isn't triggered if canHold says we can't pick the items up ++ this.pickupDelay = -1; ++ } ++ // CraftBukkit end ++ ++ if (this.pickupDelay == 0 && (this.target == null || this.target.equals(entity.getUUID())) && entity.getInventory().add(itemstack)) { ++ entity.take(this, i); ++ if (itemstack.isEmpty()) { + this.discard(); +- item.setCount(count); ++ itemstack.setCount(i); + } + +- entity.awardStat(Stats.ITEM_PICKED_UP.get(item1), count); ++ entity.awardStat(Stats.ITEM_PICKED_UP.get(item), i); + entity.onItemPickup(this); + } ++ + } + } + + @Override + public Component getName() { +- Component customName = this.getCustomName(); +- return (Component)(customName != null ? customName : Component.translatable(this.getItem().getDescriptionId())); ++ Component ichatbasecomponent = this.getCustomName(); ++ ++ return (Component) (ichatbasecomponent != null ? ichatbasecomponent : Component.translatable(this.getItem().getDescriptionId())); + } + + @Override +@@ -358,27 +464,29 @@ + @Override + public Entity changeDimension(ServerLevel server) { + Entity entity = super.changeDimension(server); ++ + if (!this.level().isClientSide && entity instanceof ItemEntity) { +- ((ItemEntity)entity).mergeWithNeighbours(); ++ ((ItemEntity) entity).mergeWithNeighbours(); + } + + return entity; + } + + public ItemStack getItem() { +- return this.getEntityData().get(DATA_ITEM); ++ return (ItemStack) this.getEntityData().get(ItemEntity.DATA_ITEM); + } + + public void setItem(ItemStack stack) { +- this.getEntityData().set(DATA_ITEM, stack); ++ this.getEntityData().set(ItemEntity.DATA_ITEM, stack); + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { + super.onSyncedDataUpdated(key); +- if (DATA_ITEM.equals(key)) { ++ if (ItemEntity.DATA_ITEM.equals(key)) { + this.getItem().setEntityRepresentation(this); + } ++ + } + + public void setTarget(@Nullable UUID target) { +@@ -428,7 +536,7 @@ + } + + public float getSpin(float partialTicks) { +- return ((float)this.getAge() + partialTicks) / 20.0F + this.bobOffs; ++ return ((float) this.getAge() + partialTicks) / 20.0F + this.bobOffs; + } + + public ItemEntity copy() { +@@ -442,6 +550,6 @@ + + @Override + public float getVisualRotationYInDegrees() { +- return 180.0F - this.getSpin(0.5F) / (float) (Math.PI * 2) * 360.0F; ++ return 180.0F - this.getSpin(0.5F) / 6.2831855F * 360.0F; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/item/PrimedTnt.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/item/PrimedTnt.java.patch new file mode 100644 index 0000000000..844e4e4634 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/item/PrimedTnt.java.patch @@ -0,0 +1,180 @@ +--- a/net/minecraft/world/entity/item/PrimedTnt.java ++++ b/net/minecraft/world/entity/item/PrimedTnt.java +@@ -10,45 +10,54 @@ + import net.minecraft.network.syncher.SynchedEntityData; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.TraceableEntity; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end ++ + public class PrimedTnt extends Entity implements TraceableEntity { ++ + private static final EntityDataAccessor DATA_FUSE_ID = SynchedEntityData.defineId(PrimedTnt.class, EntityDataSerializers.INT); +- private static final EntityDataAccessor DATA_BLOCK_STATE_ID = SynchedEntityData.defineId(PrimedTnt.class, EntityDataSerializers.BLOCK_STATE); ++ private static final EntityDataAccessor DATA_BLOCK_STATE_ID = SynchedEntityData.defineId(PrimedTnt.class, EntityDataSerializers.BLOCK_STATE); + private static final int DEFAULT_FUSE_TIME = 80; + private static final String TAG_BLOCK_STATE = "block_state"; + public static final String TAG_FUSE = "fuse"; + @Nullable +- private LivingEntity owner; ++ public LivingEntity owner; ++ public float yield = 4; // CraftBukkit - add field ++ public boolean isIncendiary = false; // CraftBukkit - add field + + public PrimedTnt(EntityType entityType, Level level) { + super(entityType, level); + this.blocksBuilding = true; + } + +- public PrimedTnt(Level level, double x, double y, double z, @Nullable LivingEntity owner) { ++ public PrimedTnt(Level level, double x, double d1, double y, @Nullable LivingEntity entityliving) { + this(EntityType.TNT, level); +- this.setPos(x, y, z); +- double d = level.random.nextDouble() * (float) (Math.PI * 2); +- this.setDeltaMovement(-Math.sin(d) * 0.02, 0.2F, -Math.cos(d) * 0.02); ++ this.setPos(x, d1, y); ++ double d3 = level.random.nextDouble() * 6.2831854820251465D; ++ ++ this.setDeltaMovement(-Math.sin(d3) * 0.02D, 0.20000000298023224D, -Math.cos(d3) * 0.02D); + this.setFuse(80); + this.xo = x; +- this.yo = y; +- this.zo = z; +- this.owner = owner; ++ this.yo = d1; ++ this.zo = y; ++ this.owner = entityliving; + } + + @Override + protected void defineSynchedData() { +- this.entityData.define(DATA_FUSE_ID, 80); +- this.entityData.define(DATA_BLOCK_STATE_ID, Blocks.TNT.defaultBlockState()); ++ this.entityData.define(PrimedTnt.DATA_FUSE_ID, 80); ++ this.entityData.define(PrimedTnt.DATA_BLOCK_STATE_ID, Blocks.TNT.defaultBlockState()); + } + + @Override +@@ -64,38 +73,49 @@ + @Override + public void tick() { + if (!this.isNoGravity()) { +- this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.04, 0.0)); ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.04D, 0.0D)); + } + +- this.move(MoverType.SELF, this.getDeltaMovement()); +- this.setDeltaMovement(this.getDeltaMovement().scale(0.98)); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); ++ this.setDeltaMovement(this.getDeltaMovement().scale(0.98D)); + if (this.onGround()) { +- this.setDeltaMovement(this.getDeltaMovement().multiply(0.7, -0.5, 0.7)); ++ this.setDeltaMovement(this.getDeltaMovement().multiply(0.7D, -0.5D, 0.7D)); + } + + int i = this.getFuse() - 1; ++ + this.setFuse(i); + if (i <= 0) { +- this.discard(); ++ // CraftBukkit start - Need to reverse the order of the explosion and the entity death so we have a location for the event ++ // this.discard(); + if (!this.level().isClientSide) { + this.explode(); + } ++ this.discard(); ++ // CraftBukkit end + } else { + this.updateInWaterStateAndDoFluidPushing(); + if (this.level().isClientSide) { +- this.level().addParticle(ParticleTypes.SMOKE, this.getX(), this.getY() + 0.5, this.getZ(), 0.0, 0.0, 0.0); ++ this.level().addParticle(ParticleTypes.SMOKE, this.getX(), this.getY() + 0.5D, this.getZ(), 0.0D, 0.0D, 0.0D); + } + } ++ + } + + private void explode() { +- float f = 4.0F; +- this.level().explode(this, this.getX(), this.getY(0.0625), this.getZ(), 4.0F, Level.ExplosionInteraction.TNT); ++ // CraftBukkit start ++ // float f = 4.0F; ++ ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent((org.bukkit.entity.Explosive)this.getBukkitEntity()); ++ ++ if (!event.isCancelled()) { ++ this.level().explode(this, this.getX(), this.getY(0.0625D), this.getZ(), event.getRadius(), event.getFire(), Level.a.TNT); ++ } ++ // CraftBukkit end + } + + @Override + protected void addAdditionalSaveData(CompoundTag compound) { +- compound.putShort("fuse", (short)this.getFuse()); ++ compound.putShort("fuse", (short) this.getFuse()); + compound.put("block_state", NbtUtils.writeBlockState(this.getBlockState())); + } + +@@ -105,6 +125,7 @@ + if (compound.contains("block_state", 10)) { + this.setBlockState(NbtUtils.readBlockState(this.level().holderLookup(Registries.BLOCK), compound.getCompound("block_state"))); + } ++ + } + + @Nullable +@@ -116,29 +137,32 @@ + @Override + public void restoreFrom(Entity entity) { + super.restoreFrom(entity); +- if (entity instanceof PrimedTnt primedTnt) { +- this.owner = primedTnt.owner; ++ if (entity instanceof PrimedTnt) { ++ PrimedTnt entitytntprimed = (PrimedTnt) entity; ++ ++ this.owner = entitytntprimed.owner; + } ++ + } + + @Override +- protected float getEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.15F; + } + + public void setFuse(int life) { +- this.entityData.set(DATA_FUSE_ID, life); ++ this.entityData.set(PrimedTnt.DATA_FUSE_ID, life); + } + + public int getFuse() { +- return this.entityData.get(DATA_FUSE_ID); ++ return (Integer) this.entityData.get(PrimedTnt.DATA_FUSE_ID); + } + +- public void setBlockState(BlockState blockState) { +- this.entityData.set(DATA_BLOCK_STATE_ID, blockState); ++ public void setBlockState(IBlockData iblockdata) { ++ this.entityData.set(PrimedTnt.DATA_BLOCK_STATE_ID, iblockdata); + } + +- public BlockState getBlockState() { +- return this.entityData.get(DATA_BLOCK_STATE_ID); ++ public IBlockData getBlockState() { ++ return (IBlockData) this.entityData.get(PrimedTnt.DATA_BLOCK_STATE_ID); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/AbstractSkeleton.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/AbstractSkeleton.java.patch new file mode 100644 index 0000000000..c20b81663c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/AbstractSkeleton.java.patch @@ -0,0 +1,238 @@ +--- a/net/minecraft/world/entity/monster/AbstractSkeleton.java ++++ b/net/minecraft/world/entity/monster/AbstractSkeleton.java +@@ -12,14 +12,14 @@ + import net.minecraft.world.DifficultyInstance; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; + import net.minecraft.world.entity.PathfinderMob; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.AvoidEntityGoal; +@@ -44,11 +44,12 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public abstract class AbstractSkeleton extends Monster implements RangedAttackMob { +- private final RangedBowAttackGoal bowGoal = new RangedBowAttackGoal<>(this, 1.0, 20, 15.0F); +- private final MeleeAttackGoal meleeGoal = new MeleeAttackGoal(this, 1.2, false) { ++ ++ private final RangedBowAttackGoal bowGoal = new RangedBowAttackGoal<>(this, 1.0D, 20, 15.0F); ++ private final MeleeAttackGoal meleeGoal = new MeleeAttackGoal(this, 1.2D, false) { + @Override + public void stop() { + super.stop(); +@@ -70,51 +71,53 @@ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(2, new RestrictSunGoal(this)); +- this.goalSelector.addGoal(3, new FleeSunGoal(this, 1.0)); +- this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Wolf.class, 6.0F, 1.0, 1.2)); +- this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0)); ++ this.goalSelector.addGoal(3, new FleeSunGoal(this, 1.0D)); ++ this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Wolf.class, 6.0F, 1.0D, 1.2D)); ++ this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(6, new RandomLookAroundGoal(this)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this)); ++ this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0])); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR)); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.25); ++ return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.25D); + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(this.getStepSound(), 0.15F, 1.0F); + } + + abstract SoundEvent getStepSound(); + + @Override +- public MobType getMobType() { +- return MobType.UNDEAD; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.UNDEAD; + } + + @Override + public void aiStep() { +- boolean isSunBurnTick = this.isSunBurnTick(); +- if (isSunBurnTick) { +- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.HEAD); +- if (!itemBySlot.isEmpty()) { +- if (itemBySlot.isDamageableItem()) { +- itemBySlot.setDamageValue(itemBySlot.getDamageValue() + this.random.nextInt(2)); +- if (itemBySlot.getDamageValue() >= itemBySlot.getMaxDamage()) { ++ boolean flag = this.isSunBurnTick(); ++ ++ if (flag) { ++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); ++ ++ if (!itemstack.isEmpty()) { ++ if (itemstack.isDamageableItem()) { ++ itemstack.setDamageValue(itemstack.getDamageValue() + this.random.nextInt(2)); ++ if (itemstack.getDamageValue() >= itemstack.getMaxDamage()) { + this.broadcastBreakEvent(EquipmentSlot.HEAD); + this.setItemSlot(EquipmentSlot.HEAD, ItemStack.EMPTY); + } + } + +- isSunBurnTick = false; ++ flag = false; + } + +- if (isSunBurnTick) { ++ if (flag) { + this.setSecondsOnFire(8); + } + } +@@ -125,9 +128,14 @@ + @Override + public void rideTick() { + super.rideTick(); +- if (this.getControlledVehicle() instanceof PathfinderMob pathfinderMob) { +- this.yBodyRot = pathfinderMob.yBodyRot; ++ Entity entity = this.getControlledVehicle(); ++ ++ if (entity instanceof PathfinderMob) { ++ PathfinderMob entitycreature = (PathfinderMob) entity; ++ ++ this.yBodyRot = entitycreature.yBodyRot; + } ++ + } + + @Override +@@ -138,58 +146,73 @@ + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- SpawnGroupData var10 = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); +- RandomSource random = level.getRandom(); +- this.populateDefaultEquipmentSlots(random, difficulty); +- this.populateDefaultEquipmentEnchantments(random, difficulty); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ spawnData = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ RandomSource randomsource = level.getRandom(); ++ ++ this.populateDefaultEquipmentSlots(randomsource, difficulty); ++ this.populateDefaultEquipmentEnchantments(randomsource, difficulty); + this.reassessWeaponGoal(); +- this.setCanPickUpLoot(random.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); ++ this.setCanPickUpLoot(randomsource.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); + if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { +- LocalDate localDate = LocalDate.now(); +- int i = localDate.get(ChronoField.DAY_OF_MONTH); +- int i1 = localDate.get(ChronoField.MONTH_OF_YEAR); +- if (i1 == 10 && i == 31 && random.nextFloat() < 0.25F) { +- this.setItemSlot(EquipmentSlot.HEAD, new ItemStack(random.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN)); ++ LocalDate localdate = LocalDate.now(); ++ int i = localdate.get(ChronoField.DAY_OF_MONTH); ++ int j = localdate.get(ChronoField.MONTH_OF_YEAR); ++ ++ if (j == 10 && i == 31 && randomsource.nextFloat() < 0.25F) { ++ this.setItemSlot(EquipmentSlot.HEAD, new ItemStack(randomsource.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN)); + this.armorDropChances[EquipmentSlot.HEAD.getIndex()] = 0.0F; + } + } + +- return var10; ++ return spawnData; + } + + public void reassessWeaponGoal() { + if (this.level() != null && !this.level().isClientSide) { + this.goalSelector.removeGoal(this.meleeGoal); + this.goalSelector.removeGoal(this.bowGoal); +- ItemStack itemInHand = this.getItemInHand(ProjectileUtil.getWeaponHoldingHand(this, Items.BOW)); +- if (itemInHand.is(Items.BOW)) { +- int i = 20; ++ ItemStack itemstack = this.getItemInHand(ProjectileUtil.getWeaponHoldingHand(this, Items.BOW)); ++ ++ if (itemstack.is(Items.BOW)) { ++ byte b0 = 20; ++ + if (this.level().getDifficulty() != Difficulty.HARD) { +- i = 40; ++ b0 = 40; + } + +- this.bowGoal.setMinAttackInterval(i); ++ this.bowGoal.setMinAttackInterval(b0); + this.goalSelector.addGoal(4, this.bowGoal); + } else { + this.goalSelector.addGoal(4, this.meleeGoal); + } ++ + } + } + + @Override + public void performRangedAttack(LivingEntity target, float distanceFactor) { +- ItemStack projectile = this.getProjectile(this.getItemInHand(ProjectileUtil.getWeaponHoldingHand(this, Items.BOW))); +- AbstractArrow arrow = this.getArrow(projectile, distanceFactor); +- double d = target.getX() - this.getX(); +- double d1 = target.getY(0.3333333333333333) - arrow.getY(); ++ ItemStack itemstack = this.getProjectile(this.getItemInHand(ProjectileUtil.getWeaponHoldingHand(this, Items.BOW))); ++ AbstractArrow entityarrow = this.getArrow(itemstack, distanceFactor); ++ double d0 = target.getX() - this.getX(); ++ double d1 = target.getY(0.3333333333333333D) - entityarrow.getY(); + double d2 = target.getZ() - this.getZ(); +- double squareRoot = Math.sqrt(d * d + d2 * d2); +- arrow.shoot(d, d1 + squareRoot * 0.2F, d2, 1.6F, (float)(14 - this.level().getDifficulty().getId() * 4)); ++ double d3 = Math.sqrt(d0 * d0 + d2 * d2); ++ ++ entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level().getDifficulty().getId() * 4)); ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), null, entityarrow, net.minecraft.world.EnumHand.MAIN_HAND, 0.8F, true); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ ++ if (event.getProjectile() == entityarrow.getBukkitEntity()) { ++ this.level().addFreshEntity(entityarrow); ++ } ++ // CraftBukkit end + this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); +- this.level().addFreshEntity(arrow); ++ // this.level().addFreshEntity(entityarrow); // CraftBukkit - moved up + } + + protected AbstractArrow getArrow(ItemStack arrowStack, float velocity) { +@@ -213,10 +236,11 @@ + if (!this.level().isClientSide) { + this.reassessWeaponGoal(); + } ++ + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 1.74F; + } + diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/CaveSpider.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/CaveSpider.java.patch new file mode 100644 index 0000000000..0bb3955f74 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/CaveSpider.java.patch @@ -0,0 +1,78 @@ +--- a/net/minecraft/world/entity/monster/CaveSpider.java ++++ b/net/minecraft/world/entity/monster/CaveSpider.java +@@ -8,11 +8,11 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.level.Level; +@@ -20,27 +20,29 @@ + import org.joml.Vector3f; + + public class CaveSpider extends Spider { ++ + public CaveSpider(EntityType entityType, Level level) { + super(entityType, level); + } + + public static AttributeSupplier.Builder createCaveSpider() { +- return Spider.createAttributes().add(Attributes.MAX_HEALTH, 12.0); ++ return Spider.createAttributes().add(Attributes.MAX_HEALTH, 12.0D); + } + + @Override + public boolean doHurtTarget(Entity entity) { + if (super.doHurtTarget(entity)) { + if (entity instanceof LivingEntity) { +- int i = 0; ++ byte b0 = 0; ++ + if (this.level().getDifficulty() == Difficulty.NORMAL) { +- i = 7; ++ b0 = 7; + } else if (this.level().getDifficulty() == Difficulty.HARD) { +- i = 15; ++ b0 = 15; + } + +- if (i > 0) { +- ((LivingEntity)entity).addEffect(new MobEffectInstance(MobEffects.POISON, i * 20, 0), this); ++ if (b0 > 0) { ++ ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.POISON, b0 * 20, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + +@@ -52,20 +54,18 @@ + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + return spawnData; + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.45F; + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height, 0.0F); + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Creeper.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Creeper.java.patch new file mode 100644 index 0000000000..4a441084d9 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Creeper.java.patch @@ -0,0 +1,319 @@ +--- a/net/minecraft/world/entity/monster/Creeper.java ++++ b/net/minecraft/world/entity/monster/Creeper.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.entity.monster; + + import java.util.Collection; ++import java.util.Iterator; + import javax.annotation.Nullable; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.syncher.EntityDataAccessor; +@@ -11,7 +12,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.tags.ItemTags; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffectInstance; +@@ -38,17 +39,25 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end ++ + public class Creeper extends Monster implements PowerableMob { ++ + private static final EntityDataAccessor DATA_SWELL_DIR = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_IS_POWERED = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_IS_IGNITED = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.BOOLEAN); + private int oldSwell; +- private int swell; +- private int maxSwell = 30; +- private int explosionRadius = 3; ++ public int swell; ++ public int maxSwell = 30; ++ public int explosionRadius = 3; + private int droppedSkulls; + + public Creeper(EntityType entityType, Level level) { +@@ -59,29 +68,30 @@ + protected void registerGoals() { + this.goalSelector.addGoal(1, new FloatGoal(this)); + this.goalSelector.addGoal(2, new SwellGoal(this)); +- this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Ocelot.class, 6.0F, 1.0, 1.2)); +- this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Cat.class, 6.0F, 1.0, 1.2)); +- this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0, false)); +- this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.8)); ++ this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Ocelot.class, 6.0F, 1.0D, 1.2D)); ++ this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Cat.class, 6.0F, 1.0D, 1.2D)); ++ this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0D, false)); ++ this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.8D)); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(6, new RandomLookAroundGoal(this)); + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, true)); +- this.targetSelector.addGoal(2, new HurtByTargetGoal(this)); ++ this.targetSelector.addGoal(2, new HurtByTargetGoal(this, new Class[0])); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.25); ++ return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.25D); + } + + @Override + public int getMaxFallDistance() { +- return this.getTarget() == null ? 3 : 3 + (int)(this.getHealth() - 1.0F); ++ return this.getTarget() == null ? 3 : 3 + (int) (this.getHealth() - 1.0F); + } + + @Override + public boolean causeFallDamage(float fallDistance, float multiplier, DamageSource source) { + boolean flag = super.causeFallDamage(fallDistance, multiplier, source); +- this.swell += (int)(fallDistance * 1.5F); ++ ++ this.swell += (int) (fallDistance * 1.5F); + if (this.swell > this.maxSwell - 5) { + this.swell = this.maxSwell - 5; + } +@@ -92,27 +102,27 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_SWELL_DIR, -1); +- this.entityData.define(DATA_IS_POWERED, false); +- this.entityData.define(DATA_IS_IGNITED, false); ++ this.entityData.define(Creeper.DATA_SWELL_DIR, -1); ++ this.entityData.define(Creeper.DATA_IS_POWERED, false); ++ this.entityData.define(Creeper.DATA_IS_IGNITED, false); + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- if (this.entityData.get(DATA_IS_POWERED)) { ++ if ((Boolean) this.entityData.get(Creeper.DATA_IS_POWERED)) { + compound.putBoolean("powered", true); + } + +- compound.putShort("Fuse", (short)this.maxSwell); +- compound.putByte("ExplosionRadius", (byte)this.explosionRadius); ++ compound.putShort("Fuse", (short) this.maxSwell); ++ compound.putByte("ExplosionRadius", (byte) this.explosionRadius); + compound.putBoolean("ignited", this.isIgnited()); + } + + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); +- this.entityData.set(DATA_IS_POWERED, compound.getBoolean("powered")); ++ this.entityData.set(Creeper.DATA_IS_POWERED, compound.getBoolean("powered")); + if (compound.contains("Fuse", 99)) { + this.maxSwell = compound.getShort("Fuse"); + } +@@ -124,6 +134,7 @@ + if (compound.getBoolean("ignited")) { + this.ignite(); + } ++ + } + + @Override +@@ -134,13 +145,14 @@ + this.setSwellDir(1); + } + +- int swellDir = this.getSwellDir(); +- if (swellDir > 0 && this.swell == 0) { ++ int i = this.getSwellDir(); ++ ++ if (i > 0 && this.swell == 0) { + this.playSound(SoundEvents.CREEPER_PRIMED, 1.0F, 0.5F); + this.gameEvent(GameEvent.PRIME_FUSE); + } + +- this.swell += swellDir; ++ this.swell += i; + if (this.swell < 0) { + this.swell = 0; + } +@@ -175,10 +187,16 @@ + protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { + super.dropCustomDeathLoot(source, looting, recentlyHit); + Entity entity = source.getEntity(); +- if (entity != this && entity instanceof Creeper creeper && creeper.canDropMobsSkull()) { +- creeper.increaseDroppedSkulls(); +- this.spawnAtLocation(Items.CREEPER_HEAD); ++ ++ if (entity != this && entity instanceof Creeper) { ++ Creeper entitycreeper = (Creeper) entity; ++ ++ if (entitycreeper.canDropMobsSkull()) { ++ entitycreeper.increaseDroppedSkulls(); ++ this.spawnAtLocation((IMaterial) Items.CREEPER_HEAD); ++ } + } ++ + } + + @Override +@@ -188,40 +206,54 @@ + + @Override + public boolean isPowered() { +- return this.entityData.get(DATA_IS_POWERED); ++ return (Boolean) this.entityData.get(Creeper.DATA_IS_POWERED); + } + + public float getSwelling(float partialTicks) { +- return Mth.lerp(partialTicks, (float)this.oldSwell, (float)this.swell) / (float)(this.maxSwell - 2); ++ return Mth.lerp(partialTicks, (float) this.oldSwell, (float) this.swell) / (float) (this.maxSwell - 2); + } + + public int getSwellDir() { +- return this.entityData.get(DATA_SWELL_DIR); ++ return (Integer) this.entityData.get(Creeper.DATA_SWELL_DIR); + } + + public void setSwellDir(int state) { +- this.entityData.set(DATA_SWELL_DIR, state); ++ this.entityData.set(Creeper.DATA_SWELL_DIR, state); + } + + @Override + public void thunderHit(ServerLevel level, LightningBolt lightning) { + super.thunderHit(level, lightning); +- this.entityData.set(DATA_IS_POWERED, true); ++ // CraftBukkit start ++ if (CraftEventFactory.callCreeperPowerEvent(this, lightning, org.bukkit.event.entity.CreeperPowerEvent.PowerCause.LIGHTNING).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ this.entityData.set(Creeper.DATA_IS_POWERED, true); + } + ++ // CraftBukkit start ++ public void setPowered(boolean powered) { ++ this.entityData.set(Creeper.DATA_IS_POWERED, powered); ++ } ++ // CraftBukkit end ++ + @Override +- protected InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (itemInHand.is(ItemTags.CREEPER_IGNITERS)) { +- SoundEvent soundEvent = itemInHand.is(Items.FIRE_CHARGE) ? SoundEvents.FIRECHARGE_USE : SoundEvents.FLINTANDSTEEL_USE; +- this.level() +- .playSound(player, this.getX(), this.getY(), this.getZ(), soundEvent, this.getSoundSource(), 1.0F, this.random.nextFloat() * 0.4F + 0.8F); ++ protected InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (itemstack.is(ItemTags.CREEPER_IGNITERS)) { ++ SoundEvent soundeffect = itemstack.is(Items.FIRE_CHARGE) ? SoundEvents.FIRECHARGE_USE : SoundEvents.FLINTANDSTEEL_USE; ++ ++ this.level().playSound(player, this.getX(), this.getY(), this.getZ(), soundeffect, this.getSoundSource(), 1.0F, this.random.nextFloat() * 0.4F + 0.8F); + if (!this.level().isClientSide) { + this.ignite(); +- if (!itemInHand.isDamageableItem()) { +- itemInHand.shrink(1); ++ if (itemstack.getItem().getMaxDamage() == 0) { // CraftBukkit - fix MC-264285: unbreakable flint and steels are completely consumed when igniting a creeper ++ itemstack.shrink(1); + } else { +- itemInHand.hurtAndBreak(1, player, entity -> entity.broadcastBreakEvent(hand)); ++ itemstack.hurtAndBreak(1, player, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(hand); ++ }); + } + } + +@@ -231,40 +263,58 @@ + } + } + +- private void explodeCreeper() { ++ public void explodeCreeper() { + if (!this.level().isClientSide) { + float f = this.isPowered() ? 2.0F : 1.0F; ++ ++ // CraftBukkit start ++ ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent(this, this.explosionRadius * f, false); ++ if (!event.isCancelled()) { ++ // CraftBukkit end + this.dead = true; +- this.level().explode(this, this.getX(), this.getY(), this.getZ(), (float)this.explosionRadius * f, Level.ExplosionInteraction.MOB); ++ this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.MOB); // CraftBukkit + this.discard(); + this.spawnLingeringCloud(); ++ // CraftBukkit start ++ } else { ++ swell = 0; ++ } ++ // CraftBukkit end + } ++ + } + + private void spawnLingeringCloud() { +- Collection activeEffects = this.getActiveEffects(); +- if (!activeEffects.isEmpty()) { +- AreaEffectCloud areaEffectCloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); +- areaEffectCloud.setRadius(2.5F); +- areaEffectCloud.setRadiusOnUse(-0.5F); +- areaEffectCloud.setWaitTime(10); +- areaEffectCloud.setDuration(areaEffectCloud.getDuration() / 2); +- areaEffectCloud.setRadiusPerTick(-areaEffectCloud.getRadius() / (float)areaEffectCloud.getDuration()); ++ Collection collection = this.getActiveEffects(); + +- for (MobEffectInstance mobEffectInstance : activeEffects) { +- areaEffectCloud.addEffect(new MobEffectInstance(mobEffectInstance)); ++ if (!collection.isEmpty()) { ++ AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); ++ ++ entityareaeffectcloud.setOwner(this); // CraftBukkit ++ entityareaeffectcloud.setRadius(2.5F); ++ entityareaeffectcloud.setRadiusOnUse(-0.5F); ++ entityareaeffectcloud.setWaitTime(10); ++ entityareaeffectcloud.setDuration(entityareaeffectcloud.getDuration() / 2); ++ entityareaeffectcloud.setRadiusPerTick(-entityareaeffectcloud.getRadius() / (float) entityareaeffectcloud.getDuration()); ++ Iterator iterator = collection.iterator(); ++ ++ while (iterator.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); ++ ++ entityareaeffectcloud.addEffect(new MobEffectInstance(mobeffect)); + } + +- this.level().addFreshEntity(areaEffectCloud); ++ this.level().addFreshEntity(entityareaeffectcloud, CreatureSpawnEvent.SpawnReason.EXPLOSION); // CraftBukkit + } ++ + } + + public boolean isIgnited() { +- return this.entityData.get(DATA_IS_IGNITED); ++ return (Boolean) this.entityData.get(Creeper.DATA_IS_IGNITED); + } + + public void ignite() { +- this.entityData.set(DATA_IS_IGNITED, true); ++ this.entityData.set(Creeper.DATA_IS_IGNITED, true); + } + + public boolean canDropMobsSkull() { +@@ -272,6 +322,6 @@ + } + + public void increaseDroppedSkulls() { +- this.droppedSkulls++; ++ ++this.droppedSkulls; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Drowned.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Drowned.java.patch new file mode 100644 index 0000000000..e6905ed1f3 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Drowned.java.patch @@ -0,0 +1,580 @@ +--- a/net/minecraft/world/entity/monster/Drowned.java ++++ b/net/minecraft/world/entity/monster/Drowned.java +@@ -13,15 +13,15 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.world.Difficulty; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.PathfinderMob; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.MoveControl; + import net.minecraft.world.entity.ai.goal.Goal; +@@ -53,10 +53,11 @@ + import net.minecraft.world.phys.Vec3; + + public class Drowned extends Zombie implements RangedAttackMob { ++ + public static final float NAUTILUS_SHELL_CHANCE = 0.03F; + boolean searchingForLand; +- protected final WaterBoundPathNavigation waterNavigation; +- protected final GroundPathNavigation groundNavigation; ++ public final WaterBoundPathNavigation waterNavigation; ++ public final GroundPathNavigation groundNavigation; + + public Drowned(EntityType entityType, Level level) { + super(entityType, level); +@@ -69,13 +70,13 @@ + + @Override + protected void addBehaviourGoals() { +- this.goalSelector.addGoal(1, new Drowned.DrownedGoToWaterGoal(this, 1.0)); +- this.goalSelector.addGoal(2, new Drowned.DrownedTridentAttackGoal(this, 1.0, 40, 10.0F)); +- this.goalSelector.addGoal(2, new Drowned.DrownedAttackGoal(this, 1.0, false)); +- this.goalSelector.addGoal(5, new Drowned.DrownedGoToBeachGoal(this, 1.0)); +- this.goalSelector.addGoal(6, new Drowned.DrownedSwimUpGoal(this, 1.0, this.level().getSeaLevel())); +- this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Drowned.class).setAlertOthers(ZombifiedPiglin.class)); ++ this.goalSelector.addGoal(1, new Drowned.DrownedGoToWaterGoal(this, 1.0D)); ++ this.goalSelector.addGoal(2, new Drowned.DrownedTridentAttackGoal(this, 1.0D, 40, 10.0F)); ++ this.goalSelector.addGoal(2, new Drowned.DrownedAttackGoal(this, 1.0D, false)); ++ this.goalSelector.addGoal(5, new Drowned.DrownedGoToBeachGoal(this, 1.0D)); ++ this.goalSelector.addGoal(6, new Drowned.DrownedSwimUpGoal(this, 1.0D, this.level().getSeaLevel())); ++ this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0D)); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Drowned.class})).setAlertOthers(ZombifiedPiglin.class)); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::okTarget)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); +@@ -84,35 +85,24 @@ + } + + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- SpawnGroupData var6 = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ spawnData = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + if (this.getItemBySlot(EquipmentSlot.OFFHAND).isEmpty() && level.getRandom().nextFloat() < 0.03F) { + this.setItemSlot(EquipmentSlot.OFFHAND, new ItemStack(Items.NAUTILUS_SHELL)); + this.setGuaranteedDrop(EquipmentSlot.OFFHAND); + } + +- return var6; ++ return spawnData; + } + +- public static boolean checkDrownedSpawnRules( +- EntityType drowned, ServerLevelAccessor serverLevel, MobSpawnType mobSpawnType, BlockPos pos, RandomSource random +- ) { +- if (!serverLevel.getFluidState(pos.below()).is(FluidTags.WATER) && !MobSpawnType.isSpawner(mobSpawnType)) { ++ public static boolean checkDrownedSpawnRules(EntityType drowned, ServerLevelAccessor serverLevel, EnumMobSpawn mobSpawnType, BlockPos pos, RandomSource random) { ++ if (!serverLevel.getFluidState(pos.below()).is(FluidTags.WATER) && !EnumMobSpawn.isSpawner(mobSpawnType)) { + return false; + } else { +- Holder biome = serverLevel.getBiome(pos); +- boolean flag = serverLevel.getDifficulty() != Difficulty.PEACEFUL +- && (MobSpawnType.ignoresLightRequirements(mobSpawnType) || isDarkEnoughToSpawn(serverLevel, pos, random)) +- && (MobSpawnType.isSpawner(mobSpawnType) || serverLevel.getFluidState(pos).is(FluidTags.WATER)); +- if (flag && MobSpawnType.isSpawner(mobSpawnType)) { +- return true; +- } else { +- return biome.is(BiomeTags.MORE_FREQUENT_DROWNED_SPAWNS) +- ? random.nextInt(15) == 0 && flag +- : random.nextInt(40) == 0 && isDeepEnoughToSpawn(serverLevel, pos) && flag; +- } ++ Holder holder = serverLevel.getBiome(pos); ++ boolean flag = serverLevel.getDifficulty() != Difficulty.PEACEFUL && (EnumMobSpawn.ignoresLightRequirements(mobSpawnType) || isDarkEnoughToSpawn(serverLevel, pos, random)) && (EnumMobSpawn.isSpawner(mobSpawnType) || serverLevel.getFluidState(pos).is(FluidTags.WATER)); ++ ++ return flag && EnumMobSpawn.isSpawner(mobSpawnType) ? true : (holder.is(BiomeTags.MORE_FREQUENT_DROWNED_SPAWNS) ? random.nextInt(15) == 0 && flag : random.nextInt(40) == 0 && isDeepEnoughToSpawn(serverLevel, pos) && flag); + } + } + +@@ -157,25 +147,21 @@ + + @Override + protected void populateDefaultEquipmentSlots(RandomSource random, DifficultyInstance difficulty) { +- if ((double)random.nextFloat() > 0.9) { +- int randomInt = random.nextInt(16); +- if (randomInt < 10) { ++ if ((double) random.nextFloat() > 0.9D) { ++ int i = random.nextInt(16); ++ ++ if (i < 10) { + this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.TRIDENT)); + } else { + this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.FISHING_ROD)); + } + } ++ + } + + @Override + protected boolean canReplaceCurrentItem(ItemStack candidate, ItemStack existing) { +- if (existing.is(Items.NAUTILUS_SHELL)) { +- return false; +- } else { +- return existing.is(Items.TRIDENT) +- ? candidate.is(Items.TRIDENT) && candidate.getDamageValue() < existing.getDamageValue() +- : candidate.is(Items.TRIDENT) || super.canReplaceCurrentItem(candidate, existing); +- } ++ return existing.is(Items.NAUTILUS_SHELL) ? false : (existing.is(Items.TRIDENT) ? (candidate.is(Items.TRIDENT) ? candidate.getDamageValue() < existing.getDamageValue() : false) : (candidate.is(Items.TRIDENT) ? true : super.canReplaceCurrentItem(candidate, existing))); + } + + @Override +@@ -189,7 +175,7 @@ + } + + public boolean okTarget(@Nullable LivingEntity target) { +- return target != null && (!this.level().isDay() || target.isInWater()); ++ return target != null ? !this.level().isDay() || target.isInWater() : false; + } + + @Override +@@ -201,8 +187,9 @@ + if (this.searchingForLand) { + return true; + } else { +- LivingEntity target = this.getTarget(); +- return target != null && target.isInWater(); ++ LivingEntity entityliving = this.getTarget(); ++ ++ return entityliving != null && entityliving.isInWater(); + } + } + +@@ -210,11 +197,12 @@ + public void travel(Vec3 travelVector) { + if (this.isControlledByLocalInstance() && this.isInWater() && this.wantsToSwim()) { + this.moveRelative(0.01F, travelVector); +- this.move(MoverType.SELF, this.getDeltaMovement()); +- this.setDeltaMovement(this.getDeltaMovement().scale(0.9)); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); ++ this.setDeltaMovement(this.getDeltaMovement().scale(0.9D)); + } else { + super.travel(travelVector); + } ++ + } + + @Override +@@ -228,6 +216,7 @@ + this.setSwimming(false); + } + } ++ + } + + @Override +@@ -236,12 +225,15 @@ + } + + protected boolean closeToNextPos() { +- Path path = this.getNavigation().getPath(); +- if (path != null) { +- BlockPos target = path.getTarget(); +- if (target != null) { +- double d = this.distanceToSqr((double)target.getX(), (double)target.getY(), (double)target.getZ()); +- if (d < 4.0) { ++ Path pathentity = this.getNavigation().getPath(); ++ ++ if (pathentity != null) { ++ BlockPos blockposition = pathentity.getTarget(); ++ ++ if (blockposition != null) { ++ double d0 = this.distanceToSqr((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()); ++ ++ if (d0 < 4.0D) { + return true; + } + } +@@ -252,80 +244,72 @@ + + @Override + public void performRangedAttack(LivingEntity target, float distanceFactor) { +- ThrownTrident thrownTrident = new ThrownTrident(this.level(), this, new ItemStack(Items.TRIDENT)); +- double d = target.getX() - this.getX(); +- double d1 = target.getY(0.3333333333333333) - thrownTrident.getY(); ++ ThrownTrident entitythrowntrident = new ThrownTrident(this.level(), this, this.getItemInHand(net.minecraft.world.entity.projectile.ProjectileUtil.getWeaponHoldingHand(this, Items.TRIDENT))); // CraftBukkit - Use Trident in hand like skeletons (SPIGOT-7025) ++ double d0 = target.getX() - this.getX(); ++ double d1 = target.getY(0.3333333333333333D) - entitythrowntrident.getY(); + double d2 = target.getZ() - this.getZ(); +- double squareRoot = Math.sqrt(d * d + d2 * d2); +- thrownTrident.shoot(d, d1 + squareRoot * 0.2F, d2, 1.6F, (float)(14 - this.level().getDifficulty().getId() * 4)); ++ double d3 = Math.sqrt(d0 * d0 + d2 * d2); ++ ++ entitythrowntrident.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level().getDifficulty().getId() * 4)); + this.playSound(SoundEvents.DROWNED_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); +- this.level().addFreshEntity(thrownTrident); ++ this.level().addFreshEntity(entitythrowntrident); + } + + public void setSearchingForLand(boolean searchingForLand) { + this.searchingForLand = searchingForLand; + } + +- static class DrownedAttackGoal extends ZombieAttackGoal { ++ private static class DrownedMoveControl extends MoveControl { ++ + private final Drowned drowned; + +- public DrownedAttackGoal(Drowned drowned, double speedModifier, boolean followingTargetEvenIfNotSeen) { +- super(drowned, speedModifier, followingTargetEvenIfNotSeen); ++ public DrownedMoveControl(Drowned drowned) { ++ super(drowned); + this.drowned = drowned; + } + + @Override +- public boolean canUse() { +- return super.canUse() && this.drowned.okTarget(this.drowned.getTarget()); +- } ++ public void tick() { ++ LivingEntity entityliving = this.drowned.getTarget(); + +- @Override +- public boolean canContinueToUse() { +- return super.canContinueToUse() && this.drowned.okTarget(this.drowned.getTarget()); +- } +- } ++ if (this.drowned.wantsToSwim() && this.drowned.isInWater()) { ++ if (entityliving != null && entityliving.getY() > this.drowned.getY() || this.drowned.searchingForLand) { ++ this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(0.0D, 0.002D, 0.0D)); ++ } + +- static class DrownedGoToBeachGoal extends MoveToBlockGoal { +- private final Drowned drowned; ++ if (this.operation != MoveControl.Operation.MOVE_TO || this.drowned.getNavigation().isDone()) { ++ this.drowned.setSpeed(0.0F); ++ return; ++ } + +- public DrownedGoToBeachGoal(Drowned drowned, double speedModifier) { +- super(drowned, speedModifier, 8, 2); +- this.drowned = drowned; +- } ++ double d0 = this.wantedX - this.drowned.getX(); ++ double d1 = this.wantedY - this.drowned.getY(); ++ double d2 = this.wantedZ - this.drowned.getZ(); ++ double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2); + +- @Override +- public boolean canUse() { +- return super.canUse() +- && !this.drowned.level().isDay() +- && this.drowned.isInWater() +- && this.drowned.getY() >= (double)(this.drowned.level().getSeaLevel() - 3); +- } ++ d1 /= d3; ++ float f = (float) (Mth.atan2(d2, d0) * 57.2957763671875D) - 90.0F; + +- @Override +- public boolean canContinueToUse() { +- return super.canContinueToUse(); +- } ++ this.drowned.setYRot(this.rotlerp(this.drowned.getYRot(), f, 90.0F)); ++ this.drowned.yBodyRot = this.drowned.getYRot(); ++ float f1 = (float) (this.speedModifier * this.drowned.getAttributeValue(Attributes.MOVEMENT_SPEED)); ++ float f2 = Mth.lerp(0.125F, this.drowned.getSpeed(), f1); + +- @Override +- protected boolean isValidTarget(LevelReader level, BlockPos pos) { +- BlockPos blockPos = pos.above(); +- return level.isEmptyBlock(blockPos) && level.isEmptyBlock(blockPos.above()) && level.getBlockState(pos).entityCanStandOn(level, pos, this.drowned); +- } ++ this.drowned.setSpeed(f2); ++ this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add((double) f2 * d0 * 0.005D, (double) f2 * d1 * 0.1D, (double) f2 * d2 * 0.005D)); ++ } else { ++ if (!this.drowned.onGround()) { ++ this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(0.0D, -0.008D, 0.0D)); ++ } + +- @Override +- public void start() { +- this.drowned.setSearchingForLand(false); +- this.drowned.navigation = this.drowned.groundNavigation; +- super.start(); +- } ++ super.tick(); ++ } + +- @Override +- public void stop() { +- super.stop(); + } + } + +- static class DrownedGoToWaterGoal extends Goal { ++ private static class DrownedGoToWaterGoal extends Goal { ++ + private final PathfinderMob mob; + private double wantedX; + private double wantedY; +@@ -337,7 +321,7 @@ + this.mob = mob; + this.speedModifier = speedModifier; + this.level = mob.level(); +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +@@ -347,13 +331,14 @@ + } else if (this.mob.isInWater()) { + return false; + } else { +- Vec3 waterPos = this.getWaterPos(); +- if (waterPos == null) { ++ Vec3 vec3d = this.getWaterPos(); ++ ++ if (vec3d == null) { + return false; + } else { +- this.wantedX = waterPos.x; +- this.wantedY = waterPos.y; +- this.wantedZ = waterPos.z; ++ this.wantedX = vec3d.x; ++ this.wantedY = vec3d.y; ++ this.wantedZ = vec3d.z; + return true; + } + } +@@ -371,13 +356,14 @@ + + @Nullable + private Vec3 getWaterPos() { +- RandomSource random = this.mob.getRandom(); +- BlockPos blockPos = this.mob.blockPosition(); ++ RandomSource randomsource = this.mob.getRandom(); ++ BlockPos blockposition = this.mob.blockPosition(); + +- for (int i = 0; i < 10; i++) { +- BlockPos blockPos1 = blockPos.offset(random.nextInt(20) - 10, 2 - random.nextInt(8), random.nextInt(20) - 10); +- if (this.level.getBlockState(blockPos1).is(Blocks.WATER)) { +- return Vec3.atBottomCenterOf(blockPos1); ++ for (int i = 0; i < 10; ++i) { ++ BlockPos blockposition1 = blockposition.offset(randomsource.nextInt(20) - 10, 2 - randomsource.nextInt(8), randomsource.nextInt(20) - 10); ++ ++ if (this.level.getBlockState(blockposition1).is(Blocks.WATER)) { ++ return Vec3.atBottomCenterOf(blockposition1); + } + } + +@@ -385,123 +371,141 @@ + } + } + +- static class DrownedMoveControl extends MoveControl { ++ private static class DrownedTridentAttackGoal extends RangedAttackGoal { ++ + private final Drowned drowned; + +- public DrownedMoveControl(Drowned mob) { +- super(mob); +- this.drowned = mob; ++ public DrownedTridentAttackGoal(RangedAttackMob rangedAttackMob, double speedModifier, int i, float attackInterval) { ++ super(rangedAttackMob, speedModifier, i, attackInterval); ++ this.drowned = (Drowned) rangedAttackMob; + } + + @Override +- public void tick() { +- LivingEntity target = this.drowned.getTarget(); +- if (this.drowned.wantsToSwim() && this.drowned.isInWater()) { +- if (target != null && target.getY() > this.drowned.getY() || this.drowned.searchingForLand) { +- this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(0.0, 0.002, 0.0)); +- } ++ public boolean canUse() { ++ return super.canUse() && this.drowned.getMainHandItem().is(Items.TRIDENT); ++ } + +- if (this.operation != MoveControl.Operation.MOVE_TO || this.drowned.getNavigation().isDone()) { +- this.drowned.setSpeed(0.0F); +- return; +- } ++ @Override ++ public void start() { ++ super.start(); ++ this.drowned.setAggressive(true); ++ this.drowned.startUsingItem(EnumHand.MAIN_HAND); ++ } + +- double d = this.wantedX - this.drowned.getX(); +- double d1 = this.wantedY - this.drowned.getY(); +- double d2 = this.wantedZ - this.drowned.getZ(); +- double squareRoot = Math.sqrt(d * d + d1 * d1 + d2 * d2); +- d1 /= squareRoot; +- float f = (float)(Mth.atan2(d2, d) * 180.0F / (float)Math.PI) - 90.0F; +- this.drowned.setYRot(this.rotlerp(this.drowned.getYRot(), f, 90.0F)); +- this.drowned.yBodyRot = this.drowned.getYRot(); +- float f1 = (float)(this.speedModifier * this.drowned.getAttributeValue(Attributes.MOVEMENT_SPEED)); +- float f2 = Mth.lerp(0.125F, this.drowned.getSpeed(), f1); +- this.drowned.setSpeed(f2); +- this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add((double)f2 * d * 0.005, (double)f2 * d1 * 0.1, (double)f2 * d2 * 0.005)); +- } else { +- if (!this.drowned.onGround()) { +- this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(0.0, -0.008, 0.0)); +- } ++ @Override ++ public void stop() { ++ super.stop(); ++ this.drowned.stopUsingItem(); ++ this.drowned.setAggressive(false); ++ } ++ } + +- super.tick(); +- } ++ private static class DrownedAttackGoal extends ZombieAttackGoal { ++ ++ private final Drowned drowned; ++ ++ public DrownedAttackGoal(Drowned drowned, double speedModifier, boolean flag) { ++ super((Zombie) drowned, speedModifier, flag); ++ this.drowned = drowned; + } ++ ++ @Override ++ public boolean canUse() { ++ return super.canUse() && this.drowned.okTarget(this.drowned.getTarget()); ++ } ++ ++ @Override ++ public boolean canContinueToUse() { ++ return super.canContinueToUse() && this.drowned.okTarget(this.drowned.getTarget()); ++ } + } + +- static class DrownedSwimUpGoal extends Goal { ++ private static class DrownedGoToBeachGoal extends MoveToBlockGoal { ++ + private final Drowned drowned; +- private final double speedModifier; +- private final int seaLevel; +- private boolean stuck; + +- public DrownedSwimUpGoal(Drowned drowned, double speedModifier, int seaLevel) { ++ public DrownedGoToBeachGoal(Drowned drowned, double speedModifier) { ++ super(drowned, speedModifier, 8, 2); + this.drowned = drowned; +- this.speedModifier = speedModifier; +- this.seaLevel = seaLevel; + } + + @Override + public boolean canUse() { +- return !this.drowned.level().isDay() && this.drowned.isInWater() && this.drowned.getY() < (double)(this.seaLevel - 2); ++ return super.canUse() && !this.drowned.level().isDay() && this.drowned.isInWater() && this.drowned.getY() >= (double) (this.drowned.level().getSeaLevel() - 3); + } + + @Override + public boolean canContinueToUse() { +- return this.canUse() && !this.stuck; ++ return super.canContinueToUse(); + } + + @Override +- public void tick() { +- if (this.drowned.getY() < (double)(this.seaLevel - 1) && (this.drowned.getNavigation().isDone() || this.drowned.closeToNextPos())) { +- Vec3 posTowards = DefaultRandomPos.getPosTowards( +- this.drowned, 4, 8, new Vec3(this.drowned.getX(), (double)(this.seaLevel - 1), this.drowned.getZ()), (float) (Math.PI / 2) +- ); +- if (posTowards == null) { +- this.stuck = true; +- return; +- } ++ protected boolean isValidTarget(LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.above(); + +- this.drowned.getNavigation().moveTo(posTowards.x, posTowards.y, posTowards.z, this.speedModifier); +- } ++ return level.isEmptyBlock(blockposition1) && level.isEmptyBlock(blockposition1.above()) ? level.getBlockState(pos).entityCanStandOn(level, pos, this.drowned) : false; + } + + @Override + public void start() { +- this.drowned.setSearchingForLand(true); +- this.stuck = false; ++ this.drowned.setSearchingForLand(false); ++ this.drowned.navigation = this.drowned.groundNavigation; ++ super.start(); + } + + @Override + public void stop() { +- this.drowned.setSearchingForLand(false); ++ super.stop(); + } + } + +- static class DrownedTridentAttackGoal extends RangedAttackGoal { ++ private static class DrownedSwimUpGoal extends Goal { ++ + private final Drowned drowned; ++ private final double speedModifier; ++ private final int seaLevel; ++ private boolean stuck; + +- public DrownedTridentAttackGoal(RangedAttackMob rangedAttackMob, double speedModifier, int attackInterval, float attackRadius) { +- super(rangedAttackMob, speedModifier, attackInterval, attackRadius); +- this.drowned = (Drowned)rangedAttackMob; ++ public DrownedSwimUpGoal(Drowned drowned, double speedModifier, int i) { ++ this.drowned = drowned; ++ this.speedModifier = speedModifier; ++ this.seaLevel = i; + } + + @Override + public boolean canUse() { +- return super.canUse() && this.drowned.getMainHandItem().is(Items.TRIDENT); ++ return !this.drowned.level().isDay() && this.drowned.isInWater() && this.drowned.getY() < (double) (this.seaLevel - 2); + } + + @Override ++ public boolean canContinueToUse() { ++ return this.canUse() && !this.stuck; ++ } ++ ++ @Override ++ public void tick() { ++ if (this.drowned.getY() < (double) (this.seaLevel - 1) && (this.drowned.getNavigation().isDone() || this.drowned.closeToNextPos())) { ++ Vec3 vec3d = DefaultRandomPos.getPosTowards(this.drowned, 4, 8, new Vec3(this.drowned.getX(), (double) (this.seaLevel - 1), this.drowned.getZ()), 1.5707963705062866D); ++ ++ if (vec3d == null) { ++ this.stuck = true; ++ return; ++ } ++ ++ this.drowned.getNavigation().moveTo(vec3d.x, vec3d.y, vec3d.z, this.speedModifier); ++ } ++ ++ } ++ ++ @Override + public void start() { +- super.start(); +- this.drowned.setAggressive(true); +- this.drowned.startUsingItem(InteractionHand.MAIN_HAND); ++ this.drowned.setSearchingForLand(true); ++ this.stuck = false; + } + + @Override + public void stop() { +- super.stop(); +- this.drowned.stopUsingItem(); +- this.drowned.setAggressive(false); ++ this.drowned.setSearchingForLand(false); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/ElderGuardian.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/ElderGuardian.java.patch new file mode 100644 index 0000000000..52bedd93b6 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/ElderGuardian.java.patch @@ -0,0 +1,54 @@ +--- a/net/minecraft/world/entity/monster/ElderGuardian.java ++++ b/net/minecraft/world/entity/monster/ElderGuardian.java +@@ -19,6 +19,7 @@ + import org.joml.Vector3f; + + public class ElderGuardian extends Guardian { ++ + public static final float ELDER_SIZE_SCALE = EntityType.ELDER_GUARDIAN.getWidth() / EntityType.GUARDIAN.getWidth(); + private static final int EFFECT_INTERVAL = 1200; + private static final int EFFECT_RADIUS = 50; +@@ -32,10 +33,11 @@ + if (this.randomStrollGoal != null) { + this.randomStrollGoal.setInterval(400); + } ++ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Guardian.createAttributes().add(Attributes.MOVEMENT_SPEED, 0.3F).add(Attributes.ATTACK_DAMAGE, 8.0).add(Attributes.MAX_HEALTH, 80.0); ++ return Guardian.createAttributes().add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D).add(Attributes.ATTACK_DAMAGE, 8.0D).add(Attributes.MAX_HEALTH, 80.0D); + } + + @Override +@@ -67,21 +69,22 @@ + protected void customServerAiStep() { + super.customServerAiStep(); + if ((this.tickCount + this.getId()) % 1200 == 0) { +- MobEffectInstance mobEffectInstance = new MobEffectInstance(MobEffects.DIG_SLOWDOWN, 6000, 2); +- List list = MobEffectUtil.addEffectToPlayersAround((ServerLevel)this.level(), this, this.position(), 50.0, mobEffectInstance, 1200); +- list.forEach( +- serverPlayer -> serverPlayer.connection +- .send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, this.isSilent() ? 0.0F : 1.0F)) +- ); ++ MobEffectInstance mobeffect = new MobEffectInstance(MobEffects.DIG_SLOWDOWN, 6000, 2); ++ List list = MobEffectUtil.addEffectToPlayersAround((ServerLevel) this.level(), this, this.position(), 50.0D, mobeffect, 1200, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit ++ ++ list.forEach((entityplayer) -> { ++ entityplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, this.isSilent() ? 0.0F : 1.0F)); ++ }); + } + + if (!this.hasRestriction()) { + this.restrictTo(this.blockPosition(), 16); + } ++ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.353125F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.353125F * f, 0.0F); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/EnderMan.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/EnderMan.java.patch new file mode 100644 index 0000000000..56412da320 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/EnderMan.java.patch @@ -0,0 +1,692 @@ +--- a/net/minecraft/world/entity/monster/EnderMan.java ++++ b/net/minecraft/world/entity/monster/EnderMan.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.entity.monster; + + import java.util.EnumSet; ++import java.util.Iterator; + import java.util.List; + import java.util.Optional; + import java.util.UUID; +@@ -29,10 +30,10 @@ + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.NeutralMob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -60,7 +61,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.level.storage.loot.LootParams; +@@ -70,16 +71,18 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end ++ + public class EnderMan extends Monster implements NeutralMob { ++ + private static final UUID SPEED_MODIFIER_ATTACKING_UUID = UUID.fromString("020E0DFB-87AE-4653-9556-831010E291A0"); +- private static final AttributeModifier SPEED_MODIFIER_ATTACKING = new AttributeModifier( +- SPEED_MODIFIER_ATTACKING_UUID, "Attacking speed boost", 0.15F, AttributeModifier.Operation.ADDITION +- ); ++ private static final AttributeModifier SPEED_MODIFIER_ATTACKING = new AttributeModifier(EnderMan.SPEED_MODIFIER_ATTACKING_UUID, "Attacking speed boost", 0.15000000596046448D, AttributeModifier.Operation.ADDITION); + private static final int DELAY_BETWEEN_CREEPY_STARE_SOUND = 400; + private static final int MIN_DEAGGRESSION_TIME = 600; +- private static final EntityDataAccessor> DATA_CARRY_STATE = SynchedEntityData.defineId( +- EnderMan.class, EntityDataSerializers.OPTIONAL_BLOCK_STATE +- ); ++ private static final EntityDataAccessor> DATA_CARRY_STATE = SynchedEntityData.defineId(EnderMan.class, EntityDataSerializers.OPTIONAL_BLOCK_STATE); + private static final EntityDataAccessor DATA_CREEPY = SynchedEntityData.defineId(EnderMan.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_STARED_AT = SynchedEntityData.defineId(EnderMan.class, EntityDataSerializers.BOOLEAN); + private int lastStareSound = Integer.MIN_VALUE; +@@ -99,55 +102,64 @@ + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(1, new EnderMan.EndermanFreezeWhenLookedAt(this)); +- this.goalSelector.addGoal(2, new MeleeAttackGoal(this, 1.0, false)); +- this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0, 0.0F)); ++ this.goalSelector.addGoal(2, new MeleeAttackGoal(this, 1.0D, false)); ++ this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D, 0.0F)); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); + this.goalSelector.addGoal(10, new EnderMan.EndermanLeaveBlockGoal(this)); + this.goalSelector.addGoal(11, new EnderMan.EndermanTakeBlockGoal(this)); + this.targetSelector.addGoal(1, new EnderMan.EndermanLookForPlayerGoal(this, this::isAngryAt)); +- this.targetSelector.addGoal(2, new HurtByTargetGoal(this)); ++ this.targetSelector.addGoal(2, new HurtByTargetGoal(this, new Class[0])); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Endermite.class, true, false)); + this.targetSelector.addGoal(4, new ResetUniversalAngerTargetGoal<>(this, false)); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes() +- .add(Attributes.MAX_HEALTH, 40.0) +- .add(Attributes.MOVEMENT_SPEED, 0.3F) +- .add(Attributes.ATTACK_DAMAGE, 7.0) +- .add(Attributes.FOLLOW_RANGE, 64.0); ++ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 40.0D).add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D).add(Attributes.ATTACK_DAMAGE, 7.0D).add(Attributes.FOLLOW_RANGE, 64.0D); + } + + @Override + public void setTarget(@Nullable LivingEntity livingEntity) { +- super.setTarget(livingEntity); +- AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED); +- if (livingEntity == null) { ++ // CraftBukkit start - fire event ++ setTarget(livingEntity, EntityTargetEvent.TargetReason.UNKNOWN, true); ++ } ++ ++ @Override ++ public boolean setTarget(LivingEntity entityliving, EntityTargetEvent.TargetReason reason, boolean fireEvent) { ++ if (!super.setTarget(entityliving, reason, fireEvent)) { ++ return false; ++ } ++ entityliving = getTarget(); ++ // CraftBukkit end ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ ++ if (entityliving == null) { + this.targetChangeTime = 0; +- this.entityData.set(DATA_CREEPY, false); +- this.entityData.set(DATA_STARED_AT, false); +- attribute.removeModifier(SPEED_MODIFIER_ATTACKING.getId()); ++ this.entityData.set(EnderMan.DATA_CREEPY, false); ++ this.entityData.set(EnderMan.DATA_STARED_AT, false); ++ attributemodifiable.removeModifier(EnderMan.SPEED_MODIFIER_ATTACKING.getId()); + } else { + this.targetChangeTime = this.tickCount; +- this.entityData.set(DATA_CREEPY, true); +- if (!attribute.hasModifier(SPEED_MODIFIER_ATTACKING)) { +- attribute.addTransientModifier(SPEED_MODIFIER_ATTACKING); ++ this.entityData.set(EnderMan.DATA_CREEPY, true); ++ if (!attributemodifiable.hasModifier(EnderMan.SPEED_MODIFIER_ATTACKING)) { ++ attributemodifiable.addTransientModifier(EnderMan.SPEED_MODIFIER_ATTACKING); + } + } ++ return true; ++ + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_CARRY_STATE, Optional.empty()); +- this.entityData.define(DATA_CREEPY, false); +- this.entityData.define(DATA_STARED_AT, false); ++ this.entityData.define(EnderMan.DATA_CARRY_STATE, Optional.empty()); ++ this.entityData.define(EnderMan.DATA_CREEPY, false); ++ this.entityData.define(EnderMan.DATA_STARED_AT, false); + } + + @Override + public void startPersistentAngerTimer() { +- this.setRemainingPersistentAngerTime(PERSISTENT_ANGER_TIME.sample(this.random)); ++ this.setRemainingPersistentAngerTime(EnderMan.PERSISTENT_ANGER_TIME.sample(this.random)); + } + + @Override +@@ -178,11 +190,12 @@ + this.level().playLocalSound(this.getX(), this.getEyeY(), this.getZ(), SoundEvents.ENDERMAN_STARE, this.getSoundSource(), 2.5F, 1.0F, false); + } + } ++ + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { +- if (DATA_CREEPY.equals(key) && this.hasBeenStaredAt() && this.level().isClientSide) { ++ if (EnderMan.DATA_CREEPY.equals(key) && this.hasBeenStaredAt() && this.level().isClientSide) { + this.playStareSound(); + } + +@@ -192,9 +205,10 @@ + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- BlockState carriedBlock = this.getCarriedBlock(); +- if (carriedBlock != null) { +- compound.put("carriedBlockState", NbtUtils.writeBlockState(carriedBlock)); ++ IBlockData iblockdata = this.getCarriedBlock(); ++ ++ if (iblockdata != null) { ++ compound.put("carriedBlockState", NbtUtils.writeBlockState(iblockdata)); + } + + this.addPersistentAngerSaveData(compound); +@@ -203,62 +217,57 @@ + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); +- BlockState blockState = null; ++ IBlockData iblockdata = null; ++ + if (compound.contains("carriedBlockState", 10)) { +- blockState = NbtUtils.readBlockState(this.level().holderLookup(Registries.BLOCK), compound.getCompound("carriedBlockState")); +- if (blockState.isAir()) { +- blockState = null; ++ iblockdata = NbtUtils.readBlockState(this.level().holderLookup(Registries.BLOCK), compound.getCompound("carriedBlockState")); ++ if (iblockdata.isAir()) { ++ iblockdata = null; + } + } + +- this.setCarriedBlock(blockState); ++ this.setCarriedBlock(iblockdata); + this.readPersistentAngerSaveData(this.level(), compound); + } + + boolean isLookingAtMe(Player player) { +- ItemStack itemStack = player.getInventory().armor.get(3); +- if (itemStack.is(Blocks.CARVED_PUMPKIN.asItem())) { ++ ItemStack itemstack = (ItemStack) player.getInventory().armor.get(3); ++ ++ if (itemstack.is(Blocks.CARVED_PUMPKIN.asItem())) { + return false; + } else { +- Vec3 vec3 = player.getViewVector(1.0F).normalize(); +- Vec3 vec31 = new Vec3(this.getX() - player.getX(), this.getEyeY() - player.getEyeY(), this.getZ() - player.getZ()); +- double len = vec31.length(); +- vec31 = vec31.normalize(); +- double d = vec3.dot(vec31); +- return d > 1.0 - 0.025 / len && player.hasLineOfSight(this); ++ Vec3 vec3d = player.getViewVector(1.0F).normalize(); ++ Vec3 vec3d1 = new Vec3(this.getX() - player.getX(), this.getEyeY() - player.getEyeY(), this.getZ() - player.getZ()); ++ double d0 = vec3d1.length(); ++ ++ vec3d1 = vec3d1.normalize(); ++ double d1 = vec3d.dot(vec3d1); ++ ++ return d1 > 1.0D - 0.025D / d0 ? player.hasLineOfSight(this) : false; + } + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 2.55F; + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height - 0.09375F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.09375F * f, 0.0F); + } + + @Override + public void aiStep() { + if (this.level().isClientSide) { +- for (int i = 0; i < 2; i++) { +- this.level() +- .addParticle( +- ParticleTypes.PORTAL, +- this.getRandomX(0.5), +- this.getRandomY() - 0.25, +- this.getRandomZ(0.5), +- (this.random.nextDouble() - 0.5) * 2.0, +- -this.random.nextDouble(), +- (this.random.nextDouble() - 0.5) * 2.0 +- ); ++ for (int i = 0; i < 2; ++i) { ++ this.level().addParticle(ParticleTypes.PORTAL, this.getRandomX(0.5D), this.getRandomY() - 0.25D, this.getRandomZ(0.5D), (this.random.nextDouble() - 0.5D) * 2.0D, -this.random.nextDouble(), (this.random.nextDouble() - 0.5D) * 2.0D); + } + } + + this.jumping = false; + if (!this.level().isClientSide) { +- this.updatePersistentAnger((ServerLevel)this.level(), true); ++ this.updatePersistentAnger((ServerLevel) this.level(), true); + } + + super.aiStep(); +@@ -272,11 +281,10 @@ + @Override + protected void customServerAiStep() { + if (this.level().isDay() && this.tickCount >= this.targetChangeTime + 600) { +- float lightLevelDependentMagicValue = this.getLightLevelDependentMagicValue(); +- if (lightLevelDependentMagicValue > 0.5F +- && this.level().canSeeSky(this.blockPosition()) +- && this.random.nextFloat() * 30.0F < (lightLevelDependentMagicValue - 0.4F) * 2.0F) { +- this.setTarget(null); ++ float f = this.getLightLevelDependentMagicValue(); ++ ++ if (f > 0.5F && this.level().canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F) { ++ this.setTarget((LivingEntity) null); + this.teleport(); + } + } +@@ -284,49 +292,54 @@ + super.customServerAiStep(); + } + +- protected boolean teleport() { ++ public boolean teleport() { + if (!this.level().isClientSide() && this.isAlive()) { +- double d = this.getX() + (this.random.nextDouble() - 0.5) * 64.0; +- double d1 = this.getY() + (double)(this.random.nextInt(64) - 32); +- double d2 = this.getZ() + (this.random.nextDouble() - 0.5) * 64.0; +- return this.teleport(d, d1, d2); ++ double d0 = this.getX() + (this.random.nextDouble() - 0.5D) * 64.0D; ++ double d1 = this.getY() + (double) (this.random.nextInt(64) - 32); ++ double d2 = this.getZ() + (this.random.nextDouble() - 0.5D) * 64.0D; ++ ++ return this.teleport(d0, d1, d2); + } else { + return false; + } + } + +- boolean teleportTowards(Entity target) { +- Vec3 vec3 = new Vec3(this.getX() - target.getX(), this.getY(0.5) - target.getEyeY(), this.getZ() - target.getZ()); +- vec3 = vec3.normalize(); +- double d = 16.0; +- double d1 = this.getX() + (this.random.nextDouble() - 0.5) * 8.0 - vec3.x * 16.0; +- double d2 = this.getY() + (double)(this.random.nextInt(16) - 8) - vec3.y * 16.0; +- double d3 = this.getZ() + (this.random.nextDouble() - 0.5) * 8.0 - vec3.z * 16.0; ++ public boolean teleportTowards(Entity target) { ++ Vec3 vec3d = new Vec3(this.getX() - target.getX(), this.getY(0.5D) - target.getEyeY(), this.getZ() - target.getZ()); ++ ++ vec3d = vec3d.normalize(); ++ double d0 = 16.0D; ++ double d1 = this.getX() + (this.random.nextDouble() - 0.5D) * 8.0D - vec3d.x * 16.0D; ++ double d2 = this.getY() + (double) (this.random.nextInt(16) - 8) - vec3d.y * 16.0D; ++ double d3 = this.getZ() + (this.random.nextDouble() - 0.5D) * 8.0D - vec3d.z * 16.0D; ++ + return this.teleport(d1, d2, d3); + } + +- private boolean teleport(double x, double y, double z) { +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(x, y, z); ++ private boolean teleport(double x, double d1, double y) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(x, d1, y); + +- while (mutableBlockPos.getY() > this.level().getMinBuildHeight() && !this.level().getBlockState(mutableBlockPos).blocksMotion()) { +- mutableBlockPos.move(Direction.DOWN); ++ while (blockposition_mutableblockposition.getY() > this.level().getMinBuildHeight() && !this.level().getBlockState(blockposition_mutableblockposition).blocksMotion()) { ++ blockposition_mutableblockposition.move(Direction.DOWN); + } + +- BlockState blockState = this.level().getBlockState(mutableBlockPos); +- boolean flag = blockState.blocksMotion(); +- boolean isWater = blockState.getFluidState().is(FluidTags.WATER); +- if (flag && !isWater) { +- Vec3 vec3 = this.position(); +- boolean flag1 = this.randomTeleport(x, y, z, true); +- if (flag1) { +- this.level().gameEvent(GameEvent.TELEPORT, vec3, GameEvent.Context.of(this)); ++ IBlockData iblockdata = this.level().getBlockState(blockposition_mutableblockposition); ++ boolean flag = iblockdata.blocksMotion(); ++ boolean flag1 = iblockdata.getFluidState().is(FluidTags.WATER); ++ ++ if (flag && !flag1) { ++ Vec3 vec3d = this.position(); ++ boolean flag2 = this.randomTeleport(x, d1, y, true); ++ ++ if (flag2) { ++ this.level().gameEvent(GameEvent.TELEPORT, vec3d, GameEvent.Context.of((Entity) this)); + if (!this.isSilent()) { +- this.level().playSound(null, this.xo, this.yo, this.zo, SoundEvents.ENDERMAN_TELEPORT, this.getSoundSource(), 1.0F, 1.0F); ++ this.level().playSound((Player) null, this.xo, this.yo, this.zo, SoundEvents.ENDERMAN_TELEPORT, this.getSoundSource(), 1.0F, 1.0F); + this.playSound(SoundEvents.ENDERMAN_TELEPORT, 1.0F, 1.0F); + } + } + +- return flag1; ++ return flag2; + } else { + return false; + } +@@ -350,28 +363,32 @@ + @Override + protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { + super.dropCustomDeathLoot(source, looting, recentlyHit); +- BlockState carriedBlock = this.getCarriedBlock(); +- if (carriedBlock != null) { +- ItemStack itemStack = new ItemStack(Items.DIAMOND_AXE); +- itemStack.enchant(Enchantments.SILK_TOUCH, 1); +- LootParams.Builder builder = new LootParams.Builder((ServerLevel)this.level()) +- .withParameter(LootContextParams.ORIGIN, this.position()) +- .withParameter(LootContextParams.TOOL, itemStack) +- .withOptionalParameter(LootContextParams.THIS_ENTITY, this); ++ IBlockData iblockdata = this.getCarriedBlock(); + +- for (ItemStack itemStack1 : carriedBlock.getDrops(builder)) { +- this.spawnAtLocation(itemStack1); ++ if (iblockdata != null) { ++ ItemStack itemstack = new ItemStack(Items.DIAMOND_AXE); ++ ++ itemstack.enchant(Enchantments.SILK_TOUCH, 1); ++ LootParams.Builder lootparams_a = (new LootParams.Builder((ServerLevel) this.level())).withParameter(LootContextParams.ORIGIN, this.position()).withParameter(LootContextParams.TOOL, itemstack).withOptionalParameter(LootContextParams.THIS_ENTITY, this); ++ List list = iblockdata.getDrops(lootparams_a); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ ItemStack itemstack1 = (ItemStack) iterator.next(); ++ ++ this.spawnAtLocation(itemstack1); + } + } ++ + } + +- public void setCarriedBlock(@Nullable BlockState state) { +- this.entityData.set(DATA_CARRY_STATE, Optional.ofNullable(state)); ++ public void setCarriedBlock(@Nullable IBlockData state) { ++ this.entityData.set(EnderMan.DATA_CARRY_STATE, Optional.ofNullable(state)); + } + + @Nullable +- public BlockState getCarriedBlock() { +- return this.entityData.get(DATA_CARRY_STATE).orElse(null); ++ public IBlockData getCarriedBlock() { ++ return (IBlockData) ((Optional) this.entityData.get(EnderMan.DATA_CARRY_STATE)).orElse((Object) null); + } + + @Override +@@ -380,17 +397,19 @@ + return false; + } else { + boolean flag = source.getDirectEntity() instanceof ThrownPotion; ++ boolean flag1; ++ + if (!source.is(DamageTypeTags.IS_PROJECTILE) && !flag) { +- boolean flag1 = super.hurt(source, amount); ++ flag1 = super.hurt(source, amount); + if (!this.level().isClientSide() && !(source.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0) { + this.teleport(); + } + + return flag1; + } else { +- boolean flag1 = flag && this.hurtWithCleanWater(source, (ThrownPotion)source.getDirectEntity(), amount); ++ flag1 = flag && this.hurtWithCleanWater(source, (ThrownPotion) source.getDirectEntity(), amount); + +- for (int i = 0; i < 64; i++) { ++ for (int i = 0; i < 64; ++i) { + if (this.teleport()) { + return true; + } +@@ -402,23 +421,24 @@ + } + + private boolean hurtWithCleanWater(DamageSource source, ThrownPotion potion, float amount) { +- ItemStack item = potion.getItem(); +- Potion potion1 = PotionUtils.getPotion(item); +- List mobEffects = PotionUtils.getMobEffects(item); +- boolean flag = potion1 == Potions.WATER && mobEffects.isEmpty(); +- return flag && super.hurt(source, amount); ++ ItemStack itemstack = potion.getItem(); ++ Potion potionregistry = PotionUtils.getPotion(itemstack); ++ List list = PotionUtils.getMobEffects(itemstack); ++ boolean flag = potionregistry == Potions.WATER && list.isEmpty(); ++ ++ return flag ? super.hurt(source, amount) : false; + } + + public boolean isCreepy() { +- return this.entityData.get(DATA_CREEPY); ++ return (Boolean) this.entityData.get(EnderMan.DATA_CREEPY); + } + + public boolean hasBeenStaredAt() { +- return this.entityData.get(DATA_STARED_AT); ++ return (Boolean) this.entityData.get(EnderMan.DATA_STARED_AT); + } + + public void setBeingStaredAt() { +- this.entityData.set(DATA_STARED_AT, true); ++ this.entityData.set(EnderMan.DATA_STARED_AT, true); + } + + @Override +@@ -426,14 +446,15 @@ + return super.requiresCustomPersistence() || this.getCarriedBlock() != null; + } + +- static class EndermanFreezeWhenLookedAt extends Goal { ++ private static class EndermanFreezeWhenLookedAt extends Goal { ++ + private final EnderMan enderman; + @Nullable + private LivingEntity target; + + public EndermanFreezeWhenLookedAt(EnderMan enderman) { + this.enderman = enderman; +- this.setFlags(EnumSet.of(Goal.Flag.JUMP, Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.JUMP, Goal.Type.MOVE)); + } + + @Override +@@ -442,8 +463,9 @@ + if (!(this.target instanceof Player)) { + return false; + } else { +- double d = this.target.distanceToSqr(this.enderman); +- return !(d > 256.0) && this.enderman.isLookingAtMe((Player)this.target); ++ double d0 = this.target.distanceToSqr((Entity) this.enderman); ++ ++ return d0 > 256.0D ? false : this.enderman.isLookingAtMe((Player) this.target); + } + } + +@@ -458,7 +480,8 @@ + } + } + +- static class EndermanLeaveBlockGoal extends Goal { ++ private static class EndermanLeaveBlockGoal extends Goal { ++ + private final EnderMan enderman; + + public EndermanLeaveBlockGoal(EnderMan enderman) { +@@ -467,52 +490,81 @@ + + @Override + public boolean canUse() { +- return this.enderman.getCarriedBlock() != null +- && this.enderman.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) +- && this.enderman.getRandom().nextInt(reducedTickDelay(2000)) == 0; ++ return this.enderman.getCarriedBlock() == null ? false : (!this.enderman.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? false : this.enderman.getRandom().nextInt(reducedTickDelay(2000)) == 0); + } + + @Override + public void tick() { +- RandomSource random = this.enderman.getRandom(); +- Level level = this.enderman.level(); +- int floor = Mth.floor(this.enderman.getX() - 1.0 + random.nextDouble() * 2.0); +- int floor1 = Mth.floor(this.enderman.getY() + random.nextDouble() * 2.0); +- int floor2 = Mth.floor(this.enderman.getZ() - 1.0 + random.nextDouble() * 2.0); +- BlockPos blockPos = new BlockPos(floor, floor1, floor2); +- BlockState blockState = level.getBlockState(blockPos); +- BlockPos blockPos1 = blockPos.below(); +- BlockState blockState1 = level.getBlockState(blockPos1); +- BlockState carriedBlock = this.enderman.getCarriedBlock(); +- if (carriedBlock != null) { +- BlockState var11 = Block.updateFromNeighbourShapes(carriedBlock, this.enderman.level(), blockPos); +- if (this.canPlaceBlock(level, blockPos, var11, blockState, blockState1, blockPos1)) { +- level.setBlock(blockPos, var11, 3); +- level.gameEvent(GameEvent.BLOCK_PLACE, blockPos, GameEvent.Context.of(this.enderman, var11)); +- this.enderman.setCarriedBlock(null); ++ RandomSource randomsource = this.enderman.getRandom(); ++ Level world = this.enderman.level(); ++ int i = Mth.floor(this.enderman.getX() - 1.0D + randomsource.nextDouble() * 2.0D); ++ int j = Mth.floor(this.enderman.getY() + randomsource.nextDouble() * 2.0D); ++ int k = Mth.floor(this.enderman.getZ() - 1.0D + randomsource.nextDouble() * 2.0D); ++ BlockPos blockposition = new BlockPos(i, j, k); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ BlockPos blockposition1 = blockposition.below(); ++ IBlockData iblockdata1 = world.getBlockState(blockposition1); ++ IBlockData iblockdata2 = this.enderman.getCarriedBlock(); ++ ++ if (iblockdata2 != null) { ++ iblockdata2 = Block.updateFromNeighbourShapes(iblockdata2, this.enderman.level(), blockposition); ++ if (this.canPlaceBlock(world, blockposition, iblockdata2, iblockdata, iblockdata1, blockposition1)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockposition, iblockdata2)) { // CraftBukkit - Place event ++ world.setBlock(blockposition, iblockdata2, 3); ++ world.gameEvent(GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(this.enderman, iblockdata2)); ++ this.enderman.setCarriedBlock((IBlockData) null); ++ } // CraftBukkit + } ++ + } + } + +- private boolean canPlaceBlock( +- Level level, +- BlockPos destinationPos, +- BlockState carriedState, +- BlockState destinationState, +- BlockState belowDestinationState, +- BlockPos belowDestinationPos +- ) { +- return destinationState.isAir() +- && !belowDestinationState.isAir() +- && !belowDestinationState.is(Blocks.BEDROCK) +- && belowDestinationState.isCollisionShapeFullBlock(level, belowDestinationPos) +- && carriedState.canSurvive(level, destinationPos) +- && level.getEntities(this.enderman, AABB.unitCubeFromLowerCorner(Vec3.atLowerCornerOf(destinationPos))).isEmpty(); ++ private boolean canPlaceBlock(Level level, BlockPos destinationPos, IBlockData carriedState, IBlockData destinationState, IBlockData belowDestinationState, BlockPos belowDestinationPos) { ++ return destinationState.isAir() && !belowDestinationState.isAir() && !belowDestinationState.is(Blocks.BEDROCK) && belowDestinationState.isCollisionShapeFullBlock(level, belowDestinationPos) && carriedState.canSurvive(level, destinationPos) && level.getEntities(this.enderman, AABB.unitCubeFromLowerCorner(Vec3.atLowerCornerOf(destinationPos))).isEmpty(); + } + } + +- static class EndermanLookForPlayerGoal extends NearestAttackableTargetGoal { ++ private static class EndermanTakeBlockGoal extends Goal { ++ + private final EnderMan enderman; ++ ++ public EndermanTakeBlockGoal(EnderMan enderman) { ++ this.enderman = enderman; ++ } ++ ++ @Override ++ public boolean canUse() { ++ return this.enderman.getCarriedBlock() != null ? false : (!this.enderman.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? false : this.enderman.getRandom().nextInt(reducedTickDelay(20)) == 0); ++ } ++ ++ @Override ++ public void tick() { ++ RandomSource randomsource = this.enderman.getRandom(); ++ Level world = this.enderman.level(); ++ int i = Mth.floor(this.enderman.getX() - 2.0D + randomsource.nextDouble() * 4.0D); ++ int j = Mth.floor(this.enderman.getY() + randomsource.nextDouble() * 3.0D); ++ int k = Mth.floor(this.enderman.getZ() - 2.0D + randomsource.nextDouble() * 4.0D); ++ BlockPos blockposition = new BlockPos(i, j, k); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ Vec3 vec3d = new Vec3((double) this.enderman.getBlockX() + 0.5D, (double) j + 0.5D, (double) this.enderman.getBlockZ() + 0.5D); ++ Vec3 vec3d1 = new Vec3((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D); ++ BlockHitResult movingobjectpositionblock = world.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.enderman)); ++ boolean flag = movingobjectpositionblock.getBlockPos().equals(blockposition); ++ ++ if (iblockdata.is(BlockTags.ENDERMAN_HOLDABLE) && flag) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockposition, Blocks.AIR.defaultBlockState())) { // CraftBukkit - Place event ++ world.removeBlock(blockposition, false); ++ world.gameEvent(GameEvent.BLOCK_DESTROY, blockposition, GameEvent.Context.of(this.enderman, iblockdata)); ++ this.enderman.setCarriedBlock(iblockdata.getBlock().defaultBlockState()); ++ } // CraftBukkit ++ } ++ ++ } ++ } ++ ++ private static class EndermanLookForPlayerGoal extends NearestAttackableTargetGoal { ++ ++ private final EnderMan enderman; + @Nullable + private Player pendingTarget; + private int aggroTime; +@@ -524,7 +576,9 @@ + public EndermanLookForPlayerGoal(EnderMan enderman, @Nullable Predicate selectionPredicate) { + super(enderman, Player.class, 10, false, false, selectionPredicate); + this.enderman = enderman; +- this.isAngerInducing = entity -> (enderman.isLookingAtMe((Player)entity) || enderman.isAngryAt(entity)) && !enderman.hasIndirectPassenger(entity); ++ this.isAngerInducing = (entityliving) -> { ++ return (enderman.isLookingAtMe((Player) entityliving) || enderman.isAngryAt(entityliving)) && !enderman.hasIndirectPassenger(entityliving); ++ }; + this.startAggroTargetConditions = TargetingConditions.forCombat().range(this.getFollowDistance()).selector(this.isAngerInducing); + } + +@@ -574,7 +628,7 @@ + @Override + public void tick() { + if (this.enderman.getTarget() == null) { +- super.setTarget(null); ++ super.setTarget((LivingEntity) null); + } + + if (this.pendingTarget != null) { +@@ -585,56 +639,20 @@ + } + } else { + if (this.target != null && !this.enderman.isPassenger()) { +- if (this.enderman.isLookingAtMe((Player)this.target)) { +- if (this.target.distanceToSqr(this.enderman) < 16.0) { ++ if (this.enderman.isLookingAtMe((Player) this.target)) { ++ if (this.target.distanceToSqr((Entity) this.enderman) < 16.0D) { + this.enderman.teleport(); + } + + this.teleportTime = 0; +- } else if (this.target.distanceToSqr(this.enderman) > 256.0 +- && this.teleportTime++ >= this.adjustedTickDelay(30) +- && this.enderman.teleportTowards(this.target)) { ++ } else if (this.target.distanceToSqr((Entity) this.enderman) > 256.0D && this.teleportTime++ >= this.adjustedTickDelay(30) && this.enderman.teleportTowards(this.target)) { + this.teleportTime = 0; + } + } + + super.tick(); + } +- } +- } + +- static class EndermanTakeBlockGoal extends Goal { +- private final EnderMan enderman; +- +- public EndermanTakeBlockGoal(EnderMan enderman) { +- this.enderman = enderman; + } +- +- @Override +- public boolean canUse() { +- return this.enderman.getCarriedBlock() == null +- && this.enderman.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) +- && this.enderman.getRandom().nextInt(reducedTickDelay(20)) == 0; +- } +- +- @Override +- public void tick() { +- RandomSource random = this.enderman.getRandom(); +- Level level = this.enderman.level(); +- int floor = Mth.floor(this.enderman.getX() - 2.0 + random.nextDouble() * 4.0); +- int floor1 = Mth.floor(this.enderman.getY() + random.nextDouble() * 3.0); +- int floor2 = Mth.floor(this.enderman.getZ() - 2.0 + random.nextDouble() * 4.0); +- BlockPos blockPos = new BlockPos(floor, floor1, floor2); +- BlockState blockState = level.getBlockState(blockPos); +- Vec3 vec3 = new Vec3((double)this.enderman.getBlockX() + 0.5, (double)floor1 + 0.5, (double)this.enderman.getBlockZ() + 0.5); +- Vec3 vec31 = new Vec3((double)floor + 0.5, (double)floor1 + 0.5, (double)floor2 + 0.5); +- BlockHitResult blockHitResult = level.clip(new ClipContext(vec3, vec31, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.enderman)); +- boolean flag = blockHitResult.getBlockPos().equals(blockPos); +- if (blockState.is(BlockTags.ENDERMAN_HOLDABLE) && flag) { +- level.removeBlock(blockPos, false); +- level.gameEvent(GameEvent.BLOCK_DESTROY, blockPos, GameEvent.Context.of(this.enderman, blockState)); +- this.enderman.setCarriedBlock(blockState.getBlock().defaultBlockState()); +- } +- } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Evoker.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Evoker.java.patch new file mode 100644 index 0000000000..fd571c6fc7 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Evoker.java.patch @@ -0,0 +1,410 @@ +--- a/net/minecraft/world/entity/monster/Evoker.java ++++ b/net/minecraft/world/entity/monster/Evoker.java +@@ -12,10 +12,11 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.AvoidEntityGoal; +@@ -34,13 +35,14 @@ + import net.minecraft.world.item.DyeColor; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.scores.PlayerTeam; + + public class Evoker extends SpellcasterIllager { ++ + @Nullable + private Sheep wololoTarget; + +@@ -54,21 +56,21 @@ + super.registerGoals(); + this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(1, new Evoker.EvokerCastingSpellGoal()); +- this.goalSelector.addGoal(2, new AvoidEntityGoal<>(this, Player.class, 8.0F, 0.6, 1.0)); ++ this.goalSelector.addGoal(2, new AvoidEntityGoal<>(this, Player.class, 8.0F, 0.6D, 1.0D)); + this.goalSelector.addGoal(4, new Evoker.EvokerSummonSpellGoal()); + this.goalSelector.addGoal(5, new Evoker.EvokerAttackSpellGoal()); + this.goalSelector.addGoal(6, new Evoker.EvokerWololoSpellGoal()); +- this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6)); ++ this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6D)); + this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Raider.class).setAlertOthers()); +- this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true).setUnseenMemoryTicks(300)); +- this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false).setUnseenMemoryTicks(300)); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers()); ++ this.targetSelector.addGoal(2, (new NearestAttackableTargetGoal<>(this, Player.class, true)).setUnseenMemoryTicks(300)); ++ this.targetSelector.addGoal(3, (new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)).setUnseenMemoryTicks(300)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, false)); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.5).add(Attributes.FOLLOW_RANGE, 12.0).add(Attributes.MAX_HEALTH, 24.0); ++ return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.5D).add(Attributes.FOLLOW_RANGE, 12.0D).add(Attributes.MAX_HEALTH, 24.0D); + } + + @Override +@@ -98,20 +100,7 @@ + + @Override + public boolean isAlliedTo(Entity entity) { +- if (entity == null) { +- return false; +- } else if (entity == this) { +- return true; +- } else if (super.isAlliedTo(entity)) { +- return true; +- } else { +- return entity instanceof Vex +- ? this.isAlliedTo(((Vex)entity).getOwner()) +- : entity instanceof LivingEntity +- && ((LivingEntity)entity).getMobType() == MobType.ILLAGER +- && this.getTeam() == null +- && entity.getTeam() == null; +- } ++ return entity == null ? false : (entity == this ? true : (super.isAlliedTo(entity) ? true : (entity instanceof Vex ? this.isAlliedTo((Entity) ((Vex) entity).getOwner()) : (entity instanceof LivingEntity && ((LivingEntity) entity).getMobType() == EnumMonsterType.ILLAGER ? this.getTeam() == null && entity.getTeam() == null : false)))); + } + + @Override +@@ -144,162 +133,192 @@ + } + + @Override +- public void applyRaidBuffs(int wave, boolean unusedFalse) { ++ public void applyRaidBuffs(int wave, boolean unusedFalse) {} ++ ++ private class EvokerCastingSpellGoal extends SpellcasterIllager.SpellcasterCastingSpellGoal { ++ ++ EvokerCastingSpellGoal() { ++ super(); ++ } ++ ++ @Override ++ public void tick() { ++ if (Evoker.this.getTarget() != null) { ++ Evoker.this.getLookControl().setLookAt(Evoker.this.getTarget(), (float) Evoker.this.getMaxHeadYRot(), (float) Evoker.this.getMaxHeadXRot()); ++ } else if (Evoker.this.getWololoTarget() != null) { ++ Evoker.this.getLookControl().setLookAt(Evoker.this.getWololoTarget(), (float) Evoker.this.getMaxHeadYRot(), (float) Evoker.this.getMaxHeadXRot()); ++ } ++ ++ } + } + +- class EvokerAttackSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { ++ private class EvokerSummonSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { ++ ++ private final TargetingConditions vexCountTargeting = TargetingConditions.forNonCombat().range(16.0D).ignoreLineOfSight().ignoreInvisibilityTesting(); ++ ++ EvokerSummonSpellGoal() { ++ super(); ++ } ++ + @Override ++ public boolean canUse() { ++ if (!super.canUse()) { ++ return false; ++ } else { ++ int i = Evoker.this.level().getNearbyEntities(Vex.class, this.vexCountTargeting, Evoker.this, Evoker.this.getBoundingBox().inflate(16.0D)).size(); ++ ++ return Evoker.this.random.nextInt(8) + 1 > i; ++ } ++ } ++ ++ @Override + protected int getCastingTime() { +- return 40; ++ return 100; + } + + @Override + protected int getCastingInterval() { +- return 100; ++ return 340; + } + + @Override + protected void performSpellCasting() { +- LivingEntity target = Evoker.this.getTarget(); +- double min = Math.min(target.getY(), Evoker.this.getY()); +- double d = Math.max(target.getY(), Evoker.this.getY()) + 1.0; +- float f = (float)Mth.atan2(target.getZ() - Evoker.this.getZ(), target.getX() - Evoker.this.getX()); +- if (Evoker.this.distanceToSqr(target) < 9.0) { +- for (int i = 0; i < 5; i++) { +- float f1 = f + (float)i * (float) Math.PI * 0.4F; +- this.createSpellEntity(Evoker.this.getX() + (double)Mth.cos(f1) * 1.5, Evoker.this.getZ() + (double)Mth.sin(f1) * 1.5, min, d, f1, 0); +- } ++ ServerLevel worldserver = (ServerLevel) Evoker.this.level(); ++ PlayerTeam scoreboardteam = Evoker.this.getTeam(); + +- for (int i = 0; i < 8; i++) { +- float f1 = f + (float)i * (float) Math.PI * 2.0F / 8.0F + (float) (Math.PI * 2.0 / 5.0); +- this.createSpellEntity(Evoker.this.getX() + (double)Mth.cos(f1) * 2.5, Evoker.this.getZ() + (double)Mth.sin(f1) * 2.5, min, d, f1, 3); +- } +- } else { +- for (int i = 0; i < 16; i++) { +- double d1 = 1.25 * (double)(i + 1); +- int i1 = 1 * i; +- this.createSpellEntity(Evoker.this.getX() + (double)Mth.cos(f) * d1, Evoker.this.getZ() + (double)Mth.sin(f) * d1, min, d, f, i1); +- } +- } +- } ++ for (int i = 0; i < 3; ++i) { ++ BlockPos blockposition = Evoker.this.blockPosition().offset(-2 + Evoker.this.random.nextInt(5), 1, -2 + Evoker.this.random.nextInt(5)); ++ Vex entityvex = (Vex) EntityType.VEX.create(Evoker.this.level()); + +- private void createSpellEntity(double x, double z, double minY, double maxY, float yRot, int warmupDelay) { +- BlockPos blockPos = BlockPos.containing(x, maxY, z); +- boolean flag = false; +- double d = 0.0; +- +- do { +- BlockPos blockPos1 = blockPos.below(); +- BlockState blockState = Evoker.this.level().getBlockState(blockPos1); +- if (blockState.isFaceSturdy(Evoker.this.level(), blockPos1, Direction.UP)) { +- if (!Evoker.this.level().isEmptyBlock(blockPos)) { +- BlockState blockState1 = Evoker.this.level().getBlockState(blockPos); +- VoxelShape collisionShape = blockState1.getCollisionShape(Evoker.this.level(), blockPos); +- if (!collisionShape.isEmpty()) { +- d = collisionShape.max(Direction.Axis.Y); +- } ++ if (entityvex != null) { ++ entityvex.moveTo(blockposition, 0.0F, 0.0F); ++ entityvex.finalizeSpawn(worldserver, Evoker.this.level().getCurrentDifficultyAt(blockposition), EnumMobSpawn.MOB_SUMMONED, (GroupDataEntity) null, (CompoundTag) null); ++ entityvex.setOwner(Evoker.this); ++ entityvex.setBoundOrigin(blockposition); ++ entityvex.setLimitedLife(20 * (30 + Evoker.this.random.nextInt(90))); ++ if (scoreboardteam != null) { ++ worldserver.getScoreboard().addPlayerToTeam(entityvex.getScoreboardName(), scoreboardteam); + } + +- flag = true; +- break; ++ worldserver.addFreshEntityWithPassengers(entityvex, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPELL); // CraftBukkit - Add SpawnReason ++ worldserver.gameEvent(GameEvent.ENTITY_PLACE, blockposition, GameEvent.Context.of((Entity) Evoker.this)); + } +- +- blockPos = blockPos.below(); +- } while (blockPos.getY() >= Mth.floor(minY) - 1); +- +- if (flag) { +- Evoker.this.level().addFreshEntity(new EvokerFangs(Evoker.this.level(), x, (double)blockPos.getY() + d, z, yRot, warmupDelay, Evoker.this)); +- Evoker.this.level().gameEvent(GameEvent.ENTITY_PLACE, new Vec3(x, (double)blockPos.getY() + d, z), GameEvent.Context.of(Evoker.this)); + } ++ + } + + @Override + protected SoundEvent getSpellPrepareSound() { +- return SoundEvents.EVOKER_PREPARE_ATTACK; ++ return SoundEvents.EVOKER_PREPARE_SUMMON; + } + + @Override + protected SpellcasterIllager.IllagerSpell getSpell() { +- return SpellcasterIllager.IllagerSpell.FANGS; ++ return SpellcasterIllager.IllagerSpell.SUMMON_VEX; + } + } + +- class EvokerCastingSpellGoal extends SpellcasterIllager.SpellcasterCastingSpellGoal { +- @Override +- public void tick() { +- if (Evoker.this.getTarget() != null) { +- Evoker.this.getLookControl().setLookAt(Evoker.this.getTarget(), (float)Evoker.this.getMaxHeadYRot(), (float)Evoker.this.getMaxHeadXRot()); +- } else if (Evoker.this.getWololoTarget() != null) { +- Evoker.this.getLookControl().setLookAt(Evoker.this.getWololoTarget(), (float)Evoker.this.getMaxHeadYRot(), (float)Evoker.this.getMaxHeadXRot()); +- } +- } +- } ++ private class EvokerAttackSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { + +- class EvokerSummonSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { +- private final TargetingConditions vexCountTargeting = TargetingConditions.forNonCombat().range(16.0).ignoreLineOfSight().ignoreInvisibilityTesting(); +- +- @Override +- public boolean canUse() { +- if (!super.canUse()) { +- return false; +- } else { +- int size = Evoker.this.level() +- .getNearbyEntities(Vex.class, this.vexCountTargeting, Evoker.this, Evoker.this.getBoundingBox().inflate(16.0)) +- .size(); +- return Evoker.this.random.nextInt(8) + 1 > size; +- } ++ EvokerAttackSpellGoal() { ++ super(); + } + + @Override + protected int getCastingTime() { +- return 100; ++ return 40; + } + + @Override + protected int getCastingInterval() { +- return 340; ++ return 100; + } + + @Override + protected void performSpellCasting() { +- ServerLevel serverLevel = (ServerLevel)Evoker.this.level(); +- PlayerTeam team = Evoker.this.getTeam(); ++ LivingEntity entityliving = Evoker.this.getTarget(); ++ double d0 = Math.min(entityliving.getY(), Evoker.this.getY()); ++ double d1 = Math.max(entityliving.getY(), Evoker.this.getY()) + 1.0D; ++ float f = (float) Mth.atan2(entityliving.getZ() - Evoker.this.getZ(), entityliving.getX() - Evoker.this.getX()); ++ int i; + +- for (int i = 0; i < 3; i++) { +- BlockPos blockPos = Evoker.this.blockPosition().offset(-2 + Evoker.this.random.nextInt(5), 1, -2 + Evoker.this.random.nextInt(5)); +- Vex vex = EntityType.VEX.create(Evoker.this.level()); +- if (vex != null) { +- vex.moveTo(blockPos, 0.0F, 0.0F); +- vex.finalizeSpawn(serverLevel, Evoker.this.level().getCurrentDifficultyAt(blockPos), MobSpawnType.MOB_SUMMONED, null, null); +- vex.setOwner(Evoker.this); +- vex.setBoundOrigin(blockPos); +- vex.setLimitedLife(20 * (30 + Evoker.this.random.nextInt(90))); +- if (team != null) { +- serverLevel.getScoreboard().addPlayerToTeam(vex.getScoreboardName(), team); ++ if (Evoker.this.distanceToSqr((Entity) entityliving) < 9.0D) { ++ float f1; ++ ++ for (i = 0; i < 5; ++i) { ++ f1 = f + (float) i * 3.1415927F * 0.4F; ++ this.createSpellEntity(Evoker.this.getX() + (double) Mth.cos(f1) * 1.5D, Evoker.this.getZ() + (double) Mth.sin(f1) * 1.5D, d0, d1, f1, 0); ++ } ++ ++ for (i = 0; i < 8; ++i) { ++ f1 = f + (float) i * 3.1415927F * 2.0F / 8.0F + 1.2566371F; ++ this.createSpellEntity(Evoker.this.getX() + (double) Mth.cos(f1) * 2.5D, Evoker.this.getZ() + (double) Mth.sin(f1) * 2.5D, d0, d1, f1, 3); ++ } ++ } else { ++ for (i = 0; i < 16; ++i) { ++ double d2 = 1.25D * (double) (i + 1); ++ int j = 1 * i; ++ ++ this.createSpellEntity(Evoker.this.getX() + (double) Mth.cos(f) * d2, Evoker.this.getZ() + (double) Mth.sin(f) * d2, d0, d1, f, j); ++ } ++ } ++ ++ } ++ ++ private void createSpellEntity(double x, double d1, double z, double d3, float minY, int i) { ++ BlockPos blockposition = BlockPos.containing(x, d3, d1); ++ boolean flag = false; ++ double d4 = 0.0D; ++ ++ do { ++ BlockPos blockposition1 = blockposition.below(); ++ IBlockData iblockdata = Evoker.this.level().getBlockState(blockposition1); ++ ++ if (iblockdata.isFaceSturdy(Evoker.this.level(), blockposition1, Direction.UP)) { ++ if (!Evoker.this.level().isEmptyBlock(blockposition)) { ++ IBlockData iblockdata1 = Evoker.this.level().getBlockState(blockposition); ++ VoxelShape voxelshape = iblockdata1.getCollisionShape(Evoker.this.level(), blockposition); ++ ++ if (!voxelshape.isEmpty()) { ++ d4 = voxelshape.max(Direction.Axis.Y); ++ } + } + +- serverLevel.addFreshEntityWithPassengers(vex); +- serverLevel.gameEvent(GameEvent.ENTITY_PLACE, blockPos, GameEvent.Context.of(Evoker.this)); ++ flag = true; ++ break; + } ++ ++ blockposition = blockposition.below(); ++ } while (blockposition.getY() >= Mth.floor(z) - 1); ++ ++ if (flag) { ++ Evoker.this.level().addFreshEntity(new EvokerFangs(Evoker.this.level(), x, (double) blockposition.getY() + d4, d1, minY, i, Evoker.this)); ++ Evoker.this.level().gameEvent(GameEvent.ENTITY_PLACE, new Vec3(x, (double) blockposition.getY() + d4, d1), GameEvent.Context.of((Entity) Evoker.this)); + } ++ + } + + @Override + protected SoundEvent getSpellPrepareSound() { +- return SoundEvents.EVOKER_PREPARE_SUMMON; ++ return SoundEvents.EVOKER_PREPARE_ATTACK; + } + + @Override + protected SpellcasterIllager.IllagerSpell getSpell() { +- return SpellcasterIllager.IllagerSpell.SUMMON_VEX; ++ return SpellcasterIllager.IllagerSpell.FANGS; + } + } + + public class EvokerWololoSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { +- private final TargetingConditions wololoTargeting = TargetingConditions.forNonCombat() +- .range(16.0) +- .selector(entity -> ((Sheep)entity).getColor() == DyeColor.BLUE); + ++ private final TargetingConditions wololoTargeting = TargetingConditions.forNonCombat().range(16.0D).selector((entityliving) -> { ++ return ((Sheep) entityliving).getColor() == DyeColor.BLUE; ++ }); ++ ++ public EvokerWololoSpellGoal() { ++ super(); ++ } ++ + @Override + public boolean canUse() { + if (Evoker.this.getTarget() != null) { +@@ -311,12 +330,12 @@ + } else if (!Evoker.this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { + return false; + } else { +- List nearbyEntities = Evoker.this.level() +- .getNearbyEntities(Sheep.class, this.wololoTargeting, Evoker.this, Evoker.this.getBoundingBox().inflate(16.0, 4.0, 16.0)); +- if (nearbyEntities.isEmpty()) { ++ List list = Evoker.this.level().getNearbyEntities(Sheep.class, this.wololoTargeting, Evoker.this, Evoker.this.getBoundingBox().inflate(16.0D, 4.0D, 16.0D)); ++ ++ if (list.isEmpty()) { + return false; + } else { +- Evoker.this.setWololoTarget(nearbyEntities.get(Evoker.this.random.nextInt(nearbyEntities.size()))); ++ Evoker.this.setWololoTarget((Sheep) list.get(Evoker.this.random.nextInt(list.size()))); + return true; + } + } +@@ -330,15 +349,17 @@ + @Override + public void stop() { + super.stop(); +- Evoker.this.setWololoTarget(null); ++ Evoker.this.setWololoTarget((Sheep) null); + } + + @Override + protected void performSpellCasting() { +- Sheep wololoTarget = Evoker.this.getWololoTarget(); +- if (wololoTarget != null && wololoTarget.isAlive()) { +- wololoTarget.setColor(DyeColor.RED); ++ Sheep entitysheep = Evoker.this.getWololoTarget(); ++ ++ if (entitysheep != null && entitysheep.isAlive()) { ++ entitysheep.setColor(DyeColor.RED); + } ++ + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Ghast.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Ghast.java.patch new file mode 100644 index 0000000000..883eb23c05 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Ghast.java.patch @@ -0,0 +1,392 @@ +--- a/net/minecraft/world/entity/monster/Ghast.java ++++ b/net/minecraft/world/entity/monster/Ghast.java +@@ -15,12 +15,12 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.FlyingMob; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.MoveControl; +@@ -34,7 +34,8 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Ghast extends FlyingMob implements Enemy { ++public class Ghast extends FlyingMob implements IMonster { ++ + private static final EntityDataAccessor DATA_IS_CHARGING = SynchedEntityData.defineId(Ghast.class, EntityDataSerializers.BOOLEAN); + private int explosionPower = 1; + +@@ -49,18 +50,17 @@ + this.goalSelector.addGoal(5, new Ghast.RandomFloatAroundGoal(this)); + this.goalSelector.addGoal(7, new Ghast.GhastLookGoal(this)); + this.goalSelector.addGoal(7, new Ghast.GhastShootFireballGoal(this)); +- this.targetSelector +- .addGoal( +- 1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, livingEntity -> Math.abs(livingEntity.getY() - this.getY()) <= 4.0) +- ); ++ this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (entityliving) -> { ++ return Math.abs(entityliving.getY() - this.getY()) <= 4.0D; ++ })); + } + + public boolean isCharging() { +- return this.entityData.get(DATA_IS_CHARGING); ++ return (Boolean) this.entityData.get(Ghast.DATA_IS_CHARGING); + } + + public void setCharging(boolean charging) { +- this.entityData.set(DATA_IS_CHARGING, charging); ++ this.entityData.set(Ghast.DATA_IS_CHARGING, charging); + } + + public int getExplosionPower() { +@@ -87,18 +87,18 @@ + super.hurt(source, 1000.0F); + return true; + } else { +- return !this.isInvulnerableTo(source) && super.hurt(source, amount); ++ return this.isInvulnerableTo(source) ? false : super.hurt(source, amount); + } + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_IS_CHARGING, false); ++ this.entityData.define(Ghast.DATA_IS_CHARGING, false); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0).add(Attributes.FOLLOW_RANGE, 100.0); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.FOLLOW_RANGE, 100.0D); + } + + @Override +@@ -126,7 +126,7 @@ + return 5.0F; + } + +- public static boolean checkGhastSpawnRules(EntityType ghast, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) { ++ public static boolean checkGhastSpawnRules(EntityType ghast, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { + return level.getDifficulty() != Difficulty.PEACEFUL && random.nextInt(20) == 0 && checkMobSpawnRules(ghast, level, spawnType, pos, random); + } + +@@ -136,8 +136,8 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.0625F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.0625F * f, 0.0F); + } + + @Override +@@ -148,7 +148,7 @@ + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- compound.putByte("ExplosionPower", (byte)this.explosionPower); ++ compound.putByte("ExplosionPower", (byte) this.explosionPower); + } + + @Override +@@ -157,91 +157,142 @@ + if (compound.contains("ExplosionPower", 99)) { + this.explosionPower = compound.getByte("ExplosionPower"); + } ++ + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 2.6F; + } + +- static class GhastLookGoal extends Goal { ++ private static class GhastMoveControl extends MoveControl { ++ + private final Ghast ghast; ++ private int floatDuration; + +- public GhastLookGoal(Ghast ghast) { ++ public GhastMoveControl(Ghast ghast) { ++ super(ghast); + this.ghast = ghast; +- this.setFlags(EnumSet.of(Goal.Flag.LOOK)); + } + + @Override +- public boolean canUse() { +- return true; ++ public void tick() { ++ if (this.operation == MoveControl.Operation.MOVE_TO) { ++ if (this.floatDuration-- <= 0) { ++ this.floatDuration += this.ghast.getRandom().nextInt(5) + 2; ++ Vec3 vec3d = new Vec3(this.wantedX - this.ghast.getX(), this.wantedY - this.ghast.getY(), this.wantedZ - this.ghast.getZ()); ++ double d0 = vec3d.length(); ++ ++ vec3d = vec3d.normalize(); ++ if (this.canReach(vec3d, Mth.ceil(d0))) { ++ this.ghast.setDeltaMovement(this.ghast.getDeltaMovement().add(vec3d.scale(0.1D))); ++ } else { ++ this.operation = MoveControl.Operation.WAIT; ++ } ++ } ++ ++ } + } + +- @Override +- public boolean requiresUpdateEveryTick() { ++ private boolean canReach(Vec3 pos, int length) { ++ AABB axisalignedbb = this.ghast.getBoundingBox(); ++ ++ for (int j = 1; j < length; ++j) { ++ axisalignedbb = axisalignedbb.move(pos); ++ if (!this.ghast.level().noCollision(this.ghast, axisalignedbb)) { ++ return false; ++ } ++ } ++ + return true; + } ++ } + ++ private static class RandomFloatAroundGoal extends Goal { ++ ++ private final Ghast ghast; ++ ++ public RandomFloatAroundGoal(Ghast ghast) { ++ this.ghast = ghast; ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); ++ } ++ + @Override +- public void tick() { +- if (this.ghast.getTarget() == null) { +- Vec3 deltaMovement = this.ghast.getDeltaMovement(); +- this.ghast.setYRot(-((float)Mth.atan2(deltaMovement.x, deltaMovement.z)) * (180.0F / (float)Math.PI)); +- this.ghast.yBodyRot = this.ghast.getYRot(); ++ public boolean canUse() { ++ MoveControl controllermove = this.ghast.getMoveControl(); ++ ++ if (!controllermove.hasWanted()) { ++ return true; + } else { +- LivingEntity target = this.ghast.getTarget(); +- double d = 64.0; +- if (target.distanceToSqr(this.ghast) < 4096.0) { +- double d1 = target.getX() - this.ghast.getX(); +- double d2 = target.getZ() - this.ghast.getZ(); +- this.ghast.setYRot(-((float)Mth.atan2(d1, d2)) * (180.0F / (float)Math.PI)); +- this.ghast.yBodyRot = this.ghast.getYRot(); +- } ++ double d0 = controllermove.getWantedX() - this.ghast.getX(); ++ double d1 = controllermove.getWantedY() - this.ghast.getY(); ++ double d2 = controllermove.getWantedZ() - this.ghast.getZ(); ++ double d3 = d0 * d0 + d1 * d1 + d2 * d2; ++ ++ return d3 < 1.0D || d3 > 3600.0D; + } + } ++ ++ @Override ++ public boolean canContinueToUse() { ++ return false; ++ } ++ ++ @Override ++ public void start() { ++ RandomSource randomsource = this.ghast.getRandom(); ++ double d0 = this.ghast.getX() + (double) ((randomsource.nextFloat() * 2.0F - 1.0F) * 16.0F); ++ double d1 = this.ghast.getY() + (double) ((randomsource.nextFloat() * 2.0F - 1.0F) * 16.0F); ++ double d2 = this.ghast.getZ() + (double) ((randomsource.nextFloat() * 2.0F - 1.0F) * 16.0F); ++ ++ this.ghast.getMoveControl().setWantedPosition(d0, d1, d2, 1.0D); ++ } + } + +- static class GhastMoveControl extends MoveControl { ++ private static class GhastLookGoal extends Goal { ++ + private final Ghast ghast; +- private int floatDuration; + +- public GhastMoveControl(Ghast mob) { +- super(mob); +- this.ghast = mob; ++ public GhastLookGoal(Ghast ghast) { ++ this.ghast = ghast; ++ this.setFlags(EnumSet.of(Goal.Type.LOOK)); + } + + @Override +- public void tick() { +- if (this.operation == MoveControl.Operation.MOVE_TO) { +- if (this.floatDuration-- <= 0) { +- this.floatDuration = this.floatDuration + this.ghast.getRandom().nextInt(5) + 2; +- Vec3 vec3 = new Vec3(this.wantedX - this.ghast.getX(), this.wantedY - this.ghast.getY(), this.wantedZ - this.ghast.getZ()); +- double len = vec3.length(); +- Vec3 var4 = vec3.normalize(); +- if (this.canReach(var4, Mth.ceil(len))) { +- this.ghast.setDeltaMovement(this.ghast.getDeltaMovement().add(var4.scale(0.1))); +- } else { +- this.operation = MoveControl.Operation.WAIT; +- } +- } +- } ++ public boolean canUse() { ++ return true; + } + +- private boolean canReach(Vec3 pos, int length) { +- AABB boundingBox = this.ghast.getBoundingBox(); ++ @Override ++ public boolean requiresUpdateEveryTick() { ++ return true; ++ } + +- for (int i = 1; i < length; i++) { +- boundingBox = boundingBox.move(pos); +- if (!this.ghast.level().noCollision(this.ghast, boundingBox)) { +- return false; ++ @Override ++ public void tick() { ++ if (this.ghast.getTarget() == null) { ++ Vec3 vec3d = this.ghast.getDeltaMovement(); ++ ++ this.ghast.setYRot(-((float) Mth.atan2(vec3d.x, vec3d.z)) * 57.295776F); ++ this.ghast.yBodyRot = this.ghast.getYRot(); ++ } else { ++ LivingEntity entityliving = this.ghast.getTarget(); ++ double d0 = 64.0D; ++ ++ if (entityliving.distanceToSqr((Entity) this.ghast) < 4096.0D) { ++ double d1 = entityliving.getX() - this.ghast.getX(); ++ double d2 = entityliving.getZ() - this.ghast.getZ(); ++ ++ this.ghast.setYRot(-((float) Mth.atan2(d1, d2)) * 57.295776F); ++ this.ghast.yBodyRot = this.ghast.getYRot(); + } + } + +- return true; + } + } + +- static class GhastShootFireballGoal extends Goal { ++ private static class GhastShootFireballGoal extends Goal { ++ + private final Ghast ghast; + public int chargeTime; + +@@ -271,74 +322,44 @@ + + @Override + public void tick() { +- LivingEntity target = this.ghast.getTarget(); +- if (target != null) { +- double d = 64.0; +- if (target.distanceToSqr(this.ghast) < 4096.0 && this.ghast.hasLineOfSight(target)) { +- Level level = this.ghast.level(); +- this.chargeTime++; ++ LivingEntity entityliving = this.ghast.getTarget(); ++ ++ if (entityliving != null) { ++ double d0 = 64.0D; ++ ++ if (entityliving.distanceToSqr((Entity) this.ghast) < 4096.0D && this.ghast.hasLineOfSight(entityliving)) { ++ Level world = this.ghast.level(); ++ ++ ++this.chargeTime; + if (this.chargeTime == 10 && !this.ghast.isSilent()) { +- level.levelEvent(null, 1015, this.ghast.blockPosition(), 0); ++ world.levelEvent((Player) null, 1015, this.ghast.blockPosition(), 0); + } + + if (this.chargeTime == 20) { +- double d1 = 4.0; +- Vec3 viewVector = this.ghast.getViewVector(1.0F); +- double d2 = target.getX() - (this.ghast.getX() + viewVector.x * 4.0); +- double d3 = target.getY(0.5) - (0.5 + this.ghast.getY(0.5)); +- double d4 = target.getZ() - (this.ghast.getZ() + viewVector.z * 4.0); ++ double d1 = 4.0D; ++ Vec3 vec3d = this.ghast.getViewVector(1.0F); ++ double d2 = entityliving.getX() - (this.ghast.getX() + vec3d.x * 4.0D); ++ double d3 = entityliving.getY(0.5D) - (0.5D + this.ghast.getY(0.5D)); ++ double d4 = entityliving.getZ() - (this.ghast.getZ() + vec3d.z * 4.0D); ++ + if (!this.ghast.isSilent()) { +- level.levelEvent(null, 1016, this.ghast.blockPosition(), 0); ++ world.levelEvent((Player) null, 1016, this.ghast.blockPosition(), 0); + } + +- LargeFireball largeFireball = new LargeFireball(level, this.ghast, d2, d3, d4, this.ghast.getExplosionPower()); +- largeFireball.setPos(this.ghast.getX() + viewVector.x * 4.0, this.ghast.getY(0.5) + 0.5, largeFireball.getZ() + viewVector.z * 4.0); +- level.addFreshEntity(largeFireball); ++ LargeFireball entitylargefireball = new LargeFireball(world, this.ghast, d2, d3, d4, this.ghast.getExplosionPower()); ++ ++ // CraftBukkit - set bukkitYield when setting explosionpower ++ entitylargefireball.bukkitYield = entitylargefireball.explosionPower = this.ghast.getExplosionPower(); ++ entitylargefireball.setPos(this.ghast.getX() + vec3d.x * 4.0D, this.ghast.getY(0.5D) + 0.5D, entitylargefireball.getZ() + vec3d.z * 4.0D); ++ world.addFreshEntity(entitylargefireball); + this.chargeTime = -40; + } + } else if (this.chargeTime > 0) { +- this.chargeTime--; ++ --this.chargeTime; + } + + this.ghast.setCharging(this.chargeTime > 10); + } + } + } +- +- static class RandomFloatAroundGoal extends Goal { +- private final Ghast ghast; +- +- public RandomFloatAroundGoal(Ghast ghast) { +- this.ghast = ghast; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); +- } +- +- @Override +- public boolean canUse() { +- MoveControl moveControl = this.ghast.getMoveControl(); +- if (!moveControl.hasWanted()) { +- return true; +- } else { +- double d = moveControl.getWantedX() - this.ghast.getX(); +- double d1 = moveControl.getWantedY() - this.ghast.getY(); +- double d2 = moveControl.getWantedZ() - this.ghast.getZ(); +- double d3 = d * d + d1 * d1 + d2 * d2; +- return d3 < 1.0 || d3 > 3600.0; +- } +- } +- +- @Override +- public boolean canContinueToUse() { +- return false; +- } +- +- @Override +- public void start() { +- RandomSource random = this.ghast.getRandom(); +- double d = this.ghast.getX() + (double)((random.nextFloat() * 2.0F - 1.0F) * 16.0F); +- double d1 = this.ghast.getY() + (double)((random.nextFloat() * 2.0F - 1.0F) * 16.0F); +- double d2 = this.ghast.getZ() + (double)((random.nextFloat() * 2.0F - 1.0F) * 16.0F); +- this.ghast.getMoveControl().setWantedPosition(d, d1, d2, 1.0); +- } +- } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Guardian.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Guardian.java.patch new file mode 100644 index 0000000000..b2e7e561b7 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Guardian.java.patch @@ -0,0 +1,574 @@ +--- a/net/minecraft/world/entity/monster/Guardian.java ++++ b/net/minecraft/world/entity/monster/Guardian.java +@@ -19,12 +19,12 @@ + import net.minecraft.world.damagesource.DamageTypes; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.LookControl; +@@ -48,6 +48,7 @@ + import org.joml.Vector3f; + + public class Guardian extends Monster { ++ + protected static final int ATTACK_TIME = 80; + private static final EntityDataAccessor DATA_ID_MOVING = SynchedEntityData.defineId(Guardian.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_ID_ATTACK_TARGET = SynchedEntityData.defineId(Guardian.class, EntityDataSerializers.INT); +@@ -61,7 +62,8 @@ + private int clientSideAttackTime; + private boolean clientSideTouchedGround; + @Nullable +- protected RandomStrollGoal randomStrollGoal; ++ public RandomStrollGoal randomStrollGoal; ++ public Guardian.GuardianAttackGoal guardianAttackGoal; // CraftBukkit - add field + + public Guardian(EntityType entityType, Level level) { + super(entityType, level); +@@ -74,25 +76,22 @@ + + @Override + protected void registerGoals() { +- MoveTowardsRestrictionGoal moveTowardsRestrictionGoal = new MoveTowardsRestrictionGoal(this, 1.0); +- this.randomStrollGoal = new RandomStrollGoal(this, 1.0, 80); +- this.goalSelector.addGoal(4, new Guardian.GuardianAttackGoal(this)); +- this.goalSelector.addGoal(5, moveTowardsRestrictionGoal); ++ MoveTowardsRestrictionGoal pathfindergoalmovetowardsrestriction = new MoveTowardsRestrictionGoal(this, 1.0D); ++ ++ this.randomStrollGoal = new RandomStrollGoal(this, 1.0D, 80); ++ this.goalSelector.addGoal(4, guardianAttackGoal = new Guardian.GuardianAttackGoal(this)); // CraftBukkit - assign field ++ this.goalSelector.addGoal(5, pathfindergoalmovetowardsrestriction); + this.goalSelector.addGoal(7, this.randomStrollGoal); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Guardian.class, 12.0F, 0.01F)); + this.goalSelector.addGoal(9, new RandomLookAroundGoal(this)); +- this.randomStrollGoal.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); +- moveTowardsRestrictionGoal.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ this.randomStrollGoal.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); ++ pathfindergoalmovetowardsrestriction.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, LivingEntity.class, 10, true, false, new Guardian.GuardianAttackSelector(this))); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes() +- .add(Attributes.ATTACK_DAMAGE, 6.0) +- .add(Attributes.MOVEMENT_SPEED, 0.5) +- .add(Attributes.FOLLOW_RANGE, 16.0) +- .add(Attributes.MAX_HEALTH, 30.0); ++ return Monster.createMonsterAttributes().add(Attributes.ATTACK_DAMAGE, 6.0D).add(Attributes.MOVEMENT_SPEED, 0.5D).add(Attributes.FOLLOW_RANGE, 16.0D).add(Attributes.MAX_HEALTH, 30.0D); + } + + @Override +@@ -103,33 +102,33 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_ID_MOVING, false); +- this.entityData.define(DATA_ID_ATTACK_TARGET, 0); ++ this.entityData.define(Guardian.DATA_ID_MOVING, false); ++ this.entityData.define(Guardian.DATA_ID_ATTACK_TARGET, 0); + } + + @Override +- public MobType getMobType() { +- return MobType.WATER; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.WATER; + } + + public boolean isMoving() { +- return this.entityData.get(DATA_ID_MOVING); ++ return (Boolean) this.entityData.get(Guardian.DATA_ID_MOVING); + } + + void setMoving(boolean moving) { +- this.entityData.set(DATA_ID_MOVING, moving); ++ this.entityData.set(Guardian.DATA_ID_MOVING, moving); + } + + public int getAttackDuration() { + return 80; + } + +- void setActiveAttackTarget(int activeAttackTargetId) { +- this.entityData.set(DATA_ID_ATTACK_TARGET, activeAttackTargetId); ++ public void setActiveAttackTarget(int activeAttackTargetId) { ++ this.entityData.set(Guardian.DATA_ID_ATTACK_TARGET, activeAttackTargetId); + } + + public boolean hasActiveAttackTarget() { +- return this.entityData.get(DATA_ID_ATTACK_TARGET) != 0; ++ return (Integer) this.entityData.get(Guardian.DATA_ID_ATTACK_TARGET) != 0; + } + + @Nullable +@@ -140,9 +139,10 @@ + if (this.clientSideCachedAttackTarget != null) { + return this.clientSideCachedAttackTarget; + } else { +- Entity entity = this.level().getEntity(this.entityData.get(DATA_ID_ATTACK_TARGET)); ++ Entity entity = this.level().getEntity((Integer) this.entityData.get(Guardian.DATA_ID_ATTACK_TARGET)); ++ + if (entity instanceof LivingEntity) { +- this.clientSideCachedAttackTarget = (LivingEntity)entity; ++ this.clientSideCachedAttackTarget = (LivingEntity) entity; + return this.clientSideCachedAttackTarget; + } else { + return null; +@@ -156,10 +156,11 @@ + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { + super.onSyncedDataUpdated(key); +- if (DATA_ID_ATTACK_TARGET.equals(key)) { ++ if (Guardian.DATA_ID_ATTACK_TARGET.equals(key)) { + this.clientSideAttackTime = 0; + this.clientSideCachedAttackTarget = null; + } ++ + } + + @Override +@@ -188,7 +189,7 @@ + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return size.height * 0.5F; + } + +@@ -202,82 +203,68 @@ + if (this.isAlive()) { + if (this.level().isClientSide) { + this.clientSideTailAnimationO = this.clientSideTailAnimation; ++ Vec3 vec3d; ++ + if (!this.isInWater()) { + this.clientSideTailAnimationSpeed = 2.0F; +- Vec3 deltaMovement = this.getDeltaMovement(); +- if (deltaMovement.y > 0.0 && this.clientSideTouchedGround && !this.isSilent()) { ++ vec3d = this.getDeltaMovement(); ++ if (vec3d.y > 0.0D && this.clientSideTouchedGround && !this.isSilent()) { + this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), this.getFlopSound(), this.getSoundSource(), 1.0F, 1.0F, false); + } + +- this.clientSideTouchedGround = deltaMovement.y < 0.0 && this.level().loadedAndEntityCanStandOn(this.blockPosition().below(), this); ++ this.clientSideTouchedGround = vec3d.y < 0.0D && this.level().loadedAndEntityCanStandOn(this.blockPosition().below(), this); + } else if (this.isMoving()) { + if (this.clientSideTailAnimationSpeed < 0.5F) { + this.clientSideTailAnimationSpeed = 4.0F; + } else { +- this.clientSideTailAnimationSpeed = this.clientSideTailAnimationSpeed + (0.5F - this.clientSideTailAnimationSpeed) * 0.1F; ++ this.clientSideTailAnimationSpeed += (0.5F - this.clientSideTailAnimationSpeed) * 0.1F; + } + } else { +- this.clientSideTailAnimationSpeed = this.clientSideTailAnimationSpeed + (0.125F - this.clientSideTailAnimationSpeed) * 0.2F; ++ this.clientSideTailAnimationSpeed += (0.125F - this.clientSideTailAnimationSpeed) * 0.2F; + } + +- this.clientSideTailAnimation = this.clientSideTailAnimation + this.clientSideTailAnimationSpeed; ++ this.clientSideTailAnimation += this.clientSideTailAnimationSpeed; + this.clientSideSpikesAnimationO = this.clientSideSpikesAnimation; + if (!this.isInWaterOrBubble()) { + this.clientSideSpikesAnimation = this.random.nextFloat(); + } else if (this.isMoving()) { +- this.clientSideSpikesAnimation = this.clientSideSpikesAnimation + (0.0F - this.clientSideSpikesAnimation) * 0.25F; ++ this.clientSideSpikesAnimation += (0.0F - this.clientSideSpikesAnimation) * 0.25F; + } else { +- this.clientSideSpikesAnimation = this.clientSideSpikesAnimation + (1.0F - this.clientSideSpikesAnimation) * 0.06F; ++ this.clientSideSpikesAnimation += (1.0F - this.clientSideSpikesAnimation) * 0.06F; + } + + if (this.isMoving() && this.isInWater()) { +- Vec3 deltaMovement = this.getViewVector(0.0F); ++ vec3d = this.getViewVector(0.0F); + +- for (int i = 0; i < 2; i++) { +- this.level() +- .addParticle( +- ParticleTypes.BUBBLE, +- this.getRandomX(0.5) - deltaMovement.x * 1.5, +- this.getRandomY() - deltaMovement.y * 1.5, +- this.getRandomZ(0.5) - deltaMovement.z * 1.5, +- 0.0, +- 0.0, +- 0.0 +- ); ++ for (int i = 0; i < 2; ++i) { ++ this.level().addParticle(ParticleTypes.BUBBLE, this.getRandomX(0.5D) - vec3d.x * 1.5D, this.getRandomY() - vec3d.y * 1.5D, this.getRandomZ(0.5D) - vec3d.z * 1.5D, 0.0D, 0.0D, 0.0D); + } + } + + if (this.hasActiveAttackTarget()) { + if (this.clientSideAttackTime < this.getAttackDuration()) { +- this.clientSideAttackTime++; ++ ++this.clientSideAttackTime; + } + +- LivingEntity activeAttackTarget = this.getActiveAttackTarget(); +- if (activeAttackTarget != null) { +- this.getLookControl().setLookAt(activeAttackTarget, 90.0F, 90.0F); ++ LivingEntity entityliving = this.getActiveAttackTarget(); ++ ++ if (entityliving != null) { ++ this.getLookControl().setLookAt(entityliving, 90.0F, 90.0F); + this.getLookControl().tick(); +- double d = (double)this.getAttackAnimationScale(0.0F); +- double d1 = activeAttackTarget.getX() - this.getX(); +- double d2 = activeAttackTarget.getY(0.5) - this.getEyeY(); +- double d3 = activeAttackTarget.getZ() - this.getZ(); +- double squareRoot = Math.sqrt(d1 * d1 + d2 * d2 + d3 * d3); +- double var17 = d1 / squareRoot; +- double var18 = d2 / squareRoot; +- double var19 = d3 / squareRoot; +- double randomDouble = this.random.nextDouble(); ++ double d0 = (double) this.getAttackAnimationScale(0.0F); ++ double d1 = entityliving.getX() - this.getX(); ++ double d2 = entityliving.getY(0.5D) - this.getEyeY(); ++ double d3 = entityliving.getZ() - this.getZ(); ++ double d4 = Math.sqrt(d1 * d1 + d2 * d2 + d3 * d3); + +- while (randomDouble < squareRoot) { +- randomDouble += 1.8 - d + this.random.nextDouble() * (1.7 - d); +- this.level() +- .addParticle( +- ParticleTypes.BUBBLE, +- this.getX() + var17 * randomDouble, +- this.getEyeY() + var18 * randomDouble, +- this.getZ() + var19 * randomDouble, +- 0.0, +- 0.0, +- 0.0 +- ); ++ d1 /= d4; ++ d2 /= d4; ++ d3 /= d4; ++ double d5 = this.random.nextDouble(); ++ ++ while (d5 < d4) { ++ d5 += 1.8D - d0 + this.random.nextDouble() * (1.7D - d0); ++ this.level().addParticle(ParticleTypes.BUBBLE, this.getX() + d1 * d5, this.getEyeY() + d2 * d5, this.getZ() + d3 * d5, 0.0D, 0.0D, 0.0D); + } + } + } +@@ -286,10 +273,7 @@ + if (this.isInWaterOrBubble()) { + this.setAirSupply(300); + } else if (this.onGround()) { +- this.setDeltaMovement( +- this.getDeltaMovement() +- .add((double)((this.random.nextFloat() * 2.0F - 1.0F) * 0.4F), 0.5, (double)((this.random.nextFloat() * 2.0F - 1.0F) * 0.4F)) +- ); ++ this.setDeltaMovement(this.getDeltaMovement().add((double) ((this.random.nextFloat() * 2.0F - 1.0F) * 0.4F), 0.5D, (double) ((this.random.nextFloat() * 2.0F - 1.0F) * 0.4F))); + this.setYRot(this.random.nextFloat() * 360.0F); + this.setOnGround(false); + this.hasImpulse = true; +@@ -316,11 +300,11 @@ + } + + public float getAttackAnimationScale(float partialTick) { +- return ((float)this.clientSideAttackTime + partialTick) / (float)this.getAttackDuration(); ++ return ((float) this.clientSideAttackTime + partialTick) / (float) this.getAttackDuration(); + } + + public float getClientSideAttackTime() { +- return (float)this.clientSideAttackTime; ++ return (float) this.clientSideAttackTime; + } + + @Override +@@ -328,13 +312,8 @@ + return level.isUnobstructed(this); + } + +- public static boolean checkGuardianSpawnRules( +- EntityType guardian, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random +- ) { +- return (random.nextInt(20) == 0 || !level.canSeeSkyFromBelowWater(pos)) +- && level.getDifficulty() != Difficulty.PEACEFUL +- && (MobSpawnType.isSpawner(spawnType) || level.getFluidState(pos).is(FluidTags.WATER)) +- && level.getFluidState(pos.below()).is(FluidTags.WATER); ++ public static boolean checkGuardianSpawnRules(EntityType guardian, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ return (random.nextInt(20) == 0 || !level.canSeeSkyFromBelowWater(pos)) && level.getDifficulty() != Difficulty.PEACEFUL && (EnumMobSpawn.isSpawner(spawnType) || level.getFluidState(pos).is(FluidTags.WATER)) && level.getFluidState(pos.below()).is(FluidTags.WATER); + } + + @Override +@@ -342,11 +321,14 @@ + if (this.level().isClientSide) { + return false; + } else { +- if (!this.isMoving() +- && !source.is(DamageTypeTags.AVOIDS_GUARDIAN_THORNS) +- && !source.is(DamageTypes.THORNS) +- && source.getDirectEntity() instanceof LivingEntity livingEntity) { +- livingEntity.hurt(this.damageSources().thorns(this), 2.0F); ++ if (!this.isMoving() && !source.is(DamageTypeTags.AVOIDS_GUARDIAN_THORNS) && !source.is(DamageTypes.THORNS)) { ++ Entity entity = source.getDirectEntity(); ++ ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ entityliving.hurt(this.damageSources().thorns(this), 2.0F); ++ } + } + + if (this.randomStrollGoal != null) { +@@ -366,51 +348,108 @@ + public void travel(Vec3 travelVector) { + if (this.isControlledByLocalInstance() && this.isInWater()) { + this.moveRelative(0.1F, travelVector); +- this.move(MoverType.SELF, this.getDeltaMovement()); +- this.setDeltaMovement(this.getDeltaMovement().scale(0.9)); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); ++ this.setDeltaMovement(this.getDeltaMovement().scale(0.9D)); + if (!this.isMoving() && this.getTarget() == null) { +- this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.005, 0.0)); ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.005D, 0.0D)); + } + } else { + super.travel(travelVector); + } ++ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.125F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.125F * f, 0.0F); + } + +- static class GuardianAttackGoal extends Goal { ++ private static class GuardianMoveControl extends MoveControl { ++ + private final Guardian guardian; +- private int attackTime; ++ ++ public GuardianMoveControl(Guardian guardian) { ++ super(guardian); ++ this.guardian = guardian; ++ } ++ ++ @Override ++ public void tick() { ++ if (this.operation == MoveControl.Operation.MOVE_TO && !this.guardian.getNavigation().isDone()) { ++ Vec3 vec3d = new Vec3(this.wantedX - this.guardian.getX(), this.wantedY - this.guardian.getY(), this.wantedZ - this.guardian.getZ()); ++ double d0 = vec3d.length(); ++ double d1 = vec3d.x / d0; ++ double d2 = vec3d.y / d0; ++ double d3 = vec3d.z / d0; ++ float f = (float) (Mth.atan2(vec3d.z, vec3d.x) * 57.2957763671875D) - 90.0F; ++ ++ this.guardian.setYRot(this.rotlerp(this.guardian.getYRot(), f, 90.0F)); ++ this.guardian.yBodyRot = this.guardian.getYRot(); ++ float f1 = (float) (this.speedModifier * this.guardian.getAttributeValue(Attributes.MOVEMENT_SPEED)); ++ float f2 = Mth.lerp(0.125F, this.guardian.getSpeed(), f1); ++ ++ this.guardian.setSpeed(f2); ++ double d4 = Math.sin((double) (this.guardian.tickCount + this.guardian.getId()) * 0.5D) * 0.05D; ++ double d5 = Math.cos((double) (this.guardian.getYRot() * 0.017453292F)); ++ double d6 = Math.sin((double) (this.guardian.getYRot() * 0.017453292F)); ++ double d7 = Math.sin((double) (this.guardian.tickCount + this.guardian.getId()) * 0.75D) * 0.05D; ++ ++ this.guardian.setDeltaMovement(this.guardian.getDeltaMovement().add(d4 * d5, d7 * (d6 + d5) * 0.25D + (double) f2 * d2 * 0.1D, d4 * d6)); ++ LookControl controllerlook = this.guardian.getLookControl(); ++ double d8 = this.guardian.getX() + d1 * 2.0D; ++ double d9 = this.guardian.getEyeY() + d2 / d0; ++ double d10 = this.guardian.getZ() + d3 * 2.0D; ++ double d11 = controllerlook.getWantedX(); ++ double d12 = controllerlook.getWantedY(); ++ double d13 = controllerlook.getWantedZ(); ++ ++ if (!controllerlook.isLookingAtTarget()) { ++ d11 = d8; ++ d12 = d9; ++ d13 = d10; ++ } ++ ++ this.guardian.getLookControl().setLookAt(Mth.lerp(0.125D, d11, d8), Mth.lerp(0.125D, d12, d9), Mth.lerp(0.125D, d13, d10), 10.0F, 40.0F); ++ this.guardian.setMoving(true); ++ } else { ++ this.guardian.setSpeed(0.0F); ++ this.guardian.setMoving(false); ++ } ++ } ++ } ++ ++ public static class GuardianAttackGoal extends Goal { ++ ++ private final Guardian guardian; ++ public int attackTime; + private final boolean elder; + + public GuardianAttackGoal(Guardian guardian) { + this.guardian = guardian; + this.elder = guardian instanceof ElderGuardian; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + } + + @Override + public boolean canUse() { +- LivingEntity target = this.guardian.getTarget(); +- return target != null && target.isAlive(); ++ LivingEntity entityliving = this.guardian.getTarget(); ++ ++ return entityliving != null && entityliving.isAlive(); + } + + @Override + public boolean canContinueToUse() { +- return super.canContinueToUse() +- && (this.elder || this.guardian.getTarget() != null && this.guardian.distanceToSqr(this.guardian.getTarget()) > 9.0); ++ return super.canContinueToUse() && (this.elder || this.guardian.getTarget() != null && this.guardian.distanceToSqr((Entity) this.guardian.getTarget()) > 9.0D); + } + + @Override + public void start() { + this.attackTime = -10; + this.guardian.getNavigation().stop(); +- LivingEntity target = this.guardian.getTarget(); +- if (target != null) { +- this.guardian.getLookControl().setLookAt(target, 90.0F, 90.0F); ++ LivingEntity entityliving = this.guardian.getTarget(); ++ ++ if (entityliving != null) { ++ this.guardian.getLookControl().setLookAt(entityliving, 90.0F, 90.0F); + } + + this.guardian.hasImpulse = true; +@@ -419,7 +458,7 @@ + @Override + public void stop() { + this.guardian.setActiveAttackTarget(0); +- this.guardian.setTarget(null); ++ this.guardian.setTarget((LivingEntity) null); + this.guardian.randomStrollGoal.trigger(); + } + +@@ -430,21 +469,23 @@ + + @Override + public void tick() { +- LivingEntity target = this.guardian.getTarget(); +- if (target != null) { ++ LivingEntity entityliving = this.guardian.getTarget(); ++ ++ if (entityliving != null) { + this.guardian.getNavigation().stop(); +- this.guardian.getLookControl().setLookAt(target, 90.0F, 90.0F); +- if (!this.guardian.hasLineOfSight(target)) { +- this.guardian.setTarget(null); ++ this.guardian.getLookControl().setLookAt(entityliving, 90.0F, 90.0F); ++ if (!this.guardian.hasLineOfSight(entityliving)) { ++ this.guardian.setTarget((LivingEntity) null); + } else { +- this.attackTime++; ++ ++this.attackTime; + if (this.attackTime == 0) { +- this.guardian.setActiveAttackTarget(target.getId()); ++ this.guardian.setActiveAttackTarget(entityliving.getId()); + if (!this.guardian.isSilent()) { +- this.guardian.level().broadcastEntityEvent(this.guardian, (byte)21); ++ this.guardian.level().broadcastEntityEvent(this.guardian, (byte) 21); + } + } else if (this.attackTime >= this.guardian.getAttackDuration()) { + float f = 1.0F; ++ + if (this.guardian.level().getDifficulty() == Difficulty.HARD) { + f += 2.0F; + } +@@ -453,9 +494,9 @@ + f += 2.0F; + } + +- target.hurt(this.guardian.damageSources().indirectMagic(this.guardian, this.guardian), f); +- target.hurt(this.guardian.damageSources().mobAttack(this.guardian), (float)this.guardian.getAttributeValue(Attributes.ATTACK_DAMAGE)); +- this.guardian.setTarget(null); ++ entityliving.hurt(this.guardian.damageSources().indirectMagic(this.guardian, this.guardian), f); ++ entityliving.hurt(this.guardian.damageSources().mobAttack(this.guardian), (float) this.guardian.getAttributeValue(Attributes.ATTACK_DAMAGE)); ++ this.guardian.setTarget((LivingEntity) null); + } + + super.tick(); +@@ -464,67 +505,16 @@ + } + } + +- static class GuardianAttackSelector implements Predicate { ++ private static class GuardianAttackSelector implements Predicate { ++ + private final Guardian guardian; + + public GuardianAttackSelector(Guardian guardian) { + this.guardian = guardian; + } + +- @Override + public boolean test(@Nullable LivingEntity entity) { +- return (entity instanceof Player || entity instanceof Squid || entity instanceof Axolotl) && entity.distanceToSqr(this.guardian) > 9.0; ++ return (entity instanceof Player || entity instanceof Squid || entity instanceof Axolotl) && entity.distanceToSqr((Entity) this.guardian) > 9.0D; + } + } +- +- static class GuardianMoveControl extends MoveControl { +- private final Guardian guardian; +- +- public GuardianMoveControl(Guardian mob) { +- super(mob); +- this.guardian = mob; +- } +- +- @Override +- public void tick() { +- if (this.operation == MoveControl.Operation.MOVE_TO && !this.guardian.getNavigation().isDone()) { +- Vec3 vec3 = new Vec3(this.wantedX - this.guardian.getX(), this.wantedY - this.guardian.getY(), this.wantedZ - this.guardian.getZ()); +- double len = vec3.length(); +- double d = vec3.x / len; +- double d1 = vec3.y / len; +- double d2 = vec3.z / len; +- float f = (float)(Mth.atan2(vec3.z, vec3.x) * 180.0F / (float)Math.PI) - 90.0F; +- this.guardian.setYRot(this.rotlerp(this.guardian.getYRot(), f, 90.0F)); +- this.guardian.yBodyRot = this.guardian.getYRot(); +- float f1 = (float)(this.speedModifier * this.guardian.getAttributeValue(Attributes.MOVEMENT_SPEED)); +- float f2 = Mth.lerp(0.125F, this.guardian.getSpeed(), f1); +- this.guardian.setSpeed(f2); +- double d3 = Math.sin((double)(this.guardian.tickCount + this.guardian.getId()) * 0.5) * 0.05; +- double cos = Math.cos((double)(this.guardian.getYRot() * (float) (Math.PI / 180.0))); +- double sin = Math.sin((double)(this.guardian.getYRot() * (float) (Math.PI / 180.0))); +- double d4 = Math.sin((double)(this.guardian.tickCount + this.guardian.getId()) * 0.75) * 0.05; +- this.guardian.setDeltaMovement(this.guardian.getDeltaMovement().add(d3 * cos, d4 * (sin + cos) * 0.25 + (double)f2 * d1 * 0.1, d3 * sin)); +- LookControl lookControl = this.guardian.getLookControl(); +- double d5 = this.guardian.getX() + d * 2.0; +- double d6 = this.guardian.getEyeY() + d1 / len; +- double d7 = this.guardian.getZ() + d2 * 2.0; +- double wantedX = lookControl.getWantedX(); +- double wantedY = lookControl.getWantedY(); +- double wantedZ = lookControl.getWantedZ(); +- if (!lookControl.isLookingAtTarget()) { +- wantedX = d5; +- wantedY = d6; +- wantedZ = d7; +- } +- +- this.guardian +- .getLookControl() +- .setLookAt(Mth.lerp(0.125, wantedX, d5), Mth.lerp(0.125, wantedY, d6), Mth.lerp(0.125, wantedZ, d7), 10.0F, 40.0F); +- this.guardian.setMoving(true); +- } else { +- this.guardian.setSpeed(0.0F); +- this.guardian.setMoving(false); +- } +- } +- } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Husk.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Husk.java.patch new file mode 100644 index 0000000000..d48c4adfd2 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Husk.java.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/world/entity/monster/Husk.java ++++ b/net/minecraft/world/entity/monster/Husk.java +@@ -10,20 +10,22 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; + import org.joml.Vector3f; + + public class Husk extends Zombie { ++ + public Husk(EntityType entityType, Level level) { + super(entityType, level); + } + +- public static boolean checkHuskSpawnRules(EntityType husk, ServerLevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) { +- return checkMonsterSpawnRules(husk, level, spawnType, pos, random) && (MobSpawnType.isSpawner(spawnType) || level.canSeeSky(pos)); ++ public static boolean checkHuskSpawnRules(EntityType husk, ServerLevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ return checkMonsterSpawnRules(husk, level, spawnType, pos, random) && (EnumMobSpawn.isSpawner(spawnType) || level.canSeeSky(pos)); + } + + @Override +@@ -54,9 +56,11 @@ + @Override + public boolean doHurtTarget(Entity entity) { + boolean flag = super.doHurtTarget(entity); ++ + if (flag && this.getMainHandItem().isEmpty() && entity instanceof LivingEntity) { +- float effectiveDifficulty = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty(); +- ((LivingEntity)entity).addEffect(new MobEffectInstance(MobEffects.HUNGER, 140 * (int)effectiveDifficulty), this); ++ float f = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty(); ++ ++ ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.HUNGER, 140 * (int) f), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + + return flag; +@@ -71,8 +75,9 @@ + protected void doUnderWaterConversion() { + this.convertToZombieType(EntityType.ZOMBIE); + if (!this.isSilent()) { +- this.level().levelEvent(null, 1041, this.blockPosition(), 0); ++ this.level().levelEvent((Player) null, 1041, this.blockPosition(), 0); + } ++ + } + + @Override +@@ -81,7 +86,7 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.125F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.125F * f, 0.0F); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Illusioner.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Illusioner.java.patch new file mode 100644 index 0000000000..2c34f0888c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Illusioner.java.patch @@ -0,0 +1,324 @@ +--- a/net/minecraft/world/entity/monster/Illusioner.java ++++ b/net/minecraft/world/entity/monster/Illusioner.java +@@ -12,12 +12,12 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.FloatGoal; +@@ -40,6 +40,7 @@ + import net.minecraft.world.phys.Vec3; + + public class Illusioner extends SpellcasterIllager implements RangedAttackMob { ++ + private static final int NUM_ILLUSIONS = 4; + private static final int ILLUSION_TRANSITION_TICKS = 3; + private static final int ILLUSION_SPREAD = 3; +@@ -51,10 +52,11 @@ + this.xpReward = 5; + this.clientSideIllusionOffsets = new Vec3[2][4]; + +- for (int i = 0; i < 4; i++) { ++ for (int i = 0; i < 4; ++i) { + this.clientSideIllusionOffsets[0][i] = Vec3.ZERO; + this.clientSideIllusionOffsets[1][i] = Vec3.ZERO; + } ++ + } + + @Override +@@ -64,24 +66,22 @@ + this.goalSelector.addGoal(1, new SpellcasterIllager.SpellcasterCastingSpellGoal()); + this.goalSelector.addGoal(4, new Illusioner.IllusionerMirrorSpellGoal()); + this.goalSelector.addGoal(5, new Illusioner.IllusionerBlindnessSpellGoal()); +- this.goalSelector.addGoal(6, new RangedBowAttackGoal<>(this, 0.5, 20, 15.0F)); +- this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6)); ++ this.goalSelector.addGoal(6, new RangedBowAttackGoal<>(this, 0.5D, 20, 15.0F)); ++ this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6D)); + this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Raider.class).setAlertOthers()); +- this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true).setUnseenMemoryTicks(300)); +- this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false).setUnseenMemoryTicks(300)); +- this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, false).setUnseenMemoryTicks(300)); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers()); ++ this.targetSelector.addGoal(2, (new NearestAttackableTargetGoal<>(this, Player.class, true)).setUnseenMemoryTicks(300)); ++ this.targetSelector.addGoal(3, (new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)).setUnseenMemoryTicks(300)); ++ this.targetSelector.addGoal(3, (new NearestAttackableTargetGoal<>(this, IronGolem.class, false)).setUnseenMemoryTicks(300)); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.5).add(Attributes.FOLLOW_RANGE, 18.0).add(Attributes.MAX_HEALTH, 32.0); ++ return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.5D).add(Attributes.FOLLOW_RANGE, 18.0D).add(Attributes.MAX_HEALTH, 32.0D); + } + + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.BOW)); + return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } +@@ -93,47 +93,47 @@ + + @Override + public AABB getBoundingBoxForCulling() { +- return this.getBoundingBox().inflate(3.0, 0.0, 3.0); ++ return this.getBoundingBox().inflate(3.0D, 0.0D, 3.0D); + } + + @Override + public void aiStep() { + super.aiStep(); + if (this.level().isClientSide && this.isInvisible()) { +- this.clientSideIllusionTicks--; ++ --this.clientSideIllusionTicks; + if (this.clientSideIllusionTicks < 0) { + this.clientSideIllusionTicks = 0; + } + +- if (this.hurtTime == 1 || this.tickCount % 1200 == 0) { ++ if (this.hurtTime != 1 && this.tickCount % 1200 != 0) { ++ if (this.hurtTime == this.hurtDuration - 1) { ++ this.clientSideIllusionTicks = 3; ++ ++ for (int i = 0; i < 4; ++i) { ++ this.clientSideIllusionOffsets[0][i] = this.clientSideIllusionOffsets[1][i]; ++ this.clientSideIllusionOffsets[1][i] = new Vec3(0.0D, 0.0D, 0.0D); ++ } ++ } ++ } else { + this.clientSideIllusionTicks = 3; + float f = -6.0F; +- int i = 13; ++ boolean flag = true; + +- for (int i1 = 0; i1 < 4; i1++) { +- this.clientSideIllusionOffsets[0][i1] = this.clientSideIllusionOffsets[1][i1]; +- this.clientSideIllusionOffsets[1][i1] = new Vec3( +- (double)(-6.0F + (float)this.random.nextInt(13)) * 0.5, +- (double)Math.max(0, this.random.nextInt(6) - 4), +- (double)(-6.0F + (float)this.random.nextInt(13)) * 0.5 +- ); +- } ++ int j; + +- for (int i1 = 0; i1 < 16; i1++) { +- this.level().addParticle(ParticleTypes.CLOUD, this.getRandomX(0.5), this.getRandomY(), this.getZ(0.5), 0.0, 0.0, 0.0); ++ for (j = 0; j < 4; ++j) { ++ this.clientSideIllusionOffsets[0][j] = this.clientSideIllusionOffsets[1][j]; ++ this.clientSideIllusionOffsets[1][j] = new Vec3((double) (-6.0F + (float) this.random.nextInt(13)) * 0.5D, (double) Math.max(0, this.random.nextInt(6) - 4), (double) (-6.0F + (float) this.random.nextInt(13)) * 0.5D); + } + +- this.level() +- .playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.ILLUSIONER_MIRROR_MOVE, this.getSoundSource(), 1.0F, 1.0F, false); +- } else if (this.hurtTime == this.hurtDuration - 1) { +- this.clientSideIllusionTicks = 3; +- +- for (int i2 = 0; i2 < 4; i2++) { +- this.clientSideIllusionOffsets[0][i2] = this.clientSideIllusionOffsets[1][i2]; +- this.clientSideIllusionOffsets[1][i2] = new Vec3(0.0, 0.0, 0.0); ++ for (j = 0; j < 16; ++j) { ++ this.level().addParticle(ParticleTypes.CLOUD, this.getRandomX(0.5D), this.getRandomY(), this.getZ(0.5D), 0.0D, 0.0D, 0.0D); + } ++ ++ this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.ILLUSIONER_MIRROR_MOVE, this.getSoundSource(), 1.0F, 1.0F, false); + } + } ++ + } + + @Override +@@ -145,22 +145,22 @@ + if (this.clientSideIllusionTicks <= 0) { + return this.clientSideIllusionOffsets[1]; + } else { +- double d = (double)(((float)this.clientSideIllusionTicks - partialTick) / 3.0F); +- double var6 = Math.pow(d, 0.25); +- Vec3[] vec3s = new Vec3[4]; ++ double d0 = (double) (((float) this.clientSideIllusionTicks - partialTick) / 3.0F); + +- for (int i = 0; i < 4; i++) { +- vec3s[i] = this.clientSideIllusionOffsets[1][i].scale(1.0 - var6).add(this.clientSideIllusionOffsets[0][i].scale(var6)); ++ d0 = Math.pow(d0, 0.25D); ++ Vec3[] avec3d = new Vec3[4]; ++ ++ for (int i = 0; i < 4; ++i) { ++ avec3d[i] = this.clientSideIllusionOffsets[1][i].scale(1.0D - d0).add(this.clientSideIllusionOffsets[0][i].scale(d0)); + } + +- return vec3s; ++ return avec3d; + } + } + + @Override + public boolean isAlliedTo(Entity entity) { +- return super.isAlliedTo(entity) +- || entity instanceof LivingEntity && ((LivingEntity)entity).getMobType() == MobType.ILLAGER && this.getTeam() == null && entity.getTeam() == null; ++ return super.isAlliedTo(entity) ? true : (entity instanceof LivingEntity && ((LivingEntity) entity).getMobType() == EnumMonsterType.ILLAGER ? this.getTeam() == null && entity.getTeam() == null : false); + } + + @Override +@@ -184,49 +184,36 @@ + } + + @Override +- public void applyRaidBuffs(int wave, boolean unusedFalse) { +- } ++ public void applyRaidBuffs(int wave, boolean unusedFalse) {} + + @Override + public void performRangedAttack(LivingEntity target, float distanceFactor) { +- ItemStack projectile = this.getProjectile(this.getItemInHand(ProjectileUtil.getWeaponHoldingHand(this, Items.BOW))); +- AbstractArrow mobArrow = ProjectileUtil.getMobArrow(this, projectile, distanceFactor); +- double d = target.getX() - this.getX(); +- double d1 = target.getY(0.3333333333333333) - mobArrow.getY(); ++ ItemStack itemstack = this.getProjectile(this.getItemInHand(ProjectileUtil.getWeaponHoldingHand(this, Items.BOW))); ++ AbstractArrow entityarrow = ProjectileUtil.getMobArrow(this, itemstack, distanceFactor); ++ double d0 = target.getX() - this.getX(); ++ double d1 = target.getY(0.3333333333333333D) - entityarrow.getY(); + double d2 = target.getZ() - this.getZ(); +- double squareRoot = Math.sqrt(d * d + d2 * d2); +- mobArrow.shoot(d, d1 + squareRoot * 0.2F, d2, 1.6F, (float)(14 - this.level().getDifficulty().getId() * 4)); ++ double d3 = Math.sqrt(d0 * d0 + d2 * d2); ++ ++ entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level().getDifficulty().getId() * 4)); + this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); +- this.level().addFreshEntity(mobArrow); ++ this.level().addFreshEntity(entityarrow); + } + + @Override +- public AbstractIllager.IllagerArmPose getArmPose() { +- if (this.isCastingSpell()) { +- return AbstractIllager.IllagerArmPose.SPELLCASTING; +- } else { +- return this.isAggressive() ? AbstractIllager.IllagerArmPose.BOW_AND_ARROW : AbstractIllager.IllagerArmPose.CROSSED; +- } ++ public AbstractIllager.a getArmPose() { ++ return this.isCastingSpell() ? AbstractIllager.a.SPELLCASTING : (this.isAggressive() ? AbstractIllager.a.BOW_AND_ARROW : AbstractIllager.a.CROSSED); + } + +- class IllusionerBlindnessSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { +- private int lastTargetId; ++ private class IllusionerMirrorSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { + +- @Override +- public boolean canUse() { +- return super.canUse() +- && Illusioner.this.getTarget() != null +- && Illusioner.this.getTarget().getId() != this.lastTargetId +- && Illusioner.this.level().getCurrentDifficultyAt(Illusioner.this.blockPosition()).isHarderThan((float)Difficulty.NORMAL.ordinal()); ++ IllusionerMirrorSpellGoal() { ++ super(); + } + + @Override +- public void start() { +- super.start(); +- LivingEntity target = Illusioner.this.getTarget(); +- if (target != null) { +- this.lastTargetId = target.getId(); +- } ++ public boolean canUse() { ++ return !super.canUse() ? false : !Illusioner.this.hasEffect(MobEffects.INVISIBILITY); + } + + @Override +@@ -236,55 +223,73 @@ + + @Override + protected int getCastingInterval() { +- return 180; ++ return 340; + } + + @Override + protected void performSpellCasting() { +- Illusioner.this.getTarget().addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 400), Illusioner.this); ++ Illusioner.this.addEffect(new MobEffectInstance(MobEffects.INVISIBILITY, 1200), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ILLUSION); // CraftBukkit + } + ++ @Nullable + @Override + protected SoundEvent getSpellPrepareSound() { +- return SoundEvents.ILLUSIONER_PREPARE_BLINDNESS; ++ return SoundEvents.ILLUSIONER_PREPARE_MIRROR; + } + + @Override + protected SpellcasterIllager.IllagerSpell getSpell() { +- return SpellcasterIllager.IllagerSpell.BLINDNESS; ++ return SpellcasterIllager.IllagerSpell.DISAPPEAR; + } + } + +- class IllusionerMirrorSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { ++ private class IllusionerBlindnessSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { ++ ++ private int lastTargetId; ++ ++ IllusionerBlindnessSpellGoal() { ++ super(); ++ } ++ + @Override + public boolean canUse() { +- return super.canUse() && !Illusioner.this.hasEffect(MobEffects.INVISIBILITY); ++ return !super.canUse() ? false : (Illusioner.this.getTarget() == null ? false : (Illusioner.this.getTarget().getId() == this.lastTargetId ? false : Illusioner.this.level().getCurrentDifficultyAt(Illusioner.this.blockPosition()).isHarderThan((float) Difficulty.NORMAL.ordinal()))); + } + + @Override ++ public void start() { ++ super.start(); ++ LivingEntity entityliving = Illusioner.this.getTarget(); ++ ++ if (entityliving != null) { ++ this.lastTargetId = entityliving.getId(); ++ } ++ ++ } ++ ++ @Override + protected int getCastingTime() { + return 20; + } + + @Override + protected int getCastingInterval() { +- return 340; ++ return 180; + } + + @Override + protected void performSpellCasting() { +- Illusioner.this.addEffect(new MobEffectInstance(MobEffects.INVISIBILITY, 1200)); ++ Illusioner.this.getTarget().addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 400), Illusioner.this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + +- @Nullable + @Override + protected SoundEvent getSpellPrepareSound() { +- return SoundEvents.ILLUSIONER_PREPARE_MIRROR; ++ return SoundEvents.ILLUSIONER_PREPARE_BLINDNESS; + } + + @Override + protected SpellcasterIllager.IllagerSpell getSpell() { +- return SpellcasterIllager.IllagerSpell.DISAPPEAR; ++ return SpellcasterIllager.IllagerSpell.BLINDNESS; + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Phantom.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Phantom.java.patch new file mode 100644 index 0000000000..cf3ac8546b --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Phantom.java.patch @@ -0,0 +1,668 @@ +--- a/net/minecraft/world/entity/monster/Phantom.java ++++ b/net/minecraft/world/entity/monster/Phantom.java +@@ -2,6 +2,7 @@ + + import java.util.Comparator; + import java.util.EnumSet; ++import java.util.Iterator; + import java.util.List; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +@@ -18,15 +19,15 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.FlyingMob; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.BodyRotationControl; + import net.minecraft.world.entity.ai.control.LookControl; +@@ -41,16 +42,20 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Phantom extends FlyingMob implements Enemy { ++public class Phantom extends FlyingMob implements IMonster { ++ + public static final float FLAP_DEGREES_PER_TICK = 7.448451F; + public static final int TICKS_PER_FLAP = Mth.ceil(24.166098F); + private static final EntityDataAccessor ID_SIZE = SynchedEntityData.defineId(Phantom.class, EntityDataSerializers.INT); +- Vec3 moveTargetPoint = Vec3.ZERO; +- BlockPos anchorPoint = BlockPos.ZERO; +- Phantom.AttackPhase attackPhase = Phantom.AttackPhase.CIRCLE; ++ Vec3 moveTargetPoint; ++ BlockPos anchorPoint; ++ Phantom.AttackPhase attackPhase; + + public Phantom(EntityType entityType, Level level) { + super(entityType, level); ++ this.moveTargetPoint = Vec3.ZERO; ++ this.anchorPoint = BlockPos.ZERO; ++ this.attackPhase = Phantom.AttackPhase.CIRCLE; + this.xpReward = 5; + this.moveControl = new Phantom.PhantomMoveControl(this); + this.lookControl = new Phantom.PhantomLookControl(this); +@@ -58,7 +63,7 @@ + + @Override + public boolean isFlapping() { +- return (this.getUniqueFlapTickOffset() + this.tickCount) % TICKS_PER_FLAP == 0; ++ return (this.getUniqueFlapTickOffset() + this.tickCount) % Phantom.TICKS_PER_FLAP == 0; + } + + @Override +@@ -77,30 +82,30 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(ID_SIZE, 0); ++ this.entityData.define(Phantom.ID_SIZE, 0); + } + + public void setPhantomSize(int phantomSize) { +- this.entityData.set(ID_SIZE, Mth.clamp(phantomSize, 0, 64)); ++ this.entityData.set(Phantom.ID_SIZE, Mth.clamp(phantomSize, 0, 64)); + } + + private void updatePhantomSizeInfo() { + this.refreshDimensions(); +- this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue((double)(6 + this.getPhantomSize())); ++ this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue((double) (6 + this.getPhantomSize())); + } + + public int getPhantomSize() { +- return this.entityData.get(ID_SIZE); ++ return (Integer) this.entityData.get(Phantom.ID_SIZE); + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return size.height * 0.35F; + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { +- if (ID_SIZE.equals(key)) { ++ if (Phantom.ID_SIZE.equals(key)) { + this.updatePhantomSizeInfo(); + } + +@@ -120,29 +125,22 @@ + public void tick() { + super.tick(); + if (this.level().isClientSide) { +- float cos = Mth.cos((float)(this.getUniqueFlapTickOffset() + this.tickCount) * 7.448451F * (float) (Math.PI / 180.0) + (float) Math.PI); +- float cos1 = Mth.cos((float)(this.getUniqueFlapTickOffset() + this.tickCount + 1) * 7.448451F * (float) (Math.PI / 180.0) + (float) Math.PI); +- if (cos > 0.0F && cos1 <= 0.0F) { +- this.level() +- .playLocalSound( +- this.getX(), +- this.getY(), +- this.getZ(), +- SoundEvents.PHANTOM_FLAP, +- this.getSoundSource(), +- 0.95F + this.random.nextFloat() * 0.05F, +- 0.95F + this.random.nextFloat() * 0.05F, +- false +- ); ++ float f = Mth.cos((float) (this.getUniqueFlapTickOffset() + this.tickCount) * 7.448451F * 0.017453292F + 3.1415927F); ++ float f1 = Mth.cos((float) (this.getUniqueFlapTickOffset() + this.tickCount + 1) * 7.448451F * 0.017453292F + 3.1415927F); ++ ++ if (f > 0.0F && f1 <= 0.0F) { ++ this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.PHANTOM_FLAP, this.getSoundSource(), 0.95F + this.random.nextFloat() * 0.05F, 0.95F + this.random.nextFloat() * 0.05F, false); + } + +- int phantomSize = this.getPhantomSize(); +- float f = Mth.cos(this.getYRot() * (float) (Math.PI / 180.0)) * (1.3F + 0.21F * (float)phantomSize); +- float f1 = Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)) * (1.3F + 0.21F * (float)phantomSize); +- float f2 = (0.3F + cos * 0.45F) * ((float)phantomSize * 0.2F + 1.0F); +- this.level().addParticle(ParticleTypes.MYCELIUM, this.getX() + (double)f, this.getY() + (double)f2, this.getZ() + (double)f1, 0.0, 0.0, 0.0); +- this.level().addParticle(ParticleTypes.MYCELIUM, this.getX() - (double)f, this.getY() + (double)f2, this.getZ() - (double)f1, 0.0, 0.0, 0.0); ++ int i = this.getPhantomSize(); ++ float f2 = Mth.cos(this.getYRot() * 0.017453292F) * (1.3F + 0.21F * (float) i); ++ float f3 = Mth.sin(this.getYRot() * 0.017453292F) * (1.3F + 0.21F * (float) i); ++ float f4 = (0.3F + f * 0.45F) * ((float) i * 0.2F + 1.0F); ++ ++ this.level().addParticle(ParticleTypes.MYCELIUM, this.getX() + (double) f2, this.getY() + (double) f4, this.getZ() + (double) f3, 0.0D, 0.0D, 0.0D); ++ this.level().addParticle(ParticleTypes.MYCELIUM, this.getX() - (double) f2, this.getY() + (double) f4, this.getZ() - (double) f3, 0.0D, 0.0D, 0.0D); + } ++ + } + + @Override +@@ -160,9 +158,7 @@ + } + + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + this.anchorPoint = this.blockPosition().above(5); + this.setPhantomSize(0); + return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); +@@ -213,8 +209,8 @@ + } + + @Override +- public MobType getMobType() { +- return MobType.UNDEAD; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.UNDEAD; + } + + @Override +@@ -228,15 +224,16 @@ + } + + @Override +- public EntityDimensions getDimensions(Pose pose) { +- int phantomSize = this.getPhantomSize(); +- EntityDimensions entityDimensions = super.getDimensions(pose); +- return entityDimensions.scale(1.0F + 0.15F * (float)phantomSize); ++ public EntityDimensions getDimensions(EntityPose pose) { ++ int i = this.getPhantomSize(); ++ EntityDimensions entitysize = super.getDimensions(pose); ++ ++ return entitysize.scale(1.0F + 0.15F * (float) i); + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height * 0.675F, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height * 0.675F, 0.0F); + } + + @Override +@@ -244,53 +241,102 @@ + return -0.125F; + } + +- static enum AttackPhase { +- CIRCLE, +- SWOOP; ++ private static enum AttackPhase { ++ ++ CIRCLE, SWOOP; ++ ++ private AttackPhase() {} + } + +- class PhantomAttackPlayerTargetGoal extends Goal { +- private final TargetingConditions attackTargeting = TargetingConditions.forCombat().range(64.0); +- private int nextScanTick = reducedTickDelay(20); ++ private class PhantomMoveControl extends MoveControl { + ++ private float speed = 0.1F; ++ ++ public PhantomMoveControl(Mob mob) { ++ super(mob); ++ } ++ + @Override +- public boolean canUse() { +- if (this.nextScanTick > 0) { +- this.nextScanTick--; +- return false; +- } else { +- this.nextScanTick = reducedTickDelay(60); +- List nearbyPlayers = Phantom.this.level() +- .getNearbyPlayers(this.attackTargeting, Phantom.this, Phantom.this.getBoundingBox().inflate(16.0, 64.0, 16.0)); +- if (!nearbyPlayers.isEmpty()) { +- nearbyPlayers.sort(Comparator.comparing(Entity::getY).reversed()); ++ public void tick() { ++ if (Phantom.this.horizontalCollision) { ++ Phantom.this.setYRot(Phantom.this.getYRot() + 180.0F); ++ this.speed = 0.1F; ++ } + +- for (Player player : nearbyPlayers) { +- if (Phantom.this.canAttack(player, TargetingConditions.DEFAULT)) { +- Phantom.this.setTarget(player); +- return true; +- } +- } ++ double d0 = Phantom.this.moveTargetPoint.x - Phantom.this.getX(); ++ double d1 = Phantom.this.moveTargetPoint.y - Phantom.this.getY(); ++ double d2 = Phantom.this.moveTargetPoint.z - Phantom.this.getZ(); ++ double d3 = Math.sqrt(d0 * d0 + d2 * d2); ++ ++ if (Math.abs(d3) > 9.999999747378752E-6D) { ++ double d4 = 1.0D - Math.abs(d1 * 0.699999988079071D) / d3; ++ ++ d0 *= d4; ++ d2 *= d4; ++ d3 = Math.sqrt(d0 * d0 + d2 * d2); ++ double d5 = Math.sqrt(d0 * d0 + d2 * d2 + d1 * d1); ++ float f = Phantom.this.getYRot(); ++ float f1 = (float) Mth.atan2(d2, d0); ++ float f2 = Mth.wrapDegrees(Phantom.this.getYRot() + 90.0F); ++ float f3 = Mth.wrapDegrees(f1 * 57.295776F); ++ ++ Phantom.this.setYRot(Mth.approachDegrees(f2, f3, 4.0F) - 90.0F); ++ Phantom.this.yBodyRot = Phantom.this.getYRot(); ++ if (Mth.degreesDifferenceAbs(f, Phantom.this.getYRot()) < 3.0F) { ++ this.speed = Mth.approach(this.speed, 1.8F, 0.005F * (1.8F / this.speed)); ++ } else { ++ this.speed = Mth.approach(this.speed, 0.2F, 0.025F); + } + +- return false; ++ float f4 = (float) (-(Mth.atan2(-d1, d3) * 57.2957763671875D)); ++ ++ Phantom.this.setXRot(f4); ++ float f5 = Phantom.this.getYRot() + 90.0F; ++ double d6 = (double) (this.speed * Mth.cos(f5 * 0.017453292F)) * Math.abs(d0 / d5); ++ double d7 = (double) (this.speed * Mth.sin(f5 * 0.017453292F)) * Math.abs(d2 / d5); ++ double d8 = (double) (this.speed * Mth.sin(f4 * 0.017453292F)) * Math.abs(d1 / d5); ++ Vec3 vec3d = Phantom.this.getDeltaMovement(); ++ ++ Phantom.this.setDeltaMovement(vec3d.add((new Vec3(d6, d8, d7)).subtract(vec3d).scale(0.2D))); + } ++ + } ++ } + ++ private class PhantomLookControl extends LookControl { ++ ++ public PhantomLookControl(Mob mob) { ++ super(mob); ++ } ++ + @Override +- public boolean canContinueToUse() { +- LivingEntity target = Phantom.this.getTarget(); +- return target != null && Phantom.this.canAttack(target, TargetingConditions.DEFAULT); ++ public void tick() {} ++ } ++ ++ private class PhantomBodyRotationControl extends BodyRotationControl { ++ ++ public PhantomBodyRotationControl(Mob mob) { ++ super(mob); + } ++ ++ @Override ++ public void clientTick() { ++ Phantom.this.yHeadRot = Phantom.this.yBodyRot; ++ Phantom.this.yBodyRot = Phantom.this.getYRot(); ++ } + } + +- class PhantomAttackStrategyGoal extends Goal { ++ private class PhantomAttackStrategyGoal extends Goal { ++ + private int nextSweepTick; + ++ PhantomAttackStrategyGoal() {} ++ + @Override + public boolean canUse() { +- LivingEntity target = Phantom.this.getTarget(); +- return target != null && Phantom.this.canAttack(target, TargetingConditions.DEFAULT); ++ LivingEntity entityliving = Phantom.this.getTarget(); ++ ++ return entityliving != null ? Phantom.this.canAttack(entityliving, TargetingConditions.DEFAULT) : false; + } + + @Override +@@ -302,15 +348,13 @@ + + @Override + public void stop() { +- Phantom.this.anchorPoint = Phantom.this.level() +- .getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, Phantom.this.anchorPoint) +- .above(10 + Phantom.this.random.nextInt(20)); ++ Phantom.this.anchorPoint = Phantom.this.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, Phantom.this.anchorPoint).above(10 + Phantom.this.random.nextInt(20)); + } + + @Override + public void tick() { + if (Phantom.this.attackPhase == Phantom.AttackPhase.CIRCLE) { +- this.nextSweepTick--; ++ --this.nextSweepTick; + if (this.nextSweepTick <= 0) { + Phantom.this.attackPhase = Phantom.AttackPhase.SWOOP; + this.setAnchorAboveTarget(); +@@ -318,36 +362,112 @@ + Phantom.this.playSound(SoundEvents.PHANTOM_SWOOP, 10.0F, 0.95F + Phantom.this.random.nextFloat() * 0.1F); + } + } ++ + } + + private void setAnchorAboveTarget() { + Phantom.this.anchorPoint = Phantom.this.getTarget().blockPosition().above(20 + Phantom.this.random.nextInt(20)); + if (Phantom.this.anchorPoint.getY() < Phantom.this.level().getSeaLevel()) { +- Phantom.this.anchorPoint = new BlockPos( +- Phantom.this.anchorPoint.getX(), Phantom.this.level().getSeaLevel() + 1, Phantom.this.anchorPoint.getZ() +- ); ++ Phantom.this.anchorPoint = new BlockPos(Phantom.this.anchorPoint.getX(), Phantom.this.level().getSeaLevel() + 1, Phantom.this.anchorPoint.getZ()); + } ++ + } + } + +- class PhantomBodyRotationControl extends BodyRotationControl { +- public PhantomBodyRotationControl(Mob mob) { +- super(mob); ++ private class PhantomSweepAttackGoal extends Phantom.h { ++ ++ private static final int CAT_SEARCH_TICK_DELAY = 20; ++ private boolean isScaredOfCat; ++ private int catSearchTick; ++ ++ PhantomSweepAttackGoal() { ++ super(); + } + + @Override +- public void clientTick() { +- Phantom.this.yHeadRot = Phantom.this.yBodyRot; +- Phantom.this.yBodyRot = Phantom.this.getYRot(); ++ public boolean canUse() { ++ return Phantom.this.getTarget() != null && Phantom.this.attackPhase == Phantom.AttackPhase.SWOOP; + } ++ ++ @Override ++ public boolean canContinueToUse() { ++ LivingEntity entityliving = Phantom.this.getTarget(); ++ ++ if (entityliving == null) { ++ return false; ++ } else if (!entityliving.isAlive()) { ++ return false; ++ } else { ++ if (entityliving instanceof Player) { ++ Player entityhuman = (Player) entityliving; ++ ++ if (entityliving.isSpectator() || entityhuman.isCreative()) { ++ return false; ++ } ++ } ++ ++ if (!this.canUse()) { ++ return false; ++ } else { ++ if (Phantom.this.tickCount > this.catSearchTick) { ++ this.catSearchTick = Phantom.this.tickCount + 20; ++ List list = Phantom.this.level().getEntitiesOfClass(Cat.class, Phantom.this.getBoundingBox().inflate(16.0D), EntitySelector.ENTITY_STILL_ALIVE); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Cat entitycat = (Cat) iterator.next(); ++ ++ entitycat.hiss(); ++ } ++ ++ this.isScaredOfCat = !list.isEmpty(); ++ } ++ ++ return !this.isScaredOfCat; ++ } ++ } ++ } ++ ++ @Override ++ public void start() {} ++ ++ @Override ++ public void stop() { ++ Phantom.this.setTarget((LivingEntity) null); ++ Phantom.this.attackPhase = Phantom.AttackPhase.CIRCLE; ++ } ++ ++ @Override ++ public void tick() { ++ LivingEntity entityliving = Phantom.this.getTarget(); ++ ++ if (entityliving != null) { ++ Phantom.this.moveTargetPoint = new Vec3(entityliving.getX(), entityliving.getY(0.5D), entityliving.getZ()); ++ if (Phantom.this.getBoundingBox().inflate(0.20000000298023224D).intersects(entityliving.getBoundingBox())) { ++ Phantom.this.doHurtTarget(entityliving); ++ Phantom.this.attackPhase = Phantom.AttackPhase.CIRCLE; ++ if (!Phantom.this.isSilent()) { ++ Phantom.this.level().levelEvent(1039, Phantom.this.blockPosition(), 0); ++ } ++ } else if (Phantom.this.horizontalCollision || Phantom.this.hurtTime > 0) { ++ Phantom.this.attackPhase = Phantom.AttackPhase.CIRCLE; ++ } ++ ++ } ++ } + } + +- class PhantomCircleAroundAnchorGoal extends Phantom.PhantomMoveTargetGoal { ++ private class PhantomCircleAroundAnchorGoal extends Phantom.h { ++ + private float angle; + private float distance; + private float height; + private float clockwise; + ++ PhantomCircleAroundAnchorGoal() { ++ super(); ++ } ++ + @Override + public boolean canUse() { + return Phantom.this.getTarget() == null || Phantom.this.attackPhase == Phantom.AttackPhase.CIRCLE; +@@ -368,7 +488,7 @@ + } + + if (Phantom.this.random.nextInt(this.adjustedTickDelay(250)) == 0) { +- this.distance++; ++ ++this.distance; + if (this.distance > 15.0F) { + this.distance = 5.0F; + this.clockwise = -this.clockwise; +@@ -376,7 +496,7 @@ + } + + if (Phantom.this.random.nextInt(this.adjustedTickDelay(450)) == 0) { +- this.angle = Phantom.this.random.nextFloat() * 2.0F * (float) Math.PI; ++ this.angle = Phantom.this.random.nextFloat() * 2.0F * 3.1415927F; + this.selectNext(); + } + +@@ -393,6 +513,7 @@ + this.height = Math.min(-1.0F, this.height); + this.selectNext(); + } ++ + } + + private void selectNext() { +@@ -400,147 +521,61 @@ + Phantom.this.anchorPoint = Phantom.this.blockPosition(); + } + +- this.angle = this.angle + this.clockwise * 15.0F * (float) (Math.PI / 180.0); +- Phantom.this.moveTargetPoint = Vec3.atLowerCornerOf(Phantom.this.anchorPoint) +- .add((double)(this.distance * Mth.cos(this.angle)), (double)(-4.0F + this.height), (double)(this.distance * Mth.sin(this.angle))); ++ this.angle += this.clockwise * 15.0F * 0.017453292F; ++ Phantom.this.moveTargetPoint = Vec3.atLowerCornerOf(Phantom.this.anchorPoint).add((double) (this.distance * Mth.cos(this.angle)), (double) (-4.0F + this.height), (double) (this.distance * Mth.sin(this.angle))); + } + } + +- class PhantomLookControl extends LookControl { +- public PhantomLookControl(Mob mob) { +- super(mob); +- } ++ private class PhantomAttackPlayerTargetGoal extends Goal { + +- @Override +- public void tick() { +- } +- } ++ private final TargetingConditions attackTargeting = TargetingConditions.forCombat().range(64.0D); ++ private int nextScanTick = reducedTickDelay(20); + +- class PhantomMoveControl extends MoveControl { +- private float speed = 0.1F; ++ PhantomAttackPlayerTargetGoal() {} + +- public PhantomMoveControl(Mob mob) { +- super(mob); +- } +- + @Override +- public void tick() { +- if (Phantom.this.horizontalCollision) { +- Phantom.this.setYRot(Phantom.this.getYRot() + 180.0F); +- this.speed = 0.1F; +- } +- +- double d = Phantom.this.moveTargetPoint.x - Phantom.this.getX(); +- double d1 = Phantom.this.moveTargetPoint.y - Phantom.this.getY(); +- double d2 = Phantom.this.moveTargetPoint.z - Phantom.this.getZ(); +- double squareRoot = Math.sqrt(d * d + d2 * d2); +- if (Math.abs(squareRoot) > 1.0E-5F) { +- double d3 = 1.0 - Math.abs(d1 * 0.7F) / squareRoot; +- double var26 = d * d3; +- double var27 = d2 * d3; +- squareRoot = Math.sqrt(var26 * var26 + var27 * var27); +- double squareRoot1 = Math.sqrt(var26 * var26 + var27 * var27 + d1 * d1); +- float yRot = Phantom.this.getYRot(); +- float f = (float)Mth.atan2(var27, var26); +- float f1 = Mth.wrapDegrees(Phantom.this.getYRot() + 90.0F); +- float f2 = Mth.wrapDegrees(f * (180.0F / (float)Math.PI)); +- Phantom.this.setYRot(Mth.approachDegrees(f1, f2, 4.0F) - 90.0F); +- Phantom.this.yBodyRot = Phantom.this.getYRot(); +- if (Mth.degreesDifferenceAbs(yRot, Phantom.this.getYRot()) < 3.0F) { +- this.speed = Mth.approach(this.speed, 1.8F, 0.005F * (1.8F / this.speed)); +- } else { +- this.speed = Mth.approach(this.speed, 0.2F, 0.025F); +- } +- +- float f3 = (float)(-(Mth.atan2(-d1, squareRoot) * 180.0F / (float)Math.PI)); +- Phantom.this.setXRot(f3); +- float f4 = Phantom.this.getYRot() + 90.0F; +- double d4 = (double)(this.speed * Mth.cos(f4 * (float) (Math.PI / 180.0))) * Math.abs(var26 / squareRoot1); +- double d5 = (double)(this.speed * Mth.sin(f4 * (float) (Math.PI / 180.0))) * Math.abs(var27 / squareRoot1); +- double d6 = (double)(this.speed * Mth.sin(f3 * (float) (Math.PI / 180.0))) * Math.abs(d1 / squareRoot1); +- Vec3 deltaMovement = Phantom.this.getDeltaMovement(); +- Phantom.this.setDeltaMovement(deltaMovement.add(new Vec3(d4, d6, d5).subtract(deltaMovement).scale(0.2))); +- } +- } +- } +- +- abstract class PhantomMoveTargetGoal extends Goal { +- public PhantomMoveTargetGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); +- } +- +- protected boolean touchingTarget() { +- return Phantom.this.moveTargetPoint.distanceToSqr(Phantom.this.getX(), Phantom.this.getY(), Phantom.this.getZ()) < 4.0; +- } +- } +- +- class PhantomSweepAttackGoal extends Phantom.PhantomMoveTargetGoal { +- private static final int CAT_SEARCH_TICK_DELAY = 20; +- private boolean isScaredOfCat; +- private int catSearchTick; +- +- @Override + public boolean canUse() { +- return Phantom.this.getTarget() != null && Phantom.this.attackPhase == Phantom.AttackPhase.SWOOP; +- } +- +- @Override +- public boolean canContinueToUse() { +- LivingEntity target = Phantom.this.getTarget(); +- if (target == null) { ++ if (this.nextScanTick > 0) { ++ --this.nextScanTick; + return false; +- } else if (!target.isAlive()) { +- return false; + } else { +- if (target instanceof Player player && (target.isSpectator() || player.isCreative())) { +- return false; +- } ++ this.nextScanTick = reducedTickDelay(60); ++ List list = Phantom.this.level().getNearbyPlayers(this.attackTargeting, Phantom.this, Phantom.this.getBoundingBox().inflate(16.0D, 64.0D, 16.0D)); + +- if (!this.canUse()) { +- return false; +- } else { +- if (Phantom.this.tickCount > this.catSearchTick) { +- this.catSearchTick = Phantom.this.tickCount + 20; +- List entitiesOfClass = Phantom.this.level() +- .getEntitiesOfClass(Cat.class, Phantom.this.getBoundingBox().inflate(16.0), EntitySelector.ENTITY_STILL_ALIVE); ++ if (!list.isEmpty()) { ++ list.sort(Comparator.comparing((Entity e) -> { return e.getY(); }).reversed()); // CraftBukkit - decompile error ++ Iterator iterator = list.iterator(); + +- for (Cat cat : entitiesOfClass) { +- cat.hiss(); +- } ++ while (iterator.hasNext()) { ++ Player entityhuman = (Player) iterator.next(); + +- this.isScaredOfCat = !entitiesOfClass.isEmpty(); ++ if (Phantom.this.canAttack(entityhuman, TargetingConditions.DEFAULT)) { ++ Phantom.this.setTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit - reason ++ return true; ++ } + } +- +- return !this.isScaredOfCat; + } ++ ++ return false; + } + } + + @Override +- public void start() { ++ public boolean canContinueToUse() { ++ LivingEntity entityliving = Phantom.this.getTarget(); ++ ++ return entityliving != null ? Phantom.this.canAttack(entityliving, TargetingConditions.DEFAULT) : false; + } ++ } + +- @Override +- public void stop() { +- Phantom.this.setTarget(null); +- Phantom.this.attackPhase = Phantom.AttackPhase.CIRCLE; ++ private abstract class h extends Goal { ++ ++ public h() { ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + +- @Override +- public void tick() { +- LivingEntity target = Phantom.this.getTarget(); +- if (target != null) { +- Phantom.this.moveTargetPoint = new Vec3(target.getX(), target.getY(0.5), target.getZ()); +- if (Phantom.this.getBoundingBox().inflate(0.2F).intersects(target.getBoundingBox())) { +- Phantom.this.doHurtTarget(target); +- Phantom.this.attackPhase = Phantom.AttackPhase.CIRCLE; +- if (!Phantom.this.isSilent()) { +- Phantom.this.level().levelEvent(1039, Phantom.this.blockPosition(), 0); +- } +- } else if (Phantom.this.horizontalCollision || Phantom.this.hurtTime > 0) { +- Phantom.this.attackPhase = Phantom.AttackPhase.CIRCLE; +- } +- } ++ protected boolean touchingTarget() { ++ return Phantom.this.moveTargetPoint.distanceToSqr(Phantom.this.getX(), Phantom.this.getY(), Phantom.this.getZ()) < 4.0D; + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Ravager.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Ravager.java.patch new file mode 100644 index 0000000000..2819d9219e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Ravager.java.patch @@ -0,0 +1,313 @@ +--- a/net/minecraft/world/entity/monster/Ravager.java ++++ b/net/minecraft/world/entity/monster/Ravager.java +@@ -1,5 +1,7 @@ + package net.minecraft.world.entity.monster; + ++import java.util.Iterator; ++import java.util.List; + import java.util.function.Predicate; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +@@ -34,21 +36,28 @@ + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.LeavesBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class Ravager extends Raider { +- private static final Predicate NO_RAVAGER_AND_ALIVE = entity -> entity.isAlive() && !(entity instanceof Ravager); +- private static final double BASE_MOVEMENT_SPEED = 0.3; +- private static final double ATTACK_MOVEMENT_SPEED = 0.35; ++ ++ private static final Predicate NO_RAVAGER_AND_ALIVE = (entity) -> { ++ return entity.isAlive() && !(entity instanceof Ravager); ++ }; ++ private static final double BASE_MOVEMENT_SPEED = 0.3D; ++ private static final double ATTACK_MOVEMENT_SPEED = 0.35D; + private static final int STUNNED_COLOR = 8356754; +- private static final double STUNNED_COLOR_BLUE = 0.5725490196078431; +- private static final double STUNNED_COLOR_GREEN = 0.5137254901960784; +- private static final double STUNNED_COLOR_RED = 0.4980392156862745; ++ private static final double STUNNED_COLOR_BLUE = 0.5725490196078431D; ++ private static final double STUNNED_COLOR_GREEN = 0.5137254901960784D; ++ private static final double STUNNED_COLOR_RED = 0.4980392156862745D; + private static final int ATTACK_DURATION = 10; + public static final int STUN_DURATION = 40; + private int attackTick; +@@ -66,13 +75,15 @@ + protected void registerGoals() { + super.registerGoals(); + this.goalSelector.addGoal(0, new FloatGoal(this)); +- this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0, true)); +- this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.4)); ++ this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0D, true)); ++ this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.4D)); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); +- this.targetSelector.addGoal(2, new HurtByTargetGoal(this, Raider.class).setAlertOthers()); ++ this.targetSelector.addGoal(2, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers()); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, true)); +- this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, true, entity -> !entity.isBaby())); ++ this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, true, (entityliving) -> { ++ return !entityliving.isBaby(); ++ })); + this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); + } + +@@ -80,20 +91,15 @@ + protected void updateControlFlags() { + boolean flag = !(this.getControllingPassenger() instanceof Mob) || this.getControllingPassenger().getType().is(EntityTypeTags.RAIDERS); + boolean flag1 = !(this.getVehicle() instanceof Boat); +- this.goalSelector.setControlFlag(Goal.Flag.MOVE, flag); +- this.goalSelector.setControlFlag(Goal.Flag.JUMP, flag && flag1); +- this.goalSelector.setControlFlag(Goal.Flag.LOOK, flag); +- this.goalSelector.setControlFlag(Goal.Flag.TARGET, flag); ++ ++ this.goalSelector.setControlFlag(Goal.Type.MOVE, flag); ++ this.goalSelector.setControlFlag(Goal.Type.JUMP, flag && flag1); ++ this.goalSelector.setControlFlag(Goal.Type.LOOK, flag); ++ this.goalSelector.setControlFlag(Goal.Type.TARGET, flag); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes() +- .add(Attributes.MAX_HEALTH, 100.0) +- .add(Attributes.MOVEMENT_SPEED, 0.3) +- .add(Attributes.KNOCKBACK_RESISTANCE, 0.75) +- .add(Attributes.ATTACK_DAMAGE, 12.0) +- .add(Attributes.ATTACK_KNOCKBACK, 1.5) +- .add(Attributes.FOLLOW_RANGE, 32.0); ++ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 100.0D).add(Attributes.MOVEMENT_SPEED, 0.3D).add(Attributes.KNOCKBACK_RESISTANCE, 0.75D).add(Attributes.ATTACK_DAMAGE, 12.0D).add(Attributes.ATTACK_KNOCKBACK, 1.5D).add(Attributes.FOLLOW_RANGE, 32.0D); + } + + @Override +@@ -123,8 +129,8 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.0625F * f, -0.0625F * f); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.0625F * f, -0.0625F * f); + } + + @Override +@@ -132,24 +138,31 @@ + super.aiStep(); + if (this.isAlive()) { + if (this.isImmobile()) { +- this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.0); ++ this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.0D); + } else { +- double d = this.getTarget() != null ? 0.35 : 0.3; +- double baseValue = this.getAttribute(Attributes.MOVEMENT_SPEED).getBaseValue(); +- this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(Mth.lerp(0.1, baseValue, d)); ++ double d0 = this.getTarget() != null ? 0.35D : 0.3D; ++ double d1 = this.getAttribute(Attributes.MOVEMENT_SPEED).getBaseValue(); ++ ++ this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(Mth.lerp(0.1D, d1, d0)); + } + + if (this.horizontalCollision && this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { + boolean flag = false; +- AABB aABB = this.getBoundingBox().inflate(0.2); ++ AABB axisalignedbb = this.getBoundingBox().inflate(0.2D); ++ Iterator iterator = BlockPos.betweenClosed(Mth.floor(axisalignedbb.minX), Mth.floor(axisalignedbb.minY), Mth.floor(axisalignedbb.minZ), Mth.floor(axisalignedbb.maxX), Mth.floor(axisalignedbb.maxY), Mth.floor(axisalignedbb.maxZ)).iterator(); + +- for (BlockPos blockPos : BlockPos.betweenClosed( +- Mth.floor(aABB.minX), Mth.floor(aABB.minY), Mth.floor(aABB.minZ), Mth.floor(aABB.maxX), Mth.floor(aABB.maxY), Mth.floor(aABB.maxZ) +- )) { +- BlockState blockState = this.level().getBlockState(blockPos); +- Block block = blockState.getBlock(); ++ while (iterator.hasNext()) { ++ BlockPos blockposition = (BlockPos) iterator.next(); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); ++ Block block = iblockdata.getBlock(); ++ + if (block instanceof LeavesBlock) { +- flag = this.level().destroyBlock(blockPos, true, this) || flag; ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState())) { ++ continue; ++ } ++ // CraftBukkit end ++ flag = this.level().destroyBlock(blockposition, true, this) || flag; + } + } + +@@ -159,38 +172,37 @@ + } + + if (this.roarTick > 0) { +- this.roarTick--; ++ --this.roarTick; + if (this.roarTick == 10) { + this.roar(); + } + } + + if (this.attackTick > 0) { +- this.attackTick--; ++ --this.attackTick; + } + + if (this.stunnedTick > 0) { +- this.stunnedTick--; ++ --this.stunnedTick; + this.stunEffect(); + if (this.stunnedTick == 0) { + this.playSound(SoundEvents.RAVAGER_ROAR, 1.0F, 1.0F); + this.roarTick = 20; + } + } ++ + } + } + + private void stunEffect() { + if (this.random.nextInt(6) == 0) { +- double d = this.getX() +- - (double)this.getBbWidth() * Math.sin((double)(this.yBodyRot * (float) (Math.PI / 180.0))) +- + (this.random.nextDouble() * 0.6 - 0.3); +- double d1 = this.getY() + (double)this.getBbHeight() - 0.3; +- double d2 = this.getZ() +- + (double)this.getBbWidth() * Math.cos((double)(this.yBodyRot * (float) (Math.PI / 180.0))) +- + (this.random.nextDouble() * 0.6 - 0.3); +- this.level().addParticle(ParticleTypes.ENTITY_EFFECT, d, d1, d2, 0.4980392156862745, 0.5137254901960784, 0.5725490196078431); ++ double d0 = this.getX() - (double) this.getBbWidth() * Math.sin((double) (this.yBodyRot * 0.017453292F)) + (this.random.nextDouble() * 0.6D - 0.3D); ++ double d1 = this.getY() + (double) this.getBbHeight() - 0.3D; ++ double d2 = this.getZ() + (double) this.getBbWidth() * Math.cos((double) (this.yBodyRot * 0.017453292F)) + (this.random.nextDouble() * 0.6D - 0.3D); ++ ++ this.level().addParticle(ParticleTypes.ENTITY_EFFECT, d0, d1, d2, 0.4980392156862745D, 0.5137254901960784D, 0.5725490196078431D); + } ++ + } + + @Override +@@ -200,16 +212,16 @@ + + @Override + public boolean hasLineOfSight(Entity entity) { +- return this.stunnedTick <= 0 && this.roarTick <= 0 && super.hasLineOfSight(entity); ++ return this.stunnedTick <= 0 && this.roarTick <= 0 ? super.hasLineOfSight(entity) : false; + } + + @Override + protected void blockedByShield(LivingEntity entity) { + if (this.roarTick == 0) { +- if (this.random.nextDouble() < 0.5) { ++ if (this.random.nextDouble() < 0.5D) { + this.stunnedTick = 40; + this.playSound(SoundEvents.RAVAGER_STUNNED, 1.0F, 1.0F); +- this.level().broadcastEntityEvent(this, (byte)39); ++ this.level().broadcastEntityEvent(this, (byte) 39); + entity.push(this); + } else { + this.strongKnockback(entity); +@@ -217,36 +229,43 @@ + + entity.hurtMarked = true; + } ++ + } + + private void roar() { + if (this.isAlive()) { +- for (LivingEntity livingEntity : this.level().getEntitiesOfClass(LivingEntity.class, this.getBoundingBox().inflate(4.0), NO_RAVAGER_AND_ALIVE)) { +- if (!(livingEntity instanceof AbstractIllager)) { +- livingEntity.hurt(this.damageSources().mobAttack(this), 6.0F); +- } ++ List list = this.level().getEntitiesOfClass(LivingEntity.class, this.getBoundingBox().inflate(4.0D), Ravager.NO_RAVAGER_AND_ALIVE); + +- this.strongKnockback(livingEntity); ++ LivingEntity entityliving; ++ ++ for (Iterator iterator = list.iterator(); iterator.hasNext(); this.strongKnockback(entityliving)) { ++ entityliving = (LivingEntity) iterator.next(); ++ if (!(entityliving instanceof AbstractIllager)) { ++ entityliving.hurt(this.damageSources().mobAttack(this), 6.0F); ++ } + } + +- Vec3 center = this.getBoundingBox().getCenter(); ++ Vec3 vec3d = this.getBoundingBox().getCenter(); + +- for (int i = 0; i < 40; i++) { +- double d = this.random.nextGaussian() * 0.2; +- double d1 = this.random.nextGaussian() * 0.2; +- double d2 = this.random.nextGaussian() * 0.2; +- this.level().addParticle(ParticleTypes.POOF, center.x, center.y, center.z, d, d1, d2); ++ for (int i = 0; i < 40; ++i) { ++ double d0 = this.random.nextGaussian() * 0.2D; ++ double d1 = this.random.nextGaussian() * 0.2D; ++ double d2 = this.random.nextGaussian() * 0.2D; ++ ++ this.level().addParticle(ParticleTypes.POOF, vec3d.x, vec3d.y, vec3d.z, d0, d1, d2); + } + + this.gameEvent(GameEvent.ENTITY_ACTION); + } ++ + } + + private void strongKnockback(Entity entity) { +- double d = entity.getX() - this.getX(); ++ double d0 = entity.getX() - this.getX(); + double d1 = entity.getZ() - this.getZ(); +- double max = Math.max(d * d + d1 * d1, 0.001); +- entity.push(d / max * 4.0, 0.2, d1 / max * 4.0); ++ double d2 = Math.max(d0 * d0 + d1 * d1, 0.001D); ++ ++ entity.push(d0 / d2 * 4.0D, 0.2D, d1 / d2 * 4.0D); + } + + @Override +@@ -276,7 +295,7 @@ + @Override + public boolean doHurtTarget(Entity entity) { + this.attackTick = 10; +- this.level().broadcastEntityEvent(this, (byte)4); ++ this.level().broadcastEntityEvent(this, (byte) 4); + this.playSound(SoundEvents.RAVAGER_ATTACK, 1.0F, 1.0F); + return super.doHurtTarget(entity); + } +@@ -298,7 +317,7 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.RAVAGER_STEP, 0.15F, 1.0F); + } + +@@ -308,8 +327,7 @@ + } + + @Override +- public void applyRaidBuffs(int wave, boolean unusedFalse) { +- } ++ public void applyRaidBuffs(int wave, boolean unusedFalse) {} + + @Override + public boolean canBeLeader() { +@@ -318,7 +336,8 @@ + + @Override + protected AABB getAttackBoundingBox() { +- AABB aABB = super.getAttackBoundingBox(); +- return aABB.deflate(0.05, 0.0, 0.05); ++ AABB axisalignedbb = super.getAttackBoundingBox(); ++ ++ return axisalignedbb.deflate(0.05D, 0.0D, 0.05D); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Shulker.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Shulker.java.patch new file mode 100644 index 0000000000..109f273887 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Shulker.java.patch @@ -0,0 +1,853 @@ +--- a/net/minecraft/world/entity/monster/Shulker.java ++++ b/net/minecraft/world/entity/monster/Shulker.java +@@ -1,6 +1,8 @@ + package net.minecraft.world.entity.monster; + + import java.util.EnumSet; ++import java.util.Iterator; ++import java.util.List; + import java.util.Optional; + import java.util.UUID; + import javax.annotation.Nullable; +@@ -23,14 +25,14 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMoveType; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.VariantHolder; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -50,20 +52,26 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.entity.EntityTypeTest; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Shulker extends AbstractGolem implements VariantHolder>, Enemy { ++// CraftBukkit start ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.entity.EntityTeleportEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ ++public class Shulker extends AbstractGolem implements VariantHolder>, IMonster { ++ + private static final UUID COVERED_ARMOR_MODIFIER_UUID = UUID.fromString("7E0292F2-9434-48D5-A29F-9583AF7DF27F"); +- private static final AttributeModifier COVERED_ARMOR_MODIFIER = new AttributeModifier( +- COVERED_ARMOR_MODIFIER_UUID, "Covered armor bonus", 20.0, AttributeModifier.Operation.ADDITION +- ); ++ private static final AttributeModifier COVERED_ARMOR_MODIFIER = new AttributeModifier(Shulker.COVERED_ARMOR_MODIFIER_UUID, "Covered armor bonus", 20.0D, AttributeModifier.Operation.ADDITION); + protected static final EntityDataAccessor DATA_ATTACH_FACE_ID = SynchedEntityData.defineId(Shulker.class, EntityDataSerializers.DIRECTION); + protected static final EntityDataAccessor DATA_PEEK_ID = SynchedEntityData.defineId(Shulker.class, EntityDataSerializers.BYTE); +- protected static final EntityDataAccessor DATA_COLOR_ID = SynchedEntityData.defineId(Shulker.class, EntityDataSerializers.BYTE); ++ public static final EntityDataAccessor DATA_COLOR_ID = SynchedEntityData.defineId(Shulker.class, EntityDataSerializers.BYTE); + private static final int TELEPORT_STEPS = 6; + private static final byte NO_COLOR = 16; + private static final byte DEFAULT_COLOR = 16; +@@ -71,9 +79,10 @@ + private static final int OTHER_SHULKER_SCAN_RADIUS = 8; + private static final int OTHER_SHULKER_LIMIT = 5; + private static final float PEEK_PER_TICK = 0.05F; +- static final Vector3f FORWARD = Util.make(() -> { +- Vec3i normal = Direction.SOUTH.getNormal(); +- return new Vector3f((float)normal.getX(), (float)normal.getY(), (float)normal.getZ()); ++ static final Vector3f FORWARD = (Vector3f) Util.make(() -> { ++ Vec3i baseblockposition = Direction.SOUTH.getNormal(); ++ ++ return new Vector3f((float) baseblockposition.getX(), (float) baseblockposition.getY(), (float) baseblockposition.getZ()); + }); + private float currentPeekAmountO; + private float currentPeekAmount; +@@ -94,7 +103,7 @@ + this.goalSelector.addGoal(4, new Shulker.ShulkerAttackGoal()); + this.goalSelector.addGoal(7, new Shulker.ShulkerPeekGoal()); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this, this.getClass()).setAlertOthers()); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{this.getClass()})).setAlertOthers()); + this.targetSelector.addGoal(2, new Shulker.ShulkerNearestAttackGoal(this)); + this.targetSelector.addGoal(3, new Shulker.ShulkerDefenseAttackGoal(this)); + } +@@ -119,6 +128,7 @@ + if (!this.isClosed()) { + super.playAmbientSound(); + } ++ + } + + @Override +@@ -134,13 +144,13 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_ATTACH_FACE_ID, Direction.DOWN); +- this.entityData.define(DATA_PEEK_ID, (byte)0); +- this.entityData.define(DATA_COLOR_ID, (byte)16); ++ this.entityData.define(Shulker.DATA_ATTACH_FACE_ID, Direction.DOWN); ++ this.entityData.define(Shulker.DATA_PEEK_ID, (byte) 0); ++ this.entityData.define(Shulker.DATA_COLOR_ID, (byte) 16); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 30.0); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 30.0D); + } + + @Override +@@ -152,18 +162,19 @@ + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); + this.setAttachFace(Direction.from3DDataValue(compound.getByte("AttachFace"))); +- this.entityData.set(DATA_PEEK_ID, compound.getByte("Peek")); ++ this.entityData.set(Shulker.DATA_PEEK_ID, compound.getByte("Peek")); + if (compound.contains("Color", 99)) { +- this.entityData.set(DATA_COLOR_ID, compound.getByte("Color")); ++ this.entityData.set(Shulker.DATA_COLOR_ID, compound.getByte("Color")); + } ++ + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- compound.putByte("AttachFace", (byte)this.getAttachFace().get3DDataValue()); +- compound.putByte("Peek", this.entityData.get(DATA_PEEK_ID)); +- compound.putByte("Color", this.entityData.get(DATA_COLOR_ID)); ++ compound.putByte("AttachFace", (byte) this.getAttachFace().get3DDataValue()); ++ compound.putByte("Peek", (Byte) this.entityData.get(Shulker.DATA_PEEK_ID)); ++ compound.putByte("Color", (Byte) this.entityData.get(Shulker.DATA_COLOR_ID)); + } + + @Override +@@ -179,37 +190,42 @@ + + if (this.level().isClientSide) { + if (this.clientSideTeleportInterpolation > 0) { +- this.clientSideTeleportInterpolation--; ++ --this.clientSideTeleportInterpolation; + } else { + this.clientOldAttachPosition = null; + } + } ++ + } + + private void findNewAttachment() { +- Direction direction = this.findAttachableSurface(this.blockPosition()); +- if (direction != null) { +- this.setAttachFace(direction); ++ Direction enumdirection = this.findAttachableSurface(this.blockPosition()); ++ ++ if (enumdirection != null) { ++ this.setAttachFace(enumdirection); + } else { + this.teleportSomewhere(); + } ++ + } + + @Override + protected AABB makeBoundingBox() { +- float physicalPeek = getPhysicalPeek(this.currentPeekAmount); +- Direction opposite = this.getAttachFace().getOpposite(); +- float f = this.getType().getWidth() / 2.0F; +- return getProgressAabb(opposite, physicalPeek).move(this.getX() - (double)f, this.getY(), this.getZ() - (double)f); ++ float f = getPhysicalPeek(this.currentPeekAmount); ++ Direction enumdirection = this.getAttachFace().getOpposite(); ++ float f1 = this.getType().getWidth() / 2.0F; ++ ++ return getProgressAabb(enumdirection, f).move(this.getX() - (double) f1, this.getY(), this.getZ() - (double) f1); + } + + private static float getPhysicalPeek(float peek) { +- return 0.5F - Mth.sin((0.5F + peek) * (float) Math.PI) * 0.5F; ++ return 0.5F - Mth.sin((0.5F + peek) * 3.1415927F) * 0.5F; + } + + private boolean updatePeekAmount() { + this.currentPeekAmountO = this.currentPeekAmount; +- float f = (float)this.getRawPeekAmount() * 0.01F; ++ float f = (float) this.getRawPeekAmount() * 0.01F; ++ + if (this.currentPeekAmount == f) { + return false; + } else { +@@ -225,24 +241,25 @@ + + private void onPeekAmountChange() { + this.reapplyPosition(); +- float physicalPeek = getPhysicalPeek(this.currentPeekAmount); +- float physicalPeek1 = getPhysicalPeek(this.currentPeekAmountO); +- Direction opposite = this.getAttachFace().getOpposite(); +- float f = physicalPeek - physicalPeek1; +- if (!(f <= 0.0F)) { +- for (Entity entity : this.level() +- .getEntities( +- this, +- getProgressDeltaAabb(opposite, physicalPeek1, physicalPeek).move(this.getX() - 0.5, this.getY(), this.getZ() - 0.5), +- EntitySelector.NO_SPECTATORS.and(entity1 -> !entity1.isPassengerOfSameVehicle(this)) +- )) { ++ float f = getPhysicalPeek(this.currentPeekAmount); ++ float f1 = getPhysicalPeek(this.currentPeekAmountO); ++ Direction enumdirection = this.getAttachFace().getOpposite(); ++ float f2 = f - f1; ++ ++ if (f2 > 0.0F) { ++ List list = this.level().getEntities((Entity) this, getProgressDeltaAabb(enumdirection, f1, f).move(this.getX() - 0.5D, this.getY(), this.getZ() - 0.5D), EntitySelector.NO_SPECTATORS.and((entity) -> { ++ return !entity.isPassengerOfSameVehicle(this); ++ })); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ + if (!(entity instanceof Shulker) && !entity.noPhysics) { +- entity.move( +- MoverType.SHULKER, +- new Vec3((double)(f * (float)opposite.getStepX()), (double)(f * (float)opposite.getStepY()), (double)(f * (float)opposite.getStepZ())) +- ); ++ entity.move(EnumMoveType.SHULKER, new Vec3((double) (f2 * (float) enumdirection.getStepX()), (double) (f2 * (float) enumdirection.getStepY()), (double) (f2 * (float) enumdirection.getStepZ()))); + } + } ++ + } + } + +@@ -251,11 +268,10 @@ + } + + public static AABB getProgressDeltaAabb(Direction direction, float delta, float deltaO) { +- double d = (double)Math.max(delta, deltaO); +- double d1 = (double)Math.min(delta, deltaO); +- return new AABB(BlockPos.ZERO) +- .expandTowards((double)direction.getStepX() * d, (double)direction.getStepY() * d, (double)direction.getStepZ() * d) +- .contract((double)(-direction.getStepX()) * (1.0 + d1), (double)(-direction.getStepY()) * (1.0 + d1), (double)(-direction.getStepZ()) * (1.0 + d1)); ++ double d0 = (double) Math.max(delta, deltaO); ++ double d1 = (double) Math.min(delta, deltaO); ++ ++ return (new AABB(BlockPos.ZERO)).expandTowards((double) direction.getStepX() * d0, (double) direction.getStepY() * d0, (double) direction.getStepZ() * d0).contract((double) (-direction.getStepX()) * (1.0D + d1), (double) (-direction.getStepY()) * (1.0D + d1), (double) (-direction.getStepZ()) * (1.0D + d1)); + } + + @Override +@@ -282,9 +298,7 @@ + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + this.setYRot(0.0F); + this.yHeadRot = this.getYRot(); + this.setOldPosAndRot(); +@@ -292,12 +306,13 @@ + } + + @Override +- public void move(MoverType type, Vec3 pos) { +- if (type == MoverType.SHULKER_BOX) { ++ public void move(EnumMoveType type, Vec3 pos) { ++ if (type == EnumMoveType.SHULKER_BOX) { + this.teleportSomewhere(); + } else { + super.move(type, pos); + } ++ + } + + @Override +@@ -306,39 +321,46 @@ + } + + @Override +- public void setDeltaMovement(Vec3 deltaMovement) { +- } ++ public void setDeltaMovement(Vec3 deltaMovement) {} + + @Override +- public void setPos(double x, double y, double z) { +- BlockPos blockPos = this.blockPosition(); ++ public void setPos(double x, double d1, double y) { ++ BlockPos blockposition = this.blockPosition(); ++ + if (this.isPassenger()) { +- super.setPos(x, y, z); ++ super.setPos(x, d1, y); + } else { +- super.setPos((double)Mth.floor(x) + 0.5, (double)Mth.floor(y + 0.5), (double)Mth.floor(z) + 0.5); ++ super.setPos((double) Mth.floor(x) + 0.5D, (double) Mth.floor(d1 + 0.5D), (double) Mth.floor(y) + 0.5D); + } + + if (this.tickCount != 0) { +- BlockPos blockPos1 = this.blockPosition(); +- if (!blockPos1.equals(blockPos)) { +- this.entityData.set(DATA_PEEK_ID, (byte)0); ++ BlockPos blockposition1 = this.blockPosition(); ++ ++ if (!blockposition1.equals(blockposition)) { ++ this.entityData.set(Shulker.DATA_PEEK_ID, (byte) 0); + this.hasImpulse = true; +- if (this.level().isClientSide && !this.isPassenger() && !blockPos1.equals(this.clientOldAttachPosition)) { +- this.clientOldAttachPosition = blockPos; ++ if (this.level().isClientSide && !this.isPassenger() && !blockposition1.equals(this.clientOldAttachPosition)) { ++ this.clientOldAttachPosition = blockposition; + this.clientSideTeleportInterpolation = 6; + this.xOld = this.getX(); + this.yOld = this.getY(); + this.zOld = this.getZ(); + } + } ++ + } + } + + @Nullable + protected Direction findAttachableSurface(BlockPos pos) { +- for (Direction direction : Direction.values()) { +- if (this.canStayAt(pos, direction)) { +- return direction; ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; ++ ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ ++ if (this.canStayAt(pos, enumdirection)) { ++ return enumdirection; + } + } + +@@ -349,49 +371,56 @@ + if (this.isPositionBlocked(pos)) { + return false; + } else { +- Direction opposite = facing.getOpposite(); +- if (!this.level().loadedAndEntityCanStandOnFace(pos.relative(facing), this, opposite)) { ++ Direction enumdirection1 = facing.getOpposite(); ++ ++ if (!this.level().loadedAndEntityCanStandOnFace(pos.relative(facing), this, enumdirection1)) { + return false; + } else { +- AABB aABB = getProgressAabb(opposite, 1.0F).move(pos).deflate(1.0E-6); +- return this.level().noCollision(this, aABB); ++ AABB axisalignedbb = getProgressAabb(enumdirection1, 1.0F).move(pos).deflate(1.0E-6D); ++ ++ return this.level().noCollision(this, axisalignedbb); + } + } + } + + private boolean isPositionBlocked(BlockPos pos) { +- BlockState blockState = this.level().getBlockState(pos); +- if (blockState.isAir()) { ++ IBlockData iblockdata = this.level().getBlockState(pos); ++ ++ if (iblockdata.isAir()) { + return false; + } else { +- boolean flag = blockState.is(Blocks.MOVING_PISTON) && pos.equals(this.blockPosition()); ++ boolean flag = iblockdata.is(Blocks.MOVING_PISTON) && pos.equals(this.blockPosition()); ++ + return !flag; + } + } + + protected boolean teleportSomewhere() { + if (!this.isNoAi() && this.isAlive()) { +- BlockPos blockPos = this.blockPosition(); ++ BlockPos blockposition = this.blockPosition(); + +- for (int i = 0; i < 5; i++) { +- BlockPos blockPos1 = blockPos.offset( +- Mth.randomBetweenInclusive(this.random, -8, 8), +- Mth.randomBetweenInclusive(this.random, -8, 8), +- Mth.randomBetweenInclusive(this.random, -8, 8) +- ); +- if (blockPos1.getY() > this.level().getMinBuildHeight() +- && this.level().isEmptyBlock(blockPos1) +- && this.level().getWorldBorder().isWithinBounds(blockPos1) +- && this.level().noCollision(this, new AABB(blockPos1).deflate(1.0E-6))) { +- Direction direction = this.findAttachableSurface(blockPos1); +- if (direction != null) { ++ for (int i = 0; i < 5; ++i) { ++ BlockPos blockposition1 = blockposition.offset(Mth.randomBetweenInclusive(this.random, -8, 8), Mth.randomBetweenInclusive(this.random, -8, 8), Mth.randomBetweenInclusive(this.random, -8, 8)); ++ ++ if (blockposition1.getY() > this.level().getMinBuildHeight() && this.level().isEmptyBlock(blockposition1) && this.level().getWorldBorder().isWithinBounds(blockposition1) && this.level().noCollision(this, (new AABB(blockposition1)).deflate(1.0E-6D))) { ++ Direction enumdirection = this.findAttachableSurface(blockposition1); ++ ++ if (enumdirection != null) { ++ // CraftBukkit start ++ EntityTeleportEvent teleportEvent = CraftEventFactory.callEntityTeleportEvent(this, blockposition1.getX(), blockposition1.getY(), blockposition1.getZ()); ++ if (teleportEvent.isCancelled()) { ++ return false; ++ } else { ++ blockposition1 = CraftLocation.toBlockPosition(teleportEvent.getTo()); ++ } ++ // CraftBukkit end + this.unRide(); +- this.setAttachFace(direction); ++ this.setAttachFace(enumdirection); + this.playSound(SoundEvents.SHULKER_TELEPORT, 1.0F, 1.0F); +- this.setPos((double)blockPos1.getX() + 0.5, (double)blockPos1.getY(), (double)blockPos1.getZ() + 0.5); +- this.level().gameEvent(GameEvent.TELEPORT, blockPos, GameEvent.Context.of(this)); +- this.entityData.set(DATA_PEEK_ID, (byte)0); +- this.setTarget(null); ++ this.setPos((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY(), (double) blockposition1.getZ() + 0.5D); ++ this.level().gameEvent(GameEvent.TELEPORT, blockposition, GameEvent.Context.of((Entity) this)); ++ this.entityData.set(Shulker.DATA_PEEK_ID, (byte) 0); ++ this.setTarget((LivingEntity) null); + return true; + } + } +@@ -404,17 +433,19 @@ + } + + @Override +- public void lerpTo(double d, double d1, double d2, float f, float f1, int i) { ++ public void lerpTo(double d0, double d1, double d2, float f, float f1, int i) { + this.lerpSteps = 0; +- this.setPos(d, d1, d2); ++ this.setPos(d0, d1, d2); + this.setRot(f, f1); + } + + @Override + public boolean hurt(DamageSource source, float amount) { ++ Entity entity; ++ + if (this.isClosed()) { +- Entity directEntity = source.getDirectEntity(); +- if (directEntity instanceof AbstractArrow) { ++ entity = source.getDirectEntity(); ++ if (entity instanceof AbstractArrow) { + return false; + } + } +@@ -422,11 +453,11 @@ + if (!super.hurt(source, amount)) { + return false; + } else { +- if ((double)this.getHealth() < (double)this.getMaxHealth() * 0.5 && this.random.nextInt(4) == 0) { ++ if ((double) this.getHealth() < (double) this.getMaxHealth() * 0.5D && this.random.nextInt(4) == 0) { + this.teleportSomewhere(); + } else if (source.is(DamageTypeTags.IS_PROJECTILE)) { +- Entity directEntity = source.getDirectEntity(); +- if (directEntity != null && directEntity.getType() == EntityType.SHULKER_BULLET) { ++ entity = source.getDirectEntity(); ++ if (entity != null && entity.getType() == EntityType.SHULKER_BULLET) { + this.hitByShulkerBullet(); + } + } +@@ -440,18 +471,22 @@ + } + + private void hitByShulkerBullet() { +- Vec3 vec3 = this.position(); +- AABB boundingBox = this.getBoundingBox(); ++ Vec3 vec3d = this.position(); ++ AABB axisalignedbb = this.getBoundingBox(); ++ + if (!this.isClosed() && this.teleportSomewhere()) { +- int size = this.level().getEntities(EntityType.SHULKER, boundingBox.inflate(8.0), Entity::isAlive).size(); +- float f = (float)(size - 1) / 5.0F; +- if (!(this.level().random.nextFloat() < f)) { +- Shulker shulker = EntityType.SHULKER.create(this.level()); +- if (shulker != null) { +- shulker.setVariant(this.getVariant()); +- shulker.moveTo(vec3); +- this.level().addFreshEntity(shulker); ++ int i = this.level().getEntities((EntityTypeTest) EntityType.SHULKER, axisalignedbb.inflate(8.0D), Entity::isAlive).size(); ++ float f = (float) (i - 1) / 5.0F; ++ ++ if (this.level().random.nextFloat() >= f) { ++ Shulker entityshulker = (Shulker) EntityType.SHULKER.create(this.level()); ++ ++ if (entityshulker != null) { ++ entityshulker.setVariant(this.getVariant()); ++ entityshulker.moveTo(vec3d); ++ this.level().addFreshEntity(entityshulker, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - the mysteries of life + } ++ + } + } + } +@@ -462,31 +497,31 @@ + } + + public Direction getAttachFace() { +- return this.entityData.get(DATA_ATTACH_FACE_ID); ++ return (Direction) this.entityData.get(Shulker.DATA_ATTACH_FACE_ID); + } + +- private void setAttachFace(Direction attachFace) { +- this.entityData.set(DATA_ATTACH_FACE_ID, attachFace); ++ public void setAttachFace(Direction attachFace) { ++ this.entityData.set(Shulker.DATA_ATTACH_FACE_ID, attachFace); + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { +- if (DATA_ATTACH_FACE_ID.equals(key)) { ++ if (Shulker.DATA_ATTACH_FACE_ID.equals(key)) { + this.setBoundingBox(this.makeBoundingBox()); + } + + super.onSyncedDataUpdated(key); + } + +- private int getRawPeekAmount() { +- return this.entityData.get(DATA_PEEK_ID); ++ public int getRawPeekAmount() { ++ return (Byte) this.entityData.get(Shulker.DATA_PEEK_ID); + } + +- void setRawPeekAmount(int peekAmount) { ++ public void setRawPeekAmount(int peekAmount) { + if (!this.level().isClientSide) { +- this.getAttribute(Attributes.ARMOR).removeModifier(COVERED_ARMOR_MODIFIER.getId()); ++ this.getAttribute(Attributes.ARMOR).removeModifier(Shulker.COVERED_ARMOR_MODIFIER.getId()); + if (peekAmount == 0) { +- this.getAttribute(Attributes.ARMOR).addPermanentModifier(COVERED_ARMOR_MODIFIER); ++ this.getAttribute(Attributes.ARMOR).addPermanentModifier(Shulker.COVERED_ARMOR_MODIFIER); + this.playSound(SoundEvents.SHULKER_CLOSE, 1.0F, 1.0F); + this.gameEvent(GameEvent.CONTAINER_CLOSE); + } else { +@@ -495,7 +530,7 @@ + } + } + +- this.entityData.set(DATA_PEEK_ID, (byte)peekAmount); ++ this.entityData.set(Shulker.DATA_PEEK_ID, (byte) peekAmount); + } + + public float getClientPeekAmount(float partialTick) { +@@ -503,7 +538,7 @@ + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.5F; + } + +@@ -525,26 +560,28 @@ + } + + @Override +- public void push(Entity entity) { +- } ++ public void push(Entity entity) {} + + public Optional getRenderPosition(float partial) { + if (this.clientOldAttachPosition != null && this.clientSideTeleportInterpolation > 0) { +- double d = (double)((float)this.clientSideTeleportInterpolation - partial) / 6.0; +- d *= d; +- BlockPos blockPos = this.blockPosition(); +- double d1 = (double)(blockPos.getX() - this.clientOldAttachPosition.getX()) * d; +- double d2 = (double)(blockPos.getY() - this.clientOldAttachPosition.getY()) * d; +- double d3 = (double)(blockPos.getZ() - this.clientOldAttachPosition.getZ()) * d; ++ double d0 = (double) ((float) this.clientSideTeleportInterpolation - partial) / 6.0D; ++ ++ d0 *= d0; ++ BlockPos blockposition = this.blockPosition(); ++ double d1 = (double) (blockposition.getX() - this.clientOldAttachPosition.getX()) * d0; ++ double d2 = (double) (blockposition.getY() - this.clientOldAttachPosition.getY()) * d0; ++ double d3 = (double) (blockposition.getZ() - this.clientOldAttachPosition.getZ()) * d0; ++ + return Optional.of(new Vec3(-d1, -d2, -d3)); + } else { + return Optional.empty(); + } + } + +- @Override + public void setVariant(Optional variant) { +- this.entityData.set(DATA_COLOR_ID, variant.map(color -> (byte)color.getId()).orElse((byte)16)); ++ this.entityData.set(Shulker.DATA_COLOR_ID, (Byte) variant.map((enumcolor) -> { ++ return (byte) enumcolor.getId(); ++ }).orElse((byte) 16)); + } + + @Override +@@ -554,21 +591,57 @@ + + @Nullable + public DyeColor getColor() { +- byte b = this.entityData.get(DATA_COLOR_ID); +- return b != 16 && b <= 15 ? DyeColor.byId(b) : null; ++ byte b0 = (Byte) this.entityData.get(Shulker.DATA_COLOR_ID); ++ ++ return b0 != 16 && b0 <= 15 ? DyeColor.byId(b0) : null; + } + +- class ShulkerAttackGoal extends Goal { ++ private class ShulkerLookControl extends LookControl { ++ ++ public ShulkerLookControl(Mob mob) { ++ super(mob); ++ } ++ ++ @Override ++ protected void clampHeadRotationToBody() {} ++ ++ @Override ++ protected Optional getYRotD() { ++ Direction enumdirection = Shulker.this.getAttachFace().getOpposite(); ++ Vector3f vector3f = enumdirection.getRotation().transform(new Vector3f(Shulker.FORWARD)); ++ Vec3i baseblockposition = enumdirection.getNormal(); ++ Vector3f vector3f1 = new Vector3f((float) baseblockposition.getX(), (float) baseblockposition.getY(), (float) baseblockposition.getZ()); ++ ++ vector3f1.cross(vector3f); ++ double d0 = this.wantedX - this.mob.getX(); ++ double d1 = this.wantedY - this.mob.getEyeY(); ++ double d2 = this.wantedZ - this.mob.getZ(); ++ Vector3f vector3f2 = new Vector3f((float) d0, (float) d1, (float) d2); ++ float f = vector3f1.dot(vector3f2); ++ float f1 = vector3f.dot(vector3f2); ++ ++ return Math.abs(f) <= 1.0E-5F && Math.abs(f1) <= 1.0E-5F ? Optional.empty() : Optional.of((float) (Mth.atan2((double) (-f), (double) f1) * 57.2957763671875D)); ++ } ++ ++ @Override ++ protected Optional getXRotD() { ++ return Optional.of(0.0F); ++ } ++ } ++ ++ private class ShulkerAttackGoal extends Goal { ++ + private int attackTime; + + public ShulkerAttackGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + } + + @Override + public boolean canUse() { +- LivingEntity target = Shulker.this.getTarget(); +- return target != null && target.isAlive() && Shulker.this.level().getDifficulty() != Difficulty.PEACEFUL; ++ LivingEntity entityliving = Shulker.this.getTarget(); ++ ++ return entityliving != null && entityliving.isAlive() ? Shulker.this.level().getDifficulty() != Difficulty.PEACEFUL : false; + } + + @Override +@@ -590,22 +663,21 @@ + @Override + public void tick() { + if (Shulker.this.level().getDifficulty() != Difficulty.PEACEFUL) { +- this.attackTime--; +- LivingEntity target = Shulker.this.getTarget(); +- if (target != null) { +- Shulker.this.getLookControl().setLookAt(target, 180.0F, 180.0F); +- double d = Shulker.this.distanceToSqr(target); +- if (d < 400.0) { ++ --this.attackTime; ++ LivingEntity entityliving = Shulker.this.getTarget(); ++ ++ if (entityliving != null) { ++ Shulker.this.getLookControl().setLookAt(entityliving, 180.0F, 180.0F); ++ double d0 = Shulker.this.distanceToSqr((Entity) entityliving); ++ ++ if (d0 < 400.0D) { + if (this.attackTime <= 0) { + this.attackTime = 20 + Shulker.this.random.nextInt(10) * 20 / 2; +- Shulker.this.level() +- .addFreshEntity(new ShulkerBullet(Shulker.this.level(), Shulker.this, target, Shulker.this.getAttachFace().getAxis())); +- Shulker.this.playSound( +- SoundEvents.SHULKER_SHOOT, 2.0F, (Shulker.this.random.nextFloat() - Shulker.this.random.nextFloat()) * 0.2F + 1.0F +- ); ++ Shulker.this.level().addFreshEntity(new ShulkerBullet(Shulker.this.level(), Shulker.this, entityliving, Shulker.this.getAttachFace().getAxis())); ++ Shulker.this.playSound(SoundEvents.SHULKER_SHOOT, 2.0F, (Shulker.this.random.nextFloat() - Shulker.this.random.nextFloat()) * 0.2F + 1.0F); + } + } else { +- Shulker.this.setTarget(null); ++ Shulker.this.setTarget((LivingEntity) null); + } + + super.tick(); +@@ -614,126 +686,89 @@ + } + } + +- static class ShulkerBodyRotationControl extends BodyRotationControl { +- public ShulkerBodyRotationControl(Mob mob) { +- super(mob); +- } ++ private class ShulkerPeekGoal extends Goal { + +- @Override +- public void clientTick() { +- } +- } ++ private int peekTime; + +- static class ShulkerDefenseAttackGoal extends NearestAttackableTargetGoal { +- public ShulkerDefenseAttackGoal(Shulker shulker) { +- super(shulker, LivingEntity.class, 10, true, false, entity -> entity instanceof Enemy); +- } ++ ShulkerPeekGoal() {} + + @Override + public boolean canUse() { +- return this.mob.getTeam() != null && super.canUse(); ++ return Shulker.this.getTarget() == null && Shulker.this.random.nextInt(reducedTickDelay(40)) == 0 && Shulker.this.canStayAt(Shulker.this.blockPosition(), Shulker.this.getAttachFace()); + } + + @Override +- protected AABB getTargetSearchArea(double targetDistance) { +- Direction attachFace = ((Shulker)this.mob).getAttachFace(); +- if (attachFace.getAxis() == Direction.Axis.X) { +- return this.mob.getBoundingBox().inflate(4.0, targetDistance, targetDistance); +- } else { +- return attachFace.getAxis() == Direction.Axis.Z +- ? this.mob.getBoundingBox().inflate(targetDistance, targetDistance, 4.0) +- : this.mob.getBoundingBox().inflate(targetDistance, 4.0, targetDistance); +- } ++ public boolean canContinueToUse() { ++ return Shulker.this.getTarget() == null && this.peekTime > 0; + } +- } + +- class ShulkerLookControl extends LookControl { +- public ShulkerLookControl(Mob mob) { +- super(mob); +- } +- + @Override +- protected void clampHeadRotationToBody() { ++ public void start() { ++ this.peekTime = this.adjustedTickDelay(20 * (1 + Shulker.this.random.nextInt(3))); ++ Shulker.this.setRawPeekAmount(30); + } + + @Override +- protected Optional getYRotD() { +- Direction opposite = Shulker.this.getAttachFace().getOpposite(); +- Vector3f vector3f = opposite.getRotation().transform(new Vector3f(Shulker.FORWARD)); +- Vec3i normal = opposite.getNormal(); +- Vector3f vector3f1 = new Vector3f((float)normal.getX(), (float)normal.getY(), (float)normal.getZ()); +- vector3f1.cross(vector3f); +- double d = this.wantedX - this.mob.getX(); +- double d1 = this.wantedY - this.mob.getEyeY(); +- double d2 = this.wantedZ - this.mob.getZ(); +- Vector3f vector3f2 = new Vector3f((float)d, (float)d1, (float)d2); +- float f = vector3f1.dot(vector3f2); +- float f1 = vector3f.dot(vector3f2); +- return !(Math.abs(f) > 1.0E-5F) && !(Math.abs(f1) > 1.0E-5F) +- ? Optional.empty() +- : Optional.of((float)(Mth.atan2((double)(-f), (double)f1) * 180.0F / (float)Math.PI)); ++ public void stop() { ++ if (Shulker.this.getTarget() == null) { ++ Shulker.this.setRawPeekAmount(0); ++ } ++ + } + + @Override +- protected Optional getXRotD() { +- return Optional.of(0.0F); ++ public void tick() { ++ --this.peekTime; + } + } + +- class ShulkerNearestAttackGoal extends NearestAttackableTargetGoal { +- public ShulkerNearestAttackGoal(Shulker shulker) { +- super(shulker, Player.class, true); ++ private class ShulkerNearestAttackGoal extends NearestAttackableTargetGoal { ++ ++ public ShulkerNearestAttackGoal(Shulker entityshulker) { ++ super(entityshulker, Player.class, true); + } + + @Override + public boolean canUse() { +- return Shulker.this.level().getDifficulty() != Difficulty.PEACEFUL && super.canUse(); ++ return Shulker.this.level().getDifficulty() == Difficulty.PEACEFUL ? false : super.canUse(); + } + + @Override + protected AABB getTargetSearchArea(double targetDistance) { +- Direction attachFace = ((Shulker)this.mob).getAttachFace(); +- if (attachFace.getAxis() == Direction.Axis.X) { +- return this.mob.getBoundingBox().inflate(4.0, targetDistance, targetDistance); +- } else { +- return attachFace.getAxis() == Direction.Axis.Z +- ? this.mob.getBoundingBox().inflate(targetDistance, targetDistance, 4.0) +- : this.mob.getBoundingBox().inflate(targetDistance, 4.0, targetDistance); +- } ++ Direction enumdirection = ((Shulker) this.mob).getAttachFace(); ++ ++ return enumdirection.getAxis() == Direction.Axis.X ? this.mob.getBoundingBox().inflate(4.0D, targetDistance, targetDistance) : (enumdirection.getAxis() == Direction.Axis.Z ? this.mob.getBoundingBox().inflate(targetDistance, targetDistance, 4.0D) : this.mob.getBoundingBox().inflate(targetDistance, 4.0D, targetDistance)); + } + } + +- class ShulkerPeekGoal extends Goal { +- private int peekTime; ++ private static class ShulkerDefenseAttackGoal extends NearestAttackableTargetGoal { + +- @Override +- public boolean canUse() { +- return Shulker.this.getTarget() == null +- && Shulker.this.random.nextInt(reducedTickDelay(40)) == 0 +- && Shulker.this.canStayAt(Shulker.this.blockPosition(), Shulker.this.getAttachFace()); ++ public ShulkerDefenseAttackGoal(Shulker shulker) { ++ super(shulker, LivingEntity.class, 10, true, false, (entityliving) -> { ++ return entityliving instanceof IMonster; ++ }); + } + + @Override +- public boolean canContinueToUse() { +- return Shulker.this.getTarget() == null && this.peekTime > 0; ++ public boolean canUse() { ++ return this.mob.getTeam() == null ? false : super.canUse(); + } + + @Override +- public void start() { +- this.peekTime = this.adjustedTickDelay(20 * (1 + Shulker.this.random.nextInt(3))); +- Shulker.this.setRawPeekAmount(30); ++ protected AABB getTargetSearchArea(double targetDistance) { ++ Direction enumdirection = ((Shulker) this.mob).getAttachFace(); ++ ++ return enumdirection.getAxis() == Direction.Axis.X ? this.mob.getBoundingBox().inflate(4.0D, targetDistance, targetDistance) : (enumdirection.getAxis() == Direction.Axis.Z ? this.mob.getBoundingBox().inflate(targetDistance, targetDistance, 4.0D) : this.mob.getBoundingBox().inflate(targetDistance, 4.0D, targetDistance)); + } ++ } + +- @Override +- public void stop() { +- if (Shulker.this.getTarget() == null) { +- Shulker.this.setRawPeekAmount(0); +- } ++ private static class ShulkerBodyRotationControl extends BodyRotationControl { ++ ++ public ShulkerBodyRotationControl(Mob mob) { ++ super(mob); + } + + @Override +- public void tick() { +- this.peekTime--; +- } ++ public void clientTick() {} + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Silverfish.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Silverfish.java.patch new file mode 100644 index 0000000000..1e5713e0bb --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Silverfish.java.patch @@ -0,0 +1,282 @@ +--- a/net/minecraft/world/entity/monster/Silverfish.java ++++ b/net/minecraft/world/entity/monster/Silverfish.java +@@ -11,10 +11,10 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.Pose; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.ClimbOnTopOfPowderSnowGoal; +@@ -31,10 +31,15 @@ + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.InfestedBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class Silverfish extends Monster { ++ + @Nullable + private Silverfish.SilverfishWakeUpFriendsGoal friendsGoal; + +@@ -48,19 +53,19 @@ + this.goalSelector.addGoal(1, new FloatGoal(this)); + this.goalSelector.addGoal(1, new ClimbOnTopOfPowderSnowGoal(this, this.level())); + this.goalSelector.addGoal(3, this.friendsGoal); +- this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0, false)); ++ this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0D, false)); + this.goalSelector.addGoal(5, new Silverfish.SilverfishMergeWithStoneGoal(this)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers()); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[0])).setAlertOthers()); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.13F; + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 8.0).add(Attributes.MOVEMENT_SPEED, 0.25).add(Attributes.ATTACK_DAMAGE, 1.0); ++ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 8.0D).add(Attributes.MOVEMENT_SPEED, 0.25D).add(Attributes.ATTACK_DAMAGE, 1.0D); + } + + @Override +@@ -84,7 +89,7 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.SILVERFISH_STEP, 0.15F, 1.0F); + } + +@@ -118,35 +123,95 @@ + return InfestedBlock.isCompatibleHostBlock(level.getBlockState(pos.below())) ? 10.0F : super.getWalkTargetValue(pos, level); + } + +- public static boolean checkSilverfishSpawnRules( +- EntityType silverfish, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random +- ) { ++ public static boolean checkSilverfishSpawnRules(EntityType silverfish, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { + if (checkAnyLightMonsterSpawnRules(silverfish, level, spawnType, pos, random)) { +- Player nearestPlayer = level.getNearestPlayer((double)pos.getX() + 0.5, (double)pos.getY() + 0.5, (double)pos.getZ() + 0.5, 5.0, true); +- return nearestPlayer == null; ++ Player entityhuman = level.getNearestPlayer((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, 5.0D, true); ++ ++ return entityhuman == null; + } else { + return false; + } + } + + @Override +- public MobType getMobType() { +- return MobType.ARTHROPOD; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.ARTHROPOD; + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height - 0.0625F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.0625F * f, 0.0F); + } + +- static class SilverfishMergeWithStoneGoal extends RandomStrollGoal { ++ private static class SilverfishWakeUpFriendsGoal extends Goal { ++ ++ private final Silverfish silverfish; ++ private int lookForFriends; ++ ++ public SilverfishWakeUpFriendsGoal(Silverfish silverfish) { ++ this.silverfish = silverfish; ++ } ++ ++ public void notifyHurt() { ++ if (this.lookForFriends == 0) { ++ this.lookForFriends = this.adjustedTickDelay(20); ++ } ++ ++ } ++ ++ @Override ++ public boolean canUse() { ++ return this.lookForFriends > 0; ++ } ++ ++ @Override ++ public void tick() { ++ --this.lookForFriends; ++ if (this.lookForFriends <= 0) { ++ Level world = this.silverfish.level(); ++ RandomSource randomsource = this.silverfish.getRandom(); ++ BlockPos blockposition = this.silverfish.blockPosition(); ++ ++ for (int i = 0; i <= 5 && i >= -5; i = (i <= 0 ? 1 : 0) - i) { ++ for (int j = 0; j <= 10 && j >= -10; j = (j <= 0 ? 1 : 0) - j) { ++ for (int k = 0; k <= 10 && k >= -10; k = (k <= 0 ? 1 : 0) - k) { ++ BlockPos blockposition1 = blockposition.offset(j, i, k); ++ IBlockData iblockdata = world.getBlockState(blockposition1); ++ Block block = iblockdata.getBlock(); ++ ++ if (block instanceof InfestedBlock) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.silverfish, blockposition1, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState())) { ++ continue; ++ } ++ // CraftBukkit end ++ if (world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ world.destroyBlock(blockposition1, true, this.silverfish); ++ } else { ++ world.setBlock(blockposition1, ((InfestedBlock) block).hostStateByInfested(world.getBlockState(blockposition1)), 3); ++ } ++ ++ if (randomsource.nextBoolean()) { ++ return; ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ } ++ } ++ ++ private static class SilverfishMergeWithStoneGoal extends RandomStrollGoal { ++ + @Nullable + private Direction selectedDirection; + private boolean doMerge; + + public SilverfishMergeWithStoneGoal(Silverfish silverfish) { +- super(silverfish, 1.0, 10); +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ super(silverfish, 1.0D, 10); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +@@ -156,12 +221,14 @@ + } else if (!this.mob.getNavigation().isDone()) { + return false; + } else { +- RandomSource random = this.mob.getRandom(); +- if (this.mob.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && random.nextInt(reducedTickDelay(10)) == 0) { +- this.selectedDirection = Direction.getRandom(random); +- BlockPos blockPos = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5, this.mob.getZ()).relative(this.selectedDirection); +- BlockState blockState = this.mob.level().getBlockState(blockPos); +- if (InfestedBlock.isCompatibleHostBlock(blockState)) { ++ RandomSource randomsource = this.mob.getRandom(); ++ ++ if (this.mob.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && randomsource.nextInt(reducedTickDelay(10)) == 0) { ++ this.selectedDirection = Direction.getRandom(randomsource); ++ BlockPos blockposition = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5D, this.mob.getZ()).relative(this.selectedDirection); ++ IBlockData iblockdata = this.mob.level().getBlockState(blockposition); ++ ++ if (InfestedBlock.isCompatibleHostBlock(iblockdata)) { + this.doMerge = true; + return true; + } +@@ -174,7 +241,7 @@ + + @Override + public boolean canContinueToUse() { +- return !this.doMerge && super.canContinueToUse(); ++ return this.doMerge ? false : super.canContinueToUse(); + } + + @Override +@@ -182,66 +249,22 @@ + if (!this.doMerge) { + super.start(); + } else { +- LevelAccessor levelAccessor = this.mob.level(); +- BlockPos blockPos = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5, this.mob.getZ()).relative(this.selectedDirection); +- BlockState blockState = levelAccessor.getBlockState(blockPos); +- if (InfestedBlock.isCompatibleHostBlock(blockState)) { +- levelAccessor.setBlock(blockPos, InfestedBlock.infestedStateByHost(blockState), 3); ++ Level world = this.mob.level(); ++ BlockPos blockposition = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5D, this.mob.getZ()).relative(this.selectedDirection); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ ++ if (InfestedBlock.isCompatibleHostBlock(iblockdata)) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition, InfestedBlock.infestedStateByHost(iblockdata))) { ++ return; ++ } ++ // CraftBukkit end ++ world.setBlock(blockposition, InfestedBlock.infestedStateByHost(iblockdata), 3); + this.mob.spawnAnim(); + this.mob.discard(); + } +- } +- } +- } + +- static class SilverfishWakeUpFriendsGoal extends Goal { +- private final Silverfish silverfish; +- private int lookForFriends; +- +- public SilverfishWakeUpFriendsGoal(Silverfish silverfish) { +- this.silverfish = silverfish; +- } +- +- public void notifyHurt() { +- if (this.lookForFriends == 0) { +- this.lookForFriends = this.adjustedTickDelay(20); + } + } +- +- @Override +- public boolean canUse() { +- return this.lookForFriends > 0; +- } +- +- @Override +- public void tick() { +- this.lookForFriends--; +- if (this.lookForFriends <= 0) { +- Level level = this.silverfish.level(); +- RandomSource random = this.silverfish.getRandom(); +- BlockPos blockPos = this.silverfish.blockPosition(); +- +- for (int i = 0; i <= 5 && i >= -5; i = (i <= 0 ? 1 : 0) - i) { +- for (int i1 = 0; i1 <= 10 && i1 >= -10; i1 = (i1 <= 0 ? 1 : 0) - i1) { +- for (int i2 = 0; i2 <= 10 && i2 >= -10; i2 = (i2 <= 0 ? 1 : 0) - i2) { +- BlockPos blockPos1 = blockPos.offset(i1, i, i2); +- BlockState blockState = level.getBlockState(blockPos1); +- Block block = blockState.getBlock(); +- if (block instanceof InfestedBlock) { +- if (level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- level.destroyBlock(blockPos1, true, this.silverfish); +- } else { +- level.setBlock(blockPos1, ((InfestedBlock)block).hostStateByInfested(level.getBlockState(blockPos1)), 3); +- } +- +- if (random.nextBoolean()) { +- return; +- } +- } +- } +- } +- } +- } +- } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Skeleton.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Skeleton.java.patch new file mode 100644 index 0000000000..ede8670387 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Skeleton.java.patch @@ -0,0 +1,103 @@ +--- a/net/minecraft/world/entity/monster/Skeleton.java ++++ b/net/minecraft/world/entity/monster/Skeleton.java +@@ -7,16 +7,20 @@ + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.world.damagesource.DamageSource; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Items; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + + public class Skeleton extends AbstractSkeleton { ++ + private static final int TOTAL_CONVERSION_TIME = 300; +- private static final EntityDataAccessor DATA_STRAY_CONVERSION_ID = SynchedEntityData.defineId(Skeleton.class, EntityDataSerializers.BOOLEAN); ++ public static final EntityDataAccessor DATA_STRAY_CONVERSION_ID = SynchedEntityData.defineId(Skeleton.class, EntityDataSerializers.BOOLEAN); + public static final String CONVERSION_TAG = "StrayConversionTime"; + private int inPowderSnowTime; +- private int conversionTime; ++ public int conversionTime; + + public Skeleton(EntityType entityType, Level level) { + super(entityType, level); +@@ -25,15 +29,15 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.getEntityData().define(DATA_STRAY_CONVERSION_ID, false); ++ this.getEntityData().define(Skeleton.DATA_STRAY_CONVERSION_ID, false); + } + + public boolean isFreezeConverting() { +- return this.getEntityData().get(DATA_STRAY_CONVERSION_ID); ++ return (Boolean) this.getEntityData().get(Skeleton.DATA_STRAY_CONVERSION_ID); + } + + public void setFreezeConverting(boolean isFrozen) { +- this.entityData.set(DATA_STRAY_CONVERSION_ID, isFrozen); ++ this.entityData.set(Skeleton.DATA_STRAY_CONVERSION_ID, isFrozen); + } + + @Override +@@ -46,12 +50,12 @@ + if (!this.level().isClientSide && this.isAlive() && !this.isNoAi()) { + if (this.isInPowderSnow) { + if (this.isFreezeConverting()) { +- this.conversionTime--; ++ --this.conversionTime; + if (this.conversionTime < 0) { + this.doFreezeConversion(); + } + } else { +- this.inPowderSnowTime++; ++ ++this.inPowderSnowTime; + if (this.inPowderSnowTime >= 140) { + this.startFreezeConversion(300); + } +@@ -77,18 +81,20 @@ + if (compound.contains("StrayConversionTime", 99) && compound.getInt("StrayConversionTime") > -1) { + this.startFreezeConversion(compound.getInt("StrayConversionTime")); + } ++ + } + +- private void startFreezeConversion(int conversionTime) { ++ public void startFreezeConversion(int conversionTime) { + this.conversionTime = conversionTime; + this.setFreezeConverting(true); + } + + protected void doFreezeConversion() { +- this.convertTo(EntityType.STRAY, true); ++ this.convertTo(EntityType.STRAY, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.FROZEN, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.FROZEN); // CraftBukkit - add spawn and transform reasons + if (!this.isSilent()) { +- this.level().levelEvent(null, 1048, this.blockPosition(), 0); ++ this.level().levelEvent((Player) null, 1048, this.blockPosition(), 0); + } ++ + } + + @Override +@@ -119,9 +125,16 @@ + @Override + protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { + super.dropCustomDeathLoot(source, looting, recentlyHit); +- if (source.getEntity() instanceof Creeper creeper && creeper.canDropMobsSkull()) { +- creeper.increaseDroppedSkulls(); +- this.spawnAtLocation(Items.SKELETON_SKULL); ++ Entity entity = source.getEntity(); ++ ++ if (entity instanceof Creeper) { ++ Creeper entitycreeper = (Creeper) entity; ++ ++ if (entitycreeper.canDropMobsSkull()) { ++ entitycreeper.increaseDroppedSkulls(); ++ this.spawnAtLocation((IMaterial) Items.SKELETON_SKULL); ++ } + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Slime.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Slime.java.patch new file mode 100644 index 0000000000..7808f88a35 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Slime.java.patch @@ -0,0 +1,665 @@ +--- a/net/minecraft/world/entity/monster/Slime.java ++++ b/net/minecraft/world/entity/monster/Slime.java +@@ -23,12 +23,12 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.MoveControl; + import net.minecraft.world.entity.ai.goal.Goal; +@@ -44,7 +44,16 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Slime extends Mob implements Enemy { ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTransformEvent; ++import org.bukkit.event.entity.SlimeSplitEvent; ++// CraftBukkit end ++ ++public class Slime extends Mob implements IMonster { ++ + private static final EntityDataAccessor ID_SIZE = SynchedEntityData.defineId(Slime.class, EntityDataSerializers.INT); + public static final int MIN_SIZE = 1; + public static final int MAX_SIZE = 127; +@@ -65,10 +74,9 @@ + this.goalSelector.addGoal(2, new Slime.SlimeAttackGoal(this)); + this.goalSelector.addGoal(3, new Slime.SlimeRandomDirectionGoal(this)); + this.goalSelector.addGoal(5, new Slime.SlimeKeepOnJumpingGoal(this)); +- this.targetSelector +- .addGoal( +- 1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, livingEntity -> Math.abs(livingEntity.getY() - this.getY()) <= 4.0) +- ); ++ this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (entityliving) -> { ++ return Math.abs(entityliving.getY() - this.getY()) <= 4.0D; ++ })); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); + } + +@@ -80,27 +88,28 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(ID_SIZE, 1); ++ this.entityData.define(Slime.ID_SIZE, 1); + } + + @VisibleForTesting + public void setSize(int size, boolean resetHealth) { +- int i = Mth.clamp(size, 1, 127); +- this.entityData.set(ID_SIZE, i); ++ int j = Mth.clamp(size, 1, 127); ++ ++ this.entityData.set(Slime.ID_SIZE, j); + this.reapplyPosition(); + this.refreshDimensions(); +- this.getAttribute(Attributes.MAX_HEALTH).setBaseValue((double)(i * i)); +- this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue((double)(0.2F + 0.1F * (float)i)); +- this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue((double)i); ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue((double) (j * j)); ++ this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue((double) (0.2F + 0.1F * (float) j)); ++ this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue((double) j); + if (resetHealth) { + this.setHealth(this.getMaxHealth()); + } + +- this.xpReward = i; ++ this.xpReward = j; + } + + public int getSize() { +- return this.entityData.get(ID_SIZE); ++ return (Integer) this.entityData.get(Slime.ID_SIZE); + } + + @Override +@@ -132,18 +141,19 @@ + + @Override + public void tick() { +- this.squish = this.squish + (this.targetSquish - this.squish) * 0.5F; ++ this.squish += (this.targetSquish - this.squish) * 0.5F; + this.oSquish = this.squish; + super.tick(); + if (this.onGround() && !this.wasOnGround) { +- int size = this.getSize(); ++ int i = this.getSize(); + +- for (int i = 0; i < size * 8; i++) { +- float f = this.random.nextFloat() * (float) (Math.PI * 2); ++ for (int j = 0; j < i * 8; ++j) { ++ float f = this.random.nextFloat() * 6.2831855F; + float f1 = this.random.nextFloat() * 0.5F + 0.5F; +- float f2 = Mth.sin(f) * (float)size * 0.5F * f1; +- float f3 = Mth.cos(f) * (float)size * 0.5F * f1; +- this.level().addParticle(this.getParticleType(), this.getX() + (double)f2, this.getY(), this.getZ() + (double)f3, 0.0, 0.0, 0.0); ++ float f2 = Mth.sin(f) * (float) i * 0.5F * f1; ++ float f3 = Mth.cos(f) * (float) i * 0.5F * f1; ++ ++ this.level().addParticle(this.getParticleType(), this.getX() + (double) f2, this.getY(), this.getZ() + (double) f3, 0.0D, 0.0D, 0.0D); + } + + this.playSound(this.getSquishSound(), this.getSoundVolume(), ((this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F) / 0.8F); +@@ -166,16 +176,17 @@ + + @Override + public void refreshDimensions() { +- double x = this.getX(); +- double y = this.getY(); +- double z = this.getZ(); ++ double d0 = this.getX(); ++ double d1 = this.getY(); ++ double d2 = this.getZ(); ++ + super.refreshDimensions(); +- this.setPos(x, y, z); ++ this.setPos(d0, d1, d2); + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { +- if (ID_SIZE.equals(key)) { ++ if (Slime.ID_SIZE.equals(key)) { + this.refreshDimensions(); + this.setYRot(this.yHeadRot); + this.yBodyRot = this.yHeadRot; +@@ -189,36 +200,60 @@ + + @Override + public EntityType getType() { +- return (EntityType)super.getType(); ++ return (EntityType) super.getType(); // CraftBukkit - decompile error + } + + @Override + public void remove(Entity.RemovalReason reason) { +- int size = this.getSize(); +- if (!this.level().isClientSide && size > 1 && this.isDeadOrDying()) { +- Component customName = this.getCustomName(); +- boolean isNoAi = this.isNoAi(); +- float f = (float)size / 4.0F; +- int i = size / 2; +- int i1 = 2 + this.random.nextInt(3); ++ int i = this.getSize(); + +- for (int i2 = 0; i2 < i1; i2++) { +- float f1 = ((float)(i2 % 2) - 0.5F) * f; +- float f2 = ((float)(i2 / 2) - 0.5F) * f; +- Slime slime = this.getType().create(this.level()); +- if (slime != null) { ++ if (!this.level().isClientSide && i > 1 && this.isDeadOrDying()) { ++ Component ichatbasecomponent = this.getCustomName(); ++ boolean flag = this.isNoAi(); ++ float f = (float) i / 4.0F; ++ int j = i / 2; ++ int k = 2 + this.random.nextInt(3); ++ ++ // CraftBukkit start ++ SlimeSplitEvent event = new SlimeSplitEvent((org.bukkit.entity.Slime) this.getBukkitEntity(), k); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled() && event.getCount() > 0) { ++ k = event.getCount(); ++ } else { ++ super.remove(reason); ++ return; ++ } ++ List slimes = new ArrayList<>(j); ++ // CraftBukkit end ++ ++ for (int l = 0; l < k; ++l) { ++ float f1 = ((float) (l % 2) - 0.5F) * f; ++ float f2 = ((float) (l / 2) - 0.5F) * f; ++ Slime entityslime = (Slime) this.getType().create(this.level()); ++ ++ if (entityslime != null) { + if (this.isPersistenceRequired()) { +- slime.setPersistenceRequired(); ++ entityslime.setPersistenceRequired(); + } + +- slime.setCustomName(customName); +- slime.setNoAi(isNoAi); +- slime.setInvulnerable(this.isInvulnerable()); +- slime.setSize(i, true); +- slime.moveTo(this.getX() + (double)f1, this.getY() + 0.5, this.getZ() + (double)f2, this.random.nextFloat() * 360.0F, 0.0F); +- this.level().addFreshEntity(slime); ++ entityslime.setCustomName(ichatbasecomponent); ++ entityslime.setNoAi(flag); ++ entityslime.setInvulnerable(this.isInvulnerable()); ++ entityslime.setSize(j, true); ++ entityslime.moveTo(this.getX() + (double) f1, this.getY() + 0.5D, this.getZ() + (double) f2, this.random.nextFloat() * 360.0F, 0.0F); ++ slimes.add(entityslime); // CraftBukkit + } + } ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, slimes, EntityTransformEvent.TransformReason.SPLIT).isCancelled()) { ++ super.remove(reason); ++ return; ++ } ++ for (LivingEntity living : slimes) { ++ this.level().addFreshEntity(living, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SLIME_SPLIT); // CraftBukkit - SpawnReason ++ } ++ // CraftBukkit end + } + + super.remove(reason); +@@ -228,8 +263,9 @@ + public void push(Entity entity) { + super.push(entity); + if (entity instanceof IronGolem && this.isDealsDamage()) { +- this.dealDamage((LivingEntity)entity); ++ this.dealDamage((LivingEntity) entity); + } ++ + } + + @Override +@@ -237,28 +273,29 @@ + if (this.isDealsDamage()) { + this.dealDamage(entity); + } ++ + } + + protected void dealDamage(LivingEntity livingEntity) { + if (this.isAlive()) { +- int size = this.getSize(); +- if (this.distanceToSqr(livingEntity) < 0.6 * (double)size * 0.6 * (double)size +- && this.hasLineOfSight(livingEntity) +- && livingEntity.hurt(this.damageSources().mobAttack(this), this.getAttackDamage())) { ++ int i = this.getSize(); ++ ++ if (this.distanceToSqr((Entity) livingEntity) < 0.6D * (double) i * 0.6D * (double) i && this.hasLineOfSight(livingEntity) && livingEntity.hurt(this.damageSources().mobAttack(this), this.getAttackDamage())) { + this.playSound(SoundEvents.SLIME_ATTACK, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); + this.doEnchantDamageEffects(this, livingEntity); + } + } ++ + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.625F * size.height; + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height - 0.015625F * (float)this.getSize() * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.015625F * (float) this.getSize() * f, 0.0F); + } + + protected boolean isDealsDamage() { +@@ -266,7 +303,7 @@ + } + + protected float getAttackDamage() { +- return (float)this.getAttributeValue(Attributes.ATTACK_DAMAGE); ++ return (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE); + } + + @Override +@@ -283,21 +320,16 @@ + return this.isTiny() ? SoundEvents.SLIME_SQUISH_SMALL : SoundEvents.SLIME_SQUISH; + } + +- public static boolean checkSlimeSpawnRules(EntityType slime, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) { +- if (MobSpawnType.isSpawner(spawnType)) { ++ public static boolean checkSlimeSpawnRules(EntityType slime, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ if (EnumMobSpawn.isSpawner(spawnType)) { + return checkMobSpawnRules(slime, level, spawnType, pos, random); + } else { + if (level.getDifficulty() != Difficulty.PEACEFUL) { +- if (spawnType == MobSpawnType.SPAWNER) { ++ if (spawnType == EnumMobSpawn.SPAWNER) { + return checkMobSpawnRules(slime, level, spawnType, pos, random); + } + +- if (level.getBiome(pos).is(BiomeTags.ALLOWS_SURFACE_SLIME_SPAWNS) +- && pos.getY() > 50 +- && pos.getY() < 70 +- && random.nextFloat() < 0.5F +- && random.nextFloat() < level.getMoonBrightness() +- && level.getMaxLocalRawBrightness(pos) <= random.nextInt(8)) { ++ if (level.getBiome(pos).is(BiomeTags.ALLOWS_SURFACE_SLIME_SPAWNS) && pos.getY() > 50 && pos.getY() < 70 && random.nextFloat() < 0.5F && random.nextFloat() < level.getMoonBrightness() && level.getMaxLocalRawBrightness(pos) <= random.nextInt(8)) { + return checkMobSpawnRules(slime, level, spawnType, pos, random); + } + +@@ -305,8 +337,9 @@ + return false; + } + +- ChunkPos chunkPos = new ChunkPos(pos); +- boolean flag = WorldgenRandom.seedSlimeChunk(chunkPos.x, chunkPos.z, ((WorldGenLevel)level).getSeed(), 987234911L).nextInt(10) == 0; ++ ChunkPos chunkcoordintpair = new ChunkPos(pos); ++ boolean flag = WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) level).getSeed(), 987234911L).nextInt(10) == 0; ++ + if (random.nextInt(10) == 0 && flag && pos.getY() < 40) { + return checkMobSpawnRules(slime, level, spawnType, pos, random); + } +@@ -318,7 +351,7 @@ + + @Override + protected float getSoundVolume() { +- return 0.4F * (float)this.getSize(); ++ return 0.4F * (float) this.getSize(); + } + + @Override +@@ -332,29 +365,31 @@ + + @Override + protected void jumpFromGround() { +- Vec3 deltaMovement = this.getDeltaMovement(); +- this.setDeltaMovement(deltaMovement.x, (double)this.getJumpPower(), deltaMovement.z); ++ Vec3 vec3d = this.getDeltaMovement(); ++ ++ this.setDeltaMovement(vec3d.x, (double) this.getJumpPower(), vec3d.z); + this.hasImpulse = true; + } + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- RandomSource random = level.getRandom(); +- int randomInt = random.nextInt(3); +- if (randomInt < 2 && random.nextFloat() < 0.5F * difficulty.getSpecialMultiplier()) { +- randomInt++; ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ RandomSource randomsource = level.getRandom(); ++ int i = randomsource.nextInt(3); ++ ++ if (i < 2 && randomsource.nextFloat() < 0.5F * difficulty.getSpecialMultiplier()) { ++ ++i; + } + +- int i = 1 << randomInt; +- this.setSize(i, true); ++ int j = 1 << i; ++ ++ this.setSize(j, true); + return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + + float getSoundPitch() { + float f = this.isTiny() ? 1.4F : 0.8F; ++ + return ((this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F) * f; + } + +@@ -363,61 +398,74 @@ + } + + @Override +- public EntityDimensions getDimensions(Pose pose) { +- return super.getDimensions(pose).scale(0.255F * (float)this.getSize()); ++ public EntityDimensions getDimensions(EntityPose pose) { ++ return super.getDimensions(pose).scale(0.255F * (float) this.getSize()); + } + +- static class SlimeAttackGoal extends Goal { ++ private static class SlimeMoveControl extends MoveControl { ++ ++ private float yRot; ++ private int jumpDelay; + private final Slime slime; +- private int growTiredTimer; ++ private boolean isAggressive; + +- public SlimeAttackGoal(Slime slime) { ++ public SlimeMoveControl(Slime slime) { ++ super(slime); + this.slime = slime; +- this.setFlags(EnumSet.of(Goal.Flag.LOOK)); ++ this.yRot = 180.0F * slime.getYRot() / 3.1415927F; + } + +- @Override +- public boolean canUse() { +- LivingEntity target = this.slime.getTarget(); +- return target != null && this.slime.canAttack(target) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl; ++ public void setDirection(float yRot, boolean aggressive) { ++ this.yRot = yRot; ++ this.isAggressive = aggressive; + } + +- @Override +- public void start() { +- this.growTiredTimer = reducedTickDelay(300); +- super.start(); ++ public void setWantedMovement(double speed) { ++ this.speedModifier = speed; ++ this.operation = MoveControl.Operation.MOVE_TO; + } + + @Override +- public boolean canContinueToUse() { +- LivingEntity target = this.slime.getTarget(); +- return target != null && this.slime.canAttack(target) && --this.growTiredTimer > 0; +- } ++ public void tick() { ++ this.mob.setYRot(this.rotlerp(this.mob.getYRot(), this.yRot, 90.0F)); ++ this.mob.yHeadRot = this.mob.getYRot(); ++ this.mob.yBodyRot = this.mob.getYRot(); ++ if (this.operation != MoveControl.Operation.MOVE_TO) { ++ this.mob.setZza(0.0F); ++ } else { ++ this.operation = MoveControl.Operation.WAIT; ++ if (this.mob.onGround()) { ++ this.mob.setSpeed((float) (this.speedModifier * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED))); ++ if (this.jumpDelay-- <= 0) { ++ this.jumpDelay = this.slime.getJumpDelay(); ++ if (this.isAggressive) { ++ this.jumpDelay /= 3; ++ } + +- @Override +- public boolean requiresUpdateEveryTick() { +- return true; +- } ++ this.slime.getJumpControl().jump(); ++ if (this.slime.doPlayJumpSound()) { ++ this.slime.playSound(this.slime.getJumpSound(), this.slime.getSoundVolume(), this.slime.getSoundPitch()); ++ } ++ } else { ++ this.slime.xxa = 0.0F; ++ this.slime.zza = 0.0F; ++ this.mob.setSpeed(0.0F); ++ } ++ } else { ++ this.mob.setSpeed((float) (this.speedModifier * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED))); ++ } + +- @Override +- public void tick() { +- LivingEntity target = this.slime.getTarget(); +- if (target != null) { +- this.slime.lookAt(target, 10.0F, 10.0F); + } +- +- if (this.slime.getMoveControl() instanceof Slime.SlimeMoveControl slimeMoveControl) { +- slimeMoveControl.setDirection(this.slime.getYRot(), this.slime.isDealsDamage()); +- } + } + } + +- static class SlimeFloatGoal extends Goal { ++ private static class SlimeFloatGoal extends Goal { ++ + private final Slime slime; + + public SlimeFloatGoal(Slime slime) { + this.slime = slime; +- this.setFlags(EnumSet.of(Goal.Flag.JUMP, Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.JUMP, Goal.Type.MOVE)); + slime.getNavigation().setCanFloat(true); + } + +@@ -437,115 +485,129 @@ + this.slime.getJumpControl().jump(); + } + +- if (this.slime.getMoveControl() instanceof Slime.SlimeMoveControl slimeMoveControl) { +- slimeMoveControl.setWantedMovement(1.2); ++ MoveControl controllermove = this.slime.getMoveControl(); ++ ++ if (controllermove instanceof Slime.SlimeMoveControl) { ++ Slime.SlimeMoveControl entityslime_controllermoveslime = (Slime.SlimeMoveControl) controllermove; ++ ++ entityslime_controllermoveslime.setWantedMovement(1.2D); + } ++ + } + } + +- static class SlimeKeepOnJumpingGoal extends Goal { ++ private static class SlimeAttackGoal extends Goal { ++ + private final Slime slime; ++ private int growTiredTimer; + +- public SlimeKeepOnJumpingGoal(Slime slime) { ++ public SlimeAttackGoal(Slime slime) { + this.slime = slime; +- this.setFlags(EnumSet.of(Goal.Flag.JUMP, Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.LOOK)); + } + + @Override + public boolean canUse() { +- return !this.slime.isPassenger(); ++ LivingEntity entityliving = this.slime.getTarget(); ++ ++ return entityliving == null ? false : (!this.slime.canAttack(entityliving) ? false : this.slime.getMoveControl() instanceof Slime.SlimeMoveControl); + } + + @Override +- public void tick() { +- if (this.slime.getMoveControl() instanceof Slime.SlimeMoveControl slimeMoveControl) { +- slimeMoveControl.setWantedMovement(1.0); +- } ++ public void start() { ++ this.growTiredTimer = reducedTickDelay(300); ++ super.start(); + } +- } + +- static class SlimeMoveControl extends MoveControl { +- private float yRot; +- private int jumpDelay; +- private final Slime slime; +- private boolean isAggressive; ++ @Override ++ public boolean canContinueToUse() { ++ LivingEntity entityliving = this.slime.getTarget(); + +- public SlimeMoveControl(Slime mob) { +- super(mob); +- this.slime = mob; +- this.yRot = 180.0F * mob.getYRot() / (float) Math.PI; ++ return entityliving == null ? false : (!this.slime.canAttack(entityliving) ? false : --this.growTiredTimer > 0); + } + +- public void setDirection(float yRot, boolean aggressive) { +- this.yRot = yRot; +- this.isAggressive = aggressive; ++ @Override ++ public boolean requiresUpdateEveryTick() { ++ return true; + } + +- public void setWantedMovement(double speed) { +- this.speedModifier = speed; +- this.operation = MoveControl.Operation.MOVE_TO; +- } +- + @Override + public void tick() { +- this.mob.setYRot(this.rotlerp(this.mob.getYRot(), this.yRot, 90.0F)); +- this.mob.yHeadRot = this.mob.getYRot(); +- this.mob.yBodyRot = this.mob.getYRot(); +- if (this.operation != MoveControl.Operation.MOVE_TO) { +- this.mob.setZza(0.0F); +- } else { +- this.operation = MoveControl.Operation.WAIT; +- if (this.mob.onGround()) { +- this.mob.setSpeed((float)(this.speedModifier * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED))); +- if (this.jumpDelay-- <= 0) { +- this.jumpDelay = this.slime.getJumpDelay(); +- if (this.isAggressive) { +- this.jumpDelay /= 3; +- } ++ LivingEntity entityliving = this.slime.getTarget(); + +- this.slime.getJumpControl().jump(); +- if (this.slime.doPlayJumpSound()) { +- this.slime.playSound(this.slime.getJumpSound(), this.slime.getSoundVolume(), this.slime.getSoundPitch()); +- } +- } else { +- this.slime.xxa = 0.0F; +- this.slime.zza = 0.0F; +- this.mob.setSpeed(0.0F); +- } +- } else { +- this.mob.setSpeed((float)(this.speedModifier * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED))); +- } ++ if (entityliving != null) { ++ this.slime.lookAt(entityliving, 10.0F, 10.0F); + } ++ ++ MoveControl controllermove = this.slime.getMoveControl(); ++ ++ if (controllermove instanceof Slime.SlimeMoveControl) { ++ Slime.SlimeMoveControl entityslime_controllermoveslime = (Slime.SlimeMoveControl) controllermove; ++ ++ entityslime_controllermoveslime.setDirection(this.slime.getYRot(), this.slime.isDealsDamage()); ++ } ++ + } + } + +- static class SlimeRandomDirectionGoal extends Goal { ++ private static class SlimeRandomDirectionGoal extends Goal { ++ + private final Slime slime; + private float chosenDegrees; + private int nextRandomizeTime; + + public SlimeRandomDirectionGoal(Slime slime) { + this.slime = slime; +- this.setFlags(EnumSet.of(Goal.Flag.LOOK)); ++ this.setFlags(EnumSet.of(Goal.Type.LOOK)); + } + + @Override + public boolean canUse() { +- return this.slime.getTarget() == null +- && (this.slime.onGround() || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) +- && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl; ++ return this.slime.getTarget() == null && (this.slime.onGround() || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl; + } + + @Override + public void tick() { + if (--this.nextRandomizeTime <= 0) { + this.nextRandomizeTime = this.adjustedTickDelay(40 + this.slime.getRandom().nextInt(60)); +- this.chosenDegrees = (float)this.slime.getRandom().nextInt(360); ++ this.chosenDegrees = (float) this.slime.getRandom().nextInt(360); + } + +- if (this.slime.getMoveControl() instanceof Slime.SlimeMoveControl slimeMoveControl) { +- slimeMoveControl.setDirection(this.chosenDegrees, false); ++ MoveControl controllermove = this.slime.getMoveControl(); ++ ++ if (controllermove instanceof Slime.SlimeMoveControl) { ++ Slime.SlimeMoveControl entityslime_controllermoveslime = (Slime.SlimeMoveControl) controllermove; ++ ++ entityslime_controllermoveslime.setDirection(this.chosenDegrees, false); + } ++ + } + } ++ ++ private static class SlimeKeepOnJumpingGoal extends Goal { ++ ++ private final Slime slime; ++ ++ public SlimeKeepOnJumpingGoal(Slime slime) { ++ this.slime = slime; ++ this.setFlags(EnumSet.of(Goal.Type.JUMP, Goal.Type.MOVE)); ++ } ++ ++ @Override ++ public boolean canUse() { ++ return !this.slime.isPassenger(); ++ } ++ ++ @Override ++ public void tick() { ++ MoveControl controllermove = this.slime.getMoveControl(); ++ ++ if (controllermove instanceof Slime.SlimeMoveControl) { ++ Slime.SlimeMoveControl entityslime_controllermoveslime = (Slime.SlimeMoveControl) controllermove; ++ ++ entityslime_controllermoveslime.setWantedMovement(1.0D); ++ } ++ ++ } ++ } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/SpellcasterIllager.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/SpellcasterIllager.java.patch new file mode 100644 index 0000000000..c726efdf25 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/SpellcasterIllager.java.patch @@ -0,0 +1,271 @@ +--- a/net/minecraft/world/entity/monster/SpellcasterIllager.java ++++ b/net/minecraft/world/entity/monster/SpellcasterIllager.java +@@ -15,20 +15,25 @@ + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.ai.goal.Goal; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public abstract class SpellcasterIllager extends AbstractIllager { ++ + private static final EntityDataAccessor DATA_SPELL_CASTING_ID = SynchedEntityData.defineId(SpellcasterIllager.class, EntityDataSerializers.BYTE); + protected int spellCastingTickCount; +- private SpellcasterIllager.IllagerSpell currentSpell = SpellcasterIllager.IllagerSpell.NONE; ++ private SpellcasterIllager.IllagerSpell currentSpell; + + protected SpellcasterIllager(EntityType entityType, Level level) { + super(entityType, level); ++ this.currentSpell = SpellcasterIllager.IllagerSpell.NONE; + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_SPELL_CASTING_ID, (byte)0); ++ this.entityData.define(SpellcasterIllager.DATA_SPELL_CASTING_ID, (byte) 0); + } + + @Override +@@ -44,51 +49,48 @@ + } + + @Override +- public AbstractIllager.IllagerArmPose getArmPose() { +- if (this.isCastingSpell()) { +- return AbstractIllager.IllagerArmPose.SPELLCASTING; +- } else { +- return this.isCelebrating() ? AbstractIllager.IllagerArmPose.CELEBRATING : AbstractIllager.IllagerArmPose.CROSSED; +- } ++ public AbstractIllager.a getArmPose() { ++ return this.isCastingSpell() ? AbstractIllager.a.SPELLCASTING : (this.isCelebrating() ? AbstractIllager.a.CELEBRATING : AbstractIllager.a.CROSSED); + } + + public boolean isCastingSpell() { +- return this.level().isClientSide ? this.entityData.get(DATA_SPELL_CASTING_ID) > 0 : this.spellCastingTickCount > 0; ++ return this.level().isClientSide ? (Byte) this.entityData.get(SpellcasterIllager.DATA_SPELL_CASTING_ID) > 0 : this.spellCastingTickCount > 0; + } + + public void setIsCastingSpell(SpellcasterIllager.IllagerSpell currentSpell) { + this.currentSpell = currentSpell; +- this.entityData.set(DATA_SPELL_CASTING_ID, (byte)currentSpell.id); ++ this.entityData.set(SpellcasterIllager.DATA_SPELL_CASTING_ID, (byte) currentSpell.id); + } + +- protected SpellcasterIllager.IllagerSpell getCurrentSpell() { +- return !this.level().isClientSide ? this.currentSpell : SpellcasterIllager.IllagerSpell.byId(this.entityData.get(DATA_SPELL_CASTING_ID)); ++ public SpellcasterIllager.IllagerSpell getCurrentSpell() { ++ return !this.level().isClientSide ? this.currentSpell : SpellcasterIllager.IllagerSpell.byId((Byte) this.entityData.get(SpellcasterIllager.DATA_SPELL_CASTING_ID)); + } + + @Override + protected void customServerAiStep() { + super.customServerAiStep(); + if (this.spellCastingTickCount > 0) { +- this.spellCastingTickCount--; ++ --this.spellCastingTickCount; + } ++ + } + + @Override + public void tick() { + super.tick(); + if (this.level().isClientSide && this.isCastingSpell()) { +- SpellcasterIllager.IllagerSpell currentSpell = this.getCurrentSpell(); +- double d = currentSpell.spellColor[0]; +- double d1 = currentSpell.spellColor[1]; +- double d2 = currentSpell.spellColor[2]; +- float f = this.yBodyRot * (float) (Math.PI / 180.0) + Mth.cos((float)this.tickCount * 0.6662F) * 0.25F; +- float cos = Mth.cos(f); +- float sin = Mth.sin(f); +- this.level() +- .addParticle(ParticleTypes.ENTITY_EFFECT, this.getX() + (double)cos * 0.6, this.getY() + 1.8, this.getZ() + (double)sin * 0.6, d, d1, d2); +- this.level() +- .addParticle(ParticleTypes.ENTITY_EFFECT, this.getX() - (double)cos * 0.6, this.getY() + 1.8, this.getZ() - (double)sin * 0.6, d, d1, d2); ++ SpellcasterIllager.IllagerSpell entityillagerwizard_spell = this.getCurrentSpell(); ++ double d0 = entityillagerwizard_spell.spellColor[0]; ++ double d1 = entityillagerwizard_spell.spellColor[1]; ++ double d2 = entityillagerwizard_spell.spellColor[2]; ++ float f = this.yBodyRot * 0.017453292F + Mth.cos((float) this.tickCount * 0.6662F) * 0.25F; ++ float f1 = Mth.cos(f); ++ float f2 = Mth.sin(f); ++ ++ this.level().addParticle(ParticleTypes.ENTITY_EFFECT, this.getX() + (double) f1 * 0.6D, this.getY() + 1.8D, this.getZ() + (double) f2 * 0.6D, d0, d1, d2); ++ this.level().addParticle(ParticleTypes.ENTITY_EFFECT, this.getX() - (double) f1 * 0.6D, this.getY() + 1.8D, this.getZ() - (double) f2 * 0.6D, d0, d1, d2); + } ++ + } + + protected int getSpellCastingTime() { +@@ -97,80 +99,45 @@ + + protected abstract SoundEvent getCastingSoundEvent(); + +- protected static enum IllagerSpell { +- NONE(0, 0.0, 0.0, 0.0), +- SUMMON_VEX(1, 0.7, 0.7, 0.8), +- FANGS(2, 0.4, 0.3, 0.35), +- WOLOLO(3, 0.7, 0.5, 0.2), +- DISAPPEAR(4, 0.3, 0.3, 0.8), +- BLINDNESS(5, 0.1, 0.1, 0.2); ++ public static enum IllagerSpell { + +- private static final IntFunction BY_ID = ByIdMap.continuous( +- illagerSpell -> illagerSpell.id, values(), ByIdMap.OutOfBoundsStrategy.ZERO +- ); ++ NONE(0, 0.0D, 0.0D, 0.0D), SUMMON_VEX(1, 0.7D, 0.7D, 0.8D), FANGS(2, 0.4D, 0.3D, 0.35D), WOLOLO(3, 0.7D, 0.5D, 0.2D), DISAPPEAR(4, 0.3D, 0.3D, 0.8D), BLINDNESS(5, 0.1D, 0.1D, 0.2D); ++ ++ private static final IntFunction BY_ID = ByIdMap.continuous((entityillagerwizard_spell) -> { ++ return entityillagerwizard_spell.id; ++ }, values(), ByIdMap.a.ZERO); + final int id; + final double[] spellColor; + +- private IllagerSpell(int id, double red, double green, double blue) { +- this.id = id; +- this.spellColor = new double[]{red, green, blue}; ++ private IllagerSpell(int i, double d0, double d1, double d2) { ++ this.id = i; ++ this.spellColor = new double[]{d0, d1, d2}; + } + + public static SpellcasterIllager.IllagerSpell byId(int id) { +- return BY_ID.apply(id); ++ return (SpellcasterIllager.IllagerSpell) SpellcasterIllager.IllagerSpell.BY_ID.apply(id); + } + } + +- protected class SpellcasterCastingSpellGoal extends Goal { +- public SpellcasterCastingSpellGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); +- } +- +- @Override +- public boolean canUse() { +- return SpellcasterIllager.this.getSpellCastingTime() > 0; +- } +- +- @Override +- public void start() { +- super.start(); +- SpellcasterIllager.this.navigation.stop(); +- } +- +- @Override +- public void stop() { +- super.stop(); +- SpellcasterIllager.this.setIsCastingSpell(SpellcasterIllager.IllagerSpell.NONE); +- } +- +- @Override +- public void tick() { +- if (SpellcasterIllager.this.getTarget() != null) { +- SpellcasterIllager.this.getLookControl() +- .setLookAt( +- SpellcasterIllager.this.getTarget(), (float)SpellcasterIllager.this.getMaxHeadYRot(), (float)SpellcasterIllager.this.getMaxHeadXRot() +- ); +- } +- } +- } +- + protected abstract class SpellcasterUseSpellGoal extends Goal { ++ + protected int attackWarmupDelay; + protected int nextAttackTickCount; + ++ protected SpellcasterUseSpellGoal() {} ++ + @Override + public boolean canUse() { +- LivingEntity target = SpellcasterIllager.this.getTarget(); +- return target != null +- && target.isAlive() +- && !SpellcasterIllager.this.isCastingSpell() +- && SpellcasterIllager.this.tickCount >= this.nextAttackTickCount; ++ LivingEntity entityliving = SpellcasterIllager.this.getTarget(); ++ ++ return entityliving != null && entityliving.isAlive() ? (SpellcasterIllager.this.isCastingSpell() ? false : SpellcasterIllager.this.tickCount >= this.nextAttackTickCount) : false; + } + + @Override + public boolean canContinueToUse() { +- LivingEntity target = SpellcasterIllager.this.getTarget(); +- return target != null && target.isAlive() && this.attackWarmupDelay > 0; ++ LivingEntity entityliving = SpellcasterIllager.this.getTarget(); ++ ++ return entityliving != null && entityliving.isAlive() && this.attackWarmupDelay > 0; + } + + @Override +@@ -178,9 +145,10 @@ + this.attackWarmupDelay = this.adjustedTickDelay(this.getCastWarmupTime()); + SpellcasterIllager.this.spellCastingTickCount = this.getCastingTime(); + this.nextAttackTickCount = SpellcasterIllager.this.tickCount + this.getCastingInterval(); +- SoundEvent spellPrepareSound = this.getSpellPrepareSound(); +- if (spellPrepareSound != null) { +- SpellcasterIllager.this.playSound(spellPrepareSound, 1.0F, 1.0F); ++ SoundEvent soundeffect = this.getSpellPrepareSound(); ++ ++ if (soundeffect != null) { ++ SpellcasterIllager.this.playSound(soundeffect, 1.0F, 1.0F); + } + + SpellcasterIllager.this.setIsCastingSpell(this.getSpell()); +@@ -188,11 +156,17 @@ + + @Override + public void tick() { +- this.attackWarmupDelay--; ++ --this.attackWarmupDelay; + if (this.attackWarmupDelay == 0) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handleEntitySpellCastEvent(SpellcasterIllager.this, this.getSpell())) { ++ return; ++ } ++ // CraftBukkit end + this.performSpellCasting(); + SpellcasterIllager.this.playSound(SpellcasterIllager.this.getCastingSoundEvent(), 1.0F, 1.0F); + } ++ + } + + protected abstract void performSpellCasting(); +@@ -210,4 +184,36 @@ + + protected abstract SpellcasterIllager.IllagerSpell getSpell(); + } ++ ++ protected class SpellcasterCastingSpellGoal extends Goal { ++ ++ public SpellcasterCastingSpellGoal() { ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); ++ } ++ ++ @Override ++ public boolean canUse() { ++ return SpellcasterIllager.this.getSpellCastingTime() > 0; ++ } ++ ++ @Override ++ public void start() { ++ super.start(); ++ SpellcasterIllager.this.navigation.stop(); ++ } ++ ++ @Override ++ public void stop() { ++ super.stop(); ++ SpellcasterIllager.this.setIsCastingSpell(SpellcasterIllager.IllagerSpell.NONE); ++ } ++ ++ @Override ++ public void tick() { ++ if (SpellcasterIllager.this.getTarget() != null) { ++ SpellcasterIllager.this.getLookControl().setLookAt(SpellcasterIllager.this.getTarget(), (float) SpellcasterIllager.this.getMaxHeadYRot(), (float) SpellcasterIllager.this.getMaxHeadXRot()); ++ } ++ ++ } ++ } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Spider.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Spider.java.patch new file mode 100644 index 0000000000..8019035f12 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Spider.java.patch @@ -0,0 +1,278 @@ +--- a/net/minecraft/world/entity/monster/Spider.java ++++ b/net/minecraft/world/entity/monster/Spider.java +@@ -17,12 +17,12 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.FloatGoal; +@@ -40,11 +40,12 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + + public class Spider extends Monster { ++ + private static final EntityDataAccessor DATA_FLAGS_ID = SynchedEntityData.defineId(Spider.class, EntityDataSerializers.BYTE); + private static final float SPIDER_SPECIAL_EFFECT_CHANCE = 0.1F; + +@@ -57,17 +58,17 @@ + this.goalSelector.addGoal(1, new FloatGoal(this)); + this.goalSelector.addGoal(3, new LeapAtTargetGoal(this, 0.4F)); + this.goalSelector.addGoal(4, new Spider.SpiderAttackGoal(this)); +- this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.8)); ++ this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.8D)); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(6, new RandomLookAroundGoal(this)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this)); ++ this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0])); + this.targetSelector.addGoal(2, new Spider.SpiderTargetGoal<>(this, Player.class)); + this.targetSelector.addGoal(3, new Spider.SpiderTargetGoal<>(this, IronGolem.class)); + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height * 0.85F, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height * 0.85F, 0.0F); + } + + @Override +@@ -78,7 +79,7 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_FLAGS_ID, (byte)0); ++ this.entityData.define(Spider.DATA_FLAGS_ID, (byte) 0); + } + + @Override +@@ -87,10 +88,11 @@ + if (!this.level().isClientSide) { + this.setClimbing(this.horizontalCollision); + } ++ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 16.0).add(Attributes.MOVEMENT_SPEED, 0.3F); ++ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 16.0D).add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D); + } + + @Override +@@ -109,7 +111,7 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.SPIDER_STEP, 0.15F, 1.0F); + } + +@@ -119,72 +121,76 @@ + } + + @Override +- public void makeStuckInBlock(BlockState state, Vec3 motionMultiplier) { ++ public void makeStuckInBlock(IBlockData state, Vec3 motionMultiplier) { + if (!state.is(Blocks.COBWEB)) { + super.makeStuckInBlock(state, motionMultiplier); + } ++ + } + + @Override +- public MobType getMobType() { +- return MobType.ARTHROPOD; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.ARTHROPOD; + } + + @Override + public boolean canBeAffected(MobEffectInstance potioneffect) { +- return potioneffect.getEffect() != MobEffects.POISON && super.canBeAffected(potioneffect); ++ return potioneffect.getEffect() == MobEffects.POISON ? false : super.canBeAffected(potioneffect); + } + + public boolean isClimbing() { +- return (this.entityData.get(DATA_FLAGS_ID) & 1) != 0; ++ return ((Byte) this.entityData.get(Spider.DATA_FLAGS_ID) & 1) != 0; + } + + public void setClimbing(boolean climbing) { +- byte b = this.entityData.get(DATA_FLAGS_ID); ++ byte b0 = (Byte) this.entityData.get(Spider.DATA_FLAGS_ID); ++ + if (climbing) { +- b = (byte)(b | 1); ++ b0 = (byte) (b0 | 1); + } else { +- b = (byte)(b & -2); ++ b0 &= -2; + } + +- this.entityData.set(DATA_FLAGS_ID, b); ++ this.entityData.set(Spider.DATA_FLAGS_ID, b0); + } + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- SpawnGroupData var9 = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); +- RandomSource random = level.getRandom(); +- if (random.nextInt(100) == 0) { +- Skeleton skeleton = EntityType.SKELETON.create(this.level()); +- if (skeleton != null) { +- skeleton.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); +- skeleton.finalizeSpawn(level, difficulty, reason, null, null); +- skeleton.startRiding(this); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ Object object = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ RandomSource randomsource = level.getRandom(); ++ ++ if (randomsource.nextInt(100) == 0) { ++ Skeleton entityskeleton = (Skeleton) EntityType.SKELETON.create(this.level()); ++ ++ if (entityskeleton != null) { ++ entityskeleton.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); ++ entityskeleton.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) null, (CompoundTag) null); ++ entityskeleton.startRiding(this); + } + } + +- if (var9 == null) { +- var9 = new Spider.SpiderEffectsGroupData(); +- if (level.getDifficulty() == Difficulty.HARD && random.nextFloat() < 0.1F * difficulty.getSpecialMultiplier()) { +- ((Spider.SpiderEffectsGroupData)var9).setRandomEffect(random); ++ if (object == null) { ++ object = new Spider.SpiderEffectsGroupData(); ++ if (level.getDifficulty() == Difficulty.HARD && randomsource.nextFloat() < 0.1F * difficulty.getSpecialMultiplier()) { ++ ((Spider.SpiderEffectsGroupData) object).setRandomEffect(randomsource); + } + } + +- if (var9 instanceof Spider.SpiderEffectsGroupData spiderEffectsGroupData) { +- MobEffect mobEffect = spiderEffectsGroupData.effect; +- if (mobEffect != null) { +- this.addEffect(new MobEffectInstance(mobEffect, -1)); ++ if (object instanceof Spider.SpiderEffectsGroupData) { ++ Spider.SpiderEffectsGroupData entityspider_groupdataspider = (Spider.SpiderEffectsGroupData) object; ++ MobEffect mobeffectlist = entityspider_groupdataspider.effect; ++ ++ if (mobeffectlist != null) { ++ this.addEffect(new MobEffectInstance(mobeffectlist, -1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.SPIDER_SPAWN); // CraftBukkit + } + } + +- return (SpawnGroupData)var9; ++ return (GroupDataEntity) object; + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.65F; + } + +@@ -193,9 +199,10 @@ + return entity.getBbWidth() <= this.getBbWidth() ? -0.3125F : 0.0F; + } + +- static class SpiderAttackGoal extends MeleeAttackGoal { ++ private static class SpiderAttackGoal extends MeleeAttackGoal { ++ + public SpiderAttackGoal(Spider spider) { +- super(spider, 1.0, true); ++ super(spider, 1.0D, true); + } + + @Override +@@ -205,9 +212,10 @@ + + @Override + public boolean canContinueToUse() { +- float lightLevelDependentMagicValue = this.mob.getLightLevelDependentMagicValue(); +- if (lightLevelDependentMagicValue >= 0.5F && this.mob.getRandom().nextInt(100) == 0) { +- this.mob.setTarget(null); ++ float f = this.mob.getLightLevelDependentMagicValue(); ++ ++ if (f >= 0.5F && this.mob.getRandom().nextInt(100) == 0) { ++ this.mob.setTarget((LivingEntity) null); + return false; + } else { + return super.canContinueToUse(); +@@ -215,33 +223,40 @@ + } + } + +- public static class SpiderEffectsGroupData implements SpawnGroupData { ++ private static class SpiderTargetGoal extends NearestAttackableTargetGoal { ++ ++ public SpiderTargetGoal(Spider spider, Class entityTypeToTarget) { ++ super(spider, entityTypeToTarget, true); ++ } ++ ++ @Override ++ public boolean canUse() { ++ float f = this.mob.getLightLevelDependentMagicValue(); ++ ++ return f >= 0.5F ? false : super.canUse(); ++ } ++ } ++ ++ public static class SpiderEffectsGroupData implements GroupDataEntity { ++ + @Nullable + public MobEffect effect; + ++ public SpiderEffectsGroupData() {} ++ + public void setRandomEffect(RandomSource random) { +- int randomInt = random.nextInt(5); +- if (randomInt <= 1) { ++ int i = random.nextInt(5); ++ ++ if (i <= 1) { + this.effect = MobEffects.MOVEMENT_SPEED; +- } else if (randomInt <= 2) { ++ } else if (i <= 2) { + this.effect = MobEffects.DAMAGE_BOOST; +- } else if (randomInt <= 3) { ++ } else if (i <= 3) { + this.effect = MobEffects.REGENERATION; +- } else if (randomInt <= 4) { ++ } else if (i <= 4) { + this.effect = MobEffects.INVISIBILITY; + } +- } +- } + +- static class SpiderTargetGoal extends NearestAttackableTargetGoal { +- public SpiderTargetGoal(Spider spider, Class entityTypeToTarget) { +- super(spider, entityTypeToTarget, true); + } +- +- @Override +- public boolean canUse() { +- float lightLevelDependentMagicValue = this.mob.getLightLevelDependentMagicValue(); +- return !(lightLevelDependentMagicValue >= 0.5F) && super.canUse(); +- } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Strider.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Strider.java.patch new file mode 100644 index 0000000000..23517c9040 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Strider.java.patch @@ -0,0 +1,583 @@ +--- a/net/minecraft/world/entity/monster/Strider.java ++++ b/net/minecraft/world/entity/monster/Strider.java +@@ -1,6 +1,8 @@ + package net.minecraft.world.entity.monster; + + import com.google.common.collect.Sets; ++import com.google.common.collect.UnmodifiableIterator; ++import java.util.Iterator; + import java.util.Set; + import java.util.UUID; + import javax.annotation.Nullable; +@@ -19,22 +21,22 @@ + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; ++import net.minecraft.world.entity.ISteerable; + import net.minecraft.world.entity.ItemBasedSteering; +-import net.minecraft.world.entity.ItemSteerable; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.Saddleable; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -55,28 +57,28 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.item.crafting.Ingredient; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.LiquidBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.pathfinder.BlockPathTypes; +-import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraft.world.level.pathfinder.PathFinder; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.level.pathfinder.WalkNodeEvaluator; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; + import org.joml.Vector3f; + +-public class Strider extends Animal implements ItemSteerable, Saddleable { ++public class Strider extends Animal implements ISteerable, Saddleable { ++ + private static final UUID SUFFOCATING_MODIFIER_UUID = UUID.fromString("9e362924-01de-4ddd-a2b2-d0f7a405a174"); +- private static final AttributeModifier SUFFOCATING_MODIFIER = new AttributeModifier( +- SUFFOCATING_MODIFIER_UUID, "Strider suffocating modifier", -0.34F, AttributeModifier.Operation.MULTIPLY_BASE +- ); ++ private static final AttributeModifier SUFFOCATING_MODIFIER = new AttributeModifier(Strider.SUFFOCATING_MODIFIER_UUID, "Strider suffocating modifier", -0.3400000035762787D, AttributeModifier.Operation.MULTIPLY_BASE); + private static final float SUFFOCATE_STEERING_MODIFIER = 0.35F; + private static final float STEERING_MODIFIER = 0.55F; + private static final Ingredient FOOD_ITEMS = Ingredient.of(Items.WARPED_FUNGUS); +@@ -84,12 +86,13 @@ + private static final EntityDataAccessor DATA_BOOST_TIME = SynchedEntityData.defineId(Strider.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_SUFFOCATING = SynchedEntityData.defineId(Strider.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_SADDLE_ID = SynchedEntityData.defineId(Strider.class, EntityDataSerializers.BOOLEAN); +- private final ItemBasedSteering steering = new ItemBasedSteering(this.entityData, DATA_BOOST_TIME, DATA_SADDLE_ID); ++ public final ItemBasedSteering steering; + @Nullable + private TemptGoal temptGoal; + + public Strider(EntityType entityType, Level level) { + super(entityType, level); ++ this.steering = new ItemBasedSteering(this.entityData, Strider.DATA_BOOST_TIME, Strider.DATA_SADDLE_ID); + this.blocksBuilding = true; + this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); + this.setPathfindingMalus(BlockPathTypes.LAVA, 0.0F); +@@ -97,19 +100,19 @@ + this.setPathfindingMalus(BlockPathTypes.DAMAGE_FIRE, 0.0F); + } + +- public static boolean checkStriderSpawnRules(EntityType strider, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) { +- BlockPos.MutableBlockPos mutableBlockPos = pos.mutable(); ++ public static boolean checkStriderSpawnRules(EntityType strider, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); + + do { +- mutableBlockPos.move(Direction.UP); +- } while (level.getFluidState(mutableBlockPos).is(FluidTags.LAVA)); ++ blockposition_mutableblockposition.move(Direction.UP); ++ } while (level.getFluidState(blockposition_mutableblockposition).is(FluidTags.LAVA)); + +- return level.getBlockState(mutableBlockPos).isAir(); ++ return level.getBlockState(blockposition_mutableblockposition).isAir(); + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { +- if (DATA_BOOST_TIME.equals(key) && this.level().isClientSide) { ++ if (Strider.DATA_BOOST_TIME.equals(key) && this.level().isClientSide) { + this.steering.onSynced(); + } + +@@ -119,9 +122,9 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_BOOST_TIME, 0); +- this.entityData.define(DATA_SUFFOCATING, false); +- this.entityData.define(DATA_SADDLE_ID, false); ++ this.entityData.define(Strider.DATA_BOOST_TIME, 0); ++ this.entityData.define(Strider.DATA_SUFFOCATING, false); ++ this.entityData.define(Strider.DATA_SADDLE_ID, false); + } + + @Override +@@ -150,37 +153,40 @@ + public void equipSaddle(@Nullable SoundSource source) { + this.steering.setSaddle(true); + if (source != null) { +- this.level().playSound(null, this, SoundEvents.STRIDER_SADDLE, source, 0.5F, 1.0F); ++ this.level().playSound((Player) null, (Entity) this, SoundEvents.STRIDER_SADDLE, source, 0.5F, 1.0F); + } ++ + } + + @Override + protected void registerGoals() { +- this.goalSelector.addGoal(1, new PanicGoal(this, 1.65)); +- this.goalSelector.addGoal(2, new BreedGoal(this, 1.0)); +- this.temptGoal = new TemptGoal(this, 1.4, TEMPT_ITEMS, false); ++ this.goalSelector.addGoal(1, new PanicGoal(this, 1.65D)); ++ this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); ++ this.temptGoal = new TemptGoal(this, 1.4D, Strider.TEMPT_ITEMS, false); + this.goalSelector.addGoal(3, this.temptGoal); +- this.goalSelector.addGoal(4, new Strider.StriderGoToLavaGoal(this, 1.0)); +- this.goalSelector.addGoal(5, new FollowParentGoal(this, 1.0)); +- this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0, 60)); ++ this.goalSelector.addGoal(4, new Strider.StriderGoToLavaGoal(this, 1.0D)); ++ this.goalSelector.addGoal(5, new FollowParentGoal(this, 1.0D)); ++ this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0D, 60)); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); + this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Strider.class, 8.0F)); + } + + public void setSuffocating(boolean suffocating) { +- this.entityData.set(DATA_SUFFOCATING, suffocating); +- AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED); +- if (attribute != null) { +- attribute.removeModifier(SUFFOCATING_MODIFIER_UUID); ++ this.entityData.set(Strider.DATA_SUFFOCATING, suffocating); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ ++ if (attributemodifiable != null) { ++ attributemodifiable.removeModifier(Strider.SUFFOCATING_MODIFIER_UUID); + if (suffocating) { +- attribute.addTransientModifier(SUFFOCATING_MODIFIER); ++ attributemodifiable.addTransientModifier(Strider.SUFFOCATING_MODIFIER); + } + } ++ + } + + public boolean isSuffocating() { +- return this.entityData.get(DATA_SUFFOCATING); ++ return (Boolean) this.entityData.get(Strider.DATA_SUFFOCATING); + } + + @Override +@@ -189,11 +195,12 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- float min = Math.min(0.25F, this.walkAnimation.speed()); +- float f1 = this.walkAnimation.position(); +- float f2 = 0.12F * Mth.cos(f1 * 1.5F) * 2.0F * min; +- return new Vector3f(0.0F, entityDimensions.height + f2 * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ float f1 = Math.min(0.25F, this.walkAnimation.speed()); ++ float f2 = this.walkAnimation.position(); ++ float f3 = 0.12F * Mth.cos(f2 * 1.5F) * 2.0F * f1; ++ ++ return new Vector3f(0.0F, entitysize.height + f3 * f, 0.0F); + } + + @Override +@@ -204,45 +211,61 @@ + @Nullable + @Override + public LivingEntity getControllingPassenger() { +- return (LivingEntity)(this.isSaddled() && this.getFirstPassenger() instanceof Player player && player.isHolding(Items.WARPED_FUNGUS_ON_A_STICK) +- ? player +- : super.getControllingPassenger()); ++ if (this.isSaddled()) { ++ Entity entity = this.getFirstPassenger(); ++ ++ if (entity instanceof Player) { ++ Player entityhuman = (Player) entity; ++ ++ if (entityhuman.isHolding(Items.WARPED_FUNGUS_ON_A_STICK)) { ++ return entityhuman; ++ } ++ } ++ } ++ ++ return super.getControllingPassenger(); + } + + @Override + public Vec3 getDismountLocationForPassenger(LivingEntity livingEntity) { +- Vec3[] vec3s = new Vec3[]{ +- getCollisionHorizontalEscapeVector((double)this.getBbWidth(), (double)livingEntity.getBbWidth(), livingEntity.getYRot()), +- getCollisionHorizontalEscapeVector((double)this.getBbWidth(), (double)livingEntity.getBbWidth(), livingEntity.getYRot() - 22.5F), +- getCollisionHorizontalEscapeVector((double)this.getBbWidth(), (double)livingEntity.getBbWidth(), livingEntity.getYRot() + 22.5F), +- getCollisionHorizontalEscapeVector((double)this.getBbWidth(), (double)livingEntity.getBbWidth(), livingEntity.getYRot() - 45.0F), +- getCollisionHorizontalEscapeVector((double)this.getBbWidth(), (double)livingEntity.getBbWidth(), livingEntity.getYRot() + 45.0F) +- }; ++ Vec3[] avec3d = new Vec3[]{getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingEntity.getBbWidth(), livingEntity.getYRot()), getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingEntity.getBbWidth(), livingEntity.getYRot() - 22.5F), getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingEntity.getBbWidth(), livingEntity.getYRot() + 22.5F), getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingEntity.getBbWidth(), livingEntity.getYRot() - 45.0F), getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingEntity.getBbWidth(), livingEntity.getYRot() + 45.0F)}; + Set set = Sets.newLinkedHashSet(); +- double d = this.getBoundingBox().maxY; +- double d1 = this.getBoundingBox().minY - 0.5; +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ double d0 = this.getBoundingBox().maxY; ++ double d1 = this.getBoundingBox().minY - 0.5D; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ Vec3[] avec3d1 = avec3d; ++ int i = avec3d.length; + +- for (Vec3 vec3 : vec3s) { +- mutableBlockPos.set(this.getX() + vec3.x, d, this.getZ() + vec3.z); ++ for (int j = 0; j < i; ++j) { ++ Vec3 vec3d = avec3d1[j]; + +- for (double d2 = d; d2 > d1; d2--) { +- set.add(mutableBlockPos.immutable()); +- mutableBlockPos.move(Direction.DOWN); ++ blockposition_mutableblockposition.set(this.getX() + vec3d.x, d0, this.getZ() + vec3d.z); ++ ++ for (double d2 = d0; d2 > d1; --d2) { ++ set.add(blockposition_mutableblockposition.immutable()); ++ blockposition_mutableblockposition.move(Direction.DOWN); + } + } + +- for (BlockPos blockPos : set) { +- if (!this.level().getFluidState(blockPos).is(FluidTags.LAVA)) { +- double blockFloorHeight = this.level().getBlockFloorHeight(blockPos); +- if (DismountHelper.isBlockFloorValid(blockFloorHeight)) { +- Vec3 vec31 = Vec3.upFromBottomCenterOf(blockPos, blockFloorHeight); ++ Iterator iterator = set.iterator(); + +- for (Pose pose : livingEntity.getDismountPoses()) { +- AABB localBoundsForPose = livingEntity.getLocalBoundsForPose(pose); +- if (DismountHelper.canDismountTo(this.level(), livingEntity, localBoundsForPose.move(vec31))) { +- livingEntity.setPose(pose); +- return vec31; ++ while (iterator.hasNext()) { ++ BlockPos blockposition = (BlockPos) iterator.next(); ++ ++ if (!this.level().getFluidState(blockposition).is(FluidTags.LAVA)) { ++ double d3 = this.level().getBlockFloorHeight(blockposition); ++ ++ if (DismountHelper.isBlockFloorValid(d3)) { ++ Vec3 vec3d1 = Vec3.upFromBottomCenterOf(blockposition, d3); ++ UnmodifiableIterator unmodifiableiterator = livingEntity.getDismountPoses().iterator(); ++ ++ while (unmodifiableiterator.hasNext()) { ++ EntityPose entitypose = (EntityPose) unmodifiableiterator.next(); ++ AABB axisalignedbb = livingEntity.getLocalBoundsForPose(entitypose); ++ ++ if (DismountHelper.canDismountTo(this.level(), livingEntity, axisalignedbb.move(vec3d1))) { ++ livingEntity.setPose(entitypose); ++ return vec3d1; + } + } + } +@@ -262,12 +285,12 @@ + + @Override + protected Vec3 getRiddenInput(Player player, Vec3 travelVector) { +- return new Vec3(0.0, 0.0, 1.0); ++ return new Vec3(0.0D, 0.0D, 1.0D); + } + + @Override + protected float getRiddenSpeed(Player player) { +- return (float)(this.getAttributeValue(Attributes.MOVEMENT_SPEED) * (double)(this.isSuffocating() ? 0.35F : 0.55F) * (double)this.steering.boostFactor()); ++ return (float) (this.getAttributeValue(Attributes.MOVEMENT_SPEED) * (double) (this.isSuffocating() ? 0.35F : 0.55F) * (double) this.steering.boostFactor()); + } + + @Override +@@ -276,7 +299,7 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(this.isInLava() ? SoundEvents.STRIDER_STEP_LAVA : SoundEvents.STRIDER_STEP, 1.0F, 1.0F); + } + +@@ -286,12 +309,12 @@ + } + + @Override +- protected void checkFallDamage(double y, boolean onGround, BlockState state, BlockPos pos) { ++ protected void checkFallDamage(double y, boolean flag, IBlockData onGround, BlockPos state) { + this.checkInsideBlocks(); + if (this.isInLava()) { + this.resetFallDistance(); + } else { +- super.checkFallDamage(y, onGround, state, pos); ++ super.checkFallDamage(y, flag, onGround, state); + } + } + +@@ -305,23 +328,37 @@ + + if (!this.isNoAi()) { + boolean flag; +- boolean var10000; +- label36: { +- BlockState blockState = this.level().getBlockState(this.blockPosition()); +- BlockState blockStateOnLegacy = this.getBlockStateOnLegacy(); +- flag = blockState.is(BlockTags.STRIDER_WARM_BLOCKS) +- || blockStateOnLegacy.is(BlockTags.STRIDER_WARM_BLOCKS) +- || this.getFluidHeight(FluidTags.LAVA) > 0.0; +- if (this.getVehicle() instanceof Strider strider && strider.isSuffocating()) { +- var10000 = true; +- break label36; ++ boolean flag1; ++ label36: ++ { ++ IBlockData iblockdata = this.level().getBlockState(this.blockPosition()); ++ IBlockData iblockdata1 = this.getBlockStateOnLegacy(); ++ ++ flag = iblockdata.is(BlockTags.STRIDER_WARM_BLOCKS) || iblockdata1.is(BlockTags.STRIDER_WARM_BLOCKS) || this.getFluidHeight(FluidTags.LAVA) > 0.0D; ++ Entity entity = this.getVehicle(); ++ ++ if (entity instanceof Strider) { ++ Strider entitystrider = (Strider) entity; ++ ++ if (entitystrider.isSuffocating()) { ++ flag1 = true; ++ break label36; ++ } + } + +- var10000 = false; ++ flag1 = false; + } + +- boolean flag1 = var10000; +- this.setSuffocating(!flag || flag1); ++ boolean flag2 = flag1; ++ ++ // CraftBukkit start ++ boolean suffocating = !flag || flag2; ++ if (suffocating ^ this.isSuffocating()) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callStriderTemperatureChangeEvent(this, suffocating)) { ++ this.setSuffocating(suffocating); ++ } ++ } ++ // CraftBukkit end + } + + super.tick(); +@@ -340,18 +377,19 @@ + + private void floatStrider() { + if (this.isInLava()) { +- CollisionContext collisionContext = CollisionContext.of(this); +- if (collisionContext.isAbove(LiquidBlock.STABLE_SHAPE, this.blockPosition(), true) +- && !this.level().getFluidState(this.blockPosition().above()).is(FluidTags.LAVA)) { ++ CollisionContext voxelshapecollision = CollisionContext.of(this); ++ ++ if (voxelshapecollision.isAbove(LiquidBlock.STABLE_SHAPE, this.blockPosition(), true) && !this.level().getFluidState(this.blockPosition().above()).is(FluidTags.LAVA)) { + this.setOnGround(true); + } else { +- this.setDeltaMovement(this.getDeltaMovement().scale(0.5).add(0.0, 0.05, 0.0)); ++ this.setDeltaMovement(this.getDeltaMovement().scale(0.5D).add(0.0D, 0.05D, 0.0D)); + } + } ++ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.175F).add(Attributes.FOLLOW_RANGE, 16.0); ++ return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.17499999701976776D).add(Attributes.FOLLOW_RANGE, 16.0D); + } + + @Override +@@ -391,109 +429,101 @@ + + @Override + public float getWalkTargetValue(BlockPos pos, LevelReader level) { +- if (level.getBlockState(pos).getFluidState().is(FluidTags.LAVA)) { +- return 10.0F; +- } else { +- return this.isInLava() ? Float.NEGATIVE_INFINITY : 0.0F; +- } ++ return level.getBlockState(pos).getFluidState().is(FluidTags.LAVA) ? 10.0F : (this.isInLava() ? Float.NEGATIVE_INFINITY : 0.0F); + } + + @Nullable + @Override + public Strider getBreedOffspring(ServerLevel level, AgeableMob otherParent) { +- return EntityType.STRIDER.create(level); ++ return (Strider) EntityType.STRIDER.create(level); + } + + @Override + public boolean isFood(ItemStack stack) { +- return FOOD_ITEMS.test(stack); ++ return Strider.FOOD_ITEMS.test(stack); + } + + @Override + protected void dropEquipment() { + super.dropEquipment(); + if (this.isSaddled()) { +- this.spawnAtLocation(Items.SADDLE); ++ this.spawnAtLocation((IMaterial) Items.SADDLE); + } ++ + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- boolean isFood = this.isFood(player.getItemInHand(hand)); +- if (!isFood && this.isSaddled() && !this.isVehicle() && !player.isSecondaryUseActive()) { ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ boolean flag = this.isFood(player.getItemInHand(hand)); ++ ++ if (!flag && this.isSaddled() && !this.isVehicle() && !player.isSecondaryUseActive()) { + if (!this.level().isClientSide) { + player.startRiding(this); + } + + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { +- InteractionResult interactionResult = super.mobInteract(player, hand); +- if (!interactionResult.consumesAction()) { +- ItemStack itemInHand = player.getItemInHand(hand); +- return itemInHand.is(Items.SADDLE) ? itemInHand.interactLivingEntity(player, this, hand) : InteractionResult.PASS; ++ InteractionResult enuminteractionresult = super.mobInteract(player, hand); ++ ++ if (!enuminteractionresult.consumesAction()) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ return itemstack.is(Items.SADDLE) ? itemstack.interactLivingEntity(player, this, hand) : InteractionResult.PASS; + } else { +- if (isFood && !this.isSilent()) { +- this.level() +- .playSound( +- null, +- this.getX(), +- this.getY(), +- this.getZ(), +- SoundEvents.STRIDER_EAT, +- this.getSoundSource(), +- 1.0F, +- 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F +- ); ++ if (flag && !this.isSilent()) { ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.STRIDER_EAT, this.getSoundSource(), 1.0F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F); + } + +- return interactionResult; ++ return enuminteractionresult; + } + } + } + + @Override + public Vec3 getLeashOffset() { +- return new Vec3(0.0, (double)(0.6F * this.getEyeHeight()), (double)(this.getBbWidth() * 0.4F)); ++ return new Vec3(0.0D, (double) (0.6F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); + } + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + if (this.isBaby()) { +- return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } else { +- RandomSource random = level.getRandom(); +- if (random.nextInt(30) == 0) { +- Mob mob = EntityType.ZOMBIFIED_PIGLIN.create(level.getLevel()); +- if (mob != null) { +- spawnData = this.spawnJockey(level, difficulty, mob, new Zombie.ZombieGroupData(Zombie.getSpawnAsBabyOdds(random), false)); +- mob.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.WARPED_FUNGUS_ON_A_STICK)); +- this.equipSaddle(null); ++ RandomSource randomsource = level.getRandom(); ++ ++ if (randomsource.nextInt(30) == 0) { ++ Mob entityinsentient = (Mob) EntityType.ZOMBIFIED_PIGLIN.create(level.getLevel()); ++ ++ if (entityinsentient != null) { ++ spawnData = this.spawnJockey(level, difficulty, entityinsentient, new Zombie.ZombieGroupData(Zombie.getSpawnAsBabyOdds(randomsource), false)); ++ entityinsentient.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.WARPED_FUNGUS_ON_A_STICK)); ++ this.equipSaddle((SoundSource) null); + } +- } else if (random.nextInt(10) == 0) { +- AgeableMob ageableMob = EntityType.STRIDER.create(level.getLevel()); +- if (ageableMob != null) { +- ageableMob.setAge(-24000); +- spawnData = this.spawnJockey(level, difficulty, ageableMob, null); ++ } else if (randomsource.nextInt(10) == 0) { ++ AgeableMob entityageable = (AgeableMob) EntityType.STRIDER.create(level.getLevel()); ++ ++ if (entityageable != null) { ++ entityageable.setAge(-24000); ++ spawnData = this.spawnJockey(level, difficulty, entityageable, (GroupDataEntity) null); + } + } else { + spawnData = new AgeableMob.AgeableMobGroupData(0.5F); + } + +- return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + } + +- private SpawnGroupData spawnJockey(ServerLevelAccessor serverLevel, DifficultyInstance difficulty, Mob jockey, @Nullable SpawnGroupData spawnData) { ++ private GroupDataEntity spawnJockey(ServerLevelAccessor serverLevel, DifficultyInstance difficulty, Mob jockey, @Nullable GroupDataEntity spawnData) { + jockey.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); +- jockey.finalizeSpawn(serverLevel, difficulty, MobSpawnType.JOCKEY, spawnData, null); ++ jockey.finalizeSpawn(serverLevel, difficulty, EnumMobSpawn.JOCKEY, spawnData, (CompoundTag) null); + jockey.startRiding(this, true); + return new AgeableMob.AgeableMobGroupData(0.0F); + } + +- static class StriderGoToLavaGoal extends MoveToBlockGoal { ++ private static class StriderGoToLavaGoal extends MoveToBlockGoal { ++ + private final Strider strider; + + StriderGoToLavaGoal(Strider strider, double speedModifier) { +@@ -523,11 +553,12 @@ + + @Override + protected boolean isValidTarget(LevelReader level, BlockPos pos) { +- return level.getBlockState(pos).is(Blocks.LAVA) && level.getBlockState(pos.above()).isPathfindable(level, pos, PathComputationType.LAND); ++ return level.getBlockState(pos).is(Blocks.LAVA) && level.getBlockState(pos.above()).isPathfindable(level, pos, PathMode.LAND); + } + } + +- static class StriderPathNavigation extends GroundPathNavigation { ++ private static class StriderPathNavigation extends GroundPathNavigation { ++ + StriderPathNavigation(Strider strider, Level level) { + super(strider, level); + } +@@ -541,10 +572,7 @@ + + @Override + protected boolean hasValidPathType(BlockPathTypes pathType) { +- return pathType == BlockPathTypes.LAVA +- || pathType == BlockPathTypes.DAMAGE_FIRE +- || pathType == BlockPathTypes.DANGER_FIRE +- || super.hasValidPathType(pathType); ++ return pathType != BlockPathTypes.LAVA && pathType != BlockPathTypes.DAMAGE_FIRE && pathType != BlockPathTypes.DANGER_FIRE ? super.hasValidPathType(pathType) : true; + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Vex.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Vex.java.patch new file mode 100644 index 0000000000..07677de98b --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Vex.java.patch @@ -0,0 +1,402 @@ +--- a/net/minecraft/world/entity/monster/Vex.java ++++ b/net/minecraft/world/entity/monster/Vex.java +@@ -15,15 +15,15 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.PathfinderMob; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.TraceableEntity; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -45,16 +45,17 @@ + import org.joml.Vector3f; + + public class Vex extends Monster implements TraceableEntity { ++ + public static final float FLAP_DEGREES_PER_TICK = 45.836624F; +- public static final int TICKS_PER_FLAP = Mth.ceil((float) (Math.PI * 5.0 / 4.0)); ++ public static final int TICKS_PER_FLAP = Mth.ceil(3.9269907F); + protected static final EntityDataAccessor DATA_FLAGS_ID = SynchedEntityData.defineId(Vex.class, EntityDataSerializers.BYTE); + private static final int FLAG_IS_CHARGING = 1; + @Nullable + Mob owner; + @Nullable + private BlockPos boundOrigin; +- private boolean hasLimitedLife; +- private int limitedLifeTicks; ++ public boolean hasLimitedLife; ++ public int limitedLifeTicks; + + public Vex(EntityType entityType, Level level) { + super(entityType, level); +@@ -63,17 +64,17 @@ + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions dimensions) { + return dimensions.height - 0.28125F; + } + + @Override + public boolean isFlapping() { +- return this.tickCount % TICKS_PER_FLAP == 0; ++ return this.tickCount % Vex.TICKS_PER_FLAP == 0; + } + + @Override +- public void move(MoverType type, Vec3 pos) { ++ public void move(EnumMoveType type, Vec3 pos) { + super.move(type, pos); + this.checkInsideBlocks(); + } +@@ -88,6 +89,7 @@ + this.limitedLifeTicks = 20; + this.hurt(this.damageSources().starve(), 1.0F); + } ++ + } + + @Override +@@ -98,19 +100,19 @@ + this.goalSelector.addGoal(8, new Vex.VexRandomMoveGoal()); + this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Raider.class).setAlertOthers()); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers()); + this.targetSelector.addGoal(2, new Vex.VexCopyOwnerTargetGoal(this)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, true)); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 14.0).add(Attributes.ATTACK_DAMAGE, 4.0); ++ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 14.0D).add(Attributes.ATTACK_DAMAGE, 4.0D); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_FLAGS_ID, (byte)0); ++ this.entityData.define(Vex.DATA_FLAGS_ID, (byte) 0); + } + + @Override +@@ -123,14 +125,18 @@ + if (compound.contains("LifeTicks")) { + this.setLimitedLife(compound.getInt("LifeTicks")); + } ++ + } + + @Override + public void restoreFrom(Entity entity) { + super.restoreFrom(entity); +- if (entity instanceof Vex vex) { +- this.owner = vex.getOwner(); ++ if (entity instanceof Vex) { ++ Vex entityvex = (Vex) entity; ++ ++ this.owner = entityvex.getOwner(); + } ++ + } + + @Override +@@ -145,6 +151,7 @@ + if (this.hasLimitedLife) { + compound.putInt("LifeTicks", this.limitedLifeTicks); + } ++ + } + + @Nullable +@@ -163,19 +170,22 @@ + } + + private boolean getVexFlag(int mask) { +- int i = this.entityData.get(DATA_FLAGS_ID); +- return (i & mask) != 0; ++ byte b0 = (Byte) this.entityData.get(Vex.DATA_FLAGS_ID); ++ ++ return (b0 & mask) != 0; + } + + private void setVexFlag(int mask, boolean value) { +- int i = this.entityData.get(DATA_FLAGS_ID); ++ byte b0 = (Byte) this.entityData.get(Vex.DATA_FLAGS_ID); ++ int j; ++ + if (value) { +- i |= mask; ++ j = b0 | mask; + } else { +- i &= ~mask; ++ j = b0 & ~mask; + } + +- this.entityData.set(DATA_FLAGS_ID, (byte)(i & 0xFF)); ++ this.entityData.set(Vex.DATA_FLAGS_ID, (byte) (j & 255)); + } + + public boolean isCharging() { +@@ -217,12 +227,11 @@ + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- RandomSource random = level.getRandom(); +- this.populateDefaultEquipmentSlots(random, difficulty); +- this.populateDefaultEquipmentEnchantments(random, difficulty); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ RandomSource randomsource = level.getRandom(); ++ ++ this.populateDefaultEquipmentSlots(randomsource, difficulty); ++ this.populateDefaultEquipmentEnchantments(randomsource, difficulty); + return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + +@@ -238,23 +247,56 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height - 0.0625F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.0625F * f, 0.0F); + } + +- class VexChargeAttackGoal extends Goal { ++ private class VexMoveControl extends MoveControl { ++ ++ public VexMoveControl(Vex entityvex) { ++ super(entityvex); ++ } ++ ++ @Override ++ public void tick() { ++ if (this.operation == MoveControl.Operation.MOVE_TO) { ++ Vec3 vec3d = new Vec3(this.wantedX - Vex.this.getX(), this.wantedY - Vex.this.getY(), this.wantedZ - Vex.this.getZ()); ++ double d0 = vec3d.length(); ++ ++ if (d0 < Vex.this.getBoundingBox().getSize()) { ++ this.operation = MoveControl.Operation.WAIT; ++ Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().scale(0.5D)); ++ } else { ++ Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().add(vec3d.scale(this.speedModifier * 0.05D / d0))); ++ if (Vex.this.getTarget() == null) { ++ Vec3 vec3d1 = Vex.this.getDeltaMovement(); ++ ++ Vex.this.setYRot(-((float) Mth.atan2(vec3d1.x, vec3d1.z)) * 57.295776F); ++ Vex.this.yBodyRot = Vex.this.getYRot(); ++ } else { ++ double d1 = Vex.this.getTarget().getX() - Vex.this.getX(); ++ double d2 = Vex.this.getTarget().getZ() - Vex.this.getZ(); ++ ++ Vex.this.setYRot(-((float) Mth.atan2(d1, d2)) * 57.295776F); ++ Vex.this.yBodyRot = Vex.this.getYRot(); ++ } ++ } ++ ++ } ++ } ++ } ++ ++ private class VexChargeAttackGoal extends Goal { ++ + public VexChargeAttackGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override + public boolean canUse() { +- LivingEntity target = Vex.this.getTarget(); +- return target != null +- && target.isAlive() +- && !Vex.this.getMoveControl().hasWanted() +- && Vex.this.random.nextInt(reducedTickDelay(7)) == 0 +- && Vex.this.distanceToSqr(target) > 4.0; ++ LivingEntity entityliving = Vex.this.getTarget(); ++ ++ return entityliving != null && entityliving.isAlive() && !Vex.this.getMoveControl().hasWanted() && Vex.this.random.nextInt(reducedTickDelay(7)) == 0 ? Vex.this.distanceToSqr((Entity) entityliving) > 4.0D : false; + } + + @Override +@@ -264,10 +306,12 @@ + + @Override + public void start() { +- LivingEntity target = Vex.this.getTarget(); +- if (target != null) { +- Vec3 eyePosition = target.getEyePosition(); +- Vex.this.moveControl.setWantedPosition(eyePosition.x, eyePosition.y, eyePosition.z, 1.0); ++ LivingEntity entityliving = Vex.this.getTarget(); ++ ++ if (entityliving != null) { ++ Vec3 vec3d = entityliving.getEyePosition(); ++ ++ Vex.this.moveControl.setWantedPosition(vec3d.x, vec3d.y, vec3d.z, 1.0D); + } + + Vex.this.setIsCharging(true); +@@ -286,104 +330,82 @@ + + @Override + public void tick() { +- LivingEntity target = Vex.this.getTarget(); +- if (target != null) { +- if (Vex.this.getBoundingBox().intersects(target.getBoundingBox())) { +- Vex.this.doHurtTarget(target); ++ LivingEntity entityliving = Vex.this.getTarget(); ++ ++ if (entityliving != null) { ++ if (Vex.this.getBoundingBox().intersects(entityliving.getBoundingBox())) { ++ Vex.this.doHurtTarget(entityliving); + Vex.this.setIsCharging(false); + } else { +- double d = Vex.this.distanceToSqr(target); +- if (d < 9.0) { +- Vec3 eyePosition = target.getEyePosition(); +- Vex.this.moveControl.setWantedPosition(eyePosition.x, eyePosition.y, eyePosition.z, 1.0); ++ double d0 = Vex.this.distanceToSqr((Entity) entityliving); ++ ++ if (d0 < 9.0D) { ++ Vec3 vec3d = entityliving.getEyePosition(); ++ ++ Vex.this.moveControl.setWantedPosition(vec3d.x, vec3d.y, vec3d.z, 1.0D); + } + } ++ + } + } + } + +- class VexCopyOwnerTargetGoal extends TargetGoal { +- private final TargetingConditions copyOwnerTargeting = TargetingConditions.forNonCombat().ignoreLineOfSight().ignoreInvisibilityTesting(); ++ private class VexRandomMoveGoal extends Goal { + +- public VexCopyOwnerTargetGoal(PathfinderMob mob) { +- super(mob, false); ++ public VexRandomMoveGoal() { ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override + public boolean canUse() { +- return Vex.this.owner != null && Vex.this.owner.getTarget() != null && this.canAttack(Vex.this.owner.getTarget(), this.copyOwnerTargeting); ++ return !Vex.this.getMoveControl().hasWanted() && Vex.this.random.nextInt(reducedTickDelay(7)) == 0; + } + + @Override +- public void start() { +- Vex.this.setTarget(Vex.this.owner.getTarget()); +- super.start(); ++ public boolean canContinueToUse() { ++ return false; + } +- } + +- class VexMoveControl extends MoveControl { +- public VexMoveControl(Vex mob) { +- super(mob); +- } +- + @Override + public void tick() { +- if (this.operation == MoveControl.Operation.MOVE_TO) { +- Vec3 vec3 = new Vec3(this.wantedX - Vex.this.getX(), this.wantedY - Vex.this.getY(), this.wantedZ - Vex.this.getZ()); +- double len = vec3.length(); +- if (len < Vex.this.getBoundingBox().getSize()) { +- this.operation = MoveControl.Operation.WAIT; +- Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().scale(0.5)); +- } else { +- Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().add(vec3.scale(this.speedModifier * 0.05 / len))); ++ BlockPos blockposition = Vex.this.getBoundOrigin(); ++ ++ if (blockposition == null) { ++ blockposition = Vex.this.blockPosition(); ++ } ++ ++ for (int i = 0; i < 3; ++i) { ++ BlockPos blockposition1 = blockposition.offset(Vex.this.random.nextInt(15) - 7, Vex.this.random.nextInt(11) - 5, Vex.this.random.nextInt(15) - 7); ++ ++ if (Vex.this.level().isEmptyBlock(blockposition1)) { ++ Vex.this.moveControl.setWantedPosition((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.5D, (double) blockposition1.getZ() + 0.5D, 0.25D); + if (Vex.this.getTarget() == null) { +- Vec3 deltaMovement = Vex.this.getDeltaMovement(); +- Vex.this.setYRot(-((float)Mth.atan2(deltaMovement.x, deltaMovement.z)) * (180.0F / (float)Math.PI)); +- Vex.this.yBodyRot = Vex.this.getYRot(); +- } else { +- double d = Vex.this.getTarget().getX() - Vex.this.getX(); +- double d1 = Vex.this.getTarget().getZ() - Vex.this.getZ(); +- Vex.this.setYRot(-((float)Mth.atan2(d, d1)) * (180.0F / (float)Math.PI)); +- Vex.this.yBodyRot = Vex.this.getYRot(); ++ Vex.this.getLookControl().setLookAt((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.5D, (double) blockposition1.getZ() + 0.5D, 180.0F, 20.0F); + } ++ break; + } + } ++ + } + } + +- class VexRandomMoveGoal extends Goal { +- public VexRandomMoveGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ private class VexCopyOwnerTargetGoal extends TargetGoal { ++ ++ private final TargetingConditions copyOwnerTargeting = TargetingConditions.forNonCombat().ignoreLineOfSight().ignoreInvisibilityTesting(); ++ ++ public VexCopyOwnerTargetGoal(PathfinderMob entitycreature) { ++ super(entitycreature, false); + } + + @Override + public boolean canUse() { +- return !Vex.this.getMoveControl().hasWanted() && Vex.this.random.nextInt(reducedTickDelay(7)) == 0; ++ return Vex.this.owner != null && Vex.this.owner.getTarget() != null && this.canAttack(Vex.this.owner.getTarget(), this.copyOwnerTargeting); + } + + @Override +- public boolean canContinueToUse() { +- return false; ++ public void start() { ++ Vex.this.setTarget(Vex.this.owner.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.OWNER_ATTACKED_TARGET, true); // CraftBukkit ++ super.start(); + } +- +- @Override +- public void tick() { +- BlockPos boundOrigin = Vex.this.getBoundOrigin(); +- if (boundOrigin == null) { +- boundOrigin = Vex.this.blockPosition(); +- } +- +- for (int i = 0; i < 3; i++) { +- BlockPos blockPos = boundOrigin.offset(Vex.this.random.nextInt(15) - 7, Vex.this.random.nextInt(11) - 5, Vex.this.random.nextInt(15) - 7); +- if (Vex.this.level().isEmptyBlock(blockPos)) { +- Vex.this.moveControl.setWantedPosition((double)blockPos.getX() + 0.5, (double)blockPos.getY() + 0.5, (double)blockPos.getZ() + 0.5, 0.25); +- if (Vex.this.getTarget() == null) { +- Vex.this.getLookControl() +- .setLookAt((double)blockPos.getX() + 0.5, (double)blockPos.getY() + 0.5, (double)blockPos.getZ() + 0.5, 180.0F, 20.0F); +- } +- break; +- } +- } +- } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Witch.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Witch.java.patch new file mode 100644 index 0000000000..64cc833019 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Witch.java.patch @@ -0,0 +1,313 @@ +--- a/net/minecraft/world/entity/monster/Witch.java ++++ b/net/minecraft/world/entity/monster/Witch.java +@@ -1,7 +1,9 @@ + package net.minecraft.world.entity.monster; + ++import java.util.Iterator; + import java.util.List; + import java.util.UUID; ++import java.util.function.Predicate; + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; +@@ -15,10 +17,10 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -45,10 +47,9 @@ + import org.joml.Vector3f; + + public class Witch extends Raider implements RangedAttackMob { ++ + private static final UUID SPEED_MODIFIER_DRINKING_UUID = UUID.fromString("5CD17E52-A79A-43D3-A529-90FDE04B181E"); +- private static final AttributeModifier SPEED_MODIFIER_DRINKING = new AttributeModifier( +- SPEED_MODIFIER_DRINKING_UUID, "Drinking speed penalty", -0.25, AttributeModifier.Operation.ADDITION +- ); ++ private static final AttributeModifier SPEED_MODIFIER_DRINKING = new AttributeModifier(Witch.SPEED_MODIFIER_DRINKING_UUID, "Drinking speed penalty", -0.25D, AttributeModifier.Operation.ADDITION); + private static final EntityDataAccessor DATA_USING_ITEM = SynchedEntityData.defineId(Witch.class, EntityDataSerializers.BOOLEAN); + private int usingTime; + private NearestHealableRaiderTargetGoal healRaidersGoal; +@@ -61,16 +62,16 @@ + @Override + protected void registerGoals() { + super.registerGoals(); +- this.healRaidersGoal = new NearestHealableRaiderTargetGoal<>( +- this, Raider.class, true, livingEntity -> livingEntity != null && this.hasActiveRaid() && livingEntity.getType() != EntityType.WITCH +- ); +- this.attackPlayersGoal = new NearestAttackableWitchTargetGoal<>(this, Player.class, 10, true, false, null); ++ this.healRaidersGoal = new NearestHealableRaiderTargetGoal<>(this, Raider.class, true, (entityliving) -> { ++ return entityliving != null && this.hasActiveRaid() && entityliving.getType() != EntityType.WITCH; ++ }); ++ this.attackPlayersGoal = new NearestAttackableWitchTargetGoal<>(this, Player.class, 10, true, false, (Predicate) null); + this.goalSelector.addGoal(1, new FloatGoal(this)); +- this.goalSelector.addGoal(2, new RangedAttackGoal(this, 1.0, 60, 10.0F)); +- this.goalSelector.addGoal(2, new WaterAvoidingRandomStrollGoal(this, 1.0)); ++ this.goalSelector.addGoal(2, new RangedAttackGoal(this, 1.0D, 60, 10.0F)); ++ this.goalSelector.addGoal(2, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.goalSelector.addGoal(3, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(3, new RandomLookAroundGoal(this)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Raider.class)); ++ this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[]{Raider.class})); + this.targetSelector.addGoal(2, this.healRaidersGoal); + this.targetSelector.addGoal(3, this.attackPlayersGoal); + } +@@ -78,7 +79,7 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.getEntityData().define(DATA_USING_ITEM, false); ++ this.getEntityData().define(Witch.DATA_USING_ITEM, false); + } + + @Override +@@ -97,15 +98,15 @@ + } + + public void setUsingItem(boolean usingItem) { +- this.getEntityData().set(DATA_USING_ITEM, usingItem); ++ this.getEntityData().set(Witch.DATA_USING_ITEM, usingItem); + } + + public boolean isDrinkingPotion() { +- return this.getEntityData().get(DATA_USING_ITEM); ++ return (Boolean) this.getEntityData().get(Witch.DATA_USING_ITEM); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 26.0).add(Attributes.MOVEMENT_SPEED, 0.25); ++ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 26.0D).add(Attributes.MOVEMENT_SPEED, 0.25D); + } + + @Override +@@ -121,63 +122,56 @@ + if (this.isDrinkingPotion()) { + if (this.usingTime-- <= 0) { + this.setUsingItem(false); +- ItemStack mainHandItem = this.getMainHandItem(); ++ ItemStack itemstack = this.getMainHandItem(); ++ + this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); +- if (mainHandItem.is(Items.POTION)) { +- List mobEffects = PotionUtils.getMobEffects(mainHandItem); +- if (mobEffects != null) { +- for (MobEffectInstance mobEffectInstance : mobEffects) { +- this.addEffect(new MobEffectInstance(mobEffectInstance)); ++ if (itemstack.is(Items.POTION)) { ++ List list = PotionUtils.getMobEffects(itemstack); ++ ++ if (list != null) { ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); ++ ++ this.addEffect(new MobEffectInstance(mobeffect), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + } + + this.gameEvent(GameEvent.DRINK); +- this.getAttribute(Attributes.MOVEMENT_SPEED).removeModifier(SPEED_MODIFIER_DRINKING.getId()); ++ this.getAttribute(Attributes.MOVEMENT_SPEED).removeModifier(Witch.SPEED_MODIFIER_DRINKING.getId()); + } + } else { +- Potion potion = null; ++ Potion potionregistry = null; ++ + if (this.random.nextFloat() < 0.15F && this.isEyeInFluid(FluidTags.WATER) && !this.hasEffect(MobEffects.WATER_BREATHING)) { +- potion = Potions.WATER_BREATHING; +- } else if (this.random.nextFloat() < 0.15F +- && (this.isOnFire() || this.getLastDamageSource() != null && this.getLastDamageSource().is(DamageTypeTags.IS_FIRE)) +- && !this.hasEffect(MobEffects.FIRE_RESISTANCE)) { +- potion = Potions.FIRE_RESISTANCE; ++ potionregistry = Potions.WATER_BREATHING; ++ } else if (this.random.nextFloat() < 0.15F && (this.isOnFire() || this.getLastDamageSource() != null && this.getLastDamageSource().is(DamageTypeTags.IS_FIRE)) && !this.hasEffect(MobEffects.FIRE_RESISTANCE)) { ++ potionregistry = Potions.FIRE_RESISTANCE; + } else if (this.random.nextFloat() < 0.05F && this.getHealth() < this.getMaxHealth()) { +- potion = Potions.HEALING; +- } else if (this.random.nextFloat() < 0.5F +- && this.getTarget() != null +- && !this.hasEffect(MobEffects.MOVEMENT_SPEED) +- && this.getTarget().distanceToSqr(this) > 121.0) { +- potion = Potions.SWIFTNESS; ++ potionregistry = Potions.HEALING; ++ } else if (this.random.nextFloat() < 0.5F && this.getTarget() != null && !this.hasEffect(MobEffects.MOVEMENT_SPEED) && this.getTarget().distanceToSqr((Entity) this) > 121.0D) { ++ potionregistry = Potions.SWIFTNESS; + } + +- if (potion != null) { +- this.setItemSlot(EquipmentSlot.MAINHAND, PotionUtils.setPotion(new ItemStack(Items.POTION), potion)); ++ if (potionregistry != null) { ++ this.setItemSlot(EquipmentSlot.MAINHAND, PotionUtils.setPotion(new ItemStack(Items.POTION), potionregistry)); + this.usingTime = this.getMainHandItem().getUseDuration(); + this.setUsingItem(true); + if (!this.isSilent()) { +- this.level() +- .playSound( +- null, +- this.getX(), +- this.getY(), +- this.getZ(), +- SoundEvents.WITCH_DRINK, +- this.getSoundSource(), +- 1.0F, +- 0.8F + this.random.nextFloat() * 0.4F +- ); ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.WITCH_DRINK, this.getSoundSource(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); + } + +- AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED); +- attribute.removeModifier(SPEED_MODIFIER_DRINKING.getId()); +- attribute.addTransientModifier(SPEED_MODIFIER_DRINKING); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ ++ attributemodifiable.removeModifier(Witch.SPEED_MODIFIER_DRINKING.getId()); ++ attributemodifiable.addTransientModifier(Witch.SPEED_MODIFIER_DRINKING); + } + } + + if (this.random.nextFloat() < 7.5E-4F) { +- this.level().broadcastEntityEvent(this, (byte)15); ++ this.level().broadcastEntityEvent(this, (byte) 15); + } + } + +@@ -192,97 +186,80 @@ + @Override + public void handleEntityEvent(byte id) { + if (id == 15) { +- for (int i = 0; i < this.random.nextInt(35) + 10; i++) { +- this.level() +- .addParticle( +- ParticleTypes.WITCH, +- this.getX() + this.random.nextGaussian() * 0.13F, +- this.getBoundingBox().maxY + 0.5 + this.random.nextGaussian() * 0.13F, +- this.getZ() + this.random.nextGaussian() * 0.13F, +- 0.0, +- 0.0, +- 0.0 +- ); ++ for (int i = 0; i < this.random.nextInt(35) + 10; ++i) { ++ this.level().addParticle(ParticleTypes.WITCH, this.getX() + this.random.nextGaussian() * 0.12999999523162842D, this.getBoundingBox().maxY + 0.5D + this.random.nextGaussian() * 0.12999999523162842D, this.getZ() + this.random.nextGaussian() * 0.12999999523162842D, 0.0D, 0.0D, 0.0D); + } + } else { + super.handleEntityEvent(id); + } ++ + } + + @Override + protected float getDamageAfterMagicAbsorb(DamageSource source, float damage) { +- float var3 = super.getDamageAfterMagicAbsorb(source, damage); ++ damage = super.getDamageAfterMagicAbsorb(source, damage); + if (source.getEntity() == this) { +- var3 = 0.0F; ++ damage = 0.0F; + } + + if (source.is(DamageTypeTags.WITCH_RESISTANT_TO)) { +- var3 *= 0.15F; ++ damage *= 0.15F; + } + +- return var3; ++ return damage; + } + + @Override + public void performRangedAttack(LivingEntity target, float distanceFactor) { + if (!this.isDrinkingPotion()) { +- Vec3 deltaMovement = target.getDeltaMovement(); +- double d = target.getX() + deltaMovement.x - this.getX(); +- double d1 = target.getEyeY() - 1.1F - this.getY(); +- double d2 = target.getZ() + deltaMovement.z - this.getZ(); +- double squareRoot = Math.sqrt(d * d + d2 * d2); +- Potion potion = Potions.HARMING; ++ Vec3 vec3d = target.getDeltaMovement(); ++ double d0 = target.getX() + vec3d.x - this.getX(); ++ double d1 = target.getEyeY() - 1.100000023841858D - this.getY(); ++ double d2 = target.getZ() + vec3d.z - this.getZ(); ++ double d3 = Math.sqrt(d0 * d0 + d2 * d2); ++ Potion potionregistry = Potions.HARMING; ++ + if (target instanceof Raider) { + if (target.getHealth() <= 4.0F) { +- potion = Potions.HEALING; ++ potionregistry = Potions.HEALING; + } else { +- potion = Potions.REGENERATION; ++ potionregistry = Potions.REGENERATION; + } + +- this.setTarget(null); +- } else if (squareRoot >= 8.0 && !target.hasEffect(MobEffects.MOVEMENT_SLOWDOWN)) { +- potion = Potions.SLOWNESS; ++ this.setTarget((LivingEntity) null); ++ } else if (d3 >= 8.0D && !target.hasEffect(MobEffects.MOVEMENT_SLOWDOWN)) { ++ potionregistry = Potions.SLOWNESS; + } else if (target.getHealth() >= 8.0F && !target.hasEffect(MobEffects.POISON)) { +- potion = Potions.POISON; +- } else if (squareRoot <= 3.0 && !target.hasEffect(MobEffects.WEAKNESS) && this.random.nextFloat() < 0.25F) { +- potion = Potions.WEAKNESS; ++ potionregistry = Potions.POISON; ++ } else if (d3 <= 3.0D && !target.hasEffect(MobEffects.WEAKNESS) && this.random.nextFloat() < 0.25F) { ++ potionregistry = Potions.WEAKNESS; + } + +- ThrownPotion thrownPotion = new ThrownPotion(this.level(), this); +- thrownPotion.setItem(PotionUtils.setPotion(new ItemStack(Items.SPLASH_POTION), potion)); +- thrownPotion.setXRot(thrownPotion.getXRot() - -20.0F); +- thrownPotion.shoot(d, d1 + squareRoot * 0.2, d2, 0.75F, 8.0F); ++ ThrownPotion entitypotion = new ThrownPotion(this.level(), this); ++ ++ entitypotion.setItem(PotionUtils.setPotion(new ItemStack(Items.SPLASH_POTION), potionregistry)); ++ entitypotion.setXRot(entitypotion.getXRot() - -20.0F); ++ entitypotion.shoot(d0, d1 + d3 * 0.2D, d2, 0.75F, 8.0F); + if (!this.isSilent()) { +- this.level() +- .playSound( +- null, +- this.getX(), +- this.getY(), +- this.getZ(), +- SoundEvents.WITCH_THROW, +- this.getSoundSource(), +- 1.0F, +- 0.8F + this.random.nextFloat() * 0.4F +- ); ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.WITCH_THROW, this.getSoundSource(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); + } + +- this.level().addFreshEntity(thrownPotion); ++ this.level().addFreshEntity(entitypotion); + } + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 1.62F; + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.3125F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.3125F * f, 0.0F); + } + + @Override +- public void applyRaidBuffs(int wave, boolean unusedFalse) { +- } ++ public void applyRaidBuffs(int wave, boolean unusedFalse) {} + + @Override + public boolean canBeLeader() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/WitherSkeleton.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/WitherSkeleton.java.patch new file mode 100644 index 0000000000..7ece9183c9 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/WitherSkeleton.java.patch @@ -0,0 +1,110 @@ +--- a/net/minecraft/world/entity/monster/WitherSkeleton.java ++++ b/net/minecraft/world/entity/monster/WitherSkeleton.java +@@ -11,23 +11,25 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; + import net.minecraft.world.entity.monster.piglin.AbstractPiglin; + import net.minecraft.world.entity.projectile.AbstractArrow; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + + public class WitherSkeleton extends AbstractSkeleton { ++ + public WitherSkeleton(EntityType entityType, Level level) { + super(entityType, level); + this.setPathfindingMalus(BlockPathTypes.LAVA, 8.0F); +@@ -62,10 +64,17 @@ + @Override + protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { + super.dropCustomDeathLoot(source, looting, recentlyHit); +- if (source.getEntity() instanceof Creeper creeper && creeper.canDropMobsSkull()) { +- creeper.increaseDroppedSkulls(); +- this.spawnAtLocation(Items.WITHER_SKELETON_SKULL); ++ Entity entity = source.getEntity(); ++ ++ if (entity instanceof Creeper) { ++ Creeper entitycreeper = (Creeper) entity; ++ ++ if (entitycreeper.canDropMobsSkull()) { ++ entitycreeper.increaseDroppedSkulls(); ++ this.spawnAtLocation((IMaterial) Items.WITHER_SKELETON_SKULL); ++ } + } ++ + } + + @Override +@@ -74,22 +83,20 @@ + } + + @Override +- protected void populateDefaultEquipmentEnchantments(RandomSource random, DifficultyInstance difficulty) { +- } ++ protected void populateDefaultEquipmentEnchantments(RandomSource random, DifficultyInstance difficulty) {} + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- SpawnGroupData spawnGroupData = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); +- this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(4.0); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ GroupDataEntity groupdataentity1 = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ ++ this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(4.0D); + this.reassessWeaponGoal(); +- return spawnGroupData; ++ return groupdataentity1; + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 2.1F; + } + +@@ -104,7 +111,7 @@ + return false; + } else { + if (entity instanceof LivingEntity) { +- ((LivingEntity)entity).addEffect(new MobEffectInstance(MobEffects.WITHER, 200), this); ++ ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.WITHER, 200), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + + return true; +@@ -113,13 +120,14 @@ + + @Override + protected AbstractArrow getArrow(ItemStack arrowStack, float distanceFactor) { +- AbstractArrow abstractArrow = super.getArrow(arrowStack, distanceFactor); +- abstractArrow.setSecondsOnFire(100); +- return abstractArrow; ++ AbstractArrow entityarrow = super.getArrow(arrowStack, distanceFactor); ++ ++ entityarrow.setSecondsOnFire(100); ++ return entityarrow; + } + + @Override + public boolean canBeAffected(MobEffectInstance potioneffect) { +- return potioneffect.getEffect() != MobEffects.WITHER && super.canBeAffected(potioneffect); ++ return potioneffect.getEffect() == MobEffects.WITHER ? false : super.canBeAffected(potioneffect); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Zombie.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Zombie.java.patch new file mode 100644 index 0000000000..d2568e3ef0 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Zombie.java.patch @@ -0,0 +1,718 @@ +--- a/net/minecraft/world/entity/monster/Zombie.java ++++ b/net/minecraft/world/entity/monster/Zombie.java +@@ -6,17 +6,6 @@ + import java.util.UUID; + import java.util.function.Predicate; + import javax.annotation.Nullable; +-import net.minecraft.core.BlockPos; +-import net.minecraft.nbt.CompoundTag; +-import net.minecraft.nbt.NbtOps; +-import net.minecraft.network.syncher.EntityDataAccessor; +-import net.minecraft.network.syncher.EntityDataSerializers; +-import net.minecraft.network.syncher.SynchedEntityData; +-import net.minecraft.server.level.ServerLevel; +-import net.minecraft.sounds.SoundEvent; +-import net.minecraft.sounds.SoundEvents; +-import net.minecraft.sounds.SoundSource; +-import net.minecraft.tags.FluidTags; + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.world.Difficulty; +@@ -24,15 +13,15 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; + import net.minecraft.world.entity.PathfinderMob; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.SpawnPlacements; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; +@@ -63,31 +52,53 @@ + import net.minecraft.world.level.NaturalSpawner; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import org.joml.Vector3f; ++import net.minecraft.core.BlockPos; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.Tag; ++import net.minecraft.network.syncher.EntityDataAccessor; ++import net.minecraft.network.syncher.EntityDataSerializers; ++import net.minecraft.network.syncher.SynchedEntityData; ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundEvents; ++import net.minecraft.sounds.SoundSource; ++import net.minecraft.tags.FluidTags; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++// CraftBukkit end + + public class Zombie extends Monster { ++ + private static final UUID SPEED_MODIFIER_BABY_UUID = UUID.fromString("B9766B59-9566-4402-BC1F-2EE2A276D836"); +- private static final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier( +- SPEED_MODIFIER_BABY_UUID, "Baby speed boost", 0.5, AttributeModifier.Operation.MULTIPLY_BASE +- ); ++ private static final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier(Zombie.SPEED_MODIFIER_BABY_UUID, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE); + private static final EntityDataAccessor DATA_BABY_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_SPECIAL_TYPE_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.INT); +- private static final EntityDataAccessor DATA_DROWNED_CONVERSION_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); ++ public static final EntityDataAccessor DATA_DROWNED_CONVERSION_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); + public static final float ZOMBIE_LEADER_CHANCE = 0.05F; + public static final int REINFORCEMENT_ATTEMPTS = 50; + public static final int REINFORCEMENT_RANGE_MAX = 40; + public static final int REINFORCEMENT_RANGE_MIN = 7; + protected static final float BABY_EYE_HEIGHT_ADJUSTMENT = 0.81F; + private static final float BREAK_DOOR_CHANCE = 0.1F; +- private static final Predicate DOOR_BREAKING_PREDICATE = difficulty -> difficulty == Difficulty.HARD; +- private final BreakDoorGoal breakDoorGoal = new BreakDoorGoal(this, DOOR_BREAKING_PREDICATE); ++ private static final Predicate DOOR_BREAKING_PREDICATE = (enumdifficulty) -> { ++ return enumdifficulty == Difficulty.HARD; ++ }; ++ private final BreakDoorGoal breakDoorGoal; + private boolean canBreakDoors; + private int inWaterTime; +- private int conversionTime; ++ public int conversionTime; ++ private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field + + public Zombie(EntityType entityType, Level level) { + super(entityType, level); ++ this.breakDoorGoal = new BreakDoorGoal(this, Zombie.DOOR_BREAKING_PREDICATE); + } + + public Zombie(Level level) { +@@ -96,17 +107,17 @@ + + @Override + protected void registerGoals() { +- this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0, 3)); ++ this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0D, 3)); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); + this.addBehaviourGoals(); + } + + protected void addBehaviourGoals() { +- this.goalSelector.addGoal(2, new ZombieAttackGoal(this, 1.0, false)); +- this.goalSelector.addGoal(6, new MoveThroughVillageGoal(this, 1.0, true, 4, this::canBreakDoors)); +- this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers(ZombifiedPiglin.class)); ++ this.goalSelector.addGoal(2, new ZombieAttackGoal(this, 1.0D, false)); ++ this.goalSelector.addGoal(6, new MoveThroughVillageGoal(this, 1.0D, true, 4, this::canBreakDoors)); ++ this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D)); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[0])).setAlertOthers(ZombifiedPiglin.class)); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); +@@ -114,24 +125,19 @@ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes() +- .add(Attributes.FOLLOW_RANGE, 35.0) +- .add(Attributes.MOVEMENT_SPEED, 0.23F) +- .add(Attributes.ATTACK_DAMAGE, 3.0) +- .add(Attributes.ARMOR, 2.0) +- .add(Attributes.SPAWN_REINFORCEMENTS_CHANCE); ++ return Monster.createMonsterAttributes().add(Attributes.FOLLOW_RANGE, 35.0D).add(Attributes.MOVEMENT_SPEED, 0.23000000417232513D).add(Attributes.ATTACK_DAMAGE, 3.0D).add(Attributes.ARMOR, 2.0D).add(Attributes.SPAWN_REINFORCEMENTS_CHANCE); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.getEntityData().define(DATA_BABY_ID, false); +- this.getEntityData().define(DATA_SPECIAL_TYPE_ID, 0); +- this.getEntityData().define(DATA_DROWNED_CONVERSION_ID, false); ++ this.getEntityData().define(Zombie.DATA_BABY_ID, false); ++ this.getEntityData().define(Zombie.DATA_SPECIAL_TYPE_ID, 0); ++ this.getEntityData().define(Zombie.DATA_DROWNED_CONVERSION_ID, false); + } + + public boolean isUnderWaterConverting() { +- return this.getEntityData().get(DATA_DROWNED_CONVERSION_ID); ++ return (Boolean) this.getEntityData().get(Zombie.DATA_DROWNED_CONVERSION_ID); + } + + public boolean canBreakDoors() { +@@ -142,7 +148,7 @@ + if (this.supportsBreakDoorGoal() && GoalUtils.hasGroundPathNavigation(this)) { + if (this.canBreakDoors != canBreakDoors) { + this.canBreakDoors = canBreakDoors; +- ((GroundPathNavigation)this.getNavigation()).setCanOpenDoors(canBreakDoors); ++ ((GroundPathNavigation) this.getNavigation()).setCanOpenDoors(canBreakDoors); + if (canBreakDoors) { + this.goalSelector.addGoal(1, this.breakDoorGoal); + } else { +@@ -153,6 +159,7 @@ + this.goalSelector.removeGoal(this.breakDoorGoal); + this.canBreakDoors = false; + } ++ + } + + protected boolean supportsBreakDoorGoal() { +@@ -161,13 +168,13 @@ + + @Override + public boolean isBaby() { +- return this.getEntityData().get(DATA_BABY_ID); ++ return (Boolean) this.getEntityData().get(Zombie.DATA_BABY_ID); + } + + @Override + public int getExperienceReward() { + if (this.isBaby()) { +- this.xpReward = (int)((double)this.xpReward * 2.5); ++ this.xpReward = (int) ((double) this.xpReward * 2.5D); + } + + return super.getExperienceReward(); +@@ -175,19 +182,21 @@ + + @Override + public void setBaby(boolean childZombie) { +- this.getEntityData().set(DATA_BABY_ID, childZombie); ++ this.getEntityData().set(Zombie.DATA_BABY_ID, childZombie); + if (this.level() != null && !this.level().isClientSide) { +- AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED); +- attribute.removeModifier(SPEED_MODIFIER_BABY.getId()); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ ++ attributemodifiable.removeModifier(Zombie.SPEED_MODIFIER_BABY.getId()); + if (childZombie) { +- attribute.addTransientModifier(SPEED_MODIFIER_BABY); ++ attributemodifiable.addTransientModifier(Zombie.SPEED_MODIFIER_BABY); + } + } ++ + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { +- if (DATA_BABY_ID.equals(key)) { ++ if (Zombie.DATA_BABY_ID.equals(key)) { + this.refreshDimensions(); + } + +@@ -202,13 +211,16 @@ + public void tick() { + if (!this.level().isClientSide && this.isAlive() && !this.isNoAi()) { + if (this.isUnderWaterConverting()) { +- this.conversionTime--; ++ // CraftBukkit start - Use wall time instead of ticks for conversion ++ int elapsedTicks = MinecraftServer.currentTick - this.lastTick; ++ this.conversionTime -= elapsedTicks; ++ // CraftBukkit end + if (this.conversionTime < 0) { + this.doUnderWaterConversion(); + } + } else if (this.convertsInWater()) { + if (this.isEyeInFluid(FluidTags.WATER)) { +- this.inWaterTime++; ++ ++this.inWaterTime; + if (this.inWaterTime >= 600) { + this.startUnderWaterConversion(300); + } +@@ -219,18 +231,21 @@ + } + + super.tick(); ++ this.lastTick = MinecraftServer.currentTick; // CraftBukkit + } + + @Override + public void aiStep() { + if (this.isAlive()) { + boolean flag = this.isSunSensitive() && this.isSunBurnTick(); ++ + if (flag) { +- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.HEAD); +- if (!itemBySlot.isEmpty()) { +- if (itemBySlot.isDamageableItem()) { +- itemBySlot.setDamageValue(itemBySlot.getDamageValue() + this.random.nextInt(2)); +- if (itemBySlot.getDamageValue() >= itemBySlot.getMaxDamage()) { ++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); ++ ++ if (!itemstack.isEmpty()) { ++ if (itemstack.isDamageableItem()) { ++ itemstack.setDamageValue(itemstack.getDamageValue() + this.random.nextInt(2)); ++ if (itemstack.getDamageValue() >= itemstack.getMaxDamage()) { + this.broadcastBreakEvent(EquipmentSlot.HEAD); + this.setItemSlot(EquipmentSlot.HEAD, ItemStack.EMPTY); + } +@@ -248,24 +263,32 @@ + super.aiStep(); + } + +- private void startUnderWaterConversion(int conversionTime) { ++ public void startUnderWaterConversion(int conversionTime) { ++ this.lastTick = MinecraftServer.currentTick; // CraftBukkit + this.conversionTime = conversionTime; +- this.getEntityData().set(DATA_DROWNED_CONVERSION_ID, true); ++ this.getEntityData().set(Zombie.DATA_DROWNED_CONVERSION_ID, true); + } + + protected void doUnderWaterConversion() { + this.convertToZombieType(EntityType.DROWNED); + if (!this.isSilent()) { +- this.level().levelEvent(null, 1040, this.blockPosition(), 0); ++ this.level().levelEvent((Player) null, 1040, this.blockPosition(), 0); + } ++ + } + + protected void convertToZombieType(EntityType entityType) { +- Zombie zombie = this.convertTo(entityType, true); +- if (zombie != null) { +- zombie.handleAttributes(zombie.level().getCurrentDifficultyAt(zombie.blockPosition()).getSpecialMultiplier()); +- zombie.setCanBreakDoors(zombie.supportsBreakDoorGoal() && this.canBreakDoors()); ++ Zombie entityzombie = (Zombie) this.convertTo(entityType, true, EntityTransformEvent.TransformReason.DROWNED, CreatureSpawnEvent.SpawnReason.DROWNED); ++ ++ if (entityzombie != null) { ++ entityzombie.handleAttributes(entityzombie.level().getCurrentDifficultyAt(entityzombie.blockPosition()).getSpecialMultiplier()); ++ entityzombie.setCanBreakDoors(entityzombie.supportsBreakDoorGoal() && this.canBreakDoors()); ++ // CraftBukkit start - SPIGOT-5208: End conversion to stop event spam ++ } else { ++ ((org.bukkit.entity.Zombie) getBukkitEntity()).setConversionTime(-1); ++ // CraftBukkit end + } ++ + } + + protected boolean isSunSensitive() { +@@ -279,44 +302,35 @@ + } else if (!(this.level() instanceof ServerLevel)) { + return false; + } else { +- ServerLevel serverLevel = (ServerLevel)this.level(); +- LivingEntity target = this.getTarget(); +- if (target == null && source.getEntity() instanceof LivingEntity) { +- target = (LivingEntity)source.getEntity(); ++ ServerLevel worldserver = (ServerLevel) this.level(); ++ LivingEntity entityliving = this.getTarget(); ++ ++ if (entityliving == null && source.getEntity() instanceof LivingEntity) { ++ entityliving = (LivingEntity) source.getEntity(); + } + +- if (target != null +- && this.level().getDifficulty() == Difficulty.HARD +- && (double)this.random.nextFloat() < this.getAttributeValue(Attributes.SPAWN_REINFORCEMENTS_CHANCE) +- && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { +- int floor = Mth.floor(this.getX()); +- int floor1 = Mth.floor(this.getY()); +- int floor2 = Mth.floor(this.getZ()); +- Zombie zombie = new Zombie(this.level()); ++ if (entityliving != null && this.level().getDifficulty() == Difficulty.HARD && (double) this.random.nextFloat() < this.getAttributeValue(Attributes.SPAWN_REINFORCEMENTS_CHANCE) && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { ++ int i = Mth.floor(this.getX()); ++ int j = Mth.floor(this.getY()); ++ int k = Mth.floor(this.getZ()); ++ Zombie entityzombie = new Zombie(this.level()); + +- for (int i = 0; i < 50; i++) { +- int i1 = floor + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); +- int i2 = floor1 + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); +- int i3 = floor2 + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); +- BlockPos blockPos = new BlockPos(i1, i2, i3); +- EntityType type = zombie.getType(); +- SpawnPlacements.Type placementType = SpawnPlacements.getPlacementType(type); +- if (NaturalSpawner.isSpawnPositionOk(placementType, this.level(), blockPos, type) +- && SpawnPlacements.checkSpawnRules(type, serverLevel, MobSpawnType.REINFORCEMENT, blockPos, this.level().random)) { +- zombie.setPos((double)i1, (double)i2, (double)i3); +- if (!this.level().hasNearbyAlivePlayer((double)i1, (double)i2, (double)i3, 7.0) +- && this.level().isUnobstructed(zombie) +- && this.level().noCollision(zombie) +- && !this.level().containsAnyLiquid(zombie.getBoundingBox())) { +- zombie.setTarget(target); +- zombie.finalizeSpawn( +- serverLevel, this.level().getCurrentDifficultyAt(zombie.blockPosition()), MobSpawnType.REINFORCEMENT, null, null +- ); +- serverLevel.addFreshEntityWithPassengers(zombie); +- this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE) +- .addPermanentModifier(new AttributeModifier("Zombie reinforcement caller charge", -0.05F, AttributeModifier.Operation.ADDITION)); +- zombie.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE) +- .addPermanentModifier(new AttributeModifier("Zombie reinforcement callee charge", -0.05F, AttributeModifier.Operation.ADDITION)); ++ for (int l = 0; l < 50; ++l) { ++ int i1 = i + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); ++ int j1 = j + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); ++ int k1 = k + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); ++ BlockPos blockposition = new BlockPos(i1, j1, k1); ++ EntityType entitytypes = entityzombie.getType(); ++ SpawnPlacements.Surface entitypositiontypes_surface = SpawnPlacements.getPlacementType(entitytypes); ++ ++ if (NaturalSpawner.isSpawnPositionOk(entitypositiontypes_surface, this.level(), blockposition, entitytypes) && SpawnPlacements.checkSpawnRules(entitytypes, worldserver, EnumMobSpawn.REINFORCEMENT, blockposition, this.level().random)) { ++ entityzombie.setPos((double) i1, (double) j1, (double) k1); ++ if (!this.level().hasNearbyAlivePlayer((double) i1, (double) j1, (double) k1, 7.0D) && this.level().isUnobstructed(entityzombie) && this.level().noCollision((Entity) entityzombie) && !this.level().containsAnyLiquid(entityzombie.getBoundingBox())) { ++ entityzombie.setTarget(entityliving, EntityTargetEvent.TargetReason.REINFORCEMENT_TARGET, true); // CraftBukkit ++ entityzombie.finalizeSpawn(worldserver, this.level().getCurrentDifficultyAt(entityzombie.blockPosition()), EnumMobSpawn.REINFORCEMENT, (GroupDataEntity) null, (CompoundTag) null); ++ worldserver.addFreshEntityWithPassengers(entityzombie, CreatureSpawnEvent.SpawnReason.REINFORCEMENTS); // CraftBukkit ++ this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).addPermanentModifier(new AttributeModifier("Zombie reinforcement caller charge", -0.05000000074505806D, AttributeModifier.Operation.ADDITION)); ++ entityzombie.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).addPermanentModifier(new AttributeModifier("Zombie reinforcement callee charge", -0.05000000074505806D, AttributeModifier.Operation.ADDITION)); + break; + } + } +@@ -330,10 +344,19 @@ + @Override + public boolean doHurtTarget(Entity entity) { + boolean flag = super.doHurtTarget(entity); ++ + if (flag) { +- float effectiveDifficulty = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty(); +- if (this.getMainHandItem().isEmpty() && this.isOnFire() && this.random.nextFloat() < effectiveDifficulty * 0.3F) { +- entity.setSecondsOnFire(2 * (int)effectiveDifficulty); ++ float f = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty(); ++ ++ if (this.getMainHandItem().isEmpty() && this.isOnFire() && this.random.nextFloat() < f * 0.3F) { ++ // CraftBukkit start ++ EntityCombustByEntityEvent event = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), 2 * (int) f); // PAIL: fixme ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ entity.setSecondsOnFire(event.getDuration(), false); ++ } ++ // CraftBukkit end + } + } + +@@ -360,26 +383,28 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(this.getStepSound(), 0.15F, 1.0F); + } + + @Override +- public MobType getMobType() { +- return MobType.UNDEAD; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.UNDEAD; + } + + @Override + protected void populateDefaultEquipmentSlots(RandomSource random, DifficultyInstance difficulty) { + super.populateDefaultEquipmentSlots(random, difficulty); + if (random.nextFloat() < (this.level().getDifficulty() == Difficulty.HARD ? 0.05F : 0.01F)) { +- int randomInt = random.nextInt(3); +- if (randomInt == 0) { ++ int i = random.nextInt(3); ++ ++ if (i == 0) { + this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.IRON_SWORD)); + } else { + this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.IRON_SHOVEL)); + } + } ++ + } + + @Override +@@ -400,107 +425,124 @@ + if (compound.contains("DrownedConversionTime", 99) && compound.getInt("DrownedConversionTime") > -1) { + this.startUnderWaterConversion(compound.getInt("DrownedConversionTime")); + } ++ + } + + @Override + public boolean killedEntity(ServerLevel level, LivingEntity entity) { + boolean flag = super.killedEntity(level, entity); +- if ((level.getDifficulty() == Difficulty.NORMAL || level.getDifficulty() == Difficulty.HARD) && entity instanceof Villager villager) { ++ ++ if ((level.getDifficulty() == Difficulty.NORMAL || level.getDifficulty() == Difficulty.HARD) && entity instanceof Villager) { ++ Villager entityvillager = (Villager) entity; ++ + if (level.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { + return flag; + } ++ // CraftBukkit start ++ flag = zombifyVillager(level, entityvillager, this.blockPosition(), this.isSilent(), CreatureSpawnEvent.SpawnReason.INFECTION) == null; ++ } + +- ZombieVillager zombieVillager = villager.convertTo(EntityType.ZOMBIE_VILLAGER, false); +- if (zombieVillager != null) { +- zombieVillager.finalizeSpawn( +- level, level.getCurrentDifficultyAt(zombieVillager.blockPosition()), MobSpawnType.CONVERSION, new Zombie.ZombieGroupData(false, true), null +- ); +- zombieVillager.setVillagerData(villager.getVillagerData()); +- zombieVillager.setGossips(villager.getGossips().store(NbtOps.INSTANCE)); +- zombieVillager.setTradeOffers(villager.getOffers().createTag()); +- zombieVillager.setVillagerXp(villager.getVillagerXp()); +- if (!this.isSilent()) { +- level.levelEvent(null, 1026, this.blockPosition(), 0); ++ return flag; ++ } ++ ++ public static ZombieVillager zombifyVillager(ServerLevel worldserver, Villager entityvillager, net.minecraft.core.BlockPos blockPosition, boolean silent, CreatureSpawnEvent.SpawnReason spawnReason) { ++ { ++ ZombieVillager entityzombievillager = (ZombieVillager) entityvillager.convertTo(EntityType.ZOMBIE_VILLAGER, false, EntityTransformEvent.TransformReason.INFECTION, spawnReason); ++ // CraftBukkit end ++ ++ if (entityzombievillager != null) { ++ entityzombievillager.finalizeSpawn(worldserver, worldserver.getCurrentDifficultyAt(entityzombievillager.blockPosition()), EnumMobSpawn.CONVERSION, new Zombie.ZombieGroupData(false, true), (CompoundTag) null); ++ entityzombievillager.setVillagerData(entityvillager.getVillagerData()); ++ entityzombievillager.setGossips((Tag) entityvillager.getGossips().store(NbtOps.INSTANCE)); ++ entityzombievillager.setTradeOffers(entityvillager.getOffers().createTag()); ++ entityzombievillager.setVillagerXp(entityvillager.getVillagerXp()); ++ // CraftBukkit start ++ if (!silent) { ++ worldserver.levelEvent((Player) null, 1026, blockPosition, 0); + } + +- flag = false; ++ // flag = false; + } +- } + +- return flag; ++ return entityzombievillager; ++ } ++ // CraftBukkit end + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return this.isBaby() ? 0.93F : 1.74F; + } + + @Override + public boolean canHoldItem(ItemStack stack) { +- return (!stack.is(Items.EGG) || !this.isBaby() || !this.isPassenger()) && super.canHoldItem(stack); ++ return stack.is(Items.EGG) && this.isBaby() && this.isPassenger() ? false : super.canHoldItem(stack); + } + + @Override + public boolean wantsToPickUp(ItemStack stack) { +- return !stack.is(Items.GLOW_INK_SAC) && super.wantsToPickUp(stack); ++ return stack.is(Items.GLOW_INK_SAC) ? false : super.wantsToPickUp(stack); + } + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- RandomSource random = level.getRandom(); +- SpawnGroupData var11 = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); +- float specialMultiplier = difficulty.getSpecialMultiplier(); +- this.setCanPickUpLoot(random.nextFloat() < 0.55F * specialMultiplier); +- if (var11 == null) { +- var11 = new Zombie.ZombieGroupData(getSpawnAsBabyOdds(random), true); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ RandomSource randomsource = level.getRandom(); ++ Object object = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ float f = difficulty.getSpecialMultiplier(); ++ ++ this.setCanPickUpLoot(randomsource.nextFloat() < 0.55F * f); ++ if (object == null) { ++ object = new Zombie.ZombieGroupData(getSpawnAsBabyOdds(randomsource), true); + } + +- if (var11 instanceof Zombie.ZombieGroupData zombieGroupData) { +- if (zombieGroupData.isBaby) { ++ if (object instanceof Zombie.ZombieGroupData) { ++ Zombie.ZombieGroupData entityzombie_groupdatazombie = (Zombie.ZombieGroupData) object; ++ ++ if (entityzombie_groupdatazombie.isBaby) { + this.setBaby(true); +- if (zombieGroupData.canSpawnJockey) { +- if ((double)random.nextFloat() < 0.05) { +- List entitiesOfClass = level.getEntitiesOfClass( +- Chicken.class, this.getBoundingBox().inflate(5.0, 3.0, 5.0), EntitySelector.ENTITY_NOT_BEING_RIDDEN +- ); +- if (!entitiesOfClass.isEmpty()) { +- Chicken chicken = entitiesOfClass.get(0); +- chicken.setChickenJockey(true); +- this.startRiding(chicken); ++ if (entityzombie_groupdatazombie.canSpawnJockey) { ++ if ((double) randomsource.nextFloat() < 0.05D) { ++ List list = level.getEntitiesOfClass(Chicken.class, this.getBoundingBox().inflate(5.0D, 3.0D, 5.0D), EntitySelector.ENTITY_NOT_BEING_RIDDEN); ++ ++ if (!list.isEmpty()) { ++ Chicken entitychicken = (Chicken) list.get(0); ++ ++ entitychicken.setChickenJockey(true); ++ this.startRiding(entitychicken); + } +- } else if ((double)random.nextFloat() < 0.05) { +- Chicken chicken1 = EntityType.CHICKEN.create(this.level()); +- if (chicken1 != null) { +- chicken1.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); +- chicken1.finalizeSpawn(level, difficulty, MobSpawnType.JOCKEY, null, null); +- chicken1.setChickenJockey(true); +- this.startRiding(chicken1); +- level.addFreshEntity(chicken1); ++ } else if ((double) randomsource.nextFloat() < 0.05D) { ++ Chicken entitychicken1 = (Chicken) EntityType.CHICKEN.create(this.level()); ++ ++ if (entitychicken1 != null) { ++ entitychicken1.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); ++ entitychicken1.finalizeSpawn(level, difficulty, EnumMobSpawn.JOCKEY, (GroupDataEntity) null, (CompoundTag) null); ++ entitychicken1.setChickenJockey(true); ++ this.startRiding(entitychicken1); ++ level.addFreshEntity(entitychicken1, CreatureSpawnEvent.SpawnReason.MOUNT); // CraftBukkit + } + } + } + } + +- this.setCanBreakDoors(this.supportsBreakDoorGoal() && random.nextFloat() < specialMultiplier * 0.1F); +- this.populateDefaultEquipmentSlots(random, difficulty); +- this.populateDefaultEquipmentEnchantments(random, difficulty); ++ this.setCanBreakDoors(this.supportsBreakDoorGoal() && randomsource.nextFloat() < f * 0.1F); ++ this.populateDefaultEquipmentSlots(randomsource, difficulty); ++ this.populateDefaultEquipmentEnchantments(randomsource, difficulty); + } + + if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { +- LocalDate localDate = LocalDate.now(); +- int i = localDate.get(ChronoField.DAY_OF_MONTH); +- int i1 = localDate.get(ChronoField.MONTH_OF_YEAR); +- if (i1 == 10 && i == 31 && random.nextFloat() < 0.25F) { +- this.setItemSlot(EquipmentSlot.HEAD, new ItemStack(random.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN)); ++ LocalDate localdate = LocalDate.now(); ++ int i = localdate.get(ChronoField.DAY_OF_MONTH); ++ int j = localdate.get(ChronoField.MONTH_OF_YEAR); ++ ++ if (j == 10 && i == 31 && randomsource.nextFloat() < 0.25F) { ++ this.setItemSlot(EquipmentSlot.HEAD, new ItemStack(randomsource.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN)); + this.armorDropChances[EquipmentSlot.HEAD.getIndex()] = 0.0F; + } + } + +- this.handleAttributes(specialMultiplier); +- return (SpawnGroupData)var11; ++ this.handleAttributes(f); ++ return (GroupDataEntity) object; + } + + public static boolean getSpawnAsBabyOdds(RandomSource random) { +@@ -509,32 +551,28 @@ + + protected void handleAttributes(float difficulty) { + this.randomizeReinforcementsChance(); +- this.getAttribute(Attributes.KNOCKBACK_RESISTANCE) +- .addPermanentModifier(new AttributeModifier("Random spawn bonus", this.random.nextDouble() * 0.05F, AttributeModifier.Operation.ADDITION)); +- double d = this.random.nextDouble() * 1.5 * (double)difficulty; +- if (d > 1.0) { +- this.getAttribute(Attributes.FOLLOW_RANGE) +- .addPermanentModifier(new AttributeModifier("Random zombie-spawn bonus", d, AttributeModifier.Operation.MULTIPLY_TOTAL)); ++ this.getAttribute(Attributes.KNOCKBACK_RESISTANCE).addPermanentModifier(new AttributeModifier("Random spawn bonus", this.random.nextDouble() * 0.05000000074505806D, AttributeModifier.Operation.ADDITION)); ++ double d0 = this.random.nextDouble() * 1.5D * (double) difficulty; ++ ++ if (d0 > 1.0D) { ++ this.getAttribute(Attributes.FOLLOW_RANGE).addPermanentModifier(new AttributeModifier("Random zombie-spawn bonus", d0, AttributeModifier.Operation.MULTIPLY_TOTAL)); + } + + if (this.random.nextFloat() < difficulty * 0.05F) { +- this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE) +- .addPermanentModifier(new AttributeModifier("Leader zombie bonus", this.random.nextDouble() * 0.25 + 0.5, AttributeModifier.Operation.ADDITION)); +- this.getAttribute(Attributes.MAX_HEALTH) +- .addPermanentModifier( +- new AttributeModifier("Leader zombie bonus", this.random.nextDouble() * 3.0 + 1.0, AttributeModifier.Operation.MULTIPLY_TOTAL) +- ); ++ this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).addPermanentModifier(new AttributeModifier("Leader zombie bonus", this.random.nextDouble() * 0.25D + 0.5D, AttributeModifier.Operation.ADDITION)); ++ this.getAttribute(Attributes.MAX_HEALTH).addPermanentModifier(new AttributeModifier("Leader zombie bonus", this.random.nextDouble() * 3.0D + 1.0D, AttributeModifier.Operation.MULTIPLY_TOTAL)); + this.setCanBreakDoors(this.supportsBreakDoorGoal()); + } ++ + } + + protected void randomizeReinforcementsChance() { +- this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(this.random.nextDouble() * 0.1F); ++ this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(this.random.nextDouble() * 0.10000000149011612D); + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.0625F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.0625F * f, 0.0F); + } + + @Override +@@ -545,41 +583,51 @@ + @Override + protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { + super.dropCustomDeathLoot(source, looting, recentlyHit); +- if (source.getEntity() instanceof Creeper creeper && creeper.canDropMobsSkull()) { +- ItemStack skull = this.getSkull(); +- if (!skull.isEmpty()) { +- creeper.increaseDroppedSkulls(); +- this.spawnAtLocation(skull); ++ Entity entity = source.getEntity(); ++ ++ if (entity instanceof Creeper) { ++ Creeper entitycreeper = (Creeper) entity; ++ ++ if (entitycreeper.canDropMobsSkull()) { ++ ItemStack itemstack = this.getSkull(); ++ ++ if (!itemstack.isEmpty()) { ++ entitycreeper.increaseDroppedSkulls(); ++ this.spawnAtLocation(itemstack); ++ } + } + } ++ + } + + protected ItemStack getSkull() { + return new ItemStack(Items.ZOMBIE_HEAD); + } + +- class ZombieAttackTurtleEggGoal extends RemoveBlockGoal { +- ZombieAttackTurtleEggGoal(PathfinderMob mob, double speedModifier, int verticalSearchRange) { +- super(Blocks.TURTLE_EGG, mob, speedModifier, verticalSearchRange); ++ private class ZombieAttackTurtleEggGoal extends RemoveBlockGoal { ++ ++ ZombieAttackTurtleEggGoal(PathfinderMob mob, double speedModifier, int i) { ++ super(Blocks.TURTLE_EGG, mob, speedModifier, i); + } + + @Override + public void playDestroyProgressSound(LevelAccessor level, BlockPos pos) { +- level.playSound(null, pos, SoundEvents.ZOMBIE_DESTROY_EGG, SoundSource.HOSTILE, 0.5F, 0.9F + Zombie.this.random.nextFloat() * 0.2F); ++ level.playSound((Player) null, pos, SoundEvents.ZOMBIE_DESTROY_EGG, SoundSource.HOSTILE, 0.5F, 0.9F + Zombie.this.random.nextFloat() * 0.2F); + } + + @Override + public void playBreakSound(Level level, BlockPos pos) { +- level.playSound(null, pos, SoundEvents.TURTLE_EGG_BREAK, SoundSource.BLOCKS, 0.7F, 0.9F + level.random.nextFloat() * 0.2F); ++ level.playSound((Player) null, pos, SoundEvents.TURTLE_EGG_BREAK, SoundSource.BLOCKS, 0.7F, 0.9F + level.random.nextFloat() * 0.2F); + } + + @Override + public double acceptedDistance() { +- return 1.14; ++ return 1.14D; + } + } + +- public static class ZombieGroupData implements SpawnGroupData { ++ public static class ZombieGroupData implements GroupDataEntity { ++ + public final boolean isBaby; + public final boolean canSpawnJockey; + diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/ZombieVillager.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/ZombieVillager.java.patch new file mode 100644 index 0000000000..e2bfe9f30e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/ZombieVillager.java.patch @@ -0,0 +1,389 @@ +--- a/net/minecraft/world/entity/monster/ZombieVillager.java ++++ b/net/minecraft/world/entity/monster/ZombieVillager.java +@@ -3,11 +3,11 @@ + import com.mojang.logging.LogUtils; + import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; ++import java.util.Objects; + import java.util.UUID; + import javax.annotation.Nullable; + import net.minecraft.advancements.CriteriaTriggers; + import net.minecraft.core.BlockPos; +-import net.minecraft.core.Holder; + import net.minecraft.core.registries.BuiltInRegistries; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtOps; +@@ -15,12 +15,8 @@ + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; +-import net.minecraft.server.level.ServerLevel; +-import net.minecraft.server.level.ServerPlayer; +-import net.minecraft.sounds.SoundEvent; +-import net.minecraft.sounds.SoundEvents; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffectInstance; +@@ -28,9 +24,9 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.ai.village.ReputationEventType; + import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.entity.npc.VillagerData; +@@ -46,50 +42,63 @@ + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.BedBlock; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import org.joml.Vector3f; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundEvents; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++// CraftBukkit end ++ + public class ZombieVillager extends Zombie implements VillagerDataHolder { ++ + private static final Logger LOGGER = LogUtils.getLogger(); +- private static final EntityDataAccessor DATA_CONVERTING_ID = SynchedEntityData.defineId(ZombieVillager.class, EntityDataSerializers.BOOLEAN); +- private static final EntityDataAccessor DATA_VILLAGER_DATA = SynchedEntityData.defineId( +- ZombieVillager.class, EntityDataSerializers.VILLAGER_DATA +- ); ++ public static final EntityDataAccessor DATA_CONVERTING_ID = SynchedEntityData.defineId(ZombieVillager.class, EntityDataSerializers.BOOLEAN); ++ private static final EntityDataAccessor DATA_VILLAGER_DATA = SynchedEntityData.defineId(ZombieVillager.class, EntityDataSerializers.VILLAGER_DATA); + private static final int VILLAGER_CONVERSION_WAIT_MIN = 3600; + private static final int VILLAGER_CONVERSION_WAIT_MAX = 6000; + private static final int MAX_SPECIAL_BLOCKS_COUNT = 14; + private static final int SPECIAL_BLOCK_RADIUS = 4; +- private int villagerConversionTime; ++ public int villagerConversionTime; + @Nullable +- private UUID conversionStarter; ++ public UUID conversionStarter; + @Nullable + private Tag gossips; + @Nullable + private CompoundTag tradeOffers; + private int villagerXp; ++ private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field + + public ZombieVillager(EntityType entityType, Level level) { + super(entityType, level); +- BuiltInRegistries.VILLAGER_PROFESSION +- .getRandom(this.random) +- .ifPresent(profession -> this.setVillagerData(this.getVillagerData().setProfession(profession.value()))); ++ BuiltInRegistries.VILLAGER_PROFESSION.getRandom(this.random).ifPresent((holder_c) -> { ++ this.setVillagerData(this.getVillagerData().setProfession((VillagerProfession) holder_c.value())); ++ }); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_CONVERTING_ID, false); +- this.entityData.define(DATA_VILLAGER_DATA, new VillagerData(VillagerType.PLAINS, VillagerProfession.NONE, 1)); ++ this.entityData.define(ZombieVillager.DATA_CONVERTING_ID, false); ++ this.entityData.define(ZombieVillager.DATA_VILLAGER_DATA, new VillagerData(VillagerType.PLAINS, VillagerProfession.NONE, 1)); + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- VillagerData.CODEC +- .encodeStart(NbtOps.INSTANCE, this.getVillagerData()) +- .resultOrPartial(LOGGER::error) +- .ifPresent(tag -> compound.put("VillagerData", tag)); ++ DataResult dataresult = VillagerData.CODEC.encodeStart(NbtOps.INSTANCE, this.getVillagerData()); // CraftBukkit - decompile error ++ Logger logger = ZombieVillager.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("VillagerData", nbtbase); ++ }); + if (this.tradeOffers != null) { + compound.put("Offers", this.tradeOffers); + } +@@ -110,8 +119,11 @@ + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); + if (compound.contains("VillagerData", 10)) { +- DataResult dataResult = VillagerData.CODEC.parse(new Dynamic<>(NbtOps.INSTANCE, compound.get("VillagerData"))); +- dataResult.resultOrPartial(LOGGER::error).ifPresent(this::setVillagerData); ++ DataResult dataresult = VillagerData.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compound.get("VillagerData"))); ++ Logger logger = ZombieVillager.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent(this::setVillagerData); + } + + if (compound.contains("Offers", 10)) { +@@ -129,28 +141,36 @@ + if (compound.contains("Xp", 3)) { + this.villagerXp = compound.getInt("Xp"); + } ++ + } + + @Override + public void tick() { + if (!this.level().isClientSide && this.isAlive() && this.isConverting()) { +- int conversionProgress = this.getConversionProgress(); +- this.villagerConversionTime -= conversionProgress; ++ int i = this.getConversionProgress(); ++ // CraftBukkit start - Use wall time instead of ticks for villager conversion ++ int elapsedTicks = MinecraftServer.currentTick - this.lastTick; ++ i *= elapsedTicks; ++ // CraftBukkit end ++ ++ this.villagerConversionTime -= i; + if (this.villagerConversionTime <= 0) { +- this.finishConversion((ServerLevel)this.level()); ++ this.finishConversion((ServerLevel) this.level()); + } + } + + super.tick(); ++ this.lastTick = MinecraftServer.currentTick; // CraftBukkit + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (itemInHand.is(Items.GOLDEN_APPLE)) { ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (itemstack.is(Items.GOLDEN_APPLE)) { + if (this.hasEffect(MobEffects.WEAKNESS)) { + if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + + if (!this.level().isClientSide) { +@@ -177,98 +197,108 @@ + } + + public boolean isConverting() { +- return this.getEntityData().get(DATA_CONVERTING_ID); ++ return (Boolean) this.getEntityData().get(ZombieVillager.DATA_CONVERTING_ID); + } + +- private void startConverting(@Nullable UUID conversionStarter, int villagerConversionTime) { ++ public void startConverting(@Nullable UUID conversionStarter, int villagerConversionTime) { + this.conversionStarter = conversionStarter; + this.villagerConversionTime = villagerConversionTime; +- this.getEntityData().set(DATA_CONVERTING_ID, true); +- this.removeEffect(MobEffects.WEAKNESS); +- this.addEffect(new MobEffectInstance(MobEffects.DAMAGE_BOOST, villagerConversionTime, Math.min(this.level().getDifficulty().getId() - 1, 0))); +- this.level().broadcastEntityEvent(this, (byte)16); ++ this.getEntityData().set(ZombieVillager.DATA_CONVERTING_ID, true); ++ // CraftBukkit start ++ this.removeEffect(MobEffects.WEAKNESS, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); ++ this.addEffect(new MobEffectInstance(MobEffects.DAMAGE_BOOST, villagerConversionTime, Math.min(this.level().getDifficulty().getId() - 1, 0)), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); ++ // CraftBukkit end ++ this.level().broadcastEntityEvent(this, (byte) 16); + } + + @Override + public void handleEntityEvent(byte id) { + if (id == 16) { + if (!this.isSilent()) { +- this.level() +- .playLocalSound( +- this.getX(), +- this.getEyeY(), +- this.getZ(), +- SoundEvents.ZOMBIE_VILLAGER_CURE, +- this.getSoundSource(), +- 1.0F + this.random.nextFloat(), +- this.random.nextFloat() * 0.7F + 0.3F, +- false +- ); ++ this.level().playLocalSound(this.getX(), this.getEyeY(), this.getZ(), SoundEvents.ZOMBIE_VILLAGER_CURE, this.getSoundSource(), 1.0F + this.random.nextFloat(), this.random.nextFloat() * 0.7F + 0.3F, false); + } ++ + } else { + super.handleEntityEvent(id); + } + } + + private void finishConversion(ServerLevel serverLevel) { +- Villager villager = this.convertTo(EntityType.VILLAGER, false); ++ // CraftBukkit start ++ Villager entityvillager = (Villager) this.convertTo(EntityType.VILLAGER, false, EntityTransformEvent.TransformReason.CURED, CreatureSpawnEvent.SpawnReason.CURED); ++ if (entityvillager == null) { ++ ((org.bukkit.entity.ZombieVillager) getBukkitEntity()).setConversionTime(-1); // SPIGOT-5208: End conversion to stop event spam ++ return; ++ } ++ // CraftBukkit end ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ int i = aenumitemslot.length; + +- for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) { +- ItemStack itemBySlot = this.getItemBySlot(equipmentSlot); +- if (!itemBySlot.isEmpty()) { +- if (EnchantmentHelper.hasBindingCurse(itemBySlot)) { +- villager.getSlot(equipmentSlot.getIndex() + 300).set(itemBySlot); ++ for (int j = 0; j < i; ++j) { ++ EquipmentSlot enumitemslot = aenumitemslot[j]; ++ ItemStack itemstack = this.getItemBySlot(enumitemslot); ++ ++ if (!itemstack.isEmpty()) { ++ if (EnchantmentHelper.hasBindingCurse(itemstack)) { ++ entityvillager.getSlot(enumitemslot.getIndex() + 300).set(itemstack); + } else { +- double d = (double)this.getEquipmentDropChance(equipmentSlot); +- if (d > 1.0) { +- this.spawnAtLocation(itemBySlot); ++ double d0 = (double) this.getEquipmentDropChance(enumitemslot); ++ ++ if (d0 > 1.0D) { ++ this.forceDrops = true; // CraftBukkit ++ this.spawnAtLocation(itemstack); ++ this.forceDrops = false; // CraftBukkit + } + } + } + } + +- villager.setVillagerData(this.getVillagerData()); ++ entityvillager.setVillagerData(this.getVillagerData()); + if (this.gossips != null) { +- villager.setGossips(this.gossips); ++ entityvillager.setGossips(this.gossips); + } + + if (this.tradeOffers != null) { +- villager.setOffers(new MerchantOffers(this.tradeOffers)); ++ entityvillager.setOffers(new MerchantOffers(this.tradeOffers)); + } + +- villager.setVillagerXp(this.villagerXp); +- villager.finalizeSpawn(serverLevel, serverLevel.getCurrentDifficultyAt(villager.blockPosition()), MobSpawnType.CONVERSION, null, null); +- villager.refreshBrain(serverLevel); ++ entityvillager.setVillagerXp(this.villagerXp); ++ entityvillager.finalizeSpawn(serverLevel, serverLevel.getCurrentDifficultyAt(entityvillager.blockPosition()), EnumMobSpawn.CONVERSION, (GroupDataEntity) null, (CompoundTag) null); ++ entityvillager.refreshBrain(serverLevel); + if (this.conversionStarter != null) { +- Player playerByUUID = serverLevel.getPlayerByUUID(this.conversionStarter); +- if (playerByUUID instanceof ServerPlayer) { +- CriteriaTriggers.CURED_ZOMBIE_VILLAGER.trigger((ServerPlayer)playerByUUID, this, villager); +- serverLevel.onReputationEvent(ReputationEventType.ZOMBIE_VILLAGER_CURED, playerByUUID, villager); ++ Player entityhuman = serverLevel.getPlayerByUUID(this.conversionStarter); ++ ++ if (entityhuman instanceof ServerPlayer) { ++ CriteriaTriggers.CURED_ZOMBIE_VILLAGER.trigger((ServerPlayer) entityhuman, this, entityvillager); ++ serverLevel.onReputationEvent(ReputationEventType.ZOMBIE_VILLAGER_CURED, entityhuman, entityvillager); + } + } + +- villager.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0)); ++ entityvillager.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); // CraftBukkit + if (!this.isSilent()) { +- serverLevel.levelEvent(null, 1027, this.blockPosition(), 0); ++ serverLevel.levelEvent((Player) null, 1027, this.blockPosition(), 0); + } ++ + } + + private int getConversionProgress() { + int i = 1; ++ + if (this.random.nextFloat() < 0.01F) { +- int i1 = 0; +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ int j = 0; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + +- for (int i2 = (int)this.getX() - 4; i2 < (int)this.getX() + 4 && i1 < 14; i2++) { +- for (int i3 = (int)this.getY() - 4; i3 < (int)this.getY() + 4 && i1 < 14; i3++) { +- for (int i4 = (int)this.getZ() - 4; i4 < (int)this.getZ() + 4 && i1 < 14; i4++) { +- BlockState blockState = this.level().getBlockState(mutableBlockPos.set(i2, i3, i4)); +- if (blockState.is(Blocks.IRON_BARS) || blockState.getBlock() instanceof BedBlock) { ++ for (int k = (int) this.getX() - 4; k < (int) this.getX() + 4 && j < 14; ++k) { ++ for (int l = (int) this.getY() - 4; l < (int) this.getY() + 4 && j < 14; ++l) { ++ for (int i1 = (int) this.getZ() - 4; i1 < (int) this.getZ() + 4 && j < 14; ++i1) { ++ IBlockData iblockdata = this.level().getBlockState(blockposition_mutableblockposition.set(k, l, i1)); ++ ++ if (iblockdata.is(Blocks.IRON_BARS) || iblockdata.getBlock() instanceof BedBlock) { + if (this.random.nextFloat() < 0.3F) { +- i++; ++ ++i; + } + +- i1++; ++ ++j; + } + } + } +@@ -280,9 +310,7 @@ + + @Override + public float getVoicePitch() { +- return this.isBaby() +- ? (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 2.0F +- : (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F; ++ return this.isBaby() ? (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 2.0F : (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F; + } + + @Override +@@ -320,26 +348,25 @@ + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + this.setVillagerData(this.getVillagerData().setType(VillagerType.byBiome(level.getBiome(this.blockPosition())))); + return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + + @Override + public void setVillagerData(VillagerData data) { +- VillagerData villagerData = this.getVillagerData(); +- if (villagerData.getProfession() != data.getProfession()) { ++ VillagerData villagerdata1 = this.getVillagerData(); ++ ++ if (villagerdata1.getProfession() != data.getProfession()) { + this.tradeOffers = null; + } + +- this.entityData.set(DATA_VILLAGER_DATA, data); ++ this.entityData.set(ZombieVillager.DATA_VILLAGER_DATA, data); + } + + @Override + public VillagerData getVillagerData() { +- return this.entityData.get(DATA_VILLAGER_DATA); ++ return (VillagerData) this.entityData.get(ZombieVillager.DATA_VILLAGER_DATA); + } + + public int getVillagerXp() { +@@ -351,7 +378,7 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.175F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.175F * f, 0.0F); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/ZombifiedPiglin.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/ZombifiedPiglin.java.patch new file mode 100644 index 0000000000..e8ce6c3e73 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/ZombifiedPiglin.java.patch @@ -0,0 +1,202 @@ +--- a/net/minecraft/world/entity/monster/ZombifiedPiglin.java ++++ b/net/minecraft/world/entity/monster/ZombifiedPiglin.java +@@ -15,13 +15,13 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.NeutralMob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -43,10 +43,9 @@ + import org.joml.Vector3f; + + public class ZombifiedPiglin extends Zombie implements NeutralMob { ++ + private static final UUID SPEED_MODIFIER_ATTACKING_UUID = UUID.fromString("49455A49-7EC5-45BA-B886-3B90B23A1718"); +- private static final AttributeModifier SPEED_MODIFIER_ATTACKING = new AttributeModifier( +- SPEED_MODIFIER_ATTACKING_UUID, "Attacking speed boost", 0.05, AttributeModifier.Operation.ADDITION +- ); ++ private static final AttributeModifier SPEED_MODIFIER_ATTACKING = new AttributeModifier(ZombifiedPiglin.SPEED_MODIFIER_ATTACKING_UUID, "Attacking speed boost", 0.05D, AttributeModifier.Operation.ADDITION); + private static final UniformInt FIRST_ANGER_SOUND_DELAY = TimeUtil.rangeOfSeconds(0, 1); + private int playFirstAngerSoundIn; + private static final UniformInt PERSISTENT_ANGER_TIME = TimeUtil.rangeOfSeconds(20, 39); +@@ -71,22 +70,19 @@ + + @Override + protected void addBehaviourGoals() { +- this.goalSelector.addGoal(2, new ZombieAttackGoal(this, 1.0, false)); +- this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers()); ++ this.goalSelector.addGoal(2, new ZombieAttackGoal(this, 1.0D, false)); ++ this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D)); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[0])).setAlertOthers()); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt)); + this.targetSelector.addGoal(3, new ResetUniversalAngerTargetGoal<>(this, true)); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Zombie.createAttributes() +- .add(Attributes.SPAWN_REINFORCEMENTS_CHANCE, 0.0) +- .add(Attributes.MOVEMENT_SPEED, 0.23F) +- .add(Attributes.ATTACK_DAMAGE, 5.0); ++ return Zombie.createAttributes().add(Attributes.SPAWN_REINFORCEMENTS_CHANCE, 0.0D).add(Attributes.MOVEMENT_SPEED, 0.23000000417232513D).add(Attributes.ATTACK_DAMAGE, 5.0D); + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return this.isBaby() ? 0.96999997F : 1.79F; + } + +@@ -97,18 +93,19 @@ + + @Override + protected void customServerAiStep() { +- AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ + if (this.isAngry()) { +- if (!this.isBaby() && !attribute.hasModifier(SPEED_MODIFIER_ATTACKING)) { +- attribute.addTransientModifier(SPEED_MODIFIER_ATTACKING); ++ if (!this.isBaby() && !attributemodifiable.hasModifier(ZombifiedPiglin.SPEED_MODIFIER_ATTACKING)) { ++ attributemodifiable.addTransientModifier(ZombifiedPiglin.SPEED_MODIFIER_ATTACKING); + } + + this.maybePlayFirstAngerSound(); +- } else if (attribute.hasModifier(SPEED_MODIFIER_ATTACKING)) { +- attribute.removeModifier(SPEED_MODIFIER_ATTACKING.getId()); ++ } else if (attributemodifiable.hasModifier(ZombifiedPiglin.SPEED_MODIFIER_ATTACKING)) { ++ attributemodifiable.removeModifier(ZombifiedPiglin.SPEED_MODIFIER_ATTACKING.getId()); + } + +- this.updatePersistentAnger((ServerLevel)this.level(), true); ++ this.updatePersistentAnger((ServerLevel) this.level(), true); + if (this.getTarget() != null) { + this.maybeAlertOthers(); + } +@@ -122,35 +119,39 @@ + + private void maybePlayFirstAngerSound() { + if (this.playFirstAngerSoundIn > 0) { +- this.playFirstAngerSoundIn--; ++ --this.playFirstAngerSoundIn; + if (this.playFirstAngerSoundIn == 0) { + this.playAngerSound(); + } + } ++ + } + + private void maybeAlertOthers() { + if (this.ticksUntilNextAlert > 0) { +- this.ticksUntilNextAlert--; ++ --this.ticksUntilNextAlert; + } else { + if (this.getSensing().hasLineOfSight(this.getTarget())) { + this.alertOthers(); + } + +- this.ticksUntilNextAlert = ALERT_INTERVAL.sample(this.random); ++ this.ticksUntilNextAlert = ZombifiedPiglin.ALERT_INTERVAL.sample(this.random); + } + } + + private void alertOthers() { +- double attributeValue = this.getAttributeValue(Attributes.FOLLOW_RANGE); +- AABB aABB = AABB.unitCubeFromLowerCorner(this.position()).inflate(attributeValue, 10.0, attributeValue); +- this.level() +- .getEntitiesOfClass(ZombifiedPiglin.class, aABB, EntitySelector.NO_SPECTATORS) +- .stream() +- .filter(zombifiedPiglin -> zombifiedPiglin != this) +- .filter(zombifiedPiglin -> zombifiedPiglin.getTarget() == null) +- .filter(zombifiedPiglin -> !zombifiedPiglin.isAlliedTo(this.getTarget())) +- .forEach(zombifiedPiglin -> zombifiedPiglin.setTarget(this.getTarget())); ++ double d0 = this.getAttributeValue(Attributes.FOLLOW_RANGE); ++ AABB axisalignedbb = AABB.unitCubeFromLowerCorner(this.position()).inflate(d0, 10.0D, d0); ++ ++ this.level().getEntitiesOfClass(ZombifiedPiglin.class, axisalignedbb, EntitySelector.NO_SPECTATORS).stream().filter((entitypigzombie) -> { ++ return entitypigzombie != this; ++ }).filter((entitypigzombie) -> { ++ return entitypigzombie.getTarget() == null; ++ }).filter((entitypigzombie) -> { ++ return !entitypigzombie.isAlliedTo((Entity) this.getTarget()); ++ }).forEach((entitypigzombie) -> { ++ entitypigzombie.setTarget(this.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_NEARBY_ENTITY, true); // CraftBukkit ++ }); + } + + private void playAngerSound() { +@@ -158,27 +159,34 @@ + } + + @Override +- public void setTarget(@Nullable LivingEntity livingEntity) { +- if (this.getTarget() == null && livingEntity != null) { +- this.playFirstAngerSoundIn = FIRST_ANGER_SOUND_DELAY.sample(this.random); +- this.ticksUntilNextAlert = ALERT_INTERVAL.sample(this.random); ++ public boolean setTarget(@Nullable LivingEntity entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) { // CraftBukkit - signature ++ if (this.getTarget() == null && entityliving != null) { ++ this.playFirstAngerSoundIn = ZombifiedPiglin.FIRST_ANGER_SOUND_DELAY.sample(this.random); ++ this.ticksUntilNextAlert = ZombifiedPiglin.ALERT_INTERVAL.sample(this.random); + } + +- if (livingEntity instanceof Player) { +- this.setLastHurtByPlayer((Player)livingEntity); ++ if (entityliving instanceof Player) { ++ this.setLastHurtByPlayer((Player) entityliving); + } + +- super.setTarget(livingEntity); ++ return super.setTarget(entityliving, reason, fireEvent); // CraftBukkit + } + + @Override + public void startPersistentAngerTimer() { +- this.setRemainingPersistentAngerTime(PERSISTENT_ANGER_TIME.sample(this.random)); ++ // CraftBukkit start ++ Entity entity = ((ServerLevel) this.level()).getEntity(getPersistentAngerTarget()); ++ org.bukkit.event.entity.PigZombieAngerEvent event = new org.bukkit.event.entity.PigZombieAngerEvent((org.bukkit.entity.PigZombie) this.getBukkitEntity(), (entity == null) ? null : entity.getBukkitEntity(), ZombifiedPiglin.PERSISTENT_ANGER_TIME.sample(this.random)); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ this.setPersistentAngerTarget(null); ++ return; ++ } ++ this.setRemainingPersistentAngerTime(event.getNewAnger()); ++ // CraftBukkit end + } + +- public static boolean checkZombifiedPiglinSpawnRules( +- EntityType zombifiedPiglin, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random +- ) { ++ public static boolean checkZombifiedPiglinSpawnRules(EntityType zombifiedPiglin, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { + return level.getDifficulty() != Difficulty.PEACEFUL && !level.getBlockState(pos.below()).is(Blocks.NETHER_WART_BLOCK); + } + +@@ -236,7 +244,7 @@ + + @Override + protected void randomizeReinforcementsChance() { +- this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(0.0); ++ this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(0.0D); + } + + @Nullable +@@ -256,7 +264,7 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.05F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.05F * f, 0.0F); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java.patch new file mode 100644 index 0000000000..4b8d2d70f8 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java.patch @@ -0,0 +1,133 @@ +--- a/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java ++++ b/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java +@@ -11,9 +11,9 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + import net.minecraft.world.entity.ai.navigation.GroundPathNavigation; + import net.minecraft.world.entity.ai.util.GoalUtils; +@@ -25,12 +25,11 @@ + import org.joml.Vector3f; + + public abstract class AbstractPiglin extends Monster { +- protected static final EntityDataAccessor DATA_IMMUNE_TO_ZOMBIFICATION = SynchedEntityData.defineId( +- AbstractPiglin.class, EntityDataSerializers.BOOLEAN +- ); ++ ++ protected static final EntityDataAccessor DATA_IMMUNE_TO_ZOMBIFICATION = SynchedEntityData.defineId(AbstractPiglin.class, EntityDataSerializers.BOOLEAN); + protected static final int CONVERSION_TIME = 300; + protected static final float PIGLIN_EYE_HEIGHT = 1.79F; +- protected int timeInOverworld; ++ public int timeInOverworld; + + public AbstractPiglin(EntityType entityType, Level level) { + super(entityType, level); +@@ -42,12 +41,13 @@ + + private void applyOpenDoorsAbility() { + if (GoalUtils.hasGroundPathNavigation(this)) { +- ((GroundPathNavigation)this.getNavigation()).setCanOpenDoors(true); ++ ((GroundPathNavigation) this.getNavigation()).setCanOpenDoors(true); + } ++ + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions dimensions) { + return 1.79F; + } + +@@ -57,24 +57,24 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.0625F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.0625F * f, 0.0F); + } + + protected abstract boolean canHunt(); + + public void setImmuneToZombification(boolean immuneToZombification) { +- this.getEntityData().set(DATA_IMMUNE_TO_ZOMBIFICATION, immuneToZombification); ++ this.getEntityData().set(AbstractPiglin.DATA_IMMUNE_TO_ZOMBIFICATION, immuneToZombification); + } + +- protected boolean isImmuneToZombification() { +- return this.getEntityData().get(DATA_IMMUNE_TO_ZOMBIFICATION); ++ public boolean isImmuneToZombification() { ++ return (Boolean) this.getEntityData().get(AbstractPiglin.DATA_IMMUNE_TO_ZOMBIFICATION); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_IMMUNE_TO_ZOMBIFICATION, false); ++ this.entityData.define(AbstractPiglin.DATA_IMMUNE_TO_ZOMBIFICATION, false); + } + + @Override +@@ -98,15 +98,16 @@ + protected void customServerAiStep() { + super.customServerAiStep(); + if (this.isConverting()) { +- this.timeInOverworld++; ++ ++this.timeInOverworld; + } else { + this.timeInOverworld = 0; + } + + if (this.timeInOverworld > 300) { + this.playConvertedSound(); +- this.finishConversion((ServerLevel)this.level()); ++ this.finishConversion((ServerLevel) this.level()); + } ++ + } + + public boolean isConverting() { +@@ -114,22 +115,24 @@ + } + + protected void finishConversion(ServerLevel serverLevel) { +- ZombifiedPiglin zombifiedPiglin = this.convertTo(EntityType.ZOMBIFIED_PIGLIN, true); +- if (zombifiedPiglin != null) { +- zombifiedPiglin.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0)); ++ ZombifiedPiglin entitypigzombie = (ZombifiedPiglin) this.convertTo(EntityType.ZOMBIFIED_PIGLIN, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.PIGLIN_ZOMBIFIED, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.PIGLIN_ZOMBIFIED); // CraftBukkit - add spawn and transform reasons ++ ++ if (entitypigzombie != null) { ++ entitypigzombie.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0)); + } ++ + } + + public boolean isAdult() { + return !this.isBaby(); + } + +- public abstract PiglinArmPose getArmPose(); ++ public abstract EntityPiglinArmPose getArmPose(); + + @Nullable + @Override + public LivingEntity getTarget() { +- return this.brain.getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); ++ return (LivingEntity) this.brain.getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); // CraftBukkit - decompile error + } + + protected boolean isHoldingMeleeWeapon() { +@@ -141,6 +144,7 @@ + if (PiglinAi.isIdle(this)) { + super.playAmbientSound(); + } ++ + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/piglin/Piglin.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/piglin/Piglin.java.patch new file mode 100644 index 0000000000..7bda1083f5 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/piglin/Piglin.java.patch @@ -0,0 +1,474 @@ +--- a/net/minecraft/world/entity/monster/piglin/Piglin.java ++++ b/net/minecraft/world/entity/monster/piglin/Piglin.java +@@ -5,30 +5,22 @@ + import java.util.List; + import java.util.UUID; + import javax.annotation.Nullable; +-import net.minecraft.core.BlockPos; +-import net.minecraft.nbt.CompoundTag; +-import net.minecraft.network.syncher.EntityDataAccessor; +-import net.minecraft.network.syncher.EntityDataSerializers; +-import net.minecraft.network.syncher.SynchedEntityData; +-import net.minecraft.server.level.ServerLevel; +-import net.minecraft.sounds.SoundEvent; +-import net.minecraft.sounds.SoundEvents; + import net.minecraft.util.RandomSource; + import net.minecraft.util.VisibleForDebug; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; +@@ -53,16 +45,35 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start ++import java.util.stream.Collectors; ++import java.util.HashSet; ++import java.util.Set; ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.registries.BuiltInRegistries; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; ++import net.minecraft.nbt.StringTag; ++import net.minecraft.nbt.Tag; ++import net.minecraft.network.syncher.EntityDataAccessor; ++import net.minecraft.network.syncher.EntityDataSerializers; ++import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundEvents; ++import net.minecraft.world.item.Item; ++// CraftBukkit end ++ + public class Piglin extends AbstractPiglin implements CrossbowAttackMob, InventoryCarrier { ++ + private static final EntityDataAccessor DATA_BABY_ID = SynchedEntityData.defineId(Piglin.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_IS_CHARGING_CROSSBOW = SynchedEntityData.defineId(Piglin.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_IS_DANCING = SynchedEntityData.defineId(Piglin.class, EntityDataSerializers.BOOLEAN); + private static final UUID SPEED_MODIFIER_BABY_UUID = UUID.fromString("766bfa64-11f3-11ea-8d71-362b9e155667"); +- private static final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier( +- SPEED_MODIFIER_BABY_UUID, "Baby speed boost", 0.2F, AttributeModifier.Operation.MULTIPLY_BASE +- ); ++ private static final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier(Piglin.SPEED_MODIFIER_BABY_UUID, "Baby speed boost", 0.20000000298023224D, AttributeModifier.Operation.MULTIPLY_BASE); + private static final int MAX_HEALTH = 16; + private static final float MOVEMENT_SPEED_WHEN_FIGHTING = 0.35F; + private static final int ATTACK_DAMAGE = 5; +@@ -71,53 +82,15 @@ + private static final int MAX_PASSENGERS_ON_ONE_HOGLIN = 3; + private static final float PROBABILITY_OF_SPAWNING_AS_BABY = 0.2F; + private static final float BABY_EYE_HEIGHT_ADJUSTMENT = 0.82F; +- private static final double PROBABILITY_OF_SPAWNING_WITH_CROSSBOW_INSTEAD_OF_SWORD = 0.5; +- private final SimpleContainer inventory = new SimpleContainer(8); +- private boolean cannotHunt; +- protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of( +- SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.NEAREST_ITEMS, SensorType.HURT_BY, SensorType.PIGLIN_SPECIFIC_SENSOR +- ); +- protected static final ImmutableList> MEMORY_TYPES = ImmutableList.of( +- MemoryModuleType.LOOK_TARGET, +- MemoryModuleType.DOORS_TO_CLOSE, +- MemoryModuleType.NEAREST_LIVING_ENTITIES, +- MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, +- MemoryModuleType.NEAREST_VISIBLE_PLAYER, +- MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, +- MemoryModuleType.NEAREST_VISIBLE_ADULT_PIGLINS, +- MemoryModuleType.NEARBY_ADULT_PIGLINS, +- MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, +- MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS, +- MemoryModuleType.HURT_BY, +- MemoryModuleType.HURT_BY_ENTITY, +- MemoryModuleType.WALK_TARGET, +- MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, +- MemoryModuleType.ATTACK_TARGET, +- MemoryModuleType.ATTACK_COOLING_DOWN, +- MemoryModuleType.INTERACTION_TARGET, +- MemoryModuleType.PATH, +- MemoryModuleType.ANGRY_AT, +- MemoryModuleType.UNIVERSAL_ANGER, +- MemoryModuleType.AVOID_TARGET, +- MemoryModuleType.ADMIRING_ITEM, +- MemoryModuleType.TIME_TRYING_TO_REACH_ADMIRE_ITEM, +- MemoryModuleType.ADMIRING_DISABLED, +- MemoryModuleType.DISABLE_WALK_TO_ADMIRE_ITEM, +- MemoryModuleType.CELEBRATE_LOCATION, +- MemoryModuleType.DANCING, +- MemoryModuleType.HUNTED_RECENTLY, +- MemoryModuleType.NEAREST_VISIBLE_BABY_HOGLIN, +- MemoryModuleType.NEAREST_VISIBLE_NEMESIS, +- MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED, +- MemoryModuleType.RIDE_TARGET, +- MemoryModuleType.VISIBLE_ADULT_PIGLIN_COUNT, +- MemoryModuleType.VISIBLE_ADULT_HOGLIN_COUNT, +- MemoryModuleType.NEAREST_VISIBLE_HUNTABLE_HOGLIN, +- MemoryModuleType.NEAREST_TARGETABLE_PLAYER_NOT_WEARING_GOLD, +- MemoryModuleType.NEAREST_PLAYER_HOLDING_WANTED_ITEM, +- MemoryModuleType.ATE_RECENTLY, +- MemoryModuleType.NEAREST_REPELLENT +- ); ++ private static final double PROBABILITY_OF_SPAWNING_WITH_CROSSBOW_INSTEAD_OF_SWORD = 0.5D; ++ public final SimpleContainer inventory = new SimpleContainer(8); ++ public boolean cannotHunt; ++ protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.NEAREST_ITEMS, SensorType.HURT_BY, SensorType.PIGLIN_SPECIFIC_SENSOR); ++ protected static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.LOOK_TARGET, MemoryModuleType.DOORS_TO_CLOSE, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ADULT_PIGLINS, MemoryModuleType.NEARBY_ADULT_PIGLINS, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, new MemoryModuleType[]{MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.ATTACK_TARGET, MemoryModuleType.ATTACK_COOLING_DOWN, MemoryModuleType.INTERACTION_TARGET, MemoryModuleType.PATH, MemoryModuleType.ANGRY_AT, MemoryModuleType.UNIVERSAL_ANGER, MemoryModuleType.AVOID_TARGET, MemoryModuleType.ADMIRING_ITEM, MemoryModuleType.TIME_TRYING_TO_REACH_ADMIRE_ITEM, MemoryModuleType.ADMIRING_DISABLED, MemoryModuleType.DISABLE_WALK_TO_ADMIRE_ITEM, MemoryModuleType.CELEBRATE_LOCATION, MemoryModuleType.DANCING, MemoryModuleType.HUNTED_RECENTLY, MemoryModuleType.NEAREST_VISIBLE_BABY_HOGLIN, MemoryModuleType.NEAREST_VISIBLE_NEMESIS, MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED, MemoryModuleType.RIDE_TARGET, MemoryModuleType.VISIBLE_ADULT_PIGLIN_COUNT, MemoryModuleType.VISIBLE_ADULT_HOGLIN_COUNT, MemoryModuleType.NEAREST_VISIBLE_HUNTABLE_HOGLIN, MemoryModuleType.NEAREST_TARGETABLE_PLAYER_NOT_WEARING_GOLD, MemoryModuleType.NEAREST_PLAYER_HOLDING_WANTED_ITEM, MemoryModuleType.ATE_RECENTLY, MemoryModuleType.NEAREST_REPELLENT}); ++ // CraftBukkit start - Custom bartering and interest list ++ public Set allowedBarterItems = new HashSet<>(); ++ public Set interestItems = new HashSet<>(); ++ // CraftBukkit end + + public Piglin(EntityType entityType, Level level) { + super(entityType, level); +@@ -136,6 +109,14 @@ + } + + this.writeInventoryToTag(compound); ++ // CraftBukkit start ++ ListTag barterList = new ListTag(); ++ allowedBarterItems.stream().map(BuiltInRegistries.ITEM::getKey).map(ResourceLocation::toString).map(StringTag::valueOf).forEach(barterList::add); ++ compound.put("Bukkit.BarterList", barterList); ++ ListTag interestList = new ListTag(); ++ interestItems.stream().map(BuiltInRegistries.ITEM::getKey).map(ResourceLocation::toString).map(StringTag::valueOf).forEach(interestList::add); ++ compound.put("Bukkit.InterestList", interestList); ++ // CraftBukkit end + } + + @Override +@@ -144,6 +125,10 @@ + this.setBaby(compound.getBoolean("IsBaby")); + this.setCannotHunt(compound.getBoolean("CannotHunt")); + this.readInventoryFromTag(compound); ++ // CraftBukkit start ++ this.allowedBarterItems = compound.getList("Bukkit.BarterList", 8).stream().map(Tag::getAsString).map(ResourceLocation::tryParse).map(BuiltInRegistries.ITEM::get).collect(Collectors.toCollection(HashSet::new)); ++ this.interestItems = compound.getList("Bukkit.InterestList", 8).stream().map(Tag::getAsString).map(ResourceLocation::tryParse).map(BuiltInRegistries.ITEM::get).collect(Collectors.toCollection(HashSet::new)); ++ // CraftBukkit end + } + + @VisibleForDebug +@@ -155,10 +140,17 @@ + @Override + protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { + super.dropCustomDeathLoot(source, looting, recentlyHit); +- if (source.getEntity() instanceof Creeper creeper && creeper.canDropMobsSkull()) { +- ItemStack itemStack = new ItemStack(Items.PIGLIN_HEAD); +- creeper.increaseDroppedSkulls(); +- this.spawnAtLocation(itemStack); ++ Entity entity = source.getEntity(); ++ ++ if (entity instanceof Creeper) { ++ Creeper entitycreeper = (Creeper) entity; ++ ++ if (entitycreeper.canDropMobsSkull()) { ++ ItemStack itemstack = new ItemStack(Items.PIGLIN_HEAD); ++ ++ entitycreeper.increaseDroppedSkulls(); ++ this.spawnAtLocation(itemstack); ++ } + } + + this.inventory.removeAllItems().forEach(this::spawnAtLocation); +@@ -175,35 +167,35 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_BABY_ID, false); +- this.entityData.define(DATA_IS_CHARGING_CROSSBOW, false); +- this.entityData.define(DATA_IS_DANCING, false); ++ this.entityData.define(Piglin.DATA_BABY_ID, false); ++ this.entityData.define(Piglin.DATA_IS_CHARGING_CROSSBOW, false); ++ this.entityData.define(Piglin.DATA_IS_DANCING, false); + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { + super.onSyncedDataUpdated(key); +- if (DATA_BABY_ID.equals(key)) { ++ if (Piglin.DATA_BABY_ID.equals(key)) { + this.refreshDimensions(); + } ++ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 16.0).add(Attributes.MOVEMENT_SPEED, 0.35F).add(Attributes.ATTACK_DAMAGE, 5.0); ++ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 16.0D).add(Attributes.MOVEMENT_SPEED, 0.3499999940395355D).add(Attributes.ATTACK_DAMAGE, 5.0D); + } + +- public static boolean checkPiglinSpawnRules(EntityType piglin, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) { ++ public static boolean checkPiglinSpawnRules(EntityType piglin, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { + return !level.getBlockState(pos.below()).is(Blocks.NETHER_WART_BLOCK); + } + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- RandomSource random = level.getRandom(); +- if (reason != MobSpawnType.STRUCTURE) { +- if (random.nextFloat() < 0.2F) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ RandomSource randomsource = level.getRandom(); ++ ++ if (reason != EnumMobSpawn.STRUCTURE) { ++ if (randomsource.nextFloat() < 0.2F) { + this.setBaby(true); + } else if (this.isAdult()) { + this.setItemSlot(EquipmentSlot.MAINHAND, this.createSpawnWeapon()); +@@ -211,8 +203,8 @@ + } + + PiglinAi.initMemories(this, level.getRandom()); +- this.populateDefaultEquipmentSlots(random, difficulty); +- this.populateDefaultEquipmentEnchantments(random, difficulty); ++ this.populateDefaultEquipmentSlots(randomsource, difficulty); ++ this.populateDefaultEquipmentEnchantments(randomsource, difficulty); + return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + +@@ -234,17 +226,19 @@ + this.maybeWearArmor(EquipmentSlot.LEGS, new ItemStack(Items.GOLDEN_LEGGINGS), random); + this.maybeWearArmor(EquipmentSlot.FEET, new ItemStack(Items.GOLDEN_BOOTS), random); + } ++ + } + + private void maybeWearArmor(EquipmentSlot slot, ItemStack stack, RandomSource random) { + if (random.nextFloat() < 0.1F) { + this.setItemSlot(slot, stack); + } ++ + } + + @Override + protected Brain.Provider brainProvider() { +- return Brain.provider(MEMORY_TYPES, SENSOR_TYPES); ++ return Brain.provider(Piglin.MEMORY_TYPES, Piglin.SENSOR_TYPES); + } + + @Override +@@ -254,43 +248,48 @@ + + @Override + public Brain getBrain() { +- return (Brain)super.getBrain(); ++ return (Brain) super.getBrain(); // CraftBukkit - Decompile error + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- InteractionResult interactionResult = super.mobInteract(player, hand); +- if (interactionResult.consumesAction()) { +- return interactionResult; ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ InteractionResult enuminteractionresult = super.mobInteract(player, hand); ++ ++ if (enuminteractionresult.consumesAction()) { ++ return enuminteractionresult; + } else if (!this.level().isClientSide) { + return PiglinAi.mobInteract(this, player, hand); + } else { +- boolean flag = PiglinAi.canAdmire(this, player.getItemInHand(hand)) && this.getArmPose() != PiglinArmPose.ADMIRING_ITEM; ++ boolean flag = PiglinAi.canAdmire(this, player.getItemInHand(hand)) && this.getArmPose() != EntityPiglinArmPose.ADMIRING_ITEM; ++ + return flag ? InteractionResult.SUCCESS : InteractionResult.PASS; + } + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + float f = super.getStandingEyeHeight(pose, size); ++ + return this.isBaby() ? f - 0.82F : f; + } + + @Override + public void setBaby(boolean childZombie) { +- this.getEntityData().set(DATA_BABY_ID, childZombie); ++ this.getEntityData().set(Piglin.DATA_BABY_ID, childZombie); + if (!this.level().isClientSide) { +- AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED); +- attribute.removeModifier(SPEED_MODIFIER_BABY.getId()); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ ++ attributemodifiable.removeModifier(Piglin.SPEED_MODIFIER_BABY.getId()); + if (childZombie) { +- attribute.addTransientModifier(SPEED_MODIFIER_BABY); ++ attributemodifiable.addTransientModifier(Piglin.SPEED_MODIFIER_BABY); + } + } ++ + } + + @Override + public boolean isBaby() { +- return this.getEntityData().get(DATA_BABY_ID); ++ return (Boolean) this.getEntityData().get(Piglin.DATA_BABY_ID); + } + + private void setCannotHunt(boolean cannotHunt) { +@@ -305,7 +304,7 @@ + @Override + protected void customServerAiStep() { + this.level().getProfiler().push("piglinBrain"); +- this.getBrain().tick((ServerLevel)this.level(), this); ++ this.getBrain().tick((ServerLevel) this.level(), this); + this.level().getProfiler().pop(); + PiglinAi.updateActivity(this); + super.customServerAiStep(); +@@ -324,16 +323,16 @@ + } + + private ItemStack createSpawnWeapon() { +- return (double)this.random.nextFloat() < 0.5 ? new ItemStack(Items.CROSSBOW) : new ItemStack(Items.GOLDEN_SWORD); ++ return (double) this.random.nextFloat() < 0.5D ? new ItemStack(Items.CROSSBOW) : new ItemStack(Items.GOLDEN_SWORD); + } + + private boolean isChargingCrossbow() { +- return this.entityData.get(DATA_IS_CHARGING_CROSSBOW); ++ return (Boolean) this.entityData.get(Piglin.DATA_IS_CHARGING_CROSSBOW); + } + + @Override + public void setChargingCrossbow(boolean isCharging) { +- this.entityData.set(DATA_IS_CHARGING_CROSSBOW, isCharging); ++ this.entityData.set(Piglin.DATA_IS_CHARGING_CROSSBOW, isCharging); + } + + @Override +@@ -342,36 +341,27 @@ + } + + @Override +- public PiglinArmPose getArmPose() { +- if (this.isDancing()) { +- return PiglinArmPose.DANCING; +- } else if (PiglinAi.isLovedItem(this.getOffhandItem())) { +- return PiglinArmPose.ADMIRING_ITEM; +- } else if (this.isAggressive() && this.isHoldingMeleeWeapon()) { +- return PiglinArmPose.ATTACKING_WITH_MELEE_WEAPON; +- } else if (this.isChargingCrossbow()) { +- return PiglinArmPose.CROSSBOW_CHARGE; +- } else { +- return this.isAggressive() && this.isHolding(Items.CROSSBOW) ? PiglinArmPose.CROSSBOW_HOLD : PiglinArmPose.DEFAULT; +- } ++ public EntityPiglinArmPose getArmPose() { ++ return this.isDancing() ? EntityPiglinArmPose.DANCING : (PiglinAi.isLovedItem(this.getOffhandItem()) ? EntityPiglinArmPose.ADMIRING_ITEM : (this.isAggressive() && this.isHoldingMeleeWeapon() ? EntityPiglinArmPose.ATTACKING_WITH_MELEE_WEAPON : (this.isChargingCrossbow() ? EntityPiglinArmPose.CROSSBOW_CHARGE : (this.isAggressive() && this.isHolding(Items.CROSSBOW) ? EntityPiglinArmPose.CROSSBOW_HOLD : EntityPiglinArmPose.DEFAULT)))); + } + + public boolean isDancing() { +- return this.entityData.get(DATA_IS_DANCING); ++ return (Boolean) this.entityData.get(Piglin.DATA_IS_DANCING); + } + + public void setDancing(boolean dancing) { +- this.entityData.set(DATA_IS_DANCING, dancing); ++ this.entityData.set(Piglin.DATA_IS_DANCING, dancing); + } + + @Override + public boolean hurt(DamageSource source, float amount) { + boolean flag = super.hurt(source, amount); ++ + if (this.level().isClientSide) { + return false; + } else { + if (flag && source.getEntity() instanceof LivingEntity) { +- PiglinAi.wasHurtBy(this, (LivingEntity)source.getEntity()); ++ PiglinAi.wasHurtBy(this, (LivingEntity) source.getEntity()); + } + + return flag; +@@ -398,12 +388,13 @@ + } + + protected void holdInOffHand(ItemStack stack) { +- if (stack.is(PiglinAi.BARTERING_ITEM)) { ++ if (stack.is(PiglinAi.BARTERING_ITEM) || allowedBarterItems.contains(stack.getItem())) { // CraftBukkit - Changes to accept custom payment items + this.setItemSlot(EquipmentSlot.OFFHAND, stack); + this.setGuaranteedDrop(EquipmentSlot.OFFHAND); + } else { + this.setItemSlotAndDropWhenKilled(EquipmentSlot.OFFHAND, stack); + } ++ + } + + @Override +@@ -412,9 +403,10 @@ + } + + protected boolean canReplaceCurrentItem(ItemStack candidate) { +- EquipmentSlot equipmentSlotForItem = Mob.getEquipmentSlotForItem(candidate); +- ItemStack itemBySlot = this.getItemBySlot(equipmentSlotForItem); +- return this.canReplaceCurrentItem(candidate, itemBySlot); ++ EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(candidate); ++ ItemStack itemstack1 = this.getItemBySlot(enumitemslot); ++ ++ return this.canReplaceCurrentItem(candidate, itemstack1); + } + + @Override +@@ -422,12 +414,10 @@ + if (EnchantmentHelper.hasBindingCurse(existing)) { + return false; + } else { +- boolean flag = PiglinAi.isLovedItem(candidate) || candidate.is(Items.CROSSBOW); +- boolean flag1 = PiglinAi.isLovedItem(existing) || existing.is(Items.CROSSBOW); +- return flag && !flag1 +- || (flag || !flag1) +- && (!this.isAdult() || candidate.is(Items.CROSSBOW) || !existing.is(Items.CROSSBOW)) +- && super.canReplaceCurrentItem(candidate, existing); ++ boolean flag = PiglinAi.isLovedItem(candidate, this) || candidate.is(Items.CROSSBOW); // CraftBukkit ++ boolean flag1 = PiglinAi.isLovedItem(existing, this) || existing.is(Items.CROSSBOW); // CraftBukkit ++ ++ return flag && !flag1 ? true : (!flag && flag1 ? false : (this.isAdult() && !candidate.is(Items.CROSSBOW) && existing.is(Items.CROSSBOW) ? false : super.canReplaceCurrentItem(candidate, existing))); + } + } + +@@ -447,13 +437,14 @@ + } + + private Entity getTopPassenger(Entity vehicle, int maxPosition) { +- List passengers = vehicle.getPassengers(); +- return maxPosition != 1 && !passengers.isEmpty() ? this.getTopPassenger(passengers.get(0), maxPosition - 1) : vehicle; ++ List list = vehicle.getPassengers(); ++ ++ return maxPosition != 1 && !list.isEmpty() ? this.getTopPassenger((Entity) list.get(0), maxPosition - 1) : vehicle; + } + + @Override + protected SoundEvent getAmbientSound() { +- return this.level().isClientSide ? null : PiglinAi.getSoundForCurrentActivity(this).orElse(null); ++ return this.level().isClientSide ? null : (SoundEvent) PiglinAi.getSoundForCurrentActivity(this).orElse(null); // CraftBukkit - Decompile error + } + + @Override +@@ -467,7 +458,7 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.PIGLIN_STEP, 0.15F, 1.0F); + } + diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/piglin/PiglinAi.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/piglin/PiglinAi.java.patch new file mode 100644 index 0000000000..da1bd1d9a0 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/piglin/PiglinAi.java.patch @@ -0,0 +1,967 @@ +--- a/net/minecraft/world/entity/monster/piglin/PiglinAi.java ++++ b/net/minecraft/world/entity/monster/piglin/PiglinAi.java +@@ -4,7 +4,9 @@ + import com.google.common.collect.ImmutableSet; + import com.mojang.datafixers.util.Pair; + import java.util.Collections; ++import java.util.Iterator; + import java.util.List; ++import java.util.Objects; + import java.util.Optional; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.sounds.SoundEvent; +@@ -13,7 +15,7 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.util.TimeUtil; + import net.minecraft.util.valueproviders.UniformInt; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +@@ -52,7 +54,6 @@ + import net.minecraft.world.entity.ai.behavior.StopBeingAngryIfTargetDead; + import net.minecraft.world.entity.ai.behavior.TriggerGate; + import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder; +-import net.minecraft.world.entity.ai.behavior.declarative.Trigger; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + import net.minecraft.world.entity.ai.sensing.Sensor; + import net.minecraft.world.entity.ai.util.LandRandomPos; +@@ -72,8 +73,15 @@ + import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; + import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import java.util.stream.Collectors; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.entity.PiglinBarterEvent; ++// CraftBukkit end + + public class PiglinAi { ++ + public static final int REPELLENT_DETECTION_RANGE_HORIZONTAL = 8; + public static final int REPELLENT_DETECTION_RANGE_VERTICAL = 4; + public static final Item BARTERING_ITEM = Items.GOLD_INGOT; +@@ -111,6 +119,8 @@ + private static final float SPEED_MULTIPLIER_WHEN_DANCING = 0.6F; + private static final float SPEED_MULTIPLIER_WHEN_IDLING = 0.6F; + ++ public PiglinAi() {} ++ + protected static Brain makeBrain(Piglin piglin, Brain brain) { + initCoreActivity(brain); + initIdleActivity(brain); +@@ -126,159 +136,56 @@ + } + + protected static void initMemories(Piglin piglin, RandomSource random) { +- int i = TIME_BETWEEN_HUNTS.sample(random); +- piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.HUNTED_RECENTLY, true, (long)i); ++ int i = PiglinAi.TIME_BETWEEN_HUNTS.sample(random); ++ ++ piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.HUNTED_RECENTLY, true, (long) i); + } + + private static void initCoreActivity(Brain brain) { +- brain.addActivity( +- Activity.CORE, +- 0, +- ImmutableList.of( +- new LookAtTargetSink(45, 90), +- new MoveToTargetSink(), +- InteractWithDoor.create(), +- babyAvoidNemesis(), +- avoidZombified(), +- StopHoldingItemIfNoLongerAdmiring.create(), +- StartAdmiringItemIfSeen.create(119), +- StartCelebratingIfTargetDead.create(300, PiglinAi::wantsToDance), +- StopBeingAngryIfTargetDead.create() +- ) +- ); ++ brain.addActivity(Activity.CORE, 0, ImmutableList.of(new LookAtTargetSink(45, 90), new MoveToTargetSink(), InteractWithDoor.create(), babyAvoidNemesis(), avoidZombified(), StopHoldingItemIfNoLongerAdmiring.create(), StartAdmiringItemIfSeen.create(119), StartCelebratingIfTargetDead.create(300, PiglinAi::wantsToDance), StopBeingAngryIfTargetDead.create())); + } + + private static void initIdleActivity(Brain brain) { +- brain.addActivity( +- Activity.IDLE, +- 10, +- ImmutableList.of( +- SetEntityLookTarget.create(PiglinAi::isPlayerHoldingLovedItem, 14.0F), +- StartAttacking.create(AbstractPiglin::isAdult, PiglinAi::findNearestValidAttackTarget), +- BehaviorBuilder.triggerIf(Piglin::canHunt, StartHuntingHoglin.create()), +- avoidRepellent(), +- babySometimesRideBabyHoglin(), +- createIdleLookBehaviors(), +- createIdleMovementBehaviors(), +- SetLookAndInteract.create(EntityType.PLAYER, 4) +- ) +- ); ++ brain.addActivity(Activity.IDLE, 10, ImmutableList.of(SetEntityLookTarget.create(PiglinAi::isPlayerHoldingLovedItem, 14.0F), StartAttacking.create(AbstractPiglin::isAdult, PiglinAi::findNearestValidAttackTarget), BehaviorBuilder.triggerIf(Piglin::canHunt, StartHuntingHoglin.create()), avoidRepellent(), babySometimesRideBabyHoglin(), createIdleLookBehaviors(), createIdleMovementBehaviors(), SetLookAndInteract.create(EntityType.PLAYER, 4))); + } + + private static void initFightActivity(Piglin piglin, Brain brain) { +- brain.addActivityAndRemoveMemoryWhenStopped( +- Activity.FIGHT, +- 10, +- ImmutableList.>of( +- StopAttackingIfTargetInvalid.create(entity -> !isNearestValidAttackTarget(piglin, entity)), +- BehaviorBuilder.triggerIf(PiglinAi::hasCrossbow, BackUpIfTooClose.create(5, 0.75F)), +- SetWalkTargetFromAttackTargetIfTargetOutOfReach.create(1.0F), +- MeleeAttack.create(20), +- new CrossbowAttack(), +- RememberIfHoglinWasKilled.create(), +- EraseMemoryIf.create(PiglinAi::isNearZombified, MemoryModuleType.ATTACK_TARGET) +- ), +- MemoryModuleType.ATTACK_TARGET +- ); ++ brain.addActivityAndRemoveMemoryWhenStopped(Activity.FIGHT, 10, ImmutableList.of(StopAttackingIfTargetInvalid.create((entityliving) -> { ++ return !isNearestValidAttackTarget(piglin, entityliving); ++ }), BehaviorBuilder.triggerIf(PiglinAi::hasCrossbow, BackUpIfTooClose.create(5, 0.75F)), SetWalkTargetFromAttackTargetIfTargetOutOfReach.create(1.0F), MeleeAttack.create(20), new CrossbowAttack<>(), RememberIfHoglinWasKilled.create(), EraseMemoryIf.create(PiglinAi::isNearZombified, MemoryModuleType.ATTACK_TARGET)), MemoryModuleType.ATTACK_TARGET); + } + + private static void initCelebrateActivity(Brain brain) { +- brain.addActivityAndRemoveMemoryWhenStopped( +- Activity.CELEBRATE, +- 10, +- ImmutableList.of( +- avoidRepellent(), +- SetEntityLookTarget.create(PiglinAi::isPlayerHoldingLovedItem, 14.0F), +- StartAttacking.create(AbstractPiglin::isAdult, PiglinAi::findNearestValidAttackTarget), +- BehaviorBuilder.triggerIf(piglin -> !piglin.isDancing(), GoToTargetLocation.create(MemoryModuleType.CELEBRATE_LOCATION, 2, 1.0F)), +- BehaviorBuilder.triggerIf(Piglin::isDancing, GoToTargetLocation.create(MemoryModuleType.CELEBRATE_LOCATION, 4, 0.6F)), +- new RunOne<>( +- ImmutableList.of( +- Pair.of(SetEntityLookTarget.create(EntityType.PIGLIN, 8.0F), 1), +- Pair.of(RandomStroll.stroll(0.6F, 2, 1), 1), +- Pair.of(new DoNothing(10, 20), 1) +- ) +- ) +- ), +- MemoryModuleType.CELEBRATE_LOCATION +- ); ++ brain.addActivityAndRemoveMemoryWhenStopped(Activity.CELEBRATE, 10, ImmutableList.of(avoidRepellent(), SetEntityLookTarget.create(PiglinAi::isPlayerHoldingLovedItem, 14.0F), StartAttacking.create(AbstractPiglin::isAdult, PiglinAi::findNearestValidAttackTarget), BehaviorBuilder.triggerIf((entitypiglin) -> { ++ return !entitypiglin.isDancing(); ++ }, GoToTargetLocation.create(MemoryModuleType.CELEBRATE_LOCATION, 2, 1.0F)), BehaviorBuilder.triggerIf(Piglin::isDancing, GoToTargetLocation.create(MemoryModuleType.CELEBRATE_LOCATION, 4, 0.6F)), new RunOne<>(ImmutableList.of(Pair.of(SetEntityLookTarget.create(EntityType.PIGLIN, 8.0F), 1), Pair.of(RandomStroll.stroll(0.6F, 2, 1), 1), Pair.of(new DoNothing(10, 20), 1)))), MemoryModuleType.CELEBRATE_LOCATION); + } + + private static void initAdmireItemActivity(Brain brain) { +- brain.addActivityAndRemoveMemoryWhenStopped( +- Activity.ADMIRE_ITEM, +- 10, +- ImmutableList.of( +- GoToWantedItem.create(PiglinAi::isNotHoldingLovedItemInOffHand, 1.0F, true, 9), +- StopAdmiringIfItemTooFarAway.create(9), +- StopAdmiringIfTiredOfTryingToReachItem.create(200, 200) +- ), +- MemoryModuleType.ADMIRING_ITEM +- ); ++ brain.addActivityAndRemoveMemoryWhenStopped(Activity.ADMIRE_ITEM, 10, ImmutableList.of(GoToWantedItem.create(PiglinAi::isNotHoldingLovedItemInOffHand, 1.0F, true, 9), StopAdmiringIfItemTooFarAway.create(9), StopAdmiringIfTiredOfTryingToReachItem.create(200, 200)), MemoryModuleType.ADMIRING_ITEM); + } + + private static void initRetreatActivity(Brain brain) { +- brain.addActivityAndRemoveMemoryWhenStopped( +- Activity.AVOID, +- 10, +- ImmutableList.of( +- SetWalkTargetAwayFrom.entity(MemoryModuleType.AVOID_TARGET, 1.0F, 12, true), +- createIdleLookBehaviors(), +- createIdleMovementBehaviors(), +- EraseMemoryIf.create(PiglinAi::wantsToStopFleeing, MemoryModuleType.AVOID_TARGET) +- ), +- MemoryModuleType.AVOID_TARGET +- ); ++ brain.addActivityAndRemoveMemoryWhenStopped(Activity.AVOID, 10, ImmutableList.of(SetWalkTargetAwayFrom.entity(MemoryModuleType.AVOID_TARGET, 1.0F, 12, true), createIdleLookBehaviors(), createIdleMovementBehaviors(), EraseMemoryIf.create(PiglinAi::wantsToStopFleeing, MemoryModuleType.AVOID_TARGET)), MemoryModuleType.AVOID_TARGET); + } + + private static void initRideHoglinActivity(Brain brain) { +- brain.addActivityAndRemoveMemoryWhenStopped( +- Activity.RIDE, +- 10, +- ImmutableList.of( +- Mount.create(0.8F), +- SetEntityLookTarget.create(PiglinAi::isPlayerHoldingLovedItem, 8.0F), +- BehaviorBuilder.sequence( +- BehaviorBuilder.triggerIf(Entity::isPassenger), +- TriggerGate.triggerOneShuffled( +- ImmutableList., Integer>>builder() +- .addAll(createLookBehaviors()) +- .add(Pair.of(BehaviorBuilder.triggerIf(piglin -> true), 1)) +- .build() +- ) +- ), +- DismountOrSkipMounting.create(8, PiglinAi::wantsToStopRiding) +- ), +- MemoryModuleType.RIDE_TARGET +- ); ++ // CraftBukkit - decompile error ++ brain.addActivityAndRemoveMemoryWhenStopped(Activity.RIDE, 10, ImmutableList.of(Mount.create(0.8F), SetEntityLookTarget.create(PiglinAi::isPlayerHoldingLovedItem, 8.0F), BehaviorBuilder.sequence(BehaviorBuilder.triggerIf(Entity::isPassenger), TriggerGate.triggerOneShuffled(ImmutableList., Integer>>builder().addAll(createLookBehaviors()).add(Pair.of(BehaviorBuilder.triggerIf((entitypiglin) -> { ++ return true; ++ }), 1)).build())), DismountOrSkipMounting.create(8, PiglinAi::wantsToStopRiding)), MemoryModuleType.RIDE_TARGET); + } + + private static ImmutableList, Integer>> createLookBehaviors() { +- return ImmutableList.of( +- Pair.of(SetEntityLookTarget.create(EntityType.PLAYER, 8.0F), 1), +- Pair.of(SetEntityLookTarget.create(EntityType.PIGLIN, 8.0F), 1), +- Pair.of(SetEntityLookTarget.create(8.0F), 1) +- ); ++ return ImmutableList.of(Pair.of(SetEntityLookTarget.create(EntityType.PLAYER, 8.0F), 1), Pair.of(SetEntityLookTarget.create(EntityType.PIGLIN, 8.0F), 1), Pair.of(SetEntityLookTarget.create(8.0F), 1)); + } + + private static RunOne createIdleLookBehaviors() { +- return new RunOne<>( +- ImmutableList., Integer>>builder() +- .addAll(createLookBehaviors()) +- .add(Pair.of(new DoNothing(30, 60), 1)) +- .build() +- ); ++ return new RunOne<>(ImmutableList., Integer>>builder().addAll(createLookBehaviors()).add(Pair.of(new DoNothing(30, 60), 1)).build()); // CraftBukkit - decompile error + } + + private static RunOne createIdleMovementBehaviors() { +- return new RunOne<>( +- ImmutableList.of( +- Pair.of(RandomStroll.stroll(0.6F), 2), +- Pair.of(InteractWith.of(EntityType.PIGLIN, 8, MemoryModuleType.INTERACTION_TARGET, 0.6F, 2), 2), +- Pair.of(BehaviorBuilder.triggerIf(PiglinAi::doesntSeeAnyPlayerHoldingLovedItem, SetWalkTargetFromLookTarget.create(0.6F, 3)), 2), +- Pair.of(new DoNothing(30, 60), 1) +- ) +- ); ++ return new RunOne<>(ImmutableList.of(Pair.of(RandomStroll.stroll(0.6F), 2), Pair.of(InteractWith.of(EntityType.PIGLIN, 8, MemoryModuleType.INTERACTION_TARGET, 0.6F, 2), 2), Pair.of(BehaviorBuilder.triggerIf(PiglinAi::doesntSeeAnyPlayerHoldingLovedItem, SetWalkTargetFromLookTarget.create(0.6F, 3)), 2), Pair.of(new DoNothing(30, 60), 1))); + } + + private static BehaviorControl avoidRepellent() { +@@ -286,140 +193,164 @@ + } + + private static BehaviorControl babyAvoidNemesis() { +- return CopyMemoryWithExpiry.create(Piglin::isBaby, MemoryModuleType.NEAREST_VISIBLE_NEMESIS, MemoryModuleType.AVOID_TARGET, BABY_AVOID_NEMESIS_DURATION); ++ return CopyMemoryWithExpiry.create(Piglin::isBaby, MemoryModuleType.NEAREST_VISIBLE_NEMESIS, MemoryModuleType.AVOID_TARGET, PiglinAi.BABY_AVOID_NEMESIS_DURATION); + } + + private static BehaviorControl avoidZombified() { +- return CopyMemoryWithExpiry.create( +- PiglinAi::isNearZombified, MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED, MemoryModuleType.AVOID_TARGET, AVOID_ZOMBIFIED_DURATION +- ); ++ return CopyMemoryWithExpiry.create(PiglinAi::isNearZombified, MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED, MemoryModuleType.AVOID_TARGET, PiglinAi.AVOID_ZOMBIFIED_DURATION); + } + + protected static void updateActivity(Piglin piglin) { +- Brain brain = piglin.getBrain(); +- Activity activity = brain.getActiveNonCoreActivity().orElse(null); +- brain.setActiveActivityToFirstValid( +- ImmutableList.of(Activity.ADMIRE_ITEM, Activity.FIGHT, Activity.AVOID, Activity.CELEBRATE, Activity.RIDE, Activity.IDLE) +- ); +- Activity activity1 = brain.getActiveNonCoreActivity().orElse(null); ++ Brain behaviorcontroller = piglin.getBrain(); ++ Activity activity = (Activity) behaviorcontroller.getActiveNonCoreActivity().orElse(null); // CraftBukkit - decompile error ++ ++ behaviorcontroller.setActiveActivityToFirstValid(ImmutableList.of(Activity.ADMIRE_ITEM, Activity.FIGHT, Activity.AVOID, Activity.CELEBRATE, Activity.RIDE, Activity.IDLE)); ++ Activity activity1 = (Activity) behaviorcontroller.getActiveNonCoreActivity().orElse(null); // CraftBukkit - decompile error ++ + if (activity != activity1) { +- getSoundForCurrentActivity(piglin).ifPresent(piglin::playSoundEvent); ++ Optional optional = getSoundForCurrentActivity(piglin); // CraftBukkit - decompile error ++ ++ Objects.requireNonNull(piglin); ++ optional.ifPresent(piglin::playSoundEvent); + } + +- piglin.setAggressive(brain.hasMemoryValue(MemoryModuleType.ATTACK_TARGET)); +- if (!brain.hasMemoryValue(MemoryModuleType.RIDE_TARGET) && isBabyRidingBaby(piglin)) { ++ piglin.setAggressive(behaviorcontroller.hasMemoryValue(MemoryModuleType.ATTACK_TARGET)); ++ if (!behaviorcontroller.hasMemoryValue(MemoryModuleType.RIDE_TARGET) && isBabyRidingBaby(piglin)) { + piglin.stopRiding(); + } + +- if (!brain.hasMemoryValue(MemoryModuleType.CELEBRATE_LOCATION)) { +- brain.eraseMemory(MemoryModuleType.DANCING); ++ if (!behaviorcontroller.hasMemoryValue(MemoryModuleType.CELEBRATE_LOCATION)) { ++ behaviorcontroller.eraseMemory(MemoryModuleType.DANCING); + } + +- piglin.setDancing(brain.hasMemoryValue(MemoryModuleType.DANCING)); ++ piglin.setDancing(behaviorcontroller.hasMemoryValue(MemoryModuleType.DANCING)); + } + + private static boolean isBabyRidingBaby(Piglin passenger) { + if (!passenger.isBaby()) { + return false; + } else { +- Entity vehicle = passenger.getVehicle(); +- return vehicle instanceof Piglin && ((Piglin)vehicle).isBaby() || vehicle instanceof Hoglin && ((Hoglin)vehicle).isBaby(); ++ Entity entity = passenger.getVehicle(); ++ ++ return entity instanceof Piglin && ((Piglin) entity).isBaby() || entity instanceof Hoglin && ((Hoglin) entity).isBaby(); + } + } + + protected static void pickUpItem(Piglin piglin, ItemEntity itemEntity) { + stopWalking(piglin); +- ItemStack item; +- if (itemEntity.getItem().is(Items.GOLD_NUGGET)) { ++ ItemStack itemstack; ++ ++ // CraftBukkit start ++ if (itemEntity.getItem().is(Items.GOLD_NUGGET) && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(piglin, itemEntity, 0, false).isCancelled()) { + piglin.take(itemEntity, itemEntity.getItem().getCount()); +- item = itemEntity.getItem(); ++ itemstack = itemEntity.getItem(); + itemEntity.discard(); +- } else { ++ } else if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(piglin, itemEntity, itemEntity.getItem().getCount() - 1, false).isCancelled()) { + piglin.take(itemEntity, 1); +- item = removeOneItemFromItemEntity(itemEntity); ++ itemstack = removeOneItemFromItemEntity(itemEntity); ++ } else { ++ return; + } ++ // CraftBukkit end + +- if (isLovedItem(item)) { ++ if (isLovedItem(itemstack, piglin)) { // CraftBukkit - Changes to allow for custom payment in bartering + piglin.getBrain().eraseMemory(MemoryModuleType.TIME_TRYING_TO_REACH_ADMIRE_ITEM); +- holdInOffhand(piglin, item); ++ holdInOffhand(piglin, itemstack); + admireGoldItem(piglin); +- } else if (isFood(item) && !hasEatenRecently(piglin)) { ++ } else if (isFood(itemstack) && !hasEatenRecently(piglin)) { + eat(piglin); + } else { +- boolean flag = !piglin.equipItemIfPossible(item).equals(ItemStack.EMPTY); ++ boolean flag = !piglin.equipItemIfPossible(itemstack, itemEntity).equals(ItemStack.EMPTY); // CraftBukkit ++ + if (!flag) { +- putInInventory(piglin, item); ++ putInInventory(piglin, itemstack); + } + } + } + + private static void holdInOffhand(Piglin piglin, ItemStack stack) { + if (isHoldingItemInOffHand(piglin)) { +- piglin.spawnAtLocation(piglin.getItemInHand(InteractionHand.OFF_HAND)); ++ piglin.spawnAtLocation(piglin.getItemInHand(EnumHand.OFF_HAND)); + } + + piglin.holdInOffHand(stack); + } + + private static ItemStack removeOneItemFromItemEntity(ItemEntity itemEntity) { +- ItemStack item = itemEntity.getItem(); +- ItemStack itemStack = item.split(1); +- if (item.isEmpty()) { ++ ItemStack itemstack = itemEntity.getItem(); ++ ItemStack itemstack1 = itemstack.split(1); ++ ++ if (itemstack.isEmpty()) { + itemEntity.discard(); + } else { +- itemEntity.setItem(item); ++ itemEntity.setItem(itemstack); + } + +- return itemStack; ++ return itemstack1; + } + + protected static void stopHoldingOffHandItem(Piglin piglin, boolean shouldBarter) { +- ItemStack itemInHand = piglin.getItemInHand(InteractionHand.OFF_HAND); +- piglin.setItemInHand(InteractionHand.OFF_HAND, ItemStack.EMPTY); ++ ItemStack itemstack = piglin.getItemInHand(EnumHand.OFF_HAND); ++ ++ piglin.setItemInHand(EnumHand.OFF_HAND, ItemStack.EMPTY); ++ boolean flag1; ++ + if (piglin.isAdult()) { +- boolean isBarterCurrency = isBarterCurrency(itemInHand); +- if (shouldBarter && isBarterCurrency) { +- throwItems(piglin, getBarterResponseItems(piglin)); +- } else if (!isBarterCurrency) { +- boolean flag = !piglin.equipItemIfPossible(itemInHand).isEmpty(); +- if (!flag) { +- putInInventory(piglin, itemInHand); ++ flag1 = isBarterCurrency(itemstack, piglin); // CraftBukkit - Changes to allow custom payment for bartering ++ if (shouldBarter && flag1) { ++ // CraftBukkit start ++ PiglinBarterEvent event = CraftEventFactory.callPiglinBarterEvent(piglin, getBarterResponseItems(piglin), itemstack); ++ if (!event.isCancelled()) { ++ throwItems(piglin, event.getOutcome().stream().map(CraftItemStack::asNMSCopy).collect(Collectors.toList())); + } ++ // CraftBukkit end ++ } else if (!flag1) { ++ boolean flag2 = !piglin.equipItemIfPossible(itemstack).isEmpty(); ++ ++ if (!flag2) { ++ putInInventory(piglin, itemstack); ++ } + } + } else { +- boolean isBarterCurrency = !piglin.equipItemIfPossible(itemInHand).isEmpty(); +- if (!isBarterCurrency) { +- ItemStack mainHandItem = piglin.getMainHandItem(); +- if (isLovedItem(mainHandItem)) { +- putInInventory(piglin, mainHandItem); ++ flag1 = !piglin.equipItemIfPossible(itemstack).isEmpty(); ++ if (!flag1) { ++ ItemStack itemstack1 = piglin.getMainHandItem(); ++ ++ if (isLovedItem(itemstack1, piglin)) { // CraftBukkit - Changes to allow for custom payment in bartering ++ putInInventory(piglin, itemstack1); + } else { +- throwItems(piglin, Collections.singletonList(mainHandItem)); ++ throwItems(piglin, Collections.singletonList(itemstack1)); + } + +- piglin.holdInMainHand(itemInHand); ++ piglin.holdInMainHand(itemstack); + } + } ++ + } + + protected static void cancelAdmiring(Piglin piglin) { + if (isAdmiringItem(piglin) && !piglin.getOffhandItem().isEmpty()) { + piglin.spawnAtLocation(piglin.getOffhandItem()); +- piglin.setItemInHand(InteractionHand.OFF_HAND, ItemStack.EMPTY); ++ piglin.setItemInHand(EnumHand.OFF_HAND, ItemStack.EMPTY); + } ++ + } + + private static void putInInventory(Piglin piglin, ItemStack stack) { +- ItemStack itemStack = piglin.addToInventory(stack); +- throwItemsTowardRandomPos(piglin, Collections.singletonList(itemStack)); ++ ItemStack itemstack1 = piglin.addToInventory(stack); ++ ++ throwItemsTowardRandomPos(piglin, Collections.singletonList(itemstack1)); + } + + private static void throwItems(Piglin pilgin, List stacks) { +- Optional memory = pilgin.getBrain().getMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER); +- if (memory.isPresent()) { +- throwItemsTowardPlayer(pilgin, memory.get(), stacks); ++ Optional optional = pilgin.getBrain().getMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER); ++ ++ if (optional.isPresent()) { ++ throwItemsTowardPlayer(pilgin, (Player) optional.get(), stacks); + } else { + throwItemsTowardRandomPos(pilgin, stacks); + } ++ + } + + private static void throwItemsTowardRandomPos(Piglin piglin, List stacks) { +@@ -432,24 +363,27 @@ + + private static void throwItemsTowardPos(Piglin piglin, List stacks, Vec3 pos) { + if (!stacks.isEmpty()) { +- piglin.swing(InteractionHand.OFF_HAND); ++ piglin.swing(EnumHand.OFF_HAND); ++ Iterator iterator = stacks.iterator(); + +- for (ItemStack itemStack : stacks) { +- BehaviorUtils.throwItem(piglin, itemStack, pos.add(0.0, 1.0, 0.0)); ++ while (iterator.hasNext()) { ++ ItemStack itemstack = (ItemStack) iterator.next(); ++ ++ BehaviorUtils.throwItem(piglin, itemstack, pos.add(0.0D, 1.0D, 0.0D)); + } + } ++ + } + + private static List getBarterResponseItems(Piglin piglin) { +- LootTable lootTable = piglin.level().getServer().getLootData().getLootTable(BuiltInLootTables.PIGLIN_BARTERING); +- List randomItems = lootTable.getRandomItems( +- new LootParams.Builder((ServerLevel)piglin.level()).withParameter(LootContextParams.THIS_ENTITY, piglin).create(LootContextParamSets.PIGLIN_BARTER) +- ); +- return randomItems; ++ LootTable loottable = piglin.level().getServer().getLootData().getLootTable(BuiltInLootTables.PIGLIN_BARTERING); ++ List list = loottable.getRandomItems((new LootParams.Builder((ServerLevel) piglin.level())).withParameter(LootContextParams.THIS_ENTITY, piglin).create(LootContextParamSets.PIGLIN_BARTER)); ++ ++ return list; + } + + private static boolean wantsToDance(LivingEntity piglin, LivingEntity target) { +- return target.getType() == EntityType.HOGLIN && RandomSource.create(piglin.level().getGameTime()).nextFloat() < 0.1F; ++ return target.getType() != EntityType.HOGLIN ? false : RandomSource.create(piglin.level().getGameTime()).nextFloat() < 0.1F; + } + + protected static boolean wantsToPickup(Piglin piglin, ItemStack stack) { +@@ -459,86 +393,107 @@ + return false; + } else if (isAdmiringDisabled(piglin) && piglin.getBrain().hasMemoryValue(MemoryModuleType.ATTACK_TARGET)) { + return false; +- } else if (isBarterCurrency(stack)) { ++ } else if (isBarterCurrency(stack, piglin)) { // CraftBukkit + return isNotHoldingLovedItemInOffHand(piglin); + } else { +- boolean canAddToInventory = piglin.canAddToInventory(stack); +- if (stack.is(Items.GOLD_NUGGET)) { +- return canAddToInventory; +- } else if (isFood(stack)) { +- return !hasEatenRecently(piglin) && canAddToInventory; +- } else { +- return !isLovedItem(stack) ? piglin.canReplaceCurrentItem(stack) : isNotHoldingLovedItemInOffHand(piglin) && canAddToInventory; +- } ++ boolean flag = piglin.canAddToInventory(stack); ++ ++ return stack.is(Items.GOLD_NUGGET) ? flag : (isFood(stack) ? !hasEatenRecently(piglin) && flag : (!isLovedItem(stack) ? piglin.canReplaceCurrentItem(stack) : isNotHoldingLovedItemInOffHand(piglin) && flag)); + } + } + ++ // CraftBukkit start - Added method to allow checking for custom payment items ++ protected static boolean isLovedItem(ItemStack itemstack, Piglin piglin) { ++ return isLovedItem(itemstack) || (piglin.interestItems.contains(itemstack.getItem()) || piglin.allowedBarterItems.contains(itemstack.getItem())); ++ } ++ // CraftBukkit end ++ + protected static boolean isLovedItem(ItemStack item) { + return item.is(ItemTags.PIGLIN_LOVED); + } + + private static boolean wantsToStopRiding(Piglin piglin, Entity vehicle) { +- return vehicle instanceof Mob mob +- && (!mob.isBaby() || !mob.isAlive() || wasHurtRecently(piglin) || wasHurtRecently(mob) || mob instanceof Piglin && mob.getVehicle() == null); ++ if (!(vehicle instanceof Mob)) { ++ return false; ++ } else { ++ Mob entityinsentient = (Mob) vehicle; ++ ++ return !entityinsentient.isBaby() || !entityinsentient.isAlive() || wasHurtRecently(piglin) || wasHurtRecently(entityinsentient) || entityinsentient instanceof Piglin && entityinsentient.getVehicle() == null; ++ } + } + + private static boolean isNearestValidAttackTarget(Piglin piglin, LivingEntity target) { +- return findNearestValidAttackTarget(piglin).filter(entity -> entity == target).isPresent(); ++ return findNearestValidAttackTarget(piglin).filter((entityliving1) -> { ++ return entityliving1 == target; ++ }).isPresent(); + } + + private static boolean isNearZombified(Piglin piglin) { +- Brain brain = piglin.getBrain(); +- if (brain.hasMemoryValue(MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED)) { +- LivingEntity livingEntity = brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED).get(); +- return piglin.closerThan(livingEntity, 6.0); ++ Brain behaviorcontroller = piglin.getBrain(); ++ ++ if (behaviorcontroller.hasMemoryValue(MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED)) { ++ LivingEntity entityliving = (LivingEntity) behaviorcontroller.getMemory(MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED).get(); ++ ++ return piglin.closerThan(entityliving, 6.0D); + } else { + return false; + } + } + + private static Optional findNearestValidAttackTarget(Piglin piglin) { +- Brain brain = piglin.getBrain(); ++ Brain behaviorcontroller = piglin.getBrain(); ++ + if (isNearZombified(piglin)) { + return Optional.empty(); + } else { +- Optional livingEntityFromUUIDMemory = BehaviorUtils.getLivingEntityFromUUIDMemory(piglin, MemoryModuleType.ANGRY_AT); +- if (livingEntityFromUUIDMemory.isPresent() && Sensor.isEntityAttackableIgnoringLineOfSight(piglin, livingEntityFromUUIDMemory.get())) { +- return livingEntityFromUUIDMemory; ++ Optional optional = BehaviorUtils.getLivingEntityFromUUIDMemory(piglin, MemoryModuleType.ANGRY_AT); ++ ++ if (optional.isPresent() && Sensor.isEntityAttackableIgnoringLineOfSight(piglin, (LivingEntity) optional.get())) { ++ return optional; + } else { +- if (brain.hasMemoryValue(MemoryModuleType.UNIVERSAL_ANGER)) { +- Optional memory = brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER); +- if (memory.isPresent()) { +- return memory; ++ Optional optional1; ++ ++ if (behaviorcontroller.hasMemoryValue(MemoryModuleType.UNIVERSAL_ANGER)) { ++ optional1 = behaviorcontroller.getMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER); ++ if (optional1.isPresent()) { ++ return optional1; + } + } + +- Optional memory = brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_NEMESIS); +- if (memory.isPresent()) { +- return memory; ++ optional1 = behaviorcontroller.getMemory(MemoryModuleType.NEAREST_VISIBLE_NEMESIS); ++ if (optional1.isPresent()) { ++ return optional1; + } else { +- Optional memory1 = brain.getMemory(MemoryModuleType.NEAREST_TARGETABLE_PLAYER_NOT_WEARING_GOLD); +- return memory1.isPresent() && Sensor.isEntityAttackable(piglin, memory1.get()) ? memory1 : Optional.empty(); ++ Optional optional2 = behaviorcontroller.getMemory(MemoryModuleType.NEAREST_TARGETABLE_PLAYER_NOT_WEARING_GOLD); ++ ++ return optional2.isPresent() && Sensor.isEntityAttackable(piglin, (LivingEntity) optional2.get()) ? optional2 : Optional.empty(); + } + } + } + } + + public static void angerNearbyPiglins(Player player, boolean angerOnlyIfCanSee) { +- List entitiesOfClass = player.level().getEntitiesOfClass(Piglin.class, player.getBoundingBox().inflate(16.0)); +- entitiesOfClass.stream().filter(PiglinAi::isIdle).filter(piglin -> !angerOnlyIfCanSee || BehaviorUtils.canSee(piglin, player)).forEach(piglin -> { +- if (piglin.level().getGameRules().getBoolean(GameRules.RULE_UNIVERSAL_ANGER)) { +- setAngerTargetToNearestTargetablePlayerIfFound(piglin, player); ++ List list = player.level().getEntitiesOfClass(Piglin.class, player.getBoundingBox().inflate(16.0D)); ++ ++ list.stream().filter(PiglinAi::isIdle).filter((entitypiglin) -> { ++ return !angerOnlyIfCanSee || BehaviorUtils.canSee(entitypiglin, player); ++ }).forEach((entitypiglin) -> { ++ if (entitypiglin.level().getGameRules().getBoolean(GameRules.RULE_UNIVERSAL_ANGER)) { ++ setAngerTargetToNearestTargetablePlayerIfFound(entitypiglin, player); + } else { +- setAngerTarget(piglin, player); ++ setAngerTarget(entitypiglin, player); + } ++ + }); + } + +- public static InteractionResult mobInteract(Piglin piglin, Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (canAdmire(piglin, itemInHand)) { +- ItemStack itemStack = itemInHand.split(1); +- holdInOffhand(piglin, itemStack); ++ public static InteractionResult mobInteract(Piglin piglin, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (canAdmire(piglin, itemstack)) { ++ ItemStack itemstack1 = itemstack.split(1); ++ ++ holdInOffhand(piglin, itemstack1); + admireGoldItem(piglin); + stopWalking(piglin); + return InteractionResult.CONSUME; +@@ -548,7 +503,7 @@ + } + + protected static boolean canAdmire(Piglin piglin, ItemStack stack) { +- return !isAdmiringDisabled(piglin) && !isAdmiringItem(piglin) && piglin.isAdult() && isBarterCurrency(stack); ++ return !isAdmiringDisabled(piglin) && !isAdmiringItem(piglin) && piglin.isAdult() && isBarterCurrency(stack, piglin); // CraftBukkit + } + + protected static void wasHurtBy(Piglin piglin, LivingEntity target) { +@@ -557,24 +512,27 @@ + stopHoldingOffHandItem(piglin, false); + } + +- Brain brain = piglin.getBrain(); +- brain.eraseMemory(MemoryModuleType.CELEBRATE_LOCATION); +- brain.eraseMemory(MemoryModuleType.DANCING); +- brain.eraseMemory(MemoryModuleType.ADMIRING_ITEM); ++ Brain behaviorcontroller = piglin.getBrain(); ++ ++ behaviorcontroller.eraseMemory(MemoryModuleType.CELEBRATE_LOCATION); ++ behaviorcontroller.eraseMemory(MemoryModuleType.DANCING); ++ behaviorcontroller.eraseMemory(MemoryModuleType.ADMIRING_ITEM); + if (target instanceof Player) { +- brain.setMemoryWithExpiry(MemoryModuleType.ADMIRING_DISABLED, true, 400L); ++ behaviorcontroller.setMemoryWithExpiry(MemoryModuleType.ADMIRING_DISABLED, true, 400L); + } + +- getAvoidTarget(piglin).ifPresent(entity -> { +- if (entity.getType() != target.getType()) { +- brain.eraseMemory(MemoryModuleType.AVOID_TARGET); ++ getAvoidTarget(piglin).ifPresent((entityliving1) -> { ++ if (entityliving1.getType() != target.getType()) { ++ behaviorcontroller.eraseMemory(MemoryModuleType.AVOID_TARGET); + } ++ + }); + if (piglin.isBaby()) { +- brain.setMemoryWithExpiry(MemoryModuleType.AVOID_TARGET, target, 100L); ++ behaviorcontroller.setMemoryWithExpiry(MemoryModuleType.AVOID_TARGET, target, 100L); + if (Sensor.isEntityAttackableIgnoringLineOfSight(piglin, target)) { + broadcastAngerTarget(piglin, target); + } ++ + } else if (target.getType() == EntityType.HOGLIN && hoglinsOutnumberPiglins(piglin)) { + setAvoidTargetAndDontHuntForAWhile(piglin, target); + broadcastRetreat(piglin, target); +@@ -587,7 +545,7 @@ + protected static void maybeRetaliate(AbstractPiglin piglin, LivingEntity target) { + if (!piglin.getBrain().isActive(Activity.AVOID)) { + if (Sensor.isEntityAttackableIgnoringLineOfSight(piglin, target)) { +- if (!BehaviorUtils.isOtherTargetMuchFurtherAwayThanCurrentAttackTarget(piglin, target, 4.0)) { ++ if (!BehaviorUtils.isOtherTargetMuchFurtherAwayThanCurrentAttackTarget(piglin, target, 4.0D)) { + if (target.getType() == EntityType.PLAYER && piglin.level().getGameRules().getBoolean(GameRules.RULE_UNIVERSAL_ANGER)) { + setAngerTargetToNearestTargetablePlayerIfFound(piglin, target); + broadcastUniversalAnger(piglin); +@@ -595,55 +553,53 @@ + setAngerTarget(piglin, target); + broadcastAngerTarget(piglin, target); + } ++ + } + } + } + } + + public static Optional getSoundForCurrentActivity(Piglin piglin) { +- return piglin.getBrain().getActiveNonCoreActivity().map(activity -> getSoundForActivity(piglin, activity)); ++ return piglin.getBrain().getActiveNonCoreActivity().map((activity) -> { ++ return getSoundForActivity(piglin, activity); ++ }); + } + + private static SoundEvent getSoundForActivity(Piglin piglin, Activity activity) { +- if (activity == Activity.FIGHT) { +- return SoundEvents.PIGLIN_ANGRY; +- } else if (piglin.isConverting()) { +- return SoundEvents.PIGLIN_RETREAT; +- } else if (activity == Activity.AVOID && isNearAvoidTarget(piglin)) { +- return SoundEvents.PIGLIN_RETREAT; +- } else if (activity == Activity.ADMIRE_ITEM) { +- return SoundEvents.PIGLIN_ADMIRING_ITEM; +- } else if (activity == Activity.CELEBRATE) { +- return SoundEvents.PIGLIN_CELEBRATE; +- } else if (seesPlayerHoldingLovedItem(piglin)) { +- return SoundEvents.PIGLIN_JEALOUS; +- } else { +- return isNearRepellent(piglin) ? SoundEvents.PIGLIN_RETREAT : SoundEvents.PIGLIN_AMBIENT; +- } ++ return activity == Activity.FIGHT ? SoundEvents.PIGLIN_ANGRY : (piglin.isConverting() ? SoundEvents.PIGLIN_RETREAT : (activity == Activity.AVOID && isNearAvoidTarget(piglin) ? SoundEvents.PIGLIN_RETREAT : (activity == Activity.ADMIRE_ITEM ? SoundEvents.PIGLIN_ADMIRING_ITEM : (activity == Activity.CELEBRATE ? SoundEvents.PIGLIN_CELEBRATE : (seesPlayerHoldingLovedItem(piglin) ? SoundEvents.PIGLIN_JEALOUS : (isNearRepellent(piglin) ? SoundEvents.PIGLIN_RETREAT : SoundEvents.PIGLIN_AMBIENT)))))); + } + + private static boolean isNearAvoidTarget(Piglin piglin) { +- Brain brain = piglin.getBrain(); +- return brain.hasMemoryValue(MemoryModuleType.AVOID_TARGET) && brain.getMemory(MemoryModuleType.AVOID_TARGET).get().closerThan(piglin, 12.0); ++ Brain behaviorcontroller = piglin.getBrain(); ++ ++ return !behaviorcontroller.hasMemoryValue(MemoryModuleType.AVOID_TARGET) ? false : ((LivingEntity) behaviorcontroller.getMemory(MemoryModuleType.AVOID_TARGET).get()).closerThan(piglin, 12.0D); + } + + protected static List getVisibleAdultPiglins(Piglin piglin) { +- return piglin.getBrain().getMemory(MemoryModuleType.NEAREST_VISIBLE_ADULT_PIGLINS).orElse(ImmutableList.of()); ++ return (List) piglin.getBrain().getMemory(MemoryModuleType.NEAREST_VISIBLE_ADULT_PIGLINS).orElse(ImmutableList.of()); + } + + private static List getAdultPiglins(AbstractPiglin piglin) { +- return piglin.getBrain().getMemory(MemoryModuleType.NEARBY_ADULT_PIGLINS).orElse(ImmutableList.of()); ++ return (List) piglin.getBrain().getMemory(MemoryModuleType.NEARBY_ADULT_PIGLINS).orElse(ImmutableList.of()); + } + + public static boolean isWearingGold(LivingEntity livingEntity) { +- for (ItemStack itemStack : livingEntity.getArmorSlots()) { +- Item item = itemStack.getItem(); +- if (item instanceof ArmorItem && ((ArmorItem)item).getMaterial() == ArmorMaterials.GOLD) { +- return true; ++ Iterable iterable = livingEntity.getArmorSlots(); ++ Iterator iterator = iterable.iterator(); ++ ++ Item item; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return false; + } +- } + +- return false; ++ ItemStack itemstack = (ItemStack) iterator.next(); ++ ++ item = itemstack.getItem(); ++ } while (!(item instanceof ArmorItem) || ((ArmorItem) item).getMaterial() != ArmorMaterials.GOLD); ++ ++ return true; + } + + private static void stopWalking(Piglin piglin) { +@@ -652,25 +608,27 @@ + } + + private static BehaviorControl babySometimesRideBabyHoglin() { +- SetEntityLookTargetSometimes.Ticker ticker = new SetEntityLookTargetSometimes.Ticker(RIDE_START_INTERVAL); +- return CopyMemoryWithExpiry.create( +- livingEntity -> livingEntity.isBaby() && ticker.tickDownAndCheck(livingEntity.level().random), +- MemoryModuleType.NEAREST_VISIBLE_BABY_HOGLIN, +- MemoryModuleType.RIDE_TARGET, +- RIDE_DURATION +- ); ++ SetEntityLookTargetSometimes.Ticker setentitylooktargetsometimes_a = new SetEntityLookTargetSometimes.Ticker(PiglinAi.RIDE_START_INTERVAL); ++ ++ return CopyMemoryWithExpiry.create((entityliving) -> { ++ return entityliving.isBaby() && setentitylooktargetsometimes_a.tickDownAndCheck(entityliving.level().random); ++ }, MemoryModuleType.NEAREST_VISIBLE_BABY_HOGLIN, MemoryModuleType.RIDE_TARGET, PiglinAi.RIDE_DURATION); + } + + protected static void broadcastAngerTarget(AbstractPiglin piglin, LivingEntity target) { +- getAdultPiglins(piglin).forEach(adultPiglin -> { +- if (target.getType() != EntityType.HOGLIN || adultPiglin.canHunt() && ((Hoglin)target).canBeHunted()) { +- setAngerTargetIfCloserThanCurrent(adultPiglin, target); ++ getAdultPiglins(piglin).forEach((entitypiglinabstract1) -> { ++ if (target.getType() != EntityType.HOGLIN || entitypiglinabstract1.canHunt() && ((Hoglin) target).canBeHunted()) { ++ setAngerTargetIfCloserThanCurrent(entitypiglinabstract1, target); + } + }); + } + + protected static void broadcastUniversalAnger(AbstractPiglin piglin) { +- getAdultPiglins(piglin).forEach(adultPiglin -> getNearestVisibleTargetablePlayer(adultPiglin).ifPresent(player -> setAngerTarget(adultPiglin, player))); ++ getAdultPiglins(piglin).forEach((entitypiglinabstract1) -> { ++ getNearestVisibleTargetablePlayer(entitypiglinabstract1).ifPresent((entityhuman) -> { ++ setAngerTarget(entitypiglinabstract1, entityhuman); ++ }); ++ }); + } + + protected static void setAngerTarget(AbstractPiglin piglin, LivingEntity target) { +@@ -684,23 +642,27 @@ + if (target.getType() == EntityType.PLAYER && piglin.level().getGameRules().getBoolean(GameRules.RULE_UNIVERSAL_ANGER)) { + piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.UNIVERSAL_ANGER, true, 600L); + } ++ + } + } + + private static void setAngerTargetToNearestTargetablePlayerIfFound(AbstractPiglin piglin, LivingEntity currentTarget) { +- Optional nearestVisibleTargetablePlayer = getNearestVisibleTargetablePlayer(piglin); +- if (nearestVisibleTargetablePlayer.isPresent()) { +- setAngerTarget(piglin, nearestVisibleTargetablePlayer.get()); ++ Optional optional = getNearestVisibleTargetablePlayer(piglin); ++ ++ if (optional.isPresent()) { ++ setAngerTarget(piglin, (LivingEntity) optional.get()); + } else { + setAngerTarget(piglin, currentTarget); + } ++ + } + + private static void setAngerTargetIfCloserThanCurrent(AbstractPiglin piglin, LivingEntity currentTarget) { +- Optional angerTarget = getAngerTarget(piglin); +- LivingEntity nearestTarget = BehaviorUtils.getNearestTarget(piglin, angerTarget, currentTarget); +- if (!angerTarget.isPresent() || angerTarget.get() != nearestTarget) { +- setAngerTarget(piglin, nearestTarget); ++ Optional optional = getAngerTarget(piglin); ++ LivingEntity entityliving1 = BehaviorUtils.getNearestTarget(piglin, optional, currentTarget); ++ ++ if (!optional.isPresent() || optional.get() != entityliving1) { ++ setAngerTarget(piglin, entityliving1); + } + } + +@@ -713,35 +675,35 @@ + } + + public static Optional getNearestVisibleTargetablePlayer(AbstractPiglin piglin) { +- return piglin.getBrain().hasMemoryValue(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER) +- ? piglin.getBrain().getMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER) +- : Optional.empty(); ++ return piglin.getBrain().hasMemoryValue(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER) ? piglin.getBrain().getMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER) : Optional.empty(); + } + + private static void broadcastRetreat(Piglin piglin, LivingEntity target) { +- getVisibleAdultPiglins(piglin) +- .stream() +- .filter(adultPiglin -> adultPiglin instanceof Piglin) +- .forEach(adultPiglin -> retreatFromNearestTarget((Piglin)adultPiglin, target)); ++ getVisibleAdultPiglins(piglin).stream().filter((entitypiglinabstract) -> { ++ return entitypiglinabstract instanceof Piglin; ++ }).forEach((entitypiglinabstract) -> { ++ retreatFromNearestTarget((Piglin) entitypiglinabstract, target); ++ }); + } + + private static void retreatFromNearestTarget(Piglin piglin, LivingEntity target) { +- Brain brain = piglin.getBrain(); +- LivingEntity livingEntity = BehaviorUtils.getNearestTarget(piglin, brain.getMemory(MemoryModuleType.AVOID_TARGET), target); +- livingEntity = BehaviorUtils.getNearestTarget(piglin, brain.getMemory(MemoryModuleType.ATTACK_TARGET), livingEntity); +- setAvoidTargetAndDontHuntForAWhile(piglin, livingEntity); ++ Brain behaviorcontroller = piglin.getBrain(); ++ LivingEntity entityliving1 = BehaviorUtils.getNearestTarget(piglin, behaviorcontroller.getMemory(MemoryModuleType.AVOID_TARGET), target); ++ ++ entityliving1 = BehaviorUtils.getNearestTarget(piglin, behaviorcontroller.getMemory(MemoryModuleType.ATTACK_TARGET), entityliving1); ++ setAvoidTargetAndDontHuntForAWhile(piglin, entityliving1); + } + + private static boolean wantsToStopFleeing(Piglin piglin) { +- Brain brain = piglin.getBrain(); +- if (!brain.hasMemoryValue(MemoryModuleType.AVOID_TARGET)) { ++ Brain behaviorcontroller = piglin.getBrain(); ++ ++ if (!behaviorcontroller.hasMemoryValue(MemoryModuleType.AVOID_TARGET)) { + return true; + } else { +- LivingEntity livingEntity = brain.getMemory(MemoryModuleType.AVOID_TARGET).get(); +- EntityType type = livingEntity.getType(); +- return type == EntityType.HOGLIN +- ? piglinsEqualOrOutnumberHoglins(piglin) +- : isZombified(type) && !brain.isMemoryValue(MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED, livingEntity); ++ LivingEntity entityliving = (LivingEntity) behaviorcontroller.getMemory(MemoryModuleType.AVOID_TARGET).get(); ++ EntityType entitytypes = entityliving.getType(); ++ ++ return entitytypes == EntityType.HOGLIN ? piglinsEqualOrOutnumberHoglins(piglin) : (isZombified(entitytypes) ? !behaviorcontroller.isMemoryValue(MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED, entityliving) : false); + } + } + +@@ -750,21 +712,22 @@ + } + + private static boolean hoglinsOutnumberPiglins(Piglin piglin) { +- int i = piglin.getBrain().getMemory(MemoryModuleType.VISIBLE_ADULT_PIGLIN_COUNT).orElse(0) + 1; +- int i1 = piglin.getBrain().getMemory(MemoryModuleType.VISIBLE_ADULT_HOGLIN_COUNT).orElse(0); +- return i1 > i; ++ int i = (Integer) piglin.getBrain().getMemory(MemoryModuleType.VISIBLE_ADULT_PIGLIN_COUNT).orElse(0) + 1; ++ int j = (Integer) piglin.getBrain().getMemory(MemoryModuleType.VISIBLE_ADULT_HOGLIN_COUNT).orElse(0); ++ ++ return j > i; + } + + private static void setAvoidTargetAndDontHuntForAWhile(Piglin piglin, LivingEntity target) { + piglin.getBrain().eraseMemory(MemoryModuleType.ANGRY_AT); + piglin.getBrain().eraseMemory(MemoryModuleType.ATTACK_TARGET); + piglin.getBrain().eraseMemory(MemoryModuleType.WALK_TARGET); +- piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.AVOID_TARGET, target, (long)RETREAT_DURATION.sample(piglin.level().random)); ++ piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.AVOID_TARGET, target, (long) PiglinAi.RETREAT_DURATION.sample(piglin.level().random)); + dontKillAnyMoreHoglinsForAWhile(piglin); + } + + protected static void dontKillAnyMoreHoglinsForAWhile(AbstractPiglin piglin) { +- piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.HUNTED_RECENTLY, true, (long)TIME_BETWEEN_HUNTS.sample(piglin.level().random)); ++ piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.HUNTED_RECENTLY, true, (long) PiglinAi.TIME_BETWEEN_HUNTS.sample(piglin.level().random)); + } + + private static void eat(Piglin piglin) { +@@ -772,8 +735,9 @@ + } + + private static Vec3 getRandomNearbyPos(Piglin piglin) { +- Vec3 pos = LandRandomPos.getPos(piglin, 4, 2); +- return pos == null ? piglin.position() : pos; ++ Vec3 vec3d = LandRandomPos.getPos(piglin, 4, 2); ++ ++ return vec3d == null ? piglin.position() : vec3d; + } + + private static boolean hasEatenRecently(Piglin piglin) { +@@ -796,8 +760,14 @@ + return piglin.getBrain().hasMemoryValue(MemoryModuleType.ADMIRING_ITEM); + } + ++ // CraftBukkit start - Changes to allow custom payment for bartering ++ private static boolean isBarterCurrency(ItemStack itemstack, Piglin piglin) { ++ return isBarterCurrency(itemstack) || piglin.allowedBarterItems.contains(itemstack.getItem()); ++ } ++ // CraftBukkit end ++ + private static boolean isBarterCurrency(ItemStack stack) { +- return stack.is(BARTERING_ITEM); ++ return stack.is(PiglinAi.BARTERING_ITEM); + } + + private static boolean isFood(ItemStack stack) { +@@ -833,7 +803,7 @@ + } + + private static boolean isNotHoldingLovedItemInOffHand(Piglin piglin) { +- return piglin.getOffhandItem().isEmpty() || !isLovedItem(piglin.getOffhandItem()); ++ return piglin.getOffhandItem().isEmpty() || !isLovedItem(piglin.getOffhandItem(), piglin); // CraftBukkit - Changes to allow custom payment for bartering + } + + public static boolean isZombified(EntityType entityType) { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/warden/Warden.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/warden/Warden.java.patch new file mode 100644 index 0000000000..7cb6a96030 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/warden/Warden.java.patch @@ -0,0 +1,615 @@ +--- a/net/minecraft/world/entity/monster/warden/Warden.java ++++ b/net/minecraft/world/entity/monster/warden/Warden.java +@@ -2,8 +2,10 @@ + + import com.google.common.annotations.VisibleForTesting; + import com.mojang.logging.LogUtils; ++import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; + import java.util.Collections; ++import java.util.Objects; + import java.util.Optional; + import java.util.function.BiConsumer; + import javax.annotation.Nullable; +@@ -12,7 +14,6 @@ + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtOps; +-import net.minecraft.nbt.Tag; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientGamePacketListener; + import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; +@@ -37,12 +38,12 @@ + import net.minecraft.world.entity.AnimationState; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -56,8 +57,8 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.ServerLevelAccessor; +-import net.minecraft.world.level.block.RenderShape; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.EnumRenderType; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.DynamicGameEventListener; + import net.minecraft.world.level.gameevent.EntityPositionSource; + import net.minecraft.world.level.gameevent.GameEvent; +@@ -73,6 +74,7 @@ + import org.slf4j.Logger; + + public class Warden extends Monster implements VibrationSystem { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int VIBRATION_COOLDOWN_TICKS = 40; + private static final int TIME_TO_USE_MELEE_UNTIL_SONIC_BOOM = 200; +@@ -106,16 +108,13 @@ + public AnimationState diggingAnimationState = new AnimationState(); + public AnimationState attackAnimationState = new AnimationState(); + public AnimationState sonicBoomAnimationState = new AnimationState(); +- private final DynamicGameEventListener dynamicGameEventListener; +- private final VibrationSystem.User vibrationUser; +- private VibrationSystem.Data vibrationData; ++ private final DynamicGameEventListener dynamicGameEventListener = new DynamicGameEventListener<>(new VibrationSystem.Listener(this)); ++ private final VibrationSystem.User vibrationUser = new Warden.a(); ++ private VibrationSystem.Data vibrationData = new VibrationSystem.Data(); + AngerManagement angerManagement = new AngerManagement(this::canTargetEntity, Collections.emptyList()); + + public Warden(EntityType entityType, Level level) { + super(entityType, level); +- this.vibrationUser = new Warden.VibrationUser(); +- this.vibrationData = new VibrationSystem.Data(); +- this.dynamicGameEventListener = new DynamicGameEventListener<>(new VibrationSystem.Listener(this)); + this.xpReward = 5; + this.getNavigation().setCanFloat(true); + this.setPathfindingMalus(BlockPathTypes.UNPASSABLE_RAIL, 0.0F); +@@ -128,15 +127,16 @@ + + @Override + public Packet getAddEntityPacket() { +- return new ClientboundAddEntityPacket(this, this.hasPose(Pose.EMERGING) ? 1 : 0); ++ return new ClientboundAddEntityPacket(this, this.hasPose(EntityPose.EMERGING) ? 1 : 0); + } + + @Override + public void recreateFromPacket(ClientboundAddEntityPacket packet) { + super.recreateFromPacket(packet); + if (packet.getData() == 1) { +- this.setPose(Pose.EMERGING); ++ this.setPose(EntityPose.EMERGING); + } ++ + } + + @Override +@@ -151,11 +151,11 @@ + + @Override + public boolean isInvulnerableTo(DamageSource source) { +- return this.isDiggingOrEmerging() && !source.is(DamageTypeTags.BYPASSES_INVULNERABILITY) || super.isInvulnerableTo(source); ++ return this.isDiggingOrEmerging() && !source.is(DamageTypeTags.BYPASSES_INVULNERABILITY) ? true : super.isInvulnerableTo(source); + } + + boolean isDiggingOrEmerging() { +- return this.hasPose(Pose.DIGGING) || this.hasPose(Pose.EMERGING); ++ return this.hasPose(EntityPose.DIGGING) || this.hasPose(EntityPose.EMERGING); + } + + @Override +@@ -174,12 +174,7 @@ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes() +- .add(Attributes.MAX_HEALTH, 500.0) +- .add(Attributes.MOVEMENT_SPEED, 0.3F) +- .add(Attributes.KNOCKBACK_RESISTANCE, 1.0) +- .add(Attributes.ATTACK_KNOCKBACK, 1.5) +- .add(Attributes.ATTACK_DAMAGE, 30.0); ++ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 500.0D).add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D).add(Attributes.KNOCKBACK_RESISTANCE, 1.0D).add(Attributes.ATTACK_KNOCKBACK, 1.5D).add(Attributes.ATTACK_DAMAGE, 30.0D); + } + + @Override +@@ -195,7 +190,7 @@ + @Nullable + @Override + protected SoundEvent getAmbientSound() { +- return !this.hasPose(Pose.ROARING) && !this.isDiggingOrEmerging() ? this.getAngerLevel().getAmbientSound() : null; ++ return !this.hasPose(EntityPose.ROARING) && !this.isDiggingOrEmerging() ? this.getAngerLevel().getAmbientSound() : null; + } + + @Override +@@ -209,36 +204,40 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState state) { ++ protected void playStepSound(BlockPos pos, IBlockData state) { + this.playSound(SoundEvents.WARDEN_STEP, 10.0F, 1.0F); + } + + @Override +- public boolean doHurtTarget(Entity entity) { +- this.level().broadcastEntityEvent(this, (byte)4); ++ public boolean doHurtTarget(Entity target) { ++ this.level().broadcastEntityEvent(this, (byte) 4); + this.playSound(SoundEvents.WARDEN_ATTACK_IMPACT, 10.0F, this.getVoicePitch()); + SonicBoom.setCooldown(this, 40); +- return super.doHurtTarget(entity); ++ return super.doHurtTarget(target); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(CLIENT_ANGER_LEVEL, 0); ++ this.entityData.define(Warden.CLIENT_ANGER_LEVEL, 0); + } + + public int getClientAngerLevel() { +- return this.entityData.get(CLIENT_ANGER_LEVEL); ++ return (Integer) this.entityData.get(Warden.CLIENT_ANGER_LEVEL); + } + + private void syncClientAngerLevel() { +- this.entityData.set(CLIENT_ANGER_LEVEL, this.getActiveAnger()); ++ this.entityData.set(Warden.CLIENT_ANGER_LEVEL, this.getActiveAnger()); + } + + @Override + public void tick() { +- if (this.level() instanceof ServerLevel serverLevel) { +- VibrationSystem.Ticker.tick(serverLevel, this.vibrationData, this.vibrationUser); ++ Level world = this.level(); ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ ++ VibrationSystem.Ticker.tick(worldserver, this.vibrationData, this.vibrationUser); + if (this.isPersistenceRequired() || this.requiresCustomPersistence()) { + WardenAi.setDigCooldown(this); + } +@@ -249,21 +248,18 @@ + if (this.tickCount % this.getHeartBeatDelay() == 0) { + this.heartAnimation = 10; + if (!this.isSilent()) { +- this.level() +- .playLocalSound( +- this.getX(), this.getY(), this.getZ(), SoundEvents.WARDEN_HEARTBEAT, this.getSoundSource(), 5.0F, this.getVoicePitch(), false +- ); ++ this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.WARDEN_HEARTBEAT, this.getSoundSource(), 5.0F, this.getVoicePitch(), false); + } + } + + this.tendrilAnimationO = this.tendrilAnimation; + if (this.tendrilAnimation > 0) { +- this.tendrilAnimation--; ++ --this.tendrilAnimation; + } + + this.heartAnimationO = this.heartAnimation; + if (this.heartAnimation > 0) { +- this.heartAnimation--; ++ --this.heartAnimation; + } + + switch (this.getPose()) { +@@ -274,21 +270,23 @@ + this.clientDiggingParticles(this.diggingAnimationState); + } + } ++ + } + + @Override + protected void customServerAiStep() { +- ServerLevel serverLevel = (ServerLevel)this.level(); +- serverLevel.getProfiler().push("wardenBrain"); +- this.getBrain().tick(serverLevel, this); ++ ServerLevel worldserver = (ServerLevel) this.level(); ++ ++ worldserver.getProfiler().push("wardenBrain"); ++ this.getBrain().tick(worldserver, this); + this.level().getProfiler().pop(); + super.customServerAiStep(); + if ((this.tickCount + this.getId()) % 120 == 0) { +- applyDarknessAround(serverLevel, this.position(), this, 20); ++ applyDarknessAround(worldserver, this.position(), this, 20); + } + + if (this.tickCount % 20 == 0) { +- this.angerManagement.tick(serverLevel, this::canTargetEntity); ++ this.angerManagement.tick(worldserver, this::canTargetEntity); + this.syncClientAngerLevel(); + } + +@@ -307,39 +305,44 @@ + } else { + super.handleEntityEvent(id); + } ++ + } + + private int getHeartBeatDelay() { +- float f = (float)this.getClientAngerLevel() / (float)AngerLevel.ANGRY.getMinimumAnger(); ++ float f = (float) this.getClientAngerLevel() / (float) AngerLevel.ANGRY.getMinimumAnger(); ++ + return 40 - Mth.floor(Mth.clamp(f, 0.0F, 1.0F) * 30.0F); + } + + public float getTendrilAnimation(float partialTick) { +- return Mth.lerp(partialTick, (float)this.tendrilAnimationO, (float)this.tendrilAnimation) / 10.0F; ++ return Mth.lerp(partialTick, (float) this.tendrilAnimationO, (float) this.tendrilAnimation) / 10.0F; + } + + public float getHeartAnimation(float partialTick) { +- return Mth.lerp(partialTick, (float)this.heartAnimationO, (float)this.heartAnimation) / 10.0F; ++ return Mth.lerp(partialTick, (float) this.heartAnimationO, (float) this.heartAnimation) / 10.0F; + } + + private void clientDiggingParticles(AnimationState animationState) { +- if ((float)animationState.getAccumulatedTime() < 4500.0F) { +- RandomSource random = this.getRandom(); +- BlockState blockStateOn = this.getBlockStateOn(); +- if (blockStateOn.getRenderShape() != RenderShape.INVISIBLE) { +- for (int i = 0; i < 30; i++) { +- double d = this.getX() + (double)Mth.randomBetween(random, -0.7F, 0.7F); +- double y = this.getY(); +- double d1 = this.getZ() + (double)Mth.randomBetween(random, -0.7F, 0.7F); +- this.level().addParticle(new BlockParticleOption(ParticleTypes.BLOCK, blockStateOn), d, y, d1, 0.0, 0.0, 0.0); ++ if ((float) animationState.getAccumulatedTime() < 4500.0F) { ++ RandomSource randomsource = this.getRandom(); ++ IBlockData iblockdata = this.getBlockStateOn(); ++ ++ if (iblockdata.getRenderShape() != EnumRenderType.INVISIBLE) { ++ for (int i = 0; i < 30; ++i) { ++ double d0 = this.getX() + (double) Mth.randomBetween(randomsource, -0.7F, 0.7F); ++ double d1 = this.getY(); ++ double d2 = this.getZ() + (double) Mth.randomBetween(randomsource, -0.7F, 0.7F); ++ ++ this.level().addParticle(new BlockParticleOption(ParticleTypes.BLOCK, iblockdata), d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + } + } ++ + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { +- if (DATA_POSE.equals(key)) { ++ if (Warden.DATA_POSE.equals(key)) { + switch (this.getPose()) { + case EMERGING: + this.emergeAnimationState.start(this.tickCount); +@@ -370,7 +373,7 @@ + + @Override + public Brain getBrain() { +- return (Brain)super.getBrain(); ++ return (Brain) super.getBrain(); // CraftBukkit - decompile error + } + + @Override +@@ -381,69 +384,89 @@ + + @Override + public void updateDynamicGameEventListener(BiConsumer, ServerLevel> listenerConsumer) { +- if (this.level() instanceof ServerLevel serverLevel) { +- listenerConsumer.accept(this.dynamicGameEventListener, serverLevel); ++ Level world = this.level(); ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ ++ listenerConsumer.accept(this.dynamicGameEventListener, worldserver); + } ++ + } + + @Contract("null->false") + public boolean canTargetEntity(@Nullable Entity entity) { +- if (entity instanceof LivingEntity livingEntity +- && this.level() == entity.level() +- && EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(entity) +- && !this.isAlliedTo(entity) +- && livingEntity.getType() != EntityType.ARMOR_STAND +- && livingEntity.getType() != EntityType.WARDEN +- && !livingEntity.isInvulnerable() +- && !livingEntity.isDeadOrDying() +- && this.level().getWorldBorder().isWithinBounds(livingEntity.getBoundingBox())) { +- return true; ++ boolean flag; ++ ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ if (this.level() == entity.level() && EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(entity) && !this.isAlliedTo(entity) && entityliving.getType() != EntityType.ARMOR_STAND && entityliving.getType() != EntityType.WARDEN && !entityliving.isInvulnerable() && !entityliving.isDeadOrDying() && this.level().getWorldBorder().isWithinBounds(entityliving.getBoundingBox())) { ++ flag = true; ++ return flag; ++ } + } + +- return false; ++ flag = false; ++ return flag; + } + + public static void applyDarknessAround(ServerLevel level, Vec3 pos, @Nullable Entity source, int radius) { +- MobEffectInstance mobEffectInstance = new MobEffectInstance(MobEffects.DARKNESS, 260, 0, false, false); +- MobEffectUtil.addEffectToPlayersAround(level, source, pos, (double)radius, mobEffectInstance, 200); ++ MobEffectInstance mobeffect = new MobEffectInstance(MobEffects.DARKNESS, 260, 0, false, false); ++ ++ MobEffectUtil.addEffectToPlayersAround(level, source, pos, radius, mobeffect, 200, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.WARDEN); // CraftBukkit - Add EntityPotionEffectEvent.Cause + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- AngerManagement.codec(this::canTargetEntity) +- .encodeStart(NbtOps.INSTANCE, this.angerManagement) +- .resultOrPartial(LOGGER::error) +- .ifPresent(tag -> compound.put("anger", tag)); +- VibrationSystem.Data.CODEC +- .encodeStart(NbtOps.INSTANCE, this.vibrationData) +- .resultOrPartial(LOGGER::error) +- .ifPresent(tag -> compound.put("listener", tag)); ++ DataResult dataresult = AngerManagement.codec(this::canTargetEntity).encodeStart(NbtOps.INSTANCE, this.angerManagement); // CraftBukkit - decompile error ++ Logger logger = Warden.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("anger", nbtbase); ++ }); ++ dataresult = VibrationSystem.Data.CODEC.encodeStart(NbtOps.INSTANCE, this.vibrationData); ++ logger = Warden.LOGGER; ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("listener", nbtbase); ++ }); + } + + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); ++ DataResult dataresult; ++ Logger logger; ++ + if (compound.contains("anger")) { +- AngerManagement.codec(this::canTargetEntity) +- .parse(new Dynamic<>(NbtOps.INSTANCE, compound.get("anger"))) +- .resultOrPartial(LOGGER::error) +- .ifPresent(angerManagement -> this.angerManagement = angerManagement); ++ dataresult = AngerManagement.codec(this::canTargetEntity).parse(new Dynamic(NbtOps.INSTANCE, compound.get("anger"))); ++ logger = Warden.LOGGER; ++ Objects.requireNonNull(logger); ++ ((DataResult) dataresult).resultOrPartial(logger::error).ifPresent((angermanagement) -> { // CraftBukkit - decompile error ++ this.angerManagement = angermanagement; ++ }); + this.syncClientAngerLevel(); + } + + if (compound.contains("listener", 10)) { +- VibrationSystem.Data.CODEC +- .parse(new Dynamic<>(NbtOps.INSTANCE, compound.getCompound("listener"))) +- .resultOrPartial(LOGGER::error) +- .ifPresent(vibrationData -> this.vibrationData = vibrationData); ++ dataresult = VibrationSystem.Data.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compound.getCompound("listener"))); ++ logger = Warden.LOGGER; ++ Objects.requireNonNull(logger); ++ ((DataResult) dataresult).resultOrPartial(logger::error).ifPresent((vibrationsystem_a) -> { // CraftBukkit - decompile error ++ this.vibrationData = vibrationsystem_a; ++ }); + } ++ + } + + private void playListeningSound() { +- if (!this.hasPose(Pose.ROARING)) { ++ if (!this.hasPose(EntityPose.ROARING)) { + this.playSound(this.getAngerLevel().getListeningSound(), 10.0F, this.getVoicePitch()); + } ++ + } + + public AngerLevel getAngerLevel() { +@@ -466,9 +489,10 @@ + public void increaseAngerAt(@Nullable Entity entity, int offset, boolean playListeningSound) { + if (!this.isNoAi() && this.canTargetEntity(entity)) { + WardenAi.setDigCooldown(this); +- boolean flag = !(this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null) instanceof Player); +- int i = this.angerManagement.increaseAnger(entity, offset); +- if (entity instanceof Player && flag && AngerLevel.byAnger(i).isAngry()) { ++ boolean flag1 = !(this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null) instanceof Player); // CraftBukkit - decompile error ++ int j = this.angerManagement.increaseAnger(entity, offset); ++ ++ if (entity instanceof Player && flag1 && AngerLevel.byAnger(j).isAngry()) { + this.getBrain().eraseMemory(MemoryModuleType.ATTACK_TARGET); + } + +@@ -476,6 +500,7 @@ + this.playListeningSound(); + } + } ++ + } + + public Optional getEntityAngryAt() { +@@ -485,7 +510,7 @@ + @Nullable + @Override + public LivingEntity getTarget() { +- return this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); ++ return (LivingEntity) this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); // CraftBukkit - decompile error + } + + @Override +@@ -495,13 +520,11 @@ + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + this.getBrain().setMemoryWithExpiry(MemoryModuleType.DIG_COOLDOWN, Unit.INSTANCE, 1200L); +- if (reason == MobSpawnType.TRIGGERED) { +- this.setPose(Pose.EMERGING); +- this.getBrain().setMemoryWithExpiry(MemoryModuleType.IS_EMERGING, Unit.INSTANCE, (long)WardenAi.EMERGE_DURATION); ++ if (reason == EnumMobSpawn.TRIGGERED) { ++ this.setPose(EntityPose.EMERGING); ++ this.getBrain().setMemoryWithExpiry(MemoryModuleType.IS_EMERGING, Unit.INSTANCE, (long) WardenAi.EMERGE_DURATION); + this.playSound(SoundEvents.WARDEN_AGITATED, 5.0F, 1.0F); + } + +@@ -511,13 +534,17 @@ + @Override + public boolean hurt(DamageSource source, float amount) { + boolean flag = super.hurt(source, amount); ++ + if (!this.level().isClientSide && !this.isNoAi() && !this.isDiggingOrEmerging()) { + Entity entity = source.getEntity(); ++ + this.increaseAngerAt(entity, AngerLevel.ANGRY.getMinimumAnger() + 20, false); +- if (this.brain.getMemory(MemoryModuleType.ATTACK_TARGET).isEmpty() +- && entity instanceof LivingEntity livingEntity +- && (!source.isIndirect() || this.closerThan(livingEntity, 5.0))) { +- this.setAttackTarget(livingEntity); ++ if (this.brain.getMemory(MemoryModuleType.ATTACK_TARGET).isEmpty() && entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ if (!source.isIndirect() || this.closerThan(entityliving, 5.0D)) { ++ this.setAttackTarget(entityliving); ++ } + } + } + +@@ -526,15 +553,16 @@ + + public void setAttackTarget(LivingEntity attackTarget) { + this.getBrain().eraseMemory(MemoryModuleType.ROAR_TARGET); +- this.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, attackTarget); ++ this.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, attackTarget); // CraftBukkit - decompile error + this.getBrain().eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE); + SonicBoom.setCooldown(this, 200); + } + + @Override +- public EntityDimensions getDimensions(Pose pose) { +- EntityDimensions entityDimensions = super.getDimensions(pose); +- return this.isDiggingOrEmerging() ? EntityDimensions.fixed(entityDimensions.width, 1.0F) : entityDimensions; ++ public EntityDimensions getDimensions(EntityPose pose) { ++ EntityDimensions entitysize = super.getDimensions(pose); ++ ++ return this.isDiggingOrEmerging() ? EntityDimensions.fixed(entitysize.width, 1.0F) : entitysize; + } + + @Override +@@ -576,8 +604,8 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.25F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.25F * f, 0.0F); + } + + @Override +@@ -590,10 +618,13 @@ + return this.vibrationUser; + } + +- class VibrationUser implements VibrationSystem.User { ++ private class a implements VibrationSystem.User { ++ + private static final int GAME_EVENT_LISTENER_RANGE = 16; + private final PositionSource positionSource = new EntityPositionSource(Warden.this, Warden.this.getEyeHeight()); + ++ a() {} ++ + @Override + public int getListenerRadius() { + return 16; +@@ -616,35 +647,39 @@ + + @Override + public boolean canReceiveVibration(ServerLevel level, BlockPos pos, GameEvent gameEvent, GameEvent.Context context) { +- if (!Warden.this.isNoAi() +- && !Warden.this.isDeadOrDying() +- && !Warden.this.getBrain().hasMemoryValue(MemoryModuleType.VIBRATION_COOLDOWN) +- && !Warden.this.isDiggingOrEmerging() +- && level.getWorldBorder().isWithinBounds(pos)) { +- if (context.sourceEntity() instanceof LivingEntity livingEntity && !Warden.this.canTargetEntity(livingEntity)) { +- return false; ++ if (!Warden.this.isNoAi() && !Warden.this.isDeadOrDying() && !Warden.this.getBrain().hasMemoryValue(MemoryModuleType.VIBRATION_COOLDOWN) && !Warden.this.isDiggingOrEmerging() && level.getWorldBorder().isWithinBounds(pos)) { ++ Entity entity = context.sourceEntity(); ++ boolean flag; ++ ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ if (!Warden.this.canTargetEntity(entityliving)) { ++ flag = false; ++ return flag; ++ } + } + +- return true; ++ flag = true; ++ return flag; + } else { + return false; + } + } + + @Override +- public void onReceiveVibration( +- ServerLevel level, BlockPos pos, GameEvent gameEvent, @Nullable Entity entity, @Nullable Entity playerEntity, float distance +- ) { ++ public void onReceiveVibration(ServerLevel level, BlockPos pos, GameEvent gameEvent, @Nullable Entity entity, @Nullable Entity playerEntity, float distance) { + if (!Warden.this.isDeadOrDying()) { + Warden.this.brain.setMemoryWithExpiry(MemoryModuleType.VIBRATION_COOLDOWN, Unit.INSTANCE, 40L); +- level.broadcastEntityEvent(Warden.this, (byte)61); ++ level.broadcastEntityEvent(Warden.this, (byte) 61); + Warden.this.playSound(SoundEvents.WARDEN_TENDRIL_CLICKS, 5.0F, Warden.this.getVoicePitch()); +- BlockPos blockPos = pos; ++ BlockPos blockposition1 = pos; ++ + if (playerEntity != null) { +- if (Warden.this.closerThan(playerEntity, 30.0)) { ++ if (Warden.this.closerThan(playerEntity, 30.0D)) { + if (Warden.this.getBrain().hasMemoryValue(MemoryModuleType.RECENT_PROJECTILE)) { + if (Warden.this.canTargetEntity(playerEntity)) { +- blockPos = playerEntity.blockPosition(); ++ blockposition1 = playerEntity.blockPosition(); + } + + Warden.this.increaseAngerAt(playerEntity); +@@ -659,11 +694,13 @@ + } + + if (!Warden.this.getAngerLevel().isAngry()) { +- Optional activeEntity = Warden.this.angerManagement.getActiveEntity(); +- if (playerEntity != null || activeEntity.isEmpty() || activeEntity.get() == entity) { +- WardenAi.setDisturbanceLocation(Warden.this, blockPos); ++ Optional optional = Warden.this.angerManagement.getActiveEntity(); ++ ++ if (playerEntity != null || optional.isEmpty() || optional.get() == entity) { ++ WardenAi.setDisturbanceLocation(Warden.this, blockposition1); + } + } ++ + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/npc/AbstractVillager.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/npc/AbstractVillager.java.patch new file mode 100644 index 0000000000..80869a4e93 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/npc/AbstractVillager.java.patch @@ -0,0 +1,228 @@ +--- a/net/minecraft/world/entity/npc/AbstractVillager.java ++++ b/net/minecraft/world/entity/npc/AbstractVillager.java +@@ -20,11 +20,11 @@ + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.SlotAccess; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.trading.Merchant; +@@ -34,8 +34,23 @@ + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.inventory.CraftMerchant; ++import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; ++import org.bukkit.event.entity.VillagerAcquireTradeEvent; ++// CraftBukkit end + +-public abstract class AbstractVillager extends AgeableMob implements InventoryCarrier, Npc, Merchant { ++public abstract class AbstractVillager extends AgeableMob implements InventoryCarrier, NPC, Merchant { ++ ++ // CraftBukkit start ++ private CraftMerchant craftMerchant; ++ ++ @Override ++ public CraftMerchant getCraftMerchant() { ++ return (craftMerchant == null) ? craftMerchant = new CraftMerchant(this) : craftMerchant; ++ } ++ // CraftBukkit end + private static final EntityDataAccessor DATA_UNHAPPY_COUNTER = SynchedEntityData.defineId(AbstractVillager.class, EntityDataSerializers.INT); + public static final int VILLAGER_SLOT_OFFSET = 300; + private static final int VILLAGER_INVENTORY_SIZE = 8; +@@ -43,7 +58,7 @@ + private Player tradingPlayer; + @Nullable + protected MerchantOffers offers; +- private final SimpleContainer inventory = new SimpleContainer(8); ++ private final SimpleContainer inventory = new SimpleContainer(8, (org.bukkit.craftbukkit.entity.CraftAbstractVillager) this.getBukkitEntity()); // CraftBukkit add argument + + public AbstractVillager(EntityType entityType, Level level) { + super(entityType, level); +@@ -52,22 +67,20 @@ + } + + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + if (spawnData == null) { + spawnData = new AgeableMob.AgeableMobGroupData(false); + } + +- return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + + public int getUnhappyCounter() { +- return this.entityData.get(DATA_UNHAPPY_COUNTER); ++ return (Integer) this.entityData.get(AbstractVillager.DATA_UNHAPPY_COUNTER); + } + + public void setUnhappyCounter(int unhappyCounter) { +- this.entityData.set(DATA_UNHAPPY_COUNTER, unhappyCounter); ++ this.entityData.set(AbstractVillager.DATA_UNHAPPY_COUNTER, unhappyCounter); + } + + @Override +@@ -76,14 +89,14 @@ + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return this.isBaby() ? 0.81F : 1.62F; + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_UNHAPPY_COUNTER, 0); ++ this.entityData.define(AbstractVillager.DATA_UNHAPPY_COUNTER, 0); + } + + @Override +@@ -112,12 +125,10 @@ + } + + @Override +- public void overrideOffers(@Nullable MerchantOffers offers) { +- } ++ public void overrideOffers(@Nullable MerchantOffers offers) {} + + @Override +- public void overrideXp(int xp) { +- } ++ public void overrideXp(int xp) {} + + @Override + public void notifyTrade(MerchantOffer offer) { +@@ -125,8 +136,9 @@ + this.ambientSoundTime = -this.getAmbientSoundInterval(); + this.rewardTradeXp(offer); + if (this.tradingPlayer instanceof ServerPlayer) { +- CriteriaTriggers.TRADE.trigger((ServerPlayer)this.tradingPlayer, this, offer.getResult()); ++ CriteriaTriggers.TRADE.trigger((ServerPlayer) this.tradingPlayer, this, offer.getResult()); + } ++ + } + + protected abstract void rewardTradeXp(MerchantOffer offer); +@@ -142,6 +154,7 @@ + this.ambientSoundTime = -this.getAmbientSoundInterval(); + this.playSound(this.getTradeUpdatedSound(!stack.isEmpty()), this.getSoundVolume(), this.getVoicePitch()); + } ++ + } + + @Override +@@ -160,9 +173,10 @@ + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- MerchantOffers offers = this.getOffers(); +- if (!offers.isEmpty()) { +- compound.put("Offers", offers.createTag()); ++ MerchantOffers merchantrecipelist = this.getOffers(); ++ ++ if (!merchantrecipelist.isEmpty()) { ++ compound.put("Offers", merchantrecipelist.createTag()); + } + + this.writeInventoryToTag(compound); +@@ -186,7 +200,7 @@ + } + + protected void stopTrading() { +- this.setTradingPlayer(null); ++ this.setTradingPlayer((Player) null); + } + + @Override +@@ -196,12 +210,14 @@ + } + + protected void addParticlesAroundSelf(ParticleOptions particleOption) { +- for (int i = 0; i < 5; i++) { +- double d = this.random.nextGaussian() * 0.02; +- double d1 = this.random.nextGaussian() * 0.02; +- double d2 = this.random.nextGaussian() * 0.02; +- this.level().addParticle(particleOption, this.getRandomX(1.0), this.getRandomY() + 1.0, this.getRandomZ(1.0), d, d1, d2); ++ for (int i = 0; i < 5; ++i) { ++ double d0 = this.random.nextGaussian() * 0.02D; ++ double d1 = this.random.nextGaussian() * 0.02D; ++ double d2 = this.random.nextGaussian() * 0.02D; ++ ++ this.level().addParticle(particleOption, this.getRandomX(1.0D), this.getRandomY() + 1.0D, this.getRandomZ(1.0D), d0, d1, d2); + } ++ + } + + @Override +@@ -216,30 +232,43 @@ + + @Override + public SlotAccess getSlot(int slot) { +- int i = slot - 300; +- return i >= 0 && i < this.inventory.getContainerSize() ? SlotAccess.forContainer(this.inventory, i) : super.getSlot(slot); ++ int j = slot - 300; ++ ++ return j >= 0 && j < this.inventory.getContainerSize() ? SlotAccess.forContainer(this.inventory, j) : super.getSlot(slot); + } + + protected abstract void updateTrades(); + + protected void addOffersFromItemListings(MerchantOffers givenMerchantOffers, VillagerTrades.ItemListing[] newTrades, int maxNumbers) { +- ArrayList list = Lists.newArrayList(newTrades); +- int i = 0; ++ ArrayList arraylist = Lists.newArrayList(newTrades); ++ int j = 0; + +- while (i < maxNumbers && !list.isEmpty()) { +- MerchantOffer offer = list.remove(this.random.nextInt(list.size())).getOffer(this, this.random); +- if (offer != null) { +- givenMerchantOffers.add(offer); +- i++; ++ while (j < maxNumbers && !arraylist.isEmpty()) { ++ MerchantOffer merchantrecipe = ((VillagerTrades.ItemListing) arraylist.remove(this.random.nextInt(arraylist.size()))).getOffer(this, this.random); ++ ++ if (merchantrecipe != null) { ++ // CraftBukkit start ++ VillagerAcquireTradeEvent event = new VillagerAcquireTradeEvent((org.bukkit.entity.AbstractVillager) getBukkitEntity(), merchantrecipe.asBukkit()); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ if (!event.isCancelled()) { ++ givenMerchantOffers.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); ++ } ++ // CraftBukkit end ++ ++j; + } + } ++ + } + + @Override + public Vec3 getRopeHoldPosition(float partialTicks) { +- float f = Mth.lerp(partialTicks, this.yBodyRotO, this.yBodyRot) * (float) (Math.PI / 180.0); +- Vec3 vec3 = new Vec3(0.0, this.getBoundingBox().getYsize() - 1.0, 0.2); +- return this.getPosition(partialTicks).add(vec3.yRot(-f)); ++ float f1 = Mth.lerp(partialTicks, this.yBodyRotO, this.yBodyRot) * 0.017453292F; ++ Vec3 vec3d = new Vec3(0.0D, this.getBoundingBox().getYsize() - 1.0D, 0.2D); ++ ++ return this.getPosition(partialTicks).add(vec3d.yRot(-f1)); + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/npc/InventoryCarrier.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/npc/InventoryCarrier.java.patch new file mode 100644 index 0000000000..c0d5156310 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/npc/InventoryCarrier.java.patch @@ -0,0 +1,61 @@ +--- a/net/minecraft/world/entity/npc/InventoryCarrier.java ++++ b/net/minecraft/world/entity/npc/InventoryCarrier.java +@@ -7,35 +7,48 @@ + import net.minecraft.world.item.ItemStack; + + public interface InventoryCarrier { ++ + String TAG_INVENTORY = "Inventory"; + + SimpleContainer getInventory(); + + static void pickUpItem(Mob mob, InventoryCarrier carrier, ItemEntity itemEntity) { +- ItemStack item = itemEntity.getItem(); +- if (mob.wantsToPickUp(item)) { +- SimpleContainer inventory = carrier.getInventory(); +- boolean canAddItem = inventory.canAddItem(item); +- if (!canAddItem) { ++ ItemStack itemstack = itemEntity.getItem(); ++ ++ if (mob.wantsToPickUp(itemstack)) { ++ SimpleContainer inventorysubcontainer = carrier.getInventory(); ++ boolean flag = inventorysubcontainer.canAddItem(itemstack); ++ ++ if (!flag) { + return; + } + ++ // CraftBukkit start ++ ItemStack remaining = new SimpleContainer(inventorysubcontainer).addItem(itemstack); ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(mob, itemEntity, remaining.getCount(), false).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ + mob.onItemPickup(itemEntity); +- int count = item.getCount(); +- ItemStack itemStack = inventory.addItem(item); +- mob.take(itemEntity, count - itemStack.getCount()); +- if (itemStack.isEmpty()) { ++ int i = itemstack.getCount(); ++ ItemStack itemstack1 = inventorysubcontainer.addItem(itemstack); ++ ++ mob.take(itemEntity, i - itemstack1.getCount()); ++ if (itemstack1.isEmpty()) { + itemEntity.discard(); + } else { +- item.setCount(itemStack.getCount()); ++ itemstack.setCount(itemstack1.getCount()); + } + } ++ + } + + default void readInventoryFromTag(CompoundTag tag) { + if (tag.contains("Inventory", 9)) { + this.getInventory().fromTag(tag.getList("Inventory", 10)); + } ++ + } + + default void writeInventoryToTag(CompoundTag tag) { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/npc/Villager.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/npc/Villager.java.patch new file mode 100644 index 0000000000..f8f81ca094 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/npc/Villager.java.patch @@ -0,0 +1,1148 @@ +--- a/net/minecraft/world/entity/npc/Villager.java ++++ b/net/minecraft/world/entity/npc/Villager.java +@@ -9,11 +9,12 @@ + import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; + import it.unimi.dsi.fastutil.ints.Int2ObjectMap; ++import java.util.Iterator; + import java.util.List; + import java.util.Map; ++import java.util.Objects; + import java.util.Optional; + import java.util.Set; +-import java.util.Map.Entry; + import java.util.function.BiPredicate; + import java.util.stream.Collectors; + import javax.annotation.Nullable; +@@ -41,7 +42,7 @@ + import net.minecraft.util.SpawnUtil; + import net.minecraft.world.Difficulty; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.damagesource.DamageSource; +@@ -50,13 +51,13 @@ + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.ExperienceOrb; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LightningBolt; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.ReputationEventHandler; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -91,23 +92,21 @@ + import net.minecraft.world.phys.AABB; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTransformEvent; ++import org.bukkit.event.entity.VillagerReplenishTradeEvent; ++// CraftBukkit end ++ + public class Villager extends AbstractVillager implements ReputationEventHandler, VillagerDataHolder { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final EntityDataAccessor DATA_VILLAGER_DATA = SynchedEntityData.defineId(Villager.class, EntityDataSerializers.VILLAGER_DATA); + public static final int BREEDING_FOOD_THRESHOLD = 12; + public static final Map FOOD_POINTS = ImmutableMap.of(Items.BREAD, 4, Items.POTATO, 1, Items.CARROT, 1, Items.BEETROOT, 1); + private static final int TRADES_PER_LEVEL = 2; +- private static final Set WANTED_ITEMS = ImmutableSet.of( +- Items.BREAD, +- Items.POTATO, +- Items.CARROT, +- Items.WHEAT, +- Items.WHEAT_SEEDS, +- Items.BEETROOT, +- Items.BEETROOT_SEEDS, +- Items.TORCHFLOWER_SEEDS, +- Items.PITCHER_POD +- ); ++ private static final Set WANTED_ITEMS = ImmutableSet.of(Items.BREAD, Items.POTATO, Items.CARROT, Items.WHEAT, Items.WHEAT_SEEDS, Items.BEETROOT, new Item[]{Items.BEETROOT_SEEDS, Items.TORCHFLOWER_SEEDS, Items.PITCHER_POD}); + private static final int MAX_GOSSIP_TOPICS = 10; + private static final int GOSSIP_COOLDOWN = 1200; + private static final int GOSSIP_DECAY_INTERVAL = 24000; +@@ -123,7 +122,7 @@ + private Player lastTradedPlayer; + private boolean chasing; + private int foodLevel; +- private final GossipContainer gossips = new GossipContainer(); ++ private final GossipContainer gossips; + private long lastGossipTime; + private long lastGossipDecayTime; + private int villagerXp; +@@ -131,59 +130,17 @@ + private int numberOfRestocksToday; + private long lastRestockCheckDayTime; + private boolean assignProfessionWhenSpawned; +- private static final ImmutableList> MEMORY_TYPES = ImmutableList.of( +- MemoryModuleType.HOME, +- MemoryModuleType.JOB_SITE, +- MemoryModuleType.POTENTIAL_JOB_SITE, +- MemoryModuleType.MEETING_POINT, +- MemoryModuleType.NEAREST_LIVING_ENTITIES, +- MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, +- MemoryModuleType.VISIBLE_VILLAGER_BABIES, +- MemoryModuleType.NEAREST_PLAYERS, +- MemoryModuleType.NEAREST_VISIBLE_PLAYER, +- MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, +- MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, +- MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS, +- MemoryModuleType.WALK_TARGET, +- MemoryModuleType.LOOK_TARGET, +- MemoryModuleType.INTERACTION_TARGET, +- MemoryModuleType.BREED_TARGET, +- MemoryModuleType.PATH, +- MemoryModuleType.DOORS_TO_CLOSE, +- MemoryModuleType.NEAREST_BED, +- MemoryModuleType.HURT_BY, +- MemoryModuleType.HURT_BY_ENTITY, +- MemoryModuleType.NEAREST_HOSTILE, +- MemoryModuleType.SECONDARY_JOB_SITE, +- MemoryModuleType.HIDING_PLACE, +- MemoryModuleType.HEARD_BELL_TIME, +- MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, +- MemoryModuleType.LAST_SLEPT, +- MemoryModuleType.LAST_WOKEN, +- MemoryModuleType.LAST_WORKED_AT_POI, +- MemoryModuleType.GOLEM_DETECTED_RECENTLY +- ); +- private static final ImmutableList>> SENSOR_TYPES = ImmutableList.of( +- SensorType.NEAREST_LIVING_ENTITIES, +- SensorType.NEAREST_PLAYERS, +- SensorType.NEAREST_ITEMS, +- SensorType.NEAREST_BED, +- SensorType.HURT_BY, +- SensorType.VILLAGER_HOSTILES, +- SensorType.VILLAGER_BABIES, +- SensorType.SECONDARY_POIS, +- SensorType.GOLEM_DETECTED +- ); +- public static final Map, BiPredicate>> POI_MEMORIES = ImmutableMap.of( +- MemoryModuleType.HOME, +- (villager, holder) -> holder.is(PoiTypes.HOME), +- MemoryModuleType.JOB_SITE, +- (villager, holder) -> villager.getVillagerData().getProfession().heldJobSite().test(holder), +- MemoryModuleType.POTENTIAL_JOB_SITE, +- (villager, holder) -> VillagerProfession.ALL_ACQUIRABLE_JOBS.test(holder), +- MemoryModuleType.MEETING_POINT, +- (villager, holder) -> holder.is(PoiTypes.MEETING) +- ); ++ private static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.HOME, MemoryModuleType.JOB_SITE, MemoryModuleType.POTENTIAL_JOB_SITE, MemoryModuleType.MEETING_POINT, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.VISIBLE_VILLAGER_BABIES, MemoryModuleType.NEAREST_PLAYERS, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS, new MemoryModuleType[]{MemoryModuleType.WALK_TARGET, MemoryModuleType.LOOK_TARGET, MemoryModuleType.INTERACTION_TARGET, MemoryModuleType.BREED_TARGET, MemoryModuleType.PATH, MemoryModuleType.DOORS_TO_CLOSE, MemoryModuleType.NEAREST_BED, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.NEAREST_HOSTILE, MemoryModuleType.SECONDARY_JOB_SITE, MemoryModuleType.HIDING_PLACE, MemoryModuleType.HEARD_BELL_TIME, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.LAST_SLEPT, MemoryModuleType.LAST_WOKEN, MemoryModuleType.LAST_WORKED_AT_POI, MemoryModuleType.GOLEM_DETECTED_RECENTLY}); ++ private static final ImmutableList>> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.NEAREST_ITEMS, SensorType.NEAREST_BED, SensorType.HURT_BY, SensorType.VILLAGER_HOSTILES, SensorType.VILLAGER_BABIES, SensorType.SECONDARY_POIS, SensorType.GOLEM_DETECTED); ++ public static final Map, BiPredicate>> POI_MEMORIES = ImmutableMap.of(MemoryModuleType.HOME, (entityvillager, holder) -> { ++ return holder.is(PoiTypes.HOME); ++ }, MemoryModuleType.JOB_SITE, (entityvillager, holder) -> { ++ return entityvillager.getVillagerData().getProfession().heldJobSite().test(holder); ++ }, MemoryModuleType.POTENTIAL_JOB_SITE, (entityvillager, holder) -> { ++ return VillagerProfession.ALL_ACQUIRABLE_JOBS.test(holder); ++ }, MemoryModuleType.MEETING_POINT, (entityvillager, holder) -> { ++ return holder.is(PoiTypes.MEETING); ++ }); + + public Villager(EntityType entityType, Level level) { + this(entityType, level, VillagerType.PLAINS); +@@ -191,7 +148,8 @@ + + public Villager(EntityType entityType, Level level, VillagerType villagerType) { + super(entityType, level); +- ((GroundPathNavigation)this.getNavigation()).setCanOpenDoors(true); ++ this.gossips = new GossipContainer(); ++ ((GroundPathNavigation) this.getNavigation()).setCanOpenDoors(true); + this.getNavigation().setCanFloat(true); + this.setCanPickUpLoot(true); + this.setVillagerData(this.getVillagerData().setType(villagerType).setProfession(VillagerProfession.NONE)); +@@ -199,54 +157,49 @@ + + @Override + public Brain getBrain() { +- return (Brain)super.getBrain(); ++ return (Brain) super.getBrain(); // CraftBukkit - decompile error + } + + @Override + protected Brain.Provider brainProvider() { +- return Brain.provider(MEMORY_TYPES, SENSOR_TYPES); ++ return Brain.provider(Villager.MEMORY_TYPES, Villager.SENSOR_TYPES); + } + + @Override + protected Brain makeBrain(Dynamic dynamic) { +- Brain brain = this.brainProvider().makeBrain(dynamic); +- this.registerBrainGoals(brain); +- return brain; ++ Brain behaviorcontroller = this.brainProvider().makeBrain(dynamic); ++ ++ this.registerBrainGoals(behaviorcontroller); ++ return behaviorcontroller; + } + + public void refreshBrain(ServerLevel serverLevel) { +- Brain brain = this.getBrain(); +- brain.stopAll(serverLevel, this); +- this.brain = brain.copyWithoutBehaviors(); ++ Brain behaviorcontroller = this.getBrain(); ++ ++ behaviorcontroller.stopAll(serverLevel, this); ++ this.brain = behaviorcontroller.copyWithoutBehaviors(); + this.registerBrainGoals(this.getBrain()); + } + + private void registerBrainGoals(Brain villagerBrain) { +- VillagerProfession profession = this.getVillagerData().getProfession(); ++ VillagerProfession villagerprofession = this.getVillagerData().getProfession(); ++ + if (this.isBaby()) { + villagerBrain.setSchedule(Schedule.VILLAGER_BABY); + villagerBrain.addActivity(Activity.PLAY, VillagerGoalPackages.getPlayPackage(0.5F)); + } else { + villagerBrain.setSchedule(Schedule.VILLAGER_DEFAULT); +- villagerBrain.addActivityWithConditions( +- Activity.WORK, +- VillagerGoalPackages.getWorkPackage(profession, 0.5F), +- ImmutableSet.of(Pair.of(MemoryModuleType.JOB_SITE, MemoryStatus.VALUE_PRESENT)) +- ); ++ villagerBrain.addActivityWithConditions(Activity.WORK, VillagerGoalPackages.getWorkPackage(villagerprofession, 0.5F), ImmutableSet.of(Pair.of(MemoryModuleType.JOB_SITE, MemoryStatus.VALUE_PRESENT))); + } + +- villagerBrain.addActivity(Activity.CORE, VillagerGoalPackages.getCorePackage(profession, 0.5F)); +- villagerBrain.addActivityWithConditions( +- Activity.MEET, +- VillagerGoalPackages.getMeetPackage(profession, 0.5F), +- ImmutableSet.of(Pair.of(MemoryModuleType.MEETING_POINT, MemoryStatus.VALUE_PRESENT)) +- ); +- villagerBrain.addActivity(Activity.REST, VillagerGoalPackages.getRestPackage(profession, 0.5F)); +- villagerBrain.addActivity(Activity.IDLE, VillagerGoalPackages.getIdlePackage(profession, 0.5F)); +- villagerBrain.addActivity(Activity.PANIC, VillagerGoalPackages.getPanicPackage(profession, 0.5F)); +- villagerBrain.addActivity(Activity.PRE_RAID, VillagerGoalPackages.getPreRaidPackage(profession, 0.5F)); +- villagerBrain.addActivity(Activity.RAID, VillagerGoalPackages.getRaidPackage(profession, 0.5F)); +- villagerBrain.addActivity(Activity.HIDE, VillagerGoalPackages.getHidePackage(profession, 0.5F)); ++ villagerBrain.addActivity(Activity.CORE, VillagerGoalPackages.getCorePackage(villagerprofession, 0.5F)); ++ villagerBrain.addActivityWithConditions(Activity.MEET, VillagerGoalPackages.getMeetPackage(villagerprofession, 0.5F), ImmutableSet.of(Pair.of(MemoryModuleType.MEETING_POINT, MemoryStatus.VALUE_PRESENT))); ++ villagerBrain.addActivity(Activity.REST, VillagerGoalPackages.getRestPackage(villagerprofession, 0.5F)); ++ villagerBrain.addActivity(Activity.IDLE, VillagerGoalPackages.getIdlePackage(villagerprofession, 0.5F)); ++ villagerBrain.addActivity(Activity.PANIC, VillagerGoalPackages.getPanicPackage(villagerprofession, 0.5F)); ++ villagerBrain.addActivity(Activity.PRE_RAID, VillagerGoalPackages.getPreRaidPackage(villagerprofession, 0.5F)); ++ villagerBrain.addActivity(Activity.RAID, VillagerGoalPackages.getRaidPackage(villagerprofession, 0.5F)); ++ villagerBrain.addActivity(Activity.HIDE, VillagerGoalPackages.getHidePackage(villagerprofession, 0.5F)); + villagerBrain.setCoreActivities(ImmutableSet.of(Activity.CORE)); + villagerBrain.setDefaultActivity(Activity.IDLE); + villagerBrain.setActiveActivityIfPossible(Activity.IDLE); +@@ -257,12 +210,13 @@ + protected void ageBoundaryReached() { + super.ageBoundaryReached(); + if (this.level() instanceof ServerLevel) { +- this.refreshBrain((ServerLevel)this.level()); ++ this.refreshBrain((ServerLevel) this.level()); + } ++ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.5).add(Attributes.FOLLOW_RANGE, 48.0); ++ return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.5D).add(Attributes.FOLLOW_RANGE, 48.0D); + } + + public boolean assignProfessionWhenSpawned() { +@@ -272,34 +226,35 @@ + @Override + protected void customServerAiStep() { + this.level().getProfiler().push("villagerBrain"); +- this.getBrain().tick((ServerLevel)this.level(), this); ++ this.getBrain().tick((ServerLevel) this.level(), this); + this.level().getProfiler().pop(); + if (this.assignProfessionWhenSpawned) { + this.assignProfessionWhenSpawned = false; + } + + if (!this.isTrading() && this.updateMerchantTimer > 0) { +- this.updateMerchantTimer--; ++ --this.updateMerchantTimer; + if (this.updateMerchantTimer <= 0) { + if (this.increaseProfessionLevelOnUpdate) { + this.increaseMerchantCareer(); + this.increaseProfessionLevelOnUpdate = false; + } + +- this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 200, 0)); ++ this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 200, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.VILLAGER_TRADE); // CraftBukkit + } + } + + if (this.lastTradedPlayer != null && this.level() instanceof ServerLevel) { +- ((ServerLevel)this.level()).onReputationEvent(ReputationEventType.TRADE, this.lastTradedPlayer, this); +- this.level().broadcastEntityEvent(this, (byte)14); ++ ((ServerLevel) this.level()).onReputationEvent(ReputationEventType.TRADE, this.lastTradedPlayer, this); ++ this.level().broadcastEntityEvent(this, (byte) 14); + this.lastTradedPlayer = null; + } + + if (!this.isNoAi() && this.random.nextInt(100) == 0) { +- Raid raidAt = ((ServerLevel)this.level()).getRaidAt(this.blockPosition()); +- if (raidAt != null && raidAt.isActive() && !raidAt.isOver()) { +- this.level().broadcastEntityEvent(this, (byte)42); ++ Raid raid = ((ServerLevel) this.level()).getRaidAt(this.blockPosition()); ++ ++ if (raid != null && raid.isActive() && !raid.isOver()) { ++ this.level().broadcastEntityEvent(this, (byte) 42); + } + } + +@@ -321,40 +276,45 @@ + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (itemInHand.is(Items.VILLAGER_SPAWN_EGG) || !this.isAlive() || this.isTrading() || this.isSleeping()) { +- return super.mobInteract(player, hand); +- } else if (this.isBaby()) { +- this.setUnhappy(); +- return InteractionResult.sidedSuccess(this.level().isClientSide); +- } else { +- boolean isEmpty = this.getOffers().isEmpty(); +- if (hand == InteractionHand.MAIN_HAND) { +- if (isEmpty && !this.level().isClientSide) { +- this.setUnhappy(); +- } ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); + +- player.awardStat(Stats.TALKED_TO_VILLAGER); +- } +- +- if (isEmpty) { ++ if (!itemstack.is(Items.VILLAGER_SPAWN_EGG) && this.isAlive() && !this.isTrading() && !this.isSleeping()) { ++ if (this.isBaby()) { ++ this.setUnhappy(); + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { +- if (!this.level().isClientSide && !this.offers.isEmpty()) { +- this.startTrading(player); ++ boolean flag = this.getOffers().isEmpty(); ++ ++ if (hand == EnumHand.MAIN_HAND) { ++ if (flag && !this.level().isClientSide) { ++ this.setUnhappy(); ++ } ++ ++ player.awardStat(Stats.TALKED_TO_VILLAGER); + } + +- return InteractionResult.sidedSuccess(this.level().isClientSide); ++ if (flag) { ++ return InteractionResult.sidedSuccess(this.level().isClientSide); ++ } else { ++ if (!this.level().isClientSide && !this.offers.isEmpty()) { ++ this.startTrading(player); ++ } ++ ++ return InteractionResult.sidedSuccess(this.level().isClientSide); ++ } + } ++ } else { ++ return super.mobInteract(player, hand); + } + } + +- private void setUnhappy() { ++ public void setUnhappy() { + this.setUnhappyCounter(40); + if (!this.level().isClientSide()) { + this.playSound(SoundEvents.VILLAGER_NO, this.getSoundVolume(), this.getVoicePitch()); + } ++ + } + + private void startTrading(Player player) { +@@ -366,10 +326,12 @@ + @Override + public void setTradingPlayer(@Nullable Player player) { + boolean flag = this.getTradingPlayer() != null && player == null; ++ + super.setTradingPlayer(player); + if (flag) { + this.stopTrading(); + } ++ + } + + @Override +@@ -379,9 +341,14 @@ + } + + private void resetSpecialPrices() { +- for (MerchantOffer merchantOffer : this.getOffers()) { +- merchantOffer.resetSpecialPriceDiff(); ++ Iterator iterator = this.getOffers().iterator(); ++ ++ while (iterator.hasNext()) { ++ MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); ++ ++ merchantrecipe.resetSpecialPriceDiff(); + } ++ + } + + @Override +@@ -396,39 +363,49 @@ + + public void restock() { + this.updateDemand(); ++ Iterator iterator = this.getOffers().iterator(); + +- for (MerchantOffer merchantOffer : this.getOffers()) { +- merchantOffer.resetUses(); ++ while (iterator.hasNext()) { ++ MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); ++ ++ // CraftBukkit start ++ VillagerReplenishTradeEvent event = new VillagerReplenishTradeEvent((org.bukkit.entity.Villager) this.getBukkitEntity(), merchantrecipe.asBukkit()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ merchantrecipe.resetUses(); ++ } ++ // CraftBukkit end + } + + this.resendOffersToTradingPlayer(); + this.lastRestockGameTime = this.level().getGameTime(); +- this.numberOfRestocksToday++; ++ ++this.numberOfRestocksToday; + } + + private void resendOffersToTradingPlayer() { +- MerchantOffers offers = this.getOffers(); +- Player tradingPlayer = this.getTradingPlayer(); +- if (tradingPlayer != null && !offers.isEmpty()) { +- tradingPlayer.sendMerchantOffers( +- tradingPlayer.containerMenu.containerId, +- offers, +- this.getVillagerData().getLevel(), +- this.getVillagerXp(), +- this.showProgressBar(), +- this.canRestock() +- ); ++ MerchantOffers merchantrecipelist = this.getOffers(); ++ Player entityhuman = this.getTradingPlayer(); ++ ++ if (entityhuman != null && !merchantrecipelist.isEmpty()) { ++ entityhuman.sendMerchantOffers(entityhuman.containerMenu.containerId, merchantrecipelist, this.getVillagerData().getLevel(), this.getVillagerXp(), this.showProgressBar(), this.canRestock()); + } ++ + } + + private boolean needsToRestock() { +- for (MerchantOffer merchantOffer : this.getOffers()) { +- if (merchantOffer.needsRestock()) { +- return true; ++ Iterator iterator = this.getOffers().iterator(); ++ ++ MerchantOffer merchantrecipe; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return false; + } +- } + +- return false; ++ merchantrecipe = (MerchantOffer) iterator.next(); ++ } while (!merchantrecipe.needsRestock()); ++ ++ return true; + } + + private boolean allowedToRestock() { +@@ -436,19 +413,21 @@ + } + + public boolean shouldRestock() { +- long l = this.lastRestockGameTime + 12000L; +- long gameTime = this.level().getGameTime(); +- boolean flag = gameTime > l; +- long dayTime = this.level().getDayTime(); ++ long i = this.lastRestockGameTime + 12000L; ++ long j = this.level().getGameTime(); ++ boolean flag = j > i; ++ long k = this.level().getDayTime(); ++ + if (this.lastRestockCheckDayTime > 0L) { +- long l1 = this.lastRestockCheckDayTime / 24000L; +- long l2 = dayTime / 24000L; +- flag |= l2 > l1; ++ long l = this.lastRestockCheckDayTime / 24000L; ++ long i1 = k / 24000L; ++ ++ flag |= i1 > l; + } + +- this.lastRestockCheckDayTime = dayTime; ++ this.lastRestockCheckDayTime = k; + if (flag) { +- this.lastRestockGameTime = gameTime; ++ this.lastRestockGameTime = j; + this.resetNumberOfRestocks(); + } + +@@ -457,13 +436,24 @@ + + private void catchUpDemand() { + int i = 2 - this.numberOfRestocksToday; ++ + if (i > 0) { +- for (MerchantOffer merchantOffer : this.getOffers()) { +- merchantOffer.resetUses(); ++ Iterator iterator = this.getOffers().iterator(); ++ ++ while (iterator.hasNext()) { ++ MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); ++ ++ // CraftBukkit start ++ VillagerReplenishTradeEvent event = new VillagerReplenishTradeEvent((org.bukkit.entity.Villager) this.getBukkitEntity(), merchantrecipe.asBukkit()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ merchantrecipe.resetUses(); ++ } ++ // CraftBukkit end + } + } + +- for (int i1 = 0; i1 < i; i1++) { ++ for (int j = 0; j < i; ++j) { + this.updateDemand(); + } + +@@ -471,46 +461,63 @@ + } + + private void updateDemand() { +- for (MerchantOffer merchantOffer : this.getOffers()) { +- merchantOffer.updateDemand(); ++ Iterator iterator = this.getOffers().iterator(); ++ ++ while (iterator.hasNext()) { ++ MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); ++ ++ merchantrecipe.updateDemand(); + } ++ + } + + private void updateSpecialPrices(Player player) { +- int playerReputation = this.getPlayerReputation(player); +- if (playerReputation != 0) { +- for (MerchantOffer merchantOffer : this.getOffers()) { +- merchantOffer.addToSpecialPriceDiff(-Mth.floor((float)playerReputation * merchantOffer.getPriceMultiplier())); ++ int i = this.getPlayerReputation(player); ++ ++ if (i != 0) { ++ Iterator iterator = this.getOffers().iterator(); ++ ++ while (iterator.hasNext()) { ++ MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); ++ ++ merchantrecipe.addToSpecialPriceDiff(-Mth.floor((float) i * merchantrecipe.getPriceMultiplier())); + } + } + + if (player.hasEffect(MobEffects.HERO_OF_THE_VILLAGE)) { +- MobEffectInstance effect = player.getEffect(MobEffects.HERO_OF_THE_VILLAGE); +- int amplifier = effect.getAmplifier(); ++ MobEffectInstance mobeffect = player.getEffect(MobEffects.HERO_OF_THE_VILLAGE); ++ int j = mobeffect.getAmplifier(); ++ Iterator iterator1 = this.getOffers().iterator(); + +- for (MerchantOffer merchantOffer1 : this.getOffers()) { +- double d = 0.3 + 0.0625 * (double)amplifier; +- int i = (int)Math.floor(d * (double)merchantOffer1.getBaseCostA().getCount()); +- merchantOffer1.addToSpecialPriceDiff(-Math.max(i, 1)); ++ while (iterator1.hasNext()) { ++ MerchantOffer merchantrecipe1 = (MerchantOffer) iterator1.next(); ++ double d0 = 0.3D + 0.0625D * (double) j; ++ int k = (int) Math.floor(d0 * (double) merchantrecipe1.getBaseCostA().getCount()); ++ ++ merchantrecipe1.addToSpecialPriceDiff(-Math.max(k, 1)); + } + } ++ + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_VILLAGER_DATA, new VillagerData(VillagerType.PLAINS, VillagerProfession.NONE, 1)); ++ this.entityData.define(Villager.DATA_VILLAGER_DATA, new VillagerData(VillagerType.PLAINS, VillagerProfession.NONE, 1)); + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- VillagerData.CODEC +- .encodeStart(NbtOps.INSTANCE, this.getVillagerData()) +- .resultOrPartial(LOGGER::error) +- .ifPresent(tag -> compound.put("VillagerData", tag)); +- compound.putByte("FoodLevel", (byte)this.foodLevel); +- compound.put("Gossips", this.gossips.store(NbtOps.INSTANCE)); ++ DataResult dataresult = VillagerData.CODEC.encodeStart(NbtOps.INSTANCE, this.getVillagerData()); // CraftBukkit - decompile error ++ Logger logger = Villager.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("VillagerData", nbtbase); ++ }); ++ compound.putByte("FoodLevel", (byte) this.foodLevel); ++ compound.put("Gossips", (Tag) this.gossips.store(NbtOps.INSTANCE)); + compound.putInt("Xp", this.villagerXp); + compound.putLong("LastRestock", this.lastRestockGameTime); + compound.putLong("LastGossipDecay", this.lastGossipDecayTime); +@@ -518,14 +525,18 @@ + if (this.assignProfessionWhenSpawned) { + compound.putBoolean("AssignProfessionWhenSpawned", true); + } ++ + } + + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); + if (compound.contains("VillagerData", 10)) { +- DataResult dataResult = VillagerData.CODEC.parse(new Dynamic<>(NbtOps.INSTANCE, compound.get("VillagerData"))); +- dataResult.resultOrPartial(LOGGER::error).ifPresent(this::setVillagerData); ++ DataResult dataresult = VillagerData.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compound.get("VillagerData"))); ++ Logger logger = Villager.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent(this::setVillagerData); + } + + if (compound.contains("Offers", 10)) { +@@ -536,8 +547,9 @@ + this.foodLevel = compound.getByte("FoodLevel"); + } + +- ListTag list = compound.getList("Gossips", 10); +- this.gossips.update(new Dynamic<>(NbtOps.INSTANCE, list)); ++ ListTag nbttaglist = compound.getList("Gossips", 10); ++ ++ this.gossips.update(new Dynamic(NbtOps.INSTANCE, nbttaglist)); + if (compound.contains("Xp", 3)) { + this.villagerXp = compound.getInt("Xp"); + } +@@ -546,13 +558,14 @@ + this.lastGossipDecayTime = compound.getLong("LastGossipDecay"); + this.setCanPickUpLoot(true); + if (this.level() instanceof ServerLevel) { +- this.refreshBrain((ServerLevel)this.level()); ++ this.refreshBrain((ServerLevel) this.level()); + } + + this.numberOfRestocksToday = compound.getInt("RestocksToday"); + if (compound.contains("AssignProfessionWhenSpawned")) { + this.assignProfessionWhenSpawned = compound.getBoolean("AssignProfessionWhenSpawned"); + } ++ + } + + @Override +@@ -563,11 +576,7 @@ + @Nullable + @Override + protected SoundEvent getAmbientSound() { +- if (this.isSleeping()) { +- return null; +- } else { +- return this.isTrading() ? SoundEvents.VILLAGER_TRADE : SoundEvents.VILLAGER_AMBIENT; +- } ++ return this.isSleeping() ? null : (this.isTrading() ? SoundEvents.VILLAGER_TRADE : SoundEvents.VILLAGER_AMBIENT); + } + + @Override +@@ -581,31 +590,35 @@ + } + + public void playWorkSound() { +- SoundEvent soundEvent = this.getVillagerData().getProfession().workSound(); +- if (soundEvent != null) { +- this.playSound(soundEvent, this.getSoundVolume(), this.getVoicePitch()); ++ SoundEvent soundeffect = this.getVillagerData().getProfession().workSound(); ++ ++ if (soundeffect != null) { ++ this.playSound(soundeffect, this.getSoundVolume(), this.getVoicePitch()); + } ++ + } + + @Override + public void setVillagerData(VillagerData data) { +- VillagerData villagerData = this.getVillagerData(); +- if (villagerData.getProfession() != data.getProfession()) { ++ VillagerData villagerdata1 = this.getVillagerData(); ++ ++ if (villagerdata1.getProfession() != data.getProfession()) { + this.offers = null; + } + +- this.entityData.set(DATA_VILLAGER_DATA, data); ++ this.entityData.set(Villager.DATA_VILLAGER_DATA, data); + } + + @Override + public VillagerData getVillagerData() { +- return this.entityData.get(DATA_VILLAGER_DATA); ++ return (VillagerData) this.entityData.get(Villager.DATA_VILLAGER_DATA); + } + + @Override + protected void rewardTradeXp(MerchantOffer offer) { + int i = 3 + this.random.nextInt(4); +- this.villagerXp = this.villagerXp + offer.getXp(); ++ ++ this.villagerXp += offer.getXp(); + this.lastTradedPlayer = this.getTradingPlayer(); + if (this.shouldIncreaseLevel()) { + this.updateMerchantTimer = 40; +@@ -614,8 +627,9 @@ + } + + if (offer.shouldRewardExp()) { +- this.level().addFreshEntity(new ExperienceOrb(this.level(), this.getX(), this.getY() + 0.5, this.getZ(), i)); ++ this.level().addFreshEntity(new ExperienceOrb(this.level(), this.getX(), this.getY() + 0.5D, this.getZ(), i)); + } ++ + } + + public void setChasing(boolean chasing) { +@@ -629,9 +643,9 @@ + @Override + public void setLastHurtByMob(@Nullable LivingEntity livingBase) { + if (livingBase != null && this.level() instanceof ServerLevel) { +- ((ServerLevel)this.level()).onReputationEvent(ReputationEventType.VILLAGER_HURT, livingBase, this); ++ ((ServerLevel) this.level()).onReputationEvent(ReputationEventType.VILLAGER_HURT, livingBase, this); + if (this.isAlive() && livingBase instanceof Player) { +- this.level().broadcastEntityEvent(this, (byte)13); ++ this.level().broadcastEntityEvent(this, (byte) 13); + } + } + +@@ -640,8 +654,9 @@ + + @Override + public void die(DamageSource cause) { +- LOGGER.info("Villager {} died, message: '{}'", this, cause.getLocalizedDeathMessage(this).getString()); ++ Villager.LOGGER.info("Villager {} died, message: '{}'", this, cause.getLocalizedDeathMessage(this).getString()); + Entity entity = cause.getEntity(); ++ + if (entity != null) { + this.tellWitnessesThatIWasMurdered(entity); + } +@@ -650,7 +665,7 @@ + super.die(cause); + } + +- private void releaseAllPois() { ++ public void releaseAllPois() { + this.releasePoi(MemoryModuleType.HOME); + this.releasePoi(MemoryModuleType.JOB_SITE); + this.releasePoi(MemoryModuleType.POTENTIAL_JOB_SITE); +@@ -658,29 +673,40 @@ + } + + private void tellWitnessesThatIWasMurdered(Entity murderer) { +- if (this.level() instanceof ServerLevel serverLevel) { +- Optional memory = this.brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES); +- if (!memory.isEmpty()) { +- memory.get() +- .findAll(ReputationEventHandler.class::isInstance) +- .forEach(host -> serverLevel.onReputationEvent(ReputationEventType.VILLAGER_KILLED, murderer, (ReputationEventHandler)host)); ++ Level world = this.level(); ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ Optional optional = this.brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES); ++ ++ if (!optional.isEmpty()) { ++ NearestVisibleLivingEntities nearestvisiblelivingentities = (NearestVisibleLivingEntities) optional.get(); ++ ++ Objects.requireNonNull(ReputationEventHandler.class); ++ nearestvisiblelivingentities.findAll(ReputationEventHandler.class::isInstance).forEach((entityliving) -> { ++ worldserver.onReputationEvent(ReputationEventType.VILLAGER_KILLED, murderer, (ReputationEventHandler) entityliving); ++ }); + } + } + } + + public void releasePoi(MemoryModuleType moduleType) { + if (this.level() instanceof ServerLevel) { +- MinecraftServer server = ((ServerLevel)this.level()).getServer(); +- this.brain.getMemory(moduleType).ifPresent(globalPos -> { +- ServerLevel level = server.getLevel(globalPos.dimension()); +- if (level != null) { +- PoiManager poiManager = level.getPoiManager(); +- Optional> type = poiManager.getType(globalPos.pos()); +- BiPredicate> biPredicate = POI_MEMORIES.get(moduleType); +- if (type.isPresent() && biPredicate.test(this, type.get())) { +- poiManager.release(globalPos.pos()); +- DebugPackets.sendPoiTicketCountPacket(level, globalPos.pos()); ++ MinecraftServer minecraftserver = ((ServerLevel) this.level()).getServer(); ++ ++ this.brain.getMemory(moduleType).ifPresent((globalpos) -> { ++ ServerLevel worldserver = minecraftserver.getLevel(globalpos.dimension()); ++ ++ if (worldserver != null) { ++ PoiManager villageplace = worldserver.getPoiManager(); ++ Optional> optional = villageplace.getType(globalpos.pos()); ++ BiPredicate> bipredicate = (BiPredicate) Villager.POI_MEMORIES.get(moduleType); ++ ++ if (optional.isPresent() && bipredicate.test(this, (Holder) optional.get())) { ++ villageplace.release(globalpos.pos()); ++ DebugPackets.sendPoiTicketCountPacket(worldserver, globalpos.pos()); + } ++ + } + }); + } +@@ -697,15 +723,17 @@ + + private void eatUntilFull() { + if (this.hungry() && this.countFoodPointsInInventory() != 0) { +- for (int i = 0; i < this.getInventory().getContainerSize(); i++) { +- ItemStack item = this.getInventory().getItem(i); +- if (!item.isEmpty()) { +- Integer integer = FOOD_POINTS.get(item.getItem()); ++ for (int i = 0; i < this.getInventory().getContainerSize(); ++i) { ++ ItemStack itemstack = this.getInventory().getItem(i); ++ ++ if (!itemstack.isEmpty()) { ++ Integer integer = (Integer) Villager.FOOD_POINTS.get(itemstack.getItem()); ++ + if (integer != null) { +- int count = item.getCount(); ++ int j = itemstack.getCount(); + +- for (int i1 = count; i1 > 0; i1--) { +- this.foodLevel = this.foodLevel + integer; ++ for (int k = j; k > 0; --k) { ++ this.foodLevel += integer; + this.getInventory().removeItem(i, 1); + if (!this.hungry()) { + return; +@@ -714,11 +742,14 @@ + } + } + } ++ + } + } + + public int getPlayerReputation(Player player) { +- return this.gossips.getReputation(player.getUUID(), gossipType -> true); ++ return this.gossips.getReputation(player.getUUID(), (reputationtype) -> { ++ return true; ++ }); + } + + private void digestFood(int qty) { +@@ -735,20 +766,21 @@ + } + + private boolean shouldIncreaseLevel() { +- int level = this.getVillagerData().getLevel(); +- return VillagerData.canLevelUp(level) && this.villagerXp >= VillagerData.getMaxXpPerLevel(level); ++ int i = this.getVillagerData().getLevel(); ++ ++ return VillagerData.canLevelUp(i) && this.villagerXp >= VillagerData.getMaxXpPerLevel(i); + } + +- private void increaseMerchantCareer() { ++ public void increaseMerchantCareer() { + this.setVillagerData(this.getVillagerData().setLevel(this.getVillagerData().getLevel() + 1)); + this.updateTrades(); + } + + @Override + protected Component getTypeName() { +- return Component.translatable( +- this.getType().getDescriptionId() + "." + BuiltInRegistries.VILLAGER_PROFESSION.getKey(this.getVillagerData().getProfession()).getPath() +- ); ++ String s = this.getType().getDescriptionId(); ++ ++ return Component.translatable(s + "." + BuiltInRegistries.VILLAGER_PROFESSION.getKey(this.getVillagerData().getProfession()).getPath()); + } + + @Override +@@ -764,22 +796,21 @@ + } else { + super.handleEntityEvent(id); + } ++ + } + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- if (reason == MobSpawnType.BREEDING) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ if (reason == EnumMobSpawn.BREEDING) { + this.setVillagerData(this.getVillagerData().setProfession(VillagerProfession.NONE)); + } + +- if (reason == MobSpawnType.COMMAND || reason == MobSpawnType.SPAWN_EGG || MobSpawnType.isSpawner(reason) || reason == MobSpawnType.DISPENSER) { ++ if (reason == EnumMobSpawn.COMMAND || reason == EnumMobSpawn.SPAWN_EGG || EnumMobSpawn.isSpawner(reason) || reason == EnumMobSpawn.DISPENSER) { + this.setVillagerData(this.getVillagerData().setType(VillagerType.byBiome(level.getBiome(this.blockPosition())))); + } + +- if (reason == MobSpawnType.STRUCTURE) { ++ if (reason == EnumMobSpawn.STRUCTURE) { + this.assignProfessionWhenSpawned = true; + } + +@@ -789,37 +820,45 @@ + @Nullable + @Override + public Villager getBreedOffspring(ServerLevel level, AgeableMob otherParent) { +- double randomDouble = this.random.nextDouble(); +- VillagerType villagerType; +- if (randomDouble < 0.5) { +- villagerType = VillagerType.byBiome(level.getBiome(this.blockPosition())); +- } else if (randomDouble < 0.75) { +- villagerType = this.getVillagerData().getType(); ++ double d0 = this.random.nextDouble(); ++ VillagerType villagertype; ++ ++ if (d0 < 0.5D) { ++ villagertype = VillagerType.byBiome(level.getBiome(this.blockPosition())); ++ } else if (d0 < 0.75D) { ++ villagertype = this.getVillagerData().getType(); + } else { +- villagerType = ((Villager)otherParent).getVillagerData().getType(); ++ villagertype = ((Villager) otherParent).getVillagerData().getType(); + } + +- Villager villager = new Villager(EntityType.VILLAGER, level, villagerType); +- villager.finalizeSpawn(level, level.getCurrentDifficultyAt(villager.blockPosition()), MobSpawnType.BREEDING, null, null); +- return villager; ++ Villager entityvillager = new Villager(EntityType.VILLAGER, level, villagertype); ++ ++ entityvillager.finalizeSpawn(level, level.getCurrentDifficultyAt(entityvillager.blockPosition()), EnumMobSpawn.BREEDING, (GroupDataEntity) null, (CompoundTag) null); ++ return entityvillager; + } + + @Override + public void thunderHit(ServerLevel level, LightningBolt lightning) { + if (level.getDifficulty() != Difficulty.PEACEFUL) { +- LOGGER.info("Villager {} was struck by lightning {}.", this, lightning); +- Witch witch = EntityType.WITCH.create(level); +- if (witch != null) { +- witch.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); +- witch.finalizeSpawn(level, level.getCurrentDifficultyAt(witch.blockPosition()), MobSpawnType.CONVERSION, null, null); +- witch.setNoAi(this.isNoAi()); ++ Villager.LOGGER.info("Villager {} was struck by lightning {}.", this, lightning); ++ Witch entitywitch = (Witch) EntityType.WITCH.create(level); ++ ++ if (entitywitch != null) { ++ entitywitch.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); ++ entitywitch.finalizeSpawn(level, level.getCurrentDifficultyAt(entitywitch.blockPosition()), EnumMobSpawn.CONVERSION, (GroupDataEntity) null, (CompoundTag) null); ++ entitywitch.setNoAi(this.isNoAi()); + if (this.hasCustomName()) { +- witch.setCustomName(this.getCustomName()); +- witch.setCustomNameVisible(this.isCustomNameVisible()); ++ entitywitch.setCustomName(this.getCustomName()); ++ entitywitch.setCustomNameVisible(this.isCustomNameVisible()); + } + +- witch.setPersistenceRequired(); +- level.addFreshEntityWithPassengers(witch); ++ entitywitch.setPersistenceRequired(); ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, entitywitch, EntityTransformEvent.TransformReason.LIGHTNING).isCancelled()) { ++ return; ++ } ++ level.addFreshEntityWithPassengers(entitywitch, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); ++ // CraftBukkit end + this.releaseAllPois(); + this.discard(); + } else { +@@ -828,6 +867,7 @@ + } else { + super.thunderHit(level, lightning); + } ++ + } + + @Override +@@ -838,7 +878,8 @@ + @Override + public boolean wantsToPickUp(ItemStack stack) { + Item item = stack.getItem(); +- return (WANTED_ITEMS.contains(item) || this.getVillagerData().getProfession().requestedItems().contains(item)) && this.getInventory().canAddItem(stack); ++ ++ return (Villager.WANTED_ITEMS.contains(item) || this.getVillagerData().getProfession().requestedItems().contains(item)) && this.getInventory().canAddItem(stack); + } + + public boolean hasExcessFood() { +@@ -850,37 +891,45 @@ + } + + private int countFoodPointsInInventory() { +- SimpleContainer inventory = this.getInventory(); +- return FOOD_POINTS.entrySet().stream().mapToInt(entry -> inventory.countItem(entry.getKey()) * entry.getValue()).sum(); ++ SimpleContainer inventorysubcontainer = this.getInventory(); ++ ++ return Villager.FOOD_POINTS.entrySet().stream().mapToInt((entry) -> { ++ return inventorysubcontainer.countItem((Item) entry.getKey()) * (Integer) entry.getValue(); ++ }).sum(); + } + + public boolean hasFarmSeeds() { +- return this.getInventory().hasAnyMatching(itemStack -> itemStack.is(ItemTags.VILLAGER_PLANTABLE_SEEDS)); ++ return this.getInventory().hasAnyMatching((itemstack) -> { ++ return itemstack.is(ItemTags.VILLAGER_PLANTABLE_SEEDS); ++ }); + } + + @Override + protected void updateTrades() { +- VillagerData villagerData = this.getVillagerData(); +- Int2ObjectMap map1; ++ VillagerData villagerdata = this.getVillagerData(); ++ Int2ObjectMap int2objectmap; ++ + if (this.level().enabledFeatures().contains(FeatureFlags.TRADE_REBALANCE)) { +- Int2ObjectMap map = VillagerTrades.EXPERIMENTAL_TRADES.get(villagerData.getProfession()); +- map1 = map != null ? map : VillagerTrades.TRADES.get(villagerData.getProfession()); ++ Int2ObjectMap int2objectmap1 = (Int2ObjectMap) VillagerTrades.EXPERIMENTAL_TRADES.get(villagerdata.getProfession()); ++ ++ int2objectmap = int2objectmap1 != null ? int2objectmap1 : (Int2ObjectMap) VillagerTrades.TRADES.get(villagerdata.getProfession()); + } else { +- map1 = VillagerTrades.TRADES.get(villagerData.getProfession()); ++ int2objectmap = (Int2ObjectMap) VillagerTrades.TRADES.get(villagerdata.getProfession()); + } + +- if (map1 != null && !map1.isEmpty()) { +- VillagerTrades.ItemListing[] itemListings = map1.get(villagerData.getLevel()); +- if (itemListings != null) { +- MerchantOffers offers = this.getOffers(); +- this.addOffersFromItemListings(offers, itemListings, 2); ++ if (int2objectmap != null && !int2objectmap.isEmpty()) { ++ VillagerTrades.ItemListing[] avillagertrades_imerchantrecipeoption = (VillagerTrades.ItemListing[]) int2objectmap.get(villagerdata.getLevel()); ++ ++ if (avillagertrades_imerchantrecipeoption != null) { ++ MerchantOffers merchantrecipelist = this.getOffers(); ++ ++ this.addOffersFromItemListings(merchantrecipelist, avillagertrades_imerchantrecipeoption, 2); + } + } + } + + public void gossip(ServerLevel serverLevel, Villager target, long gameTime) { +- if ((gameTime < this.lastGossipTime || gameTime >= this.lastGossipTime + 1200L) +- && (gameTime < target.lastGossipTime || gameTime >= target.lastGossipTime + 1200L)) { ++ if ((gameTime < this.lastGossipTime || gameTime >= this.lastGossipTime + 1200L) && (gameTime < target.lastGossipTime || gameTime >= target.lastGossipTime + 1200L)) { + this.gossips.transferFrom(target.gossips, this.random, 10); + this.lastGossipTime = gameTime; + target.lastGossipTime = gameTime; +@@ -889,33 +938,34 @@ + } + + private void maybeDecayGossip() { +- long gameTime = this.level().getGameTime(); ++ long i = this.level().getGameTime(); ++ + if (this.lastGossipDecayTime == 0L) { +- this.lastGossipDecayTime = gameTime; +- } else if (gameTime >= this.lastGossipDecayTime + 24000L) { ++ this.lastGossipDecayTime = i; ++ } else if (i >= this.lastGossipDecayTime + 24000L) { + this.gossips.decay(); +- this.lastGossipDecayTime = gameTime; ++ this.lastGossipDecayTime = i; + } + } + +- public void spawnGolemIfNeeded(ServerLevel serverLevel, long gameTime, int minVillagerAmount) { ++ public void spawnGolemIfNeeded(ServerLevel serverLevel, long gameTime, int j) { + if (this.wantsToSpawnGolem(gameTime)) { +- AABB aABB = this.getBoundingBox().inflate(10.0, 10.0, 10.0); +- List entitiesOfClass = serverLevel.getEntitiesOfClass(Villager.class, aABB); +- List list = entitiesOfClass.stream().filter(villager -> villager.wantsToSpawnGolem(gameTime)).limit(5L).collect(Collectors.toList()); +- if (list.size() >= minVillagerAmount) { +- if (!SpawnUtil.trySpawnMob( +- EntityType.IRON_GOLEM, MobSpawnType.MOB_SUMMONED, serverLevel, this.blockPosition(), 10, 8, 6, SpawnUtil.Strategy.LEGACY_IRON_GOLEM +- ) +- .isEmpty()) { +- entitiesOfClass.forEach(GolemSensor::golemDetected); ++ AABB axisalignedbb = this.getBoundingBox().inflate(10.0D, 10.0D, 10.0D); ++ List list = serverLevel.getEntitiesOfClass(Villager.class, axisalignedbb); ++ List list1 = (List) list.stream().filter((entityvillager) -> { ++ return entityvillager.wantsToSpawnGolem(gameTime); ++ }).limit(5L).collect(Collectors.toList()); ++ ++ if (list1.size() >= j) { ++ if (!SpawnUtil.trySpawnMob(EntityType.IRON_GOLEM, EnumMobSpawn.MOB_SUMMONED, serverLevel, this.blockPosition(), 10, 8, 6, SpawnUtil.Strategy.LEGACY_IRON_GOLEM, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE).isEmpty()) { // CraftBukkit ++ list.forEach(GolemSensor::golemDetected); + } + } + } + } + + public boolean wantsToSpawnGolem(long gameTime) { +- return this.golemSpawnConditionsMet(this.level().getGameTime()) && !this.brain.hasMemoryValue(MemoryModuleType.GOLEM_DETECTED_RECENTLY); ++ return !this.golemSpawnConditionsMet(this.level().getGameTime()) ? false : !this.brain.hasMemoryValue(MemoryModuleType.GOLEM_DETECTED_RECENTLY); + } + + @Override +@@ -930,6 +980,7 @@ + } else if (type == ReputationEventType.VILLAGER_KILLED) { + this.gossips.add(target.getUUID(), GossipType.MAJOR_NEGATIVE, 25); + } ++ + } + + @Override +@@ -951,7 +1002,7 @@ + } + + public void setGossips(Tag gossip) { +- this.gossips.update(new Dynamic<>(NbtOps.INSTANCE, gossip)); ++ this.gossips.update(new Dynamic(NbtOps.INSTANCE, gossip)); + } + + @Override +@@ -963,7 +1014,7 @@ + @Override + public void startSleeping(BlockPos pos) { + super.startSleeping(pos); +- this.brain.setMemory(MemoryModuleType.LAST_SLEPT, this.level().getGameTime()); ++ this.brain.setMemory(MemoryModuleType.LAST_SLEPT, this.level().getGameTime()); // CraftBukkit - decompile error + this.brain.eraseMemory(MemoryModuleType.WALK_TARGET); + this.brain.eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE); + } +@@ -971,11 +1022,12 @@ + @Override + public void stopSleeping() { + super.stopSleeping(); +- this.brain.setMemory(MemoryModuleType.LAST_WOKEN, this.level().getGameTime()); ++ this.brain.setMemory(MemoryModuleType.LAST_WOKEN, this.level().getGameTime()); // CraftBukkit - decompile error + } + + private boolean golemSpawnConditionsMet(long gameTime) { +- Optional memory = this.brain.getMemory(MemoryModuleType.LAST_SLEPT); +- return memory.isPresent() && gameTime - memory.get() < 24000L; ++ Optional optional = this.brain.getMemory(MemoryModuleType.LAST_SLEPT); ++ ++ return optional.isPresent() ? gameTime - (Long) optional.get() < 24000L : false; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/npc/WanderingTrader.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/npc/WanderingTrader.java.patch new file mode 100644 index 0000000000..d3d01aa735 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/npc/WanderingTrader.java.patch @@ -0,0 +1,295 @@ +--- a/net/minecraft/world/entity/npc/WanderingTrader.java ++++ b/net/minecraft/world/entity/npc/WanderingTrader.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.entity.npc; + + import java.util.EnumSet; ++import java.util.Iterator; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.nbt.CompoundTag; +@@ -9,7 +10,7 @@ + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; +@@ -19,11 +20,11 @@ + import net.minecraft.world.entity.ai.goal.AvoidEntityGoal; + import net.minecraft.world.entity.ai.goal.FloatGoal; + import net.minecraft.world.entity.ai.goal.Goal; +-import net.minecraft.world.entity.ai.goal.InteractGoal; + import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; + import net.minecraft.world.entity.ai.goal.LookAtTradingPlayerGoal; + import net.minecraft.world.entity.ai.goal.MoveTowardsRestrictionGoal; + import net.minecraft.world.entity.ai.goal.PanicGoal; ++import net.minecraft.world.entity.ai.goal.PathfinderGoalInteract; + import net.minecraft.world.entity.ai.goal.TradeWithPlayerGoal; + import net.minecraft.world.entity.ai.goal.UseItemGoal; + import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal; +@@ -46,7 +47,15 @@ + import net.minecraft.world.phys.Vec3; + import org.apache.commons.lang3.tuple.Pair; + +-public class WanderingTrader extends AbstractVillager { ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; ++import org.bukkit.entity.AbstractVillager; ++import org.bukkit.event.entity.VillagerAcquireTradeEvent; ++// CraftBukkit end ++ ++public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVillager { ++ + private static final int NUMBER_OF_TRADE_OFFERS = 5; + @Nullable + private BlockPos wanderTarget; +@@ -54,45 +63,32 @@ + + public WanderingTrader(EntityType entityType, Level level) { + super(entityType, level); ++ this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader + } + + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); +- this.goalSelector +- .addGoal( +- 0, +- new UseItemGoal<>( +- this, +- PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.INVISIBILITY), +- SoundEvents.WANDERING_TRADER_DISAPPEARED, +- wanderingTrader -> this.level().isNight() && !wanderingTrader.isInvisible() +- ) +- ); +- this.goalSelector +- .addGoal( +- 0, +- new UseItemGoal<>( +- this, +- new ItemStack(Items.MILK_BUCKET), +- SoundEvents.WANDERING_TRADER_REAPPEARED, +- wanderingTrader -> this.level().isDay() && wanderingTrader.isInvisible() +- ) +- ); ++ this.goalSelector.addGoal(0, new UseItemGoal<>(this, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.INVISIBILITY), SoundEvents.WANDERING_TRADER_DISAPPEARED, (entityvillagertrader) -> { ++ return this.level().isNight() && !entityvillagertrader.isInvisible(); ++ })); ++ this.goalSelector.addGoal(0, new UseItemGoal<>(this, new ItemStack(Items.MILK_BUCKET), SoundEvents.WANDERING_TRADER_REAPPEARED, (entityvillagertrader) -> { ++ return this.level().isDay() && entityvillagertrader.isInvisible(); ++ })); + this.goalSelector.addGoal(1, new TradeWithPlayerGoal(this)); +- this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Zombie.class, 8.0F, 0.5, 0.5)); +- this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Evoker.class, 12.0F, 0.5, 0.5)); +- this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Vindicator.class, 8.0F, 0.5, 0.5)); +- this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Vex.class, 8.0F, 0.5, 0.5)); +- this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Pillager.class, 15.0F, 0.5, 0.5)); +- this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Illusioner.class, 12.0F, 0.5, 0.5)); +- this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Zoglin.class, 10.0F, 0.5, 0.5)); +- this.goalSelector.addGoal(1, new PanicGoal(this, 0.5)); ++ this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Zombie.class, 8.0F, 0.5D, 0.5D)); ++ this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Evoker.class, 12.0F, 0.5D, 0.5D)); ++ this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Vindicator.class, 8.0F, 0.5D, 0.5D)); ++ this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Vex.class, 8.0F, 0.5D, 0.5D)); ++ this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Pillager.class, 15.0F, 0.5D, 0.5D)); ++ this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Illusioner.class, 12.0F, 0.5D, 0.5D)); ++ this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Zoglin.class, 10.0F, 0.5D, 0.5D)); ++ this.goalSelector.addGoal(1, new PanicGoal(this, 0.5D)); + this.goalSelector.addGoal(1, new LookAtTradingPlayerGoal(this)); +- this.goalSelector.addGoal(2, new WanderingTrader.WanderToPositionGoal(this, 2.0, 0.35)); +- this.goalSelector.addGoal(4, new MoveTowardsRestrictionGoal(this, 0.35)); +- this.goalSelector.addGoal(8, new WaterAvoidingRandomStrollGoal(this, 0.35)); +- this.goalSelector.addGoal(9, new InteractGoal(this, Player.class, 3.0F, 1.0F)); ++ this.goalSelector.addGoal(2, new WanderingTrader.WanderToPositionGoal(this, 2.0D, 0.35D)); ++ this.goalSelector.addGoal(4, new MoveTowardsRestrictionGoal(this, 0.35D)); ++ this.goalSelector.addGoal(8, new WaterAvoidingRandomStrollGoal(this, 0.35D)); ++ this.goalSelector.addGoal(9, new PathfinderGoalInteract(this, Player.class, 3.0F, 1.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); + } + +@@ -108,10 +104,11 @@ + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (!itemInHand.is(Items.VILLAGER_SPAWN_EGG) && this.isAlive() && !this.isTrading() && !this.isBaby()) { +- if (hand == InteractionHand.MAIN_HAND) { ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (!itemstack.is(Items.VILLAGER_SPAWN_EGG) && this.isAlive() && !this.isTrading() && !this.isBaby()) { ++ if (hand == EnumHand.MAIN_HAND) { + player.awardStat(Stats.TALKED_TO_VILLAGER); + } + +@@ -135,28 +132,45 @@ + if (this.level().enabledFeatures().contains(FeatureFlags.TRADE_REBALANCE)) { + this.experimentalUpdateTrades(); + } else { +- VillagerTrades.ItemListing[] itemListings = VillagerTrades.WANDERING_TRADER_TRADES.get(1); +- VillagerTrades.ItemListing[] itemListings1 = VillagerTrades.WANDERING_TRADER_TRADES.get(2); +- if (itemListings != null && itemListings1 != null) { +- MerchantOffers offers = this.getOffers(); +- this.addOffersFromItemListings(offers, itemListings, 5); +- int randomInt = this.random.nextInt(itemListings1.length); +- VillagerTrades.ItemListing itemListing = itemListings1[randomInt]; +- MerchantOffer offer = itemListing.getOffer(this, this.random); +- if (offer != null) { +- offers.add(offer); ++ VillagerTrades.ItemListing[] avillagertrades_imerchantrecipeoption = (VillagerTrades.ItemListing[]) VillagerTrades.WANDERING_TRADER_TRADES.get(1); ++ VillagerTrades.ItemListing[] avillagertrades_imerchantrecipeoption1 = (VillagerTrades.ItemListing[]) VillagerTrades.WANDERING_TRADER_TRADES.get(2); ++ ++ if (avillagertrades_imerchantrecipeoption != null && avillagertrades_imerchantrecipeoption1 != null) { ++ MerchantOffers merchantrecipelist = this.getOffers(); ++ ++ this.addOffersFromItemListings(merchantrecipelist, avillagertrades_imerchantrecipeoption, 5); ++ int i = this.random.nextInt(avillagertrades_imerchantrecipeoption1.length); ++ VillagerTrades.ItemListing villagertrades_imerchantrecipeoption = avillagertrades_imerchantrecipeoption1[i]; ++ MerchantOffer merchantrecipe = villagertrades_imerchantrecipeoption.getOffer(this, this.random); ++ ++ if (merchantrecipe != null) { ++ // CraftBukkit start ++ VillagerAcquireTradeEvent event = new VillagerAcquireTradeEvent((AbstractVillager) getBukkitEntity(), merchantrecipe.asBukkit()); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ if (!event.isCancelled()) { ++ merchantrecipelist.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); ++ } ++ // CraftBukkit end + } ++ + } + } + } + + private void experimentalUpdateTrades() { +- MerchantOffers offers = this.getOffers(); ++ MerchantOffers merchantrecipelist = this.getOffers(); ++ Iterator iterator = VillagerTrades.EXPERIMENTAL_WANDERING_TRADER_TRADES.iterator(); + +- for (Pair pair : VillagerTrades.EXPERIMENTAL_WANDERING_TRADER_TRADES) { +- VillagerTrades.ItemListing[] itemListings = pair.getLeft(); +- this.addOffersFromItemListings(offers, itemListings, pair.getRight()); ++ while (iterator.hasNext()) { ++ Pair pair = (Pair) iterator.next(); ++ VillagerTrades.ItemListing[] avillagertrades_imerchantrecipeoption = (VillagerTrades.ItemListing[]) pair.getLeft(); ++ ++ this.addOffersFromItemListings(merchantrecipelist, avillagertrades_imerchantrecipeoption, (Integer) pair.getRight()); + } ++ + } + + @Override +@@ -166,6 +180,7 @@ + if (this.wanderTarget != null) { + compound.put("WanderTarget", NbtUtils.writeBlockPos(this.wanderTarget)); + } ++ + } + + @Override +@@ -191,8 +206,10 @@ + protected void rewardTradeXp(MerchantOffer offer) { + if (offer.shouldRewardExp()) { + int i = 3 + this.random.nextInt(4); +- this.level().addFreshEntity(new ExperienceOrb(this.level(), this.getX(), this.getY() + 0.5, this.getZ(), i)); ++ ++ this.level().addFreshEntity(new ExperienceOrb(this.level(), this.getX(), this.getY() + 0.5D, this.getZ(), i)); + } ++ + } + + @Override +@@ -239,12 +256,14 @@ + if (!this.level().isClientSide) { + this.maybeDespawn(); + } ++ + } + + private void maybeDespawn() { + if (this.despawnDelay > 0 && !this.isTrading() && --this.despawnDelay == 0) { + this.discard(); + } ++ + } + + public void setWanderTarget(@Nullable BlockPos wanderTarget) { +@@ -256,48 +275,47 @@ + return this.wanderTarget; + } + +- class WanderToPositionGoal extends Goal { ++ private class WanderToPositionGoal extends Goal { ++ + final WanderingTrader trader; + final double stopDistance; + final double speedModifier; + +- WanderToPositionGoal(WanderingTrader trader, double stopDistance, double speedModifier) { +- this.trader = trader; +- this.stopDistance = stopDistance; +- this.speedModifier = speedModifier; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ WanderToPositionGoal(WanderingTrader entityvillagertrader, double d0, double d1) { ++ this.trader = entityvillagertrader; ++ this.stopDistance = d0; ++ this.speedModifier = d1; ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override + public void stop() { +- this.trader.setWanderTarget(null); ++ this.trader.setWanderTarget((BlockPos) null); + WanderingTrader.this.navigation.stop(); + } + + @Override + public boolean canUse() { +- BlockPos wanderTarget = this.trader.getWanderTarget(); +- return wanderTarget != null && this.isTooFarAway(wanderTarget, this.stopDistance); ++ BlockPos blockposition = this.trader.getWanderTarget(); ++ ++ return blockposition != null && this.isTooFarAway(blockposition, this.stopDistance); + } + + @Override + public void tick() { +- BlockPos wanderTarget = this.trader.getWanderTarget(); +- if (wanderTarget != null && WanderingTrader.this.navigation.isDone()) { +- if (this.isTooFarAway(wanderTarget, 10.0)) { +- Vec3 vec3 = new Vec3( +- (double)wanderTarget.getX() - this.trader.getX(), +- (double)wanderTarget.getY() - this.trader.getY(), +- (double)wanderTarget.getZ() - this.trader.getZ() +- ) +- .normalize(); +- Vec3 vec31 = vec3.scale(10.0).add(this.trader.getX(), this.trader.getY(), this.trader.getZ()); +- WanderingTrader.this.navigation.moveTo(vec31.x, vec31.y, vec31.z, this.speedModifier); ++ BlockPos blockposition = this.trader.getWanderTarget(); ++ ++ if (blockposition != null && WanderingTrader.this.navigation.isDone()) { ++ if (this.isTooFarAway(blockposition, 10.0D)) { ++ Vec3 vec3d = (new Vec3((double) blockposition.getX() - this.trader.getX(), (double) blockposition.getY() - this.trader.getY(), (double) blockposition.getZ() - this.trader.getZ())).normalize(); ++ Vec3 vec3d1 = vec3d.scale(10.0D).add(this.trader.getX(), this.trader.getY(), this.trader.getZ()); ++ ++ WanderingTrader.this.navigation.moveTo(vec3d1.x, vec3d1.y, vec3d1.z, this.speedModifier); + } else { +- WanderingTrader.this.navigation +- .moveTo((double)wanderTarget.getX(), (double)wanderTarget.getY(), (double)wanderTarget.getZ(), this.speedModifier); ++ WanderingTrader.this.navigation.moveTo((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), this.speedModifier); + } + } ++ + } + + private boolean isTooFarAway(BlockPos pos, double distance) { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/npc/WanderingTraderSpawner.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/npc/WanderingTraderSpawner.java.patch new file mode 100644 index 0000000000..af50c3d709 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/npc/WanderingTraderSpawner.java.patch @@ -0,0 +1,178 @@ +--- a/net/minecraft/world/entity/npc/WanderingTraderSpawner.java ++++ b/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +@@ -1,20 +1,20 @@ + package net.minecraft.world.entity.npc; + ++import java.util.Iterator; + import java.util.Optional; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +-import net.minecraft.core.Holder; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.tags.BiomeTags; + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.SpawnPlacements; + import net.minecraft.world.entity.ai.village.poi.PoiManager; + import net.minecraft.world.entity.ai.village.poi.PoiTypes; + import net.minecraft.world.entity.animal.horse.TraderLlama; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.CustomSpawner; + import net.minecraft.world.level.GameRules; +@@ -24,6 +24,7 @@ + import net.minecraft.world.level.storage.ServerLevelData; + + public class WanderingTraderSpawner implements CustomSpawner { ++ + private static final int DEFAULT_TICK_DELAY = 1200; + public static final int DEFAULT_SPAWN_DELAY = 24000; + private static final int MIN_SPAWN_CHANCE = 25; +@@ -48,6 +49,7 @@ + this.spawnChance = 25; + serverLevelData.setWanderingTraderSpawnChance(this.spawnChance); + } ++ + } + + @Override +@@ -68,6 +70,7 @@ + return 0; + } else { + int i = this.spawnChance; ++ + this.spawnChance = Mth.clamp(this.spawnChance + 25, 25, 75); + this.serverLevelData.setWanderingTraderSpawnChance(this.spawnChance); + if (this.random.nextInt(100) > i) { +@@ -84,33 +87,40 @@ + } + + private boolean spawn(ServerLevel serverLevel) { +- Player randomPlayer = serverLevel.getRandomPlayer(); +- if (randomPlayer == null) { ++ ServerPlayer entityplayer = serverLevel.getRandomPlayer(); ++ ++ if (entityplayer == null) { + return true; + } else if (this.random.nextInt(10) != 0) { + return false; + } else { +- BlockPos blockPos = randomPlayer.blockPosition(); +- int i = 48; +- PoiManager poiManager = serverLevel.getPoiManager(); +- Optional optional = poiManager.find(holder -> holder.is(PoiTypes.MEETING), blockPos3 -> true, blockPos, 48, PoiManager.Occupancy.ANY); +- BlockPos blockPos1 = optional.orElse(blockPos); +- BlockPos blockPos2 = this.findSpawnPositionNear(serverLevel, blockPos1, 48); +- if (blockPos2 != null && this.hasEnoughSpace(serverLevel, blockPos2)) { +- if (serverLevel.getBiome(blockPos2).is(BiomeTags.WITHOUT_WANDERING_TRADER_SPAWNS)) { ++ BlockPos blockposition = entityplayer.blockPosition(); ++ boolean flag = true; ++ PoiManager villageplace = serverLevel.getPoiManager(); ++ Optional optional = villageplace.find((holder) -> { ++ return holder.is(PoiTypes.MEETING); ++ }, (blockposition1) -> { ++ return true; ++ }, blockposition, 48, PoiManager.Occupancy.ANY); ++ BlockPos blockposition1 = (BlockPos) optional.orElse(blockposition); ++ BlockPos blockposition2 = this.findSpawnPositionNear(serverLevel, blockposition1, 48); ++ ++ if (blockposition2 != null && this.hasEnoughSpace(serverLevel, blockposition2)) { ++ if (serverLevel.getBiome(blockposition2).is(BiomeTags.WITHOUT_WANDERING_TRADER_SPAWNS)) { + return false; + } + +- WanderingTrader wanderingTrader = EntityType.WANDERING_TRADER.spawn(serverLevel, blockPos2, MobSpawnType.EVENT); +- if (wanderingTrader != null) { +- for (int i1 = 0; i1 < 2; i1++) { +- this.tryToSpawnLlamaFor(serverLevel, wanderingTrader, 4); ++ WanderingTrader entityvillagertrader = (WanderingTrader) EntityType.WANDERING_TRADER.spawn(serverLevel, blockposition2, EnumMobSpawn.EVENT, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit ++ ++ if (entityvillagertrader != null) { ++ for (int i = 0; i < 2; ++i) { ++ this.tryToSpawnLlamaFor(serverLevel, entityvillagertrader, 4); + } + +- this.serverLevelData.setWanderingTraderId(wanderingTrader.getUUID()); +- wanderingTrader.setDespawnDelay(48000); +- wanderingTrader.setWanderTarget(blockPos1); +- wanderingTrader.restrictTo(blockPos1, 16); ++ this.serverLevelData.setWanderingTraderId(entityvillagertrader.getUUID()); ++ // entityvillagertrader.setDespawnDelay(48000); // CraftBukkit - moved to EntityVillagerTrader constructor. This lets the value be modified by plugins on CreatureSpawnEvent ++ entityvillagertrader.setWanderTarget(blockposition1); ++ entityvillagertrader.restrictTo(blockposition1, 16); + return true; + } + } +@@ -120,40 +130,49 @@ + } + + private void tryToSpawnLlamaFor(ServerLevel serverLevel, WanderingTrader trader, int maxDistance) { +- BlockPos blockPos = this.findSpawnPositionNear(serverLevel, trader.blockPosition(), maxDistance); +- if (blockPos != null) { +- TraderLlama traderLlama = EntityType.TRADER_LLAMA.spawn(serverLevel, blockPos, MobSpawnType.EVENT); +- if (traderLlama != null) { +- traderLlama.setLeashedTo(trader, true); ++ BlockPos blockposition = this.findSpawnPositionNear(serverLevel, trader.blockPosition(), maxDistance); ++ ++ if (blockposition != null) { ++ TraderLlama entityllamatrader = (TraderLlama) EntityType.TRADER_LLAMA.spawn(serverLevel, blockposition, EnumMobSpawn.EVENT, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit ++ ++ if (entityllamatrader != null) { ++ entityllamatrader.setLeashedTo(trader, true); + } + } + } + + @Nullable + private BlockPos findSpawnPositionNear(LevelReader level, BlockPos pos, int maxDistance) { +- BlockPos blockPos = null; ++ BlockPos blockposition1 = null; + +- for (int i = 0; i < 10; i++) { +- int i1 = pos.getX() + this.random.nextInt(maxDistance * 2) - maxDistance; +- int i2 = pos.getZ() + this.random.nextInt(maxDistance * 2) - maxDistance; +- int height = level.getHeight(Heightmap.Types.WORLD_SURFACE, i1, i2); +- BlockPos blockPos1 = new BlockPos(i1, height, i2); +- if (NaturalSpawner.isSpawnPositionOk(SpawnPlacements.Type.ON_GROUND, level, blockPos1, EntityType.WANDERING_TRADER)) { +- blockPos = blockPos1; ++ for (int j = 0; j < 10; ++j) { ++ int k = pos.getX() + this.random.nextInt(maxDistance * 2) - maxDistance; ++ int l = pos.getZ() + this.random.nextInt(maxDistance * 2) - maxDistance; ++ int i1 = level.getHeight(Heightmap.Types.WORLD_SURFACE, k, l); ++ BlockPos blockposition2 = new BlockPos(k, i1, l); ++ ++ if (NaturalSpawner.isSpawnPositionOk(SpawnPlacements.Surface.ON_GROUND, level, blockposition2, EntityType.WANDERING_TRADER)) { ++ blockposition1 = blockposition2; + break; + } + } + +- return blockPos; ++ return blockposition1; + } + + private boolean hasEnoughSpace(BlockGetter level, BlockPos pos) { +- for (BlockPos blockPos : BlockPos.betweenClosed(pos, pos.offset(1, 2, 1))) { +- if (!level.getBlockState(blockPos).getCollisionShape(level, blockPos).isEmpty()) { +- return false; ++ Iterator iterator = BlockPos.betweenClosed(pos, pos.offset(1, 2, 1)).iterator(); ++ ++ BlockPos blockposition1; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return true; + } +- } + +- return true; ++ blockposition1 = (BlockPos) iterator.next(); ++ } while (level.getBlockState(blockposition1).getCollisionShape(level, blockposition1).isEmpty()); ++ ++ return false; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/player/Inventory.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/player/Inventory.java.patch new file mode 100644 index 0000000000..6636cdbc35 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/player/Inventory.java.patch @@ -0,0 +1,930 @@ +--- a/net/minecraft/world/entity/player/Inventory.java ++++ b/net/minecraft/world/entity/player/Inventory.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.entity.player; + + import com.google.common.collect.ImmutableList; ++import java.util.Iterator; + import java.util.List; + import java.util.function.Predicate; + import net.minecraft.CrashReport; +@@ -16,15 +17,24 @@ + import net.minecraft.tags.TagKey; + import net.minecraft.world.Container; + import net.minecraft.world.ContainerHelper; +-import net.minecraft.world.Nameable; ++import net.minecraft.world.INamableTileEntity; + import net.minecraft.world.damagesource.DamageSource; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.item.ArmorItem; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + +-public class Inventory implements Container, Nameable { ++// CraftBukkit start ++import java.util.ArrayList; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ ++public class Inventory implements Container, INamableTileEntity { ++ + public static final int POP_TIME_DURATION = 5; + public static final int INVENTORY_SIZE = 36; + private static final int SELECTION_SIZE = 9; +@@ -32,20 +42,72 @@ + public static final int NOT_FOUND_INDEX = -1; + public static final int[] ALL_ARMOR_SLOTS = new int[]{0, 1, 2, 3}; + public static final int[] HELMET_SLOT_ONLY = new int[]{3}; +- public final NonNullList items = NonNullList.withSize(36, ItemStack.EMPTY); +- public final NonNullList armor = NonNullList.withSize(4, ItemStack.EMPTY); +- public final NonNullList offhand = NonNullList.withSize(1, ItemStack.EMPTY); +- private final List> compartments = ImmutableList.of(this.items, this.armor, this.offhand); ++ public final NonNullList items; ++ public final NonNullList armor; ++ public final NonNullList offhand; ++ private final List> compartments; + public int selected; + public final Player player; + private int timesChanged; + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ List combined = new ArrayList(items.size() + armor.size() + offhand.size()); ++ for (List sub : this.compartments) { ++ combined.addAll(sub); ++ } ++ ++ return combined; ++ } ++ ++ public List getArmorContents() { ++ return this.armor; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return this.player.getBukkitEntity(); ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return player.getBukkitEntity().getLocation(); ++ } ++ // CraftBukkit end ++ + public Inventory(Player player) { ++ this.items = NonNullList.withSize(36, ItemStack.EMPTY); ++ this.armor = NonNullList.withSize(4, ItemStack.EMPTY); ++ this.offhand = NonNullList.withSize(1, ItemStack.EMPTY); ++ this.compartments = ImmutableList.of(this.items, this.armor, this.offhand); + this.player = player; + } + + public ItemStack getSelected() { +- return isHotbarSlot(this.selected) ? this.items.get(this.selected) : ItemStack.EMPTY; ++ return isHotbarSlot(this.selected) ? (ItemStack) this.items.get(this.selected) : ItemStack.EMPTY; + } + + public static int getSelectionSize() { +@@ -53,16 +115,34 @@ + } + + private boolean hasRemainingSpaceForItem(ItemStack destination, ItemStack origin) { +- return !destination.isEmpty() +- && ItemStack.isSameItemSameTags(destination, origin) +- && destination.isStackable() +- && destination.getCount() < destination.getMaxStackSize() +- && destination.getCount() < this.getMaxStackSize(); ++ return !destination.isEmpty() && ItemStack.isSameItemSameTags(destination, origin) && destination.isStackable() && destination.getCount() < destination.getMaxStackSize() && destination.getCount() < this.getMaxStackSize(); + } + ++ // CraftBukkit start - Watch method above! :D ++ public int canHold(ItemStack itemstack) { ++ int remains = itemstack.getCount(); ++ for (int i = 0; i < this.items.size(); ++i) { ++ ItemStack itemstack1 = this.getItem(i); ++ if (itemstack1.isEmpty()) return itemstack.getCount(); ++ ++ if (this.hasRemainingSpaceForItem(itemstack1, itemstack)) { ++ remains -= (itemstack1.getMaxStackSize() < this.getMaxStackSize() ? itemstack1.getMaxStackSize() : this.getMaxStackSize()) - itemstack1.getCount(); ++ } ++ if (remains <= 0) return itemstack.getCount(); ++ } ++ ItemStack offhandItemStack = this.getItem(this.items.size() + this.armor.size()); ++ if (this.hasRemainingSpaceForItem(offhandItemStack, itemstack)) { ++ remains -= (offhandItemStack.getMaxStackSize() < this.getMaxStackSize() ? offhandItemStack.getMaxStackSize() : this.getMaxStackSize()) - offhandItemStack.getCount(); ++ } ++ if (remains <= 0) return itemstack.getCount(); ++ ++ return itemstack.getCount() - remains; ++ } ++ // CraftBukkit end ++ + public int getFreeSlot() { +- for (int i = 0; i < this.items.size(); i++) { +- if (this.items.get(i).isEmpty()) { ++ for (int i = 0; i < this.items.size(); ++i) { ++ if (((ItemStack) this.items.get(i)).isEmpty()) { + return i; + } + } +@@ -72,15 +152,17 @@ + + public void setPickedItem(ItemStack stack) { + int i = this.findSlotMatchingItem(stack); ++ + if (isHotbarSlot(i)) { + this.selected = i; + } else { + if (i == -1) { + this.selected = this.getSuitableHotbarSlot(); +- if (!this.items.get(this.selected).isEmpty()) { +- int freeSlot = this.getFreeSlot(); +- if (freeSlot != -1) { +- this.items.set(freeSlot, this.items.get(this.selected)); ++ if (!((ItemStack) this.items.get(this.selected)).isEmpty()) { ++ int j = this.getFreeSlot(); ++ ++ if (j != -1) { ++ this.items.set(j, (ItemStack) this.items.get(this.selected)); + } + } + +@@ -88,14 +170,16 @@ + } else { + this.pickSlot(i); + } ++ + } + } + + public void pickSlot(int index) { + this.selected = this.getSuitableHotbarSlot(); +- ItemStack itemStack = this.items.get(this.selected); +- this.items.set(this.selected, this.items.get(index)); +- this.items.set(index, itemStack); ++ ItemStack itemstack = (ItemStack) this.items.get(this.selected); ++ ++ this.items.set(this.selected, (ItemStack) this.items.get(index)); ++ this.items.set(index, itemstack); + } + + public static boolean isHotbarSlot(int index) { +@@ -103,8 +187,8 @@ + } + + public int findSlotMatchingItem(ItemStack stack) { +- for (int i = 0; i < this.items.size(); i++) { +- if (!this.items.get(i).isEmpty() && ItemStack.isSameItemSameTags(stack, this.items.get(i))) { ++ for (int i = 0; i < this.items.size(); ++i) { ++ if (!((ItemStack) this.items.get(i)).isEmpty() && ItemStack.isSameItemSameTags(stack, (ItemStack) this.items.get(i))) { + return i; + } + } +@@ -113,13 +197,10 @@ + } + + public int findSlotMatchingUnusedItem(ItemStack stack) { +- for (int i = 0; i < this.items.size(); i++) { +- ItemStack itemStack = this.items.get(i); +- if (!this.items.get(i).isEmpty() +- && ItemStack.isSameItemSameTags(stack, this.items.get(i)) +- && !this.items.get(i).isDamaged() +- && !itemStack.isEnchanted() +- && !itemStack.hasCustomHoverName()) { ++ for (int i = 0; i < this.items.size(); ++i) { ++ ItemStack itemstack1 = (ItemStack) this.items.get(i); ++ ++ if (!((ItemStack) this.items.get(i)).isEmpty() && ItemStack.isSameItemSameTags(stack, (ItemStack) this.items.get(i)) && !((ItemStack) this.items.get(i)).isDamaged() && !itemstack1.isEnchanted() && !itemstack1.hasCustomHoverName()) { + return i; + } + } +@@ -128,17 +209,20 @@ + } + + public int getSuitableHotbarSlot() { +- for (int i = 0; i < 9; i++) { +- int i1 = (this.selected + i) % 9; +- if (this.items.get(i1).isEmpty()) { +- return i1; ++ int i; ++ int j; ++ ++ for (j = 0; j < 9; ++j) { ++ i = (this.selected + j) % 9; ++ if (((ItemStack) this.items.get(i)).isEmpty()) { ++ return i; + } + } + +- for (int ix = 0; ix < 9; ix++) { +- int i1 = (this.selected + ix) % 9; +- if (!this.items.get(i1).isEnchanted()) { +- return i1; ++ for (j = 0; j < 9; ++j) { ++ i = (this.selected + j) % 9; ++ if (!((ItemStack) this.items.get(i)).isEnchanted()) { ++ return i; + } + } + +@@ -146,70 +230,75 @@ + } + + public void swapPaint(double direction) { +- int i = (int)Math.signum(direction); +- this.selected -= i; ++ int i = (int) Math.signum(direction); + +- while (this.selected < 0) { +- this.selected += 9; ++ for (this.selected -= i; this.selected < 0; this.selected += 9) { ++ ; + } + + while (this.selected >= 9) { + this.selected -= 9; + } ++ + } + + public int clearOrCountMatchingItems(Predicate stackPredicate, int maxCount, Container inventory) { +- int i = 0; ++ byte b0 = 0; + boolean flag = maxCount == 0; +- i += ContainerHelper.clearOrCountMatchingItems(this, stackPredicate, maxCount - i, flag); +- i += ContainerHelper.clearOrCountMatchingItems(inventory, stackPredicate, maxCount - i, flag); +- ItemStack carried = this.player.containerMenu.getCarried(); +- int var9 = i + ContainerHelper.clearOrCountMatchingItems(carried, stackPredicate, maxCount - i, flag); +- if (carried.isEmpty()) { ++ int j = b0 + ContainerHelper.clearOrCountMatchingItems((Container) this, stackPredicate, maxCount - b0, flag); ++ ++ j += ContainerHelper.clearOrCountMatchingItems(inventory, stackPredicate, maxCount - j, flag); ++ ItemStack itemstack = this.player.containerMenu.getCarried(); ++ ++ j += ContainerHelper.clearOrCountMatchingItems(itemstack, stackPredicate, maxCount - j, flag); ++ if (itemstack.isEmpty()) { + this.player.containerMenu.setCarried(ItemStack.EMPTY); + } + +- return var9; ++ return j; + } + + private int addResource(ItemStack stack) { +- int slotWithRemainingSpace = this.getSlotWithRemainingSpace(stack); +- if (slotWithRemainingSpace == -1) { +- slotWithRemainingSpace = this.getFreeSlot(); ++ int i = this.getSlotWithRemainingSpace(stack); ++ ++ if (i == -1) { ++ i = this.getFreeSlot(); + } + +- return slotWithRemainingSpace == -1 ? stack.getCount() : this.addResource(slotWithRemainingSpace, stack); ++ return i == -1 ? stack.getCount() : this.addResource(i, stack); + } + + private int addResource(int slot, ItemStack stack) { + Item item = stack.getItem(); +- int count = stack.getCount(); +- ItemStack item1 = this.getItem(slot); +- if (item1.isEmpty()) { +- item1 = new ItemStack(item, 0); ++ int j = stack.getCount(); ++ ItemStack itemstack1 = this.getItem(slot); ++ ++ if (itemstack1.isEmpty()) { ++ itemstack1 = new ItemStack(item, 0); + if (stack.hasTag()) { +- item1.setTag(stack.getTag().copy()); ++ itemstack1.setTag(stack.getTag().copy()); + } + +- this.setItem(slot, item1); ++ this.setItem(slot, itemstack1); + } + +- int i = count; +- if (count > item1.getMaxStackSize() - item1.getCount()) { +- i = item1.getMaxStackSize() - item1.getCount(); ++ int k = j; ++ ++ if (j > itemstack1.getMaxStackSize() - itemstack1.getCount()) { ++ k = itemstack1.getMaxStackSize() - itemstack1.getCount(); + } + +- if (i > this.getMaxStackSize() - item1.getCount()) { +- i = this.getMaxStackSize() - item1.getCount(); ++ if (k > this.getMaxStackSize() - itemstack1.getCount()) { ++ k = this.getMaxStackSize() - itemstack1.getCount(); + } + +- if (i == 0) { +- return count; ++ if (k == 0) { ++ return j; + } else { +- count -= i; +- item1.grow(i); +- item1.setPopTime(5); +- return count; ++ j -= k; ++ itemstack1.grow(k); ++ itemstack1.setPopTime(5); ++ return j; + } + } + +@@ -219,8 +308,8 @@ + } else if (this.hasRemainingSpaceForItem(this.getItem(40), stack)) { + return 40; + } else { +- for (int i = 0; i < this.items.size(); i++) { +- if (this.hasRemainingSpaceForItem(this.items.get(i), stack)) { ++ for (int i = 0; i < this.items.size(); ++i) { ++ if (this.hasRemainingSpaceForItem((ItemStack) this.items.get(i), stack)) { + return i; + } + } +@@ -230,13 +319,18 @@ + } + + public void tick() { +- for (NonNullList list : this.compartments) { +- for (int i = 0; i < list.size(); i++) { +- if (!list.get(i).isEmpty()) { +- list.get(i).inventoryTick(this.player.level(), this.player, i, this.selected == i); ++ Iterator iterator = this.compartments.iterator(); ++ ++ while (iterator.hasNext()) { ++ NonNullList nonnulllist = (NonNullList) iterator.next(); ++ ++ for (int i = 0; i < nonnulllist.size(); ++i) { ++ if (!((ItemStack) nonnulllist.get(i)).isEmpty()) { ++ ((ItemStack) nonnulllist.get(i)).inventoryTick(this.player.level(), this.player, i, this.selected == i); + } + } + } ++ + } + + public boolean add(ItemStack stack) { +@@ -255,7 +349,7 @@ + + if (slot >= 0) { + this.items.set(slot, stack.copyAndClear()); +- this.items.get(slot).setPopTime(5); ++ ((ItemStack) this.items.get(slot)).setPopTime(5); + return true; + } else if (this.player.getAbilities().instabuild) { + stack.setCount(0); +@@ -264,30 +358,34 @@ + return false; + } + } else { +- int count; ++ int j; ++ + do { +- count = stack.getCount(); ++ j = stack.getCount(); + if (slot == -1) { + stack.setCount(this.addResource(stack)); + } else { + stack.setCount(this.addResource(slot, stack)); + } +- } while (!stack.isEmpty() && stack.getCount() < count); ++ } while (!stack.isEmpty() && stack.getCount() < j); + +- if (stack.getCount() == count && this.player.getAbilities().instabuild) { ++ if (stack.getCount() == j && this.player.getAbilities().instabuild) { + stack.setCount(0); + return true; + } else { +- return stack.getCount() < count; ++ return stack.getCount() < j; + } + } +- } catch (Throwable var6) { +- CrashReport crashReport = CrashReport.forThrowable(var6, "Adding item to inventory"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Item being added"); +- crashReportCategory.setDetail("Item ID", Item.getId(stack.getItem())); +- crashReportCategory.setDetail("Item data", stack.getDamageValue()); +- crashReportCategory.setDetail("Item name", () -> stack.getHoverName().getString()); +- throw new ReportedException(crashReport); ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Adding item to inventory"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Item being added"); ++ ++ crashreportsystemdetails.setDetail("Item ID", (Object) Item.getId(stack.getItem())); ++ crashreportsystemdetails.setDetail("Item data", (Object) stack.getDamageValue()); ++ crashreportsystemdetails.setDetail("Item name", () -> { ++ return stack.getHoverName().getString(); ++ }); ++ throw new ReportedException(crashreport); + } + } + } +@@ -297,23 +395,27 @@ + } + + public void placeItemBackInInventory(ItemStack stack, boolean sendPacket) { +- while (!stack.isEmpty()) { +- int slotWithRemainingSpace = this.getSlotWithRemainingSpace(stack); +- if (slotWithRemainingSpace == -1) { +- slotWithRemainingSpace = this.getFreeSlot(); +- } ++ while (true) { ++ if (!stack.isEmpty()) { ++ int i = this.getSlotWithRemainingSpace(stack); + +- if (slotWithRemainingSpace == -1) { ++ if (i == -1) { ++ i = this.getFreeSlot(); ++ } ++ ++ if (i != -1) { ++ int j = stack.getMaxStackSize() - this.getItem(i).getCount(); ++ ++ if (this.add(i, stack.split(j)) && sendPacket && this.player instanceof ServerPlayer) { ++ ((ServerPlayer) this.player).connection.send(new ClientboundContainerSetSlotPacket(-2, 0, i, this.getItem(i))); ++ } ++ continue; ++ } ++ + this.player.drop(stack, false); +- break; + } + +- int i = stack.getMaxStackSize() - this.getItem(slotWithRemainingSpace).getCount(); +- if (this.add(slotWithRemainingSpace, stack.split(i)) && sendPacket && this.player instanceof ServerPlayer) { +- ((ServerPlayer)this.player) +- .connection +- .send(new ClientboundContainerSetSlotPacket(-2, 0, slotWithRemainingSpace, this.getItem(slotWithRemainingSpace))); +- } ++ return; + } + } + +@@ -321,46 +423,54 @@ + public ItemStack removeItem(int index, int count) { + List list = null; + +- for (NonNullList list1 : this.compartments) { +- if (index < list1.size()) { +- list = list1; ++ NonNullList nonnulllist; ++ ++ for (Iterator iterator = this.compartments.iterator(); iterator.hasNext(); index -= nonnulllist.size()) { ++ nonnulllist = (NonNullList) iterator.next(); ++ if (index < nonnulllist.size()) { ++ list = nonnulllist; + break; + } +- +- index -= list1.size(); + } + +- return list != null && !list.get(index).isEmpty() ? ContainerHelper.removeItem(list, index, count) : ItemStack.EMPTY; ++ return list != null && !((ItemStack) list.get(index)).isEmpty() ? ContainerHelper.removeItem(list, index, count) : ItemStack.EMPTY; + } + + public void removeItem(ItemStack stack) { +- for (NonNullList list : this.compartments) { +- for (int i = 0; i < list.size(); i++) { +- if (list.get(i) == stack) { +- list.set(i, ItemStack.EMPTY); ++ Iterator iterator = this.compartments.iterator(); ++ ++ while (iterator.hasNext()) { ++ NonNullList nonnulllist = (NonNullList) iterator.next(); ++ ++ for (int i = 0; i < nonnulllist.size(); ++i) { ++ if (nonnulllist.get(i) == stack) { ++ nonnulllist.set(i, ItemStack.EMPTY); + break; + } + } + } ++ + } + + @Override + public ItemStack removeItemNoUpdate(int index) { +- NonNullList list = null; ++ NonNullList nonnulllist = null; + +- for (NonNullList list1 : this.compartments) { +- if (index < list1.size()) { +- list = list1; ++ NonNullList nonnulllist1; ++ ++ for (Iterator iterator = this.compartments.iterator(); iterator.hasNext(); index -= nonnulllist1.size()) { ++ nonnulllist1 = (NonNullList) iterator.next(); ++ if (index < nonnulllist1.size()) { ++ nonnulllist = nonnulllist1; + break; + } +- +- index -= list1.size(); + } + +- if (list != null && !list.get(index).isEmpty()) { +- ItemStack itemStack = list.get(index); +- list.set(index, ItemStack.EMPTY); +- return itemStack; ++ if (nonnulllist != null && !((ItemStack) nonnulllist.get(index)).isEmpty()) { ++ ItemStack itemstack = (ItemStack) nonnulllist.get(index); ++ ++ nonnulllist.set(index, ItemStack.EMPTY); ++ return itemstack; + } else { + return ItemStack.EMPTY; + } +@@ -368,51 +478,56 @@ + + @Override + public void setItem(int index, ItemStack stack) { +- NonNullList list = null; ++ NonNullList nonnulllist = null; + +- for (NonNullList list1 : this.compartments) { +- if (index < list1.size()) { +- list = list1; ++ NonNullList nonnulllist1; ++ ++ for (Iterator iterator = this.compartments.iterator(); iterator.hasNext(); index -= nonnulllist1.size()) { ++ nonnulllist1 = (NonNullList) iterator.next(); ++ if (index < nonnulllist1.size()) { ++ nonnulllist = nonnulllist1; + break; + } +- +- index -= list1.size(); + } + +- if (list != null) { +- list.set(index, stack); ++ if (nonnulllist != null) { ++ nonnulllist.set(index, stack); + } ++ + } + +- public float getDestroySpeed(BlockState state) { +- return this.items.get(this.selected).getDestroySpeed(state); ++ public float getDestroySpeed(IBlockData state) { ++ return ((ItemStack) this.items.get(this.selected)).getDestroySpeed(state); + } + + public ListTag save(ListTag listTag) { +- for (int i = 0; i < this.items.size(); i++) { +- if (!this.items.get(i).isEmpty()) { +- CompoundTag compoundTag = new CompoundTag(); +- compoundTag.putByte("Slot", (byte)i); +- this.items.get(i).save(compoundTag); +- listTag.add(compoundTag); ++ CompoundTag nbttagcompound; ++ int i; ++ ++ for (i = 0; i < this.items.size(); ++i) { ++ if (!((ItemStack) this.items.get(i)).isEmpty()) { ++ nbttagcompound = new CompoundTag(); ++ nbttagcompound.putByte("Slot", (byte) i); ++ ((ItemStack) this.items.get(i)).save(nbttagcompound); ++ listTag.add(nbttagcompound); + } + } + +- for (int ix = 0; ix < this.armor.size(); ix++) { +- if (!this.armor.get(ix).isEmpty()) { +- CompoundTag compoundTag = new CompoundTag(); +- compoundTag.putByte("Slot", (byte)(ix + 100)); +- this.armor.get(ix).save(compoundTag); +- listTag.add(compoundTag); ++ for (i = 0; i < this.armor.size(); ++i) { ++ if (!((ItemStack) this.armor.get(i)).isEmpty()) { ++ nbttagcompound = new CompoundTag(); ++ nbttagcompound.putByte("Slot", (byte) (i + 100)); ++ ((ItemStack) this.armor.get(i)).save(nbttagcompound); ++ listTag.add(nbttagcompound); + } + } + +- for (int ixx = 0; ixx < this.offhand.size(); ixx++) { +- if (!this.offhand.get(ixx).isEmpty()) { +- CompoundTag compoundTag = new CompoundTag(); +- compoundTag.putByte("Slot", (byte)(ixx + 150)); +- this.offhand.get(ixx).save(compoundTag); +- listTag.add(compoundTag); ++ for (i = 0; i < this.offhand.size(); ++i) { ++ if (!((ItemStack) this.offhand.get(i)).isEmpty()) { ++ nbttagcompound = new CompoundTag(); ++ nbttagcompound.putByte("Slot", (byte) (i + 150)); ++ ((ItemStack) this.offhand.get(i)).save(nbttagcompound); ++ listTag.add(nbttagcompound); + } + } + +@@ -424,20 +539,22 @@ + this.armor.clear(); + this.offhand.clear(); + +- for (int i = 0; i < listTag.size(); i++) { +- CompoundTag compound = listTag.getCompound(i); +- int i1 = compound.getByte("Slot") & 255; +- ItemStack itemStack = ItemStack.of(compound); +- if (!itemStack.isEmpty()) { +- if (i1 >= 0 && i1 < this.items.size()) { +- this.items.set(i1, itemStack); +- } else if (i1 >= 100 && i1 < this.armor.size() + 100) { +- this.armor.set(i1 - 100, itemStack); +- } else if (i1 >= 150 && i1 < this.offhand.size() + 150) { +- this.offhand.set(i1 - 150, itemStack); ++ for (int i = 0; i < listTag.size(); ++i) { ++ CompoundTag nbttagcompound = listTag.getCompound(i); ++ int j = nbttagcompound.getByte("Slot") & 255; ++ ItemStack itemstack = ItemStack.of(nbttagcompound); ++ ++ if (!itemstack.isEmpty()) { ++ if (j >= 0 && j < this.items.size()) { ++ this.items.set(j, itemstack); ++ } else if (j >= 100 && j < this.armor.size() + 100) { ++ this.armor.set(j - 100, itemstack); ++ } else if (j >= 150 && j < this.offhand.size() + 150) { ++ this.offhand.set(j - 150, itemstack); + } + } + } ++ + } + + @Override +@@ -447,41 +564,56 @@ + + @Override + public boolean isEmpty() { +- for (ItemStack itemStack : this.items) { +- if (!itemStack.isEmpty()) { +- return false; +- } +- } ++ Iterator iterator = this.items.iterator(); + +- for (ItemStack itemStackx : this.armor) { +- if (!itemStackx.isEmpty()) { +- return false; +- } +- } ++ ItemStack itemstack; + +- for (ItemStack itemStackxx : this.offhand) { +- if (!itemStackxx.isEmpty()) { ++ do { ++ if (!iterator.hasNext()) { ++ iterator = this.armor.iterator(); ++ ++ do { ++ if (!iterator.hasNext()) { ++ iterator = this.offhand.iterator(); ++ ++ do { ++ if (!iterator.hasNext()) { ++ return true; ++ } ++ ++ itemstack = (ItemStack) iterator.next(); ++ } while (itemstack.isEmpty()); ++ ++ return false; ++ } ++ ++ itemstack = (ItemStack) iterator.next(); ++ } while (itemstack.isEmpty()); ++ + return false; + } +- } + +- return true; ++ itemstack = (ItemStack) iterator.next(); ++ } while (itemstack.isEmpty()); ++ ++ return false; + } + + @Override + public ItemStack getItem(int index) { + List list = null; + +- for (NonNullList list1 : this.compartments) { +- if (index < list1.size()) { +- list = list1; ++ NonNullList nonnulllist; ++ ++ for (Iterator iterator = this.compartments.iterator(); iterator.hasNext(); index -= nonnulllist.size()) { ++ nonnulllist = (NonNullList) iterator.next(); ++ if (index < nonnulllist.size()) { ++ list = nonnulllist; + break; + } +- +- index -= list1.size(); + } + +- return list == null ? ItemStack.EMPTY : list.get(index); ++ return list == null ? ItemStack.EMPTY : (ItemStack) list.get(index); + } + + @Override +@@ -490,42 +622,54 @@ + } + + public ItemStack getArmor(int slot) { +- return this.armor.get(slot); ++ return (ItemStack) this.armor.get(slot); + } + + public void hurtArmor(DamageSource source, float damage, int[] armorPieces) { +- if (!(damage <= 0.0F)) { +- float var9 = damage / 4.0F; +- if (var9 < 1.0F) { +- var9 = 1.0F; ++ if (damage > 0.0F) { ++ damage /= 4.0F; ++ if (damage < 1.0F) { ++ damage = 1.0F; + } + +- for (int i : armorPieces) { +- ItemStack itemStack = this.armor.get(i); +- if ((!source.is(DamageTypeTags.IS_FIRE) || !itemStack.getItem().isFireResistant()) && itemStack.getItem() instanceof ArmorItem) { +- itemStack.hurtAndBreak( +- (int)var9, this.player, entity -> entity.broadcastBreakEvent(EquipmentSlot.byTypeAndIndex(EquipmentSlot.Type.ARMOR, i)) +- ); ++ int[] aint1 = armorPieces; ++ int i = armorPieces.length; ++ ++ for (int j = 0; j < i; ++j) { ++ int k = aint1[j]; ++ ItemStack itemstack = (ItemStack) this.armor.get(k); ++ ++ if ((!source.is(DamageTypeTags.IS_FIRE) || !itemstack.getItem().isFireResistant()) && itemstack.getItem() instanceof ArmorItem) { ++ itemstack.hurtAndBreak((int) damage, this.player, (entityhuman) -> { ++ entityhuman.broadcastBreakEvent(EquipmentSlot.byTypeAndIndex(EquipmentSlot.Function.ARMOR, k)); ++ }); + } + } ++ + } + } + + public void dropAll() { +- for (List list : this.compartments) { +- for (int i = 0; i < list.size(); i++) { +- ItemStack itemStack = list.get(i); +- if (!itemStack.isEmpty()) { +- this.player.drop(itemStack, true, false); ++ Iterator iterator = this.compartments.iterator(); ++ ++ while (iterator.hasNext()) { ++ List list = (List) iterator.next(); ++ ++ for (int i = 0; i < list.size(); ++i) { ++ ItemStack itemstack = (ItemStack) list.get(i); ++ ++ if (!itemstack.isEmpty()) { ++ this.player.drop(itemstack, true, false); + list.set(i, ItemStack.EMPTY); + } + } + } ++ + } + + @Override + public void setChanged() { +- this.timesChanged++; ++ ++this.timesChanged; + } + + public int getTimesChanged() { +@@ -534,13 +678,20 @@ + + @Override + public boolean stillValid(Player player) { +- return !this.player.isRemoved() && !(player.distanceToSqr(this.player) > 64.0); ++ return this.player.isRemoved() ? false : player.distanceToSqr((Entity) this.player) <= 64.0D; + } + + public boolean contains(ItemStack stack) { +- for (List list : this.compartments) { +- for (ItemStack itemStack : list) { +- if (!itemStack.isEmpty() && ItemStack.isSameItemSameTags(itemStack, stack)) { ++ Iterator iterator = this.compartments.iterator(); ++ ++ while (iterator.hasNext()) { ++ List list = (List) iterator.next(); ++ Iterator iterator1 = list.iterator(); ++ ++ while (iterator1.hasNext()) { ++ ItemStack itemstack1 = (ItemStack) iterator1.next(); ++ ++ if (!itemstack1.isEmpty() && ItemStack.isSameItemSameTags(itemstack1, stack)) { + return true; + } + } +@@ -550,9 +701,16 @@ + } + + public boolean contains(TagKey tag) { +- for (List list : this.compartments) { +- for (ItemStack itemStack : list) { +- if (!itemStack.isEmpty() && itemStack.is(tag)) { ++ Iterator iterator = this.compartments.iterator(); ++ ++ while (iterator.hasNext()) { ++ List list = (List) iterator.next(); ++ Iterator iterator1 = list.iterator(); ++ ++ while (iterator1.hasNext()) { ++ ItemStack itemstack = (ItemStack) iterator1.next(); ++ ++ if (!itemstack.isEmpty() && itemstack.is(tag)) { + return true; + } + } +@@ -562,7 +720,7 @@ + } + + public void replaceWith(Inventory playerInventory) { +- for (int i = 0; i < this.getContainerSize(); i++) { ++ for (int i = 0; i < this.getContainerSize(); ++i) { + this.setItem(i, playerInventory.getItem(i)); + } + +@@ -571,19 +729,30 @@ + + @Override + public void clearContent() { +- for (List list : this.compartments) { ++ Iterator iterator = this.compartments.iterator(); ++ ++ while (iterator.hasNext()) { ++ List list = (List) iterator.next(); ++ + list.clear(); + } ++ + } + + public void fillStackedContents(StackedContents stackedContent) { +- for (ItemStack itemStack : this.items) { +- stackedContent.accountSimpleStack(itemStack); ++ Iterator iterator = this.items.iterator(); ++ ++ while (iterator.hasNext()) { ++ ItemStack itemstack = (ItemStack) iterator.next(); ++ ++ stackedContent.accountSimpleStack(itemstack); + } ++ + } + + public ItemStack removeFromSelected(boolean removeStack) { +- ItemStack selected = this.getSelected(); +- return selected.isEmpty() ? ItemStack.EMPTY : this.removeItem(this.selected, removeStack ? selected.getCount() : 1); ++ ItemStack itemstack = this.getSelected(); ++ ++ return itemstack.isEmpty() ? ItemStack.EMPTY : this.removeItem(this.selected, removeStack ? itemstack.getCount() : 1); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/player/Player.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/player/Player.java.patch new file mode 100644 index 0000000000..ed43de2db3 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/player/Player.java.patch @@ -0,0 +1,2421 @@ +--- a/net/minecraft/world/entity/player/Player.java ++++ b/net/minecraft/world/entity/player/Player.java +@@ -6,9 +6,12 @@ + import com.mojang.authlib.GameProfile; + import com.mojang.datafixers.util.Either; + import com.mojang.logging.LogUtils; ++import com.mojang.serialization.DataResult; + import java.util.Collection; ++import java.util.Iterator; + import java.util.List; + import java.util.Map; ++import java.util.Objects; + import java.util.Optional; + import java.util.OptionalInt; + import java.util.function.Predicate; +@@ -29,7 +32,6 @@ + import net.minecraft.network.chat.ClickEvent; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.MutableComponent; +-import net.minecraft.network.chat.Style; + import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; +@@ -49,23 +51,23 @@ + import net.minecraft.util.Unit; + import net.minecraft.world.Container; + import net.minecraft.world.Difficulty; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; ++import net.minecraft.world.ITileInventory; + import net.minecraft.world.InteractionResult; +-import net.minecraft.world.MenuProvider; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.effect.MobEffectUtil; + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMonsterType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.HumanoidArm; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.SlotAccess; + import net.minecraft.world.entity.TamableAnimal; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -102,17 +104,27 @@ + import net.minecraft.world.level.block.entity.JigsawBlockEntity; + import net.minecraft.world.level.block.entity.SignBlockEntity; + import net.minecraft.world.level.block.entity.StructureBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.pattern.BlockInWorld; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.scores.PlayerTeam; + import net.minecraft.world.scores.Scoreboard; +-import net.minecraft.world.scores.Team; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.util.CraftVector; ++import org.bukkit.entity.Item; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.entity.EntityExhaustionEvent; ++import org.bukkit.event.player.PlayerDropItemEvent; ++import org.bukkit.event.player.PlayerVelocityEvent; ++// CraftBukkit end + + public abstract class Player extends LivingEntity { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + public static final int MAX_NAME_LENGTH = 16; + public static final HumanoidArm DEFAULT_MAIN_HAND = HumanoidArm.RIGHT; +@@ -126,15 +138,8 @@ + public static final float SWIMMING_BB_HEIGHT = 0.6F; + public static final float DEFAULT_EYE_HEIGHT = 1.62F; + public static final EntityDimensions STANDING_DIMENSIONS = EntityDimensions.scalable(0.6F, 1.8F); +- private static final Map POSES = ImmutableMap.builder() +- .put(Pose.STANDING, STANDING_DIMENSIONS) +- .put(Pose.SLEEPING, SLEEPING_DIMENSIONS) +- .put(Pose.FALL_FLYING, EntityDimensions.scalable(0.6F, 0.6F)) +- .put(Pose.SWIMMING, EntityDimensions.scalable(0.6F, 0.6F)) +- .put(Pose.SPIN_ATTACK, EntityDimensions.scalable(0.6F, 0.6F)) +- .put(Pose.CROUCHING, EntityDimensions.scalable(0.6F, 1.5F)) +- .put(Pose.DYING, EntityDimensions.fixed(0.2F, 0.2F)) +- .build(); ++ // CraftBukkit - decompile error ++ private static final Map POSES = ImmutableMap.builder().put(EntityPose.STANDING, Player.STANDING_DIMENSIONS).put(EntityPose.SLEEPING, Player.SLEEPING_DIMENSIONS).put(EntityPose.FALL_FLYING, EntityDimensions.scalable(0.6F, 0.6F)).put(EntityPose.SWIMMING, EntityDimensions.scalable(0.6F, 0.6F)).put(EntityPose.SPIN_ATTACK, EntityDimensions.scalable(0.6F, 0.6F)).put(EntityPose.CROUCHING, EntityDimensions.scalable(0.6F, 1.5F)).put(EntityPose.DYING, EntityDimensions.fixed(0.2F, 0.2F)).build(); + private static final EntityDataAccessor DATA_PLAYER_ABSORPTION_ID = SynchedEntityData.defineId(Player.class, EntityDataSerializers.FLOAT); + private static final EntityDataAccessor DATA_SCORE_ID = SynchedEntityData.defineId(Player.class, EntityDataSerializers.INT); + protected static final EntityDataAccessor DATA_PLAYER_MODE_CUSTOMISATION = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE); +@@ -143,10 +148,10 @@ + protected static final EntityDataAccessor DATA_SHOULDER_RIGHT = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG); + private long timeEntitySatOnShoulder; + private final Inventory inventory = new Inventory(this); +- protected PlayerEnderChestContainer enderChestInventory = new PlayerEnderChestContainer(); ++ protected PlayerEnderChestContainer enderChestInventory = new PlayerEnderChestContainer(this); // CraftBukkit - add "this" to constructor + public final InventoryMenu inventoryMenu; + public AbstractContainerMenu containerMenu; +- protected FoodData foodData = new FoodData(); ++ protected FoodData foodData = new FoodData(this); // CraftBukkit - add "this" to constructor + protected int jumpTriggerTime; + public float oBob; + public float bob; +@@ -157,31 +162,44 @@ + public double xCloak; + public double yCloak; + public double zCloak; +- private int sleepCounter; ++ public int sleepCounter; + protected boolean wasUnderwater; + private final Abilities abilities = new Abilities(); + public int experienceLevel; + public int totalExperience; + public float experienceProgress; +- protected int enchantmentSeed; ++ public int enchantmentSeed; + protected final float defaultFlySpeed = 0.02F; + private int lastLevelUpTime; + private final GameProfile gameProfile; + private boolean reducedDebugInfo; +- private ItemStack lastItemInMainHand = ItemStack.EMPTY; +- private final ItemCooldowns cooldowns = this.createItemCooldowns(); +- private Optional lastDeathLocation = Optional.empty(); ++ private ItemStack lastItemInMainHand; ++ private final ItemCooldowns cooldowns; ++ private Optional lastDeathLocation; + @Nullable + public FishingHook fishing; + protected float hurtDir; + ++ // CraftBukkit start ++ public boolean fauxSleeping; ++ public int oldLevel = -1; ++ ++ @Override ++ public CraftHumanEntity getBukkitEntity() { ++ return (CraftHumanEntity) super.getBukkitEntity(); ++ } ++ // CraftBukkit end ++ + public Player(Level level, BlockPos pos, float yRot, GameProfile gameProfile) { + super(EntityType.PLAYER, level); ++ this.lastItemInMainHand = ItemStack.EMPTY; ++ this.cooldowns = this.createItemCooldowns(); ++ this.lastDeathLocation = Optional.empty(); + this.setUUID(gameProfile.getId()); + this.gameProfile = gameProfile; + this.inventoryMenu = new InventoryMenu(this.inventory, !level.isClientSide, this); + this.containerMenu = this.inventoryMenu; +- this.moveTo((double)pos.getX() + 0.5, (double)(pos.getY() + 1), (double)pos.getZ() + 0.5, yRot, 0.0F); ++ this.moveTo((double) pos.getX() + 0.5D, (double) (pos.getY() + 1), (double) pos.getZ() + 0.5D, yRot, 0.0F); + this.rotOffs = 180.0F; + } + +@@ -193,29 +211,25 @@ + } else if (this.mayBuild()) { + return false; + } else { +- ItemStack mainHandItem = this.getMainHandItem(); +- return mainHandItem.isEmpty() +- || !mainHandItem.hasAdventureModeBreakTagForBlock(level.registryAccess().registryOrThrow(Registries.BLOCK), new BlockInWorld(level, pos, false)); ++ ItemStack itemstack = this.getMainHandItem(); ++ ++ return itemstack.isEmpty() || !itemstack.hasAdventureModeBreakTagForBlock(level.registryAccess().registryOrThrow(Registries.BLOCK), new BlockInWorld(level, pos, false)); + } + } + + public static AttributeSupplier.Builder createAttributes() { +- return LivingEntity.createLivingAttributes() +- .add(Attributes.ATTACK_DAMAGE, 1.0) +- .add(Attributes.MOVEMENT_SPEED, 0.1F) +- .add(Attributes.ATTACK_SPEED) +- .add(Attributes.LUCK); ++ return LivingEntity.createLivingAttributes().add(Attributes.ATTACK_DAMAGE, 1.0D).add(Attributes.MOVEMENT_SPEED, 0.10000000149011612D).add(Attributes.ATTACK_SPEED).add(Attributes.LUCK); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_PLAYER_ABSORPTION_ID, 0.0F); +- this.entityData.define(DATA_SCORE_ID, 0); +- this.entityData.define(DATA_PLAYER_MODE_CUSTOMISATION, (byte)0); +- this.entityData.define(DATA_PLAYER_MAIN_HAND, (byte)DEFAULT_MAIN_HAND.getId()); +- this.entityData.define(DATA_SHOULDER_LEFT, new CompoundTag()); +- this.entityData.define(DATA_SHOULDER_RIGHT, new CompoundTag()); ++ this.entityData.define(Player.DATA_PLAYER_ABSORPTION_ID, 0.0F); ++ this.entityData.define(Player.DATA_SCORE_ID, 0); ++ this.entityData.define(Player.DATA_PLAYER_MODE_CUSTOMISATION, (byte) 0); ++ this.entityData.define(Player.DATA_PLAYER_MAIN_HAND, (byte) Player.DEFAULT_MAIN_HAND.getId()); ++ this.entityData.define(Player.DATA_SHOULDER_LEFT, new CompoundTag()); ++ this.entityData.define(Player.DATA_SHOULDER_RIGHT, new CompoundTag()); + } + + @Override +@@ -226,11 +240,11 @@ + } + + if (this.takeXpDelay > 0) { +- this.takeXpDelay--; ++ --this.takeXpDelay; + } + + if (this.isSleeping()) { +- this.sleepCounter++; ++ ++this.sleepCounter; + if (this.sleepCounter > 100) { + this.sleepCounter = 100; + } +@@ -239,7 +253,7 @@ + this.stopSleepInBed(false, true); + } + } else if (this.sleepCounter > 0) { +- this.sleepCounter++; ++ ++this.sleepCounter; + if (this.sleepCounter >= 110) { + this.sleepCounter = 0; + } +@@ -271,20 +285,22 @@ + } + + int i = 29999999; +- double d = Mth.clamp(this.getX(), -2.9999999E7, 2.9999999E7); +- double d1 = Mth.clamp(this.getZ(), -2.9999999E7, 2.9999999E7); +- if (d != this.getX() || d1 != this.getZ()) { +- this.setPos(d, this.getY(), d1); ++ double d0 = Mth.clamp(this.getX(), -2.9999999E7D, 2.9999999E7D); ++ double d1 = Mth.clamp(this.getZ(), -2.9999999E7D, 2.9999999E7D); ++ ++ if (d0 != this.getX() || d1 != this.getZ()) { ++ this.setPos(d0, this.getY(), d1); + } + +- this.attackStrengthTicker++; +- ItemStack mainHandItem = this.getMainHandItem(); +- if (!ItemStack.matches(this.lastItemInMainHand, mainHandItem)) { +- if (!ItemStack.isSameItem(this.lastItemInMainHand, mainHandItem)) { ++ ++this.attackStrengthTicker; ++ ItemStack itemstack = this.getMainHandItem(); ++ ++ if (!ItemStack.matches(this.lastItemInMainHand, itemstack)) { ++ if (!ItemStack.isSameItem(this.lastItemInMainHand, itemstack)) { + this.resetAttackStrengthTicker(); + } + +- this.lastItemInMainHand = mainHandItem.copy(); ++ this.lastItemInMainHand = itemstack.copy(); + } + + this.turtleHelmetTick(); +@@ -315,10 +331,12 @@ + } + + private void turtleHelmetTick() { +- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.HEAD); +- if (itemBySlot.is(Items.TURTLE_HELMET) && !this.isEyeInFluid(FluidTags.WATER)) { +- this.addEffect(new MobEffectInstance(MobEffects.WATER_BREATHING, 200, 0, false, false, true)); ++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); ++ ++ if (itemstack.is(Items.TURTLE_HELMET) && !this.isEyeInFluid(FluidTags.WATER)) { ++ this.addEffect(new MobEffectInstance(MobEffects.WATER_BREATHING, 200, 0, false, false, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TURTLE_HELMET); // CraftBukkit + } ++ + } + + protected ItemCooldowns createItemCooldowns() { +@@ -329,87 +347,87 @@ + this.xCloakO = this.xCloak; + this.yCloakO = this.yCloak; + this.zCloakO = this.zCloak; +- double d = this.getX() - this.xCloak; ++ double d0 = this.getX() - this.xCloak; + double d1 = this.getY() - this.yCloak; + double d2 = this.getZ() - this.zCloak; +- double d3 = 10.0; +- if (d > 10.0) { ++ double d3 = 10.0D; ++ ++ if (d0 > 10.0D) { + this.xCloak = this.getX(); + this.xCloakO = this.xCloak; + } + +- if (d2 > 10.0) { ++ if (d2 > 10.0D) { + this.zCloak = this.getZ(); + this.zCloakO = this.zCloak; + } + +- if (d1 > 10.0) { ++ if (d1 > 10.0D) { + this.yCloak = this.getY(); + this.yCloakO = this.yCloak; + } + +- if (d < -10.0) { ++ if (d0 < -10.0D) { + this.xCloak = this.getX(); + this.xCloakO = this.xCloak; + } + +- if (d2 < -10.0) { ++ if (d2 < -10.0D) { + this.zCloak = this.getZ(); + this.zCloakO = this.zCloak; + } + +- if (d1 < -10.0) { ++ if (d1 < -10.0D) { + this.yCloak = this.getY(); + this.yCloakO = this.yCloak; + } + +- this.xCloak += d * 0.25; +- this.zCloak += d2 * 0.25; +- this.yCloak += d1 * 0.25; ++ this.xCloak += d0 * 0.25D; ++ this.zCloak += d2 * 0.25D; ++ this.yCloak += d1 * 0.25D; + } + + protected void updatePlayerPose() { +- if (this.canPlayerFitWithinBlocksAndEntitiesWhen(Pose.SWIMMING)) { +- Pose pose; ++ if (this.canPlayerFitWithinBlocksAndEntitiesWhen(EntityPose.SWIMMING)) { ++ EntityPose entitypose; ++ + if (this.isFallFlying()) { +- pose = Pose.FALL_FLYING; ++ entitypose = EntityPose.FALL_FLYING; + } else if (this.isSleeping()) { +- pose = Pose.SLEEPING; ++ entitypose = EntityPose.SLEEPING; + } else if (this.isSwimming()) { +- pose = Pose.SWIMMING; ++ entitypose = EntityPose.SWIMMING; + } else if (this.isAutoSpinAttack()) { +- pose = Pose.SPIN_ATTACK; ++ entitypose = EntityPose.SPIN_ATTACK; + } else if (this.isShiftKeyDown() && !this.abilities.flying) { +- pose = Pose.CROUCHING; ++ entitypose = EntityPose.CROUCHING; + } else { +- pose = Pose.STANDING; ++ entitypose = EntityPose.STANDING; + } + +- Pose pose1; +- if (this.isSpectator() || this.isPassenger() || this.canPlayerFitWithinBlocksAndEntitiesWhen(pose)) { +- pose1 = pose; +- } else if (this.canPlayerFitWithinBlocksAndEntitiesWhen(Pose.CROUCHING)) { +- pose1 = Pose.CROUCHING; ++ EntityPose entitypose1; ++ ++ if (!this.isSpectator() && !this.isPassenger() && !this.canPlayerFitWithinBlocksAndEntitiesWhen(entitypose)) { ++ if (this.canPlayerFitWithinBlocksAndEntitiesWhen(EntityPose.CROUCHING)) { ++ entitypose1 = EntityPose.CROUCHING; ++ } else { ++ entitypose1 = EntityPose.SWIMMING; ++ } + } else { +- pose1 = Pose.SWIMMING; ++ entitypose1 = entitypose; + } + +- this.setPose(pose1); ++ this.setPose(entitypose1); + } + } + +- protected boolean canPlayerFitWithinBlocksAndEntitiesWhen(Pose pose) { +- return this.level().noCollision(this, this.getDimensions(pose).makeBoundingBox(this.position()).deflate(1.0E-7)); ++ protected boolean canPlayerFitWithinBlocksAndEntitiesWhen(EntityPose entitypose) { ++ return this.level().noCollision(this, this.getDimensions(entitypose).makeBoundingBox(this.position()).deflate(1.0E-7D)); + } + + @Override + public int getPortalWaitTime() { +- return Math.max( +- 1, +- this.level() +- .getGameRules() +- .getInt(this.abilities.invulnerable ? GameRules.RULE_PLAYERS_NETHER_PORTAL_CREATIVE_DELAY : GameRules.RULE_PLAYERS_NETHER_PORTAL_DEFAULT_DELAY) +- ); ++ return Math.max(1, this.level().getGameRules().getInt(this.abilities.invulnerable ? GameRules.RULE_PLAYERS_NETHER_PORTAL_CREATIVE_DELAY : GameRules.RULE_PLAYERS_NETHER_PORTAL_DEFAULT_DELAY)); + } + + @Override +@@ -437,8 +455,7 @@ + this.level().playSound(this, this.getX(), this.getY(), this.getZ(), sound, this.getSoundSource(), volume, pitch); + } + +- public void playNotifySound(SoundEvent sound, SoundSource source, float volume, float pitch) { +- } ++ public void playNotifySound(SoundEvent sound, SoundSource source, float volume, float pitch) {} + + @Override + public SoundSource getSoundSource() { +@@ -446,7 +463,7 @@ + } + + @Override +- protected int getFireImmuneTicks() { ++ public int getFireImmuneTicks() { + return 20; + } + +@@ -463,30 +480,38 @@ + } else { + super.handleEntityEvent(id); + } ++ + } + + private void addParticlesAroundSelf(ParticleOptions particleOption) { +- for (int i = 0; i < 5; i++) { +- double d = this.random.nextGaussian() * 0.02; +- double d1 = this.random.nextGaussian() * 0.02; +- double d2 = this.random.nextGaussian() * 0.02; +- this.level().addParticle(particleOption, this.getRandomX(1.0), this.getRandomY() + 1.0, this.getRandomZ(1.0), d, d1, d2); ++ for (int i = 0; i < 5; ++i) { ++ double d0 = this.random.nextGaussian() * 0.02D; ++ double d1 = this.random.nextGaussian() * 0.02D; ++ double d2 = this.random.nextGaussian() * 0.02D; ++ ++ this.level().addParticle(particleOption, this.getRandomX(1.0D), this.getRandomY() + 1.0D, this.getRandomZ(1.0D), d0, d1, d2); + } ++ + } + +- protected void closeContainer() { ++ public void closeContainer() { + this.containerMenu = this.inventoryMenu; + } + +- protected void doCloseContainer() { +- } ++ protected void doCloseContainer() {} + + @Override + public void rideTick() { + if (!this.level().isClientSide && this.wantsToStopRiding() && this.isPassenger()) { + this.stopRiding(); +- this.setShiftKeyDown(false); +- } else { ++ // CraftBukkit start - SPIGOT-7316: no longer passenger, dismount and return ++ if (!this.isPassenger()) { ++ this.setShiftKeyDown(false); ++ return; ++ } ++ } ++ { ++ // CraftBukkit end + super.rideTick(); + this.oBob = this.bob; + this.bob = 0.0F; +@@ -503,12 +528,13 @@ + @Override + public void aiStep() { + if (this.jumpTriggerTime > 0) { +- this.jumpTriggerTime--; ++ --this.jumpTriggerTime; + } + + if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.level().getGameRules().getBoolean(GameRules.RULE_NATURAL_REGENERATION)) { + if (this.getHealth() < this.getMaxHealth() && this.tickCount % 20 == 0) { +- this.heal(1.0F); ++ // CraftBukkit - added regain reason of "REGEN" for filtering purposes. ++ this.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.REGEN); + } + + if (this.foodData.needsFood() && this.tickCount % 10 == 0) { +@@ -519,36 +545,41 @@ + this.inventory.tick(); + this.oBob = this.bob; + super.aiStep(); +- this.setSpeed((float)this.getAttributeValue(Attributes.MOVEMENT_SPEED)); ++ this.setSpeed((float) this.getAttributeValue(Attributes.MOVEMENT_SPEED)); + float f; ++ + if (this.onGround() && !this.isDeadOrDying() && !this.isSwimming()) { +- f = Math.min(0.1F, (float)this.getDeltaMovement().horizontalDistance()); ++ f = Math.min(0.1F, (float) this.getDeltaMovement().horizontalDistance()); + } else { + f = 0.0F; + } + +- this.bob = this.bob + (f - this.bob) * 0.4F; ++ this.bob += (f - this.bob) * 0.4F; + if (this.getHealth() > 0.0F && !this.isSpectator()) { +- AABB aABB; ++ AABB axisalignedbb; ++ + if (this.isPassenger() && !this.getVehicle().isRemoved()) { +- aABB = this.getBoundingBox().minmax(this.getVehicle().getBoundingBox()).inflate(1.0, 0.0, 1.0); ++ axisalignedbb = this.getBoundingBox().minmax(this.getVehicle().getBoundingBox()).inflate(1.0D, 0.0D, 1.0D); + } else { +- aABB = this.getBoundingBox().inflate(1.0, 0.5, 1.0); ++ axisalignedbb = this.getBoundingBox().inflate(1.0D, 0.5D, 1.0D); + } + +- List entities = this.level().getEntities(this, aABB); +- List list = Lists.newArrayList(); ++ List list = this.level().getEntities(this, axisalignedbb); ++ List list1 = Lists.newArrayList(); ++ Iterator iterator = list.iterator(); + +- for (Entity entity : entities) { ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ + if (entity.getType() == EntityType.EXPERIENCE_ORB) { +- list.add(entity); ++ list1.add(entity); + } else if (!entity.isRemoved()) { + this.touch(entity); + } + } + +- if (!list.isEmpty()) { +- this.touch(Util.getRandom(list, this.random)); ++ if (!list1.isEmpty()) { ++ this.touch((Entity) Util.getRandom((List) list1, this.random)); + } + } + +@@ -557,31 +588,23 @@ + if (!this.level().isClientSide && (this.fallDistance > 0.5F || this.isInWater()) || this.abilities.flying || this.isSleeping() || this.isInPowderSnow) { + this.removeEntitiesOnShoulder(); + } ++ + } + + private void playShoulderEntityAmbientSound(@Nullable CompoundTag entityCompound) { + if (entityCompound != null && (!entityCompound.contains("Silent") || !entityCompound.getBoolean("Silent")) && this.level().random.nextInt(200) == 0) { +- String string = entityCompound.getString("id"); +- EntityType.byString(string) +- .filter(entityType -> entityType == EntityType.PARROT) +- .ifPresent( +- entityType -> { +- if (!Parrot.imitateNearbyMobs(this.level(), this)) { +- this.level() +- .playSound( +- null, +- this.getX(), +- this.getY(), +- this.getZ(), +- Parrot.getAmbient(this.level(), this.level().random), +- this.getSoundSource(), +- 1.0F, +- Parrot.getPitch(this.level().random) +- ); +- } +- } +- ); ++ String s = entityCompound.getString("id"); ++ ++ EntityType.byString(s).filter((entitytypes) -> { ++ return entitytypes == EntityType.PARROT; ++ }).ifPresent((entitytypes) -> { ++ if (!Parrot.imitateNearbyMobs(this.level(), this)) { ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), Parrot.getAmbient(this.level(), this.level().random), this.getSoundSource(), 1.0F, Parrot.getPitch(this.level().random)); ++ } ++ ++ }); + } ++ + } + + private void touch(Entity entity) { +@@ -589,16 +612,17 @@ + } + + public int getScore() { +- return this.entityData.get(DATA_SCORE_ID); ++ return (Integer) this.entityData.get(Player.DATA_SCORE_ID); + } + + public void setScore(int score) { +- this.entityData.set(DATA_SCORE_ID, score); ++ this.entityData.set(Player.DATA_SCORE_ID, score); + } + + public void increaseScore(int score) { +- int score1 = this.getScore(); +- this.entityData.set(DATA_SCORE_ID, score1 + score); ++ int j = this.getScore(); ++ ++ this.entityData.set(Player.DATA_SCORE_ID, j + score); + } + + public void startAutoSpinAttack(int attackTicks) { +@@ -607,6 +631,7 @@ + this.removeEntitiesOnShoulder(); + this.setLivingEntityFlag(4, true); + } ++ + } + + @Override +@@ -618,13 +643,9 @@ + } + + if (cause != null) { +- this.setDeltaMovement( +- (double)(-Mth.cos((this.getHurtDir() + this.getYRot()) * (float) (Math.PI / 180.0)) * 0.1F), +- 0.1F, +- (double)(-Mth.sin((this.getHurtDir() + this.getYRot()) * (float) (Math.PI / 180.0)) * 0.1F) +- ); ++ this.setDeltaMovement((double) (-Mth.cos((this.getHurtDir() + this.getYRot()) * 0.017453292F) * 0.1F), 0.10000000149011612D, (double) (-Mth.sin((this.getHurtDir() + this.getYRot()) * 0.017453292F) * 0.1F)); + } else { +- this.setDeltaMovement(0.0, 0.1, 0.0); ++ this.setDeltaMovement(0.0D, 0.1D, 0.0D); + } + + this.awardStat(Stats.DEATHS); +@@ -642,15 +663,18 @@ + this.destroyVanishingCursedItems(); + this.inventory.dropAll(); + } ++ + } + + protected void destroyVanishingCursedItems() { +- for (int i = 0; i < this.inventory.getContainerSize(); i++) { +- ItemStack item = this.inventory.getItem(i); +- if (!item.isEmpty() && EnchantmentHelper.hasVanishingCurse(item)) { ++ for (int i = 0; i < this.inventory.getContainerSize(); ++i) { ++ ItemStack itemstack = this.inventory.getItem(i); ++ ++ if (!itemstack.isEmpty() && EnchantmentHelper.hasVanishingCurse(itemstack)) { + this.inventory.removeItemNoUpdate(i); + } + } ++ + } + + @Override +@@ -670,78 +694,127 @@ + + @Nullable + public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean includeThrowerName) { +- if (droppedItem.isEmpty()) { ++ // CraftBukkit start - SPIGOT-2942: Add boolean to call event ++ return drop(droppedItem, dropAround, includeThrowerName, true); ++ } ++ ++ @Nullable ++ public ItemEntity drop(ItemStack itemstack, boolean flag, boolean flag1, boolean callEvent) { ++ // CraftBukkit end ++ if (itemstack.isEmpty()) { + return null; + } else { + if (this.level().isClientSide) { +- this.swing(InteractionHand.MAIN_HAND); ++ this.swing(EnumHand.MAIN_HAND); + } + +- double d = this.getEyeY() - 0.3F; +- ItemEntity itemEntity = new ItemEntity(this.level(), this.getX(), d, this.getZ(), droppedItem); +- itemEntity.setPickUpDelay(40); +- if (includeThrowerName) { +- itemEntity.setThrower(this); ++ double d0 = this.getEyeY() - 0.30000001192092896D; ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), d0, this.getZ(), itemstack); ++ ++ entityitem.setPickUpDelay(40); ++ if (flag1) { ++ entityitem.setThrower(this); + } + +- if (dropAround) { +- float f = this.random.nextFloat() * 0.5F; +- float f1 = this.random.nextFloat() * (float) (Math.PI * 2); +- itemEntity.setDeltaMovement((double)(-Mth.sin(f1) * f), 0.2F, (double)(Mth.cos(f1) * f)); ++ float f; ++ float f1; ++ ++ if (flag) { ++ f = this.random.nextFloat() * 0.5F; ++ f1 = this.random.nextFloat() * 6.2831855F; ++ entityitem.setDeltaMovement((double) (-Mth.sin(f1) * f), 0.20000000298023224D, (double) (Mth.cos(f1) * f)); + } else { +- float f = 0.3F; +- float f1 = Mth.sin(this.getXRot() * (float) (Math.PI / 180.0)); +- float cos = Mth.cos(this.getXRot() * (float) (Math.PI / 180.0)); +- float sin = Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)); +- float cos1 = Mth.cos(this.getYRot() * (float) (Math.PI / 180.0)); +- float f2 = this.random.nextFloat() * (float) (Math.PI * 2); +- float f3 = 0.02F * this.random.nextFloat(); +- itemEntity.setDeltaMovement( +- (double)(-sin * cos * 0.3F) + Math.cos((double)f2) * (double)f3, +- (double)(-f1 * 0.3F + 0.1F + (this.random.nextFloat() - this.random.nextFloat()) * 0.1F), +- (double)(cos1 * cos * 0.3F) + Math.sin((double)f2) * (double)f3 +- ); ++ f = 0.3F; ++ f1 = Mth.sin(this.getXRot() * 0.017453292F); ++ float f2 = Mth.cos(this.getXRot() * 0.017453292F); ++ float f3 = Mth.sin(this.getYRot() * 0.017453292F); ++ float f4 = Mth.cos(this.getYRot() * 0.017453292F); ++ float f5 = this.random.nextFloat() * 6.2831855F; ++ float f6 = 0.02F * this.random.nextFloat(); ++ ++ entityitem.setDeltaMovement((double) (-f3 * f2 * 0.3F) + Math.cos((double) f5) * (double) f6, (double) (-f1 * 0.3F + 0.1F + (this.random.nextFloat() - this.random.nextFloat()) * 0.1F), (double) (f4 * f2 * 0.3F) + Math.sin((double) f5) * (double) f6); + } + +- return itemEntity; ++ // CraftBukkit start - fire PlayerDropItemEvent ++ if (!callEvent) { // SPIGOT-2942: Add boolean to call event ++ return entityitem; ++ } ++ org.bukkit.entity.Player player = (org.bukkit.entity.Player) this.getBukkitEntity(); ++ Item drop = (Item) entityitem.getBukkitEntity(); ++ ++ PlayerDropItemEvent event = new PlayerDropItemEvent(player, drop); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ org.bukkit.inventory.ItemStack cur = player.getInventory().getItemInHand(); ++ if (flag1 && (cur == null || cur.getAmount() == 0)) { ++ // The complete stack was dropped ++ player.getInventory().setItemInHand(drop.getItemStack()); ++ } else if (flag1 && cur.isSimilar(drop.getItemStack()) && cur.getAmount() < cur.getMaxStackSize() && drop.getItemStack().getAmount() == 1) { ++ // Only one item is dropped ++ cur.setAmount(cur.getAmount() + 1); ++ player.getInventory().setItemInHand(cur); ++ } else { ++ // Fallback ++ player.getInventory().addItem(drop.getItemStack()); ++ } ++ return null; ++ } ++ // CraftBukkit end ++ ++ return entityitem; + } + } + +- public float getDestroySpeed(BlockState state) { +- float destroySpeed = this.inventory.getDestroySpeed(state); +- if (destroySpeed > 1.0F) { +- int blockEfficiency = EnchantmentHelper.getBlockEfficiency(this); +- ItemStack mainHandItem = this.getMainHandItem(); +- if (blockEfficiency > 0 && !mainHandItem.isEmpty()) { +- destroySpeed += (float)(blockEfficiency * blockEfficiency + 1); ++ public float getDestroySpeed(IBlockData state) { ++ float f = this.inventory.getDestroySpeed(state); ++ ++ if (f > 1.0F) { ++ int i = EnchantmentHelper.getBlockEfficiency(this); ++ ItemStack itemstack = this.getMainHandItem(); ++ ++ if (i > 0 && !itemstack.isEmpty()) { ++ f += (float) (i * i + 1); + } + } + + if (MobEffectUtil.hasDigSpeed(this)) { +- destroySpeed *= 1.0F + (float)(MobEffectUtil.getDigSpeedAmplification(this) + 1) * 0.2F; ++ f *= 1.0F + (float) (MobEffectUtil.getDigSpeedAmplification(this) + 1) * 0.2F; + } + + if (this.hasEffect(MobEffects.DIG_SLOWDOWN)) { +- destroySpeed *= switch (this.getEffect(MobEffects.DIG_SLOWDOWN).getAmplifier()) { +- case 0 -> 0.3F; +- case 1 -> 0.09F; +- case 2 -> 0.0027F; +- default -> 8.1E-4F; +- }; ++ float f1; ++ ++ switch (this.getEffect(MobEffects.DIG_SLOWDOWN).getAmplifier()) { ++ case 0: ++ f1 = 0.3F; ++ break; ++ case 1: ++ f1 = 0.09F; ++ break; ++ case 2: ++ f1 = 0.0027F; ++ break; ++ case 3: ++ default: ++ f1 = 8.1E-4F; ++ } ++ ++ f *= f1; + } + + if (this.isEyeInFluid(FluidTags.WATER) && !EnchantmentHelper.hasAquaAffinity(this)) { +- destroySpeed /= 5.0F; ++ f /= 5.0F; + } + + if (!this.onGround()) { +- destroySpeed /= 5.0F; ++ f /= 5.0F; + } + +- return destroySpeed; ++ return f; + } + +- public boolean hasCorrectToolForDrops(BlockState state) { ++ public boolean hasCorrectToolForDrops(IBlockData state) { + return !state.requiresCorrectToolForDrops() || this.inventory.getSelected().isCorrectToolForDrops(state); + } + +@@ -749,8 +822,9 @@ + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); + this.setUUID(this.gameProfile.getId()); +- ListTag list = compound.getList("Inventory", 10); +- this.inventory.load(list); ++ ListTag nbttaglist = compound.getList("Inventory", 10); ++ ++ this.inventory.load(nbttaglist); + this.inventory.selected = compound.getInt("SelectedItemSlot"); + this.sleepCounter = compound.getShort("SleepTimer"); + this.experienceProgress = compound.getFloat("XpP"); +@@ -764,7 +838,7 @@ + this.setScore(compound.getInt("Score")); + this.foodData.readAdditionalSaveData(compound); + this.abilities.loadSaveData(compound); +- this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue((double)this.abilities.getWalkingSpeed()); ++ this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue((double) this.abilities.getWalkingSpeed()); + if (compound.contains("EnderItems", 9)) { + this.enderChestInventory.fromTag(compound.getList("EnderItems", 10)); + } +@@ -778,8 +852,13 @@ + } + + if (compound.contains("LastDeathLocation", 10)) { +- this.setLastDeathLocation(GlobalPos.CODEC.parse(NbtOps.INSTANCE, compound.get("LastDeathLocation")).resultOrPartial(LOGGER::error)); ++ DataResult dataresult = GlobalPos.CODEC.parse(NbtOps.INSTANCE, compound.get("LastDeathLocation")); // CraftBukkit - decompile error ++ Logger logger = Player.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ this.setLastDeathLocation(dataresult.resultOrPartial(logger::error)); + } ++ + } + + @Override +@@ -788,7 +867,7 @@ + NbtUtils.addCurrentDataVersion(compound); + compound.put("Inventory", this.inventory.save(new ListTag())); + compound.putInt("SelectedItemSlot", this.inventory.selected); +- compound.putShort("SleepTimer", (short)this.sleepCounter); ++ compound.putShort("SleepTimer", (short) this.sleepCounter); + compound.putFloat("XpP", this.experienceProgress); + compound.putInt("XpLevel", this.experienceLevel); + compound.putInt("XpTotal", this.totalExperience); +@@ -805,24 +884,20 @@ + compound.put("ShoulderEntityRight", this.getShoulderEntityRight()); + } + +- this.getLastDeathLocation() +- .flatMap(globalPos -> GlobalPos.CODEC.encodeStart(NbtOps.INSTANCE, globalPos).resultOrPartial(LOGGER::error)) +- .ifPresent(tag -> compound.put("LastDeathLocation", tag)); ++ this.getLastDeathLocation().flatMap((globalpos) -> { ++ DataResult dataresult = GlobalPos.CODEC.encodeStart(NbtOps.INSTANCE, globalpos); // CraftBukkit - decompile error ++ Logger logger = Player.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ return dataresult.resultOrPartial(logger::error); ++ }).ifPresent((nbtbase) -> { ++ compound.put("LastDeathLocation", nbtbase); ++ }); + } + + @Override + public boolean isInvulnerableTo(DamageSource source) { +- if (super.isInvulnerableTo(source)) { +- return true; +- } else if (source.is(DamageTypeTags.IS_DROWNING)) { +- return !this.level().getGameRules().getBoolean(GameRules.RULE_DROWNING_DAMAGE); +- } else if (source.is(DamageTypeTags.IS_FALL)) { +- return !this.level().getGameRules().getBoolean(GameRules.RULE_FALL_DAMAGE); +- } else { +- return source.is(DamageTypeTags.IS_FIRE) +- ? !this.level().getGameRules().getBoolean(GameRules.RULE_FIRE_DAMAGE) +- : source.is(DamageTypeTags.IS_FREEZING) && !this.level().getGameRules().getBoolean(GameRules.RULE_FREEZE_DAMAGE); +- } ++ return super.isInvulnerableTo(source) ? true : (source.is(DamageTypeTags.IS_DROWNING) ? !this.level().getGameRules().getBoolean(GameRules.RULE_DROWNING_DAMAGE) : (source.is(DamageTypeTags.IS_FALL) ? !this.level().getGameRules().getBoolean(GameRules.RULE_FALL_DAMAGE) : (source.is(DamageTypeTags.IS_FIRE) ? !this.level().getGameRules().getBoolean(GameRules.RULE_FIRE_DAMAGE) : (source.is(DamageTypeTags.IS_FREEZING) ? !this.level().getGameRules().getBoolean(GameRules.RULE_FREEZE_DAMAGE) : false)))); + } + + @Override +@@ -837,12 +912,12 @@ + return false; + } else { + if (!this.level().isClientSide) { +- this.removeEntitiesOnShoulder(); ++ // this.removeEntitiesOnShoulder(); // CraftBukkit - moved down + } + + if (source.scalesWithDifficulty()) { + if (this.level().getDifficulty() == Difficulty.PEACEFUL) { +- amount = 0.0F; ++ return false; // CraftBukkit - f = 0.0f -> return false + } + + if (this.level().getDifficulty() == Difficulty.EASY) { +@@ -854,7 +929,13 @@ + } + } + +- return amount != 0.0F && super.hurt(source, amount); ++ // CraftBukkit start - Don't filter out 0 damage ++ boolean damaged = super.hurt(source, amount); ++ if (damaged) { ++ this.removeEntitiesOnShoulder(); ++ } ++ return damaged; ++ // CraftBukkit end + } + } + } +@@ -865,6 +946,7 @@ + if (entity.canDisableShield()) { + this.disableShield(true); + } ++ + } + + @Override +@@ -873,9 +955,29 @@ + } + + public boolean canHarmPlayer(Player other) { +- Team team = this.getTeam(); +- Team team1 = other.getTeam(); +- return team == null || !team.isAlliedTo(team1) || team.isAllowFriendlyFire(); ++ // CraftBukkit start - Change to check OTHER player's scoreboard team according to API ++ // To summarize this method's logic, it's "Can parameter hurt this" ++ org.bukkit.scoreboard.Team team; ++ if (other instanceof ServerPlayer) { ++ ServerPlayer thatPlayer = (ServerPlayer) other; ++ team = thatPlayer.getBukkitEntity().getScoreboard().getPlayerTeam(thatPlayer.getBukkitEntity()); ++ if (team == null || team.allowFriendlyFire()) { ++ return true; ++ } ++ } else { ++ // This should never be called, but is implemented anyway ++ org.bukkit.OfflinePlayer thisPlayer = other.level().getCraftServer().getOfflinePlayer(other.getScoreboardName()); ++ team = other.level().getCraftServer().getScoreboardManager().getMainScoreboard().getPlayerTeam(thisPlayer); ++ if (team == null || team.allowFriendlyFire()) { ++ return true; ++ } ++ } ++ ++ if (this instanceof ServerPlayer) { ++ return !team.hasPlayer(((ServerPlayer) this).getBukkitEntity()); ++ } ++ return !team.hasPlayer(this.level().getCraftServer().getOfflinePlayer(this.getScoreboardName())); ++ // CraftBukkit end + } + + @Override +@@ -897,10 +999,13 @@ + + if (damage >= 3.0F) { + int i = 1 + Mth.floor(damage); +- InteractionHand usedItemHand = this.getUsedItemHand(); +- this.useItem.hurtAndBreak(i, this, player -> player.broadcastBreakEvent(usedItemHand)); ++ EnumHand enumhand = this.getUsedItemHand(); ++ ++ this.useItem.hurtAndBreak(i, this, (entityhuman) -> { ++ entityhuman.broadcastBreakEvent(enumhand); ++ }); + if (this.useItem.isEmpty()) { +- if (usedItemHand == InteractionHand.MAIN_HAND) { ++ if (enumhand == EnumHand.MAIN_HAND) { + this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); + } else { + this.setItemSlot(EquipmentSlot.OFFHAND, ItemStack.EMPTY); +@@ -910,32 +1015,42 @@ + this.playSound(SoundEvents.SHIELD_BREAK, 0.8F, 0.8F + this.level().random.nextFloat() * 0.4F); + } + } ++ + } + } + ++ // CraftBukkit start + @Override +- protected void actuallyHurt(DamageSource damageSrc, float damageAmount) { +- if (!this.isInvulnerableTo(damageSrc)) { +- damageAmount = this.getDamageAfterArmorAbsorb(damageSrc, damageAmount); +- damageAmount = this.getDamageAfterMagicAbsorb(damageSrc, damageAmount); +- float var7 = Math.max(damageAmount - this.getAbsorptionAmount(), 0.0F); +- this.setAbsorptionAmount(this.getAbsorptionAmount() - (damageAmount - var7)); +- float f1 = damageAmount - var7; +- if (f1 > 0.0F && f1 < 3.4028235E37F) { +- this.awardStat(Stats.DAMAGE_ABSORBED, Math.round(f1 * 10.0F)); ++ protected boolean damageEntity0(DamageSource damagesource, float f) { // void -> boolean ++ if (true) { ++ return super.damageEntity0(damagesource, f); ++ } ++ // CraftBukkit end ++ if (!this.isInvulnerableTo(damagesource)) { ++ f = this.getDamageAfterArmorAbsorb(damagesource, f); ++ f = this.getDamageAfterMagicAbsorb(damagesource, f); ++ float f1 = f; ++ ++ f = Math.max(f - this.getAbsorptionAmount(), 0.0F); ++ this.setAbsorptionAmount(this.getAbsorptionAmount() - (f1 - f)); ++ float f2 = f1 - f; ++ ++ if (f2 > 0.0F && f2 < 3.4028235E37F) { ++ this.awardStat(Stats.DAMAGE_ABSORBED, Math.round(f2 * 10.0F)); + } + +- if (var7 != 0.0F) { +- this.causeFoodExhaustion(damageSrc.getFoodExhaustion()); +- this.getCombatTracker().recordDamage(damageSrc, var7); +- this.setHealth(this.getHealth() - var7); +- if (var7 < 3.4028235E37F) { +- this.awardStat(Stats.DAMAGE_TAKEN, Math.round(var7 * 10.0F)); ++ if (f != 0.0F) { ++ this.causeFoodExhaustion(damagesource.getFoodExhaustion(), EntityExhaustionEvent.ExhaustionReason.DAMAGED); // CraftBukkit - EntityExhaustionEvent ++ this.getCombatTracker().recordDamage(damagesource, f); ++ this.setHealth(this.getHealth() - f); ++ if (f < 3.4028235E37F) { ++ this.awardStat(Stats.DAMAGE_TAKEN, Math.round(f * 10.0F)); + } + + this.gameEvent(GameEvent.ENTITY_DAMAGE); + } + } ++ return false; // CraftBukkit + } + + @Override +@@ -947,65 +1062,59 @@ + return false; + } + +- public void openTextEdit(SignBlockEntity signEntity, boolean isFrontText) { +- } ++ public void openTextEdit(SignBlockEntity signEntity, boolean isFrontText) {} + +- public void openMinecartCommandBlock(BaseCommandBlock commandEntity) { +- } ++ public void openMinecartCommandBlock(BaseCommandBlock commandEntity) {} + +- public void openCommandBlock(CommandBlockEntity commandBlockEntity) { +- } ++ public void openCommandBlock(CommandBlockEntity commandBlockEntity) {} + +- public void openStructureBlock(StructureBlockEntity structureEntity) { +- } ++ public void openStructureBlock(StructureBlockEntity structureEntity) {} + +- public void openJigsawBlock(JigsawBlockEntity jigsawBlockEntity) { +- } ++ public void openJigsawBlock(JigsawBlockEntity jigsawBlockEntity) {} + +- public void openHorseInventory(AbstractHorse horse, Container inventory) { +- } ++ public void openHorseInventory(AbstractHorse horse, Container inventory) {} + +- public OptionalInt openMenu(@Nullable MenuProvider menu) { ++ public OptionalInt openMenu(@Nullable ITileInventory menu) { + return OptionalInt.empty(); + } + +- public void sendMerchantOffers(int containerId, MerchantOffers offers, int villagerLevel, int villagerXp, boolean showProgress, boolean canRestock) { +- } ++ public void sendMerchantOffers(int containerId, MerchantOffers offers, int villagerLevel, int villagerXp, boolean showProgress, boolean canRestock) {} + +- public void openItemGui(ItemStack stack, InteractionHand hand) { +- } ++ public void openItemGui(ItemStack stack, EnumHand hand) {} + +- public InteractionResult interactOn(Entity entityToInteractOn, InteractionHand hand) { ++ public InteractionResult interactOn(Entity entityToInteractOn, EnumHand hand) { + if (this.isSpectator()) { +- if (entityToInteractOn instanceof MenuProvider) { +- this.openMenu((MenuProvider)entityToInteractOn); ++ if (entityToInteractOn instanceof ITileInventory) { ++ this.openMenu((ITileInventory) entityToInteractOn); + } + + return InteractionResult.PASS; + } else { +- ItemStack itemInHand = this.getItemInHand(hand); +- ItemStack itemStack = itemInHand.copy(); +- InteractionResult interactionResult = entityToInteractOn.interact(this, hand); +- if (interactionResult.consumesAction()) { +- if (this.abilities.instabuild && itemInHand == this.getItemInHand(hand) && itemInHand.getCount() < itemStack.getCount()) { +- itemInHand.setCount(itemStack.getCount()); ++ ItemStack itemstack = this.getItemInHand(hand); ++ ItemStack itemstack1 = itemstack.copy(); ++ InteractionResult enuminteractionresult = entityToInteractOn.interact(this, hand); ++ ++ if (enuminteractionresult.consumesAction()) { ++ if (this.abilities.instabuild && itemstack == this.getItemInHand(hand) && itemstack.getCount() < itemstack1.getCount()) { ++ itemstack.setCount(itemstack1.getCount()); + } + +- return interactionResult; ++ return enuminteractionresult; + } else { +- if (!itemInHand.isEmpty() && entityToInteractOn instanceof LivingEntity) { ++ if (!itemstack.isEmpty() && entityToInteractOn instanceof LivingEntity) { + if (this.abilities.instabuild) { +- itemInHand = itemStack; ++ itemstack = itemstack1; + } + +- InteractionResult interactionResult1 = itemInHand.interactLivingEntity(this, (LivingEntity)entityToInteractOn, hand); +- if (interactionResult1.consumesAction()) { +- this.level().gameEvent(GameEvent.ENTITY_INTERACT, entityToInteractOn.position(), GameEvent.Context.of(this)); +- if (itemInHand.isEmpty() && !this.abilities.instabuild) { ++ InteractionResult enuminteractionresult1 = itemstack.interactLivingEntity(this, (LivingEntity) entityToInteractOn, hand); ++ ++ if (enuminteractionresult1.consumesAction()) { ++ this.level().gameEvent(GameEvent.ENTITY_INTERACT, entityToInteractOn.position(), GameEvent.Context.of((Entity) this)); ++ if (itemstack.isEmpty() && !this.abilities.instabuild) { + this.setItemInHand(hand, ItemStack.EMPTY); + } + +- return interactionResult1; ++ return enuminteractionresult1; + } + } + +@@ -1036,242 +1145,259 @@ + } + + @Override +- protected Vec3 maybeBackOffFromEdge(Vec3 vec, MoverType mover) { +- if (!this.abilities.flying +- && vec.y <= 0.0 +- && (mover == MoverType.SELF || mover == MoverType.PLAYER) +- && this.isStayingOnGroundSurface() +- && this.isAboveGround()) { +- double d = vec.x; ++ protected Vec3 maybeBackOffFromEdge(Vec3 vec, EnumMoveType mover) { ++ if (!this.abilities.flying && vec.y <= 0.0D && (mover == EnumMoveType.SELF || mover == EnumMoveType.PLAYER) && this.isStayingOnGroundSurface() && this.isAboveGround()) { ++ double d0 = vec.x; + double d1 = vec.z; +- double d2 = 0.05; ++ double d2 = 0.05D; + +- while (d != 0.0 && this.level().noCollision(this, this.getBoundingBox().move(d, (double)(-this.maxUpStep()), 0.0))) { +- if (d < 0.05 && d >= -0.05) { +- d = 0.0; +- } else if (d > 0.0) { +- d -= 0.05; ++ while (d0 != 0.0D && this.level().noCollision(this, this.getBoundingBox().move(d0, (double) (-this.maxUpStep()), 0.0D))) { ++ if (d0 < 0.05D && d0 >= -0.05D) { ++ d0 = 0.0D; ++ } else if (d0 > 0.0D) { ++ d0 -= 0.05D; + } else { +- d += 0.05; ++ d0 += 0.05D; + } + } + +- while (d1 != 0.0 && this.level().noCollision(this, this.getBoundingBox().move(0.0, (double)(-this.maxUpStep()), d1))) { +- if (d1 < 0.05 && d1 >= -0.05) { +- d1 = 0.0; +- } else if (d1 > 0.0) { +- d1 -= 0.05; ++ while (d1 != 0.0D && this.level().noCollision(this, this.getBoundingBox().move(0.0D, (double) (-this.maxUpStep()), d1))) { ++ if (d1 < 0.05D && d1 >= -0.05D) { ++ d1 = 0.0D; ++ } else if (d1 > 0.0D) { ++ d1 -= 0.05D; + } else { +- d1 += 0.05; ++ d1 += 0.05D; + } + } + +- while (d != 0.0 && d1 != 0.0 && this.level().noCollision(this, this.getBoundingBox().move(d, (double)(-this.maxUpStep()), d1))) { +- if (d < 0.05 && d >= -0.05) { +- d = 0.0; +- } else if (d > 0.0) { +- d -= 0.05; ++ while (d0 != 0.0D && d1 != 0.0D && this.level().noCollision(this, this.getBoundingBox().move(d0, (double) (-this.maxUpStep()), d1))) { ++ if (d0 < 0.05D && d0 >= -0.05D) { ++ d0 = 0.0D; ++ } else if (d0 > 0.0D) { ++ d0 -= 0.05D; + } else { +- d += 0.05; ++ d0 += 0.05D; + } + +- if (d1 < 0.05 && d1 >= -0.05) { +- d1 = 0.0; +- } else if (d1 > 0.0) { +- d1 -= 0.05; ++ if (d1 < 0.05D && d1 >= -0.05D) { ++ d1 = 0.0D; ++ } else if (d1 > 0.0D) { ++ d1 -= 0.05D; + } else { +- d1 += 0.05; ++ d1 += 0.05D; + } + } + +- vec = new Vec3(d, vec.y, d1); ++ vec = new Vec3(d0, vec.y, d1); + } + + return vec; + } + + private boolean isAboveGround() { +- return this.onGround() +- || this.fallDistance < this.maxUpStep() +- && !this.level().noCollision(this, this.getBoundingBox().move(0.0, (double)(this.fallDistance - this.maxUpStep()), 0.0)); ++ return this.onGround() || this.fallDistance < this.maxUpStep() && !this.level().noCollision(this, this.getBoundingBox().move(0.0D, (double) (this.fallDistance - this.maxUpStep()), 0.0D)); + } + + public void attack(Entity target) { + if (target.isAttackable()) { + if (!target.skipAttackInteraction(this)) { +- float f = (float)this.getAttributeValue(Attributes.ATTACK_DAMAGE); +- float damageBonus; ++ float f = (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE); ++ float f1; ++ + if (target instanceof LivingEntity) { +- damageBonus = EnchantmentHelper.getDamageBonus(this.getMainHandItem(), ((LivingEntity)target).getMobType()); ++ f1 = EnchantmentHelper.getDamageBonus(this.getMainHandItem(), ((LivingEntity) target).getMobType()); + } else { +- damageBonus = EnchantmentHelper.getDamageBonus(this.getMainHandItem(), MobType.UNDEFINED); ++ f1 = EnchantmentHelper.getDamageBonus(this.getMainHandItem(), EnumMonsterType.UNDEFINED); + } + +- float attackStrengthScale = this.getAttackStrengthScale(0.5F); +- float var21 = f * (0.2F + attackStrengthScale * attackStrengthScale * 0.8F); +- float var23 = damageBonus * attackStrengthScale; +- this.resetAttackStrengthTicker(); +- if (var21 > 0.0F || var23 > 0.0F) { +- boolean flag = attackStrengthScale > 0.9F; ++ float f2 = this.getAttackStrengthScale(0.5F); ++ ++ f *= 0.2F + f2 * f2 * 0.8F; ++ f1 *= f2; ++ // this.resetAttackCooldown(); // CraftBukkit - Moved to EntityLiving to reset the cooldown after the damage is dealt ++ if (f > 0.0F || f1 > 0.0F) { ++ boolean flag = f2 > 0.9F; + boolean flag1 = false; +- int i = 0; +- int var24 = i + EnchantmentHelper.getKnockbackBonus(this); ++ byte b0 = 0; ++ int i = b0 + EnchantmentHelper.getKnockbackBonus(this); ++ + if (this.isSprinting() && flag) { +- this.level() +- .playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_KNOCKBACK, this.getSoundSource(), 1.0F, 1.0F); +- var24++; ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_KNOCKBACK, this.getSoundSource(), 1.0F, 1.0F); ++ ++i; + flag1 = true; + } + +- boolean flag2 = flag +- && this.fallDistance > 0.0F +- && !this.onGround() +- && !this.onClimbable() +- && !this.isInWater() +- && !this.hasEffect(MobEffects.BLINDNESS) +- && !this.isPassenger() +- && target instanceof LivingEntity; ++ boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround() && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity; ++ + flag2 = flag2 && !this.isSprinting(); + if (flag2) { +- var21 *= 1.5F; ++ f *= 1.5F; + } + +- f = var21 + var23; ++ f += f1; + boolean flag3 = false; +- double d = (double)(this.walkDist - this.walkDistO); +- if (flag && !flag2 && !flag1 && this.onGround() && d < (double)this.getSpeed()) { +- ItemStack itemInHand = this.getItemInHand(InteractionHand.MAIN_HAND); +- if (itemInHand.getItem() instanceof SwordItem) { ++ double d0 = (double) (this.walkDist - this.walkDistO); ++ ++ if (flag && !flag2 && !flag1 && this.onGround() && d0 < (double) this.getSpeed()) { ++ ItemStack itemstack = this.getItemInHand(EnumHand.MAIN_HAND); ++ ++ if (itemstack.getItem() instanceof SwordItem) { + flag3 = true; + } + } + +- float f1 = 0.0F; ++ float f3 = 0.0F; + boolean flag4 = false; +- int fireAspect = EnchantmentHelper.getFireAspect(this); ++ int j = EnchantmentHelper.getFireAspect(this); ++ + if (target instanceof LivingEntity) { +- f1 = ((LivingEntity)target).getHealth(); +- if (fireAspect > 0 && !target.isOnFire()) { +- flag4 = true; +- target.setSecondsOnFire(1); ++ f3 = ((LivingEntity) target).getHealth(); ++ if (j > 0 && !target.isOnFire()) { ++ // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), target.getBukkitEntity(), 1); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ flag4 = true; ++ target.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + } + +- Vec3 deltaMovement = target.getDeltaMovement(); ++ Vec3 vec3d = target.getDeltaMovement(); + boolean flag5 = target.hurt(this.damageSources().playerAttack(this), f); ++ + if (flag5) { +- if (var24 > 0) { ++ if (i > 0) { + if (target instanceof LivingEntity) { +- ((LivingEntity)target) +- .knockback( +- (double)((float)var24 * 0.5F), +- (double)Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)), +- (double)(-Mth.cos(this.getYRot() * (float) (Math.PI / 180.0))) +- ); ++ ((LivingEntity) target).knockback((double) ((float) i * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F))); + } else { +- target.push( +- (double)(-Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)) * (float)var24 * 0.5F), +- 0.1, +- (double)(Mth.cos(this.getYRot() * (float) (Math.PI / 180.0)) * (float)var24 * 0.5F) +- ); ++ target.push((double) (-Mth.sin(this.getYRot() * 0.017453292F) * (float) i * 0.5F), 0.1D, (double) (Mth.cos(this.getYRot() * 0.017453292F) * (float) i * 0.5F)); + } + +- this.setDeltaMovement(this.getDeltaMovement().multiply(0.6, 1.0, 0.6)); ++ this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D)); + this.setSprinting(false); + } + + if (flag3) { +- float f2 = 1.0F + EnchantmentHelper.getSweepingDamageRatio(this) * f; ++ float f4 = 1.0F + EnchantmentHelper.getSweepingDamageRatio(this) * f; ++ List list = this.level().getEntitiesOfClass(LivingEntity.class, target.getBoundingBox().inflate(1.0D, 0.25D, 1.0D)); ++ Iterator iterator = list.iterator(); + +- for (LivingEntity livingEntity : this.level() +- .getEntitiesOfClass(LivingEntity.class, target.getBoundingBox().inflate(1.0, 0.25, 1.0))) { +- if (livingEntity != this +- && livingEntity != target +- && !this.isAlliedTo(livingEntity) +- && (!(livingEntity instanceof ArmorStand) || !((ArmorStand)livingEntity).isMarker()) +- && this.distanceToSqr(livingEntity) < 9.0) { +- livingEntity.knockback( +- 0.4F, +- (double)Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)), +- (double)(-Mth.cos(this.getYRot() * (float) (Math.PI / 180.0))) +- ); +- livingEntity.hurt(this.damageSources().playerAttack(this), f2); ++ while (iterator.hasNext()) { ++ LivingEntity entityliving = (LivingEntity) iterator.next(); ++ ++ if (entityliving != this && entityliving != target && !this.isAlliedTo((Entity) entityliving) && (!(entityliving instanceof ArmorStand) || !((ArmorStand) entityliving).isMarker()) && this.distanceToSqr((Entity) entityliving) < 9.0D) { ++ // CraftBukkit start - Only apply knockback if the damage hits ++ if (entityliving.hurt(this.damageSources().playerAttack(this).sweep(), f4)) { ++ entityliving.knockback(0.4000000059604645D, (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F))); ++ } ++ // CraftBukkit end + } + } + +- this.level() +- .playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.getSoundSource(), 1.0F, 1.0F); ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.getSoundSource(), 1.0F, 1.0F); + this.sweepAttack(); + } + + if (target instanceof ServerPlayer && target.hurtMarked) { +- ((ServerPlayer)target).connection.send(new ClientboundSetEntityMotionPacket(target)); ++ // CraftBukkit start - Add Velocity Event ++ boolean cancelled = false; ++ org.bukkit.entity.Player player = (org.bukkit.entity.Player) target.getBukkitEntity(); ++ org.bukkit.util.Vector velocity = CraftVector.toBukkit(vec3d); ++ ++ PlayerVelocityEvent event = new PlayerVelocityEvent(player, velocity.clone()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ cancelled = true; ++ } else if (!velocity.equals(event.getVelocity())) { ++ player.setVelocity(event.getVelocity()); ++ } ++ ++ if (!cancelled) { ++ ((ServerPlayer) target).connection.send(new ClientboundSetEntityMotionPacket(target)); + target.hurtMarked = false; +- target.setDeltaMovement(deltaMovement); ++ target.setDeltaMovement(vec3d); ++ } ++ // CraftBukkit end + } + + if (flag2) { +- this.level() +- .playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.getSoundSource(), 1.0F, 1.0F); ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.getSoundSource(), 1.0F, 1.0F); + this.crit(target); + } + + if (!flag2 && !flag3) { + if (flag) { +- this.level() +- .playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_STRONG, this.getSoundSource(), 1.0F, 1.0F); ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_STRONG, this.getSoundSource(), 1.0F, 1.0F); + } else { +- this.level() +- .playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_WEAK, this.getSoundSource(), 1.0F, 1.0F); ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_WEAK, this.getSoundSource(), 1.0F, 1.0F); + } + } + +- if (var23 > 0.0F) { ++ if (f1 > 0.0F) { + this.magicCrit(target); + } + + this.setLastHurtMob(target); + if (target instanceof LivingEntity) { +- EnchantmentHelper.doPostHurtEffects((LivingEntity)target, this); ++ EnchantmentHelper.doPostHurtEffects((LivingEntity) target, this); + } + + EnchantmentHelper.doPostDamageEffects(this, target); +- ItemStack mainHandItem = this.getMainHandItem(); +- Entity entity = target; ++ ItemStack itemstack1 = this.getMainHandItem(); ++ Object object = target; ++ + if (target instanceof EnderDragonPart) { +- entity = ((EnderDragonPart)target).parentMob; ++ object = ((EnderDragonPart) target).parentMob; + } + +- if (!this.level().isClientSide && !mainHandItem.isEmpty() && entity instanceof LivingEntity) { +- mainHandItem.hurtEnemy((LivingEntity)entity, this); +- if (mainHandItem.isEmpty()) { +- this.setItemInHand(InteractionHand.MAIN_HAND, ItemStack.EMPTY); ++ if (!this.level().isClientSide && !itemstack1.isEmpty() && object instanceof LivingEntity) { ++ itemstack1.hurtEnemy((LivingEntity) object, this); ++ if (itemstack1.isEmpty()) { ++ this.setItemInHand(EnumHand.MAIN_HAND, ItemStack.EMPTY); + } + } + + if (target instanceof LivingEntity) { +- float f3 = f1 - ((LivingEntity)target).getHealth(); +- this.awardStat(Stats.DAMAGE_DEALT, Math.round(f3 * 10.0F)); +- if (fireAspect > 0) { +- target.setSecondsOnFire(fireAspect * 4); ++ float f5 = f3 - ((LivingEntity) target).getHealth(); ++ ++ this.awardStat(Stats.DAMAGE_DEALT, Math.round(f5 * 10.0F)); ++ if (j > 0) { ++ // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), target.getBukkitEntity(), j * 4); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ target.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + +- if (this.level() instanceof ServerLevel && f3 > 2.0F) { +- int i1 = (int)((double)f3 * 0.5); +- ((ServerLevel)this.level()) +- .sendParticles(ParticleTypes.DAMAGE_INDICATOR, target.getX(), target.getY(0.5), target.getZ(), i1, 0.1, 0.0, 0.1, 0.2); ++ if (this.level() instanceof ServerLevel && f5 > 2.0F) { ++ int k = (int) ((double) f5 * 0.5D); ++ ++ ((ServerLevel) this.level()).sendParticles(ParticleTypes.DAMAGE_INDICATOR, target.getX(), target.getY(0.5D), target.getZ(), k, 0.1D, 0.0D, 0.1D, 0.2D); + } + } + +- this.causeFoodExhaustion(0.1F); ++ this.causeFoodExhaustion(0.1F, EntityExhaustionEvent.ExhaustionReason.ATTACK); // CraftBukkit - EntityExhaustionEvent + } else { +- this.level() +- .playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F); ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F); + if (flag4) { + target.clearFire(); + } ++ // CraftBukkit start - resync on cancelled event ++ if (this instanceof ServerPlayer) { ++ ((ServerPlayer) this).getBukkitEntity().updateInventory(); ++ } ++ // CraftBukkit end + } + } ++ + } + } + } +@@ -1282,7 +1408,8 @@ + } + + public void disableShield(boolean becauseOfAxe) { +- float f = 0.25F + (float)EnchantmentHelper.getBlockEfficiency(this) * 0.05F; ++ float f = 0.25F + (float) EnchantmentHelper.getBlockEfficiency(this) * 0.05F; ++ + if (becauseOfAxe) { + f += 0.75F; + } +@@ -1290,27 +1417,27 @@ + if (this.random.nextFloat() < f) { + this.getCooldowns().addCooldown(Items.SHIELD, 100); + this.stopUsingItem(); +- this.level().broadcastEntityEvent(this, (byte)30); ++ this.level().broadcastEntityEvent(this, (byte) 30); + } +- } + +- public void crit(Entity entityHit) { + } + +- public void magicCrit(Entity entityHit) { +- } ++ public void crit(Entity entityHit) {} + ++ public void magicCrit(Entity entityHit) {} ++ + public void sweepAttack() { +- double d = (double)(-Mth.sin(this.getYRot() * (float) (Math.PI / 180.0))); +- double d1 = (double)Mth.cos(this.getYRot() * (float) (Math.PI / 180.0)); ++ double d0 = (double) (-Mth.sin(this.getYRot() * 0.017453292F)); ++ double d1 = (double) Mth.cos(this.getYRot() * 0.017453292F); ++ + if (this.level() instanceof ServerLevel) { +- ((ServerLevel)this.level()).sendParticles(ParticleTypes.SWEEP_ATTACK, this.getX() + d, this.getY(0.5), this.getZ() + d1, 0, d, 0.0, d1, 0.0); ++ ((ServerLevel) this.level()).sendParticles(ParticleTypes.SWEEP_ATTACK, this.getX() + d0, this.getY(0.5D), this.getZ() + d1, 0, d0, 0.0D, d1, 0.0D); + } +- } + +- public void respawn() { + } + ++ public void respawn() {} ++ + @Override + public void remove(Entity.RemovalReason reason) { + super.remove(reason); +@@ -1318,6 +1445,7 @@ + if (this.containerMenu != null && this.hasContainerOpen()) { + this.doCloseContainer(); + } ++ + } + + public boolean isLocalPlayer() { +@@ -1336,15 +1464,20 @@ + return this.abilities; + } + +- public void updateTutorialInventoryAction(ItemStack carried, ItemStack clicked, ClickAction action) { +- } ++ public void updateTutorialInventoryAction(ItemStack carried, ItemStack clicked, ClickAction action) {} + + public boolean hasContainerOpen() { + return this.containerMenu != this.inventoryMenu; + } + + public Either startSleepInBed(BlockPos bedPos) { +- this.startSleeping(bedPos); ++ // CraftBukkit start ++ return this.startSleepInBed(bedPos, false); ++ } ++ ++ public Either startSleepInBed(BlockPos blockposition, boolean force) { ++ // CraftBukkit end ++ this.startSleeping(blockposition); + this.sleepCounter = 0; + return Either.right(Unit.INSTANCE); + } +@@ -1352,7 +1485,7 @@ + public void stopSleepInBed(boolean wakeImmediately, boolean updateLevelForSleepingPlayers) { + super.stopSleeping(); + if (this.level() instanceof ServerLevel && updateLevelForSleepingPlayers) { +- ((ServerLevel)this.level()).updateSleepingPlayerList(); ++ ((ServerLevel) this.level()).updateSleepingPlayerList(); + } + + this.sleepCounter = wakeImmediately ? 0 : 100; +@@ -1363,33 +1496,28 @@ + this.stopSleepInBed(true, true); + } + +- public static Optional findRespawnPositionAndUseSpawnBlock( +- ServerLevel serverLevel, BlockPos spawnBlockPos, float playerOrientation, boolean isRespawnForced, boolean respawnAfterWinningTheGame +- ) { +- BlockState blockState = serverLevel.getBlockState(spawnBlockPos); +- Block block = blockState.getBlock(); +- if (block instanceof RespawnAnchorBlock +- && (isRespawnForced || blockState.getValue(RespawnAnchorBlock.CHARGE) > 0) +- && RespawnAnchorBlock.canSetSpawn(serverLevel)) { ++ public static Optional findRespawnPositionAndUseSpawnBlock(ServerLevel serverLevel, BlockPos spawnBlockPos, float playerOrientation, boolean isRespawnForced, boolean respawnAfterWinningTheGame) { ++ IBlockData iblockdata = serverLevel.getBlockState(spawnBlockPos); ++ Block block = iblockdata.getBlock(); ++ ++ if (block instanceof RespawnAnchorBlock && (isRespawnForced || (Integer) iblockdata.getValue(RespawnAnchorBlock.CHARGE) > 0) && RespawnAnchorBlock.canSetSpawn(serverLevel)) { + Optional optional = RespawnAnchorBlock.findStandUpPosition(EntityType.PLAYER, serverLevel, spawnBlockPos); ++ + if (!isRespawnForced && !respawnAfterWinningTheGame && optional.isPresent()) { +- serverLevel.setBlock( +- spawnBlockPos, blockState.setValue(RespawnAnchorBlock.CHARGE, Integer.valueOf(blockState.getValue(RespawnAnchorBlock.CHARGE) - 1)), 3 +- ); ++ serverLevel.setBlock(spawnBlockPos, (IBlockData) iblockdata.setValue(RespawnAnchorBlock.CHARGE, (Integer) iblockdata.getValue(RespawnAnchorBlock.CHARGE) - 1), 3); + } + + return optional; + } else if (block instanceof BedBlock && BedBlock.canSetSpawn(serverLevel)) { +- return BedBlock.findStandUpPosition(EntityType.PLAYER, serverLevel, spawnBlockPos, blockState.getValue(BedBlock.FACING), playerOrientation); ++ return BedBlock.findStandUpPosition(EntityType.PLAYER, serverLevel, spawnBlockPos, (Direction) iblockdata.getValue(BedBlock.FACING), playerOrientation); + } else if (!isRespawnForced) { + return Optional.empty(); + } else { +- boolean isPossibleToRespawnInThis = block.isPossibleToRespawnInThis(blockState); +- BlockState blockState1 = serverLevel.getBlockState(spawnBlockPos.above()); +- boolean isPossibleToRespawnInThis1 = blockState1.getBlock().isPossibleToRespawnInThis(blockState1); +- return isPossibleToRespawnInThis && isPossibleToRespawnInThis1 +- ? Optional.of(new Vec3((double)spawnBlockPos.getX() + 0.5, (double)spawnBlockPos.getY() + 0.1, (double)spawnBlockPos.getZ() + 0.5)) +- : Optional.empty(); ++ boolean flag2 = block.isPossibleToRespawnInThis(iblockdata); ++ IBlockData iblockdata1 = serverLevel.getBlockState(spawnBlockPos.above()); ++ boolean flag3 = iblockdata1.getBlock().isPossibleToRespawnInThis(iblockdata1); ++ ++ return flag2 && flag3 ? Optional.of(new Vec3((double) spawnBlockPos.getX() + 0.5D, (double) spawnBlockPos.getY() + 0.1D, (double) spawnBlockPos.getZ() + 0.5D)) : Optional.empty(); + } + } + +@@ -1401,8 +1529,7 @@ + return this.sleepCounter; + } + +- public void displayClientMessage(Component chatComponent, boolean actionBar) { +- } ++ public void displayClientMessage(Component chatComponent, boolean actionBar) {} + + public void awardStat(ResourceLocation statKey) { + this.awardStat(Stats.CUSTOM.get(statKey)); +@@ -1416,21 +1543,17 @@ + this.awardStat(stat, 1); + } + +- public void awardStat(Stat stat, int increment) { +- } ++ public void awardStat(Stat stat, int increment) {} + +- public void resetStat(Stat stat) { +- } ++ public void resetStat(Stat stat) {} + + public int awardRecipes(Collection> recipes) { + return 0; + } + +- public void triggerRecipeCrafted(RecipeHolder recipeHolder, List list) { +- } ++ public void triggerRecipeCrafted(RecipeHolder recipeholder, List list) {} + +- public void awardRecipesByKey(List list) { +- } ++ public void awardRecipesByKey(List list) {} + + public int resetRecipes(Collection> recipes) { + return 0; +@@ -1441,35 +1564,44 @@ + super.jumpFromGround(); + this.awardStat(Stats.JUMP); + if (this.isSprinting()) { +- this.causeFoodExhaustion(0.2F); ++ this.causeFoodExhaustion(0.2F, EntityExhaustionEvent.ExhaustionReason.JUMP_SPRINT); // CraftBukkit - EntityExhaustionEvent + } else { +- this.causeFoodExhaustion(0.05F); ++ this.causeFoodExhaustion(0.05F, EntityExhaustionEvent.ExhaustionReason.JUMP); // CraftBukkit - EntityExhaustionEvent + } ++ + } + + @Override + public void travel(Vec3 travelVector) { ++ double d0; ++ + if (this.isSwimming() && !this.isPassenger()) { +- double d = this.getLookAngle().y; +- double d1 = d < -0.2 ? 0.085 : 0.06; +- if (d <= 0.0 +- || this.jumping +- || !this.level().getBlockState(BlockPos.containing(this.getX(), this.getY() + 1.0 - 0.1, this.getZ())).getFluidState().isEmpty()) { +- Vec3 deltaMovement = this.getDeltaMovement(); +- this.setDeltaMovement(deltaMovement.add(0.0, (d - deltaMovement.y) * d1, 0.0)); ++ d0 = this.getLookAngle().y; ++ double d1 = d0 < -0.2D ? 0.085D : 0.06D; ++ ++ if (d0 <= 0.0D || this.jumping || !this.level().getBlockState(BlockPos.containing(this.getX(), this.getY() + 1.0D - 0.1D, this.getZ())).getFluidState().isEmpty()) { ++ Vec3 vec3d1 = this.getDeltaMovement(); ++ ++ this.setDeltaMovement(vec3d1.add(0.0D, (d0 - vec3d1.y) * d1, 0.0D)); + } + } + + if (this.abilities.flying && !this.isPassenger()) { +- double d = this.getDeltaMovement().y; ++ d0 = this.getDeltaMovement().y; + super.travel(travelVector); +- Vec3 deltaMovement1 = this.getDeltaMovement(); +- this.setDeltaMovement(deltaMovement1.x, d * 0.6, deltaMovement1.z); ++ Vec3 vec3d2 = this.getDeltaMovement(); ++ ++ this.setDeltaMovement(vec3d2.x, d0 * 0.6D, vec3d2.z); + this.resetFallDistance(); +- this.setSharedFlag(7, false); ++ // CraftBukkit start ++ if (getSharedFlag(7) && !org.bukkit.craftbukkit.event.CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) { ++ this.setSharedFlag(7, false); ++ } ++ // CraftBukkit end + } else { + super.travel(travelVector); + } ++ + } + + @Override +@@ -1479,6 +1611,7 @@ + } else { + super.updateSwimming(); + } ++ + } + + protected boolean freeAt(BlockPos pos) { +@@ -1487,7 +1620,7 @@ + + @Override + public float getSpeed() { +- return (float)this.getAttributeValue(Attributes.MOVEMENT_SPEED); ++ return (float) this.getAttributeValue(Attributes.MOVEMENT_SPEED); + } + + @Override +@@ -1496,7 +1629,7 @@ + return false; + } else { + if (fallDistance >= 2.0F) { +- this.awardStat(Stats.FALL_ONE_CM, (int)Math.round((double)fallDistance * 100.0)); ++ this.awardStat(Stats.FALL_ONE_CM, (int) Math.round((double) fallDistance * 100.0D)); + } + + return super.causeFallDamage(fallDistance, multiplier, source); +@@ -1505,8 +1638,9 @@ + + public boolean tryToStartFallFlying() { + if (!this.onGround() && !this.isFallFlying() && !this.isInWater() && !this.hasEffect(MobEffects.LEVITATION)) { +- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.CHEST); +- if (itemBySlot.is(Items.ELYTRA) && ElytraItem.isFlyEnabled(itemBySlot)) { ++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.CHEST); ++ ++ if (itemstack.is(Items.ELYTRA) && ElytraItem.isFlyEnabled(itemstack)) { + this.startFallFlying(); + return true; + } +@@ -1516,12 +1650,24 @@ + } + + public void startFallFlying() { +- this.setSharedFlag(7, true); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callToggleGlideEvent(this, true).isCancelled()) { ++ this.setSharedFlag(7, true); ++ } else { ++ // SPIGOT-5542: must toggle like below ++ this.setSharedFlag(7, true); ++ this.setSharedFlag(7, false); ++ } ++ // CraftBukkit end + } + + public void stopFallFlying() { ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) { + this.setSharedFlag(7, true); + this.setSharedFlag(7, false); ++ } ++ // CraftBukkit end + } + + @Override +@@ -1529,31 +1675,35 @@ + if (!this.isSpectator()) { + super.doWaterSplashEffect(); + } ++ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState state) { ++ protected void playStepSound(BlockPos pos, IBlockData state) { + if (this.isInWater()) { + this.waterSwimSound(); + this.playMuffledStepSound(state); + } else { +- BlockPos primaryStepSoundBlockPos = this.getPrimaryStepSoundBlockPos(pos); +- if (!pos.equals(primaryStepSoundBlockPos)) { +- BlockState blockState = this.level().getBlockState(primaryStepSoundBlockPos); +- if (blockState.is(BlockTags.COMBINATION_STEP_SOUND_BLOCKS)) { +- this.playCombinationStepSounds(blockState, state); ++ BlockPos blockposition1 = this.getPrimaryStepSoundBlockPos(pos); ++ ++ if (!pos.equals(blockposition1)) { ++ IBlockData iblockdata1 = this.level().getBlockState(blockposition1); ++ ++ if (iblockdata1.is(BlockTags.COMBINATION_STEP_SOUND_BLOCKS)) { ++ this.playCombinationStepSounds(iblockdata1, state); + } else { +- super.playStepSound(primaryStepSoundBlockPos, blockState); ++ super.playStepSound(blockposition1, iblockdata1); + } + } else { + super.playStepSound(pos, state); + } + } ++ + } + + @Override +- public LivingEntity.Fallsounds getFallSounds() { +- return new LivingEntity.Fallsounds(SoundEvents.PLAYER_SMALL_FALL, SoundEvents.PLAYER_BIG_FALL); ++ public LivingEntity.a getFallSounds() { ++ return new LivingEntity.a(SoundEvents.PLAYER_SMALL_FALL, SoundEvents.PLAYER_BIG_FALL); + } + + @Override +@@ -1563,22 +1713,24 @@ + } + + @Override +- public void makeStuckInBlock(BlockState state, Vec3 motionMultiplier) { ++ public void makeStuckInBlock(IBlockData state, Vec3 motionMultiplier) { + if (!this.abilities.flying) { + super.makeStuckInBlock(state, motionMultiplier); + } ++ + } + + public void giveExperiencePoints(int xpPoints) { + this.increaseScore(xpPoints); +- this.experienceProgress = this.experienceProgress + (float)xpPoints / (float)this.getXpNeededForNextLevel(); ++ this.experienceProgress += (float) xpPoints / (float) this.getXpNeededForNextLevel(); + this.totalExperience = Mth.clamp(this.totalExperience + xpPoints, 0, Integer.MAX_VALUE); + + while (this.experienceProgress < 0.0F) { +- float f = this.experienceProgress * (float)this.getXpNeededForNextLevel(); ++ float f = this.experienceProgress * (float) this.getXpNeededForNextLevel(); ++ + if (this.experienceLevel > 0) { + this.giveExperienceLevels(-1); +- this.experienceProgress = 1.0F + f / (float)this.getXpNeededForNextLevel(); ++ this.experienceProgress = 1.0F + f / (float) this.getXpNeededForNextLevel(); + } else { + this.giveExperienceLevels(-1); + this.experienceProgress = 0.0F; +@@ -1586,10 +1738,11 @@ + } + + while (this.experienceProgress >= 1.0F) { +- this.experienceProgress = (this.experienceProgress - 1.0F) * (float)this.getXpNeededForNextLevel(); ++ this.experienceProgress = (this.experienceProgress - 1.0F) * (float) this.getXpNeededForNextLevel(); + this.giveExperienceLevels(1); +- this.experienceProgress = this.experienceProgress / (float)this.getXpNeededForNextLevel(); ++ this.experienceProgress /= (float) this.getXpNeededForNextLevel(); + } ++ + } + + public int getEnchantmentSeed() { +@@ -1615,26 +1768,36 @@ + this.totalExperience = 0; + } + +- if (levels > 0 && this.experienceLevel % 5 == 0 && (float)this.lastLevelUpTime < (float)this.tickCount - 100.0F) { +- float f = this.experienceLevel > 30 ? 1.0F : (float)this.experienceLevel / 30.0F; +- this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_LEVELUP, this.getSoundSource(), f * 0.75F, 1.0F); ++ if (levels > 0 && this.experienceLevel % 5 == 0 && (float) this.lastLevelUpTime < (float) this.tickCount - 100.0F) { ++ float f = this.experienceLevel > 30 ? 1.0F : (float) this.experienceLevel / 30.0F; ++ ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_LEVELUP, this.getSoundSource(), f * 0.75F, 1.0F); + this.lastLevelUpTime = this.tickCount; + } ++ + } + + public int getXpNeededForNextLevel() { +- if (this.experienceLevel >= 30) { +- return 112 + (this.experienceLevel - 30) * 9; +- } else { +- return this.experienceLevel >= 15 ? 37 + (this.experienceLevel - 15) * 5 : 7 + this.experienceLevel * 2; +- } ++ return this.experienceLevel >= 30 ? 112 + (this.experienceLevel - 30) * 9 : (this.experienceLevel >= 15 ? 37 + (this.experienceLevel - 15) * 5 : 7 + this.experienceLevel * 2); + } + ++ // CraftBukkit start + public void causeFoodExhaustion(float exhaustion) { ++ this.causeFoodExhaustion(exhaustion, EntityExhaustionEvent.ExhaustionReason.UNKNOWN); ++ } ++ ++ public void causeFoodExhaustion(float f, EntityExhaustionEvent.ExhaustionReason reason) { ++ // CraftBukkit end + if (!this.abilities.invulnerable) { + if (!this.level().isClientSide) { +- this.foodData.addExhaustion(exhaustion); ++ // CraftBukkit start ++ EntityExhaustionEvent event = CraftEventFactory.callPlayerExhaustionEvent(this, reason, f); ++ if (!event.isCancelled()) { ++ this.foodData.addExhaustion(event.getExhaustion()); ++ } ++ // CraftBukkit end + } ++ + } + } + +@@ -1662,9 +1825,10 @@ + if (this.abilities.mayBuild) { + return true; + } else { +- BlockPos blockPos = pos.relative(facing.getOpposite()); +- BlockInWorld blockInWorld = new BlockInWorld(this.level(), blockPos, false); +- return stack.hasAdventureModePlaceTagForBlock(this.level().registryAccess().registryOrThrow(Registries.BLOCK), blockInWorld); ++ BlockPos blockposition1 = pos.relative(facing.getOpposite()); ++ BlockInWorld shapedetectorblock = new BlockInWorld(this.level(), blockposition1, false); ++ ++ return stack.hasAdventureModePlaceTagForBlock(this.level().registryAccess().registryOrThrow(Registries.BLOCK), shapedetectorblock); + } + } + +@@ -1672,6 +1836,7 @@ + public int getExperienceReward() { + if (!this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) && !this.isSpectator()) { + int i = this.experienceLevel * 7; ++ + return i > 100 ? 100 : i; + } else { + return 0; +@@ -1690,11 +1855,10 @@ + + @Override + protected Entity.MovementEmission getMovementEmission() { +- return this.abilities.flying || this.onGround() && this.isDiscrete() ? Entity.MovementEmission.NONE : Entity.MovementEmission.ALL; ++ return !this.abilities.flying && (!this.onGround() || !this.isDiscrete()) ? Entity.MovementEmission.ALL : Entity.MovementEmission.NONE; + } + +- public void onUpdateAbilities() { +- } ++ public void onUpdateAbilities() {} + + @Override + public Component getName() { +@@ -1707,30 +1871,32 @@ + + @Override + public ItemStack getItemBySlot(EquipmentSlot slot) { +- if (slot == EquipmentSlot.MAINHAND) { +- return this.inventory.getSelected(); +- } else if (slot == EquipmentSlot.OFFHAND) { +- return this.inventory.offhand.get(0); +- } else { +- return slot.getType() == EquipmentSlot.Type.ARMOR ? this.inventory.armor.get(slot.getIndex()) : ItemStack.EMPTY; +- } ++ return slot == EquipmentSlot.MAINHAND ? this.inventory.getSelected() : (slot == EquipmentSlot.OFFHAND ? (ItemStack) this.inventory.offhand.get(0) : (slot.getType() == EquipmentSlot.Function.ARMOR ? (ItemStack) this.inventory.armor.get(slot.getIndex()) : ItemStack.EMPTY)); + } + + @Override + protected boolean doesEmitEquipEvent(EquipmentSlot slot) { +- return slot.getType() == EquipmentSlot.Type.ARMOR; ++ return slot.getType() == EquipmentSlot.Function.ARMOR; + } + + @Override + public void setItemSlot(EquipmentSlot slot, ItemStack stack) { +- this.verifyEquippedItem(stack); +- if (slot == EquipmentSlot.MAINHAND) { +- this.onEquipItem(slot, this.inventory.items.set(this.inventory.selected, stack), stack); +- } else if (slot == EquipmentSlot.OFFHAND) { +- this.onEquipItem(slot, this.inventory.offhand.set(0, stack), stack); +- } else if (slot.getType() == EquipmentSlot.Type.ARMOR) { +- this.onEquipItem(slot, this.inventory.armor.set(slot.getIndex(), stack), stack); ++ // CraftBukkit start ++ setItemSlot(slot, stack, false); ++ } ++ ++ @Override ++ public void setItemSlot(EquipmentSlot enumitemslot, ItemStack itemstack, boolean silent) { ++ // CraftBukkit end ++ this.verifyEquippedItem(itemstack); ++ if (enumitemslot == EquipmentSlot.MAINHAND) { ++ this.onEquipItem(enumitemslot, (ItemStack) this.inventory.items.set(this.inventory.selected, itemstack), itemstack, silent); // CraftBukkit ++ } else if (enumitemslot == EquipmentSlot.OFFHAND) { ++ this.onEquipItem(enumitemslot, (ItemStack) this.inventory.offhand.set(0, itemstack), itemstack, silent); // CraftBukkit ++ } else if (enumitemslot.getType() == EquipmentSlot.Function.ARMOR) { ++ this.onEquipItem(enumitemslot, (ItemStack) this.inventory.armor.set(enumitemslot.getIndex(), itemstack), itemstack, silent); // CraftBukkit + } ++ + } + + public boolean addItem(ItemStack stack) { +@@ -1739,7 +1905,7 @@ + + @Override + public Iterable getHandSlots() { +- return Lists.newArrayList(this.getMainHandItem(), this.getOffhandItem()); ++ return Lists.newArrayList(new ItemStack[]{this.getMainHandItem(), this.getOffhandItem()}); + } + + @Override +@@ -1748,16 +1914,18 @@ + } + + public boolean setEntityOnShoulder(CompoundTag entityCompound) { +- if (this.isPassenger() || !this.onGround() || this.isInWater() || this.isInPowderSnow) { +- return false; +- } else if (this.getShoulderEntityLeft().isEmpty()) { +- this.setShoulderEntityLeft(entityCompound); +- this.timeEntitySatOnShoulder = this.level().getGameTime(); +- return true; +- } else if (this.getShoulderEntityRight().isEmpty()) { +- this.setShoulderEntityRight(entityCompound); +- this.timeEntitySatOnShoulder = this.level().getGameTime(); +- return true; ++ if (!this.isPassenger() && this.onGround() && !this.isInWater() && !this.isInPowderSnow) { ++ if (this.getShoulderEntityLeft().isEmpty()) { ++ this.setShoulderEntityLeft(entityCompound); ++ this.timeEntitySatOnShoulder = this.level().getGameTime(); ++ return true; ++ } else if (this.getShoulderEntityRight().isEmpty()) { ++ this.setShoulderEntityRight(entityCompound); ++ this.timeEntitySatOnShoulder = this.level().getGameTime(); ++ return true; ++ } else { ++ return false; ++ } + } else { + return false; + } +@@ -1765,24 +1933,31 @@ + + protected void removeEntitiesOnShoulder() { + if (this.timeEntitySatOnShoulder + 20L < this.level().getGameTime()) { +- this.respawnEntityOnShoulder(this.getShoulderEntityLeft()); +- this.setShoulderEntityLeft(new CompoundTag()); +- this.respawnEntityOnShoulder(this.getShoulderEntityRight()); +- this.setShoulderEntityRight(new CompoundTag()); ++ // CraftBukkit start ++ if (this.respawnEntityOnShoulder(this.getShoulderEntityLeft())) { ++ this.setShoulderEntityLeft(new CompoundTag()); ++ } ++ if (this.respawnEntityOnShoulder(this.getShoulderEntityRight())) { ++ this.setShoulderEntityRight(new CompoundTag()); ++ } ++ // CraftBukkit end + } ++ + } + +- private void respawnEntityOnShoulder(CompoundTag entityCompound) { +- if (!this.level().isClientSide && !entityCompound.isEmpty()) { +- EntityType.create(entityCompound, this.level()).ifPresent(entity -> { ++ private boolean respawnEntityOnShoulder(CompoundTag nbttagcompound) { // CraftBukkit void->boolean ++ if (!this.level().isClientSide && !nbttagcompound.isEmpty()) { ++ return EntityType.create(nbttagcompound, this.level()).map((entity) -> { // CraftBukkit + if (entity instanceof TamableAnimal) { +- ((TamableAnimal)entity).setOwnerUUID(this.uuid); ++ ((TamableAnimal) entity).setOwnerUUID(this.uuid); + } + +- entity.setPos(this.getX(), this.getY() + 0.7F, this.getZ()); +- ((ServerLevel)this.level()).addWithUUID(entity); +- }); ++ entity.setPos(this.getX(), this.getY() + 0.699999988079071D, this.getZ()); ++ return ((ServerLevel) this.level()).addWithUUID(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit ++ }).orElse(true); // CraftBukkit + } ++ ++ return true; // CraftBukkit + } + + @Override +@@ -1811,17 +1986,17 @@ + + @Override + public Component getDisplayName() { +- MutableComponent mutableComponent = PlayerTeam.formatNameForTeam(this.getTeam(), this.getName()); +- return this.decorateDisplayNameComponent(mutableComponent); ++ MutableComponent ichatmutablecomponent = PlayerTeam.formatNameForTeam(this.getTeam(), this.getName()); ++ ++ return this.decorateDisplayNameComponent(ichatmutablecomponent); + } + + private MutableComponent decorateDisplayNameComponent(MutableComponent displayName) { +- String name = this.getGameProfile().getName(); +- return displayName.withStyle( +- style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/tell " + name + " ")) +- .withHoverEvent(this.createHoverEvent()) +- .withInsertion(name) +- ); ++ String s = this.getGameProfile().getName(); ++ ++ return displayName.withStyle((chatmodifier) -> { ++ return chatmodifier.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/tell " + s + " ")).withHoverEvent(this.createHoverEvent()).withInsertion(s); ++ }); + } + + @Override +@@ -1830,7 +2005,7 @@ + } + + @Override +- public float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ public float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + switch (pose) { + case SWIMMING: + case FALL_FLYING: +@@ -1845,16 +2020,16 @@ + + @Override + protected void internalSetAbsorptionAmount(float f) { +- this.getEntityData().set(DATA_PLAYER_ABSORPTION_ID, f); ++ this.getEntityData().set(Player.DATA_PLAYER_ABSORPTION_ID, f); + } + + @Override + public float getAbsorptionAmount() { +- return this.getEntityData().get(DATA_PLAYER_ABSORPTION_ID); ++ return (Float) this.getEntityData().get(Player.DATA_PLAYER_ABSORPTION_ID); + } + + public boolean isModelPartShown(PlayerModelPart part) { +- return (this.getEntityData().get(DATA_PLAYER_MODE_CUSTOMISATION) & part.getMask()) == part.getMask(); ++ return ((Byte) this.getEntityData().get(Player.DATA_PLAYER_MODE_CUSTOMISATION) & part.getMask()) == part.getMask(); + } + + @Override +@@ -1862,8 +2037,9 @@ + if (slot >= 0 && slot < this.inventory.items.size()) { + return SlotAccess.forContainer(this.inventory, slot); + } else { +- int i = slot - 200; +- return i >= 0 && i < this.enderChestInventory.getContainerSize() ? SlotAccess.forContainer(this.enderChestInventory, i) : super.getSlot(slot); ++ int j = slot - 200; ++ ++ return j >= 0 && j < this.enderChestInventory.getContainerSize() ? SlotAccess.forContainer(this.enderChestInventory, j) : super.getSlot(slot); + } + } + +@@ -1882,35 +2058,35 @@ + + @Override + public HumanoidArm getMainArm() { +- return this.entityData.get(DATA_PLAYER_MAIN_HAND) == 0 ? HumanoidArm.LEFT : HumanoidArm.RIGHT; ++ return (Byte) this.entityData.get(Player.DATA_PLAYER_MAIN_HAND) == 0 ? HumanoidArm.LEFT : HumanoidArm.RIGHT; + } + + public void setMainArm(HumanoidArm hand) { +- this.entityData.set(DATA_PLAYER_MAIN_HAND, (byte)(hand == HumanoidArm.LEFT ? 0 : 1)); ++ this.entityData.set(Player.DATA_PLAYER_MAIN_HAND, (byte) (hand == HumanoidArm.LEFT ? 0 : 1)); + } + + public CompoundTag getShoulderEntityLeft() { +- return this.entityData.get(DATA_SHOULDER_LEFT); ++ return (CompoundTag) this.entityData.get(Player.DATA_SHOULDER_LEFT); + } + +- protected void setShoulderEntityLeft(CompoundTag entityCompound) { +- this.entityData.set(DATA_SHOULDER_LEFT, entityCompound); ++ public void setShoulderEntityLeft(CompoundTag entityCompound) { ++ this.entityData.set(Player.DATA_SHOULDER_LEFT, entityCompound); + } + + public CompoundTag getShoulderEntityRight() { +- return this.entityData.get(DATA_SHOULDER_RIGHT); ++ return (CompoundTag) this.entityData.get(Player.DATA_SHOULDER_RIGHT); + } + +- protected void setShoulderEntityRight(CompoundTag entityCompound) { +- this.entityData.set(DATA_SHOULDER_RIGHT, entityCompound); ++ public void setShoulderEntityRight(CompoundTag entityCompound) { ++ this.entityData.set(Player.DATA_SHOULDER_RIGHT, entityCompound); + } + + public float getCurrentItemAttackStrengthDelay() { +- return (float)(1.0 / this.getAttributeValue(Attributes.ATTACK_SPEED) * 20.0); ++ return (float) (1.0D / this.getAttributeValue(Attributes.ATTACK_SPEED) * 20.0D); + } + + public float getAttackStrengthScale(float adjustTicks) { +- return Mth.clamp(((float)this.attackStrengthTicker + adjustTicks) / this.getCurrentItemAttackStrengthDelay(), 0.0F, 1.0F); ++ return Mth.clamp(((float) this.attackStrengthTicker + adjustTicks) / this.getCurrentItemAttackStrengthDelay(), 0.0F, 1.0F); + } + + public void resetAttackStrengthTicker() { +@@ -1927,7 +2103,7 @@ + } + + public float getLuck() { +- return (float)this.getAttributeValue(Attributes.LUCK); ++ return (float) this.getAttributeValue(Attributes.LUCK); + } + + public boolean canUseGameMasterBlocks() { +@@ -1936,18 +2112,19 @@ + + @Override + public boolean canTakeItem(ItemStack itemstack) { +- EquipmentSlot equipmentSlotForItem = Mob.getEquipmentSlotForItem(itemstack); +- return this.getItemBySlot(equipmentSlotForItem).isEmpty(); ++ EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(itemstack); ++ ++ return this.getItemBySlot(enumitemslot).isEmpty(); + } + + @Override +- public EntityDimensions getDimensions(Pose pose) { +- return POSES.getOrDefault(pose, STANDING_DIMENSIONS); ++ public EntityDimensions getDimensions(EntityPose pose) { ++ return (EntityDimensions) Player.POSES.getOrDefault(pose, Player.STANDING_DIMENSIONS); + } + + @Override +- public ImmutableList getDismountPoses() { +- return ImmutableList.of(Pose.STANDING, Pose.CROUCHING, Pose.SWIMMING); ++ public ImmutableList getDismountPoses() { ++ return ImmutableList.of(EntityPose.STANDING, EntityPose.CROUCHING, EntityPose.SWIMMING); + } + + @Override +@@ -1955,17 +2132,19 @@ + if (!(shootable.getItem() instanceof ProjectileWeaponItem)) { + return ItemStack.EMPTY; + } else { +- Predicate supportedHeldProjectiles = ((ProjectileWeaponItem)shootable.getItem()).getSupportedHeldProjectiles(); +- ItemStack heldProjectile = ProjectileWeaponItem.getHeldProjectile(this, supportedHeldProjectiles); +- if (!heldProjectile.isEmpty()) { +- return heldProjectile; ++ Predicate predicate = ((ProjectileWeaponItem) shootable.getItem()).getSupportedHeldProjectiles(); ++ ItemStack itemstack1 = ProjectileWeaponItem.getHeldProjectile(this, predicate); ++ ++ if (!itemstack1.isEmpty()) { ++ return itemstack1; + } else { +- supportedHeldProjectiles = ((ProjectileWeaponItem)shootable.getItem()).getAllSupportedProjectiles(); ++ predicate = ((ProjectileWeaponItem) shootable.getItem()).getAllSupportedProjectiles(); + +- for (int i = 0; i < this.inventory.getContainerSize(); i++) { +- ItemStack item = this.inventory.getItem(i); +- if (supportedHeldProjectiles.test(item)) { +- return item; ++ for (int i = 0; i < this.inventory.getContainerSize(); ++i) { ++ ItemStack itemstack2 = this.inventory.getItem(i); ++ ++ if (predicate.test(itemstack2)) { ++ return itemstack2; + } + } + +@@ -1978,45 +2157,53 @@ + public ItemStack eat(Level level, ItemStack food) { + this.getFoodData().eat(food.getItem(), food); + this.awardStat(Stats.ITEM_USED.get(food.getItem())); +- level.playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_BURP, SoundSource.PLAYERS, 0.5F, level.random.nextFloat() * 0.1F + 0.9F); ++ level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_BURP, SoundSource.PLAYERS, 0.5F, level.random.nextFloat() * 0.1F + 0.9F); + if (this instanceof ServerPlayer) { +- CriteriaTriggers.CONSUME_ITEM.trigger((ServerPlayer)this, food); ++ CriteriaTriggers.CONSUME_ITEM.trigger((ServerPlayer) this, food); + } + + return super.eat(level, food); + } + + @Override +- protected boolean shouldRemoveSoulSpeed(BlockState state) { ++ protected boolean shouldRemoveSoulSpeed(IBlockData state) { + return this.abilities.flying || super.shouldRemoveSoulSpeed(state); + } + + @Override + public Vec3 getRopeHoldPosition(float partialTicks) { +- double d = 0.22 * (this.getMainArm() == HumanoidArm.RIGHT ? -1.0 : 1.0); +- float f = Mth.lerp(partialTicks * 0.5F, this.getXRot(), this.xRotO) * (float) (Math.PI / 180.0); +- float f1 = Mth.lerp(partialTicks, this.yBodyRotO, this.yBodyRot) * (float) (Math.PI / 180.0); +- if (this.isFallFlying() || this.isAutoSpinAttack()) { +- Vec3 viewVector = this.getViewVector(partialTicks); +- Vec3 deltaMovement = this.getDeltaMovement(); +- double d1 = deltaMovement.horizontalDistanceSqr(); +- double d2 = viewVector.horizontalDistanceSqr(); +- float f2; +- if (d1 > 0.0 && d2 > 0.0) { +- double d3 = (deltaMovement.x * viewVector.x + deltaMovement.z * viewVector.z) / Math.sqrt(d1 * d2); +- double d4 = deltaMovement.x * viewVector.z - deltaMovement.z * viewVector.x; +- f2 = (float)(Math.signum(d4) * Math.acos(d3)); ++ double d0 = 0.22D * (this.getMainArm() == HumanoidArm.RIGHT ? -1.0D : 1.0D); ++ float f1 = Mth.lerp(partialTicks * 0.5F, this.getXRot(), this.xRotO) * 0.017453292F; ++ float f2 = Mth.lerp(partialTicks, this.yBodyRotO, this.yBodyRot) * 0.017453292F; ++ double d1; ++ ++ if (!this.isFallFlying() && !this.isAutoSpinAttack()) { ++ if (this.isVisuallySwimming()) { ++ return this.getPosition(partialTicks).add((new Vec3(d0, 0.2D, -0.15D)).xRot(-f1).yRot(-f2)); + } else { +- f2 = 0.0F; +- } ++ double d2 = this.getBoundingBox().getYsize() - 1.0D; + +- return this.getPosition(partialTicks).add(new Vec3(d, -0.11, 0.85).zRot(-f2).xRot(-f).yRot(-f1)); +- } else if (this.isVisuallySwimming()) { +- return this.getPosition(partialTicks).add(new Vec3(d, 0.2, -0.15).xRot(-f).yRot(-f1)); ++ d1 = this.isCrouching() ? -0.2D : 0.07D; ++ return this.getPosition(partialTicks).add((new Vec3(d0, d2, d1)).yRot(-f2)); ++ } + } else { +- double d5 = this.getBoundingBox().getYsize() - 1.0; +- double d1 = this.isCrouching() ? -0.2 : 0.07; +- return this.getPosition(partialTicks).add(new Vec3(d, d5, d1).yRot(-f1)); ++ Vec3 vec3d = this.getViewVector(partialTicks); ++ Vec3 vec3d1 = this.getDeltaMovement(); ++ ++ d1 = vec3d1.horizontalDistanceSqr(); ++ double d3 = vec3d.horizontalDistanceSqr(); ++ float f3; ++ ++ if (d1 > 0.0D && d3 > 0.0D) { ++ double d4 = (vec3d1.x * vec3d.x + vec3d1.z * vec3d.z) / Math.sqrt(d1 * d3); ++ double d5 = vec3d1.x * vec3d.z - vec3d1.z * vec3d.x; ++ ++ f3 = (float) (Math.signum(d5) * Math.acos(d4)); ++ } else { ++ f3 = 0.0F; ++ } ++ ++ return this.getPosition(partialTicks).add((new Vec3(d0, -0.11D, 0.85D)).zRot(-f3).xRot(-f1).yRot(-f2)); + } + } + +@@ -2060,15 +2247,13 @@ + + @Override + protected float getFlyingSpeed() { +- if (this.abilities.flying && !this.isPassenger()) { +- return this.isSprinting() ? this.abilities.getFlyingSpeed() * 2.0F : this.abilities.getFlyingSpeed(); +- } else { +- return this.isSprinting() ? 0.025999999F : 0.02F; +- } ++ return this.abilities.flying && !this.isPassenger() ? (this.isSprinting() ? this.abilities.getFlyingSpeed() * 2.0F : this.abilities.getFlyingSpeed()) : (this.isSprinting() ? 0.025999999F : 0.02F); + } + +- public static boolean isValidUsername(String string) { +- return string.length() <= 16 && string.chars().filter(i -> i <= 32 || i >= 127).findAny().isEmpty(); ++ public static boolean isValidUsername(String s) { ++ return s.length() > 16 ? false : s.chars().filter((i) -> { ++ return i <= 32 || i >= 127; ++ }).findAny().isEmpty(); + } + + public static float getPickRange(boolean flag) { +@@ -2076,13 +2261,9 @@ + } + + public static enum BedSleepingProblem { +- NOT_POSSIBLE_HERE, +- NOT_POSSIBLE_NOW(Component.translatable("block.minecraft.bed.no_sleep")), +- TOO_FAR_AWAY(Component.translatable("block.minecraft.bed.too_far_away")), +- OBSTRUCTED(Component.translatable("block.minecraft.bed.obstructed")), +- OTHER_PROBLEM, +- NOT_SAFE(Component.translatable("block.minecraft.bed.not_safe")); + ++ NOT_POSSIBLE_HERE, NOT_POSSIBLE_NOW(Component.translatable("block.minecraft.bed.no_sleep")), TOO_FAR_AWAY(Component.translatable("block.minecraft.bed.too_far_away")), OBSTRUCTED(Component.translatable("block.minecraft.bed.obstructed")), OTHER_PROBLEM, NOT_SAFE(Component.translatable("block.minecraft.bed.not_safe")); ++ + @Nullable + private final Component message; + +@@ -2090,8 +2271,8 @@ + this.message = null; + } + +- private BedSleepingProblem(Component message) { +- this.message = message; ++ private BedSleepingProblem(Component ichatbasecomponent) { ++ this.message = ichatbasecomponent; + } + + @Nullable diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/AbstractArrow.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/AbstractArrow.java.patch new file mode 100644 index 0000000000..d546fcc7e3 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/AbstractArrow.java.patch @@ -0,0 +1,784 @@ +--- a/net/minecraft/world/entity/projectile/AbstractArrow.java ++++ b/net/minecraft/world/entity/projectile/AbstractArrow.java +@@ -3,6 +3,8 @@ + import com.google.common.collect.Lists; + import it.unimi.dsi.fastutil.ints.IntOpenHashSet; + import java.util.Arrays; ++import java.util.Collection; ++import java.util.Iterator; + import java.util.List; + import javax.annotation.Nullable; + import net.minecraft.advancements.CriteriaTriggers; +@@ -25,11 +27,12 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.Attributes; ++import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.enchantment.EnchantmentHelper; +@@ -37,56 +40,65 @@ + import net.minecraft.world.level.ClipContext; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.player.PlayerPickupArrowEvent; ++// CraftBukkit end + + public abstract class AbstractArrow extends Projectile { +- private static final double ARROW_BASE_DAMAGE = 2.0; ++ ++ private static final double ARROW_BASE_DAMAGE = 2.0D; + private static final EntityDataAccessor ID_FLAGS = SynchedEntityData.defineId(AbstractArrow.class, EntityDataSerializers.BYTE); + private static final EntityDataAccessor PIERCE_LEVEL = SynchedEntityData.defineId(AbstractArrow.class, EntityDataSerializers.BYTE); + private static final int FLAG_CRIT = 1; + private static final int FLAG_NOPHYSICS = 2; + private static final int FLAG_CROSSBOW = 4; + @Nullable +- private BlockState lastState; +- protected boolean inGround; ++ private IBlockData lastState; ++ public boolean inGround; + protected int inGroundTime; +- public AbstractArrow.Pickup pickup = AbstractArrow.Pickup.DISALLOWED; ++ public AbstractArrow.Pickup pickup; + public int shakeTime; +- private int life; +- private double baseDamage = 2.0; +- private int knockback; +- private SoundEvent soundEvent = this.getDefaultHitGroundSoundEvent(); ++ public int life; ++ private double baseDamage; ++ public int knockback; ++ private SoundEvent soundEvent; + @Nullable + private IntOpenHashSet piercingIgnoreEntityIds; + @Nullable + private List piercedAndKilledEntities; +- private ItemStack pickupItemStack; ++ public ItemStack pickupItemStack; + +- protected AbstractArrow(EntityType entityType, Level level, ItemStack itemStack) { +- super(entityType, level); +- this.pickupItemStack = itemStack.copy(); +- if (itemStack.hasCustomHoverName()) { +- this.setCustomName(itemStack.getHoverName()); ++ protected AbstractArrow(EntityType entitytypes, Level world, ItemStack itemstack) { ++ super(entitytypes, world); ++ this.pickup = AbstractArrow.Pickup.DISALLOWED; ++ this.baseDamage = 2.0D; ++ this.soundEvent = this.getDefaultHitGroundSoundEvent(); ++ this.pickupItemStack = itemstack.copy(); ++ if (itemstack.hasCustomHoverName()) { ++ this.setCustomName(itemstack.getHoverName()); + } ++ + } + +- protected AbstractArrow(EntityType entityType, double d, double d1, double d2, Level level, ItemStack itemStack) { +- this(entityType, level, itemStack); +- this.setPos(d, d1, d2); ++ protected AbstractArrow(EntityType entitytypes, double d0, double d1, double d2, Level world, ItemStack itemstack) { ++ this(entitytypes, world, itemstack); ++ this.setPos(d0, d1, d2); + } + +- protected AbstractArrow(EntityType entityType, LivingEntity livingEntity, Level level, ItemStack itemStack) { +- this(entityType, livingEntity.getX(), livingEntity.getEyeY() - 0.1F, livingEntity.getZ(), level, itemStack); +- this.setOwner(livingEntity); +- if (livingEntity instanceof Player) { ++ protected AbstractArrow(EntityType entitytypes, LivingEntity entityliving, Level world, ItemStack itemstack) { ++ this(entitytypes, entityliving.getX(), entityliving.getEyeY() - 0.10000000149011612D, entityliving.getZ(), world, itemstack); ++ this.setOwner(entityliving); ++ if (entityliving instanceof Player) { + this.pickup = AbstractArrow.Pickup.ALLOWED; + } ++ + } + + public void setSoundEvent(SoundEvent soundEvent) { +@@ -95,61 +107,70 @@ + + @Override + public boolean shouldRenderAtSqrDistance(double distance) { +- double d = this.getBoundingBox().getSize() * 10.0; +- if (Double.isNaN(d)) { +- d = 1.0; ++ double d1 = this.getBoundingBox().getSize() * 10.0D; ++ ++ if (Double.isNaN(d1)) { ++ d1 = 1.0D; + } + +- d *= 64.0 * getViewScale(); +- return distance < d * d; ++ d1 *= 64.0D * getViewScale(); ++ return distance < d1 * d1; + } + + @Override + protected void defineSynchedData() { +- this.entityData.define(ID_FLAGS, (byte)0); +- this.entityData.define(PIERCE_LEVEL, (byte)0); ++ this.entityData.define(AbstractArrow.ID_FLAGS, (byte) 0); ++ this.entityData.define(AbstractArrow.PIERCE_LEVEL, (byte) 0); + } + + @Override +- public void shoot(double x, double y, double z, float velocity, float inaccuracy) { +- super.shoot(x, y, z, velocity, inaccuracy); ++ public void shoot(double x, double d1, double y, float f, float z) { ++ super.shoot(x, d1, y, f, z); + this.life = 0; + } + + @Override +- public void lerpTo(double d, double d1, double d2, float f, float f1, int i) { +- this.setPos(d, d1, d2); ++ public void lerpTo(double d0, double d1, double d2, float f, float f1, int i) { ++ this.setPos(d0, d1, d2); + this.setRot(f, f1); + } + + @Override +- public void lerpMotion(double x, double y, double z) { +- super.lerpMotion(x, y, z); ++ public void lerpMotion(double x, double d1, double y) { ++ super.lerpMotion(x, d1, y); + this.life = 0; + } + + @Override + public void tick() { + super.tick(); +- boolean isNoPhysics = this.isNoPhysics(); +- Vec3 deltaMovement = this.getDeltaMovement(); ++ boolean flag = this.isNoPhysics(); ++ Vec3 vec3d = this.getDeltaMovement(); ++ + if (this.xRotO == 0.0F && this.yRotO == 0.0F) { +- double d = deltaMovement.horizontalDistance(); +- this.setYRot((float)(Mth.atan2(deltaMovement.x, deltaMovement.z) * 180.0F / (float)Math.PI)); +- this.setXRot((float)(Mth.atan2(deltaMovement.y, d) * 180.0F / (float)Math.PI)); ++ double d0 = vec3d.horizontalDistance(); ++ ++ this.setYRot((float) (Mth.atan2(vec3d.x, vec3d.z) * 57.2957763671875D)); ++ this.setXRot((float) (Mth.atan2(vec3d.y, d0) * 57.2957763671875D)); + this.yRotO = this.getYRot(); + this.xRotO = this.getXRot(); + } + +- BlockPos blockPos = this.blockPosition(); +- BlockState blockState = this.level().getBlockState(blockPos); +- if (!blockState.isAir() && !isNoPhysics) { +- VoxelShape collisionShape = blockState.getCollisionShape(this.level(), blockPos); +- if (!collisionShape.isEmpty()) { +- Vec3 vec3 = this.position(); ++ BlockPos blockposition = this.blockPosition(); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); ++ Vec3 vec3d1; + +- for (AABB aABB : collisionShape.toAabbs()) { +- if (aABB.move(blockPos).contains(vec3)) { ++ if (!iblockdata.isAir() && !flag) { ++ VoxelShape voxelshape = iblockdata.getCollisionShape(this.level(), blockposition); ++ ++ if (!voxelshape.isEmpty()) { ++ vec3d1 = this.position(); ++ Iterator iterator = voxelshape.toAabbs().iterator(); ++ ++ while (iterator.hasNext()) { ++ AABB axisalignedbb = (AABB) iterator.next(); ++ ++ if (axisalignedbb.move(blockposition).contains(vec3d1)) { + this.inGround = true; + break; + } +@@ -158,104 +179,104 @@ + } + + if (this.shakeTime > 0) { +- this.shakeTime--; ++ --this.shakeTime; + } + +- if (this.isInWaterOrRain() || blockState.is(Blocks.POWDER_SNOW)) { ++ if (this.isInWaterOrRain() || iblockdata.is(Blocks.POWDER_SNOW)) { + this.clearFire(); + } + +- if (this.inGround && !isNoPhysics) { +- if (this.lastState != blockState && this.shouldFall()) { ++ if (this.inGround && !flag) { ++ if (this.lastState != iblockdata && this.shouldFall()) { + this.startFalling(); + } else if (!this.level().isClientSide) { + this.tickDespawn(); + } + +- this.inGroundTime++; ++ ++this.inGroundTime; + } else { + this.inGroundTime = 0; +- Vec3 vec31 = this.position(); +- Vec3 vec3 = vec31.add(deltaMovement); +- HitResult hitResult = this.level().clip(new ClipContext(vec31, vec3, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)); +- if (hitResult.getType() != HitResult.Type.MISS) { +- vec3 = hitResult.getLocation(); ++ Vec3 vec3d2 = this.position(); ++ ++ vec3d1 = vec3d2.add(vec3d); ++ Object object = this.level().clip(new ClipContext(vec3d2, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)); ++ ++ if (((HitResult) object).getType() != HitResult.EnumMovingObjectType.MISS) { ++ vec3d1 = ((HitResult) object).getLocation(); + } + + while (!this.isRemoved()) { +- EntityHitResult entityHitResult = this.findHitEntity(vec31, vec3); +- if (entityHitResult != null) { +- hitResult = entityHitResult; ++ EntityHitResult movingobjectpositionentity = this.findHitEntity(vec3d2, vec3d1); ++ ++ if (movingobjectpositionentity != null) { ++ object = movingobjectpositionentity; + } + +- if (hitResult != null && hitResult.getType() == HitResult.Type.ENTITY) { +- Entity entity = ((EntityHitResult)hitResult).getEntity(); +- Entity owner = this.getOwner(); +- if (entity instanceof Player && owner instanceof Player && !((Player)owner).canHarmPlayer((Player)entity)) { +- hitResult = null; +- entityHitResult = null; ++ if (object != null && ((HitResult) object).getType() == HitResult.EnumMovingObjectType.ENTITY) { ++ Entity entity = ((EntityHitResult) object).getEntity(); ++ Entity entity1 = this.getOwner(); ++ ++ if (entity instanceof Player && entity1 instanceof Player && !((Player) entity1).canHarmPlayer((Player) entity)) { ++ object = null; ++ movingobjectpositionentity = null; + } + } + +- if (hitResult != null && !isNoPhysics) { +- this.onHit(hitResult); ++ if (object != null && !flag) { ++ this.preOnHit((HitResult) object); // CraftBukkit - projectile hit event + this.hasImpulse = true; + } + +- if (entityHitResult == null || this.getPierceLevel() <= 0) { ++ if (movingobjectpositionentity == null || this.getPierceLevel() <= 0) { + break; + } + +- hitResult = null; ++ object = null; + } + +- deltaMovement = this.getDeltaMovement(); +- double d1 = deltaMovement.x; +- double d2 = deltaMovement.y; +- double d3 = deltaMovement.z; ++ vec3d = this.getDeltaMovement(); ++ double d1 = vec3d.x; ++ double d2 = vec3d.y; ++ double d3 = vec3d.z; ++ + if (this.isCritArrow()) { +- for (int i = 0; i < 4; i++) { +- this.level() +- .addParticle( +- ParticleTypes.CRIT, +- this.getX() + d1 * (double)i / 4.0, +- this.getY() + d2 * (double)i / 4.0, +- this.getZ() + d3 * (double)i / 4.0, +- -d1, +- -d2 + 0.2, +- -d3 +- ); ++ for (int i = 0; i < 4; ++i) { ++ this.level().addParticle(ParticleTypes.CRIT, this.getX() + d1 * (double) i / 4.0D, this.getY() + d2 * (double) i / 4.0D, this.getZ() + d3 * (double) i / 4.0D, -d1, -d2 + 0.2D, -d3); + } + } + + double d4 = this.getX() + d1; + double d5 = this.getY() + d2; + double d6 = this.getZ() + d3; +- double d7 = deltaMovement.horizontalDistance(); +- if (isNoPhysics) { +- this.setYRot((float)(Mth.atan2(-d1, -d3) * 180.0F / (float)Math.PI)); ++ double d7 = vec3d.horizontalDistance(); ++ ++ if (flag) { ++ this.setYRot((float) (Mth.atan2(-d1, -d3) * 57.2957763671875D)); + } else { +- this.setYRot((float)(Mth.atan2(d1, d3) * 180.0F / (float)Math.PI)); ++ this.setYRot((float) (Mth.atan2(d1, d3) * 57.2957763671875D)); + } + +- this.setXRot((float)(Mth.atan2(d2, d7) * 180.0F / (float)Math.PI)); ++ this.setXRot((float) (Mth.atan2(d2, d7) * 57.2957763671875D)); + this.setXRot(lerpRotation(this.xRotO, this.getXRot())); + this.setYRot(lerpRotation(this.yRotO, this.getYRot())); + float f = 0.99F; + float f1 = 0.05F; ++ + if (this.isInWater()) { +- for (int i1 = 0; i1 < 4; i1++) { ++ for (int j = 0; j < 4; ++j) { + float f2 = 0.25F; +- this.level().addParticle(ParticleTypes.BUBBLE, d4 - d1 * 0.25, d5 - d2 * 0.25, d6 - d3 * 0.25, d1, d2, d3); ++ ++ this.level().addParticle(ParticleTypes.BUBBLE, d4 - d1 * 0.25D, d5 - d2 * 0.25D, d6 - d3 * 0.25D, d1, d2, d3); + } + + f = this.getWaterInertia(); + } + +- this.setDeltaMovement(deltaMovement.scale((double)f)); +- if (!this.isNoGravity() && !isNoPhysics) { +- Vec3 deltaMovement1 = this.getDeltaMovement(); +- this.setDeltaMovement(deltaMovement1.x, deltaMovement1.y - 0.05F, deltaMovement1.z); ++ this.setDeltaMovement(vec3d.scale((double) f)); ++ if (!this.isNoGravity() && !flag) { ++ Vec3 vec3d3 = this.getDeltaMovement(); ++ ++ this.setDeltaMovement(vec3d3.x, vec3d3.y - 0.05000000074505806D, vec3d3.z); + } + + this.setPos(d4, d5, d6); +@@ -264,31 +285,32 @@ + } + + private boolean shouldFall() { +- return this.inGround && this.level().noCollision(new AABB(this.position(), this.position()).inflate(0.06)); ++ return this.inGround && this.level().noCollision((new AABB(this.position(), this.position())).inflate(0.06D)); + } + + private void startFalling() { + this.inGround = false; +- Vec3 deltaMovement = this.getDeltaMovement(); +- this.setDeltaMovement( +- deltaMovement.multiply((double)(this.random.nextFloat() * 0.2F), (double)(this.random.nextFloat() * 0.2F), (double)(this.random.nextFloat() * 0.2F)) +- ); ++ Vec3 vec3d = this.getDeltaMovement(); ++ ++ this.setDeltaMovement(vec3d.multiply((double) (this.random.nextFloat() * 0.2F), (double) (this.random.nextFloat() * 0.2F), (double) (this.random.nextFloat() * 0.2F))); + this.life = 0; + } + + @Override +- public void move(MoverType type, Vec3 pos) { ++ public void move(EnumMoveType type, Vec3 pos) { + super.move(type, pos); +- if (type != MoverType.SELF && this.shouldFall()) { ++ if (type != EnumMoveType.SELF && this.shouldFall()) { + this.startFalling(); + } ++ + } + + protected void tickDespawn() { +- this.life++; ++ ++this.life; + if (this.life >= 1200) { + this.discard(); + } ++ + } + + private void resetPiercedEntities() { +@@ -299,14 +321,16 @@ + if (this.piercingIgnoreEntityIds != null) { + this.piercingIgnoreEntityIds.clear(); + } ++ + } + + @Override + protected void onHitEntity(EntityHitResult result) { + super.onHitEntity(result); + Entity entity = result.getEntity(); +- float f = (float)this.getDeltaMovement().length(); +- int ceil = Mth.ceil(Mth.clamp((double)f * this.baseDamage, 0.0, 2.147483647E9)); ++ float f = (float) this.getDeltaMovement().length(); ++ int i = Mth.ceil(Mth.clamp((double) f * this.baseDamage, 0.0D, 2.147483647E9D)); ++ + if (this.getPierceLevel() > 0) { + if (this.piercingIgnoreEntityIds == null) { + this.piercingIgnoreEntityIds = new IntOpenHashSet(5); +@@ -325,65 +349,79 @@ + } + + if (this.isCritArrow()) { +- long l = (long)this.random.nextInt(ceil / 2 + 2); +- ceil = (int)Math.min(l + (long)ceil, 2147483647L); ++ long j = (long) this.random.nextInt(i / 2 + 2); ++ ++ i = (int) Math.min(j + (long) i, 2147483647L); + } + +- Entity owner = this.getOwner(); +- DamageSource damageSource; +- if (owner == null) { +- damageSource = this.damageSources().arrow(this, this); ++ Entity entity1 = this.getOwner(); ++ DamageSource damagesource; ++ ++ if (entity1 == null) { ++ damagesource = this.damageSources().arrow(this, this); + } else { +- damageSource = this.damageSources().arrow(this, owner); +- if (owner instanceof LivingEntity) { +- ((LivingEntity)owner).setLastHurtMob(entity); ++ damagesource = this.damageSources().arrow(this, entity1); ++ if (entity1 instanceof LivingEntity) { ++ ((LivingEntity) entity1).setLastHurtMob(entity); + } + } + + boolean flag = entity.getType() == EntityType.ENDERMAN; +- int remainingFireTicks = entity.getRemainingFireTicks(); +- boolean isDeflectsArrows = entity.getType().is(EntityTypeTags.DEFLECTS_ARROWS); +- if (this.isOnFire() && !flag && !isDeflectsArrows) { +- entity.setSecondsOnFire(5); ++ int k = entity.getRemainingFireTicks(); ++ boolean flag1 = entity.getType().is(EntityTypeTags.DEFLECTS_ARROWS); ++ ++ if (this.isOnFire() && !flag && !flag1) { ++ // CraftBukkit start ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), 5); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ if (!combustEvent.isCancelled()) { ++ entity.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + +- if (entity.hurt(damageSource, (float)ceil)) { ++ if (entity.hurt(damagesource, (float) i)) { + if (flag) { + return; + } + +- if (entity instanceof LivingEntity livingEntity) { ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ + if (!this.level().isClientSide && this.getPierceLevel() <= 0) { +- livingEntity.setArrowCount(livingEntity.getArrowCount() + 1); ++ entityliving.setArrowCount(entityliving.getArrowCount() + 1); + } + + if (this.knockback > 0) { +- double max = Math.max(0.0, 1.0 - livingEntity.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE)); +- Vec3 vec3 = this.getDeltaMovement().multiply(1.0, 0.0, 1.0).normalize().scale((double)this.knockback * 0.6 * max); +- if (vec3.lengthSqr() > 0.0) { +- livingEntity.push(vec3.x, 0.1, vec3.z); ++ double d0 = Math.max(0.0D, 1.0D - entityliving.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE)); ++ Vec3 vec3d = this.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D).normalize().scale((double) this.knockback * 0.6D * d0); ++ ++ if (vec3d.lengthSqr() > 0.0D) { ++ entityliving.push(vec3d.x, 0.1D, vec3d.z); + } + } + +- if (!this.level().isClientSide && owner instanceof LivingEntity) { +- EnchantmentHelper.doPostHurtEffects(livingEntity, owner); +- EnchantmentHelper.doPostDamageEffects((LivingEntity)owner, livingEntity); ++ if (!this.level().isClientSide && entity1 instanceof LivingEntity) { ++ EnchantmentHelper.doPostHurtEffects(entityliving, entity1); ++ EnchantmentHelper.doPostDamageEffects((LivingEntity) entity1, entityliving); + } + +- this.doPostHurtEffects(livingEntity); +- if (owner != null && livingEntity != owner && livingEntity instanceof Player && owner instanceof ServerPlayer && !this.isSilent()) { +- ((ServerPlayer)owner).connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.ARROW_HIT_PLAYER, 0.0F)); ++ this.doPostHurtEffects(entityliving); ++ if (entity1 != null && entityliving != entity1 && entityliving instanceof Player && entity1 instanceof ServerPlayer && !this.isSilent()) { ++ ((ServerPlayer) entity1).connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.ARROW_HIT_PLAYER, 0.0F)); + } + + if (!entity.isAlive() && this.piercedAndKilledEntities != null) { +- this.piercedAndKilledEntities.add(livingEntity); ++ this.piercedAndKilledEntities.add(entityliving); + } + +- if (!this.level().isClientSide && owner instanceof ServerPlayer serverPlayer) { ++ if (!this.level().isClientSide && entity1 instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entity1; ++ + if (this.piercedAndKilledEntities != null && this.shotFromCrossbow()) { +- CriteriaTriggers.KILLED_BY_CROSSBOW.trigger(serverPlayer, this.piercedAndKilledEntities); ++ CriteriaTriggers.KILLED_BY_CROSSBOW.trigger(entityplayer, (Collection) this.piercedAndKilledEntities); + } else if (!entity.isAlive() && this.shotFromCrossbow()) { +- CriteriaTriggers.KILLED_BY_CROSSBOW.trigger(serverPlayer, Arrays.asList(entity)); ++ CriteriaTriggers.KILLED_BY_CROSSBOW.trigger(entityplayer, (Collection) Arrays.asList(entity)); + } + } + } +@@ -392,14 +430,14 @@ + if (this.getPierceLevel() <= 0) { + this.discard(); + } +- } else if (isDeflectsArrows) { ++ } else if (flag1) { + this.deflect(); + } else { +- entity.setRemainingFireTicks(remainingFireTicks); +- this.setDeltaMovement(this.getDeltaMovement().scale(-0.1)); ++ entity.setRemainingFireTicks(k); ++ this.setDeltaMovement(this.getDeltaMovement().scale(-0.1D)); + this.setYRot(this.getYRot() + 180.0F); + this.yRotO += 180.0F; +- if (!this.level().isClientSide && this.getDeltaMovement().lengthSqr() < 1.0E-7) { ++ if (!this.level().isClientSide && this.getDeltaMovement().lengthSqr() < 1.0E-7D) { + if (this.pickup == AbstractArrow.Pickup.ALLOWED) { + this.spawnAtLocation(this.getPickupItem(), 0.1F); + } +@@ -407,11 +445,13 @@ + this.discard(); + } + } ++ + } + + public void deflect() { + float f = this.random.nextFloat() * 360.0F; +- this.setDeltaMovement(this.getDeltaMovement().yRot(f * (float) (Math.PI / 180.0)).scale(0.5)); ++ ++ this.setDeltaMovement(this.getDeltaMovement().yRot(f * 0.017453292F).scale(0.5D)); + this.setYRot(this.getYRot() + f); + this.yRotO += f; + } +@@ -420,15 +460,17 @@ + protected void onHitBlock(BlockHitResult result) { + this.lastState = this.level().getBlockState(result.getBlockPos()); + super.onHitBlock(result); +- Vec3 vec3 = result.getLocation().subtract(this.getX(), this.getY(), this.getZ()); +- this.setDeltaMovement(vec3); +- Vec3 vec31 = vec3.normalize().scale(0.05F); +- this.setPosRaw(this.getX() - vec31.x, this.getY() - vec31.y, this.getZ() - vec31.z); ++ Vec3 vec3d = result.getLocation().subtract(this.getX(), this.getY(), this.getZ()); ++ ++ this.setDeltaMovement(vec3d); ++ Vec3 vec3d1 = vec3d.normalize().scale(0.05000000074505806D); ++ ++ this.setPosRaw(this.getX() - vec3d1.x, this.getY() - vec3d1.y, this.getZ() - vec3d1.z); + this.playSound(this.getHitGroundSoundEvent(), 1.0F, 1.2F / (this.random.nextFloat() * 0.2F + 0.9F)); + this.inGround = true; + this.shakeTime = 7; + this.setCritArrow(false); +- this.setPierceLevel((byte)0); ++ this.setPierceLevel((byte) 0); + this.setSoundEvent(SoundEvents.ARROW_HIT); + this.setShotFromCrossbow(false); + this.resetPiercedEntities(); +@@ -442,14 +484,11 @@ + return this.soundEvent; + } + +- protected void doPostHurtEffects(LivingEntity target) { +- } ++ protected void doPostHurtEffects(LivingEntity target) {} + + @Nullable + protected EntityHitResult findHitEntity(Vec3 startVec, Vec3 endVec) { +- return ProjectileUtil.getEntityHitResult( +- this.level(), this, startVec, endVec, this.getBoundingBox().expandTowards(this.getDeltaMovement()).inflate(1.0), this::canHitEntity +- ); ++ return ProjectileUtil.getEntityHitResult(this.level(), this, startVec, endVec, this.getBoundingBox().expandTowards(this.getDeltaMovement()).inflate(1.0D), this::canHitEntity); + } + + @Override +@@ -460,14 +499,14 @@ + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- compound.putShort("life", (short)this.life); ++ compound.putShort("life", (short) this.life); + if (this.lastState != null) { + compound.put("inBlockState", NbtUtils.writeBlockState(this.lastState)); + } + +- compound.putByte("shake", (byte)this.shakeTime); ++ compound.putByte("shake", (byte) this.shakeTime); + compound.putBoolean("inGround", this.inGround); +- compound.putByte("pickup", (byte)this.pickup.ordinal()); ++ compound.putByte("pickup", (byte) this.pickup.ordinal()); + compound.putDouble("damage", this.baseDamage); + compound.putBoolean("crit", this.isCritArrow()); + compound.putByte("PierceLevel", this.getPierceLevel()); +@@ -494,32 +533,48 @@ + this.setCritArrow(compound.getBoolean("crit")); + this.setPierceLevel(compound.getByte("PierceLevel")); + if (compound.contains("SoundEvent", 8)) { +- this.soundEvent = BuiltInRegistries.SOUND_EVENT +- .getOptional(new ResourceLocation(compound.getString("SoundEvent"))) +- .orElse(this.getDefaultHitGroundSoundEvent()); ++ this.soundEvent = (SoundEvent) BuiltInRegistries.SOUND_EVENT.getOptional(new ResourceLocation(compound.getString("SoundEvent"))).orElse(this.getDefaultHitGroundSoundEvent()); + } + + this.setShotFromCrossbow(compound.getBoolean("ShotFromCrossbow")); + if (compound.contains("item", 10)) { + this.pickupItemStack = ItemStack.of(compound.getCompound("item")); + } ++ + } + + @Override + public void setOwner(@Nullable Entity entity) { + super.setOwner(entity); + if (entity instanceof Player) { +- this.pickup = ((Player)entity).getAbilities().instabuild ? AbstractArrow.Pickup.CREATIVE_ONLY : AbstractArrow.Pickup.ALLOWED; ++ this.pickup = ((Player) entity).getAbilities().instabuild ? AbstractArrow.Pickup.CREATIVE_ONLY : AbstractArrow.Pickup.ALLOWED; + } ++ + } + + @Override + public void playerTouch(Player entity) { + if (!this.level().isClientSide && (this.inGround || this.isNoPhysics()) && this.shakeTime <= 0) { +- if (this.tryPickup(entity)) { ++ // CraftBukkit start ++ ItemStack itemstack = this.getPickupItem(); ++ if (this.pickup == Pickup.ALLOWED && !itemstack.isEmpty() && entity.getInventory().canHold(itemstack) > 0) { ++ ItemEntity item = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), itemstack); ++ PlayerPickupArrowEvent event = new PlayerPickupArrowEvent((org.bukkit.entity.Player) entity.getBukkitEntity(), new org.bukkit.craftbukkit.entity.CraftItem(this.level().getCraftServer(), item), (org.bukkit.entity.AbstractArrow) this.getBukkitEntity()); ++ // event.setCancelled(!entityhuman.canPickUpLoot); TODO ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ itemstack = item.getItem(); ++ } ++ ++ if ((this.pickup == AbstractArrow.Pickup.ALLOWED && entity.getInventory().add(itemstack)) || (this.pickup == AbstractArrow.Pickup.CREATIVE_ONLY && entity.getAbilities().instabuild)) { ++ // CraftBukkit end + entity.take(this, 1); + this.discard(); + } ++ + } + } + +@@ -569,7 +624,7 @@ + } + + @Override +- protected float getEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.13F; + } + +@@ -578,47 +633,53 @@ + } + + public void setPierceLevel(byte pierceLevel) { +- this.entityData.set(PIERCE_LEVEL, pierceLevel); ++ this.entityData.set(AbstractArrow.PIERCE_LEVEL, pierceLevel); + } + + private void setFlag(int id, boolean value) { +- byte b = this.entityData.get(ID_FLAGS); ++ byte b0 = (Byte) this.entityData.get(AbstractArrow.ID_FLAGS); ++ + if (value) { +- this.entityData.set(ID_FLAGS, (byte)(b | id)); ++ this.entityData.set(AbstractArrow.ID_FLAGS, (byte) (b0 | id)); + } else { +- this.entityData.set(ID_FLAGS, (byte)(b & ~id)); ++ this.entityData.set(AbstractArrow.ID_FLAGS, (byte) (b0 & ~id)); + } ++ + } + + public boolean isCritArrow() { +- byte b = this.entityData.get(ID_FLAGS); +- return (b & 1) != 0; ++ byte b0 = (Byte) this.entityData.get(AbstractArrow.ID_FLAGS); ++ ++ return (b0 & 1) != 0; + } + + public boolean shotFromCrossbow() { +- byte b = this.entityData.get(ID_FLAGS); +- return (b & 4) != 0; ++ byte b0 = (Byte) this.entityData.get(AbstractArrow.ID_FLAGS); ++ ++ return (b0 & 4) != 0; + } + + public byte getPierceLevel() { +- return this.entityData.get(PIERCE_LEVEL); ++ return (Byte) this.entityData.get(AbstractArrow.PIERCE_LEVEL); + } + + public void setEnchantmentEffectsFromEntity(LivingEntity shooter, float velocity) { +- int enchantmentLevel = EnchantmentHelper.getEnchantmentLevel(Enchantments.POWER_ARROWS, shooter); +- int enchantmentLevel1 = EnchantmentHelper.getEnchantmentLevel(Enchantments.PUNCH_ARROWS, shooter); +- this.setBaseDamage((double)(velocity * 2.0F) + this.random.triangle((double)this.level().getDifficulty().getId() * 0.11, 0.57425)); +- if (enchantmentLevel > 0) { +- this.setBaseDamage(this.getBaseDamage() + (double)enchantmentLevel * 0.5 + 0.5); ++ int i = EnchantmentHelper.getEnchantmentLevel(Enchantments.POWER_ARROWS, shooter); ++ int j = EnchantmentHelper.getEnchantmentLevel(Enchantments.PUNCH_ARROWS, shooter); ++ ++ this.setBaseDamage((double) (velocity * 2.0F) + this.random.triangle((double) this.level().getDifficulty().getId() * 0.11D, 0.57425D)); ++ if (i > 0) { ++ this.setBaseDamage(this.getBaseDamage() + (double) i * 0.5D + 0.5D); + } + +- if (enchantmentLevel1 > 0) { +- this.setKnockback(enchantmentLevel1); ++ if (j > 0) { ++ this.setKnockback(j); + } + + if (EnchantmentHelper.getEnchantmentLevel(Enchantments.FLAMING_ARROWS, shooter) > 0) { + this.setSecondsOnFire(100); + } ++ + } + + protected float getWaterInertia() { +@@ -631,7 +692,7 @@ + } + + public boolean isNoPhysics() { +- return !this.level().isClientSide ? this.noPhysics : (this.entityData.get(ID_FLAGS) & 2) != 0; ++ return !this.level().isClientSide ? this.noPhysics : ((Byte) this.entityData.get(AbstractArrow.ID_FLAGS) & 2) != 0; + } + + public void setShotFromCrossbow(boolean shotFromCrossbow) { +@@ -639,10 +700,11 @@ + } + + public static enum Pickup { +- DISALLOWED, +- ALLOWED, +- CREATIVE_ONLY; + ++ DISALLOWED, ALLOWED, CREATIVE_ONLY; ++ ++ private Pickup() {} ++ + public static AbstractArrow.Pickup byOrdinal(int ordinal) { + if (ordinal < 0 || ordinal > values().length) { + ordinal = 0; diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java.patch new file mode 100644 index 0000000000..d1dd2b274f --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java.patch @@ -0,0 +1,276 @@ +--- a/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java ++++ b/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java +@@ -16,56 +16,64 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public abstract class AbstractHurtingProjectile extends Projectile { ++ + public double xPower; + public double yPower; + public double zPower; ++ public float bukkitYield = 1; // CraftBukkit ++ public boolean isIncendiary = true; // CraftBukkit + + protected AbstractHurtingProjectile(EntityType entityType, Level level) { + super(entityType, level); + } + +- protected AbstractHurtingProjectile(EntityType entityType, double d, double d1, double d2, Level level) { +- this(entityType, level); +- this.setPos(d, d1, d2); ++ protected AbstractHurtingProjectile(EntityType entitytypes, double d0, double d1, double d2, Level world) { ++ this(entitytypes, world); ++ this.setPos(d0, d1, d2); + } + +- public AbstractHurtingProjectile( +- EntityType entityType, double x, double y, double z, double offsetX, double offsetY, double offsetZ, Level level +- ) { +- this(entityType, level); +- this.moveTo(x, y, z, this.getYRot(), this.getXRot()); ++ public AbstractHurtingProjectile(EntityType entityType, double x, double d1, double y, double d3, double z, double d5, Level offsetX) { ++ this(entityType, offsetX); ++ this.moveTo(x, d1, y, this.getYRot(), this.getXRot()); + this.reapplyPosition(); +- double squareRoot = Math.sqrt(offsetX * offsetX + offsetY * offsetY + offsetZ * offsetZ); +- if (squareRoot != 0.0) { +- this.xPower = offsetX / squareRoot * 0.1; +- this.yPower = offsetY / squareRoot * 0.1; +- this.zPower = offsetZ / squareRoot * 0.1; ++ // CraftBukkit start - Added setDirection method ++ this.setDirection(d3, z, d5); ++ } ++ ++ public void setDirection(double d3, double d4, double d5) { ++ // CraftBukkit end ++ double d6 = Math.sqrt(d3 * d3 + d4 * d4 + d5 * d5); ++ ++ if (d6 != 0.0D) { ++ this.xPower = d3 / d6 * 0.1D; ++ this.yPower = d4 / d6 * 0.1D; ++ this.zPower = d5 / d6 * 0.1D; + } ++ + } + +- public AbstractHurtingProjectile( +- EntityType entityType, LivingEntity shooter, double offsetX, double offsetY, double offsetZ, Level level +- ) { +- this(entityType, shooter.getX(), shooter.getY(), shooter.getZ(), offsetX, offsetY, offsetZ, level); ++ public AbstractHurtingProjectile(EntityType entityType, LivingEntity shooter, double offsetX, double d1, double offsetY, Level world) { ++ this(entityType, shooter.getX(), shooter.getY(), shooter.getZ(), offsetX, d1, offsetY, world); + this.setOwner(shooter); + this.setRot(shooter.getYRot(), shooter.getXRot()); + } + + @Override +- protected void defineSynchedData() { +- } ++ protected void defineSynchedData() {} + + @Override + public boolean shouldRenderAtSqrDistance(double distance) { +- double d = this.getBoundingBox().getSize() * 4.0; +- if (Double.isNaN(d)) { +- d = 4.0; ++ double d1 = this.getBoundingBox().getSize() * 4.0D; ++ ++ if (Double.isNaN(d1)) { ++ d1 = 4.0D; + } + +- d *= 64.0; +- return distance < d * d; ++ d1 *= 64.0D; ++ return distance < d1 * d1; + } + + protected ClipContext.Block getClipType() { +@@ -74,54 +82,57 @@ + + @Override + public void tick() { +- Entity owner = this.getOwner(); +- if (this.level().isClientSide || (owner == null || !owner.isRemoved()) && this.level().hasChunkAt(this.blockPosition())) { ++ Entity entity = this.getOwner(); ++ ++ if (!this.level().isClientSide && (entity != null && entity.isRemoved() || !this.level().hasChunkAt(this.blockPosition()))) { ++ this.discard(); ++ } else { + super.tick(); + if (this.shouldBurn()) { + this.setSecondsOnFire(1); + } + +- HitResult hitResultOnMoveVector = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity, this.getClipType()); +- if (hitResultOnMoveVector.getType() != HitResult.Type.MISS) { +- this.onHit(hitResultOnMoveVector); ++ HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity, this.getClipType()); ++ ++ if (movingobjectposition.getType() != HitResult.EnumMovingObjectType.MISS) { ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event ++ ++ // CraftBukkit start - Fire ProjectileHitEvent ++ if (this.isRemoved()) { ++ CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); ++ } ++ // CraftBukkit end + } + + this.checkInsideBlocks(); +- Vec3 deltaMovement = this.getDeltaMovement(); +- double d = this.getX() + deltaMovement.x; +- double d1 = this.getY() + deltaMovement.y; +- double d2 = this.getZ() + deltaMovement.z; ++ Vec3 vec3d = this.getDeltaMovement(); ++ double d0 = this.getX() + vec3d.x; ++ double d1 = this.getY() + vec3d.y; ++ double d2 = this.getZ() + vec3d.z; ++ + ProjectileUtil.rotateTowardsMovement(this, 0.2F); +- float liquidInertia; ++ float f; ++ + if (this.isInWater()) { +- for (int i = 0; i < 4; i++) { +- float f = 0.25F; +- this.level() +- .addParticle( +- ParticleTypes.BUBBLE, +- d - deltaMovement.x * 0.25, +- d1 - deltaMovement.y * 0.25, +- d2 - deltaMovement.z * 0.25, +- deltaMovement.x, +- deltaMovement.y, +- deltaMovement.z +- ); ++ for (int i = 0; i < 4; ++i) { ++ float f1 = 0.25F; ++ ++ this.level().addParticle(ParticleTypes.BUBBLE, d0 - vec3d.x * 0.25D, d1 - vec3d.y * 0.25D, d2 - vec3d.z * 0.25D, vec3d.x, vec3d.y, vec3d.z); + } + +- liquidInertia = this.getLiquidInertia(); ++ f = this.getLiquidInertia(); + } else { +- liquidInertia = this.getInertia(); ++ f = this.getInertia(); + } + +- this.setDeltaMovement(deltaMovement.add(this.xPower, this.yPower, this.zPower).scale((double)liquidInertia)); +- ParticleOptions trailParticle = this.getTrailParticle(); +- if (trailParticle != null) { +- this.level().addParticle(trailParticle, d, d1 + 0.5, d2, 0.0, 0.0, 0.0); ++ this.setDeltaMovement(vec3d.add(this.xPower, this.yPower, this.zPower).scale((double) f)); ++ ParticleOptions particleparam = this.getTrailParticle(); ++ ++ if (particleparam != null) { ++ this.level().addParticle(particleparam, d0, d1 + 0.5D, d2, 0.0D, 0.0D, 0.0D); + } + +- this.setPos(d, d1, d2); +- } else { +- this.discard(); ++ this.setPos(d0, d1, d2); + } + } + +@@ -157,13 +168,15 @@ + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); + if (compound.contains("power", 9)) { +- ListTag list = compound.getList("power", 6); +- if (list.size() == 3) { +- this.xPower = list.getDouble(0); +- this.yPower = list.getDouble(1); +- this.zPower = list.getDouble(2); ++ ListTag nbttaglist = compound.getList("power", 6); ++ ++ if (nbttaglist.size() == 3) { ++ this.xPower = nbttaglist.getDouble(0); ++ this.yPower = nbttaglist.getDouble(1); ++ this.zPower = nbttaglist.getDouble(2); + } + } ++ + } + + @Override +@@ -183,13 +196,20 @@ + } else { + this.markHurt(); + Entity entity = source.getEntity(); ++ + if (entity != null) { + if (!this.level().isClientSide) { +- Vec3 lookAngle = entity.getLookAngle(); +- this.setDeltaMovement(lookAngle); +- this.xPower = lookAngle.x * 0.1; +- this.yPower = lookAngle.y * 0.1; +- this.zPower = lookAngle.z * 0.1; ++ // CraftBukkit start ++ if (CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, false)) { ++ return false; ++ } ++ // CraftBukkit end ++ Vec3 vec3d = entity.getLookAngle(); ++ ++ this.setDeltaMovement(vec3d); ++ this.xPower = vec3d.x * 0.1D; ++ this.yPower = vec3d.y * 0.1D; ++ this.zPower = vec3d.z * 0.1D; + this.setOwner(entity); + } + +@@ -207,34 +227,25 @@ + + @Override + public Packet getAddEntityPacket() { +- Entity owner = this.getOwner(); +- int i = owner == null ? 0 : owner.getId(); +- return new ClientboundAddEntityPacket( +- this.getId(), +- this.getUUID(), +- this.getX(), +- this.getY(), +- this.getZ(), +- this.getXRot(), +- this.getYRot(), +- this.getType(), +- i, +- new Vec3(this.xPower, this.yPower, this.zPower), +- 0.0 +- ); ++ Entity entity = this.getOwner(); ++ int i = entity == null ? 0 : entity.getId(); ++ ++ return new ClientboundAddEntityPacket(this.getId(), this.getUUID(), this.getX(), this.getY(), this.getZ(), this.getXRot(), this.getYRot(), this.getType(), i, new Vec3(this.xPower, this.yPower, this.zPower), 0.0D); + } + + @Override + public void recreateFromPacket(ClientboundAddEntityPacket packet) { + super.recreateFromPacket(packet); +- double xa = packet.getXa(); +- double ya = packet.getYa(); +- double za = packet.getZa(); +- double squareRoot = Math.sqrt(xa * xa + ya * ya + za * za); +- if (squareRoot != 0.0) { +- this.xPower = xa / squareRoot * 0.1; +- this.yPower = ya / squareRoot * 0.1; +- this.zPower = za / squareRoot * 0.1; ++ double d0 = packet.getXa(); ++ double d1 = packet.getYa(); ++ double d2 = packet.getZa(); ++ double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2); ++ ++ if (d3 != 0.0D) { ++ this.xPower = d0 / d3 * 0.1D; ++ this.yPower = d1 / d3 * 0.1D; ++ this.zPower = d2 / d3 * 0.1D; + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/Arrow.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/Arrow.java.patch new file mode 100644 index 0000000000..4ee848deb3 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/Arrow.java.patch @@ -0,0 +1,306 @@ +--- a/net/minecraft/world/entity/projectile/Arrow.java ++++ b/net/minecraft/world/entity/projectile/Arrow.java +@@ -2,6 +2,7 @@ + + import com.google.common.collect.Sets; + import java.util.Collection; ++import java.util.Iterator; + import java.util.Set; + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.core.registries.BuiltInRegistries; +@@ -22,73 +23,89 @@ + import net.minecraft.world.level.Level; + + public class Arrow extends AbstractArrow { ++ + private static final int EXPOSED_POTION_DECAY_TIME = 600; + private static final int NO_EFFECT_COLOR = -1; + private static final EntityDataAccessor ID_EFFECT_COLOR = SynchedEntityData.defineId(Arrow.class, EntityDataSerializers.INT); + private static final byte EVENT_POTION_PUFF = 0; + private static final ItemStack DEFAULT_ARROW_STACK = new ItemStack(Items.ARROW); +- private Potion potion = Potions.EMPTY; +- private final Set effects = Sets.newHashSet(); ++ public Potion potion; ++ public final Set effects; + private boolean fixedColor; + + public Arrow(EntityType entityType, Level level) { +- super(entityType, level, DEFAULT_ARROW_STACK); ++ super(entityType, level, Arrow.DEFAULT_ARROW_STACK); ++ this.potion = Potions.EMPTY; ++ this.effects = Sets.newHashSet(); + } + +- public Arrow(Level level, double d, double d1, double d2, ItemStack itemStack) { +- super(EntityType.ARROW, d, d1, d2, level, itemStack); ++ public Arrow(Level world, double d0, double d1, double d2, ItemStack itemstack) { ++ super(EntityType.ARROW, d0, d1, d2, world, itemstack); ++ this.potion = Potions.EMPTY; ++ this.effects = Sets.newHashSet(); + } + +- public Arrow(Level level, LivingEntity livingEntity, ItemStack itemStack) { +- super(EntityType.ARROW, livingEntity, level, itemStack); ++ public Arrow(Level world, LivingEntity entityliving, ItemStack itemstack) { ++ super(EntityType.ARROW, entityliving, world, itemstack); ++ this.potion = Potions.EMPTY; ++ this.effects = Sets.newHashSet(); + } + + public void setEffectsFromItem(ItemStack stack) { + if (stack.is(Items.TIPPED_ARROW)) { + this.potion = PotionUtils.getPotion(stack); +- Collection customEffects = PotionUtils.getCustomEffects(stack); +- if (!customEffects.isEmpty()) { +- for (MobEffectInstance mobEffectInstance : customEffects) { +- this.effects.add(new MobEffectInstance(mobEffectInstance)); ++ Collection collection = PotionUtils.getCustomEffects(stack); ++ ++ if (!collection.isEmpty()) { ++ Iterator iterator = collection.iterator(); ++ ++ while (iterator.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); ++ ++ this.effects.add(new MobEffectInstance(mobeffect)); + } + } + +- int customColor = getCustomColor(stack); +- if (customColor == -1) { ++ int i = getCustomColor(stack); ++ ++ if (i == -1) { + this.updateColor(); + } else { +- this.setFixedColor(customColor); ++ this.setFixedColor(i); + } + } else if (stack.is(Items.ARROW)) { + this.potion = Potions.EMPTY; + this.effects.clear(); +- this.entityData.set(ID_EFFECT_COLOR, -1); ++ this.entityData.set(Arrow.ID_EFFECT_COLOR, -1); + } ++ + } + + public static int getCustomColor(ItemStack stack) { +- CompoundTag tag = stack.getTag(); +- return tag != null && tag.contains("CustomPotionColor", 99) ? tag.getInt("CustomPotionColor") : -1; ++ CompoundTag nbttagcompound = stack.getTag(); ++ ++ return nbttagcompound != null && nbttagcompound.contains("CustomPotionColor", 99) ? nbttagcompound.getInt("CustomPotionColor") : -1; + } + +- private void updateColor() { ++ public void updateColor() { + this.fixedColor = false; + if (this.potion == Potions.EMPTY && this.effects.isEmpty()) { +- this.entityData.set(ID_EFFECT_COLOR, -1); ++ this.entityData.set(Arrow.ID_EFFECT_COLOR, -1); + } else { +- this.entityData.set(ID_EFFECT_COLOR, PotionUtils.getColor(PotionUtils.getAllEffects(this.potion, this.effects))); ++ this.entityData.set(Arrow.ID_EFFECT_COLOR, PotionUtils.getColor((Collection) PotionUtils.getAllEffects(this.potion, this.effects))); + } ++ + } + + public void addEffect(MobEffectInstance effectInstance) { + this.effects.add(effectInstance); +- this.getEntityData().set(ID_EFFECT_COLOR, PotionUtils.getColor(PotionUtils.getAllEffects(this.potion, this.effects))); ++ this.getEntityData().set(Arrow.ID_EFFECT_COLOR, PotionUtils.getColor((Collection) PotionUtils.getAllEffects(this.potion, this.effects))); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(ID_EFFECT_COLOR, -1); ++ this.entityData.define(Arrow.ID_EFFECT_COLOR, -1); + } + + @Override +@@ -103,33 +120,36 @@ + this.makeParticle(2); + } + } else if (this.inGround && this.inGroundTime != 0 && !this.effects.isEmpty() && this.inGroundTime >= 600) { +- this.level().broadcastEntityEvent(this, (byte)0); ++ this.level().broadcastEntityEvent(this, (byte) 0); + this.potion = Potions.EMPTY; + this.effects.clear(); +- this.entityData.set(ID_EFFECT_COLOR, -1); ++ this.entityData.set(Arrow.ID_EFFECT_COLOR, -1); + } ++ + } + + private void makeParticle(int particleAmount) { +- int color = this.getColor(); +- if (color != -1 && particleAmount > 0) { +- double d = (double)(color >> 16 & 0xFF) / 255.0; +- double d1 = (double)(color >> 8 & 0xFF) / 255.0; +- double d2 = (double)(color >> 0 & 0xFF) / 255.0; ++ int j = this.getColor(); + +- for (int i = 0; i < particleAmount; i++) { +- this.level().addParticle(ParticleTypes.ENTITY_EFFECT, this.getRandomX(0.5), this.getRandomY(), this.getRandomZ(0.5), d, d1, d2); ++ if (j != -1 && particleAmount > 0) { ++ double d0 = (double) (j >> 16 & 255) / 255.0D; ++ double d1 = (double) (j >> 8 & 255) / 255.0D; ++ double d2 = (double) (j >> 0 & 255) / 255.0D; ++ ++ for (int k = 0; k < particleAmount; ++k) { ++ this.level().addParticle(ParticleTypes.ENTITY_EFFECT, this.getRandomX(0.5D), this.getRandomY(), this.getRandomZ(0.5D), d0, d1, d2); + } ++ + } + } + + public int getColor() { +- return this.entityData.get(ID_EFFECT_COLOR); ++ return (Integer) this.entityData.get(Arrow.ID_EFFECT_COLOR); + } + +- private void setFixedColor(int fixedColor) { ++ public void setFixedColor(int fixedColor) { + this.fixedColor = true; +- this.entityData.set(ID_EFFECT_COLOR, fixedColor); ++ this.entityData.set(Arrow.ID_EFFECT_COLOR, fixedColor); + } + + @Override +@@ -144,14 +164,18 @@ + } + + if (!this.effects.isEmpty()) { +- ListTag list = new ListTag(); ++ ListTag nbttaglist = new ListTag(); ++ Iterator iterator = this.effects.iterator(); + +- for (MobEffectInstance mobEffectInstance : this.effects) { +- list.add(mobEffectInstance.save(new CompoundTag())); ++ while (iterator.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); ++ ++ nbttaglist.add(mobeffect.save(new CompoundTag())); + } + +- compound.put("custom_potion_effects", list); ++ compound.put("custom_potion_effects", nbttaglist); + } ++ + } + + @Override +@@ -161,8 +185,12 @@ + this.potion = PotionUtils.getPotion(compound); + } + +- for (MobEffectInstance mobEffectInstance : PotionUtils.getCustomEffects(compound)) { +- this.addEffect(mobEffectInstance); ++ Iterator iterator = PotionUtils.getCustomEffects(compound).iterator(); ++ ++ while (iterator.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); ++ ++ this.addEffect(mobeffect); + } + + if (compound.contains("Color", 99)) { +@@ -170,64 +198,69 @@ + } else { + this.updateColor(); + } ++ + } + + @Override + protected void doPostHurtEffects(LivingEntity living) { + super.doPostHurtEffects(living); +- Entity effectSource = this.getEffectSource(); ++ Entity entity = this.getEffectSource(); ++ Iterator iterator = this.potion.getEffects().iterator(); + +- for (MobEffectInstance mobEffectInstance : this.potion.getEffects()) { +- living.addEffect( +- new MobEffectInstance( +- mobEffectInstance.getEffect(), +- Math.max(mobEffectInstance.mapDuration(i -> i / 8), 1), +- mobEffectInstance.getAmplifier(), +- mobEffectInstance.isAmbient(), +- mobEffectInstance.isVisible() +- ), +- effectSource +- ); ++ MobEffectInstance mobeffect; ++ ++ while (iterator.hasNext()) { ++ mobeffect = (MobEffectInstance) iterator.next(); ++ living.addEffect(new MobEffectInstance(mobeffect.getEffect(), Math.max(mobeffect.mapDuration((i) -> { ++ return i / 8; ++ }), 1), mobeffect.getAmplifier(), mobeffect.isAmbient(), mobeffect.isVisible()), entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ARROW); // CraftBukkit + } + + if (!this.effects.isEmpty()) { +- for (MobEffectInstance mobEffectInstance : this.effects) { +- living.addEffect(mobEffectInstance, effectSource); ++ iterator = this.effects.iterator(); ++ ++ while (iterator.hasNext()) { ++ mobeffect = (MobEffectInstance) iterator.next(); ++ living.addEffect(mobeffect, entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ARROW); // CraftBukkit + } + } ++ + } + + @Override + protected ItemStack getPickupItem() { +- ItemStack itemStack = super.getPickupItem(); ++ ItemStack itemstack = super.getPickupItem(); ++ + if (this.effects.isEmpty() && this.potion == Potions.EMPTY) { +- return itemStack; ++ return itemstack; + } else { +- PotionUtils.setPotion(itemStack, this.potion); +- PotionUtils.setCustomEffects(itemStack, this.effects); ++ PotionUtils.setPotion(itemstack, this.potion); ++ PotionUtils.setCustomEffects(itemstack, this.effects); + if (this.fixedColor) { +- itemStack.getOrCreateTag().putInt("CustomPotionColor", this.getColor()); ++ itemstack.getOrCreateTag().putInt("CustomPotionColor", this.getColor()); + } + +- return itemStack; ++ return itemstack; + } + } + + @Override + public void handleEntityEvent(byte id) { + if (id == 0) { +- int color = this.getColor(); +- if (color != -1) { +- double d = (double)(color >> 16 & 0xFF) / 255.0; +- double d1 = (double)(color >> 8 & 0xFF) / 255.0; +- double d2 = (double)(color >> 0 & 0xFF) / 255.0; ++ int i = this.getColor(); + +- for (int i = 0; i < 20; i++) { +- this.level().addParticle(ParticleTypes.ENTITY_EFFECT, this.getRandomX(0.5), this.getRandomY(), this.getRandomZ(0.5), d, d1, d2); ++ if (i != -1) { ++ double d0 = (double) (i >> 16 & 255) / 255.0D; ++ double d1 = (double) (i >> 8 & 255) / 255.0D; ++ double d2 = (double) (i >> 0 & 255) / 255.0D; ++ ++ for (int j = 0; j < 20; ++j) { ++ this.level().addParticle(ParticleTypes.ENTITY_EFFECT, this.getRandomX(0.5D), this.getRandomY(), this.getRandomZ(0.5D), d0, d1, d2); + } + } + } else { + super.handleEntityEvent(id); + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/EvokerFangs.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/EvokerFangs.java.patch new file mode 100644 index 0000000000..904fa91739 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/EvokerFangs.java.patch @@ -0,0 +1,192 @@ +--- a/net/minecraft/world/entity/projectile/EvokerFangs.java ++++ b/net/minecraft/world/entity/projectile/EvokerFangs.java +@@ -1,5 +1,7 @@ + package net.minecraft.world.entity.projectile; + ++import java.util.Iterator; ++import java.util.List; + import java.util.UUID; + import javax.annotation.Nullable; + import net.minecraft.core.particles.ParticleTypes; +@@ -13,12 +15,13 @@ + import net.minecraft.world.level.Level; + + public class EvokerFangs extends Entity implements TraceableEntity { ++ + public static final int ATTACK_DURATION = 20; + public static final int LIFE_OFFSET = 2; + public static final int ATTACK_TRIGGER_TICKS = 14; +- private int warmupDelayTicks; ++ public int warmupDelayTicks; + private boolean sentSpikeEvent; +- private int lifeTicks = 22; ++ private int lifeTicks; + private boolean clientSideAttackStarted; + @Nullable + private LivingEntity owner; +@@ -27,19 +30,19 @@ + + public EvokerFangs(EntityType entityType, Level level) { + super(entityType, level); ++ this.lifeTicks = 22; + } + +- public EvokerFangs(Level level, double x, double y, double z, float yRot, int warmupDelay, LivingEntity owner) { ++ public EvokerFangs(Level level, double x, double d1, double y, float f, int z, LivingEntity entityliving) { + this(EntityType.EVOKER_FANGS, level); +- this.warmupDelayTicks = warmupDelay; +- this.setOwner(owner); +- this.setYRot(yRot * (180.0F / (float)Math.PI)); +- this.setPos(x, y, z); ++ this.warmupDelayTicks = z; ++ this.setOwner(entityliving); ++ this.setYRot(f * 57.295776F); ++ this.setPos(x, d1, y); + } + + @Override +- protected void defineSynchedData() { +- } ++ protected void defineSynchedData() {} + + public void setOwner(@Nullable LivingEntity owner) { + this.owner = owner; +@@ -50,9 +53,10 @@ + @Override + public LivingEntity getOwner() { + if (this.owner == null && this.ownerUUID != null && this.level() instanceof ServerLevel) { +- Entity entity = ((ServerLevel)this.level()).getEntity(this.ownerUUID); ++ Entity entity = ((ServerLevel) this.level()).getEntity(this.ownerUUID); ++ + if (entity instanceof LivingEntity) { +- this.owner = (LivingEntity)entity; ++ this.owner = (LivingEntity) entity; + } + } + +@@ -65,6 +69,7 @@ + if (compound.hasUUID("Owner")) { + this.ownerUUID = compound.getUUID("Owner"); + } ++ + } + + @Override +@@ -73,6 +78,7 @@ + if (this.ownerUUID != null) { + compound.putUUID("Owner", this.ownerUUID); + } ++ + } + + @Override +@@ -80,28 +86,34 @@ + super.tick(); + if (this.level().isClientSide) { + if (this.clientSideAttackStarted) { +- this.lifeTicks--; ++ --this.lifeTicks; + if (this.lifeTicks == 14) { +- for (int i = 0; i < 12; i++) { +- double d = this.getX() + (this.random.nextDouble() * 2.0 - 1.0) * (double)this.getBbWidth() * 0.5; +- double d1 = this.getY() + 0.05 + this.random.nextDouble(); +- double d2 = this.getZ() + (this.random.nextDouble() * 2.0 - 1.0) * (double)this.getBbWidth() * 0.5; +- double d3 = (this.random.nextDouble() * 2.0 - 1.0) * 0.3; +- double d4 = 0.3 + this.random.nextDouble() * 0.3; +- double d5 = (this.random.nextDouble() * 2.0 - 1.0) * 0.3; +- this.level().addParticle(ParticleTypes.CRIT, d, d1 + 1.0, d2, d3, d4, d5); ++ for (int i = 0; i < 12; ++i) { ++ double d0 = this.getX() + (this.random.nextDouble() * 2.0D - 1.0D) * (double) this.getBbWidth() * 0.5D; ++ double d1 = this.getY() + 0.05D + this.random.nextDouble(); ++ double d2 = this.getZ() + (this.random.nextDouble() * 2.0D - 1.0D) * (double) this.getBbWidth() * 0.5D; ++ double d3 = (this.random.nextDouble() * 2.0D - 1.0D) * 0.3D; ++ double d4 = 0.3D + this.random.nextDouble() * 0.3D; ++ double d5 = (this.random.nextDouble() * 2.0D - 1.0D) * 0.3D; ++ ++ this.level().addParticle(ParticleTypes.CRIT, d0, d1 + 1.0D, d2, d3, d4, d5); + } + } + } + } else if (--this.warmupDelayTicks < 0) { + if (this.warmupDelayTicks == -8) { +- for (LivingEntity livingEntity : this.level().getEntitiesOfClass(LivingEntity.class, this.getBoundingBox().inflate(0.2, 0.0, 0.2))) { +- this.dealDamageTo(livingEntity); ++ List list = this.level().getEntitiesOfClass(LivingEntity.class, this.getBoundingBox().inflate(0.2D, 0.0D, 0.2D)); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ LivingEntity entityliving = (LivingEntity) iterator.next(); ++ ++ this.dealDamageTo(entityliving); + } + } + + if (!this.sentSpikeEvent) { +- this.level().broadcastEntityEvent(this, (byte)4); ++ this.level().broadcastEntityEvent(this, (byte) 4); + this.sentSpikeEvent = true; + } + +@@ -109,20 +121,25 @@ + this.discard(); + } + } ++ + } + + private void dealDamageTo(LivingEntity target) { +- LivingEntity owner = this.getOwner(); +- if (target.isAlive() && !target.isInvulnerable() && target != owner) { +- if (owner == null) { ++ LivingEntity entityliving1 = this.getOwner(); ++ ++ if (target.isAlive() && !target.isInvulnerable() && target != entityliving1) { ++ if (entityliving1 == null) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = this; // CraftBukkit + target.hurt(this.damageSources().magic(), 6.0F); ++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = null; // CraftBukkit + } else { +- if (owner.isAlliedTo(target)) { ++ if (entityliving1.isAlliedTo((Entity) target)) { + return; + } + +- target.hurt(this.damageSources().indirectMagic(this, owner), 6.0F); ++ target.hurt(this.damageSources().indirectMagic(this, entityliving1), 6.0F); + } ++ + } + } + +@@ -132,19 +149,10 @@ + if (id == 4) { + this.clientSideAttackStarted = true; + if (!this.isSilent()) { +- this.level() +- .playLocalSound( +- this.getX(), +- this.getY(), +- this.getZ(), +- SoundEvents.EVOKER_FANGS_ATTACK, +- this.getSoundSource(), +- 1.0F, +- this.random.nextFloat() * 0.2F + 0.85F, +- false +- ); ++ this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.EVOKER_FANGS_ATTACK, this.getSoundSource(), 1.0F, this.random.nextFloat() * 0.2F + 0.85F, false); + } + } ++ + } + + public float getAnimationProgress(float partialTicks) { +@@ -152,7 +160,8 @@ + return 0.0F; + } else { + int i = this.lifeTicks - 2; +- return i <= 0 ? 1.0F : 1.0F - ((float)i - partialTicks) / 20.0F; ++ ++ return i <= 0 ? 1.0F : 1.0F - ((float) i - partialTicks) / 20.0F; + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/EyeOfEnder.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/EyeOfEnder.java.patch new file mode 100644 index 0000000000..c01a4e5a26 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/EyeOfEnder.java.patch @@ -0,0 +1,245 @@ +--- a/net/minecraft/world/entity/projectile/EyeOfEnder.java ++++ b/net/minecraft/world/entity/projectile/EyeOfEnder.java +@@ -17,68 +17,73 @@ + import net.minecraft.world.phys.Vec3; + + public class EyeOfEnder extends Entity implements ItemSupplier { ++ + private static final EntityDataAccessor DATA_ITEM_STACK = SynchedEntityData.defineId(EyeOfEnder.class, EntityDataSerializers.ITEM_STACK); +- private double tx; +- private double ty; +- private double tz; +- private int life; +- private boolean surviveAfterDeath; ++ public double tx; ++ public double ty; ++ public double tz; ++ public int life; ++ public boolean surviveAfterDeath; + + public EyeOfEnder(EntityType entityType, Level level) { + super(entityType, level); + } + +- public EyeOfEnder(Level level, double x, double y, double z) { ++ public EyeOfEnder(Level level, double x, double d1, double y) { + this(EntityType.EYE_OF_ENDER, level); +- this.setPos(x, y, z); ++ this.setPos(x, d1, y); + } + + public void setItem(ItemStack stack) { +- if (!stack.is(Items.ENDER_EYE) || stack.hasTag()) { +- this.getEntityData().set(DATA_ITEM_STACK, stack.copyWithCount(1)); ++ if (true || !stack.is(Items.ENDER_EYE) || stack.hasTag()) { // CraftBukkit - always allow item changing ++ this.getEntityData().set(EyeOfEnder.DATA_ITEM_STACK, stack.copyWithCount(1)); + } ++ + } + + private ItemStack getItemRaw() { +- return this.getEntityData().get(DATA_ITEM_STACK); ++ return (ItemStack) this.getEntityData().get(EyeOfEnder.DATA_ITEM_STACK); + } + + @Override + public ItemStack getItem() { +- ItemStack itemRaw = this.getItemRaw(); +- return itemRaw.isEmpty() ? new ItemStack(Items.ENDER_EYE) : itemRaw; ++ ItemStack itemstack = this.getItemRaw(); ++ ++ return itemstack.isEmpty() ? new ItemStack(Items.ENDER_EYE) : itemstack; + } + + @Override + protected void defineSynchedData() { +- this.getEntityData().define(DATA_ITEM_STACK, ItemStack.EMPTY); ++ this.getEntityData().define(EyeOfEnder.DATA_ITEM_STACK, ItemStack.EMPTY); + } + + @Override + public boolean shouldRenderAtSqrDistance(double distance) { +- double d = this.getBoundingBox().getSize() * 4.0; +- if (Double.isNaN(d)) { +- d = 4.0; ++ double d1 = this.getBoundingBox().getSize() * 4.0D; ++ ++ if (Double.isNaN(d1)) { ++ d1 = 4.0D; + } + +- d *= 64.0; +- return distance < d * d; ++ d1 *= 64.0D; ++ return distance < d1 * d1; + } + + public void signalTo(BlockPos pos) { +- double d = (double)pos.getX(); +- int y = pos.getY(); +- double d1 = (double)pos.getZ(); +- double d2 = d - this.getX(); ++ double d0 = (double) pos.getX(); ++ int i = pos.getY(); ++ double d1 = (double) pos.getZ(); ++ double d2 = d0 - this.getX(); + double d3 = d1 - this.getZ(); +- double squareRoot = Math.sqrt(d2 * d2 + d3 * d3); +- if (squareRoot > 12.0) { +- this.tx = this.getX() + d2 / squareRoot * 12.0; +- this.tz = this.getZ() + d3 / squareRoot * 12.0; +- this.ty = this.getY() + 8.0; ++ double d4 = Math.sqrt(d2 * d2 + d3 * d3); ++ ++ if (d4 > 12.0D) { ++ this.tx = this.getX() + d2 / d4 * 12.0D; ++ this.tz = this.getZ() + d3 / d4 * 12.0D; ++ this.ty = this.getY() + 8.0D; + } else { +- this.tx = d; +- this.ty = (double)y; ++ this.tx = d0; ++ this.ty = (double) i; + this.tz = d1; + } + +@@ -87,74 +92,62 @@ + } + + @Override +- public void lerpMotion(double x, double y, double z) { +- this.setDeltaMovement(x, y, z); ++ public void lerpMotion(double x, double d1, double y) { ++ this.setDeltaMovement(x, d1, y); + if (this.xRotO == 0.0F && this.yRotO == 0.0F) { +- double squareRoot = Math.sqrt(x * x + z * z); +- this.setYRot((float)(Mth.atan2(x, z) * 180.0F / (float)Math.PI)); +- this.setXRot((float)(Mth.atan2(y, squareRoot) * 180.0F / (float)Math.PI)); ++ double d3 = Math.sqrt(x * x + y * y); ++ ++ this.setYRot((float) (Mth.atan2(x, y) * 57.2957763671875D)); ++ this.setXRot((float) (Mth.atan2(d1, d3) * 57.2957763671875D)); + this.yRotO = this.getYRot(); + this.xRotO = this.getXRot(); + } ++ + } + + @Override + public void tick() { + super.tick(); +- Vec3 deltaMovement = this.getDeltaMovement(); +- double d = this.getX() + deltaMovement.x; +- double d1 = this.getY() + deltaMovement.y; +- double d2 = this.getZ() + deltaMovement.z; +- double d3 = deltaMovement.horizontalDistance(); +- this.setXRot(Projectile.lerpRotation(this.xRotO, (float)(Mth.atan2(deltaMovement.y, d3) * 180.0F / (float)Math.PI))); +- this.setYRot(Projectile.lerpRotation(this.yRotO, (float)(Mth.atan2(deltaMovement.x, deltaMovement.z) * 180.0F / (float)Math.PI))); ++ Vec3 vec3d = this.getDeltaMovement(); ++ double d0 = this.getX() + vec3d.x; ++ double d1 = this.getY() + vec3d.y; ++ double d2 = this.getZ() + vec3d.z; ++ double d3 = vec3d.horizontalDistance(); ++ ++ this.setXRot(Projectile.lerpRotation(this.xRotO, (float) (Mth.atan2(vec3d.y, d3) * 57.2957763671875D))); ++ this.setYRot(Projectile.lerpRotation(this.yRotO, (float) (Mth.atan2(vec3d.x, vec3d.z) * 57.2957763671875D))); + if (!this.level().isClientSide) { +- double d4 = this.tx - d; ++ double d4 = this.tx - d0; + double d5 = this.tz - d2; +- float f = (float)Math.sqrt(d4 * d4 + d5 * d5); +- float f1 = (float)Mth.atan2(d5, d4); +- double d6 = Mth.lerp(0.0025, d3, (double)f); +- double d7 = deltaMovement.y; ++ float f = (float) Math.sqrt(d4 * d4 + d5 * d5); ++ float f1 = (float) Mth.atan2(d5, d4); ++ double d6 = Mth.lerp(0.0025D, d3, (double) f); ++ double d7 = vec3d.y; ++ + if (f < 1.0F) { +- d6 *= 0.8; +- d7 *= 0.8; ++ d6 *= 0.8D; ++ d7 *= 0.8D; + } + + int i = this.getY() < this.ty ? 1 : -1; +- deltaMovement = new Vec3(Math.cos((double)f1) * d6, d7 + ((double)i - d7) * 0.015F, Math.sin((double)f1) * d6); +- this.setDeltaMovement(deltaMovement); ++ ++ vec3d = new Vec3(Math.cos((double) f1) * d6, d7 + ((double) i - d7) * 0.014999999664723873D, Math.sin((double) f1) * d6); ++ this.setDeltaMovement(vec3d); + } + + float f2 = 0.25F; ++ + if (this.isInWater()) { +- for (int i1 = 0; i1 < 4; i1++) { +- this.level() +- .addParticle( +- ParticleTypes.BUBBLE, +- d - deltaMovement.x * 0.25, +- d1 - deltaMovement.y * 0.25, +- d2 - deltaMovement.z * 0.25, +- deltaMovement.x, +- deltaMovement.y, +- deltaMovement.z +- ); ++ for (int j = 0; j < 4; ++j) { ++ this.level().addParticle(ParticleTypes.BUBBLE, d0 - vec3d.x * 0.25D, d1 - vec3d.y * 0.25D, d2 - vec3d.z * 0.25D, vec3d.x, vec3d.y, vec3d.z); + } + } else { +- this.level() +- .addParticle( +- ParticleTypes.PORTAL, +- d - deltaMovement.x * 0.25 + this.random.nextDouble() * 0.6 - 0.3, +- d1 - deltaMovement.y * 0.25 - 0.5, +- d2 - deltaMovement.z * 0.25 + this.random.nextDouble() * 0.6 - 0.3, +- deltaMovement.x, +- deltaMovement.y, +- deltaMovement.z +- ); ++ this.level().addParticle(ParticleTypes.PORTAL, d0 - vec3d.x * 0.25D + this.random.nextDouble() * 0.6D - 0.3D, d1 - vec3d.y * 0.25D - 0.5D, d2 - vec3d.z * 0.25D + this.random.nextDouble() * 0.6D - 0.3D, vec3d.x, vec3d.y, vec3d.z); + } + + if (!this.level().isClientSide) { +- this.setPos(d, d1, d2); +- this.life++; ++ this.setPos(d0, d1, d2); ++ ++this.life; + if (this.life > 80 && !this.level().isClientSide) { + this.playSound(SoundEvents.ENDER_EYE_DEATH, 1.0F, 1.0F); + this.discard(); +@@ -165,22 +158,26 @@ + } + } + } else { +- this.setPosRaw(d, d1, d2); ++ this.setPosRaw(d0, d1, d2); + } ++ + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { +- ItemStack itemRaw = this.getItemRaw(); +- if (!itemRaw.isEmpty()) { +- compound.put("Item", itemRaw.save(new CompoundTag())); ++ ItemStack itemstack = this.getItemRaw(); ++ ++ if (!itemstack.isEmpty()) { ++ compound.put("Item", itemstack.save(new CompoundTag())); + } ++ + } + + @Override + public void readAdditionalSaveData(CompoundTag compound) { +- ItemStack itemStack = ItemStack.of(compound.getCompound("Item")); +- this.setItem(itemStack); ++ ItemStack itemstack = ItemStack.of(compound.getCompound("Item")); ++ ++ if (!itemstack.isEmpty()) this.setItem(itemstack); // CraftBukkit - SPIGOT-6103 summon, see also SPIGOT-5474 + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/Fireball.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/Fireball.java.patch new file mode 100644 index 0000000000..354ae6ed1d --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/Fireball.java.patch @@ -0,0 +1,78 @@ +--- a/net/minecraft/world/entity/projectile/Fireball.java ++++ b/net/minecraft/world/entity/projectile/Fireball.java +@@ -11,54 +11,60 @@ + import net.minecraft.world.level.Level; + + public abstract class Fireball extends AbstractHurtingProjectile implements ItemSupplier { ++ + private static final EntityDataAccessor DATA_ITEM_STACK = SynchedEntityData.defineId(Fireball.class, EntityDataSerializers.ITEM_STACK); + + public Fireball(EntityType entityType, Level level) { + super(entityType, level); + } + +- public Fireball(EntityType entityType, double x, double y, double z, double offsetX, double offsetY, double offsetZ, Level level) { +- super(entityType, x, y, z, offsetX, offsetY, offsetZ, level); ++ public Fireball(EntityType entityType, double x, double d1, double y, double d3, double z, double d5, Level offsetX) { ++ super(entityType, x, d1, y, d3, z, d5, offsetX); + } + +- public Fireball(EntityType entityType, LivingEntity shooter, double offsetX, double offsetY, double offsetZ, Level level) { +- super(entityType, shooter, offsetX, offsetY, offsetZ, level); ++ public Fireball(EntityType entityType, LivingEntity shooter, double offsetX, double d1, double offsetY, Level world) { ++ super(entityType, shooter, offsetX, d1, offsetY, world); + } + + public void setItem(ItemStack stack) { + if (!stack.is(Items.FIRE_CHARGE) || stack.hasTag()) { +- this.getEntityData().set(DATA_ITEM_STACK, stack.copyWithCount(1)); ++ this.getEntityData().set(Fireball.DATA_ITEM_STACK, stack.copyWithCount(1)); + } ++ + } + +- protected ItemStack getItemRaw() { +- return this.getEntityData().get(DATA_ITEM_STACK); ++ public ItemStack getItemRaw() { ++ return (ItemStack) this.getEntityData().get(Fireball.DATA_ITEM_STACK); + } + + @Override + public ItemStack getItem() { +- ItemStack itemRaw = this.getItemRaw(); +- return itemRaw.isEmpty() ? new ItemStack(Items.FIRE_CHARGE) : itemRaw; ++ ItemStack itemstack = this.getItemRaw(); ++ ++ return itemstack.isEmpty() ? new ItemStack(Items.FIRE_CHARGE) : itemstack; + } + + @Override + protected void defineSynchedData() { +- this.getEntityData().define(DATA_ITEM_STACK, ItemStack.EMPTY); ++ this.getEntityData().define(Fireball.DATA_ITEM_STACK, ItemStack.EMPTY); + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- ItemStack itemRaw = this.getItemRaw(); +- if (!itemRaw.isEmpty()) { +- compound.put("Item", itemRaw.save(new CompoundTag())); ++ ItemStack itemstack = this.getItemRaw(); ++ ++ if (!itemstack.isEmpty()) { ++ compound.put("Item", itemstack.save(new CompoundTag())); + } ++ + } + + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); +- ItemStack itemStack = ItemStack.of(compound.getCompound("Item")); +- this.setItem(itemStack); ++ ItemStack itemstack = ItemStack.of(compound.getCompound("Item")); ++ ++ if (!itemstack.isEmpty()) this.setItem(itemstack); // CraftBukkit - SPIGOT-5474 probably came from bugged earlier versions + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/FireworkRocketEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/FireworkRocketEntity.java.patch new file mode 100644 index 0000000000..6a80061276 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/FireworkRocketEntity.java.patch @@ -0,0 +1,445 @@ +--- a/net/minecraft/world/entity/projectile/FireworkRocketEntity.java ++++ b/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +@@ -1,5 +1,7 @@ + package net.minecraft.world.entity.projectile; + ++import java.util.Iterator; ++import java.util.List; + import java.util.OptionalInt; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +@@ -13,8 +15,9 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MoverType; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.ClipContext; +@@ -24,159 +27,149 @@ + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class FireworkRocketEntity extends Projectile implements ItemSupplier { +- private static final EntityDataAccessor DATA_ID_FIREWORKS_ITEM = SynchedEntityData.defineId( +- FireworkRocketEntity.class, EntityDataSerializers.ITEM_STACK +- ); +- private static final EntityDataAccessor DATA_ATTACHED_TO_TARGET = SynchedEntityData.defineId( +- FireworkRocketEntity.class, EntityDataSerializers.OPTIONAL_UNSIGNED_INT +- ); +- private static final EntityDataAccessor DATA_SHOT_AT_ANGLE = SynchedEntityData.defineId(FireworkRocketEntity.class, EntityDataSerializers.BOOLEAN); +- private int life; +- private int lifetime; ++ ++ public static final EntityDataAccessor DATA_ID_FIREWORKS_ITEM = SynchedEntityData.defineId(FireworkRocketEntity.class, EntityDataSerializers.ITEM_STACK); ++ private static final EntityDataAccessor DATA_ATTACHED_TO_TARGET = SynchedEntityData.defineId(FireworkRocketEntity.class, EntityDataSerializers.OPTIONAL_UNSIGNED_INT); ++ public static final EntityDataAccessor DATA_SHOT_AT_ANGLE = SynchedEntityData.defineId(FireworkRocketEntity.class, EntityDataSerializers.BOOLEAN); ++ public int life; ++ public int lifetime; + @Nullable +- private LivingEntity attachedToEntity; ++ public LivingEntity attachedToEntity; + + public FireworkRocketEntity(EntityType entityType, Level level) { + super(entityType, level); + } + +- public FireworkRocketEntity(Level level, double x, double y, double z, ItemStack stack) { ++ public FireworkRocketEntity(Level level, double x, double d1, double y, ItemStack itemstack) { + super(EntityType.FIREWORK_ROCKET, level); + this.life = 0; +- this.setPos(x, y, z); ++ this.setPos(x, d1, y); + int i = 1; +- if (!stack.isEmpty() && stack.hasTag()) { +- this.entityData.set(DATA_ID_FIREWORKS_ITEM, stack.copy()); +- i += stack.getOrCreateTagElement("Fireworks").getByte("Flight"); ++ ++ if (!itemstack.isEmpty() && itemstack.hasTag()) { ++ this.entityData.set(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, itemstack.copy()); ++ i += itemstack.getOrCreateTagElement("Fireworks").getByte("Flight"); + } + +- this.setDeltaMovement(this.random.triangle(0.0, 0.002297), 0.05, this.random.triangle(0.0, 0.002297)); ++ this.setDeltaMovement(this.random.triangle(0.0D, 0.002297D), 0.05D, this.random.triangle(0.0D, 0.002297D)); + this.lifetime = 10 * i + this.random.nextInt(6) + this.random.nextInt(7); + } + +- public FireworkRocketEntity(Level level, @Nullable Entity shooter, double x, double y, double z, ItemStack stack) { +- this(level, x, y, z, stack); ++ public FireworkRocketEntity(Level level, @Nullable Entity shooter, double x, double d1, double y, ItemStack itemstack) { ++ this(level, x, d1, y, itemstack); + this.setOwner(shooter); + } + + public FireworkRocketEntity(Level level, ItemStack stack, LivingEntity shooter) { + this(level, shooter, shooter.getX(), shooter.getY(), shooter.getZ(), stack); +- this.entityData.set(DATA_ATTACHED_TO_TARGET, OptionalInt.of(shooter.getId())); ++ this.entityData.set(FireworkRocketEntity.DATA_ATTACHED_TO_TARGET, OptionalInt.of(shooter.getId())); + this.attachedToEntity = shooter; + } + +- public FireworkRocketEntity(Level level, ItemStack stack, double x, double y, double z, boolean shotAtAngle) { +- this(level, x, y, z, stack); +- this.entityData.set(DATA_SHOT_AT_ANGLE, shotAtAngle); ++ public FireworkRocketEntity(Level level, ItemStack stack, double x, double d1, double y, boolean flag) { ++ this(level, x, d1, y, stack); ++ this.entityData.set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, flag); + } + +- public FireworkRocketEntity(Level level, ItemStack stack, Entity shooter, double x, double y, double z, boolean shotAtAngle) { +- this(level, stack, x, y, z, shotAtAngle); ++ public FireworkRocketEntity(Level level, ItemStack stack, Entity shooter, double x, double d1, double y, boolean flag) { ++ this(level, stack, x, d1, y, flag); + this.setOwner(shooter); + } + + @Override + protected void defineSynchedData() { +- this.entityData.define(DATA_ID_FIREWORKS_ITEM, ItemStack.EMPTY); +- this.entityData.define(DATA_ATTACHED_TO_TARGET, OptionalInt.empty()); +- this.entityData.define(DATA_SHOT_AT_ANGLE, false); ++ this.entityData.define(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, ItemStack.EMPTY); ++ this.entityData.define(FireworkRocketEntity.DATA_ATTACHED_TO_TARGET, OptionalInt.empty()); ++ this.entityData.define(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, false); + } + + @Override + public boolean shouldRenderAtSqrDistance(double distance) { +- return distance < 4096.0 && !this.isAttachedToEntity(); ++ return distance < 4096.0D && !this.isAttachedToEntity(); + } + + @Override +- public boolean shouldRender(double x, double y, double z) { +- return super.shouldRender(x, y, z) && !this.isAttachedToEntity(); ++ public boolean shouldRender(double x, double d1, double y) { ++ return super.shouldRender(x, d1, y) && !this.isAttachedToEntity(); + } + + @Override + public void tick() { + super.tick(); ++ Vec3 vec3d; ++ + if (this.isAttachedToEntity()) { + if (this.attachedToEntity == null) { +- this.entityData.get(DATA_ATTACHED_TO_TARGET).ifPresent(target -> { +- Entity entity = this.level().getEntity(target); ++ ((OptionalInt) this.entityData.get(FireworkRocketEntity.DATA_ATTACHED_TO_TARGET)).ifPresent((i) -> { ++ Entity entity = this.level().getEntity(i); ++ + if (entity instanceof LivingEntity) { +- this.attachedToEntity = (LivingEntity)entity; ++ this.attachedToEntity = (LivingEntity) entity; + } ++ + }); + } + + if (this.attachedToEntity != null) { +- Vec3 handHoldingItemAngle; + if (this.attachedToEntity.isFallFlying()) { +- Vec3 lookAngle = this.attachedToEntity.getLookAngle(); +- double d = 1.5; +- double d1 = 0.1; +- Vec3 deltaMovement = this.attachedToEntity.getDeltaMovement(); +- this.attachedToEntity +- .setDeltaMovement( +- deltaMovement.add( +- lookAngle.x * 0.1 + (lookAngle.x * 1.5 - deltaMovement.x) * 0.5, +- lookAngle.y * 0.1 + (lookAngle.y * 1.5 - deltaMovement.y) * 0.5, +- lookAngle.z * 0.1 + (lookAngle.z * 1.5 - deltaMovement.z) * 0.5 +- ) +- ); +- handHoldingItemAngle = this.attachedToEntity.getHandHoldingItemAngle(Items.FIREWORK_ROCKET); ++ Vec3 vec3d1 = this.attachedToEntity.getLookAngle(); ++ double d0 = 1.5D; ++ double d1 = 0.1D; ++ Vec3 vec3d2 = this.attachedToEntity.getDeltaMovement(); ++ ++ this.attachedToEntity.setDeltaMovement(vec3d2.add(vec3d1.x * 0.1D + (vec3d1.x * 1.5D - vec3d2.x) * 0.5D, vec3d1.y * 0.1D + (vec3d1.y * 1.5D - vec3d2.y) * 0.5D, vec3d1.z * 0.1D + (vec3d1.z * 1.5D - vec3d2.z) * 0.5D)); ++ vec3d = this.attachedToEntity.getHandHoldingItemAngle(Items.FIREWORK_ROCKET); + } else { +- handHoldingItemAngle = Vec3.ZERO; ++ vec3d = Vec3.ZERO; + } + +- this.setPos( +- this.attachedToEntity.getX() + handHoldingItemAngle.x, +- this.attachedToEntity.getY() + handHoldingItemAngle.y, +- this.attachedToEntity.getZ() + handHoldingItemAngle.z +- ); ++ this.setPos(this.attachedToEntity.getX() + vec3d.x, this.attachedToEntity.getY() + vec3d.y, this.attachedToEntity.getZ() + vec3d.z); + this.setDeltaMovement(this.attachedToEntity.getDeltaMovement()); + } + } else { + if (!this.isShotAtAngle()) { +- double d2 = this.horizontalCollision ? 1.0 : 1.15; +- this.setDeltaMovement(this.getDeltaMovement().multiply(d2, 1.0, d2).add(0.0, 0.04, 0.0)); ++ double d2 = this.horizontalCollision ? 1.0D : 1.15D; ++ ++ this.setDeltaMovement(this.getDeltaMovement().multiply(d2, 1.0D, d2).add(0.0D, 0.04D, 0.0D)); + } + +- Vec3 handHoldingItemAngle = this.getDeltaMovement(); +- this.move(MoverType.SELF, handHoldingItemAngle); +- this.setDeltaMovement(handHoldingItemAngle); ++ vec3d = this.getDeltaMovement(); ++ this.move(EnumMoveType.SELF, vec3d); ++ this.setDeltaMovement(vec3d); + } + +- HitResult hitResultOnMoveVector = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); ++ HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); ++ + if (!this.noPhysics) { +- this.onHit(hitResultOnMoveVector); ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + this.hasImpulse = true; + } + + this.updateRotation(); + if (this.life == 0 && !this.isSilent()) { +- this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.FIREWORK_ROCKET_LAUNCH, SoundSource.AMBIENT, 3.0F, 1.0F); ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.FIREWORK_ROCKET_LAUNCH, SoundSource.AMBIENT, 3.0F, 1.0F); + } + +- this.life++; ++ ++this.life; + if (this.level().isClientSide && this.life % 2 < 2) { +- this.level() +- .addParticle( +- ParticleTypes.FIREWORK, +- this.getX(), +- this.getY(), +- this.getZ(), +- this.random.nextGaussian() * 0.05, +- -this.getDeltaMovement().y * 0.5, +- this.random.nextGaussian() * 0.05 +- ); ++ this.level().addParticle(ParticleTypes.FIREWORK, this.getX(), this.getY(), this.getZ(), this.random.nextGaussian() * 0.05D, -this.getDeltaMovement().y * 0.5D, this.random.nextGaussian() * 0.05D); + } + + if (!this.level().isClientSide && this.life > this.lifetime) { +- this.explode(); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) { ++ this.explode(); ++ } ++ // CraftBukkit end + } ++ + } + + private void explode() { +- this.level().broadcastEntityEvent(this, (byte)17); ++ this.level().broadcastEntityEvent(this, (byte) 17); + this.gameEvent(GameEvent.EXPLODE, this.getOwner()); + this.dealExplosionDamage(); + this.discard(); +@@ -186,96 +179,110 @@ + protected void onHitEntity(EntityHitResult result) { + super.onHitEntity(result); + if (!this.level().isClientSide) { +- this.explode(); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) { ++ this.explode(); ++ } ++ // CraftBukkit end + } + } + + @Override + protected void onHitBlock(BlockHitResult result) { +- BlockPos blockPos = new BlockPos(result.getBlockPos()); +- this.level().getBlockState(blockPos).entityInside(this.level(), blockPos, this); ++ BlockPos blockposition = new BlockPos(result.getBlockPos()); ++ ++ this.level().getBlockState(blockposition).entityInside(this.level(), blockposition, this); + if (!this.level().isClientSide() && this.hasExplosion()) { +- this.explode(); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) { ++ this.explode(); ++ } ++ // CraftBukkit end + } + + super.onHitBlock(result); + } + + private boolean hasExplosion() { +- ItemStack itemStack = this.entityData.get(DATA_ID_FIREWORKS_ITEM); +- CompoundTag compoundTag = itemStack.isEmpty() ? null : itemStack.getTagElement("Fireworks"); +- ListTag list = compoundTag != null ? compoundTag.getList("Explosions", 10) : null; +- return list != null && !list.isEmpty(); ++ ItemStack itemstack = (ItemStack) this.entityData.get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM); ++ CompoundTag nbttagcompound = itemstack.isEmpty() ? null : itemstack.getTagElement("Fireworks"); ++ ListTag nbttaglist = nbttagcompound != null ? nbttagcompound.getList("Explosions", 10) : null; ++ ++ return nbttaglist != null && !nbttaglist.isEmpty(); + } + + private void dealExplosionDamage() { + float f = 0.0F; +- ItemStack itemStack = this.entityData.get(DATA_ID_FIREWORKS_ITEM); +- CompoundTag compoundTag = itemStack.isEmpty() ? null : itemStack.getTagElement("Fireworks"); +- ListTag list = compoundTag != null ? compoundTag.getList("Explosions", 10) : null; +- if (list != null && !list.isEmpty()) { +- f = 5.0F + (float)(list.size() * 2); ++ ItemStack itemstack = (ItemStack) this.entityData.get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM); ++ CompoundTag nbttagcompound = itemstack.isEmpty() ? null : itemstack.getTagElement("Fireworks"); ++ ListTag nbttaglist = nbttagcompound != null ? nbttagcompound.getList("Explosions", 10) : null; ++ ++ if (nbttaglist != null && !nbttaglist.isEmpty()) { ++ f = 5.0F + (float) (nbttaglist.size() * 2); + } + + if (f > 0.0F) { + if (this.attachedToEntity != null) { +- this.attachedToEntity.hurt(this.damageSources().fireworks(this, this.getOwner()), 5.0F + (float)(list.size() * 2)); ++ CraftEventFactory.entityDamage = this; // CraftBukkit ++ this.attachedToEntity.hurt(this.damageSources().fireworks(this, this.getOwner()), 5.0F + (float) (nbttaglist.size() * 2)); ++ CraftEventFactory.entityDamage = null; // CraftBukkit + } + +- double d = 5.0; +- Vec3 vec3 = this.position(); ++ double d0 = 5.0D; ++ Vec3 vec3d = this.position(); ++ List list = this.level().getEntitiesOfClass(LivingEntity.class, this.getBoundingBox().inflate(5.0D)); ++ Iterator iterator = list.iterator(); + +- for (LivingEntity livingEntity : this.level().getEntitiesOfClass(LivingEntity.class, this.getBoundingBox().inflate(5.0))) { +- if (livingEntity != this.attachedToEntity && !(this.distanceToSqr(livingEntity) > 25.0)) { ++ while (iterator.hasNext()) { ++ LivingEntity entityliving = (LivingEntity) iterator.next(); ++ ++ if (entityliving != this.attachedToEntity && this.distanceToSqr((Entity) entityliving) <= 25.0D) { + boolean flag = false; + +- for (int i = 0; i < 2; i++) { +- Vec3 vec31 = new Vec3(livingEntity.getX(), livingEntity.getY(0.5 * (double)i), livingEntity.getZ()); +- HitResult hitResult = this.level().clip(new ClipContext(vec3, vec31, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)); +- if (hitResult.getType() == HitResult.Type.MISS) { ++ for (int i = 0; i < 2; ++i) { ++ Vec3 vec3d1 = new Vec3(entityliving.getX(), entityliving.getY(0.5D * (double) i), entityliving.getZ()); ++ BlockHitResult movingobjectpositionblock = this.level().clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)); ++ ++ if (movingobjectpositionblock.getType() == HitResult.EnumMovingObjectType.MISS) { + flag = true; + break; + } + } + + if (flag) { +- float f1 = f * (float)Math.sqrt((5.0 - (double)this.distanceTo(livingEntity)) / 5.0); +- livingEntity.hurt(this.damageSources().fireworks(this, this.getOwner()), f1); ++ float f1 = f * (float) Math.sqrt((5.0D - (double) this.distanceTo(entityliving)) / 5.0D); ++ ++ CraftEventFactory.entityDamage = this; // CraftBukkit ++ entityliving.hurt(this.damageSources().fireworks(this, this.getOwner()), f1); ++ CraftEventFactory.entityDamage = null; // CraftBukkit + } + } + } + } ++ + } + + private boolean isAttachedToEntity() { +- return this.entityData.get(DATA_ATTACHED_TO_TARGET).isPresent(); ++ return ((OptionalInt) this.entityData.get(FireworkRocketEntity.DATA_ATTACHED_TO_TARGET)).isPresent(); + } + + public boolean isShotAtAngle() { +- return this.entityData.get(DATA_SHOT_AT_ANGLE); ++ return (Boolean) this.entityData.get(FireworkRocketEntity.DATA_SHOT_AT_ANGLE); + } + + @Override + public void handleEntityEvent(byte id) { + if (id == 17 && this.level().isClientSide) { + if (!this.hasExplosion()) { +- for (int i = 0; i < this.random.nextInt(3) + 2; i++) { +- this.level() +- .addParticle( +- ParticleTypes.POOF, +- this.getX(), +- this.getY(), +- this.getZ(), +- this.random.nextGaussian() * 0.05, +- 0.005, +- this.random.nextGaussian() * 0.05 +- ); ++ for (int i = 0; i < this.random.nextInt(3) + 2; ++i) { ++ this.level().addParticle(ParticleTypes.POOF, this.getX(), this.getY(), this.getZ(), this.random.nextGaussian() * 0.05D, 0.005D, this.random.nextGaussian() * 0.05D); + } + } else { +- ItemStack itemStack = this.entityData.get(DATA_ID_FIREWORKS_ITEM); +- CompoundTag compoundTag = itemStack.isEmpty() ? null : itemStack.getTagElement("Fireworks"); +- Vec3 deltaMovement = this.getDeltaMovement(); +- this.level().createFireworks(this.getX(), this.getY(), this.getZ(), deltaMovement.x, deltaMovement.y, deltaMovement.z, compoundTag); ++ ItemStack itemstack = (ItemStack) this.entityData.get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM); ++ CompoundTag nbttagcompound = itemstack.isEmpty() ? null : itemstack.getTagElement("Fireworks"); ++ Vec3 vec3d = this.getDeltaMovement(); ++ ++ this.level().createFireworks(this.getX(), this.getY(), this.getZ(), vec3d.x, vec3d.y, vec3d.z, nbttagcompound); + } + } + +@@ -287,12 +294,13 @@ + super.addAdditionalSaveData(compound); + compound.putInt("Life", this.life); + compound.putInt("LifeTime", this.lifetime); +- ItemStack itemStack = this.entityData.get(DATA_ID_FIREWORKS_ITEM); +- if (!itemStack.isEmpty()) { +- compound.put("FireworksItem", itemStack.save(new CompoundTag())); ++ ItemStack itemstack = (ItemStack) this.entityData.get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM); ++ ++ if (!itemstack.isEmpty()) { ++ compound.put("FireworksItem", itemstack.save(new CompoundTag())); + } + +- compound.putBoolean("ShotAtAngle", this.entityData.get(DATA_SHOT_AT_ANGLE)); ++ compound.putBoolean("ShotAtAngle", (Boolean) this.entityData.get(FireworkRocketEntity.DATA_SHOT_AT_ANGLE)); + } + + @Override +@@ -300,20 +308,23 @@ + super.readAdditionalSaveData(compound); + this.life = compound.getInt("Life"); + this.lifetime = compound.getInt("LifeTime"); +- ItemStack itemStack = ItemStack.of(compound.getCompound("FireworksItem")); +- if (!itemStack.isEmpty()) { +- this.entityData.set(DATA_ID_FIREWORKS_ITEM, itemStack); ++ ItemStack itemstack = ItemStack.of(compound.getCompound("FireworksItem")); ++ ++ if (!itemstack.isEmpty()) { ++ this.entityData.set(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, itemstack); + } + + if (compound.contains("ShotAtAngle")) { +- this.entityData.set(DATA_SHOT_AT_ANGLE, compound.getBoolean("ShotAtAngle")); ++ this.entityData.set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, compound.getBoolean("ShotAtAngle")); + } ++ + } + + @Override + public ItemStack getItem() { +- ItemStack itemStack = this.entityData.get(DATA_ID_FIREWORKS_ITEM); +- return itemStack.isEmpty() ? new ItemStack(Items.FIREWORK_ROCKET) : itemStack; ++ ItemStack itemstack = (ItemStack) this.entityData.get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM); ++ ++ return itemstack.isEmpty() ? new ItemStack(Items.FIREWORK_ROCKET) : itemstack; + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/FishingHook.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/FishingHook.java.patch new file mode 100644 index 0000000000..80a95da104 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/FishingHook.java.patch @@ -0,0 +1,854 @@ +--- a/net/minecraft/world/entity/projectile/FishingHook.java ++++ b/net/minecraft/world/entity/projectile/FishingHook.java +@@ -2,6 +2,7 @@ + + import com.mojang.logging.LogUtils; + import java.util.Collections; ++import java.util.Iterator; + import java.util.List; + import javax.annotation.Nullable; + import net.minecraft.advancements.CriteriaTriggers; +@@ -24,15 +25,14 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.ExperienceOrb; +-import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.item.ItemEntity; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.storage.loot.BuiltInLootTables; + import net.minecraft.world.level.storage.loot.LootParams; +@@ -45,28 +45,50 @@ + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.entity.Player; ++import org.bukkit.entity.FishHook; ++import org.bukkit.event.player.PlayerFishEvent; ++// CraftBukkit end ++ + public class FishingHook extends Projectile { ++ + private static final Logger LOGGER = LogUtils.getLogger(); +- private final RandomSource syncronizedRandom = RandomSource.create(); ++ private final RandomSource syncronizedRandom; + private boolean biting; + private int outOfWaterTime; + private static final int MAX_OUT_OF_WATER_TIME = 10; +- private static final EntityDataAccessor DATA_HOOKED_ENTITY = SynchedEntityData.defineId(FishingHook.class, EntityDataSerializers.INT); ++ public static final EntityDataAccessor DATA_HOOKED_ENTITY = SynchedEntityData.defineId(FishingHook.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_BITING = SynchedEntityData.defineId(FishingHook.class, EntityDataSerializers.BOOLEAN); + private int life; + private int nibble; + private int timeUntilLured; + private int timeUntilHooked; + private float fishAngle; +- private boolean openWater = true; ++ private boolean openWater; + @Nullable +- private Entity hookedIn; +- private FishingHook.FishHookState currentState = FishingHook.FishHookState.FLYING; ++ public Entity hookedIn; ++ public FishingHook.HookState currentState; + private final int luck; + private final int lureSpeed; + ++ // CraftBukkit start - Extra variables to enable modification of fishing wait time, values are minecraft defaults ++ public int minWaitTime = 100; ++ public int maxWaitTime = 600; ++ public int minLureTime = 20; ++ public int maxLureTime = 80; ++ public float minLureAngle = 0.0F; ++ public float maxLureAngle = 360.0F; ++ public boolean applyLure = true; ++ public boolean rainInfluenced = true; ++ public boolean skyInfluenced = true; ++ // CraftBukkit end ++ + private FishingHook(EntityType entityType, Level level, int luck, int lureSpeed) { + super(entityType, level); ++ this.syncronizedRandom = RandomSource.create(); ++ this.openWater = true; ++ this.currentState = FishingHook.HookState.FLYING; + this.noCulling = true; + this.luck = Math.max(0, luck); + this.lureSpeed = Math.max(0, lureSpeed); +@@ -76,50 +98,49 @@ + this(entityType, level, 0, 0); + } + +- public FishingHook(Player player, Level level, int luck, int lureSpeed) { ++ public FishingHook(net.minecraft.world.entity.player.Player player, Level level, int luck, int lureSpeed) { + this(EntityType.FISHING_BOBBER, level, luck, lureSpeed); + this.setOwner(player); +- float xRot = player.getXRot(); +- float yRot = player.getYRot(); +- float cos = Mth.cos(-yRot * (float) (Math.PI / 180.0) - (float) Math.PI); +- float sin = Mth.sin(-yRot * (float) (Math.PI / 180.0) - (float) Math.PI); +- float f = -Mth.cos(-xRot * (float) (Math.PI / 180.0)); +- float sin1 = Mth.sin(-xRot * (float) (Math.PI / 180.0)); +- double d = player.getX() - (double)sin * 0.3; +- double eyeY = player.getEyeY(); +- double d1 = player.getZ() - (double)cos * 0.3; +- this.moveTo(d, eyeY, d1, yRot, xRot); +- Vec3 vec3 = new Vec3((double)(-sin), (double)Mth.clamp(-(sin1 / f), -5.0F, 5.0F), (double)(-cos)); +- double len = vec3.length(); +- vec3 = vec3.multiply( +- 0.6 / len + this.random.triangle(0.5, 0.0103365), +- 0.6 / len + this.random.triangle(0.5, 0.0103365), +- 0.6 / len + this.random.triangle(0.5, 0.0103365) +- ); +- this.setDeltaMovement(vec3); +- this.setYRot((float)(Mth.atan2(vec3.x, vec3.z) * 180.0F / (float)Math.PI)); +- this.setXRot((float)(Mth.atan2(vec3.y, vec3.horizontalDistance()) * 180.0F / (float)Math.PI)); ++ float f = player.getXRot(); ++ float f1 = player.getYRot(); ++ float f2 = Mth.cos(-f1 * 0.017453292F - 3.1415927F); ++ float f3 = Mth.sin(-f1 * 0.017453292F - 3.1415927F); ++ float f4 = -Mth.cos(-f * 0.017453292F); ++ float f5 = Mth.sin(-f * 0.017453292F); ++ double d0 = player.getX() - (double) f3 * 0.3D; ++ double d1 = player.getEyeY(); ++ double d2 = player.getZ() - (double) f2 * 0.3D; ++ ++ this.moveTo(d0, d1, d2, f1, f); ++ Vec3 vec3d = new Vec3((double) (-f3), (double) Mth.clamp(-(f5 / f4), -5.0F, 5.0F), (double) (-f2)); ++ double d3 = vec3d.length(); ++ ++ vec3d = vec3d.multiply(0.6D / d3 + this.random.triangle(0.5D, 0.0103365D), 0.6D / d3 + this.random.triangle(0.5D, 0.0103365D), 0.6D / d3 + this.random.triangle(0.5D, 0.0103365D)); ++ this.setDeltaMovement(vec3d); ++ this.setYRot((float) (Mth.atan2(vec3d.x, vec3d.z) * 57.2957763671875D)); ++ this.setXRot((float) (Mth.atan2(vec3d.y, vec3d.horizontalDistance()) * 57.2957763671875D)); + this.yRotO = this.getYRot(); + this.xRotO = this.getXRot(); + } + + @Override + protected void defineSynchedData() { +- this.getEntityData().define(DATA_HOOKED_ENTITY, 0); +- this.getEntityData().define(DATA_BITING, false); ++ this.getEntityData().define(FishingHook.DATA_HOOKED_ENTITY, 0); ++ this.getEntityData().define(FishingHook.DATA_BITING, false); + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { +- if (DATA_HOOKED_ENTITY.equals(key)) { +- int i = this.getEntityData().get(DATA_HOOKED_ENTITY); ++ if (FishingHook.DATA_HOOKED_ENTITY.equals(key)) { ++ int i = (Integer) this.getEntityData().get(FishingHook.DATA_HOOKED_ENTITY); ++ + this.hookedIn = i > 0 ? this.level().getEntity(i - 1) : null; + } + +- if (DATA_BITING.equals(key)) { +- this.biting = this.getEntityData().get(DATA_BITING); ++ if (FishingHook.DATA_BITING.equals(key)) { ++ this.biting = (Boolean) this.getEntityData().get(FishingHook.DATA_BITING); + if (this.biting) { +- this.setDeltaMovement(this.getDeltaMovement().x, (double)(-0.4F * Mth.nextFloat(this.syncronizedRandom, 0.6F, 1.0F)), this.getDeltaMovement().z); ++ this.setDeltaMovement(this.getDeltaMovement().x, (double) (-0.4F * Mth.nextFloat(this.syncronizedRandom, 0.6F, 1.0F)), this.getDeltaMovement().z); + } + } + +@@ -128,24 +149,25 @@ + + @Override + public boolean shouldRenderAtSqrDistance(double distance) { +- double d = 64.0; +- return distance < 4096.0; ++ double d1 = 64.0D; ++ ++ return distance < 4096.0D; + } + + @Override +- public void lerpTo(double d, double d1, double d2, float f, float f1, int i) { +- } ++ public void lerpTo(double d0, double d1, double d2, float f, float f1, int i) {} + + @Override + public void tick() { + this.syncronizedRandom.setSeed(this.getUUID().getLeastSignificantBits() ^ this.level().getGameTime()); + super.tick(); +- Player playerOwner = this.getPlayerOwner(); +- if (playerOwner == null) { ++ net.minecraft.world.entity.player.Player entityhuman = this.getPlayerOwner(); ++ ++ if (entityhuman == null) { + this.discard(); +- } else if (this.level().isClientSide || !this.shouldStopFishing(playerOwner)) { ++ } else if (this.level().isClientSide || !this.shouldStopFishing(entityhuman)) { + if (this.onGround()) { +- this.life++; ++ ++this.life; + if (this.life >= 1200) { + this.discard(); + return; +@@ -155,66 +177,66 @@ + } + + float f = 0.0F; +- BlockPos blockPos = this.blockPosition(); +- FluidState fluidState = this.level().getFluidState(blockPos); +- if (fluidState.is(FluidTags.WATER)) { +- f = fluidState.getHeight(this.level(), blockPos); ++ BlockPos blockposition = this.blockPosition(); ++ FluidState fluid = this.level().getFluidState(blockposition); ++ ++ if (fluid.is(FluidTags.WATER)) { ++ f = fluid.getHeight(this.level(), blockposition); + } + + boolean flag = f > 0.0F; +- if (this.currentState == FishingHook.FishHookState.FLYING) { ++ ++ if (this.currentState == FishingHook.HookState.FLYING) { + if (this.hookedIn != null) { + this.setDeltaMovement(Vec3.ZERO); +- this.currentState = FishingHook.FishHookState.HOOKED_IN_ENTITY; ++ this.currentState = FishingHook.HookState.HOOKED_IN_ENTITY; + return; + } + + if (flag) { +- this.setDeltaMovement(this.getDeltaMovement().multiply(0.3, 0.2, 0.3)); +- this.currentState = FishingHook.FishHookState.BOBBING; ++ this.setDeltaMovement(this.getDeltaMovement().multiply(0.3D, 0.2D, 0.3D)); ++ this.currentState = FishingHook.HookState.BOBBING; + return; + } + + this.checkCollision(); + } else { +- if (this.currentState == FishingHook.FishHookState.HOOKED_IN_ENTITY) { ++ if (this.currentState == FishingHook.HookState.HOOKED_IN_ENTITY) { + if (this.hookedIn != null) { + if (!this.hookedIn.isRemoved() && this.hookedIn.level().dimension() == this.level().dimension()) { +- this.setPos(this.hookedIn.getX(), this.hookedIn.getY(0.8), this.hookedIn.getZ()); ++ this.setPos(this.hookedIn.getX(), this.hookedIn.getY(0.8D), this.hookedIn.getZ()); + } else { +- this.setHookedEntity(null); +- this.currentState = FishingHook.FishHookState.FLYING; ++ this.setHookedEntity((Entity) null); ++ this.currentState = FishingHook.HookState.FLYING; + } + } + + return; + } + +- if (this.currentState == FishingHook.FishHookState.BOBBING) { +- Vec3 deltaMovement = this.getDeltaMovement(); +- double d = this.getY() + deltaMovement.y - (double)blockPos.getY() - (double)f; +- if (Math.abs(d) < 0.01) { +- d += Math.signum(d) * 0.1; ++ if (this.currentState == FishingHook.HookState.BOBBING) { ++ Vec3 vec3d = this.getDeltaMovement(); ++ double d0 = this.getY() + vec3d.y - (double) blockposition.getY() - (double) f; ++ ++ if (Math.abs(d0) < 0.01D) { ++ d0 += Math.signum(d0) * 0.1D; + } + +- this.setDeltaMovement(deltaMovement.x * 0.9, deltaMovement.y - d * (double)this.random.nextFloat() * 0.2, deltaMovement.z * 0.9); ++ this.setDeltaMovement(vec3d.x * 0.9D, vec3d.y - d0 * (double) this.random.nextFloat() * 0.2D, vec3d.z * 0.9D); + if (this.nibble <= 0 && this.timeUntilHooked <= 0) { + this.openWater = true; + } else { +- this.openWater = this.openWater && this.outOfWaterTime < 10 && this.calculateOpenWater(blockPos); ++ this.openWater = this.openWater && this.outOfWaterTime < 10 && this.calculateOpenWater(blockposition); + } + + if (flag) { + this.outOfWaterTime = Math.max(0, this.outOfWaterTime - 1); + if (this.biting) { +- this.setDeltaMovement( +- this.getDeltaMovement() +- .add(0.0, -0.1 * (double)this.syncronizedRandom.nextFloat() * (double)this.syncronizedRandom.nextFloat(), 0.0) +- ); ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.1D * (double) this.syncronizedRandom.nextFloat() * (double) this.syncronizedRandom.nextFloat(), 0.0D)); + } + + if (!this.level().isClientSide) { +- this.catchingFish(blockPos); ++ this.catchingFish(blockposition); + } + } else { + this.outOfWaterTime = Math.min(10, this.outOfWaterTime + 1); +@@ -222,28 +244,30 @@ + } + } + +- if (!fluidState.is(FluidTags.WATER)) { +- this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.03, 0.0)); ++ if (!fluid.is(FluidTags.WATER)) { ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.03D, 0.0D)); + } + +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + this.updateRotation(); +- if (this.currentState == FishingHook.FishHookState.FLYING && (this.onGround() || this.horizontalCollision)) { ++ if (this.currentState == FishingHook.HookState.FLYING && (this.onGround() || this.horizontalCollision)) { + this.setDeltaMovement(Vec3.ZERO); + } + +- double d1 = 0.92; +- this.setDeltaMovement(this.getDeltaMovement().scale(0.92)); ++ double d1 = 0.92D; ++ ++ this.setDeltaMovement(this.getDeltaMovement().scale(0.92D)); + this.reapplyPosition(); + } + } + +- private boolean shouldStopFishing(Player player) { +- ItemStack mainHandItem = player.getMainHandItem(); +- ItemStack offhandItem = player.getOffhandItem(); +- boolean isFishingRod = mainHandItem.is(Items.FISHING_ROD); +- boolean isFishingRod1 = offhandItem.is(Items.FISHING_ROD); +- if (!player.isRemoved() && player.isAlive() && (isFishingRod || isFishingRod1) && !(this.distanceToSqr(player) > 1024.0)) { ++ private boolean shouldStopFishing(net.minecraft.world.entity.player.Player player) { ++ ItemStack itemstack = player.getMainHandItem(); ++ ItemStack itemstack1 = player.getOffhandItem(); ++ boolean flag = itemstack.is(Items.FISHING_ROD); ++ boolean flag1 = itemstack1.is(Items.FISHING_ROD); ++ ++ if (!player.isRemoved() && player.isAlive() && (flag || flag1) && this.distanceToSqr((Entity) player) <= 1024.0D) { + return false; + } else { + this.discard(); +@@ -252,8 +276,9 @@ + } + + private void checkCollision() { +- HitResult hitResultOnMoveVector = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); +- this.onHit(hitResultOnMoveVector); ++ HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); ++ ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + } + + @Override +@@ -267,6 +292,7 @@ + if (!this.level().isClientSide) { + this.setHookedEntity(result.getEntity()); + } ++ + } + + @Override +@@ -275,153 +301,162 @@ + this.setDeltaMovement(this.getDeltaMovement().normalize().scale(result.distanceTo(this))); + } + +- private void setHookedEntity(@Nullable Entity hookedEntity) { ++ public void setHookedEntity(@Nullable Entity hookedEntity) { + this.hookedIn = hookedEntity; +- this.getEntityData().set(DATA_HOOKED_ENTITY, hookedEntity == null ? 0 : hookedEntity.getId() + 1); ++ this.getEntityData().set(FishingHook.DATA_HOOKED_ENTITY, hookedEntity == null ? 0 : hookedEntity.getId() + 1); + } + + private void catchingFish(BlockPos pos) { +- ServerLevel serverLevel = (ServerLevel)this.level(); ++ ServerLevel worldserver = (ServerLevel) this.level(); + int i = 1; +- BlockPos blockPos = pos.above(); +- if (this.random.nextFloat() < 0.25F && this.level().isRainingAt(blockPos)) { +- i++; ++ BlockPos blockposition1 = pos.above(); ++ ++ if (this.rainInfluenced && this.random.nextFloat() < 0.25F && this.level().isRainingAt(blockposition1)) { // CraftBukkit ++ ++i; + } + +- if (this.random.nextFloat() < 0.5F && !this.level().canSeeSky(blockPos)) { +- i--; ++ if (this.skyInfluenced && this.random.nextFloat() < 0.5F && !this.level().canSeeSky(blockposition1)) { // CraftBukkit ++ --i; + } + + if (this.nibble > 0) { +- this.nibble--; ++ --this.nibble; + if (this.nibble <= 0) { + this.timeUntilLured = 0; + this.timeUntilHooked = 0; +- this.getEntityData().set(DATA_BITING, false); ++ this.getEntityData().set(FishingHook.DATA_BITING, false); ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) this.getPlayerOwner().getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.FAILED_ATTEMPT); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ // CraftBukkit end + } +- } else if (this.timeUntilHooked > 0) { +- this.timeUntilHooked -= i; ++ } else { ++ float f; ++ float f1; ++ float f2; ++ double d0; ++ double d1; ++ double d2; ++ IBlockData iblockdata; ++ + if (this.timeUntilHooked > 0) { +- this.fishAngle = this.fishAngle + (float)this.random.triangle(0.0, 9.188); +- float f = this.fishAngle * (float) (Math.PI / 180.0); +- float sin = Mth.sin(f); +- float cos = Mth.cos(f); +- double d = this.getX() + (double)(sin * (float)this.timeUntilHooked * 0.1F); +- double d1 = (double)((float)Mth.floor(this.getY()) + 1.0F); +- double d2 = this.getZ() + (double)(cos * (float)this.timeUntilHooked * 0.1F); +- BlockState blockState = serverLevel.getBlockState(BlockPos.containing(d, d1 - 1.0, d2)); +- if (blockState.is(Blocks.WATER)) { +- if (this.random.nextFloat() < 0.15F) { +- serverLevel.sendParticles(ParticleTypes.BUBBLE, d, d1 - 0.1F, d2, 1, (double)sin, 0.1, (double)cos, 0.0); ++ this.timeUntilHooked -= i; ++ if (this.timeUntilHooked > 0) { ++ this.fishAngle += (float) this.random.triangle(0.0D, 9.188D); ++ f = this.fishAngle * 0.017453292F; ++ f1 = Mth.sin(f); ++ f2 = Mth.cos(f); ++ d0 = this.getX() + (double) (f1 * (float) this.timeUntilHooked * 0.1F); ++ d1 = (double) ((float) Mth.floor(this.getY()) + 1.0F); ++ d2 = this.getZ() + (double) (f2 * (float) this.timeUntilHooked * 0.1F); ++ iblockdata = worldserver.getBlockState(BlockPos.containing(d0, d1 - 1.0D, d2)); ++ if (iblockdata.is(Blocks.WATER)) { ++ if (this.random.nextFloat() < 0.15F) { ++ worldserver.sendParticles(ParticleTypes.BUBBLE, d0, d1 - 0.10000000149011612D, d2, 1, (double) f1, 0.1D, (double) f2, 0.0D); ++ } ++ ++ float f3 = f1 * 0.04F; ++ float f4 = f2 * 0.04F; ++ ++ worldserver.sendParticles(ParticleTypes.FISHING, d0, d1, d2, 0, (double) f4, 0.01D, (double) (-f3), 1.0D); ++ worldserver.sendParticles(ParticleTypes.FISHING, d0, d1, d2, 0, (double) (-f4), 0.01D, (double) f3, 1.0D); + } ++ } else { ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) this.getPlayerOwner().getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.BITE); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ if (playerFishEvent.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ this.playSound(SoundEvents.FISHING_BOBBER_SPLASH, 0.25F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); ++ double d3 = this.getY() + 0.5D; + +- float f1 = sin * 0.04F; +- float f2 = cos * 0.04F; +- serverLevel.sendParticles(ParticleTypes.FISHING, d, d1, d2, 0, (double)f2, 0.01, (double)(-f1), 1.0); +- serverLevel.sendParticles(ParticleTypes.FISHING, d, d1, d2, 0, (double)(-f2), 0.01, (double)f1, 1.0); ++ worldserver.sendParticles(ParticleTypes.BUBBLE, this.getX(), d3, this.getZ(), (int) (1.0F + this.getBbWidth() * 20.0F), (double) this.getBbWidth(), 0.0D, (double) this.getBbWidth(), 0.20000000298023224D); ++ worldserver.sendParticles(ParticleTypes.FISHING, this.getX(), d3, this.getZ(), (int) (1.0F + this.getBbWidth() * 20.0F), (double) this.getBbWidth(), 0.0D, (double) this.getBbWidth(), 0.20000000298023224D); ++ this.nibble = Mth.nextInt(this.random, 20, 40); ++ this.getEntityData().set(FishingHook.DATA_BITING, true); + } +- } else { +- this.playSound(SoundEvents.FISHING_BOBBER_SPLASH, 0.25F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); +- double d3 = this.getY() + 0.5; +- serverLevel.sendParticles( +- ParticleTypes.BUBBLE, +- this.getX(), +- d3, +- this.getZ(), +- (int)(1.0F + this.getBbWidth() * 20.0F), +- (double)this.getBbWidth(), +- 0.0, +- (double)this.getBbWidth(), +- 0.2F +- ); +- serverLevel.sendParticles( +- ParticleTypes.FISHING, +- this.getX(), +- d3, +- this.getZ(), +- (int)(1.0F + this.getBbWidth() * 20.0F), +- (double)this.getBbWidth(), +- 0.0, +- (double)this.getBbWidth(), +- 0.2F +- ); +- this.nibble = Mth.nextInt(this.random, 20, 40); +- this.getEntityData().set(DATA_BITING, true); +- } +- } else if (this.timeUntilLured > 0) { +- this.timeUntilLured -= i; +- float f = 0.15F; +- if (this.timeUntilLured < 20) { +- f += (float)(20 - this.timeUntilLured) * 0.05F; +- } else if (this.timeUntilLured < 40) { +- f += (float)(40 - this.timeUntilLured) * 0.02F; +- } else if (this.timeUntilLured < 60) { +- f += (float)(60 - this.timeUntilLured) * 0.01F; +- } ++ } else if (this.timeUntilLured > 0) { ++ this.timeUntilLured -= i; ++ f = 0.15F; ++ if (this.timeUntilLured < 20) { ++ f += (float) (20 - this.timeUntilLured) * 0.05F; ++ } else if (this.timeUntilLured < 40) { ++ f += (float) (40 - this.timeUntilLured) * 0.02F; ++ } else if (this.timeUntilLured < 60) { ++ f += (float) (60 - this.timeUntilLured) * 0.01F; ++ } + +- if (this.random.nextFloat() < f) { +- float sin = Mth.nextFloat(this.random, 0.0F, 360.0F) * (float) (Math.PI / 180.0); +- float cos = Mth.nextFloat(this.random, 25.0F, 60.0F); +- double d = this.getX() + (double)(Mth.sin(sin) * cos) * 0.1; +- double d1 = (double)((float)Mth.floor(this.getY()) + 1.0F); +- double d2 = this.getZ() + (double)(Mth.cos(sin) * cos) * 0.1; +- BlockState blockState = serverLevel.getBlockState(BlockPos.containing(d, d1 - 1.0, d2)); +- if (blockState.is(Blocks.WATER)) { +- serverLevel.sendParticles(ParticleTypes.SPLASH, d, d1, d2, 2 + this.random.nextInt(2), 0.1F, 0.0, 0.1F, 0.0); ++ if (this.random.nextFloat() < f) { ++ f1 = Mth.nextFloat(this.random, 0.0F, 360.0F) * 0.017453292F; ++ f2 = Mth.nextFloat(this.random, 25.0F, 60.0F); ++ d0 = this.getX() + (double) (Mth.sin(f1) * f2) * 0.1D; ++ d1 = (double) ((float) Mth.floor(this.getY()) + 1.0F); ++ d2 = this.getZ() + (double) (Mth.cos(f1) * f2) * 0.1D; ++ iblockdata = worldserver.getBlockState(BlockPos.containing(d0, d1 - 1.0D, d2)); ++ if (iblockdata.is(Blocks.WATER)) { ++ worldserver.sendParticles(ParticleTypes.SPLASH, d0, d1, d2, 2 + this.random.nextInt(2), 0.10000000149011612D, 0.0D, 0.10000000149011612D, 0.0D); ++ } + } +- } + +- if (this.timeUntilLured <= 0) { +- this.fishAngle = Mth.nextFloat(this.random, 0.0F, 360.0F); +- this.timeUntilHooked = Mth.nextInt(this.random, 20, 80); ++ if (this.timeUntilLured <= 0) { ++ // CraftBukkit start - logic to modify fishing wait time, lure time, and lure angle ++ this.fishAngle = Mth.nextFloat(this.random, this.minLureAngle, this.maxLureAngle); ++ this.timeUntilHooked = Mth.nextInt(this.random, this.minLureTime, this.maxLureTime); ++ // CraftBukkit end ++ } ++ } else { ++ // CraftBukkit start - logic to modify fishing wait time ++ this.timeUntilLured = Mth.nextInt(this.random, this.minWaitTime, this.maxWaitTime); ++ this.timeUntilLured -= (this.applyLure) ? this.lureSpeed * 20 * 5 : 0; ++ // CraftBukkit end + } +- } else { +- this.timeUntilLured = Mth.nextInt(this.random, 100, 600); +- this.timeUntilLured = this.timeUntilLured - this.lureSpeed * 20 * 5; + } ++ + } + + private boolean calculateOpenWater(BlockPos pos) { +- FishingHook.OpenWaterType openWaterType = FishingHook.OpenWaterType.INVALID; ++ FishingHook.WaterPosition entityfishinghook_waterposition = FishingHook.WaterPosition.INVALID; + +- for (int i = -1; i <= 2; i++) { +- FishingHook.OpenWaterType openWaterTypeForArea = this.getOpenWaterTypeForArea(pos.offset(-2, i, -2), pos.offset(2, i, 2)); +- switch (openWaterTypeForArea) { ++ for (int i = -1; i <= 2; ++i) { ++ FishingHook.WaterPosition entityfishinghook_waterposition1 = this.getOpenWaterTypeForArea(pos.offset(-2, i, -2), pos.offset(2, i, 2)); ++ ++ switch (entityfishinghook_waterposition1) { + case INVALID: + return false; + case ABOVE_WATER: +- if (openWaterType == FishingHook.OpenWaterType.INVALID) { ++ if (entityfishinghook_waterposition == FishingHook.WaterPosition.INVALID) { + return false; + } + break; + case INSIDE_WATER: +- if (openWaterType == FishingHook.OpenWaterType.ABOVE_WATER) { ++ if (entityfishinghook_waterposition == FishingHook.WaterPosition.ABOVE_WATER) { + return false; + } + } + +- openWaterType = openWaterTypeForArea; ++ entityfishinghook_waterposition = entityfishinghook_waterposition1; + } + + return true; + } + +- private FishingHook.OpenWaterType getOpenWaterTypeForArea(BlockPos firstPos, BlockPos secondPos) { +- return BlockPos.betweenClosedStream(firstPos, secondPos) +- .map(this::getOpenWaterTypeForBlock) +- .reduce((firstType, secondType) -> firstType == secondType ? firstType : FishingHook.OpenWaterType.INVALID) +- .orElse(FishingHook.OpenWaterType.INVALID); ++ private FishingHook.WaterPosition getOpenWaterTypeForArea(BlockPos firstPos, BlockPos secondPos) { ++ return (FishingHook.WaterPosition) BlockPos.betweenClosedStream(firstPos, secondPos).map(this::getOpenWaterTypeForBlock).reduce((entityfishinghook_waterposition, entityfishinghook_waterposition1) -> { ++ return entityfishinghook_waterposition == entityfishinghook_waterposition1 ? entityfishinghook_waterposition : FishingHook.WaterPosition.INVALID; ++ }).orElse(FishingHook.WaterPosition.INVALID); + } + +- private FishingHook.OpenWaterType getOpenWaterTypeForBlock(BlockPos pos) { +- BlockState blockState = this.level().getBlockState(pos); +- if (!blockState.isAir() && !blockState.is(Blocks.LILY_PAD)) { +- FluidState fluidState = blockState.getFluidState(); +- return fluidState.is(FluidTags.WATER) && fluidState.isSource() && blockState.getCollisionShape(this.level(), pos).isEmpty() +- ? FishingHook.OpenWaterType.INSIDE_WATER +- : FishingHook.OpenWaterType.INVALID; ++ private FishingHook.WaterPosition getOpenWaterTypeForBlock(BlockPos pos) { ++ IBlockData iblockdata = this.level().getBlockState(pos); ++ ++ if (!iblockdata.isAir() && !iblockdata.is(Blocks.LILY_PAD)) { ++ FluidState fluid = iblockdata.getFluidState(); ++ ++ return fluid.is(FluidTags.WATER) && fluid.isSource() && iblockdata.getCollisionShape(this.level(), pos).isEmpty() ? FishingHook.WaterPosition.INSIDE_WATER : FishingHook.WaterPosition.INVALID; + } else { +- return FishingHook.OpenWaterType.ABOVE_WATER; ++ return FishingHook.WaterPosition.ABOVE_WATER; + } + } + +@@ -430,58 +465,90 @@ + } + + @Override +- public void addAdditionalSaveData(CompoundTag compound) { +- } ++ public void addAdditionalSaveData(CompoundTag compound) {} + + @Override +- public void readAdditionalSaveData(CompoundTag compound) { +- } ++ public void readAdditionalSaveData(CompoundTag compound) {} + + public int retrieve(ItemStack stack) { +- Player playerOwner = this.getPlayerOwner(); +- if (!this.level().isClientSide && playerOwner != null && !this.shouldStopFishing(playerOwner)) { ++ net.minecraft.world.entity.player.Player entityhuman = this.getPlayerOwner(); ++ ++ if (!this.level().isClientSide && entityhuman != null && !this.shouldStopFishing(entityhuman)) { + int i = 0; ++ + if (this.hookedIn != null) { ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), this.hookedIn.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_ENTITY); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ return 0; ++ } ++ // CraftBukkit end + this.pullEntity(this.hookedIn); +- CriteriaTriggers.FISHING_ROD_HOOKED.trigger((ServerPlayer)playerOwner, stack, this, Collections.emptyList()); +- this.level().broadcastEntityEvent(this, (byte)31); ++ CriteriaTriggers.FISHING_ROD_HOOKED.trigger((ServerPlayer) entityhuman, stack, this, Collections.emptyList()); ++ this.level().broadcastEntityEvent(this, (byte) 31); + i = this.hookedIn instanceof ItemEntity ? 3 : 5; + } else if (this.nibble > 0) { +- LootParams lootParams = new LootParams.Builder((ServerLevel)this.level()) +- .withParameter(LootContextParams.ORIGIN, this.position()) +- .withParameter(LootContextParams.TOOL, stack) +- .withParameter(LootContextParams.THIS_ENTITY, this) +- .withLuck((float)this.luck + playerOwner.getLuck()) +- .create(LootContextParamSets.FISHING); +- LootTable lootTable = this.level().getServer().getLootData().getLootTable(BuiltInLootTables.FISHING); +- List randomItems = lootTable.getRandomItems(lootParams); +- CriteriaTriggers.FISHING_ROD_HOOKED.trigger((ServerPlayer)playerOwner, stack, this, randomItems); ++ LootParams lootparams = (new LootParams.Builder((ServerLevel) this.level())).withParameter(LootContextParams.ORIGIN, this.position()).withParameter(LootContextParams.TOOL, stack).withParameter(LootContextParams.THIS_ENTITY, this).withLuck((float) this.luck + entityhuman.getLuck()).create(LootContextParamSets.FISHING); ++ LootTable loottable = this.level().getServer().getLootData().getLootTable(BuiltInLootTables.FISHING); ++ List list = loottable.getRandomItems(lootparams); + +- for (ItemStack itemStack : randomItems) { +- ItemEntity itemEntity = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), itemStack); +- double d = playerOwner.getX() - this.getX(); +- double d1 = playerOwner.getY() - this.getY(); +- double d2 = playerOwner.getZ() - this.getZ(); +- double d3 = 0.1; +- itemEntity.setDeltaMovement(d * 0.1, d1 * 0.1 + Math.sqrt(Math.sqrt(d * d + d1 * d1 + d2 * d2)) * 0.08, d2 * 0.1); +- this.level().addFreshEntity(itemEntity); +- playerOwner.level() +- .addFreshEntity( +- new ExperienceOrb( +- playerOwner.level(), playerOwner.getX(), playerOwner.getY() + 0.5, playerOwner.getZ() + 0.5, this.random.nextInt(6) + 1 +- ) +- ); +- if (itemStack.is(ItemTags.FISHES)) { +- playerOwner.awardStat(Stats.FISH_CAUGHT, 1); ++ CriteriaTriggers.FISHING_ROD_HOOKED.trigger((ServerPlayer) entityhuman, stack, this, list); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ ItemStack itemstack1 = (ItemStack) iterator.next(); ++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), itemstack1); ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); ++ playerFishEvent.setExpToDrop(this.random.nextInt(6) + 1); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ return 0; + } ++ // CraftBukkit end ++ double d0 = entityhuman.getX() - this.getX(); ++ double d1 = entityhuman.getY() - this.getY(); ++ double d2 = entityhuman.getZ() - this.getZ(); ++ double d3 = 0.1D; ++ ++ entityitem.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); ++ this.level().addFreshEntity(entityitem); ++ // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() ++ if (playerFishEvent.getExpToDrop() > 0) { ++ entityhuman.level().addFreshEntity(new ExperienceOrb(entityhuman.level(), entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop())); ++ } ++ // CraftBukkit end ++ if (itemstack1.is(ItemTags.FISHES)) { ++ entityhuman.awardStat(Stats.FISH_CAUGHT, 1); ++ } + } + + i = 1; + } + + if (this.onGround()) { ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.IN_GROUND); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ return 0; ++ } ++ // CraftBukkit end + i = 2; + } ++ // CraftBukkit start ++ if (i == 0) { ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.REEL_IN); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ if (playerFishEvent.isCancelled()) { ++ return 0; ++ } ++ } ++ // CraftBukkit end + + this.discard(); + return i; +@@ -492,18 +559,20 @@ + + @Override + public void handleEntityEvent(byte id) { +- if (id == 31 && this.level().isClientSide && this.hookedIn instanceof Player && ((Player)this.hookedIn).isLocalPlayer()) { ++ if (id == 31 && this.level().isClientSide && this.hookedIn instanceof net.minecraft.world.entity.player.Player && ((net.minecraft.world.entity.player.Player) this.hookedIn).isLocalPlayer()) { + this.pullEntity(this.hookedIn); + } + + super.handleEntityEvent(id); + } + +- protected void pullEntity(Entity entity) { +- Entity owner = this.getOwner(); +- if (owner != null) { +- Vec3 vec3 = new Vec3(owner.getX() - this.getX(), owner.getY() - this.getY(), owner.getZ() - this.getZ()).scale(0.1); +- entity.setDeltaMovement(entity.getDeltaMovement().add(vec3)); ++ public void pullEntity(Entity entity) { ++ Entity entity1 = this.getOwner(); ++ ++ if (entity1 != null) { ++ Vec3 vec3d = (new Vec3(entity1.getX() - this.getX(), entity1.getY() - this.getY(), entity1.getZ() - this.getZ())).scale(0.1D); ++ ++ entity.setDeltaMovement(entity.getDeltaMovement().add(vec3d)); + } + } + +@@ -514,13 +583,13 @@ + + @Override + public void remove(Entity.RemovalReason reason) { +- this.updateOwnerInfo(null); ++ this.updateOwnerInfo((FishingHook) null); + super.remove(reason); + } + + @Override + public void onClientRemoval() { +- this.updateOwnerInfo(null); ++ this.updateOwnerInfo((FishingHook) null); + } + + @Override +@@ -530,16 +599,19 @@ + } + + private void updateOwnerInfo(@Nullable FishingHook fishingHook) { +- Player playerOwner = this.getPlayerOwner(); +- if (playerOwner != null) { +- playerOwner.fishing = fishingHook; ++ net.minecraft.world.entity.player.Player entityhuman = this.getPlayerOwner(); ++ ++ if (entityhuman != null) { ++ entityhuman.fishing = fishingHook; + } ++ + } + + @Nullable +- public Player getPlayerOwner() { +- Entity owner = this.getOwner(); +- return owner instanceof Player ? (Player)owner : null; ++ public net.minecraft.world.entity.player.Player getPlayerOwner() { ++ Entity entity = this.getOwner(); ++ ++ return entity instanceof net.minecraft.world.entity.player.Player ? (net.minecraft.world.entity.player.Player) entity : null; + } + + @Nullable +@@ -554,29 +626,34 @@ + + @Override + public Packet getAddEntityPacket() { +- Entity owner = this.getOwner(); +- return new ClientboundAddEntityPacket(this, owner == null ? this.getId() : owner.getId()); ++ Entity entity = this.getOwner(); ++ ++ return new ClientboundAddEntityPacket(this, entity == null ? this.getId() : entity.getId()); + } + + @Override + public void recreateFromPacket(ClientboundAddEntityPacket packet) { + super.recreateFromPacket(packet); + if (this.getPlayerOwner() == null) { +- int data = packet.getData(); +- LOGGER.error("Failed to recreate fishing hook on client. {} (id: {}) is not a valid owner.", this.level().getEntity(data), data); ++ int i = packet.getData(); ++ ++ FishingHook.LOGGER.error("Failed to recreate fishing hook on client. {} (id: {}) is not a valid owner.", this.level().getEntity(i), i); + this.kill(); + } ++ + } + +- static enum FishHookState { +- FLYING, +- HOOKED_IN_ENTITY, +- BOBBING; ++ public static enum HookState { ++ ++ FLYING, HOOKED_IN_ENTITY, BOBBING; ++ ++ private HookState() {} + } + +- static enum OpenWaterType { +- ABOVE_WATER, +- INSIDE_WATER, +- INVALID; ++ private static enum WaterPosition { ++ ++ ABOVE_WATER, INSIDE_WATER, INVALID; ++ ++ private WaterPosition() {} + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/LargeFireball.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/LargeFireball.java.patch new file mode 100644 index 0000000000..badfa6564b --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/LargeFireball.java.patch @@ -0,0 +1,86 @@ +--- a/net/minecraft/world/entity/projectile/LargeFireball.java ++++ b/net/minecraft/world/entity/projectile/LargeFireball.java +@@ -8,27 +8,41 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++import org.bukkit.event.entity.ExplosionPrimeEvent; // CraftBukkit + + public class LargeFireball extends Fireball { +- private int explosionPower = 1; + ++ public int explosionPower = 1; ++ + public LargeFireball(EntityType entityType, Level level) { + super(entityType, level); ++ isIncendiary = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // CraftBukkit + } + +- public LargeFireball(Level level, LivingEntity shooter, double offsetX, double offsetY, double offsetZ, int explosionPower) { +- super(EntityType.FIREBALL, shooter, offsetX, offsetY, offsetZ, level); +- this.explosionPower = explosionPower; ++ public LargeFireball(Level level, LivingEntity shooter, double offsetX, double d1, double offsetY, int i) { ++ super(EntityType.FIREBALL, shooter, offsetX, d1, offsetY, level); ++ this.explosionPower = i; ++ isIncendiary = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // CraftBukkit + } + + @Override + protected void onHit(HitResult result) { + super.onHit(result); + if (!this.level().isClientSide) { +- boolean _boolean = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); +- this.level().explode(this, this.getX(), this.getY(), this.getZ(), (float)this.explosionPower, _boolean, Level.ExplosionInteraction.MOB); ++ boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); ++ ++ // CraftBukkit start - fire ExplosionPrimeEvent ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent((org.bukkit.entity.Explosive) this.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ // give 'this' instead of (Entity) null so we know what causes the damage ++ this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.MOB); ++ } ++ // CraftBukkit end + this.discard(); + } ++ + } + + @Override +@@ -36,25 +50,29 @@ + super.onHitEntity(result); + if (!this.level().isClientSide) { + Entity entity = result.getEntity(); +- Entity owner = this.getOwner(); +- entity.hurt(this.damageSources().fireball(this, owner), 6.0F); +- if (owner instanceof LivingEntity) { +- this.doEnchantDamageEffects((LivingEntity)owner, entity); ++ Entity entity1 = this.getOwner(); ++ ++ entity.hurt(this.damageSources().fireball(this, entity1), 6.0F); ++ if (entity1 instanceof LivingEntity) { ++ this.doEnchantDamageEffects((LivingEntity) entity1, entity); + } ++ + } + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- compound.putByte("ExplosionPower", (byte)this.explosionPower); ++ compound.putByte("ExplosionPower", (byte) this.explosionPower); + } + + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); + if (compound.contains("ExplosionPower", 99)) { +- this.explosionPower = compound.getByte("ExplosionPower"); ++ // CraftBukkit - set bukkitYield when setting explosionpower ++ bukkitYield = this.explosionPower = compound.getByte("ExplosionPower"); + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/LlamaSpit.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/LlamaSpit.java.patch new file mode 100644 index 0000000000..ab781fd084 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/LlamaSpit.java.patch @@ -0,0 +1,119 @@ +--- a/net/minecraft/world/entity/projectile/LlamaSpit.java ++++ b/net/minecraft/world/entity/projectile/LlamaSpit.java +@@ -3,6 +3,7 @@ + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; + import net.minecraft.util.Mth; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.animal.horse.Llama; +@@ -14,6 +15,7 @@ + import net.minecraft.world.phys.Vec3; + + public class LlamaSpit extends Projectile { ++ + public LlamaSpit(EntityType entityType, Level level) { + super(entityType, level); + } +@@ -21,45 +23,49 @@ + public LlamaSpit(Level level, Llama spitter) { + this(EntityType.LLAMA_SPIT, level); + this.setOwner(spitter); +- this.setPos( +- spitter.getX() - (double)(spitter.getBbWidth() + 1.0F) * 0.5 * (double)Mth.sin(spitter.yBodyRot * (float) (Math.PI / 180.0)), +- spitter.getEyeY() - 0.1F, +- spitter.getZ() + (double)(spitter.getBbWidth() + 1.0F) * 0.5 * (double)Mth.cos(spitter.yBodyRot * (float) (Math.PI / 180.0)) +- ); ++ this.setPos(spitter.getX() - (double) (spitter.getBbWidth() + 1.0F) * 0.5D * (double) Mth.sin(spitter.yBodyRot * 0.017453292F), spitter.getEyeY() - 0.10000000149011612D, spitter.getZ() + (double) (spitter.getBbWidth() + 1.0F) * 0.5D * (double) Mth.cos(spitter.yBodyRot * 0.017453292F)); + } + + @Override + public void tick() { + super.tick(); +- Vec3 deltaMovement = this.getDeltaMovement(); +- HitResult hitResultOnMoveVector = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); +- this.onHit(hitResultOnMoveVector); +- double d = this.getX() + deltaMovement.x; +- double d1 = this.getY() + deltaMovement.y; +- double d2 = this.getZ() + deltaMovement.z; ++ Vec3 vec3d = this.getDeltaMovement(); ++ HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); ++ ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event ++ double d0 = this.getX() + vec3d.x; ++ double d1 = this.getY() + vec3d.y; ++ double d2 = this.getZ() + vec3d.z; ++ + this.updateRotation(); + float f = 0.99F; + float f1 = 0.06F; ++ + if (this.level().getBlockStates(this.getBoundingBox()).noneMatch(BlockBehaviour.BlockStateBase::isAir)) { + this.discard(); + } else if (this.isInWaterOrBubble()) { + this.discard(); + } else { +- this.setDeltaMovement(deltaMovement.scale(0.99F)); ++ this.setDeltaMovement(vec3d.scale(0.9900000095367432D)); + if (!this.isNoGravity()) { +- this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.06F, 0.0)); ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.05999999865889549D, 0.0D)); + } + +- this.setPos(d, d1, d2); ++ this.setPos(d0, d1, d2); + } + } + + @Override + protected void onHitEntity(EntityHitResult result) { + super.onHitEntity(result); +- if (this.getOwner() instanceof LivingEntity livingEntity) { +- result.getEntity().hurt(this.damageSources().mobProjectile(this, livingEntity), 1.0F); ++ Entity entity = this.getOwner(); ++ ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ result.getEntity().hurt(this.damageSources().mobProjectile(this, entityliving), 1.0F); + } ++ + } + + @Override +@@ -68,24 +74,25 @@ + if (!this.level().isClientSide) { + this.discard(); + } ++ + } + + @Override +- protected void defineSynchedData() { +- } ++ protected void defineSynchedData() {} + + @Override + public void recreateFromPacket(ClientboundAddEntityPacket packet) { + super.recreateFromPacket(packet); +- double xa = packet.getXa(); +- double ya = packet.getYa(); +- double za = packet.getZa(); ++ double d0 = packet.getXa(); ++ double d1 = packet.getYa(); ++ double d2 = packet.getZa(); + +- for (int i = 0; i < 7; i++) { +- double d = 0.4 + 0.1 * (double)i; +- this.level().addParticle(ParticleTypes.SPIT, this.getX(), this.getY(), this.getZ(), xa * d, ya, za * d); ++ for (int i = 0; i < 7; ++i) { ++ double d3 = 0.4D + 0.1D * (double) i; ++ ++ this.level().addParticle(ParticleTypes.SPIT, this.getX(), this.getY(), this.getZ(), d0 * d3, d1, d2 * d3); + } + +- this.setDeltaMovement(xa, ya, za); ++ this.setDeltaMovement(d0, d1, d2); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/Projectile.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/Projectile.java.patch new file mode 100644 index 0000000000..2d066dcf81 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/Projectile.java.patch @@ -0,0 +1,300 @@ +--- a/net/minecraft/world/entity/projectile/Projectile.java ++++ b/net/minecraft/world/entity/projectile/Projectile.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.entity.projectile; + + import com.google.common.base.MoreObjects; ++import java.util.Iterator; + import java.util.UUID; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +@@ -17,14 +18,18 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.projectiles.ProjectileSource; ++// CraftBukkit end + + public abstract class Projectile extends Entity implements TraceableEntity { ++ + @Nullable + private UUID ownerUUID; + @Nullable +@@ -32,6 +37,10 @@ + private boolean leftOwner; + private boolean hasBeenShot; + ++ // CraftBukkit start ++ private boolean hitCancelled = false; ++ // CraftBukkit end ++ + Projectile(EntityType entityType, Level level) { + super(entityType, level); + } +@@ -41,6 +50,8 @@ + this.ownerUUID = owner.getUUID(); + this.cachedOwner = owner; + } ++ this.projectileSource = (owner != null && owner.getBukkitEntity() instanceof ProjectileSource) ? (ProjectileSource) owner.getBukkitEntity() : null; // CraftBukkit ++ + } + + @Nullable +@@ -48,16 +59,24 @@ + public Entity getOwner() { + if (this.cachedOwner != null && !this.cachedOwner.isRemoved()) { + return this.cachedOwner; +- } else if (this.ownerUUID != null && this.level() instanceof ServerLevel serverLevel) { +- this.cachedOwner = serverLevel.getEntity(this.ownerUUID); +- return this.cachedOwner; + } else { ++ if (this.ownerUUID != null) { ++ Level world = this.level(); ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ ++ this.cachedOwner = worldserver.getEntity(this.ownerUUID); ++ return this.cachedOwner; ++ } ++ } ++ + return null; + } + } + + public Entity getEffectSource() { +- return MoreObjects.firstNonNull(this.getOwner(), this); ++ return (Entity) MoreObjects.firstNonNull(this.getOwner(), this); + } + + @Override +@@ -91,9 +110,12 @@ + @Override + public void restoreFrom(Entity entity) { + super.restoreFrom(entity); +- if (entity instanceof Projectile projectile) { +- this.cachedOwner = projectile.cachedOwner; ++ if (entity instanceof Projectile) { ++ Projectile iprojectile = (Projectile) entity; ++ ++ this.cachedOwner = iprojectile.cachedOwner; + } ++ + } + + @Override +@@ -111,13 +133,17 @@ + } + + private boolean checkLeftOwner() { +- Entity owner = this.getOwner(); +- if (owner != null) { +- for (Entity entity : this.level() +- .getEntities( +- this, this.getBoundingBox().expandTowards(this.getDeltaMovement()).inflate(1.0), entity1 -> !entity1.isSpectator() && entity1.isPickable() +- )) { +- if (entity.getRootVehicle() == owner.getRootVehicle()) { ++ Entity entity = this.getOwner(); ++ ++ if (entity != null) { ++ Iterator iterator = this.level().getEntities((Entity) this, this.getBoundingBox().expandTowards(this.getDeltaMovement()).inflate(1.0D), (entity1) -> { ++ return !entity1.isSpectator() && entity1.isPickable(); ++ }).iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity1 = (Entity) iterator.next(); ++ ++ if (entity1.getRootVehicle() == entity.getRootVehicle()) { + return false; + } + } +@@ -126,80 +152,100 @@ + return true; + } + +- public void shoot(double x, double y, double z, float velocity, float inaccuracy) { +- Vec3 vec3 = new Vec3(x, y, z) +- .normalize() +- .add( +- this.random.triangle(0.0, 0.0172275 * (double)inaccuracy), +- this.random.triangle(0.0, 0.0172275 * (double)inaccuracy), +- this.random.triangle(0.0, 0.0172275 * (double)inaccuracy) +- ) +- .scale((double)velocity); +- this.setDeltaMovement(vec3); +- double d = vec3.horizontalDistance(); +- this.setYRot((float)(Mth.atan2(vec3.x, vec3.z) * 180.0F / (float)Math.PI)); +- this.setXRot((float)(Mth.atan2(vec3.y, d) * 180.0F / (float)Math.PI)); ++ public void shoot(double x, double d1, double y, float f, float z) { ++ Vec3 vec3d = (new Vec3(x, d1, y)).normalize().add(this.random.triangle(0.0D, 0.0172275D * (double) z), this.random.triangle(0.0D, 0.0172275D * (double) z), this.random.triangle(0.0D, 0.0172275D * (double) z)).scale((double) f); ++ ++ this.setDeltaMovement(vec3d); ++ double d3 = vec3d.horizontalDistance(); ++ ++ this.setYRot((float) (Mth.atan2(vec3d.x, vec3d.z) * 57.2957763671875D)); ++ this.setXRot((float) (Mth.atan2(vec3d.y, d3) * 57.2957763671875D)); + this.yRotO = this.getYRot(); + this.xRotO = this.getXRot(); + } + + public void shootFromRotation(Entity shooter, float x, float y, float z, float velocity, float inaccuracy) { +- float f = -Mth.sin(y * (float) (Math.PI / 180.0)) * Mth.cos(x * (float) (Math.PI / 180.0)); +- float f1 = -Mth.sin((x + z) * (float) (Math.PI / 180.0)); +- float f2 = Mth.cos(y * (float) (Math.PI / 180.0)) * Mth.cos(x * (float) (Math.PI / 180.0)); +- this.shoot((double)f, (double)f1, (double)f2, velocity, inaccuracy); +- Vec3 deltaMovement = shooter.getDeltaMovement(); +- this.setDeltaMovement(this.getDeltaMovement().add(deltaMovement.x, shooter.onGround() ? 0.0 : deltaMovement.y, deltaMovement.z)); ++ float f5 = -Mth.sin(y * 0.017453292F) * Mth.cos(x * 0.017453292F); ++ float f6 = -Mth.sin((x + z) * 0.017453292F); ++ float f7 = Mth.cos(y * 0.017453292F) * Mth.cos(x * 0.017453292F); ++ ++ this.shoot((double) f5, (double) f6, (double) f7, velocity, inaccuracy); ++ Vec3 vec3d = shooter.getDeltaMovement(); ++ ++ this.setDeltaMovement(this.getDeltaMovement().add(vec3d.x, shooter.onGround() ? 0.0D : vec3d.y, vec3d.z)); + } + +- protected void onHit(HitResult result) { +- HitResult.Type type = result.getType(); +- if (type == HitResult.Type.ENTITY) { +- this.onHitEntity((EntityHitResult)result); +- this.level().gameEvent(GameEvent.PROJECTILE_LAND, result.getLocation(), GameEvent.Context.of(this, null)); +- } else if (type == HitResult.Type.BLOCK) { +- BlockHitResult blockHitResult = (BlockHitResult)result; +- this.onHitBlock(blockHitResult); +- BlockPos blockPos = blockHitResult.getBlockPos(); +- this.level().gameEvent(GameEvent.PROJECTILE_LAND, blockPos, GameEvent.Context.of(this, this.level().getBlockState(blockPos))); ++ // CraftBukkit start - call projectile hit event ++ protected void preOnHit(HitResult movingobjectposition) { ++ org.bukkit.event.entity.ProjectileHitEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); ++ this.hitCancelled = event != null && event.isCancelled(); ++ if (movingobjectposition.getType() == HitResult.EnumMovingObjectType.BLOCK || !this.hitCancelled) { ++ this.onHit(movingobjectposition); + } + } ++ // CraftBukkit end + +- protected void onHitEntity(EntityHitResult result) { ++ protected void onHit(HitResult result) { ++ HitResult.EnumMovingObjectType movingobjectposition_enummovingobjecttype = result.getType(); ++ ++ if (movingobjectposition_enummovingobjecttype == HitResult.EnumMovingObjectType.ENTITY) { ++ this.onHitEntity((EntityHitResult) result); ++ this.level().gameEvent(GameEvent.PROJECTILE_LAND, result.getLocation(), GameEvent.Context.of(this, (IBlockData) null)); ++ } else if (movingobjectposition_enummovingobjecttype == HitResult.EnumMovingObjectType.BLOCK) { ++ BlockHitResult movingobjectpositionblock = (BlockHitResult) result; ++ ++ this.onHitBlock(movingobjectpositionblock); ++ BlockPos blockposition = movingobjectpositionblock.getBlockPos(); ++ ++ this.level().gameEvent(GameEvent.PROJECTILE_LAND, blockposition, GameEvent.Context.of(this, this.level().getBlockState(blockposition))); ++ } ++ + } + ++ protected void onHitEntity(EntityHitResult result) {} ++ + protected void onHitBlock(BlockHitResult result) { +- BlockState blockState = this.level().getBlockState(result.getBlockPos()); +- blockState.onProjectileHit(this.level(), blockState, result, this); ++ // CraftBukkit start - cancellable hit event ++ if (hitCancelled) { ++ return; ++ } ++ // CraftBukkit end ++ IBlockData iblockdata = this.level().getBlockState(result.getBlockPos()); ++ ++ iblockdata.onProjectileHit(this.level(), iblockdata, result, this); + } + + @Override +- public void lerpMotion(double x, double y, double z) { +- this.setDeltaMovement(x, y, z); ++ public void lerpMotion(double x, double d1, double y) { ++ this.setDeltaMovement(x, d1, y); + if (this.xRotO == 0.0F && this.yRotO == 0.0F) { +- double squareRoot = Math.sqrt(x * x + z * z); +- this.setXRot((float)(Mth.atan2(y, squareRoot) * 180.0F / (float)Math.PI)); +- this.setYRot((float)(Mth.atan2(x, z) * 180.0F / (float)Math.PI)); ++ double d3 = Math.sqrt(x * x + y * y); ++ ++ this.setXRot((float) (Mth.atan2(d1, d3) * 57.2957763671875D)); ++ this.setYRot((float) (Mth.atan2(x, y) * 57.2957763671875D)); + this.xRotO = this.getXRot(); + this.yRotO = this.getYRot(); + this.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); + } ++ + } + + protected boolean canHitEntity(Entity target) { + if (!target.canBeHitByProjectile()) { + return false; + } else { +- Entity owner = this.getOwner(); +- return owner == null || this.leftOwner || !owner.isPassengerOfSameVehicle(target); ++ Entity entity1 = this.getOwner(); ++ ++ return entity1 == null || this.leftOwner || !entity1.isPassengerOfSameVehicle(target); + } + } + + protected void updateRotation() { +- Vec3 deltaMovement = this.getDeltaMovement(); +- double d = deltaMovement.horizontalDistance(); +- this.setXRot(lerpRotation(this.xRotO, (float)(Mth.atan2(deltaMovement.y, d) * 180.0F / (float)Math.PI))); +- this.setYRot(lerpRotation(this.yRotO, (float)(Mth.atan2(deltaMovement.x, deltaMovement.z) * 180.0F / (float)Math.PI))); ++ Vec3 vec3d = this.getDeltaMovement(); ++ double d0 = vec3d.horizontalDistance(); ++ ++ this.setXRot(lerpRotation(this.xRotO, (float) (Mth.atan2(vec3d.y, d0) * 57.2957763671875D))); ++ this.setYRot(lerpRotation(this.yRotO, (float) (Mth.atan2(vec3d.x, vec3d.z) * 57.2957763671875D))); + } + + protected static float lerpRotation(float currentRotation, float targetRotation) { +@@ -216,26 +262,30 @@ + + @Override + public Packet getAddEntityPacket() { +- Entity owner = this.getOwner(); +- return new ClientboundAddEntityPacket(this, owner == null ? 0 : owner.getId()); ++ Entity entity = this.getOwner(); ++ ++ return new ClientboundAddEntityPacket(this, entity == null ? 0 : entity.getId()); + } + + @Override + public void recreateFromPacket(ClientboundAddEntityPacket packet) { + super.recreateFromPacket(packet); + Entity entity = this.level().getEntity(packet.getData()); ++ + if (entity != null) { + this.setOwner(entity); + } ++ + } + + @Override + public boolean mayInteract(Level level, BlockPos pos) { +- Entity owner = this.getOwner(); +- return owner instanceof Player ? owner.mayInteract(level, pos) : owner == null || level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); ++ Entity entity = this.getOwner(); ++ ++ return entity instanceof Player ? entity.mayInteract(level, pos) : entity == null || level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); + } + +- public boolean mayBreak(Level level) { +- return this.getType().is(EntityTypeTags.IMPACT_PROJECTILES) && level.getGameRules().getBoolean(GameRules.RULE_PROJECTILESCANBREAKBLOCKS); ++ public boolean mayBreak(Level world) { ++ return this.getType().is(EntityTypeTags.IMPACT_PROJECTILES) && world.getGameRules().getBoolean(GameRules.RULE_PROJECTILESCANBREAKBLOCKS); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ShulkerBullet.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ShulkerBullet.java.patch new file mode 100644 index 0000000000..0242bf32b8 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ShulkerBullet.java.patch @@ -0,0 +1,357 @@ +--- a/net/minecraft/world/entity/projectile/ShulkerBullet.java ++++ b/net/minecraft/world/entity/projectile/ShulkerBullet.java +@@ -30,7 +30,8 @@ + import net.minecraft.world.phys.Vec3; + + public class ShulkerBullet extends Projectile { +- private static final double SPEED = 0.15; ++ ++ private static final double SPEED = 0.15D; + @Nullable + private Entity finalTarget; + @Nullable +@@ -50,16 +51,30 @@ + public ShulkerBullet(Level level, LivingEntity shooter, Entity finalTarget, Direction.Axis axis) { + this(EntityType.SHULKER_BULLET, level); + this.setOwner(shooter); +- BlockPos blockPos = shooter.blockPosition(); +- double d = (double)blockPos.getX() + 0.5; +- double d1 = (double)blockPos.getY() + 0.5; +- double d2 = (double)blockPos.getZ() + 0.5; +- this.moveTo(d, d1, d2, this.getYRot(), this.getXRot()); ++ BlockPos blockposition = shooter.blockPosition(); ++ double d0 = (double) blockposition.getX() + 0.5D; ++ double d1 = (double) blockposition.getY() + 0.5D; ++ double d2 = (double) blockposition.getZ() + 0.5D; ++ ++ this.moveTo(d0, d1, d2, this.getYRot(), this.getXRot()); + this.finalTarget = finalTarget; + this.currentMoveDirection = Direction.UP; + this.selectNextMoveDirection(axis); ++ projectileSource = (org.bukkit.entity.LivingEntity) shooter.getBukkitEntity(); // CraftBukkit + } + ++ // CraftBukkit start ++ public Entity getTarget() { ++ return this.finalTarget; ++ } ++ ++ public void setTarget(Entity e) { ++ this.finalTarget = e; ++ this.currentMoveDirection = Direction.UP; ++ this.selectNextMoveDirection(Direction.Axis.X); ++ } ++ // CraftBukkit end ++ + @Override + public SoundSource getSoundSource() { + return SoundSource.HOSTILE; +@@ -96,11 +111,11 @@ + if (compound.hasUUID("Target")) { + this.targetId = compound.getUUID("Target"); + } ++ + } + + @Override +- protected void defineSynchedData() { +- } ++ protected void defineSynchedData() {} + + @Nullable + private Direction getMoveDirection() { +@@ -112,73 +127,77 @@ + } + + private void selectNextMoveDirection(@Nullable Direction.Axis axis) { +- double d = 0.5; +- BlockPos blockPos; ++ double d0 = 0.5D; ++ BlockPos blockposition; ++ + if (this.finalTarget == null) { +- blockPos = this.blockPosition().below(); ++ blockposition = this.blockPosition().below(); + } else { +- d = (double)this.finalTarget.getBbHeight() * 0.5; +- blockPos = BlockPos.containing(this.finalTarget.getX(), this.finalTarget.getY() + d, this.finalTarget.getZ()); ++ d0 = (double) this.finalTarget.getBbHeight() * 0.5D; ++ blockposition = BlockPos.containing(this.finalTarget.getX(), this.finalTarget.getY() + d0, this.finalTarget.getZ()); + } + +- double d1 = (double)blockPos.getX() + 0.5; +- double d2 = (double)blockPos.getY() + d; +- double d3 = (double)blockPos.getZ() + 0.5; +- Direction direction = null; +- if (!blockPos.closerToCenterThan(this.position(), 2.0)) { +- BlockPos blockPos1 = this.blockPosition(); ++ double d1 = (double) blockposition.getX() + 0.5D; ++ double d2 = (double) blockposition.getY() + d0; ++ double d3 = (double) blockposition.getZ() + 0.5D; ++ Direction enumdirection = null; ++ ++ if (!blockposition.closerToCenterThan(this.position(), 2.0D)) { ++ BlockPos blockposition1 = this.blockPosition(); + List list = Lists.newArrayList(); ++ + if (axis != Direction.Axis.X) { +- if (blockPos1.getX() < blockPos.getX() && this.level().isEmptyBlock(blockPos1.east())) { ++ if (blockposition1.getX() < blockposition.getX() && this.level().isEmptyBlock(blockposition1.east())) { + list.add(Direction.EAST); +- } else if (blockPos1.getX() > blockPos.getX() && this.level().isEmptyBlock(blockPos1.west())) { ++ } else if (blockposition1.getX() > blockposition.getX() && this.level().isEmptyBlock(blockposition1.west())) { + list.add(Direction.WEST); + } + } + + if (axis != Direction.Axis.Y) { +- if (blockPos1.getY() < blockPos.getY() && this.level().isEmptyBlock(blockPos1.above())) { ++ if (blockposition1.getY() < blockposition.getY() && this.level().isEmptyBlock(blockposition1.above())) { + list.add(Direction.UP); +- } else if (blockPos1.getY() > blockPos.getY() && this.level().isEmptyBlock(blockPos1.below())) { ++ } else if (blockposition1.getY() > blockposition.getY() && this.level().isEmptyBlock(blockposition1.below())) { + list.add(Direction.DOWN); + } + } + + if (axis != Direction.Axis.Z) { +- if (blockPos1.getZ() < blockPos.getZ() && this.level().isEmptyBlock(blockPos1.south())) { ++ if (blockposition1.getZ() < blockposition.getZ() && this.level().isEmptyBlock(blockposition1.south())) { + list.add(Direction.SOUTH); +- } else if (blockPos1.getZ() > blockPos.getZ() && this.level().isEmptyBlock(blockPos1.north())) { ++ } else if (blockposition1.getZ() > blockposition.getZ() && this.level().isEmptyBlock(blockposition1.north())) { + list.add(Direction.NORTH); + } + } + +- direction = Direction.getRandom(this.random); ++ enumdirection = Direction.getRandom(this.random); + if (list.isEmpty()) { +- for (int i = 5; !this.level().isEmptyBlock(blockPos1.relative(direction)) && i > 0; i--) { +- direction = Direction.getRandom(this.random); ++ for (int i = 5; !this.level().isEmptyBlock(blockposition1.relative(enumdirection)) && i > 0; --i) { ++ enumdirection = Direction.getRandom(this.random); + } + } else { +- direction = list.get(this.random.nextInt(list.size())); ++ enumdirection = (Direction) list.get(this.random.nextInt(list.size())); + } + +- d1 = this.getX() + (double)direction.getStepX(); +- d2 = this.getY() + (double)direction.getStepY(); +- d3 = this.getZ() + (double)direction.getStepZ(); ++ d1 = this.getX() + (double) enumdirection.getStepX(); ++ d2 = this.getY() + (double) enumdirection.getStepY(); ++ d3 = this.getZ() + (double) enumdirection.getStepZ(); + } + +- this.setMoveDirection(direction); ++ this.setMoveDirection(enumdirection); + double d4 = d1 - this.getX(); + double d5 = d2 - this.getY(); + double d6 = d3 - this.getZ(); +- double squareRoot = Math.sqrt(d4 * d4 + d5 * d5 + d6 * d6); +- if (squareRoot == 0.0) { +- this.targetDeltaX = 0.0; +- this.targetDeltaY = 0.0; +- this.targetDeltaZ = 0.0; ++ double d7 = Math.sqrt(d4 * d4 + d5 * d5 + d6 * d6); ++ ++ if (d7 == 0.0D) { ++ this.targetDeltaX = 0.0D; ++ this.targetDeltaY = 0.0D; ++ this.targetDeltaZ = 0.0D; + } else { +- this.targetDeltaX = d4 / squareRoot * 0.15; +- this.targetDeltaY = d5 / squareRoot * 0.15; +- this.targetDeltaZ = d6 / squareRoot * 0.15; ++ this.targetDeltaX = d4 / d7 * 0.15D; ++ this.targetDeltaY = d5 / d7 * 0.15D; ++ this.targetDeltaZ = d6 / d7 * 0.15D; + } + + this.hasImpulse = true; +@@ -190,73 +209,69 @@ + if (this.level().getDifficulty() == Difficulty.PEACEFUL) { + this.discard(); + } ++ + } + + @Override + public void tick() { + super.tick(); ++ Vec3 vec3d; ++ + if (!this.level().isClientSide) { + if (this.finalTarget == null && this.targetId != null) { +- this.finalTarget = ((ServerLevel)this.level()).getEntity(this.targetId); ++ this.finalTarget = ((ServerLevel) this.level()).getEntity(this.targetId); + if (this.finalTarget == null) { + this.targetId = null; + } + } + +- if (this.finalTarget == null || !this.finalTarget.isAlive() || this.finalTarget instanceof Player && this.finalTarget.isSpectator()) { +- if (!this.isNoGravity()) { +- this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.04, 0.0)); +- } +- } else { +- this.targetDeltaX = Mth.clamp(this.targetDeltaX * 1.025, -1.0, 1.0); +- this.targetDeltaY = Mth.clamp(this.targetDeltaY * 1.025, -1.0, 1.0); +- this.targetDeltaZ = Mth.clamp(this.targetDeltaZ * 1.025, -1.0, 1.0); +- Vec3 deltaMovement = this.getDeltaMovement(); +- this.setDeltaMovement( +- deltaMovement.add( +- (this.targetDeltaX - deltaMovement.x) * 0.2, (this.targetDeltaY - deltaMovement.y) * 0.2, (this.targetDeltaZ - deltaMovement.z) * 0.2 +- ) +- ); ++ if (this.finalTarget != null && this.finalTarget.isAlive() && (!(this.finalTarget instanceof Player) || !this.finalTarget.isSpectator())) { ++ this.targetDeltaX = Mth.clamp(this.targetDeltaX * 1.025D, -1.0D, 1.0D); ++ this.targetDeltaY = Mth.clamp(this.targetDeltaY * 1.025D, -1.0D, 1.0D); ++ this.targetDeltaZ = Mth.clamp(this.targetDeltaZ * 1.025D, -1.0D, 1.0D); ++ vec3d = this.getDeltaMovement(); ++ this.setDeltaMovement(vec3d.add((this.targetDeltaX - vec3d.x) * 0.2D, (this.targetDeltaY - vec3d.y) * 0.2D, (this.targetDeltaZ - vec3d.z) * 0.2D)); ++ } else if (!this.isNoGravity()) { ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.04D, 0.0D)); + } + +- HitResult hitResultOnMoveVector = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); +- if (hitResultOnMoveVector.getType() != HitResult.Type.MISS) { +- this.onHit(hitResultOnMoveVector); ++ HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); ++ ++ if (movingobjectposition.getType() != HitResult.EnumMovingObjectType.MISS) { ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + } + } + + this.checkInsideBlocks(); +- Vec3 deltaMovement = this.getDeltaMovement(); +- this.setPos(this.getX() + deltaMovement.x, this.getY() + deltaMovement.y, this.getZ() + deltaMovement.z); ++ vec3d = this.getDeltaMovement(); ++ this.setPos(this.getX() + vec3d.x, this.getY() + vec3d.y, this.getZ() + vec3d.z); + ProjectileUtil.rotateTowardsMovement(this, 0.5F); + if (this.level().isClientSide) { +- this.level() +- .addParticle( +- ParticleTypes.END_ROD, this.getX() - deltaMovement.x, this.getY() - deltaMovement.y + 0.15, this.getZ() - deltaMovement.z, 0.0, 0.0, 0.0 +- ); ++ this.level().addParticle(ParticleTypes.END_ROD, this.getX() - vec3d.x, this.getY() - vec3d.y + 0.15D, this.getZ() - vec3d.z, 0.0D, 0.0D, 0.0D); + } else if (this.finalTarget != null && !this.finalTarget.isRemoved()) { + if (this.flightSteps > 0) { +- this.flightSteps--; ++ --this.flightSteps; + if (this.flightSteps == 0) { + this.selectNextMoveDirection(this.currentMoveDirection == null ? null : this.currentMoveDirection.getAxis()); + } + } + + if (this.currentMoveDirection != null) { +- BlockPos blockPos = this.blockPosition(); +- Direction.Axis axis = this.currentMoveDirection.getAxis(); +- if (this.level().loadedAndEntityCanStandOn(blockPos.relative(this.currentMoveDirection), this)) { +- this.selectNextMoveDirection(axis); ++ BlockPos blockposition = this.blockPosition(); ++ Direction.Axis enumdirection_enumaxis = this.currentMoveDirection.getAxis(); ++ ++ if (this.level().loadedAndEntityCanStandOn(blockposition.relative(this.currentMoveDirection), this)) { ++ this.selectNextMoveDirection(enumdirection_enumaxis); + } else { +- BlockPos blockPos1 = this.finalTarget.blockPosition(); +- if (axis == Direction.Axis.X && blockPos.getX() == blockPos1.getX() +- || axis == Direction.Axis.Z && blockPos.getZ() == blockPos1.getZ() +- || axis == Direction.Axis.Y && blockPos.getY() == blockPos1.getY()) { +- this.selectNextMoveDirection(axis); ++ BlockPos blockposition1 = this.finalTarget.blockPosition(); ++ ++ if (enumdirection_enumaxis == Direction.Axis.X && blockposition.getX() == blockposition1.getX() || enumdirection_enumaxis == Direction.Axis.Z && blockposition.getZ() == blockposition1.getZ() || enumdirection_enumaxis == Direction.Axis.Y && blockposition.getY() == blockposition1.getY()) { ++ this.selectNextMoveDirection(enumdirection_enumaxis); + } + } + } + } ++ + } + + @Override +@@ -271,7 +286,7 @@ + + @Override + public boolean shouldRenderAtSqrDistance(double distance) { +- return distance < 16384.0; ++ return distance < 16384.0D; + } + + @Override +@@ -283,27 +298,31 @@ + protected void onHitEntity(EntityHitResult result) { + super.onHitEntity(result); + Entity entity = result.getEntity(); +- Entity owner = this.getOwner(); +- LivingEntity livingEntity = owner instanceof LivingEntity ? (LivingEntity)owner : null; +- boolean flag = entity.hurt(this.damageSources().mobProjectile(this, livingEntity), 4.0F); ++ Entity entity1 = this.getOwner(); ++ LivingEntity entityliving = entity1 instanceof LivingEntity ? (LivingEntity) entity1 : null; ++ boolean flag = entity.hurt(this.damageSources().mobProjectile(this, entityliving), 4.0F); ++ + if (flag) { +- this.doEnchantDamageEffects(livingEntity, entity); +- if (entity instanceof LivingEntity livingEntity1) { +- livingEntity1.addEffect(new MobEffectInstance(MobEffects.LEVITATION, 200), MoreObjects.firstNonNull(owner, this)); ++ this.doEnchantDamageEffects(entityliving, entity); ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving1 = (LivingEntity) entity; ++ ++ entityliving1.addEffect(new MobEffectInstance(MobEffects.LEVITATION, 200), (Entity) MoreObjects.firstNonNull(entity1, this), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } ++ + } + + @Override + protected void onHitBlock(BlockHitResult result) { + super.onHitBlock(result); +- ((ServerLevel)this.level()).sendParticles(ParticleTypes.EXPLOSION, this.getX(), this.getY(), this.getZ(), 2, 0.2, 0.2, 0.2, 0.0); ++ ((ServerLevel) this.level()).sendParticles(ParticleTypes.EXPLOSION, this.getX(), this.getY(), this.getZ(), 2, 0.2D, 0.2D, 0.2D, 0.0D); + this.playSound(SoundEvents.SHULKER_BULLET_HIT, 1.0F, 1.0F); + } + + private void destroy() { + this.discard(); +- this.level().gameEvent(GameEvent.ENTITY_DAMAGE, this.position(), GameEvent.Context.of(this)); ++ this.level().gameEvent(GameEvent.ENTITY_DAMAGE, this.position(), GameEvent.Context.of((Entity) this)); + } + + @Override +@@ -319,9 +338,14 @@ + + @Override + public boolean hurt(DamageSource source, float amount) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, false)) { ++ return false; ++ } ++ // CraftBukkit end + if (!this.level().isClientSide) { + this.playSound(SoundEvents.SHULKER_BULLET_HURT, 1.0F, 1.0F); +- ((ServerLevel)this.level()).sendParticles(ParticleTypes.CRIT, this.getX(), this.getY(), this.getZ(), 15, 0.2, 0.2, 0.2, 0.0); ++ ((ServerLevel) this.level()).sendParticles(ParticleTypes.CRIT, this.getX(), this.getY(), this.getZ(), 15, 0.2D, 0.2D, 0.2D, 0.0D); + this.destroy(); + } + +@@ -331,9 +355,10 @@ + @Override + public void recreateFromPacket(ClientboundAddEntityPacket packet) { + super.recreateFromPacket(packet); +- double xa = packet.getXa(); +- double ya = packet.getYa(); +- double za = packet.getZa(); +- this.setDeltaMovement(xa, ya, za); ++ double d0 = packet.getXa(); ++ double d1 = packet.getYa(); ++ double d2 = packet.getZa(); ++ ++ this.setDeltaMovement(d0, d1, d2); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/SmallFireball.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/SmallFireball.java.patch new file mode 100644 index 0000000000..f62e624986 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/SmallFireball.java.patch @@ -0,0 +1,93 @@ +--- a/net/minecraft/world/entity/projectile/SmallFireball.java ++++ b/net/minecraft/world/entity/projectile/SmallFireball.java +@@ -12,18 +12,25 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; // CraftBukkit + + public class SmallFireball extends Fireball { ++ + public SmallFireball(EntityType entityType, Level level) { + super(entityType, level); + } + +- public SmallFireball(Level level, LivingEntity shooter, double offsetX, double offsetY, double offsetZ) { +- super(EntityType.SMALL_FIREBALL, shooter, offsetX, offsetY, offsetZ, level); ++ public SmallFireball(Level level, LivingEntity shooter, double offsetX, double d1, double offsetY) { ++ super(EntityType.SMALL_FIREBALL, shooter, offsetX, d1, offsetY, level); ++ // CraftBukkit start ++ if (this.getOwner() != null && this.getOwner() instanceof Mob) { ++ isIncendiary = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); ++ } ++ // CraftBukkit end + } + +- public SmallFireball(Level level, double x, double y, double z, double offsetX, double offsetY, double offsetZ) { +- super(EntityType.SMALL_FIREBALL, x, y, z, offsetX, offsetY, offsetZ, level); ++ public SmallFireball(Level level, double x, double d1, double y, double d3, double z, double d5) { ++ super(EntityType.SMALL_FIREBALL, x, d1, y, d3, z, d5, level); + } + + @Override +@@ -31,14 +38,23 @@ + super.onHitEntity(result); + if (!this.level().isClientSide) { + Entity entity = result.getEntity(); +- Entity owner = this.getOwner(); +- int remainingFireTicks = entity.getRemainingFireTicks(); +- entity.setSecondsOnFire(5); +- if (!entity.hurt(this.damageSources().fireball(this, owner), 5.0F)) { +- entity.setRemainingFireTicks(remainingFireTicks); +- } else if (owner instanceof LivingEntity) { +- this.doEnchantDamageEffects((LivingEntity)owner, entity); ++ Entity entity1 = this.getOwner(); ++ int i = entity.getRemainingFireTicks(); ++ ++ // CraftBukkit start - Entity damage by entity event + combust event ++ EntityCombustByEntityEvent event = new EntityCombustByEntityEvent((org.bukkit.entity.Projectile) this.getBukkitEntity(), entity.getBukkitEntity(), 5); ++ entity.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ entity.setSecondsOnFire(event.getDuration(), false); + } ++ // CraftBukkit end ++ if (!entity.hurt(this.damageSources().fireball(this, entity1), 5.0F)) { ++ entity.setRemainingFireTicks(i); ++ } else if (entity1 instanceof LivingEntity) { ++ this.doEnchantDamageEffects((LivingEntity) entity1, entity); ++ } ++ + } + } + +@@ -46,13 +62,16 @@ + protected void onHitBlock(BlockHitResult result) { + super.onHitBlock(result); + if (!this.level().isClientSide) { +- Entity owner = this.getOwner(); +- if (!(owner instanceof Mob) || this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- BlockPos blockPos = result.getBlockPos().relative(result.getDirection()); +- if (this.level().isEmptyBlock(blockPos)) { +- this.level().setBlockAndUpdate(blockPos, BaseFireBlock.getState(this.level(), blockPos)); ++ Entity entity = this.getOwner(); ++ ++ if (isIncendiary) { // CraftBukkit ++ BlockPos blockposition = result.getBlockPos().relative(result.getDirection()); ++ ++ if (this.level().isEmptyBlock(blockposition) && !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition, this).isCancelled()) { // CraftBukkit ++ this.level().setBlockAndUpdate(blockposition, BaseFireBlock.getState(this.level(), blockposition)); + } + } ++ + } + } + +@@ -62,6 +81,7 @@ + if (!this.level().isClientSide) { + this.discard(); + } ++ + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/SpectralArrow.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/SpectralArrow.java.patch new file mode 100644 index 0000000000..3de2d9a67c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/SpectralArrow.java.patch @@ -0,0 +1,57 @@ +--- a/net/minecraft/world/entity/projectile/SpectralArrow.java ++++ b/net/minecraft/world/entity/projectile/SpectralArrow.java +@@ -11,34 +11,37 @@ + import net.minecraft.world.level.Level; + + public class SpectralArrow extends AbstractArrow { ++ + private static final ItemStack DEFAULT_ARROW_STACK = new ItemStack(Items.SPECTRAL_ARROW); +- private int duration = 200; ++ public int duration = 200; + + public SpectralArrow(EntityType entityType, Level level) { +- super(entityType, level, DEFAULT_ARROW_STACK); ++ super(entityType, level, SpectralArrow.DEFAULT_ARROW_STACK); + } + +- public SpectralArrow(Level level, LivingEntity livingEntity, ItemStack itemStack) { +- super(EntityType.SPECTRAL_ARROW, livingEntity, level, itemStack); ++ public SpectralArrow(Level world, LivingEntity entityliving, ItemStack itemstack) { ++ super(EntityType.SPECTRAL_ARROW, entityliving, world, itemstack); + } + +- public SpectralArrow(Level level, double d, double d1, double d2, ItemStack itemStack) { +- super(EntityType.SPECTRAL_ARROW, d, d1, d2, level, itemStack); ++ public SpectralArrow(Level world, double d0, double d1, double d2, ItemStack itemstack) { ++ super(EntityType.SPECTRAL_ARROW, d0, d1, d2, world, itemstack); + } + + @Override + public void tick() { + super.tick(); + if (this.level().isClientSide && !this.inGround) { +- this.level().addParticle(ParticleTypes.INSTANT_EFFECT, this.getX(), this.getY(), this.getZ(), 0.0, 0.0, 0.0); ++ this.level().addParticle(ParticleTypes.INSTANT_EFFECT, this.getX(), this.getY(), this.getZ(), 0.0D, 0.0D, 0.0D); + } ++ + } + + @Override + protected void doPostHurtEffects(LivingEntity living) { + super.doPostHurtEffects(living); +- MobEffectInstance mobEffectInstance = new MobEffectInstance(MobEffects.GLOWING, this.duration, 0); +- living.addEffect(mobEffectInstance, this.getEffectSource()); ++ MobEffectInstance mobeffect = new MobEffectInstance(MobEffects.GLOWING, this.duration, 0); ++ ++ living.addEffect(mobeffect, this.getEffectSource(), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ARROW); // CraftBukkit + } + + @Override +@@ -47,6 +50,7 @@ + if (compound.contains("Duration")) { + this.duration = compound.getInt("Duration"); + } ++ + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrowableItemProjectile.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrowableItemProjectile.java.patch new file mode 100644 index 0000000000..e27c9b42d6 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrowableItemProjectile.java.patch @@ -0,0 +1,86 @@ +--- a/net/minecraft/world/entity/projectile/ThrowableItemProjectile.java ++++ b/net/minecraft/world/entity/projectile/ThrowableItemProjectile.java +@@ -11,16 +11,15 @@ + import net.minecraft.world.level.Level; + + public abstract class ThrowableItemProjectile extends ThrowableProjectile implements ItemSupplier { +- private static final EntityDataAccessor DATA_ITEM_STACK = SynchedEntityData.defineId( +- ThrowableItemProjectile.class, EntityDataSerializers.ITEM_STACK +- ); + ++ private static final EntityDataAccessor DATA_ITEM_STACK = SynchedEntityData.defineId(ThrowableItemProjectile.class, EntityDataSerializers.ITEM_STACK); ++ + public ThrowableItemProjectile(EntityType entityType, Level level) { + super(entityType, level); + } + +- public ThrowableItemProjectile(EntityType entityType, double x, double y, double z, Level level) { +- super(entityType, x, y, z, level); ++ public ThrowableItemProjectile(EntityType entityType, double x, double d1, double y, Level world) { ++ super(entityType, x, d1, y, world); + } + + public ThrowableItemProjectile(EntityType entityType, LivingEntity shooter, Level level) { +@@ -29,40 +28,51 @@ + + public void setItem(ItemStack stack) { + if (!stack.is(this.getDefaultItem()) || stack.hasTag()) { +- this.getEntityData().set(DATA_ITEM_STACK, stack.copyWithCount(1)); ++ this.getEntityData().set(ThrowableItemProjectile.DATA_ITEM_STACK, stack.copyWithCount(1)); + } ++ + } + + protected abstract Item getDefaultItem(); + +- protected ItemStack getItemRaw() { +- return this.getEntityData().get(DATA_ITEM_STACK); ++ // CraftBukkit start ++ public Item getDefaultItemPublic() { ++ return getDefaultItem(); + } ++ // CraftBukkit end + ++ public ItemStack getItemRaw() { ++ return (ItemStack) this.getEntityData().get(ThrowableItemProjectile.DATA_ITEM_STACK); ++ } ++ + @Override + public ItemStack getItem() { +- ItemStack itemRaw = this.getItemRaw(); +- return itemRaw.isEmpty() ? new ItemStack(this.getDefaultItem()) : itemRaw; ++ ItemStack itemstack = this.getItemRaw(); ++ ++ return itemstack.isEmpty() ? new ItemStack(this.getDefaultItem()) : itemstack; + } + + @Override + protected void defineSynchedData() { +- this.getEntityData().define(DATA_ITEM_STACK, ItemStack.EMPTY); ++ this.getEntityData().define(ThrowableItemProjectile.DATA_ITEM_STACK, ItemStack.EMPTY); + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- ItemStack itemRaw = this.getItemRaw(); +- if (!itemRaw.isEmpty()) { +- compound.put("Item", itemRaw.save(new CompoundTag())); ++ ItemStack itemstack = this.getItemRaw(); ++ ++ if (!itemstack.isEmpty()) { ++ compound.put("Item", itemstack.save(new CompoundTag())); + } ++ + } + + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); +- ItemStack itemStack = ItemStack.of(compound.getCompound("Item")); +- this.setItem(itemStack); ++ ItemStack itemstack = ItemStack.of(compound.getCompound("Item")); ++ ++ this.setItem(itemstack); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrowableProjectile.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrowableProjectile.java.patch new file mode 100644 index 0000000000..68d2b040d1 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrowableProjectile.java.patch @@ -0,0 +1,144 @@ +--- a/net/minecraft/world/entity/projectile/ThrowableProjectile.java ++++ b/net/minecraft/world/entity/projectile/ThrowableProjectile.java +@@ -8,96 +8,96 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.TheEndGatewayBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; + + public abstract class ThrowableProjectile extends Projectile { ++ + protected ThrowableProjectile(EntityType entityType, Level level) { + super(entityType, level); + } + +- protected ThrowableProjectile(EntityType entityType, double x, double y, double z, Level level) { +- this(entityType, level); +- this.setPos(x, y, z); ++ protected ThrowableProjectile(EntityType entityType, double x, double d1, double y, Level world) { ++ this(entityType, world); ++ this.setPos(x, d1, y); + } + + protected ThrowableProjectile(EntityType entityType, LivingEntity shooter, Level level) { +- this(entityType, shooter.getX(), shooter.getEyeY() - 0.1F, shooter.getZ(), level); ++ this(entityType, shooter.getX(), shooter.getEyeY() - 0.10000000149011612D, shooter.getZ(), level); + this.setOwner(shooter); + } + + @Override + public boolean shouldRenderAtSqrDistance(double distance) { +- double d = this.getBoundingBox().getSize() * 4.0; +- if (Double.isNaN(d)) { +- d = 4.0; ++ double d1 = this.getBoundingBox().getSize() * 4.0D; ++ ++ if (Double.isNaN(d1)) { ++ d1 = 4.0D; + } + +- d *= 64.0; +- return distance < d * d; ++ d1 *= 64.0D; ++ return distance < d1 * d1; + } + + @Override + public void tick() { + super.tick(); +- HitResult hitResultOnMoveVector = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); ++ HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); + boolean flag = false; +- if (hitResultOnMoveVector.getType() == HitResult.Type.BLOCK) { +- BlockPos blockPos = ((BlockHitResult)hitResultOnMoveVector).getBlockPos(); +- BlockState blockState = this.level().getBlockState(blockPos); +- if (blockState.is(Blocks.NETHER_PORTAL)) { +- this.handleInsidePortal(blockPos); ++ ++ if (movingobjectposition.getType() == HitResult.EnumMovingObjectType.BLOCK) { ++ BlockPos blockposition = ((BlockHitResult) movingobjectposition).getBlockPos(); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); ++ ++ if (iblockdata.is(Blocks.NETHER_PORTAL)) { ++ this.handleInsidePortal(blockposition); + flag = true; +- } else if (blockState.is(Blocks.END_GATEWAY)) { +- BlockEntity blockEntity = this.level().getBlockEntity(blockPos); +- if (blockEntity instanceof TheEndGatewayBlockEntity && TheEndGatewayBlockEntity.canEntityTeleport(this)) { +- TheEndGatewayBlockEntity.teleportEntity(this.level(), blockPos, blockState, this, (TheEndGatewayBlockEntity)blockEntity); ++ } else if (iblockdata.is(Blocks.END_GATEWAY)) { ++ BlockEntity tileentity = this.level().getBlockEntity(blockposition); ++ ++ if (tileentity instanceof TheEndGatewayBlockEntity && TheEndGatewayBlockEntity.canEntityTeleport(this)) { ++ TheEndGatewayBlockEntity.teleportEntity(this.level(), blockposition, iblockdata, this, (TheEndGatewayBlockEntity) tileentity); + } + + flag = true; + } + } + +- if (hitResultOnMoveVector.getType() != HitResult.Type.MISS && !flag) { +- this.onHit(hitResultOnMoveVector); ++ if (movingobjectposition.getType() != HitResult.EnumMovingObjectType.MISS && !flag) { ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + } + + this.checkInsideBlocks(); +- Vec3 deltaMovement = this.getDeltaMovement(); +- double d = this.getX() + deltaMovement.x; +- double d1 = this.getY() + deltaMovement.y; +- double d2 = this.getZ() + deltaMovement.z; ++ Vec3 vec3d = this.getDeltaMovement(); ++ double d0 = this.getX() + vec3d.x; ++ double d1 = this.getY() + vec3d.y; ++ double d2 = this.getZ() + vec3d.z; ++ + this.updateRotation(); +- float f1; ++ float f; ++ + if (this.isInWater()) { +- for (int i = 0; i < 4; i++) { +- float f = 0.25F; +- this.level() +- .addParticle( +- ParticleTypes.BUBBLE, +- d - deltaMovement.x * 0.25, +- d1 - deltaMovement.y * 0.25, +- d2 - deltaMovement.z * 0.25, +- deltaMovement.x, +- deltaMovement.y, +- deltaMovement.z +- ); ++ for (int i = 0; i < 4; ++i) { ++ float f1 = 0.25F; ++ ++ this.level().addParticle(ParticleTypes.BUBBLE, d0 - vec3d.x * 0.25D, d1 - vec3d.y * 0.25D, d2 - vec3d.z * 0.25D, vec3d.x, vec3d.y, vec3d.z); + } + +- f1 = 0.8F; ++ f = 0.8F; + } else { +- f1 = 0.99F; ++ f = 0.99F; + } + +- this.setDeltaMovement(deltaMovement.scale((double)f1)); ++ this.setDeltaMovement(vec3d.scale((double) f)); + if (!this.isNoGravity()) { +- Vec3 deltaMovement1 = this.getDeltaMovement(); +- this.setDeltaMovement(deltaMovement1.x, deltaMovement1.y - (double)this.getGravity(), deltaMovement1.z); ++ Vec3 vec3d1 = this.getDeltaMovement(); ++ ++ this.setDeltaMovement(vec3d1.x, vec3d1.y - (double) this.getGravity(), vec3d1.z); + } + +- this.setPos(d, d1, d2); ++ this.setPos(d0, d1, d2); + } + + protected float getGravity() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrownEgg.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrownEgg.java.patch new file mode 100644 index 0000000000..cf9cf0021b --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrownEgg.java.patch @@ -0,0 +1,135 @@ +--- a/net/minecraft/world/entity/projectile/ThrownEgg.java ++++ b/net/minecraft/world/entity/projectile/ThrownEgg.java +@@ -1,47 +1,45 @@ + package net.minecraft.world.entity.projectile; + +-import net.minecraft.core.particles.ItemParticleOption; +-import net.minecraft.core.particles.ParticleTypes; +-import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.animal.Chicken; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++import net.minecraft.core.particles.ItemParticleOption; ++import net.minecraft.core.particles.ParticleTypes; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.LivingEntity; ++import org.bukkit.entity.Ageable; ++import org.bukkit.entity.EntityType; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerEggThrowEvent; ++// CraftBukkit end + + public class ThrownEgg extends ThrowableItemProjectile { +- public ThrownEgg(EntityType entityType, Level level) { ++ ++ public ThrownEgg(net.minecraft.world.entity.EntityType entityType, Level level) { + super(entityType, level); + } + + public ThrownEgg(Level level, LivingEntity shooter) { +- super(EntityType.EGG, shooter, level); ++ super(net.minecraft.world.entity.EntityType.EGG, shooter, level); + } + +- public ThrownEgg(Level level, double x, double y, double z) { +- super(EntityType.EGG, x, y, z, level); ++ public ThrownEgg(Level level, double x, double d1, double y) { ++ super(net.minecraft.world.entity.EntityType.EGG, x, d1, y, level); + } + + @Override + public void handleEntityEvent(byte id) { + if (id == 3) { +- double d = 0.08; ++ double d0 = 0.08D; + +- for (int i = 0; i < 8; i++) { +- this.level() +- .addParticle( +- new ItemParticleOption(ParticleTypes.ITEM, this.getItem()), +- this.getX(), +- this.getY(), +- this.getZ(), +- ((double)this.random.nextFloat() - 0.5) * 0.08, +- ((double)this.random.nextFloat() - 0.5) * 0.08, +- ((double)this.random.nextFloat() - 0.5) * 0.08 +- ); ++ for (int i = 0; i < 8; ++i) { ++ this.level().addParticle(new ItemParticleOption(ParticleTypes.ITEM, this.getItem()), this.getX(), this.getY(), this.getZ(), ((double) this.random.nextFloat() - 0.5D) * 0.08D, ((double) this.random.nextFloat() - 0.5D) * 0.08D, ((double) this.random.nextFloat() - 0.5D) * 0.08D); + } + } ++ + } + + @Override +@@ -54,25 +52,55 @@ + protected void onHit(HitResult result) { + super.onHit(result); + if (!this.level().isClientSide) { +- if (this.random.nextInt(8) == 0) { +- int i = 1; ++ // CraftBukkit start ++ boolean hatching = this.random.nextInt(8) == 0; ++ if (true) { ++ // CraftBukkit end ++ byte b0 = 1; ++ + if (this.random.nextInt(32) == 0) { +- i = 4; ++ b0 = 4; + } + +- for (int i1 = 0; i1 < i; i1++) { +- Chicken chicken = EntityType.CHICKEN.create(this.level()); +- if (chicken != null) { +- chicken.setAge(-24000); +- chicken.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); +- this.level().addFreshEntity(chicken); ++ // CraftBukkit start ++ EntityType hatchingType = EntityType.CHICKEN; ++ ++ Entity shooter = this.getOwner(); ++ if (!hatching) { ++ b0 = 0; ++ } ++ if (shooter instanceof ServerPlayer) { ++ PlayerEggThrowEvent event = new PlayerEggThrowEvent((Player) shooter.getBukkitEntity(), (org.bukkit.entity.Egg) this.getBukkitEntity(), hatching, b0, hatchingType); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ b0 = event.getNumHatches(); ++ hatching = event.isHatching(); ++ hatchingType = event.getHatchingType(); ++ // If hatching is set to false, ensure child count is 0 ++ if (!hatching) { ++ b0 = 0; + } + } ++ // CraftBukkit end ++ ++ for (int i = 0; i < b0; ++i) { ++ Entity entitychicken = this.level().getWorld().makeEntity(new org.bukkit.Location(this.level().getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F), hatchingType.getEntityClass()); // CraftBukkit ++ ++ if (entitychicken != null) { ++ // CraftBukkit start ++ if (entitychicken.getBukkitEntity() instanceof Ageable) { ++ ((Ageable) entitychicken.getBukkitEntity()).setBaby(); ++ } ++ this.level().addFreshEntity(entitychicken, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); ++ // CraftBukkit end ++ } ++ } + } + +- this.level().broadcastEntityEvent(this, (byte)3); ++ this.level().broadcastEntityEvent(this, (byte) 3); + this.discard(); + } ++ + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrownEnderpearl.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrownEnderpearl.java.patch new file mode 100644 index 0000000000..0bf0250ceb --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrownEnderpearl.java.patch @@ -0,0 +1,140 @@ +--- a/net/minecraft/world/entity/projectile/ThrownEnderpearl.java ++++ b/net/minecraft/world/entity/projectile/ThrownEnderpearl.java +@@ -10,14 +10,22 @@ + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.monster.Endermite; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++// CraftBukkit end + + public class ThrownEnderpearl extends ThrowableItemProjectile { ++ + public ThrownEnderpearl(EntityType entityType, Level level) { + super(entityType, level); + } +@@ -41,66 +49,78 @@ + protected void onHit(HitResult result) { + super.onHit(result); + +- for (int i = 0; i < 32; i++) { +- this.level() +- .addParticle( +- ParticleTypes.PORTAL, +- this.getX(), +- this.getY() + this.random.nextDouble() * 2.0, +- this.getZ(), +- this.random.nextGaussian(), +- 0.0, +- this.random.nextGaussian() +- ); ++ for (int i = 0; i < 32; ++i) { ++ this.level().addParticle(ParticleTypes.PORTAL, this.getX(), this.getY() + this.random.nextDouble() * 2.0D, this.getZ(), this.random.nextGaussian(), 0.0D, this.random.nextGaussian()); + } + + if (!this.level().isClientSide && !this.isRemoved()) { +- Entity owner = this.getOwner(); +- if (owner instanceof ServerPlayer serverPlayer) { +- if (serverPlayer.connection.isAcceptingMessages() && serverPlayer.level() == this.level() && !serverPlayer.isSleeping()) { +- if (this.random.nextFloat() < 0.05F && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { +- Endermite endermite = EntityType.ENDERMITE.create(this.level()); +- if (endermite != null) { +- endermite.moveTo(owner.getX(), owner.getY(), owner.getZ(), owner.getYRot(), owner.getXRot()); +- this.level().addFreshEntity(endermite); ++ Entity entity = this.getOwner(); ++ ++ if (entity instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entity; ++ ++ if (entityplayer.connection.isAcceptingMessages() && entityplayer.level() == this.level() && !entityplayer.isSleeping()) { ++ // CraftBukkit start - Fire PlayerTeleportEvent ++ org.bukkit.craftbukkit.entity.CraftPlayer player = entityplayer.getBukkitEntity(); ++ org.bukkit.Location location = getBukkitEntity().getLocation(); ++ location.setPitch(player.getLocation().getPitch()); ++ location.setYaw(player.getLocation().getYaw()); ++ ++ PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.ENDER_PEARL); ++ Bukkit.getPluginManager().callEvent(teleEvent); ++ ++ if (!teleEvent.isCancelled() && entityplayer.connection.isAcceptingMessages()) { ++ if (this.random.nextFloat() < 0.05F && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { ++ Endermite entityendermite = (Endermite) EntityType.ENDERMITE.create(this.level()); ++ ++ if (entityendermite != null) { ++ entityendermite.moveTo(entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot()); ++ this.level().addFreshEntity(entityendermite, CreatureSpawnEvent.SpawnReason.ENDER_PEARL); ++ } + } +- } + +- if (owner.isPassenger()) { +- serverPlayer.dismountTo(this.getX(), this.getY(), this.getZ()); +- } else { +- owner.teleportTo(this.getX(), this.getY(), this.getZ()); +- } ++ if (entity.isPassenger()) { ++ entity.stopRiding(); ++ } + +- owner.resetFallDistance(); +- owner.hurt(this.damageSources().fall(), 5.0F); +- this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_TELEPORT, SoundSource.PLAYERS); ++ entityplayer.connection.teleport(teleEvent.getTo()); ++ entity.resetFallDistance(); ++ CraftEventFactory.entityDamage = this; ++ entity.hurt(this.damageSources().fall(), 5.0F); ++ CraftEventFactory.entityDamage = null; ++ } ++ // CraftBukkit end ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_TELEPORT, SoundSource.PLAYERS); + } +- } else if (owner != null) { +- owner.teleportTo(this.getX(), this.getY(), this.getZ()); +- owner.resetFallDistance(); ++ } else if (entity != null) { ++ entity.teleportTo(this.getX(), this.getY(), this.getZ()); ++ entity.resetFallDistance(); + } + + this.discard(); + } ++ + } + + @Override + public void tick() { +- Entity owner = this.getOwner(); +- if (owner instanceof ServerPlayer && !owner.isAlive() && this.level().getGameRules().getBoolean(GameRules.RULE_ENDER_PEARLS_VANISH_ON_DEATH)) { ++ Entity entity = this.getOwner(); ++ ++ if (entity instanceof ServerPlayer && !entity.isAlive() && this.level().getGameRules().getBoolean(GameRules.RULE_ENDER_PEARLS_VANISH_ON_DEATH)) { + this.discard(); + } else { + super.tick(); + } ++ + } + + @Nullable + @Override + public Entity changeDimension(ServerLevel server) { +- Entity owner = this.getOwner(); +- if (owner != null && owner.level().dimension() != server.dimension()) { +- this.setOwner(null); ++ Entity entity = this.getOwner(); ++ ++ if (entity != null && server != null && entity.level().dimension() != server.dimension()) { // CraftBukkit - SPIGOT-6113 ++ this.setOwner((Entity) null); + } + + return super.changeDimension(server); diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java.patch new file mode 100644 index 0000000000..df7a925c0b --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java.patch @@ -0,0 +1,45 @@ +--- a/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java ++++ b/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java +@@ -12,6 +12,7 @@ + import net.minecraft.world.phys.HitResult; + + public class ThrownExperienceBottle extends ThrowableItemProjectile { ++ + public ThrownExperienceBottle(EntityType entityType, Level level) { + super(entityType, level); + } +@@ -20,8 +21,8 @@ + super(EntityType.EXPERIENCE_BOTTLE, shooter, level); + } + +- public ThrownExperienceBottle(Level level, double x, double y, double z) { +- super(EntityType.EXPERIENCE_BOTTLE, x, y, z, level); ++ public ThrownExperienceBottle(Level level, double x, double d1, double y) { ++ super(EntityType.EXPERIENCE_BOTTLE, x, d1, y, level); + } + + @Override +@@ -38,10 +39,21 @@ + protected void onHit(HitResult result) { + super.onHit(result); + if (this.level() instanceof ServerLevel) { +- this.level().levelEvent(2002, this.blockPosition(), PotionUtils.getColor(Potions.WATER)); ++ // CraftBukkit - moved to after event ++ // this.level().levelEvent(2002, this.blockPosition(), PotionUtil.getColor(Potions.WATER)); + int i = 3 + this.level().random.nextInt(5) + this.level().random.nextInt(5); +- ExperienceOrb.award((ServerLevel)this.level(), this.position(), i); ++ ++ // CraftBukkit start ++ org.bukkit.event.entity.ExpBottleEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExpBottleEvent(this, result, i); ++ i = event.getExperience(); ++ if (event.getShowEffect()) { ++ this.level().levelEvent(2002, this.blockPosition(), PotionUtils.getColor(Potions.WATER)); ++ } ++ // CraftBukkit end ++ ++ ExperienceOrb.award((ServerLevel) this.level(), this.position(), i); + this.discard(); + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrownPotion.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrownPotion.java.patch new file mode 100644 index 0000000000..b61b8d9855 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrownPotion.java.patch @@ -0,0 +1,381 @@ +--- a/net/minecraft/world/entity/projectile/ThrownPotion.java ++++ b/net/minecraft/world/entity/projectile/ThrownPotion.java +@@ -1,19 +1,21 @@ + package net.minecraft.world.entity.projectile; + ++import java.util.Iterator; + import java.util.List; + import java.util.function.Predicate; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.tags.BlockTags; + import net.minecraft.world.effect.MobEffect; + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.entity.AreaEffectCloud; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.animal.axolotl.Axolotl; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +@@ -22,28 +24,40 @@ + import net.minecraft.world.item.alchemy.Potions; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.AbstractCandleBlock; +-import net.minecraft.world.level.block.CampfireBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++// CraftBukkit start ++import java.util.HashMap; ++import java.util.Map; ++import net.minecraft.world.effect.MobEffects; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.CampfireBlock; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.entity.LivingEntity; ++// CraftBukkit end + + public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplier { +- public static final double SPLASH_RANGE = 4.0; +- private static final double SPLASH_RANGE_SQ = 16.0; +- public static final Predicate WATER_SENSITIVE_OR_ON_FIRE = livingEntity -> livingEntity.isSensitiveToWater() || livingEntity.isOnFire(); + ++ public static final double SPLASH_RANGE = 4.0D; ++ private static final double SPLASH_RANGE_SQ = 16.0D; ++ public static final Predicate WATER_SENSITIVE_OR_ON_FIRE = (entityliving) -> { ++ return entityliving.isSensitiveToWater() || entityliving.isOnFire(); ++ }; ++ + public ThrownPotion(EntityType entityType, Level level) { + super(entityType, level); + } + +- public ThrownPotion(Level level, LivingEntity shooter) { ++ public ThrownPotion(Level level, net.minecraft.world.entity.LivingEntity shooter) { + super(EntityType.POTION, shooter, level); + } + +- public ThrownPotion(Level level, double x, double y, double z) { +- super(EntityType.POTION, x, y, z, level); ++ public ThrownPotion(Level level, double x, double d1, double y) { ++ super(EntityType.POTION, x, d1, y, level); + } + + @Override +@@ -60,21 +74,26 @@ + protected void onHitBlock(BlockHitResult result) { + super.onHitBlock(result); + if (!this.level().isClientSide) { +- ItemStack item = this.getItem(); +- Potion potion = PotionUtils.getPotion(item); +- List mobEffects = PotionUtils.getMobEffects(item); +- boolean flag = potion == Potions.WATER && mobEffects.isEmpty(); +- Direction direction = result.getDirection(); +- BlockPos blockPos = result.getBlockPos(); +- BlockPos blockPos1 = blockPos.relative(direction); ++ ItemStack itemstack = this.getItem(); ++ Potion potionregistry = PotionUtils.getPotion(itemstack); ++ List list = PotionUtils.getMobEffects(itemstack); ++ boolean flag = potionregistry == Potions.WATER && list.isEmpty(); ++ Direction enumdirection = result.getDirection(); ++ BlockPos blockposition = result.getBlockPos(); ++ BlockPos blockposition1 = blockposition.relative(enumdirection); ++ + if (flag) { +- this.dowseFire(blockPos1); +- this.dowseFire(blockPos1.relative(direction.getOpposite())); ++ this.dowseFire(blockposition1); ++ this.dowseFire(blockposition1.relative(enumdirection.getOpposite())); ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction direction1 : Direction.Plane.HORIZONTAL) { +- this.dowseFire(blockPos1.relative(direction1)); ++ while (iterator.hasNext()) { ++ Direction enumdirection1 = (Direction) iterator.next(); ++ ++ this.dowseFire(blockposition1.relative(enumdirection1)); + } + } ++ + } + } + +@@ -82,123 +101,199 @@ + protected void onHit(HitResult result) { + super.onHit(result); + if (!this.level().isClientSide) { +- ItemStack item = this.getItem(); +- Potion potion = PotionUtils.getPotion(item); +- List mobEffects = PotionUtils.getMobEffects(item); +- boolean flag = potion == Potions.WATER && mobEffects.isEmpty(); ++ ItemStack itemstack = this.getItem(); ++ Potion potionregistry = PotionUtils.getPotion(itemstack); ++ List list = PotionUtils.getMobEffects(itemstack); ++ boolean flag = potionregistry == Potions.WATER && list.isEmpty(); ++ + if (flag) { + this.applyWater(); +- } else if (!mobEffects.isEmpty()) { ++ } else if (true || !list.isEmpty()) { // CraftBukkit - Call event even if no effects to apply + if (this.isLingering()) { +- this.makeAreaOfEffectCloud(item, potion); ++ this.makeAreaOfEffectCloud(itemstack, potionregistry, result); // CraftBukkit - Pass MovingObjectPosition + } else { +- this.applySplash(mobEffects, result.getType() == HitResult.Type.ENTITY ? ((EntityHitResult)result).getEntity() : null); ++ this.applySplash(list, result.getType() == HitResult.EnumMovingObjectType.ENTITY ? ((EntityHitResult) result).getEntity() : null, result); // CraftBukkit - Pass MovingObjectPosition + } + } + +- int i = potion.hasInstantEffects() ? 2007 : 2002; +- this.level().levelEvent(i, this.blockPosition(), PotionUtils.getColor(item)); ++ int i = potionregistry.hasInstantEffects() ? 2007 : 2002; ++ ++ this.level().levelEvent(i, this.blockPosition(), PotionUtils.getColor(itemstack)); + this.discard(); + } + } + + private void applyWater() { +- AABB aABB = this.getBoundingBox().inflate(4.0, 2.0, 4.0); ++ AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D); ++ List list = this.level().getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb, ThrownPotion.WATER_SENSITIVE_OR_ON_FIRE); ++ Iterator iterator = list.iterator(); + +- for (LivingEntity livingEntity : this.level().getEntitiesOfClass(LivingEntity.class, aABB, WATER_SENSITIVE_OR_ON_FIRE)) { +- double d = this.distanceToSqr(livingEntity); +- if (d < 16.0) { +- if (livingEntity.isSensitiveToWater()) { +- livingEntity.hurt(this.damageSources().indirectMagic(this, this.getOwner()), 1.0F); ++ while (iterator.hasNext()) { ++ net.minecraft.world.entity.LivingEntity entityliving = (net.minecraft.world.entity.LivingEntity) iterator.next(); ++ double d0 = this.distanceToSqr((Entity) entityliving); ++ ++ if (d0 < 16.0D) { ++ if (entityliving.isSensitiveToWater()) { ++ entityliving.hurt(this.damageSources().indirectMagic(this, this.getOwner()), 1.0F); + } + +- if (livingEntity.isOnFire() && livingEntity.isAlive()) { +- livingEntity.extinguishFire(); ++ if (entityliving.isOnFire() && entityliving.isAlive()) { ++ entityliving.extinguishFire(); + } + } + } + +- for (Axolotl axolotl : this.level().getEntitiesOfClass(Axolotl.class, aABB)) { ++ List list1 = this.level().getEntitiesOfClass(Axolotl.class, axisalignedbb); ++ Iterator iterator1 = list1.iterator(); ++ ++ while (iterator1.hasNext()) { ++ Axolotl axolotl = (Axolotl) iterator1.next(); ++ + axolotl.rehydrate(); + } ++ + } + +- private void applySplash(List effectInstances, @Nullable Entity target) { +- AABB aABB = this.getBoundingBox().inflate(4.0, 2.0, 4.0); +- List entitiesOfClass = this.level().getEntitiesOfClass(LivingEntity.class, aABB); +- if (!entitiesOfClass.isEmpty()) { +- Entity effectSource = this.getEffectSource(); ++ private void applySplash(List list, @Nullable Entity entity, HitResult position) { // CraftBukkit - Pass MovingObjectPosition ++ AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D); ++ List list1 = this.level().getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb); ++ Map affected = new HashMap(); // CraftBukkit + +- for (LivingEntity livingEntity : entitiesOfClass) { +- if (livingEntity.isAffectedByPotions()) { +- double d = this.distanceToSqr(livingEntity); +- if (d < 16.0) { ++ if (!list1.isEmpty()) { ++ Entity entity1 = this.getEffectSource(); ++ Iterator iterator = list1.iterator(); ++ ++ while (iterator.hasNext()) { ++ net.minecraft.world.entity.LivingEntity entityliving = (net.minecraft.world.entity.LivingEntity) iterator.next(); ++ ++ if (entityliving.isAffectedByPotions()) { ++ double d0 = this.distanceToSqr((Entity) entityliving); ++ ++ if (d0 < 16.0D) { + double d1; +- if (livingEntity == target) { +- d1 = 1.0; ++ ++ if (entityliving == entity) { ++ d1 = 1.0D; + } else { +- d1 = 1.0 - Math.sqrt(d) / 4.0; ++ d1 = 1.0D - Math.sqrt(d0) / 4.0D; + } + +- for (MobEffectInstance mobEffectInstance : effectInstances) { +- MobEffect effect = mobEffectInstance.getEffect(); +- if (effect.isInstantenous()) { +- effect.applyInstantenousEffect(this, this.getOwner(), livingEntity, mobEffectInstance.getAmplifier(), d1); +- } else { +- int i = mobEffectInstance.mapDuration(i1 -> (int)(d1 * (double)i1 + 0.5)); +- MobEffectInstance mobEffectInstance1 = new MobEffectInstance( +- effect, i, mobEffectInstance.getAmplifier(), mobEffectInstance.isAmbient(), mobEffectInstance.isVisible() +- ); +- if (!mobEffectInstance1.endsWithin(20)) { +- livingEntity.addEffect(mobEffectInstance1, effectSource); +- } +- } ++ // CraftBukkit start ++ affected.put((LivingEntity) entityliving.getBukkitEntity(), d1); ++ } ++ } ++ } ++ } ++ ++ org.bukkit.event.entity.PotionSplashEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPotionSplashEvent(this, position, affected); ++ if (!event.isCancelled() && list != null && !list.isEmpty()) { // do not process effects if there are no effects to process ++ Entity entity1 = this.getEffectSource(); ++ for (LivingEntity victim : event.getAffectedEntities()) { ++ if (!(victim instanceof CraftLivingEntity)) { ++ continue; ++ } ++ ++ net.minecraft.world.entity.LivingEntity entityliving = ((CraftLivingEntity) victim).getHandle(); ++ double d1 = event.getIntensity(victim); ++ // CraftBukkit end ++ ++ Iterator iterator1 = list.iterator(); ++ ++ while (iterator1.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator1.next(); ++ MobEffect mobeffectlist = mobeffect.getEffect(); ++ // CraftBukkit start - Abide by PVP settings - for players only! ++ if (!this.level().pvpMode && this.getOwner() instanceof ServerPlayer && entityliving instanceof ServerPlayer && entityliving != this.getOwner()) { ++ if (mobeffectlist == MobEffects.MOVEMENT_SLOWDOWN || mobeffectlist == MobEffects.DIG_SLOWDOWN || mobeffectlist == MobEffects.HARM || mobeffectlist == MobEffects.BLINDNESS ++ || mobeffectlist == MobEffects.HUNGER || mobeffectlist == MobEffects.WEAKNESS || mobeffectlist == MobEffects.POISON) { ++ continue; + } + } ++ // CraftBukkit end ++ ++ if (mobeffectlist.isInstantenous()) { ++ mobeffectlist.applyInstantenousEffect(this, this.getOwner(), entityliving, mobeffect.getAmplifier(), d1); ++ } else { ++ int i = mobeffect.mapDuration((j) -> { ++ return (int) (d1 * (double) j + 0.5D); ++ }); ++ MobEffectInstance mobeffect1 = new MobEffectInstance(mobeffectlist, i, mobeffect.getAmplifier(), mobeffect.isAmbient(), mobeffect.isVisible()); ++ ++ if (!mobeffect1.endsWithin(20)) { ++ entityliving.addEffect(mobeffect1, entity1, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_SPLASH); // CraftBukkit ++ } ++ } + } + } + } ++ + } + +- private void makeAreaOfEffectCloud(ItemStack stack, Potion potion) { +- AreaEffectCloud areaEffectCloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); +- Entity owner = this.getOwner(); +- if (owner instanceof LivingEntity) { +- areaEffectCloud.setOwner((LivingEntity)owner); ++ private void makeAreaOfEffectCloud(ItemStack itemstack, Potion potionregistry, HitResult position) { // CraftBukkit - Pass MovingObjectPosition ++ AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); ++ Entity entity = this.getOwner(); ++ ++ if (entity instanceof net.minecraft.world.entity.LivingEntity) { ++ entityareaeffectcloud.setOwner((net.minecraft.world.entity.LivingEntity) entity); + } + +- areaEffectCloud.setRadius(3.0F); +- areaEffectCloud.setRadiusOnUse(-0.5F); +- areaEffectCloud.setWaitTime(10); +- areaEffectCloud.setRadiusPerTick(-areaEffectCloud.getRadius() / (float)areaEffectCloud.getDuration()); +- areaEffectCloud.setPotion(potion); ++ entityareaeffectcloud.setRadius(3.0F); ++ entityareaeffectcloud.setRadiusOnUse(-0.5F); ++ entityareaeffectcloud.setWaitTime(10); ++ entityareaeffectcloud.setRadiusPerTick(-entityareaeffectcloud.getRadius() / (float) entityareaeffectcloud.getDuration()); ++ entityareaeffectcloud.setPotion(potionregistry); ++ Iterator iterator = PotionUtils.getCustomEffects(itemstack).iterator(); + +- for (MobEffectInstance mobEffectInstance : PotionUtils.getCustomEffects(stack)) { +- areaEffectCloud.addEffect(new MobEffectInstance(mobEffectInstance)); ++ while (iterator.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); ++ ++ entityareaeffectcloud.addEffect(new MobEffectInstance(mobeffect)); + } + +- CompoundTag tag = stack.getTag(); +- if (tag != null && tag.contains("CustomPotionColor", 99)) { +- areaEffectCloud.setFixedColor(tag.getInt("CustomPotionColor")); ++ CompoundTag nbttagcompound = itemstack.getTag(); ++ ++ if (nbttagcompound != null && nbttagcompound.contains("CustomPotionColor", 99)) { ++ entityareaeffectcloud.setFixedColor(nbttagcompound.getInt("CustomPotionColor")); + } + +- this.level().addFreshEntity(areaEffectCloud); ++ // CraftBukkit start ++ org.bukkit.event.entity.LingeringPotionSplashEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callLingeringPotionSplashEvent(this, position, entityareaeffectcloud); ++ if (!(event.isCancelled() || entityareaeffectcloud.isRemoved())) { ++ this.level().addFreshEntity(entityareaeffectcloud); ++ } else { ++ entityareaeffectcloud.discard(); ++ } ++ // CraftBukkit end + } + +- private boolean isLingering() { ++ public boolean isLingering() { + return this.getItem().is(Items.LINGERING_POTION); + } + + private void dowseFire(BlockPos pos) { +- BlockState blockState = this.level().getBlockState(pos); +- if (blockState.is(BlockTags.FIRE)) { +- this.level().destroyBlock(pos, false, this); +- } else if (AbstractCandleBlock.isLit(blockState)) { +- AbstractCandleBlock.extinguish(null, blockState, this.level(), pos); +- } else if (CampfireBlock.isLitCampfire(blockState)) { +- this.level().levelEvent(null, 1009, pos, 0); +- CampfireBlock.dowse(this.getOwner(), this.level(), pos, blockState); +- this.level().setBlockAndUpdate(pos, blockState.setValue(CampfireBlock.LIT, Boolean.valueOf(false))); ++ IBlockData iblockdata = this.level().getBlockState(pos); ++ ++ if (iblockdata.is(BlockTags.FIRE)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityChangeBlockEvent(this, pos, Blocks.AIR.defaultBlockState())) { ++ this.level().destroyBlock(pos, false, this); ++ } ++ // CraftBukkit end ++ } else if (AbstractCandleBlock.isLit(iblockdata)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityChangeBlockEvent(this, pos, iblockdata.setValue(AbstractCandleBlock.LIT, false))) { ++ AbstractCandleBlock.extinguish((Player) null, iblockdata, this.level(), pos); ++ } ++ // CraftBukkit end ++ } else if (CampfireBlock.isLitCampfire(iblockdata)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityChangeBlockEvent(this, pos, iblockdata.setValue(CampfireBlock.LIT, false))) { ++ this.level().levelEvent((Player) null, 1009, pos, 0); ++ CampfireBlock.dowse(this.getOwner(), this.level(), pos, iblockdata); ++ this.level().setBlockAndUpdate(pos, (IBlockData) iblockdata.setValue(CampfireBlock.LIT, false)); ++ } ++ // CraftBukkit end + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrownTrident.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrownTrident.java.patch new file mode 100644 index 0000000000..6f6538c6eb --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/ThrownTrident.java.patch @@ -0,0 +1,215 @@ +--- a/net/minecraft/world/entity/projectile/ThrownTrident.java ++++ b/net/minecraft/world/entity/projectile/ThrownTrident.java +@@ -25,6 +25,7 @@ + import net.minecraft.world.phys.Vec3; + + public class ThrownTrident extends AbstractArrow { ++ + private static final EntityDataAccessor ID_LOYALTY = SynchedEntityData.defineId(ThrownTrident.class, EntityDataSerializers.BYTE); + private static final EntityDataAccessor ID_FOIL = SynchedEntityData.defineId(ThrownTrident.class, EntityDataSerializers.BOOLEAN); + private static final ItemStack DEFAULT_ARROW_STACK = new ItemStack(Items.TRIDENT); +@@ -32,20 +33,20 @@ + public int clientSideReturnTridentTickCount; + + public ThrownTrident(EntityType entityType, Level level) { +- super(entityType, level, DEFAULT_ARROW_STACK); ++ super(entityType, level, ThrownTrident.DEFAULT_ARROW_STACK); + } + + public ThrownTrident(Level level, LivingEntity shooter, ItemStack stack) { + super(EntityType.TRIDENT, shooter, level, stack); +- this.entityData.set(ID_LOYALTY, (byte)EnchantmentHelper.getLoyalty(stack)); +- this.entityData.set(ID_FOIL, stack.hasFoil()); ++ this.entityData.set(ThrownTrident.ID_LOYALTY, (byte) EnchantmentHelper.getLoyalty(stack)); ++ this.entityData.set(ThrownTrident.ID_FOIL, stack.hasFoil()); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(ID_LOYALTY, (byte)0); +- this.entityData.define(ID_FOIL, false); ++ this.entityData.define(ThrownTrident.ID_LOYALTY, (byte) 0); ++ this.entityData.define(ThrownTrident.ID_FOIL, false); + } + + @Override +@@ -54,9 +55,10 @@ + this.dealtDamage = true; + } + +- Entity owner = this.getOwner(); +- int i = this.entityData.get(ID_LOYALTY); +- if (i > 0 && (this.dealtDamage || this.isNoPhysics()) && owner != null) { ++ Entity entity = this.getOwner(); ++ byte b0 = (Byte) this.entityData.get(ThrownTrident.ID_LOYALTY); ++ ++ if (b0 > 0 && (this.dealtDamage || this.isNoPhysics()) && entity != null) { + if (!this.isAcceptibleReturnOwner()) { + if (!this.level().isClientSide && this.pickup == AbstractArrow.Pickup.ALLOWED) { + this.spawnAtLocation(this.getPickupItem(), 0.1F); +@@ -65,19 +67,21 @@ + this.discard(); + } else { + this.setNoPhysics(true); +- Vec3 vec3 = owner.getEyePosition().subtract(this.position()); +- this.setPosRaw(this.getX(), this.getY() + vec3.y * 0.015 * (double)i, this.getZ()); ++ Vec3 vec3d = entity.getEyePosition().subtract(this.position()); ++ ++ this.setPosRaw(this.getX(), this.getY() + vec3d.y * 0.015D * (double) b0, this.getZ()); + if (this.level().isClientSide) { + this.yOld = this.getY(); + } + +- double d = 0.05 * (double)i; +- this.setDeltaMovement(this.getDeltaMovement().scale(0.95).add(vec3.normalize().scale(d))); ++ double d0 = 0.05D * (double) b0; ++ ++ this.setDeltaMovement(this.getDeltaMovement().scale(0.95D).add(vec3d.normalize().scale(d0))); + if (this.clientSideReturnTridentTickCount == 0) { + this.playSound(SoundEvents.TRIDENT_RETURN, 10.0F, 1.0F); + } + +- this.clientSideReturnTridentTickCount++; ++ ++this.clientSideReturnTridentTickCount; + } + } + +@@ -85,12 +89,13 @@ + } + + private boolean isAcceptibleReturnOwner() { +- Entity owner = this.getOwner(); +- return owner != null && owner.isAlive() && (!(owner instanceof ServerPlayer) || !owner.isSpectator()); ++ Entity entity = this.getOwner(); ++ ++ return entity != null && entity.isAlive() ? !(entity instanceof ServerPlayer) || !entity.isSpectator() : false; + } + + public boolean isFoil() { +- return this.entityData.get(ID_FOIL); ++ return (Boolean) this.entityData.get(ThrownTrident.ID_FOIL); + } + + @Nullable +@@ -103,49 +108,59 @@ + protected void onHitEntity(EntityHitResult result) { + Entity entity = result.getEntity(); + float f = 8.0F; +- if (entity instanceof LivingEntity livingEntity) { +- f += EnchantmentHelper.getDamageBonus(this.getPickupItemStackOrigin(), livingEntity.getMobType()); ++ ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ f += EnchantmentHelper.getDamageBonus(this.getPickupItemStackOrigin(), entityliving.getMobType()); + } + +- Entity owner = this.getOwner(); +- DamageSource damageSource = this.damageSources().trident(this, (Entity)(owner == null ? this : owner)); ++ Entity entity1 = this.getOwner(); ++ DamageSource damagesource = this.damageSources().trident(this, (Entity) (entity1 == null ? this : entity1)); ++ + this.dealtDamage = true; +- SoundEvent soundEvent = SoundEvents.TRIDENT_HIT; +- if (entity.hurt(damageSource, f)) { ++ SoundEvent soundeffect = SoundEvents.TRIDENT_HIT; ++ ++ if (entity.hurt(damagesource, f)) { + if (entity.getType() == EntityType.ENDERMAN) { + return; + } + +- if (entity instanceof LivingEntity livingEntity1) { +- if (owner instanceof LivingEntity) { +- EnchantmentHelper.doPostHurtEffects(livingEntity1, owner); +- EnchantmentHelper.doPostDamageEffects((LivingEntity)owner, livingEntity1); ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving1 = (LivingEntity) entity; ++ ++ if (entity1 instanceof LivingEntity) { ++ EnchantmentHelper.doPostHurtEffects(entityliving1, entity1); ++ EnchantmentHelper.doPostDamageEffects((LivingEntity) entity1, entityliving1); + } + +- this.doPostHurtEffects(livingEntity1); ++ this.doPostHurtEffects(entityliving1); + } + } else if (entity.getType().is(EntityTypeTags.DEFLECTS_TRIDENTS)) { + this.deflect(); + return; + } + +- this.setDeltaMovement(this.getDeltaMovement().multiply(-0.01, -0.1, -0.01)); ++ this.setDeltaMovement(this.getDeltaMovement().multiply(-0.01D, -0.1D, -0.01D)); + float f1 = 1.0F; ++ + if (this.level() instanceof ServerLevel && this.level().isThundering() && this.isChanneling()) { +- BlockPos blockPos = entity.blockPosition(); +- if (this.level().canSeeSky(blockPos)) { +- LightningBolt lightningBolt = EntityType.LIGHTNING_BOLT.create(this.level()); +- if (lightningBolt != null) { +- lightningBolt.moveTo(Vec3.atBottomCenterOf(blockPos)); +- lightningBolt.setCause(owner instanceof ServerPlayer ? (ServerPlayer)owner : null); +- this.level().addFreshEntity(lightningBolt); +- soundEvent = SoundEvents.TRIDENT_THUNDER; ++ BlockPos blockposition = entity.blockPosition(); ++ ++ if (this.level().canSeeSky(blockposition)) { ++ LightningBolt entitylightning = (LightningBolt) EntityType.LIGHTNING_BOLT.create(this.level()); ++ ++ if (entitylightning != null) { ++ entitylightning.moveTo(Vec3.atBottomCenterOf(blockposition)); ++ entitylightning.setCause(entity1 instanceof ServerPlayer ? (ServerPlayer) entity1 : null); ++ ((ServerLevel) this.level()).strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.TRIDENT); // CraftBukkit ++ soundeffect = SoundEvents.TRIDENT_THUNDER; + f1 = 5.0F; + } + } + } + +- this.playSound(soundEvent, f1, 1.0F); ++ this.playSound(soundeffect, f1, 1.0F); + } + + public boolean isChanneling() { +@@ -167,13 +182,14 @@ + if (this.ownedBy(entity) || this.getOwner() == null) { + super.playerTouch(entity); + } ++ + } + + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); + this.dealtDamage = compound.getBoolean("DealtDamage"); +- this.entityData.set(ID_LOYALTY, (byte)EnchantmentHelper.getLoyalty(this.getPickupItemStackOrigin())); ++ this.entityData.set(ThrownTrident.ID_LOYALTY, (byte) EnchantmentHelper.getLoyalty(this.getPickupItemStackOrigin())); + } + + @Override +@@ -184,10 +200,12 @@ + + @Override + public void tickDespawn() { +- int i = this.entityData.get(ID_LOYALTY); +- if (this.pickup != AbstractArrow.Pickup.ALLOWED || i <= 0) { ++ byte b0 = (Byte) this.entityData.get(ThrownTrident.ID_LOYALTY); ++ ++ if (this.pickup != AbstractArrow.Pickup.ALLOWED || b0 <= 0) { + super.tickDespawn(); + } ++ + } + + @Override +@@ -196,7 +214,7 @@ + } + + @Override +- public boolean shouldRender(double x, double y, double z) { ++ public boolean shouldRender(double x, double d1, double y) { + return true; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/WindCharge.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/WindCharge.java.patch new file mode 100644 index 0000000000..38a6ddfa83 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/WindCharge.java.patch @@ -0,0 +1,134 @@ +--- a/net/minecraft/world/entity/projectile/WindCharge.java ++++ b/net/minecraft/world/entity/projectile/WindCharge.java +@@ -4,11 +4,13 @@ + import net.minecraft.core.particles.ParticleOptions; + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.sounds.SoundEvents; ++import net.minecraft.world.damagesource.DamageSource; ++import net.minecraft.world.damagesource.DamageSources; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.monster.breeze.Breeze; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.ClipContext; +@@ -21,14 +23,15 @@ + import net.minecraft.world.phys.HitResult; + + public class WindCharge extends AbstractHurtingProjectile implements ItemSupplier { +- public static final WindCharge.WindChargeExplosionDamageCalculator EXPLOSION_DAMAGE_CALCULATOR = new WindCharge.WindChargeExplosionDamageCalculator(); + ++ public static final WindCharge.a EXPLOSION_DAMAGE_CALCULATOR = new WindCharge.a(); ++ + public WindCharge(EntityType entityType, Level level) { + super(entityType, level); + } + +- public WindCharge(EntityType entityType, Breeze breeze, Level level) { +- super(entityType, breeze.getX(), breeze.getSnoutYPosition(), breeze.getZ(), level); ++ public WindCharge(EntityType entitytypes, Breeze breeze, Level world) { ++ super(entitytypes, breeze.getX(), breeze.getSnoutYPosition(), breeze.getZ(), world); + this.setOwner(breeze); + } + +@@ -37,56 +40,49 @@ + float f = this.getType().getDimensions().width / 2.0F; + float f1 = this.getType().getDimensions().height; + float f2 = 0.15F; +- return new AABB( +- this.position().x - (double)f, +- this.position().y - 0.15F, +- this.position().z - (double)f, +- this.position().x + (double)f, +- this.position().y - 0.15F + (double)f1, +- this.position().z + (double)f +- ); ++ ++ return new AABB(this.position().x - (double) f, this.position().y - 0.15000000596046448D, this.position().z - (double) f, this.position().x + (double) f, this.position().y - 0.15000000596046448D + (double) f1, this.position().z + (double) f); + } + + @Override +- protected float getEyeHeight(Pose pose, EntityDimensions dimensions) { ++ protected float getEyeHeight(EntityPose pose, EntityDimensions dimensions) { + return 0.0F; + } + + @Override + public boolean canCollideWith(Entity entity) { +- return !(entity instanceof WindCharge) && super.canCollideWith(entity); ++ return entity instanceof WindCharge ? false : super.canCollideWith(entity); + } + + @Override + protected boolean canHitEntity(Entity target) { +- return !(target instanceof WindCharge) && super.canHitEntity(target); ++ return target instanceof WindCharge ? false : super.canHitEntity(target); + } + + @Override + protected void onHitEntity(EntityHitResult result) { + super.onHitEntity(result); + if (!this.level().isClientSide) { +- result.getEntity().hurt(this.damageSources().mobProjectile(this, this.getOwner() instanceof LivingEntity livingEntity ? livingEntity : null), 1.0F); ++ Entity entity = result.getEntity(); ++ DamageSources damagesources = this.damageSources(); ++ Entity entity1 = this.getOwner(); ++ LivingEntity entityliving; ++ ++ if (entity1 instanceof LivingEntity) { ++ LivingEntity entityliving1 = (LivingEntity) entity1; ++ ++ entityliving = entityliving1; ++ } else { ++ entityliving = null; ++ } ++ ++ entity.hurt(damagesources.mobProjectile(this, entityliving), 1.0F); + this.explode(); + } + } + +- private void explode() { +- this.level() +- .explode( +- this, +- null, +- EXPLOSION_DAMAGE_CALCULATOR, +- this.getX(), +- this.getY(), +- this.getZ(), +- (float)(3.0 + this.random.nextDouble()), +- false, +- Level.ExplosionInteraction.BLOW, +- ParticleTypes.GUST, +- ParticleTypes.GUST_EMITTER, +- SoundEvents.WIND_BURST +- ); ++ public void explode() { // PAIL private -> public ++ this.level().explode(this, (DamageSource) null, WindCharge.EXPLOSION_DAMAGE_CALCULATOR, this.getX(), this.getY(), this.getZ(), (float) (3.0D + this.random.nextDouble()), false, Level.a.BLOW, ParticleTypes.GUST, ParticleTypes.GUST_EMITTER, SoundEvents.WIND_BURST); + } + + @Override +@@ -102,6 +98,7 @@ + if (!this.level().isClientSide) { + this.discard(); + } ++ + } + + @Override +@@ -135,7 +132,10 @@ + return ClipContext.Block.OUTLINE; + } + +- public static final class WindChargeExplosionDamageCalculator extends ExplosionDamageCalculator { ++ public static final class a extends ExplosionDamageCalculator { ++ ++ public a() {} ++ + @Override + public boolean shouldDamageEntity(Explosion explosion, Entity entity) { + return false; diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/WitherSkull.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/WitherSkull.java.patch new file mode 100644 index 0000000000..1ffc1a5de3 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/projectile/WitherSkull.java.patch @@ -0,0 +1,130 @@ +--- a/net/minecraft/world/entity/projectile/WitherSkull.java ++++ b/net/minecraft/world/entity/projectile/WitherSkull.java +@@ -16,20 +16,24 @@ + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Explosion; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++// CraftBukkit start ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end + + public class WitherSkull extends AbstractHurtingProjectile { ++ + private static final EntityDataAccessor DATA_DANGEROUS = SynchedEntityData.defineId(WitherSkull.class, EntityDataSerializers.BOOLEAN); + + public WitherSkull(EntityType entityType, Level level) { + super(entityType, level); + } + +- public WitherSkull(Level level, LivingEntity shooter, double offsetX, double offsetY, double offsetZ) { +- super(EntityType.WITHER_SKULL, shooter, offsetX, offsetY, offsetZ, level); ++ public WitherSkull(Level level, LivingEntity shooter, double offsetX, double d1, double offsetY) { ++ super(EntityType.WITHER_SKULL, shooter, offsetX, d1, offsetY, level); + } + + @Override +@@ -43,9 +47,7 @@ + } + + @Override +- public float getBlockExplosionResistance( +- Explosion explosion, BlockGetter level, BlockPos pos, BlockState blockState, FluidState fluidState, float explosionPower +- ) { ++ public float getBlockExplosionResistance(Explosion explosion, BlockGetter level, BlockPos pos, IBlockData blockState, FluidState fluidState, float explosionPower) { + return this.isDangerous() && WitherBoss.canDestroy(blockState) ? Math.min(0.8F, explosionPower) : explosionPower; + } + +@@ -54,32 +56,39 @@ + super.onHitEntity(result); + if (!this.level().isClientSide) { + Entity entity = result.getEntity(); ++ Entity entity1 = this.getOwner(); ++ LivingEntity entityliving; + boolean flag; +- if (this.getOwner() instanceof LivingEntity livingEntity) { +- flag = entity.hurt(this.damageSources().witherSkull(this, livingEntity), 8.0F); ++ ++ if (entity1 instanceof LivingEntity) { ++ entityliving = (LivingEntity) entity1; ++ flag = entity.hurt(this.damageSources().witherSkull(this, entityliving), 8.0F); + if (flag) { + if (entity.isAlive()) { +- this.doEnchantDamageEffects(livingEntity, entity); ++ this.doEnchantDamageEffects(entityliving, entity); + } else { +- livingEntity.heal(5.0F); ++ entityliving.heal(5.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.WITHER); // CraftBukkit + } + } + } else { + flag = entity.hurt(this.damageSources().magic(), 5.0F); + } + +- if (flag && entity instanceof LivingEntity livingEntityx) { +- int i = 0; ++ if (flag && entity instanceof LivingEntity) { ++ entityliving = (LivingEntity) entity; ++ byte b0 = 0; ++ + if (this.level().getDifficulty() == Difficulty.NORMAL) { +- i = 10; ++ b0 = 10; + } else if (this.level().getDifficulty() == Difficulty.HARD) { +- i = 40; ++ b0 = 40; + } + +- if (i > 0) { +- livingEntityx.addEffect(new MobEffectInstance(MobEffects.WITHER, 20 * i, 1), this.getEffectSource()); ++ if (b0 > 0) { ++ entityliving.addEffect(new MobEffectInstance(MobEffects.WITHER, 20 * b0, 1), this.getEffectSource(), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } ++ + } + } + +@@ -87,9 +96,18 @@ + protected void onHit(HitResult result) { + super.onHit(result); + if (!this.level().isClientSide) { +- this.level().explode(this, this.getX(), this.getY(), this.getZ(), 1.0F, false, Level.ExplosionInteraction.MOB); ++ // CraftBukkit start ++ // this.level().explode(this, this.getX(), this.getY(), this.getZ(), 1.0F, false, World.a.MOB); ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), 1.0F, false); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.MOB); ++ } ++ // CraftBukkit end + this.discard(); + } ++ + } + + @Override +@@ -104,15 +122,15 @@ + + @Override + protected void defineSynchedData() { +- this.entityData.define(DATA_DANGEROUS, false); ++ this.entityData.define(WitherSkull.DATA_DANGEROUS, false); + } + + public boolean isDangerous() { +- return this.entityData.get(DATA_DANGEROUS); ++ return (Boolean) this.entityData.get(WitherSkull.DATA_DANGEROUS); + } + + public void setDangerous(boolean invulnerable) { +- this.entityData.set(DATA_DANGEROUS, invulnerable); ++ this.entityData.set(WitherSkull.DATA_DANGEROUS, invulnerable); + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/raid/Raid.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/raid/Raid.java.patch new file mode 100644 index 0000000000..f6ba16f649 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/raid/Raid.java.patch @@ -0,0 +1,972 @@ +--- a/net/minecraft/world/entity/raid/Raid.java ++++ b/net/minecraft/world/entity/raid/Raid.java +@@ -4,10 +4,12 @@ + import com.google.common.collect.Sets; + import java.util.Collection; + import java.util.Comparator; ++import java.util.HashSet; + import java.util.Iterator; + import java.util.List; + import java.util.Locale; + import java.util.Map; ++import java.util.Objects; + import java.util.Optional; + import java.util.Set; + import java.util.UUID; +@@ -39,9 +41,10 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.SpawnPlacements; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.BlockItem; +@@ -58,6 +61,7 @@ + import net.minecraft.world.phys.Vec3; + + public class Raid { ++ + private static final int SECTION_RADIUS_FOR_FINDING_NEW_VILLAGE_CENTER = 2; + private static final int ATTEMPT_RAID_FARTHEST = 0; + private static final int ATTEMPT_RAID_CLOSE = 1; +@@ -84,26 +88,29 @@ + public static final int RAID_REMOVAL_THRESHOLD_SQR = 12544; + private final Map groupToLeaderMap = Maps.newHashMap(); + private final Map> groupRaiderMap = Maps.newHashMap(); +- private final Set heroesOfTheVillage = Sets.newHashSet(); +- private long ticksActive; ++ public final Set heroesOfTheVillage = Sets.newHashSet(); ++ public long ticksActive; + private BlockPos center; + private final ServerLevel level; + private boolean started; + private final int id; +- private float totalHealth; +- private int badOmenLevel; ++ public float totalHealth; ++ public int badOmenLevel; + private boolean active; + private int groupsSpawned; +- private final ServerBossEvent raidEvent = new ServerBossEvent(RAID_NAME_COMPONENT, BossEvent.BossBarColor.RED, BossEvent.BossBarOverlay.NOTCHED_10); ++ private final ServerBossEvent raidEvent; + private int postRaidTicks; + private int raidCooldownTicks; +- private final RandomSource random = RandomSource.create(); +- private final int numGroups; ++ private final RandomSource random; ++ public final int numGroups; + private Raid.RaidStatus status; + private int celebrationTicks; +- private Optional waveSpawnPos = Optional.empty(); ++ private Optional waveSpawnPos; + + public Raid(int id, ServerLevel level, BlockPos center) { ++ this.raidEvent = new ServerBossEvent(Raid.RAID_NAME_COMPONENT, BossEvent.BossBarColor.RED, BossEvent.BossBarOverlay.NOTCHED_10); ++ this.random = RandomSource.create(); ++ this.waveSpawnPos = Optional.empty(); + this.id = id; + this.level = level; + this.active = true; +@@ -115,6 +122,9 @@ + } + + public Raid(ServerLevel level, CompoundTag compound) { ++ this.raidEvent = new ServerBossEvent(Raid.RAID_NAME_COMPONENT, BossEvent.BossBarColor.RED, BossEvent.BossBarOverlay.NOTCHED_10); ++ this.random = RandomSource.create(); ++ this.waveSpawnPos = Optional.empty(); + this.level = level; + this.id = compound.getInt("Id"); + this.started = compound.getBoolean("Started"); +@@ -130,10 +140,16 @@ + this.status = Raid.RaidStatus.getByName(compound.getString("Status")); + this.heroesOfTheVillage.clear(); + if (compound.contains("HeroesOfTheVillage", 9)) { +- for (Tag tag : compound.getList("HeroesOfTheVillage", 11)) { +- this.heroesOfTheVillage.add(NbtUtils.loadUUID(tag)); ++ ListTag nbttaglist = compound.getList("HeroesOfTheVillage", 11); ++ Iterator iterator = nbttaglist.iterator(); ++ ++ while (iterator.hasNext()) { ++ Tag nbtbase = (Tag) iterator.next(); ++ ++ this.heroesOfTheVillage.add(NbtUtils.loadUUID(nbtbase)); + } + } ++ + } + + public boolean isOver() { +@@ -160,14 +176,23 @@ + return this.status == Raid.RaidStatus.LOSS; + } + ++ // CraftBukkit start ++ public boolean isInProgress() { ++ return this.status == RaidStatus.ONGOING; ++ } ++ // CraftBukkit end ++ + public float getTotalHealth() { + return this.totalHealth; + } + + public Set getAllRaiders() { + Set set = Sets.newHashSet(); ++ Iterator iterator = this.groupRaiderMap.values().iterator(); + +- for (Set set1 : this.groupRaiderMap.values()) { ++ while (iterator.hasNext()) { ++ Set set1 = (Set) iterator.next(); ++ + set.addAll(set1); + } + +@@ -187,27 +212,36 @@ + } + + private Predicate validPlayer() { +- return player -> { +- BlockPos blockPos = player.blockPosition(); +- return player.isAlive() && this.level.getRaidAt(blockPos) == this; ++ return (entityplayer) -> { ++ BlockPos blockposition = entityplayer.blockPosition(); ++ ++ return entityplayer.isAlive() && this.level.getRaidAt(blockposition) == this; + }; + } + + private void updatePlayers() { + Set set = Sets.newHashSet(this.raidEvent.getPlayers()); +- List players = this.level.getPlayers(this.validPlayer()); ++ List list = this.level.getPlayers(this.validPlayer()); ++ Iterator iterator = list.iterator(); + +- for (ServerPlayer serverPlayer : players) { +- if (!set.contains(serverPlayer)) { +- this.raidEvent.addPlayer(serverPlayer); ++ ServerPlayer entityplayer; ++ ++ while (iterator.hasNext()) { ++ entityplayer = (ServerPlayer) iterator.next(); ++ if (!set.contains(entityplayer)) { ++ this.raidEvent.addPlayer(entityplayer); + } + } + +- for (ServerPlayer serverPlayerx : set) { +- if (!players.contains(serverPlayerx)) { +- this.raidEvent.removePlayer(serverPlayerx); ++ iterator = set.iterator(); ++ ++ while (iterator.hasNext()) { ++ entityplayer = (ServerPlayer) iterator.next(); ++ if (!list.contains(entityplayer)) { ++ this.raidEvent.removePlayer(entityplayer); + } + } ++ + } + + public int getMaxBadOmenLevel() { +@@ -224,7 +258,7 @@ + + public void absorbBadOmen(Player player) { + if (player.hasEffect(MobEffects.BAD_OMEN)) { +- this.badOmenLevel = this.badOmenLevel + player.getEffect(MobEffects.BAD_OMEN).getAmplifier() + 1; ++ this.badOmenLevel += player.getEffect(MobEffects.BAD_OMEN).getAmplifier() + 1; + this.badOmenLevel = Mth.clamp(this.badOmenLevel, 0, this.getMaxBadOmenLevel()); + } + +@@ -241,8 +275,10 @@ + if (!this.isStopped()) { + if (this.status == Raid.RaidStatus.ONGOING) { + boolean flag = this.active; ++ + this.active = this.level.hasChunkAt(this.center); + if (this.level.getDifficulty() == Difficulty.PEACEFUL) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.PEACE); // CraftBukkit + this.stop(); + return; + } +@@ -262,121 +298,131 @@ + if (!this.level.isVillage(this.center)) { + if (this.groupsSpawned > 0) { + this.status = Raid.RaidStatus.LOSS; ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidFinishEvent(this, new java.util.ArrayList<>()); // CraftBukkit + } else { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.NOT_IN_VILLAGE); // CraftBukkit + this.stop(); + } + } + +- this.ticksActive++; ++ ++this.ticksActive; + if (this.ticksActive >= 48000L) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.TIMEOUT); // CraftBukkit + this.stop(); + return; + } + +- int totalRaidersAlive = this.getTotalRaidersAlive(); +- if (totalRaidersAlive == 0 && this.hasMoreWaves()) { +- if (this.raidCooldownTicks <= 0) { +- if (this.raidCooldownTicks == 0 && this.groupsSpawned > 0) { +- this.raidCooldownTicks = 300; +- this.raidEvent.setName(RAID_NAME_COMPONENT); +- return; ++ int i = this.getTotalRaidersAlive(); ++ boolean flag1; ++ ++ if (i == 0 && this.hasMoreWaves()) { ++ if (this.raidCooldownTicks > 0) { ++ flag1 = this.waveSpawnPos.isPresent(); ++ boolean flag2 = !flag1 && this.raidCooldownTicks % 5 == 0; ++ ++ if (flag1 && !this.level.isPositionEntityTicking((BlockPos) this.waveSpawnPos.get())) { ++ flag2 = true; + } +- } else { +- boolean isPresent = this.waveSpawnPos.isPresent(); +- boolean flag1 = !isPresent && this.raidCooldownTicks % 5 == 0; +- if (isPresent && !this.level.isPositionEntityTicking(this.waveSpawnPos.get())) { +- flag1 = true; +- } + +- if (flag1) { +- int i = 0; ++ if (flag2) { ++ byte b0 = 0; ++ + if (this.raidCooldownTicks < 100) { +- i = 1; ++ b0 = 1; + } else if (this.raidCooldownTicks < 40) { +- i = 2; ++ b0 = 2; + } + +- this.waveSpawnPos = this.getValidSpawnPos(i); ++ this.waveSpawnPos = this.getValidSpawnPos(b0); + } + + if (this.raidCooldownTicks == 300 || this.raidCooldownTicks % 20 == 0) { + this.updatePlayers(); + } + +- this.raidCooldownTicks--; +- this.raidEvent.setProgress(Mth.clamp((float)(300 - this.raidCooldownTicks) / 300.0F, 0.0F, 1.0F)); ++ --this.raidCooldownTicks; ++ this.raidEvent.setProgress(Mth.clamp((float) (300 - this.raidCooldownTicks) / 300.0F, 0.0F, 1.0F)); ++ } else if (this.raidCooldownTicks == 0 && this.groupsSpawned > 0) { ++ this.raidCooldownTicks = 300; ++ this.raidEvent.setName(Raid.RAID_NAME_COMPONENT); ++ return; + } + } + + if (this.ticksActive % 20L == 0L) { + this.updatePlayers(); + this.updateRaiders(); +- if (totalRaidersAlive > 0) { +- if (totalRaidersAlive <= 2) { +- this.raidEvent +- .setName( +- RAID_NAME_COMPONENT.copy() +- .append(" - ") +- .append(Component.translatable("event.minecraft.raid.raiders_remaining", totalRaidersAlive)) +- ); ++ if (i > 0) { ++ if (i <= 2) { ++ this.raidEvent.setName(Raid.RAID_NAME_COMPONENT.copy().append(" - ").append((Component) Component.translatable("event.minecraft.raid.raiders_remaining", i))); + } else { +- this.raidEvent.setName(RAID_NAME_COMPONENT); ++ this.raidEvent.setName(Raid.RAID_NAME_COMPONENT); + } + } else { +- this.raidEvent.setName(RAID_NAME_COMPONENT); ++ this.raidEvent.setName(Raid.RAID_NAME_COMPONENT); + } + } + +- boolean isPresentx = false; +- int i1 = 0; ++ flag1 = false; ++ int j = 0; + + while (this.shouldSpawnGroup()) { +- BlockPos blockPos = this.waveSpawnPos.isPresent() ? this.waveSpawnPos.get() : this.findRandomSpawnPos(i1, 20); +- if (blockPos != null) { ++ BlockPos blockposition = this.waveSpawnPos.isPresent() ? (BlockPos) this.waveSpawnPos.get() : this.findRandomSpawnPos(j, 20); ++ ++ if (blockposition != null) { + this.started = true; +- this.spawnGroup(blockPos); +- if (!isPresentx) { +- this.playSound(blockPos); +- isPresentx = true; ++ this.spawnGroup(blockposition); ++ if (!flag1) { ++ this.playSound(blockposition); ++ flag1 = true; + } + } else { +- i1++; ++ ++j; + } + +- if (i1 > 3) { ++ if (j > 3) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.UNSPAWNABLE); // CraftBukkit + this.stop(); + break; + } + } + +- if (this.isStarted() && !this.hasMoreWaves() && totalRaidersAlive == 0) { ++ if (this.isStarted() && !this.hasMoreWaves() && i == 0) { + if (this.postRaidTicks < 40) { +- this.postRaidTicks++; ++ ++this.postRaidTicks; + } else { + this.status = Raid.RaidStatus.VICTORY; ++ Iterator iterator = this.heroesOfTheVillage.iterator(); + +- for (UUID uUID : this.heroesOfTheVillage) { +- Entity entity = this.level.getEntity(uUID); ++ List winners = new java.util.ArrayList<>(); // CraftBukkit ++ while (iterator.hasNext()) { ++ UUID uuid = (UUID) iterator.next(); ++ Entity entity = this.level.getEntity(uuid); ++ + if (entity instanceof LivingEntity) { +- LivingEntity livingEntity = (LivingEntity)entity; ++ LivingEntity entityliving = (LivingEntity) entity; ++ + if (!entity.isSpectator()) { +- livingEntity.addEffect( +- new MobEffectInstance(MobEffects.HERO_OF_THE_VILLAGE, 48000, this.badOmenLevel - 1, false, false, true) +- ); +- if (livingEntity instanceof ServerPlayer serverPlayer) { +- serverPlayer.awardStat(Stats.RAID_WIN); +- CriteriaTriggers.RAID_WIN.trigger(serverPlayer); ++ entityliving.addEffect(new MobEffectInstance(MobEffects.HERO_OF_THE_VILLAGE, 48000, this.badOmenLevel - 1, false, false, true)); ++ if (entityliving instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entityliving; ++ ++ entityplayer.awardStat(Stats.RAID_WIN); ++ CriteriaTriggers.RAID_WIN.trigger(entityplayer); ++ winners.add(entityplayer.getBukkitEntity()); // CraftBukkit + } + } + } + } ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidFinishEvent(this, winners); // CraftBukkit + } + } + + this.setDirty(); + } else if (this.isOver()) { +- this.celebrationTicks++; ++ ++this.celebrationTicks; + if (this.celebrationTicks >= 600) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.FINISHED); // CraftBukkit + this.stop(); + return; + } +@@ -386,28 +432,32 @@ + this.raidEvent.setVisible(true); + if (this.isVictory()) { + this.raidEvent.setProgress(0.0F); +- this.raidEvent.setName(RAID_BAR_VICTORY_COMPONENT); ++ this.raidEvent.setName(Raid.RAID_BAR_VICTORY_COMPONENT); + } else { +- this.raidEvent.setName(RAID_BAR_DEFEAT_COMPONENT); ++ this.raidEvent.setName(Raid.RAID_BAR_DEFEAT_COMPONENT); + } + } + } ++ + } + } + + private void moveRaidCenterToNearbyVillageSection() { + Stream stream = SectionPos.cube(SectionPos.of(this.center), 2); +- stream.filter(this.level::isVillage) +- .map(SectionPos::center) +- .min(Comparator.comparingDouble(pos -> pos.distSqr(this.center))) +- .ifPresent(this::setCenter); ++ ServerLevel worldserver = this.level; ++ ++ Objects.requireNonNull(this.level); ++ stream.filter(worldserver::isVillage).map(SectionPos::center).min(Comparator.comparingDouble((blockposition) -> { ++ return blockposition.distSqr(this.center); ++ })).ifPresent(this::setCenter); + } + + private Optional getValidSpawnPos(int offsetMultiplier) { +- for (int i = 0; i < 3; i++) { +- BlockPos blockPos = this.findRandomSpawnPos(offsetMultiplier, 1); +- if (blockPos != null) { +- return Optional.of(blockPos); ++ for (int j = 0; j < 3; ++j) { ++ BlockPos blockposition = this.findRandomSpawnPos(offsetMultiplier, 1); ++ ++ if (blockposition != null) { ++ return Optional.of(blockposition); + } + } + +@@ -436,123 +486,159 @@ + + private void updateRaiders() { + Iterator> iterator = this.groupRaiderMap.values().iterator(); +- Set set = Sets.newHashSet(); ++ HashSet hashset = Sets.newHashSet(); + + while (iterator.hasNext()) { +- Set set1 = iterator.next(); ++ Set set = (Set) iterator.next(); ++ Iterator iterator1 = set.iterator(); + +- for (Raider raider : set1) { +- BlockPos blockPos = raider.blockPosition(); +- if (raider.isRemoved() || raider.level().dimension() != this.level.dimension() || this.center.distSqr(blockPos) >= 12544.0) { +- set.add(raider); +- } else if (raider.tickCount > 600) { +- if (this.level.getEntity(raider.getUUID()) == null) { +- set.add(raider); +- } ++ while (iterator1.hasNext()) { ++ Raider entityraider = (Raider) iterator1.next(); ++ BlockPos blockposition = entityraider.blockPosition(); + +- if (!this.level.isVillage(blockPos) && raider.getNoActionTime() > 2400) { +- raider.setTicksOutsideRaid(raider.getTicksOutsideRaid() + 1); +- } ++ if (!entityraider.isRemoved() && entityraider.level().dimension() == this.level.dimension() && this.center.distSqr(blockposition) < 12544.0D) { ++ if (entityraider.tickCount > 600) { ++ if (this.level.getEntity(entityraider.getUUID()) == null) { ++ hashset.add(entityraider); ++ } + +- if (raider.getTicksOutsideRaid() >= 30) { +- set.add(raider); ++ if (!this.level.isVillage(blockposition) && entityraider.getNoActionTime() > 2400) { ++ entityraider.setTicksOutsideRaid(entityraider.getTicksOutsideRaid() + 1); ++ } ++ ++ if (entityraider.getTicksOutsideRaid() >= 30) { ++ hashset.add(entityraider); ++ } + } ++ } else { ++ hashset.add(entityraider); + } + } + } + +- for (Raider raider1 : set) { +- this.removeFromRaid(raider1, true); ++ Iterator iterator2 = hashset.iterator(); ++ ++ while (iterator2.hasNext()) { ++ Raider entityraider1 = (Raider) iterator2.next(); ++ ++ this.removeFromRaid(entityraider1, true); + } ++ + } + + private void playSound(BlockPos pos) { + float f = 13.0F; +- int i = 64; +- Collection players = this.raidEvent.getPlayers(); +- long randomLong = this.random.nextLong(); ++ boolean flag = true; ++ Collection collection = this.raidEvent.getPlayers(); ++ long i = this.random.nextLong(); ++ Iterator iterator = this.level.players().iterator(); + +- for (ServerPlayer serverPlayer : this.level.players()) { +- Vec3 vec3 = serverPlayer.position(); +- Vec3 vec31 = Vec3.atCenterOf(pos); +- double squareRoot = Math.sqrt((vec31.x - vec3.x) * (vec31.x - vec3.x) + (vec31.z - vec3.z) * (vec31.z - vec3.z)); +- double d = vec3.x + 13.0 / squareRoot * (vec31.x - vec3.x); +- double d1 = vec3.z + 13.0 / squareRoot * (vec31.z - vec3.z); +- if (squareRoot <= 64.0 || players.contains(serverPlayer)) { +- serverPlayer.connection +- .send(new ClientboundSoundPacket(SoundEvents.RAID_HORN, SoundSource.NEUTRAL, d, serverPlayer.getY(), d1, 64.0F, 1.0F, randomLong)); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ Vec3 vec3d = entityplayer.position(); ++ Vec3 vec3d1 = Vec3.atCenterOf(pos); ++ double d0 = Math.sqrt((vec3d1.x - vec3d.x) * (vec3d1.x - vec3d.x) + (vec3d1.z - vec3d.z) * (vec3d1.z - vec3d.z)); ++ double d1 = vec3d.x + 13.0D / d0 * (vec3d1.x - vec3d.x); ++ double d2 = vec3d.z + 13.0D / d0 * (vec3d1.z - vec3d.z); ++ ++ if (d0 <= 64.0D || collection.contains(entityplayer)) { ++ entityplayer.connection.send(new ClientboundSoundPacket(SoundEvents.RAID_HORN, SoundSource.NEUTRAL, d1, entityplayer.getY(), d2, 64.0F, 1.0F, i)); + } + } ++ + } + + private void spawnGroup(BlockPos pos) { + boolean flag = false; + int i = this.groupsSpawned + 1; ++ + this.totalHealth = 0.0F; +- DifficultyInstance currentDifficultyAt = this.level.getCurrentDifficultyAt(pos); +- boolean shouldSpawnBonusGroup = this.shouldSpawnBonusGroup(); ++ DifficultyInstance difficultydamagescaler = this.level.getCurrentDifficultyAt(pos); ++ boolean flag1 = this.shouldSpawnBonusGroup(); ++ Raid.RaiderType[] araid_wave = Raid.RaiderType.VALUES; ++ int j = araid_wave.length; ++ int k = 0; + +- for (Raid.RaiderType raiderType : Raid.RaiderType.VALUES) { +- int i1 = this.getDefaultNumSpawns(raiderType, i, shouldSpawnBonusGroup) +- + this.getPotentialBonusSpawns(raiderType, this.random, i, currentDifficultyAt, shouldSpawnBonusGroup); +- int i2 = 0; ++ // CraftBukkit start ++ Raider leader = null; ++ List raiders = new java.util.ArrayList<>(); ++ // CraftBukkit end ++ while (k < j) { ++ Raid.RaiderType raid_wave = araid_wave[k]; ++ int l = this.getDefaultNumSpawns(raid_wave, i, flag1) + this.getPotentialBonusSpawns(raid_wave, this.random, i, difficultydamagescaler, flag1); ++ int i1 = 0; ++ int j1 = 0; + +- for (int i3 = 0; i3 < i1; i3++) { +- Raider raider = raiderType.entityType.create(this.level); +- if (raider == null) { +- break; +- } ++ while (true) { ++ if (j1 < l) { ++ Raider entityraider = (Raider) raid_wave.entityType.create(this.level); + +- if (!flag && raider.canBeLeader()) { +- raider.setPatrolLeader(true); +- this.setLeader(i, raider); +- flag = true; +- } ++ if (entityraider != null) { ++ if (!flag && entityraider.canBeLeader()) { ++ entityraider.setPatrolLeader(true); ++ this.setLeader(i, entityraider); ++ flag = true; ++ leader = entityraider; // CraftBukkit ++ } + +- this.joinRaid(i, raider, pos, false); +- if (raiderType.entityType == EntityType.RAVAGER) { +- Raider raider1 = null; +- if (i == this.getNumGroups(Difficulty.NORMAL)) { +- raider1 = EntityType.PILLAGER.create(this.level); +- } else if (i >= this.getNumGroups(Difficulty.HARD)) { +- if (i2 == 0) { +- raider1 = EntityType.EVOKER.create(this.level); +- } else { +- raider1 = EntityType.VINDICATOR.create(this.level); ++ this.joinRaid(i, entityraider, pos, false); ++ raiders.add(entityraider); // CraftBukkit ++ if (raid_wave.entityType == EntityType.RAVAGER) { ++ Raider entityraider1 = null; ++ ++ if (i == this.getNumGroups(Difficulty.NORMAL)) { ++ entityraider1 = (Raider) EntityType.PILLAGER.create(this.level); ++ } else if (i >= this.getNumGroups(Difficulty.HARD)) { ++ if (i1 == 0) { ++ entityraider1 = (Raider) EntityType.EVOKER.create(this.level); ++ } else { ++ entityraider1 = (Raider) EntityType.VINDICATOR.create(this.level); ++ } ++ } ++ ++ ++i1; ++ if (entityraider1 != null) { ++ this.joinRaid(i, entityraider1, pos, false); ++ entityraider1.moveTo(pos, 0.0F, 0.0F); ++ entityraider1.startRiding(entityraider); ++ raiders.add(entityraider); // CraftBukkit ++ } + } +- } + +- i2++; +- if (raider1 != null) { +- this.joinRaid(i, raider1, pos, false); +- raider1.moveTo(pos, 0.0F, 0.0F); +- raider1.startRiding(raider); ++ ++j1; ++ continue; + } + } ++ ++ ++k; ++ break; + } + } + + this.waveSpawnPos = Optional.empty(); +- this.groupsSpawned++; ++ ++this.groupsSpawned; + this.updateBossbar(); + this.setDirty(); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidSpawnWaveEvent(this, leader, raiders); // CraftBukkit + } + + public void joinRaid(int wave, Raider raider, @Nullable BlockPos pos, boolean isRecruited) { +- boolean flag = this.addWaveMob(wave, raider); +- if (flag) { ++ boolean flag1 = this.addWaveMob(wave, raider); ++ ++ if (flag1) { + raider.setCurrentRaid(this); + raider.setWave(wave); + raider.setCanJoinRaid(true); + raider.setTicksOutsideRaid(0); + if (!isRecruited && pos != null) { +- raider.setPos((double)pos.getX() + 0.5, (double)pos.getY() + 1.0, (double)pos.getZ() + 0.5); +- raider.finalizeSpawn(this.level, this.level.getCurrentDifficultyAt(pos), MobSpawnType.EVENT, null, null); ++ raider.setPos((double) pos.getX() + 0.5D, (double) pos.getY() + 1.0D, (double) pos.getZ() + 0.5D); ++ raider.finalizeSpawn(this.level, this.level.getCurrentDifficultyAt(pos), EnumMobSpawn.EVENT, (GroupDataEntity) null, (CompoundTag) null); + raider.applyRaidBuffs(wave, false); + raider.setOnGround(true); +- this.level.addFreshEntityWithPassengers(raider); ++ this.level.addFreshEntityWithPassengers(raider, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.RAID); // CraftBukkit + } + } ++ + } + + public void updateBossbar() { +@@ -561,10 +647,15 @@ + + public float getHealthOfLivingRaiders() { + float f = 0.0F; ++ Iterator iterator = this.groupRaiderMap.values().iterator(); + +- for (Set set : this.groupRaiderMap.values()) { +- for (Raider raider : set) { +- f += raider.getHealth(); ++ while (iterator.hasNext()) { ++ Set set = (Set) iterator.next(); ++ ++ Raider entityraider; ++ ++ for (Iterator iterator1 = set.iterator(); iterator1.hasNext(); f += entityraider.getHealth()) { ++ entityraider = (Raider) iterator1.next(); + } + } + +@@ -580,19 +671,22 @@ + } + + public void removeFromRaid(Raider raider, boolean wanderedOutOfRaid) { +- Set set = this.groupRaiderMap.get(raider.getWave()); ++ Set set = (Set) this.groupRaiderMap.get(raider.getWave()); ++ + if (set != null) { +- boolean flag = set.remove(raider); +- if (flag) { ++ boolean flag1 = set.remove(raider); ++ ++ if (flag1) { + if (wanderedOutOfRaid) { +- this.totalHealth = this.totalHealth - raider.getHealth(); ++ this.totalHealth -= raider.getHealth(); + } + +- raider.setCurrentRaid(null); ++ raider.setCurrentRaid((Raid) null); + this.updateBossbar(); + this.setDirty(); + } + } ++ + } + + private void setDirty() { +@@ -600,50 +694,39 @@ + } + + public static ItemStack getLeaderBannerInstance() { +- ItemStack itemStack = new ItemStack(Items.WHITE_BANNER); +- CompoundTag compoundTag = new CompoundTag(); +- ListTag list = new BannerPattern.Builder() +- .addPattern(BannerPatterns.RHOMBUS_MIDDLE, DyeColor.CYAN) +- .addPattern(BannerPatterns.STRIPE_BOTTOM, DyeColor.LIGHT_GRAY) +- .addPattern(BannerPatterns.STRIPE_CENTER, DyeColor.GRAY) +- .addPattern(BannerPatterns.BORDER, DyeColor.LIGHT_GRAY) +- .addPattern(BannerPatterns.STRIPE_MIDDLE, DyeColor.BLACK) +- .addPattern(BannerPatterns.HALF_HORIZONTAL, DyeColor.LIGHT_GRAY) +- .addPattern(BannerPatterns.CIRCLE_MIDDLE, DyeColor.LIGHT_GRAY) +- .addPattern(BannerPatterns.BORDER, DyeColor.BLACK) +- .toListTag(); +- compoundTag.put("Patterns", list); +- BlockItem.setBlockEntityData(itemStack, BlockEntityType.BANNER, compoundTag); +- itemStack.hideTooltipPart(ItemStack.TooltipPart.ADDITIONAL); +- itemStack.setHoverName(Component.translatable("block.minecraft.ominous_banner").withStyle(ChatFormatting.GOLD)); +- return itemStack; ++ ItemStack itemstack = new ItemStack(Items.WHITE_BANNER); ++ CompoundTag nbttagcompound = new CompoundTag(); ++ ListTag nbttaglist = (new BannerPattern.Builder()).addPattern(BannerPatterns.RHOMBUS_MIDDLE, DyeColor.CYAN).addPattern(BannerPatterns.STRIPE_BOTTOM, DyeColor.LIGHT_GRAY).addPattern(BannerPatterns.STRIPE_CENTER, DyeColor.GRAY).addPattern(BannerPatterns.BORDER, DyeColor.LIGHT_GRAY).addPattern(BannerPatterns.STRIPE_MIDDLE, DyeColor.BLACK).addPattern(BannerPatterns.HALF_HORIZONTAL, DyeColor.LIGHT_GRAY).addPattern(BannerPatterns.CIRCLE_MIDDLE, DyeColor.LIGHT_GRAY).addPattern(BannerPatterns.BORDER, DyeColor.BLACK).toListTag(); ++ ++ nbttagcompound.put("Patterns", nbttaglist); ++ BlockItem.setBlockEntityData(itemstack, BlockEntityType.BANNER, nbttagcompound); ++ itemstack.hideTooltipPart(ItemStack.HideFlags.ADDITIONAL); ++ itemstack.setHoverName(Component.translatable("block.minecraft.ominous_banner").withStyle(ChatFormatting.GOLD)); ++ return itemstack; + } + + @Nullable + public Raider getLeader(int wave) { +- return this.groupToLeaderMap.get(wave); ++ return (Raider) this.groupToLeaderMap.get(wave); + } + + @Nullable + private BlockPos findRandomSpawnPos(int offsetMultiplier, int maxTry) { +- int i = offsetMultiplier == 0 ? 2 : 2 - offsetMultiplier; +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ int k = offsetMultiplier == 0 ? 2 : 2 - offsetMultiplier; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + +- for (int i1 = 0; i1 < maxTry; i1++) { +- float f = this.level.random.nextFloat() * (float) (Math.PI * 2); +- int i2 = this.center.getX() + Mth.floor(Mth.cos(f) * 32.0F * (float)i) + this.level.random.nextInt(5); +- int i3 = this.center.getZ() + Mth.floor(Mth.sin(f) * 32.0F * (float)i) + this.level.random.nextInt(5); +- int height = this.level.getHeight(Heightmap.Types.WORLD_SURFACE, i2, i3); +- mutableBlockPos.set(i2, height, i3); +- if (!this.level.isVillage(mutableBlockPos) || offsetMultiplier >= 2) { +- int i4 = 10; +- if (this.level.hasChunksAt(mutableBlockPos.getX() - 10, mutableBlockPos.getZ() - 10, mutableBlockPos.getX() + 10, mutableBlockPos.getZ() + 10) +- && this.level.isPositionEntityTicking(mutableBlockPos) +- && ( +- NaturalSpawner.isSpawnPositionOk(SpawnPlacements.Type.ON_GROUND, this.level, mutableBlockPos, EntityType.RAVAGER) +- || this.level.getBlockState(mutableBlockPos.below()).is(Blocks.SNOW) && this.level.getBlockState(mutableBlockPos).isAir() +- )) { +- return mutableBlockPos; ++ for (int l = 0; l < maxTry; ++l) { ++ float f = this.level.random.nextFloat() * 6.2831855F; ++ int i1 = this.center.getX() + Mth.floor(Mth.cos(f) * 32.0F * (float) k) + this.level.random.nextInt(5); ++ int j1 = this.center.getZ() + Mth.floor(Mth.sin(f) * 32.0F * (float) k) + this.level.random.nextInt(5); ++ int k1 = this.level.getHeight(Heightmap.Types.WORLD_SURFACE, i1, j1); ++ ++ blockposition_mutableblockposition.set(i1, k1, j1); ++ if (!this.level.isVillage((BlockPos) blockposition_mutableblockposition) || offsetMultiplier >= 2) { ++ boolean flag = true; ++ ++ if (this.level.hasChunksAt(blockposition_mutableblockposition.getX() - 10, blockposition_mutableblockposition.getZ() - 10, blockposition_mutableblockposition.getX() + 10, blockposition_mutableblockposition.getZ() + 10) && this.level.isPositionEntityTicking(blockposition_mutableblockposition) && (NaturalSpawner.isSpawnPositionOk(SpawnPlacements.Surface.ON_GROUND, this.level, blockposition_mutableblockposition, EntityType.RAVAGER) || this.level.getBlockState(blockposition_mutableblockposition.below()).is(Blocks.SNOW) && this.level.getBlockState(blockposition_mutableblockposition).isAir())) { ++ return blockposition_mutableblockposition; + } + } + } +@@ -656,25 +739,30 @@ + } + + public boolean addWaveMob(int wave, Raider raider, boolean isRecruited) { +- this.groupRaiderMap.computeIfAbsent(wave, value -> Sets.newHashSet()); +- Set set = this.groupRaiderMap.get(wave); +- Raider raider1 = null; ++ this.groupRaiderMap.computeIfAbsent(wave, (integer) -> { ++ return Sets.newHashSet(); ++ }); ++ Set set = (Set) this.groupRaiderMap.get(wave); ++ Raider entityraider1 = null; ++ Iterator iterator = set.iterator(); + +- for (Raider raider2 : set) { +- if (raider2.getUUID().equals(raider.getUUID())) { +- raider1 = raider2; ++ while (iterator.hasNext()) { ++ Raider entityraider2 = (Raider) iterator.next(); ++ ++ if (entityraider2.getUUID().equals(raider.getUUID())) { ++ entityraider1 = entityraider2; + break; + } + } + +- if (raider1 != null) { +- set.remove(raider1); ++ if (entityraider1 != null) { ++ set.remove(entityraider1); + set.add(raider); + } + + set.add(raider); + if (isRecruited) { +- this.totalHealth = this.totalHealth + raider.getHealth(); ++ this.totalHealth += raider.getHealth(); + } + + this.updateBossbar(); +@@ -709,36 +797,37 @@ + } + + private int getPotentialBonusSpawns(Raid.RaiderType raiderType, RandomSource random, int wave, DifficultyInstance difficulty, boolean shouldSpawnBonusGroup) { +- Difficulty difficulty1 = difficulty.getDifficulty(); +- boolean flag = difficulty1 == Difficulty.EASY; +- boolean flag1 = difficulty1 == Difficulty.NORMAL; +- int i; ++ Difficulty enumdifficulty = difficulty.getDifficulty(); ++ boolean flag1 = enumdifficulty == Difficulty.EASY; ++ boolean flag2 = enumdifficulty == Difficulty.NORMAL; ++ int j; ++ + switch (raiderType) { + case WITCH: +- if (flag || wave <= 2 || wave == 4) { ++ if (flag1 || wave <= 2 || wave == 4) { + return 0; + } + +- i = 1; ++ j = 1; + break; + case PILLAGER: + case VINDICATOR: +- if (flag) { +- i = random.nextInt(2); +- } else if (flag1) { +- i = 1; ++ if (flag1) { ++ j = random.nextInt(2); ++ } else if (flag2) { ++ j = 1; + } else { +- i = 2; ++ j = 2; + } + break; + case RAVAGER: +- i = !flag && shouldSpawnBonusGroup ? 1 : 0; ++ j = !flag1 && shouldSpawnBonusGroup ? 1 : 0; + break; + default: + return 0; + } + +- return i > 0 ? random.nextInt(i + 1) : 0; ++ return j > 0 ? random.nextInt(j + 1) : 0; + } + + public boolean isActive() { +@@ -760,13 +849,16 @@ + compound.putInt("CX", this.center.getX()); + compound.putInt("CY", this.center.getY()); + compound.putInt("CZ", this.center.getZ()); +- ListTag list = new ListTag(); ++ ListTag nbttaglist = new ListTag(); ++ Iterator iterator = this.heroesOfTheVillage.iterator(); + +- for (UUID uUID : this.heroesOfTheVillage) { +- list.add(NbtUtils.createUUID(uUID)); ++ while (iterator.hasNext()) { ++ UUID uuid = (UUID) iterator.next(); ++ ++ nbttaglist.add(NbtUtils.createUUID(uuid)); + } + +- compound.put("HeroesOfTheVillage", list); ++ compound.put("HeroesOfTheVillage", nbttaglist); + return compound; + } + +@@ -784,38 +876,42 @@ + } + + public float getEnchantOdds() { +- int badOmenLevel = this.getBadOmenLevel(); +- if (badOmenLevel == 2) { +- return 0.1F; +- } else if (badOmenLevel == 3) { +- return 0.25F; +- } else if (badOmenLevel == 4) { +- return 0.5F; +- } else { +- return badOmenLevel == 5 ? 0.75F : 0.0F; +- } ++ int i = this.getBadOmenLevel(); ++ ++ return i == 2 ? 0.1F : (i == 3 ? 0.25F : (i == 4 ? 0.5F : (i == 5 ? 0.75F : 0.0F))); + } + + public void addHeroOfTheVillage(Entity player) { + this.heroesOfTheVillage.add(player.getUUID()); + } + +- static enum RaidStatus { +- ONGOING, +- VICTORY, +- LOSS, +- STOPPED; ++ // CraftBukkit start - a method to get all raiders ++ public java.util.Collection getRaiders() { ++ return this.groupRaiderMap.values().stream().flatMap(Set::stream).collect(java.util.stream.Collectors.toSet()); ++ } ++ // CraftBukkit end + ++ private static enum RaidStatus { ++ ++ ONGOING, VICTORY, LOSS, STOPPED; ++ + private static final Raid.RaidStatus[] VALUES = values(); + ++ private RaidStatus() {} ++ + static Raid.RaidStatus getByName(String name) { +- for (Raid.RaidStatus raidStatus : VALUES) { +- if (name.equalsIgnoreCase(raidStatus.name())) { +- return raidStatus; ++ Raid.RaidStatus[] araid_status = Raid.RaidStatus.VALUES; ++ int i = araid_status.length; ++ ++ for (int j = 0; j < i; ++j) { ++ Raid.RaidStatus raid_status = araid_status[j]; ++ ++ if (name.equalsIgnoreCase(raid_status.name())) { ++ return raid_status; + } + } + +- return ONGOING; ++ return Raid.RaidStatus.ONGOING; + } + + public String getName() { +@@ -823,20 +919,17 @@ + } + } + +- static enum RaiderType { +- VINDICATOR(EntityType.VINDICATOR, new int[]{0, 0, 2, 0, 1, 4, 2, 5}), +- EVOKER(EntityType.EVOKER, new int[]{0, 0, 0, 0, 0, 1, 1, 2}), +- PILLAGER(EntityType.PILLAGER, new int[]{0, 4, 3, 3, 4, 4, 4, 2}), +- WITCH(EntityType.WITCH, new int[]{0, 0, 0, 0, 3, 0, 0, 1}), +- RAVAGER(EntityType.RAVAGER, new int[]{0, 0, 0, 1, 0, 1, 0, 2}); ++ private static enum RaiderType { + ++ VINDICATOR(EntityType.VINDICATOR, new int[]{0, 0, 2, 0, 1, 4, 2, 5}), EVOKER(EntityType.EVOKER, new int[]{0, 0, 0, 0, 0, 1, 1, 2}), PILLAGER(EntityType.PILLAGER, new int[]{0, 4, 3, 3, 4, 4, 4, 2}), WITCH(EntityType.WITCH, new int[]{0, 0, 0, 0, 3, 0, 0, 1}), RAVAGER(EntityType.RAVAGER, new int[]{0, 0, 0, 1, 0, 1, 0, 2}); ++ + static final Raid.RaiderType[] VALUES = values(); + final EntityType entityType; + final int[] spawnsPerWaveBeforeBonus; + +- private RaiderType(EntityType entityType, int[] spawnsPerWaveBeforeBonus) { +- this.entityType = entityType; +- this.spawnsPerWaveBeforeBonus = spawnsPerWaveBeforeBonus; ++ private RaiderType(EntityType entitytypes, int[] aint) { ++ this.entityType = entitytypes; ++ this.spawnsPerWaveBeforeBonus = aint; + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/raid/Raider.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/raid/Raider.java.patch new file mode 100644 index 0000000000..78ed81a8bb --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/raid/Raider.java.patch @@ -0,0 +1,660 @@ +--- a/net/minecraft/world/entity/raid/Raider.java ++++ b/net/minecraft/world/entity/raid/Raider.java +@@ -2,13 +2,13 @@ + + import com.google.common.collect.Lists; + import java.util.EnumSet; ++import java.util.Iterator; + import java.util.List; + import java.util.Objects; + import java.util.Optional; + import java.util.function.Predicate; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +-import net.minecraft.core.Holder; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; +@@ -22,10 +22,10 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.goal.Goal; + import net.minecraft.world.entity.ai.goal.PathfindToRaidGoal; + import net.minecraft.world.entity.ai.targeting.TargetingConditions; +@@ -44,10 +44,11 @@ + import net.minecraft.world.phys.Vec3; + + public abstract class Raider extends PatrollingMonster { ++ + protected static final EntityDataAccessor IS_CELEBRATING = SynchedEntityData.defineId(Raider.class, EntityDataSerializers.BOOLEAN); +- static final Predicate ALLOWED_ITEMS = itemEntity -> !itemEntity.hasPickUpDelay() +- && itemEntity.isAlive() +- && ItemStack.matches(itemEntity.getItem(), Raid.getLeaderBannerInstance()); ++ static final Predicate ALLOWED_ITEMS = (entityitem) -> { ++ return !entityitem.hasPickUpDelay() && entityitem.isAlive() && ItemStack.matches(entityitem.getItem(), Raid.getLeaderBannerInstance()); ++ }; + @Nullable + protected Raid raid; + private int wave; +@@ -63,14 +64,14 @@ + super.registerGoals(); + this.goalSelector.addGoal(1, new Raider.ObtainRaidLeaderBannerGoal<>(this)); + this.goalSelector.addGoal(3, new PathfindToRaidGoal<>(this)); +- this.goalSelector.addGoal(4, new Raider.RaiderMoveThroughVillageGoal(this, 1.05F, 1)); ++ this.goalSelector.addGoal(4, new Raider.RaiderMoveThroughVillageGoal(this, 1.0499999523162842D, 1)); + this.goalSelector.addGoal(5, new Raider.RaiderCelebration(this)); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(IS_CELEBRATING, false); ++ this.entityData.define(Raider.IS_CELEBRATING, false); + } + + public abstract void applyRaidBuffs(int wave, boolean unusedFalse); +@@ -86,18 +87,21 @@ + @Override + public void aiStep() { + if (this.level() instanceof ServerLevel && this.isAlive()) { +- Raid currentRaid = this.getCurrentRaid(); ++ Raid raid = this.getCurrentRaid(); ++ + if (this.canJoinRaid()) { +- if (currentRaid == null) { ++ if (raid == null) { + if (this.level().getGameTime() % 20L == 0L) { +- Raid raidAt = ((ServerLevel)this.level()).getRaidAt(this.blockPosition()); +- if (raidAt != null && Raids.canJoinRaid(this, raidAt)) { +- raidAt.joinRaid(raidAt.getGroupsSpawned(), this, null, true); ++ Raid raid1 = ((ServerLevel) this.level()).getRaidAt(this.blockPosition()); ++ ++ if (raid1 != null && Raids.canJoinRaid(this, raid1)) { ++ raid1.joinRaid(raid1.getGroupsSpawned(), this, (BlockPos) null, true); + } + } + } else { +- LivingEntity target = this.getTarget(); +- if (target != null && (target.getType() == EntityType.PLAYER || target.getType() == EntityType.IRON_GOLEM)) { ++ LivingEntity entityliving = this.getTarget(); ++ ++ if (entityliving != null && (entityliving.getType() == EntityType.PLAYER || entityliving.getType() == EntityType.IRON_GOLEM)) { + this.noActionTime = 0; + } + } +@@ -116,45 +120,52 @@ + public void die(DamageSource cause) { + if (this.level() instanceof ServerLevel) { + Entity entity = cause.getEntity(); +- Raid currentRaid = this.getCurrentRaid(); +- if (currentRaid != null) { ++ Raid raid = this.getCurrentRaid(); ++ ++ if (raid != null) { + if (this.isPatrolLeader()) { +- currentRaid.removeLeader(this.getWave()); ++ raid.removeLeader(this.getWave()); + } + + if (entity != null && entity.getType() == EntityType.PLAYER) { +- currentRaid.addHeroOfTheVillage(entity); ++ raid.addHeroOfTheVillage(entity); + } + +- currentRaid.removeFromRaid(this, false); ++ raid.removeFromRaid(this, false); + } + +- if (this.isPatrolLeader() && currentRaid == null && ((ServerLevel)this.level()).getRaidAt(this.blockPosition()) == null) { +- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.HEAD); +- Player player = null; ++ if (this.isPatrolLeader() && raid == null && ((ServerLevel) this.level()).getRaidAt(this.blockPosition()) == null) { ++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); ++ Player entityhuman = null; ++ + if (entity instanceof Player) { +- player = (Player)entity; +- } else if (entity instanceof Wolf wolf) { +- LivingEntity owner = wolf.getOwner(); +- if (wolf.isTame() && owner instanceof Player) { +- player = (Player)owner; ++ entityhuman = (Player) entity; ++ } else if (entity instanceof Wolf) { ++ Wolf entitywolf = (Wolf) entity; ++ LivingEntity entityliving = entitywolf.getOwner(); ++ ++ if (entitywolf.isTame() && entityliving instanceof Player) { ++ entityhuman = (Player) entityliving; + } + } + +- if (!itemBySlot.isEmpty() && ItemStack.matches(itemBySlot, Raid.getLeaderBannerInstance()) && player != null) { +- MobEffectInstance effect = player.getEffect(MobEffects.BAD_OMEN); +- int i = 1; +- if (effect != null) { +- i += effect.getAmplifier(); +- player.removeEffectNoUpdate(MobEffects.BAD_OMEN); ++ if (!itemstack.isEmpty() && ItemStack.matches(itemstack, Raid.getLeaderBannerInstance()) && entityhuman != null) { ++ MobEffectInstance mobeffect = entityhuman.getEffect(MobEffects.BAD_OMEN); ++ byte b0 = 1; ++ int i; ++ ++ if (mobeffect != null) { ++ i = b0 + mobeffect.getAmplifier(); ++ entityhuman.removeEffectNoUpdate(MobEffects.BAD_OMEN); + } else { +- i--; ++ i = b0 - 1; + } + + i = Mth.clamp(i, 0, 4); +- MobEffectInstance mobEffectInstance = new MobEffectInstance(MobEffects.BAD_OMEN, 120000, i, false, false, true); ++ MobEffectInstance mobeffect1 = new MobEffectInstance(MobEffects.BAD_OMEN, 120000, i, false, false, true); ++ + if (!this.level().getGameRules().getBoolean(GameRules.RULE_DISABLE_RAIDS)) { +- player.addEffect(mobEffectInstance); ++ entityhuman.addEffect(mobeffect1, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN); // CraftBukkit + } + } + } +@@ -190,11 +201,11 @@ + } + + public boolean isCelebrating() { +- return this.entityData.get(IS_CELEBRATING); ++ return (Boolean) this.entityData.get(Raider.IS_CELEBRATING); + } + + public void setCelebrating(boolean celebrating) { +- this.entityData.set(IS_CELEBRATING, celebrating); ++ this.entityData.set(Raider.IS_CELEBRATING, celebrating); + } + + @Override +@@ -205,6 +216,7 @@ + if (this.raid != null) { + compound.putInt("RaidId", this.raid.getId()); + } ++ + } + + @Override +@@ -214,7 +226,7 @@ + this.canJoinRaid = compound.getBoolean("CanJoinRaid"); + if (compound.contains("RaidId", 3)) { + if (this.level() instanceof ServerLevel) { +- this.raid = ((ServerLevel)this.level()).getRaids().get(compound.getInt("RaidId")); ++ this.raid = ((ServerLevel) this.level()).getRaids().get(compound.getInt("RaidId")); + } + + if (this.raid != null) { +@@ -224,34 +236,38 @@ + } + } + } ++ + } + + @Override + protected void pickUpItem(ItemEntity itemEntity) { +- ItemStack item = itemEntity.getItem(); ++ ItemStack itemstack = itemEntity.getItem(); + boolean flag = this.hasActiveRaid() && this.getCurrentRaid().getLeader(this.getWave()) != null; +- if (this.hasActiveRaid() && !flag && ItemStack.matches(item, Raid.getLeaderBannerInstance())) { +- EquipmentSlot equipmentSlot = EquipmentSlot.HEAD; +- ItemStack itemBySlot = this.getItemBySlot(equipmentSlot); +- double d = (double)this.getEquipmentDropChance(equipmentSlot); +- if (!itemBySlot.isEmpty() && (double)Math.max(this.random.nextFloat() - 0.1F, 0.0F) < d) { +- this.spawnAtLocation(itemBySlot); ++ ++ if (this.hasActiveRaid() && !flag && ItemStack.matches(itemstack, Raid.getLeaderBannerInstance())) { ++ EquipmentSlot enumitemslot = EquipmentSlot.HEAD; ++ ItemStack itemstack1 = this.getItemBySlot(enumitemslot); ++ double d0 = (double) this.getEquipmentDropChance(enumitemslot); ++ ++ if (!itemstack1.isEmpty() && (double) Math.max(this.random.nextFloat() - 0.1F, 0.0F) < d0) { ++ this.spawnAtLocation(itemstack1); + } + + this.onItemPickup(itemEntity); +- this.setItemSlot(equipmentSlot, item); +- this.take(itemEntity, item.getCount()); ++ this.setItemSlot(enumitemslot, itemstack); ++ this.take(itemEntity, itemstack.getCount()); + itemEntity.discard(); + this.getCurrentRaid().setLeader(this.getWave(), this); + this.setPatrolLeader(true); + } else { + super.pickUpItem(itemEntity); + } ++ + } + + @Override + public boolean removeWhenFarAway(double distanceToClosestPlayer) { +- return this.getCurrentRaid() == null && super.removeWhenFarAway(distanceToClosestPlayer); ++ return this.getCurrentRaid() == null ? super.removeWhenFarAway(distanceToClosestPlayer) : false; + } + + @Override +@@ -278,143 +294,176 @@ + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- this.setCanJoinRaid(this.getType() != EntityType.WITCH || reason != MobSpawnType.NATURAL); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ this.setCanJoinRaid(this.getType() != EntityType.WITCH || reason != EnumMobSpawn.NATURAL); + return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + + public abstract SoundEvent getCelebrateSound(); + +- protected class HoldGroundAttackGoal extends Goal { +- private final Raider mob; +- private final float hostileRadiusSqr; +- public final TargetingConditions shoutTargeting = TargetingConditions.forNonCombat().range(8.0).ignoreLineOfSight().ignoreInvisibilityTesting(); ++ public class ObtainRaidLeaderBannerGoal extends Goal { + +- public HoldGroundAttackGoal(AbstractIllager mob, float hostileRadiusSquare) { +- this.mob = mob; +- this.hostileRadiusSqr = hostileRadiusSquare * hostileRadiusSquare; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ private final T mob; ++ ++ public ObtainRaidLeaderBannerGoal(T entityraider) { // CraftBukkit - decompile error ++ this.mob = entityraider; ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override + public boolean canUse() { +- LivingEntity lastHurtByMob = this.mob.getLastHurtByMob(); +- return this.mob.getCurrentRaid() == null +- && this.mob.isPatrolling() +- && this.mob.getTarget() != null +- && !this.mob.isAggressive() +- && (lastHurtByMob == null || lastHurtByMob.getType() != EntityType.PLAYER); +- } ++ Raid raid = this.mob.getCurrentRaid(); + +- @Override +- public void start() { +- super.start(); +- this.mob.getNavigation().stop(); ++ if (this.mob.hasActiveRaid() && !this.mob.getCurrentRaid().isOver() && this.mob.canBeLeader() && !ItemStack.matches(this.mob.getItemBySlot(EquipmentSlot.HEAD), Raid.getLeaderBannerInstance())) { ++ Raider entityraider = raid.getLeader(this.mob.getWave()); + +- for (Raider raider : this.mob +- .level() +- .getNearbyEntities(Raider.class, this.shoutTargeting, this.mob, this.mob.getBoundingBox().inflate(8.0, 8.0, 8.0))) { +- raider.setTarget(this.mob.getTarget()); +- } +- } ++ if (entityraider == null || !entityraider.isAlive()) { ++ List list = this.mob.level().getEntitiesOfClass(ItemEntity.class, this.mob.getBoundingBox().inflate(16.0D, 8.0D, 16.0D), Raider.ALLOWED_ITEMS); + +- @Override +- public void stop() { +- super.stop(); +- LivingEntity target = this.mob.getTarget(); +- if (target != null) { +- for (Raider raider : this.mob +- .level() +- .getNearbyEntities(Raider.class, this.shoutTargeting, this.mob, this.mob.getBoundingBox().inflate(8.0, 8.0, 8.0))) { +- raider.setTarget(target); +- raider.setAggressive(true); ++ if (!list.isEmpty()) { ++ return this.mob.getNavigation().moveTo((Entity) list.get(0), 1.149999976158142D); ++ } + } + +- this.mob.setAggressive(true); ++ return false; ++ } else { ++ return false; + } + } + + @Override +- public boolean requiresUpdateEveryTick() { +- return true; +- } +- +- @Override + public void tick() { +- LivingEntity target = this.mob.getTarget(); +- if (target != null) { +- if (this.mob.distanceToSqr(target) > (double)this.hostileRadiusSqr) { +- this.mob.getLookControl().setLookAt(target, 30.0F, 30.0F); +- if (this.mob.random.nextInt(50) == 0) { +- this.mob.playAmbientSound(); +- } +- } else { +- this.mob.setAggressive(true); +- } ++ if (this.mob.getNavigation().getTargetPos().closerToCenterThan(this.mob.position(), 1.414D)) { ++ List list = this.mob.level().getEntitiesOfClass(ItemEntity.class, this.mob.getBoundingBox().inflate(4.0D, 4.0D, 4.0D), Raider.ALLOWED_ITEMS); + +- super.tick(); ++ if (!list.isEmpty()) { ++ this.mob.pickUpItem((ItemEntity) list.get(0)); ++ } + } ++ + } + } + +- public class ObtainRaidLeaderBannerGoal extends Goal { +- private final T mob; ++ private static class RaiderMoveThroughVillageGoal extends Goal { + +- public ObtainRaidLeaderBannerGoal(T mob) { +- this.mob = mob; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ private final Raider raider; ++ private final double speedModifier; ++ private BlockPos poiPos; ++ private final List visited = Lists.newArrayList(); ++ private final int distanceToPoi; ++ private boolean stuck; ++ ++ public RaiderMoveThroughVillageGoal(Raider raider, double speedModifier, int i) { ++ this.raider = raider; ++ this.speedModifier = speedModifier; ++ this.distanceToPoi = i; ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override + public boolean canUse() { +- Raid currentRaid = this.mob.getCurrentRaid(); +- if (this.mob.hasActiveRaid() +- && !this.mob.getCurrentRaid().isOver() +- && this.mob.canBeLeader() +- && !ItemStack.matches(this.mob.getItemBySlot(EquipmentSlot.HEAD), Raid.getLeaderBannerInstance())) { +- Raider leader = currentRaid.getLeader(this.mob.getWave()); +- if (leader == null || !leader.isAlive()) { +- List entitiesOfClass = this.mob +- .level() +- .getEntitiesOfClass(ItemEntity.class, this.mob.getBoundingBox().inflate(16.0, 8.0, 16.0), Raider.ALLOWED_ITEMS); +- if (!entitiesOfClass.isEmpty()) { +- return this.mob.getNavigation().moveTo(entitiesOfClass.get(0), 1.15F); +- } +- } ++ this.updateVisited(); ++ return this.isValidRaid() && this.hasSuitablePoi() && this.raider.getTarget() == null; ++ } + ++ private boolean isValidRaid() { ++ return this.raider.hasActiveRaid() && !this.raider.getCurrentRaid().isOver(); ++ } ++ ++ private boolean hasSuitablePoi() { ++ ServerLevel worldserver = (ServerLevel) this.raider.level(); ++ BlockPos blockposition = this.raider.blockPosition(); ++ Optional optional = worldserver.getPoiManager().getRandom((holder) -> { ++ return holder.is(PoiTypes.HOME); ++ }, this::hasNotVisited, PoiManager.Occupancy.ANY, blockposition, 48, this.raider.random); ++ ++ if (optional.isEmpty()) { + return false; + } else { +- return false; ++ this.poiPos = ((BlockPos) optional.get()).immutable(); ++ return true; + } + } + + @Override ++ public boolean canContinueToUse() { ++ return this.raider.getNavigation().isDone() ? false : this.raider.getTarget() == null && !this.poiPos.closerToCenterThan(this.raider.position(), (double) (this.raider.getBbWidth() + (float) this.distanceToPoi)) && !this.stuck; ++ } ++ ++ @Override ++ public void stop() { ++ if (this.poiPos.closerToCenterThan(this.raider.position(), (double) this.distanceToPoi)) { ++ this.visited.add(this.poiPos); ++ } ++ ++ } ++ ++ @Override ++ public void start() { ++ super.start(); ++ this.raider.setNoActionTime(0); ++ this.raider.getNavigation().moveTo((double) this.poiPos.getX(), (double) this.poiPos.getY(), (double) this.poiPos.getZ(), this.speedModifier); ++ this.stuck = false; ++ } ++ ++ @Override + public void tick() { +- if (this.mob.getNavigation().getTargetPos().closerToCenterThan(this.mob.position(), 1.414)) { +- List entitiesOfClass = this.mob +- .level() +- .getEntitiesOfClass(ItemEntity.class, this.mob.getBoundingBox().inflate(4.0, 4.0, 4.0), Raider.ALLOWED_ITEMS); +- if (!entitiesOfClass.isEmpty()) { +- this.mob.pickUpItem(entitiesOfClass.get(0)); ++ if (this.raider.getNavigation().isDone()) { ++ Vec3 vec3d = Vec3.atBottomCenterOf(this.poiPos); ++ Vec3 vec3d1 = DefaultRandomPos.getPosTowards(this.raider, 16, 7, vec3d, 0.3141592741012573D); ++ ++ if (vec3d1 == null) { ++ vec3d1 = DefaultRandomPos.getPosTowards(this.raider, 8, 7, vec3d, 1.5707963705062866D); + } ++ ++ if (vec3d1 == null) { ++ this.stuck = true; ++ return; ++ } ++ ++ this.raider.getNavigation().moveTo(vec3d1.x, vec3d1.y, vec3d1.z, this.speedModifier); + } ++ + } ++ ++ private boolean hasNotVisited(BlockPos pos) { ++ Iterator iterator = this.visited.iterator(); ++ ++ BlockPos blockposition1; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return true; ++ } ++ ++ blockposition1 = (BlockPos) iterator.next(); ++ } while (!Objects.equals(pos, blockposition1)); ++ ++ return false; ++ } ++ ++ private void updateVisited() { ++ if (this.visited.size() > 2) { ++ this.visited.remove(0); ++ } ++ ++ } + } + + public class RaiderCelebration extends Goal { ++ + private final Raider mob; + +- RaiderCelebration(Raider mob) { +- this.mob = mob; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ RaiderCelebration(Raider entityraider) { ++ this.mob = entityraider; ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override + public boolean canUse() { +- Raid currentRaid = this.mob.getCurrentRaid(); +- return this.mob.isAlive() && this.mob.getTarget() == null && currentRaid != null && currentRaid.isLoss(); ++ Raid raid = this.mob.getCurrentRaid(); ++ ++ return this.mob.isAlive() && this.mob.getTarget() == null && raid != null && raid.isLoss(); + } + + @Override +@@ -443,99 +492,82 @@ + } + } + +- static class RaiderMoveThroughVillageGoal extends Goal { +- private final Raider raider; +- private final double speedModifier; +- private BlockPos poiPos; +- private final List visited = Lists.newArrayList(); +- private final int distanceToPoi; +- private boolean stuck; ++ protected class HoldGroundAttackGoal extends Goal { + +- public RaiderMoveThroughVillageGoal(Raider raider, double speedModifier, int distanceToPoi) { +- this.raider = raider; +- this.speedModifier = speedModifier; +- this.distanceToPoi = distanceToPoi; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ private final Raider mob; ++ private final float hostileRadiusSqr; ++ public final TargetingConditions shoutTargeting = TargetingConditions.forNonCombat().range(8.0D).ignoreLineOfSight().ignoreInvisibilityTesting(); ++ ++ public HoldGroundAttackGoal(AbstractIllager entityillagerabstract, float f) { ++ this.mob = entityillagerabstract; ++ this.hostileRadiusSqr = f * f; ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + } + + @Override + public boolean canUse() { +- this.updateVisited(); +- return this.isValidRaid() && this.hasSuitablePoi() && this.raider.getTarget() == null; +- } ++ LivingEntity entityliving = this.mob.getLastHurtByMob(); + +- private boolean isValidRaid() { +- return this.raider.hasActiveRaid() && !this.raider.getCurrentRaid().isOver(); ++ return this.mob.getCurrentRaid() == null && this.mob.isPatrolling() && this.mob.getTarget() != null && !this.mob.isAggressive() && (entityliving == null || entityliving.getType() != EntityType.PLAYER); + } + +- private boolean hasSuitablePoi() { +- ServerLevel serverLevel = (ServerLevel)this.raider.level(); +- BlockPos blockPos = this.raider.blockPosition(); +- Optional random = serverLevel.getPoiManager() +- .getRandom(holder -> holder.is(PoiTypes.HOME), this::hasNotVisited, PoiManager.Occupancy.ANY, blockPos, 48, this.raider.random); +- if (random.isEmpty()) { +- return false; +- } else { +- this.poiPos = random.get().immutable(); +- return true; ++ @Override ++ public void start() { ++ super.start(); ++ this.mob.getNavigation().stop(); ++ List list = this.mob.level().getNearbyEntities(Raider.class, this.shoutTargeting, this.mob, this.mob.getBoundingBox().inflate(8.0D, 8.0D, 8.0D)); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Raider entityraider = (Raider) iterator.next(); ++ ++ entityraider.setTarget(this.mob.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.FOLLOW_LEADER, true); // CraftBukkit + } +- } + +- @Override +- public boolean canContinueToUse() { +- return !this.raider.getNavigation().isDone() +- && this.raider.getTarget() == null +- && !this.poiPos.closerToCenterThan(this.raider.position(), (double)(this.raider.getBbWidth() + (float)this.distanceToPoi)) +- && !this.stuck; + } + + @Override + public void stop() { +- if (this.poiPos.closerToCenterThan(this.raider.position(), (double)this.distanceToPoi)) { +- this.visited.add(this.poiPos); ++ super.stop(); ++ LivingEntity entityliving = this.mob.getTarget(); ++ ++ if (entityliving != null) { ++ List list = this.mob.level().getNearbyEntities(Raider.class, this.shoutTargeting, this.mob, this.mob.getBoundingBox().inflate(8.0D, 8.0D, 8.0D)); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Raider entityraider = (Raider) iterator.next(); ++ ++ entityraider.setTarget(this.mob.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.FOLLOW_LEADER, true); // CraftBukkit ++ entityraider.setAggressive(true); ++ } ++ ++ this.mob.setAggressive(true); + } ++ + } + + @Override +- public void start() { +- super.start(); +- this.raider.setNoActionTime(0); +- this.raider.getNavigation().moveTo((double)this.poiPos.getX(), (double)this.poiPos.getY(), (double)this.poiPos.getZ(), this.speedModifier); +- this.stuck = false; ++ public boolean requiresUpdateEveryTick() { ++ return true; + } + + @Override + public void tick() { +- if (this.raider.getNavigation().isDone()) { +- Vec3 vec3 = Vec3.atBottomCenterOf(this.poiPos); +- Vec3 posTowards = DefaultRandomPos.getPosTowards(this.raider, 16, 7, vec3, (float) (Math.PI / 10)); +- if (posTowards == null) { +- posTowards = DefaultRandomPos.getPosTowards(this.raider, 8, 7, vec3, (float) (Math.PI / 2)); +- } ++ LivingEntity entityliving = this.mob.getTarget(); + +- if (posTowards == null) { +- this.stuck = true; +- return; ++ if (entityliving != null) { ++ if (this.mob.distanceToSqr((Entity) entityliving) > (double) this.hostileRadiusSqr) { ++ this.mob.getLookControl().setLookAt(entityliving, 30.0F, 30.0F); ++ if (this.mob.random.nextInt(50) == 0) { ++ this.mob.playAmbientSound(); ++ } ++ } else { ++ this.mob.setAggressive(true); + } + +- this.raider.getNavigation().moveTo(posTowards.x, posTowards.y, posTowards.z, this.speedModifier); ++ super.tick(); + } + } +- +- private boolean hasNotVisited(BlockPos pos) { +- for (BlockPos blockPos : this.visited) { +- if (Objects.equals(pos, blockPos)) { +- return false; +- } +- } +- +- return true; +- } +- +- private void updateVisited() { +- if (this.visited.size() > 2) { +- this.visited.remove(0); +- } +- } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/raid/Raids.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/raid/Raids.java.patch new file mode 100644 index 0000000000..9eda1a872a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/raid/Raids.java.patch @@ -0,0 +1,232 @@ +--- a/net/minecraft/world/entity/raid/Raids.java ++++ b/net/minecraft/world/entity/raid/Raids.java +@@ -27,14 +27,19 @@ + import net.minecraft.world.phys.Vec3; + + public class Raids extends SavedData { ++ + private static final String RAID_FILE_ID = "raids"; +- private final Map raidMap = Maps.newHashMap(); ++ public final Map raidMap = Maps.newHashMap(); + private final ServerLevel level; + private int nextAvailableID; + private int tick; + +- public static SavedData.Factory factory(ServerLevel serverLevel) { +- return new SavedData.Factory<>(() -> new Raids(serverLevel), compoundTag -> load(serverLevel, compoundTag), DataFixTypes.SAVED_DATA_RAIDS); ++ public static SavedData.a factory(ServerLevel worldserver) { ++ return new SavedData.a<>(() -> { ++ return new Raids(worldserver); ++ }, (nbttagcompound) -> { ++ return load(worldserver, nbttagcompound); ++ }, DataFixTypes.SAVED_DATA_RAIDS); + } + + public Raids(ServerLevel level) { +@@ -44,15 +49,16 @@ + } + + public Raid get(int id) { +- return this.raidMap.get(id); ++ return (Raid) this.raidMap.get(id); + } + + public void tick() { +- this.tick++; +- Iterator iterator = this.raidMap.values().iterator(); ++ ++this.tick; ++ Iterator iterator = this.raidMap.values().iterator(); + + while (iterator.hasNext()) { +- Raid raid = iterator.next(); ++ Raid raid = (Raid) iterator.next(); ++ + if (this.level.getGameRules().getBoolean(GameRules.RULE_DISABLE_RAIDS)) { + raid.stop(); + } +@@ -73,13 +79,7 @@ + } + + public static boolean canJoinRaid(Raider raider, Raid raid) { +- return raider != null +- && raid != null +- && raid.getLevel() != null +- && raider.isAlive() +- && raider.canJoinRaid() +- && raider.getNoActionTime() <= 2400 +- && raider.level().dimensionType() == raid.getLevel().dimensionType(); ++ return raider != null && raid != null && raid.getLevel() != null ? raider.isAlive() && raider.canJoinRaid() && raider.getNoActionTime() <= 2400 && raider.level().dimensionType() == raid.getLevel().dimensionType() : false; + } + + @Nullable +@@ -89,50 +89,67 @@ + } else if (this.level.getGameRules().getBoolean(GameRules.RULE_DISABLE_RAIDS)) { + return null; + } else { +- DimensionType dimensionType = serverPlayer.level().dimensionType(); +- if (!dimensionType.hasRaids()) { ++ DimensionType dimensionmanager = serverPlayer.level().dimensionType(); ++ ++ if (!dimensionmanager.hasRaids()) { + return null; + } else { +- BlockPos blockPos = serverPlayer.blockPosition(); +- List list = this.level +- .getPoiManager() +- .getInRange(holder -> holder.is(PoiTypeTags.VILLAGE), blockPos, 64, PoiManager.Occupancy.IS_OCCUPIED) +- .toList(); ++ BlockPos blockposition = serverPlayer.blockPosition(); ++ List list = this.level.getPoiManager().getInRange((holder) -> { ++ return holder.is(PoiTypeTags.VILLAGE); ++ }, blockposition, 64, PoiManager.Occupancy.IS_OCCUPIED).toList(); + int i = 0; +- Vec3 vec3 = Vec3.ZERO; ++ Vec3 vec3d = Vec3.ZERO; + +- for (PoiRecord poiRecord : list) { +- BlockPos pos = poiRecord.getPos(); +- vec3 = vec3.add((double)pos.getX(), (double)pos.getY(), (double)pos.getZ()); +- i++; ++ for (Iterator iterator = list.iterator(); iterator.hasNext(); ++i) { ++ PoiRecord villageplacerecord = (PoiRecord) iterator.next(); ++ BlockPos blockposition1 = villageplacerecord.getPos(); ++ ++ vec3d = vec3d.add((double) blockposition1.getX(), (double) blockposition1.getY(), (double) blockposition1.getZ()); + } + +- BlockPos blockPos1; ++ BlockPos blockposition2; ++ + if (i > 0) { +- vec3 = vec3.scale(1.0 / (double)i); +- blockPos1 = BlockPos.containing(vec3); ++ vec3d = vec3d.scale(1.0D / (double) i); ++ blockposition2 = BlockPos.containing(vec3d); + } else { +- blockPos1 = blockPos; ++ blockposition2 = blockposition; + } + +- Raid raid = this.getOrCreateRaid(serverPlayer.serverLevel(), blockPos1); ++ Raid raid = this.getOrCreateRaid(serverPlayer.serverLevel(), blockposition2); + boolean flag = false; ++ + if (!raid.isStarted()) { ++ /* CraftBukkit - moved down + if (!this.raidMap.containsKey(raid.getId())) { + this.raidMap.put(raid.getId(), raid); + } ++ */ + + flag = true; +- } else if (raid.getBadOmenLevel() < raid.getMaxBadOmenLevel()) { ++ // CraftBukkit start - fixed a bug with raid: players could add up Bad Omen level even when the raid had finished ++ } else if (raid.isInProgress() && raid.getBadOmenLevel() < raid.getMaxBadOmenLevel()) { + flag = true; ++ // CraftBukkit end + } else { + serverPlayer.removeEffect(MobEffects.BAD_OMEN); +- serverPlayer.connection.send(new ClientboundEntityEventPacket(serverPlayer, (byte)43)); ++ serverPlayer.connection.send(new ClientboundEntityEventPacket(serverPlayer, (byte) 43)); + } + + if (flag) { ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callRaidTriggerEvent(raid, serverPlayer)) { ++ serverPlayer.removeEffect(MobEffects.BAD_OMEN); ++ return null; ++ } ++ ++ if (!this.raidMap.containsKey(raid.getId())) { ++ this.raidMap.put(raid.getId(), raid); ++ } ++ // CraftBukkit end + raid.absorbBadOmen(serverPlayer); +- serverPlayer.connection.send(new ClientboundEntityEventPacket(serverPlayer, (byte)43)); ++ serverPlayer.connection.send(new ClientboundEntityEventPacket(serverPlayer, (byte) 43)); + if (!raid.hasFirstWaveSpawned()) { + serverPlayer.awardStat(Stats.RAID_TRIGGER); + CriteriaTriggers.BAD_OMEN.trigger(serverPlayer); +@@ -146,38 +163,44 @@ + } + + private Raid getOrCreateRaid(ServerLevel serverLevel, BlockPos pos) { +- Raid raidAt = serverLevel.getRaidAt(pos); +- return raidAt != null ? raidAt : new Raid(this.getUniqueId(), serverLevel, pos); ++ Raid raid = serverLevel.getRaidAt(pos); ++ ++ return raid != null ? raid : new Raid(this.getUniqueId(), serverLevel, pos); + } + + public static Raids load(ServerLevel level, CompoundTag tag) { +- Raids raids = new Raids(level); +- raids.nextAvailableID = tag.getInt("NextAvailableID"); +- raids.tick = tag.getInt("Tick"); +- ListTag list = tag.getList("Raids", 10); ++ Raids persistentraid = new Raids(level); + +- for (int i = 0; i < list.size(); i++) { +- CompoundTag compound = list.getCompound(i); +- Raid raid = new Raid(level, compound); +- raids.raidMap.put(raid.getId(), raid); ++ persistentraid.nextAvailableID = tag.getInt("NextAvailableID"); ++ persistentraid.tick = tag.getInt("Tick"); ++ ListTag nbttaglist = tag.getList("Raids", 10); ++ ++ for (int i = 0; i < nbttaglist.size(); ++i) { ++ CompoundTag nbttagcompound1 = nbttaglist.getCompound(i); ++ Raid raid = new Raid(level, nbttagcompound1); ++ ++ persistentraid.raidMap.put(raid.getId(), raid); + } + +- return raids; ++ return persistentraid; + } + + @Override + public CompoundTag save(CompoundTag compound) { + compound.putInt("NextAvailableID", this.nextAvailableID); + compound.putInt("Tick", this.tick); +- ListTag list = new ListTag(); ++ ListTag nbttaglist = new ListTag(); ++ Iterator iterator = this.raidMap.values().iterator(); + +- for (Raid raid : this.raidMap.values()) { +- CompoundTag compoundTag = new CompoundTag(); +- raid.save(compoundTag); +- list.add(compoundTag); ++ while (iterator.hasNext()) { ++ Raid raid = (Raid) iterator.next(); ++ CompoundTag nbttagcompound1 = new CompoundTag(); ++ ++ raid.save(nbttagcompound1); ++ nbttaglist.add(nbttagcompound1); + } + +- compound.put("Raids", list); ++ compound.put("Raids", nbttaglist); + return compound; + } + +@@ -192,13 +215,16 @@ + @Nullable + public Raid getNearbyRaid(BlockPos pos, int distance) { + Raid raid = null; +- double d = (double)distance; ++ double d0 = (double) distance; ++ Iterator iterator = this.raidMap.values().iterator(); + +- for (Raid raid1 : this.raidMap.values()) { ++ while (iterator.hasNext()) { ++ Raid raid1 = (Raid) iterator.next(); + double d1 = raid1.getCenter().distSqr(pos); +- if (raid1.isActive() && d1 < d) { ++ ++ if (raid1.isActive() && d1 < d0) { + raid = raid1; +- d = d1; ++ d0 = d1; + } + } + diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/AbstractMinecart.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/AbstractMinecart.java.patch new file mode 100644 index 0000000000..7653e3615f --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/AbstractMinecart.java.patch @@ -0,0 +1,1292 @@ +--- a/net/minecraft/world/entity/vehicle/AbstractMinecart.java ++++ b/net/minecraft/world/entity/vehicle/AbstractMinecart.java +@@ -3,8 +3,9 @@ + import com.google.common.collect.ImmutableList; + import com.google.common.collect.ImmutableMap; + import com.google.common.collect.Maps; ++import com.google.common.collect.UnmodifiableIterator; + import com.mojang.datafixers.util.Pair; +-import java.util.EnumMap; ++import java.util.Iterator; + import java.util.List; + import java.util.Map; + import javax.annotation.Nullable; +@@ -24,15 +25,16 @@ + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.animal.IronGolem; + import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.entity.npc.WanderingTrader; + import net.minecraft.world.entity.player.Player; ++import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; +@@ -40,21 +42,28 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.PoweredRailBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.RailShape; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.Vehicle; ++import org.bukkit.event.vehicle.VehicleEntityCollisionEvent; ++import org.bukkit.util.Vector; ++// CraftBukkit end ++ + public abstract class AbstractMinecart extends VehicleEntity { ++ + private static final float LOWERED_PASSENGER_ATTACHMENT_Y = 0.0F; + private static final float PASSENGER_ATTACHMENT_Y = 0.1875F; + private static final EntityDataAccessor DATA_ID_DISPLAY_BLOCK = SynchedEntityData.defineId(AbstractMinecart.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_ID_DISPLAY_OFFSET = SynchedEntityData.defineId(AbstractMinecart.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_ID_CUSTOM_DISPLAY = SynchedEntityData.defineId(AbstractMinecart.class, EntityDataSerializers.BOOLEAN); +- private static final ImmutableMap> POSE_DISMOUNT_HEIGHTS = ImmutableMap.of( +- Pose.STANDING, ImmutableList.of(0, 1, -1), Pose.CROUCHING, ImmutableList.of(0, 1, -1), Pose.SWIMMING, ImmutableList.of(0, 1) +- ); ++ private static final ImmutableMap> POSE_DISMOUNT_HEIGHTS = ImmutableMap.of(EntityPose.STANDING, ImmutableList.of(0, 1, -1), EntityPose.CROUCHING, ImmutableList.of(0, 1, -1), EntityPose.SWIMMING, ImmutableList.of(0, 1)); + protected static final float WATER_SLOWDOWN_FACTOR = 0.95F; + private boolean flipped; + private boolean onRails; +@@ -64,55 +73,84 @@ + private double lerpZ; + private double lerpYRot; + private double lerpXRot; +- private Vec3 targetDeltaMovement = Vec3.ZERO; +- private static final Map> EXITS = Util.make(Maps.newEnumMap(RailShape.class), map -> { +- Vec3i normal = Direction.WEST.getNormal(); +- Vec3i normal1 = Direction.EAST.getNormal(); +- Vec3i normal2 = Direction.NORTH.getNormal(); +- Vec3i normal3 = Direction.SOUTH.getNormal(); +- Vec3i vec3i = normal.below(); +- Vec3i vec3i1 = normal1.below(); +- Vec3i vec3i2 = normal2.below(); +- Vec3i vec3i3 = normal3.below(); +- map.put(RailShape.NORTH_SOUTH, Pair.of(normal2, normal3)); +- map.put(RailShape.EAST_WEST, Pair.of(normal, normal1)); +- map.put(RailShape.ASCENDING_EAST, Pair.of(vec3i, normal1)); +- map.put(RailShape.ASCENDING_WEST, Pair.of(normal, vec3i1)); +- map.put(RailShape.ASCENDING_NORTH, Pair.of(normal2, vec3i3)); +- map.put(RailShape.ASCENDING_SOUTH, Pair.of(vec3i2, normal3)); +- map.put(RailShape.SOUTH_EAST, Pair.of(normal3, normal1)); +- map.put(RailShape.SOUTH_WEST, Pair.of(normal3, normal)); +- map.put(RailShape.NORTH_WEST, Pair.of(normal2, normal)); +- map.put(RailShape.NORTH_EAST, Pair.of(normal2, normal1)); ++ private Vec3 targetDeltaMovement; ++ private static final Map> EXITS = (Map) Util.make(Maps.newEnumMap(RailShape.class), (enummap) -> { ++ Vec3i baseblockposition = Direction.WEST.getNormal(); ++ Vec3i baseblockposition1 = Direction.EAST.getNormal(); ++ Vec3i baseblockposition2 = Direction.NORTH.getNormal(); ++ Vec3i baseblockposition3 = Direction.SOUTH.getNormal(); ++ Vec3i baseblockposition4 = baseblockposition.below(); ++ Vec3i baseblockposition5 = baseblockposition1.below(); ++ Vec3i baseblockposition6 = baseblockposition2.below(); ++ Vec3i baseblockposition7 = baseblockposition3.below(); ++ ++ enummap.put(RailShape.NORTH_SOUTH, Pair.of(baseblockposition2, baseblockposition3)); ++ enummap.put(RailShape.EAST_WEST, Pair.of(baseblockposition, baseblockposition1)); ++ enummap.put(RailShape.ASCENDING_EAST, Pair.of(baseblockposition4, baseblockposition1)); ++ enummap.put(RailShape.ASCENDING_WEST, Pair.of(baseblockposition, baseblockposition5)); ++ enummap.put(RailShape.ASCENDING_NORTH, Pair.of(baseblockposition2, baseblockposition7)); ++ enummap.put(RailShape.ASCENDING_SOUTH, Pair.of(baseblockposition6, baseblockposition3)); ++ enummap.put(RailShape.SOUTH_EAST, Pair.of(baseblockposition3, baseblockposition1)); ++ enummap.put(RailShape.SOUTH_WEST, Pair.of(baseblockposition3, baseblockposition)); ++ enummap.put(RailShape.NORTH_WEST, Pair.of(baseblockposition2, baseblockposition)); ++ enummap.put(RailShape.NORTH_EAST, Pair.of(baseblockposition2, baseblockposition1)); + }); + ++ // CraftBukkit start ++ public boolean slowWhenEmpty = true; ++ private double derailedX = 0.5; ++ private double derailedY = 0.5; ++ private double derailedZ = 0.5; ++ private double flyingX = 0.95; ++ private double flyingY = 0.95; ++ private double flyingZ = 0.95; ++ public double maxSpeed = 0.4D; ++ // CraftBukkit end ++ + protected AbstractMinecart(EntityType entityType, Level level) { + super(entityType, level); ++ this.targetDeltaMovement = Vec3.ZERO; + this.blocksBuilding = true; + } + +- protected AbstractMinecart(EntityType entityType, Level level, double x, double y, double z) { ++ protected AbstractMinecart(EntityType entityType, Level level, double x, double d1, double y) { + this(entityType, level); +- this.setPos(x, y, z); ++ this.setPos(x, d1, y); + this.xo = x; +- this.yo = y; +- this.zo = z; ++ this.yo = d1; ++ this.zo = y; + } + +- public static AbstractMinecart createMinecart( +- ServerLevel serverLevel, double d, double d1, double d2, AbstractMinecart.Type type, ItemStack itemStack, @Nullable Player player +- ) { +- AbstractMinecart abstractMinecart = (AbstractMinecart)(switch (type) { +- case CHEST -> new MinecartChest(serverLevel, d, d1, d2); +- case FURNACE -> new MinecartFurnace(serverLevel, d, d1, d2); +- case TNT -> new MinecartTNT(serverLevel, d, d1, d2); +- case SPAWNER -> new MinecartSpawner(serverLevel, d, d1, d2); +- case HOPPER -> new MinecartHopper(serverLevel, d, d1, d2); +- case COMMAND_BLOCK -> new MinecartCommandBlock(serverLevel, d, d1, d2); +- default -> new Minecart(serverLevel, d, d1, d2); +- }); +- EntityType.createDefaultStackConfig(serverLevel, itemStack, player).accept(abstractMinecart); +- return abstractMinecart; ++ public static AbstractMinecart createMinecart(ServerLevel worldserver, double d0, double d1, double d2, AbstractMinecart.EnumMinecartType entityminecartabstract_enumminecarttype, ItemStack itemstack, @Nullable Player entityhuman) { ++ Object object; ++ ++ switch (entityminecartabstract_enumminecarttype) { ++ case CHEST: ++ object = new MinecartChest(worldserver, d0, d1, d2); ++ break; ++ case FURNACE: ++ object = new MinecartFurnace(worldserver, d0, d1, d2); ++ break; ++ case TNT: ++ object = new MinecartTNT(worldserver, d0, d1, d2); ++ break; ++ case SPAWNER: ++ object = new MinecartSpawner(worldserver, d0, d1, d2); ++ break; ++ case HOPPER: ++ object = new MinecartHopper(worldserver, d0, d1, d2); ++ break; ++ case COMMAND_BLOCK: ++ object = new MinecartCommandBlock(worldserver, d0, d1, d2); ++ break; ++ default: ++ object = new Minecart(worldserver, d0, d1, d2); ++ } ++ ++ AbstractMinecart object1 = (AbstractMinecart) object; // CraftBukkit- decompile error ++ ++ EntityType.createDefaultStackConfig(worldserver, itemstack, entityhuman).accept(object1); ++ return (AbstractMinecart) object1; + } + + @Override +@@ -123,9 +161,9 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_ID_DISPLAY_BLOCK, Block.getId(Blocks.AIR.defaultBlockState())); +- this.entityData.define(DATA_ID_DISPLAY_OFFSET, 6); +- this.entityData.define(DATA_ID_CUSTOM_DISPLAY, false); ++ this.entityData.define(AbstractMinecart.DATA_ID_DISPLAY_BLOCK, Block.getId(Blocks.AIR.defaultBlockState())); ++ this.entityData.define(AbstractMinecart.DATA_ID_DISPLAY_OFFSET, 6); ++ this.entityData.define(AbstractMinecart.DATA_ID_CUSTOM_DISPLAY, false); + } + + @Override +@@ -144,55 +182,72 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { + boolean flag = entity instanceof Villager || entity instanceof WanderingTrader; ++ + return new Vector3f(0.0F, flag ? 0.0F : 0.1875F, 0.0F); + } + + @Override + public Vec3 getDismountLocationForPassenger(LivingEntity livingEntity) { +- Direction motionDirection = this.getMotionDirection(); +- if (motionDirection.getAxis() == Direction.Axis.Y) { ++ Direction enumdirection = this.getMotionDirection(); ++ ++ if (enumdirection.getAxis() == Direction.Axis.Y) { + return super.getDismountLocationForPassenger(livingEntity); + } else { +- int[][] ints = DismountHelper.offsetsForDirection(motionDirection); +- BlockPos blockPos = this.blockPosition(); +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); +- ImmutableList dismountPoses = livingEntity.getDismountPoses(); ++ int[][] aint = DismountHelper.offsetsForDirection(enumdirection); ++ BlockPos blockposition = this.blockPosition(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ ImmutableList immutablelist = livingEntity.getDismountPoses(); ++ UnmodifiableIterator unmodifiableiterator = immutablelist.iterator(); + +- for (Pose pose : dismountPoses) { +- EntityDimensions dimensions = livingEntity.getDimensions(pose); +- float f = Math.min(dimensions.width, 1.0F) / 2.0F; ++ while (unmodifiableiterator.hasNext()) { ++ EntityPose entitypose = (EntityPose) unmodifiableiterator.next(); ++ EntityDimensions entitysize = livingEntity.getDimensions(entitypose); ++ float f = Math.min(entitysize.width, 1.0F) / 2.0F; ++ UnmodifiableIterator unmodifiableiterator1 = ((ImmutableList) AbstractMinecart.POSE_DISMOUNT_HEIGHTS.get(entitypose)).iterator(); + +- for (int i : POSE_DISMOUNT_HEIGHTS.get(pose)) { +- for (int[] ints1 : ints) { +- mutableBlockPos.set(blockPos.getX() + ints1[0], blockPos.getY() + i, blockPos.getZ() + ints1[1]); +- double blockFloorHeight = this.level() +- .getBlockFloorHeight( +- DismountHelper.nonClimbableShape(this.level(), mutableBlockPos), +- () -> DismountHelper.nonClimbableShape(this.level(), mutableBlockPos.below()) +- ); +- if (DismountHelper.isBlockFloorValid(blockFloorHeight)) { +- AABB aABB = new AABB((double)(-f), 0.0, (double)(-f), (double)f, (double)dimensions.height, (double)f); +- Vec3 vec3 = Vec3.upFromBottomCenterOf(mutableBlockPos, blockFloorHeight); +- if (DismountHelper.canDismountTo(this.level(), livingEntity, aABB.move(vec3))) { +- livingEntity.setPose(pose); +- return vec3; ++ while (unmodifiableiterator1.hasNext()) { ++ int i = (Integer) unmodifiableiterator1.next(); ++ int[][] aint1 = aint; ++ int j = aint.length; ++ ++ for (int k = 0; k < j; ++k) { ++ int[] aint2 = aint1[k]; ++ ++ blockposition_mutableblockposition.set(blockposition.getX() + aint2[0], blockposition.getY() + i, blockposition.getZ() + aint2[1]); ++ double d0 = this.level().getBlockFloorHeight(DismountHelper.nonClimbableShape(this.level(), blockposition_mutableblockposition), () -> { ++ return DismountHelper.nonClimbableShape(this.level(), blockposition_mutableblockposition.below()); ++ }); ++ ++ if (DismountHelper.isBlockFloorValid(d0)) { ++ AABB axisalignedbb = new AABB((double) (-f), 0.0D, (double) (-f), (double) f, (double) entitysize.height, (double) f); ++ Vec3 vec3d = Vec3.upFromBottomCenterOf(blockposition_mutableblockposition, d0); ++ ++ if (DismountHelper.canDismountTo(this.level(), livingEntity, axisalignedbb.move(vec3d))) { ++ livingEntity.setPose(entitypose); ++ return vec3d; + } + } + } + } + } + +- double d = this.getBoundingBox().maxY; +- mutableBlockPos.set((double)blockPos.getX(), d, (double)blockPos.getZ()); ++ double d1 = this.getBoundingBox().maxY; + +- for (Pose pose1 : dismountPoses) { +- double d1 = (double)livingEntity.getDimensions(pose1).height; +- int ceil = Mth.ceil(d - (double)mutableBlockPos.getY() + d1); +- double d2 = DismountHelper.findCeilingFrom(mutableBlockPos, ceil, pos -> this.level().getBlockState(pos).getCollisionShape(this.level(), pos)); +- if (d + d1 <= d2) { +- livingEntity.setPose(pose1); ++ blockposition_mutableblockposition.set((double) blockposition.getX(), d1, (double) blockposition.getZ()); ++ UnmodifiableIterator unmodifiableiterator2 = immutablelist.iterator(); ++ ++ while (unmodifiableiterator2.hasNext()) { ++ EntityPose entitypose1 = (EntityPose) unmodifiableiterator2.next(); ++ double d2 = (double) livingEntity.getDimensions(entitypose1).height; ++ int l = Mth.ceil(d1 - (double) blockposition_mutableblockposition.getY() + d2); ++ double d3 = DismountHelper.findCeilingFrom(blockposition_mutableblockposition, l, (blockposition1) -> { ++ return this.level().getBlockState(blockposition1).getCollisionShape(this.level(), blockposition1); ++ }); ++ ++ if (d1 + d2 <= d3) { ++ livingEntity.setPose(entitypose1); + break; + } + } +@@ -203,8 +258,9 @@ + + @Override + protected float getBlockSpeedFactor() { +- BlockState blockState = this.level().getBlockState(this.blockPosition()); +- return blockState.is(BlockTags.RAILS) ? 1.0F : super.getBlockSpeedFactor(); ++ IBlockData iblockdata = this.level().getBlockState(this.blockPosition()); ++ ++ return iblockdata.is(BlockTags.RAILS) ? 1.0F : super.getBlockSpeedFactor(); + } + + @Override +@@ -220,7 +276,7 @@ + } + + private static Pair exits(RailShape shape) { +- return EXITS.get(shape); ++ return (Pair) AbstractMinecart.EXITS.get(shape); + } + + @Override +@@ -230,6 +286,14 @@ + + @Override + public void tick() { ++ // CraftBukkit start ++ double prevX = this.getX(); ++ double prevY = this.getY(); ++ double prevZ = this.getZ(); ++ float prevYaw = this.getYRot(); ++ float prevPitch = this.getXRot(); ++ // CraftBukkit end ++ + if (this.getHurtTime() > 0) { + this.setHurtTime(this.getHurtTime() - 1); + } +@@ -239,35 +303,39 @@ + } + + this.checkBelowWorld(); +- this.handleNetherPortal(); ++ // this.handleNetherPortal(); // CraftBukkit - handled in postTick + if (this.level().isClientSide) { + if (this.lerpSteps > 0) { + this.lerpPositionAndRotationStep(this.lerpSteps, this.lerpX, this.lerpY, this.lerpZ, this.lerpYRot, this.lerpXRot); +- this.lerpSteps--; ++ --this.lerpSteps; + } else { + this.reapplyPosition(); + this.setRot(this.getYRot(), this.getXRot()); + } ++ + } else { + if (!this.isNoGravity()) { +- double d = this.isInWater() ? -0.005 : -0.04; +- this.setDeltaMovement(this.getDeltaMovement().add(0.0, d, 0.0)); ++ double d0 = this.isInWater() ? -0.005D : -0.04D; ++ ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, d0, 0.0D)); + } + +- int floor = Mth.floor(this.getX()); +- int floor1 = Mth.floor(this.getY()); +- int floor2 = Mth.floor(this.getZ()); +- if (this.level().getBlockState(new BlockPos(floor, floor1 - 1, floor2)).is(BlockTags.RAILS)) { +- floor1--; ++ int i = Mth.floor(this.getX()); ++ int j = Mth.floor(this.getY()); ++ int k = Mth.floor(this.getZ()); ++ ++ if (this.level().getBlockState(new BlockPos(i, j - 1, k)).is(BlockTags.RAILS)) { ++ --j; + } + +- BlockPos blockPos = new BlockPos(floor, floor1, floor2); +- BlockState blockState = this.level().getBlockState(blockPos); +- this.onRails = BaseRailBlock.isRail(blockState); ++ BlockPos blockposition = new BlockPos(i, j, k); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); ++ ++ this.onRails = BaseRailBlock.isRail(iblockdata); + if (this.onRails) { +- this.moveAlongTrack(blockPos, blockState); +- if (blockState.is(Blocks.ACTIVATOR_RAIL)) { +- this.activateMinecart(floor, floor1, floor2, blockState.getValue(PoweredRailBlock.POWERED)); ++ this.moveAlongTrack(blockposition, iblockdata); ++ if (iblockdata.is(Blocks.ACTIVATOR_RAIL)) { ++ this.activateMinecart(i, j, k, (Boolean) iblockdata.getValue(PoweredRailBlock.POWERED)); + } + } else { + this.comeOffTrack(); +@@ -277,38 +345,83 @@ + this.setXRot(0.0F); + double d1 = this.xo - this.getX(); + double d2 = this.zo - this.getZ(); +- if (d1 * d1 + d2 * d2 > 0.001) { +- this.setYRot((float)(Mth.atan2(d2, d1) * 180.0 / Math.PI)); ++ ++ if (d1 * d1 + d2 * d2 > 0.001D) { ++ this.setYRot((float) (Mth.atan2(d2, d1) * 180.0D / 3.141592653589793D)); + if (this.flipped) { + this.setYRot(this.getYRot() + 180.0F); + } + } + +- double d3 = (double)Mth.wrapDegrees(this.getYRot() - this.yRotO); +- if (d3 < -170.0 || d3 >= 170.0) { ++ double d3 = (double) Mth.wrapDegrees(this.getYRot() - this.yRotO); ++ ++ if (d3 < -170.0D || d3 >= 170.0D) { + this.setYRot(this.getYRot() + 180.0F); + this.flipped = !this.flipped; + } + + this.setRot(this.getYRot(), this.getXRot()); +- if (this.getMinecartType() == AbstractMinecart.Type.RIDEABLE && this.getDeltaMovement().horizontalDistanceSqr() > 0.01) { +- List entities = this.level().getEntities(this, this.getBoundingBox().inflate(0.2F, 0.0, 0.2F), EntitySelector.pushableBy(this)); +- if (!entities.isEmpty()) { +- for (Entity entity : entities) { +- if (!(entity instanceof Player) +- && !(entity instanceof IronGolem) +- && !(entity instanceof AbstractMinecart) +- && !this.isVehicle() +- && !entity.isPassenger()) { ++ // CraftBukkit start ++ org.bukkit.World bworld = this.level().getWorld(); ++ Location from = new Location(bworld, prevX, prevY, prevZ, prevYaw, prevPitch); ++ Location to = CraftLocation.toBukkit(this.position(), bworld, this.getYRot(), this.getXRot()); ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ ++ this.level().getCraftServer().getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleUpdateEvent(vehicle)); ++ ++ if (!from.equals(to)) { ++ this.level().getCraftServer().getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleMoveEvent(vehicle, from, to)); ++ } ++ // CraftBukkit end ++ if (this.getMinecartType() == AbstractMinecart.EnumMinecartType.RIDEABLE && this.getDeltaMovement().horizontalDistanceSqr() > 0.01D) { ++ List list = this.level().getEntities((Entity) this, this.getBoundingBox().inflate(0.20000000298023224D, 0.0D, 0.20000000298023224D), EntitySelector.pushableBy(this)); ++ ++ if (!list.isEmpty()) { ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ ++ if (!(entity instanceof Player) && !(entity instanceof IronGolem) && !(entity instanceof AbstractMinecart) && !this.isVehicle() && !entity.isPassenger()) { ++ // CraftBukkit start ++ VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(collisionEvent); ++ ++ if (collisionEvent.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end + entity.startRiding(this); + } else { ++ // CraftBukkit start ++ if (!this.isPassengerOfSameVehicle(entity)) { ++ VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(collisionEvent); ++ ++ if (collisionEvent.isCancelled()) { ++ continue; ++ } ++ } ++ // CraftBukkit end + entity.push(this); + } + } + } + } else { +- for (Entity entity1 : this.level().getEntities(this, this.getBoundingBox().inflate(0.2F, 0.0, 0.2F))) { ++ Iterator iterator1 = this.level().getEntities(this, this.getBoundingBox().inflate(0.20000000298023224D, 0.0D, 0.20000000298023224D)).iterator(); ++ ++ while (iterator1.hasNext()) { ++ Entity entity1 = (Entity) iterator1.next(); ++ + if (!this.hasPassenger(entity1) && entity1.isPushable() && entity1 instanceof AbstractMinecart) { ++ // CraftBukkit start ++ VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, entity1.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(collisionEvent); ++ ++ if (collisionEvent.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end + entity1.push(this); + } + } +@@ -325,183 +438,210 @@ + } + + protected double getMaxSpeed() { +- return (this.isInWater() ? 4.0 : 8.0) / 20.0; ++ return (this.isInWater() ? this.maxSpeed / 2.0D: this.maxSpeed); // CraftBukkit + } + +- public void activateMinecart(int x, int y, int z, boolean powered) { +- } ++ public void activateMinecart(int x, int y, int z, boolean powered) {} + + protected void comeOffTrack() { +- double maxSpeed = this.getMaxSpeed(); +- Vec3 deltaMovement = this.getDeltaMovement(); +- this.setDeltaMovement(Mth.clamp(deltaMovement.x, -maxSpeed, maxSpeed), deltaMovement.y, Mth.clamp(deltaMovement.z, -maxSpeed, maxSpeed)); ++ double d0 = this.getMaxSpeed(); ++ Vec3 vec3d = this.getDeltaMovement(); ++ ++ this.setDeltaMovement(Mth.clamp(vec3d.x, -d0, d0), vec3d.y, Mth.clamp(vec3d.z, -d0, d0)); + if (this.onGround()) { +- this.setDeltaMovement(this.getDeltaMovement().scale(0.5)); ++ // CraftBukkit start - replace magic numbers with our variables ++ this.setDeltaMovement(new Vec3(this.getDeltaMovement().x * this.derailedX, this.getDeltaMovement().y * this.derailedY, this.getDeltaMovement().z * this.derailedZ)); ++ // CraftBukkit end + } + +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + if (!this.onGround()) { +- this.setDeltaMovement(this.getDeltaMovement().scale(0.95)); ++ // CraftBukkit start - replace magic numbers with our variables ++ this.setDeltaMovement(new Vec3(this.getDeltaMovement().x * this.flyingX, this.getDeltaMovement().y * this.flyingY, this.getDeltaMovement().z * this.flyingZ)); ++ // CraftBukkit end + } ++ + } + +- protected void moveAlongTrack(BlockPos pos, BlockState state) { ++ protected void moveAlongTrack(BlockPos pos, IBlockData state) { + this.resetFallDistance(); +- double x = this.getX(); +- double y = this.getY(); +- double z = this.getZ(); +- Vec3 pos1 = this.getPos(x, y, z); +- double var56 = (double)pos.getY(); ++ double d0 = this.getX(); ++ double d1 = this.getY(); ++ double d2 = this.getZ(); ++ Vec3 vec3d = this.getPos(d0, d1, d2); ++ ++ d1 = (double) pos.getY(); + boolean flag = false; + boolean flag1 = false; ++ + if (state.is(Blocks.POWERED_RAIL)) { +- flag = state.getValue(PoweredRailBlock.POWERED); ++ flag = (Boolean) state.getValue(PoweredRailBlock.POWERED); + flag1 = !flag; + } + +- double d = 0.0078125; ++ double d3 = 0.0078125D; ++ + if (this.isInWater()) { +- d *= 0.2; ++ d3 *= 0.2D; + } + +- Vec3 deltaMovement = this.getDeltaMovement(); +- RailShape railShape = state.getValue(((BaseRailBlock)state.getBlock()).getShapeProperty()); +- switch (railShape) { ++ Vec3 vec3d1 = this.getDeltaMovement(); ++ RailShape blockpropertytrackposition = (RailShape) state.getValue(((BaseRailBlock) state.getBlock()).getShapeProperty()); ++ ++ switch (blockpropertytrackposition) { + case ASCENDING_EAST: +- this.setDeltaMovement(deltaMovement.add(-d, 0.0, 0.0)); +- var56++; ++ this.setDeltaMovement(vec3d1.add(-d3, 0.0D, 0.0D)); ++ ++d1; + break; + case ASCENDING_WEST: +- this.setDeltaMovement(deltaMovement.add(d, 0.0, 0.0)); +- var56++; ++ this.setDeltaMovement(vec3d1.add(d3, 0.0D, 0.0D)); ++ ++d1; + break; + case ASCENDING_NORTH: +- this.setDeltaMovement(deltaMovement.add(0.0, 0.0, d)); +- var56++; ++ this.setDeltaMovement(vec3d1.add(0.0D, 0.0D, d3)); ++ ++d1; + break; + case ASCENDING_SOUTH: +- this.setDeltaMovement(deltaMovement.add(0.0, 0.0, -d)); +- var56++; ++ this.setDeltaMovement(vec3d1.add(0.0D, 0.0D, -d3)); ++ ++d1; + } + +- deltaMovement = this.getDeltaMovement(); +- Pair pair = exits(railShape); +- Vec3i vec3i = pair.getFirst(); +- Vec3i vec3i1 = pair.getSecond(); +- double d1 = (double)(vec3i1.getX() - vec3i.getX()); +- double d2 = (double)(vec3i1.getZ() - vec3i.getZ()); +- double squareRoot = Math.sqrt(d1 * d1 + d2 * d2); +- double d3 = deltaMovement.x * d1 + deltaMovement.z * d2; +- if (d3 < 0.0) { +- d1 = -d1; +- d2 = -d2; ++ vec3d1 = this.getDeltaMovement(); ++ Pair pair = exits(blockpropertytrackposition); ++ Vec3i baseblockposition = (Vec3i) pair.getFirst(); ++ Vec3i baseblockposition1 = (Vec3i) pair.getSecond(); ++ double d4 = (double) (baseblockposition1.getX() - baseblockposition.getX()); ++ double d5 = (double) (baseblockposition1.getZ() - baseblockposition.getZ()); ++ double d6 = Math.sqrt(d4 * d4 + d5 * d5); ++ double d7 = vec3d1.x * d4 + vec3d1.z * d5; ++ ++ if (d7 < 0.0D) { ++ d4 = -d4; ++ d5 = -d5; + } + +- double min = Math.min(2.0, deltaMovement.horizontalDistance()); +- deltaMovement = new Vec3(min * d1 / squareRoot, deltaMovement.y, min * d2 / squareRoot); +- this.setDeltaMovement(deltaMovement); +- Entity firstPassenger = this.getFirstPassenger(); +- if (firstPassenger instanceof Player) { +- Vec3 deltaMovement1 = firstPassenger.getDeltaMovement(); +- double d4 = deltaMovement1.horizontalDistanceSqr(); +- double d5 = this.getDeltaMovement().horizontalDistanceSqr(); +- if (d4 > 1.0E-4 && d5 < 0.01) { +- this.setDeltaMovement(this.getDeltaMovement().add(deltaMovement1.x * 0.1, 0.0, deltaMovement1.z * 0.1)); ++ double d8 = Math.min(2.0D, vec3d1.horizontalDistance()); ++ ++ vec3d1 = new Vec3(d8 * d4 / d6, vec3d1.y, d8 * d5 / d6); ++ this.setDeltaMovement(vec3d1); ++ Entity entity = this.getFirstPassenger(); ++ ++ if (entity instanceof Player) { ++ Vec3 vec3d2 = entity.getDeltaMovement(); ++ double d9 = vec3d2.horizontalDistanceSqr(); ++ double d10 = this.getDeltaMovement().horizontalDistanceSqr(); ++ ++ if (d9 > 1.0E-4D && d10 < 0.01D) { ++ this.setDeltaMovement(this.getDeltaMovement().add(vec3d2.x * 0.1D, 0.0D, vec3d2.z * 0.1D)); + flag1 = false; + } + } + ++ double d11; ++ + if (flag1) { +- double d6 = this.getDeltaMovement().horizontalDistance(); +- if (d6 < 0.03) { ++ d11 = this.getDeltaMovement().horizontalDistance(); ++ if (d11 < 0.03D) { + this.setDeltaMovement(Vec3.ZERO); + } else { +- this.setDeltaMovement(this.getDeltaMovement().multiply(0.5, 0.0, 0.5)); ++ this.setDeltaMovement(this.getDeltaMovement().multiply(0.5D, 0.0D, 0.5D)); + } + } + +- double d6 = (double)pos.getX() + 0.5 + (double)vec3i.getX() * 0.5; +- double d7 = (double)pos.getZ() + 0.5 + (double)vec3i.getZ() * 0.5; +- double d8 = (double)pos.getX() + 0.5 + (double)vec3i1.getX() * 0.5; +- double d9 = (double)pos.getZ() + 0.5 + (double)vec3i1.getZ() * 0.5; +- d1 = d8 - d6; +- d2 = d9 - d7; +- double d10; +- if (d1 == 0.0) { +- d10 = z - (double)pos.getZ(); +- } else if (d2 == 0.0) { +- d10 = x - (double)pos.getX(); ++ d11 = (double) pos.getX() + 0.5D + (double) baseblockposition.getX() * 0.5D; ++ double d12 = (double) pos.getZ() + 0.5D + (double) baseblockposition.getZ() * 0.5D; ++ double d13 = (double) pos.getX() + 0.5D + (double) baseblockposition1.getX() * 0.5D; ++ double d14 = (double) pos.getZ() + 0.5D + (double) baseblockposition1.getZ() * 0.5D; ++ ++ d4 = d13 - d11; ++ d5 = d14 - d12; ++ double d15; ++ double d16; ++ double d17; ++ ++ if (d4 == 0.0D) { ++ d15 = d2 - (double) pos.getZ(); ++ } else if (d5 == 0.0D) { ++ d15 = d0 - (double) pos.getX(); + } else { +- double d11 = x - d6; +- double d12 = z - d7; +- d10 = (d11 * d1 + d12 * d2) * 2.0; ++ d16 = d0 - d11; ++ d17 = d2 - d12; ++ d15 = (d16 * d4 + d17 * d5) * 2.0D; + } + +- x = d6 + d1 * d10; +- z = d7 + d2 * d10; +- this.setPos(x, var56, z); +- double d11 = this.isVehicle() ? 0.75 : 1.0; +- double d12 = this.getMaxSpeed(); +- deltaMovement = this.getDeltaMovement(); +- this.move(MoverType.SELF, new Vec3(Mth.clamp(d11 * deltaMovement.x, -d12, d12), 0.0, Mth.clamp(d11 * deltaMovement.z, -d12, d12))); +- if (vec3i.getY() != 0 && Mth.floor(this.getX()) - pos.getX() == vec3i.getX() && Mth.floor(this.getZ()) - pos.getZ() == vec3i.getZ()) { +- this.setPos(this.getX(), this.getY() + (double)vec3i.getY(), this.getZ()); +- } else if (vec3i1.getY() != 0 && Mth.floor(this.getX()) - pos.getX() == vec3i1.getX() && Mth.floor(this.getZ()) - pos.getZ() == vec3i1.getZ()) { +- this.setPos(this.getX(), this.getY() + (double)vec3i1.getY(), this.getZ()); ++ d0 = d11 + d4 * d15; ++ d2 = d12 + d5 * d15; ++ this.setPos(d0, d1, d2); ++ d16 = this.isVehicle() ? 0.75D : 1.0D; ++ d17 = this.getMaxSpeed(); ++ vec3d1 = this.getDeltaMovement(); ++ this.move(EnumMoveType.SELF, new Vec3(Mth.clamp(d16 * vec3d1.x, -d17, d17), 0.0D, Mth.clamp(d16 * vec3d1.z, -d17, d17))); ++ if (baseblockposition.getY() != 0 && Mth.floor(this.getX()) - pos.getX() == baseblockposition.getX() && Mth.floor(this.getZ()) - pos.getZ() == baseblockposition.getZ()) { ++ this.setPos(this.getX(), this.getY() + (double) baseblockposition.getY(), this.getZ()); ++ } else if (baseblockposition1.getY() != 0 && Mth.floor(this.getX()) - pos.getX() == baseblockposition1.getX() && Mth.floor(this.getZ()) - pos.getZ() == baseblockposition1.getZ()) { ++ this.setPos(this.getX(), this.getY() + (double) baseblockposition1.getY(), this.getZ()); + } + + this.applyNaturalSlowdown(); +- Vec3 pos2 = this.getPos(this.getX(), this.getY(), this.getZ()); +- if (pos2 != null && pos1 != null) { +- double d13 = (pos1.y - pos2.y) * 0.05; +- Vec3 deltaMovement2 = this.getDeltaMovement(); +- double d14 = deltaMovement2.horizontalDistance(); +- if (d14 > 0.0) { +- this.setDeltaMovement(deltaMovement2.multiply((d14 + d13) / d14, 1.0, (d14 + d13) / d14)); ++ Vec3 vec3d3 = this.getPos(this.getX(), this.getY(), this.getZ()); ++ Vec3 vec3d4; ++ double d18; ++ ++ if (vec3d3 != null && vec3d != null) { ++ double d19 = (vec3d.y - vec3d3.y) * 0.05D; ++ ++ vec3d4 = this.getDeltaMovement(); ++ d18 = vec3d4.horizontalDistance(); ++ if (d18 > 0.0D) { ++ this.setDeltaMovement(vec3d4.multiply((d18 + d19) / d18, 1.0D, (d18 + d19) / d18)); + } + +- this.setPos(this.getX(), pos2.y, this.getZ()); ++ this.setPos(this.getX(), vec3d3.y, this.getZ()); + } + +- int floor = Mth.floor(this.getX()); +- int floor1 = Mth.floor(this.getZ()); +- if (floor != pos.getX() || floor1 != pos.getZ()) { +- Vec3 deltaMovement2 = this.getDeltaMovement(); +- double d14 = deltaMovement2.horizontalDistance(); +- this.setDeltaMovement(d14 * (double)(floor - pos.getX()), deltaMovement2.y, d14 * (double)(floor1 - pos.getZ())); ++ int i = Mth.floor(this.getX()); ++ int j = Mth.floor(this.getZ()); ++ ++ if (i != pos.getX() || j != pos.getZ()) { ++ vec3d4 = this.getDeltaMovement(); ++ d18 = vec3d4.horizontalDistance(); ++ this.setDeltaMovement(d18 * (double) (i - pos.getX()), vec3d4.y, d18 * (double) (j - pos.getZ())); + } + + if (flag) { +- Vec3 deltaMovement2 = this.getDeltaMovement(); +- double d14 = deltaMovement2.horizontalDistance(); +- if (d14 > 0.01) { +- double d15 = 0.06; +- this.setDeltaMovement(deltaMovement2.add(deltaMovement2.x / d14 * 0.06, 0.0, deltaMovement2.z / d14 * 0.06)); ++ vec3d4 = this.getDeltaMovement(); ++ d18 = vec3d4.horizontalDistance(); ++ if (d18 > 0.01D) { ++ double d20 = 0.06D; ++ ++ this.setDeltaMovement(vec3d4.add(vec3d4.x / d18 * 0.06D, 0.0D, vec3d4.z / d18 * 0.06D)); + } else { +- Vec3 deltaMovement3 = this.getDeltaMovement(); +- double d16 = deltaMovement3.x; +- double d17 = deltaMovement3.z; +- if (railShape == RailShape.EAST_WEST) { ++ Vec3 vec3d5 = this.getDeltaMovement(); ++ double d21 = vec3d5.x; ++ double d22 = vec3d5.z; ++ ++ if (blockpropertytrackposition == RailShape.EAST_WEST) { + if (this.isRedstoneConductor(pos.west())) { +- d16 = 0.02; ++ d21 = 0.02D; + } else if (this.isRedstoneConductor(pos.east())) { +- d16 = -0.02; ++ d21 = -0.02D; + } + } else { +- if (railShape != RailShape.NORTH_SOUTH) { ++ if (blockpropertytrackposition != RailShape.NORTH_SOUTH) { + return; + } + + if (this.isRedstoneConductor(pos.north())) { +- d17 = 0.02; ++ d22 = 0.02D; + } else if (this.isRedstoneConductor(pos.south())) { +- d17 = -0.02; ++ d22 = -0.02D; + } + } + +- this.setDeltaMovement(d16, deltaMovement3.y, d17); ++ this.setDeltaMovement(d21, vec3d5.y, d22); + } + } ++ + } + + @Override +@@ -514,100 +654,109 @@ + } + + protected void applyNaturalSlowdown() { +- double d = this.isVehicle() ? 0.997 : 0.96; +- Vec3 deltaMovement = this.getDeltaMovement(); +- Vec3 var4 = deltaMovement.multiply(d, 0.0, d); ++ double d0 = this.isVehicle() || !this.slowWhenEmpty ? 0.997D : 0.96D; // CraftBukkit - add !this.slowWhenEmpty ++ Vec3 vec3d = this.getDeltaMovement(); ++ ++ vec3d = vec3d.multiply(d0, 0.0D, d0); + if (this.isInWater()) { +- var4 = var4.scale(0.95F); ++ vec3d = vec3d.scale(0.949999988079071D); + } + +- this.setDeltaMovement(var4); ++ this.setDeltaMovement(vec3d); + } + + @Nullable +- public Vec3 getPosOffs(double x, double y, double z, double offset) { +- int floor = Mth.floor(x); +- int floor1 = Mth.floor(y); +- int floor2 = Mth.floor(z); +- if (this.level().getBlockState(new BlockPos(floor, floor1 - 1, floor2)).is(BlockTags.RAILS)) { +- floor1--; ++ public Vec3 getPosOffs(double x, double d1, double y, double d3) { ++ int i = Mth.floor(x); ++ int j = Mth.floor(d1); ++ int k = Mth.floor(y); ++ ++ if (this.level().getBlockState(new BlockPos(i, j - 1, k)).is(BlockTags.RAILS)) { ++ --j; + } + +- BlockState blockState = this.level().getBlockState(new BlockPos(floor, floor1, floor2)); +- if (BaseRailBlock.isRail(blockState)) { +- RailShape railShape = blockState.getValue(((BaseRailBlock)blockState.getBlock()).getShapeProperty()); +- double var24 = (double)floor1; +- if (railShape.isAscending()) { +- var24 = (double)(floor1 + 1); ++ IBlockData iblockdata = this.level().getBlockState(new BlockPos(i, j, k)); ++ ++ if (BaseRailBlock.isRail(iblockdata)) { ++ RailShape blockpropertytrackposition = (RailShape) iblockdata.getValue(((BaseRailBlock) iblockdata.getBlock()).getShapeProperty()); ++ ++ d1 = (double) j; ++ if (blockpropertytrackposition.isAscending()) { ++ d1 = (double) (j + 1); + } + +- Pair pair = exits(railShape); +- Vec3i vec3i = pair.getFirst(); +- Vec3i vec3i1 = pair.getSecond(); +- double d = (double)(vec3i1.getX() - vec3i.getX()); +- double d1 = (double)(vec3i1.getZ() - vec3i.getZ()); +- double squareRoot = Math.sqrt(d * d + d1 * d1); +- d /= squareRoot; +- d1 /= squareRoot; +- double var23 = x + d * offset; +- double var25 = z + d1 * offset; +- if (vec3i.getY() != 0 && Mth.floor(var23) - floor == vec3i.getX() && Mth.floor(var25) - floor2 == vec3i.getZ()) { +- var24 += (double)vec3i.getY(); +- } else if (vec3i1.getY() != 0 && Mth.floor(var23) - floor == vec3i1.getX() && Mth.floor(var25) - floor2 == vec3i1.getZ()) { +- var24 += (double)vec3i1.getY(); ++ Pair pair = exits(blockpropertytrackposition); ++ Vec3i baseblockposition = (Vec3i) pair.getFirst(); ++ Vec3i baseblockposition1 = (Vec3i) pair.getSecond(); ++ double d4 = (double) (baseblockposition1.getX() - baseblockposition.getX()); ++ double d5 = (double) (baseblockposition1.getZ() - baseblockposition.getZ()); ++ double d6 = Math.sqrt(d4 * d4 + d5 * d5); ++ ++ d4 /= d6; ++ d5 /= d6; ++ x += d4 * d3; ++ y += d5 * d3; ++ if (baseblockposition.getY() != 0 && Mth.floor(x) - i == baseblockposition.getX() && Mth.floor(y) - k == baseblockposition.getZ()) { ++ d1 += (double) baseblockposition.getY(); ++ } else if (baseblockposition1.getY() != 0 && Mth.floor(x) - i == baseblockposition1.getX() && Mth.floor(y) - k == baseblockposition1.getZ()) { ++ d1 += (double) baseblockposition1.getY(); + } + +- return this.getPos(var23, var24, var25); ++ return this.getPos(x, d1, y); + } else { + return null; + } + } + + @Nullable +- public Vec3 getPos(double x, double y, double z) { +- int floor = Mth.floor(x); +- int floor1 = Mth.floor(y); +- int floor2 = Mth.floor(z); +- if (this.level().getBlockState(new BlockPos(floor, floor1 - 1, floor2)).is(BlockTags.RAILS)) { +- floor1--; ++ public Vec3 getPos(double x, double d1, double y) { ++ int i = Mth.floor(x); ++ int j = Mth.floor(d1); ++ int k = Mth.floor(y); ++ ++ if (this.level().getBlockState(new BlockPos(i, j - 1, k)).is(BlockTags.RAILS)) { ++ --j; + } + +- BlockState blockState = this.level().getBlockState(new BlockPos(floor, floor1, floor2)); +- if (BaseRailBlock.isRail(blockState)) { +- RailShape railShape = blockState.getValue(((BaseRailBlock)blockState.getBlock()).getShapeProperty()); +- Pair pair = exits(railShape); +- Vec3i vec3i = pair.getFirst(); +- Vec3i vec3i1 = pair.getSecond(); +- double d = (double)floor + 0.5 + (double)vec3i.getX() * 0.5; +- double d1 = (double)floor1 + 0.0625 + (double)vec3i.getY() * 0.5; +- double d2 = (double)floor2 + 0.5 + (double)vec3i.getZ() * 0.5; +- double d3 = (double)floor + 0.5 + (double)vec3i1.getX() * 0.5; +- double d4 = (double)floor1 + 0.0625 + (double)vec3i1.getY() * 0.5; +- double d5 = (double)floor2 + 0.5 + (double)vec3i1.getZ() * 0.5; +- double d6 = d3 - d; +- double d7 = (d4 - d1) * 2.0; +- double d8 = d5 - d2; +- double d9; +- if (d6 == 0.0) { +- d9 = z - (double)floor2; +- } else if (d8 == 0.0) { +- d9 = x - (double)floor; ++ IBlockData iblockdata = this.level().getBlockState(new BlockPos(i, j, k)); ++ ++ if (BaseRailBlock.isRail(iblockdata)) { ++ RailShape blockpropertytrackposition = (RailShape) iblockdata.getValue(((BaseRailBlock) iblockdata.getBlock()).getShapeProperty()); ++ Pair pair = exits(blockpropertytrackposition); ++ Vec3i baseblockposition = (Vec3i) pair.getFirst(); ++ Vec3i baseblockposition1 = (Vec3i) pair.getSecond(); ++ double d3 = (double) i + 0.5D + (double) baseblockposition.getX() * 0.5D; ++ double d4 = (double) j + 0.0625D + (double) baseblockposition.getY() * 0.5D; ++ double d5 = (double) k + 0.5D + (double) baseblockposition.getZ() * 0.5D; ++ double d6 = (double) i + 0.5D + (double) baseblockposition1.getX() * 0.5D; ++ double d7 = (double) j + 0.0625D + (double) baseblockposition1.getY() * 0.5D; ++ double d8 = (double) k + 0.5D + (double) baseblockposition1.getZ() * 0.5D; ++ double d9 = d6 - d3; ++ double d10 = (d7 - d4) * 2.0D; ++ double d11 = d8 - d5; ++ double d12; ++ ++ if (d9 == 0.0D) { ++ d12 = y - (double) k; ++ } else if (d11 == 0.0D) { ++ d12 = x - (double) i; + } else { +- double d10 = x - d; +- double d11 = z - d2; +- d9 = (d10 * d6 + d11 * d8) * 2.0; ++ double d13 = x - d3; ++ double d14 = y - d5; ++ ++ d12 = (d13 * d9 + d14 * d11) * 2.0D; + } + +- x = d + d6 * d9; +- double var40 = d1 + d7 * d9; +- z = d2 + d8 * d9; +- if (d7 < 0.0) { +- var40++; +- } else if (d7 > 0.0) { +- var40 += 0.5; ++ x = d3 + d9 * d12; ++ d1 = d4 + d10 * d12; ++ y = d5 + d11 * d12; ++ if (d10 < 0.0D) { ++ ++d1; ++ } else if (d10 > 0.0D) { ++ d1 += 0.5D; + } + +- return new Vec3(x, var40, z); ++ return new Vec3(x, d1, y); + } else { + return null; + } +@@ -615,8 +764,9 @@ + + @Override + public AABB getBoundingBoxForCulling() { +- AABB boundingBox = this.getBoundingBox(); +- return this.hasCustomDisplay() ? boundingBox.inflate((double)Math.abs(this.getDisplayOffset()) / 16.0) : boundingBox; ++ AABB axisalignedbb = this.getBoundingBox(); ++ ++ return this.hasCustomDisplay() ? axisalignedbb.inflate((double) Math.abs(this.getDisplayOffset()) / 16.0D) : axisalignedbb; + } + + @Override +@@ -625,6 +775,7 @@ + this.setDisplayBlockState(NbtUtils.readBlockState(this.level().holderLookup(Registries.BLOCK), compound.getCompound("DisplayState"))); + this.setDisplayOffset(compound.getInt("DisplayOffset")); + } ++ + } + + @Override +@@ -634,6 +785,7 @@ + compound.put("DisplayState", NbtUtils.writeBlockState(this.getDisplayBlockState())); + compound.putInt("DisplayOffset", this.getDisplayOffset()); + } ++ + } + + @Override +@@ -641,76 +793,83 @@ + if (!this.level().isClientSide) { + if (!entity.noPhysics && !this.noPhysics) { + if (!this.hasPassenger(entity)) { +- double d = entity.getX() - this.getX(); ++ // CraftBukkit start ++ VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(collisionEvent); ++ ++ if (collisionEvent.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ double d0 = entity.getX() - this.getX(); + double d1 = entity.getZ() - this.getZ(); +- double d2 = d * d + d1 * d1; +- if (d2 >= 1.0E-4F) { ++ double d2 = d0 * d0 + d1 * d1; ++ ++ if (d2 >= 9.999999747378752E-5D) { + d2 = Math.sqrt(d2); +- double var24 = d / d2; +- double var28 = d1 / d2; +- double d3 = 1.0 / d2; +- if (d3 > 1.0) { +- d3 = 1.0; ++ d0 /= d2; ++ d1 /= d2; ++ double d3 = 1.0D / d2; ++ ++ if (d3 > 1.0D) { ++ d3 = 1.0D; + } + +- d = var24 * d3; +- d1 = var28 * d3; +- d *= 0.1F; +- d1 *= 0.1F; +- double var27 = d * 0.5; +- double var31 = d1 * 0.5; ++ d0 *= d3; ++ d1 *= d3; ++ d0 *= 0.10000000149011612D; ++ d1 *= 0.10000000149011612D; ++ d0 *= 0.5D; ++ d1 *= 0.5D; + if (entity instanceof AbstractMinecart) { + double d4 = entity.getX() - this.getX(); + double d5 = entity.getZ() - this.getZ(); +- Vec3 vec3 = new Vec3(d4, 0.0, d5).normalize(); +- Vec3 vec31 = new Vec3( +- (double)Mth.cos(this.getYRot() * (float) (Math.PI / 180.0)), +- 0.0, +- (double)Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)) +- ) +- .normalize(); +- double abs = Math.abs(vec3.dot(vec31)); +- if (abs < 0.8F) { ++ Vec3 vec3d = (new Vec3(d4, 0.0D, d5)).normalize(); ++ Vec3 vec3d1 = (new Vec3((double) Mth.cos(this.getYRot() * 0.017453292F), 0.0D, (double) Mth.sin(this.getYRot() * 0.017453292F))).normalize(); ++ double d6 = Math.abs(vec3d.dot(vec3d1)); ++ ++ if (d6 < 0.800000011920929D) { + return; + } + +- Vec3 deltaMovement = this.getDeltaMovement(); +- Vec3 deltaMovement1 = entity.getDeltaMovement(); +- if (((AbstractMinecart)entity).getMinecartType() == AbstractMinecart.Type.FURNACE +- && this.getMinecartType() != AbstractMinecart.Type.FURNACE) { +- this.setDeltaMovement(deltaMovement.multiply(0.2, 1.0, 0.2)); +- this.push(deltaMovement1.x - var27, 0.0, deltaMovement1.z - var31); +- entity.setDeltaMovement(deltaMovement1.multiply(0.95, 1.0, 0.95)); +- } else if (((AbstractMinecart)entity).getMinecartType() != AbstractMinecart.Type.FURNACE +- && this.getMinecartType() == AbstractMinecart.Type.FURNACE) { +- entity.setDeltaMovement(deltaMovement1.multiply(0.2, 1.0, 0.2)); +- entity.push(deltaMovement.x + var27, 0.0, deltaMovement.z + var31); +- this.setDeltaMovement(deltaMovement.multiply(0.95, 1.0, 0.95)); ++ Vec3 vec3d2 = this.getDeltaMovement(); ++ Vec3 vec3d3 = entity.getDeltaMovement(); ++ ++ if (((AbstractMinecart) entity).getMinecartType() == AbstractMinecart.EnumMinecartType.FURNACE && this.getMinecartType() != AbstractMinecart.EnumMinecartType.FURNACE) { ++ this.setDeltaMovement(vec3d2.multiply(0.2D, 1.0D, 0.2D)); ++ this.push(vec3d3.x - d0, 0.0D, vec3d3.z - d1); ++ entity.setDeltaMovement(vec3d3.multiply(0.95D, 1.0D, 0.95D)); ++ } else if (((AbstractMinecart) entity).getMinecartType() != AbstractMinecart.EnumMinecartType.FURNACE && this.getMinecartType() == AbstractMinecart.EnumMinecartType.FURNACE) { ++ entity.setDeltaMovement(vec3d3.multiply(0.2D, 1.0D, 0.2D)); ++ entity.push(vec3d2.x + d0, 0.0D, vec3d2.z + d1); ++ this.setDeltaMovement(vec3d2.multiply(0.95D, 1.0D, 0.95D)); + } else { +- double d6 = (deltaMovement1.x + deltaMovement.x) / 2.0; +- double d7 = (deltaMovement1.z + deltaMovement.z) / 2.0; +- this.setDeltaMovement(deltaMovement.multiply(0.2, 1.0, 0.2)); +- this.push(d6 - var27, 0.0, d7 - var31); +- entity.setDeltaMovement(deltaMovement1.multiply(0.2, 1.0, 0.2)); +- entity.push(d6 + var27, 0.0, d7 + var31); ++ double d7 = (vec3d3.x + vec3d2.x) / 2.0D; ++ double d8 = (vec3d3.z + vec3d2.z) / 2.0D; ++ ++ this.setDeltaMovement(vec3d2.multiply(0.2D, 1.0D, 0.2D)); ++ this.push(d7 - d0, 0.0D, d8 - d1); ++ entity.setDeltaMovement(vec3d3.multiply(0.2D, 1.0D, 0.2D)); ++ entity.push(d7 + d0, 0.0D, d8 + d1); + } + } else { +- this.push(-var27, 0.0, -var31); +- entity.push(var27 / 4.0, 0.0, var31 / 4.0); ++ this.push(-d0, 0.0D, -d1); ++ entity.push(d0 / 4.0D, 0.0D, d1 / 4.0D); + } + } ++ + } + } + } + } + + @Override +- public void lerpTo(double d, double d1, double d2, float f, float f1, int i) { +- this.lerpX = d; ++ public void lerpTo(double d0, double d1, double d2, float f, float f1, int i) { ++ this.lerpX = d0; + this.lerpY = d1; + this.lerpZ = d2; +- this.lerpYRot = (double)f; +- this.lerpXRot = (double)f1; ++ this.lerpYRot = (double) f; ++ this.lerpXRot = (double) f1; + this.lerpSteps = i + 2; + this.setDeltaMovement(this.targetDeltaMovement); + } +@@ -732,75 +891,110 @@ + + @Override + public float lerpTargetXRot() { +- return this.lerpSteps > 0 ? (float)this.lerpXRot : this.getXRot(); ++ return this.lerpSteps > 0 ? (float) this.lerpXRot : this.getXRot(); + } + + @Override + public float lerpTargetYRot() { +- return this.lerpSteps > 0 ? (float)this.lerpYRot : this.getYRot(); ++ return this.lerpSteps > 0 ? (float) this.lerpYRot : this.getYRot(); + } + + @Override +- public void lerpMotion(double x, double y, double z) { +- this.targetDeltaMovement = new Vec3(x, y, z); ++ public void lerpMotion(double x, double d1, double y) { ++ this.targetDeltaMovement = new Vec3(x, d1, y); + this.setDeltaMovement(this.targetDeltaMovement); + } + +- public abstract AbstractMinecart.Type getMinecartType(); ++ public abstract AbstractMinecart.EnumMinecartType getMinecartType(); + +- public BlockState getDisplayBlockState() { +- return !this.hasCustomDisplay() ? this.getDefaultDisplayBlockState() : Block.stateById(this.getEntityData().get(DATA_ID_DISPLAY_BLOCK)); ++ public IBlockData getDisplayBlockState() { ++ return !this.hasCustomDisplay() ? this.getDefaultDisplayBlockState() : Block.stateById((Integer) this.getEntityData().get(AbstractMinecart.DATA_ID_DISPLAY_BLOCK)); + } + +- public BlockState getDefaultDisplayBlockState() { ++ public IBlockData getDefaultDisplayBlockState() { + return Blocks.AIR.defaultBlockState(); + } + + public int getDisplayOffset() { +- return !this.hasCustomDisplay() ? this.getDefaultDisplayOffset() : this.getEntityData().get(DATA_ID_DISPLAY_OFFSET); ++ return !this.hasCustomDisplay() ? this.getDefaultDisplayOffset() : (Integer) this.getEntityData().get(AbstractMinecart.DATA_ID_DISPLAY_OFFSET); + } + + public int getDefaultDisplayOffset() { + return 6; + } + +- public void setDisplayBlockState(BlockState displayState) { +- this.getEntityData().set(DATA_ID_DISPLAY_BLOCK, Block.getId(displayState)); ++ public void setDisplayBlockState(IBlockData displayState) { ++ this.getEntityData().set(AbstractMinecart.DATA_ID_DISPLAY_BLOCK, Block.getId(displayState)); + this.setCustomDisplay(true); + } + + public void setDisplayOffset(int displayOffset) { +- this.getEntityData().set(DATA_ID_DISPLAY_OFFSET, displayOffset); ++ this.getEntityData().set(AbstractMinecart.DATA_ID_DISPLAY_OFFSET, displayOffset); + this.setCustomDisplay(true); + } + + public boolean hasCustomDisplay() { +- return this.getEntityData().get(DATA_ID_CUSTOM_DISPLAY); ++ return (Boolean) this.getEntityData().get(AbstractMinecart.DATA_ID_CUSTOM_DISPLAY); + } + + public void setCustomDisplay(boolean customDisplay) { +- this.getEntityData().set(DATA_ID_CUSTOM_DISPLAY, customDisplay); ++ this.getEntityData().set(AbstractMinecart.DATA_ID_CUSTOM_DISPLAY, customDisplay); + } + + @Override + public ItemStack getPickResult() { +- return new ItemStack(switch (this.getMinecartType()) { +- case CHEST -> Items.CHEST_MINECART; +- case FURNACE -> Items.FURNACE_MINECART; +- case TNT -> Items.TNT_MINECART; +- default -> Items.MINECART; +- case HOPPER -> Items.HOPPER_MINECART; +- case COMMAND_BLOCK -> Items.COMMAND_BLOCK_MINECART; +- }); ++ Item item; ++ ++ switch (this.getMinecartType()) { ++ case CHEST: ++ item = Items.CHEST_MINECART; ++ break; ++ case FURNACE: ++ item = Items.FURNACE_MINECART; ++ break; ++ case TNT: ++ item = Items.TNT_MINECART; ++ break; ++ case SPAWNER: ++ default: ++ item = Items.MINECART; ++ break; ++ case HOPPER: ++ item = Items.HOPPER_MINECART; ++ break; ++ case COMMAND_BLOCK: ++ item = Items.COMMAND_BLOCK_MINECART; ++ } ++ ++ return new ItemStack(item); + } + +- public static enum Type { +- RIDEABLE, +- CHEST, +- FURNACE, +- TNT, +- SPAWNER, +- HOPPER, +- COMMAND_BLOCK; ++ public static enum EnumMinecartType { ++ ++ RIDEABLE, CHEST, FURNACE, TNT, SPAWNER, HOPPER, COMMAND_BLOCK; ++ ++ private EnumMinecartType() {} + } ++ ++ // CraftBukkit start - Methods for getting and setting flying and derailed velocity modifiers ++ public Vector getFlyingVelocityMod() { ++ return new Vector(flyingX, flyingY, flyingZ); ++ } ++ ++ public void setFlyingVelocityMod(Vector flying) { ++ flyingX = flying.getX(); ++ flyingY = flying.getY(); ++ flyingZ = flying.getZ(); ++ } ++ ++ public Vector getDerailedVelocityMod() { ++ return new Vector(derailedX, derailedY, derailedZ); ++ } ++ ++ public void setDerailedVelocityMod(Vector derailed) { ++ derailedX = derailed.getX(); ++ derailedY = derailed.getY(); ++ derailedZ = derailed.getZ(); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java.patch new file mode 100644 index 0000000000..85c4cf618a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java.patch @@ -0,0 +1,137 @@ +--- a/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java ++++ b/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java +@@ -4,8 +4,9 @@ + import net.minecraft.core.NonNullList; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.resources.ResourceLocation; ++import net.minecraft.world.Container; + import net.minecraft.world.Containers; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; +@@ -16,19 +17,70 @@ + import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end + + public abstract class AbstractMinecartContainer extends AbstractMinecart implements ContainerEntity { +- private NonNullList itemStacks = NonNullList.withSize(36, ItemStack.EMPTY); ++ ++ private NonNullList itemStacks; + @Nullable +- private ResourceLocation lootTable; +- private long lootTableSeed; ++ public ResourceLocation lootTable; ++ public long lootTableSeed; + ++ // CraftBukkit start ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.itemStacks; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public InventoryHolder getOwner() { ++ org.bukkit.entity.Entity cart = getBukkitEntity(); ++ if(cart instanceof InventoryHolder) return (InventoryHolder) cart; ++ return null; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return getBukkitEntity().getLocation(); ++ } ++ // CraftBukkit end ++ + protected AbstractMinecartContainer(EntityType entityType, Level level) { + super(entityType, level); ++ this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); // CraftBukkit - SPIGOT-3513 + } + +- protected AbstractMinecartContainer(EntityType entityType, double x, double y, double z, Level level) { +- super(entityType, level, x, y, z); ++ protected AbstractMinecartContainer(EntityType entityType, double x, double d1, double y, Level world) { ++ super(entityType, world, x, d1, y); ++ this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); // CraftBukkit - SPIGOT-3513 + } + + @Override +@@ -63,8 +115,7 @@ + } + + @Override +- public void setChanged() { +- } ++ public void setChanged() {} + + @Override + public boolean stillValid(Player player) { +@@ -74,7 +125,7 @@ + @Override + public void remove(Entity.RemovalReason reason) { + if (!this.level().isClientSide && reason.shouldDestroy()) { +- Containers.dropContents(this.level(), this, this); ++ Containers.dropContents(this.level(), (Entity) this, (Container) this); + } + + super.remove(reason); +@@ -93,23 +144,25 @@ + } + + @Override +- public InteractionResult interact(Player player, InteractionHand hand) { ++ public InteractionResult interact(Player player, EnumHand hand) { + return this.interactWithContainerVehicle(player); + } + + @Override + protected void applyNaturalSlowdown() { + float f = 0.98F; ++ + if (this.lootTable == null) { + int i = 15 - AbstractContainerMenu.getRedstoneSignalFromContainer(this); +- f += (float)i * 0.001F; ++ ++ f += (float) i * 0.001F; + } + + if (this.isInWater()) { + f *= 0.95F; + } + +- this.setDeltaMovement(this.getDeltaMovement().multiply((double)f, 0.0, (double)f)); ++ this.setDeltaMovement(this.getDeltaMovement().multiply((double) f, 0.0D, (double) f)); + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/Boat.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/Boat.java.patch new file mode 100644 index 0000000000..4efaffd9de --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/Boat.java.patch @@ -0,0 +1,1156 @@ +--- a/net/minecraft/world/entity/vehicle/Boat.java ++++ b/net/minecraft/world/entity/vehicle/Boat.java +@@ -1,6 +1,8 @@ + package net.minecraft.world.entity.vehicle; + + import com.google.common.collect.Lists; ++import com.google.common.collect.UnmodifiableIterator; ++import java.util.Iterator; + import java.util.List; + import java.util.function.IntFunction; + import javax.annotation.Nullable; +@@ -21,15 +23,15 @@ + import net.minecraft.util.ByIdMap; + import net.minecraft.util.Mth; + import net.minecraft.util.StringRepresentable; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.VariantHolder; + import net.minecraft.world.entity.animal.Animal; + import net.minecraft.world.entity.animal.WaterAnimal; +@@ -38,11 +40,12 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.GameRules; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.WaterlilyBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.phys.AABB; +@@ -52,7 +55,17 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.Vehicle; ++import org.bukkit.event.vehicle.VehicleDestroyEvent; ++import org.bukkit.event.vehicle.VehicleEntityCollisionEvent; ++import org.bukkit.event.vehicle.VehicleMoveEvent; ++// CraftBukkit end ++ + public class Boat extends VehicleEntity implements VariantHolder { ++ + private static final EntityDataAccessor DATA_ID_TYPE = SynchedEntityData.defineId(Boat.class, EntityDataSerializers.INT); + private static final EntityDataAccessor DATA_ID_PADDLE_LEFT = SynchedEntityData.defineId(Boat.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_ID_PADDLE_RIGHT = SynchedEntityData.defineId(Boat.class, EntityDataSerializers.BOOLEAN); +@@ -60,10 +73,10 @@ + public static final int PADDLE_LEFT = 0; + public static final int PADDLE_RIGHT = 1; + private static final int TIME_TO_EJECT = 60; +- private static final float PADDLE_SPEED = (float) (Math.PI / 8); +- public static final double PADDLE_SOUND_TIME = (float) (Math.PI / 4); ++ private static final float PADDLE_SPEED = 0.3926991F; ++ public static final double PADDLE_SOUND_TIME = 0.7853981852531433D; + public static final int BUBBLE_TIME = 60; +- private final float[] paddlePositions = new float[2]; ++ private final float[] paddlePositions; + private float invFriction; + private float outOfControlTicks; + private float deltaRotation; +@@ -79,8 +92,8 @@ + private boolean inputDown; + private double waterLevel; + private float landFriction; +- private Boat.Status status; +- private Boat.Status oldStatus; ++ public Boat.EnumStatus status; ++ private Boat.EnumStatus oldStatus; + private double lastYd; + private boolean isAboveBubbleColumn; + private boolean bubbleColumnDirectionIsDown; +@@ -88,21 +101,30 @@ + private float bubbleAngle; + private float bubbleAngleO; + ++ // CraftBukkit start ++ // PAIL: Some of these haven't worked since a few updates, and since 1.9 they are less and less applicable. ++ public double maxSpeed = 0.4D; ++ public double occupiedDeceleration = 0.2D; ++ public double unoccupiedDeceleration = -1; ++ public boolean landBoats = false; ++ // CraftBukkit end ++ + public Boat(EntityType entityType, Level level) { + super(entityType, level); ++ this.paddlePositions = new float[2]; + this.blocksBuilding = true; + } + +- public Boat(Level level, double x, double y, double z) { ++ public Boat(Level level, double x, double d1, double y) { + this(EntityType.BOAT, level); +- this.setPos(x, y, z); ++ this.setPos(x, d1, y); + this.xo = x; +- this.yo = y; +- this.zo = z; ++ this.yo = d1; ++ this.zo = y; + } + + @Override +- protected float getEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getEyeHeight(EntityPose pose, EntityDimensions size) { + return size.height; + } + +@@ -114,10 +136,10 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_ID_TYPE, Boat.Type.OAK.ordinal()); +- this.entityData.define(DATA_ID_PADDLE_LEFT, false); +- this.entityData.define(DATA_ID_PADDLE_RIGHT, false); +- this.entityData.define(DATA_ID_BUBBLE_TIME, 0); ++ this.entityData.define(Boat.DATA_ID_TYPE, Boat.Type.OAK.ordinal()); ++ this.entityData.define(Boat.DATA_ID_PADDLE_LEFT, false); ++ this.entityData.define(Boat.DATA_ID_PADDLE_RIGHT, false); ++ this.entityData.define(Boat.DATA_ID_BUBBLE_TIME, 0); + } + + @Override +@@ -145,24 +167,24 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- float singlePassengerXOffset = this.getSinglePassengerXOffset(); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ float f1 = this.getSinglePassengerXOffset(); ++ + if (this.getPassengers().size() > 1) { +- int index = this.getPassengers().indexOf(entity); +- if (index == 0) { +- singlePassengerXOffset = 0.2F; ++ int i = this.getPassengers().indexOf(entity); ++ ++ if (i == 0) { ++ f1 = 0.2F; + } else { +- singlePassengerXOffset = -0.6F; ++ f1 = -0.6F; + } + + if (entity instanceof Animal) { +- singlePassengerXOffset += 0.2F; ++ f1 += 0.2F; + } + } + +- return new Vector3f( +- 0.0F, this.getVariant() == Boat.Type.BAMBOO ? entityDimensions.height * 0.8888889F : entityDimensions.height / 3.0F, singlePassengerXOffset +- ); ++ return new Vector3f(0.0F, this.getVariant() == Boat.Type.BAMBOO ? entitysize.height * 0.8888889F : entitysize.height / 3.0F, f1); + } + + @Override +@@ -175,49 +197,80 @@ + } + } + +- this.level() +- .addParticle( +- ParticleTypes.SPLASH, +- this.getX() + (double)this.random.nextFloat(), +- this.getY() + 0.7, +- this.getZ() + (double)this.random.nextFloat(), +- 0.0, +- 0.0, +- 0.0 +- ); ++ this.level().addParticle(ParticleTypes.SPLASH, this.getX() + (double) this.random.nextFloat(), this.getY() + 0.7D, this.getZ() + (double) this.random.nextFloat(), 0.0D, 0.0D, 0.0D); + if (this.random.nextInt(20) == 0) { +- this.level() +- .playLocalSound( +- this.getX(), this.getY(), this.getZ(), this.getSwimSplashSound(), this.getSoundSource(), 1.0F, 0.8F + 0.4F * this.random.nextFloat(), false +- ); ++ this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), this.getSwimSplashSound(), this.getSoundSource(), 1.0F, 0.8F + 0.4F * this.random.nextFloat(), false); + this.gameEvent(GameEvent.SPLASH, this.getControllingPassenger()); + } ++ + } + + @Override + public void push(Entity entity) { + if (entity instanceof Boat) { + if (entity.getBoundingBox().minY < this.getBoundingBox().maxY) { ++ // CraftBukkit start ++ if (!this.isPassengerOfSameVehicle(entity)) { ++ VehicleEntityCollisionEvent event = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + super.push(entity); + } + } else if (entity.getBoundingBox().minY <= this.getBoundingBox().minY) { ++ // CraftBukkit start ++ if (!this.isPassengerOfSameVehicle(entity)) { ++ VehicleEntityCollisionEvent event = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + super.push(entity); + } ++ + } + + @Override + public Item getDropItem() { +- return switch (this.getVariant()) { +- case SPRUCE -> Items.SPRUCE_BOAT; +- case BIRCH -> Items.BIRCH_BOAT; +- case JUNGLE -> Items.JUNGLE_BOAT; +- case ACACIA -> Items.ACACIA_BOAT; +- case CHERRY -> Items.CHERRY_BOAT; +- case DARK_OAK -> Items.DARK_OAK_BOAT; +- case MANGROVE -> Items.MANGROVE_BOAT; +- case BAMBOO -> Items.BAMBOO_RAFT; +- default -> Items.OAK_BOAT; +- }; ++ Item item; ++ ++ switch (this.getVariant()) { ++ case SPRUCE: ++ item = Items.SPRUCE_BOAT; ++ break; ++ case BIRCH: ++ item = Items.BIRCH_BOAT; ++ break; ++ case JUNGLE: ++ item = Items.JUNGLE_BOAT; ++ break; ++ case ACACIA: ++ item = Items.ACACIA_BOAT; ++ break; ++ case CHERRY: ++ item = Items.CHERRY_BOAT; ++ break; ++ case DARK_OAK: ++ item = Items.DARK_OAK_BOAT; ++ break; ++ case MANGROVE: ++ item = Items.MANGROVE_BOAT; ++ break; ++ case BAMBOO: ++ item = Items.BAMBOO_RAFT; ++ break; ++ default: ++ item = Items.OAK_BOAT; ++ } ++ ++ return item; + } + + @Override +@@ -233,12 +286,12 @@ + } + + @Override +- public void lerpTo(double d, double d1, double d2, float f, float f1, int i) { +- this.lerpX = d; ++ public void lerpTo(double d0, double d1, double d2, float f, float f1, int i) { ++ this.lerpX = d0; + this.lerpY = d1; + this.lerpZ = d2; +- this.lerpYRot = (double)f; +- this.lerpXRot = (double)f1; ++ this.lerpYRot = (double) f; ++ this.lerpXRot = (double) f1; + this.lerpSteps = 10; + } + +@@ -259,12 +312,12 @@ + + @Override + public float lerpTargetXRot() { +- return this.lerpSteps > 0 ? (float)this.lerpXRot : this.getXRot(); ++ return this.lerpSteps > 0 ? (float) this.lerpXRot : this.getXRot(); + } + + @Override + public float lerpTargetYRot() { +- return this.lerpSteps > 0 ? (float)this.lerpYRot : this.getYRot(); ++ return this.lerpSteps > 0 ? (float) this.lerpYRot : this.getYRot(); + } + + @Override +@@ -272,14 +325,15 @@ + return this.getDirection().getClockWise(); + } + ++ private Location lastLocation; // CraftBukkit + @Override + public void tick() { + this.oldStatus = this.status; + this.status = this.getStatus(); +- if (this.status != Boat.Status.UNDER_WATER && this.status != Boat.Status.UNDER_FLOWING_WATER) { ++ if (this.status != Boat.EnumStatus.UNDER_WATER && this.status != Boat.EnumStatus.UNDER_FLOWING_WATER) { + this.outOfControlTicks = 0.0F; + } else { +- this.outOfControlTicks++; ++ ++this.outOfControlTicks; + } + + if (!this.level().isClientSide && this.outOfControlTicks >= 60.0F) { +@@ -307,57 +361,61 @@ + this.level().sendPacketToServer(new ServerboundPaddleBoatPacket(this.getPaddleState(0), this.getPaddleState(1))); + } + +- this.move(MoverType.SELF, this.getDeltaMovement()); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); + } else { + this.setDeltaMovement(Vec3.ZERO); + } + ++ // CraftBukkit start ++ org.bukkit.Server server = this.level().getCraftServer(); ++ org.bukkit.World bworld = this.level().getWorld(); ++ ++ Location to = CraftLocation.toBukkit(this.position(), bworld, this.getYRot(), this.getXRot()); ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ ++ server.getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleUpdateEvent(vehicle)); ++ ++ if (lastLocation != null && !lastLocation.equals(to)) { ++ VehicleMoveEvent event = new VehicleMoveEvent(vehicle, lastLocation, to); ++ server.getPluginManager().callEvent(event); ++ } ++ lastLocation = vehicle.getLocation(); ++ // CraftBukkit end ++ + this.tickBubbleColumn(); + +- for (int i = 0; i <= 1; i++) { ++ for (int i = 0; i <= 1; ++i) { + if (this.getPaddleState(i)) { +- if (!this.isSilent() +- && (double)(this.paddlePositions[i] % (float) (Math.PI * 2)) <= (float) (Math.PI / 4) +- && (double)((this.paddlePositions[i] + (float) (Math.PI / 8)) % (float) (Math.PI * 2)) >= (float) (Math.PI / 4)) { +- SoundEvent paddleSound = this.getPaddleSound(); +- if (paddleSound != null) { +- Vec3 viewVector = this.getViewVector(1.0F); +- double d = i == 1 ? -viewVector.z : viewVector.z; +- double d1 = i == 1 ? viewVector.x : -viewVector.x; +- this.level() +- .playSound( +- null, +- this.getX() + d, +- this.getY(), +- this.getZ() + d1, +- paddleSound, +- this.getSoundSource(), +- 1.0F, +- 0.8F + 0.4F * this.random.nextFloat() +- ); ++ if (!this.isSilent() && (double) (this.paddlePositions[i] % 6.2831855F) <= 0.7853981852531433D && (double) ((this.paddlePositions[i] + 0.3926991F) % 6.2831855F) >= 0.7853981852531433D) { ++ SoundEvent soundeffect = this.getPaddleSound(); ++ ++ if (soundeffect != null) { ++ Vec3 vec3d = this.getViewVector(1.0F); ++ double d0 = i == 1 ? -vec3d.z : vec3d.z; ++ double d1 = i == 1 ? vec3d.x : -vec3d.x; ++ ++ this.level().playSound((Player) null, this.getX() + d0, this.getY(), this.getZ() + d1, soundeffect, this.getSoundSource(), 1.0F, 0.8F + 0.4F * this.random.nextFloat()); + } + } + +- this.paddlePositions[i] = this.paddlePositions[i] + (float) (Math.PI / 8); ++ this.paddlePositions[i] += 0.3926991F; + } else { + this.paddlePositions[i] = 0.0F; + } + } + + this.checkInsideBlocks(); +- List entities = this.level().getEntities(this, this.getBoundingBox().inflate(0.2F, -0.01F, 0.2F), EntitySelector.pushableBy(this)); +- if (!entities.isEmpty()) { ++ List list = this.level().getEntities((Entity) this, this.getBoundingBox().inflate(0.20000000298023224D, -0.009999999776482582D, 0.20000000298023224D), EntitySelector.pushableBy(this)); ++ ++ if (!list.isEmpty()) { + boolean flag = !this.level().isClientSide && !(this.getControllingPassenger() instanceof Player); ++ Iterator iterator = list.iterator(); + +- for (Entity entity : entities) { +- if (!entity.hasPassenger(this)) { +- if (flag +- && this.getPassengers().size() < this.getMaxPassengers() +- && !entity.isPassenger() +- && this.hasEnoughSpaceFor(entity) +- && entity instanceof LivingEntity +- && !(entity instanceof WaterAnimal) +- && !(entity instanceof Player)) { ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ ++ if (!entity.hasPassenger((Entity) this)) { ++ if (flag && this.getPassengers().size() < this.getMaxPassengers() && !entity.isPassenger() && this.hasEnoughSpaceFor(entity) && entity instanceof LivingEntity && !(entity instanceof WaterAnimal) && !(entity instanceof Player)) { + entity.startRiding(this); + } else { + this.push(entity); +@@ -365,12 +423,15 @@ + } + } + } ++ + } + + private void tickBubbleColumn() { ++ int i; ++ + if (this.level().isClientSide) { +- int bubbleTime = this.getBubbleTime(); +- if (bubbleTime > 0) { ++ i = this.getBubbleTime(); ++ if (i > 0) { + this.bubbleMultiplier += 0.05F; + } else { + this.bubbleMultiplier -= 0.1F; +@@ -378,30 +439,36 @@ + + this.bubbleMultiplier = Mth.clamp(this.bubbleMultiplier, 0.0F, 1.0F); + this.bubbleAngleO = this.bubbleAngle; +- this.bubbleAngle = 10.0F * (float)Math.sin((double)(0.5F * (float)this.level().getGameTime())) * this.bubbleMultiplier; ++ this.bubbleAngle = 10.0F * (float) Math.sin((double) (0.5F * (float) this.level().getGameTime())) * this.bubbleMultiplier; + } else { + if (!this.isAboveBubbleColumn) { + this.setBubbleTime(0); + } + +- int bubbleTime = this.getBubbleTime(); +- if (bubbleTime > 0) { +- this.setBubbleTime(--bubbleTime); +- int i = 60 - bubbleTime - 1; +- if (i > 0 && bubbleTime == 0) { ++ i = this.getBubbleTime(); ++ if (i > 0) { ++ --i; ++ this.setBubbleTime(i); ++ int j = 60 - i - 1; ++ ++ if (j > 0 && i == 0) { + this.setBubbleTime(0); +- Vec3 deltaMovement = this.getDeltaMovement(); ++ Vec3 vec3d = this.getDeltaMovement(); ++ + if (this.bubbleColumnDirectionIsDown) { +- this.setDeltaMovement(deltaMovement.add(0.0, -0.7, 0.0)); ++ this.setDeltaMovement(vec3d.add(0.0D, -0.7D, 0.0D)); + this.ejectPassengers(); + } else { +- this.setDeltaMovement(deltaMovement.x, this.hasPassenger(entity -> entity instanceof Player) ? 2.7 : 0.6, deltaMovement.z); ++ this.setDeltaMovement(vec3d.x, this.hasPassenger((entity) -> { ++ return entity instanceof Player; ++ }) ? 2.7D : 0.6D, vec3d.z); + } + } + + this.isAboveBubbleColumn = false; + } + } ++ + } + + @Nullable +@@ -427,103 +494,117 @@ + + if (this.lerpSteps > 0) { + this.lerpPositionAndRotationStep(this.lerpSteps, this.lerpX, this.lerpY, this.lerpZ, this.lerpYRot, this.lerpXRot); +- this.lerpSteps--; ++ --this.lerpSteps; + } + } + + public void setPaddleState(boolean left, boolean right) { +- this.entityData.set(DATA_ID_PADDLE_LEFT, left); +- this.entityData.set(DATA_ID_PADDLE_RIGHT, right); ++ this.entityData.set(Boat.DATA_ID_PADDLE_LEFT, left); ++ this.entityData.set(Boat.DATA_ID_PADDLE_RIGHT, right); + } + + public float getRowingTime(int side, float limbSwing) { +- return this.getPaddleState(side) ? Mth.clampedLerp(this.paddlePositions[side] - (float) (Math.PI / 8), this.paddlePositions[side], limbSwing) : 0.0F; ++ return this.getPaddleState(side) ? Mth.clampedLerp(this.paddlePositions[side] - 0.3926991F, this.paddlePositions[side], limbSwing) : 0.0F; + } + +- private Boat.Status getStatus() { +- Boat.Status status = this.isUnderwater(); +- if (status != null) { ++ private Boat.EnumStatus getStatus() { ++ Boat.EnumStatus entityboat_enumstatus = this.isUnderwater(); ++ ++ if (entityboat_enumstatus != null) { + this.waterLevel = this.getBoundingBox().maxY; +- return status; ++ return entityboat_enumstatus; + } else if (this.checkInWater()) { +- return Boat.Status.IN_WATER; ++ return Boat.EnumStatus.IN_WATER; + } else { +- float groundFriction = this.getGroundFriction(); +- if (groundFriction > 0.0F) { +- this.landFriction = groundFriction; +- return Boat.Status.ON_LAND; ++ float f = this.getGroundFriction(); ++ ++ if (f > 0.0F) { ++ this.landFriction = f; ++ return Boat.EnumStatus.ON_LAND; + } else { +- return Boat.Status.IN_AIR; ++ return Boat.EnumStatus.IN_AIR; + } + } + } + + public float getWaterLevelAbove() { +- AABB boundingBox = this.getBoundingBox(); +- int floor = Mth.floor(boundingBox.minX); +- int ceil = Mth.ceil(boundingBox.maxX); +- int floor1 = Mth.floor(boundingBox.maxY); +- int ceil1 = Mth.ceil(boundingBox.maxY - this.lastYd); +- int floor2 = Mth.floor(boundingBox.minZ); +- int ceil2 = Mth.ceil(boundingBox.maxZ); +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ AABB axisalignedbb = this.getBoundingBox(); ++ int i = Mth.floor(axisalignedbb.minX); ++ int j = Mth.ceil(axisalignedbb.maxX); ++ int k = Mth.floor(axisalignedbb.maxY); ++ int l = Mth.ceil(axisalignedbb.maxY - this.lastYd); ++ int i1 = Mth.floor(axisalignedbb.minZ); ++ int j1 = Mth.ceil(axisalignedbb.maxZ); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ int k1 = k; + +- label39: +- for (int i = floor1; i < ceil1; i++) { ++ while (k1 < l) { + float f = 0.0F; ++ int l1 = i; + +- for (int i1 = floor; i1 < ceil; i1++) { +- for (int i2 = floor2; i2 < ceil2; i2++) { +- mutableBlockPos.set(i1, i, i2); +- FluidState fluidState = this.level().getFluidState(mutableBlockPos); +- if (fluidState.is(FluidTags.WATER)) { +- f = Math.max(f, fluidState.getHeight(this.level(), mutableBlockPos)); +- } ++ label35: ++ while (true) { ++ if (l1 < j) { ++ int i2 = i1; + +- if (f >= 1.0F) { +- continue label39; ++ while (true) { ++ if (i2 >= j1) { ++ ++l1; ++ continue label35; ++ } ++ ++ blockposition_mutableblockposition.set(l1, k1, i2); ++ FluidState fluid = this.level().getFluidState(blockposition_mutableblockposition); ++ ++ if (fluid.is(FluidTags.WATER)) { ++ f = Math.max(f, fluid.getHeight(this.level(), blockposition_mutableblockposition)); ++ } ++ ++ if (f >= 1.0F) { ++ break; ++ } ++ ++ ++i2; + } ++ } else if (f < 1.0F) { ++ return (float) blockposition_mutableblockposition.getY() + f; + } +- } + +- if (f < 1.0F) { +- return (float)mutableBlockPos.getY() + f; ++ ++k1; ++ break; + } + } + +- return (float)(ceil1 + 1); ++ return (float) (l + 1); + } + + public float getGroundFriction() { +- AABB boundingBox = this.getBoundingBox(); +- AABB aABB = new AABB(boundingBox.minX, boundingBox.minY - 0.001, boundingBox.minZ, boundingBox.maxX, boundingBox.minY, boundingBox.maxZ); +- int i = Mth.floor(aABB.minX) - 1; +- int i1 = Mth.ceil(aABB.maxX) + 1; +- int i2 = Mth.floor(aABB.minY) - 1; +- int i3 = Mth.ceil(aABB.maxY) + 1; +- int i4 = Mth.floor(aABB.minZ) - 1; +- int i5 = Mth.ceil(aABB.maxZ) + 1; +- VoxelShape voxelShape = Shapes.create(aABB); ++ AABB axisalignedbb = this.getBoundingBox(); ++ AABB axisalignedbb1 = new AABB(axisalignedbb.minX, axisalignedbb.minY - 0.001D, axisalignedbb.minZ, axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.maxZ); ++ int i = Mth.floor(axisalignedbb1.minX) - 1; ++ int j = Mth.ceil(axisalignedbb1.maxX) + 1; ++ int k = Mth.floor(axisalignedbb1.minY) - 1; ++ int l = Mth.ceil(axisalignedbb1.maxY) + 1; ++ int i1 = Mth.floor(axisalignedbb1.minZ) - 1; ++ int j1 = Mth.ceil(axisalignedbb1.maxZ) + 1; ++ VoxelShape voxelshape = Shapes.create(axisalignedbb1); + float f = 0.0F; +- int i6 = 0; +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ int k1 = 0; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + +- for (int i7 = i; i7 < i1; i7++) { +- for (int i8 = i4; i8 < i5; i8++) { +- int i9 = (i7 != i && i7 != i1 - 1 ? 0 : 1) + (i8 != i4 && i8 != i5 - 1 ? 0 : 1); +- if (i9 != 2) { +- for (int i10 = i2; i10 < i3; i10++) { +- if (i9 <= 0 || i10 != i2 && i10 != i3 - 1) { +- mutableBlockPos.set(i7, i10, i8); +- BlockState blockState = this.level().getBlockState(mutableBlockPos); +- if (!(blockState.getBlock() instanceof WaterlilyBlock) +- && Shapes.joinIsNotEmpty( +- blockState.getCollisionShape(this.level(), mutableBlockPos).move((double)i7, (double)i10, (double)i8), +- voxelShape, +- BooleanOp.AND +- )) { +- f += blockState.getBlock().getFriction(); +- i6++; ++ for (int l1 = i; l1 < j; ++l1) { ++ for (int i2 = i1; i2 < j1; ++i2) { ++ int j2 = (l1 != i && l1 != j - 1 ? 0 : 1) + (i2 != i1 && i2 != j1 - 1 ? 0 : 1); ++ ++ if (j2 != 2) { ++ for (int k2 = k; k2 < l; ++k2) { ++ if (j2 <= 0 || k2 != k && k2 != l - 1) { ++ blockposition_mutableblockposition.set(l1, k2, i2); ++ IBlockData iblockdata = this.level().getBlockState(blockposition_mutableblockposition); ++ ++ if (!(iblockdata.getBlock() instanceof WaterlilyBlock) && Shapes.joinIsNotEmpty(iblockdata.getCollisionShape(this.level(), blockposition_mutableblockposition).move((double) l1, (double) k2, (double) i2), voxelshape, BooleanOp.AND)) { ++ f += iblockdata.getBlock().getFriction(); ++ ++k1; + } + } + } +@@ -531,30 +612,33 @@ + } + } + +- return f / (float)i6; ++ return f / (float) k1; + } + + private boolean checkInWater() { +- AABB boundingBox = this.getBoundingBox(); +- int floor = Mth.floor(boundingBox.minX); +- int ceil = Mth.ceil(boundingBox.maxX); +- int floor1 = Mth.floor(boundingBox.minY); +- int ceil1 = Mth.ceil(boundingBox.minY + 0.001); +- int floor2 = Mth.floor(boundingBox.minZ); +- int ceil2 = Mth.ceil(boundingBox.maxZ); ++ AABB axisalignedbb = this.getBoundingBox(); ++ int i = Mth.floor(axisalignedbb.minX); ++ int j = Mth.ceil(axisalignedbb.maxX); ++ int k = Mth.floor(axisalignedbb.minY); ++ int l = Mth.ceil(axisalignedbb.minY + 0.001D); ++ int i1 = Mth.floor(axisalignedbb.minZ); ++ int j1 = Mth.ceil(axisalignedbb.maxZ); + boolean flag = false; +- this.waterLevel = -Double.MAX_VALUE; +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); + +- for (int i = floor; i < ceil; i++) { +- for (int i1 = floor1; i1 < ceil1; i1++) { +- for (int i2 = floor2; i2 < ceil2; i2++) { +- mutableBlockPos.set(i, i1, i2); +- FluidState fluidState = this.level().getFluidState(mutableBlockPos); +- if (fluidState.is(FluidTags.WATER)) { +- float f = (float)i1 + fluidState.getHeight(this.level(), mutableBlockPos); +- this.waterLevel = Math.max((double)f, this.waterLevel); +- flag |= boundingBox.minY < (double)f; ++ this.waterLevel = -1.7976931348623157E308D; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ ++ for (int k1 = i; k1 < j; ++k1) { ++ for (int l1 = k; l1 < l; ++l1) { ++ for (int i2 = i1; i2 < j1; ++i2) { ++ blockposition_mutableblockposition.set(k1, l1, i2); ++ FluidState fluid = this.level().getFluidState(blockposition_mutableblockposition); ++ ++ if (fluid.is(FluidTags.WATER)) { ++ float f = (float) l1 + fluid.getHeight(this.level(), blockposition_mutableblockposition); ++ ++ this.waterLevel = Math.max((double) f, this.waterLevel); ++ flag |= axisalignedbb.minY < (double) f; + } + } + } +@@ -564,26 +648,27 @@ + } + + @Nullable +- private Boat.Status isUnderwater() { +- AABB boundingBox = this.getBoundingBox(); +- double d = boundingBox.maxY + 0.001; +- int floor = Mth.floor(boundingBox.minX); +- int ceil = Mth.ceil(boundingBox.maxX); +- int floor1 = Mth.floor(boundingBox.maxY); +- int ceil1 = Mth.ceil(d); +- int floor2 = Mth.floor(boundingBox.minZ); +- int ceil2 = Mth.ceil(boundingBox.maxZ); ++ private Boat.EnumStatus isUnderwater() { ++ AABB axisalignedbb = this.getBoundingBox(); ++ double d0 = axisalignedbb.maxY + 0.001D; ++ int i = Mth.floor(axisalignedbb.minX); ++ int j = Mth.ceil(axisalignedbb.maxX); ++ int k = Mth.floor(axisalignedbb.maxY); ++ int l = Mth.ceil(d0); ++ int i1 = Mth.floor(axisalignedbb.minZ); ++ int j1 = Mth.ceil(axisalignedbb.maxZ); + boolean flag = false; +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + +- for (int i = floor; i < ceil; i++) { +- for (int i1 = floor1; i1 < ceil1; i1++) { +- for (int i2 = floor2; i2 < ceil2; i2++) { +- mutableBlockPos.set(i, i1, i2); +- FluidState fluidState = this.level().getFluidState(mutableBlockPos); +- if (fluidState.is(FluidTags.WATER) && d < (double)((float)mutableBlockPos.getY() + fluidState.getHeight(this.level(), mutableBlockPos))) { +- if (!fluidState.isSource()) { +- return Boat.Status.UNDER_FLOWING_WATER; ++ for (int k1 = i; k1 < j; ++k1) { ++ for (int l1 = k; l1 < l; ++l1) { ++ for (int i2 = i1; i2 < j1; ++i2) { ++ blockposition_mutableblockposition.set(k1, l1, i2); ++ FluidState fluid = this.level().getFluidState(blockposition_mutableblockposition); ++ ++ if (fluid.is(FluidTags.WATER) && d0 < (double) ((float) blockposition_mutableblockposition.getY() + fluid.getHeight(this.level(), blockposition_mutableblockposition))) { ++ if (!fluid.isSource()) { ++ return Boat.EnumStatus.UNDER_FLOWING_WATER; + } + + flag = true; +@@ -592,58 +677,63 @@ + } + } + +- return flag ? Boat.Status.UNDER_WATER : null; ++ return flag ? Boat.EnumStatus.UNDER_WATER : null; + } + + private void floatBoat() { +- double d = -0.04F; +- double d1 = this.isNoGravity() ? 0.0 : -0.04F; +- double d2 = 0.0; ++ double d0 = -0.03999999910593033D; ++ double d1 = this.isNoGravity() ? 0.0D : -0.03999999910593033D; ++ double d2 = 0.0D; ++ + this.invFriction = 0.05F; +- if (this.oldStatus == Boat.Status.IN_AIR && this.status != Boat.Status.IN_AIR && this.status != Boat.Status.ON_LAND) { +- this.waterLevel = this.getY(1.0); +- this.setPos(this.getX(), (double)(this.getWaterLevelAbove() - this.getBbHeight()) + 0.101, this.getZ()); +- this.setDeltaMovement(this.getDeltaMovement().multiply(1.0, 0.0, 1.0)); +- this.lastYd = 0.0; +- this.status = Boat.Status.IN_WATER; ++ if (this.oldStatus == Boat.EnumStatus.IN_AIR && this.status != Boat.EnumStatus.IN_AIR && this.status != Boat.EnumStatus.ON_LAND) { ++ this.waterLevel = this.getY(1.0D); ++ this.setPos(this.getX(), (double) (this.getWaterLevelAbove() - this.getBbHeight()) + 0.101D, this.getZ()); ++ this.setDeltaMovement(this.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D)); ++ this.lastYd = 0.0D; ++ this.status = Boat.EnumStatus.IN_WATER; + } else { +- if (this.status == Boat.Status.IN_WATER) { +- d2 = (this.waterLevel - this.getY()) / (double)this.getBbHeight(); ++ if (this.status == Boat.EnumStatus.IN_WATER) { ++ d2 = (this.waterLevel - this.getY()) / (double) this.getBbHeight(); + this.invFriction = 0.9F; +- } else if (this.status == Boat.Status.UNDER_FLOWING_WATER) { +- d1 = -7.0E-4; ++ } else if (this.status == Boat.EnumStatus.UNDER_FLOWING_WATER) { ++ d1 = -7.0E-4D; + this.invFriction = 0.9F; +- } else if (this.status == Boat.Status.UNDER_WATER) { +- d2 = 0.01F; ++ } else if (this.status == Boat.EnumStatus.UNDER_WATER) { ++ d2 = 0.009999999776482582D; + this.invFriction = 0.45F; +- } else if (this.status == Boat.Status.IN_AIR) { ++ } else if (this.status == Boat.EnumStatus.IN_AIR) { + this.invFriction = 0.9F; +- } else if (this.status == Boat.Status.ON_LAND) { ++ } else if (this.status == Boat.EnumStatus.ON_LAND) { + this.invFriction = this.landFriction; + if (this.getControllingPassenger() instanceof Player) { + this.landFriction /= 2.0F; + } + } + +- Vec3 deltaMovement = this.getDeltaMovement(); +- this.setDeltaMovement(deltaMovement.x * (double)this.invFriction, deltaMovement.y + d1, deltaMovement.z * (double)this.invFriction); +- this.deltaRotation = this.deltaRotation * this.invFriction; +- if (d2 > 0.0) { +- Vec3 deltaMovement1 = this.getDeltaMovement(); +- this.setDeltaMovement(deltaMovement1.x, (deltaMovement1.y + d2 * 0.06153846016296973) * 0.75, deltaMovement1.z); ++ Vec3 vec3d = this.getDeltaMovement(); ++ ++ this.setDeltaMovement(vec3d.x * (double) this.invFriction, vec3d.y + d1, vec3d.z * (double) this.invFriction); ++ this.deltaRotation *= this.invFriction; ++ if (d2 > 0.0D) { ++ Vec3 vec3d1 = this.getDeltaMovement(); ++ ++ this.setDeltaMovement(vec3d1.x, (vec3d1.y + d2 * 0.06153846016296973D) * 0.75D, vec3d1.z); + } + } ++ + } + + private void controlBoat() { + if (this.isVehicle()) { + float f = 0.0F; ++ + if (this.inputLeft) { +- this.deltaRotation--; ++ --this.deltaRotation; + } + + if (this.inputRight) { +- this.deltaRotation++; ++ ++this.deltaRotation; + } + + if (this.inputRight != this.inputLeft && !this.inputUp && !this.inputDown) { +@@ -659,14 +749,7 @@ + f -= 0.005F; + } + +- this.setDeltaMovement( +- this.getDeltaMovement() +- .add( +- (double)(Mth.sin(-this.getYRot() * (float) (Math.PI / 180.0)) * f), +- 0.0, +- (double)(Mth.cos(this.getYRot() * (float) (Math.PI / 180.0)) * f) +- ) +- ); ++ this.setDeltaMovement(this.getDeltaMovement().add((double) (Mth.sin(-this.getYRot() * 0.017453292F) * f), 0.0D, (double) (Mth.cos(this.getYRot() * 0.017453292F) * f))); + this.setPaddleState(this.inputRight && !this.inputLeft || this.inputUp, this.inputLeft && !this.inputRight || this.inputUp); + } + } +@@ -688,38 +771,48 @@ + this.clampRotation(passenger); + if (passenger instanceof Animal && this.getPassengers().size() == this.getMaxPassengers()) { + int i = passenger.getId() % 2 == 0 ? 90 : 270; +- passenger.setYBodyRot(((Animal)passenger).yBodyRot + (float)i); +- passenger.setYHeadRot(passenger.getYHeadRot() + (float)i); ++ ++ passenger.setYBodyRot(((Animal) passenger).yBodyRot + (float) i); ++ passenger.setYHeadRot(passenger.getYHeadRot() + (float) i); + } ++ + } + } + + @Override + public Vec3 getDismountLocationForPassenger(LivingEntity livingEntity) { +- Vec3 collisionHorizontalEscapeVector = getCollisionHorizontalEscapeVector( +- (double)(this.getBbWidth() * Mth.SQRT_OF_TWO), (double)livingEntity.getBbWidth(), livingEntity.getYRot() +- ); +- double d = this.getX() + collisionHorizontalEscapeVector.x; +- double d1 = this.getZ() + collisionHorizontalEscapeVector.z; +- BlockPos blockPos = BlockPos.containing(d, this.getBoundingBox().maxY, d1); +- BlockPos blockPos1 = blockPos.below(); +- if (!this.level().isWaterAt(blockPos1)) { ++ Vec3 vec3d = getCollisionHorizontalEscapeVector((double) (this.getBbWidth() * Mth.SQRT_OF_TWO), (double) livingEntity.getBbWidth(), livingEntity.getYRot()); ++ double d0 = this.getX() + vec3d.x; ++ double d1 = this.getZ() + vec3d.z; ++ BlockPos blockposition = BlockPos.containing(d0, this.getBoundingBox().maxY, d1); ++ BlockPos blockposition1 = blockposition.below(); ++ ++ if (!this.level().isWaterAt(blockposition1)) { + List list = Lists.newArrayList(); +- double blockFloorHeight = this.level().getBlockFloorHeight(blockPos); +- if (DismountHelper.isBlockFloorValid(blockFloorHeight)) { +- list.add(new Vec3(d, (double)blockPos.getY() + blockFloorHeight, d1)); ++ double d2 = this.level().getBlockFloorHeight(blockposition); ++ ++ if (DismountHelper.isBlockFloorValid(d2)) { ++ list.add(new Vec3(d0, (double) blockposition.getY() + d2, d1)); + } + +- double blockFloorHeight1 = this.level().getBlockFloorHeight(blockPos1); +- if (DismountHelper.isBlockFloorValid(blockFloorHeight1)) { +- list.add(new Vec3(d, (double)blockPos1.getY() + blockFloorHeight1, d1)); ++ double d3 = this.level().getBlockFloorHeight(blockposition1); ++ ++ if (DismountHelper.isBlockFloorValid(d3)) { ++ list.add(new Vec3(d0, (double) blockposition1.getY() + d3, d1)); + } + +- for (Pose pose : livingEntity.getDismountPoses()) { +- for (Vec3 vec3 : list) { +- if (DismountHelper.canDismountTo(this.level(), vec3, livingEntity, pose)) { +- livingEntity.setPose(pose); +- return vec3; ++ UnmodifiableIterator unmodifiableiterator = livingEntity.getDismountPoses().iterator(); ++ ++ while (unmodifiableiterator.hasNext()) { ++ EntityPose entitypose = (EntityPose) unmodifiableiterator.next(); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Vec3 vec3d1 = (Vec3) iterator.next(); ++ ++ if (DismountHelper.canDismountTo(this.level(), vec3d1, livingEntity, entitypose)) { ++ livingEntity.setPose(entitypose); ++ return vec3d1; + } + } + } +@@ -732,6 +825,7 @@ + entityToUpdate.setYBodyRot(this.getYRot()); + float f = Mth.wrapDegrees(entityToUpdate.getYRot() - this.getYRot()); + float f1 = Mth.clamp(f, -105.0F, 105.0F); ++ + entityToUpdate.yRotO += f1 - f; + entityToUpdate.setYRot(entityToUpdate.getYRot() + f1 - f); + entityToUpdate.setYHeadRot(entityToUpdate.getYRot()); +@@ -752,80 +846,79 @@ + if (compound.contains("Type", 8)) { + this.setVariant(Boat.Type.byName(compound.getString("Type"))); + } ++ + } + + @Override +- public InteractionResult interact(Player player, InteractionHand hand) { +- if (player.isSecondaryUseActive()) { +- return InteractionResult.PASS; +- } else if (this.outOfControlTicks < 60.0F) { +- if (!this.level().isClientSide) { +- return player.startRiding(this) ? InteractionResult.CONSUME : InteractionResult.PASS; +- } else { +- return InteractionResult.SUCCESS; +- } +- } else { +- return InteractionResult.PASS; +- } ++ public InteractionResult interact(Player player, EnumHand hand) { ++ return player.isSecondaryUseActive() ? InteractionResult.PASS : (this.outOfControlTicks < 60.0F ? (!this.level().isClientSide ? (player.startRiding(this) ? InteractionResult.CONSUME : InteractionResult.PASS) : InteractionResult.SUCCESS) : InteractionResult.PASS); + } + + @Override +- protected void checkFallDamage(double y, boolean onGround, BlockState state, BlockPos pos) { ++ protected void checkFallDamage(double y, boolean flag, IBlockData onGround, BlockPos state) { + this.lastYd = this.getDeltaMovement().y; + if (!this.isPassenger()) { +- if (onGround) { ++ if (flag) { + if (this.fallDistance > 3.0F) { +- if (this.status != Boat.Status.ON_LAND) { ++ if (this.status != Boat.EnumStatus.ON_LAND) { + this.resetFallDistance(); + return; + } + + this.causeFallDamage(this.fallDistance, 1.0F, this.damageSources().fall()); + if (!this.level().isClientSide && !this.isRemoved()) { ++ // CraftBukkit start ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, null); ++ this.level().getCraftServer().getPluginManager().callEvent(destroyEvent); ++ if (!destroyEvent.isCancelled()) { + this.kill(); + if (this.level().getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { +- for (int i = 0; i < 3; i++) { +- this.spawnAtLocation(this.getVariant().getPlanks()); ++ int i; ++ ++ for (i = 0; i < 3; ++i) { ++ this.spawnAtLocation((IMaterial) this.getVariant().getPlanks()); + } + +- for (int i = 0; i < 2; i++) { +- this.spawnAtLocation(Items.STICK); ++ for (i = 0; i < 2; ++i) { ++ this.spawnAtLocation((IMaterial) Items.STICK); + } + } + } ++ } // CraftBukkit end + } + + this.resetFallDistance(); +- } else if (!this.level().getFluidState(this.blockPosition().below()).is(FluidTags.WATER) && y < 0.0) { +- this.fallDistance -= (float)y; ++ } else if (!this.level().getFluidState(this.blockPosition().below()).is(FluidTags.WATER) && y < 0.0D) { ++ this.fallDistance -= (float) y; + } ++ + } + } + + public boolean getPaddleState(int side) { +- return this.entityData.get(side == 0 ? DATA_ID_PADDLE_LEFT : DATA_ID_PADDLE_RIGHT) && this.getControllingPassenger() != null; ++ return (Boolean) this.entityData.get(side == 0 ? Boat.DATA_ID_PADDLE_LEFT : Boat.DATA_ID_PADDLE_RIGHT) && this.getControllingPassenger() != null; + } + + private void setBubbleTime(int bubbleTime) { +- this.entityData.set(DATA_ID_BUBBLE_TIME, bubbleTime); ++ this.entityData.set(Boat.DATA_ID_BUBBLE_TIME, bubbleTime); + } + + private int getBubbleTime() { +- return this.entityData.get(DATA_ID_BUBBLE_TIME); ++ return (Integer) this.entityData.get(Boat.DATA_ID_BUBBLE_TIME); + } + + public float getBubbleAngle(float partialTicks) { + return Mth.lerp(partialTicks, this.bubbleAngleO, this.bubbleAngle); + } + +- @Override + public void setVariant(Boat.Type variant) { +- this.entityData.set(DATA_ID_TYPE, variant.ordinal()); ++ this.entityData.set(Boat.DATA_ID_TYPE, variant.ordinal()); + } + + @Override + public Boat.Type getVariant() { +- return Boat.Type.byId(this.entityData.get(DATA_ID_TYPE)); ++ return Boat.Type.byId((Integer) this.entityData.get(Boat.DATA_ID_TYPE)); + } + + @Override +@@ -840,7 +933,18 @@ + @Nullable + @Override + public LivingEntity getControllingPassenger() { +- return this.getFirstPassenger() instanceof LivingEntity livingEntity ? livingEntity : super.getControllingPassenger(); ++ Entity entity = this.getFirstPassenger(); ++ LivingEntity entityliving; ++ ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving1 = (LivingEntity) entity; ++ ++ entityliving = entityliving1; ++ } else { ++ entityliving = super.getControllingPassenger(); ++ } ++ ++ return entityliving; + } + + public void setInput(boolean inputLeft, boolean inputRight, boolean inputUp, boolean inputDown) { +@@ -857,7 +961,7 @@ + + @Override + public boolean isUnderWater() { +- return this.status == Boat.Status.UNDER_WATER || this.status == Boat.Status.UNDER_FLOWING_WATER; ++ return this.status == Boat.EnumStatus.UNDER_WATER || this.status == Boat.EnumStatus.UNDER_FLOWING_WATER; + } + + @Override +@@ -865,33 +969,18 @@ + return new ItemStack(this.getDropItem()); + } + +- public static enum Status { +- IN_WATER, +- UNDER_WATER, +- UNDER_FLOWING_WATER, +- ON_LAND, +- IN_AIR; +- } +- + public static enum Type implements StringRepresentable { +- OAK(Blocks.OAK_PLANKS, "oak"), +- SPRUCE(Blocks.SPRUCE_PLANKS, "spruce"), +- BIRCH(Blocks.BIRCH_PLANKS, "birch"), +- JUNGLE(Blocks.JUNGLE_PLANKS, "jungle"), +- ACACIA(Blocks.ACACIA_PLANKS, "acacia"), +- CHERRY(Blocks.CHERRY_PLANKS, "cherry"), +- DARK_OAK(Blocks.DARK_OAK_PLANKS, "dark_oak"), +- MANGROVE(Blocks.MANGROVE_PLANKS, "mangrove"), +- BAMBOO(Blocks.BAMBOO_PLANKS, "bamboo"); + ++ OAK(Blocks.OAK_PLANKS, "oak"), SPRUCE(Blocks.SPRUCE_PLANKS, "spruce"), BIRCH(Blocks.BIRCH_PLANKS, "birch"), JUNGLE(Blocks.JUNGLE_PLANKS, "jungle"), ACACIA(Blocks.ACACIA_PLANKS, "acacia"), CHERRY(Blocks.CHERRY_PLANKS, "cherry"), DARK_OAK(Blocks.DARK_OAK_PLANKS, "dark_oak"), MANGROVE(Blocks.MANGROVE_PLANKS, "mangrove"), BAMBOO(Blocks.BAMBOO_PLANKS, "bamboo"); ++ + private final String name; + private final Block planks; + public static final StringRepresentable.EnumCodec CODEC = StringRepresentable.fromEnum(Boat.Type::values); +- private static final IntFunction BY_ID = ByIdMap.continuous(Enum::ordinal, values(), ByIdMap.OutOfBoundsStrategy.ZERO); ++ private static final IntFunction BY_ID = ByIdMap.continuous(Enum::ordinal, values(), ByIdMap.a.ZERO); + +- private Type(Block planks, String name) { +- this.name = name; +- this.planks = planks; ++ private Type(Block block, String s) { ++ this.name = s; ++ this.planks = block; + } + + @Override +@@ -907,17 +996,23 @@ + return this.planks; + } + +- @Override + public String toString() { + return this.name; + } + + public static Boat.Type byId(int id) { +- return BY_ID.apply(id); ++ return (Boat.Type) Boat.Type.BY_ID.apply(id); + } + + public static Boat.Type byName(String name) { +- return CODEC.byName(name, OAK); ++ return (Boat.Type) Boat.Type.CODEC.byName(name, Boat.Type.OAK); + } + } ++ ++ public static enum EnumStatus { ++ ++ IN_WATER, UNDER_WATER, UNDER_FLOWING_WATER, ON_LAND, IN_AIR; ++ ++ private EnumStatus() {} ++ } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/ChestBoat.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/ChestBoat.java.patch new file mode 100644 index 0000000000..c4a0363d2c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/ChestBoat.java.patch @@ -0,0 +1,204 @@ +--- a/net/minecraft/world/entity/vehicle/ChestBoat.java ++++ b/net/minecraft/world/entity/vehicle/ChestBoat.java +@@ -4,8 +4,9 @@ + import net.minecraft.core.NonNullList; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.resources.ResourceLocation; ++import net.minecraft.world.Container; + import net.minecraft.world.Containers; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; +@@ -22,24 +23,34 @@ + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end + + public class ChestBoat extends Boat implements HasCustomInventoryScreen, ContainerEntity { ++ + private static final int CONTAINER_SIZE = 27; +- private NonNullList itemStacks = NonNullList.withSize(27, ItemStack.EMPTY); ++ private NonNullList itemStacks; + @Nullable + private ResourceLocation lootTable; + private long lootTableSeed; + + public ChestBoat(EntityType entityType, Level level) { + super(entityType, level); ++ this.itemStacks = NonNullList.withSize(27, ItemStack.EMPTY); + } + +- public ChestBoat(Level level, double x, double y, double z) { ++ public ChestBoat(Level level, double x, double d1, double y) { + super(EntityType.CHEST_BOAT, level); +- this.setPos(x, y, z); ++ this.itemStacks = NonNullList.withSize(27, ItemStack.EMPTY); ++ this.setPos(x, d1, y); + this.xo = x; +- this.yo = y; +- this.zo = z; ++ this.yo = d1; ++ this.zo = y; + } + + @Override +@@ -73,24 +84,25 @@ + @Override + public void remove(Entity.RemovalReason reason) { + if (!this.level().isClientSide && reason.shouldDestroy()) { +- Containers.dropContents(this.level(), this, this); ++ Containers.dropContents(this.level(), (Entity) this, (Container) this); + } + + super.remove(reason); + } + + @Override +- public InteractionResult interact(Player player, InteractionHand hand) { ++ public InteractionResult interact(Player player, EnumHand hand) { + if (this.canAddPassenger(player) && !player.isSecondaryUseActive()) { + return super.interact(player, hand); + } else { +- InteractionResult interactionResult = this.interactWithContainerVehicle(player); +- if (interactionResult.consumesAction()) { ++ InteractionResult enuminteractionresult = this.interactWithContainerVehicle(player); ++ ++ if (enuminteractionresult.consumesAction()) { + this.gameEvent(GameEvent.CONTAINER_OPEN, player); + PiglinAi.angerNearbyPiglins(player, true); + } + +- return interactionResult; ++ return enuminteractionresult; + } + } + +@@ -101,21 +113,43 @@ + this.gameEvent(GameEvent.CONTAINER_OPEN, player); + PiglinAi.angerNearbyPiglins(player, true); + } ++ + } + + @Override + public Item getDropItem() { +- return switch (this.getVariant()) { +- case SPRUCE -> Items.SPRUCE_CHEST_BOAT; +- case BIRCH -> Items.BIRCH_CHEST_BOAT; +- case JUNGLE -> Items.JUNGLE_CHEST_BOAT; +- case ACACIA -> Items.ACACIA_CHEST_BOAT; +- case CHERRY -> Items.CHERRY_CHEST_BOAT; +- case DARK_OAK -> Items.DARK_OAK_CHEST_BOAT; +- case MANGROVE -> Items.MANGROVE_CHEST_BOAT; +- case BAMBOO -> Items.BAMBOO_CHEST_RAFT; +- default -> Items.OAK_CHEST_BOAT; +- }; ++ Item item; ++ ++ switch (this.getVariant()) { ++ case SPRUCE: ++ item = Items.SPRUCE_CHEST_BOAT; ++ break; ++ case BIRCH: ++ item = Items.BIRCH_CHEST_BOAT; ++ break; ++ case JUNGLE: ++ item = Items.JUNGLE_CHEST_BOAT; ++ break; ++ case ACACIA: ++ item = Items.ACACIA_CHEST_BOAT; ++ break; ++ case CHERRY: ++ item = Items.CHERRY_CHEST_BOAT; ++ break; ++ case DARK_OAK: ++ item = Items.DARK_OAK_CHEST_BOAT; ++ break; ++ case MANGROVE: ++ item = Items.MANGROVE_CHEST_BOAT; ++ break; ++ case BAMBOO: ++ item = Items.BAMBOO_CHEST_RAFT; ++ break; ++ default: ++ item = Items.OAK_CHEST_BOAT; ++ } ++ ++ return item; + } + + @Override +@@ -154,8 +188,7 @@ + } + + @Override +- public void setChanged() { +- } ++ public void setChanged() {} + + @Override + public boolean stillValid(Player player) { +@@ -210,6 +243,53 @@ + + @Override + public void stopOpen(Player player) { +- this.level().gameEvent(GameEvent.CONTAINER_CLOSE, this.position(), GameEvent.Context.of(player)); ++ this.level().gameEvent(GameEvent.CONTAINER_CLOSE, this.position(), GameEvent.Context.of((Entity) player)); + } ++ ++ // CraftBukkit start ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ @Override ++ public List getContents() { ++ return this.itemStacks; ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public InventoryHolder getOwner() { ++ org.bukkit.entity.Entity entity = getBukkitEntity(); ++ if (entity instanceof InventoryHolder) return (InventoryHolder) entity; ++ return null; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ @Override ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return getBukkitEntity().getLocation(); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java.patch new file mode 100644 index 0000000000..af317adc3e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java.patch @@ -0,0 +1,158 @@ +--- a/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java ++++ b/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java +@@ -8,7 +8,7 @@ + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; + import net.minecraft.server.level.ServerLevel; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.player.Player; +@@ -17,13 +17,14 @@ + import net.minecraft.world.level.BaseCommandBlock; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; + + public class MinecartCommandBlock extends AbstractMinecart { +- static final EntityDataAccessor DATA_ID_COMMAND_NAME = SynchedEntityData.defineId(MinecartCommandBlock.class, EntityDataSerializers.STRING); ++ ++ public static final EntityDataAccessor DATA_ID_COMMAND_NAME = SynchedEntityData.defineId(MinecartCommandBlock.class, EntityDataSerializers.STRING); + static final EntityDataAccessor DATA_ID_LAST_OUTPUT = SynchedEntityData.defineId(MinecartCommandBlock.class, EntityDataSerializers.COMPONENT); +- private final BaseCommandBlock commandBlock = new MinecartCommandBlock.MinecartCommandBase(); ++ private final BaseCommandBlock commandBlock = new MinecartCommandBlock.a(); + private static final int ACTIVATION_DELAY = 4; + private int lastActivated; + +@@ -31,8 +32,8 @@ + super(entityType, level); + } + +- public MinecartCommandBlock(Level level, double x, double y, double z) { +- super(EntityType.COMMAND_BLOCK_MINECART, level, x, y, z); ++ public MinecartCommandBlock(Level level, double x, double d1, double y) { ++ super(EntityType.COMMAND_BLOCK_MINECART, level, x, d1, y); + } + + @Override +@@ -43,16 +44,16 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.getEntityData().define(DATA_ID_COMMAND_NAME, ""); +- this.getEntityData().define(DATA_ID_LAST_OUTPUT, CommonComponents.EMPTY); ++ this.getEntityData().define(MinecartCommandBlock.DATA_ID_COMMAND_NAME, ""); ++ this.getEntityData().define(MinecartCommandBlock.DATA_ID_LAST_OUTPUT, CommonComponents.EMPTY); + } + + @Override + protected void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); + this.commandBlock.load(compound); +- this.getEntityData().set(DATA_ID_COMMAND_NAME, this.getCommandBlock().getCommand()); +- this.getEntityData().set(DATA_ID_LAST_OUTPUT, this.getCommandBlock().getLastOutput()); ++ this.getEntityData().set(MinecartCommandBlock.DATA_ID_COMMAND_NAME, this.getCommandBlock().getCommand()); ++ this.getEntityData().set(MinecartCommandBlock.DATA_ID_LAST_OUTPUT, this.getCommandBlock().getLastOutput()); + } + + @Override +@@ -62,12 +63,12 @@ + } + + @Override +- public AbstractMinecart.Type getMinecartType() { +- return AbstractMinecart.Type.COMMAND_BLOCK; ++ public AbstractMinecart.EnumMinecartType getMinecartType() { ++ return AbstractMinecart.EnumMinecartType.COMMAND_BLOCK; + } + + @Override +- public BlockState getDefaultDisplayBlockState() { ++ public IBlockData getDefaultDisplayBlockState() { + return Blocks.COMMAND_BLOCK.defaultBlockState(); + } + +@@ -81,24 +82,27 @@ + this.getCommandBlock().performCommand(this.level()); + this.lastActivated = this.tickCount; + } ++ + } + + @Override +- public InteractionResult interact(Player player, InteractionHand hand) { ++ public InteractionResult interact(Player player, EnumHand hand) { + return this.commandBlock.usedBy(player); + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor key) { + super.onSyncedDataUpdated(key); +- if (DATA_ID_LAST_OUTPUT.equals(key)) { ++ if (MinecartCommandBlock.DATA_ID_LAST_OUTPUT.equals(key)) { + try { +- this.commandBlock.setLastOutput(this.getEntityData().get(DATA_ID_LAST_OUTPUT)); +- } catch (Throwable var3) { ++ this.commandBlock.setLastOutput((Component) this.getEntityData().get(MinecartCommandBlock.DATA_ID_LAST_OUTPUT)); ++ } catch (Throwable throwable) { ++ ; + } +- } else if (DATA_ID_COMMAND_NAME.equals(key)) { +- this.commandBlock.setCommand(this.getEntityData().get(DATA_ID_COMMAND_NAME)); ++ } else if (MinecartCommandBlock.DATA_ID_COMMAND_NAME.equals(key)) { ++ this.commandBlock.setCommand((String) this.getEntityData().get(MinecartCommandBlock.DATA_ID_COMMAND_NAME)); + } ++ + } + + @Override +@@ -106,10 +110,13 @@ + return true; + } + +- public class MinecartCommandBase extends BaseCommandBlock { ++ public class a extends BaseCommandBlock { ++ ++ public a() {} ++ + @Override + public ServerLevel getLevel() { +- return (ServerLevel)MinecartCommandBlock.this.level(); ++ return (ServerLevel) MinecartCommandBlock.this.level(); + } + + @Override +@@ -129,22 +136,19 @@ + + @Override + public CommandSourceStack createCommandSourceStack() { +- return new CommandSourceStack( +- this, +- MinecartCommandBlock.this.position(), +- MinecartCommandBlock.this.getRotationVector(), +- this.getLevel(), +- 2, +- this.getName().getString(), +- MinecartCommandBlock.this.getDisplayName(), +- this.getLevel().getServer(), +- MinecartCommandBlock.this +- ); ++ return new CommandSourceStack(this, MinecartCommandBlock.this.position(), MinecartCommandBlock.this.getRotationVector(), this.getLevel(), 2, this.getName().getString(), MinecartCommandBlock.this.getDisplayName(), this.getLevel().getServer(), MinecartCommandBlock.this); + } + + @Override + public boolean isValid() { + return !MinecartCommandBlock.this.isRemoved(); + } ++ ++ // CraftBukkit start ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return (org.bukkit.craftbukkit.entity.CraftMinecartCommand) MinecartCommandBlock.this.getBukkitEntity(); ++ } ++ // CraftBukkit end + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/MinecartTNT.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/MinecartTNT.java.patch new file mode 100644 index 0000000000..93a8cb523b --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/MinecartTNT.java.patch @@ -0,0 +1,249 @@ +--- a/net/minecraft/world/entity/vehicle/MinecartTNT.java ++++ b/net/minecraft/world/entity/vehicle/MinecartTNT.java +@@ -9,36 +9,43 @@ + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.DamageTypeTags; + import net.minecraft.world.damagesource.DamageSource; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.AbstractArrow; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Explosion; ++import net.minecraft.world.level.ExplosionDamageCalculator; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; ++// CraftBukkit start ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end + + public class MinecartTNT extends AbstractMinecart { ++ + private static final byte EVENT_PRIME = 10; +- private int fuse = -1; ++ public int fuse = -1; + + public MinecartTNT(EntityType entityType, Level level) { + super(entityType, level); + } + +- public MinecartTNT(Level level, double x, double y, double z) { +- super(EntityType.TNT_MINECART, level, x, y, z); ++ public MinecartTNT(Level level, double x, double d1, double y) { ++ super(EntityType.TNT_MINECART, level, x, d1, y); + } + + @Override +- public AbstractMinecart.Type getMinecartType() { +- return AbstractMinecart.Type.TNT; ++ public AbstractMinecart.EnumMinecartType getMinecartType() { ++ return AbstractMinecart.EnumMinecartType.TNT; + } + + @Override +- public BlockState getDefaultDisplayBlockState() { ++ public IBlockData getDefaultDisplayBlockState() { + return Blocks.TNT.defaultBlockState(); + } + +@@ -46,25 +53,34 @@ + public void tick() { + super.tick(); + if (this.fuse > 0) { +- this.fuse--; +- this.level().addParticle(ParticleTypes.SMOKE, this.getX(), this.getY() + 0.5, this.getZ(), 0.0, 0.0, 0.0); ++ --this.fuse; ++ this.level().addParticle(ParticleTypes.SMOKE, this.getX(), this.getY() + 0.5D, this.getZ(), 0.0D, 0.0D, 0.0D); + } else if (this.fuse == 0) { + this.explode(this.getDeltaMovement().horizontalDistanceSqr()); + } + + if (this.horizontalCollision) { +- double d = this.getDeltaMovement().horizontalDistanceSqr(); +- if (d >= 0.01F) { +- this.explode(d); ++ double d0 = this.getDeltaMovement().horizontalDistanceSqr(); ++ ++ if (d0 >= 0.009999999776482582D) { ++ this.explode(d0); + } + } ++ + } + + @Override + public boolean hurt(DamageSource source, float amount) { +- if (source.getDirectEntity() instanceof AbstractArrow abstractArrow && abstractArrow.isOnFire()) { +- DamageSource damageSource = this.damageSources().explosion(this, source.getEntity()); +- this.explode(damageSource, abstractArrow.getDeltaMovement().lengthSqr()); ++ Entity entity = source.getDirectEntity(); ++ ++ if (entity instanceof AbstractArrow) { ++ AbstractArrow entityarrow = (AbstractArrow) entity; ++ ++ if (entityarrow.isOnFire()) { ++ DamageSource damagesource1 = this.damageSources().explosion(this, source.getEntity()); ++ ++ this.explode(damagesource1, entityarrow.getDeltaMovement().lengthSqr()); ++ } + } + + return super.hurt(source, amount); +@@ -72,14 +88,16 @@ + + @Override + public void destroy(DamageSource source) { +- double d = this.getDeltaMovement().horizontalDistanceSqr(); +- if (!damageSourceIgnitesTnt(source) && !(d >= 0.01F)) { ++ double d0 = this.getDeltaMovement().horizontalDistanceSqr(); ++ ++ if (!damageSourceIgnitesTnt(source) && d0 < 0.009999999776482582D) { + this.destroy(this.getDropItem()); + } else { + if (this.fuse < 0) { + this.primeFuse(); + this.fuse = this.random.nextInt(20) + this.random.nextInt(20); + } ++ + } + } + +@@ -88,38 +106,38 @@ + return Items.TNT_MINECART; + } + +- protected void explode(double radiusModifier) { +- this.explode(null, radiusModifier); ++ public void explode(double radiusModifier) { ++ this.explode((DamageSource) null, radiusModifier); + } + + protected void explode(@Nullable DamageSource damageSource, double radiusModifier) { + if (!this.level().isClientSide) { +- double squareRoot = Math.sqrt(radiusModifier); +- if (squareRoot > 5.0) { +- squareRoot = 5.0; ++ double d1 = Math.sqrt(radiusModifier); ++ ++ if (d1 > 5.0D) { ++ d1 = 5.0D; + } + +- this.level() +- .explode( +- this, +- damageSource, +- null, +- this.getX(), +- this.getY(), +- this.getZ(), +- (float)(4.0 + this.random.nextDouble() * 1.5 * squareRoot), +- false, +- Level.ExplosionInteraction.TNT +- ); ++ // CraftBukkit start ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), (float) (4.0D + this.random.nextDouble() * 1.5D * d1), false); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ fuse = -1; ++ return; ++ } ++ this.level().explode(this, damageSource, (ExplosionDamageCalculator) null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.TNT); ++ // CraftBukkit end + this.discard(); + } ++ + } + + @Override + public boolean causeFallDamage(float fallDistance, float multiplier, DamageSource source) { + if (fallDistance >= 3.0F) { +- float f = fallDistance / 10.0F; +- this.explode((double)(f * f)); ++ float f2 = fallDistance / 10.0F; ++ ++ this.explode((double) (f2 * f2)); + } + + return super.causeFallDamage(fallDistance, multiplier, source); +@@ -130,6 +148,7 @@ + if (receivingPower && this.fuse < 0) { + this.primeFuse(); + } ++ + } + + @Override +@@ -139,16 +158,18 @@ + } else { + super.handleEntityEvent(id); + } ++ + } + + public void primeFuse() { + this.fuse = 80; + if (!this.level().isClientSide) { +- this.level().broadcastEntityEvent(this, (byte)10); ++ this.level().broadcastEntityEvent(this, (byte) 10); + if (!this.isSilent()) { +- this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F); ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F); + } + } ++ + } + + public int getFuse() { +@@ -160,18 +181,13 @@ + } + + @Override +- public float getBlockExplosionResistance( +- Explosion explosion, BlockGetter level, BlockPos pos, BlockState blockState, FluidState fluidState, float explosionPower +- ) { +- return !this.isPrimed() || !blockState.is(BlockTags.RAILS) && !level.getBlockState(pos.above()).is(BlockTags.RAILS) +- ? super.getBlockExplosionResistance(explosion, level, pos, blockState, fluidState, explosionPower) +- : 0.0F; ++ public float getBlockExplosionResistance(Explosion explosion, BlockGetter level, BlockPos pos, IBlockData blockState, FluidState fluidState, float explosionPower) { ++ return this.isPrimed() && (blockState.is(BlockTags.RAILS) || level.getBlockState(pos.above()).is(BlockTags.RAILS)) ? 0.0F : super.getBlockExplosionResistance(explosion, level, pos, blockState, fluidState, explosionPower); + } + + @Override +- public boolean shouldBlockExplode(Explosion explosion, BlockGetter level, BlockPos pos, BlockState blockState, float explosionPower) { +- return (!this.isPrimed() || !blockState.is(BlockTags.RAILS) && !level.getBlockState(pos.above()).is(BlockTags.RAILS)) +- && super.shouldBlockExplode(explosion, level, pos, blockState, explosionPower); ++ public boolean shouldBlockExplode(Explosion explosion, BlockGetter level, BlockPos pos, IBlockData blockState, float explosionPower) { ++ return this.isPrimed() && (blockState.is(BlockTags.RAILS) || level.getBlockState(pos.above()).is(BlockTags.RAILS)) ? false : super.shouldBlockExplode(explosion, level, pos, blockState, explosionPower); + } + + @Override +@@ -180,6 +196,7 @@ + if (compound.contains("TNTFuse", 99)) { + this.fuse = compound.getInt("TNTFuse"); + } ++ + } + + @Override +@@ -189,11 +206,11 @@ + } + + @Override +- boolean shouldSourceDestroy(DamageSource damageSource) { +- return damageSourceIgnitesTnt(damageSource); ++ boolean shouldSourceDestroy(DamageSource damagesource) { ++ return damageSourceIgnitesTnt(damagesource); + } + +- private static boolean damageSourceIgnitesTnt(DamageSource damageSource) { +- return damageSource.is(DamageTypeTags.IS_FIRE) || damageSource.is(DamageTypeTags.IS_EXPLOSION); ++ private static boolean damageSourceIgnitesTnt(DamageSource damagesource) { ++ return damagesource.is(DamageTypeTags.IS_FIRE) || damagesource.is(DamageTypeTags.IS_EXPLOSION); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/VehicleEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/VehicleEntity.java.patch new file mode 100644 index 0000000000..ffeffb251f --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/vehicle/VehicleEntity.java.patch @@ -0,0 +1,156 @@ +--- a/net/minecraft/world/entity/vehicle/VehicleEntity.java ++++ b/net/minecraft/world/entity/vehicle/VehicleEntity.java +@@ -13,7 +13,14 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.entity.Vehicle; ++import org.bukkit.event.vehicle.VehicleDamageEvent; ++import org.bukkit.event.vehicle.VehicleDestroyEvent; ++// CraftBukkit end ++ + public abstract class VehicleEntity extends Entity { ++ + protected static final EntityDataAccessor DATA_ID_HURT = SynchedEntityData.defineId(VehicleEntity.class, EntityDataSerializers.INT); + protected static final EntityDataAccessor DATA_ID_HURTDIR = SynchedEntityData.defineId(VehicleEntity.class, EntityDataSerializers.INT); + protected static final EntityDataAccessor DATA_ID_DAMAGE = SynchedEntityData.defineId(VehicleEntity.class, EntityDataSerializers.FLOAT); +@@ -24,74 +31,108 @@ + + @Override + public boolean hurt(DamageSource source, float amount) { +- if (this.level().isClientSide || this.isRemoved()) { +- return true; +- } else if (this.isInvulnerableTo(source)) { +- return false; +- } else { +- this.setHurtDir(-this.getHurtDir()); +- this.setHurtTime(10); +- this.markHurt(); +- this.setDamage(this.getDamage() + amount * 10.0F); +- this.gameEvent(GameEvent.ENTITY_DAMAGE, source.getEntity()); +- boolean flag = source.getEntity() instanceof Player && ((Player)source.getEntity()).getAbilities().instabuild; +- if ((flag || !(this.getDamage() > 40.0F)) && !this.shouldSourceDestroy(source)) { +- if (flag) { +- this.discard(); +- } ++ if (!this.level().isClientSide && !this.isRemoved()) { ++ if (this.isInvulnerableTo(source)) { ++ return false; + } else { +- this.destroy(source); +- } ++ // CraftBukkit start ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ org.bukkit.entity.Entity attacker = (source.getEntity() == null) ? null : source.getEntity().getBukkitEntity(); + ++ VehicleDamageEvent event = new VehicleDamageEvent(vehicle, attacker, (double) amount); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ amount = (float) event.getDamage(); ++ // CraftBukkit end ++ this.setHurtDir(-this.getHurtDir()); ++ this.setHurtTime(10); ++ this.markHurt(); ++ this.setDamage(this.getDamage() + amount * 10.0F); ++ this.gameEvent(GameEvent.ENTITY_DAMAGE, source.getEntity()); ++ boolean flag = source.getEntity() instanceof Player && ((Player) source.getEntity()).getAbilities().instabuild; ++ ++ if ((flag || this.getDamage() <= 40.0F) && !this.shouldSourceDestroy(source)) { ++ if (flag) { ++ // CraftBukkit start ++ VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, attacker); ++ this.level().getCraftServer().getPluginManager().callEvent(destroyEvent); ++ ++ if (destroyEvent.isCancelled()) { ++ this.setDamage(40.0F); // Maximize damage so this doesn't get triggered again right away ++ return true; ++ } ++ // CraftBukkit end ++ this.discard(); ++ } ++ } else { ++ // CraftBukkit start ++ VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, attacker); ++ this.level().getCraftServer().getPluginManager().callEvent(destroyEvent); ++ ++ if (destroyEvent.isCancelled()) { ++ this.setDamage(40.0F); // Maximize damage so this doesn't get triggered again right away ++ return true; ++ } ++ // CraftBukkit end ++ this.destroy(source); ++ } ++ ++ return true; ++ } ++ } else { + return true; + } + } + +- boolean shouldSourceDestroy(DamageSource damageSource) { ++ boolean shouldSourceDestroy(DamageSource damagesource) { + return false; + } + + public void destroy(Item item) { + this.kill(); + if (this.level().getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { +- ItemStack itemStack = new ItemStack(item); ++ ItemStack itemstack = new ItemStack(item); ++ + if (this.hasCustomName()) { +- itemStack.setHoverName(this.getCustomName()); ++ itemstack.setHoverName(this.getCustomName()); + } + +- this.spawnAtLocation(itemStack); ++ this.spawnAtLocation(itemstack); + } + } + + @Override + protected void defineSynchedData() { +- this.entityData.define(DATA_ID_HURT, 0); +- this.entityData.define(DATA_ID_HURTDIR, 1); +- this.entityData.define(DATA_ID_DAMAGE, 0.0F); ++ this.entityData.define(VehicleEntity.DATA_ID_HURT, 0); ++ this.entityData.define(VehicleEntity.DATA_ID_HURTDIR, 1); ++ this.entityData.define(VehicleEntity.DATA_ID_DAMAGE, 0.0F); + } + + public void setHurtTime(int i) { +- this.entityData.set(DATA_ID_HURT, i); ++ this.entityData.set(VehicleEntity.DATA_ID_HURT, i); + } + + public void setHurtDir(int i) { +- this.entityData.set(DATA_ID_HURTDIR, i); ++ this.entityData.set(VehicleEntity.DATA_ID_HURTDIR, i); + } + + public void setDamage(float f) { +- this.entityData.set(DATA_ID_DAMAGE, f); ++ this.entityData.set(VehicleEntity.DATA_ID_DAMAGE, f); + } + + public float getDamage() { +- return this.entityData.get(DATA_ID_DAMAGE); ++ return (Float) this.entityData.get(VehicleEntity.DATA_ID_DAMAGE); + } + + public int getHurtTime() { +- return this.entityData.get(DATA_ID_HURT); ++ return (Integer) this.entityData.get(VehicleEntity.DATA_ID_HURT); + } + + public int getHurtDir() { +- return this.entityData.get(DATA_ID_HURTDIR); ++ return (Integer) this.entityData.get(VehicleEntity.DATA_ID_HURTDIR); + } + + protected void destroy(DamageSource damageSource) { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/food/FoodData.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/food/FoodData.java.patch new file mode 100644 index 0000000000..cd6d9cbd46 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/food/FoodData.java.patch @@ -0,0 +1,150 @@ +--- a/net/minecraft/world/food/FoodData.java ++++ b/net/minecraft/world/food/FoodData.java +@@ -1,6 +1,8 @@ + package net.minecraft.world.food; + + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.network.protocol.game.ClientboundSetHealthPacket; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.Difficulty; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Item; +@@ -8,60 +10,96 @@ + import net.minecraft.world.level.GameRules; + + public class FoodData { +- private int foodLevel = 20; +- private float saturationLevel; +- private float exhaustionLevel; ++ ++ public int foodLevel = 20; ++ public float saturationLevel = 5.0F; ++ public float exhaustionLevel; + private int tickTimer; ++ // CraftBukkit start ++ private Player entityhuman; ++ public int saturatedRegenRate = 10; ++ public int unsaturatedRegenRate = 80; ++ public int starvationRate = 80; ++ // CraftBukkit end + private int lastFoodLevel = 20; + +- public FoodData() { +- this.saturationLevel = 5.0F; ++ public FoodData() { throw new AssertionError("Whoopsie, we missed the bukkit."); } // CraftBukkit start - throw an error ++ ++ // CraftBukkit start - added EntityHuman constructor ++ public FoodData(Player entityhuman) { ++ org.apache.commons.lang.Validate.notNull(entityhuman); ++ this.entityhuman = entityhuman; + } ++ // CraftBukkit end + + public void eat(int foodLevelModifier, float saturationLevelModifier) { + this.foodLevel = Math.min(foodLevelModifier + this.foodLevel, 20); +- this.saturationLevel = Math.min(this.saturationLevel + (float)foodLevelModifier * saturationLevelModifier * 2.0F, (float)this.foodLevel); ++ this.saturationLevel = Math.min(this.saturationLevel + (float) foodLevelModifier * saturationLevelModifier * 2.0F, (float) this.foodLevel); + } + + public void eat(Item item, ItemStack stack) { + if (item.isEdible()) { +- FoodProperties foodProperties = item.getFoodProperties(); +- this.eat(foodProperties.getNutrition(), foodProperties.getSaturationModifier()); ++ FoodProperties foodinfo = item.getFoodProperties(); ++ // CraftBukkit start ++ int oldFoodLevel = foodLevel; ++ ++ org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(entityhuman, foodinfo.getNutrition() + oldFoodLevel, stack); ++ ++ if (!event.isCancelled()) { ++ this.eat(event.getFoodLevel() - oldFoodLevel, foodinfo.getSaturationModifier()); ++ } ++ ++ ((ServerPlayer) entityhuman).getBukkitEntity().sendHealthUpdate(); ++ // CraftBukkit end + } ++ + } + + public void tick(Player player) { +- Difficulty difficulty = player.level().getDifficulty(); ++ Difficulty enumdifficulty = player.level().getDifficulty(); ++ + this.lastFoodLevel = this.foodLevel; + if (this.exhaustionLevel > 4.0F) { + this.exhaustionLevel -= 4.0F; + if (this.saturationLevel > 0.0F) { + this.saturationLevel = Math.max(this.saturationLevel - 1.0F, 0.0F); +- } else if (difficulty != Difficulty.PEACEFUL) { +- this.foodLevel = Math.max(this.foodLevel - 1, 0); ++ } else if (enumdifficulty != Difficulty.PEACEFUL) { ++ // CraftBukkit start ++ org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(player, Math.max(this.foodLevel - 1, 0)); ++ ++ if (!event.isCancelled()) { ++ this.foodLevel = event.getFoodLevel(); ++ } ++ ++ ((ServerPlayer) player).connection.send(new ClientboundSetHealthPacket(((ServerPlayer) player).getBukkitEntity().getScaledHealth(), this.foodLevel, this.saturationLevel)); ++ // CraftBukkit end + } + } + +- boolean _boolean = player.level().getGameRules().getBoolean(GameRules.RULE_NATURAL_REGENERATION); +- if (_boolean && this.saturationLevel > 0.0F && player.isHurt() && this.foodLevel >= 20) { +- this.tickTimer++; +- if (this.tickTimer >= 10) { +- float min = Math.min(this.saturationLevel, 6.0F); +- player.heal(min / 6.0F); +- this.addExhaustion(min); ++ boolean flag = player.level().getGameRules().getBoolean(GameRules.RULE_NATURAL_REGENERATION); ++ ++ if (flag && this.saturationLevel > 0.0F && player.isHurt() && this.foodLevel >= 20) { ++ ++this.tickTimer; ++ if (this.tickTimer >= this.saturatedRegenRate) { // CraftBukkit ++ float f = Math.min(this.saturationLevel, 6.0F); ++ ++ player.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED); // CraftBukkit - added RegainReason ++ // this.addExhaustion(f); CraftBukkit - EntityExhaustionEvent ++ player.causeFoodExhaustion(f, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.REGEN); // CraftBukkit - EntityExhaustionEvent + this.tickTimer = 0; + } +- } else if (_boolean && this.foodLevel >= 18 && player.isHurt()) { +- this.tickTimer++; +- if (this.tickTimer >= 80) { +- player.heal(1.0F); +- this.addExhaustion(6.0F); ++ } else if (flag && this.foodLevel >= 18 && player.isHurt()) { ++ ++this.tickTimer; ++ if (this.tickTimer >= this.unsaturatedRegenRate) { // CraftBukkit - add regen rate manipulation ++ player.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED); // CraftBukkit - added RegainReason ++ // this.a(6.0F); CraftBukkit - EntityExhaustionEvent ++ player.causeFoodExhaustion(6.0f, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.REGEN); // CraftBukkit - EntityExhaustionEvent + this.tickTimer = 0; + } + } else if (this.foodLevel <= 0) { +- this.tickTimer++; +- if (this.tickTimer >= 80) { +- if (player.getHealth() > 10.0F || difficulty == Difficulty.HARD || player.getHealth() > 1.0F && difficulty == Difficulty.NORMAL) { ++ ++this.tickTimer; ++ if (this.tickTimer >= this.starvationRate) { // CraftBukkit - add regen rate manipulation ++ if (player.getHealth() > 10.0F || enumdifficulty == Difficulty.HARD || player.getHealth() > 1.0F && enumdifficulty == Difficulty.NORMAL) { + player.hurt(player.damageSources().starve(), 1.0F); + } + +@@ -70,6 +108,7 @@ + } else { + this.tickTimer = 0; + } ++ + } + + public void readAdditionalSaveData(CompoundTag compoundTag) { +@@ -79,6 +118,7 @@ + this.saturationLevel = compoundTag.getFloat("foodSaturationLevel"); + this.exhaustionLevel = compoundTag.getFloat("foodExhaustionLevel"); + } ++ + } + + public void addAdditionalSaveData(CompoundTag compoundTag) { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/AbstractContainerMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/AbstractContainerMenu.java.patch new file mode 100644 index 0000000000..7e810d4818 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/AbstractContainerMenu.java.patch @@ -0,0 +1,1188 @@ +--- a/net/minecraft/world/inventory/AbstractContainerMenu.java ++++ b/net/minecraft/world/inventory/AbstractContainerMenu.java +@@ -8,7 +8,9 @@ + import com.mojang.logging.LogUtils; + import it.unimi.dsi.fastutil.ints.IntArrayList; + import it.unimi.dsi.fastutil.ints.IntList; ++import java.util.Iterator; + import java.util.List; ++import java.util.Objects; + import java.util.Optional; + import java.util.OptionalInt; + import java.util.Set; +@@ -17,9 +19,10 @@ + import net.minecraft.CrashReport; + import net.minecraft.CrashReportCategory; + import net.minecraft.ReportedException; +-import net.minecraft.core.BlockPos; + import net.minecraft.core.NonNullList; + import net.minecraft.core.registries.BuiltInRegistries; ++import net.minecraft.network.chat.Component; ++import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.Mth; + import net.minecraft.world.Container; +@@ -28,12 +31,24 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.flag.FeatureFlagSet; + import net.minecraft.world.item.ItemStack; +-import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.entity.BlockEntity; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.google.common.base.Preconditions; ++import java.util.HashMap; ++import java.util.Map; ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.Event.Result; ++import org.bukkit.event.inventory.InventoryDragEvent; ++import org.bukkit.event.inventory.InventoryType; ++import org.bukkit.inventory.InventoryView; ++// CraftBukkit end ++ + public abstract class AbstractContainerMenu { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + public static final int SLOT_CLICKED_OUTSIDE = -999; + public static final int QUICKCRAFT_TYPE_CHARITABLE = 0; +@@ -43,37 +58,62 @@ + public static final int QUICKCRAFT_HEADER_CONTINUE = 1; + public static final int QUICKCRAFT_HEADER_END = 2; + public static final int CARRIED_SLOT_SIZE = Integer.MAX_VALUE; +- private final NonNullList lastSlots = NonNullList.create(); +- public final NonNullList slots = NonNullList.create(); ++ public NonNullList lastSlots = NonNullList.create(); ++ public NonNullList slots = NonNullList.create(); + private final List dataSlots = Lists.newArrayList(); +- private ItemStack carried = ItemStack.EMPTY; +- private final NonNullList remoteSlots = NonNullList.create(); +- private final IntList remoteDataSlots = new IntArrayList(); +- private ItemStack remoteCarried = ItemStack.EMPTY; ++ private ItemStack carried; ++ public NonNullList remoteSlots; ++ private final IntList remoteDataSlots; ++ private ItemStack remoteCarried; + private int stateId; + @Nullable + private final MenuType menuType; + public final int containerId; +- private int quickcraftType = -1; ++ private int quickcraftType; + private int quickcraftStatus; +- private final Set quickcraftSlots = Sets.newHashSet(); +- private final List containerListeners = Lists.newArrayList(); ++ private final Set quickcraftSlots; ++ private final List containerListeners; + @Nullable + private ContainerSynchronizer synchronizer; + private boolean suppressRemoteUpdates; + ++ // CraftBukkit start ++ public boolean checkReachable = true; ++ public abstract InventoryView getBukkitView(); ++ public void transferTo(AbstractContainerMenu other, org.bukkit.craftbukkit.entity.CraftHumanEntity player) { ++ InventoryView source = this.getBukkitView(), destination = other.getBukkitView(); ++ ((CraftInventory) source.getTopInventory()).getInventory().onClose(player); ++ ((CraftInventory) source.getBottomInventory()).getInventory().onClose(player); ++ ((CraftInventory) destination.getTopInventory()).getInventory().onOpen(player); ++ ((CraftInventory) destination.getBottomInventory()).getInventory().onOpen(player); ++ } ++ private Component title; ++ public final Component getTitle() { ++ Preconditions.checkState(this.title != null, "Title not set"); ++ return this.title; ++ } ++ public final void setTitle(Component title) { ++ Preconditions.checkState(this.title == null, "Title already set"); ++ this.title = title; ++ } ++ // CraftBukkit end ++ + protected AbstractContainerMenu(@Nullable MenuType menuType, int containerId) { ++ this.carried = ItemStack.EMPTY; ++ this.remoteSlots = NonNullList.create(); ++ this.remoteDataSlots = new IntArrayList(); ++ this.remoteCarried = ItemStack.EMPTY; ++ this.quickcraftType = -1; ++ this.quickcraftSlots = Sets.newHashSet(); ++ this.containerListeners = Lists.newArrayList(); + this.menuType = menuType; + this.containerId = containerId; + } + + protected static boolean stillValid(ContainerLevelAccess access, Player player, Block targetBlock) { +- return access.evaluate( +- (level, blockPos) -> !level.getBlockState(blockPos).is(targetBlock) +- ? false +- : player.distanceToSqr((double)blockPos.getX() + 0.5, (double)blockPos.getY() + 0.5, (double)blockPos.getZ() + 0.5) <= 64.0, +- true +- ); ++ return (Boolean) access.evaluate((world, blockposition) -> { ++ return !world.getBlockState(blockposition).is(targetBlock) ? false : player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) <= 64.0D; ++ }, true); + } + + public MenuType getType() { +@@ -85,16 +125,18 @@ + } + + protected static void checkContainerSize(Container container, int minSize) { +- int containerSize = container.getContainerSize(); +- if (containerSize < minSize) { +- throw new IllegalArgumentException("Container size " + containerSize + " is smaller than expected " + minSize); ++ int j = container.getContainerSize(); ++ ++ if (j < minSize) { ++ throw new IllegalArgumentException("Container size " + j + " is smaller than expected " + minSize); + } + } + + protected static void checkContainerDataCount(ContainerData intArray, int minSize) { +- int count = intArray.getCount(); +- if (count < minSize) { +- throw new IllegalArgumentException("Container data count " + count + " is smaller than expected " + minSize); ++ int j = intArray.getCount(); ++ ++ if (j < minSize) { ++ throw new IllegalArgumentException("Container data count " + j + " is smaller than expected " + minSize); + } + } + +@@ -117,9 +159,10 @@ + } + + protected void addDataSlots(ContainerData array) { +- for (int i = 0; i < array.getCount(); i++) { ++ for (int i = 0; i < array.getCount(); ++i) { + this.addDataSlot(DataSlot.forContainer(array, i)); + } ++ + } + + public void addSlotListener(ContainerListener listener) { +@@ -137,67 +180,94 @@ + public void sendAllDataToRemote() { + int i = 0; + +- for (int size = this.slots.size(); i < size; i++) { +- this.remoteSlots.set(i, this.slots.get(i).getItem().copy()); ++ int j; ++ ++ for (j = this.slots.size(); i < j; ++i) { ++ this.remoteSlots.set(i, ((Slot) this.slots.get(i)).getItem().copy()); + } + + this.remoteCarried = this.getCarried().copy(); + i = 0; + +- for (int size = this.dataSlots.size(); i < size; i++) { +- this.remoteDataSlots.set(i, this.dataSlots.get(i).get()); ++ for (j = this.dataSlots.size(); i < j; ++i) { ++ this.remoteDataSlots.set(i, ((DataSlot) this.dataSlots.get(i)).get()); + } + + if (this.synchronizer != null) { + this.synchronizer.sendInitialData(this, this.remoteSlots, this.remoteCarried, this.remoteDataSlots.toIntArray()); + } ++ + } + ++ // CraftBukkit start ++ public void broadcastCarriedItem() { ++ this.remoteCarried = this.getCarried().copy(); ++ if (this.synchronizer != null) { ++ this.synchronizer.sendCarriedChange(this, this.remoteCarried); ++ } ++ } ++ // CraftBukkit end ++ + public void removeSlotListener(ContainerListener listener) { + this.containerListeners.remove(listener); + } + + public NonNullList getItems() { +- NonNullList list = NonNullList.create(); ++ NonNullList nonnulllist = NonNullList.create(); ++ Iterator iterator = this.slots.iterator(); + +- for (Slot slot : this.slots) { +- list.add(slot.getItem()); ++ while (iterator.hasNext()) { ++ Slot slot = (Slot) iterator.next(); ++ ++ nonnulllist.add(slot.getItem()); + } + +- return list; ++ return nonnulllist; + } + + public void broadcastChanges() { +- for (int i = 0; i < this.slots.size(); i++) { +- ItemStack item = this.slots.get(i).getItem(); +- Supplier supplier = Suppliers.memoize(item::copy); +- this.triggerSlotListeners(i, item, supplier); +- this.synchronizeSlotToRemote(i, item, supplier); ++ int i; ++ ++ for (i = 0; i < this.slots.size(); ++i) { ++ ItemStack itemstack = ((Slot) this.slots.get(i)).getItem(); ++ ++ Objects.requireNonNull(itemstack); ++ Supplier supplier = Suppliers.memoize(itemstack::copy); ++ ++ this.triggerSlotListeners(i, itemstack, supplier); ++ this.synchronizeSlotToRemote(i, itemstack, supplier); + } + + this.synchronizeCarriedToRemote(); + +- for (int i = 0; i < this.dataSlots.size(); i++) { +- DataSlot dataSlot = this.dataSlots.get(i); +- int i1 = dataSlot.get(); +- if (dataSlot.checkAndClearUpdateFlag()) { +- this.updateDataSlotListeners(i, i1); ++ for (i = 0; i < this.dataSlots.size(); ++i) { ++ DataSlot containerproperty = (DataSlot) this.dataSlots.get(i); ++ int j = containerproperty.get(); ++ ++ if (containerproperty.checkAndClearUpdateFlag()) { ++ this.updateDataSlotListeners(i, j); + } + +- this.synchronizeDataSlotToRemote(i, i1); ++ this.synchronizeDataSlotToRemote(i, j); + } ++ + } + + public void broadcastFullState() { +- for (int i = 0; i < this.slots.size(); i++) { +- ItemStack item = this.slots.get(i).getItem(); +- this.triggerSlotListeners(i, item, item::copy); ++ int i; ++ ++ for (i = 0; i < this.slots.size(); ++i) { ++ ItemStack itemstack = ((Slot) this.slots.get(i)).getItem(); ++ ++ Objects.requireNonNull(itemstack); ++ this.triggerSlotListeners(i, itemstack, itemstack::copy); + } + +- for (int i = 0; i < this.dataSlots.size(); i++) { +- DataSlot dataSlot = this.dataSlots.get(i); +- if (dataSlot.checkAndClearUpdateFlag()) { +- this.updateDataSlotListeners(i, dataSlot.get()); ++ for (i = 0; i < this.dataSlots.size(); ++i) { ++ DataSlot containerproperty = (DataSlot) this.dataSlots.get(i); ++ ++ if (containerproperty.checkAndClearUpdateFlag()) { ++ this.updateDataSlotListeners(i, containerproperty.get()); + } + } + +@@ -205,45 +275,61 @@ + } + + private void updateDataSlotListeners(int slotIndex, int value) { +- for (ContainerListener containerListener : this.containerListeners) { +- containerListener.dataChanged(this, slotIndex, value); ++ Iterator iterator = this.containerListeners.iterator(); ++ ++ while (iterator.hasNext()) { ++ ContainerListener icrafting = (ContainerListener) iterator.next(); ++ ++ icrafting.dataChanged(this, slotIndex, value); + } ++ + } + + private void triggerSlotListeners(int slotIndex, ItemStack stack, Supplier supplier) { +- ItemStack itemStack = this.lastSlots.get(slotIndex); +- if (!ItemStack.matches(itemStack, stack)) { +- ItemStack itemStack1 = supplier.get(); +- this.lastSlots.set(slotIndex, itemStack1); ++ ItemStack itemstack1 = (ItemStack) this.lastSlots.get(slotIndex); + +- for (ContainerListener containerListener : this.containerListeners) { +- containerListener.slotChanged(this, slotIndex, itemStack1); ++ if (!ItemStack.matches(itemstack1, stack)) { ++ ItemStack itemstack2 = (ItemStack) supplier.get(); ++ ++ this.lastSlots.set(slotIndex, itemstack2); ++ Iterator iterator = this.containerListeners.iterator(); ++ ++ while (iterator.hasNext()) { ++ ContainerListener icrafting = (ContainerListener) iterator.next(); ++ ++ icrafting.slotChanged(this, slotIndex, itemstack2); + } + } ++ + } + + private void synchronizeSlotToRemote(int slotIndex, ItemStack stack, Supplier supplier) { + if (!this.suppressRemoteUpdates) { +- ItemStack itemStack = this.remoteSlots.get(slotIndex); +- if (!ItemStack.matches(itemStack, stack)) { +- ItemStack itemStack1 = supplier.get(); +- this.remoteSlots.set(slotIndex, itemStack1); ++ ItemStack itemstack1 = (ItemStack) this.remoteSlots.get(slotIndex); ++ ++ if (!ItemStack.matches(itemstack1, stack)) { ++ ItemStack itemstack2 = (ItemStack) supplier.get(); ++ ++ this.remoteSlots.set(slotIndex, itemstack2); + if (this.synchronizer != null) { +- this.synchronizer.sendSlotChange(this, slotIndex, itemStack1); ++ this.synchronizer.sendSlotChange(this, slotIndex, itemstack2); + } + } ++ + } + } + + private void synchronizeDataSlotToRemote(int slotIndex, int value) { + if (!this.suppressRemoteUpdates) { +- int _int = this.remoteDataSlots.getInt(slotIndex); +- if (_int != value) { ++ int k = this.remoteDataSlots.getInt(slotIndex); ++ ++ if (k != value) { + this.remoteDataSlots.set(slotIndex, value); + if (this.synchronizer != null) { + this.synchronizer.sendDataChange(this, slotIndex, value); + } + } ++ + } + } + +@@ -255,6 +341,7 @@ + this.synchronizer.sendCarriedChange(this, this.remoteCarried); + } + } ++ + } + } + +@@ -266,7 +353,7 @@ + if (slot >= 0 && slot < this.remoteSlots.size()) { + this.remoteSlots.set(slot, stack); + } else { +- LOGGER.debug("Incorrect slot index: {} available slots: {}", slot, this.remoteSlots.size()); ++ AbstractContainerMenu.LOGGER.debug("Incorrect slot index: {} available slots: {}", slot, this.remoteSlots.size()); + } + } + +@@ -279,33 +366,45 @@ + } + + public Slot getSlot(int slotId) { +- return this.slots.get(slotId); ++ return (Slot) this.slots.get(slotId); + } + + public abstract ItemStack quickMoveStack(Player player, int index); + +- public void clicked(int slotId, int button, ClickType clickType, Player player) { ++ public void clicked(int slotId, int button, InventoryClickType clickType, Player player) { + try { + this.doClick(slotId, button, clickType, player); +- } catch (Exception var8) { +- CrashReport crashReport = CrashReport.forThrowable(var8, "Container click"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Click info"); +- crashReportCategory.setDetail("Menu Type", () -> this.menuType != null ? BuiltInRegistries.MENU.getKey(this.menuType).toString() : ""); +- crashReportCategory.setDetail("Menu Class", () -> this.getClass().getCanonicalName()); +- crashReportCategory.setDetail("Slot Count", this.slots.size()); +- crashReportCategory.setDetail("Slot", slotId); +- crashReportCategory.setDetail("Button", button); +- crashReportCategory.setDetail("Type", clickType); +- throw new ReportedException(crashReport); ++ } catch (Exception exception) { ++ CrashReport crashreport = CrashReport.forThrowable(exception, "Container click"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Click info"); ++ ++ crashreportsystemdetails.setDetail("Menu Type", () -> { ++ return this.menuType != null ? BuiltInRegistries.MENU.getKey(this.menuType).toString() : ""; ++ }); ++ crashreportsystemdetails.setDetail("Menu Class", () -> { ++ return this.getClass().getCanonicalName(); ++ }); ++ crashreportsystemdetails.setDetail("Slot Count", (Object) this.slots.size()); ++ crashreportsystemdetails.setDetail("Slot", (Object) slotId); ++ crashreportsystemdetails.setDetail("Button", (Object) button); ++ crashreportsystemdetails.setDetail("Type", (Object) clickType); ++ throw new ReportedException(crashreport); + } + } + +- private void doClick(int slotId, int button, ClickType clickType, Player player) { +- Inventory inventory = player.getInventory(); +- if (clickType == ClickType.QUICK_CRAFT) { +- int i = this.quickcraftStatus; ++ private void doClick(int slotId, int button, InventoryClickType clickType, Player player) { ++ Inventory playerinventory = player.getInventory(); ++ Slot slot; ++ ItemStack itemstack; ++ int k; ++ ItemStack itemstack1; ++ int l; ++ ++ if (clickType == InventoryClickType.QUICK_CRAFT) { ++ int i1 = this.quickcraftStatus; ++ + this.quickcraftStatus = getQuickcraftHeader(button); +- if ((i != 1 || this.quickcraftStatus != 2) && i != this.quickcraftStatus) { ++ if ((i1 != 1 || this.quickcraftStatus != 2) && i1 != this.quickcraftStatus) { + this.resetQuickCraft(); + } else if (this.getCarried().isEmpty()) { + this.resetQuickCraft(); +@@ -318,48 +417,82 @@ + this.resetQuickCraft(); + } + } else if (this.quickcraftStatus == 1) { +- Slot slot = this.slots.get(slotId); +- ItemStack carried = this.getCarried(); +- if (canItemQuickReplace(slot, carried, true) +- && slot.mayPlace(carried) +- && (this.quickcraftType == 2 || carried.getCount() > this.quickcraftSlots.size()) +- && this.canDragTo(slot)) { ++ slot = (Slot) this.slots.get(slotId); ++ itemstack = this.getCarried(); ++ if (canItemQuickReplace(slot, itemstack, true) && slot.mayPlace(itemstack) && (this.quickcraftType == 2 || itemstack.getCount() > this.quickcraftSlots.size()) && this.canDragTo(slot)) { + this.quickcraftSlots.add(slot); + } + } else if (this.quickcraftStatus == 2) { + if (!this.quickcraftSlots.isEmpty()) { +- if (this.quickcraftSlots.size() == 1) { +- int i1 = this.quickcraftSlots.iterator().next().index; ++ if (false && this.quickcraftSlots.size() == 1) { // CraftBukkit - treat everything as a drag since we are unable to easily call InventoryClickEvent instead ++ k = ((Slot) this.quickcraftSlots.iterator().next()).index; + this.resetQuickCraft(); +- this.doClick(i1, this.quickcraftType, ClickType.PICKUP, player); ++ this.doClick(k, this.quickcraftType, InventoryClickType.PICKUP, player); + return; + } + +- ItemStack itemStack = this.getCarried().copy(); +- if (itemStack.isEmpty()) { ++ itemstack1 = this.getCarried().copy(); ++ if (itemstack1.isEmpty()) { + this.resetQuickCraft(); + return; + } + +- int count = this.getCarried().getCount(); ++ l = this.getCarried().getCount(); ++ Iterator iterator = this.quickcraftSlots.iterator(); + +- for (Slot slot1 : this.quickcraftSlots) { +- ItemStack carried1 = this.getCarried(); +- if (slot1 != null +- && canItemQuickReplace(slot1, carried1, true) +- && slot1.mayPlace(carried1) +- && (this.quickcraftType == 2 || carried1.getCount() >= this.quickcraftSlots.size()) +- && this.canDragTo(slot1)) { +- int i2 = slot1.hasItem() ? slot1.getItem().getCount() : 0; +- int min = Math.min(itemStack.getMaxStackSize(), slot1.getMaxStackSize(itemStack)); +- int min1 = Math.min(getQuickCraftPlaceCount(this.quickcraftSlots, this.quickcraftType, itemStack) + i2, min); +- count -= min1 - i2; +- slot1.setByPlayer(itemStack.copyWithCount(min1)); ++ Map draggedSlots = new HashMap(); // CraftBukkit - Store slots from drag in map (raw slot id -> new stack) ++ while (iterator.hasNext()) { ++ Slot slot1 = (Slot) iterator.next(); ++ ItemStack itemstack2 = this.getCarried(); ++ ++ if (slot1 != null && canItemQuickReplace(slot1, itemstack2, true) && slot1.mayPlace(itemstack2) && (this.quickcraftType == 2 || itemstack2.getCount() >= this.quickcraftSlots.size()) && this.canDragTo(slot1)) { ++ int j1 = slot1.hasItem() ? slot1.getItem().getCount() : 0; ++ int k1 = Math.min(itemstack1.getMaxStackSize(), slot1.getMaxStackSize(itemstack1)); ++ int l1 = Math.min(getQuickCraftPlaceCount(this.quickcraftSlots, this.quickcraftType, itemstack1) + j1, k1); ++ ++ l -= l1 - j1; ++ // slot1.setByPlayer(itemstack1.copyWithCount(l1)); ++ draggedSlots.put(slot1.index, itemstack1.copyWithCount(l1)); // CraftBukkit - Put in map instead of setting + } + } + +- itemStack.setCount(count); +- this.setCarried(itemStack); ++ // CraftBukkit start - InventoryDragEvent ++ InventoryView view = getBukkitView(); ++ org.bukkit.inventory.ItemStack newcursor = CraftItemStack.asCraftMirror(itemstack1); ++ newcursor.setAmount(l); ++ Map eventmap = new HashMap(); ++ for (Map.Entry ditem : draggedSlots.entrySet()) { ++ eventmap.put(ditem.getKey(), CraftItemStack.asBukkitCopy(ditem.getValue())); ++ } ++ ++ // It's essential that we set the cursor to the new value here to prevent item duplication if a plugin closes the inventory. ++ ItemStack oldCursor = this.getCarried(); ++ this.setCarried(CraftItemStack.asNMSCopy(newcursor)); ++ ++ InventoryDragEvent event = new InventoryDragEvent(view, (newcursor.getType() != org.bukkit.Material.AIR ? newcursor : null), CraftItemStack.asBukkitCopy(oldCursor), this.quickcraftType == 1, eventmap); ++ player.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ // Whether or not a change was made to the inventory that requires an update. ++ boolean needsUpdate = event.getResult() != Result.DEFAULT; ++ ++ if (event.getResult() != Result.DENY) { ++ for (Map.Entry dslot : draggedSlots.entrySet()) { ++ view.setItem(dslot.getKey(), CraftItemStack.asBukkitCopy(dslot.getValue())); ++ } ++ // The only time the carried item will be set to null is if the inventory is closed by the server. ++ // If the inventory is closed by the server, then the cursor items are dropped. This is why we change the cursor early. ++ if (this.getCarried() != null) { ++ this.setCarried(CraftItemStack.asNMSCopy(event.getCursor())); ++ needsUpdate = true; ++ } ++ } else { ++ this.setCarried(oldCursor); ++ } ++ ++ if (needsUpdate && player instanceof ServerPlayer) { ++ this.sendAllDataToRemote(); ++ } ++ // CraftBukkit end + } + + this.resetQuickCraft(); +@@ -368,154 +501,181 @@ + } + } else if (this.quickcraftStatus != 0) { + this.resetQuickCraft(); +- } else if ((clickType == ClickType.PICKUP || clickType == ClickType.QUICK_MOVE) && (button == 0 || button == 1)) { +- ClickAction clickAction = button == 0 ? ClickAction.PRIMARY : ClickAction.SECONDARY; +- if (slotId == -999) { +- if (!this.getCarried().isEmpty()) { +- if (clickAction == ClickAction.PRIMARY) { +- player.drop(this.getCarried(), true); +- this.setCarried(ItemStack.EMPTY); +- } else { +- player.drop(this.getCarried().split(1), true); ++ } else { ++ int i2; ++ ++ if ((clickType == InventoryClickType.PICKUP || clickType == InventoryClickType.QUICK_MOVE) && (button == 0 || button == 1)) { ++ ClickAction clickaction = button == 0 ? ClickAction.PRIMARY : ClickAction.SECONDARY; ++ ++ if (slotId == -999) { ++ if (!this.getCarried().isEmpty()) { ++ if (clickaction == ClickAction.PRIMARY) { ++ // CraftBukkit start ++ ItemStack carried = this.getCarried(); ++ this.setCarried(ItemStack.EMPTY); ++ player.drop(carried, true); ++ // CraftBukkit start ++ } else { ++ player.drop(this.getCarried().split(1), true); ++ } + } +- } +- } else if (clickType == ClickType.QUICK_MOVE) { +- if (slotId < 0) { +- return; +- } ++ } else if (clickType == InventoryClickType.QUICK_MOVE) { ++ if (slotId < 0) { ++ return; ++ } + +- Slot slot = this.slots.get(slotId); +- if (!slot.mayPickup(player)) { +- return; +- } ++ slot = (Slot) this.slots.get(slotId); ++ if (!slot.mayPickup(player)) { ++ return; ++ } + +- ItemStack carried = this.quickMoveStack(player, slotId); ++ for (itemstack = this.quickMoveStack(player, slotId); !itemstack.isEmpty() && ItemStack.isSameItem(slot.getItem(), itemstack); itemstack = this.quickMoveStack(player, slotId)) { ++ ; ++ } ++ } else { ++ if (slotId < 0) { ++ return; ++ } + +- while (!carried.isEmpty() && ItemStack.isSameItem(slot.getItem(), carried)) { +- carried = this.quickMoveStack(player, slotId); +- } +- } else { +- if (slotId < 0) { +- return; +- } ++ slot = (Slot) this.slots.get(slotId); ++ itemstack = slot.getItem(); ++ ItemStack itemstack3 = this.getCarried(); + +- Slot slot = this.slots.get(slotId); +- ItemStack carried = slot.getItem(); +- ItemStack carried2 = this.getCarried(); +- player.updateTutorialInventoryAction(carried2, slot.getItem(), clickAction); +- if (!this.tryItemClickBehaviourOverride(player, clickAction, slot, carried, carried2)) { +- if (carried.isEmpty()) { +- if (!carried2.isEmpty()) { +- int i3 = clickAction == ClickAction.PRIMARY ? carried2.getCount() : 1; +- this.setCarried(slot.safeInsert(carried2, i3)); +- } +- } else if (slot.mayPickup(player)) { +- if (carried2.isEmpty()) { +- int i3 = clickAction == ClickAction.PRIMARY ? carried.getCount() : (carried.getCount() + 1) / 2; +- Optional optional = slot.tryRemove(i3, Integer.MAX_VALUE, player); +- optional.ifPresent(stack -> { +- this.setCarried(stack); +- slot.onTake(player, stack); +- }); +- } else if (slot.mayPlace(carried2)) { +- if (ItemStack.isSameItemSameTags(carried, carried2)) { +- int i3 = clickAction == ClickAction.PRIMARY ? carried2.getCount() : 1; +- this.setCarried(slot.safeInsert(carried2, i3)); +- } else if (carried2.getCount() <= slot.getMaxStackSize(carried2)) { +- this.setCarried(carried); +- slot.setByPlayer(carried2); ++ player.updateTutorialInventoryAction(itemstack3, slot.getItem(), clickaction); ++ if (!this.tryItemClickBehaviourOverride(player, clickaction, slot, itemstack, itemstack3)) { ++ if (itemstack.isEmpty()) { ++ if (!itemstack3.isEmpty()) { ++ i2 = clickaction == ClickAction.PRIMARY ? itemstack3.getCount() : 1; ++ this.setCarried(slot.safeInsert(itemstack3, i2)); + } +- } else if (ItemStack.isSameItemSameTags(carried, carried2)) { +- Optional optional1 = slot.tryRemove(carried.getCount(), carried2.getMaxStackSize() - carried2.getCount(), player); +- optional1.ifPresent(stack -> { +- carried2.grow(stack.getCount()); +- slot.onTake(player, stack); +- }); ++ } else if (slot.mayPickup(player)) { ++ if (itemstack3.isEmpty()) { ++ i2 = clickaction == ClickAction.PRIMARY ? itemstack.getCount() : (itemstack.getCount() + 1) / 2; ++ Optional optional = slot.tryRemove(i2, Integer.MAX_VALUE, player); ++ ++ optional.ifPresent((itemstack4) -> { ++ this.setCarried(itemstack4); ++ slot.onTake(player, itemstack4); ++ }); ++ } else if (slot.mayPlace(itemstack3)) { ++ if (ItemStack.isSameItemSameTags(itemstack, itemstack3)) { ++ i2 = clickaction == ClickAction.PRIMARY ? itemstack3.getCount() : 1; ++ this.setCarried(slot.safeInsert(itemstack3, i2)); ++ } else if (itemstack3.getCount() <= slot.getMaxStackSize(itemstack3)) { ++ this.setCarried(itemstack); ++ slot.setByPlayer(itemstack3); ++ } ++ } else if (ItemStack.isSameItemSameTags(itemstack, itemstack3)) { ++ Optional optional1 = slot.tryRemove(itemstack.getCount(), itemstack3.getMaxStackSize() - itemstack3.getCount(), player); ++ ++ optional1.ifPresent((itemstack4) -> { ++ itemstack3.grow(itemstack4.getCount()); ++ slot.onTake(player, itemstack4); ++ }); ++ } + } + } +- } + +- slot.setChanged(); +- } +- } else if (clickType == ClickType.SWAP && (button >= 0 && button < 9 || button == 40)) { +- ItemStack item = inventory.getItem(button); +- Slot slot = this.slots.get(slotId); +- ItemStack carried = slot.getItem(); +- if (!item.isEmpty() || !carried.isEmpty()) { +- if (item.isEmpty()) { +- if (slot.mayPickup(player)) { +- inventory.setItem(button, carried); +- slot.onSwapCraft(carried.getCount()); +- slot.setByPlayer(ItemStack.EMPTY); +- slot.onTake(player, carried); +- } +- } else if (carried.isEmpty()) { +- if (slot.mayPlace(item)) { +- int maxStackSize = slot.getMaxStackSize(item); +- if (item.getCount() > maxStackSize) { +- slot.setByPlayer(item.split(maxStackSize)); +- } else { +- inventory.setItem(button, ItemStack.EMPTY); +- slot.setByPlayer(item); ++ slot.setChanged(); ++ // CraftBukkit start - Make sure the client has the right slot contents ++ if (player instanceof ServerPlayer && slot.getMaxStackSize() != 64) { ++ ((ServerPlayer) player).connection.send(new ClientboundContainerSetSlotPacket(this.containerId, this.incrementStateId(), slot.index, slot.getItem())); ++ // Updating a crafting inventory makes the client reset the result slot, have to send it again ++ if (this.getBukkitView().getType() == InventoryType.WORKBENCH || this.getBukkitView().getType() == InventoryType.CRAFTING) { ++ ((ServerPlayer) player).connection.send(new ClientboundContainerSetSlotPacket(this.containerId, this.incrementStateId(), 0, this.getSlot(0).getItem())); + } + } +- } else if (slot.mayPickup(player) && slot.mayPlace(item)) { +- int maxStackSize = slot.getMaxStackSize(item); +- if (item.getCount() > maxStackSize) { +- slot.setByPlayer(item.split(maxStackSize)); +- slot.onTake(player, carried); +- if (!inventory.add(carried)) { +- player.drop(carried, true); ++ // CraftBukkit end ++ } ++ } else { ++ int j2; ++ ++ if (clickType == InventoryClickType.SWAP && (button >= 0 && button < 9 || button == 40)) { ++ ItemStack itemstack4 = playerinventory.getItem(button); ++ ++ slot = (Slot) this.slots.get(slotId); ++ itemstack = slot.getItem(); ++ if (!itemstack4.isEmpty() || !itemstack.isEmpty()) { ++ if (itemstack4.isEmpty()) { ++ if (slot.mayPickup(player)) { ++ playerinventory.setItem(button, itemstack); ++ slot.onSwapCraft(itemstack.getCount()); ++ slot.setByPlayer(ItemStack.EMPTY); ++ slot.onTake(player, itemstack); ++ } ++ } else if (itemstack.isEmpty()) { ++ if (slot.mayPlace(itemstack4)) { ++ j2 = slot.getMaxStackSize(itemstack4); ++ if (itemstack4.getCount() > j2) { ++ slot.setByPlayer(itemstack4.split(j2)); ++ } else { ++ playerinventory.setItem(button, ItemStack.EMPTY); ++ slot.setByPlayer(itemstack4); ++ } ++ } ++ } else if (slot.mayPickup(player) && slot.mayPlace(itemstack4)) { ++ j2 = slot.getMaxStackSize(itemstack4); ++ if (itemstack4.getCount() > j2) { ++ slot.setByPlayer(itemstack4.split(j2)); ++ slot.onTake(player, itemstack); ++ if (!playerinventory.add(itemstack)) { ++ player.drop(itemstack, true); ++ } ++ } else { ++ playerinventory.setItem(button, itemstack); ++ slot.setByPlayer(itemstack4); ++ slot.onTake(player, itemstack); ++ } + } +- } else { +- inventory.setItem(button, carried); +- slot.setByPlayer(item); +- slot.onTake(player, carried); + } +- } +- } +- } else if (clickType == ClickType.CLONE && player.getAbilities().instabuild && this.getCarried().isEmpty() && slotId >= 0) { +- Slot slot2 = this.slots.get(slotId); +- if (slot2.hasItem()) { +- ItemStack itemStack = slot2.getItem(); +- this.setCarried(itemStack.copyWithCount(itemStack.getMaxStackSize())); +- } +- } else if (clickType == ClickType.THROW && this.getCarried().isEmpty() && slotId >= 0) { +- Slot slot2 = this.slots.get(slotId); +- int i1 = button == 0 ? 1 : slot2.getItem().getCount(); +- ItemStack carried = slot2.safeTake(i1, Integer.MAX_VALUE, player); +- player.drop(carried, true); +- } else if (clickType == ClickType.PICKUP_ALL && slotId >= 0) { +- Slot slot2 = this.slots.get(slotId); +- ItemStack itemStack = this.getCarried(); +- if (!itemStack.isEmpty() && (!slot2.hasItem() || !slot2.mayPickup(player))) { +- int count = button == 0 ? 0 : this.slots.size() - 1; +- int maxStackSize = button == 0 ? 1 : -1; ++ } else { ++ Slot slot2; + +- for (int i3 = 0; i3 < 2; i3++) { +- for (int i4 = count; i4 >= 0 && i4 < this.slots.size() && itemStack.getCount() < itemStack.getMaxStackSize(); i4 += maxStackSize) { +- Slot slot3 = this.slots.get(i4); +- if (slot3.hasItem() +- && canItemQuickReplace(slot3, itemStack, true) +- && slot3.mayPickup(player) +- && this.canTakeItemForPickAll(itemStack, slot3)) { +- ItemStack item1 = slot3.getItem(); +- if (i3 != 0 || item1.getCount() != item1.getMaxStackSize()) { +- ItemStack itemStack1 = slot3.safeTake(item1.getCount(), itemStack.getMaxStackSize() - itemStack.getCount(), player); +- itemStack.grow(itemStack1.getCount()); ++ if (clickType == InventoryClickType.CLONE && player.getAbilities().instabuild && this.getCarried().isEmpty() && slotId >= 0) { ++ slot2 = (Slot) this.slots.get(slotId); ++ if (slot2.hasItem()) { ++ itemstack1 = slot2.getItem(); ++ this.setCarried(itemstack1.copyWithCount(itemstack1.getMaxStackSize())); ++ } ++ } else if (clickType == InventoryClickType.THROW && this.getCarried().isEmpty() && slotId >= 0) { ++ slot2 = (Slot) this.slots.get(slotId); ++ k = button == 0 ? 1 : slot2.getItem().getCount(); ++ itemstack = slot2.safeTake(k, Integer.MAX_VALUE, player); ++ player.drop(itemstack, true); ++ } else if (clickType == InventoryClickType.PICKUP_ALL && slotId >= 0) { ++ slot2 = (Slot) this.slots.get(slotId); ++ itemstack1 = this.getCarried(); ++ if (!itemstack1.isEmpty() && (!slot2.hasItem() || !slot2.mayPickup(player))) { ++ l = button == 0 ? 0 : this.slots.size() - 1; ++ j2 = button == 0 ? 1 : -1; ++ ++ for (i2 = 0; i2 < 2; ++i2) { ++ for (int k2 = l; k2 >= 0 && k2 < this.slots.size() && itemstack1.getCount() < itemstack1.getMaxStackSize(); k2 += j2) { ++ Slot slot3 = (Slot) this.slots.get(k2); ++ ++ if (slot3.hasItem() && canItemQuickReplace(slot3, itemstack1, true) && slot3.mayPickup(player) && this.canTakeItemForPickAll(itemstack1, slot3)) { ++ ItemStack itemstack5 = slot3.getItem(); ++ ++ if (i2 != 0 || itemstack5.getCount() != itemstack5.getMaxStackSize()) { ++ ItemStack itemstack6 = slot3.safeTake(itemstack5.getCount(), itemstack1.getMaxStackSize() - itemstack1.getCount(), player); ++ ++ itemstack1.grow(itemstack6.getCount()); ++ } ++ } ++ } + } + } + } + } + } + } ++ + } + + private boolean tryItemClickBehaviourOverride(Player player, ClickAction action, Slot slot, ItemStack clickedItem, ItemStack carriedItem) { +- FeatureFlagSet featureFlagSet = player.level().enabledFeatures(); +- return carriedItem.isItemEnabled(featureFlagSet) && carriedItem.overrideStackedOnOther(slot, action, player) +- || clickedItem.isItemEnabled(featureFlagSet) +- && clickedItem.overrideOtherStackedOnMe(carriedItem, slot, action, player, this.createCarriedSlotAccess()); ++ FeatureFlagSet featureflagset = player.level().enabledFeatures(); ++ ++ return carriedItem.isItemEnabled(featureflagset) && carriedItem.overrideStackedOnOther(slot, action, player) ? true : clickedItem.isItemEnabled(featureflagset) && clickedItem.overrideOtherStackedOnMe(carriedItem, slot, action, player, this.createCarriedSlotAccess()); + } + + private SlotAccess createCarriedSlotAccess() { +@@ -539,31 +699,39 @@ + + public void removed(Player player) { + if (player instanceof ServerPlayer) { +- ItemStack carried = this.getCarried(); +- if (!carried.isEmpty()) { +- if (player.isAlive() && !((ServerPlayer)player).hasDisconnected()) { +- player.getInventory().placeItemBackInInventory(carried); ++ ItemStack itemstack = this.getCarried(); ++ ++ if (!itemstack.isEmpty()) { ++ this.setCarried(ItemStack.EMPTY); // CraftBukkit - SPIGOT-4556 - from below ++ if (player.isAlive() && !((ServerPlayer) player).hasDisconnected()) { ++ player.getInventory().placeItemBackInInventory(itemstack); + } else { +- player.drop(carried, false); ++ player.drop(itemstack, false); + } + +- this.setCarried(ItemStack.EMPTY); ++ // this.setCarried(ItemStack.EMPTY); // CraftBukkit - moved up + } + } ++ + } + + protected void clearContainer(Player player, Container container) { +- if (!player.isAlive() || player instanceof ServerPlayer && ((ServerPlayer)player).hasDisconnected()) { +- for (int i = 0; i < container.getContainerSize(); i++) { +- player.drop(container.removeItemNoUpdate(i), false); ++ int i; ++ ++ if (player.isAlive() && (!(player instanceof ServerPlayer) || !((ServerPlayer) player).hasDisconnected())) { ++ for (i = 0; i < container.getContainerSize(); ++i) { ++ Inventory playerinventory = player.getInventory(); ++ ++ if (playerinventory.player instanceof ServerPlayer) { ++ playerinventory.placeItemBackInInventory(container.removeItemNoUpdate(i)); ++ } + } ++ + } else { +- for (int i = 0; i < container.getContainerSize(); i++) { +- Inventory inventory = player.getInventory(); +- if (inventory.player instanceof ServerPlayer) { +- inventory.placeItemBackInInventory(container.removeItemNoUpdate(i)); +- } ++ for (i = 0; i < container.getContainerSize(); ++i) { ++ player.drop(container.removeItemNoUpdate(i), false); + } ++ + } + } + +@@ -577,8 +745,8 @@ + } + + public void initializeContents(int stateId, List items, ItemStack carried) { +- for (int i = 0; i < items.size(); i++) { +- this.getSlot(i).set(items.get(i)); ++ for (int j = 0; j < items.size(); ++j) { ++ this.getSlot(j).set((ItemStack) items.get(j)); + } + + this.carried = carried; +@@ -586,76 +754,97 @@ + } + + public void setData(int id, int data) { +- this.dataSlots.get(id).set(data); ++ ((DataSlot) this.dataSlots.get(id)).set(data); + } + + public abstract boolean stillValid(Player player); + + protected boolean moveItemStackTo(ItemStack stack, int startIndex, int endIndex, boolean reverseDirection) { +- boolean flag = false; +- int i = startIndex; ++ boolean flag1 = false; ++ int k = startIndex; ++ + if (reverseDirection) { +- i = endIndex - 1; ++ k = endIndex - 1; + } + ++ Slot slot; ++ ItemStack itemstack1; ++ + if (stack.isStackable()) { +- while (!stack.isEmpty() && (reverseDirection ? i >= startIndex : i < endIndex)) { +- Slot slot = this.slots.get(i); +- ItemStack item = slot.getItem(); +- if (!item.isEmpty() && ItemStack.isSameItemSameTags(stack, item)) { +- int i1 = item.getCount() + stack.getCount(); +- if (i1 <= stack.getMaxStackSize()) { ++ while (!stack.isEmpty()) { ++ if (reverseDirection) { ++ if (k < startIndex) { ++ break; ++ } ++ } else if (k >= endIndex) { ++ break; ++ } ++ ++ slot = (Slot) this.slots.get(k); ++ itemstack1 = slot.getItem(); ++ if (!itemstack1.isEmpty() && ItemStack.isSameItemSameTags(stack, itemstack1)) { ++ int l = itemstack1.getCount() + stack.getCount(); ++ ++ if (l <= stack.getMaxStackSize()) { + stack.setCount(0); +- item.setCount(i1); ++ itemstack1.setCount(l); + slot.setChanged(); +- flag = true; +- } else if (item.getCount() < stack.getMaxStackSize()) { +- stack.shrink(stack.getMaxStackSize() - item.getCount()); +- item.setCount(stack.getMaxStackSize()); ++ flag1 = true; ++ } else if (itemstack1.getCount() < stack.getMaxStackSize()) { ++ stack.shrink(stack.getMaxStackSize() - itemstack1.getCount()); ++ itemstack1.setCount(stack.getMaxStackSize()); + slot.setChanged(); +- flag = true; ++ flag1 = true; + } + } + + if (reverseDirection) { +- i--; ++ --k; + } else { +- i++; ++ ++k; + } + } + } + + if (!stack.isEmpty()) { + if (reverseDirection) { +- i = endIndex - 1; ++ k = endIndex - 1; + } else { +- i = startIndex; ++ k = startIndex; + } + +- while (reverseDirection ? i >= startIndex : i < endIndex) { +- Slot slotx = this.slots.get(i); +- ItemStack itemx = slotx.getItem(); +- if (itemx.isEmpty() && slotx.mayPlace(stack)) { +- if (stack.getCount() > slotx.getMaxStackSize()) { +- slotx.setByPlayer(stack.split(slotx.getMaxStackSize())); ++ while (true) { ++ if (reverseDirection) { ++ if (k < startIndex) { ++ break; ++ } ++ } else if (k >= endIndex) { ++ break; ++ } ++ ++ slot = (Slot) this.slots.get(k); ++ itemstack1 = slot.getItem(); ++ if (itemstack1.isEmpty() && slot.mayPlace(stack)) { ++ if (stack.getCount() > slot.getMaxStackSize()) { ++ slot.setByPlayer(stack.split(slot.getMaxStackSize())); + } else { +- slotx.setByPlayer(stack.split(stack.getCount())); ++ slot.setByPlayer(stack.split(stack.getCount())); + } + +- slotx.setChanged(); +- flag = true; ++ slot.setChanged(); ++ flag1 = true; + break; + } + + if (reverseDirection) { +- i--; ++ --k; + } else { +- i++; ++ ++k; + } + } + } + +- return flag; ++ return flag1; + } + + public static int getQuickcraftType(int eventButton) { +@@ -671,7 +860,7 @@ + } + + public static boolean isValidQuickcraftType(int dragMode, Player player) { +- return dragMode == 0 || dragMode == 1 || dragMode == 2 && player.getAbilities().instabuild; ++ return dragMode == 0 ? true : (dragMode == 1 ? true : dragMode == 2 && player.getAbilities().instabuild); + } + + protected void resetQuickCraft() { +@@ -680,19 +869,29 @@ + } + + public static boolean canItemQuickReplace(@Nullable Slot slot, ItemStack stack, boolean stackSizeMatters) { +- boolean flag = slot == null || !slot.hasItem(); +- return !flag && ItemStack.isSameItemSameTags(stack, slot.getItem()) +- ? slot.getItem().getCount() + (stackSizeMatters ? 0 : stack.getCount()) <= stack.getMaxStackSize() +- : flag; ++ boolean flag1 = slot == null || !slot.hasItem(); ++ ++ return !flag1 && ItemStack.isSameItemSameTags(stack, slot.getItem()) ? slot.getItem().getCount() + (stackSizeMatters ? 0 : stack.getCount()) <= stack.getMaxStackSize() : flag1; + } + + public static int getQuickCraftPlaceCount(Set slots, int type, ItemStack stack) { +- return switch (type) { +- case 0 -> Mth.floor((float)stack.getCount() / (float)slots.size()); +- case 1 -> 1; +- case 2 -> stack.getItem().getMaxStackSize(); +- default -> stack.getCount(); +- }; ++ int j; ++ ++ switch (type) { ++ case 0: ++ j = Mth.floor((float) stack.getCount() / (float) slots.size()); ++ break; ++ case 1: ++ j = 1; ++ break; ++ case 2: ++ j = stack.getItem().getMaxStackSize(); ++ break; ++ default: ++ j = stack.getCount(); ++ } ++ ++ return j; + } + + public boolean canDragTo(Slot slot) { +@@ -700,7 +899,7 @@ + } + + public static int getRedstoneSignalFromBlockEntity(@Nullable BlockEntity blockEntity) { +- return blockEntity instanceof Container ? getRedstoneSignalFromContainer((Container)blockEntity) : 0; ++ return blockEntity instanceof Container ? getRedstoneSignalFromContainer((Container) blockEntity) : 0; + } + + public static int getRedstoneSignalFromContainer(@Nullable Container container) { +@@ -709,14 +908,15 @@ + } else { + float f = 0.0F; + +- for (int i = 0; i < container.getContainerSize(); i++) { +- ItemStack item = container.getItem(i); +- if (!item.isEmpty()) { +- f += (float)item.getCount() / (float)Math.min(container.getMaxStackSize(), item.getMaxStackSize()); ++ for (int i = 0; i < container.getContainerSize(); ++i) { ++ ItemStack itemstack = container.getItem(i); ++ ++ if (!itemstack.isEmpty()) { ++ f += (float) itemstack.getCount() / (float) Math.min(container.getMaxStackSize(), itemstack.getMaxStackSize()); + } + } + +- f /= (float)container.getContainerSize(); ++ f /= (float) container.getContainerSize(); + return Mth.lerpDiscrete(f, 0, 15); + } + } +@@ -726,6 +926,11 @@ + } + + public ItemStack getCarried() { ++ // CraftBukkit start ++ if (this.carried.isEmpty()) { ++ this.setCarried(ItemStack.EMPTY); ++ } ++ // CraftBukkit end + return this.carried; + } + +@@ -740,26 +945,32 @@ + public void transferState(AbstractContainerMenu menu) { + Table table = HashBasedTable.create(); + +- for (int i = 0; i < menu.slots.size(); i++) { +- Slot slot = menu.slots.get(i); ++ Slot slot; ++ int i; ++ ++ for (i = 0; i < menu.slots.size(); ++i) { ++ slot = (Slot) menu.slots.get(i); + table.put(slot.container, slot.getContainerSlot(), i); + } + +- for (int i = 0; i < this.slots.size(); i++) { +- Slot slot = this.slots.get(i); +- Integer integer = table.get(slot.container, slot.getContainerSlot()); ++ for (i = 0; i < this.slots.size(); ++i) { ++ slot = (Slot) this.slots.get(i); ++ Integer integer = (Integer) table.get(slot.container, slot.getContainerSlot()); ++ + if (integer != null) { +- this.lastSlots.set(i, menu.lastSlots.get(integer)); +- this.remoteSlots.set(i, menu.remoteSlots.get(integer)); ++ this.lastSlots.set(i, (ItemStack) menu.lastSlots.get(integer)); ++ this.remoteSlots.set(i, (ItemStack) menu.remoteSlots.get(integer)); + } + } ++ + } + + public OptionalInt findSlot(Container container, int slotIndex) { +- for (int i = 0; i < this.slots.size(); i++) { +- Slot slot = this.slots.get(i); ++ for (int j = 0; j < this.slots.size(); ++j) { ++ Slot slot = (Slot) this.slots.get(j); ++ + if (slot.container == container && slotIndex == slot.getContainerSlot()) { +- return OptionalInt.of(i); ++ return OptionalInt.of(j); + } + } + diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/AbstractFurnaceMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/AbstractFurnaceMenu.java.patch new file mode 100644 index 0000000000..b44c8b90b9 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/AbstractFurnaceMenu.java.patch @@ -0,0 +1,207 @@ +--- a/net/minecraft/world/inventory/AbstractFurnaceMenu.java ++++ b/net/minecraft/world/inventory/AbstractFurnaceMenu.java +@@ -13,8 +13,13 @@ + import net.minecraft.world.item.crafting.RecipeType; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryFurnace; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + + public abstract class AbstractFurnaceMenu extends RecipeBookMenu { ++ + public static final int INGREDIENT_SLOT = 0; + public static final int FUEL_SLOT = 1; + public static final int RESULT_SLOT = 2; +@@ -30,21 +35,27 @@ + private final RecipeType recipeType; + private final RecipeBookType recipeBookType; + +- protected AbstractFurnaceMenu( +- MenuType menuType, RecipeType recipeType, RecipeBookType recipeBookType, int containerId, Inventory playerInventory +- ) { ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryFurnace inventory = new CraftInventoryFurnace((AbstractFurnaceBlockEntity) this.container); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end ++ ++ protected AbstractFurnaceMenu(MenuType menuType, RecipeType recipeType, RecipeBookType recipeBookType, int containerId, Inventory playerInventory) { + this(menuType, recipeType, recipeBookType, containerId, playerInventory, new SimpleContainer(3), new SimpleContainerData(4)); + } + +- protected AbstractFurnaceMenu( +- MenuType menuType, +- RecipeType recipeType, +- RecipeBookType recipeBookType, +- int containerId, +- Inventory playerInventory, +- Container container, +- ContainerData data +- ) { ++ protected AbstractFurnaceMenu(MenuType menuType, RecipeType recipeType, RecipeBookType recipeBookType, int containerId, Inventory playerInventory, Container container, ContainerData data) { + super(menuType, containerId); + this.recipeType = recipeType; + this.recipeBookType = recipeBookType; +@@ -56,15 +67,18 @@ + this.addSlot(new Slot(container, 0, 56, 17)); + this.addSlot(new FurnaceFuelSlot(this, container, 1, 56, 53)); + this.addSlot(new FurnaceResultSlot(playerInventory.player, container, 2, 116, 35)); ++ this.player = playerInventory; // CraftBukkit - save player + +- for (int i = 0; i < 3; i++) { +- for (int i1 = 0; i1 < 9; i1++) { +- this.addSlot(new Slot(playerInventory, i1 + i * 9 + 9, 8 + i1 * 18, 84 + i * 18)); ++ int j; ++ ++ for (j = 0; j < 3; ++j) { ++ for (int k = 0; k < 9; ++k) { ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); + } + } + +- for (int i = 0; i < 9; i++) { +- this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142)); ++ for (j = 0; j < 9; ++j) { ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } + + this.addDataSlots(data); +@@ -73,8 +87,9 @@ + @Override + public void fillCraftSlotsStackedContents(StackedContents itemHelper) { + if (this.container instanceof StackedContentsCompatible) { +- ((StackedContentsCompatible)this.container).fillStackedContents(itemHelper); ++ ((StackedContentsCompatible) this.container).fillStackedContents(itemHelper); + } ++ + } + + @Override +@@ -84,8 +99,8 @@ + } + + @Override +- public boolean recipeMatches(RecipeHolder> recipeHolder) { +- return recipeHolder.value().matches(this.container, this.level); ++ public boolean recipeMatches(RecipeHolder> recipeholder) { ++ return recipeholder.value().matches(this.container, this.level); + } + + @Override +@@ -110,60 +125,63 @@ + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(player); + } + + @Override + public ItemStack quickMoveStack(Player player, int index) { +- ItemStack itemStack = ItemStack.EMPTY; +- Slot slot = this.slots.get(index); ++ ItemStack itemstack = ItemStack.EMPTY; ++ Slot slot = (Slot) this.slots.get(index); ++ + if (slot != null && slot.hasItem()) { +- ItemStack item = slot.getItem(); +- itemStack = item.copy(); ++ ItemStack itemstack1 = slot.getItem(); ++ ++ itemstack = itemstack1.copy(); + if (index == 2) { +- if (!this.moveItemStackTo(item, 3, 39, true)) { ++ if (!this.moveItemStackTo(itemstack1, 3, 39, true)) { + return ItemStack.EMPTY; + } + +- slot.onQuickCraft(item, itemStack); ++ slot.onQuickCraft(itemstack1, itemstack); + } else if (index != 1 && index != 0) { +- if (this.canSmelt(item)) { +- if (!this.moveItemStackTo(item, 0, 1, false)) { ++ if (this.canSmelt(itemstack1)) { ++ if (!this.moveItemStackTo(itemstack1, 0, 1, false)) { + return ItemStack.EMPTY; + } +- } else if (this.isFuel(item)) { +- if (!this.moveItemStackTo(item, 1, 2, false)) { ++ } else if (this.isFuel(itemstack1)) { ++ if (!this.moveItemStackTo(itemstack1, 1, 2, false)) { + return ItemStack.EMPTY; + } + } else if (index >= 3 && index < 30) { +- if (!this.moveItemStackTo(item, 30, 39, false)) { ++ if (!this.moveItemStackTo(itemstack1, 30, 39, false)) { + return ItemStack.EMPTY; + } +- } else if (index >= 30 && index < 39 && !this.moveItemStackTo(item, 3, 30, false)) { ++ } else if (index >= 30 && index < 39 && !this.moveItemStackTo(itemstack1, 3, 30, false)) { + return ItemStack.EMPTY; + } +- } else if (!this.moveItemStackTo(item, 3, 39, false)) { ++ } else if (!this.moveItemStackTo(itemstack1, 3, 39, false)) { + return ItemStack.EMPTY; + } + +- if (item.isEmpty()) { ++ if (itemstack1.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + +- if (item.getCount() == itemStack.getCount()) { ++ if (itemstack1.getCount() == itemstack.getCount()) { + return ItemStack.EMPTY; + } + +- slot.onTake(player, item); ++ slot.onTake(player, itemstack1); + } + +- return itemStack; ++ return itemstack; + } + + protected boolean canSmelt(ItemStack stack) { +- return this.level.getRecipeManager().getRecipeFor(this.recipeType, new SimpleContainer(stack), this.level).isPresent(); ++ return this.level.getRecipeManager().getRecipeFor((RecipeType) this.recipeType, new SimpleContainer(new ItemStack[]{stack}), this.level).isPresent(); // Eclipse fail + } + + protected boolean isFuel(ItemStack stack) { +@@ -172,17 +190,19 @@ + + public float getBurnProgress() { + int i = this.data.get(2); +- int i1 = this.data.get(3); +- return i1 != 0 && i != 0 ? Mth.clamp((float)i / (float)i1, 0.0F, 1.0F) : 0.0F; ++ int j = this.data.get(3); ++ ++ return j != 0 && i != 0 ? Mth.clamp((float) i / (float) j, 0.0F, 1.0F) : 0.0F; + } + + public float getLitProgress() { + int i = this.data.get(1); ++ + if (i == 0) { + i = 200; + } + +- return Mth.clamp((float)this.data.get(0) / (float)i, 0.0F, 1.0F); ++ return Mth.clamp((float) this.data.get(0) / (float) i, 0.0F, 1.0F); + } + + public boolean isLit() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/AnvilMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/AnvilMenu.java.patch new file mode 100644 index 0000000000..4bf0394d19 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/AnvilMenu.java.patch @@ -0,0 +1,470 @@ +--- a/net/minecraft/world/inventory/AnvilMenu.java ++++ b/net/minecraft/world/inventory/AnvilMenu.java +@@ -1,11 +1,11 @@ + package net.minecraft.world.inventory; + + import com.mojang.logging.LogUtils; ++import java.util.Iterator; + import java.util.Map; + import javax.annotation.Nullable; + import net.minecraft.SharedConstants; + import net.minecraft.Util; +-import net.minecraft.core.BlockPos; + import net.minecraft.network.chat.Component; + import net.minecraft.tags.BlockTags; + import net.minecraft.world.entity.player.Inventory; +@@ -15,22 +15,26 @@ + import net.minecraft.world.item.Items; + import net.minecraft.world.item.enchantment.Enchantment; + import net.minecraft.world.item.enchantment.EnchantmentHelper; +-import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.AnvilBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class AnvilMenu extends ItemCombinerMenu { ++ + public static final int INPUT_SLOT = 0; + public static final int ADDITIONAL_SLOT = 1; + public static final int RESULT_SLOT = 2; + private static final Logger LOGGER = LogUtils.getLogger(); + private static final boolean DEBUG_COST = false; + public static final int MAX_NAME_LENGTH = 50; +- private int repairItemCountCost; ++ public int repairItemCountCost; + @Nullable +- private String itemName; +- private final DataSlot cost = DataSlot.standalone(); ++ public String itemName; ++ public final DataSlot cost; + private static final int COST_FAIL = 0; + private static final int COST_BASE = 1; + private static final int COST_ADDED_BASE = 1; +@@ -42,6 +46,11 @@ + private static final int ADDITIONAL_SLOT_X_PLACEMENT = 76; + private static final int RESULT_SLOT_X_PLACEMENT = 134; + private static final int SLOT_Y_PLACEMENT = 47; ++ // CraftBukkit start ++ public static final int DEFAULT_DENIED_COST = -1; ++ public int maximumRepairCost = 40; ++ private CraftInventoryView bukkitEntity; ++ // CraftBukkit end + + public AnvilMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, ContainerLevelAccess.NULL); +@@ -49,26 +58,27 @@ + + public AnvilMenu(int containerId, Inventory playerInventory, ContainerLevelAccess access) { + super(MenuType.ANVIL, containerId, playerInventory, access); ++ this.cost = DataSlot.standalone(); + this.addDataSlot(this.cost); + } + + @Override + protected ItemCombinerMenuSlotDefinition createInputSlotDefinitions() { +- return ItemCombinerMenuSlotDefinition.create() +- .withSlot(0, 27, 47, itemStack -> true) +- .withSlot(1, 76, 47, itemStack -> true) +- .withResultSlot(2, 134, 47) +- .build(); ++ return ItemCombinerMenuSlotDefinition.create().withSlot(0, 27, 47, (itemstack) -> { ++ return true; ++ }).withSlot(1, 76, 47, (itemstack) -> { ++ return true; ++ }).withResultSlot(2, 134, 47).build(); + } + + @Override +- protected boolean isValidBlock(BlockState state) { ++ protected boolean isValidBlock(IBlockData state) { + return state.is(BlockTags.ANVIL); + } + + @Override + protected boolean mayPickup(Player player, boolean hasStack) { +- return (player.getAbilities().instabuild || player.experienceLevel >= this.cost.get()) && this.cost.get() > 0; ++ return (player.getAbilities().instabuild || player.experienceLevel >= this.cost.get()) && this.cost.get() > AnvilMenu.DEFAULT_DENIED_COST && hasStack; // CraftBukkit - allow cost 0 like a free item + } + + @Override +@@ -79,10 +89,11 @@ + + this.inputSlots.setItem(0, ItemStack.EMPTY); + if (this.repairItemCountCost > 0) { +- ItemStack item = this.inputSlots.getItem(1); +- if (!item.isEmpty() && item.getCount() > this.repairItemCountCost) { +- item.shrink(this.repairItemCountCost); +- this.inputSlots.setItem(1, item); ++ ItemStack itemstack1 = this.inputSlots.getItem(1); ++ ++ if (!itemstack1.isEmpty() && itemstack1.getCount() > this.repairItemCountCost) { ++ itemstack1.shrink(this.repairItemCountCost); ++ this.inputSlots.setItem(1, itemstack1); + } else { + this.inputSlots.setItem(1, ItemStack.EMPTY); + } +@@ -90,133 +101,153 @@ + this.inputSlots.setItem(1, ItemStack.EMPTY); + } + +- this.cost.set(0); +- this.access.execute((level, blockPos) -> { +- BlockState blockState = level.getBlockState(blockPos); +- if (!player.getAbilities().instabuild && blockState.is(BlockTags.ANVIL) && player.getRandom().nextFloat() < 0.12F) { +- BlockState blockState1 = AnvilBlock.damage(blockState); +- if (blockState1 == null) { +- level.removeBlock(blockPos, false); +- level.levelEvent(1029, blockPos, 0); ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item ++ this.access.execute((world, blockposition) -> { ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ ++ if (!player.getAbilities().instabuild && iblockdata.is(BlockTags.ANVIL) && player.getRandom().nextFloat() < 0.12F) { ++ IBlockData iblockdata1 = AnvilBlock.damage(iblockdata); ++ ++ if (iblockdata1 == null) { ++ world.removeBlock(blockposition, false); ++ world.levelEvent(1029, blockposition, 0); + } else { +- level.setBlock(blockPos, blockState1, 2); +- level.levelEvent(1030, blockPos, 0); ++ world.setBlock(blockposition, iblockdata1, 2); ++ world.levelEvent(1030, blockposition, 0); + } + } else { +- level.levelEvent(1030, blockPos, 0); ++ world.levelEvent(1030, blockposition, 0); + } ++ + }); + } + + @Override + public void createResult() { +- ItemStack item = this.inputSlots.getItem(0); ++ ItemStack itemstack = this.inputSlots.getItem(0); ++ + this.cost.set(1); + int i = 0; +- int i1 = 0; +- int i2 = 0; +- if (item.isEmpty()) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- this.cost.set(0); ++ byte b0 = 0; ++ byte b1 = 0; ++ ++ if (itemstack.isEmpty()) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + } else { +- ItemStack itemStack = item.copy(); +- ItemStack item1 = this.inputSlots.getItem(1); +- Map enchantments = EnchantmentHelper.getEnchantments(itemStack); +- int var19 = i1 + item.getBaseRepairCost() + (item1.isEmpty() ? 0 : item1.getBaseRepairCost()); ++ ItemStack itemstack1 = itemstack.copy(); ++ ItemStack itemstack2 = this.inputSlots.getItem(1); ++ Map map = EnchantmentHelper.getEnchantments(itemstack1); ++ int j = b0 + itemstack.getBaseRepairCost() + (itemstack2.isEmpty() ? 0 : itemstack2.getBaseRepairCost()); ++ + this.repairItemCountCost = 0; +- if (!item1.isEmpty()) { +- boolean flag = item1.is(Items.ENCHANTED_BOOK) && !EnchantedBookItem.getEnchantments(item1).isEmpty(); +- if (itemStack.isDamageableItem() && itemStack.getItem().isValidRepairItem(item, item1)) { +- int min = Math.min(itemStack.getDamageValue(), itemStack.getMaxDamage() / 4); +- if (min <= 0) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- this.cost.set(0); ++ if (!itemstack2.isEmpty()) { ++ boolean flag = itemstack2.is(Items.ENCHANTED_BOOK) && !EnchantedBookItem.getEnchantments(itemstack2).isEmpty(); ++ int k; ++ int l; ++ int i1; ++ ++ if (itemstack1.isDamageableItem() && itemstack1.getItem().isValidRepairItem(itemstack, itemstack2)) { ++ k = Math.min(itemstack1.getDamageValue(), itemstack1.getMaxDamage() / 4); ++ if (k <= 0) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + return; + } + +- int i3; +- for (i3 = 0; min > 0 && i3 < item1.getCount(); i3++) { +- int i4 = itemStack.getDamageValue() - min; +- itemStack.setDamageValue(i4); +- i++; +- min = Math.min(itemStack.getDamageValue(), itemStack.getMaxDamage() / 4); ++ for (i1 = 0; k > 0 && i1 < itemstack2.getCount(); ++i1) { ++ l = itemstack1.getDamageValue() - k; ++ itemstack1.setDamageValue(l); ++ ++i; ++ k = Math.min(itemstack1.getDamageValue(), itemstack1.getMaxDamage() / 4); + } + +- this.repairItemCountCost = i3; ++ this.repairItemCountCost = i1; + } else { +- if (!flag && (!itemStack.is(item1.getItem()) || !itemStack.isDamageableItem())) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- this.cost.set(0); ++ if (!flag && (!itemstack1.is(itemstack2.getItem()) || !itemstack1.isDamageableItem())) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + return; + } + +- if (itemStack.isDamageableItem() && !flag) { +- int minx = item.getMaxDamage() - item.getDamageValue(); +- int i3 = item1.getMaxDamage() - item1.getDamageValue(); +- int i4 = i3 + itemStack.getMaxDamage() * 12 / 100; +- int i5 = minx + i4; +- int i6 = itemStack.getMaxDamage() - i5; +- if (i6 < 0) { +- i6 = 0; ++ if (itemstack1.isDamageableItem() && !flag) { ++ k = itemstack.getMaxDamage() - itemstack.getDamageValue(); ++ i1 = itemstack2.getMaxDamage() - itemstack2.getDamageValue(); ++ l = i1 + itemstack1.getMaxDamage() * 12 / 100; ++ int j1 = k + l; ++ int k1 = itemstack1.getMaxDamage() - j1; ++ ++ if (k1 < 0) { ++ k1 = 0; + } + +- if (i6 < itemStack.getDamageValue()) { +- itemStack.setDamageValue(i6); ++ if (k1 < itemstack1.getDamageValue()) { ++ itemstack1.setDamageValue(k1); + i += 2; + } + } + +- Map enchantments1 = EnchantmentHelper.getEnchantments(item1); ++ Map map1 = EnchantmentHelper.getEnchantments(itemstack2); + boolean flag1 = false; + boolean flag2 = false; ++ Iterator iterator = map1.keySet().iterator(); + +- for (Enchantment enchantment : enchantments1.keySet()) { ++ while (iterator.hasNext()) { ++ Enchantment enchantment = (Enchantment) iterator.next(); ++ + if (enchantment != null) { +- int i7 = enchantments.getOrDefault(enchantment, 0); +- int i8 = enchantments1.get(enchantment); +- int var29 = i7 == i8 ? i8 + 1 : Math.max(i8, i7); +- boolean canEnchant = enchantment.canEnchant(item); +- if (this.player.getAbilities().instabuild || item.is(Items.ENCHANTED_BOOK)) { +- canEnchant = true; ++ int l1 = (Integer) map.getOrDefault(enchantment, 0); ++ int i2 = (Integer) map1.get(enchantment); ++ ++ i2 = l1 == i2 ? i2 + 1 : Math.max(i2, l1); ++ boolean flag3 = enchantment.canEnchant(itemstack); ++ ++ if (this.player.getAbilities().instabuild || itemstack.is(Items.ENCHANTED_BOOK)) { ++ flag3 = true; + } + +- for (Enchantment enchantment1 : enchantments.keySet()) { ++ Iterator iterator1 = map.keySet().iterator(); ++ ++ while (iterator1.hasNext()) { ++ Enchantment enchantment1 = (Enchantment) iterator1.next(); ++ + if (enchantment1 != enchantment && !enchantment.isCompatibleWith(enchantment1)) { +- canEnchant = false; +- i++; ++ flag3 = false; ++ ++i; + } + } + +- if (!canEnchant) { ++ if (!flag3) { + flag2 = true; + } else { + flag1 = true; +- if (var29 > enchantment.getMaxLevel()) { +- var29 = enchantment.getMaxLevel(); ++ if (i2 > enchantment.getMaxLevel()) { ++ i2 = enchantment.getMaxLevel(); + } + +- enchantments.put(enchantment, var29); +- int i9 = 0; ++ map.put(enchantment, i2); ++ int j2 = 0; ++ + switch (enchantment.getRarity()) { + case COMMON: +- i9 = 1; ++ j2 = 1; + break; + case UNCOMMON: +- i9 = 2; ++ j2 = 2; + break; + case RARE: +- i9 = 4; ++ j2 = 4; + break; + case VERY_RARE: +- i9 = 8; ++ j2 = 8; + } + + if (flag) { +- i9 = Math.max(1, i9 / 2); ++ j2 = Math.max(1, j2 / 2); + } + +- i += i9 * var29; +- if (item.getCount() > 1) { ++ i += j2 * i2; ++ if (itemstack.getCount() > 1) { + i = 40; + } + } +@@ -224,53 +255,55 @@ + } + + if (flag2 && !flag1) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- this.cost.set(0); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + return; + } + } + } + + if (this.itemName != null && !Util.isBlank(this.itemName)) { +- if (!this.itemName.equals(item.getHoverName().getString())) { +- i2 = 1; +- i += i2; +- itemStack.setHoverName(Component.literal(this.itemName)); ++ if (!this.itemName.equals(itemstack.getHoverName().getString())) { ++ b1 = 1; ++ i += b1; ++ itemstack1.setHoverName(Component.literal(this.itemName)); + } +- } else if (item.hasCustomHoverName()) { +- i2 = 1; +- i += i2; +- itemStack.resetHoverName(); ++ } else if (itemstack.hasCustomHoverName()) { ++ b1 = 1; ++ i += b1; ++ itemstack1.resetHoverName(); + } + +- this.cost.set(var19 + i); ++ this.cost.set(j + i); + if (i <= 0) { +- itemStack = ItemStack.EMPTY; ++ itemstack1 = ItemStack.EMPTY; + } + +- if (i2 == i && i2 > 0 && this.cost.get() >= 40) { +- this.cost.set(39); ++ if (b1 == i && b1 > 0 && this.cost.get() >= maximumRepairCost) { // CraftBukkit ++ this.cost.set(maximumRepairCost - 1); // CraftBukkit + } + +- if (this.cost.get() >= 40 && !this.player.getAbilities().instabuild) { +- itemStack = ItemStack.EMPTY; ++ if (this.cost.get() >= maximumRepairCost && !this.player.getAbilities().instabuild) { // CraftBukkit ++ itemstack1 = ItemStack.EMPTY; + } + +- if (!itemStack.isEmpty()) { +- int baseRepairCost = itemStack.getBaseRepairCost(); +- if (!item1.isEmpty() && baseRepairCost < item1.getBaseRepairCost()) { +- baseRepairCost = item1.getBaseRepairCost(); ++ if (!itemstack1.isEmpty()) { ++ int k2 = itemstack1.getBaseRepairCost(); ++ ++ if (!itemstack2.isEmpty() && k2 < itemstack2.getBaseRepairCost()) { ++ k2 = itemstack2.getBaseRepairCost(); + } + +- if (i2 != i || i2 == 0) { +- baseRepairCost = calculateIncreasedRepairCost(baseRepairCost); ++ if (b1 != i || b1 == 0) { ++ k2 = calculateIncreasedRepairCost(k2); + } + +- itemStack.setRepairCost(baseRepairCost); +- EnchantmentHelper.setEnchantments(enchantments, itemStack); ++ itemstack1.setRepairCost(k2); ++ EnchantmentHelper.setEnchantments(map, itemstack1); + } + +- this.resultSlots.setItem(0, itemStack); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), itemstack1); // CraftBukkit ++ sendAllDataToRemote(); // CraftBukkit - SPIGOT-6686: Always send completed inventory to stay in sync with client + this.broadcastChanges(); + } + } +@@ -280,15 +313,17 @@ + } + + public boolean setItemName(String itemName) { +- String string = validateName(itemName); +- if (string != null && !string.equals(this.itemName)) { +- this.itemName = string; ++ String s1 = validateName(itemName); ++ ++ if (s1 != null && !s1.equals(this.itemName)) { ++ this.itemName = s1; + if (this.getSlot(2).hasItem()) { +- ItemStack item = this.getSlot(2).getItem(); +- if (Util.isBlank(string)) { +- item.resetHoverName(); ++ ItemStack itemstack = this.getSlot(2).getItem(); ++ ++ if (Util.isBlank(s1)) { ++ itemstack.resetHoverName(); + } else { +- item.setHoverName(Component.literal(string)); ++ itemstack.setHoverName(Component.literal(s1)); + } + } + +@@ -301,11 +336,26 @@ + + @Nullable + private static String validateName(String itemName) { +- String string = SharedConstants.filterText(itemName); +- return string.length() <= 50 ? string : null; ++ String s1 = SharedConstants.filterText(itemName); ++ ++ return s1.length() <= 50 ? s1 : null; + } + + public int getCost() { + return this.cost.get(); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventory inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryAnvil( ++ access.getLocation(), this.inputSlots, this.resultSlots, this); ++ bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/BeaconMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/BeaconMenu.java.patch new file mode 100644 index 0000000000..ae5d159144 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/BeaconMenu.java.patch @@ -0,0 +1,240 @@ +--- a/net/minecraft/world/inventory/BeaconMenu.java ++++ b/net/minecraft/world/inventory/BeaconMenu.java +@@ -7,12 +7,16 @@ + import net.minecraft.world.Container; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.effect.MobEffect; ++import net.minecraft.world.entity.player.Inventory; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + + public class BeaconMenu extends AbstractContainerMenu { ++ + private static final int PAYMENT_SLOT = 0; + private static final int SLOT_COUNT = 1; + private static final int DATA_COUNT = 3; +@@ -21,20 +25,14 @@ + private static final int USE_ROW_SLOT_START = 28; + private static final int USE_ROW_SLOT_END = 37; + private static final int NO_EFFECT = 0; +- private final Container beacon = new SimpleContainer(1) { +- @Override +- public boolean canPlaceItem(int index, ItemStack stack) { +- return stack.is(ItemTags.BEACON_PAYMENT_ITEMS); +- } +- +- @Override +- public int getMaxStackSize() { +- return 1; +- } +- }; ++ private final Container beacon; + private final BeaconMenu.PaymentSlot paymentSlot; + private final ContainerLevelAccess access; + private final ContainerData beaconData; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ // CraftBukkit end + + public BeaconMenu(int containerId, Container container) { + this(containerId, container, new SimpleContainerData(3), ContainerLevelAccess.NULL); +@@ -42,39 +40,57 @@ + + public BeaconMenu(int containerId, Container container, ContainerData beaconData, ContainerLevelAccess access) { + super(MenuType.BEACON, containerId); ++ player = (Inventory) container; // CraftBukkit - TODO: check this ++ this.beacon = new SimpleContainer(1) { ++ @Override ++ public boolean canPlaceItem(int index, ItemStack stack) { ++ return stack.is(ItemTags.BEACON_PAYMENT_ITEMS); ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return 1; ++ } ++ }; + checkContainerDataCount(beaconData, 3); + this.beaconData = beaconData; + this.access = access; + this.paymentSlot = new BeaconMenu.PaymentSlot(this.beacon, 0, 136, 110); + this.addSlot(this.paymentSlot); + this.addDataSlots(beaconData); +- int i = 36; +- int i1 = 137; ++ boolean flag = true; ++ boolean flag1 = true; + +- for (int i2 = 0; i2 < 3; i2++) { +- for (int i3 = 0; i3 < 9; i3++) { +- this.addSlot(new Slot(container, i3 + i2 * 9 + 9, 36 + i3 * 18, 137 + i2 * 18)); ++ int j; ++ ++ for (j = 0; j < 3; ++j) { ++ for (int k = 0; k < 9; ++k) { ++ this.addSlot(new Slot(container, k + j * 9 + 9, 36 + k * 18, 137 + j * 18)); + } + } + +- for (int i2 = 0; i2 < 9; i2++) { +- this.addSlot(new Slot(container, i2, 36 + i2 * 18, 195)); ++ for (j = 0; j < 9; ++j) { ++ this.addSlot(new Slot(container, j, 36 + j * 18, 195)); + } ++ + } + + @Override + public void removed(Player player) { + super.removed(player); + if (!player.level().isClientSide) { +- ItemStack itemStack = this.paymentSlot.remove(this.paymentSlot.getMaxStackSize()); +- if (!itemStack.isEmpty()) { +- player.drop(itemStack, false); ++ ItemStack itemstack = this.paymentSlot.remove(this.paymentSlot.getMaxStackSize()); ++ ++ if (!itemstack.isEmpty()) { ++ player.drop(itemstack, false); + } ++ + } + } + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.BEACON); + } + +@@ -86,60 +102,62 @@ + + @Override + public ItemStack quickMoveStack(Player player, int index) { +- ItemStack itemStack = ItemStack.EMPTY; +- Slot slot = this.slots.get(index); ++ ItemStack itemstack = ItemStack.EMPTY; ++ Slot slot = (Slot) this.slots.get(index); ++ + if (slot != null && slot.hasItem()) { +- ItemStack item = slot.getItem(); +- itemStack = item.copy(); ++ ItemStack itemstack1 = slot.getItem(); ++ ++ itemstack = itemstack1.copy(); + if (index == 0) { +- if (!this.moveItemStackTo(item, 1, 37, true)) { ++ if (!this.moveItemStackTo(itemstack1, 1, 37, true)) { + return ItemStack.EMPTY; + } + +- slot.onQuickCraft(item, itemStack); +- } else if (!this.paymentSlot.hasItem() && this.paymentSlot.mayPlace(item) && item.getCount() == 1) { +- if (!this.moveItemStackTo(item, 0, 1, false)) { ++ slot.onQuickCraft(itemstack1, itemstack); ++ } else if (!this.paymentSlot.hasItem() && this.paymentSlot.mayPlace(itemstack1) && itemstack1.getCount() == 1) { ++ if (!this.moveItemStackTo(itemstack1, 0, 1, false)) { + return ItemStack.EMPTY; + } + } else if (index >= 1 && index < 28) { +- if (!this.moveItemStackTo(item, 28, 37, false)) { ++ if (!this.moveItemStackTo(itemstack1, 28, 37, false)) { + return ItemStack.EMPTY; + } + } else if (index >= 28 && index < 37) { +- if (!this.moveItemStackTo(item, 1, 28, false)) { ++ if (!this.moveItemStackTo(itemstack1, 1, 28, false)) { + return ItemStack.EMPTY; + } +- } else if (!this.moveItemStackTo(item, 1, 37, false)) { ++ } else if (!this.moveItemStackTo(itemstack1, 1, 37, false)) { + return ItemStack.EMPTY; + } + +- if (item.isEmpty()) { ++ if (itemstack1.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + +- if (item.getCount() == itemStack.getCount()) { ++ if (itemstack1.getCount() == itemstack.getCount()) { + return ItemStack.EMPTY; + } + +- slot.onTake(player, item); ++ slot.onTake(player, itemstack1); + } + +- return itemStack; ++ return itemstack; + } + + public int getLevels() { + return this.beaconData.get(0); + } + +- public static int encodeEffect(@Nullable MobEffect mobEffect) { +- return mobEffect == null ? 0 : BuiltInRegistries.MOB_EFFECT.getId(mobEffect) + 1; ++ public static int encodeEffect(@Nullable MobEffect mobeffectlist) { ++ return mobeffectlist == null ? 0 : BuiltInRegistries.MOB_EFFECT.getId(mobeffectlist) + 1; + } + + @Nullable + public static MobEffect decodeEffect(int i) { +- return i == 0 ? null : BuiltInRegistries.MOB_EFFECT.byId(i - 1); ++ return i == 0 ? null : (MobEffect) BuiltInRegistries.MOB_EFFECT.byId(i - 1); + } + + @Nullable +@@ -154,20 +172,22 @@ + + public void updateEffects(Optional primaryEffect, Optional secondaryEffect) { + if (this.paymentSlot.hasItem()) { +- this.beaconData.set(1, encodeEffect(primaryEffect.orElse(null))); +- this.beaconData.set(2, encodeEffect(secondaryEffect.orElse(null))); ++ this.beaconData.set(1, encodeEffect((MobEffect) primaryEffect.orElse(null))); // CraftBukkit - decompile error ++ this.beaconData.set(2, encodeEffect((MobEffect) secondaryEffect.orElse(null))); // CraftBukkit - decompile error + this.paymentSlot.remove(1); + this.access.execute(Level::blockEntityChanged); + } ++ + } + + public boolean hasPayment() { + return !this.beacon.getItem(0).isEmpty(); + } + +- class PaymentSlot extends Slot { +- public PaymentSlot(Container container, int containerIndex, int xPosition, int yPosition) { +- super(container, containerIndex, xPosition, yPosition); ++ private class PaymentSlot extends Slot { ++ ++ public PaymentSlot(Container container, int slot, int x, int y) { ++ super(container, slot, x, y); + } + + @Override +@@ -180,4 +200,17 @@ + return 1; + } + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventory inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryBeacon(this.beacon); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/BrewingStandMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/BrewingStandMenu.java.patch new file mode 100644 index 0000000000..b8eb8c074e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/BrewingStandMenu.java.patch @@ -0,0 +1,247 @@ +--- a/net/minecraft/world/inventory/BrewingStandMenu.java ++++ b/net/minecraft/world/inventory/BrewingStandMenu.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.inventory; + + import net.minecraft.advancements.CriteriaTriggers; ++import net.minecraft.core.Holder; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.Container; + import net.minecraft.world.SimpleContainer; +@@ -11,8 +12,13 @@ + import net.minecraft.world.item.alchemy.Potion; + import net.minecraft.world.item.alchemy.PotionBrewing; + import net.minecraft.world.item.alchemy.PotionUtils; ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryBrewer; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + + public class BrewingStandMenu extends AbstractContainerMenu { ++ + private static final int BOTTLE_SLOT_START = 0; + private static final int BOTTLE_SLOT_END = 2; + private static final int INGREDIENT_SLOT = 3; +@@ -27,12 +33,18 @@ + private final ContainerData brewingStandData; + private final Slot ingredientSlot; + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ // CraftBukkit end ++ + public BrewingStandMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, new SimpleContainer(5), new SimpleContainerData(2)); + } + + public BrewingStandMenu(int containerId, Inventory playerInventory, Container brewingStandContainer, ContainerData brewingStandData) { + super(MenuType.BREWING_STAND, containerId); ++ player = playerInventory; // CraftBukkit + checkContainerSize(brewingStandContainer, 5); + checkContainerDataCount(brewingStandData, 2); + this.brewingStand = brewingStandContainer; +@@ -44,75 +56,81 @@ + this.addSlot(new BrewingStandMenu.FuelSlot(brewingStandContainer, 4, 17, 17)); + this.addDataSlots(brewingStandData); + +- for (int i = 0; i < 3; i++) { +- for (int i1 = 0; i1 < 9; i1++) { +- this.addSlot(new Slot(playerInventory, i1 + i * 9 + 9, 8 + i1 * 18, 84 + i * 18)); ++ int j; ++ ++ for (j = 0; j < 3; ++j) { ++ for (int k = 0; k < 9; ++k) { ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); + } + } + +- for (int i = 0; i < 9; i++) { +- this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142)); ++ for (j = 0; j < 9; ++j) { ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } ++ + } + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.brewingStand.stillValid(player); + } + + @Override + public ItemStack quickMoveStack(Player player, int index) { +- ItemStack itemStack = ItemStack.EMPTY; +- Slot slot = this.slots.get(index); ++ ItemStack itemstack = ItemStack.EMPTY; ++ Slot slot = (Slot) this.slots.get(index); ++ + if (slot != null && slot.hasItem()) { +- ItemStack item = slot.getItem(); +- itemStack = item.copy(); ++ ItemStack itemstack1 = slot.getItem(); ++ ++ itemstack = itemstack1.copy(); + if ((index < 0 || index > 2) && index != 3 && index != 4) { +- if (BrewingStandMenu.FuelSlot.mayPlaceItem(itemStack)) { +- if (this.moveItemStackTo(item, 4, 5, false) || this.ingredientSlot.mayPlace(item) && !this.moveItemStackTo(item, 3, 4, false)) { ++ if (BrewingStandMenu.FuelSlot.mayPlaceItem(itemstack)) { ++ if (this.moveItemStackTo(itemstack1, 4, 5, false) || this.ingredientSlot.mayPlace(itemstack1) && !this.moveItemStackTo(itemstack1, 3, 4, false)) { + return ItemStack.EMPTY; + } +- } else if (this.ingredientSlot.mayPlace(item)) { +- if (!this.moveItemStackTo(item, 3, 4, false)) { ++ } else if (this.ingredientSlot.mayPlace(itemstack1)) { ++ if (!this.moveItemStackTo(itemstack1, 3, 4, false)) { + return ItemStack.EMPTY; + } +- } else if (BrewingStandMenu.PotionSlot.mayPlaceItem(itemStack) && itemStack.getCount() == 1) { +- if (!this.moveItemStackTo(item, 0, 3, false)) { ++ } else if (BrewingStandMenu.PotionSlot.mayPlaceItem(itemstack) && itemstack.getCount() == 1) { ++ if (!this.moveItemStackTo(itemstack1, 0, 3, false)) { + return ItemStack.EMPTY; + } + } else if (index >= 5 && index < 32) { +- if (!this.moveItemStackTo(item, 32, 41, false)) { ++ if (!this.moveItemStackTo(itemstack1, 32, 41, false)) { + return ItemStack.EMPTY; + } + } else if (index >= 32 && index < 41) { +- if (!this.moveItemStackTo(item, 5, 32, false)) { ++ if (!this.moveItemStackTo(itemstack1, 5, 32, false)) { + return ItemStack.EMPTY; + } +- } else if (!this.moveItemStackTo(item, 5, 41, false)) { ++ } else if (!this.moveItemStackTo(itemstack1, 5, 41, false)) { + return ItemStack.EMPTY; + } + } else { +- if (!this.moveItemStackTo(item, 5, 41, true)) { ++ if (!this.moveItemStackTo(itemstack1, 5, 41, true)) { + return ItemStack.EMPTY; + } + +- slot.onQuickCraft(item, itemStack); ++ slot.onQuickCraft(itemstack1, itemstack); + } + +- if (item.isEmpty()) { ++ if (itemstack1.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + +- if (item.getCount() == itemStack.getCount()) { ++ if (itemstack1.getCount() == itemstack.getCount()) { + return ItemStack.EMPTY; + } + +- slot.onTake(player, item); ++ slot.onTake(player, itemstack1); + } + +- return itemStack; ++ return itemstack; + } + + public int getFuel() { +@@ -123,8 +141,9 @@ + return this.brewingStandData.get(0); + } + +- static class FuelSlot extends Slot { +- public FuelSlot(Container container, int slot, int x, int y) { ++ private static class PotionSlot extends Slot { ++ ++ public PotionSlot(Container container, int slot, int x, int y) { + super(container, slot, x, y); + } + +@@ -133,17 +152,29 @@ + return mayPlaceItem(stack); + } + +- public static boolean mayPlaceItem(ItemStack itemStack) { +- return itemStack.is(Items.BLAZE_POWDER); ++ @Override ++ public int getMaxStackSize() { ++ return 1; + } + + @Override +- public int getMaxStackSize() { +- return 64; ++ public void onTake(Player player, ItemStack stack) { ++ Potion potionregistry = PotionUtils.getPotion(stack); ++ ++ if (player instanceof ServerPlayer) { ++ CriteriaTriggers.BREWED_POTION.trigger((ServerPlayer) player, (Holder) potionregistry.builtInRegistryHolder()); ++ } ++ ++ super.onTake(player, stack); + } ++ ++ public static boolean mayPlaceItem(ItemStack stack) { ++ return stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE); ++ } + } + +- static class IngredientsSlot extends Slot { ++ private static class IngredientsSlot extends Slot { ++ + public IngredientsSlot(Container container, int slot, int x, int y) { + super(container, slot, x, y); + } +@@ -159,8 +190,9 @@ + } + } + +- static class PotionSlot extends Slot { +- public PotionSlot(Container container, int slot, int x, int y) { ++ private static class FuelSlot extends Slot { ++ ++ public FuelSlot(Container container, int slot, int x, int y) { + super(container, slot, x, y); + } + +@@ -169,23 +201,26 @@ + return mayPlaceItem(stack); + } + +- @Override +- public int getMaxStackSize() { +- return 1; ++ public static boolean mayPlaceItem(ItemStack itemStack) { ++ return itemStack.is(Items.BLAZE_POWDER); + } + + @Override +- public void onTake(Player player, ItemStack stack) { +- Potion potion = PotionUtils.getPotion(stack); +- if (player instanceof ServerPlayer) { +- CriteriaTriggers.BREWED_POTION.trigger((ServerPlayer)player, potion.builtInRegistryHolder()); +- } +- +- super.onTake(player, stack); ++ public int getMaxStackSize() { ++ return 64; + } ++ } + +- public static boolean mayPlaceItem(ItemStack stack) { +- return stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE); ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; + } ++ ++ CraftInventoryBrewer inventory = new CraftInventoryBrewer(this.brewingStand); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; + } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/CartographyTableMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/CartographyTableMenu.java.patch new file mode 100644 index 0000000000..2fd70c98be --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/CartographyTableMenu.java.patch @@ -0,0 +1,312 @@ +--- a/net/minecraft/world/inventory/CartographyTableMenu.java ++++ b/net/minecraft/world/inventory/CartographyTableMenu.java +@@ -1,20 +1,39 @@ + package net.minecraft.world.inventory; + +-import net.minecraft.core.BlockPos; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.Container; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.entity.player.Inventory; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.item.MapItem; +-import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.saveddata.maps.MapItemSavedData; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.inventory.CraftInventoryCartography; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class CartographyTableMenu extends AbstractContainerMenu { ++ ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryCartography inventory = new CraftInventoryCartography(this.container, this.resultContainer); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + public static final int MAP_SLOT = 0; + public static final int ADDITIONAL_SLOT = 1; + public static final int RESULT_SLOT = 2; +@@ -24,20 +43,8 @@ + private static final int USE_ROW_SLOT_END = 39; + private final ContainerLevelAccess access; + long lastSoundTime; +- public final Container container = new SimpleContainer(2) { +- @Override +- public void setChanged() { +- CartographyTableMenu.this.slotsChanged(this); +- super.setChanged(); +- } +- }; +- private final ResultContainer resultContainer = new ResultContainer() { +- @Override +- public void setChanged() { +- CartographyTableMenu.this.slotsChanged(this); +- super.setChanged(); +- } +- }; ++ public final Container container; ++ private final ResultContainer resultContainer; + + public CartographyTableMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, ContainerLevelAccess.NULL); +@@ -45,6 +52,34 @@ + + public CartographyTableMenu(int containerId, Inventory playerInventory, final ContainerLevelAccess access) { + super(MenuType.CARTOGRAPHY_TABLE, containerId); ++ this.container = new SimpleContainer(2) { ++ @Override ++ public void setChanged() { ++ CartographyTableMenu.this.slotsChanged(this); ++ super.setChanged(); ++ } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end ++ }; ++ this.resultContainer = new ResultContainer() { ++ @Override ++ public void setChanged() { ++ CartographyTableMenu.this.slotsChanged(this); ++ super.setChanged(); ++ } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end ++ }; + this.access = access; + this.addSlot(new Slot(this.container, 0, 15, 15) { + @Override +@@ -65,63 +100,72 @@ + } + + @Override +- public void onTake(Player player, ItemStack stack) { +- CartographyTableMenu.this.slots.get(0).remove(1); +- CartographyTableMenu.this.slots.get(1).remove(1); ++ public void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) { ++ ((Slot) CartographyTableMenu.this.slots.get(0)).remove(1); ++ ((Slot) CartographyTableMenu.this.slots.get(1)).remove(1); + stack.getItem().onCraftedBy(stack, player.level(), player); +- access.execute((level, blockPos) -> { +- long gameTime = level.getGameTime(); +- if (CartographyTableMenu.this.lastSoundTime != gameTime) { +- level.playSound(null, blockPos, SoundEvents.UI_CARTOGRAPHY_TABLE_TAKE_RESULT, SoundSource.BLOCKS, 1.0F, 1.0F); +- CartographyTableMenu.this.lastSoundTime = gameTime; ++ access.execute((world, blockposition) -> { ++ long j = world.getGameTime(); ++ ++ if (CartographyTableMenu.this.lastSoundTime != j) { ++ world.playSound((net.minecraft.world.entity.player.Player) null, blockposition, SoundEvents.UI_CARTOGRAPHY_TABLE_TAKE_RESULT, SoundSource.BLOCKS, 1.0F, 1.0F); ++ CartographyTableMenu.this.lastSoundTime = j; + } ++ + }); + super.onTake(player, stack); + } + }); + +- for (int i = 0; i < 3; i++) { +- for (int i1 = 0; i1 < 9; i1++) { +- this.addSlot(new Slot(playerInventory, i1 + i * 9 + 9, 8 + i1 * 18, 84 + i * 18)); ++ int j; ++ ++ for (j = 0; j < 3; ++j) { ++ for (int k = 0; k < 9; ++k) { ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); + } + } + +- for (int i = 0; i < 9; i++) { +- this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142)); ++ for (j = 0; j < 9; ++j) { ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } ++ ++ player = (Player) playerInventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.CARTOGRAPHY_TABLE); + } + + @Override + public void slotsChanged(Container inventory) { +- ItemStack item = this.container.getItem(0); +- ItemStack item1 = this.container.getItem(1); +- ItemStack item2 = this.resultContainer.getItem(2); +- if (item2.isEmpty() || !item.isEmpty() && !item1.isEmpty()) { +- if (!item.isEmpty() && !item1.isEmpty()) { +- this.setupResultSlot(item, item1, item2); +- } +- } else { ++ ItemStack itemstack = this.container.getItem(0); ++ ItemStack itemstack1 = this.container.getItem(1); ++ ItemStack itemstack2 = this.resultContainer.getItem(2); ++ ++ if (!itemstack2.isEmpty() && (itemstack.isEmpty() || itemstack1.isEmpty())) { + this.resultContainer.removeItemNoUpdate(2); ++ } else if (!itemstack.isEmpty() && !itemstack1.isEmpty()) { ++ this.setupResultSlot(itemstack, itemstack1, itemstack2); + } ++ + } + + private void setupResultSlot(ItemStack map, ItemStack firstSlotStack, ItemStack resultOutput) { +- this.access.execute((level, blockPos) -> { +- MapItemSavedData savedData = MapItem.getSavedData(map, level); +- if (savedData != null) { +- ItemStack itemStack; +- if (firstSlotStack.is(Items.PAPER) && !savedData.locked && savedData.scale < 4) { +- itemStack = map.copyWithCount(1); +- itemStack.getOrCreateTag().putInt("map_scale_direction", 1); ++ this.access.execute((world, blockposition) -> { ++ MapItemSavedData worldmap = MapItem.getSavedData(map, world); ++ ++ if (worldmap != null) { ++ ItemStack itemstack3; ++ ++ if (firstSlotStack.is(Items.PAPER) && !worldmap.locked && worldmap.scale < 4) { ++ itemstack3 = map.copyWithCount(1); ++ itemstack3.getOrCreateTag().putInt("map_scale_direction", 1); + this.broadcastChanges(); +- } else if (firstSlotStack.is(Items.GLASS_PANE) && !savedData.locked) { +- itemStack = map.copyWithCount(1); +- itemStack.getOrCreateTag().putBoolean("map_to_lock", true); ++ } else if (firstSlotStack.is(Items.GLASS_PANE) && !worldmap.locked) { ++ itemstack3 = map.copyWithCount(1); ++ itemstack3.getOrCreateTag().putBoolean("map_to_lock", true); + this.broadcastChanges(); + } else { + if (!firstSlotStack.is(Items.MAP)) { +@@ -130,14 +174,15 @@ + return; + } + +- itemStack = map.copyWithCount(2); ++ itemstack3 = map.copyWithCount(2); + this.broadcastChanges(); + } + +- if (!ItemStack.matches(itemStack, resultOutput)) { +- this.resultContainer.setItem(2, itemStack); ++ if (!ItemStack.matches(itemstack3, resultOutput)) { ++ this.resultContainer.setItem(2, itemstack3); + this.broadcastChanges(); + } ++ + } + }); + } +@@ -148,59 +193,63 @@ + } + + @Override +- public ItemStack quickMoveStack(Player player, int index) { +- ItemStack itemStack = ItemStack.EMPTY; +- Slot slot = this.slots.get(index); ++ public ItemStack quickMoveStack(net.minecraft.world.entity.player.Player player, int index) { ++ ItemStack itemstack = ItemStack.EMPTY; ++ Slot slot = (Slot) this.slots.get(index); ++ + if (slot != null && slot.hasItem()) { +- ItemStack item = slot.getItem(); +- itemStack = item.copy(); ++ ItemStack itemstack1 = slot.getItem(); ++ ++ itemstack = itemstack1.copy(); + if (index == 2) { +- item.getItem().onCraftedBy(item, player.level(), player); +- if (!this.moveItemStackTo(item, 3, 39, true)) { ++ itemstack1.getItem().onCraftedBy(itemstack1, player.level(), player); ++ if (!this.moveItemStackTo(itemstack1, 3, 39, true)) { + return ItemStack.EMPTY; + } + +- slot.onQuickCraft(item, itemStack); ++ slot.onQuickCraft(itemstack1, itemstack); + } else if (index != 1 && index != 0) { +- if (item.is(Items.FILLED_MAP)) { +- if (!this.moveItemStackTo(item, 0, 1, false)) { ++ if (itemstack1.is(Items.FILLED_MAP)) { ++ if (!this.moveItemStackTo(itemstack1, 0, 1, false)) { + return ItemStack.EMPTY; + } +- } else if (!item.is(Items.PAPER) && !item.is(Items.MAP) && !item.is(Items.GLASS_PANE)) { ++ } else if (!itemstack1.is(Items.PAPER) && !itemstack1.is(Items.MAP) && !itemstack1.is(Items.GLASS_PANE)) { + if (index >= 3 && index < 30) { +- if (!this.moveItemStackTo(item, 30, 39, false)) { ++ if (!this.moveItemStackTo(itemstack1, 30, 39, false)) { + return ItemStack.EMPTY; + } +- } else if (index >= 30 && index < 39 && !this.moveItemStackTo(item, 3, 30, false)) { ++ } else if (index >= 30 && index < 39 && !this.moveItemStackTo(itemstack1, 3, 30, false)) { + return ItemStack.EMPTY; + } +- } else if (!this.moveItemStackTo(item, 1, 2, false)) { ++ } else if (!this.moveItemStackTo(itemstack1, 1, 2, false)) { + return ItemStack.EMPTY; + } +- } else if (!this.moveItemStackTo(item, 3, 39, false)) { ++ } else if (!this.moveItemStackTo(itemstack1, 3, 39, false)) { + return ItemStack.EMPTY; + } + +- if (item.isEmpty()) { ++ if (itemstack1.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } + + slot.setChanged(); +- if (item.getCount() == itemStack.getCount()) { ++ if (itemstack1.getCount() == itemstack.getCount()) { + return ItemStack.EMPTY; + } + +- slot.onTake(player, item); ++ slot.onTake(player, itemstack1); + this.broadcastChanges(); + } + +- return itemStack; ++ return itemstack; + } + + @Override +- public void removed(Player player) { ++ public void removed(net.minecraft.world.entity.player.Player player) { + super.removed(player); + this.resultContainer.removeItemNoUpdate(2); +- this.access.execute((level, blockPos) -> this.clearContainer(player, this.container)); ++ this.access.execute((world, blockposition) -> { ++ this.clearContainer(player, this.container); ++ }); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/ChestMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/ChestMenu.java.patch new file mode 100644 index 0000000000..b4144d2714 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/ChestMenu.java.patch @@ -0,0 +1,129 @@ +--- a/net/minecraft/world/inventory/ChestMenu.java ++++ b/net/minecraft/world/inventory/ChestMenu.java +@@ -1,16 +1,44 @@ + package net.minecraft.world.inventory; + ++import net.minecraft.world.CompoundContainer; + import net.minecraft.world.Container; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.entity.player.Inventory; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + + public class ChestMenu extends AbstractContainerMenu { ++ + private static final int SLOTS_PER_ROW = 9; + private final Container container; + private final int containerRows; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; + ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventory inventory; ++ if (this.container instanceof Inventory) { ++ inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryPlayer((Inventory) this.container); ++ } else if (this.container instanceof CompoundContainer) { ++ inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) this.container); ++ } else { ++ inventory = new CraftInventory(this.container); ++ } ++ ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end ++ + private ChestMenu(MenuType type, int containerId, Inventory playerInventory, int rows) { + this(type, containerId, playerInventory, new SimpleContainer(9 * rows), rows); + } +@@ -53,53 +81,64 @@ + this.container = container; + this.containerRows = rows; + container.startOpen(playerInventory.player); +- int i = (this.containerRows - 4) * 18; ++ int k = (this.containerRows - 4) * 18; + +- for (int i1 = 0; i1 < this.containerRows; i1++) { +- for (int i2 = 0; i2 < 9; i2++) { +- this.addSlot(new Slot(container, i2 + i1 * 9, 8 + i2 * 18, 18 + i1 * 18)); ++ // CraftBukkit start - Save player ++ this.player = playerInventory; ++ // CraftBukkit end ++ ++ int l; ++ int i1; ++ ++ for (l = 0; l < this.containerRows; ++l) { ++ for (i1 = 0; i1 < 9; ++i1) { ++ this.addSlot(new Slot(container, i1 + l * 9, 8 + i1 * 18, 18 + l * 18)); + } + } + +- for (int i1 = 0; i1 < 3; i1++) { +- for (int i2 = 0; i2 < 9; i2++) { +- this.addSlot(new Slot(playerInventory, i2 + i1 * 9 + 9, 8 + i2 * 18, 103 + i1 * 18 + i)); ++ for (l = 0; l < 3; ++l) { ++ for (i1 = 0; i1 < 9; ++i1) { ++ this.addSlot(new Slot(playerInventory, i1 + l * 9 + 9, 8 + i1 * 18, 103 + l * 18 + k)); + } + } + +- for (int i1 = 0; i1 < 9; i1++) { +- this.addSlot(new Slot(playerInventory, i1, 8 + i1 * 18, 161 + i)); ++ for (l = 0; l < 9; ++l) { ++ this.addSlot(new Slot(playerInventory, l, 8 + l * 18, 161 + k)); + } ++ + } + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(player); + } + + @Override + public ItemStack quickMoveStack(Player player, int index) { +- ItemStack itemStack = ItemStack.EMPTY; +- Slot slot = this.slots.get(index); ++ ItemStack itemstack = ItemStack.EMPTY; ++ Slot slot = (Slot) this.slots.get(index); ++ + if (slot != null && slot.hasItem()) { +- ItemStack item = slot.getItem(); +- itemStack = item.copy(); ++ ItemStack itemstack1 = slot.getItem(); ++ ++ itemstack = itemstack1.copy(); + if (index < this.containerRows * 9) { +- if (!this.moveItemStackTo(item, this.containerRows * 9, this.slots.size(), true)) { ++ if (!this.moveItemStackTo(itemstack1, this.containerRows * 9, this.slots.size(), true)) { + return ItemStack.EMPTY; + } +- } else if (!this.moveItemStackTo(item, 0, this.containerRows * 9, false)) { ++ } else if (!this.moveItemStackTo(itemstack1, 0, this.containerRows * 9, false)) { + return ItemStack.EMPTY; + } + +- if (item.isEmpty()) { ++ if (itemstack1.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + } + +- return itemStack; ++ return itemstack; + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/ContainerLevelAccess.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/ContainerLevelAccess.java.patch new file mode 100644 index 0000000000..231e885087 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/ContainerLevelAccess.java.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/inventory/ContainerLevelAccess.java ++++ b/net/minecraft/world/inventory/ContainerLevelAccess.java +@@ -7,6 +7,21 @@ + import net.minecraft.world.level.Level; + + public interface ContainerLevelAccess { ++ ++ // CraftBukkit start ++ default Level getWorld() { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ ++ default BlockPos getPosition() { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ ++ default org.bukkit.Location getLocation() { ++ return new org.bukkit.Location(getWorld().getWorld(), getPosition().getX(), getPosition().getY(), getPosition().getZ()); ++ } ++ // CraftBukkit end ++ + ContainerLevelAccess NULL = new ContainerLevelAccess() { + @Override + public Optional evaluate(BiFunction levelPosConsumer) { +@@ -16,7 +31,19 @@ + + static ContainerLevelAccess create(final Level level, final BlockPos pos) { + return new ContainerLevelAccess() { ++ // CraftBukkit start + @Override ++ public Level getWorld() { ++ return level; ++ } ++ ++ @Override ++ public BlockPos getPosition() { ++ return pos; ++ } ++ // CraftBukkit end ++ ++ @Override + public Optional evaluate(BiFunction levelPosConsumer) { + return Optional.of(levelPosConsumer.apply(level, pos)); + } +@@ -30,8 +57,8 @@ + } + + default void execute(BiConsumer levelPosConsumer) { +- this.evaluate((level, pos) -> { +- levelPosConsumer.accept(level, pos); ++ this.evaluate((world, blockposition) -> { ++ levelPosConsumer.accept(world, blockposition); + return Optional.empty(); + }); + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/CrafterMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/CrafterMenu.java.patch new file mode 100644 index 0000000000..db784515c3 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/CrafterMenu.java.patch @@ -0,0 +1,204 @@ +--- a/net/minecraft/world/inventory/CrafterMenu.java ++++ b/net/minecraft/world/inventory/CrafterMenu.java +@@ -5,11 +5,30 @@ + import net.minecraft.world.entity.player.Inventory; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; +-import net.minecraft.world.item.crafting.CraftingRecipe; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.CrafterBlock; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryCrafter; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class CrafterMenu extends AbstractContainerMenu implements ContainerListener { ++ ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryCrafter inventory = new CraftInventoryCrafter(this.container, this.resultContainer); ++ bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + protected static final int SLOT_COUNT = 9; + private static final int INV_SLOT_START = 9; + private static final int INV_SLOT_END = 36; +@@ -18,43 +37,47 @@ + private final ResultContainer resultContainer = new ResultContainer(); + private final ContainerData containerData; + private final Player player; +- private final CraftingContainer container; ++ private final InventoryCrafting container; + +- public CrafterMenu(int containerId, Inventory inventory) { +- super(MenuType.CRAFTER_3x3, containerId); +- this.player = inventory.player; ++ public CrafterMenu(int i, Inventory playerinventory) { ++ super(MenuType.CRAFTER_3x3, i); ++ this.player = playerinventory.player; + this.containerData = new SimpleContainerData(10); + this.container = new TransientCraftingContainer(this, 3, 3); +- this.addSlots(inventory); ++ this.addSlots(playerinventory); + } + +- public CrafterMenu(int containerId, Inventory inventory, CraftingContainer craftingContainer, ContainerData containerData) { +- super(MenuType.CRAFTER_3x3, containerId); +- this.player = inventory.player; +- this.containerData = containerData; +- this.container = craftingContainer; +- checkContainerSize(craftingContainer, 9); +- craftingContainer.startOpen(inventory.player); +- this.addSlots(inventory); ++ public CrafterMenu(int i, Inventory playerinventory, InventoryCrafting inventorycrafting, ContainerData icontainerproperties) { ++ super(MenuType.CRAFTER_3x3, i); ++ this.player = playerinventory.player; ++ this.containerData = icontainerproperties; ++ this.container = inventorycrafting; ++ checkContainerSize(inventorycrafting, 9); ++ inventorycrafting.startOpen(playerinventory.player); ++ this.addSlots(playerinventory); + this.addSlotListener(this); + } + +- private void addSlots(Inventory inventory) { +- for (int i = 0; i < 3; i++) { +- for (int i1 = 0; i1 < 3; i1++) { +- int i2 = i1 + i * 3; +- this.addSlot(new CrafterSlot(this.container, i2, 26 + i1 * 18, 17 + i * 18, this)); ++ private void addSlots(Inventory playerinventory) { ++ int i; ++ int j; ++ ++ for (j = 0; j < 3; ++j) { ++ for (i = 0; i < 3; ++i) { ++ int k = i + j * 3; ++ ++ this.addSlot(new CrafterSlot(this.container, k, 26 + i * 18, 17 + j * 18, this)); + } + } + +- for (int i = 0; i < 3; i++) { +- for (int i1 = 0; i1 < 9; i1++) { +- this.addSlot(new Slot(inventory, i1 + i * 9 + 9, 8 + i1 * 18, 84 + i * 18)); ++ for (j = 0; j < 3; ++j) { ++ for (i = 0; i < 9; ++i) { ++ this.addSlot(new Slot(playerinventory, i + j * 9 + 9, 8 + i * 18, 84 + j * 18)); + } + } + +- for (int i = 0; i < 9; i++) { +- this.addSlot(new Slot(inventory, i, 8 + i * 18, 142)); ++ for (j = 0; j < 9; ++j) { ++ this.addSlot(new Slot(playerinventory, j, 8 + j * 18, 142)); + } + + this.addSlot(new NonInteractiveResultSlot(this.resultContainer, 0, 134, 35)); +@@ -63,13 +86,14 @@ + } + + public void setSlotState(int i, boolean flag) { +- CrafterSlot crafterSlot = (CrafterSlot)this.getSlot(i); +- this.containerData.set(crafterSlot.index, flag ? 0 : 1); ++ CrafterSlot crafterslot = (CrafterSlot) this.getSlot(i); ++ ++ this.containerData.set(crafterslot.index, flag ? 0 : 1); + this.broadcastChanges(); + } + + public boolean isSlotDisabled(int i) { +- return i > -1 && i < 9 && this.containerData.get(i) == 1; ++ return i > -1 && i < 9 ? this.containerData.get(i) == 1 : false; + } + + public boolean isPowered() { +@@ -78,48 +102,56 @@ + + @Override + public ItemStack quickMoveStack(Player player, int index) { +- ItemStack itemStack = ItemStack.EMPTY; +- Slot slot = this.slots.get(index); ++ ItemStack itemstack = ItemStack.EMPTY; ++ Slot slot = (Slot) this.slots.get(index); ++ + if (slot != null && slot.hasItem()) { +- ItemStack item = slot.getItem(); +- itemStack = item.copy(); ++ ItemStack itemstack1 = slot.getItem(); ++ ++ itemstack = itemstack1.copy(); + if (index < 9) { +- if (!this.moveItemStackTo(item, 9, 45, true)) { ++ if (!this.moveItemStackTo(itemstack1, 9, 45, true)) { + return ItemStack.EMPTY; + } +- } else if (!this.moveItemStackTo(item, 0, 9, false)) { ++ } else if (!this.moveItemStackTo(itemstack1, 0, 9, false)) { + return ItemStack.EMPTY; + } + +- if (item.isEmpty()) { ++ if (itemstack1.isEmpty()) { + slot.set(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + +- if (item.getCount() == itemStack.getCount()) { ++ if (itemstack1.getCount() == itemstack.getCount()) { + return ItemStack.EMPTY; + } + +- slot.onTake(player, item); ++ slot.onTake(player, itemstack1); + } + +- return itemStack; ++ return itemstack; + } + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(player); + } + + private void refreshRecipeResult() { +- if (this.player instanceof ServerPlayer serverPlayer) { +- Level level = serverPlayer.level(); +- ItemStack itemStack = CrafterBlock.getPotentialResults(level, this.container) +- .map(craftingRecipe -> craftingRecipe.assemble(this.container, level.registryAccess())) +- .orElse(ItemStack.EMPTY); +- this.resultContainer.setItem(0, itemStack); ++ Player entityhuman = this.player; ++ ++ if (entityhuman instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entityhuman; ++ Level world = entityplayer.level(); ++ ItemStack itemstack = (ItemStack) CrafterBlock.getPotentialResults(world, this.container).map((recipecrafting) -> { ++ return recipecrafting.assemble(this.container, world.registryAccess()); ++ }).orElse(ItemStack.EMPTY); ++ ++ this.resultContainer.setItem(0, itemstack); + } ++ + } + + public Container getContainer() { +@@ -132,6 +164,5 @@ + } + + @Override +- public void dataChanged(AbstractContainerMenu containerMenu, int dataSlotIndex, int value) { +- } ++ public void dataChanged(AbstractContainerMenu containerMenu, int dataSlotIndex, int value) {} + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/CraftingMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/CraftingMenu.java.patch new file mode 100644 index 0000000000..c6d4c94f1e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/CraftingMenu.java.patch @@ -0,0 +1,251 @@ +--- a/net/minecraft/world/inventory/CraftingMenu.java ++++ b/net/minecraft/world/inventory/CraftingMenu.java +@@ -1,7 +1,6 @@ + package net.minecraft.world.inventory; + + import java.util.Optional; +-import net.minecraft.core.BlockPos; + import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.Container; +@@ -9,14 +8,19 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.player.StackedContents; + import net.minecraft.world.item.ItemStack; +-import net.minecraft.world.item.crafting.CraftingRecipe; + import net.minecraft.world.item.crafting.Recipe; ++import net.minecraft.world.item.crafting.RecipeCrafting; + import net.minecraft.world.item.crafting.RecipeHolder; + import net.minecraft.world.item.crafting.RecipeType; ++import net.minecraft.world.item.crafting.RepairItemRecipe; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; ++import org.bukkit.craftbukkit.inventory.CraftInventoryCrafting; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + +-public class CraftingMenu extends RecipeBookMenu { ++public class CraftingMenu extends RecipeBookMenu { ++ + public static final int RESULT_SLOT = 0; + private static final int CRAFT_SLOT_START = 1; + private static final int CRAFT_SLOT_END = 10; +@@ -24,10 +28,13 @@ + private static final int INV_SLOT_END = 37; + private static final int USE_ROW_SLOT_START = 37; + private static final int USE_ROW_SLOT_END = 46; +- private final CraftingContainer craftSlots = new TransientCraftingContainer(this, 3, 3); +- private final ResultContainer resultSlots = new ResultContainer(); +- private final ContainerLevelAccess access; ++ public final TransientCraftingContainer craftSlots; // CraftBukkit ++ public final ResultContainer resultSlots; ++ public final ContainerLevelAccess access; + private final Player player; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ // CraftBukkit end + + public CraftingMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, ContainerLevelAccess.NULL); +@@ -35,52 +42,67 @@ + + public CraftingMenu(int containerId, Inventory playerInventory, ContainerLevelAccess access) { + super(MenuType.CRAFTING, containerId); ++ // CraftBukkit start - Switched order of IInventory construction and stored player ++ this.resultSlots = new ResultContainer(); ++ this.craftSlots = new TransientCraftingContainer(this, 3, 3, playerInventory.player); // CraftBukkit - pass player ++ this.craftSlots.resultInventory = this.resultSlots; ++ // CraftBukkit end + this.access = access; + this.player = playerInventory.player; + this.addSlot(new ResultSlot(playerInventory.player, this.craftSlots, this.resultSlots, 0, 124, 35)); + +- for (int i = 0; i < 3; i++) { +- for (int i1 = 0; i1 < 3; i1++) { +- this.addSlot(new Slot(this.craftSlots, i1 + i * 3, 30 + i1 * 18, 17 + i * 18)); ++ int j; ++ int k; ++ ++ for (j = 0; j < 3; ++j) { ++ for (k = 0; k < 3; ++k) { ++ this.addSlot(new Slot(this.craftSlots, k + j * 3, 30 + k * 18, 17 + j * 18)); + } + } + +- for (int i = 0; i < 3; i++) { +- for (int i1 = 0; i1 < 9; i1++) { +- this.addSlot(new Slot(playerInventory, i1 + i * 9 + 9, 8 + i1 * 18, 84 + i * 18)); ++ for (j = 0; j < 3; ++j) { ++ for (k = 0; k < 9; ++k) { ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); + } + } + +- for (int i = 0; i < 9; i++) { +- this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142)); ++ for (j = 0; j < 9; ++j) { ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } ++ + } + +- protected static void slotChangedCraftingGrid(AbstractContainerMenu menu, Level level, Player player, CraftingContainer container, ResultContainer result) { ++ protected static void slotChangedCraftingGrid(AbstractContainerMenu menu, Level level, Player player, InventoryCrafting container, ResultContainer result) { + if (!level.isClientSide) { +- ServerPlayer serverPlayer = (ServerPlayer)player; +- ItemStack itemStack = ItemStack.EMPTY; +- Optional> recipeFor = level.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, container, level); +- if (recipeFor.isPresent()) { +- RecipeHolder recipeHolder = recipeFor.get(); +- CraftingRecipe craftingRecipe = recipeHolder.value(); +- if (result.setRecipeUsed(level, serverPlayer, recipeHolder)) { +- ItemStack itemStack1 = craftingRecipe.assemble(container, level.registryAccess()); +- if (itemStack1.isItemEnabled(level.enabledFeatures())) { +- itemStack = itemStack1; ++ ServerPlayer entityplayer = (ServerPlayer) player; ++ ItemStack itemstack = ItemStack.EMPTY; ++ Optional> optional = level.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, container, level); ++ ++ if (optional.isPresent()) { ++ RecipeHolder recipeholder = (RecipeHolder) optional.get(); ++ RecipeCrafting recipecrafting = (RecipeCrafting) recipeholder.value(); ++ ++ if (result.setRecipeUsed(level, entityplayer, recipeholder)) { ++ ItemStack itemstack1 = recipecrafting.assemble(container, level.registryAccess()); ++ ++ if (itemstack1.isItemEnabled(level.enabledFeatures())) { ++ itemstack = itemstack1; + } + } + } ++ itemstack = org.bukkit.craftbukkit.event.CraftEventFactory.callPreCraftEvent(container, result, itemstack, menu.getBukkitView(), optional.map(RecipeHolder::toBukkitRecipe).orElse(null) instanceof RepairItemRecipe); // CraftBukkit + +- result.setItem(0, itemStack); +- menu.setRemoteSlot(0, itemStack); +- serverPlayer.connection.send(new ClientboundContainerSetSlotPacket(menu.containerId, menu.incrementStateId(), 0, itemStack)); ++ result.setItem(0, itemstack); ++ menu.setRemoteSlot(0, itemstack); ++ entityplayer.connection.send(new ClientboundContainerSetSlotPacket(menu.containerId, menu.incrementStateId(), 0, itemstack)); + } + } + + @Override + public void slotsChanged(Container inventory) { +- this.access.execute((level, blockPos) -> slotChangedCraftingGrid(this, level, this.player, this.craftSlots, this.resultSlots)); ++ this.access.execute((world, blockposition) -> { ++ slotChangedCraftingGrid(this, world, this.player, this.craftSlots, this.resultSlots); ++ }); + } + + @Override +@@ -95,66 +117,73 @@ + } + + @Override +- public boolean recipeMatches(RecipeHolder> recipeHolder) { +- return recipeHolder.value().matches(this.craftSlots, this.player.level()); ++ public boolean recipeMatches(RecipeHolder> recipeholder) { ++ return recipeholder.value().matches(this.craftSlots, this.player.level()); + } + + @Override + public void removed(Player player) { + super.removed(player); +- this.access.execute((level, blockPos) -> this.clearContainer(player, this.craftSlots)); ++ this.access.execute((world, blockposition) -> { ++ this.clearContainer(player, this.craftSlots); ++ }); + } + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.CRAFTING_TABLE); + } + + @Override + public ItemStack quickMoveStack(Player player, int index) { +- ItemStack itemStack = ItemStack.EMPTY; +- Slot slot = this.slots.get(index); ++ ItemStack itemstack = ItemStack.EMPTY; ++ Slot slot = (Slot) this.slots.get(index); ++ + if (slot != null && slot.hasItem()) { +- ItemStack item = slot.getItem(); +- itemStack = item.copy(); ++ ItemStack itemstack1 = slot.getItem(); ++ ++ itemstack = itemstack1.copy(); + if (index == 0) { +- this.access.execute((level, blockPos) -> item.getItem().onCraftedBy(item, level, player)); +- if (!this.moveItemStackTo(item, 10, 46, true)) { ++ this.access.execute((world, blockposition) -> { ++ itemstack1.getItem().onCraftedBy(itemstack1, world, player); ++ }); ++ if (!this.moveItemStackTo(itemstack1, 10, 46, true)) { + return ItemStack.EMPTY; + } + +- slot.onQuickCraft(item, itemStack); ++ slot.onQuickCraft(itemstack1, itemstack); + } else if (index >= 10 && index < 46) { +- if (!this.moveItemStackTo(item, 1, 10, false)) { ++ if (!this.moveItemStackTo(itemstack1, 1, 10, false)) { + if (index < 37) { +- if (!this.moveItemStackTo(item, 37, 46, false)) { ++ if (!this.moveItemStackTo(itemstack1, 37, 46, false)) { + return ItemStack.EMPTY; + } +- } else if (!this.moveItemStackTo(item, 10, 37, false)) { ++ } else if (!this.moveItemStackTo(itemstack1, 10, 37, false)) { + return ItemStack.EMPTY; + } + } +- } else if (!this.moveItemStackTo(item, 10, 46, false)) { ++ } else if (!this.moveItemStackTo(itemstack1, 10, 46, false)) { + return ItemStack.EMPTY; + } + +- if (item.isEmpty()) { ++ if (itemstack1.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + +- if (item.getCount() == itemStack.getCount()) { ++ if (itemstack1.getCount() == itemstack.getCount()) { + return ItemStack.EMPTY; + } + +- slot.onTake(player, item); ++ slot.onTake(player, itemstack1); + if (index == 0) { +- player.drop(item, false); ++ player.drop(itemstack1, false); + } + } + +- return itemStack; ++ return itemstack; + } + + @Override +@@ -191,4 +220,17 @@ + public boolean shouldMoveToInventory(int slotIndex) { + return slotIndex != this.getResultSlotIndex(); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryCrafting inventory = new CraftInventoryCrafting(this.craftSlots, this.resultSlots); ++ bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/DispenserMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/DispenserMenu.java.patch new file mode 100644 index 0000000000..205c988be3 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/DispenserMenu.java.patch @@ -0,0 +1,136 @@ +--- a/net/minecraft/world/inventory/DispenserMenu.java ++++ b/net/minecraft/world/inventory/DispenserMenu.java +@@ -6,13 +6,23 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class DispenserMenu extends AbstractContainerMenu { ++ + private static final int SLOT_COUNT = 9; + private static final int INV_SLOT_START = 9; + private static final int INV_SLOT_END = 36; + private static final int USE_ROW_SLOT_START = 36; + private static final int USE_ROW_SLOT_END = 45; +- private final Container dispenser; ++ public final Container dispenser; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ // CraftBukkit end + + public DispenserMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, new SimpleContainer(9)); +@@ -20,61 +30,72 @@ + + public DispenserMenu(int containerId, Inventory playerInventory, Container container) { + super(MenuType.GENERIC_3x3, containerId); ++ // CraftBukkit start - Save player ++ this.player = playerInventory; ++ // CraftBukkit end ++ + checkContainerSize(container, 9); + this.dispenser = container; + container.startOpen(playerInventory.player); + +- for (int i = 0; i < 3; i++) { +- for (int i1 = 0; i1 < 3; i1++) { +- this.addSlot(new Slot(container, i1 + i * 3, 62 + i1 * 18, 17 + i * 18)); ++ int j; ++ int k; ++ ++ for (j = 0; j < 3; ++j) { ++ for (k = 0; k < 3; ++k) { ++ this.addSlot(new Slot(container, k + j * 3, 62 + k * 18, 17 + j * 18)); + } + } + +- for (int i = 0; i < 3; i++) { +- for (int i1 = 0; i1 < 9; i1++) { +- this.addSlot(new Slot(playerInventory, i1 + i * 9 + 9, 8 + i1 * 18, 84 + i * 18)); ++ for (j = 0; j < 3; ++j) { ++ for (k = 0; k < 9; ++k) { ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); + } + } + +- for (int i = 0; i < 9; i++) { +- this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142)); ++ for (j = 0; j < 9; ++j) { ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } ++ + } + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.dispenser.stillValid(player); + } + + @Override + public ItemStack quickMoveStack(Player player, int index) { +- ItemStack itemStack = ItemStack.EMPTY; +- Slot slot = this.slots.get(index); ++ ItemStack itemstack = ItemStack.EMPTY; ++ Slot slot = (Slot) this.slots.get(index); ++ + if (slot != null && slot.hasItem()) { +- ItemStack item = slot.getItem(); +- itemStack = item.copy(); ++ ItemStack itemstack1 = slot.getItem(); ++ ++ itemstack = itemstack1.copy(); + if (index < 9) { +- if (!this.moveItemStackTo(item, 9, 45, true)) { ++ if (!this.moveItemStackTo(itemstack1, 9, 45, true)) { + return ItemStack.EMPTY; + } +- } else if (!this.moveItemStackTo(item, 0, 9, false)) { ++ } else if (!this.moveItemStackTo(itemstack1, 0, 9, false)) { + return ItemStack.EMPTY; + } + +- if (item.isEmpty()) { ++ if (itemstack1.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + +- if (item.getCount() == itemStack.getCount()) { ++ if (itemstack1.getCount() == itemstack.getCount()) { + return ItemStack.EMPTY; + } + +- slot.onTake(player, item); ++ slot.onTake(player, itemstack1); + } + +- return itemStack; ++ return itemstack; + } + + @Override +@@ -82,4 +103,17 @@ + super.removed(player); + this.dispenser.stopOpen(player); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventory inventory = new CraftInventory(this.dispenser); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/EnchantmentMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/EnchantmentMenu.java.patch new file mode 100644 index 0000000000..eec50525af --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/EnchantmentMenu.java.patch @@ -0,0 +1,498 @@ +--- a/net/minecraft/world/inventory/EnchantmentMenu.java ++++ b/net/minecraft/world/inventory/EnchantmentMenu.java +@@ -1,12 +1,14 @@ + package net.minecraft.world.inventory; + + import com.mojang.datafixers.util.Pair; ++import java.util.Iterator; + import java.util.List; + import net.minecraft.Util; + import net.minecraft.advancements.CriteriaTriggers; + import net.minecraft.core.BlockPos; + import net.minecraft.core.registries.BuiltInRegistries; + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.network.chat.Component; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvents; +@@ -16,31 +18,42 @@ + import net.minecraft.world.Container; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.entity.player.Inventory; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.EnchantedBookItem; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +-import net.minecraft.world.item.enchantment.EnchantmentHelper; +-import net.minecraft.world.item.enchantment.EnchantmentInstance; +-import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.EnchantmentTableBlock; ++// CraftBukkit start ++import java.util.Map; ++import net.minecraft.world.item.enchantment.Enchantment; ++import net.minecraft.world.item.enchantment.EnchantmentHelper; ++import net.minecraft.world.item.enchantment.EnchantmentInstance; ++import org.bukkit.Location; ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftInventoryEnchanting; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.enchantments.EnchantmentOffer; ++import org.bukkit.event.enchantment.EnchantItemEvent; ++import org.bukkit.event.enchantment.PrepareItemEnchantEvent; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class EnchantmentMenu extends AbstractContainerMenu { ++ + static final ResourceLocation EMPTY_SLOT_LAPIS_LAZULI = new ResourceLocation("item/empty_slot_lapis_lazuli"); +- private final Container enchantSlots = new SimpleContainer(2) { +- @Override +- public void setChanged() { +- super.setChanged(); +- EnchantmentMenu.this.slotsChanged(this); +- } +- }; ++ private final Container enchantSlots; + private final ContainerLevelAccess access; +- private final RandomSource random = RandomSource.create(); +- private final DataSlot enchantmentSeed = DataSlot.standalone(); +- public final int[] costs = new int[3]; +- public final int[] enchantClue = new int[]{-1, -1, -1}; +- public final int[] levelClue = new int[]{-1, -1, -1}; ++ private final RandomSource random; ++ private final DataSlot enchantmentSeed; ++ public final int[] costs; ++ public final int[] enchantClue; ++ public final int[] levelClue; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ // CraftBukkit end + + public EnchantmentMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, ContainerLevelAccess.NULL); +@@ -48,6 +61,25 @@ + + public EnchantmentMenu(int containerId, Inventory playerInventory, ContainerLevelAccess access) { + super(MenuType.ENCHANTMENT, containerId); ++ this.enchantSlots = new SimpleContainer(2) { ++ @Override ++ public void setChanged() { ++ super.setChanged(); ++ EnchantmentMenu.this.slotsChanged(this); ++ } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end ++ }; ++ this.random = RandomSource.create(); ++ this.enchantmentSeed = DataSlot.standalone(); ++ this.costs = new int[3]; ++ this.enchantClue = new int[]{-1, -1, -1}; ++ this.levelClue = new int[]{-1, -1, -1}; + this.access = access; + this.addSlot(new Slot(this.enchantSlots, 0, 15, 47) { + @Override +@@ -67,14 +99,16 @@ + } + }); + +- for (int i = 0; i < 3; i++) { +- for (int i1 = 0; i1 < 9; i1++) { +- this.addSlot(new Slot(playerInventory, i1 + i * 9 + 9, 8 + i1 * 18, 84 + i * 18)); ++ int j; ++ ++ for (j = 0; j < 3; ++j) { ++ for (int k = 0; k < 9; ++k) { ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); + } + } + +- for (int i = 0; i < 9; i++) { +- this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142)); ++ for (j = 0; j < 9; ++j) { ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } + + this.addDataSlot(DataSlot.shared(this.costs, 0)); +@@ -87,122 +121,208 @@ + this.addDataSlot(DataSlot.shared(this.levelClue, 0)); + this.addDataSlot(DataSlot.shared(this.levelClue, 1)); + this.addDataSlot(DataSlot.shared(this.levelClue, 2)); ++ // CraftBukkit start ++ player = (Player) playerInventory.player.getBukkitEntity(); ++ // CraftBukkit end + } + + @Override + public void slotsChanged(Container inventory) { + if (inventory == this.enchantSlots) { +- ItemStack item = inventory.getItem(0); +- if (!item.isEmpty() && item.isEnchantable()) { +- this.access.execute((level, blockPos) -> { +- int i1 = 0; ++ ItemStack itemstack = inventory.getItem(0); + +- for (BlockPos blockPos1 : EnchantmentTableBlock.BOOKSHELF_OFFSETS) { +- if (EnchantmentTableBlock.isValidBookShelf(level, blockPos, blockPos1)) { +- i1++; ++ if (!itemstack.isEmpty()) { // CraftBukkit - relax condition ++ this.access.execute((world, blockposition) -> { ++ int i = 0; ++ Iterator iterator = EnchantmentTableBlock.BOOKSHELF_OFFSETS.iterator(); ++ ++ while (iterator.hasNext()) { ++ BlockPos blockposition1 = (BlockPos) iterator.next(); ++ ++ if (EnchantmentTableBlock.isValidBookShelf(world, blockposition, blockposition1)) { ++ ++i; + } + } + +- this.random.setSeed((long)this.enchantmentSeed.get()); ++ this.random.setSeed((long) this.enchantmentSeed.get()); + +- for (int i2 = 0; i2 < 3; i2++) { +- this.costs[i2] = EnchantmentHelper.getEnchantmentCost(this.random, i2, i1, item); +- this.enchantClue[i2] = -1; +- this.levelClue[i2] = -1; +- if (this.costs[i2] < i2 + 1) { +- this.costs[i2] = 0; ++ int j; ++ ++ for (j = 0; j < 3; ++j) { ++ this.costs[j] = EnchantmentHelper.getEnchantmentCost(this.random, j, i, itemstack); ++ this.enchantClue[j] = -1; ++ this.levelClue[j] = -1; ++ if (this.costs[j] < j + 1) { ++ this.costs[j] = 0; + } + } + +- for (int i2x = 0; i2x < 3; i2x++) { +- if (this.costs[i2x] > 0) { +- List enchantmentList = this.getEnchantmentList(item, i2x, this.costs[i2x]); +- if (enchantmentList != null && !enchantmentList.isEmpty()) { +- EnchantmentInstance enchantmentInstance = enchantmentList.get(this.random.nextInt(enchantmentList.size())); +- this.enchantClue[i2x] = BuiltInRegistries.ENCHANTMENT.getId(enchantmentInstance.enchantment); +- this.levelClue[i2x] = enchantmentInstance.level; ++ for (j = 0; j < 3; ++j) { ++ if (this.costs[j] > 0) { ++ List list = this.getEnchantmentList(itemstack, j, this.costs[j]); ++ ++ if (list != null && !list.isEmpty()) { ++ EnchantmentInstance weightedrandomenchant = (EnchantmentInstance) list.get(this.random.nextInt(list.size())); ++ ++ this.enchantClue[j] = BuiltInRegistries.ENCHANTMENT.getId(weightedrandomenchant.enchantment); ++ this.levelClue[j] = weightedrandomenchant.level; + } + } + } + ++ // CraftBukkit start ++ CraftItemStack item = CraftItemStack.asCraftMirror(itemstack); ++ org.bukkit.enchantments.EnchantmentOffer[] offers = new EnchantmentOffer[3]; ++ for (j = 0; j < 3; ++j) { ++ org.bukkit.enchantments.Enchantment enchantment = (this.enchantClue[j] >= 0) ? org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(BuiltInRegistries.ENCHANTMENT.byId(this.enchantClue[j])))) : null; ++ offers[j] = (enchantment != null) ? new EnchantmentOffer(enchantment, this.levelClue[j], this.costs[j]) : null; ++ } ++ ++ PrepareItemEnchantEvent event = new PrepareItemEnchantEvent(player, this.getBukkitView(), access.getLocation().getBlock(), item, offers, i); ++ event.setCancelled(!itemstack.isEnchantable()); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ for (j = 0; j < 3; ++j) { ++ this.costs[j] = 0; ++ this.enchantClue[j] = -1; ++ this.levelClue[j] = -1; ++ } ++ return; ++ } ++ ++ for (j = 0; j < 3; j++) { ++ EnchantmentOffer offer = event.getOffers()[j]; ++ if (offer != null) { ++ this.costs[j] = offer.getCost(); ++ this.enchantClue[j] = BuiltInRegistries.ENCHANTMENT.getId(BuiltInRegistries.ENCHANTMENT.get(CraftNamespacedKey.toMinecraft(offer.getEnchantment().getKey()))); ++ this.levelClue[j] = offer.getEnchantmentLevel(); ++ } else { ++ this.costs[j] = 0; ++ this.enchantClue[j] = -1; ++ this.levelClue[j] = -1; ++ } ++ } ++ // CraftBukkit end ++ + this.broadcastChanges(); + }); + } else { +- for (int i = 0; i < 3; i++) { ++ for (int i = 0; i < 3; ++i) { + this.costs[i] = 0; + this.enchantClue[i] = -1; + this.levelClue[i] = -1; + } + } + } ++ + } + + @Override +- public boolean clickMenuButton(Player player, int id) { ++ public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { + if (id >= 0 && id < this.costs.length) { +- ItemStack item = this.enchantSlots.getItem(0); +- ItemStack item1 = this.enchantSlots.getItem(1); +- int i = id + 1; +- if ((item1.isEmpty() || item1.getCount() < i) && !player.getAbilities().instabuild) { ++ ItemStack itemstack = this.enchantSlots.getItem(0); ++ ItemStack itemstack1 = this.enchantSlots.getItem(1); ++ int j = id + 1; ++ ++ if ((itemstack1.isEmpty() || itemstack1.getCount() < j) && !player.getAbilities().instabuild) { + return false; +- } else if (this.costs[id] <= 0 +- || item.isEmpty() +- || (player.experienceLevel < i || player.experienceLevel < this.costs[id]) && !player.getAbilities().instabuild) { +- return false; +- } else { +- this.access.execute((level, blockPos) -> { +- ItemStack itemStack = item; +- List enchantmentList = this.getEnchantmentList(item, id, this.costs[id]); +- if (!enchantmentList.isEmpty()) { +- player.onEnchantmentPerformed(item, i); +- boolean isBook = item.is(Items.BOOK); +- if (isBook) { +- itemStack = new ItemStack(Items.ENCHANTED_BOOK); +- CompoundTag tag = item.getTag(); +- if (tag != null) { +- itemStack.setTag(tag.copy()); ++ } else if (this.costs[id] > 0 && !itemstack.isEmpty() && (player.experienceLevel >= j && player.experienceLevel >= this.costs[id] || player.getAbilities().instabuild)) { ++ this.access.execute((world, blockposition) -> { ++ ItemStack itemstack2 = itemstack; ++ List list = this.getEnchantmentList(itemstack, id, this.costs[id]); ++ ++ // CraftBukkit start ++ if (true || !list.isEmpty()) { ++ // entityhuman.onEnchantmentPerformed(itemstack, j); // Moved down ++ Map enchants = new java.util.HashMap(); ++ for (EnchantmentInstance instance : list) { ++ enchants.put(org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(instance.enchantment))), instance.level); ++ } ++ CraftItemStack item = CraftItemStack.asCraftMirror(itemstack2); ++ ++ org.bukkit.enchantments.Enchantment hintedEnchantment = org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(Enchantment.byId(enchantClue[id])))); ++ int hintedEnchantmentLevel = levelClue[id]; ++ EnchantItemEvent event = new EnchantItemEvent((Player) player.getBukkitEntity(), this.getBukkitView(), access.getLocation().getBlock(), item, this.costs[id], enchants, hintedEnchantment, hintedEnchantmentLevel, id); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ int level = event.getExpLevelCost(); ++ if (event.isCancelled() || (level > player.experienceLevel && !player.getAbilities().instabuild) || event.getEnchantsToAdd().isEmpty()) { ++ return; ++ } ++ // CraftBukkit end ++ boolean flag = itemstack.is(Items.BOOK); ++ ++ if (flag) { ++ itemstack2 = new ItemStack(Items.ENCHANTED_BOOK); ++ CompoundTag nbttagcompound = itemstack.getTag(); ++ ++ if (nbttagcompound != null) { ++ itemstack2.setTag(nbttagcompound.copy()); + } + +- this.enchantSlots.setItem(0, itemStack); ++ this.enchantSlots.setItem(0, itemstack2); + } + +- for (EnchantmentInstance enchantmentInstance : enchantmentList) { +- if (isBook) { +- EnchantedBookItem.addEnchantment(itemStack, enchantmentInstance); +- } else { +- itemStack.enchant(enchantmentInstance.enchantment, enchantmentInstance.level); ++ // CraftBukkit start ++ for (Map.Entry entry : event.getEnchantsToAdd().entrySet()) { ++ try { ++ if (flag) { ++ NamespacedKey enchantId = entry.getKey().getKey(); ++ Enchantment nms = BuiltInRegistries.ENCHANTMENT.get(CraftNamespacedKey.toMinecraft(enchantId)); ++ if (nms == null) { ++ continue; ++ } ++ ++ EnchantmentInstance weightedrandomenchant = new EnchantmentInstance(nms, entry.getValue()); ++ EnchantedBookItem.addEnchantment(itemstack2, weightedrandomenchant); ++ } else { ++ item.addUnsafeEnchantment(entry.getKey(), entry.getValue()); ++ } ++ } catch (IllegalArgumentException e) { ++ /* Just swallow invalid enchantments */ + } + } + ++ player.onEnchantmentPerformed(itemstack, j); ++ // CraftBukkit end ++ ++ // CraftBukkit - TODO: let plugins change this + if (!player.getAbilities().instabuild) { +- item1.shrink(i); +- if (item1.isEmpty()) { ++ itemstack1.shrink(j); ++ if (itemstack1.isEmpty()) { + this.enchantSlots.setItem(1, ItemStack.EMPTY); + } + } + + player.awardStat(Stats.ENCHANT_ITEM); + if (player instanceof ServerPlayer) { +- CriteriaTriggers.ENCHANTED_ITEM.trigger((ServerPlayer)player, itemStack, i); ++ CriteriaTriggers.ENCHANTED_ITEM.trigger((ServerPlayer) player, itemstack2, j); + } + + this.enchantSlots.setChanged(); + this.enchantmentSeed.set(player.getEnchantmentSeed()); + this.slotsChanged(this.enchantSlots); +- level.playSound(null, blockPos, SoundEvents.ENCHANTMENT_TABLE_USE, SoundSource.BLOCKS, 1.0F, level.random.nextFloat() * 0.1F + 0.9F); ++ world.playSound((net.minecraft.world.entity.player.Player) null, blockposition, SoundEvents.ENCHANTMENT_TABLE_USE, SoundSource.BLOCKS, 1.0F, world.random.nextFloat() * 0.1F + 0.9F); + } ++ + }); + return true; ++ } else { ++ return false; + } + } else { +- Util.logAndPauseIfInIde(player.getName() + " pressed invalid button id: " + id); ++ Component ichatbasecomponent = player.getName(); ++ ++ Util.logAndPauseIfInIde(ichatbasecomponent + " pressed invalid button id: " + id); + return false; + } + } + + private List getEnchantmentList(ItemStack stack, int enchantSlot, int level) { +- this.random.setSeed((long)(this.enchantmentSeed.get() + enchantSlot)); ++ this.random.setSeed((long) (this.enchantmentSeed.get() + enchantSlot)); + List list = EnchantmentHelper.selectEnchantment(this.random, stack, level, false); ++ + if (stack.is(Items.BOOK) && list.size() > 1) { + list.remove(this.random.nextInt(list.size())); + } +@@ -211,8 +331,9 @@ + } + + public int getGoldCount() { +- ItemStack item = this.enchantSlots.getItem(1); +- return item.isEmpty() ? 0 : item.getCount(); ++ ItemStack itemstack = this.enchantSlots.getItem(1); ++ ++ return itemstack.isEmpty() ? 0 : itemstack.getCount(); + } + + public int getEnchantmentSeed() { +@@ -220,58 +341,77 @@ + } + + @Override +- public void removed(Player player) { ++ public void removed(net.minecraft.world.entity.player.Player player) { + super.removed(player); +- this.access.execute((level, blockPos) -> this.clearContainer(player, this.enchantSlots)); ++ this.access.execute((world, blockposition) -> { ++ this.clearContainer(player, this.enchantSlots); ++ }); + } + + @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.ENCHANTING_TABLE); + } + + @Override +- public ItemStack quickMoveStack(Player player, int index) { +- ItemStack itemStack = ItemStack.EMPTY; +- Slot slot = this.slots.get(index); ++ public ItemStack quickMoveStack(net.minecraft.world.entity.player.Player player, int index) { ++ ItemStack itemstack = ItemStack.EMPTY; ++ Slot slot = (Slot) this.slots.get(index); ++ + if (slot != null && slot.hasItem()) { +- ItemStack item = slot.getItem(); +- itemStack = item.copy(); ++ ItemStack itemstack1 = slot.getItem(); ++ ++ itemstack = itemstack1.copy(); + if (index == 0) { +- if (!this.moveItemStackTo(item, 2, 38, true)) { ++ if (!this.moveItemStackTo(itemstack1, 2, 38, true)) { + return ItemStack.EMPTY; + } + } else if (index == 1) { +- if (!this.moveItemStackTo(item, 2, 38, true)) { ++ if (!this.moveItemStackTo(itemstack1, 2, 38, true)) { + return ItemStack.EMPTY; + } +- } else if (item.is(Items.LAPIS_LAZULI)) { +- if (!this.moveItemStackTo(item, 1, 2, true)) { ++ } else if (itemstack1.is(Items.LAPIS_LAZULI)) { ++ if (!this.moveItemStackTo(itemstack1, 1, 2, true)) { + return ItemStack.EMPTY; + } + } else { +- if (this.slots.get(0).hasItem() || !this.slots.get(0).mayPlace(item)) { ++ if (((Slot) this.slots.get(0)).hasItem() || !((Slot) this.slots.get(0)).mayPlace(itemstack1)) { + return ItemStack.EMPTY; + } + +- ItemStack itemStack1 = item.copyWithCount(1); +- item.shrink(1); +- this.slots.get(0).setByPlayer(itemStack1); ++ ItemStack itemstack2 = itemstack1.copyWithCount(1); ++ ++ itemstack1.shrink(1); ++ ((Slot) this.slots.get(0)).setByPlayer(itemstack2); + } + +- if (item.isEmpty()) { ++ if (itemstack1.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + +- if (item.getCount() == itemStack.getCount()) { ++ if (itemstack1.getCount() == itemstack.getCount()) { + return ItemStack.EMPTY; + } + +- slot.onTake(player, item); ++ slot.onTake(player, itemstack1); + } + +- return itemStack; ++ return itemstack; + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryEnchanting inventory = new CraftInventoryEnchanting(this.enchantSlots); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/FurnaceResultSlot.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/FurnaceResultSlot.java.patch new file mode 100644 index 0000000000..4d7f3def30 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/FurnaceResultSlot.java.patch @@ -0,0 +1,39 @@ +--- a/net/minecraft/world/inventory/FurnaceResultSlot.java ++++ b/net/minecraft/world/inventory/FurnaceResultSlot.java +@@ -7,6 +7,7 @@ + import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; + + public class FurnaceResultSlot extends Slot { ++ + private final Player player; + private int removeCount; + +@@ -23,7 +24,7 @@ + @Override + public ItemStack remove(int amount) { + if (this.hasItem()) { +- this.removeCount = this.removeCount + Math.min(amount, this.getItem().getCount()); ++ this.removeCount += Math.min(amount, this.getItem().getCount()); + } + + return super.remove(amount); +@@ -44,8 +45,17 @@ + @Override + protected void checkTakeAchievements(ItemStack stack) { + stack.onCraftedBy(this.player.level(), this.player, this.removeCount); +- if (this.player instanceof ServerPlayer serverPlayer && this.container instanceof AbstractFurnaceBlockEntity abstractFurnaceBlockEntity) { +- abstractFurnaceBlockEntity.awardUsedRecipesAndPopExperience(serverPlayer); ++ Player entityhuman = this.player; ++ ++ if (entityhuman instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entityhuman; ++ Container iinventory = this.container; ++ ++ if (iinventory instanceof AbstractFurnaceBlockEntity) { ++ AbstractFurnaceBlockEntity tileentityfurnace = (AbstractFurnaceBlockEntity) iinventory; ++ ++ tileentityfurnace.awardUsedRecipesAndPopExperience(entityplayer, stack, this.removeCount); // CraftBukkit ++ } + } + + this.removeCount = 0; diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/GrindstoneMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/GrindstoneMenu.java.patch new file mode 100644 index 0000000000..24f305693c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/GrindstoneMenu.java.patch @@ -0,0 +1,430 @@ +--- a/net/minecraft/world/inventory/GrindstoneMenu.java ++++ b/net/minecraft/world/inventory/GrindstoneMenu.java +@@ -1,15 +1,14 @@ + package net.minecraft.world.inventory; + ++import java.util.Iterator; + import java.util.Map; + import java.util.Map.Entry; + import java.util.stream.Collectors; +-import net.minecraft.core.BlockPos; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.Container; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.entity.ExperienceOrb; + import net.minecraft.world.entity.player.Inventory; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +@@ -18,8 +17,30 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.inventory.CraftInventoryGrindstone; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class GrindstoneMenu extends AbstractContainerMenu { ++ ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryGrindstone inventory = new CraftInventoryGrindstone(this.repairSlots, this.resultSlots); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + public static final int MAX_NAME_LENGTH = 35; + public static final int INPUT_SLOT = 0; + public static final int ADDITIONAL_SLOT = 1; +@@ -28,14 +49,8 @@ + private static final int INV_SLOT_END = 30; + private static final int USE_ROW_SLOT_START = 30; + private static final int USE_ROW_SLOT_END = 39; +- private final Container resultSlots = new ResultContainer(); +- final Container repairSlots = new SimpleContainer(2) { +- @Override +- public void setChanged() { +- super.setChanged(); +- GrindstoneMenu.this.slotsChanged(this); +- } +- }; ++ private final Container resultSlots; ++ final Container repairSlots; + private final ContainerLevelAccess access; + + public GrindstoneMenu(int containerId, Inventory playerInventory) { +@@ -44,6 +59,21 @@ + + public GrindstoneMenu(int containerId, Inventory playerInventory, final ContainerLevelAccess access) { + super(MenuType.GRINDSTONE, containerId); ++ this.resultSlots = new ResultContainer(); ++ this.repairSlots = new SimpleContainer(2) { ++ @Override ++ public void setChanged() { ++ super.setChanged(); ++ GrindstoneMenu.this.slotsChanged(this); ++ } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end ++ }; + this.access = access; + this.addSlot(new Slot(this.repairSlots, 0, 49, 19) { + @Override +@@ -64,55 +94,64 @@ + } + + @Override +- public void onTake(Player player, ItemStack stack) { +- access.execute((level, blockPos) -> { +- if (level instanceof ServerLevel) { +- ExperienceOrb.award((ServerLevel)level, Vec3.atCenterOf(blockPos), this.getExperienceAmount(level)); ++ public void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) { ++ access.execute((world, blockposition) -> { ++ if (world instanceof ServerLevel) { ++ ExperienceOrb.award((ServerLevel) world, Vec3.atCenterOf(blockposition), this.getExperienceAmount(world)); + } + +- level.levelEvent(1042, blockPos, 0); ++ world.levelEvent(1042, blockposition, 0); + }); + GrindstoneMenu.this.repairSlots.setItem(0, ItemStack.EMPTY); + GrindstoneMenu.this.repairSlots.setItem(1, ItemStack.EMPTY); + } + + private int getExperienceAmount(Level level) { +- int i2 = 0; +- i2 += this.getExperienceFromItem(GrindstoneMenu.this.repairSlots.getItem(0)); +- int var5 = i2 + this.getExperienceFromItem(GrindstoneMenu.this.repairSlots.getItem(1)); +- if (var5 > 0) { +- int i3 = (int)Math.ceil((double)var5 / 2.0); +- return i3 + level.random.nextInt(i3); ++ byte b0 = 0; ++ int j = b0 + this.getExperienceFromItem(GrindstoneMenu.this.repairSlots.getItem(0)); ++ ++ j += this.getExperienceFromItem(GrindstoneMenu.this.repairSlots.getItem(1)); ++ if (j > 0) { ++ int k = (int) Math.ceil((double) j / 2.0D); ++ ++ return k + level.random.nextInt(k); + } else { + return 0; + } + } + + private int getExperienceFromItem(ItemStack stack) { +- int i2 = 0; +- Map enchantments = EnchantmentHelper.getEnchantments(stack); ++ int j = 0; ++ Map map = EnchantmentHelper.getEnchantments(stack); ++ Iterator iterator = map.entrySet().iterator(); + +- for (Entry entry : enchantments.entrySet()) { +- Enchantment enchantment = entry.getKey(); +- Integer integer = entry.getValue(); ++ while (iterator.hasNext()) { ++ Entry entry = (Entry) iterator.next(); ++ Enchantment enchantment = (Enchantment) entry.getKey(); ++ Integer integer = (Integer) entry.getValue(); ++ + if (!enchantment.isCurse()) { +- i2 += enchantment.getMinCost(integer); ++ j += enchantment.getMinCost(integer); + } + } + +- return i2; ++ return j; + } + }); + +- for (int i = 0; i < 3; i++) { +- for (int i1 = 0; i1 < 9; i1++) { +- this.addSlot(new Slot(playerInventory, i1 + i * 9 + 9, 8 + i1 * 18, 84 + i * 18)); ++ int j; ++ ++ for (j = 0; j < 3; ++j) { ++ for (int k = 0; k < 9; ++k) { ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); + } + } + +- for (int i = 0; i < 9; i++) { +- this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142)); ++ for (j = 0; j < 9; ++j) { ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } ++ ++ player = (Player) playerInventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override +@@ -121,161 +160,175 @@ + if (inventory == this.repairSlots) { + this.createResult(); + } ++ + } + + private void createResult() { +- ItemStack item = this.repairSlots.getItem(0); +- ItemStack item1 = this.repairSlots.getItem(1); +- boolean flag = !item.isEmpty() || !item1.isEmpty(); +- boolean flag1 = !item.isEmpty() && !item1.isEmpty(); +- if (!flag) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- } else { +- boolean flag2 = !item.isEmpty() && !item.is(Items.ENCHANTED_BOOK) && !item.isEnchanted() +- || !item1.isEmpty() && !item1.is(Items.ENCHANTED_BOOK) && !item1.isEnchanted(); +- if (item.getCount() > 1 || item1.getCount() > 1 || !flag1 && flag2) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ ItemStack itemstack = this.repairSlots.getItem(0); ++ ItemStack itemstack1 = this.repairSlots.getItem(1); ++ boolean flag = !itemstack.isEmpty() || !itemstack1.isEmpty(); ++ boolean flag1 = !itemstack.isEmpty() && !itemstack1.isEmpty(); ++ ++ if (flag) { ++ boolean flag2 = !itemstack.isEmpty() && !itemstack.is(Items.ENCHANTED_BOOK) && !itemstack.isEnchanted() || !itemstack1.isEmpty() && !itemstack1.is(Items.ENCHANTED_BOOK) && !itemstack1.isEnchanted(); ++ ++ if (itemstack.getCount() > 1 || itemstack1.getCount() > 1 || !flag1 && flag2) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + this.broadcastChanges(); + return; + } + +- int i = 1; +- int max; +- ItemStack itemStack; ++ byte b0 = 1; ++ int i; ++ ItemStack itemstack2; ++ + if (flag1) { +- if (!item.is(item1.getItem())) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ if (!itemstack.is(itemstack1.getItem())) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + this.broadcastChanges(); + return; + } + +- Item item2 = item.getItem(); +- int i1 = item2.getMaxDamage() - item.getDamageValue(); +- int i2 = item2.getMaxDamage() - item1.getDamageValue(); +- int i3 = i1 + i2 + item2.getMaxDamage() * 5 / 100; +- max = Math.max(item2.getMaxDamage() - i3, 0); +- itemStack = this.mergeEnchants(item, item1); +- if (!itemStack.isDamageableItem()) { +- if (!ItemStack.matches(item, item1)) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ Item item = itemstack.getItem(); ++ int j = item.getMaxDamage() - itemstack.getDamageValue(); ++ int k = item.getMaxDamage() - itemstack1.getDamageValue(); ++ int l = j + k + item.getMaxDamage() * 5 / 100; ++ ++ i = Math.max(item.getMaxDamage() - l, 0); ++ itemstack2 = this.mergeEnchants(itemstack, itemstack1); ++ if (!itemstack2.isDamageableItem()) { ++ if (!ItemStack.matches(itemstack, itemstack1)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + this.broadcastChanges(); + return; + } + +- i = 2; ++ b0 = 2; + } + } else { +- boolean flag3 = !item.isEmpty(); +- max = flag3 ? item.getDamageValue() : item1.getDamageValue(); +- itemStack = flag3 ? item : item1; +- } ++ boolean flag3 = !itemstack.isEmpty(); + +- this.resultSlots.setItem(0, this.removeNonCurses(itemStack, max, i)); ++ i = flag3 ? itemstack.getDamageValue() : itemstack1.getDamageValue(); ++ itemstack2 = flag3 ? itemstack : itemstack1; ++ } ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), this.removeNonCurses(itemstack2, i, b0)); // CraftBukkit ++ } else { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + } + ++ sendAllDataToRemote(); // CraftBukkit - SPIGOT-6686: Always send completed inventory to stay in sync with client + this.broadcastChanges(); + } + + private ItemStack mergeEnchants(ItemStack copyTo, ItemStack copyFrom) { +- ItemStack itemStack = copyTo.copy(); +- Map enchantments = EnchantmentHelper.getEnchantments(copyFrom); ++ ItemStack itemstack2 = copyTo.copy(); ++ Map map = EnchantmentHelper.getEnchantments(copyFrom); ++ Iterator iterator = map.entrySet().iterator(); + +- for (Entry entry : enchantments.entrySet()) { +- Enchantment enchantment = entry.getKey(); +- if (!enchantment.isCurse() || EnchantmentHelper.getItemEnchantmentLevel(enchantment, itemStack) == 0) { +- itemStack.enchant(enchantment, entry.getValue()); ++ while (iterator.hasNext()) { ++ Entry entry = (Entry) iterator.next(); ++ Enchantment enchantment = (Enchantment) entry.getKey(); ++ ++ if (!enchantment.isCurse() || EnchantmentHelper.getItemEnchantmentLevel(enchantment, itemstack2) == 0) { ++ itemstack2.enchant(enchantment, (Integer) entry.getValue()); + } + } + +- return itemStack; ++ return itemstack2; + } + + private ItemStack removeNonCurses(ItemStack stack, int damage, int count) { +- ItemStack itemStack = stack.copyWithCount(count); +- itemStack.removeTagKey("Enchantments"); +- itemStack.removeTagKey("StoredEnchantments"); ++ ItemStack itemstack1 = stack.copyWithCount(count); ++ ++ itemstack1.removeTagKey("Enchantments"); ++ itemstack1.removeTagKey("StoredEnchantments"); + if (damage > 0) { +- itemStack.setDamageValue(damage); ++ itemstack1.setDamageValue(damage); + } else { +- itemStack.removeTagKey("Damage"); ++ itemstack1.removeTagKey("Damage"); + } + +- Map map = EnchantmentHelper.getEnchantments(stack) +- .entrySet() +- .stream() +- .filter(enchantment -> enchantment.getKey().isCurse()) +- .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); +- EnchantmentHelper.setEnchantments(map, itemStack); +- itemStack.setRepairCost(0); +- if (itemStack.is(Items.ENCHANTED_BOOK) && map.size() == 0) { +- itemStack = new ItemStack(Items.BOOK); ++ Map map = (Map) EnchantmentHelper.getEnchantments(stack).entrySet().stream().filter((entry) -> { ++ return ((Enchantment) entry.getKey()).isCurse(); ++ }).collect(Collectors.toMap(Entry::getKey, Entry::getValue)); ++ ++ EnchantmentHelper.setEnchantments(map, itemstack1); ++ itemstack1.setRepairCost(0); ++ if (itemstack1.is(Items.ENCHANTED_BOOK) && map.size() == 0) { ++ itemstack1 = new ItemStack(Items.BOOK); + if (stack.hasCustomHoverName()) { +- itemStack.setHoverName(stack.getHoverName()); ++ itemstack1.setHoverName(stack.getHoverName()); + } + } + +- for (int i = 0; i < map.size(); i++) { +- itemStack.setRepairCost(AnvilMenu.calculateIncreasedRepairCost(itemStack.getBaseRepairCost())); ++ for (int k = 0; k < map.size(); ++k) { ++ itemstack1.setRepairCost(AnvilMenu.calculateIncreasedRepairCost(itemstack1.getBaseRepairCost())); + } + +- return itemStack; ++ return itemstack1; + } + + @Override +- public void removed(Player player) { ++ public void removed(net.minecraft.world.entity.player.Player player) { + super.removed(player); +- this.access.execute((level, blockPos) -> this.clearContainer(player, this.repairSlots)); ++ this.access.execute((world, blockposition) -> { ++ this.clearContainer(player, this.repairSlots); ++ }); + } + + @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.GRINDSTONE); + } + + @Override +- public ItemStack quickMoveStack(Player player, int index) { +- ItemStack itemStack = ItemStack.EMPTY; +- Slot slot = this.slots.get(index); ++ public ItemStack quickMoveStack(net.minecraft.world.entity.player.Player player, int index) { ++ ItemStack itemstack = ItemStack.EMPTY; ++ Slot slot = (Slot) this.slots.get(index); ++ + if (slot != null && slot.hasItem()) { +- ItemStack item = slot.getItem(); +- itemStack = item.copy(); +- ItemStack item1 = this.repairSlots.getItem(0); +- ItemStack item2 = this.repairSlots.getItem(1); ++ ItemStack itemstack1 = slot.getItem(); ++ ++ itemstack = itemstack1.copy(); ++ ItemStack itemstack2 = this.repairSlots.getItem(0); ++ ItemStack itemstack3 = this.repairSlots.getItem(1); ++ + if (index == 2) { +- if (!this.moveItemStackTo(item, 3, 39, true)) { ++ if (!this.moveItemStackTo(itemstack1, 3, 39, true)) { + return ItemStack.EMPTY; + } + +- slot.onQuickCraft(item, itemStack); ++ slot.onQuickCraft(itemstack1, itemstack); + } else if (index != 0 && index != 1) { +- if (!item1.isEmpty() && !item2.isEmpty()) { ++ if (!itemstack2.isEmpty() && !itemstack3.isEmpty()) { + if (index >= 3 && index < 30) { +- if (!this.moveItemStackTo(item, 30, 39, false)) { ++ if (!this.moveItemStackTo(itemstack1, 30, 39, false)) { + return ItemStack.EMPTY; + } +- } else if (index >= 30 && index < 39 && !this.moveItemStackTo(item, 3, 30, false)) { ++ } else if (index >= 30 && index < 39 && !this.moveItemStackTo(itemstack1, 3, 30, false)) { + return ItemStack.EMPTY; + } +- } else if (!this.moveItemStackTo(item, 0, 2, false)) { ++ } else if (!this.moveItemStackTo(itemstack1, 0, 2, false)) { + return ItemStack.EMPTY; + } +- } else if (!this.moveItemStackTo(item, 3, 39, false)) { ++ } else if (!this.moveItemStackTo(itemstack1, 3, 39, false)) { + return ItemStack.EMPTY; + } + +- if (item.isEmpty()) { ++ if (itemstack1.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + +- if (item.getCount() == itemStack.getCount()) { ++ if (itemstack1.getCount() == itemstack.getCount()) { + return ItemStack.EMPTY; + } + +- slot.onTake(player, item); ++ slot.onTake(player, itemstack1); + } + +- return itemStack; ++ return itemstack; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/HopperMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/HopperMenu.java.patch new file mode 100644 index 0000000000..603f1dc02f --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/HopperMenu.java.patch @@ -0,0 +1,112 @@ +--- a/net/minecraft/world/inventory/HopperMenu.java ++++ b/net/minecraft/world/inventory/HopperMenu.java +@@ -6,10 +6,32 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class HopperMenu extends AbstractContainerMenu { ++ + public static final int CONTAINER_SIZE = 5; + private final Container hopper; + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventory inventory = new CraftInventory(this.hopper); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end ++ + public HopperMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, new SimpleContainer(5)); + } +@@ -17,53 +39,60 @@ + public HopperMenu(int containerId, Inventory playerInventory, Container container) { + super(MenuType.HOPPER, containerId); + this.hopper = container; ++ this.player = playerInventory; // CraftBukkit - save player + checkContainerSize(container, 5); + container.startOpen(playerInventory.player); +- int i = 51; ++ boolean flag = true; + +- for (int i1 = 0; i1 < 5; i1++) { +- this.addSlot(new Slot(container, i1, 44 + i1 * 18, 20)); ++ int j; ++ ++ for (j = 0; j < 5; ++j) { ++ this.addSlot(new Slot(container, j, 44 + j * 18, 20)); + } + +- for (int i1 = 0; i1 < 3; i1++) { +- for (int i2 = 0; i2 < 9; i2++) { +- this.addSlot(new Slot(playerInventory, i2 + i1 * 9 + 9, 8 + i2 * 18, i1 * 18 + 51)); ++ for (j = 0; j < 3; ++j) { ++ for (int k = 0; k < 9; ++k) { ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, j * 18 + 51)); + } + } + +- for (int i1 = 0; i1 < 9; i1++) { +- this.addSlot(new Slot(playerInventory, i1, 8 + i1 * 18, 109)); ++ for (j = 0; j < 9; ++j) { ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 109)); + } ++ + } + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.hopper.stillValid(player); + } + + @Override + public ItemStack quickMoveStack(Player player, int index) { +- ItemStack itemStack = ItemStack.EMPTY; +- Slot slot = this.slots.get(index); ++ ItemStack itemstack = ItemStack.EMPTY; ++ Slot slot = (Slot) this.slots.get(index); ++ + if (slot != null && slot.hasItem()) { +- ItemStack item = slot.getItem(); +- itemStack = item.copy(); ++ ItemStack itemstack1 = slot.getItem(); ++ ++ itemstack = itemstack1.copy(); + if (index < this.hopper.getContainerSize()) { +- if (!this.moveItemStackTo(item, this.hopper.getContainerSize(), this.slots.size(), true)) { ++ if (!this.moveItemStackTo(itemstack1, this.hopper.getContainerSize(), this.slots.size(), true)) { + return ItemStack.EMPTY; + } +- } else if (!this.moveItemStackTo(item, 0, this.hopper.getContainerSize(), false)) { ++ } else if (!this.moveItemStackTo(itemstack1, 0, this.hopper.getContainerSize(), false)) { + return ItemStack.EMPTY; + } + +- if (item.isEmpty()) { ++ if (itemstack1.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + } + +- return itemStack; ++ return itemstack; + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/HorseInventoryMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/HorseInventoryMenu.java.patch new file mode 100644 index 0000000000..259880a6b5 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/HorseInventoryMenu.java.patch @@ -0,0 +1,169 @@ +--- a/net/minecraft/world/inventory/HorseInventoryMenu.java ++++ b/net/minecraft/world/inventory/HorseInventoryMenu.java +@@ -8,17 +8,40 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.inventory.InventoryView; ++// CraftBukkit end ++ + public class HorseInventoryMenu extends AbstractContainerMenu { ++ + private final Container horseContainer; + private final AbstractHorse horse; + ++ // CraftBukkit start ++ org.bukkit.craftbukkit.inventory.CraftInventoryView bukkitEntity; ++ Inventory player; ++ ++ @Override ++ public InventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ return bukkitEntity = new CraftInventoryView(player.player.getBukkitEntity(), horseContainer.getOwner().getInventory(), this); ++ } ++ + public HorseInventoryMenu(int containerId, Inventory playerInventory, Container container, final AbstractHorse horse) { +- super(null, containerId); ++ super((MenuType) null, containerId); ++ player = playerInventory; ++ // CraftBukkit end + this.horseContainer = container; + this.horse = horse; +- int i = 3; ++ boolean flag = true; ++ + container.startOpen(playerInventory.player); +- int i1 = -18; ++ boolean flag1 = true; ++ + this.addSlot(new Slot(container, 0, 8, 18) { + @Override + public boolean mayPlace(ItemStack stack) { +@@ -46,83 +69,88 @@ + return 1; + } + }); ++ int j; ++ int k; ++ + if (this.hasChest(horse)) { +- for (int i2 = 0; i2 < 3; i2++) { +- for (int i3 = 0; i3 < ((AbstractChestedHorse)horse).getInventoryColumns(); i3++) { +- this.addSlot(new Slot(container, 2 + i3 + i2 * ((AbstractChestedHorse)horse).getInventoryColumns(), 80 + i3 * 18, 18 + i2 * 18)); ++ for (j = 0; j < 3; ++j) { ++ for (k = 0; k < ((AbstractChestedHorse) horse).getInventoryColumns(); ++k) { ++ this.addSlot(new Slot(container, 2 + k + j * ((AbstractChestedHorse) horse).getInventoryColumns(), 80 + k * 18, 18 + j * 18)); + } + } + } + +- for (int i2 = 0; i2 < 3; i2++) { +- for (int i3 = 0; i3 < 9; i3++) { +- this.addSlot(new Slot(playerInventory, i3 + i2 * 9 + 9, 8 + i3 * 18, 102 + i2 * 18 + -18)); ++ for (j = 0; j < 3; ++j) { ++ for (k = 0; k < 9; ++k) { ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 102 + j * 18 + -18)); + } + } + +- for (int i2 = 0; i2 < 9; i2++) { +- this.addSlot(new Slot(playerInventory, i2, 8 + i2 * 18, 142)); ++ for (j = 0; j < 9; ++j) { ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } ++ + } + + @Override + public boolean stillValid(Player player) { +- return !this.horse.hasInventoryChanged(this.horseContainer) +- && this.horseContainer.stillValid(player) +- && this.horse.isAlive() +- && this.horse.distanceTo(player) < 8.0F; ++ return !this.horse.hasInventoryChanged(this.horseContainer) && this.horseContainer.stillValid(player) && this.horse.isAlive() && this.horse.distanceTo(player) < 8.0F; + } + + private boolean hasChest(AbstractHorse horse) { +- return horse instanceof AbstractChestedHorse && ((AbstractChestedHorse)horse).hasChest(); ++ return horse instanceof AbstractChestedHorse && ((AbstractChestedHorse) horse).hasChest(); + } + + @Override + public ItemStack quickMoveStack(Player player, int index) { +- ItemStack itemStack = ItemStack.EMPTY; +- Slot slot = this.slots.get(index); ++ ItemStack itemstack = ItemStack.EMPTY; ++ Slot slot = (Slot) this.slots.get(index); ++ + if (slot != null && slot.hasItem()) { +- ItemStack item = slot.getItem(); +- itemStack = item.copy(); +- int containerSize = this.horseContainer.getContainerSize(); +- if (index < containerSize) { +- if (!this.moveItemStackTo(item, containerSize, this.slots.size(), true)) { ++ ItemStack itemstack1 = slot.getItem(); ++ ++ itemstack = itemstack1.copy(); ++ int j = this.horseContainer.getContainerSize(); ++ ++ if (index < j) { ++ if (!this.moveItemStackTo(itemstack1, j, this.slots.size(), true)) { + return ItemStack.EMPTY; + } +- } else if (this.getSlot(1).mayPlace(item) && !this.getSlot(1).hasItem()) { +- if (!this.moveItemStackTo(item, 1, 2, false)) { ++ } else if (this.getSlot(1).mayPlace(itemstack1) && !this.getSlot(1).hasItem()) { ++ if (!this.moveItemStackTo(itemstack1, 1, 2, false)) { + return ItemStack.EMPTY; + } +- } else if (this.getSlot(0).mayPlace(item)) { +- if (!this.moveItemStackTo(item, 0, 1, false)) { ++ } else if (this.getSlot(0).mayPlace(itemstack1)) { ++ if (!this.moveItemStackTo(itemstack1, 0, 1, false)) { + return ItemStack.EMPTY; + } +- } else if (containerSize <= 2 || !this.moveItemStackTo(item, 2, containerSize, false)) { +- int i1 = containerSize + 27; +- int i3 = i1 + 9; +- if (index >= i1 && index < i3) { +- if (!this.moveItemStackTo(item, containerSize, i1, false)) { ++ } else if (j <= 2 || !this.moveItemStackTo(itemstack1, 2, j, false)) { ++ int k = j + 27; ++ int l = k + 9; ++ ++ if (index >= k && index < l) { ++ if (!this.moveItemStackTo(itemstack1, j, k, false)) { + return ItemStack.EMPTY; + } +- } else if (index >= containerSize && index < i1) { +- if (!this.moveItemStackTo(item, i1, i3, false)) { ++ } else if (index >= j && index < k) { ++ if (!this.moveItemStackTo(itemstack1, k, l, false)) { + return ItemStack.EMPTY; + } +- } else if (!this.moveItemStackTo(item, i1, i1, false)) { ++ } else if (!this.moveItemStackTo(itemstack1, k, k, false)) { + return ItemStack.EMPTY; + } + + return ItemStack.EMPTY; + } + +- if (item.isEmpty()) { ++ if (itemstack1.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + } + +- return itemStack; ++ return itemstack; + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/InventoryMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/InventoryMenu.java.patch new file mode 100644 index 0000000000..063abda430 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/InventoryMenu.java.patch @@ -0,0 +1,268 @@ +--- a/net/minecraft/world/inventory/InventoryMenu.java ++++ b/net/minecraft/world/inventory/InventoryMenu.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.inventory; + + import com.mojang.datafixers.util.Pair; ++import net.minecraft.network.chat.Component; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.world.Container; + import net.minecraft.world.entity.EquipmentSlot; +@@ -12,8 +13,12 @@ + import net.minecraft.world.item.crafting.Recipe; + import net.minecraft.world.item.crafting.RecipeHolder; + import net.minecraft.world.item.enchantment.EnchantmentHelper; ++import org.bukkit.craftbukkit.inventory.CraftInventoryCrafting; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end + +-public class InventoryMenu extends RecipeBookMenu { ++public class InventoryMenu extends RecipeBookMenu { ++ + public static final int CONTAINER_ID = 0; + public static final int RESULT_SLOT = 0; + public static final int CRAFT_SLOT_START = 1; +@@ -31,34 +36,49 @@ + public static final ResourceLocation EMPTY_ARMOR_SLOT_LEGGINGS = new ResourceLocation("item/empty_armor_slot_leggings"); + public static final ResourceLocation EMPTY_ARMOR_SLOT_BOOTS = new ResourceLocation("item/empty_armor_slot_boots"); + public static final ResourceLocation EMPTY_ARMOR_SLOT_SHIELD = new ResourceLocation("item/empty_armor_slot_shield"); +- static final ResourceLocation[] TEXTURE_EMPTY_SLOTS = new ResourceLocation[]{ +- EMPTY_ARMOR_SLOT_BOOTS, EMPTY_ARMOR_SLOT_LEGGINGS, EMPTY_ARMOR_SLOT_CHESTPLATE, EMPTY_ARMOR_SLOT_HELMET +- }; ++ static final ResourceLocation[] TEXTURE_EMPTY_SLOTS = new ResourceLocation[]{InventoryMenu.EMPTY_ARMOR_SLOT_BOOTS, InventoryMenu.EMPTY_ARMOR_SLOT_LEGGINGS, InventoryMenu.EMPTY_ARMOR_SLOT_CHESTPLATE, InventoryMenu.EMPTY_ARMOR_SLOT_HELMET}; + private static final EquipmentSlot[] SLOT_IDS = new EquipmentSlot[]{EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET}; +- private final CraftingContainer craftSlots = new TransientCraftingContainer(this, 2, 2); +- private final ResultContainer resultSlots = new ResultContainer(); ++ // CraftBukkit start ++ private final TransientCraftingContainer craftSlots; ++ private final ResultContainer resultSlots; ++ // CraftBukkit end + public final boolean active; + private final Player owner; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ // CraftBukkit end + + public InventoryMenu(Inventory playerInventory, boolean active, final Player owner) { +- super(null, 0); ++ super((MenuType) null, 0); + this.active = active; + this.owner = owner; ++ // CraftBukkit start ++ this.resultSlots = new ResultContainer(); // CraftBukkit - moved to before InventoryCrafting construction ++ this.craftSlots = new TransientCraftingContainer(this, 2, 2, playerInventory.player); // CraftBukkit - pass player ++ this.craftSlots.resultInventory = this.resultSlots; // CraftBukkit - let InventoryCrafting know about its result slot ++ this.player = playerInventory; // CraftBukkit - save player ++ setTitle(Component.translatable("container.crafting")); // SPIGOT-4722: Allocate title for player inventory ++ // CraftBukkit end + this.addSlot(new ResultSlot(playerInventory.player, this.craftSlots, this.resultSlots, 0, 154, 28)); + +- for (int i = 0; i < 2; i++) { +- for (int i1 = 0; i1 < 2; i1++) { +- this.addSlot(new Slot(this.craftSlots, i1 + i * 2, 98 + i1 * 18, 18 + i * 18)); ++ int i; ++ int j; ++ ++ for (i = 0; i < 2; ++i) { ++ for (j = 0; j < 2; ++j) { ++ this.addSlot(new Slot(this.craftSlots, j + i * 2, 98 + j * 18, 18 + i * 18)); + } + } + +- for (int i = 0; i < 4; i++) { +- final EquipmentSlot equipmentSlot = SLOT_IDS[i]; ++ for (i = 0; i < 4; ++i) { ++ final EquipmentSlot enumitemslot = InventoryMenu.SLOT_IDS[i]; ++ + this.addSlot(new Slot(playerInventory, 39 - i, 8, 8 + i * 18) { + @Override +- public void setByPlayer(ItemStack itemStack, ItemStack itemStack1) { +- InventoryMenu.onEquipItem(owner, equipmentSlot, itemStack, itemStack1); +- super.setByPlayer(itemStack, itemStack1); ++ public void setByPlayer(ItemStack itemstack, ItemStack itemstack1) { ++ InventoryMenu.onEquipItem(owner, enumitemslot, itemstack, itemstack1); ++ super.setByPlayer(itemstack, itemstack1); + } + + @Override +@@ -68,37 +88,38 @@ + + @Override + public boolean mayPlace(ItemStack stack) { +- return equipmentSlot == Mob.getEquipmentSlotForItem(stack); ++ return enumitemslot == Mob.getEquipmentSlotForItem(stack); + } + + @Override + public boolean mayPickup(Player player) { +- ItemStack item = this.getItem(); +- return (item.isEmpty() || player.isCreative() || !EnchantmentHelper.hasBindingCurse(item)) && super.mayPickup(player); ++ ItemStack itemstack = this.getItem(); ++ ++ return !itemstack.isEmpty() && !player.isCreative() && EnchantmentHelper.hasBindingCurse(itemstack) ? false : super.mayPickup(player); + } + + @Override + public Pair getNoItemIcon() { +- return Pair.of(InventoryMenu.BLOCK_ATLAS, InventoryMenu.TEXTURE_EMPTY_SLOTS[equipmentSlot.getIndex()]); ++ return Pair.of(InventoryMenu.BLOCK_ATLAS, InventoryMenu.TEXTURE_EMPTY_SLOTS[enumitemslot.getIndex()]); + } + }); + } + +- for (int i = 0; i < 3; i++) { +- for (int i1 = 0; i1 < 9; i1++) { +- this.addSlot(new Slot(playerInventory, i1 + (i + 1) * 9, 8 + i1 * 18, 84 + i * 18)); ++ for (i = 0; i < 3; ++i) { ++ for (j = 0; j < 9; ++j) { ++ this.addSlot(new Slot(playerInventory, j + (i + 1) * 9, 8 + j * 18, 84 + i * 18)); + } + } + +- for (int i = 0; i < 9; i++) { ++ for (i = 0; i < 9; ++i) { + this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142)); + } + + this.addSlot(new Slot(playerInventory, 40, 77, 62) { + @Override +- public void setByPlayer(ItemStack itemStack, ItemStack itemStack1) { +- InventoryMenu.onEquipItem(owner, EquipmentSlot.OFFHAND, itemStack, itemStack1); +- super.setByPlayer(itemStack, itemStack1); ++ public void setByPlayer(ItemStack itemstack, ItemStack itemstack1) { ++ InventoryMenu.onEquipItem(owner, EquipmentSlot.OFFHAND, itemstack, itemstack1); ++ super.setByPlayer(itemstack, itemstack1); + } + + @Override +@@ -128,8 +149,8 @@ + } + + @Override +- public boolean recipeMatches(RecipeHolder> recipeHolder) { +- return recipeHolder.value().matches(this.craftSlots, this.owner.level()); ++ public boolean recipeMatches(RecipeHolder> recipeholder) { ++ return recipeholder.value().matches(this.craftSlots, this.owner.level()); + } + + @Override +@@ -153,64 +174,68 @@ + + @Override + public ItemStack quickMoveStack(Player player, int index) { +- ItemStack itemStack = ItemStack.EMPTY; +- Slot slot = this.slots.get(index); ++ ItemStack itemstack = ItemStack.EMPTY; ++ Slot slot = (Slot) this.slots.get(index); ++ + if (slot.hasItem()) { +- ItemStack item = slot.getItem(); +- itemStack = item.copy(); +- EquipmentSlot equipmentSlotForItem = Mob.getEquipmentSlotForItem(itemStack); ++ ItemStack itemstack1 = slot.getItem(); ++ ++ itemstack = itemstack1.copy(); ++ EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(itemstack); ++ + if (index == 0) { +- if (!this.moveItemStackTo(item, 9, 45, true)) { ++ if (!this.moveItemStackTo(itemstack1, 9, 45, true)) { + return ItemStack.EMPTY; + } + +- slot.onQuickCraft(item, itemStack); ++ slot.onQuickCraft(itemstack1, itemstack); + } else if (index >= 1 && index < 5) { +- if (!this.moveItemStackTo(item, 9, 45, false)) { ++ if (!this.moveItemStackTo(itemstack1, 9, 45, false)) { + return ItemStack.EMPTY; + } + } else if (index >= 5 && index < 9) { +- if (!this.moveItemStackTo(item, 9, 45, false)) { ++ if (!this.moveItemStackTo(itemstack1, 9, 45, false)) { + return ItemStack.EMPTY; + } +- } else if (equipmentSlotForItem.getType() == EquipmentSlot.Type.ARMOR && !this.slots.get(8 - equipmentSlotForItem.getIndex()).hasItem()) { +- int i = 8 - equipmentSlotForItem.getIndex(); +- if (!this.moveItemStackTo(item, i, i + 1, false)) { ++ } else if (enumitemslot.getType() == EquipmentSlot.Function.ARMOR && !((Slot) this.slots.get(8 - enumitemslot.getIndex())).hasItem()) { ++ int j = 8 - enumitemslot.getIndex(); ++ ++ if (!this.moveItemStackTo(itemstack1, j, j + 1, false)) { + return ItemStack.EMPTY; + } +- } else if (equipmentSlotForItem == EquipmentSlot.OFFHAND && !this.slots.get(45).hasItem()) { +- if (!this.moveItemStackTo(item, 45, 46, false)) { ++ } else if (enumitemslot == EquipmentSlot.OFFHAND && !((Slot) this.slots.get(45)).hasItem()) { ++ if (!this.moveItemStackTo(itemstack1, 45, 46, false)) { + return ItemStack.EMPTY; + } + } else if (index >= 9 && index < 36) { +- if (!this.moveItemStackTo(item, 36, 45, false)) { ++ if (!this.moveItemStackTo(itemstack1, 36, 45, false)) { + return ItemStack.EMPTY; + } + } else if (index >= 36 && index < 45) { +- if (!this.moveItemStackTo(item, 9, 36, false)) { ++ if (!this.moveItemStackTo(itemstack1, 9, 36, false)) { + return ItemStack.EMPTY; + } +- } else if (!this.moveItemStackTo(item, 9, 45, false)) { ++ } else if (!this.moveItemStackTo(itemstack1, 9, 45, false)) { + return ItemStack.EMPTY; + } + +- if (item.isEmpty()) { +- slot.setByPlayer(ItemStack.EMPTY, itemStack); ++ if (itemstack1.isEmpty()) { ++ slot.setByPlayer(ItemStack.EMPTY, itemstack); + } else { + slot.setChanged(); + } + +- if (item.getCount() == itemStack.getCount()) { ++ if (itemstack1.getCount() == itemstack.getCount()) { + return ItemStack.EMPTY; + } + +- slot.onTake(player, item); ++ slot.onTake(player, itemstack1); + if (index == 0) { +- player.drop(item, false); ++ player.drop(itemstack1, false); + } + } + +- return itemStack; ++ return itemstack; + } + + @Override +@@ -238,7 +263,7 @@ + return 5; + } + +- public CraftingContainer getCraftSlots() { ++ public InventoryCrafting getCraftSlots() { + return this.craftSlots; + } + +@@ -251,4 +276,17 @@ + public boolean shouldMoveToInventory(int slotIndex) { + return slotIndex != this.getResultSlotIndex(); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryCrafting inventory = new CraftInventoryCrafting(this.craftSlots, this.resultSlots); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/ItemCombinerMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/ItemCombinerMenu.java.patch new file mode 100644 index 0000000000..3736efd372 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/ItemCombinerMenu.java.patch @@ -0,0 +1,238 @@ +--- a/net/minecraft/world/inventory/ItemCombinerMenu.java ++++ b/net/minecraft/world/inventory/ItemCombinerMenu.java +@@ -1,17 +1,17 @@ + package net.minecraft.world.inventory; + ++import java.util.Iterator; + import java.util.List; + import javax.annotation.Nullable; +-import net.minecraft.core.BlockPos; + import net.minecraft.world.Container; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.entity.player.Inventory; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; +-import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public abstract class ItemCombinerMenu extends AbstractContainerMenu { ++ + private static final int INVENTORY_SLOTS_PER_ROW = 9; + private static final int INVENTORY_SLOTS_PER_COLUMN = 3; + protected final ContainerLevelAccess access; +@@ -25,63 +25,70 @@ + + protected abstract void onTake(Player player, ItemStack stack); + +- protected abstract boolean isValidBlock(BlockState state); ++ protected abstract boolean isValidBlock(IBlockData state); + + public ItemCombinerMenu(@Nullable MenuType type, int containerId, Inventory playerInventory, ContainerLevelAccess access) { + super(type, containerId); + this.access = access; + this.player = playerInventory.player; +- ItemCombinerMenuSlotDefinition itemCombinerMenuSlotDefinition = this.createInputSlotDefinitions(); +- this.inputSlots = this.createContainer(itemCombinerMenuSlotDefinition.getNumOfInputSlots()); +- this.inputSlotIndexes = itemCombinerMenuSlotDefinition.getInputSlotIndexes(); +- this.resultSlotIndex = itemCombinerMenuSlotDefinition.getResultSlotIndex(); +- this.createInputSlots(itemCombinerMenuSlotDefinition); +- this.createResultSlot(itemCombinerMenuSlotDefinition); ++ ItemCombinerMenuSlotDefinition itemcombinermenuslotdefinition = this.createInputSlotDefinitions(); ++ ++ this.inputSlots = this.createContainer(itemcombinermenuslotdefinition.getNumOfInputSlots()); ++ this.inputSlotIndexes = itemcombinermenuslotdefinition.getInputSlotIndexes(); ++ this.resultSlotIndex = itemcombinermenuslotdefinition.getResultSlotIndex(); ++ this.createInputSlots(itemcombinermenuslotdefinition); ++ this.createResultSlot(itemcombinermenuslotdefinition); + this.createInventorySlots(playerInventory); + } + + private void createInputSlots(ItemCombinerMenuSlotDefinition slotDefinition) { +- for (final ItemCombinerMenuSlotDefinition.SlotDefinition slotDefinition1 : slotDefinition.getSlots()) { +- this.addSlot(new Slot(this.inputSlots, slotDefinition1.slotIndex(), slotDefinition1.x(), slotDefinition1.y()) { ++ Iterator iterator = slotDefinition.getSlots().iterator(); ++ ++ while (iterator.hasNext()) { ++ final ItemCombinerMenuSlotDefinition.b itemcombinermenuslotdefinition_b = (ItemCombinerMenuSlotDefinition.b) iterator.next(); ++ ++ this.addSlot(new Slot(this.inputSlots, itemcombinermenuslotdefinition_b.slotIndex(), itemcombinermenuslotdefinition_b.x(), itemcombinermenuslotdefinition_b.y()) { + @Override + public boolean mayPlace(ItemStack stack) { +- return slotDefinition1.mayPlace().test(stack); ++ return itemcombinermenuslotdefinition_b.mayPlace().test(stack); + } + }); + } ++ + } + + private void createResultSlot(ItemCombinerMenuSlotDefinition slotDefinition) { +- this.addSlot( +- new Slot(this.resultSlots, slotDefinition.getResultSlot().slotIndex(), slotDefinition.getResultSlot().x(), slotDefinition.getResultSlot().y()) { +- @Override +- public boolean mayPlace(ItemStack stack) { +- return false; +- } +- +- @Override +- public boolean mayPickup(Player player) { +- return ItemCombinerMenu.this.mayPickup(player, this.hasItem()); +- } +- +- @Override +- public void onTake(Player player, ItemStack stack) { +- ItemCombinerMenu.this.onTake(player, stack); +- } ++ this.addSlot(new Slot(this.resultSlots, slotDefinition.getResultSlot().slotIndex(), slotDefinition.getResultSlot().x(), slotDefinition.getResultSlot().y()) { ++ @Override ++ public boolean mayPlace(ItemStack stack) { ++ return false; + } +- ); ++ ++ @Override ++ public boolean mayPickup(Player player) { ++ return ItemCombinerMenu.this.mayPickup(player, this.hasItem()); ++ } ++ ++ @Override ++ public void onTake(Player player, ItemStack stack) { ++ ItemCombinerMenu.this.onTake(player, stack); ++ } ++ }); + } + + private void createInventorySlots(Inventory inventory) { +- for (int i = 0; i < 3; i++) { +- for (int i1 = 0; i1 < 9; i1++) { +- this.addSlot(new Slot(inventory, i1 + i * 9 + 9, 8 + i1 * 18, 84 + i * 18)); ++ int i; ++ ++ for (i = 0; i < 3; ++i) { ++ for (int j = 0; j < 9; ++j) { ++ this.addSlot(new Slot(inventory, j + i * 9 + 9, 8 + j * 18, 84 + i * 18)); + } + } + +- for (int i = 0; i < 9; i++) { ++ for (i = 0; i < 9; ++i) { + this.addSlot(new Slot(inventory, i, 8 + i * 18, 142)); + } ++ + } + + public abstract void createResult(); +@@ -104,73 +111,75 @@ + if (inventory == this.inputSlots) { + this.createResult(); + } ++ + } + + @Override + public void removed(Player player) { + super.removed(player); +- this.access.execute((level, blockPos) -> this.clearContainer(player, this.inputSlots)); ++ this.access.execute((world, blockposition) -> { ++ this.clearContainer(player, this.inputSlots); ++ }); + } + + @Override + public boolean stillValid(Player player) { +- return this.access +- .evaluate( +- (level, blockPos) -> !this.isValidBlock(level.getBlockState(blockPos)) +- ? false +- : player.distanceToSqr((double)blockPos.getX() + 0.5, (double)blockPos.getY() + 0.5, (double)blockPos.getZ() + 0.5) <= 64.0, +- true +- ); ++ if (!this.checkReachable) return true; // CraftBukkit ++ return (Boolean) this.access.evaluate((world, blockposition) -> { ++ return !this.isValidBlock(world.getBlockState(blockposition)) ? false : player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) <= 64.0D; ++ }, true); + } + + @Override + public ItemStack quickMoveStack(Player player, int index) { +- ItemStack itemStack = ItemStack.EMPTY; +- Slot slot = this.slots.get(index); ++ ItemStack itemstack = ItemStack.EMPTY; ++ Slot slot = (Slot) this.slots.get(index); ++ + if (slot != null && slot.hasItem()) { +- ItemStack item = slot.getItem(); +- itemStack = item.copy(); +- int inventorySlotStart = this.getInventorySlotStart(); +- int useRowEnd = this.getUseRowEnd(); ++ ItemStack itemstack1 = slot.getItem(); ++ ++ itemstack = itemstack1.copy(); ++ int j = this.getInventorySlotStart(); ++ int k = this.getUseRowEnd(); ++ + if (index == this.getResultSlot()) { +- if (!this.moveItemStackTo(item, inventorySlotStart, useRowEnd, true)) { ++ if (!this.moveItemStackTo(itemstack1, j, k, true)) { + return ItemStack.EMPTY; + } + +- slot.onQuickCraft(item, itemStack); ++ slot.onQuickCraft(itemstack1, itemstack); + } else if (this.inputSlotIndexes.contains(index)) { +- if (!this.moveItemStackTo(item, inventorySlotStart, useRowEnd, false)) { ++ if (!this.moveItemStackTo(itemstack1, j, k, false)) { + return ItemStack.EMPTY; + } +- } else if (this.canMoveIntoInputSlots(item) && index >= this.getInventorySlotStart() && index < this.getUseRowEnd()) { +- int slotToQuickMoveTo = this.getSlotToQuickMoveTo(itemStack); +- if (!this.moveItemStackTo(item, slotToQuickMoveTo, this.getResultSlot(), false)) { ++ } else if (this.canMoveIntoInputSlots(itemstack1) && index >= this.getInventorySlotStart() && index < this.getUseRowEnd()) { ++ int l = this.getSlotToQuickMoveTo(itemstack); ++ ++ if (!this.moveItemStackTo(itemstack1, l, this.getResultSlot(), false)) { + return ItemStack.EMPTY; + } + } else if (index >= this.getInventorySlotStart() && index < this.getInventorySlotEnd()) { +- if (!this.moveItemStackTo(item, this.getUseRowStart(), this.getUseRowEnd(), false)) { ++ if (!this.moveItemStackTo(itemstack1, this.getUseRowStart(), this.getUseRowEnd(), false)) { + return ItemStack.EMPTY; + } +- } else if (index >= this.getUseRowStart() +- && index < this.getUseRowEnd() +- && !this.moveItemStackTo(item, this.getInventorySlotStart(), this.getInventorySlotEnd(), false)) { ++ } else if (index >= this.getUseRowStart() && index < this.getUseRowEnd() && !this.moveItemStackTo(itemstack1, this.getInventorySlotStart(), this.getInventorySlotEnd(), false)) { + return ItemStack.EMPTY; + } + +- if (item.isEmpty()) { ++ if (itemstack1.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + +- if (item.getCount() == itemStack.getCount()) { ++ if (itemstack1.getCount() == itemstack.getCount()) { + return ItemStack.EMPTY; + } + +- slot.onTake(player, item); ++ slot.onTake(player, itemstack1); + } + +- return itemStack; ++ return itemstack; + } + + protected boolean canMoveIntoInputSlots(ItemStack stack) { +@@ -178,7 +187,7 @@ + } + + public int getSlotToQuickMoveTo(ItemStack stack) { +- return this.inputSlots.isEmpty() ? 0 : this.inputSlotIndexes.get(0); ++ return this.inputSlots.isEmpty() ? 0 : (Integer) this.inputSlotIndexes.get(0); + } + + public int getResultSlot() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/LecternMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/LecternMenu.java.patch new file mode 100644 index 0000000000..101d57b5dd --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/LecternMenu.java.patch @@ -0,0 +1,146 @@ +--- a/net/minecraft/world/inventory/LecternMenu.java ++++ b/net/minecraft/world/inventory/LecternMenu.java +@@ -2,10 +2,33 @@ + + import net.minecraft.world.Container; + import net.minecraft.world.SimpleContainer; +-import net.minecraft.world.entity.player.Player; ++import net.minecraft.world.entity.player.Inventory; + import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.level.block.entity.LecternBlockEntity.LecternInventory; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.inventory.CraftInventoryLectern; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerTakeLecternBookEvent; ++// CraftBukkit end + + public class LecternMenu extends AbstractContainerMenu { ++ ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryLectern inventory = new CraftInventoryLectern(this.lectern); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + private static final int DATA_COUNT = 1; + private static final int SLOT_COUNT = 1; + public static final int BUTTON_PREV_PAGE = 1; +@@ -15,53 +38,64 @@ + private final Container lectern; + private final ContainerData lecternData; + +- public LecternMenu(int containerId) { +- this(containerId, new SimpleContainer(1), new SimpleContainerData(1)); ++ // CraftBukkit start - add player ++ public LecternMenu(int i, Inventory playerinventory) { ++ this(i, new SimpleContainer(1), new SimpleContainerData(1), playerinventory); + } + +- public LecternMenu(int containerId, Container lectern, ContainerData lecternData) { +- super(MenuType.LECTERN, containerId); +- checkContainerSize(lectern, 1); +- checkContainerDataCount(lecternData, 1); +- this.lectern = lectern; +- this.lecternData = lecternData; +- this.addSlot(new Slot(lectern, 0, 0, 0) { ++ public LecternMenu(int i, Container iinventory, ContainerData icontainerproperties, Inventory playerinventory) { ++ // CraftBukkit end ++ super(MenuType.LECTERN, i); ++ checkContainerSize(iinventory, 1); ++ checkContainerDataCount(icontainerproperties, 1); ++ this.lectern = iinventory; ++ this.lecternData = icontainerproperties; ++ this.addSlot(new Slot(iinventory, 0, 0, 0) { + @Override + public void setChanged() { + super.setChanged(); + LecternMenu.this.slotsChanged(this.container); + } + }); +- this.addDataSlots(lecternData); ++ this.addDataSlots(icontainerproperties); ++ player = (Player) playerinventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override +- public boolean clickMenuButton(Player player, int id) { ++ public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { ++ int j; ++ + if (id >= 100) { +- int i = id - 100; +- this.setData(0, i); ++ j = id - 100; ++ this.setData(0, j); + return true; + } else { + switch (id) { +- case 1: { +- int i = this.lecternData.get(0); +- this.setData(0, i - 1); ++ case 1: ++ j = this.lecternData.get(0); ++ this.setData(0, j - 1); + return true; +- } +- case 2: { +- int i = this.lecternData.get(0); +- this.setData(0, i + 1); ++ case 2: ++ j = this.lecternData.get(0); ++ this.setData(0, j + 1); + return true; +- } + case 3: + if (!player.mayBuild()) { + return false; + } + +- ItemStack itemStack = this.lectern.removeItemNoUpdate(0); ++ // CraftBukkit start - Event for taking the book ++ PlayerTakeLecternBookEvent event = new PlayerTakeLecternBookEvent(player, ((CraftInventoryLectern) getBukkitView().getTopInventory()).getHolder()); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ ItemStack itemstack = this.lectern.removeItemNoUpdate(0); ++ + this.lectern.setChanged(); +- if (!player.getInventory().add(itemStack)) { +- player.drop(itemStack, false); ++ if (!player.getInventory().add(itemstack)) { ++ player.drop(itemstack, false); + } + + return true; +@@ -72,7 +106,7 @@ + } + + @Override +- public ItemStack quickMoveStack(Player player, int index) { ++ public ItemStack quickMoveStack(net.minecraft.world.entity.player.Player player, int index) { + return ItemStack.EMPTY; + } + +@@ -83,7 +117,9 @@ + } + + @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (lectern instanceof LecternInventory && !((LecternInventory) lectern).getLectern().hasBook()) return false; // CraftBukkit ++ if (!this.checkReachable) return true; // CraftBukkit + return this.lectern.stillValid(player); + } + diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/LoomMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/LoomMenu.java.patch new file mode 100644 index 0000000000..d5efb07af3 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/LoomMenu.java.patch @@ -0,0 +1,431 @@ +--- a/net/minecraft/world/inventory/LoomMenu.java ++++ b/net/minecraft/world/inventory/LoomMenu.java +@@ -2,7 +2,6 @@ + + import com.google.common.collect.ImmutableList; + import java.util.List; +-import net.minecraft.core.BlockPos; + import net.minecraft.core.Holder; + import net.minecraft.core.registries.BuiltInRegistries; + import net.minecraft.nbt.CompoundTag; +@@ -13,49 +12,56 @@ + import net.minecraft.world.Container; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.entity.player.Inventory; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.BannerItem; + import net.minecraft.world.item.BannerPatternItem; + import net.minecraft.world.item.BlockItem; + import net.minecraft.world.item.DyeColor; + import net.minecraft.world.item.DyeItem; ++import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; +-import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.BannerPattern; + import net.minecraft.world.level.block.entity.BlockEntityType; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.inventory.CraftInventoryLoom; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++// CraftBukkit end + + public class LoomMenu extends AbstractContainerMenu { ++ ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryLoom inventory = new CraftInventoryLoom(this.inputContainer, this.outputContainer); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + private static final int PATTERN_NOT_SET = -1; + private static final int INV_SLOT_START = 4; + private static final int INV_SLOT_END = 31; + private static final int USE_ROW_SLOT_START = 31; + private static final int USE_ROW_SLOT_END = 40; + private final ContainerLevelAccess access; +- final DataSlot selectedBannerPatternIndex = DataSlot.standalone(); +- private List> selectablePatterns = List.of(); +- Runnable slotUpdateListener = () -> { +- }; ++ final DataSlot selectedBannerPatternIndex; ++ private List> selectablePatterns; ++ Runnable slotUpdateListener; + final Slot bannerSlot; + final Slot dyeSlot; + private final Slot patternSlot; + private final Slot resultSlot; + long lastSoundTime; +- private final Container inputContainer = new SimpleContainer(3) { +- @Override +- public void setChanged() { +- super.setChanged(); +- LoomMenu.this.slotsChanged(this); +- LoomMenu.this.slotUpdateListener.run(); +- } +- }; +- private final Container outputContainer = new SimpleContainer(1) { +- @Override +- public void setChanged() { +- super.setChanged(); +- LoomMenu.this.slotUpdateListener.run(); +- } +- }; ++ private final Container inputContainer; ++ private final Container outputContainer; + + public LoomMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, ContainerLevelAccess.NULL); +@@ -63,6 +69,39 @@ + + public LoomMenu(int containerId, Inventory playerInventory, final ContainerLevelAccess access) { + super(MenuType.LOOM, containerId); ++ this.selectedBannerPatternIndex = DataSlot.standalone(); ++ this.selectablePatterns = List.of(); ++ this.slotUpdateListener = () -> { ++ }; ++ this.inputContainer = new SimpleContainer(3) { ++ @Override ++ public void setChanged() { ++ super.setChanged(); ++ LoomMenu.this.slotsChanged(this); ++ LoomMenu.this.slotUpdateListener.run(); ++ } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end ++ }; ++ this.outputContainer = new SimpleContainer(1) { ++ @Override ++ public void setChanged() { ++ super.setChanged(); ++ LoomMenu.this.slotUpdateListener.run(); ++ } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end ++ }; + this.access = access; + this.bannerSlot = this.addSlot(new Slot(this.inputContainer, 0, 13, 26) { + @Override +@@ -89,47 +128,53 @@ + } + + @Override +- public void onTake(Player player, ItemStack stack) { ++ public void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) { + LoomMenu.this.bannerSlot.remove(1); + LoomMenu.this.dyeSlot.remove(1); + if (!LoomMenu.this.bannerSlot.hasItem() || !LoomMenu.this.dyeSlot.hasItem()) { + LoomMenu.this.selectedBannerPatternIndex.set(-1); + } + +- access.execute((level, blockPos) -> { +- long gameTime = level.getGameTime(); +- if (LoomMenu.this.lastSoundTime != gameTime) { +- level.playSound(null, blockPos, SoundEvents.UI_LOOM_TAKE_RESULT, SoundSource.BLOCKS, 1.0F, 1.0F); +- LoomMenu.this.lastSoundTime = gameTime; ++ access.execute((world, blockposition) -> { ++ long j = world.getGameTime(); ++ ++ if (LoomMenu.this.lastSoundTime != j) { ++ world.playSound((net.minecraft.world.entity.player.Player) null, blockposition, SoundEvents.UI_LOOM_TAKE_RESULT, SoundSource.BLOCKS, 1.0F, 1.0F); ++ LoomMenu.this.lastSoundTime = j; + } ++ + }); + super.onTake(player, stack); + } + }); + +- for (int i = 0; i < 3; i++) { +- for (int i1 = 0; i1 < 9; i1++) { +- this.addSlot(new Slot(playerInventory, i1 + i * 9 + 9, 8 + i1 * 18, 84 + i * 18)); ++ int j; ++ ++ for (j = 0; j < 3; ++j) { ++ for (int k = 0; k < 9; ++k) { ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); + } + } + +- for (int i = 0; i < 9; i++) { +- this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142)); ++ for (j = 0; j < 9; ++j) { ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } + + this.addDataSlot(this.selectedBannerPatternIndex); ++ player = (Player) playerInventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.LOOM); + } + + @Override +- public boolean clickMenuButton(Player player, int id) { ++ public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { + if (id >= 0 && id < this.selectablePatterns.size()) { + this.selectedBannerPatternIndex.set(id); +- this.setupResultSlot(this.selectablePatterns.get(id)); ++ this.setupResultSlot((Holder) this.selectablePatterns.get(id)); + return true; + } else { + return false; +@@ -138,11 +183,17 @@ + + private List> getSelectablePatterns(ItemStack stack) { + if (stack.isEmpty()) { +- return BuiltInRegistries.BANNER_PATTERN.getTag(BannerPatternTags.NO_ITEM_REQUIRED).map(ImmutableList::copyOf).orElse(ImmutableList.of()); ++ return (List) BuiltInRegistries.BANNER_PATTERN.getTag(BannerPatternTags.NO_ITEM_REQUIRED).map(ImmutableList::copyOf).orElse(ImmutableList.of()); + } else { +- return (List>)(stack.getItem() instanceof BannerPatternItem bannerPatternItem +- ? BuiltInRegistries.BANNER_PATTERN.getTag(bannerPatternItem.getBannerPattern()).map(ImmutableList::copyOf).orElse(ImmutableList.of()) +- : List.of()); ++ Item item = stack.getItem(); ++ ++ if (item instanceof BannerPatternItem) { ++ BannerPatternItem itembannerpattern = (BannerPatternItem) item; ++ ++ return (List) BuiltInRegistries.BANNER_PATTERN.getTag(itembannerpattern.getBannerPattern()).map(ImmutableList::copyOf).orElse(ImmutableList.of()); ++ } else { ++ return List.of(); ++ } + } + } + +@@ -152,27 +203,31 @@ + + @Override + public void slotsChanged(Container inventory) { +- ItemStack item = this.bannerSlot.getItem(); +- ItemStack item1 = this.dyeSlot.getItem(); +- ItemStack item2 = this.patternSlot.getItem(); +- if (!item.isEmpty() && !item1.isEmpty()) { ++ ItemStack itemstack = this.bannerSlot.getItem(); ++ ItemStack itemstack1 = this.dyeSlot.getItem(); ++ ItemStack itemstack2 = this.patternSlot.getItem(); ++ ++ if (!itemstack.isEmpty() && !itemstack1.isEmpty()) { + int i = this.selectedBannerPatternIndex.get(); +- boolean isValidPatternIndex = this.isValidPatternIndex(i); ++ boolean flag = this.isValidPatternIndex(i); + List> list = this.selectablePatterns; +- this.selectablePatterns = this.getSelectablePatterns(item2); +- Holder holder; ++ ++ this.selectablePatterns = this.getSelectablePatterns(itemstack2); ++ Holder holder; ++ + if (this.selectablePatterns.size() == 1) { + this.selectedBannerPatternIndex.set(0); +- holder = this.selectablePatterns.get(0); +- } else if (!isValidPatternIndex) { ++ holder = (Holder) this.selectablePatterns.get(0); ++ } else if (!flag) { + this.selectedBannerPatternIndex.set(-1); + holder = null; + } else { +- Holder holder1 = list.get(i); +- int index = this.selectablePatterns.indexOf(holder1); +- if (index != -1) { ++ Holder holder1 = (Holder) list.get(i); ++ int j = this.selectablePatterns.indexOf(holder1); ++ ++ if (j != -1) { + holder = holder1; +- this.selectedBannerPatternIndex.set(index); ++ this.selectedBannerPatternIndex.set(j); + } else { + holder = null; + this.selectedBannerPatternIndex.set(-1); +@@ -180,12 +235,10 @@ + } + + if (holder != null) { +- CompoundTag blockEntityData = BlockItem.getBlockEntityData(item); +- boolean flag = blockEntityData != null +- && blockEntityData.contains("Patterns", 9) +- && !item.isEmpty() +- && blockEntityData.getList("Patterns", 10).size() >= 6; +- if (flag) { ++ CompoundTag nbttagcompound = BlockItem.getBlockEntityData(itemstack); ++ boolean flag1 = nbttagcompound != null && nbttagcompound.contains("Patterns", 9) && !itemstack.isEmpty() && nbttagcompound.getList("Patterns", 10).size() >= 6; ++ ++ if (flag1) { + this.selectedBannerPatternIndex.set(-1); + this.resultSlot.set(ItemStack.EMPTY); + } else { +@@ -216,94 +269,107 @@ + } + + @Override +- public ItemStack quickMoveStack(Player player, int index) { +- ItemStack itemStack = ItemStack.EMPTY; +- Slot slot = this.slots.get(index); ++ public ItemStack quickMoveStack(net.minecraft.world.entity.player.Player player, int index) { ++ ItemStack itemstack = ItemStack.EMPTY; ++ Slot slot = (Slot) this.slots.get(index); ++ + if (slot != null && slot.hasItem()) { +- ItemStack item = slot.getItem(); +- itemStack = item.copy(); ++ ItemStack itemstack1 = slot.getItem(); ++ ++ itemstack = itemstack1.copy(); + if (index == this.resultSlot.index) { +- if (!this.moveItemStackTo(item, 4, 40, true)) { ++ if (!this.moveItemStackTo(itemstack1, 4, 40, true)) { + return ItemStack.EMPTY; + } + +- slot.onQuickCraft(item, itemStack); ++ slot.onQuickCraft(itemstack1, itemstack); + } else if (index != this.dyeSlot.index && index != this.bannerSlot.index && index != this.patternSlot.index) { +- if (item.getItem() instanceof BannerItem) { +- if (!this.moveItemStackTo(item, this.bannerSlot.index, this.bannerSlot.index + 1, false)) { ++ if (itemstack1.getItem() instanceof BannerItem) { ++ if (!this.moveItemStackTo(itemstack1, this.bannerSlot.index, this.bannerSlot.index + 1, false)) { + return ItemStack.EMPTY; + } +- } else if (item.getItem() instanceof DyeItem) { +- if (!this.moveItemStackTo(item, this.dyeSlot.index, this.dyeSlot.index + 1, false)) { ++ } else if (itemstack1.getItem() instanceof DyeItem) { ++ if (!this.moveItemStackTo(itemstack1, this.dyeSlot.index, this.dyeSlot.index + 1, false)) { + return ItemStack.EMPTY; + } +- } else if (item.getItem() instanceof BannerPatternItem) { +- if (!this.moveItemStackTo(item, this.patternSlot.index, this.patternSlot.index + 1, false)) { ++ } else if (itemstack1.getItem() instanceof BannerPatternItem) { ++ if (!this.moveItemStackTo(itemstack1, this.patternSlot.index, this.patternSlot.index + 1, false)) { + return ItemStack.EMPTY; + } + } else if (index >= 4 && index < 31) { +- if (!this.moveItemStackTo(item, 31, 40, false)) { ++ if (!this.moveItemStackTo(itemstack1, 31, 40, false)) { + return ItemStack.EMPTY; + } +- } else if (index >= 31 && index < 40 && !this.moveItemStackTo(item, 4, 31, false)) { ++ } else if (index >= 31 && index < 40 && !this.moveItemStackTo(itemstack1, 4, 31, false)) { + return ItemStack.EMPTY; + } +- } else if (!this.moveItemStackTo(item, 4, 40, false)) { ++ } else if (!this.moveItemStackTo(itemstack1, 4, 40, false)) { + return ItemStack.EMPTY; + } + +- if (item.isEmpty()) { ++ if (itemstack1.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + +- if (item.getCount() == itemStack.getCount()) { ++ if (itemstack1.getCount() == itemstack.getCount()) { + return ItemStack.EMPTY; + } + +- slot.onTake(player, item); ++ slot.onTake(player, itemstack1); + } + +- return itemStack; ++ return itemstack; + } + + @Override +- public void removed(Player player) { ++ public void removed(net.minecraft.world.entity.player.Player player) { + super.removed(player); +- this.access.execute((level, blockPos) -> this.clearContainer(player, this.inputContainer)); ++ this.access.execute((world, blockposition) -> { ++ this.clearContainer(player, this.inputContainer); ++ }); + } + + private void setupResultSlot(Holder pattern) { +- ItemStack item = this.bannerSlot.getItem(); +- ItemStack item1 = this.dyeSlot.getItem(); +- ItemStack itemStack = ItemStack.EMPTY; +- if (!item.isEmpty() && !item1.isEmpty()) { +- itemStack = item.copyWithCount(1); +- DyeColor dyeColor = ((DyeItem)item1.getItem()).getDyeColor(); +- CompoundTag blockEntityData = BlockItem.getBlockEntityData(itemStack); +- ListTag list; +- if (blockEntityData != null && blockEntityData.contains("Patterns", 9)) { +- list = blockEntityData.getList("Patterns", 10); ++ ItemStack itemstack = this.bannerSlot.getItem(); ++ ItemStack itemstack1 = this.dyeSlot.getItem(); ++ ItemStack itemstack2 = ItemStack.EMPTY; ++ ++ if (!itemstack.isEmpty() && !itemstack1.isEmpty()) { ++ itemstack2 = itemstack.copyWithCount(1); ++ DyeColor enumcolor = ((DyeItem) itemstack1.getItem()).getDyeColor(); ++ CompoundTag nbttagcompound = BlockItem.getBlockEntityData(itemstack2); ++ ListTag nbttaglist; ++ ++ if (nbttagcompound != null && nbttagcompound.contains("Patterns", 9)) { ++ nbttaglist = nbttagcompound.getList("Patterns", 10); ++ // CraftBukkit start ++ while (nbttaglist.size() > 20) { ++ nbttaglist.remove(20); ++ } ++ // CraftBukkit end + } else { +- list = new ListTag(); +- if (blockEntityData == null) { +- blockEntityData = new CompoundTag(); ++ nbttaglist = new ListTag(); ++ if (nbttagcompound == null) { ++ nbttagcompound = new CompoundTag(); + } + +- blockEntityData.put("Patterns", list); ++ nbttagcompound.put("Patterns", nbttaglist); + } + +- CompoundTag compoundTag = new CompoundTag(); +- compoundTag.putString("Pattern", pattern.value().getHashname()); +- compoundTag.putInt("Color", dyeColor.getId()); +- list.add(compoundTag); +- BlockItem.setBlockEntityData(itemStack, BlockEntityType.BANNER, blockEntityData); ++ CompoundTag nbttagcompound1 = new CompoundTag(); ++ ++ nbttagcompound1.putString("Pattern", ((BannerPattern) pattern.value()).getHashname()); ++ nbttagcompound1.putInt("Color", enumcolor.getId()); ++ nbttaglist.add(nbttagcompound1); ++ BlockItem.setBlockEntityData(itemstack2, BlockEntityType.BANNER, nbttagcompound); + } + +- if (!ItemStack.matches(itemStack, this.resultSlot.getItem())) { +- this.resultSlot.set(itemStack); ++ if (!ItemStack.matches(itemstack2, this.resultSlot.getItem())) { ++ this.resultSlot.set(itemstack2); + } ++ + } + + public Slot getBannerSlot() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/MenuType.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/MenuType.java.patch new file mode 100644 index 0000000000..affa5b0d7f --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/MenuType.java.patch @@ -0,0 +1,45 @@ +--- a/net/minecraft/world/inventory/MenuType.java ++++ b/net/minecraft/world/inventory/MenuType.java +@@ -9,6 +9,7 @@ + import net.minecraft.world.flag.FeatureFlags; + + public class MenuType implements FeatureElement { ++ + public static final MenuType GENERIC_9x1 = register("generic_9x1", ChestMenu::oneRow); + public static final MenuType GENERIC_9x2 = register("generic_9x2", ChestMenu::twoRows); + public static final MenuType GENERIC_9x3 = register("generic_9x3", ChestMenu::threeRows); +@@ -26,7 +27,9 @@ + public static final MenuType FURNACE = register("furnace", FurnaceMenu::new); + public static final MenuType GRINDSTONE = register("grindstone", GrindstoneMenu::new); + public static final MenuType HOPPER = register("hopper", HopperMenu::new); +- public static final MenuType LECTERN = register("lectern", (containerId, playerInventory) -> new LecternMenu(containerId)); ++ public static final MenuType LECTERN = register("lectern", (i, playerinventory) -> { ++ return new LecternMenu(i, playerinventory); // CraftBukkit ++ }); + public static final MenuType LOOM = register("loom", LoomMenu::new); + public static final MenuType MERCHANT = register("merchant", MerchantMenu::new); + public static final MenuType SHULKER_BOX = register("shulker_box", ShulkerBoxMenu::new); +@@ -38,11 +41,11 @@ + private final MenuType.MenuSupplier constructor; + + private static MenuType register(String key, MenuType.MenuSupplier factory) { +- return Registry.register(BuiltInRegistries.MENU, key, new MenuType<>(factory, FeatureFlags.VANILLA_SET)); ++ return (MenuType) Registry.register(BuiltInRegistries.MENU, key, new MenuType<>(factory, FeatureFlags.VANILLA_SET)); + } + + private static MenuType register(String key, MenuType.MenuSupplier factory, FeatureFlag... requiredFeatures) { +- return Registry.register(BuiltInRegistries.MENU, key, new MenuType<>(factory, FeatureFlags.REGISTRY.subset(requiredFeatures))); ++ return (MenuType) Registry.register(BuiltInRegistries.MENU, key, new MenuType<>(factory, FeatureFlags.REGISTRY.subset(requiredFeatures))); + } + + private MenuType(MenuType.MenuSupplier constructor, FeatureFlagSet requiredFeatures) { +@@ -59,7 +62,8 @@ + return this.requiredFeatures; + } + +- interface MenuSupplier { ++ private interface MenuSupplier { ++ + T create(int containerId, Inventory playerInventory); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/MerchantContainer.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/MerchantContainer.java.patch new file mode 100644 index 0000000000..4ce4a4d409 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/MerchantContainer.java.patch @@ -0,0 +1,196 @@ +--- a/net/minecraft/world/inventory/MerchantContainer.java ++++ b/net/minecraft/world/inventory/MerchantContainer.java +@@ -1,24 +1,76 @@ + package net.minecraft.world.inventory; + ++import java.util.Iterator; + import javax.annotation.Nullable; + import net.minecraft.core.NonNullList; + import net.minecraft.world.Container; + import net.minecraft.world.ContainerHelper; ++import net.minecraft.world.entity.npc.AbstractVillager; ++import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.trading.Merchant; + import net.minecraft.world.item.trading.MerchantOffer; + import net.minecraft.world.item.trading.MerchantOffers; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.entity.CraftAbstractVillager; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end + + public class MerchantContainer implements Container { ++ + private final Merchant merchant; +- private final NonNullList itemStacks = NonNullList.withSize(3, ItemStack.EMPTY); ++ private final NonNullList itemStacks; + @Nullable + private MerchantOffer activeOffer; +- private int selectionHint; ++ public int selectionHint; + private int futureXp; + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.itemStacks; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ merchant.setTradingPlayer((Player) null); // SPIGOT-4860 ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return (merchant instanceof AbstractVillager) ? (CraftAbstractVillager) ((AbstractVillager) this.merchant).getBukkitEntity() : null; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return (merchant instanceof Villager) ? ((Villager) this.merchant).getBukkitEntity().getLocation() : null; ++ } ++ // CraftBukkit end ++ + public MerchantContainer(Merchant merchant) { ++ this.itemStacks = NonNullList.withSize(3, ItemStack.EMPTY); + this.merchant = merchant; + } + +@@ -29,32 +81,40 @@ + + @Override + public boolean isEmpty() { +- for (ItemStack itemStack : this.itemStacks) { +- if (!itemStack.isEmpty()) { +- return false; ++ Iterator iterator = this.itemStacks.iterator(); ++ ++ ItemStack itemstack; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return true; + } +- } + +- return true; ++ itemstack = (ItemStack) iterator.next(); ++ } while (itemstack.isEmpty()); ++ ++ return false; + } + + @Override + public ItemStack getItem(int index) { +- return this.itemStacks.get(index); ++ return (ItemStack) this.itemStacks.get(index); + } + + @Override + public ItemStack removeItem(int index, int count) { +- ItemStack itemStack = this.itemStacks.get(index); +- if (index == 2 && !itemStack.isEmpty()) { +- return ContainerHelper.removeItem(this.itemStacks, index, itemStack.getCount()); ++ ItemStack itemstack = (ItemStack) this.itemStacks.get(index); ++ ++ if (index == 2 && !itemstack.isEmpty()) { ++ return ContainerHelper.removeItem(this.itemStacks, index, itemstack.getCount()); + } else { +- ItemStack itemStack1 = ContainerHelper.removeItem(this.itemStacks, index, count); +- if (!itemStack1.isEmpty() && this.isPaymentSlot(index)) { ++ ItemStack itemstack1 = ContainerHelper.removeItem(this.itemStacks, index, count); ++ ++ if (!itemstack1.isEmpty() && this.isPaymentSlot(index)) { + this.updateSellItem(); + } + +- return itemStack1; ++ return itemstack1; + } + } + +@@ -77,6 +137,7 @@ + if (this.isPaymentSlot(index)) { + this.updateSellItem(); + } ++ + } + + @Override +@@ -91,32 +152,35 @@ + + public void updateSellItem() { + this.activeOffer = null; +- ItemStack itemStack; +- ItemStack itemStack1; +- if (this.itemStacks.get(0).isEmpty()) { +- itemStack = this.itemStacks.get(1); +- itemStack1 = ItemStack.EMPTY; ++ ItemStack itemstack; ++ ItemStack itemstack1; ++ ++ if (((ItemStack) this.itemStacks.get(0)).isEmpty()) { ++ itemstack = (ItemStack) this.itemStacks.get(1); ++ itemstack1 = ItemStack.EMPTY; + } else { +- itemStack = this.itemStacks.get(0); +- itemStack1 = this.itemStacks.get(1); ++ itemstack = (ItemStack) this.itemStacks.get(0); ++ itemstack1 = (ItemStack) this.itemStacks.get(1); + } + +- if (itemStack.isEmpty()) { ++ if (itemstack.isEmpty()) { + this.setItem(2, ItemStack.EMPTY); + this.futureXp = 0; + } else { +- MerchantOffers offers = this.merchant.getOffers(); +- if (!offers.isEmpty()) { +- MerchantOffer recipeFor = offers.getRecipeFor(itemStack, itemStack1, this.selectionHint); +- if (recipeFor == null || recipeFor.isOutOfStock()) { +- this.activeOffer = recipeFor; +- recipeFor = offers.getRecipeFor(itemStack1, itemStack, this.selectionHint); ++ MerchantOffers merchantrecipelist = this.merchant.getOffers(); ++ ++ if (!merchantrecipelist.isEmpty()) { ++ MerchantOffer merchantrecipe = merchantrecipelist.getRecipeFor(itemstack, itemstack1, this.selectionHint); ++ ++ if (merchantrecipe == null || merchantrecipe.isOutOfStock()) { ++ this.activeOffer = merchantrecipe; ++ merchantrecipe = merchantrecipelist.getRecipeFor(itemstack1, itemstack, this.selectionHint); + } + +- if (recipeFor != null && !recipeFor.isOutOfStock()) { +- this.activeOffer = recipeFor; +- this.setItem(2, recipeFor.assemble()); +- this.futureXp = recipeFor.getXp(); ++ if (merchantrecipe != null && !merchantrecipe.isOutOfStock()) { ++ this.activeOffer = merchantrecipe; ++ this.setItem(2, merchantrecipe.assemble()); ++ this.futureXp = merchantrecipe.getXp(); + } else { + this.setItem(2, ItemStack.EMPTY); + this.futureXp = 0; diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/MerchantMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/MerchantMenu.java.patch new file mode 100644 index 0000000000..288e1f73d9 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/MerchantMenu.java.patch @@ -0,0 +1,253 @@ +--- a/net/minecraft/world/inventory/MerchantMenu.java ++++ b/net/minecraft/world/inventory/MerchantMenu.java +@@ -9,9 +9,12 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.trading.Merchant; ++import net.minecraft.world.item.trading.MerchantOffer; + import net.minecraft.world.item.trading.MerchantOffers; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; // CraftBukkit + + public class MerchantMenu extends AbstractContainerMenu { ++ + protected static final int PAYMENT1_SLOT = 0; + protected static final int PAYMENT2_SLOT = 1; + protected static final int RESULT_SLOT = 2; +@@ -29,6 +32,19 @@ + private boolean showProgressBar; + private boolean canRestock; + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Inventory player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity == null) { ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), new org.bukkit.craftbukkit.inventory.CraftInventoryMerchant(trader, tradeContainer), this); ++ } ++ return bukkitEntity; ++ } ++ // CraftBukkit end ++ + public MerchantMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, new ClientSideMerchant(playerInventory.player)); + } +@@ -40,16 +56,20 @@ + this.addSlot(new Slot(this.tradeContainer, 0, 136, 37)); + this.addSlot(new Slot(this.tradeContainer, 1, 162, 37)); + this.addSlot(new MerchantResultSlot(playerInventory.player, trader, this.tradeContainer, 2, 220, 37)); ++ this.player = playerInventory; // CraftBukkit - save player + +- for (int i = 0; i < 3; i++) { +- for (int i1 = 0; i1 < 9; i1++) { +- this.addSlot(new Slot(playerInventory, i1 + i * 9 + 9, 108 + i1 * 18, 84 + i * 18)); ++ int j; ++ ++ for (j = 0; j < 3; ++j) { ++ for (int k = 0; k < 9; ++k) { ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 108 + k * 18, 84 + j * 18)); + } + } + +- for (int i = 0; i < 9; i++) { +- this.addSlot(new Slot(playerInventory, i, 108 + i * 18, 142)); ++ for (j = 0; j < 9; ++j) { ++ this.addSlot(new Slot(playerInventory, j, 108 + j * 18, 142)); + } ++ + } + + public void setShowProgressBar(boolean showProgressBar) { +@@ -106,124 +126,139 @@ + + @Override + public ItemStack quickMoveStack(Player player, int index) { +- ItemStack itemStack = ItemStack.EMPTY; +- Slot slot = this.slots.get(index); ++ ItemStack itemstack = ItemStack.EMPTY; ++ Slot slot = (Slot) this.slots.get(index); ++ + if (slot != null && slot.hasItem()) { +- ItemStack item = slot.getItem(); +- itemStack = item.copy(); ++ ItemStack itemstack1 = slot.getItem(); ++ ++ itemstack = itemstack1.copy(); + if (index == 2) { +- if (!this.moveItemStackTo(item, 3, 39, true)) { ++ if (!this.moveItemStackTo(itemstack1, 3, 39, true)) { + return ItemStack.EMPTY; + } + +- slot.onQuickCraft(item, itemStack); ++ slot.onQuickCraft(itemstack1, itemstack); + this.playTradeSound(); + } else if (index != 0 && index != 1) { + if (index >= 3 && index < 30) { +- if (!this.moveItemStackTo(item, 30, 39, false)) { ++ if (!this.moveItemStackTo(itemstack1, 30, 39, false)) { + return ItemStack.EMPTY; + } +- } else if (index >= 30 && index < 39 && !this.moveItemStackTo(item, 3, 30, false)) { ++ } else if (index >= 30 && index < 39 && !this.moveItemStackTo(itemstack1, 3, 30, false)) { + return ItemStack.EMPTY; + } +- } else if (!this.moveItemStackTo(item, 3, 39, false)) { ++ } else if (!this.moveItemStackTo(itemstack1, 3, 39, false)) { + return ItemStack.EMPTY; + } + +- if (item.isEmpty()) { ++ if (itemstack1.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + +- if (item.getCount() == itemStack.getCount()) { ++ if (itemstack1.getCount() == itemstack.getCount()) { + return ItemStack.EMPTY; + } + +- slot.onTake(player, item); ++ slot.onTake(player, itemstack1); + } + +- return itemStack; ++ return itemstack; + } + + private void playTradeSound() { +- if (!this.trader.isClientSide()) { +- Entity entity = (Entity)this.trader; +- entity.level() +- .playLocalSound(entity.getX(), entity.getY(), entity.getZ(), this.trader.getNotifyTradeSound(), SoundSource.NEUTRAL, 1.0F, 1.0F, false); ++ if (!this.trader.isClientSide() && this.trader instanceof Entity) { // CraftBukkit - SPIGOT-5035 ++ Entity entity = (Entity) this.trader; ++ ++ entity.level().playLocalSound(entity.getX(), entity.getY(), entity.getZ(), this.trader.getNotifyTradeSound(), SoundSource.NEUTRAL, 1.0F, 1.0F, false); + } ++ + } + + @Override + public void removed(Player player) { + super.removed(player); +- this.trader.setTradingPlayer(null); ++ this.trader.setTradingPlayer((Player) null); + if (!this.trader.isClientSide()) { +- if (!player.isAlive() || player instanceof ServerPlayer && ((ServerPlayer)player).hasDisconnected()) { +- ItemStack itemStack = this.tradeContainer.removeItemNoUpdate(0); +- if (!itemStack.isEmpty()) { +- player.drop(itemStack, false); ++ if (player.isAlive() && (!(player instanceof ServerPlayer) || !((ServerPlayer) player).hasDisconnected())) { ++ if (player instanceof ServerPlayer) { ++ player.getInventory().placeItemBackInInventory(this.tradeContainer.removeItemNoUpdate(0)); ++ player.getInventory().placeItemBackInInventory(this.tradeContainer.removeItemNoUpdate(1)); + } ++ } else { ++ ItemStack itemstack = this.tradeContainer.removeItemNoUpdate(0); + +- itemStack = this.tradeContainer.removeItemNoUpdate(1); +- if (!itemStack.isEmpty()) { +- player.drop(itemStack, false); ++ if (!itemstack.isEmpty()) { ++ player.drop(itemstack, false); + } +- } else if (player instanceof ServerPlayer) { +- player.getInventory().placeItemBackInInventory(this.tradeContainer.removeItemNoUpdate(0)); +- player.getInventory().placeItemBackInInventory(this.tradeContainer.removeItemNoUpdate(1)); ++ ++ itemstack = this.tradeContainer.removeItemNoUpdate(1); ++ if (!itemstack.isEmpty()) { ++ player.drop(itemstack, false); ++ } + } ++ + } + } + + public void tryMoveItems(int selectedMerchantRecipe) { + if (selectedMerchantRecipe >= 0 && this.getOffers().size() > selectedMerchantRecipe) { +- ItemStack item = this.tradeContainer.getItem(0); +- if (!item.isEmpty()) { +- if (!this.moveItemStackTo(item, 3, 39, true)) { ++ ItemStack itemstack = this.tradeContainer.getItem(0); ++ ++ if (!itemstack.isEmpty()) { ++ if (!this.moveItemStackTo(itemstack, 3, 39, true)) { + return; + } + +- this.tradeContainer.setItem(0, item); ++ this.tradeContainer.setItem(0, itemstack); + } + +- ItemStack item1 = this.tradeContainer.getItem(1); +- if (!item1.isEmpty()) { +- if (!this.moveItemStackTo(item1, 3, 39, true)) { ++ ItemStack itemstack1 = this.tradeContainer.getItem(1); ++ ++ if (!itemstack1.isEmpty()) { ++ if (!this.moveItemStackTo(itemstack1, 3, 39, true)) { + return; + } + +- this.tradeContainer.setItem(1, item1); ++ this.tradeContainer.setItem(1, itemstack1); + } + + if (this.tradeContainer.getItem(0).isEmpty() && this.tradeContainer.getItem(1).isEmpty()) { +- ItemStack costA = this.getOffers().get(selectedMerchantRecipe).getCostA(); +- this.moveFromInventoryToPaymentSlot(0, costA); +- ItemStack costB = this.getOffers().get(selectedMerchantRecipe).getCostB(); +- this.moveFromInventoryToPaymentSlot(1, costB); ++ ItemStack itemstack2 = ((MerchantOffer) this.getOffers().get(selectedMerchantRecipe)).getCostA(); ++ ++ this.moveFromInventoryToPaymentSlot(0, itemstack2); ++ ItemStack itemstack3 = ((MerchantOffer) this.getOffers().get(selectedMerchantRecipe)).getCostB(); ++ ++ this.moveFromInventoryToPaymentSlot(1, itemstack3); + } ++ + } + } + + private void moveFromInventoryToPaymentSlot(int paymentSlotIndex, ItemStack paymentSlot) { + if (!paymentSlot.isEmpty()) { +- for (int i = 3; i < 39; i++) { +- ItemStack item = this.slots.get(i).getItem(); +- if (!item.isEmpty() && ItemStack.isSameItemSameTags(paymentSlot, item)) { +- ItemStack item1 = this.tradeContainer.getItem(paymentSlotIndex); +- int i1 = item1.isEmpty() ? 0 : item1.getCount(); +- int min = Math.min(paymentSlot.getMaxStackSize() - i1, item.getCount()); +- ItemStack itemStack = item.copy(); +- int i2 = i1 + min; +- item.shrink(min); +- itemStack.setCount(i2); +- this.tradeContainer.setItem(paymentSlotIndex, itemStack); +- if (i2 >= paymentSlot.getMaxStackSize()) { ++ for (int j = 3; j < 39; ++j) { ++ ItemStack itemstack1 = ((Slot) this.slots.get(j)).getItem(); ++ ++ if (!itemstack1.isEmpty() && ItemStack.isSameItemSameTags(paymentSlot, itemstack1)) { ++ ItemStack itemstack2 = this.tradeContainer.getItem(paymentSlotIndex); ++ int k = itemstack2.isEmpty() ? 0 : itemstack2.getCount(); ++ int l = Math.min(paymentSlot.getMaxStackSize() - k, itemstack1.getCount()); ++ ItemStack itemstack3 = itemstack1.copy(); ++ int i1 = k + l; ++ ++ itemstack1.shrink(l); ++ itemstack3.setCount(i1); ++ this.tradeContainer.setItem(paymentSlotIndex, itemstack3); ++ if (i1 >= paymentSlot.getMaxStackSize()) { + break; + } + } + } + } ++ + } + + public void setOffers(MerchantOffers offers) { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/PlayerEnderChestContainer.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/PlayerEnderChestContainer.java.patch new file mode 100644 index 0000000000..250101bd8c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/PlayerEnderChestContainer.java.patch @@ -0,0 +1,98 @@ +--- a/net/minecraft/world/inventory/PlayerEnderChestContainer.java ++++ b/net/minecraft/world/inventory/PlayerEnderChestContainer.java +@@ -7,13 +7,32 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.entity.EnderChestBlockEntity; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end + + public class PlayerEnderChestContainer extends SimpleContainer { ++ + @Nullable + private EnderChestBlockEntity activeChest; ++ // CraftBukkit start ++ private final Player owner; + +- public PlayerEnderChestContainer() { ++ public InventoryHolder getBukkitOwner() { ++ return owner.getBukkitEntity(); ++ } ++ ++ @Override ++ public Location getLocation() { ++ return this.activeChest != null ? CraftLocation.toBukkit(this.activeChest.getBlockPos(), this.activeChest.getLevel().getWorld()) : null; ++ } ++ ++ public PlayerEnderChestContainer(Player owner) { + super(27); ++ this.owner = owner; ++ // CraftBukkit end + } + + public void setActiveChest(EnderChestBlockEntity enderChestBlockEntity) { +@@ -26,39 +45,45 @@ + + @Override + public void fromTag(ListTag containerNbt) { +- for (int i = 0; i < this.getContainerSize(); i++) { ++ int i; ++ ++ for (i = 0; i < this.getContainerSize(); ++i) { + this.setItem(i, ItemStack.EMPTY); + } + +- for (int i = 0; i < containerNbt.size(); i++) { +- CompoundTag compound = containerNbt.getCompound(i); +- int i1 = compound.getByte("Slot") & 255; +- if (i1 >= 0 && i1 < this.getContainerSize()) { +- this.setItem(i1, ItemStack.of(compound)); ++ for (i = 0; i < containerNbt.size(); ++i) { ++ CompoundTag nbttagcompound = containerNbt.getCompound(i); ++ int j = nbttagcompound.getByte("Slot") & 255; ++ ++ if (j >= 0 && j < this.getContainerSize()) { ++ this.setItem(j, ItemStack.of(nbttagcompound)); + } + } ++ + } + + @Override + public ListTag createTag() { +- ListTag list = new ListTag(); ++ ListTag nbttaglist = new ListTag(); + +- for (int i = 0; i < this.getContainerSize(); i++) { +- ItemStack item = this.getItem(i); +- if (!item.isEmpty()) { +- CompoundTag compoundTag = new CompoundTag(); +- compoundTag.putByte("Slot", (byte)i); +- item.save(compoundTag); +- list.add(compoundTag); ++ for (int i = 0; i < this.getContainerSize(); ++i) { ++ ItemStack itemstack = this.getItem(i); ++ ++ if (!itemstack.isEmpty()) { ++ CompoundTag nbttagcompound = new CompoundTag(); ++ ++ nbttagcompound.putByte("Slot", (byte) i); ++ itemstack.save(nbttagcompound); ++ nbttaglist.add(nbttagcompound); + } + } + +- return list; ++ return nbttaglist; + } + + @Override + public boolean stillValid(Player player) { +- return (this.activeChest == null || this.activeChest.stillValid(player)) && super.stillValid(player); ++ return this.activeChest != null && !this.activeChest.stillValid(player) ? false : super.stillValid(player); + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/ResultContainer.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/ResultContainer.java.patch new file mode 100644 index 0000000000..49eb45cd80 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/ResultContainer.java.patch @@ -0,0 +1,118 @@ +--- a/net/minecraft/world/inventory/ResultContainer.java ++++ b/net/minecraft/world/inventory/ResultContainer.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.inventory; + ++import java.util.Iterator; + import javax.annotation.Nullable; + import net.minecraft.core.NonNullList; + import net.minecraft.world.Container; +@@ -8,30 +9,80 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.crafting.RecipeHolder; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class ResultContainer implements Container, RecipeCraftingHolder { +- private final NonNullList itemStacks = NonNullList.withSize(1, ItemStack.EMPTY); ++ ++ private final NonNullList itemStacks; + @Nullable + private RecipeHolder recipeUsed; + ++ // CraftBukkit start ++ private int maxStack = MAX_STACK; ++ ++ public java.util.List getContents() { ++ return this.itemStacks; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return null; // Result slots don't get an owner ++ } ++ ++ // Don't need a transaction; the InventoryCrafting keeps track of it for us ++ public void onOpen(CraftHumanEntity who) {} ++ public void onClose(CraftHumanEntity who) {} ++ public java.util.List getViewers() { ++ return new java.util.ArrayList(); ++ } ++ + @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return null; ++ } ++ // CraftBukkit end ++ ++ public ResultContainer() { ++ this.itemStacks = NonNullList.withSize(1, ItemStack.EMPTY); ++ } ++ ++ @Override + public int getContainerSize() { + return 1; + } + + @Override + public boolean isEmpty() { +- for (ItemStack itemStack : this.itemStacks) { +- if (!itemStack.isEmpty()) { +- return false; ++ Iterator iterator = this.itemStacks.iterator(); ++ ++ ItemStack itemstack; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return true; + } +- } + +- return true; ++ itemstack = (ItemStack) iterator.next(); ++ } while (itemstack.isEmpty()); ++ ++ return false; + } + + @Override + public ItemStack getItem(int index) { +- return this.itemStacks.get(0); ++ return (ItemStack) this.itemStacks.get(0); + } + + @Override +@@ -50,8 +101,7 @@ + } + + @Override +- public void setChanged() { +- } ++ public void setChanged() {} + + @Override + public boolean stillValid(Player player) { +@@ -64,8 +114,8 @@ + } + + @Override +- public void setRecipeUsed(@Nullable RecipeHolder recipeHolder) { +- this.recipeUsed = recipeHolder; ++ public void setRecipeUsed(@Nullable RecipeHolder recipeholder) { ++ this.recipeUsed = recipeholder; + } + + @Nullable diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/ShulkerBoxMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/ShulkerBoxMenu.java.patch new file mode 100644 index 0000000000..bd5d544366 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/ShulkerBoxMenu.java.patch @@ -0,0 +1,115 @@ +--- a/net/minecraft/world/inventory/ShulkerBoxMenu.java ++++ b/net/minecraft/world/inventory/ShulkerBoxMenu.java +@@ -6,10 +6,30 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class ShulkerBoxMenu extends AbstractContainerMenu { ++ + private static final int CONTAINER_SIZE = 27; + private final Container container; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity; ++ private Inventory player; + ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), new CraftInventory(this.container), this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end ++ + public ShulkerBoxMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, new SimpleContainer(27)); + } +@@ -18,55 +38,63 @@ + super(MenuType.SHULKER_BOX, containerId); + checkContainerSize(container, 27); + this.container = container; ++ this.player = playerInventory; // CraftBukkit - save player + container.startOpen(playerInventory.player); +- int i = 3; +- int i1 = 9; ++ boolean flag = true; ++ boolean flag1 = true; + +- for (int i2 = 0; i2 < 3; i2++) { +- for (int i3 = 0; i3 < 9; i3++) { +- this.addSlot(new ShulkerBoxSlot(container, i3 + i2 * 9, 8 + i3 * 18, 18 + i2 * 18)); ++ int j; ++ int k; ++ ++ for (j = 0; j < 3; ++j) { ++ for (k = 0; k < 9; ++k) { ++ this.addSlot(new ShulkerBoxSlot(container, k + j * 9, 8 + k * 18, 18 + j * 18)); + } + } + +- for (int i2 = 0; i2 < 3; i2++) { +- for (int i3 = 0; i3 < 9; i3++) { +- this.addSlot(new Slot(playerInventory, i3 + i2 * 9 + 9, 8 + i3 * 18, 84 + i2 * 18)); ++ for (j = 0; j < 3; ++j) { ++ for (k = 0; k < 9; ++k) { ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); + } + } + +- for (int i2 = 0; i2 < 9; i2++) { +- this.addSlot(new Slot(playerInventory, i2, 8 + i2 * 18, 142)); ++ for (j = 0; j < 9; ++j) { ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } ++ + } + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(player); + } + + @Override + public ItemStack quickMoveStack(Player player, int index) { +- ItemStack itemStack = ItemStack.EMPTY; +- Slot slot = this.slots.get(index); ++ ItemStack itemstack = ItemStack.EMPTY; ++ Slot slot = (Slot) this.slots.get(index); ++ + if (slot != null && slot.hasItem()) { +- ItemStack item = slot.getItem(); +- itemStack = item.copy(); ++ ItemStack itemstack1 = slot.getItem(); ++ ++ itemstack = itemstack1.copy(); + if (index < this.container.getContainerSize()) { +- if (!this.moveItemStackTo(item, this.container.getContainerSize(), this.slots.size(), true)) { ++ if (!this.moveItemStackTo(itemstack1, this.container.getContainerSize(), this.slots.size(), true)) { + return ItemStack.EMPTY; + } +- } else if (!this.moveItemStackTo(item, 0, this.container.getContainerSize(), false)) { ++ } else if (!this.moveItemStackTo(itemstack1, 0, this.container.getContainerSize(), false)) { + return ItemStack.EMPTY; + } + +- if (item.isEmpty()) { ++ if (itemstack1.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + } + +- return itemStack; ++ return itemstack; + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/SmithingMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/SmithingMenu.java.patch new file mode 100644 index 0000000000..62da5e3e2c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/SmithingMenu.java.patch @@ -0,0 +1,180 @@ +--- a/net/minecraft/world/inventory/SmithingMenu.java ++++ b/net/minecraft/world/inventory/SmithingMenu.java +@@ -3,7 +3,6 @@ + import java.util.List; + import java.util.OptionalInt; + import javax.annotation.Nullable; +-import net.minecraft.core.BlockPos; + import net.minecraft.world.entity.player.Inventory; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; +@@ -12,9 +11,12 @@ + import net.minecraft.world.item.crafting.SmithingRecipe; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; // CraftBukkit ++ + public class SmithingMenu extends ItemCombinerMenu { ++ + public static final int TEMPLATE_SLOT = 0; + public static final int BASE_SLOT = 1; + public static final int ADDITIONAL_SLOT = 2; +@@ -28,6 +30,9 @@ + @Nullable + private RecipeHolder selectedRecipe; + private final List> recipes; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity; ++ // CraftBukkit end + + public SmithingMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, ContainerLevelAccess.NULL); +@@ -41,22 +46,29 @@ + + @Override + protected ItemCombinerMenuSlotDefinition createInputSlotDefinitions() { +- return ItemCombinerMenuSlotDefinition.create() +- .withSlot(0, 8, 48, itemStack -> this.recipes.stream().anyMatch(recipeHolder -> recipeHolder.value().isTemplateIngredient(itemStack))) +- .withSlot(1, 26, 48, itemStack -> this.recipes.stream().anyMatch(recipeHolder -> recipeHolder.value().isBaseIngredient(itemStack))) +- .withSlot(2, 44, 48, itemStack -> this.recipes.stream().anyMatch(recipeHolder -> recipeHolder.value().isAdditionIngredient(itemStack))) +- .withResultSlot(3, 98, 48) +- .build(); ++ return ItemCombinerMenuSlotDefinition.create().withSlot(0, 8, 48, (itemstack) -> { ++ return this.recipes.stream().anyMatch((recipeholder) -> { ++ return ((SmithingRecipe) recipeholder.value()).isTemplateIngredient(itemstack); ++ }); ++ }).withSlot(1, 26, 48, (itemstack) -> { ++ return this.recipes.stream().anyMatch((recipeholder) -> { ++ return ((SmithingRecipe) recipeholder.value()).isBaseIngredient(itemstack); ++ }); ++ }).withSlot(2, 44, 48, (itemstack) -> { ++ return this.recipes.stream().anyMatch((recipeholder) -> { ++ return ((SmithingRecipe) recipeholder.value()).isAdditionIngredient(itemstack); ++ }); ++ }).withResultSlot(3, 98, 48).build(); + } + + @Override +- protected boolean isValidBlock(BlockState state) { ++ protected boolean isValidBlock(IBlockData state) { + return state.is(Blocks.SMITHING_TABLE); + } + + @Override + protected boolean mayPickup(Player player, boolean hasStack) { +- return this.selectedRecipe != null && this.selectedRecipe.value().matches(this.inputSlots, this.level); ++ return this.selectedRecipe != null && ((SmithingRecipe) this.selectedRecipe.value()).matches(this.inputSlots, this.level); + } + + @Override +@@ -66,7 +78,9 @@ + this.shrinkStackInSlot(0); + this.shrinkStackInSlot(1); + this.shrinkStackInSlot(2); +- this.access.execute((level, blockPos) -> level.levelEvent(1044, blockPos, 0)); ++ this.access.execute((world, blockposition) -> { ++ world.levelEvent(1044, blockposition, 0); ++ }); + } + + private List getRelevantItems() { +@@ -74,27 +88,34 @@ + } + + private void shrinkStackInSlot(int index) { +- ItemStack item = this.inputSlots.getItem(index); +- if (!item.isEmpty()) { +- item.shrink(1); +- this.inputSlots.setItem(index, item); ++ ItemStack itemstack = this.inputSlots.getItem(index); ++ ++ if (!itemstack.isEmpty()) { ++ itemstack.shrink(1); ++ this.inputSlots.setItem(index, itemstack); + } ++ + } + + @Override + public void createResult() { +- List> recipesFor = this.level.getRecipeManager().getRecipesFor(RecipeType.SMITHING, this.inputSlots, this.level); +- if (recipesFor.isEmpty()) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ List> list = this.level.getRecipeManager().getRecipesFor(RecipeType.SMITHING, this.inputSlots, this.level); ++ ++ if (list.isEmpty()) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareSmithingEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + } else { +- RecipeHolder recipeHolder = recipesFor.get(0); +- ItemStack itemStack = recipeHolder.value().assemble(this.inputSlots, this.level.registryAccess()); +- if (itemStack.isItemEnabled(this.level.enabledFeatures())) { +- this.selectedRecipe = recipeHolder; +- this.resultSlots.setRecipeUsed(recipeHolder); +- this.resultSlots.setItem(0, itemStack); ++ RecipeHolder recipeholder = (RecipeHolder) list.get(0); ++ ItemStack itemstack = ((SmithingRecipe) recipeholder.value()).assemble(this.inputSlots, this.level.registryAccess()); ++ ++ if (itemstack.isItemEnabled(this.level.enabledFeatures())) { ++ this.selectedRecipe = recipeholder; ++ this.resultSlots.setRecipeUsed(recipeholder); ++ // CraftBukkit start ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareSmithingEvent(getBukkitView(), itemstack); ++ // CraftBukkit end + } + } ++ + } + + @Override +@@ -102,14 +123,8 @@ + return this.findSlotToQuickMoveTo(stack).orElse(0); + } + +- private static OptionalInt findSlotMatchingIngredient(SmithingRecipe smithingRecipe, ItemStack itemStack) { +- if (smithingRecipe.isTemplateIngredient(itemStack)) { +- return OptionalInt.of(0); +- } else if (smithingRecipe.isBaseIngredient(itemStack)) { +- return OptionalInt.of(1); +- } else { +- return smithingRecipe.isAdditionIngredient(itemStack) ? OptionalInt.of(2) : OptionalInt.empty(); +- } ++ private static OptionalInt findSlotMatchingIngredient(SmithingRecipe smithingrecipe, ItemStack itemstack) { ++ return smithingrecipe.isTemplateIngredient(itemstack) ? OptionalInt.of(0) : (smithingrecipe.isBaseIngredient(itemstack) ? OptionalInt.of(1) : (smithingrecipe.isAdditionIngredient(itemstack) ? OptionalInt.of(2) : OptionalInt.empty())); + } + + @Override +@@ -122,11 +137,25 @@ + return this.findSlotToQuickMoveTo(stack).isPresent(); + } + +- private OptionalInt findSlotToQuickMoveTo(ItemStack itemStack) { +- return this.recipes +- .stream() +- .flatMapToInt(recipeHolder -> findSlotMatchingIngredient(recipeHolder.value(), itemStack).stream()) +- .filter(i -> !this.getSlot(i).hasItem()) +- .findFirst(); ++ private OptionalInt findSlotToQuickMoveTo(ItemStack itemstack) { ++ return this.recipes.stream().flatMapToInt((recipeholder) -> { ++ return findSlotMatchingIngredient((SmithingRecipe) recipeholder.value(), itemstack).stream(); ++ }).filter((i) -> { ++ return !this.getSlot(i).hasItem(); ++ }).findFirst(); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventory inventory = new org.bukkit.craftbukkit.inventory.CraftInventorySmithing( ++ access.getLocation(), this.inputSlots, this.resultSlots); ++ bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/StonecutterMenu.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/StonecutterMenu.java.patch new file mode 100644 index 0000000000..33e4a9acb2 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/StonecutterMenu.java.patch @@ -0,0 +1,301 @@ +--- a/net/minecraft/world/inventory/StonecutterMenu.java ++++ b/net/minecraft/world/inventory/StonecutterMenu.java +@@ -2,13 +2,11 @@ + + import com.google.common.collect.Lists; + import java.util.List; +-import net.minecraft.core.BlockPos; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.Container; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.entity.player.Inventory; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.crafting.RecipeHolder; +@@ -17,7 +15,15 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.inventory.CraftInventoryStonecutter; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++// CraftBukkit end ++ + public class StonecutterMenu extends AbstractContainerMenu { ++ + public static final int INPUT_SLOT = 0; + public static final int RESULT_SLOT = 1; + private static final int INV_SLOT_START = 2; +@@ -25,31 +31,59 @@ + private static final int USE_ROW_SLOT_START = 29; + private static final int USE_ROW_SLOT_END = 38; + private final ContainerLevelAccess access; +- private final DataSlot selectedRecipeIndex = DataSlot.standalone(); ++ private final DataSlot selectedRecipeIndex; + private final Level level; +- private List> recipes = Lists.newArrayList(); +- private ItemStack input = ItemStack.EMPTY; ++ private List> recipes; ++ private ItemStack input; + long lastSoundTime; + final Slot inputSlot; + final Slot resultSlot; +- Runnable slotUpdateListener = () -> { +- }; +- public final Container container = new SimpleContainer(1) { +- @Override +- public void setChanged() { +- super.setChanged(); +- StonecutterMenu.this.slotsChanged(this); +- StonecutterMenu.this.slotUpdateListener.run(); ++ Runnable slotUpdateListener; ++ public final Container container; ++ final ResultContainer resultContainer; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; + } +- }; +- final ResultContainer resultContainer = new ResultContainer(); + ++ CraftInventoryStonecutter inventory = new CraftInventoryStonecutter(this.container, this.resultContainer); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end ++ + public StonecutterMenu(int containerId, Inventory playerInventory) { + this(containerId, playerInventory, ContainerLevelAccess.NULL); + } + + public StonecutterMenu(int containerId, Inventory playerInventory, final ContainerLevelAccess access) { + super(MenuType.STONECUTTER, containerId); ++ this.selectedRecipeIndex = DataSlot.standalone(); ++ this.recipes = Lists.newArrayList(); ++ this.input = ItemStack.EMPTY; ++ this.slotUpdateListener = () -> { ++ }; ++ this.container = new SimpleContainer(1) { ++ @Override ++ public void setChanged() { ++ super.setChanged(); ++ StonecutterMenu.this.slotsChanged(this); ++ StonecutterMenu.this.slotUpdateListener.run(); ++ } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return access.getLocation(); ++ } ++ // CraftBukkit end ++ }; ++ this.resultContainer = new ResultContainer(); + this.access = access; + this.level = playerInventory.player.level(); + this.inputSlot = this.addSlot(new Slot(this.container, 0, 20, 33)); +@@ -60,20 +94,23 @@ + } + + @Override +- public void onTake(Player player, ItemStack stack) { ++ public void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) { + stack.onCraftedBy(player.level(), player, stack.getCount()); + StonecutterMenu.this.resultContainer.awardUsedRecipes(player, this.getRelevantItems()); +- ItemStack itemStack = StonecutterMenu.this.inputSlot.remove(1); +- if (!itemStack.isEmpty()) { ++ ItemStack itemstack1 = StonecutterMenu.this.inputSlot.remove(1); ++ ++ if (!itemstack1.isEmpty()) { + StonecutterMenu.this.setupResultSlot(); + } + +- access.execute((level, blockPos) -> { +- long gameTime = level.getGameTime(); +- if (StonecutterMenu.this.lastSoundTime != gameTime) { +- level.playSound(null, blockPos, SoundEvents.UI_STONECUTTER_TAKE_RESULT, SoundSource.BLOCKS, 1.0F, 1.0F); +- StonecutterMenu.this.lastSoundTime = gameTime; ++ access.execute((world, blockposition) -> { ++ long j = world.getGameTime(); ++ ++ if (StonecutterMenu.this.lastSoundTime != j) { ++ world.playSound((net.minecraft.world.entity.player.Player) null, blockposition, SoundEvents.UI_STONECUTTER_TAKE_RESULT, SoundSource.BLOCKS, 1.0F, 1.0F); ++ StonecutterMenu.this.lastSoundTime = j; + } ++ + }); + super.onTake(player, stack); + } +@@ -83,17 +120,20 @@ + } + }); + +- for (int i = 0; i < 3; i++) { +- for (int i1 = 0; i1 < 9; i1++) { +- this.addSlot(new Slot(playerInventory, i1 + i * 9 + 9, 8 + i1 * 18, 84 + i * 18)); ++ int j; ++ ++ for (j = 0; j < 3; ++j) { ++ for (int k = 0; k < 9; ++k) { ++ this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, 84 + j * 18)); + } + } + +- for (int i = 0; i < 9; i++) { +- this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142)); ++ for (j = 0; j < 9; ++j) { ++ this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 142)); + } + + this.addDataSlot(this.selectedRecipeIndex); ++ player = (Player) playerInventory.player.getBukkitEntity(); // CraftBukkit + } + + public int getSelectedRecipeIndex() { +@@ -113,12 +153,13 @@ + } + + @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, player, Blocks.STONECUTTER); + } + + @Override +- public boolean clickMenuButton(Player player, int id) { ++ public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { + if (this.isValidRecipeIndex(id)) { + this.selectedRecipeIndex.set(id); + this.setupResultSlot(); +@@ -133,11 +174,13 @@ + + @Override + public void slotsChanged(Container inventory) { +- ItemStack item = this.inputSlot.getItem(); +- if (!item.is(this.input.getItem())) { +- this.input = item.copy(); +- this.setupRecipeList(inventory, item); ++ ItemStack itemstack = this.inputSlot.getItem(); ++ ++ if (!itemstack.is(this.input.getItem())) { ++ this.input = itemstack.copy(); ++ this.setupRecipeList(inventory, itemstack); + } ++ + } + + private void setupRecipeList(Container container, ItemStack stack) { +@@ -147,15 +190,17 @@ + if (!stack.isEmpty()) { + this.recipes = this.level.getRecipeManager().getRecipesFor(RecipeType.STONECUTTING, container, this.level); + } ++ + } + + void setupResultSlot() { + if (!this.recipes.isEmpty() && this.isValidRecipeIndex(this.selectedRecipeIndex.get())) { +- RecipeHolder recipeHolder = this.recipes.get(this.selectedRecipeIndex.get()); +- ItemStack itemStack = recipeHolder.value().assemble(this.container, this.level.registryAccess()); +- if (itemStack.isItemEnabled(this.level.enabledFeatures())) { +- this.resultContainer.setRecipeUsed(recipeHolder); +- this.resultSlot.set(itemStack); ++ RecipeHolder recipeholder = (RecipeHolder) this.recipes.get(this.selectedRecipeIndex.get()); ++ ItemStack itemstack = ((StonecutterRecipe) recipeholder.value()).assemble(this.container, this.level.registryAccess()); ++ ++ if (itemstack.isItemEnabled(this.level.enabledFeatures())) { ++ this.resultContainer.setRecipeUsed(recipeholder); ++ this.resultSlot.set(itemstack); + } else { + this.resultSlot.set(ItemStack.EMPTY); + } +@@ -181,56 +226,60 @@ + } + + @Override +- public ItemStack quickMoveStack(Player player, int index) { +- ItemStack itemStack = ItemStack.EMPTY; +- Slot slot = this.slots.get(index); ++ public ItemStack quickMoveStack(net.minecraft.world.entity.player.Player player, int index) { ++ ItemStack itemstack = ItemStack.EMPTY; ++ Slot slot = (Slot) this.slots.get(index); ++ + if (slot != null && slot.hasItem()) { +- ItemStack item = slot.getItem(); +- Item item1 = item.getItem(); +- itemStack = item.copy(); ++ ItemStack itemstack1 = slot.getItem(); ++ Item item = itemstack1.getItem(); ++ ++ itemstack = itemstack1.copy(); + if (index == 1) { +- item1.onCraftedBy(item, player.level(), player); +- if (!this.moveItemStackTo(item, 2, 38, true)) { ++ item.onCraftedBy(itemstack1, player.level(), player); ++ if (!this.moveItemStackTo(itemstack1, 2, 38, true)) { + return ItemStack.EMPTY; + } + +- slot.onQuickCraft(item, itemStack); ++ slot.onQuickCraft(itemstack1, itemstack); + } else if (index == 0) { +- if (!this.moveItemStackTo(item, 2, 38, false)) { ++ if (!this.moveItemStackTo(itemstack1, 2, 38, false)) { + return ItemStack.EMPTY; + } +- } else if (this.level.getRecipeManager().getRecipeFor(RecipeType.STONECUTTING, new SimpleContainer(item), this.level).isPresent()) { +- if (!this.moveItemStackTo(item, 0, 1, false)) { ++ } else if (this.level.getRecipeManager().getRecipeFor(RecipeType.STONECUTTING, new SimpleContainer(new ItemStack[]{itemstack1}), this.level).isPresent()) { ++ if (!this.moveItemStackTo(itemstack1, 0, 1, false)) { + return ItemStack.EMPTY; + } + } else if (index >= 2 && index < 29) { +- if (!this.moveItemStackTo(item, 29, 38, false)) { ++ if (!this.moveItemStackTo(itemstack1, 29, 38, false)) { + return ItemStack.EMPTY; + } +- } else if (index >= 29 && index < 38 && !this.moveItemStackTo(item, 2, 29, false)) { ++ } else if (index >= 29 && index < 38 && !this.moveItemStackTo(itemstack1, 2, 29, false)) { + return ItemStack.EMPTY; + } + +- if (item.isEmpty()) { ++ if (itemstack1.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } + + slot.setChanged(); +- if (item.getCount() == itemStack.getCount()) { ++ if (itemstack1.getCount() == itemstack.getCount()) { + return ItemStack.EMPTY; + } + +- slot.onTake(player, item); ++ slot.onTake(player, itemstack1); + this.broadcastChanges(); + } + +- return itemStack; ++ return itemstack; + } + + @Override +- public void removed(Player player) { ++ public void removed(net.minecraft.world.entity.player.Player player) { + super.removed(player); + this.resultContainer.removeItemNoUpdate(1); +- this.access.execute((level, blockPos) -> this.clearContainer(player, this.container)); ++ this.access.execute((world, blockposition) -> { ++ this.clearContainer(player, this.container); ++ }); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/inventory/TransientCraftingContainer.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/inventory/TransientCraftingContainer.java.patch new file mode 100644 index 0000000000..3293479c5a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/inventory/TransientCraftingContainer.java.patch @@ -0,0 +1,170 @@ +--- a/net/minecraft/world/inventory/TransientCraftingContainer.java ++++ b/net/minecraft/world/inventory/TransientCraftingContainer.java +@@ -1,18 +1,92 @@ + package net.minecraft.world.inventory; + ++import java.util.Iterator; + import java.util.List; + import net.minecraft.core.NonNullList; ++import net.minecraft.world.Container; + import net.minecraft.world.ContainerHelper; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.player.StackedContents; + import net.minecraft.world.item.ItemStack; + +-public class TransientCraftingContainer implements CraftingContainer { ++// CraftBukkit start ++import java.util.List; ++import net.minecraft.world.item.crafting.RecipeHolder; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.event.inventory.InventoryType; ++// CraftBukkit end ++ ++public class TransientCraftingContainer implements InventoryCrafting { ++ + private final NonNullList items; + private final int width; + private final int height; + private final AbstractContainerMenu menu; + ++ // CraftBukkit start - add fields ++ public List transaction = new java.util.ArrayList(); ++ private RecipeHolder currentRecipe; ++ public Container resultInventory; ++ private Player owner; ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public InventoryType getInvType() { ++ return items.size() == 4 ? InventoryType.CRAFTING : InventoryType.WORKBENCH; ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return (owner == null) ? null : owner.getBukkitEntity(); ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ resultInventory.setMaxStackSize(size); ++ } ++ ++ @Override ++ public Location getLocation() { ++ return menu instanceof CraftingMenu ? ((CraftingMenu) menu).access.getLocation() : owner.getBukkitEntity().getLocation(); ++ } ++ ++ @Override ++ public RecipeHolder getCurrentRecipe() { ++ return currentRecipe; ++ } ++ ++ @Override ++ public void setCurrentRecipe(RecipeHolder currentRecipe) { ++ this.currentRecipe = currentRecipe; ++ } ++ ++ public TransientCraftingContainer(AbstractContainerMenu container, int i, int j, Player player) { ++ this(container, i, j); ++ this.owner = player; ++ } ++ // CraftBukkit end ++ + public TransientCraftingContainer(AbstractContainerMenu menu, int width, int height) { + this(menu, width, height, NonNullList.withSize(width * height, ItemStack.EMPTY)); + } +@@ -31,18 +105,24 @@ + + @Override + public boolean isEmpty() { +- for (ItemStack itemStack : this.items) { +- if (!itemStack.isEmpty()) { +- return false; ++ Iterator iterator = this.items.iterator(); ++ ++ ItemStack itemstack; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return true; + } +- } + +- return true; ++ itemstack = (ItemStack) iterator.next(); ++ } while (itemstack.isEmpty()); ++ ++ return false; + } + + @Override + public ItemStack getItem(int slot) { +- return slot >= this.getContainerSize() ? ItemStack.EMPTY : this.items.get(slot); ++ return slot >= this.getContainerSize() ? ItemStack.EMPTY : (ItemStack) this.items.get(slot); + } + + @Override +@@ -52,12 +132,13 @@ + + @Override + public ItemStack removeItem(int slot, int amount) { +- ItemStack itemStack = ContainerHelper.removeItem(this.items, slot, amount); +- if (!itemStack.isEmpty()) { ++ ItemStack itemstack = ContainerHelper.removeItem(this.items, slot, amount); ++ ++ if (!itemstack.isEmpty()) { + this.menu.slotsChanged(this); + } + +- return itemStack; ++ return itemstack; + } + + @Override +@@ -67,8 +148,7 @@ + } + + @Override +- public void setChanged() { +- } ++ public void setChanged() {} + + @Override + public boolean stillValid(Player player) { +@@ -97,8 +177,13 @@ + + @Override + public void fillStackedContents(StackedContents contents) { +- for (ItemStack itemStack : this.items) { +- contents.accountSimpleStack(itemStack); ++ Iterator iterator = this.items.iterator(); ++ ++ while (iterator.hasNext()) { ++ ItemStack itemstack = (ItemStack) iterator.next(); ++ ++ contents.accountSimpleStack(itemstack); + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/ArmorItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/ArmorItem.java.patch new file mode 100644 index 0000000000..8e4d6b77b1 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/ArmorItem.java.patch @@ -0,0 +1,176 @@ +--- a/net/minecraft/world/item/ArmorItem.java ++++ b/net/minecraft/world/item/ArmorItem.java +@@ -1,18 +1,19 @@ + package net.minecraft.world.item; + + import com.google.common.collect.ImmutableMultimap; +-import com.google.common.collect.Multimap; + import com.google.common.collect.ImmutableMultimap.Builder; ++import com.google.common.collect.Multimap; + import java.util.EnumMap; + import java.util.List; + import java.util.UUID; + import net.minecraft.Util; + import net.minecraft.core.BlockPos; +-import net.minecraft.core.dispenser.BlockSource; ++import net.minecraft.core.Direction; + import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; + import net.minecraft.core.dispenser.DispenseItemBehavior; ++import net.minecraft.core.dispenser.SourceBlock; + import net.minecraft.sounds.SoundEvent; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EquipmentSlot; +@@ -25,18 +26,24 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.DispenserBlock; + import net.minecraft.world.phys.AABB; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseArmorEvent; ++// CraftBukkit end + + public class ArmorItem extends Item implements Equipable { +- private static final EnumMap ARMOR_MODIFIER_UUID_PER_TYPE = Util.make(new EnumMap<>(ArmorItem.Type.class), map -> { +- map.put(ArmorItem.Type.BOOTS, UUID.fromString("845DB27C-C624-495F-8C9F-6020A9A58B6B")); +- map.put(ArmorItem.Type.LEGGINGS, UUID.fromString("D8499B04-0E66-4726-AB29-64469D734E0D")); +- map.put(ArmorItem.Type.CHESTPLATE, UUID.fromString("9F3D476D-C118-4544-8365-64846904B48E")); +- map.put(ArmorItem.Type.HELMET, UUID.fromString("2AD3F246-FEE1-4E67-B886-69FD380BB150")); ++ ++ private static final EnumMap ARMOR_MODIFIER_UUID_PER_TYPE = (EnumMap) Util.make(new EnumMap(ArmorItem.Type.class), (enummap) -> { ++ enummap.put(ArmorItem.Type.BOOTS, UUID.fromString("845DB27C-C624-495F-8C9F-6020A9A58B6B")); ++ enummap.put(ArmorItem.Type.LEGGINGS, UUID.fromString("D8499B04-0E66-4726-AB29-64469D734E0D")); ++ enummap.put(ArmorItem.Type.CHESTPLATE, UUID.fromString("9F3D476D-C118-4544-8365-64846904B48E")); ++ enummap.put(ArmorItem.Type.HELMET, UUID.fromString("2AD3F246-FEE1-4E67-B886-69FD380BB150")); + }); + public static final DispenseItemBehavior DISPENSE_ITEM_BEHAVIOR = new DefaultDispenseItemBehavior() { + @Override +- protected ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- return ArmorItem.dispenseArmor(blockSource, itemStack) ? itemStack : super.execute(blockSource, itemStack); ++ protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ return ArmorItem.dispenseArmor(sourceblock, itemstack) ? itemstack : super.execute(sourceblock, itemstack); + } + }; + protected final ArmorItem.Type type; +@@ -46,24 +53,49 @@ + protected final ArmorMaterial material; + private final Multimap defaultModifiers; + +- public static boolean dispenseArmor(BlockSource blockSource, ItemStack itemStack) { +- BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); +- List entitiesOfClass = blockSource.level() +- .getEntitiesOfClass( +- LivingEntity.class, new AABB(blockPos), EntitySelector.NO_SPECTATORS.and(new EntitySelector.MobCanWearArmorEntitySelector(itemStack)) +- ); +- if (entitiesOfClass.isEmpty()) { ++ public static boolean dispenseArmor(SourceBlock sourceblock, ItemStack itemstack) { ++ BlockPos blockposition = sourceblock.pos().relative((Direction) sourceblock.state().getValue(DispenserBlock.FACING)); ++ List list = sourceblock.level().getEntitiesOfClass(LivingEntity.class, new AABB(blockposition), EntitySelector.NO_SPECTATORS.and(new EntitySelector.MobCanWearArmorEntitySelector(itemstack))); ++ ++ if (list.isEmpty()) { + return false; + } else { +- LivingEntity livingEntity = entitiesOfClass.get(0); +- EquipmentSlot equipmentSlotForItem = Mob.getEquipmentSlotForItem(itemStack); +- ItemStack itemStack1 = itemStack.split(1); +- livingEntity.setItemSlot(equipmentSlotForItem, itemStack1); +- if (livingEntity instanceof Mob) { +- ((Mob)livingEntity).setDropChance(equipmentSlotForItem, 2.0F); +- ((Mob)livingEntity).setPersistenceRequired(); ++ LivingEntity entityliving = (LivingEntity) list.get(0); ++ EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(itemstack); ++ ItemStack itemstack1 = itemstack.split(1); ++ // CraftBukkit start ++ Level world = sourceblock.level(); ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityliving.getBukkitEntity()); ++ if (!DispenserBlock.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); + } + ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return false; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return true; ++ } ++ } ++ ++ entityliving.setItemSlot(enumitemslot, CraftItemStack.asNMSCopy(event.getItem())); ++ // CraftBukkit end ++ if (entityliving instanceof Mob) { ++ ((Mob) entityliving).setDropChance(enumitemslot, 2.0F); ++ ((Mob) entityliving).setPersistenceRequired(); ++ } ++ + return true; + } + } +@@ -75,16 +107,14 @@ + this.defense = material.getDefenseForType(type); + this.toughness = material.getToughness(); + this.knockbackResistance = material.getKnockbackResistance(); +- DispenserBlock.registerBehavior(this, DISPENSE_ITEM_BEHAVIOR); ++ DispenserBlock.registerBehavior(this, ArmorItem.DISPENSE_ITEM_BEHAVIOR); + Builder builder = ImmutableMultimap.builder(); +- UUID uUID = ARMOR_MODIFIER_UUID_PER_TYPE.get(type); +- builder.put(Attributes.ARMOR, new AttributeModifier(uUID, "Armor modifier", (double)this.defense, AttributeModifier.Operation.ADDITION)); +- builder.put(Attributes.ARMOR_TOUGHNESS, new AttributeModifier(uUID, "Armor toughness", (double)this.toughness, AttributeModifier.Operation.ADDITION)); ++ UUID uuid = (UUID) ArmorItem.ARMOR_MODIFIER_UUID_PER_TYPE.get(type); ++ ++ builder.put(Attributes.ARMOR, new AttributeModifier(uuid, "Armor modifier", (double) this.defense, AttributeModifier.Operation.ADDITION)); ++ builder.put(Attributes.ARMOR_TOUGHNESS, new AttributeModifier(uuid, "Armor toughness", (double) this.toughness, AttributeModifier.Operation.ADDITION)); + if (material == ArmorMaterials.NETHERITE) { +- builder.put( +- Attributes.KNOCKBACK_RESISTANCE, +- new AttributeModifier(uUID, "Armor knockback resistance", (double)this.knockbackResistance, AttributeModifier.Operation.ADDITION) +- ); ++ builder.put(Attributes.KNOCKBACK_RESISTANCE, new AttributeModifier(uuid, "Armor knockback resistance", (double) this.knockbackResistance, AttributeModifier.Operation.ADDITION)); + } + + this.defaultModifiers = builder.build(); +@@ -109,7 +139,7 @@ + } + + @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { + return this.swapWithEquipmentSlot(this, level, player, hand); + } + +@@ -137,17 +167,15 @@ + } + + public static enum Type { +- HELMET(EquipmentSlot.HEAD, "helmet"), +- CHESTPLATE(EquipmentSlot.CHEST, "chestplate"), +- LEGGINGS(EquipmentSlot.LEGS, "leggings"), +- BOOTS(EquipmentSlot.FEET, "boots"); + ++ HELMET(EquipmentSlot.HEAD, "helmet"), CHESTPLATE(EquipmentSlot.CHEST, "chestplate"), LEGGINGS(EquipmentSlot.LEGS, "leggings"), BOOTS(EquipmentSlot.FEET, "boots"); ++ + private final EquipmentSlot slot; + private final String name; + +- private Type(EquipmentSlot slot, String name) { +- this.slot = slot; +- this.name = name; ++ private Type(EquipmentSlot enumitemslot, String s) { ++ this.slot = enumitemslot; ++ this.name = s; + } + + public EquipmentSlot getSlot() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/ArmorStandItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/ArmorStandItem.java.patch new file mode 100644 index 0000000000..1b400dd595 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/ArmorStandItem.java.patch @@ -0,0 +1,89 @@ +--- a/net/minecraft/world/item/ArmorStandItem.java ++++ b/net/minecraft/world/item/ArmorStandItem.java +@@ -8,9 +8,11 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.util.Mth; + import net.minecraft.world.InteractionResult; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.decoration.ArmorStand; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.context.BlockPlaceContext; + import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.Level; +@@ -19,42 +21,50 @@ + import net.minecraft.world.phys.Vec3; + + public class ArmorStandItem extends Item { ++ + public ArmorStandItem(Item.Properties properties) { + super(properties); + } + + @Override + public InteractionResult useOn(UseOnContext context) { +- Direction clickedFace = context.getClickedFace(); +- if (clickedFace == Direction.DOWN) { ++ Direction enumdirection = context.getClickedFace(); ++ ++ if (enumdirection == Direction.DOWN) { + return InteractionResult.FAIL; + } else { +- Level level = context.getLevel(); +- BlockPlaceContext blockPlaceContext = new BlockPlaceContext(context); +- BlockPos clickedPos = blockPlaceContext.getClickedPos(); +- ItemStack itemInHand = context.getItemInHand(); +- Vec3 vec3 = Vec3.atBottomCenterOf(clickedPos); +- AABB aABB = EntityType.ARMOR_STAND.getDimensions().makeBoundingBox(vec3.x(), vec3.y(), vec3.z()); +- if (level.noCollision(null, aABB) && level.getEntities(null, aABB).isEmpty()) { +- if (level instanceof ServerLevel serverLevel) { +- Consumer consumer = EntityType.createDefaultStackConfig(serverLevel, itemInHand, context.getPlayer()); +- ArmorStand armorStand = EntityType.ARMOR_STAND +- .create(serverLevel, itemInHand.getTag(), consumer, clickedPos, MobSpawnType.SPAWN_EGG, true, true); +- if (armorStand == null) { ++ Level world = context.getLevel(); ++ BlockPlaceContext blockactioncontext = new BlockPlaceContext(context); ++ BlockPos blockposition = blockactioncontext.getClickedPos(); ++ ItemStack itemstack = context.getItemInHand(); ++ Vec3 vec3d = Vec3.atBottomCenterOf(blockposition); ++ AABB axisalignedbb = EntityType.ARMOR_STAND.getDimensions().makeBoundingBox(vec3d.x(), vec3d.y(), vec3d.z()); ++ ++ if (world.noCollision((Entity) null, axisalignedbb) && world.getEntities((Entity) null, axisalignedbb).isEmpty()) { ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ Consumer consumer = EntityType.createDefaultStackConfig(worldserver, itemstack, context.getPlayer()); ++ ArmorStand entityarmorstand = (ArmorStand) EntityType.ARMOR_STAND.create(worldserver, itemstack.getTag(), consumer, blockposition, EnumMobSpawn.SPAWN_EGG, true, true); ++ ++ if (entityarmorstand == null) { + return InteractionResult.FAIL; + } + +- float f = (float)Mth.floor((Mth.wrapDegrees(context.getRotation() - 180.0F) + 22.5F) / 45.0F) * 45.0F; +- armorStand.moveTo(armorStand.getX(), armorStand.getY(), armorStand.getZ(), f, 0.0F); +- serverLevel.addFreshEntityWithPassengers(armorStand); +- level.playSound( +- null, armorStand.getX(), armorStand.getY(), armorStand.getZ(), SoundEvents.ARMOR_STAND_PLACE, SoundSource.BLOCKS, 0.75F, 0.8F +- ); +- armorStand.gameEvent(GameEvent.ENTITY_PLACE, context.getPlayer()); ++ float f = (float) Mth.floor((Mth.wrapDegrees(context.getRotation() - 180.0F) + 22.5F) / 45.0F) * 45.0F; ++ ++ entityarmorstand.moveTo(entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), f, 0.0F); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(context, entityarmorstand).isCancelled()) { ++ return InteractionResult.FAIL; ++ } ++ // CraftBukkit end ++ worldserver.addFreshEntityWithPassengers(entityarmorstand); ++ world.playSound((Player) null, entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), SoundEvents.ARMOR_STAND_PLACE, SoundSource.BLOCKS, 0.75F, 0.8F); ++ entityarmorstand.gameEvent(GameEvent.ENTITY_PLACE, context.getPlayer()); + } + +- itemInHand.shrink(1); +- return InteractionResult.sidedSuccess(level.isClientSide); ++ itemstack.shrink(1); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } else { + return InteractionResult.FAIL; + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/BlockItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/BlockItem.java.patch new file mode 100644 index 0000000000..5230934354 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/BlockItem.java.patch @@ -0,0 +1,345 @@ +--- a/net/minecraft/world/item/BlockItem.java ++++ b/net/minecraft/world/item/BlockItem.java +@@ -1,7 +1,10 @@ + package net.minecraft.world.item; + ++import java.util.Iterator; + import java.util.List; + import java.util.Map; ++import java.util.Objects; ++import java.util.stream.Stream; + import javax.annotation.Nullable; + import net.minecraft.advancements.CriteriaTriggers; + import net.minecraft.core.BlockPos; +@@ -9,9 +12,9 @@ + import net.minecraft.nbt.ListTag; + import net.minecraft.network.chat.Component; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; +-import net.minecraft.sounds.SoundSource; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; +@@ -24,15 +27,21 @@ + import net.minecraft.world.level.block.SoundType; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BlockEntityType; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.Property; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.CollisionContext; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.event.block.BlockCanBuildEvent; ++// CraftBukkit end + + public class BlockItem extends Item { ++ + public static final String BLOCK_ENTITY_TAG = "BlockEntityTag"; + public static final String BLOCK_STATE_TAG = "BlockStateTag"; ++ /** @deprecated */ + @Deprecated + private final Block block; + +@@ -43,12 +52,14 @@ + + @Override + public InteractionResult useOn(UseOnContext context) { +- InteractionResult interactionResult = this.place(new BlockPlaceContext(context)); +- if (!interactionResult.consumesAction() && this.isEdible()) { +- InteractionResult result = this.use(context.getLevel(), context.getPlayer(), context.getHand()).getResult(); +- return result == InteractionResult.CONSUME ? InteractionResult.CONSUME_PARTIAL : result; ++ InteractionResult enuminteractionresult = this.place(new BlockPlaceContext(context)); ++ ++ if (!enuminteractionresult.consumesAction() && this.isEdible()) { ++ InteractionResult enuminteractionresult1 = this.use(context.getLevel(), context.getPlayer(), context.getHand()).getResult(); ++ ++ return enuminteractionresult1 == InteractionResult.CONSUME ? InteractionResult.CONSUME_PARTIAL : enuminteractionresult1; + } else { +- return interactionResult; ++ return enuminteractionresult; + } + } + +@@ -58,51 +69,67 @@ + } else if (!context.canPlace()) { + return InteractionResult.FAIL; + } else { +- BlockPlaceContext blockPlaceContext = this.updatePlacementContext(context); +- if (blockPlaceContext == null) { ++ BlockPlaceContext blockactioncontext1 = this.updatePlacementContext(context); ++ ++ if (blockactioncontext1 == null) { + return InteractionResult.FAIL; + } else { +- BlockState placementState = this.getPlacementState(blockPlaceContext); +- if (placementState == null) { ++ IBlockData iblockdata = this.getPlacementState(blockactioncontext1); ++ // CraftBukkit start - special case for handling block placement with water lilies and snow buckets ++ org.bukkit.block.BlockState blockstate = null; ++ if (this instanceof PlaceOnWaterBlockItem || this instanceof SolidBucketItem) { ++ blockstate = org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockactioncontext1.getLevel(), blockactioncontext1.getClickedPos()); ++ } ++ // CraftBukkit end ++ ++ if (iblockdata == null) { + return InteractionResult.FAIL; +- } else if (!this.placeBlock(blockPlaceContext, placementState)) { ++ } else if (!this.placeBlock(blockactioncontext1, iblockdata)) { + return InteractionResult.FAIL; + } else { +- BlockPos clickedPos = blockPlaceContext.getClickedPos(); +- Level level = blockPlaceContext.getLevel(); +- Player player = blockPlaceContext.getPlayer(); +- ItemStack itemInHand = blockPlaceContext.getItemInHand(); +- BlockState blockState = level.getBlockState(clickedPos); +- if (blockState.is(placementState.getBlock())) { +- blockState = this.updateBlockStateFromTag(clickedPos, level, itemInHand, blockState); +- this.updateCustomBlockEntityTag(clickedPos, level, player, itemInHand, blockState); +- blockState.getBlock().setPlacedBy(level, clickedPos, blockState, player, itemInHand); +- if (player instanceof ServerPlayer) { +- CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer)player, clickedPos, itemInHand); ++ BlockPos blockposition = blockactioncontext1.getClickedPos(); ++ Level world = blockactioncontext1.getLevel(); ++ Player entityhuman = blockactioncontext1.getPlayer(); ++ ItemStack itemstack = blockactioncontext1.getItemInHand(); ++ IBlockData iblockdata1 = world.getBlockState(blockposition); ++ ++ if (iblockdata1.is(iblockdata.getBlock())) { ++ iblockdata1 = this.updateBlockStateFromTag(blockposition, world, itemstack, iblockdata1); ++ this.updateCustomBlockEntityTag(blockposition, world, entityhuman, itemstack, iblockdata1); ++ iblockdata1.getBlock().setPlacedBy(world, blockposition, iblockdata1, entityhuman, itemstack); ++ // CraftBukkit start ++ if (blockstate != null) { ++ org.bukkit.event.block.BlockPlaceEvent placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEvent((ServerLevel) world, entityhuman, blockactioncontext1.getHand(), blockstate, blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild())) { ++ blockstate.update(true, false); ++ ++ if (this instanceof SolidBucketItem) { ++ ((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 ++ } ++ return InteractionResult.FAIL; ++ } + } ++ // CraftBukkit end ++ if (entityhuman instanceof ServerPlayer) { ++ CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) entityhuman, blockposition, itemstack); ++ } + } + +- SoundType soundType = blockState.getSoundType(); +- level.playSound( +- player, +- clickedPos, +- this.getPlaceSound(blockState), +- SoundSource.BLOCKS, +- (soundType.getVolume() + 1.0F) / 2.0F, +- soundType.getPitch() * 0.8F +- ); +- level.gameEvent(GameEvent.BLOCK_PLACE, clickedPos, GameEvent.Context.of(player, blockState)); +- if (player == null || !player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ SoundType soundeffecttype = iblockdata1.getSoundType(); ++ ++ // world.playSound(entityhuman, blockposition, this.getPlaceSound(iblockdata1), SoundCategory.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F); ++ world.gameEvent(GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(entityhuman, iblockdata1)); ++ if ((entityhuman == null || !entityhuman.getAbilities().instabuild) && itemstack != ItemStack.EMPTY) { // CraftBukkit ++ itemstack.shrink(1); + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } + } + } + } + +- protected SoundEvent getPlaceSound(BlockState state) { ++ protected SoundEvent getPlaceSound(IBlockData state) { + return state.getSoundType().getPlaceSound(); + } + +@@ -111,77 +138,106 @@ + return context; + } + +- protected boolean updateCustomBlockEntityTag(BlockPos pos, Level level, @Nullable Player player, ItemStack stack, BlockState state) { ++ protected boolean updateCustomBlockEntityTag(BlockPos pos, Level level, @Nullable Player player, ItemStack stack, IBlockData state) { + return updateCustomBlockEntityTag(level, player, pos, stack); + } + + @Nullable +- protected BlockState getPlacementState(BlockPlaceContext context) { +- BlockState stateForPlacement = this.getBlock().getStateForPlacement(context); +- return stateForPlacement != null && this.canPlace(context, stateForPlacement) ? stateForPlacement : null; ++ protected IBlockData getPlacementState(BlockPlaceContext context) { ++ IBlockData iblockdata = this.getBlock().getStateForPlacement(context); ++ ++ return iblockdata != null && this.canPlace(context, iblockdata) ? iblockdata : null; + } + +- private BlockState updateBlockStateFromTag(BlockPos pos, Level level, ItemStack stack, BlockState state) { +- BlockState blockState = state; +- CompoundTag tag = stack.getTag(); +- if (tag != null) { +- CompoundTag compound = tag.getCompound("BlockStateTag"); +- StateDefinition stateDefinition = state.getBlock().getStateDefinition(); ++ private IBlockData updateBlockStateFromTag(BlockPos pos, Level level, ItemStack stack, IBlockData state) { ++ IBlockData iblockdata1 = state; ++ CompoundTag nbttagcompound = stack.getTag(); + +- for (String string : compound.getAllKeys()) { +- Property property = stateDefinition.getProperty(string); +- if (property != null) { +- String asString = compound.get(string).getAsString(); +- blockState = updateState(blockState, property, asString); +- } +- } ++ if (nbttagcompound != null) { ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("BlockStateTag"); ++ // CraftBukkit start ++ iblockdata1 = getBlockState(iblockdata1, nbttagcompound1); + } + +- if (blockState != state) { +- level.setBlock(pos, blockState, 2); ++ if (iblockdata1 != state) { ++ level.setBlock(pos, iblockdata1, 2); + } + +- return blockState; ++ return iblockdata1; + } + +- private static > BlockState updateState(BlockState state, Property property, String valueIdentifier) { +- return property.getValue(valueIdentifier).map(comparable -> state.setValue(property, comparable)).orElse(state); ++ public static IBlockData getBlockState(IBlockData iblockdata, CompoundTag nbttagcompound1) { ++ IBlockData iblockdata1 = iblockdata; ++ { ++ // CraftBukkit end ++ StateDefinition blockstatelist = iblockdata.getBlock().getStateDefinition(); ++ Iterator iterator = nbttagcompound1.getAllKeys().iterator(); ++ ++ while (iterator.hasNext()) { ++ String s = (String) iterator.next(); ++ Property iblockstate = blockstatelist.getProperty(s); ++ ++ if (iblockstate != null) { ++ String s1 = nbttagcompound1.get(s).getAsString(); ++ ++ iblockdata1 = updateState(iblockdata1, iblockstate, s1); ++ } ++ } ++ } ++ return iblockdata1; + } + +- protected boolean canPlace(BlockPlaceContext context, BlockState state) { +- Player player = context.getPlayer(); +- CollisionContext collisionContext = player == null ? CollisionContext.empty() : CollisionContext.of(player); +- return (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) +- && context.getLevel().isUnobstructed(state, context.getClickedPos(), collisionContext); ++ private static > IBlockData updateState(IBlockData state, Property property, String valueIdentifier) { ++ return (IBlockData) property.getValue(valueIdentifier).map((comparable) -> { ++ return (IBlockData) state.setValue(property, comparable); ++ }).orElse(state); + } + ++ protected boolean canPlace(BlockPlaceContext context, IBlockData state) { ++ Player entityhuman = context.getPlayer(); ++ CollisionContext voxelshapecollision = entityhuman == null ? CollisionContext.empty() : CollisionContext.of(entityhuman); ++ // CraftBukkit start - store default return ++ boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && context.getLevel().isUnobstructed(state, context.getClickedPos(), voxelshapecollision); ++ org.bukkit.entity.Player player = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null; ++ ++ BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(context.getLevel(), context.getClickedPos()), player, CraftBlockData.fromData(state), defaultReturn); ++ context.getLevel().getCraftServer().getPluginManager().callEvent(event); ++ ++ return event.isBuildable(); ++ // CraftBukkit end ++ } ++ + protected boolean mustSurvive() { + return true; + } + +- protected boolean placeBlock(BlockPlaceContext context, BlockState state) { ++ protected boolean placeBlock(BlockPlaceContext context, IBlockData state) { + return context.getLevel().setBlock(context.getClickedPos(), state, 11); + } + + public static boolean updateCustomBlockEntityTag(Level level, @Nullable Player player, BlockPos pos, ItemStack stack) { +- MinecraftServer server = level.getServer(); +- if (server == null) { ++ MinecraftServer minecraftserver = level.getServer(); ++ ++ if (minecraftserver == null) { + return false; + } else { +- CompoundTag blockEntityData = getBlockEntityData(stack); +- if (blockEntityData != null) { +- BlockEntity blockEntity = level.getBlockEntity(pos); +- if (blockEntity != null) { +- if (!level.isClientSide && blockEntity.onlyOpCanSetNbt() && (player == null || !player.canUseGameMasterBlocks())) { ++ CompoundTag nbttagcompound = getBlockEntityData(stack); ++ ++ if (nbttagcompound != null) { ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity != null) { ++ if (!level.isClientSide && tileentity.onlyOpCanSetNbt() && (player == null || !player.canUseGameMasterBlocks())) { + return false; + } + +- CompoundTag compoundTag = blockEntity.saveWithoutMetadata(); +- CompoundTag compoundTag1 = compoundTag.copy(); +- compoundTag.merge(blockEntityData); +- if (!compoundTag.equals(compoundTag1)) { +- blockEntity.load(compoundTag); +- blockEntity.setChanged(); ++ CompoundTag nbttagcompound1 = tileentity.saveWithoutMetadata(); ++ CompoundTag nbttagcompound2 = nbttagcompound1.copy(); ++ ++ nbttagcompound1.merge(nbttagcompound); ++ if (!nbttagcompound1.equals(nbttagcompound2)) { ++ tileentity.load(nbttagcompound1); ++ tileentity.setChanged(); + return true; + } + } +@@ -218,13 +274,18 @@ + @Override + public void onDestroyed(ItemEntity itemEntity) { + if (this.block instanceof ShulkerBoxBlock) { +- ItemStack item = itemEntity.getItem(); +- CompoundTag blockEntityData = getBlockEntityData(item); +- if (blockEntityData != null && blockEntityData.contains("Items", 9)) { +- ListTag list = blockEntityData.getList("Items", 10); +- ItemUtils.onContainerDestroyed(itemEntity, list.stream().map(CompoundTag.class::cast).map(ItemStack::of)); ++ ItemStack itemstack = itemEntity.getItem(); ++ CompoundTag nbttagcompound = getBlockEntityData(itemstack); ++ ++ if (nbttagcompound != null && nbttagcompound.contains("Items", 9)) { ++ ListTag nbttaglist = nbttagcompound.getList("Items", 10); ++ Stream stream = nbttaglist.stream(); // CraftBukkit - decompile error ++ ++ Objects.requireNonNull(CompoundTag.class); ++ ItemUtils.onContainerDestroyed(itemEntity, stream.map(CompoundTag.class::cast).map(ItemStack::of)); + } + } ++ + } + + @Nullable +@@ -239,6 +300,7 @@ + BlockEntity.addEntityType(blockEntityData, blockEntityType); + stack.addTagElement("BlockEntityTag", blockEntityData); + } ++ + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/BoatItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/BoatItem.java.patch new file mode 100644 index 0000000000..62e5ee2651 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/BoatItem.java.patch @@ -0,0 +1,141 @@ +--- a/net/minecraft/world/item/BoatItem.java ++++ b/net/minecraft/world/item/BoatItem.java +@@ -1,10 +1,11 @@ + package net.minecraft.world.item; + ++import java.util.Iterator; + import java.util.List; + import java.util.function.Predicate; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntitySelector; +@@ -16,10 +17,12 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; ++import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; + + public class BoatItem extends Item { ++ + private static final Predicate ENTITY_PREDICATE = EntitySelector.NO_SPECTATORS.and(Entity::isPickable); + private final Boat.Type type; + private final boolean hasChest; +@@ -31,57 +34,81 @@ + } + + @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- HitResult playerPOVHitResult = getPlayerPOVHitResult(level, player, ClipContext.Fluid.ANY); +- if (playerPOVHitResult.getType() == HitResult.Type.MISS) { +- return InteractionResultHolder.pass(itemInHand); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ BlockHitResult movingobjectpositionblock = getPlayerPOVHitResult(level, player, ClipContext.Fluid.ANY); ++ ++ if (movingobjectpositionblock.getType() == HitResult.EnumMovingObjectType.MISS) { ++ return InteractionResultHolder.pass(itemstack); + } else { +- Vec3 viewVector = player.getViewVector(1.0F); +- double d = 5.0; +- List entities = level.getEntities(player, player.getBoundingBox().expandTowards(viewVector.scale(5.0)).inflate(1.0), ENTITY_PREDICATE); +- if (!entities.isEmpty()) { +- Vec3 eyePosition = player.getEyePosition(); ++ Vec3 vec3d = player.getViewVector(1.0F); ++ double d0 = 5.0D; ++ List list = level.getEntities((Entity) player, player.getBoundingBox().expandTowards(vec3d.scale(5.0D)).inflate(1.0D), BoatItem.ENTITY_PREDICATE); + +- for (Entity entity : entities) { +- AABB aABB = entity.getBoundingBox().inflate((double)entity.getPickRadius()); +- if (aABB.contains(eyePosition)) { +- return InteractionResultHolder.pass(itemInHand); ++ if (!list.isEmpty()) { ++ Vec3 vec3d1 = player.getEyePosition(); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ AABB axisalignedbb = entity.getBoundingBox().inflate((double) entity.getPickRadius()); ++ ++ if (axisalignedbb.contains(vec3d1)) { ++ return InteractionResultHolder.pass(itemstack); + } + } + } + +- if (playerPOVHitResult.getType() == HitResult.Type.BLOCK) { +- Boat boat = this.getBoat(level, playerPOVHitResult, itemInHand, player); +- boat.setVariant(this.type); +- boat.setYRot(player.getYRot()); +- if (!level.noCollision(boat, boat.getBoundingBox())) { +- return InteractionResultHolder.fail(itemInHand); ++ if (movingobjectpositionblock.getType() == HitResult.EnumMovingObjectType.BLOCK) { ++ // CraftBukkit start - Boat placement ++ org.bukkit.event.player.PlayerInteractEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(player, org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), itemstack, false, hand, movingobjectpositionblock.getLocation()); ++ ++ if (event.isCancelled()) { ++ return InteractionResultHolder.pass(itemstack); ++ } ++ // CraftBukkit end ++ Boat entityboat = this.getBoat(level, movingobjectpositionblock, itemstack, player); ++ ++ entityboat.setVariant(this.type); ++ entityboat.setYRot(player.getYRot()); ++ if (!level.noCollision(entityboat, entityboat.getBoundingBox())) { ++ return InteractionResultHolder.fail(itemstack); + } else { + if (!level.isClientSide) { +- level.addFreshEntity(boat); +- level.gameEvent(player, GameEvent.ENTITY_PLACE, playerPOVHitResult.getLocation()); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(level, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), player, entityboat, hand).isCancelled()) { ++ return InteractionResultHolder.fail(itemstack); ++ } ++ ++ if (!level.addFreshEntity(entityboat)) { ++ return InteractionResultHolder.pass(itemstack); ++ } ++ // CraftBukkit end ++ level.gameEvent((Entity) player, GameEvent.ENTITY_PLACE, movingobjectpositionblock.getLocation()); + if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + } + + player.awardStat(Stats.ITEM_USED.get(this)); +- return InteractionResultHolder.sidedSuccess(itemInHand, level.isClientSide()); ++ return InteractionResultHolder.sidedSuccess(itemstack, level.isClientSide()); + } + } else { +- return InteractionResultHolder.pass(itemInHand); ++ return InteractionResultHolder.pass(itemstack); + } + } + } + +- private Boat getBoat(Level level, HitResult hitResult, ItemStack itemStack, Player player) { +- Vec3 location = hitResult.getLocation(); +- Boat boat = (Boat)(this.hasChest ? new ChestBoat(level, location.x, location.y, location.z) : new Boat(level, location.x, location.y, location.z)); +- if (level instanceof ServerLevel serverLevel) { +- EntityType.createDefaultStackConfig(serverLevel, itemStack, player).accept(boat); ++ private Boat getBoat(Level world, HitResult movingobjectposition, ItemStack itemstack, Player entityhuman) { ++ Vec3 vec3d = movingobjectposition.getLocation(); ++ Boat object = this.hasChest ? new ChestBoat(world, vec3d.x, vec3d.y, vec3d.z) : new Boat(world, vec3d.x, vec3d.y, vec3d.z); // CraftBukkit - decompile error ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ ++ EntityType.createDefaultStackConfig(worldserver, itemstack, entityhuman).accept(object); + } + +- return boat; ++ return (Boat) object; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/BoneMealItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/BoneMealItem.java.patch new file mode 100644 index 0000000000..1d357a7708 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/BoneMealItem.java.patch @@ -0,0 +1,277 @@ +--- a/net/minecraft/world/item/BoneMealItem.java ++++ b/net/minecraft/world/item/BoneMealItem.java +@@ -4,7 +4,6 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.core.Holder; +-import net.minecraft.core.HolderSet; + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.core.registries.BuiltInRegistries; + import net.minecraft.server.level.ServerLevel; +@@ -17,13 +16,14 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.biome.Biome; + import net.minecraft.world.level.block.BaseCoralWallFanBlock; ++import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.BonemealableBlock; +-import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + + public class BoneMealItem extends Item { ++ + public static final int GRASS_SPREAD_WIDTH = 3; + public static final int GRASS_SPREAD_HEIGHT = 1; + public static final int GRASS_COUNT_MULTIPLIER = 3; +@@ -34,26 +34,34 @@ + + @Override + public InteractionResult useOn(UseOnContext context) { +- Level level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- BlockPos blockPos = clickedPos.relative(context.getClickedFace()); +- if (growCrop(context.getItemInHand(), level, clickedPos)) { +- if (!level.isClientSide) { +- context.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); +- level.levelEvent(1505, clickedPos, 0); ++ // CraftBukkit start - extract bonemeal application logic to separate, static method ++ return applyBonemeal(context); ++ } ++ ++ public static InteractionResult applyBonemeal(UseOnContext itemactioncontext) { ++ // CraftBukkit end ++ Level world = itemactioncontext.getLevel(); ++ BlockPos blockposition = itemactioncontext.getClickedPos(); ++ BlockPos blockposition1 = blockposition.relative(itemactioncontext.getClickedFace()); ++ ++ if (growCrop(itemactioncontext.getItemInHand(), world, blockposition)) { ++ if (!world.isClientSide) { ++ if (itemactioncontext.getPlayer() != null) itemactioncontext.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); // CraftBukkit - SPIGOT-7518 ++ world.levelEvent(1505, blockposition, 0); + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } else { +- BlockState blockState = level.getBlockState(clickedPos); +- boolean isFaceSturdy = blockState.isFaceSturdy(level, clickedPos, context.getClickedFace()); +- if (isFaceSturdy && growWaterPlant(context.getItemInHand(), level, blockPos, context.getClickedFace())) { +- if (!level.isClientSide) { +- context.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); +- level.levelEvent(1505, blockPos, 0); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ boolean flag = iblockdata.isFaceSturdy(world, blockposition, itemactioncontext.getClickedFace()); ++ ++ if (flag && growWaterPlant(itemactioncontext.getItemInHand(), world, blockposition1, itemactioncontext.getClickedFace())) { ++ if (!world.isClientSide) { ++ if (itemactioncontext.getPlayer() != null) itemactioncontext.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); // CraftBukkit - SPIGOT-7518 ++ world.levelEvent(1505, blockposition1, 0); + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } else { + return InteractionResult.PASS; + } +@@ -61,17 +69,23 @@ + } + + public static boolean growCrop(ItemStack stack, Level level, BlockPos pos) { +- BlockState blockState = level.getBlockState(pos); +- if (blockState.getBlock() instanceof BonemealableBlock bonemealableBlock && bonemealableBlock.isValidBonemealTarget(level, pos, blockState)) { +- if (level instanceof ServerLevel) { +- if (bonemealableBlock.isBonemealSuccess(level, level.random, pos, blockState)) { +- bonemealableBlock.performBonemeal((ServerLevel)level, level.random, pos, blockState); ++ IBlockData iblockdata = level.getBlockState(pos); ++ Block block = iblockdata.getBlock(); ++ ++ if (block instanceof BonemealableBlock) { ++ BonemealableBlock iblockfragileplantelement = (BonemealableBlock) block; ++ ++ if (iblockfragileplantelement.isValidBonemealTarget(level, pos, iblockdata)) { ++ if (level instanceof ServerLevel) { ++ if (iblockfragileplantelement.isBonemealSuccess(level, level.random, pos, iblockdata)) { ++ iblockfragileplantelement.performBonemeal((ServerLevel) level, level.random, pos, iblockdata); ++ } ++ ++ stack.shrink(1); + } + +- stack.shrink(1); ++ return true; + } +- +- return true; + } + + return false; +@@ -82,53 +96,64 @@ + if (!(level instanceof ServerLevel)) { + return true; + } else { +- RandomSource random = level.getRandom(); ++ RandomSource randomsource = level.getRandom(); ++ int i = 0; + +- label78: +- for (int i = 0; i < 128; i++) { +- BlockPos blockPos = pos; +- BlockState blockState = Blocks.SEAGRASS.defaultBlockState(); ++ while (i < 128) { ++ BlockPos blockposition1 = pos; ++ IBlockData iblockdata = Blocks.SEAGRASS.defaultBlockState(); ++ int j = 0; + +- for (int i1 = 0; i1 < i / 16; i1++) { +- blockPos = blockPos.offset(random.nextInt(3) - 1, (random.nextInt(3) - 1) * random.nextInt(3) / 2, random.nextInt(3) - 1); +- if (level.getBlockState(blockPos).isCollisionShapeFullBlock(level, blockPos)) { +- continue label78; +- } +- } ++ while (true) { ++ if (j < i / 16) { ++ blockposition1 = blockposition1.offset(randomsource.nextInt(3) - 1, (randomsource.nextInt(3) - 1) * randomsource.nextInt(3) / 2, randomsource.nextInt(3) - 1); ++ if (!level.getBlockState(blockposition1).isCollisionShapeFullBlock(level, blockposition1)) { ++ ++j; ++ continue; ++ } ++ } else { ++ Holder holder = level.getBiome(blockposition1); + +- Holder biome = level.getBiome(blockPos); +- if (biome.is(BiomeTags.PRODUCES_CORALS_FROM_BONEMEAL)) { +- if (i == 0 && clickedSide != null && clickedSide.getAxis().isHorizontal()) { +- blockState = BuiltInRegistries.BLOCK +- .getTag(BlockTags.WALL_CORALS) +- .flatMap(set -> set.getRandomElement(level.random)) +- .map(holder -> holder.value().defaultBlockState()) +- .orElse(blockState); +- if (blockState.hasProperty(BaseCoralWallFanBlock.FACING)) { +- blockState = blockState.setValue(BaseCoralWallFanBlock.FACING, clickedSide); ++ if (holder.is(BiomeTags.PRODUCES_CORALS_FROM_BONEMEAL)) { ++ if (i == 0 && clickedSide != null && clickedSide.getAxis().isHorizontal()) { ++ iblockdata = (IBlockData) BuiltInRegistries.BLOCK.getTag(BlockTags.WALL_CORALS).flatMap((holderset_named) -> { ++ return holderset_named.getRandomElement(level.random); ++ }).map((holder1) -> { ++ return ((Block) holder1.value()).defaultBlockState(); ++ }).orElse(iblockdata); ++ if (iblockdata.hasProperty(BaseCoralWallFanBlock.FACING)) { ++ iblockdata = (IBlockData) iblockdata.setValue(BaseCoralWallFanBlock.FACING, clickedSide); ++ } ++ } else if (randomsource.nextInt(4) == 0) { ++ iblockdata = (IBlockData) BuiltInRegistries.BLOCK.getTag(BlockTags.UNDERWATER_BONEMEALS).flatMap((holderset_named) -> { ++ return holderset_named.getRandomElement(level.random); ++ }).map((holder1) -> { ++ return ((Block) holder1.value()).defaultBlockState(); ++ }).orElse(iblockdata); ++ } + } +- } else if (random.nextInt(4) == 0) { +- blockState = BuiltInRegistries.BLOCK +- .getTag(BlockTags.UNDERWATER_BONEMEALS) +- .flatMap(set -> set.getRandomElement(level.random)) +- .map(holder -> holder.value().defaultBlockState()) +- .orElse(blockState); +- } +- } + +- if (blockState.is(BlockTags.WALL_CORALS, state -> state.hasProperty(BaseCoralWallFanBlock.FACING))) { +- for (int i2 = 0; !blockState.canSurvive(level, blockPos) && i2 < 4; i2++) { +- blockState = blockState.setValue(BaseCoralWallFanBlock.FACING, Direction.Plane.HORIZONTAL.getRandomDirection(random)); +- } +- } ++ if (iblockdata.is(BlockTags.WALL_CORALS, (blockbase_blockdata) -> { ++ return blockbase_blockdata.hasProperty(BaseCoralWallFanBlock.FACING); ++ })) { ++ for (int k = 0; !iblockdata.canSurvive(level, blockposition1) && k < 4; ++k) { ++ iblockdata = (IBlockData) iblockdata.setValue(BaseCoralWallFanBlock.FACING, Direction.Plane.HORIZONTAL.getRandomDirection(randomsource)); ++ } ++ } + +- if (blockState.canSurvive(level, blockPos)) { +- BlockState blockState1 = level.getBlockState(blockPos); +- if (blockState1.is(Blocks.WATER) && level.getFluidState(blockPos).getAmount() == 8) { +- level.setBlock(blockPos, blockState, 3); +- } else if (blockState1.is(Blocks.SEAGRASS) && random.nextInt(10) == 0) { +- ((BonemealableBlock)Blocks.SEAGRASS).performBonemeal((ServerLevel)level, random, blockPos, blockState1); ++ if (iblockdata.canSurvive(level, blockposition1)) { ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ if (iblockdata1.is(Blocks.WATER) && level.getFluidState(blockposition1).getAmount() == 8) { ++ level.setBlock(blockposition1, iblockdata, 3); ++ } else if (iblockdata1.is(Blocks.SEAGRASS) && randomsource.nextInt(10) == 0) { ++ ((BonemealableBlock) Blocks.SEAGRASS).performBonemeal((ServerLevel) level, randomsource, blockposition1, iblockdata1); ++ } ++ } + } ++ ++ ++i; ++ break; + } + } + +@@ -145,38 +170,42 @@ + data = 15; + } + +- BlockState blockState = level.getBlockState(pos); +- if (!blockState.isAir()) { +- double d = 0.5; ++ IBlockData iblockdata = level.getBlockState(pos); ++ ++ if (!iblockdata.isAir()) { ++ double d0 = 0.5D; + double d1; +- if (blockState.is(Blocks.WATER)) { ++ ++ if (iblockdata.is(Blocks.WATER)) { + data *= 3; +- d1 = 1.0; +- d = 3.0; +- } else if (blockState.isSolidRender(level, pos)) { ++ d1 = 1.0D; ++ d0 = 3.0D; ++ } else if (iblockdata.isSolidRender(level, pos)) { + pos = pos.above(); + data *= 3; +- d = 3.0; +- d1 = 1.0; ++ d0 = 3.0D; ++ d1 = 1.0D; + } else { +- d1 = blockState.getShape(level, pos).max(Direction.Axis.Y); ++ d1 = iblockdata.getShape(level, pos).max(Direction.Axis.Y); + } + +- level.addParticle(ParticleTypes.HAPPY_VILLAGER, (double)pos.getX() + 0.5, (double)pos.getY() + 0.5, (double)pos.getZ() + 0.5, 0.0, 0.0, 0.0); +- RandomSource random = level.getRandom(); ++ level.addParticle(ParticleTypes.HAPPY_VILLAGER, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, 0.0D, 0.0D, 0.0D); ++ RandomSource randomsource = level.getRandom(); + +- for (int i = 0; i < data; i++) { +- double d2 = random.nextGaussian() * 0.02; +- double d3 = random.nextGaussian() * 0.02; +- double d4 = random.nextGaussian() * 0.02; +- double d5 = 0.5 - d; +- double d6 = (double)pos.getX() + d5 + random.nextDouble() * d * 2.0; +- double d7 = (double)pos.getY() + random.nextDouble() * d1; +- double d8 = (double)pos.getZ() + d5 + random.nextDouble() * d * 2.0; ++ for (int j = 0; j < data; ++j) { ++ double d2 = randomsource.nextGaussian() * 0.02D; ++ double d3 = randomsource.nextGaussian() * 0.02D; ++ double d4 = randomsource.nextGaussian() * 0.02D; ++ double d5 = 0.5D - d0; ++ double d6 = (double) pos.getX() + d5 + randomsource.nextDouble() * d0 * 2.0D; ++ double d7 = (double) pos.getY() + randomsource.nextDouble() * d1; ++ double d8 = (double) pos.getZ() + d5 + randomsource.nextDouble() * d0 * 2.0D; ++ + if (!level.getBlockState(BlockPos.containing(d6, d7, d8).below()).isAir()) { + level.addParticle(ParticleTypes.HAPPY_VILLAGER, d6, d7, d8, d2, d3, d4); + } + } ++ + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/BowItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/BowItem.java.patch new file mode 100644 index 0000000000..4607fa28b2 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/BowItem.java.patch @@ -0,0 +1,200 @@ +--- a/net/minecraft/world/item/BowItem.java ++++ b/net/minecraft/world/item/BowItem.java +@@ -4,7 +4,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.player.Player; +@@ -13,7 +13,8 @@ + import net.minecraft.world.item.enchantment.Enchantments; + import net.minecraft.world.level.Level; + +-public class BowItem extends ProjectileWeaponItem implements Vanishable { ++public class BowItem extends ProjectileWeaponItem implements ItemVanishable { ++ + public static final int MAX_DRAW_DURATION = 20; + public static final int DEFAULT_RANGE = 15; + +@@ -23,79 +24,97 @@ + + @Override + public void releaseUsing(ItemStack stack, Level level, LivingEntity entityLiving, int timeLeft) { +- if (entityLiving instanceof Player player) { +- boolean flag = player.getAbilities().instabuild || EnchantmentHelper.getItemEnchantmentLevel(Enchantments.INFINITY_ARROWS, stack) > 0; +- ItemStack projectile = player.getProjectile(stack); +- if (!projectile.isEmpty() || flag) { +- if (projectile.isEmpty()) { +- projectile = new ItemStack(Items.ARROW); ++ if (entityLiving instanceof Player) { ++ Player entityhuman = (Player) entityLiving; ++ boolean flag = entityhuman.getAbilities().instabuild || EnchantmentHelper.getItemEnchantmentLevel(Enchantments.INFINITY_ARROWS, stack) > 0; ++ ItemStack itemstack1 = entityhuman.getProjectile(stack); ++ ++ if (!itemstack1.isEmpty() || flag) { ++ if (itemstack1.isEmpty()) { ++ itemstack1 = new ItemStack(Items.ARROW); + } + +- int i = this.getUseDuration(stack) - timeLeft; +- float powerForTime = getPowerForTime(i); +- if (!((double)powerForTime < 0.1)) { +- boolean flag1 = flag && projectile.is(Items.ARROW); ++ int j = this.getUseDuration(stack) - timeLeft; ++ float f = getPowerForTime(j); ++ ++ if ((double) f >= 0.1D) { ++ boolean flag1 = flag && itemstack1.is(Items.ARROW); ++ + if (!level.isClientSide) { +- ArrowItem arrowItem = (ArrowItem)(projectile.getItem() instanceof ArrowItem ? projectile.getItem() : Items.ARROW); +- AbstractArrow abstractArrow = arrowItem.createArrow(level, projectile, player); +- abstractArrow.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, powerForTime * 3.0F, 1.0F); +- if (powerForTime == 1.0F) { +- abstractArrow.setCritArrow(true); ++ ArrowItem itemarrow = (ArrowItem) (itemstack1.getItem() instanceof ArrowItem ? itemstack1.getItem() : Items.ARROW); ++ AbstractArrow entityarrow = itemarrow.createArrow(level, itemstack1, entityhuman); ++ ++ entityarrow.shootFromRotation(entityhuman, entityhuman.getXRot(), entityhuman.getYRot(), 0.0F, f * 3.0F, 1.0F); ++ if (f == 1.0F) { ++ entityarrow.setCritArrow(true); + } + +- int itemEnchantmentLevel = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.POWER_ARROWS, stack); +- if (itemEnchantmentLevel > 0) { +- abstractArrow.setBaseDamage(abstractArrow.getBaseDamage() + (double)itemEnchantmentLevel * 0.5 + 0.5); ++ int k = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.POWER_ARROWS, stack); ++ ++ if (k > 0) { ++ entityarrow.setBaseDamage(entityarrow.getBaseDamage() + (double) k * 0.5D + 0.5D); + } + +- int itemEnchantmentLevel1 = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.PUNCH_ARROWS, stack); +- if (itemEnchantmentLevel1 > 0) { +- abstractArrow.setKnockback(itemEnchantmentLevel1); ++ int l = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.PUNCH_ARROWS, stack); ++ ++ if (l > 0) { ++ entityarrow.setKnockback(l); + } + + if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.FLAMING_ARROWS, stack) > 0) { +- abstractArrow.setSecondsOnFire(100); ++ entityarrow.setSecondsOnFire(100); + } ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(entityhuman, stack, itemstack1, entityarrow, entityhuman.getUsedItemHand(), f, !flag1); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ flag1 = !event.shouldConsumeItem(); ++ // CraftBukkit end + +- stack.hurtAndBreak(1, player, player1 -> player1.broadcastBreakEvent(player.getUsedItemHand())); +- if (flag1 || player.getAbilities().instabuild && (projectile.is(Items.SPECTRAL_ARROW) || projectile.is(Items.TIPPED_ARROW))) { +- abstractArrow.pickup = AbstractArrow.Pickup.CREATIVE_ONLY; ++ stack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(entityhuman.getUsedItemHand()); ++ }); ++ if (flag1 || entityhuman.getAbilities().instabuild && (itemstack1.is(Items.SPECTRAL_ARROW) || itemstack1.is(Items.TIPPED_ARROW))) { ++ entityarrow.pickup = AbstractArrow.Pickup.CREATIVE_ONLY; + } + +- level.addFreshEntity(abstractArrow); ++ // CraftBukkit start ++ if (event.getProjectile() == entityarrow.getBukkitEntity()) { ++ if (!level.addFreshEntity(entityarrow)) { ++ if (entityhuman instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } ++ return; ++ } ++ } ++ // CraftBukkit end + } + +- level.playSound( +- null, +- player.getX(), +- player.getY(), +- player.getZ(), +- SoundEvents.ARROW_SHOOT, +- SoundSource.PLAYERS, +- 1.0F, +- 1.0F / (level.getRandom().nextFloat() * 0.4F + 1.2F) + powerForTime * 0.5F +- ); +- if (!flag1 && !player.getAbilities().instabuild) { +- projectile.shrink(1); +- if (projectile.isEmpty()) { +- player.getInventory().removeItem(projectile); ++ level.playSound((Player) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEvents.ARROW_SHOOT, SoundSource.PLAYERS, 1.0F, 1.0F / (level.getRandom().nextFloat() * 0.4F + 1.2F) + f * 0.5F); ++ if (!flag1 && !entityhuman.getAbilities().instabuild) { ++ itemstack1.shrink(1); ++ if (itemstack1.isEmpty()) { ++ entityhuman.getInventory().removeItem(itemstack1); + } + } + +- player.awardStat(Stats.ITEM_USED.get(this)); ++ entityhuman.awardStat(Stats.ITEM_USED.get(this)); + } + } + } + } + + public static float getPowerForTime(int charge) { +- float f = (float)charge / 20.0F; +- float var2 = (f * f + f * 2.0F) / 3.0F; +- if (var2 > 1.0F) { +- var2 = 1.0F; ++ float f = (float) charge / 20.0F; ++ ++ f = (f * f + f * 2.0F) / 3.0F; ++ if (f > 1.0F) { ++ f = 1.0F; + } + +- return var2; ++ return f; + } + + @Override +@@ -104,25 +123,26 @@ + } + + @Override +- public UseAnim getUseAnimation(ItemStack stack) { +- return UseAnim.BOW; ++ public EnumAnimation getUseAnimation(ItemStack stack) { ++ return EnumAnimation.BOW; + } + + @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- boolean flag = !player.getProjectile(itemInHand).isEmpty(); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ boolean flag = !player.getProjectile(itemstack).isEmpty(); ++ + if (!player.getAbilities().instabuild && !flag) { +- return InteractionResultHolder.fail(itemInHand); ++ return InteractionResultHolder.fail(itemstack); + } else { + player.startUsingItem(hand); +- return InteractionResultHolder.consume(itemInHand); ++ return InteractionResultHolder.consume(itemstack); + } + } + + @Override + public Predicate getAllSupportedProjectiles() { +- return ARROW_ONLY; ++ return BowItem.ARROW_ONLY; + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/BucketItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/BucketItem.java.patch new file mode 100644 index 0000000000..fad620d749 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/BucketItem.java.patch @@ -0,0 +1,310 @@ +--- a/net/minecraft/world/item/BucketItem.java ++++ b/net/minecraft/world/item/BucketItem.java +@@ -5,14 +5,17 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.core.particles.ParticleTypes; ++import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; + import net.minecraft.tags.FluidTags; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.ClipContext; + import net.minecraft.world.level.Level; +@@ -20,70 +23,100 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.BucketPickup; + import net.minecraft.world.level.block.LiquidBlockContainer; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.FlowingFluid; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.HitResult; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.DummyGeneratorAccess; ++import org.bukkit.event.player.PlayerBucketEmptyEvent; ++import org.bukkit.event.player.PlayerBucketFillEvent; ++// CraftBukkit end + + public class BucketItem extends Item implements DispensibleContainerItem { +- private final Fluid content; + ++ public final Fluid content; ++ + public BucketItem(Fluid content, Item.Properties properties) { + super(properties); + this.content = content; + } + + @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- BlockHitResult playerPOVHitResult = getPlayerPOVHitResult( +- level, player, this.content == Fluids.EMPTY ? ClipContext.Fluid.SOURCE_ONLY : ClipContext.Fluid.NONE +- ); +- if (playerPOVHitResult.getType() == HitResult.Type.MISS) { +- return InteractionResultHolder.pass(itemInHand); +- } else if (playerPOVHitResult.getType() != HitResult.Type.BLOCK) { +- return InteractionResultHolder.pass(itemInHand); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ BlockHitResult movingobjectpositionblock = getPlayerPOVHitResult(level, player, this.content == Fluids.EMPTY ? ClipContext.Fluid.SOURCE_ONLY : ClipContext.Fluid.NONE); ++ ++ if (movingobjectpositionblock.getType() == HitResult.EnumMovingObjectType.MISS) { ++ return InteractionResultHolder.pass(itemstack); ++ } else if (movingobjectpositionblock.getType() != HitResult.EnumMovingObjectType.BLOCK) { ++ return InteractionResultHolder.pass(itemstack); + } else { +- BlockPos blockPos = playerPOVHitResult.getBlockPos(); +- Direction direction = playerPOVHitResult.getDirection(); +- BlockPos blockPos1 = blockPos.relative(direction); +- if (!level.mayInteract(player, blockPos) || !player.mayUseItemAt(blockPos1, direction, itemInHand)) { +- return InteractionResultHolder.fail(itemInHand); +- } else if (this.content == Fluids.EMPTY) { +- BlockState blockState = level.getBlockState(blockPos); +- if (blockState.getBlock() instanceof BucketPickup bucketPickup) { +- ItemStack itemStack = bucketPickup.pickupBlock(player, level, blockPos, blockState); +- if (!itemStack.isEmpty()) { +- player.awardStat(Stats.ITEM_USED.get(this)); +- bucketPickup.getPickupSound().ifPresent(soundEvent -> player.playSound(soundEvent, 1.0F, 1.0F)); +- level.gameEvent(player, GameEvent.FLUID_PICKUP, blockPos); +- ItemStack itemStack1 = ItemUtils.createFilledResult(itemInHand, player, itemStack); +- if (!level.isClientSide) { +- CriteriaTriggers.FILLED_BUCKET.trigger((ServerPlayer)player, itemStack); ++ BlockPos blockposition = movingobjectpositionblock.getBlockPos(); ++ Direction enumdirection = movingobjectpositionblock.getDirection(); ++ BlockPos blockposition1 = blockposition.relative(enumdirection); ++ ++ if (level.mayInteract(player, blockposition) && player.mayUseItemAt(blockposition1, enumdirection, itemstack)) { ++ IBlockData iblockdata; ++ ++ if (this.content == Fluids.EMPTY) { ++ iblockdata = level.getBlockState(blockposition); ++ Block block = iblockdata.getBlock(); ++ ++ if (block instanceof BucketPickup) { ++ BucketPickup ifluidsource = (BucketPickup) block; ++ // CraftBukkit start ++ ItemStack dummyFluid = ifluidsource.pickupBlock(player, DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); ++ if (dummyFluid.isEmpty()) return InteractionResultHolder.fail(itemstack); // Don't fire event if the bucket won't be filled. ++ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) level, player, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.getItem(), hand); ++ ++ if (event.isCancelled()) { ++ ((ServerPlayer) player).connection.send(new ClientboundBlockUpdatePacket(level, blockposition)); // SPIGOT-5163 (see PlayerInteractManager) ++ ((ServerPlayer) player).getBukkitEntity().updateInventory(); // SPIGOT-4541 ++ return InteractionResultHolder.fail(itemstack); + } ++ // CraftBukkit end ++ ItemStack itemstack1 = ifluidsource.pickupBlock(player, level, blockposition, iblockdata); + +- return InteractionResultHolder.sidedSuccess(itemStack1, level.isClientSide()); +- } +- } ++ if (!itemstack1.isEmpty()) { ++ player.awardStat(Stats.ITEM_USED.get(this)); ++ ifluidsource.getPickupSound().ifPresent((soundeffect) -> { ++ player.playSound(soundeffect, 1.0F, 1.0F); ++ }); ++ level.gameEvent((Entity) player, GameEvent.FLUID_PICKUP, blockposition); ++ ItemStack itemstack2 = ItemUtils.createFilledResult(itemstack, player, CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit + +- return InteractionResultHolder.fail(itemInHand); +- } else { +- BlockState blockState = level.getBlockState(blockPos); +- BlockPos blockPos2 = blockState.getBlock() instanceof LiquidBlockContainer && this.content == Fluids.WATER ? blockPos : blockPos1; +- if (this.emptyContents(player, level, blockPos2, playerPOVHitResult)) { +- this.checkExtraContent(player, level, itemInHand, blockPos2); +- if (player instanceof ServerPlayer) { +- CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer)player, blockPos2, itemInHand); ++ if (!level.isClientSide) { ++ CriteriaTriggers.FILLED_BUCKET.trigger((ServerPlayer) player, itemstack1); ++ } ++ ++ return InteractionResultHolder.sidedSuccess(itemstack2, level.isClientSide()); ++ } + } + +- player.awardStat(Stats.ITEM_USED.get(this)); +- return InteractionResultHolder.sidedSuccess(getEmptySuccessItem(itemInHand, player), level.isClientSide()); ++ return InteractionResultHolder.fail(itemstack); + } else { +- return InteractionResultHolder.fail(itemInHand); ++ iblockdata = level.getBlockState(blockposition); ++ BlockPos blockposition2 = iblockdata.getBlock() instanceof LiquidBlockContainer && this.content == Fluids.WATER ? blockposition : blockposition1; ++ ++ if (this.emptyContents(player, level, blockposition2, movingobjectpositionblock, movingobjectpositionblock.getDirection(), blockposition, itemstack, hand)) { // CraftBukkit ++ this.checkExtraContent(player, level, itemstack, blockposition2); ++ if (player instanceof ServerPlayer) { ++ CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) player, blockposition2, itemstack); ++ } ++ ++ player.awardStat(Stats.ITEM_USED.get(this)); ++ return InteractionResultHolder.sidedSuccess(getEmptySuccessItem(itemstack, player), level.isClientSide()); ++ } else { ++ return InteractionResultHolder.fail(itemstack); ++ } + } ++ } else { ++ return InteractionResultHolder.fail(itemstack); + } + } + } +@@ -93,67 +126,95 @@ + } + + @Override +- public void checkExtraContent(@Nullable Player player, Level level, ItemStack containerStack, BlockPos pos) { +- } ++ public void checkExtraContent(@Nullable Player player, Level level, ItemStack containerStack, BlockPos pos) {} + + @Override + public boolean emptyContents(@Nullable Player player, Level level, BlockPos pos, @Nullable BlockHitResult result) { +- if (!(this.content instanceof FlowingFluid flowingFluid)) { ++ // CraftBukkit start ++ return emptyContents(player, level, pos, result, null, null, null, EnumHand.MAIN_HAND); ++ } ++ ++ public boolean emptyContents(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack, EnumHand enumhand) { ++ // CraftBukkit end ++ Fluid fluidtype = this.content; ++ ++ if (!(fluidtype instanceof FlowingFluid)) { + return false; + } else { ++ FlowingFluid fluidtypeflowing; ++ IBlockData iblockdata; + Block block; +- boolean canBeReplaced; +- BlockState blockState; +- boolean var10000; +- label82: { +- blockState = level.getBlockState(pos); +- block = blockState.getBlock(); +- canBeReplaced = blockState.canBeReplaced(this.content); +- label70: +- if (!blockState.isAir() && !canBeReplaced) { +- if (block instanceof LiquidBlockContainer liquidBlockContainer +- && liquidBlockContainer.canPlaceLiquid(player, level, pos, blockState, this.content)) { ++ boolean flag; ++ LiquidBlockContainer ifluidcontainer; ++ boolean flag1; ++ label70: ++ { ++ fluidtypeflowing = (FlowingFluid) fluidtype; ++ iblockdata = world.getBlockState(blockposition); ++ block = iblockdata.getBlock(); ++ flag = iblockdata.canBeReplaced(this.content); ++ if (!iblockdata.isAir() && !flag) { ++ label67: ++ { ++ if (block instanceof LiquidBlockContainer) { ++ ifluidcontainer = (LiquidBlockContainer) block; ++ if (ifluidcontainer.canPlaceLiquid(entityhuman, world, blockposition, iblockdata, this.content)) { ++ break label67; ++ } ++ } ++ ++ flag1 = false; + break label70; + } +- +- var10000 = false; +- break label82; + } + +- var10000 = true; ++ flag1 = true; + } + +- boolean flag = var10000; +- if (!flag) { +- return result != null && this.emptyContents(player, level, result.getBlockPos().relative(result.getDirection()), null); +- } else if (level.dimensionType().ultraWarm() && this.content.is(FluidTags.WATER)) { +- int x = pos.getX(); +- int y = pos.getY(); +- int z = pos.getZ(); +- level.playSound( +- player, pos, SoundEvents.FIRE_EXTINGUISH, SoundSource.BLOCKS, 0.5F, 2.6F + (level.random.nextFloat() - level.random.nextFloat()) * 0.8F +- ); ++ boolean flag2 = flag1; + +- for (int i = 0; i < 8; i++) { +- level.addParticle(ParticleTypes.LARGE_SMOKE, (double)x + Math.random(), (double)y + Math.random(), (double)z + Math.random(), 0.0, 0.0, 0.0); ++ // CraftBukkit start ++ if (flag2 && entityhuman != null) { ++ PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((ServerLevel) world, entityhuman, blockposition, clicked, enumdirection, itemstack, enumhand); ++ if (event.isCancelled()) { ++ ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-4238: needed when looking through entity ++ ((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 ++ return false; + } ++ } ++ // CraftBukkit end ++ if (!flag2) { ++ return movingobjectpositionblock != null && this.emptyContents(entityhuman, world, movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()), (BlockHitResult) null, enumdirection, clicked, itemstack, enumhand); // CraftBukkit ++ } else if (world.dimensionType().ultraWarm() && this.content.is(FluidTags.WATER)) { ++ int i = blockposition.getX(); ++ int j = blockposition.getY(); ++ int k = blockposition.getZ(); + ++ world.playSound(entityhuman, blockposition, SoundEvents.FIRE_EXTINGUISH, SoundSource.BLOCKS, 0.5F, 2.6F + (world.random.nextFloat() - world.random.nextFloat()) * 0.8F); ++ ++ for (int l = 0; l < 8; ++l) { ++ world.addParticle(ParticleTypes.LARGE_SMOKE, (double) i + Math.random(), (double) j + Math.random(), (double) k + Math.random(), 0.0D, 0.0D, 0.0D); ++ } ++ + return true; + } else { +- if (block instanceof LiquidBlockContainer liquidBlockContainer && this.content == Fluids.WATER) { +- liquidBlockContainer.placeLiquid(level, pos, blockState, flowingFluid.getSource(false)); +- this.playEmptySound(player, level, pos); +- return true; ++ if (block instanceof LiquidBlockContainer) { ++ ifluidcontainer = (LiquidBlockContainer) block; ++ if (this.content == Fluids.WATER) { ++ ifluidcontainer.placeLiquid(world, blockposition, iblockdata, fluidtypeflowing.getSource(false)); ++ this.playEmptySound(entityhuman, world, blockposition); ++ return true; ++ } + } + +- if (!level.isClientSide && canBeReplaced && !blockState.liquid()) { +- level.destroyBlock(pos, true); ++ if (!world.isClientSide && flag && !iblockdata.liquid()) { ++ world.destroyBlock(blockposition, true); + } + +- if (!level.setBlock(pos, this.content.defaultFluidState().createLegacyBlock(), 11) && !blockState.getFluidState().isSource()) { ++ if (!world.setBlock(blockposition, this.content.defaultFluidState().createLegacyBlock(), 11) && !iblockdata.getFluidState().isSource()) { + return false; + } else { +- this.playEmptySound(player, level, pos); ++ this.playEmptySound(entityhuman, world, blockposition); + return true; + } + } +@@ -161,8 +222,9 @@ + } + + protected void playEmptySound(@Nullable Player player, LevelAccessor level, BlockPos pos) { +- SoundEvent soundEvent = this.content.is(FluidTags.LAVA) ? SoundEvents.BUCKET_EMPTY_LAVA : SoundEvents.BUCKET_EMPTY; +- level.playSound(player, pos, soundEvent, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent(player, GameEvent.FLUID_PLACE, pos); ++ SoundEvent soundeffect = this.content.is(FluidTags.LAVA) ? SoundEvents.BUCKET_EMPTY_LAVA : SoundEvents.BUCKET_EMPTY; ++ ++ level.playSound(player, pos, soundeffect, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.gameEvent((Entity) player, GameEvent.FLUID_PLACE, pos); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/ChorusFruitItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/ChorusFruitItem.java.patch new file mode 100644 index 0000000000..8f1c09e300 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/ChorusFruitItem.java.patch @@ -0,0 +1,95 @@ +--- a/net/minecraft/world/item/ChorusFruitItem.java ++++ b/net/minecraft/world/item/ChorusFruitItem.java +@@ -5,6 +5,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.util.Mth; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.animal.Fox; + import net.minecraft.world.entity.player.Player; +@@ -13,50 +14,62 @@ + import net.minecraft.world.phys.Vec3; + + public class ChorusFruitItem extends Item { ++ + public ChorusFruitItem(Item.Properties properties) { + super(properties); + } + + @Override + public ItemStack finishUsingItem(ItemStack stack, Level level, LivingEntity entityLiving) { +- ItemStack itemStack = super.finishUsingItem(stack, level, entityLiving); ++ ItemStack itemstack1 = super.finishUsingItem(stack, level, entityLiving); ++ + if (!level.isClientSide) { +- for (int i = 0; i < 16; i++) { +- double d = entityLiving.getX() + (entityLiving.getRandom().nextDouble() - 0.5) * 16.0; +- double d1 = Mth.clamp( +- entityLiving.getY() + (double)(entityLiving.getRandom().nextInt(16) - 8), +- (double)level.getMinBuildHeight(), +- (double)(level.getMinBuildHeight() + ((ServerLevel)level).getLogicalHeight() - 1) +- ); +- double d2 = entityLiving.getZ() + (entityLiving.getRandom().nextDouble() - 0.5) * 16.0; ++ for (int i = 0; i < 16; ++i) { ++ double d0 = entityLiving.getX() + (entityLiving.getRandom().nextDouble() - 0.5D) * 16.0D; ++ double d1 = Mth.clamp(entityLiving.getY() + (double) (entityLiving.getRandom().nextInt(16) - 8), (double) level.getMinBuildHeight(), (double) (level.getMinBuildHeight() + ((ServerLevel) level).getLogicalHeight() - 1)); ++ double d2 = entityLiving.getZ() + (entityLiving.getRandom().nextDouble() - 0.5D) * 16.0D; ++ + if (entityLiving.isPassenger()) { + entityLiving.stopRiding(); + } + +- Vec3 vec3 = entityLiving.position(); +- if (entityLiving.randomTeleport(d, d1, d2, true)) { +- level.gameEvent(GameEvent.TELEPORT, vec3, GameEvent.Context.of(entityLiving)); +- SoundSource soundSource; +- SoundEvent soundEvent; ++ Vec3 vec3d = entityLiving.position(); ++ ++ // CraftBukkit start - handle canceled status of teleport event ++ java.util.Optional status = entityLiving.randomTeleport(d0, d1, d2, true, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.CHORUS_FRUIT); ++ ++ if (!status.isPresent()) { ++ // teleport event was canceled, no more tries ++ break; ++ } ++ ++ if (status.get()) { ++ // CraftBukkit end ++ level.gameEvent(GameEvent.TELEPORT, vec3d, GameEvent.Context.of((Entity) entityLiving)); ++ SoundEvent soundeffect; ++ SoundSource soundcategory; ++ + if (entityLiving instanceof Fox) { +- soundEvent = SoundEvents.FOX_TELEPORT; +- soundSource = SoundSource.NEUTRAL; ++ soundeffect = SoundEvents.FOX_TELEPORT; ++ soundcategory = SoundSource.NEUTRAL; + } else { +- soundEvent = SoundEvents.CHORUS_FRUIT_TELEPORT; +- soundSource = SoundSource.PLAYERS; ++ soundeffect = SoundEvents.CHORUS_FRUIT_TELEPORT; ++ soundcategory = SoundSource.PLAYERS; + } + +- level.playSound(null, entityLiving.getX(), entityLiving.getY(), entityLiving.getZ(), soundEvent, soundSource); ++ level.playSound((Player) null, entityLiving.getX(), entityLiving.getY(), entityLiving.getZ(), soundeffect, soundcategory); + entityLiving.resetFallDistance(); + break; + } + } + +- if (entityLiving instanceof Player player) { +- player.getCooldowns().addCooldown(this, 20); ++ if (entityLiving instanceof Player) { ++ Player entityhuman = (Player) entityLiving; ++ ++ entityhuman.getCooldowns().addCooldown(this, 20); + } + } + +- return itemStack; ++ return itemstack1; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/CrossbowItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/CrossbowItem.java.patch new file mode 100644 index 0000000000..482db78cd4 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/CrossbowItem.java.patch @@ -0,0 +1,526 @@ +--- a/net/minecraft/world/item/CrossbowItem.java ++++ b/net/minecraft/world/item/CrossbowItem.java +@@ -16,8 +16,9 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.monster.CrossbowAttackMob; + import net.minecraft.world.entity.player.Player; +@@ -31,7 +32,8 @@ + import org.joml.Quaternionf; + import org.joml.Vector3f; + +-public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { ++public class CrossbowItem extends ProjectileWeaponItem implements ItemVanishable { ++ + private static final String TAG_CHARGED = "Charged"; + private static final String TAG_CHARGED_PROJECTILES = "ChargedProjectiles"; + private static final int MAX_CHARGE_DURATION = 25; +@@ -49,31 +51,32 @@ + + @Override + public Predicate getSupportedHeldProjectiles() { +- return ARROW_OR_FIREWORK; ++ return CrossbowItem.ARROW_OR_FIREWORK; + } + + @Override + public Predicate getAllSupportedProjectiles() { +- return ARROW_ONLY; ++ return CrossbowItem.ARROW_ONLY; + } + + @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (isCharged(itemInHand)) { +- performShooting(level, player, hand, itemInHand, getShootingPower(itemInHand), 1.0F); +- setCharged(itemInHand, false); +- return InteractionResultHolder.consume(itemInHand); +- } else if (!player.getProjectile(itemInHand).isEmpty()) { +- if (!isCharged(itemInHand)) { ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (isCharged(itemstack)) { ++ performShooting(level, player, hand, itemstack, getShootingPower(itemstack), 1.0F); ++ setCharged(itemstack, false); ++ return InteractionResultHolder.consume(itemstack); ++ } else if (!player.getProjectile(itemstack).isEmpty()) { ++ if (!isCharged(itemstack)) { + this.startSoundPlayed = false; + this.midLoadSoundPlayed = false; + player.startUsingItem(hand); + } + +- return InteractionResultHolder.consume(itemInHand); ++ return InteractionResultHolder.consume(itemstack); + } else { +- return InteractionResultHolder.fail(itemInHand); ++ return InteractionResultHolder.fail(itemstack); + } + } + +@@ -83,42 +86,36 @@ + + @Override + public void releaseUsing(ItemStack stack, Level level, LivingEntity entityLiving, int timeLeft) { +- int i = this.getUseDuration(stack) - timeLeft; +- float powerForTime = getPowerForTime(i, stack); +- if (powerForTime >= 1.0F && !isCharged(stack) && tryLoadProjectiles(entityLiving, stack)) { ++ int j = this.getUseDuration(stack) - timeLeft; ++ float f = getPowerForTime(j, stack); ++ ++ if (f >= 1.0F && !isCharged(stack) && tryLoadProjectiles(entityLiving, stack)) { + setCharged(stack, true); +- SoundSource soundSource = entityLiving instanceof Player ? SoundSource.PLAYERS : SoundSource.HOSTILE; +- level.playSound( +- null, +- entityLiving.getX(), +- entityLiving.getY(), +- entityLiving.getZ(), +- SoundEvents.CROSSBOW_LOADING_END, +- soundSource, +- 1.0F, +- 1.0F / (level.getRandom().nextFloat() * 0.5F + 1.0F) + 0.2F +- ); ++ SoundSource soundcategory = entityLiving instanceof Player ? SoundSource.PLAYERS : SoundSource.HOSTILE; ++ ++ level.playSound((Player) null, entityLiving.getX(), entityLiving.getY(), entityLiving.getZ(), SoundEvents.CROSSBOW_LOADING_END, soundcategory, 1.0F, 1.0F / (level.getRandom().nextFloat() * 0.5F + 1.0F) + 0.2F); + } ++ + } + + private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack crossbowStack) { +- int itemEnchantmentLevel = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.MULTISHOT, crossbowStack); +- int i = itemEnchantmentLevel == 0 ? 1 : 3; +- boolean flag = shooter instanceof Player && ((Player)shooter).getAbilities().instabuild; +- ItemStack projectile = shooter.getProjectile(crossbowStack); +- ItemStack itemStack = projectile.copy(); ++ int i = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.MULTISHOT, crossbowStack); ++ int j = i == 0 ? 1 : 3; ++ boolean flag = shooter instanceof Player && ((Player) shooter).getAbilities().instabuild; ++ ItemStack itemstack1 = shooter.getProjectile(crossbowStack); ++ ItemStack itemstack2 = itemstack1.copy(); + +- for (int i1 = 0; i1 < i; i1++) { +- if (i1 > 0) { +- projectile = itemStack.copy(); ++ for (int k = 0; k < j; ++k) { ++ if (k > 0) { ++ itemstack1 = itemstack2.copy(); + } + +- if (projectile.isEmpty() && flag) { +- projectile = new ItemStack(Items.ARROW); +- itemStack = projectile.copy(); ++ if (itemstack1.isEmpty() && flag) { ++ itemstack1 = new ItemStack(Items.ARROW); ++ itemstack2 = itemstack1.copy(); + } + +- if (!loadProjectile(shooter, crossbowStack, projectile, i1 > 0, flag)) { ++ if (!loadProjectile(shooter, crossbowStack, itemstack1, k > 0, flag)) { + return false; + } + } +@@ -130,56 +127,64 @@ + if (ammoStack.isEmpty()) { + return false; + } else { +- boolean flag = isCreative && ammoStack.getItem() instanceof ArrowItem; +- ItemStack itemStack; +- if (!flag && !isCreative && !hasAmmo) { +- itemStack = ammoStack.split(1); ++ boolean flag2 = isCreative && ammoStack.getItem() instanceof ArrowItem; ++ ItemStack itemstack2; ++ ++ if (!flag2 && !isCreative && !hasAmmo) { ++ itemstack2 = ammoStack.split(1); + if (ammoStack.isEmpty() && shooter instanceof Player) { +- ((Player)shooter).getInventory().removeItem(ammoStack); ++ ((Player) shooter).getInventory().removeItem(ammoStack); + } + } else { +- itemStack = ammoStack.copy(); ++ itemstack2 = ammoStack.copy(); + } + +- addChargedProjectile(crossbowStack, itemStack); ++ addChargedProjectile(crossbowStack, itemstack2); + return true; + } + } + + public static boolean isCharged(ItemStack crossbowStack) { +- CompoundTag tag = crossbowStack.getTag(); +- return tag != null && tag.getBoolean("Charged"); ++ CompoundTag nbttagcompound = crossbowStack.getTag(); ++ ++ return nbttagcompound != null && nbttagcompound.getBoolean("Charged"); + } + + public static void setCharged(ItemStack crossbowStack, boolean isCharged) { +- CompoundTag tag = crossbowStack.getOrCreateTag(); +- tag.putBoolean("Charged", isCharged); ++ CompoundTag nbttagcompound = crossbowStack.getOrCreateTag(); ++ ++ nbttagcompound.putBoolean("Charged", isCharged); + } + + private static void addChargedProjectile(ItemStack crossbowStack, ItemStack ammoStack) { +- CompoundTag tag = crossbowStack.getOrCreateTag(); +- ListTag list; +- if (tag.contains("ChargedProjectiles", 9)) { +- list = tag.getList("ChargedProjectiles", 10); ++ CompoundTag nbttagcompound = crossbowStack.getOrCreateTag(); ++ ListTag nbttaglist; ++ ++ if (nbttagcompound.contains("ChargedProjectiles", 9)) { ++ nbttaglist = nbttagcompound.getList("ChargedProjectiles", 10); + } else { +- list = new ListTag(); ++ nbttaglist = new ListTag(); + } + +- CompoundTag compoundTag = new CompoundTag(); +- ammoStack.save(compoundTag); +- list.add(compoundTag); +- tag.put("ChargedProjectiles", list); ++ CompoundTag nbttagcompound1 = new CompoundTag(); ++ ++ ammoStack.save(nbttagcompound1); ++ nbttaglist.add(nbttagcompound1); ++ nbttagcompound.put("ChargedProjectiles", nbttaglist); + } + + private static List getChargedProjectiles(ItemStack crossbowStack) { + List list = Lists.newArrayList(); +- CompoundTag tag = crossbowStack.getTag(); +- if (tag != null && tag.contains("ChargedProjectiles", 9)) { +- ListTag list1 = tag.getList("ChargedProjectiles", 10); +- if (list1 != null) { +- for (int i = 0; i < list1.size(); i++) { +- CompoundTag compound = list1.getCompound(i); +- list.add(ItemStack.of(compound)); ++ CompoundTag nbttagcompound = crossbowStack.getTag(); ++ ++ if (nbttagcompound != null && nbttagcompound.contains("ChargedProjectiles", 9)) { ++ ListTag nbttaglist = nbttagcompound.getList("ChargedProjectiles", 10); ++ ++ if (nbttaglist != null) { ++ for (int i = 0; i < nbttaglist.size(); ++i) { ++ CompoundTag nbttagcompound1 = nbttaglist.getCompound(i); ++ ++ list.add(ItemStack.of(nbttagcompound1)); + } + } + } +@@ -188,90 +193,108 @@ + } + + private static void clearChargedProjectiles(ItemStack crossbowStack) { +- CompoundTag tag = crossbowStack.getTag(); +- if (tag != null) { +- ListTag list = tag.getList("ChargedProjectiles", 9); +- list.clear(); +- tag.put("ChargedProjectiles", list); ++ CompoundTag nbttagcompound = crossbowStack.getTag(); ++ ++ if (nbttagcompound != null) { ++ ListTag nbttaglist = nbttagcompound.getList("ChargedProjectiles", 9); ++ ++ nbttaglist.clear(); ++ nbttagcompound.put("ChargedProjectiles", nbttaglist); + } ++ + } + + public static boolean containsChargedProjectile(ItemStack crossbowStack, Item ammoItem) { +- return getChargedProjectiles(crossbowStack).stream().anyMatch(stackToCheck -> stackToCheck.is(ammoItem)); ++ return getChargedProjectiles(crossbowStack).stream().anyMatch((itemstack1) -> { ++ return itemstack1.is(ammoItem); ++ }); + } + +- private static void shootProjectile( +- Level level, +- LivingEntity shooter, +- InteractionHand hand, +- ItemStack crossbowStack, +- ItemStack ammoStack, +- float soundPitch, +- boolean isCreativeMode, +- float velocity, +- float inaccuracy, +- float projectileAngle +- ) { ++ private static void shootProjectile(Level level, LivingEntity shooter, EnumHand hand, ItemStack crossbowStack, ItemStack ammoStack, float soundPitch, boolean isCreativeMode, float velocity, float inaccuracy, float projectileAngle) { + if (!level.isClientSide) { +- boolean isFireworkRocket = ammoStack.is(Items.FIREWORK_ROCKET); +- Projectile projectile; +- if (isFireworkRocket) { +- projectile = new FireworkRocketEntity(level, ammoStack, shooter, shooter.getX(), shooter.getEyeY() - 0.15F, shooter.getZ(), true); ++ boolean flag1 = ammoStack.is(Items.FIREWORK_ROCKET); ++ Object object; ++ ++ if (flag1) { ++ object = new FireworkRocketEntity(level, ammoStack, shooter, shooter.getX(), shooter.getEyeY() - 0.15000000596046448D, shooter.getZ(), true); + } else { +- projectile = getArrow(level, shooter, crossbowStack, ammoStack); ++ object = getArrow(level, shooter, crossbowStack, ammoStack); + if (isCreativeMode || projectileAngle != 0.0F) { +- ((AbstractArrow)projectile).pickup = AbstractArrow.Pickup.CREATIVE_ONLY; ++ ((AbstractArrow) object).pickup = AbstractArrow.Pickup.CREATIVE_ONLY; + } + } + +- if (shooter instanceof CrossbowAttackMob crossbowAttackMob) { +- crossbowAttackMob.shootCrossbowProjectile(crossbowAttackMob.getTarget(), crossbowStack, projectile, projectileAngle); ++ if (shooter instanceof CrossbowAttackMob) { ++ CrossbowAttackMob icrossbow = (CrossbowAttackMob) shooter; ++ ++ icrossbow.shootCrossbowProjectile(icrossbow.getTarget(), crossbowStack, (Projectile) object, projectileAngle); + } else { +- Vec3 upVector = shooter.getUpVector(1.0F); +- Quaternionf quaternionf = new Quaternionf() +- .setAngleAxis((double)(projectileAngle * (float) (Math.PI / 180.0)), upVector.x, upVector.y, upVector.z); +- Vec3 viewVector = shooter.getViewVector(1.0F); +- Vector3f vector3f = viewVector.toVector3f().rotate(quaternionf); +- projectile.shoot((double)vector3f.x(), (double)vector3f.y(), (double)vector3f.z(), velocity, inaccuracy); ++ Vec3 vec3d = shooter.getUpVector(1.0F); ++ Quaternionf quaternionf = (new Quaternionf()).setAngleAxis((double) (projectileAngle * 0.017453292F), vec3d.x, vec3d.y, vec3d.z); ++ Vec3 vec3d1 = shooter.getViewVector(1.0F); ++ Vector3f vector3f = vec3d1.toVector3f().rotate(quaternionf); ++ ++ ((Projectile) object).shoot((double) vector3f.x(), (double) vector3f.y(), (double) vector3f.z(), velocity, inaccuracy); + } ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(shooter, crossbowStack, ammoStack, (Entity) object, shooter.getUsedItemHand(), soundPitch, true); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ // CraftBukkit end + +- crossbowStack.hurtAndBreak(isFireworkRocket ? 3 : 1, shooter, contextEntity -> contextEntity.broadcastBreakEvent(hand)); +- level.addFreshEntity(projectile); +- level.playSound(null, shooter.getX(), shooter.getY(), shooter.getZ(), SoundEvents.CROSSBOW_SHOOT, SoundSource.PLAYERS, 1.0F, soundPitch); ++ crossbowStack.hurtAndBreak(flag1 ? 3 : 1, shooter, (entityliving1) -> { ++ entityliving1.broadcastBreakEvent(hand); ++ }); ++ // CraftBukkit start ++ if (event.getProjectile() == ((Entity) object).getBukkitEntity()) { ++ if (!level.addFreshEntity((Entity) object)) { ++ if (shooter instanceof ServerPlayer) { ++ ((ServerPlayer) shooter).getBukkitEntity().updateInventory(); ++ } ++ return; ++ } ++ } ++ // CraftBukkit end ++ level.playSound((Player) null, shooter.getX(), shooter.getY(), shooter.getZ(), SoundEvents.CROSSBOW_SHOOT, SoundSource.PLAYERS, 1.0F, soundPitch); + } + } + + private static AbstractArrow getArrow(Level level, LivingEntity livingEntity, ItemStack crossbowStack, ItemStack ammoStack) { +- ArrowItem arrowItem = (ArrowItem)(ammoStack.getItem() instanceof ArrowItem ? ammoStack.getItem() : Items.ARROW); +- AbstractArrow abstractArrow = arrowItem.createArrow(level, ammoStack, livingEntity); ++ ArrowItem itemarrow = (ArrowItem) (ammoStack.getItem() instanceof ArrowItem ? ammoStack.getItem() : Items.ARROW); ++ AbstractArrow entityarrow = itemarrow.createArrow(level, ammoStack, livingEntity); ++ + if (livingEntity instanceof Player) { +- abstractArrow.setCritArrow(true); ++ entityarrow.setCritArrow(true); + } + +- abstractArrow.setSoundEvent(SoundEvents.CROSSBOW_HIT); +- abstractArrow.setShotFromCrossbow(true); +- int itemEnchantmentLevel = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.PIERCING, crossbowStack); +- if (itemEnchantmentLevel > 0) { +- abstractArrow.setPierceLevel((byte)itemEnchantmentLevel); ++ entityarrow.setSoundEvent(SoundEvents.CROSSBOW_HIT); ++ entityarrow.setShotFromCrossbow(true); ++ int i = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.PIERCING, crossbowStack); ++ ++ if (i > 0) { ++ entityarrow.setPierceLevel((byte) i); + } + +- return abstractArrow; ++ return entityarrow; + } + +- public static void performShooting(Level level, LivingEntity shooter, InteractionHand usedHand, ItemStack crossbowStack, float velocity, float inaccuracy) { +- List chargedProjectiles = getChargedProjectiles(crossbowStack); +- float[] shotPitches = getShotPitches(shooter.getRandom()); ++ public static void performShooting(Level level, LivingEntity shooter, EnumHand usedHand, ItemStack crossbowStack, float velocity, float inaccuracy) { ++ List list = getChargedProjectiles(crossbowStack); ++ float[] afloat = getShotPitches(shooter.getRandom()); + +- for (int i = 0; i < chargedProjectiles.size(); i++) { +- ItemStack itemStack = chargedProjectiles.get(i); +- boolean flag = shooter instanceof Player && ((Player)shooter).getAbilities().instabuild; +- if (!itemStack.isEmpty()) { ++ for (int i = 0; i < list.size(); ++i) { ++ ItemStack itemstack1 = (ItemStack) list.get(i); ++ boolean flag = shooter instanceof Player && ((Player) shooter).getAbilities().instabuild; ++ ++ if (!itemstack1.isEmpty()) { + if (i == 0) { +- shootProjectile(level, shooter, usedHand, crossbowStack, itemStack, shotPitches[i], flag, velocity, inaccuracy, 0.0F); ++ shootProjectile(level, shooter, usedHand, crossbowStack, itemstack1, afloat[i], flag, velocity, inaccuracy, 0.0F); + } else if (i == 1) { +- shootProjectile(level, shooter, usedHand, crossbowStack, itemStack, shotPitches[i], flag, velocity, inaccuracy, -10.0F); ++ shootProjectile(level, shooter, usedHand, crossbowStack, itemstack1, afloat[i], flag, velocity, inaccuracy, -10.0F); + } else if (i == 2) { +- shootProjectile(level, shooter, usedHand, crossbowStack, itemStack, shotPitches[i], flag, velocity, inaccuracy, 10.0F); ++ shootProjectile(level, shooter, usedHand, crossbowStack, itemstack1, afloat[i], flag, velocity, inaccuracy, 10.0F); + } + } + } +@@ -280,22 +303,26 @@ + } + + private static float[] getShotPitches(RandomSource random) { +- boolean randomBoolean = random.nextBoolean(); +- return new float[]{1.0F, getRandomShotPitch(randomBoolean, random), getRandomShotPitch(!randomBoolean, random)}; ++ boolean flag = random.nextBoolean(); ++ ++ return new float[]{1.0F, getRandomShotPitch(flag, random), getRandomShotPitch(!flag, random)}; + } + + private static float getRandomShotPitch(boolean isHighPitched, RandomSource random) { + float f = isHighPitched ? 0.63F : 0.43F; ++ + return 1.0F / (random.nextFloat() * 0.5F + 1.8F) + f; + } + + private static void onCrossbowShot(Level level, LivingEntity shooter, ItemStack crossbowStack) { +- if (shooter instanceof ServerPlayer serverPlayer) { ++ if (shooter instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) shooter; ++ + if (!level.isClientSide) { +- CriteriaTriggers.SHOT_CROSSBOW.trigger(serverPlayer, crossbowStack); ++ CriteriaTriggers.SHOT_CROSSBOW.trigger(entityplayer, crossbowStack); + } + +- serverPlayer.awardStat(Stats.ITEM_USED.get(crossbowStack.getItem())); ++ entityplayer.awardStat(Stats.ITEM_USED.get(crossbowStack.getItem())); + } + + clearChargedProjectiles(crossbowStack); +@@ -304,10 +331,11 @@ + @Override + public void onUseTick(Level level, LivingEntity livingEntity, ItemStack stack, int count) { + if (!level.isClientSide) { +- int itemEnchantmentLevel = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.QUICK_CHARGE, stack); +- SoundEvent startSound = this.getStartSound(itemEnchantmentLevel); +- SoundEvent soundEvent = itemEnchantmentLevel == 0 ? SoundEvents.CROSSBOW_LOADING_MIDDLE : null; +- float f = (float)(stack.getUseDuration() - count) / (float)getChargeDuration(stack); ++ int j = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.QUICK_CHARGE, stack); ++ SoundEvent soundeffect = this.getStartSound(j); ++ SoundEvent soundeffect1 = j == 0 ? SoundEvents.CROSSBOW_LOADING_MIDDLE : null; ++ float f = (float) (stack.getUseDuration() - count) / (float) getChargeDuration(stack); ++ + if (f < 0.2F) { + this.startSoundPlayed = false; + this.midLoadSoundPlayed = false; +@@ -315,14 +343,15 @@ + + if (f >= 0.2F && !this.startSoundPlayed) { + this.startSoundPlayed = true; +- level.playSound(null, livingEntity.getX(), livingEntity.getY(), livingEntity.getZ(), startSound, SoundSource.PLAYERS, 0.5F, 1.0F); ++ level.playSound((Player) null, livingEntity.getX(), livingEntity.getY(), livingEntity.getZ(), soundeffect, SoundSource.PLAYERS, 0.5F, 1.0F); + } + +- if (f >= 0.5F && soundEvent != null && !this.midLoadSoundPlayed) { ++ if (f >= 0.5F && soundeffect1 != null && !this.midLoadSoundPlayed) { + this.midLoadSoundPlayed = true; +- level.playSound(null, livingEntity.getX(), livingEntity.getY(), livingEntity.getZ(), soundEvent, SoundSource.PLAYERS, 0.5F, 1.0F); ++ level.playSound((Player) null, livingEntity.getX(), livingEntity.getY(), livingEntity.getZ(), soundeffect1, SoundSource.PLAYERS, 0.5F, 1.0F); + } + } ++ + } + + @Override +@@ -331,13 +360,14 @@ + } + + public static int getChargeDuration(ItemStack crossbowStack) { +- int itemEnchantmentLevel = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.QUICK_CHARGE, crossbowStack); +- return itemEnchantmentLevel == 0 ? 25 : 25 - 5 * itemEnchantmentLevel; ++ int i = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.QUICK_CHARGE, crossbowStack); ++ ++ return i == 0 ? 25 : 25 - 5 * i; + } + + @Override +- public UseAnim getUseAnimation(ItemStack stack) { +- return UseAnim.CROSSBOW; ++ public EnumAnimation getUseAnimation(ItemStack stack) { ++ return EnumAnimation.CROSSBOW; + } + + private SoundEvent getStartSound(int enchantmentLevel) { +@@ -354,7 +384,8 @@ + } + + private static float getPowerForTime(int useTime, ItemStack crossbowStack) { +- float f = (float)useTime / (float)getChargeDuration(crossbowStack); ++ float f = (float) useTime / (float) getChargeDuration(crossbowStack); ++ + if (f > 1.0F) { + f = 1.0F; + } +@@ -364,27 +395,31 @@ + + @Override + public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { +- List chargedProjectiles = getChargedProjectiles(stack); +- if (isCharged(stack) && !chargedProjectiles.isEmpty()) { +- ItemStack itemStack = chargedProjectiles.get(0); +- tooltip.add(Component.translatable("item.minecraft.crossbow.projectile").append(CommonComponents.SPACE).append(itemStack.getDisplayName())); +- if (flag.isAdvanced() && itemStack.is(Items.FIREWORK_ROCKET)) { +- List list = Lists.newArrayList(); +- Items.FIREWORK_ROCKET.appendHoverText(itemStack, level, list, flag); +- if (!list.isEmpty()) { +- for (int i = 0; i < list.size(); i++) { +- list.set(i, Component.literal(" ").append(list.get(i)).withStyle(ChatFormatting.GRAY)); ++ List list1 = getChargedProjectiles(stack); ++ ++ if (isCharged(stack) && !list1.isEmpty()) { ++ ItemStack itemstack1 = (ItemStack) list1.get(0); ++ ++ tooltip.add(Component.translatable("item.minecraft.crossbow.projectile").append(CommonComponents.SPACE).append(itemstack1.getDisplayName())); ++ if (flag.isAdvanced() && itemstack1.is(Items.FIREWORK_ROCKET)) { ++ List list2 = Lists.newArrayList(); ++ ++ Items.FIREWORK_ROCKET.appendHoverText(itemstack1, level, list2, flag); ++ if (!list2.isEmpty()) { ++ for (int i = 0; i < list2.size(); ++i) { ++ list2.set(i, Component.literal(" ").append((Component) list2.get(i)).withStyle(ChatFormatting.GRAY)); + } + +- tooltip.addAll(list); ++ tooltip.addAll(list2); + } + } ++ + } + } + + @Override + public boolean useOnRelease(ItemStack stack) { +- return stack.is(this); ++ return stack.is((Item) this); + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/DebugStickItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/DebugStickItem.java.patch new file mode 100644 index 0000000000..9933f93c07 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/DebugStickItem.java.patch @@ -0,0 +1,144 @@ +--- a/net/minecraft/world/item/DebugStickItem.java ++++ b/net/minecraft/world/item/DebugStickItem.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.world.item; + + import java.util.Collection; +@@ -8,18 +9,19 @@ + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; + import net.minecraft.server.level.ServerPlayer; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.Block; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.Property; + + public class DebugStickItem extends Item { ++ + public DebugStickItem(Item.Properties properties) { + super(properties); + } +@@ -30,9 +32,9 @@ + } + + @Override +- public boolean canAttackBlock(BlockState state, Level level, BlockPos pos, Player player) { ++ public boolean canAttackBlock(IBlockData state, Level level, BlockPos pos, Player player) { + if (!level.isClientSide) { +- this.handleInteraction(player, state, level, pos, false, player.getItemInHand(InteractionHand.MAIN_HAND)); ++ this.handleInteraction(player, state, level, pos, false, player.getItemInHand(EnumHand.MAIN_HAND)); + } + + return false; +@@ -40,48 +42,52 @@ + + @Override + public InteractionResult useOn(UseOnContext context) { +- Player player = context.getPlayer(); +- Level level = context.getLevel(); +- if (!level.isClientSide && player != null) { +- BlockPos clickedPos = context.getClickedPos(); +- if (!this.handleInteraction(player, level.getBlockState(clickedPos), level, clickedPos, true, context.getItemInHand())) { ++ Player entityhuman = context.getPlayer(); ++ Level world = context.getLevel(); ++ ++ if (!world.isClientSide && entityhuman != null) { ++ BlockPos blockposition = context.getClickedPos(); ++ ++ if (!this.handleInteraction(entityhuman, world.getBlockState(blockposition), world, blockposition, true, context.getItemInHand())) { + return InteractionResult.FAIL; + } + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } + +- private boolean handleInteraction( +- Player player, BlockState stateClicked, LevelAccessor accessor, BlockPos pos, boolean shouldCycleState, ItemStack debugStack +- ) { ++ public boolean handleInteraction(Player player, IBlockData stateClicked, LevelAccessor accessor, BlockPos pos, boolean shouldCycleState, ItemStack debugStack) { + if (!player.canUseGameMasterBlocks()) { + return false; + } else { + Block block = stateClicked.getBlock(); +- StateDefinition stateDefinition = block.getStateDefinition(); +- Collection> properties = stateDefinition.getProperties(); +- String string = BuiltInRegistries.BLOCK.getKey(block).toString(); +- if (properties.isEmpty()) { +- message(player, Component.translatable(this.getDescriptionId() + ".empty", string)); ++ StateDefinition blockstatelist = block.getStateDefinition(); ++ Collection> collection = blockstatelist.getProperties(); ++ String s = BuiltInRegistries.BLOCK.getKey(block).toString(); ++ ++ if (collection.isEmpty()) { ++ message(player, Component.translatable(this.getDescriptionId() + ".empty", s)); + return false; + } else { +- CompoundTag tagElement = debugStack.getOrCreateTagElement("DebugProperty"); +- String string1 = tagElement.getString(string); +- Property property = stateDefinition.getProperty(string1); ++ CompoundTag nbttagcompound = debugStack.getOrCreateTagElement("DebugProperty"); ++ String s1 = nbttagcompound.getString(s); ++ Property iblockstate = blockstatelist.getProperty(s1); ++ + if (shouldCycleState) { +- if (property == null) { +- property = properties.iterator().next(); ++ if (iblockstate == null) { ++ iblockstate = (Property) collection.iterator().next(); + } + +- BlockState blockState = cycleState(stateClicked, property, player.isSecondaryUseActive()); +- accessor.setBlock(pos, blockState, 18); +- message(player, Component.translatable(this.getDescriptionId() + ".update", property.getName(), getNameHelper(blockState, property))); ++ IBlockData iblockdata1 = cycleState(stateClicked, iblockstate, player.isSecondaryUseActive()); ++ ++ accessor.setBlock(pos, iblockdata1, 18); ++ message(player, Component.translatable(this.getDescriptionId() + ".update", iblockstate.getName(), getNameHelper(iblockdata1, iblockstate))); + } else { +- property = getRelative(properties, property, player.isSecondaryUseActive()); +- String name = property.getName(); +- tagElement.putString(string, name); +- message(player, Component.translatable(this.getDescriptionId() + ".select", name, getNameHelper(stateClicked, property))); ++ iblockstate = (Property) getRelative(collection, iblockstate, player.isSecondaryUseActive()); ++ String s2 = iblockstate.getName(); ++ ++ nbttagcompound.putString(s, s2); ++ message(player, Component.translatable(this.getDescriptionId() + ".select", s2, getNameHelper(stateClicked, iblockstate))); + } + + return true; +@@ -89,8 +95,8 @@ + } + } + +- private static > BlockState cycleState(BlockState state, Property property, boolean backwards) { +- return state.setValue(property, getRelative(property.getPossibleValues(), state.getValue(property), backwards)); ++ private static > IBlockData cycleState(IBlockData state, Property property, boolean backwards) { ++ return (IBlockData) state.setValue(property, getRelative(property.getPossibleValues(), state.getValue(property), backwards)); // CraftBukkit - decompile error + } + + private static T getRelative(Iterable allowedValues, @Nullable T currentValue, boolean backwards) { +@@ -98,10 +104,10 @@ + } + + private static void message(Player player, Component messageComponent) { +- ((ServerPlayer)player).sendSystemMessage(messageComponent, true); ++ ((ServerPlayer) player).sendSystemMessage(messageComponent, true); + } + +- private static > String getNameHelper(BlockState state, Property property) { ++ private static > String getNameHelper(IBlockData state, Property property) { + return property.getName(state.getValue(property)); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/DyeItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/DyeItem.java.patch new file mode 100644 index 0000000000..7d57bbc525 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/DyeItem.java.patch @@ -0,0 +1,84 @@ +--- a/net/minecraft/world/item/DyeItem.java ++++ b/net/minecraft/world/item/DyeItem.java +@@ -4,35 +4,51 @@ + import java.util.Map; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.animal.Sheep; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.SignBlockEntity; +-import net.minecraft.world.level.block.entity.SignText; ++import org.bukkit.event.entity.SheepDyeWoolEvent; // CraftBukkit + + public class DyeItem extends Item implements SignApplicator { ++ + private static final Map ITEM_BY_COLOR = Maps.newEnumMap(DyeColor.class); + private final DyeColor dyeColor; + + public DyeItem(DyeColor dyeColor, Item.Properties properties) { + super(properties); + this.dyeColor = dyeColor; +- ITEM_BY_COLOR.put(dyeColor, this); ++ DyeItem.ITEM_BY_COLOR.put(dyeColor, this); + } + + @Override +- public InteractionResult interactLivingEntity(ItemStack stack, Player player, LivingEntity target, InteractionHand hand) { +- if (target instanceof Sheep sheep && sheep.isAlive() && !sheep.isSheared() && sheep.getColor() != this.dyeColor) { +- sheep.level().playSound(player, sheep, SoundEvents.DYE_USE, SoundSource.PLAYERS, 1.0F, 1.0F); +- if (!player.level().isClientSide) { +- sheep.setColor(this.dyeColor); +- stack.shrink(1); +- } ++ public InteractionResult interactLivingEntity(ItemStack stack, Player player, LivingEntity target, EnumHand hand) { ++ if (target instanceof Sheep) { ++ Sheep entitysheep = (Sheep) target; + +- return InteractionResult.sidedSuccess(player.level().isClientSide); ++ if (entitysheep.isAlive() && !entitysheep.isSheared() && entitysheep.getColor() != this.dyeColor) { ++ entitysheep.level().playSound(player, (Entity) entitysheep, SoundEvents.DYE_USE, SoundSource.PLAYERS, 1.0F, 1.0F); ++ if (!player.level().isClientSide) { ++ // CraftBukkit start ++ byte bColor = (byte) this.dyeColor.getId(); ++ SheepDyeWoolEvent event = new SheepDyeWoolEvent((org.bukkit.entity.Sheep) entitysheep.getBukkitEntity(), org.bukkit.DyeColor.getByWoolData(bColor), (org.bukkit.entity.Player) player.getBukkitEntity()); ++ entitysheep.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return InteractionResult.PASS; ++ } ++ ++ entitysheep.setColor(DyeColor.byId((byte) event.getColor().getWoolData())); ++ // CraftBukkit end ++ stack.shrink(1); ++ } ++ ++ return InteractionResult.sidedSuccess(player.level().isClientSide); ++ } + } + + return InteractionResult.PASS; +@@ -43,13 +59,15 @@ + } + + public static DyeItem byColor(DyeColor color) { +- return ITEM_BY_COLOR.get(color); ++ return (DyeItem) DyeItem.ITEM_BY_COLOR.get(color); + } + + @Override + public boolean tryApplyToSign(Level level, SignBlockEntity sign, boolean isFront, Player player) { +- if (sign.updateText(signText -> signText.setColor(this.getDyeColor()), isFront)) { +- level.playSound(null, sign.getBlockPos(), SoundEvents.DYE_USE, SoundSource.BLOCKS, 1.0F, 1.0F); ++ if (sign.updateText((signtext) -> { ++ return signtext.setColor(this.getDyeColor()); ++ }, isFront)) { ++ level.playSound((Player) null, sign.getBlockPos(), SoundEvents.DYE_USE, SoundSource.BLOCKS, 1.0F, 1.0F); + return true; + } else { + return false; diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/EggItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/EggItem.java.patch new file mode 100644 index 0000000000..ed27a63783 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/EggItem.java.patch @@ -0,0 +1,66 @@ +--- a/net/minecraft/world/item/EggItem.java ++++ b/net/minecraft/world/item/EggItem.java +@@ -3,42 +3,44 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.ThrownEgg; + import net.minecraft.world.level.Level; + + public class EggItem extends Item { ++ + public EggItem(Item.Properties properties) { + super(properties); + } + + @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- level.playSound( +- null, +- player.getX(), +- player.getY(), +- player.getZ(), +- SoundEvents.EGG_THROW, +- SoundSource.PLAYERS, +- 0.5F, +- 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F) +- ); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ // world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); // CraftBukkit - moved down + if (!level.isClientSide) { +- ThrownEgg thrownEgg = new ThrownEgg(level, player); +- thrownEgg.setItem(itemInHand); +- thrownEgg.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 1.5F, 1.0F); +- level.addFreshEntity(thrownEgg); ++ ThrownEgg entityegg = new ThrownEgg(level, player); ++ ++ entityegg.setItem(itemstack); ++ entityegg.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 1.5F, 1.0F); ++ // CraftBukkit start ++ if (!level.addFreshEntity(entityegg)) { ++ if (player instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().updateInventory(); ++ } ++ return InteractionResultHolder.fail(itemstack); ++ } ++ // CraftBukkit end + } ++ level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.EGG_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); + + player.awardStat(Stats.ITEM_USED.get(this)); + if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + +- return InteractionResultHolder.sidedSuccess(itemInHand, level.isClientSide()); ++ return InteractionResultHolder.sidedSuccess(itemstack, level.isClientSide()); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/EndCrystalItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/EndCrystalItem.java.patch new file mode 100644 index 0000000000..dbe8d5b5fc --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/EndCrystalItem.java.patch @@ -0,0 +1,83 @@ +--- a/net/minecraft/world/item/EndCrystalItem.java ++++ b/net/minecraft/world/item/EndCrystalItem.java +@@ -9,48 +9,59 @@ + import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.dimension.end.EndDragonFight; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; + + public class EndCrystalItem extends Item { ++ + public EndCrystalItem(Item.Properties properties) { + super(properties); + } + + @Override + public InteractionResult useOn(UseOnContext context) { +- Level level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- BlockState blockState = level.getBlockState(clickedPos); +- if (!blockState.is(Blocks.OBSIDIAN) && !blockState.is(Blocks.BEDROCK)) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ ++ if (!iblockdata.is(Blocks.OBSIDIAN) && !iblockdata.is(Blocks.BEDROCK)) { + return InteractionResult.FAIL; + } else { +- BlockPos blockPos = clickedPos.above(); +- if (!level.isEmptyBlock(blockPos)) { ++ BlockPos blockposition1 = blockposition.above(); ++ ++ if (!world.isEmptyBlock(blockposition1)) { + return InteractionResult.FAIL; + } else { +- double d = (double)blockPos.getX(); +- double d1 = (double)blockPos.getY(); +- double d2 = (double)blockPos.getZ(); +- List entities = level.getEntities(null, new AABB(d, d1, d2, d + 1.0, d1 + 2.0, d2 + 1.0)); +- if (!entities.isEmpty()) { ++ double d0 = (double) blockposition1.getX(); ++ double d1 = (double) blockposition1.getY(); ++ double d2 = (double) blockposition1.getZ(); ++ List list = world.getEntities((Entity) null, new AABB(d0, d1, d2, d0 + 1.0D, d1 + 2.0D, d2 + 1.0D)); ++ ++ if (!list.isEmpty()) { + return InteractionResult.FAIL; + } else { +- if (level instanceof ServerLevel) { +- EndCrystal endCrystal = new EndCrystal(level, d + 0.5, d1, d2 + 0.5); +- endCrystal.setShowBottom(false); +- level.addFreshEntity(endCrystal); +- level.gameEvent(context.getPlayer(), GameEvent.ENTITY_PLACE, blockPos); +- EndDragonFight dragonFight = ((ServerLevel)level).getDragonFight(); +- if (dragonFight != null) { +- dragonFight.tryRespawn(); ++ if (world instanceof ServerLevel) { ++ EndCrystal entityendercrystal = new EndCrystal(world, d0 + 0.5D, d1, d2 + 0.5D); ++ ++ entityendercrystal.setShowBottom(false); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(context, entityendercrystal).isCancelled()) { ++ return InteractionResult.FAIL; + } ++ // CraftBukkit end ++ world.addFreshEntity(entityendercrystal); ++ world.gameEvent((Entity) context.getPlayer(), GameEvent.ENTITY_PLACE, blockposition1); ++ EndDragonFight enderdragonbattle = ((ServerLevel) world).getDragonFight(); ++ ++ if (enderdragonbattle != null) { ++ enderdragonbattle.tryRespawn(); ++ } + } + + context.getItemInHand().shrink(1); +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/EnderEyeItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/EnderEyeItem.java.patch new file mode 100644 index 0000000000..23e574aaab --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/EnderEyeItem.java.patch @@ -0,0 +1,164 @@ +--- a/net/minecraft/world/item/EnderEyeItem.java ++++ b/net/minecraft/world/item/EnderEyeItem.java +@@ -8,9 +8,10 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; + import net.minecraft.tags.StructureTags; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.EyeOfEnder; + import net.minecraft.world.item.context.UseOnContext; +@@ -19,92 +20,97 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.EndPortalFrameBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.pattern.BlockPattern; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.HitResult; + + public class EnderEyeItem extends Item { ++ + public EnderEyeItem(Item.Properties properties) { + super(properties); + } + + @Override + public InteractionResult useOn(UseOnContext context) { +- Level level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- BlockState blockState = level.getBlockState(clickedPos); +- if (!blockState.is(Blocks.END_PORTAL_FRAME) || blockState.getValue(EndPortalFrameBlock.HAS_EYE)) { +- return InteractionResult.PASS; +- } else if (level.isClientSide) { +- return InteractionResult.SUCCESS; +- } else { +- BlockState blockState1 = blockState.setValue(EndPortalFrameBlock.HAS_EYE, Boolean.valueOf(true)); +- Block.pushEntitiesUp(blockState, blockState1, level, clickedPos); +- level.setBlock(clickedPos, blockState1, 2); +- level.updateNeighbourForOutputSignal(clickedPos, Blocks.END_PORTAL_FRAME); +- context.getItemInHand().shrink(1); +- level.levelEvent(1503, clickedPos, 0); +- BlockPattern.BlockPatternMatch blockPatternMatch = EndPortalFrameBlock.getOrCreatePortalShape().find(level, clickedPos); +- if (blockPatternMatch != null) { +- BlockPos blockPos = blockPatternMatch.getFrontTopLeft().offset(-3, 0, -3); ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ IBlockData iblockdata = world.getBlockState(blockposition); + +- for (int i = 0; i < 3; i++) { +- for (int i1 = 0; i1 < 3; i1++) { +- level.setBlock(blockPos.offset(i, 0, i1), Blocks.END_PORTAL.defaultBlockState(), 2); ++ if (iblockdata.is(Blocks.END_PORTAL_FRAME) && !(Boolean) iblockdata.getValue(EndPortalFrameBlock.HAS_EYE)) { ++ if (world.isClientSide) { ++ return InteractionResult.SUCCESS; ++ } else { ++ IBlockData iblockdata1 = (IBlockData) iblockdata.setValue(EndPortalFrameBlock.HAS_EYE, true); ++ ++ Block.pushEntitiesUp(iblockdata, iblockdata1, world, blockposition); ++ world.setBlock(blockposition, iblockdata1, 2); ++ world.updateNeighbourForOutputSignal(blockposition, Blocks.END_PORTAL_FRAME); ++ context.getItemInHand().shrink(1); ++ world.levelEvent(1503, blockposition, 0); ++ BlockPattern.BlockPatternMatch shapedetector_shapedetectorcollection = EndPortalFrameBlock.getOrCreatePortalShape().find(world, blockposition); ++ ++ if (shapedetector_shapedetectorcollection != null) { ++ BlockPos blockposition1 = shapedetector_shapedetectorcollection.getFrontTopLeft().offset(-3, 0, -3); ++ ++ for (int i = 0; i < 3; ++i) { ++ for (int j = 0; j < 3; ++j) { ++ world.setBlock(blockposition1.offset(i, 0, j), Blocks.END_PORTAL.defaultBlockState(), 2); ++ } + } ++ ++ world.globalLevelEvent(1038, blockposition1.offset(1, 0, 1), 0); + } + +- level.globalLevelEvent(1038, blockPos.offset(1, 0, 1), 0); ++ return InteractionResult.CONSUME; + } +- +- return InteractionResult.CONSUME; ++ } else { ++ return InteractionResult.PASS; + } + } + + @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- BlockHitResult playerPOVHitResult = getPlayerPOVHitResult(level, player, ClipContext.Fluid.NONE); +- if (playerPOVHitResult.getType() == HitResult.Type.BLOCK && level.getBlockState(playerPOVHitResult.getBlockPos()).is(Blocks.END_PORTAL_FRAME)) { +- return InteractionResultHolder.pass(itemInHand); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ BlockHitResult movingobjectpositionblock = getPlayerPOVHitResult(level, player, ClipContext.Fluid.NONE); ++ ++ if (movingobjectpositionblock.getType() == HitResult.EnumMovingObjectType.BLOCK && level.getBlockState(movingobjectpositionblock.getBlockPos()).is(Blocks.END_PORTAL_FRAME)) { ++ return InteractionResultHolder.pass(itemstack); + } else { + player.startUsingItem(hand); +- if (level instanceof ServerLevel serverLevel) { +- BlockPos blockPos = serverLevel.findNearestMapStructure(StructureTags.EYE_OF_ENDER_LOCATED, player.blockPosition(), 100, false); +- if (blockPos != null) { +- EyeOfEnder eyeOfEnder = new EyeOfEnder(level, player.getX(), player.getY(0.5), player.getZ()); +- eyeOfEnder.setItem(itemInHand); +- eyeOfEnder.signalTo(blockPos); +- level.gameEvent(GameEvent.PROJECTILE_SHOOT, eyeOfEnder.position(), GameEvent.Context.of(player)); +- level.addFreshEntity(eyeOfEnder); ++ if (level instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) level; ++ BlockPos blockposition = worldserver.findNearestMapStructure(StructureTags.EYE_OF_ENDER_LOCATED, player.blockPosition(), 100, false); ++ ++ if (blockposition != null) { ++ EyeOfEnder entityendersignal = new EyeOfEnder(level, player.getX(), player.getY(0.5D), player.getZ()); ++ ++ entityendersignal.setItem(itemstack); ++ entityendersignal.signalTo(blockposition); ++ level.gameEvent(GameEvent.PROJECTILE_SHOOT, entityendersignal.position(), GameEvent.Context.of((Entity) player)); ++ // CraftBukkit start ++ if (!level.addFreshEntity(entityendersignal)) { ++ return new InteractionResultHolder(InteractionResult.FAIL, itemstack); ++ } ++ // CraftBukkit end + if (player instanceof ServerPlayer) { +- CriteriaTriggers.USED_ENDER_EYE.trigger((ServerPlayer)player, blockPos); ++ CriteriaTriggers.USED_ENDER_EYE.trigger((ServerPlayer) player, blockposition); + } + +- level.playSound( +- null, +- player.getX(), +- player.getY(), +- player.getZ(), +- SoundEvents.ENDER_EYE_LAUNCH, +- SoundSource.NEUTRAL, +- 0.5F, +- 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F) +- ); +- level.levelEvent(null, 1003, player.blockPosition(), 0); ++ level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.ENDER_EYE_LAUNCH, SoundSource.NEUTRAL, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); ++ level.levelEvent((Player) null, 1003, player.blockPosition(), 0); + if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + + player.awardStat(Stats.ITEM_USED.get(this)); + player.swing(hand, true); +- return InteractionResultHolder.success(itemInHand); ++ return InteractionResultHolder.success(itemstack); + } + } + +- return InteractionResultHolder.consume(itemInHand); ++ return InteractionResultHolder.consume(itemstack); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/EnderpearlItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/EnderpearlItem.java.patch new file mode 100644 index 0000000000..09162a980d --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/EnderpearlItem.java.patch @@ -0,0 +1,68 @@ +--- a/net/minecraft/world/item/EnderpearlItem.java ++++ b/net/minecraft/world/item/EnderpearlItem.java +@@ -3,43 +3,45 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.ThrownEnderpearl; + import net.minecraft.world.level.Level; + + public class EnderpearlItem extends Item { ++ + public EnderpearlItem(Item.Properties properties) { + super(properties); + } + + @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- level.playSound( +- null, +- player.getX(), +- player.getY(), +- player.getZ(), +- SoundEvents.ENDER_PEARL_THROW, +- SoundSource.NEUTRAL, +- 0.5F, +- 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F) +- ); +- player.getCooldowns().addCooldown(this, 20); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ // CraftBukkit start - change order + if (!level.isClientSide) { +- ThrownEnderpearl thrownEnderpearl = new ThrownEnderpearl(level, player); +- thrownEnderpearl.setItem(itemInHand); +- thrownEnderpearl.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 1.5F, 1.0F); +- level.addFreshEntity(thrownEnderpearl); ++ ThrownEnderpearl entityenderpearl = new ThrownEnderpearl(level, player); ++ ++ entityenderpearl.setItem(itemstack); ++ entityenderpearl.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 1.5F, 1.0F); ++ if (!level.addFreshEntity(entityenderpearl)) { ++ if (player instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().updateInventory(); ++ } ++ return InteractionResultHolder.fail(itemstack); ++ } + } + ++ level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); ++ player.getCooldowns().addCooldown(this, 20); ++ // CraftBukkit end ++ + player.awardStat(Stats.ITEM_USED.get(this)); + if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + +- return InteractionResultHolder.sidedSuccess(itemInHand, level.isClientSide()); ++ return InteractionResultHolder.sidedSuccess(itemstack, level.isClientSide()); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/FireChargeItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/FireChargeItem.java.patch new file mode 100644 index 0000000000..25fe364878 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/FireChargeItem.java.patch @@ -0,0 +1,92 @@ +--- a/net/minecraft/world/item/FireChargeItem.java ++++ b/net/minecraft/world/item/FireChargeItem.java +@@ -5,52 +5,73 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.util.RandomSource; + import net.minecraft.world.InteractionResult; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.BaseFireBlock; + import net.minecraft.world.level.block.CampfireBlock; + import net.minecraft.world.level.block.CandleBlock; + import net.minecraft.world.level.block.CandleCakeBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.gameevent.GameEvent; + + public class FireChargeItem extends Item { ++ + public FireChargeItem(Item.Properties properties) { + super(properties); + } + + @Override + public InteractionResult useOn(UseOnContext context) { +- Level level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- BlockState blockState = level.getBlockState(clickedPos); ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ IBlockData iblockdata = world.getBlockState(blockposition); + boolean flag = false; +- if (!CampfireBlock.canLight(blockState) && !CandleBlock.canLight(blockState) && !CandleCakeBlock.canLight(blockState)) { +- BlockPos var6 = clickedPos.relative(context.getClickedFace()); +- if (BaseFireBlock.canBePlacedAt(level, var6, context.getHorizontalDirection())) { +- this.playSound(level, var6); +- level.setBlockAndUpdate(var6, BaseFireBlock.getState(level, var6)); +- level.gameEvent(context.getPlayer(), GameEvent.BLOCK_PLACE, var6); ++ ++ if (!CampfireBlock.canLight(iblockdata) && !CandleBlock.canLight(iblockdata) && !CandleCakeBlock.canLight(iblockdata)) { ++ blockposition = blockposition.relative(context.getClickedFace()); ++ if (BaseFireBlock.canBePlacedAt(world, blockposition, context.getHorizontalDirection())) { ++ // CraftBukkit start - fire BlockIgniteEvent ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FIREBALL, context.getPlayer()).isCancelled()) { ++ if (!context.getPlayer().getAbilities().instabuild) { ++ context.getItemInHand().shrink(1); ++ } ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end ++ this.playSound(world, blockposition); ++ world.setBlockAndUpdate(blockposition, BaseFireBlock.getState(world, blockposition)); ++ world.gameEvent((Entity) context.getPlayer(), GameEvent.BLOCK_PLACE, blockposition); + flag = true; + } + } else { +- this.playSound(level, clickedPos); +- level.setBlockAndUpdate(clickedPos, blockState.setValue(BlockStateProperties.LIT, Boolean.valueOf(true))); +- level.gameEvent(context.getPlayer(), GameEvent.BLOCK_CHANGE, clickedPos); ++ // CraftBukkit start - fire BlockIgniteEvent ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FIREBALL, context.getPlayer()).isCancelled()) { ++ if (!context.getPlayer().getAbilities().instabuild) { ++ context.getItemInHand().shrink(1); ++ } ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end ++ this.playSound(world, blockposition); ++ world.setBlockAndUpdate(blockposition, (IBlockData) iblockdata.setValue(BlockStateProperties.LIT, true)); ++ world.gameEvent((Entity) context.getPlayer(), GameEvent.BLOCK_CHANGE, blockposition); + flag = true; + } + + if (flag) { + context.getItemInHand().shrink(1); +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } else { + return InteractionResult.FAIL; + } + } + + private void playSound(Level level, BlockPos pos) { +- RandomSource random = level.getRandom(); +- level.playSound(null, pos, SoundEvents.FIRECHARGE_USE, SoundSource.BLOCKS, 1.0F, (random.nextFloat() - random.nextFloat()) * 0.2F + 1.0F); ++ RandomSource randomsource = level.getRandom(); ++ ++ level.playSound((Player) null, pos, SoundEvents.FIRECHARGE_USE, SoundSource.BLOCKS, 1.0F, (randomsource.nextFloat() - randomsource.nextFloat()) * 0.2F + 1.0F); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/FishingRodItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/FishingRodItem.java.patch new file mode 100644 index 0000000000..b426cb8fe7 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/FishingRodItem.java.patch @@ -0,0 +1,98 @@ +--- a/net/minecraft/world/item/FishingRodItem.java ++++ b/net/minecraft/world/item/FishingRodItem.java +@@ -3,7 +3,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.FishingHook; +@@ -11,53 +11,57 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + +-public class FishingRodItem extends Item implements Vanishable { ++// CraftBukkit start ++import org.bukkit.event.player.PlayerFishEvent; ++import org.bukkit.craftbukkit.CraftEquipmentSlot; ++// CraftBukkit end ++ ++public class FishingRodItem extends Item implements ItemVanishable { ++ + public FishingRodItem(Item.Properties properties) { + super(properties); + } + + @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ int i; ++ + if (player.fishing != null) { + if (!level.isClientSide) { +- int i = player.fishing.retrieve(itemInHand); +- itemInHand.hurtAndBreak(i, player, contextEntity -> contextEntity.broadcastBreakEvent(hand)); ++ i = player.fishing.retrieve(itemstack); ++ itemstack.hurtAndBreak(i, player, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(hand); ++ }); + } + +- level.playSound( +- null, +- player.getX(), +- player.getY(), +- player.getZ(), +- SoundEvents.FISHING_BOBBER_RETRIEVE, +- SoundSource.NEUTRAL, +- 1.0F, +- 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F) +- ); ++ level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.FISHING_BOBBER_RETRIEVE, SoundSource.NEUTRAL, 1.0F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); + player.gameEvent(GameEvent.ITEM_INTERACT_FINISH); + } else { +- level.playSound( +- null, +- player.getX(), +- player.getY(), +- player.getZ(), +- SoundEvents.FISHING_BOBBER_THROW, +- SoundSource.NEUTRAL, +- 0.5F, +- 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F) +- ); ++ // world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.FISHING_BOBBER_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); + if (!level.isClientSide) { +- int i = EnchantmentHelper.getFishingSpeedBonus(itemInHand); +- int fishingLuckBonus = EnchantmentHelper.getFishingLuckBonus(itemInHand); +- level.addFreshEntity(new FishingHook(player, level, fishingLuckBonus, i)); ++ i = EnchantmentHelper.getFishingSpeedBonus(itemstack); ++ int j = EnchantmentHelper.getFishingLuckBonus(itemstack); ++ ++ // CraftBukkit start ++ FishingHook entityfishinghook = new FishingHook(player, level, j, i); ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((org.bukkit.entity.Player) player.getBukkitEntity(), null, (org.bukkit.entity.FishHook) entityfishinghook.getBukkitEntity(), CraftEquipmentSlot.getHand(hand), PlayerFishEvent.State.FISHING); ++ level.getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ player.fishing = null; ++ return InteractionResultHolder.pass(itemstack); ++ } ++ level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.FISHING_BOBBER_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); ++ level.addFreshEntity(entityfishinghook); ++ // CraftBukkit end + } + + player.awardStat(Stats.ITEM_USED.get(this)); + player.gameEvent(GameEvent.ITEM_INTERACT_START); + } + +- return InteractionResultHolder.sidedSuccess(itemInHand, level.isClientSide()); ++ return InteractionResultHolder.sidedSuccess(itemstack, level.isClientSide()); + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/FlintAndSteelItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/FlintAndSteelItem.java.patch new file mode 100644 index 0000000000..37ab07b16e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/FlintAndSteelItem.java.patch @@ -0,0 +1,106 @@ +--- a/net/minecraft/world/item/FlintAndSteelItem.java ++++ b/net/minecraft/world/item/FlintAndSteelItem.java +@@ -6,6 +6,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.InteractionResult; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.Level; +@@ -13,47 +14,72 @@ + import net.minecraft.world.level.block.CampfireBlock; + import net.minecraft.world.level.block.CandleBlock; + import net.minecraft.world.level.block.CandleCakeBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.gameevent.GameEvent; + + public class FlintAndSteelItem extends Item { ++ + public FlintAndSteelItem(Item.Properties properties) { + super(properties); + } + + @Override + public InteractionResult useOn(UseOnContext context) { +- Player player = context.getPlayer(); +- Level level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- BlockState blockState = level.getBlockState(clickedPos); +- if (!CampfireBlock.canLight(blockState) && !CandleBlock.canLight(blockState) && !CandleCakeBlock.canLight(blockState)) { +- BlockPos blockPos = clickedPos.relative(context.getClickedFace()); +- if (BaseFireBlock.canBePlacedAt(level, blockPos, context.getHorizontalDirection())) { +- level.playSound(player, blockPos, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.4F + 0.8F); +- BlockState state = BaseFireBlock.getState(level, blockPos); +- level.setBlock(blockPos, state, 11); +- level.gameEvent(player, GameEvent.BLOCK_PLACE, clickedPos); +- ItemStack itemInHand = context.getItemInHand(); +- if (player instanceof ServerPlayer) { +- CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer)player, blockPos, itemInHand); +- itemInHand.hurtAndBreak(1, player, contextPlayer -> contextPlayer.broadcastBreakEvent(context.getHand())); ++ Player entityhuman = context.getPlayer(); ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ ++ if (!CampfireBlock.canLight(iblockdata) && !CandleBlock.canLight(iblockdata) && !CandleCakeBlock.canLight(iblockdata)) { ++ BlockPos blockposition1 = blockposition.relative(context.getClickedFace()); ++ ++ if (BaseFireBlock.canBePlacedAt(world, blockposition1, context.getHorizontalDirection())) { ++ // CraftBukkit start - Store the clicked block ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition1, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL, entityhuman).isCancelled()) { ++ context.getItemInHand().hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(context.getHand()); ++ }); ++ return InteractionResult.PASS; + } ++ // CraftBukkit end ++ world.playSound(entityhuman, blockposition1, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, world.getRandom().nextFloat() * 0.4F + 0.8F); ++ IBlockData iblockdata1 = BaseFireBlock.getState(world, blockposition1); + +- return InteractionResult.sidedSuccess(level.isClientSide()); ++ world.setBlock(blockposition1, iblockdata1, 11); ++ world.gameEvent((Entity) entityhuman, GameEvent.BLOCK_PLACE, blockposition); ++ ItemStack itemstack = context.getItemInHand(); ++ ++ if (entityhuman instanceof ServerPlayer) { ++ CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) entityhuman, blockposition1, itemstack); ++ itemstack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(context.getHand()); ++ }); ++ } ++ ++ return InteractionResult.sidedSuccess(world.isClientSide()); + } else { + return InteractionResult.FAIL; + } + } else { +- level.playSound(player, clickedPos, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.4F + 0.8F); +- level.setBlock(clickedPos, blockState.setValue(BlockStateProperties.LIT, Boolean.valueOf(true)), 11); +- level.gameEvent(player, GameEvent.BLOCK_CHANGE, clickedPos); +- if (player != null) { +- context.getItemInHand().hurtAndBreak(1, player, contextPlayer -> contextPlayer.broadcastBreakEvent(context.getHand())); ++ // CraftBukkit start - Store the clicked block ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL, entityhuman).isCancelled()) { ++ context.getItemInHand().hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(context.getHand()); ++ }); ++ return InteractionResult.PASS; + } ++ // CraftBukkit end ++ world.playSound(entityhuman, blockposition, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, world.getRandom().nextFloat() * 0.4F + 0.8F); ++ world.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockStateProperties.LIT, true), 11); ++ world.gameEvent((Entity) entityhuman, GameEvent.BLOCK_CHANGE, blockposition); ++ if (entityhuman != null) { ++ context.getItemInHand().hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(context.getHand()); ++ }); ++ } + +- return InteractionResult.sidedSuccess(level.isClientSide()); ++ return InteractionResult.sidedSuccess(world.isClientSide()); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/HangingEntityItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/HangingEntityItem.java.patch new file mode 100644 index 0000000000..f19767ab05 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/HangingEntityItem.java.patch @@ -0,0 +1,183 @@ +--- a/net/minecraft/world/item/HangingEntityItem.java ++++ b/net/minecraft/world/item/HangingEntityItem.java +@@ -6,23 +6,28 @@ + import net.minecraft.ChatFormatting; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.Holder; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; +-import net.minecraft.resources.ResourceKey; + import net.minecraft.util.Mth; + import net.minecraft.world.InteractionResult; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.decoration.GlowItemFrame; + import net.minecraft.world.entity.decoration.HangingEntity; + import net.minecraft.world.entity.decoration.ItemFrame; + import net.minecraft.world.entity.decoration.Painting; +-import net.minecraft.world.entity.player.Player; ++import net.minecraft.world.entity.decoration.PaintingVariant; + import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.entity.Player; ++import org.bukkit.event.hanging.HangingPlaceEvent; ++// CraftBukkit end ++ + public class HangingEntityItem extends Item { ++ + private static final Component TOOLTIP_RANDOM_VARIANT = Component.translatable("painting.random").withStyle(ChatFormatting.GRAY); + private final EntityType type; + +@@ -33,54 +38,71 @@ + + @Override + public InteractionResult useOn(UseOnContext context) { +- BlockPos clickedPos = context.getClickedPos(); +- Direction clickedFace = context.getClickedFace(); +- BlockPos blockPos = clickedPos.relative(clickedFace); +- Player player = context.getPlayer(); +- ItemStack itemInHand = context.getItemInHand(); +- if (player != null && !this.mayPlace(player, clickedFace, itemInHand, blockPos)) { ++ BlockPos blockposition = context.getClickedPos(); ++ Direction enumdirection = context.getClickedFace(); ++ BlockPos blockposition1 = blockposition.relative(enumdirection); ++ net.minecraft.world.entity.player.Player entityhuman = context.getPlayer(); ++ ItemStack itemstack = context.getItemInHand(); ++ ++ if (entityhuman != null && !this.mayPlace(entityhuman, enumdirection, itemstack, blockposition1)) { + return InteractionResult.FAIL; + } else { +- Level level = context.getLevel(); +- HangingEntity hangingEntity; ++ Level world = context.getLevel(); ++ Object object; ++ + if (this.type == EntityType.PAINTING) { +- Optional optional = Painting.create(level, blockPos, clickedFace); ++ Optional optional = Painting.create(world, blockposition1, enumdirection); ++ + if (optional.isEmpty()) { + return InteractionResult.CONSUME; + } + +- hangingEntity = optional.get(); ++ object = (HangingEntity) optional.get(); + } else if (this.type == EntityType.ITEM_FRAME) { +- hangingEntity = new ItemFrame(level, blockPos, clickedFace); ++ object = new ItemFrame(world, blockposition1, enumdirection); + } else { + if (this.type != EntityType.GLOW_ITEM_FRAME) { +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } + +- hangingEntity = new GlowItemFrame(level, blockPos, clickedFace); ++ object = new GlowItemFrame(world, blockposition1, enumdirection); + } + +- CompoundTag tag = itemInHand.getTag(); +- if (tag != null) { +- EntityType.updateCustomEntityTag(level, player, hangingEntity, tag); ++ CompoundTag nbttagcompound = itemstack.getTag(); ++ ++ if (nbttagcompound != null) { ++ EntityType.updateCustomEntityTag(world, entityhuman, (Entity) object, nbttagcompound); + } + +- if (hangingEntity.survives()) { +- if (!level.isClientSide) { +- hangingEntity.playPlacementSound(); +- level.gameEvent(player, GameEvent.ENTITY_PLACE, hangingEntity.position()); +- level.addFreshEntity(hangingEntity); ++ if (((HangingEntity) object).survives()) { ++ if (!world.isClientSide) { ++ // CraftBukkit start - fire HangingPlaceEvent ++ Player who = (context.getPlayer() == null) ? null : (Player) context.getPlayer().getBukkitEntity(); ++ org.bukkit.block.Block blockClicked = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(enumdirection); ++ org.bukkit.inventory.EquipmentSlot hand = org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand()); ++ ++ HangingPlaceEvent event = new HangingPlaceEvent((org.bukkit.entity.Hanging) ((HangingEntity) object).getBukkitEntity(), who, blockClicked, blockFace, hand, org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return InteractionResult.FAIL; ++ } ++ // CraftBukkit end ++ ((HangingEntity) object).playPlacementSound(); ++ world.gameEvent((Entity) entityhuman, GameEvent.ENTITY_PLACE, ((HangingEntity) object).position()); ++ world.addFreshEntity((Entity) object); + } + +- itemInHand.shrink(1); +- return InteractionResult.sidedSuccess(level.isClientSide); ++ itemstack.shrink(1); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } else { + return InteractionResult.CONSUME; + } + } + } + +- protected boolean mayPlace(Player player, Direction direction, ItemStack hangingEntityStack, BlockPos pos) { ++ protected boolean mayPlace(net.minecraft.world.entity.player.Player player, Direction direction, ItemStack hangingEntityStack, BlockPos pos) { + return !direction.getAxis().isVertical() && player.mayUseItemAt(pos, direction, hangingEntityStack); + } + +@@ -88,36 +110,24 @@ + public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltipComponents, TooltipFlag isAdvanced) { + super.appendHoverText(stack, level, tooltipComponents, isAdvanced); + if (this.type == EntityType.PAINTING) { +- CompoundTag tag = stack.getTag(); +- if (tag != null && tag.contains("EntityTag", 10)) { +- CompoundTag compound = tag.getCompound("EntityTag"); +- Painting.loadVariant(compound) +- .ifPresentOrElse( +- holder -> { +- holder.unwrapKey() +- .ifPresent( +- resourceKey -> { +- tooltipComponents.add( +- Component.translatable(resourceKey.location().toLanguageKey("painting", "title")).withStyle(ChatFormatting.YELLOW) +- ); +- tooltipComponents.add( +- Component.translatable(resourceKey.location().toLanguageKey("painting", "author")).withStyle(ChatFormatting.GRAY) +- ); +- } +- ); +- tooltipComponents.add( +- Component.translatable( +- "painting.dimensions", +- Mth.positiveCeilDiv(holder.value().getWidth(), 16), +- Mth.positiveCeilDiv(holder.value().getHeight(), 16) +- ) +- ); +- }, +- () -> tooltipComponents.add(TOOLTIP_RANDOM_VARIANT) +- ); ++ CompoundTag nbttagcompound = stack.getTag(); ++ ++ if (nbttagcompound != null && nbttagcompound.contains("EntityTag", 10)) { ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("EntityTag"); ++ ++ Painting.loadVariant(nbttagcompound1).ifPresentOrElse((holder) -> { ++ holder.unwrapKey().ifPresent((resourcekey) -> { ++ tooltipComponents.add(Component.translatable(resourcekey.location().toLanguageKey("painting", "title")).withStyle(ChatFormatting.YELLOW)); ++ tooltipComponents.add(Component.translatable(resourcekey.location().toLanguageKey("painting", "author")).withStyle(ChatFormatting.GRAY)); ++ }); ++ tooltipComponents.add(Component.translatable("painting.dimensions", Mth.positiveCeilDiv(((PaintingVariant) holder.value()).getWidth(), 16), Mth.positiveCeilDiv(((PaintingVariant) holder.value()).getHeight(), 16))); ++ }, () -> { ++ tooltipComponents.add(HangingEntityItem.TOOLTIP_RANDOM_VARIANT); ++ }); + } else if (isAdvanced.isCreative()) { +- tooltipComponents.add(TOOLTIP_RANDOM_VARIANT); ++ tooltipComponents.add(HangingEntityItem.TOOLTIP_RANDOM_VARIANT); + } + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/ItemStack.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/ItemStack.java.patch new file mode 100644 index 0000000000..8f2b7a5500 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/ItemStack.java.patch @@ -0,0 +1,1384 @@ +--- a/net/minecraft/world/item/ItemStack.java ++++ b/net/minecraft/world/item/ItemStack.java +@@ -9,15 +9,15 @@ + import com.mojang.serialization.DataResult; + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import java.text.DecimalFormat; + import java.text.DecimalFormatSymbols; + import java.util.Collection; ++import java.util.Iterator; + import java.util.List; + import java.util.Locale; ++import java.util.Map.Entry; + import java.util.Objects; + import java.util.Optional; +-import java.util.Map.Entry; + import java.util.function.Consumer; + import java.util.function.Predicate; + import java.util.stream.Collectors; +@@ -28,6 +28,7 @@ + import net.minecraft.advancements.CriteriaTriggers; + import net.minecraft.commands.arguments.blocks.BlockStateParser; + import net.minecraft.core.BlockPos; ++import net.minecraft.core.Direction; + import net.minecraft.core.Holder; + import net.minecraft.core.HolderSet; + import net.minecraft.core.Registry; +@@ -35,6 +36,7 @@ + import net.minecraft.core.registries.Registries; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; ++import net.minecraft.nbt.NbtOps; + import net.minecraft.nbt.Tag; + import net.minecraft.nbt.TagParser; + import net.minecraft.network.chat.CommonComponents; +@@ -43,27 +45,24 @@ + import net.minecraft.network.chat.HoverEvent; + import net.minecraft.network.chat.MutableComponent; + import net.minecraft.network.chat.Style; ++import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; + import net.minecraft.resources.ResourceLocation; +-import net.minecraft.server.level.ServerPlayer; +-import net.minecraft.sounds.SoundEvent; +-import net.minecraft.stats.Stats; + import net.minecraft.tags.TagKey; + import net.minecraft.util.ExtraCodecs; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobType; + import net.minecraft.world.entity.SlotAccess; + import net.minecraft.world.entity.ai.attributes.Attribute; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.decoration.ItemFrame; + import net.minecraft.world.entity.item.ItemEntity; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.flag.FeatureFlagSet; + import net.minecraft.world.inventory.ClickAction; + import net.minecraft.world.inventory.Slot; +@@ -74,52 +73,81 @@ + import net.minecraft.world.item.enchantment.Enchantment; + import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.item.enchantment.Enchantments; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; ++import net.minecraft.world.level.block.BaseEntityBlock; ++import net.minecraft.world.level.block.BedBlock; + import net.minecraft.world.level.block.Block; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.pattern.BlockInWorld; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.mojang.serialization.Dynamic; ++import java.util.Map; ++import java.util.Objects; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundSource; ++import net.minecraft.stats.Stats; ++import net.minecraft.util.datafix.fixes.DataConverterTypes; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.SaplingBlock; ++import net.minecraft.world.level.block.SignBlock; ++import net.minecraft.world.level.block.SoundType; ++import net.minecraft.world.level.block.WitherSkullBlock; ++import net.minecraft.world.level.block.entity.BlockEntity; ++import net.minecraft.world.level.block.entity.JukeboxBlockEntity; ++import net.minecraft.world.level.block.entity.SignBlockEntity; ++import net.minecraft.world.level.block.entity.SkullBlockEntity; ++import net.minecraft.world.level.gameevent.GameEvent; ++import org.bukkit.Location; ++import org.bukkit.TreeType; ++import org.bukkit.block.BlockState; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.entity.Player; ++import org.bukkit.event.block.BlockFertilizeEvent; ++import org.bukkit.event.player.PlayerItemDamageEvent; ++import org.bukkit.event.world.StructureGrowEvent; ++// CraftBukkit end ++ + public final class ItemStack { +- public static final Codec CODEC = RecordCodecBuilder.create( +- instance -> instance.group( +- BuiltInRegistries.ITEM.holderByNameCodec().fieldOf("id").forGetter(ItemStack::getItemHolder), +- Codec.INT.fieldOf("Count").forGetter(ItemStack::getCount), +- CompoundTag.CODEC.optionalFieldOf("tag").forGetter(itemStack -> Optional.ofNullable(itemStack.getTag())) +- ) +- .apply(instance, ItemStack::new) +- ); +- private static final Codec ITEM_NON_AIR_CODEC = ExtraCodecs.validate( +- BuiltInRegistries.ITEM.byNameCodec(), item -> item == Items.AIR ? DataResult.error(() -> "Item must not be minecraft:air") : DataResult.success(item) +- ); +- public static final Codec ADVANCEMENT_ICON_CODEC = RecordCodecBuilder.create( +- instance -> instance.group( +- BuiltInRegistries.ITEM.holderByNameCodec().fieldOf("item").forGetter(ItemStack::getItemHolder), +- ExtraCodecs.strictOptionalField(TagParser.AS_CODEC, "nbt").forGetter(itemStack -> Optional.ofNullable(itemStack.getTag())) +- ) +- .apply(instance, (holder, optional) -> new ItemStack(holder, 1, optional)) +- ); +- public static final Codec ITEM_WITH_COUNT_CODEC = RecordCodecBuilder.create( +- instance -> instance.group( +- ITEM_NON_AIR_CODEC.fieldOf("item").forGetter(ItemStack::getItem), +- ExtraCodecs.strictOptionalField(ExtraCodecs.POSITIVE_INT, "count", 1).forGetter(ItemStack::getCount) +- ) +- .apply(instance, ItemStack::new) +- ); +- public static final Codec SINGLE_ITEM_CODEC = ITEM_NON_AIR_CODEC.xmap(ItemStack::new, ItemStack::getItem); +- public static final MapCodec RESULT_CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group( +- BuiltInRegistries.ITEM.byNameCodec().fieldOf("result").forGetter(ItemStack::getItem), +- Codec.INT.fieldOf("count").forGetter(ItemStack::getCount) +- ) +- .apply(instance, ItemStack::new) +- ); ++ ++ public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(BuiltInRegistries.ITEM.holderByNameCodec().fieldOf("id").forGetter(ItemStack::getItemHolder), Codec.INT.fieldOf("Count").forGetter(ItemStack::getCount), CompoundTag.CODEC.optionalFieldOf("tag").forGetter((itemstack) -> { ++ return Optional.ofNullable(itemstack.getTag()); ++ })).apply(instance, ItemStack::new); ++ }); ++ private static final Codec ITEM_NON_AIR_CODEC = ExtraCodecs.validate(BuiltInRegistries.ITEM.byNameCodec(), (item) -> { ++ return item == Items.AIR ? DataResult.error(() -> { ++ return "Item must not be minecraft:air"; ++ }) : DataResult.success(item); ++ }); ++ public static final Codec ADVANCEMENT_ICON_CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(BuiltInRegistries.ITEM.holderByNameCodec().fieldOf("item").forGetter(ItemStack::getItemHolder), ExtraCodecs.strictOptionalField(TagParser.AS_CODEC, "nbt").forGetter((itemstack) -> { ++ return Optional.ofNullable(itemstack.getTag()); ++ })).apply(instance, (holder, optional) -> { ++ return new ItemStack(holder, 1, optional); ++ }); ++ }); ++ public static final Codec ITEM_WITH_COUNT_CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(ItemStack.ITEM_NON_AIR_CODEC.fieldOf("item").forGetter(ItemStack::getItem), ExtraCodecs.strictOptionalField(ExtraCodecs.POSITIVE_INT, "count", 1).forGetter(ItemStack::getCount)).apply(instance, ItemStack::new); ++ }); ++ public static final Codec SINGLE_ITEM_CODEC = ItemStack.ITEM_NON_AIR_CODEC.xmap(ItemStack::new, ItemStack::getItem); ++ public static final MapCodec RESULT_CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(BuiltInRegistries.ITEM.byNameCodec().fieldOf("result").forGetter(ItemStack::getItem), Codec.INT.fieldOf("count").forGetter(ItemStack::getCount)).apply(instance, ItemStack::new); ++ }); + private static final Logger LOGGER = LogUtils.getLogger(); +- public static final ItemStack EMPTY = new ItemStack((Void)null); +- public static final DecimalFormat ATTRIBUTE_MODIFIER_FORMAT = Util.make( +- new DecimalFormat("#.##"), decimalFormat -> decimalFormat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)) +- ); ++ public static final ItemStack EMPTY = new ItemStack((Void) null); ++ public static final DecimalFormat ATTRIBUTE_MODIFIER_FORMAT = (DecimalFormat) Util.make(new DecimalFormat("#.##"), (decimalformat) -> { ++ decimalformat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)); ++ }); + public static final String TAG_ENCH = "Enchantments"; + public static final String TAG_DISPLAY = "display"; + public static final String TAG_DISPLAY_NAME = "Name"; +@@ -136,9 +164,10 @@ + private static final Style LORE_STYLE = Style.EMPTY.withColor(ChatFormatting.DARK_PURPLE).withItalic(true); + private int count; + private int popTime; ++ /** @deprecated */ + @Deprecated + @Nullable +- private final Item item; ++ private Item item; + @Nullable + private CompoundTag tag; + @Nullable +@@ -152,12 +181,12 @@ + return this.getItem().getTooltipImage(this); + } + +- public ItemStack(ItemLike item) { ++ public ItemStack(IMaterial item) { + this(item, 1); + } + + public ItemStack(Holder tag) { +- this(tag.value(), 1); ++ this((IMaterial) tag.value(), 1); + } + + public ItemStack(Holder item, int count, Optional optional) { +@@ -166,45 +195,63 @@ + } + + public ItemStack(Holder item, int count) { +- this(item.value(), count); ++ this((IMaterial) item.value(), count); + } + +- public ItemStack(ItemLike item, int count) { ++ public ItemStack(IMaterial item, int count) { + this.item = item.asItem(); + this.count = count; + if (this.item.canBeDepleted()) { + this.setDamageValue(this.getDamageValue()); + } ++ + } + +- private ItemStack(@Nullable Void _void) { ++ private ItemStack(@Nullable Void ovoid) { + this.item = null; + } + +- private ItemStack(CompoundTag compoundTag) { +- this.item = BuiltInRegistries.ITEM.get(new ResourceLocation(compoundTag.getString("id"))); +- this.count = compoundTag.getByte("Count"); +- if (compoundTag.contains("tag", 10)) { +- this.tag = compoundTag.getCompound("tag").copy(); ++ // Called to run this stack through the data converter to handle older storage methods and serialized items ++ public void convertStack(int version) { ++ if (0 < version && version < CraftMagicNumbers.INSTANCE.getDataVersion()) { ++ CompoundTag savedStack = new CompoundTag(); ++ this.save(savedStack); ++ savedStack = (CompoundTag) MinecraftServer.getServer().fixerUpper.update(DataConverterTypes.ITEM_STACK, new Dynamic(NbtOps.INSTANCE, savedStack), version, CraftMagicNumbers.INSTANCE.getDataVersion()).getValue(); ++ this.load(savedStack); ++ } ++ } ++ ++ // CraftBukkit - break into own method ++ private void load(CompoundTag nbttagcompound) { ++ this.item = (Item) BuiltInRegistries.ITEM.get(new ResourceLocation(nbttagcompound.getString("id"))); ++ this.count = nbttagcompound.getByte("Count"); ++ if (nbttagcompound.contains("tag", 10)) { ++ this.tag = nbttagcompound.getCompound("tag").copy(); + this.getItem().verifyTagAfterLoad(this.tag); + } + + if (this.getItem().canBeDepleted()) { + this.setDamageValue(this.getDamageValue()); + } ++ + } + ++ private ItemStack(CompoundTag compoundTag) { ++ this.load(compoundTag); ++ // CraftBukkit end ++ } ++ + public static ItemStack of(CompoundTag compoundTag) { + try { + return new ItemStack(compoundTag); +- } catch (RuntimeException var2) { +- LOGGER.debug("Tried to load invalid item: {}", compoundTag, var2); +- return EMPTY; ++ } catch (RuntimeException runtimeexception) { ++ ItemStack.LOGGER.debug("Tried to load invalid item: {}", compoundTag, runtimeexception); ++ return ItemStack.EMPTY; + } + } + + public boolean isEmpty() { +- return this == EMPTY || this.item == Items.AIR || this.count <= 0; ++ return this == ItemStack.EMPTY || this.item == Items.AIR || this.count <= 0; + } + + public boolean isItemEnabled(FeatureFlagSet enabledFlags) { +@@ -212,19 +259,21 @@ + } + + public ItemStack split(int amount) { +- int min = Math.min(amount, this.getCount()); +- ItemStack itemStack = this.copyWithCount(min); +- this.shrink(min); +- return itemStack; ++ int j = Math.min(amount, this.getCount()); ++ ItemStack itemstack = this.copyWithCount(j); ++ ++ this.shrink(j); ++ return itemstack; + } + + public ItemStack copyAndClear() { + if (this.isEmpty()) { +- return EMPTY; ++ return ItemStack.EMPTY; + } else { +- ItemStack itemStack = this.copy(); ++ ItemStack itemstack = this.copy(); ++ + this.setCount(0); +- return itemStack; ++ return itemstack; + } + } + +@@ -252,8 +301,8 @@ + return this.getItem().builtInRegistryHolder() == item; + } + +- public boolean is(HolderSet holderSet) { +- return holderSet.contains(this.getItemHolder()); ++ public boolean is(HolderSet holderset) { ++ return holderset.contains(this.getItemHolder()); + } + + public Stream> getTags() { +@@ -261,29 +310,208 @@ + } + + public InteractionResult useOn(UseOnContext context) { +- Player player = context.getPlayer(); +- BlockPos clickedPos = context.getClickedPos(); +- BlockInWorld blockInWorld = new BlockInWorld(context.getLevel(), clickedPos, false); +- if (player != null +- && !player.getAbilities().mayBuild +- && !this.hasAdventureModePlaceTagForBlock(context.getLevel().registryAccess().registryOrThrow(Registries.BLOCK), blockInWorld)) { ++ net.minecraft.world.entity.player.Player entityhuman = context.getPlayer(); ++ BlockPos blockposition = context.getClickedPos(); ++ BlockInWorld shapedetectorblock = new BlockInWorld(context.getLevel(), blockposition, false); ++ ++ if (entityhuman != null && !entityhuman.getAbilities().mayBuild && !this.hasAdventureModePlaceTagForBlock(context.getLevel().registryAccess().registryOrThrow(Registries.BLOCK), shapedetectorblock)) { + return InteractionResult.PASS; + } else { + Item item = this.getItem(); +- InteractionResult interactionResult = item.useOn(context); +- if (player != null && interactionResult.shouldAwardStats()) { +- player.awardStat(Stats.ITEM_USED.get(item)); ++ // CraftBukkit start - handle all block place event logic here ++ CompoundTag oldData = this.getTagClone(); ++ int oldCount = this.getCount(); ++ ServerLevel world = (ServerLevel) context.getLevel(); ++ ++ if (!(item instanceof BucketItem || item instanceof SolidBucketItem)) { // if not bucket ++ world.captureBlockStates = true; ++ // special case bonemeal ++ if (item == Items.BONE_MEAL) { ++ world.captureTreeGeneration = true; ++ } + } ++ InteractionResult enuminteractionresult; ++ try { ++ enuminteractionresult = item.useOn(context); ++ } finally { ++ world.captureBlockStates = false; ++ } ++ CompoundTag newData = this.getTagClone(); ++ int newCount = this.getCount(); ++ this.setCount(oldCount); ++ this.setTagClone(oldData); ++ if (enuminteractionresult.consumesAction() && world.captureTreeGeneration && world.capturedBlockStates.size() > 0) { ++ world.captureTreeGeneration = false; ++ Location location = CraftLocation.toBukkit(blockposition, world.getWorld()); ++ TreeType treeType = SaplingBlock.treeType; ++ SaplingBlock.treeType = null; ++ List blocks = new java.util.ArrayList<>(world.capturedBlockStates.values()); ++ world.capturedBlockStates.clear(); ++ StructureGrowEvent structureEvent = null; ++ if (treeType != null) { ++ boolean isBonemeal = getItem() == Items.BONE_MEAL; ++ structureEvent = new StructureGrowEvent(location, treeType, isBonemeal, (Player) entityhuman.getBukkitEntity(), (List< BlockState>) (List) blocks); ++ org.bukkit.Bukkit.getPluginManager().callEvent(structureEvent); ++ } + +- return interactionResult; ++ BlockFertilizeEvent fertilizeEvent = new BlockFertilizeEvent(CraftBlock.at(world, blockposition), (Player) entityhuman.getBukkitEntity(), (List< BlockState>) (List) blocks); ++ fertilizeEvent.setCancelled(structureEvent != null && structureEvent.isCancelled()); ++ org.bukkit.Bukkit.getPluginManager().callEvent(fertilizeEvent); ++ ++ if (!fertilizeEvent.isCancelled()) { ++ // Change the stack to its new contents if it hasn't been tampered with. ++ if (this.getCount() == oldCount && Objects.equals(this.tag, oldData)) { ++ this.setTag(newData); ++ this.setCount(newCount); ++ } ++ for (CraftBlockState blockstate : blocks) { ++ world.setBlock(blockstate.getPosition(),blockstate.getHandle(), blockstate.getFlag()); // SPIGOT-7248 - manual update to avoid physics where appropriate ++ } ++ entityhuman.awardStat(Stats.ITEM_USED.get(item)); // SPIGOT-7236 - award stat ++ } ++ ++ SignItem.openSign = null; // SPIGOT-6758 - Reset on early return ++ return enuminteractionresult; ++ } ++ world.captureTreeGeneration = false; ++ ++ if (entityhuman != null && enuminteractionresult.shouldAwardStats()) { ++ EnumHand enumhand = context.getHand(); ++ org.bukkit.event.block.BlockPlaceEvent placeEvent = null; ++ List blocks = new java.util.ArrayList<>(world.capturedBlockStates.values()); ++ world.capturedBlockStates.clear(); ++ if (blocks.size() > 1) { ++ placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockMultiPlaceEvent(world, entityhuman, enumhand, blocks, blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ } else if (blocks.size() == 1) { ++ placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEvent(world, entityhuman, enumhand, blocks.get(0), blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ } ++ ++ if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild())) { ++ enuminteractionresult = InteractionResult.FAIL; // cancel placement ++ // PAIL: Remove this when MC-99075 fixed ++ placeEvent.getPlayer().updateInventory(); ++ // revert back all captured blocks ++ world.preventPoiUpdated = true; // CraftBukkit - SPIGOT-5710 ++ for (BlockState blockstate : blocks) { ++ blockstate.update(true, false); ++ } ++ world.preventPoiUpdated = false; ++ ++ // Brute force all possible updates ++ BlockPos placedPos = ((CraftBlock) placeEvent.getBlock()).getPosition(); ++ for (Direction dir : Direction.values()) { ++ ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, placedPos.relative(dir))); ++ } ++ SignItem.openSign = null; // SPIGOT-6758 - Reset on early return ++ } else { ++ // Change the stack to its new contents if it hasn't been tampered with. ++ if (this.getCount() == oldCount && Objects.equals(this.tag, oldData)) { ++ this.setTag(newData); ++ this.setCount(newCount); ++ } ++ ++ for (Map.Entry e : world.capturedTileEntities.entrySet()) { ++ world.setBlockEntity(e.getValue()); ++ } ++ ++ for (BlockState blockstate : blocks) { ++ int updateFlag = ((CraftBlockState) blockstate).getFlag(); ++ IBlockData oldBlock = ((CraftBlockState) blockstate).getHandle(); ++ BlockPos newblockposition = ((CraftBlockState) blockstate).getPosition(); ++ IBlockData block = world.getBlockState(newblockposition); ++ ++ if (!(block.getBlock() instanceof BaseEntityBlock)) { // Containers get placed automatically ++ block.getBlock().onPlace(block, world, newblockposition, oldBlock, true); ++ } ++ ++ world.notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, world.getBlockState(newblockposition), updateFlag, 512); // send null chunk as chunk.k() returns false by this point ++ } ++ ++ // Special case juke boxes as they update their tile entity. Copied from ItemRecord. ++ // PAIL: checkme on updates. ++ if (this.item instanceof RecordItem) { ++ BlockEntity tileentity = world.getBlockEntity(blockposition); ++ ++ if (tileentity instanceof JukeboxBlockEntity) { ++ JukeboxBlockEntity tileentityjukebox = (JukeboxBlockEntity) tileentity; ++ ++ // There can only be one ++ ItemStack record = this.copy(); ++ if (!record.isEmpty()) { ++ record.setCount(1); ++ } ++ ++ tileentityjukebox.setTheItem(record); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entityhuman, world.getBlockState(blockposition))); ++ } ++ ++ this.shrink(1); ++ entityhuman.awardStat(Stats.PLAY_RECORD); ++ } ++ ++ if (this.item == Items.WITHER_SKELETON_SKULL) { // Special case skulls to allow wither spawns to be cancelled ++ BlockPos bp = blockposition; ++ if (!world.getBlockState(blockposition).canBeReplaced()) { ++ if (!world.getBlockState(blockposition).isSolid()) { ++ bp = null; ++ } else { ++ bp = bp.relative(context.getClickedFace()); ++ } ++ } ++ if (bp != null) { ++ BlockEntity te = world.getBlockEntity(bp); ++ if (te instanceof SkullBlockEntity) { ++ WitherSkullBlock.checkSpawn(world, bp, (SkullBlockEntity) te); ++ } ++ } ++ } ++ ++ // SPIGOT-4678 ++ if (this.item instanceof SignItem && SignItem.openSign != null) { ++ try { ++ if (world.getBlockEntity(SignItem.openSign) instanceof SignBlockEntity tileentitysign) { ++ if (world.getBlockState(SignItem.openSign).getBlock() instanceof SignBlock blocksign) { ++ blocksign.openTextEdit(entityhuman, tileentitysign, true, org.bukkit.event.player.PlayerSignOpenEvent.Cause.PLACE); // Craftbukkit ++ } ++ } ++ } finally { ++ SignItem.openSign = null; ++ } ++ } ++ ++ // SPIGOT-7315: Moved from BlockBed#setPlacedBy ++ if (placeEvent != null && this.item instanceof BedItem) { ++ BlockPos position = ((CraftBlock) placeEvent.getBlock()).getPosition(); ++ IBlockData blockData = world.getBlockState(position); ++ ++ if (blockData.getBlock() instanceof BedBlock) { ++ world.blockUpdated(position, Blocks.AIR); ++ blockData.updateNeighbourShapes(world, position, 3); ++ } ++ } ++ ++ // SPIGOT-1288 - play sound stripped from ItemBlock ++ if (this.item instanceof BlockItem) { ++ SoundType soundeffecttype = ((BlockItem) this.item).getBlock().defaultBlockState().getSoundType(); // TODO: not strictly correct, however currently only affects decorated pots ++ world.playSound(entityhuman, blockposition, soundeffecttype.getPlaceSound(), SoundSource.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F); ++ } ++ ++ entityhuman.awardStat(Stats.ITEM_USED.get(item)); ++ } ++ } ++ world.capturedTileEntities.clear(); ++ world.capturedBlockStates.clear(); ++ // CraftBukkit end ++ ++ return enuminteractionresult; + } + } + +- public float getDestroySpeed(BlockState state) { ++ public float getDestroySpeed(IBlockData state) { + return this.getItem().getDestroySpeed(this, state); + } + +- public InteractionResultHolder use(Level level, Player player, InteractionHand usedHand) { ++ public InteractionResultHolder use(Level level, net.minecraft.world.entity.player.Player player, EnumHand usedHand) { + return this.getItem().use(level, player, usedHand); + } + +@@ -292,9 +520,10 @@ + } + + public CompoundTag save(CompoundTag compoundTag) { +- ResourceLocation key = BuiltInRegistries.ITEM.getKey(this.getItem()); +- compoundTag.putString("id", key == null ? "minecraft:air" : key.toString()); +- compoundTag.putByte("Count", (byte)this.count); ++ ResourceLocation minecraftkey = BuiltInRegistries.ITEM.getKey(this.getItem()); ++ ++ compoundTag.putString("id", minecraftkey == null ? "minecraft:air" : minecraftkey.toString()); ++ compoundTag.putByte("Count", (byte) this.count); + if (this.tag != null) { + compoundTag.put("tag", this.tag.copy()); + } +@@ -312,8 +541,9 @@ + + public boolean isDamageableItem() { + if (!this.isEmpty() && this.getItem().getMaxDamage() > 0) { +- CompoundTag tag = this.getTag(); +- return tag == null || !tag.getBoolean("Unbreakable"); ++ CompoundTag nbttagcompound = this.getTag(); ++ ++ return nbttagcompound == null || !nbttagcompound.getBoolean("Unbreakable"); + } else { + return false; + } +@@ -339,17 +569,34 @@ + if (!this.isDamageableItem()) { + return false; + } else { ++ int j; ++ + if (amount > 0) { +- int itemEnchantmentLevel = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.UNBREAKING, this); +- int i = 0; ++ j = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.UNBREAKING, this); ++ int k = 0; + +- for (int i1 = 0; itemEnchantmentLevel > 0 && i1 < amount; i1++) { +- if (DigDurabilityEnchantment.shouldIgnoreDurabilityDrop(this, itemEnchantmentLevel, random)) { +- i++; ++ for (int l = 0; j > 0 && l < amount; ++l) { ++ if (DigDurabilityEnchantment.shouldIgnoreDurabilityDrop(this, j, random)) { ++ ++k; + } + } + +- amount -= i; ++ amount -= k; ++ // CraftBukkit start ++ if (user != null) { ++ PlayerItemDamageEvent event = new PlayerItemDamageEvent(user.getBukkitEntity(), CraftItemStack.asCraftMirror(this), amount); ++ event.getPlayer().getServer().getPluginManager().callEvent(event); ++ ++ if (amount != event.getDamage() || event.isCancelled()) { ++ event.getPlayer().updateInventory(); ++ } ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ amount = event.getDamage(); ++ } ++ // CraftBukkit end + if (amount <= 0) { + return false; + } +@@ -359,25 +606,32 @@ + CriteriaTriggers.ITEM_DURABILITY_CHANGED.trigger(user, this, this.getDamageValue() + amount); + } + +- int itemEnchantmentLevel = this.getDamageValue() + amount; +- this.setDamageValue(itemEnchantmentLevel); +- return itemEnchantmentLevel >= this.getMaxDamage(); ++ j = this.getDamageValue() + amount; ++ this.setDamageValue(j); ++ return j >= this.getMaxDamage(); + } + } + + public void hurtAndBreak(int amount, T entity, Consumer onBroken) { +- if (!entity.level().isClientSide && (!(entity instanceof Player) || !((Player)entity).getAbilities().instabuild)) { ++ if (!entity.level().isClientSide && (!(entity instanceof net.minecraft.world.entity.player.Player) || !((net.minecraft.world.entity.player.Player) entity).getAbilities().instabuild)) { + if (this.isDamageableItem()) { +- if (this.hurt(amount, entity.getRandom(), entity instanceof ServerPlayer ? (ServerPlayer)entity : null)) { ++ if (this.hurt(amount, entity.getRandom(), entity instanceof ServerPlayer ? (ServerPlayer) entity : null)) { + onBroken.accept(entity); + Item item = this.getItem(); ++ // CraftBukkit start - Check for item breaking ++ if (this.count == 1 && entity instanceof net.minecraft.world.entity.player.Player) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemBreakEvent((net.minecraft.world.entity.player.Player) entity, this); ++ } ++ // CraftBukkit end ++ + this.shrink(1); +- if (entity instanceof Player) { +- ((Player)entity).awardStat(Stats.ITEM_BROKEN.get(item)); ++ if (entity instanceof net.minecraft.world.entity.player.Player) { ++ ((net.minecraft.world.entity.player.Player) entity).awardStat(Stats.ITEM_BROKEN.get(item)); + } + + this.setDamageValue(0); + } ++ + } + } + } +@@ -394,62 +648,68 @@ + return this.getItem().getBarColor(this); + } + +- public boolean overrideStackedOnOther(Slot slot, ClickAction action, Player player) { ++ public boolean overrideStackedOnOther(Slot slot, ClickAction action, net.minecraft.world.entity.player.Player player) { + return this.getItem().overrideStackedOnOther(this, slot, action, player); + } + +- public boolean overrideOtherStackedOnMe(ItemStack stack, Slot slot, ClickAction action, Player player, SlotAccess access) { ++ public boolean overrideOtherStackedOnMe(ItemStack stack, Slot slot, ClickAction action, net.minecraft.world.entity.player.Player player, SlotAccess access) { + return this.getItem().overrideOtherStackedOnMe(this, stack, slot, action, player, access); + } + +- public void hurtEnemy(LivingEntity entity, Player player) { ++ public void hurtEnemy(LivingEntity entity, net.minecraft.world.entity.player.Player player) { + Item item = this.getItem(); ++ + if (item.hurtEnemy(this, entity, player)) { + player.awardStat(Stats.ITEM_USED.get(item)); + } ++ + } + +- public void mineBlock(Level level, BlockState state, BlockPos pos, Player player) { ++ public void mineBlock(Level level, IBlockData state, BlockPos pos, net.minecraft.world.entity.player.Player player) { + Item item = this.getItem(); ++ + if (item.mineBlock(this, level, state, pos, player)) { + player.awardStat(Stats.ITEM_USED.get(item)); + } ++ + } + +- public boolean isCorrectToolForDrops(BlockState state) { ++ public boolean isCorrectToolForDrops(IBlockData state) { + return this.getItem().isCorrectToolForDrops(state); + } + +- public InteractionResult interactLivingEntity(Player player, LivingEntity entity, InteractionHand usedHand) { ++ public InteractionResult interactLivingEntity(net.minecraft.world.entity.player.Player player, LivingEntity entity, EnumHand usedHand) { + return this.getItem().interactLivingEntity(this, player, entity, usedHand); + } + + public ItemStack copy() { + if (this.isEmpty()) { +- return EMPTY; ++ return ItemStack.EMPTY; + } else { +- ItemStack itemStack = new ItemStack(this.getItem(), this.count); +- itemStack.setPopTime(this.getPopTime()); ++ ItemStack itemstack = new ItemStack(this.getItem(), this.count); ++ ++ itemstack.setPopTime(this.getPopTime()); + if (this.tag != null) { +- itemStack.tag = this.tag.copy(); ++ itemstack.tag = this.tag.copy(); + } + +- return itemStack; ++ return itemstack; + } + } + + public ItemStack copyWithCount(int count) { + if (this.isEmpty()) { +- return EMPTY; ++ return ItemStack.EMPTY; + } else { +- ItemStack itemStack = this.copy(); +- itemStack.setCount(count); +- return itemStack; ++ ItemStack itemstack = this.copy(); ++ ++ itemstack.setCount(count); ++ return itemstack; + } + } + + public static boolean matches(ItemStack stack, ItemStack other) { +- return stack == other || stack.getCount() == other.getCount() && isSameItemSameTags(stack, other); ++ return stack == other ? true : (stack.getCount() != other.getCount() ? false : isSameItemSameTags(stack, other)); + } + + public static boolean isSameItem(ItemStack stack, ItemStack other) { +@@ -457,42 +717,44 @@ + } + + public static boolean isSameItemSameTags(ItemStack stack, ItemStack other) { +- return stack.is(other.getItem()) && (stack.isEmpty() && other.isEmpty() || Objects.equals(stack.tag, other.tag)); ++ return !stack.is(other.getItem()) ? false : (stack.isEmpty() && other.isEmpty() ? true : Objects.equals(stack.tag, other.tag)); + } + + public String getDescriptionId() { + return this.getItem().getDescriptionId(this); + } + +- @Override + public String toString() { +- return this.getCount() + " " + this.getItem(); ++ int i = this.getCount(); ++ ++ return i + " " + this.getItem(); + } + + public void inventoryTick(Level level, Entity entity, int inventorySlot, boolean isCurrentItem) { + if (this.popTime > 0) { +- this.popTime--; ++ --this.popTime; + } + + if (this.getItem() != null) { + this.getItem().inventoryTick(this, level, entity, inventorySlot, isCurrentItem); + } ++ + } + +- public void onCraftedBy(Level level, Player player, int amount) { ++ public void onCraftedBy(Level level, net.minecraft.world.entity.player.Player player, int amount) { + player.awardStat(Stats.ITEM_CRAFTED.get(this.getItem()), amount); + this.getItem().onCraftedBy(this, level, player); + } + +- public void onCraftedBySystem(Level level) { +- this.getItem().onCraftedPostProcess(this, level); ++ public void onCraftedBySystem(Level world) { ++ this.getItem().onCraftedPostProcess(this, world); + } + + public int getUseDuration() { + return this.getItem().getUseDuration(this); + } + +- public UseAnim getUseAnimation() { ++ public EnumAnimation getUseAnimation() { + return this.getItem().getUseAnimation(this); + } + +@@ -513,6 +775,17 @@ + return this.tag; + } + ++ // CraftBukkit start ++ @Nullable ++ private CompoundTag getTagClone() { ++ return this.tag == null ? null : this.tag.copy(); ++ } ++ ++ private void setTagClone(@Nullable CompoundTag nbtttagcompound) { ++ this.setTag(nbtttagcompound == null ? null : nbtttagcompound.copy()); ++ } ++ // CraftBukkit end ++ + public CompoundTag getOrCreateTag() { + if (this.tag == null) { + this.setTag(new CompoundTag()); +@@ -525,9 +798,10 @@ + if (this.tag != null && this.tag.contains(key, 10)) { + return this.tag.getCompound(key); + } else { +- CompoundTag compoundTag = new CompoundTag(); +- this.addTagElement(key, compoundTag); +- return compoundTag; ++ CompoundTag nbttagcompound = new CompoundTag(); ++ ++ this.addTagElement(key, nbttagcompound); ++ return nbttagcompound; + } + } + +@@ -543,6 +817,7 @@ + this.tag = null; + } + } ++ + } + + public ListTag getEnchantmentTags() { +@@ -558,20 +833,23 @@ + if (compoundTag != null) { + this.getItem().verifyTagAfterLoad(compoundTag); + } ++ + } + + public Component getHoverName() { +- CompoundTag tagElement = this.getTagElement("display"); +- if (tagElement != null && tagElement.contains("Name", 8)) { ++ CompoundTag nbttagcompound = this.getTagElement("display"); ++ ++ if (nbttagcompound != null && nbttagcompound.contains("Name", 8)) { + try { +- Component component = Component.Serializer.fromJson(tagElement.getString("Name")); +- if (component != null) { +- return component; ++ MutableComponent ichatmutablecomponent = Component.Serializer.fromJson(nbttagcompound.getString("Name")); ++ ++ if (ichatmutablecomponent != null) { ++ return ichatmutablecomponent; + } + +- tagElement.remove("Name"); +- } catch (Exception var3) { +- tagElement.remove("Name"); ++ nbttagcompound.remove("Name"); ++ } catch (Exception exception) { ++ nbttagcompound.remove("Name"); + } + } + +@@ -579,21 +857,23 @@ + } + + public ItemStack setHoverName(@Nullable Component nameComponent) { +- CompoundTag tagElement = this.getOrCreateTagElement("display"); ++ CompoundTag nbttagcompound = this.getOrCreateTagElement("display"); ++ + if (nameComponent != null) { +- tagElement.putString("Name", Component.Serializer.toJson(nameComponent)); ++ nbttagcompound.putString("Name", Component.Serializer.toJson(nameComponent)); + } else { +- tagElement.remove("Name"); ++ nbttagcompound.remove("Name"); + } + + return this; + } + + public void resetHoverName() { +- CompoundTag tagElement = this.getTagElement("display"); +- if (tagElement != null) { +- tagElement.remove("Name"); +- if (tagElement.isEmpty()) { ++ CompoundTag nbttagcompound = this.getTagElement("display"); ++ ++ if (nbttagcompound != null) { ++ nbttagcompound.remove("Name"); ++ if (nbttagcompound.isEmpty()) { + this.removeTagKey("display"); + } + } +@@ -601,136 +881,132 @@ + if (this.tag != null && this.tag.isEmpty()) { + this.tag = null; + } ++ + } + + public boolean hasCustomHoverName() { +- CompoundTag tagElement = this.getTagElement("display"); +- return tagElement != null && tagElement.contains("Name", 8); ++ CompoundTag nbttagcompound = this.getTagElement("display"); ++ ++ return nbttagcompound != null && nbttagcompound.contains("Name", 8); + } + +- public List getTooltipLines(@Nullable Player player, TooltipFlag isAdvanced) { ++ public List getTooltipLines(@Nullable net.minecraft.world.entity.player.Player player, TooltipFlag isAdvanced) { + List list = Lists.newArrayList(); +- MutableComponent mutableComponent = Component.empty().append(this.getHoverName()).withStyle(this.getRarity().color); ++ MutableComponent ichatmutablecomponent = Component.empty().append(this.getHoverName()).withStyle(this.getRarity().color); ++ + if (this.hasCustomHoverName()) { +- mutableComponent.withStyle(ChatFormatting.ITALIC); ++ ichatmutablecomponent.withStyle(ChatFormatting.ITALIC); + } + +- list.add(mutableComponent); ++ list.add(ichatmutablecomponent); + if (!isAdvanced.isAdvanced() && !this.hasCustomHoverName() && this.is(Items.FILLED_MAP)) { +- Integer mapId = MapItem.getMapId(this); +- if (mapId != null) { ++ Integer integer = MapItem.getMapId(this); ++ ++ if (integer != null) { + list.add(MapItem.getTooltipForId(this)); + } + } + +- int hideFlags = this.getHideFlags(); +- if (shouldShowInTooltip(hideFlags, ItemStack.TooltipPart.ADDITIONAL)) { ++ int i = this.getHideFlags(); ++ ++ if (shouldShowInTooltip(i, ItemStack.HideFlags.ADDITIONAL)) { + this.getItem().appendHoverText(this, player == null ? null : player.level(), list, isAdvanced); + } + ++ int j; ++ + if (this.hasTag()) { +- if (shouldShowInTooltip(hideFlags, ItemStack.TooltipPart.UPGRADES) && player != null) { ++ if (shouldShowInTooltip(i, ItemStack.HideFlags.UPGRADES) && player != null) { + ArmorTrim.appendUpgradeHoverText(this, player.level().registryAccess(), list); + } + +- if (shouldShowInTooltip(hideFlags, ItemStack.TooltipPart.ENCHANTMENTS)) { ++ if (shouldShowInTooltip(i, ItemStack.HideFlags.ENCHANTMENTS)) { + appendEnchantmentNames(list, this.getEnchantmentTags()); + } + + if (this.tag.contains("display", 10)) { +- CompoundTag compound = this.tag.getCompound("display"); +- if (shouldShowInTooltip(hideFlags, ItemStack.TooltipPart.DYE) && compound.contains("color", 99)) { ++ CompoundTag nbttagcompound = this.tag.getCompound("display"); ++ ++ if (shouldShowInTooltip(i, ItemStack.HideFlags.DYE) && nbttagcompound.contains("color", 99)) { + if (isAdvanced.isAdvanced()) { +- list.add( +- Component.translatable("item.color", String.format(Locale.ROOT, "#%06X", compound.getInt("color"))).withStyle(ChatFormatting.GRAY) +- ); ++ list.add(Component.translatable("item.color", String.format(Locale.ROOT, "#%06X", nbttagcompound.getInt("color"))).withStyle(ChatFormatting.GRAY)); + } else { + list.add(Component.translatable("item.dyed").withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC)); + } + } + +- if (compound.getTagType("Lore") == 9) { +- ListTag list1 = compound.getList("Lore", 8); ++ if (nbttagcompound.getTagType("Lore") == 9) { ++ ListTag nbttaglist = nbttagcompound.getList("Lore", 8); + +- for (int i = 0; i < list1.size(); i++) { +- String string = list1.getString(i); ++ for (j = 0; j < nbttaglist.size(); ++j) { ++ String s = nbttaglist.getString(j); + + try { +- MutableComponent mutableComponent1 = Component.Serializer.fromJson(string); +- if (mutableComponent1 != null) { +- list.add(ComponentUtils.mergeStyles(mutableComponent1, LORE_STYLE)); ++ MutableComponent ichatmutablecomponent1 = Component.Serializer.fromJson(s); ++ ++ if (ichatmutablecomponent1 != null) { ++ list.add(ComponentUtils.mergeStyles(ichatmutablecomponent1, ItemStack.LORE_STYLE)); + } +- } catch (Exception var19) { +- compound.remove("Lore"); ++ } catch (Exception exception) { ++ nbttagcompound.remove("Lore"); + } + } + } + } + } + +- if (shouldShowInTooltip(hideFlags, ItemStack.TooltipPart.MODIFIERS)) { +- for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) { +- Multimap attributeModifiers = this.getAttributeModifiers(equipmentSlot); +- if (!attributeModifiers.isEmpty()) { ++ int k; ++ ++ if (shouldShowInTooltip(i, ItemStack.HideFlags.MODIFIERS)) { ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ ++ k = aenumitemslot.length; ++ ++ for (j = 0; j < k; ++j) { ++ EquipmentSlot enumitemslot = aenumitemslot[j]; ++ Multimap multimap = this.getAttributeModifiers(enumitemslot); ++ ++ if (!multimap.isEmpty()) { + list.add(CommonComponents.EMPTY); +- list.add(Component.translatable("item.modifiers." + equipmentSlot.getName()).withStyle(ChatFormatting.GRAY)); ++ list.add(Component.translatable("item.modifiers." + enumitemslot.getName()).withStyle(ChatFormatting.GRAY)); ++ Iterator iterator = multimap.entries().iterator(); + +- for (Entry entry : attributeModifiers.entries()) { +- AttributeModifier attributeModifier = entry.getValue(); +- double amount = attributeModifier.getAmount(); ++ while (iterator.hasNext()) { ++ Entry entry = (Entry) iterator.next(); ++ AttributeModifier attributemodifier = (AttributeModifier) entry.getValue(); ++ double d0 = attributemodifier.getAmount(); + boolean flag = false; ++ + if (player != null) { +- if (attributeModifier.getId() == Item.BASE_ATTACK_DAMAGE_UUID) { +- amount += player.getAttributeBaseValue(Attributes.ATTACK_DAMAGE); +- amount += (double)EnchantmentHelper.getDamageBonus(this, MobType.UNDEFINED); ++ if (attributemodifier.getId() == Item.BASE_ATTACK_DAMAGE_UUID) { ++ d0 += player.getAttributeBaseValue(Attributes.ATTACK_DAMAGE); ++ d0 += (double) EnchantmentHelper.getDamageBonus(this, EnumMonsterType.UNDEFINED); + flag = true; +- } else if (attributeModifier.getId() == Item.BASE_ATTACK_SPEED_UUID) { +- amount += player.getAttributeBaseValue(Attributes.ATTACK_SPEED); ++ } else if (attributemodifier.getId() == Item.BASE_ATTACK_SPEED_UUID) { ++ d0 += player.getAttributeBaseValue(Attributes.ATTACK_SPEED); + flag = true; + } + } + +- double d; +- if (attributeModifier.getOperation() == AttributeModifier.Operation.MULTIPLY_BASE +- || attributeModifier.getOperation() == AttributeModifier.Operation.MULTIPLY_TOTAL) { +- d = amount * 100.0; +- } else if (entry.getKey().equals(Attributes.KNOCKBACK_RESISTANCE)) { +- d = amount * 10.0; ++ double d1; ++ ++ if (attributemodifier.getOperation() != AttributeModifier.Operation.MULTIPLY_BASE && attributemodifier.getOperation() != AttributeModifier.Operation.MULTIPLY_TOTAL) { ++ if (((Attribute) entry.getKey()).equals(Attributes.KNOCKBACK_RESISTANCE)) { ++ d1 = d0 * 10.0D; ++ } else { ++ d1 = d0; ++ } + } else { +- d = amount; ++ d1 = d0 * 100.0D; + } + + if (flag) { +- list.add( +- CommonComponents.space() +- .append( +- Component.translatable( +- "attribute.modifier.equals." + attributeModifier.getOperation().toValue(), +- ATTRIBUTE_MODIFIER_FORMAT.format(d), +- Component.translatable(entry.getKey().getDescriptionId()) +- ) +- ) +- .withStyle(ChatFormatting.DARK_GREEN) +- ); +- } else if (amount > 0.0) { +- list.add( +- Component.translatable( +- "attribute.modifier.plus." + attributeModifier.getOperation().toValue(), +- ATTRIBUTE_MODIFIER_FORMAT.format(d), +- Component.translatable(entry.getKey().getDescriptionId()) +- ) +- .withStyle(ChatFormatting.BLUE) +- ); +- } else if (amount < 0.0) { +- d *= -1.0; +- list.add( +- Component.translatable( +- "attribute.modifier.take." + attributeModifier.getOperation().toValue(), +- ATTRIBUTE_MODIFIER_FORMAT.format(d), +- Component.translatable(entry.getKey().getDescriptionId()) +- ) +- .withStyle(ChatFormatting.RED) +- ); ++ list.add(CommonComponents.space().append((Component) Component.translatable("attribute.modifier.equals." + attributemodifier.getOperation().toValue(), ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(d1), Component.translatable(((Attribute) entry.getKey()).getDescriptionId()))).withStyle(ChatFormatting.DARK_GREEN)); ++ } else if (d0 > 0.0D) { ++ list.add(Component.translatable("attribute.modifier.plus." + attributemodifier.getOperation().toValue(), ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(d1), Component.translatable(((Attribute) entry.getKey()).getDescriptionId())).withStyle(ChatFormatting.BLUE)); ++ } else if (d0 < 0.0D) { ++ d1 *= -1.0D; ++ list.add(Component.translatable("attribute.modifier.take." + attributemodifier.getOperation().toValue(), ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(d1), Component.translatable(((Attribute) entry.getKey()).getDescriptionId())).withStyle(ChatFormatting.RED)); + } + } + } +@@ -738,30 +1014,32 @@ + } + + if (this.hasTag()) { +- if (shouldShowInTooltip(hideFlags, ItemStack.TooltipPart.UNBREAKABLE) && this.tag.getBoolean("Unbreakable")) { ++ if (shouldShowInTooltip(i, ItemStack.HideFlags.UNBREAKABLE) && this.tag.getBoolean("Unbreakable")) { + list.add(Component.translatable("item.unbreakable").withStyle(ChatFormatting.BLUE)); + } + +- if (shouldShowInTooltip(hideFlags, ItemStack.TooltipPart.CAN_DESTROY) && this.tag.contains("CanDestroy", 9)) { +- ListTag list2 = this.tag.getList("CanDestroy", 8); +- if (!list2.isEmpty()) { ++ ListTag nbttaglist1; ++ ++ if (shouldShowInTooltip(i, ItemStack.HideFlags.CAN_DESTROY) && this.tag.contains("CanDestroy", 9)) { ++ nbttaglist1 = this.tag.getList("CanDestroy", 8); ++ if (!nbttaglist1.isEmpty()) { + list.add(CommonComponents.EMPTY); + list.add(Component.translatable("item.canBreak").withStyle(ChatFormatting.GRAY)); + +- for (int i1 = 0; i1 < list2.size(); i1++) { +- list.addAll(expandBlockState(list2.getString(i1))); ++ for (k = 0; k < nbttaglist1.size(); ++k) { ++ list.addAll(expandBlockState(nbttaglist1.getString(k))); + } + } + } + +- if (shouldShowInTooltip(hideFlags, ItemStack.TooltipPart.CAN_PLACE) && this.tag.contains("CanPlaceOn", 9)) { +- ListTag list2 = this.tag.getList("CanPlaceOn", 8); +- if (!list2.isEmpty()) { ++ if (shouldShowInTooltip(i, ItemStack.HideFlags.CAN_PLACE) && this.tag.contains("CanPlaceOn", 9)) { ++ nbttaglist1 = this.tag.getList("CanPlaceOn", 8); ++ if (!nbttaglist1.isEmpty()) { + list.add(CommonComponents.EMPTY); + list.add(Component.translatable("item.canPlace").withStyle(ChatFormatting.GRAY)); + +- for (int i1 = 0; i1 < list2.size(); i1++) { +- list.addAll(expandBlockState(list2.getString(i1))); ++ for (k = 0; k < nbttaglist1.size(); ++k) { ++ list.addAll(expandBlockState(nbttaglist1.getString(k))); + } + } + } +@@ -779,13 +1057,13 @@ + } + + if (player != null && !this.getItem().isEnabled(player.level().enabledFeatures())) { +- list.add(DISABLED_ITEM_TOOLTIP); ++ list.add(ItemStack.DISABLED_ITEM_TOOLTIP); + } + + return list; + } + +- private static boolean shouldShowInTooltip(int hideFlags, ItemStack.TooltipPart part) { ++ private static boolean shouldShowInTooltip(int hideFlags, ItemStack.HideFlags part) { + return (hideFlags & part.getMask()) == 0; + } + +@@ -793,32 +1071,34 @@ + return this.hasTag() && this.tag.contains("HideFlags", 99) ? this.tag.getInt("HideFlags") : 0; + } + +- public void hideTooltipPart(ItemStack.TooltipPart part) { +- CompoundTag tag = this.getOrCreateTag(); +- tag.putInt("HideFlags", tag.getInt("HideFlags") | part.getMask()); ++ public void hideTooltipPart(ItemStack.HideFlags part) { ++ CompoundTag nbttagcompound = this.getOrCreateTag(); ++ ++ nbttagcompound.putInt("HideFlags", nbttagcompound.getInt("HideFlags") | part.getMask()); + } + + public static void appendEnchantmentNames(List tooltipComponents, ListTag storedEnchantments) { +- for (int i = 0; i < storedEnchantments.size(); i++) { +- CompoundTag compound = storedEnchantments.getCompound(i); +- BuiltInRegistries.ENCHANTMENT +- .getOptional(EnchantmentHelper.getEnchantmentId(compound)) +- .ifPresent(enchantment -> tooltipComponents.add(enchantment.getFullname(EnchantmentHelper.getEnchantmentLevel(compound)))); ++ for (int i = 0; i < storedEnchantments.size(); ++i) { ++ CompoundTag nbttagcompound = storedEnchantments.getCompound(i); ++ ++ BuiltInRegistries.ENCHANTMENT.getOptional(EnchantmentHelper.getEnchantmentId(nbttagcompound)).ifPresent((enchantment) -> { ++ tooltipComponents.add(enchantment.getFullname(EnchantmentHelper.getEnchantmentLevel(nbttagcompound))); ++ }); + } ++ + } + + private static Collection expandBlockState(String stateString) { + try { +- return BlockStateParser.parseForTesting(BuiltInRegistries.BLOCK.asLookup(), stateString, true) +- .map( +- blockResult -> Lists.newArrayList(blockResult.blockState().getBlock().getName().withStyle(ChatFormatting.DARK_GRAY)), +- tagResult -> tagResult.tag() +- .stream() +- .map(holder -> holder.value().getName().withStyle(ChatFormatting.DARK_GRAY)) +- .collect(Collectors.toList()) +- ); +- } catch (CommandSyntaxException var2) { +- return Lists.newArrayList(Component.literal("missingno").withStyle(ChatFormatting.DARK_GRAY)); ++ return (Collection) BlockStateParser.parseForTesting(BuiltInRegistries.BLOCK.asLookup(), stateString, true).map((argumentblock_a) -> { ++ return Lists.newArrayList(new Component[]{argumentblock_a.blockState().getBlock().getName().withStyle(ChatFormatting.DARK_GRAY)}); ++ }, (argumentblock_b) -> { ++ return (List) argumentblock_b.tag().stream().map((holder) -> { ++ return ((Block) holder.value()).getName().withStyle(ChatFormatting.DARK_GRAY); ++ }).collect(Collectors.toList()); ++ }); ++ } catch (CommandSyntaxException commandsyntaxexception) { ++ return Lists.newArrayList(new Component[]{Component.literal("missingno").withStyle(ChatFormatting.DARK_GRAY)}); + } + } + +@@ -831,7 +1111,7 @@ + } + + public boolean isEnchantable() { +- return this.getItem().isEnchantable(this) && !this.isEnchanted(); ++ return !this.getItem().isEnchantable(this) ? false : !this.isEnchanted(); + } + + public void enchant(Enchantment enchantment, int level) { +@@ -840,12 +1120,13 @@ + this.tag.put("Enchantments", new ListTag()); + } + +- ListTag list = this.tag.getList("Enchantments", 10); +- list.add(EnchantmentHelper.storeEnchantment(EnchantmentHelper.getEnchantmentId(enchantment), (byte)level)); ++ ListTag nbttaglist = this.tag.getList("Enchantments", 10); ++ ++ nbttaglist.add(EnchantmentHelper.storeEnchantment(EnchantmentHelper.getEnchantmentId(enchantment), (byte) level)); + } + + public boolean isEnchanted() { +- return this.tag != null && this.tag.contains("Enchantments", 9) && !this.tag.getList("Enchantments", 10).isEmpty(); ++ return this.tag != null && this.tag.contains("Enchantments", 9) ? !this.tag.getList("Enchantments", 10).isEmpty() : false; + } + + public void addTagElement(String key, Tag tag) { +@@ -862,7 +1143,7 @@ + + @Nullable + public ItemFrame getFrame() { +- return this.entityRepresentation instanceof ItemFrame ? (ItemFrame)this.getEntityRepresentation() : null; ++ return this.entityRepresentation instanceof ItemFrame ? (ItemFrame) this.getEntityRepresentation() : null; + } + + @Nullable +@@ -880,33 +1161,36 @@ + } else { + this.removeTagKey("RepairCost"); + } ++ + } + + public Multimap getAttributeModifiers(EquipmentSlot slot) { +- Multimap multimap; ++ Object object; ++ + if (this.hasTag() && this.tag.contains("AttributeModifiers", 9)) { +- multimap = HashMultimap.create(); +- ListTag list = this.tag.getList("AttributeModifiers", 10); ++ object = HashMultimap.create(); ++ ListTag nbttaglist = this.tag.getList("AttributeModifiers", 10); + +- for (int i = 0; i < list.size(); i++) { +- CompoundTag compound = list.getCompound(i); +- if (!compound.contains("Slot", 8) || compound.getString("Slot").equals(slot.getName())) { +- Optional optional = BuiltInRegistries.ATTRIBUTE.getOptional(ResourceLocation.tryParse(compound.getString("AttributeName"))); ++ for (int i = 0; i < nbttaglist.size(); ++i) { ++ CompoundTag nbttagcompound = nbttaglist.getCompound(i); ++ ++ if (!nbttagcompound.contains("Slot", 8) || nbttagcompound.getString("Slot").equals(slot.getName())) { ++ Optional optional = BuiltInRegistries.ATTRIBUTE.getOptional(ResourceLocation.tryParse(nbttagcompound.getString("AttributeName"))); ++ + if (!optional.isEmpty()) { +- AttributeModifier attributeModifier = AttributeModifier.load(compound); +- if (attributeModifier != null +- && attributeModifier.getId().getLeastSignificantBits() != 0L +- && attributeModifier.getId().getMostSignificantBits() != 0L) { +- multimap.put(optional.get(), attributeModifier); ++ AttributeModifier attributemodifier = AttributeModifier.load(nbttagcompound); ++ ++ if (attributemodifier != null && attributemodifier.getId().getLeastSignificantBits() != 0L && attributemodifier.getId().getMostSignificantBits() != 0L) { ++ ((Multimap) object).put((Attribute) optional.get(), attributemodifier); + } + } + } + } + } else { +- multimap = this.getItem().getDefaultAttributeModifiers(slot); ++ object = this.getItem().getDefaultAttributeModifiers(slot); + } + +- return multimap; ++ return (Multimap) object; + } + + public void addAttributeModifier(Attribute attribute, AttributeModifier modifier, @Nullable EquipmentSlot slot) { +@@ -915,29 +1199,40 @@ + this.tag.put("AttributeModifiers", new ListTag()); + } + +- ListTag list = this.tag.getList("AttributeModifiers", 10); +- CompoundTag compoundTag = modifier.save(); +- compoundTag.putString("AttributeName", BuiltInRegistries.ATTRIBUTE.getKey(attribute).toString()); ++ ListTag nbttaglist = this.tag.getList("AttributeModifiers", 10); ++ CompoundTag nbttagcompound = modifier.save(); ++ ++ nbttagcompound.putString("AttributeName", BuiltInRegistries.ATTRIBUTE.getKey(attribute).toString()); + if (slot != null) { +- compoundTag.putString("Slot", slot.getName()); ++ nbttagcompound.putString("Slot", slot.getName()); + } + +- list.add(compoundTag); ++ nbttaglist.add(nbttagcompound); + } + ++ // CraftBukkit start ++ @Deprecated ++ public void setItem(Item item) { ++ this.item = item; ++ } ++ // CraftBukkit end ++ + public Component getDisplayName() { +- MutableComponent mutableComponent = Component.empty().append(this.getHoverName()); ++ MutableComponent ichatmutablecomponent = Component.empty().append(this.getHoverName()); ++ + if (this.hasCustomHoverName()) { +- mutableComponent.withStyle(ChatFormatting.ITALIC); ++ ichatmutablecomponent.withStyle(ChatFormatting.ITALIC); + } + +- MutableComponent mutableComponent1 = ComponentUtils.wrapInSquareBrackets(mutableComponent); ++ MutableComponent ichatmutablecomponent1 = ComponentUtils.wrapInSquareBrackets(ichatmutablecomponent); ++ + if (!this.isEmpty()) { +- mutableComponent1.withStyle(this.getRarity().color) +- .withStyle(style -> style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_ITEM, new HoverEvent.ItemStackInfo(this)))); ++ ichatmutablecomponent1.withStyle(this.getRarity().color).withStyle((chatmodifier) -> { ++ return chatmodifier.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_ITEM, new HoverEvent.ItemStackInfo(this))); ++ }); + } + +- return mutableComponent1; ++ return ichatmutablecomponent1; + } + + public boolean hasAdventureModePlaceTagForBlock(Registry blockRegistry, BlockInWorld block) { +@@ -1000,18 +1295,14 @@ + return this.getItem().getEatingSound(); + } + +- public static enum TooltipPart { +- ENCHANTMENTS, +- MODIFIERS, +- UNBREAKABLE, +- CAN_DESTROY, +- CAN_PLACE, +- ADDITIONAL, +- DYE, +- UPGRADES; ++ public static enum HideFlags { + ++ ENCHANTMENTS, MODIFIERS, UNBREAKABLE, CAN_DESTROY, CAN_PLACE, ADDITIONAL, DYE, UPGRADES; ++ + private final int mask = 1 << this.ordinal(); + ++ private HideFlags() {} ++ + public int getMask() { + return this.mask; + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/LeadItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/LeadItem.java.patch new file mode 100644 index 0000000000..c5ea6ddded --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/LeadItem.java.patch @@ -0,0 +1,127 @@ +--- a/net/minecraft/world/item/LeadItem.java ++++ b/net/minecraft/world/item/LeadItem.java +@@ -1,65 +1,100 @@ + package net.minecraft.world.item; + ++import java.util.Iterator; ++import java.util.List; + import net.minecraft.core.BlockPos; + import net.minecraft.tags.BlockTags; + import net.minecraft.world.InteractionResult; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.Mob; + import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; ++// CraftBukkit start ++import org.bukkit.craftbukkit.CraftEquipmentSlot; ++import org.bukkit.event.hanging.HangingPlaceEvent; ++// CraftBukkit end + + public class LeadItem extends Item { ++ + public LeadItem(Item.Properties properties) { + super(properties); + } + + @Override + public InteractionResult useOn(UseOnContext context) { +- Level level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- BlockState blockState = level.getBlockState(clickedPos); +- if (blockState.is(BlockTags.FENCES)) { +- Player player = context.getPlayer(); +- if (!level.isClientSide && player != null) { +- bindPlayerMobs(player, level, clickedPos); ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ ++ if (iblockdata.is(BlockTags.FENCES)) { ++ Player entityhuman = context.getPlayer(); ++ ++ if (!world.isClientSide && entityhuman != null) { ++ bindPlayerMobs(entityhuman, world, blockposition, context.getHand()); // CraftBukkit - Pass hand + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } else { + return InteractionResult.PASS; + } + } + +- public static InteractionResult bindPlayerMobs(Player player, Level level, BlockPos pos) { +- LeashFenceKnotEntity leashFenceKnotEntity = null; ++ public static InteractionResult bindPlayerMobs(Player entityhuman, Level world, BlockPos blockposition, net.minecraft.world.EnumHand enumhand) { // CraftBukkit - Add EnumHand ++ LeashFenceKnotEntity entityleash = null; + boolean flag = false; +- double d = 7.0; +- int x = pos.getX(); +- int y = pos.getY(); +- int z = pos.getZ(); ++ double d0 = 7.0D; ++ int i = blockposition.getX(); ++ int j = blockposition.getY(); ++ int k = blockposition.getZ(); ++ List list = world.getEntitiesOfClass(Mob.class, new AABB((double) i - 7.0D, (double) j - 7.0D, (double) k - 7.0D, (double) i + 7.0D, (double) j + 7.0D, (double) k + 7.0D)); ++ Iterator iterator = list.iterator(); + +- for (Mob mob : level.getEntitiesOfClass( +- Mob.class, new AABB((double)x - 7.0, (double)y - 7.0, (double)z - 7.0, (double)x + 7.0, (double)y + 7.0, (double)z + 7.0) +- )) { +- if (mob.getLeashHolder() == player) { +- if (leashFenceKnotEntity == null) { +- leashFenceKnotEntity = LeashFenceKnotEntity.getOrCreateKnot(level, pos); +- leashFenceKnotEntity.playPlacementSound(); ++ while (iterator.hasNext()) { ++ Mob entityinsentient = (Mob) iterator.next(); ++ ++ if (entityinsentient.getLeashHolder() == entityhuman) { ++ if (entityleash == null) { ++ entityleash = LeashFenceKnotEntity.getOrCreateKnot(world, blockposition); ++ ++ // CraftBukkit start - fire HangingPlaceEvent ++ org.bukkit.inventory.EquipmentSlot hand = CraftEquipmentSlot.getHand(enumhand); ++ HangingPlaceEvent event = new HangingPlaceEvent((org.bukkit.entity.Hanging) entityleash.getBukkitEntity(), entityhuman != null ? (org.bukkit.entity.Player) entityhuman.getBukkitEntity() : null, world.getWorld().getBlockAt(i, j, k), org.bukkit.block.BlockFace.SELF, hand); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ entityleash.discard(); ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end ++ entityleash.playPlacementSound(); + } + +- mob.setLeashedTo(leashFenceKnotEntity, true); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerLeashEntityEvent(entityinsentient, entityleash, entityhuman, enumhand).isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end ++ ++ entityinsentient.setLeashedTo(entityleash, true); + flag = true; + } + } + + if (flag) { +- level.gameEvent(GameEvent.BLOCK_ATTACH, pos, GameEvent.Context.of(player)); ++ world.gameEvent(GameEvent.BLOCK_ATTACH, blockposition, GameEvent.Context.of((Entity) entityhuman)); + } + + return flag ? InteractionResult.SUCCESS : InteractionResult.PASS; + } ++ ++ // CraftBukkit start ++ public static InteractionResult bindPlayerMobs(Player player, Level level, BlockPos pos) { ++ return bindPlayerMobs(player, level, pos, net.minecraft.world.EnumHand.MAIN_HAND); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/MapItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/MapItem.java.patch new file mode 100644 index 0000000000..6556502cec --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/MapItem.java.patch @@ -0,0 +1,615 @@ +--- a/net/minecraft/world/item/MapItem.java ++++ b/net/minecraft/world/item/MapItem.java +@@ -26,7 +26,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.biome.Biome; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.level.levelgen.Heightmap; + import net.minecraft.world.level.material.FluidState; +@@ -34,6 +34,7 @@ + import net.minecraft.world.level.saveddata.maps.MapItemSavedData; + + public class MapItem extends ComplexItem { ++ + public static final int IMAGE_WIDTH = 128; + public static final int IMAGE_HEIGHT = 128; + private static final int DEFAULT_MAP_COLOR = -12173266; +@@ -46,9 +47,10 @@ + } + + public static ItemStack create(Level level, int levelX, int levelZ, byte scale, boolean trackingPosition, boolean unlimitedTracking) { +- ItemStack itemStack = new ItemStack(Items.FILLED_MAP); +- createAndStoreSavedData(itemStack, level, levelX, levelZ, scale, trackingPosition, unlimitedTracking, level.dimension()); +- return itemStack; ++ ItemStack itemstack = new ItemStack(Items.FILLED_MAP); ++ ++ createAndStoreSavedData(itemstack, level, levelX, levelZ, scale, trackingPosition, unlimitedTracking, level.dimension()); ++ return itemstack; + } + + @Nullable +@@ -58,34 +60,34 @@ + + @Nullable + public static MapItemSavedData getSavedData(ItemStack stack, Level level) { +- Integer mapId = getMapId(stack); +- return getSavedData(mapId, level); ++ Integer integer = getMapId(stack); ++ ++ return getSavedData(integer, level); + } + + @Nullable + public static Integer getMapId(ItemStack stack) { +- CompoundTag tag = stack.getTag(); +- return tag != null && tag.contains("map", 99) ? tag.getInt("map") : null; ++ CompoundTag nbttagcompound = stack.getTag(); ++ ++ return nbttagcompound != null && nbttagcompound.contains("map", 99) ? nbttagcompound.getInt("map") : -1; // CraftBukkit - make new maps for no tag + } + +- private static int createNewSavedData( +- Level level, int x, int z, int scale, boolean trackingPosition, boolean unlimitedTracking, ResourceKey dimension +- ) { +- MapItemSavedData mapItemSavedData = MapItemSavedData.createFresh((double)x, (double)z, (byte)scale, trackingPosition, unlimitedTracking, dimension); +- int freeMapId = level.getFreeMapId(); +- level.setMapData(makeKey(freeMapId), mapItemSavedData); +- return freeMapId; ++ public static int createNewSavedData(Level level, int x, int z, int scale, boolean trackingPosition, boolean unlimitedTracking, ResourceKey dimension) { ++ MapItemSavedData worldmap = MapItemSavedData.createFresh((double) x, (double) z, (byte) scale, trackingPosition, unlimitedTracking, dimension); ++ int l = level.getFreeMapId(); ++ ++ level.setMapData(makeKey(l), worldmap); ++ return l; + } + + private static void storeMapData(ItemStack stack, int mapId) { + stack.getOrCreateTag().putInt("map", mapId); + } + +- private static void createAndStoreSavedData( +- ItemStack stack, Level level, int x, int z, int scale, boolean trackingPosition, boolean unlimitedTracking, ResourceKey dimension +- ) { +- int i = createNewSavedData(level, x, z, scale, trackingPosition, unlimitedTracking, dimension); +- storeMapData(stack, i); ++ private static void createAndStoreSavedData(ItemStack stack, Level level, int x, int z, int scale, boolean trackingPosition, boolean unlimitedTracking, ResourceKey dimension) { ++ int l = createNewSavedData(level, x, z, scale, trackingPosition, unlimitedTracking, dimension); ++ ++ storeMapData(stack, l); + } + + public static String makeKey(int mapId) { +@@ -95,121 +97,134 @@ + public void update(Level level, Entity viewer, MapItemSavedData data) { + if (level.dimension() == data.dimension && viewer instanceof Player) { + int i = 1 << data.scale; +- int i1 = data.centerX; +- int i2 = data.centerZ; +- int i3 = Mth.floor(viewer.getX() - (double)i1) / i + 64; +- int i4 = Mth.floor(viewer.getZ() - (double)i2) / i + 64; +- int i5 = 128 / i; ++ int j = data.centerX; ++ int k = data.centerZ; ++ int l = Mth.floor(viewer.getX() - (double) j) / i + 64; ++ int i1 = Mth.floor(viewer.getZ() - (double) k) / i + 64; ++ int j1 = 128 / i; ++ + if (level.dimensionType().hasCeiling()) { +- i5 /= 2; ++ j1 /= 2; + } + +- MapItemSavedData.HoldingPlayer holdingPlayer = data.getHoldingPlayer((Player)viewer); +- holdingPlayer.step++; +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); +- BlockPos.MutableBlockPos mutableBlockPos1 = new BlockPos.MutableBlockPos(); ++ MapItemSavedData.HoldingPlayer worldmap_worldmaphumantracker = data.getHoldingPlayer((Player) viewer); ++ ++ ++worldmap_worldmaphumantracker.step; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition1 = new BlockPos.MutableBlockPos(); + boolean flag = false; + +- for (int i6 = i3 - i5 + 1; i6 < i3 + i5; i6++) { +- if ((i6 & 15) == (holdingPlayer.step & 15) || flag) { ++ for (int k1 = l - j1 + 1; k1 < l + j1; ++k1) { ++ if ((k1 & 15) == (worldmap_worldmaphumantracker.step & 15) || flag) { + flag = false; +- double d = 0.0; ++ double d0 = 0.0D; + +- for (int i7 = i4 - i5 - 1; i7 < i4 + i5; i7++) { +- if (i6 >= 0 && i7 >= -1 && i6 < 128 && i7 < 128) { +- int i8 = Mth.square(i6 - i3) + Mth.square(i7 - i4); +- boolean flag1 = i8 > (i5 - 2) * (i5 - 2); +- int i9 = (i1 / i + i6 - 64) * i; +- int i10 = (i2 / i + i7 - 64) * i; ++ for (int l1 = i1 - j1 - 1; l1 < i1 + j1; ++l1) { ++ if (k1 >= 0 && l1 >= -1 && k1 < 128 && l1 < 128) { ++ int i2 = Mth.square(k1 - l) + Mth.square(l1 - i1); ++ boolean flag1 = i2 > (j1 - 2) * (j1 - 2); ++ int j2 = (j / i + k1 - 64) * i; ++ int k2 = (k / i + l1 - 64) * i; + Multiset multiset = LinkedHashMultiset.create(); +- LevelChunk chunk = level.getChunk(SectionPos.blockToSectionCoord(i9), SectionPos.blockToSectionCoord(i10)); ++ LevelChunk chunk = level.getChunk(SectionPos.blockToSectionCoord(j2), SectionPos.blockToSectionCoord(k2)); ++ + if (!chunk.isEmpty()) { +- int i11 = 0; +- double d1 = 0.0; ++ int l2 = 0; ++ double d1 = 0.0D; ++ int i3; ++ + if (level.dimensionType().hasCeiling()) { +- int i12 = i9 + i10 * 231871; +- i12 = i12 * i12 * 31287121 + i12 * 11; +- if ((i12 >> 20 & 1) == 0) { ++ i3 = j2 + k2 * 231871; ++ i3 = i3 * i3 * 31287121 + i3 * 11; ++ if ((i3 >> 20 & 1) == 0) { + multiset.add(Blocks.DIRT.defaultBlockState().getMapColor(level, BlockPos.ZERO), 10); + } else { + multiset.add(Blocks.STONE.defaultBlockState().getMapColor(level, BlockPos.ZERO), 100); + } + +- d1 = 100.0; ++ d1 = 100.0D; + } else { +- for (int i12 = 0; i12 < i; i12++) { +- for (int i13 = 0; i13 < i; i13++) { +- mutableBlockPos.set(i9 + i12, 0, i10 + i13); +- int i14 = chunk.getHeight(Heightmap.Types.WORLD_SURFACE, mutableBlockPos.getX(), mutableBlockPos.getZ()) + 1; +- BlockState blockState; +- if (i14 <= level.getMinBuildHeight() + 1) { +- blockState = Blocks.BEDROCK.defaultBlockState(); +- } else { ++ for (i3 = 0; i3 < i; ++i3) { ++ for (int j3 = 0; j3 < i; ++j3) { ++ blockposition_mutableblockposition.set(j2 + i3, 0, k2 + j3); ++ int k3 = chunk.getHeight(Heightmap.Types.WORLD_SURFACE, blockposition_mutableblockposition.getX(), blockposition_mutableblockposition.getZ()) + 1; ++ IBlockData iblockdata; ++ ++ if (k3 > level.getMinBuildHeight() + 1) { + do { +- mutableBlockPos.setY(--i14); +- blockState = chunk.getBlockState(mutableBlockPos); +- } while (blockState.getMapColor(level, mutableBlockPos) == MapColor.NONE && i14 > level.getMinBuildHeight()); ++ --k3; ++ blockposition_mutableblockposition.setY(k3); ++ iblockdata = chunk.getBlockState(blockposition_mutableblockposition); ++ } while (iblockdata.getMapColor(level, blockposition_mutableblockposition) == MapColor.NONE && k3 > level.getMinBuildHeight()); + +- if (i14 > level.getMinBuildHeight() && !blockState.getFluidState().isEmpty()) { +- int i15 = i14 - 1; +- mutableBlockPos1.set(mutableBlockPos); ++ if (k3 > level.getMinBuildHeight() && !iblockdata.getFluidState().isEmpty()) { ++ int l3 = k3 - 1; + +- BlockState blockState1; ++ blockposition_mutableblockposition1.set(blockposition_mutableblockposition); ++ ++ IBlockData iblockdata1; ++ + do { +- mutableBlockPos1.setY(i15--); +- blockState1 = chunk.getBlockState(mutableBlockPos1); +- i11++; +- } while (i15 > level.getMinBuildHeight() && !blockState1.getFluidState().isEmpty()); ++ blockposition_mutableblockposition1.setY(l3--); ++ iblockdata1 = chunk.getBlockState(blockposition_mutableblockposition1); ++ ++l2; ++ } while (l3 > level.getMinBuildHeight() && !iblockdata1.getFluidState().isEmpty()); + +- blockState = this.getCorrectStateForFluidBlock(level, blockState, mutableBlockPos); ++ iblockdata = this.getCorrectStateForFluidBlock(level, iblockdata, blockposition_mutableblockposition); + } ++ } else { ++ iblockdata = Blocks.BEDROCK.defaultBlockState(); + } + +- data.checkBanners(level, mutableBlockPos.getX(), mutableBlockPos.getZ()); +- d1 += (double)i14 / (double)(i * i); +- multiset.add(blockState.getMapColor(level, mutableBlockPos)); ++ data.checkBanners(level, blockposition_mutableblockposition.getX(), blockposition_mutableblockposition.getZ()); ++ d1 += (double) k3 / (double) (i * i); ++ multiset.add(iblockdata.getMapColor(level, blockposition_mutableblockposition)); + } + } + } + +- int var33 = i11 / (i * i); +- MapColor mapColor = Iterables.getFirst(Multisets.copyHighestCountFirst(multiset), MapColor.NONE); +- MapColor.Brightness brightness; +- if (mapColor == MapColor.WATER) { +- double d2 = (double)var33 * 0.1 + (double)(i6 + i7 & 1) * 0.2; +- if (d2 < 0.5) { +- brightness = MapColor.Brightness.HIGH; +- } else if (d2 > 0.9) { +- brightness = MapColor.Brightness.LOW; ++ l2 /= i * i; ++ MapColor materialmapcolor = (MapColor) Iterables.getFirst(Multisets.copyHighestCountFirst(multiset), MapColor.NONE); ++ double d2; ++ MapColor.Brightness materialmapcolor_a; ++ ++ if (materialmapcolor == MapColor.WATER) { ++ d2 = (double) l2 * 0.1D + (double) (k1 + l1 & 1) * 0.2D; ++ if (d2 < 0.5D) { ++ materialmapcolor_a = MapColor.Brightness.HIGH; ++ } else if (d2 > 0.9D) { ++ materialmapcolor_a = MapColor.Brightness.LOW; + } else { +- brightness = MapColor.Brightness.NORMAL; ++ materialmapcolor_a = MapColor.Brightness.NORMAL; + } + } else { +- double d2 = (d1 - d) * 4.0 / (double)(i + 4) + ((double)(i6 + i7 & 1) - 0.5) * 0.4; +- if (d2 > 0.6) { +- brightness = MapColor.Brightness.HIGH; +- } else if (d2 < -0.6) { +- brightness = MapColor.Brightness.LOW; ++ d2 = (d1 - d0) * 4.0D / (double) (i + 4) + ((double) (k1 + l1 & 1) - 0.5D) * 0.4D; ++ if (d2 > 0.6D) { ++ materialmapcolor_a = MapColor.Brightness.HIGH; ++ } else if (d2 < -0.6D) { ++ materialmapcolor_a = MapColor.Brightness.LOW; + } else { +- brightness = MapColor.Brightness.NORMAL; ++ materialmapcolor_a = MapColor.Brightness.NORMAL; + } + } + +- d = d1; +- if (i7 >= 0 && i8 < i5 * i5 && (!flag1 || (i6 + i7 & 1) != 0)) { +- flag |= data.updateColor(i6, i7, mapColor.getPackedId(brightness)); ++ d0 = d1; ++ if (l1 >= 0 && i2 < j1 * j1 && (!flag1 || (k1 + l1 & 1) != 0)) { ++ flag |= data.updateColor(k1, l1, materialmapcolor.getPackedId(materialmapcolor_a)); + } + } + } + } + } + } ++ + } + } + +- private BlockState getCorrectStateForFluidBlock(Level level, BlockState state, BlockPos pos) { +- FluidState fluidState = state.getFluidState(); +- return !fluidState.isEmpty() && !state.isFaceSturdy(level, pos, Direction.UP) ? fluidState.createLegacyBlock() : state; ++ private IBlockData getCorrectStateForFluidBlock(Level level, IBlockData state, BlockPos pos) { ++ FluidState fluid = state.getFluidState(); ++ ++ return !fluid.isEmpty() && !state.isFaceSturdy(level, pos, Direction.UP) ? fluid.createLegacyBlock() : state; + } + + private static boolean isBiomeWatery(boolean[] wateryMap, int xSample, int zSample) { +@@ -217,76 +232,83 @@ + } + + public static void renderBiomePreviewMap(ServerLevel serverLevel, ItemStack stack) { +- MapItemSavedData savedData = getSavedData(stack, serverLevel); +- if (savedData != null) { +- if (serverLevel.dimension() == savedData.dimension) { +- int i = 1 << savedData.scale; +- int i1 = savedData.centerX; +- int i2 = savedData.centerZ; +- boolean[] flags = new boolean[16384]; +- int i3 = i1 / i - 64; +- int i4 = i2 / i - 64; +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ MapItemSavedData worldmap = getSavedData(stack, serverLevel); + +- for (int i5 = 0; i5 < 128; i5++) { +- for (int i6 = 0; i6 < 128; i6++) { +- Holder biome = serverLevel.getBiome(mutableBlockPos.set((i3 + i6) * i, 0, (i4 + i5) * i)); +- flags[i5 * 128 + i6] = biome.is(BiomeTags.WATER_ON_MAP_OUTLINES); ++ if (worldmap != null) { ++ if (serverLevel.dimension() == worldmap.dimension) { ++ int i = 1 << worldmap.scale; ++ int j = worldmap.centerX; ++ int k = worldmap.centerZ; ++ boolean[] aboolean = new boolean[16384]; ++ int l = j / i - 64; ++ int i1 = k / i - 64; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ ++ int j1; ++ int k1; ++ ++ for (j1 = 0; j1 < 128; ++j1) { ++ for (k1 = 0; k1 < 128; ++k1) { ++ Holder holder = serverLevel.getBiome(blockposition_mutableblockposition.set((l + k1) * i, 0, (i1 + j1) * i)); ++ ++ aboolean[j1 * 128 + k1] = holder.is(BiomeTags.WATER_ON_MAP_OUTLINES); + } + } + +- for (int i5 = 1; i5 < 127; i5++) { +- for (int i6 = 1; i6 < 127; i6++) { +- int i7 = 0; ++ for (j1 = 1; j1 < 127; ++j1) { ++ for (k1 = 1; k1 < 127; ++k1) { ++ int l1 = 0; + +- for (int i8 = -1; i8 < 2; i8++) { +- for (int i9 = -1; i9 < 2; i9++) { +- if ((i8 != 0 || i9 != 0) && isBiomeWatery(flags, i5 + i8, i6 + i9)) { +- i7++; ++ for (int i2 = -1; i2 < 2; ++i2) { ++ for (int j2 = -1; j2 < 2; ++j2) { ++ if ((i2 != 0 || j2 != 0) && isBiomeWatery(aboolean, j1 + i2, k1 + j2)) { ++ ++l1; + } + } + } + +- MapColor.Brightness brightness = MapColor.Brightness.LOWEST; +- MapColor mapColor = MapColor.NONE; +- if (isBiomeWatery(flags, i5, i6)) { +- mapColor = MapColor.COLOR_ORANGE; +- if (i7 > 7 && i6 % 2 == 0) { +- switch ((i5 + (int)(Mth.sin((float)i6 + 0.0F) * 7.0F)) / 8 % 5) { ++ MapColor.Brightness materialmapcolor_a = MapColor.Brightness.LOWEST; ++ MapColor materialmapcolor = MapColor.NONE; ++ ++ if (isBiomeWatery(aboolean, j1, k1)) { ++ materialmapcolor = MapColor.COLOR_ORANGE; ++ if (l1 > 7 && k1 % 2 == 0) { ++ switch ((j1 + (int) (Mth.sin((float) k1 + 0.0F) * 7.0F)) / 8 % 5) { + case 0: + case 4: +- brightness = MapColor.Brightness.LOW; ++ materialmapcolor_a = MapColor.Brightness.LOW; + break; + case 1: + case 3: +- brightness = MapColor.Brightness.NORMAL; ++ materialmapcolor_a = MapColor.Brightness.NORMAL; + break; + case 2: +- brightness = MapColor.Brightness.HIGH; ++ materialmapcolor_a = MapColor.Brightness.HIGH; + } +- } else if (i7 > 7) { +- mapColor = MapColor.NONE; +- } else if (i7 > 5) { +- brightness = MapColor.Brightness.NORMAL; +- } else if (i7 > 3) { +- brightness = MapColor.Brightness.LOW; +- } else if (i7 > 1) { +- brightness = MapColor.Brightness.LOW; ++ } else if (l1 > 7) { ++ materialmapcolor = MapColor.NONE; ++ } else if (l1 > 5) { ++ materialmapcolor_a = MapColor.Brightness.NORMAL; ++ } else if (l1 > 3) { ++ materialmapcolor_a = MapColor.Brightness.LOW; ++ } else if (l1 > 1) { ++ materialmapcolor_a = MapColor.Brightness.LOW; + } +- } else if (i7 > 0) { +- mapColor = MapColor.COLOR_BROWN; +- if (i7 > 3) { +- brightness = MapColor.Brightness.NORMAL; ++ } else if (l1 > 0) { ++ materialmapcolor = MapColor.COLOR_BROWN; ++ if (l1 > 3) { ++ materialmapcolor_a = MapColor.Brightness.NORMAL; + } else { +- brightness = MapColor.Brightness.LOWEST; ++ materialmapcolor_a = MapColor.Brightness.LOWEST; + } + } + +- if (mapColor != MapColor.NONE) { +- savedData.setColor(i5, i6, mapColor.getPackedId(brightness)); ++ if (materialmapcolor != MapColor.NONE) { ++ worldmap.setColor(j1, k1, materialmapcolor.getPackedId(materialmapcolor_a)); + } + } + } ++ + } + } + } +@@ -294,15 +316,19 @@ + @Override + public void inventoryTick(ItemStack stack, Level level, Entity entity, int itemSlot, boolean isSelected) { + if (!level.isClientSide) { +- MapItemSavedData savedData = getSavedData(stack, level); +- if (savedData != null) { +- if (entity instanceof Player player) { +- savedData.tickCarriedBy(player, stack); ++ MapItemSavedData worldmap = getSavedData(stack, level); ++ ++ if (worldmap != null) { ++ if (entity instanceof Player) { ++ Player entityhuman = (Player) entity; ++ ++ worldmap.tickCarriedBy(entityhuman, stack); + } + +- if (!savedData.locked && (isSelected || entity instanceof Player && ((Player)entity).getOffhandItem() == stack)) { +- this.update(level, entity, savedData); ++ if (!worldmap.locked && (isSelected || entity instanceof Player && ((Player) entity).getOffhandItem() == stack)) { ++ this.update(level, entity, worldmap); + } ++ + } + } + } +@@ -310,90 +336,104 @@ + @Nullable + @Override + public Packet getUpdatePacket(ItemStack stack, Level level, Player player) { +- Integer mapId = getMapId(stack); +- MapItemSavedData savedData = getSavedData(mapId, level); +- return savedData != null ? savedData.getUpdatePacket(mapId, player) : null; ++ Integer integer = getMapId(stack); ++ MapItemSavedData worldmap = getSavedData(integer, level); ++ ++ return worldmap != null ? worldmap.getUpdatePacket(integer, player) : null; + } + + @Override +- public void onCraftedPostProcess(ItemStack itemStack, Level level) { +- CompoundTag tag = itemStack.getTag(); +- if (tag != null && tag.contains("map_scale_direction", 99)) { +- scaleMap(itemStack, level, tag.getInt("map_scale_direction")); +- tag.remove("map_scale_direction"); +- } else if (tag != null && tag.contains("map_to_lock", 1) && tag.getBoolean("map_to_lock")) { +- lockMap(level, itemStack); +- tag.remove("map_to_lock"); ++ public void onCraftedPostProcess(ItemStack itemstack, Level world) { ++ CompoundTag nbttagcompound = itemstack.getTag(); ++ ++ if (nbttagcompound != null && nbttagcompound.contains("map_scale_direction", 99)) { ++ scaleMap(itemstack, world, nbttagcompound.getInt("map_scale_direction")); ++ nbttagcompound.remove("map_scale_direction"); ++ } else if (nbttagcompound != null && nbttagcompound.contains("map_to_lock", 1) && nbttagcompound.getBoolean("map_to_lock")) { ++ lockMap(world, itemstack); ++ nbttagcompound.remove("map_to_lock"); + } ++ + } + + private static void scaleMap(ItemStack stack, Level level, int scale) { +- MapItemSavedData savedData = getSavedData(stack, level); +- if (savedData != null) { +- int freeMapId = level.getFreeMapId(); +- level.setMapData(makeKey(freeMapId), savedData.scaled(scale)); +- storeMapData(stack, freeMapId); ++ MapItemSavedData worldmap = getSavedData(stack, level); ++ ++ if (worldmap != null) { ++ int j = level.getFreeMapId(); ++ ++ level.setMapData(makeKey(j), worldmap.scaled(scale)); ++ storeMapData(stack, j); + } ++ + } + + public static void lockMap(Level level, ItemStack stack) { +- MapItemSavedData savedData = getSavedData(stack, level); +- if (savedData != null) { +- int freeMapId = level.getFreeMapId(); +- String string = makeKey(freeMapId); +- MapItemSavedData mapItemSavedData = savedData.locked(); +- level.setMapData(string, mapItemSavedData); +- storeMapData(stack, freeMapId); ++ MapItemSavedData worldmap = getSavedData(stack, level); ++ ++ if (worldmap != null) { ++ int i = level.getFreeMapId(); ++ String s = makeKey(i); ++ MapItemSavedData worldmap1 = worldmap.locked(); ++ ++ level.setMapData(s, worldmap1); ++ storeMapData(stack, i); + } ++ + } + + @Override + public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { +- Integer mapId = getMapId(stack); +- MapItemSavedData mapItemSavedData = level == null ? null : getSavedData(mapId, level); +- CompoundTag tag = stack.getTag(); +- boolean _boolean; +- byte _byte; +- if (tag != null) { +- _boolean = tag.getBoolean("map_to_lock"); +- _byte = tag.getByte("map_scale_direction"); ++ Integer integer = getMapId(stack); ++ MapItemSavedData worldmap = level == null ? null : getSavedData(integer, level); ++ CompoundTag nbttagcompound = stack.getTag(); ++ boolean flag; ++ byte b0; ++ ++ if (nbttagcompound != null) { ++ flag = nbttagcompound.getBoolean("map_to_lock"); ++ b0 = nbttagcompound.getByte("map_scale_direction"); + } else { +- _boolean = false; +- _byte = 0; ++ flag = false; ++ b0 = 0; + } + +- if (mapItemSavedData != null && (mapItemSavedData.locked || _boolean)) { +- tooltip.add(Component.translatable("filled_map.locked", mapId).withStyle(ChatFormatting.GRAY)); ++ if (worldmap != null && (worldmap.locked || flag)) { ++ tooltip.add(Component.translatable("filled_map.locked", integer).withStyle(ChatFormatting.GRAY)); + } + + if (flag.isAdvanced()) { +- if (mapItemSavedData != null) { +- if (!_boolean && _byte == 0) { +- tooltip.add(getTooltipForId(mapId)); ++ if (worldmap != null) { ++ if (!flag && b0 == 0) { ++ tooltip.add(getTooltipForId(integer)); + } + +- int min = Math.min(mapItemSavedData.scale + _byte, 4); +- tooltip.add(Component.translatable("filled_map.scale", 1 << min).withStyle(ChatFormatting.GRAY)); +- tooltip.add(Component.translatable("filled_map.level", min, 4).withStyle(ChatFormatting.GRAY)); ++ int i = Math.min(worldmap.scale + b0, 4); ++ ++ tooltip.add(Component.translatable("filled_map.scale", 1 << i).withStyle(ChatFormatting.GRAY)); ++ tooltip.add(Component.translatable("filled_map.level", i, 4).withStyle(ChatFormatting.GRAY)); + } else { + tooltip.add(Component.translatable("filled_map.unknown").withStyle(ChatFormatting.GRAY)); + } + } ++ + } + + private static Component getTooltipForId(int i) { + return Component.translatable("filled_map.id", i).withStyle(ChatFormatting.GRAY); + } + +- public static Component getTooltipForId(ItemStack itemStack) { +- return getTooltipForId(getMapId(itemStack)); ++ public static Component getTooltipForId(ItemStack itemstack) { ++ return getTooltipForId(getMapId(itemstack)); + } + + public static int getColor(ItemStack stack) { +- CompoundTag tagElement = stack.getTagElement("display"); +- if (tagElement != null && tagElement.contains("MapColor", 99)) { +- int _int = tagElement.getInt("MapColor"); +- return 0xFF000000 | _int & 16777215; ++ CompoundTag nbttagcompound = stack.getTagElement("display"); ++ ++ if (nbttagcompound != null && nbttagcompound.contains("MapColor", 99)) { ++ int i = nbttagcompound.getInt("MapColor"); ++ ++ return -16777216 | i & 16777215; + } else { + return -12173266; + } +@@ -401,11 +441,13 @@ + + @Override + public InteractionResult useOn(UseOnContext context) { +- BlockState blockState = context.getLevel().getBlockState(context.getClickedPos()); +- if (blockState.is(BlockTags.BANNERS)) { ++ IBlockData iblockdata = context.getLevel().getBlockState(context.getClickedPos()); ++ ++ if (iblockdata.is(BlockTags.BANNERS)) { + if (!context.getLevel().isClientSide) { +- MapItemSavedData savedData = getSavedData(context.getItemInHand(), context.getLevel()); +- if (savedData != null && !savedData.toggleBanner(context.getLevel(), context.getClickedPos())) { ++ MapItemSavedData worldmap = getSavedData(context.getItemInHand(), context.getLevel()); ++ ++ if (worldmap != null && !worldmap.toggleBanner(context.getLevel(), context.getClickedPos())) { + return InteractionResult.FAIL; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/MilkBucketItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/MilkBucketItem.java.patch new file mode 100644 index 0000000000..2e929e5667 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/MilkBucketItem.java.patch @@ -0,0 +1,59 @@ +--- a/net/minecraft/world/item/MilkBucketItem.java ++++ b/net/minecraft/world/item/MilkBucketItem.java +@@ -3,13 +3,14 @@ + import net.minecraft.advancements.CriteriaTriggers; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; + + public class MilkBucketItem extends Item { ++ + private static final int DRINK_DURATION = 32; + + public MilkBucketItem(Item.Properties properties) { +@@ -18,17 +19,19 @@ + + @Override + public ItemStack finishUsingItem(ItemStack stack, Level level, LivingEntity entityLiving) { +- if (entityLiving instanceof ServerPlayer serverPlayer) { +- CriteriaTriggers.CONSUME_ITEM.trigger(serverPlayer, stack); +- serverPlayer.awardStat(Stats.ITEM_USED.get(this)); ++ if (entityLiving instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entityLiving; ++ ++ CriteriaTriggers.CONSUME_ITEM.trigger(entityplayer, stack); ++ entityplayer.awardStat(Stats.ITEM_USED.get(this)); + } + +- if (entityLiving instanceof Player && !((Player)entityLiving).getAbilities().instabuild) { ++ if (entityLiving instanceof Player && !((Player) entityLiving).getAbilities().instabuild) { + stack.shrink(1); + } + + if (!level.isClientSide) { +- entityLiving.removeAllEffects(); ++ entityLiving.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.MILK); // CraftBukkit + } + + return stack.isEmpty() ? new ItemStack(Items.BUCKET) : stack; +@@ -40,12 +43,12 @@ + } + + @Override +- public UseAnim getUseAnimation(ItemStack stack) { +- return UseAnim.DRINK; ++ public EnumAnimation getUseAnimation(ItemStack stack) { ++ return EnumAnimation.DRINK; + } + + @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { + return ItemUtils.startUsingInstantly(level, player, hand); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/MinecartItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/MinecartItem.java.patch new file mode 100644 index 0000000000..a46e0e5dde --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/MinecartItem.java.patch @@ -0,0 +1,217 @@ +--- a/net/minecraft/world/item/MinecartItem.java ++++ b/net/minecraft/world/item/MinecartItem.java +@@ -2,118 +2,149 @@ + + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.dispenser.BlockSource; + import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; + import net.minecraft.core.dispenser.DispenseItemBehavior; ++import net.minecraft.core.dispenser.SourceBlock; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.tags.BlockTags; + import net.minecraft.world.InteractionResult; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.vehicle.AbstractMinecart; + import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.BaseRailBlock; + import net.minecraft.world.level.block.DispenserBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.RailShape; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end + + public class MinecartItem extends Item { ++ + private static final DispenseItemBehavior DISPENSE_ITEM_BEHAVIOR = new DefaultDispenseItemBehavior() { + private final DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior(); + + @Override +- public ItemStack execute(BlockSource blockSource, ItemStack itemStack) { +- Direction direction = blockSource.state().getValue(DispenserBlock.FACING); +- ServerLevel serverLevel = blockSource.level(); +- Vec3 vec3 = blockSource.center(); +- double d = vec3.x() + (double)direction.getStepX() * 1.125; +- double d1 = Math.floor(vec3.y()) + (double)direction.getStepY(); +- double d2 = vec3.z() + (double)direction.getStepZ() * 1.125; +- BlockPos blockPos = blockSource.pos().relative(direction); +- BlockState blockState = serverLevel.getBlockState(blockPos); +- RailShape railShape = blockState.getBlock() instanceof BaseRailBlock +- ? blockState.getValue(((BaseRailBlock)blockState.getBlock()).getShapeProperty()) +- : RailShape.NORTH_SOUTH; ++ public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ ServerLevel worldserver = sourceblock.level(); ++ Vec3 vec3d = sourceblock.center(); ++ double d0 = vec3d.x() + (double) enumdirection.getStepX() * 1.125D; ++ double d1 = Math.floor(vec3d.y()) + (double) enumdirection.getStepY(); ++ double d2 = vec3d.z() + (double) enumdirection.getStepZ() * 1.125D; ++ BlockPos blockposition = sourceblock.pos().relative(enumdirection); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ RailShape blockpropertytrackposition = iblockdata.getBlock() instanceof BaseRailBlock ? (RailShape) iblockdata.getValue(((BaseRailBlock) iblockdata.getBlock()).getShapeProperty()) : RailShape.NORTH_SOUTH; + double d3; +- if (blockState.is(BlockTags.RAILS)) { +- if (railShape.isAscending()) { +- d3 = 0.6; ++ ++ if (iblockdata.is(BlockTags.RAILS)) { ++ if (blockpropertytrackposition.isAscending()) { ++ d3 = 0.6D; + } else { +- d3 = 0.1; ++ d3 = 0.1D; + } + } else { +- if (!blockState.isAir() || !serverLevel.getBlockState(blockPos.below()).is(BlockTags.RAILS)) { +- return this.defaultDispenseItemBehavior.dispense(blockSource, itemStack); ++ if (!iblockdata.isAir() || !worldserver.getBlockState(blockposition.below()).is(BlockTags.RAILS)) { ++ return this.defaultDispenseItemBehavior.dispense(sourceblock, itemstack); + } + +- BlockState blockState1 = serverLevel.getBlockState(blockPos.below()); +- RailShape railShape1 = blockState1.getBlock() instanceof BaseRailBlock +- ? blockState1.getValue(((BaseRailBlock)blockState1.getBlock()).getShapeProperty()) +- : RailShape.NORTH_SOUTH; +- if (direction != Direction.DOWN && railShape1.isAscending()) { +- d3 = -0.4; ++ IBlockData iblockdata1 = worldserver.getBlockState(blockposition.below()); ++ RailShape blockpropertytrackposition1 = iblockdata1.getBlock() instanceof BaseRailBlock ? (RailShape) iblockdata1.getValue(((BaseRailBlock) iblockdata1.getBlock()).getShapeProperty()) : RailShape.NORTH_SOUTH; ++ ++ if (enumdirection != Direction.DOWN && blockpropertytrackposition1.isAscending()) { ++ d3 = -0.4D; + } else { +- d3 = -0.9; ++ d3 = -0.9D; + } + } + +- AbstractMinecart abstractMinecart = AbstractMinecart.createMinecart( +- serverLevel, d, d1 + d3, d2, ((MinecartItem)itemStack.getItem()).type, itemStack, null +- ); +- serverLevel.addFreshEntity(abstractMinecart); +- itemStack.shrink(1); +- return itemStack; ++ // CraftBukkit start ++ // EntityMinecartAbstract entityminecartabstract = EntityMinecartAbstract.createMinecart(worldserver, d0, d1 + d3, d2, ((ItemMinecart) itemstack.getItem()).type); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block2 = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block2, craftItem.clone(), new org.bukkit.util.Vector(d0, d1 + d3, d2)); ++ if (!DispenserBlock.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); ++ AbstractMinecart entityminecartabstract = AbstractMinecart.createMinecart(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), ((MinecartItem) itemstack1.getItem()).type, itemstack1, (Player) null); ++ ++ if (!worldserver.addFreshEntity(entityminecartabstract)) itemstack.grow(1); ++ // itemstack.shrink(1); // CraftBukkit - handled during event processing ++ // CraftBukkit end ++ return itemstack; + } + + @Override +- protected void playSound(BlockSource blockSource) { +- blockSource.level().levelEvent(1000, blockSource.pos(), 0); ++ protected void playSound(SourceBlock sourceblock) { ++ sourceblock.level().levelEvent(1000, sourceblock.pos(), 0); + } + }; +- final AbstractMinecart.Type type; ++ final AbstractMinecart.EnumMinecartType type; + +- public MinecartItem(AbstractMinecart.Type type, Item.Properties properties) { ++ public MinecartItem(AbstractMinecart.EnumMinecartType type, Item.Properties properties) { + super(properties); + this.type = type; +- DispenserBlock.registerBehavior(this, DISPENSE_ITEM_BEHAVIOR); ++ DispenserBlock.registerBehavior(this, MinecartItem.DISPENSE_ITEM_BEHAVIOR); + } + + @Override + public InteractionResult useOn(UseOnContext context) { +- Level level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- BlockState blockState = level.getBlockState(clickedPos); +- if (!blockState.is(BlockTags.RAILS)) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ ++ if (!iblockdata.is(BlockTags.RAILS)) { + return InteractionResult.FAIL; + } else { +- ItemStack itemInHand = context.getItemInHand(); +- if (level instanceof ServerLevel serverLevel) { +- RailShape railShape = blockState.getBlock() instanceof BaseRailBlock +- ? blockState.getValue(((BaseRailBlock)blockState.getBlock()).getShapeProperty()) +- : RailShape.NORTH_SOUTH; +- double d = 0.0; +- if (railShape.isAscending()) { +- d = 0.5; ++ ItemStack itemstack = context.getItemInHand(); ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ RailShape blockpropertytrackposition = iblockdata.getBlock() instanceof BaseRailBlock ? (RailShape) iblockdata.getValue(((BaseRailBlock) iblockdata.getBlock()).getShapeProperty()) : RailShape.NORTH_SOUTH; ++ double d0 = 0.0D; ++ ++ if (blockpropertytrackposition.isAscending()) { ++ d0 = 0.5D; + } + +- AbstractMinecart abstractMinecart = AbstractMinecart.createMinecart( +- serverLevel, +- (double)clickedPos.getX() + 0.5, +- (double)clickedPos.getY() + 0.0625 + d, +- (double)clickedPos.getZ() + 0.5, +- this.type, +- itemInHand, +- context.getPlayer() +- ); +- serverLevel.addFreshEntity(abstractMinecart); +- serverLevel.gameEvent( +- GameEvent.ENTITY_PLACE, clickedPos, GameEvent.Context.of(context.getPlayer(), serverLevel.getBlockState(clickedPos.below())) +- ); ++ AbstractMinecart entityminecartabstract = AbstractMinecart.createMinecart(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.0625D + d0, (double) blockposition.getZ() + 0.5D, this.type, itemstack, context.getPlayer()); ++ ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(context, entityminecartabstract).isCancelled()) { ++ return InteractionResult.FAIL; ++ } ++ // CraftBukkit end ++ if (!worldserver.addFreshEntity(entityminecartabstract)) return InteractionResult.PASS; // CraftBukkit ++ worldserver.gameEvent(GameEvent.ENTITY_PLACE, blockposition, GameEvent.Context.of(context.getPlayer(), worldserver.getBlockState(blockposition.below()))); + } + +- itemInHand.shrink(1); +- return InteractionResult.sidedSuccess(level.isClientSide); ++ itemstack.shrink(1); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/PotionItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/PotionItem.java.patch new file mode 100644 index 0000000000..a1fac302b7 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/PotionItem.java.patch @@ -0,0 +1,162 @@ +--- a/net/minecraft/world/item/PotionItem.java ++++ b/net/minecraft/world/item/PotionItem.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.item; + ++import java.util.Iterator; + import java.util.List; + import javax.annotation.Nullable; + import net.minecraft.advancements.CriteriaTriggers; +@@ -13,10 +14,11 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; + import net.minecraft.tags.BlockTags; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.effect.MobEffectInstance; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.alchemy.PotionUtils; +@@ -24,10 +26,11 @@ + import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + + public class PotionItem extends Item { ++ + private static final int DRINK_DURATION = 32; + + public PotionItem(Item.Properties properties) { +@@ -41,35 +44,41 @@ + + @Override + public ItemStack finishUsingItem(ItemStack stack, Level level, LivingEntity entityLiving) { +- Player player = entityLiving instanceof Player ? (Player)entityLiving : null; +- if (player instanceof ServerPlayer) { +- CriteriaTriggers.CONSUME_ITEM.trigger((ServerPlayer)player, stack); ++ Player entityhuman = entityLiving instanceof Player ? (Player) entityLiving : null; ++ ++ if (entityhuman instanceof ServerPlayer) { ++ CriteriaTriggers.CONSUME_ITEM.trigger((ServerPlayer) entityhuman, stack); + } + + if (!level.isClientSide) { +- for (MobEffectInstance mobEffectInstance : PotionUtils.getMobEffects(stack)) { +- if (mobEffectInstance.getEffect().isInstantenous()) { +- mobEffectInstance.getEffect().applyInstantenousEffect(player, player, entityLiving, mobEffectInstance.getAmplifier(), 1.0); ++ List list = PotionUtils.getMobEffects(stack); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); ++ ++ if (mobeffect.getEffect().isInstantenous()) { ++ mobeffect.getEffect().applyInstantenousEffect(entityhuman, entityhuman, entityLiving, mobeffect.getAmplifier(), 1.0D); + } else { +- entityLiving.addEffect(new MobEffectInstance(mobEffectInstance)); ++ entityLiving.addEffect(new MobEffectInstance(mobeffect), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_DRINK); // CraftBukkit + } + } + } + +- if (player != null) { +- player.awardStat(Stats.ITEM_USED.get(this)); +- if (!player.getAbilities().instabuild) { ++ if (entityhuman != null) { ++ entityhuman.awardStat(Stats.ITEM_USED.get(this)); ++ if (!entityhuman.getAbilities().instabuild) { + stack.shrink(1); + } + } + +- if (player == null || !player.getAbilities().instabuild) { ++ if (entityhuman == null || !entityhuman.getAbilities().instabuild) { + if (stack.isEmpty()) { + return new ItemStack(Items.GLASS_BOTTLE); + } + +- if (player != null) { +- player.getInventory().add(new ItemStack(Items.GLASS_BOTTLE)); ++ if (entityhuman != null) { ++ entityhuman.getInventory().add(new ItemStack(Items.GLASS_BOTTLE)); + } + } + +@@ -79,37 +88,28 @@ + + @Override + public InteractionResult useOn(UseOnContext context) { +- Level level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- Player player = context.getPlayer(); +- ItemStack itemInHand = context.getItemInHand(); +- BlockState blockState = level.getBlockState(clickedPos); +- if (context.getClickedFace() != Direction.DOWN && blockState.is(BlockTags.CONVERTABLE_TO_MUD) && PotionUtils.getPotion(itemInHand) == Potions.WATER) { +- level.playSound(null, clickedPos, SoundEvents.GENERIC_SPLASH, SoundSource.BLOCKS, 1.0F, 1.0F); +- player.setItemInHand(context.getHand(), ItemUtils.createFilledResult(itemInHand, player, new ItemStack(Items.GLASS_BOTTLE))); +- player.awardStat(Stats.ITEM_USED.get(itemInHand.getItem())); +- if (!level.isClientSide) { +- ServerLevel serverLevel = (ServerLevel)level; ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ Player entityhuman = context.getPlayer(); ++ ItemStack itemstack = context.getItemInHand(); ++ IBlockData iblockdata = world.getBlockState(blockposition); + +- for (int i = 0; i < 5; i++) { +- serverLevel.sendParticles( +- ParticleTypes.SPLASH, +- (double)clickedPos.getX() + level.random.nextDouble(), +- (double)(clickedPos.getY() + 1), +- (double)clickedPos.getZ() + level.random.nextDouble(), +- 1, +- 0.0, +- 0.0, +- 0.0, +- 1.0 +- ); ++ if (context.getClickedFace() != Direction.DOWN && iblockdata.is(BlockTags.CONVERTABLE_TO_MUD) && PotionUtils.getPotion(itemstack) == Potions.WATER) { ++ world.playSound((Player) null, blockposition, SoundEvents.GENERIC_SPLASH, SoundSource.BLOCKS, 1.0F, 1.0F); ++ entityhuman.setItemInHand(context.getHand(), ItemUtils.createFilledResult(itemstack, entityhuman, new ItemStack(Items.GLASS_BOTTLE))); ++ entityhuman.awardStat(Stats.ITEM_USED.get(itemstack.getItem())); ++ if (!world.isClientSide) { ++ ServerLevel worldserver = (ServerLevel) world; ++ ++ for (int i = 0; i < 5; ++i) { ++ worldserver.sendParticles(ParticleTypes.SPLASH, (double) blockposition.getX() + world.random.nextDouble(), (double) (blockposition.getY() + 1), (double) blockposition.getZ() + world.random.nextDouble(), 1, 0.0D, 0.0D, 0.0D, 1.0D); + } + } + +- level.playSound(null, clickedPos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent(null, GameEvent.FLUID_PLACE, clickedPos); +- level.setBlockAndUpdate(clickedPos, Blocks.MUD.defaultBlockState()); +- return InteractionResult.sidedSuccess(level.isClientSide); ++ world.playSound((Player) null, blockposition, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockposition); ++ world.setBlockAndUpdate(blockposition, Blocks.MUD.defaultBlockState()); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } else { + return InteractionResult.PASS; + } +@@ -121,12 +121,12 @@ + } + + @Override +- public UseAnim getUseAnimation(ItemStack stack) { +- return UseAnim.DRINK; ++ public EnumAnimation getUseAnimation(ItemStack stack) { ++ return EnumAnimation.DRINK; + } + + @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { + return ItemUtils.startUsingInstantly(level, player, hand); + } + diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/RecordItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/RecordItem.java.patch new file mode 100644 index 0000000000..c9f63ee89d --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/RecordItem.java.patch @@ -0,0 +1,79 @@ +--- a/net/minecraft/world/item/RecordItem.java ++++ b/net/minecraft/world/item/RecordItem.java +@@ -16,11 +16,13 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.JukeboxBlock; ++import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.JukeboxBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + + public class RecordItem extends Item { ++ + private static final Map BY_NAME = Maps.newHashMap(); + private final int analogOutput; + private final SoundEvent sound; +@@ -31,30 +33,37 @@ + this.analogOutput = analogOutput; + this.sound = sound; + this.lengthInTicks = lengthInSeconds * 20; +- BY_NAME.put(this.sound, this); ++ RecordItem.BY_NAME.put(this.sound, this); + } + + @Override + public InteractionResult useOn(UseOnContext context) { +- Level level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- BlockState blockState = level.getBlockState(clickedPos); +- if (blockState.is(Blocks.JUKEBOX) && !blockState.getValue(JukeboxBlock.HAS_RECORD)) { +- ItemStack itemInHand = context.getItemInHand(); +- if (!level.isClientSide) { +- Player player = context.getPlayer(); +- if (level.getBlockEntity(clickedPos) instanceof JukeboxBlockEntity jukeboxBlockEntity) { +- jukeboxBlockEntity.setTheItem(itemInHand.copy()); +- level.gameEvent(GameEvent.BLOCK_CHANGE, clickedPos, GameEvent.Context.of(player, blockState)); ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ ++ if (iblockdata.is(Blocks.JUKEBOX) && !(Boolean) iblockdata.getValue(JukeboxBlock.HAS_RECORD)) { ++ ItemStack itemstack = context.getItemInHand(); ++ ++ if (!world.isClientSide) { ++ if (true) return InteractionResult.SUCCESS; // CraftBukkit - handled in ItemStack ++ Player entityhuman = context.getPlayer(); ++ BlockEntity tileentity = world.getBlockEntity(blockposition); ++ ++ if (tileentity instanceof JukeboxBlockEntity) { ++ JukeboxBlockEntity tileentityjukebox = (JukeboxBlockEntity) tileentity; ++ ++ tileentityjukebox.setTheItem(itemstack.copy()); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entityhuman, iblockdata)); + } + +- itemInHand.shrink(1); +- if (player != null) { +- player.awardStat(Stats.PLAY_RECORD); ++ itemstack.shrink(1); ++ if (entityhuman != null) { ++ entityhuman.awardStat(Stats.PLAY_RECORD); + } + } + +- return InteractionResult.sidedSuccess(level.isClientSide); ++ return InteractionResult.sidedSuccess(world.isClientSide); + } else { + return InteractionResult.PASS; + } +@@ -75,7 +84,7 @@ + + @Nullable + public static RecordItem getBySound(SoundEvent sound) { +- return BY_NAME.get(sound); ++ return (RecordItem) RecordItem.BY_NAME.get(sound); + } + + public SoundEvent getSound() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/SignItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/SignItem.java.patch new file mode 100644 index 0000000000..ccb176dc5c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/SignItem.java.patch @@ -0,0 +1,51 @@ +--- a/net/minecraft/world/item/SignItem.java ++++ b/net/minecraft/world/item/SignItem.java +@@ -7,10 +7,14 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.SignBlock; ++import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.SignBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public class SignItem extends StandingAndWallBlockItem { ++ ++ public static BlockPos openSign; // CraftBukkit ++ + public SignItem(Item.Properties properties, Block standingBlock, Block wallBlock) { + super(standingBlock, wallBlock, properties, Direction.DOWN); + } +@@ -20,14 +24,25 @@ + } + + @Override +- protected boolean updateCustomBlockEntityTag(BlockPos pos, Level level, @Nullable Player player, ItemStack stack, BlockState state) { ++ protected boolean updateCustomBlockEntityTag(BlockPos pos, Level level, @Nullable Player player, ItemStack stack, IBlockData state) { + boolean flag = super.updateCustomBlockEntityTag(pos, level, player, stack, state); +- if (!level.isClientSide +- && !flag +- && player != null +- && level.getBlockEntity(pos) instanceof SignBlockEntity signBlockEntity +- && level.getBlockState(pos).getBlock() instanceof SignBlock signBlock) { +- signBlock.openTextEdit(player, signBlockEntity, true); ++ ++ if (!level.isClientSide && !flag && player != null) { ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof SignBlockEntity) { ++ SignBlockEntity tileentitysign = (SignBlockEntity) tileentity; ++ Block block = level.getBlockState(pos).getBlock(); ++ ++ if (block instanceof SignBlock) { ++ SignBlock blocksign = (SignBlock) block; ++ ++ // CraftBukkit start - SPIGOT-4678 ++ // blocksign.openTextEdit(entityhuman, tileentitysign, true); ++ SignItem.openSign = pos; ++ // CraftBukkit end ++ } ++ } + } + + return flag; diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/SnowballItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/SnowballItem.java.patch new file mode 100644 index 0000000000..e7a11c6556 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/SnowballItem.java.patch @@ -0,0 +1,72 @@ +--- a/net/minecraft/world/item/SnowballItem.java ++++ b/net/minecraft/world/item/SnowballItem.java +@@ -3,42 +3,49 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.Snowball; + import net.minecraft.world.level.Level; + + public class SnowballItem extends Item { ++ + public SnowballItem(Item.Properties properties) { + super(properties); + } + + @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- level.playSound( +- null, +- player.getX(), +- player.getY(), +- player.getZ(), +- SoundEvents.SNOWBALL_THROW, +- SoundSource.NEUTRAL, +- 0.5F, +- 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F) +- ); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ // CraftBukkit - moved down ++ // world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.SNOWBALL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); + if (!level.isClientSide) { +- Snowball snowball = new Snowball(level, player); +- snowball.setItem(itemInHand); +- snowball.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 1.5F, 1.0F); +- level.addFreshEntity(snowball); ++ Snowball entitysnowball = new Snowball(level, player); ++ ++ entitysnowball.setItem(itemstack); ++ entitysnowball.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 1.5F, 1.0F); ++ if (level.addFreshEntity(entitysnowball)) { ++ if (!player.getAbilities().instabuild) { ++ itemstack.shrink(1); ++ } ++ ++ level.playSound((Player) null, player.getX(), player.getY(), player.getZ(), SoundEvents.SNOWBALL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)); ++ } else if (player instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().updateInventory(); ++ } + } ++ // CraftBukkit end + + player.awardStat(Stats.ITEM_USED.get(this)); +- if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ // CraftBukkit start - moved up ++ /* ++ if (!entityhuman.getAbilities().instabuild) { ++ itemstack.shrink(1); + } ++ */ + +- return InteractionResultHolder.sidedSuccess(itemInHand, level.isClientSide()); ++ return InteractionResultHolder.sidedSuccess(itemstack, level.isClientSide()); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/SpawnEggItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/SpawnEggItem.java.patch new file mode 100644 index 0000000000..e55ed2d4a1 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/SpawnEggItem.java.patch @@ -0,0 +1,241 @@ +--- a/net/minecraft/world/item/SpawnEggItem.java ++++ b/net/minecraft/world/item/SpawnEggItem.java +@@ -11,14 +11,14 @@ + import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.flag.FeatureFlagSet; + import net.minecraft.world.item.context.UseOnContext; +@@ -26,13 +26,15 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.Spawner; + import net.minecraft.world.level.block.LiquidBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.entity.BlockEntity; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; + + public class SpawnEggItem extends Item { ++ + private static final Map, SpawnEggItem> BY_ID = Maps.newIdentityHashMap(); + private final int backgroundColor; + private final int highlightColor; +@@ -43,47 +45,45 @@ + this.defaultType = defaultType; + this.backgroundColor = backgroundColor; + this.highlightColor = highlightColor; +- BY_ID.put(defaultType, this); ++ SpawnEggItem.BY_ID.put(defaultType, this); + } + + @Override + public InteractionResult useOn(UseOnContext context) { +- Level level = context.getLevel(); +- if (!(level instanceof ServerLevel)) { ++ Level world = context.getLevel(); ++ ++ if (!(world instanceof ServerLevel)) { + return InteractionResult.SUCCESS; + } else { +- ItemStack itemInHand = context.getItemInHand(); +- BlockPos clickedPos = context.getClickedPos(); +- Direction clickedFace = context.getClickedFace(); +- BlockState blockState = level.getBlockState(clickedPos); +- if (level.getBlockEntity(clickedPos) instanceof Spawner spawner) { +- EntityType type = this.getType(itemInHand.getTag()); +- spawner.setEntityId(type, level.getRandom()); +- level.sendBlockUpdated(clickedPos, blockState, blockState, 3); +- level.gameEvent(context.getPlayer(), GameEvent.BLOCK_CHANGE, clickedPos); +- itemInHand.shrink(1); ++ ItemStack itemstack = context.getItemInHand(); ++ BlockPos blockposition = context.getClickedPos(); ++ Direction enumdirection = context.getClickedFace(); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ BlockEntity tileentity = world.getBlockEntity(blockposition); ++ EntityType entitytypes; ++ ++ if (tileentity instanceof Spawner) { ++ Spawner spawner = (Spawner) tileentity; ++ ++ entitytypes = this.getType(itemstack.getTag()); ++ spawner.setEntityId(entitytypes, world.getRandom()); ++ world.sendBlockUpdated(blockposition, iblockdata, iblockdata, 3); ++ world.gameEvent((Entity) context.getPlayer(), GameEvent.BLOCK_CHANGE, blockposition); ++ itemstack.shrink(1); + return InteractionResult.CONSUME; + } else { +- BlockPos blockPos; +- if (blockState.getCollisionShape(level, clickedPos).isEmpty()) { +- blockPos = clickedPos; ++ BlockPos blockposition1; ++ ++ if (iblockdata.getCollisionShape(world, blockposition).isEmpty()) { ++ blockposition1 = blockposition; + } else { +- blockPos = clickedPos.relative(clickedFace); ++ blockposition1 = blockposition.relative(enumdirection); + } + +- EntityType type = this.getType(itemInHand.getTag()); +- if (type.spawn( +- (ServerLevel)level, +- itemInHand, +- context.getPlayer(), +- blockPos, +- MobSpawnType.SPAWN_EGG, +- true, +- !Objects.equals(clickedPos, blockPos) && clickedFace == Direction.UP +- ) +- != null) { +- itemInHand.shrink(1); +- level.gameEvent(context.getPlayer(), GameEvent.ENTITY_PLACE, clickedPos); ++ entitytypes = this.getType(itemstack.getTag()); ++ if (entitytypes.spawn((ServerLevel) world, itemstack, context.getPlayer(), blockposition1, EnumMobSpawn.SPAWN_EGG, true, !Objects.equals(blockposition, blockposition1) && enumdirection == Direction.UP) != null) { ++ itemstack.shrink(1); ++ world.gameEvent((Entity) context.getPlayer(), GameEvent.ENTITY_PLACE, blockposition); + } + + return InteractionResult.CONSUME; +@@ -92,33 +92,36 @@ + } + + @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- BlockHitResult playerPOVHitResult = getPlayerPOVHitResult(level, player, ClipContext.Fluid.SOURCE_ONLY); +- if (playerPOVHitResult.getType() != HitResult.Type.BLOCK) { +- return InteractionResultHolder.pass(itemInHand); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ BlockHitResult movingobjectpositionblock = getPlayerPOVHitResult(level, player, ClipContext.Fluid.SOURCE_ONLY); ++ ++ if (movingobjectpositionblock.getType() != HitResult.EnumMovingObjectType.BLOCK) { ++ return InteractionResultHolder.pass(itemstack); + } else if (!(level instanceof ServerLevel)) { +- return InteractionResultHolder.success(itemInHand); ++ return InteractionResultHolder.success(itemstack); + } else { +- BlockPos blockPos = playerPOVHitResult.getBlockPos(); +- if (!(level.getBlockState(blockPos).getBlock() instanceof LiquidBlock)) { +- return InteractionResultHolder.pass(itemInHand); +- } else if (level.mayInteract(player, blockPos) && player.mayUseItemAt(blockPos, playerPOVHitResult.getDirection(), itemInHand)) { +- EntityType type = this.getType(itemInHand.getTag()); +- Entity entity = type.spawn((ServerLevel)level, itemInHand, player, blockPos, MobSpawnType.SPAWN_EGG, false, false); ++ BlockPos blockposition = movingobjectpositionblock.getBlockPos(); ++ ++ if (!(level.getBlockState(blockposition).getBlock() instanceof LiquidBlock)) { ++ return InteractionResultHolder.pass(itemstack); ++ } else if (level.mayInteract(player, blockposition) && player.mayUseItemAt(blockposition, movingobjectpositionblock.getDirection(), itemstack)) { ++ EntityType entitytypes = this.getType(itemstack.getTag()); ++ Entity entity = entitytypes.spawn((ServerLevel) level, itemstack, player, blockposition, EnumMobSpawn.SPAWN_EGG, false, false); ++ + if (entity == null) { +- return InteractionResultHolder.pass(itemInHand); ++ return InteractionResultHolder.pass(itemstack); + } else { + if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + + player.awardStat(Stats.ITEM_USED.get(this)); +- level.gameEvent(player, GameEvent.ENTITY_PLACE, entity.position()); +- return InteractionResultHolder.consume(itemInHand); ++ level.gameEvent((Entity) player, GameEvent.ENTITY_PLACE, entity.position()); ++ return InteractionResultHolder.consume(itemstack); + } + } else { +- return InteractionResultHolder.fail(itemInHand); ++ return InteractionResultHolder.fail(itemstack); + } + } + } +@@ -133,18 +136,19 @@ + + @Nullable + public static SpawnEggItem byId(@Nullable EntityType type) { +- return BY_ID.get(type); ++ return (SpawnEggItem) SpawnEggItem.BY_ID.get(type); + } + + public static Iterable eggs() { +- return Iterables.unmodifiableIterable(BY_ID.values()); ++ return Iterables.unmodifiableIterable(SpawnEggItem.BY_ID.values()); + } + + public EntityType getType(@Nullable CompoundTag nbt) { + if (nbt != null && nbt.contains("EntityTag", 10)) { +- CompoundTag compound = nbt.getCompound("EntityTag"); +- if (compound.contains("id", 8)) { +- return EntityType.byString(compound.getString("id")).orElse(this.defaultType); ++ CompoundTag nbttagcompound1 = nbt.getCompound("EntityTag"); ++ ++ if (nbttagcompound1.contains("id", 8)) { ++ return (EntityType) EntityType.byString(nbttagcompound1.getString("id")).orElse(this.defaultType); + } + } + +@@ -156,37 +160,36 @@ + return this.defaultType.requiredFeatures(); + } + +- public Optional spawnOffspringFromSpawnEgg( +- Player player, Mob mob, EntityType entityType, ServerLevel serverLevel, Vec3 pos, ItemStack stack +- ) { ++ public Optional spawnOffspringFromSpawnEgg(Player player, Mob mob, EntityType entityType, ServerLevel serverLevel, Vec3 pos, ItemStack stack) { + if (!this.spawnsEntity(stack.getTag(), entityType)) { + return Optional.empty(); + } else { +- Mob breedOffspring; ++ Object object; ++ + if (mob instanceof AgeableMob) { +- breedOffspring = ((AgeableMob)mob).getBreedOffspring(serverLevel, (AgeableMob)mob); ++ object = ((AgeableMob) mob).getBreedOffspring(serverLevel, (AgeableMob) mob); + } else { +- breedOffspring = entityType.create(serverLevel); ++ object = (Mob) entityType.create(serverLevel); + } + +- if (breedOffspring == null) { ++ if (object == null) { + return Optional.empty(); + } else { +- breedOffspring.setBaby(true); +- if (!breedOffspring.isBaby()) { ++ ((Mob) object).setBaby(true); ++ if (!((Mob) object).isBaby()) { + return Optional.empty(); + } else { +- breedOffspring.moveTo(pos.x(), pos.y(), pos.z(), 0.0F, 0.0F); +- serverLevel.addFreshEntityWithPassengers(breedOffspring); ++ ((Mob) object).moveTo(pos.x(), pos.y(), pos.z(), 0.0F, 0.0F); ++ serverLevel.addFreshEntityWithPassengers((Entity) object, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG); // CraftBukkit + if (stack.hasCustomHoverName()) { +- breedOffspring.setCustomName(stack.getHoverName()); ++ ((Mob) object).setCustomName(stack.getHoverName()); + } + + if (!player.getAbilities().instabuild) { + stack.shrink(1); + } + +- return Optional.of(breedOffspring); ++ return Optional.of((Mob) object); // CraftBukkit - decompile error + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/StandingAndWallBlockItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/StandingAndWallBlockItem.java.patch new file mode 100644 index 0000000000..2b71c68f68 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/StandingAndWallBlockItem.java.patch @@ -0,0 +1,85 @@ +--- a/net/minecraft/world/item/StandingAndWallBlockItem.java ++++ b/net/minecraft/world/item/StandingAndWallBlockItem.java +@@ -4,14 +4,21 @@ + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.item.context.BlockPlaceContext; ++import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.Block; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.shapes.CollisionContext; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.event.block.BlockCanBuildEvent; ++// CraftBukkit end + + public class StandingAndWallBlockItem extends BlockItem { +- protected final Block wallBlock; ++ ++ public final Block wallBlock; + private final Direction attachmentDirection; + + public StandingAndWallBlockItem(Block block, Block wallBlock, Item.Properties properties, Direction attachmentDirection) { +@@ -20,29 +27,46 @@ + this.attachmentDirection = attachmentDirection; + } + +- protected boolean canPlace(LevelReader level, BlockState state, BlockPos pos) { ++ protected boolean canPlace(LevelReader level, IBlockData state, BlockPos pos) { + return state.canSurvive(level, pos); + } + + @Nullable + @Override +- protected BlockState getPlacementState(BlockPlaceContext context) { +- BlockState stateForPlacement = this.wallBlock.getStateForPlacement(context); +- BlockState blockState = null; +- LevelReader level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); ++ protected IBlockData getPlacementState(BlockPlaceContext context) { ++ IBlockData iblockdata = this.wallBlock.getStateForPlacement(context); ++ IBlockData iblockdata1 = null; ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ Direction[] aenumdirection = context.getNearestLookingDirections(); ++ int i = aenumdirection.length; + +- for (Direction direction : context.getNearestLookingDirections()) { +- if (direction != this.attachmentDirection.getOpposite()) { +- BlockState blockState1 = direction == this.attachmentDirection ? this.getBlock().getStateForPlacement(context) : stateForPlacement; +- if (blockState1 != null && this.canPlace(level, blockState1, clickedPos)) { +- blockState = blockState1; ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ ++ if (enumdirection != this.attachmentDirection.getOpposite()) { ++ IBlockData iblockdata2 = enumdirection == this.attachmentDirection ? this.getBlock().getStateForPlacement(context) : iblockdata; ++ ++ if (iblockdata2 != null && this.canPlace(world, iblockdata2, blockposition)) { ++ iblockdata1 = iblockdata2; + break; + } + } + } + +- return blockState != null && level.isUnobstructed(blockState, clickedPos, CollisionContext.empty()) ? blockState : null; ++ // CraftBukkit start ++ if (iblockdata1 != null) { ++ boolean defaultReturn = world.isUnobstructed(iblockdata1, blockposition, CollisionContext.empty()); ++ org.bukkit.entity.Player player = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null; ++ ++ BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(world, blockposition), player, CraftBlockData.fromData(iblockdata1), defaultReturn); ++ context.getLevel().getCraftServer().getPluginManager().callEvent(event); ++ ++ return (event.isBuildable()) ? iblockdata1 : null; ++ } else { ++ return null; ++ } ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/TridentItem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/TridentItem.java.patch new file mode 100644 index 0000000000..36f0180224 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/TridentItem.java.patch @@ -0,0 +1,244 @@ +--- a/net/minecraft/world/item/TridentItem.java ++++ b/net/minecraft/world/item/TridentItem.java +@@ -1,19 +1,20 @@ + package net.minecraft.world.item; + + import com.google.common.collect.ImmutableMultimap; +-import com.google.common.collect.Multimap; + import com.google.common.collect.ImmutableMultimap.Builder; ++import com.google.common.collect.Multimap; + import net.minecraft.core.BlockPos; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResultHolder; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.ai.attributes.Attribute; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -22,10 +23,11 @@ + import net.minecraft.world.entity.projectile.ThrownTrident; + import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; + +-public class TridentItem extends Item implements Vanishable { ++public class TridentItem extends Item implements ItemVanishable { ++ + public static final int THROW_THRESHOLD_TIME = 10; + public static final float BASE_DAMAGE = 8.0F; + public static final float SHOOT_POWER = 2.5F; +@@ -34,19 +36,20 @@ + public TridentItem(Item.Properties properties) { + super(properties); + Builder builder = ImmutableMultimap.builder(); +- builder.put(Attributes.ATTACK_DAMAGE, new AttributeModifier(BASE_ATTACK_DAMAGE_UUID, "Tool modifier", 8.0, AttributeModifier.Operation.ADDITION)); +- builder.put(Attributes.ATTACK_SPEED, new AttributeModifier(BASE_ATTACK_SPEED_UUID, "Tool modifier", -2.9F, AttributeModifier.Operation.ADDITION)); ++ ++ builder.put(Attributes.ATTACK_DAMAGE, new AttributeModifier(TridentItem.BASE_ATTACK_DAMAGE_UUID, "Tool modifier", 8.0D, AttributeModifier.Operation.ADDITION)); ++ builder.put(Attributes.ATTACK_SPEED, new AttributeModifier(TridentItem.BASE_ATTACK_SPEED_UUID, "Tool modifier", -2.9000000953674316D, AttributeModifier.Operation.ADDITION)); + this.defaultModifiers = builder.build(); + } + + @Override +- public boolean canAttackBlock(BlockState state, Level level, BlockPos pos, Player player) { ++ public boolean canAttackBlock(IBlockData state, Level level, BlockPos pos, Player player) { + return !player.isCreative(); + } + + @Override +- public UseAnim getUseAnimation(ItemStack stack) { +- return UseAnim.SPEAR; ++ public EnumAnimation getUseAnimation(ItemStack stack) { ++ return EnumAnimation.SPEAR; + } + + @Override +@@ -56,86 +59,127 @@ + + @Override + public void releaseUsing(ItemStack stack, Level level, LivingEntity entityLiving, int timeLeft) { +- if (entityLiving instanceof Player player) { +- int i = this.getUseDuration(stack) - timeLeft; +- if (i >= 10) { +- int riptide = EnchantmentHelper.getRiptide(stack); +- if (riptide <= 0 || player.isInWaterOrRain()) { ++ if (entityLiving instanceof Player) { ++ Player entityhuman = (Player) entityLiving; ++ int j = this.getUseDuration(stack) - timeLeft; ++ ++ if (j >= 10) { ++ int k = EnchantmentHelper.getRiptide(stack); ++ ++ if (k <= 0 || entityhuman.isInWaterOrRain()) { + if (!level.isClientSide) { +- stack.hurtAndBreak(1, player, contextEntity -> contextEntity.broadcastBreakEvent(entityLiving.getUsedItemHand())); +- if (riptide == 0) { +- ThrownTrident thrownTrident = new ThrownTrident(level, player, stack); +- thrownTrident.shootFromRotation(player, player.getXRot(), player.getYRot(), 0.0F, 2.5F + (float)riptide * 0.5F, 1.0F); +- if (player.getAbilities().instabuild) { +- thrownTrident.pickup = AbstractArrow.Pickup.CREATIVE_ONLY; ++ // CraftBukkit - moved down ++ /* ++ itemstack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(entityliving.getUsedItemHand()); ++ }); ++ */ ++ if (k == 0) { ++ ThrownTrident entitythrowntrident = new ThrownTrident(level, entityhuman, stack); ++ ++ entitythrowntrident.shootFromRotation(entityhuman, entityhuman.getXRot(), entityhuman.getYRot(), 0.0F, 2.5F + (float) k * 0.5F, 1.0F); ++ if (entityhuman.getAbilities().instabuild) { ++ entitythrowntrident.pickup = AbstractArrow.Pickup.CREATIVE_ONLY; + } + +- level.addFreshEntity(thrownTrident); +- level.playSound(null, thrownTrident, SoundEvents.TRIDENT_THROW, SoundSource.PLAYERS, 1.0F, 1.0F); +- if (!player.getAbilities().instabuild) { +- player.getInventory().removeItem(stack); ++ // CraftBukkit start ++ if (!level.addFreshEntity(entitythrowntrident)) { ++ if (entityhuman instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } ++ return; + } ++ ++ stack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(entityLiving.getUsedItemHand()); ++ }); ++ entitythrowntrident.pickupItemStack = stack.copy(); // SPIGOT-4511 update since damage call moved ++ // CraftBukkit end ++ ++ level.playSound((Player) null, (Entity) entitythrowntrident, SoundEvents.TRIDENT_THROW, SoundSource.PLAYERS, 1.0F, 1.0F); ++ if (!entityhuman.getAbilities().instabuild) { ++ entityhuman.getInventory().removeItem(stack); ++ } ++ // CraftBukkit start - SPIGOT-5458 also need in this branch :( ++ } else { ++ stack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(entityLiving.getUsedItemHand()); ++ }); ++ // CraftBukkkit end + } + } + +- player.awardStat(Stats.ITEM_USED.get(this)); +- if (riptide > 0) { +- float yRot = player.getYRot(); +- float xRot = player.getXRot(); +- float f = -Mth.sin(yRot * (float) (Math.PI / 180.0)) * Mth.cos(xRot * (float) (Math.PI / 180.0)); +- float f1 = -Mth.sin(xRot * (float) (Math.PI / 180.0)); +- float f2 = Mth.cos(yRot * (float) (Math.PI / 180.0)) * Mth.cos(xRot * (float) (Math.PI / 180.0)); +- float squareRoot = Mth.sqrt(f * f + f1 * f1 + f2 * f2); +- float f3 = 3.0F * ((1.0F + (float)riptide) / 4.0F); +- f *= f3 / squareRoot; +- f1 *= f3 / squareRoot; +- f2 *= f3 / squareRoot; +- player.push((double)f, (double)f1, (double)f2); +- player.startAutoSpinAttack(20); +- if (player.onGround()) { +- float f4 = 1.1999999F; +- player.move(MoverType.SELF, new Vec3(0.0, 1.1999999F, 0.0)); ++ entityhuman.awardStat(Stats.ITEM_USED.get(this)); ++ if (k > 0) { ++ // CraftBukkit start ++ org.bukkit.event.player.PlayerRiptideEvent event = new org.bukkit.event.player.PlayerRiptideEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack)); ++ event.getPlayer().getServer().getPluginManager().callEvent(event); ++ // CraftBukkit end ++ float f = entityhuman.getYRot(); ++ float f1 = entityhuman.getXRot(); ++ float f2 = -Mth.sin(f * 0.017453292F) * Mth.cos(f1 * 0.017453292F); ++ float f3 = -Mth.sin(f1 * 0.017453292F); ++ float f4 = Mth.cos(f * 0.017453292F) * Mth.cos(f1 * 0.017453292F); ++ float f5 = Mth.sqrt(f2 * f2 + f3 * f3 + f4 * f4); ++ float f6 = 3.0F * ((1.0F + (float) k) / 4.0F); ++ ++ f2 *= f6 / f5; ++ f3 *= f6 / f5; ++ f4 *= f6 / f5; ++ entityhuman.push((double) f2, (double) f3, (double) f4); ++ entityhuman.startAutoSpinAttack(20); ++ if (entityhuman.onGround()) { ++ float f7 = 1.1999999F; ++ ++ entityhuman.move(EnumMoveType.SELF, new Vec3(0.0D, 1.1999999284744263D, 0.0D)); + } + +- SoundEvent soundEvent; +- if (riptide >= 3) { +- soundEvent = SoundEvents.TRIDENT_RIPTIDE_3; +- } else if (riptide == 2) { +- soundEvent = SoundEvents.TRIDENT_RIPTIDE_2; ++ SoundEvent soundeffect; ++ ++ if (k >= 3) { ++ soundeffect = SoundEvents.TRIDENT_RIPTIDE_3; ++ } else if (k == 2) { ++ soundeffect = SoundEvents.TRIDENT_RIPTIDE_2; + } else { +- soundEvent = SoundEvents.TRIDENT_RIPTIDE_1; ++ soundeffect = SoundEvents.TRIDENT_RIPTIDE_1; + } + +- level.playSound(null, player, soundEvent, SoundSource.PLAYERS, 1.0F, 1.0F); ++ level.playSound((Player) null, (Entity) entityhuman, soundeffect, SoundSource.PLAYERS, 1.0F, 1.0F); + } ++ + } + } + } + } + + @Override +- public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (itemInHand.getDamageValue() >= itemInHand.getMaxDamage() - 1) { +- return InteractionResultHolder.fail(itemInHand); +- } else if (EnchantmentHelper.getRiptide(itemInHand) > 0 && !player.isInWaterOrRain()) { +- return InteractionResultHolder.fail(itemInHand); ++ public InteractionResultHolder use(Level level, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (itemstack.getDamageValue() >= itemstack.getMaxDamage() - 1) { ++ return InteractionResultHolder.fail(itemstack); ++ } else if (EnchantmentHelper.getRiptide(itemstack) > 0 && !player.isInWaterOrRain()) { ++ return InteractionResultHolder.fail(itemstack); + } else { + player.startUsingItem(hand); +- return InteractionResultHolder.consume(itemInHand); ++ return InteractionResultHolder.consume(itemstack); + } + } + + @Override + public boolean hurtEnemy(ItemStack stack, LivingEntity target, LivingEntity attacker) { +- stack.hurtAndBreak(1, attacker, contextEntity -> contextEntity.broadcastBreakEvent(EquipmentSlot.MAINHAND)); ++ stack.hurtAndBreak(1, attacker, (entityliving2) -> { ++ entityliving2.broadcastBreakEvent(EquipmentSlot.MAINHAND); ++ }); + return true; + } + + @Override +- public boolean mineBlock(ItemStack stack, Level level, BlockState state, BlockPos pos, LivingEntity entityLiving) { +- if ((double)state.getDestroySpeed(level, pos) != 0.0) { +- stack.hurtAndBreak(2, entityLiving, contextEntity -> contextEntity.broadcastBreakEvent(EquipmentSlot.MAINHAND)); ++ public boolean mineBlock(ItemStack stack, Level level, IBlockData state, BlockPos pos, LivingEntity entityLiving) { ++ if ((double) state.getDestroySpeed(level, pos) != 0.0D) { ++ stack.hurtAndBreak(2, entityLiving, (entityliving1) -> { ++ entityliving1.broadcastBreakEvent(EquipmentSlot.MAINHAND); ++ }); + } + + return true; diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/BlastingRecipe.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/BlastingRecipe.java.patch new file mode 100644 index 0000000000..b1903d9db4 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/BlastingRecipe.java.patch @@ -0,0 +1,41 @@ +--- a/net/minecraft/world/item/crafting/BlastingRecipe.java ++++ b/net/minecraft/world/item/crafting/BlastingRecipe.java +@@ -3,9 +3,18 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftBlastingRecipe; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class BlastingRecipe extends AbstractCookingRecipe { +- public BlastingRecipe(String string, CookingBookCategory cookingBookCategory, Ingredient ingredient, ItemStack itemStack, float f, int i) { +- super(RecipeType.BLASTING, string, cookingBookCategory, ingredient, itemStack, f, i); ++ ++ public BlastingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient recipeitemstack, ItemStack itemstack, float f, int i) { ++ super(RecipeType.BLASTING, s, cookingbookcategory, recipeitemstack, itemstack, f, i); + } + + @Override +@@ -17,4 +26,17 @@ + public RecipeSerializer getSerializer() { + return RecipeSerializer.BLASTING_RECIPE; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftBlastingRecipe recipe = new CraftBlastingRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/CampfireCookingRecipe.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/CampfireCookingRecipe.java.patch new file mode 100644 index 0000000000..c92ff1542f --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/CampfireCookingRecipe.java.patch @@ -0,0 +1,41 @@ +--- a/net/minecraft/world/item/crafting/CampfireCookingRecipe.java ++++ b/net/minecraft/world/item/crafting/CampfireCookingRecipe.java +@@ -3,9 +3,18 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftCampfireRecipe; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class CampfireCookingRecipe extends AbstractCookingRecipe { +- public CampfireCookingRecipe(String string, CookingBookCategory cookingBookCategory, Ingredient ingredient, ItemStack itemStack, float f, int i) { +- super(RecipeType.CAMPFIRE_COOKING, string, cookingBookCategory, ingredient, itemStack, f, i); ++ ++ public CampfireCookingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient recipeitemstack, ItemStack itemstack, float f, int i) { ++ super(RecipeType.CAMPFIRE_COOKING, s, cookingbookcategory, recipeitemstack, itemstack, f, i); + } + + @Override +@@ -17,4 +26,17 @@ + public RecipeSerializer getSerializer() { + return RecipeSerializer.CAMPFIRE_COOKING_RECIPE; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftCampfireRecipe recipe = new CraftCampfireRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/CustomRecipe.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/CustomRecipe.java.patch new file mode 100644 index 0000000000..16057f8555 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/CustomRecipe.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/item/crafting/CustomRecipe.java ++++ b/net/minecraft/world/item/crafting/CustomRecipe.java +@@ -3,11 +3,17 @@ + import net.minecraft.core.RegistryAccess; + import net.minecraft.world.item.ItemStack; + +-public abstract class CustomRecipe implements CraftingRecipe { ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ ++public abstract class CustomRecipe implements RecipeCrafting { ++ + private final CraftingBookCategory category; + +- public CustomRecipe(CraftingBookCategory craftingBookCategory) { +- this.category = craftingBookCategory; ++ public CustomRecipe(CraftingBookCategory craftingbookcategory) { ++ this.category = craftingbookcategory; + } + + @Override +@@ -24,4 +30,11 @@ + public CraftingBookCategory category() { + return this.category; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ return new org.bukkit.craftbukkit.inventory.CraftComplexRecipe(id, this); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/Ingredient.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/Ingredient.java.patch new file mode 100644 index 0000000000..a4e23f27af --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/Ingredient.java.patch @@ -0,0 +1,323 @@ +--- a/net/minecraft/world/item/crafting/Ingredient.java ++++ b/net/minecraft/world/item/crafting/Ingredient.java +@@ -5,13 +5,13 @@ + import com.mojang.serialization.Codec; + import com.mojang.serialization.DataResult; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import it.unimi.dsi.fastutil.ints.IntArrayList; + import it.unimi.dsi.fastutil.ints.IntComparators; + import it.unimi.dsi.fastutil.ints.IntList; + import java.util.Arrays; + import java.util.Collection; + import java.util.Collections; ++import java.util.Iterator; + import java.util.List; + import java.util.function.Predicate; + import java.util.stream.Stream; +@@ -25,43 +25,64 @@ + import net.minecraft.world.entity.player.StackedContents; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + + public final class Ingredient implements Predicate { ++ + public static final Ingredient EMPTY = new Ingredient(Stream.empty()); +- private final Ingredient.Value[] values; ++ private final Ingredient.Provider[] values; + @Nullable +- private ItemStack[] itemStacks; ++ public ItemStack[] itemStacks; + @Nullable + private IntList stackingIds; ++ public boolean exact; // CraftBukkit + public static final Codec CODEC = codec(true); + public static final Codec CODEC_NONEMPTY = codec(false); + +- private Ingredient(Stream values) { +- this.values = values.toArray(Ingredient.Value[]::new); ++ public Ingredient(Stream values) { ++ this.values = (Ingredient.Provider[]) values.toArray((i) -> { ++ return new Ingredient.Provider[i]; ++ }); + } + +- private Ingredient(Ingredient.Value[] values) { +- this.values = values; ++ private Ingredient(Ingredient.Provider[] arecipeitemstack_provider) { ++ this.values = arecipeitemstack_provider; + } + + public ItemStack[] getItems() { + if (this.itemStacks == null) { +- this.itemStacks = Arrays.stream(this.values).flatMap(value -> value.getItems().stream()).distinct().toArray(ItemStack[]::new); ++ this.itemStacks = (ItemStack[]) Arrays.stream(this.values).flatMap((recipeitemstack_provider) -> { ++ return recipeitemstack_provider.getItems().stream(); ++ }).distinct().toArray((i) -> { ++ return new ItemStack[i]; ++ }); + } + + return this.itemStacks; + } + +- @Override + public boolean test(@Nullable ItemStack stack) { + if (stack == null) { + return false; + } else if (this.isEmpty()) { + return stack.isEmpty(); + } else { +- for (ItemStack itemStack : this.getItems()) { +- if (itemStack.is(stack.getItem())) { ++ ItemStack[] aitemstack = this.getItems(); ++ int i = aitemstack.length; ++ ++ for (int j = 0; j < i; ++j) { ++ ItemStack itemstack1 = aitemstack[j]; ++ ++ // CraftBukkit start ++ if (exact) { ++ if (itemstack1.getItem() == stack.getItem() && ItemStack.isSameItemSameTags(stack, itemstack1)) { ++ return true; ++ } ++ ++ continue; ++ } ++ // CraftBukkit end ++ if (itemstack1.is(stack.getItem())) { + return true; + } + } +@@ -72,11 +93,16 @@ + + public IntList getStackingIds() { + if (this.stackingIds == null) { +- ItemStack[] items = this.getItems(); +- this.stackingIds = new IntArrayList(items.length); ++ ItemStack[] aitemstack = this.getItems(); + +- for (ItemStack itemStack : items) { +- this.stackingIds.add(StackedContents.getStackingIndex(itemStack)); ++ this.stackingIds = new IntArrayList(aitemstack.length); ++ ItemStack[] aitemstack1 = aitemstack; ++ int i = aitemstack.length; ++ ++ for (int j = 0; j < i; ++j) { ++ ItemStack itemstack = aitemstack1[j]; ++ ++ this.stackingIds.add(StackedContents.getStackingIndex(itemstack)); + } + + this.stackingIds.sort(IntComparators.NATURAL_COMPARATOR); +@@ -93,21 +119,27 @@ + return this.values.length == 0; + } + +- @Override + public boolean equals(Object object) { +- return object instanceof Ingredient ingredient && Arrays.equals((Object[])this.values, (Object[])ingredient.values); ++ if (object instanceof Ingredient) { ++ Ingredient recipeitemstack = (Ingredient) object; ++ ++ return Arrays.equals(this.values, recipeitemstack.values); ++ } else { ++ return false; ++ } + } + +- private static Ingredient fromValues(Stream stream) { +- Ingredient ingredient = new Ingredient(stream); +- return ingredient.isEmpty() ? EMPTY : ingredient; ++ private static Ingredient fromValues(Stream stream) { ++ Ingredient recipeitemstack = new Ingredient(stream); ++ ++ return recipeitemstack.isEmpty() ? Ingredient.EMPTY : recipeitemstack; + } + + public static Ingredient of() { +- return EMPTY; ++ return Ingredient.EMPTY; + } + +- public static Ingredient of(ItemLike... items) { ++ public static Ingredient of(IMaterial... items) { + return of(Arrays.stream(items).map(ItemStack::new)); + } + +@@ -116,7 +148,9 @@ + } + + public static Ingredient of(Stream stacks) { +- return fromValues(stacks.filter(stack -> !stack.isEmpty()).map(Ingredient.ItemValue::new)); ++ return fromValues(stacks.filter((itemstack) -> { ++ return !itemstack.isEmpty(); ++ }).map(Ingredient.ItemValue::new)); + } + + public static Ingredient of(TagKey tag) { +@@ -124,67 +158,78 @@ + } + + public static Ingredient fromNetwork(FriendlyByteBuf buffer) { +- return fromValues(buffer.readList(FriendlyByteBuf::readItem).stream().map(Ingredient.ItemValue::new)); ++ return fromValues(buffer.readList(FriendlyByteBuf::readItem).stream().map(Ingredient.ItemValue::new)); + } + + private static Codec codec(boolean flag) { +- Codec codec = Codec.list(Ingredient.Value.CODEC) +- .comapFlatMap( +- list -> !flag && list.size() < 1 +- ? DataResult.error(() -> "Item array cannot be empty, at least one item must be defined") +- : DataResult.success(list.toArray(new Ingredient.Value[0])), +- List::of +- ); +- return ExtraCodecs.either(codec, Ingredient.Value.CODEC) +- .flatComapMap( +- either -> either.map(Ingredient::new, value -> new Ingredient(new Ingredient.Value[]{value})), +- ingredient -> { +- if (ingredient.values.length == 1) { +- return DataResult.success(Either.right(ingredient.values[0])); +- } else { +- return ingredient.values.length == 0 && !flag +- ? DataResult.error(() -> "Item array cannot be empty, at least one item must be defined") +- : DataResult.success(Either.left(ingredient.values)); +- } +- } +- ); ++ Codec codec = Codec.list(Ingredient.Provider.CODEC).comapFlatMap((list) -> { ++ return !flag && list.size() < 1 ? DataResult.error(() -> { ++ return "Item array cannot be empty, at least one item must be defined"; ++ }) : DataResult.success((Ingredient.Provider[]) list.toArray(new Ingredient.Provider[0])); ++ }, List::of); ++ ++ return ExtraCodecs.either(codec, Ingredient.Provider.CODEC).flatComapMap((either) -> { ++ return (Ingredient) either.map(Ingredient::new, (recipeitemstack_provider) -> { ++ return new Ingredient(new Ingredient.Provider[]{recipeitemstack_provider}); ++ }); ++ }, (recipeitemstack) -> { ++ return recipeitemstack.values.length == 1 ? DataResult.success(Either.right(recipeitemstack.values[0])) : (recipeitemstack.values.length == 0 && !flag ? DataResult.error(() -> { ++ return "Item array cannot be empty, at least one item must be defined"; ++ }) : DataResult.success(Either.left(recipeitemstack.values))); ++ }); + } + +- static record ItemValue(ItemStack item) implements Ingredient.Value { +- static final Codec CODEC = RecordCodecBuilder.create( +- instance -> instance.group(ItemStack.SINGLE_ITEM_CODEC.fieldOf("item").forGetter(itemValue -> itemValue.item)) +- .apply(instance, Ingredient.ItemValue::new) +- ); ++ public interface Provider { + +- @Override +- public boolean equals(Object object) { +- return object instanceof Ingredient.ItemValue itemValue +- && itemValue.item.getItem().equals(this.item.getItem()) +- && itemValue.item.getCount() == this.item.getCount(); +- } ++ Codec CODEC = ExtraCodecs.xor(Ingredient.ItemValue.CODEC, Ingredient.TagValue.CODEC).xmap((either) -> { ++ return (Ingredient.Provider) either.map((recipeitemstack_stackprovider) -> { ++ return recipeitemstack_stackprovider; ++ }, (recipeitemstack_b) -> { ++ return recipeitemstack_b; ++ }); ++ }, (recipeitemstack_provider) -> { ++ if (recipeitemstack_provider instanceof Ingredient.TagValue) { ++ Ingredient.TagValue recipeitemstack_b = (Ingredient.TagValue) recipeitemstack_provider; + +- @Override +- public Collection getItems() { +- return Collections.singleton(this.item); +- } ++ return Either.right(recipeitemstack_b); ++ } else if (recipeitemstack_provider instanceof Ingredient.ItemValue) { ++ Ingredient.ItemValue recipeitemstack_stackprovider = (Ingredient.ItemValue) recipeitemstack_provider; ++ ++ return Either.left(recipeitemstack_stackprovider); ++ } else { ++ throw new UnsupportedOperationException("This is neither an item value nor a tag value."); ++ } ++ }); ++ ++ Collection getItems(); + } + +- static record TagValue(TagKey tag) implements Ingredient.Value { +- static final Codec CODEC = RecordCodecBuilder.create( +- instance -> instance.group(TagKey.codec(Registries.ITEM).fieldOf("tag").forGetter(tagValue -> tagValue.tag)) +- .apply(instance, Ingredient.TagValue::new) +- ); ++ private static record TagValue(TagKey tag) implements Ingredient.Provider { + +- @Override ++ static final Codec CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(TagKey.codec(Registries.ITEM).fieldOf("tag").forGetter((recipeitemstack_b) -> { ++ return recipeitemstack_b.tag; ++ })).apply(instance, Ingredient.TagValue::new); ++ }); ++ + public boolean equals(Object object) { +- return object instanceof Ingredient.TagValue tagValue && tagValue.tag.location().equals(this.tag.location()); ++ if (object instanceof Ingredient.TagValue) { ++ Ingredient.TagValue recipeitemstack_b = (Ingredient.TagValue) object; ++ ++ return recipeitemstack_b.tag.location().equals(this.tag.location()); ++ } else { ++ return false; ++ } + } + + @Override + public Collection getItems() { + List list = Lists.newArrayList(); ++ Iterator iterator = BuiltInRegistries.ITEM.getTagOrEmpty(this.tag).iterator(); + +- for (Holder holder : BuiltInRegistries.ITEM.getTagOrEmpty(this.tag)) { ++ while (iterator.hasNext()) { ++ Holder holder = (Holder) iterator.next(); ++ + list.add(new ItemStack(holder)); + } + +@@ -192,18 +237,27 @@ + } + } + +- interface Value { +- Codec CODEC = ExtraCodecs.xor(Ingredient.ItemValue.CODEC, Ingredient.TagValue.CODEC) +- .xmap(either -> either.map(itemValue -> itemValue, tagValue -> tagValue), value -> { +- if (value instanceof Ingredient.TagValue tagValue) { +- return Either.right(tagValue); +- } else if (value instanceof Ingredient.ItemValue itemValue) { +- return Either.left(itemValue); +- } else { +- throw new UnsupportedOperationException("This is neither an item value nor a tag value."); +- } +- }); ++ public static record ItemValue(ItemStack item) implements Ingredient.Provider { + +- Collection getItems(); ++ static final Codec CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(ItemStack.SINGLE_ITEM_CODEC.fieldOf("item").forGetter((recipeitemstack_stackprovider) -> { ++ return recipeitemstack_stackprovider.item; ++ })).apply(instance, Ingredient.ItemValue::new); ++ }); ++ ++ public boolean equals(Object object) { ++ if (!(object instanceof Ingredient.ItemValue)) { ++ return false; ++ } else { ++ Ingredient.ItemValue recipeitemstack_stackprovider = (Ingredient.ItemValue) object; ++ ++ return recipeitemstack_stackprovider.item.getItem().equals(this.item.getItem()) && recipeitemstack_stackprovider.item.getCount() == this.item.getCount(); ++ } ++ } ++ ++ @Override ++ public Collection getItems() { ++ return Collections.singleton(this.item); ++ } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/Recipe.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/Recipe.java.patch new file mode 100644 index 0000000000..0d6b152103 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/Recipe.java.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/world/item/crafting/Recipe.java ++++ b/net/minecraft/world/item/crafting/Recipe.java +@@ -11,6 +11,7 @@ + import net.minecraft.world.level.block.Blocks; + + public interface Recipe { ++ + Codec> CODEC = BuiltInRegistries.RECIPE_SERIALIZER.byNameCodec().dispatch(Recipe::getSerializer, RecipeSerializer::codec); + + boolean matches(C container, Level level); +@@ -22,16 +23,17 @@ + ItemStack getResultItem(RegistryAccess registryAccess); + + default NonNullList getRemainingItems(C container) { +- NonNullList list = NonNullList.withSize(container.getContainerSize(), ItemStack.EMPTY); ++ NonNullList nonnulllist = NonNullList.withSize(container.getContainerSize(), ItemStack.EMPTY); + +- for (int i = 0; i < list.size(); i++) { ++ for (int i = 0; i < nonnulllist.size(); ++i) { + Item item = container.getItem(i).getItem(); ++ + if (item.hasCraftingRemainingItem()) { +- list.set(i, new ItemStack(item.getCraftingRemainingItem())); ++ nonnulllist.set(i, new ItemStack(item.getCraftingRemainingItem())); + } + } + +- return list; ++ return nonnulllist; + } + + default NonNullList getIngredients() { +@@ -59,7 +61,12 @@ + RecipeType getType(); + + default boolean isIncomplete() { +- NonNullList ingredients = this.getIngredients(); +- return ingredients.isEmpty() || ingredients.stream().anyMatch(ingredient -> ingredient.getItems().length == 0); ++ NonNullList nonnulllist = this.getIngredients(); ++ ++ return nonnulllist.isEmpty() || nonnulllist.stream().anyMatch((recipeitemstack) -> { ++ return recipeitemstack.getItems().length == 0; ++ }); + } ++ ++ org.bukkit.inventory.Recipe toBukkitRecipe(org.bukkit.NamespacedKey id); // CraftBukkit + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/RecipeHolder.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/RecipeHolder.java.patch new file mode 100644 index 0000000000..b9dcb13846 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/RecipeHolder.java.patch @@ -0,0 +1,51 @@ +--- a/net/minecraft/world/item/crafting/RecipeHolder.java ++++ b/net/minecraft/world/item/crafting/RecipeHolder.java +@@ -1,27 +1,41 @@ + package net.minecraft.world.item.crafting; + + import net.minecraft.resources.ResourceLocation; ++// CraftBukkit start ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.inventory.Recipe; + +-public record RecipeHolder>(ResourceLocation id, T value) { +- @Override ++public record RecipeHolder>(ResourceLocation id, T value) { ++ ++ public final Recipe toBukkitRecipe() { ++ return this.value.toBukkitRecipe(CraftNamespacedKey.fromMinecraft(this.id)); ++ } ++ // CraftBukkit end ++ + public boolean equals(Object object) { + if (this == object) { + return true; + } else { +- if (object instanceof RecipeHolder recipeHolder && this.id.equals(recipeHolder.id)) { +- return true; ++ boolean flag; ++ ++ if (object instanceof RecipeHolder) { ++ RecipeHolder recipeholder = (RecipeHolder) object; ++ ++ if (this.id.equals(recipeholder.id)) { ++ flag = true; ++ return flag; ++ } + } + +- return false; ++ flag = false; ++ return flag; + } + } + +- @Override + public int hashCode() { + return this.id.hashCode(); + } + +- @Override + public String toString() { + return this.id.toString(); + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/RecipeManager.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/RecipeManager.java.patch new file mode 100644 index 0000000000..bef8eeac66 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/RecipeManager.java.patch @@ -0,0 +1,322 @@ +--- a/net/minecraft/world/item/crafting/RecipeManager.java ++++ b/net/minecraft/world/item/crafting/RecipeManager.java +@@ -1,8 +1,8 @@ + package net.minecraft.world.item.crafting; + + import com.google.common.collect.ImmutableMap; +-import com.google.common.collect.Maps; + import com.google.common.collect.ImmutableMap.Builder; ++import com.google.common.collect.Maps; + import com.google.gson.Gson; + import com.google.gson.GsonBuilder; + import com.google.gson.JsonElement; +@@ -14,83 +14,122 @@ + import java.util.Collection; + import java.util.Collections; + import java.util.Comparator; ++import java.util.Iterator; + import java.util.List; + import java.util.Map; +-import java.util.Optional; + import java.util.Map.Entry; ++import java.util.Optional; + import java.util.stream.Collectors; + import java.util.stream.Stream; + import javax.annotation.Nullable; + import net.minecraft.Util; + import net.minecraft.core.NonNullList; ++import net.minecraft.world.Container; ++import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.level.Level; ++import org.slf4j.Logger; ++ ++// CraftBukkit start ++import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; ++import net.minecraft.core.registries.BuiltInRegistries; ++// CraftBukkit end + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.packs.resources.ResourceManager; + import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; + import net.minecraft.util.GsonHelper; + import net.minecraft.util.profiling.ProfilerFiller; +-import net.minecraft.world.Container; +-import net.minecraft.world.item.ItemStack; +-import net.minecraft.world.level.Level; +-import org.slf4j.Logger; + + public class RecipeManager extends SimpleJsonResourceReloadListener { +- private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); ++ ++ private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().disableHtmlEscaping().create(); + private static final Logger LOGGER = LogUtils.getLogger(); +- private Map, Map>> recipes = ImmutableMap.of(); ++ public Map, Object2ObjectLinkedOpenHashMap>> recipes = ImmutableMap.of(); // CraftBukkit + private Map> byName = ImmutableMap.of(); + private boolean hasErrors; + + public RecipeManager() { +- super(GSON, "recipes"); ++ super(RecipeManager.GSON, "recipes"); + } + +- @Override + protected void apply(Map object, ResourceManager resourceManager, ProfilerFiller profiler) { + this.hasErrors = false; +- Map, Builder>> map = Maps.newHashMap(); ++ // CraftBukkit start - SPIGOT-5667 make sure all types are populated and mutable ++ Map, Object2ObjectLinkedOpenHashMap>> map1 = Maps.newHashMap(); ++ for (RecipeType recipeType : BuiltInRegistries.RECIPE_TYPE) { ++ map1.put(recipeType, new Object2ObjectLinkedOpenHashMap<>()); ++ } ++ // CraftBukkit end + Builder> builder = ImmutableMap.builder(); ++ Iterator iterator = object.entrySet().iterator(); + +- for (Entry entry : object.entrySet()) { +- ResourceLocation resourceLocation = entry.getKey(); ++ while (iterator.hasNext()) { ++ Entry entry = (Entry) iterator.next(); ++ ResourceLocation minecraftkey = (ResourceLocation) entry.getKey(); + + try { +- RecipeHolder recipeHolder = fromJson(resourceLocation, GsonHelper.convertToJsonObject(entry.getValue(), "top element")); +- map.computeIfAbsent(recipeHolder.value().getType(), type -> ImmutableMap.builder()).put(resourceLocation, recipeHolder); +- builder.put(resourceLocation, recipeHolder); +- } catch (IllegalArgumentException | JsonParseException var10) { +- LOGGER.error("Parsing error loading recipe {}", resourceLocation, var10); ++ RecipeHolder recipeholder = fromJson(minecraftkey, GsonHelper.convertToJsonObject((JsonElement) entry.getValue(), "top element")); ++ ++ // CraftBukkit start ++ (map1.computeIfAbsent(recipeholder.value().getType(), (recipes) -> { ++ return new Object2ObjectLinkedOpenHashMap<>(); ++ // CraftBukkit end ++ })).put(minecraftkey, recipeholder); ++ builder.put(minecraftkey, recipeholder); ++ } catch (IllegalArgumentException | JsonParseException jsonparseexception) { ++ RecipeManager.LOGGER.error("Parsing error loading recipe {}", minecraftkey, jsonparseexception); + } + } + +- this.recipes = map.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, entry1 -> entry1.getValue().build())); +- this.byName = builder.build(); +- LOGGER.info("Loaded {} recipes", map.size()); ++ this.recipes = (Map) map1.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry1) -> { ++ return (entry1.getValue()); // CraftBukkit ++ })); ++ this.byName = Maps.newHashMap(builder.build()); // CraftBukkit ++ RecipeManager.LOGGER.info("Loaded {} recipes", map1.size()); + } + ++ // CraftBukkit start ++ public void addRecipe(RecipeHolder irecipe) { ++ Object2ObjectLinkedOpenHashMap> map = this.recipes.get(irecipe.value().getType()); // CraftBukkit ++ ++ if (byName.containsKey(irecipe.id()) || map.containsKey(irecipe.id())) { ++ throw new IllegalStateException("Duplicate recipe ignored with ID " + irecipe.id()); ++ } else { ++ map.putAndMoveToFirst(irecipe.id(), irecipe); // CraftBukkit - SPIGOT-4638: last recipe gets priority ++ byName.put(irecipe.id(), irecipe); ++ } ++ } ++ // CraftBukkit end ++ + public boolean hadErrorsLoading() { + return this.hasErrors; + } + + public > Optional> getRecipeFor(RecipeType recipeType, C inventory, Level level) { +- return this.byType(recipeType).values().stream().filter(recipeHolder -> recipeHolder.value().matches(inventory, level)).findFirst(); ++ // CraftBukkit start ++ Optional> recipe = this.byType(recipeType).values().stream().filter((recipeholder) -> { ++ return recipeholder.value().matches(inventory, level); ++ }).findFirst(); ++ inventory.setCurrentRecipe(recipe.orElse(null)); // CraftBukkit - Clear recipe when no recipe is found ++ return recipe; ++ // CraftBukkit end + } + +- public > Optional>> getRecipeFor( +- RecipeType recipeType, C inventory, Level level, @Nullable ResourceLocation lastRecipe +- ) { ++ public > Optional>> getRecipeFor(RecipeType recipeType, C inventory, Level level, @Nullable ResourceLocation lastRecipe) { + Map> map = this.byType(recipeType); ++ + if (lastRecipe != null) { +- RecipeHolder recipeHolder = map.get(lastRecipe); +- if (recipeHolder != null && recipeHolder.value().matches(inventory, level)) { +- return Optional.of(Pair.of(lastRecipe, recipeHolder)); ++ RecipeHolder recipeholder = (RecipeHolder) map.get(lastRecipe); ++ ++ if (recipeholder != null && recipeholder.value().matches(inventory, level)) { ++ return Optional.of(Pair.of(lastRecipe, recipeholder)); + } + } + +- return map.entrySet() +- .stream() +- .filter(entry -> entry.getValue().value().matches(inventory, level)) +- .findFirst() +- .map(entry -> Pair.of(entry.getKey(), entry.getValue())); ++ return map.entrySet().stream().filter((entry) -> { ++ return ((RecipeHolder) entry.getValue()).value().matches(inventory, level); ++ }).findFirst().map((entry) -> { ++ return Pair.of((ResourceLocation) entry.getKey(), (RecipeHolder) entry.getValue()); ++ }); + } + + public > List> getAllRecipesFor(RecipeType recipeType) { +@@ -98,67 +137,96 @@ + } + + public > List> getRecipesFor(RecipeType recipeType, C inventory, Level level) { +- return this.byType(recipeType) +- .values() +- .stream() +- .filter(recipeHolder -> recipeHolder.value().matches(inventory, level)) +- .sorted(Comparator.comparing(recipeHolder -> recipeHolder.value().getResultItem(level.registryAccess()).getDescriptionId())) +- .collect(Collectors.toList()); ++ return (List) this.byType(recipeType).values().stream().filter((recipeholder) -> { ++ return recipeholder.value().matches(inventory, level); ++ }).sorted(Comparator.comparing((recipeholder) -> { ++ return recipeholder.value().getResultItem(level.registryAccess()).getDescriptionId(); ++ })).collect(Collectors.toList()); + } + + private > Map> byType(RecipeType recipeType) { +- return (Map>) ((Map) this.recipes.getOrDefault(recipeType, Collections.emptyMap())); ++ return (Map) this.recipes.getOrDefault(recipeType, new Object2ObjectLinkedOpenHashMap<>()); // CraftBukkit + } + + public > NonNullList getRemainingItemsFor(RecipeType recipeType, C inventory, Level level) { +- Optional> recipeFor = this.getRecipeFor(recipeType, inventory, level); +- if (recipeFor.isPresent()) { +- return recipeFor.get().value().getRemainingItems(inventory); ++ Optional> optional = this.getRecipeFor(recipeType, inventory, level); ++ ++ if (optional.isPresent()) { ++ return ((RecipeHolder) optional.get()).value().getRemainingItems(inventory); + } else { +- NonNullList list = NonNullList.withSize(inventory.getContainerSize(), ItemStack.EMPTY); ++ NonNullList nonnulllist = NonNullList.withSize(inventory.getContainerSize(), ItemStack.EMPTY); + +- for (int i = 0; i < list.size(); i++) { +- list.set(i, inventory.getItem(i)); ++ for (int i = 0; i < nonnulllist.size(); ++i) { ++ nonnulllist.set(i, inventory.getItem(i)); + } + +- return list; ++ return nonnulllist; + } + } + + public Optional> byKey(ResourceLocation recipeId) { +- return Optional.ofNullable(this.byName.get(recipeId)); ++ return Optional.ofNullable((RecipeHolder) this.byName.get(recipeId)); + } + + public Collection> getRecipes() { +- return this.recipes.values().stream().flatMap(map -> map.values().stream()).collect(Collectors.toSet()); ++ return (Collection) this.recipes.values().stream().flatMap((map) -> { ++ return map.values().stream(); ++ }).collect(Collectors.toSet()); + } + + public Stream getRecipeIds() { +- return this.recipes.values().stream().flatMap(map -> map.keySet().stream()); ++ return this.recipes.values().stream().flatMap((map) -> { ++ return map.keySet().stream(); ++ }); + } + +- protected static RecipeHolder fromJson(ResourceLocation resourceLocation, JsonObject jsonObject) { +- Recipe recipe = Util.getOrThrow(Recipe.CODEC.parse(JsonOps.INSTANCE, jsonObject), JsonParseException::new); +- return new RecipeHolder<>(resourceLocation, recipe); ++ protected static RecipeHolder fromJson(ResourceLocation minecraftkey, JsonObject jsonobject) { ++ Recipe irecipe = (Recipe) Util.getOrThrow(Recipe.CODEC.parse(JsonOps.INSTANCE, jsonobject), JsonParseException::new); ++ ++ return new RecipeHolder<>(minecraftkey, irecipe); + } + + public void replaceRecipes(Iterable> recipes) { + this.hasErrors = false; +- Map, Map>> map = Maps.newHashMap(); ++ Map, Object2ObjectLinkedOpenHashMap>> map = Maps.newHashMap(); // CraftBukkit + Builder> builder = ImmutableMap.builder(); +- recipes.forEach(recipeHolder -> { +- Map> map1 = map.computeIfAbsent(recipeHolder.value().getType(), recipeType -> Maps.newHashMap()); +- ResourceLocation resourceLocation = recipeHolder.id(); +- RecipeHolder recipeHolder1 = map1.put(resourceLocation, (RecipeHolder)recipeHolder); +- builder.put(resourceLocation, (RecipeHolder)recipeHolder); +- if (recipeHolder1 != null) { +- throw new IllegalStateException("Duplicate recipe ignored with ID " + resourceLocation); ++ ++ recipes.forEach((recipeholder) -> { ++ Map> map1 = (Map) map.computeIfAbsent(recipeholder.value().getType(), (recipes) -> { ++ return new Object2ObjectLinkedOpenHashMap<>(); // CraftBukkit ++ }); ++ ResourceLocation minecraftkey = recipeholder.id(); ++ RecipeHolder recipeholder1 = (RecipeHolder) map1.put(minecraftkey, recipeholder); ++ ++ builder.put(minecraftkey, recipeholder); ++ if (recipeholder1 != null) { ++ throw new IllegalStateException("Duplicate recipe ignored with ID " + minecraftkey); + } + }); + this.recipes = ImmutableMap.copyOf(map); +- this.byName = builder.build(); ++ this.byName = Maps.newHashMap(builder.build()); // CraftBukkit + } + ++ // CraftBukkit start ++ public boolean removeRecipe(ResourceLocation mcKey) { ++ for (Object2ObjectLinkedOpenHashMap> recipes : recipes.values()) { ++ recipes.remove(mcKey); ++ } ++ ++ return byName.remove(mcKey) != null; ++ } ++ ++ public void clearRecipes() { ++ this.recipes = Maps.newHashMap(); ++ ++ for (RecipeType recipeType : BuiltInRegistries.RECIPE_TYPE) { ++ this.recipes.put(recipeType, new Object2ObjectLinkedOpenHashMap<>()); ++ } ++ ++ this.byName = Maps.newHashMap(); ++ } ++ // CraftBukkit end ++ + public static > RecipeManager.CachedCheck createCheck(final RecipeType recipeType) { + return new RecipeManager.CachedCheck() { + @Nullable +@@ -166,12 +234,14 @@ + + @Override + public Optional> getRecipeFor(C container, Level level) { +- RecipeManager recipeManager = level.getRecipeManager(); +- Optional>> recipeFor = recipeManager.getRecipeFor(recipeType, container, level, this.lastRecipe); +- if (recipeFor.isPresent()) { +- Pair> pair = recipeFor.get(); +- this.lastRecipe = pair.getFirst(); +- return Optional.of(pair.getSecond()); ++ RecipeManager craftingmanager = level.getRecipeManager(); ++ Optional>> optional = craftingmanager.getRecipeFor(recipeType, container, level, this.lastRecipe); ++ ++ if (optional.isPresent()) { ++ Pair> pair = (Pair) optional.get(); ++ ++ this.lastRecipe = (ResourceLocation) pair.getFirst(); ++ return Optional.of((RecipeHolder) pair.getSecond()); + } else { + return Optional.empty(); + } +@@ -180,6 +250,7 @@ + } + + public interface CachedCheck> { ++ + Optional> getRecipeFor(C container, Level level); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/ShapedRecipe.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/ShapedRecipe.java.patch new file mode 100644 index 0000000000..bf7e64ba97 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/ShapedRecipe.java.patch @@ -0,0 +1,205 @@ +--- a/net/minecraft/world/item/crafting/ShapedRecipe.java ++++ b/net/minecraft/world/item/crafting/ShapedRecipe.java +@@ -2,35 +2,104 @@ + + import com.mojang.serialization.Codec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import net.minecraft.core.NonNullList; + import net.minecraft.core.RegistryAccess; + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.util.ExtraCodecs; +-import net.minecraft.world.inventory.CraftingContainer; ++import net.minecraft.world.inventory.InventoryCrafting; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftShapedRecipe; ++import org.bukkit.inventory.RecipeChoice; ++// CraftBukkit end + +-public class ShapedRecipe implements CraftingRecipe { ++public class ShapedRecipe implements RecipeCrafting { ++ + final ShapedRecipePattern pattern; + final ItemStack result; + final String group; + final CraftingBookCategory category; + final boolean showNotification; + +- public ShapedRecipe(String string, CraftingBookCategory craftingBookCategory, ShapedRecipePattern shapedRecipePattern, ItemStack itemStack, boolean flag) { +- this.group = string; +- this.category = craftingBookCategory; +- this.pattern = shapedRecipePattern; +- this.result = itemStack; ++ public ShapedRecipe(String s, CraftingBookCategory craftingbookcategory, ShapedRecipePattern shapedrecipepattern, ItemStack itemstack, boolean flag) { ++ this.group = s; ++ this.category = craftingbookcategory; ++ this.pattern = shapedrecipepattern; ++ this.result = itemstack; + this.showNotification = flag; + } + +- public ShapedRecipe(String string, CraftingBookCategory craftingBookCategory, ShapedRecipePattern shapedRecipePattern, ItemStack itemStack) { +- this(string, craftingBookCategory, shapedRecipePattern, itemStack, true); ++ public ShapedRecipe(String s, CraftingBookCategory craftingbookcategory, ShapedRecipePattern shapedrecipepattern, ItemStack itemstack) { ++ this(s, craftingbookcategory, shapedrecipepattern, itemstack, true); + } + ++ // CraftBukkit start + @Override ++ public org.bukkit.inventory.ShapedRecipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ CraftShapedRecipe recipe = new CraftShapedRecipe(id, result, this); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ switch (this.pattern.height()) { ++ case 1: ++ switch (this.pattern.width()) { ++ case 1: ++ recipe.shape("a"); ++ break; ++ case 2: ++ recipe.shape("ab"); ++ break; ++ case 3: ++ recipe.shape("abc"); ++ break; ++ } ++ break; ++ case 2: ++ switch (this.pattern.width()) { ++ case 1: ++ recipe.shape("a","b"); ++ break; ++ case 2: ++ recipe.shape("ab","cd"); ++ break; ++ case 3: ++ recipe.shape("abc","def"); ++ break; ++ } ++ break; ++ case 3: ++ switch (this.pattern.width()) { ++ case 1: ++ recipe.shape("a","b","c"); ++ break; ++ case 2: ++ recipe.shape("ab","cd","ef"); ++ break; ++ case 3: ++ recipe.shape("abc","def","ghi"); ++ break; ++ } ++ break; ++ } ++ char c = 'a'; ++ for (Ingredient list : this.pattern.ingredients()) { ++ RecipeChoice choice = CraftRecipe.toBukkit(list); ++ if (choice != null) { ++ recipe.setIngredient(c, choice); ++ } ++ ++ c++; ++ } ++ return recipe; ++ } ++ // CraftBukkit end ++ ++ @Override + public RecipeSerializer getSerializer() { + return RecipeSerializer.SHAPED_RECIPE; + } +@@ -65,13 +134,11 @@ + return width >= this.pattern.width() && height >= this.pattern.height(); + } + +- @Override +- public boolean matches(CraftingContainer inv, Level level) { ++ public boolean matches(InventoryCrafting inv, Level level) { + return this.pattern.matches(inv); + } + +- @Override +- public ItemStack assemble(CraftingContainer container, RegistryAccess registryAccess) { ++ public ItemStack assemble(InventoryCrafting container, RegistryAccess registryAccess) { + return this.getResultItem(registryAccess).copy(); + } + +@@ -85,39 +152,49 @@ + + @Override + public boolean isIncomplete() { +- NonNullList ingredients = this.getIngredients(); +- return ingredients.isEmpty() +- || ingredients.stream().filter(ingredient -> !ingredient.isEmpty()).anyMatch(filteredIngredients -> filteredIngredients.getItems().length == 0); ++ NonNullList nonnulllist = this.getIngredients(); ++ ++ return nonnulllist.isEmpty() || nonnulllist.stream().filter((recipeitemstack) -> { ++ return !recipeitemstack.isEmpty(); ++ }).anyMatch((recipeitemstack) -> { ++ return recipeitemstack.getItems().length == 0; ++ }); + } + + public static class Serializer implements RecipeSerializer { +- public static final Codec CODEC = RecordCodecBuilder.create( +- instance -> instance.group( +- ExtraCodecs.strictOptionalField(Codec.STRING, "group", "").forGetter(shapedRecipe -> shapedRecipe.group), +- CraftingBookCategory.CODEC.fieldOf("category").orElse(CraftingBookCategory.MISC).forGetter(shapedRecipe -> shapedRecipe.category), +- ShapedRecipePattern.MAP_CODEC.forGetter(shapedRecipe -> shapedRecipe.pattern), +- ItemStack.ITEM_WITH_COUNT_CODEC.fieldOf("result").forGetter(shapedRecipe -> shapedRecipe.result), +- ExtraCodecs.strictOptionalField(Codec.BOOL, "show_notification", true).forGetter(shapedRecipe -> shapedRecipe.showNotification) +- ) +- .apply(instance, ShapedRecipe::new) +- ); + ++ public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(ExtraCodecs.strictOptionalField(Codec.STRING, "group", "").forGetter((shapedrecipes) -> { ++ return shapedrecipes.group; ++ }), CraftingBookCategory.CODEC.fieldOf("category").orElse(CraftingBookCategory.MISC).forGetter((shapedrecipes) -> { ++ return shapedrecipes.category; ++ }), ShapedRecipePattern.MAP_CODEC.forGetter((shapedrecipes) -> { ++ return shapedrecipes.pattern; ++ }), ItemStack.ITEM_WITH_COUNT_CODEC.fieldOf("result").forGetter((shapedrecipes) -> { ++ return shapedrecipes.result; ++ }), ExtraCodecs.strictOptionalField(Codec.BOOL, "show_notification", true).forGetter((shapedrecipes) -> { ++ return shapedrecipes.showNotification; ++ })).apply(instance, ShapedRecipe::new); ++ }); ++ ++ public Serializer() {} ++ + @Override + public Codec codec() { +- return CODEC; ++ return ShapedRecipe.Serializer.CODEC; + } + + @Override +- public ShapedRecipe fromNetwork(FriendlyByteBuf friendlyByteBuf) { +- String utf = friendlyByteBuf.readUtf(); +- CraftingBookCategory craftingBookCategory = friendlyByteBuf.readEnum(CraftingBookCategory.class); +- ShapedRecipePattern shapedRecipePattern = ShapedRecipePattern.fromNetwork(friendlyByteBuf); +- ItemStack item = friendlyByteBuf.readItem(); +- boolean _boolean = friendlyByteBuf.readBoolean(); +- return new ShapedRecipe(utf, craftingBookCategory, shapedRecipePattern, item, _boolean); ++ public ShapedRecipe fromNetwork(FriendlyByteBuf packetdataserializer) { ++ String s = packetdataserializer.readUtf(); ++ CraftingBookCategory craftingbookcategory = (CraftingBookCategory) packetdataserializer.readEnum(CraftingBookCategory.class); ++ ShapedRecipePattern shapedrecipepattern = ShapedRecipePattern.fromNetwork(packetdataserializer); ++ ItemStack itemstack = packetdataserializer.readItem(); ++ boolean flag = packetdataserializer.readBoolean(); ++ ++ return new ShapedRecipe(s, craftingbookcategory, shapedrecipepattern, itemstack, flag); + } + +- @Override + public void toNetwork(FriendlyByteBuf buffer, ShapedRecipe recipe) { + buffer.writeUtf(recipe.group); + buffer.writeEnum(recipe.category); diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/ShapelessRecipe.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/ShapelessRecipe.java.patch new file mode 100644 index 0000000000..0434c3100b --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/ShapelessRecipe.java.patch @@ -0,0 +1,204 @@ +--- a/net/minecraft/world/item/crafting/ShapelessRecipe.java ++++ b/net/minecraft/world/item/crafting/ShapelessRecipe.java +@@ -3,31 +3,54 @@ + import com.mojang.serialization.Codec; + import com.mojang.serialization.DataResult; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; +-import java.util.List; ++import it.unimi.dsi.fastutil.ints.IntList; ++import java.util.Iterator; + import net.minecraft.core.NonNullList; + import net.minecraft.core.RegistryAccess; + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.util.ExtraCodecs; + import net.minecraft.world.entity.player.StackedContents; +-import net.minecraft.world.inventory.CraftingContainer; ++import net.minecraft.world.inventory.InventoryCrafting; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftShapelessRecipe; ++// CraftBukkit end + +-public class ShapelessRecipe implements CraftingRecipe { ++public class ShapelessRecipe implements RecipeCrafting { ++ + final String group; + final CraftingBookCategory category; + final ItemStack result; + final NonNullList ingredients; + +- public ShapelessRecipe(String string, CraftingBookCategory craftingBookCategory, ItemStack itemStack, NonNullList list) { +- this.group = string; +- this.category = craftingBookCategory; +- this.result = itemStack; +- this.ingredients = list; ++ public ShapelessRecipe(String s, CraftingBookCategory craftingbookcategory, ItemStack itemstack, NonNullList nonnulllist) { ++ this.group = s; ++ this.category = craftingbookcategory; ++ this.result = itemstack; ++ this.ingredients = nonnulllist; + } + ++ // CraftBukkit start ++ @SuppressWarnings("unchecked") + @Override ++ public org.bukkit.inventory.ShapelessRecipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ CraftShapelessRecipe recipe = new CraftShapelessRecipe(id, result, this); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ for (Ingredient list : this.ingredients) { ++ recipe.addIngredient(CraftRecipe.toBukkit(list)); ++ } ++ return recipe; ++ } ++ // CraftBukkit end ++ ++ @Override + public RecipeSerializer getSerializer() { + return RecipeSerializer.SHAPELESS_RECIPE; + } +@@ -52,24 +75,23 @@ + return this.ingredients; + } + +- @Override +- public boolean matches(CraftingContainer inv, Level level) { +- StackedContents stackedContents = new StackedContents(); ++ public boolean matches(InventoryCrafting inv, Level level) { ++ StackedContents autorecipestackmanager = new StackedContents(); + int i = 0; + +- for (int i1 = 0; i1 < inv.getContainerSize(); i1++) { +- ItemStack item = inv.getItem(i1); +- if (!item.isEmpty()) { +- i++; +- stackedContents.accountStack(item, 1); ++ for (int j = 0; j < inv.getContainerSize(); ++j) { ++ ItemStack itemstack = inv.getItem(j); ++ ++ if (!itemstack.isEmpty()) { ++ ++i; ++ autorecipestackmanager.accountStack(itemstack, 1); + } + } + +- return i == this.ingredients.size() && stackedContents.canCraft(this, null); ++ return i == this.ingredients.size() && autorecipestackmanager.canCraft(this, (IntList) null); + } + +- @Override +- public ItemStack assemble(CraftingContainer container, RegistryAccess registryAccess) { ++ public ItemStack assemble(InventoryCrafting container, RegistryAccess registryAccess) { + return this.result.copy(); + } + +@@ -79,60 +101,64 @@ + } + + public static class Serializer implements RecipeSerializer { +- private static final Codec CODEC = RecordCodecBuilder.create( +- instance -> instance.group( +- ExtraCodecs.strictOptionalField(Codec.STRING, "group", "").forGetter(shapelessRecipe -> shapelessRecipe.group), +- CraftingBookCategory.CODEC.fieldOf("category").orElse(CraftingBookCategory.MISC).forGetter(shapelessRecipe -> shapelessRecipe.category), +- ItemStack.ITEM_WITH_COUNT_CODEC.fieldOf("result").forGetter(shapelessRecipe -> shapelessRecipe.result), +- Ingredient.CODEC_NONEMPTY +- .listOf() +- .fieldOf("ingredients") +- .flatXmap( +- list -> { +- Ingredient[] ingredients = list.stream().filter(ingredient -> !ingredient.isEmpty()).toArray(Ingredient[]::new); +- if (ingredients.length == 0) { +- return DataResult.error(() -> "No ingredients for shapeless recipe"); +- } else { +- return ingredients.length > 9 +- ? DataResult.error(() -> "Too many ingredients for shapeless recipe") +- : DataResult.success(NonNullList.of(Ingredient.EMPTY, ingredients)); +- } +- }, +- DataResult::success +- ) +- .forGetter(shapelessRecipe -> shapelessRecipe.ingredients) +- ) +- .apply(instance, ShapelessRecipe::new) +- ); + ++ private static final Codec CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(ExtraCodecs.strictOptionalField(Codec.STRING, "group", "").forGetter((shapelessrecipes) -> { ++ return shapelessrecipes.group; ++ }), CraftingBookCategory.CODEC.fieldOf("category").orElse(CraftingBookCategory.MISC).forGetter((shapelessrecipes) -> { ++ return shapelessrecipes.category; ++ }), ItemStack.ITEM_WITH_COUNT_CODEC.fieldOf("result").forGetter((shapelessrecipes) -> { ++ return shapelessrecipes.result; ++ }), Ingredient.CODEC_NONEMPTY.listOf().fieldOf("ingredients").flatXmap((list) -> { ++ Ingredient[] arecipeitemstack = (Ingredient[]) list.stream().filter((recipeitemstack) -> { ++ return !recipeitemstack.isEmpty(); ++ }).toArray((i) -> { ++ return new Ingredient[i]; ++ }); ++ ++ return arecipeitemstack.length == 0 ? DataResult.error(() -> { ++ return "No ingredients for shapeless recipe"; ++ }) : (arecipeitemstack.length > 9 ? DataResult.error(() -> { ++ return "Too many ingredients for shapeless recipe"; ++ }) : DataResult.success(NonNullList.of(Ingredient.EMPTY, arecipeitemstack))); ++ }, DataResult::success).forGetter((shapelessrecipes) -> { ++ return shapelessrecipes.ingredients; ++ })).apply(instance, ShapelessRecipe::new); ++ }); ++ ++ public Serializer() {} ++ + @Override + public Codec codec() { +- return CODEC; ++ return ShapelessRecipe.Serializer.CODEC; + } + + @Override +- public ShapelessRecipe fromNetwork(FriendlyByteBuf friendlyByteBuf) { +- String utf = friendlyByteBuf.readUtf(); +- CraftingBookCategory craftingBookCategory = friendlyByteBuf.readEnum(CraftingBookCategory.class); +- int varInt = friendlyByteBuf.readVarInt(); +- NonNullList list = NonNullList.withSize(varInt, Ingredient.EMPTY); ++ public ShapelessRecipe fromNetwork(FriendlyByteBuf packetdataserializer) { ++ String s = packetdataserializer.readUtf(); ++ CraftingBookCategory craftingbookcategory = (CraftingBookCategory) packetdataserializer.readEnum(CraftingBookCategory.class); ++ int i = packetdataserializer.readVarInt(); ++ NonNullList nonnulllist = NonNullList.withSize(i, Ingredient.EMPTY); + +- for (int i = 0; i < list.size(); i++) { +- list.set(i, Ingredient.fromNetwork(friendlyByteBuf)); ++ for (int j = 0; j < nonnulllist.size(); ++j) { ++ nonnulllist.set(j, Ingredient.fromNetwork(packetdataserializer)); + } + +- ItemStack item = friendlyByteBuf.readItem(); +- return new ShapelessRecipe(utf, craftingBookCategory, item, list); ++ ItemStack itemstack = packetdataserializer.readItem(); ++ ++ return new ShapelessRecipe(s, craftingbookcategory, itemstack, nonnulllist); + } + +- @Override + public void toNetwork(FriendlyByteBuf buffer, ShapelessRecipe recipe) { + buffer.writeUtf(recipe.group); + buffer.writeEnum(recipe.category); + buffer.writeVarInt(recipe.ingredients.size()); ++ Iterator iterator = recipe.ingredients.iterator(); + +- for (Ingredient ingredient : recipe.ingredients) { +- ingredient.toNetwork(buffer); ++ while (iterator.hasNext()) { ++ Ingredient recipeitemstack = (Ingredient) iterator.next(); ++ ++ recipeitemstack.toNetwork(buffer); + } + + buffer.writeItem(recipe.result); diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/SmeltingRecipe.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/SmeltingRecipe.java.patch new file mode 100644 index 0000000000..69d9e9092e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/SmeltingRecipe.java.patch @@ -0,0 +1,41 @@ +--- a/net/minecraft/world/item/crafting/SmeltingRecipe.java ++++ b/net/minecraft/world/item/crafting/SmeltingRecipe.java +@@ -3,9 +3,18 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftFurnaceRecipe; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class SmeltingRecipe extends AbstractCookingRecipe { +- public SmeltingRecipe(String string, CookingBookCategory cookingBookCategory, Ingredient ingredient, ItemStack itemStack, float f, int i) { +- super(RecipeType.SMELTING, string, cookingBookCategory, ingredient, itemStack, f, i); ++ ++ public SmeltingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient recipeitemstack, ItemStack itemstack, float f, int i) { ++ super(RecipeType.SMELTING, s, cookingbookcategory, recipeitemstack, itemstack, f, i); + } + + @Override +@@ -17,4 +26,17 @@ + public RecipeSerializer getSerializer() { + return RecipeSerializer.SMELTING_RECIPE; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftFurnaceRecipe recipe = new CraftFurnaceRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/SmithingTransformRecipe.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/SmithingTransformRecipe.java.patch new file mode 100644 index 0000000000..da1e2ac7d4 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/SmithingTransformRecipe.java.patch @@ -0,0 +1,139 @@ +--- a/net/minecraft/world/item/crafting/SmithingTransformRecipe.java ++++ b/net/minecraft/world/item/crafting/SmithingTransformRecipe.java +@@ -2,7 +2,6 @@ + + import com.mojang.serialization.Codec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import java.util.stream.Stream; + import net.minecraft.core.RegistryAccess; + import net.minecraft.nbt.CompoundTag; +@@ -10,18 +9,26 @@ + import net.minecraft.world.Container; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftSmithingTransformRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end + + public class SmithingTransformRecipe implements SmithingRecipe { ++ + final Ingredient template; + final Ingredient base; + final Ingredient addition; + final ItemStack result; + +- public SmithingTransformRecipe(Ingredient ingredient, Ingredient ingredient1, Ingredient ingredient2, ItemStack itemStack) { +- this.template = ingredient; +- this.base = ingredient1; +- this.addition = ingredient2; +- this.result = itemStack; ++ public SmithingTransformRecipe(Ingredient recipeitemstack, Ingredient recipeitemstack1, Ingredient recipeitemstack2, ItemStack itemstack) { ++ this.template = recipeitemstack; ++ this.base = recipeitemstack1; ++ this.addition = recipeitemstack2; ++ this.result = itemstack; + } + + @Override +@@ -31,13 +38,14 @@ + + @Override + public ItemStack assemble(Container container, RegistryAccess registryAccess) { +- ItemStack itemStack = this.result.copy(); +- CompoundTag tag = container.getItem(1).getTag(); +- if (tag != null) { +- itemStack.setTag(tag.copy()); ++ ItemStack itemstack = this.result.copy(); ++ CompoundTag nbttagcompound = container.getItem(1).getTag(); ++ ++ if (nbttagcompound != null) { ++ itemstack.setTag(nbttagcompound.copy()); + } + +- return itemStack; ++ return itemstack; + } + + @Override +@@ -70,37 +78,53 @@ + return Stream.of(this.template, this.base, this.addition).anyMatch(Ingredient::isEmpty); + } + +- public static class Serializer implements RecipeSerializer { +- private static final Codec CODEC = RecordCodecBuilder.create( +- instance -> instance.group( +- Ingredient.CODEC.fieldOf("template").forGetter(smithingTransformRecipe -> smithingTransformRecipe.template), +- Ingredient.CODEC.fieldOf("base").forGetter(smithingTransformRecipe -> smithingTransformRecipe.base), +- Ingredient.CODEC.fieldOf("addition").forGetter(smithingTransformRecipe -> smithingTransformRecipe.addition), +- ItemStack.ITEM_WITH_COUNT_CODEC.fieldOf("result").forGetter(smithingTransformRecipe -> smithingTransformRecipe.result) +- ) +- .apply(instance, SmithingTransformRecipe::new) +- ); ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); + ++ CraftSmithingTransformRecipe recipe = new CraftSmithingTransformRecipe(id, result, CraftRecipe.toBukkit(this.template), CraftRecipe.toBukkit(this.base), CraftRecipe.toBukkit(this.addition)); ++ ++ return recipe; ++ } ++ // CraftBukkit end ++ ++ public static class a implements RecipeSerializer { ++ ++ private static final Codec CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(Ingredient.CODEC.fieldOf("template").forGetter((smithingtransformrecipe) -> { ++ return smithingtransformrecipe.template; ++ }), Ingredient.CODEC.fieldOf("base").forGetter((smithingtransformrecipe) -> { ++ return smithingtransformrecipe.base; ++ }), Ingredient.CODEC.fieldOf("addition").forGetter((smithingtransformrecipe) -> { ++ return smithingtransformrecipe.addition; ++ }), ItemStack.ITEM_WITH_COUNT_CODEC.fieldOf("result").forGetter((smithingtransformrecipe) -> { ++ return smithingtransformrecipe.result; ++ })).apply(instance, SmithingTransformRecipe::new); ++ }); ++ ++ public a() {} ++ + @Override + public Codec codec() { +- return CODEC; ++ return SmithingTransformRecipe.a.CODEC; + } + + @Override +- public SmithingTransformRecipe fromNetwork(FriendlyByteBuf friendlyByteBuf) { +- Ingredient ingredient = Ingredient.fromNetwork(friendlyByteBuf); +- Ingredient ingredient1 = Ingredient.fromNetwork(friendlyByteBuf); +- Ingredient ingredient2 = Ingredient.fromNetwork(friendlyByteBuf); +- ItemStack item = friendlyByteBuf.readItem(); +- return new SmithingTransformRecipe(ingredient, ingredient1, ingredient2, item); ++ public SmithingTransformRecipe fromNetwork(FriendlyByteBuf packetdataserializer) { ++ Ingredient recipeitemstack = Ingredient.fromNetwork(packetdataserializer); ++ Ingredient recipeitemstack1 = Ingredient.fromNetwork(packetdataserializer); ++ Ingredient recipeitemstack2 = Ingredient.fromNetwork(packetdataserializer); ++ ItemStack itemstack = packetdataserializer.readItem(); ++ ++ return new SmithingTransformRecipe(recipeitemstack, recipeitemstack1, recipeitemstack2, itemstack); + } + +- @Override +- public void toNetwork(FriendlyByteBuf buffer, SmithingTransformRecipe recipe) { +- recipe.template.toNetwork(buffer); +- recipe.base.toNetwork(buffer); +- recipe.addition.toNetwork(buffer); +- buffer.writeItem(recipe.result); ++ public void toNetwork(FriendlyByteBuf packetdataserializer, SmithingTransformRecipe smithingtransformrecipe) { ++ smithingtransformrecipe.template.toNetwork(packetdataserializer); ++ smithingtransformrecipe.base.toNetwork(packetdataserializer); ++ smithingtransformrecipe.addition.toNetwork(packetdataserializer); ++ packetdataserializer.writeItem(smithingtransformrecipe.result); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/SmithingTrimRecipe.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/SmithingTrimRecipe.java.patch new file mode 100644 index 0000000000..ef758f8657 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/SmithingTrimRecipe.java.patch @@ -0,0 +1,170 @@ +--- a/net/minecraft/world/item/crafting/SmithingTrimRecipe.java ++++ b/net/minecraft/world/item/crafting/SmithingTrimRecipe.java +@@ -2,7 +2,6 @@ + + import com.mojang.serialization.Codec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import java.util.Optional; + import java.util.stream.Stream; + import net.minecraft.core.Holder; +@@ -18,16 +17,23 @@ + import net.minecraft.world.item.armortrim.TrimPattern; + import net.minecraft.world.item.armortrim.TrimPatterns; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftSmithingTrimRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end + + public class SmithingTrimRecipe implements SmithingRecipe { ++ + final Ingredient template; + final Ingredient base; + final Ingredient addition; + +- public SmithingTrimRecipe(Ingredient ingredient, Ingredient ingredient1, Ingredient ingredient2) { +- this.template = ingredient; +- this.base = ingredient1; +- this.addition = ingredient2; ++ public SmithingTrimRecipe(Ingredient recipeitemstack, Ingredient recipeitemstack1, Ingredient recipeitemstack2) { ++ this.template = recipeitemstack; ++ this.base = recipeitemstack1; ++ this.addition = recipeitemstack2; + } + + @Override +@@ -37,21 +43,26 @@ + + @Override + public ItemStack assemble(Container container, RegistryAccess registryAccess) { +- ItemStack item = container.getItem(1); +- if (this.base.test(item)) { +- Optional> fromIngredient = TrimMaterials.getFromIngredient(registryAccess, container.getItem(2)); +- Optional> fromTemplate = TrimPatterns.getFromTemplate(registryAccess, container.getItem(0)); +- if (fromIngredient.isPresent() && fromTemplate.isPresent()) { +- Optional trim = ArmorTrim.getTrim(registryAccess, item, false); +- if (trim.isPresent() && trim.get().hasPatternAndMaterial(fromTemplate.get(), fromIngredient.get())) { ++ ItemStack itemstack = container.getItem(1); ++ ++ if (this.base.test(itemstack)) { ++ Optional> optional = TrimMaterials.getFromIngredient(registryAccess, container.getItem(2)); ++ Optional> optional1 = TrimPatterns.getFromTemplate(registryAccess, container.getItem(0)); ++ ++ if (optional.isPresent() && optional1.isPresent()) { ++ Optional optional2 = ArmorTrim.getTrim(registryAccess, itemstack, false); ++ ++ if (optional2.isPresent() && ((ArmorTrim) optional2.get()).hasPatternAndMaterial((Holder) optional1.get(), (Holder) optional.get())) { + return ItemStack.EMPTY; + } + +- ItemStack itemStack = item.copy(); +- itemStack.setCount(1); +- ArmorTrim armorTrim = new ArmorTrim(fromIngredient.get(), fromTemplate.get()); +- if (ArmorTrim.setTrim(registryAccess, itemStack, armorTrim)) { +- return itemStack; ++ ItemStack itemstack1 = itemstack.copy(); ++ ++ itemstack1.setCount(1); ++ ArmorTrim armortrim = new ArmorTrim((Holder) optional.get(), (Holder) optional1.get()); ++ ++ if (ArmorTrim.setTrim(registryAccess, itemstack1, armortrim)) { ++ return itemstack1; + } + } + } +@@ -61,17 +72,20 @@ + + @Override + public ItemStack getResultItem(RegistryAccess registryAccess) { +- ItemStack itemStack = new ItemStack(Items.IRON_CHESTPLATE); ++ ItemStack itemstack = new ItemStack(Items.IRON_CHESTPLATE); + Optional> optional = registryAccess.registryOrThrow(Registries.TRIM_PATTERN).holders().findFirst(); ++ + if (optional.isPresent()) { +- Optional> holder = registryAccess.registryOrThrow(Registries.TRIM_MATERIAL).getHolder(TrimMaterials.REDSTONE); +- if (holder.isPresent()) { +- ArmorTrim armorTrim = new ArmorTrim(holder.get(), optional.get()); +- ArmorTrim.setTrim(registryAccess, itemStack, armorTrim); ++ Optional> optional1 = registryAccess.registryOrThrow(Registries.TRIM_MATERIAL).getHolder(TrimMaterials.REDSTONE); ++ ++ if (optional1.isPresent()) { ++ ArmorTrim armortrim = new ArmorTrim((Holder) optional1.get(), (Holder) optional.get()); ++ ++ ArmorTrim.setTrim(registryAccess, itemstack, armortrim); + } + } + +- return itemStack; ++ return itemstack; + } + + @Override +@@ -99,34 +113,45 @@ + return Stream.of(this.template, this.base, this.addition).anyMatch(Ingredient::isEmpty); + } + +- public static class Serializer implements RecipeSerializer { +- private static final Codec CODEC = RecordCodecBuilder.create( +- instance -> instance.group( +- Ingredient.CODEC.fieldOf("template").forGetter(smithingTrimRecipe -> smithingTrimRecipe.template), +- Ingredient.CODEC.fieldOf("base").forGetter(smithingTrimRecipe -> smithingTrimRecipe.base), +- Ingredient.CODEC.fieldOf("addition").forGetter(smithingTrimRecipe -> smithingTrimRecipe.addition) +- ) +- .apply(instance, SmithingTrimRecipe::new) +- ); ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ return new CraftSmithingTrimRecipe(id, CraftRecipe.toBukkit(this.template), CraftRecipe.toBukkit(this.base), CraftRecipe.toBukkit(this.addition)); ++ } ++ // CraftBukkit end + ++ public static class a implements RecipeSerializer { ++ ++ private static final Codec CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(Ingredient.CODEC.fieldOf("template").forGetter((smithingtrimrecipe) -> { ++ return smithingtrimrecipe.template; ++ }), Ingredient.CODEC.fieldOf("base").forGetter((smithingtrimrecipe) -> { ++ return smithingtrimrecipe.base; ++ }), Ingredient.CODEC.fieldOf("addition").forGetter((smithingtrimrecipe) -> { ++ return smithingtrimrecipe.addition; ++ })).apply(instance, SmithingTrimRecipe::new); ++ }); ++ ++ public a() {} ++ + @Override + public Codec codec() { +- return CODEC; ++ return SmithingTrimRecipe.a.CODEC; + } + + @Override +- public SmithingTrimRecipe fromNetwork(FriendlyByteBuf friendlyByteBuf) { +- Ingredient ingredient = Ingredient.fromNetwork(friendlyByteBuf); +- Ingredient ingredient1 = Ingredient.fromNetwork(friendlyByteBuf); +- Ingredient ingredient2 = Ingredient.fromNetwork(friendlyByteBuf); +- return new SmithingTrimRecipe(ingredient, ingredient1, ingredient2); ++ public SmithingTrimRecipe fromNetwork(FriendlyByteBuf packetdataserializer) { ++ Ingredient recipeitemstack = Ingredient.fromNetwork(packetdataserializer); ++ Ingredient recipeitemstack1 = Ingredient.fromNetwork(packetdataserializer); ++ Ingredient recipeitemstack2 = Ingredient.fromNetwork(packetdataserializer); ++ ++ return new SmithingTrimRecipe(recipeitemstack, recipeitemstack1, recipeitemstack2); + } + +- @Override +- public void toNetwork(FriendlyByteBuf buffer, SmithingTrimRecipe recipe) { +- recipe.template.toNetwork(buffer); +- recipe.base.toNetwork(buffer); +- recipe.addition.toNetwork(buffer); ++ public void toNetwork(FriendlyByteBuf packetdataserializer, SmithingTrimRecipe smithingtrimrecipe) { ++ smithingtrimrecipe.template.toNetwork(packetdataserializer); ++ smithingtrimrecipe.base.toNetwork(packetdataserializer); ++ smithingtrimrecipe.addition.toNetwork(packetdataserializer); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/SmokingRecipe.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/SmokingRecipe.java.patch new file mode 100644 index 0000000000..125f7896db --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/SmokingRecipe.java.patch @@ -0,0 +1,41 @@ +--- a/net/minecraft/world/item/crafting/SmokingRecipe.java ++++ b/net/minecraft/world/item/crafting/SmokingRecipe.java +@@ -3,9 +3,18 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftSmokingRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class SmokingRecipe extends AbstractCookingRecipe { +- public SmokingRecipe(String string, CookingBookCategory cookingBookCategory, Ingredient ingredient, ItemStack itemStack, float f, int i) { +- super(RecipeType.SMOKING, string, cookingBookCategory, ingredient, itemStack, f, i); ++ ++ public SmokingRecipe(String s, CookingBookCategory cookingbookcategory, Ingredient recipeitemstack, ItemStack itemstack, float f, int i) { ++ super(RecipeType.SMOKING, s, cookingbookcategory, recipeitemstack, itemstack, f, i); + } + + @Override +@@ -17,4 +26,17 @@ + public RecipeSerializer getSerializer() { + return RecipeSerializer.SMOKING_RECIPE; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftSmokingRecipe recipe = new CraftSmokingRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/StonecutterRecipe.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/StonecutterRecipe.java.patch new file mode 100644 index 0000000000..47fa959efd --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/crafting/StonecutterRecipe.java.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/item/crafting/StonecutterRecipe.java ++++ b/net/minecraft/world/item/crafting/StonecutterRecipe.java +@@ -5,9 +5,18 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftStonecuttingRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class StonecutterRecipe extends SingleItemRecipe { +- public StonecutterRecipe(String string, Ingredient ingredient, ItemStack itemStack) { +- super(RecipeType.STONECUTTING, RecipeSerializer.STONECUTTER, string, ingredient, itemStack); ++ ++ public StonecutterRecipe(String s, Ingredient recipeitemstack, ItemStack itemstack) { ++ super(RecipeType.STONECUTTING, RecipeSerializer.STONECUTTER, s, recipeitemstack, itemstack); + } + + @Override +@@ -19,4 +28,16 @@ + public ItemStack getToastSymbol() { + return new ItemStack(Blocks.STONECUTTER); + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftStonecuttingRecipe recipe = new CraftStonecuttingRecipe(id, result, CraftRecipe.toBukkit(this.ingredient)); ++ recipe.setGroup(this.group); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/enchantment/DamageEnchantment.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/enchantment/DamageEnchantment.java.patch new file mode 100644 index 0000000000..e5cb62c89f --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/enchantment/DamageEnchantment.java.patch @@ -0,0 +1,75 @@ +--- a/net/minecraft/world/item/enchantment/DamageEnchantment.java ++++ b/net/minecraft/world/item/enchantment/DamageEnchantment.java +@@ -3,13 +3,14 @@ + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobType; + import net.minecraft.world.item.AxeItem; + import net.minecraft.world.item.ItemStack; + + public class DamageEnchantment extends Enchantment { ++ + public static final int ALL = 0; + public static final int UNDEAD = 1; + public static final int ARTHROPODS = 2; +@@ -26,12 +27,12 @@ + + @Override + public int getMinCost(int enchantmentLevel) { +- return MIN_COST[this.type] + (enchantmentLevel - 1) * LEVEL_COST[this.type]; ++ return DamageEnchantment.MIN_COST[this.type] + (enchantmentLevel - 1) * DamageEnchantment.LEVEL_COST[this.type]; + } + + @Override + public int getMaxCost(int enchantmentLevel) { +- return this.getMinCost(enchantmentLevel) + LEVEL_COST_SPAN[this.type]; ++ return this.getMinCost(enchantmentLevel) + DamageEnchantment.LEVEL_COST_SPAN[this.type]; + } + + @Override +@@ -40,14 +41,8 @@ + } + + @Override +- public float getDamageBonus(int level, MobType creatureType) { +- if (this.type == 0) { +- return 1.0F + (float)Math.max(0, level - 1) * 0.5F; +- } else if (this.type == 1 && creatureType == MobType.UNDEAD) { +- return (float)level * 2.5F; +- } else { +- return this.type == 2 && creatureType == MobType.ARTHROPOD ? (float)level * 2.5F : 0.0F; +- } ++ public float getDamageBonus(int level, EnumMonsterType creatureType) { ++ return this.type == 0 ? 1.0F + (float) Math.max(0, level - 1) * 0.5F : (this.type == 1 && creatureType == EnumMonsterType.UNDEAD ? (float) level * 2.5F : (this.type == 2 && creatureType == EnumMonsterType.ARTHROPOD ? (float) level * 2.5F : 0.0F)); + } + + @Override +@@ -57,14 +52,20 @@ + + @Override + public boolean canEnchant(ItemStack stack) { +- return stack.getItem() instanceof AxeItem || super.canEnchant(stack); ++ return stack.getItem() instanceof AxeItem ? true : super.canEnchant(stack); + } + + @Override + public void doPostAttack(LivingEntity user, Entity target, int level) { +- if (target instanceof LivingEntity livingEntity && this.type == 2 && level > 0 && livingEntity.getMobType() == MobType.ARTHROPOD) { +- int i = 20 + user.getRandom().nextInt(10 * level); +- livingEntity.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, i, 3)); ++ if (target instanceof LivingEntity) { ++ LivingEntity entityliving1 = (LivingEntity) target; ++ ++ if (this.type == 2 && level > 0 && entityliving1.getMobType() == EnumMonsterType.ARTHROPOD) { ++ int j = 20 + user.getRandom().nextInt(10 * level); ++ ++ entityliving1.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, j, 3), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit ++ } + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/enchantment/FrostWalkerEnchantment.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/enchantment/FrostWalkerEnchantment.java.patch new file mode 100644 index 0000000000..9fc59385d6 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/enchantment/FrostWalkerEnchantment.java.patch @@ -0,0 +1,69 @@ +--- a/net/minecraft/world/item/enchantment/FrostWalkerEnchantment.java ++++ b/net/minecraft/world/item/enchantment/FrostWalkerEnchantment.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.item.enchantment; + ++import java.util.Iterator; + import net.minecraft.core.BlockPos; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.EquipmentSlot; +@@ -7,10 +8,11 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.FrostedIceBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.shapes.CollisionContext; + + public class FrostWalkerEnchantment extends Enchantment { ++ + public FrostWalkerEnchantment(Enchantment.Rarity rarity, EquipmentSlot... applicableSlots) { + super(rarity, EnchantmentCategory.ARMOR_FEET, applicableSlots); + } +@@ -37,25 +39,32 @@ + + public static void onEntityMoved(LivingEntity living, Level level, BlockPos pos, int levelConflicting) { + if (living.onGround()) { +- BlockState blockState = Blocks.FROSTED_ICE.defaultBlockState(); +- int min = Math.min(16, 2 + levelConflicting); +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ IBlockData iblockdata = Blocks.FROSTED_ICE.defaultBlockState(); ++ int j = Math.min(16, 2 + levelConflicting); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ Iterator iterator = BlockPos.betweenClosed(pos.offset(-j, -1, -j), pos.offset(j, -1, j)).iterator(); + +- for (BlockPos blockPos : BlockPos.betweenClosed(pos.offset(-min, -1, -min), pos.offset(min, -1, min))) { +- if (blockPos.closerToCenterThan(living.position(), (double)min)) { +- mutableBlockPos.set(blockPos.getX(), blockPos.getY() + 1, blockPos.getZ()); +- BlockState blockState1 = level.getBlockState(mutableBlockPos); +- if (blockState1.isAir()) { +- BlockState blockState2 = level.getBlockState(blockPos); +- if (blockState2 == FrostedIceBlock.meltsInto() +- && blockState.canSurvive(level, blockPos) +- && level.isUnobstructed(blockState, blockPos, CollisionContext.empty())) { +- level.setBlockAndUpdate(blockPos, blockState); +- level.scheduleTick(blockPos, Blocks.FROSTED_ICE, Mth.nextInt(living.getRandom(), 60, 120)); ++ while (iterator.hasNext()) { ++ BlockPos blockposition1 = (BlockPos) iterator.next(); ++ ++ if (blockposition1.closerToCenterThan(living.position(), (double) j)) { ++ blockposition_mutableblockposition.set(blockposition1.getX(), blockposition1.getY() + 1, blockposition1.getZ()); ++ IBlockData iblockdata1 = level.getBlockState(blockposition_mutableblockposition); ++ ++ if (iblockdata1.isAir()) { ++ IBlockData iblockdata2 = level.getBlockState(blockposition1); ++ ++ if (iblockdata2 == FrostedIceBlock.meltsInto() && iblockdata.canSurvive(level, blockposition1) && level.isUnobstructed(iblockdata, blockposition1, CollisionContext.empty())) { ++ // CraftBukkit Start - Call EntityBlockFormEvent for Frost Walker ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, blockposition1, iblockdata, living)) { ++ level.scheduleTick(blockposition1, Blocks.FROSTED_ICE, Mth.nextInt(living.getRandom(), 60, 120)); ++ } ++ // CraftBukkit End + } + } + } + } ++ + } + } + diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/trading/Merchant.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/trading/Merchant.java.patch new file mode 100644 index 0000000000..f4aecf8456 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/trading/Merchant.java.patch @@ -0,0 +1,45 @@ +--- a/net/minecraft/world/item/trading/Merchant.java ++++ b/net/minecraft/world/item/trading/Merchant.java +@@ -5,12 +5,12 @@ + import net.minecraft.network.chat.Component; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.world.SimpleMenuProvider; +-import net.minecraft.world.entity.player.Inventory; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.inventory.MerchantMenu; + import net.minecraft.world.item.ItemStack; + + public interface Merchant { ++ + void setTradingPlayer(@Nullable Player tradingPlayer); + + @Nullable +@@ -37,16 +37,21 @@ + } + + default void openTradingScreen(Player player, Component displayName, int level) { +- OptionalInt optionalInt = player.openMenu( +- new SimpleMenuProvider((containerId, inventory, player1) -> new MerchantMenu(containerId, inventory, this), displayName) +- ); +- if (optionalInt.isPresent()) { +- MerchantOffers offers = this.getOffers(); +- if (!offers.isEmpty()) { +- player.sendMerchantOffers(optionalInt.getAsInt(), offers, level, this.getVillagerXp(), this.showProgressBar(), this.canRestock()); ++ OptionalInt optionalint = player.openMenu(new SimpleMenuProvider((j, playerinventory, entityhuman1) -> { ++ return new MerchantMenu(j, playerinventory, this); ++ }, displayName)); ++ ++ if (optionalint.isPresent()) { ++ MerchantOffers merchantrecipelist = this.getOffers(); ++ ++ if (!merchantrecipelist.isEmpty()) { ++ player.sendMerchantOffers(optionalint.getAsInt(), merchantrecipelist, level, this.getVillagerXp(), this.showProgressBar(), this.canRestock()); + } + } ++ + } + + boolean isClientSide(); ++ ++ org.bukkit.craftbukkit.inventory.CraftMerchant getCraftMerchant(); // CraftBukkit + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/item/trading/MerchantOffer.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/item/trading/MerchantOffer.java.patch new file mode 100644 index 0000000000..b95fea8462 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/item/trading/MerchantOffer.java.patch @@ -0,0 +1,200 @@ +--- a/net/minecraft/world/item/trading/MerchantOffer.java ++++ b/net/minecraft/world/item/trading/MerchantOffer.java +@@ -5,19 +5,40 @@ + import net.minecraft.util.Mth; + import net.minecraft.world.item.ItemStack; + ++import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; // CraftBukkit ++ + public class MerchantOffer { +- private final ItemStack baseCostA; +- private final ItemStack costB; +- private final ItemStack result; +- private int uses; +- private final int maxUses; +- private boolean rewardExp = true; +- private int specialPriceDiff; +- private int demand; +- private float priceMultiplier; +- private int xp = 1; + ++ public ItemStack baseCostA; ++ public ItemStack costB; ++ public final ItemStack result; ++ public int uses; ++ public int maxUses; ++ public boolean rewardExp; ++ public int specialPriceDiff; ++ public int demand; ++ public float priceMultiplier; ++ public int xp; ++ // CraftBukkit start ++ private CraftMerchantRecipe bukkitHandle; ++ ++ public CraftMerchantRecipe asBukkit() { ++ return (bukkitHandle == null) ? bukkitHandle = new CraftMerchantRecipe(this) : bukkitHandle; ++ } ++ ++ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, CraftMerchantRecipe bukkit) { ++ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, 0, bukkit); ++ } ++ ++ public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, int demand, CraftMerchantRecipe bukkit) { ++ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, demand); ++ this.bukkitHandle = bukkit; ++ } ++ // CraftBukkit end ++ + public MerchantOffer(CompoundTag compoundTag) { ++ this.rewardExp = true; ++ this.xp = 1; + this.baseCostA = ItemStack.of(compoundTag.getCompound("buy")); + this.costB = ItemStack.of(compoundTag.getCompound("buyB")); + this.result = ItemStack.of(compoundTag.getCompound("sell")); +@@ -52,32 +73,36 @@ + this(baseCostA, costB, result, 0, maxUses, xp, priceMultiplier); + } + +- public MerchantOffer(ItemStack baseCostA, ItemStack costB, ItemStack result, int _uses, int maxUses, int xp, float priceMultiplier) { +- this(baseCostA, costB, result, _uses, maxUses, xp, priceMultiplier, 0); ++ public MerchantOffer(ItemStack baseCostA, ItemStack costB, ItemStack result, int uses, int maxUses, int xp, float priceMultiplier) { ++ this(baseCostA, costB, result, uses, maxUses, xp, priceMultiplier, 0); + } + +- public MerchantOffer(ItemStack baseCostA, ItemStack costB, ItemStack result, int _uses, int maxUses, int xp, float priceMultiplier, int demand) { ++ public MerchantOffer(ItemStack baseCostA, ItemStack costB, ItemStack result, int uses, int maxUses, int xp, float priceMultiplier, int demand) { ++ this.rewardExp = true; ++ this.xp = 1; + this.baseCostA = baseCostA; + this.costB = costB; + this.result = result; +- this.uses = _uses; ++ this.uses = uses; + this.maxUses = maxUses; + this.xp = xp; + this.priceMultiplier = priceMultiplier; + this.demand = demand; + } + +- private MerchantOffer(MerchantOffer merchantOffer) { +- this.baseCostA = merchantOffer.baseCostA.copy(); +- this.costB = merchantOffer.costB.copy(); +- this.result = merchantOffer.result.copy(); +- this.uses = merchantOffer.uses; +- this.maxUses = merchantOffer.maxUses; +- this.rewardExp = merchantOffer.rewardExp; +- this.specialPriceDiff = merchantOffer.specialPriceDiff; +- this.demand = merchantOffer.demand; +- this.priceMultiplier = merchantOffer.priceMultiplier; +- this.xp = merchantOffer.xp; ++ private MerchantOffer(MerchantOffer merchantrecipe) { ++ this.rewardExp = true; ++ this.xp = 1; ++ this.baseCostA = merchantrecipe.baseCostA.copy(); ++ this.costB = merchantrecipe.costB.copy(); ++ this.result = merchantrecipe.result.copy(); ++ this.uses = merchantrecipe.uses; ++ this.maxUses = merchantrecipe.maxUses; ++ this.rewardExp = merchantrecipe.rewardExp; ++ this.specialPriceDiff = merchantrecipe.specialPriceDiff; ++ this.demand = merchantrecipe.demand; ++ this.priceMultiplier = merchantrecipe.priceMultiplier; ++ this.xp = merchantrecipe.xp; + } + + public ItemStack getBaseCostA() { +@@ -88,9 +113,11 @@ + if (this.baseCostA.isEmpty()) { + return ItemStack.EMPTY; + } else { +- int count = this.baseCostA.getCount(); +- int max = Math.max(0, Mth.floor((float)(count * this.demand) * this.priceMultiplier)); +- return this.baseCostA.copyWithCount(Mth.clamp(count + max + this.specialPriceDiff, 1, this.baseCostA.getItem().getMaxStackSize())); ++ int i = this.baseCostA.getCount(); ++ if (i <= 0) return ItemStack.EMPTY; // CraftBukkit - SPIGOT-5476 ++ int j = Math.max(0, Mth.floor((float) (i * this.demand) * this.priceMultiplier)); ++ ++ return this.baseCostA.copyWithCount(Mth.clamp(i + j + this.specialPriceDiff, 1, this.baseCostA.getItem().getMaxStackSize())); + } + } + +@@ -123,7 +150,7 @@ + } + + public void increaseUses() { +- this.uses++; ++ ++this.uses; + } + + public int getDemand() { +@@ -171,38 +198,36 @@ + } + + public CompoundTag createTag() { +- CompoundTag compoundTag = new CompoundTag(); +- compoundTag.put("buy", this.baseCostA.save(new CompoundTag())); +- compoundTag.put("sell", this.result.save(new CompoundTag())); +- compoundTag.put("buyB", this.costB.save(new CompoundTag())); +- compoundTag.putInt("uses", this.uses); +- compoundTag.putInt("maxUses", this.maxUses); +- compoundTag.putBoolean("rewardExp", this.rewardExp); +- compoundTag.putInt("xp", this.xp); +- compoundTag.putFloat("priceMultiplier", this.priceMultiplier); +- compoundTag.putInt("specialPrice", this.specialPriceDiff); +- compoundTag.putInt("demand", this.demand); +- return compoundTag; ++ CompoundTag nbttagcompound = new CompoundTag(); ++ ++ nbttagcompound.put("buy", this.baseCostA.save(new CompoundTag())); ++ nbttagcompound.put("sell", this.result.save(new CompoundTag())); ++ nbttagcompound.put("buyB", this.costB.save(new CompoundTag())); ++ nbttagcompound.putInt("uses", this.uses); ++ nbttagcompound.putInt("maxUses", this.maxUses); ++ nbttagcompound.putBoolean("rewardExp", this.rewardExp); ++ nbttagcompound.putInt("xp", this.xp); ++ nbttagcompound.putFloat("priceMultiplier", this.priceMultiplier); ++ nbttagcompound.putInt("specialPrice", this.specialPriceDiff); ++ nbttagcompound.putInt("demand", this.demand); ++ return nbttagcompound; + } + + public boolean satisfiedBy(ItemStack playerOfferA, ItemStack playerOfferB) { +- return this.isRequiredItem(playerOfferA, this.getCostA()) +- && playerOfferA.getCount() >= this.getCostA().getCount() +- && this.isRequiredItem(playerOfferB, this.costB) +- && playerOfferB.getCount() >= this.costB.getCount(); ++ return this.isRequiredItem(playerOfferA, this.getCostA()) && playerOfferA.getCount() >= this.getCostA().getCount() && this.isRequiredItem(playerOfferB, this.costB) && playerOfferB.getCount() >= this.costB.getCount(); + } + + private boolean isRequiredItem(ItemStack offer, ItemStack cost) { + if (cost.isEmpty() && offer.isEmpty()) { + return true; + } else { +- ItemStack itemStack = offer.copy(); +- if (itemStack.getItem().canBeDepleted()) { +- itemStack.setDamageValue(itemStack.getDamageValue()); ++ ItemStack itemstack2 = offer.copy(); ++ ++ if (itemstack2.getItem().canBeDepleted()) { ++ itemstack2.setDamageValue(itemstack2.getDamageValue()); + } + +- return ItemStack.isSameItem(itemStack, cost) +- && (!cost.hasTag() || itemStack.hasTag() && NbtUtils.compareNbt(cost.getTag(), itemStack.getTag(), false)); ++ return ItemStack.isSameItem(itemstack2, cost) && (!cost.hasTag() || itemstack2.hasTag() && NbtUtils.compareNbt(cost.getTag(), itemstack2.getTag(), false)); + } + } + +@@ -210,7 +235,11 @@ + if (!this.satisfiedBy(playerOfferA, playerOfferB)) { + return false; + } else { +- playerOfferA.shrink(this.getCostA().getCount()); ++ // CraftBukkit start ++ if (!this.getCostA().isEmpty()) { ++ playerOfferA.shrink(this.getCostA().getCount()); ++ } ++ // CraftBukkit end + if (!this.getCostB().isEmpty()) { + playerOfferB.shrink(this.getCostB().getCount()); + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/BaseCommandBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/BaseCommandBlock.java.patch new file mode 100644 index 0000000000..8cdd6c747e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/BaseCommandBlock.java.patch @@ -0,0 +1,151 @@ +--- a/net/minecraft/world/level/BaseCommandBlock.java ++++ b/net/minecraft/world/level/BaseCommandBlock.java +@@ -19,6 +19,7 @@ + import net.minecraft.world.phys.Vec3; + + public abstract class BaseCommandBlock implements CommandSource { ++ + private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss"); + private static final Component DEFAULT_NAME = Component.literal("@"); + private long lastExecution = -1L; +@@ -28,8 +29,16 @@ + @Nullable + private Component lastOutput; + private String command = ""; +- private Component name = DEFAULT_NAME; ++ private Component name; ++ // CraftBukkit start ++ @Override ++ public abstract org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper); ++ // CraftBukkit end + ++ public BaseCommandBlock() { ++ this.name = BaseCommandBlock.DEFAULT_NAME; ++ } ++ + public int getSuccessCount() { + return this.successCount; + } +@@ -73,8 +82,8 @@ + if (nbt.contains("LastOutput", 8) && this.trackOutput) { + try { + this.lastOutput = Component.Serializer.fromJson(nbt.getString("LastOutput")); +- } catch (Throwable var3) { +- this.lastOutput = Component.literal(var3.getMessage()); ++ } catch (Throwable throwable) { ++ this.lastOutput = Component.literal(throwable.getMessage()); + } + } else { + this.lastOutput = null; +@@ -89,6 +98,7 @@ + } else { + this.lastExecution = -1L; + } ++ + } + + public void setCommand(String command) { +@@ -101,40 +111,48 @@ + } + + public boolean performCommand(Level level) { +- if (level.isClientSide || level.getGameTime() == this.lastExecution) { +- return false; +- } else if ("Searge".equalsIgnoreCase(this.command)) { +- this.lastOutput = Component.literal("#itzlipofutzli"); +- this.successCount = 1; +- return true; +- } else { +- this.successCount = 0; +- MinecraftServer server = this.getLevel().getServer(); +- if (server.isCommandBlockEnabled() && !StringUtil.isNullOrEmpty(this.command)) { +- try { +- this.lastOutput = null; +- CommandSourceStack commandSourceStack = this.createCommandSourceStack().withCallback((flag, i) -> { +- if (flag) { +- this.successCount++; +- } +- }); +- server.getCommands().performPrefixedCommand(commandSourceStack, this.command); +- } catch (Throwable var6) { +- CrashReport crashReport = CrashReport.forThrowable(var6, "Executing command block"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Command to be executed"); +- crashReportCategory.setDetail("Command", this::getCommand); +- crashReportCategory.setDetail("Name", () -> this.getName().getString()); +- throw new ReportedException(crashReport); ++ if (!level.isClientSide && level.getGameTime() != this.lastExecution) { ++ if ("Searge".equalsIgnoreCase(this.command)) { ++ this.lastOutput = Component.literal("#itzlipofutzli"); ++ this.successCount = 1; ++ return true; ++ } else { ++ this.successCount = 0; ++ MinecraftServer minecraftserver = this.getLevel().getServer(); ++ ++ if (minecraftserver.isCommandBlockEnabled() && !StringUtil.isNullOrEmpty(this.command)) { ++ try { ++ this.lastOutput = null; ++ CommandSourceStack commandlistenerwrapper = this.createCommandSourceStack().withCallback((flag, i) -> { ++ if (flag) { ++ ++this.successCount; ++ } ++ ++ }); ++ ++ minecraftserver.getCommands().dispatchServerCommand(commandlistenerwrapper, this.command); // CraftBukkit ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Executing command block"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Command to be executed"); ++ ++ crashreportsystemdetails.setDetail("Command", this::getCommand); ++ crashreportsystemdetails.setDetail("Name", () -> { ++ return this.getName().getString(); ++ }); ++ throw new ReportedException(crashreport); ++ } + } +- } + +- if (this.updateLastExecution) { +- this.lastExecution = level.getGameTime(); +- } else { +- this.lastExecution = -1L; +- } ++ if (this.updateLastExecution) { ++ this.lastExecution = level.getGameTime(); ++ } else { ++ this.lastExecution = -1L; ++ } + +- return true; ++ return true; ++ } ++ } else { ++ return false; + } + } + +@@ -146,16 +164,21 @@ + if (name != null) { + this.name = name; + } else { +- this.name = DEFAULT_NAME; ++ this.name = BaseCommandBlock.DEFAULT_NAME; + } ++ + } + + @Override + public void sendSystemMessage(Component component) { + if (this.trackOutput) { +- this.lastOutput = Component.literal("[" + TIME_FORMAT.format(new Date()) + "] ").append(component); ++ SimpleDateFormat simpledateformat = BaseCommandBlock.TIME_FORMAT; ++ Date date = new Date(); ++ ++ this.lastOutput = Component.literal("[" + simpledateformat.format(date) + "] ").append(component); + this.onUpdated(); + } ++ + } + + public abstract ServerLevel getLevel(); diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/BaseSpawner.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/BaseSpawner.java.patch new file mode 100644 index 0000000000..355c04a40d --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/BaseSpawner.java.patch @@ -0,0 +1,354 @@ +--- a/net/minecraft/world/level/BaseSpawner.java ++++ b/net/minecraft/world/level/BaseSpawner.java +@@ -10,6 +10,7 @@ + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.Tag; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.RandomSource; + import net.minecraft.util.random.SimpleWeightedRandomList; +@@ -18,8 +19,9 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.SpawnPlacements; + import net.minecraft.world.level.entity.EntityTypeTest; + import net.minecraft.world.level.gameevent.GameEvent; +@@ -27,49 +29,55 @@ + import org.slf4j.Logger; + + public abstract class BaseSpawner { ++ + public static final String SPAWN_DATA_TAG = "SpawnData"; + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int EVENT_SPAWN = 1; +- private int spawnDelay = 20; +- private SimpleWeightedRandomList spawnPotentials = SimpleWeightedRandomList.empty(); ++ public int spawnDelay = 20; ++ public SimpleWeightedRandomList spawnPotentials = SimpleWeightedRandomList.empty(); + @Nullable +- private SpawnData nextSpawnData; ++ public SpawnData nextSpawnData; + private double spin; + private double oSpin; +- private int minSpawnDelay = 200; +- private int maxSpawnDelay = 800; +- private int spawnCount = 4; ++ public int minSpawnDelay = 200; ++ public int maxSpawnDelay = 800; ++ public int spawnCount = 4; + @Nullable + private Entity displayEntity; +- private int maxNearbyEntities = 6; +- private int requiredPlayerRange = 16; +- private int spawnRange = 4; ++ public int maxNearbyEntities = 6; ++ public int requiredPlayerRange = 16; ++ public int spawnRange = 4; + ++ public BaseSpawner() {} ++ + public void setEntityId(EntityType type, @Nullable Level level, RandomSource random, BlockPos pos) { + this.getOrCreateNextSpawnData(level, random, pos).getEntityToSpawn().putString("id", BuiltInRegistries.ENTITY_TYPE.getKey(type).toString()); ++ this.spawnPotentials = SimpleWeightedRandomList.empty(); // CraftBukkit - SPIGOT-3496, MC-92282 + } + + private boolean isNearPlayer(Level level, BlockPos pos) { +- return level.hasNearbyAlivePlayer((double)pos.getX() + 0.5, (double)pos.getY() + 0.5, (double)pos.getZ() + 0.5, (double)this.requiredPlayerRange); ++ return level.hasNearbyAlivePlayer((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (double) this.requiredPlayerRange); + } + + public void clientTick(Level level, BlockPos pos) { + if (!this.isNearPlayer(level, pos)) { + this.oSpin = this.spin; + } else if (this.displayEntity != null) { +- RandomSource random = level.getRandom(); +- double d = (double)pos.getX() + random.nextDouble(); +- double d1 = (double)pos.getY() + random.nextDouble(); +- double d2 = (double)pos.getZ() + random.nextDouble(); +- level.addParticle(ParticleTypes.SMOKE, d, d1, d2, 0.0, 0.0, 0.0); +- level.addParticle(ParticleTypes.FLAME, d, d1, d2, 0.0, 0.0, 0.0); ++ RandomSource randomsource = level.getRandom(); ++ double d0 = (double) pos.getX() + randomsource.nextDouble(); ++ double d1 = (double) pos.getY() + randomsource.nextDouble(); ++ double d2 = (double) pos.getZ() + randomsource.nextDouble(); ++ ++ level.addParticle(ParticleTypes.SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); ++ level.addParticle(ParticleTypes.FLAME, d0, d1, d2, 0.0D, 0.0D, 0.0D); + if (this.spawnDelay > 0) { +- this.spawnDelay--; ++ --this.spawnDelay; + } + + this.oSpin = this.spin; +- this.spin = (this.spin + (double)(1000.0F / ((float)this.spawnDelay + 200.0F))) % 360.0; ++ this.spin = (this.spin + (double) (1000.0F / ((float) this.spawnDelay + 200.0F))) % 360.0D; + } ++ + } + + public void serverTick(ServerLevel serverLevel, BlockPos pos) { +@@ -79,93 +87,88 @@ + } + + if (this.spawnDelay > 0) { +- this.spawnDelay--; ++ --this.spawnDelay; + } else { + boolean flag = false; +- RandomSource random = serverLevel.getRandom(); +- SpawnData nextSpawnData = this.getOrCreateNextSpawnData(serverLevel, random, pos); ++ RandomSource randomsource = serverLevel.getRandom(); ++ SpawnData mobspawnerdata = this.getOrCreateNextSpawnData(serverLevel, randomsource, pos); + +- for (int i = 0; i < this.spawnCount; i++) { +- CompoundTag entityToSpawn = nextSpawnData.getEntityToSpawn(); +- Optional> optional = EntityType.by(entityToSpawn); ++ for (int i = 0; i < this.spawnCount; ++i) { ++ CompoundTag nbttagcompound = mobspawnerdata.getEntityToSpawn(); ++ Optional> optional = EntityType.by(nbttagcompound); ++ + if (optional.isEmpty()) { + this.delay(serverLevel, pos); + return; + } + +- ListTag list = entityToSpawn.getList("Pos", 6); +- int size = list.size(); +- double d = size >= 1 ? list.getDouble(0) : (double)pos.getX() + (random.nextDouble() - random.nextDouble()) * (double)this.spawnRange + 0.5; +- double d1 = size >= 2 ? list.getDouble(1) : (double)(pos.getY() + random.nextInt(3) - 1); +- double d2 = size >= 3 +- ? list.getDouble(2) +- : (double)pos.getZ() + (random.nextDouble() - random.nextDouble()) * (double)this.spawnRange + 0.5; +- if (serverLevel.noCollision(optional.get().getAABB(d, d1, d2))) { +- BlockPos blockPos = BlockPos.containing(d, d1, d2); +- if (nextSpawnData.getCustomSpawnRules().isPresent()) { +- if (!optional.get().getCategory().isFriendly() && serverLevel.getDifficulty() == Difficulty.PEACEFUL) { ++ ListTag nbttaglist = nbttagcompound.getList("Pos", 6); ++ int j = nbttaglist.size(); ++ double d0 = j >= 1 ? nbttaglist.getDouble(0) : (double) pos.getX() + (randomsource.nextDouble() - randomsource.nextDouble()) * (double) this.spawnRange + 0.5D; ++ double d1 = j >= 2 ? nbttaglist.getDouble(1) : (double) (pos.getY() + randomsource.nextInt(3) - 1); ++ double d2 = j >= 3 ? nbttaglist.getDouble(2) : (double) pos.getZ() + (randomsource.nextDouble() - randomsource.nextDouble()) * (double) this.spawnRange + 0.5D; ++ ++ if (serverLevel.noCollision(((EntityType) optional.get()).getAABB(d0, d1, d2))) { ++ BlockPos blockposition1 = BlockPos.containing(d0, d1, d2); ++ ++ if (mobspawnerdata.getCustomSpawnRules().isPresent()) { ++ if (!((EntityType) optional.get()).getCategory().isFriendly() && serverLevel.getDifficulty() == Difficulty.PEACEFUL) { + continue; + } + +- SpawnData.CustomSpawnRules customSpawnRules = nextSpawnData.getCustomSpawnRules().get(); +- if (!customSpawnRules.blockLightLimit().isValueInRange(serverLevel.getBrightness(LightLayer.BLOCK, blockPos)) +- || !customSpawnRules.skyLightLimit().isValueInRange(serverLevel.getBrightness(LightLayer.SKY, blockPos))) { ++ SpawnData.CustomSpawnRules mobspawnerdata_a = (SpawnData.CustomSpawnRules) mobspawnerdata.getCustomSpawnRules().get(); ++ ++ if (!mobspawnerdata_a.blockLightLimit().isValueInRange(serverLevel.getBrightness(EnumSkyBlock.BLOCK, blockposition1)) || !mobspawnerdata_a.skyLightLimit().isValueInRange(serverLevel.getBrightness(EnumSkyBlock.SKY, blockposition1))) { + continue; + } +- } else if (!SpawnPlacements.checkSpawnRules(optional.get(), serverLevel, MobSpawnType.SPAWNER, blockPos, serverLevel.getRandom())) { ++ } else if (!SpawnPlacements.checkSpawnRules((EntityType) optional.get(), serverLevel, EnumMobSpawn.SPAWNER, blockposition1, serverLevel.getRandom())) { + continue; + } + +- Entity entity = EntityType.loadEntityRecursive(entityToSpawn, serverLevel, entity1 -> { +- entity1.moveTo(d, d1, d2, entity1.getYRot(), entity1.getXRot()); ++ Entity entity = EntityType.loadEntityRecursive(nbttagcompound, serverLevel, (entity1) -> { ++ entity1.moveTo(d0, d1, d2, entity1.getYRot(), entity1.getXRot()); + return entity1; + }); ++ + if (entity == null) { + this.delay(serverLevel, pos); + return; + } + +- int size1 = serverLevel.getEntities( +- EntityTypeTest.forExactClass(entity.getClass()), +- new AABB( +- (double)pos.getX(), +- (double)pos.getY(), +- (double)pos.getZ(), +- (double)(pos.getX() + 1), +- (double)(pos.getY() + 1), +- (double)(pos.getZ() + 1) +- ) +- .inflate((double)this.spawnRange), +- EntitySelector.NO_SPECTATORS +- ) +- .size(); +- if (size1 >= this.maxNearbyEntities) { ++ int k = serverLevel.getEntities(EntityTypeTest.forExactClass(entity.getClass()), (new AABB((double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), (double) (pos.getX() + 1), (double) (pos.getY() + 1), (double) (pos.getZ() + 1))).inflate((double) this.spawnRange), EntitySelector.NO_SPECTATORS).size(); ++ ++ if (k >= this.maxNearbyEntities) { + this.delay(serverLevel, pos); + return; + } + +- entity.moveTo(entity.getX(), entity.getY(), entity.getZ(), random.nextFloat() * 360.0F, 0.0F); +- if (entity instanceof Mob mob) { +- if (nextSpawnData.getCustomSpawnRules().isEmpty() && !mob.checkSpawnRules(serverLevel, MobSpawnType.SPAWNER) +- || !mob.checkSpawnObstruction(serverLevel)) { ++ entity.moveTo(entity.getX(), entity.getY(), entity.getZ(), randomsource.nextFloat() * 360.0F, 0.0F); ++ if (entity instanceof Mob) { ++ Mob entityinsentient = (Mob) entity; ++ ++ if (mobspawnerdata.getCustomSpawnRules().isEmpty() && !entityinsentient.checkSpawnRules(serverLevel, EnumMobSpawn.SPAWNER) || !entityinsentient.checkSpawnObstruction(serverLevel)) { + continue; + } + +- if (nextSpawnData.getEntityToSpawn().size() == 1 && nextSpawnData.getEntityToSpawn().contains("id", 8)) { +- ((Mob)entity) +- .finalizeSpawn(serverLevel, serverLevel.getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.SPAWNER, null, null); ++ if (mobspawnerdata.getEntityToSpawn().size() == 1 && mobspawnerdata.getEntityToSpawn().contains("id", 8)) { ++ ((Mob) entity).finalizeSpawn(serverLevel, serverLevel.getCurrentDifficultyAt(entity.blockPosition()), EnumMobSpawn.SPAWNER, (GroupDataEntity) null, (CompoundTag) null); + } + } + +- if (!serverLevel.tryAddFreshEntityWithPassengers(entity)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) { ++ continue; ++ } ++ if (!serverLevel.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER)) { ++ // CraftBukkit end + this.delay(serverLevel, pos); + return; + } + + serverLevel.levelEvent(2004, pos, 0); +- serverLevel.gameEvent(entity, GameEvent.ENTITY_PLACE, blockPos); ++ serverLevel.gameEvent(entity, GameEvent.ENTITY_PLACE, blockposition1); + if (entity instanceof Mob) { +- ((Mob)entity).spawnAnim(); ++ ((Mob) entity).spawnAnim(); + } + + flag = true; +@@ -175,40 +178,46 @@ + if (flag) { + this.delay(serverLevel, pos); + } ++ + } + } + } + + private void delay(Level level, BlockPos pos) { +- RandomSource randomSource = level.random; ++ RandomSource randomsource = level.random; ++ + if (this.maxSpawnDelay <= this.minSpawnDelay) { + this.spawnDelay = this.minSpawnDelay; + } else { +- this.spawnDelay = this.minSpawnDelay + randomSource.nextInt(this.maxSpawnDelay - this.minSpawnDelay); ++ this.spawnDelay = this.minSpawnDelay + randomsource.nextInt(this.maxSpawnDelay - this.minSpawnDelay); + } + +- this.spawnPotentials.getRandom(randomSource).ifPresent(data -> this.setNextSpawnData(level, pos, data.getData())); ++ this.spawnPotentials.getRandom(randomsource).ifPresent((weightedentry_b) -> { ++ this.setNextSpawnData(level, pos, (SpawnData) weightedentry_b.getData()); ++ }); + this.broadcastEvent(level, pos, 1); + } + + public void load(@Nullable Level level, BlockPos pos, CompoundTag tag) { + this.spawnDelay = tag.getShort("Delay"); + boolean flag = tag.contains("SpawnData", 10); ++ + if (flag) { +- SpawnData spawnData = SpawnData.CODEC +- .parse(NbtOps.INSTANCE, tag.getCompound("SpawnData")) +- .resultOrPartial(data -> LOGGER.warn("Invalid SpawnData: {}", data)) +- .orElseGet(SpawnData::new); +- this.setNextSpawnData(level, pos, spawnData); ++ SpawnData mobspawnerdata = (SpawnData) SpawnData.CODEC.parse(NbtOps.INSTANCE, tag.getCompound("SpawnData")).resultOrPartial((s) -> { ++ BaseSpawner.LOGGER.warn("Invalid SpawnData: {}", s); ++ }).orElseGet(SpawnData::new); ++ ++ this.setNextSpawnData(level, pos, mobspawnerdata); + } + + boolean flag1 = tag.contains("SpawnPotentials", 9); ++ + if (flag1) { +- ListTag list = tag.getList("SpawnPotentials", 10); +- this.spawnPotentials = SpawnData.LIST_CODEC +- .parse(NbtOps.INSTANCE, list) +- .resultOrPartial(potentials -> LOGGER.warn("Invalid SpawnPotentials list: {}", potentials)) +- .orElseGet(SimpleWeightedRandomList::empty); ++ ListTag nbttaglist = tag.getList("SpawnPotentials", 10); ++ ++ this.spawnPotentials = (SimpleWeightedRandomList) SpawnData.LIST_CODEC.parse(NbtOps.INSTANCE, nbttaglist).resultOrPartial((s) -> { ++ BaseSpawner.LOGGER.warn("Invalid SpawnPotentials list: {}", s); ++ }).orElseGet(SimpleWeightedRandomList::empty); + } else { + this.spawnPotentials = SimpleWeightedRandomList.single(this.nextSpawnData != null ? this.nextSpawnData : new SpawnData()); + } +@@ -232,34 +241,35 @@ + } + + public CompoundTag save(CompoundTag tag) { +- tag.putShort("Delay", (short)this.spawnDelay); +- tag.putShort("MinSpawnDelay", (short)this.minSpawnDelay); +- tag.putShort("MaxSpawnDelay", (short)this.maxSpawnDelay); +- tag.putShort("SpawnCount", (short)this.spawnCount); +- tag.putShort("MaxNearbyEntities", (short)this.maxNearbyEntities); +- tag.putShort("RequiredPlayerRange", (short)this.requiredPlayerRange); +- tag.putShort("SpawnRange", (short)this.spawnRange); ++ tag.putShort("Delay", (short) this.spawnDelay); ++ tag.putShort("MinSpawnDelay", (short) this.minSpawnDelay); ++ tag.putShort("MaxSpawnDelay", (short) this.maxSpawnDelay); ++ tag.putShort("SpawnCount", (short) this.spawnCount); ++ tag.putShort("MaxNearbyEntities", (short) this.maxNearbyEntities); ++ tag.putShort("RequiredPlayerRange", (short) this.requiredPlayerRange); ++ tag.putShort("SpawnRange", (short) this.spawnRange); + if (this.nextSpawnData != null) { +- tag.put( +- "SpawnData", +- SpawnData.CODEC.encodeStart(NbtOps.INSTANCE, this.nextSpawnData).result().orElseThrow(() -> new IllegalStateException("Invalid SpawnData")) +- ); ++ tag.put("SpawnData", (Tag) SpawnData.CODEC.encodeStart(NbtOps.INSTANCE, this.nextSpawnData).result().orElseThrow(() -> { ++ return new IllegalStateException("Invalid SpawnData"); ++ })); + } + +- tag.put("SpawnPotentials", SpawnData.LIST_CODEC.encodeStart(NbtOps.INSTANCE, this.spawnPotentials).result().orElseThrow()); ++ tag.put("SpawnPotentials", (Tag) SpawnData.LIST_CODEC.encodeStart(NbtOps.INSTANCE, this.spawnPotentials).result().orElseThrow()); + return tag; + } + + @Nullable +- public Entity getOrCreateDisplayEntity(Level level, BlockPos blockPos) { ++ public Entity getOrCreateDisplayEntity(Level world, BlockPos blockposition) { + if (this.displayEntity == null) { +- CompoundTag entityToSpawn = this.getOrCreateNextSpawnData(level, level.getRandom(), blockPos).getEntityToSpawn(); +- if (!entityToSpawn.contains("id", 8)) { ++ CompoundTag nbttagcompound = this.getOrCreateNextSpawnData(world, world.getRandom(), blockposition).getEntityToSpawn(); ++ ++ if (!nbttagcompound.contains("id", 8)) { + return null; + } + +- this.displayEntity = EntityType.loadEntityRecursive(entityToSpawn, level, Function.identity()); +- if (entityToSpawn.size() == 1 && this.displayEntity instanceof Mob) { ++ this.displayEntity = EntityType.loadEntityRecursive(nbttagcompound, world, Function.identity()); ++ if (nbttagcompound.size() == 1 && this.displayEntity instanceof Mob) { ++ ; + } + } + +@@ -286,7 +296,7 @@ + if (this.nextSpawnData != null) { + return this.nextSpawnData; + } else { +- this.setNextSpawnData(level, pos, this.spawnPotentials.getRandom(random).map(WeightedEntry.Wrapper::getData).orElseGet(SpawnData::new)); ++ this.setNextSpawnData(level, pos, (SpawnData) this.spawnPotentials.getRandom(random).map(WeightedEntry.Wrapper::getData).orElseGet(SpawnData::new)); + return this.nextSpawnData; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/BlockGetter.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/BlockGetter.java.patch new file mode 100644 index 0000000000..b818ddd2bd --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/BlockGetter.java.patch @@ -0,0 +1,254 @@ +--- a/net/minecraft/world/level/BlockGetter.java ++++ b/net/minecraft/world/level/BlockGetter.java +@@ -11,7 +11,7 @@ + import net.minecraft.util.Mth; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BlockEntityType; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.BlockHitResult; +@@ -19,15 +19,17 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + + public interface BlockGetter extends LevelHeightAccessor { ++ + @Nullable + BlockEntity getBlockEntity(BlockPos pos); + + default Optional getBlockEntity(BlockPos pos, BlockEntityType blockEntityType) { +- BlockEntity blockEntity = this.getBlockEntity(pos); +- return blockEntity != null && blockEntity.getType() == blockEntityType ? Optional.of((T)blockEntity) : Optional.empty(); ++ BlockEntity tileentity = this.getBlockEntity(pos); ++ ++ return tileentity != null && tileentity.getType() == blockEntityType ? (Optional) Optional.of(tileentity) : Optional.empty(); // CraftBukkit - decompile error + } + +- BlockState getBlockState(BlockPos pos); ++ IBlockData getBlockState(BlockPos pos); + + FluidState getFluidState(BlockPos pos); + +@@ -39,77 +41,80 @@ + return 15; + } + +- default Stream getBlockStates(AABB area) { ++ default Stream getBlockStates(AABB area) { + return BlockPos.betweenClosedStream(area).map(this::getBlockState); + } + + default BlockHitResult isBlockInLine(ClipBlockStateContext context) { +- return traverseBlocks( +- context.getFrom(), +- context.getTo(), +- context, +- (traverseContext, traversePos) -> { +- BlockState blockState = this.getBlockState(traversePos); +- Vec3 vec3 = traverseContext.getFrom().subtract(traverseContext.getTo()); +- return traverseContext.isTargetBlock().test(blockState) +- ? new BlockHitResult( +- traverseContext.getTo(), Direction.getNearest(vec3.x, vec3.y, vec3.z), BlockPos.containing(traverseContext.getTo()), false +- ) +- : null; +- }, +- failContext -> { +- Vec3 vec3 = failContext.getFrom().subtract(failContext.getTo()); +- return BlockHitResult.miss(failContext.getTo(), Direction.getNearest(vec3.x, vec3.y, vec3.z), BlockPos.containing(failContext.getTo())); +- } +- ); ++ return (BlockHitResult) traverseBlocks(context.getFrom(), context.getTo(), context, (clipblockstatecontext1, blockposition) -> { ++ IBlockData iblockdata = this.getBlockState(blockposition); ++ Vec3 vec3d = clipblockstatecontext1.getFrom().subtract(clipblockstatecontext1.getTo()); ++ ++ return clipblockstatecontext1.isTargetBlock().test(iblockdata) ? new BlockHitResult(clipblockstatecontext1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(clipblockstatecontext1.getTo()), false) : null; ++ }, (clipblockstatecontext1) -> { ++ Vec3 vec3d = clipblockstatecontext1.getFrom().subtract(clipblockstatecontext1.getTo()); ++ ++ return BlockHitResult.miss(clipblockstatecontext1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(clipblockstatecontext1.getTo())); ++ }); + } + ++ // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace ++ default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition) { ++ IBlockData iblockdata = this.getBlockState(blockposition); ++ FluidState fluid = this.getFluidState(blockposition); ++ Vec3 vec3d = raytrace1.getFrom(); ++ Vec3 vec3d1 = raytrace1.getTo(); ++ VoxelShape voxelshape = raytrace1.getBlockShape(iblockdata, this, blockposition); ++ BlockHitResult movingobjectpositionblock = this.clipWithInteractionOverride(vec3d, vec3d1, blockposition, voxelshape, iblockdata); ++ VoxelShape voxelshape1 = raytrace1.getFluidShape(fluid, this, blockposition); ++ BlockHitResult movingobjectpositionblock1 = voxelshape1.clip(vec3d, vec3d1, blockposition); ++ double d0 = movingobjectpositionblock == null ? Double.MAX_VALUE : raytrace1.getFrom().distanceToSqr(movingobjectpositionblock.getLocation()); ++ double d1 = movingobjectpositionblock1 == null ? Double.MAX_VALUE : raytrace1.getFrom().distanceToSqr(movingobjectpositionblock1.getLocation()); ++ ++ return d0 <= d1 ? movingobjectpositionblock : movingobjectpositionblock1; ++ } ++ // CraftBukkit end ++ + default BlockHitResult clip(ClipContext context) { +- return traverseBlocks(context.getFrom(), context.getTo(), context, (traverseContext, traversePos) -> { +- BlockState blockState = this.getBlockState(traversePos); +- FluidState fluidState = this.getFluidState(traversePos); +- Vec3 from = traverseContext.getFrom(); +- Vec3 to = traverseContext.getTo(); +- VoxelShape blockShape = traverseContext.getBlockShape(blockState, this, traversePos); +- BlockHitResult blockHitResult = this.clipWithInteractionOverride(from, to, traversePos, blockShape, blockState); +- VoxelShape fluidShape = traverseContext.getFluidShape(fluidState, this, traversePos); +- BlockHitResult blockHitResult1 = fluidShape.clip(from, to, traversePos); +- double d = blockHitResult == null ? Double.MAX_VALUE : traverseContext.getFrom().distanceToSqr(blockHitResult.getLocation()); +- double d1 = blockHitResult1 == null ? Double.MAX_VALUE : traverseContext.getFrom().distanceToSqr(blockHitResult1.getLocation()); +- return d <= d1 ? blockHitResult : blockHitResult1; +- }, failContext -> { +- Vec3 vec3 = failContext.getFrom().subtract(failContext.getTo()); +- return BlockHitResult.miss(failContext.getTo(), Direction.getNearest(vec3.x, vec3.y, vec3.z), BlockPos.containing(failContext.getTo())); ++ return (BlockHitResult) traverseBlocks(context.getFrom(), context.getTo(), context, (raytrace1, blockposition) -> { ++ return this.clip(raytrace1, blockposition); // CraftBukkit - moved into separate method ++ }, (raytrace1) -> { ++ Vec3 vec3d = raytrace1.getFrom().subtract(raytrace1.getTo()); ++ ++ return BlockHitResult.miss(raytrace1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(raytrace1.getTo())); + }); + } + + @Nullable +- default BlockHitResult clipWithInteractionOverride(Vec3 startVec, Vec3 endVec, BlockPos pos, VoxelShape shape, BlockState state) { +- BlockHitResult blockHitResult = shape.clip(startVec, endVec, pos); +- if (blockHitResult != null) { +- BlockHitResult blockHitResult1 = state.getInteractionShape(this, pos).clip(startVec, endVec, pos); +- if (blockHitResult1 != null +- && blockHitResult1.getLocation().subtract(startVec).lengthSqr() < blockHitResult.getLocation().subtract(startVec).lengthSqr()) { +- return blockHitResult.withDirection(blockHitResult1.getDirection()); ++ default BlockHitResult clipWithInteractionOverride(Vec3 startVec, Vec3 endVec, BlockPos pos, VoxelShape shape, IBlockData state) { ++ BlockHitResult movingobjectpositionblock = shape.clip(startVec, endVec, pos); ++ ++ if (movingobjectpositionblock != null) { ++ BlockHitResult movingobjectpositionblock1 = state.getInteractionShape(this, pos).clip(startVec, endVec, pos); ++ ++ if (movingobjectpositionblock1 != null && movingobjectpositionblock1.getLocation().subtract(startVec).lengthSqr() < movingobjectpositionblock.getLocation().subtract(startVec).lengthSqr()) { ++ return movingobjectpositionblock.withDirection(movingobjectpositionblock1.getDirection()); + } + } + +- return blockHitResult; ++ return movingobjectpositionblock; + } + + default double getBlockFloorHeight(VoxelShape shape, Supplier belowShapeSupplier) { + if (!shape.isEmpty()) { + return shape.max(Direction.Axis.Y); + } else { +- double d = belowShapeSupplier.get().max(Direction.Axis.Y); +- return d >= 1.0 ? d - 1.0 : Double.NEGATIVE_INFINITY; ++ double d0 = ((VoxelShape) belowShapeSupplier.get()).max(Direction.Axis.Y); ++ ++ return d0 >= 1.0D ? d0 - 1.0D : Double.NEGATIVE_INFINITY; + } + } + + default double getBlockFloorHeight(BlockPos pos) { + return this.getBlockFloorHeight(this.getBlockState(pos).getCollisionShape(this, pos), () -> { +- BlockPos blockPos = pos.below(); +- return this.getBlockState(blockPos).getCollisionShape(this, blockPos); ++ BlockPos blockposition1 = pos.below(); ++ ++ return this.getBlockState(blockposition1).getCollisionShape(this, blockposition1); + }); + } + +@@ -117,57 +122,61 @@ + if (from.equals(to)) { + return onFail.apply(context); + } else { +- double d = Mth.lerp(-1.0E-7, to.x, from.x); +- double d1 = Mth.lerp(-1.0E-7, to.y, from.y); +- double d2 = Mth.lerp(-1.0E-7, to.z, from.z); +- double d3 = Mth.lerp(-1.0E-7, from.x, to.x); +- double d4 = Mth.lerp(-1.0E-7, from.y, to.y); +- double d5 = Mth.lerp(-1.0E-7, from.z, to.z); +- int floor = Mth.floor(d3); +- int floor1 = Mth.floor(d4); +- int floor2 = Mth.floor(d5); +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(floor, floor1, floor2); +- T object = tester.apply(context, mutableBlockPos); +- if (object != null) { +- return object; ++ double d0 = Mth.lerp(-1.0E-7D, to.x, from.x); ++ double d1 = Mth.lerp(-1.0E-7D, to.y, from.y); ++ double d2 = Mth.lerp(-1.0E-7D, to.z, from.z); ++ double d3 = Mth.lerp(-1.0E-7D, from.x, to.x); ++ double d4 = Mth.lerp(-1.0E-7D, from.y, to.y); ++ double d5 = Mth.lerp(-1.0E-7D, from.z, to.z); ++ int i = Mth.floor(d3); ++ int j = Mth.floor(d4); ++ int k = Mth.floor(d5); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(i, j, k); ++ T t0 = tester.apply(context, blockposition_mutableblockposition); ++ ++ if (t0 != null) { ++ return t0; + } else { +- double d6 = d - d3; ++ double d6 = d0 - d3; + double d7 = d1 - d4; + double d8 = d2 - d5; +- int i = Mth.sign(d6); ++ int l = Mth.sign(d6); + int i1 = Mth.sign(d7); +- int i2 = Mth.sign(d8); +- double d9 = i == 0 ? Double.MAX_VALUE : (double)i / d6; +- double d10 = i1 == 0 ? Double.MAX_VALUE : (double)i1 / d7; +- double d11 = i2 == 0 ? Double.MAX_VALUE : (double)i2 / d8; +- double d12 = d9 * (i > 0 ? 1.0 - Mth.frac(d3) : Mth.frac(d3)); +- double d13 = d10 * (i1 > 0 ? 1.0 - Mth.frac(d4) : Mth.frac(d4)); +- double d14 = d11 * (i2 > 0 ? 1.0 - Mth.frac(d5) : Mth.frac(d5)); ++ int j1 = Mth.sign(d8); ++ double d9 = l == 0 ? Double.MAX_VALUE : (double) l / d6; ++ double d10 = i1 == 0 ? Double.MAX_VALUE : (double) i1 / d7; ++ double d11 = j1 == 0 ? Double.MAX_VALUE : (double) j1 / d8; ++ double d12 = d9 * (l > 0 ? 1.0D - Mth.frac(d3) : Mth.frac(d3)); ++ double d13 = d10 * (i1 > 0 ? 1.0D - Mth.frac(d4) : Mth.frac(d4)); ++ double d14 = d11 * (j1 > 0 ? 1.0D - Mth.frac(d5) : Mth.frac(d5)); + +- while (d12 <= 1.0 || d13 <= 1.0 || d14 <= 1.0) { ++ T object; // CraftBukkit - decompile error ++ ++ do { ++ if (d12 > 1.0D && d13 > 1.0D && d14 > 1.0D) { ++ return onFail.apply(context); ++ } ++ + if (d12 < d13) { + if (d12 < d14) { +- floor += i; ++ i += l; + d12 += d9; + } else { +- floor2 += i2; ++ k += j1; + d14 += d11; + } + } else if (d13 < d14) { +- floor1 += i1; ++ j += i1; + d13 += d10; + } else { +- floor2 += i2; ++ k += j1; + d14 += d11; + } + +- T object1 = tester.apply(context, mutableBlockPos.set(floor, floor1, floor2)); +- if (object1 != null) { +- return object1; +- } +- } ++ object = tester.apply(context, blockposition_mutableblockposition.set(i, j, k)); ++ } while (object == null); + +- return onFail.apply(context); ++ return object; + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/ClipContext.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/ClipContext.java.patch new file mode 100644 index 0000000000..b1405c9354 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/ClipContext.java.patch @@ -0,0 +1,111 @@ +--- a/net/minecraft/world/level/ClipContext.java ++++ b/net/minecraft/world/level/ClipContext.java +@@ -6,7 +6,7 @@ + import net.minecraft.tags.FluidTags; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; +@@ -14,6 +14,7 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + + public class ClipContext { ++ + private final Vec3 from; + private final Vec3 to; + private final ClipContext.Block block; +@@ -21,15 +22,15 @@ + private final CollisionContext collisionContext; + + public ClipContext(Vec3 from, Vec3 to, ClipContext.Block block, ClipContext.Fluid fluid, Entity entity) { +- this(from, to, block, fluid, CollisionContext.of(entity)); ++ this(from, to, block, fluid, (entity == null) ? CollisionContext.empty() : CollisionContext.of(entity)); // CraftBukkit + } + +- public ClipContext(Vec3 vec3, Vec3 vec31, ClipContext.Block block, ClipContext.Fluid fluid, CollisionContext collisionContext) { +- this.from = vec3; +- this.to = vec31; +- this.block = block; +- this.fluid = fluid; +- this.collisionContext = collisionContext; ++ public ClipContext(Vec3 vec3d, Vec3 vec3d1, ClipContext.Block raytrace_blockcollisionoption, ClipContext.Fluid raytrace_fluidcollisionoption, CollisionContext voxelshapecollision) { ++ this.from = vec3d; ++ this.to = vec3d1; ++ this.block = raytrace_blockcollisionoption; ++ this.fluid = raytrace_fluidcollisionoption; ++ this.collisionContext = voxelshapecollision; + } + + public Vec3 getTo() { +@@ -40,7 +41,7 @@ + return this.from; + } + +- public VoxelShape getBlockShape(BlockState blockState, BlockGetter level, BlockPos pos) { ++ public VoxelShape getBlockShape(IBlockData blockState, BlockGetter level, BlockPos pos) { + return this.block.get(blockState, level, pos, this.collisionContext); + } + +@@ -49,33 +50,37 @@ + } + + public static enum Block implements ClipContext.ShapeGetter { +- COLLIDER(BlockBehaviour.BlockStateBase::getCollisionShape), +- OUTLINE(BlockBehaviour.BlockStateBase::getShape), +- VISUAL(BlockBehaviour.BlockStateBase::getVisualShape), +- FALLDAMAGE_RESETTING((state, block, pos, collisionContext) -> state.is(BlockTags.FALL_DAMAGE_RESETTING) ? Shapes.block() : Shapes.empty()); + ++ COLLIDER(BlockBehaviour.BlockStateBase::getCollisionShape), OUTLINE(BlockBehaviour.BlockStateBase::getShape), VISUAL(BlockBehaviour.BlockStateBase::getVisualShape), FALLDAMAGE_RESETTING((iblockdata, iblockaccess, blockposition, voxelshapecollision) -> { ++ return iblockdata.is(BlockTags.FALL_DAMAGE_RESETTING) ? Shapes.block() : Shapes.empty(); ++ }); ++ + private final ClipContext.ShapeGetter shapeGetter; + +- private Block(ClipContext.ShapeGetter shapeGetter) { +- this.shapeGetter = shapeGetter; ++ private Block(ClipContext.ShapeGetter raytrace_c) { ++ this.shapeGetter = raytrace_c; + } + + @Override +- public VoxelShape get(BlockState state, BlockGetter block, BlockPos pos, CollisionContext collisionContext) { ++ public VoxelShape get(IBlockData state, BlockGetter block, BlockPos pos, CollisionContext collisionContext) { + return this.shapeGetter.get(state, block, pos, collisionContext); + } + } + + public static enum Fluid { +- NONE(fluid -> false), +- SOURCE_ONLY(FluidState::isSource), +- ANY(fluid -> !fluid.isEmpty()), +- WATER(fluid -> fluid.is(FluidTags.WATER)); + ++ NONE((fluid) -> { ++ return false; ++ }), SOURCE_ONLY(FluidState::isSource), ANY((fluid) -> { ++ return !fluid.isEmpty(); ++ }), WATER((fluid) -> { ++ return fluid.is(FluidTags.WATER); ++ }); ++ + private final Predicate canPick; + +- private Fluid(Predicate canPick) { +- this.canPick = canPick; ++ private Fluid(Predicate predicate) { // CraftBukkit - decompile error ++ this.canPick = predicate; + } + + public boolean canPick(FluidState state) { +@@ -84,6 +89,7 @@ + } + + public interface ShapeGetter { +- VoxelShape get(BlockState state, BlockGetter block, BlockPos pos, CollisionContext collisionContext); ++ ++ VoxelShape get(IBlockData state, BlockGetter block, BlockPos pos, CollisionContext collisionContext); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/Explosion.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/Explosion.java.patch new file mode 100644 index 0000000000..fa41a48d09 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/Explosion.java.patch @@ -0,0 +1,694 @@ +--- a/net/minecraft/world/level/Explosion.java ++++ b/net/minecraft/world/level/Explosion.java +@@ -4,7 +4,9 @@ + import com.google.common.collect.Sets; + import com.mojang.datafixers.util.Pair; + import it.unimi.dsi.fastutil.objects.ObjectArrayList; ++import it.unimi.dsi.fastutil.objects.ObjectListIterator; + import java.util.ArrayList; ++import java.util.Iterator; + import java.util.List; + import java.util.Map; + import java.util.Optional; +@@ -22,6 +24,8 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; ++import net.minecraft.world.entity.boss.EnderDragonPart; ++import net.minecraft.world.entity.boss.enderdragon.EnderDragon; + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.item.PrimedTnt; + import net.minecraft.world.entity.player.Player; +@@ -30,160 +34,117 @@ + import net.minecraft.world.item.enchantment.ProtectionEnchantment; + import net.minecraft.world.level.block.BaseFireBlock; + import net.minecraft.world.level.block.Block; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++import net.minecraft.world.level.block.Blocks; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityExplodeEvent; ++import org.bukkit.Location; ++import org.bukkit.event.block.BlockExplodeEvent; ++// CraftBukkit end + + public class Explosion { ++ + private static final ExplosionDamageCalculator EXPLOSION_DAMAGE_CALCULATOR = new ExplosionDamageCalculator(); + private static final int MAX_DROPS_PER_COMBINED_STACK = 16; + private final boolean fire; +- private final Explosion.BlockInteraction blockInteraction; +- private final RandomSource random = RandomSource.create(); ++ private final Explosion.Effect blockInteraction; ++ private final RandomSource random; + private final Level level; + private final double x; + private final double y; + private final double z; + @Nullable +- private final Entity source; ++ public final Entity source; + private final float radius; + private final DamageSource damageSource; + private final ExplosionDamageCalculator damageCalculator; + private final ParticleOptions smallExplosionParticles; + private final ParticleOptions largeExplosionParticles; + private final SoundEvent explosionSound; +- private final ObjectArrayList toBlow = new ObjectArrayList<>(); +- private final Map hitPlayers = Maps.newHashMap(); ++ private final ObjectArrayList toBlow; ++ private final Map hitPlayers; ++ // CraftBukkit - add field ++ public boolean wasCanceled = false; ++ public float yield; ++ // CraftBukkit end + +- public static DamageSource getDefaultDamageSource(Level level, @Nullable Entity entity) { +- return level.damageSources().explosion(entity, getIndirectSourceEntityInternal(entity)); ++ public static DamageSource getDefaultDamageSource(Level world, @Nullable Entity entity) { ++ return world.damageSources().explosion(entity, getIndirectSourceEntityInternal(entity)); + } + +- public Explosion( +- Level level, +- @Nullable Entity entity, +- double d, +- double d1, +- double d2, +- float f, +- List list, +- Explosion.BlockInteraction blockInteraction, +- ParticleOptions particleOptions, +- ParticleOptions particleOptions1, +- SoundEvent soundEvent +- ) { +- this(level, entity, getDefaultDamageSource(level, entity), null, d, d1, d2, f, false, blockInteraction, particleOptions, particleOptions1, soundEvent); ++ public Explosion(Level world, @Nullable Entity entity, double d0, double d1, double d2, float f, List list, Explosion.Effect explosion_effect, ParticleOptions particleparam, ParticleOptions particleparam1, SoundEvent soundeffect) { ++ this(world, entity, getDefaultDamageSource(world, entity), (ExplosionDamageCalculator) null, d0, d1, d2, f, false, explosion_effect, particleparam, particleparam1, soundeffect); + this.toBlow.addAll(list); + } + +- public Explosion( +- Level level, +- @Nullable Entity source, +- double toBlowX, +- double toBlowY, +- double toBlowZ, +- float radius, +- boolean fire, +- Explosion.BlockInteraction blockInteraction, +- List positions +- ) { +- this(level, source, toBlowX, toBlowY, toBlowZ, radius, fire, blockInteraction); +- this.toBlow.addAll(positions); ++ public Explosion(Level level, @Nullable Entity source, double toBlowX, double d1, double toBlowY, float f, boolean toBlowZ, Explosion.Effect explosion_effect, List radius) { ++ this(level, source, toBlowX, d1, toBlowY, f, toBlowZ, explosion_effect); ++ this.toBlow.addAll(radius); + } + +- public Explosion( +- Level level, +- @Nullable Entity source, +- double toBlowX, +- double toBlowY, +- double toBlowZ, +- float radius, +- boolean fire, +- Explosion.BlockInteraction blockInteraction +- ) { +- this( +- level, +- source, +- getDefaultDamageSource(level, source), +- null, +- toBlowX, +- toBlowY, +- toBlowZ, +- radius, +- fire, +- blockInteraction, +- ParticleTypes.EXPLOSION, +- ParticleTypes.EXPLOSION_EMITTER, +- SoundEvents.GENERIC_EXPLODE +- ); ++ public Explosion(Level level, @Nullable Entity source, double toBlowX, double d1, double toBlowY, float f, boolean toBlowZ, Explosion.Effect explosion_effect) { ++ this(level, source, getDefaultDamageSource(level, source), (ExplosionDamageCalculator) null, toBlowX, d1, toBlowY, f, toBlowZ, explosion_effect, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); + } + +- public Explosion( +- Level level, +- @Nullable Entity entity, +- @Nullable DamageSource damageSource, +- @Nullable ExplosionDamageCalculator explosionDamageCalculator, +- double d, +- double d1, +- double d2, +- float f, +- boolean flag, +- Explosion.BlockInteraction blockInteraction, +- ParticleOptions particleOptions, +- ParticleOptions particleOptions1, +- SoundEvent soundEvent +- ) { +- this.level = level; ++ public Explosion(Level world, @Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Explosion.Effect explosion_effect, ParticleOptions particleparam, ParticleOptions particleparam1, SoundEvent soundeffect) { ++ this.random = RandomSource.create(); ++ this.toBlow = new ObjectArrayList(); ++ this.hitPlayers = Maps.newHashMap(); ++ this.level = world; + this.source = entity; +- this.radius = f; +- this.x = d; ++ this.radius = (float) Math.max(f, 0.0); // CraftBukkit - clamp bad values ++ this.x = d0; + this.y = d1; + this.z = d2; + this.fire = flag; +- this.blockInteraction = blockInteraction; +- this.damageSource = damageSource == null ? level.damageSources().explosion(this) : damageSource; +- this.damageCalculator = explosionDamageCalculator == null ? this.makeDamageCalculator(entity) : explosionDamageCalculator; +- this.smallExplosionParticles = particleOptions; +- this.largeExplosionParticles = particleOptions1; +- this.explosionSound = soundEvent; ++ this.blockInteraction = explosion_effect; ++ this.damageSource = damagesource == null ? world.damageSources().explosion(this) : damagesource; ++ this.damageCalculator = explosiondamagecalculator == null ? this.makeDamageCalculator(entity) : explosiondamagecalculator; ++ this.smallExplosionParticles = particleparam; ++ this.largeExplosionParticles = particleparam1; ++ this.explosionSound = soundeffect; ++ this.yield = this.blockInteraction == Explosion.Effect.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F; // CraftBukkit + } + + private ExplosionDamageCalculator makeDamageCalculator(@Nullable Entity entity) { +- return (ExplosionDamageCalculator)(entity == null ? EXPLOSION_DAMAGE_CALCULATOR : new EntityBasedExplosionDamageCalculator(entity)); ++ return (ExplosionDamageCalculator) (entity == null ? Explosion.EXPLOSION_DAMAGE_CALCULATOR : new EntityBasedExplosionDamageCalculator(entity)); + } + + public static float getSeenPercent(Vec3 explosionVector, Entity entity) { +- AABB boundingBox = entity.getBoundingBox(); +- double d = 1.0 / ((boundingBox.maxX - boundingBox.minX) * 2.0 + 1.0); +- double d1 = 1.0 / ((boundingBox.maxY - boundingBox.minY) * 2.0 + 1.0); +- double d2 = 1.0 / ((boundingBox.maxZ - boundingBox.minZ) * 2.0 + 1.0); +- double d3 = (1.0 - Math.floor(1.0 / d) * d) / 2.0; +- double d4 = (1.0 - Math.floor(1.0 / d2) * d2) / 2.0; +- if (!(d < 0.0) && !(d1 < 0.0) && !(d2 < 0.0)) { ++ AABB axisalignedbb = entity.getBoundingBox(); ++ double d0 = 1.0D / ((axisalignedbb.maxX - axisalignedbb.minX) * 2.0D + 1.0D); ++ double d1 = 1.0D / ((axisalignedbb.maxY - axisalignedbb.minY) * 2.0D + 1.0D); ++ double d2 = 1.0D / ((axisalignedbb.maxZ - axisalignedbb.minZ) * 2.0D + 1.0D); ++ double d3 = (1.0D - Math.floor(1.0D / d0) * d0) / 2.0D; ++ double d4 = (1.0D - Math.floor(1.0D / d2) * d2) / 2.0D; ++ ++ if (d0 >= 0.0D && d1 >= 0.0D && d2 >= 0.0D) { + int i = 0; +- int i1 = 0; ++ int j = 0; + +- for (double d5 = 0.0; d5 <= 1.0; d5 += d) { +- for (double d6 = 0.0; d6 <= 1.0; d6 += d1) { +- for (double d7 = 0.0; d7 <= 1.0; d7 += d2) { +- double d8 = Mth.lerp(d5, boundingBox.minX, boundingBox.maxX); +- double d9 = Mth.lerp(d6, boundingBox.minY, boundingBox.maxY); +- double d10 = Mth.lerp(d7, boundingBox.minZ, boundingBox.maxZ); +- Vec3 vec3 = new Vec3(d8 + d3, d9, d10 + d4); +- if (entity.level().clip(new ClipContext(vec3, explosionVector, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, entity)).getType() +- == HitResult.Type.MISS) { +- i++; ++ for (double d5 = 0.0D; d5 <= 1.0D; d5 += d0) { ++ for (double d6 = 0.0D; d6 <= 1.0D; d6 += d1) { ++ for (double d7 = 0.0D; d7 <= 1.0D; d7 += d2) { ++ double d8 = Mth.lerp(d5, axisalignedbb.minX, axisalignedbb.maxX); ++ double d9 = Mth.lerp(d6, axisalignedbb.minY, axisalignedbb.maxY); ++ double d10 = Mth.lerp(d7, axisalignedbb.minZ, axisalignedbb.maxZ); ++ Vec3 vec3d1 = new Vec3(d8 + d3, d9, d10 + d4); ++ ++ if (entity.level().clip(new ClipContext(vec3d1, explosionVector, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, entity)).getType() == HitResult.EnumMovingObjectType.MISS) { ++ ++i; + } + +- i1++; ++ ++j; + } + } + } + +- return (float)i / (float)i1; ++ return (float) i / (float) j; + } else { + return 0.0F; + } +@@ -198,47 +159,57 @@ + } + + public void explode() { ++ // CraftBukkit start ++ if (this.radius < 0.1F) { ++ return; ++ } ++ // CraftBukkit end + this.level.gameEvent(this.source, GameEvent.EXPLODE, new Vec3(this.x, this.y, this.z)); + Set set = Sets.newHashSet(); +- int i = 16; ++ boolean flag = true; + +- for (int i1 = 0; i1 < 16; i1++) { +- for (int i2 = 0; i2 < 16; i2++) { +- for (int i3 = 0; i3 < 16; i3++) { +- if (i1 == 0 || i1 == 15 || i2 == 0 || i2 == 15 || i3 == 0 || i3 == 15) { +- double d = (double)((float)i1 / 15.0F * 2.0F - 1.0F); +- double d1 = (double)((float)i2 / 15.0F * 2.0F - 1.0F); +- double d2 = (double)((float)i3 / 15.0F * 2.0F - 1.0F); +- double squareRoot = Math.sqrt(d * d + d1 * d1 + d2 * d2); +- double var33 = d / squareRoot; +- double var35 = d1 / squareRoot; +- double var37 = d2 / squareRoot; ++ int i; ++ int j; ++ ++ for (int k = 0; k < 16; ++k) { ++ for (i = 0; i < 16; ++i) { ++ for (j = 0; j < 16; ++j) { ++ if (k == 0 || k == 15 || i == 0 || i == 15 || j == 0 || j == 15) { ++ double d0 = (double) ((float) k / 15.0F * 2.0F - 1.0F); ++ double d1 = (double) ((float) i / 15.0F * 2.0F - 1.0F); ++ double d2 = (double) ((float) j / 15.0F * 2.0F - 1.0F); ++ double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2); ++ ++ d0 /= d3; ++ d1 /= d3; ++ d2 /= d3; + float f = this.radius * (0.7F + this.level.random.nextFloat() * 0.6F); +- double d3 = this.x; +- double d4 = this.y; +- double d5 = this.z; ++ double d4 = this.x; ++ double d5 = this.y; ++ double d6 = this.z; + + for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { +- BlockPos blockPos = BlockPos.containing(d3, d4, d5); +- BlockState blockState = this.level.getBlockState(blockPos); +- FluidState fluidState = this.level.getFluidState(blockPos); +- if (!this.level.isInWorldBounds(blockPos)) { ++ BlockPos blockposition = BlockPos.containing(d4, d5, d6); ++ IBlockData iblockdata = this.level.getBlockState(blockposition); ++ FluidState fluid = this.level.getFluidState(blockposition); ++ ++ if (!this.level.isInWorldBounds(blockposition)) { + break; + } + +- Optional blockExplosionResistance = this.damageCalculator +- .getBlockExplosionResistance(this, this.level, blockPos, blockState, fluidState); +- if (blockExplosionResistance.isPresent()) { +- f -= (blockExplosionResistance.get() + 0.3F) * 0.3F; ++ Optional optional = this.damageCalculator.getBlockExplosionResistance(this, this.level, blockposition, iblockdata, fluid); ++ ++ if (optional.isPresent()) { ++ f -= ((Float) optional.get() + 0.3F) * 0.3F; + } + +- if (f > 0.0F && this.damageCalculator.shouldBlockExplode(this, this.level, blockPos, blockState, f)) { +- set.add(blockPos); ++ if (f > 0.0F && this.damageCalculator.shouldBlockExplode(this, this.level, blockposition, iblockdata, f)) { ++ set.add(blockposition); + } + +- d3 += var33 * 0.3F; +- d4 += var35 * 0.3F; +- d5 += var37 * 0.3F; ++ d4 += d0 * 0.30000001192092896D; ++ d5 += d1 * 0.30000001192092896D; ++ d6 += d2 * 0.30000001192092896D; + } + } + } +@@ -247,130 +218,234 @@ + + this.toBlow.addAll(set); + float f2 = this.radius * 2.0F; +- int i2 = Mth.floor(this.x - (double)f2 - 1.0); +- int i3x = Mth.floor(this.x + (double)f2 + 1.0); +- int floor = Mth.floor(this.y - (double)f2 - 1.0); +- int floor1 = Mth.floor(this.y + (double)f2 + 1.0); +- int floor2 = Mth.floor(this.z - (double)f2 - 1.0); +- int floor3 = Mth.floor(this.z + (double)f2 + 1.0); +- List entities = this.level +- .getEntities(this.source, new AABB((double)i2, (double)floor, (double)floor2, (double)i3x, (double)floor1, (double)floor3)); +- Vec3 vec3 = new Vec3(this.x, this.y, this.z); + +- for (Entity entity : entities) { ++ i = Mth.floor(this.x - (double) f2 - 1.0D); ++ j = Mth.floor(this.x + (double) f2 + 1.0D); ++ int l = Mth.floor(this.y - (double) f2 - 1.0D); ++ int i1 = Mth.floor(this.y + (double) f2 + 1.0D); ++ int j1 = Mth.floor(this.z - (double) f2 - 1.0D); ++ int k1 = Mth.floor(this.z + (double) f2 + 1.0D); ++ List list = this.level.getEntities(this.source, new AABB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1)); ++ Vec3 vec3d = new Vec3(this.x, this.y, this.z); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ + if (!entity.ignoreExplosion(this)) { +- double d6 = Math.sqrt(entity.distanceToSqr(vec3)) / (double)f2; +- if (d6 <= 1.0) { +- double d7 = entity.getX() - this.x; +- double d8 = (entity instanceof PrimedTnt ? entity.getY() : entity.getEyeY()) - this.y; +- double d9 = entity.getZ() - this.z; +- double squareRoot1 = Math.sqrt(d7 * d7 + d8 * d8 + d9 * d9); +- if (squareRoot1 != 0.0) { +- double var41 = d7 / squareRoot1; +- double var43 = d8 / squareRoot1; +- double var45 = d9 / squareRoot1; ++ double d7 = Math.sqrt(entity.distanceToSqr(vec3d)) / (double) f2; ++ ++ if (d7 <= 1.0D) { ++ double d8 = entity.getX() - this.x; ++ double d9 = (entity instanceof PrimedTnt ? entity.getY() : entity.getEyeY()) - this.y; ++ double d10 = entity.getZ() - this.z; ++ double d11 = Math.sqrt(d8 * d8 + d9 * d9 + d10 * d10); ++ ++ if (d11 != 0.0D) { ++ d8 /= d11; ++ d9 /= d11; ++ d10 /= d11; + if (this.damageCalculator.shouldDamageEntity(this, entity)) { +- entity.hurt(this.damageSource, this.damageCalculator.getEntityDamageAmount(this, entity)); ++ // CraftBukkit start ++ ++ // Special case ender dragon only give knockback if no damage is cancelled ++ // Thinks to note: ++ // - Setting a velocity to a ComplexEntityPart is ignored (and therefore not needed) ++ // - Damaging ComplexEntityPart while forward the damage to EntityEnderDragon ++ // - Damaging EntityEnderDragon does nothing ++ // - EntityEnderDragon hitbock always covers the other parts and is therefore always present ++ if (entity instanceof EnderDragonPart) { ++ continue; ++ } ++ ++ CraftEventFactory.entityDamage = source; ++ entity.lastDamageCancelled = false; ++ ++ if (entity instanceof EnderDragon) { ++ for (EnderDragonPart entityComplexPart : ((EnderDragon) entity).subEntities) { ++ // Calculate damage separately for each EntityComplexPart ++ if (list.contains(entityComplexPart)) { ++ entityComplexPart.hurt(this.damageSource, this.damageCalculator.getEntityDamageAmount(this, entity)); ++ } ++ } ++ } else { ++ entity.hurt(this.damageSource, this.damageCalculator.getEntityDamageAmount(this, entity)); ++ } ++ ++ CraftEventFactory.entityDamage = null; ++ if (entity.lastDamageCancelled) { // SPIGOT-5339, SPIGOT-6252, SPIGOT-6777: Skip entity if damage event was cancelled ++ continue; ++ } ++ // CraftBukkit end + } + +- double d10 = (1.0 - d6) * (double)getSeenPercent(vec3, entity); +- double explosionKnockbackAfterDampener; +- if (entity instanceof LivingEntity livingEntity) { +- explosionKnockbackAfterDampener = ProtectionEnchantment.getExplosionKnockbackAfterDampener(livingEntity, d10); ++ double d12 = (1.0D - d7) * (double) getSeenPercent(vec3d, entity); ++ double d13; ++ ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ d13 = ProtectionEnchantment.getExplosionKnockbackAfterDampener(entityliving, d12); + } else { +- explosionKnockbackAfterDampener = d10; ++ d13 = d12; + } + +- d7 = var41 * explosionKnockbackAfterDampener; +- d8 = var43 * explosionKnockbackAfterDampener; +- d9 = var45 * explosionKnockbackAfterDampener; +- Vec3 vec31 = new Vec3(d7, d8, d9); +- entity.setDeltaMovement(entity.getDeltaMovement().add(vec31)); ++ d8 *= d13; ++ d9 *= d13; ++ d10 *= d13; ++ Vec3 vec3d1 = new Vec3(d8, d9, d10); ++ ++ entity.setDeltaMovement(entity.getDeltaMovement().add(vec3d1)); + if (entity instanceof Player) { +- Player player = (Player)entity; +- if (!player.isSpectator() && (!player.isCreative() || !player.getAbilities().flying)) { +- this.hitPlayers.put(player, vec31); ++ Player entityhuman = (Player) entity; ++ ++ if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.getAbilities().flying)) { ++ this.hitPlayers.put(entityhuman, vec3d1); + } + } + } + } + } + } ++ + } + + public void finalizeExplosion(boolean spawnParticles) { + if (this.level.isClientSide) { +- this.level +- .playLocalSound( +- this.x, +- this.y, +- this.z, +- this.explosionSound, +- SoundSource.BLOCKS, +- 4.0F, +- (1.0F + (this.level.random.nextFloat() - this.level.random.nextFloat()) * 0.2F) * 0.7F, +- false +- ); ++ this.level.playLocalSound(this.x, this.y, this.z, this.explosionSound, SoundSource.BLOCKS, 4.0F, (1.0F + (this.level.random.nextFloat() - this.level.random.nextFloat()) * 0.2F) * 0.7F, false); + } + +- boolean flag = this.interactsWithBlocks(); ++ boolean flag1 = this.interactsWithBlocks(); ++ + if (spawnParticles) { +- ParticleOptions particleOptions; +- if (!(this.radius < 2.0F) && flag) { +- particleOptions = this.largeExplosionParticles; ++ ParticleOptions particleparam; ++ ++ if (this.radius >= 2.0F && flag1) { ++ particleparam = this.largeExplosionParticles; + } else { +- particleOptions = this.smallExplosionParticles; ++ particleparam = this.smallExplosionParticles; + } + +- this.level.addParticle(particleOptions, this.x, this.y, this.z, 1.0, 0.0, 0.0); ++ this.level.addParticle(particleparam, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D); + } + +- if (flag) { ++ if (flag1) { + this.level.getProfiler().push("explosion_blocks"); +- List> list = new ArrayList<>(); ++ List> list = new ArrayList(); ++ + Util.shuffle(this.toBlow, this.level.random); ++ ObjectListIterator objectlistiterator = this.toBlow.iterator(); ++ // CraftBukkit start ++ org.bukkit.World bworld = this.level.getWorld(); ++ org.bukkit.entity.Entity explode = this.source == null ? null : this.source.getBukkitEntity(); ++ Location location = new Location(bworld, this.x, this.y, this.z); + +- for (BlockPos blockPos : this.toBlow) { +- this.level +- .getBlockState(blockPos) +- .onExplosionHit(this.level, blockPos, this, (itemStack, blockPos2) -> addOrAppendStack(list, itemStack, blockPos2)); ++ List blockList = new ObjectArrayList<>(); ++ for (int i1 = this.toBlow.size() - 1; i1 >= 0; i1--) { ++ BlockPos cpos = this.toBlow.get(i1); ++ org.bukkit.block.Block bblock = bworld.getBlockAt(cpos.getX(), cpos.getY(), cpos.getZ()); ++ if (!bblock.getType().isAir()) { ++ blockList.add(bblock); ++ } + } + +- for (Pair pair : list) { +- Block.popResource(this.level, pair.getSecond(), pair.getFirst()); ++ List bukkitBlocks; ++ ++ if (explode != null) { ++ EntityExplodeEvent event = new EntityExplodeEvent(explode, location, blockList, this.yield); ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ this.wasCanceled = event.isCancelled(); ++ bukkitBlocks = event.blockList(); ++ this.yield = event.getYield(); ++ } else { ++ BlockExplodeEvent event = new BlockExplodeEvent(location.getBlock(), blockList, this.yield); ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ this.wasCanceled = event.isCancelled(); ++ bukkitBlocks = event.blockList(); ++ this.yield = event.getYield(); + } + ++ this.toBlow.clear(); ++ ++ for (org.bukkit.block.Block bblock : bukkitBlocks) { ++ BlockPos coords = new BlockPos(bblock.getX(), bblock.getY(), bblock.getZ()); ++ toBlow.add(coords); ++ } ++ ++ if (this.wasCanceled) { ++ return; ++ } ++ // CraftBukkit end ++ objectlistiterator = this.toBlow.iterator(); ++ ++ while (objectlistiterator.hasNext()) { ++ BlockPos blockposition = (BlockPos) objectlistiterator.next(); ++ // CraftBukkit start - TNTPrimeEvent ++ IBlockData iblockdata = this.level.getBlockState(blockposition); ++ Block block = iblockdata.getBlock(); ++ if (block instanceof net.minecraft.world.level.block.TntBlock) { ++ Entity sourceEntity = source == null ? null : source; ++ BlockPos sourceBlock = sourceEntity == null ? BlockPos.containing(this.x, this.y, this.z) : null; ++ if (!CraftEventFactory.callTNTPrimeEvent(this.level, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.EXPLOSION, sourceEntity, sourceBlock)) { ++ this.level.sendBlockUpdated(blockposition, Blocks.AIR.defaultBlockState(), iblockdata, 3); // Update the block on the client ++ continue; ++ } ++ } ++ // CraftBukkit end ++ ++ this.level.getBlockState(blockposition).onExplosionHit(this.level, blockposition, this, (itemstack, blockposition1) -> { ++ addOrAppendStack(list, itemstack, blockposition1); ++ }); ++ } ++ ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Pair pair = (Pair) iterator.next(); ++ ++ Block.popResource(this.level, (BlockPos) pair.getSecond(), (ItemStack) pair.getFirst()); ++ } ++ + this.level.getProfiler().pop(); + } + + if (this.fire) { +- for (BlockPos blockPos1 : this.toBlow) { +- if (this.random.nextInt(3) == 0 +- && this.level.getBlockState(blockPos1).isAir() +- && this.level.getBlockState(blockPos1.below()).isSolidRender(this.level, blockPos1.below())) { +- this.level.setBlockAndUpdate(blockPos1, BaseFireBlock.getState(this.level, blockPos1)); ++ ObjectListIterator objectlistiterator1 = this.toBlow.iterator(); ++ ++ while (objectlistiterator1.hasNext()) { ++ BlockPos blockposition1 = (BlockPos) objectlistiterator1.next(); ++ ++ if (this.random.nextInt(3) == 0 && this.level.getBlockState(blockposition1).isAir() && this.level.getBlockState(blockposition1.below()).isSolidRender(this.level, blockposition1.below())) { ++ // CraftBukkit start - Ignition by explosion ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(this.level, blockposition1, this).isCancelled()) { ++ this.level.setBlockAndUpdate(blockposition1, BaseFireBlock.getState(this.level, blockposition1)); ++ } ++ // CraftBukkit end + } + } + } ++ + } + +- private static void addOrAppendStack(List> list, ItemStack itemStack, BlockPos blockPos) { +- for (int i = 0; i < list.size(); i++) { +- Pair pair = list.get(i); +- ItemStack itemStack1 = pair.getFirst(); +- if (ItemEntity.areMergable(itemStack1, itemStack)) { +- list.set(i, Pair.of(ItemEntity.merge(itemStack1, itemStack, 16), pair.getSecond())); +- if (itemStack.isEmpty()) { ++ private static void addOrAppendStack(List> list, ItemStack itemstack, BlockPos blockposition) { ++ if (itemstack.isEmpty()) return; // CraftBukkit - SPIGOT-5425 ++ for (int i = 0; i < list.size(); ++i) { ++ Pair pair = (Pair) list.get(i); ++ ItemStack itemstack1 = (ItemStack) pair.getFirst(); ++ ++ if (ItemEntity.areMergable(itemstack1, itemstack)) { ++ list.set(i, Pair.of(ItemEntity.merge(itemstack1, itemstack, 16), (BlockPos) pair.getSecond())); ++ if (itemstack.isEmpty()) { + return; + } + } + } + +- list.add(Pair.of(itemStack, blockPos)); ++ list.add(Pair.of(itemstack, blockposition)); + } + + public boolean interactsWithBlocks() { +- return this.blockInteraction != Explosion.BlockInteraction.KEEP; ++ return this.blockInteraction != Explosion.Effect.KEEP; + } + + public Map getHitPlayers() { +@@ -381,15 +456,23 @@ + private static LivingEntity getIndirectSourceEntityInternal(@Nullable Entity entity) { + if (entity == null) { + return null; +- } else if (entity instanceof PrimedTnt primedTnt) { +- return primedTnt.getOwner(); ++ } else if (entity instanceof PrimedTnt) { ++ PrimedTnt entitytntprimed = (PrimedTnt) entity; ++ ++ return entitytntprimed.getOwner(); + } else if (entity instanceof LivingEntity) { +- return (LivingEntity)entity; ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ return entityliving; + } else { +- if (entity instanceof Projectile projectile) { +- Entity owner = projectile.getOwner(); +- if (owner instanceof LivingEntity) { +- return (LivingEntity)owner; ++ if (entity instanceof Projectile) { ++ Projectile iprojectile = (Projectile) entity; ++ Entity entity1 = iprojectile.getOwner(); ++ ++ if (entity1 instanceof LivingEntity) { ++ LivingEntity entityliving1 = (LivingEntity) entity1; ++ ++ return entityliving1; + } + } + +@@ -415,7 +498,7 @@ + return this.toBlow; + } + +- public Explosion.BlockInteraction getBlockInteraction() { ++ public Explosion.Effect getBlockInteraction() { + return this.blockInteraction; + } + +@@ -431,10 +514,10 @@ + return this.explosionSound; + } + +- public static enum BlockInteraction { +- KEEP, +- DESTROY, +- DESTROY_WITH_DECAY, +- TRIGGER_BLOCK; ++ public static enum Effect { ++ ++ KEEP, DESTROY, DESTROY_WITH_DECAY, TRIGGER_BLOCK; ++ ++ private Effect() {} + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/GameRules.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/GameRules.java.patch new file mode 100644 index 0000000000..6318c19005 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/GameRules.java.patch @@ -0,0 +1,737 @@ +--- a/net/minecraft/world/level/GameRules.java ++++ b/net/minecraft/world/level/GameRules.java +@@ -10,8 +10,11 @@ + import com.mojang.logging.LogUtils; + import com.mojang.serialization.DynamicLike; + import java.util.Comparator; ++import java.util.Iterator; + import java.util.Map; + import java.util.Map.Entry; ++import java.util.Objects; ++import java.util.Optional; + import java.util.function.BiConsumer; + import java.util.function.Function; + import java.util.function.Supplier; +@@ -26,182 +29,100 @@ + import org.slf4j.Logger; + + public class GameRules { ++ + public static final int DEFAULT_RANDOM_TICK_SPEED = 3; + static final Logger LOGGER = LogUtils.getLogger(); +- private static final Map, GameRules.Type> GAME_RULE_TYPES = Maps.newTreeMap(Comparator.comparing(entry -> entry.id)); +- public static final GameRules.Key RULE_DOFIRETICK = register( +- "doFireTick", GameRules.Category.UPDATES, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_MOBGRIEFING = register( +- "mobGriefing", GameRules.Category.MOBS, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_KEEPINVENTORY = register( +- "keepInventory", GameRules.Category.PLAYER, GameRules.BooleanValue.create(false) +- ); +- public static final GameRules.Key RULE_DOMOBSPAWNING = register( +- "doMobSpawning", GameRules.Category.SPAWNING, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_DOMOBLOOT = register( +- "doMobLoot", GameRules.Category.DROPS, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_PROJECTILESCANBREAKBLOCKS = register( +- "projectilesCanBreakBlocks", GameRules.Category.DROPS, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_DOBLOCKDROPS = register( +- "doTileDrops", GameRules.Category.DROPS, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_DOENTITYDROPS = register( +- "doEntityDrops", GameRules.Category.DROPS, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_COMMANDBLOCKOUTPUT = register( +- "commandBlockOutput", GameRules.Category.CHAT, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_NATURAL_REGENERATION = register( +- "naturalRegeneration", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_DAYLIGHT = register( +- "doDaylightCycle", GameRules.Category.UPDATES, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_LOGADMINCOMMANDS = register( +- "logAdminCommands", GameRules.Category.CHAT, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_SHOWDEATHMESSAGES = register( +- "showDeathMessages", GameRules.Category.CHAT, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_RANDOMTICKING = register( +- "randomTickSpeed", GameRules.Category.UPDATES, GameRules.IntegerValue.create(3) +- ); +- public static final GameRules.Key RULE_SENDCOMMANDFEEDBACK = register( +- "sendCommandFeedback", GameRules.Category.CHAT, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_REDUCEDDEBUGINFO = register( +- "reducedDebugInfo", GameRules.Category.MISC, GameRules.BooleanValue.create(false, (server, value) -> { +- byte b = (byte)(value.get() ? 22 : 23); +- +- for (ServerPlayer serverPlayer : server.getPlayerList().getPlayers()) { +- serverPlayer.connection.send(new ClientboundEntityEventPacket(serverPlayer, b)); +- } +- }) +- ); +- public static final GameRules.Key RULE_SPECTATORSGENERATECHUNKS = register( +- "spectatorsGenerateChunks", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_SPAWN_RADIUS = register( +- "spawnRadius", GameRules.Category.PLAYER, GameRules.IntegerValue.create(10) +- ); +- public static final GameRules.Key RULE_DISABLE_ELYTRA_MOVEMENT_CHECK = register( +- "disableElytraMovementCheck", GameRules.Category.PLAYER, GameRules.BooleanValue.create(false) +- ); +- public static final GameRules.Key RULE_MAX_ENTITY_CRAMMING = register( +- "maxEntityCramming", GameRules.Category.MOBS, GameRules.IntegerValue.create(24) +- ); +- public static final GameRules.Key RULE_WEATHER_CYCLE = register( +- "doWeatherCycle", GameRules.Category.UPDATES, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_LIMITED_CRAFTING = register( +- "doLimitedCrafting", GameRules.Category.PLAYER, GameRules.BooleanValue.create(false, (server, value) -> { +- for (ServerPlayer serverPlayer : server.getPlayerList().getPlayers()) { +- serverPlayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LIMITED_CRAFTING, value.get() ? 1.0F : 0.0F)); +- } +- }) +- ); +- public static final GameRules.Key RULE_MAX_COMMAND_CHAIN_LENGTH = register( +- "maxCommandChainLength", GameRules.Category.MISC, GameRules.IntegerValue.create(65536) +- ); +- public static final GameRules.Key RULE_MAX_COMMAND_FORK_COUNT = register( +- "maxCommandForkCount", GameRules.Category.MISC, GameRules.IntegerValue.create(65536) +- ); +- public static final GameRules.Key RULE_COMMAND_MODIFICATION_BLOCK_LIMIT = register( +- "commandModificationBlockLimit", GameRules.Category.MISC, GameRules.IntegerValue.create(32768) +- ); +- public static final GameRules.Key RULE_ANNOUNCE_ADVANCEMENTS = register( +- "announceAdvancements", GameRules.Category.CHAT, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_DISABLE_RAIDS = register( +- "disableRaids", GameRules.Category.MOBS, GameRules.BooleanValue.create(false) +- ); +- public static final GameRules.Key RULE_DOINSOMNIA = register( +- "doInsomnia", GameRules.Category.SPAWNING, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_DO_IMMEDIATE_RESPAWN = register( +- "doImmediateRespawn", GameRules.Category.PLAYER, GameRules.BooleanValue.create(false, (minecraftServer, booleanValue) -> { +- for (ServerPlayer serverPlayer : minecraftServer.getPlayerList().getPlayers()) { +- serverPlayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.IMMEDIATE_RESPAWN, booleanValue.get() ? 1.0F : 0.0F)); +- } +- }) +- ); +- public static final GameRules.Key RULE_PLAYERS_NETHER_PORTAL_DEFAULT_DELAY = register( +- "playersNetherPortalDefaultDelay", GameRules.Category.PLAYER, GameRules.IntegerValue.create(80) +- ); +- public static final GameRules.Key RULE_PLAYERS_NETHER_PORTAL_CREATIVE_DELAY = register( +- "playersNetherPortalCreativeDelay", GameRules.Category.PLAYER, GameRules.IntegerValue.create(1) +- ); +- public static final GameRules.Key RULE_DROWNING_DAMAGE = register( +- "drowningDamage", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_FALL_DAMAGE = register( +- "fallDamage", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_FIRE_DAMAGE = register( +- "fireDamage", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_FREEZE_DAMAGE = register( +- "freezeDamage", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_DO_PATROL_SPAWNING = register( +- "doPatrolSpawning", GameRules.Category.SPAWNING, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_DO_TRADER_SPAWNING = register( +- "doTraderSpawning", GameRules.Category.SPAWNING, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_DO_WARDEN_SPAWNING = register( +- "doWardenSpawning", GameRules.Category.SPAWNING, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_FORGIVE_DEAD_PLAYERS = register( +- "forgiveDeadPlayers", GameRules.Category.MOBS, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_UNIVERSAL_ANGER = register( +- "universalAnger", GameRules.Category.MOBS, GameRules.BooleanValue.create(false) +- ); +- public static final GameRules.Key RULE_PLAYERS_SLEEPING_PERCENTAGE = register( +- "playersSleepingPercentage", GameRules.Category.PLAYER, GameRules.IntegerValue.create(100) +- ); +- public static final GameRules.Key RULE_BLOCK_EXPLOSION_DROP_DECAY = register( +- "blockExplosionDropDecay", GameRules.Category.DROPS, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_MOB_EXPLOSION_DROP_DECAY = register( +- "mobExplosionDropDecay", GameRules.Category.DROPS, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_TNT_EXPLOSION_DROP_DECAY = register( +- "tntExplosionDropDecay", GameRules.Category.DROPS, GameRules.BooleanValue.create(false) +- ); +- public static final GameRules.Key RULE_SNOW_ACCUMULATION_HEIGHT = register( +- "snowAccumulationHeight", GameRules.Category.UPDATES, GameRules.IntegerValue.create(1) +- ); +- public static final GameRules.Key RULE_WATER_SOURCE_CONVERSION = register( +- "waterSourceConversion", GameRules.Category.UPDATES, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_LAVA_SOURCE_CONVERSION = register( +- "lavaSourceConversion", GameRules.Category.UPDATES, GameRules.BooleanValue.create(false) +- ); +- public static final GameRules.Key RULE_GLOBAL_SOUND_EVENTS = register( +- "globalSoundEvents", GameRules.Category.MISC, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_DO_VINES_SPREAD = register( +- "doVinesSpread", GameRules.Category.UPDATES, GameRules.BooleanValue.create(true) +- ); +- public static final GameRules.Key RULE_ENDER_PEARLS_VANISH_ON_DEATH = register( +- "enderPearlsVanishOnDeath", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true) +- ); ++ private static final Map, GameRules.Type> GAME_RULE_TYPES = Maps.newTreeMap(Comparator.comparing((gamerules_gamerulekey) -> { ++ return gamerules_gamerulekey.id; ++ })); ++ public static final GameRules.Key RULE_DOFIRETICK = register("doFireTick", GameRules.Category.UPDATES, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_MOBGRIEFING = register("mobGriefing", GameRules.Category.MOBS, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_KEEPINVENTORY = register("keepInventory", GameRules.Category.PLAYER, GameRules.BooleanValue.create(false)); ++ public static final GameRules.Key RULE_DOMOBSPAWNING = register("doMobSpawning", GameRules.Category.SPAWNING, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_DOMOBLOOT = register("doMobLoot", GameRules.Category.DROPS, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_PROJECTILESCANBREAKBLOCKS = register("projectilesCanBreakBlocks", GameRules.Category.DROPS, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_DOBLOCKDROPS = register("doTileDrops", GameRules.Category.DROPS, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_DOENTITYDROPS = register("doEntityDrops", GameRules.Category.DROPS, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_COMMANDBLOCKOUTPUT = register("commandBlockOutput", GameRules.Category.CHAT, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_NATURAL_REGENERATION = register("naturalRegeneration", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_DAYLIGHT = register("doDaylightCycle", GameRules.Category.UPDATES, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_LOGADMINCOMMANDS = register("logAdminCommands", GameRules.Category.CHAT, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_SHOWDEATHMESSAGES = register("showDeathMessages", GameRules.Category.CHAT, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_RANDOMTICKING = register("randomTickSpeed", GameRules.Category.UPDATES, GameRules.IntegerValue.create(3)); ++ public static final GameRules.Key RULE_SENDCOMMANDFEEDBACK = register("sendCommandFeedback", GameRules.Category.CHAT, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_REDUCEDDEBUGINFO = register("reducedDebugInfo", GameRules.Category.MISC, GameRules.BooleanValue.create(false, (minecraftserver, gamerules_gameruleboolean) -> { ++ int i = gamerules_gameruleboolean.get() ? 22 : 23; ++ Iterator iterator = minecraftserver.getPlayerList().getPlayers().iterator(); ++ ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ entityplayer.connection.send(new ClientboundEntityEventPacket(entityplayer, (byte) i)); ++ } ++ ++ })); ++ public static final GameRules.Key RULE_SPECTATORSGENERATECHUNKS = register("spectatorsGenerateChunks", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_SPAWN_RADIUS = register("spawnRadius", GameRules.Category.PLAYER, GameRules.IntegerValue.create(10)); ++ public static final GameRules.Key RULE_DISABLE_ELYTRA_MOVEMENT_CHECK = register("disableElytraMovementCheck", GameRules.Category.PLAYER, GameRules.BooleanValue.create(false)); ++ public static final GameRules.Key RULE_MAX_ENTITY_CRAMMING = register("maxEntityCramming", GameRules.Category.MOBS, GameRules.IntegerValue.create(24)); ++ public static final GameRules.Key RULE_WEATHER_CYCLE = register("doWeatherCycle", GameRules.Category.UPDATES, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_LIMITED_CRAFTING = register("doLimitedCrafting", GameRules.Category.PLAYER, GameRules.BooleanValue.create(false, (minecraftserver, gamerules_gameruleboolean) -> { ++ Iterator iterator = minecraftserver.getPlayerList().getPlayers().iterator(); ++ ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ entityplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LIMITED_CRAFTING, gamerules_gameruleboolean.get() ? 1.0F : 0.0F)); ++ } ++ ++ })); ++ public static final GameRules.Key RULE_MAX_COMMAND_CHAIN_LENGTH = register("maxCommandChainLength", GameRules.Category.MISC, GameRules.IntegerValue.create(65536)); ++ public static final GameRules.Key RULE_MAX_COMMAND_FORK_COUNT = register("maxCommandForkCount", GameRules.Category.MISC, GameRules.IntegerValue.create(65536)); ++ public static final GameRules.Key RULE_COMMAND_MODIFICATION_BLOCK_LIMIT = register("commandModificationBlockLimit", GameRules.Category.MISC, GameRules.IntegerValue.create(32768)); ++ public static final GameRules.Key RULE_ANNOUNCE_ADVANCEMENTS = register("announceAdvancements", GameRules.Category.CHAT, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_DISABLE_RAIDS = register("disableRaids", GameRules.Category.MOBS, GameRules.BooleanValue.create(false)); ++ public static final GameRules.Key RULE_DOINSOMNIA = register("doInsomnia", GameRules.Category.SPAWNING, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_DO_IMMEDIATE_RESPAWN = register("doImmediateRespawn", GameRules.Category.PLAYER, GameRules.BooleanValue.create(false, (minecraftserver, gamerules_gameruleboolean) -> { ++ Iterator iterator = minecraftserver.getPlayerList().getPlayers().iterator(); ++ ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ entityplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.IMMEDIATE_RESPAWN, gamerules_gameruleboolean.get() ? 1.0F : 0.0F)); ++ } ++ ++ })); ++ public static final GameRules.Key RULE_PLAYERS_NETHER_PORTAL_DEFAULT_DELAY = register("playersNetherPortalDefaultDelay", GameRules.Category.PLAYER, GameRules.IntegerValue.create(80)); ++ public static final GameRules.Key RULE_PLAYERS_NETHER_PORTAL_CREATIVE_DELAY = register("playersNetherPortalCreativeDelay", GameRules.Category.PLAYER, GameRules.IntegerValue.create(1)); ++ public static final GameRules.Key RULE_DROWNING_DAMAGE = register("drowningDamage", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_FALL_DAMAGE = register("fallDamage", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_FIRE_DAMAGE = register("fireDamage", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_FREEZE_DAMAGE = register("freezeDamage", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_DO_PATROL_SPAWNING = register("doPatrolSpawning", GameRules.Category.SPAWNING, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_DO_TRADER_SPAWNING = register("doTraderSpawning", GameRules.Category.SPAWNING, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_DO_WARDEN_SPAWNING = register("doWardenSpawning", GameRules.Category.SPAWNING, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_FORGIVE_DEAD_PLAYERS = register("forgiveDeadPlayers", GameRules.Category.MOBS, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_UNIVERSAL_ANGER = register("universalAnger", GameRules.Category.MOBS, GameRules.BooleanValue.create(false)); ++ public static final GameRules.Key RULE_PLAYERS_SLEEPING_PERCENTAGE = register("playersSleepingPercentage", GameRules.Category.PLAYER, GameRules.IntegerValue.create(100)); ++ public static final GameRules.Key RULE_BLOCK_EXPLOSION_DROP_DECAY = register("blockExplosionDropDecay", GameRules.Category.DROPS, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_MOB_EXPLOSION_DROP_DECAY = register("mobExplosionDropDecay", GameRules.Category.DROPS, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_TNT_EXPLOSION_DROP_DECAY = register("tntExplosionDropDecay", GameRules.Category.DROPS, GameRules.BooleanValue.create(false)); ++ public static final GameRules.Key RULE_SNOW_ACCUMULATION_HEIGHT = register("snowAccumulationHeight", GameRules.Category.UPDATES, GameRules.IntegerValue.create(1)); ++ public static final GameRules.Key RULE_WATER_SOURCE_CONVERSION = register("waterSourceConversion", GameRules.Category.UPDATES, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_LAVA_SOURCE_CONVERSION = register("lavaSourceConversion", GameRules.Category.UPDATES, GameRules.BooleanValue.create(false)); ++ public static final GameRules.Key RULE_GLOBAL_SOUND_EVENTS = register("globalSoundEvents", GameRules.Category.MISC, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_DO_VINES_SPREAD = register("doVinesSpread", GameRules.Category.UPDATES, GameRules.BooleanValue.create(true)); ++ public static final GameRules.Key RULE_ENDER_PEARLS_VANISH_ON_DEATH = register("enderPearlsVanishOnDeath", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true)); + private final Map, GameRules.Value> rules; + + private static > GameRules.Key register(String name, GameRules.Category category, GameRules.Type type) { +- GameRules.Key key = new GameRules.Key<>(name, category); +- GameRules.Type type1 = GAME_RULE_TYPES.put(key, type); +- if (type1 != null) { ++ GameRules.Key gamerules_gamerulekey = new GameRules.Key<>(name, category); ++ GameRules.Type gamerules_gameruledefinition1 = (GameRules.Type) GameRules.GAME_RULE_TYPES.put(gamerules_gamerulekey, type); ++ ++ if (gamerules_gameruledefinition1 != null) { + throw new IllegalStateException("Duplicate game rule registration for " + name); + } else { +- return key; ++ return gamerules_gamerulekey; + } + } + +@@ -211,7 +132,9 @@ + } + + public GameRules() { +- this.rules = GAME_RULE_TYPES.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, entry -> entry.getValue().createRule())); ++ this.rules = (Map) GameRules.GAME_RULE_TYPES.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry) -> { ++ return ((GameRules.Type) entry.getValue()).createRule(); ++ })); + } + + private GameRules(Map, GameRules.Value> rules) { +@@ -219,60 +142,201 @@ + } + + public > T getRule(GameRules.Key key) { +- return (T)this.rules.get(key); ++ return (T) this.rules.get(key); // CraftBukkit - decompile error + } + + public CompoundTag createTag() { +- CompoundTag compoundTag = new CompoundTag(); +- this.rules.forEach((key, value) -> compoundTag.putString(key.id, value.serialize())); +- return compoundTag; ++ CompoundTag nbttagcompound = new CompoundTag(); ++ ++ this.rules.forEach((gamerules_gamerulekey, gamerules_gamerulevalue) -> { ++ nbttagcompound.putString(gamerules_gamerulekey.id, gamerules_gamerulevalue.serialize()); ++ }); ++ return nbttagcompound; + } + + private void loadFromTag(DynamicLike dynamic) { +- this.rules.forEach((key, value) -> dynamic.get(key.id).asString().result().ifPresent(value::deserialize)); ++ this.rules.forEach((gamerules_gamerulekey, gamerules_gamerulevalue) -> { ++ Optional optional = dynamic.get(gamerules_gamerulekey.id).asString().result(); // CraftBukkit - decompile error ++ ++ Objects.requireNonNull(gamerules_gamerulevalue); ++ optional.ifPresent(gamerules_gamerulevalue::deserialize); ++ }); + } + + public GameRules copy() { +- return new GameRules(this.rules.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, entry -> entry.getValue().copy()))); ++ return new GameRules((Map) this.rules.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry) -> { ++ return ((GameRules.Value) entry.getValue()).copy(); ++ }))); + } + + public static void visitGameRuleTypes(GameRules.GameRuleTypeVisitor visitor) { +- GAME_RULE_TYPES.forEach((key, type) -> callVisitorCap(visitor, (GameRules.Key)key, (GameRules.Type)type)); ++ GameRules.GAME_RULE_TYPES.forEach((gamerules_gamerulekey, gamerules_gameruledefinition) -> { ++ callVisitorCap(visitor, gamerules_gamerulekey, gamerules_gameruledefinition); ++ }); + } + + private static > void callVisitorCap(GameRules.GameRuleTypeVisitor visitor, GameRules.Key key, GameRules.Type type) { +- visitor.visit((GameRules.Key) key, (GameRules.Type) type); +- ((GameRules.Type) type).callVisitor(visitor, (GameRules.Key) key); ++ visitor.visit((GameRules.Key) key, (GameRules.Type) type); // CraftBukkit - decompile error ++ ((GameRules.Type) type).callVisitor(visitor, (GameRules.Key) key); // CraftBukkit - decompile error + } + + public void assignFrom(GameRules rules, @Nullable MinecraftServer server) { +- rules.rules.keySet().forEach(key -> this.assignCap((GameRules.Key)key, rules, server)); ++ rules.rules.keySet().forEach((gamerules_gamerulekey) -> { ++ this.assignCap(gamerules_gamerulekey, rules, server); ++ }); + } + + private > void assignCap(GameRules.Key key, GameRules rules, @Nullable MinecraftServer server) { +- T rule = rules.getRule(key); +- this.getRule(key).setFrom(rule, server); ++ T t0 = rules.getRule(key); ++ ++ this.getRule(key).setFrom(t0, server); + } + + public boolean getBoolean(GameRules.Key key) { +- return this.getRule(key).get(); ++ return ((GameRules.BooleanValue) this.getRule(key)).get(); + } + + public int getInt(GameRules.Key key) { +- return this.getRule(key).get(); ++ return ((GameRules.IntegerValue) this.getRule(key)).get(); + } + ++ public static final class Key> { ++ ++ final String id; ++ private final GameRules.Category category; ++ ++ public Key(String id, GameRules.Category category) { ++ this.id = id; ++ this.category = category; ++ } ++ ++ public String toString() { ++ return this.id; ++ } ++ ++ public boolean equals(Object object) { ++ return this == object ? true : object instanceof GameRules.Key && ((GameRules.Key) object).id.equals(this.id); ++ } ++ ++ public int hashCode() { ++ return this.id.hashCode(); ++ } ++ ++ public String getId() { ++ return this.id; ++ } ++ ++ public String getDescriptionId() { ++ return "gamerule." + this.id; ++ } ++ ++ public GameRules.Category getCategory() { ++ return this.category; ++ } ++ } ++ ++ public static enum Category { ++ ++ PLAYER("gamerule.category.player"), MOBS("gamerule.category.mobs"), SPAWNING("gamerule.category.spawning"), DROPS("gamerule.category.drops"), UPDATES("gamerule.category.updates"), CHAT("gamerule.category.chat"), MISC("gamerule.category.misc"); ++ ++ private final String descriptionId; ++ ++ private Category(String s) { ++ this.descriptionId = s; ++ } ++ ++ public String getDescriptionId() { ++ return this.descriptionId; ++ } ++ } ++ ++ public static class Type> { ++ ++ private final Supplier> argument; ++ private final Function, T> constructor; ++ final BiConsumer callback; ++ private final GameRules.VisitorCaller visitorCaller; ++ ++ Type(Supplier> argument, Function, T> constructor, BiConsumer callback, GameRules.VisitorCaller visitorCaller) { ++ this.argument = argument; ++ this.constructor = constructor; ++ this.callback = callback; ++ this.visitorCaller = visitorCaller; ++ } ++ ++ public RequiredArgumentBuilder createArgument(String name) { ++ return Commands.argument(name, (ArgumentType) this.argument.get()); ++ } ++ ++ public T createRule() { ++ return this.constructor.apply(this); // CraftBukkit - decompile error ++ } ++ ++ public void callVisitor(GameRules.GameRuleTypeVisitor visitor, GameRules.Key key) { ++ this.visitorCaller.call(visitor, key, this); ++ } ++ } ++ ++ public abstract static class Value> { ++ ++ protected final GameRules.Type type; ++ ++ public Value(GameRules.Type type) { ++ this.type = type; ++ } ++ ++ protected abstract void updateFromArgument(CommandContext context, String paramName); ++ ++ public void setFromArgument(CommandContext context, String paramName) { ++ this.updateFromArgument(context, paramName); ++ this.onChanged(((CommandSourceStack) context.getSource()).getServer()); ++ } ++ ++ public void onChanged(@Nullable MinecraftServer server) { ++ if (server != null) { ++ this.type.callback.accept(server, this.getSelf()); ++ } ++ ++ } ++ ++ public abstract void deserialize(String value); // PAIL - private->public ++ ++ public abstract String serialize(); ++ ++ public String toString() { ++ return this.serialize(); ++ } ++ ++ public abstract int getCommandResult(); ++ ++ protected abstract T getSelf(); ++ ++ protected abstract T copy(); ++ ++ public abstract void setFrom(T value, @Nullable MinecraftServer server); ++ } ++ ++ public interface GameRuleTypeVisitor { ++ ++ default > void visit(GameRules.Key key, GameRules.Type type) {} ++ ++ default void visitBoolean(GameRules.Key key, GameRules.Type type) {} ++ ++ default void visitInteger(GameRules.Key key, GameRules.Type type) {} ++ } ++ + public static class BooleanValue extends GameRules.Value { ++ + private boolean value; + + static GameRules.Type create(boolean defaultValue, BiConsumer changeListener) { +- return new GameRules.Type<>( +- BoolArgumentType::bool, type -> new GameRules.BooleanValue(type, defaultValue), changeListener, GameRules.GameRuleTypeVisitor::visitBoolean +- ); ++ return new GameRules.Type<>(BoolArgumentType::bool, (gamerules_gameruledefinition) -> { ++ return new GameRules.BooleanValue(gamerules_gameruledefinition, defaultValue); ++ }, changeListener, GameRules.GameRuleTypeVisitor::visitBoolean); + } + + static GameRules.Type create(boolean defaultValue) { +- return create(defaultValue, (key, value) -> { ++ return create(defaultValue, (minecraftserver, gamerules_gameruleboolean) -> { + }); + } + +@@ -301,7 +365,7 @@ + } + + @Override +- protected void deserialize(String value) { ++ public void deserialize(String value) { // PAIL - protected->public + this.value = Boolean.parseBoolean(value); + } + +@@ -320,58 +384,24 @@ + return new GameRules.BooleanValue(this.type, this.value); + } + +- @Override + public void setFrom(GameRules.BooleanValue value, @Nullable MinecraftServer server) { + this.value = value.value; + this.onChanged(server); + } + } + +- public static enum Category { +- PLAYER("gamerule.category.player"), +- MOBS("gamerule.category.mobs"), +- SPAWNING("gamerule.category.spawning"), +- DROPS("gamerule.category.drops"), +- UPDATES("gamerule.category.updates"), +- CHAT("gamerule.category.chat"), +- MISC("gamerule.category.misc"); +- +- private final String descriptionId; +- +- private Category(String descriptionId) { +- this.descriptionId = descriptionId; +- } +- +- public String getDescriptionId() { +- return this.descriptionId; +- } +- } +- +- public interface GameRuleTypeVisitor { +- default > void visit(GameRules.Key key, GameRules.Type type) { +- } +- +- default void visitBoolean(GameRules.Key key, GameRules.Type type) { +- } +- +- default void visitInteger(GameRules.Key key, GameRules.Type type) { +- } +- } +- + public static class IntegerValue extends GameRules.Value { ++ + private int value; + + private static GameRules.Type create(int defaultValue, BiConsumer changeListener) { +- return new GameRules.Type<>( +- IntegerArgumentType::integer, +- type -> new GameRules.IntegerValue(type, defaultValue), +- changeListener, +- GameRules.GameRuleTypeVisitor::visitInteger +- ); ++ return new GameRules.Type<>(IntegerArgumentType::integer, (gamerules_gameruledefinition) -> { ++ return new GameRules.IntegerValue(gamerules_gameruledefinition, defaultValue); ++ }, changeListener, GameRules.GameRuleTypeVisitor::visitInteger); + } + + static GameRules.Type create(int defaultValue) { +- return create(defaultValue, (key, value) -> { ++ return create(defaultValue, (minecraftserver, gamerules_gameruleint) -> { + }); + } + +@@ -400,7 +430,7 @@ + } + + @Override +- protected void deserialize(String value) { ++ public void deserialize(String value) { // PAIL - protected->public + this.value = safeParse(value); + } + +@@ -408,7 +438,7 @@ + try { + this.value = Integer.parseInt(name); + return true; +- } catch (NumberFormatException var3) { ++ } catch (NumberFormatException numberformatexception) { + return false; + } + } +@@ -417,7 +447,7 @@ + if (!strValue.isEmpty()) { + try { + return Integer.parseInt(strValue); +- } catch (NumberFormatException var2) { ++ } catch (NumberFormatException numberformatexception) { + GameRules.LOGGER.warn("Failed to parse integer {}", strValue); + } + } +@@ -440,120 +470,14 @@ + return new GameRules.IntegerValue(this.type, this.value); + } + +- @Override + public void setFrom(GameRules.IntegerValue value, @Nullable MinecraftServer server) { + this.value = value.value; + this.onChanged(server); + } + } + +- public static final class Key> { +- final String id; +- private final GameRules.Category category; ++ private interface VisitorCaller> { + +- public Key(String id, GameRules.Category category) { +- this.id = id; +- this.category = category; +- } +- +- @Override +- public String toString() { +- return this.id; +- } +- +- @Override +- public boolean equals(Object other) { +- return this == other || other instanceof GameRules.Key && ((GameRules.Key)other).id.equals(this.id); +- } +- +- @Override +- public int hashCode() { +- return this.id.hashCode(); +- } +- +- public String getId() { +- return this.id; +- } +- +- public String getDescriptionId() { +- return "gamerule." + this.id; +- } +- +- public GameRules.Category getCategory() { +- return this.category; +- } +- } +- +- public static class Type> { +- private final Supplier> argument; +- private final Function, T> constructor; +- final BiConsumer callback; +- private final GameRules.VisitorCaller visitorCaller; +- +- Type( +- Supplier> argument, +- Function, T> constructor, +- BiConsumer callback, +- GameRules.VisitorCaller visitorCaller +- ) { +- this.argument = argument; +- this.constructor = constructor; +- this.callback = callback; +- this.visitorCaller = visitorCaller; +- } +- +- public RequiredArgumentBuilder createArgument(String name) { +- return Commands.argument(name, this.argument.get()); +- } +- +- public T createRule() { +- return this.constructor.apply(this); +- } +- +- public void callVisitor(GameRules.GameRuleTypeVisitor visitor, GameRules.Key key) { +- this.visitorCaller.call(visitor, key, this); +- } +- } +- +- public abstract static class Value> { +- protected final GameRules.Type type; +- +- public Value(GameRules.Type type) { +- this.type = type; +- } +- +- protected abstract void updateFromArgument(CommandContext context, String paramName); +- +- public void setFromArgument(CommandContext context, String paramName) { +- this.updateFromArgument(context, paramName); +- this.onChanged(context.getSource().getServer()); +- } +- +- protected void onChanged(@Nullable MinecraftServer server) { +- if (server != null) { +- this.type.callback.accept(server, this.getSelf()); +- } +- } +- +- protected abstract void deserialize(String value); +- +- public abstract String serialize(); +- +- @Override +- public String toString() { +- return this.serialize(); +- } +- +- public abstract int getCommandResult(); +- +- protected abstract T getSelf(); +- +- protected abstract T copy(); +- +- public abstract void setFrom(T value, @Nullable MinecraftServer server); +- } +- +- interface VisitorCaller> { + void call(GameRules.GameRuleTypeVisitor visitor, GameRules.Key key, GameRules.Type type); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/Level.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/Level.java.patch new file mode 100644 index 0000000000..ffd751fa28 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/Level.java.patch @@ -0,0 +1,1360 @@ +--- a/net/minecraft/world/level/Level.java ++++ b/net/minecraft/world/level/Level.java +@@ -5,6 +5,7 @@ + import java.io.IOException; + import java.util.Iterator; + import java.util.List; ++import java.util.Objects; + import java.util.function.Consumer; + import java.util.function.Predicate; + import java.util.function.Supplier; +@@ -27,6 +28,7 @@ + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.FullChunkStatus; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; +@@ -41,6 +43,7 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.boss.EnderDragonPart; + import net.minecraft.world.entity.boss.enderdragon.EnderDragon; ++import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.crafting.RecipeManager; +@@ -51,12 +54,15 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.TickingBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.border.BorderChangeListener; + import net.minecraft.world.level.border.WorldBorder; + import net.minecraft.world.level.chunk.ChunkAccess; ++import net.minecraft.world.level.chunk.ChunkSource; + import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.level.dimension.DimensionType; ++import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.entity.EntityTypeTest; + import net.minecraft.world.level.entity.LevelEntityGetter; + import net.minecraft.world.level.gameevent.GameEvent; +@@ -73,7 +79,29 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.scores.Scoreboard; + ++// CraftBukkit start ++import java.util.HashMap; ++import java.util.Map; ++import net.minecraft.network.protocol.game.ClientboundSetBorderCenterPacket; ++import net.minecraft.network.protocol.game.ClientboundSetBorderLerpSizePacket; ++import net.minecraft.network.protocol.game.ClientboundSetBorderSizePacket; ++import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDelayPacket; ++import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDistancePacket; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.block.CapturedBlockState; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.craftbukkit.util.CraftSpawnCategory; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.entity.SpawnCategory; ++import org.bukkit.event.block.BlockPhysicsEvent; ++import org.bukkit.event.world.GenericGameEvent; ++// CraftBukkit end ++ + public abstract class Level implements LevelAccessor, AutoCloseable { ++ + public static final Codec> RESOURCE_KEY_CODEC = ResourceKey.codec(Registries.DIMENSION); + public static final ResourceKey OVERWORLD = ResourceKey.create(Registries.DIMENSION, new ResourceLocation("overworld")); + public static final ResourceKey NETHER = ResourceKey.create(Registries.DIMENSION, new ResourceLocation("the_nether")); +@@ -89,21 +117,22 @@ + protected final NeighborUpdater neighborUpdater; + private final List pendingBlockEntityTickers = Lists.newArrayList(); + private boolean tickingBlockEntities; +- private final Thread thread; ++ public final Thread thread; + private final boolean isDebug; + private int skyDarken; + protected int randValue = RandomSource.create().nextInt(); + protected final int addend = 1013904223; + protected float oRainLevel; +- protected float rainLevel; ++ public float rainLevel; + protected float oThunderLevel; +- protected float thunderLevel; ++ public float thunderLevel; + public final RandomSource random = RandomSource.create(); ++ /** @deprecated */ + @Deprecated + private final RandomSource threadSafeRandom = RandomSource.createThreadSafe(); + private final ResourceKey dimensionTypeId; + private final Holder dimensionTypeRegistration; +- protected final WritableLevelData levelData; ++ public final WritableLevelData levelData; + private final Supplier profiler; + public final boolean isClientSide; + private final WorldBorder worldBorder; +@@ -113,35 +142,63 @@ + private final DamageSources damageSources; + private long subTickCount; + +- protected Level( +- WritableLevelData levelData, +- ResourceKey dimension, +- RegistryAccess registryAccess, +- Holder dimensionTypeRegistration, +- Supplier profiler, +- boolean isClientSide, +- boolean isDebug, +- long biomeZoomSeed, +- int maxChainedNeighborUpdates +- ) { +- this.profiler = profiler; +- this.levelData = levelData; +- this.dimensionTypeRegistration = dimensionTypeRegistration; +- this.dimensionTypeId = dimensionTypeRegistration.unwrapKey() +- .orElseThrow(() -> new IllegalArgumentException("Dimension must be registered, got " + dimensionTypeRegistration)); +- final DimensionType dimensionType = dimensionTypeRegistration.value(); +- this.dimension = dimension; +- this.isClientSide = isClientSide; +- if (dimensionType.coordinateScale() != 1.0) { ++ // CraftBukkit start Added the following ++ private final CraftWorld world; ++ public boolean pvpMode; ++ public boolean keepSpawnInMemory = true; ++ public org.bukkit.generator.ChunkGenerator generator; ++ ++ public boolean preventPoiUpdated = false; // CraftBukkit - SPIGOT-5710 ++ public boolean captureBlockStates = false; ++ public boolean captureTreeGeneration = false; ++ public Map capturedBlockStates = new java.util.LinkedHashMap<>(); ++ public Map capturedTileEntities = new HashMap<>(); ++ public List captureDrops; ++ public final it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap ticksPerSpawnCategory = new it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<>(); ++ public boolean populating; ++ ++ public CraftWorld getWorld() { ++ return this.world; ++ } ++ ++ public CraftServer getCraftServer() { ++ return (CraftServer) Bukkit.getServer(); ++ } ++ ++ public abstract ResourceKey getTypeKey(); ++ ++ protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env) { ++ this.generator = gen; ++ this.world = new CraftWorld((ServerLevel) this, gen, biomeProvider, env); ++ ++ // CraftBukkit Ticks things ++ for (SpawnCategory spawnCategory : SpawnCategory.values()) { ++ if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { ++ this.ticksPerSpawnCategory.put(spawnCategory, (long) this.getCraftServer().getTicksPerSpawns(spawnCategory)); ++ } ++ } ++ ++ // CraftBukkit end ++ this.profiler = supplier; ++ this.levelData = worlddatamutable; ++ this.dimensionTypeRegistration = holder; ++ this.dimensionTypeId = (ResourceKey) holder.unwrapKey().orElseThrow(() -> { ++ return new IllegalArgumentException("Dimension must be registered, got " + holder); ++ }); ++ final DimensionType dimensionmanager = (DimensionType) holder.value(); ++ ++ this.dimension = resourcekey; ++ this.isClientSide = flag; ++ if (dimensionmanager.coordinateScale() != 1.0D) { + this.worldBorder = new WorldBorder() { + @Override + public double getCenterX() { +- return super.getCenterX() / dimensionType.coordinateScale(); ++ return super.getCenterX(); // CraftBukkit + } + + @Override + public double getCenterZ() { +- return super.getCenterZ() / dimensionType.coordinateScale(); ++ return super.getCenterZ(); // CraftBukkit + } + }; + } else { +@@ -149,11 +206,47 @@ + } + + this.thread = Thread.currentThread(); +- this.biomeManager = new BiomeManager(this, biomeZoomSeed); +- this.isDebug = isDebug; +- this.neighborUpdater = new CollectingNeighborUpdater(this, maxChainedNeighborUpdates); +- this.registryAccess = registryAccess; +- this.damageSources = new DamageSources(registryAccess); ++ this.biomeManager = new BiomeManager(this, i); ++ this.isDebug = flag1; ++ this.neighborUpdater = new CollectingNeighborUpdater(this, j); ++ this.registryAccess = iregistrycustom; ++ this.damageSources = new DamageSources(iregistrycustom); ++ // CraftBukkit start ++ getWorldBorder().world = (ServerLevel) this; ++ // From PlayerList.setPlayerFileData ++ getWorldBorder().addListener(new BorderChangeListener() { ++ @Override ++ public void onBorderSizeSet(WorldBorder border, double size) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderSizePacket(border), border.world); ++ } ++ ++ @Override ++ public void onBorderSizeLerping(WorldBorder border, double oldSize, double d1, long newSize) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderLerpSizePacket(border), border.world); ++ } ++ ++ @Override ++ public void onBorderCenterSet(WorldBorder border, double x, double d1) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderCenterPacket(border), border.world); ++ } ++ ++ @Override ++ public void onBorderSetWarningTime(WorldBorder border, int warningTime) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderWarningDelayPacket(border), border.world); ++ } ++ ++ @Override ++ public void onBorderSetWarningBlocks(WorldBorder border, int warningBlocks) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderWarningDistancePacket(border), border.world); ++ } ++ ++ @Override ++ public void onBorderSetDamagePerBlock(WorldBorder border, double damagePerBlock) {} ++ ++ @Override ++ public void onBorderSetDamageSafeZOne(WorldBorder border, double damageSafeZone) {} ++ }); ++ // CraftBukkit end + } + + @Override +@@ -189,149 +282,234 @@ + + @Override + public LevelChunk getChunk(int chunkX, int chunkZ) { +- return (LevelChunk)this.getChunk(chunkX, chunkZ, ChunkStatus.FULL); ++ return (LevelChunk) this.getChunk(chunkX, chunkZ, ChunkStatus.FULL); + } + + @Nullable + @Override + public ChunkAccess getChunk(int x, int z, ChunkStatus requiredStatus, boolean nonnull) { +- ChunkAccess chunk = this.getChunkSource().getChunk(x, z, requiredStatus, nonnull); +- if (chunk == null && nonnull) { ++ ChunkAccess ichunkaccess = this.getChunkSource().getChunk(x, z, requiredStatus, nonnull); ++ ++ if (ichunkaccess == null && nonnull) { + throw new IllegalStateException("Should always be able to create a chunk!"); + } else { +- return chunk; ++ return ichunkaccess; + } + } + + @Override +- public boolean setBlock(BlockPos pos, BlockState newState, int flags) { ++ public boolean setBlock(BlockPos pos, IBlockData newState, int flags) { + return this.setBlock(pos, newState, flags, 512); + } + + @Override +- public boolean setBlock(BlockPos pos, BlockState state, int flags, int recursionLeft) { ++ public boolean setBlock(BlockPos pos, IBlockData state, int flags, int recursionLeft) { ++ // CraftBukkit start - tree generation ++ if (this.captureTreeGeneration) { ++ CapturedBlockState blockstate = capturedBlockStates.get(pos); ++ if (blockstate == null) { ++ blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags); ++ this.capturedBlockStates.put(pos.immutable(), blockstate); ++ } ++ blockstate.setData(state); ++ return true; ++ } ++ // CraftBukkit end + if (this.isOutsideBuildHeight(pos)) { + return false; + } else if (!this.isClientSide && this.isDebug()) { + return false; + } else { +- LevelChunk chunkAt = this.getChunkAt(pos); ++ LevelChunk chunk = this.getChunkAt(pos); + Block block = state.getBlock(); +- BlockState blockState = chunkAt.setBlockState(pos, state, (flags & 64) != 0); +- if (blockState == null) { ++ ++ // CraftBukkit start - capture blockstates ++ boolean captured = false; ++ if (this.captureBlockStates && !this.capturedBlockStates.containsKey(pos)) { ++ CapturedBlockState blockstate = CapturedBlockState.getBlockState(this, pos, flags); ++ this.capturedBlockStates.put(pos.immutable(), blockstate); ++ captured = true; ++ } ++ // CraftBukkit end ++ ++ IBlockData iblockdata1 = chunk.setBlockState(pos, state, (flags & 64) != 0, (flags & 1024) == 0); // CraftBukkit custom NO_PLACE flag ++ ++ if (iblockdata1 == null) { ++ // CraftBukkit start - remove blockstate if failed (or the same) ++ if (this.captureBlockStates && captured) { ++ this.capturedBlockStates.remove(pos); ++ } ++ // CraftBukkit end + return false; + } else { +- BlockState blockState1 = this.getBlockState(pos); +- if (blockState1 == state) { +- if (blockState != blockState1) { +- this.setBlocksDirty(pos, blockState, blockState1); ++ IBlockData iblockdata2 = this.getBlockState(pos); ++ ++ /* ++ if (iblockdata2 == iblockdata) { ++ if (iblockdata1 != iblockdata2) { ++ this.setBlocksDirty(blockposition, iblockdata1, iblockdata2); + } + +- if ((flags & 2) != 0 +- && (!this.isClientSide || (flags & 4) == 0) +- && (this.isClientSide || chunkAt.getFullStatus() != null && chunkAt.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING))) { +- this.sendBlockUpdated(pos, blockState, state, flags); ++ if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk.getFullStatus() != null && chunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING))) { ++ this.sendBlockUpdated(blockposition, iblockdata1, iblockdata, i); + } + +- if ((flags & 1) != 0) { +- this.blockUpdated(pos, blockState.getBlock()); +- if (!this.isClientSide && state.hasAnalogOutputSignal()) { +- this.updateNeighbourForOutputSignal(pos, block); ++ if ((i & 1) != 0) { ++ this.blockUpdated(blockposition, iblockdata1.getBlock()); ++ if (!this.isClientSide && iblockdata.hasAnalogOutputSignal()) { ++ this.updateNeighbourForOutputSignal(blockposition, block); + } + } + +- if ((flags & 16) == 0 && recursionLeft > 0) { +- int i = flags & -34; +- blockState.updateIndirectNeighbourShapes(this, pos, i, recursionLeft - 1); +- state.updateNeighbourShapes(this, pos, i, recursionLeft - 1); +- state.updateIndirectNeighbourShapes(this, pos, i, recursionLeft - 1); ++ if ((i & 16) == 0 && j > 0) { ++ int k = i & -34; ++ ++ iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); ++ iblockdata.updateNeighbourShapes(this, blockposition, k, j - 1); ++ iblockdata.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); + } + +- this.onBlockStateChange(pos, blockState, blockState1); ++ this.onBlockStateChange(blockposition, iblockdata1, iblockdata2); + } ++ */ + ++ // CraftBukkit start ++ if (!this.captureBlockStates) { // Don't notify clients or update physics while capturing blockstates ++ // Modularize client and physic updates ++ notifyAndUpdatePhysics(pos, chunk, iblockdata1, state, iblockdata2, flags, recursionLeft); ++ } ++ // CraftBukkit end ++ + return true; + } + } + } + +- public void onBlockStateChange(BlockPos pos, BlockState blockState, BlockState newState) { ++ // CraftBukkit start - Split off from above in order to directly send client and physic updates ++ public void notifyAndUpdatePhysics(BlockPos blockposition, LevelChunk chunk, IBlockData oldBlock, IBlockData newBlock, IBlockData actualBlock, int i, int j) { ++ IBlockData iblockdata = newBlock; ++ IBlockData iblockdata1 = oldBlock; ++ IBlockData iblockdata2 = actualBlock; ++ if (iblockdata2 == iblockdata) { ++ if (iblockdata1 != iblockdata2) { ++ this.setBlocksDirty(blockposition, iblockdata1, iblockdata2); ++ } ++ ++ if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getFullStatus() != null && chunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement ++ this.sendBlockUpdated(blockposition, iblockdata1, iblockdata, i); ++ } ++ ++ if ((i & 1) != 0) { ++ this.blockUpdated(blockposition, iblockdata1.getBlock()); ++ if (!this.isClientSide && iblockdata.hasAnalogOutputSignal()) { ++ this.updateNeighbourForOutputSignal(blockposition, newBlock.getBlock()); ++ } ++ } ++ ++ if ((i & 16) == 0 && j > 0) { ++ int k = i & -34; ++ ++ // CraftBukkit start ++ iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam ++ CraftWorld world = ((ServerLevel) this).getWorld(); ++ if (world != null) { ++ BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata)); ++ this.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ iblockdata.updateNeighbourShapes(this, blockposition, k, j - 1); ++ iblockdata.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); ++ } ++ ++ // CraftBukkit start - SPIGOT-5710 ++ if (!preventPoiUpdated) { ++ this.onBlockStateChange(blockposition, iblockdata1, iblockdata2); ++ } ++ // CraftBukkit end ++ } + } ++ // CraftBukkit end + ++ public void onBlockStateChange(BlockPos pos, IBlockData blockState, IBlockData newState) {} ++ + @Override + public boolean removeBlock(BlockPos pos, boolean isMoving) { +- FluidState fluidState = this.getFluidState(pos); +- return this.setBlock(pos, fluidState.createLegacyBlock(), 3 | (isMoving ? 64 : 0)); ++ FluidState fluid = this.getFluidState(pos); ++ ++ return this.setBlock(pos, fluid.createLegacyBlock(), 3 | (isMoving ? 64 : 0)); + } + + @Override + public boolean destroyBlock(BlockPos pos, boolean dropBlock, @Nullable Entity entity, int recursionLeft) { +- BlockState blockState = this.getBlockState(pos); +- if (blockState.isAir()) { ++ IBlockData iblockdata = this.getBlockState(pos); ++ ++ if (iblockdata.isAir()) { + return false; + } else { +- FluidState fluidState = this.getFluidState(pos); +- if (!(blockState.getBlock() instanceof BaseFireBlock)) { +- this.levelEvent(2001, pos, Block.getId(blockState)); ++ FluidState fluid = this.getFluidState(pos); ++ ++ if (!(iblockdata.getBlock() instanceof BaseFireBlock)) { ++ this.levelEvent(2001, pos, Block.getId(iblockdata)); + } + + if (dropBlock) { +- BlockEntity blockEntity = blockState.hasBlockEntity() ? this.getBlockEntity(pos) : null; +- Block.dropResources(blockState, this, pos, blockEntity, entity, ItemStack.EMPTY); ++ BlockEntity tileentity = iblockdata.hasBlockEntity() ? this.getBlockEntity(pos) : null; ++ ++ Block.dropResources(iblockdata, this, pos, tileentity, entity, ItemStack.EMPTY); + } + +- boolean flag = this.setBlock(pos, fluidState.createLegacyBlock(), 3, recursionLeft); +- if (flag) { +- this.gameEvent(GameEvent.BLOCK_DESTROY, pos, GameEvent.Context.of(entity, blockState)); ++ boolean flag1 = this.setBlock(pos, fluid.createLegacyBlock(), 3, recursionLeft); ++ ++ if (flag1) { ++ this.gameEvent(GameEvent.BLOCK_DESTROY, pos, GameEvent.Context.of(entity, iblockdata)); + } + +- return flag; ++ return flag1; + } + } + +- public void addDestroyBlockEffect(BlockPos pos, BlockState state) { +- } ++ public void addDestroyBlockEffect(BlockPos pos, IBlockData state) {} + +- public boolean setBlockAndUpdate(BlockPos pos, BlockState state) { ++ public boolean setBlockAndUpdate(BlockPos pos, IBlockData state) { + return this.setBlock(pos, state, 3); + } + +- public abstract void sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags); ++ public abstract void sendBlockUpdated(BlockPos pos, IBlockData oldState, IBlockData newState, int flags); + +- public void setBlocksDirty(BlockPos blockPos, BlockState oldState, BlockState newState) { +- } ++ public void setBlocksDirty(BlockPos blockPos, IBlockData oldState, IBlockData newState) {} + +- public void updateNeighborsAt(BlockPos pos, Block block) { +- } ++ public void updateNeighborsAt(BlockPos pos, Block block) {} + +- public void updateNeighborsAtExceptFromFacing(BlockPos pos, Block blockType, Direction skipSide) { +- } ++ public void updateNeighborsAtExceptFromFacing(BlockPos pos, Block blockType, Direction skipSide) {} + +- public void neighborChanged(BlockPos pos, Block block, BlockPos fromPos) { +- } ++ public void neighborChanged(BlockPos pos, Block block, BlockPos fromPos) {} + +- public void neighborChanged(BlockState state, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { +- } ++ public void neighborChanged(IBlockData state, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) {} + + @Override +- public void neighborShapeChanged(Direction direction, BlockState queried, BlockPos pos, BlockPos offsetPos, int flags, int recursionLevel) { ++ public void neighborShapeChanged(Direction direction, IBlockData queried, BlockPos pos, BlockPos offsetPos, int flags, int recursionLevel) { + this.neighborUpdater.shapeUpdate(direction, queried, pos, offsetPos, flags, recursionLevel); + } + + @Override + public int getHeight(Heightmap.Types heightmapType, int x, int z) { +- int i; ++ int k; ++ + if (x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000) { + if (this.hasChunk(SectionPos.blockToSectionCoord(x), SectionPos.blockToSectionCoord(z))) { +- i = this.getChunk(SectionPos.blockToSectionCoord(x), SectionPos.blockToSectionCoord(z)).getHeight(heightmapType, x & 15, z & 15) + 1; ++ k = this.getChunk(SectionPos.blockToSectionCoord(x), SectionPos.blockToSectionCoord(z)).getHeight(heightmapType, x & 15, z & 15) + 1; + } else { +- i = this.getMinBuildHeight(); ++ k = this.getMinBuildHeight(); + } + } else { +- i = this.getSeaLevel() + 1; ++ k = this.getSeaLevel() + 1; + } + +- return i; ++ return k; + } + + @Override +@@ -340,11 +518,20 @@ + } + + @Override +- public BlockState getBlockState(BlockPos pos) { ++ public IBlockData getBlockState(BlockPos pos) { ++ // CraftBukkit start - tree generation ++ if (captureTreeGeneration) { ++ CapturedBlockState previous = capturedBlockStates.get(pos); ++ if (previous != null) { ++ return previous.getHandle(); ++ } ++ } ++ // CraftBukkit end + if (this.isOutsideBuildHeight(pos)) { + return Blocks.VOID_AIR.defaultBlockState(); + } else { + LevelChunk chunk = this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())); ++ + return chunk.getBlockState(pos); + } + } +@@ -354,8 +541,9 @@ + if (this.isOutsideBuildHeight(pos)) { + return Fluids.EMPTY.defaultFluidState(); + } else { +- LevelChunk chunkAt = this.getChunkAt(pos); +- return chunkAt.getFluidState(pos); ++ LevelChunk chunk = this.getChunkAt(pos); ++ ++ return chunk.getFluidState(pos); + } + } + +@@ -368,34 +556,38 @@ + } + + public void playSound(@Nullable Entity entity, BlockPos pos, SoundEvent sound, SoundSource category, float volume, float pitch) { +- this.playSound(entity instanceof Player player ? player : null, pos, sound, category, volume, pitch); ++ Player entityhuman; ++ ++ if (entity instanceof Player) { ++ Player entityhuman1 = (Player) entity; ++ ++ entityhuman = entityhuman1; ++ } else { ++ entityhuman = null; ++ } ++ ++ this.playSound(entityhuman, pos, sound, category, volume, pitch); + } + + @Override + public void playSound(@Nullable Player player, BlockPos pos, SoundEvent sound, SoundSource category, float volume, float pitch) { +- this.playSound(player, (double)pos.getX() + 0.5, (double)pos.getY() + 0.5, (double)pos.getZ() + 0.5, sound, category, volume, pitch); ++ this.playSound(player, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, sound, category, volume, pitch); + } + +- public abstract void playSeededSound( +- @Nullable Player player, double x, double d, double y, Holder holder, SoundSource z, float f, float sound, long source +- ); ++ public abstract void playSeededSound(@Nullable Player player, double x, double d1, double y, Holder holder, SoundSource z, float f, float sound, long source); + +- public void playSeededSound( +- @Nullable Player player, double x, double y, double z, SoundEvent sound, SoundSource source, float volume, float pitch, long seed +- ) { +- this.playSeededSound(player, x, y, z, BuiltInRegistries.SOUND_EVENT.wrapAsHolder(sound), source, volume, pitch, seed); ++ public void playSeededSound(@Nullable Player player, double x, double d1, double y, SoundEvent soundeffect, SoundSource z, float f, float sound, long source) { ++ this.playSeededSound(player, x, d1, y, BuiltInRegistries.SOUND_EVENT.wrapAsHolder(soundeffect), z, f, sound, source); + } + +- public abstract void playSeededSound( +- @Nullable Player player, Entity entity, Holder sound, SoundSource category, float volume, float pitch, long seed +- ); ++ public abstract void playSeededSound(@Nullable Player player, Entity entity, Holder sound, SoundSource category, float volume, float pitch, long seed); + +- public void playSound(@Nullable Player player, double d, double d1, double d2, SoundEvent soundEvent, SoundSource soundSource) { +- this.playSound(player, d, d1, d2, soundEvent, soundSource, 1.0F, 1.0F); ++ public void playSound(@Nullable Player entityhuman, double d0, double d1, double d2, SoundEvent soundeffect, SoundSource soundcategory) { ++ this.playSound(entityhuman, d0, d1, d2, soundeffect, soundcategory, 1.0F, 1.0F); + } + +- public void playSound(@Nullable Player player, double x, double y, double z, SoundEvent sound, SoundSource category, float volume, float pitch) { +- this.playSeededSound(player, x, y, z, sound, category, volume, pitch, this.threadSafeRandom.nextLong()); ++ public void playSound(@Nullable Player player, double x, double d1, double y, SoundEvent soundeffect, SoundSource z, float f, float sound) { ++ this.playSeededSound(player, x, d1, y, soundeffect, z, f, sound, this.threadSafeRandom.nextLong()); + } + + public void playSound(@Nullable Player player, Entity entity, SoundEvent event, SoundSource category, float volume, float pitch) { +@@ -403,33 +595,26 @@ + } + + public void playLocalSound(BlockPos pos, SoundEvent sound, SoundSource category, float volume, float pitch, boolean distanceDelay) { +- this.playLocalSound((double)pos.getX() + 0.5, (double)pos.getY() + 0.5, (double)pos.getZ() + 0.5, sound, category, volume, pitch, distanceDelay); ++ this.playLocalSound((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, sound, category, volume, pitch, distanceDelay); + } + +- public void playLocalSound(Entity entity, SoundEvent soundEvent, SoundSource soundSource, float f, float f1) { +- } ++ public void playLocalSound(Entity entity, SoundEvent soundeffect, SoundSource soundcategory, float f, float f1) {} + +- public void playLocalSound(double x, double y, double z, SoundEvent sound, SoundSource category, float volume, float pitch, boolean distanceDelay) { +- } ++ public void playLocalSound(double x, double d1, double y, SoundEvent soundeffect, SoundSource z, float f, float sound, boolean category) {} + + @Override +- public void addParticle(ParticleOptions particleData, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { +- } ++ public void addParticle(ParticleOptions particleData, double x, double d1, double y, double d3, double z, double d5) {} + +- public void addParticle(ParticleOptions particleData, boolean forceAlwaysRender, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { +- } ++ public void addParticle(ParticleOptions particleData, boolean forceAlwaysRender, double x, double d1, double y, double d3, double z, double d5) {} + +- public void addAlwaysVisibleParticle(ParticleOptions particleData, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { +- } ++ public void addAlwaysVisibleParticle(ParticleOptions particleData, double x, double d1, double y, double d3, double z, double d5) {} + +- public void addAlwaysVisibleParticle( +- ParticleOptions particleData, boolean ignoreRange, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed +- ) { +- } ++ public void addAlwaysVisibleParticle(ParticleOptions particleData, boolean ignoreRange, double x, double d1, double y, double d3, double z, double d5) {} + + public float getSunAngle(float partialTicks) { +- float timeOfDay = this.getTimeOfDay(partialTicks); +- return timeOfDay * (float) (Math.PI * 2); ++ float f1 = this.getTimeOfDay(partialTicks); ++ ++ return f1 * 6.2831855F; + } + + public void addBlockEntityTicker(TickingBlockEntity ticker) { +@@ -437,8 +622,9 @@ + } + + protected void tickBlockEntities() { +- ProfilerFiller profiler = this.getProfiler(); +- profiler.push("blockEntities"); ++ ProfilerFiller gameprofilerfiller = this.getProfiler(); ++ ++ gameprofilerfiller.push("blockEntities"); + this.tickingBlockEntities = true; + if (!this.pendingBlockEntityTickers.isEmpty()) { + this.blockEntityTickers.addAll(this.pendingBlockEntityTickers); +@@ -449,26 +635,28 @@ + boolean flag = this.tickRateManager().runsNormally(); + + while (iterator.hasNext()) { +- TickingBlockEntity tickingBlockEntity = iterator.next(); +- if (tickingBlockEntity.isRemoved()) { ++ TickingBlockEntity tickingblockentity = (TickingBlockEntity) iterator.next(); ++ ++ if (tickingblockentity.isRemoved()) { + iterator.remove(); +- } else if (flag && this.shouldTickBlocksAt(tickingBlockEntity.getPos())) { +- tickingBlockEntity.tick(); ++ } else if (flag && this.shouldTickBlocksAt(tickingblockentity.getPos())) { ++ tickingblockentity.tick(); + } + } + + this.tickingBlockEntities = false; +- profiler.pop(); ++ gameprofilerfiller.pop(); + } + + public void guardEntityTick(Consumer consumerEntity, T entity) { + try { + consumerEntity.accept(entity); +- } catch (Throwable var6) { +- CrashReport crashReport = CrashReport.forThrowable(var6, "Ticking entity"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Entity being ticked"); +- entity.fillCrashReportCategory(crashReportCategory); +- throw new ReportedException(crashReport); ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking entity"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being ticked"); ++ ++ entity.fillCrashReportCategory(crashreportsystemdetails); ++ throw new ReportedException(crashreport); + } + } + +@@ -484,145 +672,59 @@ + return this.shouldTickBlocksAt(ChunkPos.asLong(pos)); + } + +- public Explosion explode(@Nullable Entity source, double x, double y, double z, float radius, Level.ExplosionInteraction explosionInteraction) { +- return this.explode( +- source, +- Explosion.getDefaultDamageSource(this, source), +- null, +- x, +- y, +- z, +- radius, +- false, +- explosionInteraction, +- ParticleTypes.EXPLOSION, +- ParticleTypes.EXPLOSION_EMITTER, +- SoundEvents.GENERIC_EXPLODE +- ); ++ public Explosion explode(@Nullable Entity source, double x, double d1, double y, float f, Level.a z) { ++ return this.explode(source, Explosion.getDefaultDamageSource(this, source), (ExplosionDamageCalculator) null, x, d1, y, f, false, z, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); + } + +- public Explosion explode(@Nullable Entity source, double x, double y, double z, float radius, boolean fire, Level.ExplosionInteraction explosionInteraction) { +- return this.explode( +- source, +- Explosion.getDefaultDamageSource(this, source), +- null, +- x, +- y, +- z, +- radius, +- fire, +- explosionInteraction, +- ParticleTypes.EXPLOSION, +- ParticleTypes.EXPLOSION_EMITTER, +- SoundEvents.GENERIC_EXPLODE +- ); ++ public Explosion explode(@Nullable Entity source, double x, double d1, double y, float f, boolean z, Level.a world_a) { ++ return this.explode(source, Explosion.getDefaultDamageSource(this, source), (ExplosionDamageCalculator) null, x, d1, y, f, z, world_a, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); + } + +- public Explosion explode( +- @Nullable Entity source, +- @Nullable DamageSource damageSource, +- @Nullable ExplosionDamageCalculator damageCalculator, +- Vec3 pos, +- float radius, +- boolean fire, +- Level.ExplosionInteraction explosionInteraction +- ) { +- return this.explode( +- source, +- damageSource, +- damageCalculator, +- pos.x(), +- pos.y(), +- pos.z(), +- radius, +- fire, +- explosionInteraction, +- ParticleTypes.EXPLOSION, +- ParticleTypes.EXPLOSION_EMITTER, +- SoundEvents.GENERIC_EXPLODE +- ); ++ public Explosion explode(@Nullable Entity source, @Nullable DamageSource damageSource, @Nullable ExplosionDamageCalculator damageCalculator, Vec3 pos, float radius, boolean fire, Level.a explosionInteraction) { ++ return this.explode(source, damageSource, damageCalculator, pos.x(), pos.y(), pos.z(), radius, fire, explosionInteraction, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); + } + +- public Explosion explode( +- @Nullable Entity source, +- @Nullable DamageSource damageSource, +- @Nullable ExplosionDamageCalculator damageCalculator, +- double x, +- double y, +- double z, +- float radius, +- boolean fire, +- Level.ExplosionInteraction explosionInteraction +- ) { +- return this.explode( +- source, +- damageSource, +- damageCalculator, +- x, +- y, +- z, +- radius, +- fire, +- explosionInteraction, +- ParticleTypes.EXPLOSION, +- ParticleTypes.EXPLOSION_EMITTER, +- SoundEvents.GENERIC_EXPLODE +- ); ++ public Explosion explode(@Nullable Entity source, @Nullable DamageSource damageSource, @Nullable ExplosionDamageCalculator damageCalculator, double x, double d1, double y, float f, boolean z, Level.a world_a) { ++ return this.explode(source, damageSource, damageCalculator, x, d1, y, f, z, world_a, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); + } + +- public Explosion explode( +- @Nullable Entity entity, +- @Nullable DamageSource damageSource, +- @Nullable ExplosionDamageCalculator explosionDamageCalculator, +- double d, +- double d1, +- double d2, +- float f, +- boolean flag, +- Level.ExplosionInteraction explosionInteraction, +- ParticleOptions particleOptions, +- ParticleOptions particleOptions1, +- SoundEvent soundEvent +- ) { +- return this.explode( +- entity, damageSource, explosionDamageCalculator, d, d1, d2, f, flag, explosionInteraction, true, particleOptions, particleOptions1, soundEvent +- ); ++ public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.a world_a, ParticleOptions particleparam, ParticleOptions particleparam1, SoundEvent soundeffect) { ++ return this.explode(entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, world_a, true, particleparam, particleparam1, soundeffect); + } + +- public Explosion explode( +- @Nullable Entity entity, +- @Nullable DamageSource damageSource, +- @Nullable ExplosionDamageCalculator explosionDamageCalculator, +- double d, +- double d1, +- double d2, +- float f, +- boolean flag, +- Level.ExplosionInteraction explosionInteraction, +- boolean flag1, +- ParticleOptions particleOptions, +- ParticleOptions particleOptions1, +- SoundEvent soundEvent +- ) { +- Explosion.BlockInteraction blockInteraction = switch (explosionInteraction) { +- case NONE -> Explosion.BlockInteraction.KEEP; +- case BLOCK -> this.getDestroyType(GameRules.RULE_BLOCK_EXPLOSION_DROP_DECAY); +- case MOB -> this.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) +- ? this.getDestroyType(GameRules.RULE_MOB_EXPLOSION_DROP_DECAY) +- : Explosion.BlockInteraction.KEEP; +- case TNT -> this.getDestroyType(GameRules.RULE_TNT_EXPLOSION_DROP_DECAY); +- case BLOW -> Explosion.BlockInteraction.TRIGGER_BLOCK; +- }; +- Explosion explosion = new Explosion( +- this, entity, damageSource, explosionDamageCalculator, d, d1, d2, f, flag, blockInteraction, particleOptions, particleOptions1, soundEvent +- ); ++ public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.a world_a, boolean flag1, ParticleOptions particleparam, ParticleOptions particleparam1, SoundEvent soundeffect) { ++ Explosion.Effect explosion_effect; ++ ++ switch (world_a) { ++ case NONE: ++ explosion_effect = Explosion.Effect.KEEP; ++ break; ++ case BLOCK: ++ explosion_effect = this.getDestroyType(GameRules.RULE_BLOCK_EXPLOSION_DROP_DECAY); ++ break; ++ case MOB: ++ explosion_effect = this.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? this.getDestroyType(GameRules.RULE_MOB_EXPLOSION_DROP_DECAY) : Explosion.Effect.KEEP; ++ break; ++ case TNT: ++ explosion_effect = this.getDestroyType(GameRules.RULE_TNT_EXPLOSION_DROP_DECAY); ++ break; ++ case BLOW: ++ explosion_effect = Explosion.Effect.TRIGGER_BLOCK; ++ break; ++ default: ++ throw new IncompatibleClassChangeError(); ++ } ++ ++ Explosion.Effect explosion_effect1 = explosion_effect; ++ Explosion explosion = new Explosion(this, entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, explosion_effect1, particleparam, particleparam1, soundeffect); ++ + explosion.explode(); + explosion.finalizeExplosion(flag1); + return explosion; + } + +- private Explosion.BlockInteraction getDestroyType(GameRules.Key gameRule) { +- return this.getGameRules().getBoolean(gameRule) ? Explosion.BlockInteraction.DESTROY_WITH_DECAY : Explosion.BlockInteraction.DESTROY; ++ private Explosion.Effect getDestroyType(GameRules.Key gameRule) { ++ return this.getGameRules().getBoolean(gameRule) ? Explosion.Effect.DESTROY_WITH_DECAY : Explosion.Effect.DESTROY; + } + + public abstract String gatherChunkSourceStats(); +@@ -630,19 +732,30 @@ + @Nullable + @Override + public BlockEntity getBlockEntity(BlockPos pos) { +- if (this.isOutsideBuildHeight(pos)) { +- return null; +- } else { +- return !this.isClientSide && Thread.currentThread() != this.thread +- ? null +- : this.getChunkAt(pos).getBlockEntity(pos, LevelChunk.EntityCreationType.IMMEDIATE); ++ // CraftBukkit start ++ return getBlockEntity(pos, true); ++ } ++ ++ @Nullable ++ public BlockEntity getBlockEntity(BlockPos blockposition, boolean validate) { ++ if (capturedTileEntities.containsKey(blockposition)) { ++ return capturedTileEntities.get(blockposition); + } ++ // CraftBukkit end ++ return this.isOutsideBuildHeight(blockposition) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(blockposition).getBlockEntity(blockposition, LevelChunk.EnumTileEntityState.IMMEDIATE)); + } + + public void setBlockEntity(BlockEntity blockEntity) { +- BlockPos blockPos = blockEntity.getBlockPos(); +- if (!this.isOutsideBuildHeight(blockPos)) { +- this.getChunkAt(blockPos).addAndRegisterBlockEntity(blockEntity); ++ BlockPos blockposition = blockEntity.getBlockPos(); ++ ++ if (!this.isOutsideBuildHeight(blockposition)) { ++ // CraftBukkit start ++ if (captureBlockStates) { ++ capturedTileEntities.put(blockposition.immutable(), blockEntity); ++ return; ++ } ++ // CraftBukkit end ++ this.getChunkAt(blockposition).addAndRegisterBlockEntity(blockEntity); + } + } + +@@ -653,16 +766,16 @@ + } + + public boolean isLoaded(BlockPos pos) { +- return !this.isOutsideBuildHeight(pos) +- && this.getChunkSource().hasChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())); ++ return this.isOutsideBuildHeight(pos) ? false : this.getChunkSource().hasChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())); + } + + public boolean loadedAndEntityCanStandOnFace(BlockPos pos, Entity entity, Direction direction) { + if (this.isOutsideBuildHeight(pos)) { + return false; + } else { +- ChunkAccess chunk = this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()), ChunkStatus.FULL, false); +- return chunk != null && chunk.getBlockState(pos).entityCanStandOnFace(this, pos, entity, direction); ++ ChunkAccess ichunkaccess = this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()), ChunkStatus.FULL, false); ++ ++ return ichunkaccess == null ? false : ichunkaccess.getBlockState(pos).entityCanStandOnFace(this, pos, entity, direction); + } + } + +@@ -671,10 +784,11 @@ + } + + public void updateSkyBrightness() { +- double d = 1.0 - (double)(this.getRainLevel(1.0F) * 5.0F) / 16.0; +- double d1 = 1.0 - (double)(this.getThunderLevel(1.0F) * 5.0F) / 16.0; +- double d2 = 0.5 + 2.0 * Mth.clamp((double)Mth.cos(this.getTimeOfDay(1.0F) * (float) (Math.PI * 2)), -0.25, 0.25); +- this.skyDarken = (int)((1.0 - d2 * d * d1) * 11.0); ++ double d0 = 1.0D - (double) (this.getRainLevel(1.0F) * 5.0F) / 16.0D; ++ double d1 = 1.0D - (double) (this.getThunderLevel(1.0F) * 5.0F) / 16.0D; ++ double d2 = 0.5D + 2.0D * Mth.clamp((double) Mth.cos(this.getTimeOfDay(1.0F) * 6.2831855F), -0.25D, 0.25D); ++ ++ this.skyDarken = (int) ((1.0D - d2 * d0 * d1) * 11.0D); + } + + public void setSpawnSettings(boolean hostile, boolean peaceful) { +@@ -682,14 +796,13 @@ + } + + public BlockPos getSharedSpawnPos() { +- BlockPos blockPos = new BlockPos(this.levelData.getXSpawn(), this.levelData.getYSpawn(), this.levelData.getZSpawn()); +- if (!this.getWorldBorder().isWithinBounds(blockPos)) { +- blockPos = this.getHeightmapPos( +- Heightmap.Types.MOTION_BLOCKING, BlockPos.containing(this.getWorldBorder().getCenterX(), 0.0, this.getWorldBorder().getCenterZ()) +- ); ++ BlockPos blockposition = new BlockPos(this.levelData.getXSpawn(), this.levelData.getYSpawn(), this.levelData.getZSpawn()); ++ ++ if (!this.getWorldBorder().isWithinBounds(blockposition)) { ++ blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, BlockPos.containing(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); + } + +- return blockPos; ++ return blockposition; + } + + public float getSharedSpawnAngle() { +@@ -703,9 +816,9 @@ + this.thunderLevel = 1.0F; + } + } ++ + } + +- @Override + public void close() throws IOException { + this.getChunkSource().close(); + } +@@ -720,18 +833,25 @@ + public List getEntities(@Nullable Entity entity, AABB boundingBox, Predicate predicate) { + this.getProfiler().incrementCounter("getEntities"); + List list = Lists.newArrayList(); +- this.getEntities().get(boundingBox, entity1 -> { ++ ++ this.getEntities().get(boundingBox, (entity1) -> { + if (entity1 != entity && predicate.test(entity1)) { + list.add(entity1); + } + + if (entity1 instanceof EnderDragon) { +- for (EnderDragonPart enderDragonPart : ((EnderDragon)entity1).getSubEntities()) { +- if (entity1 != entity && predicate.test(enderDragonPart)) { +- list.add(enderDragonPart); ++ EnderDragonPart[] aentitycomplexpart = ((EnderDragon) entity1).getSubEntities(); ++ int i = aentitycomplexpart.length; ++ ++ for (int j = 0; j < i; ++j) { ++ EnderDragonPart entitycomplexpart = aentitycomplexpart[j]; ++ ++ if (entity1 != entity && predicate.test(entitycomplexpart)) { ++ list.add(entitycomplexpart); + } + } + } ++ + }); + return list; + } +@@ -739,6 +859,7 @@ + @Override + public List getEntities(EntityTypeTest entityTypeTest, AABB bounds, Predicate predicate) { + List list = Lists.newArrayList(); ++ + this.getEntities(entityTypeTest, bounds, predicate, list); + return list; + } +@@ -747,31 +868,35 @@ + this.getEntities(entityTypeTest, bounds, predicate, output, Integer.MAX_VALUE); + } + +- public void getEntities( +- EntityTypeTest entityTypeTest, AABB bounds, Predicate predicate, List output, int maxResults +- ) { ++ public void getEntities(EntityTypeTest entityTypeTest, AABB bounds, Predicate predicate, List output, int maxResults) { + this.getProfiler().incrementCounter("getEntities"); +- this.getEntities().get(entityTypeTest, bounds, entity -> { ++ this.getEntities().get(entityTypeTest, bounds, (entity) -> { + if (predicate.test(entity)) { + output.add(entity); + if (output.size() >= maxResults) { +- return AbortableIterationConsumer.Continuation.ABORT; ++ return AbortableIterationConsumer.a.ABORT; + } + } + +- if (entity instanceof EnderDragon enderDragon) { +- for (EnderDragonPart enderDragonPart : enderDragon.getSubEntities()) { +- T entity1 = entityTypeTest.tryCast(enderDragonPart); +- if (entity1 != null && predicate.test(entity1)) { +- output.add(entity1); ++ if (entity instanceof EnderDragon) { ++ EnderDragon entityenderdragon = (EnderDragon) entity; ++ EnderDragonPart[] aentitycomplexpart = entityenderdragon.getSubEntities(); ++ int j = aentitycomplexpart.length; ++ ++ for (int k = 0; k < j; ++k) { ++ EnderDragonPart entitycomplexpart = aentitycomplexpart[k]; ++ T t0 = entityTypeTest.tryCast(entitycomplexpart); // CraftBukkit - decompile error ++ ++ if (t0 != null && predicate.test(t0)) { ++ output.add(t0); + if (output.size() >= maxResults) { +- return AbortableIterationConsumer.Continuation.ABORT; ++ return AbortableIterationConsumer.a.ABORT; + } + } + } + } + +- return AbortableIterationConsumer.Continuation.CONTINUE; ++ return AbortableIterationConsumer.a.CONTINUE; + }); + } + +@@ -782,6 +907,7 @@ + if (this.hasChunkAt(pos)) { + this.getChunkAt(pos).setUnsaved(true); + } ++ + } + + @Override +@@ -789,8 +915,7 @@ + return 63; + } + +- public void disconnect() { +- } ++ public void disconnect() {} + + public long getGameTime() { + return this.levelData.getGameTime(); +@@ -804,11 +929,9 @@ + return true; + } + +- public void broadcastEntityEvent(Entity entity, byte state) { +- } ++ public void broadcastEntityEvent(Entity entity, byte state) {} + +- public void broadcastDamageEvent(Entity entity, DamageSource damageSource) { +- } ++ public void broadcastDamageEvent(Entity entity, DamageSource damageSource) {} + + public void blockEvent(BlockPos pos, Block block, int eventID, int eventParam) { + this.getBlockState(pos).triggerEvent(this, pos, eventID, eventParam); +@@ -830,9 +953,10 @@ + } + + public void setThunderLevel(float strength) { +- float f = Mth.clamp(strength, 0.0F, 1.0F); +- this.oThunderLevel = f; +- this.thunderLevel = f; ++ float f1 = Mth.clamp(strength, 0.0F, 1.0F); ++ ++ this.oThunderLevel = f1; ++ this.thunderLevel = f1; + } + + public float getRainLevel(float delta) { +@@ -840,17 +964,18 @@ + } + + public void setRainLevel(float strength) { +- float f = Mth.clamp(strength, 0.0F, 1.0F); +- this.oRainLevel = f; +- this.rainLevel = f; ++ float f1 = Mth.clamp(strength, 0.0F, 1.0F); ++ ++ this.oRainLevel = f1; ++ this.rainLevel = f1; + } + + public boolean isThundering() { +- return this.dimensionType().hasSkyLight() && !this.dimensionType().hasCeiling() && (double)this.getThunderLevel(1.0F) > 0.9; ++ return this.dimensionType().hasSkyLight() && !this.dimensionType().hasCeiling() ? (double) this.getThunderLevel(1.0F) > 0.9D : false; + } + + public boolean isRaining() { +- return (double)this.getRainLevel(1.0F) > 0.2; ++ return (double) this.getRainLevel(1.0F) > 0.2D; + } + + public boolean isRainingAt(BlockPos pos) { +@@ -861,8 +986,9 @@ + } else if (this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, pos).getY() > pos.getY()) { + return false; + } else { +- Biome biome = this.getBiome(pos).value(); +- return biome.getPrecipitationAt(pos) == Biome.Precipitation.RAIN; ++ Biome biomebase = (Biome) this.getBiome(pos).value(); ++ ++ return biomebase.getPrecipitationAt(pos) == Biome.Precipitation.RAIN; + } + } + +@@ -873,59 +999,74 @@ + + public abstract int getFreeMapId(); + +- public void globalLevelEvent(int id, BlockPos pos, int data) { +- } ++ public void globalLevelEvent(int id, BlockPos pos, int data) {} + + public CrashReportCategory fillReportDetails(CrashReport report) { +- CrashReportCategory crashReportCategory = report.addCategory("Affected level", 1); +- crashReportCategory.setDetail("All players", () -> this.players().size() + " total; " + this.players()); +- crashReportCategory.setDetail("Chunk stats", this.getChunkSource()::gatherStats); +- crashReportCategory.setDetail("Level dimension", () -> this.dimension().location().toString()); ++ CrashReportCategory crashreportsystemdetails = report.addCategory("Affected level", 1); + ++ crashreportsystemdetails.setDetail("All players", () -> { ++ int i = this.players().size(); ++ ++ return i + " total; " + this.players(); ++ }); ++ ChunkSource ichunkprovider = this.getChunkSource(); ++ ++ Objects.requireNonNull(ichunkprovider); ++ crashreportsystemdetails.setDetail("Chunk stats", ichunkprovider::gatherStats); ++ crashreportsystemdetails.setDetail("Level dimension", () -> { ++ return this.dimension().location().toString(); ++ }); ++ + try { +- this.levelData.fillCrashReportCategory(crashReportCategory, this); +- } catch (Throwable var4) { +- crashReportCategory.setDetailError("Level Data Unobtainable", var4); ++ this.levelData.fillCrashReportCategory(crashreportsystemdetails, this); ++ } catch (Throwable throwable) { ++ crashreportsystemdetails.setDetailError("Level Data Unobtainable", throwable); + } + +- return crashReportCategory; ++ return crashreportsystemdetails; + } + + public abstract void destroyBlockProgress(int breakerId, BlockPos pos, int progress); + +- public void createFireworks(double x, double y, double z, double motionX, double motionY, double motionZ, @Nullable CompoundTag compound) { +- } ++ public void createFireworks(double x, double d1, double y, double d3, double z, double d5, @Nullable CompoundTag motionX) {} + + public abstract Scoreboard getScoreboard(); + + public void updateNeighbourForOutputSignal(BlockPos pos, Block block) { +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- BlockPos blockPos = pos.relative(direction); +- if (this.hasChunkAt(blockPos)) { +- BlockState blockState = this.getBlockState(blockPos); +- if (blockState.is(Blocks.COMPARATOR)) { +- this.neighborChanged(blockState, blockPos, block, pos, false); +- } else if (blockState.isRedstoneConductor(this, blockPos)) { +- BlockPos var7 = blockPos.relative(direction); +- blockState = this.getBlockState(var7); +- if (blockState.is(Blocks.COMPARATOR)) { +- this.neighborChanged(blockState, var7, block, pos, false); ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); ++ ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ ++ if (this.hasChunkAt(blockposition1)) { ++ IBlockData iblockdata = this.getBlockState(blockposition1); ++ ++ if (iblockdata.is(Blocks.COMPARATOR)) { ++ this.neighborChanged(iblockdata, blockposition1, block, pos, false); ++ } else if (iblockdata.isRedstoneConductor(this, blockposition1)) { ++ blockposition1 = blockposition1.relative(enumdirection); ++ iblockdata = this.getBlockState(blockposition1); ++ if (iblockdata.is(Blocks.COMPARATOR)) { ++ this.neighborChanged(iblockdata, blockposition1, block, pos, false); + } + } + } + } ++ + } + + @Override + public DifficultyInstance getCurrentDifficultyAt(BlockPos pos) { +- long l = 0L; ++ long i = 0L; + float f = 0.0F; ++ + if (this.hasChunkAt(pos)) { + f = this.getMoonBrightness(); +- l = this.getChunkAt(pos).getInhabitedTime(); ++ i = this.getChunkAt(pos).getInhabitedTime(); + } + +- return new DifficultyInstance(this.getDifficulty(), this.getDayTime(), l, f); ++ return new DifficultyInstance(this.getDifficulty(), this.getDayTime(), i, f); + } + + @Override +@@ -933,8 +1074,7 @@ + return this.skyDarken; + } + +- public void setSkyFlashTime(int timeFlash) { +- } ++ public void setSkyFlashTime(int timeFlash) {} + + @Override + public WorldBorder getWorldBorder() { +@@ -947,7 +1087,7 @@ + + @Override + public DimensionType dimensionType() { +- return this.dimensionTypeRegistration.value(); ++ return (DimensionType) this.dimensionTypeRegistration.value(); + } + + public ResourceKey dimensionTypeId() { +@@ -968,7 +1108,7 @@ + } + + @Override +- public boolean isStateAtPosition(BlockPos pos, Predicate state) { ++ public boolean isStateAtPosition(BlockPos pos, Predicate state) { + return state.test(this.getBlockState(pos)); + } + +@@ -981,8 +1121,9 @@ + + public BlockPos getBlockRandomPos(int x, int y, int z, int yMask) { + this.randValue = this.randValue * 3 + 1013904223; +- int i = this.randValue >> 2; +- return new BlockPos(x + (i & 15), y + (i >> 16 & yMask), z + (i >> 8 & 15)); ++ int i1 = this.randValue >> 2; ++ ++ return new BlockPos(x + (i1 & 15), y + (i1 >> 16 & yMask), z + (i1 >> 8 & 15)); + } + + public boolean noSave() { +@@ -990,7 +1131,7 @@ + } + + public ProfilerFiller getProfiler() { +- return this.profiler.get(); ++ return (ProfilerFiller) this.profiler.get(); + } + + public Supplier getProfilerSupplier() { +@@ -1006,11 +1147,11 @@ + return this.isDebug; + } + +- protected abstract LevelEntityGetter getEntities(); ++ public abstract LevelEntityGetter getEntities(); + + @Override + public long nextSubTickCount() { +- return this.subTickCount++; ++ return (long) (this.subTickCount++); + } + + @Override +@@ -1022,11 +1163,10 @@ + return this.damageSources; + } + +- public static enum ExplosionInteraction { +- NONE, +- BLOCK, +- MOB, +- TNT, +- BLOW; ++ public static enum a { ++ ++ NONE, BLOCK, MOB, TNT, BLOW; ++ ++ private a() {} + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/LevelAccessor.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/LevelAccessor.java.patch new file mode 100644 index 0000000000..847e66d295 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/LevelAccessor.java.patch @@ -0,0 +1,81 @@ +--- a/net/minecraft/world/level/LevelAccessor.java ++++ b/net/minecraft/world/level/LevelAccessor.java +@@ -13,7 +13,7 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.block.Block; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ChunkSource; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.Fluid; +@@ -25,6 +25,7 @@ + import net.minecraft.world.ticks.TickPriority; + + public interface LevelAccessor extends CommonLevelAccessor, LevelTimeAccess { ++ + @Override + default long dayTime() { + return this.getLevelData().getDayTime(); +@@ -34,12 +35,12 @@ + + LevelTickAccess getBlockTicks(); + +- private ScheduledTick createTick(BlockPos pos, T type, int delay, TickPriority priority) { +- return new ScheduledTick<>(type, pos, this.getLevelData().getGameTime() + (long)delay, priority, this.nextSubTickCount()); ++ default ScheduledTick createTick(BlockPos pos, T type, int delay, TickPriority priority) { // CraftBukkit - decompile error ++ return new ScheduledTick<>(type, pos, this.getLevelData().getGameTime() + (long) delay, priority, this.nextSubTickCount()); + } + +- private ScheduledTick createTick(BlockPos pos, T type, int delay) { +- return new ScheduledTick<>(type, pos, this.getLevelData().getGameTime() + (long)delay, this.nextSubTickCount()); ++ default ScheduledTick createTick(BlockPos pos, T type, int delay) { // CraftBukkit - decompile error ++ return new ScheduledTick<>(type, pos, this.getLevelData().getGameTime() + (long) delay, this.nextSubTickCount()); + } + + default void scheduleTick(BlockPos pos, Block block, int delay, TickPriority priority) { +@@ -80,10 +81,9 @@ + + RandomSource getRandom(); + +- default void blockUpdated(BlockPos pos, Block block) { +- } ++ default void blockUpdated(BlockPos pos, Block block) {} + +- default void neighborShapeChanged(Direction direction, BlockState queried, BlockPos pos, BlockPos offsetPos, int flags, int recursionLevel) { ++ default void neighborShapeChanged(Direction direction, IBlockData queried, BlockPos pos, BlockPos offsetPos, int flags, int recursionLevel) { + NeighborUpdater.executeShapeUpdate(this, direction, queried, pos, offsetPos, flags, recursionLevel - 1); + } + +@@ -93,25 +93,27 @@ + + void playSound(@Nullable Player player, BlockPos pos, SoundEvent sound, SoundSource source, float volume, float pitch); + +- void addParticle(ParticleOptions particleData, double x, double d, double y, double d1, double z, double d2); ++ void addParticle(ParticleOptions particleData, double x, double d1, double y, double d3, double z, double d5); + + void levelEvent(@Nullable Player player, int type, BlockPos pos, int data); + + default void levelEvent(int type, BlockPos pos, int data) { +- this.levelEvent(null, type, pos, data); ++ this.levelEvent((Player) null, type, pos, data); + } + + void gameEvent(GameEvent event, Vec3 position, GameEvent.Context context); + + default void gameEvent(@Nullable Entity entity, GameEvent event, Vec3 position) { +- this.gameEvent(event, position, new GameEvent.Context(entity, null)); ++ this.gameEvent(event, position, new GameEvent.Context(entity, (IBlockData) null)); + } + + default void gameEvent(@Nullable Entity entity, GameEvent event, BlockPos pos) { +- this.gameEvent(event, pos, new GameEvent.Context(entity, null)); ++ this.gameEvent(event, pos, new GameEvent.Context(entity, (IBlockData) null)); + } + + default void gameEvent(GameEvent event, BlockPos pos, GameEvent.Context context) { + this.gameEvent(event, Vec3.atCenterOf(pos), context); + } ++ ++ net.minecraft.server.level.ServerLevel getMinecraftWorld(); // CraftBukkit + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/LevelWriter.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/LevelWriter.java.patch new file mode 100644 index 0000000000..488346db68 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/LevelWriter.java.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/world/level/LevelWriter.java ++++ b/net/minecraft/world/level/LevelWriter.java +@@ -3,19 +3,20 @@ + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.world.entity.Entity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public interface LevelWriter { +- boolean setBlock(BlockPos pos, BlockState state, int flags, int recursionLeft); + +- default boolean setBlock(BlockPos pos, BlockState newState, int flags) { ++ boolean setBlock(BlockPos pos, IBlockData state, int flags, int recursionLeft); ++ ++ default boolean setBlock(BlockPos pos, IBlockData newState, int flags) { + return this.setBlock(pos, newState, flags, 512); + } + + boolean removeBlock(BlockPos pos, boolean isMoving); + + default boolean destroyBlock(BlockPos pos, boolean dropBlock) { +- return this.destroyBlock(pos, dropBlock, null); ++ return this.destroyBlock(pos, dropBlock, (Entity) null); + } + + default boolean destroyBlock(BlockPos pos, boolean dropBlock, @Nullable Entity entity) { +@@ -27,4 +28,10 @@ + default boolean addFreshEntity(Entity entity) { + return false; + } ++ ++ // CraftBukkit start ++ default boolean addFreshEntity(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ return false; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/NaturalSpawner.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/NaturalSpawner.java.patch new file mode 100644 index 0000000000..ef2620e36c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/NaturalSpawner.java.patch @@ -0,0 +1,826 @@ +--- a/net/minecraft/world/level/NaturalSpawner.java ++++ b/net/minecraft/world/level/NaturalSpawner.java +@@ -4,6 +4,7 @@ + import it.unimi.dsi.fastutil.objects.Object2IntMap; + import it.unimi.dsi.fastutil.objects.Object2IntMaps; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; ++import java.util.Iterator; + import java.util.Objects; + import java.util.Optional; + import java.util.function.Consumer; +@@ -15,6 +16,7 @@ + import net.minecraft.core.QuartPos; + import net.minecraft.core.registries.BuiltInRegistries; + import net.minecraft.core.registries.Registries; ++import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.tags.BiomeTags; + import net.minecraft.tags.BlockTags; +@@ -25,16 +27,16 @@ + import net.minecraft.util.random.WeightedRandomList; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.Mob; + import net.minecraft.world.entity.MobCategory; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.SpawnPlacements; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.biome.Biome; + import net.minecraft.world.level.biome.MobSpawnSettings; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.chunk.LevelChunk; +@@ -43,196 +45,231 @@ + import net.minecraft.world.level.levelgen.structure.Structure; + import net.minecraft.world.level.levelgen.structure.structures.NetherFortressStructure; + import net.minecraft.world.level.material.FluidState; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; ++import net.minecraft.world.level.storage.LevelData; + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.util.CraftSpawnCategory; ++import org.bukkit.entity.SpawnCategory; ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; ++// CraftBukkit end + + public final class NaturalSpawner { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int MIN_SPAWN_DISTANCE = 24; + public static final int SPAWN_DISTANCE_CHUNK = 8; + public static final int SPAWN_DISTANCE_BLOCK = 128; +- static final int MAGIC_NUMBER = (int)Math.pow(17.0, 2.0); +- private static final MobCategory[] SPAWNING_CATEGORIES = Stream.of(MobCategory.values()) +- .filter(category -> category != MobCategory.MISC) +- .toArray(MobCategory[]::new); ++ static final int MAGIC_NUMBER = (int) Math.pow(17.0D, 2.0D); ++ private static final MobCategory[] SPAWNING_CATEGORIES = (MobCategory[]) Stream.of(MobCategory.values()).filter((enumcreaturetype) -> { ++ return enumcreaturetype != MobCategory.MISC; ++ }).toArray((i) -> { ++ return new MobCategory[i]; ++ }); + +- private NaturalSpawner() { +- } ++ private NaturalSpawner() {} + +- public static NaturalSpawner.SpawnState createState( +- int spawnableChunkCount, Iterable entities, NaturalSpawner.ChunkGetter chunkGetter, LocalMobCapCalculator calculator +- ) { +- PotentialCalculator potentialCalculator = new PotentialCalculator(); +- Object2IntOpenHashMap map = new Object2IntOpenHashMap<>(); ++ public static NaturalSpawner.SpawnState createState(int spawnableChunkCount, Iterable entities, NaturalSpawner.ChunkGetter chunkGetter, LocalMobCapCalculator calculator) { ++ PotentialCalculator spawnercreatureprobabilities = new PotentialCalculator(); ++ Object2IntOpenHashMap object2intopenhashmap = new Object2IntOpenHashMap(); ++ Iterator iterator = entities.iterator(); + +- for (Entity entity : entities) { +- if (entity instanceof Mob mob && (mob.isPersistenceRequired() || mob.requiresCustomPersistence())) { +- continue; ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ ++ if (entity instanceof Mob) { ++ Mob entityinsentient = (Mob) entity; ++ ++ if (entityinsentient.isPersistenceRequired() || entityinsentient.requiresCustomPersistence()) { ++ continue; ++ } + } + +- MobCategory category = entity.getType().getCategory(); +- if (category != MobCategory.MISC) { +- BlockPos blockPos = entity.blockPosition(); +- chunkGetter.query(ChunkPos.asLong(blockPos), chunk -> { +- MobSpawnSettings.MobSpawnCost mobSpawnCost = getRoughBiome(blockPos, chunk).getMobSettings().getMobSpawnCost(entity.getType()); +- if (mobSpawnCost != null) { +- potentialCalculator.addCharge(entity.blockPosition(), mobSpawnCost.charge()); ++ MobCategory enumcreaturetype = entity.getType().getCategory(); ++ ++ if (enumcreaturetype != MobCategory.MISC) { ++ BlockPos blockposition = entity.blockPosition(); ++ ++ chunkGetter.query(ChunkPos.asLong(blockposition), (chunk) -> { ++ MobSpawnSettings.MobSpawnCost biomesettingsmobs_b = getRoughBiome(blockposition, chunk).getMobSettings().getMobSpawnCost(entity.getType()); ++ ++ if (biomesettingsmobs_b != null) { ++ spawnercreatureprobabilities.addCharge(entity.blockPosition(), biomesettingsmobs_b.charge()); + } + + if (entity instanceof Mob) { +- calculator.addMob(chunk.getPos(), category); ++ calculator.addMob(chunk.getPos(), enumcreaturetype); + } + +- map.addTo(category, 1); ++ object2intopenhashmap.addTo(enumcreaturetype, 1); + }); + } + } + +- return new NaturalSpawner.SpawnState(spawnableChunkCount, map, potentialCalculator, calculator); ++ return new NaturalSpawner.SpawnState(spawnableChunkCount, object2intopenhashmap, spawnercreatureprobabilities, calculator); + } + + static Biome getRoughBiome(BlockPos pos, ChunkAccess chunk) { +- return chunk.getNoiseBiome(QuartPos.fromBlock(pos.getX()), QuartPos.fromBlock(pos.getY()), QuartPos.fromBlock(pos.getZ())).value(); ++ return (Biome) chunk.getNoiseBiome(QuartPos.fromBlock(pos.getX()), QuartPos.fromBlock(pos.getY()), QuartPos.fromBlock(pos.getZ())).value(); + } + +- public static void spawnForChunk( +- ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnState spawnState, boolean spawnFriendlies, boolean spawnMonsters, boolean forcedDespawn +- ) { ++ public static void spawnForChunk(ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnState spawnState, boolean spawnFriendlies, boolean spawnMonsters, boolean forcedDespawn) { + level.getProfiler().push("spawner"); ++ MobCategory[] aenumcreaturetype = NaturalSpawner.SPAWNING_CATEGORIES; ++ int i = aenumcreaturetype.length; + +- for (MobCategory mobCategory : SPAWNING_CATEGORIES) { +- if ((spawnFriendlies || !mobCategory.isFriendly()) +- && (spawnMonsters || mobCategory.isFriendly()) +- && (forcedDespawn || !mobCategory.isPersistent()) +- && spawnState.canSpawnForCategory(mobCategory, chunk.getPos())) { +- spawnCategoryForChunk(mobCategory, level, chunk, spawnState::canSpawn, spawnState::afterSpawn); ++ LevelData worlddata = level.getLevelData(); // CraftBukkit - Other mob type spawn tick rate ++ ++ for (int j = 0; j < i; ++j) { ++ MobCategory enumcreaturetype = aenumcreaturetype[j]; ++ // CraftBukkit start - Use per-world spawn limits ++ boolean spawnThisTick = true; ++ int limit = enumcreaturetype.getMaxInstancesPerChunk(); ++ SpawnCategory spawnCategory = CraftSpawnCategory.toBukkit(enumcreaturetype); ++ if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { ++ spawnThisTick = level.ticksPerSpawnCategory.getLong(spawnCategory) != 0 && worlddata.getGameTime() % level.ticksPerSpawnCategory.getLong(spawnCategory) == 0; ++ limit = level.getWorld().getSpawnLimit(spawnCategory); + } ++ ++ if (!spawnThisTick || limit == 0) { ++ continue; ++ } ++ ++ if ((spawnFriendlies || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (forcedDespawn || !enumcreaturetype.isPersistent()) && spawnState.canSpawnForCategory(enumcreaturetype, chunk.getPos(), limit)) { ++ // CraftBukkit end ++ Objects.requireNonNull(spawnState); ++ NaturalSpawner.SpawnPredicate spawnercreature_c = spawnState::canSpawn; ++ ++ Objects.requireNonNull(spawnState); ++ spawnCategoryForChunk(enumcreaturetype, level, chunk, spawnercreature_c, spawnState::afterSpawn); ++ } + } + + level.getProfiler().pop(); + } + +- public static void spawnCategoryForChunk( +- MobCategory category, ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback +- ) { +- BlockPos randomPosWithin = getRandomPosWithin(level, chunk); +- if (randomPosWithin.getY() >= level.getMinBuildHeight() + 1) { +- spawnCategoryForPosition(category, level, chunk, randomPosWithin, filter, callback); ++ public static void spawnCategoryForChunk(MobCategory category, ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback) { ++ BlockPos blockposition = getRandomPosWithin(level, chunk); ++ ++ if (blockposition.getY() >= level.getMinBuildHeight() + 1) { ++ spawnCategoryForPosition(category, level, chunk, blockposition, filter, callback); + } + } + + @VisibleForDebug + public static void spawnCategoryForPosition(MobCategory category, ServerLevel level, BlockPos pos) { +- spawnCategoryForPosition(category, level, level.getChunk(pos), pos, (entityType, spawnPos, chunk) -> true, (mob, chunk) -> { ++ spawnCategoryForPosition(category, level, level.getChunk(pos), pos, (entitytypes, blockposition1, ichunkaccess) -> { ++ return true; ++ }, (entityinsentient, ichunkaccess) -> { + }); + } + +- public static void spawnCategoryForPosition( +- MobCategory category, +- ServerLevel level, +- ChunkAccess chunk, +- BlockPos pos, +- NaturalSpawner.SpawnPredicate filter, +- NaturalSpawner.AfterSpawnCallback callback +- ) { +- StructureManager structureManager = level.structureManager(); +- ChunkGenerator generator = level.getChunkSource().getGenerator(); +- int y = pos.getY(); +- BlockState blockState = chunk.getBlockState(pos); +- if (!blockState.isRedstoneConductor(chunk, pos)) { +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); +- int i = 0; ++ public static void spawnCategoryForPosition(MobCategory category, ServerLevel level, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback) { ++ StructureManager structuremanager = level.structureManager(); ++ ChunkGenerator chunkgenerator = level.getChunkSource().getGenerator(); ++ int i = pos.getY(); ++ IBlockData iblockdata = chunk.getBlockState(pos); + +- for (int i1 = 0; i1 < 3; i1++) { +- int x = pos.getX(); +- int z = pos.getZ(); +- int i2 = 6; +- MobSpawnSettings.SpawnerData spawnerData = null; +- SpawnGroupData spawnGroupData = null; +- int ceil = Mth.ceil(level.random.nextFloat() * 4.0F); +- int i3 = 0; ++ if (!iblockdata.isRedstoneConductor(chunk, pos)) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ int j = 0; ++ int k = 0; + +- for (int i4 = 0; i4 < ceil; i4++) { +- x += level.random.nextInt(6) - level.random.nextInt(6); +- z += level.random.nextInt(6) - level.random.nextInt(6); +- mutableBlockPos.set(x, y, z); +- double d = (double)x + 0.5; +- double d1 = (double)z + 0.5; +- Player nearestPlayer = level.getNearestPlayer(d, (double)y, d1, -1.0, false); +- if (nearestPlayer != null) { +- double d2 = nearestPlayer.distanceToSqr(d, (double)y, d1); +- if (isRightDistanceToPlayerAndSpawnPoint(level, chunk, mutableBlockPos, d2)) { +- if (spawnerData == null) { +- Optional randomSpawnMobAt = getRandomSpawnMobAt( +- level, structureManager, generator, category, level.random, mutableBlockPos +- ); +- if (randomSpawnMobAt.isEmpty()) { +- break; +- } ++ while (k < 3) { ++ int l = pos.getX(); ++ int i1 = pos.getZ(); ++ boolean flag = true; ++ MobSpawnSettings.SpawnerData biomesettingsmobs_c = null; ++ GroupDataEntity groupdataentity = null; ++ int j1 = Mth.ceil(level.random.nextFloat() * 4.0F); ++ int k1 = 0; ++ int l1 = 0; + +- spawnerData = randomSpawnMobAt.get(); +- ceil = spawnerData.minCount + level.random.nextInt(1 + spawnerData.maxCount - spawnerData.minCount); +- } ++ while (true) { ++ if (l1 < j1) { ++ label53: ++ { ++ l += level.random.nextInt(6) - level.random.nextInt(6); ++ i1 += level.random.nextInt(6) - level.random.nextInt(6); ++ blockposition_mutableblockposition.set(l, i, i1); ++ double d0 = (double) l + 0.5D; ++ double d1 = (double) i1 + 0.5D; ++ Player entityhuman = level.getNearestPlayer(d0, (double) i, d1, -1.0D, false); + +- if (isValidSpawnPostitionForType(level, category, structureManager, generator, spawnerData, mutableBlockPos, d2) +- && filter.test(spawnerData.type, mutableBlockPos, chunk)) { +- Mob mobForSpawn = getMobForSpawn(level, spawnerData.type); +- if (mobForSpawn == null) { +- return; +- } ++ if (entityhuman != null) { ++ double d2 = entityhuman.distanceToSqr(d0, (double) i, d1); + +- mobForSpawn.moveTo(d, (double)y, d1, level.random.nextFloat() * 360.0F, 0.0F); +- if (isValidPositionForMob(level, mobForSpawn, d2)) { +- spawnGroupData = mobForSpawn.finalizeSpawn( +- level, level.getCurrentDifficultyAt(mobForSpawn.blockPosition()), MobSpawnType.NATURAL, spawnGroupData, null +- ); +- i++; +- i3++; +- level.addFreshEntityWithPassengers(mobForSpawn); +- callback.run(mobForSpawn, chunk); +- if (i >= mobForSpawn.getMaxSpawnClusterSize()) { +- return; ++ if (isRightDistanceToPlayerAndSpawnPoint(level, chunk, blockposition_mutableblockposition, d2)) { ++ if (biomesettingsmobs_c == null) { ++ Optional optional = getRandomSpawnMobAt(level, structuremanager, chunkgenerator, category, level.random, blockposition_mutableblockposition); ++ ++ if (optional.isEmpty()) { ++ break label53; ++ } ++ ++ biomesettingsmobs_c = (MobSpawnSettings.SpawnerData) optional.get(); ++ j1 = biomesettingsmobs_c.minCount + level.random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount); + } + +- if (mobForSpawn.isMaxGroupSizeReached(i3)) { +- break; ++ if (isValidSpawnPostitionForType(level, category, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2) && filter.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { ++ Mob entityinsentient = getMobForSpawn(level, biomesettingsmobs_c.type); ++ ++ if (entityinsentient == null) { ++ return; ++ } ++ ++ entityinsentient.moveTo(d0, (double) i, d1, level.random.nextFloat() * 360.0F, 0.0F); ++ if (isValidPositionForMob(level, entityinsentient, d2)) { ++ groupdataentity = entityinsentient.finalizeSpawn(level, level.getCurrentDifficultyAt(entityinsentient.blockPosition()), EnumMobSpawn.NATURAL, groupdataentity, (CompoundTag) null); ++ // CraftBukkit start ++ // SPIGOT-7045: Give ocelot babies back their special spawn reason. Note: This is the only modification required as ocelots count as monsters which means they only spawn during normal chunk ticking and do not spawn during chunk generation as starter mobs. ++ level.addFreshEntityWithPassengers(entityinsentient, (entityinsentient instanceof net.minecraft.world.entity.animal.Ocelot && !((org.bukkit.entity.Ageable) entityinsentient.getBukkitEntity()).isAdult()) ? SpawnReason.OCELOT_BABY : SpawnReason.NATURAL); ++ if (!entityinsentient.isRemoved()) { ++ ++j; ++ ++k1; ++ callback.run(entityinsentient, chunk); ++ } ++ // CraftBukkit end ++ if (j >= entityinsentient.getMaxSpawnClusterSize()) { ++ return; ++ } ++ ++ if (entityinsentient.isMaxGroupSizeReached(k1)) { ++ break label53; ++ } ++ } + } + } + } ++ ++ ++l1; ++ continue; + } + } ++ ++ ++k; ++ break; + } + } ++ + } + } + + private static boolean isRightDistanceToPlayerAndSpawnPoint(ServerLevel level, ChunkAccess chunk, BlockPos.MutableBlockPos pos, double distance) { +- return !(distance <= 576.0) +- && !level.getSharedSpawnPos().closerToCenterThan(new Vec3((double)pos.getX() + 0.5, (double)pos.getY(), (double)pos.getZ() + 0.5), 24.0) +- && (Objects.equals(new ChunkPos(pos), chunk.getPos()) || level.isNaturalSpawningAllowed(pos)); ++ return distance <= 576.0D ? false : (level.getSharedSpawnPos().closerToCenterThan(new Vec3((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D), 24.0D) ? false : Objects.equals(new ChunkPos(pos), chunk.getPos()) || level.isNaturalSpawningAllowed((BlockPos) pos)); + } + +- private static boolean isValidSpawnPostitionForType( +- ServerLevel level, +- MobCategory category, +- StructureManager structureManager, +- ChunkGenerator generator, +- MobSpawnSettings.SpawnerData data, +- BlockPos.MutableBlockPos pos, +- double distance +- ) { +- EntityType entityType = data.type; +- if (entityType.getCategory() == MobCategory.MISC) { ++ private static boolean isValidSpawnPostitionForType(ServerLevel level, MobCategory category, StructureManager structureManager, ChunkGenerator generator, MobSpawnSettings.SpawnerData data, BlockPos.MutableBlockPos pos, double distance) { ++ EntityType entitytypes = data.type; ++ ++ if (entitytypes.getCategory() == MobCategory.MISC) { + return false; +- } else if (!entityType.canSpawnFarFromPlayer() +- && distance > (double)(entityType.getCategory().getDespawnDistance() * entityType.getCategory().getDespawnDistance())) { ++ } else if (!entitytypes.canSpawnFarFromPlayer() && distance > (double) (entitytypes.getCategory().getDespawnDistance() * entitytypes.getCategory().getDespawnDistance())) { + return false; +- } else if (entityType.canSummon() && canSpawnMobAt(level, structureManager, generator, category, data, pos)) { +- SpawnPlacements.Type placementType = SpawnPlacements.getPlacementType(entityType); +- return isSpawnPositionOk(placementType, level, pos, entityType) +- && SpawnPlacements.checkSpawnRules(entityType, level, MobSpawnType.NATURAL, pos, level.random) +- && level.noCollision(entityType.getAABB((double)pos.getX() + 0.5, (double)pos.getY(), (double)pos.getZ() + 0.5)); ++ } else if (entitytypes.canSummon() && canSpawnMobAt(level, structureManager, generator, category, data, pos)) { ++ SpawnPlacements.Surface entitypositiontypes_surface = SpawnPlacements.getPlacementType(entitytypes); ++ ++ return !isSpawnPositionOk(entitypositiontypes_surface, level, pos, entitytypes) ? false : (!SpawnPlacements.checkSpawnRules(entitytypes, level, EnumMobSpawn.NATURAL, pos, level.random) ? false : level.noCollision(entitytypes.getAABB((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D))); + } else { + return false; + } +@@ -241,96 +278,83 @@ + @Nullable + private static Mob getMobForSpawn(ServerLevel level, EntityType entityType) { + try { +- Entity var3 = entityType.create(level); +- if (var3 instanceof Mob) { +- return (Mob)var3; ++ Entity entity = entityType.create(level); ++ ++ if (entity instanceof Mob) { ++ Mob entityinsentient = (Mob) entity; ++ ++ return entityinsentient; + } + +- LOGGER.warn("Can't spawn entity of type: {}", BuiltInRegistries.ENTITY_TYPE.getKey(entityType)); +- } catch (Exception var4) { +- LOGGER.warn("Failed to create mob", (Throwable)var4); ++ NaturalSpawner.LOGGER.warn("Can't spawn entity of type: {}", BuiltInRegistries.ENTITY_TYPE.getKey(entityType)); ++ } catch (Exception exception) { ++ NaturalSpawner.LOGGER.warn("Failed to create mob", exception); + } + + return null; + } + + private static boolean isValidPositionForMob(ServerLevel level, Mob mob, double distance) { +- return ( +- !(distance > (double)(mob.getType().getCategory().getDespawnDistance() * mob.getType().getCategory().getDespawnDistance())) +- || !mob.removeWhenFarAway(distance) +- ) +- && mob.checkSpawnRules(level, MobSpawnType.NATURAL) +- && mob.checkSpawnObstruction(level); ++ return distance > (double) (mob.getType().getCategory().getDespawnDistance() * mob.getType().getCategory().getDespawnDistance()) && mob.removeWhenFarAway(distance) ? false : mob.checkSpawnRules(level, EnumMobSpawn.NATURAL) && mob.checkSpawnObstruction(level); + } + +- private static Optional getRandomSpawnMobAt( +- ServerLevel level, StructureManager structureManager, ChunkGenerator generator, MobCategory category, RandomSource random, BlockPos pos +- ) { +- Holder biome = level.getBiome(pos); +- return category == MobCategory.WATER_AMBIENT && biome.is(BiomeTags.REDUCED_WATER_AMBIENT_SPAWNS) && random.nextFloat() < 0.98F +- ? Optional.empty() +- : mobsAt(level, structureManager, generator, category, pos, biome).getRandom(random); ++ private static Optional getRandomSpawnMobAt(ServerLevel level, StructureManager structureManager, ChunkGenerator generator, MobCategory category, RandomSource random, BlockPos pos) { ++ Holder holder = level.getBiome(pos); ++ ++ return category == MobCategory.WATER_AMBIENT && holder.is(BiomeTags.REDUCED_WATER_AMBIENT_SPAWNS) && random.nextFloat() < 0.98F ? Optional.empty() : mobsAt(level, structureManager, generator, category, pos, holder).getRandom(random); + } + +- private static boolean canSpawnMobAt( +- ServerLevel level, StructureManager structureManager, ChunkGenerator generator, MobCategory category, MobSpawnSettings.SpawnerData data, BlockPos pos +- ) { +- return mobsAt(level, structureManager, generator, category, pos, null).unwrap().contains(data); ++ private static boolean canSpawnMobAt(ServerLevel level, StructureManager structureManager, ChunkGenerator generator, MobCategory category, MobSpawnSettings.SpawnerData data, BlockPos pos) { ++ return mobsAt(level, structureManager, generator, category, pos, (Holder) null).unwrap().contains(data); + } + +- private static WeightedRandomList mobsAt( +- ServerLevel level, StructureManager structureManager, ChunkGenerator generator, MobCategory category, BlockPos pos, @Nullable Holder biome +- ) { +- return isInNetherFortressBounds(pos, level, category, structureManager) +- ? NetherFortressStructure.FORTRESS_ENEMIES +- : generator.getMobsAt(biome != null ? biome : level.getBiome(pos), structureManager, category, pos); ++ private static WeightedRandomList mobsAt(ServerLevel level, StructureManager structureManager, ChunkGenerator generator, MobCategory category, BlockPos pos, @Nullable Holder biome) { ++ return isInNetherFortressBounds(pos, level, category, structureManager) ? NetherFortressStructure.FORTRESS_ENEMIES : generator.getMobsAt(biome != null ? biome : level.getBiome(pos), structureManager, category, pos); + } + + public static boolean isInNetherFortressBounds(BlockPos pos, ServerLevel level, MobCategory category, StructureManager structureManager) { + if (category == MobCategory.MONSTER && level.getBlockState(pos.below()).is(Blocks.NETHER_BRICKS)) { +- Structure structure = structureManager.registryAccess().registryOrThrow(Registries.STRUCTURE).get(BuiltinStructures.FORTRESS); +- return structure != null && structureManager.getStructureAt(pos, structure).isValid(); ++ Structure structure = (Structure) structureManager.registryAccess().registryOrThrow(Registries.STRUCTURE).get(BuiltinStructures.FORTRESS); ++ ++ return structure == null ? false : structureManager.getStructureAt(pos, structure).isValid(); + } else { + return false; + } + } + + private static BlockPos getRandomPosWithin(Level level, LevelChunk chunk) { +- ChunkPos pos = chunk.getPos(); +- int i = pos.getMinBlockX() + level.random.nextInt(16); +- int i1 = pos.getMinBlockZ() + level.random.nextInt(16); +- int i2 = chunk.getHeight(Heightmap.Types.WORLD_SURFACE, i, i1) + 1; +- int i3 = Mth.randomBetweenInclusive(level.random, level.getMinBuildHeight(), i2); +- return new BlockPos(i, i3, i1); ++ ChunkPos chunkcoordintpair = chunk.getPos(); ++ int i = chunkcoordintpair.getMinBlockX() + level.random.nextInt(16); ++ int j = chunkcoordintpair.getMinBlockZ() + level.random.nextInt(16); ++ int k = chunk.getHeight(Heightmap.Types.WORLD_SURFACE, i, j) + 1; ++ int l = Mth.randomBetweenInclusive(level.random, level.getMinBuildHeight(), k); ++ ++ return new BlockPos(i, l, j); + } + +- public static boolean isValidEmptySpawnBlock(BlockGetter block, BlockPos pos, BlockState blockState, FluidState fluidState, EntityType entityType) { +- return !blockState.isCollisionShapeFullBlock(block, pos) +- && !blockState.isSignalSource() +- && fluidState.isEmpty() +- && !blockState.is(BlockTags.PREVENT_MOB_SPAWNING_INSIDE) +- && !entityType.isBlockDangerous(blockState); ++ public static boolean isValidEmptySpawnBlock(BlockGetter block, BlockPos pos, IBlockData blockState, FluidState fluidState, EntityType entityType) { ++ return blockState.isCollisionShapeFullBlock(block, pos) ? false : (blockState.isSignalSource() ? false : (!fluidState.isEmpty() ? false : (blockState.is(BlockTags.PREVENT_MOB_SPAWNING_INSIDE) ? false : !entityType.isBlockDangerous(blockState)))); + } + +- public static boolean isSpawnPositionOk(SpawnPlacements.Type placeType, LevelReader level, BlockPos pos, @Nullable EntityType entityType) { +- if (placeType == SpawnPlacements.Type.NO_RESTRICTIONS) { ++ public static boolean isSpawnPositionOk(SpawnPlacements.Surface placeType, LevelReader level, BlockPos pos, @Nullable EntityType entityType) { ++ if (placeType == SpawnPlacements.Surface.NO_RESTRICTIONS) { + return true; + } else if (entityType != null && level.getWorldBorder().isWithinBounds(pos)) { +- BlockState blockState = level.getBlockState(pos); +- FluidState fluidState = level.getFluidState(pos); +- BlockPos blockPos = pos.above(); +- BlockPos blockPos1 = pos.below(); ++ IBlockData iblockdata = level.getBlockState(pos); ++ FluidState fluid = level.getFluidState(pos); ++ BlockPos blockposition1 = pos.above(); ++ BlockPos blockposition2 = pos.below(); ++ + switch (placeType) { + case IN_WATER: +- return fluidState.is(FluidTags.WATER) && !level.getBlockState(blockPos).isRedstoneConductor(level, blockPos); ++ return fluid.is(FluidTags.WATER) && !level.getBlockState(blockposition1).isRedstoneConductor(level, blockposition1); + case IN_LAVA: +- return fluidState.is(FluidTags.LAVA); ++ return fluid.is(FluidTags.LAVA); + case ON_GROUND: + default: +- BlockState blockState1 = level.getBlockState(blockPos1); +- return blockState1.isValidSpawn(level, blockPos1, entityType) +- && isValidEmptySpawnBlock(level, pos, blockState, fluidState, entityType) +- && isValidEmptySpawnBlock(level, blockPos, level.getBlockState(blockPos), level.getFluidState(blockPos), entityType); ++ IBlockData iblockdata1 = level.getBlockState(blockposition2); ++ ++ return !iblockdata1.isValidSpawn(level, blockposition2, entityType) ? false : isValidEmptySpawnBlock(level, pos, iblockdata, fluid, entityType) && isValidEmptySpawnBlock(level, blockposition1, level.getBlockState(blockposition1), level.getFluidState(blockposition1), entityType); + } + } else { + return false; +@@ -338,49 +362,46 @@ + } + + public static void spawnMobsForChunkGeneration(ServerLevelAccessor levelAccessor, Holder biome, ChunkPos chunkPos, RandomSource random) { +- MobSpawnSettings mobSettings = biome.value().getMobSettings(); +- WeightedRandomList mobs = mobSettings.getMobs(MobCategory.CREATURE); +- if (!mobs.isEmpty()) { +- int minBlockX = chunkPos.getMinBlockX(); +- int minBlockZ = chunkPos.getMinBlockZ(); ++ MobSpawnSettings biomesettingsmobs = ((Biome) biome.value()).getMobSettings(); ++ WeightedRandomList weightedrandomlist = biomesettingsmobs.getMobs(MobCategory.CREATURE); + +- while (random.nextFloat() < mobSettings.getCreatureProbability()) { +- Optional random1 = mobs.getRandom(random); +- if (!random1.isEmpty()) { +- MobSpawnSettings.SpawnerData spawnerData = random1.get(); +- int i = spawnerData.minCount + random.nextInt(1 + spawnerData.maxCount - spawnerData.minCount); +- SpawnGroupData spawnGroupData = null; +- int i1 = minBlockX + random.nextInt(16); +- int i2 = minBlockZ + random.nextInt(16); +- int i3 = i1; +- int i4 = i2; ++ if (!weightedrandomlist.isEmpty()) { ++ int i = chunkPos.getMinBlockX(); ++ int j = chunkPos.getMinBlockZ(); + +- for (int i5 = 0; i5 < i; i5++) { ++ while (random.nextFloat() < biomesettingsmobs.getCreatureProbability()) { ++ Optional optional = weightedrandomlist.getRandom(random); ++ ++ if (!optional.isEmpty()) { ++ MobSpawnSettings.SpawnerData biomesettingsmobs_c = (MobSpawnSettings.SpawnerData) optional.get(); ++ int k = biomesettingsmobs_c.minCount + random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount); ++ GroupDataEntity groupdataentity = null; ++ int l = i + random.nextInt(16); ++ int i1 = j + random.nextInt(16); ++ int j1 = l; ++ int k1 = i1; ++ ++ for (int l1 = 0; l1 < k; ++l1) { + boolean flag = false; + +- for (int i6 = 0; !flag && i6 < 4; i6++) { +- BlockPos topNonCollidingPos = getTopNonCollidingPos(levelAccessor, spawnerData.type, i1, i2); +- if (spawnerData.type.canSummon() +- && isSpawnPositionOk(SpawnPlacements.getPlacementType(spawnerData.type), levelAccessor, topNonCollidingPos, spawnerData.type)) { +- float width = spawnerData.type.getWidth(); +- double d = Mth.clamp((double)i1, (double)minBlockX + (double)width, (double)minBlockX + 16.0 - (double)width); +- double d1 = Mth.clamp((double)i2, (double)minBlockZ + (double)width, (double)minBlockZ + 16.0 - (double)width); +- if (!levelAccessor.noCollision(spawnerData.type.getAABB(d, (double)topNonCollidingPos.getY(), d1)) +- || !SpawnPlacements.checkSpawnRules( +- spawnerData.type, +- levelAccessor, +- MobSpawnType.CHUNK_GENERATION, +- BlockPos.containing(d, (double)topNonCollidingPos.getY(), d1), +- levelAccessor.getRandom() +- )) { ++ for (int i2 = 0; !flag && i2 < 4; ++i2) { ++ BlockPos blockposition = getTopNonCollidingPos(levelAccessor, biomesettingsmobs_c.type, l, i1); ++ ++ if (biomesettingsmobs_c.type.canSummon() && isSpawnPositionOk(SpawnPlacements.getPlacementType(biomesettingsmobs_c.type), levelAccessor, blockposition, biomesettingsmobs_c.type)) { ++ float f = biomesettingsmobs_c.type.getWidth(); ++ double d0 = Mth.clamp((double) l, (double) i + (double) f, (double) i + 16.0D - (double) f); ++ double d1 = Mth.clamp((double) i1, (double) j + (double) f, (double) j + 16.0D - (double) f); ++ ++ if (!levelAccessor.noCollision(biomesettingsmobs_c.type.getAABB(d0, (double) blockposition.getY(), d1)) || !SpawnPlacements.checkSpawnRules(biomesettingsmobs_c.type, levelAccessor, EnumMobSpawn.CHUNK_GENERATION, BlockPos.containing(d0, (double) blockposition.getY(), d1), levelAccessor.getRandom())) { + continue; + } + + Entity entity; ++ + try { +- entity = spawnerData.type.create(levelAccessor.getLevel()); +- } catch (Exception var27) { +- LOGGER.warn("Failed to create mob", (Throwable)var27); ++ entity = biomesettingsmobs_c.type.create(levelAccessor.getLevel()); ++ } catch (Exception exception) { ++ NaturalSpawner.LOGGER.warn("Failed to create mob", exception); + continue; + } + +@@ -388,76 +409,64 @@ + continue; + } + +- entity.moveTo(d, (double)topNonCollidingPos.getY(), d1, random.nextFloat() * 360.0F, 0.0F); +- if (entity instanceof Mob mob +- && mob.checkSpawnRules(levelAccessor, MobSpawnType.CHUNK_GENERATION) +- && mob.checkSpawnObstruction(levelAccessor)) { +- spawnGroupData = mob.finalizeSpawn( +- levelAccessor, +- levelAccessor.getCurrentDifficultyAt(mob.blockPosition()), +- MobSpawnType.CHUNK_GENERATION, +- spawnGroupData, +- null +- ); +- levelAccessor.addFreshEntityWithPassengers(mob); +- flag = true; ++ entity.moveTo(d0, (double) blockposition.getY(), d1, random.nextFloat() * 360.0F, 0.0F); ++ if (entity instanceof Mob) { ++ Mob entityinsentient = (Mob) entity; ++ ++ if (entityinsentient.checkSpawnRules(levelAccessor, EnumMobSpawn.CHUNK_GENERATION) && entityinsentient.checkSpawnObstruction(levelAccessor)) { ++ groupdataentity = entityinsentient.finalizeSpawn(levelAccessor, levelAccessor.getCurrentDifficultyAt(entityinsentient.blockPosition()), EnumMobSpawn.CHUNK_GENERATION, groupdataentity, (CompoundTag) null); ++ levelAccessor.addFreshEntityWithPassengers(entityinsentient, SpawnReason.CHUNK_GEN); // CraftBukkit ++ flag = true; ++ } + } + } + +- i1 += random.nextInt(5) - random.nextInt(5); ++ l += random.nextInt(5) - random.nextInt(5); + +- for (i2 += random.nextInt(5) - random.nextInt(5); +- i1 < minBlockX || i1 >= minBlockX + 16 || i2 < minBlockZ || i2 >= minBlockZ + 16; +- i2 = i4 + random.nextInt(5) - random.nextInt(5) +- ) { +- i1 = i3 + random.nextInt(5) - random.nextInt(5); ++ for (i1 += random.nextInt(5) - random.nextInt(5); l < i || l >= i + 16 || i1 < j || i1 >= j + 16; i1 = k1 + random.nextInt(5) - random.nextInt(5)) { ++ l = j1 + random.nextInt(5) - random.nextInt(5); + } + } + } + } + } ++ + } + } + + private static BlockPos getTopNonCollidingPos(LevelReader level, EntityType entityType, int x, int z) { +- int height = level.getHeight(SpawnPlacements.getHeightmapType(entityType), x, z); +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(x, height, z); ++ int k = level.getHeight(SpawnPlacements.getHeightmapType(entityType), x, z); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(x, k, z); ++ + if (level.dimensionType().hasCeiling()) { + do { +- mutableBlockPos.move(Direction.DOWN); +- } while (!level.getBlockState(mutableBlockPos).isAir()); ++ blockposition_mutableblockposition.move(Direction.DOWN); ++ } while (!level.getBlockState(blockposition_mutableblockposition).isAir()); + + do { +- mutableBlockPos.move(Direction.DOWN); +- } while (level.getBlockState(mutableBlockPos).isAir() && mutableBlockPos.getY() > level.getMinBuildHeight()); ++ blockposition_mutableblockposition.move(Direction.DOWN); ++ } while (level.getBlockState(blockposition_mutableblockposition).isAir() && blockposition_mutableblockposition.getY() > level.getMinBuildHeight()); + } + +- if (SpawnPlacements.getPlacementType(entityType) == SpawnPlacements.Type.ON_GROUND) { +- BlockPos blockPos = mutableBlockPos.below(); +- if (level.getBlockState(blockPos).isPathfindable(level, blockPos, PathComputationType.LAND)) { +- return blockPos; ++ if (SpawnPlacements.getPlacementType(entityType) == SpawnPlacements.Surface.ON_GROUND) { ++ BlockPos blockposition = blockposition_mutableblockposition.below(); ++ ++ if (level.getBlockState(blockposition).isPathfindable(level, blockposition, PathMode.LAND)) { ++ return blockposition; + } + } + +- return mutableBlockPos.immutable(); ++ return blockposition_mutableblockposition.immutable(); + } + + @FunctionalInterface +- public interface AfterSpawnCallback { +- void run(Mob mob, ChunkAccess chunk); +- } +- +- @FunctionalInterface + public interface ChunkGetter { ++ + void query(long chunkPos, Consumer consumer); + } + +- @FunctionalInterface +- public interface SpawnPredicate { +- boolean test(EntityType entityType, BlockPos pos, ChunkAccess chunk); +- } +- + public static class SpawnState { ++ + private final int spawnableChunkCount; + private final Object2IntOpenHashMap mobCategoryCounts; + private final PotentialCalculator spawnPotential; +@@ -469,12 +478,7 @@ + private EntityType lastCheckedType; + private double lastCharge; + +- SpawnState( +- int spawnableChunkCount, +- Object2IntOpenHashMap mobCategoryCounts, +- PotentialCalculator spawnPotential, +- LocalMobCapCalculator localMobCapCalculator +- ) { ++ SpawnState(int spawnableChunkCount, Object2IntOpenHashMap mobCategoryCounts, PotentialCalculator spawnPotential, LocalMobCapCalculator localMobCapCalculator) { + this.spawnableChunkCount = spawnableChunkCount; + this.mobCategoryCounts = mobCategoryCounts; + this.spawnPotential = spawnPotential; +@@ -485,37 +489,43 @@ + private boolean canSpawn(EntityType entityType, BlockPos pos, ChunkAccess chunk) { + this.lastCheckedPos = pos; + this.lastCheckedType = entityType; +- MobSpawnSettings.MobSpawnCost mobSpawnCost = NaturalSpawner.getRoughBiome(pos, chunk).getMobSettings().getMobSpawnCost(entityType); +- if (mobSpawnCost == null) { +- this.lastCharge = 0.0; ++ MobSpawnSettings.MobSpawnCost biomesettingsmobs_b = NaturalSpawner.getRoughBiome(pos, chunk).getMobSettings().getMobSpawnCost(entityType); ++ ++ if (biomesettingsmobs_b == null) { ++ this.lastCharge = 0.0D; + return true; + } else { +- double d = mobSpawnCost.charge(); +- this.lastCharge = d; +- double potentialEnergyChange = this.spawnPotential.getPotentialEnergyChange(pos, d); +- return potentialEnergyChange <= mobSpawnCost.energyBudget(); ++ double d0 = biomesettingsmobs_b.charge(); ++ ++ this.lastCharge = d0; ++ double d1 = this.spawnPotential.getPotentialEnergyChange(pos, d0); ++ ++ return d1 <= biomesettingsmobs_b.energyBudget(); + } + } + + private void afterSpawn(Mob mob, ChunkAccess chunk) { +- EntityType type = mob.getType(); +- BlockPos blockPos = mob.blockPosition(); +- double d; +- if (blockPos.equals(this.lastCheckedPos) && type == this.lastCheckedType) { +- d = this.lastCharge; ++ EntityType entitytypes = mob.getType(); ++ BlockPos blockposition = mob.blockPosition(); ++ double d0; ++ ++ if (blockposition.equals(this.lastCheckedPos) && entitytypes == this.lastCheckedType) { ++ d0 = this.lastCharge; + } else { +- MobSpawnSettings.MobSpawnCost mobSpawnCost = NaturalSpawner.getRoughBiome(blockPos, chunk).getMobSettings().getMobSpawnCost(type); +- if (mobSpawnCost != null) { +- d = mobSpawnCost.charge(); ++ MobSpawnSettings.MobSpawnCost biomesettingsmobs_b = NaturalSpawner.getRoughBiome(blockposition, chunk).getMobSettings().getMobSpawnCost(entitytypes); ++ ++ if (biomesettingsmobs_b != null) { ++ d0 = biomesettingsmobs_b.charge(); + } else { +- d = 0.0; ++ d0 = 0.0D; + } + } + +- this.spawnPotential.addCharge(blockPos, d); +- MobCategory category = type.getCategory(); +- this.mobCategoryCounts.addTo(category, 1); +- this.localMobCapCalculator.addMob(new ChunkPos(blockPos), category); ++ this.spawnPotential.addCharge(blockposition, d0); ++ MobCategory enumcreaturetype = entitytypes.getCategory(); ++ ++ this.mobCategoryCounts.addTo(enumcreaturetype, 1); ++ this.localMobCapCalculator.addMob(new ChunkPos(blockposition), enumcreaturetype); + } + + public int getSpawnableChunkCount() { +@@ -526,9 +536,24 @@ + return this.unmodifiableMobCategoryCounts; + } + +- boolean canSpawnForCategory(MobCategory category, ChunkPos pos) { +- int i = category.getMaxInstancesPerChunk() * this.spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER; +- return this.mobCategoryCounts.getInt(category) < i && this.localMobCapCalculator.canSpawn(category, pos); ++ // CraftBukkit start ++ boolean canSpawnForCategory(MobCategory enumcreaturetype, ChunkPos chunkcoordintpair, int limit) { ++ int i = limit * this.spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER; ++ // CraftBukkit end ++ ++ return this.mobCategoryCounts.getInt(enumcreaturetype) >= i ? false : this.localMobCapCalculator.canSpawn(enumcreaturetype, chunkcoordintpair); + } + } ++ ++ @FunctionalInterface ++ public interface SpawnPredicate { ++ ++ boolean test(EntityType entityType, BlockPos pos, ChunkAccess chunk); ++ } ++ ++ @FunctionalInterface ++ public interface AfterSpawnCallback { ++ ++ void run(Mob mob, ChunkAccess chunk); ++ } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/ServerLevelAccessor.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/ServerLevelAccessor.java.patch new file mode 100644 index 0000000000..9243e29def --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/ServerLevelAccessor.java.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/world/level/ServerLevelAccessor.java ++++ b/net/minecraft/world/level/ServerLevelAccessor.java +@@ -4,9 +4,21 @@ + import net.minecraft.world.entity.Entity; + + public interface ServerLevelAccessor extends LevelAccessor { ++ + ServerLevel getLevel(); + + default void addFreshEntityWithPassengers(Entity entity) { +- entity.getSelfAndPassengers().forEach(this::addFreshEntity); ++ // CraftBukkit start ++ this.addFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); + } ++ ++ default void addFreshEntityWithPassengers(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ entity.getSelfAndPassengers().forEach((e) -> this.addFreshEntity(e, reason)); ++ } ++ ++ @Override ++ default ServerLevel getMinecraftWorld() { ++ return getLevel(); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/AbstractCandleBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/AbstractCandleBlock.java.patch new file mode 100644 index 0000000000..0dc1410719 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/AbstractCandleBlock.java.patch @@ -0,0 +1,148 @@ +--- a/net/minecraft/world/level/block/AbstractCandleBlock.java ++++ b/net/minecraft/world/level/block/AbstractCandleBlock.java +@@ -9,6 +9,7 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.tags.BlockTags; + import net.minecraft.util.RandomSource; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.Projectile; + import net.minecraft.world.item.ItemStack; +@@ -16,7 +17,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.gameevent.GameEvent; +@@ -24,6 +25,7 @@ + import net.minecraft.world.phys.Vec3; + + public abstract class AbstractCandleBlock extends Block { ++ + public static final int LIGHT_PER_CANDLE = 3; + public static final BooleanProperty LIT = BlockStateProperties.LIT; + +@@ -34,84 +36,73 @@ + super(properties); + } + +- protected abstract Iterable getParticleOffsets(BlockState state); ++ protected abstract Iterable getParticleOffsets(IBlockData state); + +- public static boolean isLit(BlockState state) { +- return state.hasProperty(LIT) && (state.is(BlockTags.CANDLES) || state.is(BlockTags.CANDLE_CAKES)) && state.getValue(LIT); ++ public static boolean isLit(IBlockData state) { ++ return state.hasProperty(AbstractCandleBlock.LIT) && (state.is(BlockTags.CANDLES) || state.is(BlockTags.CANDLE_CAKES)) && (Boolean) state.getValue(AbstractCandleBlock.LIT); + } + + @Override +- public void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) { ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { + if (!level.isClientSide && projectile.isOnFire() && this.canBeLit(state)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, hit.getBlockPos(), projectile).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + setLit(level, state, hit.getBlockPos(), true); + } ++ + } + +- protected boolean canBeLit(BlockState state) { +- return !state.getValue(LIT); ++ protected boolean canBeLit(IBlockData state) { ++ return !(Boolean) state.getValue(AbstractCandleBlock.LIT); + } + + @Override +- public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { +- if (state.getValue(LIT)) { +- this.getParticleOffsets(state) +- .forEach(offset -> addParticlesAndSound(level, offset.add((double)pos.getX(), (double)pos.getY(), (double)pos.getZ()), random)); ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(AbstractCandleBlock.LIT)) { ++ this.getParticleOffsets(state).forEach((vec3d) -> { ++ addParticlesAndSound(level, vec3d.add((double) pos.getX(), (double) pos.getY(), (double) pos.getZ()), random); ++ }); + } + } + + private static void addParticlesAndSound(Level level, Vec3 offset, RandomSource random) { +- float randomFloat = random.nextFloat(); +- if (randomFloat < 0.3F) { +- level.addParticle(ParticleTypes.SMOKE, offset.x, offset.y, offset.z, 0.0, 0.0, 0.0); +- if (randomFloat < 0.17F) { +- level.playLocalSound( +- offset.x + 0.5, +- offset.y + 0.5, +- offset.z + 0.5, +- SoundEvents.CANDLE_AMBIENT, +- SoundSource.BLOCKS, +- 1.0F + random.nextFloat(), +- random.nextFloat() * 0.7F + 0.3F, +- false +- ); ++ float f = random.nextFloat(); ++ ++ if (f < 0.3F) { ++ level.addParticle(ParticleTypes.SMOKE, offset.x, offset.y, offset.z, 0.0D, 0.0D, 0.0D); ++ if (f < 0.17F) { ++ level.playLocalSound(offset.x + 0.5D, offset.y + 0.5D, offset.z + 0.5D, SoundEvents.CANDLE_AMBIENT, SoundSource.BLOCKS, 1.0F + random.nextFloat(), random.nextFloat() * 0.7F + 0.3F, false); + } + } + +- level.addParticle(ParticleTypes.SMALL_FLAME, offset.x, offset.y, offset.z, 0.0, 0.0, 0.0); ++ level.addParticle(ParticleTypes.SMALL_FLAME, offset.x, offset.y, offset.z, 0.0D, 0.0D, 0.0D); + } + +- public static void extinguish(@Nullable Player player, BlockState state, LevelAccessor level, BlockPos pos) { ++ public static void extinguish(@Nullable Player player, IBlockData state, LevelAccessor level, BlockPos pos) { + setLit(level, state, pos, false); + if (state.getBlock() instanceof AbstractCandleBlock) { +- ((AbstractCandleBlock)state.getBlock()) +- .getParticleOffsets(state) +- .forEach( +- offset -> level.addParticle( +- ParticleTypes.SMOKE, +- (double)pos.getX() + offset.x(), +- (double)pos.getY() + offset.y(), +- (double)pos.getZ() + offset.z(), +- 0.0, +- 0.1F, +- 0.0 +- ) +- ); ++ ((AbstractCandleBlock) state.getBlock()).getParticleOffsets(state).forEach((vec3d) -> { ++ level.addParticle(ParticleTypes.SMOKE, (double) pos.getX() + vec3d.x(), (double) pos.getY() + vec3d.y(), (double) pos.getZ() + vec3d.z(), 0.0D, 0.10000000149011612D, 0.0D); ++ }); + } + +- level.playSound(null, pos, SoundEvents.CANDLE_EXTINGUISH, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent(player, GameEvent.BLOCK_CHANGE, pos); ++ level.playSound((Player) null, pos, SoundEvents.CANDLE_EXTINGUISH, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.gameEvent((Entity) player, GameEvent.BLOCK_CHANGE, pos); + } + +- private static void setLit(LevelAccessor level, BlockState state, BlockPos pos, boolean lit) { +- level.setBlock(pos, state.setValue(LIT, Boolean.valueOf(lit)), 11); ++ private static void setLit(LevelAccessor level, IBlockData state, BlockPos pos, boolean lit) { ++ level.setBlock(pos, (IBlockData) state.setValue(AbstractCandleBlock.LIT, lit), 11); + } + + @Override +- public void onExplosionHit(BlockState blockState, Level level, BlockPos blockPos, Explosion explosion, BiConsumer biConsumer) { +- if (explosion.getBlockInteraction() == Explosion.BlockInteraction.TRIGGER_BLOCK && !level.isClientSide() && blockState.getValue(LIT)) { +- extinguish(null, blockState, level, blockPos); ++ public void onExplosionHit(IBlockData iblockdata, Level world, BlockPos blockposition, Explosion explosion, BiConsumer biconsumer) { ++ if (explosion.getBlockInteraction() == Explosion.Effect.TRIGGER_BLOCK && !world.isClientSide() && (Boolean) iblockdata.getValue(AbstractCandleBlock.LIT)) { ++ extinguish((Player) null, iblockdata, world, blockposition); + } + +- super.onExplosionHit(blockState, level, blockPos, explosion, biConsumer); ++ super.onExplosionHit(iblockdata, world, blockposition, explosion, biconsumer); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/BambooSaplingBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/BambooSaplingBlock.java.patch new file mode 100644 index 0000000000..6998c5134c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/BambooSaplingBlock.java.patch @@ -0,0 +1,100 @@ +--- a/net/minecraft/world/level/block/BambooSaplingBlock.java ++++ b/net/minecraft/world/level/block/BambooSaplingBlock.java +@@ -15,20 +15,21 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BambooLeaves; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; + + public class BambooSaplingBlock extends Block implements BonemealableBlock { ++ + public static final MapCodec CODEC = simpleCodec(BambooSaplingBlock::new); + protected static final float SAPLING_AABB_OFFSET = 4.0F; +- protected static final VoxelShape SAPLING_SHAPE = Block.box(4.0, 0.0, 4.0, 12.0, 12.0, 12.0); ++ protected static final VoxelShape SAPLING_SHAPE = Block.box(4.0D, 0.0D, 4.0D, 12.0D, 12.0D, 12.0D); + + @Override + public MapCodec codec() { +- return CODEC; ++ return BambooSaplingBlock.CODEC; + } + + public BambooSaplingBlock(BlockBehaviour.Properties properties) { +@@ -36,25 +37,27 @@ + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- Vec3 offset = state.getOffset(level, pos); +- return SAPLING_SHAPE.move(offset.x, offset.y, offset.z); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ Vec3 vec3d = state.getOffset(level, pos); ++ ++ return BambooSaplingBlock.SAPLING_SHAPE.move(vec3d.x, vec3d.y, vec3d.z); + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (random.nextInt(3) == 0 && level.isEmptyBlock(pos.above()) && level.getRawBrightness(pos.above(), 0) >= 9) { + this.growBamboo(level, pos); + } ++ + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { + return level.getBlockState(pos.below()).is(BlockTags.BAMBOO_PLANTABLE_ON); + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { + if (!state.canSurvive(level, currentPos)) { + return Blocks.AIR.defaultBlockState(); + } else { +@@ -67,31 +70,31 @@ + } + + @Override +- public ItemStack getCloneItemStack(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { ++ public ItemStack getCloneItemStack(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { + return new ItemStack(Items.BAMBOO); + } + + @Override +- public boolean isValidBonemealTarget(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { +- return levelReader.getBlockState(blockPos.above()).isAir(); ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ return iworldreader.getBlockState(blockposition.above()).isAir(); + } + + @Override +- public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, BlockState state) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return true; + } + + @Override +- public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) { ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { + this.growBamboo(level, pos); + } + + @Override +- public float getDestroyProgress(BlockState state, Player player, BlockGetter level, BlockPos pos) { ++ public float getDestroyProgress(IBlockData state, Player player, BlockGetter level, BlockPos pos) { + return player.getMainHandItem().getItem() instanceof SwordItem ? 1.0F : super.getDestroyProgress(state, player, level, pos); + } + + protected void growBamboo(Level level, BlockPos state) { +- level.setBlock(state.above(), Blocks.BAMBOO.defaultBlockState().setValue(BambooStalkBlock.LEAVES, BambooLeaves.SMALL), 3); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, state, state.above(), (IBlockData) Blocks.BAMBOO.defaultBlockState().setValue(BambooStalkBlock.LEAVES, BambooLeaves.SMALL), 3); // CraftBukkit - BlockSpreadEvent + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/BambooStalkBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/BambooStalkBlock.java.patch new file mode 100644 index 0000000000..5759954f8e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/BambooStalkBlock.java.patch @@ -0,0 +1,330 @@ +--- a/net/minecraft/world/level/block/BambooStalkBlock.java ++++ b/net/minecraft/world/level/block/BambooStalkBlock.java +@@ -15,26 +15,27 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BambooLeaves; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.EnumProperty; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.level.material.FluidState; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; + + public class BambooStalkBlock extends Block implements BonemealableBlock { ++ + public static final MapCodec CODEC = simpleCodec(BambooStalkBlock::new); + protected static final float SMALL_LEAVES_AABB_OFFSET = 3.0F; + protected static final float LARGE_LEAVES_AABB_OFFSET = 5.0F; + protected static final float COLLISION_AABB_OFFSET = 1.5F; +- protected static final VoxelShape SMALL_SHAPE = Block.box(5.0, 0.0, 5.0, 11.0, 16.0, 11.0); +- protected static final VoxelShape LARGE_SHAPE = Block.box(3.0, 0.0, 3.0, 13.0, 16.0, 13.0); +- protected static final VoxelShape COLLISION_SHAPE = Block.box(6.5, 0.0, 6.5, 9.5, 16.0, 9.5); ++ protected static final VoxelShape SMALL_SHAPE = Block.box(5.0D, 0.0D, 5.0D, 11.0D, 16.0D, 11.0D); ++ protected static final VoxelShape LARGE_SHAPE = Block.box(3.0D, 0.0D, 3.0D, 13.0D, 16.0D, 13.0D); ++ protected static final VoxelShape COLLISION_SHAPE = Block.box(6.5D, 0.0D, 6.5D, 9.5D, 16.0D, 9.5D); + public static final IntegerProperty AGE = BlockStateProperties.AGE_1; + public static final EnumProperty LEAVES = BlockStateProperties.BAMBOO_LEAVES; + public static final IntegerProperty STAGE = BlockStateProperties.STAGE; +@@ -46,68 +47,70 @@ + + @Override + public MapCodec codec() { +- return CODEC; ++ return BambooStalkBlock.CODEC; + } + + public BambooStalkBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState( +- this.stateDefinition.any().setValue(AGE, Integer.valueOf(0)).setValue(LEAVES, BambooLeaves.NONE).setValue(STAGE, Integer.valueOf(0)) +- ); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(BambooStalkBlock.AGE, 0)).setValue(BambooStalkBlock.LEAVES, BambooLeaves.NONE)).setValue(BambooStalkBlock.STAGE, 0)); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(AGE, LEAVES, STAGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(BambooStalkBlock.AGE, BambooStalkBlock.LEAVES, BambooStalkBlock.STAGE); + } + + @Override +- public boolean propagatesSkylightDown(BlockState state, BlockGetter level, BlockPos pos) { ++ public boolean propagatesSkylightDown(IBlockData state, BlockGetter level, BlockPos pos) { + return true; + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- VoxelShape voxelShape = state.getValue(LEAVES) == BambooLeaves.LARGE ? LARGE_SHAPE : SMALL_SHAPE; +- Vec3 offset = state.getOffset(level, pos); +- return voxelShape.move(offset.x, offset.y, offset.z); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ VoxelShape voxelshape = state.getValue(BambooStalkBlock.LEAVES) == BambooLeaves.LARGE ? BambooStalkBlock.LARGE_SHAPE : BambooStalkBlock.SMALL_SHAPE; ++ Vec3 vec3d = state.getOffset(level, pos); ++ ++ return voxelshape.move(vec3d.x, vec3d.y, vec3d.z); + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + + @Override +- public VoxelShape getCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- Vec3 offset = state.getOffset(level, pos); +- return COLLISION_SHAPE.move(offset.x, offset.y, offset.z); ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ Vec3 vec3d = state.getOffset(level, pos); ++ ++ return BambooStalkBlock.COLLISION_SHAPE.move(vec3d.x, vec3d.y, vec3d.z); + } + + @Override +- public boolean isCollisionShapeFullBlock(BlockState state, BlockGetter level, BlockPos pos) { ++ public boolean isCollisionShapeFullBlock(IBlockData state, BlockGetter level, BlockPos pos) { + return false; + } + + @Nullable + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- FluidState fluidState = context.getLevel().getFluidState(context.getClickedPos()); +- if (!fluidState.isEmpty()) { ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ FluidState fluid = context.getLevel().getFluidState(context.getClickedPos()); ++ ++ if (!fluid.isEmpty()) { + return null; + } else { +- BlockState blockState = context.getLevel().getBlockState(context.getClickedPos().below()); +- if (blockState.is(BlockTags.BAMBOO_PLANTABLE_ON)) { +- if (blockState.is(Blocks.BAMBOO_SAPLING)) { +- return this.defaultBlockState().setValue(AGE, Integer.valueOf(0)); +- } else if (blockState.is(Blocks.BAMBOO)) { +- int i = blockState.getValue(AGE) > 0 ? 1 : 0; +- return this.defaultBlockState().setValue(AGE, Integer.valueOf(i)); ++ IBlockData iblockdata = context.getLevel().getBlockState(context.getClickedPos().below()); ++ ++ if (iblockdata.is(BlockTags.BAMBOO_PLANTABLE_ON)) { ++ if (iblockdata.is(Blocks.BAMBOO_SAPLING)) { ++ return (IBlockData) this.defaultBlockState().setValue(BambooStalkBlock.AGE, 0); ++ } else if (iblockdata.is(Blocks.BAMBOO)) { ++ int i = (Integer) iblockdata.getValue(BambooStalkBlock.AGE) > 0 ? 1 : 0; ++ ++ return (IBlockData) this.defaultBlockState().setValue(BambooStalkBlock.AGE, i); + } else { +- BlockState blockState1 = context.getLevel().getBlockState(context.getClickedPos().above()); +- return blockState1.is(Blocks.BAMBOO) +- ? this.defaultBlockState().setValue(AGE, blockState1.getValue(AGE)) +- : Blocks.BAMBOO_SAPLING.defaultBlockState(); ++ IBlockData iblockdata1 = context.getLevel().getBlockState(context.getClickedPos().above()); ++ ++ return iblockdata1.is(Blocks.BAMBOO) ? (IBlockData) this.defaultBlockState().setValue(BambooStalkBlock.AGE, (Integer) iblockdata1.getValue(BambooStalkBlock.AGE)) : Blocks.BAMBOO_SAPLING.defaultBlockState(); + } + } else { + return null; +@@ -116,123 +119,142 @@ + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (!state.canSurvive(level, pos)) { + level.destroyBlock(pos, true); + } ++ + } + + @Override +- public boolean isRandomlyTicking(BlockState state) { +- return state.getValue(STAGE) == 0; ++ public boolean isRandomlyTicking(IBlockData state) { ++ return (Integer) state.getValue(BambooStalkBlock.STAGE) == 0; + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- if (state.getValue(STAGE) == 0) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Integer) state.getValue(BambooStalkBlock.STAGE) == 0) { + if (random.nextInt(3) == 0 && level.isEmptyBlock(pos.above()) && level.getRawBrightness(pos.above(), 0) >= 9) { + int i = this.getHeightBelowUpToMax(level, pos) + 1; ++ + if (i < 16) { + this.growBamboo(state, level, pos, random, i); + } + } ++ + } + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { + return level.getBlockState(pos.below()).is(BlockTags.BAMBOO_PLANTABLE_ON); + } + + @Override +- public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { ++ public IBlockData updateShape(IBlockData state, Direction direction, IBlockData neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { + if (!state.canSurvive(level, pos)) { +- level.scheduleTick(pos, this, 1); ++ level.scheduleTick(pos, (Block) this, 1); + } + +- if (direction == Direction.UP && neighborState.is(Blocks.BAMBOO) && neighborState.getValue(AGE) > state.getValue(AGE)) { +- level.setBlock(pos, state.cycle(AGE), 2); ++ if (direction == Direction.UP && neighborState.is(Blocks.BAMBOO) && (Integer) neighborState.getValue(BambooStalkBlock.AGE) > (Integer) state.getValue(BambooStalkBlock.AGE)) { ++ level.setBlock(pos, (IBlockData) state.cycle(BambooStalkBlock.AGE), 2); + } + + return super.updateShape(state, direction, neighborState, level, pos, neighborPos); + } + + @Override +- public boolean isValidBonemealTarget(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { +- int heightAboveUpToMax = this.getHeightAboveUpToMax(levelReader, blockPos); +- int heightBelowUpToMax = this.getHeightBelowUpToMax(levelReader, blockPos); +- return heightAboveUpToMax + heightBelowUpToMax + 1 < 16 && levelReader.getBlockState(blockPos.above(heightAboveUpToMax)).getValue(STAGE) != 1; ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ int i = this.getHeightAboveUpToMax(iworldreader, blockposition); ++ int j = this.getHeightBelowUpToMax(iworldreader, blockposition); ++ ++ return i + j + 1 < 16 && (Integer) iworldreader.getBlockState(blockposition.above(i)).getValue(BambooStalkBlock.STAGE) != 1; + } + + @Override +- public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, BlockState state) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return true; + } + + @Override +- public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) { +- int heightAboveUpToMax = this.getHeightAboveUpToMax(level, pos); +- int heightBelowUpToMax = this.getHeightBelowUpToMax(level, pos); +- int i = heightAboveUpToMax + heightBelowUpToMax + 1; +- int i1 = 1 + random.nextInt(2); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ int i = this.getHeightAboveUpToMax(level, pos); ++ int j = this.getHeightBelowUpToMax(level, pos); ++ int k = i + j + 1; ++ int l = 1 + random.nextInt(2); + +- for (int i2 = 0; i2 < i1; i2++) { +- BlockPos blockPos = pos.above(heightAboveUpToMax); +- BlockState blockState = level.getBlockState(blockPos); +- if (i >= 16 || blockState.getValue(STAGE) == 1 || !level.isEmptyBlock(blockPos.above())) { ++ for (int i1 = 0; i1 < l; ++i1) { ++ BlockPos blockposition1 = pos.above(i); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ if (k >= 16 || !iblockdata1.is(Blocks.BAMBOO) || (Integer) iblockdata1.getValue(BambooStalkBlock.STAGE) == 1 || !level.isEmptyBlock(blockposition1.above())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here + return; + } + +- this.growBamboo(blockState, level, blockPos, random, i); +- heightAboveUpToMax++; +- i++; ++ this.growBamboo(iblockdata1, level, blockposition1, random, k); ++ ++i; ++ ++k; + } ++ + } + + @Override +- public float getDestroyProgress(BlockState state, Player player, BlockGetter level, BlockPos pos) { ++ public float getDestroyProgress(IBlockData state, Player player, BlockGetter level, BlockPos pos) { + return player.getMainHandItem().getItem() instanceof SwordItem ? 1.0F : super.getDestroyProgress(state, player, level, pos); + } + +- protected void growBamboo(BlockState state, Level level, BlockPos pos, RandomSource random, int age) { +- BlockState blockState = level.getBlockState(pos.below()); +- BlockPos blockPos = pos.below(2); +- BlockState blockState1 = level.getBlockState(blockPos); +- BambooLeaves bambooLeaves = BambooLeaves.NONE; ++ protected void growBamboo(IBlockData state, Level level, BlockPos pos, RandomSource random, int age) { ++ IBlockData iblockdata1 = level.getBlockState(pos.below()); ++ BlockPos blockposition1 = pos.below(2); ++ IBlockData iblockdata2 = level.getBlockState(blockposition1); ++ BambooLeaves blockpropertybamboosize = BambooLeaves.NONE; ++ boolean shouldUpdateOthers = false; // CraftBukkit ++ + if (age >= 1) { +- if (!blockState.is(Blocks.BAMBOO) || blockState.getValue(LEAVES) == BambooLeaves.NONE) { +- bambooLeaves = BambooLeaves.SMALL; +- } else if (blockState.is(Blocks.BAMBOO) && blockState.getValue(LEAVES) != BambooLeaves.NONE) { +- bambooLeaves = BambooLeaves.LARGE; +- if (blockState1.is(Blocks.BAMBOO)) { +- level.setBlock(pos.below(), blockState.setValue(LEAVES, BambooLeaves.SMALL), 3); +- level.setBlock(blockPos, blockState1.setValue(LEAVES, BambooLeaves.NONE), 3); ++ if (iblockdata1.is(Blocks.BAMBOO) && iblockdata1.getValue(BambooStalkBlock.LEAVES) != BambooLeaves.NONE) { ++ if (iblockdata1.is(Blocks.BAMBOO) && iblockdata1.getValue(BambooStalkBlock.LEAVES) != BambooLeaves.NONE) { ++ blockpropertybamboosize = BambooLeaves.LARGE; ++ if (iblockdata2.is(Blocks.BAMBOO)) { ++ // CraftBukkit start - moved down ++ // world.setBlock(blockposition.below(), (IBlockData) iblockdata1.setValue(BlockBamboo.LEAVES, BlockPropertyBambooSize.SMALL), 3); ++ // world.setBlock(blockposition1, (IBlockData) iblockdata2.setValue(BlockBamboo.LEAVES, BlockPropertyBambooSize.NONE), 3); ++ shouldUpdateOthers = true; ++ // CraftBukkit end ++ } + } ++ } else { ++ blockpropertybamboosize = BambooLeaves.SMALL; + } + } + +- int i = state.getValue(AGE) != 1 && !blockState1.is(Blocks.BAMBOO) ? 0 : 1; +- int i1 = (age < 11 || !(random.nextFloat() < 0.25F)) && age != 15 ? 0 : 1; +- level.setBlock( +- pos.above(), this.defaultBlockState().setValue(AGE, Integer.valueOf(i)).setValue(LEAVES, bambooLeaves).setValue(STAGE, Integer.valueOf(i1)), 3 +- ); ++ int j = (Integer) state.getValue(BambooStalkBlock.AGE) != 1 && !iblockdata2.is(Blocks.BAMBOO) ? 0 : 1; ++ int k = (age < 11 || random.nextFloat() >= 0.25F) && age != 15 ? 0 : 1; ++ ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, pos.above(), (IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(BambooStalkBlock.AGE, j)).setValue(BambooStalkBlock.LEAVES, blockpropertybamboosize)).setValue(BambooStalkBlock.STAGE, k), 3)) { ++ if (shouldUpdateOthers) { ++ level.setBlock(pos.below(), (IBlockData) iblockdata1.setValue(BambooStalkBlock.LEAVES, BambooLeaves.SMALL), 3); ++ level.setBlock(blockposition1, (IBlockData) iblockdata2.setValue(BambooStalkBlock.LEAVES, BambooLeaves.NONE), 3); ++ } ++ } ++ // CraftBukkit end + } + + protected int getHeightAboveUpToMax(BlockGetter level, BlockPos pos) { +- int i = 0; ++ int i; + +- while (i < 16 && level.getBlockState(pos.above(i + 1)).is(Blocks.BAMBOO)) { +- i++; ++ for (i = 0; i < 16 && level.getBlockState(pos.above(i + 1)).is(Blocks.BAMBOO); ++i) { ++ ; + } + + return i; + } + + protected int getHeightBelowUpToMax(BlockGetter level, BlockPos pos) { +- int i = 0; ++ int i; + +- while (i < 16 && level.getBlockState(pos.below(i + 1)).is(Blocks.BAMBOO)) { +- i++; ++ for (i = 0; i < 16 && level.getBlockState(pos.below(i + 1)).is(Blocks.BAMBOO); ++i) { ++ ; + } + + return i; diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/BaseFireBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/BaseFireBlock.java.patch new file mode 100644 index 0000000000..3df0d4f312 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/BaseFireBlock.java.patch @@ -0,0 +1,281 @@ +--- a/net/minecraft/world/level/block/BaseFireBlock.java ++++ b/net/minecraft/world/level/block/BaseFireBlock.java +@@ -14,16 +14,17 @@ + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.portal.PortalShape; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; + + public abstract class BaseFireBlock extends Block { ++ + private static final int SECONDS_ON_FIRE = 8; + private final float fireDamage; + protected static final float AABB_OFFSET = 1.0F; +- protected static final VoxelShape DOWN_AABB = Block.box(0.0, 0.0, 0.0, 16.0, 1.0, 16.0); ++ protected static final VoxelShape DOWN_AABB = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 1.0D, 16.0D); + + public BaseFireBlock(BlockBehaviour.Properties properties, float fireDamage) { + super(properties); +@@ -34,101 +35,106 @@ + protected abstract MapCodec codec(); + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { + return getState(context.getLevel(), context.getClickedPos()); + } + +- public static BlockState getState(BlockGetter reader, BlockPos pos) { +- BlockPos blockPos = pos.below(); +- BlockState blockState = reader.getBlockState(blockPos); +- return SoulFireBlock.canSurviveOnBlock(blockState) ? Blocks.SOUL_FIRE.defaultBlockState() : ((FireBlock)Blocks.FIRE).getStateForPlacement(reader, pos); ++ public static IBlockData getState(BlockGetter reader, BlockPos pos) { ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata = reader.getBlockState(blockposition1); ++ ++ return SoulFireBlock.canSurviveOnBlock(iblockdata) ? Blocks.SOUL_FIRE.defaultBlockState() : ((FireBlock) Blocks.FIRE).getStateForPlacement(reader, pos); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return DOWN_AABB; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return BaseFireBlock.DOWN_AABB; + } + + @Override +- public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { + if (random.nextInt(24) == 0) { +- level.playLocalSound( +- (double)pos.getX() + 0.5, +- (double)pos.getY() + 0.5, +- (double)pos.getZ() + 0.5, +- SoundEvents.FIRE_AMBIENT, +- SoundSource.BLOCKS, +- 1.0F + random.nextFloat(), +- random.nextFloat() * 0.7F + 0.3F, +- false +- ); ++ level.playLocalSound((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.FIRE_AMBIENT, SoundSource.BLOCKS, 1.0F + random.nextFloat(), random.nextFloat() * 0.7F + 0.3F, false); + } + +- BlockPos blockPos = pos.below(); +- BlockState blockState = level.getBlockState(blockPos); +- if (!this.canBurn(blockState) && !blockState.isFaceSturdy(level, blockPos, Direction.UP)) { ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ double d0; ++ double d1; ++ double d2; ++ int i; ++ ++ if (!this.canBurn(iblockdata1) && !iblockdata1.isFaceSturdy(level, blockposition1, Direction.UP)) { + if (this.canBurn(level.getBlockState(pos.west()))) { +- for (int i = 0; i < 2; i++) { +- double d = (double)pos.getX() + random.nextDouble() * 0.1F; +- double d1 = (double)pos.getY() + random.nextDouble(); +- double d2 = (double)pos.getZ() + random.nextDouble(); +- level.addParticle(ParticleTypes.LARGE_SMOKE, d, d1, d2, 0.0, 0.0, 0.0); ++ for (i = 0; i < 2; ++i) { ++ d0 = (double) pos.getX() + random.nextDouble() * 0.10000000149011612D; ++ d1 = (double) pos.getY() + random.nextDouble(); ++ d2 = (double) pos.getZ() + random.nextDouble(); ++ level.addParticle(ParticleTypes.LARGE_SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + } + + if (this.canBurn(level.getBlockState(pos.east()))) { +- for (int i = 0; i < 2; i++) { +- double d = (double)(pos.getX() + 1) - random.nextDouble() * 0.1F; +- double d1 = (double)pos.getY() + random.nextDouble(); +- double d2 = (double)pos.getZ() + random.nextDouble(); +- level.addParticle(ParticleTypes.LARGE_SMOKE, d, d1, d2, 0.0, 0.0, 0.0); ++ for (i = 0; i < 2; ++i) { ++ d0 = (double) (pos.getX() + 1) - random.nextDouble() * 0.10000000149011612D; ++ d1 = (double) pos.getY() + random.nextDouble(); ++ d2 = (double) pos.getZ() + random.nextDouble(); ++ level.addParticle(ParticleTypes.LARGE_SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + } + + if (this.canBurn(level.getBlockState(pos.north()))) { +- for (int i = 0; i < 2; i++) { +- double d = (double)pos.getX() + random.nextDouble(); +- double d1 = (double)pos.getY() + random.nextDouble(); +- double d2 = (double)pos.getZ() + random.nextDouble() * 0.1F; +- level.addParticle(ParticleTypes.LARGE_SMOKE, d, d1, d2, 0.0, 0.0, 0.0); ++ for (i = 0; i < 2; ++i) { ++ d0 = (double) pos.getX() + random.nextDouble(); ++ d1 = (double) pos.getY() + random.nextDouble(); ++ d2 = (double) pos.getZ() + random.nextDouble() * 0.10000000149011612D; ++ level.addParticle(ParticleTypes.LARGE_SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + } + + if (this.canBurn(level.getBlockState(pos.south()))) { +- for (int i = 0; i < 2; i++) { +- double d = (double)pos.getX() + random.nextDouble(); +- double d1 = (double)pos.getY() + random.nextDouble(); +- double d2 = (double)(pos.getZ() + 1) - random.nextDouble() * 0.1F; +- level.addParticle(ParticleTypes.LARGE_SMOKE, d, d1, d2, 0.0, 0.0, 0.0); ++ for (i = 0; i < 2; ++i) { ++ d0 = (double) pos.getX() + random.nextDouble(); ++ d1 = (double) pos.getY() + random.nextDouble(); ++ d2 = (double) (pos.getZ() + 1) - random.nextDouble() * 0.10000000149011612D; ++ level.addParticle(ParticleTypes.LARGE_SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + } + + if (this.canBurn(level.getBlockState(pos.above()))) { +- for (int i = 0; i < 2; i++) { +- double d = (double)pos.getX() + random.nextDouble(); +- double d1 = (double)(pos.getY() + 1) - random.nextDouble() * 0.1F; +- double d2 = (double)pos.getZ() + random.nextDouble(); +- level.addParticle(ParticleTypes.LARGE_SMOKE, d, d1, d2, 0.0, 0.0, 0.0); ++ for (i = 0; i < 2; ++i) { ++ d0 = (double) pos.getX() + random.nextDouble(); ++ d1 = (double) (pos.getY() + 1) - random.nextDouble() * 0.10000000149011612D; ++ d2 = (double) pos.getZ() + random.nextDouble(); ++ level.addParticle(ParticleTypes.LARGE_SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + } + } else { +- for (int i = 0; i < 3; i++) { +- double d = (double)pos.getX() + random.nextDouble(); +- double d1 = (double)pos.getY() + random.nextDouble() * 0.5 + 0.5; +- double d2 = (double)pos.getZ() + random.nextDouble(); +- level.addParticle(ParticleTypes.LARGE_SMOKE, d, d1, d2, 0.0, 0.0, 0.0); ++ for (i = 0; i < 3; ++i) { ++ d0 = (double) pos.getX() + random.nextDouble(); ++ d1 = (double) pos.getY() + random.nextDouble() * 0.5D + 0.5D; ++ d2 = (double) pos.getZ() + random.nextDouble(); ++ level.addParticle(ParticleTypes.LARGE_SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + } ++ + } + +- protected abstract boolean canBurn(BlockState state); ++ protected abstract boolean canBurn(IBlockData state); + + @Override +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { + if (!entity.fireImmune()) { + entity.setRemainingFireTicks(entity.getRemainingFireTicks() + 1); + if (entity.getRemainingFireTicks() == 0) { +- entity.setSecondsOnFire(8); ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityCombustEvent event = new org.bukkit.event.entity.EntityCombustByBlockEvent(org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), entity.getBukkitEntity(), 8); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ entity.setSecondsOnFire(event.getDuration(), false); ++ } ++ // CraftBukkit end + } + } + +@@ -137,53 +143,59 @@ + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { + if (!oldState.is(state.getBlock())) { + if (inPortalDimension(level)) { + Optional optional = PortalShape.findEmptyPortalShape(level, pos, Direction.Axis.X); ++ + if (optional.isPresent()) { +- optional.get().createPortalBlocks(); ++ ((PortalShape) optional.get()).createPortalBlocks(); + return; + } + } + + if (!state.canSurvive(level, pos)) { +- level.removeBlock(pos, false); ++ fireExtinguished(level, pos); // CraftBukkit - fuel block broke + } ++ + } + } + + private static boolean inPortalDimension(Level level) { +- return level.dimension() == Level.OVERWORLD || level.dimension() == Level.NETHER; ++ return level.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.OVERWORLD || level.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.NETHER; // CraftBukkit - getTypeKey() + } + + @Override +- protected void spawnDestroyParticles(Level level, Player player, BlockPos pos, BlockState state) { +- } ++ protected void spawnDestroyParticles(Level level, Player player, BlockPos pos, IBlockData state) {} + + @Override +- public BlockState playerWillDestroy(Level level, BlockPos blockPos, BlockState blockState, Player player) { +- if (!level.isClientSide()) { +- level.levelEvent(null, 1009, blockPos, 0); ++ public IBlockData playerWillDestroy(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ if (!world.isClientSide()) { ++ world.levelEvent((Player) null, 1009, blockposition, 0); + } + +- return super.playerWillDestroy(level, blockPos, blockState, player); ++ return super.playerWillDestroy(world, blockposition, iblockdata, entityhuman); + } + + public static boolean canBePlacedAt(Level level, BlockPos pos, Direction direction) { +- BlockState blockState = level.getBlockState(pos); +- return blockState.isAir() && (getState(level, pos).canSurvive(level, pos) || isPortal(level, pos, direction)); ++ IBlockData iblockdata = level.getBlockState(pos); ++ ++ return !iblockdata.isAir() ? false : getState(level, pos).canSurvive(level, pos) || isPortal(level, pos, direction); + } + + private static boolean isPortal(Level level, BlockPos pos, Direction direction) { + if (!inPortalDimension(level)) { + return false; + } else { +- BlockPos.MutableBlockPos mutableBlockPos = pos.mutable(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); + boolean flag = false; ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; + +- for (Direction direction1 : Direction.values()) { +- if (level.getBlockState(mutableBlockPos.set(pos).move(direction1)).is(Blocks.OBSIDIAN)) { ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection1 = aenumdirection[j]; ++ ++ if (level.getBlockState(blockposition_mutableblockposition.set(pos).move(enumdirection1)).is(Blocks.OBSIDIAN)) { + flag = true; + break; + } +@@ -192,11 +204,18 @@ + if (!flag) { + return false; + } else { +- Direction.Axis axis = direction.getAxis().isHorizontal() +- ? direction.getCounterClockWise().getAxis() +- : Direction.Plane.HORIZONTAL.getRandomAxis(level.random); +- return PortalShape.findEmptyPortalShape(level, pos, axis).isPresent(); ++ Direction.Axis enumdirection_enumaxis = direction.getAxis().isHorizontal() ? direction.getCounterClockWise().getAxis() : Direction.Plane.HORIZONTAL.getRandomAxis(level.random); ++ ++ return PortalShape.findEmptyPortalShape(level, pos, enumdirection_enumaxis).isPresent(); + } + } + } ++ ++ // CraftBukkit start ++ protected void fireExtinguished(net.minecraft.world.level.LevelAccessor world, BlockPos position) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, position, Blocks.AIR.defaultBlockState()).isCancelled()) { ++ world.removeBlock(position, false); ++ } ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/BasePressurePlateBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/BasePressurePlateBlock.java.patch new file mode 100644 index 0000000000..20a7fa8691 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/BasePressurePlateBlock.java.patch @@ -0,0 +1,199 @@ +--- a/net/minecraft/world/level/block/BasePressurePlateBlock.java ++++ b/net/minecraft/world/level/block/BasePressurePlateBlock.java +@@ -9,22 +9,25 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntitySelector; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockSetType; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public abstract class BasePressurePlateBlock extends Block { +- protected static final VoxelShape PRESSED_AABB = Block.box(1.0, 0.0, 1.0, 15.0, 0.5, 15.0); +- protected static final VoxelShape AABB = Block.box(1.0, 0.0, 1.0, 15.0, 1.0, 15.0); +- protected static final AABB TOUCH_AABB = new AABB(0.0625, 0.0, 0.0625, 0.9375, 0.25, 0.9375); ++ ++ protected static final VoxelShape PRESSED_AABB = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 0.5D, 15.0D); ++ protected static final VoxelShape AABB = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 1.0D, 15.0D); ++ protected static final AABB TOUCH_AABB = new AABB(0.0625D, 0.0D, 0.0625D, 0.9375D, 0.25D, 0.9375D); + protected final BlockSetType type; + + protected BasePressurePlateBlock(BlockBehaviour.Properties properties, BlockSetType type) { +@@ -36,8 +39,8 @@ + protected abstract MapCodec codec(); + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return this.getSignalForState(state) > 0 ? PRESSED_AABB : AABB; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return this.getSignalForState(state) > 0 ? BasePressurePlateBlock.PRESSED_AABB : BasePressurePlateBlock.AABB; + } + + protected int getPressedTime() { +@@ -45,67 +48,86 @@ + } + + @Override +- public boolean isPossibleToRespawnInThis(BlockState state) { ++ public boolean isPossibleToRespawnInThis(IBlockData state) { + return true; + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- return facing == Direction.DOWN && !state.canSurvive(level, currentPos) +- ? Blocks.AIR.defaultBlockState() +- : super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ return facing == Direction.DOWN && !state.canSurvive(level, currentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { +- BlockPos blockPos = pos.below(); +- return canSupportRigidBlock(level, blockPos) || canSupportCenter(level, blockPos, Direction.UP); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.below(); ++ ++ return canSupportRigidBlock(level, blockposition1) || canSupportCenter(level, blockposition1, Direction.UP); + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- int signalForState = this.getSignalForState(state); +- if (signalForState > 0) { +- this.checkPressed(null, level, pos, state, signalForState); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ int i = this.getSignalForState(state); ++ ++ if (i > 0) { ++ this.checkPressed((Entity) null, level, pos, state, i); + } ++ + } + + @Override +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { + if (!level.isClientSide) { +- int signalForState = this.getSignalForState(state); +- if (signalForState == 0) { +- this.checkPressed(entity, level, pos, state, signalForState); ++ int i = this.getSignalForState(state); ++ ++ if (i == 0) { ++ this.checkPressed(entity, level, pos, state, i); + } ++ + } + } + +- private void checkPressed(@Nullable Entity entity, Level level, BlockPos pos, BlockState state, int currentSignal) { +- int signalStrength = this.getSignalStrength(level, pos); ++ private void checkPressed(@Nullable Entity entity, Level level, BlockPos pos, IBlockData state, int currentSignal) { ++ int j = this.getSignalStrength(level, pos); + boolean flag = currentSignal > 0; +- boolean flag1 = signalStrength > 0; +- if (currentSignal != signalStrength) { +- BlockState blockState = this.setSignalForState(state, signalStrength); +- level.setBlock(pos, blockState, 2); ++ boolean flag1 = j > 0; ++ ++ // CraftBukkit start - Interact Pressure Plate ++ org.bukkit.World bworld = level.getWorld(); ++ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager(); ++ ++ if (flag != flag1) { ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), currentSignal, j); ++ manager.callEvent(eventRedstone); ++ ++ flag1 = eventRedstone.getNewCurrent() > 0; ++ j = eventRedstone.getNewCurrent(); ++ } ++ // CraftBukkit end ++ ++ if (currentSignal != j) { ++ IBlockData iblockdata1 = this.setSignalForState(state, j); ++ ++ level.setBlock(pos, iblockdata1, 2); + this.updateNeighbours(level, pos); +- level.setBlocksDirty(pos, state, blockState); ++ level.setBlocksDirty(pos, state, iblockdata1); + } + + if (!flag1 && flag) { +- level.playSound(null, pos, this.type.pressurePlateClickOff(), SoundSource.BLOCKS); ++ level.playSound((Player) null, pos, this.type.pressurePlateClickOff(), SoundSource.BLOCKS); + level.gameEvent(entity, GameEvent.BLOCK_DEACTIVATE, pos); + } else if (flag1 && !flag) { +- level.playSound(null, pos, this.type.pressurePlateClickOn(), SoundSource.BLOCKS); ++ level.playSound((Player) null, pos, this.type.pressurePlateClickOn(), SoundSource.BLOCKS); + level.gameEvent(entity, GameEvent.BLOCK_ACTIVATE, pos); + } + + if (flag1) { +- level.scheduleTick(new BlockPos(pos), this, this.getPressedTime()); ++ level.scheduleTick(new BlockPos(pos), (Block) this, this.getPressedTime()); + } ++ + } + + @Override +- public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { + if (!isMoving && !state.is(newState.getBlock())) { + if (this.getSignalForState(state) > 0) { + this.updateNeighbours(level, pos); +@@ -121,27 +143,35 @@ + } + + @Override +- public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { + return this.getSignalForState(blockState); + } + + @Override +- public int getDirectSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ public int getDirectSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { + return side == Direction.UP ? this.getSignalForState(blockState) : 0; + } + + @Override +- public boolean isSignalSource(BlockState state) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + + protected static int getEntityCount(Level level, AABB box, Class entityClass) { +- return level.getEntitiesOfClass(entityClass, box, EntitySelector.NO_SPECTATORS.and(entity -> !entity.isIgnoringBlockTriggers())).size(); ++ // CraftBukkit start ++ return getEntities(level, box, entityClass).size(); + } + ++ protected static java.util.List getEntities(Level world, AABB axisalignedbb, Class oclass) { ++ // CraftBukkit end ++ return world.getEntitiesOfClass(oclass, axisalignedbb, EntitySelector.NO_SPECTATORS.and((entity) -> { ++ return !entity.isIgnoringBlockTriggers(); ++ })); // CraftBukkit ++ } ++ + protected abstract int getSignalStrength(Level level, BlockPos pos); + +- protected abstract int getSignalForState(BlockState state); ++ protected abstract int getSignalForState(IBlockData state); + +- protected abstract BlockState setSignalForState(BlockState state, int signal); ++ protected abstract IBlockData setSignalForState(IBlockData state, int signal); + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/BedBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/BedBlock.java.patch new file mode 100644 index 0000000000..7e3e6e692a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/BedBlock.java.patch @@ -0,0 +1,519 @@ +--- a/net/minecraft/world/level/block/BedBlock.java ++++ b/net/minecraft/world/level/block/BedBlock.java +@@ -2,7 +2,6 @@ + + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import java.util.List; + import java.util.Optional; + import javax.annotation.Nullable; +@@ -10,7 +9,7 @@ + import net.minecraft.core.Direction; + import net.minecraft.network.chat.Component; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +@@ -23,18 +22,19 @@ + import net.minecraft.world.item.context.BlockPlaceContext; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.CollisionGetter; ++import net.minecraft.world.level.ExplosionDamageCalculator; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.entity.BedBlockEntity; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BedPart; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.block.state.properties.EnumProperty; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; +@@ -44,97 +44,134 @@ + import org.apache.commons.lang3.ArrayUtils; + + public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group(DyeColor.CODEC.fieldOf("color").forGetter(BedBlock::getColor), propertiesCodec()).apply(instance, BedBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(DyeColor.CODEC.fieldOf("color").forGetter(BedBlock::getColor), propertiesCodec()).apply(instance, BedBlock::new); ++ }); + public static final EnumProperty PART = BlockStateProperties.BED_PART; + public static final BooleanProperty OCCUPIED = BlockStateProperties.OCCUPIED; + protected static final int HEIGHT = 9; +- protected static final VoxelShape BASE = Block.box(0.0, 3.0, 0.0, 16.0, 9.0, 16.0); ++ protected static final VoxelShape BASE = Block.box(0.0D, 3.0D, 0.0D, 16.0D, 9.0D, 16.0D); + private static final int LEG_WIDTH = 3; +- protected static final VoxelShape LEG_NORTH_WEST = Block.box(0.0, 0.0, 0.0, 3.0, 3.0, 3.0); +- protected static final VoxelShape LEG_SOUTH_WEST = Block.box(0.0, 0.0, 13.0, 3.0, 3.0, 16.0); +- protected static final VoxelShape LEG_NORTH_EAST = Block.box(13.0, 0.0, 0.0, 16.0, 3.0, 3.0); +- protected static final VoxelShape LEG_SOUTH_EAST = Block.box(13.0, 0.0, 13.0, 16.0, 3.0, 16.0); +- protected static final VoxelShape NORTH_SHAPE = Shapes.or(BASE, LEG_NORTH_WEST, LEG_NORTH_EAST); +- protected static final VoxelShape SOUTH_SHAPE = Shapes.or(BASE, LEG_SOUTH_WEST, LEG_SOUTH_EAST); +- protected static final VoxelShape WEST_SHAPE = Shapes.or(BASE, LEG_NORTH_WEST, LEG_SOUTH_WEST); +- protected static final VoxelShape EAST_SHAPE = Shapes.or(BASE, LEG_NORTH_EAST, LEG_SOUTH_EAST); ++ protected static final VoxelShape LEG_NORTH_WEST = Block.box(0.0D, 0.0D, 0.0D, 3.0D, 3.0D, 3.0D); ++ protected static final VoxelShape LEG_SOUTH_WEST = Block.box(0.0D, 0.0D, 13.0D, 3.0D, 3.0D, 16.0D); ++ protected static final VoxelShape LEG_NORTH_EAST = Block.box(13.0D, 0.0D, 0.0D, 16.0D, 3.0D, 3.0D); ++ protected static final VoxelShape LEG_SOUTH_EAST = Block.box(13.0D, 0.0D, 13.0D, 16.0D, 3.0D, 16.0D); ++ protected static final VoxelShape NORTH_SHAPE = Shapes.or(BedBlock.BASE, BedBlock.LEG_NORTH_WEST, BedBlock.LEG_NORTH_EAST); ++ protected static final VoxelShape SOUTH_SHAPE = Shapes.or(BedBlock.BASE, BedBlock.LEG_SOUTH_WEST, BedBlock.LEG_SOUTH_EAST); ++ protected static final VoxelShape WEST_SHAPE = Shapes.or(BedBlock.BASE, BedBlock.LEG_NORTH_WEST, BedBlock.LEG_SOUTH_WEST); ++ protected static final VoxelShape EAST_SHAPE = Shapes.or(BedBlock.BASE, BedBlock.LEG_NORTH_EAST, BedBlock.LEG_SOUTH_EAST); + private final DyeColor color; + + @Override + public MapCodec codec() { +- return CODEC; ++ return BedBlock.CODEC; + } + + public BedBlock(DyeColor color, BlockBehaviour.Properties properties) { + super(properties); + this.color = color; +- this.registerDefaultState(this.stateDefinition.any().setValue(PART, BedPart.FOOT).setValue(OCCUPIED, Boolean.valueOf(false))); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(BedBlock.PART, BedPart.FOOT)).setValue(BedBlock.OCCUPIED, false)); + } + + @Nullable + public static Direction getBedOrientation(BlockGetter level, BlockPos pos) { +- BlockState blockState = level.getBlockState(pos); +- return blockState.getBlock() instanceof BedBlock ? blockState.getValue(FACING) : null; ++ IBlockData iblockdata = level.getBlockState(pos); ++ ++ return iblockdata.getBlock() instanceof BedBlock ? (Direction) iblockdata.getValue(BedBlock.FACING) : null; + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + if (level.isClientSide) { + return InteractionResult.CONSUME; + } else { +- if (state.getValue(PART) != BedPart.HEAD) { +- pos = pos.relative(state.getValue(FACING)); ++ if (state.getValue(BedBlock.PART) != BedPart.HEAD) { ++ pos = pos.relative((Direction) state.getValue(BedBlock.FACING)); + state = level.getBlockState(pos); +- if (!state.is(this)) { ++ if (!state.is((Block) this)) { + return InteractionResult.CONSUME; + } + } + +- if (!canSetSpawn(level)) { ++ // CraftBukkit - moved world and biome check into EntityHuman ++ if (false && !canSetSpawn(level)) { + level.removeBlock(pos, false); +- BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite()); +- if (level.getBlockState(blockPos).is(this)) { +- level.removeBlock(blockPos, false); ++ BlockPos blockposition1 = pos.relative(((Direction) state.getValue(BedBlock.FACING)).getOpposite()); ++ ++ if (level.getBlockState(blockposition1).is((Block) this)) { ++ level.removeBlock(blockposition1, false); + } + +- Vec3 center = pos.getCenter(); +- level.explode(null, level.damageSources().badRespawnPointExplosion(center), null, center, 5.0F, true, Level.ExplosionInteraction.BLOCK); ++ Vec3 vec3d = pos.getCenter(); ++ ++ level.explode((Entity) null, level.damageSources().badRespawnPointExplosion(vec3d), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.a.BLOCK); + return InteractionResult.SUCCESS; +- } else if (state.getValue(OCCUPIED)) { ++ } else if ((Boolean) state.getValue(BedBlock.OCCUPIED)) { + if (!this.kickVillagerOutOfBed(level, pos)) { + player.displayClientMessage(Component.translatable("block.minecraft.bed.occupied"), true); + } + + return InteractionResult.SUCCESS; + } else { +- player.startSleepInBed(pos).ifLeft(bedSleepingProblem -> { +- if (bedSleepingProblem.getMessage() != null) { +- player.displayClientMessage(bedSleepingProblem.getMessage(), true); ++ // CraftBukkit start ++ IBlockData finaliblockdata = state; ++ BlockPos finalblockposition = pos; ++ // CraftBukkit end ++ player.startSleepInBed(pos).ifLeft((entityhuman_enumbedresult) -> { ++ // CraftBukkit start - handling bed explosion from below here ++ if (!level.dimensionType().bedWorks()) { ++ this.explodeBed(finaliblockdata, level, finalblockposition); ++ } else ++ // CraftBukkit end ++ if (entityhuman_enumbedresult.getMessage() != null) { ++ player.displayClientMessage(entityhuman_enumbedresult.getMessage(), true); + } ++ + }); + return InteractionResult.SUCCESS; + } + } + } + ++ // CraftBukkit start ++ private InteractionResult explodeBed(IBlockData iblockdata, Level world, BlockPos blockposition) { ++ { ++ { ++ world.removeBlock(blockposition, false); ++ BlockPos blockposition1 = blockposition.relative(((Direction) iblockdata.getValue(BedBlock.FACING)).getOpposite()); ++ ++ if (world.getBlockState(blockposition1).getBlock() == this) { ++ world.removeBlock(blockposition1, false); ++ } ++ ++ Vec3 vec3d = blockposition.getCenter(); ++ ++ world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.a.BLOCK); ++ return InteractionResult.SUCCESS; ++ } ++ } ++ } ++ // CraftBukkit end ++ + public static boolean canSetSpawn(Level level) { +- return level.dimensionType().bedWorks(); ++ // CraftBukkit - moved world and biome check into EntityHuman ++ return true || level.dimensionType().bedWorks(); + } + + private boolean kickVillagerOutOfBed(Level level, BlockPos pos) { +- List entitiesOfClass = level.getEntitiesOfClass(Villager.class, new AABB(pos), LivingEntity::isSleeping); +- if (entitiesOfClass.isEmpty()) { ++ List list = level.getEntitiesOfClass(Villager.class, new AABB(pos), LivingEntity::isSleeping); ++ ++ if (list.isEmpty()) { + return false; + } else { +- entitiesOfClass.get(0).stopSleeping(); ++ ((Villager) list.get(0)).stopSleeping(); + return true; + } + } + + @Override +- public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, float fallDistance) { ++ public void fallOn(Level level, IBlockData state, BlockPos pos, Entity entity, float fallDistance) { + super.fallOn(level, state, pos, entity, fallDistance * 0.5F); + } + +@@ -145,25 +182,23 @@ + } else { + this.bounceUp(entity); + } ++ + } + + private void bounceUp(Entity entity) { +- Vec3 deltaMovement = entity.getDeltaMovement(); +- if (deltaMovement.y < 0.0) { +- double d = entity instanceof LivingEntity ? 1.0 : 0.8; +- entity.setDeltaMovement(deltaMovement.x, -deltaMovement.y * 0.66F * d, deltaMovement.z); ++ Vec3 vec3d = entity.getDeltaMovement(); ++ ++ if (vec3d.y < 0.0D) { ++ double d0 = entity instanceof LivingEntity ? 1.0D : 0.8D; ++ ++ entity.setDeltaMovement(vec3d.x, -vec3d.y * 0.6600000262260437D * d0, vec3d.z); + } ++ + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- if (facing == getNeighbourDirection(state.getValue(PART), state.getValue(FACING))) { +- return facingState.is(this) && facingState.getValue(PART) != state.getValue(PART) +- ? state.setValue(OCCUPIED, facingState.getValue(OCCUPIED)) +- : Blocks.AIR.defaultBlockState(); +- } else { +- return super.updateShape(state, facing, facingState, level, currentPos, facingPos); +- } ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ return facing == getNeighbourDirection((BedPart) state.getValue(BedBlock.PART), (Direction) state.getValue(BedBlock.FACING)) ? (facingState.is((Block) this) && facingState.getValue(BedBlock.PART) != state.getValue(BedBlock.PART) ? (IBlockData) state.setValue(BedBlock.OCCUPIED, (Boolean) facingState.getValue(BedBlock.OCCUPIED)) : Blocks.AIR.defaultBlockState()) : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + private static Direction getNeighbourDirection(BedPart part, Direction direction) { +@@ -171,57 +206,61 @@ + } + + @Override +- public BlockState playerWillDestroy(Level level, BlockPos blockPos, BlockState blockState, Player player) { +- if (!level.isClientSide && player.isCreative()) { +- BedPart bedPart = blockState.getValue(PART); +- if (bedPart == BedPart.FOOT) { +- BlockPos blockPos1 = blockPos.relative(getNeighbourDirection(bedPart, blockState.getValue(FACING))); +- BlockState blockState1 = level.getBlockState(blockPos1); +- if (blockState1.is(this) && blockState1.getValue(PART) == BedPart.HEAD) { +- level.setBlock(blockPos1, Blocks.AIR.defaultBlockState(), 35); +- level.levelEvent(player, 2001, blockPos1, Block.getId(blockState1)); ++ public IBlockData playerWillDestroy(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ if (!world.isClientSide && entityhuman.isCreative()) { ++ BedPart blockpropertybedpart = (BedPart) iblockdata.getValue(BedBlock.PART); ++ ++ if (blockpropertybedpart == BedPart.FOOT) { ++ BlockPos blockposition1 = blockposition.relative(getNeighbourDirection(blockpropertybedpart, (Direction) iblockdata.getValue(BedBlock.FACING))); ++ IBlockData iblockdata1 = world.getBlockState(blockposition1); ++ ++ if (iblockdata1.is((Block) this) && iblockdata1.getValue(BedBlock.PART) == BedPart.HEAD) { ++ world.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 35); ++ world.levelEvent(entityhuman, 2001, blockposition1, Block.getId(iblockdata1)); + } + } + } + +- return super.playerWillDestroy(level, blockPos, blockState, player); ++ return super.playerWillDestroy(world, blockposition, iblockdata, entityhuman); + } + + @Nullable + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- Direction horizontalDirection = context.getHorizontalDirection(); +- BlockPos clickedPos = context.getClickedPos(); +- BlockPos blockPos = clickedPos.relative(horizontalDirection); +- Level level = context.getLevel(); +- return level.getBlockState(blockPos).canBeReplaced(context) && level.getWorldBorder().isWithinBounds(blockPos) +- ? this.defaultBlockState().setValue(FACING, horizontalDirection) +- : null; ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ Direction enumdirection = context.getHorizontalDirection(); ++ BlockPos blockposition = context.getClickedPos(); ++ BlockPos blockposition1 = blockposition.relative(enumdirection); ++ Level world = context.getLevel(); ++ ++ return world.getBlockState(blockposition1).canBeReplaced(context) && world.getWorldBorder().isWithinBounds(blockposition1) ? (IBlockData) this.defaultBlockState().setValue(BedBlock.FACING, enumdirection) : null; + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- Direction opposite = getConnectedDirection(state).getOpposite(); +- switch (opposite) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ Direction enumdirection = getConnectedDirection(state).getOpposite(); ++ ++ switch (enumdirection) { + case NORTH: +- return NORTH_SHAPE; ++ return BedBlock.NORTH_SHAPE; + case SOUTH: +- return SOUTH_SHAPE; ++ return BedBlock.SOUTH_SHAPE; + case WEST: +- return WEST_SHAPE; ++ return BedBlock.WEST_SHAPE; + default: +- return EAST_SHAPE; ++ return BedBlock.EAST_SHAPE; + } + } + +- public static Direction getConnectedDirection(BlockState state) { +- Direction direction = state.getValue(FACING); +- return state.getValue(PART) == BedPart.HEAD ? direction.getOpposite() : direction; ++ public static Direction getConnectedDirection(IBlockData state) { ++ Direction enumdirection = (Direction) state.getValue(BedBlock.FACING); ++ ++ return state.getValue(BedBlock.PART) == BedPart.HEAD ? enumdirection.getOpposite() : enumdirection; + } + +- public static DoubleBlockCombiner.BlockType getBlockType(BlockState state) { +- BedPart bedPart = state.getValue(PART); +- return bedPart == BedPart.HEAD ? DoubleBlockCombiner.BlockType.FIRST : DoubleBlockCombiner.BlockType.SECOND; ++ public static DoubleBlockCombiner.BlockType getBlockType(IBlockData state) { ++ BedPart blockpropertybedpart = (BedPart) state.getValue(BedBlock.PART); ++ ++ return blockpropertybedpart == BedPart.HEAD ? DoubleBlockCombiner.BlockType.FIRST : DoubleBlockCombiner.BlockType.SECOND; + } + + private static boolean isBunkBed(BlockGetter level, BlockPos pos) { +@@ -229,57 +268,65 @@ + } + + public static Optional findStandUpPosition(EntityType entityType, CollisionGetter collisionGetter, BlockPos pos, Direction direction, float yRot) { +- Direction clockWise = direction.getClockWise(); +- Direction direction1 = clockWise.isFacingAngle(yRot) ? clockWise.getOpposite() : clockWise; ++ Direction enumdirection1 = direction.getClockWise(); ++ Direction enumdirection2 = enumdirection1.isFacingAngle(yRot) ? enumdirection1.getOpposite() : enumdirection1; ++ + if (isBunkBed(collisionGetter, pos)) { +- return findBunkBedStandUpPosition(entityType, collisionGetter, pos, direction, direction1); ++ return findBunkBedStandUpPosition(entityType, collisionGetter, pos, direction, enumdirection2); + } else { +- int[][] ints = bedStandUpOffsets(direction, direction1); +- Optional optional = findStandUpPositionAtOffset(entityType, collisionGetter, pos, ints, true); +- return optional.isPresent() ? optional : findStandUpPositionAtOffset(entityType, collisionGetter, pos, ints, false); ++ int[][] aint = bedStandUpOffsets(direction, enumdirection2); ++ Optional optional = findStandUpPositionAtOffset(entityType, collisionGetter, pos, aint, true); ++ ++ return optional.isPresent() ? optional : findStandUpPositionAtOffset(entityType, collisionGetter, pos, aint, false); + } + } + +- private static Optional findBunkBedStandUpPosition( +- EntityType entityType, CollisionGetter collisionGetter, BlockPos pos, Direction stateFacing, Direction entityFacing +- ) { +- int[][] ints = bedSurroundStandUpOffsets(stateFacing, entityFacing); +- Optional optional = findStandUpPositionAtOffset(entityType, collisionGetter, pos, ints, true); ++ private static Optional findBunkBedStandUpPosition(EntityType entityType, CollisionGetter collisionGetter, BlockPos pos, Direction stateFacing, Direction entityFacing) { ++ int[][] aint = bedSurroundStandUpOffsets(stateFacing, entityFacing); ++ Optional optional = findStandUpPositionAtOffset(entityType, collisionGetter, pos, aint, true); ++ + if (optional.isPresent()) { + return optional; + } else { +- BlockPos blockPos = pos.below(); +- Optional optional1 = findStandUpPositionAtOffset(entityType, collisionGetter, blockPos, ints, true); ++ BlockPos blockposition1 = pos.below(); ++ Optional optional1 = findStandUpPositionAtOffset(entityType, collisionGetter, blockposition1, aint, true); ++ + if (optional1.isPresent()) { + return optional1; + } else { +- int[][] ints1 = bedAboveStandUpOffsets(stateFacing); +- Optional optional2 = findStandUpPositionAtOffset(entityType, collisionGetter, pos, ints1, true); ++ int[][] aint1 = bedAboveStandUpOffsets(stateFacing); ++ Optional optional2 = findStandUpPositionAtOffset(entityType, collisionGetter, pos, aint1, true); ++ + if (optional2.isPresent()) { + return optional2; + } else { +- Optional optional3 = findStandUpPositionAtOffset(entityType, collisionGetter, pos, ints, false); ++ Optional optional3 = findStandUpPositionAtOffset(entityType, collisionGetter, pos, aint, false); ++ + if (optional3.isPresent()) { + return optional3; + } else { +- Optional optional4 = findStandUpPositionAtOffset(entityType, collisionGetter, blockPos, ints, false); +- return optional4.isPresent() ? optional4 : findStandUpPositionAtOffset(entityType, collisionGetter, pos, ints1, false); ++ Optional optional4 = findStandUpPositionAtOffset(entityType, collisionGetter, blockposition1, aint, false); ++ ++ return optional4.isPresent() ? optional4 : findStandUpPositionAtOffset(entityType, collisionGetter, pos, aint1, false); + } + } + } + } + } + +- private static Optional findStandUpPositionAtOffset( +- EntityType entityType, CollisionGetter collisionGetter, BlockPos pos, int[][] offsets, boolean simulate +- ) { +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ private static Optional findStandUpPositionAtOffset(EntityType entityType, CollisionGetter collisionGetter, BlockPos pos, int[][] offsets, boolean simulate) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ int[][] aint1 = offsets; ++ int i = offsets.length; + +- for (int[] ints : offsets) { +- mutableBlockPos.set(pos.getX() + ints[0], pos.getY(), pos.getZ() + ints[1]); +- Vec3 vec3 = DismountHelper.findSafeDismountLocation(entityType, collisionGetter, mutableBlockPos, simulate); +- if (vec3 != null) { +- return Optional.of(vec3); ++ for (int j = 0; j < i; ++j) { ++ int[] aint2 = aint1[j]; ++ ++ blockposition_mutableblockposition.set(pos.getX() + aint2[0], pos.getY(), pos.getZ() + aint2[1]); ++ Vec3 vec3d = DismountHelper.findSafeDismountLocation(entityType, collisionGetter, blockposition_mutableblockposition, simulate); ++ ++ if (vec3d != null) { ++ return Optional.of(vec3d); + } + } + +@@ -287,29 +334,36 @@ + } + + @Override +- public RenderShape getRenderShape(BlockState state) { +- return RenderShape.ENTITYBLOCK_ANIMATED; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.ENTITYBLOCK_ANIMATED; + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(FACING, PART, OCCUPIED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(BedBlock.FACING, BedBlock.PART, BedBlock.OCCUPIED); + } + + @Override +- public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { + return new BedBlockEntity(pos, state, this.color); + } + + @Override +- public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) { ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, @Nullable LivingEntity placer, ItemStack stack) { + super.setPlacedBy(level, pos, state, placer, stack); + if (!level.isClientSide) { +- BlockPos blockPos = pos.relative(state.getValue(FACING)); +- level.setBlock(blockPos, state.setValue(PART, BedPart.HEAD), 3); ++ BlockPos blockposition1 = pos.relative((Direction) state.getValue(BedBlock.FACING)); ++ ++ level.setBlock(blockposition1, (IBlockData) state.setValue(BedBlock.PART, BedPart.HEAD), 3); ++ // CraftBukkit start - SPIGOT-7315: Don't updated if we capture block states ++ if (level.captureBlockStates) { ++ return; ++ } ++ // CraftBukkit end + level.blockUpdated(pos, Blocks.AIR); + state.updateNeighbourShapes(level, pos, 3); + } ++ + } + + public DyeColor getColor() { +@@ -317,33 +371,23 @@ + } + + @Override +- public long getSeed(BlockState state, BlockPos pos) { +- BlockPos blockPos = pos.relative(state.getValue(FACING), state.getValue(PART) == BedPart.HEAD ? 0 : 1); +- return Mth.getSeed(blockPos.getX(), pos.getY(), blockPos.getZ()); ++ public long getSeed(IBlockData state, BlockPos pos) { ++ BlockPos blockposition1 = pos.relative((Direction) state.getValue(BedBlock.FACING), state.getValue(BedBlock.PART) == BedPart.HEAD ? 0 : 1); ++ ++ return Mth.getSeed(blockposition1.getX(), pos.getY(), blockposition1.getZ()); + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + + private static int[][] bedStandUpOffsets(Direction firstDir, Direction secondDir) { +- return ArrayUtils.addAll((int[][])bedSurroundStandUpOffsets(firstDir, secondDir), (int[][])bedAboveStandUpOffsets(firstDir)); ++ return (int[][]) ArrayUtils.addAll(bedSurroundStandUpOffsets(firstDir, secondDir), bedAboveStandUpOffsets(firstDir)); + } + + private static int[][] bedSurroundStandUpOffsets(Direction firstDir, Direction secondDir) { +- return new int[][]{ +- {secondDir.getStepX(), secondDir.getStepZ()}, +- {secondDir.getStepX() - firstDir.getStepX(), secondDir.getStepZ() - firstDir.getStepZ()}, +- {secondDir.getStepX() - firstDir.getStepX() * 2, secondDir.getStepZ() - firstDir.getStepZ() * 2}, +- {-firstDir.getStepX() * 2, -firstDir.getStepZ() * 2}, +- {-secondDir.getStepX() - firstDir.getStepX() * 2, -secondDir.getStepZ() - firstDir.getStepZ() * 2}, +- {-secondDir.getStepX() - firstDir.getStepX(), -secondDir.getStepZ() - firstDir.getStepZ()}, +- {-secondDir.getStepX(), -secondDir.getStepZ()}, +- {-secondDir.getStepX() + firstDir.getStepX(), -secondDir.getStepZ() + firstDir.getStepZ()}, +- {firstDir.getStepX(), firstDir.getStepZ()}, +- {secondDir.getStepX() + firstDir.getStepX(), secondDir.getStepZ() + firstDir.getStepZ()} +- }; ++ return new int[][]{{secondDir.getStepX(), secondDir.getStepZ()}, {secondDir.getStepX() - firstDir.getStepX(), secondDir.getStepZ() - firstDir.getStepZ()}, {secondDir.getStepX() - firstDir.getStepX() * 2, secondDir.getStepZ() - firstDir.getStepZ() * 2}, {-firstDir.getStepX() * 2, -firstDir.getStepZ() * 2}, {-secondDir.getStepX() - firstDir.getStepX() * 2, -secondDir.getStepZ() - firstDir.getStepZ() * 2}, {-secondDir.getStepX() - firstDir.getStepX(), -secondDir.getStepZ() - firstDir.getStepZ()}, {-secondDir.getStepX(), -secondDir.getStepZ()}, {-secondDir.getStepX() + firstDir.getStepX(), -secondDir.getStepZ() + firstDir.getStepZ()}, {firstDir.getStepX(), firstDir.getStepZ()}, {secondDir.getStepX() + firstDir.getStepX(), secondDir.getStepZ() + firstDir.getStepZ()}}; + } + + private static int[][] bedAboveStandUpOffsets(Direction dir) { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/BeehiveBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/BeehiveBlock.java.patch new file mode 100644 index 0000000000..86061ad004 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/BeehiveBlock.java.patch @@ -0,0 +1,442 @@ +--- a/net/minecraft/world/level/block/BeehiveBlock.java ++++ b/net/minecraft/world/level/block/BeehiveBlock.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.block; + + import com.mojang.serialization.MapCodec; ++import java.util.Iterator; + import java.util.List; + import javax.annotation.Nullable; + import net.minecraft.Util; +@@ -16,7 +17,7 @@ + import net.minecraft.tags.BlockTags; + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.animal.Bee; +@@ -42,7 +43,7 @@ + import net.minecraft.world.level.block.entity.BlockEntityTicker; + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.DirectionProperty; +@@ -55,6 +56,7 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + + public class BeehiveBlock extends BaseEntityBlock { ++ + public static final MapCodec CODEC = simpleCodec(BeehiveBlock::new); + public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING; + public static final IntegerProperty HONEY_LEVEL = BlockStateProperties.LEVEL_HONEY; +@@ -63,54 +65,65 @@ + + @Override + public MapCodec codec() { +- return CODEC; ++ return BeehiveBlock.CODEC; + } + + public BeehiveBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(HONEY_LEVEL, Integer.valueOf(0)).setValue(FACING, Direction.NORTH)); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(BeehiveBlock.HONEY_LEVEL, 0)).setValue(BeehiveBlock.FACING, Direction.NORTH)); + } + + @Override +- public boolean hasAnalogOutputSignal(BlockState state) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return true; + } + + @Override +- public int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) { +- return blockState.getValue(HONEY_LEVEL); ++ public int getAnalogOutputSignal(IBlockData blockState, Level level, BlockPos pos) { ++ return (Integer) blockState.getValue(BeehiveBlock.HONEY_LEVEL); + } + + @Override +- public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity te, ItemStack stack) { ++ public void playerDestroy(Level level, Player player, BlockPos pos, IBlockData state, @Nullable BlockEntity te, ItemStack stack) { + super.playerDestroy(level, player, pos, state, te, stack); +- if (!level.isClientSide && te instanceof BeehiveBlockEntity beehiveBlockEntity) { ++ if (!level.isClientSide && te instanceof BeehiveBlockEntity) { ++ BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) te; ++ + if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack) == 0) { +- beehiveBlockEntity.emptyAllLivingFromHive(player, state, BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY); ++ tileentitybeehive.emptyAllLivingFromHive(player, state, BeehiveBlockEntity.ReleaseStatus.EMERGENCY); + level.updateNeighbourForOutputSignal(pos, this); + this.angerNearbyBees(level, pos); + } + +- CriteriaTriggers.BEE_NEST_DESTROYED.trigger((ServerPlayer)player, state, stack, beehiveBlockEntity.getOccupantCount()); ++ CriteriaTriggers.BEE_NEST_DESTROYED.trigger((ServerPlayer) player, state, stack, tileentitybeehive.getOccupantCount()); + } ++ + } + + private void angerNearbyBees(Level level, BlockPos pos) { +- AABB aABB = new AABB(pos).inflate(8.0, 6.0, 8.0); +- List entitiesOfClass = level.getEntitiesOfClass(Bee.class, aABB); +- if (!entitiesOfClass.isEmpty()) { +- List entitiesOfClass1 = level.getEntitiesOfClass(Player.class, aABB); +- if (entitiesOfClass1.isEmpty()) { ++ AABB axisalignedbb = (new AABB(pos)).inflate(8.0D, 6.0D, 8.0D); ++ List list = level.getEntitiesOfClass(Bee.class, axisalignedbb); ++ ++ if (!list.isEmpty()) { ++ List list1 = level.getEntitiesOfClass(Player.class, axisalignedbb); ++ ++ if (list1.isEmpty()) { + return; + } + +- for (Bee bee : entitiesOfClass) { +- if (bee.getTarget() == null) { +- Player player = Util.getRandom(entitiesOfClass1, level.random); +- bee.setTarget(player); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Bee entitybee = (Bee) iterator.next(); ++ ++ if (entitybee.getTarget() == null) { ++ Player entityhuman = (Player) Util.getRandom(list1, level.random); ++ ++ entitybee.setTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit + } + } + } ++ + } + + public static void dropHoneycomb(Level level, BlockPos pos) { +@@ -118,29 +131,33 @@ + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { +- ItemStack itemInHand = player.getItemInHand(hand); +- int i = state.getValue(HONEY_LEVEL); ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ int i = (Integer) state.getValue(BeehiveBlock.HONEY_LEVEL); + boolean flag = false; ++ + if (i >= 5) { +- Item item = itemInHand.getItem(); +- if (itemInHand.is(Items.SHEARS)) { ++ Item item = itemstack.getItem(); ++ ++ if (itemstack.is(Items.SHEARS)) { + level.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BEEHIVE_SHEAR, SoundSource.BLOCKS, 1.0F, 1.0F); + dropHoneycomb(level, pos); +- itemInHand.hurtAndBreak(1, player, user -> user.broadcastBreakEvent(hand)); ++ itemstack.hurtAndBreak(1, player, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(hand); ++ }); + flag = true; +- level.gameEvent(player, GameEvent.SHEAR, pos); +- } else if (itemInHand.is(Items.GLASS_BOTTLE)) { +- itemInHand.shrink(1); ++ level.gameEvent((Entity) player, GameEvent.SHEAR, pos); ++ } else if (itemstack.is(Items.GLASS_BOTTLE)) { ++ itemstack.shrink(1); + level.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.BLOCKS, 1.0F, 1.0F); +- if (itemInHand.isEmpty()) { ++ if (itemstack.isEmpty()) { + player.setItemInHand(hand, new ItemStack(Items.HONEY_BOTTLE)); + } else if (!player.getInventory().add(new ItemStack(Items.HONEY_BOTTLE))) { + player.drop(new ItemStack(Items.HONEY_BOTTLE), false); + } + + flag = true; +- level.gameEvent(player, GameEvent.FLUID_PICKUP, pos); ++ level.gameEvent((Entity) player, GameEvent.FLUID_PICKUP, pos); + } + + if (!level.isClientSide() && flag) { +@@ -154,7 +171,7 @@ + this.angerNearbyBees(level, pos); + } + +- this.releaseBeesAndResetHoneyLevel(level, state, pos, player, BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY); ++ this.releaseBeesAndResetHoneyLevel(level, state, pos, player, BeehiveBlockEntity.ReleaseStatus.EMERGENCY); + } else { + this.resetHoneyLevel(level, state, pos); + } +@@ -166,141 +183,148 @@ + } + + private boolean hiveContainsBees(Level level, BlockPos pos) { +- return level.getBlockEntity(pos) instanceof BeehiveBlockEntity beehiveBlockEntity && !beehiveBlockEntity.isEmpty(); ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof BeehiveBlockEntity) { ++ BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) tileentity; ++ ++ return !tileentitybeehive.isEmpty(); ++ } else { ++ return false; ++ } + } + +- public void releaseBeesAndResetHoneyLevel( +- Level level, BlockState state, BlockPos pos, @Nullable Player player, BeehiveBlockEntity.BeeReleaseStatus beeReleaseStatus +- ) { ++ public void releaseBeesAndResetHoneyLevel(Level level, IBlockData state, BlockPos pos, @Nullable Player player, BeehiveBlockEntity.ReleaseStatus beeReleaseStatus) { + this.resetHoneyLevel(level, state, pos); +- if (level.getBlockEntity(pos) instanceof BeehiveBlockEntity beehiveBlockEntity) { +- beehiveBlockEntity.emptyAllLivingFromHive(player, state, beeReleaseStatus); ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof BeehiveBlockEntity) { ++ BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) tileentity; ++ ++ tileentitybeehive.emptyAllLivingFromHive(player, state, beeReleaseStatus); + } ++ + } + +- public void resetHoneyLevel(Level level, BlockState state, BlockPos pos) { +- level.setBlock(pos, state.setValue(HONEY_LEVEL, Integer.valueOf(0)), 3); ++ public void resetHoneyLevel(Level level, IBlockData state, BlockPos pos) { ++ level.setBlock(pos, (IBlockData) state.setValue(BeehiveBlock.HONEY_LEVEL, 0), 3); + } + + @Override +- public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { +- if (state.getValue(HONEY_LEVEL) >= 5) { +- for (int i = 0; i < random.nextInt(1) + 1; i++) { ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if ((Integer) state.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) { ++ for (int i = 0; i < random.nextInt(1) + 1; ++i) { + this.trySpawnDripParticles(level, pos, state); + } + } ++ + } + +- private void trySpawnDripParticles(Level level, BlockPos pos, BlockState state) { +- if (state.getFluidState().isEmpty() && !(level.random.nextFloat() < 0.3F)) { +- VoxelShape collisionShape = state.getCollisionShape(level, pos); +- double d = collisionShape.max(Direction.Axis.Y); +- if (d >= 1.0 && !state.is(BlockTags.IMPERMEABLE)) { +- double d1 = collisionShape.min(Direction.Axis.Y); +- if (d1 > 0.0) { +- this.spawnParticle(level, pos, collisionShape, (double)pos.getY() + d1 - 0.05); ++ private void trySpawnDripParticles(Level level, BlockPos pos, IBlockData state) { ++ if (state.getFluidState().isEmpty() && level.random.nextFloat() >= 0.3F) { ++ VoxelShape voxelshape = state.getCollisionShape(level, pos); ++ double d0 = voxelshape.max(Direction.Axis.Y); ++ ++ if (d0 >= 1.0D && !state.is(BlockTags.IMPERMEABLE)) { ++ double d1 = voxelshape.min(Direction.Axis.Y); ++ ++ if (d1 > 0.0D) { ++ this.spawnParticle(level, pos, voxelshape, (double) pos.getY() + d1 - 0.05D); + } else { +- BlockPos blockPos = pos.below(); +- BlockState blockState = level.getBlockState(blockPos); +- VoxelShape collisionShape1 = blockState.getCollisionShape(level, blockPos); +- double d2 = collisionShape1.max(Direction.Axis.Y); +- if ((d2 < 1.0 || !blockState.isCollisionShapeFullBlock(level, blockPos)) && blockState.getFluidState().isEmpty()) { +- this.spawnParticle(level, pos, collisionShape, (double)pos.getY() - 0.05); ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ VoxelShape voxelshape1 = iblockdata1.getCollisionShape(level, blockposition1); ++ double d2 = voxelshape1.max(Direction.Axis.Y); ++ ++ if ((d2 < 1.0D || !iblockdata1.isCollisionShapeFullBlock(level, blockposition1)) && iblockdata1.getFluidState().isEmpty()) { ++ this.spawnParticle(level, pos, voxelshape, (double) pos.getY() - 0.05D); + } + } + } ++ + } + } + + private void spawnParticle(Level level, BlockPos pos, VoxelShape shape, double y) { +- this.spawnFluidParticle( +- level, +- (double)pos.getX() + shape.min(Direction.Axis.X), +- (double)pos.getX() + shape.max(Direction.Axis.X), +- (double)pos.getZ() + shape.min(Direction.Axis.Z), +- (double)pos.getZ() + shape.max(Direction.Axis.Z), +- y +- ); ++ this.spawnFluidParticle(level, (double) pos.getX() + shape.min(Direction.Axis.X), (double) pos.getX() + shape.max(Direction.Axis.X), (double) pos.getZ() + shape.min(Direction.Axis.Z), (double) pos.getZ() + shape.max(Direction.Axis.Z), y); + } + +- private void spawnFluidParticle(Level particleData, double x1, double x2, double z1, double z2, double y) { +- particleData.addParticle( +- ParticleTypes.DRIPPING_HONEY, +- Mth.lerp(particleData.random.nextDouble(), x1, x2), +- y, +- Mth.lerp(particleData.random.nextDouble(), z1, z2), +- 0.0, +- 0.0, +- 0.0 +- ); ++ private void spawnFluidParticle(Level particleData, double x1, double d1, double x2, double d3, double z1) { ++ particleData.addParticle(ParticleTypes.DRIPPING_HONEY, Mth.lerp(particleData.random.nextDouble(), x1, d1), z1, Mth.lerp(particleData.random.nextDouble(), x2, d3), 0.0D, 0.0D, 0.0D); + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return (IBlockData) this.defaultBlockState().setValue(BeehiveBlock.FACING, context.getHorizontalDirection().getOpposite()); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(HONEY_LEVEL, FACING); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(BeehiveBlock.HONEY_LEVEL, BeehiveBlock.FACING); + } + + @Override +- public RenderShape getRenderShape(BlockState state) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Nullable + @Override +- public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { + return new BeehiveBlockEntity(pos, state); + } + + @Nullable + @Override +- public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { + return level.isClientSide ? null : createTickerHelper(blockEntityType, BlockEntityType.BEEHIVE, BeehiveBlockEntity::serverTick); + } + + @Override +- public BlockState playerWillDestroy(Level level, BlockPos blockPos, BlockState blockState, Player player) { +- if (!level.isClientSide +- && player.isCreative() +- && level.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS) +- && level.getBlockEntity(blockPos) instanceof BeehiveBlockEntity beehiveBlockEntity) { +- ItemStack itemStack = new ItemStack(this); +- int i = blockState.getValue(HONEY_LEVEL); +- boolean flag = !beehiveBlockEntity.isEmpty(); +- if (flag || i > 0) { +- if (flag) { +- CompoundTag compoundTag = new CompoundTag(); +- compoundTag.put("Bees", beehiveBlockEntity.writeBees()); +- BlockItem.setBlockEntityData(itemStack, BlockEntityType.BEEHIVE, compoundTag); +- } ++ public IBlockData playerWillDestroy(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ if (!world.isClientSide && entityhuman.isCreative() && world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { ++ BlockEntity tileentity = world.getBlockEntity(blockposition); + +- CompoundTag compoundTag = new CompoundTag(); +- compoundTag.putInt("honey_level", i); +- itemStack.addTagElement("BlockStateTag", compoundTag); +- ItemEntity itemEntity = new ItemEntity(level, (double)blockPos.getX(), (double)blockPos.getY(), (double)blockPos.getZ(), itemStack); +- itemEntity.setDefaultPickUpDelay(); +- level.addFreshEntity(itemEntity); ++ if (tileentity instanceof BeehiveBlockEntity) { ++ BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) tileentity; ++ ItemStack itemstack = new ItemStack(this); ++ int i = (Integer) iblockdata.getValue(BeehiveBlock.HONEY_LEVEL); ++ boolean flag = !tileentitybeehive.isEmpty(); ++ ++ if (flag || i > 0) { ++ CompoundTag nbttagcompound; ++ ++ if (flag) { ++ nbttagcompound = new CompoundTag(); ++ nbttagcompound.put("Bees", tileentitybeehive.writeBees()); ++ BlockItem.setBlockEntityData(itemstack, BlockEntityType.BEEHIVE, nbttagcompound); ++ } ++ ++ nbttagcompound = new CompoundTag(); ++ nbttagcompound.putInt("honey_level", i); ++ itemstack.addTagElement("BlockStateTag", nbttagcompound); ++ ItemEntity entityitem = new ItemEntity(world, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), itemstack); ++ ++ entityitem.setDefaultPickUpDelay(); ++ world.addFreshEntity(entityitem); ++ } + } + } + +- return super.playerWillDestroy(level, blockPos, blockState, player); ++ return super.playerWillDestroy(world, blockposition, iblockdata, entityhuman); + } + + @Override +- public List getDrops(BlockState state, LootParams.Builder params) { +- Entity entity = params.getOptionalParameter(LootContextParams.THIS_ENTITY); +- if (entity instanceof PrimedTnt +- || entity instanceof Creeper +- || entity instanceof WitherSkull +- || entity instanceof WitherBoss +- || entity instanceof MinecartTNT) { +- BlockEntity blockEntity = params.getOptionalParameter(LootContextParams.BLOCK_ENTITY); +- if (blockEntity instanceof BeehiveBlockEntity beehiveBlockEntity) { +- beehiveBlockEntity.emptyAllLivingFromHive(null, state, BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY); ++ public List getDrops(IBlockData state, LootParams.Builder params) { ++ Entity entity = (Entity) params.getOptionalParameter(LootContextParams.THIS_ENTITY); ++ ++ if (entity instanceof PrimedTnt || entity instanceof Creeper || entity instanceof WitherSkull || entity instanceof WitherBoss || entity instanceof MinecartTNT) { ++ BlockEntity tileentity = (BlockEntity) params.getOptionalParameter(LootContextParams.BLOCK_ENTITY); ++ ++ if (tileentity instanceof BeehiveBlockEntity) { ++ BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) tileentity; ++ ++ tileentitybeehive.emptyAllLivingFromHive((Player) null, state, BeehiveBlockEntity.ReleaseStatus.EMERGENCY); + } + } + +@@ -308,23 +332,27 @@ + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- if (level.getBlockState(facingPos).getBlock() instanceof FireBlock && level.getBlockEntity(currentPos) instanceof BeehiveBlockEntity beehiveBlockEntity +- ) +- { +- beehiveBlockEntity.emptyAllLivingFromHive(null, state, BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if (level.getBlockState(facingPos).getBlock() instanceof FireBlock) { ++ BlockEntity tileentity = level.getBlockEntity(currentPos); ++ ++ if (tileentity instanceof BeehiveBlockEntity) { ++ BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) tileentity; ++ ++ tileentitybeehive.emptyAllLivingFromHive((Player) null, state, BeehiveBlockEntity.ReleaseStatus.EMERGENCY); ++ } + } + + return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- public BlockState rotate(BlockState state, Rotation rotation) { +- return state.setValue(FACING, rotation.rotate(state.getValue(FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return (IBlockData) state.setValue(BeehiveBlock.FACING, rotation.rotate((Direction) state.getValue(BeehiveBlock.FACING))); + } + + @Override +- public BlockState mirror(BlockState state, Mirror mirror) { +- return state.rotate(mirror.getRotation(state.getValue(FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(BeehiveBlock.FACING))); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/BellBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/BellBlock.java.patch new file mode 100644 index 0000000000..1a998c5dbd --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/BellBlock.java.patch @@ -0,0 +1,407 @@ +--- a/net/minecraft/world/level/block/BellBlock.java ++++ b/net/minecraft/world/level/block/BellBlock.java +@@ -8,7 +8,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; +@@ -25,7 +25,7 @@ + import net.minecraft.world.level.block.entity.BlockEntityTicker; + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BellAttachType; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; +@@ -33,74 +33,78 @@ + import net.minecraft.world.level.block.state.properties.DirectionProperty; + import net.minecraft.world.level.block.state.properties.EnumProperty; + import net.minecraft.world.level.gameevent.GameEvent; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; + + public class BellBlock extends BaseEntityBlock { ++ + public static final MapCodec CODEC = simpleCodec(BellBlock::new); + public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING; + public static final EnumProperty ATTACHMENT = BlockStateProperties.BELL_ATTACHMENT; + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; +- private static final VoxelShape NORTH_SOUTH_FLOOR_SHAPE = Block.box(0.0, 0.0, 4.0, 16.0, 16.0, 12.0); +- private static final VoxelShape EAST_WEST_FLOOR_SHAPE = Block.box(4.0, 0.0, 0.0, 12.0, 16.0, 16.0); +- private static final VoxelShape BELL_TOP_SHAPE = Block.box(5.0, 6.0, 5.0, 11.0, 13.0, 11.0); +- private static final VoxelShape BELL_BOTTOM_SHAPE = Block.box(4.0, 4.0, 4.0, 12.0, 6.0, 12.0); +- private static final VoxelShape BELL_SHAPE = Shapes.or(BELL_BOTTOM_SHAPE, BELL_TOP_SHAPE); +- private static final VoxelShape NORTH_SOUTH_BETWEEN = Shapes.or(BELL_SHAPE, Block.box(7.0, 13.0, 0.0, 9.0, 15.0, 16.0)); +- private static final VoxelShape EAST_WEST_BETWEEN = Shapes.or(BELL_SHAPE, Block.box(0.0, 13.0, 7.0, 16.0, 15.0, 9.0)); +- private static final VoxelShape TO_WEST = Shapes.or(BELL_SHAPE, Block.box(0.0, 13.0, 7.0, 13.0, 15.0, 9.0)); +- private static final VoxelShape TO_EAST = Shapes.or(BELL_SHAPE, Block.box(3.0, 13.0, 7.0, 16.0, 15.0, 9.0)); +- private static final VoxelShape TO_NORTH = Shapes.or(BELL_SHAPE, Block.box(7.0, 13.0, 0.0, 9.0, 15.0, 13.0)); +- private static final VoxelShape TO_SOUTH = Shapes.or(BELL_SHAPE, Block.box(7.0, 13.0, 3.0, 9.0, 15.0, 16.0)); +- private static final VoxelShape CEILING_SHAPE = Shapes.or(BELL_SHAPE, Block.box(7.0, 13.0, 7.0, 9.0, 16.0, 9.0)); ++ private static final VoxelShape NORTH_SOUTH_FLOOR_SHAPE = Block.box(0.0D, 0.0D, 4.0D, 16.0D, 16.0D, 12.0D); ++ private static final VoxelShape EAST_WEST_FLOOR_SHAPE = Block.box(4.0D, 0.0D, 0.0D, 12.0D, 16.0D, 16.0D); ++ private static final VoxelShape BELL_TOP_SHAPE = Block.box(5.0D, 6.0D, 5.0D, 11.0D, 13.0D, 11.0D); ++ private static final VoxelShape BELL_BOTTOM_SHAPE = Block.box(4.0D, 4.0D, 4.0D, 12.0D, 6.0D, 12.0D); ++ private static final VoxelShape BELL_SHAPE = Shapes.or(BellBlock.BELL_BOTTOM_SHAPE, BellBlock.BELL_TOP_SHAPE); ++ private static final VoxelShape NORTH_SOUTH_BETWEEN = Shapes.or(BellBlock.BELL_SHAPE, Block.box(7.0D, 13.0D, 0.0D, 9.0D, 15.0D, 16.0D)); ++ private static final VoxelShape EAST_WEST_BETWEEN = Shapes.or(BellBlock.BELL_SHAPE, Block.box(0.0D, 13.0D, 7.0D, 16.0D, 15.0D, 9.0D)); ++ private static final VoxelShape TO_WEST = Shapes.or(BellBlock.BELL_SHAPE, Block.box(0.0D, 13.0D, 7.0D, 13.0D, 15.0D, 9.0D)); ++ private static final VoxelShape TO_EAST = Shapes.or(BellBlock.BELL_SHAPE, Block.box(3.0D, 13.0D, 7.0D, 16.0D, 15.0D, 9.0D)); ++ private static final VoxelShape TO_NORTH = Shapes.or(BellBlock.BELL_SHAPE, Block.box(7.0D, 13.0D, 0.0D, 9.0D, 15.0D, 13.0D)); ++ private static final VoxelShape TO_SOUTH = Shapes.or(BellBlock.BELL_SHAPE, Block.box(7.0D, 13.0D, 3.0D, 9.0D, 15.0D, 16.0D)); ++ private static final VoxelShape CEILING_SHAPE = Shapes.or(BellBlock.BELL_SHAPE, Block.box(7.0D, 13.0D, 7.0D, 9.0D, 16.0D, 9.0D)); + public static final int EVENT_BELL_RING = 1; + + @Override + public MapCodec codec() { +- return CODEC; ++ return BellBlock.CODEC; + } + + public BellBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState( +- this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(ATTACHMENT, BellAttachType.FLOOR).setValue(POWERED, Boolean.valueOf(false)) +- ); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(BellBlock.FACING, Direction.NORTH)).setValue(BellBlock.ATTACHMENT, BellAttachType.FLOOR)).setValue(BellBlock.POWERED, false)); + } + + @Override +- public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { +- boolean hasNeighborSignal = level.hasNeighborSignal(pos); +- if (hasNeighborSignal != state.getValue(POWERED)) { +- if (hasNeighborSignal) { +- this.attemptToRing(level, pos, null); ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ boolean flag1 = level.hasNeighborSignal(pos); ++ ++ if (flag1 != (Boolean) state.getValue(BellBlock.POWERED)) { ++ if (flag1) { ++ this.attemptToRing(level, pos, (Direction) null); + } + +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(hasNeighborSignal)), 3); ++ level.setBlock(pos, (IBlockData) state.setValue(BellBlock.POWERED, flag1), 3); + } ++ + } + + @Override +- public void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) { +- Entity owner = projectile.getOwner(); +- Player player = owner instanceof Player ? (Player)owner : null; +- this.onHit(level, state, hit, player, true); ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { ++ Entity entity = projectile.getOwner(); ++ Player entityhuman = entity instanceof Player ? (Player) entity : null; ++ ++ this.onHit(level, state, hit, entityhuman, true); + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + return this.onHit(level, state, hit, player, true) ? InteractionResult.sidedSuccess(level.isClientSide) : InteractionResult.PASS; + } + +- public boolean onHit(Level level, BlockState state, BlockHitResult result, @Nullable Player player, boolean canRingBell) { +- Direction direction = result.getDirection(); +- BlockPos blockPos = result.getBlockPos(); +- boolean flag = !canRingBell || this.isProperHit(state, direction, result.getLocation().y - (double)blockPos.getY()); +- if (flag) { +- boolean flag1 = this.attemptToRing(player, level, blockPos, direction); +- if (flag1 && player != null) { ++ public boolean onHit(Level level, IBlockData state, BlockHitResult result, @Nullable Player player, boolean canRingBell) { ++ Direction enumdirection = result.getDirection(); ++ BlockPos blockposition = result.getBlockPos(); ++ boolean flag1 = !canRingBell || this.isProperHit(state, enumdirection, result.getLocation().y - (double) blockposition.getY()); ++ ++ if (flag1) { ++ boolean flag2 = this.attemptToRing(player, level, blockposition, enumdirection); ++ ++ if (flag2 && player != null) { + player.awardStat(Stats.BELL_RING); + } + +@@ -110,16 +114,17 @@ + } + } + +- private boolean isProperHit(BlockState pos, Direction direction, double distanceY) { +- if (direction.getAxis() != Direction.Axis.Y && !(distanceY > 0.8124F)) { +- Direction direction1 = pos.getValue(FACING); +- BellAttachType bellAttachType = pos.getValue(ATTACHMENT); +- switch (bellAttachType) { ++ private boolean isProperHit(IBlockData pos, Direction direction, double distanceY) { ++ if (direction.getAxis() != Direction.Axis.Y && distanceY <= 0.8123999834060669D) { ++ Direction enumdirection1 = (Direction) pos.getValue(BellBlock.FACING); ++ BellAttachType blockpropertybellattach = (BellAttachType) pos.getValue(BellBlock.ATTACHMENT); ++ ++ switch (blockpropertybellattach) { + case FLOOR: +- return direction1.getAxis() == direction.getAxis(); ++ return enumdirection1.getAxis() == direction.getAxis(); + case SINGLE_WALL: + case DOUBLE_WALL: +- return direction1.getAxis() != direction.getAxis(); ++ return enumdirection1.getAxis() != direction.getAxis(); + case CEILING: + return true; + default: +@@ -131,18 +136,24 @@ + } + + public boolean attemptToRing(Level level, BlockPos pos, @Nullable Direction direction) { +- return this.attemptToRing(null, level, pos, direction); ++ return this.attemptToRing((Entity) null, level, pos, direction); + } + + public boolean attemptToRing(@Nullable Entity entity, Level level, BlockPos pos, @Nullable Direction direction) { +- BlockEntity blockEntity = level.getBlockEntity(pos); +- if (!level.isClientSide && blockEntity instanceof BellBlockEntity) { ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (!level.isClientSide && tileentity instanceof BellBlockEntity) { + if (direction == null) { +- direction = level.getBlockState(pos).getValue(FACING); ++ direction = (Direction) level.getBlockState(pos).getValue(BellBlock.FACING); + } ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBellRingEvent(level, pos, direction, entity)) { ++ return false; ++ } ++ // CraftBukkit end + +- ((BellBlockEntity)blockEntity).onHit(direction); +- level.playSound(null, pos, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2.0F, 1.0F); ++ ((BellBlockEntity) tileentity).onHit(direction); ++ level.playSound((Player) null, pos, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2.0F, 1.0F); + level.gameEvent(entity, GameEvent.BLOCK_CHANGE, pos); + return true; + } else { +@@ -150,71 +161,55 @@ + } + } + +- private VoxelShape getVoxelShape(BlockState state) { +- Direction direction = state.getValue(FACING); +- BellAttachType bellAttachType = state.getValue(ATTACHMENT); +- if (bellAttachType == BellAttachType.FLOOR) { +- return direction != Direction.NORTH && direction != Direction.SOUTH ? EAST_WEST_FLOOR_SHAPE : NORTH_SOUTH_FLOOR_SHAPE; +- } else if (bellAttachType == BellAttachType.CEILING) { +- return CEILING_SHAPE; +- } else if (bellAttachType == BellAttachType.DOUBLE_WALL) { +- return direction != Direction.NORTH && direction != Direction.SOUTH ? EAST_WEST_BETWEEN : NORTH_SOUTH_BETWEEN; +- } else if (direction == Direction.NORTH) { +- return TO_NORTH; +- } else if (direction == Direction.SOUTH) { +- return TO_SOUTH; +- } else { +- return direction == Direction.EAST ? TO_EAST : TO_WEST; +- } ++ private VoxelShape getVoxelShape(IBlockData state) { ++ Direction enumdirection = (Direction) state.getValue(BellBlock.FACING); ++ BellAttachType blockpropertybellattach = (BellAttachType) state.getValue(BellBlock.ATTACHMENT); ++ ++ return blockpropertybellattach == BellAttachType.FLOOR ? (enumdirection != Direction.NORTH && enumdirection != Direction.SOUTH ? BellBlock.EAST_WEST_FLOOR_SHAPE : BellBlock.NORTH_SOUTH_FLOOR_SHAPE) : (blockpropertybellattach == BellAttachType.CEILING ? BellBlock.CEILING_SHAPE : (blockpropertybellattach == BellAttachType.DOUBLE_WALL ? (enumdirection != Direction.NORTH && enumdirection != Direction.SOUTH ? BellBlock.EAST_WEST_BETWEEN : BellBlock.NORTH_SOUTH_BETWEEN) : (enumdirection == Direction.NORTH ? BellBlock.TO_NORTH : (enumdirection == Direction.SOUTH ? BellBlock.TO_SOUTH : (enumdirection == Direction.EAST ? BellBlock.TO_EAST : BellBlock.TO_WEST))))); + } + + @Override +- public VoxelShape getCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return this.getVoxelShape(state); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return this.getVoxelShape(state); + } + + @Override +- public RenderShape getRenderShape(BlockState state) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Nullable + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- Direction clickedFace = context.getClickedFace(); +- BlockPos clickedPos = context.getClickedPos(); +- Level level = context.getLevel(); +- Direction.Axis axis = clickedFace.getAxis(); +- if (axis == Direction.Axis.Y) { +- BlockState blockState = this.defaultBlockState() +- .setValue(ATTACHMENT, clickedFace == Direction.DOWN ? BellAttachType.CEILING : BellAttachType.FLOOR) +- .setValue(FACING, context.getHorizontalDirection()); +- if (blockState.canSurvive(context.getLevel(), clickedPos)) { +- return blockState; ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ Direction enumdirection = context.getClickedFace(); ++ BlockPos blockposition = context.getClickedPos(); ++ Level world = context.getLevel(); ++ Direction.Axis enumdirection_enumaxis = enumdirection.getAxis(); ++ IBlockData iblockdata; ++ ++ if (enumdirection_enumaxis == Direction.Axis.Y) { ++ iblockdata = (IBlockData) ((IBlockData) this.defaultBlockState().setValue(BellBlock.ATTACHMENT, enumdirection == Direction.DOWN ? BellAttachType.CEILING : BellAttachType.FLOOR)).setValue(BellBlock.FACING, context.getHorizontalDirection()); ++ if (iblockdata.canSurvive(context.getLevel(), blockposition)) { ++ return iblockdata; + } + } else { +- boolean flag = axis == Direction.Axis.X +- && level.getBlockState(clickedPos.west()).isFaceSturdy(level, clickedPos.west(), Direction.EAST) +- && level.getBlockState(clickedPos.east()).isFaceSturdy(level, clickedPos.east(), Direction.WEST) +- || axis == Direction.Axis.Z +- && level.getBlockState(clickedPos.north()).isFaceSturdy(level, clickedPos.north(), Direction.SOUTH) +- && level.getBlockState(clickedPos.south()).isFaceSturdy(level, clickedPos.south(), Direction.NORTH); +- BlockState blockState = this.defaultBlockState() +- .setValue(FACING, clickedFace.getOpposite()) +- .setValue(ATTACHMENT, flag ? BellAttachType.DOUBLE_WALL : BellAttachType.SINGLE_WALL); +- if (blockState.canSurvive(context.getLevel(), context.getClickedPos())) { +- return blockState; ++ boolean flag = enumdirection_enumaxis == Direction.Axis.X && world.getBlockState(blockposition.west()).isFaceSturdy(world, blockposition.west(), Direction.EAST) && world.getBlockState(blockposition.east()).isFaceSturdy(world, blockposition.east(), Direction.WEST) || enumdirection_enumaxis == Direction.Axis.Z && world.getBlockState(blockposition.north()).isFaceSturdy(world, blockposition.north(), Direction.SOUTH) && world.getBlockState(blockposition.south()).isFaceSturdy(world, blockposition.south(), Direction.NORTH); ++ ++ iblockdata = (IBlockData) ((IBlockData) this.defaultBlockState().setValue(BellBlock.FACING, enumdirection.getOpposite())).setValue(BellBlock.ATTACHMENT, flag ? BellAttachType.DOUBLE_WALL : BellAttachType.SINGLE_WALL); ++ if (iblockdata.canSurvive(context.getLevel(), context.getClickedPos())) { ++ return iblockdata; + } + +- boolean isFaceSturdy = level.getBlockState(clickedPos.below()).isFaceSturdy(level, clickedPos.below(), Direction.UP); +- BlockState var10 = blockState.setValue(ATTACHMENT, isFaceSturdy ? BellAttachType.FLOOR : BellAttachType.CEILING); +- if (var10.canSurvive(context.getLevel(), context.getClickedPos())) { +- return var10; ++ boolean flag1 = world.getBlockState(blockposition.below()).isFaceSturdy(world, blockposition.below(), Direction.UP); ++ ++ iblockdata = (IBlockData) iblockdata.setValue(BellBlock.ATTACHMENT, flag1 ? BellAttachType.FLOOR : BellAttachType.CEILING); ++ if (iblockdata.canSurvive(context.getLevel(), context.getClickedPos())) { ++ return iblockdata; + } + } + +@@ -222,30 +217,29 @@ + } + + @Override +- public void onExplosionHit(BlockState blockState, Level level, BlockPos blockPos, Explosion explosion, BiConsumer biConsumer) { +- if (explosion.getBlockInteraction() == Explosion.BlockInteraction.TRIGGER_BLOCK && !level.isClientSide()) { +- this.attemptToRing(level, blockPos, null); ++ public void onExplosionHit(IBlockData iblockdata, Level world, BlockPos blockposition, Explosion explosion, BiConsumer biconsumer) { ++ if (explosion.getBlockInteraction() == Explosion.Effect.TRIGGER_BLOCK && !world.isClientSide()) { ++ this.attemptToRing(world, blockposition, (Direction) null); + } + +- super.onExplosionHit(blockState, level, blockPos, explosion, biConsumer); ++ super.onExplosionHit(iblockdata, world, blockposition, explosion, biconsumer); + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- BellAttachType bellAttachType = state.getValue(ATTACHMENT); +- Direction opposite = getConnectedDirection(state).getOpposite(); +- if (opposite == facing && !state.canSurvive(level, currentPos) && bellAttachType != BellAttachType.DOUBLE_WALL) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ BellAttachType blockpropertybellattach = (BellAttachType) state.getValue(BellBlock.ATTACHMENT); ++ Direction enumdirection1 = getConnectedDirection(state).getOpposite(); ++ ++ if (enumdirection1 == facing && !state.canSurvive(level, currentPos) && blockpropertybellattach != BellAttachType.DOUBLE_WALL) { + return Blocks.AIR.defaultBlockState(); + } else { +- if (facing.getAxis() == state.getValue(FACING).getAxis()) { +- if (bellAttachType == BellAttachType.DOUBLE_WALL && !facingState.isFaceSturdy(level, facingPos, facing)) { +- return state.setValue(ATTACHMENT, BellAttachType.SINGLE_WALL).setValue(FACING, facing.getOpposite()); ++ if (facing.getAxis() == ((Direction) state.getValue(BellBlock.FACING)).getAxis()) { ++ if (blockpropertybellattach == BellAttachType.DOUBLE_WALL && !facingState.isFaceSturdy(level, facingPos, facing)) { ++ return (IBlockData) ((IBlockData) state.setValue(BellBlock.ATTACHMENT, BellAttachType.SINGLE_WALL)).setValue(BellBlock.FACING, facing.getOpposite()); + } + +- if (bellAttachType == BellAttachType.SINGLE_WALL +- && opposite.getOpposite() == facing +- && facingState.isFaceSturdy(level, facingPos, state.getValue(FACING))) { +- return state.setValue(ATTACHMENT, BellAttachType.DOUBLE_WALL); ++ if (blockpropertybellattach == BellAttachType.SINGLE_WALL && enumdirection1.getOpposite() == facing && facingState.isFaceSturdy(level, facingPos, (Direction) state.getValue(BellBlock.FACING))) { ++ return (IBlockData) state.setValue(BellBlock.ATTACHMENT, BellAttachType.DOUBLE_WALL); + } + } + +@@ -254,53 +248,52 @@ + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { +- Direction opposite = getConnectedDirection(state).getOpposite(); +- return opposite == Direction.UP +- ? Block.canSupportCenter(level, pos.above(), Direction.DOWN) +- : FaceAttachedHorizontalDirectionalBlock.canAttach(level, pos, opposite); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ Direction enumdirection = getConnectedDirection(state).getOpposite(); ++ ++ return enumdirection == Direction.UP ? Block.canSupportCenter(level, pos.above(), Direction.DOWN) : FaceAttachedHorizontalDirectionalBlock.canAttach(level, pos, enumdirection); + } + +- private static Direction getConnectedDirection(BlockState state) { +- switch ((BellAttachType)state.getValue(ATTACHMENT)) { ++ private static Direction getConnectedDirection(IBlockData state) { ++ switch ((BellAttachType) state.getValue(BellBlock.ATTACHMENT)) { + case FLOOR: + return Direction.UP; + case CEILING: + return Direction.DOWN; + default: +- return state.getValue(FACING).getOpposite(); ++ return ((Direction) state.getValue(BellBlock.FACING)).getOpposite(); + } + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(FACING, ATTACHMENT, POWERED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(BellBlock.FACING, BellBlock.ATTACHMENT, BellBlock.POWERED); + } + + @Nullable + @Override +- public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { + return new BellBlockEntity(pos, state); + } + + @Nullable + @Override +- public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { + return createTickerHelper(blockEntityType, BlockEntityType.BELL, level.isClientSide ? BellBlockEntity::clientTick : BellBlockEntity::serverTick); + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + + @Override +- public BlockState rotate(BlockState state, Rotation rotation) { +- return state.setValue(FACING, rotation.rotate(state.getValue(FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return (IBlockData) state.setValue(BellBlock.FACING, rotation.rotate((Direction) state.getValue(BellBlock.FACING))); + } + + @Override +- public BlockState mirror(BlockState state, Mirror mirror) { +- return state.rotate(mirror.getRotation(state.getValue(FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(BellBlock.FACING))); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/BigDripleafBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/BigDripleafBlock.java.patch new file mode 100644 index 0000000000..6b52b181e1 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/BigDripleafBlock.java.patch @@ -0,0 +1,403 @@ +--- a/net/minecraft/world/level/block/BigDripleafBlock.java ++++ b/net/minecraft/world/level/block/BigDripleafBlock.java +@@ -17,6 +17,7 @@ + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.Projectile; + import net.minecraft.world.item.context.BlockPlaceContext; + import net.minecraft.world.level.BlockGetter; +@@ -25,13 +26,14 @@ + import net.minecraft.world.level.LevelHeightAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.block.state.properties.EnumProperty; + import net.minecraft.world.level.block.state.properties.Tilt; + import net.minecraft.world.level.gameevent.GameEvent; ++import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.BlockHitResult; +@@ -39,243 +41,262 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end + + public class BigDripleafBlock extends HorizontalDirectionalBlock implements BonemealableBlock, SimpleWaterloggedBlock { ++ + public static final MapCodec CODEC = simpleCodec(BigDripleafBlock::new); + private static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; + private static final EnumProperty TILT = BlockStateProperties.TILT; + private static final int NO_TICK = -1; +- private static final Object2IntMap DELAY_UNTIL_NEXT_TILT_STATE = Util.make(new Object2IntArrayMap<>(), map -> { +- map.defaultReturnValue(-1); +- map.put(Tilt.UNSTABLE, 10); +- map.put(Tilt.PARTIAL, 10); +- map.put(Tilt.FULL, 100); ++ private static final Object2IntMap DELAY_UNTIL_NEXT_TILT_STATE = (Object2IntMap) Util.make(new Object2IntArrayMap(), (object2intarraymap) -> { ++ object2intarraymap.defaultReturnValue(-1); ++ object2intarraymap.put(Tilt.UNSTABLE, 10); ++ object2intarraymap.put(Tilt.PARTIAL, 10); ++ object2intarraymap.put(Tilt.FULL, 100); + }); + private static final int MAX_GEN_HEIGHT = 5; + private static final int STEM_WIDTH = 6; + private static final int ENTITY_DETECTION_MIN_Y = 11; + private static final int LOWEST_LEAF_TOP = 13; +- private static final Map LEAF_SHAPES = ImmutableMap.of( +- Tilt.NONE, +- Block.box(0.0, 11.0, 0.0, 16.0, 15.0, 16.0), +- Tilt.UNSTABLE, +- Block.box(0.0, 11.0, 0.0, 16.0, 15.0, 16.0), +- Tilt.PARTIAL, +- Block.box(0.0, 11.0, 0.0, 16.0, 13.0, 16.0), +- Tilt.FULL, +- Shapes.empty() +- ); +- private static final VoxelShape STEM_SLICER = Block.box(0.0, 13.0, 0.0, 16.0, 16.0, 16.0); +- private static final Map STEM_SHAPES = ImmutableMap.of( +- Direction.NORTH, +- Shapes.joinUnoptimized(BigDripleafStemBlock.NORTH_SHAPE, STEM_SLICER, BooleanOp.ONLY_FIRST), +- Direction.SOUTH, +- Shapes.joinUnoptimized(BigDripleafStemBlock.SOUTH_SHAPE, STEM_SLICER, BooleanOp.ONLY_FIRST), +- Direction.EAST, +- Shapes.joinUnoptimized(BigDripleafStemBlock.EAST_SHAPE, STEM_SLICER, BooleanOp.ONLY_FIRST), +- Direction.WEST, +- Shapes.joinUnoptimized(BigDripleafStemBlock.WEST_SHAPE, STEM_SLICER, BooleanOp.ONLY_FIRST) +- ); +- private final Map shapesCache; ++ private static final Map LEAF_SHAPES = ImmutableMap.of(Tilt.NONE, Block.box(0.0D, 11.0D, 0.0D, 16.0D, 15.0D, 16.0D), Tilt.UNSTABLE, Block.box(0.0D, 11.0D, 0.0D, 16.0D, 15.0D, 16.0D), Tilt.PARTIAL, Block.box(0.0D, 11.0D, 0.0D, 16.0D, 13.0D, 16.0D), Tilt.FULL, Shapes.empty()); ++ private static final VoxelShape STEM_SLICER = Block.box(0.0D, 13.0D, 0.0D, 16.0D, 16.0D, 16.0D); ++ private static final Map STEM_SHAPES = ImmutableMap.of(Direction.NORTH, Shapes.joinUnoptimized(BigDripleafStemBlock.NORTH_SHAPE, BigDripleafBlock.STEM_SLICER, BooleanOp.ONLY_FIRST), Direction.SOUTH, Shapes.joinUnoptimized(BigDripleafStemBlock.SOUTH_SHAPE, BigDripleafBlock.STEM_SLICER, BooleanOp.ONLY_FIRST), Direction.EAST, Shapes.joinUnoptimized(BigDripleafStemBlock.EAST_SHAPE, BigDripleafBlock.STEM_SLICER, BooleanOp.ONLY_FIRST), Direction.WEST, Shapes.joinUnoptimized(BigDripleafStemBlock.WEST_SHAPE, BigDripleafBlock.STEM_SLICER, BooleanOp.ONLY_FIRST)); ++ private final Map shapesCache; + + @Override + public MapCodec codec() { +- return CODEC; ++ return BigDripleafBlock.CODEC; + } + + protected BigDripleafBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState( +- this.stateDefinition.any().setValue(WATERLOGGED, Boolean.valueOf(false)).setValue(FACING, Direction.NORTH).setValue(TILT, Tilt.NONE) +- ); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(BigDripleafBlock.WATERLOGGED, false)).setValue(BigDripleafBlock.FACING, Direction.NORTH)).setValue(BigDripleafBlock.TILT, Tilt.NONE)); + this.shapesCache = this.getShapeForEachState(BigDripleafBlock::calculateShape); + } + +- private static VoxelShape calculateShape(BlockState state) { +- return Shapes.or(LEAF_SHAPES.get(state.getValue(TILT)), STEM_SHAPES.get(state.getValue(FACING))); ++ private static VoxelShape calculateShape(IBlockData state) { ++ return Shapes.or((VoxelShape) BigDripleafBlock.LEAF_SHAPES.get(state.getValue(BigDripleafBlock.TILT)), (VoxelShape) BigDripleafBlock.STEM_SHAPES.get(state.getValue(BigDripleafBlock.FACING))); + } + + public static void placeWithRandomHeight(LevelAccessor level, RandomSource random, BlockPos pos, Direction direction) { +- int randomInt = Mth.nextInt(random, 2, 5); +- BlockPos.MutableBlockPos mutableBlockPos = pos.mutable(); +- int i = 0; ++ int i = Mth.nextInt(random, 2, 5); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); ++ int j = 0; + +- while (i < randomInt && canPlaceAt(level, mutableBlockPos, level.getBlockState(mutableBlockPos))) { +- i++; +- mutableBlockPos.move(Direction.UP); ++ while (j < i && canPlaceAt(level, blockposition_mutableblockposition, level.getBlockState(blockposition_mutableblockposition))) { ++ ++j; ++ blockposition_mutableblockposition.move(Direction.UP); + } + +- int i1 = pos.getY() + i - 1; +- mutableBlockPos.setY(pos.getY()); ++ int k = pos.getY() + j - 1; + +- while (mutableBlockPos.getY() < i1) { +- BigDripleafStemBlock.place(level, mutableBlockPos, level.getFluidState(mutableBlockPos), direction); +- mutableBlockPos.move(Direction.UP); ++ blockposition_mutableblockposition.setY(pos.getY()); ++ ++ while (blockposition_mutableblockposition.getY() < k) { ++ BigDripleafStemBlock.place(level, blockposition_mutableblockposition, level.getFluidState(blockposition_mutableblockposition), direction); ++ blockposition_mutableblockposition.move(Direction.UP); + } + +- place(level, mutableBlockPos, level.getFluidState(mutableBlockPos), direction); ++ place(level, blockposition_mutableblockposition, level.getFluidState(blockposition_mutableblockposition), direction); + } + +- private static boolean canReplace(BlockState state) { ++ private static boolean canReplace(IBlockData state) { + return state.isAir() || state.is(Blocks.WATER) || state.is(Blocks.SMALL_DRIPLEAF); + } + +- protected static boolean canPlaceAt(LevelHeightAccessor level, BlockPos pos, BlockState state) { ++ protected static boolean canPlaceAt(LevelHeightAccessor level, BlockPos pos, IBlockData state) { + return !level.isOutsideBuildHeight(pos) && canReplace(state); + } + + protected static boolean place(LevelAccessor level, BlockPos pos, FluidState fluidState, Direction direction) { +- BlockState blockState = Blocks.BIG_DRIPLEAF +- .defaultBlockState() +- .setValue(WATERLOGGED, Boolean.valueOf(fluidState.isSourceOfType(Fluids.WATER))) +- .setValue(FACING, direction); +- return level.setBlock(pos, blockState, 3); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.BIG_DRIPLEAF.defaultBlockState().setValue(BigDripleafBlock.WATERLOGGED, fluidState.isSourceOfType(Fluids.WATER))).setValue(BigDripleafBlock.FACING, direction); ++ ++ return level.setBlock(pos, iblockdata, 3); + } + + @Override +- public void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) { +- this.setTiltAndScheduleTick(state, level, hit.getBlockPos(), Tilt.FULL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN); ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { ++ this.setTiltAndScheduleTick(state, level, hit.getBlockPos(), Tilt.FULL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN, projectile); // CraftBukkit + } + + @Override +- public FluidState getFluidState(BlockState state) { +- return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(BigDripleafBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { +- BlockPos blockPos = pos.below(); +- BlockState blockState = level.getBlockState(blockPos); +- return blockState.is(this) || blockState.is(Blocks.BIG_DRIPLEAF_STEM) || blockState.is(BlockTags.BIG_DRIPLEAF_PLACEABLE); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ return iblockdata1.is((Block) this) || iblockdata1.is(Blocks.BIG_DRIPLEAF_STEM) || iblockdata1.is(BlockTags.BIG_DRIPLEAF_PLACEABLE); + } + + @Override +- public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { ++ public IBlockData updateShape(IBlockData state, Direction direction, IBlockData neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { + if (direction == Direction.DOWN && !state.canSurvive(level, pos)) { + return Blocks.AIR.defaultBlockState(); + } else { +- if (state.getValue(WATERLOGGED)) { +- level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); ++ if ((Boolean) state.getValue(BigDripleafBlock.WATERLOGGED)) { ++ level.scheduleTick(pos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + +- return direction == Direction.UP && neighborState.is(this) +- ? Blocks.BIG_DRIPLEAF_STEM.withPropertiesOf(state) +- : super.updateShape(state, direction, neighborState, level, pos, neighborPos); ++ return direction == Direction.UP && neighborState.is((Block) this) ? Blocks.BIG_DRIPLEAF_STEM.withPropertiesOf(state) : super.updateShape(state, direction, neighborState, level, pos, neighborPos); + } + } + + @Override +- public boolean isValidBonemealTarget(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { +- BlockState blockState1 = levelReader.getBlockState(blockPos.above()); +- return canReplace(blockState1); ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ IBlockData iblockdata1 = iworldreader.getBlockState(blockposition.above()); ++ ++ return canReplace(iblockdata1); + } + + @Override +- public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, BlockState state) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return true; + } + + @Override +- public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) { +- BlockPos blockPos = pos.above(); +- BlockState blockState = level.getBlockState(blockPos); +- if (canPlaceAt(level, blockPos, blockState)) { +- Direction direction = state.getValue(FACING); +- BigDripleafStemBlock.place(level, pos, state.getFluidState(), direction); +- place(level, blockPos, blockState.getFluidState(), direction); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ BlockPos blockposition1 = pos.above(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ if (canPlaceAt(level, blockposition1, iblockdata1)) { ++ Direction enumdirection = (Direction) state.getValue(BigDripleafBlock.FACING); ++ ++ BigDripleafStemBlock.place(level, pos, state.getFluidState(), enumdirection); ++ place(level, blockposition1, iblockdata1.getFluidState(), enumdirection); + } ++ + } + + @Override +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { + if (!level.isClientSide) { +- if (state.getValue(TILT) == Tilt.NONE && canEntityTilt(pos, entity) && !level.hasNeighborSignal(pos)) { +- this.setTiltAndScheduleTick(state, level, pos, Tilt.UNSTABLE, null); ++ if (state.getValue(BigDripleafBlock.TILT) == Tilt.NONE && canEntityTilt(pos, entity) && !level.hasNeighborSignal(pos)) { ++ // CraftBukkit start - tilt dripleaf ++ org.bukkit.event.Cancellable cancellable; ++ if (entity instanceof Player) { ++ cancellable = CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ if (cancellable.isCancelled()) { ++ return; ++ } ++ this.setTiltAndScheduleTick(state, level, pos, Tilt.UNSTABLE, (SoundEvent) null, entity); ++ // CraftBukkit end + } ++ + } + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (level.hasNeighborSignal(pos)) { + resetTilt(state, level, pos); + } else { +- Tilt tilt = state.getValue(TILT); ++ Tilt tilt = (Tilt) state.getValue(BigDripleafBlock.TILT); ++ + if (tilt == Tilt.UNSTABLE) { +- this.setTiltAndScheduleTick(state, level, pos, Tilt.PARTIAL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN); ++ this.setTiltAndScheduleTick(state, level, pos, Tilt.PARTIAL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN, null); // CraftBukkit + } else if (tilt == Tilt.PARTIAL) { +- this.setTiltAndScheduleTick(state, level, pos, Tilt.FULL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN); ++ this.setTiltAndScheduleTick(state, level, pos, Tilt.FULL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN, null); // CraftBukkit + } else if (tilt == Tilt.FULL) { + resetTilt(state, level, pos); + } ++ + } + } + + @Override +- public void neighborChanged(BlockState state, Level level, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston) { ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston) { + if (level.hasNeighborSignal(pos)) { + resetTilt(state, level, pos); + } ++ + } + + private static void playTiltSound(Level level, BlockPos pos, SoundEvent sound) { + float f = Mth.randomBetween(level.random, 0.8F, 1.2F); +- level.playSound(null, pos, sound, SoundSource.BLOCKS, 1.0F, f); ++ ++ level.playSound((Player) null, pos, sound, SoundSource.BLOCKS, 1.0F, f); + } + + private static boolean canEntityTilt(BlockPos pos, Entity entity) { +- return entity.onGround() && entity.position().y > (double)((float)pos.getY() + 0.6875F); ++ return entity.onGround() && entity.position().y > (double) ((float) pos.getY() + 0.6875F); + } + +- private void setTiltAndScheduleTick(BlockState state, Level level, BlockPos pos, Tilt tilt, @Nullable SoundEvent sound) { +- setTilt(state, level, pos, tilt); +- if (sound != null) { +- playTiltSound(level, pos, sound); ++ // CraftBukkit start ++ private void setTiltAndScheduleTick(IBlockData iblockdata, Level world, BlockPos blockposition, Tilt tilt, @Nullable SoundEvent soundeffect, @Nullable Entity entity) { ++ if (!setTilt(iblockdata, world, blockposition, tilt, entity)) return; ++ // CraftBukkit end ++ if (soundeffect != null) { ++ playTiltSound(world, blockposition, soundeffect); + } + +- int _int = DELAY_UNTIL_NEXT_TILT_STATE.getInt(tilt); +- if (_int != -1) { +- level.scheduleTick(pos, this, _int); ++ int i = BigDripleafBlock.DELAY_UNTIL_NEXT_TILT_STATE.getInt(tilt); ++ ++ if (i != -1) { ++ world.scheduleTick(blockposition, (Block) this, i); + } ++ + } + +- private static void resetTilt(BlockState state, Level level, BlockPos pos) { +- setTilt(state, level, pos, Tilt.NONE); +- if (state.getValue(TILT) != Tilt.NONE) { ++ private static void resetTilt(IBlockData state, Level level, BlockPos pos) { ++ setTilt(state, level, pos, Tilt.NONE, null); // CraftBukkit ++ if (state.getValue(BigDripleafBlock.TILT) != Tilt.NONE) { + playTiltSound(level, pos, SoundEvents.BIG_DRIPLEAF_TILT_UP); + } ++ + } + +- private static void setTilt(BlockState state, Level level, BlockPos pos, Tilt tilt) { +- Tilt tilt1 = state.getValue(TILT); +- level.setBlock(pos, state.setValue(TILT, tilt), 2); ++ // CraftBukkit start ++ private static boolean setTilt(IBlockData iblockdata, Level world, BlockPos blockposition, Tilt tilt, @Nullable Entity entity) { ++ if (entity != null) { ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, iblockdata.setValue(BigDripleafBlock.TILT, tilt))) { ++ return false; ++ } ++ } ++ // CraftBukkit end ++ Tilt tilt1 = (Tilt) iblockdata.getValue(BigDripleafBlock.TILT); ++ ++ world.setBlock(blockposition, (IBlockData) iblockdata.setValue(BigDripleafBlock.TILT, tilt), 2); + if (tilt.causesVibration() && tilt != tilt1) { +- level.gameEvent(null, GameEvent.BLOCK_CHANGE, pos); ++ world.gameEvent((Entity) null, GameEvent.BLOCK_CHANGE, blockposition); + } ++ ++ return true; // CraftBukkit + } + + @Override +- public VoxelShape getCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return LEAF_SHAPES.get(state.getValue(TILT)); ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (VoxelShape) BigDripleafBlock.LEAF_SHAPES.get(state.getValue(BigDripleafBlock.TILT)); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return this.shapesCache.get(state); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (VoxelShape) this.shapesCache.get(state); + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- BlockState blockState = context.getLevel().getBlockState(context.getClickedPos().below()); +- FluidState fluidState = context.getLevel().getFluidState(context.getClickedPos()); +- boolean flag = blockState.is(Blocks.BIG_DRIPLEAF) || blockState.is(Blocks.BIG_DRIPLEAF_STEM); +- return this.defaultBlockState() +- .setValue(WATERLOGGED, Boolean.valueOf(fluidState.isSourceOfType(Fluids.WATER))) +- .setValue(FACING, flag ? blockState.getValue(FACING) : context.getHorizontalDirection().getOpposite()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ IBlockData iblockdata = context.getLevel().getBlockState(context.getClickedPos().below()); ++ FluidState fluid = context.getLevel().getFluidState(context.getClickedPos()); ++ boolean flag = iblockdata.is(Blocks.BIG_DRIPLEAF) || iblockdata.is(Blocks.BIG_DRIPLEAF_STEM); ++ ++ return (IBlockData) ((IBlockData) this.defaultBlockState().setValue(BigDripleafBlock.WATERLOGGED, fluid.isSourceOfType(Fluids.WATER))).setValue(BigDripleafBlock.FACING, flag ? (Direction) iblockdata.getValue(BigDripleafBlock.FACING) : context.getHorizontalDirection().getOpposite()); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(WATERLOGGED, FACING, TILT); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(BigDripleafBlock.WATERLOGGED, BigDripleafBlock.FACING, BigDripleafBlock.TILT); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/Block.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/Block.java.patch new file mode 100644 index 0000000000..41bb7ef0b3 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/Block.java.patch @@ -0,0 +1,695 @@ +--- a/net/minecraft/world/level/block/Block.java ++++ b/net/minecraft/world/level/block/Block.java +@@ -7,6 +7,7 @@ + import com.mojang.logging.LogUtils; + import com.mojang.serialization.MapCodec; + import it.unimi.dsi.fastutil.objects.Object2ByteLinkedOpenHashMap; ++import java.util.Iterator; + import java.util.List; + import java.util.function.Function; + import java.util.function.Supplier; +@@ -43,14 +44,14 @@ + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Explosion; + import net.minecraft.world.level.GameRules; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.biome.Biome; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.Property; + import net.minecraft.world.level.gameevent.GameEvent; +@@ -62,20 +63,17 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import org.slf4j.Logger; + +-public class Block extends BlockBehaviour implements ItemLike { ++public class Block extends BlockBehaviour implements IMaterial { ++ + public static final MapCodec CODEC = simpleCodec(Block::new); + private static final Logger LOGGER = LogUtils.getLogger(); +- private final Holder.Reference builtInRegistryHolder = BuiltInRegistries.BLOCK.createIntrusiveHolder(this); +- public static final IdMapper BLOCK_STATE_REGISTRY = new IdMapper<>(); +- private static final LoadingCache SHAPE_FULL_BLOCK_CACHE = CacheBuilder.newBuilder() +- .maximumSize(512L) +- .weakKeys() +- .build(new CacheLoader() { +- @Override +- public Boolean load(VoxelShape shape) { +- return !Shapes.joinIsNotEmpty(Shapes.block(), shape, BooleanOp.NOT_SAME); +- } +- }); ++ private final Holder.Reference builtInRegistryHolder; ++ public static final IdMapper BLOCK_STATE_REGISTRY = new IdMapper<>(); ++ private static final LoadingCache SHAPE_FULL_BLOCK_CACHE = CacheBuilder.newBuilder().maximumSize(512L).weakKeys().build(new CacheLoader() { ++ public Boolean load(VoxelShape voxelshape) { ++ return !Shapes.joinIsNotEmpty(Shapes.block(), voxelshape, BooleanOp.NOT_SAME); ++ } ++ }); + public static final int UPDATE_NEIGHBORS = 1; + public static final int UPDATE_CLIENTS = 2; + public static final int UPDATE_INVISIBLE = 4; +@@ -89,143 +87,156 @@ + public static final float INDESTRUCTIBLE = -1.0F; + public static final float INSTANT = 0.0F; + public static final int UPDATE_LIMIT = 512; +- protected final StateDefinition stateDefinition; +- private BlockState defaultBlockState; ++ protected final StateDefinition stateDefinition; ++ private IBlockData defaultBlockState; + @Nullable + private String descriptionId; + @Nullable + private Item item; + private static final int CACHE_SIZE = 2048; + private static final ThreadLocal> OCCLUSION_CACHE = ThreadLocal.withInitial(() -> { +- Object2ByteLinkedOpenHashMap map = new Object2ByteLinkedOpenHashMap(2048, 0.25F) { +- @Override +- protected void rehash(int newN) { +- } ++ Object2ByteLinkedOpenHashMap object2bytelinkedopenhashmap = new Object2ByteLinkedOpenHashMap(2048, 0.25F) { ++ protected void rehash(int i) {} + }; +- map.defaultReturnValue((byte)127); +- return map; ++ ++ object2bytelinkedopenhashmap.defaultReturnValue((byte) 127); ++ return object2bytelinkedopenhashmap; + }); + + @Override + protected MapCodec codec() { +- return CODEC; ++ return Block.CODEC; + } + +- public static int getId(@Nullable BlockState state) { ++ public static int getId(@Nullable IBlockData state) { + if (state == null) { + return 0; + } else { +- int id = BLOCK_STATE_REGISTRY.getId(state); +- return id == -1 ? 0 : id; ++ int i = Block.BLOCK_STATE_REGISTRY.getId(state); ++ ++ return i == -1 ? 0 : i; + } + } + +- public static BlockState stateById(int id) { +- BlockState blockState = BLOCK_STATE_REGISTRY.byId(id); +- return blockState == null ? Blocks.AIR.defaultBlockState() : blockState; ++ public static IBlockData stateById(int id) { ++ IBlockData iblockdata = (IBlockData) Block.BLOCK_STATE_REGISTRY.byId(id); ++ ++ return iblockdata == null ? Blocks.AIR.defaultBlockState() : iblockdata; + } + + public static Block byItem(@Nullable Item item) { +- return item instanceof BlockItem ? ((BlockItem)item).getBlock() : Blocks.AIR; ++ return item instanceof BlockItem ? ((BlockItem) item).getBlock() : Blocks.AIR; + } + +- public static BlockState pushEntitiesUp(BlockState oldState, BlockState newState, LevelAccessor level, BlockPos pos) { +- VoxelShape voxelShape = Shapes.joinUnoptimized(oldState.getCollisionShape(level, pos), newState.getCollisionShape(level, pos), BooleanOp.ONLY_SECOND) +- .move((double)pos.getX(), (double)pos.getY(), (double)pos.getZ()); +- if (voxelShape.isEmpty()) { ++ public static IBlockData pushEntitiesUp(IBlockData oldState, IBlockData newState, LevelAccessor level, BlockPos pos) { ++ VoxelShape voxelshape = Shapes.joinUnoptimized(oldState.getCollisionShape(level, pos), newState.getCollisionShape(level, pos), BooleanOp.ONLY_SECOND).move((double) pos.getX(), (double) pos.getY(), (double) pos.getZ()); ++ ++ if (voxelshape.isEmpty()) { + return newState; + } else { +- for (Entity entity : level.getEntities(null, voxelShape.bounds())) { +- double d = Shapes.collide(Direction.Axis.Y, entity.getBoundingBox().move(0.0, 1.0, 0.0), List.of(voxelShape), -1.0); +- entity.teleportRelative(0.0, 1.0 + d, 0.0); ++ List list = level.getEntities((Entity) null, voxelshape.bounds()); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ double d0 = Shapes.collide(Direction.Axis.Y, entity.getBoundingBox().move(0.0D, 1.0D, 0.0D), List.of(voxelshape), -1.0D); ++ ++ entity.teleportRelative(0.0D, 1.0D + d0, 0.0D); + } + + return newState; + } + } + +- public static VoxelShape box(double x1, double y1, double z1, double x2, double y2, double z2) { +- return Shapes.box(x1 / 16.0, y1 / 16.0, z1 / 16.0, x2 / 16.0, y2 / 16.0, z2 / 16.0); ++ public static VoxelShape box(double x1, double d1, double y1, double d3, double z1, double d5) { ++ return Shapes.box(x1 / 16.0D, d1 / 16.0D, y1 / 16.0D, d3 / 16.0D, z1 / 16.0D, d5 / 16.0D); + } + +- public static BlockState updateFromNeighbourShapes(BlockState currentState, LevelAccessor level, BlockPos pos) { +- BlockState blockState = currentState; +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ public static IBlockData updateFromNeighbourShapes(IBlockData currentState, LevelAccessor level, BlockPos pos) { ++ IBlockData iblockdata1 = currentState; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ Direction[] aenumdirection = Block.UPDATE_SHAPE_ORDER; ++ int i = aenumdirection.length; + +- for (Direction direction : UPDATE_SHAPE_ORDER) { +- mutableBlockPos.setWithOffset(pos, direction); +- blockState = blockState.updateShape(direction, level.getBlockState(mutableBlockPos), level, pos, mutableBlockPos); ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ ++ blockposition_mutableblockposition.setWithOffset(pos, enumdirection); ++ iblockdata1 = iblockdata1.updateShape(enumdirection, level.getBlockState(blockposition_mutableblockposition), level, pos, blockposition_mutableblockposition); + } + +- return blockState; ++ return iblockdata1; + } + +- public static void updateOrDestroy(BlockState oldState, BlockState newState, LevelAccessor level, BlockPos pos, int flags) { ++ public static void updateOrDestroy(IBlockData oldState, IBlockData newState, LevelAccessor level, BlockPos pos, int flags) { + updateOrDestroy(oldState, newState, level, pos, flags, 512); + } + +- public static void updateOrDestroy(BlockState oldState, BlockState newState, LevelAccessor level, BlockPos pos, int flags, int recursionLeft) { ++ public static void updateOrDestroy(IBlockData oldState, IBlockData newState, LevelAccessor level, BlockPos pos, int flags, int recursionLeft) { + if (newState != oldState) { + if (newState.isAir()) { + if (!level.isClientSide()) { +- level.destroyBlock(pos, (flags & 32) == 0, null, recursionLeft); ++ level.destroyBlock(pos, (flags & 32) == 0, (Entity) null, recursionLeft); + } + } else { + level.setBlock(pos, newState, flags & -33, recursionLeft); + } + } ++ + } + + public Block(BlockBehaviour.Properties properties) { + super(properties); +- StateDefinition.Builder builder = new StateDefinition.Builder<>(this); +- this.createBlockStateDefinition(builder); +- this.stateDefinition = builder.create(Block::defaultBlockState, BlockState::new); +- this.registerDefaultState(this.stateDefinition.any()); ++ this.builtInRegistryHolder = BuiltInRegistries.BLOCK.createIntrusiveHolder(this); ++ StateDefinition.Builder blockstatelist_a = new StateDefinition.Builder<>(this); ++ ++ this.createBlockStateDefinition(blockstatelist_a); ++ this.stateDefinition = blockstatelist_a.create(Block::defaultBlockState, IBlockData::new); ++ this.registerDefaultState((IBlockData) this.stateDefinition.any()); + if (SharedConstants.IS_RUNNING_IN_IDE) { +- String simpleName = this.getClass().getSimpleName(); +- if (!simpleName.endsWith("Block")) { +- LOGGER.error("Block classes should end with Block and {} doesn't.", simpleName); ++ String s = this.getClass().getSimpleName(); ++ ++ if (!s.endsWith("Block")) { ++ Block.LOGGER.error("Block classes should end with Block and {} doesn't.", s); + } + } ++ + } + +- public static boolean isExceptionForConnection(BlockState state) { +- return state.getBlock() instanceof LeavesBlock +- || state.is(Blocks.BARRIER) +- || state.is(Blocks.CARVED_PUMPKIN) +- || state.is(Blocks.JACK_O_LANTERN) +- || state.is(Blocks.MELON) +- || state.is(Blocks.PUMPKIN) +- || state.is(BlockTags.SHULKER_BOXES); ++ public static boolean isExceptionForConnection(IBlockData state) { ++ return state.getBlock() instanceof LeavesBlock || state.is(Blocks.BARRIER) || state.is(Blocks.CARVED_PUMPKIN) || state.is(Blocks.JACK_O_LANTERN) || state.is(Blocks.MELON) || state.is(Blocks.PUMPKIN) || state.is(BlockTags.SHULKER_BOXES); + } + +- public boolean isRandomlyTicking(BlockState state) { ++ public boolean isRandomlyTicking(IBlockData state) { + return this.isRandomlyTicking; + } + +- public static boolean shouldRenderFace(BlockState state, BlockGetter level, BlockPos offset, Direction face, BlockPos pos) { +- BlockState blockState = level.getBlockState(pos); +- if (state.skipRendering(blockState, face)) { ++ public static boolean shouldRenderFace(IBlockData state, BlockGetter level, BlockPos offset, Direction face, BlockPos pos) { ++ IBlockData iblockdata1 = level.getBlockState(pos); ++ ++ if (state.skipRendering(iblockdata1, face)) { + return false; +- } else if (blockState.canOcclude()) { +- Block.BlockStatePairKey blockStatePairKey = new Block.BlockStatePairKey(state, blockState, face); +- Object2ByteLinkedOpenHashMap map = OCCLUSION_CACHE.get(); +- byte andMoveToFirst = map.getAndMoveToFirst(blockStatePairKey); +- if (andMoveToFirst != 127) { +- return andMoveToFirst != 0; ++ } else if (iblockdata1.canOcclude()) { ++ Block.BlockStatePairKey block_a = new Block.BlockStatePairKey(state, iblockdata1, face); ++ Object2ByteLinkedOpenHashMap object2bytelinkedopenhashmap = (Object2ByteLinkedOpenHashMap) Block.OCCLUSION_CACHE.get(); ++ byte b0 = object2bytelinkedopenhashmap.getAndMoveToFirst(block_a); ++ ++ if (b0 != 127) { ++ return b0 != 0; + } else { +- VoxelShape faceOcclusionShape = state.getFaceOcclusionShape(level, offset, face); +- if (faceOcclusionShape.isEmpty()) { ++ VoxelShape voxelshape = state.getFaceOcclusionShape(level, offset, face); ++ ++ if (voxelshape.isEmpty()) { + return true; + } else { +- VoxelShape faceOcclusionShape1 = blockState.getFaceOcclusionShape(level, pos, face.getOpposite()); +- boolean flag = Shapes.joinIsNotEmpty(faceOcclusionShape, faceOcclusionShape1, BooleanOp.ONLY_FIRST); +- if (map.size() == 2048) { +- map.removeLastByte(); ++ VoxelShape voxelshape1 = iblockdata1.getFaceOcclusionShape(level, pos, face.getOpposite()); ++ boolean flag = Shapes.joinIsNotEmpty(voxelshape, voxelshape1, BooleanOp.ONLY_FIRST); ++ ++ if (object2bytelinkedopenhashmap.size() == 2048) { ++ object2bytelinkedopenhashmap.removeLastByte(); + } + +- map.putAndMoveToFirst(blockStatePairKey, (byte)(flag ? 1 : 0)); ++ object2bytelinkedopenhashmap.putAndMoveToFirst(block_a, (byte) (flag ? 1 : 0)); + return flag; + } + } +@@ -239,132 +250,144 @@ + } + + public static boolean canSupportCenter(LevelReader level, BlockPos pos, Direction direction) { +- BlockState blockState = level.getBlockState(pos); +- return (direction != Direction.DOWN || !blockState.is(BlockTags.UNSTABLE_BOTTOM_CENTER)) +- && blockState.isFaceSturdy(level, pos, direction, SupportType.CENTER); ++ IBlockData iblockdata = level.getBlockState(pos); ++ ++ return direction == Direction.DOWN && iblockdata.is(BlockTags.UNSTABLE_BOTTOM_CENTER) ? false : iblockdata.isFaceSturdy(level, pos, direction, SupportType.CENTER); + } + + public static boolean isFaceFull(VoxelShape shape, Direction face) { +- VoxelShape faceShape = shape.getFaceShape(face); +- return isShapeFullBlock(faceShape); ++ VoxelShape voxelshape1 = shape.getFaceShape(face); ++ ++ return isShapeFullBlock(voxelshape1); + } + + public static boolean isShapeFullBlock(VoxelShape shape) { +- return SHAPE_FULL_BLOCK_CACHE.getUnchecked(shape); ++ return (Boolean) Block.SHAPE_FULL_BLOCK_CACHE.getUnchecked(shape); + } + +- public boolean propagatesSkylightDown(BlockState state, BlockGetter level, BlockPos pos) { ++ public boolean propagatesSkylightDown(IBlockData state, BlockGetter level, BlockPos pos) { + return !isShapeFullBlock(state.getShape(level, pos)) && state.getFluidState().isEmpty(); + } + +- public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { +- } ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) {} + +- public void destroy(LevelAccessor level, BlockPos pos, BlockState state) { +- } ++ public void destroy(LevelAccessor level, BlockPos pos, IBlockData state) {} + +- public static List getDrops(BlockState state, ServerLevel level, BlockPos pos, @Nullable BlockEntity blockEntity) { +- LootParams.Builder builder = new LootParams.Builder(level) +- .withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos)) +- .withParameter(LootContextParams.TOOL, ItemStack.EMPTY) +- .withOptionalParameter(LootContextParams.BLOCK_ENTITY, blockEntity); +- return state.getDrops(builder); ++ public static List getDrops(IBlockData state, ServerLevel level, BlockPos pos, @Nullable BlockEntity blockEntity) { ++ LootParams.Builder lootparams_a = (new LootParams.Builder(level)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withOptionalParameter(LootContextParams.BLOCK_ENTITY, blockEntity); ++ ++ return state.getDrops(lootparams_a); + } + +- public static List getDrops( +- BlockState state, ServerLevel level, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool +- ) { +- LootParams.Builder builder = new LootParams.Builder(level) +- .withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos)) +- .withParameter(LootContextParams.TOOL, tool) +- .withOptionalParameter(LootContextParams.THIS_ENTITY, entity) +- .withOptionalParameter(LootContextParams.BLOCK_ENTITY, blockEntity); +- return state.getDrops(builder); ++ public static List getDrops(IBlockData state, ServerLevel level, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool) { ++ LootParams.Builder lootparams_a = (new LootParams.Builder(level)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos)).withParameter(LootContextParams.TOOL, tool).withOptionalParameter(LootContextParams.THIS_ENTITY, entity).withOptionalParameter(LootContextParams.BLOCK_ENTITY, blockEntity); ++ ++ return state.getDrops(lootparams_a); + } + +- public static void dropResources(BlockState state, Level level, BlockPos pos) { ++ public static void dropResources(IBlockData state, Level level, BlockPos pos) { + if (level instanceof ServerLevel) { +- getDrops(state, (ServerLevel)level, pos, null).forEach(itemStack -> popResource(level, pos, itemStack)); +- state.spawnAfterBreak((ServerLevel)level, pos, ItemStack.EMPTY, true); ++ getDrops(state, (ServerLevel) level, pos, (BlockEntity) null).forEach((itemstack) -> { ++ popResource(level, pos, itemstack); ++ }); ++ state.spawnAfterBreak((ServerLevel) level, pos, ItemStack.EMPTY, true); + } ++ + } + +- public static void dropResources(BlockState state, LevelAccessor level, BlockPos pos, @Nullable BlockEntity blockEntity) { ++ public static void dropResources(IBlockData state, LevelAccessor level, BlockPos pos, @Nullable BlockEntity blockEntity) { + if (level instanceof ServerLevel) { +- getDrops(state, (ServerLevel)level, pos, blockEntity).forEach(itemStack -> popResource((ServerLevel)level, pos, itemStack)); +- state.spawnAfterBreak((ServerLevel)level, pos, ItemStack.EMPTY, true); ++ getDrops(state, (ServerLevel) level, pos, blockEntity).forEach((itemstack) -> { ++ popResource((ServerLevel) level, pos, itemstack); ++ }); ++ state.spawnAfterBreak((ServerLevel) level, pos, ItemStack.EMPTY, true); + } ++ + } + +- public static void dropResources(BlockState state, Level level, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool) { ++ public static void dropResources(IBlockData state, Level level, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool) { + if (level instanceof ServerLevel) { +- getDrops(state, (ServerLevel)level, pos, blockEntity, entity, tool).forEach(itemStack -> popResource(level, pos, itemStack)); +- state.spawnAfterBreak((ServerLevel)level, pos, tool, true); ++ getDrops(state, (ServerLevel) level, pos, blockEntity, entity, tool).forEach((itemstack1) -> { ++ popResource(level, pos, itemstack1); ++ }); ++ state.spawnAfterBreak((ServerLevel) level, pos, tool, true); + } ++ + } + + public static void popResource(Level level, BlockPos pos, ItemStack stack) { +- double d = (double)EntityType.ITEM.getHeight() / 2.0; +- double d1 = (double)pos.getX() + 0.5 + Mth.nextDouble(level.random, -0.25, 0.25); +- double d2 = (double)pos.getY() + 0.5 + Mth.nextDouble(level.random, -0.25, 0.25) - d; +- double d3 = (double)pos.getZ() + 0.5 + Mth.nextDouble(level.random, -0.25, 0.25); +- popResource(level, () -> new ItemEntity(level, d1, d2, d3, stack), stack); ++ double d0 = (double) EntityType.ITEM.getHeight() / 2.0D; ++ double d1 = (double) pos.getX() + 0.5D + Mth.nextDouble(level.random, -0.25D, 0.25D); ++ double d2 = (double) pos.getY() + 0.5D + Mth.nextDouble(level.random, -0.25D, 0.25D) - d0; ++ double d3 = (double) pos.getZ() + 0.5D + Mth.nextDouble(level.random, -0.25D, 0.25D); ++ ++ popResource(level, () -> { ++ return new ItemEntity(level, d1, d2, d3, stack); ++ }, stack); + } + + public static void popResourceFromFace(Level level, BlockPos pos, Direction direction, ItemStack stack) { +- int stepX = direction.getStepX(); +- int stepY = direction.getStepY(); +- int stepZ = direction.getStepZ(); +- double d = (double)EntityType.ITEM.getWidth() / 2.0; +- double d1 = (double)EntityType.ITEM.getHeight() / 2.0; +- double d2 = (double)pos.getX() + 0.5 + (stepX == 0 ? Mth.nextDouble(level.random, -0.25, 0.25) : (double)stepX * (0.5 + d)); +- double d3 = (double)pos.getY() + 0.5 + (stepY == 0 ? Mth.nextDouble(level.random, -0.25, 0.25) : (double)stepY * (0.5 + d1)) - d1; +- double d4 = (double)pos.getZ() + 0.5 + (stepZ == 0 ? Mth.nextDouble(level.random, -0.25, 0.25) : (double)stepZ * (0.5 + d)); +- double d5 = stepX == 0 ? Mth.nextDouble(level.random, -0.1, 0.1) : (double)stepX * 0.1; +- double d6 = stepY == 0 ? Mth.nextDouble(level.random, 0.0, 0.1) : (double)stepY * 0.1 + 0.1; +- double d7 = stepZ == 0 ? Mth.nextDouble(level.random, -0.1, 0.1) : (double)stepZ * 0.1; +- popResource(level, () -> new ItemEntity(level, d2, d3, d4, stack, d5, d6, d7), stack); ++ int i = direction.getStepX(); ++ int j = direction.getStepY(); ++ int k = direction.getStepZ(); ++ double d0 = (double) EntityType.ITEM.getWidth() / 2.0D; ++ double d1 = (double) EntityType.ITEM.getHeight() / 2.0D; ++ double d2 = (double) pos.getX() + 0.5D + (i == 0 ? Mth.nextDouble(level.random, -0.25D, 0.25D) : (double) i * (0.5D + d0)); ++ double d3 = (double) pos.getY() + 0.5D + (j == 0 ? Mth.nextDouble(level.random, -0.25D, 0.25D) : (double) j * (0.5D + d1)) - d1; ++ double d4 = (double) pos.getZ() + 0.5D + (k == 0 ? Mth.nextDouble(level.random, -0.25D, 0.25D) : (double) k * (0.5D + d0)); ++ double d5 = i == 0 ? Mth.nextDouble(level.random, -0.1D, 0.1D) : (double) i * 0.1D; ++ double d6 = j == 0 ? Mth.nextDouble(level.random, 0.0D, 0.1D) : (double) j * 0.1D + 0.1D; ++ double d7 = k == 0 ? Mth.nextDouble(level.random, -0.1D, 0.1D) : (double) k * 0.1D; ++ ++ popResource(level, () -> { ++ return new ItemEntity(level, d2, d3, d4, stack, d5, d6, d7); ++ }, stack); + } + + private static void popResource(Level level, Supplier itemEntitySupplier, ItemStack stack) { + if (!level.isClientSide && !stack.isEmpty() && level.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { +- ItemEntity itemEntity = itemEntitySupplier.get(); +- itemEntity.setDefaultPickUpDelay(); +- level.addFreshEntity(itemEntity); ++ ItemEntity entityitem = (ItemEntity) itemEntitySupplier.get(); ++ ++ entityitem.setDefaultPickUpDelay(); ++ // CraftBukkit start ++ if (level.captureDrops != null) { ++ level.captureDrops.add(entityitem); ++ } else { ++ level.addFreshEntity(entityitem); ++ } ++ // CraftBukkit end + } + } + +- protected void popExperience(ServerLevel level, BlockPos pos, int amount) { ++ public void popExperience(ServerLevel level, BlockPos pos, int amount) { + if (level.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { + ExperienceOrb.award(level, Vec3.atCenterOf(pos), amount); + } ++ + } + + public float getExplosionResistance() { + return this.explosionResistance; + } + +- public void wasExploded(Level level, BlockPos pos, Explosion explosion) { +- } ++ public void wasExploded(Level level, BlockPos pos, Explosion explosion) {} + +- public void stepOn(Level level, BlockPos pos, BlockState state, Entity entity) { +- } ++ public void stepOn(Level level, BlockPos pos, IBlockData state, Entity entity) {} + + @Nullable +- public BlockState getStateForPlacement(BlockPlaceContext context) { ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { + return this.defaultBlockState(); + } + +- public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) { ++ public void playerDestroy(Level level, Player player, BlockPos pos, IBlockData state, @Nullable BlockEntity blockEntity, ItemStack tool) { + player.awardStat(Stats.BLOCK_MINED.get(this)); +- player.causeFoodExhaustion(0.005F); ++ player.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED); // CraftBukkit - EntityExhaustionEvent + dropResources(state, level, pos, blockEntity, player, tool); + } + +- public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) { +- } ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, @Nullable LivingEntity placer, ItemStack stack) {} + +- public boolean isPossibleToRespawnInThis(BlockState state) { ++ public boolean isPossibleToRespawnInThis(IBlockData state) { + return !state.isSolid() && !state.liquid(); + } + +@@ -380,15 +403,15 @@ + return this.descriptionId; + } + +- public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, float fallDistance) { ++ public void fallOn(Level level, IBlockData state, BlockPos pos, Entity entity, float fallDistance) { + entity.causeFallDamage(fallDistance, 1.0F, entity.damageSources().fall()); + } + + public void updateEntityAfterFallOn(BlockGetter level, Entity entity) { +- entity.setDeltaMovement(entity.getDeltaMovement().multiply(1.0, 0.0, 1.0)); ++ entity.setDeltaMovement(entity.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D)); + } + +- public ItemStack getCloneItemStack(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { ++ public ItemStack getCloneItemStack(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { + return new ItemStack(this); + } + +@@ -404,59 +427,60 @@ + return this.jumpFactor; + } + +- protected void spawnDestroyParticles(Level level, Player player, BlockPos pos, BlockState state) { ++ protected void spawnDestroyParticles(Level level, Player player, BlockPos pos, IBlockData state) { + level.levelEvent(player, 2001, pos, getId(state)); + } + +- public BlockState playerWillDestroy(Level level, BlockPos blockPos, BlockState blockState, Player player) { +- this.spawnDestroyParticles(level, player, blockPos, blockState); +- if (blockState.is(BlockTags.GUARDED_BY_PIGLINS)) { +- PiglinAi.angerNearbyPiglins(player, false); ++ public IBlockData playerWillDestroy(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ this.spawnDestroyParticles(world, entityhuman, blockposition, iblockdata); ++ if (iblockdata.is(BlockTags.GUARDED_BY_PIGLINS)) { ++ PiglinAi.angerNearbyPiglins(entityhuman, false); + } + +- level.gameEvent(GameEvent.BLOCK_DESTROY, blockPos, GameEvent.Context.of(player, blockState)); +- return blockState; ++ world.gameEvent(GameEvent.BLOCK_DESTROY, blockposition, GameEvent.Context.of(entityhuman, iblockdata)); ++ return iblockdata; + } + +- public void handlePrecipitation(BlockState state, Level level, BlockPos pos, Biome.Precipitation precipitation) { +- } ++ public void handlePrecipitation(IBlockData state, Level level, BlockPos pos, Biome.Precipitation precipitation) {} + + public boolean dropFromExplosion(Explosion explosion) { + return true; + } + +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- } ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) {} + +- public StateDefinition getStateDefinition() { ++ public StateDefinition getStateDefinition() { + return this.stateDefinition; + } + +- protected final void registerDefaultState(BlockState state) { ++ protected final void registerDefaultState(IBlockData state) { + this.defaultBlockState = state; + } + +- public final BlockState defaultBlockState() { ++ public final IBlockData defaultBlockState() { + return this.defaultBlockState; + } + +- public final BlockState withPropertiesOf(BlockState state) { +- BlockState blockState = this.defaultBlockState(); ++ public final IBlockData withPropertiesOf(IBlockData state) { ++ IBlockData iblockdata1 = this.defaultBlockState(); ++ Iterator iterator = state.getBlock().getStateDefinition().getProperties().iterator(); + +- for (Property property : state.getBlock().getStateDefinition().getProperties()) { +- if (blockState.hasProperty(property)) { +- blockState = copyProperty(state, blockState, property); ++ while (iterator.hasNext()) { ++ Property iblockstate = (Property) iterator.next(); ++ ++ if (iblockdata1.hasProperty(iblockstate)) { ++ iblockdata1 = copyProperty(state, iblockdata1, iblockstate); + } + } + +- return blockState; ++ return iblockdata1; + } + +- private static > BlockState copyProperty(BlockState sourceState, BlockState targetState, Property property) { +- return targetState.setValue(property, sourceState.getValue(property)); ++ private static > IBlockData copyProperty(IBlockData sourceState, IBlockData targetState, Property property) { ++ return (IBlockData) targetState.setValue(property, sourceState.getValue(property)); + } + +- public SoundType getSoundType(BlockState state) { ++ public SoundType getSoundType(IBlockData state) { + return this.soundType; + } + +@@ -473,62 +497,76 @@ + return this.dynamicShape; + } + +- @Override + public String toString() { + return "Block{" + BuiltInRegistries.BLOCK.getKey(this) + "}"; + } + +- public void appendHoverText(ItemStack stack, @Nullable BlockGetter level, List tooltip, TooltipFlag flag) { +- } ++ public void appendHoverText(ItemStack stack, @Nullable BlockGetter level, List tooltip, TooltipFlag flag) {} + + @Override + protected Block asBlock() { + return this; + } + +- protected ImmutableMap getShapeForEachState(Function shapeGetter) { +- return this.stateDefinition.getPossibleStates().stream().collect(ImmutableMap.toImmutableMap(Function.identity(), shapeGetter)); ++ protected ImmutableMap getShapeForEachState(Function shapeGetter) { ++ return (ImmutableMap) this.stateDefinition.getPossibleStates().stream().collect(ImmutableMap.toImmutableMap(Function.identity(), shapeGetter)); + } + ++ /** @deprecated */ + @Deprecated + public Holder.Reference builtInRegistryHolder() { + return this.builtInRegistryHolder; + } + +- protected void tryDropExperience(ServerLevel level, BlockPos pos, ItemStack heldItem, IntProvider amount) { +- if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, heldItem) == 0) { +- int i = amount.sample(level.random); ++ // CraftBukkit start ++ protected int tryDropExperience(ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, IntProvider intprovider) { ++ if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, itemstack) == 0) { ++ int i = intprovider.sample(worldserver.random); ++ + if (i > 0) { +- this.popExperience(level, pos, i); ++ // this.popExperience(worldserver, blockposition, i); ++ return i; + } + } ++ ++ return 0; + } + ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { ++ return 0; ++ } ++ // CraftBukkit end ++ + public static final class BlockStatePairKey { +- private final BlockState first; +- private final BlockState second; ++ ++ private final IBlockData first; ++ private final IBlockData second; + private final Direction direction; + +- public BlockStatePairKey(BlockState first, BlockState second, Direction direction) { ++ public BlockStatePairKey(IBlockData first, IBlockData second, Direction direction) { + this.first = first; + this.second = second; + this.direction = direction; + } + +- @Override +- public boolean equals(Object other) { +- return this == other +- || other instanceof Block.BlockStatePairKey blockStatePairKey +- && this.first == blockStatePairKey.first +- && this.second == blockStatePairKey.second +- && this.direction == blockStatePairKey.direction; ++ public boolean equals(Object object) { ++ if (this == object) { ++ return true; ++ } else if (!(object instanceof Block.BlockStatePairKey)) { ++ return false; ++ } else { ++ Block.BlockStatePairKey block_a = (Block.BlockStatePairKey) object; ++ ++ return this.first == block_a.first && this.second == block_a.second && this.direction == block_a.direction; ++ } + } + +- @Override + public int hashCode() { +- int hashCode = this.first.hashCode(); +- hashCode = 31 * hashCode + this.second.hashCode(); +- return 31 * hashCode + this.direction.hashCode(); ++ int i = this.first.hashCode(); ++ ++ i = 31 * i + this.second.hashCode(); ++ i = 31 * i + this.direction.hashCode(); ++ return i; + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/BuddingAmethystBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/BuddingAmethystBlock.java.patch new file mode 100644 index 0000000000..f892e73a4e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/BuddingAmethystBlock.java.patch @@ -0,0 +1,70 @@ +--- a/net/minecraft/world/level/block/BuddingAmethystBlock.java ++++ b/net/minecraft/world/level/block/BuddingAmethystBlock.java +@@ -6,17 +6,18 @@ + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.RandomSource; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.Fluids; + + public class BuddingAmethystBlock extends AmethystBlock { ++ + public static final MapCodec CODEC = simpleCodec(BuddingAmethystBlock::new); + public static final int GROWTH_CHANCE = 5; + private static final Direction[] DIRECTIONS = Direction.values(); + + @Override + public MapCodec codec() { +- return CODEC; ++ return BuddingAmethystBlock.CODEC; + } + + public BuddingAmethystBlock(BlockBehaviour.Properties properties) { +@@ -24,32 +25,33 @@ + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (random.nextInt(5) == 0) { +- Direction direction = DIRECTIONS[random.nextInt(DIRECTIONS.length)]; +- BlockPos blockPos = pos.relative(direction); +- BlockState blockState = level.getBlockState(blockPos); ++ Direction enumdirection = BuddingAmethystBlock.DIRECTIONS[random.nextInt(BuddingAmethystBlock.DIRECTIONS.length)]; ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); + Block block = null; +- if (canClusterGrowAtState(blockState)) { ++ ++ if (canClusterGrowAtState(iblockdata1)) { + block = Blocks.SMALL_AMETHYST_BUD; +- } else if (blockState.is(Blocks.SMALL_AMETHYST_BUD) && blockState.getValue(AmethystClusterBlock.FACING) == direction) { ++ } else if (iblockdata1.is(Blocks.SMALL_AMETHYST_BUD) && iblockdata1.getValue(AmethystClusterBlock.FACING) == enumdirection) { + block = Blocks.MEDIUM_AMETHYST_BUD; +- } else if (blockState.is(Blocks.MEDIUM_AMETHYST_BUD) && blockState.getValue(AmethystClusterBlock.FACING) == direction) { ++ } else if (iblockdata1.is(Blocks.MEDIUM_AMETHYST_BUD) && iblockdata1.getValue(AmethystClusterBlock.FACING) == enumdirection) { + block = Blocks.LARGE_AMETHYST_BUD; +- } else if (blockState.is(Blocks.LARGE_AMETHYST_BUD) && blockState.getValue(AmethystClusterBlock.FACING) == direction) { ++ } else if (iblockdata1.is(Blocks.LARGE_AMETHYST_BUD) && iblockdata1.getValue(AmethystClusterBlock.FACING) == enumdirection) { + block = Blocks.AMETHYST_CLUSTER; + } + + if (block != null) { +- BlockState blockState1 = block.defaultBlockState() +- .setValue(AmethystClusterBlock.FACING, direction) +- .setValue(AmethystClusterBlock.WATERLOGGED, Boolean.valueOf(blockState.getFluidState().getType() == Fluids.WATER)); +- level.setBlockAndUpdate(blockPos, blockState1); ++ IBlockData iblockdata2 = (IBlockData) ((IBlockData) block.defaultBlockState().setValue(AmethystClusterBlock.FACING, enumdirection)).setValue(AmethystClusterBlock.WATERLOGGED, iblockdata1.getFluidState().getType() == Fluids.WATER); ++ ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition1, iblockdata2); // CraftBukkit + } ++ + } + } + +- public static boolean canClusterGrowAtState(BlockState state) { ++ public static boolean canClusterGrowAtState(IBlockData state) { + return state.isAir() || state.is(Blocks.WATER) && state.getFluidState().getAmount() == 8; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/BushBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/BushBlock.java.patch new file mode 100644 index 0000000000..940c4aed25 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/BushBlock.java.patch @@ -0,0 +1,64 @@ +--- a/net/minecraft/world/level/block/BushBlock.java ++++ b/net/minecraft/world/level/block/BushBlock.java +@@ -8,10 +8,11 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.pathfinder.PathMode; + + public abstract class BushBlock extends Block { ++ + protected BushBlock(BlockBehaviour.Properties properties) { + super(properties); + } +@@ -19,30 +20,36 @@ + @Override + protected abstract MapCodec codec(); + +- protected boolean mayPlaceOn(BlockState state, BlockGetter level, BlockPos pos) { ++ protected boolean mayPlaceOn(IBlockData state, BlockGetter level, BlockPos pos) { + return state.is(BlockTags.DIRT) || state.is(Blocks.FARMLAND); + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- return !state.canSurvive(level, currentPos) +- ? Blocks.AIR.defaultBlockState() +- : super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ // CraftBukkit start ++ if (!state.canSurvive(level, currentPos)) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(level, currentPos).isCancelled()) { ++ return Blocks.AIR.defaultBlockState(); ++ } ++ } ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ // CraftBukkit end + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { +- BlockPos blockPos = pos.below(); +- return this.mayPlaceOn(level.getBlockState(blockPos), level, blockPos); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.below(); ++ ++ return this.mayPlaceOn(level.getBlockState(blockposition1), level, blockposition1); + } + + @Override +- public boolean propagatesSkylightDown(BlockState state, BlockGetter reader, BlockPos pos) { ++ public boolean propagatesSkylightDown(IBlockData state, BlockGetter reader, BlockPos pos) { + return state.getFluidState().isEmpty(); + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { +- return type == PathComputationType.AIR && !this.hasCollision || super.isPathfindable(state, level, pos, type); ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { ++ return type == PathMode.AIR && !this.hasCollision ? true : super.isPathfindable(state, level, pos, type); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/ButtonBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/ButtonBlock.java.patch new file mode 100644 index 0000000000..e677005474 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/ButtonBlock.java.patch @@ -0,0 +1,342 @@ +--- a/net/minecraft/world/level/block/ButtonBlock.java ++++ b/net/minecraft/world/level/block/ButtonBlock.java +@@ -3,7 +3,6 @@ + import com.mojang.serialization.Codec; + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import java.util.function.BiConsumer; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +@@ -12,7 +11,7 @@ + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundSource; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; +@@ -23,7 +22,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.AttachFace; + import net.minecraft.world.level.block.state.properties.BlockSetType; +@@ -33,107 +32,135 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.event.block.BlockRedstoneEvent; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end + + public class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group( +- BlockSetType.CODEC.fieldOf("block_set_type").forGetter(buttonBlock -> buttonBlock.type), +- Codec.intRange(1, 1024).fieldOf("ticks_to_stay_pressed").forGetter(buttonBlock -> buttonBlock.ticksToStayPressed), +- propertiesCodec() +- ) +- .apply(instance, ButtonBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(BlockSetType.CODEC.fieldOf("block_set_type").forGetter((blockbuttonabstract) -> { ++ return blockbuttonabstract.type; ++ }), Codec.intRange(1, 1024).fieldOf("ticks_to_stay_pressed").forGetter((blockbuttonabstract) -> { ++ return blockbuttonabstract.ticksToStayPressed; ++ }), propertiesCodec()).apply(instance, ButtonBlock::new); ++ }); + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + private static final int PRESSED_DEPTH = 1; + private static final int UNPRESSED_DEPTH = 2; + protected static final int HALF_AABB_HEIGHT = 2; + protected static final int HALF_AABB_WIDTH = 3; +- protected static final VoxelShape CEILING_AABB_X = Block.box(6.0, 14.0, 5.0, 10.0, 16.0, 11.0); +- protected static final VoxelShape CEILING_AABB_Z = Block.box(5.0, 14.0, 6.0, 11.0, 16.0, 10.0); +- protected static final VoxelShape FLOOR_AABB_X = Block.box(6.0, 0.0, 5.0, 10.0, 2.0, 11.0); +- protected static final VoxelShape FLOOR_AABB_Z = Block.box(5.0, 0.0, 6.0, 11.0, 2.0, 10.0); +- protected static final VoxelShape NORTH_AABB = Block.box(5.0, 6.0, 14.0, 11.0, 10.0, 16.0); +- protected static final VoxelShape SOUTH_AABB = Block.box(5.0, 6.0, 0.0, 11.0, 10.0, 2.0); +- protected static final VoxelShape WEST_AABB = Block.box(14.0, 6.0, 5.0, 16.0, 10.0, 11.0); +- protected static final VoxelShape EAST_AABB = Block.box(0.0, 6.0, 5.0, 2.0, 10.0, 11.0); +- protected static final VoxelShape PRESSED_CEILING_AABB_X = Block.box(6.0, 15.0, 5.0, 10.0, 16.0, 11.0); +- protected static final VoxelShape PRESSED_CEILING_AABB_Z = Block.box(5.0, 15.0, 6.0, 11.0, 16.0, 10.0); +- protected static final VoxelShape PRESSED_FLOOR_AABB_X = Block.box(6.0, 0.0, 5.0, 10.0, 1.0, 11.0); +- protected static final VoxelShape PRESSED_FLOOR_AABB_Z = Block.box(5.0, 0.0, 6.0, 11.0, 1.0, 10.0); +- protected static final VoxelShape PRESSED_NORTH_AABB = Block.box(5.0, 6.0, 15.0, 11.0, 10.0, 16.0); +- protected static final VoxelShape PRESSED_SOUTH_AABB = Block.box(5.0, 6.0, 0.0, 11.0, 10.0, 1.0); +- protected static final VoxelShape PRESSED_WEST_AABB = Block.box(15.0, 6.0, 5.0, 16.0, 10.0, 11.0); +- protected static final VoxelShape PRESSED_EAST_AABB = Block.box(0.0, 6.0, 5.0, 1.0, 10.0, 11.0); ++ protected static final VoxelShape CEILING_AABB_X = Block.box(6.0D, 14.0D, 5.0D, 10.0D, 16.0D, 11.0D); ++ protected static final VoxelShape CEILING_AABB_Z = Block.box(5.0D, 14.0D, 6.0D, 11.0D, 16.0D, 10.0D); ++ protected static final VoxelShape FLOOR_AABB_X = Block.box(6.0D, 0.0D, 5.0D, 10.0D, 2.0D, 11.0D); ++ protected static final VoxelShape FLOOR_AABB_Z = Block.box(5.0D, 0.0D, 6.0D, 11.0D, 2.0D, 10.0D); ++ protected static final VoxelShape NORTH_AABB = Block.box(5.0D, 6.0D, 14.0D, 11.0D, 10.0D, 16.0D); ++ protected static final VoxelShape SOUTH_AABB = Block.box(5.0D, 6.0D, 0.0D, 11.0D, 10.0D, 2.0D); ++ protected static final VoxelShape WEST_AABB = Block.box(14.0D, 6.0D, 5.0D, 16.0D, 10.0D, 11.0D); ++ protected static final VoxelShape EAST_AABB = Block.box(0.0D, 6.0D, 5.0D, 2.0D, 10.0D, 11.0D); ++ protected static final VoxelShape PRESSED_CEILING_AABB_X = Block.box(6.0D, 15.0D, 5.0D, 10.0D, 16.0D, 11.0D); ++ protected static final VoxelShape PRESSED_CEILING_AABB_Z = Block.box(5.0D, 15.0D, 6.0D, 11.0D, 16.0D, 10.0D); ++ protected static final VoxelShape PRESSED_FLOOR_AABB_X = Block.box(6.0D, 0.0D, 5.0D, 10.0D, 1.0D, 11.0D); ++ protected static final VoxelShape PRESSED_FLOOR_AABB_Z = Block.box(5.0D, 0.0D, 6.0D, 11.0D, 1.0D, 10.0D); ++ protected static final VoxelShape PRESSED_NORTH_AABB = Block.box(5.0D, 6.0D, 15.0D, 11.0D, 10.0D, 16.0D); ++ protected static final VoxelShape PRESSED_SOUTH_AABB = Block.box(5.0D, 6.0D, 0.0D, 11.0D, 10.0D, 1.0D); ++ protected static final VoxelShape PRESSED_WEST_AABB = Block.box(15.0D, 6.0D, 5.0D, 16.0D, 10.0D, 11.0D); ++ protected static final VoxelShape PRESSED_EAST_AABB = Block.box(0.0D, 6.0D, 5.0D, 1.0D, 10.0D, 11.0D); + private final BlockSetType type; + private final int ticksToStayPressed; + + @Override + public MapCodec codec() { +- return CODEC; ++ return ButtonBlock.CODEC; + } + +- protected ButtonBlock(BlockSetType blockSetType, int i, BlockBehaviour.Properties properties) { +- super(properties.sound(blockSetType.soundType())); +- this.type = blockSetType; +- this.registerDefaultState( +- this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(POWERED, Boolean.valueOf(false)).setValue(FACE, AttachFace.WALL) +- ); ++ protected ButtonBlock(BlockSetType blocksettype, int i, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info.sound(blocksettype.soundType())); ++ this.type = blocksettype; ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(ButtonBlock.FACING, Direction.NORTH)).setValue(ButtonBlock.POWERED, false)).setValue(ButtonBlock.FACE, AttachFace.WALL)); + this.ticksToStayPressed = i; + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- Direction direction = state.getValue(FACING); +- boolean flag = state.getValue(POWERED); +- switch ((AttachFace)state.getValue(FACE)) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ Direction enumdirection = (Direction) state.getValue(ButtonBlock.FACING); ++ boolean flag = (Boolean) state.getValue(ButtonBlock.POWERED); ++ ++ switch ((AttachFace) state.getValue(ButtonBlock.FACE)) { + case FLOOR: +- if (direction.getAxis() == Direction.Axis.X) { +- return flag ? PRESSED_FLOOR_AABB_X : FLOOR_AABB_X; ++ if (enumdirection.getAxis() == Direction.Axis.X) { ++ return flag ? ButtonBlock.PRESSED_FLOOR_AABB_X : ButtonBlock.FLOOR_AABB_X; + } + +- return flag ? PRESSED_FLOOR_AABB_Z : FLOOR_AABB_Z; ++ return flag ? ButtonBlock.PRESSED_FLOOR_AABB_Z : ButtonBlock.FLOOR_AABB_Z; + case WALL: +- return switch (direction) { +- case EAST -> flag ? PRESSED_EAST_AABB : EAST_AABB; +- case WEST -> flag ? PRESSED_WEST_AABB : WEST_AABB; +- case SOUTH -> flag ? PRESSED_SOUTH_AABB : SOUTH_AABB; +- case NORTH, UP, DOWN -> flag ? PRESSED_NORTH_AABB : NORTH_AABB; +- }; ++ VoxelShape voxelshape; ++ ++ switch (enumdirection) { ++ case EAST: ++ voxelshape = flag ? ButtonBlock.PRESSED_EAST_AABB : ButtonBlock.EAST_AABB; ++ break; ++ case WEST: ++ voxelshape = flag ? ButtonBlock.PRESSED_WEST_AABB : ButtonBlock.WEST_AABB; ++ break; ++ case SOUTH: ++ voxelshape = flag ? ButtonBlock.PRESSED_SOUTH_AABB : ButtonBlock.SOUTH_AABB; ++ break; ++ case NORTH: ++ case UP: ++ case DOWN: ++ voxelshape = flag ? ButtonBlock.PRESSED_NORTH_AABB : ButtonBlock.NORTH_AABB; ++ break; ++ default: ++ throw new IncompatibleClassChangeError(); ++ } ++ ++ return voxelshape; + case CEILING: + default: +- if (direction.getAxis() == Direction.Axis.X) { +- return flag ? PRESSED_CEILING_AABB_X : CEILING_AABB_X; +- } else { +- return flag ? PRESSED_CEILING_AABB_Z : CEILING_AABB_Z; +- } ++ return enumdirection.getAxis() == Direction.Axis.X ? (flag ? ButtonBlock.PRESSED_CEILING_AABB_X : ButtonBlock.CEILING_AABB_X) : (flag ? ButtonBlock.PRESSED_CEILING_AABB_Z : ButtonBlock.CEILING_AABB_Z); + } + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { +- if (state.getValue(POWERED)) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ if ((Boolean) state.getValue(ButtonBlock.POWERED)) { + return InteractionResult.CONSUME; + } else { ++ // CraftBukkit start ++ boolean powered = ((Boolean) state.getValue(POWERED)); ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ int old = (powered) ? 15 : 0; ++ int current = (!powered) ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if ((eventRedstone.getNewCurrent() > 0) != (!powered)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + this.press(state, level, pos); + this.playSound(player, level, pos, true); +- level.gameEvent(player, GameEvent.BLOCK_ACTIVATE, pos); ++ level.gameEvent((Entity) player, GameEvent.BLOCK_ACTIVATE, pos); + return InteractionResult.sidedSuccess(level.isClientSide); + } + } + + @Override +- public void onExplosionHit(BlockState blockState, Level level, BlockPos blockPos, Explosion explosion, BiConsumer biConsumer) { +- if (explosion.getBlockInteraction() == Explosion.BlockInteraction.TRIGGER_BLOCK && !level.isClientSide() && !blockState.getValue(POWERED)) { +- this.press(blockState, level, blockPos); ++ public void onExplosionHit(IBlockData iblockdata, Level world, BlockPos blockposition, Explosion explosion, BiConsumer biconsumer) { ++ if (explosion.getBlockInteraction() == Explosion.Effect.TRIGGER_BLOCK && !world.isClientSide() && !(Boolean) iblockdata.getValue(ButtonBlock.POWERED)) { ++ this.press(iblockdata, world, blockposition); + } + +- super.onExplosionHit(blockState, level, blockPos, explosion, biConsumer); ++ super.onExplosionHit(iblockdata, world, blockposition, explosion, biconsumer); + } + +- public void press(BlockState state, Level level, BlockPos pos) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(true)), 3); ++ public void press(IBlockData state, Level level, BlockPos pos) { ++ level.setBlock(pos, (IBlockData) state.setValue(ButtonBlock.POWERED, true), 3); + this.updateNeighbours(state, level, pos); +- level.scheduleTick(pos, this, this.ticksToStayPressed); ++ level.scheduleTick(pos, (Block) this, this.ticksToStayPressed); + } + + protected void playSound(@Nullable Player player, LevelAccessor level, BlockPos pos, boolean hitByArrow) { +@@ -145,9 +172,9 @@ + } + + @Override +- public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { + if (!isMoving && !state.is(newState.getBlock())) { +- if (state.getValue(POWERED)) { ++ if ((Boolean) state.getValue(ButtonBlock.POWERED)) { + this.updateNeighbours(state, level, pos); + } + +@@ -156,59 +183,84 @@ + } + + @Override +- public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { +- return blockState.getValue(POWERED) ? 15 : 0; ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return (Boolean) blockState.getValue(ButtonBlock.POWERED) ? 15 : 0; + } + + @Override +- public int getDirectSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { +- return blockState.getValue(POWERED) && getConnectedDirection(blockState) == side ? 15 : 0; ++ public int getDirectSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return (Boolean) blockState.getValue(ButtonBlock.POWERED) && getConnectedDirection(blockState) == side ? 15 : 0; + } + + @Override +- public boolean isSignalSource(BlockState state) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- if (state.getValue(POWERED)) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(ButtonBlock.POWERED)) { + this.checkPressed(state, level, pos); + } + } + + @Override +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { +- if (!level.isClientSide && this.type.canButtonBeActivatedByArrows() && !state.getValue(POWERED)) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ if (!level.isClientSide && this.type.canButtonBeActivatedByArrows() && !(Boolean) state.getValue(ButtonBlock.POWERED)) { + this.checkPressed(state, level, pos); + } + } + +- protected void checkPressed(BlockState state, Level level, BlockPos pos) { +- AbstractArrow abstractArrow = this.type.canButtonBeActivatedByArrows() +- ? level.getEntitiesOfClass(AbstractArrow.class, state.getShape(level, pos).bounds().move(pos)).stream().findFirst().orElse(null) +- : null; +- boolean flag = abstractArrow != null; +- boolean flag1 = state.getValue(POWERED); ++ protected void checkPressed(IBlockData state, Level level, BlockPos pos) { ++ AbstractArrow entityarrow = this.type.canButtonBeActivatedByArrows() ? (AbstractArrow) level.getEntitiesOfClass(AbstractArrow.class, state.getShape(level, pos).bounds().move(pos)).stream().findFirst().orElse(null) : null; // CraftBukkit - decompile error ++ boolean flag = entityarrow != null; ++ boolean flag1 = (Boolean) state.getValue(ButtonBlock.POWERED); ++ ++ // CraftBukkit start - Call interact event when arrows turn on wooden buttons ++ if (flag1 != flag && flag) { ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ EntityInteractEvent event = new EntityInteractEvent(entityarrow.getBukkitEntity(), block); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ + if (flag != flag1) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(flag)), 3); ++ // CraftBukkit start ++ boolean powered = flag1; ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ int old = (powered) ? 15 : 0; ++ int current = (!powered) ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if ((flag && eventRedstone.getNewCurrent() <= 0) || (!flag && eventRedstone.getNewCurrent() > 0)) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(ButtonBlock.POWERED, flag), 3); + this.updateNeighbours(state, level, pos); +- this.playSound(null, level, pos, flag); +- level.gameEvent(abstractArrow, flag ? GameEvent.BLOCK_ACTIVATE : GameEvent.BLOCK_DEACTIVATE, pos); ++ this.playSound((Player) null, level, pos, flag); ++ level.gameEvent((Entity) entityarrow, flag ? GameEvent.BLOCK_ACTIVATE : GameEvent.BLOCK_DEACTIVATE, pos); + } + + if (flag) { +- level.scheduleTick(new BlockPos(pos), this, this.ticksToStayPressed); ++ level.scheduleTick(new BlockPos(pos), (Block) this, this.ticksToStayPressed); + } ++ + } + +- private void updateNeighbours(BlockState state, Level level, BlockPos pos) { ++ private void updateNeighbours(IBlockData state, Level level, BlockPos pos) { + level.updateNeighborsAt(pos, this); + level.updateNeighborsAt(pos.relative(getConnectedDirection(state).getOpposite()), this); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(FACING, POWERED, FACE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(ButtonBlock.FACING, ButtonBlock.POWERED, ButtonBlock.FACE); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/CactusBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CactusBlock.java.patch new file mode 100644 index 0000000000..b60b073829 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CactusBlock.java.patch @@ -0,0 +1,173 @@ +--- a/net/minecraft/world/level/block/CactusBlock.java ++++ b/net/minecraft/world/level/block/CactusBlock.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.block; + + import com.mojang.serialization.MapCodec; ++import java.util.Iterator; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.server.level.ServerLevel; +@@ -13,107 +14,124 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class CactusBlock extends Block { ++ + public static final MapCodec CODEC = simpleCodec(CactusBlock::new); + public static final IntegerProperty AGE = BlockStateProperties.AGE_15; + public static final int MAX_AGE = 15; + protected static final int AABB_OFFSET = 1; +- protected static final VoxelShape COLLISION_SHAPE = Block.box(1.0, 0.0, 1.0, 15.0, 15.0, 15.0); +- protected static final VoxelShape OUTLINE_SHAPE = Block.box(1.0, 0.0, 1.0, 15.0, 16.0, 15.0); ++ protected static final VoxelShape COLLISION_SHAPE = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 15.0D, 15.0D); ++ protected static final VoxelShape OUTLINE_SHAPE = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 16.0D, 15.0D); + + @Override + public MapCodec codec() { +- return CODEC; ++ return CactusBlock.CODEC; + } + + protected CactusBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(AGE, Integer.valueOf(0))); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(CactusBlock.AGE, 0)); + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (!state.canSurvive(level, pos)) { + level.destroyBlock(pos, true); + } ++ + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- BlockPos blockPos = pos.above(); +- if (level.isEmptyBlock(blockPos)) { +- int i = 1; ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ BlockPos blockposition1 = pos.above(); + +- while (level.getBlockState(pos.below(i)).is(this)) { +- i++; ++ if (level.isEmptyBlock(blockposition1)) { ++ int i; ++ ++ for (i = 1; level.getBlockState(pos.below(i)).is((Block) this); ++i) { ++ ; + } + + if (i < 3) { +- int i1 = state.getValue(AGE); +- if (i1 == 15) { +- level.setBlockAndUpdate(blockPos, this.defaultBlockState()); +- BlockState blockState = state.setValue(AGE, Integer.valueOf(0)); +- level.setBlock(pos, blockState, 4); +- level.neighborChanged(blockState, blockPos, this, pos, false); ++ int j = (Integer) state.getValue(CactusBlock.AGE); ++ ++ if (j == 15) { ++ CraftEventFactory.handleBlockGrowEvent(level, blockposition1, this.defaultBlockState()); // CraftBukkit ++ IBlockData iblockdata1 = (IBlockData) state.setValue(CactusBlock.AGE, 0); ++ ++ level.setBlock(pos, iblockdata1, 4); ++ level.neighborChanged(iblockdata1, blockposition1, this, pos, false); + } else { +- level.setBlock(pos, state.setValue(AGE, Integer.valueOf(i1 + 1)), 4); ++ level.setBlock(pos, (IBlockData) state.setValue(CactusBlock.AGE, j + 1), 4); + } ++ + } + } + } + + @Override +- public VoxelShape getCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return COLLISION_SHAPE; ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return CactusBlock.COLLISION_SHAPE; + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return OUTLINE_SHAPE; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return CactusBlock.OUTLINE_SHAPE; + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { + if (!state.canSurvive(level, currentPos)) { +- level.scheduleTick(currentPos, this, 1); ++ level.scheduleTick(currentPos, (Block) this, 1); + } + + return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- BlockState blockState = level.getBlockState(pos.relative(direction)); +- if (blockState.isSolid() || level.getFluidState(pos.relative(direction)).is(FluidTags.LAVA)) { +- return false; ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); ++ ++ Direction enumdirection; ++ IBlockData iblockdata1; ++ ++ do { ++ if (!iterator.hasNext()) { ++ IBlockData iblockdata2 = level.getBlockState(pos.below()); ++ ++ return (iblockdata2.is(Blocks.CACTUS) || iblockdata2.is(BlockTags.SAND)) && !level.getBlockState(pos.above()).liquid(); + } +- } + +- BlockState blockState1 = level.getBlockState(pos.below()); +- return (blockState1.is(Blocks.CACTUS) || blockState1.is(BlockTags.SAND)) && !level.getBlockState(pos.above()).liquid(); ++ enumdirection = (Direction) iterator.next(); ++ iblockdata1 = level.getBlockState(pos.relative(enumdirection)); ++ } while (!iblockdata1.isSolid() && !level.getFluidState(pos.relative(enumdirection)).is(FluidTags.LAVA)); ++ ++ return false; + } + + @Override +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ CraftEventFactory.blockDamage = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); // CraftBukkit + entity.hurt(level.damageSources().cactus(), 1.0F); ++ CraftEventFactory.blockDamage = null; // CraftBukkit + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(AGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(CactusBlock.AGE); + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/CakeBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CakeBlock.java.patch new file mode 100644 index 0000000000..80c2aa613b --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CakeBlock.java.patch @@ -0,0 +1,188 @@ +--- a/net/minecraft/world/level/block/CakeBlock.java ++++ b/net/minecraft/world/level/block/CakeBlock.java +@@ -7,8 +7,9 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; + import net.minecraft.tags.ItemTags; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; +@@ -17,62 +18,57 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.level.gameevent.GameEvent; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; + + public class CakeBlock extends Block { ++ + public static final MapCodec CODEC = simpleCodec(CakeBlock::new); + public static final int MAX_BITES = 6; + public static final IntegerProperty BITES = BlockStateProperties.BITES; + public static final int FULL_CAKE_SIGNAL = getOutputSignal(0); + protected static final float AABB_OFFSET = 1.0F; + protected static final float AABB_SIZE_PER_BITE = 2.0F; +- protected static final VoxelShape[] SHAPE_BY_BITE = new VoxelShape[]{ +- Block.box(1.0, 0.0, 1.0, 15.0, 8.0, 15.0), +- Block.box(3.0, 0.0, 1.0, 15.0, 8.0, 15.0), +- Block.box(5.0, 0.0, 1.0, 15.0, 8.0, 15.0), +- Block.box(7.0, 0.0, 1.0, 15.0, 8.0, 15.0), +- Block.box(9.0, 0.0, 1.0, 15.0, 8.0, 15.0), +- Block.box(11.0, 0.0, 1.0, 15.0, 8.0, 15.0), +- Block.box(13.0, 0.0, 1.0, 15.0, 8.0, 15.0) +- }; ++ protected static final VoxelShape[] SHAPE_BY_BITE = new VoxelShape[]{Block.box(1.0D, 0.0D, 1.0D, 15.0D, 8.0D, 15.0D), Block.box(3.0D, 0.0D, 1.0D, 15.0D, 8.0D, 15.0D), Block.box(5.0D, 0.0D, 1.0D, 15.0D, 8.0D, 15.0D), Block.box(7.0D, 0.0D, 1.0D, 15.0D, 8.0D, 15.0D), Block.box(9.0D, 0.0D, 1.0D, 15.0D, 8.0D, 15.0D), Block.box(11.0D, 0.0D, 1.0D, 15.0D, 8.0D, 15.0D), Block.box(13.0D, 0.0D, 1.0D, 15.0D, 8.0D, 15.0D)}; + + @Override + public MapCodec codec() { +- return CODEC; ++ return CakeBlock.CODEC; + } + + protected CakeBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(BITES, Integer.valueOf(0))); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(CakeBlock.BITES, 0)); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPE_BY_BITE[state.getValue(BITES)]; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return CakeBlock.SHAPE_BY_BITE[(Integer) state.getValue(CakeBlock.BITES)]; + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { +- ItemStack itemInHand = player.getItemInHand(hand); +- Item item = itemInHand.getItem(); +- if (itemInHand.is(ItemTags.CANDLES) && state.getValue(BITES) == 0) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ Item item = itemstack.getItem(); ++ ++ if (itemstack.is(ItemTags.CANDLES) && (Integer) state.getValue(CakeBlock.BITES) == 0) { + Block block = Block.byItem(item); ++ + if (block instanceof CandleBlock) { + if (!player.isCreative()) { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + +- level.playSound(null, pos, SoundEvents.CAKE_ADD_CANDLE, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.playSound((Player) null, pos, SoundEvents.CAKE_ADD_CANDLE, SoundSource.BLOCKS, 1.0F, 1.0F); + level.setBlockAndUpdate(pos, CandleCakeBlock.byCandle(block)); +- level.gameEvent(player, GameEvent.BLOCK_CHANGE, pos); ++ level.gameEvent((Entity) player, GameEvent.BLOCK_CHANGE, pos); + player.awardStat(Stats.ITEM_USED.get(item)); + return InteractionResult.SUCCESS; + } +@@ -83,7 +79,7 @@ + return InteractionResult.SUCCESS; + } + +- if (itemInHand.isEmpty()) { ++ if (itemstack.isEmpty()) { + return InteractionResult.CONSUME; + } + } +@@ -91,19 +87,31 @@ + return eat(level, pos, state, player); + } + +- protected static InteractionResult eat(LevelAccessor level, BlockPos pos, BlockState state, Player player) { ++ protected static InteractionResult eat(LevelAccessor level, BlockPos pos, IBlockData state, Player player) { + if (!player.canEat(false)) { + return InteractionResult.PASS; + } else { + player.awardStat(Stats.EAT_CAKE_SLICE); +- player.getFoodData().eat(2, 0.1F); +- int i = state.getValue(BITES); +- level.gameEvent(player, GameEvent.EAT, pos); ++ // CraftBukkit start ++ // entityhuman.getFoodData().eat(2, 0.1F); ++ int oldFoodLevel = player.getFoodData().foodLevel; ++ ++ org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(player, 2 + oldFoodLevel); ++ ++ if (!event.isCancelled()) { ++ player.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, 0.1F); ++ } ++ ++ ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().sendHealthUpdate(); ++ // CraftBukkit end ++ int i = (Integer) state.getValue(CakeBlock.BITES); ++ ++ level.gameEvent((Entity) player, GameEvent.EAT, pos); + if (i < 6) { +- level.setBlock(pos, state.setValue(BITES, Integer.valueOf(i + 1)), 3); ++ level.setBlock(pos, (IBlockData) state.setValue(CakeBlock.BITES, i + 1), 3); + } else { + level.removeBlock(pos, false); +- level.gameEvent(player, GameEvent.BLOCK_DESTROY, pos); ++ level.gameEvent((Entity) player, GameEvent.BLOCK_DESTROY, pos); + } + + return InteractionResult.SUCCESS; +@@ -111,25 +119,23 @@ + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- return facing == Direction.DOWN && !state.canSurvive(level, currentPos) +- ? Blocks.AIR.defaultBlockState() +- : super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ return facing == Direction.DOWN && !state.canSurvive(level, currentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { + return level.getBlockState(pos.below()).isSolid(); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(BITES); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(CakeBlock.BITES); + } + + @Override +- public int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) { +- return getOutputSignal(blockState.getValue(BITES)); ++ public int getAnalogOutputSignal(IBlockData blockState, Level level, BlockPos pos) { ++ return getOutputSignal((Integer) blockState.getValue(CakeBlock.BITES)); + } + + public static int getOutputSignal(int eaten) { +@@ -137,12 +143,12 @@ + } + + @Override +- public boolean hasAnalogOutputSignal(BlockState state) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return true; + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/CampfireBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CampfireBlock.java.patch new file mode 100644 index 0000000000..9f0b06f9c2 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CampfireBlock.java.patch @@ -0,0 +1,438 @@ +--- a/net/minecraft/world/level/block/CampfireBlock.java ++++ b/net/minecraft/world/level/block/CampfireBlock.java +@@ -3,7 +3,6 @@ + import com.mojang.serialization.Codec; + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import java.util.Optional; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +@@ -16,7 +15,7 @@ + import net.minecraft.tags.BlockTags; + import net.minecraft.util.RandomSource; + import net.minecraft.world.Containers; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; +@@ -35,69 +34,67 @@ + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.CampfireBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.block.state.properties.DirectionProperty; + import net.minecraft.world.level.gameevent.GameEvent; ++import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++// CraftBukkit end + + public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group( +- Codec.BOOL.fieldOf("spawn_particles").forGetter(campfireBlock -> campfireBlock.spawnParticles), +- Codec.intRange(0, 1000).fieldOf("fire_damage").forGetter(campfireBlock -> campfireBlock.fireDamage), +- propertiesCodec() +- ) +- .apply(instance, CampfireBlock::new) +- ); +- protected static final VoxelShape SHAPE = Block.box(0.0, 0.0, 0.0, 16.0, 7.0, 16.0); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(Codec.BOOL.fieldOf("spawn_particles").forGetter((blockcampfire) -> { ++ return blockcampfire.spawnParticles; ++ }), Codec.intRange(0, 1000).fieldOf("fire_damage").forGetter((blockcampfire) -> { ++ return blockcampfire.fireDamage; ++ }), propertiesCodec()).apply(instance, CampfireBlock::new); ++ }); ++ protected static final VoxelShape SHAPE = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 7.0D, 16.0D); + public static final BooleanProperty LIT = BlockStateProperties.LIT; + public static final BooleanProperty SIGNAL_FIRE = BlockStateProperties.SIGNAL_FIRE; + public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; + public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; +- private static final VoxelShape VIRTUAL_FENCE_POST = Block.box(6.0, 0.0, 6.0, 10.0, 16.0, 10.0); ++ private static final VoxelShape VIRTUAL_FENCE_POST = Block.box(6.0D, 0.0D, 6.0D, 10.0D, 16.0D, 10.0D); + private static final int SMOKE_DISTANCE = 5; + private final boolean spawnParticles; + private final int fireDamage; + + @Override + public MapCodec codec() { +- return CODEC; ++ return CampfireBlock.CODEC; + } + + public CampfireBlock(boolean spawnParticles, int fireDamage, BlockBehaviour.Properties properties) { + super(properties); + this.spawnParticles = spawnParticles; + this.fireDamage = fireDamage; +- this.registerDefaultState( +- this.stateDefinition +- .any() +- .setValue(LIT, Boolean.valueOf(true)) +- .setValue(SIGNAL_FIRE, Boolean.valueOf(false)) +- .setValue(WATERLOGGED, Boolean.valueOf(false)) +- .setValue(FACING, Direction.NORTH) +- ); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(CampfireBlock.LIT, true)).setValue(CampfireBlock.SIGNAL_FIRE, false)).setValue(CampfireBlock.WATERLOGGED, false)).setValue(CampfireBlock.FACING, Direction.NORTH)); + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { +- if (level.getBlockEntity(pos) instanceof CampfireBlockEntity campfireBlockEntity) { +- ItemStack itemInHand = player.getItemInHand(hand); +- Optional> cookableRecipe = campfireBlockEntity.getCookableRecipe(itemInHand); +- if (cookableRecipe.isPresent()) { +- if (!level.isClientSide +- && campfireBlockEntity.placeFood( +- player, player.getAbilities().instabuild ? itemInHand.copy() : itemInHand, cookableRecipe.get().value().getCookingTime() +- )) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof CampfireBlockEntity) { ++ CampfireBlockEntity tileentitycampfire = (CampfireBlockEntity) tileentity; ++ ItemStack itemstack = player.getItemInHand(hand); ++ Optional> optional = tileentitycampfire.getCookableRecipe(itemstack); ++ ++ if (optional.isPresent()) { ++ if (!level.isClientSide && tileentitycampfire.placeFood(player, player.getAbilities().instabuild ? itemstack.copy() : itemstack, ((CampfireCookingRecipe) ((RecipeHolder) optional.get()).value()).getCookingTime())) { + player.awardStat(Stats.INTERACT_WITH_CAMPFIRE); + return InteractionResult.SUCCESS; + } +@@ -110,20 +107,23 @@ + } + + @Override +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { +- if (state.getValue(LIT) && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity)entity)) { +- entity.hurt(level.damageSources().inFire(), (float)this.fireDamage); ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ if ((Boolean) state.getValue(CampfireBlock.LIT) && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity) entity)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = CraftBlock.at(level, pos); // CraftBukkit ++ entity.hurt(level.damageSources().inFire(), (float) this.fireDamage); ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = null; // CraftBukkit + } + + super.entityInside(state, level, pos, entity); + } + + @Override +- public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { + if (!state.is(newState.getBlock())) { +- BlockEntity blockEntity = level.getBlockEntity(pos); +- if (blockEntity instanceof CampfireBlockEntity) { +- Containers.dropContents(level, pos, ((CampfireBlockEntity)blockEntity).getItems()); ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof CampfireBlockEntity) { ++ Containers.dropContents(level, pos, ((CampfireBlockEntity) tileentity).getItems()); + } + + super.onRemove(state, level, pos, newState, isMoving); +@@ -132,102 +132,83 @@ + + @Nullable + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- LevelAccessor level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- boolean flag = level.getFluidState(clickedPos).getType() == Fluids.WATER; +- return this.defaultBlockState() +- .setValue(WATERLOGGED, Boolean.valueOf(flag)) +- .setValue(SIGNAL_FIRE, Boolean.valueOf(this.isSmokeSource(level.getBlockState(clickedPos.below())))) +- .setValue(LIT, Boolean.valueOf(!flag)) +- .setValue(FACING, context.getHorizontalDirection()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ boolean flag = world.getFluidState(blockposition).getType() == Fluids.WATER; ++ ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(CampfireBlock.WATERLOGGED, flag)).setValue(CampfireBlock.SIGNAL_FIRE, this.isSmokeSource(world.getBlockState(blockposition.below())))).setValue(CampfireBlock.LIT, !flag)).setValue(CampfireBlock.FACING, context.getHorizontalDirection()); + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- if (state.getValue(WATERLOGGED)) { +- level.scheduleTick(currentPos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if ((Boolean) state.getValue(CampfireBlock.WATERLOGGED)) { ++ level.scheduleTick(currentPos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + +- return facing == Direction.DOWN +- ? state.setValue(SIGNAL_FIRE, Boolean.valueOf(this.isSmokeSource(facingState))) +- : super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ return facing == Direction.DOWN ? (IBlockData) state.setValue(CampfireBlock.SIGNAL_FIRE, this.isSmokeSource(facingState)) : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + +- private boolean isSmokeSource(BlockState state) { ++ private boolean isSmokeSource(IBlockData state) { + return state.is(Blocks.HAY_BLOCK); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPE; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return CampfireBlock.SHAPE; + } + + @Override +- public RenderShape getRenderShape(BlockState state) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Override +- public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { +- if (state.getValue(LIT)) { ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(CampfireBlock.LIT)) { + if (random.nextInt(10) == 0) { +- level.playLocalSound( +- (double)pos.getX() + 0.5, +- (double)pos.getY() + 0.5, +- (double)pos.getZ() + 0.5, +- SoundEvents.CAMPFIRE_CRACKLE, +- SoundSource.BLOCKS, +- 0.5F + random.nextFloat(), +- random.nextFloat() * 0.7F + 0.6F, +- false +- ); ++ level.playLocalSound((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.CAMPFIRE_CRACKLE, SoundSource.BLOCKS, 0.5F + random.nextFloat(), random.nextFloat() * 0.7F + 0.6F, false); + } + + if (this.spawnParticles && random.nextInt(5) == 0) { +- for (int i = 0; i < random.nextInt(1) + 1; i++) { +- level.addParticle( +- ParticleTypes.LAVA, +- (double)pos.getX() + 0.5, +- (double)pos.getY() + 0.5, +- (double)pos.getZ() + 0.5, +- (double)(random.nextFloat() / 2.0F), +- 5.0E-5, +- (double)(random.nextFloat() / 2.0F) +- ); ++ for (int i = 0; i < random.nextInt(1) + 1; ++i) { ++ level.addParticle(ParticleTypes.LAVA, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (double) (random.nextFloat() / 2.0F), 5.0E-5D, (double) (random.nextFloat() / 2.0F)); + } + } ++ + } + } + +- public static void dowse(@Nullable Entity entity, LevelAccessor level, BlockPos pos, BlockState state) { ++ public static void dowse(@Nullable Entity entity, LevelAccessor level, BlockPos pos, IBlockData state) { + if (level.isClientSide()) { +- for (int i = 0; i < 20; i++) { +- makeParticles((Level)level, pos, state.getValue(SIGNAL_FIRE), true); ++ for (int i = 0; i < 20; ++i) { ++ makeParticles((Level) level, pos, (Boolean) state.getValue(CampfireBlock.SIGNAL_FIRE), true); + } + } + +- BlockEntity blockEntity = level.getBlockEntity(pos); +- if (blockEntity instanceof CampfireBlockEntity) { +- ((CampfireBlockEntity)blockEntity).dowse(); ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof CampfireBlockEntity) { ++ ((CampfireBlockEntity) tileentity).dowse(); + } + + level.gameEvent(entity, GameEvent.BLOCK_CHANGE, pos); + } + + @Override +- public boolean placeLiquid(LevelAccessor level, BlockPos pos, BlockState state, FluidState fluidState) { +- if (!state.getValue(BlockStateProperties.WATERLOGGED) && fluidState.getType() == Fluids.WATER) { +- boolean flag = state.getValue(LIT); ++ public boolean placeLiquid(LevelAccessor level, BlockPos pos, IBlockData state, FluidState fluidState) { ++ if (!(Boolean) state.getValue(BlockStateProperties.WATERLOGGED) && fluidState.getType() == Fluids.WATER) { ++ boolean flag = (Boolean) state.getValue(CampfireBlock.LIT); ++ + if (flag) { + if (!level.isClientSide()) { +- level.playSound(null, pos, SoundEvents.GENERIC_EXTINGUISH_FIRE, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.playSound((Player) null, pos, SoundEvents.GENERIC_EXTINGUISH_FIRE, SoundSource.BLOCKS, 1.0F, 1.0F); + } + +- dowse(null, level, pos, state); ++ dowse((Entity) null, level, pos, state); + } + +- level.setBlock(pos, state.setValue(WATERLOGGED, Boolean.valueOf(true)).setValue(LIT, Boolean.valueOf(false)), 3); ++ level.setBlock(pos, (IBlockData) ((IBlockData) state.setValue(CampfireBlock.WATERLOGGED, true)).setValue(CampfireBlock.LIT, false), 3); + level.scheduleTick(pos, fluidState.getType(), fluidState.getType().getTickDelay(level)); + return true; + } else { +@@ -236,106 +217,95 @@ + } + + @Override +- public void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) { +- BlockPos blockPos = hit.getBlockPos(); +- if (!level.isClientSide && projectile.isOnFire() && projectile.mayInteract(level, blockPos) && !state.getValue(LIT) && !state.getValue(WATERLOGGED)) { +- level.setBlock(blockPos, state.setValue(BlockStateProperties.LIT, Boolean.valueOf(true)), 11); ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { ++ BlockPos blockposition = hit.getBlockPos(); ++ ++ if (!level.isClientSide && projectile.isOnFire() && projectile.mayInteract(level, blockposition) && !(Boolean) state.getValue(CampfireBlock.LIT) && !(Boolean) state.getValue(CampfireBlock.WATERLOGGED)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, blockposition, projectile).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(blockposition, (IBlockData) state.setValue(BlockStateProperties.LIT, true), 11); + } ++ + } + + public static void makeParticles(Level level, BlockPos pos, boolean isSignalFire, boolean spawnExtraSmoke) { +- RandomSource random = level.getRandom(); +- SimpleParticleType simpleParticleType = isSignalFire ? ParticleTypes.CAMPFIRE_SIGNAL_SMOKE : ParticleTypes.CAMPFIRE_COSY_SMOKE; +- level.addAlwaysVisibleParticle( +- simpleParticleType, +- true, +- (double)pos.getX() + 0.5 + random.nextDouble() / 3.0 * (double)(random.nextBoolean() ? 1 : -1), +- (double)pos.getY() + random.nextDouble() + random.nextDouble(), +- (double)pos.getZ() + 0.5 + random.nextDouble() / 3.0 * (double)(random.nextBoolean() ? 1 : -1), +- 0.0, +- 0.07, +- 0.0 +- ); ++ RandomSource randomsource = level.getRandom(); ++ SimpleParticleType particletype = isSignalFire ? ParticleTypes.CAMPFIRE_SIGNAL_SMOKE : ParticleTypes.CAMPFIRE_COSY_SMOKE; ++ ++ level.addAlwaysVisibleParticle(particletype, true, (double) pos.getX() + 0.5D + randomsource.nextDouble() / 3.0D * (double) (randomsource.nextBoolean() ? 1 : -1), (double) pos.getY() + randomsource.nextDouble() + randomsource.nextDouble(), (double) pos.getZ() + 0.5D + randomsource.nextDouble() / 3.0D * (double) (randomsource.nextBoolean() ? 1 : -1), 0.0D, 0.07D, 0.0D); + if (spawnExtraSmoke) { +- level.addParticle( +- ParticleTypes.SMOKE, +- (double)pos.getX() + 0.5 + random.nextDouble() / 4.0 * (double)(random.nextBoolean() ? 1 : -1), +- (double)pos.getY() + 0.4, +- (double)pos.getZ() + 0.5 + random.nextDouble() / 4.0 * (double)(random.nextBoolean() ? 1 : -1), +- 0.0, +- 0.005, +- 0.0 +- ); ++ level.addParticle(ParticleTypes.SMOKE, (double) pos.getX() + 0.5D + randomsource.nextDouble() / 4.0D * (double) (randomsource.nextBoolean() ? 1 : -1), (double) pos.getY() + 0.4D, (double) pos.getZ() + 0.5D + randomsource.nextDouble() / 4.0D * (double) (randomsource.nextBoolean() ? 1 : -1), 0.0D, 0.005D, 0.0D); + } ++ + } + + public static boolean isSmokeyPos(Level level, BlockPos pos) { +- for (int i = 1; i <= 5; i++) { +- BlockPos blockPos = pos.below(i); +- BlockState blockState = level.getBlockState(blockPos); +- if (isLitCampfire(blockState)) { ++ for (int i = 1; i <= 5; ++i) { ++ BlockPos blockposition1 = pos.below(i); ++ IBlockData iblockdata = level.getBlockState(blockposition1); ++ ++ if (isLitCampfire(iblockdata)) { + return true; + } + +- boolean flag = Shapes.joinIsNotEmpty(VIRTUAL_FENCE_POST, blockState.getCollisionShape(level, pos, CollisionContext.empty()), BooleanOp.AND); ++ boolean flag = Shapes.joinIsNotEmpty(CampfireBlock.VIRTUAL_FENCE_POST, iblockdata.getCollisionShape(level, pos, CollisionContext.empty()), BooleanOp.AND); ++ + if (flag) { +- BlockState blockState1 = level.getBlockState(blockPos.below()); +- return isLitCampfire(blockState1); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1.below()); ++ ++ return isLitCampfire(iblockdata1); + } + } + + return false; + } + +- public static boolean isLitCampfire(BlockState state) { +- return state.hasProperty(LIT) && state.is(BlockTags.CAMPFIRES) && state.getValue(LIT); ++ public static boolean isLitCampfire(IBlockData state) { ++ return state.hasProperty(CampfireBlock.LIT) && state.is(BlockTags.CAMPFIRES) && (Boolean) state.getValue(CampfireBlock.LIT); + } + + @Override +- public FluidState getFluidState(BlockState state) { +- return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(CampfireBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override +- public BlockState rotate(BlockState state, Rotation rot) { +- return state.setValue(FACING, rot.rotate(state.getValue(FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rot) { ++ return (IBlockData) state.setValue(CampfireBlock.FACING, rot.rotate((Direction) state.getValue(CampfireBlock.FACING))); + } + + @Override +- public BlockState mirror(BlockState state, Mirror mirror) { +- return state.rotate(mirror.getRotation(state.getValue(FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(CampfireBlock.FACING))); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(LIT, SIGNAL_FIRE, WATERLOGGED, FACING); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(CampfireBlock.LIT, CampfireBlock.SIGNAL_FIRE, CampfireBlock.WATERLOGGED, CampfireBlock.FACING); + } + + @Override +- public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { + return new CampfireBlockEntity(pos, state); + } + + @Nullable + @Override +- public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { +- if (level.isClientSide) { +- return state.getValue(LIT) ? createTickerHelper(blockEntityType, BlockEntityType.CAMPFIRE, CampfireBlockEntity::particleTick) : null; +- } else { +- return state.getValue(LIT) +- ? createTickerHelper(blockEntityType, BlockEntityType.CAMPFIRE, CampfireBlockEntity::cookTick) +- : createTickerHelper(blockEntityType, BlockEntityType.CAMPFIRE, CampfireBlockEntity::cooldownTick); +- } ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { ++ return level.isClientSide ? ((Boolean) state.getValue(CampfireBlock.LIT) ? createTickerHelper(blockEntityType, BlockEntityType.CAMPFIRE, CampfireBlockEntity::particleTick) : null) : ((Boolean) state.getValue(CampfireBlock.LIT) ? createTickerHelper(blockEntityType, BlockEntityType.CAMPFIRE, CampfireBlockEntity::cookTick) : createTickerHelper(blockEntityType, BlockEntityType.CAMPFIRE, CampfireBlockEntity::cooldownTick)); + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + +- public static boolean canLight(BlockState state) { +- return state.is(BlockTags.CAMPFIRES, blockStateBase -> blockStateBase.hasProperty(WATERLOGGED) && blockStateBase.hasProperty(LIT)) +- && !state.getValue(WATERLOGGED) +- && !state.getValue(LIT); ++ public static boolean canLight(IBlockData state) { ++ return state.is(BlockTags.CAMPFIRES, (blockbase_blockdata) -> { ++ return blockbase_blockdata.hasProperty(CampfireBlock.WATERLOGGED) && blockbase_blockdata.hasProperty(CampfireBlock.LIT); ++ }) && !(Boolean) state.getValue(CampfireBlock.WATERLOGGED) && !(Boolean) state.getValue(CampfireBlock.LIT); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/CarvedPumpkinBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CarvedPumpkinBlock.java.patch new file mode 100644 index 0000000000..e1681937f0 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CarvedPumpkinBlock.java.patch @@ -0,0 +1,222 @@ +--- a/net/minecraft/world/level/block/CarvedPumpkinBlock.java ++++ b/net/minecraft/world/level/block/CarvedPumpkinBlock.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.block; + + import com.mojang.serialization.MapCodec; ++import java.util.Iterator; + import java.util.function.Predicate; + import javax.annotation.Nullable; + import net.minecraft.advancements.CriteriaTriggers; +@@ -15,15 +16,19 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.pattern.BlockInWorld; + import net.minecraft.world.level.block.state.pattern.BlockPattern; + import net.minecraft.world.level.block.state.pattern.BlockPatternBuilder; + import net.minecraft.world.level.block.state.predicate.BlockStatePredicate; + import net.minecraft.world.level.block.state.properties.DirectionProperty; ++// CraftBukkit start ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; ++// CraftBukkit end + + public class CarvedPumpkinBlock extends HorizontalDirectionalBlock { ++ + public static final MapCodec CODEC = simpleCodec(CarvedPumpkinBlock::new); + public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING; + @Nullable +@@ -34,21 +39,22 @@ + private BlockPattern ironGolemBase; + @Nullable + private BlockPattern ironGolemFull; +- private static final Predicate PUMPKINS_PREDICATE = state -> state != null +- && (state.is(Blocks.CARVED_PUMPKIN) || state.is(Blocks.JACK_O_LANTERN)); ++ private static final Predicate PUMPKINS_PREDICATE = (iblockdata) -> { ++ return iblockdata != null && (iblockdata.is(Blocks.CARVED_PUMPKIN) || iblockdata.is(Blocks.JACK_O_LANTERN)); ++ }; + + @Override + public MapCodec codec() { +- return CODEC; ++ return CarvedPumpkinBlock.CODEC; + } + + protected CarvedPumpkinBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH)); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(CarvedPumpkinBlock.FACING, Direction.NORTH)); + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { + if (!oldState.is(state.getBlock())) { + this.trySpawnGolem(level, pos); + } +@@ -59,71 +65,85 @@ + } + + private void trySpawnGolem(Level level, BlockPos pos) { +- BlockPattern.BlockPatternMatch blockPatternMatch = this.getOrCreateSnowGolemFull().find(level, pos); +- if (blockPatternMatch != null) { +- SnowGolem snowGolem = EntityType.SNOW_GOLEM.create(level); +- if (snowGolem != null) { +- spawnGolemInWorld(level, blockPatternMatch, snowGolem, blockPatternMatch.getBlock(0, 2, 0).getPos()); ++ BlockPattern.BlockPatternMatch shapedetector_shapedetectorcollection = this.getOrCreateSnowGolemFull().find(level, pos); ++ ++ if (shapedetector_shapedetectorcollection != null) { ++ SnowGolem entitysnowman = (SnowGolem) EntityType.SNOW_GOLEM.create(level); ++ ++ if (entitysnowman != null) { ++ spawnGolemInWorld(level, shapedetector_shapedetectorcollection, entitysnowman, shapedetector_shapedetectorcollection.getBlock(0, 2, 0).getPos()); + } + } else { +- BlockPattern.BlockPatternMatch blockPatternMatch1 = this.getOrCreateIronGolemFull().find(level, pos); +- if (blockPatternMatch1 != null) { +- IronGolem ironGolem = EntityType.IRON_GOLEM.create(level); +- if (ironGolem != null) { +- ironGolem.setPlayerCreated(true); +- spawnGolemInWorld(level, blockPatternMatch1, ironGolem, blockPatternMatch1.getBlock(1, 2, 0).getPos()); ++ BlockPattern.BlockPatternMatch shapedetector_shapedetectorcollection1 = this.getOrCreateIronGolemFull().find(level, pos); ++ ++ if (shapedetector_shapedetectorcollection1 != null) { ++ IronGolem entityirongolem = (IronGolem) EntityType.IRON_GOLEM.create(level); ++ ++ if (entityirongolem != null) { ++ entityirongolem.setPlayerCreated(true); ++ spawnGolemInWorld(level, shapedetector_shapedetectorcollection1, entityirongolem, shapedetector_shapedetectorcollection1.getBlock(1, 2, 0).getPos()); + } + } + } ++ + } + + private static void spawnGolemInWorld(Level level, BlockPattern.BlockPatternMatch patternMatch, Entity golem, BlockPos pos) { +- clearPatternBlocks(level, patternMatch); +- golem.moveTo((double)pos.getX() + 0.5, (double)pos.getY() + 0.05, (double)pos.getZ() + 0.5, 0.0F, 0.0F); +- level.addFreshEntity(golem); ++ // clearPatternBlocks(world, shapedetector_shapedetectorcollection); // CraftBukkit - moved down ++ golem.moveTo((double) pos.getX() + 0.5D, (double) pos.getY() + 0.05D, (double) pos.getZ() + 0.5D, 0.0F, 0.0F); ++ // CraftBukkit start ++ if (!level.addFreshEntity(golem, SpawnReason.BUILD_IRONGOLEM)) { ++ return; ++ } ++ clearPatternBlocks(level, patternMatch); // CraftBukkit - from above ++ // CraftBukkit end ++ Iterator iterator = level.getEntitiesOfClass(ServerPlayer.class, golem.getBoundingBox().inflate(5.0D)).iterator(); + +- for (ServerPlayer serverPlayer : level.getEntitiesOfClass(ServerPlayer.class, golem.getBoundingBox().inflate(5.0))) { +- CriteriaTriggers.SUMMONED_ENTITY.trigger(serverPlayer, golem); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ CriteriaTriggers.SUMMONED_ENTITY.trigger(entityplayer, golem); + } + + updatePatternBlocks(level, patternMatch); + } + + public static void clearPatternBlocks(Level level, BlockPattern.BlockPatternMatch patternMatch) { +- for (int i = 0; i < patternMatch.getWidth(); i++) { +- for (int i1 = 0; i1 < patternMatch.getHeight(); i1++) { +- BlockInWorld block = patternMatch.getBlock(i, i1, 0); +- level.setBlock(block.getPos(), Blocks.AIR.defaultBlockState(), 2); +- level.levelEvent(2001, block.getPos(), Block.getId(block.getState())); ++ for (int i = 0; i < patternMatch.getWidth(); ++i) { ++ for (int j = 0; j < patternMatch.getHeight(); ++j) { ++ BlockInWorld shapedetectorblock = patternMatch.getBlock(i, j, 0); ++ ++ level.setBlock(shapedetectorblock.getPos(), Blocks.AIR.defaultBlockState(), 2); ++ level.levelEvent(2001, shapedetectorblock.getPos(), Block.getId(shapedetectorblock.getState())); + } + } ++ + } + + public static void updatePatternBlocks(Level level, BlockPattern.BlockPatternMatch patternMatch) { +- for (int i = 0; i < patternMatch.getWidth(); i++) { +- for (int i1 = 0; i1 < patternMatch.getHeight(); i1++) { +- BlockInWorld block = patternMatch.getBlock(i, i1, 0); +- level.blockUpdated(block.getPos(), Blocks.AIR); ++ for (int i = 0; i < patternMatch.getWidth(); ++i) { ++ for (int j = 0; j < patternMatch.getHeight(); ++j) { ++ BlockInWorld shapedetectorblock = patternMatch.getBlock(i, j, 0); ++ ++ level.blockUpdated(shapedetectorblock.getPos(), Blocks.AIR); + } + } ++ + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return (IBlockData) this.defaultBlockState().setValue(CarvedPumpkinBlock.FACING, context.getHorizontalDirection().getOpposite()); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(FACING); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(CarvedPumpkinBlock.FACING); + } + + private BlockPattern getOrCreateSnowGolemBase() { + if (this.snowGolemBase == null) { +- this.snowGolemBase = BlockPatternBuilder.start() +- .aisle(" ", "#", "#") +- .where('#', BlockInWorld.hasState(BlockStatePredicate.forBlock(Blocks.SNOW_BLOCK))) +- .build(); ++ this.snowGolemBase = BlockPatternBuilder.start().aisle(" ", "#", "#").where('#', BlockInWorld.hasState(BlockStatePredicate.forBlock(Blocks.SNOW_BLOCK))).build(); + } + + return this.snowGolemBase; +@@ -131,11 +151,7 @@ + + private BlockPattern getOrCreateSnowGolemFull() { + if (this.snowGolemFull == null) { +- this.snowGolemFull = BlockPatternBuilder.start() +- .aisle("^", "#", "#") +- .where('^', BlockInWorld.hasState(PUMPKINS_PREDICATE)) +- .where('#', BlockInWorld.hasState(BlockStatePredicate.forBlock(Blocks.SNOW_BLOCK))) +- .build(); ++ this.snowGolemFull = BlockPatternBuilder.start().aisle("^", "#", "#").where('^', BlockInWorld.hasState(CarvedPumpkinBlock.PUMPKINS_PREDICATE)).where('#', BlockInWorld.hasState(BlockStatePredicate.forBlock(Blocks.SNOW_BLOCK))).build(); + } + + return this.snowGolemFull; +@@ -143,11 +159,9 @@ + + private BlockPattern getOrCreateIronGolemBase() { + if (this.ironGolemBase == null) { +- this.ironGolemBase = BlockPatternBuilder.start() +- .aisle("~ ~", "###", "~#~") +- .where('#', BlockInWorld.hasState(BlockStatePredicate.forBlock(Blocks.IRON_BLOCK))) +- .where('~', block -> block.getState().isAir()) +- .build(); ++ this.ironGolemBase = BlockPatternBuilder.start().aisle("~ ~", "###", "~#~").where('#', BlockInWorld.hasState(BlockStatePredicate.forBlock(Blocks.IRON_BLOCK))).where('~', (shapedetectorblock) -> { ++ return shapedetectorblock.getState().isAir(); ++ }).build(); + } + + return this.ironGolemBase; +@@ -155,12 +169,9 @@ + + private BlockPattern getOrCreateIronGolemFull() { + if (this.ironGolemFull == null) { +- this.ironGolemFull = BlockPatternBuilder.start() +- .aisle("~^~", "###", "~#~") +- .where('^', BlockInWorld.hasState(PUMPKINS_PREDICATE)) +- .where('#', BlockInWorld.hasState(BlockStatePredicate.forBlock(Blocks.IRON_BLOCK))) +- .where('~', block -> block.getState().isAir()) +- .build(); ++ this.ironGolemFull = BlockPatternBuilder.start().aisle("~^~", "###", "~#~").where('^', BlockInWorld.hasState(CarvedPumpkinBlock.PUMPKINS_PREDICATE)).where('#', BlockInWorld.hasState(BlockStatePredicate.forBlock(Blocks.IRON_BLOCK))).where('~', (shapedetectorblock) -> { ++ return shapedetectorblock.getState().isAir(); ++ }).build(); + } + + return this.ironGolemFull; diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/CauldronBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CauldronBlock.java.patch new file mode 100644 index 0000000000..8c71ae8b26 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CauldronBlock.java.patch @@ -0,0 +1,91 @@ +--- a/net/minecraft/world/level/block/CauldronBlock.java ++++ b/net/minecraft/world/level/block/CauldronBlock.java +@@ -3,22 +3,27 @@ + import com.mojang.serialization.MapCodec; + import net.minecraft.core.BlockPos; + import net.minecraft.core.cauldron.CauldronInteraction; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.biome.Biome; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; ++// CraftBukkit start ++import org.bukkit.event.block.CauldronLevelChangeEvent; ++// CraftBukkit end + + public class CauldronBlock extends AbstractCauldronBlock { ++ + public static final MapCodec CODEC = simpleCodec(CauldronBlock::new); + private static final float RAIN_FILL_CHANCE = 0.05F; + private static final float POWDER_SNOW_FILL_CHANCE = 0.1F; + + @Override + public MapCodec codec() { +- return CODEC; ++ return CauldronBlock.CODEC; + } + + public CauldronBlock(BlockBehaviour.Properties properties) { +@@ -26,26 +31,25 @@ + } + + @Override +- public boolean isFull(BlockState state) { ++ public boolean isFull(IBlockData state) { + return false; + } + + protected static boolean shouldHandlePrecipitation(Level level, Biome.Precipitation precipitation) { +- return precipitation == Biome.Precipitation.RAIN +- ? level.getRandom().nextFloat() < 0.05F +- : precipitation == Biome.Precipitation.SNOW && level.getRandom().nextFloat() < 0.1F; ++ return precipitation == Biome.Precipitation.RAIN ? level.getRandom().nextFloat() < 0.05F : (precipitation == Biome.Precipitation.SNOW ? level.getRandom().nextFloat() < 0.1F : false); + } + + @Override +- public void handlePrecipitation(BlockState state, Level level, BlockPos pos, Biome.Precipitation precipitation) { ++ public void handlePrecipitation(IBlockData state, Level level, BlockPos pos, Biome.Precipitation precipitation) { + if (shouldHandlePrecipitation(level, precipitation)) { + if (precipitation == Biome.Precipitation.RAIN) { + level.setBlockAndUpdate(pos, Blocks.WATER_CAULDRON.defaultBlockState()); +- level.gameEvent(null, GameEvent.BLOCK_CHANGE, pos); ++ level.gameEvent((Entity) null, GameEvent.BLOCK_CHANGE, pos); + } else if (precipitation == Biome.Precipitation.SNOW) { + level.setBlockAndUpdate(pos, Blocks.POWDER_SNOW_CAULDRON.defaultBlockState()); +- level.gameEvent(null, GameEvent.BLOCK_CHANGE, pos); ++ level.gameEvent((Entity) null, GameEvent.BLOCK_CHANGE, pos); + } ++ + } + } + +@@ -55,17 +59,18 @@ + } + + @Override +- protected void receiveStalactiteDrip(BlockState state, Level level, BlockPos pos, Fluid fluid) { ++ protected void receiveStalactiteDrip(IBlockData state, Level level, BlockPos pos, Fluid fluid) { ++ IBlockData iblockdata1; ++ + if (fluid == Fluids.WATER) { +- BlockState blockState = Blocks.WATER_CAULDRON.defaultBlockState(); +- level.setBlockAndUpdate(pos, blockState); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(blockState)); ++ iblockdata1 = Blocks.WATER_CAULDRON.defaultBlockState(); ++ LayeredCauldronBlock.changeLevel(state, level, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL); // CraftBukkit + level.levelEvent(1047, pos, 0); + } else if (fluid == Fluids.LAVA) { +- BlockState blockState = Blocks.LAVA_CAULDRON.defaultBlockState(); +- level.setBlockAndUpdate(pos, blockState); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(blockState)); ++ iblockdata1 = Blocks.LAVA_CAULDRON.defaultBlockState(); ++ LayeredCauldronBlock.changeLevel(state, level, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL); // CraftBukkit + level.levelEvent(1046, pos, 0); + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/CaveVines.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CaveVines.java.patch new file mode 100644 index 0000000000..0735fcda12 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CaveVines.java.patch @@ -0,0 +1,84 @@ +--- a/net/minecraft/world/level/block/CaveVines.java ++++ b/net/minecraft/world/level/block/CaveVines.java +@@ -8,38 +8,68 @@ + import net.minecraft.util.Mth; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.VoxelShape; + ++// CraftBukkit start ++import java.util.Collections; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerHarvestBlockEvent; ++// CraftBukkit end ++ + public interface CaveVines { +- VoxelShape SHAPE = Block.box(1.0, 0.0, 1.0, 15.0, 16.0, 15.0); ++ ++ VoxelShape SHAPE = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 16.0D, 15.0D); + BooleanProperty BERRIES = BlockStateProperties.BERRIES; + +- static InteractionResult use(@Nullable Entity entity, BlockState state, Level level, BlockPos pos) { +- if (state.getValue(BERRIES)) { +- Block.popResource(level, pos, new ItemStack(Items.GLOW_BERRIES, 1)); ++ static InteractionResult use(@Nullable Entity entity, IBlockData state, Level level, BlockPos pos) { ++ if ((Boolean) state.getValue(CaveVines.BERRIES)) { ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, (IBlockData) state.setValue(CaveVines.BERRIES, false))) { ++ return InteractionResult.SUCCESS; ++ } ++ ++ if (entity instanceof Player) { ++ PlayerHarvestBlockEvent event = CraftEventFactory.callPlayerHarvestBlockEvent(level, pos, (Player) entity, net.minecraft.world.EnumHand.MAIN_HAND, Collections.singletonList(new ItemStack(Items.GLOW_BERRIES, 1))); ++ if (event.isCancelled()) { ++ return InteractionResult.SUCCESS; // We need to return a success either way, because making it PASS or FAIL will result in a bug where cancelling while harvesting w/ block in hand places block ++ } ++ for (org.bukkit.inventory.ItemStack itemStack : event.getItemsHarvested()) { ++ Block.popResource(level, pos, CraftItemStack.asNMSCopy(itemStack)); ++ } ++ } else { ++ Block.popResource(level, pos, new ItemStack(Items.GLOW_BERRIES, 1)); ++ } ++ // CraftBukkit end ++ + float f = Mth.randomBetween(level.random, 0.8F, 1.2F); +- level.playSound(null, pos, SoundEvents.CAVE_VINES_PICK_BERRIES, SoundSource.BLOCKS, 1.0F, f); +- BlockState blockState = state.setValue(BERRIES, Boolean.valueOf(false)); +- level.setBlock(pos, blockState, 2); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, blockState)); ++ ++ level.playSound((Player) null, pos, SoundEvents.CAVE_VINES_PICK_BERRIES, SoundSource.BLOCKS, 1.0F, f); ++ IBlockData iblockdata1 = (IBlockData) state.setValue(CaveVines.BERRIES, false); ++ ++ level.setBlock(pos, iblockdata1, 2); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, iblockdata1)); + return InteractionResult.sidedSuccess(level.isClientSide); + } else { + return InteractionResult.PASS; + } + } + +- static boolean hasGlowBerries(BlockState state) { +- return state.hasProperty(BERRIES) && state.getValue(BERRIES); ++ static boolean hasGlowBerries(IBlockData state) { ++ return state.hasProperty(CaveVines.BERRIES) && (Boolean) state.getValue(CaveVines.BERRIES); + } + +- static ToIntFunction emission(int berries) { +- return state -> state.getValue(BlockStateProperties.BERRIES) ? berries : 0; ++ static ToIntFunction emission(int berries) { ++ return (iblockdata) -> { ++ return (Boolean) iblockdata.getValue(BlockStateProperties.BERRIES) ? berries : 0; ++ }; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/CeilingHangingSignBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CeilingHangingSignBlock.java.patch new file mode 100644 index 0000000000..f4b329b0bb --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CeilingHangingSignBlock.java.patch @@ -0,0 +1,230 @@ +--- a/net/minecraft/world/level/block/CeilingHangingSignBlock.java ++++ b/net/minecraft/world/level/block/CeilingHangingSignBlock.java +@@ -4,14 +4,13 @@ + import com.google.common.collect.Maps; + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import java.util.Map; + import java.util.Optional; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.tags.BlockTags; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.HangingSignItem; +@@ -27,7 +26,7 @@ + import net.minecraft.world.level.block.entity.HangingSignBlockEntity; + import net.minecraft.world.level.block.entity.SignBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -41,48 +40,35 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + + public class CeilingHangingSignBlock extends SignBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group(WoodType.CODEC.fieldOf("wood_type").forGetter(SignBlock::type), propertiesCodec()) +- .apply(instance, CeilingHangingSignBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(WoodType.CODEC.fieldOf("wood_type").forGetter(SignBlock::type), propertiesCodec()).apply(instance, CeilingHangingSignBlock::new); ++ }); + public static final IntegerProperty ROTATION = BlockStateProperties.ROTATION_16; + public static final BooleanProperty ATTACHED = BlockStateProperties.ATTACHED; + protected static final float AABB_OFFSET = 5.0F; +- protected static final VoxelShape SHAPE = Block.box(3.0, 0.0, 3.0, 13.0, 16.0, 13.0); +- private static final Map AABBS = Maps.newHashMap( +- ImmutableMap.of( +- 0, +- Block.box(1.0, 0.0, 7.0, 15.0, 10.0, 9.0), +- 4, +- Block.box(7.0, 0.0, 1.0, 9.0, 10.0, 15.0), +- 8, +- Block.box(1.0, 0.0, 7.0, 15.0, 10.0, 9.0), +- 12, +- Block.box(7.0, 0.0, 1.0, 9.0, 10.0, 15.0) +- ) +- ); ++ protected static final VoxelShape SHAPE = Block.box(3.0D, 0.0D, 3.0D, 13.0D, 16.0D, 13.0D); ++ private static final Map AABBS = Maps.newHashMap(ImmutableMap.of(0, Block.box(1.0D, 0.0D, 7.0D, 15.0D, 10.0D, 9.0D), 4, Block.box(7.0D, 0.0D, 1.0D, 9.0D, 10.0D, 15.0D), 8, Block.box(1.0D, 0.0D, 7.0D, 15.0D, 10.0D, 9.0D), 12, Block.box(7.0D, 0.0D, 1.0D, 9.0D, 10.0D, 15.0D))); + + @Override + public MapCodec codec() { +- return CODEC; ++ return CeilingHangingSignBlock.CODEC; + } + +- public CeilingHangingSignBlock(WoodType woodType, BlockBehaviour.Properties properties) { +- super(woodType, properties.sound(woodType.hangingSignSoundType())); +- this.registerDefaultState( +- this.stateDefinition +- .any() +- .setValue(ROTATION, Integer.valueOf(0)) +- .setValue(ATTACHED, Boolean.valueOf(false)) +- .setValue(WATERLOGGED, Boolean.valueOf(false)) +- ); ++ public CeilingHangingSignBlock(WoodType blockpropertywood, BlockBehaviour.Properties blockbase_info) { ++ super(blockpropertywood, blockbase_info.sound(blockpropertywood.hangingSignSoundType())); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(CeilingHangingSignBlock.ROTATION, 0)).setValue(CeilingHangingSignBlock.ATTACHED, false)).setValue(CeilingHangingSignBlock.WATERLOGGED, false)); + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { +- if (level.getBlockEntity(pos) instanceof SignBlockEntity signBlockEntity) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (this.shouldTryToChainAnotherHangingSign(player, hit, signBlockEntity, itemInHand)) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof SignBlockEntity) { ++ SignBlockEntity tileentitysign = (SignBlockEntity) tileentity; ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (this.shouldTryToChainAnotherHangingSign(player, hit, tileentitysign, itemstack)) { + return InteractionResult.PASS; + } + } +@@ -91,92 +77,90 @@ + } + + private boolean shouldTryToChainAnotherHangingSign(Player player, BlockHitResult hitResult, SignBlockEntity sign, ItemStack stack) { +- return !sign.canExecuteClickCommands(sign.isFacingFrontText(player), player) +- && stack.getItem() instanceof HangingSignItem +- && hitResult.getDirection().equals(Direction.DOWN); ++ return !sign.canExecuteClickCommands(sign.isFacingFrontText(player), player) && stack.getItem() instanceof HangingSignItem && hitResult.getDirection().equals(Direction.DOWN); + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { + return level.getBlockState(pos.above()).isFaceSturdy(level, pos.above(), Direction.DOWN, SupportType.CENTER); + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- Level level = context.getLevel(); +- FluidState fluidState = level.getFluidState(context.getClickedPos()); +- BlockPos blockPos = context.getClickedPos().above(); +- BlockState blockState = level.getBlockState(blockPos); +- boolean isAllHangingSigns = blockState.is(BlockTags.ALL_HANGING_SIGNS); +- Direction direction = Direction.fromYRot((double)context.getRotation()); +- boolean flag = !Block.isFaceFull(blockState.getCollisionShape(level, blockPos), Direction.DOWN) || context.isSecondaryUseActive(); +- if (isAllHangingSigns && !context.isSecondaryUseActive()) { +- if (blockState.hasProperty(WallHangingSignBlock.FACING)) { +- Direction direction1 = blockState.getValue(WallHangingSignBlock.FACING); +- if (direction1.getAxis().test(direction)) { +- flag = false; ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ Level world = context.getLevel(); ++ FluidState fluid = world.getFluidState(context.getClickedPos()); ++ BlockPos blockposition = context.getClickedPos().above(); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ boolean flag = iblockdata.is(BlockTags.ALL_HANGING_SIGNS); ++ Direction enumdirection = Direction.fromYRot((double) context.getRotation()); ++ boolean flag1 = !Block.isFaceFull(iblockdata.getCollisionShape(world, blockposition), Direction.DOWN) || context.isSecondaryUseActive(); ++ ++ if (flag && !context.isSecondaryUseActive()) { ++ if (iblockdata.hasProperty(WallHangingSignBlock.FACING)) { ++ Direction enumdirection1 = (Direction) iblockdata.getValue(WallHangingSignBlock.FACING); ++ ++ if (enumdirection1.getAxis().test(enumdirection)) { ++ flag1 = false; + } +- } else if (blockState.hasProperty(ROTATION)) { +- Optional optional = RotationSegment.convertToDirection(blockState.getValue(ROTATION)); +- if (optional.isPresent() && optional.get().getAxis().test(direction)) { +- flag = false; ++ } else if (iblockdata.hasProperty(CeilingHangingSignBlock.ROTATION)) { ++ Optional optional = RotationSegment.convertToDirection((Integer) iblockdata.getValue(CeilingHangingSignBlock.ROTATION)); ++ ++ if (optional.isPresent() && ((Direction) optional.get()).getAxis().test(enumdirection)) { ++ flag1 = false; + } + } + } + +- int i = !flag ? RotationSegment.convertToSegment(direction.getOpposite()) : RotationSegment.convertToSegment(context.getRotation() + 180.0F); +- return this.defaultBlockState() +- .setValue(ATTACHED, Boolean.valueOf(flag)) +- .setValue(ROTATION, Integer.valueOf(i)) +- .setValue(WATERLOGGED, Boolean.valueOf(fluidState.getType() == Fluids.WATER)); ++ int i = !flag1 ? RotationSegment.convertToSegment(enumdirection.getOpposite()) : RotationSegment.convertToSegment(context.getRotation() + 180.0F); ++ ++ return (IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(CeilingHangingSignBlock.ATTACHED, flag1)).setValue(CeilingHangingSignBlock.ROTATION, i)).setValue(CeilingHangingSignBlock.WATERLOGGED, fluid.getType() == Fluids.WATER); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- VoxelShape voxelShape = AABBS.get(state.getValue(ROTATION)); +- return voxelShape == null ? SHAPE : voxelShape; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ VoxelShape voxelshape = (VoxelShape) CeilingHangingSignBlock.AABBS.get(state.getValue(CeilingHangingSignBlock.ROTATION)); ++ ++ return voxelshape == null ? CeilingHangingSignBlock.SHAPE : voxelshape; + } + + @Override +- public VoxelShape getBlockSupportShape(BlockState state, BlockGetter level, BlockPos pos) { ++ public VoxelShape getBlockSupportShape(IBlockData state, BlockGetter level, BlockPos pos) { + return this.getShape(state, level, pos, CollisionContext.empty()); + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- return facing == Direction.UP && !this.canSurvive(state, level, currentPos) +- ? Blocks.AIR.defaultBlockState() +- : super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ return facing == Direction.UP && !this.canSurvive(state, level, currentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- public float getYRotationDegrees(BlockState state) { +- return RotationSegment.convertToDegrees(state.getValue(ROTATION)); ++ public float getYRotationDegrees(IBlockData state) { ++ return RotationSegment.convertToDegrees((Integer) state.getValue(CeilingHangingSignBlock.ROTATION)); + } + + @Override +- public BlockState rotate(BlockState state, Rotation rotation) { +- return state.setValue(ROTATION, Integer.valueOf(rotation.rotate(state.getValue(ROTATION), 16))); ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return (IBlockData) state.setValue(CeilingHangingSignBlock.ROTATION, rotation.rotate((Integer) state.getValue(CeilingHangingSignBlock.ROTATION), 16)); + } + + @Override +- public BlockState mirror(BlockState state, Mirror mirror) { +- return state.setValue(ROTATION, Integer.valueOf(mirror.mirror(state.getValue(ROTATION), 16))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return (IBlockData) state.setValue(CeilingHangingSignBlock.ROTATION, mirror.mirror((Integer) state.getValue(CeilingHangingSignBlock.ROTATION), 16)); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(ROTATION, ATTACHED, WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(CeilingHangingSignBlock.ROTATION, CeilingHangingSignBlock.ATTACHED, CeilingHangingSignBlock.WATERLOGGED); + } + + @Override +- public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { + return new HangingSignBlockEntity(pos, state); + } + + @Nullable + @Override +- public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { +- return createTickerHelper(blockEntityType, BlockEntityType.HANGING_SIGN, SignBlockEntity::tick); ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { ++ return null; // Craftbukkit - remove unnecessary sign ticking + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/ChangeOverTimeBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/ChangeOverTimeBlock.java.patch new file mode 100644 index 0000000000..c304f14ee0 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/ChangeOverTimeBlock.java.patch @@ -0,0 +1,101 @@ +--- a/net/minecraft/world/level/block/ChangeOverTimeBlock.java ++++ b/net/minecraft/world/level/block/ChangeOverTimeBlock.java +@@ -1,57 +1,74 @@ + package net.minecraft.world.level.block; + ++import java.util.Iterator; + import java.util.Optional; + import net.minecraft.core.BlockPos; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public interface ChangeOverTimeBlock> { ++ + int SCAN_DISTANCE = 4; + +- Optional getNext(BlockState state); ++ Optional getNext(IBlockData state); + + float getChanceModifier(); + +- default void changeOverTime(BlockState blockState, ServerLevel serverLevel, BlockPos blockPos, RandomSource randomSource) { ++ default void changeOverTime(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, RandomSource randomsource) { + float f = 0.05688889F; +- if (randomSource.nextFloat() < 0.05688889F) { +- this.getNextState(blockState, serverLevel, blockPos, randomSource).ifPresent(blockState1 -> serverLevel.setBlockAndUpdate(blockPos, blockState1)); ++ ++ if (randomsource.nextFloat() < 0.05688889F) { ++ this.getNextState(iblockdata, worldserver, blockposition, randomsource).ifPresent((iblockdata1) -> { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(worldserver, blockposition, iblockdata1); // CraftBukkit ++ }); + } ++ + } + + T getAge(); + +- default Optional getNextState(BlockState blockState, ServerLevel serverLevel, BlockPos blockPos, RandomSource randomSource) { ++ default Optional getNextState(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, RandomSource randomsource) { + int i = this.getAge().ordinal(); +- int i1 = 0; +- int i2 = 0; ++ int j = 0; ++ int k = 0; ++ Iterator iterator = BlockPos.withinManhattan(blockposition, 4, 4, 4).iterator(); + +- for (BlockPos blockPos1 : BlockPos.withinManhattan(blockPos, 4, 4, 4)) { +- int i3 = blockPos1.distManhattan(blockPos); +- if (i3 > 4) { ++ while (iterator.hasNext()) { ++ BlockPos blockposition1 = (BlockPos) iterator.next(); ++ int l = blockposition1.distManhattan(blockposition); ++ ++ if (l > 4) { + break; + } + +- if (!blockPos1.equals(blockPos) && serverLevel.getBlockState(blockPos1).getBlock() instanceof ChangeOverTimeBlock changeOverTimeBlock) { +- Enum age = changeOverTimeBlock.getAge(); +- if (this.getAge().getClass() == age.getClass()) { +- int i4 = age.ordinal(); +- if (i4 < i) { +- return Optional.empty(); +- } ++ if (!blockposition1.equals(blockposition)) { ++ Block block = worldserver.getBlockState(blockposition1).getBlock(); + +- if (i4 > i) { +- i2++; +- } else { +- i1++; ++ if (block instanceof ChangeOverTimeBlock) { ++ ChangeOverTimeBlock changeovertimeblock = (ChangeOverTimeBlock) block; ++ Enum oenum = changeovertimeblock.getAge(); ++ ++ if (this.getAge().getClass() == oenum.getClass()) { ++ int i1 = oenum.ordinal(); ++ ++ if (i1 < i) { ++ return Optional.empty(); ++ } ++ ++ if (i1 > i) { ++ ++k; ++ } else { ++ ++j; ++ } + } + } + } + } + +- float f = (float)(i2 + 1) / (float)(i2 + i1 + 1); ++ float f = (float) (k + 1) / (float) (k + j + 1); + float f1 = f * f * this.getChanceModifier(); +- return randomSource.nextFloat() < f1 ? this.getNext(blockState) : Optional.empty(); ++ ++ return randomsource.nextFloat() < f1 ? this.getNext(iblockdata) : Optional.empty(); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/ChestBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/ChestBlock.java.patch new file mode 100644 index 0000000000..1318e4bb76 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/ChestBlock.java.patch @@ -0,0 +1,555 @@ +--- a/net/minecraft/world/level/block/ChestBlock.java ++++ b/net/minecraft/world/level/block/ChestBlock.java +@@ -2,7 +2,9 @@ + + import com.mojang.serialization.MapCodec; + import it.unimi.dsi.fastutil.floats.Float2FloatFunction; ++import java.util.Iterator; + import java.util.List; ++import java.util.Objects; + import java.util.Optional; + import java.util.function.BiPredicate; + import java.util.function.Supplier; +@@ -18,9 +20,9 @@ + import net.minecraft.world.CompoundContainer; + import net.minecraft.world.Container; + import net.minecraft.world.Containers; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; ++import net.minecraft.world.ITileInventory; + import net.minecraft.world.InteractionResult; +-import net.minecraft.world.MenuProvider; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.animal.Cat; + import net.minecraft.world.entity.monster.piglin.PiglinAi; +@@ -39,45 +41,47 @@ + import net.minecraft.world.level.block.entity.ChestBlockEntity; + import net.minecraft.world.level.block.entity.LidBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.block.state.properties.ChestType; + import net.minecraft.world.level.block.state.properties.DirectionProperty; + import net.minecraft.world.level.block.state.properties.EnumProperty; ++import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; + + public class ChestBlock extends AbstractChestBlock implements SimpleWaterloggedBlock { +- public static final MapCodec CODEC = simpleCodec(properties -> new ChestBlock(properties, () -> BlockEntityType.CHEST)); ++ ++ public static final MapCodec CODEC = simpleCodec((blockbase_info) -> { ++ return new ChestBlock(blockbase_info, () -> { ++ return BlockEntityType.CHEST; ++ }); ++ }); + public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING; + public static final EnumProperty TYPE = BlockStateProperties.CHEST_TYPE; + public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; + public static final int EVENT_SET_OPEN_COUNT = 1; + protected static final int AABB_OFFSET = 1; + protected static final int AABB_HEIGHT = 14; +- protected static final VoxelShape NORTH_AABB = Block.box(1.0, 0.0, 0.0, 15.0, 14.0, 15.0); +- protected static final VoxelShape SOUTH_AABB = Block.box(1.0, 0.0, 1.0, 15.0, 14.0, 16.0); +- protected static final VoxelShape WEST_AABB = Block.box(0.0, 0.0, 1.0, 15.0, 14.0, 15.0); +- protected static final VoxelShape EAST_AABB = Block.box(1.0, 0.0, 1.0, 16.0, 14.0, 15.0); +- protected static final VoxelShape AABB = Block.box(1.0, 0.0, 1.0, 15.0, 14.0, 15.0); +- private static final DoubleBlockCombiner.Combiner> CHEST_COMBINER = new DoubleBlockCombiner.Combiner>( +- +- ) { +- @Override +- public Optional acceptDouble(ChestBlockEntity first, ChestBlockEntity second) { +- return Optional.of(new CompoundContainer(first, second)); ++ protected static final VoxelShape NORTH_AABB = Block.box(1.0D, 0.0D, 0.0D, 15.0D, 14.0D, 15.0D); ++ protected static final VoxelShape SOUTH_AABB = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 14.0D, 16.0D); ++ protected static final VoxelShape WEST_AABB = Block.box(0.0D, 0.0D, 1.0D, 15.0D, 14.0D, 15.0D); ++ protected static final VoxelShape EAST_AABB = Block.box(1.0D, 0.0D, 1.0D, 16.0D, 14.0D, 15.0D); ++ protected static final VoxelShape AABB = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 14.0D, 15.0D); ++ private static final DoubleBlockCombiner.Combiner> CHEST_COMBINER = new DoubleBlockCombiner.Combiner>() { ++ public Optional acceptDouble(ChestBlockEntity tileentitychest, ChestBlockEntity tileentitychest1) { ++ return Optional.of(new CompoundContainer(tileentitychest, tileentitychest1)); + } + +- @Override +- public Optional acceptSingle(ChestBlockEntity single) { +- return Optional.of(single); ++ public Optional acceptSingle(ChestBlockEntity tileentitychest) { ++ return Optional.of(tileentitychest); + } + + @Override +@@ -85,182 +89,187 @@ + return Optional.empty(); + } + }; +- private static final DoubleBlockCombiner.Combiner> MENU_PROVIDER_COMBINER = new DoubleBlockCombiner.Combiner>( +- +- ) { ++ private static final DoubleBlockCombiner.Combiner> MENU_PROVIDER_COMBINER = new DoubleBlockCombiner.Combiner>() { ++ public Optional acceptDouble(final ChestBlockEntity tileentitychest, final ChestBlockEntity tileentitychest1) { ++ final CompoundContainer inventorylargechest = new CompoundContainer(tileentitychest, tileentitychest1); ++ ++ return Optional.of(new DoubleInventory(tileentitychest, tileentitychest1, inventorylargechest)); // CraftBukkit ++ } ++ ++ public Optional acceptSingle(ChestBlockEntity tileentitychest) { ++ return Optional.of(tileentitychest); ++ } ++ + @Override +- public Optional acceptDouble(final ChestBlockEntity first, final ChestBlockEntity second) { +- final Container container = new CompoundContainer(first, second); +- return Optional.of(new MenuProvider() { +- @Nullable +- @Override +- public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { +- if (first.canOpen(player) && second.canOpen(player)) { +- first.unpackLootTable(playerInventory.player); +- second.unpackLootTable(playerInventory.player); +- return ChestMenu.sixRows(containerId, playerInventory, container); +- } else { +- return null; +- } +- } ++ public Optional acceptNone() { ++ return Optional.empty(); ++ } ++ }; + +- @Override +- public Component getDisplayName() { +- if (first.hasCustomName()) { +- return first.getDisplayName(); +- } else { +- return (Component)(second.hasCustomName() ? second.getDisplayName() : Component.translatable("container.chestDouble")); +- } +- } +- }); ++ // CraftBukkit start ++ public static class DoubleInventory implements ITileInventory { ++ ++ private final ChestBlockEntity tileentitychest; ++ private final ChestBlockEntity tileentitychest1; ++ public final CompoundContainer inventorylargechest; ++ ++ public DoubleInventory(ChestBlockEntity tileentitychest, ChestBlockEntity tileentitychest1, CompoundContainer inventorylargechest) { ++ this.tileentitychest = tileentitychest; ++ this.tileentitychest1 = tileentitychest1; ++ this.inventorylargechest = inventorylargechest; + } + ++ @Nullable + @Override +- public Optional acceptSingle(ChestBlockEntity single) { +- return Optional.of(single); ++ public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { ++ if (tileentitychest.canOpen(player) && tileentitychest1.canOpen(player)) { ++ tileentitychest.unpackLootTable(playerInventory.player); ++ tileentitychest1.unpackLootTable(playerInventory.player); ++ return ChestMenu.sixRows(containerId, playerInventory, inventorylargechest); ++ } else { ++ return null; ++ } + } + + @Override +- public Optional acceptNone() { +- return Optional.empty(); ++ public Component getDisplayName() { ++ return (Component) (tileentitychest.hasCustomName() ? tileentitychest.getDisplayName() : (tileentitychest1.hasCustomName() ? tileentitychest1.getDisplayName() : Component.translatable("container.chestDouble"))); + } + }; ++ // CraftBukkit end + + @Override + public MapCodec codec() { +- return CODEC; ++ return ChestBlock.CODEC; + } + + protected ChestBlock(BlockBehaviour.Properties properties, Supplier> blockEntityType) { + super(properties, blockEntityType); +- this.registerDefaultState( +- this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(TYPE, ChestType.SINGLE).setValue(WATERLOGGED, Boolean.valueOf(false)) +- ); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(ChestBlock.FACING, Direction.NORTH)).setValue(ChestBlock.TYPE, ChestType.SINGLE)).setValue(ChestBlock.WATERLOGGED, false)); + } + +- public static DoubleBlockCombiner.BlockType getBlockType(BlockState state) { +- ChestType chestType = state.getValue(TYPE); +- if (chestType == ChestType.SINGLE) { +- return DoubleBlockCombiner.BlockType.SINGLE; +- } else { +- return chestType == ChestType.RIGHT ? DoubleBlockCombiner.BlockType.FIRST : DoubleBlockCombiner.BlockType.SECOND; +- } ++ public static DoubleBlockCombiner.BlockType getBlockType(IBlockData state) { ++ ChestType blockpropertychesttype = (ChestType) state.getValue(ChestBlock.TYPE); ++ ++ return blockpropertychesttype == ChestType.SINGLE ? DoubleBlockCombiner.BlockType.SINGLE : (blockpropertychesttype == ChestType.RIGHT ? DoubleBlockCombiner.BlockType.FIRST : DoubleBlockCombiner.BlockType.SECOND); + } + + @Override +- public RenderShape getRenderShape(BlockState state) { +- return RenderShape.ENTITYBLOCK_ANIMATED; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.ENTITYBLOCK_ANIMATED; + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- if (state.getValue(WATERLOGGED)) { +- level.scheduleTick(currentPos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if ((Boolean) state.getValue(ChestBlock.WATERLOGGED)) { ++ level.scheduleTick(currentPos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + +- if (facingState.is(this) && facing.getAxis().isHorizontal()) { +- ChestType chestType = facingState.getValue(TYPE); +- if (state.getValue(TYPE) == ChestType.SINGLE +- && chestType != ChestType.SINGLE +- && state.getValue(FACING) == facingState.getValue(FACING) +- && getConnectedDirection(facingState) == facing.getOpposite()) { +- return state.setValue(TYPE, chestType.getOpposite()); ++ if (facingState.is((Block) this) && facing.getAxis().isHorizontal()) { ++ ChestType blockpropertychesttype = (ChestType) facingState.getValue(ChestBlock.TYPE); ++ ++ if (state.getValue(ChestBlock.TYPE) == ChestType.SINGLE && blockpropertychesttype != ChestType.SINGLE && state.getValue(ChestBlock.FACING) == facingState.getValue(ChestBlock.FACING) && getConnectedDirection(facingState) == facing.getOpposite()) { ++ return (IBlockData) state.setValue(ChestBlock.TYPE, blockpropertychesttype.getOpposite()); + } + } else if (getConnectedDirection(state) == facing) { +- return state.setValue(TYPE, ChestType.SINGLE); ++ return (IBlockData) state.setValue(ChestBlock.TYPE, ChestType.SINGLE); + } + + return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- if (state.getValue(TYPE) == ChestType.SINGLE) { +- return AABB; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ if (state.getValue(ChestBlock.TYPE) == ChestType.SINGLE) { ++ return ChestBlock.AABB; + } else { + switch (getConnectedDirection(state)) { + case NORTH: + default: +- return NORTH_AABB; ++ return ChestBlock.NORTH_AABB; + case SOUTH: +- return SOUTH_AABB; ++ return ChestBlock.SOUTH_AABB; + case WEST: +- return WEST_AABB; ++ return ChestBlock.WEST_AABB; + case EAST: +- return EAST_AABB; ++ return ChestBlock.EAST_AABB; + } + } + } + +- public static Direction getConnectedDirection(BlockState state) { +- Direction direction = state.getValue(FACING); +- return state.getValue(TYPE) == ChestType.LEFT ? direction.getClockWise() : direction.getCounterClockWise(); ++ public static Direction getConnectedDirection(IBlockData state) { ++ Direction enumdirection = (Direction) state.getValue(ChestBlock.FACING); ++ ++ return state.getValue(ChestBlock.TYPE) == ChestType.LEFT ? enumdirection.getClockWise() : enumdirection.getCounterClockWise(); + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- ChestType chestType = ChestType.SINGLE; +- Direction opposite = context.getHorizontalDirection().getOpposite(); +- FluidState fluidState = context.getLevel().getFluidState(context.getClickedPos()); +- boolean isSecondaryUseActive = context.isSecondaryUseActive(); +- Direction clickedFace = context.getClickedFace(); +- if (clickedFace.getAxis().isHorizontal() && isSecondaryUseActive) { +- Direction direction = this.candidatePartnerFacing(context, clickedFace.getOpposite()); +- if (direction != null && direction.getAxis() != clickedFace.getAxis()) { +- opposite = direction; +- chestType = direction.getCounterClockWise() == clickedFace.getOpposite() ? ChestType.RIGHT : ChestType.LEFT; ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ ChestType blockpropertychesttype = ChestType.SINGLE; ++ Direction enumdirection = context.getHorizontalDirection().getOpposite(); ++ FluidState fluid = context.getLevel().getFluidState(context.getClickedPos()); ++ boolean flag = context.isSecondaryUseActive(); ++ Direction enumdirection1 = context.getClickedFace(); ++ ++ if (enumdirection1.getAxis().isHorizontal() && flag) { ++ Direction enumdirection2 = this.candidatePartnerFacing(context, enumdirection1.getOpposite()); ++ ++ if (enumdirection2 != null && enumdirection2.getAxis() != enumdirection1.getAxis()) { ++ enumdirection = enumdirection2; ++ blockpropertychesttype = enumdirection2.getCounterClockWise() == enumdirection1.getOpposite() ? ChestType.RIGHT : ChestType.LEFT; + } + } + +- if (chestType == ChestType.SINGLE && !isSecondaryUseActive) { +- if (opposite == this.candidatePartnerFacing(context, opposite.getClockWise())) { +- chestType = ChestType.LEFT; +- } else if (opposite == this.candidatePartnerFacing(context, opposite.getCounterClockWise())) { +- chestType = ChestType.RIGHT; ++ if (blockpropertychesttype == ChestType.SINGLE && !flag) { ++ if (enumdirection == this.candidatePartnerFacing(context, enumdirection.getClockWise())) { ++ blockpropertychesttype = ChestType.LEFT; ++ } else if (enumdirection == this.candidatePartnerFacing(context, enumdirection.getCounterClockWise())) { ++ blockpropertychesttype = ChestType.RIGHT; + } + } + +- return this.defaultBlockState() +- .setValue(FACING, opposite) +- .setValue(TYPE, chestType) +- .setValue(WATERLOGGED, Boolean.valueOf(fluidState.getType() == Fluids.WATER)); ++ return (IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(ChestBlock.FACING, enumdirection)).setValue(ChestBlock.TYPE, blockpropertychesttype)).setValue(ChestBlock.WATERLOGGED, fluid.getType() == Fluids.WATER); + } + + @Override +- public FluidState getFluidState(BlockState state) { +- return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(ChestBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Nullable + private Direction candidatePartnerFacing(BlockPlaceContext context, Direction direction) { +- BlockState blockState = context.getLevel().getBlockState(context.getClickedPos().relative(direction)); +- return blockState.is(this) && blockState.getValue(TYPE) == ChestType.SINGLE ? blockState.getValue(FACING) : null; ++ IBlockData iblockdata = context.getLevel().getBlockState(context.getClickedPos().relative(direction)); ++ ++ return iblockdata.is((Block) this) && iblockdata.getValue(ChestBlock.TYPE) == ChestType.SINGLE ? (Direction) iblockdata.getValue(ChestBlock.FACING) : null; + } + + @Override +- public void setPlacedBy(Level level, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, LivingEntity placer, ItemStack stack) { + if (stack.hasCustomHoverName()) { +- BlockEntity blockEntity = level.getBlockEntity(pos); +- if (blockEntity instanceof ChestBlockEntity) { +- ((ChestBlockEntity)blockEntity).setCustomName(stack.getHoverName()); ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof ChestBlockEntity) { ++ ((ChestBlockEntity) tileentity).setCustomName(stack.getHoverName()); + } + } ++ + } + + @Override +- public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { + Containers.dropContentsOnDestroy(state, newState, level, pos); + super.onRemove(state, level, pos, newState, isMoving); + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + if (level.isClientSide) { + return InteractionResult.SUCCESS; + } else { +- MenuProvider menuProvider = this.getMenuProvider(state, level, pos); +- if (menuProvider != null) { +- player.openMenu(menuProvider); ++ ITileInventory itileinventory = this.getMenuProvider(state, level, pos); ++ ++ if (itileinventory != null) { ++ player.openMenu(itileinventory); + player.awardStat(this.getOpenChestStat()); + PiglinAi.angerNearbyPiglins(player, true); + } +@@ -274,61 +283,73 @@ + } + + public BlockEntityType blockEntityType() { +- return this.blockEntityType.get(); ++ return (BlockEntityType) this.blockEntityType.get(); + } + + @Nullable +- public static Container getContainer(ChestBlock chest, BlockState state, Level level, BlockPos pos, boolean override) { +- return chest.combine(state, level, pos, override).apply(CHEST_COMBINER).orElse(null); ++ public static Container getContainer(ChestBlock chest, IBlockData state, Level level, BlockPos pos, boolean override) { ++ return (Container) ((Optional) chest.combine(state, level, pos, override).apply(ChestBlock.CHEST_COMBINER)).orElse((Object) null); + } + + @Override +- public DoubleBlockCombiner.NeighborCombineResult combine(BlockState state, Level level, BlockPos pos, boolean override) { +- BiPredicate biPredicate; ++ public DoubleBlockCombiner.NeighborCombineResult combine(IBlockData state, Level level, BlockPos pos, boolean override) { ++ BiPredicate bipredicate; // CraftBukkit - decompile error ++ + if (override) { +- biPredicate = (levelAccessor, blockPos) -> false; ++ bipredicate = (generatoraccess, blockposition1) -> { ++ return false; ++ }; + } else { +- biPredicate = ChestBlock::isChestBlockedAt; ++ bipredicate = ChestBlock::isChestBlockedAt; + } + +- return DoubleBlockCombiner.combineWithNeigbour( +- this.blockEntityType.get(), ChestBlock::getBlockType, ChestBlock::getConnectedDirection, FACING, state, level, pos, biPredicate +- ); ++ return DoubleBlockCombiner.combineWithNeigbour((BlockEntityType) this.blockEntityType.get(), ChestBlock::getBlockType, ChestBlock::getConnectedDirection, ChestBlock.FACING, state, level, pos, bipredicate); + } + + @Nullable + @Override +- public MenuProvider getMenuProvider(BlockState state, Level level, BlockPos pos) { +- return this.combine(state, level, pos, false).apply(MENU_PROVIDER_COMBINER).orElse(null); ++ public ITileInventory getMenuProvider(IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ return getMenuProvider(state, level, pos, false); + } + ++ @Nullable ++ public ITileInventory getMenuProvider(IBlockData iblockdata, Level world, BlockPos blockposition, boolean ignoreObstructions) { ++ return (ITileInventory) ((Optional) this.combine(iblockdata, world, blockposition, ignoreObstructions).apply(ChestBlock.MENU_PROVIDER_COMBINER)).orElse((Object) null); ++ // CraftBukkit end ++ } ++ + public static DoubleBlockCombiner.Combiner opennessCombiner(final LidBlockEntity lid) { + return new DoubleBlockCombiner.Combiner() { +- @Override + public Float2FloatFunction acceptDouble(ChestBlockEntity first, ChestBlockEntity second) { +- return partialTicks -> Math.max(first.getOpenNess(partialTicks), second.getOpenNess(partialTicks)); ++ return (f) -> { ++ return Math.max(first.getOpenNess(f), second.getOpenNess(f)); ++ }; + } + +- @Override + public Float2FloatFunction acceptSingle(ChestBlockEntity single) { ++ Objects.requireNonNull(single); + return single::getOpenNess; + } + + @Override + public Float2FloatFunction acceptNone() { +- return lid::getOpenNess; ++ LidBlockEntity lidblockentity1 = lid; ++ ++ Objects.requireNonNull(lid); ++ return lidblockentity1::getOpenNess; + } + }; + } + + @Override +- public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { + return new ChestBlockEntity(pos, state); + } + + @Nullable + @Override +- public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { + return level.isClientSide ? createTickerHelper(blockEntityType, this.blockEntityType(), ChestBlockEntity::lidAnimateTick) : null; + } + +@@ -337,20 +358,21 @@ + } + + private static boolean isBlockedChestByBlock(BlockGetter level, BlockPos pos) { +- BlockPos blockPos = pos.above(); +- return level.getBlockState(blockPos).isRedstoneConductor(level, blockPos); ++ BlockPos blockposition1 = pos.above(); ++ ++ return level.getBlockState(blockposition1).isRedstoneConductor(level, blockposition1); + } + + private static boolean isCatSittingOnChest(LevelAccessor level, BlockPos pos) { +- List entitiesOfClass = level.getEntitiesOfClass( +- Cat.class, +- new AABB( +- (double)pos.getX(), (double)(pos.getY() + 1), (double)pos.getZ(), (double)(pos.getX() + 1), (double)(pos.getY() + 2), (double)(pos.getZ() + 1) +- ) +- ); +- if (!entitiesOfClass.isEmpty()) { +- for (Cat cat : entitiesOfClass) { +- if (cat.isInSittingPose()) { ++ List list = level.getEntitiesOfClass(Cat.class, new AABB((double) pos.getX(), (double) (pos.getY() + 1), (double) pos.getZ(), (double) (pos.getX() + 1), (double) (pos.getY() + 2), (double) (pos.getZ() + 1))); ++ ++ if (!list.isEmpty()) { ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Cat entitycat = (Cat) iterator.next(); ++ ++ if (entitycat.isInSittingPose()) { + return true; + } + } +@@ -360,40 +382,42 @@ + } + + @Override +- public boolean hasAnalogOutputSignal(BlockState state) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return true; + } + + @Override +- public int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) { ++ public int getAnalogOutputSignal(IBlockData blockState, Level level, BlockPos pos) { + return AbstractContainerMenu.getRedstoneSignalFromContainer(getContainer(this, blockState, level, pos, false)); + } + + @Override +- public BlockState rotate(BlockState state, Rotation rotation) { +- return state.setValue(FACING, rotation.rotate(state.getValue(FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return (IBlockData) state.setValue(ChestBlock.FACING, rotation.rotate((Direction) state.getValue(ChestBlock.FACING))); + } + + @Override +- public BlockState mirror(BlockState state, Mirror mirror) { +- return state.rotate(mirror.getRotation(state.getValue(FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(ChestBlock.FACING))); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(FACING, TYPE, WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(ChestBlock.FACING, ChestBlock.TYPE, ChestBlock.WATERLOGGED); + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- BlockEntity blockEntity = level.getBlockEntity(pos); +- if (blockEntity instanceof ChestBlockEntity) { +- ((ChestBlockEntity)blockEntity).recheckOpen(); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof ChestBlockEntity) { ++ ((ChestBlockEntity) tileentity).recheckOpen(); + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/ChorusFlowerBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/ChorusFlowerBlock.java.patch new file mode 100644 index 0000000000..8a6b9c745c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/ChorusFlowerBlock.java.patch @@ -0,0 +1,386 @@ +--- a/net/minecraft/world/level/block/ChorusFlowerBlock.java ++++ b/net/minecraft/world/level/block/ChorusFlowerBlock.java +@@ -2,7 +2,7 @@ + + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; ++import java.util.Iterator; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +@@ -15,167 +15,201 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.VoxelShape; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public class ChorusFlowerBlock extends Block { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group( +- BuiltInRegistries.BLOCK.byNameCodec().fieldOf("plant").forGetter(chorusFlowerBlock -> chorusFlowerBlock.plant), propertiesCodec() +- ) +- .apply(instance, ChorusFlowerBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(BuiltInRegistries.BLOCK.byNameCodec().fieldOf("plant").forGetter((blockchorusflower) -> { ++ return blockchorusflower.plant; ++ }), propertiesCodec()).apply(instance, ChorusFlowerBlock::new); ++ }); + public static final int DEAD_AGE = 5; + public static final IntegerProperty AGE = BlockStateProperties.AGE_5; +- protected static final VoxelShape BLOCK_SUPPORT_SHAPE = Block.box(1.0, 0.0, 1.0, 15.0, 15.0, 15.0); ++ protected static final VoxelShape BLOCK_SUPPORT_SHAPE = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 15.0D, 15.0D); + private final Block plant; + + @Override + public MapCodec codec() { +- return CODEC; ++ return ChorusFlowerBlock.CODEC; + } + +- protected ChorusFlowerBlock(Block block, BlockBehaviour.Properties properties) { +- super(properties); ++ protected ChorusFlowerBlock(Block block, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info); + this.plant = block; +- this.registerDefaultState(this.stateDefinition.any().setValue(AGE, Integer.valueOf(0))); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(ChorusFlowerBlock.AGE, 0)); + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (!state.canSurvive(level, pos)) { + level.destroyBlock(pos, true); + } ++ + } + + @Override +- public boolean isRandomlyTicking(BlockState state) { +- return state.getValue(AGE) < 5; ++ public boolean isRandomlyTicking(IBlockData state) { ++ return (Integer) state.getValue(ChorusFlowerBlock.AGE) < 5; + } + + @Override +- public VoxelShape getBlockSupportShape(BlockState state, BlockGetter level, BlockPos pos) { +- return BLOCK_SUPPORT_SHAPE; ++ public VoxelShape getBlockSupportShape(IBlockData state, BlockGetter level, BlockPos pos) { ++ return ChorusFlowerBlock.BLOCK_SUPPORT_SHAPE; + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- BlockPos blockPos = pos.above(); +- if (level.isEmptyBlock(blockPos) && blockPos.getY() < level.getMaxBuildHeight()) { +- int i = state.getValue(AGE); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ BlockPos blockposition1 = pos.above(); ++ ++ if (level.isEmptyBlock(blockposition1) && blockposition1.getY() < level.getMaxBuildHeight()) { ++ int i = (Integer) state.getValue(ChorusFlowerBlock.AGE); ++ + if (i < 5) { + boolean flag = false; + boolean flag1 = false; +- BlockState blockState = level.getBlockState(pos.below()); +- if (blockState.is(Blocks.END_STONE)) { ++ IBlockData iblockdata1 = level.getBlockState(pos.below()); ++ int j; ++ ++ if (iblockdata1.is(Blocks.END_STONE)) { + flag = true; +- } else if (blockState.is(this.plant)) { +- int i1 = 1; ++ } else if (iblockdata1.is(this.plant)) { ++ j = 1; + +- for (int i2 = 0; i2 < 4; i2++) { +- BlockState blockState1 = level.getBlockState(pos.below(i1 + 1)); +- if (!blockState1.is(this.plant)) { +- if (blockState1.is(Blocks.END_STONE)) { ++ for (int k = 0; k < 4; ++k) { ++ IBlockData iblockdata2 = level.getBlockState(pos.below(j + 1)); ++ ++ if (!iblockdata2.is(this.plant)) { ++ if (iblockdata2.is(Blocks.END_STONE)) { + flag1 = true; + } + break; + } + +- i1++; ++ ++j; + } + +- if (i1 < 2 || i1 <= random.nextInt(flag1 ? 5 : 4)) { ++ if (j < 2 || j <= random.nextInt(flag1 ? 5 : 4)) { + flag = true; + } +- } else if (blockState.isAir()) { ++ } else if (iblockdata1.isAir()) { + flag = true; + } + +- if (flag && allNeighborsEmpty(level, blockPos, null) && level.isEmptyBlock(pos.above(2))) { +- level.setBlock(pos, ChorusPlantBlock.getStateWithConnections(level, pos, this.plant.defaultBlockState()), 2); +- this.placeGrownFlower(level, blockPos, i); ++ if (flag && allNeighborsEmpty(level, blockposition1, (Direction) null) && level.isEmptyBlock(pos.above(2))) { ++ // CraftBukkit start - add event ++ if (CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition1, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(i)), 2)) { ++ level.setBlock(pos, ChorusPlantBlock.getStateWithConnections(level, pos, this.plant.defaultBlockState()), 2); ++ this.placeGrownFlower(level, blockposition1, i); ++ } ++ // CraftBukkit end + } else if (i < 4) { +- int i1 = random.nextInt(4); ++ j = random.nextInt(4); + if (flag1) { +- i1++; ++ ++j; + } + + boolean flag2 = false; + +- for (int i3 = 0; i3 < i1; i3++) { +- Direction randomDirection = Direction.Plane.HORIZONTAL.getRandomDirection(random); +- BlockPos blockPos1 = pos.relative(randomDirection); +- if (level.isEmptyBlock(blockPos1) +- && level.isEmptyBlock(blockPos1.below()) +- && allNeighborsEmpty(level, blockPos1, randomDirection.getOpposite())) { +- this.placeGrownFlower(level, blockPos1, i + 1); +- flag2 = true; ++ for (int l = 0; l < j; ++l) { ++ Direction enumdirection = Direction.Plane.HORIZONTAL.getRandomDirection(random); ++ BlockPos blockposition2 = pos.relative(enumdirection); ++ ++ if (level.isEmptyBlock(blockposition2) && level.isEmptyBlock(blockposition2.below()) && allNeighborsEmpty(level, blockposition2, enumdirection.getOpposite())) { ++ // CraftBukkit start - add event ++ if (CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition2, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(i + 1)), 2)) { ++ this.placeGrownFlower(level, blockposition2, i + 1); ++ flag2 = true; ++ } ++ // CraftBukkit end + } + } + + if (flag2) { + level.setBlock(pos, ChorusPlantBlock.getStateWithConnections(level, pos, this.plant.defaultBlockState()), 2); + } else { +- this.placeDeadFlower(level, pos); ++ // CraftBukkit start - add event ++ if (CraftEventFactory.handleBlockGrowEvent(level, pos, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(5)), 2)) { ++ this.placeDeadFlower(level, pos); ++ } ++ // CraftBukkit end + } + } else { +- this.placeDeadFlower(level, pos); ++ // CraftBukkit start - add event ++ if (CraftEventFactory.handleBlockGrowEvent(level, pos, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(5)), 2)) { ++ this.placeDeadFlower(level, pos); ++ } ++ // CraftBukkit end + } ++ + } + } + } + + private void placeGrownFlower(Level level, BlockPos pos, int age) { +- level.setBlock(pos, this.defaultBlockState().setValue(AGE, Integer.valueOf(age)), 2); ++ level.setBlock(pos, (IBlockData) this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, age), 2); + level.levelEvent(1033, pos, 0); + } + + private void placeDeadFlower(Level level, BlockPos pos) { +- level.setBlock(pos, this.defaultBlockState().setValue(AGE, Integer.valueOf(5)), 2); ++ level.setBlock(pos, (IBlockData) this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, 5), 2); + level.levelEvent(1034, pos, 0); + } + + private static boolean allNeighborsEmpty(LevelReader level, BlockPos pos, @Nullable Direction excludingSide) { +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- if (direction != excludingSide && !level.isEmptyBlock(pos.relative(direction))) { +- return false; ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); ++ ++ Direction enumdirection1; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return true; + } +- } + +- return true; ++ enumdirection1 = (Direction) iterator.next(); ++ } while (enumdirection1 == excludingSide || level.isEmptyBlock(pos.relative(enumdirection1))); ++ ++ return false; + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { + if (facing != Direction.UP && !state.canSurvive(level, currentPos)) { +- level.scheduleTick(currentPos, this, 1); ++ level.scheduleTick(currentPos, (Block) this, 1); + } + + return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { +- BlockState blockState = level.getBlockState(pos.below()); +- if (!blockState.is(this.plant) && !blockState.is(Blocks.END_STONE)) { +- if (!blockState.isAir()) { ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ IBlockData iblockdata1 = level.getBlockState(pos.below()); ++ ++ if (!iblockdata1.is(this.plant) && !iblockdata1.is(Blocks.END_STONE)) { ++ if (!iblockdata1.isAir()) { + return false; + } else { + boolean flag = false; ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- BlockState blockState1 = level.getBlockState(pos.relative(direction)); +- if (blockState1.is(this.plant)) { ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ IBlockData iblockdata2 = level.getBlockState(pos.relative(enumdirection)); ++ ++ if (iblockdata2.is(this.plant)) { + if (flag) { + return false; + } + + flag = true; +- } else if (!blockState1.isAir()) { ++ } else if (!iblockdata2.isAir()) { + return false; + } + } +@@ -188,8 +222,8 @@ + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(AGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(ChorusFlowerBlock.AGE); + } + + public static void generatePlant(LevelAccessor level, BlockPos pos, RandomSource random, int maxHorizontalDistance) { +@@ -197,62 +231,65 @@ + growTreeRecursive(level, pos, random, pos, maxHorizontalDistance, 0); + } + +- private static void growTreeRecursive( +- LevelAccessor level, BlockPos branchPos, RandomSource random, BlockPos originalBranchPos, int maxHorizontalDistance, int iterations +- ) { ++ private static void growTreeRecursive(LevelAccessor level, BlockPos branchPos, RandomSource random, BlockPos originalBranchPos, int maxHorizontalDistance, int iterations) { + Block block = Blocks.CHORUS_PLANT; +- int i = random.nextInt(4) + 1; ++ int k = random.nextInt(4) + 1; ++ + if (iterations == 0) { +- i++; ++ ++k; + } + +- for (int i1 = 0; i1 < i; i1++) { +- BlockPos blockPos = branchPos.above(i1 + 1); +- if (!allNeighborsEmpty(level, blockPos, null)) { ++ for (int l = 0; l < k; ++l) { ++ BlockPos blockposition2 = branchPos.above(l + 1); ++ ++ if (!allNeighborsEmpty(level, blockposition2, (Direction) null)) { + return; + } + +- level.setBlock(blockPos, ChorusPlantBlock.getStateWithConnections(level, blockPos, block.defaultBlockState()), 2); +- level.setBlock(blockPos.below(), ChorusPlantBlock.getStateWithConnections(level, blockPos.below(), block.defaultBlockState()), 2); ++ level.setBlock(blockposition2, ChorusPlantBlock.getStateWithConnections(level, blockposition2, block.defaultBlockState()), 2); ++ level.setBlock(blockposition2.below(), ChorusPlantBlock.getStateWithConnections(level, blockposition2.below(), block.defaultBlockState()), 2); + } + + boolean flag = false; ++ + if (iterations < 4) { +- int randomInt = random.nextInt(4); ++ int i1 = random.nextInt(4); ++ + if (iterations == 0) { +- randomInt++; ++ ++i1; + } + +- for (int i2 = 0; i2 < randomInt; i2++) { +- Direction randomDirection = Direction.Plane.HORIZONTAL.getRandomDirection(random); +- BlockPos blockPos1 = branchPos.above(i).relative(randomDirection); +- if (Math.abs(blockPos1.getX() - originalBranchPos.getX()) < maxHorizontalDistance +- && Math.abs(blockPos1.getZ() - originalBranchPos.getZ()) < maxHorizontalDistance +- && level.isEmptyBlock(blockPos1) +- && level.isEmptyBlock(blockPos1.below()) +- && allNeighborsEmpty(level, blockPos1, randomDirection.getOpposite())) { ++ for (int j1 = 0; j1 < i1; ++j1) { ++ Direction enumdirection = Direction.Plane.HORIZONTAL.getRandomDirection(random); ++ BlockPos blockposition3 = branchPos.above(k).relative(enumdirection); ++ ++ if (Math.abs(blockposition3.getX() - originalBranchPos.getX()) < maxHorizontalDistance && Math.abs(blockposition3.getZ() - originalBranchPos.getZ()) < maxHorizontalDistance && level.isEmptyBlock(blockposition3) && level.isEmptyBlock(blockposition3.below()) && allNeighborsEmpty(level, blockposition3, enumdirection.getOpposite())) { + flag = true; +- level.setBlock(blockPos1, ChorusPlantBlock.getStateWithConnections(level, blockPos1, block.defaultBlockState()), 2); +- level.setBlock( +- blockPos1.relative(randomDirection.getOpposite()), +- ChorusPlantBlock.getStateWithConnections(level, blockPos1.relative(randomDirection.getOpposite()), block.defaultBlockState()), +- 2 +- ); +- growTreeRecursive(level, blockPos1, random, originalBranchPos, maxHorizontalDistance, iterations + 1); ++ level.setBlock(blockposition3, ChorusPlantBlock.getStateWithConnections(level, blockposition3, block.defaultBlockState()), 2); ++ level.setBlock(blockposition3.relative(enumdirection.getOpposite()), ChorusPlantBlock.getStateWithConnections(level, blockposition3.relative(enumdirection.getOpposite()), block.defaultBlockState()), 2); ++ growTreeRecursive(level, blockposition3, random, originalBranchPos, maxHorizontalDistance, iterations + 1); + } + } + } + + if (!flag) { +- level.setBlock(branchPos.above(i), Blocks.CHORUS_FLOWER.defaultBlockState().setValue(AGE, Integer.valueOf(5)), 2); ++ level.setBlock(branchPos.above(k), (IBlockData) Blocks.CHORUS_FLOWER.defaultBlockState().setValue(ChorusFlowerBlock.AGE, 5), 2); + } ++ + } + + @Override +- public void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) { +- BlockPos blockPos = hit.getBlockPos(); +- if (!level.isClientSide && projectile.mayInteract(level, blockPos) && projectile.mayBreak(level)) { +- level.destroyBlock(blockPos, true, projectile); ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { ++ BlockPos blockposition = hit.getBlockPos(); ++ ++ if (!level.isClientSide && projectile.mayInteract(level, blockposition) && projectile.mayBreak(level)) { ++ // CraftBukkit ++ if (!CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, Blocks.AIR.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end ++ level.destroyBlock(blockposition, true, projectile); + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/CocoaBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CocoaBlock.java.patch new file mode 100644 index 0000000000..2cbafc1f7a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CocoaBlock.java.patch @@ -0,0 +1,184 @@ +--- a/net/minecraft/world/level/block/CocoaBlock.java ++++ b/net/minecraft/world/level/block/CocoaBlock.java +@@ -13,15 +13,17 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class CocoaBlock extends HorizontalDirectionalBlock implements BonemealableBlock { ++ + public static final MapCodec CODEC = simpleCodec(CocoaBlock::new); + public static final int MAX_AGE = 2; + public static final IntegerProperty AGE = BlockStateProperties.AGE_2; +@@ -34,78 +36,78 @@ + protected static final int AGE_2_WIDTH = 8; + protected static final int AGE_2_HEIGHT = 9; + protected static final int AGE_2_HALFWIDTH = 4; +- protected static final VoxelShape[] EAST_AABB = new VoxelShape[]{ +- Block.box(11.0, 7.0, 6.0, 15.0, 12.0, 10.0), Block.box(9.0, 5.0, 5.0, 15.0, 12.0, 11.0), Block.box(7.0, 3.0, 4.0, 15.0, 12.0, 12.0) +- }; +- protected static final VoxelShape[] WEST_AABB = new VoxelShape[]{ +- Block.box(1.0, 7.0, 6.0, 5.0, 12.0, 10.0), Block.box(1.0, 5.0, 5.0, 7.0, 12.0, 11.0), Block.box(1.0, 3.0, 4.0, 9.0, 12.0, 12.0) +- }; +- protected static final VoxelShape[] NORTH_AABB = new VoxelShape[]{ +- Block.box(6.0, 7.0, 1.0, 10.0, 12.0, 5.0), Block.box(5.0, 5.0, 1.0, 11.0, 12.0, 7.0), Block.box(4.0, 3.0, 1.0, 12.0, 12.0, 9.0) +- }; +- protected static final VoxelShape[] SOUTH_AABB = new VoxelShape[]{ +- Block.box(6.0, 7.0, 11.0, 10.0, 12.0, 15.0), Block.box(5.0, 5.0, 9.0, 11.0, 12.0, 15.0), Block.box(4.0, 3.0, 7.0, 12.0, 12.0, 15.0) +- }; ++ protected static final VoxelShape[] EAST_AABB = new VoxelShape[]{Block.box(11.0D, 7.0D, 6.0D, 15.0D, 12.0D, 10.0D), Block.box(9.0D, 5.0D, 5.0D, 15.0D, 12.0D, 11.0D), Block.box(7.0D, 3.0D, 4.0D, 15.0D, 12.0D, 12.0D)}; ++ protected static final VoxelShape[] WEST_AABB = new VoxelShape[]{Block.box(1.0D, 7.0D, 6.0D, 5.0D, 12.0D, 10.0D), Block.box(1.0D, 5.0D, 5.0D, 7.0D, 12.0D, 11.0D), Block.box(1.0D, 3.0D, 4.0D, 9.0D, 12.0D, 12.0D)}; ++ protected static final VoxelShape[] NORTH_AABB = new VoxelShape[]{Block.box(6.0D, 7.0D, 1.0D, 10.0D, 12.0D, 5.0D), Block.box(5.0D, 5.0D, 1.0D, 11.0D, 12.0D, 7.0D), Block.box(4.0D, 3.0D, 1.0D, 12.0D, 12.0D, 9.0D)}; ++ protected static final VoxelShape[] SOUTH_AABB = new VoxelShape[]{Block.box(6.0D, 7.0D, 11.0D, 10.0D, 12.0D, 15.0D), Block.box(5.0D, 5.0D, 9.0D, 11.0D, 12.0D, 15.0D), Block.box(4.0D, 3.0D, 7.0D, 12.0D, 12.0D, 15.0D)}; + + @Override + public MapCodec codec() { +- return CODEC; ++ return CocoaBlock.CODEC; + } + + public CocoaBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(AGE, Integer.valueOf(0))); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(CocoaBlock.FACING, Direction.NORTH)).setValue(CocoaBlock.AGE, 0)); + } + + @Override +- public boolean isRandomlyTicking(BlockState state) { +- return state.getValue(AGE) < 2; ++ public boolean isRandomlyTicking(IBlockData state) { ++ return (Integer) state.getValue(CocoaBlock.AGE) < 2; + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (level.random.nextInt(5) == 0) { +- int i = state.getValue(AGE); ++ int i = (Integer) state.getValue(CocoaBlock.AGE); ++ + if (i < 2) { +- level.setBlock(pos, state.setValue(AGE, Integer.valueOf(i + 1)), 2); ++ CraftEventFactory.handleBlockGrowEvent(level, pos, (IBlockData) state.setValue(CocoaBlock.AGE, i + 1), 2); // CraftBukkkit + } + } ++ + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { +- BlockState blockState = level.getBlockState(pos.relative(state.getValue(FACING))); +- return blockState.is(BlockTags.JUNGLE_LOGS); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ IBlockData iblockdata1 = level.getBlockState(pos.relative((Direction) state.getValue(CocoaBlock.FACING))); ++ ++ return iblockdata1.is(BlockTags.JUNGLE_LOGS); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- int i = state.getValue(AGE); +- switch ((Direction)state.getValue(FACING)) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ int i = (Integer) state.getValue(CocoaBlock.AGE); ++ ++ switch ((Direction) state.getValue(CocoaBlock.FACING)) { + case SOUTH: +- return SOUTH_AABB[i]; ++ return CocoaBlock.SOUTH_AABB[i]; + case NORTH: + default: +- return NORTH_AABB[i]; ++ return CocoaBlock.NORTH_AABB[i]; + case WEST: +- return WEST_AABB[i]; ++ return CocoaBlock.WEST_AABB[i]; + case EAST: +- return EAST_AABB[i]; ++ return CocoaBlock.EAST_AABB[i]; + } + } + + @Nullable + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- BlockState blockState = this.defaultBlockState(); +- LevelReader level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ IBlockData iblockdata = this.defaultBlockState(); ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ Direction[] aenumdirection = context.getNearestLookingDirections(); ++ int i = aenumdirection.length; + +- for (Direction direction : context.getNearestLookingDirections()) { +- if (direction.getAxis().isHorizontal()) { +- blockState = blockState.setValue(FACING, direction); +- if (blockState.canSurvive(level, clickedPos)) { +- return blockState; ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ ++ if (enumdirection.getAxis().isHorizontal()) { ++ iblockdata = (IBlockData) iblockdata.setValue(CocoaBlock.FACING, enumdirection); ++ if (iblockdata.canSurvive(world, blockposition)) { ++ return iblockdata; + } + } + } +@@ -114,34 +116,32 @@ + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- return facing == state.getValue(FACING) && !state.canSurvive(level, currentPos) +- ? Blocks.AIR.defaultBlockState() +- : super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ return facing == state.getValue(CocoaBlock.FACING) && !state.canSurvive(level, currentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- public boolean isValidBonemealTarget(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { +- return blockState.getValue(AGE) < 2; ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ return (Integer) iblockdata.getValue(CocoaBlock.AGE) < 2; + } + + @Override +- public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, BlockState state) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return true; + } + + @Override +- public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) { +- level.setBlock(pos, state.setValue(AGE, Integer.valueOf(state.getValue(AGE) + 1)), 2); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ CraftEventFactory.handleBlockGrowEvent(level, pos, (IBlockData) state.setValue(CocoaBlock.AGE, (Integer) state.getValue(CocoaBlock.AGE) + 1), 2); // CraftBukkit + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(FACING, AGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(CocoaBlock.FACING, CocoaBlock.AGE); + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/CommandBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CommandBlock.java.patch new file mode 100644 index 0000000000..1eae375d27 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CommandBlock.java.patch @@ -0,0 +1,357 @@ +--- a/net/minecraft/world/level/block/CommandBlock.java ++++ b/net/minecraft/world/level/block/CommandBlock.java +@@ -4,13 +4,12 @@ + import com.mojang.serialization.Codec; + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.RandomSource; + import net.minecraft.util.StringUtil; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.player.Player; +@@ -23,7 +22,7 @@ + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.CommandBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -31,96 +30,121 @@ + import net.minecraft.world.phys.BlockHitResult; + import org.slf4j.Logger; + ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit ++ + public class CommandBlock extends BaseEntityBlock implements GameMasterBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group(Codec.BOOL.fieldOf("automatic").forGetter(commandBlock -> commandBlock.automatic), propertiesCodec()) +- .apply(instance, CommandBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(Codec.BOOL.fieldOf("automatic").forGetter((blockcommand) -> { ++ return blockcommand.automatic; ++ }), propertiesCodec()).apply(instance, CommandBlock::new); ++ }); + private static final Logger LOGGER = LogUtils.getLogger(); +- public static final DirectionProperty FACING = DirectionalBlock.FACING; ++ public static final DirectionProperty FACING = BlockDirectional.FACING; + public static final BooleanProperty CONDITIONAL = BlockStateProperties.CONDITIONAL; + private final boolean automatic; + + @Override + public MapCodec codec() { +- return CODEC; ++ return CommandBlock.CODEC; + } + +- public CommandBlock(boolean flag, BlockBehaviour.Properties properties) { +- super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(CONDITIONAL, Boolean.valueOf(false))); ++ public CommandBlock(boolean flag, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(CommandBlock.FACING, Direction.NORTH)).setValue(CommandBlock.CONDITIONAL, false)); + this.automatic = flag; + } + + @Override +- public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { +- CommandBlockEntity commandBlockEntity = new CommandBlockEntity(pos, state); +- commandBlockEntity.setAutomatic(this.automatic); +- return commandBlockEntity; ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ CommandBlockEntity tileentitycommand = new CommandBlockEntity(pos, state); ++ ++ tileentitycommand.setAutomatic(this.automatic); ++ return tileentitycommand; + } + + @Override +- public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { + if (!level.isClientSide) { +- if (level.getBlockEntity(pos) instanceof CommandBlockEntity commandBlockEntity) { +- boolean hasNeighborSignal = level.hasNeighborSignal(pos); +- boolean isPowered = commandBlockEntity.isPowered(); +- commandBlockEntity.setPowered(hasNeighborSignal); +- if (!isPowered && !commandBlockEntity.isAutomatic() && commandBlockEntity.getMode() != CommandBlockEntity.Mode.SEQUENCE) { +- if (hasNeighborSignal) { +- commandBlockEntity.markConditionMet(); +- level.scheduleTick(pos, this, 1); ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof CommandBlockEntity) { ++ CommandBlockEntity tileentitycommand = (CommandBlockEntity) tileentity; ++ boolean flag1 = level.hasNeighborSignal(pos); ++ boolean flag2 = tileentitycommand.isPowered(); ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ int old = flag2 ? 15 : 0; ++ int current = flag1 ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bukkitBlock, old, current); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ flag1 = eventRedstone.getNewCurrent() > 0; ++ // CraftBukkit end ++ ++ tileentitycommand.setPowered(flag1); ++ if (!flag2 && !tileentitycommand.isAutomatic() && tileentitycommand.getMode() != CommandBlockEntity.Type.SEQUENCE) { ++ if (flag1) { ++ tileentitycommand.markConditionMet(); ++ level.scheduleTick(pos, (Block) this, 1); + } ++ + } + } + } + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- if (level.getBlockEntity(pos) instanceof CommandBlockEntity commandBlockEntity) { +- BaseCommandBlock commandBlock = commandBlockEntity.getCommandBlock(); +- boolean flag = !StringUtil.isNullOrEmpty(commandBlock.getCommand()); +- CommandBlockEntity.Mode mode = commandBlockEntity.getMode(); +- boolean flag1 = commandBlockEntity.wasConditionMet(); +- if (mode == CommandBlockEntity.Mode.AUTO) { +- commandBlockEntity.markConditionMet(); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof CommandBlockEntity) { ++ CommandBlockEntity tileentitycommand = (CommandBlockEntity) tileentity; ++ BaseCommandBlock commandblocklistenerabstract = tileentitycommand.getCommandBlock(); ++ boolean flag = !StringUtil.isNullOrEmpty(commandblocklistenerabstract.getCommand()); ++ CommandBlockEntity.Type tileentitycommand_type = tileentitycommand.getMode(); ++ boolean flag1 = tileentitycommand.wasConditionMet(); ++ ++ if (tileentitycommand_type == CommandBlockEntity.Type.AUTO) { ++ tileentitycommand.markConditionMet(); + if (flag1) { +- this.execute(state, level, pos, commandBlock, flag); +- } else if (commandBlockEntity.isConditional()) { +- commandBlock.setSuccessCount(0); ++ this.execute(state, level, pos, commandblocklistenerabstract, flag); ++ } else if (tileentitycommand.isConditional()) { ++ commandblocklistenerabstract.setSuccessCount(0); + } + +- if (commandBlockEntity.isPowered() || commandBlockEntity.isAutomatic()) { +- level.scheduleTick(pos, this, 1); ++ if (tileentitycommand.isPowered() || tileentitycommand.isAutomatic()) { ++ level.scheduleTick(pos, (Block) this, 1); + } +- } else if (mode == CommandBlockEntity.Mode.REDSTONE) { ++ } else if (tileentitycommand_type == CommandBlockEntity.Type.REDSTONE) { + if (flag1) { +- this.execute(state, level, pos, commandBlock, flag); +- } else if (commandBlockEntity.isConditional()) { +- commandBlock.setSuccessCount(0); ++ this.execute(state, level, pos, commandblocklistenerabstract, flag); ++ } else if (tileentitycommand.isConditional()) { ++ commandblocklistenerabstract.setSuccessCount(0); + } + } + + level.updateNeighbourForOutputSignal(pos, this); + } ++ + } + +- private void execute(BlockState state, Level level, BlockPos pos, BaseCommandBlock logic, boolean canTrigger) { ++ private void execute(IBlockData state, Level level, BlockPos pos, BaseCommandBlock logic, boolean canTrigger) { + if (canTrigger) { + logic.performCommand(level); + } else { + logic.setSuccessCount(0); + } + +- executeChain(level, pos, state.getValue(FACING)); ++ executeChain(level, pos, (Direction) state.getValue(CommandBlock.FACING)); + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { +- BlockEntity blockEntity = level.getBlockEntity(pos); +- if (blockEntity instanceof CommandBlockEntity && player.canUseGameMasterBlocks()) { +- player.openCommandBlock((CommandBlockEntity)blockEntity); ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof CommandBlockEntity && player.canUseGameMasterBlocks()) { ++ player.openCommandBlock((CommandBlockEntity) tileentity); + return InteractionResult.sidedSuccess(level.isClientSide); + } else { + return InteractionResult.PASS; +@@ -128,97 +152,118 @@ + } + + @Override +- public boolean hasAnalogOutputSignal(BlockState state) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return true; + } + + @Override +- public int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) { +- BlockEntity blockEntity = level.getBlockEntity(pos); +- return blockEntity instanceof CommandBlockEntity ? ((CommandBlockEntity)blockEntity).getCommandBlock().getSuccessCount() : 0; ++ public int getAnalogOutputSignal(IBlockData blockState, Level level, BlockPos pos) { ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ return tileentity instanceof CommandBlockEntity ? ((CommandBlockEntity) tileentity).getCommandBlock().getSuccessCount() : 0; + } + + @Override +- public void setPlacedBy(Level level, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { +- if (level.getBlockEntity(pos) instanceof CommandBlockEntity commandBlockEntity) { +- BaseCommandBlock commandBlock = commandBlockEntity.getCommandBlock(); ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, LivingEntity placer, ItemStack stack) { ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof CommandBlockEntity) { ++ CommandBlockEntity tileentitycommand = (CommandBlockEntity) tileentity; ++ BaseCommandBlock commandblocklistenerabstract = tileentitycommand.getCommandBlock(); ++ + if (stack.hasCustomHoverName()) { +- commandBlock.setName(stack.getHoverName()); ++ commandblocklistenerabstract.setName(stack.getHoverName()); + } + + if (!level.isClientSide) { + if (BlockItem.getBlockEntityData(stack) == null) { +- commandBlock.setTrackOutput(level.getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK)); +- commandBlockEntity.setAutomatic(this.automatic); ++ commandblocklistenerabstract.setTrackOutput(level.getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK)); ++ tileentitycommand.setAutomatic(this.automatic); + } + +- if (commandBlockEntity.getMode() == CommandBlockEntity.Mode.SEQUENCE) { +- boolean hasNeighborSignal = level.hasNeighborSignal(pos); +- commandBlockEntity.setPowered(hasNeighborSignal); ++ if (tileentitycommand.getMode() == CommandBlockEntity.Type.SEQUENCE) { ++ boolean flag = level.hasNeighborSignal(pos); ++ ++ tileentitycommand.setPowered(flag); + } + } ++ + } + } + + @Override +- public RenderShape getRenderShape(BlockState state) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Override +- public BlockState rotate(BlockState state, Rotation rotation) { +- return state.setValue(FACING, rotation.rotate(state.getValue(FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return (IBlockData) state.setValue(CommandBlock.FACING, rotation.rotate((Direction) state.getValue(CommandBlock.FACING))); + } + + @Override +- public BlockState mirror(BlockState state, Mirror mirror) { +- return state.rotate(mirror.getRotation(state.getValue(FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(CommandBlock.FACING))); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(FACING, CONDITIONAL); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(CommandBlock.FACING, CommandBlock.CONDITIONAL); + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- return this.defaultBlockState().setValue(FACING, context.getNearestLookingDirection().getOpposite()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return (IBlockData) this.defaultBlockState().setValue(CommandBlock.FACING, context.getNearestLookingDirection().getOpposite()); + } + + private static void executeChain(Level level, BlockPos pos, Direction direction) { +- BlockPos.MutableBlockPos mutableBlockPos = pos.mutable(); +- GameRules gameRules = level.getGameRules(); +- int _int = gameRules.getInt(GameRules.RULE_MAX_COMMAND_CHAIN_LENGTH); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); ++ GameRules gamerules = level.getGameRules(); + +- while (_int-- > 0) { +- mutableBlockPos.move(direction); +- BlockState blockState = level.getBlockState(mutableBlockPos); +- Block block = blockState.getBlock(); +- if (!blockState.is(Blocks.CHAIN_COMMAND_BLOCK) +- || !(level.getBlockEntity(mutableBlockPos) instanceof CommandBlockEntity commandBlockEntity) +- || commandBlockEntity.getMode() != CommandBlockEntity.Mode.SEQUENCE) { ++ IBlockData iblockdata; ++ int i; ++ ++ for (i = gamerules.getInt(GameRules.RULE_MAX_COMMAND_CHAIN_LENGTH); i-- > 0; direction = (Direction) iblockdata.getValue(CommandBlock.FACING)) { ++ blockposition_mutableblockposition.move(direction); ++ iblockdata = level.getBlockState(blockposition_mutableblockposition); ++ Block block = iblockdata.getBlock(); ++ ++ if (!iblockdata.is(Blocks.CHAIN_COMMAND_BLOCK)) { + break; + } + +- if (commandBlockEntity.isPowered() || commandBlockEntity.isAutomatic()) { +- BaseCommandBlock commandBlock = commandBlockEntity.getCommandBlock(); +- if (commandBlockEntity.markConditionMet()) { +- if (!commandBlock.performCommand(level)) { ++ BlockEntity tileentity = level.getBlockEntity(blockposition_mutableblockposition); ++ ++ if (!(tileentity instanceof CommandBlockEntity)) { ++ break; ++ } ++ ++ CommandBlockEntity tileentitycommand = (CommandBlockEntity) tileentity; ++ ++ if (tileentitycommand.getMode() != CommandBlockEntity.Type.SEQUENCE) { ++ break; ++ } ++ ++ if (tileentitycommand.isPowered() || tileentitycommand.isAutomatic()) { ++ BaseCommandBlock commandblocklistenerabstract = tileentitycommand.getCommandBlock(); ++ ++ if (tileentitycommand.markConditionMet()) { ++ if (!commandblocklistenerabstract.performCommand(level)) { + break; + } + +- level.updateNeighbourForOutputSignal(mutableBlockPos, block); +- } else if (commandBlockEntity.isConditional()) { +- commandBlock.setSuccessCount(0); ++ level.updateNeighbourForOutputSignal(blockposition_mutableblockposition, block); ++ } else if (tileentitycommand.isConditional()) { ++ commandblocklistenerabstract.setSuccessCount(0); + } + } +- +- direction = blockState.getValue(FACING); + } + +- if (_int <= 0) { +- int max = Math.max(gameRules.getInt(GameRules.RULE_MAX_COMMAND_CHAIN_LENGTH), 0); +- LOGGER.warn("Command Block chain tried to execute more than {} steps!", max); ++ if (i <= 0) { ++ int j = Math.max(gamerules.getInt(GameRules.RULE_MAX_COMMAND_CHAIN_LENGTH), 0); ++ ++ CommandBlock.LOGGER.warn("Command Block chain tried to execute more than {} steps!", j); + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/ComparatorBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/ComparatorBlock.java.patch new file mode 100644 index 0000000000..dabef3db52 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/ComparatorBlock.java.patch @@ -0,0 +1,282 @@ +--- a/net/minecraft/world/level/block/ComparatorBlock.java ++++ b/net/minecraft/world/level/block/ComparatorBlock.java +@@ -9,7 +9,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.decoration.ItemFrame; + import net.minecraft.world.entity.player.Player; +@@ -19,7 +19,7 @@ + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.ComparatorBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.ComparatorMode; +@@ -27,84 +27,82 @@ + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.ticks.TickPriority; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class ComparatorBlock extends DiodeBlock implements EntityBlock { ++ + public static final MapCodec CODEC = simpleCodec(ComparatorBlock::new); + public static final EnumProperty MODE = BlockStateProperties.MODE_COMPARATOR; + + @Override + public MapCodec codec() { +- return CODEC; ++ return ComparatorBlock.CODEC; + } + + public ComparatorBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState( +- this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(POWERED, Boolean.valueOf(false)).setValue(MODE, ComparatorMode.COMPARE) +- ); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(ComparatorBlock.FACING, Direction.NORTH)).setValue(ComparatorBlock.POWERED, false)).setValue(ComparatorBlock.MODE, ComparatorMode.COMPARE)); + } + + @Override +- protected int getDelay(BlockState state) { ++ protected int getDelay(IBlockData state) { + return 2; + } + + @Override +- public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { +- return direction == Direction.DOWN && !this.canSurviveOn(level, neighborPos, neighborState) +- ? Blocks.AIR.defaultBlockState() +- : super.updateShape(state, direction, neighborState, level, pos, neighborPos); ++ public IBlockData updateShape(IBlockData state, Direction direction, IBlockData neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { ++ return direction == Direction.DOWN && !this.canSurviveOn(level, neighborPos, neighborState) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, direction, neighborState, level, pos, neighborPos); + } + + @Override +- protected int getOutputSignal(BlockGetter level, BlockPos pos, BlockState state) { +- BlockEntity blockEntity = level.getBlockEntity(pos); +- return blockEntity instanceof ComparatorBlockEntity ? ((ComparatorBlockEntity)blockEntity).getOutputSignal() : 0; ++ protected int getOutputSignal(BlockGetter level, BlockPos pos, IBlockData state) { ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ return tileentity instanceof ComparatorBlockEntity ? ((ComparatorBlockEntity) tileentity).getOutputSignal() : 0; + } + +- private int calculateOutputSignal(Level level, BlockPos pos, BlockState state) { +- int inputSignal = this.getInputSignal(level, pos, state); +- if (inputSignal == 0) { ++ private int calculateOutputSignal(Level level, BlockPos pos, IBlockData state) { ++ int i = this.getInputSignal(level, pos, state); ++ ++ if (i == 0) { + return 0; + } else { +- int alternateSignal = this.getAlternateSignal(level, pos, state); +- if (alternateSignal > inputSignal) { +- return 0; +- } else { +- return state.getValue(MODE) == ComparatorMode.SUBTRACT ? inputSignal - alternateSignal : inputSignal; +- } ++ int j = this.getAlternateSignal(level, pos, state); ++ ++ return j > i ? 0 : (state.getValue(ComparatorBlock.MODE) == ComparatorMode.SUBTRACT ? i - j : i); + } + } + + @Override +- protected boolean shouldTurnOn(Level level, BlockPos pos, BlockState state) { +- int inputSignal = this.getInputSignal(level, pos, state); +- if (inputSignal == 0) { ++ protected boolean shouldTurnOn(Level level, BlockPos pos, IBlockData state) { ++ int i = this.getInputSignal(level, pos, state); ++ ++ if (i == 0) { + return false; + } else { +- int alternateSignal = this.getAlternateSignal(level, pos, state); +- return inputSignal > alternateSignal || inputSignal == alternateSignal && state.getValue(MODE) == ComparatorMode.COMPARE; ++ int j = this.getAlternateSignal(level, pos, state); ++ ++ return i > j ? true : i == j && state.getValue(ComparatorBlock.MODE) == ComparatorMode.COMPARE; + } + } + + @Override +- protected int getInputSignal(Level level, BlockPos pos, BlockState state) { ++ protected int getInputSignal(Level level, BlockPos pos, IBlockData state) { + int i = super.getInputSignal(level, pos, state); +- Direction direction = state.getValue(FACING); +- BlockPos blockPos = pos.relative(direction); +- BlockState blockState = level.getBlockState(blockPos); +- if (blockState.hasAnalogOutputSignal()) { +- i = blockState.getAnalogOutputSignal(level, blockPos); +- } else if (i < 15 && blockState.isRedstoneConductor(level, blockPos)) { +- blockPos = blockPos.relative(direction); +- blockState = level.getBlockState(blockPos); +- ItemFrame itemFrame = this.getItemFrame(level, direction, blockPos); +- int max = Math.max( +- itemFrame == null ? Integer.MIN_VALUE : itemFrame.getAnalogOutput(), +- blockState.hasAnalogOutputSignal() ? blockState.getAnalogOutputSignal(level, blockPos) : Integer.MIN_VALUE +- ); +- if (max != Integer.MIN_VALUE) { +- i = max; ++ Direction enumdirection = (Direction) state.getValue(ComparatorBlock.FACING); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ if (iblockdata1.hasAnalogOutputSignal()) { ++ i = iblockdata1.getAnalogOutputSignal(level, blockposition1); ++ } else if (i < 15 && iblockdata1.isRedstoneConductor(level, blockposition1)) { ++ blockposition1 = blockposition1.relative(enumdirection); ++ iblockdata1 = level.getBlockState(blockposition1); ++ ItemFrame entityitemframe = this.getItemFrame(level, enumdirection, blockposition1); ++ int j = Math.max(entityitemframe == null ? Integer.MIN_VALUE : entityitemframe.getAnalogOutput(), iblockdata1.hasAnalogOutputSignal() ? iblockdata1.getAnalogOutputSignal(level, blockposition1) : Integer.MIN_VALUE); ++ ++ if (j != Integer.MIN_VALUE) { ++ i = j; + } + } + +@@ -113,21 +111,22 @@ + + @Nullable + private ItemFrame getItemFrame(Level level, Direction facing, BlockPos pos) { +- List entitiesOfClass = level.getEntitiesOfClass( +- ItemFrame.class, +- new AABB((double)pos.getX(), (double)pos.getY(), (double)pos.getZ(), (double)(pos.getX() + 1), (double)(pos.getY() + 1), (double)(pos.getZ() + 1)), +- itemFrame -> itemFrame != null && itemFrame.getDirection() == facing +- ); +- return entitiesOfClass.size() == 1 ? entitiesOfClass.get(0) : null; ++ // CraftBukkit - decompile error ++ List list = level.getEntitiesOfClass(ItemFrame.class, new AABB((double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), (double) (pos.getX() + 1), (double) (pos.getY() + 1), (double) (pos.getZ() + 1)), (java.util.function.Predicate) (entityitemframe) -> { ++ return entityitemframe != null && entityitemframe.getDirection() == facing; ++ }); ++ ++ return list.size() == 1 ? (ItemFrame) list.get(0) : null; + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + if (!player.getAbilities().mayBuild) { + return InteractionResult.PASS; + } else { +- state = state.cycle(MODE); +- float f = state.getValue(MODE) == ComparatorMode.SUBTRACT ? 0.55F : 0.5F; ++ state = (IBlockData) state.cycle(ComparatorBlock.MODE); ++ float f = state.getValue(ComparatorBlock.MODE) == ComparatorMode.SUBTRACT ? 0.55F : 0.5F; ++ + level.playSound(player, pos, SoundEvents.COMPARATOR_CLICK, SoundSource.BLOCKS, 0.3F, f); + level.setBlock(pos, state, 2); + this.refreshOutputState(level, pos, state); +@@ -136,59 +135,78 @@ + } + + @Override +- protected void checkTickOnNeighbor(Level level, BlockPos pos, BlockState state) { ++ protected void checkTickOnNeighbor(Level level, BlockPos pos, IBlockData state) { + if (!level.getBlockTicks().willTickThisTick(pos, this)) { + int i = this.calculateOutputSignal(level, pos, state); +- BlockEntity blockEntity = level.getBlockEntity(pos); +- int i1 = blockEntity instanceof ComparatorBlockEntity ? ((ComparatorBlockEntity)blockEntity).getOutputSignal() : 0; +- if (i != i1 || state.getValue(POWERED) != this.shouldTurnOn(level, pos, state)) { +- TickPriority tickPriority = this.shouldPrioritize(level, pos, state) ? TickPriority.HIGH : TickPriority.NORMAL; +- level.scheduleTick(pos, this, 2, tickPriority); ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ int j = tileentity instanceof ComparatorBlockEntity ? ((ComparatorBlockEntity) tileentity).getOutputSignal() : 0; ++ ++ if (i != j || (Boolean) state.getValue(ComparatorBlock.POWERED) != this.shouldTurnOn(level, pos, state)) { ++ TickPriority ticklistpriority = this.shouldPrioritize(level, pos, state) ? TickPriority.HIGH : TickPriority.NORMAL; ++ ++ level.scheduleTick(pos, (Block) this, 2, ticklistpriority); + } ++ + } + } + +- private void refreshOutputState(Level level, BlockPos pos, BlockState state) { ++ private void refreshOutputState(Level level, BlockPos pos, IBlockData state) { + int i = this.calculateOutputSignal(level, pos, state); +- BlockEntity blockEntity = level.getBlockEntity(pos); +- int i1 = 0; +- if (blockEntity instanceof ComparatorBlockEntity comparatorBlockEntity) { +- i1 = comparatorBlockEntity.getOutputSignal(); +- comparatorBlockEntity.setOutputSignal(i); ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ int j = 0; ++ ++ if (tileentity instanceof ComparatorBlockEntity) { ++ ComparatorBlockEntity tileentitycomparator = (ComparatorBlockEntity) tileentity; ++ ++ j = tileentitycomparator.getOutputSignal(); ++ tileentitycomparator.setOutputSignal(i); + } + +- if (i1 != i || state.getValue(MODE) == ComparatorMode.COMPARE) { +- boolean shouldTurnOn = this.shouldTurnOn(level, pos, state); +- boolean flag = state.getValue(POWERED); +- if (flag && !shouldTurnOn) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(false)), 2); +- } else if (!flag && shouldTurnOn) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(true)), 2); ++ if (j != i || state.getValue(ComparatorBlock.MODE) == ComparatorMode.COMPARE) { ++ boolean flag = this.shouldTurnOn(level, pos, state); ++ boolean flag1 = (Boolean) state.getValue(ComparatorBlock.POWERED); ++ ++ if (flag1 && !flag) { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 15, 0).getNewCurrent() != 0) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(ComparatorBlock.POWERED, false), 2); ++ } else if (!flag1 && flag) { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 0, 15).getNewCurrent() != 15) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(ComparatorBlock.POWERED, true), 2); + } + + this.updateNeighborsInFront(level, pos, state); + } ++ + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + this.refreshOutputState(level, pos, state); + } + + @Override +- public boolean triggerEvent(BlockState state, Level level, BlockPos pos, int id, int param) { ++ public boolean triggerEvent(IBlockData state, Level level, BlockPos pos, int id, int param) { + super.triggerEvent(state, level, pos, id, param); +- BlockEntity blockEntity = level.getBlockEntity(pos); +- return blockEntity != null && blockEntity.triggerEvent(id, param); ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ return tileentity != null && tileentity.triggerEvent(id, param); + } + + @Override +- public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { + return new ComparatorBlockEntity(pos, state); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(FACING, MODE, POWERED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(ComparatorBlock.FACING, ComparatorBlock.MODE, ComparatorBlock.POWERED); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/ComposterBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/ComposterBlock.java.patch new file mode 100644 index 0000000000..f5b32cecc2 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/ComposterBlock.java.patch @@ -0,0 +1,486 @@ +--- a/net/minecraft/world/level/block/ComposterBlock.java ++++ b/net/minecraft/world/level/block/ComposterBlock.java +@@ -13,7 +13,7 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.WorldlyContainer; +@@ -24,52 +24,58 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.level.BlockGetter; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.level.gameevent.GameEvent; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftBlockInventoryHolder; ++import org.bukkit.craftbukkit.util.DummyGeneratorAccess; ++// CraftBukkit end + + public class ComposterBlock extends Block implements WorldlyContainerHolder { ++ + public static final MapCodec CODEC = simpleCodec(ComposterBlock::new); + public static final int READY = 8; + public static final int MIN_LEVEL = 0; + public static final int MAX_LEVEL = 7; + public static final IntegerProperty LEVEL = BlockStateProperties.LEVEL_COMPOSTER; +- public static final Object2FloatMap COMPOSTABLES = new Object2FloatOpenHashMap<>(); ++ public static final Object2FloatMap COMPOSTABLES = new Object2FloatOpenHashMap(); + private static final int AABB_SIDE_THICKNESS = 2; + private static final VoxelShape OUTER_SHAPE = Shapes.block(); +- private static final VoxelShape[] SHAPES = Util.make(new VoxelShape[9], shapes -> { +- for (int i = 0; i < 8; i++) { +- shapes[i] = Shapes.join(OUTER_SHAPE, Block.box(2.0, (double)Math.max(2, 1 + i * 2), 2.0, 14.0, 16.0, 14.0), BooleanOp.ONLY_FIRST); ++ private static final VoxelShape[] SHAPES = (VoxelShape[]) Util.make(new VoxelShape[9], (avoxelshape) -> { ++ for (int i = 0; i < 8; ++i) { ++ avoxelshape[i] = Shapes.join(ComposterBlock.OUTER_SHAPE, Block.box(2.0D, (double) Math.max(2, 1 + i * 2), 2.0D, 14.0D, 16.0D, 14.0D), BooleanOp.ONLY_FIRST); + } + +- shapes[8] = shapes[7]; ++ avoxelshape[8] = avoxelshape[7]; + }); + + @Override + public MapCodec codec() { +- return CODEC; ++ return ComposterBlock.CODEC; + } + + public static void bootStrap() { +- COMPOSTABLES.defaultReturnValue(-1.0F); ++ ComposterBlock.COMPOSTABLES.defaultReturnValue(-1.0F); + float f = 0.3F; + float f1 = 0.5F; + float f2 = 0.65F; + float f3 = 0.85F; + float f4 = 1.0F; ++ + add(0.3F, Items.JUNGLE_LEAVES); + add(0.3F, Items.OAK_LEAVES); + add(0.3F, Items.SPRUCE_LEAVES); +@@ -173,72 +179,70 @@ + add(1.0F, Items.PUMPKIN_PIE); + } + +- private static void add(float chance, ItemLike item) { +- COMPOSTABLES.put(item.asItem(), chance); ++ private static void add(float chance, IMaterial item) { ++ ComposterBlock.COMPOSTABLES.put(item.asItem(), chance); + } + + public ComposterBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(LEVEL, Integer.valueOf(0))); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(ComposterBlock.LEVEL, 0)); + } + + public static void handleFill(Level level, BlockPos pos, boolean success) { +- BlockState blockState = level.getBlockState(pos); ++ IBlockData iblockdata = level.getBlockState(pos); ++ + level.playLocalSound(pos, success ? SoundEvents.COMPOSTER_FILL_SUCCESS : SoundEvents.COMPOSTER_FILL, SoundSource.BLOCKS, 1.0F, 1.0F, false); +- double d = blockState.getShape(level, pos).max(Direction.Axis.Y, 0.5, 0.5) + 0.03125; +- double d1 = 0.13125F; +- double d2 = 0.7375F; +- RandomSource random = level.getRandom(); ++ double d0 = iblockdata.getShape(level, pos).max(Direction.Axis.Y, 0.5D, 0.5D) + 0.03125D; ++ double d1 = 0.13124999403953552D; ++ double d2 = 0.737500011920929D; ++ RandomSource randomsource = level.getRandom(); + +- for (int i = 0; i < 10; i++) { +- double d3 = random.nextGaussian() * 0.02; +- double d4 = random.nextGaussian() * 0.02; +- double d5 = random.nextGaussian() * 0.02; +- level.addParticle( +- ParticleTypes.COMPOSTER, +- (double)pos.getX() + 0.13125F + 0.7375F * (double)random.nextFloat(), +- (double)pos.getY() + d + (double)random.nextFloat() * (1.0 - d), +- (double)pos.getZ() + 0.13125F + 0.7375F * (double)random.nextFloat(), +- d3, +- d4, +- d5 +- ); ++ for (int i = 0; i < 10; ++i) { ++ double d3 = randomsource.nextGaussian() * 0.02D; ++ double d4 = randomsource.nextGaussian() * 0.02D; ++ double d5 = randomsource.nextGaussian() * 0.02D; ++ ++ level.addParticle(ParticleTypes.COMPOSTER, (double) pos.getX() + 0.13124999403953552D + 0.737500011920929D * (double) randomsource.nextFloat(), (double) pos.getY() + d0 + (double) randomsource.nextFloat() * (1.0D - d0), (double) pos.getZ() + 0.13124999403953552D + 0.737500011920929D * (double) randomsource.nextFloat(), d3, d4, d5); + } ++ + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPES[state.getValue(LEVEL)]; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return ComposterBlock.SHAPES[(Integer) state.getValue(ComposterBlock.LEVEL)]; + } + + @Override +- public VoxelShape getInteractionShape(BlockState state, BlockGetter level, BlockPos pos) { +- return OUTER_SHAPE; ++ public VoxelShape getInteractionShape(IBlockData state, BlockGetter level, BlockPos pos) { ++ return ComposterBlock.OUTER_SHAPE; + } + + @Override +- public VoxelShape getCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPES[0]; ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return ComposterBlock.SHAPES[0]; + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { +- if (state.getValue(LEVEL) == 7) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ if ((Integer) state.getValue(ComposterBlock.LEVEL) == 7) { + level.scheduleTick(pos, state.getBlock(), 20); + } ++ + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { +- int i = state.getValue(LEVEL); +- ItemStack itemInHand = player.getItemInHand(hand); +- if (i < 8 && COMPOSTABLES.containsKey(itemInHand.getItem())) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ int i = (Integer) state.getValue(ComposterBlock.LEVEL); ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (i < 8 && ComposterBlock.COMPOSTABLES.containsKey(itemstack.getItem())) { + if (i < 7 && !level.isClientSide) { +- BlockState blockState = addItem(player, state, level, pos, itemInHand); +- level.levelEvent(1500, pos, state != blockState ? 1 : 0); +- player.awardStat(Stats.ITEM_USED.get(itemInHand.getItem())); ++ IBlockData iblockdata1 = addItem(player, state, level, pos, itemstack); ++ ++ level.levelEvent(1500, pos, state != iblockdata1 ? 1 : 0); ++ player.awardStat(Stats.ITEM_USED.get(itemstack.getItem())); + if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + } + +@@ -251,101 +255,143 @@ + } + } + +- public static BlockState insertItem(Entity entity, BlockState state, ServerLevel level, ItemStack stack, BlockPos pos) { +- int i = state.getValue(LEVEL); +- if (i < 7 && COMPOSTABLES.containsKey(stack.getItem())) { +- BlockState blockState = addItem(entity, state, level, pos, stack); ++ public static IBlockData insertItem(Entity entity, IBlockData state, ServerLevel level, ItemStack stack, BlockPos pos) { ++ int i = (Integer) state.getValue(ComposterBlock.LEVEL); ++ ++ if (i < 7 && ComposterBlock.COMPOSTABLES.containsKey(stack.getItem())) { ++ // CraftBukkit start ++ double rand = level.getRandom().nextDouble(); ++ IBlockData iblockdata1 = addItem(entity, state, DummyGeneratorAccess.INSTANCE, pos, stack, rand); ++ if (state == iblockdata1 || !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, iblockdata1)) { ++ return state; ++ } ++ iblockdata1 = addItem(entity, state, level, pos, stack, rand); ++ // CraftBukkit end ++ + stack.shrink(1); +- return blockState; ++ return iblockdata1; + } else { + return state; + } + } + +- public static BlockState extractProduce(Entity entity, BlockState state, Level level, BlockPos pos) { ++ public static IBlockData extractProduce(Entity entity, IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ if (entity != null && !(entity instanceof Player)) { ++ IBlockData iblockdata1 = empty(entity, state, DummyGeneratorAccess.INSTANCE, pos); ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, iblockdata1)) { ++ return state; ++ } ++ } ++ // CraftBukkit end + if (!level.isClientSide) { +- Vec3 vec3 = Vec3.atLowerCornerWithOffset(pos, 0.5, 1.01, 0.5).offsetRandom(level.random, 0.7F); +- ItemEntity itemEntity = new ItemEntity(level, vec3.x(), vec3.y(), vec3.z(), new ItemStack(Items.BONE_MEAL)); +- itemEntity.setDefaultPickUpDelay(); +- level.addFreshEntity(itemEntity); ++ Vec3 vec3d = Vec3.atLowerCornerWithOffset(pos, 0.5D, 1.01D, 0.5D).offsetRandom(level.random, 0.7F); ++ ItemEntity entityitem = new ItemEntity(level, vec3d.x(), vec3d.y(), vec3d.z(), new ItemStack(Items.BONE_MEAL)); ++ ++ entityitem.setDefaultPickUpDelay(); ++ level.addFreshEntity(entityitem); + } + +- BlockState blockState = empty(entity, state, level, pos); +- level.playSound(null, pos, SoundEvents.COMPOSTER_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); +- return blockState; ++ IBlockData iblockdata1 = empty(entity, state, level, pos); ++ ++ level.playSound((Player) null, pos, SoundEvents.COMPOSTER_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F); ++ return iblockdata1; + } + +- static BlockState empty(@Nullable Entity entity, BlockState state, LevelAccessor level, BlockPos pos) { +- BlockState blockState = state.setValue(LEVEL, Integer.valueOf(0)); +- level.setBlock(pos, blockState, 3); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, blockState)); +- return blockState; ++ static IBlockData empty(@Nullable Entity entity, IBlockData state, LevelAccessor level, BlockPos pos) { ++ IBlockData iblockdata1 = (IBlockData) state.setValue(ComposterBlock.LEVEL, 0); ++ ++ level.setBlock(pos, iblockdata1, 3); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, iblockdata1)); ++ return iblockdata1; + } + +- static BlockState addItem(@Nullable Entity entity, BlockState state, LevelAccessor level, BlockPos pos, ItemStack stack) { +- int i = state.getValue(LEVEL); +- float _float = COMPOSTABLES.getFloat(stack.getItem()); +- if ((i != 0 || !(_float > 0.0F)) && !(level.getRandom().nextDouble() < (double)_float)) { +- return state; ++ static IBlockData addItem(@Nullable Entity entity, IBlockData state, LevelAccessor level, BlockPos pos, ItemStack stack) { ++ // CraftBukkit start ++ return addItem(entity, state, level, pos, stack, level.getRandom().nextDouble()); ++ } ++ ++ static IBlockData addItem(@Nullable Entity entity, IBlockData iblockdata, LevelAccessor generatoraccess, BlockPos blockposition, ItemStack itemstack, double rand) { ++ // CraftBukkit end ++ int i = (Integer) iblockdata.getValue(ComposterBlock.LEVEL); ++ float f = ComposterBlock.COMPOSTABLES.getFloat(itemstack.getItem()); ++ ++ if ((i != 0 || f <= 0.0F) && rand >= (double) f) { ++ return iblockdata; + } else { +- int i1 = i + 1; +- BlockState blockState = state.setValue(LEVEL, Integer.valueOf(i1)); +- level.setBlock(pos, blockState, 3); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, blockState)); +- if (i1 == 7) { +- level.scheduleTick(pos, state.getBlock(), 20); ++ int j = i + 1; ++ IBlockData iblockdata1 = (IBlockData) iblockdata.setValue(ComposterBlock.LEVEL, j); ++ ++ generatoraccess.setBlock(blockposition, iblockdata1, 3); ++ generatoraccess.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entity, iblockdata1)); ++ if (j == 7) { ++ generatoraccess.scheduleTick(blockposition, iblockdata.getBlock(), 20); + } + +- return blockState; ++ return iblockdata1; + } + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- if (state.getValue(LEVEL) == 7) { +- level.setBlock(pos, state.cycle(LEVEL), 3); +- level.playSound(null, pos, SoundEvents.COMPOSTER_READY, SoundSource.BLOCKS, 1.0F, 1.0F); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Integer) state.getValue(ComposterBlock.LEVEL) == 7) { ++ level.setBlock(pos, (IBlockData) state.cycle(ComposterBlock.LEVEL), 3); ++ level.playSound((Player) null, pos, SoundEvents.COMPOSTER_READY, SoundSource.BLOCKS, 1.0F, 1.0F); + } ++ + } + + @Override +- public boolean hasAnalogOutputSignal(BlockState state) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return true; + } + + @Override +- public int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) { +- return blockState.getValue(LEVEL); ++ public int getAnalogOutputSignal(IBlockData blockState, Level level, BlockPos pos) { ++ return (Integer) blockState.getValue(ComposterBlock.LEVEL); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(LEVEL); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(ComposterBlock.LEVEL); + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + + @Override +- public WorldlyContainer getContainer(BlockState state, LevelAccessor level, BlockPos pos) { +- int i = state.getValue(LEVEL); +- if (i == 8) { +- return new ComposterBlock.OutputContainer(state, level, pos, new ItemStack(Items.BONE_MEAL)); +- } else { +- return (WorldlyContainer)(i < 7 ? new ComposterBlock.InputContainer(state, level, pos) : new ComposterBlock.EmptyContainer()); +- } ++ public WorldlyContainer getContainer(IBlockData state, LevelAccessor level, BlockPos pos) { ++ int i = (Integer) state.getValue(ComposterBlock.LEVEL); ++ ++ // CraftBukkit - empty generatoraccess, blockposition ++ return (WorldlyContainer) (i == 8 ? new ComposterBlock.OutputContainer(state, level, pos, new ItemStack(Items.BONE_MEAL)) : (i < 7 ? new ComposterBlock.InputContainer(state, level, pos) : new ComposterBlock.EmptyContainer(level, pos))); + } + +- static class EmptyContainer extends SimpleContainer implements WorldlyContainer { +- public EmptyContainer() { +- super(0); ++ public static class OutputContainer extends SimpleContainer implements WorldlyContainer { ++ ++ private final IBlockData state; ++ private final LevelAccessor level; ++ private final BlockPos pos; ++ private boolean changed; ++ ++ public OutputContainer(IBlockData state, LevelAccessor level, BlockPos pos, ItemStack stack) { ++ super(stack); ++ this.state = state; ++ this.level = level; ++ this.pos = pos; ++ this.bukkitOwner = new CraftBlockInventoryHolder(level, pos, this); // CraftBukkit + } + + @Override ++ public int getMaxStackSize() { ++ return 1; ++ } ++ ++ @Override + public int[] getSlotsForFace(Direction side) { +- return new int[0]; ++ return side == Direction.DOWN ? new int[]{0} : new int[0]; + } + + @Override +@@ -355,18 +401,33 @@ + + @Override + public boolean canTakeItemThroughFace(int index, ItemStack stack, Direction direction) { +- return false; ++ return !this.changed && direction == Direction.DOWN && stack.is(Items.BONE_MEAL); + } ++ ++ @Override ++ public void setChanged() { ++ // CraftBukkit start - allow putting items back (eg cancelled InventoryMoveItemEvent) ++ if (this.isEmpty()) { ++ ComposterBlock.empty((Entity) null, this.state, this.level, this.pos); ++ this.changed = true; ++ } else { ++ this.level.setBlock(this.pos, this.state, 3); ++ this.changed = false; ++ } ++ // CraftBukkit end ++ } + } + +- static class InputContainer extends SimpleContainer implements WorldlyContainer { +- private final BlockState state; ++ public static class InputContainer extends SimpleContainer implements WorldlyContainer { ++ ++ private final IBlockData state; + private final LevelAccessor level; + private final BlockPos pos; + private boolean changed; + +- public InputContainer(BlockState state, LevelAccessor level, BlockPos pos) { ++ public InputContainer(IBlockData state, LevelAccessor level, BlockPos pos) { + super(1); ++ this.bukkitOwner = new CraftBlockInventoryHolder(level, pos, this); // CraftBukkit + this.state = state; + this.level = level; + this.pos = pos; +@@ -394,37 +455,29 @@ + + @Override + public void setChanged() { +- ItemStack item = this.getItem(0); +- if (!item.isEmpty()) { ++ ItemStack itemstack = this.getItem(0); ++ ++ if (!itemstack.isEmpty()) { + this.changed = true; +- BlockState blockState = ComposterBlock.addItem(null, this.state, this.level, this.pos, item); +- this.level.levelEvent(1500, this.pos, blockState != this.state ? 1 : 0); ++ IBlockData iblockdata = ComposterBlock.addItem((Entity) null, this.state, this.level, this.pos, itemstack); ++ ++ this.level.levelEvent(1500, this.pos, iblockdata != this.state ? 1 : 0); + this.removeItemNoUpdate(0); + } ++ + } + } + +- static class OutputContainer extends SimpleContainer implements WorldlyContainer { +- private final BlockState state; +- private final LevelAccessor level; +- private final BlockPos pos; +- private boolean changed; ++ public static class EmptyContainer extends SimpleContainer implements WorldlyContainer { + +- public OutputContainer(BlockState state, LevelAccessor level, BlockPos pos, ItemStack stack) { +- super(stack); +- this.state = state; +- this.level = level; +- this.pos = pos; ++ public EmptyContainer(LevelAccessor generatoraccess, BlockPos blockposition) { // CraftBukkit ++ super(0); ++ this.bukkitOwner = new CraftBlockInventoryHolder(generatoraccess, blockposition, this); // CraftBukkit + } + + @Override +- public int getMaxStackSize() { +- return 1; +- } +- +- @Override + public int[] getSlotsForFace(Direction side) { +- return side == Direction.DOWN ? new int[]{0} : new int[0]; ++ return new int[0]; + } + + @Override +@@ -434,13 +487,7 @@ + + @Override + public boolean canTakeItemThroughFace(int index, ItemStack stack, Direction direction) { +- return !this.changed && direction == Direction.DOWN && stack.is(Items.BONE_MEAL); ++ return false; + } +- +- @Override +- public void setChanged() { +- ComposterBlock.empty(null, this.state, this.level, this.pos); +- this.changed = true; +- } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/ConcretePowderBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/ConcretePowderBlock.java.patch new file mode 100644 index 0000000000..2817e3b096 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/ConcretePowderBlock.java.patch @@ -0,0 +1,160 @@ +--- a/net/minecraft/world/level/block/ConcretePowderBlock.java ++++ b/net/minecraft/world/level/block/ConcretePowderBlock.java +@@ -2,7 +2,6 @@ + + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.core.registries.BuiltInRegistries; +@@ -13,20 +12,26 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.block.CraftBlockStates; ++import org.bukkit.event.block.BlockFormEvent; ++// CraftBukkit end ++ + public class ConcretePowderBlock extends FallingBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group( +- BuiltInRegistries.BLOCK.byNameCodec().fieldOf("concrete").forGetter(concretePowderBlock -> concretePowderBlock.concrete), propertiesCodec() +- ) +- .apply(instance, ConcretePowderBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(BuiltInRegistries.BLOCK.byNameCodec().fieldOf("concrete").forGetter((blockconcretepowder) -> { ++ return blockconcretepowder.concrete; ++ }), propertiesCodec()).apply(instance, ConcretePowderBlock::new); ++ }); + private final Block concrete; + + @Override + public MapCodec codec() { +- return CODEC; ++ return ConcretePowderBlock.CODEC; + } + + public ConcretePowderBlock(Block concrete, BlockBehaviour.Properties properties) { +@@ -35,34 +40,57 @@ + } + + @Override +- public void onLand(Level level, BlockPos pos, BlockState state, BlockState replaceableState, FallingBlockEntity fallingBlock) { ++ public void onLand(Level level, BlockPos pos, IBlockData state, IBlockData replaceableState, FallingBlockEntity fallingBlock) { + if (shouldSolidify(level, pos, replaceableState)) { +- level.setBlock(pos, this.concrete.defaultBlockState(), 3); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, this.concrete.defaultBlockState(), 3); // CraftBukkit + } ++ + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- BlockGetter level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- BlockState blockState = level.getBlockState(clickedPos); +- return shouldSolidify(level, clickedPos, blockState) ? this.concrete.defaultBlockState() : super.getStateForPlacement(context); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ ++ // CraftBukkit start ++ if (!shouldSolidify(world, blockposition, iblockdata)) { ++ return super.getStateForPlacement(context); ++ } ++ ++ // TODO: An event factory call for methods like this ++ CraftBlockState blockState = CraftBlockStates.getBlockState(world, blockposition); ++ blockState.setData(this.concrete.defaultBlockState()); ++ ++ BlockFormEvent event = new BlockFormEvent(blockState.getBlock(), blockState); ++ world.getServer().server.getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ return blockState.getHandle(); ++ } ++ ++ return super.getStateForPlacement(context); ++ // CraftBukkit end + } + +- private static boolean shouldSolidify(BlockGetter level, BlockPos pos, BlockState state) { ++ private static boolean shouldSolidify(BlockGetter level, BlockPos pos, IBlockData state) { + return canSolidify(state) || touchesLiquid(level, pos); + } + + private static boolean touchesLiquid(BlockGetter level, BlockPos pos) { + boolean flag = false; +- BlockPos.MutableBlockPos mutableBlockPos = pos.mutable(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; + +- for (Direction direction : Direction.values()) { +- BlockState blockState = level.getBlockState(mutableBlockPos); +- if (direction != Direction.DOWN || canSolidify(blockState)) { +- mutableBlockPos.setWithOffset(pos, direction); +- blockState = level.getBlockState(mutableBlockPos); +- if (canSolidify(blockState) && !blockState.isFaceSturdy(level, pos, direction.getOpposite())) { ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ IBlockData iblockdata = level.getBlockState(blockposition_mutableblockposition); ++ ++ if (enumdirection != Direction.DOWN || canSolidify(iblockdata)) { ++ blockposition_mutableblockposition.setWithOffset(pos, enumdirection); ++ iblockdata = level.getBlockState(blockposition_mutableblockposition); ++ if (canSolidify(iblockdata) && !iblockdata.isFaceSturdy(level, pos, enumdirection.getOpposite())) { + flag = true; + break; + } +@@ -72,19 +100,35 @@ + return flag; + } + +- private static boolean canSolidify(BlockState state) { ++ private static boolean canSolidify(IBlockData state) { + return state.getFluidState().is(FluidTags.WATER); + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- return touchesLiquid(level, currentPos) +- ? this.concrete.defaultBlockState() +- : super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ // CraftBukkit start ++ if (touchesLiquid(level, currentPos)) { ++ // Suppress during worldgen ++ if (!(level instanceof Level)) { ++ return this.concrete.defaultBlockState(); ++ } ++ CraftBlockState blockState = CraftBlockStates.getBlockState(level, currentPos); ++ blockState.setData(this.concrete.defaultBlockState()); ++ ++ BlockFormEvent event = new BlockFormEvent(blockState.getBlock(), blockState); ++ ((Level) level).getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ return blockState.getHandle(); ++ } ++ } ++ ++ return super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ // CraftBukkit end + } + + @Override +- public int getDustColor(BlockState state, BlockGetter reader, BlockPos pos) { ++ public int getDustColor(IBlockData state, BlockGetter reader, BlockPos pos) { + return state.getMapColor(reader, pos).col; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/CoralBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CoralBlock.java.patch new file mode 100644 index 0000000000..efc9a53cc4 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CoralBlock.java.patch @@ -0,0 +1,92 @@ +--- a/net/minecraft/world/level/block/CoralBlock.java ++++ b/net/minecraft/world/level/block/CoralBlock.java +@@ -2,7 +2,6 @@ + + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +@@ -14,14 +13,17 @@ + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; + + public class CoralBlock extends Block { ++ + public static final MapCodec DEAD_CORAL_FIELD = BuiltInRegistries.BLOCK.byNameCodec().fieldOf("dead"); +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group(DEAD_CORAL_FIELD.forGetter(coralBlock -> coralBlock.deadBlock), propertiesCodec()).apply(instance, CoralBlock::new) +- ); ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(CoralBlock.DEAD_CORAL_FIELD.forGetter((blockcoral) -> { ++ return blockcoral.deadBlock; ++ }), propertiesCodec()).apply(instance, CoralBlock::new); ++ }); + private final Block deadBlock; + + public CoralBlock(Block deadBlock, BlockBehaviour.Properties properties) { +@@ -31,29 +33,40 @@ + + @Override + public MapCodec codec() { +- return CODEC; ++ return CoralBlock.CODEC; + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (!this.scanForWater(level, pos)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, this.deadBlock.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + level.setBlock(pos, this.deadBlock.defaultBlockState(), 2); + } ++ + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { + if (!this.scanForWater(level, currentPos)) { +- level.scheduleTick(currentPos, this, 60 + level.getRandom().nextInt(40)); ++ level.scheduleTick(currentPos, (Block) this, 60 + level.getRandom().nextInt(40)); + } + + return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + protected boolean scanForWater(BlockGetter level, BlockPos pos) { +- for (Direction direction : Direction.values()) { +- FluidState fluidState = level.getFluidState(pos.relative(direction)); +- if (fluidState.is(FluidTags.WATER)) { ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; ++ ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ FluidState fluid = level.getFluidState(pos.relative(enumdirection)); ++ ++ if (fluid.is(FluidTags.WATER)) { + return true; + } + } +@@ -63,9 +76,9 @@ + + @Nullable + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { + if (!this.scanForWater(context.getLevel(), context.getClickedPos())) { +- context.getLevel().scheduleTick(context.getClickedPos(), this, 60 + context.getLevel().getRandom().nextInt(40)); ++ context.getLevel().scheduleTick(context.getClickedPos(), (Block) this, 60 + context.getLevel().getRandom().nextInt(40)); + } + + return this.defaultBlockState(); diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/CoralFanBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CoralFanBlock.java.patch new file mode 100644 index 0000000000..43ca62db5e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CoralFanBlock.java.patch @@ -0,0 +1,77 @@ +--- a/net/minecraft/world/level/block/CoralFanBlock.java ++++ b/net/minecraft/world/level/block/CoralFanBlock.java +@@ -2,7 +2,6 @@ + + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.server.level.ServerLevel; +@@ -10,19 +9,22 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; + + public class CoralFanBlock extends BaseCoralFanBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group(CoralBlock.DEAD_CORAL_FIELD.forGetter(coralFanBlock -> coralFanBlock.deadBlock), propertiesCodec()) +- .apply(instance, CoralFanBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(CoralBlock.DEAD_CORAL_FIELD.forGetter((blockcoralfan) -> { ++ return blockcoralfan.deadBlock; ++ }), propertiesCodec()).apply(instance, CoralFanBlock::new); ++ }); + private final Block deadBlock; + + @Override + public MapCodec codec() { +- return CODEC; ++ return CoralFanBlock.CODEC; + } + + protected CoralFanBlock(Block deadBlock, BlockBehaviour.Properties properties) { +@@ -31,25 +33,31 @@ + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { + this.tryScheduleDieTick(state, level, pos); + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (!scanForWater(state, level, pos)) { +- level.setBlock(pos, this.deadBlock.defaultBlockState().setValue(WATERLOGGED, Boolean.valueOf(false)), 2); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, this.deadBlock.defaultBlockState().setValue(CoralFanBlock.WATERLOGGED, false)).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) this.deadBlock.defaultBlockState().setValue(CoralFanBlock.WATERLOGGED, false), 2); + } ++ + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { + if (facing == Direction.DOWN && !state.canSurvive(level, currentPos)) { + return Blocks.AIR.defaultBlockState(); + } else { + this.tryScheduleDieTick(state, level, currentPos); +- if (state.getValue(WATERLOGGED)) { +- level.scheduleTick(currentPos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); ++ if ((Boolean) state.getValue(CoralFanBlock.WATERLOGGED)) { ++ level.scheduleTick(currentPos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + + return super.updateShape(state, facing, facingState, level, currentPos, facingPos); diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/CoralPlantBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CoralPlantBlock.java.patch new file mode 100644 index 0000000000..e6f2d22584 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CoralPlantBlock.java.patch @@ -0,0 +1,92 @@ +--- a/net/minecraft/world/level/block/CoralPlantBlock.java ++++ b/net/minecraft/world/level/block/CoralPlantBlock.java +@@ -2,7 +2,6 @@ + + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.server.level.ServerLevel; +@@ -11,23 +10,26 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; + + public class CoralPlantBlock extends BaseCoralPlantTypeBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group(CoralBlock.DEAD_CORAL_FIELD.forGetter(coralPlantBlock -> coralPlantBlock.deadBlock), propertiesCodec()) +- .apply(instance, CoralPlantBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(CoralBlock.DEAD_CORAL_FIELD.forGetter((blockcoralplant) -> { ++ return blockcoralplant.deadBlock; ++ }), propertiesCodec()).apply(instance, CoralPlantBlock::new); ++ }); + private final Block deadBlock; + protected static final float AABB_OFFSET = 6.0F; +- protected static final VoxelShape SHAPE = Block.box(2.0, 0.0, 2.0, 14.0, 15.0, 14.0); ++ protected static final VoxelShape SHAPE = Block.box(2.0D, 0.0D, 2.0D, 14.0D, 15.0D, 14.0D); + + @Override + public MapCodec codec() { +- return CODEC; ++ return CoralPlantBlock.CODEC; + } + + protected CoralPlantBlock(Block deadBlock, BlockBehaviour.Properties properties) { +@@ -36,25 +38,31 @@ + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { + this.tryScheduleDieTick(state, level, pos); + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (!scanForWater(state, level, pos)) { +- level.setBlock(pos, this.deadBlock.defaultBlockState().setValue(WATERLOGGED, Boolean.valueOf(false)), 2); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, this.deadBlock.defaultBlockState().setValue(CoralPlantBlock.WATERLOGGED, false)).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) this.deadBlock.defaultBlockState().setValue(CoralPlantBlock.WATERLOGGED, false), 2); + } ++ + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { + if (facing == Direction.DOWN && !state.canSurvive(level, currentPos)) { + return Blocks.AIR.defaultBlockState(); + } else { + this.tryScheduleDieTick(state, level, currentPos); +- if (state.getValue(WATERLOGGED)) { +- level.scheduleTick(currentPos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); ++ if ((Boolean) state.getValue(CoralPlantBlock.WATERLOGGED)) { ++ level.scheduleTick(currentPos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + + return super.updateShape(state, facing, facingState, level, currentPos, facingPos); +@@ -62,7 +70,7 @@ + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPE; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return CoralPlantBlock.SHAPE; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/CoralWallFanBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CoralWallFanBlock.java.patch new file mode 100644 index 0000000000..5243270877 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CoralWallFanBlock.java.patch @@ -0,0 +1,77 @@ +--- a/net/minecraft/world/level/block/CoralWallFanBlock.java ++++ b/net/minecraft/world/level/block/CoralWallFanBlock.java +@@ -2,7 +2,6 @@ + + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.server.level.ServerLevel; +@@ -10,19 +9,22 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; + + public class CoralWallFanBlock extends BaseCoralWallFanBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group(CoralBlock.DEAD_CORAL_FIELD.forGetter(coralWallFanBlock -> coralWallFanBlock.deadBlock), propertiesCodec()) +- .apply(instance, CoralWallFanBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(CoralBlock.DEAD_CORAL_FIELD.forGetter((blockcoralfanwall) -> { ++ return blockcoralfanwall.deadBlock; ++ }), propertiesCodec()).apply(instance, CoralWallFanBlock::new); ++ }); + private final Block deadBlock; + + @Override + public MapCodec codec() { +- return CODEC; ++ return CoralWallFanBlock.CODEC; + } + + protected CoralWallFanBlock(Block deadBlock, BlockBehaviour.Properties properties) { +@@ -31,24 +33,30 @@ + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { + this.tryScheduleDieTick(state, level, pos); + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (!scanForWater(state, level, pos)) { +- level.setBlock(pos, this.deadBlock.defaultBlockState().setValue(WATERLOGGED, Boolean.valueOf(false)).setValue(FACING, state.getValue(FACING)), 2); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, this.deadBlock.defaultBlockState().setValue(CoralWallFanBlock.WATERLOGGED, false).setValue(CoralWallFanBlock.FACING, state.getValue(CoralWallFanBlock.FACING))).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) ((IBlockData) this.deadBlock.defaultBlockState().setValue(CoralWallFanBlock.WATERLOGGED, false)).setValue(CoralWallFanBlock.FACING, (Direction) state.getValue(CoralWallFanBlock.FACING)), 2); + } ++ + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- if (facing.getOpposite() == state.getValue(FACING) && !state.canSurvive(level, currentPos)) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if (facing.getOpposite() == state.getValue(CoralWallFanBlock.FACING) && !state.canSurvive(level, currentPos)) { + return Blocks.AIR.defaultBlockState(); + } else { +- if (state.getValue(WATERLOGGED)) { +- level.scheduleTick(currentPos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); ++ if ((Boolean) state.getValue(CoralWallFanBlock.WATERLOGGED)) { ++ level.scheduleTick(currentPos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + + this.tryScheduleDieTick(state, level, currentPos); diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/CropBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CropBlock.java.patch new file mode 100644 index 0000000000..83c3a312b4 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/CropBlock.java.patch @@ -0,0 +1,254 @@ +--- a/net/minecraft/world/level/block/CropBlock.java ++++ b/net/minecraft/world/level/block/CropBlock.java +@@ -11,98 +11,95 @@ + import net.minecraft.world.item.Items; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.GameRules; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class CropBlock extends BushBlock implements BonemealableBlock { ++ + public static final MapCodec CODEC = simpleCodec(CropBlock::new); + public static final int MAX_AGE = 7; + public static final IntegerProperty AGE = BlockStateProperties.AGE_7; +- private static final VoxelShape[] SHAPE_BY_AGE = new VoxelShape[]{ +- Block.box(0.0, 0.0, 0.0, 16.0, 2.0, 16.0), +- Block.box(0.0, 0.0, 0.0, 16.0, 4.0, 16.0), +- Block.box(0.0, 0.0, 0.0, 16.0, 6.0, 16.0), +- Block.box(0.0, 0.0, 0.0, 16.0, 8.0, 16.0), +- Block.box(0.0, 0.0, 0.0, 16.0, 10.0, 16.0), +- Block.box(0.0, 0.0, 0.0, 16.0, 12.0, 16.0), +- Block.box(0.0, 0.0, 0.0, 16.0, 14.0, 16.0), +- Block.box(0.0, 0.0, 0.0, 16.0, 16.0, 16.0) +- }; ++ private static final VoxelShape[] SHAPE_BY_AGE = new VoxelShape[]{Block.box(0.0D, 0.0D, 0.0D, 16.0D, 2.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 4.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 6.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 8.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 10.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 12.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 14.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 16.0D, 16.0D)}; + + @Override + public MapCodec codec() { +- return CODEC; ++ return CropBlock.CODEC; + } + + protected CropBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(this.getAgeProperty(), Integer.valueOf(0))); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(this.getAgeProperty(), 0)); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPE_BY_AGE[this.getAge(state)]; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return CropBlock.SHAPE_BY_AGE[this.getAge(state)]; + } + + @Override +- protected boolean mayPlaceOn(BlockState state, BlockGetter level, BlockPos pos) { ++ protected boolean mayPlaceOn(IBlockData state, BlockGetter level, BlockPos pos) { + return state.is(Blocks.FARMLAND); + } + + protected IntegerProperty getAgeProperty() { +- return AGE; ++ return CropBlock.AGE; + } + + public int getMaxAge() { + return 7; + } + +- public int getAge(BlockState state) { +- return state.getValue(this.getAgeProperty()); ++ public int getAge(IBlockData state) { ++ return (Integer) state.getValue(this.getAgeProperty()); + } + +- public BlockState getStateForAge(int age) { +- return this.defaultBlockState().setValue(this.getAgeProperty(), Integer.valueOf(age)); ++ public IBlockData getStateForAge(int age) { ++ return (IBlockData) this.defaultBlockState().setValue(this.getAgeProperty(), age); + } + +- public final boolean isMaxAge(BlockState state) { ++ public final boolean isMaxAge(IBlockData state) { + return this.getAge(state) >= this.getMaxAge(); + } + + @Override +- public boolean isRandomlyTicking(BlockState state) { ++ public boolean isRandomlyTicking(IBlockData state) { + return !this.isMaxAge(state); + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (level.getRawBrightness(pos, 0) >= 9) { +- int age = this.getAge(state); +- if (age < this.getMaxAge()) { +- float growthSpeed = getGrowthSpeed(this, level, pos); +- if (random.nextInt((int)(25.0F / growthSpeed) + 1) == 0) { +- level.setBlock(pos, this.getStateForAge(age + 1), 2); ++ int i = this.getAge(state); ++ ++ if (i < this.getMaxAge()) { ++ float f = getGrowthSpeed(this, level, pos); ++ ++ if (random.nextInt((int) (25.0F / f) + 1) == 0) { ++ CraftEventFactory.handleBlockGrowEvent(level, pos, this.getStateForAge(i + 1), 2); // CraftBukkit + } + } + } ++ + } + +- public void growCrops(Level level, BlockPos pos, BlockState state) { ++ public void growCrops(Level level, BlockPos pos, IBlockData state) { + int i = this.getAge(state) + this.getBonemealAgeIncrease(level); +- int maxAge = this.getMaxAge(); +- if (i > maxAge) { +- i = maxAge; ++ int j = this.getMaxAge(); ++ ++ if (i > j) { ++ i = j; + } + +- level.setBlock(pos, this.getStateForAge(i), 2); ++ CraftEventFactory.handleBlockGrowEvent(level, pos, this.getStateForAge(i), 2); // CraftBukkit + } + + protected int getBonemealAgeIncrease(Level level) { +@@ -111,20 +108,21 @@ + + protected static float getGrowthSpeed(Block block, BlockGetter level, BlockPos pos) { + float f = 1.0F; +- BlockPos blockPos = pos.below(); ++ BlockPos blockposition1 = pos.below(); + +- for (int i = -1; i <= 1; i++) { +- for (int i1 = -1; i1 <= 1; i1++) { ++ for (int i = -1; i <= 1; ++i) { ++ for (int j = -1; j <= 1; ++j) { + float f1 = 0.0F; +- BlockState blockState = level.getBlockState(blockPos.offset(i, 0, i1)); +- if (blockState.is(Blocks.FARMLAND)) { ++ IBlockData iblockdata = level.getBlockState(blockposition1.offset(i, 0, j)); ++ ++ if (iblockdata.is(Blocks.FARMLAND)) { + f1 = 1.0F; +- if (blockState.getValue(FarmBlock.MOISTURE) > 0) { ++ if ((Integer) iblockdata.getValue(FarmBlock.MOISTURE) > 0) { + f1 = 3.0F; + } + } + +- if (i != 0 || i1 != 0) { ++ if (i != 0 || j != 0) { + f1 /= 4.0F; + } + +@@ -132,19 +130,18 @@ + } + } + +- BlockPos blockPos1 = pos.north(); +- BlockPos blockPos2 = pos.south(); +- BlockPos blockPos3 = pos.west(); +- BlockPos blockPos4 = pos.east(); +- boolean flag = level.getBlockState(blockPos3).is(block) || level.getBlockState(blockPos4).is(block); +- boolean flag1 = level.getBlockState(blockPos1).is(block) || level.getBlockState(blockPos2).is(block); ++ BlockPos blockposition2 = pos.north(); ++ BlockPos blockposition3 = pos.south(); ++ BlockPos blockposition4 = pos.west(); ++ BlockPos blockposition5 = pos.east(); ++ boolean flag = level.getBlockState(blockposition4).is(block) || level.getBlockState(blockposition5).is(block); ++ boolean flag1 = level.getBlockState(blockposition2).is(block) || level.getBlockState(blockposition3).is(block); ++ + if (flag && flag1) { + f /= 2.0F; + } else { +- boolean flag2 = level.getBlockState(blockPos3.north()).is(block) +- || level.getBlockState(blockPos4.north()).is(block) +- || level.getBlockState(blockPos4.south()).is(block) +- || level.getBlockState(blockPos3.south()).is(block); ++ boolean flag2 = level.getBlockState(blockposition4.north()).is(block) || level.getBlockState(blockposition5.north()).is(block) || level.getBlockState(blockposition5.south()).is(block) || level.getBlockState(blockposition4.south()).is(block); ++ + if (flag2) { + f /= 2.0F; + } +@@ -154,49 +151,49 @@ + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { + return hasSufficientLight(level, pos) && super.canSurvive(state, level, pos); + } + +- protected static boolean hasSufficientLight(LevelReader levelReader, BlockPos blockPos) { +- return levelReader.getRawBrightness(blockPos, 0) >= 8; ++ protected static boolean hasSufficientLight(LevelReader iworldreader, BlockPos blockposition) { ++ return iworldreader.getRawBrightness(blockposition, 0) >= 8; + } + + @Override +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { +- if (entity instanceof Ravager && level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ if (entity instanceof Ravager && CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit + level.destroyBlock(pos, true, entity); + } + + super.entityInside(state, level, pos, entity); + } + +- protected ItemLike getBaseSeedId() { ++ protected IMaterial getBaseSeedId() { + return Items.WHEAT_SEEDS; + } + + @Override +- public ItemStack getCloneItemStack(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { ++ public ItemStack getCloneItemStack(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { + return new ItemStack(this.getBaseSeedId()); + } + + @Override +- public boolean isValidBonemealTarget(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { +- return !this.isMaxAge(blockState); ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ return !this.isMaxAge(iblockdata); + } + + @Override +- public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, BlockState state) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return true; + } + + @Override +- public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) { ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { + this.growCrops(level, pos, state); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(AGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(CropBlock.AGE); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/DaylightDetectorBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/DaylightDetectorBlock.java.patch new file mode 100644 index 0000000000..25e7fd1b47 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/DaylightDetectorBlock.java.patch @@ -0,0 +1,165 @@ +--- a/net/minecraft/world/level/block/DaylightDetectorBlock.java ++++ b/net/minecraft/world/level/block/DaylightDetectorBlock.java +@@ -5,18 +5,18 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.BlockGetter; ++import net.minecraft.world.level.EnumSkyBlock; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BlockEntityTicker; + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.DaylightDetectorBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -27,64 +27,70 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + + public class DaylightDetectorBlock extends BaseEntityBlock { ++ + public static final MapCodec CODEC = simpleCodec(DaylightDetectorBlock::new); + public static final IntegerProperty POWER = BlockStateProperties.POWER; + public static final BooleanProperty INVERTED = BlockStateProperties.INVERTED; +- protected static final VoxelShape SHAPE = Block.box(0.0, 0.0, 0.0, 16.0, 6.0, 16.0); ++ protected static final VoxelShape SHAPE = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 6.0D, 16.0D); + + @Override + public MapCodec codec() { +- return CODEC; ++ return DaylightDetectorBlock.CODEC; + } + + public DaylightDetectorBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(POWER, Integer.valueOf(0)).setValue(INVERTED, Boolean.valueOf(false))); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(DaylightDetectorBlock.POWER, 0)).setValue(DaylightDetectorBlock.INVERTED, false)); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPE; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return DaylightDetectorBlock.SHAPE; + } + + @Override +- public boolean useShapeForLightOcclusion(BlockState state) { ++ public boolean useShapeForLightOcclusion(IBlockData state) { + return true; + } + + @Override +- public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { +- return blockState.getValue(POWER); ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return (Integer) blockState.getValue(DaylightDetectorBlock.POWER); + } + +- private static void updateSignalStrength(BlockState state, Level level, BlockPos pos) { +- int i = level.getBrightness(LightLayer.SKY, pos) - level.getSkyDarken(); +- float sunAngle = level.getSunAngle(1.0F); +- boolean flag = state.getValue(INVERTED); ++ private static void updateSignalStrength(IBlockData state, Level level, BlockPos pos) { ++ int i = level.getBrightness(EnumSkyBlock.SKY, pos) - level.getSkyDarken(); ++ float f = level.getSunAngle(1.0F); ++ boolean flag = (Boolean) state.getValue(DaylightDetectorBlock.INVERTED); ++ + if (flag) { + i = 15 - i; + } else if (i > 0) { +- float f = sunAngle < (float) Math.PI ? 0.0F : (float) (Math.PI * 2); +- sunAngle += (f - sunAngle) * 0.2F; +- i = Math.round((float)i * Mth.cos(sunAngle)); ++ float f1 = f < 3.1415927F ? 0.0F : 6.2831855F; ++ ++ f += (f1 - f) * 0.2F; ++ i = Math.round((float) i * Mth.cos(f)); + } + +- int var7 = Mth.clamp(i, 0, 15); +- if (state.getValue(POWER) != var7) { +- level.setBlock(pos, state.setValue(POWER, Integer.valueOf(var7)), 3); ++ i = Mth.clamp(i, 0, 15); ++ if ((Integer) state.getValue(DaylightDetectorBlock.POWER) != i) { ++ i = org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(level, pos, ((Integer) state.getValue(POWER)), i).getNewCurrent(); // CraftBukkit - Call BlockRedstoneEvent ++ level.setBlock(pos, (IBlockData) state.setValue(DaylightDetectorBlock.POWER, i), 3); + } ++ + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + if (player.mayBuild()) { + if (level.isClientSide) { + return InteractionResult.SUCCESS; + } else { +- BlockState blockState = state.cycle(INVERTED); +- level.setBlock(pos, blockState, 2); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(player, blockState)); +- updateSignalStrength(blockState, level, pos); ++ IBlockData iblockdata1 = (IBlockData) state.cycle(DaylightDetectorBlock.INVERTED); ++ ++ level.setBlock(pos, iblockdata1, 2); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(player, iblockdata1)); ++ updateSignalStrength(iblockdata1, level, pos); + return InteractionResult.CONSUME; + } + } else { +@@ -93,36 +99,35 @@ + } + + @Override +- public RenderShape getRenderShape(BlockState state) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Override +- public boolean isSignalSource(BlockState state) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + + @Override +- public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { + return new DaylightDetectorBlockEntity(pos, state); + } + + @Nullable + @Override +- public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { +- return !level.isClientSide && level.dimensionType().hasSkyLight() +- ? createTickerHelper(blockEntityType, BlockEntityType.DAYLIGHT_DETECTOR, DaylightDetectorBlock::tickEntity) +- : null; ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { ++ return !level.isClientSide && level.dimensionType().hasSkyLight() ? createTickerHelper(blockEntityType, BlockEntityType.DAYLIGHT_DETECTOR, DaylightDetectorBlock::tickEntity) : null; + } + +- private static void tickEntity(Level level, BlockPos pos, BlockState state, DaylightDetectorBlockEntity blockEntity) { ++ private static void tickEntity(Level level, BlockPos pos, IBlockData state, DaylightDetectorBlockEntity blockEntity) { + if (level.getGameTime() % 20L == 0L) { + updateSignalStrength(state, level, pos); + } ++ + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(POWER, INVERTED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(DaylightDetectorBlock.POWER, DaylightDetectorBlock.INVERTED); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/DetectorRailBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/DetectorRailBlock.java.patch new file mode 100644 index 0000000000..bbcf151ca5 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/DetectorRailBlock.java.patch @@ -0,0 +1,420 @@ +--- a/net/minecraft/world/level/block/DetectorRailBlock.java ++++ b/net/minecraft/world/level/block/DetectorRailBlock.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.block; + + import com.mojang.serialization.MapCodec; ++import java.util.Iterator; + import java.util.List; + import java.util.function.Predicate; + import net.minecraft.core.BlockPos; +@@ -16,7 +17,7 @@ + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -24,8 +25,10 @@ + import net.minecraft.world.level.block.state.properties.Property; + import net.minecraft.world.level.block.state.properties.RailShape; + import net.minecraft.world.phys.AABB; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class DetectorRailBlock extends BaseRailBlock { ++ + public static final MapCodec CODEC = simpleCodec(DetectorRailBlock::new); + public static final EnumProperty SHAPE = BlockStateProperties.RAIL_SHAPE_STRAIGHT; + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; +@@ -33,130 +36,143 @@ + + @Override + public MapCodec codec() { +- return CODEC; ++ return DetectorRailBlock.CODEC; + } + + public DetectorRailBlock(BlockBehaviour.Properties properties) { + super(true, properties); +- this.registerDefaultState( +- this.stateDefinition +- .any() +- .setValue(POWERED, Boolean.valueOf(false)) +- .setValue(SHAPE, RailShape.NORTH_SOUTH) +- .setValue(WATERLOGGED, Boolean.valueOf(false)) +- ); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(DetectorRailBlock.POWERED, false)).setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_SOUTH)).setValue(DetectorRailBlock.WATERLOGGED, false)); + } + + @Override +- public boolean isSignalSource(BlockState state) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + + @Override +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { + if (!level.isClientSide) { +- if (!state.getValue(POWERED)) { ++ if (!(Boolean) state.getValue(DetectorRailBlock.POWERED)) { + this.checkPressed(level, pos, state); + } + } + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- if (state.getValue(POWERED)) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(DetectorRailBlock.POWERED)) { + this.checkPressed(level, pos, state); + } + } + + @Override +- public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { +- return blockState.getValue(POWERED) ? 15 : 0; ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return (Boolean) blockState.getValue(DetectorRailBlock.POWERED) ? 15 : 0; + } + + @Override +- public int getDirectSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { +- if (!blockState.getValue(POWERED)) { +- return 0; +- } else { +- return side == Direction.UP ? 15 : 0; +- } ++ public int getDirectSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return !(Boolean) blockState.getValue(DetectorRailBlock.POWERED) ? 0 : (side == Direction.UP ? 15 : 0); + } + +- private void checkPressed(Level level, BlockPos pos, BlockState state) { ++ private void checkPressed(Level level, BlockPos pos, IBlockData state) { + if (this.canSurvive(state, level, pos)) { +- boolean flag = state.getValue(POWERED); ++ boolean flag = (Boolean) state.getValue(DetectorRailBlock.POWERED); + boolean flag1 = false; +- List interactingMinecartOfType = this.getInteractingMinecartOfType(level, pos, AbstractMinecart.class, entity -> true); +- if (!interactingMinecartOfType.isEmpty()) { ++ List list = this.getInteractingMinecartOfType(level, pos, AbstractMinecart.class, (entity) -> { ++ return true; ++ }); ++ ++ if (!list.isEmpty()) { + flag1 = true; + } + ++ IBlockData iblockdata1; ++ // CraftBukkit start ++ if (flag != flag1) { ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, flag ? 15 : 0, flag1 ? 15 : 0); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ flag1 = eventRedstone.getNewCurrent() > 0; ++ } ++ // CraftBukkit end ++ + if (flag1 && !flag) { +- BlockState blockState = state.setValue(POWERED, Boolean.valueOf(true)); +- level.setBlock(pos, blockState, 3); +- this.updatePowerToConnected(level, pos, blockState, true); ++ iblockdata1 = (IBlockData) state.setValue(DetectorRailBlock.POWERED, true); ++ level.setBlock(pos, iblockdata1, 3); ++ this.updatePowerToConnected(level, pos, iblockdata1, true); + level.updateNeighborsAt(pos, this); + level.updateNeighborsAt(pos.below(), this); +- level.setBlocksDirty(pos, state, blockState); ++ level.setBlocksDirty(pos, state, iblockdata1); + } + + if (!flag1 && flag) { +- BlockState blockState = state.setValue(POWERED, Boolean.valueOf(false)); +- level.setBlock(pos, blockState, 3); +- this.updatePowerToConnected(level, pos, blockState, false); ++ iblockdata1 = (IBlockData) state.setValue(DetectorRailBlock.POWERED, false); ++ level.setBlock(pos, iblockdata1, 3); ++ this.updatePowerToConnected(level, pos, iblockdata1, false); + level.updateNeighborsAt(pos, this); + level.updateNeighborsAt(pos.below(), this); +- level.setBlocksDirty(pos, state, blockState); ++ level.setBlocksDirty(pos, state, iblockdata1); + } + + if (flag1) { +- level.scheduleTick(pos, this, 20); ++ level.scheduleTick(pos, (Block) this, 20); + } + + level.updateNeighbourForOutputSignal(pos, this); + } + } + +- protected void updatePowerToConnected(Level level, BlockPos pos, BlockState state, boolean powered) { +- RailState railState = new RailState(level, pos, state); ++ protected void updatePowerToConnected(Level level, BlockPos pos, IBlockData state, boolean powered) { ++ RailState minecarttracklogic = new RailState(level, pos, state); ++ List list = minecarttracklogic.getConnections(); ++ Iterator iterator = list.iterator(); + +- for (BlockPos blockPos : railState.getConnections()) { +- BlockState blockState = level.getBlockState(blockPos); +- level.neighborChanged(blockState, blockPos, blockState.getBlock(), pos, false); ++ while (iterator.hasNext()) { ++ BlockPos blockposition1 = (BlockPos) iterator.next(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ level.neighborChanged(iblockdata1, blockposition1, iblockdata1.getBlock(), pos, false); + } ++ + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { + if (!oldState.is(state.getBlock())) { +- BlockState blockState = this.updateState(state, level, pos, isMoving); +- this.checkPressed(level, pos, blockState); ++ IBlockData iblockdata2 = this.updateState(state, level, pos, isMoving); ++ ++ this.checkPressed(level, pos, iblockdata2); + } + } + + @Override + public Property getShapeProperty() { +- return SHAPE; ++ return DetectorRailBlock.SHAPE; + } + + @Override +- public boolean hasAnalogOutputSignal(BlockState state) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return true; + } + + @Override +- public int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) { +- if (blockState.getValue(POWERED)) { +- List interactingMinecartOfType = this.getInteractingMinecartOfType(level, pos, MinecartCommandBlock.class, cartEntity -> true); +- if (!interactingMinecartOfType.isEmpty()) { +- return interactingMinecartOfType.get(0).getCommandBlock().getSuccessCount(); ++ public int getAnalogOutputSignal(IBlockData blockState, Level level, BlockPos pos) { ++ if ((Boolean) blockState.getValue(DetectorRailBlock.POWERED)) { ++ List list = this.getInteractingMinecartOfType(level, pos, MinecartCommandBlock.class, (entity) -> { ++ return true; ++ }); ++ ++ if (!list.isEmpty()) { ++ return ((MinecartCommandBlock) list.get(0)).getCommandBlock().getSuccessCount(); + } + +- List interactingMinecartOfType1 = this.getInteractingMinecartOfType( +- level, pos, AbstractMinecart.class, EntitySelector.CONTAINER_ENTITY_SELECTOR +- ); +- if (!interactingMinecartOfType1.isEmpty()) { +- return AbstractContainerMenu.getRedstoneSignalFromContainer((Container)interactingMinecartOfType1.get(0)); ++ List list1 = this.getInteractingMinecartOfType(level, pos, AbstractMinecart.class, EntitySelector.CONTAINER_ENTITY_SELECTOR); ++ ++ if (!list1.isEmpty()) { ++ return AbstractContainerMenu.getRedstoneSignalFromContainer((Container) list1.get(0)); + } + } + +@@ -168,84 +184,78 @@ + } + + private AABB getSearchBB(BlockPos pos) { +- double d = 0.2; +- return new AABB( +- (double)pos.getX() + 0.2, +- (double)pos.getY(), +- (double)pos.getZ() + 0.2, +- (double)(pos.getX() + 1) - 0.2, +- (double)(pos.getY() + 1) - 0.2, +- (double)(pos.getZ() + 1) - 0.2 +- ); ++ double d0 = 0.2D; ++ ++ return new AABB((double) pos.getX() + 0.2D, (double) pos.getY(), (double) pos.getZ() + 0.2D, (double) (pos.getX() + 1) - 0.2D, (double) (pos.getY() + 1) - 0.2D, (double) (pos.getZ() + 1) - 0.2D); + } + + @Override +- public BlockState rotate(BlockState state, Rotation rotation) { ++ public IBlockData rotate(IBlockData state, Rotation rotation) { + switch (rotation) { + case CLOCKWISE_180: +- switch ((RailShape)state.getValue(SHAPE)) { ++ switch ((RailShape) state.getValue(DetectorRailBlock.SHAPE)) { + case ASCENDING_EAST: +- return state.setValue(SHAPE, RailShape.ASCENDING_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_WEST); + case ASCENDING_WEST: +- return state.setValue(SHAPE, RailShape.ASCENDING_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_EAST); + case ASCENDING_NORTH: +- return state.setValue(SHAPE, RailShape.ASCENDING_SOUTH); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); + case ASCENDING_SOUTH: +- return state.setValue(SHAPE, RailShape.ASCENDING_NORTH); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_NORTH); + case SOUTH_EAST: +- return state.setValue(SHAPE, RailShape.NORTH_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_WEST); + case SOUTH_WEST: +- return state.setValue(SHAPE, RailShape.NORTH_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_EAST); + case NORTH_WEST: +- return state.setValue(SHAPE, RailShape.SOUTH_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_EAST); + case NORTH_EAST: +- return state.setValue(SHAPE, RailShape.SOUTH_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_WEST); + } + case COUNTERCLOCKWISE_90: +- switch ((RailShape)state.getValue(SHAPE)) { ++ switch ((RailShape) state.getValue(DetectorRailBlock.SHAPE)) { + case ASCENDING_EAST: +- return state.setValue(SHAPE, RailShape.ASCENDING_NORTH); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_NORTH); + case ASCENDING_WEST: +- return state.setValue(SHAPE, RailShape.ASCENDING_SOUTH); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); + case ASCENDING_NORTH: +- return state.setValue(SHAPE, RailShape.ASCENDING_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_WEST); + case ASCENDING_SOUTH: +- return state.setValue(SHAPE, RailShape.ASCENDING_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_EAST); + case SOUTH_EAST: +- return state.setValue(SHAPE, RailShape.NORTH_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_EAST); + case SOUTH_WEST: +- return state.setValue(SHAPE, RailShape.SOUTH_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_EAST); + case NORTH_WEST: +- return state.setValue(SHAPE, RailShape.SOUTH_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_WEST); + case NORTH_EAST: +- return state.setValue(SHAPE, RailShape.NORTH_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_WEST); + case NORTH_SOUTH: +- return state.setValue(SHAPE, RailShape.EAST_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.EAST_WEST); + case EAST_WEST: +- return state.setValue(SHAPE, RailShape.NORTH_SOUTH); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_SOUTH); + } + case CLOCKWISE_90: +- switch ((RailShape)state.getValue(SHAPE)) { ++ switch ((RailShape) state.getValue(DetectorRailBlock.SHAPE)) { + case ASCENDING_EAST: +- return state.setValue(SHAPE, RailShape.ASCENDING_SOUTH); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); + case ASCENDING_WEST: +- return state.setValue(SHAPE, RailShape.ASCENDING_NORTH); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_NORTH); + case ASCENDING_NORTH: +- return state.setValue(SHAPE, RailShape.ASCENDING_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_EAST); + case ASCENDING_SOUTH: +- return state.setValue(SHAPE, RailShape.ASCENDING_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_WEST); + case SOUTH_EAST: +- return state.setValue(SHAPE, RailShape.SOUTH_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_WEST); + case SOUTH_WEST: +- return state.setValue(SHAPE, RailShape.NORTH_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_WEST); + case NORTH_WEST: +- return state.setValue(SHAPE, RailShape.NORTH_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_EAST); + case NORTH_EAST: +- return state.setValue(SHAPE, RailShape.SOUTH_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_EAST); + case NORTH_SOUTH: +- return state.setValue(SHAPE, RailShape.EAST_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.EAST_WEST); + case EAST_WEST: +- return state.setValue(SHAPE, RailShape.NORTH_SOUTH); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_SOUTH); + } + default: + return state; +@@ -253,44 +263,45 @@ + } + + @Override +- public BlockState mirror(BlockState state, Mirror mirror) { +- RailShape railShape = state.getValue(SHAPE); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ RailShape blockpropertytrackposition = (RailShape) state.getValue(DetectorRailBlock.SHAPE); ++ + switch (mirror) { + case LEFT_RIGHT: +- switch (railShape) { ++ switch (blockpropertytrackposition) { + case ASCENDING_NORTH: +- return state.setValue(SHAPE, RailShape.ASCENDING_SOUTH); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); + case ASCENDING_SOUTH: +- return state.setValue(SHAPE, RailShape.ASCENDING_NORTH); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_NORTH); + case SOUTH_EAST: +- return state.setValue(SHAPE, RailShape.NORTH_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_EAST); + case SOUTH_WEST: +- return state.setValue(SHAPE, RailShape.NORTH_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_WEST); + case NORTH_WEST: +- return state.setValue(SHAPE, RailShape.SOUTH_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_WEST); + case NORTH_EAST: +- return state.setValue(SHAPE, RailShape.SOUTH_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_EAST); + default: + return super.mirror(state, mirror); + } + case FRONT_BACK: +- switch (railShape) { ++ switch (blockpropertytrackposition) { + case ASCENDING_EAST: +- return state.setValue(SHAPE, RailShape.ASCENDING_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_WEST); + case ASCENDING_WEST: +- return state.setValue(SHAPE, RailShape.ASCENDING_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.ASCENDING_EAST); + case ASCENDING_NORTH: + case ASCENDING_SOUTH: + default: + break; + case SOUTH_EAST: +- return state.setValue(SHAPE, RailShape.SOUTH_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_WEST); + case SOUTH_WEST: +- return state.setValue(SHAPE, RailShape.SOUTH_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.SOUTH_EAST); + case NORTH_WEST: +- return state.setValue(SHAPE, RailShape.NORTH_EAST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_EAST); + case NORTH_EAST: +- return state.setValue(SHAPE, RailShape.NORTH_WEST); ++ return (IBlockData) state.setValue(DetectorRailBlock.SHAPE, RailShape.NORTH_WEST); + } + } + +@@ -298,7 +309,7 @@ + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(SHAPE, POWERED, WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(DetectorRailBlock.SHAPE, DetectorRailBlock.POWERED, DetectorRailBlock.WATERLOGGED); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/DiodeBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/DiodeBlock.java.patch new file mode 100644 index 0000000000..fd6a05343e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/DiodeBlock.java.patch @@ -0,0 +1,283 @@ +--- a/net/minecraft/world/level/block/DiodeBlock.java ++++ b/net/minecraft/world/level/block/DiodeBlock.java +@@ -14,15 +14,17 @@ + import net.minecraft.world.level.SignalGetter; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.ticks.TickPriority; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public abstract class DiodeBlock extends HorizontalDirectionalBlock { +- protected static final VoxelShape SHAPE = Block.box(0.0, 0.0, 0.0, 16.0, 2.0, 16.0); ++ ++ protected static final VoxelShape SHAPE = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 2.0D, 16.0D); + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + + protected DiodeBlock(BlockBehaviour.Properties properties) { +@@ -33,167 +35,188 @@ + protected abstract MapCodec codec(); + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPE; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return DiodeBlock.SHAPE; + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { +- BlockPos blockPos = pos.below(); +- return this.canSurviveOn(level, blockPos, level.getBlockState(blockPos)); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.below(); ++ ++ return this.canSurviveOn(level, blockposition1, level.getBlockState(blockposition1)); + } + +- protected boolean canSurviveOn(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { +- return blockState.isFaceSturdy(levelReader, blockPos, Direction.UP, SupportType.RIGID); ++ protected boolean canSurviveOn(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ return iblockdata.isFaceSturdy(iworldreader, blockposition, Direction.UP, SupportType.RIGID); + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (!this.isLocked(level, pos, state)) { +- boolean flag = state.getValue(POWERED); +- boolean shouldTurnOn = this.shouldTurnOn(level, pos, state); +- if (flag && !shouldTurnOn) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(false)), 2); ++ boolean flag = (Boolean) state.getValue(DiodeBlock.POWERED); ++ boolean flag1 = this.shouldTurnOn(level, pos, state); ++ ++ if (flag && !flag1) { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 15, 0).getNewCurrent() != 0) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(DiodeBlock.POWERED, false), 2); + } else if (!flag) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(true)), 2); +- if (!shouldTurnOn) { +- level.scheduleTick(pos, this, this.getDelay(state), TickPriority.VERY_HIGH); ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 0, 15).getNewCurrent() != 15) { ++ return; + } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(DiodeBlock.POWERED, true), 2); ++ if (!flag1) { ++ level.scheduleTick(pos, (Block) this, this.getDelay(state), TickPriority.VERY_HIGH); ++ } + } ++ + } + } + + @Override +- public int getDirectSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ public int getDirectSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { + return blockState.getSignal(blockAccess, pos, side); + } + + @Override +- public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { +- if (!blockState.getValue(POWERED)) { +- return 0; +- } else { +- return blockState.getValue(FACING) == side ? this.getOutputSignal(blockAccess, pos, blockState) : 0; +- } ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return !(Boolean) blockState.getValue(DiodeBlock.POWERED) ? 0 : (blockState.getValue(DiodeBlock.FACING) == side ? this.getOutputSignal(blockAccess, pos, blockState) : 0); + } + + @Override +- public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { + if (state.canSurvive(level, pos)) { + this.checkTickOnNeighbor(level, pos, state); + } else { +- BlockEntity blockEntity = state.hasBlockEntity() ? level.getBlockEntity(pos) : null; +- dropResources(state, level, pos, blockEntity); ++ BlockEntity tileentity = state.hasBlockEntity() ? level.getBlockEntity(pos) : null; ++ ++ dropResources(state, level, pos, tileentity); + level.removeBlock(pos, false); ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; + +- for (Direction direction : Direction.values()) { +- level.updateNeighborsAt(pos.relative(direction), this); ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ ++ level.updateNeighborsAt(pos.relative(enumdirection), this); + } ++ + } + } + +- protected void checkTickOnNeighbor(Level level, BlockPos pos, BlockState state) { ++ protected void checkTickOnNeighbor(Level level, BlockPos pos, IBlockData state) { + if (!this.isLocked(level, pos, state)) { +- boolean flag = state.getValue(POWERED); +- boolean shouldTurnOn = this.shouldTurnOn(level, pos, state); +- if (flag != shouldTurnOn && !level.getBlockTicks().willTickThisTick(pos, this)) { +- TickPriority tickPriority = TickPriority.HIGH; ++ boolean flag = (Boolean) state.getValue(DiodeBlock.POWERED); ++ boolean flag1 = this.shouldTurnOn(level, pos, state); ++ ++ if (flag != flag1 && !level.getBlockTicks().willTickThisTick(pos, this)) { ++ TickPriority ticklistpriority = TickPriority.HIGH; ++ + if (this.shouldPrioritize(level, pos, state)) { +- tickPriority = TickPriority.EXTREMELY_HIGH; ++ ticklistpriority = TickPriority.EXTREMELY_HIGH; + } else if (flag) { +- tickPriority = TickPriority.VERY_HIGH; ++ ticklistpriority = TickPriority.VERY_HIGH; + } + +- level.scheduleTick(pos, this, this.getDelay(state), tickPriority); ++ level.scheduleTick(pos, (Block) this, this.getDelay(state), ticklistpriority); + } ++ + } + } + +- public boolean isLocked(LevelReader level, BlockPos pos, BlockState state) { ++ public boolean isLocked(LevelReader level, BlockPos pos, IBlockData state) { + return false; + } + +- protected boolean shouldTurnOn(Level level, BlockPos pos, BlockState state) { ++ protected boolean shouldTurnOn(Level level, BlockPos pos, IBlockData state) { + return this.getInputSignal(level, pos, state) > 0; + } + +- protected int getInputSignal(Level level, BlockPos pos, BlockState state) { +- Direction direction = state.getValue(FACING); +- BlockPos blockPos = pos.relative(direction); +- int signal = level.getSignal(blockPos, direction); +- if (signal >= 15) { +- return signal; ++ protected int getInputSignal(Level level, BlockPos pos, IBlockData state) { ++ Direction enumdirection = (Direction) state.getValue(DiodeBlock.FACING); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ int i = level.getSignal(blockposition1, enumdirection); ++ ++ if (i >= 15) { ++ return i; + } else { +- BlockState blockState = level.getBlockState(blockPos); +- return Math.max(signal, blockState.is(Blocks.REDSTONE_WIRE) ? blockState.getValue(RedStoneWireBlock.POWER) : 0); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ return Math.max(i, iblockdata1.is(Blocks.REDSTONE_WIRE) ? (Integer) iblockdata1.getValue(RedStoneWireBlock.POWER) : 0); + } + } + +- protected int getAlternateSignal(SignalGetter level, BlockPos pos, BlockState state) { +- Direction direction = state.getValue(FACING); +- Direction clockWise = direction.getClockWise(); +- Direction counterClockWise = direction.getCounterClockWise(); ++ protected int getAlternateSignal(SignalGetter level, BlockPos pos, IBlockData state) { ++ Direction enumdirection = (Direction) state.getValue(DiodeBlock.FACING); ++ Direction enumdirection1 = enumdirection.getClockWise(); ++ Direction enumdirection2 = enumdirection.getCounterClockWise(); + boolean flag = this.sideInputDiodesOnly(); +- return Math.max( +- level.getControlInputSignal(pos.relative(clockWise), clockWise, flag), +- level.getControlInputSignal(pos.relative(counterClockWise), counterClockWise, flag) +- ); ++ ++ return Math.max(level.getControlInputSignal(pos.relative(enumdirection1), enumdirection1, flag), level.getControlInputSignal(pos.relative(enumdirection2), enumdirection2, flag)); + } + + @Override +- public boolean isSignalSource(BlockState state) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return (IBlockData) this.defaultBlockState().setValue(DiodeBlock.FACING, context.getHorizontalDirection().getOpposite()); + } + + @Override +- public void setPlacedBy(Level level, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, LivingEntity placer, ItemStack stack) { + if (this.shouldTurnOn(level, pos, state)) { +- level.scheduleTick(pos, this, 1); ++ level.scheduleTick(pos, (Block) this, 1); + } ++ + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { + this.updateNeighborsInFront(level, pos, state); + } + + @Override +- public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { + if (!isMoving && !state.is(newState.getBlock())) { + super.onRemove(state, level, pos, newState, isMoving); + this.updateNeighborsInFront(level, pos, state); + } + } + +- protected void updateNeighborsInFront(Level level, BlockPos pos, BlockState state) { +- Direction direction = state.getValue(FACING); +- BlockPos blockPos = pos.relative(direction.getOpposite()); +- level.neighborChanged(blockPos, this, pos); +- level.updateNeighborsAtExceptFromFacing(blockPos, this, direction); ++ protected void updateNeighborsInFront(Level level, BlockPos pos, IBlockData state) { ++ Direction enumdirection = (Direction) state.getValue(DiodeBlock.FACING); ++ BlockPos blockposition1 = pos.relative(enumdirection.getOpposite()); ++ ++ level.neighborChanged(blockposition1, this, pos); ++ level.updateNeighborsAtExceptFromFacing(blockposition1, this, enumdirection); + } + + protected boolean sideInputDiodesOnly() { + return false; + } + +- protected int getOutputSignal(BlockGetter level, BlockPos pos, BlockState state) { ++ protected int getOutputSignal(BlockGetter level, BlockPos pos, IBlockData state) { + return 15; + } + +- public static boolean isDiode(BlockState state) { ++ public static boolean isDiode(IBlockData state) { + return state.getBlock() instanceof DiodeBlock; + } + +- public boolean shouldPrioritize(BlockGetter level, BlockPos pos, BlockState state) { +- Direction opposite = state.getValue(FACING).getOpposite(); +- BlockState blockState = level.getBlockState(pos.relative(opposite)); +- return isDiode(blockState) && blockState.getValue(FACING) != opposite; ++ public boolean shouldPrioritize(BlockGetter level, BlockPos pos, IBlockData state) { ++ Direction enumdirection = ((Direction) state.getValue(DiodeBlock.FACING)).getOpposite(); ++ IBlockData iblockdata1 = level.getBlockState(pos.relative(enumdirection)); ++ ++ return isDiode(iblockdata1) && iblockdata1.getValue(DiodeBlock.FACING) != enumdirection; + } + +- protected abstract int getDelay(BlockState state); ++ protected abstract int getDelay(IBlockData state); + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/DispenserBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/DispenserBlock.java.patch new file mode 100644 index 0000000000..62de3efd20 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/DispenserBlock.java.patch @@ -0,0 +1,254 @@ +--- a/net/minecraft/world/level/block/DispenserBlock.java ++++ b/net/minecraft/world/level/block/DispenserBlock.java +@@ -7,15 +7,15 @@ + import net.minecraft.Util; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.Position; +-import net.minecraft.core.dispenser.BlockSource; ++import net.minecraft.core.IPosition; + import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; + import net.minecraft.core.dispenser.DispenseItemBehavior; ++import net.minecraft.core.dispenser.SourceBlock; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.stats.Stats; + import net.minecraft.util.RandomSource; + import net.minecraft.world.Containers; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.player.Player; +@@ -23,14 +23,14 @@ + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.context.BlockPlaceContext; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.DispenserBlockEntity; +-import net.minecraft.world.level.block.entity.DropperBlockEntity; ++import net.minecraft.world.level.block.entity.TileEntityDropper; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -40,38 +40,41 @@ + import org.slf4j.Logger; + + public class DispenserBlock extends BaseEntityBlock { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + public static final MapCodec CODEC = simpleCodec(DispenserBlock::new); +- public static final DirectionProperty FACING = DirectionalBlock.FACING; ++ public static final DirectionProperty FACING = BlockDirectional.FACING; + public static final BooleanProperty TRIGGERED = BlockStateProperties.TRIGGERED; +- private static final Map DISPENSER_REGISTRY = Util.make( +- new Object2ObjectOpenHashMap<>(), map -> map.defaultReturnValue(new DefaultDispenseItemBehavior()) +- ); ++ public static final Map DISPENSER_REGISTRY = (Map) Util.make(new Object2ObjectOpenHashMap(), (object2objectopenhashmap) -> { ++ object2objectopenhashmap.defaultReturnValue(new DefaultDispenseItemBehavior()); ++ }); + private static final int TRIGGER_DURATION = 4; ++ public static boolean eventFired = false; // CraftBukkit + + @Override + public MapCodec codec() { +- return CODEC; ++ return DispenserBlock.CODEC; + } + +- public static void registerBehavior(ItemLike item, DispenseItemBehavior behavior) { +- DISPENSER_REGISTRY.put(item.asItem(), behavior); ++ public static void registerBehavior(IMaterial item, DispenseItemBehavior behavior) { ++ DispenserBlock.DISPENSER_REGISTRY.put(item.asItem(), behavior); + } + + protected DispenserBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(TRIGGERED, Boolean.valueOf(false))); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(DispenserBlock.FACING, Direction.NORTH)).setValue(DispenserBlock.TRIGGERED, false)); + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + if (level.isClientSide) { + return InteractionResult.SUCCESS; + } else { +- BlockEntity blockEntity = level.getBlockEntity(pos); +- if (blockEntity instanceof DispenserBlockEntity) { +- player.openMenu((DispenserBlockEntity)blockEntity); +- if (blockEntity instanceof DropperBlockEntity) { ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof DispenserBlockEntity) { ++ player.openMenu((DispenserBlockEntity) tileentity); ++ if (tileentity instanceof TileEntityDropper) { + player.awardStat(Stats.INSPECT_DROPPER); + } else { + player.awardStat(Stats.INSPECT_DISPENSER); +@@ -82,105 +85,115 @@ + } + } + +- protected void dispenseFrom(ServerLevel serverLevel, BlockState blockState, BlockPos blockPos) { +- DispenserBlockEntity dispenserBlockEntity = serverLevel.getBlockEntity(blockPos, BlockEntityType.DISPENSER).orElse(null); +- if (dispenserBlockEntity == null) { +- LOGGER.warn("Ignoring dispensing attempt for Dispenser without matching block entity at {}", blockPos); ++ public void dispenseFrom(ServerLevel worldserver, IBlockData iblockdata, BlockPos blockposition) { ++ DispenserBlockEntity tileentitydispenser = (DispenserBlockEntity) worldserver.getBlockEntity(blockposition, BlockEntityType.DISPENSER).orElse(null); // CraftBukkit - decompile error ++ ++ if (tileentitydispenser == null) { ++ DispenserBlock.LOGGER.warn("Ignoring dispensing attempt for Dispenser without matching block entity at {}", blockposition); + } else { +- BlockSource blockSource = new BlockSource(serverLevel, blockPos, blockState, dispenserBlockEntity); +- int randomSlot = dispenserBlockEntity.getRandomSlot(serverLevel.random); +- if (randomSlot < 0) { +- serverLevel.levelEvent(1001, blockPos, 0); +- serverLevel.gameEvent(GameEvent.BLOCK_ACTIVATE, blockPos, GameEvent.Context.of(dispenserBlockEntity.getBlockState())); ++ SourceBlock sourceblock = new SourceBlock(worldserver, blockposition, iblockdata, tileentitydispenser); ++ int i = tileentitydispenser.getRandomSlot(worldserver.random); ++ ++ if (i < 0) { ++ worldserver.levelEvent(1001, blockposition, 0); ++ worldserver.gameEvent(GameEvent.BLOCK_ACTIVATE, blockposition, GameEvent.Context.of(tileentitydispenser.getBlockState())); + } else { +- ItemStack item = dispenserBlockEntity.getItem(randomSlot); +- DispenseItemBehavior dispenseMethod = this.getDispenseMethod(item); +- if (dispenseMethod != DispenseItemBehavior.NOOP) { +- dispenserBlockEntity.setItem(randomSlot, dispenseMethod.dispense(blockSource, item)); ++ ItemStack itemstack = tileentitydispenser.getItem(i); ++ DispenseItemBehavior idispensebehavior = this.getDispenseMethod(itemstack); ++ ++ if (idispensebehavior != DispenseItemBehavior.NOOP) { ++ eventFired = false; // CraftBukkit - reset event status ++ tileentitydispenser.setItem(i, idispensebehavior.dispense(sourceblock, itemstack)); + } ++ + } + } + } + + protected DispenseItemBehavior getDispenseMethod(ItemStack stack) { +- return DISPENSER_REGISTRY.get(stack.getItem()); ++ return (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(stack.getItem()); + } + + @Override +- public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { +- boolean flag = level.hasNeighborSignal(pos) || level.hasNeighborSignal(pos.above()); +- boolean flag1 = state.getValue(TRIGGERED); +- if (flag && !flag1) { +- level.scheduleTick(pos, this, 4); +- level.setBlock(pos, state.setValue(TRIGGERED, Boolean.valueOf(true)), 2); +- } else if (!flag && flag1) { +- level.setBlock(pos, state.setValue(TRIGGERED, Boolean.valueOf(false)), 2); ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ boolean flag1 = level.hasNeighborSignal(pos) || level.hasNeighborSignal(pos.above()); ++ boolean flag2 = (Boolean) state.getValue(DispenserBlock.TRIGGERED); ++ ++ if (flag1 && !flag2) { ++ level.scheduleTick(pos, (Block) this, 4); ++ level.setBlock(pos, (IBlockData) state.setValue(DispenserBlock.TRIGGERED, true), 2); ++ } else if (!flag1 && flag2) { ++ level.setBlock(pos, (IBlockData) state.setValue(DispenserBlock.TRIGGERED, false), 2); + } ++ + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + this.dispenseFrom(level, state, pos); + } + + @Override +- public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { + return new DispenserBlockEntity(pos, state); + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- return this.defaultBlockState().setValue(FACING, context.getNearestLookingDirection().getOpposite()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return (IBlockData) this.defaultBlockState().setValue(DispenserBlock.FACING, context.getNearestLookingDirection().getOpposite()); + } + + @Override +- public void setPlacedBy(Level level, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, LivingEntity placer, ItemStack stack) { + if (stack.hasCustomHoverName()) { +- BlockEntity blockEntity = level.getBlockEntity(pos); +- if (blockEntity instanceof DispenserBlockEntity) { +- ((DispenserBlockEntity)blockEntity).setCustomName(stack.getHoverName()); ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof DispenserBlockEntity) { ++ ((DispenserBlockEntity) tileentity).setCustomName(stack.getHoverName()); + } + } ++ + } + + @Override +- public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { + Containers.dropContentsOnDestroy(state, newState, level, pos); + super.onRemove(state, level, pos, newState, isMoving); + } + +- public static Position getDispensePosition(BlockSource blockSource) { +- Direction direction = blockSource.state().getValue(FACING); +- return blockSource.center().add(0.7 * (double)direction.getStepX(), 0.7 * (double)direction.getStepY(), 0.7 * (double)direction.getStepZ()); ++ public static IPosition getDispensePosition(SourceBlock sourceblock) { ++ Direction enumdirection = (Direction) sourceblock.state().getValue(DispenserBlock.FACING); ++ ++ return sourceblock.center().add(0.7D * (double) enumdirection.getStepX(), 0.7D * (double) enumdirection.getStepY(), 0.7D * (double) enumdirection.getStepZ()); + } + + @Override +- public boolean hasAnalogOutputSignal(BlockState state) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return true; + } + + @Override +- public int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) { ++ public int getAnalogOutputSignal(IBlockData blockState, Level level, BlockPos pos) { + return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos)); + } + + @Override +- public RenderShape getRenderShape(BlockState state) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Override +- public BlockState rotate(BlockState state, Rotation rotation) { +- return state.setValue(FACING, rotation.rotate(state.getValue(FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return (IBlockData) state.setValue(DispenserBlock.FACING, rotation.rotate((Direction) state.getValue(DispenserBlock.FACING))); + } + + @Override +- public BlockState mirror(BlockState state, Mirror mirror) { +- return state.rotate(mirror.getRotation(state.getValue(FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(DispenserBlock.FACING))); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(FACING, TRIGGERED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(DispenserBlock.FACING, DispenserBlock.TRIGGERED); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/DoorBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/DoorBlock.java.patch new file mode 100644 index 0000000000..57fbdd1f2a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/DoorBlock.java.patch @@ -0,0 +1,449 @@ +--- a/net/minecraft/world/level/block/DoorBlock.java ++++ b/net/minecraft/world/level/block/DoorBlock.java +@@ -2,14 +2,13 @@ + + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import java.util.function.BiConsumer; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.sounds.SoundSource; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; +@@ -22,55 +21,49 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; ++import net.minecraft.world.level.block.state.properties.BlockPropertyDoorHinge; ++import net.minecraft.world.level.block.state.properties.BlockPropertyDoubleBlockHalf; + import net.minecraft.world.level.block.state.properties.BlockSetType; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.block.state.properties.DirectionProperty; +-import net.minecraft.world.level.block.state.properties.DoorHingeSide; +-import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; + import net.minecraft.world.level.block.state.properties.EnumProperty; + import net.minecraft.world.level.gameevent.GameEvent; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class DoorBlock extends Block { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group(BlockSetType.CODEC.fieldOf("block_set_type").forGetter(DoorBlock::type), propertiesCodec()).apply(instance, DoorBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(BlockSetType.CODEC.fieldOf("block_set_type").forGetter(DoorBlock::type), propertiesCodec()).apply(instance, DoorBlock::new); ++ }); + public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING; + public static final BooleanProperty OPEN = BlockStateProperties.OPEN; +- public static final EnumProperty HINGE = BlockStateProperties.DOOR_HINGE; ++ public static final EnumProperty HINGE = BlockStateProperties.DOOR_HINGE; + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; +- public static final EnumProperty HALF = BlockStateProperties.DOUBLE_BLOCK_HALF; ++ public static final EnumProperty HALF = BlockStateProperties.DOUBLE_BLOCK_HALF; + protected static final float AABB_DOOR_THICKNESS = 3.0F; +- protected static final VoxelShape SOUTH_AABB = Block.box(0.0, 0.0, 0.0, 16.0, 16.0, 3.0); +- protected static final VoxelShape NORTH_AABB = Block.box(0.0, 0.0, 13.0, 16.0, 16.0, 16.0); +- protected static final VoxelShape WEST_AABB = Block.box(13.0, 0.0, 0.0, 16.0, 16.0, 16.0); +- protected static final VoxelShape EAST_AABB = Block.box(0.0, 0.0, 0.0, 3.0, 16.0, 16.0); ++ protected static final VoxelShape SOUTH_AABB = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 16.0D, 3.0D); ++ protected static final VoxelShape NORTH_AABB = Block.box(0.0D, 0.0D, 13.0D, 16.0D, 16.0D, 16.0D); ++ protected static final VoxelShape WEST_AABB = Block.box(13.0D, 0.0D, 0.0D, 16.0D, 16.0D, 16.0D); ++ protected static final VoxelShape EAST_AABB = Block.box(0.0D, 0.0D, 0.0D, 3.0D, 16.0D, 16.0D); + private final BlockSetType type; + + @Override + public MapCodec codec() { +- return CODEC; ++ return DoorBlock.CODEC; + } + +- protected DoorBlock(BlockSetType blockSetType, BlockBehaviour.Properties properties) { +- super(properties.sound(blockSetType.soundType())); +- this.type = blockSetType; +- this.registerDefaultState( +- this.stateDefinition +- .any() +- .setValue(FACING, Direction.NORTH) +- .setValue(OPEN, Boolean.valueOf(false)) +- .setValue(HINGE, DoorHingeSide.LEFT) +- .setValue(POWERED, Boolean.valueOf(false)) +- .setValue(HALF, DoubleBlockHalf.LOWER) +- ); ++ protected DoorBlock(BlockSetType blocksettype, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info.sound(blocksettype.soundType())); ++ this.type = blocksettype; ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(DoorBlock.FACING, Direction.NORTH)).setValue(DoorBlock.OPEN, false)).setValue(DoorBlock.HINGE, BlockPropertyDoorHinge.LEFT)).setValue(DoorBlock.POWERED, false)).setValue(DoorBlock.HALF, BlockPropertyDoubleBlockHalf.LOWER)); + } + + public BlockSetType type() { +@@ -78,206 +71,234 @@ + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- Direction direction = state.getValue(FACING); +- boolean flag = !state.getValue(OPEN); +- boolean flag1 = state.getValue(HINGE) == DoorHingeSide.RIGHT; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ Direction enumdirection = (Direction) state.getValue(DoorBlock.FACING); ++ boolean flag = !(Boolean) state.getValue(DoorBlock.OPEN); ++ boolean flag1 = state.getValue(DoorBlock.HINGE) == BlockPropertyDoorHinge.RIGHT; ++ VoxelShape voxelshape; + +- return switch (direction) { +- case SOUTH -> flag ? SOUTH_AABB : (flag1 ? EAST_AABB : WEST_AABB); +- case WEST -> flag ? WEST_AABB : (flag1 ? SOUTH_AABB : NORTH_AABB); +- case NORTH -> flag ? NORTH_AABB : (flag1 ? WEST_AABB : EAST_AABB); +- default -> flag ? EAST_AABB : (flag1 ? NORTH_AABB : SOUTH_AABB); +- }; ++ switch (enumdirection) { ++ case SOUTH: ++ voxelshape = flag ? DoorBlock.SOUTH_AABB : (flag1 ? DoorBlock.EAST_AABB : DoorBlock.WEST_AABB); ++ break; ++ case WEST: ++ voxelshape = flag ? DoorBlock.WEST_AABB : (flag1 ? DoorBlock.SOUTH_AABB : DoorBlock.NORTH_AABB); ++ break; ++ case NORTH: ++ voxelshape = flag ? DoorBlock.NORTH_AABB : (flag1 ? DoorBlock.WEST_AABB : DoorBlock.EAST_AABB); ++ break; ++ default: ++ voxelshape = flag ? DoorBlock.EAST_AABB : (flag1 ? DoorBlock.NORTH_AABB : DoorBlock.SOUTH_AABB); ++ } ++ ++ return voxelshape; + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- DoubleBlockHalf doubleBlockHalf = state.getValue(HALF); +- if (facing.getAxis() != Direction.Axis.Y || doubleBlockHalf == DoubleBlockHalf.LOWER != (facing == Direction.UP)) { +- return doubleBlockHalf == DoubleBlockHalf.LOWER && facing == Direction.DOWN && !state.canSurvive(level, currentPos) +- ? Blocks.AIR.defaultBlockState() +- : super.updateShape(state, facing, facingState, level, currentPos, facingPos); +- } else { +- return facingState.getBlock() instanceof DoorBlock && facingState.getValue(HALF) != doubleBlockHalf +- ? facingState.setValue(HALF, doubleBlockHalf) +- : Blocks.AIR.defaultBlockState(); +- } ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ BlockPropertyDoubleBlockHalf blockpropertydoubleblockhalf = (BlockPropertyDoubleBlockHalf) state.getValue(DoorBlock.HALF); ++ ++ return facing.getAxis() == Direction.Axis.Y && blockpropertydoubleblockhalf == BlockPropertyDoubleBlockHalf.LOWER == (facing == Direction.UP) ? (facingState.getBlock() instanceof DoorBlock && facingState.getValue(DoorBlock.HALF) != blockpropertydoubleblockhalf ? (IBlockData) facingState.setValue(DoorBlock.HALF, blockpropertydoubleblockhalf) : Blocks.AIR.defaultBlockState()) : (blockpropertydoubleblockhalf == BlockPropertyDoubleBlockHalf.LOWER && facing == Direction.DOWN && !state.canSurvive(level, currentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, level, currentPos, facingPos)); + } + + @Override +- public void onExplosionHit(BlockState blockState, Level level, BlockPos blockPos, Explosion explosion, BiConsumer biConsumer) { +- if (explosion.getBlockInteraction() == Explosion.BlockInteraction.TRIGGER_BLOCK +- && blockState.getValue(HALF) == DoubleBlockHalf.LOWER +- && !level.isClientSide() +- && this.type.canOpenByWindCharge() +- && !blockState.getValue(POWERED)) { +- this.setOpen(null, level, blockState, blockPos, !this.isOpen(blockState)); ++ public void onExplosionHit(IBlockData iblockdata, Level world, BlockPos blockposition, Explosion explosion, BiConsumer biconsumer) { ++ if (explosion.getBlockInteraction() == Explosion.Effect.TRIGGER_BLOCK && iblockdata.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER && !world.isClientSide() && this.type.canOpenByWindCharge() && !(Boolean) iblockdata.getValue(DoorBlock.POWERED)) { ++ this.setOpen((Entity) null, world, iblockdata, blockposition, !this.isOpen(iblockdata)); + } + +- super.onExplosionHit(blockState, level, blockPos, explosion, biConsumer); ++ super.onExplosionHit(iblockdata, world, blockposition, explosion, biconsumer); + } + + @Override +- public BlockState playerWillDestroy(Level level, BlockPos blockPos, BlockState blockState, Player player) { +- if (!level.isClientSide && (player.isCreative() || !player.hasCorrectToolForDrops(blockState))) { +- DoublePlantBlock.preventDropFromBottomPart(level, blockPos, blockState, player); ++ public IBlockData playerWillDestroy(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ if (!world.isClientSide && (entityhuman.isCreative() || !entityhuman.hasCorrectToolForDrops(iblockdata))) { ++ DoublePlantBlock.preventDropFromBottomPart(world, blockposition, iblockdata, entityhuman); + } + +- return super.playerWillDestroy(level, blockPos, blockState, player); ++ return super.playerWillDestroy(world, blockposition, iblockdata, entityhuman); + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { +- return switch (type) { +- case LAND, AIR -> state.getValue(OPEN); +- case WATER -> false; +- }; ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { ++ boolean flag; ++ ++ switch (type) { ++ case LAND: ++ case AIR: ++ flag = (Boolean) state.getValue(DoorBlock.OPEN); ++ break; ++ case WATER: ++ flag = false; ++ break; ++ default: ++ throw new IncompatibleClassChangeError(); ++ } ++ ++ return flag; + } + + @Nullable + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- BlockPos clickedPos = context.getClickedPos(); +- Level level = context.getLevel(); +- if (clickedPos.getY() < level.getMaxBuildHeight() - 1 && level.getBlockState(clickedPos.above()).canBeReplaced(context)) { +- boolean flag = level.hasNeighborSignal(clickedPos) || level.hasNeighborSignal(clickedPos.above()); +- return this.defaultBlockState() +- .setValue(FACING, context.getHorizontalDirection()) +- .setValue(HINGE, this.getHinge(context)) +- .setValue(POWERED, Boolean.valueOf(flag)) +- .setValue(OPEN, Boolean.valueOf(flag)) +- .setValue(HALF, DoubleBlockHalf.LOWER); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ BlockPos blockposition = context.getClickedPos(); ++ Level world = context.getLevel(); ++ ++ if (blockposition.getY() < world.getMaxBuildHeight() - 1 && world.getBlockState(blockposition.above()).canBeReplaced(context)) { ++ boolean flag = world.hasNeighborSignal(blockposition) || world.hasNeighborSignal(blockposition.above()); ++ ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(DoorBlock.FACING, context.getHorizontalDirection())).setValue(DoorBlock.HINGE, this.getHinge(context))).setValue(DoorBlock.POWERED, flag)).setValue(DoorBlock.OPEN, flag)).setValue(DoorBlock.HALF, BlockPropertyDoubleBlockHalf.LOWER); + } else { + return null; + } + } + + @Override +- public void setPlacedBy(Level level, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { +- level.setBlock(pos.above(), state.setValue(HALF, DoubleBlockHalf.UPPER), 3); ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, LivingEntity placer, ItemStack stack) { ++ level.setBlock(pos.above(), (IBlockData) state.setValue(DoorBlock.HALF, BlockPropertyDoubleBlockHalf.UPPER), 3); + } + +- private DoorHingeSide getHinge(BlockPlaceContext context) { +- BlockGetter level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- Direction horizontalDirection = context.getHorizontalDirection(); +- BlockPos blockPos = clickedPos.above(); +- Direction counterClockWise = horizontalDirection.getCounterClockWise(); +- BlockPos blockPos1 = clickedPos.relative(counterClockWise); +- BlockState blockState = level.getBlockState(blockPos1); +- BlockPos blockPos2 = blockPos.relative(counterClockWise); +- BlockState blockState1 = level.getBlockState(blockPos2); +- Direction clockWise = horizontalDirection.getClockWise(); +- BlockPos blockPos3 = clickedPos.relative(clockWise); +- BlockState blockState2 = level.getBlockState(blockPos3); +- BlockPos blockPos4 = blockPos.relative(clockWise); +- BlockState blockState3 = level.getBlockState(blockPos4); +- int i = (blockState.isCollisionShapeFullBlock(level, blockPos1) ? -1 : 0) +- + (blockState1.isCollisionShapeFullBlock(level, blockPos2) ? -1 : 0) +- + (blockState2.isCollisionShapeFullBlock(level, blockPos3) ? 1 : 0) +- + (blockState3.isCollisionShapeFullBlock(level, blockPos4) ? 1 : 0); +- boolean flag = blockState.is(this) && blockState.getValue(HALF) == DoubleBlockHalf.LOWER; +- boolean flag1 = blockState2.is(this) && blockState2.getValue(HALF) == DoubleBlockHalf.LOWER; ++ private BlockPropertyDoorHinge getHinge(BlockPlaceContext context) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ Direction enumdirection = context.getHorizontalDirection(); ++ BlockPos blockposition1 = blockposition.above(); ++ Direction enumdirection1 = enumdirection.getCounterClockWise(); ++ BlockPos blockposition2 = blockposition.relative(enumdirection1); ++ IBlockData iblockdata = world.getBlockState(blockposition2); ++ BlockPos blockposition3 = blockposition1.relative(enumdirection1); ++ IBlockData iblockdata1 = world.getBlockState(blockposition3); ++ Direction enumdirection2 = enumdirection.getClockWise(); ++ BlockPos blockposition4 = blockposition.relative(enumdirection2); ++ IBlockData iblockdata2 = world.getBlockState(blockposition4); ++ BlockPos blockposition5 = blockposition1.relative(enumdirection2); ++ IBlockData iblockdata3 = world.getBlockState(blockposition5); ++ int i = (iblockdata.isCollisionShapeFullBlock(world, blockposition2) ? -1 : 0) + (iblockdata1.isCollisionShapeFullBlock(world, blockposition3) ? -1 : 0) + (iblockdata2.isCollisionShapeFullBlock(world, blockposition4) ? 1 : 0) + (iblockdata3.isCollisionShapeFullBlock(world, blockposition5) ? 1 : 0); ++ boolean flag = iblockdata.is((Block) this) && iblockdata.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER; ++ boolean flag1 = iblockdata2.is((Block) this) && iblockdata2.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER; ++ + if ((!flag || flag1) && i <= 0) { + if ((!flag1 || flag) && i >= 0) { +- int stepX = horizontalDirection.getStepX(); +- int stepZ = horizontalDirection.getStepZ(); +- Vec3 clickLocation = context.getClickLocation(); +- double d = clickLocation.x - (double)clickedPos.getX(); +- double d1 = clickLocation.z - (double)clickedPos.getZ(); +- return (stepX >= 0 || !(d1 < 0.5)) && (stepX <= 0 || !(d1 > 0.5)) && (stepZ >= 0 || !(d > 0.5)) && (stepZ <= 0 || !(d < 0.5)) +- ? DoorHingeSide.LEFT +- : DoorHingeSide.RIGHT; ++ int j = enumdirection.getStepX(); ++ int k = enumdirection.getStepZ(); ++ Vec3 vec3d = context.getClickLocation(); ++ double d0 = vec3d.x - (double) blockposition.getX(); ++ double d1 = vec3d.z - (double) blockposition.getZ(); ++ ++ return (j >= 0 || d1 >= 0.5D) && (j <= 0 || d1 <= 0.5D) && (k >= 0 || d0 <= 0.5D) && (k <= 0 || d0 >= 0.5D) ? BlockPropertyDoorHinge.LEFT : BlockPropertyDoorHinge.RIGHT; + } else { +- return DoorHingeSide.LEFT; ++ return BlockPropertyDoorHinge.LEFT; + } + } else { +- return DoorHingeSide.RIGHT; ++ return BlockPropertyDoorHinge.RIGHT; + } + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + if (!this.type.canOpenByHand()) { + return InteractionResult.PASS; + } else { +- state = state.cycle(OPEN); ++ state = (IBlockData) state.cycle(DoorBlock.OPEN); + level.setBlock(pos, state, 10); +- this.playSound(player, level, pos, state.getValue(OPEN)); +- level.gameEvent(player, this.isOpen(state) ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); ++ this.playSound(player, level, pos, (Boolean) state.getValue(DoorBlock.OPEN)); ++ level.gameEvent((Entity) player, this.isOpen(state) ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); + return InteractionResult.sidedSuccess(level.isClientSide); + } + } + +- public boolean isOpen(BlockState state) { +- return state.getValue(OPEN); ++ public boolean isOpen(IBlockData state) { ++ return (Boolean) state.getValue(DoorBlock.OPEN); + } + +- public void setOpen(@Nullable Entity entity, Level level, BlockState state, BlockPos pos, boolean _open) { +- if (state.is(this) && state.getValue(OPEN) != _open) { +- level.setBlock(pos, state.setValue(OPEN, Boolean.valueOf(_open)), 10); +- this.playSound(entity, level, pos, _open); +- level.gameEvent(entity, _open ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); ++ public void setOpen(@Nullable Entity entity, Level level, IBlockData state, BlockPos pos, boolean open) { ++ if (state.is((Block) this) && (Boolean) state.getValue(DoorBlock.OPEN) != open) { ++ level.setBlock(pos, (IBlockData) state.setValue(DoorBlock.OPEN, open), 10); ++ this.playSound(entity, level, pos, open); ++ level.gameEvent(entity, open ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); + } + } + + @Override +- public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { +- boolean flag = level.hasNeighborSignal(pos) +- || level.hasNeighborSignal(pos.relative(state.getValue(HALF) == DoubleBlockHalf.LOWER ? Direction.UP : Direction.DOWN)); +- if (!this.defaultBlockState().is(block) && flag != state.getValue(POWERED)) { +- if (flag != state.getValue(OPEN)) { +- this.playSound(null, level, pos, flag); +- level.gameEvent(null, flag ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ // CraftBukkit start ++ BlockPos otherHalf = pos.relative(state.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER ? Direction.UP : Direction.DOWN); ++ ++ org.bukkit.World bworld = level.getWorld(); ++ org.bukkit.block.Block bukkitBlock = bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ org.bukkit.block.Block blockTop = bworld.getBlockAt(otherHalf.getX(), otherHalf.getY(), otherHalf.getZ()); ++ ++ int power = bukkitBlock.getBlockPower(); ++ int powerTop = blockTop.getBlockPower(); ++ if (powerTop > power) power = powerTop; ++ int oldPower = (Boolean) state.getValue(DoorBlock.POWERED) ? 15 : 0; ++ ++ if (oldPower == 0 ^ power == 0) { ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bukkitBlock, oldPower, power); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ boolean flag1 = eventRedstone.getNewCurrent() > 0; ++ // CraftBukkit end ++ if (flag1 != (Boolean) state.getValue(DoorBlock.OPEN)) { ++ this.playSound((Entity) null, level, pos, flag1); ++ level.gameEvent((Entity) null, flag1 ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); + } + +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(flag)).setValue(OPEN, Boolean.valueOf(flag)), 2); ++ level.setBlock(pos, (IBlockData) ((IBlockData) state.setValue(DoorBlock.POWERED, flag1)).setValue(DoorBlock.OPEN, flag1), 2); + } ++ + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { +- BlockPos blockPos = pos.below(); +- BlockState blockState = level.getBlockState(blockPos); +- return state.getValue(HALF) == DoubleBlockHalf.LOWER ? blockState.isFaceSturdy(level, blockPos, Direction.UP) : blockState.is(this); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ return state.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER ? iblockdata1.isFaceSturdy(level, blockposition1, Direction.UP) : iblockdata1.is((Block) this); + } + + private void playSound(@Nullable Entity source, Level level, BlockPos pos, boolean isOpening) { +- level.playSound( +- source, pos, isOpening ? this.type.doorOpen() : this.type.doorClose(), SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.1F + 0.9F +- ); ++ level.playSound(source, pos, isOpening ? this.type.doorOpen() : this.type.doorClose(), SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.1F + 0.9F); + } + + @Override +- public BlockState rotate(BlockState state, Rotation rotation) { +- return state.setValue(FACING, rotation.rotate(state.getValue(FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return (IBlockData) state.setValue(DoorBlock.FACING, rotation.rotate((Direction) state.getValue(DoorBlock.FACING))); + } + + @Override +- public BlockState mirror(BlockState state, Mirror mirror) { +- return mirror == Mirror.NONE ? state : state.rotate(mirror.getRotation(state.getValue(FACING))).cycle(HINGE); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return mirror == Mirror.NONE ? state : (IBlockData) state.rotate(mirror.getRotation((Direction) state.getValue(DoorBlock.FACING))).cycle(DoorBlock.HINGE); + } + + @Override +- public long getSeed(BlockState state, BlockPos pos) { +- return Mth.getSeed(pos.getX(), pos.below(state.getValue(HALF) == DoubleBlockHalf.LOWER ? 0 : 1).getY(), pos.getZ()); ++ public long getSeed(IBlockData state, BlockPos pos) { ++ return Mth.getSeed(pos.getX(), pos.below(state.getValue(DoorBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER ? 0 : 1).getY(), pos.getZ()); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(HALF, FACING, OPEN, HINGE, POWERED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(DoorBlock.HALF, DoorBlock.FACING, DoorBlock.OPEN, DoorBlock.HINGE, DoorBlock.POWERED); + } + + public static boolean isWoodenDoor(Level level, BlockPos pos) { + return isWoodenDoor(level.getBlockState(pos)); + } + +- public static boolean isWoodenDoor(BlockState state) { +- if (state.getBlock() instanceof DoorBlock doorBlock && doorBlock.type().canOpenByHand()) { +- return true; ++ public static boolean isWoodenDoor(IBlockData state) { ++ Block block = state.getBlock(); ++ boolean flag; ++ ++ if (block instanceof DoorBlock) { ++ DoorBlock blockdoor = (DoorBlock) block; ++ ++ if (blockdoor.type().canOpenByHand()) { ++ flag = true; ++ return flag; ++ } + } + +- return false; ++ flag = false; ++ return flag; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/DoublePlantBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/DoublePlantBlock.java.patch new file mode 100644 index 0000000000..beb5457fbb --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/DoublePlantBlock.java.patch @@ -0,0 +1,181 @@ +--- a/net/minecraft/world/level/block/DoublePlantBlock.java ++++ b/net/minecraft/world/level/block/DoublePlantBlock.java +@@ -14,117 +14,121 @@ + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; ++import net.minecraft.world.level.block.state.properties.BlockPropertyDoubleBlockHalf; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; +-import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; + import net.minecraft.world.level.block.state.properties.EnumProperty; ++import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; + + public class DoublePlantBlock extends BushBlock { ++ + public static final MapCodec CODEC = simpleCodec(DoublePlantBlock::new); +- public static final EnumProperty HALF = BlockStateProperties.DOUBLE_BLOCK_HALF; ++ public static final EnumProperty HALF = BlockStateProperties.DOUBLE_BLOCK_HALF; + + @Override + public MapCodec codec() { +- return CODEC; ++ return DoublePlantBlock.CODEC; + } + + public DoublePlantBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(HALF, DoubleBlockHalf.LOWER)); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(DoublePlantBlock.HALF, BlockPropertyDoubleBlockHalf.LOWER)); + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- DoubleBlockHalf doubleBlockHalf = state.getValue(HALF); +- if (facing.getAxis() != Direction.Axis.Y +- || doubleBlockHalf == DoubleBlockHalf.LOWER != (facing == Direction.UP) +- || facingState.is(this) && facingState.getValue(HALF) != doubleBlockHalf) { +- return doubleBlockHalf == DoubleBlockHalf.LOWER && facing == Direction.DOWN && !state.canSurvive(level, currentPos) +- ? Blocks.AIR.defaultBlockState() +- : super.updateShape(state, facing, facingState, level, currentPos, facingPos); +- } else { +- return Blocks.AIR.defaultBlockState(); +- } ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ BlockPropertyDoubleBlockHalf blockpropertydoubleblockhalf = (BlockPropertyDoubleBlockHalf) state.getValue(DoublePlantBlock.HALF); ++ ++ return facing.getAxis() == Direction.Axis.Y && blockpropertydoubleblockhalf == BlockPropertyDoubleBlockHalf.LOWER == (facing == Direction.UP) && (!facingState.is((Block) this) || facingState.getValue(DoublePlantBlock.HALF) == blockpropertydoubleblockhalf) ? Blocks.AIR.defaultBlockState() : (blockpropertydoubleblockhalf == BlockPropertyDoubleBlockHalf.LOWER && facing == Direction.DOWN && !state.canSurvive(level, currentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, level, currentPos, facingPos)); + } + + @Nullable + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- BlockPos clickedPos = context.getClickedPos(); +- Level level = context.getLevel(); +- return clickedPos.getY() < level.getMaxBuildHeight() - 1 && level.getBlockState(clickedPos.above()).canBeReplaced(context) +- ? super.getStateForPlacement(context) +- : null; ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ BlockPos blockposition = context.getClickedPos(); ++ Level world = context.getLevel(); ++ ++ return blockposition.getY() < world.getMaxBuildHeight() - 1 && world.getBlockState(blockposition.above()).canBeReplaced(context) ? super.getStateForPlacement(context) : null; + } + + @Override +- public void setPlacedBy(Level level, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { +- BlockPos blockPos = pos.above(); +- level.setBlock(blockPos, copyWaterloggedFrom(level, blockPos, this.defaultBlockState().setValue(HALF, DoubleBlockHalf.UPPER)), 3); ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, LivingEntity placer, ItemStack stack) { ++ BlockPos blockposition1 = pos.above(); ++ ++ level.setBlock(blockposition1, copyWaterloggedFrom(level, blockposition1, (IBlockData) this.defaultBlockState().setValue(DoublePlantBlock.HALF, BlockPropertyDoubleBlockHalf.UPPER)), 3); + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { +- if (state.getValue(HALF) != DoubleBlockHalf.UPPER) { ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ if (state.getValue(DoublePlantBlock.HALF) != BlockPropertyDoubleBlockHalf.UPPER) { + return super.canSurvive(state, level, pos); + } else { +- BlockState blockState = level.getBlockState(pos.below()); +- return blockState.is(this) && blockState.getValue(HALF) == DoubleBlockHalf.LOWER; ++ IBlockData iblockdata1 = level.getBlockState(pos.below()); ++ ++ return iblockdata1.is((Block) this) && iblockdata1.getValue(DoublePlantBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER; + } + } + +- public static void placeAt(LevelAccessor level, BlockState state, BlockPos pos, int flags) { +- BlockPos blockPos = pos.above(); +- level.setBlock(pos, copyWaterloggedFrom(level, pos, state.setValue(HALF, DoubleBlockHalf.LOWER)), flags); +- level.setBlock(blockPos, copyWaterloggedFrom(level, blockPos, state.setValue(HALF, DoubleBlockHalf.UPPER)), flags); ++ public static void placeAt(LevelAccessor level, IBlockData state, BlockPos pos, int flags) { ++ BlockPos blockposition1 = pos.above(); ++ ++ level.setBlock(pos, copyWaterloggedFrom(level, pos, (IBlockData) state.setValue(DoublePlantBlock.HALF, BlockPropertyDoubleBlockHalf.LOWER)), flags); ++ level.setBlock(blockposition1, copyWaterloggedFrom(level, blockposition1, (IBlockData) state.setValue(DoublePlantBlock.HALF, BlockPropertyDoubleBlockHalf.UPPER)), flags); + } + +- public static BlockState copyWaterloggedFrom(LevelReader level, BlockPos pos, BlockState state) { +- return state.hasProperty(BlockStateProperties.WATERLOGGED) +- ? state.setValue(BlockStateProperties.WATERLOGGED, Boolean.valueOf(level.isWaterAt(pos))) +- : state; ++ public static IBlockData copyWaterloggedFrom(LevelReader level, BlockPos pos, IBlockData state) { ++ return state.hasProperty(BlockStateProperties.WATERLOGGED) ? (IBlockData) state.setValue(BlockStateProperties.WATERLOGGED, level.isWaterAt(pos)) : state; + } + + @Override +- public BlockState playerWillDestroy(Level level, BlockPos blockPos, BlockState blockState, Player player) { +- if (!level.isClientSide) { +- if (player.isCreative()) { +- preventDropFromBottomPart(level, blockPos, blockState, player); ++ public IBlockData playerWillDestroy(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ if (!world.isClientSide) { ++ if (entityhuman.isCreative()) { ++ preventDropFromBottomPart(world, blockposition, iblockdata, entityhuman); + } else { +- dropResources(blockState, level, blockPos, null, player, player.getMainHandItem()); ++ dropResources(iblockdata, world, blockposition, (BlockEntity) null, entityhuman, entityhuman.getMainHandItem()); + } + } + +- return super.playerWillDestroy(level, blockPos, blockState, player); ++ return super.playerWillDestroy(world, blockposition, iblockdata, entityhuman); + } + + @Override +- public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity te, ItemStack stack) { ++ public void playerDestroy(Level level, Player player, BlockPos pos, IBlockData state, @Nullable BlockEntity te, ItemStack stack) { + super.playerDestroy(level, player, pos, Blocks.AIR.defaultBlockState(), te, stack); + } + +- protected static void preventDropFromBottomPart(Level level, BlockPos blockPos, BlockState blockState, Player player) { +- DoubleBlockHalf doubleBlockHalf = blockState.getValue(HALF); +- if (doubleBlockHalf == DoubleBlockHalf.UPPER) { +- BlockPos blockPos1 = blockPos.below(); +- BlockState blockState1 = level.getBlockState(blockPos1); +- if (blockState1.is(blockState.getBlock()) && blockState1.getValue(HALF) == DoubleBlockHalf.LOWER) { +- BlockState blockState2 = blockState1.getFluidState().is(Fluids.WATER) ? Blocks.WATER.defaultBlockState() : Blocks.AIR.defaultBlockState(); +- level.setBlock(blockPos1, blockState2, 35); +- level.levelEvent(player, 2001, blockPos1, Block.getId(blockState1)); ++ protected static void preventDropFromBottomPart(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, blockposition).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ BlockPropertyDoubleBlockHalf blockpropertydoubleblockhalf = (BlockPropertyDoubleBlockHalf) iblockdata.getValue(DoublePlantBlock.HALF); ++ ++ if (blockpropertydoubleblockhalf == BlockPropertyDoubleBlockHalf.UPPER) { ++ BlockPos blockposition1 = blockposition.below(); ++ IBlockData iblockdata1 = world.getBlockState(blockposition1); ++ ++ if (iblockdata1.is(iblockdata.getBlock()) && iblockdata1.getValue(DoublePlantBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER) { ++ IBlockData iblockdata2 = iblockdata1.getFluidState().is((Fluid) Fluids.WATER) ? Blocks.WATER.defaultBlockState() : Blocks.AIR.defaultBlockState(); ++ ++ world.setBlock(blockposition1, iblockdata2, 35); ++ world.levelEvent(entityhuman, 2001, blockposition1, Block.getId(iblockdata1)); + } + } ++ + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(HALF); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(DoublePlantBlock.HALF); + } + + @Override +- public long getSeed(BlockState state, BlockPos pos) { +- return Mth.getSeed(pos.getX(), pos.below(state.getValue(HALF) == DoubleBlockHalf.LOWER ? 0 : 1).getY(), pos.getZ()); ++ public long getSeed(IBlockData state, BlockPos pos) { ++ return Mth.getSeed(pos.getX(), pos.below(state.getValue(DoublePlantBlock.HALF) == BlockPropertyDoubleBlockHalf.LOWER ? 0 : 1).getY(), pos.getZ()); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/DragonEggBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/DragonEggBlock.java.patch new file mode 100644 index 0000000000..aefc8a6286 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/DragonEggBlock.java.patch @@ -0,0 +1,127 @@ +--- a/net/minecraft/world/level/block/DragonEggBlock.java ++++ b/net/minecraft/world/level/block/DragonEggBlock.java +@@ -4,26 +4,28 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.border.WorldBorder; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockFromToEvent; // CraftBukkit + + public class DragonEggBlock extends FallingBlock { ++ + public static final MapCodec CODEC = simpleCodec(DragonEggBlock::new); +- protected static final VoxelShape SHAPE = Block.box(1.0, 0.0, 1.0, 15.0, 16.0, 15.0); ++ protected static final VoxelShape SHAPE = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 16.0D, 15.0D); + + @Override + public MapCodec codec() { +- return CODEC; ++ return DragonEggBlock.CODEC; + } + + public DragonEggBlock(BlockBehaviour.Properties properties) { +@@ -31,50 +33,61 @@ + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPE; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return DragonEggBlock.SHAPE; + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + this.teleport(state, level, pos); + return InteractionResult.sidedSuccess(level.isClientSide); + } + + @Override +- public void attack(BlockState state, Level level, BlockPos pos, Player player) { ++ public void attack(IBlockData state, Level level, BlockPos pos, Player player) { + this.teleport(state, level, pos); + } + +- private void teleport(BlockState state, Level level, BlockPos pos) { +- WorldBorder worldBorder = level.getWorldBorder(); ++ private void teleport(IBlockData state, Level level, BlockPos pos) { ++ WorldBorder worldborder = level.getWorldBorder(); + +- for (int i = 0; i < 1000; i++) { +- BlockPos blockPos = pos.offset( +- level.random.nextInt(16) - level.random.nextInt(16), +- level.random.nextInt(8) - level.random.nextInt(8), +- level.random.nextInt(16) - level.random.nextInt(16) +- ); +- if (level.getBlockState(blockPos).isAir() && worldBorder.isWithinBounds(blockPos)) { ++ for (int i = 0; i < 1000; ++i) { ++ BlockPos blockposition1 = pos.offset(level.random.nextInt(16) - level.random.nextInt(16), level.random.nextInt(8) - level.random.nextInt(8), level.random.nextInt(16) - level.random.nextInt(16)); ++ ++ if (level.getBlockState(blockposition1).isAir() && worldborder.isWithinBounds(blockposition1)) { ++ // CraftBukkit start ++ org.bukkit.block.Block from = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ org.bukkit.block.Block to = level.getWorld().getBlockAt(blockposition1.getX(), blockposition1.getY(), blockposition1.getZ()); ++ BlockFromToEvent event = new BlockFromToEvent(from, to); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ blockposition1 = new BlockPos(event.getToBlock().getX(), event.getToBlock().getY(), event.getToBlock().getZ()); ++ // CraftBukkit end + if (level.isClientSide) { +- for (int i1 = 0; i1 < 128; i1++) { +- double randomDouble = level.random.nextDouble(); ++ for (int j = 0; j < 128; ++j) { ++ double d0 = level.random.nextDouble(); + float f = (level.random.nextFloat() - 0.5F) * 0.2F; + float f1 = (level.random.nextFloat() - 0.5F) * 0.2F; + float f2 = (level.random.nextFloat() - 0.5F) * 0.2F; +- double d = Mth.lerp(randomDouble, (double)blockPos.getX(), (double)pos.getX()) + (level.random.nextDouble() - 0.5) + 0.5; +- double d1 = Mth.lerp(randomDouble, (double)blockPos.getY(), (double)pos.getY()) + level.random.nextDouble() - 0.5; +- double d2 = Mth.lerp(randomDouble, (double)blockPos.getZ(), (double)pos.getZ()) + (level.random.nextDouble() - 0.5) + 0.5; +- level.addParticle(ParticleTypes.PORTAL, d, d1, d2, (double)f, (double)f1, (double)f2); ++ double d1 = Mth.lerp(d0, (double) blockposition1.getX(), (double) pos.getX()) + (level.random.nextDouble() - 0.5D) + 0.5D; ++ double d2 = Mth.lerp(d0, (double) blockposition1.getY(), (double) pos.getY()) + level.random.nextDouble() - 0.5D; ++ double d3 = Mth.lerp(d0, (double) blockposition1.getZ(), (double) pos.getZ()) + (level.random.nextDouble() - 0.5D) + 0.5D; ++ ++ level.addParticle(ParticleTypes.PORTAL, d1, d2, d3, (double) f, (double) f1, (double) f2); + } + } else { +- level.setBlock(blockPos, state, 2); ++ level.setBlock(blockposition1, state, 2); + level.removeBlock(pos, false); + } + + return; + } + } ++ + } + + @Override +@@ -83,7 +96,7 @@ + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/DropExperienceBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/DropExperienceBlock.java.patch new file mode 100644 index 0000000000..bf7056797a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/DropExperienceBlock.java.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/world/level/block/DropExperienceBlock.java ++++ b/net/minecraft/world/level/block/DropExperienceBlock.java +@@ -2,38 +2,45 @@ + + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import net.minecraft.core.BlockPos; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.valueproviders.IntProvider; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public class DropExperienceBlock extends Block { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group( +- IntProvider.codec(0, 10).fieldOf("experience").forGetter(dropExperienceBlock -> dropExperienceBlock.xpRange), propertiesCodec() +- ) +- .apply(instance, DropExperienceBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(IntProvider.codec(0, 10).fieldOf("experience").forGetter((dropexperienceblock) -> { ++ return dropexperienceblock.xpRange; ++ }), propertiesCodec()).apply(instance, DropExperienceBlock::new); ++ }); + private final IntProvider xpRange; + + @Override + public MapCodec codec() { +- return CODEC; ++ return DropExperienceBlock.CODEC; + } + +- public DropExperienceBlock(IntProvider intProvider, BlockBehaviour.Properties properties) { +- super(properties); +- this.xpRange = intProvider; ++ public DropExperienceBlock(IntProvider intprovider, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info); ++ this.xpRange = intprovider; + } + + @Override +- public void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { + super.spawnAfterBreak(state, level, pos, stack, dropExperience); +- if (dropExperience) { +- this.tryDropExperience(level, pos, stack, this.xpRange); ++ // CraftBukkit start - Delegate to getExpDrop ++ } ++ ++ @Override ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { ++ if (flag) { ++ return this.tryDropExperience(worldserver, blockposition, itemstack, this.xpRange); + } ++ ++ return 0; ++ // CraftBukkit end + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/DropperBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/DropperBlock.java.patch new file mode 100644 index 0000000000..7ab067c899 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/DropperBlock.java.patch @@ -0,0 +1,131 @@ +--- a/net/minecraft/world/level/block/DropperBlock.java ++++ b/net/minecraft/world/level/block/DropperBlock.java +@@ -4,29 +4,34 @@ + import com.mojang.serialization.MapCodec; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.dispenser.BlockSource; + import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; + import net.minecraft.core.dispenser.DispenseItemBehavior; ++import net.minecraft.core.dispenser.SourceBlock; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.CompoundContainer; + import net.minecraft.world.Container; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.DispenserBlockEntity; +-import net.minecraft.world.level.block.entity.DropperBlockEntity; + import net.minecraft.world.level.block.entity.HopperBlockEntity; ++import net.minecraft.world.level.block.entity.TileEntityDropper; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import org.slf4j.Logger; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.inventory.InventoryMoveItemEvent; ++// CraftBukkit end + + public class DropperBlock extends DispenserBlock { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + public static final MapCodec CODEC = simpleCodec(DropperBlock::new); +- private static final DispenseItemBehavior DISPENSE_BEHAVIOUR = new DefaultDispenseItemBehavior(); ++ private static final DispenseItemBehavior DISPENSE_BEHAVIOUR = new DefaultDispenseItemBehavior(true); // CraftBukkit + + @Override + public MapCodec codec() { +- return CODEC; ++ return DropperBlock.CODEC; + } + + public DropperBlock(BlockBehaviour.Properties properties) { +@@ -35,43 +40,64 @@ + + @Override + protected DispenseItemBehavior getDispenseMethod(ItemStack stack) { +- return DISPENSE_BEHAVIOUR; ++ return DropperBlock.DISPENSE_BEHAVIOUR; + } + + @Override +- public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { +- return new DropperBlockEntity(pos, state); ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { ++ return new TileEntityDropper(pos, state); + } + + @Override +- protected void dispenseFrom(ServerLevel serverLevel, BlockState blockState, BlockPos blockPos) { +- DispenserBlockEntity dispenserBlockEntity = serverLevel.getBlockEntity(blockPos, BlockEntityType.DROPPER).orElse(null); +- if (dispenserBlockEntity == null) { +- LOGGER.warn("Ignoring dispensing attempt for Dropper without matching block entity at {}", blockPos); ++ public void dispenseFrom(ServerLevel worldserver, IBlockData iblockdata, BlockPos blockposition) { ++ DispenserBlockEntity tileentitydispenser = (DispenserBlockEntity) worldserver.getBlockEntity(blockposition, BlockEntityType.DROPPER).orElse(null); // CraftBukkit - decompile error ++ ++ if (tileentitydispenser == null) { ++ DropperBlock.LOGGER.warn("Ignoring dispensing attempt for Dropper without matching block entity at {}", blockposition); + } else { +- BlockSource blockSource = new BlockSource(serverLevel, blockPos, blockState, dispenserBlockEntity); +- int randomSlot = dispenserBlockEntity.getRandomSlot(serverLevel.random); +- if (randomSlot < 0) { +- serverLevel.levelEvent(1001, blockPos, 0); ++ SourceBlock sourceblock = new SourceBlock(worldserver, blockposition, iblockdata, tileentitydispenser); ++ int i = tileentitydispenser.getRandomSlot(worldserver.random); ++ ++ if (i < 0) { ++ worldserver.levelEvent(1001, blockposition, 0); + } else { +- ItemStack item = dispenserBlockEntity.getItem(randomSlot); +- if (!item.isEmpty()) { +- Direction direction = serverLevel.getBlockState(blockPos).getValue(FACING); +- Container containerAt = HopperBlockEntity.getContainerAt(serverLevel, blockPos.relative(direction)); +- ItemStack itemStack; +- if (containerAt == null) { +- itemStack = DISPENSE_BEHAVIOUR.dispense(blockSource, item); ++ ItemStack itemstack = tileentitydispenser.getItem(i); ++ ++ if (!itemstack.isEmpty()) { ++ Direction enumdirection = (Direction) worldserver.getBlockState(blockposition).getValue(DropperBlock.FACING); ++ Container iinventory = HopperBlockEntity.getContainerAt(worldserver, blockposition.relative(enumdirection)); ++ ItemStack itemstack1; ++ ++ if (iinventory == null) { ++ itemstack1 = DropperBlock.DISPENSE_BEHAVIOUR.dispense(sourceblock, itemstack); + } else { +- itemStack = HopperBlockEntity.addItem(dispenserBlockEntity, containerAt, item.copy().split(1), direction.getOpposite()); +- if (itemStack.isEmpty()) { +- itemStack = item.copy(); +- itemStack.shrink(1); ++ // CraftBukkit start - Fire event when pushing items into other inventories ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(itemstack.copy().split(1)); ++ ++ org.bukkit.inventory.Inventory destinationInventory; ++ // Have to special case large chests as they work oddly ++ if (iinventory instanceof CompoundContainer) { ++ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory); + } else { +- itemStack = item.copy(); ++ destinationInventory = iinventory.getOwner().getInventory(); + } ++ ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(tileentitydispenser.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true); ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ itemstack1 = HopperBlockEntity.addItem(tileentitydispenser, iinventory, CraftItemStack.asNMSCopy(event.getItem()), enumdirection.getOpposite()); ++ if (event.getItem().equals(oitemstack) && itemstack1.isEmpty()) { ++ // CraftBukkit end ++ itemstack1 = itemstack.copy(); ++ itemstack1.shrink(1); ++ } else { ++ itemstack1 = itemstack.copy(); ++ } + } + +- dispenserBlockEntity.setItem(randomSlot, itemStack); ++ tileentitydispenser.setItem(i, itemstack1); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/EndPortalBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/EndPortalBlock.java.patch new file mode 100644 index 0000000000..f58670efd6 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/EndPortalBlock.java.patch @@ -0,0 +1,118 @@ +--- a/net/minecraft/world/level/block/EndPortalBlock.java ++++ b/net/minecraft/world/level/block/EndPortalBlock.java +@@ -5,6 +5,7 @@ + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.resources.ResourceKey; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.RandomSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.item.ItemStack; +@@ -14,20 +15,25 @@ + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.TheEndPortalBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.entity.EntityPortalEnterEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++// CraftBukkit end + + public class EndPortalBlock extends BaseEntityBlock { ++ + public static final MapCodec CODEC = simpleCodec(EndPortalBlock::new); +- protected static final VoxelShape SHAPE = Block.box(0.0, 6.0, 0.0, 16.0, 12.0, 16.0); ++ protected static final VoxelShape SHAPE = Block.box(0.0D, 6.0D, 0.0D, 16.0D, 12.0D, 16.0D); + + @Override + public MapCodec codec() { +- return CODEC; ++ return EndPortalBlock.CODEC; + } + + protected EndPortalBlock(BlockBehaviour.Properties properties) { +@@ -35,49 +41,55 @@ + } + + @Override +- public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { + return new TheEndPortalBlockEntity(pos, state); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPE; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return EndPortalBlock.SHAPE; + } + + @Override +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { +- if (level instanceof ServerLevel +- && entity.canChangeDimensions() +- && Shapes.joinIsNotEmpty( +- Shapes.create(entity.getBoundingBox().move((double)(-pos.getX()), (double)(-pos.getY()), (double)(-pos.getZ()))), +- state.getShape(level, pos), +- BooleanOp.AND +- )) { +- ResourceKey resourceKey = level.dimension() == Level.END ? Level.OVERWORLD : Level.END; +- ServerLevel level1 = ((ServerLevel)level).getServer().getLevel(resourceKey); +- if (level1 == null) { +- return; ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ if (level instanceof ServerLevel && entity.canChangeDimensions() && Shapes.joinIsNotEmpty(Shapes.create(entity.getBoundingBox().move((double) (-pos.getX()), (double) (-pos.getY()), (double) (-pos.getZ()))), state.getShape(level, pos), BooleanOp.AND)) { ++ ResourceKey resourcekey = level.getTypeKey() == LevelStem.END ? Level.OVERWORLD : Level.END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends ++ ServerLevel worldserver = ((ServerLevel) level).getServer().getLevel(resourcekey); ++ ++ if (worldserver == null) { ++ // return; // CraftBukkit - always fire event in case plugins wish to change it + } + +- entity.changeDimension(level1); ++ // CraftBukkit start - Entity in portal ++ EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(level.getWorld(), pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (entity instanceof ServerPlayer) { ++ ((ServerPlayer) entity).changeDimension(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); ++ return; ++ } ++ // CraftBukkit end ++ entity.changeDimension(worldserver); + } ++ + } + + @Override +- public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { +- double d = (double)pos.getX() + random.nextDouble(); +- double d1 = (double)pos.getY() + 0.8; +- double d2 = (double)pos.getZ() + random.nextDouble(); +- level.addParticle(ParticleTypes.SMOKE, d, d1, d2, 0.0, 0.0, 0.0); ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ double d0 = (double) pos.getX() + random.nextDouble(); ++ double d1 = (double) pos.getY() + 0.8D; ++ double d2 = (double) pos.getZ() + random.nextDouble(); ++ ++ level.addParticle(ParticleTypes.SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + + @Override +- public ItemStack getCloneItemStack(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { ++ public ItemStack getCloneItemStack(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { + return ItemStack.EMPTY; + } + + @Override +- public boolean canBeReplaced(BlockState state, Fluid fluid) { ++ public boolean canBeReplaced(IBlockData state, Fluid fluid) { + return false; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/FarmBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/FarmBlock.java.patch new file mode 100644 index 0000000000..c4f556126e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/FarmBlock.java.patch @@ -0,0 +1,211 @@ +--- a/net/minecraft/world/level/block/FarmBlock.java ++++ b/net/minecraft/world/level/block/FarmBlock.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.block; + + import com.mojang.serialization.MapCodec; ++import java.util.Iterator; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +@@ -19,101 +20,128 @@ + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.piston.MovingPistonBlock; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.level.gameevent.GameEvent; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.event.entity.EntityInteractEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class FarmBlock extends Block { ++ + public static final MapCodec CODEC = simpleCodec(FarmBlock::new); + public static final IntegerProperty MOISTURE = BlockStateProperties.MOISTURE; +- protected static final VoxelShape SHAPE = Block.box(0.0, 0.0, 0.0, 16.0, 15.0, 16.0); ++ protected static final VoxelShape SHAPE = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 15.0D, 16.0D); + public static final int MAX_MOISTURE = 7; + + @Override + public MapCodec codec() { +- return CODEC; ++ return FarmBlock.CODEC; + } + + protected FarmBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(MOISTURE, Integer.valueOf(0))); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(FarmBlock.MOISTURE, 0)); + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { + if (facing == Direction.UP && !state.canSurvive(level, currentPos)) { +- level.scheduleTick(currentPos, this, 1); ++ level.scheduleTick(currentPos, (Block) this, 1); + } + + return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { +- BlockState blockState = level.getBlockState(pos.above()); +- return !blockState.isSolid() || blockState.getBlock() instanceof FenceGateBlock || blockState.getBlock() instanceof MovingPistonBlock; ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ IBlockData iblockdata1 = level.getBlockState(pos.above()); ++ ++ return !iblockdata1.isSolid() || iblockdata1.getBlock() instanceof FenceGateBlock || iblockdata1.getBlock() instanceof MovingPistonBlock; + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- return !this.defaultBlockState().canSurvive(context.getLevel(), context.getClickedPos()) +- ? Blocks.DIRT.defaultBlockState() +- : super.getStateForPlacement(context); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return !this.defaultBlockState().canSurvive(context.getLevel(), context.getClickedPos()) ? Blocks.DIRT.defaultBlockState() : super.getStateForPlacement(context); + } + + @Override +- public boolean useShapeForLightOcclusion(BlockState state) { ++ public boolean useShapeForLightOcclusion(IBlockData state) { + return true; + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPE; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return FarmBlock.SHAPE; + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (!state.canSurvive(level, pos)) { +- turnToDirt(null, state, level, pos); ++ turnToDirt((Entity) null, state, level, pos); + } ++ + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- int i = state.getValue(MOISTURE); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ int i = (Integer) state.getValue(FarmBlock.MOISTURE); ++ + if (!isNearWater(level, pos) && !level.isRainingAt(pos.above())) { + if (i > 0) { +- level.setBlock(pos, state.setValue(MOISTURE, Integer.valueOf(i - 1)), 2); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleMoistureChangeEvent(level, pos, (IBlockData) state.setValue(FarmBlock.MOISTURE, i - 1), 2); // CraftBukkit + } else if (!shouldMaintainFarmland(level, pos)) { +- turnToDirt(null, state, level, pos); ++ turnToDirt((Entity) null, state, level, pos); + } + } else if (i < 7) { +- level.setBlock(pos, state.setValue(MOISTURE, Integer.valueOf(7)), 2); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleMoistureChangeEvent(level, pos, (IBlockData) state.setValue(FarmBlock.MOISTURE, 7), 2); // CraftBukkit + } ++ + } + + @Override +- public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, float fallDistance) { +- if (!level.isClientSide +- && level.random.nextFloat() < fallDistance - 0.5F +- && entity instanceof LivingEntity +- && (entity instanceof Player || level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) +- && entity.getBbWidth() * entity.getBbWidth() * entity.getBbHeight() > 0.512F) { ++ public void fallOn(Level level, IBlockData state, BlockPos pos, Entity entity, float fallDistance) { ++ super.fallOn(level, state, pos, entity, fallDistance); // CraftBukkit - moved here as game rules / events shouldn't affect fall damage. ++ if (!level.isClientSide && level.random.nextFloat() < fallDistance - 0.5F && entity instanceof LivingEntity && (entity instanceof Player || level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && entity.getBbWidth() * entity.getBbWidth() * entity.getBbHeight() > 0.512F) { ++ // CraftBukkit start - Interact soil ++ org.bukkit.event.Cancellable cancellable; ++ if (entity instanceof Player) { ++ cancellable = CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ if (cancellable.isCancelled()) { ++ return; ++ } ++ ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.DIRT.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end + turnToDirt(entity, state, level, pos); + } + +- super.fallOn(level, state, pos, entity, fallDistance); ++ // super.fallOn(world, iblockdata, blockposition, entity, f); // CraftBukkit - moved up + } + +- public static void turnToDirt(@Nullable Entity entity, BlockState state, Level level, BlockPos pos) { +- BlockState blockState = pushEntitiesUp(state, Blocks.DIRT.defaultBlockState(), level, pos); +- level.setBlockAndUpdate(pos, blockState); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, blockState)); ++ public static void turnToDirt(@Nullable Entity entity, IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ if (CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ IBlockData iblockdata1 = pushEntitiesUp(state, Blocks.DIRT.defaultBlockState(), level, pos); ++ ++ level.setBlockAndUpdate(pos, iblockdata1); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, iblockdata1)); + } + + private static boolean shouldMaintainFarmland(BlockGetter level, BlockPos pos) { +@@ -121,22 +149,28 @@ + } + + private static boolean isNearWater(LevelReader level, BlockPos pos) { +- for (BlockPos blockPos : BlockPos.betweenClosed(pos.offset(-4, 0, -4), pos.offset(4, 1, 4))) { +- if (level.getFluidState(blockPos).is(FluidTags.WATER)) { +- return true; ++ Iterator iterator = BlockPos.betweenClosed(pos.offset(-4, 0, -4), pos.offset(4, 1, 4)).iterator(); ++ ++ BlockPos blockposition1; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return false; + } +- } + +- return false; ++ blockposition1 = (BlockPos) iterator.next(); ++ } while (!level.getFluidState(blockposition1).is(FluidTags.WATER)); ++ ++ return true; + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(MOISTURE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(FarmBlock.MOISTURE); + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/FenceGateBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/FenceGateBlock.java.patch new file mode 100644 index 0000000000..2690ba35f6 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/FenceGateBlock.java.patch @@ -0,0 +1,323 @@ +--- a/net/minecraft/world/level/block/FenceGateBlock.java ++++ b/net/minecraft/world/level/block/FenceGateBlock.java +@@ -2,14 +2,14 @@ + + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import java.util.function.BiConsumer; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.sounds.SoundSource; + import net.minecraft.tags.BlockTags; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.context.BlockPlaceContext; +@@ -18,207 +18,185 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.block.state.properties.WoodType; + import net.minecraft.world.level.gameevent.GameEvent; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; + + public class FenceGateBlock extends HorizontalDirectionalBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group(WoodType.CODEC.fieldOf("wood_type").forGetter(fenceGateBlock -> fenceGateBlock.type), propertiesCodec()) +- .apply(instance, FenceGateBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(WoodType.CODEC.fieldOf("wood_type").forGetter((blockfencegate) -> { ++ return blockfencegate.type; ++ }), propertiesCodec()).apply(instance, FenceGateBlock::new); ++ }); + public static final BooleanProperty OPEN = BlockStateProperties.OPEN; + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + public static final BooleanProperty IN_WALL = BlockStateProperties.IN_WALL; +- protected static final VoxelShape Z_SHAPE = Block.box(0.0, 0.0, 6.0, 16.0, 16.0, 10.0); +- protected static final VoxelShape X_SHAPE = Block.box(6.0, 0.0, 0.0, 10.0, 16.0, 16.0); +- protected static final VoxelShape Z_SHAPE_LOW = Block.box(0.0, 0.0, 6.0, 16.0, 13.0, 10.0); +- protected static final VoxelShape X_SHAPE_LOW = Block.box(6.0, 0.0, 0.0, 10.0, 13.0, 16.0); +- protected static final VoxelShape Z_COLLISION_SHAPE = Block.box(0.0, 0.0, 6.0, 16.0, 24.0, 10.0); +- protected static final VoxelShape X_COLLISION_SHAPE = Block.box(6.0, 0.0, 0.0, 10.0, 24.0, 16.0); +- protected static final VoxelShape Z_SUPPORT_SHAPE = Block.box(0.0, 5.0, 6.0, 16.0, 24.0, 10.0); +- protected static final VoxelShape X_SUPPORT_SHAPE = Block.box(6.0, 5.0, 0.0, 10.0, 24.0, 16.0); +- protected static final VoxelShape Z_OCCLUSION_SHAPE = Shapes.or(Block.box(0.0, 5.0, 7.0, 2.0, 16.0, 9.0), Block.box(14.0, 5.0, 7.0, 16.0, 16.0, 9.0)); +- protected static final VoxelShape X_OCCLUSION_SHAPE = Shapes.or(Block.box(7.0, 5.0, 0.0, 9.0, 16.0, 2.0), Block.box(7.0, 5.0, 14.0, 9.0, 16.0, 16.0)); +- protected static final VoxelShape Z_OCCLUSION_SHAPE_LOW = Shapes.or(Block.box(0.0, 2.0, 7.0, 2.0, 13.0, 9.0), Block.box(14.0, 2.0, 7.0, 16.0, 13.0, 9.0)); +- protected static final VoxelShape X_OCCLUSION_SHAPE_LOW = Shapes.or(Block.box(7.0, 2.0, 0.0, 9.0, 13.0, 2.0), Block.box(7.0, 2.0, 14.0, 9.0, 13.0, 16.0)); ++ protected static final VoxelShape Z_SHAPE = Block.box(0.0D, 0.0D, 6.0D, 16.0D, 16.0D, 10.0D); ++ protected static final VoxelShape X_SHAPE = Block.box(6.0D, 0.0D, 0.0D, 10.0D, 16.0D, 16.0D); ++ protected static final VoxelShape Z_SHAPE_LOW = Block.box(0.0D, 0.0D, 6.0D, 16.0D, 13.0D, 10.0D); ++ protected static final VoxelShape X_SHAPE_LOW = Block.box(6.0D, 0.0D, 0.0D, 10.0D, 13.0D, 16.0D); ++ protected static final VoxelShape Z_COLLISION_SHAPE = Block.box(0.0D, 0.0D, 6.0D, 16.0D, 24.0D, 10.0D); ++ protected static final VoxelShape X_COLLISION_SHAPE = Block.box(6.0D, 0.0D, 0.0D, 10.0D, 24.0D, 16.0D); ++ protected static final VoxelShape Z_SUPPORT_SHAPE = Block.box(0.0D, 5.0D, 6.0D, 16.0D, 24.0D, 10.0D); ++ protected static final VoxelShape X_SUPPORT_SHAPE = Block.box(6.0D, 5.0D, 0.0D, 10.0D, 24.0D, 16.0D); ++ protected static final VoxelShape Z_OCCLUSION_SHAPE = Shapes.or(Block.box(0.0D, 5.0D, 7.0D, 2.0D, 16.0D, 9.0D), Block.box(14.0D, 5.0D, 7.0D, 16.0D, 16.0D, 9.0D)); ++ protected static final VoxelShape X_OCCLUSION_SHAPE = Shapes.or(Block.box(7.0D, 5.0D, 0.0D, 9.0D, 16.0D, 2.0D), Block.box(7.0D, 5.0D, 14.0D, 9.0D, 16.0D, 16.0D)); ++ protected static final VoxelShape Z_OCCLUSION_SHAPE_LOW = Shapes.or(Block.box(0.0D, 2.0D, 7.0D, 2.0D, 13.0D, 9.0D), Block.box(14.0D, 2.0D, 7.0D, 16.0D, 13.0D, 9.0D)); ++ protected static final VoxelShape X_OCCLUSION_SHAPE_LOW = Shapes.or(Block.box(7.0D, 2.0D, 0.0D, 9.0D, 13.0D, 2.0D), Block.box(7.0D, 2.0D, 14.0D, 9.0D, 13.0D, 16.0D)); + private final WoodType type; + + @Override + public MapCodec codec() { +- return CODEC; ++ return FenceGateBlock.CODEC; + } + +- public FenceGateBlock(WoodType woodType, BlockBehaviour.Properties properties) { +- super(properties.sound(woodType.soundType())); +- this.type = woodType; +- this.registerDefaultState( +- this.stateDefinition +- .any() +- .setValue(OPEN, Boolean.valueOf(false)) +- .setValue(POWERED, Boolean.valueOf(false)) +- .setValue(IN_WALL, Boolean.valueOf(false)) +- ); ++ public FenceGateBlock(WoodType blockpropertywood, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info.sound(blockpropertywood.soundType())); ++ this.type = blockpropertywood; ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(FenceGateBlock.OPEN, false)).setValue(FenceGateBlock.POWERED, false)).setValue(FenceGateBlock.IN_WALL, false)); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- if (state.getValue(IN_WALL)) { +- return state.getValue(FACING).getAxis() == Direction.Axis.X ? X_SHAPE_LOW : Z_SHAPE_LOW; +- } else { +- return state.getValue(FACING).getAxis() == Direction.Axis.X ? X_SHAPE : Z_SHAPE; +- } ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (Boolean) state.getValue(FenceGateBlock.IN_WALL) ? (((Direction) state.getValue(FenceGateBlock.FACING)).getAxis() == Direction.Axis.X ? FenceGateBlock.X_SHAPE_LOW : FenceGateBlock.Z_SHAPE_LOW) : (((Direction) state.getValue(FenceGateBlock.FACING)).getAxis() == Direction.Axis.X ? FenceGateBlock.X_SHAPE : FenceGateBlock.Z_SHAPE); + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- Direction.Axis axis = facing.getAxis(); +- if (state.getValue(FACING).getClockWise().getAxis() != axis) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ Direction.Axis enumdirection_enumaxis = facing.getAxis(); ++ ++ if (((Direction) state.getValue(FenceGateBlock.FACING)).getClockWise().getAxis() != enumdirection_enumaxis) { + return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } else { + boolean flag = this.isWall(facingState) || this.isWall(level.getBlockState(currentPos.relative(facing.getOpposite()))); +- return state.setValue(IN_WALL, Boolean.valueOf(flag)); ++ ++ return (IBlockData) state.setValue(FenceGateBlock.IN_WALL, flag); + } + } + + @Override +- public VoxelShape getBlockSupportShape(BlockState state, BlockGetter level, BlockPos pos) { +- if (state.getValue(OPEN)) { +- return Shapes.empty(); +- } else { +- return state.getValue(FACING).getAxis() == Direction.Axis.Z ? Z_SUPPORT_SHAPE : X_SUPPORT_SHAPE; +- } ++ public VoxelShape getBlockSupportShape(IBlockData state, BlockGetter level, BlockPos pos) { ++ return (Boolean) state.getValue(FenceGateBlock.OPEN) ? Shapes.empty() : (((Direction) state.getValue(FenceGateBlock.FACING)).getAxis() == Direction.Axis.Z ? FenceGateBlock.Z_SUPPORT_SHAPE : FenceGateBlock.X_SUPPORT_SHAPE); + } + + @Override +- public VoxelShape getCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- if (state.getValue(OPEN)) { +- return Shapes.empty(); +- } else { +- return state.getValue(FACING).getAxis() == Direction.Axis.Z ? Z_COLLISION_SHAPE : X_COLLISION_SHAPE; +- } ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (Boolean) state.getValue(FenceGateBlock.OPEN) ? Shapes.empty() : (((Direction) state.getValue(FenceGateBlock.FACING)).getAxis() == Direction.Axis.Z ? FenceGateBlock.Z_COLLISION_SHAPE : FenceGateBlock.X_COLLISION_SHAPE); + } + + @Override +- public VoxelShape getOcclusionShape(BlockState state, BlockGetter level, BlockPos pos) { +- if (state.getValue(IN_WALL)) { +- return state.getValue(FACING).getAxis() == Direction.Axis.X ? X_OCCLUSION_SHAPE_LOW : Z_OCCLUSION_SHAPE_LOW; +- } else { +- return state.getValue(FACING).getAxis() == Direction.Axis.X ? X_OCCLUSION_SHAPE : Z_OCCLUSION_SHAPE; +- } ++ public VoxelShape getOcclusionShape(IBlockData state, BlockGetter level, BlockPos pos) { ++ return (Boolean) state.getValue(FenceGateBlock.IN_WALL) ? (((Direction) state.getValue(FenceGateBlock.FACING)).getAxis() == Direction.Axis.X ? FenceGateBlock.X_OCCLUSION_SHAPE_LOW : FenceGateBlock.Z_OCCLUSION_SHAPE_LOW) : (((Direction) state.getValue(FenceGateBlock.FACING)).getAxis() == Direction.Axis.X ? FenceGateBlock.X_OCCLUSION_SHAPE : FenceGateBlock.Z_OCCLUSION_SHAPE); + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + switch (type) { + case LAND: +- return state.getValue(OPEN); ++ return (Boolean) state.getValue(FenceGateBlock.OPEN); + case WATER: + return false; + case AIR: +- return state.getValue(OPEN); ++ return (Boolean) state.getValue(FenceGateBlock.OPEN); + default: + return false; + } + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- Level level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- boolean hasNeighborSignal = level.hasNeighborSignal(clickedPos); +- Direction horizontalDirection = context.getHorizontalDirection(); +- Direction.Axis axis = horizontalDirection.getAxis(); +- boolean flag = axis == Direction.Axis.Z && (this.isWall(level.getBlockState(clickedPos.west())) || this.isWall(level.getBlockState(clickedPos.east()))) +- || axis == Direction.Axis.X && (this.isWall(level.getBlockState(clickedPos.north())) || this.isWall(level.getBlockState(clickedPos.south()))); +- return this.defaultBlockState() +- .setValue(FACING, horizontalDirection) +- .setValue(OPEN, Boolean.valueOf(hasNeighborSignal)) +- .setValue(POWERED, Boolean.valueOf(hasNeighborSignal)) +- .setValue(IN_WALL, Boolean.valueOf(flag)); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ boolean flag = world.hasNeighborSignal(blockposition); ++ Direction enumdirection = context.getHorizontalDirection(); ++ Direction.Axis enumdirection_enumaxis = enumdirection.getAxis(); ++ boolean flag1 = enumdirection_enumaxis == Direction.Axis.Z && (this.isWall(world.getBlockState(blockposition.west())) || this.isWall(world.getBlockState(blockposition.east()))) || enumdirection_enumaxis == Direction.Axis.X && (this.isWall(world.getBlockState(blockposition.north())) || this.isWall(world.getBlockState(blockposition.south()))); ++ ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(FenceGateBlock.FACING, enumdirection)).setValue(FenceGateBlock.OPEN, flag)).setValue(FenceGateBlock.POWERED, flag)).setValue(FenceGateBlock.IN_WALL, flag1); + } + +- private boolean isWall(BlockState state) { ++ private boolean isWall(IBlockData state) { + return state.is(BlockTags.WALLS); + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { +- if (state.getValue(OPEN)) { +- state = state.setValue(OPEN, Boolean.valueOf(false)); ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ if ((Boolean) state.getValue(FenceGateBlock.OPEN)) { ++ state = (IBlockData) state.setValue(FenceGateBlock.OPEN, false); + level.setBlock(pos, state, 10); + } else { +- Direction direction = player.getDirection(); +- if (state.getValue(FACING) == direction.getOpposite()) { +- state = state.setValue(FACING, direction); ++ Direction enumdirection = player.getDirection(); ++ ++ if (state.getValue(FenceGateBlock.FACING) == enumdirection.getOpposite()) { ++ state = (IBlockData) state.setValue(FenceGateBlock.FACING, enumdirection); + } + +- state = state.setValue(OPEN, Boolean.valueOf(true)); ++ state = (IBlockData) state.setValue(FenceGateBlock.OPEN, true); + level.setBlock(pos, state, 10); + } + +- boolean flag = state.getValue(OPEN); +- level.playSound( +- player, pos, flag ? this.type.fenceGateOpen() : this.type.fenceGateClose(), SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.1F + 0.9F +- ); +- level.gameEvent(player, flag ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); ++ boolean flag = (Boolean) state.getValue(FenceGateBlock.OPEN); ++ ++ level.playSound(player, pos, flag ? this.type.fenceGateOpen() : this.type.fenceGateClose(), SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.1F + 0.9F); ++ level.gameEvent((Entity) player, flag ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); + return InteractionResult.sidedSuccess(level.isClientSide); + } + + @Override +- public void onExplosionHit(BlockState blockState, Level level, BlockPos blockPos, Explosion explosion, BiConsumer biConsumer) { +- if (explosion.getBlockInteraction() == Explosion.BlockInteraction.TRIGGER_BLOCK && !level.isClientSide() && !blockState.getValue(POWERED)) { +- boolean flag = blockState.getValue(OPEN); +- level.setBlockAndUpdate(blockPos, blockState.setValue(OPEN, Boolean.valueOf(!flag))); +- level.playSound( +- null, +- blockPos, +- flag ? this.type.fenceGateClose() : this.type.fenceGateOpen(), +- SoundSource.BLOCKS, +- 1.0F, +- level.getRandom().nextFloat() * 0.1F + 0.9F +- ); +- level.gameEvent(flag ? GameEvent.BLOCK_CLOSE : GameEvent.BLOCK_OPEN, blockPos, GameEvent.Context.of(blockState)); ++ public void onExplosionHit(IBlockData iblockdata, Level world, BlockPos blockposition, Explosion explosion, BiConsumer biconsumer) { ++ if (explosion.getBlockInteraction() == Explosion.Effect.TRIGGER_BLOCK && !world.isClientSide() && !(Boolean) iblockdata.getValue(FenceGateBlock.POWERED)) { ++ boolean flag = (Boolean) iblockdata.getValue(FenceGateBlock.OPEN); ++ ++ world.setBlockAndUpdate(blockposition, (IBlockData) iblockdata.setValue(FenceGateBlock.OPEN, !flag)); ++ world.playSound((Player) null, blockposition, flag ? this.type.fenceGateClose() : this.type.fenceGateOpen(), SoundSource.BLOCKS, 1.0F, world.getRandom().nextFloat() * 0.1F + 0.9F); ++ world.gameEvent(flag ? GameEvent.BLOCK_CLOSE : GameEvent.BLOCK_OPEN, blockposition, GameEvent.Context.of(iblockdata)); + } + +- super.onExplosionHit(blockState, level, blockPos, explosion, biConsumer); ++ super.onExplosionHit(iblockdata, world, blockposition, explosion, biconsumer); + } + + @Override +- public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { + if (!level.isClientSide) { +- boolean hasNeighborSignal = level.hasNeighborSignal(pos); +- if (state.getValue(POWERED) != hasNeighborSignal) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(hasNeighborSignal)).setValue(OPEN, Boolean.valueOf(hasNeighborSignal)), 2); +- if (state.getValue(OPEN) != hasNeighborSignal) { +- level.playSound( +- null, +- pos, +- hasNeighborSignal ? this.type.fenceGateOpen() : this.type.fenceGateClose(), +- SoundSource.BLOCKS, +- 1.0F, +- level.getRandom().nextFloat() * 0.1F + 0.9F +- ); +- level.gameEvent(null, hasNeighborSignal ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); ++ boolean flag1 = level.hasNeighborSignal(pos); ++ // CraftBukkit start ++ boolean oldPowered = state.getValue(FenceGateBlock.POWERED); ++ if (oldPowered != flag1) { ++ int newPower = flag1 ? 15 : 0; ++ int oldPower = oldPowered ? 15 : 0; ++ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos); ++ org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(bukkitBlock, oldPower, newPower); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ flag1 = eventRedstone.getNewCurrent() > 0; ++ } ++ // CraftBukkit end ++ ++ if ((Boolean) state.getValue(FenceGateBlock.POWERED) != flag1) { ++ level.setBlock(pos, (IBlockData) ((IBlockData) state.setValue(FenceGateBlock.POWERED, flag1)).setValue(FenceGateBlock.OPEN, flag1), 2); ++ if ((Boolean) state.getValue(FenceGateBlock.OPEN) != flag1) { ++ level.playSound((Player) null, pos, flag1 ? this.type.fenceGateOpen() : this.type.fenceGateClose(), SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.1F + 0.9F); ++ level.gameEvent((Entity) null, flag1 ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); + } + } ++ + } + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(FACING, OPEN, POWERED, IN_WALL); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(FenceGateBlock.FACING, FenceGateBlock.OPEN, FenceGateBlock.POWERED, FenceGateBlock.IN_WALL); + } + +- public static boolean connectsToDirection(BlockState state, Direction direction) { +- return state.getValue(FACING).getAxis() == direction.getClockWise().getAxis(); ++ public static boolean connectsToDirection(IBlockData state, Direction direction) { ++ return ((Direction) state.getValue(FenceGateBlock.FACING)).getAxis() == direction.getClockWise().getAxis(); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/FireBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/FireBlock.java.patch new file mode 100644 index 0000000000..ca0ce59b12 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/FireBlock.java.patch @@ -0,0 +1,859 @@ +--- a/net/minecraft/world/level/block/FireBlock.java ++++ b/net/minecraft/world/level/block/FireBlock.java +@@ -5,7 +5,6 @@ + import it.unimi.dsi.fastutil.objects.Object2IntMap; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; + import java.util.Map; +-import java.util.Map.Entry; + import java.util.function.Function; + import java.util.stream.Collectors; + import net.minecraft.Util; +@@ -21,7 +20,7 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -29,8 +28,16 @@ + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.block.CraftBlockStates; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.block.BlockBurnEvent; ++import org.bukkit.event.block.BlockFadeEvent; ++// CraftBukkit end + + public class FireBlock extends BaseFireBlock { ++ + public static final MapCodec CODEC = simpleCodec(FireBlock::new); + public static final int MAX_AGE = 15; + public static final IntegerProperty AGE = BlockStateProperties.AGE_15; +@@ -39,17 +46,15 @@ + public static final BooleanProperty SOUTH = PipeBlock.SOUTH; + public static final BooleanProperty WEST = PipeBlock.WEST; + public static final BooleanProperty UP = PipeBlock.UP; +- private static final Map PROPERTY_BY_DIRECTION = PipeBlock.PROPERTY_BY_DIRECTION +- .entrySet() +- .stream() +- .filter(directionEntry -> directionEntry.getKey() != Direction.DOWN) +- .collect(Util.toMap()); +- private static final VoxelShape UP_AABB = Block.box(0.0, 15.0, 0.0, 16.0, 16.0, 16.0); +- private static final VoxelShape WEST_AABB = Block.box(0.0, 0.0, 0.0, 1.0, 16.0, 16.0); +- private static final VoxelShape EAST_AABB = Block.box(15.0, 0.0, 0.0, 16.0, 16.0, 16.0); +- private static final VoxelShape NORTH_AABB = Block.box(0.0, 0.0, 0.0, 16.0, 16.0, 1.0); +- private static final VoxelShape SOUTH_AABB = Block.box(0.0, 0.0, 15.0, 16.0, 16.0, 16.0); +- private final Map shapesCache; ++ private static final Map PROPERTY_BY_DIRECTION = (Map) PipeBlock.PROPERTY_BY_DIRECTION.entrySet().stream().filter((entry) -> { ++ return entry.getKey() != Direction.DOWN; ++ }).collect(Util.toMap()); ++ private static final VoxelShape UP_AABB = Block.box(0.0D, 15.0D, 0.0D, 16.0D, 16.0D, 16.0D); ++ private static final VoxelShape WEST_AABB = Block.box(0.0D, 0.0D, 0.0D, 1.0D, 16.0D, 16.0D); ++ private static final VoxelShape EAST_AABB = Block.box(15.0D, 0.0D, 0.0D, 16.0D, 16.0D, 16.0D); ++ private static final VoxelShape NORTH_AABB = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 16.0D, 1.0D); ++ private static final VoxelShape SOUTH_AABB = Block.box(0.0D, 0.0D, 15.0D, 16.0D, 16.0D, 16.0D); ++ private final Map shapesCache; + private static final int IGNITE_INSTANT = 60; + private static final int IGNITE_EASY = 30; + private static final int IGNITE_MEDIUM = 15; +@@ -58,222 +63,271 @@ + private static final int BURN_EASY = 60; + private static final int BURN_MEDIUM = 20; + private static final int BURN_HARD = 5; +- private final Object2IntMap igniteOdds = new Object2IntOpenHashMap<>(); +- private final Object2IntMap burnOdds = new Object2IntOpenHashMap<>(); ++ public final Object2IntMap igniteOdds = new Object2IntOpenHashMap(); ++ private final Object2IntMap burnOdds = new Object2IntOpenHashMap(); + + @Override + public MapCodec codec() { +- return CODEC; ++ return FireBlock.CODEC; + } + + public FireBlock(BlockBehaviour.Properties properties) { + super(properties, 1.0F); +- this.registerDefaultState( +- this.stateDefinition +- .any() +- .setValue(AGE, Integer.valueOf(0)) +- .setValue(NORTH, Boolean.valueOf(false)) +- .setValue(EAST, Boolean.valueOf(false)) +- .setValue(SOUTH, Boolean.valueOf(false)) +- .setValue(WEST, Boolean.valueOf(false)) +- .setValue(UP, Boolean.valueOf(false)) +- ); +- this.shapesCache = ImmutableMap.copyOf( +- this.stateDefinition +- .getPossibleStates() +- .stream() +- .filter(state -> state.getValue(AGE) == 0) +- .collect(Collectors.toMap(Function.identity(), FireBlock::calculateShape)) +- ); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(FireBlock.AGE, 0)).setValue(FireBlock.NORTH, false)).setValue(FireBlock.EAST, false)).setValue(FireBlock.SOUTH, false)).setValue(FireBlock.WEST, false)).setValue(FireBlock.UP, false)); ++ this.shapesCache = ImmutableMap.copyOf((Map) this.stateDefinition.getPossibleStates().stream().filter((iblockdata) -> { ++ return (Integer) iblockdata.getValue(FireBlock.AGE) == 0; ++ }).collect(Collectors.toMap(Function.identity(), FireBlock::calculateShape))); + } + +- private static VoxelShape calculateShape(BlockState state) { +- VoxelShape voxelShape = Shapes.empty(); +- if (state.getValue(UP)) { +- voxelShape = UP_AABB; ++ private static VoxelShape calculateShape(IBlockData state) { ++ VoxelShape voxelshape = Shapes.empty(); ++ ++ if ((Boolean) state.getValue(FireBlock.UP)) { ++ voxelshape = FireBlock.UP_AABB; + } + +- if (state.getValue(NORTH)) { +- voxelShape = Shapes.or(voxelShape, NORTH_AABB); ++ if ((Boolean) state.getValue(FireBlock.NORTH)) { ++ voxelshape = Shapes.or(voxelshape, FireBlock.NORTH_AABB); + } + +- if (state.getValue(SOUTH)) { +- voxelShape = Shapes.or(voxelShape, SOUTH_AABB); ++ if ((Boolean) state.getValue(FireBlock.SOUTH)) { ++ voxelshape = Shapes.or(voxelshape, FireBlock.SOUTH_AABB); + } + +- if (state.getValue(EAST)) { +- voxelShape = Shapes.or(voxelShape, EAST_AABB); ++ if ((Boolean) state.getValue(FireBlock.EAST)) { ++ voxelshape = Shapes.or(voxelshape, FireBlock.EAST_AABB); + } + +- if (state.getValue(WEST)) { +- voxelShape = Shapes.or(voxelShape, WEST_AABB); ++ if ((Boolean) state.getValue(FireBlock.WEST)) { ++ voxelshape = Shapes.or(voxelshape, FireBlock.WEST_AABB); + } + +- return voxelShape.isEmpty() ? DOWN_AABB : voxelShape; ++ return voxelshape.isEmpty() ? FireBlock.DOWN_AABB : voxelshape; + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- return this.canSurvive(state, level, currentPos) ? this.getStateWithAge(level, currentPos, state.getValue(AGE)) : Blocks.AIR.defaultBlockState(); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ // CraftBukkit start ++ if (!this.canSurvive(state, level, currentPos)) { ++ // Suppress during worldgen ++ if (!(level instanceof Level)) { ++ return Blocks.AIR.defaultBlockState(); ++ } ++ CraftBlockState blockState = CraftBlockStates.getBlockState(level, currentPos); ++ blockState.setData(Blocks.AIR.defaultBlockState()); ++ ++ BlockFadeEvent event = new BlockFadeEvent(blockState.getBlock(), blockState); ++ ((Level) level).getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ return blockState.getHandle(); ++ } ++ } ++ return this.getStateWithAge(level, currentPos, (Integer) state.getValue(FireBlock.AGE)); ++ // CraftBukkit end + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return this.shapesCache.get(state.setValue(AGE, Integer.valueOf(0))); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (VoxelShape) this.shapesCache.get(state.setValue(FireBlock.AGE, 0)); + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { + return this.getStateForPlacement(context.getLevel(), context.getClickedPos()); + } + +- protected BlockState getStateForPlacement(BlockGetter level, BlockPos pos) { +- BlockPos blockPos = pos.below(); +- BlockState blockState = level.getBlockState(blockPos); +- if (!this.canBurn(blockState) && !blockState.isFaceSturdy(level, blockPos, Direction.UP)) { +- BlockState blockState1 = this.defaultBlockState(); ++ protected IBlockData getStateForPlacement(BlockGetter level, BlockPos pos) { ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata = level.getBlockState(blockposition1); + +- for (Direction direction : Direction.values()) { +- BooleanProperty booleanProperty = PROPERTY_BY_DIRECTION.get(direction); +- if (booleanProperty != null) { +- blockState1 = blockState1.setValue(booleanProperty, Boolean.valueOf(this.canBurn(level.getBlockState(pos.relative(direction))))); ++ if (!this.canBurn(iblockdata) && !iblockdata.isFaceSturdy(level, blockposition1, Direction.UP)) { ++ IBlockData iblockdata1 = this.defaultBlockState(); ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; ++ ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ BooleanProperty blockstateboolean = (BooleanProperty) FireBlock.PROPERTY_BY_DIRECTION.get(enumdirection); ++ ++ if (blockstateboolean != null) { ++ iblockdata1 = (IBlockData) iblockdata1.setValue(blockstateboolean, this.canBurn(level.getBlockState(pos.relative(enumdirection)))); + } + } + +- return blockState1; ++ return iblockdata1; + } else { + return this.defaultBlockState(); + } + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { +- BlockPos blockPos = pos.below(); +- return level.getBlockState(blockPos).isFaceSturdy(level, blockPos, Direction.UP) || this.isValidFireLocation(level, pos); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.below(); ++ ++ return level.getBlockState(blockposition1).isFaceSturdy(level, blockposition1, Direction.UP) || this.isValidFireLocation(level, pos); + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- level.scheduleTick(pos, this, getFireTickDelay(level.random)); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ level.scheduleTick(pos, (Block) this, getFireTickDelay(level.random)); + if (level.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) { + if (!state.canSurvive(level, pos)) { +- level.removeBlock(pos, false); ++ fireExtinguished(level, pos); // CraftBukkit - invalid place location + } + +- BlockState blockState = level.getBlockState(pos.below()); +- boolean isTag = blockState.is(level.dimensionType().infiniburn()); +- int i = state.getValue(AGE); +- if (!isTag && level.isRaining() && this.isNearRain(level, pos) && random.nextFloat() < 0.2F + (float)i * 0.03F) { +- level.removeBlock(pos, false); ++ IBlockData iblockdata1 = level.getBlockState(pos.below()); ++ boolean flag = iblockdata1.is(level.dimensionType().infiniburn()); ++ int i = (Integer) state.getValue(FireBlock.AGE); ++ ++ if (!flag && level.isRaining() && this.isNearRain(level, pos) && random.nextFloat() < 0.2F + (float) i * 0.03F) { ++ fireExtinguished(level, pos); // CraftBukkit - extinguished by rain + } else { +- int min = Math.min(15, i + random.nextInt(3) / 2); +- if (i != min) { +- state = state.setValue(AGE, Integer.valueOf(min)); ++ int j = Math.min(15, i + random.nextInt(3) / 2); ++ ++ if (i != j) { ++ state = (IBlockData) state.setValue(FireBlock.AGE, j); + level.setBlock(pos, state, 4); + } + +- if (!isTag) { ++ if (!flag) { + if (!this.isValidFireLocation(level, pos)) { +- BlockPos blockPos = pos.below(); +- if (!level.getBlockState(blockPos).isFaceSturdy(level, blockPos, Direction.UP) || i > 3) { +- level.removeBlock(pos, false); ++ BlockPos blockposition1 = pos.below(); ++ ++ if (!level.getBlockState(blockposition1).isFaceSturdy(level, blockposition1, Direction.UP) || i > 3) { ++ fireExtinguished(level, pos); // CraftBukkit + } + + return; + } + + if (i == 15 && random.nextInt(4) == 0 && !this.canBurn(level.getBlockState(pos.below()))) { +- level.removeBlock(pos, false); ++ fireExtinguished(level, pos); // CraftBukkit + return; + } + } + +- boolean isIncreasedFireBurnout = level.getBiome(pos).is(BiomeTags.INCREASED_FIRE_BURNOUT); +- int i1 = isIncreasedFireBurnout ? -50 : 0; +- this.checkBurnOut(level, pos.east(), 300 + i1, random, i); +- this.checkBurnOut(level, pos.west(), 300 + i1, random, i); +- this.checkBurnOut(level, pos.below(), 250 + i1, random, i); +- this.checkBurnOut(level, pos.above(), 250 + i1, random, i); +- this.checkBurnOut(level, pos.north(), 300 + i1, random, i); +- this.checkBurnOut(level, pos.south(), 300 + i1, random, i); +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ boolean flag1 = level.getBiome(pos).is(BiomeTags.INCREASED_FIRE_BURNOUT); ++ int k = flag1 ? -50 : 0; + +- for (int i2 = -1; i2 <= 1; i2++) { +- for (int i3 = -1; i3 <= 1; i3++) { +- for (int i4 = -1; i4 <= 4; i4++) { +- if (i2 != 0 || i4 != 0 || i3 != 0) { +- int i5 = 100; +- if (i4 > 1) { +- i5 += (i4 - 1) * 100; ++ // CraftBukkit start - add source blockposition to burn calls ++ this.trySpread(level, pos.east(), 300 + k, random, i, pos); ++ this.trySpread(level, pos.west(), 300 + k, random, i, pos); ++ this.trySpread(level, pos.below(), 250 + k, random, i, pos); ++ this.trySpread(level, pos.above(), 250 + k, random, i, pos); ++ this.trySpread(level, pos.north(), 300 + k, random, i, pos); ++ this.trySpread(level, pos.south(), 300 + k, random, i, pos); ++ // CraftBukkit end ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ ++ for (int l = -1; l <= 1; ++l) { ++ for (int i1 = -1; i1 <= 1; ++i1) { ++ for (int j1 = -1; j1 <= 4; ++j1) { ++ if (l != 0 || j1 != 0 || i1 != 0) { ++ int k1 = 100; ++ ++ if (j1 > 1) { ++ k1 += (j1 - 1) * 100; + } + +- mutableBlockPos.setWithOffset(pos, i2, i4, i3); +- int igniteOdds = this.getIgniteOdds(level, mutableBlockPos); +- if (igniteOdds > 0) { +- int i6 = (igniteOdds + 40 + level.getDifficulty().getId() * 7) / (i + 30); +- if (isIncreasedFireBurnout) { +- i6 /= 2; ++ blockposition_mutableblockposition.setWithOffset(pos, l, j1, i1); ++ int l1 = this.getIgniteOdds(level, blockposition_mutableblockposition); ++ ++ if (l1 > 0) { ++ int i2 = (l1 + 40 + level.getDifficulty().getId() * 7) / (i + 30); ++ ++ if (flag1) { ++ i2 /= 2; + } + +- if (i6 > 0 && random.nextInt(i5) <= i6 && (!level.isRaining() || !this.isNearRain(level, mutableBlockPos))) { +- int min1 = Math.min(15, i + random.nextInt(5) / 4); +- level.setBlock(mutableBlockPos, this.getStateWithAge(level, mutableBlockPos, min1), 3); ++ if (i2 > 0 && random.nextInt(k1) <= i2 && (!level.isRaining() || !this.isNearRain(level, blockposition_mutableblockposition))) { ++ int j2 = Math.min(15, i + random.nextInt(5) / 4); ++ ++ // CraftBukkit start - Call to stop spread of fire ++ if (level.getBlockState(blockposition_mutableblockposition).getBlock() != Blocks.FIRE) { ++ if (CraftEventFactory.callBlockIgniteEvent(level, blockposition_mutableblockposition, pos).isCancelled()) { ++ continue; ++ } ++ ++ CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition_mutableblockposition, this.getStateWithAge(level, blockposition_mutableblockposition, j2), 3); // CraftBukkit ++ } ++ // CraftBukkit end + } + } + } + } + } + } ++ + } + } + } + + protected boolean isNearRain(Level level, BlockPos pos) { +- return level.isRainingAt(pos) +- || level.isRainingAt(pos.west()) +- || level.isRainingAt(pos.east()) +- || level.isRainingAt(pos.north()) +- || level.isRainingAt(pos.south()); ++ return level.isRainingAt(pos) || level.isRainingAt(pos.west()) || level.isRainingAt(pos.east()) || level.isRainingAt(pos.north()) || level.isRainingAt(pos.south()); + } + +- private int getBurnOdds(BlockState state) { +- return state.hasProperty(BlockStateProperties.WATERLOGGED) && state.getValue(BlockStateProperties.WATERLOGGED) +- ? 0 +- : this.burnOdds.getInt(state.getBlock()); ++ private int getBurnOdds(IBlockData state) { ++ return state.hasProperty(BlockStateProperties.WATERLOGGED) && (Boolean) state.getValue(BlockStateProperties.WATERLOGGED) ? 0 : this.burnOdds.getInt(state.getBlock()); + } + +- private int getIgniteOdds(BlockState state) { +- return state.hasProperty(BlockStateProperties.WATERLOGGED) && state.getValue(BlockStateProperties.WATERLOGGED) +- ? 0 +- : this.igniteOdds.getInt(state.getBlock()); ++ private int getIgniteOdds(IBlockData state) { ++ return state.hasProperty(BlockStateProperties.WATERLOGGED) && (Boolean) state.getValue(BlockStateProperties.WATERLOGGED) ? 0 : this.igniteOdds.getInt(state.getBlock()); + } + +- private void checkBurnOut(Level level, BlockPos pos, int chance, RandomSource random, int age) { +- int burnOdds = this.getBurnOdds(level.getBlockState(pos)); +- if (random.nextInt(chance) < burnOdds) { +- BlockState blockState = level.getBlockState(pos); +- if (random.nextInt(age + 10) < 5 && !level.isRainingAt(pos)) { +- int min = Math.min(age + random.nextInt(5) / 4, 15); +- level.setBlock(pos, this.getStateWithAge(level, pos, min), 3); ++ private void trySpread(Level world, BlockPos blockposition, int i, RandomSource randomsource, int j, BlockPos sourceposition) { // CraftBukkit add sourceposition ++ int k = this.getBurnOdds(world.getBlockState(blockposition)); ++ ++ if (randomsource.nextInt(i) < k) { ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ ++ // CraftBukkit start ++ org.bukkit.block.Block theBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ org.bukkit.block.Block sourceBlock = world.getWorld().getBlockAt(sourceposition.getX(), sourceposition.getY(), sourceposition.getZ()); ++ ++ BlockBurnEvent event = new BlockBurnEvent(theBlock, sourceBlock); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ if (iblockdata.getBlock() instanceof TntBlock && !CraftEventFactory.callTNTPrimeEvent(world, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.FIRE, null, sourceposition)) { ++ return; ++ } ++ // CraftBukkit end ++ ++ if (randomsource.nextInt(j + 10) < 5 && !world.isRainingAt(blockposition)) { ++ int l = Math.min(j + randomsource.nextInt(5) / 4, 15); ++ ++ world.setBlock(blockposition, this.getStateWithAge(world, blockposition, l), 3); + } else { +- level.removeBlock(pos, false); ++ world.removeBlock(blockposition, false); + } + +- Block block = blockState.getBlock(); ++ Block block = iblockdata.getBlock(); ++ + if (block instanceof TntBlock) { +- TntBlock.explode(level, pos); ++ TntBlock.explode(world, blockposition); + } + } ++ + } + +- private BlockState getStateWithAge(LevelAccessor level, BlockPos pos, int age) { +- BlockState state = getState(level, pos); +- return state.is(Blocks.FIRE) ? state.setValue(AGE, Integer.valueOf(age)) : state; ++ private IBlockData getStateWithAge(LevelAccessor level, BlockPos pos, int age) { ++ IBlockData iblockdata = getState(level, pos); ++ ++ return iblockdata.is(Blocks.FIRE) ? (IBlockData) iblockdata.setValue(FireBlock.AGE, age) : iblockdata; + } + + private boolean isValidFireLocation(BlockGetter level, BlockPos pos) { +- for (Direction direction : Direction.values()) { +- if (this.canBurn(level.getBlockState(pos.relative(direction)))) { ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; ++ ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ ++ if (this.canBurn(level.getBlockState(pos.relative(enumdirection)))) { + return true; + } + } +@@ -286,10 +340,14 @@ + return 0; + } else { + int i = 0; ++ Direction[] aenumdirection = Direction.values(); ++ int j = aenumdirection.length; + +- for (Direction direction : Direction.values()) { +- BlockState blockState = level.getBlockState(pos.relative(direction)); +- i = Math.max(this.getIgniteOdds(blockState), i); ++ for (int k = 0; k < j; ++k) { ++ Direction enumdirection = aenumdirection[k]; ++ IBlockData iblockdata = level.getBlockState(pos.relative(enumdirection)); ++ ++ i = Math.max(this.getIgniteOdds(iblockdata), i); + } + + return i; +@@ -297,14 +355,14 @@ + } + + @Override +- protected boolean canBurn(BlockState state) { ++ protected boolean canBurn(IBlockData state) { + return this.getIgniteOdds(state) > 0; + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { + super.onPlace(state, level, pos, oldState, isMoving); +- level.scheduleTick(pos, this, getFireTickDelay(level.random)); ++ level.scheduleTick(pos, (Block) this, getFireTickDelay(level.random)); + } + + private static int getFireTickDelay(RandomSource random) { +@@ -312,8 +370,8 @@ + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(AGE, NORTH, EAST, SOUTH, WEST, UP); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(FireBlock.AGE, FireBlock.NORTH, FireBlock.EAST, FireBlock.SOUTH, FireBlock.WEST, FireBlock.UP); + } + + public void setFlammable(Block block, int encouragement, int flammability) { +@@ -322,180 +380,181 @@ + } + + public static void bootStrap() { +- FireBlock fireBlock = (FireBlock)Blocks.FIRE; +- fireBlock.setFlammable(Blocks.OAK_PLANKS, 5, 20); +- fireBlock.setFlammable(Blocks.SPRUCE_PLANKS, 5, 20); +- fireBlock.setFlammable(Blocks.BIRCH_PLANKS, 5, 20); +- fireBlock.setFlammable(Blocks.JUNGLE_PLANKS, 5, 20); +- fireBlock.setFlammable(Blocks.ACACIA_PLANKS, 5, 20); +- fireBlock.setFlammable(Blocks.CHERRY_PLANKS, 5, 20); +- fireBlock.setFlammable(Blocks.DARK_OAK_PLANKS, 5, 20); +- fireBlock.setFlammable(Blocks.MANGROVE_PLANKS, 5, 20); +- fireBlock.setFlammable(Blocks.BAMBOO_PLANKS, 5, 20); +- fireBlock.setFlammable(Blocks.BAMBOO_MOSAIC, 5, 20); +- fireBlock.setFlammable(Blocks.OAK_SLAB, 5, 20); +- fireBlock.setFlammable(Blocks.SPRUCE_SLAB, 5, 20); +- fireBlock.setFlammable(Blocks.BIRCH_SLAB, 5, 20); +- fireBlock.setFlammable(Blocks.JUNGLE_SLAB, 5, 20); +- fireBlock.setFlammable(Blocks.ACACIA_SLAB, 5, 20); +- fireBlock.setFlammable(Blocks.CHERRY_SLAB, 5, 20); +- fireBlock.setFlammable(Blocks.DARK_OAK_SLAB, 5, 20); +- fireBlock.setFlammable(Blocks.MANGROVE_SLAB, 5, 20); +- fireBlock.setFlammable(Blocks.BAMBOO_SLAB, 5, 20); +- fireBlock.setFlammable(Blocks.BAMBOO_MOSAIC_SLAB, 5, 20); +- fireBlock.setFlammable(Blocks.OAK_FENCE_GATE, 5, 20); +- fireBlock.setFlammable(Blocks.SPRUCE_FENCE_GATE, 5, 20); +- fireBlock.setFlammable(Blocks.BIRCH_FENCE_GATE, 5, 20); +- fireBlock.setFlammable(Blocks.JUNGLE_FENCE_GATE, 5, 20); +- fireBlock.setFlammable(Blocks.ACACIA_FENCE_GATE, 5, 20); +- fireBlock.setFlammable(Blocks.CHERRY_FENCE_GATE, 5, 20); +- fireBlock.setFlammable(Blocks.DARK_OAK_FENCE_GATE, 5, 20); +- fireBlock.setFlammable(Blocks.MANGROVE_FENCE_GATE, 5, 20); +- fireBlock.setFlammable(Blocks.BAMBOO_FENCE_GATE, 5, 20); +- fireBlock.setFlammable(Blocks.OAK_FENCE, 5, 20); +- fireBlock.setFlammable(Blocks.SPRUCE_FENCE, 5, 20); +- fireBlock.setFlammable(Blocks.BIRCH_FENCE, 5, 20); +- fireBlock.setFlammable(Blocks.JUNGLE_FENCE, 5, 20); +- fireBlock.setFlammable(Blocks.ACACIA_FENCE, 5, 20); +- fireBlock.setFlammable(Blocks.CHERRY_FENCE, 5, 20); +- fireBlock.setFlammable(Blocks.DARK_OAK_FENCE, 5, 20); +- fireBlock.setFlammable(Blocks.MANGROVE_FENCE, 5, 20); +- fireBlock.setFlammable(Blocks.BAMBOO_FENCE, 5, 20); +- fireBlock.setFlammable(Blocks.OAK_STAIRS, 5, 20); +- fireBlock.setFlammable(Blocks.BIRCH_STAIRS, 5, 20); +- fireBlock.setFlammable(Blocks.SPRUCE_STAIRS, 5, 20); +- fireBlock.setFlammable(Blocks.JUNGLE_STAIRS, 5, 20); +- fireBlock.setFlammable(Blocks.ACACIA_STAIRS, 5, 20); +- fireBlock.setFlammable(Blocks.CHERRY_STAIRS, 5, 20); +- fireBlock.setFlammable(Blocks.DARK_OAK_STAIRS, 5, 20); +- fireBlock.setFlammable(Blocks.MANGROVE_STAIRS, 5, 20); +- fireBlock.setFlammable(Blocks.BAMBOO_STAIRS, 5, 20); +- fireBlock.setFlammable(Blocks.BAMBOO_MOSAIC_STAIRS, 5, 20); +- fireBlock.setFlammable(Blocks.OAK_LOG, 5, 5); +- fireBlock.setFlammable(Blocks.SPRUCE_LOG, 5, 5); +- fireBlock.setFlammable(Blocks.BIRCH_LOG, 5, 5); +- fireBlock.setFlammable(Blocks.JUNGLE_LOG, 5, 5); +- fireBlock.setFlammable(Blocks.ACACIA_LOG, 5, 5); +- fireBlock.setFlammable(Blocks.CHERRY_LOG, 5, 5); +- fireBlock.setFlammable(Blocks.DARK_OAK_LOG, 5, 5); +- fireBlock.setFlammable(Blocks.MANGROVE_LOG, 5, 5); +- fireBlock.setFlammable(Blocks.BAMBOO_BLOCK, 5, 5); +- fireBlock.setFlammable(Blocks.STRIPPED_OAK_LOG, 5, 5); +- fireBlock.setFlammable(Blocks.STRIPPED_SPRUCE_LOG, 5, 5); +- fireBlock.setFlammable(Blocks.STRIPPED_BIRCH_LOG, 5, 5); +- fireBlock.setFlammable(Blocks.STRIPPED_JUNGLE_LOG, 5, 5); +- fireBlock.setFlammable(Blocks.STRIPPED_ACACIA_LOG, 5, 5); +- fireBlock.setFlammable(Blocks.STRIPPED_CHERRY_LOG, 5, 5); +- fireBlock.setFlammable(Blocks.STRIPPED_DARK_OAK_LOG, 5, 5); +- fireBlock.setFlammable(Blocks.STRIPPED_MANGROVE_LOG, 5, 5); +- fireBlock.setFlammable(Blocks.STRIPPED_BAMBOO_BLOCK, 5, 5); +- fireBlock.setFlammable(Blocks.STRIPPED_OAK_WOOD, 5, 5); +- fireBlock.setFlammable(Blocks.STRIPPED_SPRUCE_WOOD, 5, 5); +- fireBlock.setFlammable(Blocks.STRIPPED_BIRCH_WOOD, 5, 5); +- fireBlock.setFlammable(Blocks.STRIPPED_JUNGLE_WOOD, 5, 5); +- fireBlock.setFlammable(Blocks.STRIPPED_ACACIA_WOOD, 5, 5); +- fireBlock.setFlammable(Blocks.STRIPPED_CHERRY_WOOD, 5, 5); +- fireBlock.setFlammable(Blocks.STRIPPED_DARK_OAK_WOOD, 5, 5); +- fireBlock.setFlammable(Blocks.STRIPPED_MANGROVE_WOOD, 5, 5); +- fireBlock.setFlammable(Blocks.OAK_WOOD, 5, 5); +- fireBlock.setFlammable(Blocks.SPRUCE_WOOD, 5, 5); +- fireBlock.setFlammable(Blocks.BIRCH_WOOD, 5, 5); +- fireBlock.setFlammable(Blocks.JUNGLE_WOOD, 5, 5); +- fireBlock.setFlammable(Blocks.ACACIA_WOOD, 5, 5); +- fireBlock.setFlammable(Blocks.CHERRY_WOOD, 5, 5); +- fireBlock.setFlammable(Blocks.DARK_OAK_WOOD, 5, 5); +- fireBlock.setFlammable(Blocks.MANGROVE_WOOD, 5, 5); +- fireBlock.setFlammable(Blocks.MANGROVE_ROOTS, 5, 20); +- fireBlock.setFlammable(Blocks.OAK_LEAVES, 30, 60); +- fireBlock.setFlammable(Blocks.SPRUCE_LEAVES, 30, 60); +- fireBlock.setFlammable(Blocks.BIRCH_LEAVES, 30, 60); +- fireBlock.setFlammable(Blocks.JUNGLE_LEAVES, 30, 60); +- fireBlock.setFlammable(Blocks.ACACIA_LEAVES, 30, 60); +- fireBlock.setFlammable(Blocks.CHERRY_LEAVES, 30, 60); +- fireBlock.setFlammable(Blocks.DARK_OAK_LEAVES, 30, 60); +- fireBlock.setFlammable(Blocks.MANGROVE_LEAVES, 30, 60); +- fireBlock.setFlammable(Blocks.BOOKSHELF, 30, 20); +- fireBlock.setFlammable(Blocks.TNT, 15, 100); +- fireBlock.setFlammable(Blocks.SHORT_GRASS, 60, 100); +- fireBlock.setFlammable(Blocks.FERN, 60, 100); +- fireBlock.setFlammable(Blocks.DEAD_BUSH, 60, 100); +- fireBlock.setFlammable(Blocks.SUNFLOWER, 60, 100); +- fireBlock.setFlammable(Blocks.LILAC, 60, 100); +- fireBlock.setFlammable(Blocks.ROSE_BUSH, 60, 100); +- fireBlock.setFlammable(Blocks.PEONY, 60, 100); +- fireBlock.setFlammable(Blocks.TALL_GRASS, 60, 100); +- fireBlock.setFlammable(Blocks.LARGE_FERN, 60, 100); +- fireBlock.setFlammable(Blocks.DANDELION, 60, 100); +- fireBlock.setFlammable(Blocks.POPPY, 60, 100); +- fireBlock.setFlammable(Blocks.BLUE_ORCHID, 60, 100); +- fireBlock.setFlammable(Blocks.ALLIUM, 60, 100); +- fireBlock.setFlammable(Blocks.AZURE_BLUET, 60, 100); +- fireBlock.setFlammable(Blocks.RED_TULIP, 60, 100); +- fireBlock.setFlammable(Blocks.ORANGE_TULIP, 60, 100); +- fireBlock.setFlammable(Blocks.WHITE_TULIP, 60, 100); +- fireBlock.setFlammable(Blocks.PINK_TULIP, 60, 100); +- fireBlock.setFlammable(Blocks.OXEYE_DAISY, 60, 100); +- fireBlock.setFlammable(Blocks.CORNFLOWER, 60, 100); +- fireBlock.setFlammable(Blocks.LILY_OF_THE_VALLEY, 60, 100); +- fireBlock.setFlammable(Blocks.TORCHFLOWER, 60, 100); +- fireBlock.setFlammable(Blocks.PITCHER_PLANT, 60, 100); +- fireBlock.setFlammable(Blocks.WITHER_ROSE, 60, 100); +- fireBlock.setFlammable(Blocks.PINK_PETALS, 60, 100); +- fireBlock.setFlammable(Blocks.WHITE_WOOL, 30, 60); +- fireBlock.setFlammable(Blocks.ORANGE_WOOL, 30, 60); +- fireBlock.setFlammable(Blocks.MAGENTA_WOOL, 30, 60); +- fireBlock.setFlammable(Blocks.LIGHT_BLUE_WOOL, 30, 60); +- fireBlock.setFlammable(Blocks.YELLOW_WOOL, 30, 60); +- fireBlock.setFlammable(Blocks.LIME_WOOL, 30, 60); +- fireBlock.setFlammable(Blocks.PINK_WOOL, 30, 60); +- fireBlock.setFlammable(Blocks.GRAY_WOOL, 30, 60); +- fireBlock.setFlammable(Blocks.LIGHT_GRAY_WOOL, 30, 60); +- fireBlock.setFlammable(Blocks.CYAN_WOOL, 30, 60); +- fireBlock.setFlammable(Blocks.PURPLE_WOOL, 30, 60); +- fireBlock.setFlammable(Blocks.BLUE_WOOL, 30, 60); +- fireBlock.setFlammable(Blocks.BROWN_WOOL, 30, 60); +- fireBlock.setFlammable(Blocks.GREEN_WOOL, 30, 60); +- fireBlock.setFlammable(Blocks.RED_WOOL, 30, 60); +- fireBlock.setFlammable(Blocks.BLACK_WOOL, 30, 60); +- fireBlock.setFlammable(Blocks.VINE, 15, 100); +- fireBlock.setFlammable(Blocks.COAL_BLOCK, 5, 5); +- fireBlock.setFlammable(Blocks.HAY_BLOCK, 60, 20); +- fireBlock.setFlammable(Blocks.TARGET, 15, 20); +- fireBlock.setFlammable(Blocks.WHITE_CARPET, 60, 20); +- fireBlock.setFlammable(Blocks.ORANGE_CARPET, 60, 20); +- fireBlock.setFlammable(Blocks.MAGENTA_CARPET, 60, 20); +- fireBlock.setFlammable(Blocks.LIGHT_BLUE_CARPET, 60, 20); +- fireBlock.setFlammable(Blocks.YELLOW_CARPET, 60, 20); +- fireBlock.setFlammable(Blocks.LIME_CARPET, 60, 20); +- fireBlock.setFlammable(Blocks.PINK_CARPET, 60, 20); +- fireBlock.setFlammable(Blocks.GRAY_CARPET, 60, 20); +- fireBlock.setFlammable(Blocks.LIGHT_GRAY_CARPET, 60, 20); +- fireBlock.setFlammable(Blocks.CYAN_CARPET, 60, 20); +- fireBlock.setFlammable(Blocks.PURPLE_CARPET, 60, 20); +- fireBlock.setFlammable(Blocks.BLUE_CARPET, 60, 20); +- fireBlock.setFlammable(Blocks.BROWN_CARPET, 60, 20); +- fireBlock.setFlammable(Blocks.GREEN_CARPET, 60, 20); +- fireBlock.setFlammable(Blocks.RED_CARPET, 60, 20); +- fireBlock.setFlammable(Blocks.BLACK_CARPET, 60, 20); +- fireBlock.setFlammable(Blocks.DRIED_KELP_BLOCK, 30, 60); +- fireBlock.setFlammable(Blocks.BAMBOO, 60, 60); +- fireBlock.setFlammable(Blocks.SCAFFOLDING, 60, 60); +- fireBlock.setFlammable(Blocks.LECTERN, 30, 20); +- fireBlock.setFlammable(Blocks.COMPOSTER, 5, 20); +- fireBlock.setFlammable(Blocks.SWEET_BERRY_BUSH, 60, 100); +- fireBlock.setFlammable(Blocks.BEEHIVE, 5, 20); +- fireBlock.setFlammable(Blocks.BEE_NEST, 30, 20); +- fireBlock.setFlammable(Blocks.AZALEA_LEAVES, 30, 60); +- fireBlock.setFlammable(Blocks.FLOWERING_AZALEA_LEAVES, 30, 60); +- fireBlock.setFlammable(Blocks.CAVE_VINES, 15, 60); +- fireBlock.setFlammable(Blocks.CAVE_VINES_PLANT, 15, 60); +- fireBlock.setFlammable(Blocks.SPORE_BLOSSOM, 60, 100); +- fireBlock.setFlammable(Blocks.AZALEA, 30, 60); +- fireBlock.setFlammable(Blocks.FLOWERING_AZALEA, 30, 60); +- fireBlock.setFlammable(Blocks.BIG_DRIPLEAF, 60, 100); +- fireBlock.setFlammable(Blocks.BIG_DRIPLEAF_STEM, 60, 100); +- fireBlock.setFlammable(Blocks.SMALL_DRIPLEAF, 60, 100); +- fireBlock.setFlammable(Blocks.HANGING_ROOTS, 30, 60); +- fireBlock.setFlammable(Blocks.GLOW_LICHEN, 15, 100); ++ FireBlock blockfire = (FireBlock) Blocks.FIRE; ++ ++ blockfire.setFlammable(Blocks.OAK_PLANKS, 5, 20); ++ blockfire.setFlammable(Blocks.SPRUCE_PLANKS, 5, 20); ++ blockfire.setFlammable(Blocks.BIRCH_PLANKS, 5, 20); ++ blockfire.setFlammable(Blocks.JUNGLE_PLANKS, 5, 20); ++ blockfire.setFlammable(Blocks.ACACIA_PLANKS, 5, 20); ++ blockfire.setFlammable(Blocks.CHERRY_PLANKS, 5, 20); ++ blockfire.setFlammable(Blocks.DARK_OAK_PLANKS, 5, 20); ++ blockfire.setFlammable(Blocks.MANGROVE_PLANKS, 5, 20); ++ blockfire.setFlammable(Blocks.BAMBOO_PLANKS, 5, 20); ++ blockfire.setFlammable(Blocks.BAMBOO_MOSAIC, 5, 20); ++ blockfire.setFlammable(Blocks.OAK_SLAB, 5, 20); ++ blockfire.setFlammable(Blocks.SPRUCE_SLAB, 5, 20); ++ blockfire.setFlammable(Blocks.BIRCH_SLAB, 5, 20); ++ blockfire.setFlammable(Blocks.JUNGLE_SLAB, 5, 20); ++ blockfire.setFlammable(Blocks.ACACIA_SLAB, 5, 20); ++ blockfire.setFlammable(Blocks.CHERRY_SLAB, 5, 20); ++ blockfire.setFlammable(Blocks.DARK_OAK_SLAB, 5, 20); ++ blockfire.setFlammable(Blocks.MANGROVE_SLAB, 5, 20); ++ blockfire.setFlammable(Blocks.BAMBOO_SLAB, 5, 20); ++ blockfire.setFlammable(Blocks.BAMBOO_MOSAIC_SLAB, 5, 20); ++ blockfire.setFlammable(Blocks.OAK_FENCE_GATE, 5, 20); ++ blockfire.setFlammable(Blocks.SPRUCE_FENCE_GATE, 5, 20); ++ blockfire.setFlammable(Blocks.BIRCH_FENCE_GATE, 5, 20); ++ blockfire.setFlammable(Blocks.JUNGLE_FENCE_GATE, 5, 20); ++ blockfire.setFlammable(Blocks.ACACIA_FENCE_GATE, 5, 20); ++ blockfire.setFlammable(Blocks.CHERRY_FENCE_GATE, 5, 20); ++ blockfire.setFlammable(Blocks.DARK_OAK_FENCE_GATE, 5, 20); ++ blockfire.setFlammable(Blocks.MANGROVE_FENCE_GATE, 5, 20); ++ blockfire.setFlammable(Blocks.BAMBOO_FENCE_GATE, 5, 20); ++ blockfire.setFlammable(Blocks.OAK_FENCE, 5, 20); ++ blockfire.setFlammable(Blocks.SPRUCE_FENCE, 5, 20); ++ blockfire.setFlammable(Blocks.BIRCH_FENCE, 5, 20); ++ blockfire.setFlammable(Blocks.JUNGLE_FENCE, 5, 20); ++ blockfire.setFlammable(Blocks.ACACIA_FENCE, 5, 20); ++ blockfire.setFlammable(Blocks.CHERRY_FENCE, 5, 20); ++ blockfire.setFlammable(Blocks.DARK_OAK_FENCE, 5, 20); ++ blockfire.setFlammable(Blocks.MANGROVE_FENCE, 5, 20); ++ blockfire.setFlammable(Blocks.BAMBOO_FENCE, 5, 20); ++ blockfire.setFlammable(Blocks.OAK_STAIRS, 5, 20); ++ blockfire.setFlammable(Blocks.BIRCH_STAIRS, 5, 20); ++ blockfire.setFlammable(Blocks.SPRUCE_STAIRS, 5, 20); ++ blockfire.setFlammable(Blocks.JUNGLE_STAIRS, 5, 20); ++ blockfire.setFlammable(Blocks.ACACIA_STAIRS, 5, 20); ++ blockfire.setFlammable(Blocks.CHERRY_STAIRS, 5, 20); ++ blockfire.setFlammable(Blocks.DARK_OAK_STAIRS, 5, 20); ++ blockfire.setFlammable(Blocks.MANGROVE_STAIRS, 5, 20); ++ blockfire.setFlammable(Blocks.BAMBOO_STAIRS, 5, 20); ++ blockfire.setFlammable(Blocks.BAMBOO_MOSAIC_STAIRS, 5, 20); ++ blockfire.setFlammable(Blocks.OAK_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.SPRUCE_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.BIRCH_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.JUNGLE_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.ACACIA_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.CHERRY_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.DARK_OAK_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.MANGROVE_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.BAMBOO_BLOCK, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_OAK_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_SPRUCE_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_BIRCH_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_JUNGLE_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_ACACIA_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_CHERRY_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_DARK_OAK_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_MANGROVE_LOG, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_BAMBOO_BLOCK, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_OAK_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_SPRUCE_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_BIRCH_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_JUNGLE_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_ACACIA_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_CHERRY_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_DARK_OAK_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.STRIPPED_MANGROVE_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.OAK_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.SPRUCE_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.BIRCH_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.JUNGLE_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.ACACIA_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.CHERRY_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.DARK_OAK_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.MANGROVE_WOOD, 5, 5); ++ blockfire.setFlammable(Blocks.MANGROVE_ROOTS, 5, 20); ++ blockfire.setFlammable(Blocks.OAK_LEAVES, 30, 60); ++ blockfire.setFlammable(Blocks.SPRUCE_LEAVES, 30, 60); ++ blockfire.setFlammable(Blocks.BIRCH_LEAVES, 30, 60); ++ blockfire.setFlammable(Blocks.JUNGLE_LEAVES, 30, 60); ++ blockfire.setFlammable(Blocks.ACACIA_LEAVES, 30, 60); ++ blockfire.setFlammable(Blocks.CHERRY_LEAVES, 30, 60); ++ blockfire.setFlammable(Blocks.DARK_OAK_LEAVES, 30, 60); ++ blockfire.setFlammable(Blocks.MANGROVE_LEAVES, 30, 60); ++ blockfire.setFlammable(Blocks.BOOKSHELF, 30, 20); ++ blockfire.setFlammable(Blocks.TNT, 15, 100); ++ blockfire.setFlammable(Blocks.SHORT_GRASS, 60, 100); ++ blockfire.setFlammable(Blocks.FERN, 60, 100); ++ blockfire.setFlammable(Blocks.DEAD_BUSH, 60, 100); ++ blockfire.setFlammable(Blocks.SUNFLOWER, 60, 100); ++ blockfire.setFlammable(Blocks.LILAC, 60, 100); ++ blockfire.setFlammable(Blocks.ROSE_BUSH, 60, 100); ++ blockfire.setFlammable(Blocks.PEONY, 60, 100); ++ blockfire.setFlammable(Blocks.TALL_GRASS, 60, 100); ++ blockfire.setFlammable(Blocks.LARGE_FERN, 60, 100); ++ blockfire.setFlammable(Blocks.DANDELION, 60, 100); ++ blockfire.setFlammable(Blocks.POPPY, 60, 100); ++ blockfire.setFlammable(Blocks.BLUE_ORCHID, 60, 100); ++ blockfire.setFlammable(Blocks.ALLIUM, 60, 100); ++ blockfire.setFlammable(Blocks.AZURE_BLUET, 60, 100); ++ blockfire.setFlammable(Blocks.RED_TULIP, 60, 100); ++ blockfire.setFlammable(Blocks.ORANGE_TULIP, 60, 100); ++ blockfire.setFlammable(Blocks.WHITE_TULIP, 60, 100); ++ blockfire.setFlammable(Blocks.PINK_TULIP, 60, 100); ++ blockfire.setFlammable(Blocks.OXEYE_DAISY, 60, 100); ++ blockfire.setFlammable(Blocks.CORNFLOWER, 60, 100); ++ blockfire.setFlammable(Blocks.LILY_OF_THE_VALLEY, 60, 100); ++ blockfire.setFlammable(Blocks.TORCHFLOWER, 60, 100); ++ blockfire.setFlammable(Blocks.PITCHER_PLANT, 60, 100); ++ blockfire.setFlammable(Blocks.WITHER_ROSE, 60, 100); ++ blockfire.setFlammable(Blocks.PINK_PETALS, 60, 100); ++ blockfire.setFlammable(Blocks.WHITE_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.ORANGE_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.MAGENTA_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.LIGHT_BLUE_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.YELLOW_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.LIME_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.PINK_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.GRAY_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.LIGHT_GRAY_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.CYAN_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.PURPLE_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.BLUE_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.BROWN_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.GREEN_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.RED_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.BLACK_WOOL, 30, 60); ++ blockfire.setFlammable(Blocks.VINE, 15, 100); ++ blockfire.setFlammable(Blocks.COAL_BLOCK, 5, 5); ++ blockfire.setFlammable(Blocks.HAY_BLOCK, 60, 20); ++ blockfire.setFlammable(Blocks.TARGET, 15, 20); ++ blockfire.setFlammable(Blocks.WHITE_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.ORANGE_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.MAGENTA_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.LIGHT_BLUE_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.YELLOW_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.LIME_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.PINK_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.GRAY_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.LIGHT_GRAY_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.CYAN_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.PURPLE_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.BLUE_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.BROWN_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.GREEN_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.RED_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.BLACK_CARPET, 60, 20); ++ blockfire.setFlammable(Blocks.DRIED_KELP_BLOCK, 30, 60); ++ blockfire.setFlammable(Blocks.BAMBOO, 60, 60); ++ blockfire.setFlammable(Blocks.SCAFFOLDING, 60, 60); ++ blockfire.setFlammable(Blocks.LECTERN, 30, 20); ++ blockfire.setFlammable(Blocks.COMPOSTER, 5, 20); ++ blockfire.setFlammable(Blocks.SWEET_BERRY_BUSH, 60, 100); ++ blockfire.setFlammable(Blocks.BEEHIVE, 5, 20); ++ blockfire.setFlammable(Blocks.BEE_NEST, 30, 20); ++ blockfire.setFlammable(Blocks.AZALEA_LEAVES, 30, 60); ++ blockfire.setFlammable(Blocks.FLOWERING_AZALEA_LEAVES, 30, 60); ++ blockfire.setFlammable(Blocks.CAVE_VINES, 15, 60); ++ blockfire.setFlammable(Blocks.CAVE_VINES_PLANT, 15, 60); ++ blockfire.setFlammable(Blocks.SPORE_BLOSSOM, 60, 100); ++ blockfire.setFlammable(Blocks.AZALEA, 30, 60); ++ blockfire.setFlammable(Blocks.FLOWERING_AZALEA, 30, 60); ++ blockfire.setFlammable(Blocks.BIG_DRIPLEAF, 60, 100); ++ blockfire.setFlammable(Blocks.BIG_DRIPLEAF_STEM, 60, 100); ++ blockfire.setFlammable(Blocks.SMALL_DRIPLEAF, 60, 100); ++ blockfire.setFlammable(Blocks.HANGING_ROOTS, 30, 60); ++ blockfire.setFlammable(Blocks.GLOW_LICHEN, 15, 100); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/FungusBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/FungusBlock.java.patch new file mode 100644 index 0000000000..a870ac1086 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/FungusBlock.java.patch @@ -0,0 +1,108 @@ +--- a/net/minecraft/world/level/block/FungusBlock.java ++++ b/net/minecraft/world/level/block/FungusBlock.java +@@ -2,7 +2,6 @@ + + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import java.util.Optional; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Holder; +@@ -16,43 +15,43 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; + + public class FungusBlock extends BushBlock implements BonemealableBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group( +- ResourceKey.codec(Registries.CONFIGURED_FEATURE).fieldOf("feature").forGetter(fungusBlock -> fungusBlock.feature), +- BuiltInRegistries.BLOCK.byNameCodec().fieldOf("grows_on").forGetter(fungusBlock -> fungusBlock.requiredBlock), +- propertiesCodec() +- ) +- .apply(instance, FungusBlock::new) +- ); +- protected static final VoxelShape SHAPE = Block.box(4.0, 0.0, 4.0, 12.0, 9.0, 12.0); +- private static final double BONEMEAL_SUCCESS_PROBABILITY = 0.4; ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(ResourceKey.codec(Registries.CONFIGURED_FEATURE).fieldOf("feature").forGetter((blockfungi) -> { ++ return blockfungi.feature; ++ }), BuiltInRegistries.BLOCK.byNameCodec().fieldOf("grows_on").forGetter((blockfungi) -> { ++ return blockfungi.requiredBlock; ++ }), propertiesCodec()).apply(instance, FungusBlock::new); ++ }); ++ protected static final VoxelShape SHAPE = Block.box(4.0D, 0.0D, 4.0D, 12.0D, 9.0D, 12.0D); ++ private static final double BONEMEAL_SUCCESS_PROBABILITY = 0.4D; + private final Block requiredBlock; + private final ResourceKey> feature; + + @Override + public MapCodec codec() { +- return CODEC; ++ return FungusBlock.CODEC; + } + +- protected FungusBlock(ResourceKey> resourceKey, Block block, BlockBehaviour.Properties properties) { +- super(properties); +- this.feature = resourceKey; ++ protected FungusBlock(ResourceKey> resourcekey, Block block, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info); ++ this.feature = resourcekey; + this.requiredBlock = block; + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPE; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return FungusBlock.SHAPE; + } + + @Override +- protected boolean mayPlaceOn(BlockState state, BlockGetter level, BlockPos pos) { ++ protected boolean mayPlaceOn(IBlockData state, BlockGetter level, BlockPos pos) { + return state.is(BlockTags.NYLIUM) || state.is(Blocks.MYCELIUM) || state.is(Blocks.SOUL_SOIL) || super.mayPlaceOn(state, level, pos); + } + +@@ -61,18 +60,28 @@ + } + + @Override +- public boolean isValidBonemealTarget(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { +- BlockState blockState1 = levelReader.getBlockState(blockPos.below()); +- return blockState1.is(this.requiredBlock); ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ IBlockData iblockdata1 = iworldreader.getBlockState(blockposition.below()); ++ ++ return iblockdata1.is(this.requiredBlock); + } + + @Override +- public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, BlockState state) { +- return (double)random.nextFloat() < 0.4; ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { ++ return (double) random.nextFloat() < 0.4D; + } + + @Override +- public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) { +- this.getFeature(level).ifPresent(holder -> holder.value().place(level, level.getChunkSource().getGenerator(), random, pos)); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ this.getFeature(level).ifPresent((holder) -> { ++ // CraftBukkit start ++ if (this == Blocks.WARPED_FUNGUS) { ++ SaplingBlock.treeType = org.bukkit.TreeType.WARPED_FUNGUS; ++ } else if (this == Blocks.CRIMSON_FUNGUS) { ++ SaplingBlock.treeType = org.bukkit.TreeType.CRIMSON_FUNGUS; ++ } ++ // CraftBukkit end ++ ((ConfiguredFeature) holder.value()).place(level, level.getChunkSource().getGenerator(), random, pos); ++ }); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/GrowingPlantHeadBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/GrowingPlantHeadBlock.java.patch new file mode 100644 index 0000000000..4832863036 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/GrowingPlantHeadBlock.java.patch @@ -0,0 +1,160 @@ +--- a/net/minecraft/world/level/block/GrowingPlantHeadBlock.java ++++ b/net/minecraft/world/level/block/GrowingPlantHeadBlock.java +@@ -9,113 +9,116 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; ++import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.shapes.VoxelShape; + + public abstract class GrowingPlantHeadBlock extends GrowingPlantBlock implements BonemealableBlock { ++ + public static final IntegerProperty AGE = BlockStateProperties.AGE_25; + public static final int MAX_AGE = 25; + private final double growPerTickProbability; + +- protected GrowingPlantHeadBlock( +- BlockBehaviour.Properties properties, Direction growthDirection, VoxelShape shape, boolean scheduleFluidTicks, double growPerTickProbability +- ) { ++ protected GrowingPlantHeadBlock(BlockBehaviour.Properties properties, Direction growthDirection, VoxelShape shape, boolean scheduleFluidTicks, double growPerTickProbability) { + super(properties, growthDirection, shape, scheduleFluidTicks); + this.growPerTickProbability = growPerTickProbability; +- this.registerDefaultState(this.stateDefinition.any().setValue(AGE, Integer.valueOf(0))); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(GrowingPlantHeadBlock.AGE, 0)); + } + + @Override + protected abstract MapCodec codec(); + + @Override +- public BlockState getStateForPlacement(LevelAccessor level) { +- return this.defaultBlockState().setValue(AGE, Integer.valueOf(level.getRandom().nextInt(25))); ++ public IBlockData getStateForPlacement(LevelAccessor level) { ++ return (IBlockData) this.defaultBlockState().setValue(GrowingPlantHeadBlock.AGE, level.getRandom().nextInt(25)); + } + + @Override +- public boolean isRandomlyTicking(BlockState state) { +- return state.getValue(AGE) < 25; ++ public boolean isRandomlyTicking(IBlockData state) { ++ return (Integer) state.getValue(GrowingPlantHeadBlock.AGE) < 25; + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- if (state.getValue(AGE) < 25 && random.nextDouble() < this.growPerTickProbability) { +- BlockPos blockPos = pos.relative(this.growthDirection); +- if (this.canGrowInto(level.getBlockState(blockPos))) { +- level.setBlockAndUpdate(blockPos, this.getGrowIntoState(state, level.random)); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Integer) state.getValue(GrowingPlantHeadBlock.AGE) < 25 && random.nextDouble() < this.growPerTickProbability) { ++ BlockPos blockposition1 = pos.relative(this.growthDirection); ++ ++ if (this.canGrowInto(level.getBlockState(blockposition1))) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition1, this.getGrowIntoState(state, level.random)); // CraftBukkit + } + } ++ + } + +- protected BlockState getGrowIntoState(BlockState state, RandomSource random) { +- return state.cycle(AGE); ++ protected IBlockData getGrowIntoState(IBlockData state, RandomSource random) { ++ return (IBlockData) state.cycle(GrowingPlantHeadBlock.AGE); + } + +- public BlockState getMaxAgeState(BlockState state) { +- return state.setValue(AGE, Integer.valueOf(25)); ++ public IBlockData getMaxAgeState(IBlockData state) { ++ return (IBlockData) state.setValue(GrowingPlantHeadBlock.AGE, 25); + } + +- public boolean isMaxAge(BlockState state) { +- return state.getValue(AGE) == 25; ++ public boolean isMaxAge(IBlockData state) { ++ return (Integer) state.getValue(GrowingPlantHeadBlock.AGE) == 25; + } + +- protected BlockState updateBodyAfterConvertedFromHead(BlockState head, BlockState body) { ++ protected IBlockData updateBodyAfterConvertedFromHead(IBlockData head, IBlockData body) { + return body; + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { + if (facing == this.growthDirection.getOpposite() && !state.canSurvive(level, currentPos)) { +- level.scheduleTick(currentPos, this, 1); ++ level.scheduleTick(currentPos, (Block) this, 1); + } + +- if (facing != this.growthDirection || !facingState.is(this) && !facingState.is(this.getBodyBlock())) { ++ if (facing == this.growthDirection && (facingState.is((Block) this) || facingState.is(this.getBodyBlock()))) { ++ return this.updateBodyAfterConvertedFromHead(state, this.getBodyBlock().defaultBlockState()); ++ } else { + if (this.scheduleFluidTicks) { +- level.scheduleTick(currentPos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); ++ level.scheduleTick(currentPos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + + return super.updateShape(state, facing, facingState, level, currentPos, facingPos); +- } else { +- return this.updateBodyAfterConvertedFromHead(state, this.getBodyBlock().defaultBlockState()); + } + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(AGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(GrowingPlantHeadBlock.AGE); + } + + @Override +- public boolean isValidBonemealTarget(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { +- return this.canGrowInto(levelReader.getBlockState(blockPos.relative(this.growthDirection))); ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ return this.canGrowInto(iworldreader.getBlockState(blockposition.relative(this.growthDirection))); + } + + @Override +- public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, BlockState state) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return true; + } + + @Override +- public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) { +- BlockPos blockPos = pos.relative(this.growthDirection); +- int min = Math.min(state.getValue(AGE) + 1, 25); +- int blocksToGrowWhenBonemealed = this.getBlocksToGrowWhenBonemealed(random); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ BlockPos blockposition1 = pos.relative(this.growthDirection); ++ int i = Math.min((Integer) state.getValue(GrowingPlantHeadBlock.AGE) + 1, 25); ++ int j = this.getBlocksToGrowWhenBonemealed(random); + +- for (int i = 0; i < blocksToGrowWhenBonemealed && this.canGrowInto(level.getBlockState(blockPos)); i++) { +- level.setBlockAndUpdate(blockPos, state.setValue(AGE, Integer.valueOf(min))); +- blockPos = blockPos.relative(this.growthDirection); +- min = Math.min(min + 1, 25); ++ for (int k = 0; k < j && this.canGrowInto(level.getBlockState(blockposition1)); ++k) { ++ level.setBlockAndUpdate(blockposition1, (IBlockData) state.setValue(GrowingPlantHeadBlock.AGE, i)); ++ blockposition1 = blockposition1.relative(this.growthDirection); ++ i = Math.min(i + 1, 25); + } ++ + } + + protected abstract int getBlocksToGrowWhenBonemealed(RandomSource random); + +- protected abstract boolean canGrowInto(BlockState state); ++ protected abstract boolean canGrowInto(IBlockData state); + + @Override + protected GrowingPlantHeadBlock getHeadBlock() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/IceBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/IceBlock.java.patch new file mode 100644 index 0000000000..84f29ce627 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/IceBlock.java.patch @@ -0,0 +1,74 @@ +--- a/net/minecraft/world/level/block/IceBlock.java ++++ b/net/minecraft/world/level/block/IceBlock.java +@@ -9,30 +9,31 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.enchantment.EnchantmentHelper; + import net.minecraft.world.item.enchantment.Enchantments; ++import net.minecraft.world.level.EnumSkyBlock; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public class IceBlock extends HalfTransparentBlock { ++ + public static final MapCodec CODEC = simpleCodec(IceBlock::new); + + @Override + public MapCodec codec() { +- return CODEC; ++ return IceBlock.CODEC; + } + + public IceBlock(BlockBehaviour.Properties properties) { + super(properties); + } + +- public static BlockState meltsInto() { ++ public static IBlockData meltsInto() { + return Blocks.WATER.defaultBlockState(); + } + + @Override +- public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity te, ItemStack stack) { ++ public void playerDestroy(Level level, Player player, BlockPos pos, IBlockData state, @Nullable BlockEntity te, ItemStack stack) { + super.playerDestroy(level, player, pos, state, te, stack); + if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack) == 0) { + if (level.dimensionType().ultraWarm()) { +@@ -40,21 +41,29 @@ + return; + } + +- BlockState blockState = level.getBlockState(pos.below()); +- if (blockState.blocksMotion() || blockState.liquid()) { ++ IBlockData iblockdata1 = level.getBlockState(pos.below()); ++ ++ if (iblockdata1.blocksMotion() || iblockdata1.liquid()) { + level.setBlockAndUpdate(pos, meltsInto()); + } + } ++ + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- if (level.getBrightness(LightLayer.BLOCK, pos) > 11 - state.getLightBlock(level, pos)) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (level.getBrightness(EnumSkyBlock.BLOCK, pos) > 11 - state.getLightBlock(level, pos)) { + this.melt(state, level, pos); + } ++ + } + +- protected void melt(BlockState state, Level level, BlockPos pos) { ++ protected void melt(IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, level.dimensionType().ultraWarm() ? Blocks.AIR.defaultBlockState() : Blocks.WATER.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + if (level.dimensionType().ultraWarm()) { + level.removeBlock(pos, false); + } else { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/InfestedBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/InfestedBlock.java.patch new file mode 100644 index 0000000000..824b6ef241 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/InfestedBlock.java.patch @@ -0,0 +1,121 @@ +--- a/net/minecraft/world/level/block/InfestedBlock.java ++++ b/net/minecraft/world/level/block/InfestedBlock.java +@@ -3,7 +3,7 @@ + import com.google.common.collect.Maps; + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; ++import java.util.Iterator; + import java.util.Map; + import java.util.function.Supplier; + import net.minecraft.core.BlockPos; +@@ -16,72 +16,82 @@ + import net.minecraft.world.item.enchantment.Enchantments; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.Property; ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; // CraftBukkit + + public class InfestedBlock extends Block { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group(BuiltInRegistries.BLOCK.byNameCodec().fieldOf("host").forGetter(InfestedBlock::getHostBlock), propertiesCodec()) +- .apply(instance, InfestedBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(BuiltInRegistries.BLOCK.byNameCodec().fieldOf("host").forGetter(InfestedBlock::getHostBlock), propertiesCodec()).apply(instance, InfestedBlock::new); ++ }); + private final Block hostBlock; + private static final Map BLOCK_BY_HOST_BLOCK = Maps.newIdentityHashMap(); +- private static final Map HOST_TO_INFESTED_STATES = Maps.newIdentityHashMap(); +- private static final Map INFESTED_TO_HOST_STATES = Maps.newIdentityHashMap(); ++ private static final Map HOST_TO_INFESTED_STATES = Maps.newIdentityHashMap(); ++ private static final Map INFESTED_TO_HOST_STATES = Maps.newIdentityHashMap(); + + @Override + public MapCodec codec() { +- return CODEC; ++ return InfestedBlock.CODEC; + } + + public InfestedBlock(Block hostBlock, BlockBehaviour.Properties properties) { + super(properties.destroyTime(hostBlock.defaultDestroyTime() / 2.0F).explosionResistance(0.75F)); + this.hostBlock = hostBlock; +- BLOCK_BY_HOST_BLOCK.put(hostBlock, this); ++ InfestedBlock.BLOCK_BY_HOST_BLOCK.put(hostBlock, this); + } + + public Block getHostBlock() { + return this.hostBlock; + } + +- public static boolean isCompatibleHostBlock(BlockState state) { +- return BLOCK_BY_HOST_BLOCK.containsKey(state.getBlock()); ++ public static boolean isCompatibleHostBlock(IBlockData state) { ++ return InfestedBlock.BLOCK_BY_HOST_BLOCK.containsKey(state.getBlock()); + } + + private void spawnInfestation(ServerLevel level, BlockPos pos) { +- Silverfish silverfish = EntityType.SILVERFISH.create(level); +- if (silverfish != null) { +- silverfish.moveTo((double)pos.getX() + 0.5, (double)pos.getY(), (double)pos.getZ() + 0.5, 0.0F, 0.0F); +- level.addFreshEntity(silverfish); +- silverfish.spawnAnim(); ++ Silverfish entitysilverfish = (Silverfish) EntityType.SILVERFISH.create(level); ++ ++ if (entitysilverfish != null) { ++ entitysilverfish.moveTo((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, 0.0F, 0.0F); ++ level.addFreshEntity(entitysilverfish, SpawnReason.SILVERFISH_BLOCK); // CraftBukkit - add SpawnReason ++ entitysilverfish.spawnAnim(); + } ++ + } + + @Override +- public void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { + super.spawnAfterBreak(state, level, pos, stack, dropExperience); + if (level.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS) && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack) == 0) { + this.spawnInfestation(level, pos); + } ++ + } + +- public static BlockState infestedStateByHost(BlockState host) { +- return getNewStateWithProperties(HOST_TO_INFESTED_STATES, host, () -> BLOCK_BY_HOST_BLOCK.get(host.getBlock()).defaultBlockState()); ++ public static IBlockData infestedStateByHost(IBlockData host) { ++ return getNewStateWithProperties(InfestedBlock.HOST_TO_INFESTED_STATES, host, () -> { ++ return ((Block) InfestedBlock.BLOCK_BY_HOST_BLOCK.get(host.getBlock())).defaultBlockState(); ++ }); + } + +- public BlockState hostStateByInfested(BlockState infested) { +- return getNewStateWithProperties(INFESTED_TO_HOST_STATES, infested, () -> this.getHostBlock().defaultBlockState()); ++ public IBlockData hostStateByInfested(IBlockData infested) { ++ return getNewStateWithProperties(InfestedBlock.INFESTED_TO_HOST_STATES, infested, () -> { ++ return this.getHostBlock().defaultBlockState(); ++ }); + } + +- private static BlockState getNewStateWithProperties(Map stateMap, BlockState state, Supplier supplier) { +- return stateMap.computeIfAbsent(state, blockState -> { +- BlockState blockState1 = supplier.get(); ++ private static IBlockData getNewStateWithProperties(Map stateMap, IBlockData state, Supplier supplier) { ++ return (IBlockData) stateMap.computeIfAbsent(state, (iblockdata1) -> { ++ IBlockData iblockdata2 = (IBlockData) supplier.get(); + +- for (Property property : blockState.getProperties()) { +- blockState1 = blockState1.hasProperty(property) ? blockState1.setValue(property, blockState.getValue(property)) : blockState1; ++ Property iblockstate; ++ ++ for (Iterator iterator = iblockdata1.getProperties().iterator(); iterator.hasNext(); iblockdata2 = iblockdata2.hasProperty(iblockstate) ? (IBlockData) iblockdata2.setValue(iblockstate, iblockdata1.getValue(iblockstate)) : iblockdata2) { ++ iblockstate = (Property) iterator.next(); + } + +- return blockState1; ++ return iblockdata2; + }); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/LayeredCauldronBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/LayeredCauldronBlock.java.patch new file mode 100644 index 0000000000..2a4483d943 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/LayeredCauldronBlock.java.patch @@ -0,0 +1,196 @@ +--- a/net/minecraft/world/level/block/LayeredCauldronBlock.java ++++ b/net/minecraft/world/level/block/LayeredCauldronBlock.java +@@ -2,51 +2,55 @@ + + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import net.minecraft.core.BlockPos; + import net.minecraft.core.cauldron.CauldronInteraction; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.biome.Biome; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.block.CraftBlockStates; ++import org.bukkit.event.block.CauldronLevelChangeEvent; ++// CraftBukkit end + + public class LayeredCauldronBlock extends AbstractCauldronBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group( +- Biome.Precipitation.CODEC.fieldOf("precipitation").forGetter(layeredCauldronBlock -> layeredCauldronBlock.precipitationType), +- CauldronInteraction.CODEC.fieldOf("interactions").forGetter(layeredCauldronBlock -> layeredCauldronBlock.interactions), +- propertiesCodec() +- ) +- .apply(instance, LayeredCauldronBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(Biome.Precipitation.CODEC.fieldOf("precipitation").forGetter((layeredcauldronblock) -> { ++ return layeredcauldronblock.precipitationType; ++ }), CauldronInteraction.CODEC.fieldOf("interactions").forGetter((layeredcauldronblock) -> { ++ return layeredcauldronblock.interactions; ++ }), propertiesCodec()).apply(instance, LayeredCauldronBlock::new); ++ }); + public static final int MIN_FILL_LEVEL = 1; + public static final int MAX_FILL_LEVEL = 3; + public static final IntegerProperty LEVEL = BlockStateProperties.LEVEL_CAULDRON; + private static final int BASE_CONTENT_HEIGHT = 6; +- private static final double HEIGHT_PER_LEVEL = 3.0; ++ private static final double HEIGHT_PER_LEVEL = 3.0D; + private final Biome.Precipitation precipitationType; + + @Override + public MapCodec codec() { +- return CODEC; ++ return LayeredCauldronBlock.CODEC; + } + +- public LayeredCauldronBlock(Biome.Precipitation precipitation, CauldronInteraction.InteractionMap interactionMap, BlockBehaviour.Properties properties) { +- super(properties, interactionMap); +- this.precipitationType = precipitation; +- this.registerDefaultState(this.stateDefinition.any().setValue(LEVEL, Integer.valueOf(1))); ++ public LayeredCauldronBlock(Biome.Precipitation biomebase_precipitation, CauldronInteraction.a cauldroninteraction_a, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info, cauldroninteraction_a); ++ this.precipitationType = biomebase_precipitation; ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(LayeredCauldronBlock.LEVEL, 1)); + } + + @Override +- public boolean isFull(BlockState state) { +- return state.getValue(LEVEL) == 3; ++ public boolean isFull(IBlockData state) { ++ return (Integer) state.getValue(LayeredCauldronBlock.LEVEL) == 3; + } + + @Override +@@ -55,60 +59,94 @@ + } + + @Override +- protected double getContentHeight(BlockState state) { +- return (6.0 + (double)state.getValue(LEVEL).intValue() * 3.0) / 16.0; ++ protected double getContentHeight(IBlockData state) { ++ return (6.0D + (double) (Integer) state.getValue(LayeredCauldronBlock.LEVEL) * 3.0D) / 16.0D; + } + + @Override +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { + if (!level.isClientSide && entity.isOnFire() && this.isEntityInsideContent(state, pos, entity)) { +- entity.clearFire(); ++ // CraftBukkit start + if (entity.mayInteract(level, pos)) { +- this.handleEntityOnFireInside(state, level, pos); ++ if (!lowerFillLevel(state, level, pos, entity, CauldronLevelChangeEvent.ChangeReason.EXTINGUISH)) { ++ return; ++ } + } ++ entity.clearFire(); ++ // CraftBukkit end + } ++ + } + +- private void handleEntityOnFireInside(BlockState state, Level level, BlockPos pos) { ++ private void handleEntityOnFireInside(IBlockData state, Level level, BlockPos pos) { + if (this.precipitationType == Biome.Precipitation.SNOW) { +- lowerFillLevel(Blocks.WATER_CAULDRON.defaultBlockState().setValue(LEVEL, state.getValue(LEVEL)), level, pos); ++ lowerFillLevel((IBlockData) Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, (Integer) state.getValue(LayeredCauldronBlock.LEVEL)), level, pos); + } else { + lowerFillLevel(state, level, pos); + } ++ + } + +- public static void lowerFillLevel(BlockState state, Level level, BlockPos pos) { +- int i = state.getValue(LEVEL) - 1; +- BlockState blockState = i == 0 ? Blocks.CAULDRON.defaultBlockState() : state.setValue(LEVEL, Integer.valueOf(i)); +- level.setBlockAndUpdate(pos, blockState); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(blockState)); ++ public static void lowerFillLevel(IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ lowerFillLevel(state, level, pos, null, CauldronLevelChangeEvent.ChangeReason.UNKNOWN); + } + ++ public static boolean lowerFillLevel(IBlockData iblockdata, Level world, BlockPos blockposition, Entity entity, CauldronLevelChangeEvent.ChangeReason reason) { ++ int i = (Integer) iblockdata.getValue(LayeredCauldronBlock.LEVEL) - 1; ++ IBlockData iblockdata1 = i == 0 ? Blocks.CAULDRON.defaultBlockState() : (IBlockData) iblockdata.setValue(LayeredCauldronBlock.LEVEL, i); ++ ++ return changeLevel(iblockdata, world, blockposition, iblockdata1, entity, reason); ++ } ++ ++ // CraftBukkit start ++ public static boolean changeLevel(IBlockData iblockdata, Level world, BlockPos blockposition, IBlockData newBlock, Entity entity, CauldronLevelChangeEvent.ChangeReason reason) { ++ CraftBlockState newState = CraftBlockStates.getBlockState(world, blockposition); ++ newState.setData(newBlock); ++ ++ CauldronLevelChangeEvent event = new CauldronLevelChangeEvent( ++ world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), ++ (entity == null) ? null : entity.getBukkitEntity(), reason, newState ++ ); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ newState.update(true); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(newBlock)); ++ return true; ++ } ++ // CraftBukkit end ++ + @Override +- public void handlePrecipitation(BlockState state, Level level, BlockPos pos, Biome.Precipitation precipitation) { +- if (CauldronBlock.shouldHandlePrecipitation(level, precipitation) && state.getValue(LEVEL) != 3 && precipitation == this.precipitationType) { +- BlockState blockState = state.cycle(LEVEL); +- level.setBlockAndUpdate(pos, blockState); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(blockState)); ++ public void handlePrecipitation(IBlockData state, Level level, BlockPos pos, Biome.Precipitation precipitation) { ++ if (CauldronBlock.shouldHandlePrecipitation(level, precipitation) && (Integer) state.getValue(LayeredCauldronBlock.LEVEL) != 3 && precipitation == this.precipitationType) { ++ IBlockData iblockdata1 = (IBlockData) state.cycle(LayeredCauldronBlock.LEVEL); ++ ++ changeLevel(state, level, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL); // CraftBukkit + } + } + + @Override +- public int getAnalogOutputSignal(BlockState state, Level level, BlockPos pos) { +- return state.getValue(LEVEL); ++ public int getAnalogOutputSignal(IBlockData state, Level level, BlockPos pos) { ++ return (Integer) state.getValue(LayeredCauldronBlock.LEVEL); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(LEVEL); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(LayeredCauldronBlock.LEVEL); + } + + @Override +- protected void receiveStalactiteDrip(BlockState state, Level level, BlockPos pos, Fluid fluid) { ++ protected void receiveStalactiteDrip(IBlockData state, Level level, BlockPos pos, Fluid fluid) { + if (!this.isFull(state)) { +- BlockState blockState = state.setValue(LEVEL, Integer.valueOf(state.getValue(LEVEL) + 1)); +- level.setBlockAndUpdate(pos, blockState); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(blockState)); ++ IBlockData iblockdata1 = (IBlockData) state.setValue(LayeredCauldronBlock.LEVEL, (Integer) state.getValue(LayeredCauldronBlock.LEVEL) + 1); ++ ++ // CraftBukkit start ++ if (!changeLevel(state, level, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL)) { ++ return; ++ } ++ // CraftBukkit end + level.levelEvent(1047, pos, 0); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/LeavesBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/LeavesBlock.java.patch new file mode 100644 index 0000000000..9772e8b635 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/LeavesBlock.java.patch @@ -0,0 +1,199 @@ +--- a/net/minecraft/world/level/block/LeavesBlock.java ++++ b/net/minecraft/world/level/block/LeavesBlock.java +@@ -14,17 +14,20 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.block.state.properties.IntegerProperty; ++import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.LeavesDecayEvent; // CraftBukkit + + public class LeavesBlock extends Block implements SimpleWaterloggedBlock { ++ + public static final MapCodec CODEC = simpleCodec(LeavesBlock::new); + public static final int DECAY_DISTANCE = 7; + public static final IntegerProperty DISTANCE = BlockStateProperties.DISTANCE; +@@ -34,105 +37,110 @@ + + @Override + public MapCodec codec() { +- return CODEC; ++ return LeavesBlock.CODEC; + } + + public LeavesBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState( +- this.stateDefinition +- .any() +- .setValue(DISTANCE, Integer.valueOf(7)) +- .setValue(PERSISTENT, Boolean.valueOf(false)) +- .setValue(WATERLOGGED, Boolean.valueOf(false)) +- ); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(LeavesBlock.DISTANCE, 7)).setValue(LeavesBlock.PERSISTENT, false)).setValue(LeavesBlock.WATERLOGGED, false)); + } + + @Override +- public VoxelShape getBlockSupportShape(BlockState state, BlockGetter reader, BlockPos pos) { ++ public VoxelShape getBlockSupportShape(IBlockData state, BlockGetter reader, BlockPos pos) { + return Shapes.empty(); + } + + @Override +- public boolean isRandomlyTicking(BlockState state) { +- return state.getValue(DISTANCE) == 7 && !state.getValue(PERSISTENT); ++ public boolean isRandomlyTicking(IBlockData state) { ++ return (Integer) state.getValue(LeavesBlock.DISTANCE) == 7 && !(Boolean) state.getValue(LeavesBlock.PERSISTENT); + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (this.decaying(state)) { ++ // CraftBukkit start ++ LeavesDecayEvent event = new LeavesDecayEvent(level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled() || level.getBlockState(pos).getBlock() != this) { ++ return; ++ } ++ // CraftBukkit end + dropResources(state, level, pos); + level.removeBlock(pos, false); + } ++ + } + +- protected boolean decaying(BlockState state) { +- return !state.getValue(PERSISTENT) && state.getValue(DISTANCE) == 7; ++ protected boolean decaying(IBlockData state) { ++ return !(Boolean) state.getValue(LeavesBlock.PERSISTENT) && (Integer) state.getValue(LeavesBlock.DISTANCE) == 7; + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + level.setBlock(pos, updateDistance(state, level, pos), 3); + } + + @Override +- public int getLightBlock(BlockState state, BlockGetter level, BlockPos pos) { ++ public int getLightBlock(IBlockData state, BlockGetter level, BlockPos pos) { + return 1; + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- if (state.getValue(WATERLOGGED)) { +- level.scheduleTick(currentPos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if ((Boolean) state.getValue(LeavesBlock.WATERLOGGED)) { ++ level.scheduleTick(currentPos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + + int i = getDistanceAt(facingState) + 1; +- if (i != 1 || state.getValue(DISTANCE) != i) { +- level.scheduleTick(currentPos, this, 1); ++ ++ if (i != 1 || (Integer) state.getValue(LeavesBlock.DISTANCE) != i) { ++ level.scheduleTick(currentPos, (Block) this, 1); + } + + return state; + } + +- private static BlockState updateDistance(BlockState state, LevelAccessor level, BlockPos pos) { ++ private static IBlockData updateDistance(IBlockData state, LevelAccessor level, BlockPos pos) { + int i = 7; +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ Direction[] aenumdirection = Direction.values(); ++ int j = aenumdirection.length; + +- for (Direction direction : Direction.values()) { +- mutableBlockPos.setWithOffset(pos, direction); +- i = Math.min(i, getDistanceAt(level.getBlockState(mutableBlockPos)) + 1); ++ for (int k = 0; k < j; ++k) { ++ Direction enumdirection = aenumdirection[k]; ++ ++ blockposition_mutableblockposition.setWithOffset(pos, enumdirection); ++ i = Math.min(i, getDistanceAt(level.getBlockState(blockposition_mutableblockposition)) + 1); + if (i == 1) { + break; + } + } + +- return state.setValue(DISTANCE, Integer.valueOf(i)); ++ return (IBlockData) state.setValue(LeavesBlock.DISTANCE, i); + } + +- private static int getDistanceAt(BlockState neighbor) { ++ private static int getDistanceAt(IBlockData neighbor) { + return getOptionalDistanceAt(neighbor).orElse(7); + } + +- public static OptionalInt getOptionalDistanceAt(BlockState state) { +- if (state.is(BlockTags.LOGS)) { +- return OptionalInt.of(0); +- } else { +- return state.hasProperty(DISTANCE) ? OptionalInt.of(state.getValue(DISTANCE)) : OptionalInt.empty(); +- } ++ public static OptionalInt getOptionalDistanceAt(IBlockData state) { ++ return state.is(BlockTags.LOGS) ? OptionalInt.of(0) : (state.hasProperty(LeavesBlock.DISTANCE) ? OptionalInt.of((Integer) state.getValue(LeavesBlock.DISTANCE)) : OptionalInt.empty()); + } + + @Override +- public FluidState getFluidState(BlockState state) { +- return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(LeavesBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override +- public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { + if (level.isRainingAt(pos.above())) { + if (random.nextInt(15) == 1) { +- BlockPos blockPos = pos.below(); +- BlockState blockState = level.getBlockState(blockPos); +- if (!blockState.canOcclude() || !blockState.isFaceSturdy(level, blockPos, Direction.UP)) { ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ if (!iblockdata1.canOcclude() || !iblockdata1.isFaceSturdy(level, blockposition1, Direction.UP)) { + ParticleUtils.spawnParticleBelow(level, pos, random, ParticleTypes.DRIPPING_WATER); + } + } +@@ -140,16 +148,15 @@ + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(DISTANCE, PERSISTENT, WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(LeavesBlock.DISTANCE, LeavesBlock.PERSISTENT, LeavesBlock.WATERLOGGED); + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- FluidState fluidState = context.getLevel().getFluidState(context.getClickedPos()); +- BlockState blockState = this.defaultBlockState() +- .setValue(PERSISTENT, Boolean.valueOf(true)) +- .setValue(WATERLOGGED, Boolean.valueOf(fluidState.getType() == Fluids.WATER)); +- return updateDistance(blockState, context.getLevel(), context.getClickedPos()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ FluidState fluid = context.getLevel().getFluidState(context.getClickedPos()); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) this.defaultBlockState().setValue(LeavesBlock.PERSISTENT, true)).setValue(LeavesBlock.WATERLOGGED, fluid.getType() == Fluids.WATER); ++ ++ return updateDistance(iblockdata, context.getLevel(), context.getClickedPos()); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/LecternBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/LecternBlock.java.patch new file mode 100644 index 0000000000..58d32abee4 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/LecternBlock.java.patch @@ -0,0 +1,399 @@ +--- a/net/minecraft/world/level/block/LecternBlock.java ++++ b/net/minecraft/world/level/block/LecternBlock.java +@@ -11,9 +11,9 @@ + import net.minecraft.stats.Stats; + import net.minecraft.tags.ItemTags; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; ++import net.minecraft.world.ITileInventory; + import net.minecraft.world.InteractionResult; +-import net.minecraft.world.MenuProvider; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; +@@ -25,140 +25,121 @@ + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.LecternBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.block.state.properties.DirectionProperty; + import net.minecraft.world.level.gameevent.GameEvent; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; + + public class LecternBlock extends BaseEntityBlock { ++ + public static final MapCodec CODEC = simpleCodec(LecternBlock::new); + public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING; + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + public static final BooleanProperty HAS_BOOK = BlockStateProperties.HAS_BOOK; +- public static final VoxelShape SHAPE_BASE = Block.box(0.0, 0.0, 0.0, 16.0, 2.0, 16.0); +- public static final VoxelShape SHAPE_POST = Block.box(4.0, 2.0, 4.0, 12.0, 14.0, 12.0); +- public static final VoxelShape SHAPE_COMMON = Shapes.or(SHAPE_BASE, SHAPE_POST); +- public static final VoxelShape SHAPE_TOP_PLATE = Block.box(0.0, 15.0, 0.0, 16.0, 15.0, 16.0); +- public static final VoxelShape SHAPE_COLLISION = Shapes.or(SHAPE_COMMON, SHAPE_TOP_PLATE); +- public static final VoxelShape SHAPE_WEST = Shapes.or( +- Block.box(1.0, 10.0, 0.0, 5.333333, 14.0, 16.0), +- Block.box(5.333333, 12.0, 0.0, 9.666667, 16.0, 16.0), +- Block.box(9.666667, 14.0, 0.0, 14.0, 18.0, 16.0), +- SHAPE_COMMON +- ); +- public static final VoxelShape SHAPE_NORTH = Shapes.or( +- Block.box(0.0, 10.0, 1.0, 16.0, 14.0, 5.333333), +- Block.box(0.0, 12.0, 5.333333, 16.0, 16.0, 9.666667), +- Block.box(0.0, 14.0, 9.666667, 16.0, 18.0, 14.0), +- SHAPE_COMMON +- ); +- public static final VoxelShape SHAPE_EAST = Shapes.or( +- Block.box(10.666667, 10.0, 0.0, 15.0, 14.0, 16.0), +- Block.box(6.333333, 12.0, 0.0, 10.666667, 16.0, 16.0), +- Block.box(2.0, 14.0, 0.0, 6.333333, 18.0, 16.0), +- SHAPE_COMMON +- ); +- public static final VoxelShape SHAPE_SOUTH = Shapes.or( +- Block.box(0.0, 10.0, 10.666667, 16.0, 14.0, 15.0), +- Block.box(0.0, 12.0, 6.333333, 16.0, 16.0, 10.666667), +- Block.box(0.0, 14.0, 2.0, 16.0, 18.0, 6.333333), +- SHAPE_COMMON +- ); ++ public static final VoxelShape SHAPE_BASE = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 2.0D, 16.0D); ++ public static final VoxelShape SHAPE_POST = Block.box(4.0D, 2.0D, 4.0D, 12.0D, 14.0D, 12.0D); ++ public static final VoxelShape SHAPE_COMMON = Shapes.or(LecternBlock.SHAPE_BASE, LecternBlock.SHAPE_POST); ++ public static final VoxelShape SHAPE_TOP_PLATE = Block.box(0.0D, 15.0D, 0.0D, 16.0D, 15.0D, 16.0D); ++ public static final VoxelShape SHAPE_COLLISION = Shapes.or(LecternBlock.SHAPE_COMMON, LecternBlock.SHAPE_TOP_PLATE); ++ public static final VoxelShape SHAPE_WEST = Shapes.or(Block.box(1.0D, 10.0D, 0.0D, 5.333333D, 14.0D, 16.0D), Block.box(5.333333D, 12.0D, 0.0D, 9.666667D, 16.0D, 16.0D), Block.box(9.666667D, 14.0D, 0.0D, 14.0D, 18.0D, 16.0D), LecternBlock.SHAPE_COMMON); ++ public static final VoxelShape SHAPE_NORTH = Shapes.or(Block.box(0.0D, 10.0D, 1.0D, 16.0D, 14.0D, 5.333333D), Block.box(0.0D, 12.0D, 5.333333D, 16.0D, 16.0D, 9.666667D), Block.box(0.0D, 14.0D, 9.666667D, 16.0D, 18.0D, 14.0D), LecternBlock.SHAPE_COMMON); ++ public static final VoxelShape SHAPE_EAST = Shapes.or(Block.box(10.666667D, 10.0D, 0.0D, 15.0D, 14.0D, 16.0D), Block.box(6.333333D, 12.0D, 0.0D, 10.666667D, 16.0D, 16.0D), Block.box(2.0D, 14.0D, 0.0D, 6.333333D, 18.0D, 16.0D), LecternBlock.SHAPE_COMMON); ++ public static final VoxelShape SHAPE_SOUTH = Shapes.or(Block.box(0.0D, 10.0D, 10.666667D, 16.0D, 14.0D, 15.0D), Block.box(0.0D, 12.0D, 6.333333D, 16.0D, 16.0D, 10.666667D), Block.box(0.0D, 14.0D, 2.0D, 16.0D, 18.0D, 6.333333D), LecternBlock.SHAPE_COMMON); + private static final int PAGE_CHANGE_IMPULSE_TICKS = 2; + + @Override + public MapCodec codec() { +- return CODEC; ++ return LecternBlock.CODEC; + } + + protected LecternBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState( +- this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(POWERED, Boolean.valueOf(false)).setValue(HAS_BOOK, Boolean.valueOf(false)) +- ); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(LecternBlock.FACING, Direction.NORTH)).setValue(LecternBlock.POWERED, false)).setValue(LecternBlock.HAS_BOOK, false)); + } + + @Override +- public RenderShape getRenderShape(BlockState state) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Override +- public VoxelShape getOcclusionShape(BlockState state, BlockGetter level, BlockPos pos) { +- return SHAPE_COMMON; ++ public VoxelShape getOcclusionShape(IBlockData state, BlockGetter level, BlockPos pos) { ++ return LecternBlock.SHAPE_COMMON; + } + + @Override +- public boolean useShapeForLightOcclusion(BlockState state) { ++ public boolean useShapeForLightOcclusion(IBlockData state) { + return true; + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- Level level = context.getLevel(); +- ItemStack itemInHand = context.getItemInHand(); +- Player player = context.getPlayer(); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ Level world = context.getLevel(); ++ ItemStack itemstack = context.getItemInHand(); ++ Player entityhuman = context.getPlayer(); + boolean flag = false; +- if (!level.isClientSide && player != null && player.canUseGameMasterBlocks()) { +- CompoundTag blockEntityData = BlockItem.getBlockEntityData(itemInHand); +- if (blockEntityData != null && blockEntityData.contains("Book")) { ++ ++ if (!world.isClientSide && entityhuman != null && entityhuman.canUseGameMasterBlocks()) { ++ CompoundTag nbttagcompound = BlockItem.getBlockEntityData(itemstack); ++ ++ if (nbttagcompound != null && nbttagcompound.contains("Book")) { + flag = true; + } + } + +- return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite()).setValue(HAS_BOOK, Boolean.valueOf(flag)); ++ return (IBlockData) ((IBlockData) this.defaultBlockState().setValue(LecternBlock.FACING, context.getHorizontalDirection().getOpposite())).setValue(LecternBlock.HAS_BOOK, flag); + } + + @Override +- public VoxelShape getCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPE_COLLISION; ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return LecternBlock.SHAPE_COLLISION; + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- switch ((Direction)state.getValue(FACING)) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ switch ((Direction) state.getValue(LecternBlock.FACING)) { + case NORTH: +- return SHAPE_NORTH; ++ return LecternBlock.SHAPE_NORTH; + case SOUTH: +- return SHAPE_SOUTH; ++ return LecternBlock.SHAPE_SOUTH; + case EAST: +- return SHAPE_EAST; ++ return LecternBlock.SHAPE_EAST; + case WEST: +- return SHAPE_WEST; ++ return LecternBlock.SHAPE_WEST; + default: +- return SHAPE_COMMON; ++ return LecternBlock.SHAPE_COMMON; + } + } + + @Override +- public BlockState rotate(BlockState state, Rotation rotation) { +- return state.setValue(FACING, rotation.rotate(state.getValue(FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return (IBlockData) state.setValue(LecternBlock.FACING, rotation.rotate((Direction) state.getValue(LecternBlock.FACING))); + } + + @Override +- public BlockState mirror(BlockState state, Mirror mirror) { +- return state.rotate(mirror.getRotation(state.getValue(FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(LecternBlock.FACING))); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(FACING, POWERED, HAS_BOOK); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(LecternBlock.FACING, LecternBlock.POWERED, LecternBlock.HAS_BOOK); + } + + @Override +- public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { + return new LecternBlockEntity(pos, state); + } + +- public static boolean tryPlaceBook(@Nullable Entity entity, Level level, BlockPos pos, BlockState state, ItemStack stack) { +- if (!state.getValue(HAS_BOOK)) { ++ public static boolean tryPlaceBook(@Nullable Entity entity, Level level, BlockPos pos, IBlockData state, ItemStack stack) { ++ if (!(Boolean) state.getValue(LecternBlock.HAS_BOOK)) { + if (!level.isClientSide) { + placeBook(entity, level, pos, state, stack); + } +@@ -169,49 +150,55 @@ + } + } + +- private static void placeBook(@Nullable Entity entity, Level level, BlockPos pos, BlockState state, ItemStack stack) { +- if (level.getBlockEntity(pos) instanceof LecternBlockEntity lecternBlockEntity) { +- lecternBlockEntity.setBook(stack.split(1)); ++ private static void placeBook(@Nullable Entity entity, Level level, BlockPos pos, IBlockData state, ItemStack stack) { ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof LecternBlockEntity) { ++ LecternBlockEntity tileentitylectern = (LecternBlockEntity) tileentity; ++ ++ tileentitylectern.setBook(stack.split(1)); + resetBookState(entity, level, pos, state, true); +- level.playSound(null, pos, SoundEvents.BOOK_PUT, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.playSound((Player) null, pos, SoundEvents.BOOK_PUT, SoundSource.BLOCKS, 1.0F, 1.0F); + } ++ + } + +- public static void resetBookState(@Nullable Entity entity, Level level, BlockPos pos, BlockState state, boolean hasBook) { +- BlockState blockState = state.setValue(POWERED, Boolean.valueOf(false)).setValue(HAS_BOOK, Boolean.valueOf(hasBook)); +- level.setBlock(pos, blockState, 3); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, blockState)); ++ public static void resetBookState(@Nullable Entity entity, Level level, BlockPos pos, IBlockData state, boolean hasBook) { ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) state.setValue(LecternBlock.POWERED, false)).setValue(LecternBlock.HAS_BOOK, hasBook); ++ ++ level.setBlock(pos, iblockdata1, 3); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, iblockdata1)); + updateBelow(level, pos, state); + } + +- public static void signalPageChange(Level level, BlockPos pos, BlockState state) { ++ public static void signalPageChange(Level level, BlockPos pos, IBlockData state) { + changePowered(level, pos, state, true); + level.scheduleTick(pos, state.getBlock(), 2); + level.levelEvent(1043, pos, 0); + } + +- private static void changePowered(Level level, BlockPos pos, BlockState state, boolean powered) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(powered)), 3); ++ private static void changePowered(Level level, BlockPos pos, IBlockData state, boolean powered) { ++ level.setBlock(pos, (IBlockData) state.setValue(LecternBlock.POWERED, powered), 3); + updateBelow(level, pos, state); + } + +- private static void updateBelow(Level level, BlockPos pos, BlockState state) { ++ private static void updateBelow(Level level, BlockPos pos, IBlockData state) { + level.updateNeighborsAt(pos.below(), state.getBlock()); + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + changePowered(level, pos, state, false); + } + + @Override +- public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { + if (!state.is(newState.getBlock())) { +- if (state.getValue(HAS_BOOK)) { ++ if ((Boolean) state.getValue(LecternBlock.HAS_BOOK)) { + this.popBook(state, level, pos); + } + +- if (state.getValue(POWERED)) { ++ if ((Boolean) state.getValue(LecternBlock.POWERED)) { + level.updateNeighborsAt(pos.below(), this); + } + +@@ -219,47 +206,52 @@ + } + } + +- private void popBook(BlockState state, Level level, BlockPos pos) { +- if (level.getBlockEntity(pos) instanceof LecternBlockEntity lecternBlockEntity) { +- Direction direction = state.getValue(FACING); +- ItemStack itemStack = lecternBlockEntity.getBook().copy(); +- float f = 0.25F * (float)direction.getStepX(); +- float f1 = 0.25F * (float)direction.getStepZ(); +- ItemEntity itemEntity = new ItemEntity( +- level, (double)pos.getX() + 0.5 + (double)f, (double)(pos.getY() + 1), (double)pos.getZ() + 0.5 + (double)f1, itemStack +- ); +- itemEntity.setDefaultPickUpDelay(); +- level.addFreshEntity(itemEntity); +- lecternBlockEntity.clearContent(); ++ private void popBook(IBlockData state, Level level, BlockPos pos) { ++ BlockEntity tileentity = level.getBlockEntity(pos, false); // CraftBukkit - don't validate, type may be changed already ++ ++ if (tileentity instanceof LecternBlockEntity) { ++ LecternBlockEntity tileentitylectern = (LecternBlockEntity) tileentity; ++ Direction enumdirection = (Direction) state.getValue(LecternBlock.FACING); ++ ItemStack itemstack = tileentitylectern.getBook().copy(); ++ if (itemstack.isEmpty()) return; // CraftBukkit - SPIGOT-5500 ++ float f = 0.25F * (float) enumdirection.getStepX(); ++ float f1 = 0.25F * (float) enumdirection.getStepZ(); ++ ItemEntity entityitem = new ItemEntity(level, (double) pos.getX() + 0.5D + (double) f, (double) (pos.getY() + 1), (double) pos.getZ() + 0.5D + (double) f1, itemstack); ++ ++ entityitem.setDefaultPickUpDelay(); ++ level.addFreshEntity(entityitem); ++ tileentitylectern.clearContent(); + } ++ + } + + @Override +- public boolean isSignalSource(BlockState state) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + + @Override +- public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { +- return blockState.getValue(POWERED) ? 15 : 0; ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return (Boolean) blockState.getValue(LecternBlock.POWERED) ? 15 : 0; + } + + @Override +- public int getDirectSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { +- return side == Direction.UP && blockState.getValue(POWERED) ? 15 : 0; ++ public int getDirectSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return side == Direction.UP && (Boolean) blockState.getValue(LecternBlock.POWERED) ? 15 : 0; + } + + @Override +- public boolean hasAnalogOutputSignal(BlockState state) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return true; + } + + @Override +- public int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) { +- if (blockState.getValue(HAS_BOOK)) { +- BlockEntity blockEntity = level.getBlockEntity(pos); +- if (blockEntity instanceof LecternBlockEntity) { +- return ((LecternBlockEntity)blockEntity).getRedstoneSignal(); ++ public int getAnalogOutputSignal(IBlockData blockState, Level level, BlockPos pos) { ++ if ((Boolean) blockState.getValue(LecternBlock.HAS_BOOK)) { ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof LecternBlockEntity) { ++ return ((LecternBlockEntity) tileentity).getRedstoneSignal(); + } + } + +@@ -267,35 +259,38 @@ + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { +- if (state.getValue(HAS_BOOK)) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ if ((Boolean) state.getValue(LecternBlock.HAS_BOOK)) { + if (!level.isClientSide) { + this.openScreen(level, pos, player); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + } else { +- ItemStack itemInHand = player.getItemInHand(hand); +- return !itemInHand.isEmpty() && !itemInHand.is(ItemTags.LECTERN_BOOKS) ? InteractionResult.CONSUME : InteractionResult.PASS; ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ return !itemstack.isEmpty() && !itemstack.is(ItemTags.LECTERN_BOOKS) ? InteractionResult.CONSUME : InteractionResult.PASS; + } + } + + @Nullable + @Override +- public MenuProvider getMenuProvider(BlockState state, Level level, BlockPos pos) { +- return !state.getValue(HAS_BOOK) ? null : super.getMenuProvider(state, level, pos); ++ public ITileInventory getMenuProvider(IBlockData state, Level level, BlockPos pos) { ++ return !(Boolean) state.getValue(LecternBlock.HAS_BOOK) ? null : super.getMenuProvider(state, level, pos); + } + + private void openScreen(Level level, BlockPos pos, Player player) { +- BlockEntity blockEntity = level.getBlockEntity(pos); +- if (blockEntity instanceof LecternBlockEntity) { +- player.openMenu((LecternBlockEntity)blockEntity); ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof LecternBlockEntity) { ++ player.openMenu((LecternBlockEntity) tileentity); + player.awardStat(Stats.INTERACT_WITH_LECTERN); + } ++ + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/LeverBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/LeverBlock.java.patch new file mode 100644 index 0000000000..edb624f642 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/LeverBlock.java.patch @@ -0,0 +1,256 @@ +--- a/net/minecraft/world/level/block/LeverBlock.java ++++ b/net/minecraft/world/level/block/LeverBlock.java +@@ -4,12 +4,13 @@ + import java.util.function.BiConsumer; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.particles.DustParticleOptions; ++import net.minecraft.core.particles.ParticleParamRedstone; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.BlockGetter; +@@ -17,7 +18,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.AttachFace; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; +@@ -26,123 +27,142 @@ + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class LeverBlock extends FaceAttachedHorizontalDirectionalBlock { ++ + public static final MapCodec CODEC = simpleCodec(LeverBlock::new); + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + protected static final int DEPTH = 6; + protected static final int WIDTH = 6; + protected static final int HEIGHT = 8; +- protected static final VoxelShape NORTH_AABB = Block.box(5.0, 4.0, 10.0, 11.0, 12.0, 16.0); +- protected static final VoxelShape SOUTH_AABB = Block.box(5.0, 4.0, 0.0, 11.0, 12.0, 6.0); +- protected static final VoxelShape WEST_AABB = Block.box(10.0, 4.0, 5.0, 16.0, 12.0, 11.0); +- protected static final VoxelShape EAST_AABB = Block.box(0.0, 4.0, 5.0, 6.0, 12.0, 11.0); +- protected static final VoxelShape UP_AABB_Z = Block.box(5.0, 0.0, 4.0, 11.0, 6.0, 12.0); +- protected static final VoxelShape UP_AABB_X = Block.box(4.0, 0.0, 5.0, 12.0, 6.0, 11.0); +- protected static final VoxelShape DOWN_AABB_Z = Block.box(5.0, 10.0, 4.0, 11.0, 16.0, 12.0); +- protected static final VoxelShape DOWN_AABB_X = Block.box(4.0, 10.0, 5.0, 12.0, 16.0, 11.0); ++ protected static final VoxelShape NORTH_AABB = Block.box(5.0D, 4.0D, 10.0D, 11.0D, 12.0D, 16.0D); ++ protected static final VoxelShape SOUTH_AABB = Block.box(5.0D, 4.0D, 0.0D, 11.0D, 12.0D, 6.0D); ++ protected static final VoxelShape WEST_AABB = Block.box(10.0D, 4.0D, 5.0D, 16.0D, 12.0D, 11.0D); ++ protected static final VoxelShape EAST_AABB = Block.box(0.0D, 4.0D, 5.0D, 6.0D, 12.0D, 11.0D); ++ protected static final VoxelShape UP_AABB_Z = Block.box(5.0D, 0.0D, 4.0D, 11.0D, 6.0D, 12.0D); ++ protected static final VoxelShape UP_AABB_X = Block.box(4.0D, 0.0D, 5.0D, 12.0D, 6.0D, 11.0D); ++ protected static final VoxelShape DOWN_AABB_Z = Block.box(5.0D, 10.0D, 4.0D, 11.0D, 16.0D, 12.0D); ++ protected static final VoxelShape DOWN_AABB_X = Block.box(4.0D, 10.0D, 5.0D, 12.0D, 16.0D, 11.0D); + + @Override + public MapCodec codec() { +- return CODEC; ++ return LeverBlock.CODEC; + } + + protected LeverBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState( +- this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(POWERED, Boolean.valueOf(false)).setValue(FACE, AttachFace.WALL) +- ); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(LeverBlock.FACING, Direction.NORTH)).setValue(LeverBlock.POWERED, false)).setValue(LeverBlock.FACE, AttachFace.WALL)); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- switch ((AttachFace)state.getValue(FACE)) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ switch ((AttachFace) state.getValue(LeverBlock.FACE)) { + case FLOOR: +- switch (state.getValue(FACING).getAxis()) { ++ switch (((Direction) state.getValue(LeverBlock.FACING)).getAxis()) { + case X: +- return UP_AABB_X; ++ return LeverBlock.UP_AABB_X; + case Z: + default: +- return UP_AABB_Z; ++ return LeverBlock.UP_AABB_Z; + } + case WALL: +- switch ((Direction)state.getValue(FACING)) { ++ switch ((Direction) state.getValue(LeverBlock.FACING)) { + case EAST: +- return EAST_AABB; ++ return LeverBlock.EAST_AABB; + case WEST: +- return WEST_AABB; ++ return LeverBlock.WEST_AABB; + case SOUTH: +- return SOUTH_AABB; ++ return LeverBlock.SOUTH_AABB; + case NORTH: + default: +- return NORTH_AABB; ++ return LeverBlock.NORTH_AABB; + } + case CEILING: + default: +- switch (state.getValue(FACING).getAxis()) { ++ switch (((Direction) state.getValue(LeverBlock.FACING)).getAxis()) { + case X: +- return DOWN_AABB_X; ++ return LeverBlock.DOWN_AABB_X; + case Z: + default: +- return DOWN_AABB_Z; ++ return LeverBlock.DOWN_AABB_Z; + } + } + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ IBlockData iblockdata1; ++ + if (level.isClientSide) { +- BlockState blockState = state.cycle(POWERED); +- if (blockState.getValue(POWERED)) { +- makeParticle(blockState, level, pos, 1.0F); ++ iblockdata1 = (IBlockData) state.cycle(LeverBlock.POWERED); ++ if ((Boolean) iblockdata1.getValue(LeverBlock.POWERED)) { ++ makeParticle(iblockdata1, level, pos, 1.0F); + } + + return InteractionResult.SUCCESS; + } else { +- BlockState blockState = this.pull(state, level, pos); +- float f = blockState.getValue(POWERED) ? 0.6F : 0.5F; +- level.playSound(null, pos, SoundEvents.LEVER_CLICK, SoundSource.BLOCKS, 0.3F, f); +- level.gameEvent(player, blockState.getValue(POWERED) ? GameEvent.BLOCK_ACTIVATE : GameEvent.BLOCK_DEACTIVATE, pos); ++ // CraftBukkit start - Interact Lever ++ boolean powered = state.getValue(LeverBlock.POWERED); // Old powered state ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ int old = (powered) ? 15 : 0; ++ int current = (!powered) ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if ((eventRedstone.getNewCurrent() > 0) != (!powered)) { ++ return InteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ ++ iblockdata1 = this.pull(state, level, pos); ++ float f = (Boolean) iblockdata1.getValue(LeverBlock.POWERED) ? 0.6F : 0.5F; ++ ++ level.playSound((Player) null, pos, SoundEvents.LEVER_CLICK, SoundSource.BLOCKS, 0.3F, f); ++ level.gameEvent((Entity) player, (Boolean) iblockdata1.getValue(LeverBlock.POWERED) ? GameEvent.BLOCK_ACTIVATE : GameEvent.BLOCK_DEACTIVATE, pos); + return InteractionResult.CONSUME; + } + } + + @Override +- public void onExplosionHit(BlockState blockState, Level level, BlockPos blockPos, Explosion explosion, BiConsumer biConsumer) { +- if (explosion.getBlockInteraction() == Explosion.BlockInteraction.TRIGGER_BLOCK && !level.isClientSide()) { +- this.pull(blockState, level, blockPos); ++ public void onExplosionHit(IBlockData iblockdata, Level world, BlockPos blockposition, Explosion explosion, BiConsumer biconsumer) { ++ if (explosion.getBlockInteraction() == Explosion.Effect.TRIGGER_BLOCK && !world.isClientSide()) { ++ this.pull(iblockdata, world, blockposition); + } + +- super.onExplosionHit(blockState, level, blockPos, explosion, biConsumer); ++ super.onExplosionHit(iblockdata, world, blockposition, explosion, biconsumer); + } + +- public BlockState pull(BlockState state, Level level, BlockPos pos) { +- state = state.cycle(POWERED); ++ public IBlockData pull(IBlockData state, Level level, BlockPos pos) { ++ state = (IBlockData) state.cycle(LeverBlock.POWERED); + level.setBlock(pos, state, 3); + this.updateNeighbours(state, level, pos); + return state; + } + +- private static void makeParticle(BlockState state, LevelAccessor level, BlockPos pos, float alpha) { +- Direction opposite = state.getValue(FACING).getOpposite(); +- Direction opposite1 = getConnectedDirection(state).getOpposite(); +- double d = (double)pos.getX() + 0.5 + 0.1 * (double)opposite.getStepX() + 0.2 * (double)opposite1.getStepX(); +- double d1 = (double)pos.getY() + 0.5 + 0.1 * (double)opposite.getStepY() + 0.2 * (double)opposite1.getStepY(); +- double d2 = (double)pos.getZ() + 0.5 + 0.1 * (double)opposite.getStepZ() + 0.2 * (double)opposite1.getStepZ(); +- level.addParticle(new DustParticleOptions(DustParticleOptions.REDSTONE_PARTICLE_COLOR, alpha), d, d1, d2, 0.0, 0.0, 0.0); ++ private static void makeParticle(IBlockData state, LevelAccessor level, BlockPos pos, float alpha) { ++ Direction enumdirection = ((Direction) state.getValue(LeverBlock.FACING)).getOpposite(); ++ Direction enumdirection1 = getConnectedDirection(state).getOpposite(); ++ double d0 = (double) pos.getX() + 0.5D + 0.1D * (double) enumdirection.getStepX() + 0.2D * (double) enumdirection1.getStepX(); ++ double d1 = (double) pos.getY() + 0.5D + 0.1D * (double) enumdirection.getStepY() + 0.2D * (double) enumdirection1.getStepY(); ++ double d2 = (double) pos.getZ() + 0.5D + 0.1D * (double) enumdirection.getStepZ() + 0.2D * (double) enumdirection1.getStepZ(); ++ ++ level.addParticle(new ParticleParamRedstone(ParticleParamRedstone.REDSTONE_PARTICLE_COLOR, alpha), d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + + @Override +- public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { +- if (state.getValue(POWERED) && random.nextFloat() < 0.25F) { ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(LeverBlock.POWERED) && random.nextFloat() < 0.25F) { + makeParticle(state, level, pos, 0.5F); + } ++ + } + + @Override +- public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { + if (!isMoving && !state.is(newState.getBlock())) { +- if (state.getValue(POWERED)) { ++ if ((Boolean) state.getValue(LeverBlock.POWERED)) { + this.updateNeighbours(state, level, pos); + } + +@@ -151,27 +171,27 @@ + } + + @Override +- public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { +- return blockState.getValue(POWERED) ? 15 : 0; ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return (Boolean) blockState.getValue(LeverBlock.POWERED) ? 15 : 0; + } + + @Override +- public int getDirectSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { +- return blockState.getValue(POWERED) && getConnectedDirection(blockState) == side ? 15 : 0; ++ public int getDirectSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return (Boolean) blockState.getValue(LeverBlock.POWERED) && getConnectedDirection(blockState) == side ? 15 : 0; + } + + @Override +- public boolean isSignalSource(BlockState state) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + +- private void updateNeighbours(BlockState state, Level level, BlockPos pos) { ++ private void updateNeighbours(IBlockData state, Level level, BlockPos pos) { + level.updateNeighborsAt(pos, this); + level.updateNeighborsAt(pos.relative(getConnectedDirection(state).getOpposite()), this); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(FACE, FACING, POWERED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(LeverBlock.FACE, LeverBlock.FACING, LeverBlock.POWERED); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/LightningRodBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/LightningRodBlock.java.patch new file mode 100644 index 0000000000..ad14c4d47a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/LightningRodBlock.java.patch @@ -0,0 +1,216 @@ +--- a/net/minecraft/world/level/block/LightningRodBlock.java ++++ b/net/minecraft/world/level/block/LightningRodBlock.java +@@ -14,6 +14,7 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LightningBolt; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.Projectile; + import net.minecraft.world.entity.projectile.ThrownTrident; + import net.minecraft.world.item.context.BlockPlaceContext; +@@ -21,17 +22,23 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.levelgen.Heightmap; ++import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockRedstoneEvent; ++// CraftBukkit end + + public class LightningRodBlock extends RodBlock implements SimpleWaterloggedBlock { ++ + public static final MapCodec CODEC = simpleCodec(LightningRodBlock::new); + public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; +@@ -41,77 +48,86 @@ + + @Override + public MapCodec codec() { +- return CODEC; ++ return LightningRodBlock.CODEC; + } + + public LightningRodBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState( +- this.stateDefinition.any().setValue(FACING, Direction.UP).setValue(WATERLOGGED, Boolean.valueOf(false)).setValue(POWERED, Boolean.valueOf(false)) +- ); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(LightningRodBlock.FACING, Direction.UP)).setValue(LightningRodBlock.WATERLOGGED, false)).setValue(LightningRodBlock.POWERED, false)); + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- FluidState fluidState = context.getLevel().getFluidState(context.getClickedPos()); +- boolean flag = fluidState.getType() == Fluids.WATER; +- return this.defaultBlockState().setValue(FACING, context.getClickedFace()).setValue(WATERLOGGED, Boolean.valueOf(flag)); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ FluidState fluid = context.getLevel().getFluidState(context.getClickedPos()); ++ boolean flag = fluid.getType() == Fluids.WATER; ++ ++ return (IBlockData) ((IBlockData) this.defaultBlockState().setValue(LightningRodBlock.FACING, context.getClickedFace())).setValue(LightningRodBlock.WATERLOGGED, flag); + } + + @Override +- public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { +- if (state.getValue(WATERLOGGED)) { +- level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); ++ public IBlockData updateShape(IBlockData state, Direction direction, IBlockData neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { ++ if ((Boolean) state.getValue(LightningRodBlock.WATERLOGGED)) { ++ level.scheduleTick(pos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + + return super.updateShape(state, direction, neighborState, level, pos, neighborPos); + } + + @Override +- public FluidState getFluidState(BlockState state) { +- return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(LightningRodBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override +- public int getSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { +- return state.getValue(POWERED) ? 15 : 0; ++ public int getSignal(IBlockData state, BlockGetter level, BlockPos pos, Direction direction) { ++ return (Boolean) state.getValue(LightningRodBlock.POWERED) ? 15 : 0; + } + + @Override +- public int getDirectSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { +- return state.getValue(POWERED) && state.getValue(FACING) == direction ? 15 : 0; ++ public int getDirectSignal(IBlockData state, BlockGetter level, BlockPos pos, Direction direction) { ++ return (Boolean) state.getValue(LightningRodBlock.POWERED) && state.getValue(LightningRodBlock.FACING) == direction ? 15 : 0; + } + +- public void onLightningStrike(BlockState state, Level level, BlockPos pos) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(true)), 3); ++ public void onLightningStrike(IBlockData state, Level level, BlockPos pos) { ++ // CraftBukkit start ++ boolean powered = state.getValue(LightningRodBlock.POWERED); ++ int old = (powered) ? 15 : 0; ++ int current = (!powered) ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(level, pos), old, current); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if (eventRedstone.getNewCurrent() <= 0) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(LightningRodBlock.POWERED, true), 3); + this.updateNeighbours(state, level, pos); +- level.scheduleTick(pos, this, 8); +- level.levelEvent(3002, pos, state.getValue(FACING).getAxis().ordinal()); ++ level.scheduleTick(pos, (Block) this, 8); ++ level.levelEvent(3002, pos, ((Direction) state.getValue(LightningRodBlock.FACING)).getAxis().ordinal()); + } + +- private void updateNeighbours(BlockState state, Level level, BlockPos pos) { +- level.updateNeighborsAt(pos.relative(state.getValue(FACING).getOpposite()), this); ++ private void updateNeighbours(IBlockData state, Level level, BlockPos pos) { ++ level.updateNeighborsAt(pos.relative(((Direction) state.getValue(LightningRodBlock.FACING)).getOpposite()), this); + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(false)), 3); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ level.setBlock(pos, (IBlockData) state.setValue(LightningRodBlock.POWERED, false), 3); + this.updateNeighbours(state, level, pos); + } + + @Override +- public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { +- if (level.isThundering() +- && (long)level.random.nextInt(200) <= level.getGameTime() % 200L +- && pos.getY() == level.getHeight(Heightmap.Types.WORLD_SURFACE, pos.getX(), pos.getZ()) - 1) { +- ParticleUtils.spawnParticlesAlongAxis(state.getValue(FACING).getAxis(), level, pos, 0.125, ParticleTypes.ELECTRIC_SPARK, UniformInt.of(1, 2)); ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if (level.isThundering() && (long) level.random.nextInt(200) <= level.getGameTime() % 200L && pos.getY() == level.getHeight(Heightmap.Types.WORLD_SURFACE, pos.getX(), pos.getZ()) - 1) { ++ ParticleUtils.spawnParticlesAlongAxis(((Direction) state.getValue(LightningRodBlock.FACING)).getAxis(), level, pos, 0.125D, ParticleTypes.ELECTRIC_SPARK, UniformInt.of(1, 2)); + } + } + + @Override +- public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean movedByPiston) { + if (!state.is(newState.getBlock())) { +- if (state.getValue(POWERED)) { ++ if ((Boolean) state.getValue(LightningRodBlock.POWERED)) { + this.updateNeighbours(state, level, pos); + } + +@@ -120,39 +136,44 @@ + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean movedByPiston) { + if (!state.is(oldState.getBlock())) { +- if (state.getValue(POWERED) && !level.getBlockTicks().hasScheduledTick(pos, this)) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(false)), 18); ++ if ((Boolean) state.getValue(LightningRodBlock.POWERED) && !level.getBlockTicks().hasScheduledTick(pos, this)) { ++ level.setBlock(pos, (IBlockData) state.setValue(LightningRodBlock.POWERED, false), 18); + } ++ + } + } + + @Override +- public void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) { +- if (level.isThundering() && projectile instanceof ThrownTrident && ((ThrownTrident)projectile).isChanneling()) { +- BlockPos blockPos = hit.getBlockPos(); +- if (level.canSeeSky(blockPos)) { +- LightningBolt lightningBolt = EntityType.LIGHTNING_BOLT.create(level); +- if (lightningBolt != null) { +- lightningBolt.moveTo(Vec3.atBottomCenterOf(blockPos.above())); +- Entity owner = projectile.getOwner(); +- lightningBolt.setCause(owner instanceof ServerPlayer ? (ServerPlayer)owner : null); +- level.addFreshEntity(lightningBolt); ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { ++ if (level.isThundering() && projectile instanceof ThrownTrident && ((ThrownTrident) projectile).isChanneling()) { ++ BlockPos blockposition = hit.getBlockPos(); ++ ++ if (level.canSeeSky(blockposition)) { ++ LightningBolt entitylightning = (LightningBolt) EntityType.LIGHTNING_BOLT.create(level); ++ ++ if (entitylightning != null) { ++ entitylightning.moveTo(Vec3.atBottomCenterOf(blockposition.above())); ++ Entity entity = projectile.getOwner(); ++ ++ entitylightning.setCause(entity instanceof ServerPlayer ? (ServerPlayer) entity : null); ++ ((ServerLevel) level).strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.TRIDENT); // CraftBukkit + } + +- level.playSound(null, blockPos, SoundEvents.TRIDENT_THUNDER, SoundSource.WEATHER, 5.0F, 1.0F); ++ level.playSound((Player) null, blockposition, SoundEvents.TRIDENT_THUNDER, SoundSource.WEATHER, 5.0F, 1.0F); + } + } ++ + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(FACING, POWERED, WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(LightningRodBlock.FACING, LightningRodBlock.POWERED, LightningRodBlock.WATERLOGGED); + } + + @Override +- public boolean isSignalSource(BlockState state) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/LiquidBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/LiquidBlock.java.patch new file mode 100644 index 0000000000..0464db1371 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/LiquidBlock.java.patch @@ -0,0 +1,255 @@ +--- a/net/minecraft/world/level/block/LiquidBlock.java ++++ b/net/minecraft/world/level/block/LiquidBlock.java +@@ -2,11 +2,11 @@ + + import com.google.common.collect.ImmutableList; + import com.google.common.collect.Lists; ++import com.google.common.collect.UnmodifiableIterator; + import com.mojang.serialization.Codec; + import com.mojang.serialization.DataResult; + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import java.util.Collections; + import java.util.List; + import java.util.Optional; +@@ -24,41 +24,51 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.level.material.FlowingFluid; +-import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.level.storage.loot.LootParams; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; + + public class LiquidBlock extends Block implements BucketPickup { +- private static final Codec FLOWING_FLUID = BuiltInRegistries.FLUID +- .byNameCodec() +- .comapFlatMap( +- fluid -> fluid instanceof FlowingFluid flowingFluid ? DataResult.success(flowingFluid) : DataResult.error(() -> "Not a flowing fluid: " + fluid), +- flowingFluid -> (Fluid)flowingFluid +- ); +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group(FLOWING_FLUID.fieldOf("fluid").forGetter(liquidBlock -> liquidBlock.fluid), propertiesCodec()) +- .apply(instance, LiquidBlock::new) +- ); ++ ++ private static final Codec FLOWING_FLUID = BuiltInRegistries.FLUID.byNameCodec().comapFlatMap((fluidtype) -> { ++ DataResult dataresult; // CraftBukkit - decompile error ++ ++ if (fluidtype instanceof FlowingFluid) { ++ FlowingFluid fluidtypeflowing = (FlowingFluid) fluidtype; ++ ++ dataresult = DataResult.success(fluidtypeflowing); ++ } else { ++ dataresult = DataResult.error(() -> { ++ return "Not a flowing fluid: " + fluidtype; ++ }); ++ } ++ ++ return dataresult; ++ }, (fluidtypeflowing) -> { ++ return fluidtypeflowing; ++ }); ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(LiquidBlock.FLOWING_FLUID.fieldOf("fluid").forGetter((blockfluids) -> { ++ return blockfluids.fluid; ++ }), propertiesCodec()).apply(instance, LiquidBlock::new); ++ }); + public static final IntegerProperty LEVEL = BlockStateProperties.LEVEL; + protected final FlowingFluid fluid; + private final List stateCache; +- public static final VoxelShape STABLE_SHAPE = Block.box(0.0, 0.0, 0.0, 16.0, 8.0, 16.0); +- public static final ImmutableList POSSIBLE_FLOW_DIRECTIONS = ImmutableList.of( +- Direction.DOWN, Direction.SOUTH, Direction.NORTH, Direction.EAST, Direction.WEST +- ); ++ public static final VoxelShape STABLE_SHAPE = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 8.0D, 16.0D); ++ public static final ImmutableList POSSIBLE_FLOW_DIRECTIONS = ImmutableList.of(Direction.DOWN, Direction.SOUTH, Direction.NORTH, Direction.EAST, Direction.WEST); + + @Override + public MapCodec codec() { +- return CODEC; ++ return LiquidBlock.CODEC; + } + + protected LiquidBlock(FlowingFluid fluid, BlockBehaviour.Properties properties) { +@@ -67,78 +77,76 @@ + this.stateCache = Lists.newArrayList(); + this.stateCache.add(fluid.getSource(false)); + +- for (int i = 1; i < 8; i++) { ++ for (int i = 1; i < 8; ++i) { + this.stateCache.add(fluid.getFlowing(8 - i, false)); + } + + this.stateCache.add(fluid.getFlowing(8, true)); +- this.registerDefaultState(this.stateDefinition.any().setValue(LEVEL, Integer.valueOf(0))); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(LiquidBlock.LEVEL, 0)); + } + + @Override +- public VoxelShape getCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return context.isAbove(STABLE_SHAPE, pos, true) +- && state.getValue(LEVEL) == 0 +- && context.canStandOnFluid(level.getFluidState(pos.above()), state.getFluidState()) +- ? STABLE_SHAPE +- : Shapes.empty(); ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return context.isAbove(LiquidBlock.STABLE_SHAPE, pos, true) && (Integer) state.getValue(LiquidBlock.LEVEL) == 0 && context.canStandOnFluid(level.getFluidState(pos.above()), state.getFluidState()) ? LiquidBlock.STABLE_SHAPE : Shapes.empty(); + } + + @Override +- public boolean isRandomlyTicking(BlockState state) { ++ public boolean isRandomlyTicking(IBlockData state) { + return state.getFluidState().isRandomlyTicking(); + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + state.getFluidState().randomTick(level, pos, random); + } + + @Override +- public boolean propagatesSkylightDown(BlockState state, BlockGetter reader, BlockPos pos) { ++ public boolean propagatesSkylightDown(IBlockData state, BlockGetter reader, BlockPos pos) { + return false; + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return !this.fluid.is(FluidTags.LAVA); + } + + @Override +- public FluidState getFluidState(BlockState state) { +- int i = state.getValue(LEVEL); +- return this.stateCache.get(Math.min(i, 8)); ++ public FluidState getFluidState(IBlockData state) { ++ int i = (Integer) state.getValue(LiquidBlock.LEVEL); ++ ++ return (FluidState) this.stateCache.get(Math.min(i, 8)); + } + + @Override +- public boolean skipRendering(BlockState state, BlockState adjacentBlockState, Direction side) { ++ public boolean skipRendering(IBlockData state, IBlockData adjacentBlockState, Direction side) { + return adjacentBlockState.getFluidState().getType().isSame(this.fluid); + } + + @Override +- public RenderShape getRenderShape(BlockState state) { +- return RenderShape.INVISIBLE; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.INVISIBLE; + } + + @Override +- public List getDrops(BlockState state, LootParams.Builder params) { ++ public List getDrops(IBlockData state, LootParams.Builder params) { + return Collections.emptyList(); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return Shapes.empty(); + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { + if (this.shouldSpreadLiquid(level, pos, state)) { + level.scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay(level)); + } ++ + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { + if (state.getFluidState().isSource() || facingState.getFluidState().isSource()) { + level.scheduleTick(currentPos, state.getFluidState().getType(), this.fluid.getTickDelay(level)); + } +@@ -147,28 +155,39 @@ + } + + @Override +- public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { + if (this.shouldSpreadLiquid(level, pos, state)) { + level.scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay(level)); + } ++ + } + +- private boolean shouldSpreadLiquid(Level level, BlockPos pos, BlockState state) { ++ private boolean shouldSpreadLiquid(Level level, BlockPos pos, IBlockData state) { + if (this.fluid.is(FluidTags.LAVA)) { +- boolean isSoulSoil = level.getBlockState(pos.below()).is(Blocks.SOUL_SOIL); ++ boolean flag = level.getBlockState(pos.below()).is(Blocks.SOUL_SOIL); ++ UnmodifiableIterator unmodifiableiterator = LiquidBlock.POSSIBLE_FLOW_DIRECTIONS.iterator(); + +- for (Direction direction : POSSIBLE_FLOW_DIRECTIONS) { +- BlockPos blockPos = pos.relative(direction.getOpposite()); +- if (level.getFluidState(blockPos).is(FluidTags.WATER)) { ++ while (unmodifiableiterator.hasNext()) { ++ Direction enumdirection = (Direction) unmodifiableiterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection.getOpposite()); ++ ++ if (level.getFluidState(blockposition1).is(FluidTags.WATER)) { + Block block = level.getFluidState(pos).isSource() ? Blocks.OBSIDIAN : Blocks.COBBLESTONE; +- level.setBlockAndUpdate(pos, block.defaultBlockState()); +- this.fizz(level, pos); ++ ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, block.defaultBlockState())) { ++ this.fizz(level, pos); ++ } ++ // CraftBukkit end + return false; + } + +- if (isSoulSoil && level.getBlockState(blockPos).is(Blocks.BLUE_ICE)) { +- level.setBlockAndUpdate(pos, Blocks.BASALT.defaultBlockState()); +- this.fizz(level, pos); ++ if (flag && level.getBlockState(blockposition1).is(Blocks.BLUE_ICE)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, Blocks.BASALT.defaultBlockState())) { ++ this.fizz(level, pos); ++ } ++ // CraftBukkit end + return false; + } + } +@@ -182,14 +201,14 @@ + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(LEVEL); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(LiquidBlock.LEVEL); + } + + @Override +- public ItemStack pickupBlock(@Nullable Player player, LevelAccessor levelAccessor, BlockPos blockPos, BlockState blockState) { +- if (blockState.getValue(LEVEL) == 0) { +- levelAccessor.setBlock(blockPos, Blocks.AIR.defaultBlockState(), 11); ++ public ItemStack pickupBlock(@Nullable Player entityhuman, LevelAccessor generatoraccess, BlockPos blockposition, IBlockData iblockdata) { ++ if ((Integer) iblockdata.getValue(LiquidBlock.LEVEL) == 0) { ++ generatoraccess.setBlock(blockposition, Blocks.AIR.defaultBlockState(), 11); + return new ItemStack(this.fluid.getBucket()); + } else { + return ItemStack.EMPTY; diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/MagmaBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/MagmaBlock.java.patch new file mode 100644 index 0000000000..121ba5692a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/MagmaBlock.java.patch @@ -0,0 +1,61 @@ +--- a/net/minecraft/world/level/block/MagmaBlock.java ++++ b/net/minecraft/world/level/block/MagmaBlock.java +@@ -11,15 +11,16 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public class MagmaBlock extends Block { ++ + public static final MapCodec CODEC = simpleCodec(MagmaBlock::new); + private static final int BUBBLE_COLUMN_CHECK_DELAY = 20; + + @Override + public MapCodec codec() { +- return CODEC; ++ return MagmaBlock.CODEC; + } + + public MagmaBlock(BlockBehaviour.Properties properties) { +@@ -27,30 +28,32 @@ + } + + @Override +- public void stepOn(Level level, BlockPos pos, BlockState state, Entity entity) { +- if (!entity.isSteppingCarefully() && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity)entity)) { ++ public void stepOn(Level level, BlockPos pos, IBlockData state, Entity entity) { ++ if (!entity.isSteppingCarefully() && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity) entity)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); // CraftBukkit + entity.hurt(level.damageSources().hotFloor(), 1.0F); ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = null; // CraftBukkit + } + + super.stepOn(level, pos, state, entity); + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + BubbleColumnBlock.updateColumn(level, pos.above(), state); + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { + if (facing == Direction.UP && facingState.is(Blocks.WATER)) { +- level.scheduleTick(currentPos, this, 20); ++ level.scheduleTick(currentPos, (Block) this, 20); + } + + return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { +- level.scheduleTick(pos, this, 20); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ level.scheduleTick(pos, (Block) this, 20); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/MultifaceSpreader.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/MultifaceSpreader.java.patch new file mode 100644 index 0000000000..5ed8f85432 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/MultifaceSpreader.java.patch @@ -0,0 +1,288 @@ +--- a/net/minecraft/world/level/block/MultifaceSpreader.java ++++ b/net/minecraft/world/level/block/MultifaceSpreader.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.block; + + import com.google.common.annotations.VisibleForTesting; ++import java.util.Objects; + import java.util.Optional; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +@@ -8,99 +9,98 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.LevelAccessor; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public class MultifaceSpreader { +- public static final MultifaceSpreader.SpreadType[] DEFAULT_SPREAD_ORDER = new MultifaceSpreader.SpreadType[]{ +- MultifaceSpreader.SpreadType.SAME_POSITION, MultifaceSpreader.SpreadType.SAME_PLANE, MultifaceSpreader.SpreadType.WRAP_AROUND +- }; ++ ++ public static final MultifaceSpreader.SpreadType[] DEFAULT_SPREAD_ORDER = new MultifaceSpreader.SpreadType[]{MultifaceSpreader.SpreadType.SAME_POSITION, MultifaceSpreader.SpreadType.SAME_PLANE, MultifaceSpreader.SpreadType.WRAP_AROUND}; + private final MultifaceSpreader.SpreadConfig config; + +- public MultifaceSpreader(MultifaceBlock config) { +- this(new MultifaceSpreader.DefaultSpreaderConfig(config)); ++ public MultifaceSpreader(MultifaceBlock block) { ++ this((MultifaceSpreader.SpreadConfig) (new MultifaceSpreader.DefaultSpreaderConfig(block))); + } + + public MultifaceSpreader(MultifaceSpreader.SpreadConfig config) { + this.config = config; + } + +- public boolean canSpreadInAnyDirection(BlockState state, BlockGetter level, BlockPos pos, Direction spreadDirection) { +- return Direction.stream() +- .anyMatch(face -> this.getSpreadFromFaceTowardDirection(state, level, pos, spreadDirection, face, this.config::canSpreadInto).isPresent()); ++ public boolean canSpreadInAnyDirection(IBlockData state, BlockGetter level, BlockPos pos, Direction spreadDirection) { ++ return Direction.stream().anyMatch((enumdirection1) -> { ++ MultifaceSpreader.SpreadConfig multifacespreader_b = this.config; ++ ++ Objects.requireNonNull(this.config); ++ return this.getSpreadFromFaceTowardDirection(state, level, pos, spreadDirection, enumdirection1, multifacespreader_b::canSpreadInto).isPresent(); ++ }); + } + +- public Optional spreadFromRandomFaceTowardRandomDirection( +- BlockState state, LevelAccessor level, BlockPos pos, RandomSource random +- ) { +- return Direction.allShuffled(random) +- .stream() +- .filter(direction -> this.config.canSpreadFrom(state, direction)) +- .map(spreadDirection -> this.spreadFromFaceTowardRandomDirection(state, level, pos, spreadDirection, random, false)) +- .filter(Optional::isPresent) +- .findFirst() +- .orElse(Optional.empty()); ++ public Optional spreadFromRandomFaceTowardRandomDirection(IBlockData state, LevelAccessor level, BlockPos pos, RandomSource random) { ++ return (Optional) Direction.allShuffled(random).stream().filter((enumdirection) -> { ++ return this.config.canSpreadFrom(state, enumdirection); ++ }).map((enumdirection) -> { ++ return this.spreadFromFaceTowardRandomDirection(state, level, pos, enumdirection, random, false); ++ }).filter(Optional::isPresent).findFirst().orElse(Optional.empty()); + } + +- public long spreadAll(BlockState state, LevelAccessor level, BlockPos pos, boolean markForPostprocessing) { +- return Direction.stream() +- .filter(direction -> this.config.canSpreadFrom(state, direction)) +- .map(spreadDirection -> this.spreadFromFaceTowardAllDirections(state, level, pos, spreadDirection, markForPostprocessing)) +- .reduce(0L, Long::sum); ++ public long spreadAll(IBlockData state, LevelAccessor level, BlockPos pos, boolean markForPostprocessing) { ++ return (Long) Direction.stream().filter((enumdirection) -> { ++ return this.config.canSpreadFrom(state, enumdirection); ++ }).map((enumdirection) -> { ++ return this.spreadFromFaceTowardAllDirections(state, level, pos, enumdirection, markForPostprocessing); ++ }).reduce(0L, Long::sum); + } + +- public Optional spreadFromFaceTowardRandomDirection( +- BlockState state, LevelAccessor level, BlockPos pos, Direction spreadDirection, RandomSource random, boolean markForPostprocessing +- ) { +- return Direction.allShuffled(random) +- .stream() +- .map(face -> this.spreadFromFaceTowardDirection(state, level, pos, spreadDirection, face, markForPostprocessing)) +- .filter(Optional::isPresent) +- .findFirst() +- .orElse(Optional.empty()); ++ public Optional spreadFromFaceTowardRandomDirection(IBlockData state, LevelAccessor level, BlockPos pos, Direction spreadDirection, RandomSource random, boolean markForPostprocessing) { ++ return (Optional) Direction.allShuffled(random).stream().map((enumdirection1) -> { ++ return this.spreadFromFaceTowardDirection(state, level, pos, spreadDirection, enumdirection1, markForPostprocessing); ++ }).filter(Optional::isPresent).findFirst().orElse(Optional.empty()); + } + +- private long spreadFromFaceTowardAllDirections( +- BlockState state, LevelAccessor level, BlockPos pos, Direction spreadDirection, boolean markForPostprocessing +- ) { +- return Direction.stream() +- .map(face -> this.spreadFromFaceTowardDirection(state, level, pos, spreadDirection, face, markForPostprocessing)) +- .filter(Optional::isPresent) +- .count(); ++ private long spreadFromFaceTowardAllDirections(IBlockData state, LevelAccessor level, BlockPos pos, Direction spreadDirection, boolean markForPostprocessing) { ++ return Direction.stream().map((enumdirection1) -> { ++ return this.spreadFromFaceTowardDirection(state, level, pos, spreadDirection, enumdirection1, markForPostprocessing); ++ }).filter(Optional::isPresent).count(); + } + + @VisibleForTesting +- public Optional spreadFromFaceTowardDirection( +- BlockState state, LevelAccessor level, BlockPos pos, Direction spreadDirection, Direction face, boolean markForPostprocessing +- ) { +- return this.getSpreadFromFaceTowardDirection(state, level, pos, spreadDirection, face, this.config::canSpreadInto) +- .flatMap(spreadPos -> this.spreadToFace(level, spreadPos, markForPostprocessing)); ++ public Optional spreadFromFaceTowardDirection(IBlockData state, LevelAccessor level, BlockPos pos, Direction spreadDirection, Direction face, boolean markForPostprocessing) { ++ MultifaceSpreader.SpreadConfig multifacespreader_b = this.config; ++ ++ Objects.requireNonNull(this.config); ++ return this.getSpreadFromFaceTowardDirection(state, level, pos, spreadDirection, face, multifacespreader_b::canSpreadInto).flatMap((multifacespreader_c) -> { ++ return this.spreadToFace(level, multifacespreader_c, markForPostprocessing); ++ }); + } + +- public Optional getSpreadFromFaceTowardDirection( +- BlockState state, BlockGetter level, BlockPos pos, Direction spreadDirection, Direction face, MultifaceSpreader.SpreadPredicate predicate +- ) { ++ public Optional getSpreadFromFaceTowardDirection(IBlockData state, BlockGetter level, BlockPos pos, Direction spreadDirection, Direction face, MultifaceSpreader.SpreadPredicate predicate) { + if (face.getAxis() == spreadDirection.getAxis()) { + return Optional.empty(); +- } else if (this.config.isOtherBlockValidAsSource(state) || this.config.hasFace(state, spreadDirection) && !this.config.hasFace(state, face)) { +- for (MultifaceSpreader.SpreadType spreadType : this.config.getSpreadTypes()) { +- MultifaceSpreader.SpreadPos spreadPos = spreadType.getSpreadPos(pos, face, spreadDirection); +- if (predicate.test(level, pos, spreadPos)) { +- return Optional.of(spreadPos); ++ } else if (!this.config.isOtherBlockValidAsSource(state) && (!this.config.hasFace(state, spreadDirection) || this.config.hasFace(state, face))) { ++ return Optional.empty(); ++ } else { ++ MultifaceSpreader.SpreadType[] amultifacespreader_e = this.config.getSpreadTypes(); ++ int i = amultifacespreader_e.length; ++ ++ for (int j = 0; j < i; ++j) { ++ MultifaceSpreader.SpreadType multifacespreader_e = amultifacespreader_e[j]; ++ MultifaceSpreader.c multifacespreader_c = multifacespreader_e.getSpreadPos(pos, face, spreadDirection); ++ ++ if (predicate.test(level, pos, multifacespreader_c)) { ++ return Optional.of(multifacespreader_c); + } + } + + return Optional.empty(); +- } else { +- return Optional.empty(); + } + } + +- public Optional spreadToFace(LevelAccessor level, MultifaceSpreader.SpreadPos pos, boolean markForPostprocessing) { +- BlockState blockState = level.getBlockState(pos.pos()); +- return this.config.placeBlock(level, pos, blockState, markForPostprocessing) ? Optional.of(pos) : Optional.empty(); ++ public Optional spreadToFace(LevelAccessor level, MultifaceSpreader.c pos, boolean markForPostprocessing) { ++ IBlockData iblockdata = level.getBlockState(pos.pos()); ++ ++ return this.config.placeBlock(level, pos, iblockdata, markForPostprocessing) ? Optional.of(pos) : Optional.empty(); + } + + public static class DefaultSpreaderConfig implements MultifaceSpreader.SpreadConfig { ++ + protected MultifaceBlock block; + + public DefaultSpreaderConfig(MultifaceBlock block) { +@@ -109,86 +109,93 @@ + + @Nullable + @Override +- public BlockState getStateForPlacement(BlockState currentState, BlockGetter level, BlockPos pos, Direction lookingDirection) { ++ public IBlockData getStateForPlacement(IBlockData currentState, BlockGetter level, BlockPos pos, Direction lookingDirection) { + return this.block.getStateForPlacement(currentState, level, pos, lookingDirection); + } + +- protected boolean stateCanBeReplaced(BlockGetter level, BlockPos pos, BlockPos spreadPos, Direction direction, BlockState state) { +- return state.isAir() || state.is(this.block) || state.is(Blocks.WATER) && state.getFluidState().isSource(); ++ protected boolean stateCanBeReplaced(BlockGetter level, BlockPos pos, BlockPos spreadPos, Direction direction, IBlockData state) { ++ return state.isAir() || state.is((Block) this.block) || state.is(Blocks.WATER) && state.getFluidState().isSource(); + } + + @Override +- public boolean canSpreadInto(BlockGetter level, BlockPos pos, MultifaceSpreader.SpreadPos spreadPos) { +- BlockState blockState = level.getBlockState(spreadPos.pos()); +- return this.stateCanBeReplaced(level, pos, spreadPos.pos(), spreadPos.face(), blockState) +- && this.block.isValidStateForPlacement(level, blockState, spreadPos.pos(), spreadPos.face()); ++ public boolean canSpreadInto(BlockGetter level, BlockPos pos, MultifaceSpreader.c spreadPos) { ++ IBlockData iblockdata = level.getBlockState(spreadPos.pos()); ++ ++ return this.stateCanBeReplaced(level, pos, spreadPos.pos(), spreadPos.face(), iblockdata) && this.block.isValidStateForPlacement(level, iblockdata, spreadPos.pos(), spreadPos.face()); + } + } + + public interface SpreadConfig { ++ + @Nullable +- BlockState getStateForPlacement(BlockState currentState, BlockGetter level, BlockPos pos, Direction lookingDirection); ++ IBlockData getStateForPlacement(IBlockData currentState, BlockGetter level, BlockPos pos, Direction lookingDirection); + +- boolean canSpreadInto(BlockGetter level, BlockPos pos, MultifaceSpreader.SpreadPos spreadPos); ++ boolean canSpreadInto(BlockGetter level, BlockPos pos, MultifaceSpreader.c spreadPos); + + default MultifaceSpreader.SpreadType[] getSpreadTypes() { + return MultifaceSpreader.DEFAULT_SPREAD_ORDER; + } + +- default boolean hasFace(BlockState state, Direction direction) { ++ default boolean hasFace(IBlockData state, Direction direction) { + return MultifaceBlock.hasFace(state, direction); + } + +- default boolean isOtherBlockValidAsSource(BlockState otherBlock) { ++ default boolean isOtherBlockValidAsSource(IBlockData otherBlock) { + return false; + } + +- default boolean canSpreadFrom(BlockState state, Direction direction) { ++ default boolean canSpreadFrom(IBlockData state, Direction direction) { + return this.isOtherBlockValidAsSource(state) || this.hasFace(state, direction); + } + +- default boolean placeBlock(LevelAccessor level, MultifaceSpreader.SpreadPos pos, BlockState state, boolean markForPostprocessing) { +- BlockState stateForPlacement = this.getStateForPlacement(state, level, pos.pos(), pos.face()); +- if (stateForPlacement != null) { ++ default boolean placeBlock(LevelAccessor level, MultifaceSpreader.c pos, IBlockData state, boolean markForPostprocessing) { ++ IBlockData iblockdata1 = this.getStateForPlacement(state, level, pos.pos(), pos.face()); ++ ++ if (iblockdata1 != null) { + if (markForPostprocessing) { + level.getChunk(pos.pos()).markPosForPostprocessing(pos.pos()); + } + +- return level.setBlock(pos.pos(), stateForPlacement, 2); ++ return org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos.source(), pos.pos(), iblockdata1, 2); // CraftBukkit + } else { + return false; + } + } + } + +- public static record SpreadPos(BlockPos pos, Direction face) { +- } +- + @FunctionalInterface + public interface SpreadPredicate { +- boolean test(BlockGetter level, BlockPos pos, MultifaceSpreader.SpreadPos spreadPos); ++ ++ boolean test(BlockGetter level, BlockPos pos, MultifaceSpreader.c spreadPos); + } + + public static enum SpreadType { ++ + SAME_POSITION { + @Override +- public MultifaceSpreader.SpreadPos getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection) { +- return new MultifaceSpreader.SpreadPos(pos, face); ++ public MultifaceSpreader.c getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection) { ++ return new MultifaceSpreader.c(pos, face, pos); // CraftBukkit + } + }, + SAME_PLANE { + @Override +- public MultifaceSpreader.SpreadPos getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection) { +- return new MultifaceSpreader.SpreadPos(pos.relative(face), spreadDirection); ++ public MultifaceSpreader.c getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection) { ++ return new MultifaceSpreader.c(pos.relative(face), spreadDirection, pos); // CraftBukkit + } + }, + WRAP_AROUND { + @Override +- public MultifaceSpreader.SpreadPos getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection) { +- return new MultifaceSpreader.SpreadPos(pos.relative(face).relative(spreadDirection), face.getOpposite()); ++ public MultifaceSpreader.c getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection) { ++ return new MultifaceSpreader.c(pos.relative(face).relative(spreadDirection), face.getOpposite(), pos); // CraftBukkit + } + }; + +- public abstract MultifaceSpreader.SpreadPos getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection); ++ SpreadType() {} ++ ++ public abstract MultifaceSpreader.c getSpreadPos(BlockPos pos, Direction face, Direction spreadDirection); + } ++ ++ public static record c(BlockPos pos, Direction face, BlockPos source) { // CraftBukkit ++ ++ } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/MushroomBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/MushroomBlock.java.patch new file mode 100644 index 0000000000..8f59742221 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/MushroomBlock.java.patch @@ -0,0 +1,168 @@ +--- a/net/minecraft/world/level/block/MushroomBlock.java ++++ b/net/minecraft/world/level/block/MushroomBlock.java +@@ -2,7 +2,7 @@ + + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; ++import java.util.Iterator; + import java.util.Optional; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Holder; +@@ -15,88 +15,97 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.TreeType; ++// CraftBukkit end + + public class MushroomBlock extends BushBlock implements BonemealableBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group( +- ResourceKey.codec(Registries.CONFIGURED_FEATURE).fieldOf("feature").forGetter(mushroomBlock -> mushroomBlock.feature), propertiesCodec() +- ) +- .apply(instance, MushroomBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(ResourceKey.codec(Registries.CONFIGURED_FEATURE).fieldOf("feature").forGetter((blockmushroom) -> { ++ return blockmushroom.feature; ++ }), propertiesCodec()).apply(instance, MushroomBlock::new); ++ }); + protected static final float AABB_OFFSET = 3.0F; +- protected static final VoxelShape SHAPE = Block.box(5.0, 0.0, 5.0, 11.0, 6.0, 11.0); ++ protected static final VoxelShape SHAPE = Block.box(5.0D, 0.0D, 5.0D, 11.0D, 6.0D, 11.0D); + private final ResourceKey> feature; + + @Override + public MapCodec codec() { +- return CODEC; ++ return MushroomBlock.CODEC; + } + +- public MushroomBlock(ResourceKey> resourceKey, BlockBehaviour.Properties properties) { +- super(properties); +- this.feature = resourceKey; ++ public MushroomBlock(ResourceKey> resourcekey, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info); ++ this.feature = resourcekey; + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPE; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return MushroomBlock.SHAPE; + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (random.nextInt(25) == 0) { + int i = 5; +- int i1 = 4; ++ boolean flag = true; ++ Iterator iterator = BlockPos.betweenClosed(pos.offset(-4, -1, -4), pos.offset(4, 1, 4)).iterator(); + +- for (BlockPos blockPos : BlockPos.betweenClosed(pos.offset(-4, -1, -4), pos.offset(4, 1, 4))) { +- if (level.getBlockState(blockPos).is(this)) { +- if (--i <= 0) { ++ while (iterator.hasNext()) { ++ BlockPos blockposition1 = (BlockPos) iterator.next(); ++ ++ if (level.getBlockState(blockposition1).is((Block) this)) { ++ --i; ++ if (i <= 0) { + return; + } + } + } + +- BlockPos blockPos1 = pos.offset(random.nextInt(3) - 1, random.nextInt(2) - random.nextInt(2), random.nextInt(3) - 1); ++ BlockPos blockposition2 = pos.offset(random.nextInt(3) - 1, random.nextInt(2) - random.nextInt(2), random.nextInt(3) - 1); + +- for (int i2 = 0; i2 < 4; i2++) { +- if (level.isEmptyBlock(blockPos1) && state.canSurvive(level, blockPos1)) { +- pos = blockPos1; ++ for (int j = 0; j < 4; ++j) { ++ if (level.isEmptyBlock(blockposition2) && state.canSurvive(level, blockposition2)) { ++ pos = blockposition2; + } + +- blockPos1 = pos.offset(random.nextInt(3) - 1, random.nextInt(2) - random.nextInt(2), random.nextInt(3) - 1); ++ blockposition2 = pos.offset(random.nextInt(3) - 1, random.nextInt(2) - random.nextInt(2), random.nextInt(3) - 1); + } + +- if (level.isEmptyBlock(blockPos1) && state.canSurvive(level, blockPos1)) { +- level.setBlock(blockPos1, state, 2); ++ if (level.isEmptyBlock(blockposition2) && state.canSurvive(level, blockposition2)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition2, state, 2); // CraftBukkit + } + } ++ + } + + @Override +- protected boolean mayPlaceOn(BlockState state, BlockGetter level, BlockPos pos) { ++ protected boolean mayPlaceOn(IBlockData state, BlockGetter level, BlockPos pos) { + return state.isSolidRender(level, pos); + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { +- BlockPos blockPos = pos.below(); +- BlockState blockState = level.getBlockState(blockPos); +- return blockState.is(BlockTags.MUSHROOM_GROW_BLOCK) || level.getRawBrightness(pos, 0) < 13 && this.mayPlaceOn(blockState, level, blockPos); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ return iblockdata1.is(BlockTags.MUSHROOM_GROW_BLOCK) ? true : level.getRawBrightness(pos, 0) < 13 && this.mayPlaceOn(iblockdata1, level, blockposition1); + } + +- public boolean growMushroom(ServerLevel level, BlockPos pos, BlockState state, RandomSource random) { +- Optional>> holder = level.registryAccess() +- .registryOrThrow(Registries.CONFIGURED_FEATURE) +- .getHolder(this.feature); +- if (holder.isEmpty()) { ++ public boolean growMushroom(ServerLevel level, BlockPos pos, IBlockData state, RandomSource random) { ++ Optional>> optional = level.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE).getHolder(this.feature); ++ ++ if (optional.isEmpty()) { + return false; + } else { + level.removeBlock(pos, false); +- if (holder.get().value().place(level, level.getChunkSource().getGenerator(), random, pos)) { ++ SaplingBlock.treeType = (this == Blocks.BROWN_MUSHROOM) ? TreeType.BROWN_MUSHROOM : TreeType.BROWN_MUSHROOM; // CraftBukkit ++ if (((ConfiguredFeature) ((Holder) optional.get()).value()).place(level, level.getChunkSource().getGenerator(), random, pos)) { + return true; + } else { + level.setBlock(pos, state, 3); +@@ -106,17 +115,17 @@ + } + + @Override +- public boolean isValidBonemealTarget(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { + return true; + } + + @Override +- public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, BlockState state) { +- return (double)random.nextFloat() < 0.4; ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { ++ return (double) random.nextFloat() < 0.4D; + } + + @Override +- public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) { ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { + this.growMushroom(level, pos, state, random); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/NetherPortalBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/NetherPortalBlock.java.patch new file mode 100644 index 0000000000..f4dfc316b3 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/NetherPortalBlock.java.patch @@ -0,0 +1,204 @@ +--- a/net/minecraft/world/level/block/NetherPortalBlock.java ++++ b/net/minecraft/world/level/block/NetherPortalBlock.java +@@ -10,7 +10,7 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.GameRules; +@@ -18,127 +18,129 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.EnumProperty; + import net.minecraft.world.level.portal.PortalShape; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.event.entity.EntityPortalEnterEvent; ++// CraftBukkit end + + public class NetherPortalBlock extends Block { ++ + public static final MapCodec CODEC = simpleCodec(NetherPortalBlock::new); + public static final EnumProperty AXIS = BlockStateProperties.HORIZONTAL_AXIS; + protected static final int AABB_OFFSET = 2; +- protected static final VoxelShape X_AXIS_AABB = Block.box(0.0, 0.0, 6.0, 16.0, 16.0, 10.0); +- protected static final VoxelShape Z_AXIS_AABB = Block.box(6.0, 0.0, 0.0, 10.0, 16.0, 16.0); ++ protected static final VoxelShape X_AXIS_AABB = Block.box(0.0D, 0.0D, 6.0D, 16.0D, 16.0D, 10.0D); ++ protected static final VoxelShape Z_AXIS_AABB = Block.box(6.0D, 0.0D, 0.0D, 10.0D, 16.0D, 16.0D); + + @Override + public MapCodec codec() { +- return CODEC; ++ return NetherPortalBlock.CODEC; + } + + public NetherPortalBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(AXIS, Direction.Axis.X)); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(NetherPortalBlock.AXIS, Direction.Axis.X)); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- switch ((Direction.Axis)state.getValue(AXIS)) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ switch ((Direction.Axis) state.getValue(NetherPortalBlock.AXIS)) { + case Z: +- return Z_AXIS_AABB; ++ return NetherPortalBlock.Z_AXIS_AABB; + case X: + default: +- return X_AXIS_AABB; ++ return NetherPortalBlock.X_AXIS_AABB; + } + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- if (level.dimensionType().natural() +- && level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) +- && random.nextInt(2000) < level.getDifficulty().getId()) { +- while (level.getBlockState(pos).is(this)) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (level.dimensionType().natural() && level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && random.nextInt(2000) < level.getDifficulty().getId()) { ++ while (level.getBlockState(pos).is((Block) this)) { + pos = pos.below(); + } + + if (level.getBlockState(pos).isValidSpawn(level, pos, EntityType.ZOMBIFIED_PIGLIN)) { +- Entity entity = EntityType.ZOMBIFIED_PIGLIN.spawn(level, pos.above(), MobSpawnType.STRUCTURE); ++ // CraftBukkit - set spawn reason to NETHER_PORTAL ++ Entity entity = EntityType.ZOMBIFIED_PIGLIN.spawn(level, pos.above(), EnumMobSpawn.STRUCTURE, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NETHER_PORTAL); ++ + if (entity != null) { + entity.setPortalCooldown(); + } + } + } ++ + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- Direction.Axis axis = facing.getAxis(); +- Direction.Axis axis1 = state.getValue(AXIS); +- boolean flag = axis1 != axis && axis.isHorizontal(); +- return !flag && !facingState.is(this) && !new PortalShape(level, currentPos, axis1).isComplete() +- ? Blocks.AIR.defaultBlockState() +- : super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ Direction.Axis enumdirection_enumaxis = facing.getAxis(); ++ Direction.Axis enumdirection_enumaxis1 = (Direction.Axis) state.getValue(NetherPortalBlock.AXIS); ++ boolean flag = enumdirection_enumaxis1 != enumdirection_enumaxis && enumdirection_enumaxis.isHorizontal(); ++ ++ return !flag && !facingState.is((Block) this) && !(new PortalShape(level, currentPos, enumdirection_enumaxis1)).isComplete() ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { + if (entity.canChangeDimensions()) { ++ // CraftBukkit start - Entity in portal ++ EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(level.getWorld(), pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ // CraftBukkit end + entity.handleInsidePortal(pos); + } ++ + } + + @Override +- public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { + if (random.nextInt(100) == 0) { +- level.playLocalSound( +- (double)pos.getX() + 0.5, +- (double)pos.getY() + 0.5, +- (double)pos.getZ() + 0.5, +- SoundEvents.PORTAL_AMBIENT, +- SoundSource.BLOCKS, +- 0.5F, +- random.nextFloat() * 0.4F + 0.8F, +- false +- ); ++ level.playLocalSound((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.PORTAL_AMBIENT, SoundSource.BLOCKS, 0.5F, random.nextFloat() * 0.4F + 0.8F, false); + } + +- for (int i = 0; i < 4; i++) { +- double d = (double)pos.getX() + random.nextDouble(); +- double d1 = (double)pos.getY() + random.nextDouble(); +- double d2 = (double)pos.getZ() + random.nextDouble(); +- double d3 = ((double)random.nextFloat() - 0.5) * 0.5; +- double d4 = ((double)random.nextFloat() - 0.5) * 0.5; +- double d5 = ((double)random.nextFloat() - 0.5) * 0.5; +- int i1 = random.nextInt(2) * 2 - 1; +- if (!level.getBlockState(pos.west()).is(this) && !level.getBlockState(pos.east()).is(this)) { +- d = (double)pos.getX() + 0.5 + 0.25 * (double)i1; +- d3 = (double)(random.nextFloat() * 2.0F * (float)i1); ++ for (int i = 0; i < 4; ++i) { ++ double d0 = (double) pos.getX() + random.nextDouble(); ++ double d1 = (double) pos.getY() + random.nextDouble(); ++ double d2 = (double) pos.getZ() + random.nextDouble(); ++ double d3 = ((double) random.nextFloat() - 0.5D) * 0.5D; ++ double d4 = ((double) random.nextFloat() - 0.5D) * 0.5D; ++ double d5 = ((double) random.nextFloat() - 0.5D) * 0.5D; ++ int j = random.nextInt(2) * 2 - 1; ++ ++ if (!level.getBlockState(pos.west()).is((Block) this) && !level.getBlockState(pos.east()).is((Block) this)) { ++ d0 = (double) pos.getX() + 0.5D + 0.25D * (double) j; ++ d3 = (double) (random.nextFloat() * 2.0F * (float) j); + } else { +- d2 = (double)pos.getZ() + 0.5 + 0.25 * (double)i1; +- d5 = (double)(random.nextFloat() * 2.0F * (float)i1); ++ d2 = (double) pos.getZ() + 0.5D + 0.25D * (double) j; ++ d5 = (double) (random.nextFloat() * 2.0F * (float) j); + } + +- level.addParticle(ParticleTypes.PORTAL, d, d1, d2, d3, d4, d5); ++ level.addParticle(ParticleTypes.PORTAL, d0, d1, d2, d3, d4, d5); + } ++ + } + + @Override +- public ItemStack getCloneItemStack(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { ++ public ItemStack getCloneItemStack(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { + return ItemStack.EMPTY; + } + + @Override +- public BlockState rotate(BlockState state, Rotation rot) { ++ public IBlockData rotate(IBlockData state, Rotation rot) { + switch (rot) { + case COUNTERCLOCKWISE_90: + case CLOCKWISE_90: +- switch ((Direction.Axis)state.getValue(AXIS)) { ++ switch ((Direction.Axis) state.getValue(NetherPortalBlock.AXIS)) { + case Z: +- return state.setValue(AXIS, Direction.Axis.X); ++ return (IBlockData) state.setValue(NetherPortalBlock.AXIS, Direction.Axis.X); + case X: +- return state.setValue(AXIS, Direction.Axis.Z); ++ return (IBlockData) state.setValue(NetherPortalBlock.AXIS, Direction.Axis.Z); + default: + return state; + } +@@ -148,7 +150,7 @@ + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(AXIS); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(NetherPortalBlock.AXIS); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/NetherWartBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/NetherWartBlock.java.patch new file mode 100644 index 0000000000..efe2163707 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/NetherWartBlock.java.patch @@ -0,0 +1,87 @@ +--- a/net/minecraft/world/level/block/NetherWartBlock.java ++++ b/net/minecraft/world/level/block/NetherWartBlock.java +@@ -9,7 +9,7 @@ + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; +@@ -17,57 +17,55 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + + public class NetherWartBlock extends BushBlock { ++ + public static final MapCodec CODEC = simpleCodec(NetherWartBlock::new); + public static final int MAX_AGE = 3; + public static final IntegerProperty AGE = BlockStateProperties.AGE_3; +- private static final VoxelShape[] SHAPE_BY_AGE = new VoxelShape[]{ +- Block.box(0.0, 0.0, 0.0, 16.0, 5.0, 16.0), +- Block.box(0.0, 0.0, 0.0, 16.0, 8.0, 16.0), +- Block.box(0.0, 0.0, 0.0, 16.0, 11.0, 16.0), +- Block.box(0.0, 0.0, 0.0, 16.0, 14.0, 16.0) +- }; ++ private static final VoxelShape[] SHAPE_BY_AGE = new VoxelShape[]{Block.box(0.0D, 0.0D, 0.0D, 16.0D, 5.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 8.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 11.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 14.0D, 16.0D)}; + + @Override + public MapCodec codec() { +- return CODEC; ++ return NetherWartBlock.CODEC; + } + + protected NetherWartBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(AGE, Integer.valueOf(0))); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(NetherWartBlock.AGE, 0)); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPE_BY_AGE[state.getValue(AGE)]; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return NetherWartBlock.SHAPE_BY_AGE[(Integer) state.getValue(NetherWartBlock.AGE)]; + } + + @Override +- protected boolean mayPlaceOn(BlockState state, BlockGetter level, BlockPos pos) { ++ protected boolean mayPlaceOn(IBlockData state, BlockGetter level, BlockPos pos) { + return state.is(Blocks.SOUL_SAND); + } + + @Override +- public boolean isRandomlyTicking(BlockState state) { +- return state.getValue(AGE) < 3; ++ public boolean isRandomlyTicking(IBlockData state) { ++ return (Integer) state.getValue(NetherWartBlock.AGE) < 3; + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- int i = state.getValue(AGE); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ int i = (Integer) state.getValue(NetherWartBlock.AGE); ++ + if (i < 3 && random.nextInt(10) == 0) { +- state = state.setValue(AGE, Integer.valueOf(i + 1)); +- level.setBlock(pos, state, 2); ++ state = (IBlockData) state.setValue(NetherWartBlock.AGE, i + 1); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, state, 2); // CraftBukkit + } ++ + } + + @Override +- public ItemStack getCloneItemStack(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { ++ public ItemStack getCloneItemStack(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { + return new ItemStack(Items.NETHER_WART); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(AGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(NetherWartBlock.AGE); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/NoteBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/NoteBlock.java.patch new file mode 100644 index 0000000000..622cdb32e7 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/NoteBlock.java.patch @@ -0,0 +1,234 @@ +--- a/net/minecraft/world/level/block/NoteBlock.java ++++ b/net/minecraft/world/level/block/NoteBlock.java +@@ -11,7 +11,7 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; + import net.minecraft.tags.ItemTags; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; +@@ -19,9 +19,10 @@ + import net.minecraft.world.item.context.BlockPlaceContext; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; ++import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.SkullBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -32,6 +33,7 @@ + import net.minecraft.world.phys.BlockHitResult; + + public class NoteBlock extends Block { ++ + public static final MapCodec CODEC = simpleCodec(NoteBlock::new); + public static final EnumProperty INSTRUMENT = BlockStateProperties.NOTEBLOCK_INSTRUMENT; + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; +@@ -40,70 +42,78 @@ + + @Override + public MapCodec codec() { +- return CODEC; ++ return NoteBlock.CODEC; + } + + public NoteBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState( +- this.stateDefinition +- .any() +- .setValue(INSTRUMENT, NoteBlockInstrument.HARP) +- .setValue(NOTE, Integer.valueOf(0)) +- .setValue(POWERED, Boolean.valueOf(false)) +- ); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(NoteBlock.INSTRUMENT, NoteBlockInstrument.HARP)).setValue(NoteBlock.NOTE, 0)).setValue(NoteBlock.POWERED, false)); + } + +- private BlockState setInstrument(LevelAccessor level, BlockPos pos, BlockState state) { +- NoteBlockInstrument noteBlockInstrument = level.getBlockState(pos.above()).instrument(); +- if (noteBlockInstrument.worksAboveNoteBlock()) { +- return state.setValue(INSTRUMENT, noteBlockInstrument); ++ private IBlockData setInstrument(LevelAccessor level, BlockPos pos, IBlockData state) { ++ NoteBlockInstrument blockpropertyinstrument = level.getBlockState(pos.above()).instrument(); ++ ++ if (blockpropertyinstrument.worksAboveNoteBlock()) { ++ return (IBlockData) state.setValue(NoteBlock.INSTRUMENT, blockpropertyinstrument); + } else { +- NoteBlockInstrument noteBlockInstrument1 = level.getBlockState(pos.below()).instrument(); +- NoteBlockInstrument noteBlockInstrument2 = noteBlockInstrument1.worksAboveNoteBlock() ? NoteBlockInstrument.HARP : noteBlockInstrument1; +- return state.setValue(INSTRUMENT, noteBlockInstrument2); ++ NoteBlockInstrument blockpropertyinstrument1 = level.getBlockState(pos.below()).instrument(); ++ NoteBlockInstrument blockpropertyinstrument2 = blockpropertyinstrument1.worksAboveNoteBlock() ? NoteBlockInstrument.HARP : blockpropertyinstrument1; ++ ++ return (IBlockData) state.setValue(NoteBlock.INSTRUMENT, blockpropertyinstrument2); + } + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { + return this.setInstrument(context.getLevel(), context.getClickedPos(), this.defaultBlockState()); + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { + boolean flag = facing.getAxis() == Direction.Axis.Y; ++ + return flag ? this.setInstrument(level, currentPos, state) : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { +- boolean hasNeighborSignal = level.hasNeighborSignal(pos); +- if (hasNeighborSignal != state.getValue(POWERED)) { +- if (hasNeighborSignal) { +- this.playNote(null, state, level, pos); ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ boolean flag1 = level.hasNeighborSignal(pos); ++ ++ if (flag1 != (Boolean) state.getValue(NoteBlock.POWERED)) { ++ if (flag1) { ++ this.playNote((Entity) null, state, level, pos); ++ state = level.getBlockState(pos); // CraftBukkit - SPIGOT-5617: update in case changed in event + } + +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(hasNeighborSignal)), 3); ++ level.setBlock(pos, (IBlockData) state.setValue(NoteBlock.POWERED, flag1), 3); + } ++ + } + +- private void playNote(@Nullable Entity entity, BlockState state, Level level, BlockPos pos) { +- if (state.getValue(INSTRUMENT).worksAboveNoteBlock() || level.getBlockState(pos.above()).isAir()) { ++ private void playNote(@Nullable Entity entity, IBlockData state, Level level, BlockPos pos) { ++ if (((NoteBlockInstrument) state.getValue(NoteBlock.INSTRUMENT)).worksAboveNoteBlock() || level.getBlockState(pos.above()).isAir()) { ++ // CraftBukkit start ++ org.bukkit.event.block.NotePlayEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callNotePlayEvent(level, pos, state.getValue(NoteBlock.INSTRUMENT), state.getValue(NoteBlock.NOTE)); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + level.blockEvent(pos, this, 0, 0); + level.gameEvent(entity, GameEvent.NOTE_BLOCK_PLAY, pos); + } ++ + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (itemInHand.is(ItemTags.NOTE_BLOCK_TOP_INSTRUMENTS) && hit.getDirection() == Direction.UP) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (itemstack.is(ItemTags.NOTE_BLOCK_TOP_INSTRUMENTS) && hit.getDirection() == Direction.UP) { + return InteractionResult.PASS; + } else if (level.isClientSide) { + return InteractionResult.SUCCESS; + } else { +- state = state.cycle(NOTE); ++ state = (IBlockData) state.cycle(NoteBlock.NOTE); + level.setBlock(pos, state, 3); + this.playNote(player, state, level, pos); + player.awardStat(Stats.TUNE_NOTEBLOCK); +@@ -112,7 +122,7 @@ + } + + @Override +- public void attack(BlockState state, Level level, BlockPos pos, Player player) { ++ public void attack(IBlockData state, Level level, BlockPos pos, Player player) { + if (!level.isClientSide) { + this.playNote(player, state, level, pos); + player.awardStat(Stats.PLAY_NOTEBLOCK); +@@ -120,54 +130,56 @@ + } + + public static float getPitchFromNote(int note) { +- return (float)Math.pow(2.0, (double)(note - 12) / 12.0); ++ return (float) Math.pow(2.0D, (double) (note - 12) / 12.0D); + } + + @Override +- public boolean triggerEvent(BlockState state, Level level, BlockPos pos, int id, int param) { +- NoteBlockInstrument noteBlockInstrument = state.getValue(INSTRUMENT); +- float pitchFromNote; +- if (noteBlockInstrument.isTunable()) { +- int i = state.getValue(NOTE); +- pitchFromNote = getPitchFromNote(i); +- level.addParticle(ParticleTypes.NOTE, (double)pos.getX() + 0.5, (double)pos.getY() + 1.2, (double)pos.getZ() + 0.5, (double)i / 24.0, 0.0, 0.0); ++ public boolean triggerEvent(IBlockData state, Level level, BlockPos pos, int id, int param) { ++ NoteBlockInstrument blockpropertyinstrument = (NoteBlockInstrument) state.getValue(NoteBlock.INSTRUMENT); ++ float f; ++ ++ if (blockpropertyinstrument.isTunable()) { ++ int k = (Integer) state.getValue(NoteBlock.NOTE); ++ ++ f = getPitchFromNote(k); ++ level.addParticle(ParticleTypes.NOTE, (double) pos.getX() + 0.5D, (double) pos.getY() + 1.2D, (double) pos.getZ() + 0.5D, (double) k / 24.0D, 0.0D, 0.0D); + } else { +- pitchFromNote = 1.0F; ++ f = 1.0F; + } + +- Holder holder; +- if (noteBlockInstrument.hasCustomSound()) { +- ResourceLocation customSoundId = this.getCustomSoundId(level, pos); +- if (customSoundId == null) { ++ Holder holder; ++ ++ if (blockpropertyinstrument.hasCustomSound()) { ++ ResourceLocation minecraftkey = this.getCustomSoundId(level, pos); ++ ++ if (minecraftkey == null) { + return false; + } + +- holder = Holder.direct(SoundEvent.createVariableRangeEvent(customSoundId)); ++ holder = Holder.direct(SoundEvent.createVariableRangeEvent(minecraftkey)); + } else { +- holder = noteBlockInstrument.getSoundEvent(); ++ holder = blockpropertyinstrument.getSoundEvent(); + } + +- level.playSeededSound( +- null, +- (double)pos.getX() + 0.5, +- (double)pos.getY() + 0.5, +- (double)pos.getZ() + 0.5, +- holder, +- SoundSource.RECORDS, +- 3.0F, +- pitchFromNote, +- level.random.nextLong() +- ); ++ level.playSeededSound((Player) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, holder, SoundSource.RECORDS, 3.0F, f, level.random.nextLong()); + return true; + } + + @Nullable + private ResourceLocation getCustomSoundId(Level level, BlockPos pos) { +- return level.getBlockEntity(pos.above()) instanceof SkullBlockEntity skullBlockEntity ? skullBlockEntity.getNoteBlockSound() : null; ++ BlockEntity tileentity = level.getBlockEntity(pos.above()); ++ ++ if (tileentity instanceof SkullBlockEntity) { ++ SkullBlockEntity tileentityskull = (SkullBlockEntity) tileentity; ++ ++ return tileentityskull.getNoteBlockSound(); ++ } else { ++ return null; ++ } + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(INSTRUMENT, POWERED, NOTE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(NoteBlock.INSTRUMENT, NoteBlock.POWERED, NoteBlock.NOTE); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/NyliumBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/NyliumBlock.java.patch new file mode 100644 index 0000000000..84056ed9d8 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/NyliumBlock.java.patch @@ -0,0 +1,119 @@ +--- a/net/minecraft/world/level/block/NyliumBlock.java ++++ b/net/minecraft/world/level/block/NyliumBlock.java +@@ -3,7 +3,6 @@ + import com.mojang.serialization.MapCodec; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.Holder; + import net.minecraft.core.Registry; + import net.minecraft.core.registries.Registries; + import net.minecraft.data.worldgen.features.NetherFeatures; +@@ -13,72 +12,77 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; + import net.minecraft.world.level.lighting.LightEngine; + + public class NyliumBlock extends Block implements BonemealableBlock { ++ + public static final MapCodec CODEC = simpleCodec(NyliumBlock::new); + + @Override + public MapCodec codec() { +- return CODEC; ++ return NyliumBlock.CODEC; + } + + protected NyliumBlock(BlockBehaviour.Properties properties) { + super(properties); + } + +- private static boolean canBeNylium(BlockState state, LevelReader reader, BlockPos pos) { +- BlockPos blockPos = pos.above(); +- BlockState blockState = reader.getBlockState(blockPos); +- int lightBlockInto = LightEngine.getLightBlockInto(reader, state, pos, blockState, blockPos, Direction.UP, blockState.getLightBlock(reader, blockPos)); +- return lightBlockInto < reader.getMaxLightLevel(); ++ private static boolean canBeNylium(IBlockData state, LevelReader reader, BlockPos pos) { ++ BlockPos blockposition1 = pos.above(); ++ IBlockData iblockdata1 = reader.getBlockState(blockposition1); ++ int i = LightEngine.getLightBlockInto(reader, state, pos, iblockdata1, blockposition1, Direction.UP, iblockdata1.getLightBlock(reader, blockposition1)); ++ ++ return i < reader.getMaxLightLevel(); + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (!canBeNylium(state, level, pos)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.NETHERRACK.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + level.setBlockAndUpdate(pos, Blocks.NETHERRACK.defaultBlockState()); + } ++ + } + + @Override +- public boolean isValidBonemealTarget(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { +- return levelReader.getBlockState(blockPos.above()).isAir(); ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ return iworldreader.getBlockState(blockposition.above()).isAir(); + } + + @Override +- public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, BlockState state) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return true; + } + + @Override +- public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) { +- BlockState blockState = level.getBlockState(pos); +- BlockPos blockPos = pos.above(); +- ChunkGenerator generator = level.getChunkSource().getGenerator(); +- Registry> registry = level.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE); +- if (blockState.is(Blocks.CRIMSON_NYLIUM)) { +- this.place(registry, NetherFeatures.CRIMSON_FOREST_VEGETATION_BONEMEAL, level, generator, random, blockPos); +- } else if (blockState.is(Blocks.WARPED_NYLIUM)) { +- this.place(registry, NetherFeatures.WARPED_FOREST_VEGETATION_BONEMEAL, level, generator, random, blockPos); +- this.place(registry, NetherFeatures.NETHER_SPROUTS_BONEMEAL, level, generator, random, blockPos); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ IBlockData iblockdata1 = level.getBlockState(pos); ++ BlockPos blockposition1 = pos.above(); ++ ChunkGenerator chunkgenerator = level.getChunkSource().getGenerator(); ++ Registry> iregistry = level.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE); ++ ++ if (iblockdata1.is(Blocks.CRIMSON_NYLIUM)) { ++ this.place(iregistry, NetherFeatures.CRIMSON_FOREST_VEGETATION_BONEMEAL, level, chunkgenerator, random, blockposition1); ++ } else if (iblockdata1.is(Blocks.WARPED_NYLIUM)) { ++ this.place(iregistry, NetherFeatures.WARPED_FOREST_VEGETATION_BONEMEAL, level, chunkgenerator, random, blockposition1); ++ this.place(iregistry, NetherFeatures.NETHER_SPROUTS_BONEMEAL, level, chunkgenerator, random, blockposition1); + if (random.nextInt(8) == 0) { +- this.place(registry, NetherFeatures.TWISTING_VINES_BONEMEAL, level, generator, random, blockPos); ++ this.place(iregistry, NetherFeatures.TWISTING_VINES_BONEMEAL, level, chunkgenerator, random, blockposition1); + } + } ++ + } + +- private void place( +- Registry> featureRegistry, +- ResourceKey> featureKey, +- ServerLevel level, +- ChunkGenerator chunkGenerator, +- RandomSource random, +- BlockPos pos +- ) { +- featureRegistry.getHolder(featureKey).ifPresent(configuredFeature -> configuredFeature.value().place(level, chunkGenerator, random, pos)); ++ private void place(Registry> featureRegistry, ResourceKey> featureKey, ServerLevel level, ChunkGenerator chunkGenerator, RandomSource random, BlockPos pos) { ++ featureRegistry.getHolder(featureKey).ifPresent((holder_c) -> { ++ ((ConfiguredFeature) holder_c.value()).place(level, chunkGenerator, random, pos); ++ }); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/ObserverBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/ObserverBlock.java.patch new file mode 100644 index 0000000000..e1ac8ed0d4 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/ObserverBlock.java.patch @@ -0,0 +1,167 @@ +--- a/net/minecraft/world/level/block/ObserverBlock.java ++++ b/net/minecraft/world/level/block/ObserverBlock.java +@@ -10,55 +10,67 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + +-public class ObserverBlock extends DirectionalBlock { ++public class ObserverBlock extends BlockDirectional { ++ + public static final MapCodec CODEC = simpleCodec(ObserverBlock::new); + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + + @Override + public MapCodec codec() { +- return CODEC; ++ return ObserverBlock.CODEC; + } + + public ObserverBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.SOUTH).setValue(POWERED, Boolean.valueOf(false))); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(ObserverBlock.FACING, Direction.SOUTH)).setValue(ObserverBlock.POWERED, false)); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(FACING, POWERED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(ObserverBlock.FACING, ObserverBlock.POWERED); + } + + @Override +- public BlockState rotate(BlockState state, Rotation rot) { +- return state.setValue(FACING, rot.rotate(state.getValue(FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rot) { ++ return (IBlockData) state.setValue(ObserverBlock.FACING, rot.rotate((Direction) state.getValue(ObserverBlock.FACING))); + } + + @Override +- public BlockState mirror(BlockState state, Mirror mirror) { +- return state.rotate(mirror.getRotation(state.getValue(FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(ObserverBlock.FACING))); + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- if (state.getValue(POWERED)) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(false)), 2); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(ObserverBlock.POWERED)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 15, 0).getNewCurrent() != 0) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(ObserverBlock.POWERED, false), 2); + } else { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(true)), 2); +- level.scheduleTick(pos, this, 2); ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 0, 15).getNewCurrent() != 15) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(ObserverBlock.POWERED, true), 2); ++ level.scheduleTick(pos, (Block) this, 2); + } + + this.updateNeighborsInFront(level, pos, state); + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- if (state.getValue(FACING) == facing && !state.getValue(POWERED)) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if (state.getValue(ObserverBlock.FACING) == facing && !(Boolean) state.getValue(ObserverBlock.POWERED)) { + this.startSignal(level, currentPos); + } + +@@ -67,54 +79,59 @@ + + private void startSignal(LevelAccessor level, BlockPos pos) { + if (!level.isClientSide() && !level.getBlockTicks().hasScheduledTick(pos, this)) { +- level.scheduleTick(pos, this, 2); ++ level.scheduleTick(pos, (Block) this, 2); + } ++ + } + +- protected void updateNeighborsInFront(Level level, BlockPos pos, BlockState state) { +- Direction direction = state.getValue(FACING); +- BlockPos blockPos = pos.relative(direction.getOpposite()); +- level.neighborChanged(blockPos, this, pos); +- level.updateNeighborsAtExceptFromFacing(blockPos, this, direction); ++ protected void updateNeighborsInFront(Level level, BlockPos pos, IBlockData state) { ++ Direction enumdirection = (Direction) state.getValue(ObserverBlock.FACING); ++ BlockPos blockposition1 = pos.relative(enumdirection.getOpposite()); ++ ++ level.neighborChanged(blockposition1, this, pos); ++ level.updateNeighborsAtExceptFromFacing(blockposition1, this, enumdirection); + } + + @Override +- public boolean isSignalSource(BlockState state) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + + @Override +- public int getDirectSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ public int getDirectSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { + return blockState.getSignal(blockAccess, pos, side); + } + + @Override +- public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { +- return blockState.getValue(POWERED) && blockState.getValue(FACING) == side ? 15 : 0; ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return (Boolean) blockState.getValue(ObserverBlock.POWERED) && blockState.getValue(ObserverBlock.FACING) == side ? 15 : 0; + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { + if (!state.is(oldState.getBlock())) { +- if (!level.isClientSide() && state.getValue(POWERED) && !level.getBlockTicks().hasScheduledTick(pos, this)) { +- BlockState blockState = state.setValue(POWERED, Boolean.valueOf(false)); +- level.setBlock(pos, blockState, 18); +- this.updateNeighborsInFront(level, pos, blockState); ++ if (!level.isClientSide() && (Boolean) state.getValue(ObserverBlock.POWERED) && !level.getBlockTicks().hasScheduledTick(pos, this)) { ++ IBlockData iblockdata2 = (IBlockData) state.setValue(ObserverBlock.POWERED, false); ++ ++ level.setBlock(pos, iblockdata2, 18); ++ this.updateNeighborsInFront(level, pos, iblockdata2); + } ++ + } + } + + @Override +- public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { + if (!state.is(newState.getBlock())) { +- if (!level.isClientSide && state.getValue(POWERED) && level.getBlockTicks().hasScheduledTick(pos, this)) { +- this.updateNeighborsInFront(level, pos, state.setValue(POWERED, Boolean.valueOf(false))); ++ if (!level.isClientSide && (Boolean) state.getValue(ObserverBlock.POWERED) && level.getBlockTicks().hasScheduledTick(pos, this)) { ++ this.updateNeighborsInFront(level, pos, (IBlockData) state.setValue(ObserverBlock.POWERED, false)); + } ++ + } + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- return this.defaultBlockState().setValue(FACING, context.getNearestLookingDirection().getOpposite().getOpposite()); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return (IBlockData) this.defaultBlockState().setValue(ObserverBlock.FACING, context.getNearestLookingDirection().getOpposite().getOpposite()); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/PointedDripstoneBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/PointedDripstoneBlock.java.patch new file mode 100644 index 0000000000..1efe033f22 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/PointedDripstoneBlock.java.patch @@ -0,0 +1,893 @@ +--- a/net/minecraft/world/level/block/PointedDripstoneBlock.java ++++ b/net/minecraft/world/level/block/PointedDripstoneBlock.java +@@ -8,8 +8,8 @@ + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.particles.ParticleOptions; + import net.minecraft.core.particles.ParticleTypes; ++import net.minecraft.core.particles.SimpleParticleType; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.tags.FluidTags; + import net.minecraft.util.RandomSource; +@@ -24,7 +24,7 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -35,15 +35,20 @@ + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class PointedDripstoneBlock extends Block implements Fallable, SimpleWaterloggedBlock { ++ + public static final MapCodec CODEC = simpleCodec(PointedDripstoneBlock::new); + public static final DirectionProperty TIP_DIRECTION = BlockStateProperties.VERTICAL_DIRECTION; + public static final EnumProperty THICKNESS = BlockStateProperties.DRIPSTONE_THICKNESS; +@@ -55,7 +60,7 @@ + private static final int MAX_SEARCH_LENGTH_BETWEEN_STALACTITE_TIP_AND_CAULDRON = 11; + private static final float WATER_TRANSFER_PROBABILITY_PER_RANDOM_TICK = 0.17578125F; + private static final float LAVA_TRANSFER_PROBABILITY_PER_RANDOM_TICK = 0.05859375F; +- private static final double MIN_TRIDENT_VELOCITY_TO_BREAK_DRIPSTONE = 0.6; ++ private static final double MIN_TRIDENT_VELOCITY_TO_BREAK_DRIPSTONE = 0.6D; + private static final float STALACTITE_DAMAGE_PER_FALL_DISTANCE_AND_SIZE = 1.0F; + private static final int STALACTITE_MAX_DAMAGE = 40; + private static final int MAX_STALACTITE_HEIGHT_FOR_DAMAGE_CALCULATION = 6; +@@ -66,155 +71,169 @@ + private static final int MAX_GROWTH_LENGTH = 7; + private static final int MAX_STALAGMITE_SEARCH_RANGE_WHEN_GROWING = 10; + private static final float STALACTITE_DRIP_START_PIXEL = 0.6875F; +- private static final VoxelShape TIP_MERGE_SHAPE = Block.box(5.0, 0.0, 5.0, 11.0, 16.0, 11.0); +- private static final VoxelShape TIP_SHAPE_UP = Block.box(5.0, 0.0, 5.0, 11.0, 11.0, 11.0); +- private static final VoxelShape TIP_SHAPE_DOWN = Block.box(5.0, 5.0, 5.0, 11.0, 16.0, 11.0); +- private static final VoxelShape FRUSTUM_SHAPE = Block.box(4.0, 0.0, 4.0, 12.0, 16.0, 12.0); +- private static final VoxelShape MIDDLE_SHAPE = Block.box(3.0, 0.0, 3.0, 13.0, 16.0, 13.0); +- private static final VoxelShape BASE_SHAPE = Block.box(2.0, 0.0, 2.0, 14.0, 16.0, 14.0); ++ private static final VoxelShape TIP_MERGE_SHAPE = Block.box(5.0D, 0.0D, 5.0D, 11.0D, 16.0D, 11.0D); ++ private static final VoxelShape TIP_SHAPE_UP = Block.box(5.0D, 0.0D, 5.0D, 11.0D, 11.0D, 11.0D); ++ private static final VoxelShape TIP_SHAPE_DOWN = Block.box(5.0D, 5.0D, 5.0D, 11.0D, 16.0D, 11.0D); ++ private static final VoxelShape FRUSTUM_SHAPE = Block.box(4.0D, 0.0D, 4.0D, 12.0D, 16.0D, 12.0D); ++ private static final VoxelShape MIDDLE_SHAPE = Block.box(3.0D, 0.0D, 3.0D, 13.0D, 16.0D, 13.0D); ++ private static final VoxelShape BASE_SHAPE = Block.box(2.0D, 0.0D, 2.0D, 14.0D, 16.0D, 14.0D); + private static final float MAX_HORIZONTAL_OFFSET = 0.125F; +- private static final VoxelShape REQUIRED_SPACE_TO_DRIP_THROUGH_NON_SOLID_BLOCK = Block.box(6.0, 0.0, 6.0, 10.0, 16.0, 10.0); ++ private static final VoxelShape REQUIRED_SPACE_TO_DRIP_THROUGH_NON_SOLID_BLOCK = Block.box(6.0D, 0.0D, 6.0D, 10.0D, 16.0D, 10.0D); + + @Override + public MapCodec codec() { +- return CODEC; ++ return PointedDripstoneBlock.CODEC; + } + + public PointedDripstoneBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState( +- this.stateDefinition +- .any() +- .setValue(TIP_DIRECTION, Direction.UP) +- .setValue(THICKNESS, DripstoneThickness.TIP) +- .setValue(WATERLOGGED, Boolean.valueOf(false)) +- ); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(PointedDripstoneBlock.TIP_DIRECTION, Direction.UP)).setValue(PointedDripstoneBlock.THICKNESS, DripstoneThickness.TIP)).setValue(PointedDripstoneBlock.WATERLOGGED, false)); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(TIP_DIRECTION, THICKNESS, WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(PointedDripstoneBlock.TIP_DIRECTION, PointedDripstoneBlock.THICKNESS, PointedDripstoneBlock.WATERLOGGED); + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { +- return isValidPointedDripstonePlacement(level, pos, state.getValue(TIP_DIRECTION)); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ return isValidPointedDripstonePlacement(level, pos, (Direction) state.getValue(PointedDripstoneBlock.TIP_DIRECTION)); + } + + @Override +- public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { +- if (state.getValue(WATERLOGGED)) { +- level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); ++ public IBlockData updateShape(IBlockData state, Direction direction, IBlockData neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { ++ if ((Boolean) state.getValue(PointedDripstoneBlock.WATERLOGGED)) { ++ level.scheduleTick(pos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + + if (direction != Direction.UP && direction != Direction.DOWN) { + return state; + } else { +- Direction direction1 = state.getValue(TIP_DIRECTION); +- if (direction1 == Direction.DOWN && level.getBlockTicks().hasScheduledTick(pos, this)) { ++ Direction enumdirection1 = (Direction) state.getValue(PointedDripstoneBlock.TIP_DIRECTION); ++ ++ if (enumdirection1 == Direction.DOWN && level.getBlockTicks().hasScheduledTick(pos, this)) { + return state; +- } else if (direction == direction1.getOpposite() && !this.canSurvive(state, level, pos)) { +- if (direction1 == Direction.DOWN) { +- level.scheduleTick(pos, this, 2); ++ } else if (direction == enumdirection1.getOpposite() && !this.canSurvive(state, level, pos)) { ++ if (enumdirection1 == Direction.DOWN) { ++ level.scheduleTick(pos, (Block) this, 2); + } else { +- level.scheduleTick(pos, this, 1); ++ level.scheduleTick(pos, (Block) this, 1); + } + + return state; + } else { +- boolean flag = state.getValue(THICKNESS) == DripstoneThickness.TIP_MERGE; +- DripstoneThickness dripstoneThickness = calculateDripstoneThickness(level, pos, direction1, flag); +- return state.setValue(THICKNESS, dripstoneThickness); ++ boolean flag = state.getValue(PointedDripstoneBlock.THICKNESS) == DripstoneThickness.TIP_MERGE; ++ DripstoneThickness dripstonethickness = calculateDripstoneThickness(level, pos, enumdirection1, flag); ++ ++ return (IBlockData) state.setValue(PointedDripstoneBlock.THICKNESS, dripstonethickness); + } + } + } + + @Override +- public void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) { ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { + if (!level.isClientSide) { +- BlockPos blockPos = hit.getBlockPos(); +- if (projectile.mayInteract(level, blockPos) +- && projectile.mayBreak(level) +- && projectile instanceof ThrownTrident +- && projectile.getDeltaMovement().length() > 0.6) { +- level.destroyBlock(blockPos, true); ++ BlockPos blockposition = hit.getBlockPos(); ++ ++ if (projectile.mayInteract(level, blockposition) && projectile.mayBreak(level) && projectile instanceof ThrownTrident && projectile.getDeltaMovement().length() > 0.6D) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, Blocks.AIR.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end ++ level.destroyBlock(blockposition, true); + } ++ + } + } + + @Override +- public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, float fallDistance) { +- if (state.getValue(TIP_DIRECTION) == Direction.UP && state.getValue(THICKNESS) == DripstoneThickness.TIP) { ++ public void fallOn(Level level, IBlockData state, BlockPos pos, Entity entity, float fallDistance) { ++ if (state.getValue(PointedDripstoneBlock.TIP_DIRECTION) == Direction.UP && state.getValue(PointedDripstoneBlock.THICKNESS) == DripstoneThickness.TIP) { ++ CraftEventFactory.blockDamage = CraftBlock.at(level, pos); // CraftBukkit + entity.causeFallDamage(fallDistance + 2.0F, 2.0F, level.damageSources().stalagmite()); ++ CraftEventFactory.blockDamage = null; // CraftBukkit + } else { + super.fallOn(level, state, pos, entity, fallDistance); + } ++ + } + + @Override +- public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { + if (canDrip(state)) { +- float randomFloat = random.nextFloat(); +- if (!(randomFloat > 0.12F)) { +- getFluidAboveStalactite(level, pos, state) +- .filter(fluidInfo -> randomFloat < 0.02F || canFillCauldron(fluidInfo.fluid)) +- .ifPresent(fluidInfo -> spawnDripParticle(level, pos, state, fluidInfo.fluid)); ++ float f = random.nextFloat(); ++ ++ if (f <= 0.12F) { ++ getFluidAboveStalactite(level, pos, state).filter((pointeddripstoneblock_a) -> { ++ return f < 0.02F || canFillCauldron(pointeddripstoneblock_a.fluid); ++ }).ifPresent((pointeddripstoneblock_a) -> { ++ spawnDripParticle(level, pos, state, pointeddripstoneblock_a.fluid); ++ }); + } + } + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (isStalagmite(state) && !this.canSurvive(state, level, pos)) { + level.destroyBlock(pos, true); + } else { + spawnFallingStalactite(state, level, pos); + } ++ + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + maybeTransferFluid(state, level, pos, random.nextFloat()); + if (random.nextFloat() < 0.011377778F && isStalactiteStartPos(state, level, pos)) { + growStalactiteOrStalagmiteIfPossible(state, level, pos, random); + } ++ + } + + @VisibleForTesting +- public static void maybeTransferFluid(BlockState state, ServerLevel level, BlockPos pos, float randChance) { +- if (!(randChance > 0.17578125F) || !(randChance > 0.05859375F)) { ++ public static void maybeTransferFluid(IBlockData state, ServerLevel level, BlockPos pos, float randChance) { ++ if (randChance <= 0.17578125F || randChance <= 0.05859375F) { + if (isStalactiteStartPos(state, level, pos)) { +- Optional fluidAboveStalactite = getFluidAboveStalactite(level, pos, state); +- if (!fluidAboveStalactite.isEmpty()) { +- Fluid fluid = fluidAboveStalactite.get().fluid; +- float f; +- if (fluid == Fluids.WATER) { +- f = 0.17578125F; ++ Optional optional = getFluidAboveStalactite(level, pos, state); ++ ++ if (!optional.isEmpty()) { ++ Fluid fluidtype = ((PointedDripstoneBlock.a) optional.get()).fluid; ++ float f1; ++ ++ if (fluidtype == Fluids.WATER) { ++ f1 = 0.17578125F; + } else { +- if (fluid != Fluids.LAVA) { ++ if (fluidtype != Fluids.LAVA) { + return; + } + +- f = 0.05859375F; ++ f1 = 0.05859375F; + } + +- if (!(randChance >= f)) { +- BlockPos blockPos = findTip(state, level, pos, 11, false); +- if (blockPos != null) { +- if (fluidAboveStalactite.get().sourceState.is(Blocks.MUD) && fluid == Fluids.WATER) { +- BlockState blockState = Blocks.CLAY.defaultBlockState(); +- level.setBlockAndUpdate(fluidAboveStalactite.get().pos, blockState); +- Block.pushEntitiesUp(fluidAboveStalactite.get().sourceState, blockState, level, fluidAboveStalactite.get().pos); +- level.gameEvent(GameEvent.BLOCK_CHANGE, fluidAboveStalactite.get().pos, GameEvent.Context.of(blockState)); +- level.levelEvent(1504, blockPos, 0); ++ if (randChance < f1) { ++ BlockPos blockposition1 = findTip(state, level, pos, 11, false); ++ ++ if (blockposition1 != null) { ++ if (((PointedDripstoneBlock.a) optional.get()).sourceState.is(Blocks.MUD) && fluidtype == Fluids.WATER) { ++ IBlockData iblockdata1 = Blocks.CLAY.defaultBlockState(); ++ ++ level.setBlockAndUpdate(((PointedDripstoneBlock.a) optional.get()).pos, iblockdata1); ++ Block.pushEntitiesUp(((PointedDripstoneBlock.a) optional.get()).sourceState, iblockdata1, level, ((PointedDripstoneBlock.a) optional.get()).pos); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, ((PointedDripstoneBlock.a) optional.get()).pos, GameEvent.Context.of(iblockdata1)); ++ level.levelEvent(1504, blockposition1, 0); + } else { +- BlockPos blockPos1 = findFillableCauldronBelowStalactiteTip(level, blockPos, fluid); +- if (blockPos1 != null) { +- level.levelEvent(1504, blockPos, 0); +- int i = blockPos.getY() - blockPos1.getY(); +- int i1 = 50 + i; +- BlockState blockState1 = level.getBlockState(blockPos1); +- level.scheduleTick(blockPos1, blockState1.getBlock(), i1); ++ BlockPos blockposition2 = findFillableCauldronBelowStalactiteTip(level, blockposition1, fluidtype); ++ ++ if (blockposition2 != null) { ++ level.levelEvent(1504, blockposition1, 0); ++ int i = blockposition1.getY() - blockposition2.getY(); ++ int j = 50 + i; ++ IBlockData iblockdata2 = level.getBlockState(blockposition2); ++ ++ level.scheduleTick(blockposition2, iblockdata2.getBlock(), j); + } + } + } +@@ -226,61 +245,60 @@ + + @Nullable + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- LevelAccessor level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- Direction opposite = context.getNearestLookingVerticalDirection().getOpposite(); +- Direction direction = calculateTipDirection(level, clickedPos, opposite); +- if (direction == null) { ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ Direction enumdirection = context.getNearestLookingVerticalDirection().getOpposite(); ++ Direction enumdirection1 = calculateTipDirection(world, blockposition, enumdirection); ++ ++ if (enumdirection1 == null) { + return null; + } else { + boolean flag = !context.isSecondaryUseActive(); +- DripstoneThickness dripstoneThickness = calculateDripstoneThickness(level, clickedPos, direction, flag); +- return dripstoneThickness == null +- ? null +- : this.defaultBlockState() +- .setValue(TIP_DIRECTION, direction) +- .setValue(THICKNESS, dripstoneThickness) +- .setValue(WATERLOGGED, Boolean.valueOf(level.getFluidState(clickedPos).getType() == Fluids.WATER)); ++ DripstoneThickness dripstonethickness = calculateDripstoneThickness(world, blockposition, enumdirection1, flag); ++ ++ return dripstonethickness == null ? null : (IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(PointedDripstoneBlock.TIP_DIRECTION, enumdirection1)).setValue(PointedDripstoneBlock.THICKNESS, dripstonethickness)).setValue(PointedDripstoneBlock.WATERLOGGED, world.getFluidState(blockposition).getType() == Fluids.WATER); + } + } + + @Override +- public FluidState getFluidState(BlockState state) { +- return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(PointedDripstoneBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override +- public VoxelShape getOcclusionShape(BlockState state, BlockGetter level, BlockPos pos) { ++ public VoxelShape getOcclusionShape(IBlockData state, BlockGetter level, BlockPos pos) { + return Shapes.empty(); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- DripstoneThickness dripstoneThickness = state.getValue(THICKNESS); +- VoxelShape voxelShape; +- if (dripstoneThickness == DripstoneThickness.TIP_MERGE) { +- voxelShape = TIP_MERGE_SHAPE; +- } else if (dripstoneThickness == DripstoneThickness.TIP) { +- if (state.getValue(TIP_DIRECTION) == Direction.DOWN) { +- voxelShape = TIP_SHAPE_DOWN; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ DripstoneThickness dripstonethickness = (DripstoneThickness) state.getValue(PointedDripstoneBlock.THICKNESS); ++ VoxelShape voxelshape; ++ ++ if (dripstonethickness == DripstoneThickness.TIP_MERGE) { ++ voxelshape = PointedDripstoneBlock.TIP_MERGE_SHAPE; ++ } else if (dripstonethickness == DripstoneThickness.TIP) { ++ if (state.getValue(PointedDripstoneBlock.TIP_DIRECTION) == Direction.DOWN) { ++ voxelshape = PointedDripstoneBlock.TIP_SHAPE_DOWN; + } else { +- voxelShape = TIP_SHAPE_UP; ++ voxelshape = PointedDripstoneBlock.TIP_SHAPE_UP; + } +- } else if (dripstoneThickness == DripstoneThickness.FRUSTUM) { +- voxelShape = FRUSTUM_SHAPE; +- } else if (dripstoneThickness == DripstoneThickness.MIDDLE) { +- voxelShape = MIDDLE_SHAPE; ++ } else if (dripstonethickness == DripstoneThickness.FRUSTUM) { ++ voxelshape = PointedDripstoneBlock.FRUSTUM_SHAPE; ++ } else if (dripstonethickness == DripstoneThickness.MIDDLE) { ++ voxelshape = PointedDripstoneBlock.MIDDLE_SHAPE; + } else { +- voxelShape = BASE_SHAPE; ++ voxelshape = PointedDripstoneBlock.BASE_SHAPE; + } + +- Vec3 offset = state.getOffset(level, pos); +- return voxelShape.move(offset.x, 0.0, offset.z); ++ Vec3 vec3d = state.getOffset(level, pos); ++ ++ return voxelshape.move(vec3d.x, 0.0D, vec3d.z); + } + + @Override +- public boolean isCollisionShapeFullBlock(BlockState state, BlockGetter level, BlockPos pos) { ++ public boolean isCollisionShapeFullBlock(IBlockData state, BlockGetter level, BlockPos pos) { + return false; + } + +@@ -294,6 +312,7 @@ + if (!fallingBlock.isSilent()) { + level.levelEvent(1045, pos, 0); + } ++ + } + + @Override +@@ -301,258 +320,287 @@ + return entity.damageSources().fallingStalactite(entity); + } + +- private static void spawnFallingStalactite(BlockState state, ServerLevel level, BlockPos pos) { +- BlockPos.MutableBlockPos mutableBlockPos = pos.mutable(); +- BlockState blockState = state; ++ private static void spawnFallingStalactite(IBlockData state, ServerLevel level, BlockPos pos) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); + +- while (isStalactite(blockState)) { +- FallingBlockEntity fallingBlockEntity = FallingBlockEntity.fall(level, mutableBlockPos, blockState); +- if (isTip(blockState, true)) { +- int max = Math.max(1 + pos.getY() - mutableBlockPos.getY(), 6); +- float f = 1.0F * (float)max; +- fallingBlockEntity.setHurtsEntities(f, 40); ++ for (IBlockData iblockdata1 = state; isStalactite(iblockdata1); iblockdata1 = level.getBlockState(blockposition_mutableblockposition)) { ++ FallingBlockEntity entityfallingblock = FallingBlockEntity.fall(level, blockposition_mutableblockposition, iblockdata1); ++ ++ if (isTip(iblockdata1, true)) { ++ int i = Math.max(1 + pos.getY() - blockposition_mutableblockposition.getY(), 6); ++ float f = 1.0F * (float) i; ++ ++ entityfallingblock.setHurtsEntities(f, 40); + break; + } + +- mutableBlockPos.move(Direction.DOWN); +- blockState = level.getBlockState(mutableBlockPos); ++ blockposition_mutableblockposition.move(Direction.DOWN); + } ++ + } + + @VisibleForTesting +- public static void growStalactiteOrStalagmiteIfPossible(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- BlockState blockState = level.getBlockState(pos.above(1)); +- BlockState blockState1 = level.getBlockState(pos.above(2)); +- if (canGrow(blockState, blockState1)) { +- BlockPos blockPos = findTip(state, level, pos, 7, false); +- if (blockPos != null) { +- BlockState blockState2 = level.getBlockState(blockPos); +- if (canDrip(blockState2) && canTipGrow(blockState2, level, blockPos)) { ++ public static void growStalactiteOrStalagmiteIfPossible(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ IBlockData iblockdata1 = level.getBlockState(pos.above(1)); ++ IBlockData iblockdata2 = level.getBlockState(pos.above(2)); ++ ++ if (canGrow(iblockdata1, iblockdata2)) { ++ BlockPos blockposition1 = findTip(state, level, pos, 7, false); ++ ++ if (blockposition1 != null) { ++ IBlockData iblockdata3 = level.getBlockState(blockposition1); ++ ++ if (canDrip(iblockdata3) && canTipGrow(iblockdata3, level, blockposition1)) { + if (random.nextBoolean()) { +- grow(level, blockPos, Direction.DOWN); ++ grow(level, blockposition1, Direction.DOWN); + } else { +- growStalagmiteBelow(level, blockPos); ++ growStalagmiteBelow(level, blockposition1); + } ++ + } + } + } + } + + private static void growStalagmiteBelow(ServerLevel level, BlockPos pos) { +- BlockPos.MutableBlockPos mutableBlockPos = pos.mutable(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); + +- for (int i = 0; i < 10; i++) { +- mutableBlockPos.move(Direction.DOWN); +- BlockState blockState = level.getBlockState(mutableBlockPos); +- if (!blockState.getFluidState().isEmpty()) { ++ for (int i = 0; i < 10; ++i) { ++ blockposition_mutableblockposition.move(Direction.DOWN); ++ IBlockData iblockdata = level.getBlockState(blockposition_mutableblockposition); ++ ++ if (!iblockdata.getFluidState().isEmpty()) { + return; + } + +- if (isUnmergedTipWithDirection(blockState, Direction.UP) && canTipGrow(blockState, level, mutableBlockPos)) { +- grow(level, mutableBlockPos, Direction.UP); ++ if (isUnmergedTipWithDirection(iblockdata, Direction.UP) && canTipGrow(iblockdata, level, blockposition_mutableblockposition)) { ++ grow(level, blockposition_mutableblockposition, Direction.UP); + return; + } + +- if (isValidPointedDripstonePlacement(level, mutableBlockPos, Direction.UP) && !level.isWaterAt(mutableBlockPos.below())) { +- grow(level, mutableBlockPos.below(), Direction.UP); ++ if (isValidPointedDripstonePlacement(level, blockposition_mutableblockposition, Direction.UP) && !level.isWaterAt(blockposition_mutableblockposition.below())) { ++ grow(level, blockposition_mutableblockposition.below(), Direction.UP); + return; + } + +- if (!canDripThrough(level, mutableBlockPos, blockState)) { ++ if (!canDripThrough(level, blockposition_mutableblockposition, iblockdata)) { + return; + } + } ++ + } + + private static void grow(ServerLevel server, BlockPos pos, Direction direction) { +- BlockPos blockPos = pos.relative(direction); +- BlockState blockState = server.getBlockState(blockPos); +- if (isUnmergedTipWithDirection(blockState, direction.getOpposite())) { +- createMergedTips(blockState, server, blockPos); +- } else if (blockState.isAir() || blockState.is(Blocks.WATER)) { +- createDripstone(server, blockPos, direction, DripstoneThickness.TIP); ++ BlockPos blockposition1 = pos.relative(direction); ++ IBlockData iblockdata = server.getBlockState(blockposition1); ++ ++ if (isUnmergedTipWithDirection(iblockdata, direction.getOpposite())) { ++ createMergedTips(iblockdata, server, blockposition1); ++ } else if (iblockdata.isAir() || iblockdata.is(Blocks.WATER)) { ++ createDripstone(server, blockposition1, direction, DripstoneThickness.TIP, pos); // CraftBukkit + } ++ + } + +- private static void createDripstone(LevelAccessor level, BlockPos pos, Direction direction, DripstoneThickness thickness) { +- BlockState blockState = Blocks.POINTED_DRIPSTONE +- .defaultBlockState() +- .setValue(TIP_DIRECTION, direction) +- .setValue(THICKNESS, thickness) +- .setValue(WATERLOGGED, Boolean.valueOf(level.getFluidState(pos).getType() == Fluids.WATER)); +- level.setBlock(pos, blockState, 3); ++ private static void createDripstone(LevelAccessor generatoraccess, BlockPos blockposition, Direction enumdirection, DripstoneThickness dripstonethickness, BlockPos source) { // CraftBukkit ++ IBlockData iblockdata = (IBlockData) ((IBlockData) ((IBlockData) Blocks.POINTED_DRIPSTONE.defaultBlockState().setValue(PointedDripstoneBlock.TIP_DIRECTION, enumdirection)).setValue(PointedDripstoneBlock.THICKNESS, dripstonethickness)).setValue(PointedDripstoneBlock.WATERLOGGED, generatoraccess.getFluidState(blockposition).getType() == Fluids.WATER); ++ ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(generatoraccess, source, blockposition, iblockdata, 3); // CraftBukkit + } + +- private static void createMergedTips(BlockState state, LevelAccessor level, BlockPos pos) { +- BlockPos blockPos1; +- BlockPos blockPos; +- if (state.getValue(TIP_DIRECTION) == Direction.UP) { +- blockPos = pos; +- blockPos1 = pos.above(); ++ private static void createMergedTips(IBlockData state, LevelAccessor level, BlockPos pos) { ++ BlockPos blockposition1; ++ BlockPos blockposition2; ++ ++ if (state.getValue(PointedDripstoneBlock.TIP_DIRECTION) == Direction.UP) { ++ blockposition1 = pos; ++ blockposition2 = pos.above(); + } else { +- blockPos1 = pos; +- blockPos = pos.below(); ++ blockposition2 = pos; ++ blockposition1 = pos.below(); + } + +- createDripstone(level, blockPos1, Direction.DOWN, DripstoneThickness.TIP_MERGE); +- createDripstone(level, blockPos, Direction.UP, DripstoneThickness.TIP_MERGE); ++ createDripstone(level, blockposition2, Direction.DOWN, DripstoneThickness.TIP_MERGE, pos); // CraftBukkit ++ createDripstone(level, blockposition1, Direction.UP, DripstoneThickness.TIP_MERGE, pos); // CraftBukkit + } + +- public static void spawnDripParticle(Level level, BlockPos pos, BlockState state) { +- getFluidAboveStalactite(level, pos, state).ifPresent(fluidInfo -> spawnDripParticle(level, pos, state, fluidInfo.fluid)); ++ public static void spawnDripParticle(Level level, BlockPos pos, IBlockData state) { ++ getFluidAboveStalactite(level, pos, state).ifPresent((pointeddripstoneblock_a) -> { ++ spawnDripParticle(level, pos, state, pointeddripstoneblock_a.fluid); ++ }); + } + +- private static void spawnDripParticle(Level level, BlockPos pos, BlockState state, Fluid fluid) { +- Vec3 offset = state.getOffset(level, pos); +- double d = 0.0625; +- double d1 = (double)pos.getX() + 0.5 + offset.x; +- double d2 = (double)((float)(pos.getY() + 1) - 0.6875F) - 0.0625; +- double d3 = (double)pos.getZ() + 0.5 + offset.z; +- Fluid dripFluid = getDripFluid(level, fluid); +- ParticleOptions particleOptions = dripFluid.is(FluidTags.LAVA) ? ParticleTypes.DRIPPING_DRIPSTONE_LAVA : ParticleTypes.DRIPPING_DRIPSTONE_WATER; +- level.addParticle(particleOptions, d1, d2, d3, 0.0, 0.0, 0.0); ++ private static void spawnDripParticle(Level level, BlockPos pos, IBlockData state, Fluid fluid) { ++ Vec3 vec3d = state.getOffset(level, pos); ++ double d0 = 0.0625D; ++ double d1 = (double) pos.getX() + 0.5D + vec3d.x; ++ double d2 = (double) ((float) (pos.getY() + 1) - 0.6875F) - 0.0625D; ++ double d3 = (double) pos.getZ() + 0.5D + vec3d.z; ++ Fluid fluidtype1 = getDripFluid(level, fluid); ++ SimpleParticleType particletype = fluidtype1.is(FluidTags.LAVA) ? ParticleTypes.DRIPPING_DRIPSTONE_LAVA : ParticleTypes.DRIPPING_DRIPSTONE_WATER; ++ ++ level.addParticle(particletype, d1, d2, d3, 0.0D, 0.0D, 0.0D); + } + + @Nullable +- private static BlockPos findTip(BlockState state, LevelAccessor level, BlockPos pos, int maxIterations, boolean isTipMerge) { ++ private static BlockPos findTip(IBlockData state, LevelAccessor level, BlockPos pos, int maxIterations, boolean isTipMerge) { + if (isTip(state, isTipMerge)) { + return pos; + } else { +- Direction direction = state.getValue(TIP_DIRECTION); +- BiPredicate biPredicate = (predPos, predState) -> predState.is(Blocks.POINTED_DRIPSTONE) +- && predState.getValue(TIP_DIRECTION) == direction; +- return findBlockVertical(level, pos, direction.getAxisDirection(), biPredicate, predState -> isTip(predState, isTipMerge), maxIterations) +- .orElse(null); ++ Direction enumdirection = (Direction) state.getValue(PointedDripstoneBlock.TIP_DIRECTION); ++ BiPredicate bipredicate = (blockposition1, iblockdata1) -> { ++ return iblockdata1.is(Blocks.POINTED_DRIPSTONE) && iblockdata1.getValue(PointedDripstoneBlock.TIP_DIRECTION) == enumdirection; ++ }; ++ ++ return (BlockPos) findBlockVertical(level, pos, enumdirection.getAxisDirection(), bipredicate, (iblockdata1) -> { ++ return isTip(iblockdata1, isTipMerge); ++ }, maxIterations).orElse(null); // CraftBukkit - decompile error + } + } + + @Nullable + private static Direction calculateTipDirection(LevelReader level, BlockPos pos, Direction dir) { +- Direction direction; ++ Direction enumdirection1; ++ + if (isValidPointedDripstonePlacement(level, pos, dir)) { +- direction = dir; ++ enumdirection1 = dir; + } else { + if (!isValidPointedDripstonePlacement(level, pos, dir.getOpposite())) { + return null; + } + +- direction = dir.getOpposite(); ++ enumdirection1 = dir.getOpposite(); + } + +- return direction; ++ return enumdirection1; + } + + private static DripstoneThickness calculateDripstoneThickness(LevelReader level, BlockPos pos, Direction dir, boolean isTipMerge) { +- Direction opposite = dir.getOpposite(); +- BlockState blockState = level.getBlockState(pos.relative(dir)); +- if (isPointedDripstoneWithDirection(blockState, opposite)) { +- return !isTipMerge && blockState.getValue(THICKNESS) != DripstoneThickness.TIP_MERGE ? DripstoneThickness.TIP : DripstoneThickness.TIP_MERGE; +- } else if (!isPointedDripstoneWithDirection(blockState, dir)) { ++ Direction enumdirection1 = dir.getOpposite(); ++ IBlockData iblockdata = level.getBlockState(pos.relative(dir)); ++ ++ if (isPointedDripstoneWithDirection(iblockdata, enumdirection1)) { ++ return !isTipMerge && iblockdata.getValue(PointedDripstoneBlock.THICKNESS) != DripstoneThickness.TIP_MERGE ? DripstoneThickness.TIP : DripstoneThickness.TIP_MERGE; ++ } else if (!isPointedDripstoneWithDirection(iblockdata, dir)) { + return DripstoneThickness.TIP; + } else { +- DripstoneThickness dripstoneThickness = blockState.getValue(THICKNESS); +- if (dripstoneThickness != DripstoneThickness.TIP && dripstoneThickness != DripstoneThickness.TIP_MERGE) { +- BlockState blockState1 = level.getBlockState(pos.relative(opposite)); +- return !isPointedDripstoneWithDirection(blockState1, dir) ? DripstoneThickness.BASE : DripstoneThickness.MIDDLE; ++ DripstoneThickness dripstonethickness = (DripstoneThickness) iblockdata.getValue(PointedDripstoneBlock.THICKNESS); ++ ++ if (dripstonethickness != DripstoneThickness.TIP && dripstonethickness != DripstoneThickness.TIP_MERGE) { ++ IBlockData iblockdata1 = level.getBlockState(pos.relative(enumdirection1)); ++ ++ return !isPointedDripstoneWithDirection(iblockdata1, dir) ? DripstoneThickness.BASE : DripstoneThickness.MIDDLE; + } else { + return DripstoneThickness.FRUSTUM; + } + } + } + +- public static boolean canDrip(BlockState state) { +- return isStalactite(state) && state.getValue(THICKNESS) == DripstoneThickness.TIP && !state.getValue(WATERLOGGED); ++ public static boolean canDrip(IBlockData state) { ++ return isStalactite(state) && state.getValue(PointedDripstoneBlock.THICKNESS) == DripstoneThickness.TIP && !(Boolean) state.getValue(PointedDripstoneBlock.WATERLOGGED); + } + +- private static boolean canTipGrow(BlockState state, ServerLevel level, BlockPos pos) { +- Direction direction = state.getValue(TIP_DIRECTION); +- BlockPos blockPos = pos.relative(direction); +- BlockState blockState = level.getBlockState(blockPos); +- return blockState.getFluidState().isEmpty() && (blockState.isAir() || isUnmergedTipWithDirection(blockState, direction.getOpposite())); ++ private static boolean canTipGrow(IBlockData state, ServerLevel level, BlockPos pos) { ++ Direction enumdirection = (Direction) state.getValue(PointedDripstoneBlock.TIP_DIRECTION); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ return !iblockdata1.getFluidState().isEmpty() ? false : (iblockdata1.isAir() ? true : isUnmergedTipWithDirection(iblockdata1, enumdirection.getOpposite())); + } + +- private static Optional findRootBlock(Level level, BlockPos pos, BlockState state, int maxIterations) { +- Direction direction = state.getValue(TIP_DIRECTION); +- BiPredicate biPredicate = (predPos, predState) -> predState.is(Blocks.POINTED_DRIPSTONE) +- && predState.getValue(TIP_DIRECTION) == direction; +- return findBlockVertical( +- level, pos, direction.getOpposite().getAxisDirection(), biPredicate, predState -> !predState.is(Blocks.POINTED_DRIPSTONE), maxIterations +- ); ++ private static Optional findRootBlock(Level level, BlockPos pos, IBlockData state, int maxIterations) { ++ Direction enumdirection = (Direction) state.getValue(PointedDripstoneBlock.TIP_DIRECTION); ++ BiPredicate bipredicate = (blockposition1, iblockdata1) -> { ++ return iblockdata1.is(Blocks.POINTED_DRIPSTONE) && iblockdata1.getValue(PointedDripstoneBlock.TIP_DIRECTION) == enumdirection; ++ }; ++ ++ return findBlockVertical(level, pos, enumdirection.getOpposite().getAxisDirection(), bipredicate, (iblockdata1) -> { ++ return !iblockdata1.is(Blocks.POINTED_DRIPSTONE); ++ }, maxIterations); + } + + private static boolean isValidPointedDripstonePlacement(LevelReader level, BlockPos pos, Direction dir) { +- BlockPos blockPos = pos.relative(dir.getOpposite()); +- BlockState blockState = level.getBlockState(blockPos); +- return blockState.isFaceSturdy(level, blockPos, dir) || isPointedDripstoneWithDirection(blockState, dir); ++ BlockPos blockposition1 = pos.relative(dir.getOpposite()); ++ IBlockData iblockdata = level.getBlockState(blockposition1); ++ ++ return iblockdata.isFaceSturdy(level, blockposition1, dir) || isPointedDripstoneWithDirection(iblockdata, dir); + } + +- private static boolean isTip(BlockState state, boolean isTipMerge) { ++ private static boolean isTip(IBlockData state, boolean isTipMerge) { + if (!state.is(Blocks.POINTED_DRIPSTONE)) { + return false; + } else { +- DripstoneThickness dripstoneThickness = state.getValue(THICKNESS); +- return dripstoneThickness == DripstoneThickness.TIP || isTipMerge && dripstoneThickness == DripstoneThickness.TIP_MERGE; ++ DripstoneThickness dripstonethickness = (DripstoneThickness) state.getValue(PointedDripstoneBlock.THICKNESS); ++ ++ return dripstonethickness == DripstoneThickness.TIP || isTipMerge && dripstonethickness == DripstoneThickness.TIP_MERGE; + } + } + +- private static boolean isUnmergedTipWithDirection(BlockState state, Direction dir) { +- return isTip(state, false) && state.getValue(TIP_DIRECTION) == dir; ++ private static boolean isUnmergedTipWithDirection(IBlockData state, Direction dir) { ++ return isTip(state, false) && state.getValue(PointedDripstoneBlock.TIP_DIRECTION) == dir; + } + +- private static boolean isStalactite(BlockState state) { ++ private static boolean isStalactite(IBlockData state) { + return isPointedDripstoneWithDirection(state, Direction.DOWN); + } + +- private static boolean isStalagmite(BlockState state) { ++ private static boolean isStalagmite(IBlockData state) { + return isPointedDripstoneWithDirection(state, Direction.UP); + } + +- private static boolean isStalactiteStartPos(BlockState state, LevelReader level, BlockPos pos) { ++ private static boolean isStalactiteStartPos(IBlockData state, LevelReader level, BlockPos pos) { + return isStalactite(state) && !level.getBlockState(pos.above()).is(Blocks.POINTED_DRIPSTONE); + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + +- private static boolean isPointedDripstoneWithDirection(BlockState state, Direction dir) { +- return state.is(Blocks.POINTED_DRIPSTONE) && state.getValue(TIP_DIRECTION) == dir; ++ private static boolean isPointedDripstoneWithDirection(IBlockData state, Direction dir) { ++ return state.is(Blocks.POINTED_DRIPSTONE) && state.getValue(PointedDripstoneBlock.TIP_DIRECTION) == dir; + } + + @Nullable + private static BlockPos findFillableCauldronBelowStalactiteTip(Level level, BlockPos pos, Fluid fluid) { +- Predicate predicate = state -> state.getBlock() instanceof AbstractCauldronBlock +- && ((AbstractCauldronBlock)state.getBlock()).canReceiveStalactiteDrip(fluid); +- BiPredicate biPredicate = (predPos, predState) -> canDripThrough(level, predPos, predState); +- return findBlockVertical(level, pos, Direction.DOWN.getAxisDirection(), biPredicate, predicate, 11).orElse(null); ++ Predicate predicate = (iblockdata) -> { ++ return iblockdata.getBlock() instanceof AbstractCauldronBlock && ((AbstractCauldronBlock) iblockdata.getBlock()).canReceiveStalactiteDrip(fluid); ++ }; ++ BiPredicate bipredicate = (blockposition1, iblockdata) -> { ++ return canDripThrough(level, blockposition1, iblockdata); ++ }; ++ ++ return (BlockPos) findBlockVertical(level, pos, Direction.DOWN.getAxisDirection(), bipredicate, predicate, 11).orElse(null); // CraftBukkit - decompile error + } + + @Nullable + public static BlockPos findStalactiteTipAboveCauldron(Level level, BlockPos pos) { +- BiPredicate biPredicate = (predPos, predState) -> canDripThrough(level, predPos, predState); +- return findBlockVertical(level, pos, Direction.UP.getAxisDirection(), biPredicate, PointedDripstoneBlock::canDrip, 11).orElse(null); ++ BiPredicate bipredicate = (blockposition1, iblockdata) -> { ++ return canDripThrough(level, blockposition1, iblockdata); ++ }; ++ ++ return (BlockPos) findBlockVertical(level, pos, Direction.UP.getAxisDirection(), bipredicate, PointedDripstoneBlock::canDrip, 11).orElse(null); // CraftBukkit - decompile error + } + + public static Fluid getCauldronFillFluidType(ServerLevel level, BlockPos pos) { +- return getFluidAboveStalactite(level, pos, level.getBlockState(pos)) +- .map(fluidInfo -> fluidInfo.fluid) +- .filter(PointedDripstoneBlock::canFillCauldron) +- .orElse(Fluids.EMPTY); ++ return (Fluid) getFluidAboveStalactite(level, pos, level.getBlockState(pos)).map((pointeddripstoneblock_a) -> { ++ return pointeddripstoneblock_a.fluid; ++ }).filter(PointedDripstoneBlock::canFillCauldron).orElse(Fluids.EMPTY); + } + +- private static Optional getFluidAboveStalactite(Level level, BlockPos pos, BlockState state) { +- return !isStalactite(state) ? Optional.empty() : findRootBlock(level, pos, state, 11).map(rootBlockPos -> { +- BlockPos blockPos = rootBlockPos.above(); +- BlockState blockState = level.getBlockState(blockPos); +- Fluid fluid; +- if (blockState.is(Blocks.MUD) && !level.dimensionType().ultraWarm()) { +- fluid = Fluids.WATER; ++ private static Optional getFluidAboveStalactite(Level level, BlockPos pos, IBlockData state) { ++ return !isStalactite(state) ? Optional.empty() : findRootBlock(level, pos, state, 11).map((blockposition1) -> { ++ BlockPos blockposition2 = blockposition1.above(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition2); ++ Object object; ++ ++ if (iblockdata1.is(Blocks.MUD) && !level.dimensionType().ultraWarm()) { ++ object = Fluids.WATER; + } else { +- fluid = level.getFluidState(blockPos).getType(); ++ object = level.getFluidState(blockposition2).getType(); + } + +- return new PointedDripstoneBlock.FluidInfo(blockPos, fluid, blockState); ++ return new PointedDripstoneBlock.a(blockposition2, (Fluid) object, iblockdata1); + }); + } + +@@ -560,37 +608,27 @@ + return fluid == Fluids.LAVA || fluid == Fluids.WATER; + } + +- private static boolean canGrow(BlockState dripstoneState, BlockState state) { ++ private static boolean canGrow(IBlockData dripstoneState, IBlockData state) { + return dripstoneState.is(Blocks.DRIPSTONE_BLOCK) && state.is(Blocks.WATER) && state.getFluidState().isSource(); + } + + private static Fluid getDripFluid(Level level, Fluid fluid) { +- if (fluid.isSame(Fluids.EMPTY)) { +- return level.dimensionType().ultraWarm() ? Fluids.LAVA : Fluids.WATER; +- } else { +- return fluid; +- } ++ return (Fluid) (fluid.isSame(Fluids.EMPTY) ? (level.dimensionType().ultraWarm() ? Fluids.LAVA : Fluids.WATER) : fluid); + } + +- private static Optional findBlockVertical( +- LevelAccessor level, +- BlockPos pos, +- Direction.AxisDirection axis, +- BiPredicate positionalStatePredicate, +- Predicate statePredicate, +- int maxIterations +- ) { +- Direction direction = Direction.get(axis, Direction.Axis.Y); +- BlockPos.MutableBlockPos mutableBlockPos = pos.mutable(); ++ private static Optional findBlockVertical(LevelAccessor level, BlockPos pos, Direction.AxisDirection axis, BiPredicate positionalStatePredicate, Predicate statePredicate, int maxIterations) { ++ Direction enumdirection = Direction.get(axis, Direction.Axis.Y); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); + +- for (int i = 1; i < maxIterations; i++) { +- mutableBlockPos.move(direction); +- BlockState blockState = level.getBlockState(mutableBlockPos); +- if (statePredicate.test(blockState)) { +- return Optional.of(mutableBlockPos.immutable()); ++ for (int j = 1; j < maxIterations; ++j) { ++ blockposition_mutableblockposition.move(enumdirection); ++ IBlockData iblockdata = level.getBlockState(blockposition_mutableblockposition); ++ ++ if (statePredicate.test(iblockdata)) { ++ return Optional.of(blockposition_mutableblockposition.immutable()); + } + +- if (level.isOutsideBuildHeight(mutableBlockPos.getY()) || !positionalStatePredicate.test(mutableBlockPos, blockState)) { ++ if (level.isOutsideBuildHeight(blockposition_mutableblockposition.getY()) || !positionalStatePredicate.test(blockposition_mutableblockposition, iblockdata)) { + return Optional.empty(); + } + } +@@ -598,7 +636,7 @@ + return Optional.empty(); + } + +- private static boolean canDripThrough(BlockGetter level, BlockPos pos, BlockState state) { ++ private static boolean canDripThrough(BlockGetter level, BlockPos pos, IBlockData state) { + if (state.isAir()) { + return true; + } else if (state.isSolidRender(level, pos)) { +@@ -606,11 +644,13 @@ + } else if (!state.getFluidState().isEmpty()) { + return false; + } else { +- VoxelShape collisionShape = state.getCollisionShape(level, pos); +- return !Shapes.joinIsNotEmpty(REQUIRED_SPACE_TO_DRIP_THROUGH_NON_SOLID_BLOCK, collisionShape, BooleanOp.AND); ++ VoxelShape voxelshape = state.getCollisionShape(level, pos); ++ ++ return !Shapes.joinIsNotEmpty(PointedDripstoneBlock.REQUIRED_SPACE_TO_DRIP_THROUGH_NON_SOLID_BLOCK, voxelshape, BooleanOp.AND); + } + } + +- static record FluidInfo(BlockPos pos, Fluid fluid, BlockState sourceState) { ++ static record a(BlockPos pos, Fluid fluid, IBlockData sourceState) { ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/PowderSnowBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/PowderSnowBlock.java.patch new file mode 100644 index 0000000000..d89092747b --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/PowderSnowBlock.java.patch @@ -0,0 +1,172 @@ +--- a/net/minecraft/world/level/block/PowderSnowBlock.java ++++ b/net/minecraft/world/level/block/PowderSnowBlock.java +@@ -23,8 +23,8 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.EntityCollisionContext; +@@ -32,18 +32,19 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + + public class PowderSnowBlock extends Block implements BucketPickup { ++ + public static final MapCodec CODEC = simpleCodec(PowderSnowBlock::new); + private static final float HORIZONTAL_PARTICLE_MOMENTUM_FACTOR = 0.083333336F; + private static final float IN_BLOCK_HORIZONTAL_SPEED_MULTIPLIER = 0.9F; + private static final float IN_BLOCK_VERTICAL_SPEED_MULTIPLIER = 1.5F; + private static final float NUM_BLOCKS_TO_FALL_INTO_BLOCK = 2.5F; +- private static final VoxelShape FALLING_COLLISION_SHAPE = Shapes.box(0.0, 0.0, 0.0, 1.0, 0.9F, 1.0); +- private static final double MINIMUM_FALL_DISTANCE_FOR_SOUND = 4.0; +- private static final double MINIMUM_FALL_DISTANCE_FOR_BIG_SOUND = 7.0; ++ private static final VoxelShape FALLING_COLLISION_SHAPE = Shapes.box(0.0D, 0.0D, 0.0D, 1.0D, 0.8999999761581421D, 1.0D); ++ private static final double MINIMUM_FALL_DISTANCE_FOR_SOUND = 4.0D; ++ private static final double MINIMUM_FALL_DISTANCE_FOR_BIG_SOUND = 7.0D; + + @Override + public MapCodec codec() { +- return CODEC; ++ return PowderSnowBlock.CODEC; + } + + public PowderSnowBlock(BlockBehaviour.Properties properties) { +@@ -51,67 +52,69 @@ + } + + @Override +- public boolean skipRendering(BlockState state, BlockState adjacentState, Direction direction) { +- return adjacentState.is(this) || super.skipRendering(state, adjacentState, direction); ++ public boolean skipRendering(IBlockData state, IBlockData adjacentState, Direction direction) { ++ return adjacentState.is((Block) this) ? true : super.skipRendering(state, adjacentState, direction); + } + + @Override +- public VoxelShape getOcclusionShape(BlockState state, BlockGetter level, BlockPos pos) { ++ public VoxelShape getOcclusionShape(IBlockData state, BlockGetter level, BlockPos pos) { + return Shapes.empty(); + } + + @Override +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { +- if (!(entity instanceof LivingEntity) || entity.getFeetBlockState().is(this)) { +- entity.makeStuckInBlock(state, new Vec3(0.9F, 1.5, 0.9F)); ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { ++ if (!(entity instanceof LivingEntity) || entity.getFeetBlockState().is((Block) this)) { ++ entity.makeStuckInBlock(state, new Vec3(0.8999999761581421D, 1.5D, 0.8999999761581421D)); + if (level.isClientSide) { +- RandomSource random = level.getRandom(); ++ RandomSource randomsource = level.getRandom(); + boolean flag = entity.xOld != entity.getX() || entity.zOld != entity.getZ(); +- if (flag && random.nextBoolean()) { +- level.addParticle( +- ParticleTypes.SNOWFLAKE, +- entity.getX(), +- (double)(pos.getY() + 1), +- entity.getZ(), +- (double)(Mth.randomBetween(random, -1.0F, 1.0F) * 0.083333336F), +- 0.05F, +- (double)(Mth.randomBetween(random, -1.0F, 1.0F) * 0.083333336F) +- ); ++ ++ if (flag && randomsource.nextBoolean()) { ++ level.addParticle(ParticleTypes.SNOWFLAKE, entity.getX(), (double) (pos.getY() + 1), entity.getZ(), (double) (Mth.randomBetween(randomsource, -1.0F, 1.0F) * 0.083333336F), 0.05000000074505806D, (double) (Mth.randomBetween(randomsource, -1.0F, 1.0F) * 0.083333336F)); + } + } + } + + entity.setIsInPowderSnow(true); + if (!level.isClientSide) { +- if (entity.isOnFire() +- && (level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity instanceof Player) +- && entity.mayInteract(level, pos)) { ++ // CraftBukkit start ++ if (entity.isOnFire() && entity.mayInteract(level, pos)) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !(level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity instanceof Player))) { ++ return; ++ } ++ // CraftBukkit end + level.destroyBlock(pos, false); + } + + entity.setSharedFlagOnFire(false); + } ++ + } + + @Override +- public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, float fallDistance) { +- if (!((double)fallDistance < 4.0) && entity instanceof LivingEntity livingEntity) { +- LivingEntity.Fallsounds fallSounds = livingEntity.getFallSounds(); +- SoundEvent soundEvent = (double)fallDistance < 7.0 ? fallSounds.small() : fallSounds.big(); +- entity.playSound(soundEvent, 1.0F, 1.0F); ++ public void fallOn(Level level, IBlockData state, BlockPos pos, Entity entity, float fallDistance) { ++ if ((double) fallDistance >= 4.0D && entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ LivingEntity.a entityliving_a = entityliving.getFallSounds(); ++ SoundEvent soundeffect = (double) fallDistance < 7.0D ? entityliving_a.small() : entityliving_a.big(); ++ ++ entity.playSound(soundeffect, 1.0F, 1.0F); + } + } + + @Override +- public VoxelShape getCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- if (context instanceof EntityCollisionContext entityCollisionContext) { +- Entity entity = entityCollisionContext.getEntity(); ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ if (context instanceof EntityCollisionContext) { ++ EntityCollisionContext voxelshapecollisionentity = (EntityCollisionContext) context; ++ Entity entity = voxelshapecollisionentity.getEntity(); ++ + if (entity != null) { + if (entity.fallDistance > 2.5F) { +- return FALLING_COLLISION_SHAPE; ++ return PowderSnowBlock.FALLING_COLLISION_SHAPE; + } + + boolean flag = entity instanceof FallingBlockEntity; ++ + if (flag || canEntityWalkOnPowderSnow(entity) && context.isAbove(Shapes.block(), pos, false) && !context.isDescending()) { + return super.getCollisionShape(state, level, pos, context); + } +@@ -122,20 +125,19 @@ + } + + @Override +- public VoxelShape getVisualShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ public VoxelShape getVisualShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return Shapes.empty(); + } + + public static boolean canEntityWalkOnPowderSnow(Entity entity) { +- return entity.getType().is(EntityTypeTags.POWDER_SNOW_WALKABLE_MOBS) +- || entity instanceof LivingEntity && ((LivingEntity)entity).getItemBySlot(EquipmentSlot.FEET).is(Items.LEATHER_BOOTS); ++ return entity.getType().is(EntityTypeTags.POWDER_SNOW_WALKABLE_MOBS) ? true : (entity instanceof LivingEntity ? ((LivingEntity) entity).getItemBySlot(EquipmentSlot.FEET).is(Items.LEATHER_BOOTS) : false); + } + + @Override +- public ItemStack pickupBlock(@Nullable Player player, LevelAccessor levelAccessor, BlockPos blockPos, BlockState blockState) { +- levelAccessor.setBlock(blockPos, Blocks.AIR.defaultBlockState(), 11); +- if (!levelAccessor.isClientSide()) { +- levelAccessor.levelEvent(2001, blockPos, Block.getId(blockState)); ++ public ItemStack pickupBlock(@Nullable Player entityhuman, LevelAccessor generatoraccess, BlockPos blockposition, IBlockData iblockdata) { ++ generatoraccess.setBlock(blockposition, Blocks.AIR.defaultBlockState(), 11); ++ if (!generatoraccess.isClientSide()) { ++ generatoraccess.levelEvent(2001, blockposition, Block.getId(iblockdata)); + } + + return new ItemStack(Items.POWDER_SNOW_BUCKET); +@@ -147,7 +149,7 @@ + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return true; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/PoweredRailBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/PoweredRailBlock.java.patch new file mode 100644 index 0000000000..e8e8b74e39 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/PoweredRailBlock.java.patch @@ -0,0 +1,381 @@ +--- a/net/minecraft/world/level/block/PoweredRailBlock.java ++++ b/net/minecraft/world/level/block/PoweredRailBlock.java +@@ -4,215 +4,211 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.block.state.properties.EnumProperty; + import net.minecraft.world.level.block.state.properties.Property; + import net.minecraft.world.level.block.state.properties.RailShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class PoweredRailBlock extends BaseRailBlock { ++ + public static final MapCodec CODEC = simpleCodec(PoweredRailBlock::new); + public static final EnumProperty SHAPE = BlockStateProperties.RAIL_SHAPE_STRAIGHT; + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + + @Override + public MapCodec codec() { +- return CODEC; ++ return PoweredRailBlock.CODEC; + } + + protected PoweredRailBlock(BlockBehaviour.Properties properties) { + super(true, properties); +- this.registerDefaultState( +- this.stateDefinition +- .any() +- .setValue(SHAPE, RailShape.NORTH_SOUTH) +- .setValue(POWERED, Boolean.valueOf(false)) +- .setValue(WATERLOGGED, Boolean.valueOf(false)) +- ); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_SOUTH)).setValue(PoweredRailBlock.POWERED, false)).setValue(PoweredRailBlock.WATERLOGGED, false)); + } + +- protected boolean findPoweredRailSignal(Level level, BlockPos pos, BlockState state, boolean searchForward, int recursionCount) { ++ protected boolean findPoweredRailSignal(Level level, BlockPos pos, IBlockData state, boolean searchForward, int recursionCount) { + if (recursionCount >= 8) { + return false; + } else { +- int x = pos.getX(); +- int y = pos.getY(); +- int z = pos.getZ(); +- boolean flag = true; +- RailShape railShape = state.getValue(SHAPE); +- switch (railShape) { ++ int j = pos.getX(); ++ int k = pos.getY(); ++ int l = pos.getZ(); ++ boolean flag1 = true; ++ RailShape blockpropertytrackposition = (RailShape) state.getValue(PoweredRailBlock.SHAPE); ++ ++ switch (blockpropertytrackposition) { + case NORTH_SOUTH: + if (searchForward) { +- z++; ++ ++l; + } else { +- z--; ++ --l; + } + break; + case EAST_WEST: + if (searchForward) { +- x--; ++ --j; + } else { +- x++; ++ ++j; + } + break; + case ASCENDING_EAST: + if (searchForward) { +- x--; ++ --j; + } else { +- x++; +- y++; +- flag = false; ++ ++j; ++ ++k; ++ flag1 = false; + } + +- railShape = RailShape.EAST_WEST; ++ blockpropertytrackposition = RailShape.EAST_WEST; + break; + case ASCENDING_WEST: + if (searchForward) { +- x--; +- y++; +- flag = false; ++ --j; ++ ++k; ++ flag1 = false; + } else { +- x++; ++ ++j; + } + +- railShape = RailShape.EAST_WEST; ++ blockpropertytrackposition = RailShape.EAST_WEST; + break; + case ASCENDING_NORTH: + if (searchForward) { +- z++; ++ ++l; + } else { +- z--; +- y++; +- flag = false; ++ --l; ++ ++k; ++ flag1 = false; + } + +- railShape = RailShape.NORTH_SOUTH; ++ blockpropertytrackposition = RailShape.NORTH_SOUTH; + break; + case ASCENDING_SOUTH: + if (searchForward) { +- z++; +- y++; +- flag = false; ++ ++l; ++ ++k; ++ flag1 = false; + } else { +- z--; ++ --l; + } + +- railShape = RailShape.NORTH_SOUTH; ++ blockpropertytrackposition = RailShape.NORTH_SOUTH; + } + +- return this.isSameRailWithPower(level, new BlockPos(x, y, z), searchForward, recursionCount, railShape) +- || flag && this.isSameRailWithPower(level, new BlockPos(x, y - 1, z), searchForward, recursionCount, railShape); ++ return this.isSameRailWithPower(level, new BlockPos(j, k, l), searchForward, recursionCount, blockpropertytrackposition) ? true : flag1 && this.isSameRailWithPower(level, new BlockPos(j, k - 1, l), searchForward, recursionCount, blockpropertytrackposition); + } + } + + protected boolean isSameRailWithPower(Level level, BlockPos state, boolean searchForward, int recursionCount, RailShape shape) { +- BlockState blockState = level.getBlockState(state); +- if (!blockState.is(this)) { ++ IBlockData iblockdata = level.getBlockState(state); ++ ++ if (!iblockdata.is((Block) this)) { + return false; + } else { +- RailShape railShape = blockState.getValue(SHAPE); +- return ( +- shape != RailShape.EAST_WEST +- || railShape != RailShape.NORTH_SOUTH && railShape != RailShape.ASCENDING_NORTH && railShape != RailShape.ASCENDING_SOUTH +- ) +- && ( +- shape != RailShape.NORTH_SOUTH +- || railShape != RailShape.EAST_WEST && railShape != RailShape.ASCENDING_EAST && railShape != RailShape.ASCENDING_WEST +- ) +- && blockState.getValue(POWERED) +- && (level.hasNeighborSignal(state) || this.findPoweredRailSignal(level, state, blockState, searchForward, recursionCount + 1)); ++ RailShape blockpropertytrackposition1 = (RailShape) iblockdata.getValue(PoweredRailBlock.SHAPE); ++ ++ return shape == RailShape.EAST_WEST && (blockpropertytrackposition1 == RailShape.NORTH_SOUTH || blockpropertytrackposition1 == RailShape.ASCENDING_NORTH || blockpropertytrackposition1 == RailShape.ASCENDING_SOUTH) ? false : (shape == RailShape.NORTH_SOUTH && (blockpropertytrackposition1 == RailShape.EAST_WEST || blockpropertytrackposition1 == RailShape.ASCENDING_EAST || blockpropertytrackposition1 == RailShape.ASCENDING_WEST) ? false : ((Boolean) iblockdata.getValue(PoweredRailBlock.POWERED) ? (level.hasNeighborSignal(state) ? true : this.findPoweredRailSignal(level, state, iblockdata, searchForward, recursionCount + 1)) : false)); + } + } + + @Override +- protected void updateState(BlockState state, Level level, BlockPos pos, Block block) { +- boolean flag = state.getValue(POWERED); +- boolean flag1 = level.hasNeighborSignal(pos) +- || this.findPoweredRailSignal(level, pos, state, true, 0) +- || this.findPoweredRailSignal(level, pos, state, false, 0); ++ protected void updateState(IBlockData state, Level level, BlockPos pos, Block block) { ++ boolean flag = (Boolean) state.getValue(PoweredRailBlock.POWERED); ++ boolean flag1 = level.hasNeighborSignal(pos) || this.findPoweredRailSignal(level, pos, state, true, 0) || this.findPoweredRailSignal(level, pos, state, false, 0); ++ + if (flag1 != flag) { +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(flag1)), 3); ++ // CraftBukkit start ++ int power = flag ? 15 : 0; ++ int newPower = CraftEventFactory.callRedstoneChange(level, pos, power, 15 - power).getNewCurrent(); ++ if (newPower == power) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(PoweredRailBlock.POWERED, flag1), 3); + level.updateNeighborsAt(pos.below(), this); +- if (state.getValue(SHAPE).isAscending()) { ++ if (((RailShape) state.getValue(PoweredRailBlock.SHAPE)).isAscending()) { + level.updateNeighborsAt(pos.above(), this); + } + } ++ + } + + @Override + public Property getShapeProperty() { +- return SHAPE; ++ return PoweredRailBlock.SHAPE; + } + + @Override +- public BlockState rotate(BlockState state, Rotation rot) { ++ public IBlockData rotate(IBlockData state, Rotation rot) { + switch (rot) { + case CLOCKWISE_180: +- switch ((RailShape)state.getValue(SHAPE)) { ++ switch ((RailShape) state.getValue(PoweredRailBlock.SHAPE)) { + case ASCENDING_EAST: +- return state.setValue(SHAPE, RailShape.ASCENDING_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_WEST); + case ASCENDING_WEST: +- return state.setValue(SHAPE, RailShape.ASCENDING_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_EAST); + case ASCENDING_NORTH: +- return state.setValue(SHAPE, RailShape.ASCENDING_SOUTH); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); + case ASCENDING_SOUTH: +- return state.setValue(SHAPE, RailShape.ASCENDING_NORTH); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_NORTH); + case SOUTH_EAST: +- return state.setValue(SHAPE, RailShape.NORTH_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_WEST); + case SOUTH_WEST: +- return state.setValue(SHAPE, RailShape.NORTH_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_EAST); + case NORTH_WEST: +- return state.setValue(SHAPE, RailShape.SOUTH_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_EAST); + case NORTH_EAST: +- return state.setValue(SHAPE, RailShape.SOUTH_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_WEST); + } + case COUNTERCLOCKWISE_90: +- switch ((RailShape)state.getValue(SHAPE)) { ++ switch ((RailShape) state.getValue(PoweredRailBlock.SHAPE)) { + case NORTH_SOUTH: +- return state.setValue(SHAPE, RailShape.EAST_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.EAST_WEST); + case EAST_WEST: +- return state.setValue(SHAPE, RailShape.NORTH_SOUTH); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_SOUTH); + case ASCENDING_EAST: +- return state.setValue(SHAPE, RailShape.ASCENDING_NORTH); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_NORTH); + case ASCENDING_WEST: +- return state.setValue(SHAPE, RailShape.ASCENDING_SOUTH); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); + case ASCENDING_NORTH: +- return state.setValue(SHAPE, RailShape.ASCENDING_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_WEST); + case ASCENDING_SOUTH: +- return state.setValue(SHAPE, RailShape.ASCENDING_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_EAST); + case SOUTH_EAST: +- return state.setValue(SHAPE, RailShape.NORTH_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_EAST); + case SOUTH_WEST: +- return state.setValue(SHAPE, RailShape.SOUTH_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_EAST); + case NORTH_WEST: +- return state.setValue(SHAPE, RailShape.SOUTH_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_WEST); + case NORTH_EAST: +- return state.setValue(SHAPE, RailShape.NORTH_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_WEST); + } + case CLOCKWISE_90: +- switch ((RailShape)state.getValue(SHAPE)) { ++ switch ((RailShape) state.getValue(PoweredRailBlock.SHAPE)) { + case NORTH_SOUTH: +- return state.setValue(SHAPE, RailShape.EAST_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.EAST_WEST); + case EAST_WEST: +- return state.setValue(SHAPE, RailShape.NORTH_SOUTH); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_SOUTH); + case ASCENDING_EAST: +- return state.setValue(SHAPE, RailShape.ASCENDING_SOUTH); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); + case ASCENDING_WEST: +- return state.setValue(SHAPE, RailShape.ASCENDING_NORTH); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_NORTH); + case ASCENDING_NORTH: +- return state.setValue(SHAPE, RailShape.ASCENDING_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_EAST); + case ASCENDING_SOUTH: +- return state.setValue(SHAPE, RailShape.ASCENDING_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_WEST); + case SOUTH_EAST: +- return state.setValue(SHAPE, RailShape.SOUTH_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_WEST); + case SOUTH_WEST: +- return state.setValue(SHAPE, RailShape.NORTH_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_WEST); + case NORTH_WEST: +- return state.setValue(SHAPE, RailShape.NORTH_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_EAST); + case NORTH_EAST: +- return state.setValue(SHAPE, RailShape.SOUTH_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_EAST); + } + default: + return state; +@@ -220,44 +216,45 @@ + } + + @Override +- public BlockState mirror(BlockState state, Mirror mirror) { +- RailShape railShape = state.getValue(SHAPE); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ RailShape blockpropertytrackposition = (RailShape) state.getValue(PoweredRailBlock.SHAPE); ++ + switch (mirror) { + case LEFT_RIGHT: +- switch (railShape) { ++ switch (blockpropertytrackposition) { + case ASCENDING_NORTH: +- return state.setValue(SHAPE, RailShape.ASCENDING_SOUTH); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_SOUTH); + case ASCENDING_SOUTH: +- return state.setValue(SHAPE, RailShape.ASCENDING_NORTH); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_NORTH); + case SOUTH_EAST: +- return state.setValue(SHAPE, RailShape.NORTH_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_EAST); + case SOUTH_WEST: +- return state.setValue(SHAPE, RailShape.NORTH_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_WEST); + case NORTH_WEST: +- return state.setValue(SHAPE, RailShape.SOUTH_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_WEST); + case NORTH_EAST: +- return state.setValue(SHAPE, RailShape.SOUTH_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_EAST); + default: + return super.mirror(state, mirror); + } + case FRONT_BACK: +- switch (railShape) { ++ switch (blockpropertytrackposition) { + case ASCENDING_EAST: +- return state.setValue(SHAPE, RailShape.ASCENDING_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_WEST); + case ASCENDING_WEST: +- return state.setValue(SHAPE, RailShape.ASCENDING_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.ASCENDING_EAST); + case ASCENDING_NORTH: + case ASCENDING_SOUTH: + default: + break; + case SOUTH_EAST: +- return state.setValue(SHAPE, RailShape.SOUTH_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_WEST); + case SOUTH_WEST: +- return state.setValue(SHAPE, RailShape.SOUTH_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.SOUTH_EAST); + case NORTH_WEST: +- return state.setValue(SHAPE, RailShape.NORTH_EAST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_EAST); + case NORTH_EAST: +- return state.setValue(SHAPE, RailShape.NORTH_WEST); ++ return (IBlockData) state.setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_WEST); + } + } + +@@ -265,7 +262,7 @@ + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(SHAPE, POWERED, WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(PoweredRailBlock.SHAPE, PoweredRailBlock.POWERED, PoweredRailBlock.WATERLOGGED); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/PressurePlateBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/PressurePlateBlock.java.patch new file mode 100644 index 0000000000..6f7e246e10 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/PressurePlateBlock.java.patch @@ -0,0 +1,119 @@ +--- a/net/minecraft/world/level/block/PressurePlateBlock.java ++++ b/net/minecraft/world/level/block/PressurePlateBlock.java +@@ -2,56 +2,95 @@ + + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import net.minecraft.core.BlockPos; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockSetType; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end + + public class PressurePlateBlock extends BasePressurePlateBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group(BlockSetType.CODEC.fieldOf("block_set_type").forGetter(pressurePlateBlock -> pressurePlateBlock.type), propertiesCodec()) +- .apply(instance, PressurePlateBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(BlockSetType.CODEC.fieldOf("block_set_type").forGetter((blockpressureplatebinary) -> { ++ return blockpressureplatebinary.type; ++ }), propertiesCodec()).apply(instance, PressurePlateBlock::new); ++ }); + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + + @Override + public MapCodec codec() { +- return CODEC; ++ return PressurePlateBlock.CODEC; + } + +- protected PressurePlateBlock(BlockSetType type, BlockBehaviour.Properties properties) { +- super(properties, type); +- this.registerDefaultState(this.stateDefinition.any().setValue(POWERED, Boolean.valueOf(false))); ++ protected PressurePlateBlock(BlockSetType blocksettype, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info, blocksettype); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(PressurePlateBlock.POWERED, false)); + } + + @Override +- protected int getSignalForState(BlockState state) { +- return state.getValue(POWERED) ? 15 : 0; ++ protected int getSignalForState(IBlockData state) { ++ return (Boolean) state.getValue(PressurePlateBlock.POWERED) ? 15 : 0; + } + + @Override +- protected BlockState setSignalForState(BlockState state, int strength) { +- return state.setValue(POWERED, Boolean.valueOf(strength > 0)); ++ protected IBlockData setSignalForState(IBlockData state, int strength) { ++ return (IBlockData) state.setValue(PressurePlateBlock.POWERED, strength > 0); + } + + @Override + protected int getSignalStrength(Level level, BlockPos pos) { +- Class clazz = switch (this.type.pressurePlateSensitivity()) { +- case EVERYTHING -> Entity.class; +- case MOBS -> LivingEntity.class; +- }; +- return getEntityCount(level, TOUCH_AABB.move(pos), clazz) > 0 ? 15 : 0; ++ Class oclass; // CraftBukkit ++ ++ switch (this.type.pressurePlateSensitivity()) { ++ case EVERYTHING: ++ oclass = Entity.class; ++ break; ++ case MOBS: ++ oclass = LivingEntity.class; ++ break; ++ default: ++ throw new IncompatibleClassChangeError(); ++ } ++ ++ Class oclass1 = oclass; ++ ++ // CraftBukkit start - Call interact event when turning on a pressure plate ++ for (Entity entity : getEntities(level, PressurePlateBlock.TOUCH_AABB.move(pos), oclass)) { ++ if (this.getSignalForState(level.getBlockState(pos)) == 0) { ++ org.bukkit.World bworld = level.getWorld(); ++ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager(); ++ org.bukkit.event.Cancellable cancellable; ++ ++ if (entity instanceof Player) { ++ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ manager.callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ // We only want to block turning the plate on if all events are cancelled ++ if (cancellable.isCancelled()) { ++ continue; ++ } ++ } ++ ++ return 15; ++ } ++ ++ return 0; ++ // CraftBukkit end + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(POWERED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(PressurePlateBlock.POWERED); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/RedStoneOreBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/RedStoneOreBlock.java.patch new file mode 100644 index 0000000000..a73bf922c1 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/RedStoneOreBlock.java.patch @@ -0,0 +1,209 @@ +--- a/net/minecraft/world/level/block/RedStoneOreBlock.java ++++ b/net/minecraft/world/level/block/RedStoneOreBlock.java +@@ -3,10 +3,10 @@ + import com.mojang.serialization.MapCodec; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.particles.DustParticleOptions; ++import net.minecraft.core.particles.ParticleParamRedstone; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; +@@ -17,107 +17,153 @@ + import net.minecraft.world.item.enchantment.Enchantments; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.phys.BlockHitResult; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end + + public class RedStoneOreBlock extends Block { ++ + public static final MapCodec CODEC = simpleCodec(RedStoneOreBlock::new); + public static final BooleanProperty LIT = RedstoneTorchBlock.LIT; + + @Override + public MapCodec codec() { +- return CODEC; ++ return RedStoneOreBlock.CODEC; + } + + public RedStoneOreBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.defaultBlockState().setValue(LIT, Boolean.valueOf(false))); ++ this.registerDefaultState((IBlockData) this.defaultBlockState().setValue(RedStoneOreBlock.LIT, false)); + } + + @Override +- public void attack(BlockState state, Level level, BlockPos pos, Player player) { +- interact(state, level, pos); ++ public void attack(IBlockData state, Level level, BlockPos pos, Player player) { ++ interact(state, level, pos, player); // CraftBukkit - add entityhuman + super.attack(state, level, pos, player); + } + + @Override +- public void stepOn(Level level, BlockPos pos, BlockState state, Entity entity) { ++ public void stepOn(Level level, BlockPos pos, IBlockData state, Entity entity) { + if (!entity.isSteppingCarefully()) { +- interact(state, level, pos); ++ // CraftBukkit start ++ if (entity instanceof Player) { ++ org.bukkit.event.player.PlayerInteractEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ if (!event.isCancelled()) { ++ interact(level.getBlockState(pos), level, pos, entity); // add entity ++ } ++ } else { ++ EntityInteractEvent event = new EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ interact(level.getBlockState(pos), level, pos, entity); // add entity ++ } ++ } ++ // CraftBukkit end + } + + super.stepOn(level, pos, state, entity); + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + if (level.isClientSide) { + spawnParticles(level, pos); + } else { +- interact(state, level, pos); ++ interact(state, level, pos, player); // CraftBukkit - add entityhuman + } + +- ItemStack itemInHand = player.getItemInHand(hand); +- return itemInHand.getItem() instanceof BlockItem && new BlockPlaceContext(player, hand, itemInHand, hit).canPlace() +- ? InteractionResult.PASS +- : InteractionResult.SUCCESS; ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ return itemstack.getItem() instanceof BlockItem && (new BlockPlaceContext(player, hand, itemstack, hit)).canPlace() ? InteractionResult.PASS : InteractionResult.SUCCESS; + } + +- private static void interact(BlockState state, Level level, BlockPos pos) { +- spawnParticles(level, pos); +- if (!state.getValue(LIT)) { +- level.setBlock(pos, state.setValue(LIT, Boolean.valueOf(true)), 3); ++ private static void interact(IBlockData iblockdata, Level world, BlockPos blockposition, Entity entity) { // CraftBukkit - add Entity ++ spawnParticles(world, blockposition); ++ if (!(Boolean) iblockdata.getValue(RedStoneOreBlock.LIT)) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, iblockdata.setValue(RedStoneOreBlock.LIT, true))) { ++ return; ++ } ++ // CraftBukkit end ++ world.setBlock(blockposition, (IBlockData) iblockdata.setValue(RedStoneOreBlock.LIT, true), 3); + } ++ + } + + @Override +- public boolean isRandomlyTicking(BlockState state) { +- return state.getValue(LIT); ++ public boolean isRandomlyTicking(IBlockData state) { ++ return (Boolean) state.getValue(RedStoneOreBlock.LIT); + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- if (state.getValue(LIT)) { +- level.setBlock(pos, state.setValue(LIT, Boolean.valueOf(false)), 3); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(RedStoneOreBlock.LIT)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callBlockFadeEvent(level, pos, state.setValue(RedStoneOreBlock.LIT, false)).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(RedStoneOreBlock.LIT, false), 3); + } ++ + } + + @Override +- public void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { + super.spawnAfterBreak(state, level, pos, stack, dropExperience); +- if (dropExperience && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack) == 0) { +- int i = 1 + level.random.nextInt(5); +- this.popExperience(level, pos, i); ++ // CraftBukkit start - Delegated to getExpDrop ++ } ++ ++ @Override ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { ++ if (flag && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, itemstack) == 0) { ++ int i = 1 + worldserver.random.nextInt(5); ++ ++ // this.popExperience(worldserver, blockposition, i); ++ return i; + } ++ ++ return 0; ++ // CraftBukkit end + } + + @Override +- public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { +- if (state.getValue(LIT)) { ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(RedStoneOreBlock.LIT)) { + spawnParticles(level, pos); + } ++ + } + + private static void spawnParticles(Level level, BlockPos pos) { +- double d = 0.5625; +- RandomSource randomSource = level.random; ++ double d0 = 0.5625D; ++ RandomSource randomsource = level.random; ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; + +- for (Direction direction : Direction.values()) { +- BlockPos blockPos = pos.relative(direction); +- if (!level.getBlockState(blockPos).isSolidRender(level, blockPos)) { +- Direction.Axis axis = direction.getAxis(); +- double d1 = axis == Direction.Axis.X ? 0.5 + 0.5625 * (double)direction.getStepX() : (double)randomSource.nextFloat(); +- double d2 = axis == Direction.Axis.Y ? 0.5 + 0.5625 * (double)direction.getStepY() : (double)randomSource.nextFloat(); +- double d3 = axis == Direction.Axis.Z ? 0.5 + 0.5625 * (double)direction.getStepZ() : (double)randomSource.nextFloat(); +- level.addParticle(DustParticleOptions.REDSTONE, (double)pos.getX() + d1, (double)pos.getY() + d2, (double)pos.getZ() + d3, 0.0, 0.0, 0.0); ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ ++ if (!level.getBlockState(blockposition1).isSolidRender(level, blockposition1)) { ++ Direction.Axis enumdirection_enumaxis = enumdirection.getAxis(); ++ double d1 = enumdirection_enumaxis == Direction.Axis.X ? 0.5D + 0.5625D * (double) enumdirection.getStepX() : (double) randomsource.nextFloat(); ++ double d2 = enumdirection_enumaxis == Direction.Axis.Y ? 0.5D + 0.5625D * (double) enumdirection.getStepY() : (double) randomsource.nextFloat(); ++ double d3 = enumdirection_enumaxis == Direction.Axis.Z ? 0.5D + 0.5625D * (double) enumdirection.getStepZ() : (double) randomsource.nextFloat(); ++ ++ level.addParticle(ParticleParamRedstone.REDSTONE, (double) pos.getX() + d1, (double) pos.getY() + d2, (double) pos.getZ() + d3, 0.0D, 0.0D, 0.0D); + } + } ++ + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(LIT); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(RedStoneOreBlock.LIT); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/RedStoneWireBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/RedStoneWireBlock.java.patch new file mode 100644 index 0000000000..0c0803fda6 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/RedStoneWireBlock.java.patch @@ -0,0 +1,823 @@ +--- a/net/minecraft/world/level/block/RedStoneWireBlock.java ++++ b/net/minecraft/world/level/block/RedStoneWireBlock.java +@@ -3,17 +3,19 @@ + import com.google.common.collect.ImmutableMap; + import com.google.common.collect.Maps; + import com.google.common.collect.Sets; ++import com.google.common.collect.UnmodifiableIterator; + import com.mojang.serialization.MapCodec; ++import java.util.Iterator; + import java.util.Map; + import java.util.Set; + import javax.annotation.Nullable; + import net.minecraft.Util; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.particles.DustParticleOptions; ++import net.minecraft.core.particles.ParticleParamRedstone; + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.context.BlockPlaceContext; +@@ -22,165 +24,147 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.EnumProperty; + import net.minecraft.world.level.block.state.properties.IntegerProperty; ++import net.minecraft.world.level.block.state.properties.Property; + import net.minecraft.world.level.block.state.properties.RedstoneSide; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class RedStoneWireBlock extends Block { ++ + public static final MapCodec CODEC = simpleCodec(RedStoneWireBlock::new); + public static final EnumProperty NORTH = BlockStateProperties.NORTH_REDSTONE; + public static final EnumProperty EAST = BlockStateProperties.EAST_REDSTONE; + public static final EnumProperty SOUTH = BlockStateProperties.SOUTH_REDSTONE; + public static final EnumProperty WEST = BlockStateProperties.WEST_REDSTONE; + public static final IntegerProperty POWER = BlockStateProperties.POWER; +- public static final Map> PROPERTY_BY_DIRECTION = Maps.newEnumMap( +- ImmutableMap.of(Direction.NORTH, NORTH, Direction.EAST, EAST, Direction.SOUTH, SOUTH, Direction.WEST, WEST) +- ); ++ public static final Map> PROPERTY_BY_DIRECTION = Maps.newEnumMap(ImmutableMap.of(Direction.NORTH, RedStoneWireBlock.NORTH, Direction.EAST, RedStoneWireBlock.EAST, Direction.SOUTH, RedStoneWireBlock.SOUTH, Direction.WEST, RedStoneWireBlock.WEST)); + protected static final int H = 1; + protected static final int W = 3; + protected static final int E = 13; + protected static final int N = 3; + protected static final int S = 13; +- private static final VoxelShape SHAPE_DOT = Block.box(3.0, 0.0, 3.0, 13.0, 1.0, 13.0); +- private static final Map SHAPES_FLOOR = Maps.newEnumMap( +- ImmutableMap.of( +- Direction.NORTH, +- Block.box(3.0, 0.0, 0.0, 13.0, 1.0, 13.0), +- Direction.SOUTH, +- Block.box(3.0, 0.0, 3.0, 13.0, 1.0, 16.0), +- Direction.EAST, +- Block.box(3.0, 0.0, 3.0, 16.0, 1.0, 13.0), +- Direction.WEST, +- Block.box(0.0, 0.0, 3.0, 13.0, 1.0, 13.0) +- ) +- ); +- private static final Map SHAPES_UP = Maps.newEnumMap( +- ImmutableMap.of( +- Direction.NORTH, +- Shapes.or(SHAPES_FLOOR.get(Direction.NORTH), Block.box(3.0, 0.0, 0.0, 13.0, 16.0, 1.0)), +- Direction.SOUTH, +- Shapes.or(SHAPES_FLOOR.get(Direction.SOUTH), Block.box(3.0, 0.0, 15.0, 13.0, 16.0, 16.0)), +- Direction.EAST, +- Shapes.or(SHAPES_FLOOR.get(Direction.EAST), Block.box(15.0, 0.0, 3.0, 16.0, 16.0, 13.0)), +- Direction.WEST, +- Shapes.or(SHAPES_FLOOR.get(Direction.WEST), Block.box(0.0, 0.0, 3.0, 1.0, 16.0, 13.0)) +- ) +- ); +- private static final Map SHAPES_CACHE = Maps.newHashMap(); +- private static final Vec3[] COLORS = Util.make(new Vec3[16], array -> { +- for (int i = 0; i <= 15; i++) { +- float f = (float)i / 15.0F; ++ private static final VoxelShape SHAPE_DOT = Block.box(3.0D, 0.0D, 3.0D, 13.0D, 1.0D, 13.0D); ++ private static final Map SHAPES_FLOOR = Maps.newEnumMap(ImmutableMap.of(Direction.NORTH, Block.box(3.0D, 0.0D, 0.0D, 13.0D, 1.0D, 13.0D), Direction.SOUTH, Block.box(3.0D, 0.0D, 3.0D, 13.0D, 1.0D, 16.0D), Direction.EAST, Block.box(3.0D, 0.0D, 3.0D, 16.0D, 1.0D, 13.0D), Direction.WEST, Block.box(0.0D, 0.0D, 3.0D, 13.0D, 1.0D, 13.0D))); ++ private static final Map SHAPES_UP = Maps.newEnumMap(ImmutableMap.of(Direction.NORTH, Shapes.or((VoxelShape) RedStoneWireBlock.SHAPES_FLOOR.get(Direction.NORTH), Block.box(3.0D, 0.0D, 0.0D, 13.0D, 16.0D, 1.0D)), Direction.SOUTH, Shapes.or((VoxelShape) RedStoneWireBlock.SHAPES_FLOOR.get(Direction.SOUTH), Block.box(3.0D, 0.0D, 15.0D, 13.0D, 16.0D, 16.0D)), Direction.EAST, Shapes.or((VoxelShape) RedStoneWireBlock.SHAPES_FLOOR.get(Direction.EAST), Block.box(15.0D, 0.0D, 3.0D, 16.0D, 16.0D, 13.0D)), Direction.WEST, Shapes.or((VoxelShape) RedStoneWireBlock.SHAPES_FLOOR.get(Direction.WEST), Block.box(0.0D, 0.0D, 3.0D, 1.0D, 16.0D, 13.0D)))); ++ private static final Map SHAPES_CACHE = Maps.newHashMap(); ++ private static final Vec3[] COLORS = (Vec3[]) Util.make(new Vec3[16], (avec3d) -> { ++ for (int i = 0; i <= 15; ++i) { ++ float f = (float) i / 15.0F; + float f1 = f * 0.6F + (f > 0.0F ? 0.4F : 0.3F); + float f2 = Mth.clamp(f * f * 0.7F - 0.5F, 0.0F, 1.0F); + float f3 = Mth.clamp(f * f * 0.6F - 0.7F, 0.0F, 1.0F); +- array[i] = new Vec3((double)f1, (double)f2, (double)f3); ++ ++ avec3d[i] = new Vec3((double) f1, (double) f2, (double) f3); + } ++ + }); + private static final float PARTICLE_DENSITY = 0.2F; +- private final BlockState crossState; ++ private final IBlockData crossState; + private boolean shouldSignal = true; + + @Override + public MapCodec codec() { +- return CODEC; ++ return RedStoneWireBlock.CODEC; + } + + public RedStoneWireBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState( +- this.stateDefinition +- .any() +- .setValue(NORTH, RedstoneSide.NONE) +- .setValue(EAST, RedstoneSide.NONE) +- .setValue(SOUTH, RedstoneSide.NONE) +- .setValue(WEST, RedstoneSide.NONE) +- .setValue(POWER, Integer.valueOf(0)) +- ); +- this.crossState = this.defaultBlockState() +- .setValue(NORTH, RedstoneSide.SIDE) +- .setValue(EAST, RedstoneSide.SIDE) +- .setValue(SOUTH, RedstoneSide.SIDE) +- .setValue(WEST, RedstoneSide.SIDE); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(RedStoneWireBlock.NORTH, RedstoneSide.NONE)).setValue(RedStoneWireBlock.EAST, RedstoneSide.NONE)).setValue(RedStoneWireBlock.SOUTH, RedstoneSide.NONE)).setValue(RedStoneWireBlock.WEST, RedstoneSide.NONE)).setValue(RedStoneWireBlock.POWER, 0)); ++ this.crossState = (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(RedStoneWireBlock.NORTH, RedstoneSide.SIDE)).setValue(RedStoneWireBlock.EAST, RedstoneSide.SIDE)).setValue(RedStoneWireBlock.SOUTH, RedstoneSide.SIDE)).setValue(RedStoneWireBlock.WEST, RedstoneSide.SIDE); ++ UnmodifiableIterator unmodifiableiterator = this.getStateDefinition().getPossibleStates().iterator(); + +- for (BlockState blockState : this.getStateDefinition().getPossibleStates()) { +- if (blockState.getValue(POWER) == 0) { +- SHAPES_CACHE.put(blockState, this.calculateShape(blockState)); ++ while (unmodifiableiterator.hasNext()) { ++ IBlockData iblockdata = (IBlockData) unmodifiableiterator.next(); ++ ++ if ((Integer) iblockdata.getValue(RedStoneWireBlock.POWER) == 0) { ++ RedStoneWireBlock.SHAPES_CACHE.put(iblockdata, this.calculateShape(iblockdata)); + } + } ++ + } + +- private VoxelShape calculateShape(BlockState state) { +- VoxelShape voxelShape = SHAPE_DOT; ++ private VoxelShape calculateShape(IBlockData state) { ++ VoxelShape voxelshape = RedStoneWireBlock.SHAPE_DOT; ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- RedstoneSide redstoneSide = state.getValue(PROPERTY_BY_DIRECTION.get(direction)); +- if (redstoneSide == RedstoneSide.SIDE) { +- voxelShape = Shapes.or(voxelShape, SHAPES_FLOOR.get(direction)); +- } else if (redstoneSide == RedstoneSide.UP) { +- voxelShape = Shapes.or(voxelShape, SHAPES_UP.get(direction)); ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ RedstoneSide blockpropertyredstoneside = (RedstoneSide) state.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(enumdirection)); ++ ++ if (blockpropertyredstoneside == RedstoneSide.SIDE) { ++ voxelshape = Shapes.or(voxelshape, (VoxelShape) RedStoneWireBlock.SHAPES_FLOOR.get(enumdirection)); ++ } else if (blockpropertyredstoneside == RedstoneSide.UP) { ++ voxelshape = Shapes.or(voxelshape, (VoxelShape) RedStoneWireBlock.SHAPES_UP.get(enumdirection)); + } + } + +- return voxelShape; ++ return voxelshape; + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPES_CACHE.get(state.setValue(POWER, Integer.valueOf(0))); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (VoxelShape) RedStoneWireBlock.SHAPES_CACHE.get(state.setValue(RedStoneWireBlock.POWER, 0)); + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { + return this.getConnectionState(context.getLevel(), this.crossState, context.getClickedPos()); + } + +- private BlockState getConnectionState(BlockGetter level, BlockState state, BlockPos pos) { +- boolean isDot = isDot(state); +- BlockState var11 = this.getMissingConnections(level, this.defaultBlockState().setValue(POWER, state.getValue(POWER)), pos); +- if (isDot && isDot(var11)) { +- return var11; ++ private IBlockData getConnectionState(BlockGetter level, IBlockData state, BlockPos pos) { ++ boolean flag = isDot(state); ++ ++ state = this.getMissingConnections(level, (IBlockData) this.defaultBlockState().setValue(RedStoneWireBlock.POWER, (Integer) state.getValue(RedStoneWireBlock.POWER)), pos); ++ if (flag && isDot(state)) { ++ return state; + } else { +- boolean isConnected = var11.getValue(NORTH).isConnected(); +- boolean isConnected1 = var11.getValue(SOUTH).isConnected(); +- boolean isConnected2 = var11.getValue(EAST).isConnected(); +- boolean isConnected3 = var11.getValue(WEST).isConnected(); +- boolean flag = !isConnected && !isConnected1; +- boolean flag1 = !isConnected2 && !isConnected3; +- if (!isConnected3 && flag) { +- var11 = var11.setValue(WEST, RedstoneSide.SIDE); ++ boolean flag1 = ((RedstoneSide) state.getValue(RedStoneWireBlock.NORTH)).isConnected(); ++ boolean flag2 = ((RedstoneSide) state.getValue(RedStoneWireBlock.SOUTH)).isConnected(); ++ boolean flag3 = ((RedstoneSide) state.getValue(RedStoneWireBlock.EAST)).isConnected(); ++ boolean flag4 = ((RedstoneSide) state.getValue(RedStoneWireBlock.WEST)).isConnected(); ++ boolean flag5 = !flag1 && !flag2; ++ boolean flag6 = !flag3 && !flag4; ++ ++ if (!flag4 && flag5) { ++ state = (IBlockData) state.setValue(RedStoneWireBlock.WEST, RedstoneSide.SIDE); + } + +- if (!isConnected2 && flag) { +- var11 = var11.setValue(EAST, RedstoneSide.SIDE); ++ if (!flag3 && flag5) { ++ state = (IBlockData) state.setValue(RedStoneWireBlock.EAST, RedstoneSide.SIDE); + } + +- if (!isConnected && flag1) { +- var11 = var11.setValue(NORTH, RedstoneSide.SIDE); ++ if (!flag1 && flag6) { ++ state = (IBlockData) state.setValue(RedStoneWireBlock.NORTH, RedstoneSide.SIDE); + } + +- if (!isConnected1 && flag1) { +- var11 = var11.setValue(SOUTH, RedstoneSide.SIDE); ++ if (!flag2 && flag6) { ++ state = (IBlockData) state.setValue(RedStoneWireBlock.SOUTH, RedstoneSide.SIDE); + } + +- return var11; ++ return state; + } + } + +- private BlockState getMissingConnections(BlockGetter level, BlockState state, BlockPos pos) { ++ private IBlockData getMissingConnections(BlockGetter level, IBlockData state, BlockPos pos) { + boolean flag = !level.getBlockState(pos.above()).isRedstoneConductor(level, pos); ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- if (!state.getValue(PROPERTY_BY_DIRECTION.get(direction)).isConnected()) { +- RedstoneSide connectingSide = this.getConnectingSide(level, pos, direction, flag); +- state = state.setValue(PROPERTY_BY_DIRECTION.get(direction), connectingSide); ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ ++ if (!((RedstoneSide) state.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(enumdirection))).isConnected()) { ++ RedstoneSide blockpropertyredstoneside = this.getConnectingSide(level, pos, enumdirection, flag); ++ ++ state = (IBlockData) state.setValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(enumdirection), blockpropertyredstoneside); + } + } + +@@ -188,57 +172,56 @@ + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { + if (facing == Direction.DOWN) { + return !this.canSurviveOn(level, facingPos, facingState) ? Blocks.AIR.defaultBlockState() : state; + } else if (facing == Direction.UP) { + return this.getConnectionState(level, state, currentPos); + } else { +- RedstoneSide connectingSide = this.getConnectingSide(level, currentPos, facing); +- return connectingSide.isConnected() == state.getValue(PROPERTY_BY_DIRECTION.get(facing)).isConnected() && !isCross(state) +- ? state.setValue(PROPERTY_BY_DIRECTION.get(facing), connectingSide) +- : this.getConnectionState( +- level, this.crossState.setValue(POWER, state.getValue(POWER)).setValue(PROPERTY_BY_DIRECTION.get(facing), connectingSide), currentPos +- ); ++ RedstoneSide blockpropertyredstoneside = this.getConnectingSide(level, currentPos, facing); ++ ++ return blockpropertyredstoneside.isConnected() == ((RedstoneSide) state.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(facing))).isConnected() && !isCross(state) ? (IBlockData) state.setValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(facing), blockpropertyredstoneside) : this.getConnectionState(level, (IBlockData) ((IBlockData) this.crossState.setValue(RedStoneWireBlock.POWER, (Integer) state.getValue(RedStoneWireBlock.POWER))).setValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(facing), blockpropertyredstoneside), currentPos); + } + } + +- private static boolean isCross(BlockState state) { +- return state.getValue(NORTH).isConnected() +- && state.getValue(SOUTH).isConnected() +- && state.getValue(EAST).isConnected() +- && state.getValue(WEST).isConnected(); ++ private static boolean isCross(IBlockData state) { ++ return ((RedstoneSide) state.getValue(RedStoneWireBlock.NORTH)).isConnected() && ((RedstoneSide) state.getValue(RedStoneWireBlock.SOUTH)).isConnected() && ((RedstoneSide) state.getValue(RedStoneWireBlock.EAST)).isConnected() && ((RedstoneSide) state.getValue(RedStoneWireBlock.WEST)).isConnected(); + } + +- private static boolean isDot(BlockState state) { +- return !state.getValue(NORTH).isConnected() +- && !state.getValue(SOUTH).isConnected() +- && !state.getValue(EAST).isConnected() +- && !state.getValue(WEST).isConnected(); ++ private static boolean isDot(IBlockData state) { ++ return !((RedstoneSide) state.getValue(RedStoneWireBlock.NORTH)).isConnected() && !((RedstoneSide) state.getValue(RedStoneWireBlock.SOUTH)).isConnected() && !((RedstoneSide) state.getValue(RedStoneWireBlock.EAST)).isConnected() && !((RedstoneSide) state.getValue(RedStoneWireBlock.WEST)).isConnected(); + } + + @Override +- public void updateIndirectNeighbourShapes(BlockState state, LevelAccessor level, BlockPos pos, int flags, int recursionLeft) { +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ public void updateIndirectNeighbourShapes(IBlockData state, LevelAccessor level, BlockPos pos, int flags, int recursionLeft) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- RedstoneSide redstoneSide = state.getValue(PROPERTY_BY_DIRECTION.get(direction)); +- if (redstoneSide != RedstoneSide.NONE && !level.getBlockState(mutableBlockPos.setWithOffset(pos, direction)).is(this)) { +- mutableBlockPos.move(Direction.DOWN); +- BlockState blockState = level.getBlockState(mutableBlockPos); +- if (blockState.is(this)) { +- BlockPos blockPos = mutableBlockPos.relative(direction.getOpposite()); +- level.neighborShapeChanged(direction.getOpposite(), level.getBlockState(blockPos), mutableBlockPos, blockPos, flags, recursionLeft); ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ RedstoneSide blockpropertyredstoneside = (RedstoneSide) state.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(enumdirection)); ++ ++ if (blockpropertyredstoneside != RedstoneSide.NONE && !level.getBlockState(blockposition_mutableblockposition.setWithOffset(pos, enumdirection)).is((Block) this)) { ++ blockposition_mutableblockposition.move(Direction.DOWN); ++ IBlockData iblockdata1 = level.getBlockState(blockposition_mutableblockposition); ++ ++ if (iblockdata1.is((Block) this)) { ++ BlockPos blockposition1 = blockposition_mutableblockposition.relative(enumdirection.getOpposite()); ++ ++ level.neighborShapeChanged(enumdirection.getOpposite(), level.getBlockState(blockposition1), blockposition_mutableblockposition, blockposition1, flags, recursionLeft); + } + +- mutableBlockPos.setWithOffset(pos, direction).move(Direction.UP); +- BlockState blockState1 = level.getBlockState(mutableBlockPos); +- if (blockState1.is(this)) { +- BlockPos blockPos1 = mutableBlockPos.relative(direction.getOpposite()); +- level.neighborShapeChanged(direction.getOpposite(), level.getBlockState(blockPos1), mutableBlockPos, blockPos1, flags, recursionLeft); ++ blockposition_mutableblockposition.setWithOffset(pos, enumdirection).move(Direction.UP); ++ IBlockData iblockdata2 = level.getBlockState(blockposition_mutableblockposition); ++ ++ if (iblockdata2.is((Block) this)) { ++ BlockPos blockposition2 = blockposition_mutableblockposition.relative(enumdirection.getOpposite()); ++ ++ level.neighborShapeChanged(enumdirection.getOpposite(), level.getBlockState(blockposition2), blockposition_mutableblockposition, blockposition2, flags, recursionLeft); + } + } + } ++ + } + + private RedstoneSide getConnectingSide(BlockGetter level, BlockPos pos, Direction face) { +@@ -246,12 +229,14 @@ + } + + private RedstoneSide getConnectingSide(BlockGetter level, BlockPos pos, Direction direction, boolean nonNormalCubeAbove) { +- BlockPos blockPos = pos.relative(direction); +- BlockState blockState = level.getBlockState(blockPos); ++ BlockPos blockposition1 = pos.relative(direction); ++ IBlockData iblockdata = level.getBlockState(blockposition1); ++ + if (nonNormalCubeAbove) { +- boolean flag = blockState.getBlock() instanceof TrapDoorBlock || this.canSurviveOn(level, blockPos, blockState); +- if (flag && shouldConnectTo(level.getBlockState(blockPos.above()))) { +- if (blockState.isFaceSturdy(level, blockPos, direction.getOpposite())) { ++ boolean flag1 = iblockdata.getBlock() instanceof TrapDoorBlock || this.canSurviveOn(level, blockposition1, iblockdata); ++ ++ if (flag1 && shouldConnectTo(level.getBlockState(blockposition1.above()))) { ++ if (iblockdata.isFaceSturdy(level, blockposition1, direction.getOpposite())) { + return RedstoneSide.UP; + } + +@@ -259,86 +244,119 @@ + } + } + +- return !shouldConnectTo(blockState, direction) +- && (blockState.isRedstoneConductor(level, blockPos) || !shouldConnectTo(level.getBlockState(blockPos.below()))) +- ? RedstoneSide.NONE +- : RedstoneSide.SIDE; ++ return !shouldConnectTo(iblockdata, direction) && (iblockdata.isRedstoneConductor(level, blockposition1) || !shouldConnectTo(level.getBlockState(blockposition1.below()))) ? RedstoneSide.NONE : RedstoneSide.SIDE; + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { +- BlockPos blockPos = pos.below(); +- BlockState blockState = level.getBlockState(blockPos); +- return this.canSurviveOn(level, blockPos, blockState); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ return this.canSurviveOn(level, blockposition1, iblockdata1); + } + +- private boolean canSurviveOn(BlockGetter level, BlockPos pos, BlockState state) { ++ private boolean canSurviveOn(BlockGetter level, BlockPos pos, IBlockData state) { + return state.isFaceSturdy(level, pos, Direction.UP) || state.is(Blocks.HOPPER); + } + +- private void updatePowerStrength(Level level, BlockPos pos, BlockState state) { ++ private void updatePowerStrength(Level level, BlockPos pos, IBlockData state) { + int i = this.calculateTargetStrength(level, pos); +- if (state.getValue(POWER) != i) { ++ ++ // CraftBukkit start ++ int oldPower = (Integer) state.getValue(RedStoneWireBlock.POWER); ++ if (oldPower != i) { ++ BlockRedstoneEvent event = new BlockRedstoneEvent(level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()), oldPower, i); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ i = event.getNewCurrent(); ++ } ++ if (oldPower != i) { ++ // CraftBukkit end + if (level.getBlockState(pos) == state) { +- level.setBlock(pos, state.setValue(POWER, Integer.valueOf(i)), 2); ++ level.setBlock(pos, (IBlockData) state.setValue(RedStoneWireBlock.POWER, i), 2); + } + + Set set = Sets.newHashSet(); ++ + set.add(pos); ++ Direction[] aenumdirection = Direction.values(); ++ int j = aenumdirection.length; + +- for (Direction direction : Direction.values()) { +- set.add(pos.relative(direction)); ++ for (int k = 0; k < j; ++k) { ++ Direction enumdirection = aenumdirection[k]; ++ ++ set.add(pos.relative(enumdirection)); + } + +- for (BlockPos blockPos : set) { +- level.updateNeighborsAt(blockPos, this); ++ Iterator iterator = set.iterator(); ++ ++ while (iterator.hasNext()) { ++ BlockPos blockposition1 = (BlockPos) iterator.next(); ++ ++ level.updateNeighborsAt(blockposition1, this); + } + } ++ + } + + private int calculateTargetStrength(Level level, BlockPos pos) { + this.shouldSignal = false; +- int bestNeighborSignal = level.getBestNeighborSignal(pos); ++ int i = level.getBestNeighborSignal(pos); ++ + this.shouldSignal = true; +- int i = 0; +- if (bestNeighborSignal < 15) { +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- BlockPos blockPos = pos.relative(direction); +- BlockState blockState = level.getBlockState(blockPos); +- i = Math.max(i, this.getWireSignal(blockState)); +- BlockPos blockPos1 = pos.above(); +- if (blockState.isRedstoneConductor(level, blockPos) && !level.getBlockState(blockPos1).isRedstoneConductor(level, blockPos1)) { +- i = Math.max(i, this.getWireSignal(level.getBlockState(blockPos.above()))); +- } else if (!blockState.isRedstoneConductor(level, blockPos)) { +- i = Math.max(i, this.getWireSignal(level.getBlockState(blockPos.below()))); ++ int j = 0; ++ ++ if (i < 15) { ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); ++ ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ IBlockData iblockdata = level.getBlockState(blockposition1); ++ ++ j = Math.max(j, this.getWireSignal(iblockdata)); ++ BlockPos blockposition2 = pos.above(); ++ ++ if (iblockdata.isRedstoneConductor(level, blockposition1) && !level.getBlockState(blockposition2).isRedstoneConductor(level, blockposition2)) { ++ j = Math.max(j, this.getWireSignal(level.getBlockState(blockposition1.above()))); ++ } else if (!iblockdata.isRedstoneConductor(level, blockposition1)) { ++ j = Math.max(j, this.getWireSignal(level.getBlockState(blockposition1.below()))); + } + } + } + +- return Math.max(bestNeighborSignal, i - 1); ++ return Math.max(i, j - 1); + } + +- private int getWireSignal(BlockState state) { +- return state.is(this) ? state.getValue(POWER) : 0; ++ private int getWireSignal(IBlockData state) { ++ return state.is((Block) this) ? (Integer) state.getValue(RedStoneWireBlock.POWER) : 0; + } + + private void checkCornerChangeAt(Level level, BlockPos pos) { +- if (level.getBlockState(pos).is(this)) { ++ if (level.getBlockState(pos).is((Block) this)) { + level.updateNeighborsAt(pos, this); ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; + +- for (Direction direction : Direction.values()) { +- level.updateNeighborsAt(pos.relative(direction), this); ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ ++ level.updateNeighborsAt(pos.relative(enumdirection), this); + } ++ + } + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { + if (!oldState.is(state.getBlock()) && !level.isClientSide) { + this.updatePowerStrength(level, pos, state); ++ Iterator iterator = Direction.Plane.VERTICAL.iterator(); + +- for (Direction direction : Direction.Plane.VERTICAL) { +- level.updateNeighborsAt(pos.relative(direction), this); ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ ++ level.updateNeighborsAt(pos.relative(enumdirection), this); + } + + this.updateNeighborsOfNeighboringWires(level, pos); +@@ -346,12 +364,17 @@ + } + + @Override +- public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { + if (!isMoving && !state.is(newState.getBlock())) { + super.onRemove(state, level, pos, newState, isMoving); + if (!level.isClientSide) { +- for (Direction direction : Direction.values()) { +- level.updateNeighborsAt(pos.relative(direction), this); ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; ++ ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ ++ level.updateNeighborsAt(pos.relative(enumdirection), this); + } + + this.updatePowerStrength(level, pos, state); +@@ -361,22 +384,32 @@ + } + + private void updateNeighborsOfNeighboringWires(Level level, BlockPos pos) { +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- this.checkCornerChangeAt(level, pos.relative(direction)); ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); ++ ++ Direction enumdirection; ++ ++ while (iterator.hasNext()) { ++ enumdirection = (Direction) iterator.next(); ++ this.checkCornerChangeAt(level, pos.relative(enumdirection)); + } + +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- BlockPos blockPos = pos.relative(direction); +- if (level.getBlockState(blockPos).isRedstoneConductor(level, blockPos)) { +- this.checkCornerChangeAt(level, blockPos.above()); ++ iterator = Direction.Plane.HORIZONTAL.iterator(); ++ ++ while (iterator.hasNext()) { ++ enumdirection = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ ++ if (level.getBlockState(blockposition1).isRedstoneConductor(level, blockposition1)) { ++ this.checkCornerChangeAt(level, blockposition1.above()); + } else { +- this.checkCornerChangeAt(level, blockPos.below()); ++ this.checkCornerChangeAt(level, blockposition1.below()); + } + } ++ + } + + @Override +- public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { + if (!level.isClientSide) { + if (state.canSurvive(level, pos)) { + this.updatePowerStrength(level, pos, state); +@@ -384,150 +417,137 @@ + dropResources(state, level, pos); + level.removeBlock(pos, false); + } ++ + } + } + + @Override +- public int getDirectSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ public int getDirectSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { + return !this.shouldSignal ? 0 : blockState.getSignal(blockAccess, pos, side); + } + + @Override +- public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { + if (this.shouldSignal && side != Direction.DOWN) { +- int i = blockState.getValue(POWER); +- if (i == 0) { +- return 0; +- } else { +- return side != Direction.UP +- && !this.getConnectionState(blockAccess, blockState, pos).getValue(PROPERTY_BY_DIRECTION.get(side.getOpposite())).isConnected() +- ? 0 +- : i; +- } ++ int i = (Integer) blockState.getValue(RedStoneWireBlock.POWER); ++ ++ return i == 0 ? 0 : (side != Direction.UP && !((RedstoneSide) this.getConnectionState(blockAccess, blockState, pos).getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(side.getOpposite()))).isConnected() ? 0 : i); + } else { + return 0; + } + } + +- protected static boolean shouldConnectTo(BlockState state) { +- return shouldConnectTo(state, null); ++ protected static boolean shouldConnectTo(IBlockData state) { ++ return shouldConnectTo(state, (Direction) null); + } + +- protected static boolean shouldConnectTo(BlockState state, @Nullable Direction direction) { ++ protected static boolean shouldConnectTo(IBlockData state, @Nullable Direction direction) { + if (state.is(Blocks.REDSTONE_WIRE)) { + return true; + } else if (state.is(Blocks.REPEATER)) { +- Direction direction1 = state.getValue(RepeaterBlock.FACING); +- return direction1 == direction || direction1.getOpposite() == direction; ++ Direction enumdirection1 = (Direction) state.getValue(RepeaterBlock.FACING); ++ ++ return enumdirection1 == direction || enumdirection1.getOpposite() == direction; + } else { + return state.is(Blocks.OBSERVER) ? direction == state.getValue(ObserverBlock.FACING) : state.isSignalSource() && direction != null; + } + } + + @Override +- public boolean isSignalSource(BlockState state) { ++ public boolean isSignalSource(IBlockData state) { + return this.shouldSignal; + } + + public static int getColorForPower(int power) { +- Vec3 vec3 = COLORS[power]; +- return Mth.color((float)vec3.x(), (float)vec3.y(), (float)vec3.z()); ++ Vec3 vec3d = RedStoneWireBlock.COLORS[power]; ++ ++ return Mth.color((float) vec3d.x(), (float) vec3d.y(), (float) vec3d.z()); + } + +- private void spawnParticlesAlongLine( +- Level level, RandomSource random, BlockPos pos, Vec3 particleVec, Direction xDirection, Direction zDirection, float min, float max +- ) { +- float f = max - min; +- if (!(random.nextFloat() >= 0.2F * f)) { +- float f1 = 0.4375F; +- float f2 = min + f * random.nextFloat(); +- double d = 0.5 + (double)(0.4375F * (float)xDirection.getStepX()) + (double)(f2 * (float)zDirection.getStepX()); +- double d1 = 0.5 + (double)(0.4375F * (float)xDirection.getStepY()) + (double)(f2 * (float)zDirection.getStepY()); +- double d2 = 0.5 + (double)(0.4375F * (float)xDirection.getStepZ()) + (double)(f2 * (float)zDirection.getStepZ()); +- level.addParticle( +- new DustParticleOptions(particleVec.toVector3f(), 1.0F), +- (double)pos.getX() + d, +- (double)pos.getY() + d1, +- (double)pos.getZ() + d2, +- 0.0, +- 0.0, +- 0.0 +- ); ++ private void spawnParticlesAlongLine(Level level, RandomSource random, BlockPos pos, Vec3 particleVec, Direction xDirection, Direction zDirection, float min, float max) { ++ float f2 = max - min; ++ ++ if (random.nextFloat() < 0.2F * f2) { ++ float f3 = 0.4375F; ++ float f4 = min + f2 * random.nextFloat(); ++ double d0 = 0.5D + (double) (0.4375F * (float) xDirection.getStepX()) + (double) (f4 * (float) zDirection.getStepX()); ++ double d1 = 0.5D + (double) (0.4375F * (float) xDirection.getStepY()) + (double) (f4 * (float) zDirection.getStepY()); ++ double d2 = 0.5D + (double) (0.4375F * (float) xDirection.getStepZ()) + (double) (f4 * (float) zDirection.getStepZ()); ++ ++ level.addParticle(new ParticleParamRedstone(particleVec.toVector3f(), 1.0F), (double) pos.getX() + d0, (double) pos.getY() + d1, (double) pos.getZ() + d2, 0.0D, 0.0D, 0.0D); + } + } + + @Override +- public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { +- int i = state.getValue(POWER); ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ int i = (Integer) state.getValue(RedStoneWireBlock.POWER); ++ + if (i != 0) { +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- RedstoneSide redstoneSide = state.getValue(PROPERTY_BY_DIRECTION.get(direction)); +- switch (redstoneSide) { ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); ++ ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ RedstoneSide blockpropertyredstoneside = (RedstoneSide) state.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(enumdirection)); ++ ++ switch (blockpropertyredstoneside) { + case UP: +- this.spawnParticlesAlongLine(level, random, pos, COLORS[i], direction, Direction.UP, -0.5F, 0.5F); ++ this.spawnParticlesAlongLine(level, random, pos, RedStoneWireBlock.COLORS[i], enumdirection, Direction.UP, -0.5F, 0.5F); + case SIDE: +- this.spawnParticlesAlongLine(level, random, pos, COLORS[i], Direction.DOWN, direction, 0.0F, 0.5F); ++ this.spawnParticlesAlongLine(level, random, pos, RedStoneWireBlock.COLORS[i], Direction.DOWN, enumdirection, 0.0F, 0.5F); + break; + case NONE: + default: +- this.spawnParticlesAlongLine(level, random, pos, COLORS[i], Direction.DOWN, direction, 0.0F, 0.3F); ++ this.spawnParticlesAlongLine(level, random, pos, RedStoneWireBlock.COLORS[i], Direction.DOWN, enumdirection, 0.0F, 0.3F); + } + } ++ + } + } + + @Override +- public BlockState rotate(BlockState state, Rotation rotation) { ++ public IBlockData rotate(IBlockData state, Rotation rotation) { + switch (rotation) { + case CLOCKWISE_180: +- return state.setValue(NORTH, state.getValue(SOUTH)) +- .setValue(EAST, state.getValue(WEST)) +- .setValue(SOUTH, state.getValue(NORTH)) +- .setValue(WEST, state.getValue(EAST)); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) state.setValue(RedStoneWireBlock.NORTH, (RedstoneSide) state.getValue(RedStoneWireBlock.SOUTH))).setValue(RedStoneWireBlock.EAST, (RedstoneSide) state.getValue(RedStoneWireBlock.WEST))).setValue(RedStoneWireBlock.SOUTH, (RedstoneSide) state.getValue(RedStoneWireBlock.NORTH))).setValue(RedStoneWireBlock.WEST, (RedstoneSide) state.getValue(RedStoneWireBlock.EAST)); + case COUNTERCLOCKWISE_90: +- return state.setValue(NORTH, state.getValue(EAST)) +- .setValue(EAST, state.getValue(SOUTH)) +- .setValue(SOUTH, state.getValue(WEST)) +- .setValue(WEST, state.getValue(NORTH)); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) state.setValue(RedStoneWireBlock.NORTH, (RedstoneSide) state.getValue(RedStoneWireBlock.EAST))).setValue(RedStoneWireBlock.EAST, (RedstoneSide) state.getValue(RedStoneWireBlock.SOUTH))).setValue(RedStoneWireBlock.SOUTH, (RedstoneSide) state.getValue(RedStoneWireBlock.WEST))).setValue(RedStoneWireBlock.WEST, (RedstoneSide) state.getValue(RedStoneWireBlock.NORTH)); + case CLOCKWISE_90: +- return state.setValue(NORTH, state.getValue(WEST)) +- .setValue(EAST, state.getValue(NORTH)) +- .setValue(SOUTH, state.getValue(EAST)) +- .setValue(WEST, state.getValue(SOUTH)); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) state.setValue(RedStoneWireBlock.NORTH, (RedstoneSide) state.getValue(RedStoneWireBlock.WEST))).setValue(RedStoneWireBlock.EAST, (RedstoneSide) state.getValue(RedStoneWireBlock.NORTH))).setValue(RedStoneWireBlock.SOUTH, (RedstoneSide) state.getValue(RedStoneWireBlock.EAST))).setValue(RedStoneWireBlock.WEST, (RedstoneSide) state.getValue(RedStoneWireBlock.SOUTH)); + default: + return state; + } + } + + @Override +- public BlockState mirror(BlockState state, Mirror mirror) { ++ public IBlockData mirror(IBlockData state, Mirror mirror) { + switch (mirror) { + case LEFT_RIGHT: +- return state.setValue(NORTH, state.getValue(SOUTH)).setValue(SOUTH, state.getValue(NORTH)); ++ return (IBlockData) ((IBlockData) state.setValue(RedStoneWireBlock.NORTH, (RedstoneSide) state.getValue(RedStoneWireBlock.SOUTH))).setValue(RedStoneWireBlock.SOUTH, (RedstoneSide) state.getValue(RedStoneWireBlock.NORTH)); + case FRONT_BACK: +- return state.setValue(EAST, state.getValue(WEST)).setValue(WEST, state.getValue(EAST)); ++ return (IBlockData) ((IBlockData) state.setValue(RedStoneWireBlock.EAST, (RedstoneSide) state.getValue(RedStoneWireBlock.WEST))).setValue(RedStoneWireBlock.WEST, (RedstoneSide) state.getValue(RedStoneWireBlock.EAST)); + default: + return super.mirror(state, mirror); + } + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(NORTH, EAST, SOUTH, WEST, POWER); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(RedStoneWireBlock.NORTH, RedStoneWireBlock.EAST, RedStoneWireBlock.SOUTH, RedStoneWireBlock.WEST, RedStoneWireBlock.POWER); + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + if (!player.getAbilities().mayBuild) { + return InteractionResult.PASS; + } else { + if (isCross(state) || isDot(state)) { +- BlockState blockState = isCross(state) ? this.defaultBlockState() : this.crossState; +- blockState = blockState.setValue(POWER, state.getValue(POWER)); +- BlockState var9 = this.getConnectionState(level, blockState, pos); +- if (var9 != state) { +- level.setBlock(pos, var9, 3); +- this.updatesOnShapeChange(level, pos, state, var9); ++ IBlockData iblockdata1 = isCross(state) ? this.defaultBlockState() : this.crossState; ++ ++ iblockdata1 = (IBlockData) iblockdata1.setValue(RedStoneWireBlock.POWER, (Integer) state.getValue(RedStoneWireBlock.POWER)); ++ iblockdata1 = this.getConnectionState(level, iblockdata1, pos); ++ if (iblockdata1 != state) { ++ level.setBlock(pos, iblockdata1, 3); ++ this.updatesOnShapeChange(level, pos, state, iblockdata1); + return InteractionResult.SUCCESS; + } + } +@@ -536,13 +556,17 @@ + } + } + +- private void updatesOnShapeChange(Level level, BlockPos pos, BlockState oldState, BlockState newState) { +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- BlockPos blockPos = pos.relative(direction); +- if (oldState.getValue(PROPERTY_BY_DIRECTION.get(direction)).isConnected() != newState.getValue(PROPERTY_BY_DIRECTION.get(direction)).isConnected() +- && level.getBlockState(blockPos).isRedstoneConductor(level, blockPos)) { +- level.updateNeighborsAtExceptFromFacing(blockPos, newState.getBlock(), direction.getOpposite()); ++ private void updatesOnShapeChange(Level level, BlockPos pos, IBlockData oldState, IBlockData newState) { ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); ++ ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ ++ if (((RedstoneSide) oldState.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(enumdirection))).isConnected() != ((RedstoneSide) newState.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(enumdirection))).isConnected() && level.getBlockState(blockposition1).isRedstoneConductor(level, blockposition1)) { ++ level.updateNeighborsAtExceptFromFacing(blockposition1, newState.getBlock(), enumdirection.getOpposite()); + } + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/RedstoneLampBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/RedstoneLampBlock.java.patch new file mode 100644 index 0000000000..65c155795e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/RedstoneLampBlock.java.patch @@ -0,0 +1,87 @@ +--- a/net/minecraft/world/level/block/RedstoneLampBlock.java ++++ b/net/minecraft/world/level/block/RedstoneLampBlock.java +@@ -8,53 +8,68 @@ + import net.minecraft.world.item.context.BlockPlaceContext; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BooleanProperty; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class RedstoneLampBlock extends Block { ++ + public static final MapCodec CODEC = simpleCodec(RedstoneLampBlock::new); + public static final BooleanProperty LIT = RedstoneTorchBlock.LIT; + + @Override + public MapCodec codec() { +- return CODEC; ++ return RedstoneLampBlock.CODEC; + } + + public RedstoneLampBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.defaultBlockState().setValue(LIT, Boolean.valueOf(false))); ++ this.registerDefaultState((IBlockData) this.defaultBlockState().setValue(RedstoneLampBlock.LIT, false)); + } + + @Nullable + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- return this.defaultBlockState().setValue(LIT, Boolean.valueOf(context.getLevel().hasNeighborSignal(context.getClickedPos()))); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return (IBlockData) this.defaultBlockState().setValue(RedstoneLampBlock.LIT, context.getLevel().hasNeighborSignal(context.getClickedPos())); + } + + @Override +- public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { + if (!level.isClientSide) { +- boolean flag = state.getValue(LIT); +- if (flag != level.hasNeighborSignal(pos)) { +- if (flag) { +- level.scheduleTick(pos, this, 4); ++ boolean flag1 = (Boolean) state.getValue(RedstoneLampBlock.LIT); ++ ++ if (flag1 != level.hasNeighborSignal(pos)) { ++ if (flag1) { ++ level.scheduleTick(pos, (Block) this, 4); + } else { +- level.setBlock(pos, state.cycle(LIT), 2); ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 0, 15).getNewCurrent() != 15) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.cycle(RedstoneLampBlock.LIT), 2); + } + } ++ + } + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- if (state.getValue(LIT) && !level.hasNeighborSignal(pos)) { +- level.setBlock(pos, state.cycle(LIT), 2); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(RedstoneLampBlock.LIT) && !level.hasNeighborSignal(pos)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(level, pos, 15, 0).getNewCurrent() != 0) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.cycle(RedstoneLampBlock.LIT), 2); + } ++ + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(LIT); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(RedstoneLampBlock.LIT); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/RedstoneTorchBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/RedstoneTorchBlock.java.patch new file mode 100644 index 0000000000..af3cb1122c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/RedstoneTorchBlock.java.patch @@ -0,0 +1,232 @@ +--- a/net/minecraft/world/level/block/RedstoneTorchBlock.java ++++ b/net/minecraft/world/level/block/RedstoneTorchBlock.java +@@ -2,26 +2,29 @@ + + import com.google.common.collect.Lists; + import com.mojang.serialization.MapCodec; ++import java.util.Iterator; + import java.util.List; + import java.util.Map; + import java.util.WeakHashMap; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.particles.DustParticleOptions; ++import net.minecraft.core.particles.ParticleParamRedstone; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.RandomSource; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class RedstoneTorchBlock extends BaseTorchBlock { ++ + public static final MapCodec CODEC = simpleCodec(RedstoneTorchBlock::new); + public static final BooleanProperty LIT = BlockStateProperties.LIT; +- private static final Map> RECENT_TOGGLES = new WeakHashMap<>(); ++ private static final Map> RECENT_TOGGLES = new WeakHashMap(); + public static final int RECENT_TOGGLE_TIMER = 60; + public static final int MAX_RECENT_TOGGLES = 8; + public static final int RESTART_DELAY = 160; +@@ -29,104 +32,151 @@ + + @Override + public MapCodec codec() { +- return CODEC; ++ return RedstoneTorchBlock.CODEC; + } + + protected RedstoneTorchBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(LIT, Boolean.valueOf(true))); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(RedstoneTorchBlock.LIT, true)); + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { +- for (Direction direction : Direction.values()) { +- level.updateNeighborsAt(pos.relative(direction), this); ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; ++ ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ ++ level.updateNeighborsAt(pos.relative(enumdirection), this); + } ++ + } + + @Override +- public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { + if (!isMoving) { +- for (Direction direction : Direction.values()) { +- level.updateNeighborsAt(pos.relative(direction), this); ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; ++ ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ ++ level.updateNeighborsAt(pos.relative(enumdirection), this); + } ++ + } + } + + @Override +- public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { +- return blockState.getValue(LIT) && Direction.UP != side ? 15 : 0; ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return (Boolean) blockState.getValue(RedstoneTorchBlock.LIT) && Direction.UP != side ? 15 : 0; + } + +- protected boolean hasNeighborSignal(Level level, BlockPos pos, BlockState state) { ++ protected boolean hasNeighborSignal(Level level, BlockPos pos, IBlockData state) { + return level.hasSignal(pos.below(), Direction.DOWN); + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- boolean hasNeighborSignal = this.hasNeighborSignal(level, pos, state); +- List list = RECENT_TOGGLES.get(level); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ boolean flag = this.hasNeighborSignal(level, pos, state); ++ List list = (List) RedstoneTorchBlock.RECENT_TOGGLES.get(level); + +- while (list != null && !list.isEmpty() && level.getGameTime() - list.get(0).when > 60L) { ++ while (list != null && !list.isEmpty() && level.getGameTime() - ((RedstoneTorchBlock.Toggle) list.get(0)).when > 60L) { + list.remove(0); + } + +- if (state.getValue(LIT)) { +- if (hasNeighborSignal) { +- level.setBlock(pos, state.setValue(LIT, Boolean.valueOf(false)), 3); ++ // CraftBukkit start ++ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager(); ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ int oldCurrent = ((Boolean) state.getValue(RedstoneTorchBlock.LIT)).booleanValue() ? 15 : 0; ++ ++ BlockRedstoneEvent event = new BlockRedstoneEvent(block, oldCurrent, oldCurrent); ++ // CraftBukkit end ++ if ((Boolean) state.getValue(RedstoneTorchBlock.LIT)) { ++ if (flag) { ++ // CraftBukkit start ++ if (oldCurrent != 0) { ++ event.setNewCurrent(0); ++ manager.callEvent(event); ++ if (event.getNewCurrent() != 0) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(RedstoneTorchBlock.LIT, false), 3); + if (isToggledTooFrequently(level, pos, true)) { + level.levelEvent(1502, pos, 0); + level.scheduleTick(pos, level.getBlockState(pos).getBlock(), 160); + } + } +- } else if (!hasNeighborSignal && !isToggledTooFrequently(level, pos, false)) { +- level.setBlock(pos, state.setValue(LIT, Boolean.valueOf(true)), 3); ++ } else if (!flag && !isToggledTooFrequently(level, pos, false)) { ++ // CraftBukkit start ++ if (oldCurrent != 15) { ++ event.setNewCurrent(15); ++ manager.callEvent(event); ++ if (event.getNewCurrent() != 15) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) state.setValue(RedstoneTorchBlock.LIT, true), 3); + } ++ + } + + @Override +- public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { +- if (state.getValue(LIT) == this.hasNeighborSignal(level, pos, state) && !level.getBlockTicks().willTickThisTick(pos, this)) { +- level.scheduleTick(pos, this, 2); ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ if ((Boolean) state.getValue(RedstoneTorchBlock.LIT) == this.hasNeighborSignal(level, pos, state) && !level.getBlockTicks().willTickThisTick(pos, this)) { ++ level.scheduleTick(pos, (Block) this, 2); + } ++ + } + + @Override +- public int getDirectSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ public int getDirectSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { + return side == Direction.DOWN ? blockState.getSignal(blockAccess, pos, side) : 0; + } + + @Override +- public boolean isSignalSource(BlockState state) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + + @Override +- public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { +- if (state.getValue(LIT)) { +- double d = (double)pos.getX() + 0.5 + (random.nextDouble() - 0.5) * 0.2; +- double d1 = (double)pos.getY() + 0.7 + (random.nextDouble() - 0.5) * 0.2; +- double d2 = (double)pos.getZ() + 0.5 + (random.nextDouble() - 0.5) * 0.2; +- level.addParticle(DustParticleOptions.REDSTONE, d, d1, d2, 0.0, 0.0, 0.0); ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(RedstoneTorchBlock.LIT)) { ++ double d0 = (double) pos.getX() + 0.5D + (random.nextDouble() - 0.5D) * 0.2D; ++ double d1 = (double) pos.getY() + 0.7D + (random.nextDouble() - 0.5D) * 0.2D; ++ double d2 = (double) pos.getZ() + 0.5D + (random.nextDouble() - 0.5D) * 0.2D; ++ ++ level.addParticle(ParticleParamRedstone.REDSTONE, d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(LIT); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(RedstoneTorchBlock.LIT); + } + + private static boolean isToggledTooFrequently(Level level, BlockPos pos, boolean logToggle) { +- List list = RECENT_TOGGLES.computeIfAbsent(level, toggles -> Lists.newArrayList()); ++ List list = (List) RedstoneTorchBlock.RECENT_TOGGLES.computeIfAbsent(level, (iblockaccess) -> { ++ return Lists.newArrayList(); ++ }); ++ + if (logToggle) { + list.add(new RedstoneTorchBlock.Toggle(pos.immutable(), level.getGameTime())); + } + + int i = 0; ++ Iterator iterator = list.iterator(); + +- for (RedstoneTorchBlock.Toggle toggle : list) { +- if (toggle.pos.equals(pos)) { +- if (++i >= 8) { ++ while (iterator.hasNext()) { ++ RedstoneTorchBlock.Toggle blockredstonetorch_redstoneupdateinfo = (RedstoneTorchBlock.Toggle) iterator.next(); ++ ++ if (blockredstonetorch_redstoneupdateinfo.pos.equals(pos)) { ++ ++i; ++ if (i >= 8) { + return true; + } + } +@@ -136,6 +186,7 @@ + } + + public static class Toggle { ++ + final BlockPos pos; + final long when; + diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/RespawnAnchorBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/RespawnAnchorBlock.java.patch new file mode 100644 index 0000000000..09739013ea --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/RespawnAnchorBlock.java.patch @@ -0,0 +1,315 @@ +--- a/net/minecraft/world/level/block/RespawnAnchorBlock.java ++++ b/net/minecraft/world/level/block/RespawnAnchorBlock.java +@@ -2,8 +2,11 @@ + + import com.google.common.collect.ImmutableList; + import com.google.common.collect.ImmutableList.Builder; ++import com.google.common.collect.UnmodifiableIterator; + import com.mojang.serialization.MapCodec; ++import java.util.Objects; + import java.util.Optional; ++import java.util.stream.Stream; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +@@ -15,7 +18,7 @@ + import net.minecraft.tags.FluidTags; + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +@@ -29,61 +32,49 @@ + import net.minecraft.world.level.ExplosionDamageCalculator; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.FluidState; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; + + public class RespawnAnchorBlock extends Block { ++ + public static final MapCodec CODEC = simpleCodec(RespawnAnchorBlock::new); + public static final int MIN_CHARGES = 0; + public static final int MAX_CHARGES = 4; + public static final IntegerProperty CHARGE = BlockStateProperties.RESPAWN_ANCHOR_CHARGES; +- private static final ImmutableList RESPAWN_HORIZONTAL_OFFSETS = ImmutableList.of( +- new Vec3i(0, 0, -1), +- new Vec3i(-1, 0, 0), +- new Vec3i(0, 0, 1), +- new Vec3i(1, 0, 0), +- new Vec3i(-1, 0, -1), +- new Vec3i(1, 0, -1), +- new Vec3i(-1, 0, 1), +- new Vec3i(1, 0, 1) +- ); +- private static final ImmutableList RESPAWN_OFFSETS = new Builder() +- .addAll(RESPAWN_HORIZONTAL_OFFSETS) +- .addAll(RESPAWN_HORIZONTAL_OFFSETS.stream().map(Vec3i::below).iterator()) +- .addAll(RESPAWN_HORIZONTAL_OFFSETS.stream().map(Vec3i::above).iterator()) +- .add(new Vec3i(0, 1, 0)) +- .build(); ++ private static final ImmutableList RESPAWN_HORIZONTAL_OFFSETS = ImmutableList.of(new Vec3i(0, 0, -1), new Vec3i(-1, 0, 0), new Vec3i(0, 0, 1), new Vec3i(1, 0, 0), new Vec3i(-1, 0, -1), new Vec3i(1, 0, -1), new Vec3i(-1, 0, 1), new Vec3i(1, 0, 1)); ++ private static final ImmutableList RESPAWN_OFFSETS = (new Builder()).addAll(RespawnAnchorBlock.RESPAWN_HORIZONTAL_OFFSETS).addAll(RespawnAnchorBlock.RESPAWN_HORIZONTAL_OFFSETS.stream().map(Vec3i::below).iterator()).addAll(RespawnAnchorBlock.RESPAWN_HORIZONTAL_OFFSETS.stream().map(Vec3i::above).iterator()).add(new Vec3i(0, 1, 0)).build(); + + @Override + public MapCodec codec() { +- return CODEC; ++ return RespawnAnchorBlock.CODEC; + } + + public RespawnAnchorBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(CHARGE, Integer.valueOf(0))); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(RespawnAnchorBlock.CHARGE, 0)); + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (hand == InteractionHand.MAIN_HAND && !isRespawnFuel(itemInHand) && isRespawnFuel(player.getItemInHand(InteractionHand.OFF_HAND))) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (hand == EnumHand.MAIN_HAND && !isRespawnFuel(itemstack) && isRespawnFuel(player.getItemInHand(EnumHand.OFF_HAND))) { + return InteractionResult.PASS; +- } else if (isRespawnFuel(itemInHand) && canBeCharged(state)) { ++ } else if (isRespawnFuel(itemstack) && canBeCharged(state)) { + charge(player, level, pos, state); + if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + + return InteractionResult.sidedSuccess(level.isClientSide); +- } else if (state.getValue(CHARGE) == 0) { ++ } else if ((Integer) state.getValue(RespawnAnchorBlock.CHARGE) == 0) { + return InteractionResult.PASS; + } else if (!canSetSpawn(level)) { + if (!level.isClientSide) { +@@ -93,19 +84,11 @@ + return InteractionResult.sidedSuccess(level.isClientSide); + } else { + if (!level.isClientSide) { +- ServerPlayer serverPlayer = (ServerPlayer)player; +- if (serverPlayer.getRespawnDimension() != level.dimension() || !pos.equals(serverPlayer.getRespawnPosition())) { +- serverPlayer.setRespawnPosition(level.dimension(), pos, 0.0F, false, true); +- level.playSound( +- null, +- (double)pos.getX() + 0.5, +- (double)pos.getY() + 0.5, +- (double)pos.getZ() + 0.5, +- SoundEvents.RESPAWN_ANCHOR_SET_SPAWN, +- SoundSource.BLOCKS, +- 1.0F, +- 1.0F +- ); ++ ServerPlayer entityplayer = (ServerPlayer) player; ++ ++ if (entityplayer.getRespawnDimension() != level.dimension() || !pos.equals(entityplayer.getRespawnPosition())) { ++ entityplayer.setRespawnPosition(level.dimension(), pos, 0.0F, false, true, org.bukkit.event.player.PlayerSpawnChangeEvent.Cause.RESPAWN_ANCHOR); // CraftBukkit ++ level.playSound((Player) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.RESPAWN_ANCHOR_SET_SPAWN, SoundSource.BLOCKS, 1.0F, 1.0F); + return InteractionResult.SUCCESS; + } + } +@@ -118,129 +101,125 @@ + return stack.is(Items.GLOWSTONE); + } + +- private static boolean canBeCharged(BlockState state) { +- return state.getValue(CHARGE) < 4; ++ private static boolean canBeCharged(IBlockData state) { ++ return (Integer) state.getValue(RespawnAnchorBlock.CHARGE) < 4; + } + + private static boolean isWaterThatWouldFlow(BlockPos pos, Level level) { +- FluidState fluidState = level.getFluidState(pos); +- if (!fluidState.is(FluidTags.WATER)) { ++ FluidState fluid = level.getFluidState(pos); ++ ++ if (!fluid.is(FluidTags.WATER)) { + return false; +- } else if (fluidState.isSource()) { ++ } else if (fluid.isSource()) { + return true; + } else { +- float f = (float)fluidState.getAmount(); ++ float f = (float) fluid.getAmount(); ++ + if (f < 2.0F) { + return false; + } else { +- FluidState fluidState1 = level.getFluidState(pos.below()); +- return !fluidState1.is(FluidTags.WATER); ++ FluidState fluid1 = level.getFluidState(pos.below()); ++ ++ return !fluid1.is(FluidTags.WATER); + } + } + } + +- private void explode(BlockState state, Level level, final BlockPos pos2) { ++ private void explode(IBlockData state, Level level, final BlockPos pos2) { + level.removeBlock(pos2, false); +- boolean flag = Direction.Plane.HORIZONTAL.stream().map(pos2::relative).anyMatch(pos -> isWaterThatWouldFlow(pos, level)); ++ Stream stream = Direction.Plane.HORIZONTAL.stream(); // CraftBukkit - decompile error ++ ++ Objects.requireNonNull(pos2); ++ boolean flag = stream.map(pos2::relative).anyMatch((blockposition1) -> { ++ return isWaterThatWouldFlow(blockposition1, level); ++ }); + final boolean flag1 = flag || level.getFluidState(pos2.above()).is(FluidTags.WATER); +- ExplosionDamageCalculator explosionDamageCalculator = new ExplosionDamageCalculator() { ++ ExplosionDamageCalculator explosiondamagecalculator = new ExplosionDamageCalculator() { + @Override +- public Optional getBlockExplosionResistance(Explosion explosion, BlockGetter reader, BlockPos pos, BlockState state1, FluidState fluid) { +- return pos.equals(pos2) && flag1 +- ? Optional.of(Blocks.WATER.getExplosionResistance()) +- : super.getBlockExplosionResistance(explosion, reader, pos, state1, fluid); ++ public Optional getBlockExplosionResistance(Explosion explosion, BlockGetter reader, BlockPos pos, IBlockData state, FluidState fluid) { ++ return pos.equals(pos2) && flag1 ? Optional.of(Blocks.WATER.getExplosionResistance()) : super.getBlockExplosionResistance(explosion, reader, pos, state, fluid); + } + }; +- Vec3 center = pos2.getCenter(); +- level.explode( +- null, level.damageSources().badRespawnPointExplosion(center), explosionDamageCalculator, center, 5.0F, true, Level.ExplosionInteraction.BLOCK +- ); ++ Vec3 vec3d = pos2.getCenter(); ++ ++ level.explode((Entity) null, level.damageSources().badRespawnPointExplosion(vec3d), explosiondamagecalculator, vec3d, 5.0F, true, Level.a.BLOCK); + } + + public static boolean canSetSpawn(Level level) { + return level.dimensionType().respawnAnchorWorks(); + } + +- public static void charge(@Nullable Entity entity, Level level, BlockPos pos, BlockState state) { +- BlockState blockState = state.setValue(CHARGE, Integer.valueOf(state.getValue(CHARGE) + 1)); +- level.setBlock(pos, blockState, 3); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, blockState)); +- level.playSound( +- null, +- (double)pos.getX() + 0.5, +- (double)pos.getY() + 0.5, +- (double)pos.getZ() + 0.5, +- SoundEvents.RESPAWN_ANCHOR_CHARGE, +- SoundSource.BLOCKS, +- 1.0F, +- 1.0F +- ); ++ public static void charge(@Nullable Entity entity, Level level, BlockPos pos, IBlockData state) { ++ IBlockData iblockdata1 = (IBlockData) state.setValue(RespawnAnchorBlock.CHARGE, (Integer) state.getValue(RespawnAnchorBlock.CHARGE) + 1); ++ ++ level.setBlock(pos, iblockdata1, 3); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, iblockdata1)); ++ level.playSound((Player) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.RESPAWN_ANCHOR_CHARGE, SoundSource.BLOCKS, 1.0F, 1.0F); + } + + @Override +- public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { +- if (state.getValue(CHARGE) != 0) { ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ if ((Integer) state.getValue(RespawnAnchorBlock.CHARGE) != 0) { + if (random.nextInt(100) == 0) { +- level.playSound( +- null, +- (double)pos.getX() + 0.5, +- (double)pos.getY() + 0.5, +- (double)pos.getZ() + 0.5, +- SoundEvents.RESPAWN_ANCHOR_AMBIENT, +- SoundSource.BLOCKS, +- 1.0F, +- 1.0F +- ); ++ level.playSound((Player) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.RESPAWN_ANCHOR_AMBIENT, SoundSource.BLOCKS, 1.0F, 1.0F); + } + +- double d = (double)pos.getX() + 0.5 + (0.5 - random.nextDouble()); +- double d1 = (double)pos.getY() + 1.0; +- double d2 = (double)pos.getZ() + 0.5 + (0.5 - random.nextDouble()); +- double d3 = (double)random.nextFloat() * 0.04; +- level.addParticle(ParticleTypes.REVERSE_PORTAL, d, d1, d2, 0.0, d3, 0.0); ++ double d0 = (double) pos.getX() + 0.5D + (0.5D - random.nextDouble()); ++ double d1 = (double) pos.getY() + 1.0D; ++ double d2 = (double) pos.getZ() + 0.5D + (0.5D - random.nextDouble()); ++ double d3 = (double) random.nextFloat() * 0.04D; ++ ++ level.addParticle(ParticleTypes.REVERSE_PORTAL, d0, d1, d2, 0.0D, d3, 0.0D); + } + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(CHARGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(RespawnAnchorBlock.CHARGE); + } + + @Override +- public boolean hasAnalogOutputSignal(BlockState state) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return true; + } + +- public static int getScaledChargeLevel(BlockState state, int scale) { +- return Mth.floor((float)(state.getValue(CHARGE) - 0) / 4.0F * (float)scale); ++ public static int getScaledChargeLevel(IBlockData state, int scale) { ++ return Mth.floor((float) ((Integer) state.getValue(RespawnAnchorBlock.CHARGE) - 0) / 4.0F * (float) scale); + } + + @Override +- public int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) { ++ public int getAnalogOutputSignal(IBlockData blockState, Level level, BlockPos pos) { + return getScaledChargeLevel(blockState, 15); + } + + public static Optional findStandUpPosition(EntityType entityType, CollisionGetter level, BlockPos pos) { + Optional optional = findStandUpPosition(entityType, level, pos, true); ++ + return optional.isPresent() ? optional : findStandUpPosition(entityType, level, pos, false); + } + + private static Optional findStandUpPosition(EntityType entityType, CollisionGetter level, BlockPos pos, boolean simulate) { +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ UnmodifiableIterator unmodifiableiterator = RespawnAnchorBlock.RESPAWN_OFFSETS.iterator(); + +- for (Vec3i vec3i : RESPAWN_OFFSETS) { +- mutableBlockPos.set(pos).move(vec3i); +- Vec3 vec3 = DismountHelper.findSafeDismountLocation(entityType, level, mutableBlockPos, simulate); +- if (vec3 != null) { +- return Optional.of(vec3); ++ Vec3 vec3d; ++ ++ do { ++ if (!unmodifiableiterator.hasNext()) { ++ return Optional.empty(); + } +- } + +- return Optional.empty(); ++ Vec3i baseblockposition = (Vec3i) unmodifiableiterator.next(); ++ ++ blockposition_mutableblockposition.set(pos).move(baseblockposition); ++ vec3d = DismountHelper.findSafeDismountLocation(entityType, level, blockposition_mutableblockposition, simulate); ++ } while (vec3d == null); ++ ++ return Optional.of(vec3d); + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/RootedDirtBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/RootedDirtBlock.java.patch new file mode 100644 index 0000000000..a08956bba9 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/RootedDirtBlock.java.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/world/level/block/RootedDirtBlock.java ++++ b/net/minecraft/world/level/block/RootedDirtBlock.java +@@ -7,14 +7,15 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public class RootedDirtBlock extends Block implements BonemealableBlock { ++ + public static final MapCodec CODEC = simpleCodec(RootedDirtBlock::new); + + @Override + public MapCodec codec() { +- return CODEC; ++ return RootedDirtBlock.CODEC; + } + + public RootedDirtBlock(BlockBehaviour.Properties properties) { +@@ -22,17 +23,17 @@ + } + + @Override +- public boolean isValidBonemealTarget(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { +- return levelReader.getBlockState(blockPos.below()).isAir(); ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ return iworldreader.getBlockState(blockposition.below()).isAir(); + } + + @Override +- public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, BlockState state) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return true; + } + + @Override +- public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) { +- level.setBlockAndUpdate(pos.below(), Blocks.HANGING_ROOTS.defaultBlockState()); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, pos.below(), Blocks.HANGING_ROOTS.defaultBlockState()); // CraftBukkit + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/SaplingBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SaplingBlock.java.patch new file mode 100644 index 0000000000..b1118b0207 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SaplingBlock.java.patch @@ -0,0 +1,146 @@ +--- a/net/minecraft/world/level/block/SaplingBlock.java ++++ b/net/minecraft/world/level/block/SaplingBlock.java +@@ -2,80 +2,116 @@ + + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import net.minecraft.core.BlockPos; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.RandomSource; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; +-import net.minecraft.world.level.block.grower.TreeGrower; ++import net.minecraft.world.level.block.grower.WorldGenTreeProvider; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.TreeType; ++import org.bukkit.block.BlockState; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.world.StructureGrowEvent; ++// CraftBukkit end + + public class SaplingBlock extends BushBlock implements BonemealableBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group(TreeGrower.CODEC.fieldOf("tree").forGetter(saplingBlock -> saplingBlock.treeGrower), propertiesCodec()) +- .apply(instance, SaplingBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(WorldGenTreeProvider.CODEC.fieldOf("tree").forGetter((blocksapling) -> { ++ return blocksapling.treeGrower; ++ }), propertiesCodec()).apply(instance, SaplingBlock::new); ++ }); + public static final IntegerProperty STAGE = BlockStateProperties.STAGE; + protected static final float AABB_OFFSET = 6.0F; +- protected static final VoxelShape SHAPE = Block.box(2.0, 0.0, 2.0, 14.0, 12.0, 14.0); +- protected final TreeGrower treeGrower; ++ protected static final VoxelShape SHAPE = Block.box(2.0D, 0.0D, 2.0D, 14.0D, 12.0D, 14.0D); ++ protected final WorldGenTreeProvider treeGrower; ++ public static TreeType treeType; // CraftBukkit + + @Override + public MapCodec codec() { +- return CODEC; ++ return SaplingBlock.CODEC; + } + +- protected SaplingBlock(TreeGrower treeGrower, BlockBehaviour.Properties properties) { +- super(properties); +- this.treeGrower = treeGrower; +- this.registerDefaultState(this.stateDefinition.any().setValue(STAGE, Integer.valueOf(0))); ++ protected SaplingBlock(WorldGenTreeProvider worldgentreeprovider, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info); ++ this.treeGrower = worldgentreeprovider; ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(SaplingBlock.STAGE, 0)); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPE; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return SaplingBlock.SHAPE; + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (level.getMaxLocalRawBrightness(pos.above()) >= 9 && random.nextInt(7) == 0) { + this.advanceTree(level, pos, state, random); + } ++ + } + +- public void advanceTree(ServerLevel level, BlockPos pos, BlockState state, RandomSource random) { +- if (state.getValue(STAGE) == 0) { +- level.setBlock(pos, state.cycle(STAGE), 4); ++ public void advanceTree(ServerLevel level, BlockPos pos, IBlockData state, RandomSource random) { ++ if ((Integer) state.getValue(SaplingBlock.STAGE) == 0) { ++ level.setBlock(pos, (IBlockData) state.cycle(SaplingBlock.STAGE), 4); + } else { +- this.treeGrower.growTree(level, level.getChunkSource().getGenerator(), pos, state, random); ++ // CraftBukkit start ++ if (level.captureTreeGeneration) { ++ this.treeGrower.growTree(level, level.getChunkSource().getGenerator(), pos, state, random); ++ } else { ++ level.captureTreeGeneration = true; ++ this.treeGrower.growTree(level, level.getChunkSource().getGenerator(), pos, state, random); ++ level.captureTreeGeneration = false; ++ if (level.capturedBlockStates.size() > 0) { ++ TreeType treeType = SaplingBlock.treeType; ++ SaplingBlock.treeType = null; ++ Location location = CraftLocation.toBukkit(pos, level.getWorld()); ++ java.util.List blocks = new java.util.ArrayList<>(level.capturedBlockStates.values()); ++ level.capturedBlockStates.clear(); ++ StructureGrowEvent event = null; ++ if (treeType != null) { ++ event = new StructureGrowEvent(location, treeType, false, null, blocks); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ } ++ if (event == null || !event.isCancelled()) { ++ for (BlockState blockstate : blocks) { ++ blockstate.update(true); ++ } ++ } ++ } ++ } ++ // CraftBukkit end + } ++ + } + + @Override +- public boolean isValidBonemealTarget(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { + return true; + } + + @Override +- public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, BlockState state) { +- return (double)level.random.nextFloat() < 0.45; ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { ++ return (double) level.random.nextFloat() < 0.45D; + } + + @Override +- public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) { ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { + this.advanceTree(level, pos, state, random); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(STAGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(SaplingBlock.STAGE); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/ScaffoldingBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/ScaffoldingBlock.java.patch new file mode 100644 index 0000000000..22652c83ec --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/ScaffoldingBlock.java.patch @@ -0,0 +1,249 @@ +--- a/net/minecraft/world/level/block/ScaffoldingBlock.java ++++ b/net/minecraft/world/level/block/ScaffoldingBlock.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.block; + + import com.mojang.serialization.MapCodec; ++import java.util.Iterator; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.server.level.ServerLevel; +@@ -12,11 +13,12 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.block.state.properties.IntegerProperty; ++import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.shapes.CollisionContext; +@@ -24,12 +26,13 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + + public class ScaffoldingBlock extends Block implements SimpleWaterloggedBlock { ++ + public static final MapCodec CODEC = simpleCodec(ScaffoldingBlock::new); + private static final int TICK_DELAY = 1; + private static final VoxelShape STABLE_SHAPE; + private static final VoxelShape UNSTABLE_SHAPE; +- private static final VoxelShape UNSTABLE_SHAPE_BOTTOM = Block.box(0.0, 0.0, 0.0, 16.0, 2.0, 16.0); +- private static final VoxelShape BELOW_BLOCK = Shapes.block().move(0.0, -1.0, 0.0); ++ private static final VoxelShape UNSTABLE_SHAPE_BOTTOM = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 2.0D, 16.0D); ++ private static final VoxelShape BELOW_BLOCK = Shapes.block().move(0.0D, -1.0D, 0.0D); + public static final int STABILITY_MAX_DISTANCE = 7; + public static final IntegerProperty DISTANCE = BlockStateProperties.STABILITY_DISTANCE; + public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; +@@ -37,127 +40,119 @@ + + @Override + public MapCodec codec() { +- return CODEC; ++ return ScaffoldingBlock.CODEC; + } + + protected ScaffoldingBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState( +- this.stateDefinition +- .any() +- .setValue(DISTANCE, Integer.valueOf(7)) +- .setValue(WATERLOGGED, Boolean.valueOf(false)) +- .setValue(BOTTOM, Boolean.valueOf(false)) +- ); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(ScaffoldingBlock.DISTANCE, 7)).setValue(ScaffoldingBlock.WATERLOGGED, false)).setValue(ScaffoldingBlock.BOTTOM, false)); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(DISTANCE, WATERLOGGED, BOTTOM); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(ScaffoldingBlock.DISTANCE, ScaffoldingBlock.WATERLOGGED, ScaffoldingBlock.BOTTOM); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- if (!context.isHoldingItem(state.getBlock().asItem())) { +- return state.getValue(BOTTOM) ? UNSTABLE_SHAPE : STABLE_SHAPE; +- } else { +- return Shapes.block(); +- } ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return !context.isHoldingItem(state.getBlock().asItem()) ? ((Boolean) state.getValue(ScaffoldingBlock.BOTTOM) ? ScaffoldingBlock.UNSTABLE_SHAPE : ScaffoldingBlock.STABLE_SHAPE) : Shapes.block(); + } + + @Override +- public VoxelShape getInteractionShape(BlockState state, BlockGetter level, BlockPos pos) { ++ public VoxelShape getInteractionShape(IBlockData state, BlockGetter level, BlockPos pos) { + return Shapes.block(); + } + + @Override +- public boolean canBeReplaced(BlockState state, BlockPlaceContext useContext) { ++ public boolean canBeReplaced(IBlockData state, BlockPlaceContext useContext) { + return useContext.getItemInHand().is(this.asItem()); + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- BlockPos clickedPos = context.getClickedPos(); +- Level level = context.getLevel(); +- int distance = getDistance(level, clickedPos); +- return this.defaultBlockState() +- .setValue(WATERLOGGED, Boolean.valueOf(level.getFluidState(clickedPos).getType() == Fluids.WATER)) +- .setValue(DISTANCE, Integer.valueOf(distance)) +- .setValue(BOTTOM, Boolean.valueOf(this.isBottom(level, clickedPos, distance))); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ BlockPos blockposition = context.getClickedPos(); ++ Level world = context.getLevel(); ++ int i = getDistance(world, blockposition); ++ ++ return (IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(ScaffoldingBlock.WATERLOGGED, world.getFluidState(blockposition).getType() == Fluids.WATER)).setValue(ScaffoldingBlock.DISTANCE, i)).setValue(ScaffoldingBlock.BOTTOM, this.isBottom(world, blockposition, i)); + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { + if (!level.isClientSide) { +- level.scheduleTick(pos, this, 1); ++ level.scheduleTick(pos, (Block) this, 1); + } ++ + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- if (state.getValue(WATERLOGGED)) { +- level.scheduleTick(currentPos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if ((Boolean) state.getValue(ScaffoldingBlock.WATERLOGGED)) { ++ level.scheduleTick(currentPos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + + if (!level.isClientSide()) { +- level.scheduleTick(currentPos, this, 1); ++ level.scheduleTick(currentPos, (Block) this, 1); + } + + return state; + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- int distance = getDistance(level, pos); +- BlockState blockState = state.setValue(DISTANCE, Integer.valueOf(distance)).setValue(BOTTOM, Boolean.valueOf(this.isBottom(level, pos, distance))); +- if (blockState.getValue(DISTANCE) == 7) { +- if (state.getValue(DISTANCE) == 7) { +- FallingBlockEntity.fall(level, pos, blockState); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ int i = getDistance(level, pos); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) state.setValue(ScaffoldingBlock.DISTANCE, i)).setValue(ScaffoldingBlock.BOTTOM, this.isBottom(level, pos, i)); ++ ++ if ((Integer) iblockdata1.getValue(ScaffoldingBlock.DISTANCE) == 7 && !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.AIR.defaultBlockState()).isCancelled()) { // CraftBukkit - BlockFadeEvent ++ if ((Integer) state.getValue(ScaffoldingBlock.DISTANCE) == 7) { ++ FallingBlockEntity.fall(level, pos, iblockdata1); + } else { + level.destroyBlock(pos, true); + } +- } else if (state != blockState) { +- level.setBlock(pos, blockState, 3); ++ } else if (state != iblockdata1) { ++ level.setBlock(pos, iblockdata1, 3); + } ++ + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { + return getDistance(level, pos) < 7; + } + + @Override +- public VoxelShape getCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- if (context.isAbove(Shapes.block(), pos, true) && !context.isDescending()) { +- return STABLE_SHAPE; +- } else { +- return state.getValue(DISTANCE) != 0 && state.getValue(BOTTOM) && context.isAbove(BELOW_BLOCK, pos, true) ? UNSTABLE_SHAPE_BOTTOM : Shapes.empty(); +- } ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return context.isAbove(Shapes.block(), pos, true) && !context.isDescending() ? ScaffoldingBlock.STABLE_SHAPE : ((Integer) state.getValue(ScaffoldingBlock.DISTANCE) != 0 && (Boolean) state.getValue(ScaffoldingBlock.BOTTOM) && context.isAbove(ScaffoldingBlock.BELOW_BLOCK, pos, true) ? ScaffoldingBlock.UNSTABLE_SHAPE_BOTTOM : Shapes.empty()); + } + + @Override +- public FluidState getFluidState(BlockState state) { +- return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(ScaffoldingBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + private boolean isBottom(BlockGetter level, BlockPos pos, int distance) { +- return distance > 0 && !level.getBlockState(pos.below()).is(this); ++ return distance > 0 && !level.getBlockState(pos.below()).is((Block) this); + } + + public static int getDistance(BlockGetter level, BlockPos pos) { +- BlockPos.MutableBlockPos mutableBlockPos = pos.mutable().move(Direction.DOWN); +- BlockState blockState = level.getBlockState(mutableBlockPos); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable().move(Direction.DOWN); ++ IBlockData iblockdata = level.getBlockState(blockposition_mutableblockposition); + int i = 7; +- if (blockState.is(Blocks.SCAFFOLDING)) { +- i = blockState.getValue(DISTANCE); +- } else if (blockState.isFaceSturdy(level, mutableBlockPos, Direction.UP)) { ++ ++ if (iblockdata.is(Blocks.SCAFFOLDING)) { ++ i = (Integer) iblockdata.getValue(ScaffoldingBlock.DISTANCE); ++ } else if (iblockdata.isFaceSturdy(level, blockposition_mutableblockposition, Direction.UP)) { + return 0; + } + +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- BlockState blockState1 = level.getBlockState(mutableBlockPos.setWithOffset(pos, direction)); +- if (blockState1.is(Blocks.SCAFFOLDING)) { +- i = Math.min(i, blockState1.getValue(DISTANCE) + 1); ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); ++ ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition_mutableblockposition.setWithOffset(pos, enumdirection)); ++ ++ if (iblockdata1.is(Blocks.SCAFFOLDING)) { ++ i = Math.min(i, (Integer) iblockdata1.getValue(ScaffoldingBlock.DISTANCE) + 1); + if (i == 1) { + break; + } +@@ -168,16 +163,18 @@ + } + + static { +- VoxelShape voxelShape = Block.box(0.0, 14.0, 0.0, 16.0, 16.0, 16.0); +- VoxelShape voxelShape1 = Block.box(0.0, 0.0, 0.0, 2.0, 16.0, 2.0); +- VoxelShape voxelShape2 = Block.box(14.0, 0.0, 0.0, 16.0, 16.0, 2.0); +- VoxelShape voxelShape3 = Block.box(0.0, 0.0, 14.0, 2.0, 16.0, 16.0); +- VoxelShape voxelShape4 = Block.box(14.0, 0.0, 14.0, 16.0, 16.0, 16.0); +- STABLE_SHAPE = Shapes.or(voxelShape, voxelShape1, voxelShape2, voxelShape3, voxelShape4); +- VoxelShape voxelShape5 = Block.box(0.0, 0.0, 0.0, 2.0, 2.0, 16.0); +- VoxelShape voxelShape6 = Block.box(14.0, 0.0, 0.0, 16.0, 2.0, 16.0); +- VoxelShape voxelShape7 = Block.box(0.0, 0.0, 14.0, 16.0, 2.0, 16.0); +- VoxelShape voxelShape8 = Block.box(0.0, 0.0, 0.0, 16.0, 2.0, 2.0); +- UNSTABLE_SHAPE = Shapes.or(ScaffoldingBlock.UNSTABLE_SHAPE_BOTTOM, STABLE_SHAPE, voxelShape6, voxelShape5, voxelShape8, voxelShape7); ++ VoxelShape voxelshape = Block.box(0.0D, 14.0D, 0.0D, 16.0D, 16.0D, 16.0D); ++ VoxelShape voxelshape1 = Block.box(0.0D, 0.0D, 0.0D, 2.0D, 16.0D, 2.0D); ++ VoxelShape voxelshape2 = Block.box(14.0D, 0.0D, 0.0D, 16.0D, 16.0D, 2.0D); ++ VoxelShape voxelshape3 = Block.box(0.0D, 0.0D, 14.0D, 2.0D, 16.0D, 16.0D); ++ VoxelShape voxelshape4 = Block.box(14.0D, 0.0D, 14.0D, 16.0D, 16.0D, 16.0D); ++ ++ STABLE_SHAPE = Shapes.or(voxelshape, voxelshape1, voxelshape2, voxelshape3, voxelshape4); ++ VoxelShape voxelshape5 = Block.box(0.0D, 0.0D, 0.0D, 2.0D, 2.0D, 16.0D); ++ VoxelShape voxelshape6 = Block.box(14.0D, 0.0D, 0.0D, 16.0D, 2.0D, 16.0D); ++ VoxelShape voxelshape7 = Block.box(0.0D, 0.0D, 14.0D, 16.0D, 2.0D, 16.0D); ++ VoxelShape voxelshape8 = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 2.0D, 2.0D); ++ ++ UNSTABLE_SHAPE = Shapes.or(ScaffoldingBlock.UNSTABLE_SHAPE_BOTTOM, ScaffoldingBlock.STABLE_SHAPE, voxelshape6, voxelshape5, voxelshape8, voxelshape7); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/SculkBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SculkBlock.java.patch new file mode 100644 index 0000000000..c9f215fc2e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SculkBlock.java.patch @@ -0,0 +1,152 @@ +--- a/net/minecraft/world/level/block/SculkBlock.java ++++ b/net/minecraft/world/level/block/SculkBlock.java +@@ -1,23 +1,27 @@ + package net.minecraft.world.level.block; + + import com.mojang.serialization.MapCodec; ++import java.util.Iterator; + import net.minecraft.core.BlockPos; + import net.minecraft.sounds.SoundSource; + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.util.valueproviders.ConstantInt; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; ++import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; + + public class SculkBlock extends DropExperienceBlock implements SculkBehaviour { ++ + public static final MapCodec CODEC = simpleCodec(SculkBlock::new); + + @Override + public MapCodec codec() { +- return CODEC; ++ return SculkBlock.CODEC; + } + + public SculkBlock(BlockBehaviour.Properties properties) { +@@ -25,70 +29,79 @@ + } + + @Override +- public int attemptUseCharge( +- SculkSpreader.ChargeCursor cursor, LevelAccessor level, BlockPos pos, RandomSource random, SculkSpreader spreader, boolean shouldConvertBlocks +- ) { +- int charge = cursor.getCharge(); +- if (charge != 0 && random.nextInt(spreader.chargeDecayRate()) == 0) { +- BlockPos pos1 = cursor.getPos(); +- boolean flag = pos1.closerThan(pos, (double)spreader.noGrowthRadius()); +- if (!flag && canPlaceGrowth(level, pos1)) { +- int i = spreader.growthSpawnCost(); +- if (random.nextInt(i) < charge) { +- BlockPos blockPos = pos1.above(); +- BlockState randomGrowthState = this.getRandomGrowthState(level, blockPos, random, spreader.isWorldGeneration()); +- level.setBlock(blockPos, randomGrowthState, 3); +- level.playSound(null, pos1, randomGrowthState.getSoundType().getPlaceSound(), SoundSource.BLOCKS, 1.0F, 1.0F); ++ public int attemptUseCharge(SculkSpreader.ChargeCursor cursor, LevelAccessor level, BlockPos pos, RandomSource random, SculkSpreader spreader, boolean shouldConvertBlocks) { ++ int i = cursor.getCharge(); ++ ++ if (i != 0 && random.nextInt(spreader.chargeDecayRate()) == 0) { ++ BlockPos blockposition1 = cursor.getPos(); ++ boolean flag1 = blockposition1.closerThan(pos, (double) spreader.noGrowthRadius()); ++ ++ if (!flag1 && canPlaceGrowth(level, blockposition1)) { ++ int j = spreader.growthSpawnCost(); ++ ++ if (random.nextInt(j) < i) { ++ BlockPos blockposition2 = blockposition1.above(); ++ IBlockData iblockdata = this.getRandomGrowthState(level, blockposition2, random, spreader.isWorldGeneration()); ++ ++ // CraftBukkit start - Call BlockSpreadEvent ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition2, iblockdata, 3)) { ++ level.playSound((Player) null, blockposition1, iblockdata.getSoundType().getPlaceSound(), SoundSource.BLOCKS, 1.0F, 1.0F); ++ } ++ // CraftBukkit end + } + +- return Math.max(0, charge - i); ++ return Math.max(0, i - j); + } else { +- return random.nextInt(spreader.additionalDecayRate()) != 0 ? charge : charge - (flag ? 1 : getDecayPenalty(spreader, pos1, pos, charge)); ++ return random.nextInt(spreader.additionalDecayRate()) != 0 ? i : i - (flag1 ? 1 : getDecayPenalty(spreader, blockposition1, pos, i)); + } + } else { +- return charge; ++ return i; + } + } + + private static int getDecayPenalty(SculkSpreader spreader, BlockPos cursorPos, BlockPos rootPos, int charge) { +- int i = spreader.noGrowthRadius(); +- float squared = Mth.square((float)Math.sqrt(cursorPos.distSqr(rootPos)) - (float)i); +- int squared1 = Mth.square(24 - i); +- float min = Math.min(1.0F, squared / (float)squared1); +- return Math.max(1, (int)((float)charge * min * 0.5F)); ++ int j = spreader.noGrowthRadius(); ++ float f = Mth.square((float) Math.sqrt(cursorPos.distSqr(rootPos)) - (float) j); ++ int k = Mth.square(24 - j); ++ float f1 = Math.min(1.0F, f / (float) k); ++ ++ return Math.max(1, (int) ((float) charge * f1 * 0.5F)); + } + +- private BlockState getRandomGrowthState(LevelAccessor level, BlockPos pos, RandomSource random, boolean isWorldGeneration) { +- BlockState blockState; ++ private IBlockData getRandomGrowthState(LevelAccessor level, BlockPos pos, RandomSource random, boolean isWorldGeneration) { ++ IBlockData iblockdata; ++ + if (random.nextInt(11) == 0) { +- blockState = Blocks.SCULK_SHRIEKER.defaultBlockState().setValue(SculkShriekerBlock.CAN_SUMMON, Boolean.valueOf(isWorldGeneration)); ++ iblockdata = (IBlockData) Blocks.SCULK_SHRIEKER.defaultBlockState().setValue(SculkShriekerBlock.CAN_SUMMON, isWorldGeneration); + } else { +- blockState = Blocks.SCULK_SENSOR.defaultBlockState(); ++ iblockdata = Blocks.SCULK_SENSOR.defaultBlockState(); + } + +- return blockState.hasProperty(BlockStateProperties.WATERLOGGED) && !level.getFluidState(pos).isEmpty() +- ? blockState.setValue(BlockStateProperties.WATERLOGGED, Boolean.valueOf(true)) +- : blockState; ++ return iblockdata.hasProperty(BlockStateProperties.WATERLOGGED) && !level.getFluidState(pos).isEmpty() ? (IBlockData) iblockdata.setValue(BlockStateProperties.WATERLOGGED, true) : iblockdata; + } + + private static boolean canPlaceGrowth(LevelAccessor level, BlockPos pos) { +- BlockState blockState = level.getBlockState(pos.above()); +- if (blockState.isAir() || blockState.is(Blocks.WATER) && blockState.getFluidState().is(Fluids.WATER)) { ++ IBlockData iblockdata = level.getBlockState(pos.above()); ++ ++ if (!iblockdata.isAir() && (!iblockdata.is(Blocks.WATER) || !iblockdata.getFluidState().is((Fluid) Fluids.WATER))) { ++ return false; ++ } else { + int i = 0; ++ Iterator iterator = BlockPos.betweenClosed(pos.offset(-4, 0, -4), pos.offset(4, 2, 4)).iterator(); + +- for (BlockPos blockPos : BlockPos.betweenClosed(pos.offset(-4, 0, -4), pos.offset(4, 2, 4))) { +- BlockState blockState1 = level.getBlockState(blockPos); +- if (blockState1.is(Blocks.SCULK_SENSOR) || blockState1.is(Blocks.SCULK_SHRIEKER)) { +- i++; ++ do { ++ if (!iterator.hasNext()) { ++ return true; + } + +- if (i > 2) { +- return false; ++ BlockPos blockposition1 = (BlockPos) iterator.next(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ if (iblockdata1.is(Blocks.SCULK_SENSOR) || iblockdata1.is(Blocks.SCULK_SHRIEKER)) { ++ ++i; + } +- } ++ } while (i <= 2); + +- return true; +- } else { + return false; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/SculkCatalystBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SculkCatalystBlock.java.patch new file mode 100644 index 0000000000..3fe0bb5bed --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SculkCatalystBlock.java.patch @@ -0,0 +1,88 @@ +--- a/net/minecraft/world/level/block/SculkCatalystBlock.java ++++ b/net/minecraft/world/level/block/SculkCatalystBlock.java +@@ -14,60 +14,70 @@ + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.SculkCatalystBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + + public class SculkCatalystBlock extends BaseEntityBlock { ++ + public static final MapCodec CODEC = simpleCodec(SculkCatalystBlock::new); + public static final BooleanProperty PULSE = BlockStateProperties.BLOOM; + private final IntProvider xpRange = ConstantInt.of(5); + + @Override + public MapCodec codec() { +- return CODEC; ++ return SculkCatalystBlock.CODEC; + } + + public SculkCatalystBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(PULSE, Boolean.valueOf(false))); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(SculkCatalystBlock.PULSE, false)); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(PULSE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(SculkCatalystBlock.PULSE); + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- if (state.getValue(PULSE)) { +- level.setBlock(pos, state.setValue(PULSE, Boolean.valueOf(false)), 3); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(SculkCatalystBlock.PULSE)) { ++ level.setBlock(pos, (IBlockData) state.setValue(SculkCatalystBlock.PULSE, false), 3); + } ++ + } + + @Nullable + @Override +- public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { + return new SculkCatalystBlockEntity(pos, state); + } + + @Nullable + @Override +- public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { + return level.isClientSide ? null : createTickerHelper(blockEntityType, BlockEntityType.SCULK_CATALYST, SculkCatalystBlockEntity::serverTick); + } + + @Override +- public RenderShape getRenderShape(BlockState state) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Override +- public void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { + super.spawnAfterBreak(state, level, pos, stack, dropExperience); +- if (dropExperience) { +- this.tryDropExperience(level, pos, stack, this.xpRange); ++ // CraftBukkit start - Delegate to getExpDrop ++ } ++ ++ @Override ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { ++ if (flag) { ++ return this.tryDropExperience(worldserver, blockposition, itemstack, this.xpRange); + } ++ ++ return 0; ++ // CraftBukkit end + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/SculkSensorBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SculkSensorBlock.java.patch new file mode 100644 index 0000000000..77534998a8 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SculkSensorBlock.java.patch @@ -0,0 +1,429 @@ +--- a/net/minecraft/world/level/block/SculkSensorBlock.java ++++ b/net/minecraft/world/level/block/SculkSensorBlock.java +@@ -15,6 +15,7 @@ + import net.minecraft.util.valueproviders.ConstantInt; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.context.BlockPlaceContext; + import net.minecraft.world.level.BlockGetter; +@@ -25,7 +26,7 @@ + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.SculkSensorBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -34,96 +35,119 @@ + import net.minecraft.world.level.block.state.properties.SculkSensorPhase; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.gameevent.vibrations.VibrationSystem; ++import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockRedstoneEvent; ++// CraftBukkit end + + public class SculkSensorBlock extends BaseEntityBlock implements SimpleWaterloggedBlock { ++ + public static final MapCodec CODEC = simpleCodec(SculkSensorBlock::new); + public static final int ACTIVE_TICKS = 30; + public static final int COOLDOWN_TICKS = 10; + public static final EnumProperty PHASE = BlockStateProperties.SCULK_SENSOR_PHASE; + public static final IntegerProperty POWER = BlockStateProperties.POWER; + public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; +- protected static final VoxelShape SHAPE = Block.box(0.0, 0.0, 0.0, 16.0, 8.0, 16.0); +- private static final float[] RESONANCE_PITCH_BEND = Util.make(new float[16], pitchBends -> { +- int[] ints = new int[]{0, 0, 2, 4, 6, 7, 9, 10, 12, 14, 15, 18, 19, 21, 22, 24}; ++ protected static final VoxelShape SHAPE = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 8.0D, 16.0D); ++ private static final float[] RESONANCE_PITCH_BEND = (float[]) Util.make(new float[16], (afloat) -> { ++ int[] aint = new int[]{0, 0, 2, 4, 6, 7, 9, 10, 12, 14, 15, 18, 19, 21, 22, 24}; + +- for (int i = 0; i < 16; i++) { +- pitchBends[i] = NoteBlock.getPitchFromNote(ints[i]); ++ for (int i = 0; i < 16; ++i) { ++ afloat[i] = NoteBlock.getPitchFromNote(aint[i]); + } ++ + }); + + @Override + public MapCodec codec() { +- return CODEC; ++ return SculkSensorBlock.CODEC; + } + + public SculkSensorBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState( +- this.stateDefinition +- .any() +- .setValue(PHASE, SculkSensorPhase.INACTIVE) +- .setValue(POWER, Integer.valueOf(0)) +- .setValue(WATERLOGGED, Boolean.valueOf(false)) +- ); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(SculkSensorBlock.PHASE, SculkSensorPhase.INACTIVE)).setValue(SculkSensorBlock.POWER, 0)).setValue(SculkSensorBlock.WATERLOGGED, false)); + } + + @Nullable + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- BlockPos clickedPos = context.getClickedPos(); +- FluidState fluidState = context.getLevel().getFluidState(clickedPos); +- return this.defaultBlockState().setValue(WATERLOGGED, Boolean.valueOf(fluidState.getType() == Fluids.WATER)); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ BlockPos blockposition = context.getClickedPos(); ++ FluidState fluid = context.getLevel().getFluidState(blockposition); ++ ++ return (IBlockData) this.defaultBlockState().setValue(SculkSensorBlock.WATERLOGGED, fluid.getType() == Fluids.WATER); + } + + @Override +- public FluidState getFluidState(BlockState state) { +- return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(SculkSensorBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (getPhase(state) != SculkSensorPhase.ACTIVE) { + if (getPhase(state) == SculkSensorPhase.COOLDOWN) { +- level.setBlock(pos, state.setValue(PHASE, SculkSensorPhase.INACTIVE), 3); +- if (!state.getValue(WATERLOGGED)) { +- level.playSound(null, pos, SoundEvents.SCULK_CLICKING_STOP, SoundSource.BLOCKS, 1.0F, level.random.nextFloat() * 0.2F + 0.8F); ++ level.setBlock(pos, (IBlockData) state.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.INACTIVE), 3); ++ if (!(Boolean) state.getValue(SculkSensorBlock.WATERLOGGED)) { ++ level.playSound((Player) null, pos, SoundEvents.SCULK_CLICKING_STOP, SoundSource.BLOCKS, 1.0F, level.random.nextFloat() * 0.2F + 0.8F); + } + } ++ + } else { + deactivate(level, pos, state); + } + } + + @Override +- public void stepOn(Level level, BlockPos pos, BlockState state, Entity entity) { +- if (!level.isClientSide() +- && canActivate(state) +- && entity.getType() != EntityType.WARDEN +- && level.getBlockEntity(pos) instanceof SculkSensorBlockEntity sculkSensorBlockEntity +- && level instanceof ServerLevel serverLevel +- && sculkSensorBlockEntity.getVibrationUser().canReceiveVibration(serverLevel, pos, GameEvent.STEP, GameEvent.Context.of(state))) { +- sculkSensorBlockEntity.getListener().forceScheduleVibration(serverLevel, GameEvent.STEP, GameEvent.Context.of(entity), entity.position()); ++ public void stepOn(Level level, BlockPos pos, IBlockData state, Entity entity) { ++ if (!level.isClientSide() && canActivate(state) && entity.getType() != EntityType.WARDEN) { ++ // CraftBukkit start ++ org.bukkit.event.Cancellable cancellable; ++ if (entity instanceof Player) { ++ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new org.bukkit.event.entity.EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent((org.bukkit.event.entity.EntityInteractEvent) cancellable); ++ } ++ if (cancellable.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof SculkSensorBlockEntity) { ++ SculkSensorBlockEntity sculksensorblockentity = (SculkSensorBlockEntity) tileentity; ++ ++ if (level instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) level; ++ ++ if (sculksensorblockentity.getVibrationUser().canReceiveVibration(worldserver, pos, GameEvent.STEP, GameEvent.Context.of(state))) { ++ sculksensorblockentity.getListener().forceScheduleVibration(worldserver, GameEvent.STEP, GameEvent.Context.of(entity), entity.position()); ++ } ++ } ++ } + } + + super.stepOn(level, pos, state, entity); + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean movedByPiston) { + if (!level.isClientSide() && !state.is(oldState.getBlock())) { +- if (state.getValue(POWER) > 0 && !level.getBlockTicks().hasScheduledTick(pos, this)) { +- level.setBlock(pos, state.setValue(POWER, Integer.valueOf(0)), 18); ++ if ((Integer) state.getValue(SculkSensorBlock.POWER) > 0 && !level.getBlockTicks().hasScheduledTick(pos, this)) { ++ level.setBlock(pos, (IBlockData) state.setValue(SculkSensorBlock.POWER, 0), 18); + } ++ + } + } + + @Override +- public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean movedByPiston) { + if (!state.is(newState.getBlock())) { + if (getPhase(state) == SculkSensorPhase.ACTIVE) { + updateNeighbours(level, pos, state); +@@ -134,73 +158,79 @@ + } + + @Override +- public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { +- if (state.getValue(WATERLOGGED)) { +- level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); ++ public IBlockData updateShape(IBlockData state, Direction direction, IBlockData neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { ++ if ((Boolean) state.getValue(SculkSensorBlock.WATERLOGGED)) { ++ level.scheduleTick(pos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + + return super.updateShape(state, direction, neighborState, level, pos, neighborPos); + } + +- private static void updateNeighbours(Level level, BlockPos pos, BlockState state) { ++ private static void updateNeighbours(Level level, BlockPos pos, IBlockData state) { + Block block = state.getBlock(); ++ + level.updateNeighborsAt(pos, block); + level.updateNeighborsAt(pos.below(), block); + } + + @Nullable + @Override +- public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { + return new SculkSensorBlockEntity(pos, state); + } + + @Nullable + @Override +- public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { +- return !level.isClientSide +- ? createTickerHelper( +- blockEntityType, +- BlockEntityType.SCULK_SENSOR, +- (level1, pos, state1, blockEntity) -> VibrationSystem.Ticker.tick(level1, blockEntity.getVibrationData(), blockEntity.getVibrationUser()) +- ) +- : null; ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { ++ return !level.isClientSide ? createTickerHelper(blockEntityType, BlockEntityType.SCULK_SENSOR, (world1, blockposition, iblockdata1, sculksensorblockentity) -> { ++ VibrationSystem.Ticker.tick(world1, sculksensorblockentity.getVibrationData(), sculksensorblockentity.getVibrationUser()); ++ }) : null; + } + + @Override +- public RenderShape getRenderShape(BlockState state) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPE; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return SculkSensorBlock.SHAPE; + } + + @Override +- public boolean isSignalSource(BlockState state) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + + @Override +- public int getSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { +- return state.getValue(POWER); ++ public int getSignal(IBlockData state, BlockGetter level, BlockPos pos, Direction direction) { ++ return (Integer) state.getValue(SculkSensorBlock.POWER); + } + + @Override +- public int getDirectSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { ++ public int getDirectSignal(IBlockData state, BlockGetter level, BlockPos pos, Direction direction) { + return direction == Direction.UP ? state.getSignal(level, pos, direction) : 0; + } + +- public static SculkSensorPhase getPhase(BlockState state) { +- return state.getValue(PHASE); ++ public static SculkSensorPhase getPhase(IBlockData state) { ++ return (SculkSensorPhase) state.getValue(SculkSensorBlock.PHASE); + } + +- public static boolean canActivate(BlockState state) { ++ public static boolean canActivate(IBlockData state) { + return getPhase(state) == SculkSensorPhase.INACTIVE; + } + +- public static void deactivate(Level level, BlockPos pos, BlockState state) { +- level.setBlock(pos, state.setValue(PHASE, SculkSensorPhase.COOLDOWN).setValue(POWER, Integer.valueOf(0)), 3); ++ public static void deactivate(Level level, BlockPos pos, IBlockData state) { ++ // CraftBukkit start ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(level, pos), state.getValue(SculkSensorBlock.POWER), 0); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if (eventRedstone.getNewCurrent() > 0) { ++ level.setBlock(pos, state.setValue(SculkSensorBlock.POWER, eventRedstone.getNewCurrent()), 3); ++ return; ++ } ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) ((IBlockData) state.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.COOLDOWN)).setValue(SculkSensorBlock.POWER, 0), 3); + level.scheduleTick(pos, state.getBlock(), 10); + updateNeighbours(level, pos, state); + } +@@ -210,86 +240,108 @@ + return 30; + } + +- public void activate(@Nullable Entity entity, Level level, BlockPos pos, BlockState state, int power, int frequency) { +- level.setBlock(pos, state.setValue(PHASE, SculkSensorPhase.ACTIVE).setValue(POWER, Integer.valueOf(power)), 3); ++ public void activate(@Nullable Entity entity, Level level, BlockPos pos, IBlockData state, int power, int frequency) { ++ // CraftBukkit start ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(level, pos), state.getValue(SculkSensorBlock.POWER), power); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if (eventRedstone.getNewCurrent() <= 0) { ++ return; ++ } ++ power = eventRedstone.getNewCurrent(); ++ // CraftBukkit end ++ level.setBlock(pos, (IBlockData) ((IBlockData) state.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.ACTIVE)).setValue(SculkSensorBlock.POWER, power), 3); + level.scheduleTick(pos, state.getBlock(), this.getActiveTicks()); + updateNeighbours(level, pos, state); + tryResonateVibration(entity, level, pos, frequency); + level.gameEvent(entity, GameEvent.SCULK_SENSOR_TENDRILS_CLICKING, pos); +- if (!state.getValue(WATERLOGGED)) { +- level.playSound( +- null, +- (double)pos.getX() + 0.5, +- (double)pos.getY() + 0.5, +- (double)pos.getZ() + 0.5, +- SoundEvents.SCULK_CLICKING, +- SoundSource.BLOCKS, +- 1.0F, +- level.random.nextFloat() * 0.2F + 0.8F +- ); ++ if (!(Boolean) state.getValue(SculkSensorBlock.WATERLOGGED)) { ++ level.playSound((Player) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.SCULK_CLICKING, SoundSource.BLOCKS, 1.0F, level.random.nextFloat() * 0.2F + 0.8F); + } ++ + } + + public static void tryResonateVibration(@Nullable Entity entity, Level level, BlockPos pos, int frequency) { +- for (Direction direction : Direction.values()) { +- BlockPos blockPos = pos.relative(direction); +- BlockState blockState = level.getBlockState(blockPos); +- if (blockState.is(BlockTags.VIBRATION_RESONATORS)) { +- level.gameEvent(VibrationSystem.getResonanceEventByFrequency(frequency), blockPos, GameEvent.Context.of(entity, blockState)); +- float f = RESONANCE_PITCH_BEND[frequency]; +- level.playSound(null, blockPos, SoundEvents.AMETHYST_BLOCK_RESONATE, SoundSource.BLOCKS, 1.0F, f); ++ Direction[] aenumdirection = Direction.values(); ++ int j = aenumdirection.length; ++ ++ for (int k = 0; k < j; ++k) { ++ Direction enumdirection = aenumdirection[k]; ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ IBlockData iblockdata = level.getBlockState(blockposition1); ++ ++ if (iblockdata.is(BlockTags.VIBRATION_RESONATORS)) { ++ level.gameEvent(VibrationSystem.getResonanceEventByFrequency(frequency), blockposition1, GameEvent.Context.of(entity, iblockdata)); ++ float f = SculkSensorBlock.RESONANCE_PITCH_BEND[frequency]; ++ ++ level.playSound((Player) null, blockposition1, SoundEvents.AMETHYST_BLOCK_RESONATE, SoundSource.BLOCKS, 1.0F, f); + } + } ++ + } + + @Override +- public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { + if (getPhase(state) == SculkSensorPhase.ACTIVE) { +- Direction random1 = Direction.getRandom(random); +- if (random1 != Direction.UP && random1 != Direction.DOWN) { +- double d = (double)pos.getX() + 0.5 + (random1.getStepX() == 0 ? 0.5 - random.nextDouble() : (double)random1.getStepX() * 0.6); +- double d1 = (double)pos.getY() + 0.25; +- double d2 = (double)pos.getZ() + 0.5 + (random1.getStepZ() == 0 ? 0.5 - random.nextDouble() : (double)random1.getStepZ() * 0.6); +- double d3 = (double)random.nextFloat() * 0.04; +- level.addParticle(DustColorTransitionOptions.SCULK_TO_REDSTONE, d, d1, d2, 0.0, d3, 0.0); ++ Direction enumdirection = Direction.getRandom(random); ++ ++ if (enumdirection != Direction.UP && enumdirection != Direction.DOWN) { ++ double d0 = (double) pos.getX() + 0.5D + (enumdirection.getStepX() == 0 ? 0.5D - random.nextDouble() : (double) enumdirection.getStepX() * 0.6D); ++ double d1 = (double) pos.getY() + 0.25D; ++ double d2 = (double) pos.getZ() + 0.5D + (enumdirection.getStepZ() == 0 ? 0.5D - random.nextDouble() : (double) enumdirection.getStepZ() * 0.6D); ++ double d3 = (double) random.nextFloat() * 0.04D; ++ ++ level.addParticle(DustColorTransitionOptions.SCULK_TO_REDSTONE, d0, d1, d2, 0.0D, d3, 0.0D); + } + } + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(PHASE, POWER, WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(SculkSensorBlock.PHASE, SculkSensorBlock.POWER, SculkSensorBlock.WATERLOGGED); + } + + @Override +- public boolean hasAnalogOutputSignal(BlockState state) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return true; + } + + @Override +- public int getAnalogOutputSignal(BlockState state, Level level, BlockPos pos) { +- if (level.getBlockEntity(pos) instanceof SculkSensorBlockEntity sculkSensorBlockEntity) { +- return getPhase(state) == SculkSensorPhase.ACTIVE ? sculkSensorBlockEntity.getLastVibrationFrequency() : 0; ++ public int getAnalogOutputSignal(IBlockData state, Level level, BlockPos pos) { ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof SculkSensorBlockEntity) { ++ SculkSensorBlockEntity sculksensorblockentity = (SculkSensorBlockEntity) tileentity; ++ ++ return getPhase(state) == SculkSensorPhase.ACTIVE ? sculksensorblockentity.getLastVibrationFrequency() : 0; + } else { + return 0; + } + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + + @Override +- public boolean useShapeForLightOcclusion(BlockState state) { ++ public boolean useShapeForLightOcclusion(IBlockData state) { + return true; + } + + @Override +- public void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { + super.spawnAfterBreak(state, level, pos, stack, dropExperience); +- if (dropExperience) { +- this.tryDropExperience(level, pos, stack, ConstantInt.of(5)); ++ // CraftBukkit start - Delegate to getExpDrop ++ } ++ ++ @Override ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { ++ if (flag) { ++ return this.tryDropExperience(worldserver, blockposition, itemstack, ConstantInt.of(5)); + } ++ ++ return 0; ++ // CraftBukkit end + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/SculkShriekerBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SculkShriekerBlock.java.patch new file mode 100644 index 0000000000..321db785aa --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SculkShriekerBlock.java.patch @@ -0,0 +1,210 @@ +--- a/net/minecraft/world/level/block/SculkShriekerBlock.java ++++ b/net/minecraft/world/level/block/SculkShriekerBlock.java +@@ -19,53 +19,54 @@ + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.SculkShriekerBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.gameevent.vibrations.VibrationSystem; ++import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; + + public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterloggedBlock { ++ + public static final MapCodec CODEC = simpleCodec(SculkShriekerBlock::new); + public static final BooleanProperty SHRIEKING = BlockStateProperties.SHRIEKING; + public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; + public static final BooleanProperty CAN_SUMMON = BlockStateProperties.CAN_SUMMON; +- protected static final VoxelShape COLLIDER = Block.box(0.0, 0.0, 0.0, 16.0, 8.0, 16.0); +- public static final double TOP_Y = COLLIDER.max(Direction.Axis.Y); ++ protected static final VoxelShape COLLIDER = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 8.0D, 16.0D); ++ public static final double TOP_Y = SculkShriekerBlock.COLLIDER.max(Direction.Axis.Y); + + @Override + public MapCodec codec() { +- return CODEC; ++ return SculkShriekerBlock.CODEC; + } + + public SculkShriekerBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState( +- this.stateDefinition +- .any() +- .setValue(SHRIEKING, Boolean.valueOf(false)) +- .setValue(WATERLOGGED, Boolean.valueOf(false)) +- .setValue(CAN_SUMMON, Boolean.valueOf(false)) +- ); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(SculkShriekerBlock.SHRIEKING, false)).setValue(SculkShriekerBlock.WATERLOGGED, false)).setValue(SculkShriekerBlock.CAN_SUMMON, false)); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(SHRIEKING); +- builder.add(WATERLOGGED); +- builder.add(CAN_SUMMON); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(SculkShriekerBlock.SHRIEKING); ++ builder.add(SculkShriekerBlock.WATERLOGGED); ++ builder.add(SculkShriekerBlock.CAN_SUMMON); + } + + @Override +- public void stepOn(Level level, BlockPos pos, BlockState state, Entity entity) { +- if (level instanceof ServerLevel serverLevel) { +- ServerPlayer serverPlayer = SculkShriekerBlockEntity.tryGetPlayer(entity); +- if (serverPlayer != null) { +- serverLevel.getBlockEntity(pos, BlockEntityType.SCULK_SHRIEKER).ifPresent(sculkShrieker -> sculkShrieker.tryShriek(serverLevel, serverPlayer)); ++ public void stepOn(Level level, BlockPos pos, IBlockData state, Entity entity) { ++ if (level instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) level; ++ ServerPlayer entityplayer = SculkShriekerBlockEntity.tryGetPlayer(entity); ++ ++ if (entityplayer != null) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(entityplayer, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null).isCancelled()) return; // CraftBukkit ++ worldserver.getBlockEntity(pos, BlockEntityType.SCULK_SHRIEKER).ifPresent((sculkshriekerblockentity) -> { ++ sculkshriekerblockentity.tryShriek(worldserver, entityplayer); ++ }); + } + } + +@@ -73,52 +74,61 @@ + } + + @Override +- public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { +- if (level instanceof ServerLevel serverLevel && state.getValue(SHRIEKING) && !state.is(newState.getBlock())) { +- serverLevel.getBlockEntity(pos, BlockEntityType.SCULK_SHRIEKER).ifPresent(sculkShrieker -> sculkShrieker.tryRespond(serverLevel)); ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean movedByPiston) { ++ if (level instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) level; ++ ++ if ((Boolean) state.getValue(SculkShriekerBlock.SHRIEKING) && !state.is(newState.getBlock())) { ++ worldserver.getBlockEntity(pos, BlockEntityType.SCULK_SHRIEKER).ifPresent((sculkshriekerblockentity) -> { ++ sculkshriekerblockentity.tryRespond(worldserver); ++ }); ++ } + } + + super.onRemove(state, level, pos, newState, movedByPiston); + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- if (state.getValue(SHRIEKING)) { +- level.setBlock(pos, state.setValue(SHRIEKING, Boolean.valueOf(false)), 3); +- level.getBlockEntity(pos, BlockEntityType.SCULK_SHRIEKER).ifPresent(sculkShrieker -> sculkShrieker.tryRespond(level)); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) state.getValue(SculkShriekerBlock.SHRIEKING)) { ++ level.setBlock(pos, (IBlockData) state.setValue(SculkShriekerBlock.SHRIEKING, false), 3); ++ level.getBlockEntity(pos, BlockEntityType.SCULK_SHRIEKER).ifPresent((sculkshriekerblockentity) -> { ++ sculkshriekerblockentity.tryRespond(level); ++ }); + } ++ + } + + @Override +- public RenderShape getRenderShape(BlockState state) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Override +- public VoxelShape getCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return COLLIDER; ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return SculkShriekerBlock.COLLIDER; + } + + @Override +- public VoxelShape getOcclusionShape(BlockState state, BlockGetter level, BlockPos pos) { +- return COLLIDER; ++ public VoxelShape getOcclusionShape(IBlockData state, BlockGetter level, BlockPos pos) { ++ return SculkShriekerBlock.COLLIDER; + } + + @Override +- public boolean useShapeForLightOcclusion(BlockState state) { ++ public boolean useShapeForLightOcclusion(IBlockData state) { + return true; + } + + @Nullable + @Override +- public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { + return new SculkShriekerBlockEntity(pos, state); + } + + @Override +- public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { +- if (state.getValue(WATERLOGGED)) { +- level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); ++ public IBlockData updateShape(IBlockData state, Direction direction, IBlockData neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { ++ if ((Boolean) state.getValue(SculkShriekerBlock.WATERLOGGED)) { ++ level.scheduleTick(pos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + + return super.updateShape(state, direction, neighborState, level, pos, neighborPos); +@@ -126,33 +136,36 @@ + + @Nullable + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- return this.defaultBlockState() +- .setValue(WATERLOGGED, Boolean.valueOf(context.getLevel().getFluidState(context.getClickedPos()).getType() == Fluids.WATER)); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return (IBlockData) this.defaultBlockState().setValue(SculkShriekerBlock.WATERLOGGED, context.getLevel().getFluidState(context.getClickedPos()).getType() == Fluids.WATER); + } + + @Override +- public FluidState getFluidState(BlockState state) { +- return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(SculkShriekerBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override +- public void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { + super.spawnAfterBreak(state, level, pos, stack, dropExperience); +- if (dropExperience) { +- this.tryDropExperience(level, pos, stack, ConstantInt.of(5)); ++ // CraftBukkit start - Delegate to getExpDrop ++ } ++ ++ @Override ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { ++ if (flag) { ++ return this.tryDropExperience(worldserver, blockposition, itemstack, ConstantInt.of(5)); + } ++ ++ return 0; ++ // CraftBukkit end + } + + @Nullable + @Override +- public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { +- return !level.isClientSide +- ? BaseEntityBlock.createTickerHelper( +- blockEntityType, +- BlockEntityType.SCULK_SHRIEKER, +- (level1, pos, state1, blockEntity) -> VibrationSystem.Ticker.tick(level1, blockEntity.getVibrationData(), blockEntity.getVibrationUser()) +- ) +- : null; ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { ++ return !level.isClientSide ? BaseEntityBlock.createTickerHelper(blockEntityType, BlockEntityType.SCULK_SHRIEKER, (world1, blockposition, iblockdata1, sculkshriekerblockentity) -> { ++ VibrationSystem.Ticker.tick(world1, sculkshriekerblockentity.getVibrationData(), sculkshriekerblockentity.getVibrationUser()); ++ }) : null; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/SculkSpreader.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SculkSpreader.java.patch new file mode 100644 index 0000000000..e6f5c721e9 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SculkSpreader.java.patch @@ -0,0 +1,466 @@ +--- a/net/minecraft/world/level/block/SculkSpreader.java ++++ b/net/minecraft/world/level/block/SculkSpreader.java +@@ -5,20 +5,24 @@ + import com.google.common.collect.Sets; + import com.mojang.logging.LogUtils; + import com.mojang.serialization.Codec; ++import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import it.unimi.dsi.fastutil.objects.Object2IntMap; ++import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; + import it.unimi.dsi.fastutil.objects.ObjectArrayList; +-import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; ++import it.unimi.dsi.fastutil.objects.ObjectIterator; + import java.util.ArrayList; + import java.util.Collection; + import java.util.HashMap; ++import java.util.Iterator; + import java.util.List; + import java.util.Map; ++import java.util.Objects; + import java.util.Optional; + import java.util.Set; ++import java.util.stream.Stream; + import javax.annotation.Nullable; + import net.minecraft.Util; + import net.minecraft.core.BlockPos; +@@ -33,11 +37,18 @@ + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.TagKey; + import net.minecraft.util.RandomSource; ++import net.minecraft.world.entity.player.Player; ++import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.SculkBloomEvent; ++// CraftBukkit end + + public class SculkSpreader { ++ + public static final int MAX_GROWTH_RATE_RADIUS = 24; + public static final int MAX_CHARGE = 1000; + public static final float MAX_DECAY_FACTOR = 0.5F; +@@ -49,12 +60,11 @@ + private final int noGrowthRadius; + private final int chargeDecayRate; + private final int additionalDecayRate; +- private List cursors = new ArrayList<>(); ++ private List cursors = new ArrayList(); + private static final Logger LOGGER = LogUtils.getLogger(); ++ public Level level; // CraftBukkit + +- public SculkSpreader( +- boolean isWorldGeneration, TagKey replaceableBlocks, int growthSpawnCoat, int noGrowthRadius, int chargeDecayRate, int additionalDecayRate +- ) { ++ public SculkSpreader(boolean isWorldGeneration, TagKey replaceableBlocks, int growthSpawnCoat, int noGrowthRadius, int chargeDecayRate, int additionalDecayRate) { + this.isWorldGeneration = isWorldGeneration; + this.replaceableBlocks = replaceableBlocks; + this.growthSpawnCost = growthSpawnCoat; +@@ -107,78 +117,110 @@ + public void load(CompoundTag tag) { + if (tag.contains("cursors", 9)) { + this.cursors.clear(); +- List list = SculkSpreader.ChargeCursor.CODEC +- .listOf() +- .parse(new Dynamic<>(NbtOps.INSTANCE, tag.getList("cursors", 10))) +- .resultOrPartial(LOGGER::error) +- .orElseGet(ArrayList::new); +- int min = Math.min(list.size(), 32); ++ DataResult> dataresult = SculkSpreader.ChargeCursor.CODEC.listOf().parse(new Dynamic<>(NbtOps.INSTANCE, tag.getList("cursors", 10))); // CraftBukkit - decompile error ++ Logger logger = SculkSpreader.LOGGER; + +- for (int i = 0; i < min; i++) { +- this.addCursor(list.get(i)); ++ Objects.requireNonNull(logger); ++ List list = (List) dataresult.resultOrPartial(logger::error).orElseGet(ArrayList::new); ++ int i = Math.min(list.size(), 32); ++ ++ for (int j = 0; j < i; ++j) { ++ this.addCursor((SculkSpreader.ChargeCursor) list.get(j)); + } + } ++ + } + + public void save(CompoundTag tag) { +- SculkSpreader.ChargeCursor.CODEC +- .listOf() +- .encodeStart(NbtOps.INSTANCE, this.cursors) +- .resultOrPartial(LOGGER::error) +- .ifPresent(cursorsTag -> tag.put("cursors", cursorsTag)); ++ DataResult dataresult = SculkSpreader.ChargeCursor.CODEC.listOf().encodeStart(NbtOps.INSTANCE, this.cursors); // CraftBukkit - decompile error ++ Logger logger = SculkSpreader.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ tag.put("cursors", nbtbase); ++ }); + } + + public void addCursors(BlockPos pos, int charge) { + while (charge > 0) { +- int min = Math.min(charge, 1000); +- this.addCursor(new SculkSpreader.ChargeCursor(pos, min)); +- charge -= min; ++ int j = Math.min(charge, 1000); ++ ++ this.addCursor(new SculkSpreader.ChargeCursor(pos, j)); ++ charge -= j; + } ++ + } + + private void addCursor(SculkSpreader.ChargeCursor cursor) { + if (this.cursors.size() < 32) { ++ // CraftBukkit start ++ if (!isWorldGeneration()) { // CraftBukkit - SPIGOT-7475: Don't call event during world generation ++ CraftBlock bukkitBlock = CraftBlock.at(level, cursor.pos); ++ SculkBloomEvent event = new SculkBloomEvent(bukkitBlock, cursor.getCharge()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ cursor.charge = event.getCharge(); ++ } ++ // CraftBukkit end ++ + this.cursors.add(cursor); + } + } + + public void updateCursors(LevelAccessor level, BlockPos pos, RandomSource random, boolean shouldConvertBlocks) { + if (!this.cursors.isEmpty()) { +- List list = new ArrayList<>(); +- Map map = new HashMap<>(); +- Object2IntMap map1 = new Object2IntOpenHashMap<>(); ++ List list = new ArrayList(); ++ Map map = new HashMap(); ++ Object2IntMap object2intmap = new Object2IntOpenHashMap(); ++ Iterator iterator = this.cursors.iterator(); + +- for (SculkSpreader.ChargeCursor chargeCursor : this.cursors) { +- chargeCursor.update(level, pos, random, this, shouldConvertBlocks); +- if (chargeCursor.charge <= 0) { +- level.levelEvent(3006, chargeCursor.getPos(), 0); ++ BlockPos blockposition1; ++ ++ while (iterator.hasNext()) { ++ SculkSpreader.ChargeCursor sculkspreader_a = (SculkSpreader.ChargeCursor) iterator.next(); ++ ++ sculkspreader_a.update(level, pos, random, this, shouldConvertBlocks); ++ if (sculkspreader_a.charge <= 0) { ++ level.levelEvent(3006, sculkspreader_a.getPos(), 0); + } else { +- BlockPos pos1 = chargeCursor.getPos(); +- map1.computeInt(pos1, (cursorPos, charge) -> (charge == null ? 0 : charge) + chargeCursor.charge); +- SculkSpreader.ChargeCursor chargeCursor1 = map.get(pos1); +- if (chargeCursor1 == null) { +- map.put(pos1, chargeCursor); +- list.add(chargeCursor); +- } else if (!this.isWorldGeneration() && chargeCursor.charge + chargeCursor1.charge <= 1000) { +- chargeCursor1.mergeWith(chargeCursor); ++ blockposition1 = sculkspreader_a.getPos(); ++ object2intmap.computeInt(blockposition1, (blockposition2, integer) -> { ++ return (integer == null ? 0 : integer) + sculkspreader_a.charge; ++ }); ++ SculkSpreader.ChargeCursor sculkspreader_a1 = (SculkSpreader.ChargeCursor) map.get(blockposition1); ++ ++ if (sculkspreader_a1 == null) { ++ map.put(blockposition1, sculkspreader_a); ++ list.add(sculkspreader_a); ++ } else if (!this.isWorldGeneration() && sculkspreader_a.charge + sculkspreader_a1.charge <= 1000) { ++ sculkspreader_a1.mergeWith(sculkspreader_a); + } else { +- list.add(chargeCursor); +- if (chargeCursor.charge < chargeCursor1.charge) { +- map.put(pos1, chargeCursor); ++ list.add(sculkspreader_a); ++ if (sculkspreader_a.charge < sculkspreader_a1.charge) { ++ map.put(blockposition1, sculkspreader_a); + } + } + } + } + +- for (Entry entry : map1.object2IntEntrySet()) { +- BlockPos pos1 = entry.getKey(); +- int intValue = entry.getIntValue(); +- SculkSpreader.ChargeCursor chargeCursor2 = map.get(pos1); +- Collection collection = chargeCursor2 == null ? null : chargeCursor2.getFacingData(); +- if (intValue > 0 && collection != null) { +- int i = (int)(Math.log1p((double)intValue) / 2.3F) + 1; +- int i1 = (i << 6) + MultifaceBlock.pack(collection); +- level.levelEvent(3006, pos1, i1); ++ ObjectIterator objectiterator = object2intmap.object2IntEntrySet().iterator(); ++ ++ while (objectiterator.hasNext()) { ++ Entry entry = (Entry) objectiterator.next(); ++ ++ blockposition1 = (BlockPos) entry.getKey(); ++ int i = entry.getIntValue(); ++ SculkSpreader.ChargeCursor sculkspreader_a2 = (SculkSpreader.ChargeCursor) map.get(blockposition1); ++ Collection collection = sculkspreader_a2 == null ? null : sculkspreader_a2.getFacingData(); ++ ++ if (i > 0 && collection != null) { ++ int j = (int) (Math.log1p((double) i) / 2.299999952316284D) + 1; ++ int k = (j << 6) + MultifaceBlock.pack(collection); ++ ++ level.levelEvent(3006, blockposition1, k); + } + } + +@@ -187,16 +229,15 @@ + } + + public static class ChargeCursor { +- private static final ObjectArrayList NON_CORNER_NEIGHBOURS = Util.make( +- new ObjectArrayList<>(18), +- list -> BlockPos.betweenClosedStream(new BlockPos(-1, -1, -1), new BlockPos(1, 1, 1)) +- .filter( +- candidatePos -> (candidatePos.getX() == 0 || candidatePos.getY() == 0 || candidatePos.getZ() == 0) +- && !candidatePos.equals(BlockPos.ZERO) +- ) +- .map(BlockPos::immutable) +- .forEach(list::add) +- ); ++ ++ private static final ObjectArrayList NON_CORNER_NEIGHBOURS = (ObjectArrayList) Util.make(new ObjectArrayList(18), (objectarraylist) -> { ++ Stream stream = BlockPos.betweenClosedStream(new BlockPos(-1, -1, -1), new BlockPos(1, 1, 1)).filter((blockposition) -> { ++ return (blockposition.getX() == 0 || blockposition.getY() == 0 || blockposition.getZ() == 0) && !blockposition.equals(BlockPos.ZERO); ++ }).map(BlockPos::immutable); ++ ++ Objects.requireNonNull(objectarraylist); ++ stream.forEach(objectarraylist::add); ++ }); + public static final int MAX_CURSOR_DECAY_DELAY = 1; + private BlockPos pos; + int charge; +@@ -204,26 +245,23 @@ + private int decayDelay; + @Nullable + private Set facings; +- private static final Codec> DIRECTION_SET = Direction.CODEC +- .listOf() +- .xmap(directions -> Sets.newEnumSet(directions, Direction.class), Lists::newArrayList); +- public static final Codec CODEC = RecordCodecBuilder.create( +- instance -> instance.group( +- BlockPos.CODEC.fieldOf("pos").forGetter(SculkSpreader.ChargeCursor::getPos), +- Codec.intRange(0, 1000).fieldOf("charge").orElse(0).forGetter(SculkSpreader.ChargeCursor::getCharge), +- Codec.intRange(0, 1).fieldOf("decay_delay").orElse(1).forGetter(SculkSpreader.ChargeCursor::getDecayDelay), +- Codec.intRange(0, Integer.MAX_VALUE).fieldOf("update_delay").orElse(0).forGetter(cursor -> cursor.updateDelay), +- DIRECTION_SET.optionalFieldOf("facings").forGetter(cursor -> Optional.ofNullable(cursor.getFacingData())) +- ) +- .apply(instance, SculkSpreader.ChargeCursor::new) +- ); ++ private static final Codec> DIRECTION_SET = Direction.CODEC.listOf().xmap((list) -> { ++ return Sets.newEnumSet(list, Direction.class); ++ }, Lists::newArrayList); ++ public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(BlockPos.CODEC.fieldOf("pos").forGetter(SculkSpreader.ChargeCursor::getPos), Codec.intRange(0, 1000).fieldOf("charge").orElse(0).forGetter(SculkSpreader.ChargeCursor::getCharge), Codec.intRange(0, 1).fieldOf("decay_delay").orElse(1).forGetter(SculkSpreader.ChargeCursor::getDecayDelay), Codec.intRange(0, Integer.MAX_VALUE).fieldOf("update_delay").orElse(0).forGetter((sculkspreader_a) -> { ++ return sculkspreader_a.updateDelay; ++ }), SculkSpreader.ChargeCursor.DIRECTION_SET.optionalFieldOf("facings").forGetter((sculkspreader_a) -> { ++ return Optional.ofNullable(sculkspreader_a.getFacingData()); ++ })).apply(instance, SculkSpreader.ChargeCursor::new); ++ }); + + private ChargeCursor(BlockPos pos, int charge, int decayDelay, int updateDelay, Optional> facings) { + this.pos = pos; + this.charge = charge; + this.decayDelay = decayDelay; + this.updateDelay = updateDelay; +- this.facings = facings.orElse(null); ++ this.facings = (Set) facings.orElse(null); // CraftBukkit - decompile error + } + + public ChargeCursor(BlockPos pos, int charge) { +@@ -248,112 +286,129 @@ + } + + private boolean shouldUpdate(LevelAccessor level, BlockPos pos, boolean isWorldGeneration) { +- return this.charge > 0 && (isWorldGeneration || level instanceof ServerLevel serverLevel && serverLevel.shouldTickBlocksAt(pos)); ++ if (this.charge <= 0) { ++ return false; ++ } else if (isWorldGeneration) { ++ return true; ++ } else if (level instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) level; ++ ++ return worldserver.shouldTickBlocksAt(pos); ++ } else { ++ return false; ++ } + } + + public void update(LevelAccessor level, BlockPos pos, RandomSource random, SculkSpreader spreader, boolean shouldConvertBlocks) { + if (this.shouldUpdate(level, pos, spreader.isWorldGeneration)) { + if (this.updateDelay > 0) { +- this.updateDelay--; ++ --this.updateDelay; + } else { +- BlockState blockState = level.getBlockState(this.pos); +- SculkBehaviour blockBehaviour = getBlockBehaviour(blockState); +- if (shouldConvertBlocks && blockBehaviour.attemptSpreadVein(level, this.pos, blockState, this.facings, spreader.isWorldGeneration())) { +- if (blockBehaviour.canChangeBlockStateOnSpread()) { +- blockState = level.getBlockState(this.pos); +- blockBehaviour = getBlockBehaviour(blockState); ++ IBlockData iblockdata = level.getBlockState(this.pos); ++ SculkBehaviour sculkbehaviour = getBlockBehaviour(iblockdata); ++ ++ if (shouldConvertBlocks && sculkbehaviour.attemptSpreadVein(level, this.pos, iblockdata, this.facings, spreader.isWorldGeneration())) { ++ if (sculkbehaviour.canChangeBlockStateOnSpread()) { ++ iblockdata = level.getBlockState(this.pos); ++ sculkbehaviour = getBlockBehaviour(iblockdata); + } + +- level.playSound(null, this.pos, SoundEvents.SCULK_BLOCK_SPREAD, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.playSound((Player) null, this.pos, SoundEvents.SCULK_BLOCK_SPREAD, SoundSource.BLOCKS, 1.0F, 1.0F); + } + +- this.charge = blockBehaviour.attemptUseCharge(this, level, pos, random, spreader, shouldConvertBlocks); ++ this.charge = sculkbehaviour.attemptUseCharge(this, level, pos, random, spreader, shouldConvertBlocks); + if (this.charge <= 0) { +- blockBehaviour.onDischarged(level, blockState, this.pos, random); ++ sculkbehaviour.onDischarged(level, iblockdata, this.pos, random); + } else { +- BlockPos validMovementPos = getValidMovementPos(level, this.pos, random); +- if (validMovementPos != null) { +- blockBehaviour.onDischarged(level, blockState, this.pos, random); +- this.pos = validMovementPos.immutable(); +- if (spreader.isWorldGeneration() && !this.pos.closerThan(new Vec3i(pos.getX(), this.pos.getY(), pos.getZ()), 15.0)) { ++ BlockPos blockposition1 = getValidMovementPos(level, this.pos, random); ++ ++ if (blockposition1 != null) { ++ sculkbehaviour.onDischarged(level, iblockdata, this.pos, random); ++ this.pos = blockposition1.immutable(); ++ if (spreader.isWorldGeneration() && !this.pos.closerThan(new Vec3i(pos.getX(), this.pos.getY(), pos.getZ()), 15.0D)) { + this.charge = 0; + return; + } + +- blockState = level.getBlockState(validMovementPos); ++ iblockdata = level.getBlockState(blockposition1); + } + +- if (blockState.getBlock() instanceof SculkBehaviour) { +- this.facings = MultifaceBlock.availableFaces(blockState); ++ if (iblockdata.getBlock() instanceof SculkBehaviour) { ++ this.facings = MultifaceBlock.availableFaces(iblockdata); + } + +- this.decayDelay = blockBehaviour.updateDecayDelay(this.decayDelay); +- this.updateDelay = blockBehaviour.getSculkSpreadDelay(); ++ this.decayDelay = sculkbehaviour.updateDecayDelay(this.decayDelay); ++ this.updateDelay = sculkbehaviour.getSculkSpreadDelay(); + } + } + } + } + + void mergeWith(SculkSpreader.ChargeCursor cursor) { +- this.charge = this.charge + cursor.charge; ++ this.charge += cursor.charge; + cursor.charge = 0; + this.updateDelay = Math.min(this.updateDelay, cursor.updateDelay); + } + +- private static SculkBehaviour getBlockBehaviour(BlockState state) { +- return state.getBlock() instanceof SculkBehaviour sculkBehaviour ? sculkBehaviour : SculkBehaviour.DEFAULT; ++ private static SculkBehaviour getBlockBehaviour(IBlockData state) { ++ Block block = state.getBlock(); ++ SculkBehaviour sculkbehaviour; ++ ++ if (block instanceof SculkBehaviour) { ++ SculkBehaviour sculkbehaviour1 = (SculkBehaviour) block; ++ ++ sculkbehaviour = sculkbehaviour1; ++ } else { ++ sculkbehaviour = SculkBehaviour.DEFAULT; ++ } ++ ++ return sculkbehaviour; + } + + private static List getRandomizedNonCornerNeighbourOffsets(RandomSource random) { +- return Util.shuffledCopy(NON_CORNER_NEIGHBOURS, random); ++ return Util.shuffledCopy(SculkSpreader.ChargeCursor.NON_CORNER_NEIGHBOURS, random); + } + + @Nullable + private static BlockPos getValidMovementPos(LevelAccessor level, BlockPos pos, RandomSource random) { +- BlockPos.MutableBlockPos mutableBlockPos = pos.mutable(); +- BlockPos.MutableBlockPos mutableBlockPos1 = pos.mutable(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition1 = pos.mutable(); ++ Iterator iterator = getRandomizedNonCornerNeighbourOffsets(random).iterator(); + +- for (Vec3i vec3i : getRandomizedNonCornerNeighbourOffsets(random)) { +- mutableBlockPos1.setWithOffset(pos, vec3i); +- BlockState blockState = level.getBlockState(mutableBlockPos1); +- if (blockState.getBlock() instanceof SculkBehaviour && isMovementUnobstructed(level, pos, mutableBlockPos1)) { +- mutableBlockPos.set(mutableBlockPos1); +- if (SculkVeinBlock.hasSubstrateAccess(level, blockState, mutableBlockPos1)) { ++ while (iterator.hasNext()) { ++ Vec3i baseblockposition = (Vec3i) iterator.next(); ++ ++ blockposition_mutableblockposition1.setWithOffset(pos, baseblockposition); ++ IBlockData iblockdata = level.getBlockState(blockposition_mutableblockposition1); ++ ++ if (iblockdata.getBlock() instanceof SculkBehaviour && isMovementUnobstructed(level, pos, blockposition_mutableblockposition1)) { ++ blockposition_mutableblockposition.set(blockposition_mutableblockposition1); ++ if (SculkVeinBlock.hasSubstrateAccess(level, iblockdata, blockposition_mutableblockposition1)) { + break; + } + } + } + +- return mutableBlockPos.equals(pos) ? null : mutableBlockPos; ++ return blockposition_mutableblockposition.equals(pos) ? null : blockposition_mutableblockposition; + } + + private static boolean isMovementUnobstructed(LevelAccessor level, BlockPos fromPos, BlockPos toPos) { + if (fromPos.distManhattan(toPos) == 1) { + return true; + } else { +- BlockPos blockPos = toPos.subtract(fromPos); +- Direction direction = Direction.fromAxisAndDirection( +- Direction.Axis.X, blockPos.getX() < 0 ? Direction.AxisDirection.NEGATIVE : Direction.AxisDirection.POSITIVE +- ); +- Direction direction1 = Direction.fromAxisAndDirection( +- Direction.Axis.Y, blockPos.getY() < 0 ? Direction.AxisDirection.NEGATIVE : Direction.AxisDirection.POSITIVE +- ); +- Direction direction2 = Direction.fromAxisAndDirection( +- Direction.Axis.Z, blockPos.getZ() < 0 ? Direction.AxisDirection.NEGATIVE : Direction.AxisDirection.POSITIVE +- ); +- if (blockPos.getX() == 0) { +- return isUnobstructed(level, fromPos, direction1) || isUnobstructed(level, fromPos, direction2); +- } else { +- return blockPos.getY() == 0 +- ? isUnobstructed(level, fromPos, direction) || isUnobstructed(level, fromPos, direction2) +- : isUnobstructed(level, fromPos, direction) || isUnobstructed(level, fromPos, direction1); +- } ++ BlockPos blockposition2 = toPos.subtract(fromPos); ++ Direction enumdirection = Direction.fromAxisAndDirection(Direction.Axis.X, blockposition2.getX() < 0 ? Direction.AxisDirection.NEGATIVE : Direction.AxisDirection.POSITIVE); ++ Direction enumdirection1 = Direction.fromAxisAndDirection(Direction.Axis.Y, blockposition2.getY() < 0 ? Direction.AxisDirection.NEGATIVE : Direction.AxisDirection.POSITIVE); ++ Direction enumdirection2 = Direction.fromAxisAndDirection(Direction.Axis.Z, blockposition2.getZ() < 0 ? Direction.AxisDirection.NEGATIVE : Direction.AxisDirection.POSITIVE); ++ ++ return blockposition2.getX() == 0 ? isUnobstructed(level, fromPos, enumdirection1) || isUnobstructed(level, fromPos, enumdirection2) : (blockposition2.getY() == 0 ? isUnobstructed(level, fromPos, enumdirection) || isUnobstructed(level, fromPos, enumdirection2) : isUnobstructed(level, fromPos, enumdirection) || isUnobstructed(level, fromPos, enumdirection1)); + } + } + + private static boolean isUnobstructed(LevelAccessor level, BlockPos pos, Direction direction) { +- BlockPos blockPos = pos.relative(direction); +- return !level.getBlockState(blockPos).isFaceSturdy(level, blockPos, direction.getOpposite()); ++ BlockPos blockposition1 = pos.relative(direction); ++ ++ return !level.getBlockState(blockposition1).isFaceSturdy(level, blockposition1, direction.getOpposite()); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/SculkVeinBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SculkVeinBlock.java.patch new file mode 100644 index 0000000000..a5988edecc --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SculkVeinBlock.java.patch @@ -0,0 +1,305 @@ +--- a/net/minecraft/world/level/block/SculkVeinBlock.java ++++ b/net/minecraft/world/level/block/SculkVeinBlock.java +@@ -2,6 +2,7 @@ + + import com.mojang.serialization.MapCodec; + import java.util.Collection; ++import java.util.Iterator; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.sounds.SoundEvents; +@@ -10,34 +11,37 @@ + import net.minecraft.tags.TagKey; + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Items; + import net.minecraft.world.item.context.BlockPlaceContext; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; ++import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; + + public class SculkVeinBlock extends MultifaceBlock implements SculkBehaviour, SimpleWaterloggedBlock { ++ + public static final MapCodec CODEC = simpleCodec(SculkVeinBlock::new); + private static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; +- private final MultifaceSpreader veinSpreader = new MultifaceSpreader(new SculkVeinBlock.SculkVeinSpreaderConfig(MultifaceSpreader.DEFAULT_SPREAD_ORDER)); +- private final MultifaceSpreader sameSpaceSpreader = new MultifaceSpreader( +- new SculkVeinBlock.SculkVeinSpreaderConfig(MultifaceSpreader.SpreadType.SAME_POSITION) +- ); ++ private final MultifaceSpreader veinSpreader; ++ private final MultifaceSpreader sameSpaceSpreader; + + @Override + public MapCodec codec() { +- return CODEC; ++ return SculkVeinBlock.CODEC; + } + + public SculkVeinBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.defaultBlockState().setValue(WATERLOGGED, Boolean.valueOf(false))); ++ this.veinSpreader = new MultifaceSpreader(new SculkVeinBlock.SculkVeinSpreaderConfig(MultifaceSpreader.DEFAULT_SPREAD_ORDER)); ++ this.sameSpaceSpreader = new MultifaceSpreader(new SculkVeinBlock.SculkVeinSpreaderConfig(new MultifaceSpreader.SpreadType[]{MultifaceSpreader.SpreadType.SAME_POSITION})); ++ this.registerDefaultState((IBlockData) this.defaultBlockState().setValue(SculkVeinBlock.WATERLOGGED, false)); + } + + @Override +@@ -49,14 +53,17 @@ + return this.sameSpaceSpreader; + } + +- public static boolean regrow(LevelAccessor level, BlockPos pos, BlockState state, Collection directions) { ++ public static boolean regrow(LevelAccessor level, BlockPos pos, IBlockData state, Collection directions) { + boolean flag = false; +- BlockState blockState = Blocks.SCULK_VEIN.defaultBlockState(); ++ IBlockData iblockdata1 = Blocks.SCULK_VEIN.defaultBlockState(); ++ Iterator iterator = directions.iterator(); + +- for (Direction direction : directions) { +- BlockPos blockPos = pos.relative(direction); +- if (canAttachTo(level, direction, blockPos, level.getBlockState(blockPos))) { +- blockState = blockState.setValue(getFaceProperty(direction), Boolean.valueOf(true)); ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ ++ if (canAttachTo(level, enumdirection, blockposition1, level.getBlockState(blockposition1))) { ++ iblockdata1 = (IBlockData) iblockdata1.setValue(getFaceProperty(enumdirection), true); + flag = true; + } + } +@@ -65,27 +72,33 @@ + return false; + } else { + if (!state.getFluidState().isEmpty()) { +- blockState = blockState.setValue(WATERLOGGED, Boolean.valueOf(true)); ++ iblockdata1 = (IBlockData) iblockdata1.setValue(SculkVeinBlock.WATERLOGGED, true); + } + +- level.setBlock(pos, blockState, 3); ++ level.setBlock(pos, iblockdata1, 3); + return true; + } + } + + @Override +- public void onDischarged(LevelAccessor level, BlockState state, BlockPos pos, RandomSource random) { +- if (state.is(this)) { +- for (Direction direction : DIRECTIONS) { +- BooleanProperty faceProperty = getFaceProperty(direction); +- if (state.getValue(faceProperty) && level.getBlockState(pos.relative(direction)).is(Blocks.SCULK)) { +- state = state.setValue(faceProperty, Boolean.valueOf(false)); ++ public void onDischarged(LevelAccessor level, IBlockData state, BlockPos pos, RandomSource random) { ++ if (state.is((Block) this)) { ++ Direction[] aenumdirection = SculkVeinBlock.DIRECTIONS; ++ int i = aenumdirection.length; ++ ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ BooleanProperty blockstateboolean = getFaceProperty(enumdirection); ++ ++ if ((Boolean) state.getValue(blockstateboolean) && level.getBlockState(pos.relative(enumdirection)).is(Blocks.SCULK)) { ++ state = (IBlockData) state.setValue(blockstateboolean, false); + } + } + + if (!hasAnyFace(state)) { +- FluidState fluidState = level.getFluidState(pos); +- state = (fluidState.isEmpty() ? Blocks.AIR : Blocks.WATER).defaultBlockState(); ++ FluidState fluid = level.getFluidState(pos); ++ ++ state = (fluid.isEmpty() ? Blocks.AIR : Blocks.WATER).defaultBlockState(); + } + + level.setBlock(pos, state, 3); +@@ -94,38 +107,47 @@ + } + + @Override +- public int attemptUseCharge( +- SculkSpreader.ChargeCursor cursor, LevelAccessor level, BlockPos pos, RandomSource random, SculkSpreader spreader, boolean shouldConvertBlocks +- ) { +- if (shouldConvertBlocks && this.attemptPlaceSculk(spreader, level, cursor.getPos(), random)) { +- return cursor.getCharge() - 1; +- } else { +- return random.nextInt(spreader.chargeDecayRate()) == 0 ? Mth.floor((float)cursor.getCharge() * 0.5F) : cursor.getCharge(); +- } ++ public int attemptUseCharge(SculkSpreader.ChargeCursor cursor, LevelAccessor level, BlockPos pos, RandomSource random, SculkSpreader spreader, boolean shouldConvertBlocks) { ++ // CraftBukkit - add source block ++ return shouldConvertBlocks && this.attemptPlaceSculk(spreader, level, cursor.getPos(), random, pos) ? cursor.getCharge() - 1 : (random.nextInt(spreader.chargeDecayRate()) == 0 ? Mth.floor((float) cursor.getCharge() * 0.5F) : cursor.getCharge()); + } + +- private boolean attemptPlaceSculk(SculkSpreader spreader, LevelAccessor level, BlockPos pos, RandomSource random) { +- BlockState blockState = level.getBlockState(pos); +- TagKey tagKey = spreader.replaceableBlocks(); ++ private boolean attemptPlaceSculk(SculkSpreader sculkspreader, LevelAccessor generatoraccess, BlockPos blockposition, RandomSource randomsource, BlockPos sourceBlock) { // CraftBukkit ++ IBlockData iblockdata = generatoraccess.getBlockState(blockposition); ++ TagKey tagkey = sculkspreader.replaceableBlocks(); ++ Iterator iterator = Direction.allShuffled(randomsource).iterator(); + +- for (Direction direction : Direction.allShuffled(random)) { +- if (hasFace(blockState, direction)) { +- BlockPos blockPos = pos.relative(direction); +- BlockState blockState1 = level.getBlockState(blockPos); +- if (blockState1.is(tagKey)) { +- BlockState blockState2 = Blocks.SCULK.defaultBlockState(); +- level.setBlock(blockPos, blockState2, 3); +- Block.pushEntitiesUp(blockState1, blockState2, level, blockPos); +- level.playSound(null, blockPos, SoundEvents.SCULK_BLOCK_SPREAD, SoundSource.BLOCKS, 1.0F, 1.0F); +- this.veinSpreader.spreadAll(blockState2, level, blockPos, spreader.isWorldGeneration()); +- Direction opposite = direction.getOpposite(); ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); + +- for (Direction direction1 : DIRECTIONS) { +- if (direction1 != opposite) { +- BlockPos blockPos1 = blockPos.relative(direction1); +- BlockState blockState3 = level.getBlockState(blockPos1); +- if (blockState3.is(this)) { +- this.onDischarged(level, blockState3, blockPos1, random); ++ if (hasFace(iblockdata, enumdirection)) { ++ BlockPos blockposition1 = blockposition.relative(enumdirection); ++ IBlockData iblockdata1 = generatoraccess.getBlockState(blockposition1); ++ ++ if (iblockdata1.is(tagkey)) { ++ IBlockData iblockdata2 = Blocks.SCULK.defaultBlockState(); ++ ++ // CraftBukkit start - Call BlockSpreadEvent ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(generatoraccess, sourceBlock, blockposition1, iblockdata2, 3)) { ++ return false; ++ } ++ // CraftBukkit end ++ Block.pushEntitiesUp(iblockdata1, iblockdata2, generatoraccess, blockposition1); ++ generatoraccess.playSound((Player) null, blockposition1, SoundEvents.SCULK_BLOCK_SPREAD, SoundSource.BLOCKS, 1.0F, 1.0F); ++ this.veinSpreader.spreadAll(iblockdata2, generatoraccess, blockposition1, sculkspreader.isWorldGeneration()); ++ Direction enumdirection1 = enumdirection.getOpposite(); ++ Direction[] aenumdirection = SculkVeinBlock.DIRECTIONS; ++ int i = aenumdirection.length; ++ ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection2 = aenumdirection[j]; ++ ++ if (enumdirection2 != enumdirection1) { ++ BlockPos blockposition2 = blockposition1.relative(enumdirection2); ++ IBlockData iblockdata3 = generatoraccess.getBlockState(blockposition2); ++ ++ if (iblockdata3.is((Block) this)) { ++ this.onDischarged(generatoraccess, iblockdata3, blockposition2, randomsource); + } + } + } +@@ -138,12 +160,17 @@ + return false; + } + +- public static boolean hasSubstrateAccess(LevelAccessor level, BlockState state, BlockPos pos) { ++ public static boolean hasSubstrateAccess(LevelAccessor level, IBlockData state, BlockPos pos) { + if (!state.is(Blocks.SCULK_VEIN)) { + return false; + } else { +- for (Direction direction : DIRECTIONS) { +- if (hasFace(state, direction) && level.getBlockState(pos.relative(direction)).is(BlockTags.SCULK_REPLACEABLE)) { ++ Direction[] aenumdirection = SculkVeinBlock.DIRECTIONS; ++ int i = aenumdirection.length; ++ ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ ++ if (hasFace(state, enumdirection) && level.getBlockState(pos.relative(enumdirection)).is(BlockTags.SCULK_REPLACEABLE)) { + return true; + } + } +@@ -153,53 +180,55 @@ + } + + @Override +- public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { +- if (state.getValue(WATERLOGGED)) { +- level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); ++ public IBlockData updateShape(IBlockData state, Direction direction, IBlockData neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { ++ if ((Boolean) state.getValue(SculkVeinBlock.WATERLOGGED)) { ++ level.scheduleTick(pos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + + return super.updateShape(state, direction, neighborState, level, pos, neighborPos); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { + super.createBlockStateDefinition(builder); +- builder.add(WATERLOGGED); ++ builder.add(SculkVeinBlock.WATERLOGGED); + } + + @Override +- public boolean canBeReplaced(BlockState state, BlockPlaceContext useContext) { ++ public boolean canBeReplaced(IBlockData state, BlockPlaceContext useContext) { + return !useContext.getItemInHand().is(Items.SCULK_VEIN) || super.canBeReplaced(state, useContext); + } + + @Override +- public FluidState getFluidState(BlockState state) { +- return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(SculkVeinBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + +- class SculkVeinSpreaderConfig extends MultifaceSpreader.DefaultSpreaderConfig { ++ private class SculkVeinSpreaderConfig extends MultifaceSpreader.DefaultSpreaderConfig { ++ + private final MultifaceSpreader.SpreadType[] spreadTypes; + +- public SculkVeinSpreaderConfig(MultifaceSpreader.SpreadType... spreadTypes) { ++ public SculkVeinSpreaderConfig(MultifaceSpreader.SpreadType... amultifacespreader_e) { + super(SculkVeinBlock.this); +- this.spreadTypes = spreadTypes; ++ this.spreadTypes = amultifacespreader_e; + } + + @Override +- public boolean stateCanBeReplaced(BlockGetter level, BlockPos pos, BlockPos spreadPos, Direction direction, BlockState state) { +- BlockState blockState = level.getBlockState(spreadPos.relative(direction)); +- if (!blockState.is(Blocks.SCULK) && !blockState.is(Blocks.SCULK_CATALYST) && !blockState.is(Blocks.MOVING_PISTON)) { ++ public boolean stateCanBeReplaced(BlockGetter level, BlockPos pos, BlockPos spreadPos, Direction direction, IBlockData state) { ++ IBlockData iblockdata1 = level.getBlockState(spreadPos.relative(direction)); ++ ++ if (!iblockdata1.is(Blocks.SCULK) && !iblockdata1.is(Blocks.SCULK_CATALYST) && !iblockdata1.is(Blocks.MOVING_PISTON)) { + if (pos.distManhattan(spreadPos) == 2) { +- BlockPos blockPos = pos.relative(direction.getOpposite()); +- if (level.getBlockState(blockPos).isFaceSturdy(level, blockPos, direction)) { ++ BlockPos blockposition2 = pos.relative(direction.getOpposite()); ++ ++ if (level.getBlockState(blockposition2).isFaceSturdy(level, blockposition2, direction)) { + return false; + } + } + +- FluidState fluidState = state.getFluidState(); +- return (fluidState.isEmpty() || fluidState.is(Fluids.WATER)) +- && !state.is(BlockTags.FIRE) +- && (state.canBeReplaced() || super.stateCanBeReplaced(level, pos, spreadPos, direction, state)); ++ FluidState fluid = state.getFluidState(); ++ ++ return !fluid.isEmpty() && !fluid.is((Fluid) Fluids.WATER) ? false : (state.is(BlockTags.FIRE) ? false : state.canBeReplaced() || super.stateCanBeReplaced(level, pos, spreadPos, direction, state)); + } else { + return false; + } +@@ -211,7 +240,7 @@ + } + + @Override +- public boolean isOtherBlockValidAsSource(BlockState otherBlock) { ++ public boolean isOtherBlockValidAsSource(IBlockData otherBlock) { + return !otherBlock.is(Blocks.SCULK_VEIN); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/SignBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SignBlock.java.patch new file mode 100644 index 0000000000..eff8385b56 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SignBlock.java.patch @@ -0,0 +1,239 @@ +--- a/net/minecraft/world/level/block/SignBlock.java ++++ b/net/minecraft/world/level/block/SignBlock.java +@@ -7,11 +7,10 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.network.chat.CommonComponents; +-import net.minecraft.network.chat.Component; +-import net.minecraft.network.chat.contents.PlainTextContents; ++import net.minecraft.network.chat.contents.LiteralContents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Item; +@@ -26,11 +25,12 @@ + import net.minecraft.world.level.block.entity.SignBlockEntity; + import net.minecraft.world.level.block.entity.SignText; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.block.state.properties.WoodType; + import net.minecraft.world.level.gameevent.GameEvent; ++import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.BlockHitResult; +@@ -39,80 +39,92 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + + public abstract class SignBlock extends BaseEntityBlock implements SimpleWaterloggedBlock { ++ + public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; + protected static final float AABB_OFFSET = 4.0F; +- protected static final VoxelShape SHAPE = Block.box(4.0, 0.0, 4.0, 12.0, 16.0, 12.0); ++ protected static final VoxelShape SHAPE = Block.box(4.0D, 0.0D, 4.0D, 12.0D, 16.0D, 12.0D); + private final WoodType type; + +- protected SignBlock(WoodType woodType, BlockBehaviour.Properties properties) { +- super(properties); +- this.type = woodType; ++ protected SignBlock(WoodType blockpropertywood, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info); ++ this.type = blockpropertywood; + } + + @Override + protected abstract MapCodec codec(); + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- if (state.getValue(WATERLOGGED)) { +- level.scheduleTick(currentPos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if ((Boolean) state.getValue(SignBlock.WATERLOGGED)) { ++ level.scheduleTick(currentPos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + + return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPE; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return SignBlock.SHAPE; + } + + @Override +- public boolean isPossibleToRespawnInThis(BlockState state) { ++ public boolean isPossibleToRespawnInThis(IBlockData state) { + return true; + } + + @Override +- public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { + return new SignBlockEntity(pos, state); + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { +- ItemStack itemInHand = player.getItemInHand(hand); +- Item item = itemInHand.getItem(); +- SignApplicator signApplicator1 = itemInHand.getItem() instanceof SignApplicator signApplicator ? signApplicator : null; +- boolean flag = signApplicator1 != null && player.mayBuild(); +- if (level.getBlockEntity(pos) instanceof SignBlockEntity signBlockEntity) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ Item item = itemstack.getItem(); ++ Item item1 = itemstack.getItem(); ++ SignApplicator signapplicator; ++ ++ if (item1 instanceof SignApplicator) { ++ SignApplicator signapplicator1 = (SignApplicator) item1; ++ ++ signapplicator = signapplicator1; ++ } else { ++ signapplicator = null; ++ } ++ ++ SignApplicator signapplicator2 = signapplicator; ++ boolean flag = signapplicator2 != null && player.mayBuild(); ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof SignBlockEntity) { ++ SignBlockEntity tileentitysign = (SignBlockEntity) tileentity; ++ + if (!level.isClientSide) { +- boolean isFacingFrontText = signBlockEntity.isFacingFrontText(player); +- SignText text = signBlockEntity.getText(isFacingFrontText); +- boolean flag1 = signBlockEntity.executeClickCommandsIfPresent(player, level, pos, isFacingFrontText); +- if (signBlockEntity.isWaxed()) { +- level.playSound(null, signBlockEntity.getBlockPos(), signBlockEntity.getSignInteractionFailedSoundEvent(), SoundSource.BLOCKS); ++ boolean flag1 = tileentitysign.isFacingFrontText(player); ++ SignText signtext = tileentitysign.getText(flag1); ++ boolean flag2 = tileentitysign.executeClickCommandsIfPresent(player, level, pos, flag1); ++ ++ if (tileentitysign.isWaxed()) { ++ level.playSound((Player) null, tileentitysign.getBlockPos(), tileentitysign.getSignInteractionFailedSoundEvent(), SoundSource.BLOCKS); + return this.getInteractionResult(flag); +- } else if (flag +- && !this.otherPlayerIsEditingSign(player, signBlockEntity) +- && signApplicator1.canApplyToSign(text, player) +- && signApplicator1.tryApplyToSign(level, signBlockEntity, isFacingFrontText, player)) { ++ } else if (flag && !this.otherPlayerIsEditingSign(player, tileentitysign) && signapplicator2.canApplyToSign(signtext, player) && signapplicator2.tryApplyToSign(level, tileentitysign, flag1, player)) { + if (!player.isCreative()) { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + +- level.gameEvent(GameEvent.BLOCK_CHANGE, signBlockEntity.getBlockPos(), GameEvent.Context.of(player, signBlockEntity.getBlockState())); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, tileentitysign.getBlockPos(), GameEvent.Context.of(player, tileentitysign.getBlockState())); + player.awardStat(Stats.ITEM_USED.get(item)); + return InteractionResult.SUCCESS; +- } else if (flag1) { ++ } else if (flag2) { + return InteractionResult.SUCCESS; +- } else if (!this.otherPlayerIsEditingSign(player, signBlockEntity) +- && player.mayBuild() +- && this.hasEditableText(player, signBlockEntity, isFacingFrontText)) { +- this.openTextEdit(player, signBlockEntity, isFacingFrontText); ++ } else if (!this.otherPlayerIsEditingSign(player, tileentitysign) && player.mayBuild() && this.hasEditableText(player, tileentitysign, flag1)) { ++ this.openTextEdit(player, tileentitysign, flag1, org.bukkit.event.player.PlayerSignOpenEvent.Cause.INTERACT); // CraftBukkit + return this.getInteractionResult(flag); + } else { + return InteractionResult.PASS; + } + } else { +- return !flag && !signBlockEntity.isWaxed() ? InteractionResult.CONSUME : InteractionResult.SUCCESS; ++ return !flag && !tileentitysign.isWaxed() ? InteractionResult.CONSUME : InteractionResult.SUCCESS; + } + } else { + return InteractionResult.PASS; +@@ -124,20 +136,22 @@ + } + + private boolean hasEditableText(Player player, SignBlockEntity signEntity, boolean isFrontText) { +- SignText text = signEntity.getText(isFrontText); +- return Arrays.stream(text.getMessages(player.isTextFilteringEnabled())) +- .allMatch(line -> line.equals(CommonComponents.EMPTY) || line.getContents() instanceof PlainTextContents); ++ SignText signtext = signEntity.getText(isFrontText); ++ ++ return Arrays.stream(signtext.getMessages(player.isTextFilteringEnabled())).allMatch((ichatbasecomponent) -> { ++ return ichatbasecomponent.equals(CommonComponents.EMPTY) || ichatbasecomponent.getContents() instanceof LiteralContents; ++ }); + } + +- public abstract float getYRotationDegrees(BlockState state); ++ public abstract float getYRotationDegrees(IBlockData state); + +- public Vec3 getSignHitboxCenterPosition(BlockState state) { +- return new Vec3(0.5, 0.5, 0.5); ++ public Vec3 getSignHitboxCenterPosition(IBlockData state) { ++ return new Vec3(0.5D, 0.5D, 0.5D); + } + + @Override +- public FluidState getFluidState(BlockState state) { +- return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(SignBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + public WoodType type() { +@@ -145,29 +159,40 @@ + } + + public static WoodType getWoodType(Block block) { +- WoodType woodType; ++ WoodType blockpropertywood; ++ + if (block instanceof SignBlock) { +- woodType = ((SignBlock)block).type(); ++ blockpropertywood = ((SignBlock) block).type(); + } else { +- woodType = WoodType.OAK; ++ blockpropertywood = WoodType.OAK; + } + +- return woodType; ++ return blockpropertywood; + } + + public void openTextEdit(Player player, SignBlockEntity signEntity, boolean isFrontText) { +- signEntity.setAllowedPlayerEditor(player.getUUID()); +- player.openTextEdit(signEntity, isFrontText); ++ // Craftbukkit start ++ openTextEdit(player, signEntity, isFrontText, org.bukkit.event.player.PlayerSignOpenEvent.Cause.UNKNOWN); + } + ++ public void openTextEdit(Player entityhuman, SignBlockEntity tileentitysign, boolean flag, org.bukkit.event.player.PlayerSignOpenEvent.Cause cause) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerSignOpenEvent(entityhuman, tileentitysign, flag, cause)) { ++ return; ++ } ++ // Craftbukkit end ++ tileentitysign.setAllowedPlayerEditor(entityhuman.getUUID()); ++ entityhuman.openTextEdit(tileentitysign, flag); ++ } ++ + private boolean otherPlayerIsEditingSign(Player player, SignBlockEntity signEntity) { +- UUID playerWhoMayEdit = signEntity.getPlayerWhoMayEdit(); +- return playerWhoMayEdit != null && !playerWhoMayEdit.equals(player.getUUID()); ++ UUID uuid = signEntity.getPlayerWhoMayEdit(); ++ ++ return uuid != null && !uuid.equals(player.getUUID()); + } + + @Nullable + @Override +- public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { +- return createTickerHelper(blockEntityType, BlockEntityType.SIGN, SignBlockEntity::tick); ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { ++ return null; // Craftbukkit - remove unnecessary sign ticking + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/SnowLayerBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SnowLayerBlock.java.patch new file mode 100644 index 0000000000..f0a4428754 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SnowLayerBlock.java.patch @@ -0,0 +1,185 @@ +--- a/net/minecraft/world/level/block/SnowLayerBlock.java ++++ b/net/minecraft/world/level/block/SnowLayerBlock.java +@@ -9,51 +9,42 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.world.item.context.BlockPlaceContext; + import net.minecraft.world.level.BlockGetter; ++import net.minecraft.world.level.EnumSkyBlock; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; +-import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; + + public class SnowLayerBlock extends Block { ++ + public static final MapCodec CODEC = simpleCodec(SnowLayerBlock::new); + public static final int MAX_HEIGHT = 8; + public static final IntegerProperty LAYERS = BlockStateProperties.LAYERS; +- protected static final VoxelShape[] SHAPE_BY_LAYER = new VoxelShape[]{ +- Shapes.empty(), +- Block.box(0.0, 0.0, 0.0, 16.0, 2.0, 16.0), +- Block.box(0.0, 0.0, 0.0, 16.0, 4.0, 16.0), +- Block.box(0.0, 0.0, 0.0, 16.0, 6.0, 16.0), +- Block.box(0.0, 0.0, 0.0, 16.0, 8.0, 16.0), +- Block.box(0.0, 0.0, 0.0, 16.0, 10.0, 16.0), +- Block.box(0.0, 0.0, 0.0, 16.0, 12.0, 16.0), +- Block.box(0.0, 0.0, 0.0, 16.0, 14.0, 16.0), +- Block.box(0.0, 0.0, 0.0, 16.0, 16.0, 16.0) +- }; ++ protected static final VoxelShape[] SHAPE_BY_LAYER = new VoxelShape[]{Shapes.empty(), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 2.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 4.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 6.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 8.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 10.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 12.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 14.0D, 16.0D), Block.box(0.0D, 0.0D, 0.0D, 16.0D, 16.0D, 16.0D)}; + public static final int HEIGHT_IMPASSABLE = 5; + + @Override + public MapCodec codec() { +- return CODEC; ++ return SnowLayerBlock.CODEC; + } + + protected SnowLayerBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(LAYERS, Integer.valueOf(1))); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(SnowLayerBlock.LAYERS, 1)); + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + switch (type) { + case LAND: +- return state.getValue(LAYERS) < 5; ++ return (Integer) state.getValue(SnowLayerBlock.LAYERS) < 5; + case WATER: + return false; + case AIR: +@@ -64,83 +55,84 @@ + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPE_BY_LAYER[state.getValue(LAYERS)]; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return SnowLayerBlock.SHAPE_BY_LAYER[(Integer) state.getValue(SnowLayerBlock.LAYERS)]; + } + + @Override +- public VoxelShape getCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPE_BY_LAYER[state.getValue(LAYERS) - 1]; ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return SnowLayerBlock.SHAPE_BY_LAYER[(Integer) state.getValue(SnowLayerBlock.LAYERS) - 1]; + } + + @Override +- public VoxelShape getBlockSupportShape(BlockState state, BlockGetter reader, BlockPos pos) { +- return SHAPE_BY_LAYER[state.getValue(LAYERS)]; ++ public VoxelShape getBlockSupportShape(IBlockData state, BlockGetter reader, BlockPos pos) { ++ return SnowLayerBlock.SHAPE_BY_LAYER[(Integer) state.getValue(SnowLayerBlock.LAYERS)]; + } + + @Override +- public VoxelShape getVisualShape(BlockState state, BlockGetter reader, BlockPos pos, CollisionContext context) { +- return SHAPE_BY_LAYER[state.getValue(LAYERS)]; ++ public VoxelShape getVisualShape(IBlockData state, BlockGetter reader, BlockPos pos, CollisionContext context) { ++ return SnowLayerBlock.SHAPE_BY_LAYER[(Integer) state.getValue(SnowLayerBlock.LAYERS)]; + } + + @Override +- public boolean useShapeForLightOcclusion(BlockState state) { ++ public boolean useShapeForLightOcclusion(IBlockData state) { + return true; + } + + @Override +- public float getShadeBrightness(BlockState state, BlockGetter level, BlockPos pos) { +- return state.getValue(LAYERS) == 8 ? 0.2F : 1.0F; ++ public float getShadeBrightness(IBlockData state, BlockGetter level, BlockPos pos) { ++ return (Integer) state.getValue(SnowLayerBlock.LAYERS) == 8 ? 0.2F : 1.0F; + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { +- BlockState blockState = level.getBlockState(pos.below()); +- return !blockState.is(BlockTags.SNOW_LAYER_CANNOT_SURVIVE_ON) +- && ( +- blockState.is(BlockTags.SNOW_LAYER_CAN_SURVIVE_ON) +- || Block.isFaceFull(blockState.getCollisionShape(level, pos.below()), Direction.UP) +- || blockState.is(this) && blockState.getValue(LAYERS) == 8 +- ); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ IBlockData iblockdata1 = level.getBlockState(pos.below()); ++ ++ return iblockdata1.is(BlockTags.SNOW_LAYER_CANNOT_SURVIVE_ON) ? false : (iblockdata1.is(BlockTags.SNOW_LAYER_CAN_SURVIVE_ON) ? true : Block.isFaceFull(iblockdata1.getCollisionShape(level, pos.below()), Direction.UP) || iblockdata1.is((Block) this) && (Integer) iblockdata1.getValue(SnowLayerBlock.LAYERS) == 8); + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- return !state.canSurvive(level, currentPos) +- ? Blocks.AIR.defaultBlockState() +- : super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ return !state.canSurvive(level, currentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- if (level.getBrightness(LightLayer.BLOCK, pos) > 11) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if (level.getBrightness(EnumSkyBlock.BLOCK, pos) > 11) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.AIR.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + dropResources(state, level, pos); + level.removeBlock(pos, false); + } ++ + } + + @Override +- public boolean canBeReplaced(BlockState state, BlockPlaceContext useContext) { +- int i = state.getValue(LAYERS); +- return !useContext.getItemInHand().is(this.asItem()) || i >= 8 +- ? i == 1 +- : !useContext.replacingClickedOnBlock() || useContext.getClickedFace() == Direction.UP; ++ public boolean canBeReplaced(IBlockData state, BlockPlaceContext useContext) { ++ int i = (Integer) state.getValue(SnowLayerBlock.LAYERS); ++ ++ return useContext.getItemInHand().is(this.asItem()) && i < 8 ? (useContext.replacingClickedOnBlock() ? useContext.getClickedFace() == Direction.UP : true) : i == 1; + } + + @Nullable + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- BlockState blockState = context.getLevel().getBlockState(context.getClickedPos()); +- if (blockState.is(this)) { +- int i = blockState.getValue(LAYERS); +- return blockState.setValue(LAYERS, Integer.valueOf(Math.min(8, i + 1))); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ IBlockData iblockdata = context.getLevel().getBlockState(context.getClickedPos()); ++ ++ if (iblockdata.is((Block) this)) { ++ int i = (Integer) iblockdata.getValue(SnowLayerBlock.LAYERS); ++ ++ return (IBlockData) iblockdata.setValue(SnowLayerBlock.LAYERS, Math.min(8, i + 1)); + } else { + return super.getStateForPlacement(context); + } + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(LAYERS); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(SnowLayerBlock.LAYERS); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/SpawnerBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SpawnerBlock.java.patch new file mode 100644 index 0000000000..731a9ad28a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SpawnerBlock.java.patch @@ -0,0 +1,70 @@ +--- a/net/minecraft/world/level/block/SpawnerBlock.java ++++ b/net/minecraft/world/level/block/SpawnerBlock.java +@@ -16,14 +16,15 @@ + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.SpawnerBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public class SpawnerBlock extends BaseEntityBlock { ++ + public static final MapCodec CODEC = simpleCodec(SpawnerBlock::new); + + @Override + public MapCodec codec() { +- return CODEC; ++ return SpawnerBlock.CODEC; + } + + protected SpawnerBlock(BlockBehaviour.Properties properties) { +@@ -31,30 +32,38 @@ + } + + @Override +- public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { + return new SpawnerBlockEntity(pos, state); + } + + @Nullable + @Override +- public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { +- return createTickerHelper( +- blockEntityType, BlockEntityType.MOB_SPAWNER, level.isClientSide ? SpawnerBlockEntity::clientTick : SpawnerBlockEntity::serverTick +- ); ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { ++ return createTickerHelper(blockEntityType, BlockEntityType.MOB_SPAWNER, level.isClientSide ? SpawnerBlockEntity::clientTick : SpawnerBlockEntity::serverTick); + } + + @Override +- public void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { + super.spawnAfterBreak(state, level, pos, stack, dropExperience); +- if (dropExperience) { +- int i = 15 + level.random.nextInt(15) + level.random.nextInt(15); +- this.popExperience(level, pos, i); ++ // CraftBukkit start - Delegate to getExpDrop ++ } ++ ++ @Override ++ public int getExpDrop(IBlockData iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { ++ if (flag) { ++ int i = 15 + worldserver.random.nextInt(15) + worldserver.random.nextInt(15); ++ ++ // this.popExperience(worldserver, blockposition, i); ++ return i; + } ++ ++ return 0; ++ // CraftBukkit end + } + + @Override +- public RenderShape getRenderShape(BlockState state) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/SpongeBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SpongeBlock.java.patch new file mode 100644 index 0000000000..2fb61bbd53 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SpongeBlock.java.patch @@ -0,0 +1,195 @@ +--- a/net/minecraft/world/level/block/SpongeBlock.java ++++ b/net/minecraft/world/level/block/SpongeBlock.java +@@ -1,19 +1,26 @@ + package net.minecraft.world.level.block; + + import com.mojang.serialization.MapCodec; +-import java.util.function.Consumer; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.tags.FluidTags; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.util.BlockStateListPopulator; ++import org.bukkit.event.block.SpongeAbsorbEvent; ++// CraftBukkit end + + public class SpongeBlock extends Block { ++ + public static final MapCodec CODEC = simpleCodec(SpongeBlock::new); + public static final int MAX_DEPTH = 6; + public static final int MAX_COUNT = 64; +@@ -21,7 +28,7 @@ + + @Override + public MapCodec codec() { +- return CODEC; ++ return SpongeBlock.CODEC; + } + + protected SpongeBlock(BlockBehaviour.Properties properties) { +@@ -29,14 +36,14 @@ + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { + if (!oldState.is(state.getBlock())) { + this.tryAbsorbWater(level, pos); + } + } + + @Override +- public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { + this.tryAbsorbWater(level, pos); + super.neighborChanged(state, level, pos, block, fromPos, isMoving); + } +@@ -44,54 +51,98 @@ + protected void tryAbsorbWater(Level level, BlockPos pos) { + if (this.removeWaterBreadthFirstSearch(level, pos)) { + level.setBlock(pos, Blocks.WET_SPONGE.defaultBlockState(), 2); +- level.playSound(null, pos, SoundEvents.SPONGE_ABSORB, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.playSound((Player) null, pos, SoundEvents.SPONGE_ABSORB, SoundSource.BLOCKS, 1.0F, 1.0F); + } ++ + } + + private boolean removeWaterBreadthFirstSearch(Level level, BlockPos pos) { +- return BlockPos.breadthFirstTraversal( +- pos, +- 6, +- 65, +- (validPos, queueAdder) -> { +- for (Direction direction : ALL_DIRECTIONS) { +- queueAdder.accept(validPos.relative(direction)); ++ BlockStateListPopulator blockList = new BlockStateListPopulator(level); // CraftBukkit - Use BlockStateListPopulator ++ BlockPos.breadthFirstTraversal(pos, 6, 65, (blockposition1, consumer) -> { ++ Direction[] aenumdirection = SpongeBlock.ALL_DIRECTIONS; ++ int i = aenumdirection.length; ++ ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ ++ consumer.accept(blockposition1.relative(enumdirection)); ++ } ++ ++ }, (blockposition1) -> { ++ if (blockposition1.equals(pos)) { ++ return true; ++ } else { ++ // CraftBukkit start ++ IBlockData iblockdata = blockList.getBlockState(blockposition1); ++ FluidState fluid = blockList.getFluidState(blockposition1); ++ // CraftBukkit end ++ ++ if (!fluid.is(FluidTags.WATER)) { ++ return false; ++ } else { ++ Block block = iblockdata.getBlock(); ++ ++ if (block instanceof BucketPickup) { ++ BucketPickup ifluidsource = (BucketPickup) block; ++ ++ if (!ifluidsource.pickupBlock((Player) null, blockList, blockposition1, iblockdata).isEmpty()) { // CraftBukkit ++ return true; ++ } + } +- }, +- currentPos -> { +- if (currentPos.equals(pos)) { +- return true; ++ ++ if (iblockdata.getBlock() instanceof LiquidBlock) { ++ blockList.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3); // CraftBukkit + } else { +- BlockState blockState = level.getBlockState(currentPos); +- FluidState fluidState = level.getFluidState(currentPos); +- if (!fluidState.is(FluidTags.WATER)) { ++ if (!iblockdata.is(Blocks.KELP) && !iblockdata.is(Blocks.KELP_PLANT) && !iblockdata.is(Blocks.SEAGRASS) && !iblockdata.is(Blocks.TALL_SEAGRASS)) { + return false; +- } else { +- if (blockState.getBlock() instanceof BucketPickup bucketPickup +- && !bucketPickup.pickupBlock(null, level, currentPos, blockState).isEmpty()) { +- return true; +- } +- +- if (blockState.getBlock() instanceof LiquidBlock) { +- level.setBlock(currentPos, Blocks.AIR.defaultBlockState(), 3); +- } else { +- if (!blockState.is(Blocks.KELP) +- && !blockState.is(Blocks.KELP_PLANT) +- && !blockState.is(Blocks.SEAGRASS) +- && !blockState.is(Blocks.TALL_SEAGRASS)) { +- return false; +- } +- +- BlockEntity blockEntity = blockState.hasBlockEntity() ? level.getBlockEntity(currentPos) : null; +- dropResources(blockState, level, currentPos, blockEntity); +- level.setBlock(currentPos, Blocks.AIR.defaultBlockState(), 3); +- } +- +- return true; + } ++ ++ // CraftBukkit start ++ // TileEntity tileentity = iblockdata.hasBlockEntity() ? world.getBlockEntity(blockposition1) : null; ++ ++ // dropResources(iblockdata, world, blockposition1, tileentity); ++ blockList.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3); ++ // CraftBukkit end + } ++ ++ return true; + } +- ) +- > 1; ++ } ++ }); ++ // CraftBukkit start ++ List blocks = blockList.getList(); // Is a clone ++ if (!blocks.isEmpty()) { ++ final org.bukkit.block.Block bblock = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ ++ SpongeAbsorbEvent event = new SpongeAbsorbEvent(bblock, (List) (List) blocks); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ for (CraftBlockState block : blocks) { ++ BlockPos blockposition1 = block.getPosition(); ++ IBlockData iblockdata = level.getBlockState(blockposition1); ++ FluidState fluid = level.getFluidState(blockposition1); ++ ++ if (fluid.is(FluidTags.WATER)) { ++ if (iblockdata.getBlock() instanceof BucketPickup && !((BucketPickup) iblockdata.getBlock()).pickupBlock((Player) null, blockList, blockposition1, iblockdata).isEmpty()) { ++ // NOP ++ } else if (iblockdata.getBlock() instanceof LiquidBlock) { ++ // NOP ++ } else if (iblockdata.is(Blocks.KELP) || iblockdata.is(Blocks.KELP_PLANT) || iblockdata.is(Blocks.SEAGRASS) || iblockdata.is(Blocks.TALL_SEAGRASS)) { ++ BlockEntity tileentity = iblockdata.hasBlockEntity() ? level.getBlockEntity(blockposition1) : null; ++ ++ dropResources(iblockdata, level, blockposition1, tileentity); ++ } ++ } ++ level.setBlock(blockposition1, block.getHandle(), block.getFlag()); ++ } ++ ++ return true; ++ } ++ return false; ++ // CraftBukkit end + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java.patch new file mode 100644 index 0000000000..777fbd096e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java.patch @@ -0,0 +1,83 @@ +--- a/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java ++++ b/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java +@@ -8,52 +8,61 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.lighting.LightEngine; + + public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock { ++ + protected SpreadingSnowyDirtBlock(BlockBehaviour.Properties properties) { + super(properties); + } + +- private static boolean canBeGrass(BlockState state, LevelReader levelReader, BlockPos pos) { +- BlockPos blockPos = pos.above(); +- BlockState blockState = levelReader.getBlockState(blockPos); +- if (blockState.is(Blocks.SNOW) && blockState.getValue(SnowLayerBlock.LAYERS) == 1) { ++ private static boolean canBeGrass(IBlockData state, LevelReader levelReader, BlockPos pos) { ++ BlockPos blockposition1 = pos.above(); ++ IBlockData iblockdata1 = levelReader.getBlockState(blockposition1); ++ ++ if (iblockdata1.is(Blocks.SNOW) && (Integer) iblockdata1.getValue(SnowLayerBlock.LAYERS) == 1) { + return true; +- } else if (blockState.getFluidState().getAmount() == 8) { ++ } else if (iblockdata1.getFluidState().getAmount() == 8) { + return false; + } else { +- int lightBlockInto = LightEngine.getLightBlockInto( +- levelReader, state, pos, blockState, blockPos, Direction.UP, blockState.getLightBlock(levelReader, blockPos) +- ); +- return lightBlockInto < levelReader.getMaxLightLevel(); ++ int i = LightEngine.getLightBlockInto(levelReader, state, pos, iblockdata1, blockposition1, Direction.UP, iblockdata1.getLightBlock(levelReader, blockposition1)); ++ ++ return i < levelReader.getMaxLightLevel(); + } + } + + @Override + protected abstract MapCodec codec(); + +- private static boolean canPropagate(BlockState state, LevelReader level, BlockPos pos) { +- BlockPos blockPos = pos.above(); +- return canBeGrass(state, level, pos) && !level.getFluidState(blockPos).is(FluidTags.WATER); ++ private static boolean canPropagate(IBlockData state, LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.above(); ++ ++ return canBeGrass(state, level, pos) && !level.getFluidState(blockposition1).is(FluidTags.WATER); + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (!canBeGrass(state, level, pos)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + level.setBlockAndUpdate(pos, Blocks.DIRT.defaultBlockState()); + } else { + if (level.getMaxLocalRawBrightness(pos.above()) >= 9) { +- BlockState blockState = this.defaultBlockState(); ++ IBlockData iblockdata1 = this.defaultBlockState(); + +- for (int i = 0; i < 4; i++) { +- BlockPos blockPos = pos.offset(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1); +- if (level.getBlockState(blockPos).is(Blocks.DIRT) && canPropagate(blockState, level, blockPos)) { +- level.setBlockAndUpdate(blockPos, blockState.setValue(SNOWY, Boolean.valueOf(level.getBlockState(blockPos.above()).is(Blocks.SNOW)))); ++ for (int i = 0; i < 4; ++i) { ++ BlockPos blockposition1 = pos.offset(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1); ++ ++ if (level.getBlockState(blockposition1).is(Blocks.DIRT) && canPropagate(iblockdata1, level, blockposition1)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition1, (IBlockData) iblockdata1.setValue(SpreadingSnowyDirtBlock.SNOWY, level.getBlockState(blockposition1.above()).is(Blocks.SNOW))); // CraftBukkit + } + } + } ++ + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/StemBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/StemBlock.java.patch new file mode 100644 index 0000000000..e3ffac8ec4 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/StemBlock.java.patch @@ -0,0 +1,194 @@ +--- a/net/minecraft/world/level/block/StemBlock.java ++++ b/net/minecraft/world/level/block/StemBlock.java +@@ -3,7 +3,6 @@ + import com.mojang.datafixers.DataFixUtils; + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import java.util.Optional; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +@@ -17,120 +16,125 @@ + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.BlockGetter; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class StemBlock extends BushBlock implements BonemealableBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group( +- ResourceKey.codec(Registries.BLOCK).fieldOf("fruit").forGetter(stemBlock -> stemBlock.fruit), +- ResourceKey.codec(Registries.BLOCK).fieldOf("attached_stem").forGetter(stemBlock -> stemBlock.attachedStem), +- ResourceKey.codec(Registries.ITEM).fieldOf("seed").forGetter(stemBlock -> stemBlock.seed), +- propertiesCodec() +- ) +- .apply(instance, StemBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(ResourceKey.codec(Registries.BLOCK).fieldOf("fruit").forGetter((blockstem) -> { ++ return blockstem.fruit; ++ }), ResourceKey.codec(Registries.BLOCK).fieldOf("attached_stem").forGetter((blockstem) -> { ++ return blockstem.attachedStem; ++ }), ResourceKey.codec(Registries.ITEM).fieldOf("seed").forGetter((blockstem) -> { ++ return blockstem.seed; ++ }), propertiesCodec()).apply(instance, StemBlock::new); ++ }); + public static final int MAX_AGE = 7; + public static final IntegerProperty AGE = BlockStateProperties.AGE_7; + protected static final float AABB_OFFSET = 1.0F; +- protected static final VoxelShape[] SHAPE_BY_AGE = new VoxelShape[]{ +- Block.box(7.0, 0.0, 7.0, 9.0, 2.0, 9.0), +- Block.box(7.0, 0.0, 7.0, 9.0, 4.0, 9.0), +- Block.box(7.0, 0.0, 7.0, 9.0, 6.0, 9.0), +- Block.box(7.0, 0.0, 7.0, 9.0, 8.0, 9.0), +- Block.box(7.0, 0.0, 7.0, 9.0, 10.0, 9.0), +- Block.box(7.0, 0.0, 7.0, 9.0, 12.0, 9.0), +- Block.box(7.0, 0.0, 7.0, 9.0, 14.0, 9.0), +- Block.box(7.0, 0.0, 7.0, 9.0, 16.0, 9.0) +- }; ++ protected static final VoxelShape[] SHAPE_BY_AGE = new VoxelShape[]{Block.box(7.0D, 0.0D, 7.0D, 9.0D, 2.0D, 9.0D), Block.box(7.0D, 0.0D, 7.0D, 9.0D, 4.0D, 9.0D), Block.box(7.0D, 0.0D, 7.0D, 9.0D, 6.0D, 9.0D), Block.box(7.0D, 0.0D, 7.0D, 9.0D, 8.0D, 9.0D), Block.box(7.0D, 0.0D, 7.0D, 9.0D, 10.0D, 9.0D), Block.box(7.0D, 0.0D, 7.0D, 9.0D, 12.0D, 9.0D), Block.box(7.0D, 0.0D, 7.0D, 9.0D, 14.0D, 9.0D), Block.box(7.0D, 0.0D, 7.0D, 9.0D, 16.0D, 9.0D)}; + private final ResourceKey fruit; + private final ResourceKey attachedStem; + private final ResourceKey seed; + + @Override + public MapCodec codec() { +- return CODEC; ++ return StemBlock.CODEC; + } + +- protected StemBlock(ResourceKey resourceKey, ResourceKey resourceKey1, ResourceKey resourceKey2, BlockBehaviour.Properties properties) { +- super(properties); +- this.fruit = resourceKey; +- this.attachedStem = resourceKey1; +- this.seed = resourceKey2; +- this.registerDefaultState(this.stateDefinition.any().setValue(AGE, Integer.valueOf(0))); ++ protected StemBlock(ResourceKey resourcekey, ResourceKey resourcekey1, ResourceKey resourcekey2, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info); ++ this.fruit = resourcekey; ++ this.attachedStem = resourcekey1; ++ this.seed = resourcekey2; ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(StemBlock.AGE, 0)); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPE_BY_AGE[state.getValue(AGE)]; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return StemBlock.SHAPE_BY_AGE[(Integer) state.getValue(StemBlock.AGE)]; + } + + @Override +- protected boolean mayPlaceOn(BlockState state, BlockGetter level, BlockPos pos) { ++ protected boolean mayPlaceOn(IBlockData state, BlockGetter level, BlockPos pos) { + return state.is(Blocks.FARMLAND); + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (level.getRawBrightness(pos, 0) >= 9) { +- float growthSpeed = CropBlock.getGrowthSpeed(this, level, pos); +- if (random.nextInt((int)(25.0F / growthSpeed) + 1) == 0) { +- int i = state.getValue(AGE); ++ float f = CropBlock.getGrowthSpeed(this, level, pos); ++ ++ if (random.nextInt((int) (25.0F / f) + 1) == 0) { ++ int i = (Integer) state.getValue(StemBlock.AGE); ++ + if (i < 7) { +- state = state.setValue(AGE, Integer.valueOf(i + 1)); +- level.setBlock(pos, state, 2); ++ state = (IBlockData) state.setValue(StemBlock.AGE, i + 1); ++ CraftEventFactory.handleBlockGrowEvent(level, pos, state, 2); // CraftBukkit + } else { +- Direction randomDirection = Direction.Plane.HORIZONTAL.getRandomDirection(random); +- BlockPos blockPos = pos.relative(randomDirection); +- BlockState blockState = level.getBlockState(blockPos.below()); +- if (level.getBlockState(blockPos).isAir() && (blockState.is(Blocks.FARMLAND) || blockState.is(BlockTags.DIRT))) { +- Registry registry = level.registryAccess().registryOrThrow(Registries.BLOCK); +- Optional optional = registry.getOptional(this.fruit); +- Optional optional1 = registry.getOptional(this.attachedStem); ++ Direction enumdirection = Direction.Plane.HORIZONTAL.getRandomDirection(random); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1.below()); ++ ++ if (level.getBlockState(blockposition1).isAir() && (iblockdata1.is(Blocks.FARMLAND) || iblockdata1.is(BlockTags.DIRT))) { ++ Registry iregistry = level.registryAccess().registryOrThrow(Registries.BLOCK); ++ Optional optional = iregistry.getOptional(this.fruit); ++ Optional optional1 = iregistry.getOptional(this.attachedStem); ++ + if (optional.isPresent() && optional1.isPresent()) { +- level.setBlockAndUpdate(blockPos, optional.get().defaultBlockState()); +- level.setBlockAndUpdate(pos, optional1.get().defaultBlockState().setValue(HorizontalDirectionalBlock.FACING, randomDirection)); ++ // CraftBukkit start ++ if (!CraftEventFactory.handleBlockGrowEvent(level, blockposition1, ((Block) optional.get()).defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end ++ level.setBlockAndUpdate(pos, (IBlockData) ((Block) optional1.get()).defaultBlockState().setValue(HorizontalDirectionalBlock.FACING, enumdirection)); + } + } + } + } ++ + } + } + + @Override +- public ItemStack getCloneItemStack(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { +- return new ItemStack(DataFixUtils.orElse(levelReader.registryAccess().registryOrThrow(Registries.ITEM).getOptional(this.seed), this)); ++ public ItemStack getCloneItemStack(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ return new ItemStack((IMaterial) DataFixUtils.orElse(iworldreader.registryAccess().registryOrThrow(Registries.ITEM).getOptional(this.seed), this)); + } + + @Override +- public boolean isValidBonemealTarget(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { +- return blockState.getValue(AGE) != 7; ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ return (Integer) iblockdata.getValue(StemBlock.AGE) != 7; + } + + @Override +- public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, BlockState state) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return true; + } + + @Override +- public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) { +- int min = Math.min(7, state.getValue(AGE) + Mth.nextInt(level.random, 2, 5)); +- BlockState blockState = state.setValue(AGE, Integer.valueOf(min)); +- level.setBlock(pos, blockState, 2); +- if (min == 7) { +- blockState.randomTick(level, pos, level.random); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ int i = Math.min(7, (Integer) state.getValue(StemBlock.AGE) + Mth.nextInt(level.random, 2, 5)); ++ IBlockData iblockdata1 = (IBlockData) state.setValue(StemBlock.AGE, i); ++ ++ CraftEventFactory.handleBlockGrowEvent(level, pos, iblockdata1, 2); // CraftBukkit ++ if (i == 7) { ++ iblockdata1.randomTick(level, pos, level.random); + } ++ + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(AGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(StemBlock.AGE); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/SugarCaneBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SugarCaneBlock.java.patch new file mode 100644 index 0000000000..741ee0345e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SugarCaneBlock.java.patch @@ -0,0 +1,140 @@ +--- a/net/minecraft/world/level/block/SugarCaneBlock.java ++++ b/net/minecraft/world/level/block/SugarCaneBlock.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.block; + + import com.mojang.serialization.MapCodec; ++import java.util.Iterator; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.server.level.ServerLevel; +@@ -11,7 +12,7 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; +@@ -20,76 +21,84 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + + public class SugarCaneBlock extends Block { ++ + public static final MapCodec CODEC = simpleCodec(SugarCaneBlock::new); + public static final IntegerProperty AGE = BlockStateProperties.AGE_15; + protected static final float AABB_OFFSET = 6.0F; +- protected static final VoxelShape SHAPE = Block.box(2.0, 0.0, 2.0, 14.0, 16.0, 14.0); ++ protected static final VoxelShape SHAPE = Block.box(2.0D, 0.0D, 2.0D, 14.0D, 16.0D, 14.0D); + + @Override + public MapCodec codec() { +- return CODEC; ++ return SugarCaneBlock.CODEC; + } + + protected SugarCaneBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(AGE, Integer.valueOf(0))); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(SugarCaneBlock.AGE, 0)); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return SHAPE; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return SugarCaneBlock.SHAPE; + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (!state.canSurvive(level, pos)) { + level.destroyBlock(pos, true); + } ++ + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (level.isEmptyBlock(pos.above())) { +- int i = 1; ++ int i; + +- while (level.getBlockState(pos.below(i)).is(this)) { +- i++; ++ for (i = 1; level.getBlockState(pos.below(i)).is((Block) this); ++i) { ++ ; + } + + if (i < 3) { +- int i1 = state.getValue(AGE); +- if (i1 == 15) { +- level.setBlockAndUpdate(pos.above(), this.defaultBlockState()); +- level.setBlock(pos, state.setValue(AGE, Integer.valueOf(0)), 4); ++ int j = (Integer) state.getValue(SugarCaneBlock.AGE); ++ ++ if (j == 15) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos.above(), this.defaultBlockState()); // CraftBukkit ++ level.setBlock(pos, (IBlockData) state.setValue(SugarCaneBlock.AGE, 0), 4); + } else { +- level.setBlock(pos, state.setValue(AGE, Integer.valueOf(i1 + 1)), 4); ++ level.setBlock(pos, (IBlockData) state.setValue(SugarCaneBlock.AGE, j + 1), 4); + } + } + } ++ + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { + if (!state.canSurvive(level, currentPos)) { +- level.scheduleTick(currentPos, this, 1); ++ level.scheduleTick(currentPos, (Block) this, 1); + } + + return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { +- BlockState blockState = level.getBlockState(pos.below()); +- if (blockState.is(this)) { ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ IBlockData iblockdata1 = level.getBlockState(pos.below()); ++ ++ if (iblockdata1.is((Block) this)) { + return true; + } else { +- if (blockState.is(BlockTags.DIRT) || blockState.is(BlockTags.SAND)) { +- BlockPos blockPos = pos.below(); ++ if (iblockdata1.is(BlockTags.DIRT) || iblockdata1.is(BlockTags.SAND)) { ++ BlockPos blockposition1 = pos.below(); ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- BlockState blockState1 = level.getBlockState(blockPos.relative(direction)); +- FluidState fluidState = level.getFluidState(blockPos.relative(direction)); +- if (fluidState.is(FluidTags.WATER) || blockState1.is(Blocks.FROSTED_ICE)) { ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ IBlockData iblockdata2 = level.getBlockState(blockposition1.relative(enumdirection)); ++ FluidState fluid = level.getFluidState(blockposition1.relative(enumdirection)); ++ ++ if (fluid.is(FluidTags.WATER) || iblockdata2.is(Blocks.FROSTED_ICE)) { + return true; + } + } +@@ -100,7 +109,7 @@ + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(AGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(SugarCaneBlock.AGE); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/SweetBerryBushBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SweetBerryBushBlock.java.patch new file mode 100644 index 0000000000..5e553362ce --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/SweetBerryBushBlock.java.patch @@ -0,0 +1,189 @@ +--- a/net/minecraft/world/level/block/SweetBerryBushBlock.java ++++ b/net/minecraft/world/level/block/SweetBerryBushBlock.java +@@ -6,7 +6,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +@@ -18,7 +18,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; +@@ -27,81 +27,103 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import java.util.Collections; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerHarvestBlockEvent; ++// CraftBukkit end + + public class SweetBerryBushBlock extends BushBlock implements BonemealableBlock { ++ + public static final MapCodec CODEC = simpleCodec(SweetBerryBushBlock::new); + private static final float HURT_SPEED_THRESHOLD = 0.003F; + public static final int MAX_AGE = 3; + public static final IntegerProperty AGE = BlockStateProperties.AGE_3; +- private static final VoxelShape SAPLING_SHAPE = Block.box(3.0, 0.0, 3.0, 13.0, 8.0, 13.0); +- private static final VoxelShape MID_GROWTH_SHAPE = Block.box(1.0, 0.0, 1.0, 15.0, 16.0, 15.0); ++ private static final VoxelShape SAPLING_SHAPE = Block.box(3.0D, 0.0D, 3.0D, 13.0D, 8.0D, 13.0D); ++ private static final VoxelShape MID_GROWTH_SHAPE = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 16.0D, 15.0D); + + @Override + public MapCodec codec() { +- return CODEC; ++ return SweetBerryBushBlock.CODEC; + } + + public SweetBerryBushBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(AGE, Integer.valueOf(0))); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(SweetBerryBushBlock.AGE, 0)); + } + + @Override +- public ItemStack getCloneItemStack(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { ++ public ItemStack getCloneItemStack(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { + return new ItemStack(Items.SWEET_BERRIES); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- if (state.getValue(AGE) == 0) { +- return SAPLING_SHAPE; +- } else { +- return state.getValue(AGE) < 3 ? MID_GROWTH_SHAPE : super.getShape(state, level, pos, context); +- } ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (Integer) state.getValue(SweetBerryBushBlock.AGE) == 0 ? SweetBerryBushBlock.SAPLING_SHAPE : ((Integer) state.getValue(SweetBerryBushBlock.AGE) < 3 ? SweetBerryBushBlock.MID_GROWTH_SHAPE : super.getShape(state, level, pos, context)); + } + + @Override +- public boolean isRandomlyTicking(BlockState state) { +- return state.getValue(AGE) < 3; ++ public boolean isRandomlyTicking(IBlockData state) { ++ return (Integer) state.getValue(SweetBerryBushBlock.AGE) < 3; + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- int i = state.getValue(AGE); ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ int i = (Integer) state.getValue(SweetBerryBushBlock.AGE); ++ + if (i < 3 && random.nextInt(5) == 0 && level.getRawBrightness(pos.above(), 0) >= 9) { +- BlockState blockState = state.setValue(AGE, Integer.valueOf(i + 1)); +- level.setBlock(pos, blockState, 2); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(blockState)); ++ IBlockData iblockdata1 = (IBlockData) state.setValue(SweetBerryBushBlock.AGE, i + 1); ++ ++ if (!CraftEventFactory.handleBlockGrowEvent(level, pos, iblockdata1, 2)) return; // CraftBukkit ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(iblockdata1)); + } ++ + } + + @Override +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { + if (entity instanceof LivingEntity && entity.getType() != EntityType.FOX && entity.getType() != EntityType.BEE) { +- entity.makeStuckInBlock(state, new Vec3(0.8F, 0.75, 0.8F)); +- if (!level.isClientSide && state.getValue(AGE) > 0 && (entity.xOld != entity.getX() || entity.zOld != entity.getZ())) { +- double abs = Math.abs(entity.getX() - entity.xOld); +- double abs1 = Math.abs(entity.getZ() - entity.zOld); +- if (abs >= 0.003F || abs1 >= 0.003F) { ++ entity.makeStuckInBlock(state, new Vec3(0.800000011920929D, 0.75D, 0.800000011920929D)); ++ if (!level.isClientSide && (Integer) state.getValue(SweetBerryBushBlock.AGE) > 0 && (entity.xOld != entity.getX() || entity.zOld != entity.getZ())) { ++ double d0 = Math.abs(entity.getX() - entity.xOld); ++ double d1 = Math.abs(entity.getZ() - entity.zOld); ++ ++ if (d0 >= 0.003000000026077032D || d1 >= 0.003000000026077032D) { ++ CraftEventFactory.blockDamage = CraftBlock.at(level, pos); // CraftBukkit + entity.hurt(level.damageSources().sweetBerryBush(), 1.0F); ++ CraftEventFactory.blockDamage = null; // CraftBukkit + } + } ++ + } + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { +- int i = state.getValue(AGE); ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ int i = (Integer) state.getValue(SweetBerryBushBlock.AGE); + boolean flag = i == 3; ++ + if (!flag && player.getItemInHand(hand).is(Items.BONE_MEAL)) { + return InteractionResult.PASS; + } else if (i > 1) { +- int i1 = 1 + level.random.nextInt(2); +- popResource(level, pos, new ItemStack(Items.SWEET_BERRIES, i1 + (flag ? 1 : 0))); +- level.playSound(null, pos, SoundEvents.SWEET_BERRY_BUSH_PICK_BERRIES, SoundSource.BLOCKS, 1.0F, 0.8F + level.random.nextFloat() * 0.4F); +- BlockState blockState = state.setValue(AGE, Integer.valueOf(1)); +- level.setBlock(pos, blockState, 2); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(player, blockState)); ++ int j = 1 + level.random.nextInt(2); ++ ++ // CraftBukkit start ++ PlayerHarvestBlockEvent event = CraftEventFactory.callPlayerHarvestBlockEvent(level, pos, player, hand, Collections.singletonList(new ItemStack(Items.SWEET_BERRIES, j + (flag ? 1 : 0)))); ++ if (event.isCancelled()) { ++ return InteractionResult.SUCCESS; // We need to return a success either way, because making it PASS or FAIL will result in a bug where cancelling while harvesting w/ block in hand places block ++ } ++ for (org.bukkit.inventory.ItemStack itemStack : event.getItemsHarvested()) { ++ popResource(level, pos, CraftItemStack.asNMSCopy(itemStack)); ++ } ++ // CraftBukkit end ++ level.playSound((Player) null, pos, SoundEvents.SWEET_BERRY_BUSH_PICK_BERRIES, SoundSource.BLOCKS, 1.0F, 0.8F + level.random.nextFloat() * 0.4F); ++ IBlockData iblockdata1 = (IBlockData) state.setValue(SweetBerryBushBlock.AGE, 1); ++ ++ level.setBlock(pos, iblockdata1, 2); ++ level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(player, iblockdata1)); + return InteractionResult.sidedSuccess(level.isClientSide); + } else { + return super.use(state, level, pos, player, hand, hit); +@@ -109,23 +131,24 @@ + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(AGE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(SweetBerryBushBlock.AGE); + } + + @Override +- public boolean isValidBonemealTarget(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { +- return blockState.getValue(AGE) < 3; ++ public boolean isValidBonemealTarget(LevelReader iworldreader, BlockPos blockposition, IBlockData iblockdata) { ++ return (Integer) iblockdata.getValue(SweetBerryBushBlock.AGE) < 3; + } + + @Override +- public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, BlockState state) { ++ public boolean isBonemealSuccess(Level level, RandomSource random, BlockPos pos, IBlockData state) { + return true; + } + + @Override +- public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) { +- int min = Math.min(3, state.getValue(AGE) + 1); +- level.setBlock(pos, state.setValue(AGE, Integer.valueOf(min)), 2); ++ public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, IBlockData state) { ++ int i = Math.min(3, (Integer) state.getValue(SweetBerryBushBlock.AGE) + 1); ++ ++ level.setBlock(pos, (IBlockData) state.setValue(SweetBerryBushBlock.AGE, i), 2); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/TntBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/TntBlock.java.patch new file mode 100644 index 0000000000..ad1cad392a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/TntBlock.java.patch @@ -0,0 +1,189 @@ +--- a/net/minecraft/world/level/block/TntBlock.java ++++ b/net/minecraft/world/level/block/TntBlock.java +@@ -6,7 +6,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; +@@ -19,93 +19,109 @@ + import net.minecraft.world.level.Explosion; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.BlockHitResult; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.block.TNTPrimeEvent.PrimeCause; ++// CraftBukkit end + + public class TntBlock extends Block { ++ + public static final MapCodec CODEC = simpleCodec(TntBlock::new); + public static final BooleanProperty UNSTABLE = BlockStateProperties.UNSTABLE; + + @Override + public MapCodec codec() { +- return CODEC; ++ return TntBlock.CODEC; + } + + public TntBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.defaultBlockState().setValue(UNSTABLE, Boolean.valueOf(false))); ++ this.registerDefaultState((IBlockData) this.defaultBlockState().setValue(TntBlock.UNSTABLE, false)); + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { + if (!oldState.is(state.getBlock())) { +- if (level.hasNeighborSignal(pos)) { ++ if (level.hasNeighborSignal(pos) && CraftEventFactory.callTNTPrimeEvent(level, pos, PrimeCause.REDSTONE, null, null)) { // CraftBukkit - TNTPrimeEvent + explode(level, pos); + level.removeBlock(pos, false); + } ++ + } + } + + @Override +- public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { +- if (level.hasNeighborSignal(pos)) { ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ if (level.hasNeighborSignal(pos) && CraftEventFactory.callTNTPrimeEvent(level, pos, PrimeCause.REDSTONE, null, fromPos)) { // CraftBukkit - TNTPrimeEvent + explode(level, pos); + level.removeBlock(pos, false); + } ++ + } + + @Override +- public BlockState playerWillDestroy(Level level, BlockPos blockPos, BlockState blockState, Player player) { +- if (!level.isClientSide() && !player.isCreative() && blockState.getValue(UNSTABLE)) { +- explode(level, blockPos); ++ public IBlockData playerWillDestroy(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ if (!world.isClientSide() && !entityhuman.isCreative() && (Boolean) iblockdata.getValue(TntBlock.UNSTABLE) && CraftEventFactory.callTNTPrimeEvent(world, blockposition, PrimeCause.BLOCK_BREAK, entityhuman, null)) { // CraftBukkit - TNTPrimeEvent ++ explode(world, blockposition); + } + +- return super.playerWillDestroy(level, blockPos, blockState, player); ++ return super.playerWillDestroy(world, blockposition, iblockdata, entityhuman); + } + + @Override + public void wasExploded(Level level, BlockPos pos, Explosion explosion) { + if (!level.isClientSide) { +- PrimedTnt primedTnt = new PrimedTnt( +- level, (double)pos.getX() + 0.5, (double)pos.getY(), (double)pos.getZ() + 0.5, explosion.getIndirectSourceEntity() +- ); +- int fuse = primedTnt.getFuse(); +- primedTnt.setFuse((short)(level.random.nextInt(fuse / 4) + fuse / 8)); +- level.addFreshEntity(primedTnt); ++ PrimedTnt entitytntprimed = new PrimedTnt(level, (double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, explosion.getIndirectSourceEntity()); ++ int i = entitytntprimed.getFuse(); ++ ++ entitytntprimed.setFuse((short) (level.random.nextInt(i / 4) + i / 8)); ++ level.addFreshEntity(entitytntprimed); + } + } + + public static void explode(Level level, BlockPos pos) { +- explode(level, pos, null); ++ explode(level, pos, (LivingEntity) null); + } + + private static void explode(Level level, BlockPos pos, @Nullable LivingEntity entity) { + if (!level.isClientSide) { +- PrimedTnt primedTnt = new PrimedTnt(level, (double)pos.getX() + 0.5, (double)pos.getY(), (double)pos.getZ() + 0.5, entity); +- level.addFreshEntity(primedTnt); +- level.playSound(null, primedTnt.getX(), primedTnt.getY(), primedTnt.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent(entity, GameEvent.PRIME_FUSE, pos); ++ PrimedTnt entitytntprimed = new PrimedTnt(level, (double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, entity); ++ ++ level.addFreshEntity(entitytntprimed); ++ level.playSound((Player) null, entitytntprimed.getX(), entitytntprimed.getY(), entitytntprimed.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.gameEvent((Entity) entity, GameEvent.PRIME_FUSE, pos); + } + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (!itemInHand.is(Items.FLINT_AND_STEEL) && !itemInHand.is(Items.FIRE_CHARGE)) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (!itemstack.is(Items.FLINT_AND_STEEL) && !itemstack.is(Items.FIRE_CHARGE)) { + return super.use(state, level, pos, player, hand, hit); + } else { ++ // CraftBukkit start - TNTPrimeEvent ++ if (!CraftEventFactory.callTNTPrimeEvent(level, pos, PrimeCause.PLAYER, player, null)) { ++ return InteractionResult.CONSUME; ++ } ++ // CraftBukkit end + explode(level, pos, player); + level.setBlock(pos, Blocks.AIR.defaultBlockState(), 11); +- Item item = itemInHand.getItem(); ++ Item item = itemstack.getItem(); ++ + if (!player.isCreative()) { +- if (itemInHand.is(Items.FLINT_AND_STEEL)) { +- itemInHand.hurtAndBreak(1, player, user -> user.broadcastBreakEvent(hand)); ++ if (itemstack.is(Items.FLINT_AND_STEEL)) { ++ itemstack.hurtAndBreak(1, player, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(hand); ++ }); + } else { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + } + +@@ -115,15 +131,22 @@ + } + + @Override +- public void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) { ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { + if (!level.isClientSide) { +- BlockPos blockPos = hit.getBlockPos(); +- Entity owner = projectile.getOwner(); +- if (projectile.isOnFire() && projectile.mayInteract(level, blockPos)) { +- explode(level, blockPos, owner instanceof LivingEntity ? (LivingEntity)owner : null); +- level.removeBlock(blockPos, false); ++ BlockPos blockposition = hit.getBlockPos(); ++ Entity entity = projectile.getOwner(); ++ ++ if (projectile.isOnFire() && projectile.mayInteract(level, blockposition)) { ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, Blocks.AIR.defaultBlockState()) || !CraftEventFactory.callTNTPrimeEvent(level, blockposition, PrimeCause.PROJECTILE, projectile, null)) { ++ return; ++ } ++ // CraftBukkit end ++ explode(level, blockposition, entity instanceof LivingEntity ? (LivingEntity) entity : null); ++ level.removeBlock(blockposition, false); + } + } ++ + } + + @Override +@@ -132,7 +155,7 @@ + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(UNSTABLE); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(TntBlock.UNSTABLE); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/TrapDoorBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/TrapDoorBlock.java.patch new file mode 100644 index 0000000000..ba701cbdb1 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/TrapDoorBlock.java.patch @@ -0,0 +1,288 @@ +--- a/net/minecraft/world/level/block/TrapDoorBlock.java ++++ b/net/minecraft/world/level/block/TrapDoorBlock.java +@@ -2,14 +2,14 @@ + + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import java.util.function.BiConsumer; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.sounds.SoundSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.context.BlockPlaceContext; +@@ -18,7 +18,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockSetType; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; +@@ -26,85 +26,81 @@ + import net.minecraft.world.level.block.state.properties.EnumProperty; + import net.minecraft.world.level.block.state.properties.Half; + import net.minecraft.world.level.gameevent.GameEvent; ++import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + + public class TrapDoorBlock extends HorizontalDirectionalBlock implements SimpleWaterloggedBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group(BlockSetType.CODEC.fieldOf("block_set_type").forGetter(trapDoorBlock -> trapDoorBlock.type), propertiesCodec()) +- .apply(instance, TrapDoorBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(BlockSetType.CODEC.fieldOf("block_set_type").forGetter((blocktrapdoor) -> { ++ return blocktrapdoor.type; ++ }), propertiesCodec()).apply(instance, TrapDoorBlock::new); ++ }); + public static final BooleanProperty OPEN = BlockStateProperties.OPEN; + public static final EnumProperty HALF = BlockStateProperties.HALF; + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; + protected static final int AABB_THICKNESS = 3; +- protected static final VoxelShape EAST_OPEN_AABB = Block.box(0.0, 0.0, 0.0, 3.0, 16.0, 16.0); +- protected static final VoxelShape WEST_OPEN_AABB = Block.box(13.0, 0.0, 0.0, 16.0, 16.0, 16.0); +- protected static final VoxelShape SOUTH_OPEN_AABB = Block.box(0.0, 0.0, 0.0, 16.0, 16.0, 3.0); +- protected static final VoxelShape NORTH_OPEN_AABB = Block.box(0.0, 0.0, 13.0, 16.0, 16.0, 16.0); +- protected static final VoxelShape BOTTOM_AABB = Block.box(0.0, 0.0, 0.0, 16.0, 3.0, 16.0); +- protected static final VoxelShape TOP_AABB = Block.box(0.0, 13.0, 0.0, 16.0, 16.0, 16.0); ++ protected static final VoxelShape EAST_OPEN_AABB = Block.box(0.0D, 0.0D, 0.0D, 3.0D, 16.0D, 16.0D); ++ protected static final VoxelShape WEST_OPEN_AABB = Block.box(13.0D, 0.0D, 0.0D, 16.0D, 16.0D, 16.0D); ++ protected static final VoxelShape SOUTH_OPEN_AABB = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 16.0D, 3.0D); ++ protected static final VoxelShape NORTH_OPEN_AABB = Block.box(0.0D, 0.0D, 13.0D, 16.0D, 16.0D, 16.0D); ++ protected static final VoxelShape BOTTOM_AABB = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 3.0D, 16.0D); ++ protected static final VoxelShape TOP_AABB = Block.box(0.0D, 13.0D, 0.0D, 16.0D, 16.0D, 16.0D); + private final BlockSetType type; + + @Override + public MapCodec codec() { +- return CODEC; ++ return TrapDoorBlock.CODEC; + } + +- protected TrapDoorBlock(BlockSetType blockSetType, BlockBehaviour.Properties properties) { +- super(properties.sound(blockSetType.soundType())); +- this.type = blockSetType; +- this.registerDefaultState( +- this.stateDefinition +- .any() +- .setValue(FACING, Direction.NORTH) +- .setValue(OPEN, Boolean.valueOf(false)) +- .setValue(HALF, Half.BOTTOM) +- .setValue(POWERED, Boolean.valueOf(false)) +- .setValue(WATERLOGGED, Boolean.valueOf(false)) +- ); ++ protected TrapDoorBlock(BlockSetType blocksettype, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info.sound(blocksettype.soundType())); ++ this.type = blocksettype; ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(TrapDoorBlock.FACING, Direction.NORTH)).setValue(TrapDoorBlock.OPEN, false)).setValue(TrapDoorBlock.HALF, Half.BOTTOM)).setValue(TrapDoorBlock.POWERED, false)).setValue(TrapDoorBlock.WATERLOGGED, false)); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- if (!state.getValue(OPEN)) { +- return state.getValue(HALF) == Half.TOP ? TOP_AABB : BOTTOM_AABB; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ if (!(Boolean) state.getValue(TrapDoorBlock.OPEN)) { ++ return state.getValue(TrapDoorBlock.HALF) == Half.TOP ? TrapDoorBlock.TOP_AABB : TrapDoorBlock.BOTTOM_AABB; + } else { +- switch ((Direction)state.getValue(FACING)) { ++ switch ((Direction) state.getValue(TrapDoorBlock.FACING)) { + case NORTH: + default: +- return NORTH_OPEN_AABB; ++ return TrapDoorBlock.NORTH_OPEN_AABB; + case SOUTH: +- return SOUTH_OPEN_AABB; ++ return TrapDoorBlock.SOUTH_OPEN_AABB; + case WEST: +- return WEST_OPEN_AABB; ++ return TrapDoorBlock.WEST_OPEN_AABB; + case EAST: +- return EAST_OPEN_AABB; ++ return TrapDoorBlock.EAST_OPEN_AABB; + } + } + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + switch (type) { + case LAND: +- return state.getValue(OPEN); ++ return (Boolean) state.getValue(TrapDoorBlock.OPEN); + case WATER: +- return state.getValue(WATERLOGGED); ++ return (Boolean) state.getValue(TrapDoorBlock.WATERLOGGED); + case AIR: +- return state.getValue(OPEN); ++ return (Boolean) state.getValue(TrapDoorBlock.OPEN); + default: + return false; + } + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + if (!this.type.canOpenByHand()) { + return InteractionResult.PASS; + } else { +@@ -114,86 +110,96 @@ + } + + @Override +- public void onExplosionHit(BlockState blockState, Level level, BlockPos blockPos, Explosion explosion, BiConsumer biConsumer) { +- if (explosion.getBlockInteraction() == Explosion.BlockInteraction.TRIGGER_BLOCK +- && !level.isClientSide() +- && this.type.canOpenByWindCharge() +- && !blockState.getValue(POWERED)) { +- this.toggle(blockState, level, blockPos, null); ++ public void onExplosionHit(IBlockData iblockdata, Level world, BlockPos blockposition, Explosion explosion, BiConsumer biconsumer) { ++ if (explosion.getBlockInteraction() == Explosion.Effect.TRIGGER_BLOCK && !world.isClientSide() && this.type.canOpenByWindCharge() && !(Boolean) iblockdata.getValue(TrapDoorBlock.POWERED)) { ++ this.toggle(iblockdata, world, blockposition, (Player) null); + } + +- super.onExplosionHit(blockState, level, blockPos, explosion, biConsumer); ++ super.onExplosionHit(iblockdata, world, blockposition, explosion, biconsumer); + } + +- private void toggle(BlockState blockState, Level level, BlockPos blockPos, @Nullable Player player) { +- BlockState blockState1 = blockState.cycle(OPEN); +- level.setBlock(blockPos, blockState1, 2); +- if (blockState1.getValue(WATERLOGGED)) { +- level.scheduleTick(blockPos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); ++ private void toggle(IBlockData iblockdata, Level world, BlockPos blockposition, @Nullable Player entityhuman) { ++ IBlockData iblockdata1 = (IBlockData) iblockdata.cycle(TrapDoorBlock.OPEN); ++ ++ world.setBlock(blockposition, iblockdata1, 2); ++ if ((Boolean) iblockdata1.getValue(TrapDoorBlock.WATERLOGGED)) { ++ world.scheduleTick(blockposition, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(world)); + } + +- this.playSound(player, level, blockPos, blockState1.getValue(OPEN)); ++ this.playSound(entityhuman, world, blockposition, (Boolean) iblockdata1.getValue(TrapDoorBlock.OPEN)); + } + + protected void playSound(@Nullable Player player, Level level, BlockPos pos, boolean isOpened) { +- level.playSound( +- player, pos, isOpened ? this.type.trapdoorOpen() : this.type.trapdoorClose(), SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.1F + 0.9F +- ); +- level.gameEvent(player, isOpened ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); ++ level.playSound(player, pos, isOpened ? this.type.trapdoorOpen() : this.type.trapdoorClose(), SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.1F + 0.9F); ++ level.gameEvent((Entity) player, isOpened ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, pos); + } + + @Override +- public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { + if (!level.isClientSide) { +- boolean hasNeighborSignal = level.hasNeighborSignal(pos); +- if (hasNeighborSignal != state.getValue(POWERED)) { +- if (state.getValue(OPEN) != hasNeighborSignal) { +- state = state.setValue(OPEN, Boolean.valueOf(hasNeighborSignal)); +- this.playSound(null, level, pos, hasNeighborSignal); ++ boolean flag1 = level.hasNeighborSignal(pos); ++ ++ if (flag1 != (Boolean) state.getValue(TrapDoorBlock.POWERED)) { ++ // CraftBukkit start ++ org.bukkit.World bworld = level.getWorld(); ++ org.bukkit.block.Block bblock = bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ ++ int power = bblock.getBlockPower(); ++ int oldPower = (Boolean) state.getValue(OPEN) ? 15 : 0; ++ ++ if (oldPower == 0 ^ power == 0 || block.defaultBlockState().isSignalSource()) { ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bblock, oldPower, power); ++ level.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ flag1 = eventRedstone.getNewCurrent() > 0; + } ++ // CraftBukkit end ++ if ((Boolean) state.getValue(TrapDoorBlock.OPEN) != flag1) { ++ state = (IBlockData) state.setValue(TrapDoorBlock.OPEN, flag1); ++ this.playSound((Player) null, level, pos, flag1); ++ } + +- level.setBlock(pos, state.setValue(POWERED, Boolean.valueOf(hasNeighborSignal)), 2); +- if (state.getValue(WATERLOGGED)) { +- level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); ++ level.setBlock(pos, (IBlockData) state.setValue(TrapDoorBlock.POWERED, flag1), 2); ++ if ((Boolean) state.getValue(TrapDoorBlock.WATERLOGGED)) { ++ level.scheduleTick(pos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + } ++ + } + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- BlockState blockState = this.defaultBlockState(); +- FluidState fluidState = context.getLevel().getFluidState(context.getClickedPos()); +- Direction clickedFace = context.getClickedFace(); +- if (!context.replacingClickedOnBlock() && clickedFace.getAxis().isHorizontal()) { +- blockState = blockState.setValue(FACING, clickedFace) +- .setValue(HALF, context.getClickLocation().y - (double)context.getClickedPos().getY() > 0.5 ? Half.TOP : Half.BOTTOM); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ IBlockData iblockdata = this.defaultBlockState(); ++ FluidState fluid = context.getLevel().getFluidState(context.getClickedPos()); ++ Direction enumdirection = context.getClickedFace(); ++ ++ if (!context.replacingClickedOnBlock() && enumdirection.getAxis().isHorizontal()) { ++ iblockdata = (IBlockData) ((IBlockData) iblockdata.setValue(TrapDoorBlock.FACING, enumdirection)).setValue(TrapDoorBlock.HALF, context.getClickLocation().y - (double) context.getClickedPos().getY() > 0.5D ? Half.TOP : Half.BOTTOM); + } else { +- blockState = blockState.setValue(FACING, context.getHorizontalDirection().getOpposite()) +- .setValue(HALF, clickedFace == Direction.UP ? Half.BOTTOM : Half.TOP); ++ iblockdata = (IBlockData) ((IBlockData) iblockdata.setValue(TrapDoorBlock.FACING, context.getHorizontalDirection().getOpposite())).setValue(TrapDoorBlock.HALF, enumdirection == Direction.UP ? Half.BOTTOM : Half.TOP); + } + + if (context.getLevel().hasNeighborSignal(context.getClickedPos())) { +- blockState = blockState.setValue(OPEN, Boolean.valueOf(true)).setValue(POWERED, Boolean.valueOf(true)); ++ iblockdata = (IBlockData) ((IBlockData) iblockdata.setValue(TrapDoorBlock.OPEN, true)).setValue(TrapDoorBlock.POWERED, true); + } + +- return blockState.setValue(WATERLOGGED, Boolean.valueOf(fluidState.getType() == Fluids.WATER)); ++ return (IBlockData) iblockdata.setValue(TrapDoorBlock.WATERLOGGED, fluid.getType() == Fluids.WATER); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(FACING, OPEN, HALF, POWERED, WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(TrapDoorBlock.FACING, TrapDoorBlock.OPEN, TrapDoorBlock.HALF, TrapDoorBlock.POWERED, TrapDoorBlock.WATERLOGGED); + } + + @Override +- public FluidState getFluidState(BlockState state) { +- return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); ++ public FluidState getFluidState(IBlockData state) { ++ return (Boolean) state.getValue(TrapDoorBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- if (state.getValue(WATERLOGGED)) { +- level.scheduleTick(currentPos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ if ((Boolean) state.getValue(TrapDoorBlock.WATERLOGGED)) { ++ level.scheduleTick(currentPos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(level)); + } + + return super.updateShape(state, facing, facingState, level, currentPos, facingPos); diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/TripWireBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/TripWireBlock.java.patch new file mode 100644 index 0000000000..8cf6f75c90 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/TripWireBlock.java.patch @@ -0,0 +1,332 @@ +--- a/net/minecraft/world/level/block/TripWireBlock.java ++++ b/net/minecraft/world/level/block/TripWireBlock.java +@@ -2,7 +2,7 @@ + + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; ++import java.util.Iterator; + import java.util.List; + import java.util.Map; + import net.minecraft.core.BlockPos; +@@ -18,19 +18,23 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; ++import net.minecraft.world.level.block.state.properties.Property; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.event.entity.EntityInteractEvent; // CraftBukkit + + public class TripWireBlock extends Block { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group(BuiltInRegistries.BLOCK.byNameCodec().fieldOf("hook").forGetter(tripWireBlock -> tripWireBlock.hook), propertiesCodec()) +- .apply(instance, TripWireBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(BuiltInRegistries.BLOCK.byNameCodec().fieldOf("hook").forGetter((blocktripwire) -> { ++ return blocktripwire.hook; ++ }), propertiesCodec()).apply(instance, TripWireBlock::new); ++ }); + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + public static final BooleanProperty ATTACHED = BlockStateProperties.ATTACHED; + public static final BooleanProperty DISARMED = BlockStateProperties.DISARMED; +@@ -39,121 +43,123 @@ + public static final BooleanProperty SOUTH = PipeBlock.SOUTH; + public static final BooleanProperty WEST = PipeBlock.WEST; + private static final Map PROPERTY_BY_DIRECTION = CrossCollisionBlock.PROPERTY_BY_DIRECTION; +- protected static final VoxelShape AABB = Block.box(0.0, 1.0, 0.0, 16.0, 2.5, 16.0); +- protected static final VoxelShape NOT_ATTACHED_AABB = Block.box(0.0, 0.0, 0.0, 16.0, 8.0, 16.0); ++ protected static final VoxelShape AABB = Block.box(0.0D, 1.0D, 0.0D, 16.0D, 2.5D, 16.0D); ++ protected static final VoxelShape NOT_ATTACHED_AABB = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 8.0D, 16.0D); + private static final int RECHECK_PERIOD = 10; + private final Block hook; + + @Override + public MapCodec codec() { +- return CODEC; ++ return TripWireBlock.CODEC; + } + +- public TripWireBlock(Block block, BlockBehaviour.Properties properties) { +- super(properties); +- this.registerDefaultState( +- this.stateDefinition +- .any() +- .setValue(POWERED, Boolean.valueOf(false)) +- .setValue(ATTACHED, Boolean.valueOf(false)) +- .setValue(DISARMED, Boolean.valueOf(false)) +- .setValue(NORTH, Boolean.valueOf(false)) +- .setValue(EAST, Boolean.valueOf(false)) +- .setValue(SOUTH, Boolean.valueOf(false)) +- .setValue(WEST, Boolean.valueOf(false)) +- ); ++ public TripWireBlock(Block block, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(TripWireBlock.POWERED, false)).setValue(TripWireBlock.ATTACHED, false)).setValue(TripWireBlock.DISARMED, false)).setValue(TripWireBlock.NORTH, false)).setValue(TripWireBlock.EAST, false)).setValue(TripWireBlock.SOUTH, false)).setValue(TripWireBlock.WEST, false)); + this.hook = block; + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return state.getValue(ATTACHED) ? AABB : NOT_ATTACHED_AABB; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (Boolean) state.getValue(TripWireBlock.ATTACHED) ? TripWireBlock.AABB : TripWireBlock.NOT_ATTACHED_AABB; + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- BlockGetter level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- return this.defaultBlockState() +- .setValue(NORTH, Boolean.valueOf(this.shouldConnectTo(level.getBlockState(clickedPos.north()), Direction.NORTH))) +- .setValue(EAST, Boolean.valueOf(this.shouldConnectTo(level.getBlockState(clickedPos.east()), Direction.EAST))) +- .setValue(SOUTH, Boolean.valueOf(this.shouldConnectTo(level.getBlockState(clickedPos.south()), Direction.SOUTH))) +- .setValue(WEST, Boolean.valueOf(this.shouldConnectTo(level.getBlockState(clickedPos.west()), Direction.WEST))); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(TripWireBlock.NORTH, this.shouldConnectTo(world.getBlockState(blockposition.north()), Direction.NORTH))).setValue(TripWireBlock.EAST, this.shouldConnectTo(world.getBlockState(blockposition.east()), Direction.EAST))).setValue(TripWireBlock.SOUTH, this.shouldConnectTo(world.getBlockState(blockposition.south()), Direction.SOUTH))).setValue(TripWireBlock.WEST, this.shouldConnectTo(world.getBlockState(blockposition.west()), Direction.WEST)); + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- return facing.getAxis().isHorizontal() +- ? state.setValue(PROPERTY_BY_DIRECTION.get(facing), Boolean.valueOf(this.shouldConnectTo(facingState, facing))) +- : super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ return facing.getAxis().isHorizontal() ? (IBlockData) state.setValue((Property) TripWireBlock.PROPERTY_BY_DIRECTION.get(facing), this.shouldConnectTo(facingState, facing)) : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { + if (!oldState.is(state.getBlock())) { + this.updateSource(level, pos, state); + } + } + + @Override +- public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { + if (!isMoving && !state.is(newState.getBlock())) { +- this.updateSource(level, pos, state.setValue(POWERED, Boolean.valueOf(true))); ++ this.updateSource(level, pos, (IBlockData) state.setValue(TripWireBlock.POWERED, true)); + } + } + + @Override +- public BlockState playerWillDestroy(Level level, BlockPos blockPos, BlockState blockState, Player player) { +- if (!level.isClientSide && !player.getMainHandItem().isEmpty() && player.getMainHandItem().is(Items.SHEARS)) { +- level.setBlock(blockPos, blockState.setValue(DISARMED, Boolean.valueOf(true)), 4); +- level.gameEvent(player, GameEvent.SHEAR, blockPos); ++ public IBlockData playerWillDestroy(Level world, BlockPos blockposition, IBlockData iblockdata, Player entityhuman) { ++ if (!world.isClientSide && !entityhuman.getMainHandItem().isEmpty() && entityhuman.getMainHandItem().is(Items.SHEARS)) { ++ world.setBlock(blockposition, (IBlockData) iblockdata.setValue(TripWireBlock.DISARMED, true), 4); ++ world.gameEvent((Entity) entityhuman, GameEvent.SHEAR, blockposition); + } + +- return super.playerWillDestroy(level, blockPos, blockState, player); ++ return super.playerWillDestroy(world, blockposition, iblockdata, entityhuman); + } + +- private void updateSource(Level level, BlockPos pos, BlockState state) { +- for (Direction direction : new Direction[]{Direction.SOUTH, Direction.WEST}) { +- for (int i = 1; i < 42; i++) { +- BlockPos blockPos = pos.relative(direction, i); +- BlockState blockState = level.getBlockState(blockPos); +- if (blockState.is(this.hook)) { +- if (blockState.getValue(TripWireHookBlock.FACING) == direction.getOpposite()) { +- TripWireHookBlock.calculateState(level, blockPos, blockState, false, true, i, state); ++ private void updateSource(Level level, BlockPos pos, IBlockData state) { ++ Direction[] aenumdirection = new Direction[]{Direction.SOUTH, Direction.WEST}; ++ int i = aenumdirection.length; ++ int j = 0; ++ ++ while (j < i) { ++ Direction enumdirection = aenumdirection[j]; ++ int k = 1; ++ ++ while (true) { ++ if (k < 42) { ++ BlockPos blockposition1 = pos.relative(enumdirection, k); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ if (iblockdata1.is(this.hook)) { ++ if (iblockdata1.getValue(TripWireHookBlock.FACING) == enumdirection.getOpposite()) { ++ TripWireHookBlock.calculateState(level, blockposition1, iblockdata1, false, true, k, state); ++ } ++ } else if (iblockdata1.is((Block) this)) { ++ ++k; ++ continue; + } +- break; + } + +- if (!blockState.is(this)) { +- break; +- } ++ ++j; ++ break; + } + } ++ + } + + @Override +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { + if (!level.isClientSide) { +- if (!state.getValue(POWERED)) { ++ if (!(Boolean) state.getValue(TripWireBlock.POWERED)) { + this.checkPressed(level, pos); + } + } + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- if (level.getBlockState(pos).getValue(POWERED)) { ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ if ((Boolean) level.getBlockState(pos).getValue(TripWireBlock.POWERED)) { + this.checkPressed(level, pos); + } + } + + private void checkPressed(Level level, BlockPos pos) { +- BlockState blockState = level.getBlockState(pos); +- boolean flag = blockState.getValue(POWERED); ++ IBlockData iblockdata = level.getBlockState(pos); ++ boolean flag = (Boolean) iblockdata.getValue(TripWireBlock.POWERED); + boolean flag1 = false; +- List entities = level.getEntities(null, blockState.getShape(level, pos).bounds().move(pos)); +- if (!entities.isEmpty()) { +- for (Entity entity : entities) { ++ List list = level.getEntities((Entity) null, iblockdata.getShape(level, pos).bounds().move(pos)); ++ ++ if (!list.isEmpty()) { ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ + if (!entity.isIgnoringBlockTriggers()) { + flag1 = true; + break; +@@ -161,58 +167,84 @@ + } + } + ++ // CraftBukkit start - Call interact even when triggering connected tripwire ++ if (flag != flag1 && flag1 && (Boolean)iblockdata.getValue(ATTACHED)) { ++ org.bukkit.World bworld = level.getWorld(); ++ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager(); ++ org.bukkit.block.Block block = bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ boolean allowed = false; ++ ++ // If all of the events are cancelled block the tripwire trigger, else allow ++ for (Object object : list) { ++ if (object != null) { ++ org.bukkit.event.Cancellable cancellable; ++ ++ if (object instanceof Player) { ++ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) object, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else if (object instanceof Entity) { ++ cancellable = new EntityInteractEvent(((Entity) object).getBukkitEntity(), block); ++ manager.callEvent((EntityInteractEvent) cancellable); ++ } else { ++ continue; ++ } ++ ++ if (!cancellable.isCancelled()) { ++ allowed = true; ++ break; ++ } ++ } ++ } ++ ++ if (!allowed) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ + if (flag1 != flag) { +- blockState = blockState.setValue(POWERED, Boolean.valueOf(flag1)); +- level.setBlock(pos, blockState, 3); +- this.updateSource(level, pos, blockState); ++ iblockdata = (IBlockData) iblockdata.setValue(TripWireBlock.POWERED, flag1); ++ level.setBlock(pos, iblockdata, 3); ++ this.updateSource(level, pos, iblockdata); + } + + if (flag1) { +- level.scheduleTick(new BlockPos(pos), this, 10); ++ level.scheduleTick(new BlockPos(pos), (Block) this, 10); + } ++ + } + +- public boolean shouldConnectTo(BlockState state, Direction direction) { +- return state.is(this.hook) ? state.getValue(TripWireHookBlock.FACING) == direction.getOpposite() : state.is(this); ++ public boolean shouldConnectTo(IBlockData state, Direction direction) { ++ return state.is(this.hook) ? state.getValue(TripWireHookBlock.FACING) == direction.getOpposite() : state.is((Block) this); + } + + @Override +- public BlockState rotate(BlockState state, Rotation rot) { ++ public IBlockData rotate(IBlockData state, Rotation rot) { + switch (rot) { + case CLOCKWISE_180: +- return state.setValue(NORTH, state.getValue(SOUTH)) +- .setValue(EAST, state.getValue(WEST)) +- .setValue(SOUTH, state.getValue(NORTH)) +- .setValue(WEST, state.getValue(EAST)); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) state.setValue(TripWireBlock.NORTH, (Boolean) state.getValue(TripWireBlock.SOUTH))).setValue(TripWireBlock.EAST, (Boolean) state.getValue(TripWireBlock.WEST))).setValue(TripWireBlock.SOUTH, (Boolean) state.getValue(TripWireBlock.NORTH))).setValue(TripWireBlock.WEST, (Boolean) state.getValue(TripWireBlock.EAST)); + case COUNTERCLOCKWISE_90: +- return state.setValue(NORTH, state.getValue(EAST)) +- .setValue(EAST, state.getValue(SOUTH)) +- .setValue(SOUTH, state.getValue(WEST)) +- .setValue(WEST, state.getValue(NORTH)); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) state.setValue(TripWireBlock.NORTH, (Boolean) state.getValue(TripWireBlock.EAST))).setValue(TripWireBlock.EAST, (Boolean) state.getValue(TripWireBlock.SOUTH))).setValue(TripWireBlock.SOUTH, (Boolean) state.getValue(TripWireBlock.WEST))).setValue(TripWireBlock.WEST, (Boolean) state.getValue(TripWireBlock.NORTH)); + case CLOCKWISE_90: +- return state.setValue(NORTH, state.getValue(WEST)) +- .setValue(EAST, state.getValue(NORTH)) +- .setValue(SOUTH, state.getValue(EAST)) +- .setValue(WEST, state.getValue(SOUTH)); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) state.setValue(TripWireBlock.NORTH, (Boolean) state.getValue(TripWireBlock.WEST))).setValue(TripWireBlock.EAST, (Boolean) state.getValue(TripWireBlock.NORTH))).setValue(TripWireBlock.SOUTH, (Boolean) state.getValue(TripWireBlock.EAST))).setValue(TripWireBlock.WEST, (Boolean) state.getValue(TripWireBlock.SOUTH)); + default: + return state; + } + } + + @Override +- public BlockState mirror(BlockState state, Mirror mirror) { ++ public IBlockData mirror(IBlockData state, Mirror mirror) { + switch (mirror) { + case LEFT_RIGHT: +- return state.setValue(NORTH, state.getValue(SOUTH)).setValue(SOUTH, state.getValue(NORTH)); ++ return (IBlockData) ((IBlockData) state.setValue(TripWireBlock.NORTH, (Boolean) state.getValue(TripWireBlock.SOUTH))).setValue(TripWireBlock.SOUTH, (Boolean) state.getValue(TripWireBlock.NORTH)); + case FRONT_BACK: +- return state.setValue(EAST, state.getValue(WEST)).setValue(WEST, state.getValue(EAST)); ++ return (IBlockData) ((IBlockData) state.setValue(TripWireBlock.EAST, (Boolean) state.getValue(TripWireBlock.WEST))).setValue(TripWireBlock.WEST, (Boolean) state.getValue(TripWireBlock.EAST)); + default: + return super.mirror(state, mirror); + } + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(POWERED, ATTACHED, DISARMED, NORTH, EAST, WEST, SOUTH); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(TripWireBlock.POWERED, TripWireBlock.ATTACHED, TripWireBlock.DISARMED, TripWireBlock.NORTH, TripWireBlock.EAST, TripWireBlock.WEST, TripWireBlock.SOUTH); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/TripWireHookBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/TripWireHookBlock.java.patch new file mode 100644 index 0000000000..ca96239d64 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/TripWireHookBlock.java.patch @@ -0,0 +1,403 @@ +--- a/net/minecraft/world/level/block/TripWireHookBlock.java ++++ b/net/minecraft/world/level/block/TripWireHookBlock.java +@@ -10,7 +10,9 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.util.RandomSource; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.context.BlockPlaceContext; + import net.minecraft.world.level.BlockGetter; +@@ -18,7 +20,7 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -26,8 +28,13 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockRedstoneEvent; ++// CraftBukkit end + + public class TripWireHookBlock extends Block { ++ + public static final MapCodec CODEC = simpleCodec(TripWireHookBlock::new); + public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING; + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; +@@ -36,67 +43,69 @@ + protected static final int WIRE_DIST_MAX = 42; + private static final int RECHECK_PERIOD = 10; + protected static final int AABB_OFFSET = 3; +- protected static final VoxelShape NORTH_AABB = Block.box(5.0, 0.0, 10.0, 11.0, 10.0, 16.0); +- protected static final VoxelShape SOUTH_AABB = Block.box(5.0, 0.0, 0.0, 11.0, 10.0, 6.0); +- protected static final VoxelShape WEST_AABB = Block.box(10.0, 0.0, 5.0, 16.0, 10.0, 11.0); +- protected static final VoxelShape EAST_AABB = Block.box(0.0, 0.0, 5.0, 6.0, 10.0, 11.0); ++ protected static final VoxelShape NORTH_AABB = Block.box(5.0D, 0.0D, 10.0D, 11.0D, 10.0D, 16.0D); ++ protected static final VoxelShape SOUTH_AABB = Block.box(5.0D, 0.0D, 0.0D, 11.0D, 10.0D, 6.0D); ++ protected static final VoxelShape WEST_AABB = Block.box(10.0D, 0.0D, 5.0D, 16.0D, 10.0D, 11.0D); ++ protected static final VoxelShape EAST_AABB = Block.box(0.0D, 0.0D, 5.0D, 6.0D, 10.0D, 11.0D); + + @Override + public MapCodec codec() { +- return CODEC; ++ return TripWireHookBlock.CODEC; + } + + public TripWireHookBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState( +- this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(POWERED, Boolean.valueOf(false)).setValue(ATTACHED, Boolean.valueOf(false)) +- ); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(TripWireHookBlock.FACING, Direction.NORTH)).setValue(TripWireHookBlock.POWERED, false)).setValue(TripWireHookBlock.ATTACHED, false)); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- switch ((Direction)state.getValue(FACING)) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ switch ((Direction) state.getValue(TripWireHookBlock.FACING)) { + case EAST: + default: +- return EAST_AABB; ++ return TripWireHookBlock.EAST_AABB; + case WEST: +- return WEST_AABB; ++ return TripWireHookBlock.WEST_AABB; + case SOUTH: +- return SOUTH_AABB; ++ return TripWireHookBlock.SOUTH_AABB; + case NORTH: +- return NORTH_AABB; ++ return TripWireHookBlock.NORTH_AABB; + } + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { +- Direction direction = state.getValue(FACING); +- BlockPos blockPos = pos.relative(direction.getOpposite()); +- BlockState blockState = level.getBlockState(blockPos); +- return direction.getAxis().isHorizontal() && blockState.isFaceSturdy(level, blockPos, direction); ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { ++ Direction enumdirection = (Direction) state.getValue(TripWireHookBlock.FACING); ++ BlockPos blockposition1 = pos.relative(enumdirection.getOpposite()); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ return enumdirection.getAxis().isHorizontal() && iblockdata1.isFaceSturdy(level, blockposition1, enumdirection); + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- return facing.getOpposite() == state.getValue(FACING) && !state.canSurvive(level, currentPos) +- ? Blocks.AIR.defaultBlockState() +- : super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ return facing.getOpposite() == state.getValue(TripWireHookBlock.FACING) && !state.canSurvive(level, currentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Nullable + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- BlockState blockState = this.defaultBlockState().setValue(POWERED, Boolean.valueOf(false)).setValue(ATTACHED, Boolean.valueOf(false)); +- LevelReader level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); +- Direction[] nearestLookingDirections = context.getNearestLookingDirections(); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ IBlockData iblockdata = (IBlockData) ((IBlockData) this.defaultBlockState().setValue(TripWireHookBlock.POWERED, false)).setValue(TripWireHookBlock.ATTACHED, false); ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ Direction[] aenumdirection = context.getNearestLookingDirections(); ++ Direction[] aenumdirection1 = aenumdirection; ++ int i = aenumdirection.length; + +- for (Direction direction : nearestLookingDirections) { +- if (direction.getAxis().isHorizontal()) { +- Direction opposite = direction.getOpposite(); +- blockState = blockState.setValue(FACING, opposite); +- if (blockState.canSurvive(level, clickedPos)) { +- return blockState; ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection1[j]; ++ ++ if (enumdirection.getAxis().isHorizontal()) { ++ Direction enumdirection1 = enumdirection.getOpposite(); ++ ++ iblockdata = (IBlockData) iblockdata.setValue(TripWireHookBlock.FACING, enumdirection1); ++ if (iblockdata.canSurvive(world, blockposition)) { ++ return iblockdata; + } + } + } +@@ -105,124 +114,143 @@ + } + + @Override +- public void setPlacedBy(Level level, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { +- calculateState(level, pos, state, false, false, -1, null); ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, LivingEntity placer, ItemStack stack) { ++ calculateState(level, pos, state, false, false, -1, (IBlockData) null); + } + +- public static void calculateState( +- Level level, BlockPos level1, BlockState pos, boolean hookState, boolean attaching, int shouldNotifyNeighbours, @Nullable BlockState searchRange +- ) { +- Optional state = pos.getOptionalValue(FACING); +- if (state.isPresent()) { +- Direction direction = state.get(); +- boolean flag = pos.getOptionalValue(ATTACHED).orElse(false); +- boolean flag1 = pos.getOptionalValue(POWERED).orElse(false); ++ public static void calculateState(Level world, BlockPos level, IBlockData pos, boolean hookState, boolean attaching, int shouldNotifyNeighbours, @Nullable IBlockData searchRange) { ++ Optional optional = pos.getOptionalValue(TripWireHookBlock.FACING); ++ ++ if (optional.isPresent()) { ++ Direction enumdirection = (Direction) optional.get(); ++ boolean flag2 = (Boolean) pos.getOptionalValue(TripWireHookBlock.ATTACHED).orElse(false); ++ boolean flag3 = (Boolean) pos.getOptionalValue(TripWireHookBlock.POWERED).orElse(false); + Block block = pos.getBlock(); +- boolean flag2 = !hookState; +- boolean flag3 = false; +- int i = 0; +- BlockState[] blockStates = new BlockState[42]; ++ boolean flag4 = !hookState; ++ boolean flag5 = false; ++ int j = 0; ++ IBlockData[] aiblockdata = new IBlockData[42]; + +- for (int i1 = 1; i1 < 42; i1++) { +- BlockPos blockPos = level1.relative(direction, i1); +- BlockState blockState = level.getBlockState(blockPos); +- if (blockState.is(Blocks.TRIPWIRE_HOOK)) { +- if (blockState.getValue(FACING) == direction.getOpposite()) { +- i = i1; ++ BlockPos blockposition1; ++ ++ for (int k = 1; k < 42; ++k) { ++ blockposition1 = level.relative(enumdirection, k); ++ IBlockData iblockdata2 = world.getBlockState(blockposition1); ++ ++ if (iblockdata2.is(Blocks.TRIPWIRE_HOOK)) { ++ if (iblockdata2.getValue(TripWireHookBlock.FACING) == enumdirection.getOpposite()) { ++ j = k; + } + break; + } + +- if (!blockState.is(Blocks.TRIPWIRE) && i1 != shouldNotifyNeighbours) { +- blockStates[i1] = null; +- flag2 = false; ++ if (!iblockdata2.is(Blocks.TRIPWIRE) && k != shouldNotifyNeighbours) { ++ aiblockdata[k] = null; ++ flag4 = false; + } else { +- if (i1 == shouldNotifyNeighbours) { +- blockState = MoreObjects.firstNonNull(searchRange, blockState); ++ if (k == shouldNotifyNeighbours) { ++ iblockdata2 = (IBlockData) MoreObjects.firstNonNull(searchRange, iblockdata2); + } + +- boolean flag4 = !blockState.getValue(TripWireBlock.DISARMED); +- boolean flag5 = blockState.getValue(TripWireBlock.POWERED); +- flag3 |= flag4 && flag5; +- blockStates[i1] = blockState; +- if (i1 == shouldNotifyNeighbours) { +- level.scheduleTick(level1, block, 10); +- flag2 &= flag4; ++ boolean flag6 = !(Boolean) iblockdata2.getValue(TripWireBlock.DISARMED); ++ boolean flag7 = (Boolean) iblockdata2.getValue(TripWireBlock.POWERED); ++ ++ flag5 |= flag6 && flag7; ++ aiblockdata[k] = iblockdata2; ++ if (k == shouldNotifyNeighbours) { ++ world.scheduleTick(level, block, 10); ++ flag4 &= flag6; + } + } + } + +- boolean var21 = flag2 & i > 1; +- boolean var22 = flag3 & var21; +- BlockState blockState1 = block.defaultBlockState().trySetValue(ATTACHED, Boolean.valueOf(var21)).trySetValue(POWERED, Boolean.valueOf(var22)); +- if (i > 0) { +- BlockPos blockPosx = level1.relative(direction, i); +- Direction opposite = direction.getOpposite(); +- level.setBlock(blockPosx, blockState1.setValue(FACING, opposite), 3); +- notifyNeighbors(block, level, blockPosx, opposite); +- emitState(level, blockPosx, var21, var22, flag, flag1); ++ flag4 &= j > 1; ++ flag5 &= flag4; ++ IBlockData iblockdata3 = (IBlockData) ((IBlockData) block.defaultBlockState().trySetValue(TripWireHookBlock.ATTACHED, flag4)).trySetValue(TripWireHookBlock.POWERED, flag5); ++ ++ if (j > 0) { ++ blockposition1 = level.relative(enumdirection, j); ++ Direction enumdirection1 = enumdirection.getOpposite(); ++ ++ world.setBlock(blockposition1, (IBlockData) iblockdata3.setValue(TripWireHookBlock.FACING, enumdirection1), 3); ++ notifyNeighbors(block, world, blockposition1, enumdirection1); ++ emitState(world, blockposition1, flag4, flag5, flag2, flag3); + } + +- emitState(level, level1, var21, var22, flag, flag1); ++ // CraftBukkit start ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(world, level), 15, 0); ++ world.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if (eventRedstone.getNewCurrent() > 0) { ++ return; ++ } ++ // CraftBukkit end ++ ++ emitState(world, level, flag4, flag5, flag2, flag3); + if (!hookState) { +- level.setBlock(level1, blockState1.setValue(FACING, direction), 3); ++ world.setBlock(level, (IBlockData) iblockdata3.setValue(TripWireHookBlock.FACING, enumdirection), 3); + if (attaching) { +- notifyNeighbors(block, level, level1, direction); ++ notifyNeighbors(block, world, level, enumdirection); + } + } + +- if (flag != var21) { +- for (int i2 = 1; i2 < i; i2++) { +- BlockPos blockPos1 = level1.relative(direction, i2); +- BlockState blockState2 = blockStates[i2]; +- if (blockState2 != null) { +- level.setBlock(blockPos1, blockState2.trySetValue(ATTACHED, Boolean.valueOf(var21)), 3); +- if (!level.getBlockState(blockPos1).isAir()) { ++ if (flag2 != flag4) { ++ for (int l = 1; l < j; ++l) { ++ BlockPos blockposition2 = level.relative(enumdirection, l); ++ IBlockData iblockdata4 = aiblockdata[l]; ++ ++ if (iblockdata4 != null) { ++ world.setBlock(blockposition2, (IBlockData) iblockdata4.trySetValue(TripWireHookBlock.ATTACHED, flag4), 3); ++ if (!world.getBlockState(blockposition2).isAir()) { ++ ; + } + } + } + } ++ + } + } + + @Override +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- calculateState(level, pos, state, false, true, -1, null); ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { ++ calculateState(level, pos, state, false, true, -1, (IBlockData) null); + } + +- private static void emitState(Level level, BlockPos level1, boolean pos, boolean attached, boolean powered, boolean wasAttached) { ++ private static void emitState(Level world, BlockPos level, boolean pos, boolean attached, boolean powered, boolean wasAttached) { + if (attached && !wasAttached) { +- level.playSound(null, level1, SoundEvents.TRIPWIRE_CLICK_ON, SoundSource.BLOCKS, 0.4F, 0.6F); +- level.gameEvent(null, GameEvent.BLOCK_ACTIVATE, level1); ++ world.playSound((Player) null, level, SoundEvents.TRIPWIRE_CLICK_ON, SoundSource.BLOCKS, 0.4F, 0.6F); ++ world.gameEvent((Entity) null, GameEvent.BLOCK_ACTIVATE, level); + } else if (!attached && wasAttached) { +- level.playSound(null, level1, SoundEvents.TRIPWIRE_CLICK_OFF, SoundSource.BLOCKS, 0.4F, 0.5F); +- level.gameEvent(null, GameEvent.BLOCK_DEACTIVATE, level1); ++ world.playSound((Player) null, level, SoundEvents.TRIPWIRE_CLICK_OFF, SoundSource.BLOCKS, 0.4F, 0.5F); ++ world.gameEvent((Entity) null, GameEvent.BLOCK_DEACTIVATE, level); + } else if (pos && !powered) { +- level.playSound(null, level1, SoundEvents.TRIPWIRE_ATTACH, SoundSource.BLOCKS, 0.4F, 0.7F); +- level.gameEvent(null, GameEvent.BLOCK_ATTACH, level1); ++ world.playSound((Player) null, level, SoundEvents.TRIPWIRE_ATTACH, SoundSource.BLOCKS, 0.4F, 0.7F); ++ world.gameEvent((Entity) null, GameEvent.BLOCK_ATTACH, level); + } else if (!pos && powered) { +- level.playSound(null, level1, SoundEvents.TRIPWIRE_DETACH, SoundSource.BLOCKS, 0.4F, 1.2F / (level.random.nextFloat() * 0.2F + 0.9F)); +- level.gameEvent(null, GameEvent.BLOCK_DETACH, level1); ++ world.playSound((Player) null, level, SoundEvents.TRIPWIRE_DETACH, SoundSource.BLOCKS, 0.4F, 1.2F / (world.random.nextFloat() * 0.2F + 0.9F)); ++ world.gameEvent((Entity) null, GameEvent.BLOCK_DETACH, level); + } ++ + } + +- private static void notifyNeighbors(Block block, Level level, BlockPos blockPos, Direction direction) { +- level.updateNeighborsAt(blockPos, block); +- level.updateNeighborsAt(blockPos.relative(direction.getOpposite()), block); ++ private static void notifyNeighbors(Block block, Level world, BlockPos blockposition, Direction enumdirection) { ++ world.updateNeighborsAt(blockposition, block); ++ world.updateNeighborsAt(blockposition.relative(enumdirection.getOpposite()), block); + } + + @Override +- public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean isMoving) { + if (!isMoving && !state.is(newState.getBlock())) { +- boolean flag = state.getValue(ATTACHED); +- boolean flag1 = state.getValue(POWERED); +- if (flag || flag1) { +- calculateState(level, pos, state, true, false, -1, null); ++ boolean flag1 = (Boolean) state.getValue(TripWireHookBlock.ATTACHED); ++ boolean flag2 = (Boolean) state.getValue(TripWireHookBlock.POWERED); ++ ++ if (flag1 || flag2) { ++ calculateState(level, pos, state, true, false, -1, (IBlockData) null); + } + +- if (flag1) { ++ if (flag2) { + level.updateNeighborsAt(pos, this); +- level.updateNeighborsAt(pos.relative(state.getValue(FACING).getOpposite()), this); ++ level.updateNeighborsAt(pos.relative(((Direction) state.getValue(TripWireHookBlock.FACING)).getOpposite()), this); + } + + super.onRemove(state, level, pos, newState, isMoving); +@@ -230,36 +258,32 @@ + } + + @Override +- public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { +- return blockState.getValue(POWERED) ? 15 : 0; ++ public int getSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return (Boolean) blockState.getValue(TripWireHookBlock.POWERED) ? 15 : 0; + } + + @Override +- public int getDirectSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { +- if (!blockState.getValue(POWERED)) { +- return 0; +- } else { +- return blockState.getValue(FACING) == side ? 15 : 0; +- } ++ public int getDirectSignal(IBlockData blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { ++ return !(Boolean) blockState.getValue(TripWireHookBlock.POWERED) ? 0 : (blockState.getValue(TripWireHookBlock.FACING) == side ? 15 : 0); + } + + @Override +- public boolean isSignalSource(BlockState state) { ++ public boolean isSignalSource(IBlockData state) { + return true; + } + + @Override +- public BlockState rotate(BlockState state, Rotation rotation) { +- return state.setValue(FACING, rotation.rotate(state.getValue(FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return (IBlockData) state.setValue(TripWireHookBlock.FACING, rotation.rotate((Direction) state.getValue(TripWireHookBlock.FACING))); + } + + @Override +- public BlockState mirror(BlockState state, Mirror mirror) { +- return state.rotate(mirror.getRotation(state.getValue(FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(TripWireHookBlock.FACING))); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(FACING, POWERED, ATTACHED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(TripWireHookBlock.FACING, TripWireHookBlock.POWERED, TripWireHookBlock.ATTACHED); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/TurtleEggBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/TurtleEggBlock.java.patch new file mode 100644 index 0000000000..f0c7ff9a36 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/TurtleEggBlock.java.patch @@ -0,0 +1,228 @@ +--- a/net/minecraft/world/level/block/TurtleEggBlock.java ++++ b/net/minecraft/world/level/block/TurtleEggBlock.java +@@ -22,36 +22,42 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.event.entity.EntityInteractEvent; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class TurtleEggBlock extends Block { ++ + public static final MapCodec CODEC = simpleCodec(TurtleEggBlock::new); + public static final int MAX_HATCH_LEVEL = 2; + public static final int MIN_EGGS = 1; + public static final int MAX_EGGS = 4; +- private static final VoxelShape ONE_EGG_AABB = Block.box(3.0, 0.0, 3.0, 12.0, 7.0, 12.0); +- private static final VoxelShape MULTIPLE_EGGS_AABB = Block.box(1.0, 0.0, 1.0, 15.0, 7.0, 15.0); ++ private static final VoxelShape ONE_EGG_AABB = Block.box(3.0D, 0.0D, 3.0D, 12.0D, 7.0D, 12.0D); ++ private static final VoxelShape MULTIPLE_EGGS_AABB = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 7.0D, 15.0D); + public static final IntegerProperty HATCH = BlockStateProperties.HATCH; + public static final IntegerProperty EGGS = BlockStateProperties.EGGS; + + @Override + public MapCodec codec() { +- return CODEC; ++ return TurtleEggBlock.CODEC; + } + + public TurtleEggBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(HATCH, Integer.valueOf(0)).setValue(EGGS, Integer.valueOf(1))); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(TurtleEggBlock.HATCH, 0)).setValue(TurtleEggBlock.EGGS, 1)); + } + + @Override +- public void stepOn(Level level, BlockPos pos, BlockState state, Entity entity) { ++ public void stepOn(Level level, BlockPos pos, IBlockData state, Entity entity) { + if (!entity.isSteppingCarefully()) { + this.destroyEgg(level, state, pos, entity, 100); + } +@@ -60,7 +66,7 @@ + } + + @Override +- public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, float fallDistance) { ++ public void fallOn(Level level, IBlockData state, BlockPos pos, Entity entity, float fallDistance) { + if (!(entity instanceof Zombie)) { + this.destroyEgg(level, state, pos, entity, 3); + } +@@ -68,51 +74,80 @@ + super.fallOn(level, state, pos, entity, fallDistance); + } + +- private void destroyEgg(Level level, BlockState state, BlockPos pos, Entity entity, int chance) { ++ private void destroyEgg(Level level, IBlockData state, BlockPos pos, Entity entity, int chance) { + if (this.canDestroyEgg(level, entity)) { + if (!level.isClientSide && level.random.nextInt(chance) == 0 && state.is(Blocks.TURTLE_EGG)) { ++ // CraftBukkit start - Step on eggs ++ org.bukkit.event.Cancellable cancellable; ++ if (entity instanceof Player) { ++ cancellable = CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), CraftBlock.at(level, pos)); ++ level.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ if (cancellable.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.decreaseEggs(level, pos, state); + } ++ + } + } + +- private void decreaseEggs(Level level, BlockPos pos, BlockState state) { +- level.playSound(null, pos, SoundEvents.TURTLE_EGG_BREAK, SoundSource.BLOCKS, 0.7F, 0.9F + level.random.nextFloat() * 0.2F); +- int i = state.getValue(EGGS); ++ private void decreaseEggs(Level level, BlockPos pos, IBlockData state) { ++ level.playSound((Player) null, pos, SoundEvents.TURTLE_EGG_BREAK, SoundSource.BLOCKS, 0.7F, 0.9F + level.random.nextFloat() * 0.2F); ++ int i = (Integer) state.getValue(TurtleEggBlock.EGGS); ++ + if (i <= 1) { + level.destroyBlock(pos, false); + } else { +- level.setBlock(pos, state.setValue(EGGS, Integer.valueOf(i - 1)), 2); ++ level.setBlock(pos, (IBlockData) state.setValue(TurtleEggBlock.EGGS, i - 1), 2); + level.gameEvent(GameEvent.BLOCK_DESTROY, pos, GameEvent.Context.of(state)); + level.levelEvent(2001, pos, Block.getId(state)); + } ++ + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (this.shouldUpdateHatchLevel(level) && onSand(level, pos)) { +- int i = state.getValue(HATCH); ++ int i = (Integer) state.getValue(TurtleEggBlock.HATCH); ++ + if (i < 2) { +- level.playSound(null, pos, SoundEvents.TURTLE_EGG_CRACK, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F); +- level.setBlock(pos, state.setValue(HATCH, Integer.valueOf(i + 1)), 2); ++ // CraftBukkit start - Call BlockGrowEvent ++ if (!CraftEventFactory.handleBlockGrowEvent(level, pos, state.setValue(TurtleEggBlock.HATCH, i + 1), 2)) { ++ return; ++ } ++ // CraftBukkit end ++ level.playSound((Player) null, pos, SoundEvents.TURTLE_EGG_CRACK, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F); ++ // worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockTurtleEgg.HATCH, i + 1), 2); // CraftBukkit - handled above + level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(state)); + } else { +- level.playSound(null, pos, SoundEvents.TURTLE_EGG_HATCH, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F); ++ // CraftBukkit start - Call BlockFadeEvent ++ if (CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.AIR.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ level.playSound((Player) null, pos, SoundEvents.TURTLE_EGG_HATCH, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F); + level.removeBlock(pos, false); + level.gameEvent(GameEvent.BLOCK_DESTROY, pos, GameEvent.Context.of(state)); + +- for (int i1 = 0; i1 < state.getValue(EGGS); i1++) { ++ for (int j = 0; j < (Integer) state.getValue(TurtleEggBlock.EGGS); ++j) { + level.levelEvent(2001, pos, Block.getId(state)); +- Turtle turtle = EntityType.TURTLE.create(level); +- if (turtle != null) { +- turtle.setAge(-24000); +- turtle.setHomePos(pos); +- turtle.moveTo((double)pos.getX() + 0.3 + (double)i1 * 0.2, (double)pos.getY(), (double)pos.getZ() + 0.3, 0.0F, 0.0F); +- level.addFreshEntity(turtle); ++ Turtle entityturtle = (Turtle) EntityType.TURTLE.create(level); ++ ++ if (entityturtle != null) { ++ entityturtle.setAge(-24000); ++ entityturtle.setHomePos(pos); ++ entityturtle.moveTo((double) pos.getX() + 0.3D + (double) j * 0.2D, (double) pos.getY(), (double) pos.getZ() + 0.3D, 0.0F, 0.0F); ++ level.addFreshEntity(entityturtle, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); // CraftBukkit + } + } + } + } ++ + } + + public static boolean onSand(BlockGetter level, BlockPos pos) { +@@ -124,52 +159,49 @@ + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { + if (onSand(level, pos) && !level.isClientSide) { + level.levelEvent(2005, pos, 0); + } ++ + } + + private boolean shouldUpdateHatchLevel(Level level) { +- float timeOfDay = level.getTimeOfDay(1.0F); +- return (double)timeOfDay < 0.69 && (double)timeOfDay > 0.65 || level.random.nextInt(500) == 0; ++ float f = level.getTimeOfDay(1.0F); ++ ++ return (double) f < 0.69D && (double) f > 0.65D ? true : level.random.nextInt(500) == 0; + } + + @Override +- public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity te, ItemStack stack) { ++ public void playerDestroy(Level level, Player player, BlockPos pos, IBlockData state, @Nullable BlockEntity te, ItemStack stack) { + super.playerDestroy(level, player, pos, state, te, stack); + this.decreaseEggs(level, pos, state); + } + + @Override +- public boolean canBeReplaced(BlockState state, BlockPlaceContext useContext) { +- return !useContext.isSecondaryUseActive() && useContext.getItemInHand().is(this.asItem()) && state.getValue(EGGS) < 4 +- || super.canBeReplaced(state, useContext); ++ public boolean canBeReplaced(IBlockData state, BlockPlaceContext useContext) { ++ return !useContext.isSecondaryUseActive() && useContext.getItemInHand().is(this.asItem()) && (Integer) state.getValue(TurtleEggBlock.EGGS) < 4 ? true : super.canBeReplaced(state, useContext); + } + + @Nullable + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- BlockState blockState = context.getLevel().getBlockState(context.getClickedPos()); +- return blockState.is(this) +- ? blockState.setValue(EGGS, Integer.valueOf(Math.min(4, blockState.getValue(EGGS) + 1))) +- : super.getStateForPlacement(context); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ IBlockData iblockdata = context.getLevel().getBlockState(context.getClickedPos()); ++ ++ return iblockdata.is((Block) this) ? (IBlockData) iblockdata.setValue(TurtleEggBlock.EGGS, Math.min(4, (Integer) iblockdata.getValue(TurtleEggBlock.EGGS) + 1)) : super.getStateForPlacement(context); + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return state.getValue(EGGS) > 1 ? MULTIPLE_EGGS_AABB : ONE_EGG_AABB; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (Integer) state.getValue(TurtleEggBlock.EGGS) > 1 ? TurtleEggBlock.MULTIPLE_EGGS_AABB : TurtleEggBlock.ONE_EGG_AABB; + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(HATCH, EGGS); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(TurtleEggBlock.HATCH, TurtleEggBlock.EGGS); + } + + private boolean canDestroyEgg(Level level, Entity entity) { +- return !(entity instanceof Turtle) +- && !(entity instanceof Bat) +- && entity instanceof LivingEntity +- && (entity instanceof Player || level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)); ++ return !(entity instanceof Turtle) && !(entity instanceof Bat) ? (!(entity instanceof LivingEntity) ? false : entity instanceof Player || level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) : false; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/VineBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/VineBlock.java.patch new file mode 100644 index 0000000000..1833700717 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/VineBlock.java.patch @@ -0,0 +1,534 @@ +--- a/net/minecraft/world/level/block/VineBlock.java ++++ b/net/minecraft/world/level/block/VineBlock.java +@@ -2,8 +2,8 @@ + + import com.google.common.collect.ImmutableMap; + import com.mojang.serialization.MapCodec; ++import java.util.Iterator; + import java.util.Map; +-import java.util.Map.Entry; + import java.util.function.Function; + import java.util.stream.Collectors; + import javax.annotation.Nullable; +@@ -18,104 +18,98 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit + + public class VineBlock extends Block { ++ + public static final MapCodec CODEC = simpleCodec(VineBlock::new); + public static final BooleanProperty UP = PipeBlock.UP; + public static final BooleanProperty NORTH = PipeBlock.NORTH; + public static final BooleanProperty EAST = PipeBlock.EAST; + public static final BooleanProperty SOUTH = PipeBlock.SOUTH; + public static final BooleanProperty WEST = PipeBlock.WEST; +- public static final Map PROPERTY_BY_DIRECTION = PipeBlock.PROPERTY_BY_DIRECTION +- .entrySet() +- .stream() +- .filter(entry -> entry.getKey() != Direction.DOWN) +- .collect(Util.toMap()); ++ public static final Map PROPERTY_BY_DIRECTION = (Map) PipeBlock.PROPERTY_BY_DIRECTION.entrySet().stream().filter((entry) -> { ++ return entry.getKey() != Direction.DOWN; ++ }).collect(Util.toMap()); + protected static final float AABB_OFFSET = 1.0F; +- private static final VoxelShape UP_AABB = Block.box(0.0, 15.0, 0.0, 16.0, 16.0, 16.0); +- private static final VoxelShape WEST_AABB = Block.box(0.0, 0.0, 0.0, 1.0, 16.0, 16.0); +- private static final VoxelShape EAST_AABB = Block.box(15.0, 0.0, 0.0, 16.0, 16.0, 16.0); +- private static final VoxelShape NORTH_AABB = Block.box(0.0, 0.0, 0.0, 16.0, 16.0, 1.0); +- private static final VoxelShape SOUTH_AABB = Block.box(0.0, 0.0, 15.0, 16.0, 16.0, 16.0); +- private final Map shapesCache; ++ private static final VoxelShape UP_AABB = Block.box(0.0D, 15.0D, 0.0D, 16.0D, 16.0D, 16.0D); ++ private static final VoxelShape WEST_AABB = Block.box(0.0D, 0.0D, 0.0D, 1.0D, 16.0D, 16.0D); ++ private static final VoxelShape EAST_AABB = Block.box(15.0D, 0.0D, 0.0D, 16.0D, 16.0D, 16.0D); ++ private static final VoxelShape NORTH_AABB = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 16.0D, 1.0D); ++ private static final VoxelShape SOUTH_AABB = Block.box(0.0D, 0.0D, 15.0D, 16.0D, 16.0D, 16.0D); ++ private final Map shapesCache; + + @Override + public MapCodec codec() { +- return CODEC; ++ return VineBlock.CODEC; + } + + public VineBlock(BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState( +- this.stateDefinition +- .any() +- .setValue(UP, Boolean.valueOf(false)) +- .setValue(NORTH, Boolean.valueOf(false)) +- .setValue(EAST, Boolean.valueOf(false)) +- .setValue(SOUTH, Boolean.valueOf(false)) +- .setValue(WEST, Boolean.valueOf(false)) +- ); +- this.shapesCache = ImmutableMap.copyOf( +- this.stateDefinition.getPossibleStates().stream().collect(Collectors.toMap(Function.identity(), VineBlock::calculateShape)) +- ); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(VineBlock.UP, false)).setValue(VineBlock.NORTH, false)).setValue(VineBlock.EAST, false)).setValue(VineBlock.SOUTH, false)).setValue(VineBlock.WEST, false)); ++ this.shapesCache = ImmutableMap.copyOf((Map) this.stateDefinition.getPossibleStates().stream().collect(Collectors.toMap(Function.identity(), VineBlock::calculateShape))); + } + +- private static VoxelShape calculateShape(BlockState state) { +- VoxelShape voxelShape = Shapes.empty(); +- if (state.getValue(UP)) { +- voxelShape = UP_AABB; ++ private static VoxelShape calculateShape(IBlockData state) { ++ VoxelShape voxelshape = Shapes.empty(); ++ ++ if ((Boolean) state.getValue(VineBlock.UP)) { ++ voxelshape = VineBlock.UP_AABB; + } + +- if (state.getValue(NORTH)) { +- voxelShape = Shapes.or(voxelShape, NORTH_AABB); ++ if ((Boolean) state.getValue(VineBlock.NORTH)) { ++ voxelshape = Shapes.or(voxelshape, VineBlock.NORTH_AABB); + } + +- if (state.getValue(SOUTH)) { +- voxelShape = Shapes.or(voxelShape, SOUTH_AABB); ++ if ((Boolean) state.getValue(VineBlock.SOUTH)) { ++ voxelshape = Shapes.or(voxelshape, VineBlock.SOUTH_AABB); + } + +- if (state.getValue(EAST)) { +- voxelShape = Shapes.or(voxelShape, EAST_AABB); ++ if ((Boolean) state.getValue(VineBlock.EAST)) { ++ voxelshape = Shapes.or(voxelshape, VineBlock.EAST_AABB); + } + +- if (state.getValue(WEST)) { +- voxelShape = Shapes.or(voxelShape, WEST_AABB); ++ if ((Boolean) state.getValue(VineBlock.WEST)) { ++ voxelshape = Shapes.or(voxelshape, VineBlock.WEST_AABB); + } + +- return voxelShape.isEmpty() ? Shapes.block() : voxelShape; ++ return voxelshape.isEmpty() ? Shapes.block() : voxelshape; + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return this.shapesCache.get(state); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (VoxelShape) this.shapesCache.get(state); + } + + @Override +- public boolean propagatesSkylightDown(BlockState state, BlockGetter level, BlockPos pos) { ++ public boolean propagatesSkylightDown(IBlockData state, BlockGetter level, BlockPos pos) { + return true; + } + + @Override +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { + return this.hasFaces(this.getUpdatedState(state, level, pos)); + } + +- private boolean hasFaces(BlockState state) { ++ private boolean hasFaces(IBlockData state) { + return this.countFaces(state) > 0; + } + +- private int countFaces(BlockState state) { ++ private int countFaces(IBlockData state) { + int i = 0; ++ Iterator iterator = VineBlock.PROPERTY_BY_DIRECTION.values().iterator(); + +- for (BooleanProperty booleanProperty : PROPERTY_BY_DIRECTION.values()) { +- if (state.getValue(booleanProperty)) { +- i++; ++ while (iterator.hasNext()) { ++ BooleanProperty blockstateboolean = (BooleanProperty) iterator.next(); ++ ++ if ((Boolean) state.getValue(blockstateboolean)) { ++ ++i; + } + } + +@@ -126,15 +120,17 @@ + if (direction == Direction.DOWN) { + return false; + } else { +- BlockPos blockPos = pos.relative(direction); +- if (isAcceptableNeighbour(level, blockPos, direction)) { ++ BlockPos blockposition1 = pos.relative(direction); ++ ++ if (isAcceptableNeighbour(level, blockposition1, direction)) { + return true; + } else if (direction.getAxis() == Direction.Axis.Y) { + return false; + } else { +- BooleanProperty booleanProperty = PROPERTY_BY_DIRECTION.get(direction); +- BlockState blockState = level.getBlockState(pos.above()); +- return blockState.is(this) && blockState.getValue(booleanProperty); ++ BooleanProperty blockstateboolean = (BooleanProperty) VineBlock.PROPERTY_BY_DIRECTION.get(direction); ++ IBlockData iblockdata = level.getBlockState(pos.above()); ++ ++ return iblockdata.is((Block) this) && (Boolean) iblockdata.getValue(blockstateboolean); + } + } + } +@@ -143,27 +139,32 @@ + return MultifaceBlock.canAttachTo(blockReader, attachedFace, neighborPos, blockReader.getBlockState(neighborPos)); + } + +- private BlockState getUpdatedState(BlockState state, BlockGetter level, BlockPos pos) { +- BlockPos blockPos = pos.above(); +- if (state.getValue(UP)) { +- state = state.setValue(UP, Boolean.valueOf(isAcceptableNeighbour(level, blockPos, Direction.DOWN))); ++ private IBlockData getUpdatedState(IBlockData state, BlockGetter level, BlockPos pos) { ++ BlockPos blockposition1 = pos.above(); ++ ++ if ((Boolean) state.getValue(VineBlock.UP)) { ++ state = (IBlockData) state.setValue(VineBlock.UP, isAcceptableNeighbour(level, blockposition1, Direction.DOWN)); + } + +- BlockState blockState = null; ++ IBlockData iblockdata1 = null; ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- BooleanProperty propertyForFace = getPropertyForFace(direction); +- if (state.getValue(propertyForFace)) { +- boolean canSupportAtFace = this.canSupportAtFace(level, pos, direction); +- if (!canSupportAtFace) { +- if (blockState == null) { +- blockState = level.getBlockState(blockPos); ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ BooleanProperty blockstateboolean = getPropertyForFace(enumdirection); ++ ++ if ((Boolean) state.getValue(blockstateboolean)) { ++ boolean flag = this.canSupportAtFace(level, pos, enumdirection); ++ ++ if (!flag) { ++ if (iblockdata1 == null) { ++ iblockdata1 = level.getBlockState(blockposition1); + } + +- canSupportAtFace = blockState.is(this) && blockState.getValue(propertyForFace); ++ flag = iblockdata1.is((Block) this) && (Boolean) iblockdata1.getValue(blockstateboolean); + } + +- state = state.setValue(propertyForFace, Boolean.valueOf(canSupportAtFace)); ++ state = (IBlockData) state.setValue(blockstateboolean, flag); + } + } + +@@ -171,72 +172,86 @@ + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { + if (facing == Direction.DOWN) { + return super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } else { +- BlockState updatedState = this.getUpdatedState(state, level, currentPos); +- return !this.hasFaces(updatedState) ? Blocks.AIR.defaultBlockState() : updatedState; ++ IBlockData iblockdata2 = this.getUpdatedState(state, level, currentPos); ++ ++ return !this.hasFaces(iblockdata2) ? Blocks.AIR.defaultBlockState() : iblockdata2; + } + } + + @Override +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) { + if (level.getGameRules().getBoolean(GameRules.RULE_DO_VINES_SPREAD)) { + if (random.nextInt(4) == 0) { +- Direction random1 = Direction.getRandom(random); +- BlockPos blockPos = pos.above(); +- if (random1.getAxis().isHorizontal() && !state.getValue(getPropertyForFace(random1))) { ++ Direction enumdirection = Direction.getRandom(random); ++ BlockPos blockposition1 = pos.above(); ++ BlockPos blockposition2; ++ IBlockData iblockdata1; ++ Direction enumdirection1; ++ ++ if (enumdirection.getAxis().isHorizontal() && !(Boolean) state.getValue(getPropertyForFace(enumdirection))) { + if (this.canSpread(level, pos)) { +- BlockPos blockPos1 = pos.relative(random1); +- BlockState blockState = level.getBlockState(blockPos1); +- if (blockState.isAir()) { +- Direction clockWise = random1.getClockWise(); +- Direction counterClockWise = random1.getCounterClockWise(); +- boolean flag = state.getValue(getPropertyForFace(clockWise)); +- boolean flag1 = state.getValue(getPropertyForFace(counterClockWise)); +- BlockPos blockPos2 = blockPos1.relative(clockWise); +- BlockPos blockPos3 = blockPos1.relative(counterClockWise); +- if (flag && isAcceptableNeighbour(level, blockPos2, clockWise)) { +- level.setBlock(blockPos1, this.defaultBlockState().setValue(getPropertyForFace(clockWise), Boolean.valueOf(true)), 2); +- } else if (flag1 && isAcceptableNeighbour(level, blockPos3, counterClockWise)) { +- level.setBlock(blockPos1, this.defaultBlockState().setValue(getPropertyForFace(counterClockWise), Boolean.valueOf(true)), 2); ++ blockposition2 = pos.relative(enumdirection); ++ iblockdata1 = level.getBlockState(blockposition2); ++ if (iblockdata1.isAir()) { ++ enumdirection1 = enumdirection.getClockWise(); ++ Direction enumdirection2 = enumdirection.getCounterClockWise(); ++ boolean flag = (Boolean) state.getValue(getPropertyForFace(enumdirection1)); ++ boolean flag1 = (Boolean) state.getValue(getPropertyForFace(enumdirection2)); ++ BlockPos blockposition3 = blockposition2.relative(enumdirection1); ++ BlockPos blockposition4 = blockposition2.relative(enumdirection2); ++ ++ // CraftBukkit start - Call BlockSpreadEvent ++ BlockPos source = pos; ++ ++ if (flag && isAcceptableNeighbour(level, blockposition3, enumdirection1)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, source, blockposition2, (IBlockData) this.defaultBlockState().setValue(getPropertyForFace(enumdirection1), true), 2); ++ } else if (flag1 && isAcceptableNeighbour(level, blockposition4, enumdirection2)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, source, blockposition2, (IBlockData) this.defaultBlockState().setValue(getPropertyForFace(enumdirection2), true), 2); + } else { +- Direction opposite = random1.getOpposite(); +- if (flag && level.isEmptyBlock(blockPos2) && isAcceptableNeighbour(level, pos.relative(clockWise), opposite)) { +- level.setBlock(blockPos2, this.defaultBlockState().setValue(getPropertyForFace(opposite), Boolean.valueOf(true)), 2); +- } else if (flag1 && level.isEmptyBlock(blockPos3) && isAcceptableNeighbour(level, pos.relative(counterClockWise), opposite)) { +- level.setBlock(blockPos3, this.defaultBlockState().setValue(getPropertyForFace(opposite), Boolean.valueOf(true)), 2); +- } else if ((double)random.nextFloat() < 0.05 && isAcceptableNeighbour(level, blockPos1.above(), Direction.UP)) { +- level.setBlock(blockPos1, this.defaultBlockState().setValue(UP, Boolean.valueOf(true)), 2); ++ Direction enumdirection3 = enumdirection.getOpposite(); ++ ++ if (flag && level.isEmptyBlock(blockposition3) && isAcceptableNeighbour(level, pos.relative(enumdirection1), enumdirection3)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, source, blockposition3, (IBlockData) this.defaultBlockState().setValue(getPropertyForFace(enumdirection3), true), 2); ++ } else if (flag1 && level.isEmptyBlock(blockposition4) && isAcceptableNeighbour(level, pos.relative(enumdirection2), enumdirection3)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, source, blockposition4, (IBlockData) this.defaultBlockState().setValue(getPropertyForFace(enumdirection3), true), 2); ++ } else if ((double) random.nextFloat() < 0.05D && isAcceptableNeighbour(level, blockposition2.above(), Direction.UP)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, source, blockposition2, (IBlockData) this.defaultBlockState().setValue(VineBlock.UP, true), 2); + } ++ // CraftBukkit end + } +- } else if (isAcceptableNeighbour(level, blockPos1, random1)) { +- level.setBlock(pos, state.setValue(getPropertyForFace(random1), Boolean.valueOf(true)), 2); ++ } else if (isAcceptableNeighbour(level, blockposition2, enumdirection)) { ++ CraftEventFactory.handleBlockGrowEvent(level, pos, (IBlockData) state.setValue(getPropertyForFace(enumdirection), true), 2); // CraftBukkit + } ++ + } + } else { +- if (random1 == Direction.UP && pos.getY() < level.getMaxBuildHeight() - 1) { +- if (this.canSupportAtFace(level, pos, random1)) { +- level.setBlock(pos, state.setValue(UP, Boolean.valueOf(true)), 2); ++ if (enumdirection == Direction.UP && pos.getY() < level.getMaxBuildHeight() - 1) { ++ if (this.canSupportAtFace(level, pos, enumdirection)) { ++ CraftEventFactory.handleBlockGrowEvent(level, pos, (IBlockData) state.setValue(VineBlock.UP, true), 2); // CraftBukkit + return; + } + +- if (level.isEmptyBlock(blockPos)) { ++ if (level.isEmptyBlock(blockposition1)) { + if (!this.canSpread(level, pos)) { + return; + } + +- BlockState blockState1 = state; ++ IBlockData iblockdata2 = state; ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction clockWise : Direction.Plane.HORIZONTAL) { +- if (random.nextBoolean() || !isAcceptableNeighbour(level, blockPos.relative(clockWise), clockWise)) { +- blockState1 = blockState1.setValue(getPropertyForFace(clockWise), Boolean.valueOf(false)); ++ while (iterator.hasNext()) { ++ enumdirection1 = (Direction) iterator.next(); ++ if (random.nextBoolean() || !isAcceptableNeighbour(level, blockposition1.relative(enumdirection1), enumdirection1)) { ++ iblockdata2 = (IBlockData) iblockdata2.setValue(getPropertyForFace(enumdirection1), false); + } + } + +- if (this.hasHorizontalConnection(blockState1)) { +- level.setBlock(blockPos, blockState1, 2); ++ if (this.hasHorizontalConnection(iblockdata2)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition1, iblockdata2, 2); // CraftBukkit + } + + return; +@@ -244,27 +259,34 @@ + } + + if (pos.getY() > level.getMinBuildHeight()) { +- BlockPos blockPos1 = pos.below(); +- BlockState blockState = level.getBlockState(blockPos1); +- if (blockState.isAir() || blockState.is(this)) { +- BlockState blockState2 = blockState.isAir() ? this.defaultBlockState() : blockState; +- BlockState blockState3 = this.copyRandomFaces(state, blockState2, random); +- if (blockState2 != blockState3 && this.hasHorizontalConnection(blockState3)) { +- level.setBlock(blockPos1, blockState3, 2); ++ blockposition2 = pos.below(); ++ iblockdata1 = level.getBlockState(blockposition2); ++ if (iblockdata1.isAir() || iblockdata1.is((Block) this)) { ++ IBlockData iblockdata3 = iblockdata1.isAir() ? this.defaultBlockState() : iblockdata1; ++ IBlockData iblockdata4 = this.copyRandomFaces(state, iblockdata3, random); ++ ++ if (iblockdata3 != iblockdata4 && this.hasHorizontalConnection(iblockdata4)) { ++ CraftEventFactory.handleBlockSpreadEvent(level, pos, blockposition2, iblockdata4, 2); // CraftBukkit + } + } + } ++ + } + } + } + } + +- private BlockState copyRandomFaces(BlockState sourceState, BlockState spreadState, RandomSource random) { +- for (Direction direction : Direction.Plane.HORIZONTAL) { ++ private IBlockData copyRandomFaces(IBlockData sourceState, IBlockData spreadState, RandomSource random) { ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); ++ ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ + if (random.nextBoolean()) { +- BooleanProperty propertyForFace = getPropertyForFace(direction); +- if (sourceState.getValue(propertyForFace)) { +- spreadState = spreadState.setValue(propertyForFace, Boolean.valueOf(true)); ++ BooleanProperty blockstateboolean = getPropertyForFace(enumdirection); ++ ++ if ((Boolean) sourceState.getValue(blockstateboolean)) { ++ spreadState = (IBlockData) spreadState.setValue(blockstateboolean, true); + } + } + } +@@ -272,18 +294,22 @@ + return spreadState; + } + +- private boolean hasHorizontalConnection(BlockState state) { +- return state.getValue(NORTH) || state.getValue(EAST) || state.getValue(SOUTH) || state.getValue(WEST); ++ private boolean hasHorizontalConnection(IBlockData state) { ++ return (Boolean) state.getValue(VineBlock.NORTH) || (Boolean) state.getValue(VineBlock.EAST) || (Boolean) state.getValue(VineBlock.SOUTH) || (Boolean) state.getValue(VineBlock.WEST); + } + + private boolean canSpread(BlockGetter blockReader, BlockPos pos) { +- int i = 4; ++ boolean flag = true; + Iterable iterable = BlockPos.betweenClosed(pos.getX() - 4, pos.getY() - 1, pos.getZ() - 4, pos.getX() + 4, pos.getY() + 1, pos.getZ() + 4); +- int i1 = 5; ++ int i = 5; ++ Iterator iterator = iterable.iterator(); + +- for (BlockPos blockPos : iterable) { +- if (blockReader.getBlockState(blockPos).is(this)) { +- if (--i1 <= 0) { ++ while (iterator.hasNext()) { ++ BlockPos blockposition1 = (BlockPos) iterator.next(); ++ ++ if (blockReader.getBlockState(blockposition1).is((Block) this)) { ++ --i; ++ if (i <= 0) { + return false; + } + } +@@ -293,72 +319,69 @@ + } + + @Override +- public boolean canBeReplaced(BlockState state, BlockPlaceContext useContext) { +- BlockState blockState = useContext.getLevel().getBlockState(useContext.getClickedPos()); +- return blockState.is(this) ? this.countFaces(blockState) < PROPERTY_BY_DIRECTION.size() : super.canBeReplaced(state, useContext); ++ public boolean canBeReplaced(IBlockData state, BlockPlaceContext useContext) { ++ IBlockData iblockdata1 = useContext.getLevel().getBlockState(useContext.getClickedPos()); ++ ++ return iblockdata1.is((Block) this) ? this.countFaces(iblockdata1) < VineBlock.PROPERTY_BY_DIRECTION.size() : super.canBeReplaced(state, useContext); + } + + @Nullable + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- BlockState blockState = context.getLevel().getBlockState(context.getClickedPos()); +- boolean isBlock = blockState.is(this); +- BlockState blockState1 = isBlock ? blockState : this.defaultBlockState(); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ IBlockData iblockdata = context.getLevel().getBlockState(context.getClickedPos()); ++ boolean flag = iblockdata.is((Block) this); ++ IBlockData iblockdata1 = flag ? iblockdata : this.defaultBlockState(); ++ Direction[] aenumdirection = context.getNearestLookingDirections(); ++ int i = aenumdirection.length; + +- for (Direction direction : context.getNearestLookingDirections()) { +- if (direction != Direction.DOWN) { +- BooleanProperty propertyForFace = getPropertyForFace(direction); +- boolean flag = isBlock && blockState.getValue(propertyForFace); +- if (!flag && this.canSupportAtFace(context.getLevel(), context.getClickedPos(), direction)) { +- return blockState1.setValue(propertyForFace, Boolean.valueOf(true)); ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ ++ if (enumdirection != Direction.DOWN) { ++ BooleanProperty blockstateboolean = getPropertyForFace(enumdirection); ++ boolean flag1 = flag && (Boolean) iblockdata.getValue(blockstateboolean); ++ ++ if (!flag1 && this.canSupportAtFace(context.getLevel(), context.getClickedPos(), enumdirection)) { ++ return (IBlockData) iblockdata1.setValue(blockstateboolean, true); + } + } + } + +- return isBlock ? blockState1 : null; ++ return flag ? iblockdata1 : null; + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(UP, NORTH, EAST, SOUTH, WEST); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(VineBlock.UP, VineBlock.NORTH, VineBlock.EAST, VineBlock.SOUTH, VineBlock.WEST); + } + + @Override +- public BlockState rotate(BlockState state, Rotation rotate) { ++ public IBlockData rotate(IBlockData state, Rotation rotate) { + switch (rotate) { + case CLOCKWISE_180: +- return state.setValue(NORTH, state.getValue(SOUTH)) +- .setValue(EAST, state.getValue(WEST)) +- .setValue(SOUTH, state.getValue(NORTH)) +- .setValue(WEST, state.getValue(EAST)); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) state.setValue(VineBlock.NORTH, (Boolean) state.getValue(VineBlock.SOUTH))).setValue(VineBlock.EAST, (Boolean) state.getValue(VineBlock.WEST))).setValue(VineBlock.SOUTH, (Boolean) state.getValue(VineBlock.NORTH))).setValue(VineBlock.WEST, (Boolean) state.getValue(VineBlock.EAST)); + case COUNTERCLOCKWISE_90: +- return state.setValue(NORTH, state.getValue(EAST)) +- .setValue(EAST, state.getValue(SOUTH)) +- .setValue(SOUTH, state.getValue(WEST)) +- .setValue(WEST, state.getValue(NORTH)); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) state.setValue(VineBlock.NORTH, (Boolean) state.getValue(VineBlock.EAST))).setValue(VineBlock.EAST, (Boolean) state.getValue(VineBlock.SOUTH))).setValue(VineBlock.SOUTH, (Boolean) state.getValue(VineBlock.WEST))).setValue(VineBlock.WEST, (Boolean) state.getValue(VineBlock.NORTH)); + case CLOCKWISE_90: +- return state.setValue(NORTH, state.getValue(WEST)) +- .setValue(EAST, state.getValue(NORTH)) +- .setValue(SOUTH, state.getValue(EAST)) +- .setValue(WEST, state.getValue(SOUTH)); ++ return (IBlockData) ((IBlockData) ((IBlockData) ((IBlockData) state.setValue(VineBlock.NORTH, (Boolean) state.getValue(VineBlock.WEST))).setValue(VineBlock.EAST, (Boolean) state.getValue(VineBlock.NORTH))).setValue(VineBlock.SOUTH, (Boolean) state.getValue(VineBlock.EAST))).setValue(VineBlock.WEST, (Boolean) state.getValue(VineBlock.SOUTH)); + default: + return state; + } + } + + @Override +- public BlockState mirror(BlockState state, Mirror mirror) { ++ public IBlockData mirror(IBlockData state, Mirror mirror) { + switch (mirror) { + case LEFT_RIGHT: +- return state.setValue(NORTH, state.getValue(SOUTH)).setValue(SOUTH, state.getValue(NORTH)); ++ return (IBlockData) ((IBlockData) state.setValue(VineBlock.NORTH, (Boolean) state.getValue(VineBlock.SOUTH))).setValue(VineBlock.SOUTH, (Boolean) state.getValue(VineBlock.NORTH)); + case FRONT_BACK: +- return state.setValue(EAST, state.getValue(WEST)).setValue(WEST, state.getValue(EAST)); ++ return (IBlockData) ((IBlockData) state.setValue(VineBlock.EAST, (Boolean) state.getValue(VineBlock.WEST))).setValue(VineBlock.WEST, (Boolean) state.getValue(VineBlock.EAST)); + default: + return super.mirror(state, mirror); + } + } + + public static BooleanProperty getPropertyForFace(Direction face) { +- return PROPERTY_BY_DIRECTION.get(face); ++ return (BooleanProperty) VineBlock.PROPERTY_BY_DIRECTION.get(face); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/WallHangingSignBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/WallHangingSignBlock.java.patch new file mode 100644 index 0000000000..6e303e44e8 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/WallHangingSignBlock.java.patch @@ -0,0 +1,254 @@ +--- a/net/minecraft/world/level/block/WallHangingSignBlock.java ++++ b/net/minecraft/world/level/block/WallHangingSignBlock.java +@@ -4,13 +4,12 @@ + import com.google.common.collect.Maps; + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import java.util.Map; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.tags.BlockTags; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.HangingSignItem; +@@ -26,47 +25,49 @@ + import net.minecraft.world.level.block.entity.HangingSignBlockEntity; + import net.minecraft.world.level.block.entity.SignBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.DirectionProperty; + import net.minecraft.world.level.block.state.properties.WoodType; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; + + public class WallHangingSignBlock extends SignBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group(WoodType.CODEC.fieldOf("wood_type").forGetter(SignBlock::type), propertiesCodec()) +- .apply(instance, WallHangingSignBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(WoodType.CODEC.fieldOf("wood_type").forGetter(SignBlock::type), propertiesCodec()).apply(instance, WallHangingSignBlock::new); ++ }); + public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING; +- public static final VoxelShape PLANK_NORTHSOUTH = Block.box(0.0, 14.0, 6.0, 16.0, 16.0, 10.0); +- public static final VoxelShape PLANK_EASTWEST = Block.box(6.0, 14.0, 0.0, 10.0, 16.0, 16.0); +- public static final VoxelShape SHAPE_NORTHSOUTH = Shapes.or(PLANK_NORTHSOUTH, Block.box(1.0, 0.0, 7.0, 15.0, 10.0, 9.0)); +- public static final VoxelShape SHAPE_EASTWEST = Shapes.or(PLANK_EASTWEST, Block.box(7.0, 0.0, 1.0, 9.0, 10.0, 15.0)); +- private static final Map AABBS = Maps.newEnumMap( +- ImmutableMap.of(Direction.NORTH, SHAPE_NORTHSOUTH, Direction.SOUTH, SHAPE_NORTHSOUTH, Direction.EAST, SHAPE_EASTWEST, Direction.WEST, SHAPE_EASTWEST) +- ); ++ public static final VoxelShape PLANK_NORTHSOUTH = Block.box(0.0D, 14.0D, 6.0D, 16.0D, 16.0D, 10.0D); ++ public static final VoxelShape PLANK_EASTWEST = Block.box(6.0D, 14.0D, 0.0D, 10.0D, 16.0D, 16.0D); ++ public static final VoxelShape SHAPE_NORTHSOUTH = Shapes.or(WallHangingSignBlock.PLANK_NORTHSOUTH, Block.box(1.0D, 0.0D, 7.0D, 15.0D, 10.0D, 9.0D)); ++ public static final VoxelShape SHAPE_EASTWEST = Shapes.or(WallHangingSignBlock.PLANK_EASTWEST, Block.box(7.0D, 0.0D, 1.0D, 9.0D, 10.0D, 15.0D)); ++ private static final Map AABBS = Maps.newEnumMap(ImmutableMap.of(Direction.NORTH, WallHangingSignBlock.SHAPE_NORTHSOUTH, Direction.SOUTH, WallHangingSignBlock.SHAPE_NORTHSOUTH, Direction.EAST, WallHangingSignBlock.SHAPE_EASTWEST, Direction.WEST, WallHangingSignBlock.SHAPE_EASTWEST)); + + @Override + public MapCodec codec() { +- return CODEC; ++ return WallHangingSignBlock.CODEC; + } + +- public WallHangingSignBlock(WoodType woodType, BlockBehaviour.Properties properties) { +- super(woodType, properties.sound(woodType.hangingSignSoundType())); +- this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(WATERLOGGED, Boolean.valueOf(false))); ++ public WallHangingSignBlock(WoodType blockpropertywood, BlockBehaviour.Properties blockbase_info) { ++ super(blockpropertywood, blockbase_info.sound(blockpropertywood.hangingSignSoundType())); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(WallHangingSignBlock.FACING, Direction.NORTH)).setValue(WallHangingSignBlock.WATERLOGGED, false)); + } + + @Override +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { +- if (level.getBlockEntity(pos) instanceof SignBlockEntity signBlockEntity) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (this.shouldTryToChainAnotherHangingSign(state, player, hit, signBlockEntity, itemInHand)) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof SignBlockEntity) { ++ SignBlockEntity tileentitysign = (SignBlockEntity) tileentity; ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (this.shouldTryToChainAnotherHangingSign(state, player, hit, tileentitysign, itemstack)) { + return InteractionResult.PASS; + } + } +@@ -74,14 +75,12 @@ + return super.use(state, level, pos, player, hand, hit); + } + +- private boolean shouldTryToChainAnotherHangingSign(BlockState state, Player player, BlockHitResult hitResult, SignBlockEntity sign, ItemStack stack) { +- return !sign.canExecuteClickCommands(sign.isFacingFrontText(player), player) +- && stack.getItem() instanceof HangingSignItem +- && !this.isHittingEditableSide(hitResult, state); ++ private boolean shouldTryToChainAnotherHangingSign(IBlockData state, Player player, BlockHitResult hitResult, SignBlockEntity sign, ItemStack stack) { ++ return !sign.canExecuteClickCommands(sign.isFacingFrontText(player), player) && stack.getItem() instanceof HangingSignItem && !this.isHittingEditableSide(hitResult, state); + } + +- private boolean isHittingEditableSide(BlockHitResult hitResult, BlockState state) { +- return hitResult.getDirection().getAxis() == state.getValue(FACING).getAxis(); ++ private boolean isHittingEditableSide(BlockHitResult hitResult, IBlockData state) { ++ return hitResult.getDirection().getAxis() == ((Direction) state.getValue(WallHangingSignBlock.FACING)).getAxis(); + } + + @Override +@@ -90,54 +89,58 @@ + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return AABBS.get(state.getValue(FACING)); ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return (VoxelShape) WallHangingSignBlock.AABBS.get(state.getValue(WallHangingSignBlock.FACING)); + } + + @Override +- public VoxelShape getBlockSupportShape(BlockState state, BlockGetter level, BlockPos pos) { ++ public VoxelShape getBlockSupportShape(IBlockData state, BlockGetter level, BlockPos pos) { + return this.getShape(state, level, pos, CollisionContext.empty()); + } + + @Override +- public VoxelShape getCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- switch ((Direction)state.getValue(FACING)) { ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ switch ((Direction) state.getValue(WallHangingSignBlock.FACING)) { + case EAST: + case WEST: +- return PLANK_EASTWEST; ++ return WallHangingSignBlock.PLANK_EASTWEST; + default: +- return PLANK_NORTHSOUTH; ++ return WallHangingSignBlock.PLANK_NORTHSOUTH; + } + } + +- public boolean canPlace(BlockState state, LevelReader level, BlockPos pos) { +- Direction clockWise = state.getValue(FACING).getClockWise(); +- Direction counterClockWise = state.getValue(FACING).getCounterClockWise(); +- return this.canAttachTo(level, state, pos.relative(clockWise), counterClockWise) +- || this.canAttachTo(level, state, pos.relative(counterClockWise), clockWise); ++ public boolean canPlace(IBlockData state, LevelReader level, BlockPos pos) { ++ Direction enumdirection = ((Direction) state.getValue(WallHangingSignBlock.FACING)).getClockWise(); ++ Direction enumdirection1 = ((Direction) state.getValue(WallHangingSignBlock.FACING)).getCounterClockWise(); ++ ++ return this.canAttachTo(level, state, pos.relative(enumdirection), enumdirection1) || this.canAttachTo(level, state, pos.relative(enumdirection1), enumdirection); + } + +- public boolean canAttachTo(LevelReader level, BlockState state, BlockPos pos, Direction direction) { +- BlockState blockState = level.getBlockState(pos); +- return blockState.is(BlockTags.WALL_HANGING_SIGNS) +- ? blockState.getValue(FACING).getAxis().test(state.getValue(FACING)) +- : blockState.isFaceSturdy(level, pos, direction, SupportType.FULL); ++ public boolean canAttachTo(LevelReader level, IBlockData state, BlockPos pos, Direction direction) { ++ IBlockData iblockdata1 = level.getBlockState(pos); ++ ++ return iblockdata1.is(BlockTags.WALL_HANGING_SIGNS) ? ((Direction) iblockdata1.getValue(WallHangingSignBlock.FACING)).getAxis().test((Direction) state.getValue(WallHangingSignBlock.FACING)) : iblockdata1.isFaceSturdy(level, pos, direction, SupportType.FULL); + } + + @Nullable + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- BlockState blockState = this.defaultBlockState(); +- FluidState fluidState = context.getLevel().getFluidState(context.getClickedPos()); +- LevelReader level = context.getLevel(); +- BlockPos clickedPos = context.getClickedPos(); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ IBlockData iblockdata = this.defaultBlockState(); ++ FluidState fluid = context.getLevel().getFluidState(context.getClickedPos()); ++ Level world = context.getLevel(); ++ BlockPos blockposition = context.getClickedPos(); ++ Direction[] aenumdirection = context.getNearestLookingDirections(); ++ int i = aenumdirection.length; + +- for (Direction direction : context.getNearestLookingDirections()) { +- if (direction.getAxis().isHorizontal() && !direction.getAxis().test(context.getClickedFace())) { +- Direction opposite = direction.getOpposite(); +- blockState = blockState.setValue(FACING, opposite); +- if (blockState.canSurvive(level, clickedPos) && this.canPlace(blockState, level, clickedPos)) { +- return blockState.setValue(WATERLOGGED, Boolean.valueOf(fluidState.getType() == Fluids.WATER)); ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ ++ if (enumdirection.getAxis().isHorizontal() && !enumdirection.getAxis().test(context.getClickedFace())) { ++ Direction enumdirection1 = enumdirection.getOpposite(); ++ ++ iblockdata = (IBlockData) iblockdata.setValue(WallHangingSignBlock.FACING, enumdirection1); ++ if (iblockdata.canSurvive(world, blockposition) && this.canPlace(iblockdata, world, blockposition)) { ++ return (IBlockData) iblockdata.setValue(WallHangingSignBlock.WATERLOGGED, fluid.getType() == Fluids.WATER); + } + } + } +@@ -146,45 +149,43 @@ + } + + @Override +- public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { +- return facing.getAxis() == state.getValue(FACING).getClockWise().getAxis() && !state.canSurvive(level, currentPos) +- ? Blocks.AIR.defaultBlockState() +- : super.updateShape(state, facing, facingState, level, currentPos, facingPos); ++ public IBlockData updateShape(IBlockData state, Direction facing, IBlockData facingState, LevelAccessor level, BlockPos currentPos, BlockPos facingPos) { ++ return facing.getAxis() == ((Direction) state.getValue(WallHangingSignBlock.FACING)).getClockWise().getAxis() && !state.canSurvive(level, currentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, facing, facingState, level, currentPos, facingPos); + } + + @Override +- public float getYRotationDegrees(BlockState state) { +- return state.getValue(FACING).toYRot(); ++ public float getYRotationDegrees(IBlockData state) { ++ return ((Direction) state.getValue(WallHangingSignBlock.FACING)).toYRot(); + } + + @Override +- public BlockState rotate(BlockState state, Rotation rotation) { +- return state.setValue(FACING, rotation.rotate(state.getValue(FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rotation) { ++ return (IBlockData) state.setValue(WallHangingSignBlock.FACING, rotation.rotate((Direction) state.getValue(WallHangingSignBlock.FACING))); + } + + @Override +- public BlockState mirror(BlockState state, Mirror mirror) { +- return state.rotate(mirror.getRotation(state.getValue(FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(WallHangingSignBlock.FACING))); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(FACING, WATERLOGGED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(WallHangingSignBlock.FACING, WallHangingSignBlock.WATERLOGGED); + } + + @Override +- public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { ++ public BlockEntity newBlockEntity(BlockPos pos, IBlockData state) { + return new HangingSignBlockEntity(pos, state); + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + + @Nullable + @Override +- public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { +- return createTickerHelper(blockEntityType, BlockEntityType.HANGING_SIGN, SignBlockEntity::tick); ++ public BlockEntityTicker getTicker(Level level, IBlockData state, BlockEntityType blockEntityType) { ++ return null; // Craftbukkit - remove unnecessary sign ticking + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/WaterlilyBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/WaterlilyBlock.java.patch new file mode 100644 index 0000000000..8cab7f6cb8 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/WaterlilyBlock.java.patch @@ -0,0 +1,66 @@ +--- a/net/minecraft/world/level/block/WaterlilyBlock.java ++++ b/net/minecraft/world/level/block/WaterlilyBlock.java +@@ -8,19 +8,23 @@ + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class WaterlilyBlock extends BushBlock { ++ + public static final MapCodec CODEC = simpleCodec(WaterlilyBlock::new); +- protected static final VoxelShape AABB = Block.box(1.0, 0.0, 1.0, 15.0, 1.5, 15.0); ++ protected static final VoxelShape AABB = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 1.5D, 15.0D); + + @Override + public MapCodec codec() { +- return CODEC; ++ return WaterlilyBlock.CODEC; + } + + protected WaterlilyBlock(BlockBehaviour.Properties properties) { +@@ -28,22 +32,29 @@ + } + + @Override +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { + super.entityInside(state, level, pos, entity); + if (level instanceof ServerLevel && entity instanceof Boat) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end + level.destroyBlock(new BlockPos(pos), true, entity); + } ++ + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- return AABB; ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ return WaterlilyBlock.AABB; + } + + @Override +- protected boolean mayPlaceOn(BlockState state, BlockGetter level, BlockPos pos) { +- FluidState fluidState = level.getFluidState(pos); +- FluidState fluidState1 = level.getFluidState(pos.above()); +- return (fluidState.getType() == Fluids.WATER || state.getBlock() instanceof IceBlock) && fluidState1.getType() == Fluids.EMPTY; ++ protected boolean mayPlaceOn(IBlockData state, BlockGetter level, BlockPos pos) { ++ FluidState fluid = level.getFluidState(pos); ++ FluidState fluid1 = level.getFluidState(pos.above()); ++ ++ return (fluid.getType() == Fluids.WATER || state.getBlock() instanceof IceBlock) && fluid1.getType() == Fluids.EMPTY; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/WeightedPressurePlateBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/WeightedPressurePlateBlock.java.patch new file mode 100644 index 0000000000..b4a90e668e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/WeightedPressurePlateBlock.java.patch @@ -0,0 +1,118 @@ +--- a/net/minecraft/world/level/block/WeightedPressurePlateBlock.java ++++ b/net/minecraft/world/level/block/WeightedPressurePlateBlock.java +@@ -3,46 +3,70 @@ + import com.mojang.serialization.Codec; + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import net.minecraft.core.BlockPos; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockSetType; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.IntegerProperty; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end + + public class WeightedPressurePlateBlock extends BasePressurePlateBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group( +- Codec.intRange(1, 1024).fieldOf("max_weight").forGetter(weightedPressurePlateBlock -> weightedPressurePlateBlock.maxWeight), +- BlockSetType.CODEC.fieldOf("block_set_type").forGetter(weightedPressurePlateBlock -> weightedPressurePlateBlock.type), +- propertiesCodec() +- ) +- .apply(instance, WeightedPressurePlateBlock::new) +- ); ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(Codec.intRange(1, 1024).fieldOf("max_weight").forGetter((blockpressureplateweighted) -> { ++ return blockpressureplateweighted.maxWeight; ++ }), BlockSetType.CODEC.fieldOf("block_set_type").forGetter((blockpressureplateweighted) -> { ++ return blockpressureplateweighted.type; ++ }), propertiesCodec()).apply(instance, WeightedPressurePlateBlock::new); ++ }); + public static final IntegerProperty POWER = BlockStateProperties.POWER; + private final int maxWeight; + + @Override + public MapCodec codec() { +- return CODEC; ++ return WeightedPressurePlateBlock.CODEC; + } + +- protected WeightedPressurePlateBlock(int i, BlockSetType type, BlockBehaviour.Properties properties) { +- super(properties, type); +- this.registerDefaultState(this.stateDefinition.any().setValue(POWER, Integer.valueOf(0))); ++ protected WeightedPressurePlateBlock(int i, BlockSetType blocksettype, BlockBehaviour.Properties blockbase_info) { ++ super(blockbase_info, blocksettype); ++ this.registerDefaultState((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(WeightedPressurePlateBlock.POWER, 0)); + this.maxWeight = i; + } + + @Override + protected int getSignalStrength(Level level, BlockPos pos) { +- int min = Math.min(getEntityCount(level, TOUCH_AABB.move(pos), Entity.class), this.maxWeight); +- if (min > 0) { +- float f = (float)Math.min(this.maxWeight, min) / (float)this.maxWeight; ++ // CraftBukkit start ++ // int i = Math.min(getEntityCount(world, BlockPressurePlateWeighted.TOUCH_AABB.move(blockposition), Entity.class), this.maxWeight); ++ int i = 0; ++ for (Entity entity : getEntities(level, WeightedPressurePlateBlock.TOUCH_AABB.move(pos), Entity.class)) { ++ org.bukkit.event.Cancellable cancellable; ++ ++ if (entity instanceof Player) { ++ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); ++ level.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ // We only want to block turning the plate on if all events are cancelled ++ if (!cancellable.isCancelled()) { ++ i++; ++ } ++ } ++ ++ i = Math.min(i, this.maxWeight); ++ // CraftBukkit end ++ ++ if (i > 0) { ++ float f = (float) Math.min(this.maxWeight, i) / (float) this.maxWeight; ++ + return Mth.ceil(f * 15.0F); + } else { + return 0; +@@ -50,13 +74,13 @@ + } + + @Override +- protected int getSignalForState(BlockState state) { +- return state.getValue(POWER); ++ protected int getSignalForState(IBlockData state) { ++ return (Integer) state.getValue(WeightedPressurePlateBlock.POWER); + } + + @Override +- protected BlockState setSignalForState(BlockState state, int strength) { +- return state.setValue(POWER, Integer.valueOf(strength)); ++ protected IBlockData setSignalForState(IBlockData state, int strength) { ++ return (IBlockData) state.setValue(WeightedPressurePlateBlock.POWER, strength); + } + + @Override +@@ -65,7 +89,7 @@ + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(POWER); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(WeightedPressurePlateBlock.POWER); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/WitherRoseBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/WitherRoseBlock.java.patch new file mode 100644 index 0000000000..347e9a53de --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/WitherRoseBlock.java.patch @@ -0,0 +1,100 @@ +--- a/net/minecraft/world/level/block/WitherRoseBlock.java ++++ b/net/minecraft/world/level/block/WitherRoseBlock.java +@@ -2,7 +2,6 @@ + + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import java.util.List; + import net.minecraft.core.BlockPos; + import net.minecraft.core.particles.ParticleTypes; +@@ -16,62 +15,61 @@ + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.VoxelShape; + + public class WitherRoseBlock extends FlowerBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group(EFFECTS_FIELD.forGetter(FlowerBlock::getSuspiciousEffects), propertiesCodec()).apply(instance, WitherRoseBlock::new) +- ); + ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(WitherRoseBlock.EFFECTS_FIELD.forGetter(FlowerBlock::getSuspiciousEffects), propertiesCodec()).apply(instance, WitherRoseBlock::new); ++ }); ++ + @Override + public MapCodec codec() { +- return CODEC; ++ return WitherRoseBlock.CODEC; + } + +- public WitherRoseBlock(MobEffect mobEffect, int i, BlockBehaviour.Properties properties) { +- this(makeEffectList(mobEffect, i), properties); ++ public WitherRoseBlock(MobEffect suspiciousStewEffect, int effectDuration, BlockBehaviour.Properties properties) { ++ this(makeEffectList(suspiciousStewEffect, effectDuration), properties); + } + +- public WitherRoseBlock(List list, BlockBehaviour.Properties properties) { +- super(list, properties); ++ public WitherRoseBlock(List list, BlockBehaviour.Properties blockbase_info) { ++ super(list, blockbase_info); + } + + @Override +- protected boolean mayPlaceOn(BlockState state, BlockGetter level, BlockPos pos) { ++ protected boolean mayPlaceOn(IBlockData state, BlockGetter level, BlockPos pos) { + return super.mayPlaceOn(state, level, pos) || state.is(Blocks.NETHERRACK) || state.is(Blocks.SOUL_SAND) || state.is(Blocks.SOUL_SOIL); + } + + @Override +- public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { +- VoxelShape shape = this.getShape(state, level, pos, CollisionContext.empty()); +- Vec3 center = shape.bounds().getCenter(); +- double d = (double)pos.getX() + center.x; +- double d1 = (double)pos.getZ() + center.z; ++ public void animateTick(IBlockData state, Level level, BlockPos pos, RandomSource random) { ++ VoxelShape voxelshape = this.getShape(state, level, pos, CollisionContext.empty()); ++ Vec3 vec3d = voxelshape.bounds().getCenter(); ++ double d0 = (double) pos.getX() + vec3d.x; ++ double d1 = (double) pos.getZ() + vec3d.z; + +- for (int i = 0; i < 3; i++) { ++ for (int i = 0; i < 3; ++i) { + if (random.nextBoolean()) { +- level.addParticle( +- ParticleTypes.SMOKE, +- d + random.nextDouble() / 5.0, +- (double)pos.getY() + (0.5 - random.nextDouble()), +- d1 + random.nextDouble() / 5.0, +- 0.0, +- 0.0, +- 0.0 +- ); ++ level.addParticle(ParticleTypes.SMOKE, d0 + random.nextDouble() / 5.0D, (double) pos.getY() + (0.5D - random.nextDouble()), d1 + random.nextDouble() / 5.0D, 0.0D, 0.0D, 0.0D); + } + } ++ + } + + @Override +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) { + if (!level.isClientSide && level.getDifficulty() != Difficulty.PEACEFUL) { +- if (entity instanceof LivingEntity livingEntity && !livingEntity.isInvulnerableTo(level.damageSources().wither())) { +- livingEntity.addEffect(new MobEffectInstance(MobEffects.WITHER, 40)); ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ if (!entityliving.isInvulnerableTo(level.damageSources().wither())) { ++ entityliving.addEffect(new MobEffectInstance(MobEffects.WITHER, 40), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.WITHER_ROSE); // CraftBukkit ++ } + } ++ + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/WitherSkullBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/WitherSkullBlock.java.patch new file mode 100644 index 0000000000..49339e0a4c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/WitherSkullBlock.java.patch @@ -0,0 +1,182 @@ +--- a/net/minecraft/world/level/block/WitherSkullBlock.java ++++ b/net/minecraft/world/level/block/WitherSkullBlock.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.block; + + import com.mojang.serialization.MapCodec; ++import java.util.Iterator; + import javax.annotation.Nullable; + import net.minecraft.advancements.CriteriaTriggers; + import net.minecraft.core.BlockPos; +@@ -8,6 +9,7 @@ + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.tags.BlockTags; + import net.minecraft.world.Difficulty; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.boss.wither.WitherBoss; +@@ -17,13 +19,18 @@ + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.SkullBlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.pattern.BlockInWorld; + import net.minecraft.world.level.block.state.pattern.BlockPattern; + import net.minecraft.world.level.block.state.pattern.BlockPatternBuilder; + import net.minecraft.world.level.block.state.predicate.BlockStatePredicate; + ++// CraftBukkit start ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; ++// CraftBukkit end ++ + public class WitherSkullBlock extends SkullBlock { ++ + public static final MapCodec CODEC = simpleCodec(WitherSkullBlock::new); + @Nullable + private static BlockPattern witherPatternFull; +@@ -32,90 +39,91 @@ + + @Override + public MapCodec codec() { +- return CODEC; ++ return WitherSkullBlock.CODEC; + } + + protected WitherSkullBlock(BlockBehaviour.Properties properties) { +- super(SkullBlock.Types.WITHER_SKELETON, properties); ++ super(SkullBlock.Type.WITHER_SKELETON, properties); + } + + @Override +- public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) { ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, @Nullable LivingEntity placer, ItemStack stack) { + super.setPlacedBy(level, pos, state, placer, stack); +- BlockEntity blockEntity = level.getBlockEntity(pos); +- if (blockEntity instanceof SkullBlockEntity) { +- checkSpawn(level, pos, (SkullBlockEntity)blockEntity); ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof SkullBlockEntity) { ++ checkSpawn(level, pos, (SkullBlockEntity) tileentity); + } ++ + } + + public static void checkSpawn(Level level, BlockPos pos, SkullBlockEntity blockEntity) { ++ if (level.captureBlockStates) return; // CraftBukkit + if (!level.isClientSide) { +- BlockState blockState = blockEntity.getBlockState(); +- boolean flag = blockState.is(Blocks.WITHER_SKELETON_SKULL) || blockState.is(Blocks.WITHER_SKELETON_WALL_SKULL); ++ IBlockData iblockdata = blockEntity.getBlockState(); ++ boolean flag = iblockdata.is(Blocks.WITHER_SKELETON_SKULL) || iblockdata.is(Blocks.WITHER_SKELETON_WALL_SKULL); ++ + if (flag && pos.getY() >= level.getMinBuildHeight() && level.getDifficulty() != Difficulty.PEACEFUL) { +- BlockPattern.BlockPatternMatch blockPatternMatch = getOrCreateWitherFull().find(level, pos); +- if (blockPatternMatch != null) { +- WitherBoss witherBoss = EntityType.WITHER.create(level); +- if (witherBoss != null) { +- CarvedPumpkinBlock.clearPatternBlocks(level, blockPatternMatch); +- BlockPos pos1 = blockPatternMatch.getBlock(1, 2, 0).getPos(); +- witherBoss.moveTo( +- (double)pos1.getX() + 0.5, +- (double)pos1.getY() + 0.55, +- (double)pos1.getZ() + 0.5, +- blockPatternMatch.getForwards().getAxis() == Direction.Axis.X ? 0.0F : 90.0F, +- 0.0F +- ); +- witherBoss.yBodyRot = blockPatternMatch.getForwards().getAxis() == Direction.Axis.X ? 0.0F : 90.0F; +- witherBoss.makeInvulnerable(); ++ BlockPattern.BlockPatternMatch shapedetector_shapedetectorcollection = getOrCreateWitherFull().find(level, pos); + +- for (ServerPlayer serverPlayer : level.getEntitiesOfClass(ServerPlayer.class, witherBoss.getBoundingBox().inflate(50.0))) { +- CriteriaTriggers.SUMMONED_ENTITY.trigger(serverPlayer, witherBoss); ++ if (shapedetector_shapedetectorcollection != null) { ++ WitherBoss entitywither = (WitherBoss) EntityType.WITHER.create(level); ++ ++ if (entitywither != null) { ++ // BlockPumpkinCarved.clearPatternBlocks(world, shapedetector_shapedetectorcollection); // CraftBukkit - move down ++ BlockPos blockposition1 = shapedetector_shapedetectorcollection.getBlock(1, 2, 0).getPos(); ++ ++ entitywither.moveTo((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.55D, (double) blockposition1.getZ() + 0.5D, shapedetector_shapedetectorcollection.getForwards().getAxis() == Direction.Axis.X ? 0.0F : 90.0F, 0.0F); ++ entitywither.yBodyRot = shapedetector_shapedetectorcollection.getForwards().getAxis() == Direction.Axis.X ? 0.0F : 90.0F; ++ entitywither.makeInvulnerable(); ++ // CraftBukkit start ++ if (!level.addFreshEntity(entitywither, SpawnReason.BUILD_WITHER)) { ++ return; + } ++ CarvedPumpkinBlock.clearPatternBlocks(level, shapedetector_shapedetectorcollection); // CraftBukkit - from above ++ // CraftBukkit end ++ Iterator iterator = level.getEntitiesOfClass(ServerPlayer.class, entitywither.getBoundingBox().inflate(50.0D)).iterator(); + +- level.addFreshEntity(witherBoss); +- CarvedPumpkinBlock.updatePatternBlocks(level, blockPatternMatch); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ CriteriaTriggers.SUMMONED_ENTITY.trigger(entityplayer, (Entity) entitywither); ++ } ++ ++ // world.addFreshEntity(entitywither); // CraftBukkit - moved up ++ CarvedPumpkinBlock.updatePatternBlocks(level, shapedetector_shapedetectorcollection); + } ++ + } + } + } + } + + public static boolean canSpawnMob(Level level, BlockPos pos, ItemStack stack) { +- return stack.is(Items.WITHER_SKELETON_SKULL) +- && pos.getY() >= level.getMinBuildHeight() + 2 +- && level.getDifficulty() != Difficulty.PEACEFUL +- && !level.isClientSide +- && getOrCreateWitherBase().find(level, pos) != null; ++ return stack.is(Items.WITHER_SKELETON_SKULL) && pos.getY() >= level.getMinBuildHeight() + 2 && level.getDifficulty() != Difficulty.PEACEFUL && !level.isClientSide ? getOrCreateWitherBase().find(level, pos) != null : false; + } + + private static BlockPattern getOrCreateWitherFull() { +- if (witherPatternFull == null) { +- witherPatternFull = BlockPatternBuilder.start() +- .aisle("^^^", "###", "~#~") +- .where('#', block -> block.getState().is(BlockTags.WITHER_SUMMON_BASE_BLOCKS)) +- .where( +- '^', +- BlockInWorld.hasState( +- BlockStatePredicate.forBlock(Blocks.WITHER_SKELETON_SKULL).or(BlockStatePredicate.forBlock(Blocks.WITHER_SKELETON_WALL_SKULL)) +- ) +- ) +- .where('~', block -> block.getState().isAir()) +- .build(); ++ if (WitherSkullBlock.witherPatternFull == null) { ++ WitherSkullBlock.witherPatternFull = BlockPatternBuilder.start().aisle("^^^", "###", "~#~").where('#', (shapedetectorblock) -> { ++ return shapedetectorblock.getState().is(BlockTags.WITHER_SUMMON_BASE_BLOCKS); ++ }).where('^', BlockInWorld.hasState(BlockStatePredicate.forBlock(Blocks.WITHER_SKELETON_SKULL).or(BlockStatePredicate.forBlock(Blocks.WITHER_SKELETON_WALL_SKULL)))).where('~', (shapedetectorblock) -> { ++ return shapedetectorblock.getState().isAir(); ++ }).build(); + } + +- return witherPatternFull; ++ return WitherSkullBlock.witherPatternFull; + } + + private static BlockPattern getOrCreateWitherBase() { +- if (witherPatternBase == null) { +- witherPatternBase = BlockPatternBuilder.start() +- .aisle(" ", "###", "~#~") +- .where('#', block -> block.getState().is(BlockTags.WITHER_SUMMON_BASE_BLOCKS)) +- .where('~', block -> block.getState().isAir()) +- .build(); ++ if (WitherSkullBlock.witherPatternBase == null) { ++ WitherSkullBlock.witherPatternBase = BlockPatternBuilder.start().aisle(" ", "###", "~#~").where('#', (shapedetectorblock) -> { ++ return shapedetectorblock.getState().is(BlockTags.WITHER_SUMMON_BASE_BLOCKS); ++ }).where('~', (shapedetectorblock) -> { ++ return shapedetectorblock.getState().isAir(); ++ }).build(); + } + +- return witherPatternBase; ++ return WitherSkullBlock.witherPatternBase; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java.patch new file mode 100644 index 0000000000..5a42cae474 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java.patch @@ -0,0 +1,816 @@ +--- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -2,8 +2,10 @@ + + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; +-import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; + import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; ++import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectIterator; ++import java.util.Iterator; + import java.util.List; + import java.util.Map; + import javax.annotation.Nullable; +@@ -26,7 +28,6 @@ + import net.minecraft.world.ContainerHelper; + import net.minecraft.world.WorldlyContainer; + import net.minecraft.world.entity.ExperienceOrb; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.player.StackedContents; + import net.minecraft.world.inventory.ContainerData; + import net.minecraft.world.inventory.RecipeCraftingHolder; +@@ -38,14 +39,28 @@ + import net.minecraft.world.item.crafting.RecipeHolder; + import net.minecraft.world.item.crafting.RecipeManager; + import net.minecraft.world.item.crafting.RecipeType; +-import net.minecraft.world.level.ItemLike; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.AbstractFurnaceBlock; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.block.BlockExpEvent; ++import org.bukkit.event.inventory.FurnaceBurnEvent; ++import org.bukkit.event.inventory.FurnaceExtractEvent; ++import org.bukkit.event.inventory.FurnaceSmeltEvent; ++import org.bukkit.event.inventory.FurnaceStartSmeltEvent; ++import org.bukkit.inventory.CookingRecipe; ++// CraftBukkit end + + public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntity implements WorldlyContainer, RecipeCraftingHolder, StackedContentsCompatible { ++ + protected static final int SLOT_INPUT = 0; + protected static final int SLOT_FUEL = 1; + protected static final int SLOT_RESULT = 2; +@@ -59,143 +74,184 @@ + public static final int NUM_DATA_VALUES = 4; + public static final int BURN_TIME_STANDARD = 200; + public static final int BURN_COOL_SPEED = 2; +- protected NonNullList items = NonNullList.withSize(3, ItemStack.EMPTY); +- int litTime; ++ protected NonNullList items; ++ public int litTime; + int litDuration; +- int cookingProgress; +- int cookingTotalTime; +- protected final ContainerData dataAccess = new ContainerData() { +- @Override +- public int get(int index) { +- switch (index) { +- case 0: +- return AbstractFurnaceBlockEntity.this.litTime; +- case 1: +- return AbstractFurnaceBlockEntity.this.litDuration; +- case 2: +- return AbstractFurnaceBlockEntity.this.cookingProgress; +- case 3: +- return AbstractFurnaceBlockEntity.this.cookingTotalTime; +- default: +- return 0; +- } +- } ++ public int cookingProgress; ++ public int cookingTotalTime; ++ protected final ContainerData dataAccess; ++ public final Object2IntOpenHashMap recipesUsed; ++ private final RecipeManager.CachedCheck quickCheck; + +- @Override +- public void set(int index, int value) { +- switch (index) { +- case 0: +- AbstractFurnaceBlockEntity.this.litTime = value; +- break; +- case 1: +- AbstractFurnaceBlockEntity.this.litDuration = value; +- break; +- case 2: +- AbstractFurnaceBlockEntity.this.cookingProgress = value; +- break; +- case 3: +- AbstractFurnaceBlockEntity.this.cookingTotalTime = value; ++ protected AbstractFurnaceBlockEntity(BlockEntityType type, BlockPos pos, IBlockData blockState, RecipeType recipeType) { ++ super(type, pos, blockState); ++ this.items = NonNullList.withSize(3, ItemStack.EMPTY); ++ this.dataAccess = new ContainerData() { ++ @Override ++ public int get(int index) { ++ switch (index) { ++ case 0: ++ return AbstractFurnaceBlockEntity.this.litTime; ++ case 1: ++ return AbstractFurnaceBlockEntity.this.litDuration; ++ case 2: ++ return AbstractFurnaceBlockEntity.this.cookingProgress; ++ case 3: ++ return AbstractFurnaceBlockEntity.this.cookingTotalTime; ++ default: ++ return 0; ++ } + } +- } + +- @Override +- public int getCount() { +- return 4; +- } +- }; +- private final Object2IntOpenHashMap recipesUsed = new Object2IntOpenHashMap<>(); +- private final RecipeManager.CachedCheck quickCheck; ++ @Override ++ public void set(int index, int value) { ++ switch (index) { ++ case 0: ++ AbstractFurnaceBlockEntity.this.litTime = value; ++ break; ++ case 1: ++ AbstractFurnaceBlockEntity.this.litDuration = value; ++ break; ++ case 2: ++ AbstractFurnaceBlockEntity.this.cookingProgress = value; ++ break; ++ case 3: ++ AbstractFurnaceBlockEntity.this.cookingTotalTime = value; ++ } + +- protected AbstractFurnaceBlockEntity(BlockEntityType type, BlockPos pos, BlockState blockState, RecipeType recipeType) { +- super(type, pos, blockState); +- this.quickCheck = RecipeManager.createCheck(recipeType); ++ } ++ ++ @Override ++ public int getCount() { ++ return 4; ++ } ++ }; ++ this.recipesUsed = new Object2IntOpenHashMap(); ++ this.quickCheck = RecipeManager.createCheck((RecipeType) recipeType); // CraftBukkit - decompile error // Eclipse fail + } + + public static Map getFuel() { + Map map = Maps.newLinkedHashMap(); +- add(map, Items.LAVA_BUCKET, 20000); +- add(map, Blocks.COAL_BLOCK, 16000); +- add(map, Items.BLAZE_ROD, 2400); +- add(map, Items.COAL, 1600); +- add(map, Items.CHARCOAL, 1600); ++ ++ add(map, (IMaterial) Items.LAVA_BUCKET, 20000); ++ add(map, (IMaterial) Blocks.COAL_BLOCK, 16000); ++ add(map, (IMaterial) Items.BLAZE_ROD, 2400); ++ add(map, (IMaterial) Items.COAL, 1600); ++ add(map, (IMaterial) Items.CHARCOAL, 1600); + add(map, ItemTags.LOGS, 300); + add(map, ItemTags.BAMBOO_BLOCKS, 300); + add(map, ItemTags.PLANKS, 300); +- add(map, Blocks.BAMBOO_MOSAIC, 300); ++ add(map, (IMaterial) Blocks.BAMBOO_MOSAIC, 300); + add(map, ItemTags.WOODEN_STAIRS, 300); +- add(map, Blocks.BAMBOO_MOSAIC_STAIRS, 300); ++ add(map, (IMaterial) Blocks.BAMBOO_MOSAIC_STAIRS, 300); + add(map, ItemTags.WOODEN_SLABS, 150); +- add(map, Blocks.BAMBOO_MOSAIC_SLAB, 150); ++ add(map, (IMaterial) Blocks.BAMBOO_MOSAIC_SLAB, 150); + add(map, ItemTags.WOODEN_TRAPDOORS, 300); + add(map, ItemTags.WOODEN_PRESSURE_PLATES, 300); + add(map, ItemTags.WOODEN_FENCES, 300); + add(map, ItemTags.FENCE_GATES, 300); +- add(map, Blocks.NOTE_BLOCK, 300); +- add(map, Blocks.BOOKSHELF, 300); +- add(map, Blocks.CHISELED_BOOKSHELF, 300); +- add(map, Blocks.LECTERN, 300); +- add(map, Blocks.JUKEBOX, 300); +- add(map, Blocks.CHEST, 300); +- add(map, Blocks.TRAPPED_CHEST, 300); +- add(map, Blocks.CRAFTING_TABLE, 300); +- add(map, Blocks.DAYLIGHT_DETECTOR, 300); ++ add(map, (IMaterial) Blocks.NOTE_BLOCK, 300); ++ add(map, (IMaterial) Blocks.BOOKSHELF, 300); ++ add(map, (IMaterial) Blocks.CHISELED_BOOKSHELF, 300); ++ add(map, (IMaterial) Blocks.LECTERN, 300); ++ add(map, (IMaterial) Blocks.JUKEBOX, 300); ++ add(map, (IMaterial) Blocks.CHEST, 300); ++ add(map, (IMaterial) Blocks.TRAPPED_CHEST, 300); ++ add(map, (IMaterial) Blocks.CRAFTING_TABLE, 300); ++ add(map, (IMaterial) Blocks.DAYLIGHT_DETECTOR, 300); + add(map, ItemTags.BANNERS, 300); +- add(map, Items.BOW, 300); +- add(map, Items.FISHING_ROD, 300); +- add(map, Blocks.LADDER, 300); ++ add(map, (IMaterial) Items.BOW, 300); ++ add(map, (IMaterial) Items.FISHING_ROD, 300); ++ add(map, (IMaterial) Blocks.LADDER, 300); + add(map, ItemTags.SIGNS, 200); + add(map, ItemTags.HANGING_SIGNS, 800); +- add(map, Items.WOODEN_SHOVEL, 200); +- add(map, Items.WOODEN_SWORD, 200); +- add(map, Items.WOODEN_HOE, 200); +- add(map, Items.WOODEN_AXE, 200); +- add(map, Items.WOODEN_PICKAXE, 200); ++ add(map, (IMaterial) Items.WOODEN_SHOVEL, 200); ++ add(map, (IMaterial) Items.WOODEN_SWORD, 200); ++ add(map, (IMaterial) Items.WOODEN_HOE, 200); ++ add(map, (IMaterial) Items.WOODEN_AXE, 200); ++ add(map, (IMaterial) Items.WOODEN_PICKAXE, 200); + add(map, ItemTags.WOODEN_DOORS, 200); + add(map, ItemTags.BOATS, 1200); + add(map, ItemTags.WOOL, 100); + add(map, ItemTags.WOODEN_BUTTONS, 100); +- add(map, Items.STICK, 100); ++ add(map, (IMaterial) Items.STICK, 100); + add(map, ItemTags.SAPLINGS, 100); +- add(map, Items.BOWL, 100); ++ add(map, (IMaterial) Items.BOWL, 100); + add(map, ItemTags.WOOL_CARPETS, 67); +- add(map, Blocks.DRIED_KELP_BLOCK, 4001); +- add(map, Items.CROSSBOW, 300); +- add(map, Blocks.BAMBOO, 50); +- add(map, Blocks.DEAD_BUSH, 100); +- add(map, Blocks.SCAFFOLDING, 50); +- add(map, Blocks.LOOM, 300); +- add(map, Blocks.BARREL, 300); +- add(map, Blocks.CARTOGRAPHY_TABLE, 300); +- add(map, Blocks.FLETCHING_TABLE, 300); +- add(map, Blocks.SMITHING_TABLE, 300); +- add(map, Blocks.COMPOSTER, 300); +- add(map, Blocks.AZALEA, 100); +- add(map, Blocks.FLOWERING_AZALEA, 100); +- add(map, Blocks.MANGROVE_ROOTS, 300); ++ add(map, (IMaterial) Blocks.DRIED_KELP_BLOCK, 4001); ++ add(map, (IMaterial) Items.CROSSBOW, 300); ++ add(map, (IMaterial) Blocks.BAMBOO, 50); ++ add(map, (IMaterial) Blocks.DEAD_BUSH, 100); ++ add(map, (IMaterial) Blocks.SCAFFOLDING, 50); ++ add(map, (IMaterial) Blocks.LOOM, 300); ++ add(map, (IMaterial) Blocks.BARREL, 300); ++ add(map, (IMaterial) Blocks.CARTOGRAPHY_TABLE, 300); ++ add(map, (IMaterial) Blocks.FLETCHING_TABLE, 300); ++ add(map, (IMaterial) Blocks.SMITHING_TABLE, 300); ++ add(map, (IMaterial) Blocks.COMPOSTER, 300); ++ add(map, (IMaterial) Blocks.AZALEA, 100); ++ add(map, (IMaterial) Blocks.FLOWERING_AZALEA, 100); ++ add(map, (IMaterial) Blocks.MANGROVE_ROOTS, 300); + return map; + } + ++ // CraftBukkit start - add fields and methods ++ private int maxStack = MAX_STACK; ++ public List transaction = new java.util.ArrayList(); ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ public Object2IntOpenHashMap getRecipesUsed() { ++ return this.recipesUsed; // PAIL private -> public ++ } ++ // CraftBukkit end ++ + private static boolean isNeverAFurnaceFuel(Item item) { + return item.builtInRegistryHolder().is(ItemTags.NON_FLAMMABLE_WOOD); + } + + private static void add(Map map, TagKey itemTag, int burnTime) { +- for (Holder holder : BuiltInRegistries.ITEM.getTagOrEmpty(itemTag)) { +- if (!isNeverAFurnaceFuel(holder.value())) { +- map.put(holder.value(), burnTime); ++ Iterator iterator = BuiltInRegistries.ITEM.getTagOrEmpty(itemTag).iterator(); ++ ++ while (iterator.hasNext()) { ++ Holder holder = (Holder) iterator.next(); ++ ++ if (!isNeverAFurnaceFuel((Item) holder.value())) { ++ map.put((Item) holder.value(), burnTime); + } + } ++ + } + +- private static void add(Map map, ItemLike item, int burnTime) { ++ private static void add(Map map, IMaterial item, int burnTime) { + Item item1 = item.asItem(); ++ + if (isNeverAFurnaceFuel(item1)) { + if (SharedConstants.IS_RUNNING_IN_IDE) { +- throw (IllegalStateException)Util.pauseInIde( +- new IllegalStateException( +- "A developer tried to explicitly make fire resistant item " + item1.getName(null).getString() + " a furnace fuel. That will not work!" +- ) +- ); ++ throw (IllegalStateException) Util.pauseInIde(new IllegalStateException("A developer tried to explicitly make fire resistant item " + item1.getName((ItemStack) null).getString() + " a furnace fuel. That will not work!")); + } + } else { + map.put(item1, burnTime); +@@ -214,125 +270,189 @@ + this.litTime = tag.getShort("BurnTime"); + this.cookingProgress = tag.getShort("CookTime"); + this.cookingTotalTime = tag.getShort("CookTimeTotal"); +- this.litDuration = this.getBurnDuration(this.items.get(1)); +- CompoundTag compound = tag.getCompound("RecipesUsed"); ++ this.litDuration = this.getBurnDuration((ItemStack) this.items.get(1)); ++ CompoundTag nbttagcompound1 = tag.getCompound("RecipesUsed"); ++ Iterator iterator = nbttagcompound1.getAllKeys().iterator(); + +- for (String string : compound.getAllKeys()) { +- this.recipesUsed.put(new ResourceLocation(string), compound.getInt(string)); ++ while (iterator.hasNext()) { ++ String s = (String) iterator.next(); ++ ++ this.recipesUsed.put(new ResourceLocation(s), nbttagcompound1.getInt(s)); + } ++ + } + + @Override + protected void saveAdditional(CompoundTag tag) { + super.saveAdditional(tag); +- tag.putShort("BurnTime", (short)this.litTime); +- tag.putShort("CookTime", (short)this.cookingProgress); +- tag.putShort("CookTimeTotal", (short)this.cookingTotalTime); ++ tag.putShort("BurnTime", (short) this.litTime); ++ tag.putShort("CookTime", (short) this.cookingProgress); ++ tag.putShort("CookTimeTotal", (short) this.cookingTotalTime); + ContainerHelper.saveAllItems(tag, this.items); +- CompoundTag compoundTag = new CompoundTag(); +- this.recipesUsed.forEach((id, index) -> compoundTag.putInt(id.toString(), index)); +- tag.put("RecipesUsed", compoundTag); ++ CompoundTag nbttagcompound1 = new CompoundTag(); ++ ++ this.recipesUsed.forEach((minecraftkey, integer) -> { ++ nbttagcompound1.putInt(minecraftkey.toString(), integer); ++ }); ++ tag.put("RecipesUsed", nbttagcompound1); + } + +- public static void serverTick(Level level, BlockPos pos, BlockState state, AbstractFurnaceBlockEntity blockEntity) { +- boolean isLit = blockEntity.isLit(); +- boolean flag = false; ++ public static void serverTick(Level level, BlockPos pos, IBlockData state, AbstractFurnaceBlockEntity blockEntity) { ++ boolean flag = blockEntity.isLit(); ++ boolean flag1 = false; ++ + if (blockEntity.isLit()) { +- blockEntity.litTime--; ++ --blockEntity.litTime; + } + +- ItemStack itemStack = blockEntity.items.get(1); +- boolean flag1 = !blockEntity.items.get(0).isEmpty(); +- boolean flag2 = !itemStack.isEmpty(); +- if (blockEntity.isLit() || flag2 && flag1) { +- RecipeHolder recipeHolder; +- if (flag1) { +- recipeHolder = blockEntity.quickCheck.getRecipeFor(blockEntity, level).orElse(null); ++ ItemStack itemstack = (ItemStack) blockEntity.items.get(1); ++ boolean flag2 = !((ItemStack) blockEntity.items.get(0)).isEmpty(); ++ boolean flag3 = !itemstack.isEmpty(); ++ ++ if (!blockEntity.isLit() && (!flag3 || !flag2)) { ++ if (!blockEntity.isLit() && blockEntity.cookingProgress > 0) { ++ blockEntity.cookingProgress = Mth.clamp(blockEntity.cookingProgress - 2, 0, blockEntity.cookingTotalTime); ++ } ++ } else { ++ RecipeHolder recipeholder; ++ ++ if (flag2) { ++ recipeholder = (RecipeHolder) blockEntity.quickCheck.getRecipeFor(blockEntity, level).orElse(null); // CraftBukkit - decompile error + } else { +- recipeHolder = null; ++ recipeholder = null; + } + +- int maxStackSize = blockEntity.getMaxStackSize(); +- if (!blockEntity.isLit() && canBurn(level.registryAccess(), recipeHolder, blockEntity.items, maxStackSize)) { +- blockEntity.litTime = blockEntity.getBurnDuration(itemStack); ++ int i = blockEntity.getMaxStackSize(); ++ ++ if (!blockEntity.isLit() && canBurn(level.registryAccess(), recipeholder, blockEntity.items, i)) { ++ // CraftBukkit start ++ CraftItemStack fuel = CraftItemStack.asCraftMirror(itemstack); ++ ++ FurnaceBurnEvent furnaceBurnEvent = new FurnaceBurnEvent(CraftBlock.at(level, pos), fuel, blockEntity.getBurnDuration(itemstack)); ++ level.getCraftServer().getPluginManager().callEvent(furnaceBurnEvent); ++ ++ if (furnaceBurnEvent.isCancelled()) { ++ return; ++ } ++ ++ blockEntity.litTime = furnaceBurnEvent.getBurnTime(); + blockEntity.litDuration = blockEntity.litTime; +- if (blockEntity.isLit()) { +- flag = true; +- if (flag2) { +- Item item = itemStack.getItem(); +- itemStack.shrink(1); +- if (itemStack.isEmpty()) { +- Item craftingRemainingItem = item.getCraftingRemainingItem(); +- blockEntity.items.set(1, craftingRemainingItem == null ? ItemStack.EMPTY : new ItemStack(craftingRemainingItem)); ++ if (blockEntity.isLit() && furnaceBurnEvent.isBurning()) { ++ // CraftBukkit end ++ flag1 = true; ++ if (flag3) { ++ Item item = itemstack.getItem(); ++ ++ itemstack.shrink(1); ++ if (itemstack.isEmpty()) { ++ Item item1 = item.getCraftingRemainingItem(); ++ ++ blockEntity.items.set(1, item1 == null ? ItemStack.EMPTY : new ItemStack(item1)); + } + } + } + } + +- if (blockEntity.isLit() && canBurn(level.registryAccess(), recipeHolder, blockEntity.items, maxStackSize)) { +- blockEntity.cookingProgress++; ++ if (blockEntity.isLit() && canBurn(level.registryAccess(), recipeholder, blockEntity.items, i)) { ++ // CraftBukkit start ++ if (recipeholder != null && blockEntity.cookingProgress == 0) { ++ CraftItemStack source = CraftItemStack.asCraftMirror(blockEntity.items.get(0)); ++ CookingRecipe recipe = (CookingRecipe) recipeholder.toBukkitRecipe(); ++ ++ FurnaceStartSmeltEvent event = new FurnaceStartSmeltEvent(CraftBlock.at(level, pos), source, recipe); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ blockEntity.cookingTotalTime = event.getTotalCookTime(); ++ } ++ // CraftBukkit end ++ ++ ++blockEntity.cookingProgress; + if (blockEntity.cookingProgress == blockEntity.cookingTotalTime) { + blockEntity.cookingProgress = 0; + blockEntity.cookingTotalTime = getTotalCookTime(level, blockEntity); +- if (burn(level.registryAccess(), recipeHolder, blockEntity.items, maxStackSize)) { +- blockEntity.setRecipeUsed(recipeHolder); ++ if (burn(blockEntity.level, blockEntity.worldPosition, level.registryAccess(), recipeholder, blockEntity.items, i)) { // CraftBukkit ++ blockEntity.setRecipeUsed(recipeholder); + } + +- flag = true; ++ flag1 = true; + } + } else { + blockEntity.cookingProgress = 0; + } +- } else if (!blockEntity.isLit() && blockEntity.cookingProgress > 0) { +- blockEntity.cookingProgress = Mth.clamp(blockEntity.cookingProgress - 2, 0, blockEntity.cookingTotalTime); + } + +- if (isLit != blockEntity.isLit()) { +- flag = true; +- state = state.setValue(AbstractFurnaceBlock.LIT, Boolean.valueOf(blockEntity.isLit())); ++ if (flag != blockEntity.isLit()) { ++ flag1 = true; ++ state = (IBlockData) state.setValue(AbstractFurnaceBlock.LIT, blockEntity.isLit()); + level.setBlock(pos, state, 3); + } + +- if (flag) { ++ if (flag1) { + setChanged(level, pos, state); + } ++ + } + +- private static boolean canBurn(RegistryAccess registryAccess, @Nullable RecipeHolder recipeHolder, NonNullList list, int i) { +- if (!list.get(0).isEmpty() && recipeHolder != null) { +- ItemStack resultItem = recipeHolder.value().getResultItem(registryAccess); +- if (resultItem.isEmpty()) { ++ private static boolean canBurn(RegistryAccess iregistrycustom, @Nullable RecipeHolder recipeholder, NonNullList nonnulllist, int i) { ++ if (!((ItemStack) nonnulllist.get(0)).isEmpty() && recipeholder != null) { ++ ItemStack itemstack = recipeholder.value().getResultItem(iregistrycustom); ++ ++ if (itemstack.isEmpty()) { + return false; + } else { +- ItemStack itemStack = list.get(2); +- return itemStack.isEmpty() +- || ItemStack.isSameItem(itemStack, resultItem) +- && ( +- itemStack.getCount() < i && itemStack.getCount() < itemStack.getMaxStackSize() +- || itemStack.getCount() < resultItem.getMaxStackSize() +- ); ++ ItemStack itemstack1 = (ItemStack) nonnulllist.get(2); ++ ++ return itemstack1.isEmpty() ? true : (!ItemStack.isSameItem(itemstack1, itemstack) ? false : (itemstack1.getCount() < i && itemstack1.getCount() < itemstack1.getMaxStackSize() ? true : itemstack1.getCount() < itemstack.getMaxStackSize())); + } + } else { + return false; + } + } + +- private static boolean burn(RegistryAccess registryAccess, @Nullable RecipeHolder recipeHolder, NonNullList list, int i) { +- if (recipeHolder != null && canBurn(registryAccess, recipeHolder, list, i)) { +- ItemStack itemStack = list.get(0); +- ItemStack resultItem = recipeHolder.value().getResultItem(registryAccess); +- ItemStack itemStack1 = list.get(2); +- if (itemStack1.isEmpty()) { +- list.set(2, resultItem.copy()); +- } else if (itemStack1.is(resultItem.getItem())) { +- itemStack1.grow(1); ++ private static boolean burn(Level world, BlockPos blockposition, RegistryAccess iregistrycustom, @Nullable RecipeHolder recipeholder, NonNullList nonnulllist, int i) { // CraftBukkit ++ if (recipeholder != null && canBurn(iregistrycustom, recipeholder, nonnulllist, i)) { ++ ItemStack itemstack = (ItemStack) nonnulllist.get(0); ++ ItemStack itemstack1 = recipeholder.value().getResultItem(iregistrycustom); ++ ItemStack itemstack2 = (ItemStack) nonnulllist.get(2); ++ ++ // CraftBukkit start - fire FurnaceSmeltEvent ++ CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); ++ org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); ++ ++ FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(CraftBlock.at(world, blockposition), source, result); ++ world.getCraftServer().getPluginManager().callEvent(furnaceSmeltEvent); ++ ++ if (furnaceSmeltEvent.isCancelled()) { ++ return false; + } + +- if (itemStack.is(Blocks.WET_SPONGE.asItem()) && !list.get(1).isEmpty() && list.get(1).is(Items.BUCKET)) { +- list.set(1, new ItemStack(Items.WATER_BUCKET)); ++ result = furnaceSmeltEvent.getResult(); ++ itemstack1 = CraftItemStack.asNMSCopy(result); ++ ++ if (!itemstack1.isEmpty()) { ++ if (itemstack2.isEmpty()) { ++ nonnulllist.set(2, itemstack1.copy()); ++ } else if (CraftItemStack.asCraftMirror(itemstack2).isSimilar(result)) { ++ itemstack2.grow(itemstack1.getCount()); ++ } else { ++ return false; ++ } + } + +- itemStack.shrink(1); ++ /* ++ if (itemstack2.isEmpty()) { ++ nonnulllist.set(2, itemstack1.copy()); ++ } else if (itemstack2.is(itemstack1.getItem())) { ++ itemstack2.grow(1); ++ } ++ */ ++ // CraftBukkit end ++ ++ if (itemstack.is(Blocks.WET_SPONGE.asItem()) && !((ItemStack) nonnulllist.get(1)).isEmpty() && ((ItemStack) nonnulllist.get(1)).is(Items.BUCKET)) { ++ nonnulllist.set(1, new ItemStack(Items.WATER_BUCKET)); ++ } ++ ++ itemstack.shrink(1); + return true; + } else { + return false; +@@ -344,12 +464,16 @@ + return 0; + } else { + Item item = fuel.getItem(); +- return getFuel().getOrDefault(item, 0); ++ ++ return (Integer) getFuel().getOrDefault(item, 0); + } + } + + private static int getTotalCookTime(Level level, AbstractFurnaceBlockEntity blockEntity) { +- return blockEntity.quickCheck.getRecipeFor(blockEntity, level).map(recipeHolder -> recipeHolder.value().getCookingTime()).orElse(200); ++ if (level == null) return 200; // CraftBukkit - SPIGOT-4302 ++ return (Integer) blockEntity.quickCheck.getRecipeFor(blockEntity, level).map((recipeholder) -> { ++ return ((AbstractCookingRecipe) recipeholder.value()).getCookingTime(); ++ }).orElse(200); + } + + public static boolean isFuel(ItemStack stack) { +@@ -358,11 +482,7 @@ + + @Override + public int[] getSlotsForFace(Direction side) { +- if (side == Direction.DOWN) { +- return SLOTS_FOR_DOWN; +- } else { +- return side == Direction.UP ? SLOTS_FOR_UP : SLOTS_FOR_SIDES; +- } ++ return side == Direction.DOWN ? AbstractFurnaceBlockEntity.SLOTS_FOR_DOWN : (side == Direction.UP ? AbstractFurnaceBlockEntity.SLOTS_FOR_UP : AbstractFurnaceBlockEntity.SLOTS_FOR_SIDES); + } + + @Override +@@ -372,7 +492,7 @@ + + @Override + public boolean canTakeItemThroughFace(int index, ItemStack stack, Direction direction) { +- return direction != Direction.DOWN || index != 1 || stack.is(Items.WATER_BUCKET) || stack.is(Items.BUCKET); ++ return direction == Direction.DOWN && index == 1 ? stack.is(Items.WATER_BUCKET) || stack.is(Items.BUCKET) : true; + } + + @Override +@@ -382,18 +502,24 @@ + + @Override + public boolean isEmpty() { +- for (ItemStack itemStack : this.items) { +- if (!itemStack.isEmpty()) { +- return false; ++ Iterator iterator = this.items.iterator(); ++ ++ ItemStack itemstack; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return true; + } +- } + +- return true; ++ itemstack = (ItemStack) iterator.next(); ++ } while (itemstack.isEmpty()); ++ ++ return false; + } + + @Override + public ItemStack getItem(int index) { +- return this.items.get(index); ++ return (ItemStack) this.items.get(index); + } + + @Override +@@ -408,8 +534,9 @@ + + @Override + public void setItem(int index, ItemStack stack) { +- ItemStack itemStack = this.items.get(index); +- boolean flag = !stack.isEmpty() && ItemStack.isSameItemSameTags(itemStack, stack); ++ ItemStack itemstack1 = (ItemStack) this.items.get(index); ++ boolean flag = !stack.isEmpty() && ItemStack.isSameItemSameTags(itemstack1, stack); ++ + this.items.set(index, stack); + if (stack.getCount() > this.getMaxStackSize()) { + stack.setCount(this.getMaxStackSize()); +@@ -420,10 +547,11 @@ + this.cookingProgress = 0; + this.setChanged(); + } ++ + } + + @Override +- public boolean stillValid(Player player) { ++ public boolean stillValid(net.minecraft.world.entity.player.Player player) { + return Container.stillValidBlockEntity(this, player); + } + +@@ -434,8 +562,9 @@ + } else if (index != 1) { + return true; + } else { +- ItemStack itemStack = this.items.get(1); +- return isFuel(stack) || stack.is(Items.BUCKET) && !itemStack.is(Items.BUCKET); ++ ItemStack itemstack1 = (ItemStack) this.items.get(1); ++ ++ return isFuel(stack) || stack.is(Items.BUCKET) && !itemstack1.is(Items.BUCKET); + } + } + +@@ -445,11 +574,13 @@ + } + + @Override +- public void setRecipeUsed(@Nullable RecipeHolder recipeHolder) { +- if (recipeHolder != null) { +- ResourceLocation resourceLocation = recipeHolder.id(); +- this.recipesUsed.addTo(resourceLocation, 1); ++ public void setRecipeUsed(@Nullable RecipeHolder recipeholder) { ++ if (recipeholder != null) { ++ ResourceLocation minecraftkey = recipeholder.id(); ++ ++ this.recipesUsed.addTo(minecraftkey, 1); + } ++ + } + + @Nullable +@@ -459,16 +590,19 @@ + } + + @Override +- public void awardUsedRecipes(Player player, List items) { +- } ++ public void awardUsedRecipes(net.minecraft.world.entity.player.Player player, List items) {} + +- public void awardUsedRecipesAndPopExperience(ServerPlayer player) { +- List> recipesToAwardAndPopExperience = this.getRecipesToAwardAndPopExperience(player.serverLevel(), player.position()); +- player.awardRecipes(recipesToAwardAndPopExperience); ++ public void awardUsedRecipesAndPopExperience(ServerPlayer entityplayer, ItemStack itemstack, int amount) { // CraftBukkit ++ List> list = this.getRecipesToAwardAndPopExperience(entityplayer.serverLevel(), entityplayer.position(), this.worldPosition, entityplayer, itemstack, amount); // CraftBukkit + +- for (RecipeHolder recipeHolder : recipesToAwardAndPopExperience) { +- if (recipeHolder != null) { +- player.triggerRecipeCrafted(recipeHolder, this.items); ++ entityplayer.awardRecipes(list); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ RecipeHolder recipeholder = (RecipeHolder) iterator.next(); ++ ++ if (recipeholder != null) { ++ entityplayer.triggerRecipeCrafted(recipeholder, this.items); + } + } + +@@ -476,32 +610,58 @@ + } + + public List> getRecipesToAwardAndPopExperience(ServerLevel level, Vec3 popVec) { ++ // CraftBukkit start ++ return this.getRecipesToAwardAndPopExperience(level, popVec, this.worldPosition, null, null, 0); ++ } ++ ++ public List> getRecipesToAwardAndPopExperience(ServerLevel worldserver, Vec3 vec3d, BlockPos blockposition, ServerPlayer entityplayer, ItemStack itemstack, int amount) { ++ // CraftBukkit end + List> list = Lists.newArrayList(); ++ ObjectIterator objectiterator = this.recipesUsed.object2IntEntrySet().iterator(); + +- for (Entry entry : this.recipesUsed.object2IntEntrySet()) { +- level.getRecipeManager().byKey(entry.getKey()).ifPresent(recipeHolder -> { +- list.add((RecipeHolder)recipeHolder); +- createExperience(level, popVec, entry.getIntValue(), ((AbstractCookingRecipe)recipeHolder.value()).getExperience()); ++ while (objectiterator.hasNext()) { ++ Entry entry = (Entry) objectiterator.next(); ++ ++ worldserver.getRecipeManager().byKey((ResourceLocation) entry.getKey()).ifPresent((recipeholder) -> { ++ list.add(recipeholder); ++ createExperience(worldserver, vec3d, entry.getIntValue(), ((AbstractCookingRecipe) recipeholder.value()).getExperience(), blockposition, entityplayer, itemstack, amount); // CraftBukkit + }); + } + + return list; + } + +- private static void createExperience(ServerLevel level, Vec3 popVec, int recipeIndex, float experience) { +- int floor = Mth.floor((float)recipeIndex * experience); +- float fraction = Mth.frac((float)recipeIndex * experience); +- if (fraction != 0.0F && Math.random() < (double)fraction) { +- floor++; ++ private static void createExperience(ServerLevel worldserver, Vec3 vec3d, int i, float f, BlockPos blockposition, net.minecraft.world.entity.player.Player entityhuman, ItemStack itemstack, int amount) { // CraftBukkit ++ int j = Mth.floor((float) i * f); ++ float f1 = Mth.frac((float) i * f); ++ ++ if (f1 != 0.0F && Math.random() < (double) f1) { ++ ++j; + } + +- ExperienceOrb.award(level, popVec, floor); ++ // CraftBukkit start - fire FurnaceExtractEvent / BlockExpEvent ++ BlockExpEvent event; ++ if (amount != 0) { ++ event = new FurnaceExtractEvent((Player) entityhuman.getBukkitEntity(), CraftBlock.at(worldserver, blockposition), org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(itemstack.getItem()), amount, j); ++ } else { ++ event = new BlockExpEvent(CraftBlock.at(worldserver, blockposition), j); ++ } ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ j = event.getExpToDrop(); ++ // CraftBukkit end ++ ++ ExperienceOrb.award(worldserver, vec3d, j); + } + + @Override + public void fillStackedContents(StackedContents helper) { +- for (ItemStack itemStack : this.items) { +- helper.accountStack(itemStack); ++ Iterator iterator = this.items.iterator(); ++ ++ while (iterator.hasNext()) { ++ ItemStack itemstack = (ItemStack) iterator.next(); ++ ++ helper.accountStack(itemstack); + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BannerBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BannerBlockEntity.java.patch new file mode 100644 index 0000000000..291cc12eeb --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BannerBlockEntity.java.patch @@ -0,0 +1,182 @@ +--- a/net/minecraft/world/level/block/entity/BannerBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BannerBlockEntity.java +@@ -11,46 +11,48 @@ + import net.minecraft.nbt.ListTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +-import net.minecraft.world.Nameable; ++import net.minecraft.world.INamableTileEntity; + import net.minecraft.world.item.BlockItem; + import net.minecraft.world.item.DyeColor; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.AbstractBannerBlock; + import net.minecraft.world.level.block.BannerBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + +-public class BannerBlockEntity extends BlockEntity implements Nameable { ++public class BannerBlockEntity extends BlockEntity implements INamableTileEntity { ++ + public static final int MAX_PATTERNS = 6; + public static final String TAG_PATTERNS = "Patterns"; + public static final String TAG_PATTERN = "Pattern"; + public static final String TAG_COLOR = "Color"; + @Nullable + private Component name; +- private DyeColor baseColor; ++ public DyeColor baseColor; + @Nullable +- private ListTag itemPatterns; ++ public ListTag itemPatterns; + @Nullable + private List, DyeColor>> patterns; + +- public BannerBlockEntity(BlockPos pos, BlockState blockState) { ++ public BannerBlockEntity(BlockPos pos, IBlockData blockState) { + super(BlockEntityType.BANNER, pos, blockState); +- this.baseColor = ((AbstractBannerBlock)blockState.getBlock()).getColor(); ++ this.baseColor = ((AbstractBannerBlock) blockState.getBlock()).getColor(); + } + +- public BannerBlockEntity(BlockPos pos, BlockState blockState, DyeColor baseColor) { ++ public BannerBlockEntity(BlockPos pos, IBlockData blockState, DyeColor baseColor) { + this(pos, blockState); + this.baseColor = baseColor; + } + + @Nullable + public static ListTag getItemPatterns(ItemStack stack) { +- ListTag list = null; +- CompoundTag blockEntityData = BlockItem.getBlockEntityData(stack); +- if (blockEntityData != null && blockEntityData.contains("Patterns", 9)) { +- list = blockEntityData.getList("Patterns", 10).copy(); ++ ListTag nbttaglist = null; ++ CompoundTag nbttagcompound = BlockItem.getBlockEntityData(stack); ++ ++ if (nbttagcompound != null && nbttagcompound.contains("Patterns", 9)) { ++ nbttaglist = nbttagcompound.getList("Patterns", 10).copy(); + } + +- return list; ++ return nbttaglist; + } + + public void fromItem(ItemStack stack, DyeColor color) { +@@ -66,7 +68,7 @@ + + @Override + public Component getName() { +- return (Component)(this.name != null ? this.name : Component.translatable("block.minecraft.banner")); ++ return (Component) (this.name != null ? this.name : Component.translatable("block.minecraft.banner")); + } + + @Nullable +@@ -89,6 +91,7 @@ + if (this.name != null) { + tag.putString("CustomName", Component.Serializer.toJson(this.name)); + } ++ + } + + @Override +@@ -99,6 +102,11 @@ + } + + this.itemPatterns = tag.getList("Patterns", 10); ++ // CraftBukkit start ++ while (this.itemPatterns.size() > 20) { ++ this.itemPatterns.remove(20); ++ } ++ // CraftBukkit end + this.patterns = null; + } + +@@ -113,8 +121,9 @@ + } + + public static int getPatternCount(ItemStack stack) { +- CompoundTag blockEntityData = BlockItem.getBlockEntityData(stack); +- return blockEntityData != null && blockEntityData.contains("Patterns") ? blockEntityData.getList("Patterns", 10).size() : 0; ++ CompoundTag nbttagcompound = BlockItem.getBlockEntityData(stack); ++ ++ return nbttagcompound != null && nbttagcompound.contains("Patterns") ? nbttagcompound.getList("Patterns", 10).size() : 0; + } + + public List, DyeColor>> getPatterns() { +@@ -127,14 +136,17 @@ + + public static List, DyeColor>> createPatterns(DyeColor color, @Nullable ListTag listTag) { + List, DyeColor>> list = Lists.newArrayList(); ++ + list.add(Pair.of(BuiltInRegistries.BANNER_PATTERN.getHolderOrThrow(BannerPatterns.BASE), color)); + if (listTag != null) { +- for (int i = 0; i < listTag.size(); i++) { +- CompoundTag compound = listTag.getCompound(i); +- Holder holder = BannerPattern.byHash(compound.getString("Pattern")); ++ for (int i = 0; i < listTag.size(); ++i) { ++ CompoundTag nbttagcompound = listTag.getCompound(i); ++ Holder holder = BannerPattern.byHash(nbttagcompound.getString("Pattern")); ++ + if (holder != null) { +- int _int = compound.getInt("Color"); +- list.add(Pair.of(holder, DyeColor.byId(_int))); ++ int j = nbttagcompound.getInt("Color"); ++ ++ list.add(Pair.of(holder, DyeColor.byId(j))); + } + } + } +@@ -143,34 +155,38 @@ + } + + public static void removeLastPattern(ItemStack stack) { +- CompoundTag blockEntityData = BlockItem.getBlockEntityData(stack); +- if (blockEntityData != null && blockEntityData.contains("Patterns", 9)) { +- ListTag list = blockEntityData.getList("Patterns", 10); +- if (!list.isEmpty()) { +- list.remove(list.size() - 1); +- if (list.isEmpty()) { +- blockEntityData.remove("Patterns"); ++ CompoundTag nbttagcompound = BlockItem.getBlockEntityData(stack); ++ ++ if (nbttagcompound != null && nbttagcompound.contains("Patterns", 9)) { ++ ListTag nbttaglist = nbttagcompound.getList("Patterns", 10); ++ ++ if (!nbttaglist.isEmpty()) { ++ nbttaglist.remove(nbttaglist.size() - 1); ++ if (nbttaglist.isEmpty()) { ++ nbttagcompound.remove("Patterns"); + } + } + +- blockEntityData.remove("id"); +- BlockItem.setBlockEntityData(stack, BlockEntityType.BANNER, blockEntityData); ++ nbttagcompound.remove("id"); ++ BlockItem.setBlockEntityData(stack, BlockEntityType.BANNER, nbttagcompound); + } + } + + public ItemStack getItem() { +- ItemStack itemStack = new ItemStack(BannerBlock.byColor(this.baseColor)); ++ ItemStack itemstack = new ItemStack(BannerBlock.byColor(this.baseColor)); ++ + if (this.itemPatterns != null && !this.itemPatterns.isEmpty()) { +- CompoundTag compoundTag = new CompoundTag(); +- compoundTag.put("Patterns", this.itemPatterns.copy()); +- BlockItem.setBlockEntityData(itemStack, this.getType(), compoundTag); ++ CompoundTag nbttagcompound = new CompoundTag(); ++ ++ nbttagcompound.put("Patterns", this.itemPatterns.copy()); ++ BlockItem.setBlockEntityData(itemstack, this.getType(), nbttagcompound); + } + + if (this.name != null) { +- itemStack.setHoverName(this.name); ++ itemstack.setHoverName(this.name); + } + +- return itemStack; ++ return itemstack; + } + + public DyeColor getBaseColor() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BarrelBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BarrelBlockEntity.java.patch new file mode 100644 index 0000000000..463b6e048f --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BarrelBlockEntity.java.patch @@ -0,0 +1,181 @@ +--- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.block.entity; + + import net.minecraft.core.BlockPos; ++import net.minecraft.core.Direction; + import net.minecraft.core.NonNullList; + import net.minecraft.core.Vec3i; + import net.minecraft.nbt.CompoundTag; +@@ -17,40 +18,84 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.BarrelBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class BarrelBlockEntity extends RandomizableContainerBlockEntity { +- private NonNullList items = NonNullList.withSize(27, ItemStack.EMPTY); +- private final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() { +- @Override +- protected void onOpen(Level level, BlockPos pos, BlockState state) { +- BarrelBlockEntity.this.playSound(state, SoundEvents.BARREL_OPEN); +- BarrelBlockEntity.this.updateBlockState(state, true); +- } + +- @Override +- protected void onClose(Level level, BlockPos pos, BlockState state) { +- BarrelBlockEntity.this.playSound(state, SoundEvents.BARREL_CLOSE); +- BarrelBlockEntity.this.updateBlockState(state, false); +- } ++ // CraftBukkit start - add fields and methods ++ public List transaction = new ArrayList<>(); ++ private int maxStack = MAX_STACK; + +- @Override +- protected void openerCountChanged(Level level, BlockPos pos, BlockState state, int count, int openCount) { +- } ++ @Override ++ public List getContents() { ++ return this.items; ++ } + +- @Override +- protected boolean isOwnContainer(Player player) { +- if (player.containerMenu instanceof ChestMenu) { +- Container container = ((ChestMenu)player.containerMenu).getContainer(); +- return container == BarrelBlockEntity.this; +- } else { +- return false; +- } +- } +- }; ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } + +- public BarrelBlockEntity(BlockPos pos, BlockState blockState) { ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ @Override ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ // CraftBukkit end ++ private NonNullList items; ++ public final ContainerOpenersCounter openersCounter; ++ ++ public BarrelBlockEntity(BlockPos pos, IBlockData blockState) { + super(BlockEntityType.BARREL, pos, blockState); ++ this.items = NonNullList.withSize(27, ItemStack.EMPTY); ++ this.openersCounter = new ContainerOpenersCounter() { ++ @Override ++ protected void onOpen(Level level, BlockPos pos, IBlockData state) { ++ BarrelBlockEntity.this.playSound(state, SoundEvents.BARREL_OPEN); ++ BarrelBlockEntity.this.updateBlockState(state, true); ++ } ++ ++ @Override ++ protected void onClose(Level level, BlockPos pos, IBlockData state) { ++ BarrelBlockEntity.this.playSound(state, SoundEvents.BARREL_CLOSE); ++ BarrelBlockEntity.this.updateBlockState(state, false); ++ } ++ ++ @Override ++ protected void openerCountChanged(Level level, BlockPos pos, IBlockData state, int count, int openCount) {} ++ ++ @Override ++ protected boolean isOwnContainer(Player player) { ++ if (player.containerMenu instanceof ChestMenu) { ++ Container iinventory = ((ChestMenu) player.containerMenu).getContainer(); ++ ++ return iinventory == BarrelBlockEntity.this; ++ } else { ++ return false; ++ } ++ } ++ }; + } + + @Override +@@ -59,6 +104,7 @@ + if (!this.trySaveLootTable(tag)) { + ContainerHelper.saveAllItems(tag, this.items); + } ++ + } + + @Override +@@ -68,6 +114,7 @@ + if (!this.tryLoadLootTable(tag)) { + ContainerHelper.loadAllItems(tag, this.items); + } ++ + } + + @Override +@@ -100,6 +147,7 @@ + if (!this.remove && !player.isSpectator()) { + this.openersCounter.incrementOpeners(player, this.getLevel(), this.getBlockPos(), this.getBlockState()); + } ++ + } + + @Override +@@ -107,23 +155,26 @@ + if (!this.remove && !player.isSpectator()) { + this.openersCounter.decrementOpeners(player, this.getLevel(), this.getBlockPos(), this.getBlockState()); + } ++ + } + + public void recheckOpen() { + if (!this.remove) { + this.openersCounter.recheckOpeners(this.getLevel(), this.getBlockPos(), this.getBlockState()); + } ++ + } + +- void updateBlockState(BlockState state, boolean _open) { +- this.level.setBlock(this.getBlockPos(), state.setValue(BarrelBlock.OPEN, Boolean.valueOf(_open)), 3); ++ public void updateBlockState(IBlockData state, boolean open) { ++ this.level.setBlock(this.getBlockPos(), (IBlockData) state.setValue(BarrelBlock.OPEN, open), 3); + } + +- void playSound(BlockState state, SoundEvent sound) { +- Vec3i normal = state.getValue(BarrelBlock.FACING).getNormal(); +- double d = (double)this.worldPosition.getX() + 0.5 + (double)normal.getX() / 2.0; +- double d1 = (double)this.worldPosition.getY() + 0.5 + (double)normal.getY() / 2.0; +- double d2 = (double)this.worldPosition.getZ() + 0.5 + (double)normal.getZ() / 2.0; +- this.level.playSound(null, d, d1, d2, sound, SoundSource.BLOCKS, 0.5F, this.level.random.nextFloat() * 0.1F + 0.9F); ++ public void playSound(IBlockData state, SoundEvent sound) { ++ Vec3i baseblockposition = ((Direction) state.getValue(BarrelBlock.FACING)).getNormal(); ++ double d0 = (double) this.worldPosition.getX() + 0.5D + (double) baseblockposition.getX() / 2.0D; ++ double d1 = (double) this.worldPosition.getY() + 0.5D + (double) baseblockposition.getY() / 2.0D; ++ double d2 = (double) this.worldPosition.getZ() + 0.5D + (double) baseblockposition.getZ() / 2.0D; ++ ++ this.level.playSound((Player) null, d0, d1, d2, sound, SoundSource.BLOCKS, 0.5F, this.level.random.nextFloat() * 0.1F + 0.9F); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java.patch new file mode 100644 index 0000000000..0022209959 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java +@@ -7,21 +7,23 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.Container; ++import net.minecraft.world.INamableTileEntity; ++import net.minecraft.world.ITileInventory; + import net.minecraft.world.LockCode; +-import net.minecraft.world.MenuProvider; +-import net.minecraft.world.Nameable; + import net.minecraft.world.entity.player.Inventory; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.inventory.AbstractContainerMenu; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + +-public abstract class BaseContainerBlockEntity extends BlockEntity implements Container, MenuProvider, Nameable { +- private LockCode lockKey = LockCode.NO_LOCK; ++public abstract class BaseContainerBlockEntity extends BlockEntity implements Container, ITileInventory, INamableTileEntity { ++ ++ public LockCode lockKey; + @Nullable +- private Component name; ++ public Component name; + +- protected BaseContainerBlockEntity(BlockEntityType type, BlockPos pos, BlockState blockState) { ++ protected BaseContainerBlockEntity(BlockEntityType type, BlockPos pos, IBlockData blockState) { + super(type, pos, blockState); ++ this.lockKey = LockCode.NO_LOCK; + } + + @Override +@@ -31,6 +33,7 @@ + if (tag.contains("CustomName", 8)) { + this.name = Component.Serializer.fromJson(tag.getString("CustomName")); + } ++ + } + + @Override +@@ -40,6 +43,7 @@ + if (this.name != null) { + tag.putString("CustomName", Component.Serializer.toJson(this.name)); + } ++ + } + + public void setCustomName(Component name) { +@@ -85,4 +89,12 @@ + } + + protected abstract AbstractContainerMenu createMenu(int containerId, Inventory inventory); ++ ++ // CraftBukkit start ++ @Override ++ public org.bukkit.Location getLocation() { ++ if (level == null) return null; ++ return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BeaconBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BeaconBlockEntity.java.patch new file mode 100644 index 0000000000..6f678f819a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BeaconBlockEntity.java.patch @@ -0,0 +1,520 @@ +--- a/net/minecraft/world/level/block/entity/BeaconBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +@@ -3,6 +3,7 @@ + import com.google.common.collect.ImmutableList; + import com.google.common.collect.Lists; + import java.util.Arrays; ++import java.util.Iterator; + import java.util.List; + import java.util.Set; + import java.util.stream.Collectors; +@@ -19,9 +20,9 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.tags.BlockTags; ++import net.minecraft.world.INamableTileEntity; ++import net.minecraft.world.ITileInventory; + import net.minecraft.world.LockCode; +-import net.minecraft.world.MenuProvider; +-import net.minecraft.world.Nameable; + import net.minecraft.world.effect.MobEffect; + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.effect.MobEffects; +@@ -32,22 +33,22 @@ + import net.minecraft.world.inventory.ContainerData; + import net.minecraft.world.inventory.ContainerLevelAccess; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.BeaconBeamBlock; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.IBeaconBeam; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.levelgen.Heightmap; + import net.minecraft.world.phys.AABB; ++// CraftBukkit start ++import org.bukkit.craftbukkit.potion.CraftPotionUtil; ++import org.bukkit.potion.PotionEffect; ++// CraftBukkit end + +-public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Nameable { ++public class BeaconBlockEntity extends BlockEntity implements ITileInventory, INamableTileEntity { ++ + private static final int MAX_LEVELS = 4; +- public static final MobEffect[][] BEACON_EFFECTS = new MobEffect[][]{ +- {MobEffects.MOVEMENT_SPEED, MobEffects.DIG_SPEED}, +- {MobEffects.DAMAGE_RESISTANCE, MobEffects.JUMP}, +- {MobEffects.DAMAGE_BOOST}, +- {MobEffects.REGENERATION} +- }; +- private static final Set VALID_EFFECTS = Arrays.stream(BEACON_EFFECTS).flatMap(Arrays::stream).collect(Collectors.toSet()); ++ public static final MobEffect[][] BEACON_EFFECTS = new MobEffect[][]{{MobEffects.MOVEMENT_SPEED, MobEffects.DIG_SPEED}, {MobEffects.DAMAGE_RESISTANCE, MobEffects.JUMP}, {MobEffects.DAMAGE_BOOST}, {MobEffects.REGENERATION}}; ++ private static final Set VALID_EFFECTS = (Set) Arrays.stream(BeaconBlockEntity.BEACON_EFFECTS).flatMap(Arrays::stream).collect(Collectors.toSet()); + public static final int DATA_LEVELS = 0; + public static final int DATA_PRIMARY = 1; + public static final int DATA_SECONDARY = 2; +@@ -58,117 +59,137 @@ + private static final String TAG_SECONDARY = "secondary_effect"; + List beamSections = Lists.newArrayList(); + private List checkingBeamSections = Lists.newArrayList(); +- int levels; ++ public int levels; + private int lastCheckY; + @Nullable +- MobEffect primaryPower; ++ public MobEffect primaryPower; + @Nullable +- MobEffect secondaryPower; ++ public MobEffect secondaryPower; + @Nullable +- private Component name; +- private LockCode lockKey = LockCode.NO_LOCK; +- private final ContainerData dataAccess = new ContainerData() { +- @Override +- public int get(int index) { +- return switch (index) { +- case 0 -> BeaconBlockEntity.this.levels; +- case 1 -> BeaconMenu.encodeEffect(BeaconBlockEntity.this.primaryPower); +- case 2 -> BeaconMenu.encodeEffect(BeaconBlockEntity.this.secondaryPower); +- default -> 0; +- }; +- } ++ public Component name; ++ public LockCode lockKey; ++ private final ContainerData dataAccess; ++ // CraftBukkit start - add fields and methods ++ public PotionEffect getPrimaryEffect() { ++ return (this.primaryPower != null) ? CraftPotionUtil.toBukkit(new MobEffectInstance(this.primaryPower, getLevel(this.levels), getAmplification(levels, primaryPower, secondaryPower), true, true)) : null; ++ } + +- @Override +- public void set(int index, int value) { +- switch (index) { +- case 0: +- BeaconBlockEntity.this.levels = value; +- break; +- case 1: +- if (!BeaconBlockEntity.this.level.isClientSide && !BeaconBlockEntity.this.beamSections.isEmpty()) { +- BeaconBlockEntity.playSound(BeaconBlockEntity.this.level, BeaconBlockEntity.this.worldPosition, SoundEvents.BEACON_POWER_SELECT); +- } ++ public PotionEffect getSecondaryEffect() { ++ return (hasSecondaryEffect(levels, primaryPower, secondaryPower)) ? CraftPotionUtil.toBukkit(new MobEffectInstance(this.secondaryPower, getLevel(this.levels), getAmplification(levels, primaryPower, secondaryPower), true, true)) : null; ++ } ++ // CraftBukkit end + +- BeaconBlockEntity.this.primaryPower = BeaconBlockEntity.filterEffect(BeaconMenu.decodeEffect(value)); +- break; +- case 2: +- BeaconBlockEntity.this.secondaryPower = BeaconBlockEntity.filterEffect(BeaconMenu.decodeEffect(value)); +- } +- } +- +- @Override +- public int getCount() { +- return 3; +- } +- }; +- + @Nullable +- static MobEffect filterEffect(@Nullable MobEffect mobEffect) { +- return VALID_EFFECTS.contains(mobEffect) ? mobEffect : null; ++ static MobEffect filterEffect(@Nullable MobEffect mobeffectlist) { ++ return BeaconBlockEntity.VALID_EFFECTS.contains(mobeffectlist) ? mobeffectlist : null; + } + +- public BeaconBlockEntity(BlockPos pos, BlockState blockState) { ++ public BeaconBlockEntity(BlockPos pos, IBlockData blockState) { + super(BlockEntityType.BEACON, pos, blockState); ++ this.lockKey = LockCode.NO_LOCK; ++ this.dataAccess = new ContainerData() { ++ @Override ++ public int get(int index) { ++ int j; ++ ++ switch (index) { ++ case 0: ++ j = BeaconBlockEntity.this.levels; ++ break; ++ case 1: ++ j = BeaconMenu.encodeEffect(BeaconBlockEntity.this.primaryPower); ++ break; ++ case 2: ++ j = BeaconMenu.encodeEffect(BeaconBlockEntity.this.secondaryPower); ++ break; ++ default: ++ j = 0; ++ } ++ ++ return j; ++ } ++ ++ @Override ++ public void set(int index, int value) { ++ switch (index) { ++ case 0: ++ BeaconBlockEntity.this.levels = value; ++ break; ++ case 1: ++ if (!BeaconBlockEntity.this.level.isClientSide && !BeaconBlockEntity.this.beamSections.isEmpty()) { ++ BeaconBlockEntity.playSound(BeaconBlockEntity.this.level, BeaconBlockEntity.this.worldPosition, SoundEvents.BEACON_POWER_SELECT); ++ } ++ ++ BeaconBlockEntity.this.primaryPower = BeaconBlockEntity.filterEffect(BeaconMenu.decodeEffect(value)); ++ break; ++ case 2: ++ BeaconBlockEntity.this.secondaryPower = BeaconBlockEntity.filterEffect(BeaconMenu.decodeEffect(value)); ++ } ++ ++ } ++ ++ @Override ++ public int getCount() { ++ return 3; ++ } ++ }; + } + +- public static void tick(Level level, BlockPos pos, BlockState state, BeaconBlockEntity blockEntity) { +- int x = pos.getX(); +- int y = pos.getY(); +- int z = pos.getZ(); +- BlockPos blockPos; +- if (blockEntity.lastCheckY < y) { +- blockPos = pos; ++ public static void tick(Level level, BlockPos pos, IBlockData state, BeaconBlockEntity blockEntity) { ++ int i = pos.getX(); ++ int j = pos.getY(); ++ int k = pos.getZ(); ++ BlockPos blockposition1; ++ ++ if (blockEntity.lastCheckY < j) { ++ blockposition1 = pos; + blockEntity.checkingBeamSections = Lists.newArrayList(); + blockEntity.lastCheckY = pos.getY() - 1; + } else { +- blockPos = new BlockPos(x, blockEntity.lastCheckY + 1, z); ++ blockposition1 = new BlockPos(i, blockEntity.lastCheckY + 1, k); + } + +- BeaconBlockEntity.BeaconBeamSection beaconBeamSection = blockEntity.checkingBeamSections.isEmpty() +- ? null +- : blockEntity.checkingBeamSections.get(blockEntity.checkingBeamSections.size() - 1); +- int height = level.getHeight(Heightmap.Types.WORLD_SURFACE, x, z); ++ BeaconBlockEntity.BeaconBeamSection tileentitybeacon_beaconcolortracker = blockEntity.checkingBeamSections.isEmpty() ? null : (BeaconBlockEntity.BeaconBeamSection) blockEntity.checkingBeamSections.get(blockEntity.checkingBeamSections.size() - 1); ++ int l = level.getHeight(Heightmap.Types.WORLD_SURFACE, i, k); + +- for (int i = 0; i < 10 && blockPos.getY() <= height; i++) { +- BlockState blockState = level.getBlockState(blockPos); +- Block block = blockState.getBlock(); +- if (block instanceof BeaconBeamBlock) { +- float[] textureDiffuseColors = ((BeaconBeamBlock)block).getColor().getTextureDiffuseColors(); ++ int i1; ++ ++ for (i1 = 0; i1 < 10 && blockposition1.getY() <= l; ++i1) { ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ Block block = iblockdata1.getBlock(); ++ ++ if (block instanceof IBeaconBeam) { ++ float[] afloat = ((IBeaconBeam) block).getColor().getTextureDiffuseColors(); ++ + if (blockEntity.checkingBeamSections.size() <= 1) { +- beaconBeamSection = new BeaconBlockEntity.BeaconBeamSection(textureDiffuseColors); +- blockEntity.checkingBeamSections.add(beaconBeamSection); +- } else if (beaconBeamSection != null) { +- if (Arrays.equals(textureDiffuseColors, beaconBeamSection.color)) { +- beaconBeamSection.increaseHeight(); ++ tileentitybeacon_beaconcolortracker = new BeaconBlockEntity.BeaconBeamSection(afloat); ++ blockEntity.checkingBeamSections.add(tileentitybeacon_beaconcolortracker); ++ } else if (tileentitybeacon_beaconcolortracker != null) { ++ if (Arrays.equals(afloat, tileentitybeacon_beaconcolortracker.color)) { ++ tileentitybeacon_beaconcolortracker.increaseHeight(); + } else { +- beaconBeamSection = new BeaconBlockEntity.BeaconBeamSection( +- new float[]{ +- (beaconBeamSection.color[0] + textureDiffuseColors[0]) / 2.0F, +- (beaconBeamSection.color[1] + textureDiffuseColors[1]) / 2.0F, +- (beaconBeamSection.color[2] + textureDiffuseColors[2]) / 2.0F +- } +- ); +- blockEntity.checkingBeamSections.add(beaconBeamSection); ++ tileentitybeacon_beaconcolortracker = new BeaconBlockEntity.BeaconBeamSection(new float[]{(tileentitybeacon_beaconcolortracker.color[0] + afloat[0]) / 2.0F, (tileentitybeacon_beaconcolortracker.color[1] + afloat[1]) / 2.0F, (tileentitybeacon_beaconcolortracker.color[2] + afloat[2]) / 2.0F}); ++ blockEntity.checkingBeamSections.add(tileentitybeacon_beaconcolortracker); + } + } + } else { +- if (beaconBeamSection == null || blockState.getLightBlock(level, blockPos) >= 15 && !blockState.is(Blocks.BEDROCK)) { ++ if (tileentitybeacon_beaconcolortracker == null || iblockdata1.getLightBlock(level, blockposition1) >= 15 && !iblockdata1.is(Blocks.BEDROCK)) { + blockEntity.checkingBeamSections.clear(); +- blockEntity.lastCheckY = height; ++ blockEntity.lastCheckY = l; + break; + } + +- beaconBeamSection.increaseHeight(); ++ tileentitybeacon_beaconcolortracker.increaseHeight(); + } + +- blockPos = blockPos.above(); +- blockEntity.lastCheckY++; ++ blockposition1 = blockposition1.above(); ++ ++blockEntity.lastCheckY; + } + +- int i = blockEntity.levels; ++ i1 = blockEntity.levels; + if (level.getGameTime() % 80L == 0L) { + if (!blockEntity.beamSections.isEmpty()) { +- blockEntity.levels = updateBase(level, x, y, z); ++ blockEntity.levels = updateBase(level, i, j, k); + } + + if (blockEntity.levels > 0 && !blockEntity.beamSections.isEmpty()) { +@@ -177,41 +198,46 @@ + } + } + +- if (blockEntity.lastCheckY >= height) { ++ if (blockEntity.lastCheckY >= l) { + blockEntity.lastCheckY = level.getMinBuildHeight() - 1; +- boolean flag = i > 0; ++ boolean flag = i1 > 0; ++ + blockEntity.beamSections = blockEntity.checkingBeamSections; + if (!level.isClientSide) { + boolean flag1 = blockEntity.levels > 0; ++ + if (!flag && flag1) { + playSound(level, pos, SoundEvents.BEACON_ACTIVATE); ++ Iterator iterator = level.getEntitiesOfClass(ServerPlayer.class, (new AABB((double) i, (double) j, (double) k, (double) i, (double) (j - 4), (double) k)).inflate(10.0D, 5.0D, 10.0D)).iterator(); + +- for (ServerPlayer serverPlayer : level.getEntitiesOfClass( +- ServerPlayer.class, new AABB((double)x, (double)y, (double)z, (double)x, (double)(y - 4), (double)z).inflate(10.0, 5.0, 10.0) +- )) { +- CriteriaTriggers.CONSTRUCT_BEACON.trigger(serverPlayer, blockEntity.levels); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ CriteriaTriggers.CONSTRUCT_BEACON.trigger(entityplayer, blockEntity.levels); + } + } else if (flag && !flag1) { + playSound(level, pos, SoundEvents.BEACON_DEACTIVATE); + } + } + } ++ + } + + private static int updateBase(Level level, int x, int y, int z) { +- int i = 0; ++ int l = 0; + +- for (int i1 = 1; i1 <= 4; i = i1++) { +- int i2 = y - i1; +- if (i2 < level.getMinBuildHeight()) { ++ for (int i1 = 1; i1 <= 4; l = i1++) { ++ int j1 = y - i1; ++ ++ if (j1 < level.getMinBuildHeight()) { + break; + } + + boolean flag = true; + +- for (int i3 = x - i1; i3 <= x + i1 && flag; i3++) { +- for (int i4 = z - i1; i4 <= z + i1; i4++) { +- if (!level.getBlockState(new BlockPos(i3, i2, i4)).is(BlockTags.BEACON_BASE_BLOCKS)) { ++ for (int k1 = x - i1; k1 <= x + i1 && flag; ++k1) { ++ for (int l1 = z - i1; l1 <= z + i1; ++l1) { ++ if (!level.getBlockState(new BlockPos(k1, j1, l1)).is(BlockTags.BEACON_BASE_BLOCKS)) { + flag = false; + break; + } +@@ -223,7 +249,7 @@ + } + } + +- return i; ++ return l; + } + + @Override +@@ -232,36 +258,84 @@ + super.setRemoved(); + } + +- private static void applyEffects(Level level, BlockPos pos, int levels, @Nullable MobEffect primary, @Nullable MobEffect secondary) { +- if (!level.isClientSide && primary != null) { +- double d = (double)(levels * 10 + 10); +- int i = 0; +- if (levels >= 4 && primary == secondary) { +- i = 1; ++ // CraftBukkit start - split into components ++ private static byte getAmplification(int i, @Nullable MobEffect mobeffectlist, @Nullable MobEffect mobeffectlist1) { ++ { ++ byte b0 = 0; ++ ++ if (i >= 4 && mobeffectlist == mobeffectlist1) { ++ b0 = 1; + } + +- int i1 = (9 + levels * 2) * 20; +- AABB aABB = new AABB(pos).inflate(d).expandTowards(0.0, (double)level.getHeight(), 0.0); +- List entitiesOfClass = level.getEntitiesOfClass(Player.class, aABB); ++ return b0; ++ } ++ } + +- for (Player player : entitiesOfClass) { +- player.addEffect(new MobEffectInstance(primary, i1, i, true, true)); ++ private static int getLevel(int i) { ++ { ++ int j = (9 + i * 2) * 20; ++ return j; ++ } ++ } ++ ++ public static List getHumansInRange(Level world, BlockPos blockposition, int i) { ++ { ++ double d0 = (double) (i * 10 + 10); ++ ++ AABB axisalignedbb = (new AABB(blockposition)).inflate(d0).expandTowards(0.0D, (double) world.getHeight(), 0.0D); ++ List list = world.getEntitiesOfClass(Player.class, axisalignedbb); ++ ++ return list; ++ } ++ } ++ ++ private static void applyEffect(List list, MobEffect mobeffectlist, int j, int b0) { ++ { ++ Iterator iterator = list.iterator(); ++ ++ Player entityhuman; ++ ++ while (iterator.hasNext()) { ++ entityhuman = (Player) iterator.next(); ++ entityhuman.addEffect(new MobEffectInstance(mobeffectlist, j, b0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); + } ++ } ++ } + +- if (levels >= 4 && primary != secondary && secondary != null) { +- for (Player player : entitiesOfClass) { +- player.addEffect(new MobEffectInstance(secondary, i1, 0, true, true)); +- } ++ private static boolean hasSecondaryEffect(int i, @Nullable MobEffect mobeffectlist, @Nullable MobEffect mobeffectlist1) { ++ { ++ if (i >= 4 && mobeffectlist != mobeffectlist1 && mobeffectlist1 != null) { ++ return true; + } ++ ++ return false; + } + } + ++ private static void applyEffects(Level level, BlockPos pos, int levels, @Nullable MobEffect primary, @Nullable MobEffect secondary) { ++ if (!level.isClientSide && primary != null) { ++ double d0 = (double) (levels * 10 + 10); ++ byte b0 = getAmplification(levels, primary, secondary); ++ ++ int j = getLevel(levels); ++ List list = getHumansInRange(level, pos, levels); ++ ++ applyEffect(list, primary, j, b0); ++ ++ if (hasSecondaryEffect(levels, primary, secondary)) { ++ applyEffect(list, secondary, j, 0); ++ } ++ } ++ ++ } ++ // CraftBukkit end ++ + public static void playSound(Level level, BlockPos pos, SoundEvent sound) { +- level.playSound(null, pos, sound, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.playSound((Player) null, pos, sound, SoundSource.BLOCKS, 1.0F, 1.0F); + } + + public List getBeamSections() { +- return (List)(this.levels == 0 ? ImmutableList.of() : this.beamSections); ++ return (List) (this.levels == 0 ? ImmutableList.of() : this.beamSections); + } + + @Override +@@ -274,20 +348,23 @@ + return this.saveWithoutMetadata(); + } + +- private static void storeEffect(CompoundTag compoundTag, String string, @Nullable MobEffect mobEffect) { +- if (mobEffect != null) { +- ResourceLocation key = BuiltInRegistries.MOB_EFFECT.getKey(mobEffect); +- if (key != null) { +- compoundTag.putString(string, key.toString()); ++ private static void storeEffect(CompoundTag nbttagcompound, String s, @Nullable MobEffect mobeffectlist) { ++ if (mobeffectlist != null) { ++ ResourceLocation minecraftkey = BuiltInRegistries.MOB_EFFECT.getKey(mobeffectlist); ++ ++ if (minecraftkey != null) { ++ nbttagcompound.putString(s, minecraftkey.toString()); + } + } ++ + } + + @Nullable +- private static MobEffect loadEffect(CompoundTag compoundTag, String string) { +- if (compoundTag.contains(string, 8)) { +- ResourceLocation resourceLocation = ResourceLocation.tryParse(compoundTag.getString(string)); +- return filterEffect(BuiltInRegistries.MOB_EFFECT.get(resourceLocation)); ++ private static MobEffect loadEffect(CompoundTag nbttagcompound, String s) { ++ if (nbttagcompound.contains(s, 8)) { ++ ResourceLocation minecraftkey = ResourceLocation.tryParse(nbttagcompound.getString(s)); ++ ++ return (MobEffect) BuiltInRegistries.MOB_EFFECT.get(minecraftkey); // CraftBukkit - persist manually set non-default beacon effects (SPIGOT-3598) + } else { + return null; + } +@@ -298,6 +375,7 @@ + super.load(tag); + this.primaryPower = loadEffect(tag, "primary_effect"); + this.secondaryPower = loadEffect(tag, "secondary_effect"); ++ this.levels = tag.getInt("Levels"); // CraftBukkit - SPIGOT-5053, use where available + if (tag.contains("CustomName", 8)) { + this.name = Component.Serializer.fromJson(tag.getString("CustomName")); + } +@@ -331,9 +409,7 @@ + @Nullable + @Override + public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { +- return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName()) +- ? new BeaconMenu(containerId, playerInventory, this.dataAccess, ContainerLevelAccess.create(this.level, this.getBlockPos())) +- : null; ++ return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName()) ? new BeaconMenu(containerId, playerInventory, this.dataAccess, ContainerLevelAccess.create(this.level, this.getBlockPos())) : null; + } + + @Override +@@ -343,7 +419,7 @@ + + @Override + public Component getName() { +- return this.name != null ? this.name : DEFAULT_NAME; ++ return this.name != null ? this.name : BeaconBlockEntity.DEFAULT_NAME; + } + + @Override +@@ -353,6 +429,7 @@ + } + + public static class BeaconBeamSection { ++ + final float[] color; + private int height; + +@@ -362,7 +439,7 @@ + } + + protected void increaseHeight() { +- this.height++; ++ ++this.height; + } + + public float[] getColor() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java.patch new file mode 100644 index 0000000000..5f75d49033 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java.patch @@ -0,0 +1,543 @@ +--- a/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java +@@ -24,62 +24,35 @@ + import net.minecraft.world.level.block.BeehiveBlock; + import net.minecraft.world.level.block.CampfireBlock; + import net.minecraft.world.level.block.FireBlock; +-import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + + public class BeehiveBlockEntity extends BlockEntity { ++ + public static final String TAG_FLOWER_POS = "FlowerPos"; + public static final String MIN_OCCUPATION_TICKS = "MinOccupationTicks"; + public static final String ENTITY_DATA = "EntityData"; + public static final String TICKS_IN_HIVE = "TicksInHive"; + public static final String HAS_NECTAR = "HasNectar"; + public static final String BEES = "Bees"; +- private static final List IGNORED_BEE_TAGS = Arrays.asList( +- "Air", +- "ArmorDropChances", +- "ArmorItems", +- "Brain", +- "CanPickUpLoot", +- "DeathTime", +- "FallDistance", +- "FallFlying", +- "Fire", +- "HandDropChances", +- "HandItems", +- "HurtByTimestamp", +- "HurtTime", +- "LeftHanded", +- "Motion", +- "NoGravity", +- "OnGround", +- "PortalCooldown", +- "Pos", +- "Rotation", +- "CannotEnterHiveTicks", +- "TicksSincePollination", +- "CropsGrownSincePollination", +- "HivePos", +- "Passengers", +- "Leash", +- "UUID" +- ); ++ private static final List IGNORED_BEE_TAGS = Arrays.asList("Air", "ArmorDropChances", "ArmorItems", "Brain", "CanPickUpLoot", "DeathTime", "FallDistance", "FallFlying", "Fire", "HandDropChances", "HandItems", "HurtByTimestamp", "HurtTime", "LeftHanded", "Motion", "NoGravity", "OnGround", "PortalCooldown", "Pos", "Rotation", "CannotEnterHiveTicks", "TicksSincePollination", "CropsGrownSincePollination", "HivePos", "Passengers", "Leash", "UUID"); + public static final int MAX_OCCUPANTS = 3; + private static final int MIN_TICKS_BEFORE_REENTERING_HIVE = 400; + private static final int MIN_OCCUPATION_TICKS_NECTAR = 2400; + public static final int MIN_OCCUPATION_TICKS_NECTARLESS = 600; + private final List stored = Lists.newArrayList(); + @Nullable +- private BlockPos savedFlowerPos; ++ public BlockPos savedFlowerPos; ++ public int maxBees = 3; // CraftBukkit - allow setting max amount of bees a hive can hold + +- public BeehiveBlockEntity(BlockPos pos, BlockState blockState) { ++ public BeehiveBlockEntity(BlockPos pos, IBlockData blockState) { + super(BlockEntityType.BEEHIVE, pos, blockState); + } + + @Override + public void setChanged() { + if (this.isFireNearby()) { +- this.emptyAllLivingFromHive(null, this.level.getBlockState(this.getBlockPos()), BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY); ++ this.emptyAllLivingFromHive((Player) null, this.level.getBlockState(this.getBlockPos()), BeehiveBlockEntity.ReleaseStatus.EMERGENCY); + } + + super.setChanged(); +@@ -89,13 +62,19 @@ + if (this.level == null) { + return false; + } else { +- for (BlockPos blockPos : BlockPos.betweenClosed(this.worldPosition.offset(-1, -1, -1), this.worldPosition.offset(1, 1, 1))) { +- if (this.level.getBlockState(blockPos).getBlock() instanceof FireBlock) { +- return true; ++ Iterator iterator = BlockPos.betweenClosed(this.worldPosition.offset(-1, -1, -1), this.worldPosition.offset(1, 1, 1)).iterator(); ++ ++ BlockPos blockposition; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return false; + } +- } + +- return false; ++ blockposition = (BlockPos) iterator.next(); ++ } while (!(this.level.getBlockState(blockposition).getBlock() instanceof FireBlock)); ++ ++ return true; + } + } + +@@ -104,30 +83,46 @@ + } + + public boolean isFull() { +- return this.stored.size() == 3; ++ return this.stored.size() == this.maxBees; // CraftBukkit + } + +- public void emptyAllLivingFromHive(@Nullable Player player, BlockState state, BeehiveBlockEntity.BeeReleaseStatus releaseStatus) { ++ public void emptyAllLivingFromHive(@Nullable Player player, IBlockData state, BeehiveBlockEntity.ReleaseStatus releaseStatus) { + List list = this.releaseAllOccupants(state, releaseStatus); ++ + if (player != null) { +- for (Entity entity : list) { ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ + if (entity instanceof Bee) { +- Bee bee = (Bee)entity; +- if (player.position().distanceToSqr(entity.position()) <= 16.0) { ++ Bee entitybee = (Bee) entity; ++ ++ if (player.position().distanceToSqr(entity.position()) <= 16.0D) { + if (!this.isSedated()) { +- bee.setTarget(player); ++ entitybee.setTarget(player, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit + } else { +- bee.setStayOutOfHiveCountdown(400); ++ entitybee.setStayOutOfHiveCountdown(400); + } + } + } + } + } ++ + } + +- private List releaseAllOccupants(BlockState state, BeehiveBlockEntity.BeeReleaseStatus releaseStatus) { ++ private List releaseAllOccupants(IBlockData state, BeehiveBlockEntity.ReleaseStatus releaseStatus) { ++ // CraftBukkit start - This allows us to bypass the night/rain/emergency check ++ return releaseBees(state, releaseStatus, false); ++ } ++ ++ public List releaseBees(IBlockData iblockdata, BeehiveBlockEntity.ReleaseStatus tileentitybeehive_releasestatus, boolean force) { + List list = Lists.newArrayList(); +- this.stored.removeIf(data -> releaseOccupant(this.level, this.worldPosition, state, data, list, releaseStatus, this.savedFlowerPos)); ++ ++ this.stored.removeIf((tileentitybeehive_hivebee) -> { ++ return releaseBee(this.level, this.worldPosition, iblockdata, tileentitybeehive_hivebee, list, tileentitybeehive_releasestatus, this.savedFlowerPos, force); ++ // CraftBukkit end ++ }); + if (!list.isEmpty()) { + super.setChanged(); + } +@@ -144,8 +139,8 @@ + return this.stored.size(); + } + +- public static int getHoneyLevel(BlockState state) { +- return state.getValue(BeehiveBlock.HONEY_LEVEL); ++ public static int getHoneyLevel(IBlockData state) { ++ return (Integer) state.getValue(BeehiveBlock.HONEY_LEVEL); + } + + @VisibleForDebug +@@ -154,30 +149,38 @@ + } + + public void addOccupantWithPresetTicks(Entity occupant, boolean hasNectar, int ticksInHive) { +- if (this.stored.size() < 3) { ++ if (this.stored.size() < this.maxBees) { // CraftBukkit ++ // CraftBukkit start ++ if (this.level != null) { ++ org.bukkit.event.entity.EntityEnterBlockEvent event = new org.bukkit.event.entity.EntityEnterBlockEvent(occupant.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, getBlockPos())); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ if (occupant instanceof Bee) { ++ ((Bee) occupant).setStayOutOfHiveCountdown(400); ++ } ++ return; ++ } ++ } ++ // CraftBukkit end + occupant.stopRiding(); + occupant.ejectPassengers(); +- CompoundTag compoundTag = new CompoundTag(); +- occupant.save(compoundTag); +- this.storeBee(compoundTag, ticksInHive, hasNectar); ++ CompoundTag nbttagcompound = new CompoundTag(); ++ ++ occupant.save(nbttagcompound); ++ this.storeBee(nbttagcompound, ticksInHive, hasNectar); + if (this.level != null) { +- if (occupant instanceof Bee bee && bee.hasSavedFlowerPos() && (!this.hasSavedFlowerPos() || this.level.random.nextBoolean())) { +- this.savedFlowerPos = bee.getSavedFlowerPos(); ++ if (occupant instanceof Bee) { ++ Bee entitybee = (Bee) occupant; ++ ++ if (entitybee.hasSavedFlowerPos() && (!this.hasSavedFlowerPos() || this.level.random.nextBoolean())) { ++ this.savedFlowerPos = entitybee.getSavedFlowerPos(); ++ } + } + +- BlockPos blockPos = this.getBlockPos(); +- this.level +- .playSound( +- null, +- (double)blockPos.getX(), +- (double)blockPos.getY(), +- (double)blockPos.getZ(), +- SoundEvents.BEEHIVE_ENTER, +- SoundSource.BLOCKS, +- 1.0F, +- 1.0F +- ); +- this.level.gameEvent(GameEvent.BLOCK_CHANGE, blockPos, GameEvent.Context.of(occupant, this.getBlockState())); ++ BlockPos blockposition = this.getBlockPos(); ++ ++ this.level.playSound((Player) null, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), SoundEvents.BEEHIVE_ENTER, SoundSource.BLOCKS, 1.0F, 1.0F); ++ this.level.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(occupant, this.getBlockState())); + } + + occupant.discard(); +@@ -189,69 +192,93 @@ + this.stored.add(new BeehiveBlockEntity.BeeData(entityData, ticksInHive, hasNectar ? 2400 : 600)); + } + +- private static boolean releaseOccupant( +- Level level, +- BlockPos pos, +- BlockState state, +- BeehiveBlockEntity.BeeData data, +- @Nullable List storedInHives, +- BeehiveBlockEntity.BeeReleaseStatus releaseStatus, +- @Nullable BlockPos savedFlowerPos +- ) { +- if ((level.isNight() || level.isRaining()) && releaseStatus != BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY) { ++ private static boolean releaseOccupant(Level level, BlockPos pos, IBlockData state, BeehiveBlockEntity.BeeData data, @Nullable List storedInHives, BeehiveBlockEntity.ReleaseStatus releaseStatus, @Nullable BlockPos savedFlowerPos) { ++ // CraftBukkit start - This allows us to bypass the night/rain/emergency check ++ return releaseBee(level, pos, state, data, storedInHives, releaseStatus, savedFlowerPos, false); ++ } ++ ++ private static boolean releaseBee(Level world, BlockPos blockposition, IBlockData iblockdata, BeehiveBlockEntity.BeeData tileentitybeehive_hivebee, @Nullable List list, BeehiveBlockEntity.ReleaseStatus tileentitybeehive_releasestatus, @Nullable BlockPos blockposition1, boolean force) { ++ if (!force && (world.isNight() || world.isRaining()) && tileentitybeehive_releasestatus != BeehiveBlockEntity.ReleaseStatus.EMERGENCY) { ++ // CraftBukkit end + return false; + } else { +- CompoundTag compoundTag = data.entityData.copy(); +- removeIgnoredBeeTags(compoundTag); +- compoundTag.put("HivePos", NbtUtils.writeBlockPos(pos)); +- compoundTag.putBoolean("NoGravity", true); +- Direction direction = state.getValue(BeehiveBlock.FACING); +- BlockPos blockPos = pos.relative(direction); +- boolean flag = !level.getBlockState(blockPos).getCollisionShape(level, blockPos).isEmpty(); +- if (flag && releaseStatus != BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY) { ++ CompoundTag nbttagcompound = tileentitybeehive_hivebee.entityData.copy(); ++ ++ removeIgnoredBeeTags(nbttagcompound); ++ nbttagcompound.put("HivePos", NbtUtils.writeBlockPos(blockposition)); ++ nbttagcompound.putBoolean("NoGravity", true); ++ Direction enumdirection = (Direction) iblockdata.getValue(BeehiveBlock.FACING); ++ BlockPos blockposition2 = blockposition.relative(enumdirection); ++ boolean flag = !world.getBlockState(blockposition2).getCollisionShape(world, blockposition2).isEmpty(); ++ ++ if (flag && tileentitybeehive_releasestatus != BeehiveBlockEntity.ReleaseStatus.EMERGENCY) { + return false; + } else { +- Entity entity = EntityType.loadEntityRecursive(compoundTag, level, entity1 -> entity1); ++ Entity entity = EntityType.loadEntityRecursive(nbttagcompound, world, (entity1) -> { ++ return entity1; ++ }); ++ + if (entity != null) { + if (!entity.getType().is(EntityTypeTags.BEEHIVE_INHABITORS)) { + return false; + } else { +- if (entity instanceof Bee bee) { +- if (savedFlowerPos != null && !bee.hasSavedFlowerPos() && level.random.nextFloat() < 0.9F) { +- bee.setSavedFlowerPos(savedFlowerPos); ++ // CraftBukkit start ++ if (entity instanceof Bee) { ++ float f = entity.getBbWidth(); ++ double d0 = flag ? 0.0D : 0.55D + (double) (f / 2.0F); ++ double d1 = (double) blockposition.getX() + 0.5D + d0 * (double) enumdirection.getStepX(); ++ double d2 = (double) blockposition.getY() + 0.5D - (double) (entity.getBbHeight() / 2.0F); ++ double d3 = (double) blockposition.getZ() + 0.5D + d0 * (double) enumdirection.getStepZ(); ++ ++ entity.moveTo(d1, d2, d3, entity.getYRot(), entity.getXRot()); ++ } ++ if (!world.addFreshEntity(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BEEHIVE)) return false; // CraftBukkit - SpawnReason, moved from below ++ // CraftBukkit end ++ if (entity instanceof Bee) { ++ Bee entitybee = (Bee) entity; ++ ++ if (blockposition1 != null && !entitybee.hasSavedFlowerPos() && world.random.nextFloat() < 0.9F) { ++ entitybee.setSavedFlowerPos(blockposition1); + } + +- if (releaseStatus == BeehiveBlockEntity.BeeReleaseStatus.HONEY_DELIVERED) { +- bee.dropOffNectar(); +- if (state.is(BlockTags.BEEHIVES, hiveState -> hiveState.hasProperty(BeehiveBlock.HONEY_LEVEL))) { +- int honeyLevel = getHoneyLevel(state); +- if (honeyLevel < 5) { +- int i = level.random.nextInt(100) == 0 ? 2 : 1; +- if (honeyLevel + i > 5) { +- i--; ++ if (tileentitybeehive_releasestatus == BeehiveBlockEntity.ReleaseStatus.HONEY_DELIVERED) { ++ entitybee.dropOffNectar(); ++ if (iblockdata.is(BlockTags.BEEHIVES, (blockbase_blockdata) -> { ++ return blockbase_blockdata.hasProperty(BeehiveBlock.HONEY_LEVEL); ++ })) { ++ int i = getHoneyLevel(iblockdata); ++ ++ if (i < 5) { ++ int j = world.random.nextInt(100) == 0 ? 2 : 1; ++ ++ if (i + j > 5) { ++ --j; + } + +- level.setBlockAndUpdate(pos, state.setValue(BeehiveBlock.HONEY_LEVEL, Integer.valueOf(honeyLevel + i))); ++ world.setBlockAndUpdate(blockposition, (IBlockData) iblockdata.setValue(BeehiveBlock.HONEY_LEVEL, i + j)); + } + } + } + +- setBeeReleaseData(data.ticksInHive, bee); +- if (storedInHives != null) { +- storedInHives.add(bee); ++ setBeeReleaseData(tileentitybeehive_hivebee.ticksInHive, entitybee); ++ if (list != null) { ++ list.add(entitybee); + } + +- float bbWidth = entity.getBbWidth(); +- double d = flag ? 0.0 : 0.55 + (double)(bbWidth / 2.0F); +- double d1 = (double)pos.getX() + 0.5 + d * (double)direction.getStepX(); +- double d2 = (double)pos.getY() + 0.5 - (double)(entity.getBbHeight() / 2.0F); +- double d3 = (double)pos.getZ() + 0.5 + d * (double)direction.getStepZ(); ++ /* // CraftBukkit start ++ float f = entity.getBbWidth(); ++ double d0 = flag ? 0.0D : 0.55D + (double) (f / 2.0F); ++ double d1 = (double) blockposition.getX() + 0.5D + d0 * (double) enumdirection.getStepX(); ++ double d2 = (double) blockposition.getY() + 0.5D - (double) (entity.getBbHeight() / 2.0F); ++ double d3 = (double) blockposition.getZ() + 0.5D + d0 * (double) enumdirection.getStepZ(); ++ + entity.moveTo(d1, d2, d3, entity.getYRot(), entity.getXRot()); ++ */ // CraftBukkit end + } + +- level.playSound(null, pos, SoundEvents.BEEHIVE_EXIT, SoundSource.BLOCKS, 1.0F, 1.0F); +- level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, level.getBlockState(pos))); +- return level.addFreshEntity(entity); ++ world.playSound((Player) null, blockposition, SoundEvents.BEEHIVE_EXIT, SoundSource.BLOCKS, 1.0F, 1.0F); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entity, world.getBlockState(blockposition))); ++ return true; // return this.world.addFreshEntity(entity); // CraftBukkit - moved up + } + } else { + return false; +@@ -261,17 +288,23 @@ + } + + static void removeIgnoredBeeTags(CompoundTag tag) { +- for (String string : IGNORED_BEE_TAGS) { +- tag.remove(string); ++ Iterator iterator = BeehiveBlockEntity.IGNORED_BEE_TAGS.iterator(); ++ ++ while (iterator.hasNext()) { ++ String s = (String) iterator.next(); ++ ++ tag.remove(s); + } ++ + } + + private static void setBeeReleaseData(int timeInHive, Bee bee) { +- int age = bee.getAge(); +- if (age < 0) { +- bee.setAge(Math.min(0, age + timeInHive)); +- } else if (age > 0) { +- bee.setAge(Math.max(0, age - timeInHive)); ++ int j = bee.getAge(); ++ ++ if (j < 0) { ++ bee.setAge(Math.min(0, j + timeInHive)); ++ } else if (j > 0) { ++ bee.setAge(Math.max(0, j - timeInHive)); + } + + bee.setInLoveTime(Math.max(0, bee.getInLoveTime() - timeInHive)); +@@ -281,37 +314,41 @@ + return this.savedFlowerPos != null; + } + +- private static void tickOccupants(Level level, BlockPos pos, BlockState state, List data, @Nullable BlockPos savedFlowerPos) { ++ private static void tickOccupants(Level level, BlockPos pos, IBlockData state, List data, @Nullable BlockPos savedFlowerPos) { + boolean flag = false; +- Iterator iterator = data.iterator(); + +- while (iterator.hasNext()) { +- BeehiveBlockEntity.BeeData beeData = iterator.next(); +- if (beeData.ticksInHive > beeData.minOccupationTicks) { +- BeehiveBlockEntity.BeeReleaseStatus beeReleaseStatus = beeData.entityData.getBoolean("HasNectar") +- ? BeehiveBlockEntity.BeeReleaseStatus.HONEY_DELIVERED +- : BeehiveBlockEntity.BeeReleaseStatus.BEE_RELEASED; +- if (releaseOccupant(level, pos, state, beeData, null, beeReleaseStatus, savedFlowerPos)) { ++ BeehiveBlockEntity.BeeData tileentitybeehive_hivebee; ++ ++ for (Iterator iterator = data.iterator(); iterator.hasNext(); ++tileentitybeehive_hivebee.ticksInHive) { ++ tileentitybeehive_hivebee = (BeehiveBlockEntity.BeeData) iterator.next(); ++ if (tileentitybeehive_hivebee.ticksInHive > tileentitybeehive_hivebee.minOccupationTicks) { ++ BeehiveBlockEntity.ReleaseStatus tileentitybeehive_releasestatus = tileentitybeehive_hivebee.entityData.getBoolean("HasNectar") ? BeehiveBlockEntity.ReleaseStatus.HONEY_DELIVERED : BeehiveBlockEntity.ReleaseStatus.BEE_RELEASED; ++ ++ if (releaseOccupant(level, pos, state, tileentitybeehive_hivebee, (List) null, tileentitybeehive_releasestatus, savedFlowerPos)) { + flag = true; + iterator.remove(); ++ // CraftBukkit start ++ } else { ++ tileentitybeehive_hivebee.ticksInHive = tileentitybeehive_hivebee.minOccupationTicks / 2; // Not strictly Vanilla behaviour in cases where bees cannot spawn but still reasonable ++ // CraftBukkit end + } + } +- +- beeData.ticksInHive++; + } + + if (flag) { + setChanged(level, pos, state); + } ++ + } + +- public static void serverTick(Level level, BlockPos pos, BlockState state, BeehiveBlockEntity beehive) { ++ public static void serverTick(Level level, BlockPos pos, IBlockData state, BeehiveBlockEntity beehive) { + tickOccupants(level, pos, state, beehive.stored, beehive.savedFlowerPos); +- if (!beehive.stored.isEmpty() && level.getRandom().nextDouble() < 0.005) { +- double d = (double)pos.getX() + 0.5; +- double d1 = (double)pos.getY(); +- double d2 = (double)pos.getZ() + 0.5; +- level.playSound(null, d, d1, d2, SoundEvents.BEEHIVE_WORK, SoundSource.BLOCKS, 1.0F, 1.0F); ++ if (!beehive.stored.isEmpty() && level.getRandom().nextDouble() < 0.005D) { ++ double d0 = (double) pos.getX() + 0.5D; ++ double d1 = (double) pos.getY(); ++ double d2 = (double) pos.getZ() + 0.5D; ++ ++ level.playSound((Player) null, d0, d1, d2, SoundEvents.BEEHIVE_WORK, SoundSource.BLOCKS, 1.0F, 1.0F); + } + + DebugPackets.sendHiveInfo(level, pos, state, beehive); +@@ -321,20 +358,25 @@ + public void load(CompoundTag tag) { + super.load(tag); + this.stored.clear(); +- ListTag list = tag.getList("Bees", 10); ++ ListTag nbttaglist = tag.getList("Bees", 10); + +- for (int i = 0; i < list.size(); i++) { +- CompoundTag compound = list.getCompound(i); +- BeehiveBlockEntity.BeeData beeData = new BeehiveBlockEntity.BeeData( +- compound.getCompound("EntityData").copy(), compound.getInt("TicksInHive"), compound.getInt("MinOccupationTicks") +- ); +- this.stored.add(beeData); ++ for (int i = 0; i < nbttaglist.size(); ++i) { ++ CompoundTag nbttagcompound1 = nbttaglist.getCompound(i); ++ BeehiveBlockEntity.BeeData tileentitybeehive_hivebee = new BeehiveBlockEntity.BeeData(nbttagcompound1.getCompound("EntityData").copy(), nbttagcompound1.getInt("TicksInHive"), nbttagcompound1.getInt("MinOccupationTicks")); ++ ++ this.stored.add(tileentitybeehive_hivebee); + } + + this.savedFlowerPos = null; + if (tag.contains("FlowerPos")) { + this.savedFlowerPos = NbtUtils.readBlockPos(tag.getCompound("FlowerPos")); + } ++ ++ // CraftBukkit start ++ if (tag.contains("Bukkit.MaxEntities")) { ++ this.maxBees = tag.getInt("Bukkit.MaxEntities"); ++ } ++ // CraftBukkit end + } + + @Override +@@ -344,25 +386,39 @@ + if (this.hasSavedFlowerPos()) { + tag.put("FlowerPos", NbtUtils.writeBlockPos(this.savedFlowerPos)); + } ++ tag.putInt("Bukkit.MaxEntities", this.maxBees); // CraftBukkit ++ + } + + public ListTag writeBees() { +- ListTag list = new ListTag(); ++ ListTag nbttaglist = new ListTag(); ++ Iterator iterator = this.stored.iterator(); + +- for (BeehiveBlockEntity.BeeData beeData : this.stored) { +- CompoundTag compoundTag = beeData.entityData.copy(); +- compoundTag.remove("UUID"); +- CompoundTag compoundTag1 = new CompoundTag(); +- compoundTag1.put("EntityData", compoundTag); +- compoundTag1.putInt("TicksInHive", beeData.ticksInHive); +- compoundTag1.putInt("MinOccupationTicks", beeData.minOccupationTicks); +- list.add(compoundTag1); ++ while (iterator.hasNext()) { ++ BeehiveBlockEntity.BeeData tileentitybeehive_hivebee = (BeehiveBlockEntity.BeeData) iterator.next(); ++ CompoundTag nbttagcompound = tileentitybeehive_hivebee.entityData.copy(); ++ ++ nbttagcompound.remove("UUID"); ++ CompoundTag nbttagcompound1 = new CompoundTag(); ++ ++ nbttagcompound1.put("EntityData", nbttagcompound); ++ nbttagcompound1.putInt("TicksInHive", tileentitybeehive_hivebee.ticksInHive); ++ nbttagcompound1.putInt("MinOccupationTicks", tileentitybeehive_hivebee.minOccupationTicks); ++ nbttaglist.add(nbttagcompound1); + } + +- return list; ++ return nbttaglist; + } + +- static class BeeData { ++ public static enum ReleaseStatus { ++ ++ HONEY_DELIVERED, BEE_RELEASED, EMERGENCY; ++ ++ private ReleaseStatus() {} ++ } ++ ++ private static class BeeData { ++ + final CompoundTag entityData; + int ticksInHive; + final int minOccupationTicks; +@@ -374,10 +430,4 @@ + this.minOccupationTicks = minOccupationTicks; + } + } +- +- public static enum BeeReleaseStatus { +- HONEY_DELIVERED, +- BEE_RELEASED, +- EMERGENCY; +- } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BellBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BellBlockEntity.java.patch new file mode 100644 index 0000000000..e8f008af9e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BellBlockEntity.java.patch @@ -0,0 +1,228 @@ +--- a/net/minecraft/world/level/block/entity/BellBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BellBlockEntity.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.level.block.entity; + ++import java.util.Iterator; + import java.util.List; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +@@ -13,12 +14,14 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.AABB; + import org.apache.commons.lang3.mutable.MutableInt; + + public class BellBlockEntity extends BlockEntity { ++ + private static final int DURATION = 50; + private static final int GLOW_DURATION = 60; + private static final int MIN_TICKS_BETWEEN_SEARCHES = 60; +@@ -32,10 +35,10 @@ + public boolean shaking; + public Direction clickDirection; + private List nearbyEntities; +- private boolean resonating; +- private int resonationTicks; ++ public boolean resonating; ++ public int resonationTicks; + +- public BellBlockEntity(BlockPos pos, BlockState blockState) { ++ public BellBlockEntity(BlockPos pos, IBlockData blockState) { + super(BlockEntityType.BELL, pos, blockState); + } + +@@ -53,9 +56,9 @@ + } + } + +- private static void tick(Level level, BlockPos pos, BlockState state, BellBlockEntity blockEntity, BellBlockEntity.ResonationEndAction resonationEndAction) { ++ private static void tick(Level level, BlockPos pos, IBlockData state, BellBlockEntity blockEntity, BellBlockEntity.ResonationEndAction resonationEndAction) { + if (blockEntity.shaking) { +- blockEntity.ticks++; ++ ++blockEntity.ticks; + } + + if (blockEntity.ticks >= 50) { +@@ -65,29 +68,31 @@ + + if (blockEntity.ticks >= 5 && blockEntity.resonationTicks == 0 && areRaidersNearby(pos, blockEntity.nearbyEntities)) { + blockEntity.resonating = true; +- level.playSound(null, pos, SoundEvents.BELL_RESONATE, SoundSource.BLOCKS, 1.0F, 1.0F); ++ level.playSound((Player) null, pos, SoundEvents.BELL_RESONATE, SoundSource.BLOCKS, 1.0F, 1.0F); + } + + if (blockEntity.resonating) { + if (blockEntity.resonationTicks < 40) { +- blockEntity.resonationTicks++; ++ ++blockEntity.resonationTicks; + } else { + resonationEndAction.run(level, pos, blockEntity.nearbyEntities); + blockEntity.resonating = false; + } + } ++ + } + +- public static void clientTick(Level level, BlockPos pos, BlockState state, BellBlockEntity blockEntity) { ++ public static void clientTick(Level level, BlockPos pos, IBlockData state, BellBlockEntity blockEntity) { + tick(level, pos, state, blockEntity, BellBlockEntity::showBellParticles); + } + +- public static void serverTick(Level level, BlockPos pos, BlockState state, BellBlockEntity blockEntity) { ++ public static void serverTick(Level level, BlockPos pos, IBlockData state, BellBlockEntity blockEntity) { + tick(level, pos, state, blockEntity, BellBlockEntity::makeRaidersGlow); + } + + public void onHit(Direction direction) { +- BlockPos blockPos = this.getBlockPos(); ++ BlockPos blockposition = this.getBlockPos(); ++ + this.clickDirection = direction; + if (this.shaking) { + this.ticks = 0; +@@ -95,72 +100,88 @@ + this.shaking = true; + } + +- this.level.blockEvent(blockPos, this.getBlockState().getBlock(), 1, direction.get3DDataValue()); ++ this.level.blockEvent(blockposition, this.getBlockState().getBlock(), 1, direction.get3DDataValue()); + } + + private void updateEntities() { +- BlockPos blockPos = this.getBlockPos(); ++ BlockPos blockposition = this.getBlockPos(); ++ + if (this.level.getGameTime() > this.lastRingTimestamp + 60L || this.nearbyEntities == null) { + this.lastRingTimestamp = this.level.getGameTime(); +- AABB aABB = new AABB(blockPos).inflate(48.0); +- this.nearbyEntities = this.level.getEntitiesOfClass(LivingEntity.class, aABB); ++ AABB axisalignedbb = (new AABB(blockposition)).inflate(48.0D); ++ ++ this.nearbyEntities = this.level.getEntitiesOfClass(LivingEntity.class, axisalignedbb); + } + + if (!this.level.isClientSide) { +- for (LivingEntity livingEntity : this.nearbyEntities) { +- if (livingEntity.isAlive() && !livingEntity.isRemoved() && blockPos.closerToCenterThan(livingEntity.position(), 32.0)) { +- livingEntity.getBrain().setMemory(MemoryModuleType.HEARD_BELL_TIME, this.level.getGameTime()); ++ Iterator iterator = this.nearbyEntities.iterator(); ++ ++ while (iterator.hasNext()) { ++ LivingEntity entityliving = (LivingEntity) iterator.next(); ++ ++ if (entityliving.isAlive() && !entityliving.isRemoved() && blockposition.closerToCenterThan(entityliving.position(), 32.0D)) { ++ entityliving.getBrain().setMemory(MemoryModuleType.HEARD_BELL_TIME, this.level.getGameTime()); // CraftBukkit - decompile error + } + } + } ++ + } + + private static boolean areRaidersNearby(BlockPos pos, List raiders) { +- for (LivingEntity livingEntity : raiders) { +- if (livingEntity.isAlive() +- && !livingEntity.isRemoved() +- && pos.closerToCenterThan(livingEntity.position(), 32.0) +- && livingEntity.getType().is(EntityTypeTags.RAIDERS)) { +- return true; ++ Iterator iterator = raiders.iterator(); ++ ++ LivingEntity entityliving; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return false; + } +- } + +- return false; ++ entityliving = (LivingEntity) iterator.next(); ++ } while (!entityliving.isAlive() || entityliving.isRemoved() || !pos.closerToCenterThan(entityliving.position(), 32.0D) || !entityliving.getType().is(EntityTypeTags.RAIDERS)); ++ ++ return true; + } + + private static void makeRaidersGlow(Level level, BlockPos pos, List raiders) { +- raiders.stream().filter(raider -> isRaiderWithinRange(pos, raider)).forEach(BellBlockEntity::glow); ++ List entities = // CraftBukkit ++ raiders.stream().filter((entityliving) -> { ++ return isRaiderWithinRange(pos, entityliving); ++ }).map((entity) -> (org.bukkit.entity.LivingEntity) entity.getBukkitEntity()).collect(java.util.stream.Collectors.toCollection(java.util.ArrayList::new)); // CraftBukkit ++ ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBellResonateEvent(level, pos, entities).forEach(BellBlockEntity::glow); ++ // CraftBukkit end + } + + private static void showBellParticles(Level level, BlockPos pos, List raiders) { +- MutableInt mutableInt = new MutableInt(16700985); +- int i = (int)raiders.stream().filter(raider -> pos.closerToCenterThan(raider.position(), 48.0)).count(); +- raiders.stream() +- .filter(raider -> isRaiderWithinRange(pos, raider)) +- .forEach( +- raider -> { +- float f = 1.0F; +- double squareRoot = Math.sqrt( +- (raider.getX() - (double)pos.getX()) * (raider.getX() - (double)pos.getX()) +- + (raider.getZ() - (double)pos.getZ()) * (raider.getZ() - (double)pos.getZ()) +- ); +- double d = (double)((float)pos.getX() + 0.5F) + 1.0 / squareRoot * (raider.getX() - (double)pos.getX()); +- double d1 = (double)((float)pos.getZ() + 0.5F) + 1.0 / squareRoot * (raider.getZ() - (double)pos.getZ()); +- int i1 = Mth.clamp((i - 21) / -2, 3, 15); +- +- for (int i2 = 0; i2 < i1; i2++) { +- int i3 = mutableInt.addAndGet(5); +- double d2 = (double)FastColor.ARGB32.red(i3) / 255.0; +- double d3 = (double)FastColor.ARGB32.green(i3) / 255.0; +- double d4 = (double)FastColor.ARGB32.blue(i3) / 255.0; +- level.addParticle(ParticleTypes.ENTITY_EFFECT, d, (double)((float)pos.getY() + 0.5F), d1, d2, d3, d4); +- } +- } +- ); ++ MutableInt mutableint = new MutableInt(16700985); ++ int i = (int) raiders.stream().filter((entityliving) -> { ++ return pos.closerToCenterThan(entityliving.position(), 48.0D); ++ }).count(); ++ ++ raiders.stream().filter((entityliving) -> { ++ return isRaiderWithinRange(pos, entityliving); ++ }).forEach((entityliving) -> { ++ float f = 1.0F; ++ double d0 = Math.sqrt((entityliving.getX() - (double) pos.getX()) * (entityliving.getX() - (double) pos.getX()) + (entityliving.getZ() - (double) pos.getZ()) * (entityliving.getZ() - (double) pos.getZ())); ++ double d1 = (double) ((float) pos.getX() + 0.5F) + 1.0D / d0 * (entityliving.getX() - (double) pos.getX()); ++ double d2 = (double) ((float) pos.getZ() + 0.5F) + 1.0D / d0 * (entityliving.getZ() - (double) pos.getZ()); ++ int j = Mth.clamp((i - 21) / -2, 3, 15); ++ ++ for (int k = 0; k < j; ++k) { ++ int l = mutableint.addAndGet(5); ++ double d3 = (double) FastColor.ARGB32.red(l) / 255.0D; ++ double d4 = (double) FastColor.ARGB32.green(l) / 255.0D; ++ double d5 = (double) FastColor.ARGB32.blue(l) / 255.0D; ++ ++ level.addParticle(ParticleTypes.ENTITY_EFFECT, d1, (double) ((float) pos.getY() + 0.5F), d2, d3, d4, d5); ++ } ++ ++ }); + } + + private static boolean isRaiderWithinRange(BlockPos pos, LivingEntity raider) { +- return raider.isAlive() && !raider.isRemoved() && pos.closerToCenterThan(raider.position(), 48.0) && raider.getType().is(EntityTypeTags.RAIDERS); ++ return raider.isAlive() && !raider.isRemoved() && pos.closerToCenterThan(raider.position(), 48.0D) && raider.getType().is(EntityTypeTags.RAIDERS); + } + + private static void glow(LivingEntity entity) { +@@ -168,7 +189,8 @@ + } + + @FunctionalInterface +- interface ResonationEndAction { ++ private interface ResonationEndAction { ++ + void run(Level level, BlockPos pos, List raiders); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BlockEntity.java.patch new file mode 100644 index 0000000000..54a3a659f0 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BlockEntity.java.patch @@ -0,0 +1,208 @@ +--- a/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -12,19 +12,30 @@ + import net.minecraft.world.item.BlockItem; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer; ++import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end ++ + public abstract class BlockEntity { ++ ++ // CraftBukkit start - data containers ++ private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); ++ public CraftPersistentDataContainer persistentDataContainer; ++ // CraftBukkit end + private static final Logger LOGGER = LogUtils.getLogger(); + private final BlockEntityType type; + @Nullable + protected Level level; + protected final BlockPos worldPosition; + protected boolean remove; +- private BlockState blockState; ++ private IBlockData blockState; + +- public BlockEntity(BlockEntityType type, BlockPos pos, BlockState blockState) { ++ public BlockEntity(BlockEntityType type, BlockPos pos, IBlockData blockState) { + this.type = type; + this.worldPosition = pos.immutable(); + this.blockState = blockState; +@@ -47,36 +58,52 @@ + return this.level != null; + } + ++ // CraftBukkit start - read container + public void load(CompoundTag tag) { +- } ++ this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); + +- protected void saveAdditional(CompoundTag tag) { ++ net.minecraft.nbt.Tag persistentDataTag = tag.get("PublicBukkitValues"); ++ if (persistentDataTag instanceof CompoundTag) { ++ this.persistentDataContainer.putAll((CompoundTag) persistentDataTag); ++ } + } ++ // CraftBukkit end + ++ protected void saveAdditional(CompoundTag tag) {} ++ + public final CompoundTag saveWithFullMetadata() { +- CompoundTag compoundTag = this.saveWithoutMetadata(); +- this.saveMetadata(compoundTag); +- return compoundTag; ++ CompoundTag nbttagcompound = this.saveWithoutMetadata(); ++ ++ this.saveMetadata(nbttagcompound); ++ return nbttagcompound; + } + + public final CompoundTag saveWithId() { +- CompoundTag compoundTag = this.saveWithoutMetadata(); +- this.saveId(compoundTag); +- return compoundTag; ++ CompoundTag nbttagcompound = this.saveWithoutMetadata(); ++ ++ this.saveId(nbttagcompound); ++ return nbttagcompound; + } + + public final CompoundTag saveWithoutMetadata() { +- CompoundTag compoundTag = new CompoundTag(); +- this.saveAdditional(compoundTag); +- return compoundTag; ++ CompoundTag nbttagcompound = new CompoundTag(); ++ ++ this.saveAdditional(nbttagcompound); ++ // CraftBukkit start - store container ++ if (this.persistentDataContainer != null && !this.persistentDataContainer.isEmpty()) { ++ nbttagcompound.put("PublicBukkitValues", this.persistentDataContainer.toTagCompound()); ++ } ++ // CraftBukkit end ++ return nbttagcompound; + } + + private void saveId(CompoundTag tag) { +- ResourceLocation key = BlockEntityType.getKey(this.getType()); +- if (key == null) { ++ ResourceLocation minecraftkey = BlockEntityType.getKey(this.getType()); ++ ++ if (minecraftkey == null) { + throw new RuntimeException(this.getClass() + " is missing a mapping! This is a bug!"); + } else { +- tag.putString("id", key.toString()); ++ tag.putString("id", minecraftkey.toString()); + } + } + +@@ -96,30 +123,31 @@ + } + + @Nullable +- public static BlockEntity loadStatic(BlockPos pos, BlockState state, CompoundTag tag) { +- String string = tag.getString("id"); +- ResourceLocation resourceLocation = ResourceLocation.tryParse(string); +- if (resourceLocation == null) { +- LOGGER.error("Block entity has invalid type: {}", string); ++ public static BlockEntity loadStatic(BlockPos pos, IBlockData state, CompoundTag tag) { ++ String s = tag.getString("id"); ++ ResourceLocation minecraftkey = ResourceLocation.tryParse(s); ++ ++ if (minecraftkey == null) { ++ BlockEntity.LOGGER.error("Block entity has invalid type: {}", s); + return null; + } else { +- return BuiltInRegistries.BLOCK_ENTITY_TYPE.getOptional(resourceLocation).map(type -> { ++ return (BlockEntity) BuiltInRegistries.BLOCK_ENTITY_TYPE.getOptional(minecraftkey).map((tileentitytypes) -> { + try { +- return type.create(pos, state); +- } catch (Throwable var5) { +- LOGGER.error("Failed to create block entity {}", string, var5); ++ return tileentitytypes.create(pos, state); ++ } catch (Throwable throwable) { ++ BlockEntity.LOGGER.error("Failed to create block entity {}", s, throwable); + return null; + } +- }).map(blockEntity -> { ++ }).map((tileentity) -> { + try { +- blockEntity.load(tag); +- return (BlockEntity)blockEntity; +- } catch (Throwable var4x) { +- LOGGER.error("Failed to load data for block entity {}", string, var4x); ++ tileentity.load(tag); ++ return tileentity; ++ } catch (Throwable throwable) { ++ BlockEntity.LOGGER.error("Failed to load data for block entity {}", s, throwable); + return null; + } + }).orElseGet(() -> { +- LOGGER.warn("Skipping BlockEntity with id {}", string); ++ BlockEntity.LOGGER.warn("Skipping BlockEntity with id {}", s); + return null; + }); + } +@@ -129,20 +157,22 @@ + if (this.level != null) { + setChanged(this.level, this.worldPosition, this.blockState); + } ++ + } + +- protected static void setChanged(Level level, BlockPos pos, BlockState state) { ++ protected static void setChanged(Level level, BlockPos pos, IBlockData state) { + level.blockEntityChanged(pos); + if (!state.isAir()) { + level.updateNeighbourForOutputSignal(pos, state.getBlock()); + } ++ + } + + public BlockPos getBlockPos() { + return this.worldPosition; + } + +- public BlockState getBlockState() { ++ public IBlockData getBlockState() { + return this.blockState; + } + +@@ -172,7 +202,11 @@ + } + + public void fillCrashReportCategory(CrashReportCategory reportCategory) { +- reportCategory.setDetail("Name", () -> BuiltInRegistries.BLOCK_ENTITY_TYPE.getKey(this.getType()) + " // " + this.getClass().getCanonicalName()); ++ reportCategory.setDetail("Name", () -> { ++ ResourceLocation minecraftkey = BuiltInRegistries.BLOCK_ENTITY_TYPE.getKey(this.getType()); ++ ++ return minecraftkey + " // " + this.getClass().getCanonicalName(); ++ }); + if (this.level != null) { + CrashReportCategory.populateBlockDetails(reportCategory, this.level, this.worldPosition, this.getBlockState()); + CrashReportCategory.populateBlockDetails(reportCategory, this.level, this.worldPosition, this.level.getBlockState(this.worldPosition)); +@@ -187,8 +221,18 @@ + return this.type; + } + ++ /** @deprecated */ + @Deprecated +- public void setBlockState(BlockState blockState) { ++ public void setBlockState(IBlockData blockState) { + this.blockState = blockState; + } ++ ++ // CraftBukkit start - add method ++ public InventoryHolder getOwner() { ++ if (level == null) return null; ++ org.bukkit.block.BlockState state = level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()).getState(); ++ if (state instanceof InventoryHolder) return (InventoryHolder) state; ++ return null; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java.patch new file mode 100644 index 0000000000..6d534a0d16 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java.patch @@ -0,0 +1,423 @@ +--- a/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.block.entity; + + import java.util.Arrays; ++import java.util.Iterator; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +@@ -22,9 +23,24 @@ + import net.minecraft.world.item.alchemy.PotionBrewing; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.BrewingStandBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.event.block.BrewingStartEvent; ++import org.bukkit.event.inventory.BrewEvent; ++import org.bukkit.event.inventory.BrewingStandFuelEvent; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end ++ + public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements WorldlyContainer { ++ + private static final int INGREDIENT_SLOT = 3; + private static final int FUEL_SLOT = 4; + private static final int[] SLOTS_FOR_UP = new int[]{3}; +@@ -34,43 +50,76 @@ + public static final int DATA_BREW_TIME = 0; + public static final int DATA_FUEL_USES = 1; + public static final int NUM_DATA_VALUES = 2; +- private NonNullList items = NonNullList.withSize(5, ItemStack.EMPTY); +- int brewTime; ++ private NonNullList items; ++ public int brewTime; + private boolean[] lastPotionCount; + private Item ingredient; +- int fuel; +- protected final ContainerData dataAccess = new ContainerData() { +- @Override +- public int get(int index) { +- switch (index) { +- case 0: +- return BrewingStandBlockEntity.this.brewTime; +- case 1: +- return BrewingStandBlockEntity.this.fuel; +- default: +- return 0; +- } +- } ++ public int fuel; ++ protected final ContainerData dataAccess; ++ // CraftBukkit start - add fields and methods ++ private int lastTick = MinecraftServer.currentTick; ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = 64; + +- @Override +- public void set(int index, int value) { +- switch (index) { +- case 0: +- BrewingStandBlockEntity.this.brewTime = value; +- break; +- case 1: +- BrewingStandBlockEntity.this.fuel = value; +- } +- } ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } + +- @Override +- public int getCount() { +- return 2; +- } +- }; ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } + +- public BrewingStandBlockEntity(BlockPos pos, BlockState state) { ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ ++ public BrewingStandBlockEntity(BlockPos pos, IBlockData state) { + super(BlockEntityType.BREWING_STAND, pos, state); ++ this.items = NonNullList.withSize(5, ItemStack.EMPTY); ++ this.dataAccess = new ContainerData() { ++ @Override ++ public int get(int index) { ++ switch (index) { ++ case 0: ++ return BrewingStandBlockEntity.this.brewTime; ++ case 1: ++ return BrewingStandBlockEntity.this.fuel; ++ default: ++ return 0; ++ } ++ } ++ ++ @Override ++ public void set(int index, int value) { ++ switch (index) { ++ case 0: ++ BrewingStandBlockEntity.this.brewTime = value; ++ break; ++ case 1: ++ BrewingStandBlockEntity.this.fuel = value; ++ } ++ ++ } ++ ++ @Override ++ public int getCount() { ++ return 2; ++ } ++ }; + } + + @Override +@@ -85,81 +134,115 @@ + + @Override + public boolean isEmpty() { +- for (ItemStack itemStack : this.items) { +- if (!itemStack.isEmpty()) { +- return false; ++ Iterator iterator = this.items.iterator(); ++ ++ ItemStack itemstack; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return true; + } +- } + +- return true; ++ itemstack = (ItemStack) iterator.next(); ++ } while (itemstack.isEmpty()); ++ ++ return false; + } + +- public static void serverTick(Level level, BlockPos pos, BlockState state, BrewingStandBlockEntity blockEntity) { +- ItemStack itemStack = blockEntity.items.get(4); +- if (blockEntity.fuel <= 0 && itemStack.is(Items.BLAZE_POWDER)) { +- blockEntity.fuel = 20; +- itemStack.shrink(1); ++ public static void serverTick(Level level, BlockPos pos, IBlockData state, BrewingStandBlockEntity blockEntity) { ++ ItemStack itemstack = (ItemStack) blockEntity.items.get(4); ++ ++ if (blockEntity.fuel <= 0 && itemstack.is(Items.BLAZE_POWDER)) { ++ // CraftBukkit start ++ BrewingStandFuelEvent event = new BrewingStandFuelEvent(CraftBlock.at(level, pos), CraftItemStack.asCraftMirror(itemstack), 20); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ blockEntity.fuel = event.getFuelPower(); ++ if (blockEntity.fuel > 0 && event.isConsuming()) { ++ itemstack.shrink(1); ++ } ++ // CraftBukkit end + setChanged(level, pos, state); + } + +- boolean isBrewable = isBrewable(blockEntity.items); +- boolean flag = blockEntity.brewTime > 0; +- ItemStack itemStack1 = blockEntity.items.get(3); +- if (flag) { +- blockEntity.brewTime--; +- boolean flag1 = blockEntity.brewTime == 0; +- if (flag1 && isBrewable) { +- doBrew(level, pos, blockEntity.items); ++ boolean flag = isBrewable(blockEntity.items); ++ boolean flag1 = blockEntity.brewTime > 0; ++ ItemStack itemstack1 = (ItemStack) blockEntity.items.get(3); ++ ++ // CraftBukkit start - Use wall time instead of ticks for brewing ++ int elapsedTicks = MinecraftServer.currentTick - blockEntity.lastTick; ++ blockEntity.lastTick = MinecraftServer.currentTick; ++ ++ if (flag1) { ++ blockEntity.brewTime -= elapsedTicks; ++ boolean flag2 = blockEntity.brewTime <= 0; // == -> <= ++ // CraftBukkit end ++ ++ if (flag2 && flag) { ++ doBrew(level, pos, blockEntity.items, blockEntity); // CraftBukkit + setChanged(level, pos, state); +- } else if (!isBrewable || !itemStack1.is(blockEntity.ingredient)) { ++ } else if (!flag || !itemstack1.is(blockEntity.ingredient)) { + blockEntity.brewTime = 0; + setChanged(level, pos, state); + } +- } else if (isBrewable && blockEntity.fuel > 0) { +- blockEntity.fuel--; +- blockEntity.brewTime = 400; +- blockEntity.ingredient = itemStack1.getItem(); ++ } else if (flag && blockEntity.fuel > 0) { ++ --blockEntity.fuel; ++ // CraftBukkit start ++ BrewingStartEvent event = new BrewingStartEvent(CraftBlock.at(level, pos), CraftItemStack.asCraftMirror(itemstack1), 400); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ blockEntity.brewTime = event.getTotalBrewTime(); // 400 -> event.getTotalBrewTime() ++ // CraftBukkit end ++ blockEntity.ingredient = itemstack1.getItem(); + setChanged(level, pos, state); + } + +- boolean[] potionBits = blockEntity.getPotionBits(); +- if (!Arrays.equals(potionBits, blockEntity.lastPotionCount)) { +- blockEntity.lastPotionCount = potionBits; +- BlockState blockState = state; ++ boolean[] aboolean = blockEntity.getPotionBits(); ++ ++ if (!Arrays.equals(aboolean, blockEntity.lastPotionCount)) { ++ blockEntity.lastPotionCount = aboolean; ++ IBlockData iblockdata1 = state; ++ + if (!(state.getBlock() instanceof BrewingStandBlock)) { + return; + } + +- for (int i = 0; i < BrewingStandBlock.HAS_BOTTLE.length; i++) { +- blockState = blockState.setValue(BrewingStandBlock.HAS_BOTTLE[i], Boolean.valueOf(potionBits[i])); ++ for (int i = 0; i < BrewingStandBlock.HAS_BOTTLE.length; ++i) { ++ iblockdata1 = (IBlockData) iblockdata1.setValue(BrewingStandBlock.HAS_BOTTLE[i], aboolean[i]); + } + +- level.setBlock(pos, blockState, 2); ++ level.setBlock(pos, iblockdata1, 2); + } ++ + } + + private boolean[] getPotionBits() { +- boolean[] flags = new boolean[3]; ++ boolean[] aboolean = new boolean[3]; + +- for (int i = 0; i < 3; i++) { +- if (!this.items.get(i).isEmpty()) { +- flags[i] = true; ++ for (int i = 0; i < 3; ++i) { ++ if (!((ItemStack) this.items.get(i)).isEmpty()) { ++ aboolean[i] = true; + } + } + +- return flags; ++ return aboolean; + } + + private static boolean isBrewable(NonNullList items) { +- ItemStack itemStack = items.get(3); +- if (itemStack.isEmpty()) { ++ ItemStack itemstack = (ItemStack) items.get(3); ++ ++ if (itemstack.isEmpty()) { + return false; +- } else if (!PotionBrewing.isIngredient(itemStack)) { ++ } else if (!PotionBrewing.isIngredient(itemstack)) { + return false; + } else { +- for (int i = 0; i < 3; i++) { +- ItemStack itemStack1 = items.get(i); +- if (!itemStack1.isEmpty() && PotionBrewing.hasMix(itemStack1, itemStack)) { ++ for (int i = 0; i < 3; ++i) { ++ ItemStack itemstack1 = (ItemStack) items.get(i); ++ ++ if (!itemstack1.isEmpty() && PotionBrewing.hasMix(itemstack1, itemstack)) { + return true; + } + } +@@ -168,25 +251,48 @@ + } + } + +- private static void doBrew(Level level, BlockPos pos, NonNullList items) { +- ItemStack itemStack = items.get(3); ++ // CraftBukkit start ++ private static void doBrew(Level world, BlockPos blockposition, NonNullList nonnulllist, BrewingStandBlockEntity tileentitybrewingstand) { ++ ItemStack itemstack = (ItemStack) nonnulllist.get(3); ++ InventoryHolder owner = tileentitybrewingstand.getOwner(); ++ List brewResults = new ArrayList<>(3); + +- for (int i = 0; i < 3; i++) { +- items.set(i, PotionBrewing.mix(itemStack, items.get(i))); ++ for (int i = 0; i < 3; ++i) { ++ brewResults.add(i, CraftItemStack.asCraftMirror(PotionBrewing.mix(itemstack, (ItemStack) nonnulllist.get(i)))); + } + +- itemStack.shrink(1); +- if (itemStack.getItem().hasCraftingRemainingItem()) { +- ItemStack itemStack1 = new ItemStack(itemStack.getItem().getCraftingRemainingItem()); +- if (itemStack.isEmpty()) { +- itemStack = itemStack1; ++ if (owner != null) { ++ BrewEvent event = new BrewEvent(CraftBlock.at(world, blockposition), (org.bukkit.inventory.BrewerInventory) owner.getInventory(), brewResults, tileentitybrewingstand.fuel); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ ++ for (int i = 0; i < 3; ++i) { ++ // CraftBukkit start - validate index in case it is cleared by plugins ++ if (i < brewResults.size()) { ++ nonnulllist.set(i, CraftItemStack.asNMSCopy(brewResults.get(i))); + } else { +- Containers.dropItemStack(level, (double)pos.getX(), (double)pos.getY(), (double)pos.getZ(), itemStack1); ++ nonnulllist.set(i, ItemStack.EMPTY); + } ++ // CraftBukkit end + } + +- items.set(3, itemStack); +- level.levelEvent(1035, pos, 0); ++ itemstack.shrink(1); ++ if (itemstack.getItem().hasCraftingRemainingItem()) { ++ ItemStack itemstack1 = new ItemStack(itemstack.getItem().getCraftingRemainingItem()); ++ ++ if (itemstack.isEmpty()) { ++ itemstack = itemstack1; ++ } else { ++ Containers.dropItemStack(world, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), itemstack1); ++ } ++ } ++ ++ nonnulllist.set(3, itemstack); ++ world.levelEvent(1035, blockposition, 0); + } + + @Override +@@ -201,14 +307,14 @@ + @Override + protected void saveAdditional(CompoundTag tag) { + super.saveAdditional(tag); +- tag.putShort("BrewTime", (short)this.brewTime); ++ tag.putShort("BrewTime", (short) this.brewTime); + ContainerHelper.saveAllItems(tag, this.items); +- tag.putByte("Fuel", (byte)this.fuel); ++ tag.putByte("Fuel", (byte) this.fuel); + } + + @Override + public ItemStack getItem(int index) { +- return index >= 0 && index < this.items.size() ? this.items.get(index) : ItemStack.EMPTY; ++ return index >= 0 && index < this.items.size() ? (ItemStack) this.items.get(index) : ItemStack.EMPTY; + } + + @Override +@@ -226,6 +332,7 @@ + if (index >= 0 && index < this.items.size()) { + this.items.set(index, stack); + } ++ + } + + @Override +@@ -235,23 +342,12 @@ + + @Override + public boolean canPlaceItem(int index, ItemStack stack) { +- if (index == 3) { +- return PotionBrewing.isIngredient(stack); +- } else { +- return index == 4 +- ? stack.is(Items.BLAZE_POWDER) +- : (stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE)) +- && this.getItem(index).isEmpty(); +- } ++ return index == 3 ? PotionBrewing.isIngredient(stack) : (index == 4 ? stack.is(Items.BLAZE_POWDER) : (stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE)) && this.getItem(index).isEmpty()); + } + + @Override + public int[] getSlotsForFace(Direction side) { +- if (side == Direction.UP) { +- return SLOTS_FOR_UP; +- } else { +- return side == Direction.DOWN ? SLOTS_FOR_DOWN : SLOTS_FOR_SIDES; +- } ++ return side == Direction.UP ? BrewingStandBlockEntity.SLOTS_FOR_UP : (side == Direction.DOWN ? BrewingStandBlockEntity.SLOTS_FOR_DOWN : BrewingStandBlockEntity.SLOTS_FOR_SIDES); + } + + @Override +@@ -261,7 +357,7 @@ + + @Override + public boolean canTakeItemThroughFace(int index, ItemStack stack, Direction direction) { +- return index != 3 || stack.is(Items.GLASS_BOTTLE); ++ return index == 3 ? stack.is(Items.GLASS_BOTTLE) : true; + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BrushableBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BrushableBlockEntity.java.patch new file mode 100644 index 0000000000..c65dbb203c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/BrushableBlockEntity.java.patch @@ -0,0 +1,284 @@ +--- a/net/minecraft/world/level/block/entity/BrushableBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BrushableBlockEntity.java +@@ -19,7 +19,7 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.BrushableBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.storage.loot.LootParams; + import net.minecraft.world.level.storage.loot.LootTable; +@@ -28,7 +28,14 @@ + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.Arrays; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class BrushableBlockEntity extends BlockEntity { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final String LOOT_TABLE_TAG = "LootTable"; + private static final String LOOT_TABLE_SEED_TAG = "LootTableSeed"; +@@ -40,37 +47,41 @@ + private int brushCount; + private long brushCountResetsAtTick; + private long coolDownEndsAtTick; +- private ItemStack item = ItemStack.EMPTY; ++ public ItemStack item; + @Nullable + private Direction hitDirection; + @Nullable +- private ResourceLocation lootTable; +- private long lootTableSeed; ++ public ResourceLocation lootTable; ++ public long lootTableSeed; + +- public BrushableBlockEntity(BlockPos pos, BlockState blockState) { ++ public BrushableBlockEntity(BlockPos pos, IBlockData blockState) { + super(BlockEntityType.BRUSHABLE_BLOCK, pos, blockState); ++ this.item = ItemStack.EMPTY; + } + +- public boolean brush(long startTick, Player player, Direction hitDirection) { ++ public boolean brush(long startTick, Player entityhuman, Direction player) { + if (this.hitDirection == null) { +- this.hitDirection = hitDirection; ++ this.hitDirection = player; + } + + this.brushCountResetsAtTick = startTick + 40L; + if (startTick >= this.coolDownEndsAtTick && this.level instanceof ServerLevel) { + this.coolDownEndsAtTick = startTick + 10L; +- this.unpackLootTable(player); +- int completionState = this.getCompletionState(); ++ this.unpackLootTable(entityhuman); ++ int j = this.getCompletionState(); ++ + if (++this.brushCount >= 10) { +- this.brushingCompleted(player); ++ this.brushingCompleted(entityhuman); + return true; + } else { + this.level.scheduleTick(this.getBlockPos(), this.getBlockState().getBlock(), 2); +- int completionState1 = this.getCompletionState(); +- if (completionState != completionState1) { +- BlockState blockState = this.getBlockState(); +- BlockState blockState1 = blockState.setValue(BlockStateProperties.DUSTED, Integer.valueOf(completionState1)); +- this.level.setBlock(this.getBlockPos(), blockState1, 3); ++ int k = this.getCompletionState(); ++ ++ if (j != k) { ++ IBlockData iblockdata = this.getBlockState(); ++ IBlockData iblockdata1 = (IBlockData) iblockdata.setValue(BlockStateProperties.DUSTED, k); ++ ++ this.level.setBlock(this.getBlockPos(), iblockdata1, 3); + } + + return false; +@@ -82,26 +93,31 @@ + + public void unpackLootTable(Player player) { + if (this.lootTable != null && this.level != null && !this.level.isClientSide() && this.level.getServer() != null) { +- LootTable lootTable = this.level.getServer().getLootData().getLootTable(this.lootTable); +- if (player instanceof ServerPlayer serverPlayer) { +- CriteriaTriggers.GENERATE_LOOT.trigger(serverPlayer, this.lootTable); ++ LootTable loottable = this.level.getServer().getLootData().getLootTable(this.lootTable); ++ ++ if (player instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) player; ++ ++ CriteriaTriggers.GENERATE_LOOT.trigger(entityplayer, this.lootTable); + } + +- LootParams lootParams = new LootParams.Builder((ServerLevel)this.level) +- .withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(this.worldPosition)) +- .withLuck(player.getLuck()) +- .withParameter(LootContextParams.THIS_ENTITY, player) +- .create(LootContextParamSets.CHEST); +- ObjectArrayList randomItems = lootTable.getRandomItems(lootParams, this.lootTableSeed); ++ LootParams lootparams = (new LootParams.Builder((ServerLevel) this.level)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(this.worldPosition)).withLuck(player.getLuck()).withParameter(LootContextParams.THIS_ENTITY, player).create(LootContextParamSets.CHEST); ++ ObjectArrayList objectarraylist = loottable.getRandomItems(lootparams, this.lootTableSeed); ++ ItemStack itemstack; + +- this.item = switch (randomItems.size()) { +- case 0 -> ItemStack.EMPTY; +- case 1 -> (ItemStack)randomItems.get(0); +- default -> { +- LOGGER.warn("Expected max 1 loot from loot table " + this.lootTable + " got " + randomItems.size()); +- yield randomItems.get(0); +- } +- }; ++ switch (objectarraylist.size()) { ++ case 0: ++ itemstack = ItemStack.EMPTY; ++ break; ++ case 1: ++ itemstack = (ItemStack) objectarraylist.get(0); ++ break; ++ default: ++ BrushableBlockEntity.LOGGER.warn("Expected max 1 loot from loot table " + this.lootTable + " got " + objectarraylist.size()); ++ itemstack = (ItemStack) objectarraylist.get(0); ++ } ++ ++ this.item = itemstack; + this.lootTable = null; + this.setChanged(); + } +@@ -110,16 +126,21 @@ + private void brushingCompleted(Player player) { + if (this.level != null && this.level.getServer() != null) { + this.dropContent(player); +- BlockState blockState = this.getBlockState(); +- this.level.levelEvent(3008, this.getBlockPos(), Block.getId(blockState)); +- Block turnsInto; +- if (this.getBlockState().getBlock() instanceof BrushableBlock brushableBlock) { +- turnsInto = brushableBlock.getTurnsInto(); ++ IBlockData iblockdata = this.getBlockState(); ++ ++ this.level.levelEvent(3008, this.getBlockPos(), Block.getId(iblockdata)); ++ Block block = this.getBlockState().getBlock(); ++ Block block1; ++ ++ if (block instanceof BrushableBlock) { ++ BrushableBlock brushableblock = (BrushableBlock) block; ++ ++ block1 = brushableblock.getTurnsInto(); + } else { +- turnsInto = Blocks.AIR; ++ block1 = Blocks.AIR; + } + +- this.level.setBlock(this.worldPosition, turnsInto.defaultBlockState(), 3); ++ this.level.setBlock(this.worldPosition, block1.defaultBlockState(), 3); + } + } + +@@ -127,33 +148,41 @@ + if (this.level != null && this.level.getServer() != null) { + this.unpackLootTable(player); + if (!this.item.isEmpty()) { +- double d = (double)EntityType.ITEM.getWidth(); +- double d1 = 1.0 - d; +- double d2 = d / 2.0; +- Direction direction = Objects.requireNonNullElse(this.hitDirection, Direction.UP); +- BlockPos blockPos = this.worldPosition.relative(direction, 1); +- double d3 = (double)blockPos.getX() + 0.5 * d1 + d2; +- double d4 = (double)blockPos.getY() + 0.5 + (double)(EntityType.ITEM.getHeight() / 2.0F); +- double d5 = (double)blockPos.getZ() + 0.5 * d1 + d2; +- ItemEntity itemEntity = new ItemEntity(this.level, d3, d4, d5, this.item.split(this.level.random.nextInt(21) + 10)); +- itemEntity.setDeltaMovement(Vec3.ZERO); +- this.level.addFreshEntity(itemEntity); ++ double d0 = (double) EntityType.ITEM.getWidth(); ++ double d1 = 1.0D - d0; ++ double d2 = d0 / 2.0D; ++ Direction enumdirection = (Direction) Objects.requireNonNullElse(this.hitDirection, Direction.UP); ++ BlockPos blockposition = this.worldPosition.relative(enumdirection, 1); ++ double d3 = (double) blockposition.getX() + 0.5D * d1 + d2; ++ double d4 = (double) blockposition.getY() + 0.5D + (double) (EntityType.ITEM.getHeight() / 2.0F); ++ double d5 = (double) blockposition.getZ() + 0.5D * d1 + d2; ++ ItemEntity entityitem = new ItemEntity(this.level, d3, d4, d5, this.item.split(this.level.random.nextInt(21) + 10)); ++ ++ entityitem.setDeltaMovement(Vec3.ZERO); ++ // CraftBukkit start ++ org.bukkit.block.Block bblock = CraftBlock.at(this.level, this.worldPosition); ++ CraftEventFactory.handleBlockDropItemEvent(bblock, bblock.getState(), (ServerPlayer) player, Arrays.asList(entityitem)); ++ // CraftBukkit end + this.item = ItemStack.EMPTY; + } ++ + } + } + + public void checkReset() { + if (this.level != null) { + if (this.brushCount != 0 && this.level.getGameTime() >= this.brushCountResetsAtTick) { +- int completionState = this.getCompletionState(); ++ int i = this.getCompletionState(); ++ + this.brushCount = Math.max(0, this.brushCount - 2); +- int completionState1 = this.getCompletionState(); +- if (completionState != completionState1) { +- this.level.setBlock(this.getBlockPos(), this.getBlockState().setValue(BlockStateProperties.DUSTED, Integer.valueOf(completionState1)), 3); ++ int j = this.getCompletionState(); ++ ++ if (i != j) { ++ this.level.setBlock(this.getBlockPos(), (IBlockData) this.getBlockState().setValue(BlockStateProperties.DUSTED, j), 3); + } + +- int i = 4; ++ boolean flag = true; ++ + this.brushCountResetsAtTick = this.level.getGameTime() + 4L; + } + +@@ -164,6 +193,7 @@ + } else { + this.level.scheduleTick(this.getBlockPos(), this.getBlockState().getBlock(), 2); + } ++ + } + } + +@@ -192,13 +222,14 @@ + + @Override + public CompoundTag getUpdateTag() { +- CompoundTag compoundTag = super.getUpdateTag(); ++ CompoundTag nbttagcompound = super.getUpdateTag(); ++ + if (this.hitDirection != null) { +- compoundTag.putInt("hit_direction", this.hitDirection.ordinal()); ++ nbttagcompound.putInt("hit_direction", this.hitDirection.ordinal()); + } + +- compoundTag.put("item", this.item.save(new CompoundTag())); +- return compoundTag; ++ nbttagcompound.put("item", this.item.save(new CompoundTag())); ++ return nbttagcompound; + } + + @Override +@@ -208,6 +239,7 @@ + + @Override + public void load(CompoundTag tag) { ++ super.load(tag); // CraftBukkit - SPIGOT-7393: Load super Bukkit data + if (!this.tryLoadLootTable(tag) && tag.contains("item")) { + this.item = ItemStack.of(tag.getCompound("item")); + } +@@ -215,6 +247,7 @@ + if (tag.contains("hit_direction")) { + this.hitDirection = Direction.values()[tag.getInt("hit_direction")]; + } ++ + } + + @Override +@@ -222,6 +255,7 @@ + if (!this.trySaveLootTable(tag)) { + tag.put("item", this.item.save(new CompoundTag())); + } ++ + } + + public void setLootTable(ResourceLocation lootTable, long lootTableSeed) { +@@ -230,13 +264,7 @@ + } + + private int getCompletionState() { +- if (this.brushCount == 0) { +- return 0; +- } else if (this.brushCount < 3) { +- return 1; +- } else { +- return this.brushCount < 6 ? 2 : 3; +- } ++ return this.brushCount == 0 ? 0 : (this.brushCount < 3 ? 1 : (this.brushCount < 6 ? 2 : 3)); + } + + @Nullable diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/CampfireBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/CampfireBlockEntity.java.patch new file mode 100644 index 0000000000..7a70e42830 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/CampfireBlockEntity.java.patch @@ -0,0 +1,228 @@ +--- a/net/minecraft/world/level/block/entity/CampfireBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/CampfireBlockEntity.java +@@ -23,37 +23,66 @@ + import net.minecraft.world.item.crafting.RecipeType; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.CampfireBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockCookEvent; ++import org.bukkit.event.block.CampfireStartEvent; ++import org.bukkit.inventory.CampfireRecipe; ++// CraftBukkit end ++ + public class CampfireBlockEntity extends BlockEntity implements Clearable { ++ + private static final int BURN_COOL_SPEED = 2; + private static final int NUM_SLOTS = 4; +- private final NonNullList items = NonNullList.withSize(4, ItemStack.EMPTY); +- private final int[] cookingProgress = new int[4]; +- private final int[] cookingTime = new int[4]; +- private final RecipeManager.CachedCheck quickCheck = RecipeManager.createCheck(RecipeType.CAMPFIRE_COOKING); ++ private final NonNullList items; ++ public final int[] cookingProgress; ++ public final int[] cookingTime; ++ private final RecipeManager.CachedCheck quickCheck; + +- public CampfireBlockEntity(BlockPos pos, BlockState blockState) { ++ public CampfireBlockEntity(BlockPos pos, IBlockData blockState) { + super(BlockEntityType.CAMPFIRE, pos, blockState); ++ this.items = NonNullList.withSize(4, ItemStack.EMPTY); ++ this.cookingProgress = new int[4]; ++ this.cookingTime = new int[4]; ++ this.quickCheck = RecipeManager.createCheck(RecipeType.CAMPFIRE_COOKING); + } + +- public static void cookTick(Level level, BlockPos pos, BlockState state, CampfireBlockEntity blockEntity) { ++ public static void cookTick(Level level, BlockPos pos, IBlockData state, CampfireBlockEntity blockEntity) { + boolean flag = false; + +- for (int i = 0; i < blockEntity.items.size(); i++) { +- ItemStack itemStack = blockEntity.items.get(i); +- if (!itemStack.isEmpty()) { ++ for (int i = 0; i < blockEntity.items.size(); ++i) { ++ ItemStack itemstack = (ItemStack) blockEntity.items.get(i); ++ ++ if (!itemstack.isEmpty()) { + flag = true; +- blockEntity.cookingProgress[i]++; ++ int j = blockEntity.cookingProgress[i]++; ++ + if (blockEntity.cookingProgress[i] >= blockEntity.cookingTime[i]) { +- Container container = new SimpleContainer(itemStack); +- ItemStack itemStack1 = blockEntity.quickCheck +- .getRecipeFor(container, level) +- .map(recipeHolder -> recipeHolder.value().assemble(container, level.registryAccess())) +- .orElse(itemStack); +- if (itemStack1.isItemEnabled(level.enabledFeatures())) { +- Containers.dropItemStack(level, (double)pos.getX(), (double)pos.getY(), (double)pos.getZ(), itemStack1); ++ SimpleContainer inventorysubcontainer = new SimpleContainer(new ItemStack[]{itemstack}); ++ ItemStack itemstack1 = (ItemStack) blockEntity.quickCheck.getRecipeFor(inventorysubcontainer, level).map((recipeholder) -> { ++ return ((CampfireCookingRecipe) recipeholder.value()).assemble(inventorysubcontainer, level.registryAccess()); ++ }).orElse(itemstack); ++ ++ if (itemstack1.isItemEnabled(level.enabledFeatures())) { ++ // CraftBukkit start - fire BlockCookEvent ++ CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); ++ org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); ++ ++ BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(level, pos), source, result); ++ level.getCraftServer().getPluginManager().callEvent(blockCookEvent); ++ ++ if (blockCookEvent.isCancelled()) { ++ return; ++ } ++ ++ result = blockCookEvent.getResult(); ++ itemstack1 = CraftItemStack.asNMSCopy(result); ++ // CraftBukkit end ++ Containers.dropItemStack(level, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), itemstack1); + blockEntity.items.set(i, ItemStack.EMPTY); + level.sendBlockUpdated(pos, state, state, 3); + level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(state)); +@@ -65,12 +94,13 @@ + if (flag) { + setChanged(level, pos, state); + } ++ + } + +- public static void cooldownTick(Level level, BlockPos pos, BlockState state, CampfireBlockEntity blockEntity) { ++ public static void cooldownTick(Level level, BlockPos pos, IBlockData state, CampfireBlockEntity blockEntity) { + boolean flag = false; + +- for (int i = 0; i < blockEntity.items.size(); i++) { ++ for (int i = 0; i < blockEntity.items.size(); ++i) { + if (blockEntity.cookingProgress[i] > 0) { + flag = true; + blockEntity.cookingProgress[i] = Mth.clamp(blockEntity.cookingProgress[i] - 2, 0, blockEntity.cookingTime[i]); +@@ -80,37 +110,35 @@ + if (flag) { + setChanged(level, pos, state); + } ++ + } + +- public static void particleTick(Level level, BlockPos pos, BlockState state, CampfireBlockEntity blockEntity) { +- RandomSource randomSource = level.random; +- if (randomSource.nextFloat() < 0.11F) { +- for (int i = 0; i < randomSource.nextInt(2) + 2; i++) { +- CampfireBlock.makeParticles(level, pos, state.getValue(CampfireBlock.SIGNAL_FIRE), false); ++ public static void particleTick(Level level, BlockPos pos, IBlockData state, CampfireBlockEntity blockEntity) { ++ RandomSource randomsource = level.random; ++ int i; ++ ++ if (randomsource.nextFloat() < 0.11F) { ++ for (i = 0; i < randomsource.nextInt(2) + 2; ++i) { ++ CampfireBlock.makeParticles(level, pos, (Boolean) state.getValue(CampfireBlock.SIGNAL_FIRE), false); + } + } + +- int i = state.getValue(CampfireBlock.FACING).get2DDataValue(); ++ i = ((Direction) state.getValue(CampfireBlock.FACING)).get2DDataValue(); + +- for (int i1 = 0; i1 < blockEntity.items.size(); i1++) { +- if (!blockEntity.items.get(i1).isEmpty() && randomSource.nextFloat() < 0.2F) { +- Direction direction = Direction.from2DDataValue(Math.floorMod(i1 + i, 4)); ++ for (int j = 0; j < blockEntity.items.size(); ++j) { ++ if (!((ItemStack) blockEntity.items.get(j)).isEmpty() && randomsource.nextFloat() < 0.2F) { ++ Direction enumdirection = Direction.from2DDataValue(Math.floorMod(j + i, 4)); + float f = 0.3125F; +- double d = (double)pos.getX() +- + 0.5 +- - (double)((float)direction.getStepX() * 0.3125F) +- + (double)((float)direction.getClockWise().getStepX() * 0.3125F); +- double d1 = (double)pos.getY() + 0.5; +- double d2 = (double)pos.getZ() +- + 0.5 +- - (double)((float)direction.getStepZ() * 0.3125F) +- + (double)((float)direction.getClockWise().getStepZ() * 0.3125F); ++ double d0 = (double) pos.getX() + 0.5D - (double) ((float) enumdirection.getStepX() * 0.3125F) + (double) ((float) enumdirection.getClockWise().getStepX() * 0.3125F); ++ double d1 = (double) pos.getY() + 0.5D; ++ double d2 = (double) pos.getZ() + 0.5D - (double) ((float) enumdirection.getStepZ() * 0.3125F) + (double) ((float) enumdirection.getClockWise().getStepZ() * 0.3125F); + +- for (int i2 = 0; i2 < 4; i2++) { +- level.addParticle(ParticleTypes.SMOKE, d, d1, d2, 0.0, 5.0E-4, 0.0); ++ for (int k = 0; k < 4; ++k) { ++ level.addParticle(ParticleTypes.SMOKE, d0, d1, d2, 0.0D, 5.0E-4D, 0.0D); + } + } + } ++ + } + + public NonNullList getItems() { +@@ -122,15 +150,18 @@ + super.load(tag); + this.items.clear(); + ContainerHelper.loadAllItems(tag, this.items); ++ int[] aint; ++ + if (tag.contains("CookingTimes", 11)) { +- int[] intArray = tag.getIntArray("CookingTimes"); +- System.arraycopy(intArray, 0, this.cookingProgress, 0, Math.min(this.cookingTime.length, intArray.length)); ++ aint = tag.getIntArray("CookingTimes"); ++ System.arraycopy(aint, 0, this.cookingProgress, 0, Math.min(this.cookingTime.length, aint.length)); + } + + if (tag.contains("CookingTotalTimes", 11)) { +- int[] intArray = tag.getIntArray("CookingTotalTimes"); +- System.arraycopy(intArray, 0, this.cookingTime, 0, Math.min(this.cookingTime.length, intArray.length)); ++ aint = tag.getIntArray("CookingTotalTimes"); ++ System.arraycopy(aint, 0, this.cookingTime, 0, Math.min(this.cookingTime.length, aint.length)); + } ++ + } + + @Override +@@ -148,22 +179,28 @@ + + @Override + public CompoundTag getUpdateTag() { +- CompoundTag compoundTag = new CompoundTag(); +- ContainerHelper.saveAllItems(compoundTag, this.items, true); +- return compoundTag; ++ CompoundTag nbttagcompound = new CompoundTag(); ++ ++ ContainerHelper.saveAllItems(nbttagcompound, this.items, true); ++ return nbttagcompound; + } + + public Optional> getCookableRecipe(ItemStack stack) { +- return this.items.stream().noneMatch(ItemStack::isEmpty) ? Optional.empty() : this.quickCheck.getRecipeFor(new SimpleContainer(stack), this.level); ++ return this.items.stream().noneMatch(ItemStack::isEmpty) ? Optional.empty() : this.quickCheck.getRecipeFor(new SimpleContainer(new ItemStack[]{stack}), this.level); + } + + public boolean placeFood(@Nullable Entity entity, ItemStack stack, int cookTime) { +- for (int i = 0; i < this.items.size(); i++) { +- ItemStack itemStack = this.items.get(i); +- if (itemStack.isEmpty()) { +- this.cookingTime[i] = cookTime; +- this.cookingProgress[i] = 0; +- this.items.set(i, stack.split(1)); ++ for (int j = 0; j < this.items.size(); ++j) { ++ ItemStack itemstack1 = (ItemStack) this.items.get(j); ++ ++ if (itemstack1.isEmpty()) { ++ // CraftBukkit start ++ CampfireStartEvent event = new CampfireStartEvent(CraftBlock.at(this.level,this.worldPosition), CraftItemStack.asCraftMirror(stack), (CampfireRecipe) getCookableRecipe(stack).get().toBukkitRecipe()); ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ this.cookingTime[j] = event.getTotalCookTime(); // i -> event.getTotalCookTime() ++ // CraftBukkit end ++ this.cookingProgress[j] = 0; ++ this.items.set(j, stack.split(1)); + this.level.gameEvent(GameEvent.BLOCK_CHANGE, this.getBlockPos(), GameEvent.Context.of(entity, this.getBlockState())); + this.markUpdated(); + return true; +@@ -187,5 +224,6 @@ + if (this.level != null) { + this.markUpdated(); + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/ChestBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/ChestBlockEntity.java.patch new file mode 100644 index 0000000000..b0c2ce6a53 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/ChestBlockEntity.java.patch @@ -0,0 +1,236 @@ +--- a/net/minecraft/world/level/block/entity/ChestBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/ChestBlockEntity.java +@@ -20,46 +20,85 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.ChestBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.ChestType; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end + + public class ChestBlockEntity extends RandomizableContainerBlockEntity implements LidBlockEntity { ++ + private static final int EVENT_SET_OPEN_COUNT = 1; +- private NonNullList items = NonNullList.withSize(27, ItemStack.EMPTY); +- private final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() { +- @Override +- protected void onOpen(Level level, BlockPos pos, BlockState state) { +- ChestBlockEntity.playSound(level, pos, state, SoundEvents.CHEST_OPEN); +- } ++ private NonNullList items; ++ public final ContainerOpenersCounter openersCounter; ++ private final ChestLidController chestLidController; + +- @Override +- protected void onClose(Level level, BlockPos pos, BlockState state) { +- ChestBlockEntity.playSound(level, pos, state, SoundEvents.CHEST_CLOSE); +- } ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; + +- @Override +- protected void openerCountChanged(Level level, BlockPos pos, BlockState state, int count, int openCount) { +- ChestBlockEntity.this.signalOpenCount(level, pos, state, count, openCount); +- } ++ public List getContents() { ++ return this.items; ++ } + +- @Override +- protected boolean isOwnContainer(Player player) { +- if (!(player.containerMenu instanceof ChestMenu)) { +- return false; +- } else { +- Container container = ((ChestMenu)player.containerMenu).getContainer(); +- return container == ChestBlockEntity.this +- || container instanceof CompoundContainer && ((CompoundContainer)container).contains(ChestBlockEntity.this); +- } +- } +- }; +- private final ChestLidController chestLidController = new ChestLidController(); ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } + +- protected ChestBlockEntity(BlockEntityType type, BlockPos pos, BlockState blockState) { ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ ++ protected ChestBlockEntity(BlockEntityType type, BlockPos pos, IBlockData blockState) { + super(type, pos, blockState); ++ this.items = NonNullList.withSize(27, ItemStack.EMPTY); ++ this.openersCounter = new ContainerOpenersCounter() { ++ @Override ++ protected void onOpen(Level level, BlockPos pos, IBlockData state) { ++ ChestBlockEntity.playSound(level, pos, state, SoundEvents.CHEST_OPEN); ++ } ++ ++ @Override ++ protected void onClose(Level level, BlockPos pos, IBlockData state) { ++ ChestBlockEntity.playSound(level, pos, state, SoundEvents.CHEST_CLOSE); ++ } ++ ++ @Override ++ protected void openerCountChanged(Level level, BlockPos pos, IBlockData state, int count, int openCount) { ++ ChestBlockEntity.this.signalOpenCount(level, pos, state, count, openCount); ++ } ++ ++ @Override ++ protected boolean isOwnContainer(Player player) { ++ if (!(player.containerMenu instanceof ChestMenu)) { ++ return false; ++ } else { ++ Container iinventory = ((ChestMenu) player.containerMenu).getContainer(); ++ ++ return iinventory == ChestBlockEntity.this || iinventory instanceof CompoundContainer && ((CompoundContainer) iinventory).contains(ChestBlockEntity.this); ++ } ++ } ++ }; ++ this.chestLidController = new ChestLidController(); + } + +- public ChestBlockEntity(BlockPos pos, BlockState blockState) { ++ public ChestBlockEntity(BlockPos pos, IBlockData blockState) { + this(BlockEntityType.CHEST, pos, blockState); + } + +@@ -80,6 +119,7 @@ + if (!this.tryLoadLootTable(tag)) { + ContainerHelper.loadAllItems(tag, this.items); + } ++ + } + + @Override +@@ -88,25 +128,29 @@ + if (!this.trySaveLootTable(tag)) { + ContainerHelper.saveAllItems(tag, this.items); + } ++ + } + +- public static void lidAnimateTick(Level level, BlockPos pos, BlockState state, ChestBlockEntity blockEntity) { ++ public static void lidAnimateTick(Level level, BlockPos pos, IBlockData state, ChestBlockEntity blockEntity) { + blockEntity.chestLidController.tickLid(); + } + +- static void playSound(Level level, BlockPos pos, BlockState state, SoundEvent sound) { +- ChestType chestType = state.getValue(ChestBlock.TYPE); +- if (chestType != ChestType.LEFT) { +- double d = (double)pos.getX() + 0.5; +- double d1 = (double)pos.getY() + 0.5; +- double d2 = (double)pos.getZ() + 0.5; +- if (chestType == ChestType.RIGHT) { +- Direction connectedDirection = ChestBlock.getConnectedDirection(state); +- d += (double)connectedDirection.getStepX() * 0.5; +- d2 += (double)connectedDirection.getStepZ() * 0.5; ++ public static void playSound(Level level, BlockPos pos, IBlockData state, SoundEvent sound) { ++ ChestType blockpropertychesttype = (ChestType) state.getValue(ChestBlock.TYPE); ++ ++ if (blockpropertychesttype != ChestType.LEFT) { ++ double d0 = (double) pos.getX() + 0.5D; ++ double d1 = (double) pos.getY() + 0.5D; ++ double d2 = (double) pos.getZ() + 0.5D; ++ ++ if (blockpropertychesttype == ChestType.RIGHT) { ++ Direction enumdirection = ChestBlock.getConnectedDirection(state); ++ ++ d0 += (double) enumdirection.getStepX() * 0.5D; ++ d2 += (double) enumdirection.getStepZ() * 0.5D; + } + +- level.playSound(null, d, d1, d2, sound, SoundSource.BLOCKS, 0.5F, level.random.nextFloat() * 0.1F + 0.9F); ++ level.playSound((Player) null, d0, d1, d2, sound, SoundSource.BLOCKS, 0.5F, level.random.nextFloat() * 0.1F + 0.9F); + } + } + +@@ -125,6 +169,7 @@ + if (!this.remove && !player.isSpectator()) { + this.openersCounter.incrementOpeners(player, this.getLevel(), this.getBlockPos(), this.getBlockState()); + } ++ + } + + @Override +@@ -132,6 +177,7 @@ + if (!this.remove && !player.isSpectator()) { + this.openersCounter.decrementOpeners(player, this.getLevel(), this.getBlockPos(), this.getBlockState()); + } ++ + } + + @Override +@@ -150,11 +196,13 @@ + } + + public static int getOpenCount(BlockGetter level, BlockPos pos) { +- BlockState blockState = level.getBlockState(pos); +- if (blockState.hasBlockEntity()) { +- BlockEntity blockEntity = level.getBlockEntity(pos); +- if (blockEntity instanceof ChestBlockEntity) { +- return ((ChestBlockEntity)blockEntity).openersCounter.getOpenerCount(); ++ IBlockData iblockdata = level.getBlockState(pos); ++ ++ if (iblockdata.hasBlockEntity()) { ++ BlockEntity tileentity = level.getBlockEntity(pos); ++ ++ if (tileentity instanceof ChestBlockEntity) { ++ return ((ChestBlockEntity) tileentity).openersCounter.getOpenerCount(); + } + } + +@@ -162,9 +210,10 @@ + } + + public static void swapContents(ChestBlockEntity chest, ChestBlockEntity otherChest) { +- NonNullList items = chest.getItems(); ++ NonNullList nonnulllist = chest.getItems(); ++ + chest.setItems(otherChest.getItems()); +- otherChest.setItems(items); ++ otherChest.setItems(nonnulllist); + } + + @Override +@@ -176,10 +225,19 @@ + if (!this.remove) { + this.openersCounter.recheckOpeners(this.getLevel(), this.getBlockPos(), this.getBlockState()); + } ++ + } + +- protected void signalOpenCount(Level level, BlockPos pos, BlockState state, int eventId, int eventParam) { ++ protected void signalOpenCount(Level level, BlockPos pos, IBlockData state, int eventId, int eventParam) { + Block block = state.getBlock(); ++ + level.blockEvent(pos, block, 1, eventParam); + } ++ ++ // CraftBukkit start ++ @Override ++ public boolean onlyOpCanSetNbt() { ++ return true; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java.patch new file mode 100644 index 0000000000..a181e9777b --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java.patch @@ -0,0 +1,170 @@ +--- a/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java +@@ -11,42 +11,90 @@ + import net.minecraft.world.ContainerHelper; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.ChiseledBookShelfBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.gameevent.GameEvent; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class ChiseledBookShelfBlockEntity extends BlockEntity implements Container { ++ + public static final int MAX_BOOKS_IN_STORAGE = 6; + private static final Logger LOGGER = LogUtils.getLogger(); +- private final NonNullList items = NonNullList.withSize(6, ItemStack.EMPTY); +- private int lastInteractedSlot = -1; ++ private final NonNullList items; ++ public int lastInteractedSlot; ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList<>(); ++ private int maxStack = 1; + +- public ChiseledBookShelfBlockEntity(BlockPos pos, BlockState state) { ++ @Override ++ public List getContents() { ++ return this.items; ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ } ++ // CraftBukkit end ++ ++ public ChiseledBookShelfBlockEntity(BlockPos pos, IBlockData state) { + super(BlockEntityType.CHISELED_BOOKSHELF, pos, state); ++ this.items = NonNullList.withSize(6, ItemStack.EMPTY); ++ this.lastInteractedSlot = -1; + } + + private void updateState(int slot) { + if (slot >= 0 && slot < 6) { + this.lastInteractedSlot = slot; +- BlockState blockState = this.getBlockState(); ++ IBlockData iblockdata = this.getBlockState(); + +- for (int i = 0; i < ChiseledBookShelfBlock.SLOT_OCCUPIED_PROPERTIES.size(); i++) { +- boolean flag = !this.getItem(i).isEmpty(); +- BooleanProperty booleanProperty = ChiseledBookShelfBlock.SLOT_OCCUPIED_PROPERTIES.get(i); +- blockState = blockState.setValue(booleanProperty, Boolean.valueOf(flag)); ++ for (int j = 0; j < ChiseledBookShelfBlock.SLOT_OCCUPIED_PROPERTIES.size(); ++j) { ++ boolean flag = !this.getItem(j).isEmpty(); ++ BooleanProperty blockstateboolean = (BooleanProperty) ChiseledBookShelfBlock.SLOT_OCCUPIED_PROPERTIES.get(j); ++ ++ iblockdata = (IBlockData) iblockdata.setValue(blockstateboolean, flag); + } + +- Objects.requireNonNull(this.level).setBlock(this.worldPosition, blockState, 3); +- this.level.gameEvent(GameEvent.BLOCK_CHANGE, this.worldPosition, GameEvent.Context.of(blockState)); ++ ((Level) Objects.requireNonNull(this.level)).setBlock(this.worldPosition, iblockdata, 3); ++ this.level.gameEvent(GameEvent.BLOCK_CHANGE, this.worldPosition, GameEvent.Context.of(iblockdata)); + } else { +- LOGGER.error("Expected slot 0-5, got {}", slot); ++ ChiseledBookShelfBlockEntity.LOGGER.error("Expected slot 0-5, got {}", slot); + } + } + + @Override + public void load(CompoundTag tag) { ++ super.load(tag); // CraftBukkit - SPIGOT-7393: Load super Bukkit data + this.items.clear(); + ContainerHelper.loadAllItems(tag, this.items); + this.lastInteractedSlot = tag.getInt("last_interacted_slot"); +@@ -59,7 +107,7 @@ + } + + public int count() { +- return (int)this.items.stream().filter(Predicate.not(ItemStack::isEmpty)).count(); ++ return (int) this.items.stream().filter(Predicate.not(ItemStack::isEmpty)).count(); + } + + @Override +@@ -79,18 +127,19 @@ + + @Override + public ItemStack getItem(int slot) { +- return this.items.get(slot); ++ return (ItemStack) this.items.get(slot); + } + + @Override + public ItemStack removeItem(int slot, int amount) { +- ItemStack itemStack = Objects.requireNonNullElse(this.items.get(slot), ItemStack.EMPTY); ++ ItemStack itemstack = (ItemStack) Objects.requireNonNullElse((ItemStack) this.items.get(slot), ItemStack.EMPTY); ++ + this.items.set(slot, ItemStack.EMPTY); +- if (!itemStack.isEmpty()) { +- this.updateState(slot); ++ if (!itemstack.isEmpty()) { ++ if (level != null) this.updateState(slot); // CraftBukkit - SPIGOT-7381: check for null world + } + +- return itemStack; ++ return itemstack; + } + + @Override +@@ -102,24 +151,23 @@ + public void setItem(int slot, ItemStack stack) { + if (stack.is(ItemTags.BOOKSHELF_BOOKS)) { + this.items.set(slot, stack); +- this.updateState(slot); ++ if (level != null) this.updateState(slot); // CraftBukkit - SPIGOT-7381: check for null world + } else if (stack.isEmpty()) { + this.removeItem(slot, 1); + } ++ + } + + @Override + public boolean canTakeItem(Container target, int index, ItemStack stack) { +- return target.hasAnyMatching( +- itemStack -> itemStack.isEmpty() +- || ItemStack.isSameItemSameTags(stack, itemStack) +- && itemStack.getCount() + stack.getCount() <= Math.min(itemStack.getMaxStackSize(), target.getMaxStackSize()) +- ); ++ return target.hasAnyMatching((itemstack1) -> { ++ return itemstack1.isEmpty() ? true : ItemStack.isSameItemSameTags(stack, itemstack1) && itemstack1.getCount() + stack.getCount() <= Math.min(itemstack1.getMaxStackSize(), target.getMaxStackSize()); ++ }); + } + + @Override + public int getMaxStackSize() { +- return 1; ++ return maxStack; // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/CommandBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/CommandBlockEntity.java.patch new file mode 100644 index 0000000000..6341b27890 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/CommandBlockEntity.java.patch @@ -0,0 +1,174 @@ +--- a/net/minecraft/world/level/block/entity/CommandBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/CommandBlockEntity.java +@@ -5,20 +5,29 @@ + import net.minecraft.core.Direction; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.BaseCommandBlock; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.CommandBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; + + public class CommandBlockEntity extends BlockEntity { ++ + private boolean powered; + private boolean auto; + private boolean conditionMet; + private final BaseCommandBlock commandBlock = new BaseCommandBlock() { ++ // CraftBukkit start + @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return new org.bukkit.craftbukkit.command.CraftBlockCommandSender(wrapper, CommandBlockEntity.this); ++ } ++ // CraftBukkit end ++ ++ @Override + public void setCommand(String command) { + super.setCommand(command); + CommandBlockEntity.this.setChanged(); +@@ -26,13 +35,14 @@ + + @Override + public ServerLevel getLevel() { +- return (ServerLevel)CommandBlockEntity.this.level; ++ return (ServerLevel) CommandBlockEntity.this.level; + } + + @Override + public void onUpdated() { +- BlockState blockState = CommandBlockEntity.this.level.getBlockState(CommandBlockEntity.this.worldPosition); +- this.getLevel().sendBlockUpdated(CommandBlockEntity.this.worldPosition, blockState, blockState, 3); ++ IBlockData iblockdata = CommandBlockEntity.this.level.getBlockState(CommandBlockEntity.this.worldPosition); ++ ++ this.getLevel().sendBlockUpdated(CommandBlockEntity.this.worldPosition, iblockdata, iblockdata, 3); + } + + @Override +@@ -42,18 +52,9 @@ + + @Override + public CommandSourceStack createCommandSourceStack() { +- Direction direction = CommandBlockEntity.this.getBlockState().getValue(CommandBlock.FACING); +- return new CommandSourceStack( +- this, +- Vec3.atCenterOf(CommandBlockEntity.this.worldPosition), +- new Vec2(0.0F, direction.toYRot()), +- this.getLevel(), +- 2, +- this.getName().getString(), +- this.getName(), +- this.getLevel().getServer(), +- null +- ); ++ Direction enumdirection = (Direction) CommandBlockEntity.this.getBlockState().getValue(CommandBlock.FACING); ++ ++ return new CommandSourceStack(this, Vec3.atCenterOf(CommandBlockEntity.this.worldPosition), new Vec2(0.0F, enumdirection.toYRot()), this.getLevel(), 2, this.getName().getString(), this.getName(), this.getLevel().getServer(), (Entity) null); + } + + @Override +@@ -62,7 +63,7 @@ + } + }; + +- public CommandBlockEntity(BlockPos pos, BlockState blockState) { ++ public CommandBlockEntity(BlockPos pos, IBlockData blockState) { + super(BlockEntityType.COMMAND_BLOCK, pos, blockState); + } + +@@ -106,26 +107,32 @@ + } + + public void setAutomatic(boolean auto) { +- boolean flag = this.auto; ++ boolean flag1 = this.auto; ++ + this.auto = auto; +- if (!flag && auto && !this.powered && this.level != null && this.getMode() != CommandBlockEntity.Mode.SEQUENCE) { ++ if (!flag1 && auto && !this.powered && this.level != null && this.getMode() != CommandBlockEntity.Type.SEQUENCE) { + this.scheduleTick(); + } ++ + } + + public void onModeSwitch() { +- CommandBlockEntity.Mode mode = this.getMode(); +- if (mode == CommandBlockEntity.Mode.AUTO && (this.powered || this.auto) && this.level != null) { ++ CommandBlockEntity.Type tileentitycommand_type = this.getMode(); ++ ++ if (tileentitycommand_type == CommandBlockEntity.Type.AUTO && (this.powered || this.auto) && this.level != null) { + this.scheduleTick(); + } ++ + } + + private void scheduleTick() { + Block block = this.getBlockState().getBlock(); ++ + if (block instanceof CommandBlock) { + this.markConditionMet(); + this.level.scheduleTick(this.worldPosition, block, 1); + } ++ + } + + public boolean wasConditionMet() { +@@ -135,10 +142,12 @@ + public boolean markConditionMet() { + this.conditionMet = true; + if (this.isConditional()) { +- BlockPos blockPos = this.worldPosition.relative(this.level.getBlockState(this.worldPosition).getValue(CommandBlock.FACING).getOpposite()); +- if (this.level.getBlockState(blockPos).getBlock() instanceof CommandBlock) { +- BlockEntity blockEntity = this.level.getBlockEntity(blockPos); +- this.conditionMet = blockEntity instanceof CommandBlockEntity && ((CommandBlockEntity)blockEntity).getCommandBlock().getSuccessCount() > 0; ++ BlockPos blockposition = this.worldPosition.relative(((Direction) this.level.getBlockState(this.worldPosition).getValue(CommandBlock.FACING)).getOpposite()); ++ ++ if (this.level.getBlockState(blockposition).getBlock() instanceof CommandBlock) { ++ BlockEntity tileentity = this.level.getBlockEntity(blockposition); ++ ++ this.conditionMet = tileentity instanceof CommandBlockEntity && ((CommandBlockEntity) tileentity).getCommandBlock().getSuccessCount() > 0; + } else { + this.conditionMet = false; + } +@@ -147,25 +156,22 @@ + return this.conditionMet; + } + +- public CommandBlockEntity.Mode getMode() { +- BlockState blockState = this.getBlockState(); +- if (blockState.is(Blocks.COMMAND_BLOCK)) { +- return CommandBlockEntity.Mode.REDSTONE; +- } else if (blockState.is(Blocks.REPEATING_COMMAND_BLOCK)) { +- return CommandBlockEntity.Mode.AUTO; +- } else { +- return blockState.is(Blocks.CHAIN_COMMAND_BLOCK) ? CommandBlockEntity.Mode.SEQUENCE : CommandBlockEntity.Mode.REDSTONE; +- } ++ public CommandBlockEntity.Type getMode() { ++ IBlockData iblockdata = this.getBlockState(); ++ ++ return iblockdata.is(Blocks.COMMAND_BLOCK) ? CommandBlockEntity.Type.REDSTONE : (iblockdata.is(Blocks.REPEATING_COMMAND_BLOCK) ? CommandBlockEntity.Type.AUTO : (iblockdata.is(Blocks.CHAIN_COMMAND_BLOCK) ? CommandBlockEntity.Type.SEQUENCE : CommandBlockEntity.Type.REDSTONE)); + } + + public boolean isConditional() { +- BlockState blockState = this.level.getBlockState(this.getBlockPos()); +- return blockState.getBlock() instanceof CommandBlock && blockState.getValue(CommandBlock.CONDITIONAL); ++ IBlockData iblockdata = this.level.getBlockState(this.getBlockPos()); ++ ++ return iblockdata.getBlock() instanceof CommandBlock ? (Boolean) iblockdata.getValue(CommandBlock.CONDITIONAL) : false; + } + +- public static enum Mode { +- SEQUENCE, +- AUTO, +- REDSTONE; ++ public static enum Type { ++ ++ SEQUENCE, AUTO, REDSTONE; ++ ++ private Type() {} + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/ConduitBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/ConduitBlockEntity.java.patch new file mode 100644 index 0000000000..a92dfff4d6 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/ConduitBlockEntity.java.patch @@ -0,0 +1,374 @@ +--- a/net/minecraft/world/level/block/entity/ConduitBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/ConduitBlockEntity.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.block.entity; + + import com.google.common.collect.Lists; ++import java.util.Iterator; + import java.util.List; + import java.util.UUID; + import javax.annotation.Nullable; +@@ -17,16 +18,21 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.monster.Enemy; ++import net.minecraft.world.entity.monster.IMonster; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class ConduitBlockEntity extends BlockEntity { ++ + private static final int BLOCK_REFRESH_RATE = 2; + private static final int EFFECT_DURATION = 13; + private static final float ROTATION_SPEED = -0.0375F; +@@ -45,7 +51,7 @@ + private UUID destroyTargetUUID; + private long nextAmbientSoundActivation; + +- public ConduitBlockEntity(BlockPos pos, BlockState blockState) { ++ public ConduitBlockEntity(BlockPos pos, IBlockData blockState) { + super(BlockEntityType.CONDUIT, pos, blockState); + } + +@@ -57,6 +63,7 @@ + } else { + this.destroyTargetUUID = null; + } ++ + } + + @Override +@@ -65,6 +72,7 @@ + if (this.destroyTarget != null) { + tag.putUUID("Target", this.destroyTarget.getUUID()); + } ++ + } + + @Override +@@ -77,11 +85,12 @@ + return this.saveWithoutMetadata(); + } + +- public static void clientTick(Level level, BlockPos pos, BlockState state, ConduitBlockEntity blockEntity) { +- blockEntity.tickCount++; +- long gameTime = level.getGameTime(); ++ public static void clientTick(Level level, BlockPos pos, IBlockData state, ConduitBlockEntity blockEntity) { ++ ++blockEntity.tickCount; ++ long i = level.getGameTime(); + List list = blockEntity.effectBlocks; +- if (gameTime % 40L == 0L) { ++ ++ if (i % 40L == 0L) { + blockEntity.isActive = updateShape(level, pos, list); + updateHunting(blockEntity, list); + } +@@ -89,19 +98,23 @@ + updateClientTarget(level, pos, blockEntity); + animationTick(level, pos, list, blockEntity.destroyTarget, blockEntity.tickCount); + if (blockEntity.isActive()) { +- blockEntity.activeRotation++; ++ ++blockEntity.activeRotation; + } ++ + } + +- public static void serverTick(Level level, BlockPos pos, BlockState state, ConduitBlockEntity blockEntity) { +- blockEntity.tickCount++; +- long gameTime = level.getGameTime(); ++ public static void serverTick(Level level, BlockPos pos, IBlockData state, ConduitBlockEntity blockEntity) { ++ ++blockEntity.tickCount; ++ long i = level.getGameTime(); + List list = blockEntity.effectBlocks; +- if (gameTime % 40L == 0L) { ++ ++ if (i % 40L == 0L) { + boolean flag = updateShape(level, pos, list); ++ + if (flag != blockEntity.isActive) { +- SoundEvent soundEvent = flag ? SoundEvents.CONDUIT_ACTIVATE : SoundEvents.CONDUIT_DEACTIVATE; +- level.playSound(null, pos, soundEvent, SoundSource.BLOCKS, 1.0F, 1.0F); ++ SoundEvent soundeffect = flag ? SoundEvents.CONDUIT_ACTIVATE : SoundEvents.CONDUIT_DEACTIVATE; ++ ++ level.playSound((Player) null, pos, soundeffect, SoundSource.BLOCKS, 1.0F, 1.0F); + } + + blockEntity.isActive = flag; +@@ -113,15 +126,16 @@ + } + + if (blockEntity.isActive()) { +- if (gameTime % 80L == 0L) { +- level.playSound(null, pos, SoundEvents.CONDUIT_AMBIENT, SoundSource.BLOCKS, 1.0F, 1.0F); ++ if (i % 80L == 0L) { ++ level.playSound((Player) null, pos, SoundEvents.CONDUIT_AMBIENT, SoundSource.BLOCKS, 1.0F, 1.0F); + } + +- if (gameTime > blockEntity.nextAmbientSoundActivation) { +- blockEntity.nextAmbientSoundActivation = gameTime + 60L + (long)level.getRandom().nextInt(40); +- level.playSound(null, pos, SoundEvents.CONDUIT_AMBIENT_SHORT, SoundSource.BLOCKS, 1.0F, 1.0F); ++ if (i > blockEntity.nextAmbientSoundActivation) { ++ blockEntity.nextAmbientSoundActivation = i + 60L + (long) level.getRandom().nextInt(40); ++ level.playSound((Player) null, pos, SoundEvents.CONDUIT_AMBIENT_SHORT, SoundSource.BLOCKS, 1.0F, 1.0F); + } + } ++ + } + + private static void updateHunting(ConduitBlockEntity blockEntity, List positions) { +@@ -131,31 +145,40 @@ + private static boolean updateShape(Level level, BlockPos pos, List positions) { + positions.clear(); + +- for (int i = -1; i <= 1; i++) { +- for (int i1 = -1; i1 <= 1; i1++) { +- for (int i2 = -1; i2 <= 1; i2++) { +- BlockPos blockPos = pos.offset(i, i1, i2); +- if (!level.isWaterAt(blockPos)) { ++ int i; ++ int j; ++ int k; ++ ++ for (i = -1; i <= 1; ++i) { ++ for (j = -1; j <= 1; ++j) { ++ for (k = -1; k <= 1; ++k) { ++ BlockPos blockposition1 = pos.offset(i, j, k); ++ ++ if (!level.isWaterAt(blockposition1)) { + return false; + } + } + } + } + +- for (int i = -2; i <= 2; i++) { +- for (int i1 = -2; i1 <= 2; i1++) { +- for (int i2x = -2; i2x <= 2; i2x++) { +- int abs = Math.abs(i); +- int abs1 = Math.abs(i1); +- int abs2 = Math.abs(i2x); +- if ((abs > 1 || abs1 > 1 || abs2 > 1) +- && (i == 0 && (abs1 == 2 || abs2 == 2) || i1 == 0 && (abs == 2 || abs2 == 2) || i2x == 0 && (abs == 2 || abs1 == 2))) { +- BlockPos blockPos1 = pos.offset(i, i1, i2x); +- BlockState blockState = level.getBlockState(blockPos1); ++ for (i = -2; i <= 2; ++i) { ++ for (j = -2; j <= 2; ++j) { ++ for (k = -2; k <= 2; ++k) { ++ int l = Math.abs(i); ++ int i1 = Math.abs(j); ++ int j1 = Math.abs(k); + +- for (Block block : VALID_BLOCKS) { +- if (blockState.is(block)) { +- positions.add(blockPos1); ++ if ((l > 1 || i1 > 1 || j1 > 1) && (i == 0 && (i1 == 2 || j1 == 2) || j == 0 && (l == 2 || j1 == 2) || k == 0 && (l == 2 || i1 == 2))) { ++ BlockPos blockposition2 = pos.offset(i, j, k); ++ IBlockData iblockdata = level.getBlockState(blockposition2); ++ Block[] ablock = ConduitBlockEntity.VALID_BLOCKS; ++ int k1 = ablock.length; ++ ++ for (int l1 = 0; l1 < k1; ++l1) { ++ Block block = ablock[l1]; ++ ++ if (iblockdata.is(block)) { ++ positions.add(blockposition2); + } + } + } +@@ -167,60 +190,63 @@ + } + + private static void applyEffects(Level level, BlockPos pos, List positions) { +- int size = positions.size(); +- int i = size / 7 * 16; +- int x = pos.getX(); +- int y = pos.getY(); +- int z = pos.getZ(); +- AABB aABB = new AABB((double)x, (double)y, (double)z, (double)(x + 1), (double)(y + 1), (double)(z + 1)) +- .inflate((double)i) +- .expandTowards(0.0, (double)level.getHeight(), 0.0); +- List entitiesOfClass = level.getEntitiesOfClass(Player.class, aABB); +- if (!entitiesOfClass.isEmpty()) { +- for (Player player : entitiesOfClass) { +- if (pos.closerThan(player.blockPosition(), (double)i) && player.isInWaterOrRain()) { +- player.addEffect(new MobEffectInstance(MobEffects.CONDUIT_POWER, 260, 0, true, true)); ++ int i = positions.size(); ++ int j = i / 7 * 16; ++ int k = pos.getX(); ++ int l = pos.getY(); ++ int i1 = pos.getZ(); ++ AABB axisalignedbb = (new AABB((double) k, (double) l, (double) i1, (double) (k + 1), (double) (l + 1), (double) (i1 + 1))).inflate((double) j).expandTowards(0.0D, (double) level.getHeight(), 0.0D); ++ List list1 = level.getEntitiesOfClass(Player.class, axisalignedbb); ++ ++ if (!list1.isEmpty()) { ++ Iterator iterator = list1.iterator(); ++ ++ while (iterator.hasNext()) { ++ Player entityhuman = (Player) iterator.next(); ++ ++ if (pos.closerThan(entityhuman.blockPosition(), (double) j) && entityhuman.isInWaterOrRain()) { ++ entityhuman.addEffect(new MobEffectInstance(MobEffects.CONDUIT_POWER, 260, 0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONDUIT); // CraftBukkit + } + } ++ + } + } + +- private static void updateDestroyTarget(Level level, BlockPos pos, BlockState state, List positions, ConduitBlockEntity blockEntity) { +- LivingEntity livingEntity = blockEntity.destroyTarget; +- int size = positions.size(); +- if (size < 42) { ++ private static void updateDestroyTarget(Level level, BlockPos pos, IBlockData state, List positions, ConduitBlockEntity blockEntity) { ++ LivingEntity entityliving = blockEntity.destroyTarget; ++ int i = positions.size(); ++ ++ if (i < 42) { + blockEntity.destroyTarget = null; + } else if (blockEntity.destroyTarget == null && blockEntity.destroyTargetUUID != null) { + blockEntity.destroyTarget = findDestroyTarget(level, pos, blockEntity.destroyTargetUUID); + blockEntity.destroyTargetUUID = null; + } else if (blockEntity.destroyTarget == null) { +- List entitiesOfClass = level.getEntitiesOfClass( +- LivingEntity.class, getDestroyRangeAABB(pos), collidedEntity -> collidedEntity instanceof Enemy && collidedEntity.isInWaterOrRain() +- ); +- if (!entitiesOfClass.isEmpty()) { +- blockEntity.destroyTarget = entitiesOfClass.get(level.random.nextInt(entitiesOfClass.size())); ++ List list1 = level.getEntitiesOfClass(LivingEntity.class, getDestroyRangeAABB(pos), (entityliving1) -> { ++ return entityliving1 instanceof IMonster && entityliving1.isInWaterOrRain(); ++ }); ++ ++ if (!list1.isEmpty()) { ++ blockEntity.destroyTarget = (LivingEntity) list1.get(level.random.nextInt(list1.size())); + } +- } else if (!blockEntity.destroyTarget.isAlive() || !pos.closerThan(blockEntity.destroyTarget.blockPosition(), 8.0)) { ++ } else if (!blockEntity.destroyTarget.isAlive() || !pos.closerThan(blockEntity.destroyTarget.blockPosition(), 8.0D)) { + blockEntity.destroyTarget = null; + } + + if (blockEntity.destroyTarget != null) { +- level.playSound( +- null, +- blockEntity.destroyTarget.getX(), +- blockEntity.destroyTarget.getY(), +- blockEntity.destroyTarget.getZ(), +- SoundEvents.CONDUIT_ATTACK_TARGET, +- SoundSource.BLOCKS, +- 1.0F, +- 1.0F +- ); +- blockEntity.destroyTarget.hurt(level.damageSources().magic(), 4.0F); ++ // CraftBukkit start ++ CraftEventFactory.blockDamage = CraftBlock.at(level, pos); ++ if (blockEntity.destroyTarget.hurt(level.damageSources().magic(), 4.0F)) { ++ level.playSound((Player) null, blockEntity.destroyTarget.getX(), blockEntity.destroyTarget.getY(), blockEntity.destroyTarget.getZ(), SoundEvents.CONDUIT_ATTACK_TARGET, SoundSource.BLOCKS, 1.0F, 1.0F); ++ } ++ CraftEventFactory.blockDamage = null; ++ // CraftBukkit end + } + +- if (livingEntity != blockEntity.destroyTarget) { ++ if (entityliving != blockEntity.destroyTarget) { + level.sendBlockUpdated(pos, state, state, 2); + } ++ + } + + private static void updateClientTarget(Level level, BlockPos pos, ConduitBlockEntity blockEntity) { +@@ -232,47 +258,61 @@ + blockEntity.destroyTargetUUID = null; + } + } ++ + } + + private static AABB getDestroyRangeAABB(BlockPos pos) { +- int x = pos.getX(); +- int y = pos.getY(); +- int z = pos.getZ(); +- return new AABB((double)x, (double)y, (double)z, (double)(x + 1), (double)(y + 1), (double)(z + 1)).inflate(8.0); ++ int i = pos.getX(); ++ int j = pos.getY(); ++ int k = pos.getZ(); ++ ++ return (new AABB((double) i, (double) j, (double) k, (double) (i + 1), (double) (j + 1), (double) (k + 1))).inflate(8.0D); + } + + @Nullable + private static LivingEntity findDestroyTarget(Level level, BlockPos pos, UUID targetId) { +- List entitiesOfClass = level.getEntitiesOfClass( +- LivingEntity.class, getDestroyRangeAABB(pos), collidedEntity -> collidedEntity.getUUID().equals(targetId) +- ); +- return entitiesOfClass.size() == 1 ? entitiesOfClass.get(0) : null; ++ List list = level.getEntitiesOfClass(LivingEntity.class, getDestroyRangeAABB(pos), (entityliving) -> { ++ return entityliving.getUUID().equals(targetId); ++ }); ++ ++ return list.size() == 1 ? (LivingEntity) list.get(0) : null; + } + + private static void animationTick(Level level, BlockPos pos, List positions, @Nullable Entity entity, int tickCount) { +- RandomSource randomSource = level.random; +- double d = (double)(Mth.sin((float)(tickCount + 35) * 0.1F) / 2.0F + 0.5F); +- d = (d * d + d) * 0.3F; +- Vec3 vec3 = new Vec3((double)pos.getX() + 0.5, (double)pos.getY() + 1.5 + d, (double)pos.getZ() + 0.5); ++ RandomSource randomsource = level.random; ++ double d0 = (double) (Mth.sin((float) (tickCount + 35) * 0.1F) / 2.0F + 0.5F); + +- for (BlockPos blockPos : positions) { +- if (randomSource.nextInt(50) == 0) { +- BlockPos blockPos1 = blockPos.subtract(pos); +- float f = -0.5F + randomSource.nextFloat() + (float)blockPos1.getX(); +- float f1 = -2.0F + randomSource.nextFloat() + (float)blockPos1.getY(); +- float f2 = -0.5F + randomSource.nextFloat() + (float)blockPos1.getZ(); +- level.addParticle(ParticleTypes.NAUTILUS, vec3.x, vec3.y, vec3.z, (double)f, (double)f1, (double)f2); ++ d0 = (d0 * d0 + d0) * 0.30000001192092896D; ++ Vec3 vec3d = new Vec3((double) pos.getX() + 0.5D, (double) pos.getY() + 1.5D + d0, (double) pos.getZ() + 0.5D); ++ Iterator iterator = positions.iterator(); ++ ++ float f; ++ ++ while (iterator.hasNext()) { ++ BlockPos blockposition1 = (BlockPos) iterator.next(); ++ ++ if (randomsource.nextInt(50) == 0) { ++ BlockPos blockposition2 = blockposition1.subtract(pos); ++ ++ f = -0.5F + randomsource.nextFloat() + (float) blockposition2.getX(); ++ float f1 = -2.0F + randomsource.nextFloat() + (float) blockposition2.getY(); ++ float f2 = -0.5F + randomsource.nextFloat() + (float) blockposition2.getZ(); ++ ++ level.addParticle(ParticleTypes.NAUTILUS, vec3d.x, vec3d.y, vec3d.z, (double) f, (double) f1, (double) f2); + } + } + + if (entity != null) { +- Vec3 vec31 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); +- float f3 = (-0.5F + randomSource.nextFloat()) * (3.0F + entity.getBbWidth()); +- float f4 = -1.0F + randomSource.nextFloat() * entity.getBbHeight(); +- float f = (-0.5F + randomSource.nextFloat()) * (3.0F + entity.getBbWidth()); +- Vec3 vec32 = new Vec3((double)f3, (double)f4, (double)f); +- level.addParticle(ParticleTypes.NAUTILUS, vec31.x, vec31.y, vec31.z, vec32.x, vec32.y, vec32.z); ++ Vec3 vec3d1 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); ++ float f3 = (-0.5F + randomsource.nextFloat()) * (3.0F + entity.getBbWidth()); ++ float f4 = -1.0F + randomsource.nextFloat() * entity.getBbHeight(); ++ ++ f = (-0.5F + randomsource.nextFloat()) * (3.0F + entity.getBbWidth()); ++ Vec3 vec3d2 = new Vec3((double) f3, (double) f4, (double) f); ++ ++ level.addParticle(ParticleTypes.NAUTILUS, vec3d1.x, vec3d1.y, vec3d1.z, vec3d2.x, vec3d2.y, vec3d2.z); + } ++ + } + + public boolean isActive() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java.patch new file mode 100644 index 0000000000..aa06d65641 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java.patch @@ -0,0 +1,166 @@ +--- a/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java ++++ b/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java +@@ -1,90 +1,131 @@ + package net.minecraft.world.level.block.entity; + + import net.minecraft.core.BlockPos; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.entity.EntityTypeTest; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; + + public abstract class ContainerOpenersCounter { ++ + private static final int CHECK_TICK_DELAY = 5; + private int openCount; ++ public boolean opened; // CraftBukkit + +- protected abstract void onOpen(Level level, BlockPos pos, BlockState state); ++ public ContainerOpenersCounter() {} + +- protected abstract void onClose(Level level, BlockPos pos, BlockState state); ++ protected abstract void onOpen(Level level, BlockPos pos, IBlockData state); + +- protected abstract void openerCountChanged(Level level, BlockPos pos, BlockState state, int count, int openCount); ++ protected abstract void onClose(Level level, BlockPos pos, IBlockData state); + ++ protected abstract void openerCountChanged(Level level, BlockPos pos, IBlockData state, int count, int openCount); ++ ++ // CraftBukkit start ++ public void onAPIOpen(Level world, BlockPos blockposition, IBlockData iblockdata) { ++ onOpen(world, blockposition, iblockdata); ++ } ++ ++ public void onAPIClose(Level world, BlockPos blockposition, IBlockData iblockdata) { ++ onClose(world, blockposition, iblockdata); ++ } ++ ++ public void openerAPICountChanged(Level world, BlockPos blockposition, IBlockData iblockdata, int i, int j) { ++ openerCountChanged(world, blockposition, iblockdata, i, j); ++ } ++ // CraftBukkit end ++ + protected abstract boolean isOwnContainer(Player player); + +- public void incrementOpeners(Player player, Level level, BlockPos pos, BlockState state) { ++ public void incrementOpeners(Player player, Level level, BlockPos pos, IBlockData state) { ++ int oldPower = Math.max(0, Math.min(15, this.openCount)); // CraftBukkit - Get power before new viewer is added + int i = this.openCount++; ++ ++ // CraftBukkit start - Call redstone event ++ if (level.getBlockState(pos).is(net.minecraft.world.level.block.Blocks.TRAPPED_CHEST)) { ++ int newPower = Math.max(0, Math.min(15, this.openCount)); ++ ++ if (oldPower != newPower) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(level, pos, oldPower, newPower); ++ } ++ } ++ // CraftBukkit end ++ + if (i == 0) { + this.onOpen(level, pos, state); +- level.gameEvent(player, GameEvent.CONTAINER_OPEN, pos); ++ level.gameEvent((Entity) player, GameEvent.CONTAINER_OPEN, pos); + scheduleRecheck(level, pos, state); + } + + this.openerCountChanged(level, pos, state, i, this.openCount); + } + +- public void decrementOpeners(Player player, Level level, BlockPos pos, BlockState state) { ++ public void decrementOpeners(Player player, Level level, BlockPos pos, IBlockData state) { ++ int oldPower = Math.max(0, Math.min(15, this.openCount)); // CraftBukkit - Get power before new viewer is added + int i = this.openCount--; ++ ++ // CraftBukkit start - Call redstone event ++ if (level.getBlockState(pos).is(net.minecraft.world.level.block.Blocks.TRAPPED_CHEST)) { ++ int newPower = Math.max(0, Math.min(15, this.openCount)); ++ ++ if (oldPower != newPower) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(level, pos, oldPower, newPower); ++ } ++ } ++ // CraftBukkit end ++ + if (this.openCount == 0) { + this.onClose(level, pos, state); +- level.gameEvent(player, GameEvent.CONTAINER_CLOSE, pos); ++ level.gameEvent((Entity) player, GameEvent.CONTAINER_CLOSE, pos); + } + + this.openerCountChanged(level, pos, state, i, this.openCount); + } + + private int getOpenCount(Level level, BlockPos pos) { +- int x = pos.getX(); +- int y = pos.getY(); +- int z = pos.getZ(); ++ int i = pos.getX(); ++ int j = pos.getY(); ++ int k = pos.getZ(); + float f = 5.0F; +- AABB aABB = new AABB( +- (double)((float)x - 5.0F), +- (double)((float)y - 5.0F), +- (double)((float)z - 5.0F), +- (double)((float)(x + 1) + 5.0F), +- (double)((float)(y + 1) + 5.0F), +- (double)((float)(z + 1) + 5.0F) +- ); +- return level.getEntities(EntityTypeTest.forClass(Player.class), aABB, this::isOwnContainer).size(); ++ AABB axisalignedbb = new AABB((double) ((float) i - 5.0F), (double) ((float) j - 5.0F), (double) ((float) k - 5.0F), (double) ((float) (i + 1) + 5.0F), (double) ((float) (j + 1) + 5.0F), (double) ((float) (k + 1) + 5.0F)); ++ ++ return level.getEntities(EntityTypeTest.forClass(Player.class), axisalignedbb, this::isOwnContainer).size(); + } + +- public void recheckOpeners(Level level, BlockPos pos, BlockState state) { +- int openCount = this.getOpenCount(level, pos); +- int i = this.openCount; +- if (i != openCount) { +- boolean flag = openCount != 0; +- boolean flag1 = i != 0; ++ public void recheckOpeners(Level level, BlockPos pos, IBlockData state) { ++ int i = this.getOpenCount(level, pos); ++ if (opened) i++; // CraftBukkit - add dummy count from API ++ int j = this.openCount; ++ ++ if (j != i) { ++ boolean flag = i != 0; ++ boolean flag1 = j != 0; ++ + if (flag && !flag1) { + this.onOpen(level, pos, state); +- level.gameEvent(null, GameEvent.CONTAINER_OPEN, pos); ++ level.gameEvent((Entity) null, GameEvent.CONTAINER_OPEN, pos); + } else if (!flag) { + this.onClose(level, pos, state); +- level.gameEvent(null, GameEvent.CONTAINER_CLOSE, pos); ++ level.gameEvent((Entity) null, GameEvent.CONTAINER_CLOSE, pos); + } + +- this.openCount = openCount; ++ this.openCount = i; + } + +- this.openerCountChanged(level, pos, state, i, openCount); +- if (openCount > 0) { ++ this.openerCountChanged(level, pos, state, j, i); ++ if (i > 0) { + scheduleRecheck(level, pos, state); + } ++ + } + + public int getOpenerCount() { + return this.openCount; + } + +- private static void scheduleRecheck(Level level, BlockPos pos, BlockState state) { ++ private static void scheduleRecheck(Level level, BlockPos pos, IBlockData state) { + level.scheduleTick(pos, state.getBlock(), 5); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/CrafterBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/CrafterBlockEntity.java.patch new file mode 100644 index 0000000000..77565b9cdf --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/CrafterBlockEntity.java.patch @@ -0,0 +1,330 @@ +--- a/net/minecraft/world/level/block/entity/CrafterBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/CrafterBlockEntity.java +@@ -2,7 +2,8 @@ + + import com.google.common.annotations.VisibleForTesting; + import it.unimi.dsi.fastutil.ints.IntArrayList; +-import it.unimi.dsi.fastutil.ints.IntList; ++import java.util.Iterator; ++import java.util.List; + import net.minecraft.core.BlockPos; + import net.minecraft.core.NonNullList; + import net.minecraft.nbt.CompoundTag; +@@ -14,13 +15,20 @@ + import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.inventory.ContainerData; + import net.minecraft.world.inventory.CrafterMenu; +-import net.minecraft.world.inventory.CraftingContainer; ++import net.minecraft.world.inventory.InventoryCrafting; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.CrafterBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + +-public class CrafterBlockEntity extends RandomizableContainerBlockEntity implements CraftingContainer { ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ ++public class CrafterBlockEntity extends RandomizableContainerBlockEntity implements InventoryCrafting { ++ + public static final int CONTAINER_WIDTH = 3; + public static final int CONTAINER_HEIGHT = 3; + public static final int CONTAINER_SIZE = 9; +@@ -28,34 +36,78 @@ + public static final int SLOT_ENABLED = 0; + public static final int DATA_TRIGGERED = 9; + public static final int NUM_DATA = 10; +- private NonNullList items = NonNullList.withSize(9, ItemStack.EMPTY); +- private int craftingTicksRemaining = 0; +- protected final ContainerData containerData = new ContainerData() { +- private final int[] slotStates = new int[9]; +- private int triggered = 0; ++ private NonNullList items; ++ public int craftingTicksRemaining; ++ protected final ContainerData containerData; ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList<>(); ++ private int maxStack = 1; + +- @Override +- public int get(int index) { +- return index == 9 ? this.triggered : this.slotStates[index]; +- } ++ @Override ++ public List getContents() { ++ return this.items; ++ } + +- @Override +- public void set(int index, int value) { +- if (index == 9) { +- this.triggered = value; +- } else { +- this.slotStates[index] = value; ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ @Override ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ } ++ // CraftBukkit end ++ ++ public CrafterBlockEntity(BlockPos blockposition, IBlockData iblockdata) { ++ super(BlockEntityType.CRAFTER, blockposition, iblockdata); ++ this.items = NonNullList.withSize(9, ItemStack.EMPTY); ++ this.craftingTicksRemaining = 0; ++ this.containerData = new ContainerData() { ++ private final int[] slotStates = new int[9]; ++ private int triggered = 0; ++ ++ @Override ++ public int get(int index) { ++ return index == 9 ? this.triggered : this.slotStates[index]; + } +- } + +- @Override +- public int getCount() { +- return 10; +- } +- }; ++ @Override ++ public void set(int index, int value) { ++ if (index == 9) { ++ this.triggered = value; ++ } else { ++ this.slotStates[index] = value; ++ } + +- public CrafterBlockEntity(BlockPos pos, BlockState blockState) { +- super(BlockEntityType.CRAFTER, pos, blockState); ++ } ++ ++ @Override ++ public int getCount() { ++ return 10; ++ } ++ }; + } + + @Override +@@ -76,7 +128,7 @@ + } + + public boolean isSlotDisabled(int i) { +- return i >= 0 && i < 9 && this.containerData.get(i) == 1; ++ return i >= 0 && i < 9 ? this.containerData.get(i) == 1 : false; + } + + @Override +@@ -84,17 +136,19 @@ + if (this.containerData.get(index) == 1) { + return false; + } else { +- ItemStack itemStack = this.items.get(index); +- int count = itemStack.getCount(); +- return count < itemStack.getMaxStackSize() && (itemStack.isEmpty() || !this.smallerStackExist(count, itemStack, index)); ++ ItemStack itemstack1 = (ItemStack) this.items.get(index); ++ int j = itemstack1.getCount(); ++ ++ return j >= itemstack1.getMaxStackSize() ? false : (itemstack1.isEmpty() ? true : !this.smallerStackExist(j, itemstack1, index)); + } + } + +- private boolean smallerStackExist(int i, ItemStack itemStack, int i1) { +- for (int i2 = i1 + 1; i2 < 9; i2++) { +- if (!this.isSlotDisabled(i2)) { +- ItemStack item = this.getItem(i2); +- if (item.isEmpty() || item.getCount() < i && ItemStack.isSameItemSameTags(item, itemStack)) { ++ private boolean smallerStackExist(int i, ItemStack itemstack, int j) { ++ for (int k = j + 1; k < 9; ++k) { ++ if (!this.isSlotDisabled(k)) { ++ ItemStack itemstack1 = this.getItem(k); ++ ++ if (itemstack1.isEmpty() || itemstack1.getCount() < i && ItemStack.isSameItemSameTags(itemstack1, itemstack)) { + return true; + } + } +@@ -112,15 +166,20 @@ + ContainerHelper.loadAllItems(tag, this.items); + } + +- int[] intArray = tag.getIntArray("disabled_slots"); ++ int[] aint = tag.getIntArray("disabled_slots"); + +- for (int i = 0; i < 9; i++) { ++ for (int i = 0; i < 9; ++i) { + this.containerData.set(i, 0); + } + +- for (int i1 : intArray) { +- if (this.slotCanBeDisabled(i1)) { +- this.containerData.set(i1, 1); ++ int[] aint1 = aint; ++ int j = aint.length; ++ ++ for (int k = 0; k < j; ++k) { ++ int l = aint1[k]; ++ ++ if (this.slotCanBeDisabled(l)) { ++ this.containerData.set(l, 1); + } + } + +@@ -146,18 +205,24 @@ + + @Override + public boolean isEmpty() { +- for (ItemStack itemStack : this.items) { +- if (!itemStack.isEmpty()) { +- return false; ++ Iterator iterator = this.items.iterator(); ++ ++ ItemStack itemstack; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return true; + } +- } + +- return true; ++ itemstack = (ItemStack) iterator.next(); ++ } while (itemstack.isEmpty()); ++ ++ return false; + } + + @Override + public ItemStack getItem(int slot) { +- return this.items.get(slot); ++ return (ItemStack) this.items.get(slot); + } + + @Override +@@ -171,12 +236,7 @@ + + @Override + public boolean stillValid(Player player) { +- return this.level != null +- && this.level.getBlockEntity(this.worldPosition) == this +- && !( +- player.distanceToSqr((double)this.worldPosition.getX() + 0.5, (double)this.worldPosition.getY() + 0.5, (double)this.worldPosition.getZ() + 0.5) +- > 64.0 +- ); ++ return this.level != null && this.level.getBlockEntity(this.worldPosition) == this ? player.distanceToSqr((double) this.worldPosition.getX() + 0.5D, (double) this.worldPosition.getY() + 0.5D, (double) this.worldPosition.getZ() + 0.5D) <= 64.0D : false; + } + + @Override +@@ -201,25 +261,30 @@ + + @Override + public void fillStackedContents(StackedContents contents) { +- for (ItemStack itemStack : this.items) { +- contents.accountSimpleStack(itemStack); ++ Iterator iterator = this.items.iterator(); ++ ++ while (iterator.hasNext()) { ++ ItemStack itemstack = (ItemStack) iterator.next(); ++ ++ contents.accountSimpleStack(itemstack); + } ++ + } + +- private void addDisabledSlots(CompoundTag compoundTag) { +- IntList list = new IntArrayList(); ++ private void addDisabledSlots(CompoundTag nbttagcompound) { ++ IntArrayList intarraylist = new IntArrayList(); + +- for (int i = 0; i < 9; i++) { ++ for (int i = 0; i < 9; ++i) { + if (this.isSlotDisabled(i)) { +- list.add(i); ++ intarraylist.add(i); + } + } + +- compoundTag.putIntArray("disabled_slots", list); ++ nbttagcompound.putIntArray("disabled_slots", (List) intarraylist); + } + +- private void addTriggered(CompoundTag compoundTag) { +- compoundTag.putInt("triggered", this.containerData.get(9)); ++ private void addTriggered(CompoundTag nbttagcompound) { ++ nbttagcompound.putInt("triggered", this.containerData.get(9)); + } + + public void setTriggered(boolean flag) { +@@ -231,13 +296,15 @@ + return this.containerData.get(9) == 1; + } + +- public static void serverTick(Level level, BlockPos blockPos, BlockState blockState, CrafterBlockEntity crafterBlockEntity) { +- int i = crafterBlockEntity.craftingTicksRemaining - 1; ++ public static void serverTick(Level world, BlockPos blockposition, IBlockData iblockdata, CrafterBlockEntity crafterblockentity) { ++ int i = crafterblockentity.craftingTicksRemaining - 1; ++ + if (i >= 0) { +- crafterBlockEntity.craftingTicksRemaining = i; ++ crafterblockentity.craftingTicksRemaining = i; + if (i == 0) { +- level.setBlock(blockPos, blockState.setValue(CrafterBlock.CRAFTING, Boolean.valueOf(false)), 3); ++ world.setBlock(blockposition, (IBlockData) iblockdata.setValue(CrafterBlock.CRAFTING, false), 3); + } ++ + } + } + +@@ -248,10 +315,11 @@ + public int getRedstoneSignal() { + int i = 0; + +- for (int i1 = 0; i1 < this.getContainerSize(); i1++) { +- ItemStack item = this.getItem(i1); +- if (!item.isEmpty() || this.isSlotDisabled(i1)) { +- i++; ++ for (int j = 0; j < this.getContainerSize(); ++j) { ++ ItemStack itemstack = this.getItem(j); ++ ++ if (!itemstack.isEmpty() || this.isSlotDisabled(j)) { ++ ++i; + } + } + +@@ -259,6 +327,6 @@ + } + + private boolean slotCanBeDisabled(int i) { +- return i > -1 && i < 9 && this.items.get(i).isEmpty(); ++ return i > -1 && i < 9 && ((ItemStack) this.items.get(i)).isEmpty(); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java.patch new file mode 100644 index 0000000000..fa39db8cf8 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java.patch @@ -0,0 +1,278 @@ +--- a/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java +@@ -12,29 +12,83 @@ + import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.world.RandomizableContainer; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.BlockItem; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.ticks.ContainerSingleItem; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class DecoratedPotBlockEntity extends BlockEntity implements RandomizableContainer, ContainerSingleItem { ++ ++ // CraftBukkit start - add fields and methods ++ public List transaction = new ArrayList<>(); ++ private int maxStack = MAX_STACK; ++ ++ @Override ++ public List getContents() { ++ return Arrays.asList(this.item); ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ @Override ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return CraftLocation.toBukkit(worldPosition, level.getWorld()); ++ } ++ // CraftBukkit end ++ + public static final String TAG_SHERDS = "sherds"; + public static final String TAG_ITEM = "item"; + public static final int EVENT_POT_WOBBLES = 1; + public long wobbleStartedAtTick; + @Nullable +- public DecoratedPotBlockEntity.WobbleStyle lastWobbleStyle; +- private DecoratedPotBlockEntity.Decorations decorations; +- private ItemStack item = ItemStack.EMPTY; ++ public DecoratedPotBlockEntity.b lastWobbleStyle; ++ public DecoratedPotBlockEntity.Decorations decorations; ++ private ItemStack item; + @Nullable + protected ResourceLocation lootTable; + protected long lootTableSeed; + +- public DecoratedPotBlockEntity(BlockPos pos, BlockState state) { ++ public DecoratedPotBlockEntity(BlockPos pos, IBlockData state) { + super(BlockEntityType.DECORATED_POT, pos, state); ++ this.item = ItemStack.EMPTY; + this.decorations = DecoratedPotBlockEntity.Decorations.EMPTY; + } + +@@ -45,6 +99,7 @@ + if (!this.trySaveLootTable(tag) && !this.item.isEmpty()) { + tag.put("item", this.item.save(new CompoundTag())); + } ++ + } + + @Override +@@ -58,6 +113,7 @@ + this.item = ItemStack.EMPTY; + } + } ++ + } + + @Override +@@ -71,7 +127,7 @@ + } + + public Direction getDirection() { +- return this.getBlockState().getValue(BlockStateProperties.HORIZONTAL_FACING); ++ return (Direction) this.getBlockState().getValue(BlockStateProperties.HORIZONTAL_FACING); + } + + public DecoratedPotBlockEntity.Decorations getDecorations() { +@@ -86,11 +142,12 @@ + return createDecoratedPotItem(this.decorations); + } + +- public static ItemStack createDecoratedPotItem(DecoratedPotBlockEntity.Decorations decorations) { +- ItemStack defaultInstance = Items.DECORATED_POT.getDefaultInstance(); +- CompoundTag compoundTag = decorations.save(new CompoundTag()); +- BlockItem.setBlockEntityData(defaultInstance, BlockEntityType.DECORATED_POT, compoundTag); +- return defaultInstance; ++ public static ItemStack createDecoratedPotItem(DecoratedPotBlockEntity.Decorations decoratedpotblockentity_decoration) { ++ ItemStack itemstack = Items.DECORATED_POT.getDefaultInstance(); ++ CompoundTag nbttagcompound = decoratedpotblockentity_decoration.save(new CompoundTag()); ++ ++ BlockItem.setBlockEntityData(itemstack, BlockEntityType.DECORATED_POT, nbttagcompound); ++ return itemstack; + } + + @Nullable +@@ -100,8 +157,8 @@ + } + + @Override +- public void setLootTable(@Nullable ResourceLocation resourceLocation) { +- this.lootTable = resourceLocation; ++ public void setLootTable(@Nullable ResourceLocation minecraftkey) { ++ this.lootTable = minecraftkey; + } + + @Override +@@ -110,31 +167,32 @@ + } + + @Override +- public void setLootTableSeed(long l) { +- this.lootTableSeed = l; ++ public void setLootTableSeed(long i) { ++ this.lootTableSeed = i; + } + + @Override + public ItemStack getTheItem() { +- this.unpackLootTable(null); ++ this.unpackLootTable((Player) null); + return this.item; + } + + @Override + public ItemStack splitTheItem(int i) { +- this.unpackLootTable(null); +- ItemStack itemStack = this.item.split(i); ++ this.unpackLootTable((Player) null); ++ ItemStack itemstack = this.item.split(i); ++ + if (this.item.isEmpty()) { + this.item = ItemStack.EMPTY; + } + +- return itemStack; ++ return itemstack; + } + + @Override +- public void setTheItem(ItemStack itemStack) { +- this.unpackLootTable(null); +- this.item = itemStack; ++ public void setTheItem(ItemStack itemstack) { ++ this.unpackLootTable((Player) null); ++ this.item = itemstack; + } + + @Override +@@ -142,17 +200,17 @@ + return this; + } + +- public void wobble(DecoratedPotBlockEntity.WobbleStyle wobbleStyle) { ++ public void wobble(DecoratedPotBlockEntity.b decoratedpotblockentity_b) { + if (this.level != null && !this.level.isClientSide()) { +- this.level.blockEvent(this.getBlockPos(), this.getBlockState().getBlock(), 1, wobbleStyle.ordinal()); ++ this.level.blockEvent(this.getBlockPos(), this.getBlockState().getBlock(), 1, decoratedpotblockentity_b.ordinal()); + } + } + + @Override + public boolean triggerEvent(int id, int type) { +- if (this.level != null && id == 1 && type >= 0 && type < DecoratedPotBlockEntity.WobbleStyle.values().length) { ++ if (this.level != null && id == 1 && type >= 0 && type < DecoratedPotBlockEntity.b.values().length) { + this.wobbleStartedAtTick = this.level.getGameTime(); +- this.lastWobbleStyle = DecoratedPotBlockEntity.WobbleStyle.values()[type]; ++ this.lastWobbleStyle = DecoratedPotBlockEntity.b.values()[type]; + return true; + } else { + return super.triggerEvent(id, type); +@@ -160,17 +218,19 @@ + } + + public static record Decorations(Item back, Item left, Item right, Item front) { +- public static final DecoratedPotBlockEntity.Decorations EMPTY = new DecoratedPotBlockEntity.Decorations( +- Items.BRICK, Items.BRICK, Items.BRICK, Items.BRICK +- ); + ++ public static final DecoratedPotBlockEntity.Decorations EMPTY = new DecoratedPotBlockEntity.Decorations(Items.BRICK, Items.BRICK, Items.BRICK, Items.BRICK); ++ + public CompoundTag save(CompoundTag tag) { +- if (this.equals(EMPTY)) { ++ if (this.equals(DecoratedPotBlockEntity.Decorations.EMPTY)) { + return tag; + } else { +- ListTag list = new ListTag(); +- this.sorted().forEach(item -> list.add(StringTag.valueOf(BuiltInRegistries.ITEM.getKey(item).toString()))); +- tag.put("sherds", list); ++ ListTag nbttaglist = new ListTag(); ++ ++ this.sorted().forEach((item) -> { ++ nbttaglist.add(StringTag.valueOf(BuiltInRegistries.ITEM.getKey(item).toString())); ++ }); ++ tag.put("sherds", nbttaglist); + return tag; + } + } +@@ -181,10 +241,11 @@ + + public static DecoratedPotBlockEntity.Decorations load(@Nullable CompoundTag tag) { + if (tag != null && tag.contains("sherds", 9)) { +- ListTag list = tag.getList("sherds", 8); +- return new DecoratedPotBlockEntity.Decorations(itemFromTag(list, 0), itemFromTag(list, 1), itemFromTag(list, 2), itemFromTag(list, 3)); ++ ListTag nbttaglist = tag.getList("sherds", 8); ++ ++ return new DecoratedPotBlockEntity.Decorations(itemFromTag(nbttaglist, 0), itemFromTag(nbttaglist, 1), itemFromTag(nbttaglist, 2), itemFromTag(nbttaglist, 3)); + } else { +- return EMPTY; ++ return DecoratedPotBlockEntity.Decorations.EMPTY; + } + } + +@@ -192,19 +253,20 @@ + if (index >= tag.size()) { + return Items.BRICK; + } else { +- Tag tag1 = tag.get(index); +- return BuiltInRegistries.ITEM.get(ResourceLocation.tryParse(tag1.getAsString())); ++ Tag nbtbase = tag.get(index); ++ ++ return (Item) BuiltInRegistries.ITEM.get(ResourceLocation.tryParse(nbtbase.getAsString())); + } + } + } + +- public static enum WobbleStyle { +- POSITIVE(7), +- NEGATIVE(10); ++ public static enum b { + ++ POSITIVE(7), NEGATIVE(10); ++ + public final int duration; + +- private WobbleStyle(int i) { ++ private b(int i) { + this.duration = i; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/DispenserBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/DispenserBlockEntity.java.patch new file mode 100644 index 0000000000..e781d1acda --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/DispenserBlockEntity.java.patch @@ -0,0 +1,112 @@ +--- a/net/minecraft/world/level/block/entity/DispenserBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/DispenserBlockEntity.java +@@ -7,20 +7,59 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.world.ContainerHelper; + import net.minecraft.world.entity.player.Inventory; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.inventory.DispenserMenu; + import net.minecraft.world.item.ItemStack; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class DispenserBlockEntity extends RandomizableContainerBlockEntity { ++ + public static final int CONTAINER_SIZE = 9; +- private NonNullList items = NonNullList.withSize(9, ItemStack.EMPTY); ++ private NonNullList items; + +- protected DispenserBlockEntity(BlockEntityType type, BlockPos pos, BlockState blockState) { ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ ++ protected DispenserBlockEntity(BlockEntityType type, BlockPos pos, IBlockData blockState) { + super(type, pos, blockState); ++ this.items = NonNullList.withSize(9, ItemStack.EMPTY); + } + +- public DispenserBlockEntity(BlockPos pos, BlockState blockState) { ++ public DispenserBlockEntity(BlockPos pos, IBlockData blockState) { + this(BlockEntityType.DISPENSER, pos, blockState); + } + +@@ -30,13 +69,13 @@ + } + + public int getRandomSlot(RandomSource random) { +- this.unpackLootTable(null); ++ this.unpackLootTable((Player) null); + int i = -1; +- int i1 = 1; ++ int j = 1; + +- for (int i2 = 0; i2 < this.items.size(); i2++) { +- if (!this.items.get(i2).isEmpty() && random.nextInt(i1++) == 0) { +- i = i2; ++ for (int k = 0; k < this.items.size(); ++k) { ++ if (!((ItemStack) this.items.get(k)).isEmpty() && random.nextInt(j++) == 0) { ++ i = k; + } + } + +@@ -44,8 +83,8 @@ + } + + public int addItem(ItemStack stack) { +- for (int i = 0; i < this.items.size(); i++) { +- if (this.items.get(i).isEmpty()) { ++ for (int i = 0; i < this.items.size(); ++i) { ++ if (((ItemStack) this.items.get(i)).isEmpty()) { + this.setItem(i, stack); + return i; + } +@@ -66,6 +105,7 @@ + if (!this.tryLoadLootTable(tag)) { + ContainerHelper.loadAllItems(tag, this.items); + } ++ + } + + @Override +@@ -74,6 +114,7 @@ + if (!this.trySaveLootTable(tag)) { + ContainerHelper.saveAllItems(tag, this.items); + } ++ + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/HopperBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/HopperBlockEntity.java.patch new file mode 100644 index 0000000000..9acaffdf6b --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/HopperBlockEntity.java.patch @@ -0,0 +1,680 @@ +--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.level.block.entity; + ++import java.util.Iterator; + import java.util.List; + import java.util.function.BooleanSupplier; + import java.util.stream.Collectors; +@@ -10,6 +11,7 @@ + import net.minecraft.core.NonNullList; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; ++import net.minecraft.world.CompoundContainer; + import net.minecraft.world.Container; + import net.minecraft.world.ContainerHelper; + import net.minecraft.world.WorldlyContainer; +@@ -17,7 +19,7 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.item.ItemEntity; +-import net.minecraft.world.entity.player.Inventory; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.inventory.AbstractContainerMenu; + import net.minecraft.world.inventory.HopperMenu; + import net.minecraft.world.item.ItemStack; +@@ -25,20 +27,64 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.ChestBlock; + import net.minecraft.world.level.block.HopperBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.Shapes; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.event.inventory.HopperInventorySearchEvent; ++import org.bukkit.event.inventory.InventoryMoveItemEvent; ++import org.bukkit.event.inventory.InventoryPickupItemEvent; ++import org.bukkit.inventory.Inventory; ++// CraftBukkit end + + public class HopperBlockEntity extends RandomizableContainerBlockEntity implements Hopper { ++ + public static final int MOVE_ITEM_SPEED = 8; + public static final int HOPPER_CONTAINER_SIZE = 5; +- private NonNullList items = NonNullList.withSize(5, ItemStack.EMPTY); +- private int cooldownTime = -1; ++ private NonNullList items; ++ private int cooldownTime; + private long tickedGameTime; + +- public HopperBlockEntity(BlockPos pos, BlockState blockState) { ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ ++ public HopperBlockEntity(BlockPos pos, IBlockData blockState) { + super(BlockEntityType.HOPPER, pos, blockState); ++ this.items = NonNullList.withSize(5, ItemStack.EMPTY); ++ this.cooldownTime = -1; + } + + @Override +@@ -69,17 +115,18 @@ + + @Override + public ItemStack removeItem(int index, int count) { +- this.unpackLootTable(null); ++ this.unpackLootTable((Player) null); + return ContainerHelper.removeItem(this.getItems(), index, count); + } + + @Override + public void setItem(int index, ItemStack stack) { +- this.unpackLootTable(null); ++ this.unpackLootTable((Player) null); + this.getItems().set(index, stack); + if (stack.getCount() > this.getMaxStackSize()) { + stack.setCount(this.getMaxStackSize()); + } ++ + } + + @Override +@@ -87,23 +134,27 @@ + return Component.translatable("container.hopper"); + } + +- public static void pushItemsTick(Level level, BlockPos pos, BlockState state, HopperBlockEntity blockEntity) { +- blockEntity.cooldownTime--; ++ public static void pushItemsTick(Level level, BlockPos pos, IBlockData state, HopperBlockEntity blockEntity) { ++ --blockEntity.cooldownTime; + blockEntity.tickedGameTime = level.getGameTime(); + if (!blockEntity.isOnCooldown()) { + blockEntity.setCooldown(0); +- tryMoveItems(level, pos, state, blockEntity, () -> suckInItems(level, blockEntity)); ++ tryMoveItems(level, pos, state, blockEntity, () -> { ++ return suckInItems(level, blockEntity); ++ }); + } ++ + } + +- private static boolean tryMoveItems(Level level, BlockPos pos, BlockState state, HopperBlockEntity blockEntity, BooleanSupplier validator) { ++ private static boolean tryMoveItems(Level level, BlockPos pos, IBlockData state, HopperBlockEntity blockEntity, BooleanSupplier validator) { + if (level.isClientSide) { + return false; + } else { +- if (!blockEntity.isOnCooldown() && state.getValue(HopperBlock.ENABLED)) { ++ if (!blockEntity.isOnCooldown() && (Boolean) state.getValue(HopperBlock.ENABLED)) { + boolean flag = false; ++ + if (!blockEntity.isEmpty()) { +- flag = ejectItems(level, pos, state, blockEntity); ++ flag = ejectItems(level, pos, state, (Container) blockEntity, blockEntity); // CraftBukkit + } + + if (!blockEntity.inventoryFull()) { +@@ -122,34 +173,66 @@ + } + + private boolean inventoryFull() { +- for (ItemStack itemStack : this.items) { +- if (itemStack.isEmpty() || itemStack.getCount() != itemStack.getMaxStackSize()) { +- return false; ++ Iterator iterator = this.items.iterator(); ++ ++ ItemStack itemstack; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return true; + } +- } + +- return true; ++ itemstack = (ItemStack) iterator.next(); ++ } while (!itemstack.isEmpty() && itemstack.getCount() == itemstack.getMaxStackSize()); ++ ++ return false; + } + +- private static boolean ejectItems(Level level, BlockPos pos, BlockState state, Container sourceContainer) { +- Container attachedContainer = getAttachedContainer(level, pos, state); +- if (attachedContainer == null) { ++ private static boolean ejectItems(Level world, BlockPos blockposition, IBlockData iblockdata, Container iinventory, HopperBlockEntity hopper) { // CraftBukkit ++ Container iinventory1 = getAttachedContainer(world, blockposition, iblockdata); ++ ++ if (iinventory1 == null) { + return false; + } else { +- Direction opposite = state.getValue(HopperBlock.FACING).getOpposite(); +- if (isFullContainer(attachedContainer, opposite)) { ++ Direction enumdirection = ((Direction) iblockdata.getValue(HopperBlock.FACING)).getOpposite(); ++ ++ if (isFullContainer(iinventory1, enumdirection)) { + return false; + } else { +- for (int i = 0; i < sourceContainer.getContainerSize(); i++) { +- if (!sourceContainer.getItem(i).isEmpty()) { +- ItemStack itemStack = sourceContainer.getItem(i).copy(); +- ItemStack itemStack1 = addItem(sourceContainer, attachedContainer, sourceContainer.removeItem(i, 1), opposite); +- if (itemStack1.isEmpty()) { +- attachedContainer.setChanged(); ++ for (int i = 0; i < iinventory.getContainerSize(); ++i) { ++ if (!iinventory.getItem(i).isEmpty()) { ++ ItemStack itemstack = iinventory.getItem(i).copy(); ++ // ItemStack itemstack1 = addItem(iinventory, iinventory1, iinventory.removeItem(i, 1), enumdirection); ++ ++ // CraftBukkit start - Call event when pushing items into other inventories ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.removeItem(i, 1)); ++ ++ Inventory destinationInventory; ++ // Have to special case large chests as they work oddly ++ if (iinventory1 instanceof CompoundContainer) { ++ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory1); ++ } else if (iinventory1.getOwner() != null) { ++ destinationInventory = iinventory1.getOwner().getInventory(); ++ } else { ++ destinationInventory = new CraftInventory(iinventory); ++ } ++ ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(iinventory.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ hopper.setItem(i, itemstack); ++ hopper.setCooldown(8); // Delay hopper checks ++ return false; ++ } ++ ItemStack itemstack1 = addItem(iinventory, iinventory1, CraftItemStack.asNMSCopy(event.getItem()), enumdirection); ++ // CraftBukkit end ++ ++ if (itemstack1.isEmpty()) { ++ iinventory1.setChanged(); + return true; + } + +- sourceContainer.setItem(i, itemStack); ++ iinventory.setItem(i, itemstack); + } + } + +@@ -159,50 +242,89 @@ + } + + private static IntStream getSlots(Container container, Direction direction) { +- return container instanceof WorldlyContainer +- ? IntStream.of(((WorldlyContainer)container).getSlotsForFace(direction)) +- : IntStream.range(0, container.getContainerSize()); ++ return container instanceof WorldlyContainer ? IntStream.of(((WorldlyContainer) container).getSlotsForFace(direction)) : IntStream.range(0, container.getContainerSize()); + } + + private static boolean isFullContainer(Container container, Direction direction) { +- return getSlots(container, direction).allMatch(slot -> { +- ItemStack item = container.getItem(slot); +- return item.getCount() >= item.getMaxStackSize(); ++ return getSlots(container, direction).allMatch((i) -> { ++ ItemStack itemstack = container.getItem(i); ++ ++ return itemstack.getCount() >= itemstack.getMaxStackSize(); + }); + } + + private static boolean isEmptyContainer(Container container, Direction direction) { +- return getSlots(container, direction).allMatch(slotIndex -> container.getItem(slotIndex).isEmpty()); ++ return getSlots(container, direction).allMatch((i) -> { ++ return container.getItem(i).isEmpty(); ++ }); + } + + public static boolean suckInItems(Level level, Hopper hopper) { +- Container sourceContainer = getSourceContainer(level, hopper); +- if (sourceContainer != null) { +- Direction direction = Direction.DOWN; +- return !isEmptyContainer(sourceContainer, direction) +- && getSlots(sourceContainer, direction).anyMatch(slot -> tryTakeInItemFromSlot(hopper, sourceContainer, slot, direction)); ++ Container iinventory = getSourceContainer(level, hopper); ++ ++ if (iinventory != null) { ++ Direction enumdirection = Direction.DOWN; ++ ++ return isEmptyContainer(iinventory, enumdirection) ? false : getSlots(iinventory, enumdirection).anyMatch((i) -> { ++ return tryTakeInItemFromSlot(hopper, iinventory, i, enumdirection); ++ }); + } else { +- for (ItemEntity itemEntity : getItemsAtAndAbove(level, hopper)) { +- if (addItem(hopper, itemEntity)) { +- return true; ++ Iterator iterator = getItemsAtAndAbove(level, hopper).iterator(); ++ ++ ItemEntity entityitem; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return false; + } +- } + +- return false; ++ entityitem = (ItemEntity) iterator.next(); ++ } while (!addItem(hopper, entityitem)); ++ ++ return true; + } + } + + private static boolean tryTakeInItemFromSlot(Hopper hopper, Container container, int slot, Direction direction) { +- ItemStack item = container.getItem(slot); +- if (!item.isEmpty() && canTakeItemFromContainer(hopper, container, item, slot, direction)) { +- ItemStack itemStack = item.copy(); +- ItemStack itemStack1 = addItem(container, hopper, container.removeItem(slot, 1), null); +- if (itemStack1.isEmpty()) { ++ ItemStack itemstack = container.getItem(slot); ++ ++ if (!itemstack.isEmpty() && canTakeItemFromContainer(hopper, container, itemstack, slot, direction)) { ++ ItemStack itemstack1 = itemstack.copy(); ++ // ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.removeItem(i, 1), (EnumDirection) null); ++ // CraftBukkit start - Call event on collection of items from inventories into the hopper ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(container.removeItem(slot, 1)); ++ ++ Inventory sourceInventory; ++ // Have to special case large chests as they work oddly ++ if (container instanceof CompoundContainer) { ++ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) container); ++ } else if (container.getOwner() != null) { ++ sourceInventory = container.getOwner().getInventory(); ++ } else { ++ sourceInventory = new CraftInventory(container); ++ } ++ ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack.clone(), hopper.getOwner().getInventory(), false); ++ ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ container.setItem(slot, itemstack1); ++ ++ if (hopper instanceof HopperBlockEntity) { ++ ((HopperBlockEntity) hopper).setCooldown(8); // Delay hopper checks ++ } ++ ++ return false; ++ } ++ ItemStack itemstack2 = addItem(container, hopper, CraftItemStack.asNMSCopy(event.getItem()), null); ++ // CraftBukkit end ++ ++ if (itemstack2.isEmpty()) { + container.setChanged(); + return true; + } + +- container.setItem(slot, itemStack); ++ container.setItem(slot, itemstack1); + } + + return false; +@@ -210,33 +332,47 @@ + + public static boolean addItem(Container container, ItemEntity item) { + boolean flag = false; +- ItemStack itemStack = item.getItem().copy(); +- ItemStack itemStack1 = addItem(null, container, itemStack, null); +- if (itemStack1.isEmpty()) { ++ // CraftBukkit start ++ InventoryPickupItemEvent event = new InventoryPickupItemEvent(container.getOwner().getInventory(), (org.bukkit.entity.Item) item.getBukkitEntity()); ++ item.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ ItemStack itemstack = item.getItem().copy(); ++ ItemStack itemstack1 = addItem((Container) null, container, itemstack, (Direction) null); ++ ++ if (itemstack1.isEmpty()) { + flag = true; + item.setItem(ItemStack.EMPTY); + item.discard(); + } else { +- item.setItem(itemStack1); ++ item.setItem(itemstack1); + } + + return flag; + } + + public static ItemStack addItem(@Nullable Container source, Container destination, ItemStack stack, @Nullable Direction direction) { +- if (destination instanceof WorldlyContainer worldlyContainer && direction != null) { +- int[] slotsForFace = worldlyContainer.getSlotsForFace(direction); ++ int i; + +- for (int i = 0; i < slotsForFace.length && !stack.isEmpty(); i++) { +- stack = tryMoveInItem(source, destination, stack, slotsForFace[i], direction); +- } ++ if (destination instanceof WorldlyContainer) { ++ WorldlyContainer iworldinventory = (WorldlyContainer) destination; + +- return stack; ++ if (direction != null) { ++ int[] aint = iworldinventory.getSlotsForFace(direction); ++ ++ for (i = 0; i < aint.length && !stack.isEmpty(); ++i) { ++ stack = tryMoveInItem(source, destination, stack, aint[i], direction); ++ } ++ ++ return stack; ++ } + } + +- int containerSize = destination.getContainerSize(); ++ int j = destination.getContainerSize(); + +- for (int i = 0; i < containerSize && !stack.isEmpty(); i++) { ++ for (i = 0; i < j && !stack.isEmpty(); ++i) { + stack = tryMoveInItem(source, destination, stack, i, direction); + } + +@@ -247,11 +383,19 @@ + if (!container.canPlaceItem(slot, stack)) { + return false; + } else { +- if (container instanceof WorldlyContainer worldlyContainer && !worldlyContainer.canPlaceItemThroughFace(slot, stack, direction)) { +- return false; ++ boolean flag; ++ ++ if (container instanceof WorldlyContainer) { ++ WorldlyContainer iworldinventory = (WorldlyContainer) container; ++ ++ if (!iworldinventory.canPlaceItemThroughFace(slot, stack, direction)) { ++ flag = false; ++ return flag; ++ } + } + +- return true; ++ flag = true; ++ return flag; + } + } + +@@ -259,39 +403,59 @@ + if (!destination.canTakeItem(source, slot, stack)) { + return false; + } else { +- if (destination instanceof WorldlyContainer worldlyContainer && !worldlyContainer.canTakeItemThroughFace(slot, stack, direction)) { +- return false; ++ boolean flag; ++ ++ if (destination instanceof WorldlyContainer) { ++ WorldlyContainer iworldinventory = (WorldlyContainer) destination; ++ ++ if (!iworldinventory.canTakeItemThroughFace(slot, stack, direction)) { ++ flag = false; ++ return flag; ++ } + } + +- return true; ++ flag = true; ++ return flag; + } + } + + private static ItemStack tryMoveInItem(@Nullable Container source, Container destination, ItemStack stack, int slot, @Nullable Direction direction) { +- ItemStack item = destination.getItem(slot); ++ ItemStack itemstack1 = destination.getItem(slot); ++ + if (canPlaceItemInContainer(destination, stack, slot, direction)) { + boolean flag = false; +- boolean isEmpty = destination.isEmpty(); +- if (item.isEmpty()) { ++ boolean flag1 = destination.isEmpty(); ++ ++ if (itemstack1.isEmpty()) { + destination.setItem(slot, stack); + stack = ItemStack.EMPTY; + flag = true; +- } else if (canMergeItems(item, stack)) { +- int i = stack.getMaxStackSize() - item.getCount(); +- int min = Math.min(stack.getCount(), i); +- stack.shrink(min); +- item.grow(min); +- flag = min > 0; ++ } else if (canMergeItems(itemstack1, stack)) { ++ int j = stack.getMaxStackSize() - itemstack1.getCount(); ++ int k = Math.min(stack.getCount(), j); ++ ++ stack.shrink(k); ++ itemstack1.grow(k); ++ flag = k > 0; + } + + if (flag) { +- if (isEmpty && destination instanceof HopperBlockEntity hopperBlockEntity && !hopperBlockEntity.isOnCustomCooldown()) { +- int min = 0; +- if (source instanceof HopperBlockEntity hopperBlockEntity1 && hopperBlockEntity.tickedGameTime >= hopperBlockEntity1.tickedGameTime) { +- min = 1; +- } ++ if (flag1 && destination instanceof HopperBlockEntity) { ++ HopperBlockEntity tileentityhopper = (HopperBlockEntity) destination; + +- hopperBlockEntity.setCooldown(8 - min); ++ if (!tileentityhopper.isOnCustomCooldown()) { ++ byte b0 = 0; ++ ++ if (source instanceof HopperBlockEntity) { ++ HopperBlockEntity tileentityhopper1 = (HopperBlockEntity) source; ++ ++ if (tileentityhopper.tickedGameTime >= tileentityhopper1.tickedGameTime) { ++ b0 = 1; ++ } ++ } ++ ++ tileentityhopper.setCooldown(8 - b0); ++ } + } + + destination.setChanged(); +@@ -301,65 +465,82 @@ + return stack; + } + ++ // CraftBukkit start + @Nullable +- private static Container getAttachedContainer(Level level, BlockPos pos, BlockState state) { +- Direction direction = state.getValue(HopperBlock.FACING); +- return getContainerAt(level, pos.relative(direction)); ++ private static Container runHopperInventorySearchEvent(Container inventory, CraftBlock hopper, CraftBlock searchLocation, HopperInventorySearchEvent.ContainerType containerType) { ++ HopperInventorySearchEvent event = new HopperInventorySearchEvent((inventory != null) ? new CraftInventory(inventory) : null, containerType, hopper, searchLocation); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ CraftInventory craftInventory = (CraftInventory) event.getInventory(); ++ return (craftInventory != null) ? craftInventory.getInventory() : null; + } ++ // CraftBukkit end + + @Nullable ++ private static Container getAttachedContainer(Level level, BlockPos pos, IBlockData state) { ++ Direction enumdirection = (Direction) state.getValue(HopperBlock.FACING); ++ ++ // CraftBukkit start ++ BlockPos searchPosition = pos.relative(enumdirection); ++ Container inventory = getContainerAt(level, pos.relative(enumdirection)); ++ ++ CraftBlock hopper = CraftBlock.at(level, pos); ++ CraftBlock searchBlock = CraftBlock.at(level, searchPosition); ++ return runHopperInventorySearchEvent(inventory, hopper, searchBlock, HopperInventorySearchEvent.ContainerType.DESTINATION); ++ // CraftBukkit end ++ } ++ ++ @Nullable + private static Container getSourceContainer(Level level, Hopper hopper) { +- return getContainerAt(level, hopper.getLevelX(), hopper.getLevelY() + 1.0, hopper.getLevelZ()); ++ // CraftBukkit start ++ Container inventory = getContainerAt(level, hopper.getLevelX(), hopper.getLevelY() + 1.0D, hopper.getLevelZ()); ++ ++ BlockPos blockPosition = BlockPos.containing(hopper.getLevelX(), hopper.getLevelY(), hopper.getLevelZ()); ++ CraftBlock hopper1 = CraftBlock.at(level, blockPosition); ++ CraftBlock container = CraftBlock.at(level, blockPosition.above()); ++ return runHopperInventorySearchEvent(inventory, hopper1, container, HopperInventorySearchEvent.ContainerType.SOURCE); ++ // CraftBukkit end + } + + public static List getItemsAtAndAbove(Level level, Hopper hopper) { +- return hopper.getSuckShape() +- .toAabbs() +- .stream() +- .flatMap( +- bounds -> level.getEntitiesOfClass( +- ItemEntity.class, +- bounds.move(hopper.getLevelX() - 0.5, hopper.getLevelY() - 0.5, hopper.getLevelZ() - 0.5), +- EntitySelector.ENTITY_STILL_ALIVE +- ) +- .stream() +- ) +- .collect(Collectors.toList()); ++ return (List) hopper.getSuckShape().toAabbs().stream().flatMap((axisalignedbb) -> { ++ return level.getEntitiesOfClass(ItemEntity.class, axisalignedbb.move(hopper.getLevelX() - 0.5D, hopper.getLevelY() - 0.5D, hopper.getLevelZ() - 0.5D), EntitySelector.ENTITY_STILL_ALIVE).stream(); ++ }).collect(Collectors.toList()); + } + + @Nullable + public static Container getContainerAt(Level level, BlockPos pos) { +- return getContainerAt(level, (double)pos.getX() + 0.5, (double)pos.getY() + 0.5, (double)pos.getZ() + 0.5); ++ return getContainerAt(level, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D); + } + + @Nullable +- private static Container getContainerAt(Level level, double x, double y, double z) { +- Container container = null; +- BlockPos blockPos = BlockPos.containing(x, y, z); +- BlockState blockState = level.getBlockState(blockPos); +- Block block = blockState.getBlock(); ++ private static Container getContainerAt(Level level, double x, double d1, double y) { ++ Object object = null; ++ BlockPos blockposition = BlockPos.containing(x, d1, y); ++ IBlockData iblockdata = level.getBlockState(blockposition); ++ Block block = iblockdata.getBlock(); ++ + if (block instanceof WorldlyContainerHolder) { +- container = ((WorldlyContainerHolder)block).getContainer(blockState, level, blockPos); +- } else if (blockState.hasBlockEntity()) { +- BlockEntity blockEntity = level.getBlockEntity(blockPos); +- if (blockEntity instanceof Container) { +- container = (Container)blockEntity; +- if (container instanceof ChestBlockEntity && block instanceof ChestBlock) { +- container = ChestBlock.getContainer((ChestBlock)block, blockState, level, blockPos, true); ++ object = ((WorldlyContainerHolder) block).getContainer(iblockdata, level, blockposition); ++ } else if (iblockdata.hasBlockEntity()) { ++ BlockEntity tileentity = level.getBlockEntity(blockposition); ++ ++ if (tileentity instanceof Container) { ++ object = (Container) tileentity; ++ if (object instanceof ChestBlockEntity && block instanceof ChestBlock) { ++ object = ChestBlock.getContainer((ChestBlock) block, iblockdata, level, blockposition, true); + } + } + } + +- if (container == null) { +- List entities = level.getEntities( +- (Entity)null, new AABB(x - 0.5, y - 0.5, z - 0.5, x + 0.5, y + 0.5, z + 0.5), EntitySelector.CONTAINER_ENTITY_SELECTOR +- ); +- if (!entities.isEmpty()) { +- container = (Container)entities.get(level.random.nextInt(entities.size())); ++ if (object == null) { ++ List list = level.getEntities((Entity) null, new AABB(x - 0.5D, d1 - 0.5D, y - 0.5D, x + 0.5D, d1 + 0.5D, y + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); ++ ++ if (!list.isEmpty()) { ++ object = (Container) list.get(level.random.nextInt(list.size())); + } + } + +- return container; ++ return (Container) object; + } + + private static boolean canMergeItems(ItemStack stack1, ItemStack stack2) { +@@ -368,17 +549,17 @@ + + @Override + public double getLevelX() { +- return (double)this.worldPosition.getX() + 0.5; ++ return (double) this.worldPosition.getX() + 0.5D; + } + + @Override + public double getLevelY() { +- return (double)this.worldPosition.getY() + 0.5; ++ return (double) this.worldPosition.getY() + 0.5D; + } + + @Override + public double getLevelZ() { +- return (double)this.worldPosition.getZ() + 0.5; ++ return (double) this.worldPosition.getZ() + 0.5D; + } + + private void setCooldown(int cooldownTime) { +@@ -403,20 +584,21 @@ + this.items = items; + } + +- public static void entityInside(Level level, BlockPos pos, BlockState state, Entity entity, HopperBlockEntity blockEntity) { +- if (entity instanceof ItemEntity itemEntity +- && !itemEntity.getItem().isEmpty() +- && Shapes.joinIsNotEmpty( +- Shapes.create(entity.getBoundingBox().move((double)(-pos.getX()), (double)(-pos.getY()), (double)(-pos.getZ()))), +- blockEntity.getSuckShape(), +- BooleanOp.AND +- )) { +- tryMoveItems(level, pos, state, blockEntity, () -> addItem(blockEntity, itemEntity)); ++ public static void entityInside(Level level, BlockPos pos, IBlockData state, Entity entity, HopperBlockEntity blockEntity) { ++ if (entity instanceof ItemEntity) { ++ ItemEntity entityitem = (ItemEntity) entity; ++ ++ if (!entityitem.getItem().isEmpty() && Shapes.joinIsNotEmpty(Shapes.create(entity.getBoundingBox().move((double) (-pos.getX()), (double) (-pos.getY()), (double) (-pos.getZ()))), blockEntity.getSuckShape(), BooleanOp.AND)) { ++ tryMoveItems(level, pos, state, blockEntity, () -> { ++ return addItem(blockEntity, entityitem); ++ }); ++ } + } ++ + } + + @Override +- protected AbstractContainerMenu createMenu(int id, Inventory player) { ++ protected AbstractContainerMenu createMenu(int id, net.minecraft.world.entity.player.Inventory player) { + return new HopperMenu(id, player, this); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java.patch new file mode 100644 index 0000000000..91722bf998 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java.patch @@ -0,0 +1,248 @@ +--- a/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java +@@ -11,26 +11,73 @@ + import net.minecraft.world.Container; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.item.ItemEntity; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.RecordItem; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.JukeboxBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.ticks.ContainerSingleItem; + ++// CraftBukkit start ++import java.util.Collections; ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class JukeboxBlockEntity extends BlockEntity implements Clearable, ContainerSingleItem { ++ + private static final int SONG_END_PADDING = 20; +- private ItemStack item = ItemStack.EMPTY; ++ private ItemStack item; + private int ticksSinceLastEvent; +- private long tickCount; +- private long recordStartedTick; +- private boolean isPlaying; ++ public long tickCount; ++ public long recordStartedTick; ++ public boolean isPlaying; ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ public boolean opened; + +- public JukeboxBlockEntity(BlockPos pos, BlockState blockState) { ++ @Override ++ public List getContents() { ++ return Collections.singletonList(item); ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ } ++ // CraftBukkit end ++ ++ public JukeboxBlockEntity(BlockPos pos, IBlockData blockState) { + super(BlockEntityType.JUKEBOX, pos, blockState); ++ this.item = ItemStack.EMPTY; + } + + @Override +@@ -63,9 +110,10 @@ + + private void setHasRecordBlockState(@Nullable Entity entity, boolean hasRecord) { + if (this.level.getBlockState(this.getBlockPos()) == this.getBlockState()) { +- this.level.setBlock(this.getBlockPos(), this.getBlockState().setValue(JukeboxBlock.HAS_RECORD, Boolean.valueOf(hasRecord)), 2); ++ this.level.setBlock(this.getBlockPos(), (IBlockData) this.getBlockState().setValue(JukeboxBlock.HAS_RECORD, hasRecord), 2); + this.level.gameEvent(GameEvent.BLOCK_CHANGE, this.getBlockPos(), GameEvent.Context.of(entity, this.getBlockState())); + } ++ + } + + @VisibleForTesting +@@ -73,7 +121,7 @@ + this.recordStartedTick = this.tickCount; + this.isPlaying = true; + this.level.updateNeighborsAt(this.getBlockPos(), this.getBlockState().getBlock()); +- this.level.levelEvent(null, 1010, this.getBlockPos(), Item.getId(this.getTheItem().getItem())); ++ this.level.levelEvent((Player) null, 1010, this.getBlockPos(), Item.getId(this.getTheItem().getItem())); + this.setChanged(); + } + +@@ -85,23 +133,29 @@ + this.setChanged(); + } + +- private void tick(Level level, BlockPos pos, BlockState state) { +- this.ticksSinceLastEvent++; +- if (this.isRecordPlaying() && this.getTheItem().getItem() instanceof RecordItem recordItem) { +- if (this.shouldRecordStopPlaying(recordItem)) { +- this.stopPlaying(); +- } else if (this.shouldSendJukeboxPlayingEvent()) { +- this.ticksSinceLastEvent = 0; +- level.gameEvent(GameEvent.JUKEBOX_PLAY, pos, GameEvent.Context.of(state)); +- this.spawnMusicParticles(level, pos); ++ private void tick(Level level, BlockPos pos, IBlockData state) { ++ ++this.ticksSinceLastEvent; ++ if (this.isRecordPlaying()) { ++ Item item = this.getTheItem().getItem(); ++ ++ if (item instanceof RecordItem) { ++ RecordItem itemrecord = (RecordItem) item; ++ ++ if (this.shouldRecordStopPlaying(itemrecord)) { ++ this.stopPlaying(); ++ } else if (this.shouldSendJukeboxPlayingEvent()) { ++ this.ticksSinceLastEvent = 0; ++ level.gameEvent(GameEvent.JUKEBOX_PLAY, pos, GameEvent.Context.of(state)); ++ this.spawnMusicParticles(level, pos); ++ } + } + } + +- this.tickCount++; ++ ++this.tickCount; + } + +- private boolean shouldRecordStopPlaying(RecordItem _record) { +- return this.tickCount >= this.recordStartedTick + (long)_record.getLengthInTicks() + 20L; ++ private boolean shouldRecordStopPlaying(RecordItem record) { ++ return this.tickCount >= this.recordStartedTick + (long) record.getLengthInTicks() + 20L; + } + + private boolean shouldSendJukeboxPlayingEvent() { +@@ -115,30 +169,32 @@ + + @Override + public ItemStack splitTheItem(int i) { +- ItemStack itemStack = this.item; ++ ItemStack itemstack = this.item; ++ + this.item = ItemStack.EMPTY; +- if (!itemStack.isEmpty()) { +- this.setHasRecordBlockState(null, false); ++ if (!itemstack.isEmpty()) { ++ this.setHasRecordBlockState((Entity) null, false); + this.stopPlaying(); + } + +- return itemStack; ++ return itemstack; + } + + @Override +- public void setTheItem(ItemStack itemStack) { +- if (itemStack.is(ItemTags.MUSIC_DISCS) && this.level != null) { +- this.item = itemStack; +- this.setHasRecordBlockState(null, true); ++ public void setTheItem(ItemStack itemstack) { ++ if (itemstack.is(ItemTags.MUSIC_DISCS) && this.level != null) { ++ this.item = itemstack; ++ this.setHasRecordBlockState((Entity) null, true); + this.startPlaying(); +- } else if (itemStack.isEmpty()) { ++ } else if (itemstack.isEmpty()) { + this.splitTheItem(1); + } ++ + } + + @Override + public int getMaxStackSize() { +- return 1; ++ return maxStack; // CraftBukkit + } + + @Override +@@ -157,36 +213,45 @@ + } + + private void spawnMusicParticles(Level level, BlockPos pos) { +- if (level instanceof ServerLevel serverLevel) { +- Vec3 vec3 = Vec3.atBottomCenterOf(pos).add(0.0, 1.2F, 0.0); +- float f = (float)level.getRandom().nextInt(4) / 24.0F; +- serverLevel.sendParticles(ParticleTypes.NOTE, vec3.x(), vec3.y(), vec3.z(), 0, (double)f, 0.0, 0.0, 1.0); ++ if (level instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) level; ++ Vec3 vec3d = Vec3.atBottomCenterOf(pos).add(0.0D, 1.2000000476837158D, 0.0D); ++ float f = (float) level.getRandom().nextInt(4) / 24.0F; ++ ++ worldserver.sendParticles(ParticleTypes.NOTE, vec3d.x(), vec3d.y(), vec3d.z(), 0, (double) f, 0.0D, 0.0D, 1.0D); + } ++ + } + + public void popOutRecord() { + if (this.level != null && !this.level.isClientSide) { +- BlockPos blockPos = this.getBlockPos(); +- ItemStack theItem = this.getTheItem(); +- if (!theItem.isEmpty()) { ++ BlockPos blockposition = this.getBlockPos(); ++ ItemStack itemstack = this.getTheItem(); ++ ++ if (!itemstack.isEmpty()) { + this.removeTheItem(); +- Vec3 vec3 = Vec3.atLowerCornerWithOffset(blockPos, 0.5, 1.01, 0.5).offsetRandom(this.level.random, 0.7F); +- ItemStack itemStack = theItem.copy(); +- ItemEntity itemEntity = new ItemEntity(this.level, vec3.x(), vec3.y(), vec3.z(), itemStack); +- itemEntity.setDefaultPickUpDelay(); +- this.level.addFreshEntity(itemEntity); ++ Vec3 vec3d = Vec3.atLowerCornerWithOffset(blockposition, 0.5D, 1.01D, 0.5D).offsetRandom(this.level.random, 0.7F); ++ ItemStack itemstack1 = itemstack.copy(); ++ ItemEntity entityitem = new ItemEntity(this.level, vec3d.x(), vec3d.y(), vec3d.z(), itemstack1); ++ ++ entityitem.setDefaultPickUpDelay(); ++ this.level.addFreshEntity(entityitem); + } + } + } + +- public static void playRecordTick(Level level, BlockPos pos, BlockState state, JukeboxBlockEntity jukebox) { ++ public static void playRecordTick(Level level, BlockPos pos, IBlockData state, JukeboxBlockEntity jukebox) { + jukebox.tick(level, pos, state); + } + + @VisibleForTesting + public void setRecordWithoutPlaying(ItemStack stack) { + this.item = stack; +- this.level.updateNeighborsAt(this.getBlockPos(), this.getBlockState().getBlock()); ++ // CraftBukkit start - add null check for level ++ if (level != null) { ++ this.level.updateNeighborsAt(this.getBlockPos(), this.getBlockState().getBlock()); ++ } ++ // CraftBukkit end + this.setChanged(); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/LecternBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/LecternBlockEntity.java.patch new file mode 100644 index 0000000000..f2e7971415 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/LecternBlockEntity.java.patch @@ -0,0 +1,307 @@ +--- a/net/minecraft/world/level/block/entity/LecternBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/LecternBlockEntity.java +@@ -10,7 +10,8 @@ + import net.minecraft.util.Mth; + import net.minecraft.world.Clearable; + import net.minecraft.world.Container; +-import net.minecraft.world.MenuProvider; ++import net.minecraft.world.ITileInventory; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Inventory; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.inventory.AbstractContainerMenu; +@@ -20,17 +21,76 @@ + import net.minecraft.world.item.Items; + import net.minecraft.world.item.WrittenBookItem; + import net.minecraft.world.level.block.LecternBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.block.Lectern; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end + +-public class LecternBlockEntity extends BlockEntity implements Clearable, MenuProvider { ++public class LecternBlockEntity extends BlockEntity implements Clearable, ITileInventory, CommandSource { // CraftBukkit - ICommandListener ++ + public static final int DATA_PAGE = 0; + public static final int NUM_DATA = 1; + public static final int SLOT_BOOK = 0; + public static final int NUM_SLOTS = 1; +- private final Container bookAccess = new Container() { ++ // CraftBukkit start - add fields and methods ++ public final Container bookAccess = new LecternInventory(); ++ public class LecternInventory implements Container { ++ ++ public List transaction = new ArrayList<>(); ++ private int maxStack = 1; ++ + @Override ++ public List getContents() { ++ return Arrays.asList(book); ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return CraftLocation.toBukkit(worldPosition, level.getWorld()); ++ } ++ ++ @Override ++ public InventoryHolder getOwner() { ++ return (Lectern) LecternBlockEntity.this.getOwner(); ++ } ++ ++ public LecternBlockEntity getLectern() { ++ return LecternBlockEntity.this; ++ } ++ // CraftBukkit end ++ ++ @Override + public int getContainerSize() { + return 1; + } +@@ -48,12 +108,13 @@ + @Override + public ItemStack removeItem(int slot, int amount) { + if (slot == 0) { +- ItemStack itemStack = LecternBlockEntity.this.book.split(amount); ++ ItemStack itemstack = LecternBlockEntity.this.book.split(amount); ++ + if (LecternBlockEntity.this.book.isEmpty()) { + LecternBlockEntity.this.onBookItemRemove(); + } + +- return itemStack; ++ return itemstack; + } else { + return ItemStack.EMPTY; + } +@@ -62,22 +123,31 @@ + @Override + public ItemStack removeItemNoUpdate(int slot) { + if (slot == 0) { +- ItemStack itemStack = LecternBlockEntity.this.book; ++ ItemStack itemstack = LecternBlockEntity.this.book; ++ + LecternBlockEntity.this.book = ItemStack.EMPTY; + LecternBlockEntity.this.onBookItemRemove(); +- return itemStack; ++ return itemstack; + } else { + return ItemStack.EMPTY; + } + } + + @Override ++ // CraftBukkit start + public void setItem(int slot, ItemStack stack) { ++ if (slot == 0) { ++ LecternBlockEntity.this.setBook(stack); ++ if (LecternBlockEntity.this.getLevel() != null) { ++ LecternBlock.resetBookState(null, LecternBlockEntity.this.getLevel(), LecternBlockEntity.this.getBlockPos(), LecternBlockEntity.this.getBlockState(), LecternBlockEntity.this.hasBook()); ++ } ++ } + } ++ // CraftBukkit end + + @Override + public int getMaxStackSize() { +- return 1; ++ return maxStack; // CraftBukkit + } + + @Override +@@ -96,8 +166,7 @@ + } + + @Override +- public void clearContent() { +- } ++ public void clearContent() {} + }; + private final ContainerData dataAccess = new ContainerData() { + @Override +@@ -110,6 +179,7 @@ + if (index == 0) { + LecternBlockEntity.this.setPage(value); + } ++ + } + + @Override +@@ -117,12 +187,13 @@ + return 1; + } + }; +- ItemStack book = ItemStack.EMPTY; ++ ItemStack book; + int page; + private int pageCount; + +- public LecternBlockEntity(BlockPos pos, BlockState blockState) { ++ public LecternBlockEntity(BlockPos pos, IBlockData blockState) { + super(BlockEntityType.LECTERN, pos, blockState); ++ this.book = ItemStack.EMPTY; + } + + public ItemStack getBook() { +@@ -134,13 +205,13 @@ + } + + public void setBook(ItemStack stack) { +- this.setBook(stack, null); ++ this.setBook(stack, (Player) null); + } + + void onBookItemRemove() { + this.page = 0; + this.pageCount = 0; +- LecternBlock.resetBookState(null, this.getLevel(), this.getBlockPos(), this.getBlockState(), false); ++ LecternBlock.resetBookState((Entity) null, this.getLevel(), this.getBlockPos(), this.getBlockState(), false); + } + + public void setBook(ItemStack stack, @Nullable Player player) { +@@ -150,13 +221,15 @@ + this.setChanged(); + } + +- void setPage(int page) { +- int i = Mth.clamp(page, 0, this.pageCount - 1); +- if (i != this.page) { +- this.page = i; ++ public void setPage(int page) { ++ int j = Mth.clamp(page, 0, this.pageCount - 1); ++ ++ if (j != this.page) { ++ this.page = j; + this.setChanged(); +- LecternBlock.signalPageChange(this.getLevel(), this.getBlockPos(), this.getBlockState()); ++ if (this.level != null) LecternBlock.signalPageChange(this.getLevel(), this.getBlockPos(), this.getBlockState()); // CraftBukkit + } ++ + } + + public int getPage() { +@@ -164,7 +237,8 @@ + } + + public int getRedstoneSignal() { +- float f = this.pageCount > 1 ? (float)this.getPage() / ((float)this.pageCount - 1.0F) : 1.0F; ++ float f = this.pageCount > 1 ? (float) this.getPage() / ((float) this.pageCount - 1.0F) : 1.0F; ++ + return Mth.floor(f * 14.0F) + (this.hasBook() ? 1 : 0); + } + +@@ -176,19 +250,48 @@ + return stack; + } + ++ // CraftBukkit start ++ @Override ++ public void sendSystemMessage(Component component) { ++ } ++ ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return wrapper.getEntity() != null ? wrapper.getEntity().getBukkitSender(wrapper) : new org.bukkit.craftbukkit.command.CraftBlockCommandSender(wrapper, this); ++ } ++ ++ @Override ++ public boolean acceptsSuccess() { ++ return false; ++ } ++ ++ @Override ++ public boolean acceptsFailure() { ++ return false; ++ } ++ ++ @Override ++ public boolean shouldInformAdmins() { ++ return false; ++ } ++ ++ // CraftBukkit end + private CommandSourceStack createCommandSourceStack(@Nullable Player player) { +- String string; +- Component component; ++ String s; ++ Object object; ++ + if (player == null) { +- string = "Lectern"; +- component = Component.literal("Lectern"); ++ s = "Lectern"; ++ object = Component.literal("Lectern"); + } else { +- string = player.getName().getString(); +- component = player.getDisplayName(); ++ s = player.getName().getString(); ++ object = player.getDisplayName(); + } + +- Vec3 vec3 = Vec3.atCenterOf(this.worldPosition); +- return new CommandSourceStack(CommandSource.NULL, vec3, Vec2.ZERO, (ServerLevel)this.level, 2, string, component, this.level.getServer(), player); ++ Vec3 vec3d = Vec3.atCenterOf(this.worldPosition); ++ ++ // CraftBukkit - this ++ return new CommandSourceStack(this, vec3d, Vec2.ZERO, (ServerLevel) this.level, 2, s, (Component) object, this.level.getServer(), player); + } + + @Override +@@ -200,7 +303,7 @@ + public void load(CompoundTag tag) { + super.load(tag); + if (tag.contains("Book", 10)) { +- this.book = this.resolveBook(ItemStack.of(tag.getCompound("Book")), null); ++ this.book = this.resolveBook(ItemStack.of(tag.getCompound("Book")), (Player) null); + } else { + this.book = ItemStack.EMPTY; + } +@@ -216,6 +319,7 @@ + tag.put("Book", this.getBook().save(new CompoundTag())); + tag.putInt("Page", this.page); + } ++ + } + + @Override +@@ -225,7 +329,7 @@ + + @Override + public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { +- return new LecternMenu(containerId, this.bookAccess, this.dataAccess); ++ return new LecternMenu(containerId, this.bookAccess, this.dataAccess, playerInventory); // CraftBukkit + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java.patch new file mode 100644 index 0000000000..04feed39b3 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java.patch @@ -0,0 +1,153 @@ +--- a/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java +@@ -12,31 +12,38 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.util.RandomSource; + import net.minecraft.world.damagesource.DamageSource; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.SculkCatalystBlock; + import net.minecraft.world.level.block.SculkSpreader; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.BlockPositionSource; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.gameevent.GameEventListener; + import net.minecraft.world.level.gameevent.PositionSource; + import net.minecraft.world.phys.Vec3; + +-public class SculkCatalystBlockEntity extends BlockEntity implements GameEventListener.Holder { ++public class SculkCatalystBlockEntity extends BlockEntity implements GameEventListener.b { ++ + private final SculkCatalystBlockEntity.CatalystListener catalystListener; + +- public SculkCatalystBlockEntity(BlockPos pos, BlockState blockState) { ++ public SculkCatalystBlockEntity(BlockPos pos, IBlockData blockState) { + super(BlockEntityType.SCULK_CATALYST, pos, blockState); + this.catalystListener = new SculkCatalystBlockEntity.CatalystListener(blockState, new BlockPositionSource(pos)); ++ catalystListener.level = level; // CraftBukkit + } + +- public static void serverTick(Level level, BlockPos pos, BlockState state, SculkCatalystBlockEntity sculkCatalyst) { ++ public static void serverTick(Level level, BlockPos pos, IBlockData state, SculkCatalystBlockEntity sculkCatalyst) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = sculkCatalyst.getBlockPos(); // CraftBukkit - SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep. + sculkCatalyst.catalystListener.getSculkSpreader().updateCursors(level, pos, level.getRandom(), true); ++ org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = null; // CraftBukkit + } + + @Override + public void load(CompoundTag tag) { ++ super.load(tag); // CraftBukkit - SPIGOT-7393: Load super Bukkit data + this.catalystListener.sculkSpreader.load(tag); + } + +@@ -52,15 +59,18 @@ + } + + public static class CatalystListener implements GameEventListener { ++ + public static final int PULSE_TICKS = 8; + final SculkSpreader sculkSpreader; +- private final BlockState blockState; ++ private final IBlockData blockState; + private final PositionSource positionSource; ++ private Level level; // CraftBukkit + +- public CatalystListener(BlockState blockState, PositionSource positionSource) { ++ public CatalystListener(IBlockData blockState, PositionSource positionSource) { + this.blockState = blockState; + this.positionSource = positionSource; + this.sculkSpreader = SculkSpreader.createLevelSpreader(); ++ this.sculkSpreader.level = level; // CraftBukkit + } + + @Override +@@ -74,30 +84,37 @@ + } + + @Override +- public GameEventListener.DeliveryMode getDeliveryMode() { +- return GameEventListener.DeliveryMode.BY_DISTANCE; ++ public GameEventListener.a getDeliveryMode() { ++ return GameEventListener.a.BY_DISTANCE; + } + + @Override + public boolean handleGameEvent(ServerLevel level, GameEvent gameEvent, GameEvent.Context context, Vec3 pos) { +- if (gameEvent == GameEvent.ENTITY_DIE && context.sourceEntity() instanceof LivingEntity livingEntity) { +- if (!livingEntity.wasExperienceConsumed()) { +- int experienceReward = livingEntity.getExperienceReward(); +- if (livingEntity.shouldDropExperience() && experienceReward > 0) { +- this.sculkSpreader.addCursors(BlockPos.containing(pos.relative(Direction.UP, 0.5)), experienceReward); +- this.tryAwardItSpreadsAdvancement(level, livingEntity); ++ if (gameEvent == GameEvent.ENTITY_DIE) { ++ Entity entity = context.sourceEntity(); ++ ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ if (!entityliving.wasExperienceConsumed()) { ++ int i = entityliving.getExperienceReward(); ++ ++ if (entityliving.shouldDropExperience() && i > 0) { ++ this.sculkSpreader.addCursors(BlockPos.containing(pos.relative(Direction.UP, 0.5D)), i); ++ this.tryAwardItSpreadsAdvancement(level, entityliving); ++ } ++ ++ entityliving.skipDropExperience(); ++ this.positionSource.getPosition(level).ifPresent((vec3d1) -> { ++ this.bloom(level, BlockPos.containing(vec3d1), this.blockState, level.getRandom()); ++ }); + } + +- livingEntity.skipDropExperience(); +- this.positionSource +- .getPosition(level) +- .ifPresent(position -> this.bloom(level, BlockPos.containing(position), this.blockState, level.getRandom())); ++ return true; + } +- +- return true; +- } else { +- return false; + } ++ ++ return false; + } + + @VisibleForTesting +@@ -105,20 +122,23 @@ + return this.sculkSpreader; + } + +- private void bloom(ServerLevel level, BlockPos pos, BlockState state, RandomSource random) { +- level.setBlock(pos, state.setValue(SculkCatalystBlock.PULSE, Boolean.valueOf(true)), 3); ++ public void bloom(ServerLevel level, BlockPos pos, IBlockData state, RandomSource random) { ++ level.setBlock(pos, (IBlockData) state.setValue(SculkCatalystBlock.PULSE, true), 3); + level.scheduleTick(pos, state.getBlock(), 8); +- level.sendParticles(ParticleTypes.SCULK_SOUL, (double)pos.getX() + 0.5, (double)pos.getY() + 1.15, (double)pos.getZ() + 0.5, 2, 0.2, 0.0, 0.2, 0.0); +- level.playSound(null, pos, SoundEvents.SCULK_CATALYST_BLOOM, SoundSource.BLOCKS, 2.0F, 0.6F + random.nextFloat() * 0.4F); ++ level.sendParticles(ParticleTypes.SCULK_SOUL, (double) pos.getX() + 0.5D, (double) pos.getY() + 1.15D, (double) pos.getZ() + 0.5D, 2, 0.2D, 0.0D, 0.2D, 0.0D); ++ level.playSound((Player) null, pos, SoundEvents.SCULK_CATALYST_BLOOM, SoundSource.BLOCKS, 2.0F, 0.6F + random.nextFloat() * 0.4F); + } + + private void tryAwardItSpreadsAdvancement(Level level, LivingEntity entity) { +- if (entity.getLastHurtByMob() instanceof ServerPlayer serverPlayer) { +- DamageSource damageSource = entity.getLastDamageSource() == null +- ? level.damageSources().playerAttack(serverPlayer) +- : entity.getLastDamageSource(); +- CriteriaTriggers.KILL_MOB_NEAR_SCULK_CATALYST.trigger(serverPlayer, entity, damageSource); ++ LivingEntity entityliving1 = entity.getLastHurtByMob(); ++ ++ if (entityliving1 instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entityliving1; ++ DamageSource damagesource = entity.getLastDamageSource() == null ? level.damageSources().playerAttack(entityplayer) : entity.getLastDamageSource(); ++ ++ CriteriaTriggers.KILL_MOB_NEAR_SCULK_CATALYST.trigger(entityplayer, entity, damagesource); + } ++ + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java.patch new file mode 100644 index 0000000000..b8b528fc28 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java.patch @@ -0,0 +1,288 @@ +--- a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.level.block.entity; + ++import java.util.Iterator; + import java.util.List; + import java.util.stream.IntStream; + import javax.annotation.Nullable; +@@ -14,7 +15,7 @@ + import net.minecraft.world.ContainerHelper; + import net.minecraft.world.WorldlyContainer; + import net.minecraft.world.entity.Entity; +-import net.minecraft.world.entity.MoverType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.monster.Shulker; + import net.minecraft.world.entity.player.Inventory; + import net.minecraft.world.entity.player.Player; +@@ -25,13 +26,18 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.ShulkerBoxBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; +-import net.minecraft.world.level.material.PushReaction; ++import net.minecraft.world.level.material.EnumPistonReaction; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end + + public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity implements WorldlyContainer { ++ + public static final int COLUMNS = 9; + public static final int ROWS = 3; + public static final int CONTAINER_SIZE = 27; +@@ -41,29 +47,64 @@ + public static final float MAX_LID_ROTATION = 270.0F; + public static final String ITEMS_TAG = "Items"; + private static final int[] SLOTS = IntStream.range(0, 27).toArray(); +- private NonNullList itemStacks = NonNullList.withSize(27, ItemStack.EMPTY); +- private int openCount; +- private ShulkerBoxBlockEntity.AnimationStatus animationStatus = ShulkerBoxBlockEntity.AnimationStatus.CLOSED; ++ private NonNullList itemStacks; ++ public int openCount; ++ private ShulkerBoxBlockEntity.AnimationPhase animationStatus; + private float progress; + private float progressOld; + @Nullable + private final DyeColor color; + +- public ShulkerBoxBlockEntity(@Nullable DyeColor color, BlockPos pos, BlockState blockState) { ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ public boolean opened; ++ ++ public List getContents() { ++ return this.itemStacks; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ ++ public ShulkerBoxBlockEntity(@Nullable DyeColor color, BlockPos pos, IBlockData blockState) { + super(BlockEntityType.SHULKER_BOX, pos, blockState); ++ this.itemStacks = NonNullList.withSize(27, ItemStack.EMPTY); ++ this.animationStatus = ShulkerBoxBlockEntity.AnimationPhase.CLOSED; + this.color = color; + } + +- public ShulkerBoxBlockEntity(BlockPos pos, BlockState blockState) { ++ public ShulkerBoxBlockEntity(BlockPos pos, IBlockData blockState) { + super(BlockEntityType.SHULKER_BOX, pos, blockState); ++ this.itemStacks = NonNullList.withSize(27, ItemStack.EMPTY); ++ this.animationStatus = ShulkerBoxBlockEntity.AnimationPhase.CLOSED; + this.color = ShulkerBoxBlock.getColorFromBlock(blockState.getBlock()); + } + +- public static void tick(Level level, BlockPos pos, BlockState state, ShulkerBoxBlockEntity blockEntity) { ++ public static void tick(Level level, BlockPos pos, IBlockData state, ShulkerBoxBlockEntity blockEntity) { + blockEntity.updateAnimation(level, pos, state); + } + +- private void updateAnimation(Level level, BlockPos pos, BlockState state) { ++ private void updateAnimation(Level level, BlockPos pos, IBlockData state) { + this.progressOld = this.progress; + switch (this.animationStatus) { + case CLOSED: +@@ -76,7 +117,7 @@ + } + + if (this.progress >= 1.0F) { +- this.animationStatus = ShulkerBoxBlockEntity.AnimationStatus.OPENED; ++ this.animationStatus = ShulkerBoxBlockEntity.AnimationPhase.OPENED; + this.progress = 1.0F; + doNeighborUpdates(level, pos, state); + } +@@ -90,7 +131,7 @@ + } + + if (this.progress <= 0.0F) { +- this.animationStatus = ShulkerBoxBlockEntity.AnimationStatus.CLOSED; ++ this.animationStatus = ShulkerBoxBlockEntity.AnimationPhase.CLOSED; + this.progress = 0.0F; + doNeighborUpdates(level, pos, state); + } +@@ -98,34 +139,34 @@ + case OPENED: + this.progress = 1.0F; + } ++ + } + +- public ShulkerBoxBlockEntity.AnimationStatus getAnimationStatus() { ++ public ShulkerBoxBlockEntity.AnimationPhase getAnimationStatus() { + return this.animationStatus; + } + +- public AABB getBoundingBox(BlockState state) { +- return Shulker.getProgressAabb(state.getValue(ShulkerBoxBlock.FACING), 0.5F * this.getProgress(1.0F)); ++ public AABB getBoundingBox(IBlockData state) { ++ return Shulker.getProgressAabb((Direction) state.getValue(ShulkerBoxBlock.FACING), 0.5F * this.getProgress(1.0F)); + } + +- private void moveCollidedEntities(Level level, BlockPos pos, BlockState state) { ++ private void moveCollidedEntities(Level level, BlockPos pos, IBlockData state) { + if (state.getBlock() instanceof ShulkerBoxBlock) { +- Direction direction = state.getValue(ShulkerBoxBlock.FACING); +- AABB aABB = Shulker.getProgressDeltaAabb(direction, this.progressOld, this.progress).move(pos); +- List entities = level.getEntities(null, aABB); +- if (!entities.isEmpty()) { +- for (Entity entity : entities) { +- if (entity.getPistonPushReaction() != PushReaction.IGNORE) { +- entity.move( +- MoverType.SHULKER_BOX, +- new Vec3( +- (aABB.getXsize() + 0.01) * (double)direction.getStepX(), +- (aABB.getYsize() + 0.01) * (double)direction.getStepY(), +- (aABB.getZsize() + 0.01) * (double)direction.getStepZ() +- ) +- ); ++ Direction enumdirection = (Direction) state.getValue(ShulkerBoxBlock.FACING); ++ AABB axisalignedbb = Shulker.getProgressDeltaAabb(enumdirection, this.progressOld, this.progress).move(pos); ++ List list = level.getEntities((Entity) null, axisalignedbb); ++ ++ if (!list.isEmpty()) { ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ ++ if (entity.getPistonPushReaction() != EnumPistonReaction.IGNORE) { ++ entity.move(EnumMoveType.SHULKER_BOX, new Vec3((axisalignedbb.getXsize() + 0.01D) * (double) enumdirection.getStepX(), (axisalignedbb.getYsize() + 0.01D) * (double) enumdirection.getStepY(), (axisalignedbb.getZsize() + 0.01D) * (double) enumdirection.getStepZ())); + } + } ++ + } + } + } +@@ -140,11 +181,11 @@ + if (id == 1) { + this.openCount = type; + if (type == 0) { +- this.animationStatus = ShulkerBoxBlockEntity.AnimationStatus.CLOSING; ++ this.animationStatus = ShulkerBoxBlockEntity.AnimationPhase.CLOSING; + } + + if (type == 1) { +- this.animationStatus = ShulkerBoxBlockEntity.AnimationStatus.OPENING; ++ this.animationStatus = ShulkerBoxBlockEntity.AnimationPhase.OPENING; + } + + return true; +@@ -153,7 +194,7 @@ + } + } + +- private static void doNeighborUpdates(Level level, BlockPos pos, BlockState state) { ++ private static void doNeighborUpdates(Level level, BlockPos pos, IBlockData state) { + state.updateNeighbourShapes(level, pos, 3); + level.updateNeighborsAt(pos, state.getBlock()); + } +@@ -165,27 +206,29 @@ + this.openCount = 0; + } + +- this.openCount++; ++ ++this.openCount; ++ if (opened) return; // CraftBukkit - only animate if the ShulkerBox hasn't been forced open already by an API call. + this.level.blockEvent(this.worldPosition, this.getBlockState().getBlock(), 1, this.openCount); + if (this.openCount == 1) { +- this.level.gameEvent(player, GameEvent.CONTAINER_OPEN, this.worldPosition); +- this.level +- .playSound(null, this.worldPosition, SoundEvents.SHULKER_BOX_OPEN, SoundSource.BLOCKS, 0.5F, this.level.random.nextFloat() * 0.1F + 0.9F); ++ this.level.gameEvent((Entity) player, GameEvent.CONTAINER_OPEN, this.worldPosition); ++ this.level.playSound((Player) null, this.worldPosition, SoundEvents.SHULKER_BOX_OPEN, SoundSource.BLOCKS, 0.5F, this.level.random.nextFloat() * 0.1F + 0.9F); + } + } ++ + } + + @Override + public void stopOpen(Player player) { + if (!this.remove && !player.isSpectator()) { +- this.openCount--; ++ --this.openCount; ++ if (opened) return; // CraftBukkit - only animate if the ShulkerBox hasn't been forced open already by an API call. + this.level.blockEvent(this.worldPosition, this.getBlockState().getBlock(), 1, this.openCount); + if (this.openCount <= 0) { +- this.level.gameEvent(player, GameEvent.CONTAINER_CLOSE, this.worldPosition); +- this.level +- .playSound(null, this.worldPosition, SoundEvents.SHULKER_BOX_CLOSE, SoundSource.BLOCKS, 0.5F, this.level.random.nextFloat() * 0.1F + 0.9F); ++ this.level.gameEvent((Entity) player, GameEvent.CONTAINER_CLOSE, this.worldPosition); ++ this.level.playSound((Player) null, this.worldPosition, SoundEvents.SHULKER_BOX_CLOSE, SoundSource.BLOCKS, 0.5F, this.level.random.nextFloat() * 0.1F + 0.9F); + } + } ++ + } + + @Override +@@ -205,6 +248,7 @@ + if (!this.trySaveLootTable(tag)) { + ContainerHelper.saveAllItems(tag, this.itemStacks, false); + } ++ + } + + public void loadFromTag(CompoundTag tag) { +@@ -212,6 +256,7 @@ + if (!this.tryLoadLootTable(tag) && tag.contains("Items", 9)) { + ContainerHelper.loadAllItems(tag, this.itemStacks); + } ++ + } + + @Override +@@ -226,7 +271,7 @@ + + @Override + public int[] getSlotsForFace(Direction side) { +- return SLOTS; ++ return ShulkerBoxBlockEntity.SLOTS; + } + + @Override +@@ -254,13 +299,13 @@ + } + + public boolean isClosed() { +- return this.animationStatus == ShulkerBoxBlockEntity.AnimationStatus.CLOSED; ++ return this.animationStatus == ShulkerBoxBlockEntity.AnimationPhase.CLOSED; + } + +- public static enum AnimationStatus { +- CLOSED, +- OPENING, +- OPENED, +- CLOSING; ++ public static enum AnimationPhase { ++ ++ CLOSED, OPENING, OPENED, CLOSING; ++ ++ private AnimationPhase() {} + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/SignBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/SignBlockEntity.java.patch new file mode 100644 index 0000000000..889f8ddafa --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/SignBlockEntity.java.patch @@ -0,0 +1,395 @@ +--- a/net/minecraft/world/level/block/entity/SignBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/SignBlockEntity.java +@@ -2,7 +2,9 @@ + + import com.mojang.brigadier.exceptions.CommandSyntaxException; + import com.mojang.logging.LogUtils; ++import com.mojang.serialization.DataResult; + import java.util.List; ++import java.util.Objects; + import java.util.UUID; + import java.util.function.UnaryOperator; + import javax.annotation.Nullable; +@@ -18,48 +20,63 @@ + import net.minecraft.network.chat.Style; + import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.network.FilteredText; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.util.Mth; +-import net.minecraft.world.entity.player.Player; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.Level; ++import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.SignBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; ++import org.bukkit.block.sign.Side; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.entity.Player; ++import org.bukkit.event.block.SignChangeEvent; ++// CraftBukkit end + +-public class SignBlockEntity extends BlockEntity { ++public class SignBlockEntity extends BlockEntity implements CommandSource { // CraftBukkit - implements ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int MAX_TEXT_LINE_WIDTH = 90; + private static final int TEXT_LINE_HEIGHT = 10; + @Nullable +- private UUID playerWhoMayEdit; +- private SignText frontText = this.createDefaultSignText(); +- private SignText backText = this.createDefaultSignText(); ++ public UUID playerWhoMayEdit; ++ private SignText frontText; ++ private SignText backText; + private boolean isWaxed; + +- public SignBlockEntity(BlockPos pos, BlockState blockState) { ++ public SignBlockEntity(BlockPos pos, IBlockData blockState) { + this(BlockEntityType.SIGN, pos, blockState); + } + +- public SignBlockEntity(BlockEntityType type, BlockPos pos, BlockState blockState) { ++ public SignBlockEntity(BlockEntityType type, BlockPos pos, IBlockData blockState) { + super(type, pos, blockState); ++ this.frontText = this.createDefaultSignText(); ++ this.backText = this.createDefaultSignText(); + } + + protected SignText createDefaultSignText() { + return new SignText(); + } + +- public boolean isFacingFrontText(Player player) { +- if (this.getBlockState().getBlock() instanceof SignBlock signBlock) { +- Vec3 signHitboxCenterPosition = signBlock.getSignHitboxCenterPosition(this.getBlockState()); +- double d = player.getX() - ((double)this.getBlockPos().getX() + signHitboxCenterPosition.x); +- double d1 = player.getZ() - ((double)this.getBlockPos().getZ() + signHitboxCenterPosition.z); +- float yRotationDegrees = signBlock.getYRotationDegrees(this.getBlockState()); +- float f = (float)(Mth.atan2(d1, d) * 180.0F / (float)Math.PI) - 90.0F; +- return Mth.degreesDifferenceAbs(yRotationDegrees, f) <= 90.0F; ++ public boolean isFacingFrontText(net.minecraft.world.entity.player.Player player) { ++ Block block = this.getBlockState().getBlock(); ++ ++ if (block instanceof SignBlock) { ++ SignBlock blocksign = (SignBlock) block; ++ Vec3 vec3d = blocksign.getSignHitboxCenterPosition(this.getBlockState()); ++ double d0 = player.getX() - ((double) this.getBlockPos().getX() + vec3d.x); ++ double d1 = player.getZ() - ((double) this.getBlockPos().getZ() + vec3d.z); ++ float f = blocksign.getYRotationDegrees(this.getBlockState()); ++ float f1 = (float) (Mth.atan2(d1, d0) * 57.2957763671875D) - 90.0F; ++ ++ return Mth.degreesDifferenceAbs(f, f1) <= 90.0F; + } else { + return false; + } +@@ -88,87 +105,132 @@ + @Override + protected void saveAdditional(CompoundTag tag) { + super.saveAdditional(tag); +- SignText.DIRECT_CODEC +- .encodeStart(NbtOps.INSTANCE, this.frontText) +- .resultOrPartial(LOGGER::error) +- .ifPresent(frontTextTag -> tag.put("front_text", frontTextTag)); +- SignText.DIRECT_CODEC +- .encodeStart(NbtOps.INSTANCE, this.backText) +- .resultOrPartial(LOGGER::error) +- .ifPresent(backTextTag -> tag.put("back_text", backTextTag)); ++ DataResult dataresult = SignText.DIRECT_CODEC.encodeStart(NbtOps.INSTANCE, this.frontText); // CraftBukkit - decompile error ++ Logger logger = SignBlockEntity.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ tag.put("front_text", nbtbase); ++ }); ++ dataresult = SignText.DIRECT_CODEC.encodeStart(NbtOps.INSTANCE, this.backText); ++ logger = SignBlockEntity.LOGGER; ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ tag.put("back_text", nbtbase); ++ }); + tag.putBoolean("is_waxed", this.isWaxed); + } + + @Override + public void load(CompoundTag tag) { + super.load(tag); ++ DataResult dataresult; // CraftBukkit - decompile error ++ Logger logger; ++ + if (tag.contains("front_text")) { +- SignText.DIRECT_CODEC +- .parse(NbtOps.INSTANCE, tag.getCompound("front_text")) +- .resultOrPartial(LOGGER::error) +- .ifPresent(signText -> this.frontText = this.loadLines(signText)); ++ dataresult = SignText.DIRECT_CODEC.parse(NbtOps.INSTANCE, tag.getCompound("front_text")); ++ logger = SignBlockEntity.LOGGER; ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((signtext) -> { ++ this.frontText = this.loadLines(signtext); ++ }); + } + + if (tag.contains("back_text")) { +- SignText.DIRECT_CODEC +- .parse(NbtOps.INSTANCE, tag.getCompound("back_text")) +- .resultOrPartial(LOGGER::error) +- .ifPresent(signText -> this.backText = this.loadLines(signText)); ++ dataresult = SignText.DIRECT_CODEC.parse(NbtOps.INSTANCE, tag.getCompound("back_text")); ++ logger = SignBlockEntity.LOGGER; ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((signtext) -> { ++ this.backText = this.loadLines(signtext); ++ }); + } + + this.isWaxed = tag.getBoolean("is_waxed"); + } + + private SignText loadLines(SignText text) { +- for (int i = 0; i < 4; i++) { +- Component component = this.loadLine(text.getMessage(i, false)); +- Component component1 = this.loadLine(text.getMessage(i, true)); +- text = text.setMessage(i, component, component1); ++ for (int i = 0; i < 4; ++i) { ++ Component ichatbasecomponent = this.loadLine(text.getMessage(i, false)); ++ Component ichatbasecomponent1 = this.loadLine(text.getMessage(i, true)); ++ ++ text = text.setMessage(i, ichatbasecomponent, ichatbasecomponent1); + } + + return text; + } + + private Component loadLine(Component lineText) { +- if (this.level instanceof ServerLevel serverLevel) { ++ Level world = this.level; ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ + try { +- return ComponentUtils.updateForEntity(createCommandSourceStack(null, serverLevel, this.worldPosition), lineText, null, 0); +- } catch (CommandSyntaxException var4) { ++ return ComponentUtils.updateForEntity(createCommandSourceStack((net.minecraft.world.entity.player.Player) null, worldserver, this.worldPosition), lineText, (Entity) null, 0); ++ } catch (CommandSyntaxException commandsyntaxexception) { ++ ; + } + } + + return lineText; + } + +- public void updateSignText(Player player, boolean isFrontText, List filteredText) { ++ public void updateSignText(net.minecraft.world.entity.player.Player player, boolean isFrontText, List filteredText) { + if (!this.isWaxed() && player.getUUID().equals(this.getPlayerWhoMayEdit()) && this.level != null) { +- this.updateText(signText -> this.setMessages(player, filteredText, signText), isFrontText); +- this.setAllowedPlayerEditor(null); ++ this.updateText((signtext) -> { ++ return this.setMessages(player, filteredText, signtext, isFrontText); // CraftBukkit ++ }, isFrontText); ++ this.setAllowedPlayerEditor((UUID) null); + this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3); + } else { +- LOGGER.warn("Player {} just tried to change non-editable sign", player.getName().getString()); ++ SignBlockEntity.LOGGER.warn("Player {} just tried to change non-editable sign", player.getName().getString()); ++ ((ServerPlayer) player).connection.send(this.getUpdatePacket()); // CraftBukkit + } + } + + public boolean updateText(UnaryOperator updater, boolean isFrontText) { +- SignText text = this.getText(isFrontText); +- return this.setText(updater.apply(text), isFrontText); ++ SignText signtext = this.getText(isFrontText); ++ ++ return this.setText((SignText) updater.apply(signtext), isFrontText); + } + +- private SignText setMessages(Player player, List filteredText, SignText text) { +- for (int i = 0; i < filteredText.size(); i++) { +- FilteredText filteredText1 = filteredText.get(i); +- Style style = text.getMessage(i, player.isTextFilteringEnabled()).getStyle(); +- if (player.isTextFilteringEnabled()) { +- text = text.setMessage(i, Component.literal(filteredText1.filteredOrEmpty()).setStyle(style)); ++ private SignText setMessages(net.minecraft.world.entity.player.Player entityhuman, List list, SignText signtext, boolean front) { // CraftBukkit ++ SignText originalText = signtext; // CraftBukkit ++ for (int i = 0; i < list.size(); ++i) { ++ FilteredText filteredtext = (FilteredText) list.get(i); ++ Style chatmodifier = signtext.getMessage(i, entityhuman.isTextFilteringEnabled()).getStyle(); ++ ++ if (entityhuman.isTextFilteringEnabled()) { ++ signtext = signtext.setMessage(i, Component.literal(filteredtext.filteredOrEmpty()).setStyle(chatmodifier)); + } else { +- text = text.setMessage( +- i, Component.literal(filteredText1.raw()).setStyle(style), Component.literal(filteredText1.filteredOrEmpty()).setStyle(style) +- ); ++ signtext = signtext.setMessage(i, Component.literal(filteredtext.raw()).setStyle(chatmodifier), Component.literal(filteredtext.filteredOrEmpty()).setStyle(chatmodifier)); + } + } + +- return text; ++ // CraftBukkit start ++ Player player = ((ServerPlayer) entityhuman).getBukkitEntity(); ++ String[] lines = new String[4]; ++ ++ for (int i = 0; i < list.size(); ++i) { ++ lines[i] = CraftChatMessage.fromComponent(signtext.getMessage(i, entityhuman.isTextFilteringEnabled())); ++ } ++ ++ SignChangeEvent event = new SignChangeEvent(CraftBlock.at(this.level, this.worldPosition), player, lines.clone(), (front) ? Side.FRONT : Side.BACK); ++ entityhuman.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return originalText; ++ } ++ ++ Component[] components = org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()); ++ for (int i = 0; i < components.length; i++) { ++ if (!Objects.equals(lines[i], event.getLine(i))) { ++ signtext = signtext.setMessage(i, components[i]); ++ } ++ } ++ // CraftBukkit end ++ ++ return signtext; + } + + public boolean setText(SignText text, boolean isFrontText) { +@@ -195,32 +257,63 @@ + } + } + +- public boolean canExecuteClickCommands(boolean isFrontText, Player player) { ++ public boolean canExecuteClickCommands(boolean isFrontText, net.minecraft.world.entity.player.Player player) { + return this.isWaxed() && this.getText(isFrontText).hasAnyClickCommands(player); + } + +- public boolean executeClickCommandsIfPresent(Player player, Level level, BlockPos pos, boolean frontText) { +- boolean flag = false; ++ public boolean executeClickCommandsIfPresent(net.minecraft.world.entity.player.Player player, Level level, BlockPos pos, boolean frontText) { ++ boolean flag1 = false; ++ Component[] aichatbasecomponent = this.getText(frontText).getMessages(player.isTextFilteringEnabled()); ++ int i = aichatbasecomponent.length; + +- for (Component component : this.getText(frontText).getMessages(player.isTextFilteringEnabled())) { +- Style style = component.getStyle(); +- ClickEvent clickEvent = style.getClickEvent(); +- if (clickEvent != null && clickEvent.getAction() == ClickEvent.Action.RUN_COMMAND) { +- player.getServer().getCommands().performPrefixedCommand(createCommandSourceStack(player, level, pos), clickEvent.getValue()); +- flag = true; ++ for (int j = 0; j < i; ++j) { ++ Component ichatbasecomponent = aichatbasecomponent[j]; ++ Style chatmodifier = ichatbasecomponent.getStyle(); ++ ClickEvent chatclickable = chatmodifier.getClickEvent(); ++ ++ if (chatclickable != null && chatclickable.getAction() == ClickEvent.Action.RUN_COMMAND) { ++ player.getServer().getCommands().performPrefixedCommand(createCommandSourceStack(player, level, pos), chatclickable.getValue()); ++ flag1 = true; + } + } + +- return flag; ++ return flag1; + } + +- private static CommandSourceStack createCommandSourceStack(@Nullable Player player, Level level, BlockPos pos) { +- String string = player == null ? "Sign" : player.getName().getString(); +- Component component = (Component)(player == null ? Component.literal("Sign") : player.getDisplayName()); +- return new CommandSourceStack(CommandSource.NULL, Vec3.atCenterOf(pos), Vec2.ZERO, (ServerLevel)level, 2, string, component, level.getServer(), player); ++ // CraftBukkit start ++ @Override ++ public void sendSystemMessage(Component component) {} ++ ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) { ++ return wrapper.getEntity() != null ? wrapper.getEntity().getBukkitSender(wrapper) : new org.bukkit.craftbukkit.command.CraftBlockCommandSender(wrapper, this); + } + + @Override ++ public boolean acceptsSuccess() { ++ return false; ++ } ++ ++ @Override ++ public boolean acceptsFailure() { ++ return false; ++ } ++ ++ @Override ++ public boolean shouldInformAdmins() { ++ return false; ++ } ++ ++ private CommandSourceStack createCommandSourceStack(@Nullable net.minecraft.world.entity.player.Player level, Level pos, BlockPos blockposition) { ++ // CraftBukkit end ++ String s = level == null ? "Sign" : level.getName().getString(); ++ Object object = level == null ? Component.literal("Sign") : level.getDisplayName(); ++ ++ // CraftBukkit - this ++ return new CommandSourceStack(this, Vec3.atCenterOf(blockposition), Vec2.ZERO, (ServerLevel) pos, 2, s, (Component) object, pos.getServer(), level); ++ } ++ ++ @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } +@@ -241,12 +334,17 @@ + + @Nullable + public UUID getPlayerWhoMayEdit() { ++ // CraftBukkit start - unnecessary sign ticking removed, so do this lazily ++ if (this.level != null && this.playerWhoMayEdit != null) { ++ clearInvalidPlayerWhoMayEdit(this, this.level, this.playerWhoMayEdit); ++ } ++ // CraftBukkit end + return this.playerWhoMayEdit; + } + + private void markUpdated() { + this.setChanged(); +- this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3); ++ if (this.level != null) this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3); // CraftBukkit - skip notify if world is null (SPIGOT-5122) + } + + public boolean isWaxed() { +@@ -264,22 +362,25 @@ + } + + public boolean playerIsTooFarAwayToEdit(UUID uuid) { +- Player playerByUUID = this.level.getPlayerByUUID(uuid); +- return playerByUUID == null +- || playerByUUID.distanceToSqr((double)this.getBlockPos().getX(), (double)this.getBlockPos().getY(), (double)this.getBlockPos().getZ()) > 64.0; ++ net.minecraft.world.entity.player.Player entityhuman = this.level.getPlayerByUUID(uuid); ++ ++ return entityhuman == null || entityhuman.distanceToSqr((double) this.getBlockPos().getX(), (double) this.getBlockPos().getY(), (double) this.getBlockPos().getZ()) > 64.0D; + } + +- public static void tick(Level level, BlockPos pos, BlockState state, SignBlockEntity sign) { +- UUID playerWhoMayEdit = sign.getPlayerWhoMayEdit(); +- if (playerWhoMayEdit != null) { +- sign.clearInvalidPlayerWhoMayEdit(sign, level, playerWhoMayEdit); ++ public static void tick(Level level, BlockPos pos, IBlockData state, SignBlockEntity sign) { ++ UUID uuid = sign.getPlayerWhoMayEdit(); ++ ++ if (uuid != null) { ++ sign.clearInvalidPlayerWhoMayEdit(sign, level, uuid); + } ++ + } + + private void clearInvalidPlayerWhoMayEdit(SignBlockEntity sign, Level level, UUID uuid) { + if (sign.playerIsTooFarAwayToEdit(uuid)) { +- sign.setAllowedPlayerEditor(null); ++ sign.setAllowedPlayerEditor((UUID) null); + } ++ + } + + public SoundEvent getSignInteractionFailedSoundEvent() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/SkullBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/SkullBlockEntity.java.patch new file mode 100644 index 0000000000..351ac9710d --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/SkullBlockEntity.java.patch @@ -0,0 +1,241 @@ +--- a/net/minecraft/world/level/block/entity/SkullBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/SkullBlockEntity.java +@@ -23,61 +23,60 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.SkullBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public class SkullBlockEntity extends BlockEntity { ++ + public static final String TAG_SKULL_OWNER = "SkullOwner"; + public static final String TAG_NOTE_BLOCK_SOUND = "note_block_sound"; + @Nullable + private static Executor mainThreadExecutor; + @Nullable + private static LoadingCache>> profileCache; +- private static final Executor CHECKED_MAIN_THREAD_EXECUTOR = runnable -> { +- Executor executor = mainThreadExecutor; ++ private static final Executor CHECKED_MAIN_THREAD_EXECUTOR = (runnable) -> { ++ Executor executor = SkullBlockEntity.mainThreadExecutor; ++ + if (executor != null) { + executor.execute(runnable); + } ++ + }; + @Nullable +- private GameProfile owner; ++ public GameProfile owner; + @Nullable +- private ResourceLocation noteBlockSound; ++ public ResourceLocation noteBlockSound; + private int animationTickCount; + private boolean isAnimating; + +- public SkullBlockEntity(BlockPos pos, BlockState blockState) { ++ public SkullBlockEntity(BlockPos pos, IBlockData blockState) { + super(BlockEntityType.SKULL, pos, blockState); + } + + public static void setup(final Services services, Executor mainThreadExecutor) { + SkullBlockEntity.mainThreadExecutor = mainThreadExecutor; +- final BooleanSupplier booleanSupplier = () -> profileCache == null; +- profileCache = CacheBuilder.newBuilder() +- .expireAfterAccess(Duration.ofMinutes(10L)) +- .maximumSize(256L) +- .build( +- new CacheLoader>>() { +- @Override +- public CompletableFuture> load(String string) { +- return booleanSupplier.getAsBoolean() +- ? CompletableFuture.completedFuture(Optional.empty()) +- : SkullBlockEntity.loadProfile(string, services, booleanSupplier); +- } +- } +- ); ++ final BooleanSupplier booleansupplier = () -> { ++ return SkullBlockEntity.profileCache == null; ++ }; ++ ++ SkullBlockEntity.profileCache = CacheBuilder.newBuilder().expireAfterAccess(Duration.ofMinutes(10L)).maximumSize(256L).build(new CacheLoader>>() { ++ public CompletableFuture> load(String s) { ++ return booleansupplier.getAsBoolean() ? CompletableFuture.completedFuture(Optional.empty()) : SkullBlockEntity.loadProfile(s, services, booleansupplier); ++ } ++ }); + } + + public static void clear() { +- mainThreadExecutor = null; +- profileCache = null; ++ SkullBlockEntity.mainThreadExecutor = null; ++ SkullBlockEntity.profileCache = null; + } + +- static CompletableFuture> loadProfile(String string, Services services, BooleanSupplier booleanSupplier) { +- return services.profileCache().getAsync(string).thenApplyAsync(optional -> { +- if (optional.isPresent() && !booleanSupplier.getAsBoolean()) { +- UUID id = optional.get().getId(); +- ProfileResult profileResult = services.sessionService().fetchProfile(id, true); +- return profileResult != null ? Optional.ofNullable(profileResult.profile()) : optional; ++ static CompletableFuture> loadProfile(String s, Services services, BooleanSupplier booleansupplier) { ++ return services.profileCache().getAsync(s).thenApplyAsync((optional) -> { ++ if (optional.isPresent() && !booleansupplier.getAsBoolean()) { ++ UUID uuid = ((GameProfile) optional.get()).getId(); ++ ProfileResult profileresult = services.sessionService().fetchProfile(uuid, true); ++ ++ return profileresult != null ? Optional.ofNullable(profileresult.profile()) : optional; + } else { + return Optional.empty(); + } +@@ -88,14 +87,16 @@ + protected void saveAdditional(CompoundTag tag) { + super.saveAdditional(tag); + if (this.owner != null) { +- CompoundTag compoundTag = new CompoundTag(); +- NbtUtils.writeGameProfile(compoundTag, this.owner); +- tag.put("SkullOwner", compoundTag); ++ CompoundTag nbttagcompound1 = new CompoundTag(); ++ ++ NbtUtils.writeGameProfile(nbttagcompound1, this.owner); ++ tag.put("SkullOwner", nbttagcompound1); + } + + if (this.noteBlockSound != null) { + tag.putString("note_block_sound", this.noteBlockSound.toString()); + } ++ + } + + @Override +@@ -104,28 +105,31 @@ + if (tag.contains("SkullOwner", 10)) { + this.setOwner(NbtUtils.readGameProfile(tag.getCompound("SkullOwner"))); + } else if (tag.contains("ExtraType", 8)) { +- String string = tag.getString("ExtraType"); +- if (!StringUtil.isNullOrEmpty(string)) { +- this.setOwner(new GameProfile(Util.NIL_UUID, string)); ++ String s = tag.getString("ExtraType"); ++ ++ if (!StringUtil.isNullOrEmpty(s)) { ++ this.setOwner(new GameProfile(Util.NIL_UUID, s)); + } + } + + if (tag.contains("note_block_sound", 8)) { + this.noteBlockSound = ResourceLocation.tryParse(tag.getString("note_block_sound")); + } ++ + } + +- public static void animation(Level level, BlockPos pos, BlockState state, SkullBlockEntity blockEntity) { +- if (state.hasProperty(SkullBlock.POWERED) && state.getValue(SkullBlock.POWERED)) { ++ public static void animation(Level level, BlockPos pos, IBlockData state, SkullBlockEntity blockEntity) { ++ if (state.hasProperty(SkullBlock.POWERED) && (Boolean) state.getValue(SkullBlock.POWERED)) { + blockEntity.isAnimating = true; +- blockEntity.animationTickCount++; ++ ++blockEntity.animationTickCount; + } else { + blockEntity.isAnimating = false; + } ++ + } + + public float getAnimation(float partialTick) { +- return this.isAnimating ? (float)this.animationTickCount + partialTick : (float)this.animationTickCount; ++ return this.isAnimating ? (float) this.animationTickCount + partialTick : (float) this.animationTickCount; + } + + @Nullable +@@ -158,25 +162,26 @@ + + private void updateOwnerProfile() { + if (this.owner != null && !Util.isBlank(this.owner.getName()) && !hasTextures(this.owner)) { +- fetchGameProfile(this.owner.getName()).thenAcceptAsync(optional -> { +- this.owner = optional.orElse(this.owner); ++ fetchGameProfile(this.owner.getName()).thenAcceptAsync((optional) -> { ++ this.owner = (GameProfile) optional.orElse(this.owner); + this.setChanged(); +- }, CHECKED_MAIN_THREAD_EXECUTOR); ++ }, SkullBlockEntity.CHECKED_MAIN_THREAD_EXECUTOR); + } else { + this.setChanged(); + } + } + + @Nullable +- public static GameProfile getOrResolveGameProfile(CompoundTag compoundTag) { +- if (compoundTag.contains("SkullOwner", 10)) { +- return NbtUtils.readGameProfile(compoundTag.getCompound("SkullOwner")); ++ public static GameProfile getOrResolveGameProfile(CompoundTag nbttagcompound) { ++ if (nbttagcompound.contains("SkullOwner", 10)) { ++ return NbtUtils.readGameProfile(nbttagcompound.getCompound("SkullOwner")); + } else { +- if (compoundTag.contains("SkullOwner", 8)) { +- String string = compoundTag.getString("SkullOwner"); +- if (!Util.isBlank(string)) { +- compoundTag.remove("SkullOwner"); +- resolveGameProfile(compoundTag, string); ++ if (nbttagcompound.contains("SkullOwner", 8)) { ++ String s = nbttagcompound.getString("SkullOwner"); ++ ++ if (!Util.isBlank(s)) { ++ nbttagcompound.remove("SkullOwner"); ++ resolveGameProfile(nbttagcompound, s); + } + } + +@@ -184,26 +189,38 @@ + } + } + +- public static void resolveGameProfile(CompoundTag compoundTag) { +- String string = compoundTag.getString("SkullOwner"); +- if (!Util.isBlank(string)) { +- resolveGameProfile(compoundTag, string); ++ public static void resolveGameProfile(CompoundTag nbttagcompound) { ++ String s = nbttagcompound.getString("SkullOwner"); ++ ++ if (!Util.isBlank(s)) { ++ resolveGameProfile(nbttagcompound, s); ++ // CraftBukkit start ++ } else { ++ net.minecraft.nbt.ListTag textures = nbttagcompound.getCompound("SkullOwner").getCompound("Properties").getList("textures", 10); // Safe due to method contracts ++ for (int i = 0; i < textures.size(); i++) { ++ if (textures.get(i) instanceof CompoundTag && !((CompoundTag) textures.get(i)).contains("Signature", 8) && ((CompoundTag) textures.get(i)).getString("Value").trim().isEmpty()) { ++ nbttagcompound.remove("SkullOwner"); ++ break; ++ } ++ } ++ // CraftBukkit end + } ++ + } + +- private static void resolveGameProfile(CompoundTag compoundTag, String string) { +- fetchGameProfile(string) +- .thenAccept( +- optional -> compoundTag.put("SkullOwner", NbtUtils.writeGameProfile(new CompoundTag(), optional.orElse(new GameProfile(Util.NIL_UUID, string)))) +- ); ++ private static void resolveGameProfile(CompoundTag nbttagcompound, String s) { ++ fetchGameProfile(s).thenAccept((optional) -> { ++ nbttagcompound.put("SkullOwner", NbtUtils.writeGameProfile(new CompoundTag(), (GameProfile) optional.orElse(new GameProfile(Util.NIL_UUID, s)))); ++ }); + } + +- private static CompletableFuture> fetchGameProfile(String string) { +- LoadingCache>> loadingCache = profileCache; +- return loadingCache != null && Player.isValidUsername(string) ? loadingCache.getUnchecked(string) : CompletableFuture.completedFuture(Optional.empty()); ++ private static CompletableFuture> fetchGameProfile(String s) { ++ LoadingCache>> loadingcache = SkullBlockEntity.profileCache; ++ ++ return loadingcache != null && Player.isValidUsername(s) ? (CompletableFuture) loadingcache.getUnchecked(s) : CompletableFuture.completedFuture(Optional.empty()); + } + +- private static boolean hasTextures(GameProfile gameProfile) { +- return gameProfile.getProperties().containsKey("textures"); ++ private static boolean hasTextures(GameProfile gameprofile) { ++ return gameprofile.getProperties().containsKey("textures"); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java.patch new file mode 100644 index 0000000000..b88f99ba78 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java.patch @@ -0,0 +1,425 @@ +--- a/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +@@ -1,13 +1,12 @@ + package net.minecraft.world.level.block.entity; + + import com.mojang.logging.LogUtils; ++import java.util.Iterator; + import java.util.List; + import javax.annotation.Nullable; + import net.minecraft.advancements.CriteriaTriggers; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.Holder; +-import net.minecraft.core.Registry; + import net.minecraft.core.registries.Registries; + import net.minecraft.data.worldgen.features.EndFeatures; + import net.minecraft.nbt.CompoundTag; +@@ -25,28 +24,36 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.LevelChunk; ++import net.minecraft.world.level.dimension.LevelStem; ++import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; + import net.minecraft.world.level.levelgen.feature.Feature; + import net.minecraft.world.level.levelgen.feature.configurations.EndGatewayConfiguration; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import org.slf4j.Logger; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.player.PlayerTeleportEvent; ++// CraftBukkit end + + public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int SPAWN_TIME = 200; + private static final int COOLDOWN_TIME = 40; + private static final int ATTENTION_INTERVAL = 2400; + private static final int EVENT_COOLDOWN = 1; + private static final int GATEWAY_HEIGHT_ABOVE_SURFACE = 10; +- private long age; ++ public long age; + private int teleportCooldown; + @Nullable +- private BlockPos exitPortal; +- private boolean exactTeleport; ++ public BlockPos exitPortal; ++ public boolean exactTeleport; + +- public TheEndGatewayBlockEntity(BlockPos pos, BlockState blockState) { ++ public TheEndGatewayBlockEntity(BlockPos pos, IBlockData blockState) { + super(BlockEntityType.END_GATEWAY, pos, blockState); + } + +@@ -61,6 +68,7 @@ + if (this.exactTeleport) { + tag.putBoolean("ExactTeleport", true); + } ++ + } + + @Override +@@ -68,32 +76,36 @@ + super.load(tag); + this.age = tag.getLong("Age"); + if (tag.contains("ExitPortal", 10)) { +- BlockPos blockPos = NbtUtils.readBlockPos(tag.getCompound("ExitPortal")); +- if (Level.isInSpawnableBounds(blockPos)) { +- this.exitPortal = blockPos; ++ BlockPos blockposition = NbtUtils.readBlockPos(tag.getCompound("ExitPortal")); ++ ++ if (Level.isInSpawnableBounds(blockposition)) { ++ this.exitPortal = blockposition; + } + } + + this.exactTeleport = tag.getBoolean("ExactTeleport"); + } + +- public static void beamAnimationTick(Level level, BlockPos pos, BlockState state, TheEndGatewayBlockEntity blockEntity) { +- blockEntity.age++; ++ public static void beamAnimationTick(Level level, BlockPos pos, IBlockData state, TheEndGatewayBlockEntity blockEntity) { ++ ++blockEntity.age; + if (blockEntity.isCoolingDown()) { +- blockEntity.teleportCooldown--; ++ --blockEntity.teleportCooldown; + } ++ + } + +- public static void teleportTick(Level level, BlockPos pos, BlockState state, TheEndGatewayBlockEntity blockEntity) { +- boolean isSpawning = blockEntity.isSpawning(); +- boolean isCoolingDown = blockEntity.isCoolingDown(); +- blockEntity.age++; +- if (isCoolingDown) { +- blockEntity.teleportCooldown--; ++ public static void teleportTick(Level level, BlockPos pos, IBlockData state, TheEndGatewayBlockEntity blockEntity) { ++ boolean flag = blockEntity.isSpawning(); ++ boolean flag1 = blockEntity.isCoolingDown(); ++ ++ ++blockEntity.age; ++ if (flag1) { ++ --blockEntity.teleportCooldown; + } else { +- List entitiesOfClass = level.getEntitiesOfClass(Entity.class, new AABB(pos), TheEndGatewayBlockEntity::canEntityTeleport); +- if (!entitiesOfClass.isEmpty()) { +- teleportEntity(level, pos, state, entitiesOfClass.get(level.random.nextInt(entitiesOfClass.size())), blockEntity); ++ List list = level.getEntitiesOfClass(Entity.class, new AABB(pos), TheEndGatewayBlockEntity::canEntityTeleport); ++ ++ if (!list.isEmpty()) { ++ teleportEntity(level, pos, state, (Entity) list.get(level.random.nextInt(list.size())), blockEntity); + } + + if (blockEntity.age % 2400L == 0L) { +@@ -101,9 +113,10 @@ + } + } + +- if (isSpawning != blockEntity.isSpawning() || isCoolingDown != blockEntity.isCoolingDown()) { ++ if (flag != blockEntity.isSpawning() || flag1 != blockEntity.isCoolingDown()) { + setChanged(level, pos, state); + } ++ + } + + public static boolean canEntityTeleport(Entity entity) { +@@ -119,11 +132,11 @@ + } + + public float getSpawnPercent(float partialTicks) { +- return Mth.clamp(((float)this.age + partialTicks) / 200.0F, 0.0F, 1.0F); ++ return Mth.clamp(((float) this.age + partialTicks) / 200.0F, 0.0F, 1.0F); + } + + public float getCooldownPercent(float partialTicks) { +- return 1.0F - Mth.clamp(((float)this.teleportCooldown - partialTicks) / 40.0F, 0.0F, 1.0F); ++ return 1.0F - Mth.clamp(((float) this.teleportCooldown - partialTicks) / 40.0F, 0.0F, 1.0F); + } + + @Override +@@ -136,12 +149,13 @@ + return this.saveWithoutMetadata(); + } + +- private static void triggerCooldown(Level level, BlockPos pos, BlockState state, TheEndGatewayBlockEntity blockEntity) { ++ private static void triggerCooldown(Level level, BlockPos pos, IBlockData state, TheEndGatewayBlockEntity blockEntity) { + if (!level.isClientSide) { + blockEntity.teleportCooldown = 40; + level.blockEvent(pos, state.getBlock(), 1, 0); + setChanged(level, pos, state); + } ++ + } + + @Override +@@ -154,29 +168,34 @@ + } + } + +- public static void teleportEntity(Level level, BlockPos pos, BlockState state, Entity entity, TheEndGatewayBlockEntity blockEntity) { ++ public static void teleportEntity(Level level, BlockPos pos, IBlockData state, Entity entity, TheEndGatewayBlockEntity blockEntity) { + if (level instanceof ServerLevel && !blockEntity.isCoolingDown()) { +- ServerLevel serverLevel = (ServerLevel)level; ++ ServerLevel worldserver = (ServerLevel) level; ++ + blockEntity.teleportCooldown = 100; +- if (blockEntity.exitPortal == null && level.dimension() == Level.END) { +- BlockPos blockPos = findOrCreateValidTeleportPos(serverLevel, pos); +- blockPos = blockPos.above(10); +- LOGGER.debug("Creating portal at {}", blockPos); +- spawnGatewayPortal(serverLevel, blockPos, EndGatewayConfiguration.knownExit(pos, false)); +- blockEntity.exitPortal = blockPos; ++ BlockPos blockposition1; ++ ++ if (blockEntity.exitPortal == null && level.getTypeKey() == LevelStem.END) { // CraftBukkit - work in alternate worlds ++ blockposition1 = findOrCreateValidTeleportPos(worldserver, pos); ++ blockposition1 = blockposition1.above(10); ++ TheEndGatewayBlockEntity.LOGGER.debug("Creating portal at {}", blockposition1); ++ spawnGatewayPortal(worldserver, blockposition1, EndGatewayConfiguration.knownExit(pos, false)); ++ blockEntity.exitPortal = blockposition1; + } + + if (blockEntity.exitPortal != null) { +- BlockPos blockPos = blockEntity.exactTeleport ? blockEntity.exitPortal : findExitPosition(level, blockEntity.exitPortal); ++ blockposition1 = blockEntity.exactTeleport ? blockEntity.exitPortal : findExitPosition(level, blockEntity.exitPortal); + Entity entity1; ++ + if (entity instanceof ThrownEnderpearl) { +- Entity owner = ((ThrownEnderpearl)entity).getOwner(); +- if (owner instanceof ServerPlayer) { +- CriteriaTriggers.ENTER_BLOCK.trigger((ServerPlayer)owner, state); ++ Entity entity2 = ((ThrownEnderpearl) entity).getOwner(); ++ ++ if (entity2 instanceof ServerPlayer) { ++ CriteriaTriggers.ENTER_BLOCK.trigger((ServerPlayer) entity2, state); + } + +- if (owner != null) { +- entity1 = owner; ++ if (entity2 != null) { ++ entity1 = entity2; + entity.discard(); + } else { + entity1 = entity; +@@ -185,8 +204,34 @@ + entity1 = entity.getRootVehicle(); + } + ++ // CraftBukkit start - Fire PlayerTeleportEvent/EntityTeleportEvent ++ if (entity1 instanceof ServerPlayer) { ++ org.bukkit.craftbukkit.entity.CraftPlayer player = (CraftPlayer) entity1.getBukkitEntity(); ++ org.bukkit.Location location = CraftLocation.toBukkit(blockposition1, level.getWorld()).add(0.5D, 0.5D, 0.5D); ++ location.setPitch(player.getLocation().getPitch()); ++ location.setYaw(player.getLocation().getYaw()); ++ ++ PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.END_GATEWAY); ++ Bukkit.getPluginManager().callEvent(teleEvent); ++ if (teleEvent.isCancelled()) { ++ return; ++ } ++ ++ entity1.setPortalCooldown(); ++ ((ServerPlayer) entity1).connection.teleport(teleEvent.getTo()); ++ triggerCooldown(level, pos, state, blockEntity); // CraftBukkit - call at end of method ++ return; ++ ++ } ++ ++ org.bukkit.event.entity.EntityTeleportEvent teleEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTeleportEvent(entity1, blockposition1.getX() + 0.5, blockposition1.getY() + 0.5, blockposition1.getZ() + 0.5); ++ if (teleEvent.isCancelled()) { ++ return; ++ } ++ + entity1.setPortalCooldown(); +- entity1.teleportToWithTicket((double)blockPos.getX() + 0.5, (double)blockPos.getY(), (double)blockPos.getZ() + 0.5); ++ entity1.teleportToWithTicket(teleEvent.getTo().getX(), teleEvent.getTo().getY(), teleEvent.getTo().getZ()); ++ // CraftBukkit end + } + + triggerCooldown(level, pos, state, blockEntity); +@@ -194,45 +239,51 @@ + } + + private static BlockPos findExitPosition(Level level, BlockPos pos) { +- BlockPos blockPos = findTallestBlock(level, pos.offset(0, 2, 0), 5, false); +- LOGGER.debug("Best exit position for portal at {} is {}", pos, blockPos); +- return blockPos.above(); ++ BlockPos blockposition1 = findTallestBlock(level, pos.offset(0, 2, 0), 5, false); ++ ++ TheEndGatewayBlockEntity.LOGGER.debug("Best exit position for portal at {} is {}", pos, blockposition1); ++ return blockposition1.above(); + } + + private static BlockPos findOrCreateValidTeleportPos(ServerLevel level, BlockPos pos) { +- Vec3 vec3 = findExitPortalXZPosTentative(level, pos); +- LevelChunk chunk = getChunk(level, vec3); +- BlockPos blockPos = findValidSpawnInChunk(chunk); +- if (blockPos == null) { +- BlockPos blockPos1 = BlockPos.containing(vec3.x + 0.5, 75.0, vec3.z + 0.5); +- LOGGER.debug("Failed to find a suitable block to teleport to, spawning an island on {}", blockPos1); +- level.registryAccess() +- .registry(Registries.CONFIGURED_FEATURE) +- .flatMap(configuredFeatureRegistry -> configuredFeatureRegistry.getHolder(EndFeatures.END_ISLAND)) +- .ifPresent(feature -> feature.value().place(level, level.getChunkSource().getGenerator(), RandomSource.create(blockPos1.asLong()), blockPos1)); +- blockPos = blockPos1; ++ Vec3 vec3d = findExitPortalXZPosTentative(level, pos); ++ LevelChunk chunk = getChunk(level, vec3d); ++ BlockPos blockposition1 = findValidSpawnInChunk(chunk); ++ ++ if (blockposition1 == null) { ++ BlockPos blockposition2 = BlockPos.containing(vec3d.x + 0.5D, 75.0D, vec3d.z + 0.5D); ++ ++ TheEndGatewayBlockEntity.LOGGER.debug("Failed to find a suitable block to teleport to, spawning an island on {}", blockposition2); ++ level.registryAccess().registry(Registries.CONFIGURED_FEATURE).flatMap((iregistry) -> { ++ return iregistry.getHolder(EndFeatures.END_ISLAND); ++ }).ifPresent((holder_c) -> { ++ ((ConfiguredFeature) holder_c.value()).place(level, level.getChunkSource().getGenerator(), RandomSource.create(blockposition2.asLong()), blockposition2); ++ }); ++ blockposition1 = blockposition2; + } else { +- LOGGER.debug("Found suitable block to teleport to: {}", blockPos); ++ TheEndGatewayBlockEntity.LOGGER.debug("Found suitable block to teleport to: {}", blockposition1); + } + +- return findTallestBlock(level, blockPos, 16, true); ++ return findTallestBlock(level, blockposition1, 16, true); + } + + private static Vec3 findExitPortalXZPosTentative(ServerLevel level, BlockPos pos) { +- Vec3 vec3 = new Vec3((double)pos.getX(), 0.0, (double)pos.getZ()).normalize(); +- int i = 1024; +- Vec3 vec31 = vec3.scale(1024.0); ++ Vec3 vec3d = (new Vec3((double) pos.getX(), 0.0D, (double) pos.getZ())).normalize(); ++ boolean flag = true; ++ Vec3 vec3d1 = vec3d.scale(1024.0D); + +- for (int i1 = 16; !isChunkEmpty(level, vec31) && i1-- > 0; vec31 = vec31.add(vec3.scale(-16.0))) { +- LOGGER.debug("Skipping backwards past nonempty chunk at {}", vec31); ++ int i; ++ ++ for (i = 16; !isChunkEmpty(level, vec3d1) && i-- > 0; vec3d1 = vec3d1.add(vec3d.scale(-16.0D))) { ++ TheEndGatewayBlockEntity.LOGGER.debug("Skipping backwards past nonempty chunk at {}", vec3d1); + } + +- for (int var6 = 16; isChunkEmpty(level, vec31) && var6-- > 0; vec31 = vec31.add(vec3.scale(16.0))) { +- LOGGER.debug("Skipping forward past empty chunk at {}", vec31); ++ for (i = 16; isChunkEmpty(level, vec3d1) && i-- > 0; vec3d1 = vec3d1.add(vec3d.scale(16.0D))) { ++ TheEndGatewayBlockEntity.LOGGER.debug("Skipping forward past empty chunk at {}", vec3d1); + } + +- LOGGER.debug("Found chunk at {}", vec31); +- return vec31; ++ TheEndGatewayBlockEntity.LOGGER.debug("Found chunk at {}", vec3d1); ++ return vec3d1; + } + + private static boolean isChunkEmpty(ServerLevel level, Vec3 pos) { +@@ -240,16 +291,17 @@ + } + + private static BlockPos findTallestBlock(BlockGetter level, BlockPos pos, int radius, boolean allowBedrock) { +- BlockPos blockPos = null; ++ BlockPos blockposition1 = null; + +- for (int i = -radius; i <= radius; i++) { +- for (int i1 = -radius; i1 <= radius; i1++) { +- if (i != 0 || i1 != 0 || allowBedrock) { +- for (int i2 = level.getMaxBuildHeight() - 1; i2 > (blockPos == null ? level.getMinBuildHeight() : blockPos.getY()); i2--) { +- BlockPos blockPos1 = new BlockPos(pos.getX() + i, i2, pos.getZ() + i1); +- BlockState blockState = level.getBlockState(blockPos1); +- if (blockState.isCollisionShapeFullBlock(level, blockPos1) && (allowBedrock || !blockState.is(Blocks.BEDROCK))) { +- blockPos = blockPos1; ++ for (int j = -radius; j <= radius; ++j) { ++ for (int k = -radius; k <= radius; ++k) { ++ if (j != 0 || k != 0 || allowBedrock) { ++ for (int l = level.getMaxBuildHeight() - 1; l > (blockposition1 == null ? level.getMinBuildHeight() : blockposition1.getY()); --l) { ++ BlockPos blockposition2 = new BlockPos(pos.getX() + j, l, pos.getZ() + k); ++ IBlockData iblockdata = level.getBlockState(blockposition2); ++ ++ if (iblockdata.isCollisionShapeFullBlock(level, blockposition2) && (allowBedrock || !iblockdata.is(Blocks.BEDROCK))) { ++ blockposition1 = blockposition2; + break; + } + } +@@ -257,38 +309,40 @@ + } + } + +- return blockPos == null ? pos : blockPos; ++ return blockposition1 == null ? pos : blockposition1; + } + + private static LevelChunk getChunk(Level level, Vec3 pos) { +- return level.getChunk(Mth.floor(pos.x / 16.0), Mth.floor(pos.z / 16.0)); ++ return level.getChunk(Mth.floor(pos.x / 16.0D), Mth.floor(pos.z / 16.0D)); + } + + @Nullable + private static BlockPos findValidSpawnInChunk(LevelChunk chunk) { +- ChunkPos pos = chunk.getPos(); +- BlockPos blockPos = new BlockPos(pos.getMinBlockX(), 30, pos.getMinBlockZ()); ++ ChunkPos chunkcoordintpair = chunk.getPos(); ++ BlockPos blockposition = new BlockPos(chunkcoordintpair.getMinBlockX(), 30, chunkcoordintpair.getMinBlockZ()); + int i = chunk.getHighestSectionPosition() + 16 - 1; +- BlockPos blockPos1 = new BlockPos(pos.getMaxBlockX(), i, pos.getMaxBlockZ()); +- BlockPos blockPos2 = null; +- double d = 0.0; ++ BlockPos blockposition1 = new BlockPos(chunkcoordintpair.getMaxBlockX(), i, chunkcoordintpair.getMaxBlockZ()); ++ BlockPos blockposition2 = null; ++ double d0 = 0.0D; ++ Iterator iterator = BlockPos.betweenClosed(blockposition, blockposition1).iterator(); + +- for (BlockPos blockPos3 : BlockPos.betweenClosed(blockPos, blockPos1)) { +- BlockState blockState = chunk.getBlockState(blockPos3); +- BlockPos blockPos4 = blockPos3.above(); +- BlockPos blockPos5 = blockPos3.above(2); +- if (blockState.is(Blocks.END_STONE) +- && !chunk.getBlockState(blockPos4).isCollisionShapeFullBlock(chunk, blockPos4) +- && !chunk.getBlockState(blockPos5).isCollisionShapeFullBlock(chunk, blockPos5)) { +- double d1 = blockPos3.distToCenterSqr(0.0, 0.0, 0.0); +- if (blockPos2 == null || d1 < d) { +- blockPos2 = blockPos3; +- d = d1; ++ while (iterator.hasNext()) { ++ BlockPos blockposition3 = (BlockPos) iterator.next(); ++ IBlockData iblockdata = chunk.getBlockState(blockposition3); ++ BlockPos blockposition4 = blockposition3.above(); ++ BlockPos blockposition5 = blockposition3.above(2); ++ ++ if (iblockdata.is(Blocks.END_STONE) && !chunk.getBlockState(blockposition4).isCollisionShapeFullBlock(chunk, blockposition4) && !chunk.getBlockState(blockposition5).isCollisionShapeFullBlock(chunk, blockposition5)) { ++ double d1 = blockposition3.distToCenterSqr(0.0D, 0.0D, 0.0D); ++ ++ if (blockposition2 == null || d1 < d0) { ++ blockposition2 = blockposition3; ++ d0 = d1; + } + } + } + +- return blockPos2; ++ return blockposition2; + } + + private static void spawnGatewayPortal(ServerLevel level, BlockPos pos, EndGatewayConfiguration config) { +@@ -302,9 +356,13 @@ + + public int getParticleAmount() { + int i = 0; ++ Direction[] aenumdirection = Direction.values(); ++ int j = aenumdirection.length; + +- for (Direction direction : Direction.values()) { +- i += this.shouldRenderFace(direction) ? 1 : 0; ++ for (int k = 0; k < j; ++k) { ++ Direction enumdirection = aenumdirection[k]; ++ ++ i += this.shouldRenderFace(enumdirection) ? 1 : 0; + } + + return i; diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/piston/PistonBaseBlock.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/piston/PistonBaseBlock.java.patch new file mode 100644 index 0000000000..e6f71e8186 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/piston/PistonBaseBlock.java.patch @@ -0,0 +1,704 @@ +--- a/net/minecraft/world/level/block/piston/PistonBaseBlock.java ++++ b/net/minecraft/world/level/block/piston/PistonBaseBlock.java +@@ -5,7 +5,7 @@ + import com.mojang.serialization.Codec; + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; ++import java.util.Iterator; + import java.util.List; + import java.util.Map; + import java.util.Map.Entry; +@@ -16,76 +16,86 @@ + import net.minecraft.sounds.SoundSource; + import net.minecraft.tags.BlockTags; + import net.minecraft.world.entity.LivingEntity; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.context.BlockPlaceContext; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.SignalGetter; + import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.BlockDirectional; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.DirectionalBlock; + import net.minecraft.world.level.block.Mirror; + import net.minecraft.world.level.block.Rotation; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; + import net.minecraft.world.level.block.state.properties.PistonType; + import net.minecraft.world.level.gameevent.GameEvent; +-import net.minecraft.world.level.material.PushReaction; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.material.EnumPistonReaction; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.shapes.CollisionContext; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import com.google.common.collect.ImmutableList; ++import java.util.AbstractList; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockPistonRetractEvent; ++import org.bukkit.event.block.BlockPistonExtendEvent; ++// CraftBukkit end + +-public class PistonBaseBlock extends DirectionalBlock { +- public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( +- instance -> instance.group(Codec.BOOL.fieldOf("sticky").forGetter(pistonBaseBlock -> pistonBaseBlock.isSticky), propertiesCodec()) +- .apply(instance, PistonBaseBlock::new) +- ); ++public class PistonBaseBlock extends BlockDirectional { ++ ++ public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(Codec.BOOL.fieldOf("sticky").forGetter((blockpiston) -> { ++ return blockpiston.isSticky; ++ }), propertiesCodec()).apply(instance, PistonBaseBlock::new); ++ }); + public static final BooleanProperty EXTENDED = BlockStateProperties.EXTENDED; + public static final int TRIGGER_EXTEND = 0; + public static final int TRIGGER_CONTRACT = 1; + public static final int TRIGGER_DROP = 2; + public static final float PLATFORM_THICKNESS = 4.0F; +- protected static final VoxelShape EAST_AABB = Block.box(0.0, 0.0, 0.0, 12.0, 16.0, 16.0); +- protected static final VoxelShape WEST_AABB = Block.box(4.0, 0.0, 0.0, 16.0, 16.0, 16.0); +- protected static final VoxelShape SOUTH_AABB = Block.box(0.0, 0.0, 0.0, 16.0, 16.0, 12.0); +- protected static final VoxelShape NORTH_AABB = Block.box(0.0, 0.0, 4.0, 16.0, 16.0, 16.0); +- protected static final VoxelShape UP_AABB = Block.box(0.0, 0.0, 0.0, 16.0, 12.0, 16.0); +- protected static final VoxelShape DOWN_AABB = Block.box(0.0, 4.0, 0.0, 16.0, 16.0, 16.0); ++ protected static final VoxelShape EAST_AABB = Block.box(0.0D, 0.0D, 0.0D, 12.0D, 16.0D, 16.0D); ++ protected static final VoxelShape WEST_AABB = Block.box(4.0D, 0.0D, 0.0D, 16.0D, 16.0D, 16.0D); ++ protected static final VoxelShape SOUTH_AABB = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 16.0D, 12.0D); ++ protected static final VoxelShape NORTH_AABB = Block.box(0.0D, 0.0D, 4.0D, 16.0D, 16.0D, 16.0D); ++ protected static final VoxelShape UP_AABB = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 12.0D, 16.0D); ++ protected static final VoxelShape DOWN_AABB = Block.box(0.0D, 4.0D, 0.0D, 16.0D, 16.0D, 16.0D); + private final boolean isSticky; + + @Override + public MapCodec codec() { +- return CODEC; ++ return PistonBaseBlock.CODEC; + } + + public PistonBaseBlock(boolean isSticky, BlockBehaviour.Properties properties) { + super(properties); +- this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(EXTENDED, Boolean.valueOf(false))); ++ this.registerDefaultState((IBlockData) ((IBlockData) ((IBlockData) this.stateDefinition.any()).setValue(PistonBaseBlock.FACING, Direction.NORTH)).setValue(PistonBaseBlock.EXTENDED, false)); + this.isSticky = isSticky; + } + + @Override +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { +- if (state.getValue(EXTENDED)) { +- switch ((Direction)state.getValue(FACING)) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ if ((Boolean) state.getValue(PistonBaseBlock.EXTENDED)) { ++ switch ((Direction) state.getValue(PistonBaseBlock.FACING)) { + case DOWN: +- return DOWN_AABB; ++ return PistonBaseBlock.DOWN_AABB; + case UP: + default: +- return UP_AABB; ++ return PistonBaseBlock.UP_AABB; + case NORTH: +- return NORTH_AABB; ++ return PistonBaseBlock.NORTH_AABB; + case SOUTH: +- return SOUTH_AABB; ++ return PistonBaseBlock.SOUTH_AABB; + case WEST: +- return WEST_AABB; ++ return PistonBaseBlock.WEST_AABB; + case EAST: +- return EAST_AABB; ++ return PistonBaseBlock.EAST_AABB; + } + } else { + return Shapes.block(); +@@ -93,63 +103,88 @@ + } + + @Override +- public void setPlacedBy(Level level, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { ++ public void setPlacedBy(Level level, BlockPos pos, IBlockData state, LivingEntity placer, ItemStack stack) { + if (!level.isClientSide) { + this.checkIfExtend(level, pos, state); + } ++ + } + + @Override +- public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { + if (!level.isClientSide) { + this.checkIfExtend(level, pos, state); + } ++ + } + + @Override +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean isMoving) { + if (!oldState.is(state.getBlock())) { + if (!level.isClientSide && level.getBlockEntity(pos) == null) { + this.checkIfExtend(level, pos, state); + } ++ + } + } + + @Override +- public BlockState getStateForPlacement(BlockPlaceContext context) { +- return this.defaultBlockState().setValue(FACING, context.getNearestLookingDirection().getOpposite()).setValue(EXTENDED, Boolean.valueOf(false)); ++ public IBlockData getStateForPlacement(BlockPlaceContext context) { ++ return (IBlockData) ((IBlockData) this.defaultBlockState().setValue(PistonBaseBlock.FACING, context.getNearestLookingDirection().getOpposite())).setValue(PistonBaseBlock.EXTENDED, false); + } + +- private void checkIfExtend(Level level, BlockPos pos, BlockState state) { +- Direction direction = state.getValue(FACING); +- boolean neighborSignal = this.getNeighborSignal(level, pos, direction); +- if (neighborSignal && !state.getValue(EXTENDED)) { +- if (new PistonStructureResolver(level, pos, direction, true).resolve()) { +- level.blockEvent(pos, this, 0, direction.get3DDataValue()); ++ private void checkIfExtend(Level level, BlockPos pos, IBlockData state) { ++ Direction enumdirection = (Direction) state.getValue(PistonBaseBlock.FACING); ++ boolean flag = this.getNeighborSignal(level, pos, enumdirection); ++ ++ if (flag && !(Boolean) state.getValue(PistonBaseBlock.EXTENDED)) { ++ if ((new PistonStructureResolver(level, pos, enumdirection, true)).resolve()) { ++ level.blockEvent(pos, this, 0, enumdirection.get3DDataValue()); + } +- } else if (!neighborSignal && state.getValue(EXTENDED)) { +- BlockPos blockPos = pos.relative(direction, 2); +- BlockState blockState = level.getBlockState(blockPos); +- int i = 1; +- if (blockState.is(Blocks.MOVING_PISTON) +- && blockState.getValue(FACING) == direction +- && level.getBlockEntity(blockPos) instanceof PistonMovingBlockEntity pistonMovingBlockEntity +- && pistonMovingBlockEntity.isExtending() +- && ( +- pistonMovingBlockEntity.getProgress(0.0F) < 0.5F +- || level.getGameTime() == pistonMovingBlockEntity.getLastTicked() +- || ((ServerLevel)level).isHandlingTick() +- )) { +- i = 2; ++ } else if (!flag && (Boolean) state.getValue(PistonBaseBlock.EXTENDED)) { ++ BlockPos blockposition1 = pos.relative(enumdirection, 2); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ byte b0 = 1; ++ ++ if (iblockdata1.is(Blocks.MOVING_PISTON) && iblockdata1.getValue(PistonBaseBlock.FACING) == enumdirection) { ++ BlockEntity tileentity = level.getBlockEntity(blockposition1); ++ ++ if (tileentity instanceof PistonMovingBlockEntity) { ++ PistonMovingBlockEntity tileentitypiston = (PistonMovingBlockEntity) tileentity; ++ ++ if (tileentitypiston.isExtending() && (tileentitypiston.getProgress(0.0F) < 0.5F || level.getGameTime() == tileentitypiston.getLastTicked() || ((ServerLevel) level).isHandlingTick())) { ++ b0 = 2; ++ } ++ } + } + +- level.blockEvent(pos, this, i, direction.get3DDataValue()); ++ // CraftBukkit start ++ if (!this.isSticky) { ++ org.bukkit.block.Block block = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ BlockPistonRetractEvent event = new BlockPistonRetractEvent(block, ImmutableList.of(), CraftBlock.notchToBlockFace(enumdirection)); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // PAIL: checkME - what happened to setTypeAndData? ++ // CraftBukkit end ++ level.blockEvent(pos, this, b0, enumdirection.get3DDataValue()); + } ++ + } + + private boolean getNeighborSignal(SignalGetter signalGetter, BlockPos pos, Direction direction) { +- for (Direction direction1 : Direction.values()) { +- if (direction1 != direction && signalGetter.hasSignal(pos.relative(direction1), direction1)) { ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; ++ ++ int j; ++ ++ for (j = 0; j < i; ++j) { ++ Direction enumdirection1 = aenumdirection[j]; ++ ++ if (enumdirection1 != direction && signalGetter.hasSignal(pos.relative(enumdirection1), enumdirection1)) { + return true; + } + } +@@ -157,10 +192,15 @@ + if (signalGetter.hasSignal(pos, Direction.DOWN)) { + return true; + } else { +- BlockPos blockPos = pos.above(); ++ BlockPos blockposition1 = pos.above(); ++ Direction[] aenumdirection1 = Direction.values(); + +- for (Direction direction2 : Direction.values()) { +- if (direction2 != Direction.DOWN && signalGetter.hasSignal(blockPos.relative(direction2), direction2)) { ++ j = aenumdirection1.length; ++ ++ for (int k = 0; k < j; ++k) { ++ Direction enumdirection2 = aenumdirection1[k]; ++ ++ if (enumdirection2 != Direction.DOWN && signalGetter.hasSignal(blockposition1.relative(enumdirection2), enumdirection2)) { + return true; + } + } +@@ -170,209 +210,271 @@ + } + + @Override +- public boolean triggerEvent(BlockState state, Level level, BlockPos pos, int id, int param) { +- Direction direction = state.getValue(FACING); +- BlockState blockState = state.setValue(EXTENDED, Boolean.valueOf(true)); ++ public boolean triggerEvent(IBlockData state, Level level, BlockPos pos, int id, int param) { ++ Direction enumdirection = (Direction) state.getValue(PistonBaseBlock.FACING); ++ IBlockData iblockdata1 = (IBlockData) state.setValue(PistonBaseBlock.EXTENDED, true); ++ + if (!level.isClientSide) { +- boolean neighborSignal = this.getNeighborSignal(level, pos, direction); +- if (neighborSignal && (id == 1 || id == 2)) { +- level.setBlock(pos, blockState, 2); ++ boolean flag = this.getNeighborSignal(level, pos, enumdirection); ++ ++ if (flag && (id == 1 || id == 2)) { ++ level.setBlock(pos, iblockdata1, 2); + return false; + } + +- if (!neighborSignal && id == 0) { ++ if (!flag && id == 0) { + return false; + } + } + + if (id == 0) { +- if (!this.moveBlocks(level, pos, direction, true)) { ++ if (!this.moveBlocks(level, pos, enumdirection, true)) { + return false; + } + +- level.setBlock(pos, blockState, 67); +- level.playSound(null, pos, SoundEvents.PISTON_EXTEND, SoundSource.BLOCKS, 0.5F, level.random.nextFloat() * 0.25F + 0.6F); +- level.gameEvent(GameEvent.BLOCK_ACTIVATE, pos, GameEvent.Context.of(blockState)); ++ level.setBlock(pos, iblockdata1, 67); ++ level.playSound((Player) null, pos, SoundEvents.PISTON_EXTEND, SoundSource.BLOCKS, 0.5F, level.random.nextFloat() * 0.25F + 0.6F); ++ level.gameEvent(GameEvent.BLOCK_ACTIVATE, pos, GameEvent.Context.of(iblockdata1)); + } else if (id == 1 || id == 2) { +- BlockEntity blockEntity = level.getBlockEntity(pos.relative(direction)); +- if (blockEntity instanceof PistonMovingBlockEntity) { +- ((PistonMovingBlockEntity)blockEntity).finalTick(); ++ BlockEntity tileentity = level.getBlockEntity(pos.relative(enumdirection)); ++ ++ if (tileentity instanceof PistonMovingBlockEntity) { ++ ((PistonMovingBlockEntity) tileentity).finalTick(); + } + +- BlockState blockState1 = Blocks.MOVING_PISTON +- .defaultBlockState() +- .setValue(MovingPistonBlock.FACING, direction) +- .setValue(MovingPistonBlock.TYPE, this.isSticky ? PistonType.STICKY : PistonType.DEFAULT); +- level.setBlock(pos, blockState1, 20); +- level.setBlockEntity( +- MovingPistonBlock.newMovingBlockEntity( +- pos, blockState1, this.defaultBlockState().setValue(FACING, Direction.from3DDataValue(param & 7)), direction, false, true +- ) +- ); +- level.blockUpdated(pos, blockState1.getBlock()); +- blockState1.updateNeighbourShapes(level, pos, 2); ++ IBlockData iblockdata2 = (IBlockData) ((IBlockData) Blocks.MOVING_PISTON.defaultBlockState().setValue(MovingPistonBlock.FACING, enumdirection)).setValue(MovingPistonBlock.TYPE, this.isSticky ? PistonType.STICKY : PistonType.DEFAULT); ++ ++ level.setBlock(pos, iblockdata2, 20); ++ level.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(pos, iblockdata2, (IBlockData) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(param & 7)), enumdirection, false, true)); ++ level.blockUpdated(pos, iblockdata2.getBlock()); ++ iblockdata2.updateNeighbourShapes(level, pos, 2); + if (this.isSticky) { +- BlockPos blockPos = pos.offset(direction.getStepX() * 2, direction.getStepY() * 2, direction.getStepZ() * 2); +- BlockState blockState2 = level.getBlockState(blockPos); +- boolean flag = false; +- if (blockState2.is(Blocks.MOVING_PISTON) +- && level.getBlockEntity(blockPos) instanceof PistonMovingBlockEntity pistonMovingBlockEntity +- && pistonMovingBlockEntity.getDirection() == direction +- && pistonMovingBlockEntity.isExtending()) { +- pistonMovingBlockEntity.finalTick(); +- flag = true; ++ BlockPos blockposition1 = pos.offset(enumdirection.getStepX() * 2, enumdirection.getStepY() * 2, enumdirection.getStepZ() * 2); ++ IBlockData iblockdata3 = level.getBlockState(blockposition1); ++ boolean flag1 = false; ++ ++ if (iblockdata3.is(Blocks.MOVING_PISTON)) { ++ BlockEntity tileentity1 = level.getBlockEntity(blockposition1); ++ ++ if (tileentity1 instanceof PistonMovingBlockEntity) { ++ PistonMovingBlockEntity tileentitypiston = (PistonMovingBlockEntity) tileentity1; ++ ++ if (tileentitypiston.getDirection() == enumdirection && tileentitypiston.isExtending()) { ++ tileentitypiston.finalTick(); ++ flag1 = true; ++ } ++ } + } + +- if (!flag) { +- if (id != 1 +- || blockState2.isAir() +- || !isPushable(blockState2, level, blockPos, direction.getOpposite(), false, direction) +- || blockState2.getPistonPushReaction() != PushReaction.NORMAL +- && !blockState2.is(Blocks.PISTON) +- && !blockState2.is(Blocks.STICKY_PISTON)) { +- level.removeBlock(pos.relative(direction), false); ++ if (!flag1) { ++ if (id == 1 && !iblockdata3.isAir() && isPushable(iblockdata3, level, blockposition1, enumdirection.getOpposite(), false, enumdirection) && (iblockdata3.getPistonPushReaction() == EnumPistonReaction.NORMAL || iblockdata3.is(Blocks.PISTON) || iblockdata3.is(Blocks.STICKY_PISTON))) { ++ this.moveBlocks(level, pos, enumdirection, false); + } else { +- this.moveBlocks(level, pos, direction, false); ++ level.removeBlock(pos.relative(enumdirection), false); + } + } + } else { +- level.removeBlock(pos.relative(direction), false); ++ level.removeBlock(pos.relative(enumdirection), false); + } + +- level.playSound(null, pos, SoundEvents.PISTON_CONTRACT, SoundSource.BLOCKS, 0.5F, level.random.nextFloat() * 0.15F + 0.6F); +- level.gameEvent(GameEvent.BLOCK_DEACTIVATE, pos, GameEvent.Context.of(blockState1)); ++ level.playSound((Player) null, pos, SoundEvents.PISTON_CONTRACT, SoundSource.BLOCKS, 0.5F, level.random.nextFloat() * 0.15F + 0.6F); ++ level.gameEvent(GameEvent.BLOCK_DEACTIVATE, pos, GameEvent.Context.of(iblockdata2)); + } + + return true; + } + +- public static boolean isPushable(BlockState state, Level level, BlockPos pos, Direction movementDirection, boolean allowDestroy, Direction pistonFacing) { +- if (pos.getY() < level.getMinBuildHeight() || pos.getY() > level.getMaxBuildHeight() - 1 || !level.getWorldBorder().isWithinBounds(pos)) { +- return false; +- } else if (state.isAir()) { +- return true; +- } else if (state.is(Blocks.OBSIDIAN) || state.is(Blocks.CRYING_OBSIDIAN) || state.is(Blocks.RESPAWN_ANCHOR) || state.is(Blocks.REINFORCED_DEEPSLATE)) { +- return false; +- } else if (movementDirection == Direction.DOWN && pos.getY() == level.getMinBuildHeight()) { +- return false; +- } else if (movementDirection == Direction.UP && pos.getY() == level.getMaxBuildHeight() - 1) { +- return false; +- } else { +- if (!state.is(Blocks.PISTON) && !state.is(Blocks.STICKY_PISTON)) { +- if (state.getDestroySpeed(level, pos) == -1.0F) { ++ public static boolean isPushable(IBlockData state, Level level, BlockPos pos, Direction movementDirection, boolean allowDestroy, Direction pistonFacing) { ++ if (pos.getY() >= level.getMinBuildHeight() && pos.getY() <= level.getMaxBuildHeight() - 1 && level.getWorldBorder().isWithinBounds(pos)) { ++ if (state.isAir()) { ++ return true; ++ } else if (!state.is(Blocks.OBSIDIAN) && !state.is(Blocks.CRYING_OBSIDIAN) && !state.is(Blocks.RESPAWN_ANCHOR) && !state.is(Blocks.REINFORCED_DEEPSLATE)) { ++ if (movementDirection == Direction.DOWN && pos.getY() == level.getMinBuildHeight()) { + return false; +- } ++ } else if (movementDirection == Direction.UP && pos.getY() == level.getMaxBuildHeight() - 1) { ++ return false; ++ } else { ++ if (!state.is(Blocks.PISTON) && !state.is(Blocks.STICKY_PISTON)) { ++ if (state.getDestroySpeed(level, pos) == -1.0F) { ++ return false; ++ } + +- switch (state.getPistonPushReaction()) { +- case BLOCK: ++ switch (state.getPistonPushReaction()) { ++ case BLOCK: ++ return false; ++ case DESTROY: ++ return allowDestroy; ++ case PUSH_ONLY: ++ return movementDirection == pistonFacing; ++ } ++ } else if ((Boolean) state.getValue(PistonBaseBlock.EXTENDED)) { + return false; +- case DESTROY: +- return allowDestroy; +- case PUSH_ONLY: +- return movementDirection == pistonFacing; ++ } ++ ++ return !state.hasBlockEntity(); + } +- } else if (state.getValue(EXTENDED)) { ++ } else { + return false; + } +- +- return !state.hasBlockEntity(); ++ } else { ++ return false; + } + } + + private boolean moveBlocks(Level level, BlockPos pos, Direction facing, boolean extending) { +- BlockPos blockPos = pos.relative(facing); +- if (!extending && level.getBlockState(blockPos).is(Blocks.PISTON_HEAD)) { +- level.setBlock(blockPos, Blocks.AIR.defaultBlockState(), 20); ++ BlockPos blockposition1 = pos.relative(facing); ++ ++ if (!extending && level.getBlockState(blockposition1).is(Blocks.PISTON_HEAD)) { ++ level.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 20); + } + +- PistonStructureResolver pistonStructureResolver = new PistonStructureResolver(level, pos, facing, extending); +- if (!pistonStructureResolver.resolve()) { ++ PistonStructureResolver pistonextendschecker = new PistonStructureResolver(level, pos, facing, extending); ++ ++ if (!pistonextendschecker.resolve()) { + return false; + } else { +- Map map = Maps.newHashMap(); +- List toPush = pistonStructureResolver.getToPush(); +- List list = Lists.newArrayList(); ++ Map map = Maps.newHashMap(); ++ List list = pistonextendschecker.getToPush(); ++ List list1 = Lists.newArrayList(); ++ Iterator iterator = list.iterator(); + +- for (BlockPos blockPos1 : toPush) { +- BlockState blockState = level.getBlockState(blockPos1); +- list.add(blockState); +- map.put(blockPos1, blockState); ++ while (iterator.hasNext()) { ++ BlockPos blockposition2 = (BlockPos) iterator.next(); ++ IBlockData iblockdata = level.getBlockState(blockposition2); ++ ++ list1.add(iblockdata); ++ map.put(blockposition2, iblockdata); + } + +- List toDestroy = pistonStructureResolver.getToDestroy(); +- BlockState[] blockStates = new BlockState[toPush.size() + toDestroy.size()]; +- Direction direction = extending ? facing : facing.getOpposite(); ++ List list2 = pistonextendschecker.getToDestroy(); ++ IBlockData[] aiblockdata = new IBlockData[list.size() + list2.size()]; ++ Direction enumdirection1 = extending ? facing : facing.getOpposite(); + int i = 0; ++ // CraftBukkit start ++ final org.bukkit.block.Block bblock = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); + +- for (int i1 = toDestroy.size() - 1; i1 >= 0; i1--) { +- BlockPos blockPos2 = toDestroy.get(i1); +- BlockState blockState1 = level.getBlockState(blockPos2); +- BlockEntity blockEntity = blockState1.hasBlockEntity() ? level.getBlockEntity(blockPos2) : null; +- dropResources(blockState1, level, blockPos2, blockEntity); +- level.setBlock(blockPos2, Blocks.AIR.defaultBlockState(), 18); +- level.gameEvent(GameEvent.BLOCK_DESTROY, blockPos2, GameEvent.Context.of(blockState1)); +- if (!blockState1.is(BlockTags.FIRE)) { +- level.addDestroyBlockEffect(blockPos2, blockState1); ++ final List moved = pistonextendschecker.getToPush(); ++ final List broken = pistonextendschecker.getToDestroy(); ++ ++ List blocks = new AbstractList() { ++ ++ @Override ++ public int size() { ++ return moved.size() + broken.size(); + } + +- blockStates[i++] = blockState1; ++ @Override ++ public org.bukkit.block.Block get(int index) { ++ if (index >= size() || index < 0) { ++ throw new ArrayIndexOutOfBoundsException(index); ++ } ++ BlockPos pos = (BlockPos) (index < moved.size() ? moved.get(index) : broken.get(index - moved.size())); ++ return bblock.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ } ++ }; ++ org.bukkit.event.block.BlockPistonEvent event; ++ if (extending) { ++ event = new BlockPistonExtendEvent(bblock, blocks, CraftBlock.notchToBlockFace(enumdirection1)); ++ } else { ++ event = new BlockPistonRetractEvent(bblock, blocks, CraftBlock.notchToBlockFace(enumdirection1)); + } ++ level.getCraftServer().getPluginManager().callEvent(event); + +- for (int i1 = toPush.size() - 1; i1 >= 0; i1--) { +- BlockPos blockPos2 = toPush.get(i1); +- BlockState blockState1 = level.getBlockState(blockPos2); +- blockPos2 = blockPos2.relative(direction); +- map.remove(blockPos2); +- BlockState blockState2 = Blocks.MOVING_PISTON.defaultBlockState().setValue(FACING, facing); +- level.setBlock(blockPos2, blockState2, 68); +- level.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(blockPos2, blockState2, list.get(i1), facing, extending, false)); +- blockStates[i++] = blockState1; ++ if (event.isCancelled()) { ++ for (BlockPos b : broken) { ++ level.sendBlockUpdated(b, Blocks.AIR.defaultBlockState(), level.getBlockState(b), 3); ++ } ++ for (BlockPos b : moved) { ++ level.sendBlockUpdated(b, Blocks.AIR.defaultBlockState(), level.getBlockState(b), 3); ++ b = b.relative(enumdirection1); ++ level.sendBlockUpdated(b, Blocks.AIR.defaultBlockState(), level.getBlockState(b), 3); ++ } ++ return false; + } ++ // CraftBukkit end + ++ BlockPos blockposition3; ++ int j; ++ IBlockData iblockdata1; ++ ++ for (j = list2.size() - 1; j >= 0; --j) { ++ blockposition3 = (BlockPos) list2.get(j); ++ iblockdata1 = level.getBlockState(blockposition3); ++ BlockEntity tileentity = iblockdata1.hasBlockEntity() ? level.getBlockEntity(blockposition3) : null; ++ ++ dropResources(iblockdata1, level, blockposition3, tileentity); ++ level.setBlock(blockposition3, Blocks.AIR.defaultBlockState(), 18); ++ level.gameEvent(GameEvent.BLOCK_DESTROY, blockposition3, GameEvent.Context.of(iblockdata1)); ++ if (!iblockdata1.is(BlockTags.FIRE)) { ++ level.addDestroyBlockEffect(blockposition3, iblockdata1); ++ } ++ ++ aiblockdata[i++] = iblockdata1; ++ } ++ ++ for (j = list.size() - 1; j >= 0; --j) { ++ blockposition3 = (BlockPos) list.get(j); ++ iblockdata1 = level.getBlockState(blockposition3); ++ blockposition3 = blockposition3.relative(enumdirection1); ++ map.remove(blockposition3); ++ IBlockData iblockdata2 = (IBlockData) Blocks.MOVING_PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, facing); ++ ++ level.setBlock(blockposition3, iblockdata2, 68); ++ level.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(blockposition3, iblockdata2, (IBlockData) list1.get(j), facing, extending, false)); ++ aiblockdata[i++] = iblockdata1; ++ } ++ + if (extending) { +- PistonType pistonType = this.isSticky ? PistonType.STICKY : PistonType.DEFAULT; +- BlockState blockState3 = Blocks.PISTON_HEAD +- .defaultBlockState() +- .setValue(PistonHeadBlock.FACING, facing) +- .setValue(PistonHeadBlock.TYPE, pistonType); +- BlockState blockState1 = Blocks.MOVING_PISTON +- .defaultBlockState() +- .setValue(MovingPistonBlock.FACING, facing) +- .setValue(MovingPistonBlock.TYPE, this.isSticky ? PistonType.STICKY : PistonType.DEFAULT); +- map.remove(blockPos); +- level.setBlock(blockPos, blockState1, 68); +- level.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(blockPos, blockState1, blockState3, facing, true, true)); ++ PistonType blockpropertypistontype = this.isSticky ? PistonType.STICKY : PistonType.DEFAULT; ++ IBlockData iblockdata3 = (IBlockData) ((IBlockData) Blocks.PISTON_HEAD.defaultBlockState().setValue(PistonHeadBlock.FACING, facing)).setValue(PistonHeadBlock.TYPE, blockpropertypistontype); ++ ++ iblockdata1 = (IBlockData) ((IBlockData) Blocks.MOVING_PISTON.defaultBlockState().setValue(MovingPistonBlock.FACING, facing)).setValue(MovingPistonBlock.TYPE, this.isSticky ? PistonType.STICKY : PistonType.DEFAULT); ++ map.remove(blockposition1); ++ level.setBlock(blockposition1, iblockdata1, 68); ++ level.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(blockposition1, iblockdata1, iblockdata3, facing, true, true)); + } + +- BlockState blockState4 = Blocks.AIR.defaultBlockState(); ++ IBlockData iblockdata4 = Blocks.AIR.defaultBlockState(); ++ Iterator iterator1 = map.keySet().iterator(); + +- for (BlockPos blockPos3 : map.keySet()) { +- level.setBlock(blockPos3, blockState4, 82); ++ while (iterator1.hasNext()) { ++ BlockPos blockposition4 = (BlockPos) iterator1.next(); ++ ++ level.setBlock(blockposition4, iblockdata4, 82); + } + +- for (Entry entry : map.entrySet()) { +- BlockPos blockPos4 = entry.getKey(); +- BlockState blockState5 = entry.getValue(); +- blockState5.updateIndirectNeighbourShapes(level, blockPos4, 2); +- blockState4.updateNeighbourShapes(level, blockPos4, 2); +- blockState4.updateIndirectNeighbourShapes(level, blockPos4, 2); ++ iterator1 = map.entrySet().iterator(); ++ ++ BlockPos blockposition5; ++ ++ while (iterator1.hasNext()) { ++ Entry entry = (Entry) iterator1.next(); ++ ++ blockposition5 = (BlockPos) entry.getKey(); ++ IBlockData iblockdata5 = (IBlockData) entry.getValue(); ++ ++ iblockdata5.updateIndirectNeighbourShapes(level, blockposition5, 2); ++ iblockdata4.updateNeighbourShapes(level, blockposition5, 2); ++ iblockdata4.updateIndirectNeighbourShapes(level, blockposition5, 2); + } + +- int var22 = 0; ++ i = 0; + +- for (int i2 = toDestroy.size() - 1; i2 >= 0; i2--) { +- BlockState blockState1 = blockStates[var22++]; +- BlockPos blockPos4 = toDestroy.get(i2); +- blockState1.updateIndirectNeighbourShapes(level, blockPos4, 2); +- level.updateNeighborsAt(blockPos4, blockState1.getBlock()); ++ int k; ++ ++ for (k = list2.size() - 1; k >= 0; --k) { ++ iblockdata1 = aiblockdata[i++]; ++ blockposition5 = (BlockPos) list2.get(k); ++ iblockdata1.updateIndirectNeighbourShapes(level, blockposition5, 2); ++ level.updateNeighborsAt(blockposition5, iblockdata1.getBlock()); + } + +- for (int i2 = toPush.size() - 1; i2 >= 0; i2--) { +- level.updateNeighborsAt(toPush.get(i2), blockStates[var22++].getBlock()); ++ for (k = list.size() - 1; k >= 0; --k) { ++ level.updateNeighborsAt((BlockPos) list.get(k), aiblockdata[i++].getBlock()); + } + + if (extending) { +- level.updateNeighborsAt(blockPos, Blocks.PISTON_HEAD); ++ level.updateNeighborsAt(blockposition1, Blocks.PISTON_HEAD); + } + + return true; +@@ -380,27 +482,27 @@ + } + + @Override +- public BlockState rotate(BlockState state, Rotation rot) { +- return state.setValue(FACING, rot.rotate(state.getValue(FACING))); ++ public IBlockData rotate(IBlockData state, Rotation rot) { ++ return (IBlockData) state.setValue(PistonBaseBlock.FACING, rot.rotate((Direction) state.getValue(PistonBaseBlock.FACING))); + } + + @Override +- public BlockState mirror(BlockState state, Mirror mirror) { +- return state.rotate(mirror.getRotation(state.getValue(FACING))); ++ public IBlockData mirror(IBlockData state, Mirror mirror) { ++ return state.rotate(mirror.getRotation((Direction) state.getValue(PistonBaseBlock.FACING))); + } + + @Override +- protected void createBlockStateDefinition(StateDefinition.Builder builder) { +- builder.add(FACING, EXTENDED); ++ protected void createBlockStateDefinition(StateDefinition.Builder builder) { ++ builder.add(PistonBaseBlock.FACING, PistonBaseBlock.EXTENDED); + } + + @Override +- public boolean useShapeForLightOcclusion(BlockState state) { +- return state.getValue(EXTENDED); ++ public boolean useShapeForLightOcclusion(IBlockData state) { ++ return (Boolean) state.getValue(PistonBaseBlock.EXTENDED); + } + + @Override +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + return false; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/block/state/BlockBehaviour.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/block/state/BlockBehaviour.java.patch new file mode 100644 index 0000000000..089e566b45 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/block/state/BlockBehaviour.java.patch @@ -0,0 +1,1610 @@ +--- a/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -4,7 +4,6 @@ + import com.mojang.serialization.Codec; + import com.mojang.serialization.MapCodec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import java.util.Arrays; + import java.util.Collections; + import java.util.List; +@@ -29,9 +28,9 @@ + import net.minecraft.tags.TagKey; + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; ++import net.minecraft.world.ITileInventory; + import net.minecraft.world.InteractionResult; +-import net.minecraft.world.MenuProvider; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.player.Player; +@@ -53,8 +52,8 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.EntityBlock; ++import net.minecraft.world.level.block.EnumRenderType; + import net.minecraft.world.level.block.Mirror; +-import net.minecraft.world.level.block.RenderShape; + import net.minecraft.world.level.block.Rotation; + import net.minecraft.world.level.block.SoundType; + import net.minecraft.world.level.block.SupportType; +@@ -63,12 +62,12 @@ + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.state.properties.NoteBlockInstrument; + import net.minecraft.world.level.block.state.properties.Property; ++import net.minecraft.world.level.material.EnumPistonReaction; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.level.material.MapColor; +-import net.minecraft.world.level.material.PushReaction; +-import net.minecraft.world.level.pathfinder.PathComputationType; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.level.storage.loot.BuiltInLootTables; + import net.minecraft.world.level.storage.loot.LootParams; + import net.minecraft.world.level.storage.loot.LootTable; +@@ -82,9 +81,8 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + + public abstract class BlockBehaviour implements FeatureElement { +- protected static final Direction[] UPDATE_SHAPE_ORDER = new Direction[]{ +- Direction.WEST, Direction.EAST, Direction.NORTH, Direction.SOUTH, Direction.DOWN, Direction.UP +- }; ++ ++ protected static final Direction[] UPDATE_SHAPE_ORDER = new Direction[]{Direction.WEST, Direction.EAST, Direction.NORTH, Direction.SOUTH, Direction.DOWN, Direction.UP}; + protected final boolean hasCollision; + protected final float explosionResistance; + protected final boolean isRandomlyTicking; +@@ -123,15 +121,18 @@ + } + + public static MapCodec simpleCodec(Function function) { +- return RecordCodecBuilder.mapCodec(instance -> instance.group(propertiesCodec()).apply(instance, function)); ++ return RecordCodecBuilder.mapCodec((instance) -> { ++ return instance.group(propertiesCodec()).apply(instance, function); ++ }); + } + ++ /** @deprecated */ + @Deprecated +- public void updateIndirectNeighbourShapes(BlockState state, LevelAccessor level, BlockPos pos, int flags, int recursionLeft) { +- } ++ public void updateIndirectNeighbourShapes(IBlockData state, LevelAccessor level, BlockPos pos, int flags, int recursionLeft) {} + ++ /** @deprecated */ + @Deprecated +- public boolean isPathfindable(BlockState state, BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(IBlockData state, BlockGetter level, BlockPos pos, PathMode type) { + switch (type) { + case LAND: + return !state.isCollisionShapeFullBlock(level, pos); +@@ -144,89 +145,105 @@ + } + } + ++ /** @deprecated */ + @Deprecated +- public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { ++ public IBlockData updateShape(IBlockData state, Direction direction, IBlockData neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { + return state; + } + ++ /** @deprecated */ + @Deprecated +- public boolean skipRendering(BlockState state, BlockState adjacentState, Direction direction) { ++ public boolean skipRendering(IBlockData state, IBlockData adjacentState, Direction direction) { + return false; + } + ++ /** @deprecated */ + @Deprecated +- public void neighborChanged(BlockState state, Level level, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston) { ++ public void neighborChanged(IBlockData state, Level level, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston) { + DebugPackets.sendNeighborsUpdatePacket(level, pos); + } + ++ /** @deprecated */ + @Deprecated +- public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) { +- } ++ public void onPlace(IBlockData state, Level level, BlockPos pos, IBlockData oldState, boolean movedByPiston) {} + ++ /** @deprecated */ + @Deprecated +- public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { ++ public void onRemove(IBlockData state, Level level, BlockPos pos, IBlockData newState, boolean movedByPiston) { + if (state.hasBlockEntity() && !state.is(newState.getBlock())) { + level.removeBlockEntity(pos); + } ++ + } + ++ /** @deprecated */ + @Deprecated +- public void onExplosionHit(BlockState blockState, Level level, BlockPos blockPos, Explosion explosion, BiConsumer biConsumer) { +- if (!blockState.isAir() && explosion.getBlockInteraction() != Explosion.BlockInteraction.TRIGGER_BLOCK) { +- Block block = blockState.getBlock(); ++ public void onExplosionHit(IBlockData iblockdata, Level world, BlockPos blockposition, Explosion explosion, BiConsumer biconsumer) { ++ if (!iblockdata.isAir() && explosion.getBlockInteraction() != Explosion.Effect.TRIGGER_BLOCK) { ++ Block block = iblockdata.getBlock(); + boolean flag = explosion.getIndirectSourceEntity() instanceof Player; +- if (block.dropFromExplosion(explosion) && level instanceof ServerLevel serverLevel) { +- BlockEntity blockEntity = blockState.hasBlockEntity() ? level.getBlockEntity(blockPos) : null; +- LootParams.Builder builder = new LootParams.Builder(serverLevel) +- .withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockPos)) +- .withParameter(LootContextParams.TOOL, ItemStack.EMPTY) +- .withOptionalParameter(LootContextParams.BLOCK_ENTITY, blockEntity) +- .withOptionalParameter(LootContextParams.THIS_ENTITY, explosion.getDirectSourceEntity()); +- if (explosion.getBlockInteraction() == Explosion.BlockInteraction.DESTROY_WITH_DECAY) { +- builder.withParameter(LootContextParams.EXPLOSION_RADIUS, explosion.radius()); ++ ++ if (block.dropFromExplosion(explosion) && world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ BlockEntity tileentity = iblockdata.hasBlockEntity() ? world.getBlockEntity(blockposition) : null; ++ LootParams.Builder lootparams_a = (new LootParams.Builder(worldserver)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockposition)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withOptionalParameter(LootContextParams.BLOCK_ENTITY, tileentity).withOptionalParameter(LootContextParams.THIS_ENTITY, explosion.getDirectSourceEntity()); ++ ++ // CraftBukkit start - add yield ++ if (explosion.yield < 1.0F) { ++ lootparams_a.withParameter(LootContextParams.EXPLOSION_RADIUS, 1.0F / explosion.yield); ++ // CraftBukkit end + } + +- blockState.spawnAfterBreak(serverLevel, blockPos, ItemStack.EMPTY, flag); +- blockState.getDrops(builder).forEach(itemStack -> biConsumer.accept(itemStack, blockPos)); ++ iblockdata.spawnAfterBreak(worldserver, blockposition, ItemStack.EMPTY, flag); ++ iblockdata.getDrops(lootparams_a).forEach((itemstack) -> { ++ biconsumer.accept(itemstack, blockposition); ++ }); + } + +- level.setBlock(blockPos, Blocks.AIR.defaultBlockState(), 3); +- block.wasExploded(level, blockPos, explosion); ++ world.setBlock(blockposition, Blocks.AIR.defaultBlockState(), 3); ++ block.wasExploded(world, blockposition, explosion); + } + } + ++ /** @deprecated */ + @Deprecated +- public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { ++ public InteractionResult use(IBlockData state, Level level, BlockPos pos, Player player, EnumHand hand, BlockHitResult hit) { + return InteractionResult.PASS; + } + ++ /** @deprecated */ + @Deprecated +- public boolean triggerEvent(BlockState state, Level level, BlockPos pos, int id, int param) { ++ public boolean triggerEvent(IBlockData state, Level level, BlockPos pos, int id, int param) { + return false; + } + ++ /** @deprecated */ + @Deprecated +- public RenderShape getRenderShape(BlockState state) { +- return RenderShape.MODEL; ++ public EnumRenderType getRenderShape(IBlockData state) { ++ return EnumRenderType.MODEL; + } + ++ /** @deprecated */ + @Deprecated +- public boolean useShapeForLightOcclusion(BlockState state) { ++ public boolean useShapeForLightOcclusion(IBlockData state) { + return false; + } + ++ /** @deprecated */ + @Deprecated +- public boolean isSignalSource(BlockState state) { ++ public boolean isSignalSource(IBlockData state) { + return false; + } + ++ /** @deprecated */ + @Deprecated +- public FluidState getFluidState(BlockState state) { ++ public FluidState getFluidState(IBlockData state) { + return Fluids.EMPTY.defaultFluidState(); + } + ++ /** @deprecated */ + @Deprecated +- public boolean hasAnalogOutputSignal(BlockState state) { ++ public boolean hasAnalogOutputSignal(IBlockData state) { + return false; + } + +@@ -243,192 +260,577 @@ + return this.requiredFeatures; + } + ++ /** @deprecated */ + @Deprecated +- public BlockState rotate(BlockState state, Rotation rotation) { ++ public IBlockData rotate(IBlockData state, Rotation rotation) { + return state; + } + ++ /** @deprecated */ + @Deprecated +- public BlockState mirror(BlockState state, Mirror mirror) { ++ public IBlockData mirror(IBlockData state, Mirror mirror) { + return state; + } + ++ /** @deprecated */ + @Deprecated +- public boolean canBeReplaced(BlockState state, BlockPlaceContext useContext) { ++ public boolean canBeReplaced(IBlockData state, BlockPlaceContext useContext) { + return state.canBeReplaced() && (useContext.getItemInHand().isEmpty() || !useContext.getItemInHand().is(this.asItem())); + } + ++ /** @deprecated */ + @Deprecated +- public boolean canBeReplaced(BlockState state, Fluid fluid) { ++ public boolean canBeReplaced(IBlockData state, Fluid fluid) { + return state.canBeReplaced() || !state.isSolid(); + } + ++ /** @deprecated */ + @Deprecated +- public List getDrops(BlockState state, LootParams.Builder params) { +- ResourceLocation lootTable = this.getLootTable(); +- if (lootTable == BuiltInLootTables.EMPTY) { ++ public List getDrops(IBlockData state, LootParams.Builder params) { ++ ResourceLocation minecraftkey = this.getLootTable(); ++ ++ if (minecraftkey == BuiltInLootTables.EMPTY) { + return Collections.emptyList(); + } else { +- LootParams lootParams = params.withParameter(LootContextParams.BLOCK_STATE, state).create(LootContextParamSets.BLOCK); +- ServerLevel level = lootParams.getLevel(); +- LootTable lootTable1 = level.getServer().getLootData().getLootTable(lootTable); +- return lootTable1.getRandomItems(lootParams); ++ LootParams lootparams = params.withParameter(LootContextParams.BLOCK_STATE, state).create(LootContextParamSets.BLOCK); ++ ServerLevel worldserver = lootparams.getLevel(); ++ LootTable loottable = worldserver.getServer().getLootData().getLootTable(minecraftkey); ++ ++ return loottable.getRandomItems(lootparams); + } + } + ++ /** @deprecated */ + @Deprecated +- public long getSeed(BlockState state, BlockPos pos) { ++ public long getSeed(IBlockData state, BlockPos pos) { + return Mth.getSeed(pos); + } + ++ /** @deprecated */ + @Deprecated +- public VoxelShape getOcclusionShape(BlockState state, BlockGetter level, BlockPos pos) { ++ public VoxelShape getOcclusionShape(IBlockData state, BlockGetter level, BlockPos pos) { + return state.getShape(level, pos); + } + ++ /** @deprecated */ + @Deprecated +- public VoxelShape getBlockSupportShape(BlockState state, BlockGetter level, BlockPos pos) { ++ public VoxelShape getBlockSupportShape(IBlockData state, BlockGetter level, BlockPos pos) { + return this.getCollisionShape(state, level, pos, CollisionContext.empty()); + } + ++ /** @deprecated */ + @Deprecated +- public VoxelShape getInteractionShape(BlockState state, BlockGetter level, BlockPos pos) { ++ public VoxelShape getInteractionShape(IBlockData state, BlockGetter level, BlockPos pos) { + return Shapes.empty(); + } + ++ /** @deprecated */ + @Deprecated +- public int getLightBlock(BlockState state, BlockGetter level, BlockPos pos) { +- if (state.isSolidRender(level, pos)) { +- return level.getMaxLightLevel(); +- } else { +- return state.propagatesSkylightDown(level, pos) ? 0 : 1; +- } ++ public int getLightBlock(IBlockData state, BlockGetter level, BlockPos pos) { ++ return state.isSolidRender(level, pos) ? level.getMaxLightLevel() : (state.propagatesSkylightDown(level, pos) ? 0 : 1); + } + ++ /** @deprecated */ + @Nullable + @Deprecated +- public MenuProvider getMenuProvider(BlockState state, Level level, BlockPos pos) { ++ public ITileInventory getMenuProvider(IBlockData state, Level level, BlockPos pos) { + return null; + } + ++ /** @deprecated */ + @Deprecated +- public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) { ++ public boolean canSurvive(IBlockData state, LevelReader level, BlockPos pos) { + return true; + } + ++ /** @deprecated */ + @Deprecated +- public float getShadeBrightness(BlockState state, BlockGetter level, BlockPos pos) { ++ public float getShadeBrightness(IBlockData state, BlockGetter level, BlockPos pos) { + return state.isCollisionShapeFullBlock(level, pos) ? 0.2F : 1.0F; + } + ++ /** @deprecated */ + @Deprecated +- public int getAnalogOutputSignal(BlockState state, Level level, BlockPos pos) { ++ public int getAnalogOutputSignal(IBlockData state, Level level, BlockPos pos) { + return 0; + } + ++ /** @deprecated */ + @Deprecated +- public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ public VoxelShape getShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return Shapes.block(); + } + ++ /** @deprecated */ + @Deprecated +- public VoxelShape getCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ public VoxelShape getCollisionShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return this.hasCollision ? state.getShape(level, pos) : Shapes.empty(); + } + ++ /** @deprecated */ + @Deprecated +- public boolean isCollisionShapeFullBlock(BlockState state, BlockGetter level, BlockPos pos) { ++ public boolean isCollisionShapeFullBlock(IBlockData state, BlockGetter level, BlockPos pos) { + return Block.isShapeFullBlock(state.getCollisionShape(level, pos)); + } + ++ /** @deprecated */ + @Deprecated +- public boolean isOcclusionShapeFullBlock(BlockState state, BlockGetter level, BlockPos pos) { ++ public boolean isOcclusionShapeFullBlock(IBlockData state, BlockGetter level, BlockPos pos) { + return Block.isShapeFullBlock(state.getOcclusionShape(level, pos)); + } + ++ /** @deprecated */ + @Deprecated +- public VoxelShape getVisualShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { ++ public VoxelShape getVisualShape(IBlockData state, BlockGetter level, BlockPos pos, CollisionContext context) { + return this.getCollisionShape(state, level, pos, context); + } + ++ /** @deprecated */ + @Deprecated +- public void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- } ++ public void randomTick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) {} + ++ /** @deprecated */ + @Deprecated +- public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { +- } ++ public void tick(IBlockData state, ServerLevel level, BlockPos pos, RandomSource random) {} + ++ /** @deprecated */ + @Deprecated +- public float getDestroyProgress(BlockState state, Player player, BlockGetter level, BlockPos pos) { +- float destroySpeed = state.getDestroySpeed(level, pos); +- if (destroySpeed == -1.0F) { ++ public float getDestroyProgress(IBlockData state, Player player, BlockGetter level, BlockPos pos) { ++ float f = state.getDestroySpeed(level, pos); ++ ++ if (f == -1.0F) { + return 0.0F; + } else { + int i = player.hasCorrectToolForDrops(state) ? 30 : 100; +- return player.getDestroySpeed(state) / destroySpeed / (float)i; ++ ++ return player.getDestroySpeed(state) / f / (float) i; + } + } + ++ /** @deprecated */ + @Deprecated +- public void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { +- } ++ public void spawnAfterBreak(IBlockData state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {} + ++ /** @deprecated */ + @Deprecated +- public void attack(BlockState state, Level level, BlockPos pos, Player player) { +- } ++ public void attack(IBlockData state, Level level, BlockPos pos, Player player) {} + ++ /** @deprecated */ + @Deprecated +- public int getSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { ++ public int getSignal(IBlockData state, BlockGetter level, BlockPos pos, Direction direction) { + return 0; + } + ++ /** @deprecated */ + @Deprecated +- public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { +- } ++ public void entityInside(IBlockData state, Level level, BlockPos pos, Entity entity) {} + ++ /** @deprecated */ + @Deprecated +- public int getDirectSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) { ++ public int getDirectSignal(IBlockData state, BlockGetter level, BlockPos pos, Direction direction) { + return 0; + } + + public final ResourceLocation getLootTable() { + if (this.drops == null) { +- ResourceLocation key = BuiltInRegistries.BLOCK.getKey(this.asBlock()); +- this.drops = key.withPrefix("blocks/"); ++ ResourceLocation minecraftkey = BuiltInRegistries.BLOCK.getKey(this.asBlock()); ++ ++ this.drops = minecraftkey.withPrefix("blocks/"); + } + + return this.drops; + } + ++ /** @deprecated */ + @Deprecated +- public void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) { +- } ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) {} + + public abstract Item asItem(); + + protected abstract Block asBlock(); + + public MapColor defaultMapColor() { +- return this.properties.mapColor.apply(this.asBlock().defaultBlockState()); ++ return (MapColor) this.properties.mapColor.apply(this.asBlock().defaultBlockState()); + } + + public float defaultDestroyTime() { + return this.properties.destroyTime; + } + +- public abstract static class BlockStateBase extends StateHolder { ++ public static class Properties { ++ ++ public static final Codec CODEC = Codec.unit(() -> { ++ return of(); ++ }); ++ Function mapColor = (iblockdata) -> { ++ return MapColor.NONE; ++ }; ++ boolean hasCollision = true; ++ SoundType soundType; ++ ToIntFunction lightEmission; ++ float explosionResistance; ++ float destroyTime; ++ boolean requiresCorrectToolForDrops; ++ boolean isRandomlyTicking; ++ float friction; ++ float speedFactor; ++ float jumpFactor; ++ ResourceLocation drops; ++ boolean canOcclude; ++ boolean isAir; ++ boolean ignitedByLava; ++ /** @deprecated */ ++ @Deprecated ++ boolean liquid; ++ /** @deprecated */ ++ @Deprecated ++ boolean forceSolidOff; ++ boolean forceSolidOn; ++ EnumPistonReaction pushReaction; ++ boolean spawnTerrainParticles; ++ NoteBlockInstrument instrument; ++ boolean replaceable; ++ BlockBehaviour.StateArgumentPredicate> isValidSpawn; ++ BlockBehaviour.StatePredicate isRedstoneConductor; ++ BlockBehaviour.StatePredicate isSuffocating; ++ BlockBehaviour.StatePredicate isViewBlocking; ++ BlockBehaviour.StatePredicate hasPostProcess; ++ BlockBehaviour.StatePredicate emissiveRendering; ++ boolean dynamicShape; ++ FeatureFlagSet requiredFeatures; ++ Optional offsetFunction; ++ ++ private Properties() { ++ this.soundType = SoundType.STONE; ++ this.lightEmission = (iblockdata) -> { ++ return 0; ++ }; ++ this.friction = 0.6F; ++ this.speedFactor = 1.0F; ++ this.jumpFactor = 1.0F; ++ this.canOcclude = true; ++ this.pushReaction = EnumPistonReaction.NORMAL; ++ this.spawnTerrainParticles = true; ++ this.instrument = NoteBlockInstrument.HARP; ++ this.isValidSpawn = (iblockdata, iblockaccess, blockposition, entitytypes) -> { ++ return iblockdata.isFaceSturdy(iblockaccess, blockposition, Direction.UP) && iblockdata.getLightEmission() < 14; ++ }; ++ this.isRedstoneConductor = (iblockdata, iblockaccess, blockposition) -> { ++ return iblockdata.isCollisionShapeFullBlock(iblockaccess, blockposition); ++ }; ++ this.isSuffocating = (iblockdata, iblockaccess, blockposition) -> { ++ return iblockdata.blocksMotion() && iblockdata.isCollisionShapeFullBlock(iblockaccess, blockposition); ++ }; ++ this.isViewBlocking = this.isSuffocating; ++ this.hasPostProcess = (iblockdata, iblockaccess, blockposition) -> { ++ return false; ++ }; ++ this.emissiveRendering = (iblockdata, iblockaccess, blockposition) -> { ++ return false; ++ }; ++ this.requiredFeatures = FeatureFlags.VANILLA_SET; ++ this.offsetFunction = Optional.empty(); ++ } ++ ++ public static BlockBehaviour.Properties of() { ++ return new BlockBehaviour.Properties(); ++ } ++ ++ public static BlockBehaviour.Properties ofFullCopy(BlockBehaviour blockbase) { ++ BlockBehaviour.Properties blockbase_info = ofLegacyCopy(blockbase); ++ BlockBehaviour.Properties blockbase_info1 = blockbase.properties; ++ ++ blockbase_info.jumpFactor = blockbase_info1.jumpFactor; ++ blockbase_info.isRedstoneConductor = blockbase_info1.isRedstoneConductor; ++ blockbase_info.isValidSpawn = blockbase_info1.isValidSpawn; ++ blockbase_info.hasPostProcess = blockbase_info1.hasPostProcess; ++ blockbase_info.isSuffocating = blockbase_info1.isSuffocating; ++ blockbase_info.isViewBlocking = blockbase_info1.isViewBlocking; ++ blockbase_info.drops = blockbase_info1.drops; ++ return blockbase_info; ++ } ++ ++ /** @deprecated */ ++ @Deprecated ++ public static BlockBehaviour.Properties ofLegacyCopy(BlockBehaviour blockbase) { ++ BlockBehaviour.Properties blockbase_info = new BlockBehaviour.Properties(); ++ BlockBehaviour.Properties blockbase_info1 = blockbase.properties; ++ ++ blockbase_info.destroyTime = blockbase_info1.destroyTime; ++ blockbase_info.explosionResistance = blockbase_info1.explosionResistance; ++ blockbase_info.hasCollision = blockbase_info1.hasCollision; ++ blockbase_info.isRandomlyTicking = blockbase_info1.isRandomlyTicking; ++ blockbase_info.lightEmission = blockbase_info1.lightEmission; ++ blockbase_info.mapColor = blockbase_info1.mapColor; ++ blockbase_info.soundType = blockbase_info1.soundType; ++ blockbase_info.friction = blockbase_info1.friction; ++ blockbase_info.speedFactor = blockbase_info1.speedFactor; ++ blockbase_info.dynamicShape = blockbase_info1.dynamicShape; ++ blockbase_info.canOcclude = blockbase_info1.canOcclude; ++ blockbase_info.isAir = blockbase_info1.isAir; ++ blockbase_info.ignitedByLava = blockbase_info1.ignitedByLava; ++ blockbase_info.liquid = blockbase_info1.liquid; ++ blockbase_info.forceSolidOff = blockbase_info1.forceSolidOff; ++ blockbase_info.forceSolidOn = blockbase_info1.forceSolidOn; ++ blockbase_info.pushReaction = blockbase_info1.pushReaction; ++ blockbase_info.requiresCorrectToolForDrops = blockbase_info1.requiresCorrectToolForDrops; ++ blockbase_info.offsetFunction = blockbase_info1.offsetFunction; ++ blockbase_info.spawnTerrainParticles = blockbase_info1.spawnTerrainParticles; ++ blockbase_info.requiredFeatures = blockbase_info1.requiredFeatures; ++ blockbase_info.emissiveRendering = blockbase_info1.emissiveRendering; ++ blockbase_info.instrument = blockbase_info1.instrument; ++ blockbase_info.replaceable = blockbase_info1.replaceable; ++ return blockbase_info; ++ } ++ ++ public BlockBehaviour.Properties mapColor(DyeColor mapColor) { ++ this.mapColor = (iblockdata) -> { ++ return mapColor.getMapColor(); ++ }; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties mapColor(MapColor mapColor) { ++ this.mapColor = (iblockdata) -> { ++ return mapColor; ++ }; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties mapColor(Function mapColor) { ++ this.mapColor = mapColor; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties noCollission() { ++ this.hasCollision = false; ++ this.canOcclude = false; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties noOcclusion() { ++ this.canOcclude = false; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties friction(float friction) { ++ this.friction = friction; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties speedFactor(float speedFactor) { ++ this.speedFactor = speedFactor; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties jumpFactor(float jumpFactor) { ++ this.jumpFactor = jumpFactor; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties sound(SoundType soundType) { ++ this.soundType = soundType; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties lightLevel(ToIntFunction lightEmission) { ++ this.lightEmission = lightEmission; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties strength(float destroyTime, float explosionResistance) { ++ return this.destroyTime(destroyTime).explosionResistance(explosionResistance); ++ } ++ ++ public BlockBehaviour.Properties instabreak() { ++ return this.strength(0.0F); ++ } ++ ++ public BlockBehaviour.Properties strength(float strength) { ++ this.strength(strength, strength); ++ return this; ++ } ++ ++ public BlockBehaviour.Properties randomTicks() { ++ this.isRandomlyTicking = true; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties dynamicShape() { ++ this.dynamicShape = true; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties noLootTable() { ++ this.drops = BuiltInLootTables.EMPTY; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties dropsLike(Block block) { ++ this.drops = block.getLootTable(); ++ return this; ++ } ++ ++ public BlockBehaviour.Properties ignitedByLava() { ++ this.ignitedByLava = true; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties liquid() { ++ this.liquid = true; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties forceSolidOn() { ++ this.forceSolidOn = true; ++ return this; ++ } ++ ++ /** @deprecated */ ++ @Deprecated ++ public BlockBehaviour.Properties forceSolidOff() { ++ this.forceSolidOff = true; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties pushReaction(EnumPistonReaction pushReaction) { ++ this.pushReaction = pushReaction; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties air() { ++ this.isAir = true; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties isValidSpawn(BlockBehaviour.StateArgumentPredicate> isValidSpawn) { ++ this.isValidSpawn = isValidSpawn; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties isRedstoneConductor(BlockBehaviour.StatePredicate isRedstoneConductor) { ++ this.isRedstoneConductor = isRedstoneConductor; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties isSuffocating(BlockBehaviour.StatePredicate isSuffocating) { ++ this.isSuffocating = isSuffocating; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties isViewBlocking(BlockBehaviour.StatePredicate isViewBlocking) { ++ this.isViewBlocking = isViewBlocking; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties hasPostProcess(BlockBehaviour.StatePredicate hasPostProcess) { ++ this.hasPostProcess = hasPostProcess; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties emissiveRendering(BlockBehaviour.StatePredicate emissiveRendering) { ++ this.emissiveRendering = emissiveRendering; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties requiresCorrectToolForDrops() { ++ this.requiresCorrectToolForDrops = true; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties destroyTime(float destroyTime) { ++ this.destroyTime = destroyTime; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties explosionResistance(float explosionResistance) { ++ this.explosionResistance = Math.max(0.0F, explosionResistance); ++ return this; ++ } ++ ++ public BlockBehaviour.Properties offsetType(BlockBehaviour.EnumRandomOffset offsetType) { ++ switch (offsetType) { ++ case XYZ: ++ this.offsetFunction = Optional.of((iblockdata, iblockaccess, blockposition) -> { ++ Block block = iblockdata.getBlock(); ++ long i = Mth.getSeed(blockposition.getX(), 0, blockposition.getZ()); ++ double d0 = ((double) ((float) (i >> 4 & 15L) / 15.0F) - 1.0D) * (double) block.getMaxVerticalOffset(); ++ float f = block.getMaxHorizontalOffset(); ++ double d1 = Mth.clamp(((double) ((float) (i & 15L) / 15.0F) - 0.5D) * 0.5D, (double) (-f), (double) f); ++ double d2 = Mth.clamp(((double) ((float) (i >> 8 & 15L) / 15.0F) - 0.5D) * 0.5D, (double) (-f), (double) f); ++ ++ return new Vec3(d1, d0, d2); ++ }); ++ break; ++ case XZ: ++ this.offsetFunction = Optional.of((iblockdata, iblockaccess, blockposition) -> { ++ Block block = iblockdata.getBlock(); ++ long i = Mth.getSeed(blockposition.getX(), 0, blockposition.getZ()); ++ float f = block.getMaxHorizontalOffset(); ++ double d0 = Mth.clamp(((double) ((float) (i & 15L) / 15.0F) - 0.5D) * 0.5D, (double) (-f), (double) f); ++ double d1 = Mth.clamp(((double) ((float) (i >> 8 & 15L) / 15.0F) - 0.5D) * 0.5D, (double) (-f), (double) f); ++ ++ return new Vec3(d0, 0.0D, d1); ++ }); ++ break; ++ default: ++ this.offsetFunction = Optional.empty(); ++ } ++ ++ return this; ++ } ++ ++ public BlockBehaviour.Properties noTerrainParticles() { ++ this.spawnTerrainParticles = false; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties requiredFeatures(FeatureFlag... requiredFeatures) { ++ this.requiredFeatures = FeatureFlags.REGISTRY.subset(requiredFeatures); ++ return this; ++ } ++ ++ public BlockBehaviour.Properties instrument(NoteBlockInstrument instrument) { ++ this.instrument = instrument; ++ return this; ++ } ++ ++ public BlockBehaviour.Properties replaceable() { ++ this.replaceable = true; ++ return this; ++ } ++ } ++ ++ public interface StateArgumentPredicate { ++ ++ boolean test(IBlockData state, BlockGetter level, BlockPos pos, A value); ++ } ++ ++ public interface OffsetFunction { ++ ++ Vec3 evaluate(IBlockData state, BlockGetter level, BlockPos pos); ++ } ++ ++ public interface StatePredicate { ++ ++ boolean test(IBlockData state, BlockGetter level, BlockPos pos); ++ } ++ ++ public abstract static class BlockStateBase extends StateHolder { ++ + private final int lightEmission; + private final boolean useShapeForLightOcclusion; + private final boolean isAir; + private final boolean ignitedByLava; ++ /** @deprecated */ + @Deprecated + private final boolean liquid; ++ /** @deprecated */ + @Deprecated + private boolean legacySolid; +- private final PushReaction pushReaction; ++ private final EnumPistonReaction pushReaction; + private final MapColor mapColor; +- private final float destroySpeed; ++ public final float destroySpeed; + private final boolean requiresCorrectToolForDrops; + private final boolean canOcclude; + private final BlockBehaviour.StatePredicate isRedstoneConductor; +@@ -442,54 +844,58 @@ + private final boolean replaceable; + @Nullable + protected BlockBehaviour.BlockStateBase.Cache cache; +- private FluidState fluidState = Fluids.EMPTY.defaultFluidState(); ++ private FluidState fluidState; + private boolean isRandomlyTicking; + +- protected BlockStateBase(Block owner, ImmutableMap, Comparable> values, MapCodec propertiesCodec) { ++ protected BlockStateBase(Block owner, ImmutableMap, Comparable> values, MapCodec propertiesCodec) { + super(owner, values, propertiesCodec); +- BlockBehaviour.Properties properties = owner.properties; +- this.lightEmission = properties.lightEmission.applyAsInt(this.asState()); ++ this.fluidState = Fluids.EMPTY.defaultFluidState(); ++ BlockBehaviour.Properties blockbase_info = owner.properties; ++ ++ this.lightEmission = blockbase_info.lightEmission.applyAsInt(this.asState()); + this.useShapeForLightOcclusion = owner.useShapeForLightOcclusion(this.asState()); +- this.isAir = properties.isAir; +- this.ignitedByLava = properties.ignitedByLava; +- this.liquid = properties.liquid; +- this.pushReaction = properties.pushReaction; +- this.mapColor = properties.mapColor.apply(this.asState()); +- this.destroySpeed = properties.destroyTime; +- this.requiresCorrectToolForDrops = properties.requiresCorrectToolForDrops; +- this.canOcclude = properties.canOcclude; +- this.isRedstoneConductor = properties.isRedstoneConductor; +- this.isSuffocating = properties.isSuffocating; +- this.isViewBlocking = properties.isViewBlocking; +- this.hasPostProcess = properties.hasPostProcess; +- this.emissiveRendering = properties.emissiveRendering; +- this.offsetFunction = properties.offsetFunction; +- this.spawnTerrainParticles = properties.spawnTerrainParticles; +- this.instrument = properties.instrument; +- this.replaceable = properties.replaceable; ++ this.isAir = blockbase_info.isAir; ++ this.ignitedByLava = blockbase_info.ignitedByLava; ++ this.liquid = blockbase_info.liquid; ++ this.pushReaction = blockbase_info.pushReaction; ++ this.mapColor = (MapColor) blockbase_info.mapColor.apply(this.asState()); ++ this.destroySpeed = blockbase_info.destroyTime; ++ this.requiresCorrectToolForDrops = blockbase_info.requiresCorrectToolForDrops; ++ this.canOcclude = blockbase_info.canOcclude; ++ this.isRedstoneConductor = blockbase_info.isRedstoneConductor; ++ this.isSuffocating = blockbase_info.isSuffocating; ++ this.isViewBlocking = blockbase_info.isViewBlocking; ++ this.hasPostProcess = blockbase_info.hasPostProcess; ++ this.emissiveRendering = blockbase_info.emissiveRendering; ++ this.offsetFunction = blockbase_info.offsetFunction; ++ this.spawnTerrainParticles = blockbase_info.spawnTerrainParticles; ++ this.instrument = blockbase_info.instrument; ++ this.replaceable = blockbase_info.replaceable; + } + + private boolean calculateSolid() { +- if (this.owner.properties.forceSolidOn) { ++ if (((Block) this.owner).properties.forceSolidOn) { + return true; +- } else if (this.owner.properties.forceSolidOff) { ++ } else if (((Block) this.owner).properties.forceSolidOff) { + return false; + } else if (this.cache == null) { + return false; + } else { +- VoxelShape voxelShape = this.cache.collisionShape; +- if (voxelShape.isEmpty()) { ++ VoxelShape voxelshape = this.cache.collisionShape; ++ ++ if (voxelshape.isEmpty()) { + return false; + } else { +- AABB aABB = voxelShape.bounds(); +- return aABB.getSize() >= 0.7291666666666666 || aABB.getYsize() >= 1.0; ++ AABB axisalignedbb = voxelshape.bounds(); ++ ++ return axisalignedbb.getSize() >= 0.7291666666666666D ? true : axisalignedbb.getYsize() >= 1.0D; + } + } + } + + public void initCache() { +- this.fluidState = this.owner.getFluidState(this.asState()); +- this.isRandomlyTicking = this.owner.isRandomlyTicking(this.asState()); ++ this.fluidState = ((Block) this.owner).getFluidState(this.asState()); ++ this.isRandomlyTicking = ((Block) this.owner).isRandomlyTicking(this.asState()); + if (!this.getBlock().hasDynamicShape()) { + this.cache = new BlockBehaviour.BlockStateBase.Cache(this.asState()); + } +@@ -498,19 +904,22 @@ + } + + public Block getBlock() { +- return this.owner; ++ return (Block) this.owner; + } + + public Holder getBlockHolder() { +- return this.owner.builtInRegistryHolder(); ++ return ((Block) this.owner).builtInRegistryHolder(); + } + ++ /** @deprecated */ + @Deprecated + public boolean blocksMotion() { + Block block = this.getBlock(); ++ + return block != Blocks.COBWEB && block != Blocks.BAMBOO_SAPLING && this.isSolid(); + } + ++ /** @deprecated */ + @Deprecated + public boolean isSolid() { + return this.legacySolid; +@@ -529,9 +938,7 @@ + } + + public VoxelShape getFaceOcclusionShape(BlockGetter level, BlockPos pos, Direction direction) { +- return this.cache != null && this.cache.occlusionShapes != null +- ? this.cache.occlusionShapes[direction.ordinal()] +- : Shapes.getFaceShape(this.getOcclusionShape(level, pos), direction); ++ return this.cache != null && this.cache.occlusionShapes != null ? this.cache.occlusionShapes[direction.ordinal()] : Shapes.getFaceShape(this.getOcclusionShape(level, pos), direction); + } + + public VoxelShape getOcclusionShape(BlockGetter level, BlockPos pos) { +@@ -558,6 +965,7 @@ + return this.ignitedByLava; + } + ++ /** @deprecated */ + @Deprecated + public boolean liquid() { + return this.liquid; +@@ -567,15 +975,15 @@ + return this.mapColor; + } + +- public BlockState rotate(Rotation rotation) { ++ public IBlockData rotate(Rotation rotation) { + return this.getBlock().rotate(this.asState(), rotation); + } + +- public BlockState mirror(Mirror mirror) { ++ public IBlockData mirror(Mirror mirror) { + return this.getBlock().mirror(this.asState(), mirror); + } + +- public RenderShape getRenderShape() { ++ public EnumRenderType getRenderShape() { + return this.getBlock().getRenderShape(this.asState()); + } + +@@ -619,7 +1027,7 @@ + return this.getBlock().getDirectSignal(this.asState(), level, pos, direction); + } + +- public PushReaction getPistonPushReaction() { ++ public EnumPistonReaction getPistonPushReaction() { + return this.pushReaction; + } + +@@ -627,8 +1035,9 @@ + if (this.cache != null) { + return this.cache.solidRender; + } else { +- BlockState state = this.asState(); +- return state.canOcclude() && Block.isShapeFullBlock(state.getOcclusionShape(level, pos)); ++ IBlockData iblockdata = this.asState(); ++ ++ return iblockdata.canOcclude() ? Block.isShapeFullBlock(iblockdata.getOcclusionShape(level, pos)) : false; + } + } + +@@ -636,7 +1045,7 @@ + return this.canOcclude; + } + +- public boolean skipRendering(BlockState state, Direction face) { ++ public boolean skipRendering(IBlockData state, Direction face) { + return this.getBlock().skipRendering(this.asState(), state, face); + } + +@@ -677,7 +1086,9 @@ + } + + public Vec3 getOffset(BlockGetter level, BlockPos pos) { +- return this.offsetFunction.map(offsetFunction -> offsetFunction.evaluate(this.asState(), level, pos)).orElse(Vec3.ZERO); ++ return (Vec3) this.offsetFunction.map((blockbase_b) -> { ++ return blockbase_b.evaluate(this.asState(), level, pos); ++ }).orElse(Vec3.ZERO); + } + + public boolean hasOffsetFunction() { +@@ -688,6 +1099,7 @@ + return this.getBlock().triggerEvent(this.asState(), level, pos, id, param); + } + ++ /** @deprecated */ + @Deprecated + public void neighborChanged(Level level, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston) { + this.getBlock().neighborChanged(this.asState(), level, pos, neighborBlock, neighborPos, movedByPiston); +@@ -698,12 +1110,17 @@ + } + + public final void updateNeighbourShapes(LevelAccessor level, BlockPos pos, int flags, int recursionLeft) { +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ Direction[] aenumdirection = BlockBehaviour.UPDATE_SHAPE_ORDER; ++ int k = aenumdirection.length; + +- for (Direction direction : BlockBehaviour.UPDATE_SHAPE_ORDER) { +- mutableBlockPos.setWithOffset(pos, direction); +- level.neighborShapeChanged(direction.getOpposite(), this.asState(), mutableBlockPos, pos, flags, recursionLeft); ++ for (int l = 0; l < k; ++l) { ++ Direction enumdirection = aenumdirection[l]; ++ ++ blockposition_mutableblockposition.setWithOffset(pos, enumdirection); ++ level.neighborShapeChanged(enumdirection.getOpposite(), this.asState(), blockposition_mutableblockposition, pos, flags, recursionLeft); + } ++ + } + + public final void updateIndirectNeighbourShapes(LevelAccessor level, BlockPos pos, int flags) { +@@ -714,16 +1131,16 @@ + this.getBlock().updateIndirectNeighbourShapes(this.asState(), level, pos, flags, recursionLeft); + } + +- public void onPlace(Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) { ++ public void onPlace(Level level, BlockPos pos, IBlockData oldState, boolean movedByPiston) { + this.getBlock().onPlace(this.asState(), level, pos, oldState, movedByPiston); + } + +- public void onRemove(Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { ++ public void onRemove(Level level, BlockPos pos, IBlockData newState, boolean movedByPiston) { + this.getBlock().onRemove(this.asState(), level, pos, newState, movedByPiston); + } + +- public void onExplosionHit(Level level, BlockPos blockPos, Explosion explosion, BiConsumer biConsumer) { +- this.getBlock().onExplosionHit(this.asState(), level, blockPos, explosion, biConsumer); ++ public void onExplosionHit(Level world, BlockPos blockposition, Explosion explosion, BiConsumer biconsumer) { ++ this.getBlock().onExplosionHit(this.asState(), world, blockposition, explosion, biconsumer); + } + + public void tick(ServerLevel level, BlockPos pos, RandomSource random) { +@@ -746,7 +1163,7 @@ + return this.getBlock().getDrops(this.asState(), lootParams); + } + +- public InteractionResult use(Level level, Player player, InteractionHand hand, BlockHitResult result) { ++ public InteractionResult use(Level level, Player player, EnumHand hand, BlockHitResult result) { + return this.getBlock().use(this.asState(), level, result.getBlockPos(), player, hand, result); + } + +@@ -762,11 +1179,11 @@ + return this.isViewBlocking.test(this.asState(), level, pos); + } + +- public BlockState updateShape(Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { ++ public IBlockData updateShape(Direction direction, IBlockData neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { + return this.getBlock().updateShape(this.asState(), direction, neighborState, level, pos, neighborPos); + } + +- public boolean isPathfindable(BlockGetter level, BlockPos pos, PathComputationType type) { ++ public boolean isPathfindable(BlockGetter level, BlockPos pos, PathMode type) { + return this.getBlock().isPathfindable(this.asState(), level, pos, type); + } + +@@ -791,7 +1208,7 @@ + } + + @Nullable +- public MenuProvider getMenuProvider(Level level, BlockPos pos) { ++ public ITileInventory getMenuProvider(Level level, BlockPos pos) { + return this.getBlock().getMenuProvider(this.asState(), level, pos); + } + +@@ -808,7 +1225,7 @@ + } + + public boolean is(Holder holder) { +- return this.is(holder.value()); ++ return this.is((Block) holder.value()); + } + + public Stream> getTags() { +@@ -821,15 +1238,15 @@ + + @Nullable + public BlockEntityTicker getTicker(Level level, BlockEntityType blockEntityType) { +- return this.getBlock() instanceof EntityBlock ? ((EntityBlock)this.getBlock()).getTicker(level, this.asState(), blockEntityType) : null; ++ return this.getBlock() instanceof EntityBlock ? ((EntityBlock) this.getBlock()).getTicker(level, this.asState(), blockEntityType) : null; + } + + public boolean is(Block block) { + return this.getBlock() == block; + } + +- public boolean is(ResourceKey resourceKey) { +- return this.getBlock().builtInRegistryHolder().is(resourceKey); ++ public boolean is(ResourceKey resourcekey) { ++ return this.getBlock().builtInRegistryHolder().is(resourcekey); + } + + public FluidState getFluidState() { +@@ -848,7 +1265,7 @@ + return this.getBlock().getSoundType(this.asState()); + } + +- public void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) { ++ public void onProjectileHit(Level level, IBlockData state, BlockHitResult hit, Projectile projectile) { + this.getBlock().onProjectileHit(level, state, hit, projectile); + } + +@@ -864,7 +1281,7 @@ + return this.cache != null ? this.cache.isCollisionShapeFullBlock : this.getBlock().isCollisionShapeFullBlock(this.asState(), level, pos); + } + +- protected abstract BlockState asState(); ++ protected abstract IBlockData asState(); + + public boolean requiresCorrectToolForDrops() { + return this.requiresCorrectToolForDrops; +@@ -878,7 +1295,8 @@ + return this.instrument; + } + +- static final class Cache { ++ private static final class Cache { ++ + private static final Direction[] DIRECTIONS = Direction.values(); + private static final int SUPPORT_TYPE_COUNT = SupportType.values().length; + protected final boolean solidRender; +@@ -891,384 +1309,71 @@ + private final boolean[] faceSturdy; + protected final boolean isCollisionShapeFullBlock; + +- Cache(BlockState state) { +- Block block = state.getBlock(); +- this.solidRender = state.isSolidRender(EmptyBlockGetter.INSTANCE, BlockPos.ZERO); +- this.propagatesSkylightDown = block.propagatesSkylightDown(state, EmptyBlockGetter.INSTANCE, BlockPos.ZERO); +- this.lightBlock = block.getLightBlock(state, EmptyBlockGetter.INSTANCE, BlockPos.ZERO); +- if (!state.canOcclude()) { ++ Cache(IBlockData iblockdata) { ++ Block block = iblockdata.getBlock(); ++ ++ this.solidRender = iblockdata.isSolidRender(EmptyBlockGetter.INSTANCE, BlockPos.ZERO); ++ this.propagatesSkylightDown = block.propagatesSkylightDown(iblockdata, EmptyBlockGetter.INSTANCE, BlockPos.ZERO); ++ this.lightBlock = block.getLightBlock(iblockdata, EmptyBlockGetter.INSTANCE, BlockPos.ZERO); ++ int i; ++ ++ if (!iblockdata.canOcclude()) { + this.occlusionShapes = null; + } else { +- this.occlusionShapes = new VoxelShape[DIRECTIONS.length]; +- VoxelShape occlusionShape = block.getOcclusionShape(state, EmptyBlockGetter.INSTANCE, BlockPos.ZERO); ++ this.occlusionShapes = new VoxelShape[BlockBehaviour.BlockStateBase.Cache.DIRECTIONS.length]; ++ VoxelShape voxelshape = block.getOcclusionShape(iblockdata, EmptyBlockGetter.INSTANCE, BlockPos.ZERO); ++ Direction[] aenumdirection = BlockBehaviour.BlockStateBase.Cache.DIRECTIONS; + +- for (Direction direction : DIRECTIONS) { +- this.occlusionShapes[direction.ordinal()] = Shapes.getFaceShape(occlusionShape, direction); ++ i = aenumdirection.length; ++ ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ ++ this.occlusionShapes[enumdirection.ordinal()] = Shapes.getFaceShape(voxelshape, enumdirection); + } + } + +- this.collisionShape = block.getCollisionShape(state, EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()); +- if (!this.collisionShape.isEmpty() && state.hasOffsetFunction()) { +- throw new IllegalStateException( +- String.format( +- Locale.ROOT, +- "%s has a collision shape and an offset type, but is not marked as dynamicShape in its properties.", +- BuiltInRegistries.BLOCK.getKey(block) +- ) +- ); ++ this.collisionShape = block.getCollisionShape(iblockdata, EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CollisionContext.empty()); ++ if (!this.collisionShape.isEmpty() && iblockdata.hasOffsetFunction()) { ++ throw new IllegalStateException(String.format(Locale.ROOT, "%s has a collision shape and an offset type, but is not marked as dynamicShape in its properties.", BuiltInRegistries.BLOCK.getKey(block))); + } else { +- this.largeCollisionShape = Arrays.stream(Direction.Axis.values()) +- .anyMatch(dir -> this.collisionShape.min(dir) < 0.0 || this.collisionShape.max(dir) > 1.0); +- this.faceSturdy = new boolean[DIRECTIONS.length * SUPPORT_TYPE_COUNT]; ++ this.largeCollisionShape = Arrays.stream(Direction.Axis.values()).anyMatch((enumdirection_enumaxis) -> { ++ return this.collisionShape.min(enumdirection_enumaxis) < 0.0D || this.collisionShape.max(enumdirection_enumaxis) > 1.0D; ++ }); ++ this.faceSturdy = new boolean[BlockBehaviour.BlockStateBase.Cache.DIRECTIONS.length * BlockBehaviour.BlockStateBase.Cache.SUPPORT_TYPE_COUNT]; ++ Direction[] aenumdirection1 = BlockBehaviour.BlockStateBase.Cache.DIRECTIONS; ++ int k = aenumdirection1.length; + +- for (Direction direction1 : DIRECTIONS) { +- for (SupportType supportType : SupportType.values()) { +- this.faceSturdy[getFaceSupportIndex(direction1, supportType)] = supportType.isSupporting( +- state, EmptyBlockGetter.INSTANCE, BlockPos.ZERO, direction1 +- ); ++ for (i = 0; i < k; ++i) { ++ Direction enumdirection1 = aenumdirection1[i]; ++ SupportType[] aenumblocksupport = SupportType.values(); ++ int l = aenumblocksupport.length; ++ ++ for (int i1 = 0; i1 < l; ++i1) { ++ SupportType enumblocksupport = aenumblocksupport[i1]; ++ ++ this.faceSturdy[getFaceSupportIndex(enumdirection1, enumblocksupport)] = enumblocksupport.isSupporting(iblockdata, EmptyBlockGetter.INSTANCE, BlockPos.ZERO, enumdirection1); + } + } + +- this.isCollisionShapeFullBlock = Block.isShapeFullBlock(state.getCollisionShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)); ++ this.isCollisionShapeFullBlock = Block.isShapeFullBlock(iblockdata.getCollisionShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)); + } + } + +- public boolean isFaceSturdy(Direction direction, SupportType supportType) { +- return this.faceSturdy[getFaceSupportIndex(direction, supportType)]; ++ public boolean isFaceSturdy(Direction enumdirection, SupportType enumblocksupport) { ++ return this.faceSturdy[getFaceSupportIndex(enumdirection, enumblocksupport)]; + } + +- private static int getFaceSupportIndex(Direction direction, SupportType supportType) { +- return direction.ordinal() * SUPPORT_TYPE_COUNT + supportType.ordinal(); ++ private static int getFaceSupportIndex(Direction enumdirection, SupportType enumblocksupport) { ++ return enumdirection.ordinal() * BlockBehaviour.BlockStateBase.Cache.SUPPORT_TYPE_COUNT + enumblocksupport.ordinal(); + } + } + } + +- public interface OffsetFunction { +- Vec3 evaluate(BlockState state, BlockGetter level, BlockPos pos); +- } ++ public static enum EnumRandomOffset { + +- public static enum OffsetType { +- NONE, +- XZ, +- XYZ; +- } ++ NONE, XZ, XYZ; + +- public static class Properties { +- public static final Codec CODEC = Codec.unit(() -> of()); +- Function mapColor = blockState -> MapColor.NONE; +- boolean hasCollision = true; +- SoundType soundType = SoundType.STONE; +- ToIntFunction lightEmission = blockState -> 0; +- float explosionResistance; +- float destroyTime; +- boolean requiresCorrectToolForDrops; +- boolean isRandomlyTicking; +- float friction = 0.6F; +- float speedFactor = 1.0F; +- float jumpFactor = 1.0F; +- ResourceLocation drops; +- boolean canOcclude = true; +- boolean isAir; +- boolean ignitedByLava; +- @Deprecated +- boolean liquid; +- @Deprecated +- boolean forceSolidOff; +- boolean forceSolidOn; +- PushReaction pushReaction = PushReaction.NORMAL; +- boolean spawnTerrainParticles = true; +- NoteBlockInstrument instrument = NoteBlockInstrument.HARP; +- boolean replaceable; +- BlockBehaviour.StateArgumentPredicate> isValidSpawn = (state, level, pos, value) -> state.isFaceSturdy(level, pos, Direction.UP) +- && state.getLightEmission() < 14; +- BlockBehaviour.StatePredicate isRedstoneConductor = (state, level, pos) -> state.isCollisionShapeFullBlock(level, pos); +- BlockBehaviour.StatePredicate isSuffocating = (state, level, pos) -> state.blocksMotion() && state.isCollisionShapeFullBlock(level, pos); +- BlockBehaviour.StatePredicate isViewBlocking = this.isSuffocating; +- BlockBehaviour.StatePredicate hasPostProcess = (state, level, pos) -> false; +- BlockBehaviour.StatePredicate emissiveRendering = (state, level, pos) -> false; +- boolean dynamicShape; +- FeatureFlagSet requiredFeatures = FeatureFlags.VANILLA_SET; +- Optional offsetFunction = Optional.empty(); +- +- private Properties() { +- } +- +- public static BlockBehaviour.Properties of() { +- return new BlockBehaviour.Properties(); +- } +- +- public static BlockBehaviour.Properties ofFullCopy(BlockBehaviour blockBehaviour) { +- BlockBehaviour.Properties properties = ofLegacyCopy(blockBehaviour); +- BlockBehaviour.Properties properties1 = blockBehaviour.properties; +- properties.jumpFactor = properties1.jumpFactor; +- properties.isRedstoneConductor = properties1.isRedstoneConductor; +- properties.isValidSpawn = properties1.isValidSpawn; +- properties.hasPostProcess = properties1.hasPostProcess; +- properties.isSuffocating = properties1.isSuffocating; +- properties.isViewBlocking = properties1.isViewBlocking; +- properties.drops = properties1.drops; +- return properties; +- } +- +- @Deprecated +- public static BlockBehaviour.Properties ofLegacyCopy(BlockBehaviour blockBehaviour) { +- BlockBehaviour.Properties properties = new BlockBehaviour.Properties(); +- BlockBehaviour.Properties properties1 = blockBehaviour.properties; +- properties.destroyTime = properties1.destroyTime; +- properties.explosionResistance = properties1.explosionResistance; +- properties.hasCollision = properties1.hasCollision; +- properties.isRandomlyTicking = properties1.isRandomlyTicking; +- properties.lightEmission = properties1.lightEmission; +- properties.mapColor = properties1.mapColor; +- properties.soundType = properties1.soundType; +- properties.friction = properties1.friction; +- properties.speedFactor = properties1.speedFactor; +- properties.dynamicShape = properties1.dynamicShape; +- properties.canOcclude = properties1.canOcclude; +- properties.isAir = properties1.isAir; +- properties.ignitedByLava = properties1.ignitedByLava; +- properties.liquid = properties1.liquid; +- properties.forceSolidOff = properties1.forceSolidOff; +- properties.forceSolidOn = properties1.forceSolidOn; +- properties.pushReaction = properties1.pushReaction; +- properties.requiresCorrectToolForDrops = properties1.requiresCorrectToolForDrops; +- properties.offsetFunction = properties1.offsetFunction; +- properties.spawnTerrainParticles = properties1.spawnTerrainParticles; +- properties.requiredFeatures = properties1.requiredFeatures; +- properties.emissiveRendering = properties1.emissiveRendering; +- properties.instrument = properties1.instrument; +- properties.replaceable = properties1.replaceable; +- return properties; +- } +- +- public BlockBehaviour.Properties mapColor(DyeColor mapColor) { +- this.mapColor = blockState -> mapColor.getMapColor(); +- return this; +- } +- +- public BlockBehaviour.Properties mapColor(MapColor mapColor) { +- this.mapColor = blockState -> mapColor; +- return this; +- } +- +- public BlockBehaviour.Properties mapColor(Function mapColor) { +- this.mapColor = mapColor; +- return this; +- } +- +- public BlockBehaviour.Properties noCollission() { +- this.hasCollision = false; +- this.canOcclude = false; +- return this; +- } +- +- public BlockBehaviour.Properties noOcclusion() { +- this.canOcclude = false; +- return this; +- } +- +- public BlockBehaviour.Properties friction(float friction) { +- this.friction = friction; +- return this; +- } +- +- public BlockBehaviour.Properties speedFactor(float speedFactor) { +- this.speedFactor = speedFactor; +- return this; +- } +- +- public BlockBehaviour.Properties jumpFactor(float jumpFactor) { +- this.jumpFactor = jumpFactor; +- return this; +- } +- +- public BlockBehaviour.Properties sound(SoundType soundType) { +- this.soundType = soundType; +- return this; +- } +- +- public BlockBehaviour.Properties lightLevel(ToIntFunction lightEmission) { +- this.lightEmission = lightEmission; +- return this; +- } +- +- public BlockBehaviour.Properties strength(float destroyTime, float explosionResistance) { +- return this.destroyTime(destroyTime).explosionResistance(explosionResistance); +- } +- +- public BlockBehaviour.Properties instabreak() { +- return this.strength(0.0F); +- } +- +- public BlockBehaviour.Properties strength(float strength) { +- this.strength(strength, strength); +- return this; +- } +- +- public BlockBehaviour.Properties randomTicks() { +- this.isRandomlyTicking = true; +- return this; +- } +- +- public BlockBehaviour.Properties dynamicShape() { +- this.dynamicShape = true; +- return this; +- } +- +- public BlockBehaviour.Properties noLootTable() { +- this.drops = BuiltInLootTables.EMPTY; +- return this; +- } +- +- public BlockBehaviour.Properties dropsLike(Block block) { +- this.drops = block.getLootTable(); +- return this; +- } +- +- public BlockBehaviour.Properties ignitedByLava() { +- this.ignitedByLava = true; +- return this; +- } +- +- public BlockBehaviour.Properties liquid() { +- this.liquid = true; +- return this; +- } +- +- public BlockBehaviour.Properties forceSolidOn() { +- this.forceSolidOn = true; +- return this; +- } +- +- @Deprecated +- public BlockBehaviour.Properties forceSolidOff() { +- this.forceSolidOff = true; +- return this; +- } +- +- public BlockBehaviour.Properties pushReaction(PushReaction pushReaction) { +- this.pushReaction = pushReaction; +- return this; +- } +- +- public BlockBehaviour.Properties air() { +- this.isAir = true; +- return this; +- } +- +- public BlockBehaviour.Properties isValidSpawn(BlockBehaviour.StateArgumentPredicate> isValidSpawn) { +- this.isValidSpawn = isValidSpawn; +- return this; +- } +- +- public BlockBehaviour.Properties isRedstoneConductor(BlockBehaviour.StatePredicate isRedstoneConductor) { +- this.isRedstoneConductor = isRedstoneConductor; +- return this; +- } +- +- public BlockBehaviour.Properties isSuffocating(BlockBehaviour.StatePredicate isSuffocating) { +- this.isSuffocating = isSuffocating; +- return this; +- } +- +- public BlockBehaviour.Properties isViewBlocking(BlockBehaviour.StatePredicate isViewBlocking) { +- this.isViewBlocking = isViewBlocking; +- return this; +- } +- +- public BlockBehaviour.Properties hasPostProcess(BlockBehaviour.StatePredicate hasPostProcess) { +- this.hasPostProcess = hasPostProcess; +- return this; +- } +- +- public BlockBehaviour.Properties emissiveRendering(BlockBehaviour.StatePredicate emissiveRendering) { +- this.emissiveRendering = emissiveRendering; +- return this; +- } +- +- public BlockBehaviour.Properties requiresCorrectToolForDrops() { +- this.requiresCorrectToolForDrops = true; +- return this; +- } +- +- public BlockBehaviour.Properties destroyTime(float destroyTime) { +- this.destroyTime = destroyTime; +- return this; +- } +- +- public BlockBehaviour.Properties explosionResistance(float explosionResistance) { +- this.explosionResistance = Math.max(0.0F, explosionResistance); +- return this; +- } +- +- public BlockBehaviour.Properties offsetType(BlockBehaviour.OffsetType offsetType) { +- switch (offsetType) { +- case XYZ: +- this.offsetFunction = Optional.of( +- (state, level, pos) -> { +- Block block = state.getBlock(); +- long seed = Mth.getSeed(pos.getX(), 0, pos.getZ()); +- double d = ((double)((float)(seed >> 4 & 15L) / 15.0F) - 1.0) * (double)block.getMaxVerticalOffset(); +- float maxHorizontalOffset = block.getMaxHorizontalOffset(); +- double d1 = Mth.clamp( +- ((double)((float)(seed & 15L) / 15.0F) - 0.5) * 0.5, (double)(-maxHorizontalOffset), (double)maxHorizontalOffset +- ); +- double d2 = Mth.clamp( +- ((double)((float)(seed >> 8 & 15L) / 15.0F) - 0.5) * 0.5, (double)(-maxHorizontalOffset), (double)maxHorizontalOffset +- ); +- return new Vec3(d1, d, d2); +- } +- ); +- break; +- case XZ: +- this.offsetFunction = Optional.of( +- (state, level, pos) -> { +- Block block = state.getBlock(); +- long seed = Mth.getSeed(pos.getX(), 0, pos.getZ()); +- float maxHorizontalOffset = block.getMaxHorizontalOffset(); +- double d = Mth.clamp( +- ((double)((float)(seed & 15L) / 15.0F) - 0.5) * 0.5, (double)(-maxHorizontalOffset), (double)maxHorizontalOffset +- ); +- double d1 = Mth.clamp( +- ((double)((float)(seed >> 8 & 15L) / 15.0F) - 0.5) * 0.5, (double)(-maxHorizontalOffset), (double)maxHorizontalOffset +- ); +- return new Vec3(d, 0.0, d1); +- } +- ); +- break; +- default: +- this.offsetFunction = Optional.empty(); +- } +- +- return this; +- } +- +- public BlockBehaviour.Properties noTerrainParticles() { +- this.spawnTerrainParticles = false; +- return this; +- } +- +- public BlockBehaviour.Properties requiredFeatures(FeatureFlag... requiredFeatures) { +- this.requiredFeatures = FeatureFlags.REGISTRY.subset(requiredFeatures); +- return this; +- } +- +- public BlockBehaviour.Properties instrument(NoteBlockInstrument instrument) { +- this.instrument = instrument; +- return this; +- } +- +- public BlockBehaviour.Properties replaceable() { +- this.replaceable = true; +- return this; +- } ++ private EnumRandomOffset() {} + } +- +- public interface StateArgumentPredicate { +- boolean test(BlockState state, BlockGetter level, BlockPos pos, A value); +- } +- +- public interface StatePredicate { +- boolean test(BlockState state, BlockGetter level, BlockPos pos); +- } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/border/WorldBorder.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/border/WorldBorder.java.patch new file mode 100644 index 0000000000..3c03e915dc --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/border/WorldBorder.java.patch @@ -0,0 +1,647 @@ +--- a/net/minecraft/world/level/border/WorldBorder.java ++++ b/net/minecraft/world/level/border/WorldBorder.java +@@ -2,6 +2,7 @@ + + import com.google.common.collect.Lists; + import com.mojang.serialization.DynamicLike; ++import java.util.Iterator; + import java.util.List; + import net.minecraft.Util; + import net.minecraft.core.BlockPos; +@@ -15,47 +16,45 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + + public class WorldBorder { +- public static final double MAX_SIZE = 5.999997E7F; +- public static final double MAX_CENTER_COORDINATE = 2.9999984E7; ++ ++ public static final double MAX_SIZE = 5.9999968E7D; ++ public static final double MAX_CENTER_COORDINATE = 2.9999984E7D; + private final List listeners = Lists.newArrayList(); +- private double damagePerBlock = 0.2; +- private double damageSafeZone = 5.0; ++ private double damagePerBlock = 0.2D; ++ private double damageSafeZone = 5.0D; + private int warningTime = 15; + private int warningBlocks = 5; + private double centerX; + private double centerZ; + int absoluteMaxSize = 29999984; +- private WorldBorder.BorderExtent extent = new WorldBorder.StaticBorderExtent(5.999997E7F); +- public static final WorldBorder.Settings DEFAULT_SETTINGS = new WorldBorder.Settings(0.0, 0.0, 0.2, 5.0, 5, 15, 5.999997E7F, 0L, 0.0); ++ private WorldBorder.a extent = new WorldBorder.StaticBorderExtent(5.9999968E7D); ++ public static final WorldBorder.Settings DEFAULT_SETTINGS = new WorldBorder.Settings(0.0D, 0.0D, 0.2D, 5.0D, 5, 15, 5.9999968E7D, 0L, 0.0D); ++ public net.minecraft.server.level.ServerLevel world; // CraftBukkit + ++ public WorldBorder() {} ++ + public boolean isWithinBounds(BlockPos pos) { +- return (double)(pos.getX() + 1) > this.getMinX() +- && (double)pos.getX() < this.getMaxX() +- && (double)(pos.getZ() + 1) > this.getMinZ() +- && (double)pos.getZ() < this.getMaxZ(); ++ return (double) (pos.getX() + 1) > this.getMinX() && (double) pos.getX() < this.getMaxX() && (double) (pos.getZ() + 1) > this.getMinZ() && (double) pos.getZ() < this.getMaxZ(); + } + + public boolean isWithinBounds(ChunkPos chunkPos) { +- return (double)chunkPos.getMaxBlockX() > this.getMinX() +- && (double)chunkPos.getMinBlockX() < this.getMaxX() +- && (double)chunkPos.getMaxBlockZ() > this.getMinZ() +- && (double)chunkPos.getMinBlockZ() < this.getMaxZ(); ++ return (double) chunkPos.getMaxBlockX() > this.getMinX() && (double) chunkPos.getMinBlockX() < this.getMaxX() && (double) chunkPos.getMaxBlockZ() > this.getMinZ() && (double) chunkPos.getMinBlockZ() < this.getMaxZ(); + } + +- public boolean isWithinBounds(double x, double z) { +- return x > this.getMinX() && x < this.getMaxX() && z > this.getMinZ() && z < this.getMaxZ(); ++ public boolean isWithinBounds(double x, double d1) { ++ return x > this.getMinX() && x < this.getMaxX() && d1 > this.getMinZ() && d1 < this.getMaxZ(); + } + +- public boolean isWithinBounds(double x, double z, double offset) { +- return x > this.getMinX() - offset && x < this.getMaxX() + offset && z > this.getMinZ() - offset && z < this.getMaxZ() + offset; ++ public boolean isWithinBounds(double x, double d1, double z) { ++ return x > this.getMinX() - z && x < this.getMaxX() + z && d1 > this.getMinZ() - z && d1 < this.getMaxZ() + z; + } + + public boolean isWithinBounds(AABB box) { + return box.maxX > this.getMinX() && box.minX < this.getMaxX() && box.maxZ > this.getMinZ() && box.minZ < this.getMaxZ(); + } + +- public BlockPos clampToBounds(double x, double y, double z) { +- return BlockPos.containing(Mth.clamp(x, this.getMinX(), this.getMaxX()), y, Mth.clamp(z, this.getMinZ(), this.getMaxZ())); ++ public BlockPos clampToBounds(double x, double d1, double y) { ++ return BlockPos.containing(Mth.clamp(x, this.getMinX(), this.getMaxX()), d1, Mth.clamp(y, this.getMinZ(), this.getMaxZ())); + } + + public double getDistanceToBorder(Entity entity) { +@@ -66,19 +65,21 @@ + return this.extent.getCollisionShape(); + } + +- public double getDistanceToBorder(double x, double z) { +- double d = z - this.getMinZ(); +- double d1 = this.getMaxZ() - z; +- double d2 = x - this.getMinX(); +- double d3 = this.getMaxX() - x; +- double min = Math.min(d2, d3); +- min = Math.min(min, d); +- return Math.min(min, d1); ++ public double getDistanceToBorder(double x, double d1) { ++ double d2 = d1 - this.getMinZ(); ++ double d3 = this.getMaxZ() - d1; ++ double d4 = x - this.getMinX(); ++ double d5 = this.getMaxX() - x; ++ double d6 = Math.min(d4, d5); ++ ++ d6 = Math.min(d6, d2); ++ return Math.min(d6, d3); + } + + public boolean isInsideCloseToBorder(Entity entity, AABB bounds) { +- double max = Math.max(Mth.absMax(bounds.getXsize(), bounds.getZsize()), 1.0); +- return this.getDistanceToBorder(entity) < max * 2.0 && this.isWithinBounds(entity.getX(), entity.getZ(), max); ++ double d0 = Math.max(Mth.absMax(bounds.getXsize(), bounds.getZsize()), 1.0D); ++ ++ return this.getDistanceToBorder(entity) < d0 * 2.0D && this.isWithinBounds(entity.getX(), entity.getZ(), d0); + } + + public BorderStatus getStatus() { +@@ -109,14 +110,18 @@ + return this.centerZ; + } + +- public void setCenter(double x, double z) { ++ public void setCenter(double x, double d1) { + this.centerX = x; +- this.centerZ = z; ++ this.centerZ = d1; + this.extent.onCenterChange(); ++ Iterator iterator = this.getListeners().iterator(); + +- for (BorderChangeListener borderChangeListener : this.getListeners()) { +- borderChangeListener.onBorderCenterSet(this, x, z); ++ while (iterator.hasNext()) { ++ BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); ++ ++ iworldborderlistener.onBorderCenterSet(this, x, d1); + } ++ + } + + public double getSize() { +@@ -133,20 +138,26 @@ + + public void setSize(double size) { + this.extent = new WorldBorder.StaticBorderExtent(size); ++ Iterator iterator = this.getListeners().iterator(); + +- for (BorderChangeListener borderChangeListener : this.getListeners()) { +- borderChangeListener.onBorderSizeSet(this, size); ++ while (iterator.hasNext()) { ++ BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); ++ ++ iworldborderlistener.onBorderSizeSet(this, size); + } ++ + } + +- public void lerpSizeBetween(double oldSize, double newSize, long time) { +- this.extent = (WorldBorder.BorderExtent)(oldSize == newSize +- ? new WorldBorder.StaticBorderExtent(newSize) +- : new WorldBorder.MovingBorderExtent(oldSize, newSize, time)); ++ public void lerpSizeBetween(double oldSize, double d1, long newSize) { ++ this.extent = (WorldBorder.a) (oldSize == d1 ? new WorldBorder.StaticBorderExtent(d1) : new WorldBorder.MovingBorderExtent(oldSize, d1, newSize)); ++ Iterator iterator = this.getListeners().iterator(); + +- for (BorderChangeListener borderChangeListener : this.getListeners()) { +- borderChangeListener.onBorderSizeLerping(this, oldSize, newSize, time); ++ while (iterator.hasNext()) { ++ BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); ++ ++ iworldborderlistener.onBorderSizeLerping(this, oldSize, d1, newSize); + } ++ + } + + protected List getListeners() { +@@ -154,6 +165,7 @@ + } + + public void addListener(BorderChangeListener listener) { ++ if (listeners.contains(listener)) return; // CraftBukkit + this.listeners.add(listener); + } + +@@ -176,10 +188,14 @@ + + public void setDamageSafeZone(double damageSafeZone) { + this.damageSafeZone = damageSafeZone; ++ Iterator iterator = this.getListeners().iterator(); + +- for (BorderChangeListener borderChangeListener : this.getListeners()) { +- borderChangeListener.onBorderSetDamageSafeZOne(this, damageSafeZone); ++ while (iterator.hasNext()) { ++ BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); ++ ++ iworldborderlistener.onBorderSetDamageSafeZOne(this, damageSafeZone); + } ++ + } + + public double getDamagePerBlock() { +@@ -188,10 +204,14 @@ + + public void setDamagePerBlock(double damagePerBlock) { + this.damagePerBlock = damagePerBlock; ++ Iterator iterator = this.getListeners().iterator(); + +- for (BorderChangeListener borderChangeListener : this.getListeners()) { +- borderChangeListener.onBorderSetDamagePerBlock(this, damagePerBlock); ++ while (iterator.hasNext()) { ++ BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); ++ ++ iworldborderlistener.onBorderSetDamagePerBlock(this, damagePerBlock); + } ++ + } + + public double getLerpSpeed() { +@@ -204,10 +224,14 @@ + + public void setWarningTime(int warningTime) { + this.warningTime = warningTime; ++ Iterator iterator = this.getListeners().iterator(); + +- for (BorderChangeListener borderChangeListener : this.getListeners()) { +- borderChangeListener.onBorderSetWarningTime(this, warningTime); ++ while (iterator.hasNext()) { ++ BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); ++ ++ iworldborderlistener.onBorderSetWarningTime(this, warningTime); + } ++ + } + + public int getWarningBlocks() { +@@ -216,10 +240,14 @@ + + public void setWarningBlocks(int warningDistance) { + this.warningBlocks = warningDistance; ++ Iterator iterator = this.getListeners().iterator(); + +- for (BorderChangeListener borderChangeListener : this.getListeners()) { +- borderChangeListener.onBorderSetWarningBlocks(this, warningDistance); ++ while (iterator.hasNext()) { ++ BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); ++ ++ iworldborderlistener.onBorderSetWarningBlocks(this, warningDistance); + } ++ + } + + public void tick() { +@@ -241,9 +269,99 @@ + } else { + this.setSize(serializer.getSize()); + } ++ + } + +- interface BorderExtent { ++ private class StaticBorderExtent implements WorldBorder.a { ++ ++ private final double size; ++ private double minX; ++ private double minZ; ++ private double maxX; ++ private double maxZ; ++ private VoxelShape shape; ++ ++ public StaticBorderExtent(double d0) { ++ this.size = d0; ++ this.updateBox(); ++ } ++ ++ @Override ++ public double getMinX() { ++ return this.minX; ++ } ++ ++ @Override ++ public double getMaxX() { ++ return this.maxX; ++ } ++ ++ @Override ++ public double getMinZ() { ++ return this.minZ; ++ } ++ ++ @Override ++ public double getMaxZ() { ++ return this.maxZ; ++ } ++ ++ @Override ++ public double getSize() { ++ return this.size; ++ } ++ ++ @Override ++ public BorderStatus getStatus() { ++ return BorderStatus.STATIONARY; ++ } ++ ++ @Override ++ public double getLerpSpeed() { ++ return 0.0D; ++ } ++ ++ @Override ++ public long getLerpRemainingTime() { ++ return 0L; ++ } ++ ++ @Override ++ public double getLerpTarget() { ++ return this.size; ++ } ++ ++ private void updateBox() { ++ this.minX = Mth.clamp(WorldBorder.this.getCenterX() - this.size / 2.0D, (double) (-WorldBorder.this.absoluteMaxSize), (double) WorldBorder.this.absoluteMaxSize); ++ this.minZ = Mth.clamp(WorldBorder.this.getCenterZ() - this.size / 2.0D, (double) (-WorldBorder.this.absoluteMaxSize), (double) WorldBorder.this.absoluteMaxSize); ++ this.maxX = Mth.clamp(WorldBorder.this.getCenterX() + this.size / 2.0D, (double) (-WorldBorder.this.absoluteMaxSize), (double) WorldBorder.this.absoluteMaxSize); ++ this.maxZ = Mth.clamp(WorldBorder.this.getCenterZ() + this.size / 2.0D, (double) (-WorldBorder.this.absoluteMaxSize), (double) WorldBorder.this.absoluteMaxSize); ++ this.shape = Shapes.join(Shapes.INFINITY, Shapes.box(Math.floor(this.getMinX()), Double.NEGATIVE_INFINITY, Math.floor(this.getMinZ()), Math.ceil(this.getMaxX()), Double.POSITIVE_INFINITY, Math.ceil(this.getMaxZ())), BooleanOp.ONLY_FIRST); ++ } ++ ++ @Override ++ public void onAbsoluteMaxSizeChange() { ++ this.updateBox(); ++ } ++ ++ @Override ++ public void onCenterChange() { ++ this.updateBox(); ++ } ++ ++ @Override ++ public WorldBorder.a update() { ++ return this; ++ } ++ ++ @Override ++ public VoxelShape getCollisionShape() { ++ return this.shape; ++ } ++ } ++ ++ private interface a { ++ + double getMinX(); + + double getMaxX(); +@@ -266,63 +384,57 @@ + + void onCenterChange(); + +- WorldBorder.BorderExtent update(); ++ WorldBorder.a update(); + + VoxelShape getCollisionShape(); + } + +- class MovingBorderExtent implements WorldBorder.BorderExtent { ++ private class MovingBorderExtent implements WorldBorder.a { ++ + private final double from; + private final double to; + private final long lerpEnd; + private final long lerpBegin; + private final double lerpDuration; + +- MovingBorderExtent(double from, double to, long lerpDuration) { +- this.from = from; +- this.to = to; +- this.lerpDuration = (double)lerpDuration; ++ MovingBorderExtent(double d0, double d1, long i) { ++ this.from = d0; ++ this.to = d1; ++ this.lerpDuration = (double) i; + this.lerpBegin = Util.getMillis(); +- this.lerpEnd = this.lerpBegin + lerpDuration; ++ this.lerpEnd = this.lerpBegin + i; + } + + @Override + public double getMinX() { +- return Mth.clamp( +- WorldBorder.this.getCenterX() - this.getSize() / 2.0, (double)(-WorldBorder.this.absoluteMaxSize), (double)WorldBorder.this.absoluteMaxSize +- ); ++ return Mth.clamp(WorldBorder.this.getCenterX() - this.getSize() / 2.0D, (double) (-WorldBorder.this.absoluteMaxSize), (double) WorldBorder.this.absoluteMaxSize); + } + + @Override + public double getMinZ() { +- return Mth.clamp( +- WorldBorder.this.getCenterZ() - this.getSize() / 2.0, (double)(-WorldBorder.this.absoluteMaxSize), (double)WorldBorder.this.absoluteMaxSize +- ); ++ return Mth.clamp(WorldBorder.this.getCenterZ() - this.getSize() / 2.0D, (double) (-WorldBorder.this.absoluteMaxSize), (double) WorldBorder.this.absoluteMaxSize); + } + + @Override + public double getMaxX() { +- return Mth.clamp( +- WorldBorder.this.getCenterX() + this.getSize() / 2.0, (double)(-WorldBorder.this.absoluteMaxSize), (double)WorldBorder.this.absoluteMaxSize +- ); ++ return Mth.clamp(WorldBorder.this.getCenterX() + this.getSize() / 2.0D, (double) (-WorldBorder.this.absoluteMaxSize), (double) WorldBorder.this.absoluteMaxSize); + } + + @Override + public double getMaxZ() { +- return Mth.clamp( +- WorldBorder.this.getCenterZ() + this.getSize() / 2.0, (double)(-WorldBorder.this.absoluteMaxSize), (double)WorldBorder.this.absoluteMaxSize +- ); ++ return Mth.clamp(WorldBorder.this.getCenterZ() + this.getSize() / 2.0D, (double) (-WorldBorder.this.absoluteMaxSize), (double) WorldBorder.this.absoluteMaxSize); + } + + @Override + public double getSize() { +- double d = (double)(Util.getMillis() - this.lerpBegin) / this.lerpDuration; +- return d < 1.0 ? Mth.lerp(d, this.from, this.to) : this.to; ++ double d0 = (double) (Util.getMillis() - this.lerpBegin) / this.lerpDuration; ++ ++ return d0 < 1.0D ? Mth.lerp(d0, this.from, this.to) : this.to; + } + + @Override + public double getLerpSpeed() { +- return Math.abs(this.from - this.to) / (double)(this.lerpEnd - this.lerpBegin); ++ return Math.abs(this.from - this.to) / (double) (this.lerpEnd - this.lerpBegin); + } + + @Override +@@ -341,36 +453,24 @@ + } + + @Override +- public void onCenterChange() { +- } ++ public void onCenterChange() {} + + @Override +- public void onAbsoluteMaxSizeChange() { +- } ++ public void onAbsoluteMaxSizeChange() {} + + @Override +- public WorldBorder.BorderExtent update() { +- return (WorldBorder.BorderExtent)(this.getLerpRemainingTime() <= 0L ? WorldBorder.this.new StaticBorderExtent(this.to) : this); ++ public WorldBorder.a update() { ++ return (WorldBorder.a) (this.getLerpRemainingTime() <= 0L ? WorldBorder.this.new StaticBorderExtent(this.to) : this); + } + + @Override + public VoxelShape getCollisionShape() { +- return Shapes.join( +- Shapes.INFINITY, +- Shapes.box( +- Math.floor(this.getMinX()), +- Double.NEGATIVE_INFINITY, +- Math.floor(this.getMinZ()), +- Math.ceil(this.getMaxX()), +- Double.POSITIVE_INFINITY, +- Math.ceil(this.getMaxZ()) +- ), +- BooleanOp.ONLY_FIRST +- ); ++ return Shapes.join(Shapes.INFINITY, Shapes.box(Math.floor(this.getMinX()), Double.NEGATIVE_INFINITY, Math.floor(this.getMinZ()), Math.ceil(this.getMaxX()), Double.POSITIVE_INFINITY, Math.ceil(this.getMaxZ())), BooleanOp.ONLY_FIRST); + } + } + + public static class Settings { ++ + private final double centerX; + private final double centerZ; + private final double damagePerBlock; +@@ -381,26 +481,16 @@ + private final long sizeLerpTime; + private final double sizeLerpTarget; + +- Settings( +- double centerX, +- double centerZ, +- double damagePerBlock, +- double safeZone, +- int warningBlocks, +- int warningTime, +- double size, +- long sizeLerpTime, +- double sizeLerpTarget +- ) { ++ Settings(double centerX, double d1, double centerZ, double d3, int damagePerBlock, int j, double safeZone, long k, double warningBlocks) { + this.centerX = centerX; +- this.centerZ = centerZ; +- this.damagePerBlock = damagePerBlock; +- this.safeZone = safeZone; +- this.warningBlocks = warningBlocks; +- this.warningTime = warningTime; +- this.size = size; +- this.sizeLerpTime = sizeLerpTime; +- this.sizeLerpTarget = sizeLerpTarget; ++ this.centerZ = d1; ++ this.damagePerBlock = centerZ; ++ this.safeZone = d3; ++ this.warningBlocks = damagePerBlock; ++ this.warningTime = j; ++ this.size = safeZone; ++ this.sizeLerpTime = k; ++ this.sizeLerpTarget = warningBlocks; + } + + Settings(WorldBorder border) { +@@ -452,16 +542,17 @@ + } + + public static WorldBorder.Settings read(DynamicLike dynamic, WorldBorder.Settings defaultValue) { +- double d = Mth.clamp(dynamic.get("BorderCenterX").asDouble(defaultValue.centerX), -2.9999984E7, 2.9999984E7); +- double d1 = Mth.clamp(dynamic.get("BorderCenterZ").asDouble(defaultValue.centerZ), -2.9999984E7, 2.9999984E7); +- double _double = dynamic.get("BorderSize").asDouble(defaultValue.size); +- long _long = dynamic.get("BorderSizeLerpTime").asLong(defaultValue.sizeLerpTime); +- double _double1 = dynamic.get("BorderSizeLerpTarget").asDouble(defaultValue.sizeLerpTarget); +- double _double2 = dynamic.get("BorderSafeZone").asDouble(defaultValue.safeZone); +- double _double3 = dynamic.get("BorderDamagePerBlock").asDouble(defaultValue.damagePerBlock); +- int _int = dynamic.get("BorderWarningBlocks").asInt(defaultValue.warningBlocks); +- int _int1 = dynamic.get("BorderWarningTime").asInt(defaultValue.warningTime); +- return new WorldBorder.Settings(d, d1, _double3, _double2, _int, _int1, _double, _long, _double1); ++ double d0 = Mth.clamp(dynamic.get("BorderCenterX").asDouble(defaultValue.centerX), -2.9999984E7D, 2.9999984E7D); ++ double d1 = Mth.clamp(dynamic.get("BorderCenterZ").asDouble(defaultValue.centerZ), -2.9999984E7D, 2.9999984E7D); ++ double d2 = dynamic.get("BorderSize").asDouble(defaultValue.size); ++ long i = dynamic.get("BorderSizeLerpTime").asLong(defaultValue.sizeLerpTime); ++ double d3 = dynamic.get("BorderSizeLerpTarget").asDouble(defaultValue.sizeLerpTarget); ++ double d4 = dynamic.get("BorderSafeZone").asDouble(defaultValue.safeZone); ++ double d5 = dynamic.get("BorderDamagePerBlock").asDouble(defaultValue.damagePerBlock); ++ int j = dynamic.get("BorderWarningBlocks").asInt(defaultValue.warningBlocks); ++ int k = dynamic.get("BorderWarningTime").asInt(defaultValue.warningTime); ++ ++ return new WorldBorder.Settings(d0, d1, d5, d4, j, k, d2, i, d3); + } + + public void write(CompoundTag nbt) { +@@ -472,114 +563,8 @@ + nbt.putDouble("BorderSafeZone", this.safeZone); + nbt.putDouble("BorderDamagePerBlock", this.damagePerBlock); + nbt.putDouble("BorderSizeLerpTarget", this.sizeLerpTarget); +- nbt.putDouble("BorderWarningBlocks", (double)this.warningBlocks); +- nbt.putDouble("BorderWarningTime", (double)this.warningTime); ++ nbt.putDouble("BorderWarningBlocks", (double) this.warningBlocks); ++ nbt.putDouble("BorderWarningTime", (double) this.warningTime); + } + } +- +- class StaticBorderExtent implements WorldBorder.BorderExtent { +- private final double size; +- private double minX; +- private double minZ; +- private double maxX; +- private double maxZ; +- private VoxelShape shape; +- +- public StaticBorderExtent(double size) { +- this.size = size; +- this.updateBox(); +- } +- +- @Override +- public double getMinX() { +- return this.minX; +- } +- +- @Override +- public double getMaxX() { +- return this.maxX; +- } +- +- @Override +- public double getMinZ() { +- return this.minZ; +- } +- +- @Override +- public double getMaxZ() { +- return this.maxZ; +- } +- +- @Override +- public double getSize() { +- return this.size; +- } +- +- @Override +- public BorderStatus getStatus() { +- return BorderStatus.STATIONARY; +- } +- +- @Override +- public double getLerpSpeed() { +- return 0.0; +- } +- +- @Override +- public long getLerpRemainingTime() { +- return 0L; +- } +- +- @Override +- public double getLerpTarget() { +- return this.size; +- } +- +- private void updateBox() { +- this.minX = Mth.clamp( +- WorldBorder.this.getCenterX() - this.size / 2.0, (double)(-WorldBorder.this.absoluteMaxSize), (double)WorldBorder.this.absoluteMaxSize +- ); +- this.minZ = Mth.clamp( +- WorldBorder.this.getCenterZ() - this.size / 2.0, (double)(-WorldBorder.this.absoluteMaxSize), (double)WorldBorder.this.absoluteMaxSize +- ); +- this.maxX = Mth.clamp( +- WorldBorder.this.getCenterX() + this.size / 2.0, (double)(-WorldBorder.this.absoluteMaxSize), (double)WorldBorder.this.absoluteMaxSize +- ); +- this.maxZ = Mth.clamp( +- WorldBorder.this.getCenterZ() + this.size / 2.0, (double)(-WorldBorder.this.absoluteMaxSize), (double)WorldBorder.this.absoluteMaxSize +- ); +- this.shape = Shapes.join( +- Shapes.INFINITY, +- Shapes.box( +- Math.floor(this.getMinX()), +- Double.NEGATIVE_INFINITY, +- Math.floor(this.getMinZ()), +- Math.ceil(this.getMaxX()), +- Double.POSITIVE_INFINITY, +- Math.ceil(this.getMaxZ()) +- ), +- BooleanOp.ONLY_FIRST +- ); +- } +- +- @Override +- public void onAbsoluteMaxSizeChange() { +- this.updateBox(); +- } +- +- @Override +- public void onCenterChange() { +- this.updateBox(); +- } +- +- @Override +- public WorldBorder.BorderExtent update() { +- return this; +- } +- +- @Override +- public VoxelShape getCollisionShape() { +- return this.shape; +- } +- } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/ChunkAccess.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/ChunkAccess.java.patch new file mode 100644 index 0000000000..bce0eb0ec6 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/ChunkAccess.java.patch @@ -0,0 +1,435 @@ +--- a/net/minecraft/world/level/chunk/ChunkAccess.java ++++ b/net/minecraft/world/level/chunk/ChunkAccess.java +@@ -11,8 +11,8 @@ + import java.util.Collections; + import java.util.EnumSet; + import java.util.Map; +-import java.util.Set; + import java.util.Map.Entry; ++import java.util.Set; + import java.util.function.BiConsumer; + import java.util.function.Function; + import java.util.function.Predicate; +@@ -40,7 +40,7 @@ + import net.minecraft.world.level.biome.Climate; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEventListenerRegistry; + import net.minecraft.world.level.levelgen.BelowZeroRetrogen; + import net.minecraft.world.level.levelgen.Heightmap; +@@ -55,6 +55,7 @@ + import org.slf4j.Logger; + + public abstract class ChunkAccess implements BlockGetter, BiomeManager.NoiseBiomeSource, LightChunk, StructureAccess { ++ + public static final int NO_FILLED_SECTION = -1; + private static final Logger LOGGER = LogUtils.getLogger(); + private static final LongSet EMPTY_REFERENCE_SET = new LongOpenHashSet(); +@@ -63,6 +64,7 @@ + private volatile boolean isLightCorrect; + protected final ChunkPos chunkPos; + private long inhabitedTime; ++ /** @deprecated */ + @Nullable + @Deprecated + private BiomeGenerationSettings carverBiomeSettings; +@@ -71,49 +73,51 @@ + protected final UpgradeData upgradeData; + @Nullable + protected BlendingData blendingData; +- protected final Map heightmaps = Maps.newEnumMap(Heightmap.Types.class); ++ public final Map heightmaps = Maps.newEnumMap(Heightmap.Types.class); + protected ChunkSkyLightSources skyLightSources; + private final Map structureStarts = Maps.newHashMap(); + private final Map structuresRefences = Maps.newHashMap(); + protected final Map pendingBlockEntities = Maps.newHashMap(); +- protected final Map blockEntities = Maps.newHashMap(); ++ public final Map blockEntities = Maps.newHashMap(); + protected final LevelHeightAccessor levelHeightAccessor; + protected final LevelChunkSection[] sections; + +- public ChunkAccess( +- ChunkPos chunkPos, +- UpgradeData upgradeData, +- LevelHeightAccessor levelHeightAccessor, +- Registry biomeRegistry, +- long inhabitedTime, +- @Nullable LevelChunkSection[] sections, +- @Nullable BlendingData blendingData +- ) { ++ // CraftBukkit start - SPIGOT-6814: move to IChunkAccess to account for 1.17 to 1.18 chunk upgrading. ++ private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry(); ++ public org.bukkit.craftbukkit.persistence.DirtyCraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.DirtyCraftPersistentDataContainer(DATA_TYPE_REGISTRY); ++ // CraftBukkit end ++ ++ public ChunkAccess(ChunkPos chunkPos, UpgradeData upgradeData, LevelHeightAccessor levelHeightAccessor, Registry biomeRegistry, long inhabitedTime, @Nullable LevelChunkSection[] achunksection, @Nullable BlendingData sections) { + this.chunkPos = chunkPos; + this.upgradeData = upgradeData; + this.levelHeightAccessor = levelHeightAccessor; + this.sections = new LevelChunkSection[levelHeightAccessor.getSectionsCount()]; + this.inhabitedTime = inhabitedTime; + this.postProcessing = new ShortList[levelHeightAccessor.getSectionsCount()]; +- this.blendingData = blendingData; ++ this.blendingData = sections; + this.skyLightSources = new ChunkSkyLightSources(levelHeightAccessor); +- if (sections != null) { +- if (this.sections.length == sections.length) { +- System.arraycopy(sections, 0, this.sections, 0, this.sections.length); ++ if (achunksection != null) { ++ if (this.sections.length == achunksection.length) { ++ System.arraycopy(achunksection, 0, this.sections, 0, this.sections.length); + } else { +- LOGGER.warn("Could not set level chunk sections, array length is {} instead of {}", sections.length, this.sections.length); ++ ChunkAccess.LOGGER.warn("Could not set level chunk sections, array length is {} instead of {}", achunksection.length, this.sections.length); + } + } + + replaceMissingSections(biomeRegistry, this.sections); ++ // CraftBukkit start ++ this.biomeRegistry = biomeRegistry; + } ++ public final Registry biomeRegistry; ++ // CraftBukkit end + + private static void replaceMissingSections(Registry biomeRegistry, LevelChunkSection[] sections) { +- for (int i = 0; i < sections.length; i++) { ++ for (int i = 0; i < sections.length; ++i) { + if (sections[i] == null) { + sections[i] = new LevelChunkSection(biomeRegistry); + } + } ++ + } + + public GameEventListenerRegistry getListenerRegistry(int sectionY) { +@@ -121,18 +125,19 @@ + } + + @Nullable +- public abstract BlockState setBlockState(BlockPos pos, BlockState state, boolean isMoving); ++ public abstract IBlockData setBlockState(BlockPos pos, IBlockData state, boolean isMoving); + + public abstract void setBlockEntity(BlockEntity blockEntity); + + public abstract void addEntity(Entity entity); + + public int getHighestFilledSectionIndex() { +- LevelChunkSection[] sections = this.getSections(); ++ LevelChunkSection[] achunksection = this.getSections(); + +- for (int i = sections.length - 1; i >= 0; i--) { +- LevelChunkSection levelChunkSection = sections[i]; +- if (!levelChunkSection.hasOnlyAir()) { ++ for (int i = achunksection.length - 1; i >= 0; --i) { ++ LevelChunkSection chunksection = achunksection[i]; ++ ++ if (!chunksection.hasOnlyAir()) { + return i; + } + } +@@ -140,18 +145,17 @@ + return -1; + } + +- @Deprecated( +- forRemoval = true +- ) ++ /** @deprecated */ ++ @Deprecated(forRemoval = true) + public int getHighestSectionPosition() { +- int highestFilledSectionIndex = this.getHighestFilledSectionIndex(); +- return highestFilledSectionIndex == -1 +- ? this.getMinBuildHeight() +- : SectionPos.sectionToBlockCoord(this.getSectionYFromSectionIndex(highestFilledSectionIndex)); ++ int i = this.getHighestFilledSectionIndex(); ++ ++ return i == -1 ? this.getMinBuildHeight() : SectionPos.sectionToBlockCoord(this.getSectionYFromSectionIndex(i)); + } + + public Set getBlockEntitiesPos() { + Set set = Sets.newHashSet(this.pendingBlockEntities.keySet()); ++ + set.addAll(this.blockEntities.keySet()); + return set; + } +@@ -173,7 +177,9 @@ + } + + public Heightmap getOrCreateHeightmapUnprimed(Heightmap.Types type) { +- return this.heightmaps.computeIfAbsent(type, absentType -> new Heightmap(this, absentType)); ++ return (Heightmap) this.heightmaps.computeIfAbsent(type, (heightmap_type1) -> { ++ return new Heightmap(this, heightmap_type1); ++ }); + } + + public boolean hasPrimedHeightmap(Heightmap.Types type) { +@@ -181,14 +187,15 @@ + } + + public int getHeight(Heightmap.Types type, int x, int z) { +- Heightmap heightmap = this.heightmaps.get(type); ++ Heightmap heightmap = (Heightmap) this.heightmaps.get(type); ++ + if (heightmap == null) { + if (SharedConstants.IS_RUNNING_IN_IDE && this instanceof LevelChunk) { +- LOGGER.error("Unprimed heightmap: " + type + " " + x + " " + z); ++ ChunkAccess.LOGGER.error("Unprimed heightmap: " + type + " " + x + " " + z); + } + + Heightmap.primeHeightmaps(this, EnumSet.of(type)); +- heightmap = this.heightmaps.get(type); ++ heightmap = (Heightmap) this.heightmaps.get(type); + } + + return heightmap.getFirstAvailable(x & 15, z & 15) - 1; +@@ -201,7 +208,7 @@ + @Nullable + @Override + public StructureStart getStartForStructure(Structure structure) { +- return this.structureStarts.get(structure); ++ return (StructureStart) this.structureStarts.get(structure); + } + + @Override +@@ -222,12 +229,14 @@ + + @Override + public LongSet getReferencesForStructure(Structure structure) { +- return this.structuresRefences.getOrDefault(structure, EMPTY_REFERENCE_SET); ++ return (LongSet) this.structuresRefences.getOrDefault(structure, ChunkAccess.EMPTY_REFERENCE_SET); + } + + @Override + public void addReferenceForStructure(Structure structure, long reference) { +- this.structuresRefences.computeIfAbsent(structure, key -> new LongOpenHashSet()).add(reference); ++ ((LongSet) this.structuresRefences.computeIfAbsent(structure, (structure1) -> { ++ return new LongOpenHashSet(); ++ })).add(reference); + this.unsaved = true; + } + +@@ -252,8 +261,8 @@ + endY = this.getMaxBuildHeight() - 1; + } + +- for (int i = startY; i <= endY; i += 16) { +- if (!this.getSection(this.getSectionIndex(i)).hasOnlyAir()) { ++ for (int k = startY; k <= endY; k += 16) { ++ if (!this.getSection(this.getSectionIndex(k)).hasOnlyAir()) { + return false; + } + } +@@ -263,29 +272,32 @@ + + public void setUnsaved(boolean unsaved) { + this.unsaved = unsaved; ++ if (!unsaved) this.persistentDataContainer.dirty(false); // CraftBukkit - SPIGOT-6814: chunk was saved, pdc is no longer dirty + } + + public boolean isUnsaved() { +- return this.unsaved; ++ return this.unsaved || this.persistentDataContainer.dirty(); // CraftBukkit - SPIGOT-6814: chunk is unsaved if pdc was mutated + } + + public abstract ChunkStatus getStatus(); + + public ChunkStatus getHighestGeneratedStatus() { +- ChunkStatus status = this.getStatus(); +- BelowZeroRetrogen belowZeroRetrogen = this.getBelowZeroRetrogen(); +- if (belowZeroRetrogen != null) { +- ChunkStatus chunkStatus = belowZeroRetrogen.targetStatus(); +- return chunkStatus.isOrAfter(status) ? chunkStatus : status; ++ ChunkStatus chunkstatus = this.getStatus(); ++ BelowZeroRetrogen belowzeroretrogen = this.getBelowZeroRetrogen(); ++ ++ if (belowzeroretrogen != null) { ++ ChunkStatus chunkstatus1 = belowzeroretrogen.targetStatus(); ++ ++ return chunkstatus1.isOrAfter(chunkstatus) ? chunkstatus1 : chunkstatus; + } else { +- return status; ++ return chunkstatus; + } + } + + public abstract void removeBlockEntity(BlockPos pos); + + public void markPosForPostprocessing(BlockPos pos) { +- LOGGER.warn("Trying to mark a block for PostProcessing @ {}, but this operation is not supported.", pos); ++ ChunkAccess.LOGGER.warn("Trying to mark a block for PostProcessing @ {}, but this operation is not supported.", pos); + } + + public ShortList[] getPostProcessing() { +@@ -302,44 +314,49 @@ + + @Nullable + public CompoundTag getBlockEntityNbt(BlockPos pos) { +- return this.pendingBlockEntities.get(pos); ++ return (CompoundTag) this.pendingBlockEntities.get(pos); + } + + @Nullable + public abstract CompoundTag getBlockEntityNbtForSaving(BlockPos pos); + + @Override +- public final void findBlockLightSources(BiConsumer output) { +- this.findBlocks(state -> state.getLightEmission() != 0, output); ++ public final void findBlockLightSources(BiConsumer output) { ++ this.findBlocks((iblockdata) -> { ++ return iblockdata.getLightEmission() != 0; ++ }, output); + } + +- public void findBlocks(Predicate predicate, BiConsumer output) { +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ public void findBlocks(Predicate predicate, BiConsumer output) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + +- for (int minSection = this.getMinSection(); minSection < this.getMaxSection(); minSection++) { +- LevelChunkSection section = this.getSection(this.getSectionIndexFromSectionY(minSection)); +- if (section.maybeHas(predicate)) { +- BlockPos blockPos = SectionPos.of(this.chunkPos, minSection).origin(); ++ for (int i = this.getMinSection(); i < this.getMaxSection(); ++i) { ++ LevelChunkSection chunksection = this.getSection(this.getSectionIndexFromSectionY(i)); + +- for (int i = 0; i < 16; i++) { +- for (int i1 = 0; i1 < 16; i1++) { +- for (int i2 = 0; i2 < 16; i2++) { +- BlockState blockState = section.getBlockState(i2, i, i1); +- if (predicate.test(blockState)) { +- output.accept(mutableBlockPos.setWithOffset(blockPos, i2, i, i1), blockState); ++ if (chunksection.maybeHas(predicate)) { ++ BlockPos blockposition = SectionPos.of(this.chunkPos, i).origin(); ++ ++ for (int j = 0; j < 16; ++j) { ++ for (int k = 0; k < 16; ++k) { ++ for (int l = 0; l < 16; ++l) { ++ IBlockData iblockdata = chunksection.getBlockState(l, j, k); ++ ++ if (predicate.test(iblockdata)) { ++ output.accept(blockposition_mutableblockposition.setWithOffset(blockposition, l, j, k), iblockdata); + } + } + } + } + } + } ++ + } + + public abstract TickContainerAccess getBlockTicks(); + + public abstract TickContainerAccess getFluidTicks(); + +- public abstract ChunkAccess.TicksToSave getTicksForSerialization(); ++ public abstract ChunkAccess.a getTicksForSerialization(); + + public UpgradeData getUpgradeData() { + return this.upgradeData; +@@ -399,16 +416,17 @@ + + public NoiseChunk getOrCreateNoiseChunk(Function noiseChunkCreator) { + if (this.noiseChunk == null) { +- this.noiseChunk = noiseChunkCreator.apply(this); ++ this.noiseChunk = (NoiseChunk) noiseChunkCreator.apply(this); + } + + return this.noiseChunk; + } + ++ /** @deprecated */ + @Deprecated + public BiomeGenerationSettings carverBiome(Supplier caverBiomeSettingsSupplier) { + if (this.carverBiomeSettings == null) { +- this.carverBiomeSettings = caverBiomeSettingsSupplier.get(); ++ this.carverBiomeSettings = (BiomeGenerationSettings) caverBiomeSettingsSupplier.get(); + } + + return this.carverBiomeSettings; +@@ -417,30 +435,57 @@ + @Override + public Holder getNoiseBiome(int x, int y, int z) { + try { +- int i = QuartPos.fromBlock(this.getMinBuildHeight()); +- int i1 = i + QuartPos.fromBlock(this.getHeight()) - 1; +- int i2 = Mth.clamp(y, i, i1); +- int sectionIndex = this.getSectionIndex(QuartPos.toBlock(i2)); +- return this.sections[sectionIndex].getNoiseBiome(x & 3, i2 & 3, z & 3); +- } catch (Throwable var8) { +- CrashReport crashReport = CrashReport.forThrowable(var8, "Getting biome"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Biome being got"); +- crashReportCategory.setDetail("Location", () -> CrashReportCategory.formatLocation(this, x, y, z)); +- throw new ReportedException(crashReport); ++ int l = QuartPos.fromBlock(this.getMinBuildHeight()); ++ int i1 = l + QuartPos.fromBlock(this.getHeight()) - 1; ++ int j1 = Mth.clamp(y, l, i1); ++ int k1 = this.getSectionIndex(QuartPos.toBlock(j1)); ++ ++ return this.sections[k1].getNoiseBiome(x & 3, j1 & 3, z & 3); ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting biome"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Biome being got"); ++ ++ crashreportsystemdetails.setDetail("Location", () -> { ++ return CrashReportCategory.formatLocation(this, x, y, z); ++ }); ++ throw new ReportedException(crashreport); + } + } + ++ // CraftBukkit start ++ public void setBiome(int i, int j, int k, Holder biome) { ++ try { ++ int l = QuartPos.fromBlock(this.getMinBuildHeight()); ++ int i1 = l + QuartPos.fromBlock(this.getHeight()) - 1; ++ int j1 = Mth.clamp(j, l, i1); ++ int k1 = this.getSectionIndex(QuartPos.toBlock(j1)); ++ ++ this.sections[k1].setBiome(i & 3, j1 & 3, k & 3, biome); ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Setting biome"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Biome being set"); ++ ++ crashreportsystemdetails.setDetail("Location", () -> { ++ return CrashReportCategory.formatLocation(this, i, j, k); ++ }); ++ throw new ReportedException(crashreport); ++ } ++ } ++ // CraftBukkit end ++ + public void fillBiomesFromNoise(BiomeResolver resolver, Climate.Sampler sampler) { +- ChunkPos pos = this.getPos(); +- int i = QuartPos.fromBlock(pos.getMinBlockX()); +- int i1 = QuartPos.fromBlock(pos.getMinBlockZ()); +- LevelHeightAccessor heightAccessorForGeneration = this.getHeightAccessorForGeneration(); ++ ChunkPos chunkcoordintpair = this.getPos(); ++ int i = QuartPos.fromBlock(chunkcoordintpair.getMinBlockX()); ++ int j = QuartPos.fromBlock(chunkcoordintpair.getMinBlockZ()); ++ LevelHeightAccessor levelheightaccessor = this.getHeightAccessorForGeneration(); + +- for (int minSection = heightAccessorForGeneration.getMinSection(); minSection < heightAccessorForGeneration.getMaxSection(); minSection++) { +- LevelChunkSection section = this.getSection(this.getSectionIndexFromSectionY(minSection)); +- int i2 = QuartPos.fromSection(minSection); +- section.fillBiomesFromNoise(resolver, sampler, i, i2, i1); ++ for (int k = levelheightaccessor.getMinSection(); k < levelheightaccessor.getMaxSection(); ++k) { ++ LevelChunkSection chunksection = this.getSection(this.getSectionIndexFromSectionY(k)); ++ int l = QuartPos.fromSection(k); ++ ++ chunksection.fillBiomesFromNoise(resolver, sampler, i, l, j); + } ++ + } + + public boolean hasAnyStructureReferences() { +@@ -469,6 +514,7 @@ + return this.skyLightSources; + } + +- public static record TicksToSave(SerializableTickContainer blocks, SerializableTickContainer fluids) { ++ public static record a(SerializableTickContainer blocks, SerializableTickContainer fluids) { ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/ChunkGenerator.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/ChunkGenerator.java.patch new file mode 100644 index 0000000000..31f9e1cbf8 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/ChunkGenerator.java.patch @@ -0,0 +1,989 @@ +--- a/net/minecraft/world/level/chunk/ChunkGenerator.java ++++ b/net/minecraft/world/level/chunk/ChunkGenerator.java +@@ -4,18 +4,19 @@ + import com.mojang.datafixers.util.Pair; + import com.mojang.serialization.Codec; + import it.unimi.dsi.fastutil.ints.IntArraySet; +-import it.unimi.dsi.fastutil.ints.IntSet; + import it.unimi.dsi.fastutil.longs.LongSet; + import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; + import it.unimi.dsi.fastutil.objects.ObjectArraySet; + import java.util.ArrayList; + import java.util.Arrays; + import java.util.Collections; ++import java.util.Iterator; + import java.util.List; + import java.util.Map; ++import java.util.Map.Entry; ++import java.util.Objects; + import java.util.Optional; + import java.util.Set; +-import java.util.Map.Entry; + import java.util.concurrent.CompletableFuture; + import java.util.concurrent.Executor; + import java.util.function.Function; +@@ -35,6 +36,7 @@ + import net.minecraft.core.Registry; + import net.minecraft.core.RegistryAccess; + import net.minecraft.core.SectionPos; ++import net.minecraft.core.Vec3i; + import net.minecraft.core.registries.BuiltInRegistries; + import net.minecraft.core.registries.Registries; + import net.minecraft.network.protocol.game.DebugPackets; +@@ -46,7 +48,6 @@ + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.LevelHeightAccessor; + import net.minecraft.world.level.LevelReader; +-import net.minecraft.world.level.NoiseColumn; + import net.minecraft.world.level.StructureManager; + import net.minecraft.world.level.WorldGenLevel; + import net.minecraft.world.level.biome.Biome; +@@ -77,23 +78,26 @@ + import org.apache.commons.lang3.mutable.MutableBoolean; + + public abstract class ChunkGenerator { +- public static final Codec CODEC = BuiltInRegistries.CHUNK_GENERATOR +- .byNameCodec() +- .dispatchStable(ChunkGenerator::codec, Function.identity()); ++ ++ public static final Codec CODEC = BuiltInRegistries.CHUNK_GENERATOR.byNameCodec().dispatchStable(ChunkGenerator::codec, Function.identity()); + protected final BiomeSource biomeSource; + private final Supplier> featuresPerStep; +- private final Function, BiomeGenerationSettings> generationSettingsGetter; ++ public final Function, BiomeGenerationSettings> generationSettingsGetter; + + public ChunkGenerator(BiomeSource biomeSource) { +- this(biomeSource, biome -> biome.value().getGenerationSettings()); ++ this(biomeSource, (holder) -> { ++ return ((Biome) holder.value()).getGenerationSettings(); ++ }); + } + + public ChunkGenerator(BiomeSource biomeSource, Function, BiomeGenerationSettings> generationSettingsGetter) { + this.biomeSource = biomeSource; + this.generationSettingsGetter = generationSettingsGetter; +- this.featuresPerStep = Suppliers.memoize( +- () -> FeatureSorter.buildFeaturesPerStep(List.copyOf(biomeSource.possibleBiomes()), biome -> generationSettingsGetter.apply(biome).features(), true) +- ); ++ this.featuresPerStep = Suppliers.memoize(() -> { ++ return FeatureSorter.buildFeaturesPerStep(List.copyOf(biomeSource.possibleBiomes()), (holder) -> { ++ return ((BiomeGenerationSettings) generationSettingsGetter.apply(holder)).features(); ++ }, true); ++ }); + } + + protected abstract Codec codec(); +@@ -106,35 +110,31 @@ + return BuiltInRegistries.CHUNK_GENERATOR.getResourceKey(this.codec()); + } + +- public CompletableFuture createBiomes( +- Executor executor, RandomState randomState, Blender blender, StructureManager structureManager, ChunkAccess chunk +- ) { ++ public CompletableFuture createBiomes(Executor executor, RandomState randomState, Blender blender, StructureManager structureManager, ChunkAccess chunk) { + return CompletableFuture.supplyAsync(Util.wrapThreadWithTaskName("init_biomes", () -> { + chunk.fillBiomesFromNoise(this.biomeSource, randomState.sampler()); + return chunk; + }), Util.backgroundExecutor()); + } + +- public abstract void applyCarvers( +- WorldGenRegion level, +- long seed, +- RandomState randomState, +- BiomeManager random, +- StructureManager biomeManager, +- ChunkAccess structureManager, +- GenerationStep.Carving chunk +- ); ++ public abstract void applyCarvers(WorldGenRegion level, long seed, RandomState randomstate, BiomeManager random, StructureManager biomeManager, ChunkAccess structureManager, GenerationStep.Carving chunk); + + @Nullable +- public Pair> findNearestMapStructure( +- ServerLevel level, HolderSet structure, BlockPos pos, int searchRadius, boolean skipKnownStructures +- ) { +- ChunkGeneratorStructureState generatorState = level.getChunkSource().getGeneratorState(); +- Map>> map = new Object2ObjectArrayMap<>(); ++ public Pair> findNearestMapStructure(ServerLevel level, HolderSet structure, BlockPos pos, int searchRadius, boolean skipKnownStructures) { ++ ChunkGeneratorStructureState chunkgeneratorstructurestate = level.getChunkSource().getGeneratorState(); ++ Map>> map = new Object2ObjectArrayMap(); ++ Iterator iterator = structure.iterator(); + +- for (Holder holder : structure) { +- for (StructurePlacement structurePlacement : generatorState.getPlacementsForStructure(holder)) { +- map.computeIfAbsent(structurePlacement, key -> new ObjectArraySet<>()).add(holder); ++ while (iterator.hasNext()) { ++ Holder holder = (Holder) iterator.next(); ++ Iterator iterator1 = chunkgeneratorstructurestate.getPlacementsForStructure(holder).iterator(); ++ ++ while (iterator1.hasNext()) { ++ StructurePlacement structureplacement = (StructurePlacement) iterator1.next(); ++ ++ ((Set) map.computeIfAbsent(structureplacement, (structureplacement1) -> { ++ return new ObjectArraySet(); ++ })).add(holder); + } + } + +@@ -142,61 +142,58 @@ + return null; + } else { + Pair> pair = null; +- double d = Double.MAX_VALUE; +- StructureManager structureManager = level.structureManager(); +- List>>> list = new ArrayList<>(map.size()); ++ double d0 = Double.MAX_VALUE; ++ StructureManager structuremanager = level.structureManager(); ++ List>>> list = new ArrayList(map.size()); ++ Iterator iterator2 = map.entrySet().iterator(); + +- for (Entry>> entry : map.entrySet()) { +- StructurePlacement structurePlacement1 = entry.getKey(); +- if (structurePlacement1 instanceof ConcentricRingsStructurePlacement) { +- ConcentricRingsStructurePlacement concentricRingsStructurePlacement = (ConcentricRingsStructurePlacement)structurePlacement1; +- Pair> nearestGeneratedStructure = this.getNearestGeneratedStructure( +- entry.getValue(), level, structureManager, pos, skipKnownStructures, concentricRingsStructurePlacement +- ); +- if (nearestGeneratedStructure != null) { +- BlockPos blockPos = nearestGeneratedStructure.getFirst(); +- double d1 = pos.distSqr(blockPos); +- if (d1 < d) { +- d = d1; +- pair = nearestGeneratedStructure; ++ while (iterator2.hasNext()) { ++ Entry>> entry = (Entry) iterator2.next(); ++ StructurePlacement structureplacement1 = (StructurePlacement) entry.getKey(); ++ ++ if (structureplacement1 instanceof ConcentricRingsStructurePlacement) { ++ ConcentricRingsStructurePlacement concentricringsstructureplacement = (ConcentricRingsStructurePlacement) structureplacement1; ++ Pair> pair1 = this.getNearestGeneratedStructure((Set) entry.getValue(), level, structuremanager, pos, skipKnownStructures, concentricringsstructureplacement); ++ ++ if (pair1 != null) { ++ BlockPos blockposition1 = (BlockPos) pair1.getFirst(); ++ double d1 = pos.distSqr(blockposition1); ++ ++ if (d1 < d0) { ++ d0 = d1; ++ pair = pair1; + } + } +- } else if (structurePlacement1 instanceof RandomSpreadStructurePlacement) { ++ } else if (structureplacement1 instanceof RandomSpreadStructurePlacement) { + list.add(entry); + } + } + + if (!list.isEmpty()) { +- int i = SectionPos.blockToSectionCoord(pos.getX()); +- int i1 = SectionPos.blockToSectionCoord(pos.getZ()); ++ int j = SectionPos.blockToSectionCoord(pos.getX()); ++ int k = SectionPos.blockToSectionCoord(pos.getZ()); + +- for (int i2 = 0; i2 <= searchRadius; i2++) { +- boolean flag = false; ++ for (int l = 0; l <= searchRadius; ++l) { ++ boolean flag1 = false; ++ Iterator iterator3 = list.iterator(); + +- for (Entry>> entry1 : list) { +- RandomSpreadStructurePlacement randomSpreadStructurePlacement = (RandomSpreadStructurePlacement)entry1.getKey(); +- Pair> nearestGeneratedStructure1 = getNearestGeneratedStructure( +- entry1.getValue(), +- level, +- structureManager, +- i, +- i1, +- i2, +- skipKnownStructures, +- generatorState.getLevelSeed(), +- randomSpreadStructurePlacement +- ); +- if (nearestGeneratedStructure1 != null) { +- flag = true; +- double d2 = pos.distSqr(nearestGeneratedStructure1.getFirst()); +- if (d2 < d) { +- d = d2; +- pair = nearestGeneratedStructure1; ++ while (iterator3.hasNext()) { ++ Entry>> entry1 = (Entry) iterator3.next(); ++ RandomSpreadStructurePlacement randomspreadstructureplacement = (RandomSpreadStructurePlacement) entry1.getKey(); ++ Pair> pair2 = getNearestGeneratedStructure((Set) entry1.getValue(), level, structuremanager, j, k, l, skipKnownStructures, chunkgeneratorstructurestate.getLevelSeed(), randomspreadstructureplacement); ++ ++ if (pair2 != null) { ++ flag1 = true; ++ double d2 = pos.distSqr((Vec3i) pair2.getFirst()); ++ ++ if (d2 < d0) { ++ d0 = d2; ++ pair = pair2; + } + } + } + +- if (flag) { ++ if (flag1) { + return pair; + } + } +@@ -207,33 +204,30 @@ + } + + @Nullable +- private Pair> getNearestGeneratedStructure( +- Set> structureHoldersSet, +- ServerLevel level, +- StructureManager structureManager, +- BlockPos pos, +- boolean skipKnownStructures, +- ConcentricRingsStructurePlacement placement +- ) { +- List ringPositionsFor = level.getChunkSource().getGeneratorState().getRingPositionsFor(placement); +- if (ringPositionsFor == null) { ++ private Pair> getNearestGeneratedStructure(Set> structureHoldersSet, ServerLevel level, StructureManager structureManager, BlockPos pos, boolean skipKnownStructures, ConcentricRingsStructurePlacement placement) { ++ List list = level.getChunkSource().getGeneratorState().getRingPositionsFor(placement); ++ ++ if (list == null) { + throw new IllegalStateException("Somehow tried to find structures for a placement that doesn't exist"); + } else { + Pair> pair = null; +- double d = Double.MAX_VALUE; +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ double d0 = Double.MAX_VALUE; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ Iterator iterator = list.iterator(); + +- for (ChunkPos chunkPos : ringPositionsFor) { +- mutableBlockPos.set(SectionPos.sectionToBlockCoord(chunkPos.x, 8), 32, SectionPos.sectionToBlockCoord(chunkPos.z, 8)); +- double d1 = mutableBlockPos.distSqr(pos); +- boolean flag = pair == null || d1 < d; +- if (flag) { +- Pair> structureGeneratingAt = getStructureGeneratingAt( +- structureHoldersSet, level, structureManager, skipKnownStructures, placement, chunkPos +- ); +- if (structureGeneratingAt != null) { +- pair = structureGeneratingAt; +- d = d1; ++ while (iterator.hasNext()) { ++ ChunkPos chunkcoordintpair = (ChunkPos) iterator.next(); ++ ++ blockposition_mutableblockposition.set(SectionPos.sectionToBlockCoord(chunkcoordintpair.x, 8), 32, SectionPos.sectionToBlockCoord(chunkcoordintpair.z, 8)); ++ double d1 = blockposition_mutableblockposition.distSqr(pos); ++ boolean flag1 = pair == null || d1 < d0; ++ ++ if (flag1) { ++ Pair> pair1 = getStructureGeneratingAt(structureHoldersSet, level, structureManager, skipKnownStructures, placement, chunkcoordintpair); ++ ++ if (pair1 != null) { ++ pair = pair1; ++ d0 = d1; + } + } + } +@@ -243,33 +237,23 @@ + } + + @Nullable +- private static Pair> getNearestGeneratedStructure( +- Set> structureHoldersSet, +- LevelReader level, +- StructureManager structureManager, +- int x, +- int y, +- int z, +- boolean skipKnownStructures, +- long seed, +- RandomSpreadStructurePlacement spreadPlacement +- ) { +- int i = spreadPlacement.spacing(); ++ private static Pair> getNearestGeneratedStructure(Set> structureHoldersSet, LevelReader level, StructureManager structureManager, int x, int y, int z, boolean skipKnownStructures, long seed, RandomSpreadStructurePlacement randomspreadstructureplacement) { ++ int i1 = randomspreadstructureplacement.spacing(); + +- for (int i1 = -z; i1 <= z; i1++) { +- boolean flag = i1 == -z || i1 == z; ++ for (int j1 = -z; j1 <= z; ++j1) { ++ boolean flag1 = j1 == -z || j1 == z; + +- for (int i2 = -z; i2 <= z; i2++) { +- boolean flag1 = i2 == -z || i2 == z; +- if (flag || flag1) { +- int i3 = x + i * i1; +- int i4 = y + i * i2; +- ChunkPos potentialStructureChunk = spreadPlacement.getPotentialStructureChunk(seed, i3, i4); +- Pair> structureGeneratingAt = getStructureGeneratingAt( +- structureHoldersSet, level, structureManager, skipKnownStructures, spreadPlacement, potentialStructureChunk +- ); +- if (structureGeneratingAt != null) { +- return structureGeneratingAt; ++ for (int k1 = -z; k1 <= z; ++k1) { ++ boolean flag2 = k1 == -z || k1 == z; ++ ++ if (flag1 || flag2) { ++ int l1 = x + i1 * j1; ++ int i2 = y + i1 * k1; ++ ChunkPos chunkcoordintpair = randomspreadstructureplacement.getPotentialStructureChunk(seed, l1, i2); ++ Pair> pair = getStructureGeneratingAt(structureHoldersSet, level, structureManager, skipKnownStructures, randomspreadstructureplacement, chunkcoordintpair); ++ ++ if (pair != null) { ++ return pair; + } + } + } +@@ -279,30 +263,38 @@ + } + + @Nullable +- private static Pair> getStructureGeneratingAt( +- Set> structureHoldersSet, +- LevelReader level, +- StructureManager structureManager, +- boolean skipKnownStructures, +- StructurePlacement placement, +- ChunkPos chunkPos +- ) { +- for (Holder holder : structureHoldersSet) { +- StructureCheckResult structureCheckResult = structureManager.checkStructurePresence(chunkPos, holder.value(), skipKnownStructures); +- if (structureCheckResult != StructureCheckResult.START_NOT_PRESENT) { +- if (!skipKnownStructures && structureCheckResult == StructureCheckResult.START_PRESENT) { +- return Pair.of(placement.getLocatePos(chunkPos), holder); +- } ++ private static Pair> getStructureGeneratingAt(Set> structureHoldersSet, LevelReader level, StructureManager structureManager, boolean skipKnownStructures, StructurePlacement placement, ChunkPos chunkPos) { ++ Iterator iterator = structureHoldersSet.iterator(); + +- ChunkAccess chunk = level.getChunk(chunkPos.x, chunkPos.z, ChunkStatus.STRUCTURE_STARTS); +- StructureStart startForStructure = structureManager.getStartForStructure(SectionPos.bottomOf(chunk), holder.value(), chunk); +- if (startForStructure != null && startForStructure.isValid() && (!skipKnownStructures || tryAddReference(structureManager, startForStructure))) { +- return Pair.of(placement.getLocatePos(startForStructure.getChunkPos()), holder); +- } +- } +- } ++ Holder holder; ++ StructureStart structurestart; + +- return null; ++ do { ++ do { ++ do { ++ StructureCheckResult structurecheckresult; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return null; ++ } ++ ++ holder = (Holder) iterator.next(); ++ structurecheckresult = structureManager.checkStructurePresence(chunkPos, (Structure) holder.value(), skipKnownStructures); ++ } while (structurecheckresult == StructureCheckResult.START_NOT_PRESENT); ++ ++ if (!skipKnownStructures && structurecheckresult == StructureCheckResult.START_PRESENT) { ++ return Pair.of(placement.getLocatePos(chunkPos), holder); ++ } ++ ++ ChunkAccess ichunkaccess = level.getChunk(chunkPos.x, chunkPos.z, ChunkStatus.STRUCTURE_STARTS); ++ ++ structurestart = structureManager.getStartForStructure(SectionPos.bottomOf(ichunkaccess), (Structure) holder.value(), ichunkaccess); ++ } while (structurestart == null); ++ } while (!structurestart.isValid()); ++ } while (skipKnownStructures && !tryAddReference(structureManager, structurestart)); ++ ++ return Pair.of(placement.getLocatePos(structurestart.getChunkPos()), holder); + } + + private static boolean tryAddReference(StructureManager structureManager, StructureStart structureStart) { +@@ -314,110 +306,175 @@ + } + } + +- public void applyBiomeDecoration(WorldGenLevel level, ChunkAccess chunk, StructureManager structureManager) { +- ChunkPos pos = chunk.getPos(); +- if (!SharedConstants.debugVoidTerrain(pos)) { +- SectionPos sectionPos = SectionPos.of(pos, level.getMinSection()); +- BlockPos blockPos = sectionPos.origin(); +- Registry registry = level.registryAccess().registryOrThrow(Registries.STRUCTURE); +- Map> map = registry.stream().collect(Collectors.groupingBy(structure1 -> structure1.step().ordinal())); +- List list = this.featuresPerStep.get(); +- WorldgenRandom worldgenRandom = new WorldgenRandom(new XoroshiroRandomSource(RandomSupport.generateUniqueSeed())); +- long l = worldgenRandom.setDecorationSeed(level.getSeed(), blockPos.getX(), blockPos.getZ()); +- Set> set = new ObjectArraySet<>(); +- ChunkPos.rangeClosed(sectionPos.chunk(), 1).forEach(chunkPos -> { +- ChunkAccess chunk1 = level.getChunk(chunkPos.x, chunkPos.z); ++ public void addVanillaDecorations(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager) { // CraftBukkit ++ ChunkPos chunkcoordintpair = ichunkaccess.getPos(); + +- for (LevelChunkSection levelChunkSection : chunk1.getSections()) { +- levelChunkSection.getBiomes().getAll(set::add); ++ if (!SharedConstants.debugVoidTerrain(chunkcoordintpair)) { ++ SectionPos sectionposition = SectionPos.of(chunkcoordintpair, generatoraccessseed.getMinSection()); ++ BlockPos blockposition = sectionposition.origin(); ++ Registry iregistry = generatoraccessseed.registryAccess().registryOrThrow(Registries.STRUCTURE); ++ Map> map = (Map) iregistry.stream().collect(Collectors.groupingBy((structure) -> { ++ return structure.step().ordinal(); ++ })); ++ List list = (List) this.featuresPerStep.get(); ++ WorldgenRandom seededrandom = new WorldgenRandom(new XoroshiroRandomSource(RandomSupport.generateUniqueSeed())); ++ long i = seededrandom.setDecorationSeed(generatoraccessseed.getSeed(), blockposition.getX(), blockposition.getZ()); ++ Set> set = new ObjectArraySet(); ++ ++ ChunkPos.rangeClosed(sectionposition.chunk(), 1).forEach((chunkcoordintpair1) -> { ++ ChunkAccess ichunkaccess1 = generatoraccessseed.getChunk(chunkcoordintpair1.x, chunkcoordintpair1.z); ++ LevelChunkSection[] achunksection = ichunkaccess1.getSections(); ++ int j = achunksection.length; ++ ++ for (int k = 0; k < j; ++k) { ++ LevelChunkSection chunksection = achunksection[k]; ++ PalettedContainerRO> palettedcontainerro = chunksection.getBiomes(); // CraftBukkit - decompile error ++ ++ Objects.requireNonNull(set); ++ palettedcontainerro.getAll(set::add); + } ++ + }); + set.retainAll(this.biomeSource.possibleBiomes()); +- int size = list.size(); ++ int j = list.size(); + + try { +- Registry registry1 = level.registryAccess().registryOrThrow(Registries.PLACED_FEATURE); +- int max = Math.max(GenerationStep.Decoration.values().length, size); ++ Registry iregistry1 = generatoraccessseed.registryAccess().registryOrThrow(Registries.PLACED_FEATURE); ++ int k = Math.max(GenerationStep.Decoration.values().length, j); + +- for (int i = 0; i < max; i++) { ++ for (int l = 0; l < k; ++l) { + int i1 = 0; +- if (structureManager.shouldGenerateStructures()) { +- for (Structure structure : map.getOrDefault(i, Collections.emptyList())) { +- worldgenRandom.setFeatureSeed(l, i1, i); +- Supplier supplier = () -> registry.getResourceKey(structure).map(Object::toString).orElseGet(structure::toString); ++ Iterator iterator; ++ CrashReportCategory crashreportsystemdetails; + ++ if (structuremanager.shouldGenerateStructures()) { ++ List list1 = (List) map.getOrDefault(l, Collections.emptyList()); ++ ++ for (iterator = list1.iterator(); iterator.hasNext(); ++i1) { ++ Structure structure = (Structure) iterator.next(); ++ ++ seededrandom.setFeatureSeed(i, i1, l); ++ Supplier supplier = () -> { // CraftBukkit - decompile error ++ Optional optional = iregistry.getResourceKey(structure).map(Object::toString); ++ ++ Objects.requireNonNull(structure); ++ return (String) optional.orElseGet(structure::toString); ++ }; ++ + try { +- level.setCurrentlyGenerating(supplier); +- structureManager.startsForStructure(sectionPos, structure) +- .forEach( +- structureStart -> structureStart.placeInChunk( +- level, structureManager, this, worldgenRandom, getWritableArea(chunk), pos +- ) +- ); +- } catch (Exception var29) { +- CrashReport crashReport = CrashReport.forThrowable(var29, "Feature placement"); +- crashReport.addCategory("Feature").setDetail("Description", supplier::get); +- throw new ReportedException(crashReport); +- } ++ generatoraccessseed.setCurrentlyGenerating(supplier); ++ structuremanager.startsForStructure(sectionposition, structure).forEach((structurestart) -> { ++ structurestart.placeInChunk(generatoraccessseed, structuremanager, this, seededrandom, getWritableArea(ichunkaccess), chunkcoordintpair); ++ }); ++ } catch (Exception exception) { ++ CrashReport crashreport = CrashReport.forThrowable(exception, "Feature placement"); + +- i1++; ++ crashreportsystemdetails = crashreport.addCategory("Feature"); ++ Objects.requireNonNull(supplier); ++ crashreportsystemdetails.setDetail("Description", supplier::get); ++ throw new ReportedException(crashreport); ++ } + } + } + +- if (i < size) { +- IntSet set1 = new IntArraySet(); ++ if (l < j) { ++ IntArraySet intarrayset = new IntArraySet(); + +- for (Holder holder : set) { +- List> list2 = this.generationSettingsGetter.apply(holder).features(); +- if (i < list2.size()) { +- HolderSet holderSet = list2.get(i); +- FeatureSorter.StepFeatureData stepFeatureData = list.get(i); +- holderSet.stream() +- .map(Holder::value) +- .forEach(placedFeature1 -> set1.add(stepFeatureData.indexMapping().applyAsInt(placedFeature1))); ++ iterator = set.iterator(); ++ ++ while (iterator.hasNext()) { ++ Holder holder = (Holder) iterator.next(); ++ List> list2 = ((BiomeGenerationSettings) this.generationSettingsGetter.apply(holder)).features(); ++ ++ if (l < list2.size()) { ++ HolderSet holderset = (HolderSet) list2.get(l); ++ FeatureSorter.StepFeatureData featuresorter_b = (FeatureSorter.StepFeatureData) list.get(l); ++ ++ holderset.stream().map(Holder::value).forEach((placedfeature) -> { ++ intarrayset.add(featuresorter_b.indexMapping().applyAsInt(placedfeature)); ++ }); + } + } + +- int size1 = set1.size(); +- int[] ints = set1.toIntArray(); +- Arrays.sort(ints); +- FeatureSorter.StepFeatureData stepFeatureData1 = list.get(i); ++ int j1 = intarrayset.size(); ++ int[] aint = intarrayset.toIntArray(); + +- for (int i2 = 0; i2 < size1; i2++) { +- int i3 = ints[i2]; +- PlacedFeature placedFeature = stepFeatureData1.features().get(i3); +- Supplier supplier1 = () -> registry1.getResourceKey(placedFeature).map(Object::toString).orElseGet(placedFeature::toString); +- worldgenRandom.setFeatureSeed(l, i3, i); ++ Arrays.sort(aint); ++ FeatureSorter.StepFeatureData featuresorter_b1 = (FeatureSorter.StepFeatureData) list.get(l); + ++ for (int k1 = 0; k1 < j1; ++k1) { ++ int l1 = aint[k1]; ++ PlacedFeature placedfeature = (PlacedFeature) featuresorter_b1.features().get(l1); ++ Supplier supplier1 = () -> { ++ Optional optional = iregistry1.getResourceKey(placedfeature).map(Object::toString); ++ ++ Objects.requireNonNull(placedfeature); ++ return (String) optional.orElseGet(placedfeature::toString); ++ }; ++ ++ seededrandom.setFeatureSeed(i, l1, l); ++ + try { +- level.setCurrentlyGenerating(supplier1); +- placedFeature.placeWithBiomeCheck(level, this, worldgenRandom, blockPos); +- } catch (Exception var30) { +- CrashReport crashReport1 = CrashReport.forThrowable(var30, "Feature placement"); +- crashReport1.addCategory("Feature").setDetail("Description", supplier1::get); +- throw new ReportedException(crashReport1); ++ generatoraccessseed.setCurrentlyGenerating(supplier1); ++ placedfeature.placeWithBiomeCheck(generatoraccessseed, this, seededrandom, blockposition); ++ } catch (Exception exception1) { ++ CrashReport crashreport1 = CrashReport.forThrowable(exception1, "Feature placement"); ++ ++ crashreportsystemdetails = crashreport1.addCategory("Feature"); ++ Objects.requireNonNull(supplier1); ++ crashreportsystemdetails.setDetail("Description", supplier1::get); ++ throw new ReportedException(crashreport1); + } + } + } + } + +- level.setCurrentlyGenerating(null); +- } catch (Exception var31) { +- CrashReport crashReport2 = CrashReport.forThrowable(var31, "Biome decoration"); +- crashReport2.addCategory("Generation").setDetail("CenterX", pos.x).setDetail("CenterZ", pos.z).setDetail("Seed", l); +- throw new ReportedException(crashReport2); ++ generatoraccessseed.setCurrentlyGenerating((Supplier) null); ++ } catch (Exception exception2) { ++ CrashReport crashreport2 = CrashReport.forThrowable(exception2, "Biome decoration"); ++ ++ crashreport2.addCategory("Generation").setDetail("CenterX", (Object) chunkcoordintpair.x).setDetail("CenterZ", (Object) chunkcoordintpair.z).setDetail("Seed", (Object) i); ++ throw new ReportedException(crashreport2); + } + } + } + ++ // CraftBukkit start ++ public void applyBiomeDecoration(WorldGenLevel level, ChunkAccess chunk, StructureManager structureManager) { ++ applyBiomeDecoration(level, chunk, structureManager, true); ++ } ++ ++ public void applyBiomeDecoration(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager, boolean vanilla) { ++ if (vanilla) { ++ addVanillaDecorations(generatoraccessseed, ichunkaccess, structuremanager); ++ } ++ ++ org.bukkit.World world = generatoraccessseed.getMinecraftWorld().getWorld(); ++ // only call when a populator is present (prevents unnecessary entity conversion) ++ if (!world.getPopulators().isEmpty()) { ++ org.bukkit.craftbukkit.generator.CraftLimitedRegion limitedRegion = new org.bukkit.craftbukkit.generator.CraftLimitedRegion(generatoraccessseed, ichunkaccess.getPos()); ++ int x = ichunkaccess.getPos().x; ++ int z = ichunkaccess.getPos().z; ++ for (org.bukkit.generator.BlockPopulator populator : world.getPopulators()) { ++ WorldgenRandom seededrandom = new WorldgenRandom(new net.minecraft.world.level.levelgen.LegacyRandomSource(generatoraccessseed.getSeed())); ++ seededrandom.setDecorationSeed(generatoraccessseed.getSeed(), x, z); ++ populator.populate(world, new org.bukkit.craftbukkit.util.RandomSourceWrapper.RandomWrapper(seededrandom), x, z, limitedRegion); ++ } ++ limitedRegion.saveEntities(); ++ limitedRegion.breakLink(); ++ } ++ } ++ // CraftBukkit end ++ + private static BoundingBox getWritableArea(ChunkAccess chunk) { +- ChunkPos pos = chunk.getPos(); +- int minBlockX = pos.getMinBlockX(); +- int minBlockZ = pos.getMinBlockZ(); +- LevelHeightAccessor heightAccessorForGeneration = chunk.getHeightAccessorForGeneration(); +- int i = heightAccessorForGeneration.getMinBuildHeight() + 1; +- int i1 = heightAccessorForGeneration.getMaxBuildHeight() - 1; +- return new BoundingBox(minBlockX, i, minBlockZ, minBlockX + 15, i1, minBlockZ + 15); ++ ChunkPos chunkcoordintpair = chunk.getPos(); ++ int i = chunkcoordintpair.getMinBlockX(); ++ int j = chunkcoordintpair.getMinBlockZ(); ++ LevelHeightAccessor levelheightaccessor = chunk.getHeightAccessorForGeneration(); ++ int k = levelheightaccessor.getMinBuildHeight() + 1; ++ int l = levelheightaccessor.getMaxBuildHeight() - 1; ++ ++ return new BoundingBox(i, k, j, i + 15, l, j + 15); + } + + public abstract void buildSurface(WorldGenRegion level, StructureManager structureManager, RandomState random, ChunkAccess chunk); +@@ -434,137 +491,127 @@ + + public abstract int getGenDepth(); + +- public WeightedRandomList getMobsAt( +- Holder biome, StructureManager structureManager, MobCategory category, BlockPos pos +- ) { +- Map allStructuresAt = structureManager.getAllStructuresAt(pos); ++ public WeightedRandomList getMobsAt(Holder biome, StructureManager structureManager, MobCategory category, BlockPos pos) { ++ Map map = structureManager.getAllStructuresAt(pos); ++ Iterator iterator = map.entrySet().iterator(); + +- for (Entry entry : allStructuresAt.entrySet()) { +- Structure structure = entry.getKey(); +- StructureSpawnOverride structureSpawnOverride = structure.spawnOverrides().get(category); +- if (structureSpawnOverride != null) { +- MutableBoolean mutableBoolean = new MutableBoolean(false); +- Predicate predicate = structureSpawnOverride.boundingBox() == StructureSpawnOverride.BoundingBoxType.PIECE +- ? structureStart -> structureManager.structureHasPieceAt(pos, structureStart) +- : structureStart -> structureStart.getBoundingBox().isInside(pos); +- structureManager.fillStartsForStructure(structure, entry.getValue(), structureStart -> { +- if (mutableBoolean.isFalse() && predicate.test(structureStart)) { +- mutableBoolean.setTrue(); ++ while (iterator.hasNext()) { ++ Entry entry = (Entry) iterator.next(); ++ Structure structure = (Structure) entry.getKey(); ++ StructureSpawnOverride structurespawnoverride = (StructureSpawnOverride) structure.spawnOverrides().get(category); ++ ++ if (structurespawnoverride != null) { ++ MutableBoolean mutableboolean = new MutableBoolean(false); ++ Predicate predicate = structurespawnoverride.boundingBox() == StructureSpawnOverride.BoundingBoxType.PIECE ? (structurestart) -> { ++ return structureManager.structureHasPieceAt(pos, structurestart); ++ } : (structurestart) -> { ++ return structurestart.getBoundingBox().isInside(pos); ++ }; ++ ++ structureManager.fillStartsForStructure(structure, (LongSet) entry.getValue(), (structurestart) -> { ++ if (mutableboolean.isFalse() && predicate.test(structurestart)) { ++ mutableboolean.setTrue(); + } ++ + }); +- if (mutableBoolean.isTrue()) { +- return structureSpawnOverride.spawns(); ++ if (mutableboolean.isTrue()) { ++ return structurespawnoverride.spawns(); + } + } + } + +- return biome.value().getMobSettings().getMobs(category); ++ return ((Biome) biome.value()).getMobSettings().getMobs(category); + } + +- public void createStructures( +- RegistryAccess registryAccess, +- ChunkGeneratorStructureState structureState, +- StructureManager structureManager, +- ChunkAccess chunk, +- StructureTemplateManager structureTemplateManager +- ) { +- ChunkPos pos = chunk.getPos(); +- SectionPos sectionPos = SectionPos.bottomOf(chunk); +- RandomState randomState = structureState.randomState(); +- structureState.possibleStructureSets() +- .forEach( +- structureSet -> { +- StructurePlacement structurePlacement = structureSet.value().placement(); +- List list = structureSet.value().structures(); +- +- for (StructureSet.StructureSelectionEntry structureSelectionEntry : list) { +- StructureStart startForStructure = structureManager.getStartForStructure(sectionPos, structureSelectionEntry.structure().value(), chunk); +- if (startForStructure != null && startForStructure.isValid()) { +- return; +- } ++ public void createStructures(RegistryAccess registryAccess, ChunkGeneratorStructureState structureState, StructureManager structureManager, ChunkAccess chunk, StructureTemplateManager structureTemplateManager) { ++ ChunkPos chunkcoordintpair = chunk.getPos(); ++ SectionPos sectionposition = SectionPos.bottomOf(chunk); ++ RandomState randomstate = structureState.randomState(); ++ ++ structureState.possibleStructureSets().forEach((holder) -> { ++ StructurePlacement structureplacement = ((StructureSet) holder.value()).placement(); ++ List list = ((StructureSet) holder.value()).structures(); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ StructureSet.a structureset_a = (StructureSet.a) iterator.next(); ++ StructureStart structurestart = structureManager.getStartForStructure(sectionposition, (Structure) structureset_a.structure().value(), chunk); ++ ++ if (structurestart != null && structurestart.isValid()) { ++ return; ++ } ++ } ++ ++ if (structureplacement.isStructureChunk(structureState, chunkcoordintpair.x, chunkcoordintpair.z)) { ++ if (list.size() == 1) { ++ this.tryGenerateStructure((StructureSet.a) list.get(0), structureManager, registryAccess, randomstate, structureTemplateManager, structureState.getLevelSeed(), chunk, chunkcoordintpair, sectionposition); ++ } else { ++ ArrayList arraylist = new ArrayList(list.size()); ++ ++ arraylist.addAll(list); ++ WorldgenRandom seededrandom = new WorldgenRandom(new LegacyRandomSource(0L)); ++ ++ seededrandom.setLargeFeatureSeed(structureState.getLevelSeed(), chunkcoordintpair.x, chunkcoordintpair.z); ++ int i = 0; ++ ++ StructureSet.a structureset_a1; ++ ++ for (Iterator iterator1 = arraylist.iterator(); iterator1.hasNext(); i += structureset_a1.weight()) { ++ structureset_a1 = (StructureSet.a) iterator1.next(); + } +- +- if (structurePlacement.isStructureChunk(structureState, pos.x, pos.z)) { +- if (list.size() == 1) { +- this.tryGenerateStructure( +- list.get(0), +- structureManager, +- registryAccess, +- randomState, +- structureTemplateManager, +- structureState.getLevelSeed(), +- chunk, +- pos, +- sectionPos +- ); +- } else { +- ArrayList list1 = new ArrayList<>(list.size()); +- list1.addAll(list); +- WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L)); +- worldgenRandom.setLargeFeatureSeed(structureState.getLevelSeed(), pos.x, pos.z); +- int i = 0; +- +- for (StructureSet.StructureSelectionEntry structureSelectionEntry1 : list1) { +- i += structureSelectionEntry1.weight(); +- } +- +- while (!list1.isEmpty()) { +- int randomInt = worldgenRandom.nextInt(i); +- int i1 = 0; +- +- for (StructureSet.StructureSelectionEntry structureSelectionEntry2 : list1) { +- randomInt -= structureSelectionEntry2.weight(); +- if (randomInt < 0) { +- break; +- } +- +- i1++; ++ ++ while (!arraylist.isEmpty()) { ++ int j = seededrandom.nextInt(i); ++ int k = 0; ++ Iterator iterator2 = arraylist.iterator(); ++ ++ while (true) { ++ if (iterator2.hasNext()) { ++ StructureSet.a structureset_a2 = (StructureSet.a) iterator2.next(); ++ ++ j -= structureset_a2.weight(); ++ if (j >= 0) { ++ ++k; ++ continue; + } +- +- StructureSet.StructureSelectionEntry structureSelectionEntry3 = list1.get(i1); +- if (this.tryGenerateStructure( +- structureSelectionEntry3, +- structureManager, +- registryAccess, +- randomState, +- structureTemplateManager, +- structureState.getLevelSeed(), +- chunk, +- pos, +- sectionPos +- )) { +- return; +- } +- +- list1.remove(i1); +- i -= structureSelectionEntry3.weight(); + } ++ ++ StructureSet.a structureset_a3 = (StructureSet.a) arraylist.get(k); ++ ++ if (this.tryGenerateStructure(structureset_a3, structureManager, registryAccess, randomstate, structureTemplateManager, structureState.getLevelSeed(), chunk, chunkcoordintpair, sectionposition)) { ++ return; ++ } ++ ++ arraylist.remove(k); ++ i -= structureset_a3.weight(); ++ break; + } + } ++ + } +- ); ++ } ++ }); + } + +- private boolean tryGenerateStructure( +- StructureSet.StructureSelectionEntry structureSelectionEntry, +- StructureManager structureManager, +- RegistryAccess registryAccess, +- RandomState random, +- StructureTemplateManager structureTemplateManager, +- long seed, +- ChunkAccess chunk, +- ChunkPos chunkPos, +- SectionPos sectionPos +- ) { +- Structure structure = structureSelectionEntry.structure().value(); +- int i = fetchReferences(structureManager, chunk, sectionPos, structure); +- HolderSet holderSet = structure.biomes(); +- Predicate> predicate = holderSet::contains; +- StructureStart structureStart = structure.generate( +- registryAccess, this, this.biomeSource, random, structureTemplateManager, seed, chunkPos, i, chunk, predicate +- ); +- if (structureStart.isValid()) { +- structureManager.setStartForStructure(sectionPos, structure, structureStart, chunk); ++ private boolean tryGenerateStructure(StructureSet.a structureSelectionEntry, StructureManager structureManager, RegistryAccess registryAccess, RandomState random, StructureTemplateManager structureTemplateManager, long seed, ChunkAccess ichunkaccess, ChunkPos chunk, SectionPos chunkPos) { ++ Structure structure = (Structure) structureSelectionEntry.structure().value(); ++ int j = fetchReferences(structureManager, ichunkaccess, chunkPos, structure); ++ HolderSet holderset = structure.biomes(); ++ ++ Objects.requireNonNull(holderset); ++ Predicate> predicate = holderset::contains; ++ StructureStart structurestart = structure.generate(registryAccess, this, this.biomeSource, random, structureTemplateManager, seed, chunk, j, ichunkaccess, predicate); ++ ++ if (structurestart.isValid()) { ++ // CraftBukkit start ++ BoundingBox box = structurestart.getBoundingBox(); ++ org.bukkit.event.world.AsyncStructureSpawnEvent event = new org.bukkit.event.world.AsyncStructureSpawnEvent(structureManager.level.getMinecraftWorld().getWorld(), org.bukkit.craftbukkit.generator.structure.CraftStructure.minecraftToBukkit(structure, registryAccess), new org.bukkit.util.BoundingBox(box.minX(), box.minY(), box.minZ(), box.maxX(), box.maxY(), box.maxZ()), chunk.x, chunk.z); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return true; ++ } ++ // CraftBukkit end ++ structureManager.setStartForStructure(chunkPos, structure, structurestart, ichunkaccess); + return true; + } else { + return false; +@@ -572,48 +619,58 @@ + } + + private static int fetchReferences(StructureManager structureManager, ChunkAccess chunk, SectionPos sectionPos, Structure structure) { +- StructureStart startForStructure = structureManager.getStartForStructure(sectionPos, structure, chunk); +- return startForStructure != null ? startForStructure.getReferences() : 0; ++ StructureStart structurestart = structureManager.getStartForStructure(sectionPos, structure, chunk); ++ ++ return structurestart != null ? structurestart.getReferences() : 0; + } + + public void createReferences(WorldGenLevel level, StructureManager structureManager, ChunkAccess chunk) { +- int i = 8; +- ChunkPos pos = chunk.getPos(); +- int i1 = pos.x; +- int i2 = pos.z; +- int minBlockX = pos.getMinBlockX(); +- int minBlockZ = pos.getMinBlockZ(); +- SectionPos sectionPos = SectionPos.bottomOf(chunk); ++ boolean flag = true; ++ ChunkPos chunkcoordintpair = chunk.getPos(); ++ int i = chunkcoordintpair.x; ++ int j = chunkcoordintpair.z; ++ int k = chunkcoordintpair.getMinBlockX(); ++ int l = chunkcoordintpair.getMinBlockZ(); ++ SectionPos sectionposition = SectionPos.bottomOf(chunk); + +- for (int i3 = i1 - 8; i3 <= i1 + 8; i3++) { +- for (int i4 = i2 - 8; i4 <= i2 + 8; i4++) { +- long _long = ChunkPos.asLong(i3, i4); ++ for (int i1 = i - 8; i1 <= i + 8; ++i1) { ++ for (int j1 = j - 8; j1 <= j + 8; ++j1) { ++ long k1 = ChunkPos.asLong(i1, j1); ++ Iterator iterator = level.getChunk(i1, j1).getAllStarts().values().iterator(); + +- for (StructureStart structureStart : level.getChunk(i3, i4).getAllStarts().values()) { ++ while (iterator.hasNext()) { ++ StructureStart structurestart = (StructureStart) iterator.next(); ++ + try { +- if (structureStart.isValid() && structureStart.getBoundingBox().intersects(minBlockX, minBlockZ, minBlockX + 15, minBlockZ + 15)) { +- structureManager.addReferenceForStructure(sectionPos, structureStart.getStructure(), _long, chunk); +- DebugPackets.sendStructurePacket(level, structureStart); ++ if (structurestart.isValid() && structurestart.getBoundingBox().intersects(k, l, k + 15, l + 15)) { ++ structureManager.addReferenceForStructure(sectionposition, structurestart.getStructure(), k1, chunk); ++ DebugPackets.sendStructurePacket(level, structurestart); + } +- } catch (Exception var21) { +- CrashReport crashReport = CrashReport.forThrowable(var21, "Generating structure reference"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Structure"); ++ } catch (Exception exception) { ++ CrashReport crashreport = CrashReport.forThrowable(exception, "Generating structure reference"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Structure"); + Optional> optional = level.registryAccess().registry(Registries.STRUCTURE); +- crashReportCategory.setDetail( +- "Id", () -> optional.map(registry -> registry.getKey(structureStart.getStructure()).toString()).orElse("UNKNOWN") +- ); +- crashReportCategory.setDetail("Name", () -> BuiltInRegistries.STRUCTURE_TYPE.getKey(structureStart.getStructure().type()).toString()); +- crashReportCategory.setDetail("Class", () -> structureStart.getStructure().getClass().getCanonicalName()); +- throw new ReportedException(crashReport); ++ ++ crashreportsystemdetails.setDetail("Id", () -> { ++ return (String) optional.map((iregistry) -> { ++ return iregistry.getKey(structurestart.getStructure()).toString(); ++ }).orElse("UNKNOWN"); ++ }); ++ crashreportsystemdetails.setDetail("Name", () -> { ++ return BuiltInRegistries.STRUCTURE_TYPE.getKey(structurestart.getStructure().type()).toString(); ++ }); ++ crashreportsystemdetails.setDetail("Class", () -> { ++ return structurestart.getStructure().getClass().getCanonicalName(); ++ }); ++ throw new ReportedException(crashreport); + } + } + } + } ++ + } + +- public abstract CompletableFuture fillFromNoise( +- Executor executor, Blender blender, RandomState random, StructureManager structureManager, ChunkAccess chunk +- ); ++ public abstract CompletableFuture fillFromNoise(Executor executor, Blender blender, RandomState random, StructureManager structureManager, ChunkAccess chunk); + + public abstract int getSeaLevel(); + +@@ -621,7 +678,7 @@ + + public abstract int getBaseHeight(int x, int z, Heightmap.Types type, LevelHeightAccessor level, RandomState random); + +- public abstract NoiseColumn getBaseColumn(int x, int z, LevelHeightAccessor height, RandomState random); ++ public abstract net.minecraft.world.level.NoiseColumn getBaseColumn(int x, int z, LevelHeightAccessor height, RandomState random); + + public int getFirstFreeHeight(int x, int z, Heightmap.Types type, LevelHeightAccessor level, RandomState random) { + return this.getBaseHeight(x, z, type, level, random); +@@ -633,8 +690,9 @@ + + public abstract void addDebugScreenInfo(List info, RandomState random, BlockPos pos); + ++ /** @deprecated */ + @Deprecated + public BiomeGenerationSettings getBiomeGenerationSettings(Holder biome) { +- return this.generationSettingsGetter.apply(biome); ++ return (BiomeGenerationSettings) this.generationSettingsGetter.apply(biome); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java.patch new file mode 100644 index 0000000000..f2f2fcb37f --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java.patch @@ -0,0 +1,296 @@ +--- a/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java ++++ b/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.world.level.chunk; + + import com.google.common.base.Stopwatch; +@@ -6,8 +7,10 @@ + import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; + import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + import java.util.ArrayList; ++import java.util.Iterator; + import java.util.List; + import java.util.Map; ++import java.util.Objects; + import java.util.Set; + import java.util.concurrent.CompletableFuture; + import java.util.concurrent.TimeUnit; +@@ -32,48 +35,51 @@ + import org.slf4j.Logger; + + public class ChunkGeneratorStructureState { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private final RandomState randomState; + private final BiomeSource biomeSource; + private final long levelSeed; + private final long concentricRingsSeed; +- private final Map> placementsForStructure = new Object2ObjectOpenHashMap<>(); +- private final Map>> ringPositions = new Object2ObjectArrayMap<>(); ++ private final Map> placementsForStructure = new Object2ObjectOpenHashMap(); ++ private final Map>> ringPositions = new Object2ObjectArrayMap(); + private boolean hasGeneratedPositions; + private final List> possibleStructureSets; + +- public static ChunkGeneratorStructureState createForFlat( +- RandomState randomState, long levelSeed, BiomeSource biomeSource, Stream> structureSets +- ) { +- List> list = structureSets.filter(structureSet -> hasBiomesForStructureSet(structureSet.value(), biomeSource)).toList(); +- return new ChunkGeneratorStructureState(randomState, biomeSource, levelSeed, 0L, list); ++ public static ChunkGeneratorStructureState createForFlat(RandomState randomState, long levelSeed, BiomeSource worldchunkmanager, Stream> biomeSource) { ++ List> list = biomeSource.filter((holder) -> { ++ return hasBiomesForStructureSet((StructureSet) holder.value(), worldchunkmanager); ++ }).toList(); ++ ++ return new ChunkGeneratorStructureState(randomState, worldchunkmanager, levelSeed, 0L, list); + } + +- public static ChunkGeneratorStructureState createForNormal( +- RandomState randomState, long seed, BiomeSource biomeSource, HolderLookup structureSetLookup +- ) { +- List> list = structureSetLookup.listElements() +- .filter(structureSet -> hasBiomesForStructureSet(structureSet.value(), biomeSource)) +- .collect(Collectors.toUnmodifiableList()); +- return new ChunkGeneratorStructureState(randomState, biomeSource, seed, seed, list); ++ public static ChunkGeneratorStructureState createForNormal(RandomState randomState, long seed, BiomeSource worldchunkmanager, HolderLookup biomeSource) { ++ List> list = (List) biomeSource.listElements().filter((holder_c) -> { ++ return hasBiomesForStructureSet((StructureSet) holder_c.value(), worldchunkmanager); ++ }).collect(Collectors.toUnmodifiableList()); ++ ++ return new ChunkGeneratorStructureState(randomState, worldchunkmanager, seed, seed, list); + } + + private static boolean hasBiomesForStructureSet(StructureSet structureSet, BiomeSource biomeSource) { +- Stream> stream = structureSet.structures().stream().flatMap(structureEntry -> { +- Structure structure = structureEntry.structure().value(); ++ Stream> stream = structureSet.structures().stream().flatMap((structureset_a) -> { ++ Structure structure = (Structure) structureset_a.structure().value(); ++ + return structure.biomes().stream(); + }); +- return stream.anyMatch(biomeSource.possibleBiomes()::contains); ++ Set set = biomeSource.possibleBiomes(); ++ ++ Objects.requireNonNull(set); ++ return stream.anyMatch(set::contains); + } + +- private ChunkGeneratorStructureState( +- RandomState randomState, BiomeSource biomeSource, long levelSeed, long cocentricRingsSeed, List> possibleStructureSets +- ) { ++ private ChunkGeneratorStructureState(RandomState randomState, BiomeSource biomeSource, long levelSeed, long j, List> cocentricRingsSeed) { + this.randomState = randomState; + this.levelSeed = levelSeed; + this.biomeSource = biomeSource; +- this.concentricRingsSeed = cocentricRingsSeed; +- this.possibleStructureSets = possibleStructureSets; ++ this.concentricRingsSeed = j; ++ this.possibleStructureSets = cocentricRingsSeed; + } + + public List> possibleStructureSets() { +@@ -82,29 +88,37 @@ + + private void generatePositions() { + Set> set = this.biomeSource.possibleBiomes(); +- this.possibleStructureSets() +- .forEach( +- structureSetHolder -> { +- StructureSet structureSet = structureSetHolder.value(); +- boolean flag = false; +- +- for (StructureSet.StructureSelectionEntry structureSelectionEntry : structureSet.structures()) { +- Structure structure = structureSelectionEntry.structure().value(); +- if (structure.biomes().stream().anyMatch(set::contains)) { +- this.placementsForStructure.computeIfAbsent(structure, key -> new ArrayList<>()).add(structureSet.placement()); +- flag = true; +- } +- } +- +- if (flag && structureSet.placement() instanceof ConcentricRingsStructurePlacement concentricRingsStructurePlacement) { +- this.ringPositions +- .put( +- concentricRingsStructurePlacement, +- this.generateRingPositions((Holder)structureSetHolder, concentricRingsStructurePlacement) +- ); +- } ++ ++ this.possibleStructureSets().forEach((holder) -> { ++ StructureSet structureset = (StructureSet) holder.value(); ++ boolean flag = false; ++ Iterator iterator = structureset.structures().iterator(); ++ ++ while (iterator.hasNext()) { ++ StructureSet.a structureset_a = (StructureSet.a) iterator.next(); ++ Structure structure = (Structure) structureset_a.structure().value(); ++ Stream stream = structure.biomes().stream(); ++ ++ Objects.requireNonNull(set); ++ if (stream.anyMatch(set::contains)) { ++ ((List) this.placementsForStructure.computeIfAbsent(structure, (structure1) -> { ++ return new ArrayList(); ++ })).add(structureset.placement()); ++ flag = true; + } +- ); ++ } ++ ++ if (flag) { ++ StructurePlacement structureplacement = structureset.placement(); ++ ++ if (structureplacement instanceof ConcentricRingsStructurePlacement) { ++ ConcentricRingsStructurePlacement concentricringsstructureplacement = (ConcentricRingsStructurePlacement) structureplacement; ++ ++ this.ringPositions.put(concentricringsstructureplacement, this.generateRingPositions(holder, concentricringsstructureplacement)); ++ } ++ } ++ ++ }); + } + + private CompletableFuture> generateRingPositions(Holder structureSet, ConcentricRingsStructurePlacement placement) { +@@ -113,58 +127,55 @@ + } else { + Stopwatch stopwatch = Stopwatch.createStarted(Util.TICKER); + int i = placement.distance(); +- int i1 = placement.count(); +- List> list = new ArrayList<>(i1); +- int i2 = placement.spread(); +- HolderSet holderSet = placement.preferredBiomes(); +- RandomSource randomSource = RandomSource.create(); +- randomSource.setSeed(this.concentricRingsSeed); +- double d = randomSource.nextDouble() * Math.PI * 2.0; +- int i3 = 0; +- int i4 = 0; ++ int j = placement.count(); ++ List> list = new ArrayList(j); ++ int k = placement.spread(); ++ HolderSet holderset = placement.preferredBiomes(); ++ RandomSource randomsource = RandomSource.create(); + +- for (int i5 = 0; i5 < i1; i5++) { +- double d1 = (double)(4 * i + i * i4 * 6) + (randomSource.nextDouble() - 0.5) * (double)i * 2.5; +- int i6 = (int)Math.round(Math.cos(d) * d1); +- int i7 = (int)Math.round(Math.sin(d) * d1); +- RandomSource randomSource1 = randomSource.fork(); +- list.add( +- CompletableFuture.supplyAsync( +- () -> { +- Pair> pair = this.biomeSource +- .findBiomeHorizontal( +- SectionPos.sectionToBlockCoord(i6, 8), +- 0, +- SectionPos.sectionToBlockCoord(i7, 8), +- 112, +- holderSet::contains, +- randomSource1, +- this.randomState.sampler() +- ); +- if (pair != null) { +- BlockPos blockPos = pair.getFirst(); +- return new ChunkPos(SectionPos.blockToSectionCoord(blockPos.getX()), SectionPos.blockToSectionCoord(blockPos.getZ())); +- } else { +- return new ChunkPos(i6, i7); +- } +- }, +- Util.backgroundExecutor() +- ) +- ); +- d += (Math.PI * 2) / (double)i2; +- if (++i3 == i2) { +- i4++; +- i3 = 0; +- i2 += 2 * i2 / (i4 + 1); +- i2 = Math.min(i2, i1 - i5); +- d += randomSource.nextDouble() * Math.PI * 2.0; ++ randomsource.setSeed(this.concentricRingsSeed); ++ double d0 = randomsource.nextDouble() * 3.141592653589793D * 2.0D; ++ int l = 0; ++ int i1 = 0; ++ ++ for (int j1 = 0; j1 < j; ++j1) { ++ double d1 = (double) (4 * i + i * i1 * 6) + (randomsource.nextDouble() - 0.5D) * (double) i * 2.5D; ++ int k1 = (int) Math.round(Math.cos(d0) * d1); ++ int l1 = (int) Math.round(Math.sin(d0) * d1); ++ RandomSource randomsource1 = randomsource.fork(); ++ ++ list.add(CompletableFuture.supplyAsync(() -> { ++ BiomeSource worldchunkmanager = this.biomeSource; ++ int i2 = SectionPos.sectionToBlockCoord(k1, 8); ++ int j2 = SectionPos.sectionToBlockCoord(l1, 8); ++ ++ Objects.requireNonNull(holderset); ++ Pair> pair = worldchunkmanager.findBiomeHorizontal(i2, 0, j2, 112, holderset::contains, randomsource1, this.randomState.sampler()); ++ ++ if (pair != null) { ++ BlockPos blockposition = (BlockPos) pair.getFirst(); ++ ++ return new ChunkPos(SectionPos.blockToSectionCoord(blockposition.getX()), SectionPos.blockToSectionCoord(blockposition.getZ())); ++ } else { ++ return new ChunkPos(k1, l1); ++ } ++ }, Util.backgroundExecutor())); ++ d0 += 6.283185307179586D / (double) k; ++ ++l; ++ if (l == k) { ++ ++i1; ++ l = 0; ++ k += 2 * k / (i1 + 1); ++ k = Math.min(k, j - j1); ++ d0 += randomsource.nextDouble() * 3.141592653589793D * 2.0D; + } + } + +- return Util.sequence(list).thenApply(completed -> { +- double d2 = (double)stopwatch.stop().elapsed(TimeUnit.MILLISECONDS) / 1000.0; +- LOGGER.debug("Calculation for {} took {}s", structureSet, d2); +- return completed; ++ return Util.sequence(list).thenApply((list1) -> { ++ double d2 = (double) stopwatch.stop().elapsed(TimeUnit.MILLISECONDS) / 1000.0D; ++ ++ ChunkGeneratorStructureState.LOGGER.debug("Calculation for {} took {}s", structureSet, d2); ++ return list1; + }); + } + } +@@ -174,18 +185,20 @@ + this.generatePositions(); + this.hasGeneratedPositions = true; + } ++ + } + + @Nullable + public List getRingPositionsFor(ConcentricRingsStructurePlacement placement) { + this.ensureStructuresGenerated(); +- CompletableFuture> completableFuture = this.ringPositions.get(placement); +- return completableFuture != null ? completableFuture.join() : null; ++ CompletableFuture> completablefuture = (CompletableFuture) this.ringPositions.get(placement); ++ ++ return completablefuture != null ? (List) completablefuture.join() : null; + } + + public List getPlacementsForStructure(Holder structure) { + this.ensureStructuresGenerated(); +- return this.placementsForStructure.getOrDefault(structure.value(), List.of()); ++ return (List) this.placementsForStructure.getOrDefault(structure.value(), List.of()); + } + + public RandomState randomState() { +@@ -193,11 +206,11 @@ + } + + public boolean hasStructureChunkInRange(Holder structureSet, int x, int z, int range) { +- StructurePlacement structurePlacement = structureSet.value().placement(); ++ StructurePlacement structureplacement = ((StructureSet) structureSet.value()).placement(); + +- for (int i = x - range; i <= x + range; i++) { +- for (int i1 = z - range; i1 <= z + range; i1++) { +- if (structurePlacement.isStructureChunk(this, i, i1)) { ++ for (int l = x - range; l <= x + range; ++l) { ++ for (int i1 = z - range; i1 <= z + range; ++i1) { ++ if (structureplacement.isStructureChunk(this, l, i1)) { + return true; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/ChunkStatus.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/ChunkStatus.java.patch new file mode 100644 index 0000000000..b50d72b98d --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/ChunkStatus.java.patch @@ -0,0 +1,586 @@ +--- a/net/minecraft/world/level/chunk/ChunkStatus.java ++++ b/net/minecraft/world/level/chunk/ChunkStatus.java +@@ -29,216 +29,113 @@ + import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; + + public class ChunkStatus { ++ + public static final int MAX_STRUCTURE_DISTANCE = 8; + private static final EnumSet PRE_FEATURES = EnumSet.of(Heightmap.Types.OCEAN_FLOOR_WG, Heightmap.Types.WORLD_SURFACE_WG); +- public static final EnumSet POST_FEATURES = EnumSet.of( +- Heightmap.Types.OCEAN_FLOOR, Heightmap.Types.WORLD_SURFACE, Heightmap.Types.MOTION_BLOCKING, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES +- ); +- private static final ChunkStatus.LoadingTask PASSTHROUGH_LOAD_TASK = (status, level, structureTemplateManager, lightEngine, task, chunk) -> CompletableFuture.completedFuture( +- Either.left(chunk) +- ); +- public static final ChunkStatus EMPTY = registerSimple( +- "empty", null, -1, PRE_FEATURES, ChunkStatus.ChunkType.PROTOCHUNK, (status, level, chunkGenerator, neighboringChunks, loadingChunk) -> { ++ public static final EnumSet POST_FEATURES = EnumSet.of(Heightmap.Types.OCEAN_FLOOR, Heightmap.Types.WORLD_SURFACE, Heightmap.Types.MOTION_BLOCKING, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES); ++ private static final ChunkStatus.LoadingTask PASSTHROUGH_LOAD_TASK = (chunkstatus, worldserver, structuretemplatemanager, lightenginethreaded, function, ichunkaccess) -> { ++ return CompletableFuture.completedFuture(Either.left(ichunkaccess)); ++ }; ++ public static final ChunkStatus EMPTY = registerSimple("empty", (ChunkStatus) null, -1, ChunkStatus.PRE_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, list, ichunkaccess) -> { ++ }); ++ public static final ChunkStatus STRUCTURE_STARTS = register("structure_starts", ChunkStatus.EMPTY, 0, false, ChunkStatus.PRE_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, executor, worldserver, chunkgenerator, structuretemplatemanager, lightenginethreaded, function, list, ichunkaccess) -> { ++ if (worldserver.serverLevelData.worldGenOptions().generateStructures()) { // CraftBukkit ++ chunkgenerator.createStructures(worldserver.registryAccess(), worldserver.getChunkSource().getGeneratorState(), worldserver.structureManager(), ichunkaccess, structuretemplatemanager); + } +- ); +- public static final ChunkStatus STRUCTURE_STARTS = register( +- "structure_starts", +- EMPTY, +- 0, +- false, +- PRE_FEATURES, +- ChunkStatus.ChunkType.PROTOCHUNK, +- (status, executor, level, chunkGenerator, structureTemplateManager, lightEngine, task, cache, loadingChunk) -> { +- if (level.getServer().getWorldData().worldGenOptions().generateStructures()) { +- chunkGenerator.createStructures( +- level.registryAccess(), level.getChunkSource().getGeneratorState(), level.structureManager(), loadingChunk, structureTemplateManager +- ); +- } +- +- level.onStructureStartsAvailable(loadingChunk); +- return CompletableFuture.completedFuture(Either.left(loadingChunk)); +- }, +- (status, level, structureTemplateManager, lightEngine, task, chunk) -> { +- level.onStructureStartsAvailable(chunk); +- return CompletableFuture.completedFuture(Either.left(chunk)); +- } +- ); +- public static final ChunkStatus STRUCTURE_REFERENCES = registerSimple( +- "structure_references", +- STRUCTURE_STARTS, +- 8, +- PRE_FEATURES, +- ChunkStatus.ChunkType.PROTOCHUNK, +- (status, serverLevel, chunkGenerator, cache, loadingChunk) -> { +- WorldGenRegion worldGenRegion = new WorldGenRegion(serverLevel, cache, status, -1); +- chunkGenerator.createReferences(worldGenRegion, serverLevel.structureManager().forWorldGenRegion(worldGenRegion), loadingChunk); +- } +- ); +- public static final ChunkStatus BIOMES = register( +- "biomes", +- STRUCTURE_REFERENCES, +- 8, +- PRE_FEATURES, +- ChunkStatus.ChunkType.PROTOCHUNK, +- (status, executor, level, chunkGenerator, structureTemplateManager, lightEngine, task, cache, loadingChunk) -> { +- WorldGenRegion worldGenRegion = new WorldGenRegion(level, cache, status, -1); +- return chunkGenerator.createBiomes( +- executor, +- level.getChunkSource().randomState(), +- Blender.of(worldGenRegion), +- level.structureManager().forWorldGenRegion(worldGenRegion), +- loadingChunk +- ) +- .thenApply(chunk -> Either.left(chunk)); +- } +- ); +- public static final ChunkStatus NOISE = register( +- "noise", +- BIOMES, +- 8, +- PRE_FEATURES, +- ChunkStatus.ChunkType.PROTOCHUNK, +- (status, executor, level, chunkGenerator, structureTemplateManager, lightEngine, task, cache, loadingChunk) -> { +- WorldGenRegion worldGenRegion = new WorldGenRegion(level, cache, status, 0); +- return chunkGenerator.fillFromNoise( +- executor, +- Blender.of(worldGenRegion), +- level.getChunkSource().randomState(), +- level.structureManager().forWorldGenRegion(worldGenRegion), +- loadingChunk +- ) +- .thenApply(chunk -> { +- if (chunk instanceof ProtoChunk protoChunk) { +- BelowZeroRetrogen belowZeroRetrogen = protoChunk.getBelowZeroRetrogen(); +- if (belowZeroRetrogen != null) { +- BelowZeroRetrogen.replaceOldBedrock(protoChunk); +- if (belowZeroRetrogen.hasBedrockHoles()) { +- belowZeroRetrogen.applyBedrockMask(protoChunk); +- } +- } ++ ++ worldserver.onStructureStartsAvailable(ichunkaccess); ++ return CompletableFuture.completedFuture(Either.left(ichunkaccess)); ++ }, (chunkstatus, worldserver, structuretemplatemanager, lightenginethreaded, function, ichunkaccess) -> { ++ worldserver.onStructureStartsAvailable(ichunkaccess); ++ return CompletableFuture.completedFuture(Either.left(ichunkaccess)); ++ }); ++ public static final ChunkStatus STRUCTURE_REFERENCES = registerSimple("structure_references", ChunkStatus.STRUCTURE_STARTS, 8, ChunkStatus.PRE_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, list, ichunkaccess) -> { ++ WorldGenRegion regionlimitedworldaccess = new WorldGenRegion(worldserver, list, chunkstatus, -1); ++ ++ chunkgenerator.createReferences(regionlimitedworldaccess, worldserver.structureManager().forWorldGenRegion(regionlimitedworldaccess), ichunkaccess); ++ }); ++ public static final ChunkStatus BIOMES = register("biomes", ChunkStatus.STRUCTURE_REFERENCES, 8, ChunkStatus.PRE_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, executor, worldserver, chunkgenerator, structuretemplatemanager, lightenginethreaded, function, list, ichunkaccess) -> { ++ WorldGenRegion regionlimitedworldaccess = new WorldGenRegion(worldserver, list, chunkstatus, -1); ++ ++ return chunkgenerator.createBiomes(executor, worldserver.getChunkSource().randomState(), Blender.of(regionlimitedworldaccess), worldserver.structureManager().forWorldGenRegion(regionlimitedworldaccess), ichunkaccess).thenApply((ichunkaccess1) -> { ++ return Either.left(ichunkaccess1); ++ }); ++ }); ++ public static final ChunkStatus NOISE = register("noise", ChunkStatus.BIOMES, 8, ChunkStatus.PRE_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, executor, worldserver, chunkgenerator, structuretemplatemanager, lightenginethreaded, function, list, ichunkaccess) -> { ++ WorldGenRegion regionlimitedworldaccess = new WorldGenRegion(worldserver, list, chunkstatus, 0); ++ ++ return chunkgenerator.fillFromNoise(executor, Blender.of(regionlimitedworldaccess), worldserver.getChunkSource().randomState(), worldserver.structureManager().forWorldGenRegion(regionlimitedworldaccess), ichunkaccess).thenApply((ichunkaccess1) -> { ++ if (ichunkaccess1 instanceof ProtoChunk) { ++ ProtoChunk protochunk = (ProtoChunk) ichunkaccess1; ++ BelowZeroRetrogen belowzeroretrogen = protochunk.getBelowZeroRetrogen(); ++ ++ if (belowzeroretrogen != null) { ++ BelowZeroRetrogen.replaceOldBedrock(protochunk); ++ if (belowzeroretrogen.hasBedrockHoles()) { ++ belowzeroretrogen.applyBedrockMask(protochunk); + } +- +- return Either.left(chunk); +- }); +- } +- ); +- public static final ChunkStatus SURFACE = registerSimple( +- "surface", +- NOISE, +- 8, +- PRE_FEATURES, +- ChunkStatus.ChunkType.PROTOCHUNK, +- (status, serverLevel, chunkGenerator, cache, loadingChunk) -> { +- WorldGenRegion worldGenRegion = new WorldGenRegion(serverLevel, cache, status, 0); +- chunkGenerator.buildSurface( +- worldGenRegion, serverLevel.structureManager().forWorldGenRegion(worldGenRegion), serverLevel.getChunkSource().randomState(), loadingChunk +- ); +- } +- ); +- public static final ChunkStatus CARVERS = registerSimple( +- "carvers", +- SURFACE, +- 8, +- POST_FEATURES, +- ChunkStatus.ChunkType.PROTOCHUNK, +- (status, serverLevel, chunkGenerator, cache, loadingChunk) -> { +- WorldGenRegion worldGenRegion = new WorldGenRegion(serverLevel, cache, status, 0); +- if (loadingChunk instanceof ProtoChunk protoChunk) { +- Blender.addAroundOldChunksCarvingMaskFilter(worldGenRegion, protoChunk); ++ } + } +- +- chunkGenerator.applyCarvers( +- worldGenRegion, +- serverLevel.getSeed(), +- serverLevel.getChunkSource().randomState(), +- serverLevel.getBiomeManager(), +- serverLevel.structureManager().forWorldGenRegion(worldGenRegion), +- loadingChunk, +- GenerationStep.Carving.AIR +- ); ++ ++ return Either.left(ichunkaccess1); ++ }); ++ }); ++ public static final ChunkStatus SURFACE = registerSimple("surface", ChunkStatus.NOISE, 8, ChunkStatus.PRE_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, list, ichunkaccess) -> { ++ WorldGenRegion regionlimitedworldaccess = new WorldGenRegion(worldserver, list, chunkstatus, 0); ++ ++ chunkgenerator.buildSurface(regionlimitedworldaccess, worldserver.structureManager().forWorldGenRegion(regionlimitedworldaccess), worldserver.getChunkSource().randomState(), ichunkaccess); ++ }); ++ public static final ChunkStatus CARVERS = registerSimple("carvers", ChunkStatus.SURFACE, 8, ChunkStatus.POST_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, list, ichunkaccess) -> { ++ WorldGenRegion regionlimitedworldaccess = new WorldGenRegion(worldserver, list, chunkstatus, 0); ++ ++ if (ichunkaccess instanceof ProtoChunk) { ++ ProtoChunk protochunk = (ProtoChunk) ichunkaccess; ++ ++ Blender.addAroundOldChunksCarvingMaskFilter(regionlimitedworldaccess, protochunk); + } +- ); +- public static final ChunkStatus FEATURES = registerSimple( +- "features", +- CARVERS, +- 8, +- POST_FEATURES, +- ChunkStatus.ChunkType.PROTOCHUNK, +- (status, level, chunkGenerator, neighbouringChunks, loadingChunk) -> { +- Heightmap.primeHeightmaps( +- loadingChunk, +- EnumSet.of( +- Heightmap.Types.MOTION_BLOCKING, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, Heightmap.Types.OCEAN_FLOOR, Heightmap.Types.WORLD_SURFACE +- ) +- ); +- WorldGenRegion worldGenRegion = new WorldGenRegion(level, neighbouringChunks, status, 1); +- chunkGenerator.applyBiomeDecoration(worldGenRegion, loadingChunk, level.structureManager().forWorldGenRegion(worldGenRegion)); +- Blender.generateBorderTicks(worldGenRegion, loadingChunk); ++ ++ chunkgenerator.applyCarvers(regionlimitedworldaccess, worldserver.getSeed(), worldserver.getChunkSource().randomState(), worldserver.getBiomeManager(), worldserver.structureManager().forWorldGenRegion(regionlimitedworldaccess), ichunkaccess, GenerationStep.Carving.AIR); ++ }); ++ public static final ChunkStatus FEATURES = registerSimple("features", ChunkStatus.CARVERS, 8, ChunkStatus.POST_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, list, ichunkaccess) -> { ++ Heightmap.primeHeightmaps(ichunkaccess, EnumSet.of(Heightmap.Types.MOTION_BLOCKING, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, Heightmap.Types.OCEAN_FLOOR, Heightmap.Types.WORLD_SURFACE)); ++ WorldGenRegion regionlimitedworldaccess = new WorldGenRegion(worldserver, list, chunkstatus, 1); ++ ++ chunkgenerator.applyBiomeDecoration(regionlimitedworldaccess, ichunkaccess, worldserver.structureManager().forWorldGenRegion(regionlimitedworldaccess)); ++ Blender.generateBorderTicks(regionlimitedworldaccess, ichunkaccess); ++ }); ++ public static final ChunkStatus INITIALIZE_LIGHT = register("initialize_light", ChunkStatus.FEATURES, 0, false, ChunkStatus.POST_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, executor, worldserver, chunkgenerator, structuretemplatemanager, lightenginethreaded, function, list, ichunkaccess) -> { ++ return initializeLight(lightenginethreaded, ichunkaccess); ++ }, (chunkstatus, worldserver, structuretemplatemanager, lightenginethreaded, function, ichunkaccess) -> { ++ return initializeLight(lightenginethreaded, ichunkaccess); ++ }); ++ public static final ChunkStatus LIGHT = register("light", ChunkStatus.INITIALIZE_LIGHT, 1, true, ChunkStatus.POST_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, executor, worldserver, chunkgenerator, structuretemplatemanager, lightenginethreaded, function, list, ichunkaccess) -> { ++ return lightChunk(lightenginethreaded, ichunkaccess); ++ }, (chunkstatus, worldserver, structuretemplatemanager, lightenginethreaded, function, ichunkaccess) -> { ++ return lightChunk(lightenginethreaded, ichunkaccess); ++ }); ++ public static final ChunkStatus SPAWN = registerSimple("spawn", ChunkStatus.LIGHT, 0, ChunkStatus.POST_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, list, ichunkaccess) -> { ++ if (!ichunkaccess.isUpgrading()) { ++ chunkgenerator.spawnOriginalMobs(new WorldGenRegion(worldserver, list, chunkstatus, -1)); + } +- ); +- public static final ChunkStatus INITIALIZE_LIGHT = register( +- "initialize_light", +- FEATURES, +- 0, +- false, +- POST_FEATURES, +- ChunkStatus.ChunkType.PROTOCHUNK, +- (status, executor, level, chunkGenerator, structureTemplateManager, lightEngine, task, cache, loadingChunk) -> initializeLight( +- lightEngine, loadingChunk +- ), +- (status, level, structureTemplateManager, lightEngine, task, chunk) -> initializeLight(lightEngine, chunk) +- ); +- public static final ChunkStatus LIGHT = register( +- "light", +- INITIALIZE_LIGHT, +- 1, +- true, +- POST_FEATURES, +- ChunkStatus.ChunkType.PROTOCHUNK, +- (status, executor, level, chunkGenerator, structureTemplateManager, lightEngine, task, cache, loadingChunk) -> lightChunk(lightEngine, loadingChunk), +- (status, level, structureTemplateManager, lightEngine, task, chunk) -> lightChunk(lightEngine, chunk) +- ); +- public static final ChunkStatus SPAWN = registerSimple( +- "spawn", LIGHT, 0, POST_FEATURES, ChunkStatus.ChunkType.PROTOCHUNK, (status, serverLevel, generator, cache, loadingChunk) -> { +- if (!loadingChunk.isUpgrading()) { +- generator.spawnOriginalMobs(new WorldGenRegion(serverLevel, cache, status, -1)); +- } +- } +- ); +- public static final ChunkStatus FULL = register( +- "full", +- SPAWN, +- 0, +- false, +- POST_FEATURES, +- ChunkStatus.ChunkType.LEVELCHUNK, +- (status, executor, level, chunkGenerator, structureTemplateManager, lightEngine, task, cache, loadingChunk) -> task.apply(loadingChunk), +- (status, level, structureTemplateManager, lightEngine, task, chunk) -> task.apply(chunk) +- ); +- private static final List STATUS_BY_RANGE = ImmutableList.of( +- FULL, +- INITIALIZE_LIGHT, +- CARVERS, +- BIOMES, +- STRUCTURE_STARTS, +- STRUCTURE_STARTS, +- STRUCTURE_STARTS, +- STRUCTURE_STARTS, +- STRUCTURE_STARTS, +- STRUCTURE_STARTS, +- STRUCTURE_STARTS, +- STRUCTURE_STARTS +- ); +- private static final IntList RANGE_BY_STATUS = Util.make(new IntArrayList(getStatusList().size()), list -> { ++ ++ }); ++ public static final ChunkStatus FULL = register("full", ChunkStatus.SPAWN, 0, false, ChunkStatus.POST_FEATURES, ChunkStatus.Type.LEVELCHUNK, (chunkstatus, executor, worldserver, chunkgenerator, structuretemplatemanager, lightenginethreaded, function, list, ichunkaccess) -> { ++ return (CompletableFuture) function.apply(ichunkaccess); ++ }, (chunkstatus, worldserver, structuretemplatemanager, lightenginethreaded, function, ichunkaccess) -> { ++ return (CompletableFuture) function.apply(ichunkaccess); ++ }); ++ private static final List STATUS_BY_RANGE = ImmutableList.of(ChunkStatus.FULL, ChunkStatus.INITIALIZE_LIGHT, ChunkStatus.CARVERS, ChunkStatus.BIOMES, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, ChunkStatus.STRUCTURE_STARTS, new ChunkStatus[0]); ++ private static final IntList RANGE_BY_STATUS = (IntList) Util.make(new IntArrayList(getStatusList().size()), (intarraylist) -> { + int i = 0; + +- for (int i1 = getStatusList().size() - 1; i1 >= 0; i1--) { +- while (i + 1 < STATUS_BY_RANGE.size() && i1 <= STATUS_BY_RANGE.get(i + 1).getIndex()) { +- i++; ++ for (int j = getStatusList().size() - 1; j >= 0; --j) { ++ while (i + 1 < ChunkStatus.STATUS_BY_RANGE.size() && j <= ((ChunkStatus) ChunkStatus.STATUS_BY_RANGE.get(i + 1)).getIndex()) { ++ ++i; + } + +- list.add(0, i); ++ intarraylist.add(0, i); + } ++ + }); + private final int index; + private final ChunkStatus parent; +@@ -246,102 +143,66 @@ + private final ChunkStatus.LoadingTask loadingTask; + private final int range; + private final boolean hasLoadDependencies; +- private final ChunkStatus.ChunkType chunkType; ++ private final ChunkStatus.Type chunkType; + private final EnumSet heightmapsAfter; + +- private static CompletableFuture> initializeLight( +- ThreadedLevelLightEngine lightEngine, ChunkAccess chunk +- ) { ++ private static CompletableFuture> initializeLight(ThreadedLevelLightEngine lightEngine, ChunkAccess chunk) { + chunk.initializeLightSources(); +- ((ProtoChunk)chunk).setLightEngine(lightEngine); +- boolean isLighted = isLighted(chunk); +- return lightEngine.initializeLight(chunk, isLighted).thenApply(Either::left); ++ ((ProtoChunk) chunk).setLightEngine(lightEngine); ++ boolean flag = isLighted(chunk); ++ ++ return lightEngine.initializeLight(chunk, flag).thenApply(Either::left); + } + +- private static CompletableFuture> lightChunk(ThreadedLevelLightEngine lightEngine, ChunkAccess chunk) { +- boolean isLighted = isLighted(chunk); +- return lightEngine.lightChunk(chunk, isLighted).thenApply(Either::left); ++ private static CompletableFuture> lightChunk(ThreadedLevelLightEngine lightEngine, ChunkAccess chunk) { ++ boolean flag = isLighted(chunk); ++ ++ return lightEngine.lightChunk(chunk, flag).thenApply(Either::left); + } + +- private static ChunkStatus registerSimple( +- String key, +- @Nullable ChunkStatus parent, +- int taskRange, +- EnumSet heightmaps, +- ChunkStatus.ChunkType type, +- ChunkStatus.SimpleGenerationTask generationTask +- ) { ++ private static ChunkStatus registerSimple(String key, @Nullable ChunkStatus parent, int taskRange, EnumSet heightmaps, ChunkStatus.Type type, ChunkStatus.SimpleGenerationTask generationTask) { + return register(key, parent, taskRange, heightmaps, type, generationTask); + } + +- private static ChunkStatus register( +- String key, +- @Nullable ChunkStatus parent, +- int taskRange, +- EnumSet heightmaps, +- ChunkStatus.ChunkType type, +- ChunkStatus.GenerationTask generationTask +- ) { +- return register(key, parent, taskRange, false, heightmaps, type, generationTask, PASSTHROUGH_LOAD_TASK); ++ private static ChunkStatus register(String key, @Nullable ChunkStatus parent, int taskRange, EnumSet heightmaps, ChunkStatus.Type type, ChunkStatus.GenerationTask generationTask) { ++ return register(key, parent, taskRange, false, heightmaps, type, generationTask, ChunkStatus.PASSTHROUGH_LOAD_TASK); + } + +- private static ChunkStatus register( +- String key, +- @Nullable ChunkStatus parent, +- int taskRange, +- boolean hasLoadDependencies, +- EnumSet heightmaps, +- ChunkStatus.ChunkType type, +- ChunkStatus.GenerationTask generationTask, +- ChunkStatus.LoadingTask loadingTask +- ) { +- return Registry.register( +- BuiltInRegistries.CHUNK_STATUS, key, new ChunkStatus(parent, taskRange, hasLoadDependencies, heightmaps, type, generationTask, loadingTask) +- ); ++ private static ChunkStatus register(String key, @Nullable ChunkStatus parent, int taskRange, boolean hasLoadDependencies, EnumSet heightmaps, ChunkStatus.Type type, ChunkStatus.GenerationTask generationTask, ChunkStatus.LoadingTask loadingTask) { ++ return (ChunkStatus) Registry.register(BuiltInRegistries.CHUNK_STATUS, key, new ChunkStatus(parent, taskRange, hasLoadDependencies, heightmaps, type, generationTask, loadingTask)); + } + + public static List getStatusList() { + List list = Lists.newArrayList(); + +- ChunkStatus chunkStatus; +- for (chunkStatus = FULL; chunkStatus.getParent() != chunkStatus; chunkStatus = chunkStatus.getParent()) { +- list.add(chunkStatus); ++ ChunkStatus chunkstatus; ++ ++ for (chunkstatus = ChunkStatus.FULL; chunkstatus.getParent() != chunkstatus; chunkstatus = chunkstatus.getParent()) { ++ list.add(chunkstatus); + } + +- list.add(chunkStatus); ++ list.add(chunkstatus); + Collections.reverse(list); + return list; + } + + private static boolean isLighted(ChunkAccess chunk) { +- return chunk.getStatus().isOrAfter(LIGHT) && chunk.isLightCorrect(); ++ return chunk.getStatus().isOrAfter(ChunkStatus.LIGHT) && chunk.isLightCorrect(); + } + + public static ChunkStatus getStatusAroundFullChunk(int radius) { +- if (radius >= STATUS_BY_RANGE.size()) { +- return EMPTY; +- } else { +- return radius < 0 ? FULL : STATUS_BY_RANGE.get(radius); +- } ++ return radius >= ChunkStatus.STATUS_BY_RANGE.size() ? ChunkStatus.EMPTY : (radius < 0 ? ChunkStatus.FULL : (ChunkStatus) ChunkStatus.STATUS_BY_RANGE.get(radius)); + } + + public static int maxDistance() { +- return STATUS_BY_RANGE.size(); ++ return ChunkStatus.STATUS_BY_RANGE.size(); + } + + public static int getDistance(ChunkStatus status) { +- return RANGE_BY_STATUS.getInt(status.getIndex()); ++ return ChunkStatus.RANGE_BY_STATUS.getInt(status.getIndex()); + } + +- ChunkStatus( +- @Nullable ChunkStatus parent, +- int range, +- boolean hasLoadDependencies, +- EnumSet heightmapsAfter, +- ChunkStatus.ChunkType chunkType, +- ChunkStatus.GenerationTask generationTask, +- ChunkStatus.LoadingTask loadingTask +- ) { ++ ChunkStatus(@Nullable ChunkStatus parent, int range, boolean hasLoadDependencies, EnumSet heightmapsAfter, ChunkStatus.Type chunkType, ChunkStatus.GenerationTask generationTask, ChunkStatus.LoadingTask loadingTask) { + this.parent = parent == null ? this : parent; + this.generationTask = generationTask; + this.loadingTask = loadingTask; +@@ -360,40 +221,30 @@ + return this.parent; + } + +- public CompletableFuture> generate( +- Executor exectutor, +- ServerLevel level, +- ChunkGenerator chunkGenerator, +- StructureTemplateManager structureTemplateManager, +- ThreadedLevelLightEngine lightEngine, +- Function>> task, +- List cache +- ) { +- ChunkAccess chunkAccess = cache.get(cache.size() / 2); +- ProfiledDuration profiledDuration = JvmProfiler.INSTANCE.onChunkGenerate(chunkAccess.getPos(), level.dimension(), this.toString()); +- return this.generationTask +- .doWork(this, exectutor, level, chunkGenerator, structureTemplateManager, lightEngine, task, cache, chunkAccess) +- .thenApply(generationResult -> { +- generationResult.ifLeft(chunk -> { +- if (chunk instanceof ProtoChunk protoChunk && !protoChunk.getStatus().isOrAfter(this)) { +- protoChunk.setStatus(this); ++ public CompletableFuture> generate(Executor exectutor, ServerLevel level, ChunkGenerator chunkGenerator, StructureTemplateManager structureTemplateManager, ThreadedLevelLightEngine lightEngine, Function>> task, List cache) { ++ ChunkAccess ichunkaccess = (ChunkAccess) cache.get(cache.size() / 2); ++ ProfiledDuration profiledduration = JvmProfiler.INSTANCE.onChunkGenerate(ichunkaccess.getPos(), level.dimension(), this.toString()); ++ ++ return this.generationTask.doWork(this, exectutor, level, chunkGenerator, structureTemplateManager, lightEngine, task, cache, ichunkaccess).thenApply((either) -> { ++ either.ifLeft((ichunkaccess1) -> { ++ if (ichunkaccess1 instanceof ProtoChunk) { ++ ProtoChunk protochunk = (ProtoChunk) ichunkaccess1; ++ ++ if (!protochunk.getStatus().isOrAfter(this)) { ++ protochunk.setStatus(this); + } +- }); +- if (profiledDuration != null) { +- profiledDuration.finish(); + } +- +- return generationResult; ++ + }); ++ if (profiledduration != null) { ++ profiledduration.finish(); ++ } ++ ++ return either; ++ }); + } + +- public CompletableFuture> load( +- ServerLevel level, +- StructureTemplateManager structureTemplateManager, +- ThreadedLevelLightEngine lightEngine, +- Function>> task, +- ChunkAccess loadingChunk +- ) { ++ public CompletableFuture> load(ServerLevel level, StructureTemplateManager structureTemplateManager, ThreadedLevelLightEngine lightEngine, Function>> task, ChunkAccess loadingChunk) { + return this.loadingTask.doWork(this, level, structureTemplateManager, lightEngine, task, loadingChunk); + } + +@@ -405,12 +256,12 @@ + return this.hasLoadDependencies; + } + +- public ChunkStatus.ChunkType getChunkType() { ++ public ChunkStatus.Type getChunkType() { + return this.chunkType; + } + + public static ChunkStatus byName(String key) { +- return BuiltInRegistries.CHUNK_STATUS.get(ResourceLocation.tryParse(key)); ++ return (ChunkStatus) BuiltInRegistries.CHUNK_STATUS.get(ResourceLocation.tryParse(key)); + } + + public EnumSet heightmapsAfter() { +@@ -421,54 +272,31 @@ + return this.getIndex() >= status.getIndex(); + } + +- @Override + public String toString() { + return BuiltInRegistries.CHUNK_STATUS.getKey(this).toString(); + } + +- public static enum ChunkType { +- PROTOCHUNK, +- LEVELCHUNK; ++ public static enum Type { ++ ++ PROTOCHUNK, LEVELCHUNK; ++ ++ private Type() {} + } + +- interface GenerationTask { +- CompletableFuture> doWork( +- ChunkStatus status, +- Executor executor, +- ServerLevel level, +- ChunkGenerator chunkGenerator, +- StructureTemplateManager structureTemplateManager, +- ThreadedLevelLightEngine lightEngine, +- Function>> task, +- List cache, +- ChunkAccess loadingChunk +- ); ++ private interface GenerationTask { ++ ++ CompletableFuture> doWork(ChunkStatus status, Executor executor, ServerLevel level, ChunkGenerator chunkGenerator, StructureTemplateManager structureTemplateManager, ThreadedLevelLightEngine lightEngine, Function>> task, List cache, ChunkAccess loadingChunk); + } + +- interface LoadingTask { +- CompletableFuture> doWork( +- ChunkStatus status, +- ServerLevel level, +- StructureTemplateManager structureTemplateManager, +- ThreadedLevelLightEngine lightEngine, +- Function>> task, +- ChunkAccess chunk +- ); ++ private interface LoadingTask { ++ ++ CompletableFuture> doWork(ChunkStatus status, ServerLevel level, StructureTemplateManager structureTemplateManager, ThreadedLevelLightEngine lightEngine, Function>> task, ChunkAccess chunk); + } + +- interface SimpleGenerationTask extends ChunkStatus.GenerationTask { ++ private interface SimpleGenerationTask extends ChunkStatus.GenerationTask { ++ + @Override +- default CompletableFuture> doWork( +- ChunkStatus status, +- Executor executor, +- ServerLevel level, +- ChunkGenerator chunkGenerator, +- StructureTemplateManager structureTemplateManager, +- ThreadedLevelLightEngine lightEngine, +- Function>> task, +- List cache, +- ChunkAccess loadingChunk +- ) { ++ default CompletableFuture> doWork(ChunkStatus status, Executor executor, ServerLevel level, ChunkGenerator chunkGenerator, StructureTemplateManager structureTemplateManager, ThreadedLevelLightEngine lightEngine, Function>> task, List cache, ChunkAccess loadingChunk) { + this.doWork(status, level, chunkGenerator, cache, loadingChunk); + return CompletableFuture.completedFuture(Either.left(loadingChunk)); + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/DataLayer.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/DataLayer.java.patch new file mode 100644 index 0000000000..e1b9273e2e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/DataLayer.java.patch @@ -0,0 +1,127 @@ +--- a/net/minecraft/world/level/chunk/DataLayer.java ++++ b/net/minecraft/world/level/chunk/DataLayer.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.world.level.chunk; + + import java.util.Arrays; +@@ -6,6 +7,7 @@ + import net.minecraft.util.VisibleForDebug; + + public class DataLayer { ++ + public static final int LAYER_COUNT = 16; + public static final int LAYER_SIZE = 128; + public static final int SIZE = 2048; +@@ -26,7 +28,7 @@ + this.data = data; + this.defaultValue = 0; + if (data.length != 2048) { +- throw (IllegalArgumentException)Util.pauseInIde(new IllegalArgumentException("DataLayer should be 2048 bytes not: " + data.length)); ++ throw (IllegalArgumentException) Util.pauseInIde(new IllegalArgumentException("DataLayer should be 2048 bytes not: " + data.length)); + } + } + +@@ -46,19 +48,21 @@ + if (this.data == null) { + return this.defaultValue; + } else { +- int byteIndex = getByteIndex(index); +- int nibbleIndex = getNibbleIndex(index); +- return this.data[byteIndex] >> 4 * nibbleIndex & 15; ++ int j = getByteIndex(index); ++ int k = getNibbleIndex(index); ++ ++ return this.data[j] >> 4 * k & 15; + } + } + + private void set(int index, int value) { +- byte[] data = this.getData(); +- int byteIndex = getByteIndex(index); +- int nibbleIndex = getNibbleIndex(index); +- int i = ~(15 << 4 * nibbleIndex); +- int i1 = (value & 15) << 4 * nibbleIndex; +- data[byteIndex] = (byte)(data[byteIndex] & i | i1); ++ byte[] abyte = this.getData(); ++ int k = getByteIndex(index); ++ int l = getNibbleIndex(index); ++ int i1 = ~(15 << 4 * l); ++ int j1 = (value & 15) << 4 * l; ++ ++ abyte[k] = (byte) (abyte[k] & i1 | j1); + } + + private static int getNibbleIndex(int index) { +@@ -75,13 +79,13 @@ + } + + private static byte packFilled(int value) { +- byte b = (byte)value; ++ byte b0 = (byte) value; + +- for (int i = 4; i < 8; i += 4) { +- b = (byte)(b | value << i); ++ for (int j = 4; j < 8; j += 4) { ++ b0 = (byte) (b0 | value << j); + } + +- return b; ++ return b0; + } + + public byte[] getData() { +@@ -96,39 +100,38 @@ + } + + public DataLayer copy() { +- return this.data == null ? new DataLayer(this.defaultValue) : new DataLayer((byte[])this.data.clone()); ++ return this.data == null ? new DataLayer(this.defaultValue) : new DataLayer((byte[]) this.data.clone()); + } + +- @Override + public String toString() { +- StringBuilder stringBuilder = new StringBuilder(); ++ StringBuilder stringbuilder = new StringBuilder(); + +- for (int i = 0; i < 4096; i++) { +- stringBuilder.append(Integer.toHexString(this.get(i))); ++ for (int i = 0; i < 4096; ++i) { ++ stringbuilder.append(Integer.toHexString(this.get(i))); + if ((i & 15) == 15) { +- stringBuilder.append("\n"); ++ stringbuilder.append("\n"); + } + +- if ((i & 0xFF) == 255) { +- stringBuilder.append("\n"); ++ if ((i & 255) == 255) { ++ stringbuilder.append("\n"); + } + } + +- return stringBuilder.toString(); ++ return stringbuilder.toString(); + } + + @VisibleForDebug + public String layerToString(int unused) { +- StringBuilder stringBuilder = new StringBuilder(); ++ StringBuilder stringbuilder = new StringBuilder(); + +- for (int i = 0; i < 256; i++) { +- stringBuilder.append(Integer.toHexString(this.get(i))); +- if ((i & 15) == 15) { +- stringBuilder.append("\n"); ++ for (int j = 0; j < 256; ++j) { ++ stringbuilder.append(Integer.toHexString(this.get(j))); ++ if ((j & 15) == 15) { ++ stringbuilder.append("\n"); + } + } + +- return stringBuilder.toString(); ++ return stringbuilder.toString(); + } + + public boolean isDefinitelyHomogenous() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/LevelChunk.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/LevelChunk.java.patch new file mode 100644 index 0000000000..e759fd10af --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/LevelChunk.java.patch @@ -0,0 +1,1158 @@ +--- a/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/net/minecraft/world/level/chunk/LevelChunk.java +@@ -2,9 +2,12 @@ + + import com.google.common.collect.ImmutableList; + import com.google.common.collect.Maps; ++import com.google.common.collect.UnmodifiableIterator; + import com.mojang.logging.LogUtils; + import it.unimi.dsi.fastutil.ints.Int2ObjectMap; + import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; ++import it.unimi.dsi.fastutil.shorts.ShortListIterator; ++import java.util.Iterator; + import java.util.Map; + import java.util.Map.Entry; + import java.util.function.Consumer; +@@ -33,7 +36,7 @@ + import net.minecraft.world.level.block.entity.BlockEntityTicker; + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.TickingBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.EuclideanGameEventListenerRegistry; + import net.minecraft.world.level.gameevent.GameEventListener; + import net.minecraft.world.level.gameevent.GameEventListenerRegistry; +@@ -49,11 +52,11 @@ + import org.slf4j.Logger; + + public class LevelChunk extends ChunkAccess { ++ + static final Logger LOGGER = LogUtils.getLogger(); + private static final TickingBlockEntity NULL_TICKER = new TickingBlockEntity() { + @Override +- public void tick() { +- } ++ public void tick() {} + + @Override + public boolean isRemoved() { +@@ -70,9 +73,9 @@ + return ""; + } + }; +- private final Map tickersInLevel = Maps.newHashMap(); +- private boolean loaded; +- final Level level; ++ private final Map tickersInLevel; ++ public boolean loaded; ++ public final ServerLevel level; // CraftBukkit - type + @Nullable + private Supplier fullStatus; + @Nullable +@@ -82,70 +85,70 @@ + private final LevelChunkTicks fluidTicks; + + public LevelChunk(Level level, ChunkPos pos) { +- this(level, pos, UpgradeData.EMPTY, new LevelChunkTicks<>(), new LevelChunkTicks<>(), 0L, null, null, null); ++ this(level, pos, UpgradeData.EMPTY, new LevelChunkTicks<>(), new LevelChunkTicks<>(), 0L, (LevelChunkSection[]) null, (LevelChunk.PostLoadProcessor) null, (BlendingData) null); + } + +- public LevelChunk( +- Level level, +- ChunkPos pos, +- UpgradeData data, +- LevelChunkTicks blockTicks, +- LevelChunkTicks fluidTicks, +- long inhabitedTime, +- @Nullable LevelChunkSection[] sections, +- @Nullable LevelChunk.PostLoadProcessor postLoad, +- @Nullable BlendingData blendingData +- ) { +- super(pos, data, level, level.registryAccess().registryOrThrow(Registries.BIOME), inhabitedTime, sections, blendingData); +- this.level = level; +- this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap<>(); ++ public LevelChunk(Level level, ChunkPos pos, UpgradeData data, LevelChunkTicks blockTicks, LevelChunkTicks fluidTicks, long inhabitedTime, @Nullable LevelChunkSection[] achunksection, @Nullable LevelChunk.PostLoadProcessor sections, @Nullable BlendingData postLoad) { ++ super(pos, data, level, level.registryAccess().registryOrThrow(Registries.BIOME), inhabitedTime, achunksection, postLoad); ++ this.tickersInLevel = Maps.newHashMap(); ++ this.level = (ServerLevel) level; // CraftBukkit - type ++ this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap(); ++ Heightmap.Types[] aheightmap_type = Heightmap.Types.values(); ++ int j = aheightmap_type.length; + +- for (Heightmap.Types types : Heightmap.Types.values()) { +- if (ChunkStatus.FULL.heightmapsAfter().contains(types)) { +- this.heightmaps.put(types, new Heightmap(this, types)); ++ for (int k = 0; k < j; ++k) { ++ Heightmap.Types heightmap_type = aheightmap_type[k]; ++ ++ if (ChunkStatus.FULL.heightmapsAfter().contains(heightmap_type)) { ++ this.heightmaps.put(heightmap_type, new Heightmap(this, heightmap_type)); + } + } + +- this.postLoad = postLoad; ++ this.postLoad = sections; + this.blockTicks = blockTicks; + this.fluidTicks = fluidTicks; + } + ++ // CraftBukkit start ++ public boolean mustNotSave; ++ public boolean needsDecoration; ++ // CraftBukkit end ++ + public LevelChunk(ServerLevel level, ProtoChunk chunk, @Nullable LevelChunk.PostLoadProcessor postLoad) { +- this( +- level, +- chunk.getPos(), +- chunk.getUpgradeData(), +- chunk.unpackBlockTicks(), +- chunk.unpackFluidTicks(), +- chunk.getInhabitedTime(), +- chunk.getSections(), +- postLoad, +- chunk.getBlendingData() +- ); ++ this(level, chunk.getPos(), chunk.getUpgradeData(), chunk.unpackBlockTicks(), chunk.unpackFluidTicks(), chunk.getInhabitedTime(), chunk.getSections(), postLoad, chunk.getBlendingData()); ++ Iterator iterator = chunk.getBlockEntities().values().iterator(); + +- for (BlockEntity blockEntity : chunk.getBlockEntities().values()) { +- this.setBlockEntity(blockEntity); ++ while (iterator.hasNext()) { ++ BlockEntity tileentity = (BlockEntity) iterator.next(); ++ ++ this.setBlockEntity(tileentity); + } + + this.pendingBlockEntities.putAll(chunk.getBlockEntityNbts()); + +- for (int i = 0; i < chunk.getPostProcessing().length; i++) { ++ for (int i = 0; i < chunk.getPostProcessing().length; ++i) { + this.postProcessing[i] = chunk.getPostProcessing()[i]; + } + + this.setAllStarts(chunk.getAllStarts()); + this.setAllReferences(chunk.getAllReferences()); ++ iterator = chunk.getHeightmaps().iterator(); + +- for (Entry entry : chunk.getHeightmaps()) { ++ while (iterator.hasNext()) { ++ Entry entry = (Entry) iterator.next(); ++ + if (ChunkStatus.FULL.heightmapsAfter().contains(entry.getKey())) { +- this.setHeightmap(entry.getKey(), entry.getValue().getRawData()); ++ this.setHeightmap((Heightmap.Types) entry.getKey(), ((Heightmap) entry.getValue()).getRawData()); + } + } + + this.skyLightSources = chunk.skyLightSources; + this.setLightCorrect(chunk.isLightCorrect()); + this.unsaved = true; ++ this.needsDecoration = true; // CraftBukkit ++ // CraftBukkit start ++ this.persistentDataContainer = chunk.persistentDataContainer; // SPIGOT-6814: copy PDC to account for 1.17 to 1.18 chunk upgrading. ++ // CraftBukkit end + } + + @Override +@@ -159,50 +162,64 @@ + } + + @Override +- public ChunkAccess.TicksToSave getTicksForSerialization() { +- return new ChunkAccess.TicksToSave(this.blockTicks, this.fluidTicks); ++ public ChunkAccess.a getTicksForSerialization() { ++ return new ChunkAccess.a(this.blockTicks, this.fluidTicks); + } + + @Override + public GameEventListenerRegistry getListenerRegistry(int sectionY) { +- return this.level instanceof ServerLevel serverLevel +- ? this.gameEventListenerRegistrySections +- .computeIfAbsent(sectionY, key -> new EuclideanGameEventListenerRegistry(serverLevel, sectionY, this::removeGameEventListenerRegistry)) +- : super.getListenerRegistry(sectionY); ++ Level world = this.level; ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ ++ return (GameEventListenerRegistry) this.gameEventListenerRegistrySections.computeIfAbsent(sectionY, (j) -> { ++ return new EuclideanGameEventListenerRegistry(worldserver, sectionY, this::removeGameEventListenerRegistry); ++ }); ++ } else { ++ return super.getListenerRegistry(sectionY); ++ } + } + + @Override +- public BlockState getBlockState(BlockPos pos) { +- int x = pos.getX(); +- int y = pos.getY(); +- int z = pos.getZ(); ++ public IBlockData getBlockState(BlockPos pos) { ++ int i = pos.getX(); ++ int j = pos.getY(); ++ int k = pos.getZ(); ++ + if (this.level.isDebug()) { +- BlockState blockState = null; +- if (y == 60) { +- blockState = Blocks.BARRIER.defaultBlockState(); ++ IBlockData iblockdata = null; ++ ++ if (j == 60) { ++ iblockdata = Blocks.BARRIER.defaultBlockState(); + } + +- if (y == 70) { +- blockState = DebugLevelSource.getBlockStateFor(x, z); ++ if (j == 70) { ++ iblockdata = DebugLevelSource.getBlockStateFor(i, k); + } + +- return blockState == null ? Blocks.AIR.defaultBlockState() : blockState; ++ return iblockdata == null ? Blocks.AIR.defaultBlockState() : iblockdata; + } else { + try { +- int sectionIndex = this.getSectionIndex(y); +- if (sectionIndex >= 0 && sectionIndex < this.sections.length) { +- LevelChunkSection levelChunkSection = this.sections[sectionIndex]; +- if (!levelChunkSection.hasOnlyAir()) { +- return levelChunkSection.getBlockState(x & 15, y & 15, z & 15); ++ int l = this.getSectionIndex(j); ++ ++ if (l >= 0 && l < this.sections.length) { ++ LevelChunkSection chunksection = this.sections[l]; ++ ++ if (!chunksection.hasOnlyAir()) { ++ return chunksection.getBlockState(i & 15, j & 15, k & 15); + } + } + + return Blocks.AIR.defaultBlockState(); +- } catch (Throwable var8) { +- CrashReport crashReport = CrashReport.forThrowable(var8, "Getting block state"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Block being got"); +- crashReportCategory.setDetail("Location", () -> CrashReportCategory.formatLocation(this, x, y, z)); +- throw new ReportedException(crashReport); ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting block state"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being got"); ++ ++ crashreportsystemdetails.setDetail("Location", () -> { ++ return CrashReportCategory.formatLocation(this, i, j, k); ++ }); ++ throw new ReportedException(crashreport); + } + } + } +@@ -214,146 +231,180 @@ + + public FluidState getFluidState(int x, int y, int z) { + try { +- int sectionIndex = this.getSectionIndex(y); +- if (sectionIndex >= 0 && sectionIndex < this.sections.length) { +- LevelChunkSection levelChunkSection = this.sections[sectionIndex]; +- if (!levelChunkSection.hasOnlyAir()) { +- return levelChunkSection.getFluidState(x & 15, y & 15, z & 15); ++ int l = this.getSectionIndex(y); ++ ++ if (l >= 0 && l < this.sections.length) { ++ LevelChunkSection chunksection = this.sections[l]; ++ ++ if (!chunksection.hasOnlyAir()) { ++ return chunksection.getFluidState(x & 15, y & 15, z & 15); + } + } + + return Fluids.EMPTY.defaultFluidState(); +- } catch (Throwable var7) { +- CrashReport crashReport = CrashReport.forThrowable(var7, "Getting fluid state"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Block being got"); +- crashReportCategory.setDetail("Location", () -> CrashReportCategory.formatLocation(this, x, y, z)); +- throw new ReportedException(crashReport); ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting fluid state"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being got"); ++ ++ crashreportsystemdetails.setDetail("Location", () -> { ++ return CrashReportCategory.formatLocation(this, x, y, z); ++ }); ++ throw new ReportedException(crashreport); + } + } + ++ // CraftBukkit start + @Nullable + @Override +- public BlockState setBlockState(BlockPos pos, BlockState state, boolean isMoving) { +- int y = pos.getY(); +- LevelChunkSection section = this.getSection(this.getSectionIndex(y)); +- boolean hasOnlyAir = section.hasOnlyAir(); +- if (hasOnlyAir && state.isAir()) { ++ public IBlockData setBlockState(BlockPos pos, IBlockData state, boolean isMoving) { ++ return this.setBlockState(pos, state, isMoving, true); ++ } ++ ++ @Nullable ++ public IBlockData setBlockState(BlockPos blockposition, IBlockData iblockdata, boolean flag, boolean doPlace) { ++ // CraftBukkit end ++ int i = blockposition.getY(); ++ LevelChunkSection chunksection = this.getSection(this.getSectionIndex(i)); ++ boolean flag1 = chunksection.hasOnlyAir(); ++ ++ if (flag1 && iblockdata.isAir()) { + return null; + } else { +- int i = pos.getX() & 15; +- int i1 = y & 15; +- int i2 = pos.getZ() & 15; +- BlockState blockState = section.setBlockState(i, i1, i2, state); +- if (blockState == state) { ++ int j = blockposition.getX() & 15; ++ int k = i & 15; ++ int l = blockposition.getZ() & 15; ++ IBlockData iblockdata1 = chunksection.setBlockState(j, k, l, iblockdata); ++ ++ if (iblockdata1 == iblockdata) { + return null; + } else { +- Block block = state.getBlock(); +- this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING).update(i, y, i2, state); +- this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES).update(i, y, i2, state); +- this.heightmaps.get(Heightmap.Types.OCEAN_FLOOR).update(i, y, i2, state); +- this.heightmaps.get(Heightmap.Types.WORLD_SURFACE).update(i, y, i2, state); +- boolean hasOnlyAir1 = section.hasOnlyAir(); +- if (hasOnlyAir != hasOnlyAir1) { +- this.level.getChunkSource().getLightEngine().updateSectionStatus(pos, hasOnlyAir1); ++ Block block = iblockdata.getBlock(); ++ ++ ((Heightmap) this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING)).update(j, i, l, iblockdata); ++ ((Heightmap) this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES)).update(j, i, l, iblockdata); ++ ((Heightmap) this.heightmaps.get(Heightmap.Types.OCEAN_FLOOR)).update(j, i, l, iblockdata); ++ ((Heightmap) this.heightmaps.get(Heightmap.Types.WORLD_SURFACE)).update(j, i, l, iblockdata); ++ boolean flag2 = chunksection.hasOnlyAir(); ++ ++ if (flag1 != flag2) { ++ this.level.getChunkSource().getLightEngine().updateSectionStatus(blockposition, flag2); + } + +- if (LightEngine.hasDifferentLightProperties(this, pos, blockState, state)) { +- ProfilerFiller profiler = this.level.getProfiler(); +- profiler.push("updateSkyLightSources"); +- this.skyLightSources.update(this, i, y, i2); +- profiler.popPush("queueCheckLight"); +- this.level.getChunkSource().getLightEngine().checkBlock(pos); +- profiler.pop(); ++ if (LightEngine.hasDifferentLightProperties(this, blockposition, iblockdata1, iblockdata)) { ++ ProfilerFiller gameprofilerfiller = this.level.getProfiler(); ++ ++ gameprofilerfiller.push("updateSkyLightSources"); ++ this.skyLightSources.update(this, j, i, l); ++ gameprofilerfiller.popPush("queueCheckLight"); ++ this.level.getChunkSource().getLightEngine().checkBlock(blockposition); ++ gameprofilerfiller.pop(); + } + +- boolean hasBlockEntity = blockState.hasBlockEntity(); ++ boolean flag3 = iblockdata1.hasBlockEntity(); ++ + if (!this.level.isClientSide) { +- blockState.onRemove(this.level, pos, state, isMoving); +- } else if (!blockState.is(block) && hasBlockEntity) { +- this.removeBlockEntity(pos); ++ iblockdata1.onRemove(this.level, blockposition, iblockdata, flag); ++ } else if (!iblockdata1.is(block) && flag3) { ++ this.removeBlockEntity(blockposition); + } + +- if (!section.getBlockState(i, i1, i2).is(block)) { ++ if (!chunksection.getBlockState(j, k, l).is(block)) { + return null; + } else { +- if (!this.level.isClientSide) { +- state.onPlace(this.level, pos, blockState, isMoving); ++ // CraftBukkit - Don't place while processing the BlockPlaceEvent, unless it's a BlockContainer. Prevents blocks such as TNT from activating when cancelled. ++ if (!this.level.isClientSide && doPlace && (!this.level.captureBlockStates || block instanceof net.minecraft.world.level.block.BaseEntityBlock)) { ++ iblockdata.onPlace(this.level, blockposition, iblockdata1, flag); + } + +- if (state.hasBlockEntity()) { +- BlockEntity blockEntity = this.getBlockEntity(pos, LevelChunk.EntityCreationType.CHECK); +- if (blockEntity == null) { +- blockEntity = ((EntityBlock)block).newBlockEntity(pos, state); +- if (blockEntity != null) { +- this.addAndRegisterBlockEntity(blockEntity); ++ if (iblockdata.hasBlockEntity()) { ++ BlockEntity tileentity = this.getBlockEntity(blockposition, LevelChunk.EnumTileEntityState.CHECK); ++ ++ if (tileentity == null) { ++ tileentity = ((EntityBlock) block).newBlockEntity(blockposition, iblockdata); ++ if (tileentity != null) { ++ this.addAndRegisterBlockEntity(tileentity); + } + } else { +- blockEntity.setBlockState(state); +- this.updateBlockEntityTicker(blockEntity); ++ tileentity.setBlockState(iblockdata); ++ this.updateBlockEntityTicker(tileentity); + } + } + + this.unsaved = true; +- return blockState; ++ return iblockdata1; + } + } + } + } + ++ /** @deprecated */ + @Deprecated + @Override +- public void addEntity(Entity entity) { +- } ++ public void addEntity(Entity entity) {} + + @Nullable + private BlockEntity createBlockEntity(BlockPos pos) { +- BlockState blockState = this.getBlockState(pos); +- return !blockState.hasBlockEntity() ? null : ((EntityBlock)blockState.getBlock()).newBlockEntity(pos, blockState); ++ IBlockData iblockdata = this.getBlockState(pos); ++ ++ return !iblockdata.hasBlockEntity() ? null : ((EntityBlock) iblockdata.getBlock()).newBlockEntity(pos, iblockdata); + } + + @Nullable + @Override + public BlockEntity getBlockEntity(BlockPos pos) { +- return this.getBlockEntity(pos, LevelChunk.EntityCreationType.CHECK); ++ return this.getBlockEntity(pos, LevelChunk.EnumTileEntityState.CHECK); + } + + @Nullable +- public BlockEntity getBlockEntity(BlockPos pos, LevelChunk.EntityCreationType creationType) { +- BlockEntity blockEntity = this.blockEntities.get(pos); +- if (blockEntity == null) { +- CompoundTag compoundTag = this.pendingBlockEntities.remove(pos); +- if (compoundTag != null) { +- BlockEntity blockEntity1 = this.promotePendingBlockEntity(pos, compoundTag); +- if (blockEntity1 != null) { +- return blockEntity1; ++ public BlockEntity getBlockEntity(BlockPos pos, LevelChunk.EnumTileEntityState creationType) { ++ // CraftBukkit start ++ BlockEntity tileentity = level.capturedTileEntities.get(pos); ++ if (tileentity == null) { ++ tileentity = (BlockEntity) this.blockEntities.get(pos); ++ } ++ // CraftBukkit end ++ ++ if (tileentity == null) { ++ CompoundTag nbttagcompound = (CompoundTag) this.pendingBlockEntities.remove(pos); ++ ++ if (nbttagcompound != null) { ++ BlockEntity tileentity1 = this.promotePendingBlockEntity(pos, nbttagcompound); ++ ++ if (tileentity1 != null) { ++ return tileentity1; + } + } + } + +- if (blockEntity == null) { +- if (creationType == LevelChunk.EntityCreationType.IMMEDIATE) { +- blockEntity = this.createBlockEntity(pos); +- if (blockEntity != null) { +- this.addAndRegisterBlockEntity(blockEntity); ++ if (tileentity == null) { ++ if (creationType == LevelChunk.EnumTileEntityState.IMMEDIATE) { ++ tileentity = this.createBlockEntity(pos); ++ if (tileentity != null) { ++ this.addAndRegisterBlockEntity(tileentity); + } + } +- } else if (blockEntity.isRemoved()) { ++ } else if (tileentity.isRemoved()) { + this.blockEntities.remove(pos); + return null; + } + +- return blockEntity; ++ return tileentity; + } + + public void addAndRegisterBlockEntity(BlockEntity blockEntity) { + this.setBlockEntity(blockEntity); + if (this.isInLevel()) { +- if (this.level instanceof ServerLevel serverLevel) { +- this.addGameEventListener(blockEntity, serverLevel); ++ Level world = this.level; ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ ++ this.addGameEventListener(blockEntity, worldserver); + } + + this.updateBlockEntityTicker(blockEntity); + } ++ + } + + private boolean isInLevel() { +@@ -361,55 +412,86 @@ + } + + boolean isTicking(BlockPos pos) { +- return this.level.getWorldBorder().isWithinBounds(pos) +- && ( +- !(this.level instanceof ServerLevel serverLevel) +- || this.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING) && serverLevel.areEntitiesLoaded(ChunkPos.asLong(pos)) +- ); ++ if (!this.level.getWorldBorder().isWithinBounds(pos)) { ++ return false; ++ } else { ++ Level world = this.level; ++ ++ if (!(world instanceof ServerLevel)) { ++ return true; ++ } else { ++ ServerLevel worldserver = (ServerLevel) world; ++ ++ return this.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING) && worldserver.areEntitiesLoaded(ChunkPos.asLong(pos)); ++ } ++ } + } + + @Override + public void setBlockEntity(BlockEntity blockEntity) { +- BlockPos blockPos = blockEntity.getBlockPos(); +- if (this.getBlockState(blockPos).hasBlockEntity()) { ++ BlockPos blockposition = blockEntity.getBlockPos(); ++ ++ if (this.getBlockState(blockposition).hasBlockEntity()) { + blockEntity.setLevel(this.level); + blockEntity.clearRemoved(); +- BlockEntity blockEntity1 = this.blockEntities.put(blockPos.immutable(), blockEntity); +- if (blockEntity1 != null && blockEntity1 != blockEntity) { +- blockEntity1.setRemoved(); ++ BlockEntity tileentity1 = (BlockEntity) this.blockEntities.put(blockposition.immutable(), blockEntity); ++ ++ if (tileentity1 != null && tileentity1 != blockEntity) { ++ tileentity1.setRemoved(); + } ++ ++ // CraftBukkit start ++ } else { ++ System.out.println("Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() ++ + " (" + getBlockState(blockposition) + ") where there was no entity tile!"); ++ System.out.println("Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); ++ new Exception().printStackTrace(); ++ // CraftBukkit end + } + } + + @Nullable + @Override + public CompoundTag getBlockEntityNbtForSaving(BlockPos pos) { +- BlockEntity blockEntity = this.getBlockEntity(pos); +- if (blockEntity != null && !blockEntity.isRemoved()) { +- CompoundTag compoundTag = blockEntity.saveWithFullMetadata(); +- compoundTag.putBoolean("keepPacked", false); +- return compoundTag; ++ BlockEntity tileentity = this.getBlockEntity(pos); ++ CompoundTag nbttagcompound; ++ ++ if (tileentity != null && !tileentity.isRemoved()) { ++ nbttagcompound = tileentity.saveWithFullMetadata(); ++ nbttagcompound.putBoolean("keepPacked", false); ++ return nbttagcompound; + } else { +- CompoundTag compoundTag = this.pendingBlockEntities.get(pos); +- if (compoundTag != null) { +- compoundTag = compoundTag.copy(); +- compoundTag.putBoolean("keepPacked", true); ++ nbttagcompound = (CompoundTag) this.pendingBlockEntities.get(pos); ++ if (nbttagcompound != null) { ++ nbttagcompound = nbttagcompound.copy(); ++ nbttagcompound.putBoolean("keepPacked", true); + } + +- return compoundTag; ++ return nbttagcompound; + } + } + + @Override + public void removeBlockEntity(BlockPos pos) { + if (this.isInLevel()) { +- BlockEntity blockEntity = this.blockEntities.remove(pos); +- if (blockEntity != null) { +- if (this.level instanceof ServerLevel serverLevel) { +- this.removeGameEventListener(blockEntity, serverLevel); ++ BlockEntity tileentity = (BlockEntity) this.blockEntities.remove(pos); ++ ++ // CraftBukkit start - SPIGOT-5561: Also remove from pending map ++ if (!pendingBlockEntities.isEmpty()) { ++ pendingBlockEntities.remove(pos); ++ } ++ // CraftBukkit end ++ ++ if (tileentity != null) { ++ Level world = this.level; ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ ++ this.removeGameEventListener(tileentity, worldserver); + } + +- blockEntity.setRemoved(); ++ tileentity.setRemoved(); + } + } + +@@ -418,14 +500,18 @@ + + private void removeGameEventListener(T blockEntity, ServerLevel level) { + Block block = blockEntity.getBlockState().getBlock(); ++ + if (block instanceof EntityBlock) { +- GameEventListener listener = ((EntityBlock)block).getListener(level, blockEntity); +- if (listener != null) { ++ GameEventListener gameeventlistener = ((EntityBlock) block).getListener(level, blockEntity); ++ ++ if (gameeventlistener != null) { + int i = SectionPos.blockToSectionCoord(blockEntity.getBlockPos().getY()); +- GameEventListenerRegistry listenerRegistry = this.getListenerRegistry(i); +- listenerRegistry.unregister(listener); ++ GameEventListenerRegistry gameeventlistenerregistry = this.getListenerRegistry(i); ++ ++ gameeventlistenerregistry.unregister(gameeventlistener); + } + } ++ + } + + private void removeGameEventListenerRegistry(int sectionY) { +@@ -433,10 +519,12 @@ + } + + private void removeBlockEntityTicker(BlockPos pos) { +- LevelChunk.RebindableTickingBlockEntityWrapper rebindableTickingBlockEntityWrapper = this.tickersInLevel.remove(pos); +- if (rebindableTickingBlockEntityWrapper != null) { +- rebindableTickingBlockEntityWrapper.rebind(NULL_TICKER); ++ LevelChunk.RebindableTickingBlockEntityWrapper chunk_d = (LevelChunk.RebindableTickingBlockEntityWrapper) this.tickersInLevel.remove(pos); ++ ++ if (chunk_d != null) { ++ chunk_d.rebind(LevelChunk.NULL_TICKER); + } ++ + } + + public void runPostLoad() { +@@ -444,39 +532,111 @@ + this.postLoad.run(this); + this.postLoad = null; + } ++ + } + ++ // CraftBukkit start ++ public void loadCallback() { ++ org.bukkit.Server server = this.level.getCraftServer(); ++ if (server != null) { ++ /* ++ * If it's a new world, the first few chunks are generated inside ++ * the World constructor. We can't reliably alter that, so we have ++ * no way of creating a CraftWorld/CraftServer at that point. ++ */ ++ org.bukkit.Chunk bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this); ++ server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(bukkitChunk, this.needsDecoration)); ++ ++ if (this.needsDecoration) { ++ this.needsDecoration = false; ++ java.util.Random random = new java.util.Random(); ++ random.setSeed(level.getSeed()); ++ long xRand = random.nextLong() / 2L * 2L + 1L; ++ long zRand = random.nextLong() / 2L * 2L + 1L; ++ random.setSeed((long) this.chunkPos.x * xRand + (long) this.chunkPos.z * zRand ^ level.getSeed()); ++ ++ org.bukkit.World world = this.level.getWorld(); ++ if (world != null) { ++ this.level.populating = true; ++ try { ++ for (org.bukkit.generator.BlockPopulator populator : world.getPopulators()) { ++ populator.populate(world, random, bukkitChunk); ++ } ++ } finally { ++ this.level.populating = false; ++ } ++ } ++ server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk)); ++ } ++ } ++ } ++ ++ public void unloadCallback() { ++ org.bukkit.Server server = this.level.getCraftServer(); ++ org.bukkit.Chunk bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this); ++ org.bukkit.event.world.ChunkUnloadEvent unloadEvent = new org.bukkit.event.world.ChunkUnloadEvent(bukkitChunk, this.isUnsaved()); ++ server.getPluginManager().callEvent(unloadEvent); ++ // note: saving can be prevented, but not forced if no saving is actually required ++ this.mustNotSave = !unloadEvent.isSaveChunk(); ++ } ++ ++ @Override ++ public boolean isUnsaved() { ++ return super.isUnsaved() && !this.mustNotSave; ++ } ++ // CraftBukkit end ++ + public boolean isEmpty() { + return false; + } + + public void replaceWithPacketData(FriendlyByteBuf buffer, CompoundTag tag, Consumer outputTagConsumer) { + this.clearAllBlockEntities(); ++ LevelChunkSection[] achunksection = this.sections; ++ int i = achunksection.length; + +- for (LevelChunkSection levelChunkSection : this.sections) { +- levelChunkSection.read(buffer); ++ int j; ++ ++ for (j = 0; j < i; ++j) { ++ LevelChunkSection chunksection = achunksection[j]; ++ ++ chunksection.read(buffer); + } + +- for (Heightmap.Types types : Heightmap.Types.values()) { +- String serializationKey = types.getSerializationKey(); +- if (tag.contains(serializationKey, 12)) { +- this.setHeightmap(types, tag.getLongArray(serializationKey)); ++ Heightmap.Types[] aheightmap_type = Heightmap.Types.values(); ++ ++ i = aheightmap_type.length; ++ ++ for (j = 0; j < i; ++j) { ++ Heightmap.Types heightmap_type = aheightmap_type[j]; ++ String s = heightmap_type.getSerializationKey(); ++ ++ if (tag.contains(s, 12)) { ++ this.setHeightmap(heightmap_type, tag.getLongArray(s)); + } + } + + this.initializeLightSources(); +- outputTagConsumer.accept((pos, type, tag1) -> { +- BlockEntity blockEntity = this.getBlockEntity(pos, LevelChunk.EntityCreationType.IMMEDIATE); +- if (blockEntity != null && tag1 != null && blockEntity.getType() == type) { +- blockEntity.load(tag1); ++ outputTagConsumer.accept((blockposition, tileentitytypes, nbttagcompound1) -> { ++ BlockEntity tileentity = this.getBlockEntity(blockposition, LevelChunk.EnumTileEntityState.IMMEDIATE); ++ ++ if (tileentity != null && nbttagcompound1 != null && tileentity.getType() == tileentitytypes) { ++ tileentity.load(nbttagcompound1); + } ++ + }); + } + + public void replaceBiomes(FriendlyByteBuf buffer) { +- for (LevelChunkSection levelChunkSection : this.sections) { +- levelChunkSection.readBiomes(buffer); ++ LevelChunkSection[] achunksection = this.sections; ++ int i = achunksection.length; ++ ++ for (int j = 0; j < i; ++j) { ++ LevelChunkSection chunksection = achunksection[j]; ++ ++ chunksection.readBiomes(buffer); + } ++ + } + + public void setLoaded(boolean loaded) { +@@ -492,21 +652,26 @@ + } + + public void postProcessGeneration() { +- ChunkPos pos = this.getPos(); ++ ChunkPos chunkcoordintpair = this.getPos(); + +- for (int i = 0; i < this.postProcessing.length; i++) { ++ for (int i = 0; i < this.postProcessing.length; ++i) { + if (this.postProcessing[i] != null) { +- for (Short _short : this.postProcessing[i]) { +- BlockPos blockPos = ProtoChunk.unpackOffsetCoordinates(_short, this.getSectionYFromSectionIndex(i), pos); +- BlockState blockState = this.getBlockState(blockPos); +- FluidState fluidState = blockState.getFluidState(); +- if (!fluidState.isEmpty()) { +- fluidState.tick(this.level, blockPos); ++ ShortListIterator shortlistiterator = this.postProcessing[i].iterator(); ++ ++ while (shortlistiterator.hasNext()) { ++ Short oshort = (Short) shortlistiterator.next(); ++ BlockPos blockposition = ProtoChunk.unpackOffsetCoordinates(oshort, this.getSectionYFromSectionIndex(i), chunkcoordintpair); ++ IBlockData iblockdata = this.getBlockState(blockposition); ++ FluidState fluid = iblockdata.getFluidState(); ++ ++ if (!fluid.isEmpty()) { ++ fluid.tick(this.level, blockposition); + } + +- if (!(blockState.getBlock() instanceof LiquidBlock)) { +- BlockState blockState1 = Block.updateFromNeighbourShapes(blockState, this.level, blockPos); +- this.level.setBlock(blockPos, blockState1, 20); ++ if (!(iblockdata.getBlock() instanceof LiquidBlock)) { ++ IBlockData iblockdata1 = Block.updateFromNeighbourShapes(iblockdata, this.level, blockposition); ++ ++ this.level.setBlock(blockposition, iblockdata1, 20); + } + } + +@@ -514,8 +679,12 @@ + } + } + +- for (BlockPos blockPos1 : ImmutableList.copyOf(this.pendingBlockEntities.keySet())) { +- this.getBlockEntity(blockPos1); ++ UnmodifiableIterator unmodifiableiterator = ImmutableList.copyOf(this.pendingBlockEntities.keySet()).iterator(); ++ ++ while (unmodifiableiterator.hasNext()) { ++ BlockPos blockposition1 = (BlockPos) unmodifiableiterator.next(); ++ ++ this.getBlockEntity(blockposition1); + } + + this.pendingBlockEntities.clear(); +@@ -524,27 +693,28 @@ + + @Nullable + private BlockEntity promotePendingBlockEntity(BlockPos pos, CompoundTag tag) { +- BlockState blockState = this.getBlockState(pos); +- BlockEntity blockEntity; ++ IBlockData iblockdata = this.getBlockState(pos); ++ BlockEntity tileentity; ++ + if ("DUMMY".equals(tag.getString("id"))) { +- if (blockState.hasBlockEntity()) { +- blockEntity = ((EntityBlock)blockState.getBlock()).newBlockEntity(pos, blockState); ++ if (iblockdata.hasBlockEntity()) { ++ tileentity = ((EntityBlock) iblockdata.getBlock()).newBlockEntity(pos, iblockdata); + } else { +- blockEntity = null; +- LOGGER.warn("Tried to load a DUMMY block entity @ {} but found not block entity block {} at location", pos, blockState); ++ tileentity = null; ++ LevelChunk.LOGGER.warn("Tried to load a DUMMY block entity @ {} but found not block entity block {} at location", pos, iblockdata); + } + } else { +- blockEntity = BlockEntity.loadStatic(pos, blockState, tag); ++ tileentity = BlockEntity.loadStatic(pos, iblockdata, tag); + } + +- if (blockEntity != null) { +- blockEntity.setLevel(this.level); +- this.addAndRegisterBlockEntity(blockEntity); ++ if (tileentity != null) { ++ tileentity.setLevel(this.level); ++ this.addAndRegisterBlockEntity(tileentity); + } else { +- LOGGER.warn("Tried to load a block entity for block {} but failed at location {}", blockState, pos); ++ LevelChunk.LOGGER.warn("Tried to load a block entity for block {} but failed at location {}", iblockdata, pos); + } + +- return blockEntity; ++ return tileentity; + } + + public void unpackTicks(long pos) { +@@ -568,7 +738,7 @@ + } + + public FullChunkStatus getFullStatus() { +- return this.fullStatus == null ? FullChunkStatus.FULL : this.fullStatus.get(); ++ return this.fullStatus == null ? FullChunkStatus.FULL : (FullChunkStatus) this.fullStatus.get(); + } + + public void setFullStatus(Supplier fullStatus) { +@@ -578,172 +748,182 @@ + public void clearAllBlockEntities() { + this.blockEntities.values().forEach(BlockEntity::setRemoved); + this.blockEntities.clear(); +- this.tickersInLevel.values().forEach(blockEntityWrapper -> blockEntityWrapper.rebind(NULL_TICKER)); ++ this.tickersInLevel.values().forEach((chunk_d) -> { ++ chunk_d.rebind(LevelChunk.NULL_TICKER); ++ }); + this.tickersInLevel.clear(); + } + + public void registerAllBlockEntitiesAfterLevelLoad() { +- this.blockEntities.values().forEach(blockEntity -> { +- if (this.level instanceof ServerLevel serverLevel) { +- this.addGameEventListener(blockEntity, serverLevel); ++ this.blockEntities.values().forEach((tileentity) -> { ++ Level world = this.level; ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ ++ this.addGameEventListener(tileentity, worldserver); + } + +- this.updateBlockEntityTicker(blockEntity); ++ this.updateBlockEntityTicker(tileentity); + }); + } + + private void addGameEventListener(T blockEntity, ServerLevel level) { + Block block = blockEntity.getBlockState().getBlock(); ++ + if (block instanceof EntityBlock) { +- GameEventListener listener = ((EntityBlock)block).getListener(level, blockEntity); +- if (listener != null) { +- this.getListenerRegistry(SectionPos.blockToSectionCoord(blockEntity.getBlockPos().getY())).register(listener); ++ GameEventListener gameeventlistener = ((EntityBlock) block).getListener(level, blockEntity); ++ ++ if (gameeventlistener != null) { ++ this.getListenerRegistry(SectionPos.blockToSectionCoord(blockEntity.getBlockPos().getY())).register(gameeventlistener); + } + } ++ + } + + private void updateBlockEntityTicker(T blockEntity) { +- BlockState blockState = blockEntity.getBlockState(); +- BlockEntityTicker ticker = blockState.getTicker(this.level, (BlockEntityType)blockEntity.getType()); +- if (ticker == null) { ++ IBlockData iblockdata = blockEntity.getBlockState(); ++ BlockEntityTicker blockentityticker = iblockdata.getTicker(this.level, (BlockEntityType) blockEntity.getType()); // CraftBukkit - decompile error ++ ++ if (blockentityticker == null) { + this.removeBlockEntityTicker(blockEntity.getBlockPos()); + } else { +- this.tickersInLevel +- .compute( +- blockEntity.getBlockPos(), +- (keyBlockPos, blockEntityWrapper) -> { +- TickingBlockEntity tickingBlockEntity = this.createTicker(blockEntity, ticker); +- if (blockEntityWrapper != null) { +- blockEntityWrapper.rebind(tickingBlockEntity); +- return (LevelChunk.RebindableTickingBlockEntityWrapper)blockEntityWrapper; +- } else if (this.isInLevel()) { +- LevelChunk.RebindableTickingBlockEntityWrapper rebindableTickingBlockEntityWrapper = new LevelChunk.RebindableTickingBlockEntityWrapper( +- tickingBlockEntity +- ); +- this.level.addBlockEntityTicker(rebindableTickingBlockEntityWrapper); +- return rebindableTickingBlockEntityWrapper; +- } else { +- return null; +- } +- } +- ); ++ this.tickersInLevel.compute(blockEntity.getBlockPos(), (blockposition, chunk_d) -> { ++ TickingBlockEntity tickingblockentity = this.createTicker(blockEntity, blockentityticker); ++ ++ if (chunk_d != null) { ++ chunk_d.rebind(tickingblockentity); ++ return chunk_d; ++ } else if (this.isInLevel()) { ++ LevelChunk.RebindableTickingBlockEntityWrapper chunk_d1 = new LevelChunk.RebindableTickingBlockEntityWrapper(tickingblockentity); ++ ++ this.level.addBlockEntityTicker(chunk_d1); ++ return chunk_d1; ++ } else { ++ return null; ++ } ++ }); + } ++ + } + + private TickingBlockEntity createTicker(T blockEntity, BlockEntityTicker ticker) { + return new LevelChunk.BoundTickingBlockEntity<>(blockEntity, ticker); + } + +- class BoundTickingBlockEntity implements TickingBlockEntity { +- private final T blockEntity; +- private final BlockEntityTicker ticker; +- private boolean loggedInvalidBlockState; ++ @FunctionalInterface ++ public interface PostLoadProcessor { + +- BoundTickingBlockEntity(T blockEntity, BlockEntityTicker ticker) { +- this.blockEntity = blockEntity; ++ void run(LevelChunk chunk); ++ } ++ ++ public static enum EnumTileEntityState { ++ ++ IMMEDIATE, QUEUED, CHECK; ++ ++ private EnumTileEntityState() {} ++ } ++ ++ private class RebindableTickingBlockEntityWrapper implements TickingBlockEntity { ++ ++ private TickingBlockEntity ticker; ++ ++ RebindableTickingBlockEntityWrapper(TickingBlockEntity tickingblockentity) { ++ this.ticker = tickingblockentity; ++ } ++ ++ void rebind(TickingBlockEntity ticker) { + this.ticker = ticker; + } + + @Override + public void tick() { +- if (!this.blockEntity.isRemoved() && this.blockEntity.hasLevel()) { +- BlockPos blockPos = this.blockEntity.getBlockPos(); +- if (LevelChunk.this.isTicking(blockPos)) { +- try { +- ProfilerFiller profiler = LevelChunk.this.level.getProfiler(); +- profiler.push(this::getType); +- BlockState blockState = LevelChunk.this.getBlockState(blockPos); +- if (this.blockEntity.getType().isValid(blockState)) { +- this.ticker.tick(LevelChunk.this.level, this.blockEntity.getBlockPos(), blockState, this.blockEntity); +- this.loggedInvalidBlockState = false; +- } else if (!this.loggedInvalidBlockState) { +- this.loggedInvalidBlockState = true; +- LevelChunk.LOGGER +- .warn( +- "Block entity {} @ {} state {} invalid for ticking:", +- LogUtils.defer(this::getType), +- LogUtils.defer(this::getPos), +- blockState +- ); +- } +- +- profiler.pop(); +- } catch (Throwable var5) { +- CrashReport crashReport = CrashReport.forThrowable(var5, "Ticking block entity"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Block entity being ticked"); +- this.blockEntity.fillCrashReportCategory(crashReportCategory); +- throw new ReportedException(crashReport); +- } +- } +- } ++ this.ticker.tick(); + } + + @Override + public boolean isRemoved() { +- return this.blockEntity.isRemoved(); ++ return this.ticker.isRemoved(); + } + + @Override + public BlockPos getPos() { +- return this.blockEntity.getBlockPos(); ++ return this.ticker.getPos(); + } + + @Override + public String getType() { +- return BlockEntityType.getKey(this.blockEntity.getType()).toString(); ++ return this.ticker.getType(); + } + +- @Override + public String toString() { +- return "Level ticker for " + this.getType() + "@" + this.getPos(); ++ return this.ticker + " "; + } + } + +- public static enum EntityCreationType { +- IMMEDIATE, +- QUEUED, +- CHECK; +- } ++ private class BoundTickingBlockEntity implements TickingBlockEntity { + +- @FunctionalInterface +- public interface PostLoadProcessor { +- void run(LevelChunk chunk); +- } ++ private final T blockEntity; ++ private final BlockEntityTicker ticker; ++ private boolean loggedInvalidBlockState; + +- class RebindableTickingBlockEntityWrapper implements TickingBlockEntity { +- private TickingBlockEntity ticker; +- +- RebindableTickingBlockEntityWrapper(TickingBlockEntity ticker) { +- this.ticker = ticker; ++ BoundTickingBlockEntity(BlockEntity tileentity, BlockEntityTicker blockentityticker) { ++ this.blockEntity = (T) tileentity; // CraftBukkit - decompile error ++ this.ticker = blockentityticker; + } + +- void rebind(TickingBlockEntity ticker) { +- this.ticker = ticker; +- } +- + @Override + public void tick() { +- this.ticker.tick(); ++ if (!this.blockEntity.isRemoved() && this.blockEntity.hasLevel()) { ++ BlockPos blockposition = this.blockEntity.getBlockPos(); ++ ++ if (LevelChunk.this.isTicking(blockposition)) { ++ try { ++ ProfilerFiller gameprofilerfiller = LevelChunk.this.level.getProfiler(); ++ ++ gameprofilerfiller.push(this::getType); ++ IBlockData iblockdata = LevelChunk.this.getBlockState(blockposition); ++ ++ if (this.blockEntity.getType().isValid(iblockdata)) { ++ this.ticker.tick(LevelChunk.this.level, this.blockEntity.getBlockPos(), iblockdata, this.blockEntity); ++ this.loggedInvalidBlockState = false; ++ } else if (!this.loggedInvalidBlockState) { ++ this.loggedInvalidBlockState = true; ++ LevelChunk.LOGGER.warn("Block entity {} @ {} state {} invalid for ticking:", new Object[]{LogUtils.defer(this::getType), LogUtils.defer(this::getPos), iblockdata}); ++ } ++ ++ gameprofilerfiller.pop(); ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking block entity"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block entity being ticked"); ++ ++ this.blockEntity.fillCrashReportCategory(crashreportsystemdetails); ++ throw new ReportedException(crashreport); ++ } ++ } ++ } ++ + } + + @Override + public boolean isRemoved() { +- return this.ticker.isRemoved(); ++ return this.blockEntity.isRemoved(); + } + + @Override + public BlockPos getPos() { +- return this.ticker.getPos(); ++ return this.blockEntity.getBlockPos(); + } + + @Override + public String getType() { +- return this.ticker.getType(); ++ return BlockEntityType.getKey(this.blockEntity.getType()).toString(); + } + +- @Override + public String toString() { +- return this.ticker + " "; ++ String s = this.getType(); ++ ++ return "Level ticker for " + s + "@" + this.getPos(); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/LevelChunkSection.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/LevelChunkSection.java.patch new file mode 100644 index 0000000000..049fb81d34 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/LevelChunkSection.java.patch @@ -0,0 +1,247 @@ +--- a/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -10,10 +10,11 @@ + import net.minecraft.world.level.biome.Climate; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; + + public class LevelChunkSection { ++ + public static final int SECTION_WIDTH = 16; + public static final int SECTION_HEIGHT = 16; + public static final int SECTION_SIZE = 4096; +@@ -21,28 +22,28 @@ + private short nonEmptyBlockCount; + private short tickingBlockCount; + private short tickingFluidCount; +- private final PalettedContainer states; +- private PalettedContainerRO> biomes; ++ private final PalettedContainer states; ++ // CraftBukkit start - read/write ++ private PalettedContainer> biomes; + +- public LevelChunkSection(PalettedContainer states, PalettedContainerRO> biomes) { +- this.states = states; +- this.biomes = biomes; ++ public LevelChunkSection(PalettedContainer datapaletteblock, PalettedContainer> palettedcontainerro) { ++ // CraftBukkit end ++ this.states = datapaletteblock; ++ this.biomes = palettedcontainerro; + this.recalcBlockCounts(); + } + + public LevelChunkSection(Registry biomeRegistry) { + this.states = new PalettedContainer<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES); +- this.biomes = new PalettedContainer<>( +- biomeRegistry.asHolderIdMap(), biomeRegistry.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES +- ); ++ this.biomes = new PalettedContainer<>(biomeRegistry.asHolderIdMap(), biomeRegistry.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES); + } + +- public BlockState getBlockState(int x, int y, int z) { +- return this.states.get(x, y, z); ++ public IBlockData getBlockState(int x, int y, int z) { ++ return (IBlockData) this.states.get(x, y, z); + } + + public FluidState getFluidState(int x, int y, int z) { +- return this.states.get(x, y, z).getFluidState(); ++ return ((IBlockData) this.states.get(x, y, z)).getFluidState(); + } + + public void acquire() { +@@ -53,43 +54,45 @@ + this.states.release(); + } + +- public BlockState setBlockState(int x, int y, int z, BlockState state) { ++ public IBlockData setBlockState(int x, int y, int z, IBlockData state) { + return this.setBlockState(x, y, z, state, true); + } + +- public BlockState setBlockState(int x, int y, int z, BlockState state, boolean useLocks) { +- BlockState blockState; ++ public IBlockData setBlockState(int x, int y, int z, IBlockData state, boolean useLocks) { ++ IBlockData iblockdata1; ++ + if (useLocks) { +- blockState = this.states.getAndSet(x, y, z, state); ++ iblockdata1 = (IBlockData) this.states.getAndSet(x, y, z, state); + } else { +- blockState = this.states.getAndSetUnchecked(x, y, z, state); ++ iblockdata1 = (IBlockData) this.states.getAndSetUnchecked(x, y, z, state); + } + +- FluidState fluidState = blockState.getFluidState(); +- FluidState fluidState1 = state.getFluidState(); +- if (!blockState.isAir()) { +- this.nonEmptyBlockCount--; +- if (blockState.isRandomlyTicking()) { +- this.tickingBlockCount--; ++ FluidState fluid = iblockdata1.getFluidState(); ++ FluidState fluid1 = state.getFluidState(); ++ ++ if (!iblockdata1.isAir()) { ++ --this.nonEmptyBlockCount; ++ if (iblockdata1.isRandomlyTicking()) { ++ --this.tickingBlockCount; + } + } + +- if (!fluidState.isEmpty()) { +- this.tickingFluidCount--; ++ if (!fluid.isEmpty()) { ++ --this.tickingFluidCount; + } + + if (!state.isAir()) { +- this.nonEmptyBlockCount++; ++ ++this.nonEmptyBlockCount; + if (state.isRandomlyTicking()) { +- this.tickingBlockCount++; ++ ++this.tickingBlockCount; + } + } + +- if (!fluidState1.isEmpty()) { +- this.tickingFluidCount++; ++ if (!fluid1.isEmpty()) { ++ ++this.tickingFluidCount; + } + +- return blockState; ++ return iblockdata1; + } + + public boolean hasOnlyAir() { +@@ -109,38 +112,43 @@ + } + + public void recalcBlockCounts() { +- class BlockCounter implements PalettedContainer.CountConsumer { ++ class a implements PalettedContainer.CountConsumer { ++ + public int nonEmptyBlockCount; + public int tickingBlockCount; + public int tickingFluidCount; + +- @Override +- public void accept(BlockState state, int count) { +- FluidState fluidState = state.getFluidState(); +- if (!state.isAir()) { +- this.nonEmptyBlockCount += count; +- if (state.isRandomlyTicking()) { +- this.tickingBlockCount += count; ++ a() {} ++ ++ public void accept(IBlockData iblockdata, int i) { ++ FluidState fluid = iblockdata.getFluidState(); ++ ++ if (!iblockdata.isAir()) { ++ this.nonEmptyBlockCount += i; ++ if (iblockdata.isRandomlyTicking()) { ++ this.tickingBlockCount += i; + } + } + +- if (!fluidState.isEmpty()) { +- this.nonEmptyBlockCount += count; +- if (fluidState.isRandomlyTicking()) { +- this.tickingFluidCount += count; ++ if (!fluid.isEmpty()) { ++ this.nonEmptyBlockCount += i; ++ if (fluid.isRandomlyTicking()) { ++ this.tickingFluidCount += i; + } + } ++ + } + } + +- BlockCounter blockCounter = new BlockCounter(); +- this.states.count(blockCounter); +- this.nonEmptyBlockCount = (short)blockCounter.nonEmptyBlockCount; +- this.tickingBlockCount = (short)blockCounter.tickingBlockCount; +- this.tickingFluidCount = (short)blockCounter.tickingFluidCount; ++ a a0 = new a(); ++ ++ this.states.count(a0); ++ this.nonEmptyBlockCount = (short) a0.nonEmptyBlockCount; ++ this.tickingBlockCount = (short) a0.tickingBlockCount; ++ this.tickingFluidCount = (short) a0.tickingFluidCount; + } + +- public PalettedContainer getStates() { ++ public PalettedContainer getStates() { + return this.states; + } + +@@ -151,15 +159,17 @@ + public void read(FriendlyByteBuf buffer) { + this.nonEmptyBlockCount = buffer.readShort(); + this.states.read(buffer); +- PalettedContainer> palettedContainer = this.biomes.recreate(); +- palettedContainer.read(buffer); +- this.biomes = palettedContainer; ++ PalettedContainer> datapaletteblock = this.biomes.recreate(); ++ ++ datapaletteblock.read(buffer); ++ this.biomes = datapaletteblock; + } + + public void readBiomes(FriendlyByteBuf buffer) { +- PalettedContainer> palettedContainer = this.biomes.recreate(); +- palettedContainer.read(buffer); +- this.biomes = palettedContainer; ++ PalettedContainer> datapaletteblock = this.biomes.recreate(); ++ ++ datapaletteblock.read(buffer); ++ this.biomes = datapaletteblock; + } + + public void write(FriendlyByteBuf buffer) { +@@ -172,26 +182,32 @@ + return 2 + this.states.getSerializedSize() + this.biomes.getSerializedSize(); + } + +- public boolean maybeHas(Predicate predicate) { ++ public boolean maybeHas(Predicate predicate) { + return this.states.maybeHas(predicate); + } + + public Holder getNoiseBiome(int x, int y, int z) { +- return this.biomes.get(x, y, z); ++ return (Holder) this.biomes.get(x, y, z); + } + ++ // CraftBukkit start ++ public void setBiome(int i, int j, int k, Holder biome) { ++ this.biomes.set(i, j, k, biome); ++ } ++ // CraftBukkit end ++ + public void fillBiomesFromNoise(BiomeResolver biomeResolver, Climate.Sampler climateSampler, int x, int y, int z) { +- PalettedContainer> palettedContainer = this.biomes.recreate(); +- int i = 4; ++ PalettedContainer> datapaletteblock = this.biomes.recreate(); ++ boolean flag = true; + +- for (int i1 = 0; i1 < 4; i1++) { +- for (int i2 = 0; i2 < 4; i2++) { +- for (int i3 = 0; i3 < 4; i3++) { +- palettedContainer.getAndSetUnchecked(i1, i2, i3, biomeResolver.getNoiseBiome(x + i1, y + i2, z + i3, climateSampler)); ++ for (int l = 0; l < 4; ++l) { ++ for (int i1 = 0; i1 < 4; ++i1) { ++ for (int j1 = 0; j1 < 4; ++j1) { ++ datapaletteblock.getAndSetUnchecked(l, i1, j1, biomeResolver.getNoiseBiome(x + l, y + i1, z + j1, climateSampler)); + } + } + } + +- this.biomes = palettedContainer; ++ this.biomes = datapaletteblock; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/storage/ChunkSerializer.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/storage/ChunkSerializer.java.patch new file mode 100644 index 0000000000..ba5281ef7a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/storage/ChunkSerializer.java.patch @@ -0,0 +1,875 @@ +--- a/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -3,15 +3,19 @@ + import com.google.common.collect.Maps; + import com.mojang.logging.LogUtils; + import com.mojang.serialization.Codec; ++import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; + import it.unimi.dsi.fastutil.longs.LongOpenHashSet; + import it.unimi.dsi.fastutil.longs.LongSet; + import it.unimi.dsi.fastutil.shorts.ShortList; ++import it.unimi.dsi.fastutil.shorts.ShortListIterator; + import java.util.Arrays; + import java.util.EnumSet; ++import java.util.Iterator; + import java.util.Map; +-import java.util.Objects; + import java.util.Map.Entry; ++import java.util.Objects; ++import java.util.Optional; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Holder; +@@ -28,20 +32,21 @@ + import net.minecraft.nbt.ShortTag; + import net.minecraft.nbt.Tag; + import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ThreadedLevelLightEngine; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.ai.village.poi.PoiManager; + import net.minecraft.world.level.ChunkPos; +-import net.minecraft.world.level.LightLayer; ++import net.minecraft.world.level.EnumSkyBlock; + import net.minecraft.world.level.biome.Biome; + import net.minecraft.world.level.biome.Biomes; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.CarvingMask; + import net.minecraft.world.level.chunk.ChunkAccess; +-import net.minecraft.world.level.chunk.ChunkSource; + import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.level.chunk.DataLayer; + import net.minecraft.world.level.chunk.ImposterProtoChunk; +@@ -65,9 +70,8 @@ + import org.slf4j.Logger; + + public class ChunkSerializer { +- private static final Codec> BLOCK_STATE_CODEC = PalettedContainer.codecRW( +- Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState() +- ); ++ ++ public static final Codec> BLOCK_STATE_CODEC = PalettedContainer.codecRW(Block.BLOCK_STATE_REGISTRY, IBlockData.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState()); + private static final Logger LOGGER = LogUtils.getLogger(); + private static final String TAG_UPGRADE_DATA = "UpgradeData"; + private static final String BLOCK_TICKS_TAG = "block_ticks"; +@@ -80,393 +84,486 @@ + public static final String BLOCK_LIGHT_TAG = "BlockLight"; + public static final String SKY_LIGHT_TAG = "SkyLight"; + ++ public ChunkSerializer() {} ++ + public static ProtoChunk read(ServerLevel level, PoiManager poiManager, ChunkPos pos, CompoundTag tag) { +- ChunkPos chunkPos = new ChunkPos(tag.getInt("xPos"), tag.getInt("zPos")); +- if (!Objects.equals(pos, chunkPos)) { +- LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", pos, pos, chunkPos); ++ ChunkPos chunkcoordintpair1 = new ChunkPos(tag.getInt("xPos"), tag.getInt("zPos")); ++ ++ if (!Objects.equals(pos, chunkcoordintpair1)) { ++ ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", new Object[]{pos, pos, chunkcoordintpair1}); + } + +- UpgradeData upgradeData = tag.contains("UpgradeData", 10) ? new UpgradeData(tag.getCompound("UpgradeData"), level) : UpgradeData.EMPTY; +- boolean _boolean = tag.getBoolean("isLightOn"); +- ListTag list = tag.getList("sections", 10); +- int sectionsCount = level.getSectionsCount(); +- LevelChunkSection[] levelChunkSections = new LevelChunkSection[sectionsCount]; +- boolean hasSkyLight = level.dimensionType().hasSkyLight(); +- ChunkSource chunkSource = level.getChunkSource(); +- LevelLightEngine lightEngine = chunkSource.getLightEngine(); +- Registry registry = level.registryAccess().registryOrThrow(Registries.BIOME); +- Codec>> codec = makeBiomeCodec(registry); +- boolean flag = false; ++ UpgradeData chunkconverter = tag.contains("UpgradeData", 10) ? new UpgradeData(tag.getCompound("UpgradeData"), level) : UpgradeData.EMPTY; ++ boolean flag = tag.getBoolean("isLightOn"); ++ ListTag nbttaglist = tag.getList("sections", 10); ++ int i = level.getSectionsCount(); ++ LevelChunkSection[] achunksection = new LevelChunkSection[i]; ++ boolean flag1 = level.dimensionType().hasSkyLight(); ++ ServerChunkCache chunkproviderserver = level.getChunkSource(); ++ LevelLightEngine levellightengine = chunkproviderserver.getLightEngine(); ++ Registry iregistry = level.registryAccess().registryOrThrow(Registries.BIOME); ++ Codec>> codec = makeBiomeCodecRW(iregistry); // CraftBukkit - read/write ++ boolean flag2 = false; + +- for (int i = 0; i < list.size(); i++) { +- CompoundTag compound = list.getCompound(i); +- int _byte = compound.getByte("Y"); +- int sectionIndexFromSectionY = level.getSectionIndexFromSectionY(_byte); +- if (sectionIndexFromSectionY >= 0 && sectionIndexFromSectionY < levelChunkSections.length) { +- PalettedContainer palettedContainer; +- if (compound.contains("block_states", 10)) { +- palettedContainer = BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, compound.getCompound("block_states")) +- .promotePartial(errorMessage -> logErrors(pos, _byte, errorMessage)) +- .getOrThrow(false, LOGGER::error); ++ DataResult dataresult; ++ ++ for (int j = 0; j < nbttaglist.size(); ++j) { ++ CompoundTag nbttagcompound1 = nbttaglist.getCompound(j); ++ byte b0 = nbttagcompound1.getByte("Y"); ++ int k = level.getSectionIndexFromSectionY(b0); ++ ++ if (k >= 0 && k < achunksection.length) { ++ Logger logger; ++ PalettedContainer datapaletteblock; ++ ++ if (nbttagcompound1.contains("block_states", 10)) { ++ dataresult = ChunkSerializer.BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, nbttagcompound1.getCompound("block_states")).promotePartial((s) -> { ++ logErrors(pos, b0, s); ++ }); ++ logger = ChunkSerializer.LOGGER; ++ Objects.requireNonNull(logger); ++ datapaletteblock = (PalettedContainer) ((DataResult>) dataresult).getOrThrow(false, logger::error); // CraftBukkit - decompile error + } else { +- palettedContainer = new PalettedContainer<>( +- Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES +- ); ++ datapaletteblock = new PalettedContainer<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES); + } + +- PalettedContainerRO> palettedContainerRO; +- if (compound.contains("biomes", 10)) { +- palettedContainerRO = codec.parse(NbtOps.INSTANCE, compound.getCompound("biomes")) +- .promotePartial(errorMessage -> logErrors(pos, _byte, errorMessage)) +- .getOrThrow(false, LOGGER::error); ++ PalettedContainer object; // CraftBukkit - read/write ++ ++ if (nbttagcompound1.contains("biomes", 10)) { ++ dataresult = codec.parse(NbtOps.INSTANCE, nbttagcompound1.getCompound("biomes")).promotePartial((s) -> { ++ logErrors(pos, b0, s); ++ }); ++ logger = ChunkSerializer.LOGGER; ++ Objects.requireNonNull(logger); ++ object = ((DataResult>>) dataresult).getOrThrow(false, logger::error); // CraftBukkit - decompile error + } else { +- palettedContainerRO = new PalettedContainer<>( +- registry.asHolderIdMap(), registry.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES +- ); ++ object = new PalettedContainer<>(iregistry.asHolderIdMap(), iregistry.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES); + } + +- LevelChunkSection levelChunkSection = new LevelChunkSection(palettedContainer, palettedContainerRO); +- levelChunkSections[sectionIndexFromSectionY] = levelChunkSection; +- SectionPos sectionPos = SectionPos.of(pos, _byte); +- poiManager.checkConsistencyWithBlocks(sectionPos, levelChunkSection); ++ LevelChunkSection chunksection = new LevelChunkSection(datapaletteblock, (PalettedContainer) object); // CraftBukkit - read/write ++ ++ achunksection[k] = chunksection; ++ SectionPos sectionposition = SectionPos.of(pos, b0); ++ ++ poiManager.checkConsistencyWithBlocks(sectionposition, chunksection); + } + +- boolean flag1 = compound.contains("BlockLight", 7); +- boolean flag2 = hasSkyLight && compound.contains("SkyLight", 7); +- if (flag1 || flag2) { +- if (!flag) { +- lightEngine.retainData(pos, true); +- flag = true; ++ boolean flag3 = nbttagcompound1.contains("BlockLight", 7); ++ boolean flag4 = flag1 && nbttagcompound1.contains("SkyLight", 7); ++ ++ if (flag3 || flag4) { ++ if (!flag2) { ++ levellightengine.retainData(pos, true); ++ flag2 = true; + } + +- if (flag1) { +- lightEngine.queueSectionData(LightLayer.BLOCK, SectionPos.of(pos, _byte), new DataLayer(compound.getByteArray("BlockLight"))); ++ if (flag3) { ++ levellightengine.queueSectionData(EnumSkyBlock.BLOCK, SectionPos.of(pos, b0), new DataLayer(nbttagcompound1.getByteArray("BlockLight"))); + } + +- if (flag2) { +- lightEngine.queueSectionData(LightLayer.SKY, SectionPos.of(pos, _byte), new DataLayer(compound.getByteArray("SkyLight"))); ++ if (flag4) { ++ levellightengine.queueSectionData(EnumSkyBlock.SKY, SectionPos.of(pos, b0), new DataLayer(nbttagcompound1.getByteArray("SkyLight"))); + } + } + } + +- long _long = tag.getLong("InhabitedTime"); +- ChunkStatus.ChunkType chunkTypeFromTag = getChunkTypeFromTag(tag); +- BlendingData blendingData; ++ long l = tag.getLong("InhabitedTime"); ++ ChunkStatus.Type chunkstatus_type = getChunkTypeFromTag(tag); ++ Logger logger1; ++ BlendingData blendingdata; ++ + if (tag.contains("blending_data", 10)) { +- blendingData = BlendingData.CODEC +- .parse(new Dynamic<>(NbtOps.INSTANCE, tag.getCompound("blending_data"))) +- .resultOrPartial(LOGGER::error) +- .orElse(null); ++ dataresult = BlendingData.CODEC.parse(new Dynamic(NbtOps.INSTANCE, tag.getCompound("blending_data"))); ++ logger1 = ChunkSerializer.LOGGER; ++ Objects.requireNonNull(logger1); ++ blendingdata = (BlendingData) ((DataResult) dataresult).resultOrPartial(logger1::error).orElse(null); // CraftBukkit - decompile error + } else { +- blendingData = null; ++ blendingdata = null; + } + +- ChunkAccess chunkAccess; +- if (chunkTypeFromTag == ChunkStatus.ChunkType.LEVELCHUNK) { +- LevelChunkTicks levelChunkTicks = LevelChunkTicks.load( +- tag.getList("block_ticks", 10), id -> BuiltInRegistries.BLOCK.getOptional(ResourceLocation.tryParse(id)), pos +- ); +- LevelChunkTicks levelChunkTicks1 = LevelChunkTicks.load( +- tag.getList("fluid_ticks", 10), id -> BuiltInRegistries.FLUID.getOptional(ResourceLocation.tryParse(id)), pos +- ); +- chunkAccess = new LevelChunk( +- level.getLevel(), pos, upgradeData, levelChunkTicks, levelChunkTicks1, _long, levelChunkSections, postLoadChunk(level, tag), blendingData +- ); ++ Object object1; ++ ++ if (chunkstatus_type == ChunkStatus.Type.LEVELCHUNK) { ++ LevelChunkTicks levelchunkticks = LevelChunkTicks.load(tag.getList("block_ticks", 10), (s) -> { ++ return BuiltInRegistries.BLOCK.getOptional(ResourceLocation.tryParse(s)); ++ }, pos); ++ LevelChunkTicks levelchunkticks1 = LevelChunkTicks.load(tag.getList("fluid_ticks", 10), (s) -> { ++ return BuiltInRegistries.FLUID.getOptional(ResourceLocation.tryParse(s)); ++ }, pos); ++ ++ object1 = new LevelChunk(level.getLevel(), pos, chunkconverter, levelchunkticks, levelchunkticks1, l, achunksection, postLoadChunk(level, tag), blendingdata); + } else { +- ProtoChunkTicks protoChunkTicks = ProtoChunkTicks.load( +- tag.getList("block_ticks", 10), id -> BuiltInRegistries.BLOCK.getOptional(ResourceLocation.tryParse(id)), pos +- ); +- ProtoChunkTicks protoChunkTicks1 = ProtoChunkTicks.load( +- tag.getList("fluid_ticks", 10), id -> BuiltInRegistries.FLUID.getOptional(ResourceLocation.tryParse(id)), pos +- ); +- ProtoChunk protoChunk = new ProtoChunk(pos, upgradeData, levelChunkSections, protoChunkTicks, protoChunkTicks1, level, registry, blendingData); +- chunkAccess = protoChunk; +- protoChunk.setInhabitedTime(_long); ++ ProtoChunkTicks protochunkticklist = ProtoChunkTicks.load(tag.getList("block_ticks", 10), (s) -> { ++ return BuiltInRegistries.BLOCK.getOptional(ResourceLocation.tryParse(s)); ++ }, pos); ++ ProtoChunkTicks protochunkticklist1 = ProtoChunkTicks.load(tag.getList("fluid_ticks", 10), (s) -> { ++ return BuiltInRegistries.FLUID.getOptional(ResourceLocation.tryParse(s)); ++ }, pos); ++ ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, level, iregistry, blendingdata); ++ ++ object1 = protochunk; ++ protochunk.setInhabitedTime(l); + if (tag.contains("below_zero_retrogen", 10)) { +- BelowZeroRetrogen.CODEC +- .parse(new Dynamic<>(NbtOps.INSTANCE, tag.getCompound("below_zero_retrogen"))) +- .resultOrPartial(LOGGER::error) +- .ifPresent(protoChunk::setBelowZeroRetrogen); ++ dataresult = BelowZeroRetrogen.CODEC.parse(new Dynamic(NbtOps.INSTANCE, tag.getCompound("below_zero_retrogen"))); ++ logger1 = ChunkSerializer.LOGGER; ++ Objects.requireNonNull(logger1); ++ Optional optional = ((DataResult) dataresult).resultOrPartial(logger1::error); // CraftBukkit - decompile error ++ ++ Objects.requireNonNull(protochunk); ++ optional.ifPresent(protochunk::setBelowZeroRetrogen); + } + +- ChunkStatus chunkStatus = ChunkStatus.byName(tag.getString("Status")); +- protoChunk.setStatus(chunkStatus); +- if (chunkStatus.isOrAfter(ChunkStatus.INITIALIZE_LIGHT)) { +- protoChunk.setLightEngine(lightEngine); ++ ChunkStatus chunkstatus = ChunkStatus.byName(tag.getString("Status")); ++ ++ protochunk.setStatus(chunkstatus); ++ if (chunkstatus.isOrAfter(ChunkStatus.INITIALIZE_LIGHT)) { ++ protochunk.setLightEngine(levellightengine); + } + } + +- chunkAccess.setLightCorrect(_boolean); +- CompoundTag compound1 = tag.getCompound("Heightmaps"); +- EnumSet set = EnumSet.noneOf(Heightmap.Types.class); ++ // CraftBukkit start - load chunk persistent data from nbt - SPIGOT-6814: Already load PDC here to account for 1.17 to 1.18 chunk upgrading. ++ net.minecraft.nbt.Tag persistentBase = tag.get("ChunkBukkitValues"); ++ if (persistentBase instanceof CompoundTag) { ++ ((ChunkAccess) object1).persistentDataContainer.putAll((CompoundTag) persistentBase); ++ } ++ // CraftBukkit end + +- for (Heightmap.Types types : chunkAccess.getStatus().heightmapsAfter()) { +- String serializationKey = types.getSerializationKey(); +- if (compound1.contains(serializationKey, 12)) { +- chunkAccess.setHeightmap(types, compound1.getLongArray(serializationKey)); ++ ((ChunkAccess) object1).setLightCorrect(flag); ++ CompoundTag nbttagcompound2 = tag.getCompound("Heightmaps"); ++ EnumSet enumset = EnumSet.noneOf(Heightmap.Types.class); ++ Iterator iterator = ((ChunkAccess) object1).getStatus().heightmapsAfter().iterator(); ++ ++ while (iterator.hasNext()) { ++ Heightmap.Types heightmap_type = (Heightmap.Types) iterator.next(); ++ String s = heightmap_type.getSerializationKey(); ++ ++ if (nbttagcompound2.contains(s, 12)) { ++ ((ChunkAccess) object1).setHeightmap(heightmap_type, nbttagcompound2.getLongArray(s)); + } else { +- set.add(types); ++ enumset.add(heightmap_type); + } + } + +- Heightmap.primeHeightmaps(chunkAccess, set); +- CompoundTag compound2 = tag.getCompound("structures"); +- chunkAccess.setAllStarts(unpackStructureStart(StructurePieceSerializationContext.fromLevel(level), compound2, level.getSeed())); +- chunkAccess.setAllReferences(unpackStructureReferences(level.registryAccess(), pos, compound2)); ++ Heightmap.primeHeightmaps((ChunkAccess) object1, enumset); ++ CompoundTag nbttagcompound3 = tag.getCompound("structures"); ++ ++ ((ChunkAccess) object1).setAllStarts(unpackStructureStart(StructurePieceSerializationContext.fromLevel(level), nbttagcompound3, level.getSeed())); ++ ((ChunkAccess) object1).setAllReferences(unpackStructureReferences(level.registryAccess(), pos, nbttagcompound3)); + if (tag.getBoolean("shouldSave")) { +- chunkAccess.setUnsaved(true); ++ ((ChunkAccess) object1).setUnsaved(true); + } + +- ListTag list1 = tag.getList("PostProcessing", 9); ++ ListTag nbttaglist1 = tag.getList("PostProcessing", 9); + +- for (int i1 = 0; i1 < list1.size(); i1++) { +- ListTag list2 = list1.getList(i1); ++ ListTag nbttaglist2; ++ int i1; + +- for (int i2 = 0; i2 < list2.size(); i2++) { +- chunkAccess.addPackedPostProcess(list2.getShort(i2), i1); ++ for (int j1 = 0; j1 < nbttaglist1.size(); ++j1) { ++ nbttaglist2 = nbttaglist1.getList(j1); ++ ++ for (i1 = 0; i1 < nbttaglist2.size(); ++i1) { ++ ((ChunkAccess) object1).addPackedPostProcess(nbttaglist2.getShort(i1), j1); + } + } + +- if (chunkTypeFromTag == ChunkStatus.ChunkType.LEVELCHUNK) { +- return new ImposterProtoChunk((LevelChunk)chunkAccess, false); ++ if (chunkstatus_type == ChunkStatus.Type.LEVELCHUNK) { ++ return new ImposterProtoChunk((LevelChunk) object1, false); + } else { +- ProtoChunk protoChunk1 = (ProtoChunk)chunkAccess; +- ListTag list2 = tag.getList("entities", 10); ++ ProtoChunk protochunk1 = (ProtoChunk) object1; + +- for (int i2 = 0; i2 < list2.size(); i2++) { +- protoChunk1.addEntity(list2.getCompound(i2)); ++ nbttaglist2 = tag.getList("entities", 10); ++ ++ for (i1 = 0; i1 < nbttaglist2.size(); ++i1) { ++ protochunk1.addEntity(nbttaglist2.getCompound(i1)); + } + +- ListTag list3 = tag.getList("block_entities", 10); ++ ListTag nbttaglist3 = tag.getList("block_entities", 10); + +- for (int i3 = 0; i3 < list3.size(); i3++) { +- CompoundTag compound3 = list3.getCompound(i3); +- chunkAccess.setBlockEntityNbt(compound3); ++ for (int k1 = 0; k1 < nbttaglist3.size(); ++k1) { ++ CompoundTag nbttagcompound4 = nbttaglist3.getCompound(k1); ++ ++ ((ChunkAccess) object1).setBlockEntityNbt(nbttagcompound4); + } + +- CompoundTag compound4 = tag.getCompound("CarvingMasks"); ++ CompoundTag nbttagcompound5 = tag.getCompound("CarvingMasks"); ++ Iterator iterator1 = nbttagcompound5.getAllKeys().iterator(); + +- for (String string : compound4.getAllKeys()) { +- GenerationStep.Carving carving = GenerationStep.Carving.valueOf(string); +- protoChunk1.setCarvingMask(carving, new CarvingMask(compound4.getLongArray(string), chunkAccess.getMinBuildHeight())); ++ while (iterator1.hasNext()) { ++ String s1 = (String) iterator1.next(); ++ GenerationStep.Carving worldgenstage_features = GenerationStep.Carving.valueOf(s1); ++ ++ protochunk1.setCarvingMask(worldgenstage_features, new CarvingMask(nbttagcompound5.getLongArray(s1), ((ChunkAccess) object1).getMinBuildHeight())); + } + +- return protoChunk1; ++ return protochunk1; + } + } + + private static void logErrors(ChunkPos chunkPos, int chunkSectionY, String errorMessage) { +- LOGGER.error("Recoverable errors when loading section [" + chunkPos.x + ", " + chunkSectionY + ", " + chunkPos.z + "]: " + errorMessage); ++ ChunkSerializer.LOGGER.error("Recoverable errors when loading section [" + chunkPos.x + ", " + chunkSectionY + ", " + chunkPos.z + "]: " + errorMessage); + } + + private static Codec>> makeBiomeCodec(Registry biomeRegistry) { +- return PalettedContainer.codecRO( +- biomeRegistry.asHolderIdMap(), +- biomeRegistry.holderByNameCodec(), +- PalettedContainer.Strategy.SECTION_BIOMES, +- biomeRegistry.getHolderOrThrow(Biomes.PLAINS) +- ); ++ return PalettedContainer.codecRO(biomeRegistry.asHolderIdMap(), biomeRegistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomeRegistry.getHolderOrThrow(Biomes.PLAINS)); + } + ++ // CraftBukkit start - read/write ++ private static Codec>> makeBiomeCodecRW(Registry iregistry) { ++ return PalettedContainer.codecRW(iregistry.asHolderIdMap(), iregistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, iregistry.getHolderOrThrow(Biomes.PLAINS)); ++ } ++ // CraftBukkit end ++ + public static CompoundTag write(ServerLevel level, ChunkAccess chunk) { +- ChunkPos pos = chunk.getPos(); +- CompoundTag compoundTag = NbtUtils.addCurrentDataVersion(new CompoundTag()); +- compoundTag.putInt("xPos", pos.x); +- compoundTag.putInt("yPos", chunk.getMinSection()); +- compoundTag.putInt("zPos", pos.z); +- compoundTag.putLong("LastUpdate", level.getGameTime()); +- compoundTag.putLong("InhabitedTime", chunk.getInhabitedTime()); +- compoundTag.putString("Status", BuiltInRegistries.CHUNK_STATUS.getKey(chunk.getStatus()).toString()); +- BlendingData blendingData = chunk.getBlendingData(); +- if (blendingData != null) { +- BlendingData.CODEC +- .encodeStart(NbtOps.INSTANCE, blendingData) +- .resultOrPartial(LOGGER::error) +- .ifPresent(data -> compoundTag.put("blending_data", data)); ++ ChunkPos chunkcoordintpair = chunk.getPos(); ++ CompoundTag nbttagcompound = NbtUtils.addCurrentDataVersion(new CompoundTag()); ++ ++ nbttagcompound.putInt("xPos", chunkcoordintpair.x); ++ nbttagcompound.putInt("yPos", chunk.getMinSection()); ++ nbttagcompound.putInt("zPos", chunkcoordintpair.z); ++ nbttagcompound.putLong("LastUpdate", level.getGameTime()); ++ nbttagcompound.putLong("InhabitedTime", chunk.getInhabitedTime()); ++ nbttagcompound.putString("Status", BuiltInRegistries.CHUNK_STATUS.getKey(chunk.getStatus()).toString()); ++ BlendingData blendingdata = chunk.getBlendingData(); ++ DataResult dataresult; // CraftBukkit - decompile error ++ Logger logger; ++ ++ if (blendingdata != null) { ++ dataresult = BlendingData.CODEC.encodeStart(NbtOps.INSTANCE, blendingdata); ++ logger = ChunkSerializer.LOGGER; ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ nbttagcompound.put("blending_data", nbtbase); ++ }); + } + +- BelowZeroRetrogen belowZeroRetrogen = chunk.getBelowZeroRetrogen(); +- if (belowZeroRetrogen != null) { +- BelowZeroRetrogen.CODEC +- .encodeStart(NbtOps.INSTANCE, belowZeroRetrogen) +- .resultOrPartial(LOGGER::error) +- .ifPresent(belowZeroRetrogen1 -> compoundTag.put("below_zero_retrogen", belowZeroRetrogen1)); ++ BelowZeroRetrogen belowzeroretrogen = chunk.getBelowZeroRetrogen(); ++ ++ if (belowzeroretrogen != null) { ++ dataresult = BelowZeroRetrogen.CODEC.encodeStart(NbtOps.INSTANCE, belowzeroretrogen); ++ logger = ChunkSerializer.LOGGER; ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ nbttagcompound.put("below_zero_retrogen", nbtbase); ++ }); + } + +- UpgradeData upgradeData = chunk.getUpgradeData(); +- if (!upgradeData.isEmpty()) { +- compoundTag.put("UpgradeData", upgradeData.write()); ++ UpgradeData chunkconverter = chunk.getUpgradeData(); ++ ++ if (!chunkconverter.isEmpty()) { ++ nbttagcompound.put("UpgradeData", chunkconverter.write()); + } + +- LevelChunkSection[] sections = chunk.getSections(); +- ListTag list = new ListTag(); +- LevelLightEngine lightEngine = level.getChunkSource().getLightEngine(); +- Registry registry = level.registryAccess().registryOrThrow(Registries.BIOME); +- Codec>> codec = makeBiomeCodec(registry); +- boolean isLightCorrect = chunk.isLightCorrect(); ++ LevelChunkSection[] achunksection = chunk.getSections(); ++ ListTag nbttaglist = new ListTag(); ++ ThreadedLevelLightEngine lightenginethreaded = level.getChunkSource().getLightEngine(); ++ Registry iregistry = level.registryAccess().registryOrThrow(Registries.BIOME); ++ Codec>> codec = makeBiomeCodec(iregistry); ++ boolean flag = chunk.isLightCorrect(); + +- for (int minLightSection = lightEngine.getMinLightSection(); minLightSection < lightEngine.getMaxLightSection(); minLightSection++) { +- int sectionIndexFromSectionY = chunk.getSectionIndexFromSectionY(minLightSection); +- boolean flag = sectionIndexFromSectionY >= 0 && sectionIndexFromSectionY < sections.length; +- DataLayer dataLayerData = lightEngine.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(pos, minLightSection)); +- DataLayer dataLayerData1 = lightEngine.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(pos, minLightSection)); +- if (flag || dataLayerData != null || dataLayerData1 != null) { +- CompoundTag compoundTag1 = new CompoundTag(); +- if (flag) { +- LevelChunkSection levelChunkSection = sections[sectionIndexFromSectionY]; +- compoundTag1.put( +- "block_states", BLOCK_STATE_CODEC.encodeStart(NbtOps.INSTANCE, levelChunkSection.getStates()).getOrThrow(false, LOGGER::error) +- ); +- compoundTag1.put("biomes", codec.encodeStart(NbtOps.INSTANCE, levelChunkSection.getBiomes()).getOrThrow(false, LOGGER::error)); ++ for (int i = lightenginethreaded.getMinLightSection(); i < lightenginethreaded.getMaxLightSection(); ++i) { ++ int j = chunk.getSectionIndexFromSectionY(i); ++ boolean flag1 = j >= 0 && j < achunksection.length; ++ DataLayer nibblearray = lightenginethreaded.getLayerListener(EnumSkyBlock.BLOCK).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); ++ DataLayer nibblearray1 = lightenginethreaded.getLayerListener(EnumSkyBlock.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); ++ ++ if (flag1 || nibblearray != null || nibblearray1 != null) { ++ CompoundTag nbttagcompound1 = new CompoundTag(); ++ ++ if (flag1) { ++ LevelChunkSection chunksection = achunksection[j]; ++ DataResult dataresult1 = ChunkSerializer.BLOCK_STATE_CODEC.encodeStart(NbtOps.INSTANCE, chunksection.getStates()); // CraftBukkit - decompile error ++ Logger logger1 = ChunkSerializer.LOGGER; ++ ++ Objects.requireNonNull(logger1); ++ nbttagcompound1.put("block_states", (Tag) dataresult1.getOrThrow(false, logger1::error)); ++ dataresult1 = codec.encodeStart(NbtOps.INSTANCE, chunksection.getBiomes()); ++ logger1 = ChunkSerializer.LOGGER; ++ Objects.requireNonNull(logger1); ++ nbttagcompound1.put("biomes", (Tag) dataresult1.getOrThrow(false, logger1::error)); + } + +- if (dataLayerData != null && !dataLayerData.isEmpty()) { +- compoundTag1.putByteArray("BlockLight", dataLayerData.getData()); ++ if (nibblearray != null && !nibblearray.isEmpty()) { ++ nbttagcompound1.putByteArray("BlockLight", nibblearray.getData()); + } + +- if (dataLayerData1 != null && !dataLayerData1.isEmpty()) { +- compoundTag1.putByteArray("SkyLight", dataLayerData1.getData()); ++ if (nibblearray1 != null && !nibblearray1.isEmpty()) { ++ nbttagcompound1.putByteArray("SkyLight", nibblearray1.getData()); + } + +- if (!compoundTag1.isEmpty()) { +- compoundTag1.putByte("Y", (byte)minLightSection); +- list.add(compoundTag1); ++ if (!nbttagcompound1.isEmpty()) { ++ nbttagcompound1.putByte("Y", (byte) i); ++ nbttaglist.add(nbttagcompound1); + } + } + } + +- compoundTag.put("sections", list); +- if (isLightCorrect) { +- compoundTag.putBoolean("isLightOn", true); ++ nbttagcompound.put("sections", nbttaglist); ++ if (flag) { ++ nbttagcompound.putBoolean("isLightOn", true); + } + +- ListTag list1 = new ListTag(); ++ ListTag nbttaglist1 = new ListTag(); ++ Iterator iterator = chunk.getBlockEntitiesPos().iterator(); + +- for (BlockPos blockPos : chunk.getBlockEntitiesPos()) { +- CompoundTag blockEntityNbtForSaving = chunk.getBlockEntityNbtForSaving(blockPos); +- if (blockEntityNbtForSaving != null) { +- list1.add(blockEntityNbtForSaving); ++ CompoundTag nbttagcompound2; ++ ++ while (iterator.hasNext()) { ++ BlockPos blockposition = (BlockPos) iterator.next(); ++ ++ nbttagcompound2 = chunk.getBlockEntityNbtForSaving(blockposition); ++ if (nbttagcompound2 != null) { ++ nbttaglist1.add(nbttagcompound2); + } + } + +- compoundTag.put("block_entities", list1); +- if (chunk.getStatus().getChunkType() == ChunkStatus.ChunkType.PROTOCHUNK) { +- ProtoChunk protoChunk = (ProtoChunk)chunk; +- ListTag list2 = new ListTag(); +- list2.addAll(protoChunk.getEntities()); +- compoundTag.put("entities", list2); +- CompoundTag blockEntityNbtForSaving = new CompoundTag(); ++ nbttagcompound.put("block_entities", nbttaglist1); ++ if (chunk.getStatus().getChunkType() == ChunkStatus.Type.PROTOCHUNK) { ++ ProtoChunk protochunk = (ProtoChunk) chunk; ++ ListTag nbttaglist2 = new ListTag(); + +- for (GenerationStep.Carving carving : GenerationStep.Carving.values()) { +- CarvingMask carvingMask = protoChunk.getCarvingMask(carving); +- if (carvingMask != null) { +- blockEntityNbtForSaving.putLongArray(carving.toString(), carvingMask.toArray()); ++ nbttaglist2.addAll(protochunk.getEntities()); ++ nbttagcompound.put("entities", nbttaglist2); ++ nbttagcompound2 = new CompoundTag(); ++ GenerationStep.Carving[] aworldgenstage_features = GenerationStep.Carving.values(); ++ int k = aworldgenstage_features.length; ++ ++ for (int l = 0; l < k; ++l) { ++ GenerationStep.Carving worldgenstage_features = aworldgenstage_features[l]; ++ CarvingMask carvingmask = protochunk.getCarvingMask(worldgenstage_features); ++ ++ if (carvingmask != null) { ++ nbttagcompound2.putLongArray(worldgenstage_features.toString(), carvingmask.toArray()); + } + } + +- compoundTag.put("CarvingMasks", blockEntityNbtForSaving); ++ nbttagcompound.put("CarvingMasks", nbttagcompound2); + } + +- saveTicks(level, compoundTag, chunk.getTicksForSerialization()); +- compoundTag.put("PostProcessing", packOffsets(chunk.getPostProcessing())); +- CompoundTag compoundTag2 = new CompoundTag(); ++ saveTicks(level, nbttagcompound, chunk.getTicksForSerialization()); ++ nbttagcompound.put("PostProcessing", packOffsets(chunk.getPostProcessing())); ++ CompoundTag nbttagcompound3 = new CompoundTag(); ++ Iterator iterator1 = chunk.getHeightmaps().iterator(); + +- for (Entry entry : chunk.getHeightmaps()) { ++ while (iterator1.hasNext()) { ++ Entry entry = (Entry) iterator1.next(); ++ + if (chunk.getStatus().heightmapsAfter().contains(entry.getKey())) { +- compoundTag2.put(entry.getKey().getSerializationKey(), new LongArrayTag(entry.getValue().getRawData())); ++ nbttagcompound3.put(((Heightmap.Types) entry.getKey()).getSerializationKey(), new LongArrayTag(((Heightmap) entry.getValue()).getRawData())); + } + } + +- compoundTag.put("Heightmaps", compoundTag2); +- compoundTag.put( +- "structures", packStructureData(StructurePieceSerializationContext.fromLevel(level), pos, chunk.getAllStarts(), chunk.getAllReferences()) +- ); +- return compoundTag; ++ nbttagcompound.put("Heightmaps", nbttagcompound3); ++ nbttagcompound.put("structures", packStructureData(StructurePieceSerializationContext.fromLevel(level), chunkcoordintpair, chunk.getAllStarts(), chunk.getAllReferences())); ++ // CraftBukkit start - store chunk persistent data in nbt ++ if (!chunk.persistentDataContainer.isEmpty()) { // SPIGOT-6814: Always save PDC to account for 1.17 to 1.18 chunk upgrading. ++ nbttagcompound.put("ChunkBukkitValues", chunk.persistentDataContainer.toTagCompound()); ++ } ++ // CraftBukkit end ++ return nbttagcompound; + } + +- private static void saveTicks(ServerLevel level, CompoundTag tag, ChunkAccess.TicksToSave ticksToSave) { +- long gameTime = level.getLevelData().getGameTime(); +- tag.put("block_ticks", ticksToSave.blocks().save(gameTime, block -> BuiltInRegistries.BLOCK.getKey(block).toString())); +- tag.put("fluid_ticks", ticksToSave.fluids().save(gameTime, fluid -> BuiltInRegistries.FLUID.getKey(fluid).toString())); ++ private static void saveTicks(ServerLevel level, CompoundTag tag, ChunkAccess.a ticksToSave) { ++ long i = level.getLevelData().getGameTime(); ++ ++ tag.put("block_ticks", ticksToSave.blocks().save(i, (block) -> { ++ return BuiltInRegistries.BLOCK.getKey(block).toString(); ++ })); ++ tag.put("fluid_ticks", ticksToSave.fluids().save(i, (fluidtype) -> { ++ return BuiltInRegistries.FLUID.getKey(fluidtype).toString(); ++ })); + } + +- public static ChunkStatus.ChunkType getChunkTypeFromTag(@Nullable CompoundTag chunkNBT) { +- return chunkNBT != null ? ChunkStatus.byName(chunkNBT.getString("Status")).getChunkType() : ChunkStatus.ChunkType.PROTOCHUNK; ++ public static ChunkStatus.Type getChunkTypeFromTag(@Nullable CompoundTag chunkNBT) { ++ return chunkNBT != null ? ChunkStatus.byName(chunkNBT.getString("Status")).getChunkType() : ChunkStatus.Type.PROTOCHUNK; + } + + @Nullable + private static LevelChunk.PostLoadProcessor postLoadChunk(ServerLevel level, CompoundTag tag) { +- ListTag listOfCompoundsOrNull = getListOfCompoundsOrNull(tag, "entities"); +- ListTag listOfCompoundsOrNull1 = getListOfCompoundsOrNull(tag, "block_entities"); +- return listOfCompoundsOrNull == null && listOfCompoundsOrNull1 == null ? null : chunk -> { +- if (listOfCompoundsOrNull != null) { +- level.addLegacyChunkEntities(EntityType.loadEntitiesRecursive(listOfCompoundsOrNull, level)); ++ ListTag nbttaglist = getListOfCompoundsOrNull(tag, "entities"); ++ ListTag nbttaglist1 = getListOfCompoundsOrNull(tag, "block_entities"); ++ ++ return nbttaglist == null && nbttaglist1 == null ? null : (chunk) -> { ++ if (nbttaglist != null) { ++ level.addLegacyChunkEntities(EntityType.loadEntitiesRecursive(nbttaglist, level)); + } + +- if (listOfCompoundsOrNull1 != null) { +- for (int i = 0; i < listOfCompoundsOrNull1.size(); i++) { +- CompoundTag compound = listOfCompoundsOrNull1.getCompound(i); +- boolean _boolean = compound.getBoolean("keepPacked"); +- if (_boolean) { +- chunk.setBlockEntityNbt(compound); ++ if (nbttaglist1 != null) { ++ for (int i = 0; i < nbttaglist1.size(); ++i) { ++ CompoundTag nbttagcompound1 = nbttaglist1.getCompound(i); ++ boolean flag = nbttagcompound1.getBoolean("keepPacked"); ++ ++ if (flag) { ++ chunk.setBlockEntityNbt(nbttagcompound1); + } else { +- BlockPos posFromTag = BlockEntity.getPosFromTag(compound); +- BlockEntity blockEntity = BlockEntity.loadStatic(posFromTag, chunk.getBlockState(posFromTag), compound); +- if (blockEntity != null) { +- chunk.setBlockEntity(blockEntity); ++ BlockPos blockposition = BlockEntity.getPosFromTag(nbttagcompound1); ++ BlockEntity tileentity = BlockEntity.loadStatic(blockposition, chunk.getBlockState(blockposition), nbttagcompound1); ++ ++ if (tileentity != null) { ++ chunk.setBlockEntity(tileentity); + } + } + } + } ++ + }; + } + + @Nullable + private static ListTag getListOfCompoundsOrNull(CompoundTag tag, String key) { +- ListTag list = tag.getList(key, 10); +- return list.isEmpty() ? null : list; ++ ListTag nbttaglist = tag.getList(key, 10); ++ ++ return nbttaglist.isEmpty() ? null : nbttaglist; + } + +- private static CompoundTag packStructureData( +- StructurePieceSerializationContext context, ChunkPos pos, Map structureMap, Map referenceMap +- ) { +- CompoundTag compoundTag = new CompoundTag(); +- CompoundTag compoundTag1 = new CompoundTag(); +- Registry registry = context.registryAccess().registryOrThrow(Registries.STRUCTURE); ++ private static CompoundTag packStructureData(StructurePieceSerializationContext context, ChunkPos pos, Map structureMap, Map referenceMap) { ++ CompoundTag nbttagcompound = new CompoundTag(); ++ CompoundTag nbttagcompound1 = new CompoundTag(); ++ Registry iregistry = context.registryAccess().registryOrThrow(Registries.STRUCTURE); ++ Iterator iterator = structureMap.entrySet().iterator(); + +- for (Entry entry : structureMap.entrySet()) { +- ResourceLocation key = registry.getKey(entry.getKey()); +- compoundTag1.put(key.toString(), entry.getValue().createTag(context, pos)); ++ while (iterator.hasNext()) { ++ Entry entry = (Entry) iterator.next(); ++ ResourceLocation minecraftkey = iregistry.getKey((Structure) entry.getKey()); ++ ++ nbttagcompound1.put(minecraftkey.toString(), ((StructureStart) entry.getValue()).createTag(context, pos)); + } + +- compoundTag.put("starts", compoundTag1); +- CompoundTag compoundTag2 = new CompoundTag(); ++ nbttagcompound.put("starts", nbttagcompound1); ++ CompoundTag nbttagcompound2 = new CompoundTag(); ++ Iterator iterator1 = referenceMap.entrySet().iterator(); + +- for (Entry entry1 : referenceMap.entrySet()) { +- if (!entry1.getValue().isEmpty()) { +- ResourceLocation key1 = registry.getKey(entry1.getKey()); +- compoundTag2.put(key1.toString(), new LongArrayTag(entry1.getValue())); ++ while (iterator1.hasNext()) { ++ Entry entry1 = (Entry) iterator1.next(); ++ ++ if (!((LongSet) entry1.getValue()).isEmpty()) { ++ ResourceLocation minecraftkey1 = iregistry.getKey((Structure) entry1.getKey()); ++ ++ nbttagcompound2.put(minecraftkey1.toString(), new LongArrayTag((LongSet) entry1.getValue())); + } + } + +- compoundTag.put("References", compoundTag2); +- return compoundTag; ++ nbttagcompound.put("References", nbttagcompound2); ++ return nbttagcompound; + } + + private static Map unpackStructureStart(StructurePieceSerializationContext context, CompoundTag tag, long seed) { + Map map = Maps.newHashMap(); +- Registry registry = context.registryAccess().registryOrThrow(Registries.STRUCTURE); +- CompoundTag compound = tag.getCompound("starts"); ++ Registry iregistry = context.registryAccess().registryOrThrow(Registries.STRUCTURE); ++ CompoundTag nbttagcompound1 = tag.getCompound("starts"); ++ Iterator iterator = nbttagcompound1.getAllKeys().iterator(); + +- for (String string : compound.getAllKeys()) { +- ResourceLocation resourceLocation = ResourceLocation.tryParse(string); +- Structure structure = registry.get(resourceLocation); ++ while (iterator.hasNext()) { ++ String s = (String) iterator.next(); ++ ResourceLocation minecraftkey = ResourceLocation.tryParse(s); ++ Structure structure = (Structure) iregistry.get(minecraftkey); ++ + if (structure == null) { +- LOGGER.error("Unknown structure start: {}", resourceLocation); ++ ChunkSerializer.LOGGER.error("Unknown structure start: {}", minecraftkey); + } else { +- StructureStart structureStart = StructureStart.loadStaticStart(context, compound.getCompound(string), seed); +- if (structureStart != null) { +- map.put(structure, structureStart); ++ StructureStart structurestart = StructureStart.loadStaticStart(context, nbttagcompound1.getCompound(s), seed); ++ ++ if (structurestart != null) { ++ map.put(structure, structurestart); + } + } + } +@@ -476,21 +573,26 @@ + + private static Map unpackStructureReferences(RegistryAccess registryAccess, ChunkPos pos, CompoundTag tag) { + Map map = Maps.newHashMap(); +- Registry registry = registryAccess.registryOrThrow(Registries.STRUCTURE); +- CompoundTag compound = tag.getCompound("References"); ++ Registry iregistry = registryAccess.registryOrThrow(Registries.STRUCTURE); ++ CompoundTag nbttagcompound1 = tag.getCompound("References"); ++ Iterator iterator = nbttagcompound1.getAllKeys().iterator(); + +- for (String string : compound.getAllKeys()) { +- ResourceLocation resourceLocation = ResourceLocation.tryParse(string); +- Structure structure = registry.get(resourceLocation); ++ while (iterator.hasNext()) { ++ String s = (String) iterator.next(); ++ ResourceLocation minecraftkey = ResourceLocation.tryParse(s); ++ Structure structure = (Structure) iregistry.get(minecraftkey); ++ + if (structure == null) { +- LOGGER.warn("Found reference to unknown structure '{}' in chunk {}, discarding", resourceLocation, pos); ++ ChunkSerializer.LOGGER.warn("Found reference to unknown structure '{}' in chunk {}, discarding", minecraftkey, pos); + } else { +- long[] longArray = compound.getLongArray(string); +- if (longArray.length != 0) { +- map.put(structure, new LongOpenHashSet(Arrays.stream(longArray).filter(longPosition -> { +- ChunkPos chunkPos = new ChunkPos(longPosition); +- if (chunkPos.getChessboardDistance(pos) > 8) { +- LOGGER.warn("Found invalid structure reference [ {} @ {} ] for chunk {}.", resourceLocation, chunkPos, pos); ++ long[] along = nbttagcompound1.getLongArray(s); ++ ++ if (along.length != 0) { ++ map.put(structure, new LongOpenHashSet(Arrays.stream(along).filter((i) -> { ++ ChunkPos chunkcoordintpair1 = new ChunkPos(i); ++ ++ if (chunkcoordintpair1.getChessboardDistance(pos) > 8) { ++ ChunkSerializer.LOGGER.warn("Found invalid structure reference [ {} @ {} ] for chunk {}.", new Object[]{minecraftkey, chunkcoordintpair1, pos}); + return false; + } else { + return true; +@@ -504,19 +606,27 @@ + } + + public static ListTag packOffsets(ShortList[] list) { +- ListTag list1 = new ListTag(); ++ ListTag nbttaglist = new ListTag(); ++ ShortList[] ashortlist1 = list; ++ int i = list.length; + +- for (ShortList list2 : list) { +- ListTag list3 = new ListTag(); +- if (list2 != null) { +- for (Short _short : list2) { +- list3.add(ShortTag.valueOf(_short)); ++ for (int j = 0; j < i; ++j) { ++ ShortList shortlist = ashortlist1[j]; ++ ListTag nbttaglist1 = new ListTag(); ++ ++ if (shortlist != null) { ++ ShortListIterator shortlistiterator = shortlist.iterator(); ++ ++ while (shortlistiterator.hasNext()) { ++ Short oshort = (Short) shortlistiterator.next(); ++ ++ nbttaglist1.add(ShortTag.valueOf(oshort)); + } + } + +- list1.add(list3); ++ nbttaglist.add(nbttaglist1); + } + +- return list1; ++ return nbttaglist; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/storage/ChunkStorage.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/storage/ChunkStorage.java.patch new file mode 100644 index 0000000000..d99e4c5622 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/storage/ChunkStorage.java.patch @@ -0,0 +1,168 @@ +--- a/net/minecraft/world/level/chunk/storage/ChunkStorage.java ++++ b/net/minecraft/world/level/chunk/storage/ChunkStorage.java +@@ -12,14 +12,21 @@ + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtUtils; + import net.minecraft.resources.ResourceKey; ++import net.minecraft.server.level.ServerChunkCache; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.datafix.DataFixTypes; + import net.minecraft.world.level.ChunkPos; +-import net.minecraft.world.level.Level; ++import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.chunk.ChunkGenerator; ++// CraftBukkit start ++import java.util.concurrent.ExecutionException; ++import net.minecraft.world.level.chunk.ChunkStatus; ++import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.levelgen.structure.LegacyStructureDataHandler; + import net.minecraft.world.level.storage.DimensionDataStorage; + + public class ChunkStorage implements AutoCloseable { ++ + public static final int LAST_MONOLYTH_STRUCTURE_DATA_VERSION = 1493; + private final IOWorker worker; + protected final DataFixer fixerUpper; +@@ -35,52 +42,95 @@ + return this.worker.isOldChunkAround(pos, radius); + } + +- public CompoundTag upgradeChunkTag( +- ResourceKey levelKey, +- Supplier storage, +- CompoundTag chunkData, +- Optional>> chunkGeneratorKey +- ) { +- int version = getVersion(chunkData); +- if (version < 1493) { +- chunkData = DataFixTypes.CHUNK.update(this.fixerUpper, chunkData, version, 1493); +- if (chunkData.getCompound("Level").getBoolean("hasLegacyStructureData")) { +- LegacyStructureDataHandler legacyStructureHandler = this.getLegacyStructureHandler(levelKey, storage); +- chunkData = legacyStructureHandler.updateFromLegacy(chunkData); ++ // CraftBukkit start ++ private boolean check(ServerChunkCache cps, int x, int z) { ++ ChunkPos pos = new ChunkPos(x, z); ++ if (cps != null) { ++ com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); ++ if (cps.hasChunk(x, z)) { ++ return true; + } + } + +- injectDatafixingContext(chunkData, levelKey, chunkGeneratorKey); +- CompoundTag var7 = DataFixTypes.CHUNK.updateToCurrentVersion(this.fixerUpper, chunkData, Math.max(1493, version)); +- if (version < SharedConstants.getCurrentVersion().getDataVersion().getVersion()) { +- NbtUtils.addCurrentDataVersion(var7); ++ CompoundTag nbt; ++ try { ++ nbt = read(pos).get().orElse(null); ++ } catch (InterruptedException | ExecutionException ex) { ++ throw new RuntimeException(ex); + } ++ if (nbt != null) { ++ CompoundTag level = nbt.getCompound("Level"); ++ if (level.getBoolean("TerrainPopulated")) { ++ return true; ++ } + +- var7.remove("__context"); +- return var7; ++ ChunkStatus status = ChunkStatus.byName(level.getString("Status")); ++ if (status != null && status.isOrAfter(ChunkStatus.FEATURES)) { ++ return true; ++ } ++ } ++ ++ return false; + } + +- private LegacyStructureDataHandler getLegacyStructureHandler(ResourceKey level, Supplier storage) { +- LegacyStructureDataHandler legacyStructureDataHandler = this.legacyStructureHandler; +- if (legacyStructureDataHandler == null) { ++ public CompoundTag upgradeChunkTag(ResourceKey resourcekey, Supplier supplier, CompoundTag nbttagcompound, Optional>> optional, ChunkPos pos, @Nullable LevelAccessor generatoraccess) { ++ // CraftBukkit end ++ int i = getVersion(nbttagcompound); ++ ++ // CraftBukkit start ++ if (i < 1466) { ++ CompoundTag level = nbttagcompound.getCompound("Level"); ++ if (level.getBoolean("TerrainPopulated") && !level.getBoolean("LightPopulated")) { ++ ServerChunkCache cps = (generatoraccess == null) ? null : ((ServerLevel) generatoraccess).getChunkSource(); ++ if (check(cps, pos.x - 1, pos.z) && check(cps, pos.x - 1, pos.z - 1) && check(cps, pos.x, pos.z - 1)) { ++ level.putBoolean("LightPopulated", true); ++ } ++ } ++ } ++ // CraftBukkit end ++ ++ if (i < 1493) { ++ nbttagcompound = DataFixTypes.CHUNK.update(this.fixerUpper, nbttagcompound, i, 1493); ++ if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) { ++ LegacyStructureDataHandler persistentstructurelegacy = this.getLegacyStructureHandler(resourcekey, supplier); ++ ++ nbttagcompound = persistentstructurelegacy.updateFromLegacy(nbttagcompound); ++ } ++ } ++ ++ injectDatafixingContext(nbttagcompound, resourcekey, optional); ++ nbttagcompound = DataFixTypes.CHUNK.updateToCurrentVersion(this.fixerUpper, nbttagcompound, Math.max(1493, i)); ++ if (i < SharedConstants.getCurrentVersion().getDataVersion().getVersion()) { ++ NbtUtils.addCurrentDataVersion(nbttagcompound); ++ } ++ ++ nbttagcompound.remove("__context"); ++ return nbttagcompound; ++ } ++ ++ private LegacyStructureDataHandler getLegacyStructureHandler(ResourceKey level, Supplier storage) { // CraftBukkit ++ LegacyStructureDataHandler persistentstructurelegacy = this.legacyStructureHandler; ++ ++ if (persistentstructurelegacy == null) { + synchronized (this) { +- legacyStructureDataHandler = this.legacyStructureHandler; +- if (legacyStructureDataHandler == null) { +- this.legacyStructureHandler = legacyStructureDataHandler = LegacyStructureDataHandler.getLegacyStructureHandler(level, storage.get()); ++ persistentstructurelegacy = this.legacyStructureHandler; ++ if (persistentstructurelegacy == null) { ++ this.legacyStructureHandler = persistentstructurelegacy = LegacyStructureDataHandler.getLegacyStructureHandler(level, (DimensionDataStorage) storage.get()); + } + } + } + +- return legacyStructureDataHandler; ++ return persistentstructurelegacy; + } + +- public static void injectDatafixingContext( +- CompoundTag chunkData, ResourceKey levelKey, Optional>> chunkGeneratorKey +- ) { +- CompoundTag compoundTag = new CompoundTag(); +- compoundTag.putString("dimension", levelKey.location().toString()); +- chunkGeneratorKey.ifPresent(generator -> compoundTag.putString("generator", generator.location().toString())); +- chunkData.put("__context", compoundTag); ++ public static void injectDatafixingContext(CompoundTag chunkData, ResourceKey levelKey, Optional>> chunkGeneratorKey) { // CraftBukkit ++ CompoundTag nbttagcompound1 = new CompoundTag(); ++ ++ nbttagcompound1.putString("dimension", levelKey.location().toString()); ++ chunkGeneratorKey.ifPresent((resourcekey1) -> { ++ nbttagcompound1.putString("generator", resourcekey1.location().toString()); ++ }); ++ chunkData.put("__context", nbttagcompound1); + } + + public static int getVersion(CompoundTag chunkData) { +@@ -96,13 +146,13 @@ + if (this.legacyStructureHandler != null) { + this.legacyStructureHandler.removeIndex(chunkPos.toLong()); + } ++ + } + + public void flushWorker() { + this.worker.synchronize(true).join(); + } + +- @Override + public void close() throws IOException { + this.worker.close(); + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/storage/RegionFile.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/storage/RegionFile.java.patch new file mode 100644 index 0000000000..7ba10d324a --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/storage/RegionFile.java.patch @@ -0,0 +1,537 @@ +--- a/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.world.level.chunk.storage; + + import com.google.common.annotations.VisibleForTesting; +@@ -8,10 +9,12 @@ + import java.io.DataOutputStream; + import java.io.IOException; + import java.io.InputStream; ++import java.io.OutputStream; + import java.nio.ByteBuffer; + import java.nio.IntBuffer; + import java.nio.channels.FileChannel; + import java.nio.file.Files; ++import java.nio.file.LinkOption; + import java.nio.file.Path; + import java.nio.file.StandardCopyOption; + import java.nio.file.StandardOpenOption; +@@ -21,6 +24,7 @@ + import org.slf4j.Logger; + + public class RegionFile implements AutoCloseable { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int SECTOR_BYTES = 4096; + @VisibleForTesting +@@ -35,25 +39,27 @@ + private final FileChannel file; + private final Path externalFileDir; + final RegionFileVersion version; +- private final ByteBuffer header = ByteBuffer.allocateDirect(8192); ++ private final ByteBuffer header; + private final IntBuffer offsets; + private final IntBuffer timestamps; + @VisibleForTesting +- protected final RegionBitmap usedSectors = new RegionBitmap(); ++ protected final RegionBitmap usedSectors; + + public RegionFile(Path regionFile, Path containingFolder, boolean sync) throws IOException { + this(regionFile, containingFolder, RegionFileVersion.VERSION_DEFLATE, sync); + } + + public RegionFile(Path regionFile, Path containingFolder, RegionFileVersion version, boolean sync) throws IOException { ++ this.header = ByteBuffer.allocateDirect(8192); ++ this.usedSectors = new RegionBitmap(); + this.version = version; +- if (!Files.isDirectory(containingFolder)) { ++ if (!Files.isDirectory(containingFolder, new LinkOption[0])) { + throw new IllegalArgumentException("Expected directory, got " + containingFolder.toAbsolutePath()); + } else { + this.externalFileDir = containingFolder; + this.offsets = this.header.asIntBuffer(); +- this.offsets.limit(1024); +- this.header.position(4096); ++ ((java.nio.Buffer) this.offsets).limit(1024); // CraftBukkit - decompile error ++ ((java.nio.Buffer) this.header).position(4096); // CraftBukkit - decompile error + this.timestamps = this.header.asIntBuffer(); + if (sync) { + this.file = FileChannel.open(regionFile, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.DSYNC); +@@ -62,80 +68,89 @@ + } + + this.usedSectors.force(0, 2); +- this.header.position(0); ++ ((java.nio.Buffer) this.header).position(0); // CraftBukkit - decompile error + int i = this.file.read(this.header, 0L); ++ + if (i != -1) { + if (i != 8192) { +- LOGGER.warn("Region file {} has truncated header: {}", regionFile, i); ++ RegionFile.LOGGER.warn("Region file {} has truncated header: {}", regionFile, i); + } + +- long size = Files.size(regionFile); ++ long j = Files.size(regionFile); + +- for (int i1 = 0; i1 < 1024; i1++) { +- int i2 = this.offsets.get(i1); +- if (i2 != 0) { +- int sectorNumber = getSectorNumber(i2); +- int numSectors = getNumSectors(i2); +- if (sectorNumber < 2) { +- LOGGER.warn("Region file {} has invalid sector at index: {}; sector {} overlaps with header", regionFile, i1, sectorNumber); +- this.offsets.put(i1, 0); +- } else if (numSectors == 0) { +- LOGGER.warn("Region file {} has an invalid sector at index: {}; size has to be > 0", regionFile, i1); +- this.offsets.put(i1, 0); +- } else if ((long)sectorNumber * 4096L > size) { +- LOGGER.warn("Region file {} has an invalid sector at index: {}; sector {} is out of bounds", regionFile, i1, sectorNumber); +- this.offsets.put(i1, 0); ++ for (int k = 0; k < 1024; ++k) { ++ int l = this.offsets.get(k); ++ ++ if (l != 0) { ++ int i1 = getSectorNumber(l); ++ int j1 = getNumSectors(l); ++ ++ if (i1 < 2) { ++ RegionFile.LOGGER.warn("Region file {} has invalid sector at index: {}; sector {} overlaps with header", new Object[]{regionFile, k, i1}); ++ this.offsets.put(k, 0); ++ } else if (j1 == 0) { ++ RegionFile.LOGGER.warn("Region file {} has an invalid sector at index: {}; size has to be > 0", regionFile, k); ++ this.offsets.put(k, 0); ++ } else if ((long) i1 * 4096L > j) { ++ RegionFile.LOGGER.warn("Region file {} has an invalid sector at index: {}; sector {} is out of bounds", new Object[]{regionFile, k, i1}); ++ this.offsets.put(k, 0); + } else { +- this.usedSectors.force(sectorNumber, numSectors); ++ this.usedSectors.force(i1, j1); + } + } + } + } ++ + } + } + + private Path getExternalChunkPath(ChunkPos chunkPos) { +- String string = "c." + chunkPos.x + "." + chunkPos.z + ".mcc"; +- return this.externalFileDir.resolve(string); ++ String s = "c." + chunkPos.x + "." + chunkPos.z + ".mcc"; ++ ++ return this.externalFileDir.resolve(s); + } + + @Nullable + public synchronized DataInputStream getChunkDataInputStream(ChunkPos chunkPos) throws IOException { +- int offset = this.getOffset(chunkPos); +- if (offset == 0) { ++ int i = this.getOffset(chunkPos); ++ ++ if (i == 0) { + return null; + } else { +- int sectorNumber = getSectorNumber(offset); +- int numSectors = getNumSectors(offset); +- int i = numSectors * 4096; +- ByteBuffer byteBuffer = ByteBuffer.allocate(i); +- this.file.read(byteBuffer, (long)(sectorNumber * 4096)); +- byteBuffer.flip(); +- if (byteBuffer.remaining() < 5) { +- LOGGER.error("Chunk {} header is truncated: expected {} but read {}", chunkPos, i, byteBuffer.remaining()); ++ int j = getSectorNumber(i); ++ int k = getNumSectors(i); ++ int l = k * 4096; ++ ByteBuffer bytebuffer = ByteBuffer.allocate(l); ++ ++ this.file.read(bytebuffer, (long) (j * 4096)); ++ ((java.nio.Buffer) bytebuffer).flip(); // CraftBukkit - decompile error ++ if (bytebuffer.remaining() < 5) { ++ RegionFile.LOGGER.error("Chunk {} header is truncated: expected {} but read {}", new Object[]{chunkPos, l, bytebuffer.remaining()}); + return null; + } else { +- int _int = byteBuffer.getInt(); +- byte b = byteBuffer.get(); +- if (_int == 0) { +- LOGGER.warn("Chunk {} is allocated, but stream is missing", chunkPos); ++ int i1 = bytebuffer.getInt(); ++ byte b0 = bytebuffer.get(); ++ ++ if (i1 == 0) { ++ RegionFile.LOGGER.warn("Chunk {} is allocated, but stream is missing", chunkPos); + return null; + } else { +- int i1 = _int - 1; +- if (isExternalStreamChunk(b)) { +- if (i1 != 0) { +- LOGGER.warn("Chunk has both internal and external streams"); ++ int j1 = i1 - 1; ++ ++ if (isExternalStreamChunk(b0)) { ++ if (j1 != 0) { ++ RegionFile.LOGGER.warn("Chunk has both internal and external streams"); + } + +- return this.createExternalChunkInputStream(chunkPos, getExternalChunkVersion(b)); +- } else if (i1 > byteBuffer.remaining()) { +- LOGGER.error("Chunk {} stream is truncated: expected {} but read {}", chunkPos, i1, byteBuffer.remaining()); ++ return this.createExternalChunkInputStream(chunkPos, getExternalChunkVersion(b0)); ++ } else if (j1 > bytebuffer.remaining()) { ++ RegionFile.LOGGER.error("Chunk {} stream is truncated: expected {} but read {}", new Object[]{chunkPos, j1, bytebuffer.remaining()}); + return null; +- } else if (i1 < 0) { +- LOGGER.error("Declared size {} of chunk {} is negative", _int, chunkPos); ++ } else if (j1 < 0) { ++ RegionFile.LOGGER.error("Declared size {} of chunk {} is negative", i1, chunkPos); + return null; + } else { +- return this.createChunkInputStream(chunkPos, b, createStream(byteBuffer, i1)); ++ return this.createChunkInputStream(chunkPos, b0, createStream(bytebuffer, j1)); + } + } + } +@@ -143,7 +158,7 @@ + } + + private static int getTimestamp() { +- return (int)(Util.getEpochMillis() / 1000L); ++ return (int) (Util.getEpochMillis() / 1000L); + } + + private static boolean isExternalStreamChunk(byte versionByte) { +@@ -151,28 +166,30 @@ + } + + private static byte getExternalChunkVersion(byte versionByte) { +- return (byte)(versionByte & -129); ++ return (byte) (versionByte & -129); + } + + @Nullable + private DataInputStream createChunkInputStream(ChunkPos chunkPos, byte versionByte, InputStream inputStream) throws IOException { +- RegionFileVersion regionFileVersion = RegionFileVersion.fromId(versionByte); +- if (regionFileVersion == null) { +- LOGGER.error("Chunk {} has invalid chunk stream version {}", chunkPos, versionByte); ++ RegionFileVersion regionfilecompression = RegionFileVersion.fromId(versionByte); ++ ++ if (regionfilecompression == null) { ++ RegionFile.LOGGER.error("Chunk {} has invalid chunk stream version {}", chunkPos, versionByte); + return null; + } else { +- return new DataInputStream(regionFileVersion.wrap(inputStream)); ++ return new DataInputStream(regionfilecompression.wrap(inputStream)); + } + } + + @Nullable + private DataInputStream createExternalChunkInputStream(ChunkPos chunkPos, byte versionByte) throws IOException { +- Path externalChunkPath = this.getExternalChunkPath(chunkPos); +- if (!Files.isRegularFile(externalChunkPath)) { +- LOGGER.error("External chunk path {} is not file", externalChunkPath); ++ Path path = this.getExternalChunkPath(chunkPos); ++ ++ if (!Files.isRegularFile(path, new LinkOption[0])) { ++ RegionFile.LOGGER.error("External chunk path {} is not file", path); + return null; + } else { +- return this.createChunkInputStream(chunkPos, versionByte, Files.newInputStream(externalChunkPath)); ++ return this.createChunkInputStream(chunkPos, versionByte, Files.newInputStream(path)); + } + } + +@@ -185,7 +202,7 @@ + } + + private static int getNumSectors(int packedSectorOffset) { +- return packedSectorOffset & 0xFF; ++ return packedSectorOffset & 255; + } + + private static int getSectorNumber(int packedSectorOffset) { +@@ -197,55 +214,58 @@ + } + + public boolean doesChunkExist(ChunkPos chunkPos) { +- int offset = this.getOffset(chunkPos); +- if (offset == 0) { ++ int i = this.getOffset(chunkPos); ++ ++ if (i == 0) { + return false; + } else { +- int sectorNumber = getSectorNumber(offset); +- int numSectors = getNumSectors(offset); +- ByteBuffer byteBuffer = ByteBuffer.allocate(5); ++ int j = getSectorNumber(i); ++ int k = getNumSectors(i); ++ ByteBuffer bytebuffer = ByteBuffer.allocate(5); + + try { +- this.file.read(byteBuffer, (long)(sectorNumber * 4096)); +- byteBuffer.flip(); +- if (byteBuffer.remaining() != 5) { ++ this.file.read(bytebuffer, (long) (j * 4096)); ++ ((java.nio.Buffer) bytebuffer).flip(); // CraftBukkit - decompile error ++ if (bytebuffer.remaining() != 5) { + return false; + } else { +- int _int = byteBuffer.getInt(); +- byte b = byteBuffer.get(); +- if (isExternalStreamChunk(b)) { +- if (!RegionFileVersion.isValidVersion(getExternalChunkVersion(b))) { ++ int l = bytebuffer.getInt(); ++ byte b0 = bytebuffer.get(); ++ ++ if (isExternalStreamChunk(b0)) { ++ if (!RegionFileVersion.isValidVersion(getExternalChunkVersion(b0))) { + return false; + } + +- if (!Files.isRegularFile(this.getExternalChunkPath(chunkPos))) { ++ if (!Files.isRegularFile(this.getExternalChunkPath(chunkPos), new LinkOption[0])) { + return false; + } + } else { +- if (!RegionFileVersion.isValidVersion(b)) { ++ if (!RegionFileVersion.isValidVersion(b0)) { + return false; + } + +- if (_int == 0) { ++ if (l == 0) { + return false; + } + +- int i = _int - 1; +- if (i < 0 || i > 4096 * numSectors) { ++ int i1 = l - 1; ++ ++ if (i1 < 0 || i1 > 4096 * k) { + return false; + } + } + + return true; + } +- } catch (IOException var9) { ++ } catch (IOException ioexception) { + return false; + } + } + } + + public DataOutputStream getChunkDataOutputStream(ChunkPos chunkPos) throws IOException { +- return new DataOutputStream(this.version.wrap(new RegionFile.ChunkBuffer(chunkPos))); ++ return new DataOutputStream(this.version.wrap((OutputStream) (new RegionFile.ChunkBuffer(chunkPos)))); + } + + public void flush() throws IOException { +@@ -253,70 +273,95 @@ + } + + public void clear(ChunkPos chunkPos) throws IOException { +- int offsetIndex = getOffsetIndex(chunkPos); +- int i = this.offsets.get(offsetIndex); +- if (i != 0) { +- this.offsets.put(offsetIndex, 0); +- this.timestamps.put(offsetIndex, getTimestamp()); ++ int i = getOffsetIndex(chunkPos); ++ int j = this.offsets.get(i); ++ ++ if (j != 0) { ++ this.offsets.put(i, 0); ++ this.timestamps.put(i, getTimestamp()); + this.writeHeader(); + Files.deleteIfExists(this.getExternalChunkPath(chunkPos)); +- this.usedSectors.free(getSectorNumber(i), getNumSectors(i)); ++ this.usedSectors.free(getSectorNumber(j), getNumSectors(j)); + } + } + + protected synchronized void write(ChunkPos chunkPos, ByteBuffer chunkData) throws IOException { +- int offsetIndex = getOffsetIndex(chunkPos); +- int i = this.offsets.get(offsetIndex); +- int sectorNumber = getSectorNumber(i); +- int numSectors = getNumSectors(i); ++ int i = getOffsetIndex(chunkPos); ++ int j = this.offsets.get(i); ++ int k = getSectorNumber(j); ++ int l = getNumSectors(j); + int i1 = chunkData.remaining(); +- int i2 = sizeToSectors(i1); +- int i3; +- RegionFile.CommitOp commitOp; +- if (i2 >= 256) { +- Path externalChunkPath = this.getExternalChunkPath(chunkPos); +- LOGGER.warn("Saving oversized chunk {} ({} bytes} to external file {}", chunkPos, i1, externalChunkPath); +- i2 = 1; +- i3 = this.usedSectors.allocate(i2); +- commitOp = this.writeToExternalFile(externalChunkPath, chunkData); +- ByteBuffer byteBuffer = this.createExternalStub(); +- this.file.write(byteBuffer, (long)(i3 * 4096)); ++ int j1 = sizeToSectors(i1); ++ int k1; ++ RegionFile.b regionfile_b; ++ ++ if (j1 >= 256) { ++ Path path = this.getExternalChunkPath(chunkPos); ++ ++ RegionFile.LOGGER.warn("Saving oversized chunk {} ({} bytes} to external file {}", new Object[]{chunkPos, i1, path}); ++ j1 = 1; ++ k1 = this.usedSectors.allocate(j1); ++ regionfile_b = this.writeToExternalFile(path, chunkData); ++ ByteBuffer bytebuffer1 = this.createExternalStub(); ++ ++ this.file.write(bytebuffer1, (long) (k1 * 4096)); + } else { +- i3 = this.usedSectors.allocate(i2); +- commitOp = () -> Files.deleteIfExists(this.getExternalChunkPath(chunkPos)); +- this.file.write(chunkData, (long)(i3 * 4096)); ++ k1 = this.usedSectors.allocate(j1); ++ regionfile_b = () -> { ++ Files.deleteIfExists(this.getExternalChunkPath(chunkPos)); ++ }; ++ this.file.write(chunkData, (long) (k1 * 4096)); + } + +- this.offsets.put(offsetIndex, this.packSectorOffset(i3, i2)); +- this.timestamps.put(offsetIndex, getTimestamp()); ++ this.offsets.put(i, this.packSectorOffset(k1, j1)); ++ this.timestamps.put(i, getTimestamp()); + this.writeHeader(); +- commitOp.run(); +- if (sectorNumber != 0) { +- this.usedSectors.free(sectorNumber, numSectors); ++ regionfile_b.run(); ++ if (k != 0) { ++ this.usedSectors.free(k, l); + } ++ + } + + private ByteBuffer createExternalStub() { +- ByteBuffer byteBuffer = ByteBuffer.allocate(5); +- byteBuffer.putInt(1); +- byteBuffer.put((byte)(this.version.getId() | 128)); +- byteBuffer.flip(); +- return byteBuffer; ++ ByteBuffer bytebuffer = ByteBuffer.allocate(5); ++ ++ bytebuffer.putInt(1); ++ bytebuffer.put((byte) (this.version.getId() | 128)); ++ ((java.nio.Buffer) bytebuffer).flip(); // CraftBukkit - decompile error ++ return bytebuffer; + } + +- private RegionFile.CommitOp writeToExternalFile(Path externalChunkFile, ByteBuffer chunkData) throws IOException { +- Path path = Files.createTempFile(this.externalFileDir, "tmp", null); ++ private RegionFile.b writeToExternalFile(Path externalChunkFile, ByteBuffer chunkData) throws IOException { ++ Path path1 = Files.createTempFile(this.externalFileDir, "tmp", (String) null); ++ FileChannel filechannel = FileChannel.open(path1, StandardOpenOption.CREATE, StandardOpenOption.WRITE); + +- try (FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) { +- chunkData.position(5); +- fileChannel.write(chunkData); ++ try { ++ ((java.nio.Buffer) chunkData).position(5); // CraftBukkit - decompile error ++ filechannel.write(chunkData); ++ } catch (Throwable throwable) { ++ if (filechannel != null) { ++ try { ++ filechannel.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } + +- return () -> Files.move(path, externalChunkFile, StandardCopyOption.REPLACE_EXISTING); ++ if (filechannel != null) { ++ filechannel.close(); ++ } ++ ++ return () -> { ++ Files.move(path1, externalChunkFile, StandardCopyOption.REPLACE_EXISTING); ++ }; + } + + private void writeHeader() throws IOException { +- this.header.position(0); ++ ((java.nio.Buffer) this.header).position(0); // CraftBukkit - decompile error + this.file.write(this.header, 0L); + } + +@@ -332,7 +377,6 @@ + return chunkPos.getRegionLocalX() + chunkPos.getRegionLocalZ() * 32; + } + +- @Override + public void close() throws IOException { + try { + this.padToFullSector(); +@@ -343,40 +387,46 @@ + this.file.close(); + } + } ++ + } + + private void padToFullSector() throws IOException { +- int i = (int)this.file.size(); +- int i1 = sizeToSectors(i) * 4096; +- if (i != i1) { +- ByteBuffer byteBuffer = PADDING_BUFFER.duplicate(); +- byteBuffer.position(0); +- this.file.write(byteBuffer, (long)(i1 - 1)); ++ int i = (int) this.file.size(); ++ int j = sizeToSectors(i) * 4096; ++ ++ if (i != j) { ++ ByteBuffer bytebuffer = RegionFile.PADDING_BUFFER.duplicate(); ++ ++ ((java.nio.Buffer) bytebuffer).position(0); // CraftBukkit - decompile error ++ this.file.write(bytebuffer, (long) (j - 1)); + } ++ + } + +- class ChunkBuffer extends ByteArrayOutputStream { ++ private class ChunkBuffer extends ByteArrayOutputStream { ++ + private final ChunkPos pos; + +- public ChunkBuffer(ChunkPos pos) { ++ public ChunkBuffer(ChunkPos chunkcoordintpair) { + super(8096); + super.write(0); + super.write(0); + super.write(0); + super.write(0); + super.write(RegionFile.this.version.getId()); +- this.pos = pos; ++ this.pos = chunkcoordintpair; + } + +- @Override + public void close() throws IOException { +- ByteBuffer byteBuffer = ByteBuffer.wrap(this.buf, 0, this.count); +- byteBuffer.putInt(0, this.count - 5 + 1); +- RegionFile.this.write(this.pos, byteBuffer); ++ ByteBuffer bytebuffer = ByteBuffer.wrap(this.buf, 0, this.count); ++ ++ bytebuffer.putInt(0, this.count - 5 + 1); ++ RegionFile.this.write(this.pos, bytebuffer); + } + } + +- interface CommitOp { ++ private interface b { ++ + void run() throws IOException; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch new file mode 100644 index 0000000000..a6c314e750 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch @@ -0,0 +1,220 @@ +--- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -1,7 +1,10 @@ + package net.minecraft.world.level.chunk.storage; + + import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectIterator; ++import java.io.DataInput; + import java.io.DataInputStream; ++import java.io.DataOutput; + import java.io.DataOutputStream; + import java.io.IOException; + import java.nio.file.Path; +@@ -15,9 +18,10 @@ + import net.minecraft.world.level.ChunkPos; + + public final class RegionFileStorage implements AutoCloseable { ++ + public static final String ANVIL_EXTENSION = ".mca"; + private static final int MAX_CACHE_SIZE = 256; +- private final Long2ObjectLinkedOpenHashMap regionCache = new Long2ObjectLinkedOpenHashMap<>(); ++ public final Long2ObjectLinkedOpenHashMap regionCache = new Long2ObjectLinkedOpenHashMap(); + private final Path folder; + private final boolean sync; + +@@ -26,79 +30,160 @@ + this.sync = sync; + } + +- private RegionFile getRegionFile(ChunkPos chunkPos) throws IOException { +- long _long = ChunkPos.asLong(chunkPos.getRegionX(), chunkPos.getRegionZ()); +- RegionFile regionFile = this.regionCache.getAndMoveToFirst(_long); +- if (regionFile != null) { +- return regionFile; ++ private RegionFile getRegionFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit ++ long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); ++ RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i); ++ ++ if (regionfile != null) { ++ return regionfile; + } else { + if (this.regionCache.size() >= 256) { +- this.regionCache.removeLast().close(); ++ ((RegionFile) this.regionCache.removeLast()).close(); + } + + FileUtil.createDirectoriesSafe(this.folder); +- Path path = this.folder.resolve("r." + chunkPos.getRegionX() + "." + chunkPos.getRegionZ() + ".mca"); +- RegionFile regionFile1 = new RegionFile(path, this.folder, this.sync); +- this.regionCache.putAndMoveToFirst(_long, regionFile1); +- return regionFile1; ++ Path path = this.folder; ++ int j = chunkcoordintpair.getRegionX(); ++ Path path1 = path.resolve("r." + j + "." + chunkcoordintpair.getRegionZ() + ".mca"); ++ if (existingOnly && !java.nio.file.Files.exists(path1)) return null; // CraftBukkit ++ RegionFile regionfile1 = new RegionFile(path1, this.folder, this.sync); ++ ++ this.regionCache.putAndMoveToFirst(i, regionfile1); ++ return regionfile1; + } + } + + @Nullable + public CompoundTag read(ChunkPos chunkPos) throws IOException { +- RegionFile regionFile = this.getRegionFile(chunkPos); ++ // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing ++ RegionFile regionfile = this.getRegionFile(chunkPos, true); ++ if (regionfile == null) { ++ return null; ++ } ++ // CraftBukkit end ++ DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkPos); + +- CompoundTag var4; +- try (DataInputStream chunkDataInputStream = regionFile.getChunkDataInputStream(chunkPos)) { +- if (chunkDataInputStream == null) { +- return null; ++ CompoundTag nbttagcompound; ++ label43: ++ { ++ try { ++ if (datainputstream != null) { ++ nbttagcompound = NbtIo.read((DataInput) datainputstream); ++ break label43; ++ } ++ ++ nbttagcompound = null; ++ } catch (Throwable throwable) { ++ if (datainputstream != null) { ++ try { ++ datainputstream.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } + +- var4 = NbtIo.read(chunkDataInputStream); ++ if (datainputstream != null) { ++ datainputstream.close(); ++ } ++ ++ return nbttagcompound; + } + +- return var4; ++ if (datainputstream != null) { ++ datainputstream.close(); ++ } ++ ++ return nbttagcompound; + } + + public void scanChunk(ChunkPos chunkPos, StreamTagVisitor visitor) throws IOException { +- RegionFile regionFile = this.getRegionFile(chunkPos); ++ // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing ++ RegionFile regionfile = this.getRegionFile(chunkPos, true); ++ if (regionfile == null) { ++ return; ++ } ++ // CraftBukkit end ++ DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkPos); + +- try (DataInputStream chunkDataInputStream = regionFile.getChunkDataInputStream(chunkPos)) { +- if (chunkDataInputStream != null) { +- NbtIo.parse(chunkDataInputStream, visitor, NbtAccounter.unlimitedHeap()); ++ try { ++ if (datainputstream != null) { ++ NbtIo.parse(datainputstream, visitor, NbtAccounter.unlimitedHeap()); + } ++ } catch (Throwable throwable) { ++ if (datainputstream != null) { ++ try { ++ datainputstream.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } ++ ++ if (datainputstream != null) { ++ datainputstream.close(); ++ } ++ + } + + protected void write(ChunkPos chunkPos, @Nullable CompoundTag chunkData) throws IOException { +- RegionFile regionFile = this.getRegionFile(chunkPos); ++ RegionFile regionfile = this.getRegionFile(chunkPos, false); // CraftBukkit ++ + if (chunkData == null) { +- regionFile.clear(chunkPos); ++ regionfile.clear(chunkPos); + } else { +- try (DataOutputStream chunkDataOutputStream = regionFile.getChunkDataOutputStream(chunkPos)) { +- NbtIo.write(chunkData, chunkDataOutputStream); ++ DataOutputStream dataoutputstream = regionfile.getChunkDataOutputStream(chunkPos); ++ ++ try { ++ NbtIo.write(chunkData, (DataOutput) dataoutputstream); ++ } catch (Throwable throwable) { ++ if (dataoutputstream != null) { ++ try { ++ dataoutputstream.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } ++ ++ if (dataoutputstream != null) { ++ dataoutputstream.close(); ++ } + } ++ + } + +- @Override + public void close() throws IOException { +- ExceptionCollector exceptionCollector = new ExceptionCollector<>(); ++ ExceptionCollector exceptionsuppressor = new ExceptionCollector<>(); ++ ObjectIterator objectiterator = this.regionCache.values().iterator(); + +- for (RegionFile regionFile : this.regionCache.values()) { ++ while (objectiterator.hasNext()) { ++ RegionFile regionfile = (RegionFile) objectiterator.next(); ++ + try { +- regionFile.close(); +- } catch (IOException var5) { +- exceptionCollector.add(var5); ++ regionfile.close(); ++ } catch (IOException ioexception) { ++ exceptionsuppressor.add(ioexception); + } + } + +- exceptionCollector.throwIfPresent(); ++ exceptionsuppressor.throwIfPresent(); + } + + public void flush() throws IOException { +- for (RegionFile regionFile : this.regionCache.values()) { +- regionFile.flush(); ++ ObjectIterator objectiterator = this.regionCache.values().iterator(); ++ ++ while (objectiterator.hasNext()) { ++ RegionFile regionfile = (RegionFile) objectiterator.next(); ++ ++ regionfile.flush(); + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/dimension/end/EndDragonFight.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/dimension/end/EndDragonFight.java.patch new file mode 100644 index 0000000000..8bf87866a5 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/dimension/end/EndDragonFight.java.patch @@ -0,0 +1,759 @@ +--- a/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -9,8 +9,9 @@ + import com.mojang.logging.LogUtils; + import com.mojang.serialization.Codec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import it.unimi.dsi.fastutil.objects.ObjectArrayList; ++import java.util.Collection; ++import java.util.Iterator; + import java.util.List; + import java.util.Optional; + import java.util.Set; +@@ -21,8 +22,6 @@ + import net.minecraft.advancements.CriteriaTriggers; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.Holder; +-import net.minecraft.core.Registry; + import net.minecraft.core.UUIDUtil; + import net.minecraft.core.registries.Registries; + import net.minecraft.data.worldgen.features.EndFeatures; +@@ -55,13 +54,15 @@ + import net.minecraft.world.level.chunk.ChunkStatus; + import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.level.levelgen.Heightmap; ++import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; + import net.minecraft.world.level.levelgen.feature.EndPodiumFeature; + import net.minecraft.world.level.levelgen.feature.SpikeFeature; +-import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; ++import net.minecraft.world.level.levelgen.feature.configurations.WorldGenFeatureConfiguration; + import net.minecraft.world.phys.AABB; + import org.slf4j.Logger; + + public class EndDragonFight { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int MAX_TICKS_BEFORE_DRAGON_RESPAWN = 1200; + private static final int TIME_BETWEEN_CRYSTAL_SCANS = 100; +@@ -72,66 +73,61 @@ + private static final int GATEWAY_DISTANCE = 96; + public static final int DRAGON_SPAWN_Y = 128; + private final Predicate validPlayer; +- private final ServerBossEvent dragonEvent = (ServerBossEvent)new ServerBossEvent( +- Component.translatable("entity.minecraft.ender_dragon"), BossEvent.BossBarColor.PINK, BossEvent.BossBarOverlay.PROGRESS +- ) +- .setPlayBossMusic(true) +- .setCreateWorldFog(true); +- private final ServerLevel level; ++ public final ServerBossEvent dragonEvent; ++ public final ServerLevel level; + private final BlockPos origin; +- private final ObjectArrayList gateways = new ObjectArrayList<>(); ++ private final ObjectArrayList gateways; + private final BlockPattern exitPortalPattern; + private int ticksSinceDragonSeen; + private int crystalsAlive; + private int ticksSinceCrystalsScanned; +- private int ticksSinceLastPlayerScan = 21; ++ private int ticksSinceLastPlayerScan; + private boolean dragonKilled; + private boolean previouslyKilled; +- private boolean skipArenaLoadedCheck = false; ++ private boolean skipArenaLoadedCheck; + @Nullable +- private UUID dragonUUID; +- private boolean needsStateScanning = true; ++ public UUID dragonUUID; ++ private boolean needsStateScanning; + @Nullable +- private BlockPos portalLocation; ++ public BlockPos portalLocation; + @Nullable +- private DragonRespawnAnimation respawnStage; ++ public DragonRespawnAnimation respawnStage; + private int respawnTime; + @Nullable + private List respawnCrystals; + +- public EndDragonFight(ServerLevel level, long seed, EndDragonFight.Data data) { +- this(level, seed, data, BlockPos.ZERO); ++ public EndDragonFight(ServerLevel level, long seed, EndDragonFight.Data enderdragonbattle_a) { ++ this(level, seed, enderdragonbattle_a, BlockPos.ZERO); + } + +- public EndDragonFight(ServerLevel level, long seed, EndDragonFight.Data data, BlockPos origin) { ++ public EndDragonFight(ServerLevel level, long seed, EndDragonFight.Data enderdragonbattle_a, BlockPos data) { ++ this.dragonEvent = (ServerBossEvent) (new ServerBossEvent(Component.translatable("entity.minecraft.ender_dragon"), BossEvent.BossBarColor.PINK, BossEvent.BossBarOverlay.PROGRESS)).setPlayBossMusic(true).setCreateWorldFog(true); ++ this.gateways = new ObjectArrayList(); ++ this.ticksSinceLastPlayerScan = 21; ++ this.skipArenaLoadedCheck = false; ++ this.needsStateScanning = true; + this.level = level; +- this.origin = origin; +- this.validPlayer = EntitySelector.ENTITY_STILL_ALIVE +- .and(EntitySelector.withinDistance((double)origin.getX(), (double)(128 + origin.getY()), (double)origin.getZ(), 192.0)); +- this.needsStateScanning = data.needsStateScanning; +- this.dragonUUID = data.dragonUUID.orElse(null); +- this.dragonKilled = data.dragonKilled; +- this.previouslyKilled = data.previouslyKilled; +- if (data.isRespawning) { ++ this.origin = data; ++ this.validPlayer = EntitySelector.ENTITY_STILL_ALIVE.and(EntitySelector.withinDistance((double) data.getX(), (double) (128 + data.getY()), (double) data.getZ(), 192.0D)); ++ this.needsStateScanning = enderdragonbattle_a.needsStateScanning; ++ this.dragonUUID = (UUID) enderdragonbattle_a.dragonUUID.orElse(null); // CraftBukkit - decompile error ++ this.dragonKilled = enderdragonbattle_a.dragonKilled; ++ this.previouslyKilled = enderdragonbattle_a.previouslyKilled; ++ if (enderdragonbattle_a.isRespawning) { + this.respawnStage = DragonRespawnAnimation.START; + } + +- this.portalLocation = data.exitPortalLocation.orElse(null); +- this.gateways.addAll(data.gateways.orElseGet(() -> { +- ObjectArrayList list = new ObjectArrayList<>(ContiguousSet.create(Range.closedOpen(0, 20), DiscreteDomain.integers())); +- Util.shuffle(list, RandomSource.create(seed)); +- return list; ++ this.portalLocation = (BlockPos) enderdragonbattle_a.exitPortalLocation.orElse(null); // CraftBukkit - decompile error ++ this.gateways.addAll((Collection) enderdragonbattle_a.gateways.orElseGet(() -> { ++ ObjectArrayList objectarraylist = new ObjectArrayList(ContiguousSet.create(Range.closedOpen(0, 20), DiscreteDomain.integers())); ++ ++ Util.shuffle(objectarraylist, RandomSource.create(seed)); ++ return objectarraylist; + })); +- this.exitPortalPattern = BlockPatternBuilder.start() +- .aisle(" ", " ", " ", " # ", " ", " ", " ") +- .aisle(" ", " ", " ", " # ", " ", " ", " ") +- .aisle(" ", " ", " ", " # ", " ", " ", " ") +- .aisle(" ### ", " # # ", "# #", "# # #", "# #", " # # ", " ### ") +- .aisle(" ", " ### ", " ##### ", " ##### ", " ##### ", " ### ", " ") +- .where('#', BlockInWorld.hasState(BlockPredicate.forBlock(Blocks.BEDROCK))) +- .build(); ++ this.exitPortalPattern = BlockPatternBuilder.start().aisle(" ", " ", " ", " # ", " ", " ", " ").aisle(" ", " ", " ", " # ", " ", " ", " ").aisle(" ", " ", " ", " # ", " ", " ", " ").aisle(" ### ", " # # ", "# #", "# # #", "# #", " # # ", " ### ").aisle(" ", " ### ", " ##### ", " ##### ", " ##### ", " ### ", " ").where('#', BlockInWorld.hasState(BlockPredicate.forBlock(Blocks.BEDROCK))).build(); + } + ++ /** @deprecated */ + @Deprecated + @VisibleForTesting + public void skipArenaLoadedCheck() { +@@ -139,15 +135,7 @@ + } + + public EndDragonFight.Data saveData() { +- return new EndDragonFight.Data( +- this.needsStateScanning, +- this.dragonKilled, +- this.previouslyKilled, +- false, +- Optional.ofNullable(this.dragonUUID), +- Optional.ofNullable(this.portalLocation), +- Optional.of(this.gateways) +- ); ++ return new EndDragonFight.Data(this.needsStateScanning, this.dragonKilled, this.previouslyKilled, false, Optional.ofNullable(this.dragonUUID), Optional.ofNullable(this.portalLocation), Optional.of(this.gateways)); + } + + public void tick() { +@@ -159,14 +147,15 @@ + + if (!this.dragonEvent.getPlayers().isEmpty()) { + this.level.getChunkSource().addRegionTicket(TicketType.DRAGON, new ChunkPos(0, 0), 9, Unit.INSTANCE); +- boolean isArenaLoaded = this.isArenaLoaded(); +- if (this.needsStateScanning && isArenaLoaded) { ++ boolean flag = this.isArenaLoaded(); ++ ++ if (this.needsStateScanning && flag) { + this.scanState(); + this.needsStateScanning = false; + } + + if (this.respawnStage != null) { +- if (this.respawnCrystals == null && isArenaLoaded) { ++ if (this.respawnCrystals == null && flag) { + this.respawnStage = null; + this.tryRespawn(); + } +@@ -175,12 +164,12 @@ + } + + if (!this.dragonKilled) { +- if ((this.dragonUUID == null || ++this.ticksSinceDragonSeen >= 1200) && isArenaLoaded) { ++ if ((this.dragonUUID == null || ++this.ticksSinceDragonSeen >= 1200) && flag) { + this.findOrCreateDragon(); + this.ticksSinceDragonSeen = 0; + } + +- if (++this.ticksSinceCrystalsScanned >= 100 && isArenaLoaded) { ++ if (++this.ticksSinceCrystalsScanned >= 100 && flag) { + this.updateCrystalCount(); + this.ticksSinceCrystalsScanned = 0; + } +@@ -188,33 +177,37 @@ + } else { + this.level.getChunkSource().removeRegionTicket(TicketType.DRAGON, new ChunkPos(0, 0), 9, Unit.INSTANCE); + } ++ + } + + private void scanState() { +- LOGGER.info("Scanning for legacy world dragon fight..."); +- boolean hasActiveExitPortal = this.hasActiveExitPortal(); +- if (hasActiveExitPortal) { +- LOGGER.info("Found that the dragon has been killed in this world already."); ++ EndDragonFight.LOGGER.info("Scanning for legacy world dragon fight..."); ++ boolean flag = this.hasActiveExitPortal(); ++ ++ if (flag) { ++ EndDragonFight.LOGGER.info("Found that the dragon has been killed in this world already."); + this.previouslyKilled = true; + } else { +- LOGGER.info("Found that the dragon has not yet been killed in this world."); ++ EndDragonFight.LOGGER.info("Found that the dragon has not yet been killed in this world."); + this.previouslyKilled = false; + if (this.findExitPortal() == null) { + this.spawnExitPortal(false); + } + } + +- List dragons = this.level.getDragons(); +- if (dragons.isEmpty()) { ++ List list = this.level.getDragons(); ++ ++ if (list.isEmpty()) { + this.dragonKilled = true; + } else { +- EnderDragon enderDragon = dragons.get(0); +- this.dragonUUID = enderDragon.getUUID(); +- LOGGER.info("Found that there's a dragon still alive ({})", enderDragon); ++ EnderDragon entityenderdragon = (EnderDragon) list.get(0); ++ ++ this.dragonUUID = entityenderdragon.getUUID(); ++ EndDragonFight.LOGGER.info("Found that there's a dragon still alive ({})", entityenderdragon); + this.dragonKilled = false; +- if (!hasActiveExitPortal) { +- LOGGER.info("But we didn't have a portal, let's remove it."); +- enderDragon.discard(); ++ if (!flag) { ++ EndDragonFight.LOGGER.info("But we didn't have a portal, let's remove it."); ++ entityenderdragon.discard(); + this.dragonUUID = null; + } + } +@@ -222,20 +215,23 @@ + if (!this.previouslyKilled && this.dragonKilled) { + this.dragonKilled = false; + } ++ + } + + private void findOrCreateDragon() { +- List dragons = this.level.getDragons(); +- if (dragons.isEmpty()) { +- LOGGER.debug("Haven't seen the dragon, respawning it"); ++ List list = this.level.getDragons(); ++ ++ if (list.isEmpty()) { ++ EndDragonFight.LOGGER.debug("Haven't seen the dragon, respawning it"); + this.createNewDragon(); + } else { +- LOGGER.debug("Haven't seen our dragon, but found another one to use."); +- this.dragonUUID = dragons.get(0).getUUID(); ++ EndDragonFight.LOGGER.debug("Haven't seen our dragon, but found another one to use."); ++ this.dragonUUID = ((EnderDragon) list.get(0)).getUUID(); + } ++ + } + +- protected void setRespawnStage(DragonRespawnAnimation state) { ++ public void setRespawnStage(DragonRespawnAnimation state) { + if (this.respawnStage == null) { + throw new IllegalStateException("Dragon respawn isn't in progress, can't skip ahead in the animation."); + } else { +@@ -243,28 +239,45 @@ + if (state == DragonRespawnAnimation.END) { + this.respawnStage = null; + this.dragonKilled = false; +- EnderDragon enderDragon = this.createNewDragon(); +- if (enderDragon != null) { +- for (ServerPlayer serverPlayer : this.dragonEvent.getPlayers()) { +- CriteriaTriggers.SUMMONED_ENTITY.trigger(serverPlayer, enderDragon); ++ EnderDragon entityenderdragon = this.createNewDragon(); ++ ++ if (entityenderdragon != null) { ++ Iterator iterator = this.dragonEvent.getPlayers().iterator(); ++ ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ CriteriaTriggers.SUMMONED_ENTITY.trigger(entityplayer, (Entity) entityenderdragon); + } + } + } else { + this.respawnStage = state; + } ++ + } + } + + private boolean hasActiveExitPortal() { +- for (int i = -8; i <= 8; i++) { +- for (int i1 = -8; i1 <= 8; i1++) { +- LevelChunk chunk = this.level.getChunk(i, i1); ++ for (int i = -8; i <= 8; ++i) { ++ int j = -8; + +- for (BlockEntity blockEntity : chunk.getBlockEntities().values()) { +- if (blockEntity instanceof TheEndPortalBlockEntity) { +- return true; ++ label27: ++ while (j <= 8) { ++ LevelChunk chunk = this.level.getChunk(i, j); ++ Iterator iterator = chunk.getBlockEntities().values().iterator(); ++ ++ BlockEntity tileentity; ++ ++ do { ++ if (!iterator.hasNext()) { ++ ++j; ++ continue label27; + } +- } ++ ++ tileentity = (BlockEntity) iterator.next(); ++ } while (!(tileentity instanceof TheEndPortalBlockEntity)); ++ ++ return true; + } + } + +@@ -272,40 +285,49 @@ + } + + @Nullable +- private BlockPattern.BlockPatternMatch findExitPortal() { +- ChunkPos chunkPos = new ChunkPos(this.origin); ++ public BlockPattern.BlockPatternMatch findExitPortal() { ++ ChunkPos chunkcoordintpair = new ChunkPos(this.origin); + +- for (int i = -8 + chunkPos.x; i <= 8 + chunkPos.x; i++) { +- for (int i1 = -8 + chunkPos.z; i1 <= 8 + chunkPos.z; i1++) { +- LevelChunk chunk = this.level.getChunk(i, i1); ++ int i; + +- for (BlockEntity blockEntity : chunk.getBlockEntities().values()) { +- if (blockEntity instanceof TheEndPortalBlockEntity) { +- BlockPattern.BlockPatternMatch blockPatternMatch = this.exitPortalPattern.find(this.level, blockEntity.getBlockPos()); +- if (blockPatternMatch != null) { +- BlockPos pos = blockPatternMatch.getBlock(3, 3, 3).getPos(); ++ for (int j = -8 + chunkcoordintpair.x; j <= 8 + chunkcoordintpair.x; ++j) { ++ for (i = -8 + chunkcoordintpair.z; i <= 8 + chunkcoordintpair.z; ++i) { ++ LevelChunk chunk = this.level.getChunk(j, i); ++ Iterator iterator = chunk.getBlockEntities().values().iterator(); ++ ++ while (iterator.hasNext()) { ++ BlockEntity tileentity = (BlockEntity) iterator.next(); ++ ++ if (tileentity instanceof TheEndPortalBlockEntity) { ++ BlockPattern.BlockPatternMatch shapedetector_shapedetectorcollection = this.exitPortalPattern.find(this.level, tileentity.getBlockPos()); ++ ++ if (shapedetector_shapedetectorcollection != null) { ++ BlockPos blockposition = shapedetector_shapedetectorcollection.getBlock(3, 3, 3).getPos(); ++ + if (this.portalLocation == null) { +- this.portalLocation = pos; ++ this.portalLocation = blockposition; + } + +- return blockPatternMatch; ++ return shapedetector_shapedetectorcollection; + } + } + } + } + } + +- BlockPos location = EndPodiumFeature.getLocation(this.origin); +- int i1 = this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, location).getY(); ++ BlockPos blockposition1 = EndPodiumFeature.getLocation(this.origin); + +- for (int i2 = i1; i2 >= this.level.getMinBuildHeight(); i2--) { +- BlockPattern.BlockPatternMatch blockPatternMatch1 = this.exitPortalPattern.find(this.level, new BlockPos(location.getX(), i2, location.getZ())); +- if (blockPatternMatch1 != null) { ++ i = this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, blockposition1).getY(); ++ ++ for (int k = i; k >= this.level.getMinBuildHeight(); --k) { ++ BlockPattern.BlockPatternMatch shapedetector_shapedetectorcollection1 = this.exitPortalPattern.find(this.level, new BlockPos(blockposition1.getX(), k, blockposition1.getZ())); ++ ++ if (shapedetector_shapedetectorcollection1 != null) { + if (this.portalLocation == null) { +- this.portalLocation = blockPatternMatch1.getBlock(3, 3, 3).getPos(); ++ this.portalLocation = shapedetector_shapedetectorcollection1.getBlock(3, 3, 3).getPos(); + } + +- return blockPatternMatch1; ++ return shapedetector_shapedetectorcollection1; + } + } + +@@ -316,17 +338,19 @@ + if (this.skipArenaLoadedCheck) { + return true; + } else { +- ChunkPos chunkPos = new ChunkPos(this.origin); ++ ChunkPos chunkcoordintpair = new ChunkPos(this.origin); + +- for (int i = -8 + chunkPos.x; i <= 8 + chunkPos.x; i++) { +- for (int i1 = 8 + chunkPos.z; i1 <= 8 + chunkPos.z; i1++) { +- ChunkAccess chunk = this.level.getChunk(i, i1, ChunkStatus.FULL, false); +- if (!(chunk instanceof LevelChunk)) { ++ for (int i = -8 + chunkcoordintpair.x; i <= 8 + chunkcoordintpair.x; ++i) { ++ for (int j = 8 + chunkcoordintpair.z; j <= 8 + chunkcoordintpair.z; ++j) { ++ ChunkAccess ichunkaccess = this.level.getChunk(i, j, ChunkStatus.FULL, false); ++ ++ if (!(ichunkaccess instanceof LevelChunk)) { + return false; + } + +- FullChunkStatus fullStatus = ((LevelChunk)chunk).getFullStatus(); +- if (!fullStatus.isOrAfter(FullChunkStatus.BLOCK_TICKING)) { ++ FullChunkStatus fullchunkstatus = ((LevelChunk) ichunkaccess).getFullStatus(); ++ ++ if (!fullchunkstatus.isOrAfter(FullChunkStatus.BLOCK_TICKING)) { + return false; + } + } +@@ -338,29 +362,39 @@ + + private void updatePlayers() { + Set set = Sets.newHashSet(); ++ Iterator iterator = this.level.getPlayers(this.validPlayer).iterator(); + +- for (ServerPlayer serverPlayer : this.level.getPlayers(this.validPlayer)) { +- this.dragonEvent.addPlayer(serverPlayer); +- set.add(serverPlayer); ++ while (iterator.hasNext()) { ++ ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ++ ++ this.dragonEvent.addPlayer(entityplayer); ++ set.add(entityplayer); + } + + Set set1 = Sets.newHashSet(this.dragonEvent.getPlayers()); ++ + set1.removeAll(set); ++ Iterator iterator1 = set1.iterator(); + +- for (ServerPlayer serverPlayer1 : set1) { +- this.dragonEvent.removePlayer(serverPlayer1); ++ while (iterator1.hasNext()) { ++ ServerPlayer entityplayer1 = (ServerPlayer) iterator1.next(); ++ ++ this.dragonEvent.removePlayer(entityplayer1); + } ++ + } + + private void updateCrystalCount() { + this.ticksSinceCrystalsScanned = 0; + this.crystalsAlive = 0; + +- for (SpikeFeature.EndSpike endSpike : SpikeFeature.getSpikesForLevel(this.level)) { +- this.crystalsAlive = this.crystalsAlive + this.level.getEntitiesOfClass(EndCrystal.class, endSpike.getTopBoundingBox()).size(); ++ SpikeFeature.EndSpike worldgenender_spike; ++ ++ for (Iterator iterator = SpikeFeature.getSpikesForLevel(this.level).iterator(); iterator.hasNext(); this.crystalsAlive += this.level.getEntitiesOfClass(EndCrystal.class, worldgenender_spike.getTopBoundingBox()).size()) { ++ worldgenender_spike = (SpikeFeature.EndSpike) iterator.next(); + } + +- LOGGER.debug("Found {} end crystals still alive", this.crystalsAlive); ++ EndDragonFight.LOGGER.debug("Found {} end crystals still alive", this.crystalsAlive); + } + + public void setDragonKilled(EnderDragon dragon) { +@@ -370,18 +404,16 @@ + this.spawnExitPortal(true); + this.spawnNewGateway(); + if (!this.previouslyKilled) { +- this.level +- .setBlockAndUpdate( +- this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.getLocation(this.origin)), +- Blocks.DRAGON_EGG.defaultBlockState() +- ); ++ this.level.setBlockAndUpdate(this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.getLocation(this.origin)), Blocks.DRAGON_EGG.defaultBlockState()); + } + + this.previouslyKilled = true; + this.dragonKilled = true; + } ++ + } + ++ /** @deprecated */ + @Deprecated + @VisibleForTesting + public void removeAllGateways() { +@@ -390,56 +422,55 @@ + + private void spawnNewGateway() { + if (!this.gateways.isEmpty()) { +- int i = this.gateways.remove(this.gateways.size() - 1); +- int floor = Mth.floor(96.0 * Math.cos(2.0 * (-Math.PI + (Math.PI / 20) * (double)i))); +- int floor1 = Mth.floor(96.0 * Math.sin(2.0 * (-Math.PI + (Math.PI / 20) * (double)i))); +- this.spawnNewGateway(new BlockPos(floor, 75, floor1)); ++ int i = (Integer) this.gateways.remove(this.gateways.size() - 1); ++ int j = Mth.floor(96.0D * Math.cos(2.0D * (-3.141592653589793D + 0.15707963267948966D * (double) i))); ++ int k = Mth.floor(96.0D * Math.sin(2.0D * (-3.141592653589793D + 0.15707963267948966D * (double) i))); ++ ++ this.spawnNewGateway(new BlockPos(j, 75, k)); + } + } + + private void spawnNewGateway(BlockPos pos) { + this.level.levelEvent(3000, pos, 0); +- this.level +- .registryAccess() +- .registry(Registries.CONFIGURED_FEATURE) +- .flatMap(registry -> registry.getHolder(EndFeatures.END_GATEWAY_DELAYED)) +- .ifPresent(endGatewayFeature -> endGatewayFeature.value().place(this.level, this.level.getChunkSource().getGenerator(), RandomSource.create(), pos)); ++ this.level.registryAccess().registry(Registries.CONFIGURED_FEATURE).flatMap((iregistry) -> { ++ return iregistry.getHolder(EndFeatures.END_GATEWAY_DELAYED); ++ }).ifPresent((holder_c) -> { ++ ((ConfiguredFeature) holder_c.value()).place(this.level, this.level.getChunkSource().getGenerator(), RandomSource.create(), pos); ++ }); + } + +- private void spawnExitPortal(boolean active) { +- EndPodiumFeature endPodiumFeature = new EndPodiumFeature(active); +- if (this.portalLocation == null) { +- this.portalLocation = this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.origin)).below(); ++ public void spawnExitPortal(boolean active) { ++ EndPodiumFeature worldgenendtrophy = new EndPodiumFeature(active); + +- while (this.level.getBlockState(this.portalLocation).is(Blocks.BEDROCK) && this.portalLocation.getY() > this.level.getSeaLevel()) { +- this.portalLocation = this.portalLocation.below(); ++ if (this.portalLocation == null) { ++ for (this.portalLocation = this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, EndPodiumFeature.getLocation(this.origin)).below(); this.level.getBlockState(this.portalLocation).is(Blocks.BEDROCK) && this.portalLocation.getY() > this.level.getSeaLevel(); this.portalLocation = this.portalLocation.below()) { ++ ; + } + } + +- if (endPodiumFeature.place( +- FeatureConfiguration.NONE, this.level, this.level.getChunkSource().getGenerator(), RandomSource.create(), this.portalLocation +- )) { ++ if (worldgenendtrophy.place(WorldGenFeatureConfiguration.NONE, this.level, this.level.getChunkSource().getGenerator(), RandomSource.create(), this.portalLocation)) { + int i = Mth.positiveCeilDiv(4, 16); ++ + this.level.getChunkSource().chunkMap.waitForLightBeforeSending(new ChunkPos(this.portalLocation), i); + } ++ + } + + @Nullable + private EnderDragon createNewDragon() { + this.level.getChunkAt(new BlockPos(this.origin.getX(), 128 + this.origin.getY(), this.origin.getZ())); +- EnderDragon enderDragon = EntityType.ENDER_DRAGON.create(this.level); +- if (enderDragon != null) { +- enderDragon.setDragonFight(this); +- enderDragon.setFightOrigin(this.origin); +- enderDragon.getPhaseManager().setPhase(EnderDragonPhase.HOLDING_PATTERN); +- enderDragon.moveTo( +- (double)this.origin.getX(), (double)(128 + this.origin.getY()), (double)this.origin.getZ(), this.level.random.nextFloat() * 360.0F, 0.0F +- ); +- this.level.addFreshEntity(enderDragon); +- this.dragonUUID = enderDragon.getUUID(); ++ EnderDragon entityenderdragon = (EnderDragon) EntityType.ENDER_DRAGON.create(this.level); ++ ++ if (entityenderdragon != null) { ++ entityenderdragon.setDragonFight(this); ++ entityenderdragon.setFightOrigin(this.origin); ++ entityenderdragon.getPhaseManager().setPhase(EnderDragonPhase.HOLDING_PATTERN); ++ entityenderdragon.moveTo((double) this.origin.getX(), (double) (128 + this.origin.getY()), (double) this.origin.getZ(), this.level.random.nextFloat() * 360.0F, 0.0F); ++ this.level.addFreshEntity(entityenderdragon); ++ this.dragonUUID = entityenderdragon.getUUID(); + } + +- return enderDragon; ++ return entityenderdragon; + } + + public void updateDragon(EnderDragon dragon) { +@@ -450,6 +481,7 @@ + this.dragonEvent.setName(dragon.getDisplayName()); + } + } ++ + } + + public int getCrystalsAlive() { +@@ -458,7 +490,7 @@ + + public void onCrystalDestroyed(EndCrystal crystal, DamageSource dmgSrc) { + if (this.respawnStage != null && this.respawnCrystals.contains(crystal)) { +- LOGGER.debug("Aborting respawn sequence"); ++ EndDragonFight.LOGGER.debug("Aborting respawn sequence"); + this.respawnStage = null; + this.respawnTime = 0; + this.resetSpikeCrystals(); +@@ -466,58 +498,67 @@ + } else { + this.updateCrystalCount(); + Entity entity = this.level.getEntity(this.dragonUUID); ++ + if (entity instanceof EnderDragon) { +- ((EnderDragon)entity).onCrystalDestroyed(crystal, crystal.blockPosition(), dmgSrc); ++ ((EnderDragon) entity).onCrystalDestroyed(crystal, crystal.blockPosition(), dmgSrc); + } + } ++ + } + + public boolean hasPreviouslyKilledDragon() { + return this.previouslyKilled; + } + +- public void tryRespawn() { ++ public boolean tryRespawn() { // CraftBukkit - return boolean + if (this.dragonKilled && this.respawnStage == null) { +- BlockPos blockPos = this.portalLocation; +- if (blockPos == null) { +- LOGGER.debug("Tried to respawn, but need to find the portal first."); +- BlockPattern.BlockPatternMatch blockPatternMatch = this.findExitPortal(); +- if (blockPatternMatch == null) { +- LOGGER.debug("Couldn't find a portal, so we made one."); ++ BlockPos blockposition = this.portalLocation; ++ ++ if (blockposition == null) { ++ EndDragonFight.LOGGER.debug("Tried to respawn, but need to find the portal first."); ++ BlockPattern.BlockPatternMatch shapedetector_shapedetectorcollection = this.findExitPortal(); ++ ++ if (shapedetector_shapedetectorcollection == null) { ++ EndDragonFight.LOGGER.debug("Couldn't find a portal, so we made one."); + this.spawnExitPortal(true); + } else { +- LOGGER.debug("Found the exit portal & saved its location for next time."); ++ EndDragonFight.LOGGER.debug("Found the exit portal & saved its location for next time."); + } + +- blockPos = this.portalLocation; ++ blockposition = this.portalLocation; + } + + List list = Lists.newArrayList(); +- BlockPos blockPos1 = blockPos.above(1); ++ BlockPos blockposition1 = blockposition.above(1); ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- List entitiesOfClass = this.level.getEntitiesOfClass(EndCrystal.class, new AABB(blockPos1.relative(direction, 2))); +- if (entitiesOfClass.isEmpty()) { +- return; ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ List list1 = this.level.getEntitiesOfClass(EndCrystal.class, new AABB(blockposition1.relative(enumdirection, 2))); ++ ++ if (list1.isEmpty()) { ++ return false; // CraftBukkit - return value + } + +- list.addAll(entitiesOfClass); ++ list.addAll(list1); + } + +- LOGGER.debug("Found all crystals, respawning dragon."); +- this.respawnDragon(list); ++ EndDragonFight.LOGGER.debug("Found all crystals, respawning dragon."); ++ return this.respawnDragon(list); // CraftBukkit - return value + } ++ return false; // CraftBukkit - return value + } + +- private void respawnDragon(List crystals) { ++ public boolean respawnDragon(List list) { // CraftBukkit - return boolean + if (this.dragonKilled && this.respawnStage == null) { +- for (BlockPattern.BlockPatternMatch blockPatternMatch = this.findExitPortal(); blockPatternMatch != null; blockPatternMatch = this.findExitPortal()) { +- for (int i = 0; i < this.exitPortalPattern.getWidth(); i++) { +- for (int i1 = 0; i1 < this.exitPortalPattern.getHeight(); i1++) { +- for (int i2 = 0; i2 < this.exitPortalPattern.getDepth(); i2++) { +- BlockInWorld block = blockPatternMatch.getBlock(i, i1, i2); +- if (block.getState().is(Blocks.BEDROCK) || block.getState().is(Blocks.END_PORTAL)) { +- this.level.setBlockAndUpdate(block.getPos(), Blocks.END_STONE.defaultBlockState()); ++ for (BlockPattern.BlockPatternMatch shapedetector_shapedetectorcollection = this.findExitPortal(); shapedetector_shapedetectorcollection != null; shapedetector_shapedetectorcollection = this.findExitPortal()) { ++ for (int i = 0; i < this.exitPortalPattern.getWidth(); ++i) { ++ for (int j = 0; j < this.exitPortalPattern.getHeight(); ++j) { ++ for (int k = 0; k < this.exitPortalPattern.getDepth(); ++k) { ++ BlockInWorld shapedetectorblock = shapedetector_shapedetectorcollection.getBlock(i, j, k); ++ ++ if (shapedetectorblock.getState().is(Blocks.BEDROCK) || shapedetectorblock.getState().is(Blocks.END_PORTAL)) { ++ this.level.setBlockAndUpdate(shapedetectorblock.getPos(), Blocks.END_STONE.defaultBlockState()); + } + } + } +@@ -527,17 +568,28 @@ + this.respawnStage = DragonRespawnAnimation.START; + this.respawnTime = 0; + this.spawnExitPortal(false); +- this.respawnCrystals = crystals; ++ this.respawnCrystals = list; ++ return true; // CraftBukkit - return value + } ++ return false; // CraftBukkit - return value + } + + public void resetSpikeCrystals() { +- for (SpikeFeature.EndSpike endSpike : SpikeFeature.getSpikesForLevel(this.level)) { +- for (EndCrystal endCrystal : this.level.getEntitiesOfClass(EndCrystal.class, endSpike.getTopBoundingBox())) { +- endCrystal.setInvulnerable(false); +- endCrystal.setBeamTarget(null); ++ Iterator iterator = SpikeFeature.getSpikesForLevel(this.level).iterator(); ++ ++ while (iterator.hasNext()) { ++ SpikeFeature.EndSpike worldgenender_spike = (SpikeFeature.EndSpike) iterator.next(); ++ List list = this.level.getEntitiesOfClass(EndCrystal.class, worldgenender_spike.getTopBoundingBox()); ++ Iterator iterator1 = list.iterator(); ++ ++ while (iterator1.hasNext()) { ++ EndCrystal entityendercrystal = (EndCrystal) iterator1.next(); ++ ++ entityendercrystal.setInvulnerable(false); ++ entityendercrystal.setBeamTarget((BlockPos) null); + } + } ++ + } + + @Nullable +@@ -545,29 +597,11 @@ + return this.dragonUUID; + } + +- public static record Data( +- boolean needsStateScanning, +- boolean dragonKilled, +- boolean previouslyKilled, +- boolean isRespawning, +- Optional dragonUUID, +- Optional exitPortalLocation, +- Optional> gateways +- ) { +- public static final Codec CODEC = RecordCodecBuilder.create( +- instance -> instance.group( +- Codec.BOOL.fieldOf("NeedsStateScanning").orElse(true).forGetter(EndDragonFight.Data::needsStateScanning), +- Codec.BOOL.fieldOf("DragonKilled").orElse(false).forGetter(EndDragonFight.Data::dragonKilled), +- Codec.BOOL.fieldOf("PreviouslyKilled").orElse(false).forGetter(EndDragonFight.Data::previouslyKilled), +- Codec.BOOL.optionalFieldOf("IsRespawning", Boolean.valueOf(false)).forGetter(EndDragonFight.Data::isRespawning), +- UUIDUtil.CODEC.optionalFieldOf("Dragon").forGetter(EndDragonFight.Data::dragonUUID), +- BlockPos.CODEC.optionalFieldOf("ExitPortalLocation").forGetter(EndDragonFight.Data::exitPortalLocation), +- Codec.list(Codec.INT).optionalFieldOf("Gateways").forGetter(EndDragonFight.Data::gateways) +- ) +- .apply(instance, EndDragonFight.Data::new) +- ); +- public static final EndDragonFight.Data DEFAULT = new EndDragonFight.Data( +- true, false, false, false, Optional.empty(), Optional.empty(), Optional.empty() +- ); ++ public static record Data(boolean needsStateScanning, boolean dragonKilled, boolean previouslyKilled, boolean isRespawning, Optional dragonUUID, Optional exitPortalLocation, Optional> gateways) { ++ ++ public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(Codec.BOOL.fieldOf("NeedsStateScanning").orElse(true).forGetter(EndDragonFight.Data::needsStateScanning), Codec.BOOL.fieldOf("DragonKilled").orElse(false).forGetter(EndDragonFight.Data::dragonKilled), Codec.BOOL.fieldOf("PreviouslyKilled").orElse(false).forGetter(EndDragonFight.Data::previouslyKilled), Codec.BOOL.optionalFieldOf("IsRespawning", false).forGetter(EndDragonFight.Data::isRespawning), UUIDUtil.CODEC.optionalFieldOf("Dragon").forGetter(EndDragonFight.Data::dragonUUID), BlockPos.CODEC.optionalFieldOf("ExitPortalLocation").forGetter(EndDragonFight.Data::exitPortalLocation), Codec.list(Codec.INT).optionalFieldOf("Gateways").forGetter(EndDragonFight.Data::gateways)).apply(instance, EndDragonFight.Data::new); ++ }); ++ public static final EndDragonFight.Data DEFAULT = new EndDragonFight.Data(true, false, false, false, Optional.empty(), Optional.empty(), Optional.empty()); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/entity/PersistentEntitySectionManager.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/entity/PersistentEntitySectionManager.java.patch new file mode 100644 index 0000000000..cf76deaf1e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/entity/PersistentEntitySectionManager.java.patch @@ -0,0 +1,650 @@ +--- a/net/minecraft/world/level/entity/PersistentEntitySectionManager.java ++++ b/net/minecraft/world/level/entity/PersistentEntitySectionManager.java +@@ -5,18 +5,21 @@ + import com.google.common.collect.Sets; + import com.mojang.logging.LogUtils; + import it.unimi.dsi.fastutil.longs.Long2ObjectMap; ++import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; + import it.unimi.dsi.fastutil.longs.Long2ObjectMaps; + import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; + import it.unimi.dsi.fastutil.longs.LongOpenHashSet; + import it.unimi.dsi.fastutil.longs.LongSet; +-import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; ++import it.unimi.dsi.fastutil.objects.ObjectIterator; + import java.io.IOException; + import java.io.UncheckedIOException; + import java.io.Writer; + import java.util.List; ++import java.util.Objects; + import java.util.Queue; + import java.util.Set; + import java.util.UUID; ++import java.util.concurrent.CompletableFuture; + import java.util.function.Consumer; + import java.util.stream.Collectors; + import java.util.stream.Stream; +@@ -26,41 +29,56 @@ + import net.minecraft.util.CsvOutput; + import net.minecraft.util.VisibleForDebug; + import net.minecraft.world.entity.Entity; +-import net.minecraft.world.level.ChunkPos; + import org.slf4j.Logger; ++import net.minecraft.world.level.ChunkPos; ++// CraftBukkit start ++import net.minecraft.world.level.chunk.storage.EntityStorage; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public class PersistentEntitySectionManager implements AutoCloseable { ++ + static final Logger LOGGER = LogUtils.getLogger(); + final Set knownUuids = Sets.newHashSet(); + final LevelCallback callbacks; +- private final EntityPersistentStorage permanentStorage; +- private final EntityLookup visibleEntityStorage; ++ public final EntityPersistentStorage permanentStorage; ++ private final EntityLookup visibleEntityStorage = new EntityLookup<>(); + final EntitySectionStorage sectionStorage; + private final LevelEntityGetter entityGetter; +- private final Long2ObjectMap chunkVisibility = new Long2ObjectOpenHashMap<>(); +- private final Long2ObjectMap chunkLoadStatuses = new Long2ObjectOpenHashMap<>(); ++ private final Long2ObjectMap chunkVisibility = new Long2ObjectOpenHashMap(); ++ private final Long2ObjectMap chunkLoadStatuses = new Long2ObjectOpenHashMap(); + private final LongSet chunksToUnload = new LongOpenHashSet(); + private final Queue> loadingInbox = Queues.newConcurrentLinkedQueue(); + + public PersistentEntitySectionManager(Class entityClass, LevelCallback callbacks, EntityPersistentStorage permanentStorage) { +- this.visibleEntityStorage = new EntityLookup<>(); + this.sectionStorage = new EntitySectionStorage<>(entityClass, this.chunkVisibility); + this.chunkVisibility.defaultReturnValue(Visibility.HIDDEN); +- this.chunkLoadStatuses.defaultReturnValue(PersistentEntitySectionManager.ChunkLoadStatus.FRESH); ++ this.chunkLoadStatuses.defaultReturnValue(PersistentEntitySectionManager.b.FRESH); + this.callbacks = callbacks; + this.permanentStorage = permanentStorage; + this.entityGetter = new LevelEntityGetterAdapter<>(this.visibleEntityStorage, this.sectionStorage); + } + +- void removeSectionIfEmpty(long sectionKey, EntitySection section) { +- if (section.isEmpty()) { ++ // CraftBukkit start - add method to get all entities in chunk ++ public List getEntities(ChunkPos chunkCoordIntPair) { ++ return sectionStorage.getExistingSectionsInChunk(chunkCoordIntPair.toLong()).flatMap(EntitySection::getEntities).map(entity -> (Entity) entity).collect(Collectors.toList()); ++ } ++ ++ public boolean isPending(long pair) { ++ return chunkLoadStatuses.get(pair) == b.PENDING; ++ } ++ // CraftBukkit end ++ ++ void removeSectionIfEmpty(long sectionKey, EntitySection entitysection) { ++ if (entitysection.isEmpty()) { + this.sectionStorage.remove(sectionKey); + } ++ + } + + private boolean addEntityUuid(T entity) { + if (!this.knownUuids.add(entity.getUUID())) { +- LOGGER.warn("UUID of added entity already exists: {}", entity); ++ PersistentEntitySectionManager.LOGGER.warn("UUID of added entity already exists: {}", entity); + return false; + } else { + return true; +@@ -75,20 +93,22 @@ + if (!this.addEntityUuid(entity)) { + return false; + } else { +- long _long = SectionPos.asLong(entity.blockPosition()); +- EntitySection section = this.sectionStorage.getOrCreateSection(_long); +- section.add(entity); +- entity.setLevelCallback(new PersistentEntitySectionManager.Callback(entity, _long, section)); ++ long i = SectionPos.asLong(entity.blockPosition()); ++ EntitySection entitysection = this.sectionStorage.getOrCreateSection(i); ++ ++ entitysection.add(entity); ++ entity.setLevelCallback(new PersistentEntitySectionManager.Callback(entity, i, entitysection)); + if (!worldGenSpawned) { + this.callbacks.onCreated(entity); + } + +- Visibility effectiveStatus = getEffectiveStatus(entity, section.getStatus()); +- if (effectiveStatus.isAccessible()) { ++ Visibility visibility = getEffectiveStatus(entity, entitysection.getStatus()); ++ ++ if (visibility.isAccessible()) { + this.startTracking(entity); + } + +- if (effectiveStatus.isTicking()) { ++ if (visibility.isTicking()) { + this.startTicking(entity); + } + +@@ -101,11 +121,15 @@ + } + + public void addLegacyChunkEntities(Stream entities) { +- entities.forEach(entity -> this.addEntity((T)entity, true)); ++ entities.forEach((entityaccess) -> { ++ this.addEntity(entityaccess, true); ++ }); + } + + public void addWorldGenChunkEntities(Stream entities) { +- entities.forEach(entity -> this.addEntity((T)entity, false)); ++ entities.forEach((entityaccess) -> { ++ this.addEntity(entityaccess, false); ++ }); + } + + void startTicking(T entity) { +@@ -128,86 +152,116 @@ + + public void updateChunkStatus(ChunkPos chunkPos, FullChunkStatus fullChunkStatus) { + Visibility visibility = Visibility.fromFullChunkStatus(fullChunkStatus); ++ + this.updateChunkStatus(chunkPos, visibility); + } + + public void updateChunkStatus(ChunkPos pos, Visibility visibility) { +- long l = pos.toLong(); ++ long i = pos.toLong(); ++ + if (visibility == Visibility.HIDDEN) { +- this.chunkVisibility.remove(l); +- this.chunksToUnload.add(l); ++ this.chunkVisibility.remove(i); ++ this.chunksToUnload.add(i); + } else { +- this.chunkVisibility.put(l, visibility); +- this.chunksToUnload.remove(l); +- this.ensureChunkQueuedForLoad(l); ++ this.chunkVisibility.put(i, visibility); ++ this.chunksToUnload.remove(i); ++ this.ensureChunkQueuedForLoad(i); + } + +- this.sectionStorage.getExistingSectionsInChunk(l).forEach(entitySection -> { +- Visibility visibility1 = entitySection.updateChunkStatus(visibility); +- boolean isAccessible = visibility1.isAccessible(); +- boolean isAccessible1 = visibility.isAccessible(); +- boolean isTicking = visibility1.isTicking(); +- boolean isTicking1 = visibility.isTicking(); +- if (isTicking && !isTicking1) { +- entitySection.getEntities().filter(entity -> !entity.isAlwaysTicking()).forEach(this::stopTicking); ++ this.sectionStorage.getExistingSectionsInChunk(i).forEach((entitysection) -> { ++ Visibility visibility1 = entitysection.updateChunkStatus(visibility); ++ boolean flag = visibility1.isAccessible(); ++ boolean flag1 = visibility.isAccessible(); ++ boolean flag2 = visibility1.isTicking(); ++ boolean flag3 = visibility.isTicking(); ++ ++ if (flag2 && !flag3) { ++ entitysection.getEntities().filter((entityaccess) -> { ++ return !entityaccess.isAlwaysTicking(); ++ }).forEach(this::stopTicking); + } + +- if (isAccessible && !isAccessible1) { +- entitySection.getEntities().filter(entity -> !entity.isAlwaysTicking()).forEach(this::stopTracking); +- } else if (!isAccessible && isAccessible1) { +- entitySection.getEntities().filter(entity -> !entity.isAlwaysTicking()).forEach(this::startTracking); ++ if (flag && !flag1) { ++ entitysection.getEntities().filter((entityaccess) -> { ++ return !entityaccess.isAlwaysTicking(); ++ }).forEach(this::stopTracking); ++ } else if (!flag && flag1) { ++ entitysection.getEntities().filter((entityaccess) -> { ++ return !entityaccess.isAlwaysTicking(); ++ }).forEach(this::startTracking); + } + +- if (!isTicking && isTicking1) { +- entitySection.getEntities().filter(entity -> !entity.isAlwaysTicking()).forEach(this::startTicking); ++ if (!flag2 && flag3) { ++ entitysection.getEntities().filter((entityaccess) -> { ++ return !entityaccess.isAlwaysTicking(); ++ }).forEach(this::startTicking); + } ++ + }); + } + +- private void ensureChunkQueuedForLoad(long chunkPosValue) { +- PersistentEntitySectionManager.ChunkLoadStatus chunkLoadStatus = this.chunkLoadStatuses.get(chunkPosValue); +- if (chunkLoadStatus == PersistentEntitySectionManager.ChunkLoadStatus.FRESH) { ++ public void ensureChunkQueuedForLoad(long chunkPosValue) { ++ PersistentEntitySectionManager.b persistententitysectionmanager_b = (PersistentEntitySectionManager.b) this.chunkLoadStatuses.get(chunkPosValue); ++ ++ if (persistententitysectionmanager_b == PersistentEntitySectionManager.b.FRESH) { + this.requestChunkLoad(chunkPosValue); + } ++ + } + +- private boolean storeChunkSections(long chunkPosValue, Consumer entityAction) { +- PersistentEntitySectionManager.ChunkLoadStatus chunkLoadStatus = this.chunkLoadStatuses.get(chunkPosValue); +- if (chunkLoadStatus == PersistentEntitySectionManager.ChunkLoadStatus.PENDING) { ++ private boolean storeChunkSections(long chunkPosValue, Consumer consumer) { ++ // CraftBukkit start - add boolean for event call ++ return storeChunkSections(chunkPosValue, consumer, false); ++ } ++ ++ private boolean storeChunkSections(long i, Consumer consumer, boolean callEvent) { ++ // CraftBukkit end ++ PersistentEntitySectionManager.b persistententitysectionmanager_b = (PersistentEntitySectionManager.b) this.chunkLoadStatuses.get(i); ++ ++ if (persistententitysectionmanager_b == PersistentEntitySectionManager.b.PENDING) { + return false; + } else { +- List list = this.sectionStorage +- .getExistingSectionsInChunk(chunkPosValue) +- .flatMap(entitySection -> entitySection.getEntities().filter(EntityAccess::shouldBeSaved)) +- .collect(Collectors.toList()); ++ List list = (List) this.sectionStorage.getExistingSectionsInChunk(i).flatMap((entitysection) -> { ++ return entitysection.getEntities().filter(EntityAccess::shouldBeSaved); ++ }).collect(Collectors.toList()); ++ + if (list.isEmpty()) { +- if (chunkLoadStatus == PersistentEntitySectionManager.ChunkLoadStatus.LOADED) { +- this.permanentStorage.storeEntities(new ChunkEntities<>(new ChunkPos(chunkPosValue), ImmutableList.of())); ++ if (persistententitysectionmanager_b == PersistentEntitySectionManager.b.LOADED) { ++ if (callEvent) CraftEventFactory.callEntitiesUnloadEvent(((EntityStorage) permanentStorage).level, new ChunkPos(i), ImmutableList.of()); // CraftBukkit ++ this.permanentStorage.storeEntities(new ChunkEntities<>(new ChunkPos(i), ImmutableList.of())); + } + + return true; +- } else if (chunkLoadStatus == PersistentEntitySectionManager.ChunkLoadStatus.FRESH) { +- this.requestChunkLoad(chunkPosValue); ++ } else if (persistententitysectionmanager_b == PersistentEntitySectionManager.b.FRESH) { ++ this.requestChunkLoad(i); + return false; + } else { +- this.permanentStorage.storeEntities(new ChunkEntities<>(new ChunkPos(chunkPosValue), list)); +- list.forEach(entityAction); ++ if (callEvent) CraftEventFactory.callEntitiesUnloadEvent(((EntityStorage) permanentStorage).level, new ChunkPos(i), list.stream().map(entity -> (Entity) entity).collect(Collectors.toList())); // CraftBukkit ++ this.permanentStorage.storeEntities(new ChunkEntities<>(new ChunkPos(i), list)); ++ list.forEach(consumer); + return true; + } + } + } + + private void requestChunkLoad(long chunkPosValue) { +- this.chunkLoadStatuses.put(chunkPosValue, PersistentEntitySectionManager.ChunkLoadStatus.PENDING); +- ChunkPos chunkPos = new ChunkPos(chunkPosValue); +- this.permanentStorage.loadEntities(chunkPos).thenAccept(this.loadingInbox::add).exceptionally(throwable -> { +- LOGGER.error("Failed to read chunk {}", chunkPos, throwable); ++ this.chunkLoadStatuses.put(chunkPosValue, PersistentEntitySectionManager.b.PENDING); ++ ChunkPos chunkcoordintpair = new ChunkPos(chunkPosValue); ++ CompletableFuture completablefuture = this.permanentStorage.loadEntities(chunkcoordintpair); ++ Queue queue = this.loadingInbox; ++ ++ Objects.requireNonNull(this.loadingInbox); ++ completablefuture.thenAccept(queue::add).exceptionally((throwable) -> { ++ PersistentEntitySectionManager.LOGGER.error("Failed to read chunk {}", chunkcoordintpair, throwable); + return null; + }); + } + + private boolean processChunkUnload(long chunkPosValue) { +- boolean flag = this.storeChunkSections(chunkPosValue, entity -> entity.getPassengersAndSelf().forEach(this::unloadEntity)); ++ boolean flag = this.storeChunkSections(chunkPosValue, (entityaccess) -> { ++ entityaccess.getPassengersAndSelf().forEach(this::unloadEntity); ++ }, true); // CraftBukkit - add boolean for event call ++ + if (!flag) { + return false; + } else { +@@ -222,16 +276,25 @@ + } + + private void processUnloads() { +- this.chunksToUnload +- .removeIf(packedChunkPos -> this.chunkVisibility.get(packedChunkPos) != Visibility.HIDDEN || this.processChunkUnload(packedChunkPos)); ++ this.chunksToUnload.removeIf((java.util.function.LongPredicate) (i) -> { // CraftBukkit - decompile error ++ return this.chunkVisibility.get(i) != Visibility.HIDDEN ? true : this.processChunkUnload(i); ++ }); + } + + private void processPendingLoads() { +- ChunkEntities chunkEntities; +- while ((chunkEntities = this.loadingInbox.poll()) != null) { +- chunkEntities.getEntities().forEach(entity -> this.addEntity((T)entity, true)); +- this.chunkLoadStatuses.put(chunkEntities.getPos().toLong(), PersistentEntitySectionManager.ChunkLoadStatus.LOADED); ++ ChunkEntities chunkentities; // CraftBukkit - decompile error ++ ++ while ((chunkentities = (ChunkEntities) this.loadingInbox.poll()) != null) { ++ chunkentities.getEntities().forEach((entityaccess) -> { ++ this.addEntity(entityaccess, true); ++ }); ++ this.chunkLoadStatuses.put(chunkentities.getPos().toLong(), PersistentEntitySectionManager.b.LOADED); ++ // CraftBukkit start - call entity load event ++ List entities = getEntities(chunkentities.getPos()); ++ CraftEventFactory.callEntitiesLoadEvent(((EntityStorage) permanentStorage).level, chunkentities.getPos(), entities); ++ // CraftBukkit end + } ++ + } + + public void tick() { +@@ -240,38 +303,44 @@ + } + + private LongSet getAllChunksToSave() { +- LongSet allChunksWithExistingSections = this.sectionStorage.getAllChunksWithExistingSections(); ++ LongSet longset = this.sectionStorage.getAllChunksWithExistingSections(); ++ ObjectIterator objectiterator = Long2ObjectMaps.fastIterable(this.chunkLoadStatuses).iterator(); + +- for (Entry entry : Long2ObjectMaps.fastIterable(this.chunkLoadStatuses)) { +- if (entry.getValue() == PersistentEntitySectionManager.ChunkLoadStatus.LOADED) { +- allChunksWithExistingSections.add(entry.getLongKey()); ++ while (objectiterator.hasNext()) { ++ Entry entry = (Entry) objectiterator.next(); ++ ++ if (entry.getValue() == PersistentEntitySectionManager.b.LOADED) { ++ longset.add(entry.getLongKey()); + } + } + +- return allChunksWithExistingSections; ++ return longset; + } + + public void autoSave() { +- this.getAllChunksToSave().forEach(packedChunkPos -> { +- boolean flag = this.chunkVisibility.get(packedChunkPos) == Visibility.HIDDEN; ++ this.getAllChunksToSave().forEach((java.util.function.LongConsumer) (i) -> { // CraftBukkit - decompile error ++ boolean flag = this.chunkVisibility.get(i) == Visibility.HIDDEN; ++ + if (flag) { +- this.processChunkUnload(packedChunkPos); ++ this.processChunkUnload(i); + } else { +- this.storeChunkSections(packedChunkPos, entity -> { ++ this.storeChunkSections(i, (entityaccess) -> { + }); + } ++ + }); + } + + public void saveAll() { +- LongSet allChunksToSave = this.getAllChunksToSave(); ++ LongSet longset = this.getAllChunksToSave(); + +- while (!allChunksToSave.isEmpty()) { ++ while (!longset.isEmpty()) { + this.permanentStorage.flush(false); + this.processPendingLoads(); +- allChunksToSave.removeIf(packedChunkPos -> { +- boolean flag = this.chunkVisibility.get(packedChunkPos) == Visibility.HIDDEN; +- return flag ? this.processChunkUnload(packedChunkPos) : this.storeChunkSections(packedChunkPos, entity -> { ++ longset.removeIf((java.util.function.LongPredicate) (i) -> { // CraftBukkit - decompile error ++ boolean flag = this.chunkVisibility.get(i) == Visibility.HIDDEN; ++ ++ return flag ? this.processChunkUnload(i) : this.storeChunkSections(i, (entityaccess) -> { + }); + }); + } +@@ -279,9 +348,16 @@ + this.permanentStorage.flush(true); + } + +- @Override + public void close() throws IOException { +- this.saveAll(); ++ // CraftBukkit start - add save boolean ++ close(true); ++ } ++ ++ public void close(boolean save) throws IOException { ++ if (save) { ++ this.saveAll(); ++ } ++ // CraftBukkit end + this.permanentStorage.close(); + } + +@@ -294,71 +370,43 @@ + } + + public boolean canPositionTick(BlockPos pos) { +- return this.chunkVisibility.get(ChunkPos.asLong(pos)).isTicking(); ++ return ((Visibility) this.chunkVisibility.get(ChunkPos.asLong(pos))).isTicking(); + } + + public boolean canPositionTick(ChunkPos chunkPos) { +- return this.chunkVisibility.get(chunkPos.toLong()).isTicking(); ++ return ((Visibility) this.chunkVisibility.get(chunkPos.toLong())).isTicking(); + } + + public boolean areEntitiesLoaded(long chunkPos) { +- return this.chunkLoadStatuses.get(chunkPos) == PersistentEntitySectionManager.ChunkLoadStatus.LOADED; ++ return this.chunkLoadStatuses.get(chunkPos) == PersistentEntitySectionManager.b.LOADED; + } + + public void dumpSections(Writer writer) throws IOException { +- CsvOutput csvOutput = CsvOutput.builder() +- .addColumn("x") +- .addColumn("y") +- .addColumn("z") +- .addColumn("visibility") +- .addColumn("load_status") +- .addColumn("entity_count") +- .build(writer); +- this.sectionStorage +- .getAllChunksWithExistingSections() +- .forEach( +- packedChunkPos -> { +- PersistentEntitySectionManager.ChunkLoadStatus chunkLoadStatus = this.chunkLoadStatuses.get(packedChunkPos); +- this.sectionStorage +- .getExistingSectionPositionsInChunk(packedChunkPos) +- .forEach( +- packedSectionPos -> { +- EntitySection section = this.sectionStorage.getSection(packedSectionPos); +- if (section != null) { +- try { +- csvOutput.writeRow( +- SectionPos.x(packedSectionPos), +- SectionPos.y(packedSectionPos), +- SectionPos.z(packedSectionPos), +- section.getStatus(), +- chunkLoadStatus, +- section.size() +- ); +- } catch (IOException var7) { +- throw new UncheckedIOException(var7); +- } +- } +- } +- ); ++ CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("visibility").addColumn("load_status").addColumn("entity_count").build(writer); ++ ++ this.sectionStorage.getAllChunksWithExistingSections().forEach((java.util.function.LongConsumer) (i) -> { // CraftBukkit - decompile error ++ PersistentEntitySectionManager.b persistententitysectionmanager_b = (PersistentEntitySectionManager.b) this.chunkLoadStatuses.get(i); ++ ++ this.sectionStorage.getExistingSectionPositionsInChunk(i).forEach((j) -> { ++ EntitySection entitysection = this.sectionStorage.getSection(j); ++ ++ if (entitysection != null) { ++ try { ++ csvwriter.writeRow(SectionPos.x(j), SectionPos.y(j), SectionPos.z(j), entitysection.getStatus(), persistententitysectionmanager_b, entitysection.size()); ++ } catch (IOException ioexception) { ++ throw new UncheckedIOException(ioexception); ++ } + } +- ); ++ ++ }); ++ }); + } + + @VisibleForDebug + public String gatherStats() { +- return this.knownUuids.size() +- + "," +- + this.visibleEntityStorage.count() +- + "," +- + this.sectionStorage.count() +- + "," +- + this.chunkLoadStatuses.size() +- + "," +- + this.chunkVisibility.size() +- + "," +- + this.loadingInbox.size() +- + "," +- + this.chunksToUnload.size(); ++ int i = this.knownUuids.size(); ++ ++ return i + "," + this.visibleEntityStorage.count() + "," + this.sectionStorage.count() + "," + this.chunkLoadStatuses.size() + "," + this.chunkVisibility.size() + "," + this.loadingInbox.size() + "," + this.chunksToUnload.size(); + } + + @VisibleForDebug +@@ -366,80 +414,96 @@ + return this.visibleEntityStorage.count(); + } + +- class Callback implements EntityInLevelCallback { ++ private static enum b { ++ ++ FRESH, PENDING, LOADED; ++ ++ private b() {} ++ } ++ ++ private class Callback implements EntityInLevelCallback { ++ + private final T entity; + private long currentSectionKey; + private EntitySection currentSection; + +- Callback(T entity, long currentSectionKey, EntitySection currentSection) { +- this.entity = entity; +- this.currentSectionKey = currentSectionKey; +- this.currentSection = currentSection; ++ Callback(EntityAccess entityaccess, long i, EntitySection entitysection) { ++ this.entity = (T) entityaccess; // CraftBukkit - decompile error ++ this.currentSectionKey = i; ++ this.currentSection = entitysection; + } + + @Override + public void onMove() { +- BlockPos blockPos = this.entity.blockPosition(); +- long _long = SectionPos.asLong(blockPos); +- if (_long != this.currentSectionKey) { +- Visibility status = this.currentSection.getStatus(); ++ BlockPos blockposition = this.entity.blockPosition(); ++ long i = SectionPos.asLong(blockposition); ++ ++ if (i != this.currentSectionKey) { ++ Visibility visibility = this.currentSection.getStatus(); ++ + if (!this.currentSection.remove(this.entity)) { +- PersistentEntitySectionManager.LOGGER +- .warn("Entity {} wasn't found in section {} (moving to {})", this.entity, SectionPos.of(this.currentSectionKey), _long); ++ PersistentEntitySectionManager.LOGGER.warn("Entity {} wasn't found in section {} (moving to {})", new Object[]{this.entity, SectionPos.of(this.currentSectionKey), i}); + } + + PersistentEntitySectionManager.this.removeSectionIfEmpty(this.currentSectionKey, this.currentSection); +- EntitySection section = PersistentEntitySectionManager.this.sectionStorage.getOrCreateSection(_long); +- section.add(this.entity); +- this.currentSection = section; +- this.currentSectionKey = _long; +- this.updateStatus(status, section.getStatus()); ++ EntitySection entitysection = PersistentEntitySectionManager.this.sectionStorage.getOrCreateSection(i); ++ ++ entitysection.add(this.entity); ++ this.currentSection = entitysection; ++ this.currentSectionKey = i; ++ this.updateStatus(visibility, entitysection.getStatus()); + } ++ + } + + private void updateStatus(Visibility oldVisibility, Visibility newVisibility) { +- Visibility effectiveStatus = PersistentEntitySectionManager.getEffectiveStatus(this.entity, oldVisibility); +- Visibility effectiveStatus1 = PersistentEntitySectionManager.getEffectiveStatus(this.entity, newVisibility); +- if (effectiveStatus == effectiveStatus1) { +- if (effectiveStatus1.isAccessible()) { ++ Visibility visibility2 = PersistentEntitySectionManager.getEffectiveStatus(this.entity, oldVisibility); ++ Visibility visibility3 = PersistentEntitySectionManager.getEffectiveStatus(this.entity, newVisibility); ++ ++ if (visibility2 == visibility3) { ++ if (visibility3.isAccessible()) { + PersistentEntitySectionManager.this.callbacks.onSectionChange(this.entity); + } ++ + } else { +- boolean isAccessible = effectiveStatus.isAccessible(); +- boolean isAccessible1 = effectiveStatus1.isAccessible(); +- if (isAccessible && !isAccessible1) { ++ boolean flag = visibility2.isAccessible(); ++ boolean flag1 = visibility3.isAccessible(); ++ ++ if (flag && !flag1) { + PersistentEntitySectionManager.this.stopTracking(this.entity); +- } else if (!isAccessible && isAccessible1) { ++ } else if (!flag && flag1) { + PersistentEntitySectionManager.this.startTracking(this.entity); + } + +- boolean isTicking = effectiveStatus.isTicking(); +- boolean isTicking1 = effectiveStatus1.isTicking(); +- if (isTicking && !isTicking1) { ++ boolean flag2 = visibility2.isTicking(); ++ boolean flag3 = visibility3.isTicking(); ++ ++ if (flag2 && !flag3) { + PersistentEntitySectionManager.this.stopTicking(this.entity); +- } else if (!isTicking && isTicking1) { ++ } else if (!flag2 && flag3) { + PersistentEntitySectionManager.this.startTicking(this.entity); + } + +- if (isAccessible1) { ++ if (flag1) { + PersistentEntitySectionManager.this.callbacks.onSectionChange(this.entity); + } ++ + } + } + + @Override + public void onRemove(Entity.RemovalReason reason) { + if (!this.currentSection.remove(this.entity)) { +- PersistentEntitySectionManager.LOGGER +- .warn("Entity {} wasn't found in section {} (destroying due to {})", this.entity, SectionPos.of(this.currentSectionKey), reason); ++ PersistentEntitySectionManager.LOGGER.warn("Entity {} wasn't found in section {} (destroying due to {})", new Object[]{this.entity, SectionPos.of(this.currentSectionKey), reason}); + } + +- Visibility effectiveStatus = PersistentEntitySectionManager.getEffectiveStatus(this.entity, this.currentSection.getStatus()); +- if (effectiveStatus.isTicking()) { ++ Visibility visibility = PersistentEntitySectionManager.getEffectiveStatus(this.entity, this.currentSection.getStatus()); ++ ++ if (visibility.isTicking()) { + PersistentEntitySectionManager.this.stopTicking(this.entity); + } + +- if (effectiveStatus.isAccessible()) { ++ if (visibility.isAccessible()) { + PersistentEntitySectionManager.this.stopTracking(this.entity); + } + +@@ -448,14 +512,8 @@ + } + + PersistentEntitySectionManager.this.knownUuids.remove(this.entity.getUUID()); +- this.entity.setLevelCallback(NULL); ++ this.entity.setLevelCallback(PersistentEntitySectionManager.Callback.NULL); + PersistentEntitySectionManager.this.removeSectionIfEmpty(this.currentSectionKey, this.currentSection); + } + } +- +- static enum ChunkLoadStatus { +- FRESH, +- PENDING, +- LOADED; +- } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/gameevent/GameEventDispatcher.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/gameevent/GameEventDispatcher.java.patch new file mode 100644 index 0000000000..7d2eaa34c0 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/gameevent/GameEventDispatcher.java.patch @@ -0,0 +1,110 @@ +--- a/net/minecraft/world/level/gameevent/GameEventDispatcher.java ++++ b/net/minecraft/world/level/gameevent/GameEventDispatcher.java +@@ -2,15 +2,23 @@ + + import java.util.ArrayList; + import java.util.Collections; ++import java.util.Iterator; + import java.util.List; + import net.minecraft.core.BlockPos; + import net.minecraft.core.SectionPos; + import net.minecraft.network.protocol.game.DebugPackets; + import net.minecraft.server.level.ServerLevel; +-import net.minecraft.world.level.chunk.ChunkAccess; ++import net.minecraft.world.level.chunk.LevelChunk; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.CraftGameEvent; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.world.GenericGameEvent; ++// CraftBukkit end + + public class GameEventDispatcher { ++ + private final ServerLevel level; + + public GameEventDispatcher(ServerLevel level) { +@@ -18,30 +26,40 @@ + } + + public void post(GameEvent event, Vec3 pos, GameEvent.Context context) { +- int notificationRadius = event.getNotificationRadius(); +- BlockPos blockPos = BlockPos.containing(pos); +- int i = SectionPos.blockToSectionCoord(blockPos.getX() - notificationRadius); +- int i1 = SectionPos.blockToSectionCoord(blockPos.getY() - notificationRadius); +- int i2 = SectionPos.blockToSectionCoord(blockPos.getZ() - notificationRadius); +- int i3 = SectionPos.blockToSectionCoord(blockPos.getX() + notificationRadius); +- int i4 = SectionPos.blockToSectionCoord(blockPos.getY() + notificationRadius); +- int i5 = SectionPos.blockToSectionCoord(blockPos.getZ() + notificationRadius); +- List list = new ArrayList<>(); +- GameEventListenerRegistry.ListenerVisitor listenerVisitor = (listener, pos1) -> { +- if (listener.getDeliveryMode() == GameEventListener.DeliveryMode.BY_DISTANCE) { +- list.add(new GameEvent.ListenerInfo(event, pos, context, listener, pos1)); ++ int i = event.getNotificationRadius(); ++ BlockPos blockposition = BlockPos.containing(pos); ++ // CraftBukkit start ++ GenericGameEvent event1 = new GenericGameEvent(CraftGameEvent.minecraftToBukkit(event), CraftLocation.toBukkit(blockposition, level.getWorld()), (context.sourceEntity() == null) ? null : context.sourceEntity().getBukkitEntity(), i, !Bukkit.isPrimaryThread()); ++ level.getCraftServer().getPluginManager().callEvent(event1); ++ if (event1.isCancelled()) { ++ return; ++ } ++ i = event1.getRadius(); ++ // CraftBukkit end ++ int j = SectionPos.blockToSectionCoord(blockposition.getX() - i); ++ int k = SectionPos.blockToSectionCoord(blockposition.getY() - i); ++ int l = SectionPos.blockToSectionCoord(blockposition.getZ() - i); ++ int i1 = SectionPos.blockToSectionCoord(blockposition.getX() + i); ++ int j1 = SectionPos.blockToSectionCoord(blockposition.getY() + i); ++ int k1 = SectionPos.blockToSectionCoord(blockposition.getZ() + i); ++ List list = new ArrayList(); ++ GameEventListenerRegistry.ListenerVisitor gameeventlistenerregistry_a = (gameeventlistener, vec3d1) -> { ++ if (gameeventlistener.getDeliveryMode() == GameEventListener.a.BY_DISTANCE) { ++ list.add(new GameEvent.ListenerInfo(event, pos, context, gameeventlistener, vec3d1)); + } else { +- listener.handleGameEvent(this.level, event, context, pos); ++ gameeventlistener.handleGameEvent(this.level, event, context, pos); + } ++ + }; + boolean flag = false; + +- for (int i6 = i; i6 <= i3; i6++) { +- for (int i7 = i2; i7 <= i5; i7++) { +- ChunkAccess chunkNow = this.level.getChunkSource().getChunkNow(i6, i7); +- if (chunkNow != null) { +- for (int i8 = i1; i8 <= i4; i8++) { +- flag |= chunkNow.getListenerRegistry(i8).visitInRangeListeners(event, pos, context, listenerVisitor); ++ for (int l1 = j; l1 <= i1; ++l1) { ++ for (int i2 = l; i2 <= k1; ++i2) { ++ LevelChunk chunk = this.level.getChunkSource().getChunkNow(l1, i2); ++ ++ if (chunk != null) { ++ for (int j2 = k; j2 <= j1; ++j2) { ++ flag |= chunk.getListenerRegistry(j2).visitInRangeListeners(event, pos, context, gameeventlistenerregistry_a); + } + } + } +@@ -54,14 +72,19 @@ + if (flag) { + DebugPackets.sendGameEventInfo(this.level, event, pos); + } ++ + } + + private void handleGameEventMessagesInQueue(List listenerInfos) { + Collections.sort(listenerInfos); ++ Iterator iterator = listenerInfos.iterator(); + +- for (GameEvent.ListenerInfo listenerInfo : listenerInfos) { +- GameEventListener gameEventListener = listenerInfo.recipient(); +- gameEventListener.handleGameEvent(this.level, listenerInfo.gameEvent(), listenerInfo.context(), listenerInfo.source()); ++ while (iterator.hasNext()) { ++ GameEvent.ListenerInfo gameevent_b = (GameEvent.ListenerInfo) iterator.next(); ++ GameEventListener gameeventlistener = gameevent_b.recipient(); ++ ++ gameeventlistener.handleGameEvent(this.level, gameevent_b.gameEvent(), gameevent_b.context(), gameevent_b.source()); + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java.patch new file mode 100644 index 0000000000..093e9a9dfc --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java.patch @@ -0,0 +1,656 @@ +--- a/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java ++++ b/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java +@@ -2,7 +2,6 @@ + + import com.mojang.serialization.Codec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; + import java.util.Optional; + import java.util.function.ToIntFunction; +@@ -23,77 +22,67 @@ + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.ClipBlockStateContext; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.gameevent.GameEventListener; + import net.minecraft.world.level.gameevent.PositionSource; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import org.bukkit.craftbukkit.CraftGameEvent; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockReceiveGameEvent; ++// CraftBukkit end + + public interface VibrationSystem { +- GameEvent[] RESONANCE_EVENTS = new GameEvent[]{ +- GameEvent.RESONATE_1, +- GameEvent.RESONATE_2, +- GameEvent.RESONATE_3, +- GameEvent.RESONATE_4, +- GameEvent.RESONATE_5, +- GameEvent.RESONATE_6, +- GameEvent.RESONATE_7, +- GameEvent.RESONATE_8, +- GameEvent.RESONATE_9, +- GameEvent.RESONATE_10, +- GameEvent.RESONATE_11, +- GameEvent.RESONATE_12, +- GameEvent.RESONATE_13, +- GameEvent.RESONATE_14, +- GameEvent.RESONATE_15 +- }; +- ToIntFunction VIBRATION_FREQUENCY_FOR_EVENT = Util.make(new Object2IntOpenHashMap<>(), map -> { +- map.defaultReturnValue(0); +- map.put(GameEvent.STEP, 1); +- map.put(GameEvent.SWIM, 1); +- map.put(GameEvent.FLAP, 1); +- map.put(GameEvent.PROJECTILE_LAND, 2); +- map.put(GameEvent.HIT_GROUND, 2); +- map.put(GameEvent.SPLASH, 2); +- map.put(GameEvent.ITEM_INTERACT_FINISH, 3); +- map.put(GameEvent.PROJECTILE_SHOOT, 3); +- map.put(GameEvent.INSTRUMENT_PLAY, 3); +- map.put(GameEvent.ENTITY_ACTION, 4); +- map.put(GameEvent.ELYTRA_GLIDE, 4); +- map.put(GameEvent.UNEQUIP, 4); +- map.put(GameEvent.ENTITY_DISMOUNT, 5); +- map.put(GameEvent.EQUIP, 5); +- map.put(GameEvent.ENTITY_INTERACT, 6); +- map.put(GameEvent.SHEAR, 6); +- map.put(GameEvent.ENTITY_MOUNT, 6); +- map.put(GameEvent.ENTITY_DAMAGE, 7); +- map.put(GameEvent.DRINK, 8); +- map.put(GameEvent.EAT, 8); +- map.put(GameEvent.CONTAINER_CLOSE, 9); +- map.put(GameEvent.BLOCK_CLOSE, 9); +- map.put(GameEvent.BLOCK_DEACTIVATE, 9); +- map.put(GameEvent.BLOCK_DETACH, 9); +- map.put(GameEvent.CONTAINER_OPEN, 10); +- map.put(GameEvent.BLOCK_OPEN, 10); +- map.put(GameEvent.BLOCK_ACTIVATE, 10); +- map.put(GameEvent.BLOCK_ATTACH, 10); +- map.put(GameEvent.PRIME_FUSE, 10); +- map.put(GameEvent.NOTE_BLOCK_PLAY, 10); +- map.put(GameEvent.BLOCK_CHANGE, 11); +- map.put(GameEvent.BLOCK_DESTROY, 12); +- map.put(GameEvent.FLUID_PICKUP, 12); +- map.put(GameEvent.BLOCK_PLACE, 13); +- map.put(GameEvent.FLUID_PLACE, 13); +- map.put(GameEvent.ENTITY_PLACE, 14); +- map.put(GameEvent.LIGHTNING_STRIKE, 14); +- map.put(GameEvent.TELEPORT, 14); +- map.put(GameEvent.ENTITY_DIE, 15); +- map.put(GameEvent.EXPLODE, 15); + +- for (int i = 1; i <= 15; i++) { +- map.put(getResonanceEventByFrequency(i), i); ++ GameEvent[] RESONANCE_EVENTS = new GameEvent[]{GameEvent.RESONATE_1, GameEvent.RESONATE_2, GameEvent.RESONATE_3, GameEvent.RESONATE_4, GameEvent.RESONATE_5, GameEvent.RESONATE_6, GameEvent.RESONATE_7, GameEvent.RESONATE_8, GameEvent.RESONATE_9, GameEvent.RESONATE_10, GameEvent.RESONATE_11, GameEvent.RESONATE_12, GameEvent.RESONATE_13, GameEvent.RESONATE_14, GameEvent.RESONATE_15}; ++ ToIntFunction VIBRATION_FREQUENCY_FOR_EVENT = (ToIntFunction) Util.make(new Object2IntOpenHashMap(), (object2intopenhashmap) -> { ++ object2intopenhashmap.defaultReturnValue(0); ++ object2intopenhashmap.put(GameEvent.STEP, 1); ++ object2intopenhashmap.put(GameEvent.SWIM, 1); ++ object2intopenhashmap.put(GameEvent.FLAP, 1); ++ object2intopenhashmap.put(GameEvent.PROJECTILE_LAND, 2); ++ object2intopenhashmap.put(GameEvent.HIT_GROUND, 2); ++ object2intopenhashmap.put(GameEvent.SPLASH, 2); ++ object2intopenhashmap.put(GameEvent.ITEM_INTERACT_FINISH, 3); ++ object2intopenhashmap.put(GameEvent.PROJECTILE_SHOOT, 3); ++ object2intopenhashmap.put(GameEvent.INSTRUMENT_PLAY, 3); ++ object2intopenhashmap.put(GameEvent.ENTITY_ACTION, 4); ++ object2intopenhashmap.put(GameEvent.ELYTRA_GLIDE, 4); ++ object2intopenhashmap.put(GameEvent.UNEQUIP, 4); ++ object2intopenhashmap.put(GameEvent.ENTITY_DISMOUNT, 5); ++ object2intopenhashmap.put(GameEvent.EQUIP, 5); ++ object2intopenhashmap.put(GameEvent.ENTITY_INTERACT, 6); ++ object2intopenhashmap.put(GameEvent.SHEAR, 6); ++ object2intopenhashmap.put(GameEvent.ENTITY_MOUNT, 6); ++ object2intopenhashmap.put(GameEvent.ENTITY_DAMAGE, 7); ++ object2intopenhashmap.put(GameEvent.DRINK, 8); ++ object2intopenhashmap.put(GameEvent.EAT, 8); ++ object2intopenhashmap.put(GameEvent.CONTAINER_CLOSE, 9); ++ object2intopenhashmap.put(GameEvent.BLOCK_CLOSE, 9); ++ object2intopenhashmap.put(GameEvent.BLOCK_DEACTIVATE, 9); ++ object2intopenhashmap.put(GameEvent.BLOCK_DETACH, 9); ++ object2intopenhashmap.put(GameEvent.CONTAINER_OPEN, 10); ++ object2intopenhashmap.put(GameEvent.BLOCK_OPEN, 10); ++ object2intopenhashmap.put(GameEvent.BLOCK_ACTIVATE, 10); ++ object2intopenhashmap.put(GameEvent.BLOCK_ATTACH, 10); ++ object2intopenhashmap.put(GameEvent.PRIME_FUSE, 10); ++ object2intopenhashmap.put(GameEvent.NOTE_BLOCK_PLAY, 10); ++ object2intopenhashmap.put(GameEvent.BLOCK_CHANGE, 11); ++ object2intopenhashmap.put(GameEvent.BLOCK_DESTROY, 12); ++ object2intopenhashmap.put(GameEvent.FLUID_PICKUP, 12); ++ object2intopenhashmap.put(GameEvent.BLOCK_PLACE, 13); ++ object2intopenhashmap.put(GameEvent.FLUID_PLACE, 13); ++ object2intopenhashmap.put(GameEvent.ENTITY_PLACE, 14); ++ object2intopenhashmap.put(GameEvent.LIGHTNING_STRIKE, 14); ++ object2intopenhashmap.put(GameEvent.TELEPORT, 14); ++ object2intopenhashmap.put(GameEvent.ENTITY_DIE, 15); ++ object2intopenhashmap.put(GameEvent.EXPLODE, 15); ++ ++ for (int i = 1; i <= 15; ++i) { ++ object2intopenhashmap.put(getResonanceEventByFrequency(i), i); + } ++ + }); + + VibrationSystem.Data getVibrationData(); +@@ -101,201 +90,115 @@ + VibrationSystem.User getVibrationUser(); + + static int getGameEventFrequency(GameEvent gameEvent) { +- return VIBRATION_FREQUENCY_FOR_EVENT.applyAsInt(gameEvent); ++ return VibrationSystem.VIBRATION_FREQUENCY_FOR_EVENT.applyAsInt(gameEvent); + } + + static GameEvent getResonanceEventByFrequency(int frequency) { +- return RESONANCE_EVENTS[frequency - 1]; ++ return VibrationSystem.RESONANCE_EVENTS[frequency - 1]; + } + + static int getRedstoneStrengthForDistance(float distance, int maxDistance) { +- double d = 15.0 / (double)maxDistance; +- return Math.max(1, 15 - Mth.floor(d * (double)distance)); ++ double d0 = 15.0D / (double) maxDistance; ++ ++ return Math.max(1, 15 - Mth.floor(d0 * (double) distance)); + } + +- public static final class Data { +- public static Codec CODEC = RecordCodecBuilder.create( +- instance -> instance.group( +- VibrationInfo.CODEC.optionalFieldOf("event").forGetter(data -> Optional.ofNullable(data.currentVibration)), +- VibrationSelector.CODEC.fieldOf("selector").forGetter(VibrationSystem.Data::getSelectionStrategy), +- ExtraCodecs.NON_NEGATIVE_INT.fieldOf("event_delay").orElse(0).forGetter(VibrationSystem.Data::getTravelTimeInTicks) +- ) +- .apply( +- instance, +- (vibrationInfo, vibrationSelector, eventDelay) -> new VibrationSystem.Data( +- vibrationInfo.orElse(null), vibrationSelector, eventDelay, true +- ) +- ) +- ); +- public static final String NBT_TAG_KEY = "listener"; +- @Nullable +- VibrationInfo currentVibration; +- private int travelTimeInTicks; +- final VibrationSelector selectionStrategy; +- private boolean reloadVibrationParticle; ++ public interface User { + +- private Data(@Nullable VibrationInfo currentVibration, VibrationSelector selectionStrategy, int travelTimeInTicks, boolean reloadVibrationParticle) { +- this.currentVibration = currentVibration; +- this.travelTimeInTicks = travelTimeInTicks; +- this.selectionStrategy = selectionStrategy; +- this.reloadVibrationParticle = reloadVibrationParticle; +- } ++ int getListenerRadius(); + +- public Data() { +- this(null, new VibrationSelector(), 0, false); +- } ++ PositionSource getPositionSource(); + +- public VibrationSelector getSelectionStrategy() { +- return this.selectionStrategy; +- } ++ boolean canReceiveVibration(ServerLevel level, BlockPos pos, GameEvent gameEvent, GameEvent.Context context); + +- @Nullable +- public VibrationInfo getCurrentVibration() { +- return this.currentVibration; +- } ++ void onReceiveVibration(ServerLevel level, BlockPos pos, GameEvent gameEvent, @Nullable Entity entity, @Nullable Entity playerEntity, float distance); + +- public void setCurrentVibration(@Nullable VibrationInfo currentVibration) { +- this.currentVibration = currentVibration; ++ default TagKey getListenableEvents() { ++ return GameEventTags.VIBRATIONS; + } + +- public int getTravelTimeInTicks() { +- return this.travelTimeInTicks; ++ default boolean canTriggerAvoidVibration() { ++ return false; + } + +- public void setTravelTimeInTicks(int travelTimeInTicks) { +- this.travelTimeInTicks = travelTimeInTicks; ++ default boolean requiresAdjacentChunksToBeTicking() { ++ return false; + } + +- public void decrementTravelTime() { +- this.travelTimeInTicks = Math.max(0, this.travelTimeInTicks - 1); ++ default int calculateTravelTimeInTicks(float distance) { ++ return Mth.floor(distance); + } + +- public boolean shouldReloadVibrationParticle() { +- return this.reloadVibrationParticle; +- } +- +- public void setReloadVibrationParticle(boolean reloadVibrationParticle) { +- this.reloadVibrationParticle = reloadVibrationParticle; +- } +- } +- +- public static class Listener implements GameEventListener { +- private final VibrationSystem system; +- +- public Listener(VibrationSystem system) { +- this.system = system; +- } +- +- @Override +- public PositionSource getListenerSource() { +- return this.system.getVibrationUser().getPositionSource(); +- } +- +- @Override +- public int getListenerRadius() { +- return this.system.getVibrationUser().getListenerRadius(); +- } +- +- @Override +- public boolean handleGameEvent(ServerLevel level, GameEvent gameEvent, GameEvent.Context context, Vec3 pos) { +- VibrationSystem.Data vibrationData = this.system.getVibrationData(); +- VibrationSystem.User vibrationUser = this.system.getVibrationUser(); +- if (vibrationData.getCurrentVibration() != null) { ++ default boolean isValidVibration(GameEvent gameEvent, GameEvent.Context context) { ++ if (!gameEvent.is(this.getListenableEvents())) { + return false; +- } else if (!vibrationUser.isValidVibration(gameEvent, context)) { +- return false; + } else { +- Optional position = vibrationUser.getPositionSource().getPosition(level); +- if (position.isEmpty()) { +- return false; +- } else { +- Vec3 vec3 = position.get(); +- if (!vibrationUser.canReceiveVibration(level, BlockPos.containing(pos), gameEvent, context)) { ++ Entity entity = context.sourceEntity(); ++ ++ if (entity != null) { ++ if (entity.isSpectator()) { + return false; +- } else if (isOccluded(level, pos, vec3)) { +- return false; +- } else { +- this.scheduleVibration(level, vibrationData, gameEvent, context, pos, vec3); +- return true; + } +- } +- } +- } + +- public void forceScheduleVibration(ServerLevel level, GameEvent gameEvent, GameEvent.Context context, Vec3 eventPos) { +- this.system +- .getVibrationUser() +- .getPositionSource() +- .getPosition(level) +- .ifPresent(vibrationUserPos -> this.scheduleVibration(level, this.system.getVibrationData(), gameEvent, context, eventPos, vibrationUserPos)); +- } ++ if (entity.isSteppingCarefully() && gameEvent.is(GameEventTags.IGNORE_VIBRATIONS_SNEAKING)) { ++ if (this.canTriggerAvoidVibration() && entity instanceof ServerPlayer) { ++ ServerPlayer entityplayer = (ServerPlayer) entity; + +- private void scheduleVibration( +- ServerLevel level, VibrationSystem.Data data, GameEvent gameEvent, GameEvent.Context context, Vec3 pos, Vec3 vibrationUserPos +- ) { +- data.selectionStrategy +- .addCandidate(new VibrationInfo(gameEvent, (float)pos.distanceTo(vibrationUserPos), pos, context.sourceEntity()), level.getGameTime()); +- } ++ CriteriaTriggers.AVOID_VIBRATION.trigger(entityplayer); ++ } + +- public static float distanceBetweenInBlocks(BlockPos pos1, BlockPos pos2) { +- return (float)Math.sqrt(pos1.distSqr(pos2)); +- } ++ return false; ++ } + +- private static boolean isOccluded(Level level, Vec3 eventPos, Vec3 vibrationUserPos) { +- Vec3 vec3 = new Vec3((double)Mth.floor(eventPos.x) + 0.5, (double)Mth.floor(eventPos.y) + 0.5, (double)Mth.floor(eventPos.z) + 0.5); +- Vec3 vec31 = new Vec3( +- (double)Mth.floor(vibrationUserPos.x) + 0.5, (double)Mth.floor(vibrationUserPos.y) + 0.5, (double)Mth.floor(vibrationUserPos.z) + 0.5 +- ); +- +- for (Direction direction : Direction.values()) { +- Vec3 vec32 = vec3.relative(direction, 1.0E-5F); +- if (level.isBlockInLine(new ClipBlockStateContext(vec32, vec31, state -> state.is(BlockTags.OCCLUDES_VIBRATION_SIGNALS))).getType() +- != HitResult.Type.BLOCK) { +- return false; ++ if (entity.dampensVibrations()) { ++ return false; ++ } + } +- } + +- return true; ++ return context.affectedState() != null ? !context.affectedState().is(BlockTags.DAMPENS_VIBRATIONS) : true; ++ } + } ++ ++ default void onDataChanged() {} + } + + public interface Ticker { ++ + static void tick(Level level, VibrationSystem.Data data, VibrationSystem.User user) { +- if (level instanceof ServerLevel serverLevel) { ++ if (level instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) level; ++ + if (data.currentVibration == null) { +- trySelectAndScheduleVibration(serverLevel, data, user); ++ trySelectAndScheduleVibration(worldserver, data, user); + } + + if (data.currentVibration != null) { + boolean flag = data.getTravelTimeInTicks() > 0; +- tryReloadVibrationParticle(serverLevel, data, user); ++ ++ tryReloadVibrationParticle(worldserver, data, user); + data.decrementTravelTime(); + if (data.getTravelTimeInTicks() <= 0) { +- flag = receiveVibration(serverLevel, data, user, data.currentVibration); ++ flag = receiveVibration(worldserver, data, user, data.currentVibration); + } + + if (flag) { + user.onDataChanged(); + } ++ + } + } + } + + private static void trySelectAndScheduleVibration(ServerLevel level, VibrationSystem.Data data, VibrationSystem.User user) { +- data.getSelectionStrategy() +- .chosenCandidate(level.getGameTime()) +- .ifPresent( +- vibrationInfo -> { +- data.setCurrentVibration(vibrationInfo); +- Vec3 vec3 = vibrationInfo.pos(); +- data.setTravelTimeInTicks(user.calculateTravelTimeInTicks(vibrationInfo.distance())); +- level.sendParticles( +- new VibrationParticleOption(user.getPositionSource(), data.getTravelTimeInTicks()), vec3.x, vec3.y, vec3.z, 1, 0.0, 0.0, 0.0, 0.0 +- ); +- user.onDataChanged(); +- data.getSelectionStrategy().startOver(); +- } +- ); ++ data.getSelectionStrategy().chosenCandidate(level.getGameTime()).ifPresent((vibrationinfo) -> { ++ data.setCurrentVibration(vibrationinfo); ++ Vec3 vec3d = vibrationinfo.pos(); ++ ++ data.setTravelTimeInTicks(user.calculateTravelTimeInTicks(vibrationinfo.distance())); ++ level.sendParticles(new VibrationParticleOption(user.getPositionSource(), data.getTravelTimeInTicks()), vec3d.x, vec3d.y, vec3d.z, 1, 0.0D, 0.0D, 0.0D, 0.0D); ++ user.onDataChanged(); ++ data.getSelectionStrategy().startOver(); ++ }); + } + + private static void tryReloadVibrationParticle(ServerLevel level, VibrationSystem.Data data, VibrationSystem.User user) { +@@ -303,48 +206,45 @@ + if (data.currentVibration == null) { + data.setReloadVibrationParticle(false); + } else { +- Vec3 vec3 = data.currentVibration.pos(); +- PositionSource positionSource = user.getPositionSource(); +- Vec3 vec31 = positionSource.getPosition(level).orElse(vec3); +- int travelTimeInTicks = data.getTravelTimeInTicks(); +- int i = user.calculateTravelTimeInTicks(data.currentVibration.distance()); +- double d = 1.0 - (double)travelTimeInTicks / (double)i; +- double d1 = Mth.lerp(d, vec3.x, vec31.x); +- double d2 = Mth.lerp(d, vec3.y, vec31.y); +- double d3 = Mth.lerp(d, vec3.z, vec31.z); +- boolean flag = level.sendParticles(new VibrationParticleOption(positionSource, travelTimeInTicks), d1, d2, d3, 1, 0.0, 0.0, 0.0, 0.0) > 0; ++ Vec3 vec3d = data.currentVibration.pos(); ++ PositionSource positionsource = user.getPositionSource(); ++ Vec3 vec3d1 = (Vec3) positionsource.getPosition(level).orElse(vec3d); ++ int i = data.getTravelTimeInTicks(); ++ int j = user.calculateTravelTimeInTicks(data.currentVibration.distance()); ++ double d0 = 1.0D - (double) i / (double) j; ++ double d1 = Mth.lerp(d0, vec3d.x, vec3d1.x); ++ double d2 = Mth.lerp(d0, vec3d.y, vec3d1.y); ++ double d3 = Mth.lerp(d0, vec3d.z, vec3d1.z); ++ boolean flag = level.sendParticles(new VibrationParticleOption(positionsource, i), d1, d2, d3, 1, 0.0D, 0.0D, 0.0D, 0.0D) > 0; ++ + if (flag) { + data.setReloadVibrationParticle(false); + } ++ + } + } + } + + private static boolean receiveVibration(ServerLevel level, VibrationSystem.Data data, VibrationSystem.User user, VibrationInfo vibrationInfo) { +- BlockPos blockPos = BlockPos.containing(vibrationInfo.pos()); +- BlockPos blockPos1 = user.getPositionSource().getPosition(level).map(BlockPos::containing).orElse(blockPos); +- if (user.requiresAdjacentChunksToBeTicking() && !areAdjacentChunksTicking(level, blockPos1)) { ++ BlockPos blockposition = BlockPos.containing(vibrationInfo.pos()); ++ BlockPos blockposition1 = (BlockPos) user.getPositionSource().getPosition(level).map(BlockPos::containing).orElse(blockposition); ++ ++ if (user.requiresAdjacentChunksToBeTicking() && !areAdjacentChunksTicking(level, blockposition1)) { + return false; + } else { +- user.onReceiveVibration( +- level, +- blockPos, +- vibrationInfo.gameEvent(), +- vibrationInfo.getEntity(level).orElse(null), +- vibrationInfo.getProjectileOwner(level).orElse(null), +- VibrationSystem.Listener.distanceBetweenInBlocks(blockPos, blockPos1) +- ); +- data.setCurrentVibration(null); ++ // CraftBukkit - decompile error ++ user.onReceiveVibration(level, blockposition, vibrationInfo.gameEvent(), (Entity) vibrationInfo.getEntity(level).orElse(null), (Entity) vibrationInfo.getProjectileOwner(level).orElse(null), VibrationSystem.Listener.distanceBetweenInBlocks(blockposition, blockposition1)); ++ data.setCurrentVibration((VibrationInfo) null); + return true; + } + } + + private static boolean areAdjacentChunksTicking(Level level, BlockPos pos) { +- ChunkPos chunkPos = new ChunkPos(pos); ++ ChunkPos chunkcoordintpair = new ChunkPos(pos); + +- for (int i = chunkPos.x - 1; i <= chunkPos.x + 1; i++) { +- for (int i1 = chunkPos.z - 1; i1 <= chunkPos.z + 1; i1++) { +- if (!level.shouldTickBlocksAt(ChunkPos.asLong(i, i1)) || level.getChunkSource().getChunkNow(i, i1) == null) { ++ for (int i = chunkcoordintpair.x - 1; i <= chunkcoordintpair.x + 1; ++i) { ++ for (int j = chunkcoordintpair.z - 1; j <= chunkcoordintpair.z + 1; ++j) { ++ if (!level.shouldTickBlocksAt(ChunkPos.asLong(i, j)) || level.getChunkSource().getChunkNow(i, j) == null) { + return false; + } + } +@@ -354,59 +254,152 @@ + } + } + +- public interface User { +- int getListenerRadius(); ++ public static class Listener implements GameEventListener { + +- PositionSource getPositionSource(); ++ private final VibrationSystem system; + +- boolean canReceiveVibration(ServerLevel level, BlockPos pos, GameEvent gameEvent, GameEvent.Context context); +- +- void onReceiveVibration(ServerLevel level, BlockPos pos, GameEvent gameEvent, @Nullable Entity entity, @Nullable Entity playerEntity, float distance); +- +- default TagKey getListenableEvents() { +- return GameEventTags.VIBRATIONS; ++ public Listener(VibrationSystem system) { ++ this.system = system; + } + +- default boolean canTriggerAvoidVibration() { +- return false; ++ @Override ++ public PositionSource getListenerSource() { ++ return this.system.getVibrationUser().getPositionSource(); + } + +- default boolean requiresAdjacentChunksToBeTicking() { +- return false; ++ @Override ++ public int getListenerRadius() { ++ return this.system.getVibrationUser().getListenerRadius(); + } + +- default int calculateTravelTimeInTicks(float distance) { +- return Mth.floor(distance); +- } ++ @Override ++ public boolean handleGameEvent(ServerLevel level, GameEvent gameEvent, GameEvent.Context context, Vec3 pos) { ++ VibrationSystem.Data vibrationsystem_a = this.system.getVibrationData(); ++ VibrationSystem.User vibrationsystem_d = this.system.getVibrationUser(); + +- default boolean isValidVibration(GameEvent gameEvent, GameEvent.Context context) { +- if (!gameEvent.is(this.getListenableEvents())) { ++ if (vibrationsystem_a.getCurrentVibration() != null) { + return false; ++ } else if (!vibrationsystem_d.isValidVibration(gameEvent, context)) { ++ return false; + } else { +- Entity entity = context.sourceEntity(); +- if (entity != null) { +- if (entity.isSpectator()) { +- return false; +- } ++ Optional optional = vibrationsystem_d.getPositionSource().getPosition(level); + +- if (entity.isSteppingCarefully() && gameEvent.is(GameEventTags.IGNORE_VIBRATIONS_SNEAKING)) { +- if (this.canTriggerAvoidVibration() && entity instanceof ServerPlayer serverPlayer) { +- CriteriaTriggers.AVOID_VIBRATION.trigger(serverPlayer); +- } +- ++ if (optional.isEmpty()) { ++ return false; ++ } else { ++ Vec3 vec3d1 = (Vec3) optional.get(); ++ // CraftBukkit start ++ boolean defaultCancel = !vibrationsystem_d.canReceiveVibration(level, BlockPos.containing(pos), gameEvent, context); ++ Entity entity = context.sourceEntity(); ++ BlockReceiveGameEvent event = new BlockReceiveGameEvent(CraftGameEvent.minecraftToBukkit(gameEvent), CraftBlock.at(level, BlockPos.containing(vec3d1)), (entity == null) ? null : entity.getBukkitEntity()); ++ event.setCancelled(defaultCancel); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ // CraftBukkit end + return false; +- } +- +- if (entity.dampensVibrations()) { ++ } else if (isOccluded(level, pos, vec3d1)) { + return false; ++ } else { ++ this.scheduleVibration(level, vibrationsystem_a, gameEvent, context, pos, vec3d1); ++ return true; + } + } ++ } ++ } + +- return context.affectedState() == null || !context.affectedState().is(BlockTags.DAMPENS_VIBRATIONS); ++ public void forceScheduleVibration(ServerLevel level, GameEvent gameEvent, GameEvent.Context context, Vec3 eventPos) { ++ this.system.getVibrationUser().getPositionSource().getPosition(level).ifPresent((vec3d1) -> { ++ this.scheduleVibration(level, this.system.getVibrationData(), gameEvent, context, eventPos, vec3d1); ++ }); ++ } ++ ++ private void scheduleVibration(ServerLevel level, VibrationSystem.Data data, GameEvent gameEvent, GameEvent.Context context, Vec3 pos, Vec3 vibrationUserPos) { ++ data.selectionStrategy.addCandidate(new VibrationInfo(gameEvent, (float) pos.distanceTo(vibrationUserPos), pos, context.sourceEntity()), level.getGameTime()); ++ } ++ ++ public static float distanceBetweenInBlocks(BlockPos pos1, BlockPos pos2) { ++ return (float) Math.sqrt(pos1.distSqr(pos2)); ++ } ++ ++ private static boolean isOccluded(Level level, Vec3 eventPos, Vec3 vibrationUserPos) { ++ Vec3 vec3d2 = new Vec3((double) Mth.floor(eventPos.x) + 0.5D, (double) Mth.floor(eventPos.y) + 0.5D, (double) Mth.floor(eventPos.z) + 0.5D); ++ Vec3 vec3d3 = new Vec3((double) Mth.floor(vibrationUserPos.x) + 0.5D, (double) Mth.floor(vibrationUserPos.y) + 0.5D, (double) Mth.floor(vibrationUserPos.z) + 0.5D); ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; ++ ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ Vec3 vec3d4 = vec3d2.relative(enumdirection, 9.999999747378752E-6D); ++ ++ if (level.isBlockInLine(new ClipBlockStateContext(vec3d4, vec3d3, (iblockdata) -> { ++ return iblockdata.is(BlockTags.OCCLUDES_VIBRATION_SIGNALS); ++ })).getType() != HitResult.EnumMovingObjectType.BLOCK) { ++ return false; ++ } + } ++ ++ return true; + } ++ } + +- default void onDataChanged() { ++ public static final class Data { ++ ++ public static Codec CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(VibrationInfo.CODEC.optionalFieldOf("event").forGetter((vibrationsystem_a) -> { ++ return Optional.ofNullable(vibrationsystem_a.currentVibration); ++ }), VibrationSelector.CODEC.fieldOf("selector").forGetter(VibrationSystem.Data::getSelectionStrategy), ExtraCodecs.NON_NEGATIVE_INT.fieldOf("event_delay").orElse(0).forGetter(VibrationSystem.Data::getTravelTimeInTicks)).apply(instance, (optional, vibrationselector, integer) -> { ++ return new VibrationSystem.Data((VibrationInfo) optional.orElse(null), vibrationselector, integer, true); // CraftBukkit - decompile error ++ }); ++ }); ++ public static final String NBT_TAG_KEY = "listener"; ++ @Nullable ++ VibrationInfo currentVibration; ++ private int travelTimeInTicks; ++ final VibrationSelector selectionStrategy; ++ private boolean reloadVibrationParticle; ++ ++ private Data(@Nullable VibrationInfo currentVibration, VibrationSelector selectionStrategy, int travelTimeInTicks, boolean reloadVibrationParticle) { ++ this.currentVibration = currentVibration; ++ this.travelTimeInTicks = travelTimeInTicks; ++ this.selectionStrategy = selectionStrategy; ++ this.reloadVibrationParticle = reloadVibrationParticle; + } ++ ++ public Data() { ++ this((VibrationInfo) null, new VibrationSelector(), 0, false); ++ } ++ ++ public VibrationSelector getSelectionStrategy() { ++ return this.selectionStrategy; ++ } ++ ++ @Nullable ++ public VibrationInfo getCurrentVibration() { ++ return this.currentVibration; ++ } ++ ++ public void setCurrentVibration(@Nullable VibrationInfo currentVibration) { ++ this.currentVibration = currentVibration; ++ } ++ ++ public int getTravelTimeInTicks() { ++ return this.travelTimeInTicks; ++ } ++ ++ public void setTravelTimeInTicks(int travelTimeInTicks) { ++ this.travelTimeInTicks = travelTimeInTicks; ++ } ++ ++ public void decrementTravelTime() { ++ this.travelTimeInTicks = Math.max(0, this.travelTimeInTicks - 1); ++ } ++ ++ public boolean shouldReloadVibrationParticle() { ++ return this.reloadVibrationParticle; ++ } ++ ++ public void setReloadVibrationParticle(boolean reloadVibrationParticle) { ++ this.reloadVibrationParticle = reloadVibrationParticle; ++ } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/FlatLevelSource.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/FlatLevelSource.java.patch new file mode 100644 index 0000000000..655bb02775 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/FlatLevelSource.java.patch @@ -0,0 +1,187 @@ +--- a/net/minecraft/world/level/levelgen/FlatLevelSource.java ++++ b/net/minecraft/world/level/levelgen/FlatLevelSource.java +@@ -2,8 +2,8 @@ + + import com.mojang.serialization.Codec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import java.util.List; ++import java.util.Objects; + import java.util.concurrent.CompletableFuture; + import java.util.concurrent.Executor; + import java.util.stream.Stream; +@@ -19,7 +19,7 @@ + import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.biome.FixedBiomeSource; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.chunk.ChunkGeneratorStructureState; +@@ -28,29 +28,40 @@ + import net.minecraft.world.level.levelgen.structure.StructureSet; + + public class FlatLevelSource extends ChunkGenerator { +- public static final Codec CODEC = RecordCodecBuilder.create( +- instance -> instance.group(FlatLevelGeneratorSettings.CODEC.fieldOf("settings").forGetter(FlatLevelSource::settings)) +- .apply(instance, instance.stable(FlatLevelSource::new)) +- ); ++ ++ public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(FlatLevelGeneratorSettings.CODEC.fieldOf("settings").forGetter(FlatLevelSource::settings)).apply(instance, instance.stable(FlatLevelSource::new)); ++ }); + private final FlatLevelGeneratorSettings settings; + + public FlatLevelSource(FlatLevelGeneratorSettings settings) { +- super(new FixedBiomeSource(settings.getBiome()), Util.memoize(settings::adjustGenerationSettings)); +- this.settings = settings; ++ // CraftBukkit start ++ // WorldChunkManagerHell worldchunkmanagerhell = new WorldChunkManagerHell(generatorsettingsflat.getBiome()); ++ ++ // Objects.requireNonNull(generatorsettingsflat); ++ this(settings, new FixedBiomeSource(settings.getBiome())); + } + ++ public FlatLevelSource(FlatLevelGeneratorSettings generatorsettingsflat, net.minecraft.world.level.biome.BiomeSource worldchunkmanager) { ++ super(worldchunkmanager, Util.memoize(generatorsettingsflat::adjustGenerationSettings)); ++ // CraftBukkit end ++ this.settings = generatorsettingsflat; ++ } ++ + @Override + public ChunkGeneratorStructureState createState(HolderLookup structureSetLookup, RandomState randomState, long seed) { +- Stream> stream = this.settings +- .structureOverrides() +- .map(HolderSet::stream) +- .orElseGet(() -> structureSetLookup.listElements().map(reference -> (Holder)reference)); ++ Stream> stream = (Stream) this.settings.structureOverrides().map(HolderSet::stream).orElseGet(() -> { ++ return structureSetLookup.listElements().map((holder_c) -> { ++ return holder_c; ++ }); ++ }); ++ + return ChunkGeneratorStructureState.createForFlat(randomState, seed, this.biomeSource, stream); + } + + @Override + protected Codec codec() { +- return CODEC; ++ return FlatLevelSource.CODEC; + } + + public FlatLevelGeneratorSettings settings() { +@@ -58,8 +69,7 @@ + } + + @Override +- public void buildSurface(WorldGenRegion level, StructureManager structureManager, RandomState random, ChunkAccess chunk) { +- } ++ public void buildSurface(WorldGenRegion level, StructureManager structureManager, RandomState random, ChunkAccess chunk) {} + + @Override + public int getSpawnHeight(LevelHeightAccessor level) { +@@ -67,24 +77,23 @@ + } + + @Override +- public CompletableFuture fillFromNoise( +- Executor executor, Blender blender, RandomState random, StructureManager structureManager, ChunkAccess chunk +- ) { +- List layers = this.settings.getLayers(); +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); +- Heightmap heightmapUnprimed = chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.OCEAN_FLOOR_WG); +- Heightmap heightmapUnprimed1 = chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.WORLD_SURFACE_WG); ++ public CompletableFuture fillFromNoise(Executor executor, Blender blender, RandomState random, StructureManager structureManager, ChunkAccess chunk) { ++ List list = this.settings.getLayers(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ Heightmap heightmap = chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.OCEAN_FLOOR_WG); ++ Heightmap heightmap1 = chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.WORLD_SURFACE_WG); + +- for (int i = 0; i < Math.min(chunk.getHeight(), layers.size()); i++) { +- BlockState blockState = layers.get(i); +- if (blockState != null) { +- int i1 = chunk.getMinBuildHeight() + i; ++ for (int i = 0; i < Math.min(chunk.getHeight(), list.size()); ++i) { ++ IBlockData iblockdata = (IBlockData) list.get(i); + +- for (int i2 = 0; i2 < 16; i2++) { +- for (int i3 = 0; i3 < 16; i3++) { +- chunk.setBlockState(mutableBlockPos.set(i2, i1, i3), blockState, false); +- heightmapUnprimed.update(i2, i1, i3, blockState); +- heightmapUnprimed1.update(i2, i1, i3, blockState); ++ if (iblockdata != null) { ++ int j = chunk.getMinBuildHeight() + i; ++ ++ for (int k = 0; k < 16; ++k) { ++ for (int l = 0; l < 16; ++l) { ++ chunk.setBlockState(blockposition_mutableblockposition.set(k, j, l), iblockdata, false); ++ heightmap.update(k, j, l, iblockdata); ++ heightmap1.update(k, j, l, iblockdata); + } + } + } +@@ -95,12 +104,13 @@ + + @Override + public int getBaseHeight(int x, int z, Heightmap.Types type, LevelHeightAccessor level, RandomState random) { +- List layers = this.settings.getLayers(); ++ List list = this.settings.getLayers(); + +- for (int i = Math.min(layers.size(), level.getMaxBuildHeight()) - 1; i >= 0; i--) { +- BlockState blockState = layers.get(i); +- if (blockState != null && type.isOpaque().test(blockState)) { +- return level.getMinBuildHeight() + i + 1; ++ for (int k = Math.min(list.size(), level.getMaxBuildHeight()) - 1; k >= 0; --k) { ++ IBlockData iblockdata = (IBlockData) list.get(k); ++ ++ if (iblockdata != null && type.isOpaque().test(iblockdata)) { ++ return level.getMinBuildHeight() + k + 1; + } + } + +@@ -109,36 +119,21 @@ + + @Override + public NoiseColumn getBaseColumn(int x, int z, LevelHeightAccessor height, RandomState random) { +- return new NoiseColumn( +- height.getMinBuildHeight(), +- this.settings +- .getLayers() +- .stream() +- .limit((long)height.getHeight()) +- .map(state -> state == null ? Blocks.AIR.defaultBlockState() : state) +- .toArray(BlockState[]::new) +- ); ++ return new NoiseColumn(height.getMinBuildHeight(), (IBlockData[]) this.settings.getLayers().stream().limit((long) height.getHeight()).map((iblockdata) -> { ++ return iblockdata == null ? Blocks.AIR.defaultBlockState() : iblockdata; ++ }).toArray((k) -> { ++ return new IBlockData[k]; ++ })); + } + + @Override +- public void addDebugScreenInfo(List info, RandomState random, BlockPos pos) { +- } ++ public void addDebugScreenInfo(List info, RandomState random, BlockPos pos) {} + + @Override +- public void applyCarvers( +- WorldGenRegion level, +- long seed, +- RandomState random, +- BiomeManager biomeManager, +- StructureManager structureManager, +- ChunkAccess chunk, +- GenerationStep.Carving step +- ) { +- } ++ public void applyCarvers(WorldGenRegion level, long seed, RandomState randomstate, BiomeManager random, StructureManager biomeManager, ChunkAccess structureManager, GenerationStep.Carving chunk) {} + + @Override +- public void spawnOriginalMobs(WorldGenRegion level) { +- } ++ public void spawnOriginalMobs(WorldGenRegion level) {} + + @Override + public int getMinY() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java.patch new file mode 100644 index 0000000000..4319b82ba5 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java.patch @@ -0,0 +1,641 @@ +--- a/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java ++++ b/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +@@ -1,3 +1,4 @@ ++// keep + package net.minecraft.world.level.levelgen; + + import com.google.common.annotations.VisibleForTesting; +@@ -5,9 +6,10 @@ + import com.google.common.collect.Sets; + import com.mojang.serialization.Codec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import java.text.DecimalFormat; ++import java.util.Iterator; + import java.util.List; ++import java.util.Objects; + import java.util.OptionalInt; + import java.util.Set; + import java.util.concurrent.CompletableFuture; +@@ -36,7 +38,7 @@ + import net.minecraft.world.level.biome.BiomeResolver; + import net.minecraft.world.level.biome.BiomeSource; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.CarvingMask; + import net.minecraft.world.level.chunk.ChunkAccess; + import net.minecraft.world.level.chunk.ChunkGenerator; +@@ -49,35 +51,39 @@ + import org.apache.commons.lang3.mutable.MutableObject; + + public final class NoiseBasedChunkGenerator extends ChunkGenerator { +- public static final Codec CODEC = RecordCodecBuilder.create( +- instance -> instance.group( +- BiomeSource.CODEC.fieldOf("biome_source").forGetter(generator -> generator.biomeSource), +- NoiseGeneratorSettings.CODEC.fieldOf("settings").forGetter(generator -> generator.settings) +- ) +- .apply(instance, instance.stable(NoiseBasedChunkGenerator::new)) +- ); +- private static final BlockState AIR = Blocks.AIR.defaultBlockState(); +- private final Holder settings; ++ ++ public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(BiomeSource.CODEC.fieldOf("biome_source").forGetter((chunkgeneratorabstract) -> { ++ return chunkgeneratorabstract.biomeSource; ++ }), NoiseGeneratorSettings.CODEC.fieldOf("settings").forGetter((chunkgeneratorabstract) -> { ++ return chunkgeneratorabstract.settings; ++ })).apply(instance, instance.stable(NoiseBasedChunkGenerator::new)); ++ }); ++ private static final IBlockData AIR = Blocks.AIR.defaultBlockState(); ++ public final Holder settings; + private final Supplier globalFluidPicker; + + public NoiseBasedChunkGenerator(BiomeSource biomeSource, Holder settings) { + super(biomeSource); + this.settings = settings; +- this.globalFluidPicker = Suppliers.memoize(() -> createFluidPicker(settings.value())); ++ this.globalFluidPicker = Suppliers.memoize(() -> { ++ return createFluidPicker((NoiseGeneratorSettings) settings.value()); ++ }); + } + + private static Aquifer.FluidPicker createFluidPicker(NoiseGeneratorSettings settings) { +- Aquifer.FluidStatus fluidStatus = new Aquifer.FluidStatus(-54, Blocks.LAVA.defaultBlockState()); ++ Aquifer.FluidStatus aquifer_b = new Aquifer.FluidStatus(-54, Blocks.LAVA.defaultBlockState()); + int i = settings.seaLevel(); +- Aquifer.FluidStatus fluidStatus1 = new Aquifer.FluidStatus(i, settings.defaultFluid()); +- Aquifer.FluidStatus fluidStatus2 = new Aquifer.FluidStatus(DimensionType.MIN_Y * 2, Blocks.AIR.defaultBlockState()); +- return (x, y, z) -> y < Math.min(-54, i) ? fluidStatus : fluidStatus1; ++ Aquifer.FluidStatus aquifer_b1 = new Aquifer.FluidStatus(i, settings.defaultFluid()); ++ Aquifer.FluidStatus aquifer_b2 = new Aquifer.FluidStatus(DimensionType.MIN_Y * 2, Blocks.AIR.defaultBlockState()); ++ ++ return (j, k, l) -> { ++ return k < Math.min(-54, i) ? aquifer_b : aquifer_b1; ++ }; + } + + @Override +- public CompletableFuture createBiomes( +- Executor executor, RandomState randomState, Blender blender, StructureManager structureManager, ChunkAccess chunk +- ) { ++ public CompletableFuture createBiomes(Executor executor, RandomState randomState, Blender blender, StructureManager structureManager, ChunkAccess chunk) { + return CompletableFuture.supplyAsync(Util.wrapThreadWithTaskName("init_biomes", () -> { + this.doCreateBiomes(blender, randomState, structureManager, chunk); + return chunk; +@@ -85,20 +91,21 @@ + } + + private void doCreateBiomes(Blender blender, RandomState random, StructureManager structureManager, ChunkAccess chunk) { +- NoiseChunk noiseChunk = chunk.getOrCreateNoiseChunk(chunkAccess -> this.createNoiseChunk(chunkAccess, structureManager, blender, random)); +- BiomeResolver biomeResolver = BelowZeroRetrogen.getBiomeResolver(blender.getBiomeResolver(this.biomeSource), chunk); +- chunk.fillBiomesFromNoise(biomeResolver, noiseChunk.cachedClimateSampler(random.router(), this.settings.value().spawnTarget())); ++ NoiseChunk noisechunk = chunk.getOrCreateNoiseChunk((ichunkaccess1) -> { ++ return this.createNoiseChunk(ichunkaccess1, structureManager, blender, random); ++ }); ++ BiomeResolver biomeresolver = BelowZeroRetrogen.getBiomeResolver(blender.getBiomeResolver(this.biomeSource), chunk); ++ ++ chunk.fillBiomesFromNoise(biomeresolver, noisechunk.cachedClimateSampler(random.router(), ((NoiseGeneratorSettings) this.settings.value()).spawnTarget())); + } + + private NoiseChunk createNoiseChunk(ChunkAccess chunk, StructureManager structureManager, Blender blender, RandomState random) { +- return NoiseChunk.forChunk( +- chunk, random, Beardifier.forStructuresInChunk(structureManager, chunk.getPos()), this.settings.value(), this.globalFluidPicker.get(), blender +- ); ++ return NoiseChunk.forChunk(chunk, random, Beardifier.forStructuresInChunk(structureManager, chunk.getPos()), (NoiseGeneratorSettings) this.settings.value(), (Aquifer.FluidPicker) this.globalFluidPicker.get(), blender); + } + + @Override + protected Codec codec() { +- return CODEC; ++ return NoiseBasedChunkGenerator.CODEC; + } + + public Holder generatorSettings() { +@@ -111,110 +118,88 @@ + + @Override + public int getBaseHeight(int x, int z, Heightmap.Types type, LevelHeightAccessor level, RandomState random) { +- return this.iterateNoiseColumn(level, random, x, z, null, type.isOpaque()).orElse(level.getMinBuildHeight()); ++ return this.iterateNoiseColumn(level, random, x, z, (MutableObject) null, type.isOpaque()).orElse(level.getMinBuildHeight()); + } + + @Override + public NoiseColumn getBaseColumn(int x, int z, LevelHeightAccessor height, RandomState random) { +- MutableObject mutableObject = new MutableObject<>(); +- this.iterateNoiseColumn(height, random, x, z, mutableObject, null); +- return mutableObject.getValue(); ++ MutableObject mutableobject = new MutableObject(); ++ ++ this.iterateNoiseColumn(height, random, x, z, mutableobject, (Predicate) null); ++ return (NoiseColumn) mutableobject.getValue(); + } + + @Override + public void addDebugScreenInfo(List info, RandomState random, BlockPos pos) { +- DecimalFormat decimalFormat = new DecimalFormat("0.000"); +- NoiseRouter noiseRouter = random.router(); +- DensityFunction.SinglePointContext singlePointContext = new DensityFunction.SinglePointContext(pos.getX(), pos.getY(), pos.getZ()); +- double d = noiseRouter.ridges().compute(singlePointContext); +- info.add( +- "NoiseRouter T: " +- + decimalFormat.format(noiseRouter.temperature().compute(singlePointContext)) +- + " V: " +- + decimalFormat.format(noiseRouter.vegetation().compute(singlePointContext)) +- + " C: " +- + decimalFormat.format(noiseRouter.continents().compute(singlePointContext)) +- + " E: " +- + decimalFormat.format(noiseRouter.erosion().compute(singlePointContext)) +- + " D: " +- + decimalFormat.format(noiseRouter.depth().compute(singlePointContext)) +- + " W: " +- + decimalFormat.format(d) +- + " PV: " +- + decimalFormat.format((double)NoiseRouterData.peaksAndValleys((float)d)) +- + " AS: " +- + decimalFormat.format(noiseRouter.initialDensityWithoutJaggedness().compute(singlePointContext)) +- + " N: " +- + decimalFormat.format(noiseRouter.finalDensity().compute(singlePointContext)) +- ); ++ DecimalFormat decimalformat = new DecimalFormat("0.000"); ++ NoiseRouter noiserouter = random.router(); ++ DensityFunction.e densityfunction_e = new DensityFunction.e(pos.getX(), pos.getY(), pos.getZ()); ++ double d0 = noiserouter.ridges().compute(densityfunction_e); ++ String s = decimalformat.format(noiserouter.temperature().compute(densityfunction_e)); ++ ++ info.add("NoiseRouter T: " + s + " V: " + decimalformat.format(noiserouter.vegetation().compute(densityfunction_e)) + " C: " + decimalformat.format(noiserouter.continents().compute(densityfunction_e)) + " E: " + decimalformat.format(noiserouter.erosion().compute(densityfunction_e)) + " D: " + decimalformat.format(noiserouter.depth().compute(densityfunction_e)) + " W: " + decimalformat.format(d0) + " PV: " + decimalformat.format((double) NoiseRouterData.peaksAndValleys((float) d0)) + " AS: " + decimalformat.format(noiserouter.initialDensityWithoutJaggedness().compute(densityfunction_e)) + " N: " + decimalformat.format(noiserouter.finalDensity().compute(densityfunction_e))); + } + +- private OptionalInt iterateNoiseColumn( +- LevelHeightAccessor level, RandomState random, int x, int z, @Nullable MutableObject column, @Nullable Predicate stoppingState +- ) { +- NoiseSettings noiseSettings = this.settings.value().noiseSettings().clampToHeightAccessor(level); +- int cellHeight = noiseSettings.getCellHeight(); +- int i = noiseSettings.minY(); +- int i1 = Mth.floorDiv(i, cellHeight); +- int i2 = Mth.floorDiv(noiseSettings.height(), cellHeight); +- if (i2 <= 0) { ++ private OptionalInt iterateNoiseColumn(LevelHeightAccessor level, RandomState random, int x, int z, @Nullable MutableObject column, @Nullable Predicate stoppingState) { ++ NoiseSettings noisesettings = ((NoiseGeneratorSettings) this.settings.value()).noiseSettings().clampToHeightAccessor(level); ++ int k = noisesettings.getCellHeight(); ++ int l = noisesettings.minY(); ++ int i1 = Mth.floorDiv(l, k); ++ int j1 = Mth.floorDiv(noisesettings.height(), k); ++ ++ if (j1 <= 0) { + return OptionalInt.empty(); + } else { +- BlockState[] blockStates; ++ IBlockData[] aiblockdata; ++ + if (column == null) { +- blockStates = null; ++ aiblockdata = null; + } else { +- blockStates = new BlockState[noiseSettings.height()]; +- column.setValue(new NoiseColumn(i, blockStates)); ++ aiblockdata = new IBlockData[noisesettings.height()]; ++ column.setValue(new NoiseColumn(l, aiblockdata)); + } + +- int cellWidth = noiseSettings.getCellWidth(); +- int i3 = Math.floorDiv(x, cellWidth); +- int i4 = Math.floorDiv(z, cellWidth); +- int i5 = Math.floorMod(x, cellWidth); +- int i6 = Math.floorMod(z, cellWidth); +- int i7 = i3 * cellWidth; +- int i8 = i4 * cellWidth; +- double d = (double)i5 / (double)cellWidth; +- double d1 = (double)i6 / (double)cellWidth; +- NoiseChunk noiseChunk = new NoiseChunk( +- 1, +- random, +- i7, +- i8, +- noiseSettings, +- DensityFunctions.BeardifierMarker.INSTANCE, +- this.settings.value(), +- this.globalFluidPicker.get(), +- Blender.empty() +- ); +- noiseChunk.initializeForFirstCellX(); +- noiseChunk.advanceCellX(0); ++ int k1 = noisesettings.getCellWidth(); ++ int l1 = Math.floorDiv(x, k1); ++ int i2 = Math.floorDiv(z, k1); ++ int j2 = Math.floorMod(x, k1); ++ int k2 = Math.floorMod(z, k1); ++ int l2 = l1 * k1; ++ int i3 = i2 * k1; ++ double d0 = (double) j2 / (double) k1; ++ double d1 = (double) k2 / (double) k1; ++ NoiseChunk noisechunk = new NoiseChunk(1, random, l2, i3, noisesettings, DensityFunctions.b.INSTANCE, (NoiseGeneratorSettings) this.settings.value(), (Aquifer.FluidPicker) this.globalFluidPicker.get(), Blender.empty()); + +- for (int i9 = i2 - 1; i9 >= 0; i9--) { +- noiseChunk.selectCellYZ(i9, 0); ++ noisechunk.initializeForFirstCellX(); ++ noisechunk.advanceCellX(0); + +- for (int i10 = cellHeight - 1; i10 >= 0; i10--) { +- int i11 = (i1 + i9) * cellHeight + i10; +- double d2 = (double)i10 / (double)cellHeight; +- noiseChunk.updateForY(i11, d2); +- noiseChunk.updateForX(x, d); +- noiseChunk.updateForZ(z, d1); +- BlockState interpolatedState = noiseChunk.getInterpolatedState(); +- BlockState blockState = interpolatedState == null ? this.settings.value().defaultBlock() : interpolatedState; +- if (blockStates != null) { +- int i12 = i9 * cellHeight + i10; +- blockStates[i12] = blockState; ++ for (int j3 = j1 - 1; j3 >= 0; --j3) { ++ noisechunk.selectCellYZ(j3, 0); ++ ++ for (int k3 = k - 1; k3 >= 0; --k3) { ++ int l3 = (i1 + j3) * k + k3; ++ double d2 = (double) k3 / (double) k; ++ ++ noisechunk.updateForY(l3, d2); ++ noisechunk.updateForX(x, d0); ++ noisechunk.updateForZ(z, d1); ++ IBlockData iblockdata = noisechunk.getInterpolatedState(); ++ IBlockData iblockdata1 = iblockdata == null ? ((NoiseGeneratorSettings) this.settings.value()).defaultBlock() : iblockdata; ++ ++ if (aiblockdata != null) { ++ int i4 = j3 * k + k3; ++ ++ aiblockdata[i4] = iblockdata1; + } + +- if (stoppingState != null && stoppingState.test(blockState)) { +- noiseChunk.stopInterpolation(); +- return OptionalInt.of(i11 + 1); ++ if (stoppingState != null && stoppingState.test(iblockdata1)) { ++ noisechunk.stopInterpolation(); ++ return OptionalInt.of(l3 + 1); + } + } + } + +- noiseChunk.stopInterpolation(); ++ noisechunk.stopInterpolation(); + return OptionalInt.empty(); + } + } +@@ -222,178 +207,167 @@ + @Override + public void buildSurface(WorldGenRegion level, StructureManager structureManager, RandomState random, ChunkAccess chunk) { + if (!SharedConstants.debugVoidTerrain(chunk.getPos())) { +- WorldGenerationContext worldGenerationContext = new WorldGenerationContext(this, level); +- this.buildSurface( +- chunk, +- worldGenerationContext, +- random, +- structureManager, +- level.getBiomeManager(), +- level.registryAccess().registryOrThrow(Registries.BIOME), +- Blender.of(level) +- ); ++ WorldGenerationContext worldgenerationcontext = new WorldGenerationContext(this, level); ++ ++ this.buildSurface(chunk, worldgenerationcontext, random, structureManager, level.getBiomeManager(), level.registryAccess().registryOrThrow(Registries.BIOME), Blender.of(level)); + } + } + + @VisibleForTesting +- public void buildSurface( +- ChunkAccess chunk, +- WorldGenerationContext context, +- RandomState random, +- StructureManager structureManager, +- BiomeManager biomeManager, +- Registry biomes, +- Blender blender +- ) { +- NoiseChunk noiseChunk = chunk.getOrCreateNoiseChunk(chunkAccess -> this.createNoiseChunk(chunkAccess, structureManager, blender, random)); +- NoiseGeneratorSettings noiseGeneratorSettings = this.settings.value(); +- random.surfaceSystem() +- .buildSurface( +- random, biomeManager, biomes, noiseGeneratorSettings.useLegacyRandomSource(), context, chunk, noiseChunk, noiseGeneratorSettings.surfaceRule() +- ); ++ public void buildSurface(ChunkAccess chunk, WorldGenerationContext context, RandomState random, StructureManager structureManager, BiomeManager biomeManager, Registry biomes, Blender blender) { ++ NoiseChunk noisechunk = chunk.getOrCreateNoiseChunk((ichunkaccess1) -> { ++ return this.createNoiseChunk(ichunkaccess1, structureManager, blender, random); ++ }); ++ NoiseGeneratorSettings generatorsettingbase = (NoiseGeneratorSettings) this.settings.value(); ++ ++ random.surfaceSystem().buildSurface(random, biomeManager, biomes, generatorsettingbase.useLegacyRandomSource(), context, chunk, noisechunk, generatorsettingbase.surfaceRule()); + } + + @Override +- public void applyCarvers( +- WorldGenRegion level, +- long seed, +- RandomState random, +- BiomeManager biomeManager, +- StructureManager structureManager, +- ChunkAccess chunk, +- GenerationStep.Carving step +- ) { +- BiomeManager biomeManager1 = biomeManager.withDifferentSource((x, y, z) -> this.biomeSource.getNoiseBiome(x, y, z, random.sampler())); +- WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(RandomSupport.generateUniqueSeed())); +- int i = 8; +- ChunkPos pos = chunk.getPos(); +- NoiseChunk noiseChunk = chunk.getOrCreateNoiseChunk(chunkAccess -> this.createNoiseChunk(chunkAccess, structureManager, Blender.of(level), random)); +- Aquifer aquifer = noiseChunk.aquifer(); +- CarvingContext carvingContext = new CarvingContext( +- this, level.registryAccess(), chunk.getHeightAccessorForGeneration(), noiseChunk, random, this.settings.value().surfaceRule() +- ); +- CarvingMask carvingMask = ((ProtoChunk)chunk).getOrCreateCarvingMask(step); ++ public void applyCarvers(WorldGenRegion level, long seed, RandomState randomstate, BiomeManager random, StructureManager biomeManager, ChunkAccess structureManager, GenerationStep.Carving chunk) { ++ BiomeManager biomemanager1 = random.withDifferentSource((j, k, l) -> { ++ return this.biomeSource.getNoiseBiome(j, k, l, randomstate.sampler()); ++ }); ++ WorldgenRandom seededrandom = new WorldgenRandom(new LegacyRandomSource(RandomSupport.generateUniqueSeed())); ++ boolean flag = true; ++ ChunkPos chunkcoordintpair = structureManager.getPos(); ++ NoiseChunk noisechunk = structureManager.getOrCreateNoiseChunk((ichunkaccess1) -> { ++ return this.createNoiseChunk(ichunkaccess1, biomeManager, Blender.of(level), randomstate); ++ }); ++ Aquifer aquifer = noisechunk.aquifer(); ++ CarvingContext carvingcontext = new CarvingContext(this, level.registryAccess(), structureManager.getHeightAccessorForGeneration(), noisechunk, randomstate, ((NoiseGeneratorSettings) this.settings.value()).surfaceRule()); ++ CarvingMask carvingmask = ((ProtoChunk) structureManager).getOrCreateCarvingMask(chunk); + +- for (int i1 = -8; i1 <= 8; i1++) { +- for (int i2 = -8; i2 <= 8; i2++) { +- ChunkPos chunkPos = new ChunkPos(pos.x + i1, pos.z + i2); +- ChunkAccess chunk1 = level.getChunk(chunkPos.x, chunkPos.z); +- BiomeGenerationSettings biomeGenerationSettings = chunk1.carverBiome( +- () -> this.getBiomeGenerationSettings( +- this.biomeSource +- .getNoiseBiome(QuartPos.fromBlock(chunkPos.getMinBlockX()), 0, QuartPos.fromBlock(chunkPos.getMinBlockZ()), random.sampler()) +- ) +- ); +- Iterable>> carvers = biomeGenerationSettings.getCarvers(step); +- int i3 = 0; ++ for (int j = -8; j <= 8; ++j) { ++ for (int k = -8; k <= 8; ++k) { ++ ChunkPos chunkcoordintpair1 = new ChunkPos(chunkcoordintpair.x + j, chunkcoordintpair.z + k); ++ ChunkAccess ichunkaccess1 = level.getChunk(chunkcoordintpair1.x, chunkcoordintpair1.z); ++ BiomeGenerationSettings biomesettingsgeneration = ichunkaccess1.carverBiome(() -> { ++ return this.getBiomeGenerationSettings(this.biomeSource.getNoiseBiome(QuartPos.fromBlock(chunkcoordintpair1.getMinBlockX()), 0, QuartPos.fromBlock(chunkcoordintpair1.getMinBlockZ()), randomstate.sampler())); ++ }); ++ Iterable>> iterable = biomesettingsgeneration.getCarvers(chunk); ++ int l = 0; + +- for (Holder> holder : carvers) { +- ConfiguredWorldCarver configuredWorldCarver = holder.value(); +- worldgenRandom.setLargeFeatureSeed(seed + (long)i3, chunkPos.x, chunkPos.z); +- if (configuredWorldCarver.isStartChunk(worldgenRandom)) { +- configuredWorldCarver.carve(carvingContext, chunk, biomeManager1::getBiome, worldgenRandom, aquifer, chunkPos, carvingMask); +- } ++ for (Iterator iterator = iterable.iterator(); iterator.hasNext(); ++l) { ++ Holder> holder = (Holder) iterator.next(); ++ ConfiguredWorldCarver worldgencarverwrapper = (ConfiguredWorldCarver) holder.value(); + +- i3++; ++ seededrandom.setLargeFeatureSeed(seed + (long) l, chunkcoordintpair1.x, chunkcoordintpair1.z); ++ if (worldgencarverwrapper.isStartChunk(seededrandom)) { ++ Objects.requireNonNull(biomemanager1); ++ worldgencarverwrapper.carve(carvingcontext, structureManager, biomemanager1::getBiome, seededrandom, aquifer, chunkcoordintpair1, carvingmask); ++ } + } + } + } ++ + } + + @Override +- public CompletableFuture fillFromNoise( +- Executor executor, Blender blender, RandomState random, StructureManager structureManager, ChunkAccess chunk +- ) { +- NoiseSettings noiseSettings = this.settings.value().noiseSettings().clampToHeightAccessor(chunk.getHeightAccessorForGeneration()); +- int i = noiseSettings.minY(); +- int i1 = Mth.floorDiv(i, noiseSettings.getCellHeight()); +- int i2 = Mth.floorDiv(noiseSettings.height(), noiseSettings.getCellHeight()); +- if (i2 <= 0) { ++ public CompletableFuture fillFromNoise(Executor executor, Blender blender, RandomState random, StructureManager structureManager, ChunkAccess chunk) { ++ NoiseSettings noisesettings = ((NoiseGeneratorSettings) this.settings.value()).noiseSettings().clampToHeightAccessor(chunk.getHeightAccessorForGeneration()); ++ int i = noisesettings.minY(); ++ int j = Mth.floorDiv(i, noisesettings.getCellHeight()); ++ int k = Mth.floorDiv(noisesettings.height(), noisesettings.getCellHeight()); ++ ++ if (k <= 0) { + return CompletableFuture.completedFuture(chunk); + } else { +- int sectionIndex = chunk.getSectionIndex(i2 * noiseSettings.getCellHeight() - 1 + i); +- int sectionIndex1 = chunk.getSectionIndex(i); ++ int l = chunk.getSectionIndex(k * noisesettings.getCellHeight() - 1 + i); ++ int i1 = chunk.getSectionIndex(i); + Set set = Sets.newHashSet(); + +- for (int i3 = sectionIndex; i3 >= sectionIndex1; i3--) { +- LevelChunkSection section = chunk.getSection(i3); +- section.acquire(); +- set.add(section); ++ for (int j1 = l; j1 >= i1; --j1) { ++ LevelChunkSection chunksection = chunk.getSection(j1); ++ ++ chunksection.acquire(); ++ set.add(chunksection); + } + +- return CompletableFuture.supplyAsync( +- Util.wrapThreadWithTaskName("wgen_fill_noise", () -> this.doFill(blender, structureManager, random, chunk, i1, i2)), +- Util.backgroundExecutor() +- ) +- .whenCompleteAsync((chunkAccess, throwable) -> { +- for (LevelChunkSection levelChunkSection : set) { +- levelChunkSection.release(); +- } +- }, executor); ++ return CompletableFuture.supplyAsync(Util.wrapThreadWithTaskName("wgen_fill_noise", () -> { ++ return this.doFill(blender, structureManager, random, chunk, j, k); ++ }), Util.backgroundExecutor()).whenCompleteAsync((ichunkaccess1, throwable) -> { ++ Iterator iterator = set.iterator(); ++ ++ while (iterator.hasNext()) { ++ LevelChunkSection chunksection1 = (LevelChunkSection) iterator.next(); ++ ++ chunksection1.release(); ++ } ++ ++ }, executor); + } + } + + private ChunkAccess doFill(Blender blender, StructureManager structureManager, RandomState random, ChunkAccess chunk, int minCellY, int cellCountY) { +- NoiseChunk noiseChunk = chunk.getOrCreateNoiseChunk(chunkAccess -> this.createNoiseChunk(chunkAccess, structureManager, blender, random)); +- Heightmap heightmapUnprimed = chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.OCEAN_FLOOR_WG); +- Heightmap heightmapUnprimed1 = chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.WORLD_SURFACE_WG); +- ChunkPos pos = chunk.getPos(); +- int minBlockX = pos.getMinBlockX(); +- int minBlockZ = pos.getMinBlockZ(); +- Aquifer aquifer = noiseChunk.aquifer(); +- noiseChunk.initializeForFirstCellX(); +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); +- int i = noiseChunk.cellWidth(); +- int i1 = noiseChunk.cellHeight(); +- int i2 = 16 / i; +- int i3 = 16 / i; ++ NoiseChunk noisechunk = chunk.getOrCreateNoiseChunk((ichunkaccess1) -> { ++ return this.createNoiseChunk(ichunkaccess1, structureManager, blender, random); ++ }); ++ Heightmap heightmap = chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.OCEAN_FLOOR_WG); ++ Heightmap heightmap1 = chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.WORLD_SURFACE_WG); ++ ChunkPos chunkcoordintpair = chunk.getPos(); ++ int k = chunkcoordintpair.getMinBlockX(); ++ int l = chunkcoordintpair.getMinBlockZ(); ++ Aquifer aquifer = noisechunk.aquifer(); + +- for (int i4 = 0; i4 < i2; i4++) { +- noiseChunk.advanceCellX(i4); ++ noisechunk.initializeForFirstCellX(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ int i1 = noisechunk.cellWidth(); ++ int j1 = noisechunk.cellHeight(); ++ int k1 = 16 / i1; ++ int l1 = 16 / i1; + +- for (int i5 = 0; i5 < i3; i5++) { +- int i6 = chunk.getSectionsCount() - 1; +- LevelChunkSection section = chunk.getSection(i6); ++ for (int i2 = 0; i2 < k1; ++i2) { ++ noisechunk.advanceCellX(i2); + +- for (int i7 = cellCountY - 1; i7 >= 0; i7--) { +- noiseChunk.selectCellYZ(i7, i5); ++ for (int j2 = 0; j2 < l1; ++j2) { ++ int k2 = chunk.getSectionsCount() - 1; ++ LevelChunkSection chunksection = chunk.getSection(k2); + +- for (int i8 = i1 - 1; i8 >= 0; i8--) { +- int i9 = (minCellY + i7) * i1 + i8; +- int i10 = i9 & 15; +- int sectionIndex = chunk.getSectionIndex(i9); +- if (i6 != sectionIndex) { +- i6 = sectionIndex; +- section = chunk.getSection(sectionIndex); ++ for (int l2 = cellCountY - 1; l2 >= 0; --l2) { ++ noisechunk.selectCellYZ(l2, j2); ++ ++ for (int i3 = j1 - 1; i3 >= 0; --i3) { ++ int j3 = (minCellY + l2) * j1 + i3; ++ int k3 = j3 & 15; ++ int l3 = chunk.getSectionIndex(j3); ++ ++ if (k2 != l3) { ++ k2 = l3; ++ chunksection = chunk.getSection(l3); + } + +- double d = (double)i8 / (double)i1; +- noiseChunk.updateForY(i9, d); ++ double d0 = (double) i3 / (double) j1; + +- for (int i11 = 0; i11 < i; i11++) { +- int i12 = minBlockX + i4 * i + i11; +- int i13 = i12 & 15; +- double d1 = (double)i11 / (double)i; +- noiseChunk.updateForX(i12, d1); ++ noisechunk.updateForY(j3, d0); + +- for (int i14 = 0; i14 < i; i14++) { +- int i15 = minBlockZ + i5 * i + i14; +- int i16 = i15 & 15; +- double d2 = (double)i14 / (double)i; +- noiseChunk.updateForZ(i15, d2); +- BlockState interpolatedState = noiseChunk.getInterpolatedState(); +- if (interpolatedState == null) { +- interpolatedState = this.settings.value().defaultBlock(); ++ for (int i4 = 0; i4 < i1; ++i4) { ++ int j4 = k + i2 * i1 + i4; ++ int k4 = j4 & 15; ++ double d1 = (double) i4 / (double) i1; ++ ++ noisechunk.updateForX(j4, d1); ++ ++ for (int l4 = 0; l4 < i1; ++l4) { ++ int i5 = l + j2 * i1 + l4; ++ int j5 = i5 & 15; ++ double d2 = (double) l4 / (double) i1; ++ ++ noisechunk.updateForZ(i5, d2); ++ IBlockData iblockdata = noisechunk.getInterpolatedState(); ++ ++ if (iblockdata == null) { ++ iblockdata = ((NoiseGeneratorSettings) this.settings.value()).defaultBlock(); + } + +- BlockState var41 = this.debugPreliminarySurfaceLevel(noiseChunk, i12, i9, i15, interpolatedState); +- if (var41 != AIR && !SharedConstants.debugVoidTerrain(chunk.getPos())) { +- section.setBlockState(i13, i10, i16, var41, false); +- heightmapUnprimed.update(i13, i9, i16, var41); +- heightmapUnprimed1.update(i13, i9, i16, var41); +- if (aquifer.shouldScheduleFluidUpdate() && !var41.getFluidState().isEmpty()) { +- mutableBlockPos.set(i12, i9, i15); +- chunk.markPosForPostprocessing(mutableBlockPos); ++ iblockdata = this.debugPreliminarySurfaceLevel(noisechunk, j4, j3, i5, iblockdata); ++ if (iblockdata != NoiseBasedChunkGenerator.AIR && !SharedConstants.debugVoidTerrain(chunk.getPos())) { ++ chunksection.setBlockState(k4, k3, j5, iblockdata, false); ++ heightmap.update(k4, j3, j5, iblockdata); ++ heightmap1.update(k4, j3, j5, iblockdata); ++ if (aquifer.shouldScheduleFluidUpdate() && !iblockdata.getFluidState().isEmpty()) { ++ blockposition_mutableblockposition.set(j4, j3, i5); ++ chunk.markPosForPostprocessing(blockposition_mutableblockposition); + } + } + } +@@ -402,40 +376,41 @@ + } + } + +- noiseChunk.swapSlices(); ++ noisechunk.swapSlices(); + } + +- noiseChunk.stopInterpolation(); ++ noisechunk.stopInterpolation(); + return chunk; + } + +- private BlockState debugPreliminarySurfaceLevel(NoiseChunk chunk, int x, int y, int z, BlockState state) { ++ private IBlockData debugPreliminarySurfaceLevel(NoiseChunk chunk, int x, int y, int z, IBlockData state) { + return state; + } + + @Override + public int getGenDepth() { +- return this.settings.value().noiseSettings().height(); ++ return ((NoiseGeneratorSettings) this.settings.value()).noiseSettings().height(); + } + + @Override + public int getSeaLevel() { +- return this.settings.value().seaLevel(); ++ return ((NoiseGeneratorSettings) this.settings.value()).seaLevel(); + } + + @Override + public int getMinY() { +- return this.settings.value().noiseSettings().minY(); ++ return ((NoiseGeneratorSettings) this.settings.value()).noiseSettings().minY(); + } + + @Override + public void spawnOriginalMobs(WorldGenRegion level) { +- if (!this.settings.value().disableMobGeneration()) { +- ChunkPos center = level.getCenter(); +- Holder biome = level.getBiome(center.getWorldPosition().atY(level.getMaxBuildHeight() - 1)); +- WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(RandomSupport.generateUniqueSeed())); +- worldgenRandom.setDecorationSeed(level.getSeed(), center.getMinBlockX(), center.getMinBlockZ()); +- NaturalSpawner.spawnMobsForChunkGeneration(level, biome, center, worldgenRandom); ++ if (!((NoiseGeneratorSettings) this.settings.value()).disableMobGeneration()) { ++ ChunkPos chunkcoordintpair = level.getCenter(); ++ Holder holder = level.getBiome(chunkcoordintpair.getWorldPosition().atY(level.getMaxBuildHeight() - 1)); ++ WorldgenRandom seededrandom = new WorldgenRandom(new LegacyRandomSource(RandomSupport.generateUniqueSeed())); ++ ++ seededrandom.setDecorationSeed(level.getSeed(), chunkcoordintpair.getMinBlockX(), chunkcoordintpair.getMinBlockZ()); ++ NaturalSpawner.spawnMobsForChunkGeneration(level, holder, chunkcoordintpair, seededrandom); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/PatrolSpawner.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/PatrolSpawner.java.patch new file mode 100644 index 0000000000..d68ddd74f3 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/PatrolSpawner.java.patch @@ -0,0 +1,175 @@ +--- a/net/minecraft/world/level/levelgen/PatrolSpawner.java ++++ b/net/minecraft/world/level/levelgen/PatrolSpawner.java +@@ -2,22 +2,27 @@ + + import net.minecraft.core.BlockPos; + import net.minecraft.core.Holder; ++import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.tags.BiomeTags; + import net.minecraft.util.RandomSource; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.monster.PatrollingMonster; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.CustomSpawner; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.NaturalSpawner; + import net.minecraft.world.level.biome.Biome; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public class PatrolSpawner implements CustomSpawner { ++ + private int nextTick; + ++ public PatrolSpawner() {} ++ + @Override + public int tick(ServerLevel level, boolean spawnEnemies, boolean spawnFriendlies) { + if (!spawnEnemies) { +@@ -25,86 +30,94 @@ + } else if (!level.getGameRules().getBoolean(GameRules.RULE_DO_PATROL_SPAWNING)) { + return 0; + } else { +- RandomSource randomSource = level.random; +- this.nextTick--; ++ RandomSource randomsource = level.random; ++ ++ --this.nextTick; + if (this.nextTick > 0) { + return 0; + } else { +- this.nextTick = this.nextTick + 12000 + randomSource.nextInt(1200); +- long l = level.getDayTime() / 24000L; +- if (l < 5L || !level.isDay()) { +- return 0; +- } else if (randomSource.nextInt(5) != 0) { +- return 0; +- } else { +- int size = level.players().size(); +- if (size < 1) { ++ this.nextTick += 12000 + randomsource.nextInt(1200); ++ long i = level.getDayTime() / 24000L; ++ ++ if (i >= 5L && level.isDay()) { ++ if (randomsource.nextInt(5) != 0) { + return 0; + } else { +- Player player = level.players().get(randomSource.nextInt(size)); +- if (player.isSpectator()) { ++ int j = level.players().size(); ++ ++ if (j < 1) { + return 0; +- } else if (level.isCloseToVillage(player.blockPosition(), 2)) { +- return 0; + } else { +- int i = (24 + randomSource.nextInt(24)) * (randomSource.nextBoolean() ? -1 : 1); +- int i1 = (24 + randomSource.nextInt(24)) * (randomSource.nextBoolean() ? -1 : 1); +- BlockPos.MutableBlockPos mutableBlockPos = player.blockPosition().mutable().move(i, 0, i1); +- int i2 = 10; +- if (!level.hasChunksAt( +- mutableBlockPos.getX() - 10, mutableBlockPos.getZ() - 10, mutableBlockPos.getX() + 10, mutableBlockPos.getZ() + 10 +- )) { ++ Player entityhuman = (Player) level.players().get(randomsource.nextInt(j)); ++ ++ if (entityhuman.isSpectator()) { + return 0; ++ } else if (level.isCloseToVillage(entityhuman.blockPosition(), 2)) { ++ return 0; + } else { +- Holder biome = level.getBiome(mutableBlockPos); +- if (biome.is(BiomeTags.WITHOUT_PATROL_SPAWNS)) { ++ int k = (24 + randomsource.nextInt(24)) * (randomsource.nextBoolean() ? -1 : 1); ++ int l = (24 + randomsource.nextInt(24)) * (randomsource.nextBoolean() ? -1 : 1); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = entityhuman.blockPosition().mutable().move(k, 0, l); ++ boolean flag2 = true; ++ ++ if (!level.hasChunksAt(blockposition_mutableblockposition.getX() - 10, blockposition_mutableblockposition.getZ() - 10, blockposition_mutableblockposition.getX() + 10, blockposition_mutableblockposition.getZ() + 10)) { + return 0; + } else { +- int i3 = 0; +- int i4 = (int)Math.ceil((double)level.getCurrentDifficultyAt(mutableBlockPos).getEffectiveDifficulty()) + 1; ++ Holder holder = level.getBiome(blockposition_mutableblockposition); + +- for (int i5 = 0; i5 < i4; i5++) { +- i3++; +- mutableBlockPos.setY(level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, mutableBlockPos).getY()); +- if (i5 == 0) { +- if (!this.spawnPatrolMember(level, mutableBlockPos, randomSource, true)) { +- break; ++ if (holder.is(BiomeTags.WITHOUT_PATROL_SPAWNS)) { ++ return 0; ++ } else { ++ int i1 = 0; ++ int j1 = (int) Math.ceil((double) level.getCurrentDifficultyAt(blockposition_mutableblockposition).getEffectiveDifficulty()) + 1; ++ ++ for (int k1 = 0; k1 < j1; ++k1) { ++ ++i1; ++ blockposition_mutableblockposition.setY(level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, blockposition_mutableblockposition).getY()); ++ if (k1 == 0) { ++ if (!this.spawnPatrolMember(level, blockposition_mutableblockposition, randomsource, true)) { ++ break; ++ } ++ } else { ++ this.spawnPatrolMember(level, blockposition_mutableblockposition, randomsource, false); + } +- } else { +- this.spawnPatrolMember(level, mutableBlockPos, randomSource, false); ++ ++ blockposition_mutableblockposition.setX(blockposition_mutableblockposition.getX() + randomsource.nextInt(5) - randomsource.nextInt(5)); ++ blockposition_mutableblockposition.setZ(blockposition_mutableblockposition.getZ() + randomsource.nextInt(5) - randomsource.nextInt(5)); + } + +- mutableBlockPos.setX(mutableBlockPos.getX() + randomSource.nextInt(5) - randomSource.nextInt(5)); +- mutableBlockPos.setZ(mutableBlockPos.getZ() + randomSource.nextInt(5) - randomSource.nextInt(5)); ++ return i1; + } +- +- return i3; + } + } + } + } ++ } else { ++ return 0; + } + } + } + } + + private boolean spawnPatrolMember(ServerLevel level, BlockPos pos, RandomSource random, boolean leader) { +- BlockState blockState = level.getBlockState(pos); +- if (!NaturalSpawner.isValidEmptySpawnBlock(level, pos, blockState, blockState.getFluidState(), EntityType.PILLAGER)) { ++ IBlockData iblockdata = level.getBlockState(pos); ++ ++ if (!NaturalSpawner.isValidEmptySpawnBlock(level, pos, iblockdata, iblockdata.getFluidState(), EntityType.PILLAGER)) { + return false; +- } else if (!PatrollingMonster.checkPatrollingMonsterSpawnRules(EntityType.PILLAGER, level, MobSpawnType.PATROL, pos, random)) { ++ } else if (!PatrollingMonster.checkPatrollingMonsterSpawnRules(EntityType.PILLAGER, level, EnumMobSpawn.PATROL, pos, random)) { + return false; + } else { +- PatrollingMonster patrollingMonster = EntityType.PILLAGER.create(level); +- if (patrollingMonster != null) { ++ PatrollingMonster entitymonsterpatrolling = (PatrollingMonster) EntityType.PILLAGER.create(level); ++ ++ if (entitymonsterpatrolling != null) { + if (leader) { +- patrollingMonster.setPatrolLeader(true); +- patrollingMonster.findPatrolTarget(); ++ entitymonsterpatrolling.setPatrolLeader(true); ++ entitymonsterpatrolling.findPatrolTarget(); + } + +- patrollingMonster.setPos((double)pos.getX(), (double)pos.getY(), (double)pos.getZ()); +- patrollingMonster.finalizeSpawn(level, level.getCurrentDifficultyAt(pos), MobSpawnType.PATROL, null, null); +- level.addFreshEntityWithPassengers(patrollingMonster); ++ entitymonsterpatrolling.setPos((double) pos.getX(), (double) pos.getY(), (double) pos.getZ()); ++ entitymonsterpatrolling.finalizeSpawn(level, level.getCurrentDifficultyAt(pos), EnumMobSpawn.PATROL, (GroupDataEntity) null, (CompoundTag) null); ++ level.addFreshEntityWithPassengers(entitymonsterpatrolling, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.PATROL); // CraftBukkit + return true; + } else { + return false; diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java.patch new file mode 100644 index 0000000000..db4fc75682 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java.patch @@ -0,0 +1,378 @@ +--- a/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java ++++ b/net/minecraft/world/level/levelgen/structure/LegacyStructureDataHandler.java +@@ -5,9 +5,8 @@ + import it.unimi.dsi.fastutil.longs.Long2ObjectMap; + import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; + import it.unimi.dsi.fastutil.longs.LongArrayList; +-import it.unimi.dsi.fastutil.longs.LongList; + import java.io.IOException; +-import java.util.HashMap; ++import java.util.Iterator; + import java.util.List; + import java.util.Locale; + import java.util.Map; +@@ -19,49 +18,31 @@ + import net.minecraft.resources.ResourceKey; + import net.minecraft.util.datafix.DataFixTypes; + import net.minecraft.world.level.ChunkPos; +-import net.minecraft.world.level.Level; ++import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.storage.DimensionDataStorage; + + public class LegacyStructureDataHandler { +- private static final Map CURRENT_TO_LEGACY_MAP = Util.make(Maps.newHashMap(), map -> { +- map.put("Village", "Village"); +- map.put("Mineshaft", "Mineshaft"); +- map.put("Mansion", "Mansion"); +- map.put("Igloo", "Temple"); +- map.put("Desert_Pyramid", "Temple"); +- map.put("Jungle_Pyramid", "Temple"); +- map.put("Swamp_Hut", "Temple"); +- map.put("Stronghold", "Stronghold"); +- map.put("Monument", "Monument"); +- map.put("Fortress", "Fortress"); +- map.put("EndCity", "EndCity"); ++ ++ private static final Map CURRENT_TO_LEGACY_MAP = (Map) Util.make(Maps.newHashMap(), (hashmap) -> { ++ hashmap.put("Village", "Village"); ++ hashmap.put("Mineshaft", "Mineshaft"); ++ hashmap.put("Mansion", "Mansion"); ++ hashmap.put("Igloo", "Temple"); ++ hashmap.put("Desert_Pyramid", "Temple"); ++ hashmap.put("Jungle_Pyramid", "Temple"); ++ hashmap.put("Swamp_Hut", "Temple"); ++ hashmap.put("Stronghold", "Stronghold"); ++ hashmap.put("Monument", "Monument"); ++ hashmap.put("Fortress", "Fortress"); ++ hashmap.put("EndCity", "EndCity"); + }); +- private static final Map LEGACY_TO_CURRENT_MAP = Util.make(Maps.newHashMap(), map -> { +- map.put("Iglu", "Igloo"); +- map.put("TeDP", "Desert_Pyramid"); +- map.put("TeJP", "Jungle_Pyramid"); +- map.put("TeSH", "Swamp_Hut"); ++ private static final Map LEGACY_TO_CURRENT_MAP = (Map) Util.make(Maps.newHashMap(), (hashmap) -> { ++ hashmap.put("Iglu", "Igloo"); ++ hashmap.put("TeDP", "Desert_Pyramid"); ++ hashmap.put("TeJP", "Jungle_Pyramid"); ++ hashmap.put("TeSH", "Swamp_Hut"); + }); +- private static final Set OLD_STRUCTURE_REGISTRY_KEYS = Set.of( +- "pillager_outpost", +- "mineshaft", +- "mansion", +- "jungle_pyramid", +- "desert_pyramid", +- "igloo", +- "ruined_portal", +- "shipwreck", +- "swamp_hut", +- "stronghold", +- "monument", +- "ocean_ruin", +- "fortress", +- "endcity", +- "buried_treasure", +- "village", +- "nether_fossil", +- "bastion_remnant" +- ); ++ private static final Set OLD_STRUCTURE_REGISTRY_KEYS = Set.of("pillager_outpost", "mineshaft", "mansion", "jungle_pyramid", "desert_pyramid", "igloo", "ruined_portal", "shipwreck", "swamp_hut", "stronghold", "monument", "ocean_ruin", "fortress", "endcity", "buried_treasure", "village", "nether_fossil", "bastion_remnant"); + private final boolean hasLegacyData; + private final Map> dataMap = Maps.newHashMap(); + private final Map indexMap = Maps.newHashMap(); +@@ -74,168 +55,202 @@ + this.populateCaches(storage); + boolean flag = false; + +- for (String string : this.currentKeys) { +- flag |= this.dataMap.get(string) != null; ++ String s; ++ ++ for (Iterator iterator = this.currentKeys.iterator(); iterator.hasNext(); flag |= this.dataMap.get(s) != null) { ++ s = (String) iterator.next(); + } + + this.hasLegacyData = flag; + } + + public void removeIndex(long packedChunkPos) { +- for (String string : this.legacyKeys) { +- StructureFeatureIndexSavedData structureFeatureIndexSavedData = this.indexMap.get(string); +- if (structureFeatureIndexSavedData != null && structureFeatureIndexSavedData.hasUnhandledIndex(packedChunkPos)) { +- structureFeatureIndexSavedData.removeIndex(packedChunkPos); +- structureFeatureIndexSavedData.setDirty(); ++ Iterator iterator = this.legacyKeys.iterator(); ++ ++ while (iterator.hasNext()) { ++ String s = (String) iterator.next(); ++ StructureFeatureIndexSavedData persistentindexed = (StructureFeatureIndexSavedData) this.indexMap.get(s); ++ ++ if (persistentindexed != null && persistentindexed.hasUnhandledIndex(packedChunkPos)) { ++ persistentindexed.removeIndex(packedChunkPos); ++ persistentindexed.setDirty(); + } + } ++ + } + + public CompoundTag updateFromLegacy(CompoundTag tag) { +- CompoundTag compound = tag.getCompound("Level"); +- ChunkPos chunkPos = new ChunkPos(compound.getInt("xPos"), compound.getInt("zPos")); +- if (this.isUnhandledStructureStart(chunkPos.x, chunkPos.z)) { +- tag = this.updateStructureStart(tag, chunkPos); ++ CompoundTag nbttagcompound1 = tag.getCompound("Level"); ++ ChunkPos chunkcoordintpair = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); ++ ++ if (this.isUnhandledStructureStart(chunkcoordintpair.x, chunkcoordintpair.z)) { ++ tag = this.updateStructureStart(tag, chunkcoordintpair); + } + +- CompoundTag compound1 = compound.getCompound("Structures"); +- CompoundTag compound2 = compound1.getCompound("References"); ++ CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("Structures"); ++ CompoundTag nbttagcompound3 = nbttagcompound2.getCompound("References"); ++ Iterator iterator = this.currentKeys.iterator(); + +- for (String string : this.currentKeys) { +- boolean flag = OLD_STRUCTURE_REGISTRY_KEYS.contains(string.toLowerCase(Locale.ROOT)); +- if (!compound2.contains(string, 12) && flag) { +- int i = 8; +- LongList list = new LongArrayList(); ++ while (iterator.hasNext()) { ++ String s = (String) iterator.next(); ++ boolean flag = LegacyStructureDataHandler.OLD_STRUCTURE_REGISTRY_KEYS.contains(s.toLowerCase(Locale.ROOT)); + +- for (int i1 = chunkPos.x - 8; i1 <= chunkPos.x + 8; i1++) { +- for (int i2 = chunkPos.z - 8; i2 <= chunkPos.z + 8; i2++) { +- if (this.hasLegacyStart(i1, i2, string)) { +- list.add(ChunkPos.asLong(i1, i2)); ++ if (!nbttagcompound3.contains(s, 12) && flag) { ++ boolean flag1 = true; ++ LongArrayList longarraylist = new LongArrayList(); ++ ++ for (int i = chunkcoordintpair.x - 8; i <= chunkcoordintpair.x + 8; ++i) { ++ for (int j = chunkcoordintpair.z - 8; j <= chunkcoordintpair.z + 8; ++j) { ++ if (this.hasLegacyStart(i, j, s)) { ++ longarraylist.add(ChunkPos.asLong(i, j)); + } + } + } + +- compound2.putLongArray(string, list); ++ nbttagcompound3.putLongArray(s, (List) longarraylist); + } + } + +- compound1.put("References", compound2); +- compound.put("Structures", compound1); +- tag.put("Level", compound); ++ nbttagcompound2.put("References", nbttagcompound3); ++ nbttagcompound1.put("Structures", nbttagcompound2); ++ tag.put("Level", nbttagcompound1); + return tag; + } + + private boolean hasLegacyStart(int chunkX, int chunkZ, String key) { +- return this.hasLegacyData +- && this.dataMap.get(key) != null +- && this.indexMap.get(CURRENT_TO_LEGACY_MAP.get(key)).hasStartIndex(ChunkPos.asLong(chunkX, chunkZ)); ++ return !this.hasLegacyData ? false : this.dataMap.get(key) != null && ((StructureFeatureIndexSavedData) this.indexMap.get(LegacyStructureDataHandler.CURRENT_TO_LEGACY_MAP.get(key))).hasStartIndex(ChunkPos.asLong(chunkX, chunkZ)); + } + + private boolean isUnhandledStructureStart(int chunkX, int chunkZ) { + if (!this.hasLegacyData) { + return false; + } else { +- for (String string : this.currentKeys) { +- if (this.dataMap.get(string) != null && this.indexMap.get(CURRENT_TO_LEGACY_MAP.get(string)).hasUnhandledIndex(ChunkPos.asLong(chunkX, chunkZ)) +- ) +- { +- return true; ++ Iterator iterator = this.currentKeys.iterator(); ++ ++ String s; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return false; + } +- } + +- return false; ++ s = (String) iterator.next(); ++ } while (this.dataMap.get(s) == null || !((StructureFeatureIndexSavedData) this.indexMap.get(LegacyStructureDataHandler.CURRENT_TO_LEGACY_MAP.get(s))).hasUnhandledIndex(ChunkPos.asLong(chunkX, chunkZ))); ++ ++ return true; + } + } + + private CompoundTag updateStructureStart(CompoundTag tag, ChunkPos chunkPos) { +- CompoundTag compound = tag.getCompound("Level"); +- CompoundTag compound1 = compound.getCompound("Structures"); +- CompoundTag compound2 = compound1.getCompound("Starts"); ++ CompoundTag nbttagcompound1 = tag.getCompound("Level"); ++ CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("Structures"); ++ CompoundTag nbttagcompound3 = nbttagcompound2.getCompound("Starts"); ++ Iterator iterator = this.currentKeys.iterator(); + +- for (String string : this.currentKeys) { +- Long2ObjectMap map = this.dataMap.get(string); +- if (map != null) { +- long l = chunkPos.toLong(); +- if (this.indexMap.get(CURRENT_TO_LEGACY_MAP.get(string)).hasUnhandledIndex(l)) { +- CompoundTag compoundTag = map.get(l); +- if (compoundTag != null) { +- compound2.put(string, compoundTag); ++ while (iterator.hasNext()) { ++ String s = (String) iterator.next(); ++ Long2ObjectMap long2objectmap = (Long2ObjectMap) this.dataMap.get(s); ++ ++ if (long2objectmap != null) { ++ long i = chunkPos.toLong(); ++ ++ if (((StructureFeatureIndexSavedData) this.indexMap.get(LegacyStructureDataHandler.CURRENT_TO_LEGACY_MAP.get(s))).hasUnhandledIndex(i)) { ++ CompoundTag nbttagcompound4 = (CompoundTag) long2objectmap.get(i); ++ ++ if (nbttagcompound4 != null) { ++ nbttagcompound3.put(s, nbttagcompound4); + } + } + } + } + +- compound1.put("Starts", compound2); +- compound.put("Structures", compound1); +- tag.put("Level", compound); ++ nbttagcompound2.put("Starts", nbttagcompound3); ++ nbttagcompound1.put("Structures", nbttagcompound2); ++ tag.put("Level", nbttagcompound1); + return tag; + } + + private void populateCaches(@Nullable DimensionDataStorage storage) { + if (storage != null) { +- for (String string : this.legacyKeys) { +- CompoundTag compoundTag = new CompoundTag(); ++ Iterator iterator = this.legacyKeys.iterator(); + ++ while (iterator.hasNext()) { ++ String s = (String) iterator.next(); ++ CompoundTag nbttagcompound = new CompoundTag(); ++ + try { +- compoundTag = storage.readTagFromDisk(string, DataFixTypes.SAVED_DATA_STRUCTURE_FEATURE_INDICES, 1493) +- .getCompound("data") +- .getCompound("Features"); +- if (compoundTag.isEmpty()) { ++ nbttagcompound = storage.readTagFromDisk(s, DataFixTypes.SAVED_DATA_STRUCTURE_FEATURE_INDICES, 1493).getCompound("data").getCompound("Features"); ++ if (nbttagcompound.isEmpty()) { + continue; + } +- } catch (IOException var13) { ++ } catch (IOException ioexception) { ++ ; + } + +- for (String string1 : compoundTag.getAllKeys()) { +- CompoundTag compound = compoundTag.getCompound(string1); +- long _long = ChunkPos.asLong(compound.getInt("ChunkX"), compound.getInt("ChunkZ")); +- ListTag list = compound.getList("Children", 10); +- if (!list.isEmpty()) { +- String string2 = list.getCompound(0).getString("id"); +- String string3 = LEGACY_TO_CURRENT_MAP.get(string2); +- if (string3 != null) { +- compound.putString("id", string3); ++ Iterator iterator1 = nbttagcompound.getAllKeys().iterator(); ++ ++ while (iterator1.hasNext()) { ++ String s1 = (String) iterator1.next(); ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound(s1); ++ long i = ChunkPos.asLong(nbttagcompound1.getInt("ChunkX"), nbttagcompound1.getInt("ChunkZ")); ++ ListTag nbttaglist = nbttagcompound1.getList("Children", 10); ++ String s2; ++ ++ if (!nbttaglist.isEmpty()) { ++ s2 = nbttaglist.getCompound(0).getString("id"); ++ String s3 = (String) LegacyStructureDataHandler.LEGACY_TO_CURRENT_MAP.get(s2); ++ ++ if (s3 != null) { ++ nbttagcompound1.putString("id", s3); + } + } + +- String string2 = compound.getString("id"); +- this.dataMap.computeIfAbsent(string2, string6 -> new Long2ObjectOpenHashMap<>()).put(_long, compound); ++ s2 = nbttagcompound1.getString("id"); ++ ((Long2ObjectMap) this.dataMap.computeIfAbsent(s2, (s4) -> { ++ return new Long2ObjectOpenHashMap(); ++ })).put(i, nbttagcompound1); + } + +- String string4 = string + "_index"; +- StructureFeatureIndexSavedData structureFeatureIndexSavedData = storage.computeIfAbsent(StructureFeatureIndexSavedData.factory(), string4); +- if (!structureFeatureIndexSavedData.getAll().isEmpty()) { +- this.indexMap.put(string, structureFeatureIndexSavedData); ++ String s4 = s + "_index"; ++ StructureFeatureIndexSavedData persistentindexed = (StructureFeatureIndexSavedData) storage.computeIfAbsent(StructureFeatureIndexSavedData.factory(), s4); ++ ++ if (!persistentindexed.getAll().isEmpty()) { ++ this.indexMap.put(s, persistentindexed); + } else { +- StructureFeatureIndexSavedData structureFeatureIndexSavedData1 = new StructureFeatureIndexSavedData(); +- this.indexMap.put(string, structureFeatureIndexSavedData1); ++ StructureFeatureIndexSavedData persistentindexed1 = new StructureFeatureIndexSavedData(); + +- for (String string5 : compoundTag.getAllKeys()) { +- CompoundTag compound1 = compoundTag.getCompound(string5); +- structureFeatureIndexSavedData1.addIndex(ChunkPos.asLong(compound1.getInt("ChunkX"), compound1.getInt("ChunkZ"))); ++ this.indexMap.put(s, persistentindexed1); ++ Iterator iterator2 = nbttagcompound.getAllKeys().iterator(); ++ ++ while (iterator2.hasNext()) { ++ String s5 = (String) iterator2.next(); ++ CompoundTag nbttagcompound2 = nbttagcompound.getCompound(s5); ++ ++ persistentindexed1.addIndex(ChunkPos.asLong(nbttagcompound2.getInt("ChunkX"), nbttagcompound2.getInt("ChunkZ"))); + } + +- structureFeatureIndexSavedData1.setDirty(); ++ persistentindexed1.setDirty(); + } + } ++ + } + } + +- public static LegacyStructureDataHandler getLegacyStructureHandler(ResourceKey level, @Nullable DimensionDataStorage storage) { +- if (level == Level.OVERWORLD) { +- return new LegacyStructureDataHandler( +- storage, +- ImmutableList.of("Monument", "Stronghold", "Village", "Mineshaft", "Temple", "Mansion"), +- ImmutableList.of("Village", "Mineshaft", "Mansion", "Igloo", "Desert_Pyramid", "Jungle_Pyramid", "Swamp_Hut", "Stronghold", "Monument") +- ); +- } else if (level == Level.NETHER) { +- List list = ImmutableList.of("Fortress"); +- return new LegacyStructureDataHandler(storage, list, list); +- } else if (level == Level.END) { +- List list = ImmutableList.of("EndCity"); +- return new LegacyStructureDataHandler(storage, list, list); ++ public static LegacyStructureDataHandler getLegacyStructureHandler(ResourceKey level, @Nullable DimensionDataStorage storage) { // CraftBukkit ++ if (level == LevelStem.OVERWORLD) { // CraftBukkit ++ return new LegacyStructureDataHandler(storage, ImmutableList.of("Monument", "Stronghold", "Village", "Mineshaft", "Temple", "Mansion"), ImmutableList.of("Village", "Mineshaft", "Mansion", "Igloo", "Desert_Pyramid", "Jungle_Pyramid", "Swamp_Hut", "Stronghold", "Monument")); + } else { +- throw new RuntimeException(String.format(Locale.ROOT, "Unknown dimension type : %s", level)); ++ ImmutableList immutablelist; ++ ++ if (level == LevelStem.NETHER) { // CraftBukkit ++ immutablelist = ImmutableList.of("Fortress"); ++ return new LegacyStructureDataHandler(storage, immutablelist, immutablelist); ++ } else if (level == LevelStem.END) { // CraftBukkit ++ immutablelist = ImmutableList.of("EndCity"); ++ return new LegacyStructureDataHandler(storage, immutablelist, immutablelist); ++ } else { ++ throw new RuntimeException(String.format(Locale.ROOT, "Unknown dimension type : %s", level)); ++ } + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/StructurePiece.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/StructurePiece.java.patch new file mode 100644 index 0000000000..34e843ba92 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/StructurePiece.java.patch @@ -0,0 +1,717 @@ +--- a/net/minecraft/world/level/levelgen/structure/StructurePiece.java ++++ b/net/minecraft/world/level/levelgen/structure/StructurePiece.java +@@ -2,7 +2,10 @@ + + import com.google.common.collect.ImmutableSet; + import com.mojang.logging.LogUtils; ++import com.mojang.serialization.DataResult; ++import java.util.Iterator; + import java.util.List; ++import java.util.Objects; + import java.util.Set; + import java.util.stream.Stream; + import javax.annotation.Nullable; +@@ -11,7 +14,6 @@ + import net.minecraft.core.registries.BuiltInRegistries; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtOps; +-import net.minecraft.nbt.Tag; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.util.RandomSource; + import net.minecraft.world.level.BlockGetter; +@@ -27,9 +29,7 @@ + import net.minecraft.world.level.block.Mirror; + import net.minecraft.world.level.block.Rotation; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.entity.ChestBlockEntity; +-import net.minecraft.world.level.block.entity.DispenserBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.levelgen.Heightmap; + import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; +@@ -38,8 +38,9 @@ + import org.slf4j.Logger; + + public abstract class StructurePiece { ++ + private static final Logger LOGGER = LogUtils.getLogger(); +- protected static final BlockState CAVE_AIR = Blocks.CAVE_AIR.defaultBlockState(); ++ protected static final IBlockData CAVE_AIR = Blocks.CAVE_AIR.defaultBlockState(); + protected BoundingBox boundingBox; + @Nullable + private Direction orientation; +@@ -47,19 +48,7 @@ + private Rotation rotation; + protected int genDepth; + private final StructurePieceType type; +- private static final Set SHAPE_CHECK_BLOCKS = ImmutableSet.builder() +- .add(Blocks.NETHER_BRICK_FENCE) +- .add(Blocks.TORCH) +- .add(Blocks.WALL_TORCH) +- .add(Blocks.OAK_FENCE) +- .add(Blocks.SPRUCE_FENCE) +- .add(Blocks.DARK_OAK_FENCE) +- .add(Blocks.ACACIA_FENCE) +- .add(Blocks.BIRCH_FENCE) +- .add(Blocks.JUNGLE_FENCE) +- .add(Blocks.LADDER) +- .add(Blocks.IRON_BARS) +- .build(); ++ public static final Set SHAPE_CHECK_BLOCKS = ImmutableSet.builder().add(Blocks.NETHER_BRICK_FENCE).add(Blocks.TORCH).add(Blocks.WALL_TORCH).add(Blocks.OAK_FENCE).add(Blocks.SPRUCE_FENCE).add(Blocks.DARK_OAK_FENCE).add(Blocks.ACACIA_FENCE).add(Blocks.BIRCH_FENCE).add(Blocks.JUNGLE_FENCE).add(Blocks.LADDER).add(Blocks.IRON_BARS).build(); // CraftBukkit - decompile error / PAIL private -> public + + protected StructurePiece(StructurePieceType type, int genDepth, BoundingBox boundingBox) { + this.type = type; +@@ -68,22 +57,18 @@ + } + + public StructurePiece(StructurePieceType type, CompoundTag tag) { +- this( +- type, +- tag.getInt("GD"), +- BoundingBox.CODEC +- .parse(NbtOps.INSTANCE, tag.get("BB")) +- .resultOrPartial(LOGGER::error) +- .orElseThrow(() -> new IllegalArgumentException("Invalid boundingbox")) +- ); +- int _int = tag.getInt("O"); +- this.setOrientation(_int == -1 ? null : Direction.from2DDataValue(_int)); ++ // CraftBukkit start - decompile error ++ this(type, tag.getInt("GD"), (BoundingBox) BoundingBox.CODEC.parse(NbtOps.INSTANCE, tag.get("BB")).resultOrPartial(Objects.requireNonNull(StructurePiece.LOGGER)::error).orElseThrow(() -> { ++ return new IllegalArgumentException("Invalid boundingbox"); ++ })); ++ // CraftBukkit end ++ int j = tag.getInt("O"); ++ ++ this.setOrientation(j == -1 ? null : Direction.from2DDataValue(j)); + } + + protected static BoundingBox makeBoundingBox(int x, int y, int z, Direction direction, int offsetX, int offsetY, int offsetZ) { +- return direction.getAxis() == Direction.Axis.Z +- ? new BoundingBox(x, y, z, x + offsetX - 1, y + offsetY - 1, z + offsetZ - 1) +- : new BoundingBox(x, y, z, x + offsetZ - 1, y + offsetY - 1, z + offsetX - 1); ++ return direction.getAxis() == Direction.Axis.Z ? new BoundingBox(x, y, z, x + offsetX - 1, y + offsetY - 1, z + offsetZ - 1) : new BoundingBox(x, y, z, x + offsetZ - 1, y + offsetY - 1, z + offsetX - 1); + } + + protected static Direction getRandomHorizontalDirection(RandomSource random) { +@@ -91,24 +76,27 @@ + } + + public final CompoundTag createTag(StructurePieceSerializationContext context) { +- CompoundTag compoundTag = new CompoundTag(); +- compoundTag.putString("id", BuiltInRegistries.STRUCTURE_PIECE.getKey(this.getType()).toString()); +- BoundingBox.CODEC.encodeStart(NbtOps.INSTANCE, this.boundingBox).resultOrPartial(LOGGER::error).ifPresent(tag -> compoundTag.put("BB", tag)); +- Direction orientation = this.getOrientation(); +- compoundTag.putInt("O", orientation == null ? -1 : orientation.get2DDataValue()); +- compoundTag.putInt("GD", this.genDepth); +- this.addAdditionalSaveData(context, compoundTag); +- return compoundTag; ++ CompoundTag nbttagcompound = new CompoundTag(); ++ ++ nbttagcompound.putString("id", BuiltInRegistries.STRUCTURE_PIECE.getKey(this.getType()).toString()); ++ // CraftBukkit start - decompile error ++ BoundingBox.CODEC.encodeStart(NbtOps.INSTANCE, this.boundingBox).resultOrPartial(Objects.requireNonNull(StructurePiece.LOGGER)::error).ifPresent((nbtbase) -> { ++ nbttagcompound.put("BB", nbtbase); ++ }); ++ // CraftBukkit end ++ Direction enumdirection = this.getOrientation(); ++ ++ nbttagcompound.putInt("O", enumdirection == null ? -1 : enumdirection.get2DDataValue()); ++ nbttagcompound.putInt("GD", this.genDepth); ++ this.addAdditionalSaveData(context, nbttagcompound); ++ return nbttagcompound; + } + + protected abstract void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag); + +- public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- } ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) {} + +- public abstract void postProcess( +- WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos +- ); ++ public abstract void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos); + + public BoundingBox getBoundingBox() { + return this.boundingBox; +@@ -123,9 +111,10 @@ + } + + public boolean isCloseToChunk(ChunkPos chunkPos, int distance) { +- int minBlockX = chunkPos.getMinBlockX(); +- int minBlockZ = chunkPos.getMinBlockZ(); +- return this.boundingBox.intersects(minBlockX - distance, minBlockZ - distance, minBlockX + 15 + distance, minBlockZ + 15 + distance); ++ int j = chunkPos.getMinBlockX(); ++ int k = chunkPos.getMinBlockZ(); ++ ++ return this.boundingBox.intersects(j - distance, k - distance, j + 15 + distance, k + 15 + distance); + } + + public BlockPos getLocatorPosition() { +@@ -137,11 +126,12 @@ + } + + protected int getWorldX(int x, int z) { +- Direction orientation = this.getOrientation(); +- if (orientation == null) { ++ Direction enumdirection = this.getOrientation(); ++ ++ if (enumdirection == null) { + return x; + } else { +- switch (orientation) { ++ switch (enumdirection) { + case NORTH: + case SOUTH: + return this.boundingBox.minX() + x; +@@ -160,11 +150,12 @@ + } + + protected int getWorldZ(int x, int z) { +- Direction orientation = this.getOrientation(); +- if (orientation == null) { ++ Direction enumdirection = this.getOrientation(); ++ ++ if (enumdirection == null) { + return z; + } else { +- switch (orientation) { ++ switch (enumdirection) { + case NORTH: + return this.boundingBox.maxZ() - z; + case SOUTH: +@@ -178,9 +169,10 @@ + } + } + +- protected void placeBlock(WorldGenLevel level, BlockState blockstate, int x, int y, int z, BoundingBox boundingbox) { +- BlockPos worldPos = this.getWorldPos(x, y, z); +- if (boundingbox.isInside(worldPos)) { ++ protected void placeBlock(WorldGenLevel level, IBlockData blockstate, int x, int y, int z, BoundingBox boundingbox) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y, z); ++ ++ if (boundingbox.isInside(blockposition_mutableblockposition)) { + if (this.canBeReplaced(level, x, y, z, boundingbox)) { + if (this.mirror != Mirror.NONE) { + blockstate = blockstate.mirror(this.mirror); +@@ -190,252 +182,265 @@ + blockstate = blockstate.rotate(this.rotation); + } + +- level.setBlock(worldPos, blockstate, 2); +- FluidState fluidState = level.getFluidState(worldPos); +- if (!fluidState.isEmpty()) { +- level.scheduleTick(worldPos, fluidState.getType(), 0); ++ level.setBlock(blockposition_mutableblockposition, blockstate, 2); ++ // CraftBukkit start - fluid handling is already done if we have a transformer generator access ++ if (level instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess) { ++ return; + } ++ // CraftBukkit end ++ FluidState fluid = level.getFluidState(blockposition_mutableblockposition); + +- if (SHAPE_CHECK_BLOCKS.contains(blockstate.getBlock())) { +- level.getChunk(worldPos).markPosForPostprocessing(worldPos); ++ if (!fluid.isEmpty()) { ++ level.scheduleTick(blockposition_mutableblockposition, fluid.getType(), 0); + } ++ ++ if (StructurePiece.SHAPE_CHECK_BLOCKS.contains(blockstate.getBlock())) { ++ level.getChunk(blockposition_mutableblockposition).markPosForPostprocessing(blockposition_mutableblockposition); ++ } ++ + } + } + } + ++ // CraftBukkit start ++ protected boolean placeCraftBlockEntity(ServerLevelAccessor worldAccess, BlockPos position, org.bukkit.craftbukkit.block.CraftBlockEntityState craftBlockEntityState, int i) { ++ if (worldAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ return transformerAccess.setCraftBlock(position, craftBlockEntityState, i); ++ } ++ boolean result = worldAccess.setBlock(position, craftBlockEntityState.getHandle(), i); ++ BlockEntity tileEntity = worldAccess.getBlockEntity(position); ++ if (tileEntity != null) { ++ tileEntity.load(craftBlockEntityState.getSnapshotNBT()); ++ } ++ return result; ++ } ++ ++ protected void placeCraftSpawner(ServerLevelAccessor worldAccess, BlockPos position, org.bukkit.entity.EntityType entityType, int i) { ++ // This method is used in structures that are generated by code and place spawners as they set the entity after the block was placed making it impossible for plugins to access that information ++ org.bukkit.craftbukkit.block.CraftCreatureSpawner spawner = (org.bukkit.craftbukkit.block.CraftCreatureSpawner) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(position, Blocks.SPAWNER.defaultBlockState(), null); ++ spawner.setSpawnedType(entityType); ++ placeCraftBlockEntity(worldAccess, position, spawner, i); ++ } ++ ++ protected void setCraftLootTable(ServerLevelAccessor worldAccess, BlockPos position, RandomSource randomSource, net.minecraft.resources.ResourceLocation loottableKey) { ++ // This method is used in structures that use data markers to a loot table to loot containers as otherwise plugins won't have access to that information. ++ net.minecraft.world.level.block.entity.BlockEntity tileEntity = worldAccess.getBlockEntity(position); ++ if (tileEntity instanceof net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity tileEntityLootable) { ++ tileEntityLootable.setLootTable(loottableKey, randomSource.nextLong()); ++ if (worldAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ transformerAccess.setCraftBlock(position, (org.bukkit.craftbukkit.block.CraftBlockState) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(position, tileEntity.getBlockState(), tileEntityLootable.saveWithFullMetadata()), 3); ++ } ++ } ++ } ++ // CraftBukkit end ++ + protected boolean canBeReplaced(LevelReader level, int x, int y, int z, BoundingBox box) { + return true; + } + +- protected BlockState getBlock(BlockGetter level, int x, int y, int z, BoundingBox box) { +- BlockPos worldPos = this.getWorldPos(x, y, z); +- return !box.isInside(worldPos) ? Blocks.AIR.defaultBlockState() : level.getBlockState(worldPos); ++ protected IBlockData getBlock(BlockGetter level, int x, int y, int z, BoundingBox box) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y, z); ++ ++ return !box.isInside(blockposition_mutableblockposition) ? Blocks.AIR.defaultBlockState() : level.getBlockState(blockposition_mutableblockposition); + } + + protected boolean isInterior(LevelReader level, int x, int y, int z, BoundingBox box) { +- BlockPos worldPos = this.getWorldPos(x, y + 1, z); +- return box.isInside(worldPos) && worldPos.getY() < level.getHeight(Heightmap.Types.OCEAN_FLOOR_WG, worldPos.getX(), worldPos.getZ()); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y + 1, z); ++ ++ return !box.isInside(blockposition_mutableblockposition) ? false : blockposition_mutableblockposition.getY() < level.getHeight(Heightmap.Types.OCEAN_FLOOR_WG, blockposition_mutableblockposition.getX(), blockposition_mutableblockposition.getZ()); + } + + protected void generateAirBox(WorldGenLevel level, BoundingBox box, int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { +- for (int i = minY; i <= maxY; i++) { +- for (int i1 = minX; i1 <= maxX; i1++) { +- for (int i2 = minZ; i2 <= maxZ; i2++) { +- this.placeBlock(level, Blocks.AIR.defaultBlockState(), i1, i, i2, box); ++ for (int k1 = minY; k1 <= maxY; ++k1) { ++ for (int l1 = minX; l1 <= maxX; ++l1) { ++ for (int i2 = minZ; i2 <= maxZ; ++i2) { ++ this.placeBlock(level, Blocks.AIR.defaultBlockState(), l1, k1, i2, box); + } + } + } ++ + } + +- protected void generateBox( +- WorldGenLevel level, +- BoundingBox box, +- int xMin, +- int yMin, +- int zMin, +- int xMax, +- int yMax, +- int zMax, +- BlockState boundaryBlockState, +- BlockState insideBlockState, +- boolean existingOnly +- ) { +- for (int i = yMin; i <= yMax; i++) { +- for (int i1 = xMin; i1 <= xMax; i1++) { +- for (int i2 = zMin; i2 <= zMax; i2++) { +- if (!existingOnly || !this.getBlock(level, i1, i, i2, box).isAir()) { +- if (i != yMin && i != yMax && i1 != xMin && i1 != xMax && i2 != zMin && i2 != zMax) { +- this.placeBlock(level, insideBlockState, i1, i, i2, box); ++ protected void generateBox(WorldGenLevel level, BoundingBox box, int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, IBlockData boundaryBlockState, IBlockData insideBlockState, boolean existingOnly) { ++ for (int k1 = yMin; k1 <= yMax; ++k1) { ++ for (int l1 = xMin; l1 <= xMax; ++l1) { ++ for (int i2 = zMin; i2 <= zMax; ++i2) { ++ if (!existingOnly || !this.getBlock(level, l1, k1, i2, box).isAir()) { ++ if (k1 != yMin && k1 != yMax && l1 != xMin && l1 != xMax && i2 != zMin && i2 != zMax) { ++ this.placeBlock(level, insideBlockState, l1, k1, i2, box); + } else { +- this.placeBlock(level, boundaryBlockState, i1, i, i2, box); ++ this.placeBlock(level, boundaryBlockState, l1, k1, i2, box); + } + } + } + } + } ++ + } + +- protected void generateBox( +- WorldGenLevel level, BoundingBox boundingBox, BoundingBox box, BlockState boundaryBlockState, BlockState insideBlockState, boolean existingOnly +- ) { +- this.generateBox( +- level, boundingBox, box.minX(), box.minY(), box.minZ(), box.maxX(), box.maxY(), box.maxZ(), boundaryBlockState, insideBlockState, existingOnly +- ); ++ protected void generateBox(WorldGenLevel level, BoundingBox boundingBox, BoundingBox box, IBlockData boundaryBlockState, IBlockData insideBlockState, boolean existingOnly) { ++ this.generateBox(level, boundingBox, box.minX(), box.minY(), box.minZ(), box.maxX(), box.maxY(), box.maxZ(), boundaryBlockState, insideBlockState, existingOnly); + } + +- protected void generateBox( +- WorldGenLevel level, +- BoundingBox box, +- int minX, +- int minY, +- int minZ, +- int maxX, +- int maxY, +- int maxZ, +- boolean alwaysReplace, +- RandomSource random, +- StructurePiece.BlockSelector blockSelector +- ) { +- for (int i = minY; i <= maxY; i++) { +- for (int i1 = minX; i1 <= maxX; i1++) { +- for (int i2 = minZ; i2 <= maxZ; i2++) { +- if (!alwaysReplace || !this.getBlock(level, i1, i, i2, box).isAir()) { +- blockSelector.next(random, i1, i, i2, i == minY || i == maxY || i1 == minX || i1 == maxX || i2 == minZ || i2 == maxZ); +- this.placeBlock(level, blockSelector.getNext(), i1, i, i2, box); ++ protected void generateBox(WorldGenLevel level, BoundingBox box, int minX, int minY, int minZ, int maxX, int maxY, int maxZ, boolean alwaysReplace, RandomSource random, StructurePiece.BlockSelector blockSelector) { ++ for (int k1 = minY; k1 <= maxY; ++k1) { ++ for (int l1 = minX; l1 <= maxX; ++l1) { ++ for (int i2 = minZ; i2 <= maxZ; ++i2) { ++ if (!alwaysReplace || !this.getBlock(level, l1, k1, i2, box).isAir()) { ++ blockSelector.next(random, l1, k1, i2, k1 == minY || k1 == maxY || l1 == minX || l1 == maxX || i2 == minZ || i2 == maxZ); ++ this.placeBlock(level, blockSelector.getNext(), l1, k1, i2, box); + } + } + } + } ++ + } + +- protected void generateBox( +- WorldGenLevel level, BoundingBox boundingBox, BoundingBox box, boolean alwaysReplace, RandomSource random, StructurePiece.BlockSelector blockSelector +- ) { ++ protected void generateBox(WorldGenLevel level, BoundingBox boundingBox, BoundingBox box, boolean alwaysReplace, RandomSource random, StructurePiece.BlockSelector blockSelector) { + this.generateBox(level, boundingBox, box.minX(), box.minY(), box.minZ(), box.maxX(), box.maxY(), box.maxZ(), alwaysReplace, random, blockSelector); + } + +- protected void generateMaybeBox( +- WorldGenLevel level, +- BoundingBox box, +- RandomSource random, +- float chance, +- int x1, +- int y1, +- int z1, +- int x2, +- int y2, +- int z2, +- BlockState edgeState, +- BlockState state, +- boolean requireNonAir, +- boolean requireSkylight +- ) { +- for (int i = y1; i <= y2; i++) { +- for (int i1 = x1; i1 <= x2; i1++) { +- for (int i2 = z1; i2 <= z2; i2++) { +- if (!(random.nextFloat() > chance) +- && (!requireNonAir || !this.getBlock(level, i1, i, i2, box).isAir()) +- && (!requireSkylight || this.isInterior(level, i1, i, i2, box))) { +- if (i != y1 && i != y2 && i1 != x1 && i1 != x2 && i2 != z1 && i2 != z2) { +- this.placeBlock(level, state, i1, i, i2, box); ++ protected void generateMaybeBox(WorldGenLevel level, BoundingBox box, RandomSource random, float chance, int x1, int y1, int z1, int x2, int y2, int z2, IBlockData edgeState, IBlockData state, boolean requireNonAir, boolean requireSkylight) { ++ for (int k1 = y1; k1 <= y2; ++k1) { ++ for (int l1 = x1; l1 <= x2; ++l1) { ++ for (int i2 = z1; i2 <= z2; ++i2) { ++ if (random.nextFloat() <= chance && (!requireNonAir || !this.getBlock(level, l1, k1, i2, box).isAir()) && (!requireSkylight || this.isInterior(level, l1, k1, i2, box))) { ++ if (k1 != y1 && k1 != y2 && l1 != x1 && l1 != x2 && i2 != z1 && i2 != z2) { ++ this.placeBlock(level, state, l1, k1, i2, box); + } else { +- this.placeBlock(level, edgeState, i1, i, i2, box); ++ this.placeBlock(level, edgeState, l1, k1, i2, box); + } + } + } + } + } ++ + } + +- protected void maybeGenerateBlock(WorldGenLevel level, BoundingBox box, RandomSource random, float chance, int x, int y, int z, BlockState state) { ++ protected void maybeGenerateBlock(WorldGenLevel level, BoundingBox box, RandomSource random, float chance, int x, int y, int z, IBlockData state) { + if (random.nextFloat() < chance) { + this.placeBlock(level, state, x, y, z, box); + } ++ + } + +- protected void generateUpperHalfSphere( +- WorldGenLevel level, BoundingBox box, int minX, int minY, int minZ, int maxX, int maxY, int maxZ, BlockState state, boolean excludeAir +- ) { +- float f = (float)(maxX - minX + 1); +- float f1 = (float)(maxY - minY + 1); +- float f2 = (float)(maxZ - minZ + 1); +- float f3 = (float)minX + f / 2.0F; +- float f4 = (float)minZ + f2 / 2.0F; ++ protected void generateUpperHalfSphere(WorldGenLevel level, BoundingBox box, int minX, int minY, int minZ, int maxX, int maxY, int maxZ, IBlockData state, boolean excludeAir) { ++ float f = (float) (maxX - minX + 1); ++ float f1 = (float) (maxY - minY + 1); ++ float f2 = (float) (maxZ - minZ + 1); ++ float f3 = (float) minX + f / 2.0F; ++ float f4 = (float) minZ + f2 / 2.0F; + +- for (int i = minY; i <= maxY; i++) { +- float f5 = (float)(i - minY) / f1; ++ for (int k1 = minY; k1 <= maxY; ++k1) { ++ float f5 = (float) (k1 - minY) / f1; + +- for (int i1 = minX; i1 <= maxX; i1++) { +- float f6 = ((float)i1 - f3) / (f * 0.5F); ++ for (int l1 = minX; l1 <= maxX; ++l1) { ++ float f6 = ((float) l1 - f3) / (f * 0.5F); + +- for (int i2 = minZ; i2 <= maxZ; i2++) { +- float f7 = ((float)i2 - f4) / (f2 * 0.5F); +- if (!excludeAir || !this.getBlock(level, i1, i, i2, box).isAir()) { ++ for (int i2 = minZ; i2 <= maxZ; ++i2) { ++ float f7 = ((float) i2 - f4) / (f2 * 0.5F); ++ ++ if (!excludeAir || !this.getBlock(level, l1, k1, i2, box).isAir()) { + float f8 = f6 * f6 + f5 * f5 + f7 * f7; ++ + if (f8 <= 1.05F) { +- this.placeBlock(level, state, i1, i, i2, box); ++ this.placeBlock(level, state, l1, k1, i2, box); + } + } + } + } + } ++ + } + +- protected void fillColumnDown(WorldGenLevel level, BlockState state, int x, int y, int z, BoundingBox box) { +- BlockPos.MutableBlockPos worldPos = this.getWorldPos(x, y, z); +- if (box.isInside(worldPos)) { +- while (this.isReplaceableByStructures(level.getBlockState(worldPos)) && worldPos.getY() > level.getMinBuildHeight() + 1) { +- level.setBlock(worldPos, state, 2); +- worldPos.move(Direction.DOWN); ++ protected void fillColumnDown(WorldGenLevel level, IBlockData state, int x, int y, int z, BoundingBox box) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y, z); ++ ++ if (box.isInside(blockposition_mutableblockposition)) { ++ while (this.isReplaceableByStructures(level.getBlockState(blockposition_mutableblockposition)) && blockposition_mutableblockposition.getY() > level.getMinBuildHeight() + 1) { ++ level.setBlock(blockposition_mutableblockposition, state, 2); ++ blockposition_mutableblockposition.move(Direction.DOWN); + } ++ + } + } + +- protected boolean isReplaceableByStructures(BlockState state) { ++ protected boolean isReplaceableByStructures(IBlockData state) { + return state.isAir() || state.liquid() || state.is(Blocks.GLOW_LICHEN) || state.is(Blocks.SEAGRASS) || state.is(Blocks.TALL_SEAGRASS); + } + + protected boolean createChest(WorldGenLevel level, BoundingBox box, RandomSource random, int x, int y, int z, ResourceLocation lootTable) { +- return this.createChest(level, box, random, this.getWorldPos(x, y, z), lootTable, null); ++ return this.createChest(level, box, random, this.getWorldPos(x, y, z), lootTable, (IBlockData) null); + } + +- public static BlockState reorient(BlockGetter level, BlockPos pos, BlockState state) { +- Direction direction = null; ++ public static IBlockData reorient(BlockGetter level, BlockPos pos, IBlockData state) { ++ Direction enumdirection = null; ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction direction1 : Direction.Plane.HORIZONTAL) { +- BlockPos blockPos = pos.relative(direction1); +- BlockState blockState = level.getBlockState(blockPos); +- if (blockState.is(Blocks.CHEST)) { ++ while (iterator.hasNext()) { ++ Direction enumdirection1 = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection1); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ if (iblockdata1.is(Blocks.CHEST)) { + return state; + } + +- if (blockState.isSolidRender(level, blockPos)) { +- if (direction != null) { +- direction = null; ++ if (iblockdata1.isSolidRender(level, blockposition1)) { ++ if (enumdirection != null) { ++ enumdirection = null; + break; + } + +- direction = direction1; ++ enumdirection = enumdirection1; + } + } + +- if (direction != null) { +- return state.setValue(HorizontalDirectionalBlock.FACING, direction.getOpposite()); ++ if (enumdirection != null) { ++ return (IBlockData) state.setValue(HorizontalDirectionalBlock.FACING, enumdirection.getOpposite()); + } else { +- Direction direction2 = state.getValue(HorizontalDirectionalBlock.FACING); +- BlockPos blockPos1 = pos.relative(direction2); +- if (level.getBlockState(blockPos1).isSolidRender(level, blockPos1)) { +- direction2 = direction2.getOpposite(); +- blockPos1 = pos.relative(direction2); ++ Direction enumdirection2 = (Direction) state.getValue(HorizontalDirectionalBlock.FACING); ++ BlockPos blockposition2 = pos.relative(enumdirection2); ++ ++ if (level.getBlockState(blockposition2).isSolidRender(level, blockposition2)) { ++ enumdirection2 = enumdirection2.getOpposite(); ++ blockposition2 = pos.relative(enumdirection2); + } + +- if (level.getBlockState(blockPos1).isSolidRender(level, blockPos1)) { +- direction2 = direction2.getClockWise(); +- blockPos1 = pos.relative(direction2); ++ if (level.getBlockState(blockposition2).isSolidRender(level, blockposition2)) { ++ enumdirection2 = enumdirection2.getClockWise(); ++ blockposition2 = pos.relative(enumdirection2); + } + +- if (level.getBlockState(blockPos1).isSolidRender(level, blockPos1)) { +- direction2 = direction2.getOpposite(); +- blockPos1 = pos.relative(direction2); ++ if (level.getBlockState(blockposition2).isSolidRender(level, blockposition2)) { ++ enumdirection2 = enumdirection2.getOpposite(); ++ pos.relative(enumdirection2); + } + +- return state.setValue(HorizontalDirectionalBlock.FACING, direction2); ++ return (IBlockData) state.setValue(HorizontalDirectionalBlock.FACING, enumdirection2); + } + } + +- protected boolean createChest( +- ServerLevelAccessor level, BoundingBox box, RandomSource random, BlockPos pos, ResourceLocation lootTable, @Nullable BlockState state +- ) { ++ protected boolean createChest(ServerLevelAccessor level, BoundingBox box, RandomSource random, BlockPos pos, ResourceLocation lootTable, @Nullable IBlockData state) { + if (box.isInside(pos) && !level.getBlockState(pos).is(Blocks.CHEST)) { + if (state == null) { + state = reorient(level, pos, Blocks.CHEST.defaultBlockState()); + } + +- level.setBlock(pos, state, 2); +- BlockEntity blockEntity = level.getBlockEntity(pos); +- if (blockEntity instanceof ChestBlockEntity) { +- ((ChestBlockEntity)blockEntity).setLootTable(lootTable, random.nextLong()); ++ // CraftBukkit start ++ /* ++ worldaccess.setBlock(blockposition, iblockdata, 2); ++ TileEntity tileentity = worldaccess.getBlockEntity(blockposition); ++ ++ if (tileentity instanceof TileEntityChest) { ++ ((TileEntityChest) tileentity).setLootTable(minecraftkey, randomsource.nextLong()); + } ++ */ ++ org.bukkit.craftbukkit.block.CraftChest chestState = (org.bukkit.craftbukkit.block.CraftChest) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(pos, state, null); ++ chestState.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(lootTable))); ++ chestState.setSeed(random.nextLong()); ++ placeCraftBlockEntity(level, pos, chestState, 2); ++ // CraftBukkit end + + return true; + } else { +@@ -443,17 +448,36 @@ + } + } + +- protected boolean createDispenser( +- WorldGenLevel level, BoundingBox box, RandomSource random, int x, int y, int z, Direction facing, ResourceLocation lootTable +- ) { +- BlockPos worldPos = this.getWorldPos(x, y, z); +- if (box.isInside(worldPos) && !level.getBlockState(worldPos).is(Blocks.DISPENSER)) { +- this.placeBlock(level, Blocks.DISPENSER.defaultBlockState().setValue(DispenserBlock.FACING, facing), x, y, z, box); +- BlockEntity blockEntity = level.getBlockEntity(worldPos); +- if (blockEntity instanceof DispenserBlockEntity) { +- ((DispenserBlockEntity)blockEntity).setLootTable(lootTable, random.nextLong()); ++ protected boolean createDispenser(WorldGenLevel level, BoundingBox box, RandomSource random, int x, int y, int z, Direction facing, ResourceLocation lootTable) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y, z); ++ ++ if (box.isInside(blockposition_mutableblockposition) && !level.getBlockState(blockposition_mutableblockposition).is(Blocks.DISPENSER)) { ++ // CraftBukkit start ++ /* ++ this.placeBlock(generatoraccessseed, (IBlockData) Blocks.DISPENSER.defaultBlockState().setValue(BlockDispenser.FACING, enumdirection), i, j, k, structureboundingbox); ++ TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); ++ ++ if (tileentity instanceof TileEntityDispenser) { ++ ((TileEntityDispenser) tileentity).setLootTable(minecraftkey, randomsource.nextLong()); + } ++ */ ++ if (!this.canBeReplaced(level, x, y, z, box)) { ++ return true; ++ } ++ IBlockData iblockdata = Blocks.DISPENSER.defaultBlockState().setValue(DispenserBlock.FACING, facing); ++ if (this.mirror != Mirror.NONE) { ++ iblockdata = iblockdata.mirror(this.mirror); ++ } ++ if (this.rotation != Rotation.NONE) { ++ iblockdata = iblockdata.rotate(this.rotation); ++ } + ++ org.bukkit.craftbukkit.block.CraftDispenser dispenserState = (org.bukkit.craftbukkit.block.CraftDispenser) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockposition_mutableblockposition, iblockdata, null); ++ dispenserState.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(lootTable))); ++ dispenserState.setSeed(random.nextLong()); ++ placeCraftBlockEntity(level, blockposition_mutableblockposition, dispenserState, 2); ++ // CraftBukkit end ++ + return true; + } else { + return false; +@@ -465,19 +489,29 @@ + } + + public static BoundingBox createBoundingBox(Stream pieces) { +- return BoundingBox.encapsulatingBoxes(pieces.map(StructurePiece::getBoundingBox)::iterator) +- .orElseThrow(() -> new IllegalStateException("Unable to calculate boundingbox without pieces")); ++ Stream stream1 = pieces.map(StructurePiece::getBoundingBox); // CraftBukkit - decompile error ++ ++ Objects.requireNonNull(stream1); ++ return (BoundingBox) BoundingBox.encapsulatingBoxes(stream1::iterator).orElseThrow(() -> { ++ return new IllegalStateException("Unable to calculate boundingbox without pieces"); ++ }); + } + + @Nullable + public static StructurePiece findCollisionPiece(List pieces, BoundingBox boundingBox) { +- for (StructurePiece structurePiece : pieces) { +- if (structurePiece.getBoundingBox().intersects(boundingBox)) { +- return structurePiece; ++ Iterator iterator = pieces.iterator(); ++ ++ StructurePiece structurepiece; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return null; + } +- } + +- return null; ++ structurepiece = (StructurePiece) iterator.next(); ++ } while (!structurepiece.getBoundingBox().intersects(boundingBox)); ++ ++ return structurepiece; + } + + @Nullable +@@ -509,6 +543,7 @@ + this.rotation = Rotation.NONE; + } + } ++ + } + + public Rotation getRotation() { +@@ -524,11 +559,16 @@ + } + + public abstract static class BlockSelector { +- protected BlockState next = Blocks.AIR.defaultBlockState(); + ++ protected IBlockData next; ++ ++ public BlockSelector() { ++ this.next = Blocks.AIR.defaultBlockState(); ++ } ++ + public abstract void next(RandomSource random, int x, int y, int z, boolean wall); + +- public BlockState getNext() { ++ public IBlockData getNext() { + return this.next; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/StructureStart.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/StructureStart.java.patch new file mode 100644 index 0000000000..d6a1d8cadc --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/StructureStart.java.patch @@ -0,0 +1,173 @@ +--- a/net/minecraft/world/level/levelgen/structure/StructureStart.java ++++ b/net/minecraft/world/level/levelgen/structure/StructureStart.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.levelgen.structure; + + import com.mojang.logging.LogUtils; ++import java.util.Iterator; + import java.util.List; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +@@ -20,8 +21,9 @@ + import org.slf4j.Logger; + + public final class StructureStart { ++ + public static final String INVALID_START_ID = "INVALID"; +- public static final StructureStart INVALID_START = new StructureStart(null, new ChunkPos(0, 0), 0, new PiecesContainer(List.of())); ++ public static final StructureStart INVALID_START = new StructureStart((Structure) null, new ChunkPos(0, 0), 0, new PiecesContainer(List.of())); + private static final Logger LOGGER = LogUtils.getLogger(); + private final Structure structure; + private final PiecesContainer pieceContainer; +@@ -29,6 +31,7 @@ + private int references; + @Nullable + private volatile BoundingBox cachedBoundingBox; ++ public org.bukkit.event.world.AsyncStructureGenerateEvent.Cause generationEventCause = org.bukkit.event.world.AsyncStructureGenerateEvent.Cause.WORLD_GENERATION; // CraftBukkit + + public StructureStart(Structure structure, ChunkPos chunkPos, int references, PiecesContainer pieceContainer) { + this.structure = structure; +@@ -39,29 +42,32 @@ + + @Nullable + public static StructureStart loadStaticStart(StructurePieceSerializationContext context, CompoundTag tag, long seed) { +- String string = tag.getString("id"); +- if ("INVALID".equals(string)) { +- return INVALID_START; ++ String s = tag.getString("id"); ++ ++ if ("INVALID".equals(s)) { ++ return StructureStart.INVALID_START; + } else { +- Registry registry = context.registryAccess().registryOrThrow(Registries.STRUCTURE); +- Structure structure = registry.get(new ResourceLocation(string)); ++ Registry iregistry = context.registryAccess().registryOrThrow(Registries.STRUCTURE); ++ Structure structure = (Structure) iregistry.get(new ResourceLocation(s)); ++ + if (structure == null) { +- LOGGER.error("Unknown stucture id: {}", string); ++ StructureStart.LOGGER.error("Unknown stucture id: {}", s); + return null; + } else { +- ChunkPos chunkPos = new ChunkPos(tag.getInt("ChunkX"), tag.getInt("ChunkZ")); +- int _int = tag.getInt("references"); +- ListTag list = tag.getList("Children", 10); ++ ChunkPos chunkcoordintpair = new ChunkPos(tag.getInt("ChunkX"), tag.getInt("ChunkZ")); ++ int j = tag.getInt("references"); ++ ListTag nbttaglist = tag.getList("Children", 10); + + try { +- PiecesContainer piecesContainer = PiecesContainer.load(list, context); ++ PiecesContainer piecescontainer = PiecesContainer.load(nbttaglist, context); ++ + if (structure instanceof OceanMonumentStructure) { +- piecesContainer = OceanMonumentStructure.regeneratePiecesAfterLoad(chunkPos, seed, piecesContainer); ++ piecescontainer = OceanMonumentStructure.regeneratePiecesAfterLoad(chunkcoordintpair, seed, piecescontainer); + } + +- return new StructureStart(structure, chunkPos, _int, piecesContainer); +- } catch (Exception var11) { +- LOGGER.error("Failed Start with id {}", string, var11); ++ return new StructureStart(structure, chunkcoordintpair, j, piecescontainer); ++ } catch (Exception exception) { ++ StructureStart.LOGGER.error("Failed Start with id {}", s, exception); + return null; + } + } +@@ -69,46 +75,64 @@ + } + + public BoundingBox getBoundingBox() { +- BoundingBox boundingBox = this.cachedBoundingBox; +- if (boundingBox == null) { +- boundingBox = this.structure.adjustBoundingBox(this.pieceContainer.calculateBoundingBox()); +- this.cachedBoundingBox = boundingBox; ++ BoundingBox structureboundingbox = this.cachedBoundingBox; ++ ++ if (structureboundingbox == null) { ++ structureboundingbox = this.structure.adjustBoundingBox(this.pieceContainer.calculateBoundingBox()); ++ this.cachedBoundingBox = structureboundingbox; + } + +- return boundingBox; ++ return structureboundingbox; + } + +- public void placeInChunk( +- WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos +- ) { ++ public void placeInChunk(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos) { + List list = this.pieceContainer.pieces(); ++ + if (!list.isEmpty()) { +- BoundingBox boundingBox = list.get(0).boundingBox; +- BlockPos center = boundingBox.getCenter(); +- BlockPos blockPos = new BlockPos(center.getX(), boundingBox.minY(), center.getZ()); ++ BoundingBox structureboundingbox1 = ((StructurePiece) list.get(0)).boundingBox; ++ BlockPos blockposition = structureboundingbox1.getCenter(); ++ BlockPos blockposition1 = new BlockPos(blockposition.getX(), structureboundingbox1.minY(), blockposition.getZ()); ++ // CraftBukkit start ++ /* ++ Iterator iterator = list.iterator(); + +- for (StructurePiece structurePiece : list) { +- if (structurePiece.getBoundingBox().intersects(box)) { +- structurePiece.postProcess(level, structureManager, generator, random, box, chunkPos, blockPos); ++ while (iterator.hasNext()) { ++ StructurePiece structurepiece = (StructurePiece) iterator.next(); ++ ++ if (structurepiece.getBoundingBox().intersects(structureboundingbox)) { ++ structurepiece.postProcess(generatoraccessseed, structuremanager, chunkgenerator, randomsource, structureboundingbox, chunkcoordintpair, blockposition1); + } + } ++ */ ++ List pieces = list.stream().filter(piece -> piece.getBoundingBox().intersects(box)).toList(); ++ if (!pieces.isEmpty()) { ++ org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess = new org.bukkit.craftbukkit.util.TransformerGeneratorAccess(); ++ transformerAccess.setHandle(level); ++ transformerAccess.setStructureTransformer(new org.bukkit.craftbukkit.util.CraftStructureTransformer(generationEventCause, level, structureManager, structure, box, chunkPos)); ++ for (StructurePiece piece : pieces) { ++ piece.postProcess(transformerAccess, structureManager, generator, random, box, chunkPos, blockposition1); ++ } ++ transformerAccess.getStructureTransformer().discard(); ++ } ++ // CraftBukkit end + + this.structure.afterPlace(level, structureManager, generator, random, box, chunkPos, this.pieceContainer); + } + } + + public CompoundTag createTag(StructurePieceSerializationContext context, ChunkPos chunkPos) { +- CompoundTag compoundTag = new CompoundTag(); ++ CompoundTag nbttagcompound = new CompoundTag(); ++ + if (this.isValid()) { +- compoundTag.putString("id", context.registryAccess().registryOrThrow(Registries.STRUCTURE).getKey(this.structure).toString()); +- compoundTag.putInt("ChunkX", chunkPos.x); +- compoundTag.putInt("ChunkZ", chunkPos.z); +- compoundTag.putInt("references", this.references); +- compoundTag.put("Children", this.pieceContainer.save(context)); +- return compoundTag; ++ nbttagcompound.putString("id", context.registryAccess().registryOrThrow(Registries.STRUCTURE).getKey(this.structure).toString()); ++ nbttagcompound.putInt("ChunkX", chunkPos.x); ++ nbttagcompound.putInt("ChunkZ", chunkPos.z); ++ nbttagcompound.putInt("references", this.references); ++ nbttagcompound.put("Children", this.pieceContainer.save(context)); ++ return nbttagcompound; + } else { +- compoundTag.putString("id", "INVALID"); +- return compoundTag; ++ nbttagcompound.putString("id", "INVALID"); ++ return nbttagcompound; + } + } + +@@ -125,7 +149,7 @@ + } + + public void addReference() { +- this.references++; ++ ++this.references; + } + + public int getReferences() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java.patch new file mode 100644 index 0000000000..608ee2231f --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java.patch @@ -0,0 +1,112 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java +@@ -2,6 +2,8 @@ + + import com.mojang.serialization.Codec; + import it.unimi.dsi.fastutil.objects.ObjectArrayList; ++import it.unimi.dsi.fastutil.objects.ObjectListIterator; ++import java.util.Iterator; + import java.util.Set; + import net.minecraft.Util; + import net.minecraft.core.BlockPos; +@@ -13,7 +15,6 @@ + import net.minecraft.world.level.WorldGenLevel; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.BlockEntityType; +-import net.minecraft.world.level.block.entity.BrushableBlockEntity; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.levelgen.structure.BoundingBox; + import net.minecraft.world.level.levelgen.structure.SinglePieceStructure; +@@ -24,52 +25,66 @@ + import net.minecraft.world.level.storage.loot.BuiltInLootTables; + + public class DesertPyramidStructure extends SinglePieceStructure { ++ + public static final Codec CODEC = simpleCodec(DesertPyramidStructure::new); + +- public DesertPyramidStructure(Structure.StructureSettings settings) { ++ public DesertPyramidStructure(Structure.c settings) { + super(DesertPyramidPiece::new, 21, 21, settings); + } + + @Override +- public void afterPlace( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator chunkGenerator, +- RandomSource random, +- BoundingBox boundingBox, +- ChunkPos chunkPos, +- PiecesContainer pieces +- ) { ++ public void afterPlace(WorldGenLevel level, StructureManager structureManager, ChunkGenerator chunkGenerator, RandomSource random, BoundingBox boundingBox, ChunkPos chunkPos, PiecesContainer pieces) { + Set set = SortedArraySet.create(Vec3i::compareTo); ++ Iterator iterator = pieces.pieces().iterator(); + +- for (StructurePiece structurePiece : pieces.pieces()) { +- if (structurePiece instanceof DesertPyramidPiece desertPyramidPiece) { +- set.addAll(desertPyramidPiece.getPotentialSuspiciousSandWorldPositions()); +- placeSuspiciousSand(boundingBox, level, desertPyramidPiece.getRandomCollapsedRoofPos()); ++ while (iterator.hasNext()) { ++ StructurePiece structurepiece = (StructurePiece) iterator.next(); ++ ++ if (structurepiece instanceof DesertPyramidPiece) { ++ DesertPyramidPiece desertpyramidpiece = (DesertPyramidPiece) structurepiece; ++ ++ set.addAll(desertpyramidpiece.getPotentialSuspiciousSandWorldPositions()); ++ placeSuspiciousSand(boundingBox, level, desertpyramidpiece.getRandomCollapsedRoofPos()); + } + } + +- ObjectArrayList list = new ObjectArrayList<>(set.stream().toList()); +- RandomSource randomSource = RandomSource.create(level.getSeed()).forkPositional().at(pieces.calculateBoundingBox().getCenter()); +- Util.shuffle(list, randomSource); +- int min = Math.min(set.size(), randomSource.nextInt(5, 8)); ++ ObjectArrayList objectarraylist = new ObjectArrayList(set.stream().toList()); ++ RandomSource randomsource1 = RandomSource.create(level.getSeed()).forkPositional().at(pieces.calculateBoundingBox().getCenter()); + +- for (BlockPos blockPos : list) { +- if (min > 0) { +- min--; +- placeSuspiciousSand(boundingBox, level, blockPos); +- } else if (boundingBox.isInside(blockPos)) { +- level.setBlock(blockPos, Blocks.SAND.defaultBlockState(), 2); ++ Util.shuffle(objectarraylist, randomsource1); ++ int i = Math.min(set.size(), randomsource1.nextInt(5, 8)); ++ ObjectListIterator objectlistiterator = objectarraylist.iterator(); ++ ++ while (objectlistiterator.hasNext()) { ++ BlockPos blockposition = (BlockPos) objectlistiterator.next(); ++ ++ if (i > 0) { ++ --i; ++ placeSuspiciousSand(boundingBox, level, blockposition); ++ } else if (boundingBox.isInside(blockposition)) { ++ level.setBlock(blockposition, Blocks.SAND.defaultBlockState(), 2); + } + } ++ + } + + private static void placeSuspiciousSand(BoundingBox boundingBox, WorldGenLevel worldGenLevel, BlockPos pos) { + if (boundingBox.isInside(pos)) { ++ // CraftBukkit start ++ if (worldGenLevel instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ org.bukkit.craftbukkit.block.CraftBrushableBlock brushableState = (org.bukkit.craftbukkit.block.CraftBrushableBlock) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(pos, Blocks.SUSPICIOUS_SAND.defaultBlockState(), null); ++ brushableState.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(BuiltInLootTables.DESERT_PYRAMID_ARCHAEOLOGY))); ++ brushableState.setSeed(pos.asLong()); ++ transformerAccess.setCraftBlock(pos, brushableState, 2); ++ return; ++ } ++ // CraftBukkit end + worldGenLevel.setBlock(pos, Blocks.SUSPICIOUS_SAND.defaultBlockState(), 2); +- worldGenLevel.getBlockEntity(pos, BlockEntityType.BRUSHABLE_BLOCK) +- .ifPresent(brushableBlockEntity -> brushableBlockEntity.setLootTable(BuiltInLootTables.DESERT_PYRAMID_ARCHAEOLOGY, pos.asLong())); ++ worldGenLevel.getBlockEntity(pos, BlockEntityType.BRUSHABLE_BLOCK).ifPresent((brushableblockentity) -> { ++ brushableblockentity.setLootTable(BuiltInLootTables.DESERT_PYRAMID_ARCHAEOLOGY, pos.asLong()); ++ }); + } ++ + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java.patch new file mode 100644 index 0000000000..3171370d4c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java.patch @@ -0,0 +1,522 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.levelgen.structure.structures; + + import com.google.common.collect.Lists; ++import java.util.Iterator; + import java.util.List; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +@@ -28,126 +29,79 @@ + import net.minecraft.world.level.storage.loot.BuiltInLootTables; + + public class EndCityPieces { ++ + private static final int MAX_GEN_DEPTH = 8; + static final EndCityPieces.SectionGenerator HOUSE_TOWER_GENERATOR = new EndCityPieces.SectionGenerator() { + @Override +- public void init() { +- } ++ public void init() {} + + @Override +- public boolean generate( +- StructureTemplateManager structureTemplateManager, +- int counter, +- EndCityPieces.EndCityPiece piece, +- BlockPos startPos, +- List pieces, +- RandomSource random +- ) { ++ public boolean generate(StructureTemplateManager structureTemplateManager, int counter, EndCityPieces.EndCityPiece piece, BlockPos startPos, List pieces, RandomSource random) { + if (counter > 8) { + return false; + } else { +- Rotation rotation = piece.placeSettings().getRotation(); +- EndCityPieces.EndCityPiece endCityPiece = EndCityPieces.addHelper( +- pieces, EndCityPieces.addPiece(structureTemplateManager, piece, startPos, "base_floor", rotation, true) +- ); +- int randomInt = random.nextInt(3); +- if (randomInt == 0) { +- endCityPiece = EndCityPieces.addHelper( +- pieces, EndCityPieces.addPiece(structureTemplateManager, endCityPiece, new BlockPos(-1, 4, -1), "base_roof", rotation, true) +- ); +- } else if (randomInt == 1) { +- endCityPiece = EndCityPieces.addHelper( +- pieces, EndCityPieces.addPiece(structureTemplateManager, endCityPiece, new BlockPos(-1, 0, -1), "second_floor_2", rotation, false) +- ); +- endCityPiece = EndCityPieces.addHelper( +- pieces, EndCityPieces.addPiece(structureTemplateManager, endCityPiece, new BlockPos(-1, 8, -1), "second_roof", rotation, false) +- ); +- EndCityPieces.recursiveChildren(structureTemplateManager, EndCityPieces.TOWER_GENERATOR, counter + 1, endCityPiece, null, pieces, random); +- } else if (randomInt == 2) { +- endCityPiece = EndCityPieces.addHelper( +- pieces, EndCityPieces.addPiece(structureTemplateManager, endCityPiece, new BlockPos(-1, 0, -1), "second_floor_2", rotation, false) +- ); +- endCityPiece = EndCityPieces.addHelper( +- pieces, EndCityPieces.addPiece(structureTemplateManager, endCityPiece, new BlockPos(-1, 4, -1), "third_floor_2", rotation, false) +- ); +- endCityPiece = EndCityPieces.addHelper( +- pieces, EndCityPieces.addPiece(structureTemplateManager, endCityPiece, new BlockPos(-1, 8, -1), "third_roof", rotation, true) +- ); +- EndCityPieces.recursiveChildren(structureTemplateManager, EndCityPieces.TOWER_GENERATOR, counter + 1, endCityPiece, null, pieces, random); ++ Rotation enumblockrotation = piece.placeSettings().getRotation(); ++ EndCityPieces.EndCityPiece endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, piece, startPos, "base_floor", enumblockrotation, true)); ++ int j = random.nextInt(3); ++ ++ if (j == 0) { ++ EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(-1, 4, -1), "base_roof", enumblockrotation, true)); ++ } else if (j == 1) { ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(-1, 0, -1), "second_floor_2", enumblockrotation, false)); ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(-1, 8, -1), "second_roof", enumblockrotation, false)); ++ EndCityPieces.recursiveChildren(structureTemplateManager, EndCityPieces.TOWER_GENERATOR, counter + 1, endcitypieces_a1, (BlockPos) null, pieces, random); ++ } else if (j == 2) { ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(-1, 0, -1), "second_floor_2", enumblockrotation, false)); ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(-1, 4, -1), "third_floor_2", enumblockrotation, false)); ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(-1, 8, -1), "third_roof", enumblockrotation, true)); ++ EndCityPieces.recursiveChildren(structureTemplateManager, EndCityPieces.TOWER_GENERATOR, counter + 1, endcitypieces_a1, (BlockPos) null, pieces, random); + } + + return true; + } + } + }; +- static final List> TOWER_BRIDGES = Lists.newArrayList( +- new Tuple<>(Rotation.NONE, new BlockPos(1, -1, 0)), +- new Tuple<>(Rotation.CLOCKWISE_90, new BlockPos(6, -1, 1)), +- new Tuple<>(Rotation.COUNTERCLOCKWISE_90, new BlockPos(0, -1, 5)), +- new Tuple<>(Rotation.CLOCKWISE_180, new BlockPos(5, -1, 6)) +- ); ++ static final List> TOWER_BRIDGES = Lists.newArrayList(new Tuple[]{new Tuple<>(Rotation.NONE, new BlockPos(1, -1, 0)), new Tuple<>(Rotation.CLOCKWISE_90, new BlockPos(6, -1, 1)), new Tuple<>(Rotation.COUNTERCLOCKWISE_90, new BlockPos(0, -1, 5)), new Tuple<>(Rotation.CLOCKWISE_180, new BlockPos(5, -1, 6))}); + static final EndCityPieces.SectionGenerator TOWER_GENERATOR = new EndCityPieces.SectionGenerator() { + @Override +- public void init() { +- } ++ public void init() {} + + @Override +- public boolean generate( +- StructureTemplateManager structureTemplateManager, +- int counter, +- EndCityPieces.EndCityPiece piece, +- BlockPos startPos, +- List pieces, +- RandomSource random +- ) { +- Rotation rotation = piece.placeSettings().getRotation(); +- EndCityPieces.EndCityPiece endCityPiece = EndCityPieces.addHelper( +- pieces, +- EndCityPieces.addPiece( +- structureTemplateManager, piece, new BlockPos(3 + random.nextInt(2), -3, 3 + random.nextInt(2)), "tower_base", rotation, true +- ) +- ); +- EndCityPieces.EndCityPiece var14 = EndCityPieces.addHelper( +- pieces, EndCityPieces.addPiece(structureTemplateManager, endCityPiece, new BlockPos(0, 7, 0), "tower_piece", rotation, true) +- ); +- EndCityPieces.EndCityPiece endCityPiece1 = random.nextInt(3) == 0 ? var14 : null; +- int i = 1 + random.nextInt(3); ++ public boolean generate(StructureTemplateManager structureTemplateManager, int counter, EndCityPieces.EndCityPiece piece, BlockPos startPos, List pieces, RandomSource random) { ++ Rotation enumblockrotation = piece.placeSettings().getRotation(); ++ EndCityPieces.EndCityPiece endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, piece, new BlockPos(3 + random.nextInt(2), -3, 3 + random.nextInt(2)), "tower_base", enumblockrotation, true)); + +- for (int i1 = 0; i1 < i; i1++) { +- var14 = EndCityPieces.addHelper( +- pieces, EndCityPieces.addPiece(structureTemplateManager, var14, new BlockPos(0, 4, 0), "tower_piece", rotation, true) +- ); +- if (i1 < i - 1 && random.nextBoolean()) { +- endCityPiece1 = var14; ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(0, 7, 0), "tower_piece", enumblockrotation, true)); ++ EndCityPieces.EndCityPiece endcitypieces_a2 = random.nextInt(3) == 0 ? endcitypieces_a1 : null; ++ int j = 1 + random.nextInt(3); ++ ++ for (int k = 0; k < j; ++k) { ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(0, 4, 0), "tower_piece", enumblockrotation, true)); ++ if (k < j - 1 && random.nextBoolean()) { ++ endcitypieces_a2 = endcitypieces_a1; + } + } + +- if (endCityPiece1 != null) { +- for (Tuple tuple : EndCityPieces.TOWER_BRIDGES) { ++ if (endcitypieces_a2 != null) { ++ Iterator iterator = EndCityPieces.TOWER_BRIDGES.iterator(); ++ ++ while (iterator.hasNext()) { ++ Tuple tuple = (Tuple) iterator.next(); ++ + if (random.nextBoolean()) { +- EndCityPieces.EndCityPiece endCityPiece2 = EndCityPieces.addHelper( +- pieces, +- EndCityPieces.addPiece(structureTemplateManager, endCityPiece1, tuple.getB(), "bridge_end", rotation.getRotated(tuple.getA()), true) +- ); +- EndCityPieces.recursiveChildren( +- structureTemplateManager, EndCityPieces.TOWER_BRIDGE_GENERATOR, counter + 1, endCityPiece2, null, pieces, random +- ); ++ EndCityPieces.EndCityPiece endcitypieces_a3 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a2, (BlockPos) tuple.getB(), "bridge_end", enumblockrotation.getRotated((Rotation) tuple.getA()), true)); ++ ++ EndCityPieces.recursiveChildren(structureTemplateManager, EndCityPieces.TOWER_BRIDGE_GENERATOR, counter + 1, endcitypieces_a3, (BlockPos) null, pieces, random); + } + } + +- endCityPiece = EndCityPieces.addHelper( +- pieces, EndCityPieces.addPiece(structureTemplateManager, var14, new BlockPos(-1, 4, -1), "tower_top", rotation, true) +- ); ++ EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(-1, 4, -1), "tower_top", enumblockrotation, true)); + } else { + if (counter != 7) { +- return EndCityPieces.recursiveChildren( +- structureTemplateManager, EndCityPieces.FAT_TOWER_GENERATOR, counter + 1, var14, null, pieces, random +- ); ++ return EndCityPieces.recursiveChildren(structureTemplateManager, EndCityPieces.FAT_TOWER_GENERATOR, counter + 1, endcitypieces_a1, (BlockPos) null, pieces, random); + } + +- endCityPiece = EndCityPieces.addHelper( +- pieces, EndCityPieces.addPiece(structureTemplateManager, var14, new BlockPos(-1, 4, -1), "tower_top", rotation, true) +- ); ++ EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(-1, 4, -1), "tower_top", enumblockrotation, true)); + } + + return true; +@@ -162,150 +116,94 @@ + } + + @Override +- public boolean generate( +- StructureTemplateManager structureTemplateManager, +- int counter, +- EndCityPieces.EndCityPiece piece, +- BlockPos startPos, +- List pieces, +- RandomSource random +- ) { +- Rotation rotation = piece.placeSettings().getRotation(); +- int i = random.nextInt(4) + 1; +- EndCityPieces.EndCityPiece endCityPiece = EndCityPieces.addHelper( +- pieces, EndCityPieces.addPiece(structureTemplateManager, piece, new BlockPos(0, 0, -4), "bridge_piece", rotation, true) +- ); +- endCityPiece.setGenDepth(-1); +- int i1 = 0; ++ public boolean generate(StructureTemplateManager structureTemplateManager, int counter, EndCityPieces.EndCityPiece piece, BlockPos startPos, List pieces, RandomSource random) { ++ Rotation enumblockrotation = piece.placeSettings().getRotation(); ++ int j = random.nextInt(4) + 1; ++ EndCityPieces.EndCityPiece endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, piece, new BlockPos(0, 0, -4), "bridge_piece", enumblockrotation, true)); + +- for (int i2 = 0; i2 < i; i2++) { ++ endcitypieces_a1.setGenDepth(-1); ++ byte b0 = 0; ++ ++ for (int k = 0; k < j; ++k) { + if (random.nextBoolean()) { +- endCityPiece = EndCityPieces.addHelper( +- pieces, EndCityPieces.addPiece(structureTemplateManager, endCityPiece, new BlockPos(0, i1, -4), "bridge_piece", rotation, true) +- ); +- i1 = 0; ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(0, b0, -4), "bridge_piece", enumblockrotation, true)); ++ b0 = 0; + } else { + if (random.nextBoolean()) { +- endCityPiece = EndCityPieces.addHelper( +- pieces, +- EndCityPieces.addPiece(structureTemplateManager, endCityPiece, new BlockPos(0, i1, -4), "bridge_steep_stairs", rotation, true) +- ); ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(0, b0, -4), "bridge_steep_stairs", enumblockrotation, true)); + } else { +- endCityPiece = EndCityPieces.addHelper( +- pieces, +- EndCityPieces.addPiece(structureTemplateManager, endCityPiece, new BlockPos(0, i1, -8), "bridge_gentle_stairs", rotation, true) +- ); ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(0, b0, -8), "bridge_gentle_stairs", enumblockrotation, true)); + } + +- i1 = 4; ++ b0 = 4; + } + } + + if (!this.shipCreated && random.nextInt(10 - counter) == 0) { +- EndCityPieces.addHelper( +- pieces, +- EndCityPieces.addPiece( +- structureTemplateManager, endCityPiece, new BlockPos(-8 + random.nextInt(8), i1, -70 + random.nextInt(10)), "ship", rotation, true +- ) +- ); ++ EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(-8 + random.nextInt(8), b0, -70 + random.nextInt(10)), "ship", enumblockrotation, true)); + this.shipCreated = true; +- } else if (!EndCityPieces.recursiveChildren( +- structureTemplateManager, EndCityPieces.HOUSE_TOWER_GENERATOR, counter + 1, endCityPiece, new BlockPos(-3, i1 + 1, -11), pieces, random +- )) { ++ } else if (!EndCityPieces.recursiveChildren(structureTemplateManager, EndCityPieces.HOUSE_TOWER_GENERATOR, counter + 1, endcitypieces_a1, new BlockPos(-3, b0 + 1, -11), pieces, random)) { + return false; + } + +- endCityPiece = EndCityPieces.addHelper( +- pieces, +- EndCityPieces.addPiece( +- structureTemplateManager, endCityPiece, new BlockPos(4, i1, 0), "bridge_end", rotation.getRotated(Rotation.CLOCKWISE_180), true +- ) +- ); +- endCityPiece.setGenDepth(-1); ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(4, b0, 0), "bridge_end", enumblockrotation.getRotated(Rotation.CLOCKWISE_180), true)); ++ endcitypieces_a1.setGenDepth(-1); + return true; + } + }; +- static final List> FAT_TOWER_BRIDGES = Lists.newArrayList( +- new Tuple<>(Rotation.NONE, new BlockPos(4, -1, 0)), +- new Tuple<>(Rotation.CLOCKWISE_90, new BlockPos(12, -1, 4)), +- new Tuple<>(Rotation.COUNTERCLOCKWISE_90, new BlockPos(0, -1, 8)), +- new Tuple<>(Rotation.CLOCKWISE_180, new BlockPos(8, -1, 12)) +- ); ++ static final List> FAT_TOWER_BRIDGES = Lists.newArrayList(new Tuple[]{new Tuple<>(Rotation.NONE, new BlockPos(4, -1, 0)), new Tuple<>(Rotation.CLOCKWISE_90, new BlockPos(12, -1, 4)), new Tuple<>(Rotation.COUNTERCLOCKWISE_90, new BlockPos(0, -1, 8)), new Tuple<>(Rotation.CLOCKWISE_180, new BlockPos(8, -1, 12))}); + static final EndCityPieces.SectionGenerator FAT_TOWER_GENERATOR = new EndCityPieces.SectionGenerator() { + @Override +- public void init() { +- } ++ public void init() {} + + @Override +- public boolean generate( +- StructureTemplateManager structureTemplateManager, +- int counter, +- EndCityPieces.EndCityPiece piece, +- BlockPos startPos, +- List pieces, +- RandomSource random +- ) { +- Rotation rotation = piece.placeSettings().getRotation(); +- EndCityPieces.EndCityPiece endCityPiece = EndCityPieces.addHelper( +- pieces, EndCityPieces.addPiece(structureTemplateManager, piece, new BlockPos(-3, 4, -3), "fat_tower_base", rotation, true) +- ); +- EndCityPieces.EndCityPiece var13 = EndCityPieces.addHelper( +- pieces, EndCityPieces.addPiece(structureTemplateManager, endCityPiece, new BlockPos(0, 4, 0), "fat_tower_middle", rotation, true) +- ); ++ public boolean generate(StructureTemplateManager structureTemplateManager, int counter, EndCityPieces.EndCityPiece piece, BlockPos startPos, List pieces, RandomSource random) { ++ Rotation enumblockrotation = piece.placeSettings().getRotation(); ++ EndCityPieces.EndCityPiece endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, piece, new BlockPos(-3, 4, -3), "fat_tower_base", enumblockrotation, true)); + +- for (int i = 0; i < 2 && random.nextInt(3) != 0; i++) { +- var13 = EndCityPieces.addHelper( +- pieces, EndCityPieces.addPiece(structureTemplateManager, var13, new BlockPos(0, 8, 0), "fat_tower_middle", rotation, true) +- ); ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(0, 4, 0), "fat_tower_middle", enumblockrotation, true)); + +- for (Tuple tuple : EndCityPieces.FAT_TOWER_BRIDGES) { ++ for (int j = 0; j < 2 && random.nextInt(3) != 0; ++j) { ++ endcitypieces_a1 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(0, 8, 0), "fat_tower_middle", enumblockrotation, true)); ++ Iterator iterator = EndCityPieces.FAT_TOWER_BRIDGES.iterator(); ++ ++ while (iterator.hasNext()) { ++ Tuple tuple = (Tuple) iterator.next(); ++ + if (random.nextBoolean()) { +- EndCityPieces.EndCityPiece endCityPiece1 = EndCityPieces.addHelper( +- pieces, +- EndCityPieces.addPiece(structureTemplateManager, var13, tuple.getB(), "bridge_end", rotation.getRotated(tuple.getA()), true) +- ); +- EndCityPieces.recursiveChildren( +- structureTemplateManager, EndCityPieces.TOWER_BRIDGE_GENERATOR, counter + 1, endCityPiece1, null, pieces, random +- ); ++ EndCityPieces.EndCityPiece endcitypieces_a2 = EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, (BlockPos) tuple.getB(), "bridge_end", enumblockrotation.getRotated((Rotation) tuple.getA()), true)); ++ ++ EndCityPieces.recursiveChildren(structureTemplateManager, EndCityPieces.TOWER_BRIDGE_GENERATOR, counter + 1, endcitypieces_a2, (BlockPos) null, pieces, random); + } + } + } + +- endCityPiece = EndCityPieces.addHelper( +- pieces, EndCityPieces.addPiece(structureTemplateManager, var13, new BlockPos(-2, 8, -2), "fat_tower_top", rotation, true) +- ); ++ EndCityPieces.addHelper(pieces, EndCityPieces.addPiece(structureTemplateManager, endcitypieces_a1, new BlockPos(-2, 8, -2), "fat_tower_top", enumblockrotation, true)); + return true; + } + }; + +- static EndCityPieces.EndCityPiece addPiece( +- StructureTemplateManager structureTemplateManager, +- EndCityPieces.EndCityPiece piece, +- BlockPos startPos, +- String name, +- Rotation rotation, +- boolean overwrite +- ) { +- EndCityPieces.EndCityPiece endCityPiece = new EndCityPieces.EndCityPiece(structureTemplateManager, name, piece.templatePosition(), rotation, overwrite); +- BlockPos blockPos = piece.template().calculateConnectedPosition(piece.placeSettings(), startPos, endCityPiece.placeSettings(), BlockPos.ZERO); +- endCityPiece.move(blockPos.getX(), blockPos.getY(), blockPos.getZ()); +- return endCityPiece; ++ public EndCityPieces() {} ++ ++ static EndCityPieces.EndCityPiece addPiece(StructureTemplateManager structureTemplateManager, EndCityPieces.EndCityPiece piece, BlockPos startPos, String name, Rotation rotation, boolean overwrite) { ++ EndCityPieces.EndCityPiece endcitypieces_a1 = new EndCityPieces.EndCityPiece(structureTemplateManager, name, piece.templatePosition(), rotation, overwrite); ++ BlockPos blockposition1 = piece.template().calculateConnectedPosition(piece.placeSettings(), startPos, endcitypieces_a1.placeSettings(), BlockPos.ZERO); ++ ++ endcitypieces_a1.move(blockposition1.getX(), blockposition1.getY(), blockposition1.getZ()); ++ return endcitypieces_a1; + } + +- public static void startHouseTower( +- StructureTemplateManager structureTemplateManager, BlockPos startPos, Rotation rotation, List pieces, RandomSource random +- ) { +- FAT_TOWER_GENERATOR.init(); +- HOUSE_TOWER_GENERATOR.init(); +- TOWER_BRIDGE_GENERATOR.init(); +- TOWER_GENERATOR.init(); +- EndCityPieces.EndCityPiece endCityPiece = addHelper( +- pieces, new EndCityPieces.EndCityPiece(structureTemplateManager, "base_floor", startPos, rotation, true) +- ); +- endCityPiece = addHelper(pieces, addPiece(structureTemplateManager, endCityPiece, new BlockPos(-1, 0, -1), "second_floor_1", rotation, false)); +- endCityPiece = addHelper(pieces, addPiece(structureTemplateManager, endCityPiece, new BlockPos(-1, 4, -1), "third_floor_1", rotation, false)); +- endCityPiece = addHelper(pieces, addPiece(structureTemplateManager, endCityPiece, new BlockPos(-1, 8, -1), "third_roof", rotation, true)); +- recursiveChildren(structureTemplateManager, TOWER_GENERATOR, 1, endCityPiece, null, pieces, random); ++ public static void startHouseTower(StructureTemplateManager structureTemplateManager, BlockPos startPos, Rotation rotation, List pieces, RandomSource random) { ++ EndCityPieces.FAT_TOWER_GENERATOR.init(); ++ EndCityPieces.HOUSE_TOWER_GENERATOR.init(); ++ EndCityPieces.TOWER_BRIDGE_GENERATOR.init(); ++ EndCityPieces.TOWER_GENERATOR.init(); ++ EndCityPieces.EndCityPiece endcitypieces_a = addHelper(pieces, new EndCityPieces.EndCityPiece(structureTemplateManager, "base_floor", startPos, rotation, true)); ++ ++ endcitypieces_a = addHelper(pieces, addPiece(structureTemplateManager, endcitypieces_a, new BlockPos(-1, 0, -1), "second_floor_1", rotation, false)); ++ endcitypieces_a = addHelper(pieces, addPiece(structureTemplateManager, endcitypieces_a, new BlockPos(-1, 4, -1), "third_floor_1", rotation, false)); ++ endcitypieces_a = addHelper(pieces, addPiece(structureTemplateManager, endcitypieces_a, new BlockPos(-1, 8, -1), "third_roof", rotation, true)); ++ recursiveChildren(structureTemplateManager, EndCityPieces.TOWER_GENERATOR, 1, endcitypieces_a, (BlockPos) null, pieces, random); + } + + static EndCityPieces.EndCityPiece addHelper(List pieces, EndCityPieces.EndCityPiece piece) { +@@ -313,34 +211,31 @@ + return piece; + } + +- static boolean recursiveChildren( +- StructureTemplateManager structureTemplateManager, +- EndCityPieces.SectionGenerator sectionGenerator, +- int counter, +- EndCityPieces.EndCityPiece piece, +- BlockPos startPos, +- List pieces, +- RandomSource random +- ) { ++ static boolean recursiveChildren(StructureTemplateManager structureTemplateManager, EndCityPieces.SectionGenerator sectionGenerator, int counter, EndCityPieces.EndCityPiece piece, BlockPos startPos, List pieces, RandomSource random) { + if (counter > 8) { + return false; + } else { +- List list = Lists.newArrayList(); +- if (sectionGenerator.generate(structureTemplateManager, counter, piece, startPos, list, random)) { ++ List list1 = Lists.newArrayList(); ++ ++ if (sectionGenerator.generate(structureTemplateManager, counter, piece, startPos, list1, random)) { + boolean flag = false; +- int randomInt = random.nextInt(); ++ int j = random.nextInt(); ++ Iterator iterator = list1.iterator(); + +- for (StructurePiece structurePiece : list) { +- structurePiece.setGenDepth(randomInt); +- StructurePiece structurePiece1 = StructurePiece.findCollisionPiece(pieces, structurePiece.getBoundingBox()); +- if (structurePiece1 != null && structurePiece1.getGenDepth() != piece.getGenDepth()) { ++ while (iterator.hasNext()) { ++ StructurePiece structurepiece = (StructurePiece) iterator.next(); ++ ++ structurepiece.setGenDepth(j); ++ StructurePiece structurepiece1 = StructurePiece.findCollisionPiece(pieces, structurepiece.getBoundingBox()); ++ ++ if (structurepiece1 != null && structurepiece1.getGenDepth() != piece.getGenDepth()) { + flag = true; + break; + } + } + + if (!flag) { +- pieces.addAll(list); ++ pieces.addAll(list1); + return true; + } + } +@@ -350,22 +245,21 @@ + } + + public static class EndCityPiece extends TemplateStructurePiece { ++ + public EndCityPiece(StructureTemplateManager structureTemplateManager, String name, BlockPos startPos, Rotation rotation, boolean overwrite) { + super(StructurePieceType.END_CITY_PIECE, 0, structureTemplateManager, makeResourceLocation(name), name, makeSettings(overwrite, rotation), startPos); + } + + public EndCityPiece(StructureTemplateManager structureTemplateManager, CompoundTag tag) { +- super( +- StructurePieceType.END_CITY_PIECE, +- tag, +- structureTemplateManager, +- resourceLocation -> makeSettings(tag.getBoolean("OW"), Rotation.valueOf(tag.getString("Rot"))) +- ); ++ super(StructurePieceType.END_CITY_PIECE, tag, structureTemplateManager, (minecraftkey) -> { ++ return makeSettings(tag.getBoolean("OW"), Rotation.valueOf(tag.getString("Rot"))); ++ }); + } + + private static StructurePlaceSettings makeSettings(boolean overwrite, Rotation rotation) { +- BlockIgnoreProcessor blockIgnoreProcessor = overwrite ? BlockIgnoreProcessor.STRUCTURE_BLOCK : BlockIgnoreProcessor.STRUCTURE_AND_AIR; +- return new StructurePlaceSettings().setIgnoreEntities(true).addProcessor(blockIgnoreProcessor).setRotation(rotation); ++ BlockIgnoreProcessor definedstructureprocessorblockignore = overwrite ? BlockIgnoreProcessor.STRUCTURE_BLOCK : BlockIgnoreProcessor.STRUCTURE_AND_AIR; ++ ++ return (new StructurePlaceSettings()).setIgnoreEntities(true).addProcessor(definedstructureprocessorblockignore).setRotation(rotation); + } + + @Override +@@ -387,36 +281,39 @@ + @Override + protected void handleDataMarker(String name, BlockPos pos, ServerLevelAccessor level, RandomSource random, BoundingBox box) { + if (name.startsWith("Chest")) { +- BlockPos blockPos = pos.below(); +- if (box.isInside(blockPos)) { +- RandomizableContainer.setBlockEntityLootTable(level, random, blockPos, BuiltInLootTables.END_CITY_TREASURE); ++ BlockPos blockposition1 = pos.below(); ++ ++ if (box.isInside(blockposition1)) { ++ // CraftBukkit start - ensure block transformation ++ /* ++ RandomizableContainer.setBlockEntityLootTable(worldaccess, randomsource, blockposition1, LootTables.END_CITY_TREASURE); ++ */ ++ setCraftLootTable(level, blockposition1, random, BuiltInLootTables.END_CITY_TREASURE); ++ // CraftBukkit end + } + } else if (box.isInside(pos) && Level.isInSpawnableBounds(pos)) { + if (name.startsWith("Sentry")) { +- Shulker shulker = EntityType.SHULKER.create(level.getLevel()); +- if (shulker != null) { +- shulker.setPos((double)pos.getX() + 0.5, (double)pos.getY(), (double)pos.getZ() + 0.5); +- level.addFreshEntity(shulker); ++ Shulker entityshulker = (Shulker) EntityType.SHULKER.create(level.getLevel()); ++ ++ if (entityshulker != null) { ++ entityshulker.setPos((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D); ++ level.addFreshEntity(entityshulker); + } + } else if (name.startsWith("Elytra")) { +- ItemFrame itemFrame = new ItemFrame(level.getLevel(), pos, this.placeSettings.getRotation().rotate(Direction.SOUTH)); +- itemFrame.setItem(new ItemStack(Items.ELYTRA), false); +- level.addFreshEntity(itemFrame); ++ ItemFrame entityitemframe = new ItemFrame(level.getLevel(), pos, this.placeSettings.getRotation().rotate(Direction.SOUTH)); ++ ++ entityitemframe.setItem(new ItemStack(Items.ELYTRA), false); ++ level.addFreshEntity(entityitemframe); + } + } ++ + } + } + +- interface SectionGenerator { ++ private interface SectionGenerator { ++ + void init(); + +- boolean generate( +- StructureTemplateManager structureTemplateManager, +- int counter, +- EndCityPieces.EndCityPiece piece, +- BlockPos startPos, +- List pieces, +- RandomSource random +- ); ++ boolean generate(StructureTemplateManager structureTemplateManager, int counter, EndCityPieces.EndCityPiece piece, BlockPos startPos, List pieces, RandomSource random); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java.patch new file mode 100644 index 0000000000..7c12b03429 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java.patch @@ -0,0 +1,173 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java +@@ -3,6 +3,7 @@ + import com.google.common.collect.ImmutableMap; + import java.util.Map; + import net.minecraft.core.BlockPos; ++import net.minecraft.core.Vec3i; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.util.RandomSource; +@@ -13,9 +14,7 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.Mirror; + import net.minecraft.world.level.block.Rotation; +-import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.entity.ChestBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.levelgen.Heightmap; + import net.minecraft.world.level.levelgen.structure.BoundingBox; +@@ -30,64 +29,48 @@ + import net.minecraft.world.level.storage.loot.BuiltInLootTables; + + public class IglooPieces { ++ + public static final int GENERATION_HEIGHT = 90; + static final ResourceLocation STRUCTURE_LOCATION_IGLOO = new ResourceLocation("igloo/top"); + private static final ResourceLocation STRUCTURE_LOCATION_LADDER = new ResourceLocation("igloo/middle"); + private static final ResourceLocation STRUCTURE_LOCATION_LABORATORY = new ResourceLocation("igloo/bottom"); +- static final Map PIVOTS = ImmutableMap.of( +- STRUCTURE_LOCATION_IGLOO, new BlockPos(3, 5, 5), STRUCTURE_LOCATION_LADDER, new BlockPos(1, 3, 1), STRUCTURE_LOCATION_LABORATORY, new BlockPos(3, 6, 7) +- ); +- static final Map OFFSETS = ImmutableMap.of( +- STRUCTURE_LOCATION_IGLOO, BlockPos.ZERO, STRUCTURE_LOCATION_LADDER, new BlockPos(2, -3, 4), STRUCTURE_LOCATION_LABORATORY, new BlockPos(0, -3, -2) +- ); ++ static final Map PIVOTS = ImmutableMap.of(IglooPieces.STRUCTURE_LOCATION_IGLOO, new BlockPos(3, 5, 5), IglooPieces.STRUCTURE_LOCATION_LADDER, new BlockPos(1, 3, 1), IglooPieces.STRUCTURE_LOCATION_LABORATORY, new BlockPos(3, 6, 7)); ++ static final Map OFFSETS = ImmutableMap.of(IglooPieces.STRUCTURE_LOCATION_IGLOO, BlockPos.ZERO, IglooPieces.STRUCTURE_LOCATION_LADDER, new BlockPos(2, -3, 4), IglooPieces.STRUCTURE_LOCATION_LABORATORY, new BlockPos(0, -3, -2)); + +- public static void addPieces( +- StructureTemplateManager structureTemplateManager, BlockPos startPos, Rotation rotation, StructurePieceAccessor pieces, RandomSource random +- ) { +- if (random.nextDouble() < 0.5) { ++ public IglooPieces() {} ++ ++ public static void addPieces(StructureTemplateManager structureTemplateManager, BlockPos startPos, Rotation rotation, StructurePieceAccessor pieces, RandomSource random) { ++ if (random.nextDouble() < 0.5D) { + int i = random.nextInt(8) + 4; +- pieces.addPiece(new IglooPieces.IglooPiece(structureTemplateManager, STRUCTURE_LOCATION_LABORATORY, startPos, rotation, i * 3)); + +- for (int i1 = 0; i1 < i - 1; i1++) { +- pieces.addPiece(new IglooPieces.IglooPiece(structureTemplateManager, STRUCTURE_LOCATION_LADDER, startPos, rotation, i1 * 3)); ++ pieces.addPiece(new IglooPieces.IglooPiece(structureTemplateManager, IglooPieces.STRUCTURE_LOCATION_LABORATORY, startPos, rotation, i * 3)); ++ ++ for (int j = 0; j < i - 1; ++j) { ++ pieces.addPiece(new IglooPieces.IglooPiece(structureTemplateManager, IglooPieces.STRUCTURE_LOCATION_LADDER, startPos, rotation, j * 3)); + } + } + +- pieces.addPiece(new IglooPieces.IglooPiece(structureTemplateManager, STRUCTURE_LOCATION_IGLOO, startPos, rotation, 0)); ++ pieces.addPiece(new IglooPieces.IglooPiece(structureTemplateManager, IglooPieces.STRUCTURE_LOCATION_IGLOO, startPos, rotation, 0)); + } + + public static class IglooPiece extends TemplateStructurePiece { ++ + public IglooPiece(StructureTemplateManager structureTemplateManager, ResourceLocation location, BlockPos startPos, Rotation rotation, int down) { +- super( +- StructurePieceType.IGLOO, +- 0, +- structureTemplateManager, +- location, +- location.toString(), +- makeSettings(rotation, location), +- makePosition(location, startPos, down) +- ); ++ super(StructurePieceType.IGLOO, 0, structureTemplateManager, location, location.toString(), makeSettings(rotation, location), makePosition(location, startPos, down)); + } + + public IglooPiece(StructureTemplateManager structureTemplateManager, CompoundTag tag) { +- super( +- StructurePieceType.IGLOO, +- tag, +- structureTemplateManager, +- resourceLocation -> makeSettings(Rotation.valueOf(tag.getString("Rot")), resourceLocation) +- ); ++ super(StructurePieceType.IGLOO, tag, structureTemplateManager, (minecraftkey) -> { ++ return makeSettings(Rotation.valueOf(tag.getString("Rot")), minecraftkey); ++ }); + } + + private static StructurePlaceSettings makeSettings(Rotation rotation, ResourceLocation location) { +- return new StructurePlaceSettings() +- .setRotation(rotation) +- .setMirror(Mirror.NONE) +- .setRotationPivot(IglooPieces.PIVOTS.get(location)) +- .addProcessor(BlockIgnoreProcessor.STRUCTURE_BLOCK); ++ return (new StructurePlaceSettings()).setRotation(rotation).setMirror(Mirror.NONE).setRotationPivot((BlockPos) IglooPieces.PIVOTS.get(location)).addProcessor(BlockIgnoreProcessor.STRUCTURE_BLOCK); + } + + private static BlockPos makePosition(ResourceLocation location, BlockPos pos, int down) { +- return pos.offset(IglooPieces.OFFSETS.get(location)).below(down); ++ return pos.offset((Vec3i) IglooPieces.OFFSETS.get(location)).below(down); + } + + @Override +@@ -100,41 +83,41 @@ + protected void handleDataMarker(String name, BlockPos pos, ServerLevelAccessor level, RandomSource random, BoundingBox box) { + if ("chest".equals(name)) { + level.setBlock(pos, Blocks.AIR.defaultBlockState(), 3); +- BlockEntity blockEntity = level.getBlockEntity(pos.below()); +- if (blockEntity instanceof ChestBlockEntity) { +- ((ChestBlockEntity)blockEntity).setLootTable(BuiltInLootTables.IGLOO_CHEST, random.nextLong()); ++ // CraftBukkit start - ensure block transformation ++ /* ++ TileEntity tileentity = worldaccess.getBlockEntity(blockposition.below()); ++ ++ if (tileentity instanceof TileEntityChest) { ++ ((TileEntityChest) tileentity).setLootTable(LootTables.IGLOO_CHEST, randomsource.nextLong()); + } ++ */ ++ setCraftLootTable(level, pos.below(), random, BuiltInLootTables.IGLOO_CHEST); ++ // CraftBukkit end ++ + } + } + + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { +- ResourceLocation resourceLocation = new ResourceLocation(this.templateName); +- StructurePlaceSettings structurePlaceSettings = makeSettings(this.placeSettings.getRotation(), resourceLocation); +- BlockPos blockPos = IglooPieces.OFFSETS.get(resourceLocation); +- BlockPos blockPos1 = this.templatePosition +- .offset(StructureTemplate.calculateRelativePosition(structurePlaceSettings, new BlockPos(3 - blockPos.getX(), 0, -blockPos.getZ()))); +- int height = level.getHeight(Heightmap.Types.WORLD_SURFACE_WG, blockPos1.getX(), blockPos1.getZ()); +- BlockPos blockPos2 = this.templatePosition; +- this.templatePosition = this.templatePosition.offset(0, height - 90 - 1, 0); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ ResourceLocation minecraftkey = new ResourceLocation(this.templateName); ++ StructurePlaceSettings definedstructureinfo = makeSettings(this.placeSettings.getRotation(), minecraftkey); ++ BlockPos blockposition1 = (BlockPos) IglooPieces.OFFSETS.get(minecraftkey); ++ BlockPos blockposition2 = this.templatePosition.offset(StructureTemplate.calculateRelativePosition(definedstructureinfo, new BlockPos(3 - blockposition1.getX(), 0, -blockposition1.getZ()))); ++ int i = level.getHeight(Heightmap.Types.WORLD_SURFACE_WG, blockposition2.getX(), blockposition2.getZ()); ++ BlockPos blockposition3 = this.templatePosition; ++ ++ this.templatePosition = this.templatePosition.offset(0, i - 90 - 1, 0); + super.postProcess(level, structureManager, generator, random, box, chunkPos, pos); +- if (resourceLocation.equals(IglooPieces.STRUCTURE_LOCATION_IGLOO)) { +- BlockPos blockPos3 = this.templatePosition.offset(StructureTemplate.calculateRelativePosition(structurePlaceSettings, new BlockPos(3, 0, 5))); +- BlockState blockState = level.getBlockState(blockPos3.below()); +- if (!blockState.isAir() && !blockState.is(Blocks.LADDER)) { +- level.setBlock(blockPos3, Blocks.SNOW_BLOCK.defaultBlockState(), 3); ++ if (minecraftkey.equals(IglooPieces.STRUCTURE_LOCATION_IGLOO)) { ++ BlockPos blockposition4 = this.templatePosition.offset(StructureTemplate.calculateRelativePosition(definedstructureinfo, new BlockPos(3, 0, 5))); ++ IBlockData iblockdata = level.getBlockState(blockposition4.below()); ++ ++ if (!iblockdata.isAir() && !iblockdata.is(Blocks.LADDER)) { ++ level.setBlock(blockposition4, Blocks.SNOW_BLOCK.defaultBlockState(), 3); + } + } + +- this.templatePosition = blockPos2; ++ this.templatePosition = blockposition3; + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java.patch new file mode 100644 index 0000000000..77d27d7777 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java.patch @@ -0,0 +1,1785 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java +@@ -2,7 +2,11 @@ + + import com.google.common.collect.Lists; + import com.mojang.logging.LogUtils; ++import com.mojang.serialization.DataResult; ++import java.util.Iterator; + import java.util.List; ++import java.util.Objects; ++import java.util.Optional; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +@@ -12,7 +16,6 @@ + import net.minecraft.resources.ResourceLocation; + import net.minecraft.tags.BiomeTags; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.vehicle.MinecartChest; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.ChunkPos; +@@ -26,8 +29,7 @@ + import net.minecraft.world.level.block.FenceBlock; + import net.minecraft.world.level.block.RailBlock; + import net.minecraft.world.level.block.WallTorchBlock; +-import net.minecraft.world.level.block.entity.SpawnerBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.RailShape; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.levelgen.structure.BoundingBox; +@@ -39,6 +41,7 @@ + import org.slf4j.Logger; + + public class MineshaftPieces { ++ + static final Logger LOGGER = LogUtils.getLogger(); + private static final int DEFAULT_SHAFT_WIDTH = 3; + private static final int DEFAULT_SHAFT_HEIGHT = 3; +@@ -48,50 +51,265 @@ + private static final int MAX_DEPTH = 8; + public static final int MAGIC_START_Y = 50; + +- private static MineshaftPieces.MineShaftPiece createRandomShaftPiece( +- StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, @Nullable Direction orientation, int genDepth, MineshaftStructure.Type type +- ) { +- int randomInt = random.nextInt(100); +- if (randomInt >= 80) { +- BoundingBox boundingBox = MineshaftPieces.MineShaftCrossing.findCrossing(pieces, random, x, y, z, orientation); +- if (boundingBox != null) { +- return new MineshaftPieces.MineShaftCrossing(genDepth, boundingBox, orientation, type); ++ public MineshaftPieces() {} ++ ++ private static MineshaftPieces.MineShaftPiece createRandomShaftPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, @Nullable Direction orientation, int genDepth, MineshaftStructure.Type type) { ++ int i1 = random.nextInt(100); ++ BoundingBox structureboundingbox; ++ ++ if (i1 >= 80) { ++ structureboundingbox = MineshaftPieces.MineShaftCrossing.findCrossing(pieces, random, x, y, z, orientation); ++ if (structureboundingbox != null) { ++ return new MineshaftPieces.MineShaftCrossing(genDepth, structureboundingbox, orientation, type); + } +- } else if (randomInt >= 70) { +- BoundingBox boundingBox = MineshaftPieces.MineShaftStairs.findStairs(pieces, random, x, y, z, orientation); +- if (boundingBox != null) { +- return new MineshaftPieces.MineShaftStairs(genDepth, boundingBox, orientation, type); ++ } else if (i1 >= 70) { ++ structureboundingbox = MineshaftPieces.MineShaftStairs.findStairs(pieces, random, x, y, z, orientation); ++ if (structureboundingbox != null) { ++ return new MineshaftPieces.MineShaftStairs(genDepth, structureboundingbox, orientation, type); + } + } else { +- BoundingBox boundingBox = MineshaftPieces.MineShaftCorridor.findCorridorSize(pieces, random, x, y, z, orientation); +- if (boundingBox != null) { +- return new MineshaftPieces.MineShaftCorridor(genDepth, random, boundingBox, orientation, type); ++ structureboundingbox = MineshaftPieces.MineShaftCorridor.findCorridorSize(pieces, random, x, y, z, orientation); ++ if (structureboundingbox != null) { ++ return new MineshaftPieces.MineShaftCorridor(genDepth, random, structureboundingbox, orientation, type); + } + } + + return null; + } + +- static MineshaftPieces.MineShaftPiece generateAndAddPiece( +- StructurePiece piece, StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction direction, int genDepth +- ) { ++ static MineshaftPieces.MineShaftPiece generateAndAddPiece(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction direction, int genDepth) { + if (genDepth > 8) { + return null; + } else if (Math.abs(x - piece.getBoundingBox().minX()) <= 80 && Math.abs(z - piece.getBoundingBox().minZ()) <= 80) { +- MineshaftStructure.Type type = ((MineshaftPieces.MineShaftPiece)piece).type; +- MineshaftPieces.MineShaftPiece mineShaftPiece = createRandomShaftPiece(pieces, random, x, y, z, direction, genDepth + 1, type); +- if (mineShaftPiece != null) { +- pieces.addPiece(mineShaftPiece); +- mineShaftPiece.addChildren(piece, pieces, random); ++ MineshaftStructure.Type mineshaftstructure_a = ((MineshaftPieces.MineShaftPiece) piece).type; ++ MineshaftPieces.MineShaftPiece mineshaftpieces_c = createRandomShaftPiece(pieces, random, x, y, z, direction, genDepth + 1, mineshaftstructure_a); ++ ++ if (mineshaftpieces_c != null) { ++ pieces.addPiece(mineshaftpieces_c); ++ mineshaftpieces_c.addChildren(piece, pieces, random); + } + +- return mineShaftPiece; ++ return mineshaftpieces_c; + } else { + return null; + } + } + ++ public static class MineShaftCrossing extends MineshaftPieces.MineShaftPiece { ++ ++ private final Direction direction; ++ private final boolean isTwoFloored; ++ ++ public MineShaftCrossing(CompoundTag tag) { ++ super(StructurePieceType.MINE_SHAFT_CROSSING, tag); ++ this.isTwoFloored = tag.getBoolean("tf"); ++ this.direction = Direction.from2DDataValue(tag.getInt("D")); ++ } ++ ++ @Override ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putBoolean("tf", this.isTwoFloored); ++ tag.putInt("D", this.direction.get2DDataValue()); ++ } ++ ++ public MineShaftCrossing(int genDepth, BoundingBox boundingBox, @Nullable Direction direction, MineshaftStructure.Type type) { ++ super(StructurePieceType.MINE_SHAFT_CROSSING, genDepth, type, boundingBox); ++ this.direction = direction; ++ this.isTwoFloored = boundingBox.getYSpan() > 3; ++ } ++ ++ @Nullable ++ public static BoundingBox findCrossing(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction direction) { ++ byte b0; ++ ++ if (random.nextInt(4) == 0) { ++ b0 = 6; ++ } else { ++ b0 = 2; ++ } ++ ++ BoundingBox structureboundingbox; ++ ++ switch (direction) { ++ case NORTH: ++ default: ++ structureboundingbox = new BoundingBox(-1, 0, -4, 3, b0, 0); ++ break; ++ case SOUTH: ++ structureboundingbox = new BoundingBox(-1, 0, 0, 3, b0, 4); ++ break; ++ case WEST: ++ structureboundingbox = new BoundingBox(-4, 0, -1, 0, b0, 3); ++ break; ++ case EAST: ++ structureboundingbox = new BoundingBox(0, 0, -1, 4, b0, 3); ++ } ++ ++ structureboundingbox.move(x, y, z); ++ return pieces.findCollisionPiece(structureboundingbox) != null ? null : structureboundingbox; ++ } ++ ++ @Override ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ int i = this.getGenDepth(); ++ ++ switch (this.direction) { ++ case NORTH: ++ default: ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() - 1, Direction.NORTH, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.WEST, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.EAST, i); ++ break; ++ case SOUTH: ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.maxZ() + 1, Direction.SOUTH, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.WEST, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.EAST, i); ++ break; ++ case WEST: ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() - 1, Direction.NORTH, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.maxZ() + 1, Direction.SOUTH, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.WEST, i); ++ break; ++ case EAST: ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() - 1, Direction.NORTH, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.maxZ() + 1, Direction.SOUTH, i); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.EAST, i); ++ } ++ ++ if (this.isTwoFloored) { ++ if (random.nextBoolean()) { ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY() + 3 + 1, this.boundingBox.minZ() - 1, Direction.NORTH, i); ++ } ++ ++ if (random.nextBoolean()) { ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() + 3 + 1, this.boundingBox.minZ() + 1, Direction.WEST, i); ++ } ++ ++ if (random.nextBoolean()) { ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() + 3 + 1, this.boundingBox.minZ() + 1, Direction.EAST, i); ++ } ++ ++ if (random.nextBoolean()) { ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY() + 3 + 1, this.boundingBox.maxZ() + 1, Direction.SOUTH, i); ++ } ++ } ++ ++ } ++ ++ @Override ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ if (!this.isInInvalidLocation(level, box)) { ++ IBlockData iblockdata = this.type.getPlanksState(); ++ ++ if (this.isTwoFloored) { ++ this.generateBox(level, box, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ(), this.boundingBox.maxX() - 1, this.boundingBox.minY() + 3 - 1, this.boundingBox.maxZ(), MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, this.boundingBox.minX(), this.boundingBox.minY(), this.boundingBox.minZ() + 1, this.boundingBox.maxX(), this.boundingBox.minY() + 3 - 1, this.boundingBox.maxZ() - 1, MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, this.boundingBox.minX() + 1, this.boundingBox.maxY() - 2, this.boundingBox.minZ(), this.boundingBox.maxX() - 1, this.boundingBox.maxY(), this.boundingBox.maxZ(), MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, this.boundingBox.minX(), this.boundingBox.maxY() - 2, this.boundingBox.minZ() + 1, this.boundingBox.maxX(), this.boundingBox.maxY(), this.boundingBox.maxZ() - 1, MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, this.boundingBox.minX() + 1, this.boundingBox.minY() + 3, this.boundingBox.minZ() + 1, this.boundingBox.maxX() - 1, this.boundingBox.minY() + 3, this.boundingBox.maxZ() - 1, MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); ++ } else { ++ this.generateBox(level, box, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ(), this.boundingBox.maxX() - 1, this.boundingBox.maxY(), this.boundingBox.maxZ(), MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, this.boundingBox.minX(), this.boundingBox.minY(), this.boundingBox.minZ() + 1, this.boundingBox.maxX(), this.boundingBox.maxY(), this.boundingBox.maxZ() - 1, MineshaftPieces.MineShaftCrossing.CAVE_AIR, MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); ++ } ++ ++ this.placeSupportPillar(level, box, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, this.boundingBox.maxY()); ++ this.placeSupportPillar(level, box, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.maxZ() - 1, this.boundingBox.maxY()); ++ this.placeSupportPillar(level, box, this.boundingBox.maxX() - 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, this.boundingBox.maxY()); ++ this.placeSupportPillar(level, box, this.boundingBox.maxX() - 1, this.boundingBox.minY(), this.boundingBox.maxZ() - 1, this.boundingBox.maxY()); ++ int i = this.boundingBox.minY() - 1; ++ ++ for (int j = this.boundingBox.minX(); j <= this.boundingBox.maxX(); ++j) { ++ for (int k = this.boundingBox.minZ(); k <= this.boundingBox.maxZ(); ++k) { ++ this.setPlanksBlock(level, box, iblockdata, j, i, k); ++ } ++ } ++ ++ } ++ } ++ ++ private void placeSupportPillar(WorldGenLevel level, BoundingBox box, int x, int y, int z, int maxY) { ++ if (!this.getBlock(level, x, maxY + 1, z, box).isAir()) { ++ this.generateBox(level, box, x, y, z, x, maxY, z, this.type.getPlanksState(), MineshaftPieces.MineShaftCrossing.CAVE_AIR, false); ++ } ++ ++ } ++ } ++ ++ public static class MineShaftStairs extends MineshaftPieces.MineShaftPiece { ++ ++ public MineShaftStairs(int genDepth, BoundingBox boundingBox, Direction orientation, MineshaftStructure.Type type) { ++ super(StructurePieceType.MINE_SHAFT_STAIRS, genDepth, type, boundingBox); ++ this.setOrientation(orientation); ++ } ++ ++ public MineShaftStairs(CompoundTag tag) { ++ super(StructurePieceType.MINE_SHAFT_STAIRS, tag); ++ } ++ ++ @Nullable ++ public static BoundingBox findStairs(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction direction) { ++ BoundingBox structureboundingbox; ++ ++ switch (direction) { ++ case NORTH: ++ default: ++ structureboundingbox = new BoundingBox(0, -5, -8, 2, 2, 0); ++ break; ++ case SOUTH: ++ structureboundingbox = new BoundingBox(0, -5, 0, 2, 2, 8); ++ break; ++ case WEST: ++ structureboundingbox = new BoundingBox(-8, -5, 0, 0, 2, 2); ++ break; ++ case EAST: ++ structureboundingbox = new BoundingBox(0, -5, 0, 8, 2, 2); ++ } ++ ++ structureboundingbox.move(x, y, z); ++ return pieces.findCollisionPiece(structureboundingbox) != null ? null : structureboundingbox; ++ } ++ ++ @Override ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ int i = this.getGenDepth(); ++ Direction enumdirection = this.getOrientation(); ++ ++ if (enumdirection != null) { ++ switch (enumdirection) { ++ case NORTH: ++ default: ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX(), this.boundingBox.minY(), this.boundingBox.minZ() - 1, Direction.NORTH, i); ++ break; ++ case SOUTH: ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX(), this.boundingBox.minY(), this.boundingBox.maxZ() + 1, Direction.SOUTH, i); ++ break; ++ case WEST: ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY(), this.boundingBox.minZ(), Direction.WEST, i); ++ break; ++ case EAST: ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY(), this.boundingBox.minZ(), Direction.EAST, i); ++ } ++ } ++ ++ } ++ ++ @Override ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ if (!this.isInInvalidLocation(level, box)) { ++ this.generateBox(level, box, 0, 5, 0, 2, 7, 1, MineshaftPieces.MineShaftStairs.CAVE_AIR, MineshaftPieces.MineShaftStairs.CAVE_AIR, false); ++ this.generateBox(level, box, 0, 0, 7, 2, 2, 8, MineshaftPieces.MineShaftStairs.CAVE_AIR, MineshaftPieces.MineShaftStairs.CAVE_AIR, false); ++ ++ for (int i = 0; i < 5; ++i) { ++ this.generateBox(level, box, 0, 5 - i - (i < 4 ? 1 : 0), 2 + i, 2, 7 - i, 2 + i, MineshaftPieces.MineShaftStairs.CAVE_AIR, MineshaftPieces.MineShaftStairs.CAVE_AIR, false); ++ } ++ ++ } ++ } ++ } ++ + public static class MineShaftCorridor extends MineshaftPieces.MineShaftPiece { ++ + private final boolean hasRails; + private final boolean spiderCorridor; + private boolean hasPlacedSpider; +@@ -124,23 +342,34 @@ + } else { + this.numSections = boundingBox.getXSpan() / 5; + } ++ + } + + @Nullable + public static BoundingBox findCorridorSize(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction direction) { +- for (int i = random.nextInt(3) + 2; i > 0; i--) { +- int i1 = i * 5; ++ for (int l = random.nextInt(3) + 2; l > 0; --l) { ++ int i1 = l * 5; ++ BoundingBox structureboundingbox; + +- BoundingBox boundingBox = switch (direction) { +- default -> new BoundingBox(0, 0, -(i1 - 1), 2, 2, 0); +- case SOUTH -> new BoundingBox(0, 0, 0, 2, 2, i1 - 1); +- case WEST -> new BoundingBox(-(i1 - 1), 0, 0, 0, 2, 2); +- case EAST -> new BoundingBox(0, 0, 0, i1 - 1, 2, 2); +- }; +- boundingBox.move(x, y, z); +- if (pieces.findCollisionPiece(boundingBox) == null) { +- return boundingBox; ++ switch (direction) { ++ case NORTH: ++ default: ++ structureboundingbox = new BoundingBox(0, 0, -(i1 - 1), 2, 2, 0); ++ break; ++ case SOUTH: ++ structureboundingbox = new BoundingBox(0, 0, 0, 2, 2, i1 - 1); ++ break; ++ case WEST: ++ structureboundingbox = new BoundingBox(-(i1 - 1), 0, 0, 0, 2, 2); ++ break; ++ case EAST: ++ structureboundingbox = new BoundingBox(0, 0, 0, i1 - 1, 2, 2); + } ++ ++ structureboundingbox.move(x, y, z); ++ if (pieces.findCollisionPiece(structureboundingbox) == null) { ++ return structureboundingbox; ++ } + } + + return null; +@@ -148,202 +377,90 @@ + + @Override + public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- int genDepth = this.getGenDepth(); +- int randomInt = random.nextInt(4); +- Direction orientation = this.getOrientation(); +- if (orientation != null) { +- switch (orientation) { ++ int i = this.getGenDepth(); ++ int j = random.nextInt(4); ++ Direction enumdirection = this.getOrientation(); ++ ++ if (enumdirection != null) { ++ switch (enumdirection) { + case NORTH: + default: +- if (randomInt <= 1) { +- MineshaftPieces.generateAndAddPiece( +- piece, +- pieces, +- random, +- this.boundingBox.minX(), +- this.boundingBox.minY() - 1 + random.nextInt(3), +- this.boundingBox.minZ() - 1, +- orientation, +- genDepth +- ); +- } else if (randomInt == 2) { +- MineshaftPieces.generateAndAddPiece( +- piece, +- pieces, +- random, +- this.boundingBox.minX() - 1, +- this.boundingBox.minY() - 1 + random.nextInt(3), +- this.boundingBox.minZ(), +- Direction.WEST, +- genDepth +- ); ++ if (j <= 1) { ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX(), this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.minZ() - 1, enumdirection, i); ++ } else if (j == 2) { ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.minZ(), Direction.WEST, i); + } else { +- MineshaftPieces.generateAndAddPiece( +- piece, +- pieces, +- random, +- this.boundingBox.maxX() + 1, +- this.boundingBox.minY() - 1 + random.nextInt(3), +- this.boundingBox.minZ(), +- Direction.EAST, +- genDepth +- ); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.minZ(), Direction.EAST, i); + } + break; + case SOUTH: +- if (randomInt <= 1) { +- MineshaftPieces.generateAndAddPiece( +- piece, +- pieces, +- random, +- this.boundingBox.minX(), +- this.boundingBox.minY() - 1 + random.nextInt(3), +- this.boundingBox.maxZ() + 1, +- orientation, +- genDepth +- ); +- } else if (randomInt == 2) { +- MineshaftPieces.generateAndAddPiece( +- piece, +- pieces, +- random, +- this.boundingBox.minX() - 1, +- this.boundingBox.minY() - 1 + random.nextInt(3), +- this.boundingBox.maxZ() - 3, +- Direction.WEST, +- genDepth +- ); ++ if (j <= 1) { ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX(), this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.maxZ() + 1, enumdirection, i); ++ } else if (j == 2) { ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.maxZ() - 3, Direction.WEST, i); + } else { +- MineshaftPieces.generateAndAddPiece( +- piece, +- pieces, +- random, +- this.boundingBox.maxX() + 1, +- this.boundingBox.minY() - 1 + random.nextInt(3), +- this.boundingBox.maxZ() - 3, +- Direction.EAST, +- genDepth +- ); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.maxZ() - 3, Direction.EAST, i); + } + break; + case WEST: +- if (randomInt <= 1) { +- MineshaftPieces.generateAndAddPiece( +- piece, +- pieces, +- random, +- this.boundingBox.minX() - 1, +- this.boundingBox.minY() - 1 + random.nextInt(3), +- this.boundingBox.minZ(), +- orientation, +- genDepth +- ); +- } else if (randomInt == 2) { +- MineshaftPieces.generateAndAddPiece( +- piece, +- pieces, +- random, +- this.boundingBox.minX(), +- this.boundingBox.minY() - 1 + random.nextInt(3), +- this.boundingBox.minZ() - 1, +- Direction.NORTH, +- genDepth +- ); ++ if (j <= 1) { ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.minZ(), enumdirection, i); ++ } else if (j == 2) { ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX(), this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.minZ() - 1, Direction.NORTH, i); + } else { +- MineshaftPieces.generateAndAddPiece( +- piece, +- pieces, +- random, +- this.boundingBox.minX(), +- this.boundingBox.minY() - 1 + random.nextInt(3), +- this.boundingBox.maxZ() + 1, +- Direction.SOUTH, +- genDepth +- ); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX(), this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.maxZ() + 1, Direction.SOUTH, i); + } + break; + case EAST: +- if (randomInt <= 1) { +- MineshaftPieces.generateAndAddPiece( +- piece, +- pieces, +- random, +- this.boundingBox.maxX() + 1, +- this.boundingBox.minY() - 1 + random.nextInt(3), +- this.boundingBox.minZ(), +- orientation, +- genDepth +- ); +- } else if (randomInt == 2) { +- MineshaftPieces.generateAndAddPiece( +- piece, +- pieces, +- random, +- this.boundingBox.maxX() - 3, +- this.boundingBox.minY() - 1 + random.nextInt(3), +- this.boundingBox.minZ() - 1, +- Direction.NORTH, +- genDepth +- ); ++ if (j <= 1) { ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.minZ(), enumdirection, i); ++ } else if (j == 2) { ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() - 3, this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.minZ() - 1, Direction.NORTH, i); + } else { +- MineshaftPieces.generateAndAddPiece( +- piece, +- pieces, +- random, +- this.boundingBox.maxX() - 3, +- this.boundingBox.minY() - 1 + random.nextInt(3), +- this.boundingBox.maxZ() + 1, +- Direction.SOUTH, +- genDepth +- ); ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() - 3, this.boundingBox.minY() - 1 + random.nextInt(3), this.boundingBox.maxZ() + 1, Direction.SOUTH, i); + } + } + } + +- if (genDepth < 8) { +- if (orientation != Direction.NORTH && orientation != Direction.SOUTH) { +- for (int i = this.boundingBox.minX() + 3; i + 3 <= this.boundingBox.maxX(); i += 5) { +- int randomInt1 = random.nextInt(5); +- if (randomInt1 == 0) { +- MineshaftPieces.generateAndAddPiece( +- piece, pieces, random, i, this.boundingBox.minY(), this.boundingBox.minZ() - 1, Direction.NORTH, genDepth + 1 +- ); +- } else if (randomInt1 == 1) { +- MineshaftPieces.generateAndAddPiece( +- piece, pieces, random, i, this.boundingBox.minY(), this.boundingBox.maxZ() + 1, Direction.SOUTH, genDepth + 1 +- ); ++ if (i < 8) { ++ int k; ++ int l; ++ ++ if (enumdirection != Direction.NORTH && enumdirection != Direction.SOUTH) { ++ for (l = this.boundingBox.minX() + 3; l + 3 <= this.boundingBox.maxX(); l += 5) { ++ k = random.nextInt(5); ++ if (k == 0) { ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, l, this.boundingBox.minY(), this.boundingBox.minZ() - 1, Direction.NORTH, i + 1); ++ } else if (k == 1) { ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, l, this.boundingBox.minY(), this.boundingBox.maxZ() + 1, Direction.SOUTH, i + 1); + } + } + } else { +- for (int ix = this.boundingBox.minZ() + 3; ix + 3 <= this.boundingBox.maxZ(); ix += 5) { +- int randomInt1 = random.nextInt(5); +- if (randomInt1 == 0) { +- MineshaftPieces.generateAndAddPiece( +- piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY(), ix, Direction.WEST, genDepth + 1 +- ); +- } else if (randomInt1 == 1) { +- MineshaftPieces.generateAndAddPiece( +- piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY(), ix, Direction.EAST, genDepth + 1 +- ); ++ for (l = this.boundingBox.minZ() + 3; l + 3 <= this.boundingBox.maxZ(); l += 5) { ++ k = random.nextInt(5); ++ if (k == 0) { ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY(), l, Direction.WEST, i + 1); ++ } else if (k == 1) { ++ MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY(), l, Direction.EAST, i + 1); + } + } + } + } ++ + } + + @Override + protected boolean createChest(WorldGenLevel level, BoundingBox box, RandomSource random, int x, int y, int z, ResourceLocation lootTable) { +- BlockPos worldPos = this.getWorldPos(x, y, z); +- if (box.isInside(worldPos) && level.getBlockState(worldPos).isAir() && !level.getBlockState(worldPos.below()).isAir()) { +- BlockState blockState = Blocks.RAIL +- .defaultBlockState() +- .setValue(RailBlock.SHAPE, random.nextBoolean() ? RailShape.NORTH_SOUTH : RailShape.EAST_WEST); +- this.placeBlock(level, blockState, x, y, z, box); +- MinecartChest minecartChest = new MinecartChest( +- level.getLevel(), (double)worldPos.getX() + 0.5, (double)worldPos.getY() + 0.5, (double)worldPos.getZ() + 0.5 +- ); +- minecartChest.setLootTable(lootTable, random.nextLong()); +- level.addFreshEntity(minecartChest); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y, z); ++ ++ if (box.isInside(blockposition_mutableblockposition) && level.getBlockState(blockposition_mutableblockposition).isAir() && !level.getBlockState(blockposition_mutableblockposition.below()).isAir()) { ++ IBlockData iblockdata = (IBlockData) Blocks.RAIL.defaultBlockState().setValue(RailBlock.SHAPE, random.nextBoolean() ? RailShape.NORTH_SOUTH : RailShape.EAST_WEST); ++ ++ this.placeBlock(level, iblockdata, x, y, z, box); ++ MinecartChest entityminecartchest = new MinecartChest(level.getLevel(), (double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY() + 0.5D, (double) blockposition_mutableblockposition.getZ() + 0.5D); ++ ++ entityminecartchest.setLootTable(lootTable, random.nextLong()); ++ level.addFreshEntity(entityminecartchest); + return true; + } else { + return false; +@@ -351,201 +468,205 @@ + } + + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { + if (!this.isInInvalidLocation(level, box)) { +- int i = 0; +- int i1 = 2; +- int i2 = 0; +- int i3 = 2; +- int i4 = this.numSections * 5 - 1; +- BlockState planksState = this.type.getPlanksState(); +- this.generateBox(level, box, 0, 0, 0, 2, 1, i4, CAVE_AIR, CAVE_AIR, false); +- this.generateMaybeBox(level, box, random, 0.8F, 0, 2, 0, 2, 2, i4, CAVE_AIR, CAVE_AIR, false, false); ++ boolean flag = false; ++ boolean flag1 = true; ++ boolean flag2 = false; ++ boolean flag3 = true; ++ int i = this.numSections * 5 - 1; ++ IBlockData iblockdata = this.type.getPlanksState(); ++ ++ this.generateBox(level, box, 0, 0, 0, 2, 1, i, MineshaftPieces.MineShaftCorridor.CAVE_AIR, MineshaftPieces.MineShaftCorridor.CAVE_AIR, false); ++ this.generateMaybeBox(level, box, random, 0.8F, 0, 2, 0, 2, 2, i, MineshaftPieces.MineShaftCorridor.CAVE_AIR, MineshaftPieces.MineShaftCorridor.CAVE_AIR, false, false); + if (this.spiderCorridor) { +- this.generateMaybeBox(level, box, random, 0.6F, 0, 0, 0, 2, 1, i4, Blocks.COBWEB.defaultBlockState(), CAVE_AIR, false, true); ++ this.generateMaybeBox(level, box, random, 0.6F, 0, 0, 0, 2, 1, i, Blocks.COBWEB.defaultBlockState(), MineshaftPieces.MineShaftCorridor.CAVE_AIR, false, true); + } + +- for (int i5 = 0; i5 < this.numSections; i5++) { +- int i6 = 2 + i5 * 5; +- this.placeSupport(level, box, 0, 0, i6, 2, 2, random); +- this.maybePlaceCobWeb(level, box, random, 0.1F, 0, 2, i6 - 1); +- this.maybePlaceCobWeb(level, box, random, 0.1F, 2, 2, i6 - 1); +- this.maybePlaceCobWeb(level, box, random, 0.1F, 0, 2, i6 + 1); +- this.maybePlaceCobWeb(level, box, random, 0.1F, 2, 2, i6 + 1); +- this.maybePlaceCobWeb(level, box, random, 0.05F, 0, 2, i6 - 2); +- this.maybePlaceCobWeb(level, box, random, 0.05F, 2, 2, i6 - 2); +- this.maybePlaceCobWeb(level, box, random, 0.05F, 0, 2, i6 + 2); +- this.maybePlaceCobWeb(level, box, random, 0.05F, 2, 2, i6 + 2); ++ int j; ++ int k; ++ ++ for (k = 0; k < this.numSections; ++k) { ++ j = 2 + k * 5; ++ this.placeSupport(level, box, 0, 0, j, 2, 2, random); ++ this.maybePlaceCobWeb(level, box, random, 0.1F, 0, 2, j - 1); ++ this.maybePlaceCobWeb(level, box, random, 0.1F, 2, 2, j - 1); ++ this.maybePlaceCobWeb(level, box, random, 0.1F, 0, 2, j + 1); ++ this.maybePlaceCobWeb(level, box, random, 0.1F, 2, 2, j + 1); ++ this.maybePlaceCobWeb(level, box, random, 0.05F, 0, 2, j - 2); ++ this.maybePlaceCobWeb(level, box, random, 0.05F, 2, 2, j - 2); ++ this.maybePlaceCobWeb(level, box, random, 0.05F, 0, 2, j + 2); ++ this.maybePlaceCobWeb(level, box, random, 0.05F, 2, 2, j + 2); + if (random.nextInt(100) == 0) { +- this.createChest(level, box, random, 2, 0, i6 - 1, BuiltInLootTables.ABANDONED_MINESHAFT); ++ this.createChest(level, box, random, 2, 0, j - 1, BuiltInLootTables.ABANDONED_MINESHAFT); + } + + if (random.nextInt(100) == 0) { +- this.createChest(level, box, random, 0, 0, i6 + 1, BuiltInLootTables.ABANDONED_MINESHAFT); ++ this.createChest(level, box, random, 0, 0, j + 1, BuiltInLootTables.ABANDONED_MINESHAFT); + } + + if (this.spiderCorridor && !this.hasPlacedSpider) { +- int i7 = 1; +- int i8 = i6 - 1 + random.nextInt(3); +- BlockPos worldPos = this.getWorldPos(1, 0, i8); +- if (box.isInside(worldPos) && this.isInterior(level, 1, 0, i8, box)) { ++ boolean flag4 = true; ++ int l = j - 1 + random.nextInt(3); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(1, 0, l); ++ ++ if (box.isInside(blockposition_mutableblockposition) && this.isInterior(level, 1, 0, l, box)) { + this.hasPlacedSpider = true; +- level.setBlock(worldPos, Blocks.SPAWNER.defaultBlockState(), 2); +- if (level.getBlockEntity(worldPos) instanceof SpawnerBlockEntity spawnerBlockEntity) { +- spawnerBlockEntity.setEntityId(EntityType.CAVE_SPIDER, random); ++ // CraftBukkit start ++ /* ++ generatoraccessseed.setBlock(blockposition_mutableblockposition, Blocks.SPAWNER.defaultBlockState(), 2); ++ TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); ++ ++ if (tileentity instanceof TileEntityMobSpawner) { ++ TileEntityMobSpawner tileentitymobspawner = (TileEntityMobSpawner) tileentity; ++ ++ tileentitymobspawner.setEntityId(EntityTypes.CAVE_SPIDER, randomsource); + } ++ */ ++ placeCraftSpawner(level, blockposition_mutableblockposition, org.bukkit.entity.EntityType.CAVE_SPIDER, 2); ++ // CraftBukkit end + } + } + } + +- for (int i5 = 0; i5 <= 2; i5++) { +- for (int i6x = 0; i6x <= i4; i6x++) { +- this.setPlanksBlock(level, box, planksState, i5, -1, i6x); ++ for (k = 0; k <= 2; ++k) { ++ for (j = 0; j <= i; ++j) { ++ this.setPlanksBlock(level, box, iblockdata, k, -1, j); + } + } + +- int i5 = 2; ++ boolean flag5 = true; ++ + this.placeDoubleLowerOrUpperSupport(level, box, 0, -1, 2); + if (this.numSections > 1) { +- int i6x = i4 - 2; +- this.placeDoubleLowerOrUpperSupport(level, box, 0, -1, i6x); ++ j = i - 2; ++ this.placeDoubleLowerOrUpperSupport(level, box, 0, -1, j); + } + + if (this.hasRails) { +- BlockState blockState = Blocks.RAIL.defaultBlockState().setValue(RailBlock.SHAPE, RailShape.NORTH_SOUTH); ++ IBlockData iblockdata1 = (IBlockData) Blocks.RAIL.defaultBlockState().setValue(RailBlock.SHAPE, RailShape.NORTH_SOUTH); + +- for (int i7 = 0; i7 <= i4; i7++) { +- BlockState block = this.getBlock(level, 1, -1, i7, box); +- if (!block.isAir() && block.isSolidRender(level, this.getWorldPos(1, -1, i7))) { +- float f = this.isInterior(level, 1, 0, i7, box) ? 0.7F : 0.9F; +- this.maybeGenerateBlock(level, box, random, f, 1, 0, i7, blockState); ++ for (int i1 = 0; i1 <= i; ++i1) { ++ IBlockData iblockdata2 = this.getBlock(level, 1, -1, i1, box); ++ ++ if (!iblockdata2.isAir() && iblockdata2.isSolidRender(level, this.getWorldPos(1, -1, i1))) { ++ float f = this.isInterior(level, 1, 0, i1, box) ? 0.7F : 0.9F; ++ ++ this.maybeGenerateBlock(level, box, random, f, 1, 0, i1, iblockdata1); + } + } + } ++ + } + } + + private void placeDoubleLowerOrUpperSupport(WorldGenLevel level, BoundingBox box, int x, int y, int z) { +- BlockState woodState = this.type.getWoodState(); +- BlockState planksState = this.type.getPlanksState(); +- if (this.getBlock(level, x, y, z, box).is(planksState.getBlock())) { +- this.fillPillarDownOrChainUp(level, woodState, x, y, z, box); ++ IBlockData iblockdata = this.type.getWoodState(); ++ IBlockData iblockdata1 = this.type.getPlanksState(); ++ ++ if (this.getBlock(level, x, y, z, box).is(iblockdata1.getBlock())) { ++ this.fillPillarDownOrChainUp(level, iblockdata, x, y, z, box); + } + +- if (this.getBlock(level, x + 2, y, z, box).is(planksState.getBlock())) { +- this.fillPillarDownOrChainUp(level, woodState, x + 2, y, z, box); ++ if (this.getBlock(level, x + 2, y, z, box).is(iblockdata1.getBlock())) { ++ this.fillPillarDownOrChainUp(level, iblockdata, x + 2, y, z, box); + } ++ + } + + @Override +- protected void fillColumnDown(WorldGenLevel level, BlockState state, int x, int y, int z, BoundingBox box) { +- BlockPos.MutableBlockPos worldPos = this.getWorldPos(x, y, z); +- if (box.isInside(worldPos)) { +- int y1 = worldPos.getY(); ++ protected void fillColumnDown(WorldGenLevel level, IBlockData state, int x, int y, int z, BoundingBox box) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y, z); + +- while (this.isReplaceableByStructures(level.getBlockState(worldPos)) && worldPos.getY() > level.getMinBuildHeight() + 1) { +- worldPos.move(Direction.DOWN); ++ if (box.isInside(blockposition_mutableblockposition)) { ++ int l = blockposition_mutableblockposition.getY(); ++ ++ while (this.isReplaceableByStructures(level.getBlockState(blockposition_mutableblockposition)) && blockposition_mutableblockposition.getY() > level.getMinBuildHeight() + 1) { ++ blockposition_mutableblockposition.move(Direction.DOWN); + } + +- if (this.canPlaceColumnOnTopOf(level, worldPos, level.getBlockState(worldPos))) { +- while (worldPos.getY() < y1) { +- worldPos.move(Direction.UP); +- level.setBlock(worldPos, state, 2); ++ if (this.canPlaceColumnOnTopOf(level, blockposition_mutableblockposition, level.getBlockState(blockposition_mutableblockposition))) { ++ while (blockposition_mutableblockposition.getY() < l) { ++ blockposition_mutableblockposition.move(Direction.UP); ++ level.setBlock(blockposition_mutableblockposition, state, 2); + } ++ + } + } + } + +- protected void fillPillarDownOrChainUp(WorldGenLevel level, BlockState state, int x, int y, int z, BoundingBox box) { +- BlockPos.MutableBlockPos worldPos = this.getWorldPos(x, y, z); +- if (box.isInside(worldPos)) { +- int y1 = worldPos.getY(); +- int i = 1; ++ protected void fillPillarDownOrChainUp(WorldGenLevel level, IBlockData state, int x, int y, int z, BoundingBox box) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y, z); ++ ++ if (box.isInside(blockposition_mutableblockposition)) { ++ int l = blockposition_mutableblockposition.getY(); ++ int i1 = 1; + boolean flag = true; + +- for (boolean flag1 = true; flag || flag1; i++) { ++ for (boolean flag1 = true; flag || flag1; ++i1) { ++ IBlockData iblockdata1; ++ boolean flag2; ++ + if (flag) { +- worldPos.setY(y1 - i); +- BlockState blockState = level.getBlockState(worldPos); +- boolean flag2 = this.isReplaceableByStructures(blockState) && !blockState.is(Blocks.LAVA); +- if (!flag2 && this.canPlaceColumnOnTopOf(level, worldPos, blockState)) { +- fillColumnBetween(level, state, worldPos, y1 - i + 1, y1); ++ blockposition_mutableblockposition.setY(l - i1); ++ iblockdata1 = level.getBlockState(blockposition_mutableblockposition); ++ flag2 = this.isReplaceableByStructures(iblockdata1) && !iblockdata1.is(Blocks.LAVA); ++ if (!flag2 && this.canPlaceColumnOnTopOf(level, blockposition_mutableblockposition, iblockdata1)) { ++ fillColumnBetween(level, state, blockposition_mutableblockposition, l - i1 + 1, l); + return; + } + +- flag = i <= 20 && flag2 && worldPos.getY() > level.getMinBuildHeight() + 1; ++ flag = i1 <= 20 && flag2 && blockposition_mutableblockposition.getY() > level.getMinBuildHeight() + 1; + } + + if (flag1) { +- worldPos.setY(y1 + i); +- BlockState blockState = level.getBlockState(worldPos); +- boolean flag2 = this.isReplaceableByStructures(blockState); +- if (!flag2 && this.canHangChainBelow(level, worldPos, blockState)) { +- level.setBlock(worldPos.setY(y1 + 1), this.type.getFenceState(), 2); +- fillColumnBetween(level, Blocks.CHAIN.defaultBlockState(), worldPos, y1 + 2, y1 + i); ++ blockposition_mutableblockposition.setY(l + i1); ++ iblockdata1 = level.getBlockState(blockposition_mutableblockposition); ++ flag2 = this.isReplaceableByStructures(iblockdata1); ++ if (!flag2 && this.canHangChainBelow(level, blockposition_mutableblockposition, iblockdata1)) { ++ level.setBlock(blockposition_mutableblockposition.setY(l + 1), this.type.getFenceState(), 2); ++ fillColumnBetween(level, Blocks.CHAIN.defaultBlockState(), blockposition_mutableblockposition, l + 2, l + i1); + return; + } + +- flag1 = i <= 50 && flag2 && worldPos.getY() < level.getMaxBuildHeight() - 1; ++ flag1 = i1 <= 50 && flag2 && blockposition_mutableblockposition.getY() < level.getMaxBuildHeight() - 1; + } + } ++ + } + } + +- private static void fillColumnBetween(WorldGenLevel level, BlockState state, BlockPos.MutableBlockPos pos, int minY, int maxY) { +- for (int i = minY; i < maxY; i++) { +- level.setBlock(pos.setY(i), state, 2); ++ private static void fillColumnBetween(WorldGenLevel level, IBlockData state, BlockPos.MutableBlockPos pos, int minY, int maxY) { ++ for (int k = minY; k < maxY; ++k) { ++ level.setBlock(pos.setY(k), state, 2); + } ++ + } + +- private boolean canPlaceColumnOnTopOf(LevelReader level, BlockPos pos, BlockState state) { ++ private boolean canPlaceColumnOnTopOf(LevelReader level, BlockPos pos, IBlockData state) { + return state.isFaceSturdy(level, pos, Direction.UP); + } + +- private boolean canHangChainBelow(LevelReader level, BlockPos pos, BlockState state) { ++ private boolean canHangChainBelow(LevelReader level, BlockPos pos, IBlockData state) { + return Block.canSupportCenter(level, pos, Direction.DOWN) && !(state.getBlock() instanceof FallingBlock); + } + + private void placeSupport(WorldGenLevel level, BoundingBox box, int minX, int minY, int z, int maxY, int maxX, RandomSource random) { + if (this.isSupportingBox(level, box, minX, maxX, maxY, z)) { +- BlockState planksState = this.type.getPlanksState(); +- BlockState fenceState = this.type.getFenceState(); +- this.generateBox(level, box, minX, minY, z, minX, maxY - 1, z, fenceState.setValue(FenceBlock.WEST, Boolean.valueOf(true)), CAVE_AIR, false); +- this.generateBox(level, box, maxX, minY, z, maxX, maxY - 1, z, fenceState.setValue(FenceBlock.EAST, Boolean.valueOf(true)), CAVE_AIR, false); ++ IBlockData iblockdata = this.type.getPlanksState(); ++ IBlockData iblockdata1 = this.type.getFenceState(); ++ ++ this.generateBox(level, box, minX, minY, z, minX, maxY - 1, z, (IBlockData) iblockdata1.setValue(FenceBlock.WEST, true), MineshaftPieces.MineShaftCorridor.CAVE_AIR, false); ++ this.generateBox(level, box, maxX, minY, z, maxX, maxY - 1, z, (IBlockData) iblockdata1.setValue(FenceBlock.EAST, true), MineshaftPieces.MineShaftCorridor.CAVE_AIR, false); + if (random.nextInt(4) == 0) { +- this.generateBox(level, box, minX, maxY, z, minX, maxY, z, planksState, CAVE_AIR, false); +- this.generateBox(level, box, maxX, maxY, z, maxX, maxY, z, planksState, CAVE_AIR, false); ++ this.generateBox(level, box, minX, maxY, z, minX, maxY, z, iblockdata, MineshaftPieces.MineShaftCorridor.CAVE_AIR, false); ++ this.generateBox(level, box, maxX, maxY, z, maxX, maxY, z, iblockdata, MineshaftPieces.MineShaftCorridor.CAVE_AIR, false); + } else { +- this.generateBox(level, box, minX, maxY, z, maxX, maxY, z, planksState, CAVE_AIR, false); +- this.maybeGenerateBlock( +- level, +- box, +- random, +- 0.05F, +- minX + 1, +- maxY, +- z - 1, +- Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.SOUTH) +- ); +- this.maybeGenerateBlock( +- level, +- box, +- random, +- 0.05F, +- minX + 1, +- maxY, +- z + 1, +- Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.NORTH) +- ); ++ this.generateBox(level, box, minX, maxY, z, maxX, maxY, z, iblockdata, MineshaftPieces.MineShaftCorridor.CAVE_AIR, false); ++ this.maybeGenerateBlock(level, box, random, 0.05F, minX + 1, maxY, z - 1, (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.SOUTH)); ++ this.maybeGenerateBlock(level, box, random, 0.05F, minX + 1, maxY, z + 1, (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.NORTH)); + } ++ + } + } + +@@ -553,302 +674,35 @@ + if (this.isInterior(level, x, y, z, box) && random.nextFloat() < chance && this.hasSturdyNeighbours(level, box, x, y, z, 2)) { + this.placeBlock(level, Blocks.COBWEB.defaultBlockState(), x, y, z, box); + } ++ + } + + private boolean hasSturdyNeighbours(WorldGenLevel level, BoundingBox box, int x, int y, int z, int required) { +- BlockPos.MutableBlockPos worldPos = this.getWorldPos(x, y, z); +- int i = 0; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y, z); ++ int i1 = 0; ++ Direction[] aenumdirection = Direction.values(); ++ int j1 = aenumdirection.length; + +- for (Direction direction : Direction.values()) { +- worldPos.move(direction); +- if (box.isInside(worldPos) && level.getBlockState(worldPos).isFaceSturdy(level, worldPos, direction.getOpposite())) { +- if (++i >= required) { ++ for (int k1 = 0; k1 < j1; ++k1) { ++ Direction enumdirection = aenumdirection[k1]; ++ ++ blockposition_mutableblockposition.move(enumdirection); ++ if (box.isInside(blockposition_mutableblockposition) && level.getBlockState(blockposition_mutableblockposition).isFaceSturdy(level, blockposition_mutableblockposition, enumdirection.getOpposite())) { ++ ++i1; ++ if (i1 >= required) { + return true; + } + } + +- worldPos.move(direction.getOpposite()); ++ blockposition_mutableblockposition.move(enumdirection.getOpposite()); + } + + return false; + } + } + +- public static class MineShaftCrossing extends MineshaftPieces.MineShaftPiece { +- private final Direction direction; +- private final boolean isTwoFloored; ++ private abstract static class MineShaftPiece extends StructurePiece { + +- public MineShaftCrossing(CompoundTag tag) { +- super(StructurePieceType.MINE_SHAFT_CROSSING, tag); +- this.isTwoFloored = tag.getBoolean("tf"); +- this.direction = Direction.from2DDataValue(tag.getInt("D")); +- } +- +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { +- super.addAdditionalSaveData(context, tag); +- tag.putBoolean("tf", this.isTwoFloored); +- tag.putInt("D", this.direction.get2DDataValue()); +- } +- +- public MineShaftCrossing(int genDepth, BoundingBox boundingBox, @Nullable Direction direction, MineshaftStructure.Type type) { +- super(StructurePieceType.MINE_SHAFT_CROSSING, genDepth, type, boundingBox); +- this.direction = direction; +- this.isTwoFloored = boundingBox.getYSpan() > 3; +- } +- +- @Nullable +- public static BoundingBox findCrossing(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction direction) { +- int i; +- if (random.nextInt(4) == 0) { +- i = 6; +- } else { +- i = 2; +- } +- BoundingBox boundingBox = switch (direction) { +- default -> new BoundingBox(-1, 0, -4, 3, i, 0); +- case SOUTH -> new BoundingBox(-1, 0, 0, 3, i, 4); +- case WEST -> new BoundingBox(-4, 0, -1, 0, i, 3); +- case EAST -> new BoundingBox(0, 0, -1, 4, i, 3); +- }; +- boundingBox.move(x, y, z); +- return pieces.findCollisionPiece(boundingBox) != null ? null : boundingBox; +- } +- +- @Override +- public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- int genDepth = this.getGenDepth(); +- switch (this.direction) { +- case NORTH: +- default: +- MineshaftPieces.generateAndAddPiece( +- piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() - 1, Direction.NORTH, genDepth +- ); +- MineshaftPieces.generateAndAddPiece( +- piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.WEST, genDepth +- ); +- MineshaftPieces.generateAndAddPiece( +- piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.EAST, genDepth +- ); +- break; +- case SOUTH: +- MineshaftPieces.generateAndAddPiece( +- piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.maxZ() + 1, Direction.SOUTH, genDepth +- ); +- MineshaftPieces.generateAndAddPiece( +- piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.WEST, genDepth +- ); +- MineshaftPieces.generateAndAddPiece( +- piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.EAST, genDepth +- ); +- break; +- case WEST: +- MineshaftPieces.generateAndAddPiece( +- piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() - 1, Direction.NORTH, genDepth +- ); +- MineshaftPieces.generateAndAddPiece( +- piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.maxZ() + 1, Direction.SOUTH, genDepth +- ); +- MineshaftPieces.generateAndAddPiece( +- piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.WEST, genDepth +- ); +- break; +- case EAST: +- MineshaftPieces.generateAndAddPiece( +- piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() - 1, Direction.NORTH, genDepth +- ); +- MineshaftPieces.generateAndAddPiece( +- piece, pieces, random, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.maxZ() + 1, Direction.SOUTH, genDepth +- ); +- MineshaftPieces.generateAndAddPiece( +- piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, Direction.EAST, genDepth +- ); +- } +- +- if (this.isTwoFloored) { +- if (random.nextBoolean()) { +- MineshaftPieces.generateAndAddPiece( +- piece, +- pieces, +- random, +- this.boundingBox.minX() + 1, +- this.boundingBox.minY() + 3 + 1, +- this.boundingBox.minZ() - 1, +- Direction.NORTH, +- genDepth +- ); +- } +- +- if (random.nextBoolean()) { +- MineshaftPieces.generateAndAddPiece( +- piece, +- pieces, +- random, +- this.boundingBox.minX() - 1, +- this.boundingBox.minY() + 3 + 1, +- this.boundingBox.minZ() + 1, +- Direction.WEST, +- genDepth +- ); +- } +- +- if (random.nextBoolean()) { +- MineshaftPieces.generateAndAddPiece( +- piece, +- pieces, +- random, +- this.boundingBox.maxX() + 1, +- this.boundingBox.minY() + 3 + 1, +- this.boundingBox.minZ() + 1, +- Direction.EAST, +- genDepth +- ); +- } +- +- if (random.nextBoolean()) { +- MineshaftPieces.generateAndAddPiece( +- piece, +- pieces, +- random, +- this.boundingBox.minX() + 1, +- this.boundingBox.minY() + 3 + 1, +- this.boundingBox.maxZ() + 1, +- Direction.SOUTH, +- genDepth +- ); +- } +- } +- } +- +- @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { +- if (!this.isInInvalidLocation(level, box)) { +- BlockState planksState = this.type.getPlanksState(); +- if (this.isTwoFloored) { +- this.generateBox( +- level, +- box, +- this.boundingBox.minX() + 1, +- this.boundingBox.minY(), +- this.boundingBox.minZ(), +- this.boundingBox.maxX() - 1, +- this.boundingBox.minY() + 3 - 1, +- this.boundingBox.maxZ(), +- CAVE_AIR, +- CAVE_AIR, +- false +- ); +- this.generateBox( +- level, +- box, +- this.boundingBox.minX(), +- this.boundingBox.minY(), +- this.boundingBox.minZ() + 1, +- this.boundingBox.maxX(), +- this.boundingBox.minY() + 3 - 1, +- this.boundingBox.maxZ() - 1, +- CAVE_AIR, +- CAVE_AIR, +- false +- ); +- this.generateBox( +- level, +- box, +- this.boundingBox.minX() + 1, +- this.boundingBox.maxY() - 2, +- this.boundingBox.minZ(), +- this.boundingBox.maxX() - 1, +- this.boundingBox.maxY(), +- this.boundingBox.maxZ(), +- CAVE_AIR, +- CAVE_AIR, +- false +- ); +- this.generateBox( +- level, +- box, +- this.boundingBox.minX(), +- this.boundingBox.maxY() - 2, +- this.boundingBox.minZ() + 1, +- this.boundingBox.maxX(), +- this.boundingBox.maxY(), +- this.boundingBox.maxZ() - 1, +- CAVE_AIR, +- CAVE_AIR, +- false +- ); +- this.generateBox( +- level, +- box, +- this.boundingBox.minX() + 1, +- this.boundingBox.minY() + 3, +- this.boundingBox.minZ() + 1, +- this.boundingBox.maxX() - 1, +- this.boundingBox.minY() + 3, +- this.boundingBox.maxZ() - 1, +- CAVE_AIR, +- CAVE_AIR, +- false +- ); +- } else { +- this.generateBox( +- level, +- box, +- this.boundingBox.minX() + 1, +- this.boundingBox.minY(), +- this.boundingBox.minZ(), +- this.boundingBox.maxX() - 1, +- this.boundingBox.maxY(), +- this.boundingBox.maxZ(), +- CAVE_AIR, +- CAVE_AIR, +- false +- ); +- this.generateBox( +- level, +- box, +- this.boundingBox.minX(), +- this.boundingBox.minY(), +- this.boundingBox.minZ() + 1, +- this.boundingBox.maxX(), +- this.boundingBox.maxY(), +- this.boundingBox.maxZ() - 1, +- CAVE_AIR, +- CAVE_AIR, +- false +- ); +- } +- +- this.placeSupportPillar(level, box, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, this.boundingBox.maxY()); +- this.placeSupportPillar(level, box, this.boundingBox.minX() + 1, this.boundingBox.minY(), this.boundingBox.maxZ() - 1, this.boundingBox.maxY()); +- this.placeSupportPillar(level, box, this.boundingBox.maxX() - 1, this.boundingBox.minY(), this.boundingBox.minZ() + 1, this.boundingBox.maxY()); +- this.placeSupportPillar(level, box, this.boundingBox.maxX() - 1, this.boundingBox.minY(), this.boundingBox.maxZ() - 1, this.boundingBox.maxY()); +- int i = this.boundingBox.minY() - 1; +- +- for (int i1 = this.boundingBox.minX(); i1 <= this.boundingBox.maxX(); i1++) { +- for (int i2 = this.boundingBox.minZ(); i2 <= this.boundingBox.maxZ(); i2++) { +- this.setPlanksBlock(level, box, planksState, i1, i, i2); +- } +- } +- } +- } +- +- private void placeSupportPillar(WorldGenLevel level, BoundingBox box, int x, int y, int z, int maxY) { +- if (!this.getBlock(level, x, maxY + 1, z, box).isAir()) { +- this.generateBox(level, box, x, y, z, x, maxY, z, this.type.getPlanksState(), CAVE_AIR, false); +- } +- } +- } +- +- abstract static class MineShaftPiece extends StructurePiece { + protected MineshaftStructure.Type type; + + public MineShaftPiece(StructurePieceType structurePieceType, int genDepth, MineshaftStructure.Type type, BoundingBox boundingBox) { +@@ -863,11 +717,9 @@ + + @Override + protected boolean canBeReplaced(LevelReader level, int x, int y, int z, BoundingBox box) { +- BlockState block = this.getBlock(level, x, y, z, box); +- return !block.is(this.type.getPlanksState().getBlock()) +- && !block.is(this.type.getWoodState().getBlock()) +- && !block.is(this.type.getFenceState().getBlock()) +- && !block.is(Blocks.CHAIN); ++ IBlockData iblockdata = this.getBlock(level, x, y, z, box); ++ ++ return !iblockdata.is(this.type.getPlanksState().getBlock()) && !iblockdata.is(this.type.getWoodState().getBlock()) && !iblockdata.is(this.type.getFenceState().getBlock()) && !iblockdata.is(Blocks.CHAIN); + } + + @Override +@@ -876,8 +728,8 @@ + } + + protected boolean isSupportingBox(BlockGetter level, BoundingBox box, int xStart, int xEnd, int y, int z) { +- for (int i = xStart; i <= xEnd; i++) { +- if (this.getBlock(level, i, y + 1, z, box).isAir()) { ++ for (int i1 = xStart; i1 <= xEnd; ++i1) { ++ if (this.getBlock(level, i1, y + 1, z, box).isAir()) { + return false; + } + } +@@ -886,47 +738,51 @@ + } + + protected boolean isInInvalidLocation(LevelAccessor level, BoundingBox boundingBox) { +- int max = Math.max(this.boundingBox.minX() - 1, boundingBox.minX()); +- int max1 = Math.max(this.boundingBox.minY() - 1, boundingBox.minY()); +- int max2 = Math.max(this.boundingBox.minZ() - 1, boundingBox.minZ()); +- int min = Math.min(this.boundingBox.maxX() + 1, boundingBox.maxX()); +- int min1 = Math.min(this.boundingBox.maxY() + 1, boundingBox.maxY()); +- int min2 = Math.min(this.boundingBox.maxZ() + 1, boundingBox.maxZ()); +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos((max + min) / 2, (max1 + min1) / 2, (max2 + min2) / 2); +- if (level.getBiome(mutableBlockPos).is(BiomeTags.MINESHAFT_BLOCKING)) { ++ int i = Math.max(this.boundingBox.minX() - 1, boundingBox.minX()); ++ int j = Math.max(this.boundingBox.minY() - 1, boundingBox.minY()); ++ int k = Math.max(this.boundingBox.minZ() - 1, boundingBox.minZ()); ++ int l = Math.min(this.boundingBox.maxX() + 1, boundingBox.maxX()); ++ int i1 = Math.min(this.boundingBox.maxY() + 1, boundingBox.maxY()); ++ int j1 = Math.min(this.boundingBox.maxZ() + 1, boundingBox.maxZ()); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos((i + l) / 2, (j + i1) / 2, (k + j1) / 2); ++ ++ if (level.getBiome(blockposition_mutableblockposition).is(BiomeTags.MINESHAFT_BLOCKING)) { + return true; + } else { +- for (int i = max; i <= min; i++) { +- for (int i1 = max2; i1 <= min2; i1++) { +- if (level.getBlockState(mutableBlockPos.set(i, max1, i1)).liquid()) { ++ int k1; ++ int l1; ++ ++ for (k1 = i; k1 <= l; ++k1) { ++ for (l1 = k; l1 <= j1; ++l1) { ++ if (level.getBlockState(blockposition_mutableblockposition.set(k1, j, l1)).liquid()) { + return true; + } + +- if (level.getBlockState(mutableBlockPos.set(i, min1, i1)).liquid()) { ++ if (level.getBlockState(blockposition_mutableblockposition.set(k1, i1, l1)).liquid()) { + return true; + } + } + } + +- for (int i = max; i <= min; i++) { +- for (int i1 = max1; i1 <= min1; i1++) { +- if (level.getBlockState(mutableBlockPos.set(i, i1, max2)).liquid()) { ++ for (k1 = i; k1 <= l; ++k1) { ++ for (l1 = j; l1 <= i1; ++l1) { ++ if (level.getBlockState(blockposition_mutableblockposition.set(k1, l1, k)).liquid()) { + return true; + } + +- if (level.getBlockState(mutableBlockPos.set(i, i1, min2)).liquid()) { ++ if (level.getBlockState(blockposition_mutableblockposition.set(k1, l1, j1)).liquid()) { + return true; + } + } + } + +- for (int i = max2; i <= min2; i++) { +- for (int i1 = max1; i1 <= min1; i1++) { +- if (level.getBlockState(mutableBlockPos.set(max, i1, i)).liquid()) { ++ for (k1 = k; k1 <= j1; ++k1) { ++ for (l1 = j; l1 <= i1; ++l1) { ++ if (level.getBlockState(blockposition_mutableblockposition.set(i, l1, k1)).liquid()) { + return true; + } + +- if (level.getBlockState(mutableBlockPos.set(min, i1, i)).liquid()) { ++ if (level.getBlockState(blockposition_mutableblockposition.set(l, l1, k1)).liquid()) { + return true; + } + } +@@ -936,338 +792,147 @@ + } + } + +- protected void setPlanksBlock(WorldGenLevel level, BoundingBox box, BlockState plankState, int x, int y, int z) { ++ protected void setPlanksBlock(WorldGenLevel level, BoundingBox box, IBlockData plankState, int x, int y, int z) { + if (this.isInterior(level, x, y, z, box)) { +- BlockPos worldPos = this.getWorldPos(x, y, z); +- BlockState blockState = level.getBlockState(worldPos); +- if (!blockState.isFaceSturdy(level, worldPos, Direction.UP)) { +- level.setBlock(worldPos, plankState, 2); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(x, y, z); ++ IBlockData iblockdata1 = level.getBlockState(blockposition_mutableblockposition); ++ ++ if (!iblockdata1.isFaceSturdy(level, blockposition_mutableblockposition, Direction.UP)) { ++ level.setBlock(blockposition_mutableblockposition, plankState, 2); + } ++ + } + } + } + + public static class MineShaftRoom extends MineshaftPieces.MineShaftPiece { ++ + private final List childEntranceBoxes = Lists.newLinkedList(); + + public MineShaftRoom(int genDepth, RandomSource random, int x, int z, MineshaftStructure.Type type) { +- super( +- StructurePieceType.MINE_SHAFT_ROOM, +- genDepth, +- type, +- new BoundingBox(x, 50, z, x + 7 + random.nextInt(6), 54 + random.nextInt(6), z + 7 + random.nextInt(6)) +- ); ++ super(StructurePieceType.MINE_SHAFT_ROOM, genDepth, type, new BoundingBox(x, 50, z, x + 7 + random.nextInt(6), 54 + random.nextInt(6), z + 7 + random.nextInt(6))); + this.type = type; + } + + public MineShaftRoom(CompoundTag tag) { + super(StructurePieceType.MINE_SHAFT_ROOM, tag); +- BoundingBox.CODEC +- .listOf() +- .parse(NbtOps.INSTANCE, tag.getList("Entrances", 11)) +- .resultOrPartial(MineshaftPieces.LOGGER::error) +- .ifPresent(this.childEntranceBoxes::addAll); ++ DataResult> dataresult = BoundingBox.CODEC.listOf().parse(NbtOps.INSTANCE, tag.getList("Entrances", 11)); // CraftBukkit - decompile error ++ Logger logger = MineshaftPieces.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ Optional> optional = dataresult.resultOrPartial(logger::error); // CraftBukkit - decompile error ++ List list = this.childEntranceBoxes; ++ ++ Objects.requireNonNull(this.childEntranceBoxes); ++ optional.ifPresent(list::addAll); + } + + @Override + public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- int genDepth = this.getGenDepth(); +- int i = this.boundingBox.getYSpan() - 3 - 1; +- if (i <= 0) { +- i = 1; ++ int i = this.getGenDepth(); ++ int j = this.boundingBox.getYSpan() - 3 - 1; ++ ++ if (j <= 0) { ++ j = 1; + } + +- int i1 = 0; ++ int k; ++ MineshaftPieces.MineShaftPiece mineshaftpieces_c; ++ BoundingBox structureboundingbox; + +- while (i1 < this.boundingBox.getXSpan()) { +- int var9 = i1 + random.nextInt(this.boundingBox.getXSpan()); +- if (var9 + 3 > this.boundingBox.getXSpan()) { ++ for (k = 0; k < this.boundingBox.getXSpan(); k += 4) { ++ k += random.nextInt(this.boundingBox.getXSpan()); ++ if (k + 3 > this.boundingBox.getXSpan()) { + break; + } + +- MineshaftPieces.MineShaftPiece mineShaftPiece = MineshaftPieces.generateAndAddPiece( +- piece, +- pieces, +- random, +- this.boundingBox.minX() + var9, +- this.boundingBox.minY() + random.nextInt(i) + 1, +- this.boundingBox.minZ() - 1, +- Direction.NORTH, +- genDepth +- ); +- if (mineShaftPiece != null) { +- BoundingBox boundingBox = mineShaftPiece.getBoundingBox(); +- this.childEntranceBoxes +- .add( +- new BoundingBox( +- boundingBox.minX(), +- boundingBox.minY(), +- this.boundingBox.minZ(), +- boundingBox.maxX(), +- boundingBox.maxY(), +- this.boundingBox.minZ() + 1 +- ) +- ); ++ mineshaftpieces_c = MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() + k, this.boundingBox.minY() + random.nextInt(j) + 1, this.boundingBox.minZ() - 1, Direction.NORTH, i); ++ if (mineshaftpieces_c != null) { ++ structureboundingbox = mineshaftpieces_c.getBoundingBox(); ++ this.childEntranceBoxes.add(new BoundingBox(structureboundingbox.minX(), structureboundingbox.minY(), this.boundingBox.minZ(), structureboundingbox.maxX(), structureboundingbox.maxY(), this.boundingBox.minZ() + 1)); + } +- +- i1 = var9 + 4; + } + +- int var10 = 0; +- +- while (var10 < this.boundingBox.getXSpan()) { +- i1 = var10 + random.nextInt(this.boundingBox.getXSpan()); +- if (i1 + 3 > this.boundingBox.getXSpan()) { ++ for (k = 0; k < this.boundingBox.getXSpan(); k += 4) { ++ k += random.nextInt(this.boundingBox.getXSpan()); ++ if (k + 3 > this.boundingBox.getXSpan()) { + break; + } + +- MineshaftPieces.MineShaftPiece mineShaftPiece = MineshaftPieces.generateAndAddPiece( +- piece, +- pieces, +- random, +- this.boundingBox.minX() + i1, +- this.boundingBox.minY() + random.nextInt(i) + 1, +- this.boundingBox.maxZ() + 1, +- Direction.SOUTH, +- genDepth +- ); +- if (mineShaftPiece != null) { +- BoundingBox boundingBox = mineShaftPiece.getBoundingBox(); +- this.childEntranceBoxes +- .add( +- new BoundingBox( +- boundingBox.minX(), +- boundingBox.minY(), +- this.boundingBox.maxZ() - 1, +- boundingBox.maxX(), +- boundingBox.maxY(), +- this.boundingBox.maxZ() +- ) +- ); ++ mineshaftpieces_c = MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() + k, this.boundingBox.minY() + random.nextInt(j) + 1, this.boundingBox.maxZ() + 1, Direction.SOUTH, i); ++ if (mineshaftpieces_c != null) { ++ structureboundingbox = mineshaftpieces_c.getBoundingBox(); ++ this.childEntranceBoxes.add(new BoundingBox(structureboundingbox.minX(), structureboundingbox.minY(), this.boundingBox.maxZ() - 1, structureboundingbox.maxX(), structureboundingbox.maxY(), this.boundingBox.maxZ())); + } +- +- var10 = i1 + 4; + } + +- int var12 = 0; +- +- while (var12 < this.boundingBox.getZSpan()) { +- i1 = var12 + random.nextInt(this.boundingBox.getZSpan()); +- if (i1 + 3 > this.boundingBox.getZSpan()) { ++ for (k = 0; k < this.boundingBox.getZSpan(); k += 4) { ++ k += random.nextInt(this.boundingBox.getZSpan()); ++ if (k + 3 > this.boundingBox.getZSpan()) { + break; + } + +- MineshaftPieces.MineShaftPiece mineShaftPiece = MineshaftPieces.generateAndAddPiece( +- piece, +- pieces, +- random, +- this.boundingBox.minX() - 1, +- this.boundingBox.minY() + random.nextInt(i) + 1, +- this.boundingBox.minZ() + i1, +- Direction.WEST, +- genDepth +- ); +- if (mineShaftPiece != null) { +- BoundingBox boundingBox = mineShaftPiece.getBoundingBox(); +- this.childEntranceBoxes +- .add( +- new BoundingBox( +- this.boundingBox.minX(), +- boundingBox.minY(), +- boundingBox.minZ(), +- this.boundingBox.minX() + 1, +- boundingBox.maxY(), +- boundingBox.maxZ() +- ) +- ); ++ mineshaftpieces_c = MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() + random.nextInt(j) + 1, this.boundingBox.minZ() + k, Direction.WEST, i); ++ if (mineshaftpieces_c != null) { ++ structureboundingbox = mineshaftpieces_c.getBoundingBox(); ++ this.childEntranceBoxes.add(new BoundingBox(this.boundingBox.minX(), structureboundingbox.minY(), structureboundingbox.minZ(), this.boundingBox.minX() + 1, structureboundingbox.maxY(), structureboundingbox.maxZ())); + } +- +- var12 = i1 + 4; + } + +- int var14 = 0; +- +- while (var14 < this.boundingBox.getZSpan()) { +- i1 = var14 + random.nextInt(this.boundingBox.getZSpan()); +- if (i1 + 3 > this.boundingBox.getZSpan()) { ++ for (k = 0; k < this.boundingBox.getZSpan(); k += 4) { ++ k += random.nextInt(this.boundingBox.getZSpan()); ++ if (k + 3 > this.boundingBox.getZSpan()) { + break; + } + +- StructurePiece structurePiece = MineshaftPieces.generateAndAddPiece( +- piece, +- pieces, +- random, +- this.boundingBox.maxX() + 1, +- this.boundingBox.minY() + random.nextInt(i) + 1, +- this.boundingBox.minZ() + i1, +- Direction.EAST, +- genDepth +- ); +- if (structurePiece != null) { +- BoundingBox boundingBox = structurePiece.getBoundingBox(); +- this.childEntranceBoxes +- .add( +- new BoundingBox( +- this.boundingBox.maxX() - 1, +- boundingBox.minY(), +- boundingBox.minZ(), +- this.boundingBox.maxX(), +- boundingBox.maxY(), +- boundingBox.maxZ() +- ) +- ); ++ mineshaftpieces_c = MineshaftPieces.generateAndAddPiece(piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() + random.nextInt(j) + 1, this.boundingBox.minZ() + k, Direction.EAST, i); ++ if (mineshaftpieces_c != null) { ++ structureboundingbox = mineshaftpieces_c.getBoundingBox(); ++ this.childEntranceBoxes.add(new BoundingBox(this.boundingBox.maxX() - 1, structureboundingbox.minY(), structureboundingbox.minZ(), this.boundingBox.maxX(), structureboundingbox.maxY(), structureboundingbox.maxZ())); + } +- +- var14 = i1 + 4; + } ++ + } + + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { + if (!this.isInInvalidLocation(level, box)) { +- this.generateBox( +- level, +- box, +- this.boundingBox.minX(), +- this.boundingBox.minY() + 1, +- this.boundingBox.minZ(), +- this.boundingBox.maxX(), +- Math.min(this.boundingBox.minY() + 3, this.boundingBox.maxY()), +- this.boundingBox.maxZ(), +- CAVE_AIR, +- CAVE_AIR, +- false +- ); ++ this.generateBox(level, box, this.boundingBox.minX(), this.boundingBox.minY() + 1, this.boundingBox.minZ(), this.boundingBox.maxX(), Math.min(this.boundingBox.minY() + 3, this.boundingBox.maxY()), this.boundingBox.maxZ(), MineshaftPieces.MineShaftRoom.CAVE_AIR, MineshaftPieces.MineShaftRoom.CAVE_AIR, false); ++ Iterator iterator = this.childEntranceBoxes.iterator(); + +- for (BoundingBox boundingBox : this.childEntranceBoxes) { +- this.generateBox( +- level, +- box, +- boundingBox.minX(), +- boundingBox.maxY() - 2, +- boundingBox.minZ(), +- boundingBox.maxX(), +- boundingBox.maxY(), +- boundingBox.maxZ(), +- CAVE_AIR, +- CAVE_AIR, +- false +- ); ++ while (iterator.hasNext()) { ++ BoundingBox structureboundingbox1 = (BoundingBox) iterator.next(); ++ ++ this.generateBox(level, box, structureboundingbox1.minX(), structureboundingbox1.maxY() - 2, structureboundingbox1.minZ(), structureboundingbox1.maxX(), structureboundingbox1.maxY(), structureboundingbox1.maxZ(), MineshaftPieces.MineShaftRoom.CAVE_AIR, MineshaftPieces.MineShaftRoom.CAVE_AIR, false); + } + +- this.generateUpperHalfSphere( +- level, +- box, +- this.boundingBox.minX(), +- this.boundingBox.minY() + 4, +- this.boundingBox.minZ(), +- this.boundingBox.maxX(), +- this.boundingBox.maxY(), +- this.boundingBox.maxZ(), +- CAVE_AIR, +- false +- ); ++ this.generateUpperHalfSphere(level, box, this.boundingBox.minX(), this.boundingBox.minY() + 4, this.boundingBox.minZ(), this.boundingBox.maxX(), this.boundingBox.maxY(), this.boundingBox.maxZ(), MineshaftPieces.MineShaftRoom.CAVE_AIR, false); + } + } + + @Override + public void move(int x, int y, int z) { + super.move(x, y, z); ++ Iterator iterator = this.childEntranceBoxes.iterator(); + +- for (BoundingBox boundingBox : this.childEntranceBoxes) { +- boundingBox.move(x, y, z); ++ while (iterator.hasNext()) { ++ BoundingBox structureboundingbox = (BoundingBox) iterator.next(); ++ ++ structureboundingbox.move(x, y, z); + } ++ + } + + @Override + protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { + super.addAdditionalSaveData(context, tag); +- BoundingBox.CODEC +- .listOf() +- .encodeStart(NbtOps.INSTANCE, this.childEntranceBoxes) +- .resultOrPartial(MineshaftPieces.LOGGER::error) +- .ifPresent(tag1 -> tag.put("Entrances", tag1)); +- } +- } ++ DataResult dataresult = BoundingBox.CODEC.listOf().encodeStart(NbtOps.INSTANCE, this.childEntranceBoxes); // CraftBukkit - decompile error ++ Logger logger = MineshaftPieces.LOGGER; + +- public static class MineShaftStairs extends MineshaftPieces.MineShaftPiece { +- public MineShaftStairs(int genDepth, BoundingBox boundingBox, Direction orientation, MineshaftStructure.Type type) { +- super(StructurePieceType.MINE_SHAFT_STAIRS, genDepth, type, boundingBox); +- this.setOrientation(orientation); ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ tag.put("Entrances", nbtbase); ++ }); + } +- +- public MineShaftStairs(CompoundTag tag) { +- super(StructurePieceType.MINE_SHAFT_STAIRS, tag); +- } +- +- @Nullable +- public static BoundingBox findStairs(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction direction) { +- BoundingBox boundingBox = switch (direction) { +- default -> new BoundingBox(0, -5, -8, 2, 2, 0); +- case SOUTH -> new BoundingBox(0, -5, 0, 2, 2, 8); +- case WEST -> new BoundingBox(-8, -5, 0, 0, 2, 2); +- case EAST -> new BoundingBox(0, -5, 0, 8, 2, 2); +- }; +- boundingBox.move(x, y, z); +- return pieces.findCollisionPiece(boundingBox) != null ? null : boundingBox; +- } +- +- @Override +- public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- int genDepth = this.getGenDepth(); +- Direction orientation = this.getOrientation(); +- if (orientation != null) { +- switch (orientation) { +- case NORTH: +- default: +- MineshaftPieces.generateAndAddPiece( +- piece, pieces, random, this.boundingBox.minX(), this.boundingBox.minY(), this.boundingBox.minZ() - 1, Direction.NORTH, genDepth +- ); +- break; +- case SOUTH: +- MineshaftPieces.generateAndAddPiece( +- piece, pieces, random, this.boundingBox.minX(), this.boundingBox.minY(), this.boundingBox.maxZ() + 1, Direction.SOUTH, genDepth +- ); +- break; +- case WEST: +- MineshaftPieces.generateAndAddPiece( +- piece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY(), this.boundingBox.minZ(), Direction.WEST, genDepth +- ); +- break; +- case EAST: +- MineshaftPieces.generateAndAddPiece( +- piece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY(), this.boundingBox.minZ(), Direction.EAST, genDepth +- ); +- } +- } +- } +- +- @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { +- if (!this.isInInvalidLocation(level, box)) { +- this.generateBox(level, box, 0, 5, 0, 2, 7, 1, CAVE_AIR, CAVE_AIR, false); +- this.generateBox(level, box, 0, 0, 7, 2, 2, 8, CAVE_AIR, CAVE_AIR, false); +- +- for (int i = 0; i < 5; i++) { +- this.generateBox(level, box, 0, 5 - i - (i < 4 ? 1 : 0), 2 + i, 2, 7 - i, 2 + i, CAVE_AIR, CAVE_AIR, false); +- } +- } +- } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java.patch new file mode 100644 index 0000000000..7630f4a010 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java.patch @@ -0,0 +1,2486 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java +@@ -1,89 +1,164 @@ + package net.minecraft.world.level.levelgen.structure.structures; + + import com.google.common.collect.Lists; ++import java.util.Iterator; + import java.util.List; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.entity.EntityType; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.StructureManager; + import net.minecraft.world.level.WorldGenLevel; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.FenceBlock; + import net.minecraft.world.level.block.StairBlock; +-import net.minecraft.world.level.block.entity.SpawnerBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.levelgen.structure.BoundingBox; + import net.minecraft.world.level.levelgen.structure.StructurePiece; + import net.minecraft.world.level.levelgen.structure.StructurePieceAccessor; + import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; + import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceType; ++import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.Fluids; + import net.minecraft.world.level.storage.loot.BuiltInLootTables; + + public class NetherFortressPieces { ++ + private static final int MAX_DEPTH = 30; + private static final int LOWEST_Y_POSITION = 10; + public static final int MAGIC_START_Y = 64; +- static final NetherFortressPieces.PieceWeight[] BRIDGE_PIECE_WEIGHTS = new NetherFortressPieces.PieceWeight[]{ +- new NetherFortressPieces.PieceWeight(NetherFortressPieces.BridgeStraight.class, 30, 0, true), +- new NetherFortressPieces.PieceWeight(NetherFortressPieces.BridgeCrossing.class, 10, 4), +- new NetherFortressPieces.PieceWeight(NetherFortressPieces.RoomCrossing.class, 10, 4), +- new NetherFortressPieces.PieceWeight(NetherFortressPieces.StairsRoom.class, 10, 3), +- new NetherFortressPieces.PieceWeight(NetherFortressPieces.MonsterThrone.class, 5, 2), +- new NetherFortressPieces.PieceWeight(NetherFortressPieces.CastleEntrance.class, 5, 1) +- }; +- static final NetherFortressPieces.PieceWeight[] CASTLE_PIECE_WEIGHTS = new NetherFortressPieces.PieceWeight[]{ +- new NetherFortressPieces.PieceWeight(NetherFortressPieces.CastleSmallCorridorPiece.class, 25, 0, true), +- new NetherFortressPieces.PieceWeight(NetherFortressPieces.CastleSmallCorridorCrossingPiece.class, 15, 5), +- new NetherFortressPieces.PieceWeight(NetherFortressPieces.CastleSmallCorridorRightTurnPiece.class, 5, 10), +- new NetherFortressPieces.PieceWeight(NetherFortressPieces.CastleSmallCorridorLeftTurnPiece.class, 5, 10), +- new NetherFortressPieces.PieceWeight(NetherFortressPieces.CastleCorridorStairsPiece.class, 10, 3, true), +- new NetherFortressPieces.PieceWeight(NetherFortressPieces.CastleCorridorTBalconyPiece.class, 7, 2), +- new NetherFortressPieces.PieceWeight(NetherFortressPieces.CastleStalkRoom.class, 5, 2) +- }; ++ static final NetherFortressPieces.PieceWeight[] BRIDGE_PIECE_WEIGHTS = new NetherFortressPieces.PieceWeight[]{new NetherFortressPieces.PieceWeight(NetherFortressPieces.BridgeStraight.class, 30, 0, true), new NetherFortressPieces.PieceWeight(NetherFortressPieces.BridgeCrossing.class, 10, 4), new NetherFortressPieces.PieceWeight(NetherFortressPieces.RoomCrossing.class, 10, 4), new NetherFortressPieces.PieceWeight(NetherFortressPieces.StairsRoom.class, 10, 3), new NetherFortressPieces.PieceWeight(NetherFortressPieces.MonsterThrone.class, 5, 2), new NetherFortressPieces.PieceWeight(NetherFortressPieces.CastleEntrance.class, 5, 1)}; ++ static final NetherFortressPieces.PieceWeight[] CASTLE_PIECE_WEIGHTS = new NetherFortressPieces.PieceWeight[]{new NetherFortressPieces.PieceWeight(NetherFortressPieces.CastleSmallCorridorPiece.class, 25, 0, true), new NetherFortressPieces.PieceWeight(NetherFortressPieces.CastleSmallCorridorCrossingPiece.class, 15, 5), new NetherFortressPieces.PieceWeight(NetherFortressPieces.CastleSmallCorridorRightTurnPiece.class, 5, 10), new NetherFortressPieces.PieceWeight(NetherFortressPieces.CastleSmallCorridorLeftTurnPiece.class, 5, 10), new NetherFortressPieces.PieceWeight(NetherFortressPieces.CastleCorridorStairsPiece.class, 10, 3, true), new NetherFortressPieces.PieceWeight(NetherFortressPieces.CastleCorridorTBalconyPiece.class, 7, 2), new NetherFortressPieces.PieceWeight(NetherFortressPieces.CastleStalkRoom.class, 5, 2)}; + +- static NetherFortressPieces.NetherBridgePiece findAndCreateBridgePieceFactory( +- NetherFortressPieces.PieceWeight weight, StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth +- ) { +- Class clazz = weight.pieceClass; +- NetherFortressPieces.NetherBridgePiece netherBridgePiece = null; +- if (clazz == NetherFortressPieces.BridgeStraight.class) { +- netherBridgePiece = NetherFortressPieces.BridgeStraight.createPiece(pieces, random, x, y, z, orientation, genDepth); +- } else if (clazz == NetherFortressPieces.BridgeCrossing.class) { +- netherBridgePiece = NetherFortressPieces.BridgeCrossing.createPiece(pieces, x, y, z, orientation, genDepth); +- } else if (clazz == NetherFortressPieces.RoomCrossing.class) { +- netherBridgePiece = NetherFortressPieces.RoomCrossing.createPiece(pieces, x, y, z, orientation, genDepth); +- } else if (clazz == NetherFortressPieces.StairsRoom.class) { +- netherBridgePiece = NetherFortressPieces.StairsRoom.createPiece(pieces, x, y, z, genDepth, orientation); +- } else if (clazz == NetherFortressPieces.MonsterThrone.class) { +- netherBridgePiece = NetherFortressPieces.MonsterThrone.createPiece(pieces, x, y, z, genDepth, orientation); +- } else if (clazz == NetherFortressPieces.CastleEntrance.class) { +- netherBridgePiece = NetherFortressPieces.CastleEntrance.createPiece(pieces, random, x, y, z, orientation, genDepth); +- } else if (clazz == NetherFortressPieces.CastleSmallCorridorPiece.class) { +- netherBridgePiece = NetherFortressPieces.CastleSmallCorridorPiece.createPiece(pieces, x, y, z, orientation, genDepth); +- } else if (clazz == NetherFortressPieces.CastleSmallCorridorRightTurnPiece.class) { +- netherBridgePiece = NetherFortressPieces.CastleSmallCorridorRightTurnPiece.createPiece(pieces, random, x, y, z, orientation, genDepth); +- } else if (clazz == NetherFortressPieces.CastleSmallCorridorLeftTurnPiece.class) { +- netherBridgePiece = NetherFortressPieces.CastleSmallCorridorLeftTurnPiece.createPiece(pieces, random, x, y, z, orientation, genDepth); +- } else if (clazz == NetherFortressPieces.CastleCorridorStairsPiece.class) { +- netherBridgePiece = NetherFortressPieces.CastleCorridorStairsPiece.createPiece(pieces, x, y, z, orientation, genDepth); +- } else if (clazz == NetherFortressPieces.CastleCorridorTBalconyPiece.class) { +- netherBridgePiece = NetherFortressPieces.CastleCorridorTBalconyPiece.createPiece(pieces, x, y, z, orientation, genDepth); +- } else if (clazz == NetherFortressPieces.CastleSmallCorridorCrossingPiece.class) { +- netherBridgePiece = NetherFortressPieces.CastleSmallCorridorCrossingPiece.createPiece(pieces, x, y, z, orientation, genDepth); +- } else if (clazz == NetherFortressPieces.CastleStalkRoom.class) { +- netherBridgePiece = NetherFortressPieces.CastleStalkRoom.createPiece(pieces, x, y, z, orientation, genDepth); ++ public NetherFortressPieces() {} ++ ++ static NetherFortressPieces.NetherBridgePiece findAndCreateBridgePieceFactory(NetherFortressPieces.PieceWeight weight, StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ Class oclass = weight.pieceClass; ++ Object object = null; ++ ++ if (oclass == NetherFortressPieces.BridgeStraight.class) { ++ object = NetherFortressPieces.BridgeStraight.createPiece(pieces, random, x, y, z, orientation, genDepth); ++ } else if (oclass == NetherFortressPieces.BridgeCrossing.class) { ++ object = NetherFortressPieces.BridgeCrossing.createPiece(pieces, x, y, z, orientation, genDepth); ++ } else if (oclass == NetherFortressPieces.RoomCrossing.class) { ++ object = NetherFortressPieces.RoomCrossing.createPiece(pieces, x, y, z, orientation, genDepth); ++ } else if (oclass == NetherFortressPieces.StairsRoom.class) { ++ object = NetherFortressPieces.StairsRoom.createPiece(pieces, x, y, z, genDepth, orientation); ++ } else if (oclass == NetherFortressPieces.MonsterThrone.class) { ++ object = NetherFortressPieces.MonsterThrone.createPiece(pieces, x, y, z, genDepth, orientation); ++ } else if (oclass == NetherFortressPieces.CastleEntrance.class) { ++ object = NetherFortressPieces.CastleEntrance.createPiece(pieces, random, x, y, z, orientation, genDepth); ++ } else if (oclass == NetherFortressPieces.CastleSmallCorridorPiece.class) { ++ object = NetherFortressPieces.CastleSmallCorridorPiece.createPiece(pieces, x, y, z, orientation, genDepth); ++ } else if (oclass == NetherFortressPieces.CastleSmallCorridorRightTurnPiece.class) { ++ object = NetherFortressPieces.CastleSmallCorridorRightTurnPiece.createPiece(pieces, random, x, y, z, orientation, genDepth); ++ } else if (oclass == NetherFortressPieces.CastleSmallCorridorLeftTurnPiece.class) { ++ object = NetherFortressPieces.CastleSmallCorridorLeftTurnPiece.createPiece(pieces, random, x, y, z, orientation, genDepth); ++ } else if (oclass == NetherFortressPieces.CastleCorridorStairsPiece.class) { ++ object = NetherFortressPieces.CastleCorridorStairsPiece.createPiece(pieces, x, y, z, orientation, genDepth); ++ } else if (oclass == NetherFortressPieces.CastleCorridorTBalconyPiece.class) { ++ object = NetherFortressPieces.CastleCorridorTBalconyPiece.createPiece(pieces, x, y, z, orientation, genDepth); ++ } else if (oclass == NetherFortressPieces.CastleSmallCorridorCrossingPiece.class) { ++ object = NetherFortressPieces.CastleSmallCorridorCrossingPiece.createPiece(pieces, x, y, z, orientation, genDepth); ++ } else if (oclass == NetherFortressPieces.CastleStalkRoom.class) { ++ object = NetherFortressPieces.CastleStalkRoom.createPiece(pieces, x, y, z, orientation, genDepth); + } + +- return netherBridgePiece; ++ return (NetherFortressPieces.NetherBridgePiece) object; + } + ++ private static class PieceWeight { ++ ++ public final Class pieceClass; ++ public final int weight; ++ public int placeCount; ++ public final int maxPlaceCount; ++ public final boolean allowInRow; ++ ++ public PieceWeight(Class pieceClass, int weight, int maxPlaceCount, boolean allowInRow) { ++ this.pieceClass = pieceClass; ++ this.weight = weight; ++ this.maxPlaceCount = maxPlaceCount; ++ this.allowInRow = allowInRow; ++ } ++ ++ public PieceWeight(Class pieceClass, int weight, int maxPlaceCount) { ++ this(pieceClass, weight, maxPlaceCount, false); ++ } ++ ++ public boolean doPlace(int genDepth) { ++ return this.maxPlaceCount == 0 || this.placeCount < this.maxPlaceCount; ++ } ++ ++ public boolean isValid() { ++ return this.maxPlaceCount == 0 || this.placeCount < this.maxPlaceCount; ++ } ++ } ++ ++ public static class BridgeStraight extends NetherFortressPieces.NetherBridgePiece { ++ ++ private static final int WIDTH = 5; ++ private static final int HEIGHT = 10; ++ private static final int DEPTH = 19; ++ ++ public BridgeStraight(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_BRIDGE_STRAIGHT, genDepth, box); ++ this.setOrientation(orientation); ++ } ++ ++ public BridgeStraight(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_BRIDGE_STRAIGHT, tag); ++ } ++ ++ @Override ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateChildForward((NetherFortressPieces.StartPiece) piece, pieces, random, 1, 3, false); ++ } ++ ++ public static NetherFortressPieces.BridgeStraight createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -3, 0, 5, 10, 19, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.BridgeStraight(genDepth, random, structureboundingbox, orientation) : null; ++ } ++ ++ @Override ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 3, 0, 4, 4, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 5, 0, 3, 7, 18, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 5, 0, 0, 5, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 5, 0, 4, 5, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 4, 2, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 13, 4, 2, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 0, 0, 4, 1, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 0, 15, 4, 1, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ ++ for (int i = 0; i <= 4; ++i) { ++ for (int j = 0; j <= 2; ++j) { ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, 18 - j, box); ++ } ++ } ++ ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); ++ IBlockData iblockdata1 = (IBlockData) iblockdata.setValue(FenceBlock.EAST, true); ++ IBlockData iblockdata2 = (IBlockData) iblockdata.setValue(FenceBlock.WEST, true); ++ ++ this.generateBox(level, box, 0, 1, 1, 0, 4, 1, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 0, 3, 4, 0, 4, 4, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 0, 3, 14, 0, 4, 14, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 0, 1, 17, 0, 4, 17, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 4, 1, 1, 4, 4, 1, iblockdata2, iblockdata2, false); ++ this.generateBox(level, box, 4, 3, 4, 4, 4, 4, iblockdata2, iblockdata2, false); ++ this.generateBox(level, box, 4, 3, 14, 4, 4, 14, iblockdata2, iblockdata2, false); ++ this.generateBox(level, box, 4, 1, 17, 4, 4, 17, iblockdata2, iblockdata2, false); ++ } ++ } ++ + public static class BridgeCrossing extends NetherFortressPieces.NetherBridgePiece { ++ + private static final int WIDTH = 19; + private static final int HEIGHT = 10; + private static final int DEPTH = 19; +@@ -108,28 +183,19 @@ + + @Override + public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- this.generateChildForward((NetherFortressPieces.StartPiece)piece, pieces, random, 8, 3, false); +- this.generateChildLeft((NetherFortressPieces.StartPiece)piece, pieces, random, 3, 8, false); +- this.generateChildRight((NetherFortressPieces.StartPiece)piece, pieces, random, 3, 8, false); ++ this.generateChildForward((NetherFortressPieces.StartPiece) piece, pieces, random, 8, 3, false); ++ this.generateChildLeft((NetherFortressPieces.StartPiece) piece, pieces, random, 3, 8, false); ++ this.generateChildRight((NetherFortressPieces.StartPiece) piece, pieces, random, 3, 8, false); + } + + public static NetherFortressPieces.BridgeCrossing createPiece(StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -8, -3, 0, 19, 10, 19, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new NetherFortressPieces.BridgeCrossing(genDepth, boundingBox, orientation) +- : null; ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -8, -3, 0, 19, 10, 19, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.BridgeCrossing(genDepth, structureboundingbox, orientation) : null; + } + + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { + this.generateBox(level, box, 7, 3, 0, 11, 4, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 0, 3, 7, 18, 4, 11, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 8, 5, 0, 10, 7, 18, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +@@ -147,10 +213,13 @@ + this.generateBox(level, box, 7, 0, 0, 11, 1, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 7, 0, 15, 11, 1, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + +- for (int i = 7; i <= 11; i++) { +- for (int i1 = 0; i1 <= 2; i1++) { +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, i1, box); +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, 18 - i1, box); ++ int i; ++ int j; ++ ++ for (i = 7; i <= 11; ++i) { ++ for (j = 0; j <= 2; ++j) { ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, 18 - j, box); + } + } + +@@ -159,339 +228,230 @@ + this.generateBox(level, box, 0, 0, 7, 3, 1, 11, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 15, 0, 7, 18, 1, 11, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + +- for (int i = 0; i <= 2; i++) { +- for (int i1 = 7; i1 <= 11; i1++) { +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, i1, box); +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), 18 - i, -1, i1, box); ++ for (i = 0; i <= 2; ++i) { ++ for (j = 7; j <= 11; ++j) { ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), 18 - i, -1, j, box); + } + } ++ + } + } + +- public static class BridgeEndFiller extends NetherFortressPieces.NetherBridgePiece { +- private static final int WIDTH = 5; +- private static final int HEIGHT = 10; +- private static final int DEPTH = 8; +- private final int selfSeed; ++ public static class RoomCrossing extends NetherFortressPieces.NetherBridgePiece { + +- public BridgeEndFiller(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { +- super(StructurePieceType.NETHER_FORTRESS_BRIDGE_END_FILLER, genDepth, box); ++ private static final int WIDTH = 7; ++ private static final int HEIGHT = 9; ++ private static final int DEPTH = 7; ++ ++ public RoomCrossing(int genDepth, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_ROOM_CROSSING, genDepth, box); + this.setOrientation(orientation); +- this.selfSeed = random.nextInt(); + } + +- public BridgeEndFiller(CompoundTag tag) { +- super(StructurePieceType.NETHER_FORTRESS_BRIDGE_END_FILLER, tag); +- this.selfSeed = tag.getInt("Seed"); ++ public RoomCrossing(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_ROOM_CROSSING, tag); + } + +- public static NetherFortressPieces.BridgeEndFiller createPiece( +- StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth +- ) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -1, -3, 0, 5, 10, 8, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new NetherFortressPieces.BridgeEndFiller(genDepth, random, boundingBox, orientation) +- : null; ++ @Override ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateChildForward((NetherFortressPieces.StartPiece) piece, pieces, random, 2, 0, false); ++ this.generateChildLeft((NetherFortressPieces.StartPiece) piece, pieces, random, 0, 2, false); ++ this.generateChildRight((NetherFortressPieces.StartPiece) piece, pieces, random, 0, 2, false); + } + +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { +- super.addAdditionalSaveData(context, tag); +- tag.putInt("Seed", this.selfSeed); ++ public static NetherFortressPieces.RoomCrossing createPiece(StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -2, 0, 0, 7, 9, 7, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.RoomCrossing(genDepth, structureboundingbox, orientation) : null; + } + + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { +- RandomSource randomSource = RandomSource.create((long)this.selfSeed); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 6, 1, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 6, 7, 6, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 1, 6, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 6, 1, 6, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 2, 0, 6, 6, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 2, 6, 6, 6, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 0, 6, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 5, 0, 6, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 2, 0, 6, 6, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 2, 5, 6, 6, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); + +- for (int i = 0; i <= 4; i++) { +- for (int i1 = 3; i1 <= 4; i1++) { +- int randomInt = randomSource.nextInt(8); +- this.generateBox( +- level, box, i, i1, 0, i, i1, randomInt, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false +- ); +- } +- } ++ this.generateBox(level, box, 2, 6, 0, 4, 6, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 5, 0, 4, 5, 0, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 2, 6, 6, 4, 6, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 5, 6, 4, 5, 6, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 0, 6, 2, 0, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 5, 2, 0, 5, 4, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 6, 6, 2, 6, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 5, 2, 6, 5, 4, iblockdata1, iblockdata1, false); + +- int i = randomSource.nextInt(8); +- this.generateBox(level, box, 0, 5, 0, 0, 5, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- i = randomSource.nextInt(8); +- this.generateBox(level, box, 4, 5, 0, 4, 5, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- +- for (int ix = 0; ix <= 4; ix++) { +- int i1 = randomSource.nextInt(5); +- this.generateBox(level, box, ix, 2, 0, ix, 2, i1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- } +- +- for (int ix = 0; ix <= 4; ix++) { +- for (int i1 = 0; i1 <= 1; i1++) { +- int randomInt = randomSource.nextInt(3); +- this.generateBox( +- level, box, ix, i1, 0, ix, i1, randomInt, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false +- ); ++ for (int i = 0; i <= 6; ++i) { ++ for (int j = 0; j <= 6; ++j) { ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); + } + } ++ + } + } + +- public static class BridgeStraight extends NetherFortressPieces.NetherBridgePiece { +- private static final int WIDTH = 5; +- private static final int HEIGHT = 10; +- private static final int DEPTH = 19; ++ public static class StairsRoom extends NetherFortressPieces.NetherBridgePiece { + +- public BridgeStraight(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { +- super(StructurePieceType.NETHER_FORTRESS_BRIDGE_STRAIGHT, genDepth, box); ++ private static final int WIDTH = 7; ++ private static final int HEIGHT = 11; ++ private static final int DEPTH = 7; ++ ++ public StairsRoom(int genDepth, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_STAIRS_ROOM, genDepth, box); + this.setOrientation(orientation); + } + +- public BridgeStraight(CompoundTag tag) { +- super(StructurePieceType.NETHER_FORTRESS_BRIDGE_STRAIGHT, tag); ++ public StairsRoom(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_STAIRS_ROOM, tag); + } + + @Override + public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- this.generateChildForward((NetherFortressPieces.StartPiece)piece, pieces, random, 1, 3, false); ++ this.generateChildRight((NetherFortressPieces.StartPiece) piece, pieces, random, 6, 2, false); + } + +- public static NetherFortressPieces.BridgeStraight createPiece( +- StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth +- ) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -1, -3, 0, 5, 10, 19, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new NetherFortressPieces.BridgeStraight(genDepth, random, boundingBox, orientation) +- : null; ++ public static NetherFortressPieces.StairsRoom createPiece(StructurePieceAccessor pieces, int x, int y, int z, int genDepth, Direction orientation) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -2, 0, 0, 7, 11, 7, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.StairsRoom(genDepth, structureboundingbox, orientation) : null; + } + + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { +- this.generateBox(level, box, 0, 3, 0, 4, 4, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 1, 5, 0, 3, 7, 18, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(level, box, 0, 5, 0, 0, 5, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 4, 5, 0, 4, 5, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 0, 2, 0, 4, 2, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 0, 2, 13, 4, 2, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 0, 0, 0, 4, 1, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 0, 0, 15, 4, 1, 18, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 6, 1, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 6, 10, 6, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 1, 8, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 2, 0, 6, 8, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 1, 0, 8, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 2, 1, 6, 8, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 2, 6, 5, 8, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); + +- for (int i = 0; i <= 4; i++) { +- for (int i1 = 0; i1 <= 2; i1++) { +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, i1, box); +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, 18 - i1, box); ++ this.generateBox(level, box, 0, 3, 2, 0, 5, 4, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 6, 3, 2, 6, 5, 2, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 6, 3, 4, 6, 5, 4, iblockdata1, iblockdata1, false); ++ this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), 5, 2, 5, box); ++ this.generateBox(level, box, 4, 2, 5, 4, 3, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 3, 2, 5, 3, 4, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 2, 5, 2, 5, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 2, 5, 1, 6, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 7, 1, 5, 7, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 8, 2, 6, 8, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 6, 0, 4, 8, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 2, 5, 0, 4, 5, 0, iblockdata, iblockdata, false); ++ ++ for (int i = 0; i <= 6; ++i) { ++ for (int j = 0; j <= 6; ++j) { ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); + } + } + +- BlockState blockState = Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.NORTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.SOUTH, Boolean.valueOf(true)); +- BlockState blockState1 = blockState.setValue(FenceBlock.EAST, Boolean.valueOf(true)); +- BlockState blockState2 = blockState.setValue(FenceBlock.WEST, Boolean.valueOf(true)); +- this.generateBox(level, box, 0, 1, 1, 0, 4, 1, blockState1, blockState1, false); +- this.generateBox(level, box, 0, 3, 4, 0, 4, 4, blockState1, blockState1, false); +- this.generateBox(level, box, 0, 3, 14, 0, 4, 14, blockState1, blockState1, false); +- this.generateBox(level, box, 0, 1, 17, 0, 4, 17, blockState1, blockState1, false); +- this.generateBox(level, box, 4, 1, 1, 4, 4, 1, blockState2, blockState2, false); +- this.generateBox(level, box, 4, 3, 4, 4, 4, 4, blockState2, blockState2, false); +- this.generateBox(level, box, 4, 3, 14, 4, 4, 14, blockState2, blockState2, false); +- this.generateBox(level, box, 4, 1, 17, 4, 4, 17, blockState2, blockState2, false); + } + } + +- public static class CastleCorridorStairsPiece extends NetherFortressPieces.NetherBridgePiece { +- private static final int WIDTH = 5; +- private static final int HEIGHT = 14; +- private static final int DEPTH = 10; ++ public static class MonsterThrone extends NetherFortressPieces.NetherBridgePiece { + +- public CastleCorridorStairsPiece(int genDepth, BoundingBox box, Direction orientation) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_CORRIDOR_STAIRS, genDepth, box); ++ private static final int WIDTH = 7; ++ private static final int HEIGHT = 8; ++ private static final int DEPTH = 9; ++ private boolean hasPlacedSpawner; ++ ++ public MonsterThrone(int genDepth, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_MONSTER_THRONE, genDepth, box); + this.setOrientation(orientation); + } + +- public CastleCorridorStairsPiece(CompoundTag tag) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_CORRIDOR_STAIRS, tag); ++ public MonsterThrone(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_MONSTER_THRONE, tag); ++ this.hasPlacedSpawner = tag.getBoolean("Mob"); + } + + @Override +- public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- this.generateChildForward((NetherFortressPieces.StartPiece)piece, pieces, random, 1, 0, true); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putBoolean("Mob", this.hasPlacedSpawner); + } + +- public static NetherFortressPieces.CastleCorridorStairsPiece createPiece( +- StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth +- ) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -1, -7, 0, 5, 14, 10, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new NetherFortressPieces.CastleCorridorStairsPiece(genDepth, boundingBox, orientation) +- : null; ++ public static NetherFortressPieces.MonsterThrone createPiece(StructurePieceAccessor pieces, int x, int y, int z, int genDepth, Direction orientation) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -2, 0, 0, 7, 8, 9, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.MonsterThrone(genDepth, structureboundingbox, orientation) : null; + } + + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { +- BlockState blockState = Blocks.NETHER_BRICK_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.SOUTH); +- BlockState blockState1 = Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.NORTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.SOUTH, Boolean.valueOf(true)); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 2, 0, 6, 7, 7, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 0, 0, 5, 1, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 2, 1, 5, 2, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 3, 2, 5, 3, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 4, 3, 5, 4, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 2, 0, 1, 4, 2, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 2, 0, 5, 4, 2, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 5, 2, 1, 5, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 5, 2, 5, 5, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 5, 3, 0, 5, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 5, 3, 6, 5, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 5, 8, 5, 5, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); + +- for (int i = 0; i <= 9; i++) { +- int max = Math.max(1, 7 - i); +- int min = Math.min(Math.max(max + 5, 14 - i), 13); +- int i1 = i; +- this.generateBox(level, box, 0, 0, i, 4, max, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 1, max + 1, i, 3, min - 1, i, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- if (i <= 6) { +- this.placeBlock(level, blockState, 1, max + 1, i, box); +- this.placeBlock(level, blockState, 2, max + 1, i, box); +- this.placeBlock(level, blockState, 3, max + 1, i, box); +- } ++ this.placeBlock(level, (IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true), 1, 6, 3, box); ++ this.placeBlock(level, (IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true), 5, 6, 3, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true)).setValue(FenceBlock.NORTH, true), 0, 6, 3, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.NORTH, true), 6, 6, 3, box); ++ this.generateBox(level, box, 0, 6, 4, 0, 6, 7, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 6, 6, 4, 6, 6, 7, iblockdata1, iblockdata1, false); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true)).setValue(FenceBlock.SOUTH, true), 0, 6, 8, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.SOUTH, true), 6, 6, 8, box); ++ this.generateBox(level, box, 1, 6, 8, 5, 6, 8, iblockdata, iblockdata, false); ++ this.placeBlock(level, (IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true), 1, 7, 8, box); ++ this.generateBox(level, box, 2, 7, 8, 4, 7, 8, iblockdata, iblockdata, false); ++ this.placeBlock(level, (IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true), 5, 7, 8, box); ++ this.placeBlock(level, (IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true), 2, 8, 8, box); ++ this.placeBlock(level, iblockdata, 3, 8, 8, box); ++ this.placeBlock(level, (IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true), 4, 8, 8, box); ++ if (!this.hasPlacedSpawner) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(3, 5, 5); + +- this.generateBox(level, box, 0, min, i, 4, min, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox( +- level, box, 0, max + 1, i, 0, min - 1, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false +- ); +- this.generateBox( +- level, box, 4, max + 1, i, 4, min - 1, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false +- ); +- if ((i & 1) == 0) { +- this.generateBox(level, box, 0, max + 2, i, 0, max + 3, i, blockState1, blockState1, false); +- this.generateBox(level, box, 4, max + 2, i, 4, max + 3, i, blockState1, blockState1, false); +- } ++ if (box.isInside(blockposition_mutableblockposition)) { ++ this.hasPlacedSpawner = true; ++ // CraftBukkit start ++ /* ++ generatoraccessseed.setBlock(blockposition_mutableblockposition, Blocks.SPAWNER.defaultBlockState(), 2); ++ TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); + +- for (int i2 = 0; i2 <= 4; i2++) { +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i2, -1, i1, box); ++ if (tileentity instanceof TileEntityMobSpawner) { ++ TileEntityMobSpawner tileentitymobspawner = (TileEntityMobSpawner) tileentity; ++ ++ tileentitymobspawner.setEntityId(EntityTypes.BLAZE, randomsource); ++ } ++ */ ++ placeCraftSpawner(level, blockposition_mutableblockposition, org.bukkit.entity.EntityType.BLAZE, 2); ++ // CraftBukkit end + } + } +- } +- } + +- public static class CastleCorridorTBalconyPiece extends NetherFortressPieces.NetherBridgePiece { +- private static final int WIDTH = 9; +- private static final int HEIGHT = 7; +- private static final int DEPTH = 9; +- +- public CastleCorridorTBalconyPiece(int genDepth, BoundingBox box, Direction orientation) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_CORRIDOR_T_BALCONY, genDepth, box); +- this.setOrientation(orientation); +- } +- +- public CastleCorridorTBalconyPiece(CompoundTag tag) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_CORRIDOR_T_BALCONY, tag); +- } +- +- @Override +- public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- int i = 1; +- Direction orientation = this.getOrientation(); +- if (orientation == Direction.WEST || orientation == Direction.NORTH) { +- i = 5; ++ for (int i = 0; i <= 6; ++i) { ++ for (int j = 0; j <= 6; ++j) { ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); ++ } + } + +- this.generateChildLeft((NetherFortressPieces.StartPiece)piece, pieces, random, 0, i, random.nextInt(8) > 0); +- this.generateChildRight((NetherFortressPieces.StartPiece)piece, pieces, random, 0, i, random.nextInt(8) > 0); + } +- +- public static NetherFortressPieces.CastleCorridorTBalconyPiece createPiece( +- StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth +- ) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -3, 0, 0, 9, 7, 9, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new NetherFortressPieces.CastleCorridorTBalconyPiece(genDepth, boundingBox, orientation) +- : null; +- } +- +- @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { +- BlockState blockState = Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.NORTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.SOUTH, Boolean.valueOf(true)); +- BlockState blockState1 = Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.WEST, Boolean.valueOf(true)) +- .setValue(FenceBlock.EAST, Boolean.valueOf(true)); +- this.generateBox(level, box, 0, 0, 0, 8, 1, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 0, 2, 0, 8, 5, 8, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(level, box, 0, 6, 0, 8, 6, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 0, 2, 0, 2, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 6, 2, 0, 8, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 1, 3, 0, 1, 4, 0, blockState1, blockState1, false); +- this.generateBox(level, box, 7, 3, 0, 7, 4, 0, blockState1, blockState1, false); +- this.generateBox(level, box, 0, 2, 4, 8, 2, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 1, 1, 4, 2, 2, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(level, box, 6, 1, 4, 7, 2, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(level, box, 1, 3, 8, 7, 3, 8, blockState1, blockState1, false); +- this.placeBlock( +- level, +- Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.EAST, Boolean.valueOf(true)) +- .setValue(FenceBlock.SOUTH, Boolean.valueOf(true)), +- 0, +- 3, +- 8, +- box +- ); +- this.placeBlock( +- level, +- Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.WEST, Boolean.valueOf(true)) +- .setValue(FenceBlock.SOUTH, Boolean.valueOf(true)), +- 8, +- 3, +- 8, +- box +- ); +- this.generateBox(level, box, 0, 3, 6, 0, 3, 7, blockState, blockState, false); +- this.generateBox(level, box, 8, 3, 6, 8, 3, 7, blockState, blockState, false); +- this.generateBox(level, box, 0, 3, 4, 0, 5, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 8, 3, 4, 8, 5, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 1, 3, 5, 2, 5, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 6, 3, 5, 7, 5, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 1, 4, 5, 1, 5, 5, blockState1, blockState1, false); +- this.generateBox(level, box, 7, 4, 5, 7, 5, 5, blockState1, blockState1, false); +- +- for (int i = 0; i <= 5; i++) { +- for (int i1 = 0; i1 <= 8; i1++) { +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i1, -1, i, box); +- } +- } +- } + } + + public static class CastleEntrance extends NetherFortressPieces.NetherBridgePiece { ++ + private static final int WIDTH = 13; + private static final int HEIGHT = 14; + private static final int DEPTH = 13; +@@ -507,28 +467,17 @@ + + @Override + public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- this.generateChildForward((NetherFortressPieces.StartPiece)piece, pieces, random, 5, 3, true); ++ this.generateChildForward((NetherFortressPieces.StartPiece) piece, pieces, random, 5, 3, true); + } + +- public static NetherFortressPieces.CastleEntrance createPiece( +- StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth +- ) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -5, -3, 0, 13, 14, 13, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new NetherFortressPieces.CastleEntrance(genDepth, random, boundingBox, orientation) +- : null; ++ public static NetherFortressPieces.CastleEntrance createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -5, -3, 0, 13, 14, 13, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.CastleEntrance(genDepth, random, structureboundingbox, orientation) : null; + } + + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { + this.generateBox(level, box, 0, 3, 0, 12, 4, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 0, 5, 0, 12, 13, 12, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); + this.generateBox(level, box, 0, 5, 0, 1, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +@@ -541,104 +490,36 @@ + this.generateBox(level, box, 5, 9, 0, 7, 12, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 2, 11, 2, 10, 12, 10, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 5, 8, 0, 7, 8, 0, Blocks.NETHER_BRICK_FENCE.defaultBlockState(), Blocks.NETHER_BRICK_FENCE.defaultBlockState(), false); +- BlockState blockState = Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.WEST, Boolean.valueOf(true)) +- .setValue(FenceBlock.EAST, Boolean.valueOf(true)); +- BlockState blockState1 = Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.NORTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.SOUTH, Boolean.valueOf(true)); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); + +- for (int i = 1; i <= 11; i += 2) { +- this.generateBox(level, box, i, 10, 0, i, 11, 0, blockState, blockState, false); +- this.generateBox(level, box, i, 10, 12, i, 11, 12, blockState, blockState, false); +- this.generateBox(level, box, 0, 10, i, 0, 11, i, blockState1, blockState1, false); +- this.generateBox(level, box, 12, 10, i, 12, 11, i, blockState1, blockState1, false); ++ int i; ++ ++ for (i = 1; i <= 11; i += 2) { ++ this.generateBox(level, box, i, 10, 0, i, 11, 0, iblockdata, iblockdata, false); ++ this.generateBox(level, box, i, 10, 12, i, 11, 12, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 0, 10, i, 0, 11, i, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 12, 10, i, 12, 11, i, iblockdata1, iblockdata1, false); + this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, 13, 0, box); + this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, 13, 12, box); + this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), 0, 13, i, box); + this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), 12, 13, i, box); + if (i != 11) { +- this.placeBlock(level, blockState, i + 1, 13, 0, box); +- this.placeBlock(level, blockState, i + 1, 13, 12, box); +- this.placeBlock(level, blockState1, 0, 13, i + 1, box); +- this.placeBlock(level, blockState1, 12, 13, i + 1, box); ++ this.placeBlock(level, iblockdata, i + 1, 13, 0, box); ++ this.placeBlock(level, iblockdata, i + 1, 13, 12, box); ++ this.placeBlock(level, iblockdata1, 0, 13, i + 1, box); ++ this.placeBlock(level, iblockdata1, 12, 13, i + 1, box); + } + } + +- this.placeBlock( +- level, +- Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.NORTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.EAST, Boolean.valueOf(true)), +- 0, +- 13, +- 0, +- box +- ); +- this.placeBlock( +- level, +- Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.SOUTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.EAST, Boolean.valueOf(true)), +- 0, +- 13, +- 12, +- box +- ); +- this.placeBlock( +- level, +- Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.SOUTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.WEST, Boolean.valueOf(true)), +- 12, +- 13, +- 12, +- box +- ); +- this.placeBlock( +- level, +- Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.NORTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.WEST, Boolean.valueOf(true)), +- 12, +- 13, +- 0, +- box +- ); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.EAST, true), 0, 13, 0, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.SOUTH, true)).setValue(FenceBlock.EAST, true), 0, 13, 12, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.SOUTH, true)).setValue(FenceBlock.WEST, true), 12, 13, 12, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.WEST, true), 12, 13, 0, box); + +- for (int ix = 3; ix <= 9; ix += 2) { +- this.generateBox( +- level, +- box, +- 1, +- 7, +- ix, +- 1, +- 8, +- ix, +- blockState1.setValue(FenceBlock.WEST, Boolean.valueOf(true)), +- blockState1.setValue(FenceBlock.WEST, Boolean.valueOf(true)), +- false +- ); +- this.generateBox( +- level, +- box, +- 11, +- 7, +- ix, +- 11, +- 8, +- ix, +- blockState1.setValue(FenceBlock.EAST, Boolean.valueOf(true)), +- blockState1.setValue(FenceBlock.EAST, Boolean.valueOf(true)), +- false +- ); ++ for (i = 3; i <= 9; i += 2) { ++ this.generateBox(level, box, 1, 7, i, 1, 8, i, (IBlockData) iblockdata1.setValue(FenceBlock.WEST, true), (IBlockData) iblockdata1.setValue(FenceBlock.WEST, true), false); ++ this.generateBox(level, box, 11, 7, i, 11, 8, i, (IBlockData) iblockdata1.setValue(FenceBlock.EAST, true), (IBlockData) iblockdata1.setValue(FenceBlock.EAST, true), false); + } + + this.generateBox(level, box, 4, 2, 0, 8, 2, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +@@ -648,17 +529,19 @@ + this.generateBox(level, box, 0, 0, 4, 3, 1, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 9, 0, 4, 12, 1, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + +- for (int ix = 4; ix <= 8; ix++) { +- for (int i1 = 0; i1 <= 2; i1++) { +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), ix, -1, i1, box); +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), ix, -1, 12 - i1, box); ++ int j; ++ ++ for (i = 4; i <= 8; ++i) { ++ for (j = 0; j <= 2; ++j) { ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, 12 - j, box); + } + } + +- for (int ix = 0; ix <= 2; ix++) { +- for (int i1 = 4; i1 <= 8; i1++) { +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), ix, -1, i1, box); +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), 12 - ix, -1, i1, box); ++ for (i = 0; i <= 2; ++i) { ++ for (j = 4; j <= 8; ++j) { ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), 12 - i, -1, j, box); + } + } + +@@ -666,70 +549,131 @@ + this.generateBox(level, box, 6, 1, 6, 6, 4, 6, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); + this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), 6, 0, 6, box); + this.placeBlock(level, Blocks.LAVA.defaultBlockState(), 6, 5, 6, box); +- BlockPos worldPos = this.getWorldPos(6, 5, 6); +- if (box.isInside(worldPos)) { +- level.scheduleTick(worldPos, Fluids.LAVA, 0); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(6, 5, 6); ++ ++ if (box.isInside(blockposition_mutableblockposition)) { ++ level.scheduleTick(blockposition_mutableblockposition, (Fluid) Fluids.LAVA, 0); + } ++ + } + } + +- public static class CastleSmallCorridorCrossingPiece extends NetherFortressPieces.NetherBridgePiece { ++ public static class CastleSmallCorridorPiece extends NetherFortressPieces.NetherBridgePiece { ++ + private static final int WIDTH = 5; + private static final int HEIGHT = 7; + private static final int DEPTH = 5; + +- public CastleSmallCorridorCrossingPiece(int genDepth, BoundingBox box, Direction orientation) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR_CROSSING, genDepth, box); ++ public CastleSmallCorridorPiece(int genDepth, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR, genDepth, box); + this.setOrientation(orientation); + } + +- public CastleSmallCorridorCrossingPiece(CompoundTag tag) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR_CROSSING, tag); ++ public CastleSmallCorridorPiece(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR, tag); + } + + @Override + public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- this.generateChildForward((NetherFortressPieces.StartPiece)piece, pieces, random, 1, 0, true); +- this.generateChildLeft((NetherFortressPieces.StartPiece)piece, pieces, random, 0, 1, true); +- this.generateChildRight((NetherFortressPieces.StartPiece)piece, pieces, random, 0, 1, true); ++ this.generateChildForward((NetherFortressPieces.StartPiece) piece, pieces, random, 1, 0, true); + } + +- public static NetherFortressPieces.CastleSmallCorridorCrossingPiece createPiece( +- StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth +- ) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -1, 0, 0, 5, 7, 5, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new NetherFortressPieces.CastleSmallCorridorCrossingPiece(genDepth, boundingBox, orientation) +- : null; ++ public static NetherFortressPieces.CastleSmallCorridorPiece createPiece(StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, 0, 0, 5, 7, 5, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.CastleSmallCorridorPiece(genDepth, structureboundingbox, orientation) : null; + } + + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { + this.generateBox(level, box, 0, 0, 0, 4, 1, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 0, 2, 0, 4, 5, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(level, box, 0, 2, 0, 0, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); ++ ++ this.generateBox(level, box, 0, 2, 0, 0, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 2, 0, 4, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 3, 1, 0, 4, 1, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 0, 3, 3, 0, 4, 3, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 4, 3, 1, 4, 4, 1, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 4, 3, 3, 4, 4, 3, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 0, 6, 0, 4, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ ++ for (int i = 0; i <= 4; ++i) { ++ for (int j = 0; j <= 4; ++j) { ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); ++ } ++ } ++ ++ } ++ } ++ ++ public static class CastleSmallCorridorRightTurnPiece extends NetherFortressPieces.NetherBridgePiece { ++ ++ private static final int WIDTH = 5; ++ private static final int HEIGHT = 7; ++ private static final int DEPTH = 5; ++ private boolean isNeedingChest; ++ ++ public CastleSmallCorridorRightTurnPiece(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR_RIGHT_TURN, genDepth, box); ++ this.setOrientation(orientation); ++ this.isNeedingChest = random.nextInt(3) == 0; ++ } ++ ++ public CastleSmallCorridorRightTurnPiece(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR_RIGHT_TURN, tag); ++ this.isNeedingChest = tag.getBoolean("Chest"); ++ } ++ ++ @Override ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putBoolean("Chest", this.isNeedingChest); ++ } ++ ++ @Override ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateChildRight((NetherFortressPieces.StartPiece) piece, pieces, random, 0, 1, true); ++ } ++ ++ public static NetherFortressPieces.CastleSmallCorridorRightTurnPiece createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, 0, 0, 5, 7, 5, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.CastleSmallCorridorRightTurnPiece(genDepth, random, structureboundingbox, orientation) : null; ++ } ++ ++ @Override ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 4, 1, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 4, 5, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); ++ ++ this.generateBox(level, box, 0, 2, 0, 0, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 3, 1, 0, 4, 1, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 0, 3, 3, 0, 4, 3, iblockdata1, iblockdata1, false); + this.generateBox(level, box, 4, 2, 0, 4, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 0, 2, 4, 0, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 4, 2, 4, 4, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 2, 4, 4, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 3, 4, 1, 4, 4, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 3, 3, 4, 3, 4, 4, iblockdata, iblockdata, false); ++ if (this.isNeedingChest && box.isInside(this.getWorldPos(1, 2, 3))) { ++ this.isNeedingChest = false; ++ this.createChest(level, box, random, 1, 2, 3, BuiltInLootTables.NETHER_BRIDGE); ++ } ++ + this.generateBox(level, box, 0, 6, 0, 4, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + +- for (int i = 0; i <= 4; i++) { +- for (int i1 = 0; i1 <= 4; i1++) { +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, i1, box); ++ for (int i = 0; i <= 4; ++i) { ++ for (int j = 0; j <= 4; ++j) { ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); + } + } ++ + } + } + + public static class CastleSmallCorridorLeftTurnPiece extends NetherFortressPieces.NetherBridgePiece { ++ + private static final int WIDTH = 5; + private static final int HEIGHT = 7; + private static final int DEPTH = 5; +@@ -754,45 +698,29 @@ + + @Override + public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- this.generateChildLeft((NetherFortressPieces.StartPiece)piece, pieces, random, 0, 1, true); ++ this.generateChildLeft((NetherFortressPieces.StartPiece) piece, pieces, random, 0, 1, true); + } + +- public static NetherFortressPieces.CastleSmallCorridorLeftTurnPiece createPiece( +- StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth +- ) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -1, 0, 0, 5, 7, 5, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new NetherFortressPieces.CastleSmallCorridorLeftTurnPiece(genDepth, random, boundingBox, orientation) +- : null; ++ public static NetherFortressPieces.CastleSmallCorridorLeftTurnPiece createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, 0, 0, 5, 7, 5, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.CastleSmallCorridorLeftTurnPiece(genDepth, random, structureboundingbox, orientation) : null; + } + + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { + this.generateBox(level, box, 0, 0, 0, 4, 1, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 0, 2, 0, 4, 5, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- BlockState blockState = Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.WEST, Boolean.valueOf(true)) +- .setValue(FenceBlock.EAST, Boolean.valueOf(true)); +- BlockState blockState1 = Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.NORTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.SOUTH, Boolean.valueOf(true)); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); ++ + this.generateBox(level, box, 4, 2, 0, 4, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 4, 3, 1, 4, 4, 1, blockState1, blockState1, false); +- this.generateBox(level, box, 4, 3, 3, 4, 4, 3, blockState1, blockState1, false); ++ this.generateBox(level, box, 4, 3, 1, 4, 4, 1, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 4, 3, 3, 4, 4, 3, iblockdata1, iblockdata1, false); + this.generateBox(level, box, 0, 2, 0, 0, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 0, 2, 4, 3, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 1, 3, 4, 1, 4, 4, blockState, blockState, false); +- this.generateBox(level, box, 3, 3, 4, 3, 4, 4, blockState, blockState, false); ++ this.generateBox(level, box, 1, 3, 4, 1, 4, 4, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 3, 3, 4, 3, 4, 4, iblockdata, iblockdata, false); + if (this.isNeedingChest && box.isInside(this.getWorldPos(3, 2, 3))) { + this.isNeedingChest = false; + this.createChest(level, box, random, 3, 2, 3, BuiltInLootTables.NETHER_BRIDGE); +@@ -800,154 +728,194 @@ + + this.generateBox(level, box, 0, 6, 0, 4, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + +- for (int i = 0; i <= 4; i++) { +- for (int i1 = 0; i1 <= 4; i1++) { +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, i1, box); ++ for (int i = 0; i <= 4; ++i) { ++ for (int j = 0; j <= 4; ++j) { ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); + } + } ++ + } + } + +- public static class CastleSmallCorridorPiece extends NetherFortressPieces.NetherBridgePiece { ++ public static class CastleCorridorStairsPiece extends NetherFortressPieces.NetherBridgePiece { ++ + private static final int WIDTH = 5; +- private static final int HEIGHT = 7; +- private static final int DEPTH = 5; ++ private static final int HEIGHT = 14; ++ private static final int DEPTH = 10; + +- public CastleSmallCorridorPiece(int genDepth, BoundingBox box, Direction orientation) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR, genDepth, box); ++ public CastleCorridorStairsPiece(int genDepth, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_CORRIDOR_STAIRS, genDepth, box); + this.setOrientation(orientation); + } + +- public CastleSmallCorridorPiece(CompoundTag tag) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR, tag); ++ public CastleCorridorStairsPiece(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_CORRIDOR_STAIRS, tag); + } + + @Override + public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- this.generateChildForward((NetherFortressPieces.StartPiece)piece, pieces, random, 1, 0, true); ++ this.generateChildForward((NetherFortressPieces.StartPiece) piece, pieces, random, 1, 0, true); + } + +- public static NetherFortressPieces.CastleSmallCorridorPiece createPiece( +- StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth +- ) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -1, 0, 0, 5, 7, 5, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new NetherFortressPieces.CastleSmallCorridorPiece(genDepth, boundingBox, orientation) +- : null; ++ public static NetherFortressPieces.CastleCorridorStairsPiece createPiece(StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -7, 0, 5, 14, 10, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.CastleCorridorStairsPiece(genDepth, structureboundingbox, orientation) : null; + } + + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { +- this.generateBox(level, box, 0, 0, 0, 4, 1, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 0, 2, 0, 4, 5, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- BlockState blockState = Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.NORTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.SOUTH, Boolean.valueOf(true)); +- this.generateBox(level, box, 0, 2, 0, 0, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 4, 2, 0, 4, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 0, 3, 1, 0, 4, 1, blockState, blockState, false); +- this.generateBox(level, box, 0, 3, 3, 0, 4, 3, blockState, blockState, false); +- this.generateBox(level, box, 4, 3, 1, 4, 4, 1, blockState, blockState, false); +- this.generateBox(level, box, 4, 3, 3, 4, 4, 3, blockState, blockState, false); +- this.generateBox(level, box, 0, 6, 0, 4, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ IBlockData iblockdata = (IBlockData) Blocks.NETHER_BRICK_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.SOUTH); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); + +- for (int i = 0; i <= 4; i++) { +- for (int i1 = 0; i1 <= 4; i1++) { +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, i1, box); ++ for (int i = 0; i <= 9; ++i) { ++ int j = Math.max(1, 7 - i); ++ int k = Math.min(Math.max(j + 5, 14 - i), 13); ++ int l = i; ++ ++ this.generateBox(level, box, 0, 0, i, 4, j, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, j + 1, i, 3, k - 1, i, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ if (i <= 6) { ++ this.placeBlock(level, iblockdata, 1, j + 1, i, box); ++ this.placeBlock(level, iblockdata, 2, j + 1, i, box); ++ this.placeBlock(level, iblockdata, 3, j + 1, i, box); + } ++ ++ this.generateBox(level, box, 0, k, i, 4, k, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, j + 1, i, 0, k - 1, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 4, j + 1, i, 4, k - 1, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ if ((i & 1) == 0) { ++ this.generateBox(level, box, 0, j + 2, i, 0, j + 3, i, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 4, j + 2, i, 4, j + 3, i, iblockdata1, iblockdata1, false); ++ } ++ ++ for (int i1 = 0; i1 <= 4; ++i1) { ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i1, -1, l, box); ++ } + } ++ + } + } + +- public static class CastleSmallCorridorRightTurnPiece extends NetherFortressPieces.NetherBridgePiece { +- private static final int WIDTH = 5; ++ public static class CastleCorridorTBalconyPiece extends NetherFortressPieces.NetherBridgePiece { ++ ++ private static final int WIDTH = 9; + private static final int HEIGHT = 7; +- private static final int DEPTH = 5; +- private boolean isNeedingChest; ++ private static final int DEPTH = 9; + +- public CastleSmallCorridorRightTurnPiece(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR_RIGHT_TURN, genDepth, box); ++ public CastleCorridorTBalconyPiece(int genDepth, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_CORRIDOR_T_BALCONY, genDepth, box); + this.setOrientation(orientation); +- this.isNeedingChest = random.nextInt(3) == 0; + } + +- public CastleSmallCorridorRightTurnPiece(CompoundTag tag) { +- super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR_RIGHT_TURN, tag); +- this.isNeedingChest = tag.getBoolean("Chest"); ++ public CastleCorridorTBalconyPiece(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_CORRIDOR_T_BALCONY, tag); + } + + @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { +- super.addAdditionalSaveData(context, tag); +- tag.putBoolean("Chest", this.isNeedingChest); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ byte b0 = 1; ++ Direction enumdirection = this.getOrientation(); ++ ++ if (enumdirection == Direction.WEST || enumdirection == Direction.NORTH) { ++ b0 = 5; ++ } ++ ++ this.generateChildLeft((NetherFortressPieces.StartPiece) piece, pieces, random, 0, b0, random.nextInt(8) > 0); ++ this.generateChildRight((NetherFortressPieces.StartPiece) piece, pieces, random, 0, b0, random.nextInt(8) > 0); + } + ++ public static NetherFortressPieces.CastleCorridorTBalconyPiece createPiece(StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -3, 0, 0, 9, 7, 9, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.CastleCorridorTBalconyPiece(genDepth, structureboundingbox, orientation) : null; ++ } ++ + @Override ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); ++ ++ this.generateBox(level, box, 0, 0, 0, 8, 1, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 8, 5, 8, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 6, 0, 8, 6, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 0, 2, 0, 2, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 2, 0, 8, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 3, 0, 1, 4, 0, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 7, 3, 0, 7, 4, 0, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 0, 2, 4, 8, 2, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 1, 4, 2, 2, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 1, 4, 7, 2, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 3, 8, 7, 3, 8, iblockdata1, iblockdata1, false); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true)).setValue(FenceBlock.SOUTH, true), 0, 3, 8, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.SOUTH, true), 8, 3, 8, box); ++ this.generateBox(level, box, 0, 3, 6, 0, 3, 7, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 8, 3, 6, 8, 3, 7, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 0, 3, 4, 0, 5, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 8, 3, 4, 8, 5, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 3, 5, 2, 5, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 3, 5, 7, 5, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 4, 5, 1, 5, 5, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 7, 4, 5, 7, 5, 5, iblockdata1, iblockdata1, false); ++ ++ for (int i = 0; i <= 5; ++i) { ++ for (int j = 0; j <= 8; ++j) { ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), j, -1, i, box); ++ } ++ } ++ ++ } ++ } ++ ++ public static class CastleSmallCorridorCrossingPiece extends NetherFortressPieces.NetherBridgePiece { ++ ++ private static final int WIDTH = 5; ++ private static final int HEIGHT = 7; ++ private static final int DEPTH = 5; ++ ++ public CastleSmallCorridorCrossingPiece(int genDepth, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR_CROSSING, genDepth, box); ++ this.setOrientation(orientation); ++ } ++ ++ public CastleSmallCorridorCrossingPiece(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_CASTLE_SMALL_CORRIDOR_CROSSING, tag); ++ } ++ ++ @Override + public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- this.generateChildRight((NetherFortressPieces.StartPiece)piece, pieces, random, 0, 1, true); ++ this.generateChildForward((NetherFortressPieces.StartPiece) piece, pieces, random, 1, 0, true); ++ this.generateChildLeft((NetherFortressPieces.StartPiece) piece, pieces, random, 0, 1, true); ++ this.generateChildRight((NetherFortressPieces.StartPiece) piece, pieces, random, 0, 1, true); + } + +- public static NetherFortressPieces.CastleSmallCorridorRightTurnPiece createPiece( +- StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth +- ) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -1, 0, 0, 5, 7, 5, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new NetherFortressPieces.CastleSmallCorridorRightTurnPiece(genDepth, random, boundingBox, orientation) +- : null; ++ public static NetherFortressPieces.CastleSmallCorridorCrossingPiece createPiece(StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, 0, 0, 5, 7, 5, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.CastleSmallCorridorCrossingPiece(genDepth, structureboundingbox, orientation) : null; + } + + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { + this.generateBox(level, box, 0, 0, 0, 4, 1, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 0, 2, 0, 4, 5, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- BlockState blockState = Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.WEST, Boolean.valueOf(true)) +- .setValue(FenceBlock.EAST, Boolean.valueOf(true)); +- BlockState blockState1 = Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.NORTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.SOUTH, Boolean.valueOf(true)); +- this.generateBox(level, box, 0, 2, 0, 0, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 0, 3, 1, 0, 4, 1, blockState1, blockState1, false); +- this.generateBox(level, box, 0, 3, 3, 0, 4, 3, blockState1, blockState1, false); ++ this.generateBox(level, box, 0, 2, 0, 0, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 4, 2, 0, 4, 5, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 1, 2, 4, 4, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 1, 3, 4, 1, 4, 4, blockState, blockState, false); +- this.generateBox(level, box, 3, 3, 4, 3, 4, 4, blockState, blockState, false); +- if (this.isNeedingChest && box.isInside(this.getWorldPos(1, 2, 3))) { +- this.isNeedingChest = false; +- this.createChest(level, box, random, 1, 2, 3, BuiltInLootTables.NETHER_BRIDGE); +- } +- ++ this.generateBox(level, box, 0, 2, 4, 0, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 2, 4, 4, 5, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 0, 6, 0, 4, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + +- for (int i = 0; i <= 4; i++) { +- for (int i1 = 0; i1 <= 4; i1++) { +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, i1, box); ++ for (int i = 0; i <= 4; ++i) { ++ for (int j = 0; j <= 4; ++j) { ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, j, box); + } + } ++ + } + } + + public static class CastleStalkRoom extends NetherFortressPieces.NetherBridgePiece { ++ + private static final int WIDTH = 13; + private static final int HEIGHT = 14; + private static final int DEPTH = 13; +@@ -963,27 +931,18 @@ + + @Override + public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- this.generateChildForward((NetherFortressPieces.StartPiece)piece, pieces, random, 5, 3, true); +- this.generateChildForward((NetherFortressPieces.StartPiece)piece, pieces, random, 5, 11, true); ++ this.generateChildForward((NetherFortressPieces.StartPiece) piece, pieces, random, 5, 3, true); ++ this.generateChildForward((NetherFortressPieces.StartPiece) piece, pieces, random, 5, 11, true); + } + + public static NetherFortressPieces.CastleStalkRoom createPiece(StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -5, -3, 0, 13, 14, 13, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new NetherFortressPieces.CastleStalkRoom(genDepth, boundingBox, orientation) +- : null; ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -5, -3, 0, 13, 14, 13, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.CastleStalkRoom(genDepth, structureboundingbox, orientation) : null; + } + + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { + this.generateBox(level, box, 0, 3, 0, 12, 4, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 0, 5, 0, 12, 13, 12, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); + this.generateBox(level, box, 0, 5, 0, 1, 12, 12, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +@@ -995,114 +954,69 @@ + this.generateBox(level, box, 8, 5, 0, 10, 12, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 5, 9, 0, 7, 12, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 2, 11, 2, 10, 12, 10, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- BlockState blockState = Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.WEST, Boolean.valueOf(true)) +- .setValue(FenceBlock.EAST, Boolean.valueOf(true)); +- BlockState blockState1 = Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.NORTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.SOUTH, Boolean.valueOf(true)); +- BlockState blockState2 = blockState1.setValue(FenceBlock.WEST, Boolean.valueOf(true)); +- BlockState blockState3 = blockState1.setValue(FenceBlock.EAST, Boolean.valueOf(true)); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); ++ IBlockData iblockdata2 = (IBlockData) iblockdata1.setValue(FenceBlock.WEST, true); ++ IBlockData iblockdata3 = (IBlockData) iblockdata1.setValue(FenceBlock.EAST, true); + +- for (int i = 1; i <= 11; i += 2) { +- this.generateBox(level, box, i, 10, 0, i, 11, 0, blockState, blockState, false); +- this.generateBox(level, box, i, 10, 12, i, 11, 12, blockState, blockState, false); +- this.generateBox(level, box, 0, 10, i, 0, 11, i, blockState1, blockState1, false); +- this.generateBox(level, box, 12, 10, i, 12, 11, i, blockState1, blockState1, false); ++ int i; ++ ++ for (i = 1; i <= 11; i += 2) { ++ this.generateBox(level, box, i, 10, 0, i, 11, 0, iblockdata, iblockdata, false); ++ this.generateBox(level, box, i, 10, 12, i, 11, 12, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 0, 10, i, 0, 11, i, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 12, 10, i, 12, 11, i, iblockdata1, iblockdata1, false); + this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, 13, 0, box); + this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, 13, 12, box); + this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), 0, 13, i, box); + this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), 12, 13, i, box); + if (i != 11) { +- this.placeBlock(level, blockState, i + 1, 13, 0, box); +- this.placeBlock(level, blockState, i + 1, 13, 12, box); +- this.placeBlock(level, blockState1, 0, 13, i + 1, box); +- this.placeBlock(level, blockState1, 12, 13, i + 1, box); ++ this.placeBlock(level, iblockdata, i + 1, 13, 0, box); ++ this.placeBlock(level, iblockdata, i + 1, 13, 12, box); ++ this.placeBlock(level, iblockdata1, 0, 13, i + 1, box); ++ this.placeBlock(level, iblockdata1, 12, 13, i + 1, box); + } + } + +- this.placeBlock( +- level, +- Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.NORTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.EAST, Boolean.valueOf(true)), +- 0, +- 13, +- 0, +- box +- ); +- this.placeBlock( +- level, +- Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.SOUTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.EAST, Boolean.valueOf(true)), +- 0, +- 13, +- 12, +- box +- ); +- this.placeBlock( +- level, +- Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.SOUTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.WEST, Boolean.valueOf(true)), +- 12, +- 13, +- 12, +- box +- ); +- this.placeBlock( +- level, +- Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.NORTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.WEST, Boolean.valueOf(true)), +- 12, +- 13, +- 0, +- box +- ); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.EAST, true), 0, 13, 0, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.SOUTH, true)).setValue(FenceBlock.EAST, true), 0, 13, 12, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.SOUTH, true)).setValue(FenceBlock.WEST, true), 12, 13, 12, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.WEST, true), 12, 13, 0, box); + +- for (int ix = 3; ix <= 9; ix += 2) { +- this.generateBox(level, box, 1, 7, ix, 1, 8, ix, blockState2, blockState2, false); +- this.generateBox(level, box, 11, 7, ix, 11, 8, ix, blockState3, blockState3, false); ++ for (i = 3; i <= 9; i += 2) { ++ this.generateBox(level, box, 1, 7, i, 1, 8, i, iblockdata2, iblockdata2, false); ++ this.generateBox(level, box, 11, 7, i, 11, 8, i, iblockdata3, iblockdata3, false); + } + +- BlockState blockState4 = Blocks.NETHER_BRICK_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.NORTH); ++ IBlockData iblockdata4 = (IBlockData) Blocks.NETHER_BRICK_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.NORTH); + +- for (int i1 = 0; i1 <= 6; i1++) { +- int i2 = i1 + 4; ++ int j; ++ int k; + +- for (int i3 = 5; i3 <= 7; i3++) { +- this.placeBlock(level, blockState4, i3, 5 + i1, i2, box); ++ for (j = 0; j <= 6; ++j) { ++ int l = j + 4; ++ ++ for (k = 5; k <= 7; ++k) { ++ this.placeBlock(level, iblockdata4, k, 5 + j, l, box); + } + +- if (i2 >= 5 && i2 <= 8) { +- this.generateBox( +- level, box, 5, 5, i2, 7, i1 + 4, i2, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false +- ); +- } else if (i2 >= 9 && i2 <= 10) { +- this.generateBox( +- level, box, 5, 8, i2, 7, i1 + 4, i2, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false +- ); ++ if (l >= 5 && l <= 8) { ++ this.generateBox(level, box, 5, 5, l, 7, j + 4, l, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ } else if (l >= 9 && l <= 10) { ++ this.generateBox(level, box, 5, 8, l, 7, j + 4, l, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + } + +- if (i1 >= 1) { +- this.generateBox(level, box, 5, 6 + i1, i2, 7, 9 + i1, i2, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); ++ if (j >= 1) { ++ this.generateBox(level, box, 5, 6 + j, l, 7, 9 + j, l, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); + } + } + +- for (int i1 = 5; i1 <= 7; i1++) { +- this.placeBlock(level, blockState4, i1, 12, 11, box); ++ for (j = 5; j <= 7; ++j) { ++ this.placeBlock(level, iblockdata4, j, 12, 11, box); + } + +- this.generateBox(level, box, 5, 6, 7, 5, 7, 7, blockState3, blockState3, false); +- this.generateBox(level, box, 7, 6, 7, 7, 7, 7, blockState2, blockState2, false); ++ this.generateBox(level, box, 5, 6, 7, 5, 7, 7, iblockdata3, iblockdata3, false); ++ this.generateBox(level, box, 7, 6, 7, 7, 7, 7, iblockdata2, iblockdata2, false); + this.generateBox(level, box, 5, 13, 12, 7, 13, 12, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); + this.generateBox(level, box, 2, 5, 2, 3, 5, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 2, 5, 9, 3, 5, 10, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +@@ -1110,16 +1024,17 @@ + this.generateBox(level, box, 9, 5, 2, 10, 5, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 9, 5, 9, 10, 5, 10, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 10, 5, 4, 10, 5, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- BlockState blockState5 = blockState4.setValue(StairBlock.FACING, Direction.EAST); +- BlockState blockState6 = blockState4.setValue(StairBlock.FACING, Direction.WEST); +- this.placeBlock(level, blockState6, 4, 5, 2, box); +- this.placeBlock(level, blockState6, 4, 5, 3, box); +- this.placeBlock(level, blockState6, 4, 5, 9, box); +- this.placeBlock(level, blockState6, 4, 5, 10, box); +- this.placeBlock(level, blockState5, 8, 5, 2, box); +- this.placeBlock(level, blockState5, 8, 5, 3, box); +- this.placeBlock(level, blockState5, 8, 5, 9, box); +- this.placeBlock(level, blockState5, 8, 5, 10, box); ++ IBlockData iblockdata5 = (IBlockData) iblockdata4.setValue(StairBlock.FACING, Direction.EAST); ++ IBlockData iblockdata6 = (IBlockData) iblockdata4.setValue(StairBlock.FACING, Direction.WEST); ++ ++ this.placeBlock(level, iblockdata6, 4, 5, 2, box); ++ this.placeBlock(level, iblockdata6, 4, 5, 3, box); ++ this.placeBlock(level, iblockdata6, 4, 5, 9, box); ++ this.placeBlock(level, iblockdata6, 4, 5, 10, box); ++ this.placeBlock(level, iblockdata5, 8, 5, 2, box); ++ this.placeBlock(level, iblockdata5, 8, 5, 3, box); ++ this.placeBlock(level, iblockdata5, 8, 5, 9, box); ++ this.placeBlock(level, iblockdata5, 8, 5, 10, box); + this.generateBox(level, box, 3, 4, 4, 4, 4, 8, Blocks.SOUL_SAND.defaultBlockState(), Blocks.SOUL_SAND.defaultBlockState(), false); + this.generateBox(level, box, 8, 4, 4, 9, 4, 8, Blocks.SOUL_SAND.defaultBlockState(), Blocks.SOUL_SAND.defaultBlockState(), false); + this.generateBox(level, box, 3, 5, 4, 4, 5, 8, Blocks.NETHER_WART.defaultBlockState(), Blocks.NETHER_WART.defaultBlockState(), false); +@@ -1131,156 +1046,131 @@ + this.generateBox(level, box, 0, 0, 4, 3, 1, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + this.generateBox(level, box, 9, 0, 4, 12, 1, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + +- for (int i3 = 4; i3 <= 8; i3++) { +- for (int i4 = 0; i4 <= 2; i4++) { +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i3, -1, i4, box); +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i3, -1, 12 - i4, box); ++ int i1; ++ ++ for (k = 4; k <= 8; ++k) { ++ for (i1 = 0; i1 <= 2; ++i1) { ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), k, -1, i1, box); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), k, -1, 12 - i1, box); + } + } + +- for (int i3 = 0; i3 <= 2; i3++) { +- for (int i4 = 4; i4 <= 8; i4++) { +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i3, -1, i4, box); +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), 12 - i3, -1, i4, box); ++ for (k = 0; k <= 2; ++k) { ++ for (i1 = 4; i1 <= 8; ++i1) { ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), k, -1, i1, box); ++ this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), 12 - k, -1, i1, box); + } + } ++ + } + } + +- public static class MonsterThrone extends NetherFortressPieces.NetherBridgePiece { +- private static final int WIDTH = 7; +- private static final int HEIGHT = 8; +- private static final int DEPTH = 9; +- private boolean hasPlacedSpawner; ++ public static class BridgeEndFiller extends NetherFortressPieces.NetherBridgePiece { + +- public MonsterThrone(int genDepth, BoundingBox box, Direction orientation) { +- super(StructurePieceType.NETHER_FORTRESS_MONSTER_THRONE, genDepth, box); ++ private static final int WIDTH = 5; ++ private static final int HEIGHT = 10; ++ private static final int DEPTH = 8; ++ private final int selfSeed; ++ ++ public BridgeEndFiller(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.NETHER_FORTRESS_BRIDGE_END_FILLER, genDepth, box); + this.setOrientation(orientation); ++ this.selfSeed = random.nextInt(); + } + +- public MonsterThrone(CompoundTag tag) { +- super(StructurePieceType.NETHER_FORTRESS_MONSTER_THRONE, tag); +- this.hasPlacedSpawner = tag.getBoolean("Mob"); ++ public BridgeEndFiller(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_BRIDGE_END_FILLER, tag); ++ this.selfSeed = tag.getInt("Seed"); + } + ++ public static NetherFortressPieces.BridgeEndFiller createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -3, 0, 5, 10, 8, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new NetherFortressPieces.BridgeEndFiller(genDepth, random, structureboundingbox, orientation) : null; ++ } ++ + @Override + protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { + super.addAdditionalSaveData(context, tag); +- tag.putBoolean("Mob", this.hasPlacedSpawner); ++ tag.putInt("Seed", this.selfSeed); + } + +- public static NetherFortressPieces.MonsterThrone createPiece(StructurePieceAccessor pieces, int x, int y, int z, int genDepth, Direction orientation) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -2, 0, 0, 7, 8, 9, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new NetherFortressPieces.MonsterThrone(genDepth, boundingBox, orientation) +- : null; +- } +- + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { +- this.generateBox(level, box, 0, 2, 0, 6, 7, 7, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(level, box, 1, 0, 0, 5, 1, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 1, 2, 1, 5, 2, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 1, 3, 2, 5, 3, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 1, 4, 3, 5, 4, 7, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 1, 2, 0, 1, 4, 2, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 5, 2, 0, 5, 4, 2, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 1, 5, 2, 1, 5, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 5, 5, 2, 5, 5, 3, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 0, 5, 3, 0, 5, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 6, 5, 3, 6, 5, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 1, 5, 8, 5, 5, 8, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- BlockState blockState = Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.WEST, Boolean.valueOf(true)) +- .setValue(FenceBlock.EAST, Boolean.valueOf(true)); +- BlockState blockState1 = Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.NORTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.SOUTH, Boolean.valueOf(true)); +- this.placeBlock(level, Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, Boolean.valueOf(true)), 1, 6, 3, box); +- this.placeBlock(level, Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, Boolean.valueOf(true)), 5, 6, 3, box); +- this.placeBlock( +- level, +- Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.EAST, Boolean.valueOf(true)) +- .setValue(FenceBlock.NORTH, Boolean.valueOf(true)), +- 0, +- 6, +- 3, +- box +- ); +- this.placeBlock( +- level, +- Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.WEST, Boolean.valueOf(true)) +- .setValue(FenceBlock.NORTH, Boolean.valueOf(true)), +- 6, +- 6, +- 3, +- box +- ); +- this.generateBox(level, box, 0, 6, 4, 0, 6, 7, blockState1, blockState1, false); +- this.generateBox(level, box, 6, 6, 4, 6, 6, 7, blockState1, blockState1, false); +- this.placeBlock( +- level, +- Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.EAST, Boolean.valueOf(true)) +- .setValue(FenceBlock.SOUTH, Boolean.valueOf(true)), +- 0, +- 6, +- 8, +- box +- ); +- this.placeBlock( +- level, +- Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.WEST, Boolean.valueOf(true)) +- .setValue(FenceBlock.SOUTH, Boolean.valueOf(true)), +- 6, +- 6, +- 8, +- box +- ); +- this.generateBox(level, box, 1, 6, 8, 5, 6, 8, blockState, blockState, false); +- this.placeBlock(level, Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, Boolean.valueOf(true)), 1, 7, 8, box); +- this.generateBox(level, box, 2, 7, 8, 4, 7, 8, blockState, blockState, false); +- this.placeBlock(level, Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, Boolean.valueOf(true)), 5, 7, 8, box); +- this.placeBlock(level, Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, Boolean.valueOf(true)), 2, 8, 8, box); +- this.placeBlock(level, blockState, 3, 8, 8, box); +- this.placeBlock(level, Blocks.NETHER_BRICK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, Boolean.valueOf(true)), 4, 8, 8, box); +- if (!this.hasPlacedSpawner) { +- BlockPos worldPos = this.getWorldPos(3, 5, 5); +- if (box.isInside(worldPos)) { +- this.hasPlacedSpawner = true; +- level.setBlock(worldPos, Blocks.SPAWNER.defaultBlockState(), 2); +- if (level.getBlockEntity(worldPos) instanceof SpawnerBlockEntity spawnerBlockEntity) { +- spawnerBlockEntity.setEntityId(EntityType.BLAZE, random); +- } ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ RandomSource randomsource1 = RandomSource.create((long) this.selfSeed); ++ ++ int i; ++ int j; ++ int k; ++ ++ for (j = 0; j <= 4; ++j) { ++ for (k = 3; k <= 4; ++k) { ++ i = randomsource1.nextInt(8); ++ this.generateBox(level, box, j, k, 0, j, k, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + } + } + +- for (int i = 0; i <= 6; i++) { +- for (int i1 = 0; i1 <= 6; i1++) { +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, i1, box); ++ j = randomsource1.nextInt(8); ++ this.generateBox(level, box, 0, 5, 0, 0, 5, j, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ j = randomsource1.nextInt(8); ++ this.generateBox(level, box, 4, 5, 0, 4, 5, j, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ ++ for (j = 0; j <= 4; ++j) { ++ k = randomsource1.nextInt(5); ++ this.generateBox(level, box, j, 2, 0, j, 2, k, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); ++ } ++ ++ for (j = 0; j <= 4; ++j) { ++ for (k = 0; k <= 1; ++k) { ++ i = randomsource1.nextInt(3); ++ this.generateBox(level, box, j, k, 0, j, k, i, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); + } + } ++ + } + } + +- abstract static class NetherBridgePiece extends StructurePiece { ++ public static class StartPiece extends NetherFortressPieces.BridgeCrossing { ++ ++ public NetherFortressPieces.PieceWeight previousPiece; ++ public List availableBridgePieces; ++ public List availableCastlePieces; ++ public final List pendingChildren = Lists.newArrayList(); ++ ++ public StartPiece(RandomSource random, int x, int z) { ++ super(x, z, getRandomHorizontalDirection(random)); ++ this.availableBridgePieces = Lists.newArrayList(); ++ NetherFortressPieces.PieceWeight[] anetherfortresspieces_n = NetherFortressPieces.BRIDGE_PIECE_WEIGHTS; ++ int k = anetherfortresspieces_n.length; ++ ++ NetherFortressPieces.PieceWeight netherfortresspieces_n; ++ int l; ++ ++ for (l = 0; l < k; ++l) { ++ netherfortresspieces_n = anetherfortresspieces_n[l]; ++ netherfortresspieces_n.placeCount = 0; ++ this.availableBridgePieces.add(netherfortresspieces_n); ++ } ++ ++ this.availableCastlePieces = Lists.newArrayList(); ++ anetherfortresspieces_n = NetherFortressPieces.CASTLE_PIECE_WEIGHTS; ++ k = anetherfortresspieces_n.length; ++ ++ for (l = 0; l < k; ++l) { ++ netherfortresspieces_n = anetherfortresspieces_n[l]; ++ netherfortresspieces_n.placeCount = 0; ++ this.availableCastlePieces.add(netherfortresspieces_n); ++ } ++ ++ } ++ ++ public StartPiece(CompoundTag tag) { ++ super(StructurePieceType.NETHER_FORTRESS_START, tag); ++ } ++ } ++ ++ private abstract static class NetherBridgePiece extends StructurePiece { ++ + protected NetherBridgePiece(StructurePieceType type, int genDepth, BoundingBox boundingBox) { + super(type, genDepth, boundingBox); + } +@@ -1290,61 +1180,53 @@ + } + + @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { +- } ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) {} + + private int updatePieceWeight(List weights) { + boolean flag = false; + int i = 0; + +- for (NetherFortressPieces.PieceWeight pieceWeight : weights) { +- if (pieceWeight.maxPlaceCount > 0 && pieceWeight.placeCount < pieceWeight.maxPlaceCount) { ++ NetherFortressPieces.PieceWeight netherfortresspieces_n; ++ ++ for (Iterator iterator = weights.iterator(); iterator.hasNext(); i += netherfortresspieces_n.weight) { ++ netherfortresspieces_n = (NetherFortressPieces.PieceWeight) iterator.next(); ++ if (netherfortresspieces_n.maxPlaceCount > 0 && netherfortresspieces_n.placeCount < netherfortresspieces_n.maxPlaceCount) { + flag = true; + } +- +- i += pieceWeight.weight; + } + + return flag ? i : -1; + } + +- private NetherFortressPieces.NetherBridgePiece generatePiece( +- NetherFortressPieces.StartPiece startPiece, +- List weights, +- StructurePieceAccessor pieces, +- RandomSource random, +- int x, +- int y, +- int z, +- Direction orientation, +- int genDepth +- ) { +- int i = this.updatePieceWeight(weights); +- boolean flag = i > 0 && genDepth <= 30; +- int i1 = 0; ++ private NetherFortressPieces.NetherBridgePiece generatePiece(NetherFortressPieces.StartPiece startPiece, List weights, StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ int i1 = this.updatePieceWeight(weights); ++ boolean flag = i1 > 0 && genDepth <= 30; ++ int j1 = 0; + +- while (i1 < 5 && flag) { +- i1++; +- int randomInt = random.nextInt(i); ++ while (j1 < 5 && flag) { ++ ++j1; ++ int k1 = random.nextInt(i1); ++ Iterator iterator = weights.iterator(); + +- for (NetherFortressPieces.PieceWeight pieceWeight : weights) { +- randomInt -= pieceWeight.weight; +- if (randomInt < 0) { +- if (!pieceWeight.doPlace(genDepth) || pieceWeight == startPiece.previousPiece && !pieceWeight.allowInRow) { ++ while (iterator.hasNext()) { ++ NetherFortressPieces.PieceWeight netherfortresspieces_n = (NetherFortressPieces.PieceWeight) iterator.next(); ++ ++ k1 -= netherfortresspieces_n.weight; ++ if (k1 < 0) { ++ if (!netherfortresspieces_n.doPlace(genDepth) || netherfortresspieces_n == startPiece.previousPiece && !netherfortresspieces_n.allowInRow) { + break; + } + +- NetherFortressPieces.NetherBridgePiece netherBridgePiece = NetherFortressPieces.findAndCreateBridgePieceFactory( +- pieceWeight, pieces, random, x, y, z, orientation, genDepth +- ); +- if (netherBridgePiece != null) { +- pieceWeight.placeCount++; +- startPiece.previousPiece = pieceWeight; +- if (!pieceWeight.isValid()) { +- weights.remove(pieceWeight); ++ NetherFortressPieces.NetherBridgePiece netherfortresspieces_m = NetherFortressPieces.findAndCreateBridgePieceFactory(netherfortresspieces_n, pieces, random, x, y, z, orientation, genDepth); ++ ++ if (netherfortresspieces_m != null) { ++ ++netherfortresspieces_n.placeCount; ++ startPiece.previousPiece = netherfortresspieces_n; ++ if (!netherfortresspieces_n.isValid()) { ++ weights.remove(netherfortresspieces_n); + } + +- return netherBridgePiece; ++ return netherfortresspieces_m; + } + } + } +@@ -1353,90 +1235,41 @@ + return NetherFortressPieces.BridgeEndFiller.createPiece(pieces, random, x, y, z, orientation, genDepth); + } + +- private StructurePiece generateAndAddPiece( +- NetherFortressPieces.StartPiece startPiece, +- StructurePieceAccessor pieces, +- RandomSource random, +- int x, +- int y, +- int z, +- @Nullable Direction orientation, +- int genDepth, +- boolean castlePiece +- ) { ++ private StructurePiece generateAndAddPiece(NetherFortressPieces.StartPiece startPiece, StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, @Nullable Direction orientation, int genDepth, boolean castlePiece) { + if (Math.abs(x - startPiece.getBoundingBox().minX()) <= 112 && Math.abs(z - startPiece.getBoundingBox().minZ()) <= 112) { + List list = startPiece.availableBridgePieces; ++ + if (castlePiece) { + list = startPiece.availableCastlePieces; + } + +- StructurePiece structurePiece = this.generatePiece(startPiece, list, pieces, random, x, y, z, orientation, genDepth + 1); +- if (structurePiece != null) { +- pieces.addPiece(structurePiece); +- startPiece.pendingChildren.add(structurePiece); ++ NetherFortressPieces.NetherBridgePiece netherfortresspieces_m = this.generatePiece(startPiece, list, pieces, random, x, y, z, orientation, genDepth + 1); ++ ++ if (netherfortresspieces_m != null) { ++ pieces.addPiece(netherfortresspieces_m); ++ startPiece.pendingChildren.add(netherfortresspieces_m); + } + +- return structurePiece; ++ return netherfortresspieces_m; + } else { + return NetherFortressPieces.BridgeEndFiller.createPiece(pieces, random, x, y, z, orientation, genDepth); + } + } + + @Nullable +- protected StructurePiece generateChildForward( +- NetherFortressPieces.StartPiece startPiece, StructurePieceAccessor pieces, RandomSource random, int offsetX, int offsetY, boolean castlePiece +- ) { +- Direction orientation = this.getOrientation(); +- if (orientation != null) { +- switch (orientation) { ++ protected StructurePiece generateChildForward(NetherFortressPieces.StartPiece startPiece, StructurePieceAccessor pieces, RandomSource random, int offsetX, int offsetY, boolean castlePiece) { ++ Direction enumdirection = this.getOrientation(); ++ ++ if (enumdirection != null) { ++ switch (enumdirection) { + case NORTH: +- return this.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.minX() + offsetX, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.minZ() - 1, +- orientation, +- this.getGenDepth(), +- castlePiece +- ); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() - 1, enumdirection, this.getGenDepth(), castlePiece); + case SOUTH: +- return this.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.minX() + offsetX, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.maxZ() + 1, +- orientation, +- this.getGenDepth(), +- castlePiece +- ); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.maxZ() + 1, enumdirection, this.getGenDepth(), castlePiece); + case WEST: +- return this.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.minX() - 1, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.minZ() + offsetX, +- orientation, +- this.getGenDepth(), +- castlePiece +- ); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, enumdirection, this.getGenDepth(), castlePiece); + case EAST: +- return this.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.maxX() + 1, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.minZ() + offsetX, +- orientation, +- this.getGenDepth(), +- castlePiece +- ); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, enumdirection, this.getGenDepth(), castlePiece); + } + } + +@@ -1444,60 +1277,19 @@ + } + + @Nullable +- protected StructurePiece generateChildLeft( +- NetherFortressPieces.StartPiece startPiece, StructurePieceAccessor pieces, RandomSource random, int offsetY, int offsetX, boolean castlePiece +- ) { +- Direction orientation = this.getOrientation(); +- if (orientation != null) { +- switch (orientation) { ++ protected StructurePiece generateChildLeft(NetherFortressPieces.StartPiece startPiece, StructurePieceAccessor pieces, RandomSource random, int offsetY, int offsetX, boolean castlePiece) { ++ Direction enumdirection = this.getOrientation(); ++ ++ if (enumdirection != null) { ++ switch (enumdirection) { + case NORTH: +- return this.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.minX() - 1, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.minZ() + offsetX, +- Direction.WEST, +- this.getGenDepth(), +- castlePiece +- ); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, Direction.WEST, this.getGenDepth(), castlePiece); + case SOUTH: +- return this.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.minX() - 1, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.minZ() + offsetX, +- Direction.WEST, +- this.getGenDepth(), +- castlePiece +- ); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, Direction.WEST, this.getGenDepth(), castlePiece); + case WEST: +- return this.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.minX() + offsetX, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.minZ() - 1, +- Direction.NORTH, +- this.getGenDepth(), +- castlePiece +- ); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() - 1, Direction.NORTH, this.getGenDepth(), castlePiece); + case EAST: +- return this.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.minX() + offsetX, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.minZ() - 1, +- Direction.NORTH, +- this.getGenDepth(), +- castlePiece +- ); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() - 1, Direction.NORTH, this.getGenDepth(), castlePiece); + } + } + +@@ -1505,60 +1297,19 @@ + } + + @Nullable +- protected StructurePiece generateChildRight( +- NetherFortressPieces.StartPiece startPiece, StructurePieceAccessor pieces, RandomSource random, int offsetY, int offsetX, boolean castlePiece +- ) { +- Direction orientation = this.getOrientation(); +- if (orientation != null) { +- switch (orientation) { ++ protected StructurePiece generateChildRight(NetherFortressPieces.StartPiece startPiece, StructurePieceAccessor pieces, RandomSource random, int offsetY, int offsetX, boolean castlePiece) { ++ Direction enumdirection = this.getOrientation(); ++ ++ if (enumdirection != null) { ++ switch (enumdirection) { + case NORTH: +- return this.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.maxX() + 1, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.minZ() + offsetX, +- Direction.EAST, +- this.getGenDepth(), +- castlePiece +- ); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, Direction.EAST, this.getGenDepth(), castlePiece); + case SOUTH: +- return this.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.maxX() + 1, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.minZ() + offsetX, +- Direction.EAST, +- this.getGenDepth(), +- castlePiece +- ); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, Direction.EAST, this.getGenDepth(), castlePiece); + case WEST: +- return this.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.minX() + offsetX, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.maxZ() + 1, +- Direction.SOUTH, +- this.getGenDepth(), +- castlePiece +- ); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.maxZ() + 1, Direction.SOUTH, this.getGenDepth(), castlePiece); + case EAST: +- return this.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.minX() + offsetX, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.maxZ() + 1, +- Direction.SOUTH, +- this.getGenDepth(), +- castlePiece +- ); ++ return this.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.maxZ() + 1, Direction.SOUTH, this.getGenDepth(), castlePiece); + } + } + +@@ -1569,204 +1320,4 @@ + return box != null && box.minY() > 10; + } + } +- +- static class PieceWeight { +- public final Class pieceClass; +- public final int weight; +- public int placeCount; +- public final int maxPlaceCount; +- public final boolean allowInRow; +- +- public PieceWeight(Class pieceClass, int weight, int maxPlaceCount, boolean allowInRow) { +- this.pieceClass = pieceClass; +- this.weight = weight; +- this.maxPlaceCount = maxPlaceCount; +- this.allowInRow = allowInRow; +- } +- +- public PieceWeight(Class pieceClass, int weight, int maxPlaceCount) { +- this(pieceClass, weight, maxPlaceCount, false); +- } +- +- public boolean doPlace(int genDepth) { +- return this.maxPlaceCount == 0 || this.placeCount < this.maxPlaceCount; +- } +- +- public boolean isValid() { +- return this.maxPlaceCount == 0 || this.placeCount < this.maxPlaceCount; +- } +- } +- +- public static class RoomCrossing extends NetherFortressPieces.NetherBridgePiece { +- private static final int WIDTH = 7; +- private static final int HEIGHT = 9; +- private static final int DEPTH = 7; +- +- public RoomCrossing(int genDepth, BoundingBox box, Direction orientation) { +- super(StructurePieceType.NETHER_FORTRESS_ROOM_CROSSING, genDepth, box); +- this.setOrientation(orientation); +- } +- +- public RoomCrossing(CompoundTag tag) { +- super(StructurePieceType.NETHER_FORTRESS_ROOM_CROSSING, tag); +- } +- +- @Override +- public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- this.generateChildForward((NetherFortressPieces.StartPiece)piece, pieces, random, 2, 0, false); +- this.generateChildLeft((NetherFortressPieces.StartPiece)piece, pieces, random, 0, 2, false); +- this.generateChildRight((NetherFortressPieces.StartPiece)piece, pieces, random, 0, 2, false); +- } +- +- public static NetherFortressPieces.RoomCrossing createPiece(StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -2, 0, 0, 7, 9, 7, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new NetherFortressPieces.RoomCrossing(genDepth, boundingBox, orientation) +- : null; +- } +- +- @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { +- this.generateBox(level, box, 0, 0, 0, 6, 1, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 0, 2, 0, 6, 7, 6, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(level, box, 0, 2, 0, 1, 6, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 0, 2, 6, 1, 6, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 5, 2, 0, 6, 6, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 5, 2, 6, 6, 6, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 0, 2, 0, 0, 6, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 0, 2, 5, 0, 6, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 6, 2, 0, 6, 6, 1, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 6, 2, 5, 6, 6, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- BlockState blockState = Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.WEST, Boolean.valueOf(true)) +- .setValue(FenceBlock.EAST, Boolean.valueOf(true)); +- BlockState blockState1 = Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.NORTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.SOUTH, Boolean.valueOf(true)); +- this.generateBox(level, box, 2, 6, 0, 4, 6, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 2, 5, 0, 4, 5, 0, blockState, blockState, false); +- this.generateBox(level, box, 2, 6, 6, 4, 6, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 2, 5, 6, 4, 5, 6, blockState, blockState, false); +- this.generateBox(level, box, 0, 6, 2, 0, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 0, 5, 2, 0, 5, 4, blockState1, blockState1, false); +- this.generateBox(level, box, 6, 6, 2, 6, 6, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 6, 5, 2, 6, 5, 4, blockState1, blockState1, false); +- +- for (int i = 0; i <= 6; i++) { +- for (int i1 = 0; i1 <= 6; i1++) { +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, i1, box); +- } +- } +- } +- } +- +- public static class StairsRoom extends NetherFortressPieces.NetherBridgePiece { +- private static final int WIDTH = 7; +- private static final int HEIGHT = 11; +- private static final int DEPTH = 7; +- +- public StairsRoom(int genDepth, BoundingBox box, Direction orientation) { +- super(StructurePieceType.NETHER_FORTRESS_STAIRS_ROOM, genDepth, box); +- this.setOrientation(orientation); +- } +- +- public StairsRoom(CompoundTag tag) { +- super(StructurePieceType.NETHER_FORTRESS_STAIRS_ROOM, tag); +- } +- +- @Override +- public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- this.generateChildRight((NetherFortressPieces.StartPiece)piece, pieces, random, 6, 2, false); +- } +- +- public static NetherFortressPieces.StairsRoom createPiece(StructurePieceAccessor pieces, int x, int y, int z, int genDepth, Direction orientation) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -2, 0, 0, 7, 11, 7, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new NetherFortressPieces.StairsRoom(genDepth, boundingBox, orientation) +- : null; +- } +- +- @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { +- this.generateBox(level, box, 0, 0, 0, 6, 1, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 0, 2, 0, 6, 10, 6, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(level, box, 0, 2, 0, 1, 8, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 5, 2, 0, 6, 8, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 0, 2, 1, 0, 8, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 6, 2, 1, 6, 8, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 1, 2, 6, 5, 8, 6, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- BlockState blockState = Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.WEST, Boolean.valueOf(true)) +- .setValue(FenceBlock.EAST, Boolean.valueOf(true)); +- BlockState blockState1 = Blocks.NETHER_BRICK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.NORTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.SOUTH, Boolean.valueOf(true)); +- this.generateBox(level, box, 0, 3, 2, 0, 5, 4, blockState1, blockState1, false); +- this.generateBox(level, box, 6, 3, 2, 6, 5, 2, blockState1, blockState1, false); +- this.generateBox(level, box, 6, 3, 4, 6, 5, 4, blockState1, blockState1, false); +- this.placeBlock(level, Blocks.NETHER_BRICKS.defaultBlockState(), 5, 2, 5, box); +- this.generateBox(level, box, 4, 2, 5, 4, 3, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 3, 2, 5, 3, 4, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 2, 2, 5, 2, 5, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 1, 2, 5, 1, 6, 5, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 1, 7, 1, 5, 7, 4, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 6, 8, 2, 6, 8, 4, Blocks.AIR.defaultBlockState(), Blocks.AIR.defaultBlockState(), false); +- this.generateBox(level, box, 2, 6, 0, 4, 8, 0, Blocks.NETHER_BRICKS.defaultBlockState(), Blocks.NETHER_BRICKS.defaultBlockState(), false); +- this.generateBox(level, box, 2, 5, 0, 4, 5, 0, blockState, blockState, false); +- +- for (int i = 0; i <= 6; i++) { +- for (int i1 = 0; i1 <= 6; i1++) { +- this.fillColumnDown(level, Blocks.NETHER_BRICKS.defaultBlockState(), i, -1, i1, box); +- } +- } +- } +- } +- +- public static class StartPiece extends NetherFortressPieces.BridgeCrossing { +- public NetherFortressPieces.PieceWeight previousPiece; +- public List availableBridgePieces; +- public List availableCastlePieces; +- public final List pendingChildren = Lists.newArrayList(); +- +- public StartPiece(RandomSource random, int x, int z) { +- super(x, z, getRandomHorizontalDirection(random)); +- this.availableBridgePieces = Lists.newArrayList(); +- +- for (NetherFortressPieces.PieceWeight pieceWeight : NetherFortressPieces.BRIDGE_PIECE_WEIGHTS) { +- pieceWeight.placeCount = 0; +- this.availableBridgePieces.add(pieceWeight); +- } +- +- this.availableCastlePieces = Lists.newArrayList(); +- +- for (NetherFortressPieces.PieceWeight pieceWeight : NetherFortressPieces.CASTLE_PIECE_WEIGHTS) { +- pieceWeight.placeCount = 0; +- this.availableCastlePieces.add(pieceWeight); +- } +- } +- +- public StartPiece(CompoundTag tag) { +- super(StructurePieceType.NETHER_FORTRESS_START, tag); +- } +- } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java.patch new file mode 100644 index 0000000000..8d3d1d05b6 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java.patch @@ -0,0 +1,498 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.levelgen.structure.structures; + + import com.google.common.collect.Lists; ++import java.util.Iterator; + import java.util.List; + import net.minecraft.Util; + import net.minecraft.core.BlockPos; +@@ -12,7 +13,8 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.util.valueproviders.ConstantInt; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.monster.Drowned; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.ChunkPos; +@@ -24,9 +26,7 @@ + import net.minecraft.world.level.block.ChestBlock; + import net.minecraft.world.level.block.Mirror; + import net.minecraft.world.level.block.Rotation; +-import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.entity.ChestBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.levelgen.Heightmap; + import net.minecraft.world.level.levelgen.structure.BoundingBox; +@@ -34,12 +34,12 @@ + import net.minecraft.world.level.levelgen.structure.TemplateStructurePiece; + import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext; + import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceType; +-import net.minecraft.world.level.levelgen.structure.templatesystem.AlwaysTrueTest; + import net.minecraft.world.level.levelgen.structure.templatesystem.BlockIgnoreProcessor; + import net.minecraft.world.level.levelgen.structure.templatesystem.BlockMatchTest; + import net.minecraft.world.level.levelgen.structure.templatesystem.BlockRotProcessor; + import net.minecraft.world.level.levelgen.structure.templatesystem.CappedProcessor; +-import net.minecraft.world.level.levelgen.structure.templatesystem.PosAlwaysTrueTest; ++import net.minecraft.world.level.levelgen.structure.templatesystem.DefinedStructureTestTrue; ++import net.minecraft.world.level.levelgen.structure.templatesystem.PosRuleTestTrue; + import net.minecraft.world.level.levelgen.structure.templatesystem.ProcessorRule; + import net.minecraft.world.level.levelgen.structure.templatesystem.RuleProcessor; + import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; +@@ -51,145 +51,70 @@ + import net.minecraft.world.level.storage.loot.BuiltInLootTables; + + public class OceanRuinPieces { +- static final StructureProcessor WARM_SUSPICIOUS_BLOCK_PROCESSOR = archyRuleProcessor( +- Blocks.SAND, Blocks.SUSPICIOUS_SAND, BuiltInLootTables.OCEAN_RUIN_WARM_ARCHAEOLOGY +- ); +- static final StructureProcessor COLD_SUSPICIOUS_BLOCK_PROCESSOR = archyRuleProcessor( +- Blocks.GRAVEL, Blocks.SUSPICIOUS_GRAVEL, BuiltInLootTables.OCEAN_RUIN_COLD_ARCHAEOLOGY +- ); +- private static final ResourceLocation[] WARM_RUINS = new ResourceLocation[]{ +- new ResourceLocation("underwater_ruin/warm_1"), +- new ResourceLocation("underwater_ruin/warm_2"), +- new ResourceLocation("underwater_ruin/warm_3"), +- new ResourceLocation("underwater_ruin/warm_4"), +- new ResourceLocation("underwater_ruin/warm_5"), +- new ResourceLocation("underwater_ruin/warm_6"), +- new ResourceLocation("underwater_ruin/warm_7"), +- new ResourceLocation("underwater_ruin/warm_8") +- }; +- private static final ResourceLocation[] RUINS_BRICK = new ResourceLocation[]{ +- new ResourceLocation("underwater_ruin/brick_1"), +- new ResourceLocation("underwater_ruin/brick_2"), +- new ResourceLocation("underwater_ruin/brick_3"), +- new ResourceLocation("underwater_ruin/brick_4"), +- new ResourceLocation("underwater_ruin/brick_5"), +- new ResourceLocation("underwater_ruin/brick_6"), +- new ResourceLocation("underwater_ruin/brick_7"), +- new ResourceLocation("underwater_ruin/brick_8") +- }; +- private static final ResourceLocation[] RUINS_CRACKED = new ResourceLocation[]{ +- new ResourceLocation("underwater_ruin/cracked_1"), +- new ResourceLocation("underwater_ruin/cracked_2"), +- new ResourceLocation("underwater_ruin/cracked_3"), +- new ResourceLocation("underwater_ruin/cracked_4"), +- new ResourceLocation("underwater_ruin/cracked_5"), +- new ResourceLocation("underwater_ruin/cracked_6"), +- new ResourceLocation("underwater_ruin/cracked_7"), +- new ResourceLocation("underwater_ruin/cracked_8") +- }; +- private static final ResourceLocation[] RUINS_MOSSY = new ResourceLocation[]{ +- new ResourceLocation("underwater_ruin/mossy_1"), +- new ResourceLocation("underwater_ruin/mossy_2"), +- new ResourceLocation("underwater_ruin/mossy_3"), +- new ResourceLocation("underwater_ruin/mossy_4"), +- new ResourceLocation("underwater_ruin/mossy_5"), +- new ResourceLocation("underwater_ruin/mossy_6"), +- new ResourceLocation("underwater_ruin/mossy_7"), +- new ResourceLocation("underwater_ruin/mossy_8") +- }; +- private static final ResourceLocation[] BIG_RUINS_BRICK = new ResourceLocation[]{ +- new ResourceLocation("underwater_ruin/big_brick_1"), +- new ResourceLocation("underwater_ruin/big_brick_2"), +- new ResourceLocation("underwater_ruin/big_brick_3"), +- new ResourceLocation("underwater_ruin/big_brick_8") +- }; +- private static final ResourceLocation[] BIG_RUINS_MOSSY = new ResourceLocation[]{ +- new ResourceLocation("underwater_ruin/big_mossy_1"), +- new ResourceLocation("underwater_ruin/big_mossy_2"), +- new ResourceLocation("underwater_ruin/big_mossy_3"), +- new ResourceLocation("underwater_ruin/big_mossy_8") +- }; +- private static final ResourceLocation[] BIG_RUINS_CRACKED = new ResourceLocation[]{ +- new ResourceLocation("underwater_ruin/big_cracked_1"), +- new ResourceLocation("underwater_ruin/big_cracked_2"), +- new ResourceLocation("underwater_ruin/big_cracked_3"), +- new ResourceLocation("underwater_ruin/big_cracked_8") +- }; +- private static final ResourceLocation[] BIG_WARM_RUINS = new ResourceLocation[]{ +- new ResourceLocation("underwater_ruin/big_warm_4"), +- new ResourceLocation("underwater_ruin/big_warm_5"), +- new ResourceLocation("underwater_ruin/big_warm_6"), +- new ResourceLocation("underwater_ruin/big_warm_7") +- }; + ++ static final StructureProcessor WARM_SUSPICIOUS_BLOCK_PROCESSOR = archyRuleProcessor(Blocks.SAND, Blocks.SUSPICIOUS_SAND, BuiltInLootTables.OCEAN_RUIN_WARM_ARCHAEOLOGY); ++ static final StructureProcessor COLD_SUSPICIOUS_BLOCK_PROCESSOR = archyRuleProcessor(Blocks.GRAVEL, Blocks.SUSPICIOUS_GRAVEL, BuiltInLootTables.OCEAN_RUIN_COLD_ARCHAEOLOGY); ++ private static final ResourceLocation[] WARM_RUINS = new ResourceLocation[]{new ResourceLocation("underwater_ruin/warm_1"), new ResourceLocation("underwater_ruin/warm_2"), new ResourceLocation("underwater_ruin/warm_3"), new ResourceLocation("underwater_ruin/warm_4"), new ResourceLocation("underwater_ruin/warm_5"), new ResourceLocation("underwater_ruin/warm_6"), new ResourceLocation("underwater_ruin/warm_7"), new ResourceLocation("underwater_ruin/warm_8")}; ++ private static final ResourceLocation[] RUINS_BRICK = new ResourceLocation[]{new ResourceLocation("underwater_ruin/brick_1"), new ResourceLocation("underwater_ruin/brick_2"), new ResourceLocation("underwater_ruin/brick_3"), new ResourceLocation("underwater_ruin/brick_4"), new ResourceLocation("underwater_ruin/brick_5"), new ResourceLocation("underwater_ruin/brick_6"), new ResourceLocation("underwater_ruin/brick_7"), new ResourceLocation("underwater_ruin/brick_8")}; ++ private static final ResourceLocation[] RUINS_CRACKED = new ResourceLocation[]{new ResourceLocation("underwater_ruin/cracked_1"), new ResourceLocation("underwater_ruin/cracked_2"), new ResourceLocation("underwater_ruin/cracked_3"), new ResourceLocation("underwater_ruin/cracked_4"), new ResourceLocation("underwater_ruin/cracked_5"), new ResourceLocation("underwater_ruin/cracked_6"), new ResourceLocation("underwater_ruin/cracked_7"), new ResourceLocation("underwater_ruin/cracked_8")}; ++ private static final ResourceLocation[] RUINS_MOSSY = new ResourceLocation[]{new ResourceLocation("underwater_ruin/mossy_1"), new ResourceLocation("underwater_ruin/mossy_2"), new ResourceLocation("underwater_ruin/mossy_3"), new ResourceLocation("underwater_ruin/mossy_4"), new ResourceLocation("underwater_ruin/mossy_5"), new ResourceLocation("underwater_ruin/mossy_6"), new ResourceLocation("underwater_ruin/mossy_7"), new ResourceLocation("underwater_ruin/mossy_8")}; ++ private static final ResourceLocation[] BIG_RUINS_BRICK = new ResourceLocation[]{new ResourceLocation("underwater_ruin/big_brick_1"), new ResourceLocation("underwater_ruin/big_brick_2"), new ResourceLocation("underwater_ruin/big_brick_3"), new ResourceLocation("underwater_ruin/big_brick_8")}; ++ private static final ResourceLocation[] BIG_RUINS_MOSSY = new ResourceLocation[]{new ResourceLocation("underwater_ruin/big_mossy_1"), new ResourceLocation("underwater_ruin/big_mossy_2"), new ResourceLocation("underwater_ruin/big_mossy_3"), new ResourceLocation("underwater_ruin/big_mossy_8")}; ++ private static final ResourceLocation[] BIG_RUINS_CRACKED = new ResourceLocation[]{new ResourceLocation("underwater_ruin/big_cracked_1"), new ResourceLocation("underwater_ruin/big_cracked_2"), new ResourceLocation("underwater_ruin/big_cracked_3"), new ResourceLocation("underwater_ruin/big_cracked_8")}; ++ private static final ResourceLocation[] BIG_WARM_RUINS = new ResourceLocation[]{new ResourceLocation("underwater_ruin/big_warm_4"), new ResourceLocation("underwater_ruin/big_warm_5"), new ResourceLocation("underwater_ruin/big_warm_6"), new ResourceLocation("underwater_ruin/big_warm_7")}; ++ ++ public OceanRuinPieces() {} ++ + private static StructureProcessor archyRuleProcessor(Block input, Block output, ResourceLocation lootTable) { +- return new CappedProcessor( +- new RuleProcessor( +- List.of( +- new ProcessorRule( +- new BlockMatchTest(input), AlwaysTrueTest.INSTANCE, PosAlwaysTrueTest.INSTANCE, output.defaultBlockState(), new AppendLoot(lootTable) +- ) +- ) +- ), +- ConstantInt.of(5) +- ); ++ return new CappedProcessor(new RuleProcessor(List.of(new ProcessorRule(new BlockMatchTest(input), DefinedStructureTestTrue.INSTANCE, PosRuleTestTrue.INSTANCE, output.defaultBlockState(), new AppendLoot(lootTable)))), ConstantInt.of(5)); + } + + private static ResourceLocation getSmallWarmRuin(RandomSource random) { +- return Util.getRandom(WARM_RUINS, random); ++ return (ResourceLocation) Util.getRandom((Object[]) OceanRuinPieces.WARM_RUINS, random); + } + + private static ResourceLocation getBigWarmRuin(RandomSource random) { +- return Util.getRandom(BIG_WARM_RUINS, random); ++ return (ResourceLocation) Util.getRandom((Object[]) OceanRuinPieces.BIG_WARM_RUINS, random); + } + +- public static void addPieces( +- StructureTemplateManager structureTemplateManager, +- BlockPos pos, +- Rotation rotation, +- StructurePieceAccessor structurePieceAccessor, +- RandomSource random, +- OceanRuinStructure structure +- ) { ++ public static void addPieces(StructureTemplateManager structureTemplateManager, BlockPos pos, Rotation rotation, StructurePieceAccessor structurePieceAccessor, RandomSource random, OceanRuinStructure structure) { + boolean flag = random.nextFloat() <= structure.largeProbability; + float f = flag ? 0.9F : 0.8F; ++ + addPiece(structureTemplateManager, pos, rotation, structurePieceAccessor, random, structure, flag, f); + if (flag && random.nextFloat() <= structure.clusterProbability) { + addClusterRuins(structureTemplateManager, random, rotation, pos, structure, structurePieceAccessor); + } ++ + } + +- private static void addClusterRuins( +- StructureTemplateManager structureTemplateManager, +- RandomSource random, +- Rotation rotation, +- BlockPos pos, +- OceanRuinStructure structure, +- StructurePieceAccessor structurePieceAccessor +- ) { +- BlockPos blockPos = new BlockPos(pos.getX(), 90, pos.getZ()); +- BlockPos blockPos1 = StructureTemplate.transform(new BlockPos(15, 0, 15), Mirror.NONE, rotation, BlockPos.ZERO).offset(blockPos); +- BoundingBox boundingBox = BoundingBox.fromCorners(blockPos, blockPos1); +- BlockPos blockPos2 = new BlockPos(Math.min(blockPos.getX(), blockPos1.getX()), blockPos.getY(), Math.min(blockPos.getZ(), blockPos1.getZ())); +- List list = allPositions(random, blockPos2); +- int randomInt = Mth.nextInt(random, 4, 8); ++ private static void addClusterRuins(StructureTemplateManager structureTemplateManager, RandomSource random, Rotation rotation, BlockPos pos, OceanRuinStructure structure, StructurePieceAccessor structurePieceAccessor) { ++ BlockPos blockposition1 = new BlockPos(pos.getX(), 90, pos.getZ()); ++ BlockPos blockposition2 = StructureTemplate.transform(new BlockPos(15, 0, 15), Mirror.NONE, rotation, BlockPos.ZERO).offset(blockposition1); ++ BoundingBox structureboundingbox = BoundingBox.fromCorners(blockposition1, blockposition2); ++ BlockPos blockposition3 = new BlockPos(Math.min(blockposition1.getX(), blockposition2.getX()), blockposition1.getY(), Math.min(blockposition1.getZ(), blockposition2.getZ())); ++ List list = allPositions(random, blockposition3); ++ int i = Mth.nextInt(random, 4, 8); + +- for (int i = 0; i < randomInt; i++) { ++ for (int j = 0; j < i; ++j) { + if (!list.isEmpty()) { +- int randomInt1 = random.nextInt(list.size()); +- BlockPos blockPos3 = list.remove(randomInt1); +- Rotation random1 = Rotation.getRandom(random); +- BlockPos blockPos4 = StructureTemplate.transform(new BlockPos(5, 0, 6), Mirror.NONE, random1, BlockPos.ZERO).offset(blockPos3); +- BoundingBox boundingBox1 = BoundingBox.fromCorners(blockPos3, blockPos4); +- if (!boundingBox1.intersects(boundingBox)) { +- addPiece(structureTemplateManager, blockPos3, random1, structurePieceAccessor, random, structure, false, 0.8F); ++ int k = random.nextInt(list.size()); ++ BlockPos blockposition4 = (BlockPos) list.remove(k); ++ Rotation enumblockrotation1 = Rotation.getRandom(random); ++ BlockPos blockposition5 = StructureTemplate.transform(new BlockPos(5, 0, 6), Mirror.NONE, enumblockrotation1, BlockPos.ZERO).offset(blockposition4); ++ BoundingBox structureboundingbox1 = BoundingBox.fromCorners(blockposition4, blockposition5); ++ ++ if (!structureboundingbox1.intersects(structureboundingbox)) { ++ addPiece(structureTemplateManager, blockposition4, enumblockrotation1, structurePieceAccessor, random, structure, false, 0.8F); + } + } + } ++ + } + + private static List allPositions(RandomSource random, BlockPos pos) { + List list = Lists.newArrayList(); ++ + list.add(pos.offset(-16 + Mth.nextInt(random, 1, 8), 0, 16 + Mth.nextInt(random, 1, 7))); + list.add(pos.offset(-16 + Mth.nextInt(random, 1, 8), 0, Mth.nextInt(random, 1, 7))); + list.add(pos.offset(-16 + Mth.nextInt(random, 1, 8), 0, -16 + Mth.nextInt(random, 4, 8))); +@@ -201,99 +126,62 @@ + return list; + } + +- private static void addPiece( +- StructureTemplateManager structureTemplateManager, +- BlockPos pos, +- Rotation rotation, +- StructurePieceAccessor structurePieceAccessor, +- RandomSource random, +- OceanRuinStructure structure, +- boolean isLarge, +- float integrity +- ) { ++ private static void addPiece(StructureTemplateManager structureTemplateManager, BlockPos pos, Rotation rotation, StructurePieceAccessor structurePieceAccessor, RandomSource random, OceanRuinStructure structure, boolean isLarge, float integrity) { + switch (structure.biomeTemp) { + case WARM: + default: +- ResourceLocation resourceLocation = isLarge ? getBigWarmRuin(random) : getSmallWarmRuin(random); +- structurePieceAccessor.addPiece( +- new OceanRuinPieces.OceanRuinPiece(structureTemplateManager, resourceLocation, pos, rotation, integrity, structure.biomeTemp, isLarge) +- ); ++ ResourceLocation minecraftkey = isLarge ? getBigWarmRuin(random) : getSmallWarmRuin(random); ++ ++ structurePieceAccessor.addPiece(new OceanRuinPieces.OceanRuinPiece(structureTemplateManager, minecraftkey, pos, rotation, integrity, structure.biomeTemp, isLarge)); + break; + case COLD: +- ResourceLocation[] resourceLocations = isLarge ? BIG_RUINS_BRICK : RUINS_BRICK; +- ResourceLocation[] resourceLocations1 = isLarge ? BIG_RUINS_CRACKED : RUINS_CRACKED; +- ResourceLocation[] resourceLocations2 = isLarge ? BIG_RUINS_MOSSY : RUINS_MOSSY; +- int randomInt = random.nextInt(resourceLocations.length); +- structurePieceAccessor.addPiece( +- new OceanRuinPieces.OceanRuinPiece( +- structureTemplateManager, resourceLocations[randomInt], pos, rotation, integrity, structure.biomeTemp, isLarge +- ) +- ); +- structurePieceAccessor.addPiece( +- new OceanRuinPieces.OceanRuinPiece( +- structureTemplateManager, resourceLocations1[randomInt], pos, rotation, 0.7F, structure.biomeTemp, isLarge +- ) +- ); +- structurePieceAccessor.addPiece( +- new OceanRuinPieces.OceanRuinPiece( +- structureTemplateManager, resourceLocations2[randomInt], pos, rotation, 0.5F, structure.biomeTemp, isLarge +- ) +- ); ++ ResourceLocation[] aminecraftkey = isLarge ? OceanRuinPieces.BIG_RUINS_BRICK : OceanRuinPieces.RUINS_BRICK; ++ ResourceLocation[] aminecraftkey1 = isLarge ? OceanRuinPieces.BIG_RUINS_CRACKED : OceanRuinPieces.RUINS_CRACKED; ++ ResourceLocation[] aminecraftkey2 = isLarge ? OceanRuinPieces.BIG_RUINS_MOSSY : OceanRuinPieces.RUINS_MOSSY; ++ int i = random.nextInt(aminecraftkey.length); ++ ++ structurePieceAccessor.addPiece(new OceanRuinPieces.OceanRuinPiece(structureTemplateManager, aminecraftkey[i], pos, rotation, integrity, structure.biomeTemp, isLarge)); ++ structurePieceAccessor.addPiece(new OceanRuinPieces.OceanRuinPiece(structureTemplateManager, aminecraftkey1[i], pos, rotation, 0.7F, structure.biomeTemp, isLarge)); ++ structurePieceAccessor.addPiece(new OceanRuinPieces.OceanRuinPiece(structureTemplateManager, aminecraftkey2[i], pos, rotation, 0.5F, structure.biomeTemp, isLarge)); + } ++ + } + + public static class OceanRuinPiece extends TemplateStructurePiece { ++ + private final OceanRuinStructure.Type biomeType; + private final float integrity; + private final boolean isLarge; + +- public OceanRuinPiece( +- StructureTemplateManager structureTemplateManager, +- ResourceLocation location, +- BlockPos pos, +- Rotation rotation, +- float integrity, +- OceanRuinStructure.Type biomeType, +- boolean isLarge +- ) { ++ public OceanRuinPiece(StructureTemplateManager structureTemplateManager, ResourceLocation location, BlockPos pos, Rotation rotation, float integrity, OceanRuinStructure.Type biomeType, boolean isLarge) { + super(StructurePieceType.OCEAN_RUIN, 0, structureTemplateManager, location, location.toString(), makeSettings(rotation, integrity, biomeType), pos); + this.integrity = integrity; + this.biomeType = biomeType; + this.isLarge = isLarge; + } + +- private OceanRuinPiece( +- StructureTemplateManager structureTemplateManager, +- CompoundTag genDepth, +- Rotation rotation, +- float integrity, +- OceanRuinStructure.Type biomeType, +- boolean isLarge +- ) { +- super(StructurePieceType.OCEAN_RUIN, genDepth, structureTemplateManager, resourceLocation -> makeSettings(rotation, integrity, biomeType)); ++ private OceanRuinPiece(StructureTemplateManager structureTemplateManager, CompoundTag genDepth, Rotation rotation, float integrity, OceanRuinStructure.Type biomeType, boolean isLarge) { ++ super(StructurePieceType.OCEAN_RUIN, genDepth, structureTemplateManager, (minecraftkey) -> { ++ return makeSettings(rotation, integrity, biomeType); ++ }); + this.integrity = integrity; + this.biomeType = biomeType; + this.isLarge = isLarge; + } + + private static StructurePlaceSettings makeSettings(Rotation rotation, float integrity, OceanRuinStructure.Type structureType) { +- StructureProcessor structureProcessor = structureType == OceanRuinStructure.Type.COLD +- ? OceanRuinPieces.COLD_SUSPICIOUS_BLOCK_PROCESSOR +- : OceanRuinPieces.WARM_SUSPICIOUS_BLOCK_PROCESSOR; +- return new StructurePlaceSettings() +- .setRotation(rotation) +- .setMirror(Mirror.NONE) +- .addProcessor(new BlockRotProcessor(integrity)) +- .addProcessor(BlockIgnoreProcessor.STRUCTURE_AND_AIR) +- .addProcessor(structureProcessor); ++ StructureProcessor definedstructureprocessor = structureType == OceanRuinStructure.Type.COLD ? OceanRuinPieces.COLD_SUSPICIOUS_BLOCK_PROCESSOR : OceanRuinPieces.WARM_SUSPICIOUS_BLOCK_PROCESSOR; ++ ++ return (new StructurePlaceSettings()).setRotation(rotation).setMirror(Mirror.NONE).addProcessor(new BlockRotProcessor(integrity)).addProcessor(BlockIgnoreProcessor.STRUCTURE_AND_AIR).addProcessor(definedstructureprocessor); + } + + public static OceanRuinPieces.OceanRuinPiece create(StructureTemplateManager structureTemplateManager, CompoundTag tag) { +- Rotation rotation = Rotation.valueOf(tag.getString("Rot")); +- float _float = tag.getFloat("Integrity"); +- OceanRuinStructure.Type type = OceanRuinStructure.Type.valueOf(tag.getString("BiomeType")); +- boolean _boolean = tag.getBoolean("IsLarge"); +- return new OceanRuinPieces.OceanRuinPiece(structureTemplateManager, tag, rotation, _float, type, _boolean); ++ Rotation enumblockrotation = Rotation.valueOf(tag.getString("Rot")); ++ float f = tag.getFloat("Integrity"); ++ OceanRuinStructure.Type oceanruinstructure_a = OceanRuinStructure.Type.valueOf(tag.getString("BiomeType")); ++ boolean flag = tag.getBoolean("IsLarge"); ++ ++ return new OceanRuinPieces.OceanRuinPiece(structureTemplateManager, tag, enumblockrotation, f, oceanruinstructure_a, flag); + } + + @Override +@@ -308,21 +196,28 @@ + @Override + protected void handleDataMarker(String name, BlockPos pos, ServerLevelAccessor level, RandomSource random, BoundingBox box) { + if ("chest".equals(name)) { +- level.setBlock( +- pos, Blocks.CHEST.defaultBlockState().setValue(ChestBlock.WATERLOGGED, Boolean.valueOf(level.getFluidState(pos).is(FluidTags.WATER))), 2 +- ); +- BlockEntity blockEntity = level.getBlockEntity(pos); +- if (blockEntity instanceof ChestBlockEntity) { +- ((ChestBlockEntity)blockEntity) +- .setLootTable(this.isLarge ? BuiltInLootTables.UNDERWATER_RUIN_BIG : BuiltInLootTables.UNDERWATER_RUIN_SMALL, random.nextLong()); ++ // CraftBukkit start - transform block to ensure loot table is accessible ++ /* ++ worldaccess.setBlock(blockposition, (IBlockData) Blocks.CHEST.defaultBlockState().setValue(BlockChest.WATERLOGGED, worldaccess.getFluidState(blockposition).is(TagsFluid.WATER)), 2); ++ TileEntity tileentity = worldaccess.getBlockEntity(blockposition); ++ ++ if (tileentity instanceof TileEntityChest) { ++ ((TileEntityChest) tileentity).setLootTable(this.isLarge ? LootTables.UNDERWATER_RUIN_BIG : LootTables.UNDERWATER_RUIN_SMALL, randomsource.nextLong()); + } ++ */ ++ org.bukkit.craftbukkit.block.CraftChest craftChest = (org.bukkit.craftbukkit.block.CraftChest) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(pos, Blocks.CHEST.defaultBlockState().setValue(ChestBlock.WATERLOGGED, level.getFluidState(pos).is(FluidTags.WATER)), null); ++ craftChest.setSeed(random.nextLong()); ++ craftChest.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.isLarge ? BuiltInLootTables.UNDERWATER_RUIN_BIG : BuiltInLootTables.UNDERWATER_RUIN_SMALL))); ++ placeCraftBlockEntity(level, pos, craftChest, 2); ++ // CraftBukkit end + } else if ("drowned".equals(name)) { +- Drowned drowned = EntityType.DROWNED.create(level.getLevel()); +- if (drowned != null) { +- drowned.setPersistenceRequired(); +- drowned.moveTo(pos, 0.0F, 0.0F); +- drowned.finalizeSpawn(level, level.getCurrentDifficultyAt(pos), MobSpawnType.STRUCTURE, null, null); +- level.addFreshEntityWithPassengers(drowned); ++ Drowned entitydrowned = (Drowned) EntityType.DROWNED.create(level.getLevel()); ++ ++ if (entitydrowned != null) { ++ entitydrowned.setPersistenceRequired(); ++ entitydrowned.moveTo(pos, 0.0F, 0.0F); ++ entitydrowned.finalizeSpawn(level, level.getCurrentDifficultyAt(pos), EnumMobSpawn.STRUCTURE, (GroupDataEntity) null, (CompoundTag) null); ++ level.addFreshEntityWithPassengers(entitydrowned); + if (pos.getY() > level.getSeaLevel()) { + level.setBlock(pos, Blocks.AIR.defaultBlockState(), 2); + } else { +@@ -330,66 +225,54 @@ + } + } + } ++ + } + + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { +- int height = level.getHeight(Heightmap.Types.OCEAN_FLOOR_WG, this.templatePosition.getX(), this.templatePosition.getZ()); +- this.templatePosition = new BlockPos(this.templatePosition.getX(), height, this.templatePosition.getZ()); +- BlockPos blockPos = StructureTemplate.transform( +- new BlockPos(this.template.getSize().getX() - 1, 0, this.template.getSize().getZ() - 1), +- Mirror.NONE, +- this.placeSettings.getRotation(), +- BlockPos.ZERO +- ) +- .offset(this.templatePosition); +- this.templatePosition = new BlockPos( +- this.templatePosition.getX(), this.getHeight(this.templatePosition, level, blockPos), this.templatePosition.getZ() +- ); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ int i = level.getHeight(Heightmap.Types.OCEAN_FLOOR_WG, this.templatePosition.getX(), this.templatePosition.getZ()); ++ ++ this.templatePosition = new BlockPos(this.templatePosition.getX(), i, this.templatePosition.getZ()); ++ BlockPos blockposition1 = StructureTemplate.transform(new BlockPos(this.template.getSize().getX() - 1, 0, this.template.getSize().getZ() - 1), Mirror.NONE, this.placeSettings.getRotation(), BlockPos.ZERO).offset(this.templatePosition); ++ ++ this.templatePosition = new BlockPos(this.templatePosition.getX(), this.getHeight(this.templatePosition, level, blockposition1), this.templatePosition.getZ()); + super.postProcess(level, structureManager, generator, random, box, chunkPos, pos); + } + + private int getHeight(BlockPos templatePos, BlockGetter level, BlockPos pos) { +- int y = templatePos.getY(); +- int i = 512; +- int i1 = y - 1; +- int i2 = 0; ++ int i = templatePos.getY(); ++ int j = 512; ++ int k = i - 1; ++ int l = 0; ++ Iterator iterator = BlockPos.betweenClosed(templatePos, pos).iterator(); + +- for (BlockPos blockPos : BlockPos.betweenClosed(templatePos, pos)) { +- int x = blockPos.getX(); +- int z = blockPos.getZ(); +- int i3 = templatePos.getY() - 1; +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(x, i3, z); +- BlockState blockState = level.getBlockState(mutableBlockPos); ++ while (iterator.hasNext()) { ++ BlockPos blockposition2 = (BlockPos) iterator.next(); ++ int i1 = blockposition2.getX(); ++ int j1 = blockposition2.getZ(); ++ int k1 = templatePos.getY() - 1; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(i1, k1, j1); ++ IBlockData iblockdata = level.getBlockState(blockposition_mutableblockposition); + +- for (FluidState fluidState = level.getFluidState(mutableBlockPos); +- (blockState.isAir() || fluidState.is(FluidTags.WATER) || blockState.is(BlockTags.ICE)) && i3 > level.getMinBuildHeight() + 1; +- fluidState = level.getFluidState(mutableBlockPos) +- ) { +- mutableBlockPos.set(x, --i3, z); +- blockState = level.getBlockState(mutableBlockPos); ++ for (FluidState fluid = level.getFluidState(blockposition_mutableblockposition); (iblockdata.isAir() || fluid.is(FluidTags.WATER) || iblockdata.is(BlockTags.ICE)) && k1 > level.getMinBuildHeight() + 1; fluid = level.getFluidState(blockposition_mutableblockposition)) { ++ --k1; ++ blockposition_mutableblockposition.set(i1, k1, j1); ++ iblockdata = level.getBlockState(blockposition_mutableblockposition); + } + +- i = Math.min(i, i3); +- if (i3 < i1 - 2) { +- i2++; ++ j = Math.min(j, k1); ++ if (k1 < k - 2) { ++ ++l; + } + } + +- int abs = Math.abs(templatePos.getX() - pos.getX()); +- if (i1 - i > 2 && i2 > abs - 2) { +- y = i + 1; ++ int l1 = Math.abs(templatePos.getX() - pos.getX()); ++ ++ if (k - j > 2 && l > l1 - 2) { ++ i = j + 1; + } + +- return y; ++ return i; + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java.patch new file mode 100644 index 0000000000..9adf0a33d5 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java.patch @@ -0,0 +1,2564 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java +@@ -1,13 +1,13 @@ + package net.minecraft.world.level.levelgen.structure.structures; + + import com.google.common.collect.Lists; ++import java.util.Iterator; + import java.util.List; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.util.RandomSource; +-import net.minecraft.world.entity.EntityType; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.StructureManager; + import net.minecraft.world.level.WorldGenLevel; +@@ -21,9 +21,8 @@ + import net.minecraft.world.level.block.SlabBlock; + import net.minecraft.world.level.block.StairBlock; + import net.minecraft.world.level.block.WallTorchBlock; +-import net.minecraft.world.level.block.entity.SpawnerBlockEntity; +-import net.minecraft.world.level.block.state.BlockState; +-import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.block.state.properties.BlockPropertyDoubleBlockHalf; + import net.minecraft.world.level.block.state.properties.SlabType; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.levelgen.structure.BoundingBox; +@@ -34,997 +33,362 @@ + import net.minecraft.world.level.storage.loot.BuiltInLootTables; + + public class StrongholdPieces { ++ + private static final int SMALL_DOOR_WIDTH = 3; + private static final int SMALL_DOOR_HEIGHT = 3; + private static final int MAX_DEPTH = 50; + private static final int LOWEST_Y_POSITION = 10; + private static final boolean CHECK_AIR = true; + public static final int MAGIC_START_Y = 64; +- private static final StrongholdPieces.PieceWeight[] STRONGHOLD_PIECE_WEIGHTS = new StrongholdPieces.PieceWeight[]{ +- new StrongholdPieces.PieceWeight(StrongholdPieces.Straight.class, 40, 0), +- new StrongholdPieces.PieceWeight(StrongholdPieces.PrisonHall.class, 5, 5), +- new StrongholdPieces.PieceWeight(StrongholdPieces.LeftTurn.class, 20, 0), +- new StrongholdPieces.PieceWeight(StrongholdPieces.RightTurn.class, 20, 0), +- new StrongholdPieces.PieceWeight(StrongholdPieces.RoomCrossing.class, 10, 6), +- new StrongholdPieces.PieceWeight(StrongholdPieces.StraightStairsDown.class, 5, 5), +- new StrongholdPieces.PieceWeight(StrongholdPieces.StairsDown.class, 5, 5), +- new StrongholdPieces.PieceWeight(StrongholdPieces.FiveCrossing.class, 5, 4), +- new StrongholdPieces.PieceWeight(StrongholdPieces.ChestCorridor.class, 5, 4), +- new StrongholdPieces.PieceWeight(StrongholdPieces.Library.class, 10, 2) { +- @Override +- public boolean doPlace(int genDepth) { +- return super.doPlace(genDepth) && genDepth > 4; +- } +- }, +- new StrongholdPieces.PieceWeight(StrongholdPieces.PortalRoom.class, 20, 1) { +- @Override +- public boolean doPlace(int genDepth) { +- return super.doPlace(genDepth) && genDepth > 5; +- } +- } +- }; ++ private static final StrongholdPieces.PieceWeight[] STRONGHOLD_PIECE_WEIGHTS = new StrongholdPieces.PieceWeight[]{new StrongholdPieces.PieceWeight(StrongholdPieces.Straight.class, 40, 0), new StrongholdPieces.PieceWeight(StrongholdPieces.PrisonHall.class, 5, 5), new StrongholdPieces.PieceWeight(StrongholdPieces.LeftTurn.class, 20, 0), new StrongholdPieces.PieceWeight(StrongholdPieces.RightTurn.class, 20, 0), new StrongholdPieces.PieceWeight(StrongholdPieces.RoomCrossing.class, 10, 6), new StrongholdPieces.PieceWeight(StrongholdPieces.StraightStairsDown.class, 5, 5), new StrongholdPieces.PieceWeight(StrongholdPieces.StairsDown.class, 5, 5), new StrongholdPieces.PieceWeight(StrongholdPieces.FiveCrossing.class, 5, 4), new StrongholdPieces.PieceWeight(StrongholdPieces.ChestCorridor.class, 5, 4), new StrongholdPieces.PieceWeight(StrongholdPieces.Library.class, 10, 2) { ++ @Override ++ public boolean doPlace(int genDepth) { ++ return super.doPlace(genDepth) && genDepth > 4; ++ } ++ }, new StrongholdPieces.PieceWeight(StrongholdPieces.PortalRoom.class, 20, 1) { ++ @Override ++ public boolean doPlace(int genDepth) { ++ return super.doPlace(genDepth) && genDepth > 5; ++ } ++ } }; // CraftBukkit - fix decompile styling + private static List currentPieces; + static Class imposedPiece; + private static int totalWeight; +- static final StrongholdPieces.SmoothStoneSelector SMOOTH_STONE_SELECTOR = new StrongholdPieces.SmoothStoneSelector(); ++ static final StrongholdPieces.k SMOOTH_STONE_SELECTOR = new StrongholdPieces.k(); + ++ public StrongholdPieces() {} ++ + public static void resetPieces() { +- currentPieces = Lists.newArrayList(); ++ StrongholdPieces.currentPieces = Lists.newArrayList(); ++ StrongholdPieces.PieceWeight[] astrongholdpieces_f = StrongholdPieces.STRONGHOLD_PIECE_WEIGHTS; ++ int i = astrongholdpieces_f.length; + +- for (StrongholdPieces.PieceWeight pieceWeight : STRONGHOLD_PIECE_WEIGHTS) { +- pieceWeight.placeCount = 0; +- currentPieces.add(pieceWeight); ++ for (int j = 0; j < i; ++j) { ++ StrongholdPieces.PieceWeight strongholdpieces_f = astrongholdpieces_f[j]; ++ ++ strongholdpieces_f.placeCount = 0; ++ StrongholdPieces.currentPieces.add(strongholdpieces_f); + } + +- imposedPiece = null; ++ StrongholdPieces.imposedPiece = null; + } + + private static boolean updatePieceWeight() { + boolean flag = false; +- totalWeight = 0; + +- for (StrongholdPieces.PieceWeight pieceWeight : currentPieces) { +- if (pieceWeight.maxPlaceCount > 0 && pieceWeight.placeCount < pieceWeight.maxPlaceCount) { ++ StrongholdPieces.totalWeight = 0; ++ ++ StrongholdPieces.PieceWeight strongholdpieces_f; ++ ++ for (Iterator iterator = StrongholdPieces.currentPieces.iterator(); iterator.hasNext(); StrongholdPieces.totalWeight += strongholdpieces_f.weight) { ++ strongholdpieces_f = (StrongholdPieces.PieceWeight) iterator.next(); ++ if (strongholdpieces_f.maxPlaceCount > 0 && strongholdpieces_f.placeCount < strongholdpieces_f.maxPlaceCount) { + flag = true; + } +- +- totalWeight = totalWeight + pieceWeight.weight; + } + + return flag; + } + +- private static StrongholdPieces.StrongholdPiece findAndCreatePieceFactory( +- Class pieceClass, +- StructurePieceAccessor pieces, +- RandomSource random, +- int x, +- int y, +- int z, +- @Nullable Direction direction, +- int genDepth +- ) { +- StrongholdPieces.StrongholdPiece strongholdPiece = null; ++ private static StrongholdPieces.StrongholdPiece findAndCreatePieceFactory(Class pieceClass, StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, @Nullable Direction direction, int genDepth) { ++ Object object = null; ++ + if (pieceClass == StrongholdPieces.Straight.class) { +- strongholdPiece = StrongholdPieces.Straight.createPiece(pieces, random, x, y, z, direction, genDepth); ++ object = StrongholdPieces.Straight.createPiece(pieces, random, x, y, z, direction, genDepth); + } else if (pieceClass == StrongholdPieces.PrisonHall.class) { +- strongholdPiece = StrongholdPieces.PrisonHall.createPiece(pieces, random, x, y, z, direction, genDepth); ++ object = StrongholdPieces.PrisonHall.createPiece(pieces, random, x, y, z, direction, genDepth); + } else if (pieceClass == StrongholdPieces.LeftTurn.class) { +- strongholdPiece = StrongholdPieces.LeftTurn.createPiece(pieces, random, x, y, z, direction, genDepth); ++ object = StrongholdPieces.LeftTurn.createPiece(pieces, random, x, y, z, direction, genDepth); + } else if (pieceClass == StrongholdPieces.RightTurn.class) { +- strongholdPiece = StrongholdPieces.RightTurn.createPiece(pieces, random, x, y, z, direction, genDepth); ++ object = StrongholdPieces.RightTurn.createPiece(pieces, random, x, y, z, direction, genDepth); + } else if (pieceClass == StrongholdPieces.RoomCrossing.class) { +- strongholdPiece = StrongholdPieces.RoomCrossing.createPiece(pieces, random, x, y, z, direction, genDepth); ++ object = StrongholdPieces.RoomCrossing.createPiece(pieces, random, x, y, z, direction, genDepth); + } else if (pieceClass == StrongholdPieces.StraightStairsDown.class) { +- strongholdPiece = StrongholdPieces.StraightStairsDown.createPiece(pieces, random, x, y, z, direction, genDepth); ++ object = StrongholdPieces.StraightStairsDown.createPiece(pieces, random, x, y, z, direction, genDepth); + } else if (pieceClass == StrongholdPieces.StairsDown.class) { +- strongholdPiece = StrongholdPieces.StairsDown.createPiece(pieces, random, x, y, z, direction, genDepth); ++ object = StrongholdPieces.StairsDown.createPiece(pieces, random, x, y, z, direction, genDepth); + } else if (pieceClass == StrongholdPieces.FiveCrossing.class) { +- strongholdPiece = StrongholdPieces.FiveCrossing.createPiece(pieces, random, x, y, z, direction, genDepth); ++ object = StrongholdPieces.FiveCrossing.createPiece(pieces, random, x, y, z, direction, genDepth); + } else if (pieceClass == StrongholdPieces.ChestCorridor.class) { +- strongholdPiece = StrongholdPieces.ChestCorridor.createPiece(pieces, random, x, y, z, direction, genDepth); ++ object = StrongholdPieces.ChestCorridor.createPiece(pieces, random, x, y, z, direction, genDepth); + } else if (pieceClass == StrongholdPieces.Library.class) { +- strongholdPiece = StrongholdPieces.Library.createPiece(pieces, random, x, y, z, direction, genDepth); ++ object = StrongholdPieces.Library.createPiece(pieces, random, x, y, z, direction, genDepth); + } else if (pieceClass == StrongholdPieces.PortalRoom.class) { +- strongholdPiece = StrongholdPieces.PortalRoom.createPiece(pieces, x, y, z, direction, genDepth); ++ object = StrongholdPieces.PortalRoom.createPiece(pieces, x, y, z, direction, genDepth); + } + +- return strongholdPiece; ++ return (StrongholdPieces.StrongholdPiece) object; + } + +- private static StrongholdPieces.StrongholdPiece generatePieceFromSmallDoor( +- StrongholdPieces.StartPiece piece, StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction direction, int genDepth +- ) { ++ private static StrongholdPieces.StrongholdPiece generatePieceFromSmallDoor(StrongholdPieces.StartPiece piece, StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction direction, int genDepth) { + if (!updatePieceWeight()) { + return null; + } else { +- if (imposedPiece != null) { +- StrongholdPieces.StrongholdPiece strongholdPiece = findAndCreatePieceFactory(imposedPiece, pieces, random, x, y, z, direction, genDepth); +- imposedPiece = null; +- if (strongholdPiece != null) { +- return strongholdPiece; ++ if (StrongholdPieces.imposedPiece != null) { ++ StrongholdPieces.StrongholdPiece strongholdpieces_p = findAndCreatePieceFactory(StrongholdPieces.imposedPiece, pieces, random, x, y, z, direction, genDepth); ++ ++ StrongholdPieces.imposedPiece = null; ++ if (strongholdpieces_p != null) { ++ return strongholdpieces_p; + } + } + +- int i = 0; ++ int i1 = 0; + +- while (i < 5) { +- i++; +- int randomInt = random.nextInt(totalWeight); ++ while (i1 < 5) { ++ ++i1; ++ int j1 = random.nextInt(StrongholdPieces.totalWeight); ++ Iterator iterator = StrongholdPieces.currentPieces.iterator(); + +- for (StrongholdPieces.PieceWeight pieceWeight : currentPieces) { +- randomInt -= pieceWeight.weight; +- if (randomInt < 0) { +- if (!pieceWeight.doPlace(genDepth) || pieceWeight == piece.previousPiece) { ++ while (iterator.hasNext()) { ++ StrongholdPieces.PieceWeight strongholdpieces_f = (StrongholdPieces.PieceWeight) iterator.next(); ++ ++ j1 -= strongholdpieces_f.weight; ++ if (j1 < 0) { ++ if (!strongholdpieces_f.doPlace(genDepth) || strongholdpieces_f == piece.previousPiece) { + break; + } + +- StrongholdPieces.StrongholdPiece strongholdPiece1 = findAndCreatePieceFactory( +- pieceWeight.pieceClass, pieces, random, x, y, z, direction, genDepth +- ); +- if (strongholdPiece1 != null) { +- pieceWeight.placeCount++; +- piece.previousPiece = pieceWeight; +- if (!pieceWeight.isValid()) { +- currentPieces.remove(pieceWeight); ++ StrongholdPieces.StrongholdPiece strongholdpieces_p1 = findAndCreatePieceFactory(strongholdpieces_f.pieceClass, pieces, random, x, y, z, direction, genDepth); ++ ++ if (strongholdpieces_p1 != null) { ++ ++strongholdpieces_f.placeCount; ++ piece.previousPiece = strongholdpieces_f; ++ if (!strongholdpieces_f.isValid()) { ++ StrongholdPieces.currentPieces.remove(strongholdpieces_f); + } + +- return strongholdPiece1; ++ return strongholdpieces_p1; + } + } + } + } + +- BoundingBox boundingBox = StrongholdPieces.FillerCorridor.findPieceBox(pieces, random, x, y, z, direction); +- return boundingBox != null && boundingBox.minY() > 1 ? new StrongholdPieces.FillerCorridor(genDepth, boundingBox, direction) : null; ++ BoundingBox structureboundingbox = StrongholdPieces.FillerCorridor.findPieceBox(pieces, random, x, y, z, direction); ++ ++ if (structureboundingbox != null && structureboundingbox.minY() > 1) { ++ return new StrongholdPieces.FillerCorridor(genDepth, structureboundingbox, direction); ++ } else { ++ return null; ++ } + } + } + +- static StructurePiece generateAndAddPiece( +- StrongholdPieces.StartPiece piece, StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, @Nullable Direction direction, int genDepth +- ) { ++ static StructurePiece generateAndAddPiece(StrongholdPieces.StartPiece piece, StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, @Nullable Direction direction, int genDepth) { + if (genDepth > 50) { + return null; + } else if (Math.abs(x - piece.getBoundingBox().minX()) <= 112 && Math.abs(z - piece.getBoundingBox().minZ()) <= 112) { +- StructurePiece structurePiece = generatePieceFromSmallDoor(piece, pieces, random, x, y, z, direction, genDepth + 1); +- if (structurePiece != null) { +- pieces.addPiece(structurePiece); +- piece.pendingChildren.add(structurePiece); ++ StrongholdPieces.StrongholdPiece strongholdpieces_p = generatePieceFromSmallDoor(piece, pieces, random, x, y, z, direction, genDepth + 1); ++ ++ if (strongholdpieces_p != null) { ++ pieces.addPiece(strongholdpieces_p); ++ piece.pendingChildren.add(strongholdpieces_p); + } + +- return structurePiece; ++ return strongholdpieces_p; + } else { + return null; + } + } + +- public static class ChestCorridor extends StrongholdPieces.StrongholdPiece { +- private static final int WIDTH = 5; +- private static final int HEIGHT = 5; +- private static final int DEPTH = 7; +- private boolean hasPlacedChest; ++ private static class PieceWeight { + +- public ChestCorridor(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { +- super(StructurePieceType.STRONGHOLD_CHEST_CORRIDOR, genDepth, box); +- this.setOrientation(orientation); +- this.entryDoor = this.randomSmallDoor(random); +- } ++ public final Class pieceClass; ++ public final int weight; ++ public int placeCount; ++ public final int maxPlaceCount; + +- public ChestCorridor(CompoundTag tag) { +- super(StructurePieceType.STRONGHOLD_CHEST_CORRIDOR, tag); +- this.hasPlacedChest = tag.getBoolean("Chest"); ++ public PieceWeight(Class pieceClass, int weight, int maxPlaceCount) { ++ this.pieceClass = pieceClass; ++ this.weight = weight; ++ this.maxPlaceCount = maxPlaceCount; + } + +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { +- super.addAdditionalSaveData(context, tag); +- tag.putBoolean("Chest", this.hasPlacedChest); ++ public boolean doPlace(int genDepth) { ++ return this.maxPlaceCount == 0 || this.placeCount < this.maxPlaceCount; + } + +- @Override +- public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- this.generateSmallDoorChildForward((StrongholdPieces.StartPiece)piece, pieces, random, 1, 1); ++ public boolean isValid() { ++ return this.maxPlaceCount == 0 || this.placeCount < this.maxPlaceCount; + } +- +- public static StrongholdPieces.ChestCorridor createPiece( +- StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth +- ) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, 7, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new StrongholdPieces.ChestCorridor(genDepth, random, boundingBox, orientation) +- : null; +- } +- +- @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { +- this.generateBox(level, box, 0, 0, 0, 4, 4, 6, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateSmallDoor(level, random, box, this.entryDoor, 1, 1, 0); +- this.generateSmallDoor(level, random, box, StrongholdPieces.StrongholdPiece.SmallDoorType.OPENING, 1, 1, 6); +- this.generateBox(level, box, 3, 1, 2, 3, 1, 4, Blocks.STONE_BRICKS.defaultBlockState(), Blocks.STONE_BRICKS.defaultBlockState(), false); +- this.placeBlock(level, Blocks.STONE_BRICK_SLAB.defaultBlockState(), 3, 1, 1, box); +- this.placeBlock(level, Blocks.STONE_BRICK_SLAB.defaultBlockState(), 3, 1, 5, box); +- this.placeBlock(level, Blocks.STONE_BRICK_SLAB.defaultBlockState(), 3, 2, 2, box); +- this.placeBlock(level, Blocks.STONE_BRICK_SLAB.defaultBlockState(), 3, 2, 4, box); +- +- for (int i = 2; i <= 4; i++) { +- this.placeBlock(level, Blocks.STONE_BRICK_SLAB.defaultBlockState(), 2, 1, i, box); +- } +- +- if (!this.hasPlacedChest && box.isInside(this.getWorldPos(3, 2, 3))) { +- this.hasPlacedChest = true; +- this.createChest(level, box, random, 3, 2, 3, BuiltInLootTables.STRONGHOLD_CORRIDOR); +- } +- } + } + +- public static class FillerCorridor extends StrongholdPieces.StrongholdPiece { +- private final int steps; ++ public static class Straight extends StrongholdPieces.StrongholdPiece { + +- public FillerCorridor(int genDepth, BoundingBox box, Direction orientation) { +- super(StructurePieceType.STRONGHOLD_FILLER_CORRIDOR, genDepth, box); +- this.setOrientation(orientation); +- this.steps = orientation != Direction.NORTH && orientation != Direction.SOUTH ? box.getXSpan() : box.getZSpan(); +- } ++ private static final int WIDTH = 5; ++ private static final int HEIGHT = 5; ++ private static final int DEPTH = 7; ++ private final boolean leftChild; ++ private final boolean rightChild; + +- public FillerCorridor(CompoundTag tag) { +- super(StructurePieceType.STRONGHOLD_FILLER_CORRIDOR, tag); +- this.steps = tag.getInt("Steps"); +- } +- +- @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { +- super.addAdditionalSaveData(context, tag); +- tag.putInt("Steps", this.steps); +- } +- +- public static BoundingBox findPieceBox(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation) { +- int i = 3; +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, 4, orientation); +- StructurePiece structurePiece = pieces.findCollisionPiece(boundingBox); +- if (structurePiece == null) { +- return null; +- } else { +- if (structurePiece.getBoundingBox().minY() == boundingBox.minY()) { +- for (int i1 = 2; i1 >= 1; i1--) { +- boundingBox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, i1, orientation); +- if (!structurePiece.getBoundingBox().intersects(boundingBox)) { +- return BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, i1 + 1, orientation); +- } +- } +- } +- +- return null; +- } +- } +- +- @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { +- for (int i = 0; i < this.steps; i++) { +- this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 0, 0, i, box); +- this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 1, 0, i, box); +- this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 2, 0, i, box); +- this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 3, 0, i, box); +- this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 4, 0, i, box); +- +- for (int i1 = 1; i1 <= 3; i1++) { +- this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 0, i1, i, box); +- this.placeBlock(level, Blocks.CAVE_AIR.defaultBlockState(), 1, i1, i, box); +- this.placeBlock(level, Blocks.CAVE_AIR.defaultBlockState(), 2, i1, i, box); +- this.placeBlock(level, Blocks.CAVE_AIR.defaultBlockState(), 3, i1, i, box); +- this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 4, i1, i, box); +- } +- +- this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 0, 4, i, box); +- this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 1, 4, i, box); +- this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 2, 4, i, box); +- this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 3, 4, i, box); +- this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 4, 4, i, box); +- } +- } +- } +- +- public static class FiveCrossing extends StrongholdPieces.StrongholdPiece { +- protected static final int WIDTH = 10; +- protected static final int HEIGHT = 9; +- protected static final int DEPTH = 11; +- private final boolean leftLow; +- private final boolean leftHigh; +- private final boolean rightLow; +- private final boolean rightHigh; +- +- public FiveCrossing(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { +- super(StructurePieceType.STRONGHOLD_FIVE_CROSSING, genDepth, box); ++ public Straight(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_STRAIGHT, genDepth, box); + this.setOrientation(orientation); + this.entryDoor = this.randomSmallDoor(random); +- this.leftLow = random.nextBoolean(); +- this.leftHigh = random.nextBoolean(); +- this.rightLow = random.nextBoolean(); +- this.rightHigh = random.nextInt(3) > 0; ++ this.leftChild = random.nextInt(2) == 0; ++ this.rightChild = random.nextInt(2) == 0; + } + +- public FiveCrossing(CompoundTag tag) { +- super(StructurePieceType.STRONGHOLD_FIVE_CROSSING, tag); +- this.leftLow = tag.getBoolean("leftLow"); +- this.leftHigh = tag.getBoolean("leftHigh"); +- this.rightLow = tag.getBoolean("rightLow"); +- this.rightHigh = tag.getBoolean("rightHigh"); ++ public Straight(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_STRAIGHT, tag); ++ this.leftChild = tag.getBoolean("Left"); ++ this.rightChild = tag.getBoolean("Right"); + } + + @Override + protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { + super.addAdditionalSaveData(context, tag); +- tag.putBoolean("leftLow", this.leftLow); +- tag.putBoolean("leftHigh", this.leftHigh); +- tag.putBoolean("rightLow", this.rightLow); +- tag.putBoolean("rightHigh", this.rightHigh); ++ tag.putBoolean("Left", this.leftChild); ++ tag.putBoolean("Right", this.rightChild); + } + + @Override + public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- int i = 3; +- int i1 = 5; +- Direction orientation = this.getOrientation(); +- if (orientation == Direction.WEST || orientation == Direction.NORTH) { +- i = 8 - i; +- i1 = 8 - i1; ++ this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) piece, pieces, random, 1, 1); ++ if (this.leftChild) { ++ this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece) piece, pieces, random, 1, 2); + } + +- this.generateSmallDoorChildForward((StrongholdPieces.StartPiece)piece, pieces, random, 5, 1); +- if (this.leftLow) { +- this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece)piece, pieces, random, i, 1); ++ if (this.rightChild) { ++ this.generateSmallDoorChildRight((StrongholdPieces.StartPiece) piece, pieces, random, 1, 2); + } + +- if (this.leftHigh) { +- this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece)piece, pieces, random, i1, 7); +- } ++ } + +- if (this.rightLow) { +- this.generateSmallDoorChildRight((StrongholdPieces.StartPiece)piece, pieces, random, i, 1); +- } ++ public static StrongholdPieces.Straight createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction direction, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, 7, direction); + +- if (this.rightHigh) { +- this.generateSmallDoorChildRight((StrongholdPieces.StartPiece)piece, pieces, random, i1, 7); +- } ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new StrongholdPieces.Straight(genDepth, random, structureboundingbox, direction) : null; + } + +- public static StrongholdPieces.FiveCrossing createPiece( +- StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth +- ) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -4, -3, 0, 10, 9, 11, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new StrongholdPieces.FiveCrossing(genDepth, random, boundingBox, orientation) +- : null; +- } +- + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { +- this.generateBox(level, box, 0, 0, 0, 9, 8, 10, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateSmallDoor(level, random, box, this.entryDoor, 4, 3, 0); +- if (this.leftLow) { +- this.generateBox(level, box, 0, 3, 1, 0, 5, 3, CAVE_AIR, CAVE_AIR, false); +- } ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 4, 4, 6, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateSmallDoor(level, random, box, this.entryDoor, 1, 1, 0); ++ this.generateSmallDoor(level, random, box, StrongholdPieces.StrongholdPiece.a.OPENING, 1, 1, 6); ++ IBlockData iblockdata = (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.EAST); ++ IBlockData iblockdata1 = (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.WEST); + +- if (this.rightLow) { +- this.generateBox(level, box, 9, 3, 1, 9, 5, 3, CAVE_AIR, CAVE_AIR, false); ++ this.maybeGenerateBlock(level, box, random, 0.1F, 1, 2, 1, iblockdata); ++ this.maybeGenerateBlock(level, box, random, 0.1F, 3, 2, 1, iblockdata1); ++ this.maybeGenerateBlock(level, box, random, 0.1F, 1, 2, 5, iblockdata); ++ this.maybeGenerateBlock(level, box, random, 0.1F, 3, 2, 5, iblockdata1); ++ if (this.leftChild) { ++ this.generateBox(level, box, 0, 1, 2, 0, 3, 4, StrongholdPieces.Straight.CAVE_AIR, StrongholdPieces.Straight.CAVE_AIR, false); + } + +- if (this.leftHigh) { +- this.generateBox(level, box, 0, 5, 7, 0, 7, 9, CAVE_AIR, CAVE_AIR, false); ++ if (this.rightChild) { ++ this.generateBox(level, box, 4, 1, 2, 4, 3, 4, StrongholdPieces.Straight.CAVE_AIR, StrongholdPieces.Straight.CAVE_AIR, false); + } + +- if (this.rightHigh) { +- this.generateBox(level, box, 9, 5, 7, 9, 7, 9, CAVE_AIR, CAVE_AIR, false); +- } +- +- this.generateBox(level, box, 5, 1, 10, 7, 3, 10, CAVE_AIR, CAVE_AIR, false); +- this.generateBox(level, box, 1, 2, 1, 8, 2, 6, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(level, box, 4, 1, 5, 4, 4, 9, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(level, box, 8, 1, 5, 8, 4, 9, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(level, box, 1, 4, 7, 3, 4, 9, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(level, box, 1, 3, 5, 3, 3, 6, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(level, box, 1, 3, 4, 3, 3, 4, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); +- this.generateBox(level, box, 1, 4, 6, 3, 4, 6, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); +- this.generateBox(level, box, 5, 1, 7, 7, 1, 8, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(level, box, 5, 1, 9, 7, 1, 9, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); +- this.generateBox(level, box, 5, 2, 7, 7, 2, 7, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); +- this.generateBox(level, box, 4, 5, 7, 4, 5, 9, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); +- this.generateBox(level, box, 8, 5, 7, 8, 5, 9, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); +- this.generateBox( +- level, +- box, +- 5, +- 5, +- 7, +- 7, +- 5, +- 9, +- Blocks.SMOOTH_STONE_SLAB.defaultBlockState().setValue(SlabBlock.TYPE, SlabType.DOUBLE), +- Blocks.SMOOTH_STONE_SLAB.defaultBlockState().setValue(SlabBlock.TYPE, SlabType.DOUBLE), +- false +- ); +- this.placeBlock(level, Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.SOUTH), 6, 5, 6, box); + } + } + +- public static class LeftTurn extends StrongholdPieces.Turn { +- public LeftTurn(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { +- super(StructurePieceType.STRONGHOLD_LEFT_TURN, genDepth, box); +- this.setOrientation(orientation); +- this.entryDoor = this.randomSmallDoor(random); +- } ++ public static class PrisonHall extends StrongholdPieces.StrongholdPiece { + +- public LeftTurn(CompoundTag tag) { +- super(StructurePieceType.STRONGHOLD_LEFT_TURN, tag); +- } ++ protected static final int WIDTH = 9; ++ protected static final int HEIGHT = 5; ++ protected static final int DEPTH = 11; + +- @Override +- public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- Direction orientation = this.getOrientation(); +- if (orientation != Direction.NORTH && orientation != Direction.EAST) { +- this.generateSmallDoorChildRight((StrongholdPieces.StartPiece)piece, pieces, random, 1, 1); +- } else { +- this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece)piece, pieces, random, 1, 1); +- } +- } +- +- public static StrongholdPieces.LeftTurn createPiece( +- StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth +- ) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, 5, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new StrongholdPieces.LeftTurn(genDepth, random, boundingBox, orientation) +- : null; +- } +- +- @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { +- this.generateBox(level, box, 0, 0, 0, 4, 4, 4, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateSmallDoor(level, random, box, this.entryDoor, 1, 1, 0); +- Direction orientation = this.getOrientation(); +- if (orientation != Direction.NORTH && orientation != Direction.EAST) { +- this.generateBox(level, box, 4, 1, 1, 4, 3, 3, CAVE_AIR, CAVE_AIR, false); +- } else { +- this.generateBox(level, box, 0, 1, 1, 0, 3, 3, CAVE_AIR, CAVE_AIR, false); +- } +- } +- } +- +- public static class Library extends StrongholdPieces.StrongholdPiece { +- protected static final int WIDTH = 14; +- protected static final int HEIGHT = 6; +- protected static final int TALL_HEIGHT = 11; +- protected static final int DEPTH = 15; +- private final boolean isTall; +- +- public Library(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { +- super(StructurePieceType.STRONGHOLD_LIBRARY, genDepth, box); ++ public PrisonHall(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_PRISON_HALL, genDepth, box); + this.setOrientation(orientation); + this.entryDoor = this.randomSmallDoor(random); +- this.isTall = box.getYSpan() > 6; + } + +- public Library(CompoundTag tag) { +- super(StructurePieceType.STRONGHOLD_LIBRARY, tag); +- this.isTall = tag.getBoolean("Tall"); ++ public PrisonHall(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_PRISON_HALL, tag); + } + + @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { +- super.addAdditionalSaveData(context, tag); +- tag.putBoolean("Tall", this.isTall); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) piece, pieces, random, 1, 1); + } + +- public static StrongholdPieces.Library createPiece( +- StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth +- ) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -4, -1, 0, 14, 11, 15, orientation); +- if (!isOkBox(boundingBox) || pieces.findCollisionPiece(boundingBox) != null) { +- boundingBox = BoundingBox.orientBox(x, y, z, -4, -1, 0, 14, 6, 15, orientation); +- if (!isOkBox(boundingBox) || pieces.findCollisionPiece(boundingBox) != null) { +- return null; +- } +- } ++ public static StrongholdPieces.PrisonHall createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 9, 5, 11, orientation); + +- return new StrongholdPieces.Library(genDepth, random, boundingBox, orientation); ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new StrongholdPieces.PrisonHall(genDepth, random, structureboundingbox, orientation) : null; + } + + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { +- int i = 11; +- if (!this.isTall) { +- i = 6; +- } ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 8, 4, 10, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateSmallDoor(level, random, box, this.entryDoor, 1, 1, 0); ++ this.generateBox(level, box, 1, 1, 10, 3, 3, 10, StrongholdPieces.PrisonHall.CAVE_AIR, StrongholdPieces.PrisonHall.CAVE_AIR, false); ++ this.generateBox(level, box, 4, 1, 1, 4, 3, 1, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 4, 1, 3, 4, 3, 3, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 4, 1, 7, 4, 3, 7, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 4, 1, 9, 4, 3, 9, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); + +- this.generateBox(level, box, 0, 0, 0, 13, i - 1, 14, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateSmallDoor(level, random, box, this.entryDoor, 4, 1, 0); +- this.generateMaybeBox( +- level, box, random, 0.07F, 2, 1, 1, 11, 4, 13, Blocks.COBWEB.defaultBlockState(), Blocks.COBWEB.defaultBlockState(), false, false +- ); +- int i1 = 1; +- int i2 = 12; +- +- for (int i3 = 1; i3 <= 13; i3++) { +- if ((i3 - 1) % 4 == 0) { +- this.generateBox(level, box, 1, 1, i3, 1, 4, i3, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); +- this.generateBox(level, box, 12, 1, i3, 12, 4, i3, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); +- this.placeBlock(level, Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.EAST), 2, 3, i3, box); +- this.placeBlock(level, Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.WEST), 11, 3, i3, box); +- if (this.isTall) { +- this.generateBox(level, box, 1, 6, i3, 1, 9, i3, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); +- this.generateBox(level, box, 12, 6, i3, 12, 9, i3, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); +- } +- } else { +- this.generateBox(level, box, 1, 1, i3, 1, 4, i3, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); +- this.generateBox(level, box, 12, 1, i3, 12, 4, i3, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); +- if (this.isTall) { +- this.generateBox(level, box, 1, 6, i3, 1, 9, i3, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); +- this.generateBox(level, box, 12, 6, i3, 12, 9, i3, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); +- } +- } ++ for (int i = 1; i <= 3; ++i) { ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, true)).setValue(IronBarsBlock.SOUTH, true), 4, i, 4, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, true)).setValue(IronBarsBlock.SOUTH, true)).setValue(IronBarsBlock.EAST, true), 4, i, 5, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, true)).setValue(IronBarsBlock.SOUTH, true), 4, i, 6, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, true)).setValue(IronBarsBlock.EAST, true), 5, i, 5, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, true)).setValue(IronBarsBlock.EAST, true), 6, i, 5, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, true)).setValue(IronBarsBlock.EAST, true), 7, i, 5, box); + } + +- for (int i3x = 3; i3x < 12; i3x += 2) { +- this.generateBox(level, box, 3, 1, i3x, 4, 3, i3x, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); +- this.generateBox(level, box, 6, 1, i3x, 7, 3, i3x, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); +- this.generateBox(level, box, 9, 1, i3x, 10, 3, i3x, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); +- } ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, true)).setValue(IronBarsBlock.SOUTH, true), 4, 3, 2, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, true)).setValue(IronBarsBlock.SOUTH, true), 4, 3, 8, box); ++ IBlockData iblockdata = (IBlockData) Blocks.IRON_DOOR.defaultBlockState().setValue(DoorBlock.FACING, Direction.WEST); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.IRON_DOOR.defaultBlockState().setValue(DoorBlock.FACING, Direction.WEST)).setValue(DoorBlock.HALF, BlockPropertyDoubleBlockHalf.UPPER); + +- if (this.isTall) { +- this.generateBox(level, box, 1, 5, 1, 3, 5, 13, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); +- this.generateBox(level, box, 10, 5, 1, 12, 5, 13, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); +- this.generateBox(level, box, 4, 5, 1, 9, 5, 2, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); +- this.generateBox(level, box, 4, 5, 12, 9, 5, 13, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); +- this.placeBlock(level, Blocks.OAK_PLANKS.defaultBlockState(), 9, 5, 11, box); +- this.placeBlock(level, Blocks.OAK_PLANKS.defaultBlockState(), 8, 5, 11, box); +- this.placeBlock(level, Blocks.OAK_PLANKS.defaultBlockState(), 9, 5, 10, box); +- BlockState blockState = Blocks.OAK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.WEST, Boolean.valueOf(true)) +- .setValue(FenceBlock.EAST, Boolean.valueOf(true)); +- BlockState blockState1 = Blocks.OAK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.NORTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.SOUTH, Boolean.valueOf(true)); +- this.generateBox(level, box, 3, 6, 3, 3, 6, 11, blockState1, blockState1, false); +- this.generateBox(level, box, 10, 6, 3, 10, 6, 9, blockState1, blockState1, false); +- this.generateBox(level, box, 4, 6, 2, 9, 6, 2, blockState, blockState, false); +- this.generateBox(level, box, 4, 6, 12, 7, 6, 12, blockState, blockState, false); +- this.placeBlock( +- level, +- Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, Boolean.valueOf(true)).setValue(FenceBlock.EAST, Boolean.valueOf(true)), +- 3, +- 6, +- 2, +- box +- ); +- this.placeBlock( +- level, +- Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.SOUTH, Boolean.valueOf(true)).setValue(FenceBlock.EAST, Boolean.valueOf(true)), +- 3, +- 6, +- 12, +- box +- ); +- this.placeBlock( +- level, +- Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, Boolean.valueOf(true)).setValue(FenceBlock.WEST, Boolean.valueOf(true)), +- 10, +- 6, +- 2, +- box +- ); +- +- for (int i4 = 0; i4 <= 2; i4++) { +- this.placeBlock( +- level, +- Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.SOUTH, Boolean.valueOf(true)).setValue(FenceBlock.WEST, Boolean.valueOf(true)), +- 8 + i4, +- 6, +- 12 - i4, +- box +- ); +- if (i4 != 2) { +- this.placeBlock( +- level, +- Blocks.OAK_FENCE +- .defaultBlockState() +- .setValue(FenceBlock.NORTH, Boolean.valueOf(true)) +- .setValue(FenceBlock.EAST, Boolean.valueOf(true)), +- 8 + i4, +- 6, +- 11 - i4, +- box +- ); +- } +- } +- +- BlockState blockState2 = Blocks.LADDER.defaultBlockState().setValue(LadderBlock.FACING, Direction.SOUTH); +- this.placeBlock(level, blockState2, 10, 1, 13, box); +- this.placeBlock(level, blockState2, 10, 2, 13, box); +- this.placeBlock(level, blockState2, 10, 3, 13, box); +- this.placeBlock(level, blockState2, 10, 4, 13, box); +- this.placeBlock(level, blockState2, 10, 5, 13, box); +- this.placeBlock(level, blockState2, 10, 6, 13, box); +- this.placeBlock(level, blockState2, 10, 7, 13, box); +- int i5 = 7; +- int i6 = 7; +- BlockState blockState3 = Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, Boolean.valueOf(true)); +- this.placeBlock(level, blockState3, 6, 9, 7, box); +- BlockState blockState4 = Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, Boolean.valueOf(true)); +- this.placeBlock(level, blockState4, 7, 9, 7, box); +- this.placeBlock(level, blockState3, 6, 8, 7, box); +- this.placeBlock(level, blockState4, 7, 8, 7, box); +- BlockState blockState5 = blockState1.setValue(FenceBlock.WEST, Boolean.valueOf(true)).setValue(FenceBlock.EAST, Boolean.valueOf(true)); +- this.placeBlock(level, blockState5, 6, 7, 7, box); +- this.placeBlock(level, blockState5, 7, 7, 7, box); +- this.placeBlock(level, blockState3, 5, 7, 7, box); +- this.placeBlock(level, blockState4, 8, 7, 7, box); +- this.placeBlock(level, blockState3.setValue(FenceBlock.NORTH, Boolean.valueOf(true)), 6, 7, 6, box); +- this.placeBlock(level, blockState3.setValue(FenceBlock.SOUTH, Boolean.valueOf(true)), 6, 7, 8, box); +- this.placeBlock(level, blockState4.setValue(FenceBlock.NORTH, Boolean.valueOf(true)), 7, 7, 6, box); +- this.placeBlock(level, blockState4.setValue(FenceBlock.SOUTH, Boolean.valueOf(true)), 7, 7, 8, box); +- BlockState blockState6 = Blocks.TORCH.defaultBlockState(); +- this.placeBlock(level, blockState6, 5, 8, 7, box); +- this.placeBlock(level, blockState6, 8, 8, 7, box); +- this.placeBlock(level, blockState6, 6, 8, 6, box); +- this.placeBlock(level, blockState6, 6, 8, 8, box); +- this.placeBlock(level, blockState6, 7, 8, 6, box); +- this.placeBlock(level, blockState6, 7, 8, 8, box); +- } +- +- this.createChest(level, box, random, 3, 3, 5, BuiltInLootTables.STRONGHOLD_LIBRARY); +- if (this.isTall) { +- this.placeBlock(level, CAVE_AIR, 12, 9, 1, box); +- this.createChest(level, box, random, 12, 8, 1, BuiltInLootTables.STRONGHOLD_LIBRARY); +- } ++ this.placeBlock(level, iblockdata, 4, 1, 2, box); ++ this.placeBlock(level, iblockdata1, 4, 2, 2, box); ++ this.placeBlock(level, iblockdata, 4, 1, 8, box); ++ this.placeBlock(level, iblockdata1, 4, 2, 8, box); + } + } + +- static class PieceWeight { +- public final Class pieceClass; +- public final int weight; +- public int placeCount; +- public final int maxPlaceCount; ++ public static class LeftTurn extends StrongholdPieces.q { + +- public PieceWeight(Class pieceClass, int weight, int maxPlaceCount) { +- this.pieceClass = pieceClass; +- this.weight = weight; +- this.maxPlaceCount = maxPlaceCount; +- } +- +- public boolean doPlace(int genDepth) { +- return this.maxPlaceCount == 0 || this.placeCount < this.maxPlaceCount; +- } +- +- public boolean isValid() { +- return this.maxPlaceCount == 0 || this.placeCount < this.maxPlaceCount; +- } +- } +- +- public static class PortalRoom extends StrongholdPieces.StrongholdPiece { +- protected static final int WIDTH = 11; +- protected static final int HEIGHT = 8; +- protected static final int DEPTH = 16; +- private boolean hasPlacedSpawner; +- +- public PortalRoom(int genDepth, BoundingBox box, Direction orientation) { +- super(StructurePieceType.STRONGHOLD_PORTAL_ROOM, genDepth, box); ++ public LeftTurn(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_LEFT_TURN, genDepth, box); + this.setOrientation(orientation); ++ this.entryDoor = this.randomSmallDoor(random); + } + +- public PortalRoom(CompoundTag tag) { +- super(StructurePieceType.STRONGHOLD_PORTAL_ROOM, tag); +- this.hasPlacedSpawner = tag.getBoolean("Mob"); ++ public LeftTurn(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_LEFT_TURN, tag); + } + + @Override +- protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { +- super.addAdditionalSaveData(context, tag); +- tag.putBoolean("Mob", this.hasPlacedSpawner); +- } +- +- @Override + public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- if (piece != null) { +- ((StrongholdPieces.StartPiece)piece).portalRoomPiece = this; +- } +- } ++ Direction enumdirection = this.getOrientation(); + +- public static StrongholdPieces.PortalRoom createPiece(StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -4, -1, 0, 11, 8, 16, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new StrongholdPieces.PortalRoom(genDepth, boundingBox, orientation) +- : null; +- } +- +- @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { +- this.generateBox(level, box, 0, 0, 0, 10, 7, 15, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateSmallDoor(level, random, box, StrongholdPieces.StrongholdPiece.SmallDoorType.GRATES, 4, 1, 0); +- int i = 6; +- this.generateBox(level, box, 1, 6, 1, 1, 6, 14, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(level, box, 9, 6, 1, 9, 6, 14, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(level, box, 2, 6, 1, 8, 6, 2, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(level, box, 2, 6, 14, 8, 6, 14, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(level, box, 1, 1, 1, 2, 1, 4, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(level, box, 8, 1, 1, 9, 1, 4, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(level, box, 1, 1, 1, 1, 1, 3, Blocks.LAVA.defaultBlockState(), Blocks.LAVA.defaultBlockState(), false); +- this.generateBox(level, box, 9, 1, 1, 9, 1, 3, Blocks.LAVA.defaultBlockState(), Blocks.LAVA.defaultBlockState(), false); +- this.generateBox(level, box, 3, 1, 8, 7, 1, 12, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(level, box, 4, 1, 9, 6, 1, 11, Blocks.LAVA.defaultBlockState(), Blocks.LAVA.defaultBlockState(), false); +- BlockState blockState = Blocks.IRON_BARS +- .defaultBlockState() +- .setValue(IronBarsBlock.NORTH, Boolean.valueOf(true)) +- .setValue(IronBarsBlock.SOUTH, Boolean.valueOf(true)); +- BlockState blockState1 = Blocks.IRON_BARS +- .defaultBlockState() +- .setValue(IronBarsBlock.WEST, Boolean.valueOf(true)) +- .setValue(IronBarsBlock.EAST, Boolean.valueOf(true)); +- +- for (int i1 = 3; i1 < 14; i1 += 2) { +- this.generateBox(level, box, 0, 3, i1, 0, 4, i1, blockState, blockState, false); +- this.generateBox(level, box, 10, 3, i1, 10, 4, i1, blockState, blockState, false); ++ if (enumdirection != Direction.NORTH && enumdirection != Direction.EAST) { ++ this.generateSmallDoorChildRight((StrongholdPieces.StartPiece) piece, pieces, random, 1, 1); ++ } else { ++ this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece) piece, pieces, random, 1, 1); + } + +- for (int i1 = 2; i1 < 9; i1 += 2) { +- this.generateBox(level, box, i1, 3, 15, i1, 4, 15, blockState1, blockState1, false); +- } +- +- BlockState blockState2 = Blocks.STONE_BRICK_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.NORTH); +- this.generateBox(level, box, 4, 1, 5, 6, 1, 7, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(level, box, 4, 2, 6, 6, 2, 7, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(level, box, 4, 3, 7, 6, 3, 7, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- +- for (int i2 = 4; i2 <= 6; i2++) { +- this.placeBlock(level, blockState2, i2, 1, 4, box); +- this.placeBlock(level, blockState2, i2, 2, 5, box); +- this.placeBlock(level, blockState2, i2, 3, 6, box); +- } +- +- BlockState blockState3 = Blocks.END_PORTAL_FRAME.defaultBlockState().setValue(EndPortalFrameBlock.FACING, Direction.NORTH); +- BlockState blockState4 = Blocks.END_PORTAL_FRAME.defaultBlockState().setValue(EndPortalFrameBlock.FACING, Direction.SOUTH); +- BlockState blockState5 = Blocks.END_PORTAL_FRAME.defaultBlockState().setValue(EndPortalFrameBlock.FACING, Direction.EAST); +- BlockState blockState6 = Blocks.END_PORTAL_FRAME.defaultBlockState().setValue(EndPortalFrameBlock.FACING, Direction.WEST); +- boolean flag = true; +- boolean[] flags = new boolean[12]; +- +- for (int i3 = 0; i3 < flags.length; i3++) { +- flags[i3] = random.nextFloat() > 0.9F; +- flag &= flags[i3]; +- } +- +- this.placeBlock(level, blockState3.setValue(EndPortalFrameBlock.HAS_EYE, Boolean.valueOf(flags[0])), 4, 3, 8, box); +- this.placeBlock(level, blockState3.setValue(EndPortalFrameBlock.HAS_EYE, Boolean.valueOf(flags[1])), 5, 3, 8, box); +- this.placeBlock(level, blockState3.setValue(EndPortalFrameBlock.HAS_EYE, Boolean.valueOf(flags[2])), 6, 3, 8, box); +- this.placeBlock(level, blockState4.setValue(EndPortalFrameBlock.HAS_EYE, Boolean.valueOf(flags[3])), 4, 3, 12, box); +- this.placeBlock(level, blockState4.setValue(EndPortalFrameBlock.HAS_EYE, Boolean.valueOf(flags[4])), 5, 3, 12, box); +- this.placeBlock(level, blockState4.setValue(EndPortalFrameBlock.HAS_EYE, Boolean.valueOf(flags[5])), 6, 3, 12, box); +- this.placeBlock(level, blockState5.setValue(EndPortalFrameBlock.HAS_EYE, Boolean.valueOf(flags[6])), 3, 3, 9, box); +- this.placeBlock(level, blockState5.setValue(EndPortalFrameBlock.HAS_EYE, Boolean.valueOf(flags[7])), 3, 3, 10, box); +- this.placeBlock(level, blockState5.setValue(EndPortalFrameBlock.HAS_EYE, Boolean.valueOf(flags[8])), 3, 3, 11, box); +- this.placeBlock(level, blockState6.setValue(EndPortalFrameBlock.HAS_EYE, Boolean.valueOf(flags[9])), 7, 3, 9, box); +- this.placeBlock(level, blockState6.setValue(EndPortalFrameBlock.HAS_EYE, Boolean.valueOf(flags[10])), 7, 3, 10, box); +- this.placeBlock(level, blockState6.setValue(EndPortalFrameBlock.HAS_EYE, Boolean.valueOf(flags[11])), 7, 3, 11, box); +- if (flag) { +- BlockState blockState7 = Blocks.END_PORTAL.defaultBlockState(); +- this.placeBlock(level, blockState7, 4, 3, 9, box); +- this.placeBlock(level, blockState7, 5, 3, 9, box); +- this.placeBlock(level, blockState7, 6, 3, 9, box); +- this.placeBlock(level, blockState7, 4, 3, 10, box); +- this.placeBlock(level, blockState7, 5, 3, 10, box); +- this.placeBlock(level, blockState7, 6, 3, 10, box); +- this.placeBlock(level, blockState7, 4, 3, 11, box); +- this.placeBlock(level, blockState7, 5, 3, 11, box); +- this.placeBlock(level, blockState7, 6, 3, 11, box); +- } +- +- if (!this.hasPlacedSpawner) { +- BlockPos worldPos = this.getWorldPos(5, 3, 6); +- if (box.isInside(worldPos)) { +- this.hasPlacedSpawner = true; +- level.setBlock(worldPos, Blocks.SPAWNER.defaultBlockState(), 2); +- if (level.getBlockEntity(worldPos) instanceof SpawnerBlockEntity spawnerBlockEntity) { +- spawnerBlockEntity.setEntityId(EntityType.SILVERFISH, random); +- } +- } +- } + } +- } + +- public static class PrisonHall extends StrongholdPieces.StrongholdPiece { +- protected static final int WIDTH = 9; +- protected static final int HEIGHT = 5; +- protected static final int DEPTH = 11; ++ public static StrongholdPieces.LeftTurn createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, 5, orientation); + +- public PrisonHall(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { +- super(StructurePieceType.STRONGHOLD_PRISON_HALL, genDepth, box); +- this.setOrientation(orientation); +- this.entryDoor = this.randomSmallDoor(random); ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new StrongholdPieces.LeftTurn(genDepth, random, structureboundingbox, orientation) : null; + } + +- public PrisonHall(CompoundTag tag) { +- super(StructurePieceType.STRONGHOLD_PRISON_HALL, tag); +- } +- + @Override +- public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- this.generateSmallDoorChildForward((StrongholdPieces.StartPiece)piece, pieces, random, 1, 1); +- } +- +- public static StrongholdPieces.PrisonHall createPiece( +- StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth +- ) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 9, 5, 11, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new StrongholdPieces.PrisonHall(genDepth, random, boundingBox, orientation) +- : null; +- } +- +- @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { +- this.generateBox(level, box, 0, 0, 0, 8, 4, 10, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 4, 4, 4, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); + this.generateSmallDoor(level, random, box, this.entryDoor, 1, 1, 0); +- this.generateBox(level, box, 1, 1, 10, 3, 3, 10, CAVE_AIR, CAVE_AIR, false); +- this.generateBox(level, box, 4, 1, 1, 4, 3, 1, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(level, box, 4, 1, 3, 4, 3, 3, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(level, box, 4, 1, 7, 4, 3, 7, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateBox(level, box, 4, 1, 9, 4, 3, 9, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ Direction enumdirection = this.getOrientation(); + +- for (int i = 1; i <= 3; i++) { +- this.placeBlock( +- level, +- Blocks.IRON_BARS +- .defaultBlockState() +- .setValue(IronBarsBlock.NORTH, Boolean.valueOf(true)) +- .setValue(IronBarsBlock.SOUTH, Boolean.valueOf(true)), +- 4, +- i, +- 4, +- box +- ); +- this.placeBlock( +- level, +- Blocks.IRON_BARS +- .defaultBlockState() +- .setValue(IronBarsBlock.NORTH, Boolean.valueOf(true)) +- .setValue(IronBarsBlock.SOUTH, Boolean.valueOf(true)) +- .setValue(IronBarsBlock.EAST, Boolean.valueOf(true)), +- 4, +- i, +- 5, +- box +- ); +- this.placeBlock( +- level, +- Blocks.IRON_BARS +- .defaultBlockState() +- .setValue(IronBarsBlock.NORTH, Boolean.valueOf(true)) +- .setValue(IronBarsBlock.SOUTH, Boolean.valueOf(true)), +- 4, +- i, +- 6, +- box +- ); +- this.placeBlock( +- level, +- Blocks.IRON_BARS +- .defaultBlockState() +- .setValue(IronBarsBlock.WEST, Boolean.valueOf(true)) +- .setValue(IronBarsBlock.EAST, Boolean.valueOf(true)), +- 5, +- i, +- 5, +- box +- ); +- this.placeBlock( +- level, +- Blocks.IRON_BARS +- .defaultBlockState() +- .setValue(IronBarsBlock.WEST, Boolean.valueOf(true)) +- .setValue(IronBarsBlock.EAST, Boolean.valueOf(true)), +- 6, +- i, +- 5, +- box +- ); +- this.placeBlock( +- level, +- Blocks.IRON_BARS +- .defaultBlockState() +- .setValue(IronBarsBlock.WEST, Boolean.valueOf(true)) +- .setValue(IronBarsBlock.EAST, Boolean.valueOf(true)), +- 7, +- i, +- 5, +- box +- ); ++ if (enumdirection != Direction.NORTH && enumdirection != Direction.EAST) { ++ this.generateBox(level, box, 4, 1, 1, 4, 3, 3, StrongholdPieces.LeftTurn.CAVE_AIR, StrongholdPieces.LeftTurn.CAVE_AIR, false); ++ } else { ++ this.generateBox(level, box, 0, 1, 1, 0, 3, 3, StrongholdPieces.LeftTurn.CAVE_AIR, StrongholdPieces.LeftTurn.CAVE_AIR, false); + } + +- this.placeBlock( +- level, +- Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, Boolean.valueOf(true)).setValue(IronBarsBlock.SOUTH, Boolean.valueOf(true)), +- 4, +- 3, +- 2, +- box +- ); +- this.placeBlock( +- level, +- Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, Boolean.valueOf(true)).setValue(IronBarsBlock.SOUTH, Boolean.valueOf(true)), +- 4, +- 3, +- 8, +- box +- ); +- BlockState blockState = Blocks.IRON_DOOR.defaultBlockState().setValue(DoorBlock.FACING, Direction.WEST); +- BlockState blockState1 = Blocks.IRON_DOOR +- .defaultBlockState() +- .setValue(DoorBlock.FACING, Direction.WEST) +- .setValue(DoorBlock.HALF, DoubleBlockHalf.UPPER); +- this.placeBlock(level, blockState, 4, 1, 2, box); +- this.placeBlock(level, blockState1, 4, 2, 2, box); +- this.placeBlock(level, blockState, 4, 1, 8, box); +- this.placeBlock(level, blockState1, 4, 2, 8, box); + } + } + +- public static class RightTurn extends StrongholdPieces.Turn { ++ public static class RightTurn extends StrongholdPieces.q { ++ + public RightTurn(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { + super(StructurePieceType.STRONGHOLD_RIGHT_TURN, genDepth, box); + this.setOrientation(orientation); +@@ -1037,45 +401,39 @@ + + @Override + public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- Direction orientation = this.getOrientation(); +- if (orientation != Direction.NORTH && orientation != Direction.EAST) { +- this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece)piece, pieces, random, 1, 1); ++ Direction enumdirection = this.getOrientation(); ++ ++ if (enumdirection != Direction.NORTH && enumdirection != Direction.EAST) { ++ this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece) piece, pieces, random, 1, 1); + } else { +- this.generateSmallDoorChildRight((StrongholdPieces.StartPiece)piece, pieces, random, 1, 1); ++ this.generateSmallDoorChildRight((StrongholdPieces.StartPiece) piece, pieces, random, 1, 1); + } ++ + } + +- public static StrongholdPieces.RightTurn createPiece( +- StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth +- ) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, 5, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new StrongholdPieces.RightTurn(genDepth, random, boundingBox, orientation) +- : null; ++ public static StrongholdPieces.RightTurn createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, 5, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new StrongholdPieces.RightTurn(genDepth, random, structureboundingbox, orientation) : null; + } + + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { + this.generateBox(level, box, 0, 0, 0, 4, 4, 4, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); + this.generateSmallDoor(level, random, box, this.entryDoor, 1, 1, 0); +- Direction orientation = this.getOrientation(); +- if (orientation != Direction.NORTH && orientation != Direction.EAST) { +- this.generateBox(level, box, 0, 1, 1, 0, 3, 3, CAVE_AIR, CAVE_AIR, false); ++ Direction enumdirection = this.getOrientation(); ++ ++ if (enumdirection != Direction.NORTH && enumdirection != Direction.EAST) { ++ this.generateBox(level, box, 0, 1, 1, 0, 3, 3, StrongholdPieces.RightTurn.CAVE_AIR, StrongholdPieces.RightTurn.CAVE_AIR, false); + } else { +- this.generateBox(level, box, 4, 1, 1, 4, 3, 3, CAVE_AIR, CAVE_AIR, false); ++ this.generateBox(level, box, 4, 1, 1, 4, 3, 3, StrongholdPieces.RightTurn.CAVE_AIR, StrongholdPieces.RightTurn.CAVE_AIR, false); + } ++ + } + } + + public static class RoomCrossing extends StrongholdPieces.StrongholdPiece { ++ + protected static final int WIDTH = 11; + protected static final int HEIGHT = 7; + protected static final int DEPTH = 11; +@@ -1101,44 +459,35 @@ + + @Override + public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- this.generateSmallDoorChildForward((StrongholdPieces.StartPiece)piece, pieces, random, 4, 1); +- this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece)piece, pieces, random, 1, 4); +- this.generateSmallDoorChildRight((StrongholdPieces.StartPiece)piece, pieces, random, 1, 4); ++ this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) piece, pieces, random, 4, 1); ++ this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece) piece, pieces, random, 1, 4); ++ this.generateSmallDoorChildRight((StrongholdPieces.StartPiece) piece, pieces, random, 1, 4); + } + +- public static StrongholdPieces.RoomCrossing createPiece( +- StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth +- ) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -4, -1, 0, 11, 7, 11, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new StrongholdPieces.RoomCrossing(genDepth, random, boundingBox, orientation) +- : null; ++ public static StrongholdPieces.RoomCrossing createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -4, -1, 0, 11, 7, 11, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new StrongholdPieces.RoomCrossing(genDepth, random, structureboundingbox, orientation) : null; + } + + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { + this.generateBox(level, box, 0, 0, 0, 10, 6, 10, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); + this.generateSmallDoor(level, random, box, this.entryDoor, 4, 1, 0); +- this.generateBox(level, box, 4, 1, 10, 6, 3, 10, CAVE_AIR, CAVE_AIR, false); +- this.generateBox(level, box, 0, 1, 4, 0, 3, 6, CAVE_AIR, CAVE_AIR, false); +- this.generateBox(level, box, 10, 1, 4, 10, 3, 6, CAVE_AIR, CAVE_AIR, false); ++ this.generateBox(level, box, 4, 1, 10, 6, 3, 10, StrongholdPieces.RoomCrossing.CAVE_AIR, StrongholdPieces.RoomCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, 0, 1, 4, 0, 3, 6, StrongholdPieces.RoomCrossing.CAVE_AIR, StrongholdPieces.RoomCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, 10, 1, 4, 10, 3, 6, StrongholdPieces.RoomCrossing.CAVE_AIR, StrongholdPieces.RoomCrossing.CAVE_AIR, false); ++ int i; ++ + switch (this.type) { + case 0: + this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 5, 1, 5, box); + this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 5, 2, 5, box); + this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 5, 3, 5, box); +- this.placeBlock(level, Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.WEST), 4, 3, 5, box); +- this.placeBlock(level, Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.EAST), 6, 3, 5, box); +- this.placeBlock(level, Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.SOUTH), 5, 3, 4, box); +- this.placeBlock(level, Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.NORTH), 5, 3, 6, box); ++ this.placeBlock(level, (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.WEST), 4, 3, 5, box); ++ this.placeBlock(level, (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.EAST), 6, 3, 5, box); ++ this.placeBlock(level, (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.SOUTH), 5, 3, 4, box); ++ this.placeBlock(level, (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.NORTH), 5, 3, 6, box); + this.placeBlock(level, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 4, 1, 4, box); + this.placeBlock(level, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 4, 1, 5, box); + this.placeBlock(level, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 4, 1, 6, box); +@@ -1149,7 +498,7 @@ + this.placeBlock(level, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 5, 1, 6, box); + break; + case 1: +- for (int i = 0; i < 5; i++) { ++ for (i = 0; i < 5; ++i) { + this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 3, 1, 3 + i, box); + this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 7, 1, 3 + i, box); + this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 3 + i, 1, 3, box); +@@ -1162,12 +511,12 @@ + this.placeBlock(level, Blocks.WATER.defaultBlockState(), 5, 4, 5, box); + break; + case 2: +- for (int i = 1; i <= 9; i++) { ++ for (i = 1; i <= 9; ++i) { + this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 1, 3, i, box); + this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 9, 3, i, box); + } + +- for (int i = 1; i <= 9; i++) { ++ for (i = 1; i <= 9; ++i) { + this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), i, 3, 1, box); + this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), i, 3, 9, box); + } +@@ -1181,7 +530,7 @@ + this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 4, 3, 5, box); + this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 6, 3, 5, box); + +- for (int i = 1; i <= 3; i++) { ++ for (i = 1; i <= 3; ++i) { + this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 4, i, 4, box); + this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 6, i, 4, box); + this.placeBlock(level, Blocks.COBBLESTONE.defaultBlockState(), 4, i, 6, box); +@@ -1190,7 +539,7 @@ + + this.placeBlock(level, Blocks.WALL_TORCH.defaultBlockState(), 5, 3, 5, box); + +- for (int i = 2; i <= 8; i++) { ++ for (i = 2; i <= 8; ++i) { + this.placeBlock(level, Blocks.OAK_PLANKS.defaultBlockState(), 2, 3, i, box); + this.placeBlock(level, Blocks.OAK_PLANKS.defaultBlockState(), 3, 3, i, box); + if (i <= 3 || i >= 7) { +@@ -1203,36 +552,67 @@ + this.placeBlock(level, Blocks.OAK_PLANKS.defaultBlockState(), 8, 3, i, box); + } + +- BlockState blockState = Blocks.LADDER.defaultBlockState().setValue(LadderBlock.FACING, Direction.WEST); +- this.placeBlock(level, blockState, 9, 1, 3, box); +- this.placeBlock(level, blockState, 9, 2, 3, box); +- this.placeBlock(level, blockState, 9, 3, 3, box); ++ IBlockData iblockdata = (IBlockData) Blocks.LADDER.defaultBlockState().setValue(LadderBlock.FACING, Direction.WEST); ++ ++ this.placeBlock(level, iblockdata, 9, 1, 3, box); ++ this.placeBlock(level, iblockdata, 9, 2, 3, box); ++ this.placeBlock(level, iblockdata, 9, 3, 3, box); + this.createChest(level, box, random, 3, 4, 8, BuiltInLootTables.STRONGHOLD_CROSSING); + } ++ + } + } + +- static class SmoothStoneSelector extends StructurePiece.BlockSelector { ++ public static class StraightStairsDown extends StrongholdPieces.StrongholdPiece { ++ ++ private static final int WIDTH = 5; ++ private static final int HEIGHT = 11; ++ private static final int DEPTH = 8; ++ ++ public StraightStairsDown(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_STRAIGHT_STAIRS_DOWN, genDepth, box); ++ this.setOrientation(orientation); ++ this.entryDoor = this.randomSmallDoor(random); ++ } ++ ++ public StraightStairsDown(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_STRAIGHT_STAIRS_DOWN, tag); ++ } ++ + @Override +- public void next(RandomSource random, int x, int y, int z, boolean wall) { +- if (wall) { +- float randomFloat = random.nextFloat(); +- if (randomFloat < 0.2F) { +- this.next = Blocks.CRACKED_STONE_BRICKS.defaultBlockState(); +- } else if (randomFloat < 0.5F) { +- this.next = Blocks.MOSSY_STONE_BRICKS.defaultBlockState(); +- } else if (randomFloat < 0.55F) { +- this.next = Blocks.INFESTED_STONE_BRICKS.defaultBlockState(); +- } else { +- this.next = Blocks.STONE_BRICKS.defaultBlockState(); ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) piece, pieces, random, 1, 1); ++ } ++ ++ public static StrongholdPieces.StraightStairsDown createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -7, 0, 5, 11, 8, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new StrongholdPieces.StraightStairsDown(genDepth, random, structureboundingbox, orientation) : null; ++ } ++ ++ @Override ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 4, 10, 7, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateSmallDoor(level, random, box, this.entryDoor, 1, 7, 0); ++ this.generateSmallDoor(level, random, box, StrongholdPieces.StrongholdPiece.a.OPENING, 1, 1, 7); ++ IBlockData iblockdata = (IBlockData) Blocks.COBBLESTONE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.SOUTH); ++ ++ for (int i = 0; i < 6; ++i) { ++ this.placeBlock(level, iblockdata, 1, 6 - i, 1 + i, box); ++ this.placeBlock(level, iblockdata, 2, 6 - i, 1 + i, box); ++ this.placeBlock(level, iblockdata, 3, 6 - i, 1 + i, box); ++ if (i < 5) { ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 1, 5 - i, 1 + i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 2, 5 - i, 1 + i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 3, 5 - i, 1 + i, box); + } +- } else { +- this.next = Blocks.CAVE_AIR.defaultBlockState(); + } ++ + } + } + + public static class StairsDown extends StrongholdPieces.StrongholdPiece { ++ + private static final int WIDTH = 5; + private static final int HEIGHT = 11; + private static final int DEPTH = 5; +@@ -1242,7 +622,7 @@ + super(type, genDepth, makeBoundingBox(x, 64, z, orientation, 5, 11, 5)); + this.isSource = true; + this.setOrientation(orientation); +- this.entryDoor = StrongholdPieces.StrongholdPiece.SmallDoorType.OPENING; ++ this.entryDoor = StrongholdPieces.StrongholdPiece.a.OPENING; + } + + public StairsDown(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { +@@ -1273,31 +653,20 @@ + StrongholdPieces.imposedPiece = StrongholdPieces.FiveCrossing.class; + } + +- this.generateSmallDoorChildForward((StrongholdPieces.StartPiece)piece, pieces, random, 1, 1); ++ this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) piece, pieces, random, 1, 1); + } + +- public static StrongholdPieces.StairsDown createPiece( +- StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth +- ) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -1, -7, 0, 5, 11, 5, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new StrongholdPieces.StairsDown(genDepth, random, boundingBox, orientation) +- : null; ++ public static StrongholdPieces.StairsDown createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -7, 0, 5, 11, 5, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new StrongholdPieces.StairsDown(genDepth, random, structureboundingbox, orientation) : null; + } + + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { + this.generateBox(level, box, 0, 0, 0, 4, 10, 4, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); + this.generateSmallDoor(level, random, box, this.entryDoor, 1, 7, 0); +- this.generateSmallDoor(level, random, box, StrongholdPieces.StrongholdPiece.SmallDoorType.OPENING, 1, 1, 4); ++ this.generateSmallDoor(level, random, box, StrongholdPieces.StrongholdPiece.a.OPENING, 1, 1, 4); + this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 2, 6, 1, box); + this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 1, 5, 1, box); + this.placeBlock(level, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), 1, 6, 1, box); +@@ -1318,171 +687,484 @@ + } + } + +- public static class StartPiece extends StrongholdPieces.StairsDown { +- public StrongholdPieces.PieceWeight previousPiece; +- @Nullable +- public StrongholdPieces.PortalRoom portalRoomPiece; +- public final List pendingChildren = Lists.newArrayList(); ++ public static class FiveCrossing extends StrongholdPieces.StrongholdPiece { + +- public StartPiece(RandomSource random, int x, int z) { +- super(StructurePieceType.STRONGHOLD_START, 0, x, z, getRandomHorizontalDirection(random)); ++ protected static final int WIDTH = 10; ++ protected static final int HEIGHT = 9; ++ protected static final int DEPTH = 11; ++ private final boolean leftLow; ++ private final boolean leftHigh; ++ private final boolean rightLow; ++ private final boolean rightHigh; ++ ++ public FiveCrossing(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_FIVE_CROSSING, genDepth, box); ++ this.setOrientation(orientation); ++ this.entryDoor = this.randomSmallDoor(random); ++ this.leftLow = random.nextBoolean(); ++ this.leftHigh = random.nextBoolean(); ++ this.rightLow = random.nextBoolean(); ++ this.rightHigh = random.nextInt(3) > 0; + } + +- public StartPiece(CompoundTag tag) { +- super(StructurePieceType.STRONGHOLD_START, tag); ++ public FiveCrossing(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_FIVE_CROSSING, tag); ++ this.leftLow = tag.getBoolean("leftLow"); ++ this.leftHigh = tag.getBoolean("leftHigh"); ++ this.rightLow = tag.getBoolean("rightLow"); ++ this.rightHigh = tag.getBoolean("rightHigh"); + } + + @Override +- public BlockPos getLocatorPosition() { +- return this.portalRoomPiece != null ? this.portalRoomPiece.getLocatorPosition() : super.getLocatorPosition(); ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putBoolean("leftLow", this.leftLow); ++ tag.putBoolean("leftHigh", this.leftHigh); ++ tag.putBoolean("rightLow", this.rightLow); ++ tag.putBoolean("rightHigh", this.rightHigh); + } ++ ++ @Override ++ public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { ++ int i = 3; ++ int j = 5; ++ Direction enumdirection = this.getOrientation(); ++ ++ if (enumdirection == Direction.WEST || enumdirection == Direction.NORTH) { ++ i = 8 - i; ++ j = 8 - j; ++ } ++ ++ this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) piece, pieces, random, 5, 1); ++ if (this.leftLow) { ++ this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece) piece, pieces, random, i, 1); ++ } ++ ++ if (this.leftHigh) { ++ this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece) piece, pieces, random, j, 7); ++ } ++ ++ if (this.rightLow) { ++ this.generateSmallDoorChildRight((StrongholdPieces.StartPiece) piece, pieces, random, i, 1); ++ } ++ ++ if (this.rightHigh) { ++ this.generateSmallDoorChildRight((StrongholdPieces.StartPiece) piece, pieces, random, j, 7); ++ } ++ ++ } ++ ++ public static StrongholdPieces.FiveCrossing createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -4, -3, 0, 10, 9, 11, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new StrongholdPieces.FiveCrossing(genDepth, random, structureboundingbox, orientation) : null; ++ } ++ ++ @Override ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 9, 8, 10, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateSmallDoor(level, random, box, this.entryDoor, 4, 3, 0); ++ if (this.leftLow) { ++ this.generateBox(level, box, 0, 3, 1, 0, 5, 3, StrongholdPieces.FiveCrossing.CAVE_AIR, StrongholdPieces.FiveCrossing.CAVE_AIR, false); ++ } ++ ++ if (this.rightLow) { ++ this.generateBox(level, box, 9, 3, 1, 9, 5, 3, StrongholdPieces.FiveCrossing.CAVE_AIR, StrongholdPieces.FiveCrossing.CAVE_AIR, false); ++ } ++ ++ if (this.leftHigh) { ++ this.generateBox(level, box, 0, 5, 7, 0, 7, 9, StrongholdPieces.FiveCrossing.CAVE_AIR, StrongholdPieces.FiveCrossing.CAVE_AIR, false); ++ } ++ ++ if (this.rightHigh) { ++ this.generateBox(level, box, 9, 5, 7, 9, 7, 9, StrongholdPieces.FiveCrossing.CAVE_AIR, StrongholdPieces.FiveCrossing.CAVE_AIR, false); ++ } ++ ++ this.generateBox(level, box, 5, 1, 10, 7, 3, 10, StrongholdPieces.FiveCrossing.CAVE_AIR, StrongholdPieces.FiveCrossing.CAVE_AIR, false); ++ this.generateBox(level, box, 1, 2, 1, 8, 2, 6, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 4, 1, 5, 4, 4, 9, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 8, 1, 5, 8, 4, 9, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 1, 4, 7, 3, 4, 9, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 1, 3, 5, 3, 3, 6, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 1, 3, 4, 3, 3, 4, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); ++ this.generateBox(level, box, 1, 4, 6, 3, 4, 6, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 1, 7, 7, 1, 8, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 5, 1, 9, 7, 1, 9, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 2, 7, 7, 2, 7, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 5, 7, 4, 5, 9, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); ++ this.generateBox(level, box, 8, 5, 7, 8, 5, 9, Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), Blocks.SMOOTH_STONE_SLAB.defaultBlockState(), false); ++ this.generateBox(level, box, 5, 5, 7, 7, 5, 9, (IBlockData) Blocks.SMOOTH_STONE_SLAB.defaultBlockState().setValue(SlabBlock.TYPE, SlabType.DOUBLE), (IBlockData) Blocks.SMOOTH_STONE_SLAB.defaultBlockState().setValue(SlabBlock.TYPE, SlabType.DOUBLE), false); ++ this.placeBlock(level, (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.SOUTH), 6, 5, 6, box); ++ } + } + +- public static class Straight extends StrongholdPieces.StrongholdPiece { ++ public static class ChestCorridor extends StrongholdPieces.StrongholdPiece { ++ + private static final int WIDTH = 5; + private static final int HEIGHT = 5; + private static final int DEPTH = 7; +- private final boolean leftChild; +- private final boolean rightChild; ++ private boolean hasPlacedChest; + +- public Straight(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { +- super(StructurePieceType.STRONGHOLD_STRAIGHT, genDepth, box); ++ public ChestCorridor(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_CHEST_CORRIDOR, genDepth, box); + this.setOrientation(orientation); + this.entryDoor = this.randomSmallDoor(random); +- this.leftChild = random.nextInt(2) == 0; +- this.rightChild = random.nextInt(2) == 0; + } + +- public Straight(CompoundTag tag) { +- super(StructurePieceType.STRONGHOLD_STRAIGHT, tag); +- this.leftChild = tag.getBoolean("Left"); +- this.rightChild = tag.getBoolean("Right"); ++ public ChestCorridor(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_CHEST_CORRIDOR, tag); ++ this.hasPlacedChest = tag.getBoolean("Chest"); + } + + @Override + protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { + super.addAdditionalSaveData(context, tag); +- tag.putBoolean("Left", this.leftChild); +- tag.putBoolean("Right", this.rightChild); ++ tag.putBoolean("Chest", this.hasPlacedChest); + } + + @Override + public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- this.generateSmallDoorChildForward((StrongholdPieces.StartPiece)piece, pieces, random, 1, 1); +- if (this.leftChild) { +- this.generateSmallDoorChildLeft((StrongholdPieces.StartPiece)piece, pieces, random, 1, 2); +- } +- +- if (this.rightChild) { +- this.generateSmallDoorChildRight((StrongholdPieces.StartPiece)piece, pieces, random, 1, 2); +- } ++ this.generateSmallDoorChildForward((StrongholdPieces.StartPiece) piece, pieces, random, 1, 1); + } + +- public static StrongholdPieces.Straight createPiece( +- StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction direction, int genDepth +- ) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, 7, direction); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new StrongholdPieces.Straight(genDepth, random, boundingBox, direction) +- : null; ++ public static StrongholdPieces.ChestCorridor createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, 7, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new StrongholdPieces.ChestCorridor(genDepth, random, structureboundingbox, orientation) : null; + } + + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { + this.generateBox(level, box, 0, 0, 0, 4, 4, 6, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); + this.generateSmallDoor(level, random, box, this.entryDoor, 1, 1, 0); +- this.generateSmallDoor(level, random, box, StrongholdPieces.StrongholdPiece.SmallDoorType.OPENING, 1, 1, 6); +- BlockState blockState = Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.EAST); +- BlockState blockState1 = Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.WEST); +- this.maybeGenerateBlock(level, box, random, 0.1F, 1, 2, 1, blockState); +- this.maybeGenerateBlock(level, box, random, 0.1F, 3, 2, 1, blockState1); +- this.maybeGenerateBlock(level, box, random, 0.1F, 1, 2, 5, blockState); +- this.maybeGenerateBlock(level, box, random, 0.1F, 3, 2, 5, blockState1); +- if (this.leftChild) { +- this.generateBox(level, box, 0, 1, 2, 0, 3, 4, CAVE_AIR, CAVE_AIR, false); ++ this.generateSmallDoor(level, random, box, StrongholdPieces.StrongholdPiece.a.OPENING, 1, 1, 6); ++ this.generateBox(level, box, 3, 1, 2, 3, 1, 4, Blocks.STONE_BRICKS.defaultBlockState(), Blocks.STONE_BRICKS.defaultBlockState(), false); ++ this.placeBlock(level, Blocks.STONE_BRICK_SLAB.defaultBlockState(), 3, 1, 1, box); ++ this.placeBlock(level, Blocks.STONE_BRICK_SLAB.defaultBlockState(), 3, 1, 5, box); ++ this.placeBlock(level, Blocks.STONE_BRICK_SLAB.defaultBlockState(), 3, 2, 2, box); ++ this.placeBlock(level, Blocks.STONE_BRICK_SLAB.defaultBlockState(), 3, 2, 4, box); ++ ++ for (int i = 2; i <= 4; ++i) { ++ this.placeBlock(level, Blocks.STONE_BRICK_SLAB.defaultBlockState(), 2, 1, i, box); + } + +- if (this.rightChild) { +- this.generateBox(level, box, 4, 1, 2, 4, 3, 4, CAVE_AIR, CAVE_AIR, false); ++ if (!this.hasPlacedChest && box.isInside(this.getWorldPos(3, 2, 3))) { ++ this.hasPlacedChest = true; ++ this.createChest(level, box, random, 3, 2, 3, BuiltInLootTables.STRONGHOLD_CORRIDOR); + } ++ + } + } + +- public static class StraightStairsDown extends StrongholdPieces.StrongholdPiece { +- private static final int WIDTH = 5; +- private static final int HEIGHT = 11; +- private static final int DEPTH = 8; ++ public static class Library extends StrongholdPieces.StrongholdPiece { + +- public StraightStairsDown(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { +- super(StructurePieceType.STRONGHOLD_STRAIGHT_STAIRS_DOWN, genDepth, box); ++ protected static final int WIDTH = 14; ++ protected static final int HEIGHT = 6; ++ protected static final int TALL_HEIGHT = 11; ++ protected static final int DEPTH = 15; ++ private final boolean isTall; ++ ++ public Library(int genDepth, RandomSource random, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_LIBRARY, genDepth, box); + this.setOrientation(orientation); + this.entryDoor = this.randomSmallDoor(random); ++ this.isTall = box.getYSpan() > 6; + } + +- public StraightStairsDown(CompoundTag tag) { +- super(StructurePieceType.STRONGHOLD_STRAIGHT_STAIRS_DOWN, tag); ++ public Library(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_LIBRARY, tag); ++ this.isTall = tag.getBoolean("Tall"); + } + + @Override ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putBoolean("Tall", this.isTall); ++ } ++ ++ public static StrongholdPieces.Library createPiece(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -4, -1, 0, 14, 11, 15, orientation); ++ ++ if (!isOkBox(structureboundingbox) || pieces.findCollisionPiece(structureboundingbox) != null) { ++ structureboundingbox = BoundingBox.orientBox(x, y, z, -4, -1, 0, 14, 6, 15, orientation); ++ if (!isOkBox(structureboundingbox) || pieces.findCollisionPiece(structureboundingbox) != null) { ++ return null; ++ } ++ } ++ ++ return new StrongholdPieces.Library(genDepth, random, structureboundingbox, orientation); ++ } ++ ++ @Override ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ byte b0 = 11; ++ ++ if (!this.isTall) { ++ b0 = 6; ++ } ++ ++ this.generateBox(level, box, 0, 0, 0, 13, b0 - 1, 14, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateSmallDoor(level, random, box, this.entryDoor, 4, 1, 0); ++ this.generateMaybeBox(level, box, random, 0.07F, 2, 1, 1, 11, 4, 13, Blocks.COBWEB.defaultBlockState(), Blocks.COBWEB.defaultBlockState(), false, false); ++ boolean flag = true; ++ boolean flag1 = true; ++ ++ int i; ++ ++ for (i = 1; i <= 13; ++i) { ++ if ((i - 1) % 4 == 0) { ++ this.generateBox(level, box, 1, 1, i, 1, 4, i, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); ++ this.generateBox(level, box, 12, 1, i, 12, 4, i, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); ++ this.placeBlock(level, (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.EAST), 2, 3, i, box); ++ this.placeBlock(level, (IBlockData) Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, Direction.WEST), 11, 3, i, box); ++ if (this.isTall) { ++ this.generateBox(level, box, 1, 6, i, 1, 9, i, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); ++ this.generateBox(level, box, 12, 6, i, 12, 9, i, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); ++ } ++ } else { ++ this.generateBox(level, box, 1, 1, i, 1, 4, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); ++ this.generateBox(level, box, 12, 1, i, 12, 4, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); ++ if (this.isTall) { ++ this.generateBox(level, box, 1, 6, i, 1, 9, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); ++ this.generateBox(level, box, 12, 6, i, 12, 9, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); ++ } ++ } ++ } ++ ++ for (i = 3; i < 12; i += 2) { ++ this.generateBox(level, box, 3, 1, i, 4, 3, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); ++ this.generateBox(level, box, 6, 1, i, 7, 3, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); ++ this.generateBox(level, box, 9, 1, i, 10, 3, i, Blocks.BOOKSHELF.defaultBlockState(), Blocks.BOOKSHELF.defaultBlockState(), false); ++ } ++ ++ if (this.isTall) { ++ this.generateBox(level, box, 1, 5, 1, 3, 5, 13, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); ++ this.generateBox(level, box, 10, 5, 1, 12, 5, 13, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 5, 1, 9, 5, 2, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); ++ this.generateBox(level, box, 4, 5, 12, 9, 5, 13, Blocks.OAK_PLANKS.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState(), false); ++ this.placeBlock(level, Blocks.OAK_PLANKS.defaultBlockState(), 9, 5, 11, box); ++ this.placeBlock(level, Blocks.OAK_PLANKS.defaultBlockState(), 8, 5, 11, box); ++ this.placeBlock(level, Blocks.OAK_PLANKS.defaultBlockState(), 9, 5, 10, box); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.SOUTH, true); ++ ++ this.generateBox(level, box, 3, 6, 3, 3, 6, 11, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 10, 6, 3, 10, 6, 9, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 4, 6, 2, 9, 6, 2, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 4, 6, 12, 7, 6, 12, iblockdata, iblockdata, false); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.EAST, true), 3, 6, 2, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.SOUTH, true)).setValue(FenceBlock.EAST, true), 3, 6, 12, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.WEST, true), 10, 6, 2, box); ++ ++ for (int j = 0; j <= 2; ++j) { ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.SOUTH, true)).setValue(FenceBlock.WEST, true), 8 + j, 6, 12 - j, box); ++ if (j != 2) { ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.NORTH, true)).setValue(FenceBlock.EAST, true), 8 + j, 6, 11 - j, box); ++ } ++ } ++ ++ IBlockData iblockdata2 = (IBlockData) Blocks.LADDER.defaultBlockState().setValue(LadderBlock.FACING, Direction.SOUTH); ++ ++ this.placeBlock(level, iblockdata2, 10, 1, 13, box); ++ this.placeBlock(level, iblockdata2, 10, 2, 13, box); ++ this.placeBlock(level, iblockdata2, 10, 3, 13, box); ++ this.placeBlock(level, iblockdata2, 10, 4, 13, box); ++ this.placeBlock(level, iblockdata2, 10, 5, 13, box); ++ this.placeBlock(level, iblockdata2, 10, 6, 13, box); ++ this.placeBlock(level, iblockdata2, 10, 7, 13, box); ++ boolean flag2 = true; ++ boolean flag3 = true; ++ IBlockData iblockdata3 = (IBlockData) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.EAST, true); ++ ++ this.placeBlock(level, iblockdata3, 6, 9, 7, box); ++ IBlockData iblockdata4 = (IBlockData) Blocks.OAK_FENCE.defaultBlockState().setValue(FenceBlock.WEST, true); ++ ++ this.placeBlock(level, iblockdata4, 7, 9, 7, box); ++ this.placeBlock(level, iblockdata3, 6, 8, 7, box); ++ this.placeBlock(level, iblockdata4, 7, 8, 7, box); ++ IBlockData iblockdata5 = (IBlockData) ((IBlockData) iblockdata1.setValue(FenceBlock.WEST, true)).setValue(FenceBlock.EAST, true); ++ ++ this.placeBlock(level, iblockdata5, 6, 7, 7, box); ++ this.placeBlock(level, iblockdata5, 7, 7, 7, box); ++ this.placeBlock(level, iblockdata3, 5, 7, 7, box); ++ this.placeBlock(level, iblockdata4, 8, 7, 7, box); ++ this.placeBlock(level, (IBlockData) iblockdata3.setValue(FenceBlock.NORTH, true), 6, 7, 6, box); ++ this.placeBlock(level, (IBlockData) iblockdata3.setValue(FenceBlock.SOUTH, true), 6, 7, 8, box); ++ this.placeBlock(level, (IBlockData) iblockdata4.setValue(FenceBlock.NORTH, true), 7, 7, 6, box); ++ this.placeBlock(level, (IBlockData) iblockdata4.setValue(FenceBlock.SOUTH, true), 7, 7, 8, box); ++ IBlockData iblockdata6 = Blocks.TORCH.defaultBlockState(); ++ ++ this.placeBlock(level, iblockdata6, 5, 8, 7, box); ++ this.placeBlock(level, iblockdata6, 8, 8, 7, box); ++ this.placeBlock(level, iblockdata6, 6, 8, 6, box); ++ this.placeBlock(level, iblockdata6, 6, 8, 8, box); ++ this.placeBlock(level, iblockdata6, 7, 8, 6, box); ++ this.placeBlock(level, iblockdata6, 7, 8, 8, box); ++ } ++ ++ this.createChest(level, box, random, 3, 3, 5, BuiltInLootTables.STRONGHOLD_LIBRARY); ++ if (this.isTall) { ++ this.placeBlock(level, StrongholdPieces.Library.CAVE_AIR, 12, 9, 1, box); ++ this.createChest(level, box, random, 12, 8, 1, BuiltInLootTables.STRONGHOLD_LIBRARY); ++ } ++ ++ } ++ } ++ ++ public static class PortalRoom extends StrongholdPieces.StrongholdPiece { ++ ++ protected static final int WIDTH = 11; ++ protected static final int HEIGHT = 8; ++ protected static final int DEPTH = 16; ++ private boolean hasPlacedSpawner; ++ ++ public PortalRoom(int genDepth, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_PORTAL_ROOM, genDepth, box); ++ this.setOrientation(orientation); ++ } ++ ++ public PortalRoom(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_PORTAL_ROOM, tag); ++ this.hasPlacedSpawner = tag.getBoolean("Mob"); ++ } ++ ++ @Override ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putBoolean("Mob", this.hasPlacedSpawner); ++ } ++ ++ @Override + public void addChildren(StructurePiece piece, StructurePieceAccessor pieces, RandomSource random) { +- this.generateSmallDoorChildForward((StrongholdPieces.StartPiece)piece, pieces, random, 1, 1); ++ if (piece != null) { ++ ((StrongholdPieces.StartPiece) piece).portalRoomPiece = this; ++ } ++ + } + +- public static StrongholdPieces.StraightStairsDown createPiece( +- StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation, int genDepth +- ) { +- BoundingBox boundingBox = BoundingBox.orientBox(x, y, z, -1, -7, 0, 5, 11, 8, orientation); +- return isOkBox(boundingBox) && pieces.findCollisionPiece(boundingBox) == null +- ? new StrongholdPieces.StraightStairsDown(genDepth, random, boundingBox, orientation) +- : null; ++ public static StrongholdPieces.PortalRoom createPiece(StructurePieceAccessor pieces, int x, int y, int z, Direction orientation, int genDepth) { ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -4, -1, 0, 11, 8, 16, orientation); ++ ++ return isOkBox(structureboundingbox) && pieces.findCollisionPiece(structureboundingbox) == null ? new StrongholdPieces.PortalRoom(genDepth, structureboundingbox, orientation) : null; + } + + @Override +- public void postProcess( +- WorldGenLevel level, +- StructureManager structureManager, +- ChunkGenerator generator, +- RandomSource random, +- BoundingBox box, +- ChunkPos chunkPos, +- BlockPos pos +- ) { +- this.generateBox(level, box, 0, 0, 0, 4, 10, 7, true, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); +- this.generateSmallDoor(level, random, box, this.entryDoor, 1, 7, 0); +- this.generateSmallDoor(level, random, box, StrongholdPieces.StrongholdPiece.SmallDoorType.OPENING, 1, 1, 7); +- BlockState blockState = Blocks.COBBLESTONE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.SOUTH); ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ this.generateBox(level, box, 0, 0, 0, 10, 7, 15, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateSmallDoor(level, random, box, StrongholdPieces.StrongholdPiece.a.GRATES, 4, 1, 0); ++ boolean flag = true; + +- for (int i = 0; i < 6; i++) { +- this.placeBlock(level, blockState, 1, 6 - i, 1 + i, box); +- this.placeBlock(level, blockState, 2, 6 - i, 1 + i, box); +- this.placeBlock(level, blockState, 3, 6 - i, 1 + i, box); +- if (i < 5) { +- this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 1, 5 - i, 1 + i, box); +- this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 2, 5 - i, 1 + i, box); +- this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 3, 5 - i, 1 + i, box); ++ this.generateBox(level, box, 1, 6, 1, 1, 6, 14, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 9, 6, 1, 9, 6, 14, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 2, 6, 1, 8, 6, 2, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 2, 6, 14, 8, 6, 14, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 1, 1, 1, 2, 1, 4, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 8, 1, 1, 9, 1, 4, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 1, 1, 1, 1, 1, 3, Blocks.LAVA.defaultBlockState(), Blocks.LAVA.defaultBlockState(), false); ++ this.generateBox(level, box, 9, 1, 1, 9, 1, 3, Blocks.LAVA.defaultBlockState(), Blocks.LAVA.defaultBlockState(), false); ++ this.generateBox(level, box, 3, 1, 8, 7, 1, 12, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 4, 1, 9, 6, 1, 11, Blocks.LAVA.defaultBlockState(), Blocks.LAVA.defaultBlockState(), false); ++ IBlockData iblockdata = (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.NORTH, true)).setValue(IronBarsBlock.SOUTH, true); ++ IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, true)).setValue(IronBarsBlock.EAST, true); ++ ++ int i; ++ ++ for (i = 3; i < 14; i += 2) { ++ this.generateBox(level, box, 0, 3, i, 0, 4, i, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 10, 3, i, 10, 4, i, iblockdata, iblockdata, false); ++ } ++ ++ for (i = 2; i < 9; i += 2) { ++ this.generateBox(level, box, i, 3, 15, i, 4, 15, iblockdata1, iblockdata1, false); ++ } ++ ++ IBlockData iblockdata2 = (IBlockData) Blocks.STONE_BRICK_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.NORTH); ++ ++ this.generateBox(level, box, 4, 1, 5, 6, 1, 7, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 4, 2, 6, 6, 2, 7, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ this.generateBox(level, box, 4, 3, 7, 6, 3, 7, false, random, StrongholdPieces.SMOOTH_STONE_SELECTOR); ++ ++ for (int j = 4; j <= 6; ++j) { ++ this.placeBlock(level, iblockdata2, j, 1, 4, box); ++ this.placeBlock(level, iblockdata2, j, 2, 5, box); ++ this.placeBlock(level, iblockdata2, j, 3, 6, box); ++ } ++ ++ IBlockData iblockdata3 = (IBlockData) Blocks.END_PORTAL_FRAME.defaultBlockState().setValue(EndPortalFrameBlock.FACING, Direction.NORTH); ++ IBlockData iblockdata4 = (IBlockData) Blocks.END_PORTAL_FRAME.defaultBlockState().setValue(EndPortalFrameBlock.FACING, Direction.SOUTH); ++ IBlockData iblockdata5 = (IBlockData) Blocks.END_PORTAL_FRAME.defaultBlockState().setValue(EndPortalFrameBlock.FACING, Direction.EAST); ++ IBlockData iblockdata6 = (IBlockData) Blocks.END_PORTAL_FRAME.defaultBlockState().setValue(EndPortalFrameBlock.FACING, Direction.WEST); ++ boolean flag1 = true; ++ boolean[] aboolean = new boolean[12]; ++ ++ for (int k = 0; k < aboolean.length; ++k) { ++ aboolean[k] = random.nextFloat() > 0.9F; ++ flag1 &= aboolean[k]; ++ } ++ ++ this.placeBlock(level, (IBlockData) iblockdata3.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[0]), 4, 3, 8, box); ++ this.placeBlock(level, (IBlockData) iblockdata3.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[1]), 5, 3, 8, box); ++ this.placeBlock(level, (IBlockData) iblockdata3.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[2]), 6, 3, 8, box); ++ this.placeBlock(level, (IBlockData) iblockdata4.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[3]), 4, 3, 12, box); ++ this.placeBlock(level, (IBlockData) iblockdata4.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[4]), 5, 3, 12, box); ++ this.placeBlock(level, (IBlockData) iblockdata4.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[5]), 6, 3, 12, box); ++ this.placeBlock(level, (IBlockData) iblockdata5.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[6]), 3, 3, 9, box); ++ this.placeBlock(level, (IBlockData) iblockdata5.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[7]), 3, 3, 10, box); ++ this.placeBlock(level, (IBlockData) iblockdata5.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[8]), 3, 3, 11, box); ++ this.placeBlock(level, (IBlockData) iblockdata6.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[9]), 7, 3, 9, box); ++ this.placeBlock(level, (IBlockData) iblockdata6.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[10]), 7, 3, 10, box); ++ this.placeBlock(level, (IBlockData) iblockdata6.setValue(EndPortalFrameBlock.HAS_EYE, aboolean[11]), 7, 3, 11, box); ++ if (flag1) { ++ IBlockData iblockdata7 = Blocks.END_PORTAL.defaultBlockState(); ++ ++ this.placeBlock(level, iblockdata7, 4, 3, 9, box); ++ this.placeBlock(level, iblockdata7, 5, 3, 9, box); ++ this.placeBlock(level, iblockdata7, 6, 3, 9, box); ++ this.placeBlock(level, iblockdata7, 4, 3, 10, box); ++ this.placeBlock(level, iblockdata7, 5, 3, 10, box); ++ this.placeBlock(level, iblockdata7, 6, 3, 10, box); ++ this.placeBlock(level, iblockdata7, 4, 3, 11, box); ++ this.placeBlock(level, iblockdata7, 5, 3, 11, box); ++ this.placeBlock(level, iblockdata7, 6, 3, 11, box); ++ } ++ ++ if (!this.hasPlacedSpawner) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(5, 3, 6); ++ ++ if (box.isInside(blockposition_mutableblockposition)) { ++ this.hasPlacedSpawner = true; ++ // CraftBukkit start ++ /* ++ generatoraccessseed.setBlock(blockposition_mutableblockposition, Blocks.SPAWNER.defaultBlockState(), 2); ++ TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); ++ ++ if (tileentity instanceof TileEntityMobSpawner) { ++ TileEntityMobSpawner tileentitymobspawner = (TileEntityMobSpawner) tileentity; ++ ++ tileentitymobspawner.setEntityId(EntityTypes.SILVERFISH, randomsource); ++ } ++ */ ++ placeCraftSpawner(level, blockposition_mutableblockposition, org.bukkit.entity.EntityType.SILVERFISH, 2); ++ // CraftBukkit end + } + } ++ + } + } + +- abstract static class StrongholdPiece extends StructurePiece { +- protected StrongholdPieces.StrongholdPiece.SmallDoorType entryDoor = StrongholdPieces.StrongholdPiece.SmallDoorType.OPENING; ++ private abstract static class StrongholdPiece extends StructurePiece { + ++ protected StrongholdPieces.StrongholdPiece.a entryDoor; ++ + protected StrongholdPiece(StructurePieceType type, int genDepth, BoundingBox boundingBox) { + super(type, genDepth, boundingBox); ++ this.entryDoor = StrongholdPieces.StrongholdPiece.a.OPENING; + } + + public StrongholdPiece(StructurePieceType type, CompoundTag tag) { + super(type, tag); +- this.entryDoor = StrongholdPieces.StrongholdPiece.SmallDoorType.valueOf(tag.getString("EntryDoor")); ++ this.entryDoor = StrongholdPieces.StrongholdPiece.a.OPENING; ++ this.entryDoor = StrongholdPieces.StrongholdPiece.a.valueOf(tag.getString("EntryDoor")); + } + + @Override +@@ -1490,12 +1172,10 @@ + tag.putString("EntryDoor", this.entryDoor.name()); + } + +- protected void generateSmallDoor( +- WorldGenLevel level, RandomSource random, BoundingBox box, StrongholdPieces.StrongholdPiece.SmallDoorType type, int x, int y, int z +- ) { ++ protected void generateSmallDoor(WorldGenLevel level, RandomSource random, BoundingBox box, StrongholdPieces.StrongholdPiece.a type, int x, int y, int z) { + switch (type) { + case OPENING: +- this.generateBox(level, box, x, y, z, x + 3 - 1, y + 3 - 1, z, CAVE_AIR, CAVE_AIR, false); ++ this.generateBox(level, box, x, y, z, x + 3 - 1, y + 3 - 1, z, StrongholdPieces.StrongholdPiece.CAVE_AIR, StrongholdPieces.StrongholdPiece.CAVE_AIR, false); + break; + case WOOD_DOOR: + this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), x, y, z, box); +@@ -1506,48 +1186,18 @@ + this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), x + 2, y + 1, z, box); + this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), x + 2, y, z, box); + this.placeBlock(level, Blocks.OAK_DOOR.defaultBlockState(), x + 1, y, z, box); +- this.placeBlock(level, Blocks.OAK_DOOR.defaultBlockState().setValue(DoorBlock.HALF, DoubleBlockHalf.UPPER), x + 1, y + 1, z, box); ++ this.placeBlock(level, (IBlockData) Blocks.OAK_DOOR.defaultBlockState().setValue(DoorBlock.HALF, BlockPropertyDoubleBlockHalf.UPPER), x + 1, y + 1, z, box); + break; + case GRATES: + this.placeBlock(level, Blocks.CAVE_AIR.defaultBlockState(), x + 1, y, z, box); + this.placeBlock(level, Blocks.CAVE_AIR.defaultBlockState(), x + 1, y + 1, z, box); +- this.placeBlock(level, Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, Boolean.valueOf(true)), x, y, z, box); +- this.placeBlock(level, Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, Boolean.valueOf(true)), x, y + 1, z, box); +- this.placeBlock( +- level, +- Blocks.IRON_BARS +- .defaultBlockState() +- .setValue(IronBarsBlock.EAST, Boolean.valueOf(true)) +- .setValue(IronBarsBlock.WEST, Boolean.valueOf(true)), +- x, +- y + 2, +- z, +- box +- ); +- this.placeBlock( +- level, +- Blocks.IRON_BARS +- .defaultBlockState() +- .setValue(IronBarsBlock.EAST, Boolean.valueOf(true)) +- .setValue(IronBarsBlock.WEST, Boolean.valueOf(true)), +- x + 1, +- y + 2, +- z, +- box +- ); +- this.placeBlock( +- level, +- Blocks.IRON_BARS +- .defaultBlockState() +- .setValue(IronBarsBlock.EAST, Boolean.valueOf(true)) +- .setValue(IronBarsBlock.WEST, Boolean.valueOf(true)), +- x + 2, +- y + 2, +- z, +- box +- ); +- this.placeBlock(level, Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.EAST, Boolean.valueOf(true)), x + 2, y + 1, z, box); +- this.placeBlock(level, Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.EAST, Boolean.valueOf(true)), x + 2, y, z, box); ++ this.placeBlock(level, (IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, true), x, y, z, box); ++ this.placeBlock(level, (IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.WEST, true), x, y + 1, z, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.EAST, true)).setValue(IronBarsBlock.WEST, true), x, y + 2, z, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.EAST, true)).setValue(IronBarsBlock.WEST, true), x + 1, y + 2, z, box); ++ this.placeBlock(level, (IBlockData) ((IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.EAST, true)).setValue(IronBarsBlock.WEST, true), x + 2, y + 2, z, box); ++ this.placeBlock(level, (IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.EAST, true), x + 2, y + 1, z, box); ++ this.placeBlock(level, (IBlockData) Blocks.IRON_BARS.defaultBlockState().setValue(IronBarsBlock.EAST, true), x + 2, y, z, box); + break; + case IRON_DOOR: + this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), x, y, z, box); +@@ -1558,79 +1208,44 @@ + this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), x + 2, y + 1, z, box); + this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), x + 2, y, z, box); + this.placeBlock(level, Blocks.IRON_DOOR.defaultBlockState(), x + 1, y, z, box); +- this.placeBlock(level, Blocks.IRON_DOOR.defaultBlockState().setValue(DoorBlock.HALF, DoubleBlockHalf.UPPER), x + 1, y + 1, z, box); +- this.placeBlock(level, Blocks.STONE_BUTTON.defaultBlockState().setValue(ButtonBlock.FACING, Direction.NORTH), x + 2, y + 1, z + 1, box); +- this.placeBlock(level, Blocks.STONE_BUTTON.defaultBlockState().setValue(ButtonBlock.FACING, Direction.SOUTH), x + 2, y + 1, z - 1, box); ++ this.placeBlock(level, (IBlockData) Blocks.IRON_DOOR.defaultBlockState().setValue(DoorBlock.HALF, BlockPropertyDoubleBlockHalf.UPPER), x + 1, y + 1, z, box); ++ this.placeBlock(level, (IBlockData) Blocks.STONE_BUTTON.defaultBlockState().setValue(ButtonBlock.FACING, Direction.NORTH), x + 2, y + 1, z + 1, box); ++ this.placeBlock(level, (IBlockData) Blocks.STONE_BUTTON.defaultBlockState().setValue(ButtonBlock.FACING, Direction.SOUTH), x + 2, y + 1, z - 1, box); + } ++ + } + +- protected StrongholdPieces.StrongholdPiece.SmallDoorType randomSmallDoor(RandomSource random) { +- int randomInt = random.nextInt(5); +- switch (randomInt) { ++ protected StrongholdPieces.StrongholdPiece.a randomSmallDoor(RandomSource random) { ++ int i = random.nextInt(5); ++ ++ switch (i) { + case 0: + case 1: + default: +- return StrongholdPieces.StrongholdPiece.SmallDoorType.OPENING; ++ return StrongholdPieces.StrongholdPiece.a.OPENING; + case 2: +- return StrongholdPieces.StrongholdPiece.SmallDoorType.WOOD_DOOR; ++ return StrongholdPieces.StrongholdPiece.a.WOOD_DOOR; + case 3: +- return StrongholdPieces.StrongholdPiece.SmallDoorType.GRATES; ++ return StrongholdPieces.StrongholdPiece.a.GRATES; + case 4: +- return StrongholdPieces.StrongholdPiece.SmallDoorType.IRON_DOOR; ++ return StrongholdPieces.StrongholdPiece.a.IRON_DOOR; + } + } + + @Nullable +- protected StructurePiece generateSmallDoorChildForward( +- StrongholdPieces.StartPiece startPiece, StructurePieceAccessor pieces, RandomSource random, int offsetX, int offsetY +- ) { +- Direction orientation = this.getOrientation(); +- if (orientation != null) { +- switch (orientation) { ++ protected StructurePiece generateSmallDoorChildForward(StrongholdPieces.StartPiece startPiece, StructurePieceAccessor pieces, RandomSource random, int offsetX, int offsetY) { ++ Direction enumdirection = this.getOrientation(); ++ ++ if (enumdirection != null) { ++ switch (enumdirection) { + case NORTH: +- return StrongholdPieces.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.minX() + offsetX, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.minZ() - 1, +- orientation, +- this.getGenDepth() +- ); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() - 1, enumdirection, this.getGenDepth()); + case SOUTH: +- return StrongholdPieces.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.minX() + offsetX, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.maxZ() + 1, +- orientation, +- this.getGenDepth() +- ); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.maxZ() + 1, enumdirection, this.getGenDepth()); + case WEST: +- return StrongholdPieces.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.minX() - 1, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.minZ() + offsetX, +- orientation, +- this.getGenDepth() +- ); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, enumdirection, this.getGenDepth()); + case EAST: +- return StrongholdPieces.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.maxX() + 1, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.minZ() + offsetX, +- orientation, +- this.getGenDepth() +- ); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, enumdirection, this.getGenDepth()); + } + } + +@@ -1638,56 +1253,19 @@ + } + + @Nullable +- protected StructurePiece generateSmallDoorChildLeft( +- StrongholdPieces.StartPiece startPiece, StructurePieceAccessor pieces, RandomSource random, int offsetY, int offsetX +- ) { +- Direction orientation = this.getOrientation(); +- if (orientation != null) { +- switch (orientation) { ++ protected StructurePiece generateSmallDoorChildLeft(StrongholdPieces.StartPiece startPiece, StructurePieceAccessor pieces, RandomSource random, int offsetY, int offsetX) { ++ Direction enumdirection = this.getOrientation(); ++ ++ if (enumdirection != null) { ++ switch (enumdirection) { + case NORTH: +- return StrongholdPieces.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.minX() - 1, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.minZ() + offsetX, +- Direction.WEST, +- this.getGenDepth() +- ); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, Direction.WEST, this.getGenDepth()); + case SOUTH: +- return StrongholdPieces.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.minX() - 1, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.minZ() + offsetX, +- Direction.WEST, +- this.getGenDepth() +- ); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() - 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, Direction.WEST, this.getGenDepth()); + case WEST: +- return StrongholdPieces.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.minX() + offsetX, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.minZ() - 1, +- Direction.NORTH, +- this.getGenDepth() +- ); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() - 1, Direction.NORTH, this.getGenDepth()); + case EAST: +- return StrongholdPieces.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.minX() + offsetX, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.minZ() - 1, +- Direction.NORTH, +- this.getGenDepth() +- ); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() - 1, Direction.NORTH, this.getGenDepth()); + } + } + +@@ -1695,56 +1273,19 @@ + } + + @Nullable +- protected StructurePiece generateSmallDoorChildRight( +- StrongholdPieces.StartPiece startPiece, StructurePieceAccessor pieces, RandomSource random, int offsetY, int offsetX +- ) { +- Direction orientation = this.getOrientation(); +- if (orientation != null) { +- switch (orientation) { ++ protected StructurePiece generateSmallDoorChildRight(StrongholdPieces.StartPiece startPiece, StructurePieceAccessor pieces, RandomSource random, int offsetY, int offsetX) { ++ Direction enumdirection = this.getOrientation(); ++ ++ if (enumdirection != null) { ++ switch (enumdirection) { + case NORTH: +- return StrongholdPieces.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.maxX() + 1, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.minZ() + offsetX, +- Direction.EAST, +- this.getGenDepth() +- ); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, Direction.EAST, this.getGenDepth()); + case SOUTH: +- return StrongholdPieces.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.maxX() + 1, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.minZ() + offsetX, +- Direction.EAST, +- this.getGenDepth() +- ); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.maxX() + 1, this.boundingBox.minY() + offsetY, this.boundingBox.minZ() + offsetX, Direction.EAST, this.getGenDepth()); + case WEST: +- return StrongholdPieces.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.minX() + offsetX, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.maxZ() + 1, +- Direction.SOUTH, +- this.getGenDepth() +- ); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.maxZ() + 1, Direction.SOUTH, this.getGenDepth()); + case EAST: +- return StrongholdPieces.generateAndAddPiece( +- startPiece, +- pieces, +- random, +- this.boundingBox.minX() + offsetX, +- this.boundingBox.minY() + offsetY, +- this.boundingBox.maxZ() + 1, +- Direction.SOUTH, +- this.getGenDepth() +- ); ++ return StrongholdPieces.generateAndAddPiece(startPiece, pieces, random, this.boundingBox.minX() + offsetX, this.boundingBox.minY() + offsetY, this.boundingBox.maxZ() + 1, Direction.SOUTH, this.getGenDepth()); + } + } + +@@ -1755,24 +1296,140 @@ + return box != null && box.minY() > 10; + } + +- protected static enum SmallDoorType { +- OPENING, +- WOOD_DOOR, +- GRATES, +- IRON_DOOR; ++ protected static enum a { ++ ++ OPENING, WOOD_DOOR, GRATES, IRON_DOOR; ++ ++ private a() {} + } + } + +- public abstract static class Turn extends StrongholdPieces.StrongholdPiece { ++ public static class StartPiece extends StrongholdPieces.StairsDown { ++ ++ public StrongholdPieces.PieceWeight previousPiece; ++ @Nullable ++ public StrongholdPieces.PortalRoom portalRoomPiece; ++ public final List pendingChildren = Lists.newArrayList(); ++ ++ public StartPiece(RandomSource random, int x, int z) { ++ super(StructurePieceType.STRONGHOLD_START, 0, x, z, getRandomHorizontalDirection(random)); ++ } ++ ++ public StartPiece(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_START, tag); ++ } ++ ++ @Override ++ public BlockPos getLocatorPosition() { ++ return this.portalRoomPiece != null ? this.portalRoomPiece.getLocatorPosition() : super.getLocatorPosition(); ++ } ++ } ++ ++ public static class FillerCorridor extends StrongholdPieces.StrongholdPiece { ++ ++ private final int steps; ++ ++ public FillerCorridor(int genDepth, BoundingBox box, Direction orientation) { ++ super(StructurePieceType.STRONGHOLD_FILLER_CORRIDOR, genDepth, box); ++ this.setOrientation(orientation); ++ this.steps = orientation != Direction.NORTH && orientation != Direction.SOUTH ? box.getXSpan() : box.getZSpan(); ++ } ++ ++ public FillerCorridor(CompoundTag tag) { ++ super(StructurePieceType.STRONGHOLD_FILLER_CORRIDOR, tag); ++ this.steps = tag.getInt("Steps"); ++ } ++ ++ @Override ++ protected void addAdditionalSaveData(StructurePieceSerializationContext context, CompoundTag tag) { ++ super.addAdditionalSaveData(context, tag); ++ tag.putInt("Steps", this.steps); ++ } ++ ++ public static BoundingBox findPieceBox(StructurePieceAccessor pieces, RandomSource random, int x, int y, int z, Direction orientation) { ++ boolean flag = true; ++ BoundingBox structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, 4, orientation); ++ StructurePiece structurepiece = pieces.findCollisionPiece(structureboundingbox); ++ ++ if (structurepiece == null) { ++ return null; ++ } else { ++ if (structurepiece.getBoundingBox().minY() == structureboundingbox.minY()) { ++ for (int l = 2; l >= 1; --l) { ++ structureboundingbox = BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, l, orientation); ++ if (!structurepiece.getBoundingBox().intersects(structureboundingbox)) { ++ return BoundingBox.orientBox(x, y, z, -1, -1, 0, 5, 5, l + 1, orientation); ++ } ++ } ++ } ++ ++ return null; ++ } ++ } ++ ++ @Override ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { ++ for (int i = 0; i < this.steps; ++i) { ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 0, 0, i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 1, 0, i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 2, 0, i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 3, 0, i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 4, 0, i, box); ++ ++ for (int j = 1; j <= 3; ++j) { ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 0, j, i, box); ++ this.placeBlock(level, Blocks.CAVE_AIR.defaultBlockState(), 1, j, i, box); ++ this.placeBlock(level, Blocks.CAVE_AIR.defaultBlockState(), 2, j, i, box); ++ this.placeBlock(level, Blocks.CAVE_AIR.defaultBlockState(), 3, j, i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 4, j, i, box); ++ } ++ ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 0, 4, i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 1, 4, i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 2, 4, i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 3, 4, i, box); ++ this.placeBlock(level, Blocks.STONE_BRICKS.defaultBlockState(), 4, 4, i, box); ++ } ++ ++ } ++ } ++ ++ private static class k extends StructurePiece.BlockSelector { ++ ++ k() {} ++ ++ @Override ++ public void next(RandomSource random, int x, int y, int z, boolean wall) { ++ if (wall) { ++ float f = random.nextFloat(); ++ ++ if (f < 0.2F) { ++ this.next = Blocks.CRACKED_STONE_BRICKS.defaultBlockState(); ++ } else if (f < 0.5F) { ++ this.next = Blocks.MOSSY_STONE_BRICKS.defaultBlockState(); ++ } else if (f < 0.55F) { ++ this.next = Blocks.INFESTED_STONE_BRICKS.defaultBlockState(); ++ } else { ++ this.next = Blocks.STONE_BRICKS.defaultBlockState(); ++ } ++ } else { ++ this.next = Blocks.CAVE_AIR.defaultBlockState(); ++ } ++ ++ } ++ } ++ ++ public abstract static class q extends StrongholdPieces.StrongholdPiece { ++ + protected static final int WIDTH = 5; + protected static final int HEIGHT = 5; + protected static final int DEPTH = 5; + +- protected Turn(StructurePieceType type, int genDepth, BoundingBox boundingBox) { ++ protected q(StructurePieceType type, int genDepth, BoundingBox boundingBox) { + super(type, genDepth, boundingBox); + } + +- public Turn(StructurePieceType type, CompoundTag tag) { ++ public q(StructurePieceType type, CompoundTag tag) { + super(type, tag); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java.patch new file mode 100644 index 0000000000..bf1817f410 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java.patch @@ -0,0 +1,130 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java +@@ -5,7 +5,8 @@ + import net.minecraft.nbt.CompoundTag; + import net.minecraft.util.RandomSource; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.animal.Cat; + import net.minecraft.world.entity.monster.Witch; + import net.minecraft.world.level.ChunkPos; +@@ -14,7 +15,7 @@ + import net.minecraft.world.level.WorldGenLevel; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.StairBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.StairsShape; + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.levelgen.structure.BoundingBox; +@@ -23,6 +24,7 @@ + import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceType; + + public class SwampHutPiece extends ScatteredFeaturePiece { ++ + private boolean spawnedWitch; + private boolean spawnedCat; + +@@ -44,9 +46,7 @@ + } + + @Override +- public void postProcess( +- WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos +- ) { ++ public void postProcess(WorldGenLevel level, StructureManager structureManager, ChunkGenerator generator, RandomSource random, BoundingBox box, ChunkPos chunkPos, BlockPos pos) { + if (this.updateAverageGroundHeight(level, box, 0)) { + this.generateBox(level, box, 1, 1, 1, 5, 1, 7, Blocks.SPRUCE_PLANKS.defaultBlockState(), Blocks.SPRUCE_PLANKS.defaultBlockState(), false); + this.generateBox(level, box, 1, 4, 2, 5, 4, 7, Blocks.SPRUCE_PLANKS.defaultBlockState(), Blocks.SPRUCE_PLANKS.defaultBlockState(), false); +@@ -69,35 +69,38 @@ + this.placeBlock(level, Blocks.CAULDRON.defaultBlockState(), 4, 2, 6, box); + this.placeBlock(level, Blocks.OAK_FENCE.defaultBlockState(), 1, 2, 1, box); + this.placeBlock(level, Blocks.OAK_FENCE.defaultBlockState(), 5, 2, 1, box); +- BlockState blockState = Blocks.SPRUCE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.NORTH); +- BlockState blockState1 = Blocks.SPRUCE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.EAST); +- BlockState blockState2 = Blocks.SPRUCE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.WEST); +- BlockState blockState3 = Blocks.SPRUCE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.SOUTH); +- this.generateBox(level, box, 0, 4, 1, 6, 4, 1, blockState, blockState, false); +- this.generateBox(level, box, 0, 4, 2, 0, 4, 7, blockState1, blockState1, false); +- this.generateBox(level, box, 6, 4, 2, 6, 4, 7, blockState2, blockState2, false); +- this.generateBox(level, box, 0, 4, 8, 6, 4, 8, blockState3, blockState3, false); +- this.placeBlock(level, blockState.setValue(StairBlock.SHAPE, StairsShape.OUTER_RIGHT), 0, 4, 1, box); +- this.placeBlock(level, blockState.setValue(StairBlock.SHAPE, StairsShape.OUTER_LEFT), 6, 4, 1, box); +- this.placeBlock(level, blockState3.setValue(StairBlock.SHAPE, StairsShape.OUTER_LEFT), 0, 4, 8, box); +- this.placeBlock(level, blockState3.setValue(StairBlock.SHAPE, StairsShape.OUTER_RIGHT), 6, 4, 8, box); ++ IBlockData iblockdata = (IBlockData) Blocks.SPRUCE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.NORTH); ++ IBlockData iblockdata1 = (IBlockData) Blocks.SPRUCE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.EAST); ++ IBlockData iblockdata2 = (IBlockData) Blocks.SPRUCE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.WEST); ++ IBlockData iblockdata3 = (IBlockData) Blocks.SPRUCE_STAIRS.defaultBlockState().setValue(StairBlock.FACING, Direction.SOUTH); + ++ this.generateBox(level, box, 0, 4, 1, 6, 4, 1, iblockdata, iblockdata, false); ++ this.generateBox(level, box, 0, 4, 2, 0, 4, 7, iblockdata1, iblockdata1, false); ++ this.generateBox(level, box, 6, 4, 2, 6, 4, 7, iblockdata2, iblockdata2, false); ++ this.generateBox(level, box, 0, 4, 8, 6, 4, 8, iblockdata3, iblockdata3, false); ++ this.placeBlock(level, (IBlockData) iblockdata.setValue(StairBlock.SHAPE, StairsShape.OUTER_RIGHT), 0, 4, 1, box); ++ this.placeBlock(level, (IBlockData) iblockdata.setValue(StairBlock.SHAPE, StairsShape.OUTER_LEFT), 6, 4, 1, box); ++ this.placeBlock(level, (IBlockData) iblockdata3.setValue(StairBlock.SHAPE, StairsShape.OUTER_LEFT), 0, 4, 8, box); ++ this.placeBlock(level, (IBlockData) iblockdata3.setValue(StairBlock.SHAPE, StairsShape.OUTER_RIGHT), 6, 4, 8, box); ++ + for (int i = 2; i <= 7; i += 5) { +- for (int i1 = 1; i1 <= 5; i1 += 4) { +- this.fillColumnDown(level, Blocks.OAK_LOG.defaultBlockState(), i1, -1, i, box); ++ for (int j = 1; j <= 5; j += 4) { ++ this.fillColumnDown(level, Blocks.OAK_LOG.defaultBlockState(), j, -1, i, box); + } + } + + if (!this.spawnedWitch) { +- BlockPos worldPos = this.getWorldPos(2, 2, 5); +- if (box.isInside(worldPos)) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(2, 2, 5); ++ ++ if (box.isInside(blockposition_mutableblockposition)) { + this.spawnedWitch = true; +- Witch witch = EntityType.WITCH.create(level.getLevel()); +- if (witch != null) { +- witch.setPersistenceRequired(); +- witch.moveTo((double)worldPos.getX() + 0.5, (double)worldPos.getY(), (double)worldPos.getZ() + 0.5, 0.0F, 0.0F); +- witch.finalizeSpawn(level, level.getCurrentDifficultyAt(worldPos), MobSpawnType.STRUCTURE, null, null); +- level.addFreshEntityWithPassengers(witch); ++ Witch entitywitch = (Witch) EntityType.WITCH.create(level.getLevel()); ++ ++ if (entitywitch != null) { ++ entitywitch.setPersistenceRequired(); ++ entitywitch.moveTo((double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + 0.5D, 0.0F, 0.0F); ++ entitywitch.finalizeSpawn(level, level.getCurrentDifficultyAt(blockposition_mutableblockposition), EnumMobSpawn.STRUCTURE, (GroupDataEntity) null, (CompoundTag) null); ++ level.addFreshEntityWithPassengers(entitywitch, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN); // CraftBukkit - add SpawnReason + } + } + } +@@ -108,17 +111,20 @@ + + private void spawnCat(ServerLevelAccessor level, BoundingBox box) { + if (!this.spawnedCat) { +- BlockPos worldPos = this.getWorldPos(2, 2, 5); +- if (box.isInside(worldPos)) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getWorldPos(2, 2, 5); ++ ++ if (box.isInside(blockposition_mutableblockposition)) { + this.spawnedCat = true; +- Cat cat = EntityType.CAT.create(level.getLevel()); +- if (cat != null) { +- cat.setPersistenceRequired(); +- cat.moveTo((double)worldPos.getX() + 0.5, (double)worldPos.getY(), (double)worldPos.getZ() + 0.5, 0.0F, 0.0F); +- cat.finalizeSpawn(level, level.getCurrentDifficultyAt(worldPos), MobSpawnType.STRUCTURE, null, null); +- level.addFreshEntityWithPassengers(cat); ++ Cat entitycat = (Cat) EntityType.CAT.create(level.getLevel()); ++ ++ if (entitycat != null) { ++ entitycat.setPersistenceRequired(); ++ entitycat.moveTo((double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + 0.5D, 0.0F, 0.0F); ++ entitycat.finalizeSpawn(level, level.getCurrentDifficultyAt(blockposition_mutableblockposition), EnumMobSpawn.STRUCTURE, (GroupDataEntity) null, (CompoundTag) null); ++ level.addFreshEntityWithPassengers(entitycat, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN); // CraftBukkit - add SpawnReason + } + } + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings.java.patch new file mode 100644 index 0000000000..7744529ddf --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings.java.patch @@ -0,0 +1,102 @@ +--- a/net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings.java ++++ b/net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings.java +@@ -12,34 +12,44 @@ + import net.minecraft.world.level.levelgen.structure.BoundingBox; + + public class StructurePlaceSettings { +- private Mirror mirror = Mirror.NONE; +- private Rotation rotation = Rotation.NONE; +- private BlockPos rotationPivot = BlockPos.ZERO; ++ ++ private Mirror mirror; ++ private Rotation rotation; ++ private BlockPos rotationPivot; + private boolean ignoreEntities; + @Nullable + private BoundingBox boundingBox; +- private boolean keepLiquids = true; ++ private boolean keepLiquids; + @Nullable + private RandomSource random; +- private int palette; +- private final List processors = Lists.newArrayList(); ++ public int palette = -1; // CraftBukkit - Set initial value so we know if the palette has been set forcefully ++ private final List processors; + private boolean knownShape; + private boolean finalizeEntities; + ++ public StructurePlaceSettings() { ++ this.mirror = Mirror.NONE; ++ this.rotation = Rotation.NONE; ++ this.rotationPivot = BlockPos.ZERO; ++ this.keepLiquids = true; ++ this.processors = Lists.newArrayList(); ++ } ++ + public StructurePlaceSettings copy() { +- StructurePlaceSettings structurePlaceSettings = new StructurePlaceSettings(); +- structurePlaceSettings.mirror = this.mirror; +- structurePlaceSettings.rotation = this.rotation; +- structurePlaceSettings.rotationPivot = this.rotationPivot; +- structurePlaceSettings.ignoreEntities = this.ignoreEntities; +- structurePlaceSettings.boundingBox = this.boundingBox; +- structurePlaceSettings.keepLiquids = this.keepLiquids; +- structurePlaceSettings.random = this.random; +- structurePlaceSettings.palette = this.palette; +- structurePlaceSettings.processors.addAll(this.processors); +- structurePlaceSettings.knownShape = this.knownShape; +- structurePlaceSettings.finalizeEntities = this.finalizeEntities; +- return structurePlaceSettings; ++ StructurePlaceSettings definedstructureinfo = new StructurePlaceSettings(); ++ ++ definedstructureinfo.mirror = this.mirror; ++ definedstructureinfo.rotation = this.rotation; ++ definedstructureinfo.rotationPivot = this.rotationPivot; ++ definedstructureinfo.ignoreEntities = this.ignoreEntities; ++ definedstructureinfo.boundingBox = this.boundingBox; ++ definedstructureinfo.keepLiquids = this.keepLiquids; ++ definedstructureinfo.random = this.random; ++ definedstructureinfo.palette = this.palette; ++ definedstructureinfo.processors.addAll(this.processors); ++ definedstructureinfo.knownShape = this.knownShape; ++ definedstructureinfo.finalizeEntities = this.finalizeEntities; ++ return definedstructureinfo; + } + + public StructurePlaceSettings setMirror(Mirror mirror) { +@@ -110,11 +120,7 @@ + } + + public RandomSource getRandom(@Nullable BlockPos seedPos) { +- if (this.random != null) { +- return this.random; +- } else { +- return seedPos == null ? RandomSource.create(Util.getMillis()) : RandomSource.create(Mth.getSeed(seedPos)); +- } ++ return this.random != null ? this.random : (seedPos == null ? RandomSource.create(Util.getMillis()) : RandomSource.create(Mth.getSeed(seedPos))); + } + + public boolean isIgnoreEntities() { +@@ -139,11 +145,19 @@ + } + + public StructureTemplate.Palette getRandomPalette(List palettes, @Nullable BlockPos pos) { +- int size = palettes.size(); +- if (size == 0) { ++ int i = palettes.size(); ++ ++ if (i == 0) { + throw new IllegalStateException("No palettes"); ++ // CraftBukkit start ++ } else if (this.palette > 0) { ++ if (this.palette >= i) { ++ throw new IllegalArgumentException("Palette index out of bounds. Got " + this.palette + " where there are only " + i + " palettes available."); ++ } ++ return palettes.get(this.palette); ++ // CraftBukkit end + } else { +- return palettes.get(this.getRandom(pos).nextInt(size)); ++ return (StructureTemplate.Palette) palettes.get(this.getRandom(pos).nextInt(i)); + } + } + diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java.patch new file mode 100644 index 0000000000..9a15ae53a2 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java.patch @@ -0,0 +1,1242 @@ +--- a/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java ++++ b/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java +@@ -24,13 +24,15 @@ + import net.minecraft.nbt.IntTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtUtils; ++import net.minecraft.nbt.Tag; + import net.minecraft.util.RandomSource; + import net.minecraft.world.Clearable; + import net.minecraft.world.RandomizableContainer; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.decoration.Painting; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.EmptyBlockGetter; +@@ -43,15 +45,19 @@ + import net.minecraft.world.level.block.Mirror; + import net.minecraft.world.level.block.Rotation; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.levelgen.structure.BoundingBox; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.BitSetDiscreteVoxelShape; + import net.minecraft.world.phys.shapes.DiscreteVoxelShape; ++import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer; ++import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry; ++// CraftBukkit end + + public class StructureTemplate { ++ + public static final String PALETTE_TAG = "palette"; + public static final String PALETTE_LIST_TAG = "palettes"; + public static final String ENTITIES_TAG = "entities"; +@@ -63,11 +69,21 @@ + public static final String ENTITY_TAG_BLOCKPOS = "blockPos"; + public static final String ENTITY_TAG_NBT = "nbt"; + public static final String SIZE_TAG = "size"; +- private final List palettes = Lists.newArrayList(); +- private final List entityInfoList = Lists.newArrayList(); +- private Vec3i size = Vec3i.ZERO; +- private String author = "?"; ++ public final List palettes = Lists.newArrayList(); ++ public final List entityInfoList = Lists.newArrayList(); ++ private Vec3i size; ++ private String author; + ++ // CraftBukkit start - data containers ++ private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); ++ public CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); ++ // CraftBukkit end ++ ++ public StructureTemplate() { ++ this.size = Vec3i.ZERO; ++ this.author = "?"; ++ } ++ + public Vec3i getSize() { + return this.size; + } +@@ -82,51 +98,49 @@ + + public void fillFromWorld(Level level, BlockPos pos, Vec3i size, boolean withEntities, @Nullable Block toIgnore) { + if (size.getX() >= 1 && size.getY() >= 1 && size.getZ() >= 1) { +- BlockPos blockPos = pos.offset(size).offset(-1, -1, -1); ++ BlockPos blockposition1 = pos.offset(size).offset(-1, -1, -1); + List list = Lists.newArrayList(); + List list1 = Lists.newArrayList(); + List list2 = Lists.newArrayList(); +- BlockPos blockPos1 = new BlockPos( +- Math.min(pos.getX(), blockPos.getX()), Math.min(pos.getY(), blockPos.getY()), Math.min(pos.getZ(), blockPos.getZ()) +- ); +- BlockPos blockPos2 = new BlockPos( +- Math.max(pos.getX(), blockPos.getX()), Math.max(pos.getY(), blockPos.getY()), Math.max(pos.getZ(), blockPos.getZ()) +- ); ++ BlockPos blockposition2 = new BlockPos(Math.min(pos.getX(), blockposition1.getX()), Math.min(pos.getY(), blockposition1.getY()), Math.min(pos.getZ(), blockposition1.getZ())); ++ BlockPos blockposition3 = new BlockPos(Math.max(pos.getX(), blockposition1.getX()), Math.max(pos.getY(), blockposition1.getY()), Math.max(pos.getZ(), blockposition1.getZ())); ++ + this.size = size; ++ Iterator iterator = BlockPos.betweenClosed(blockposition2, blockposition3).iterator(); + +- for (BlockPos blockPos3 : BlockPos.betweenClosed(blockPos1, blockPos2)) { +- BlockPos blockPos4 = blockPos3.subtract(blockPos1); +- BlockState blockState = level.getBlockState(blockPos3); +- if (toIgnore == null || !blockState.is(toIgnore)) { +- BlockEntity blockEntity = level.getBlockEntity(blockPos3); +- StructureTemplate.StructureBlockInfo structureBlockInfo; +- if (blockEntity != null) { +- structureBlockInfo = new StructureTemplate.StructureBlockInfo(blockPos4, blockState, blockEntity.saveWithId()); ++ while (iterator.hasNext()) { ++ BlockPos blockposition4 = (BlockPos) iterator.next(); ++ BlockPos blockposition5 = blockposition4.subtract(blockposition2); ++ IBlockData iblockdata = level.getBlockState(blockposition4); ++ ++ if (toIgnore == null || !iblockdata.is(toIgnore)) { ++ BlockEntity tileentity = level.getBlockEntity(blockposition4); ++ StructureTemplate.StructureBlockInfo definedstructure_blockinfo; ++ ++ if (tileentity != null) { ++ definedstructure_blockinfo = new StructureTemplate.StructureBlockInfo(blockposition5, iblockdata, tileentity.saveWithId()); + } else { +- structureBlockInfo = new StructureTemplate.StructureBlockInfo(blockPos4, blockState, null); ++ definedstructure_blockinfo = new StructureTemplate.StructureBlockInfo(blockposition5, iblockdata, (CompoundTag) null); + } + +- addToLists(structureBlockInfo, list, list1, list2); ++ addToLists(definedstructure_blockinfo, list, list1, list2); + } + } + + List list3 = buildInfoList(list, list1, list2); ++ + this.palettes.clear(); + this.palettes.add(new StructureTemplate.Palette(list3)); + if (withEntities) { +- this.fillEntityList(level, blockPos1, blockPos2); ++ this.fillEntityList(level, blockposition2, blockposition3); + } else { + this.entityInfoList.clear(); + } ++ + } + } + +- private static void addToLists( +- StructureTemplate.StructureBlockInfo blockInfo, +- List normalBlocks, +- List blocksWithNbt, +- List blocksWithSpecialShape +- ) { ++ private static void addToLists(StructureTemplate.StructureBlockInfo blockInfo, List normalBlocks, List blocksWithNbt, List blocksWithSpecialShape) { + if (blockInfo.nbt != null) { + blocksWithNbt.add(blockInfo); + } else if (!blockInfo.state.getBlock().hasDynamicShape() && blockInfo.state.isCollisionShapeFullBlock(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)) { +@@ -134,78 +148,86 @@ + } else { + blocksWithSpecialShape.add(blockInfo); + } ++ + } + +- private static List buildInfoList( +- List normalBlocks, +- List blocksWithNbt, +- List blocksWithSpecialShape +- ) { +- Comparator comparator = Comparator.comparingInt( +- structureBlockInfo -> structureBlockInfo.pos.getY() +- ) +- .thenComparingInt(structureBlockInfo -> structureBlockInfo.pos.getX()) +- .thenComparingInt(structureBlockInfo -> structureBlockInfo.pos.getZ()); ++ private static List buildInfoList(List normalBlocks, List blocksWithNbt, List blocksWithSpecialShape) { ++ Comparator comparator = Comparator.comparingInt((definedstructure_blockinfo) -> { // CraftBukkit - decompile error ++ return definedstructure_blockinfo.pos.getY(); ++ }).thenComparingInt((definedstructure_blockinfo) -> { ++ return definedstructure_blockinfo.pos.getX(); ++ }).thenComparingInt((definedstructure_blockinfo) -> { ++ return definedstructure_blockinfo.pos.getZ(); ++ }); ++ + normalBlocks.sort(comparator); + blocksWithSpecialShape.sort(comparator); + blocksWithNbt.sort(comparator); +- List list = Lists.newArrayList(); +- list.addAll(normalBlocks); +- list.addAll(blocksWithSpecialShape); +- list.addAll(blocksWithNbt); +- return list; ++ List list3 = Lists.newArrayList(); ++ ++ list3.addAll(normalBlocks); ++ list3.addAll(blocksWithSpecialShape); ++ list3.addAll(blocksWithNbt); ++ return list3; + } + + private void fillEntityList(Level level, BlockPos startPos, BlockPos endPos) { +- List entitiesOfClass = level.getEntitiesOfClass( +- Entity.class, AABB.encapsulatingFullBlocks(startPos, endPos), entity1 -> !(entity1 instanceof Player) +- ); ++ List list = level.getEntitiesOfClass(Entity.class, AABB.encapsulatingFullBlocks(startPos, endPos), (entity) -> { ++ return !(entity instanceof Player); ++ }); ++ + this.entityInfoList.clear(); + +- for (Entity entity : entitiesOfClass) { +- Vec3 vec3 = new Vec3(entity.getX() - (double)startPos.getX(), entity.getY() - (double)startPos.getY(), entity.getZ() - (double)startPos.getZ()); +- CompoundTag compoundTag = new CompoundTag(); +- entity.save(compoundTag); +- BlockPos blockPos; ++ Vec3 vec3d; ++ CompoundTag nbttagcompound; ++ BlockPos blockposition2; ++ ++ for (Iterator iterator = list.iterator(); iterator.hasNext(); this.entityInfoList.add(new StructureTemplate.StructureEntityInfo(vec3d, blockposition2, nbttagcompound.copy()))) { ++ Entity entity = (Entity) iterator.next(); ++ ++ vec3d = new Vec3(entity.getX() - (double) startPos.getX(), entity.getY() - (double) startPos.getY(), entity.getZ() - (double) startPos.getZ()); ++ nbttagcompound = new CompoundTag(); ++ entity.save(nbttagcompound); + if (entity instanceof Painting) { +- blockPos = ((Painting)entity).getPos().subtract(startPos); ++ blockposition2 = ((Painting) entity).getPos().subtract(startPos); + } else { +- blockPos = BlockPos.containing(vec3); ++ blockposition2 = BlockPos.containing(vec3d); + } +- +- this.entityInfoList.add(new StructureTemplate.StructureEntityInfo(vec3, blockPos, compoundTag.copy())); + } ++ + } + + public List filterBlocks(BlockPos pos, StructurePlaceSettings settings, Block block) { + return this.filterBlocks(pos, settings, block, true); + } + +- public ObjectArrayList filterBlocks( +- BlockPos pos, StructurePlaceSettings settings, Block block, boolean relativePosition +- ) { +- ObjectArrayList list = new ObjectArrayList<>(); +- BoundingBox boundingBox = settings.getBoundingBox(); ++ public ObjectArrayList filterBlocks(BlockPos pos, StructurePlaceSettings settings, Block block, boolean relativePosition) { ++ ObjectArrayList objectarraylist = new ObjectArrayList(); ++ BoundingBox structureboundingbox = settings.getBoundingBox(); ++ + if (this.palettes.isEmpty()) { +- return list; ++ return objectarraylist; + } else { +- for (StructureTemplate.StructureBlockInfo structureBlockInfo : settings.getRandomPalette(this.palettes, pos).blocks(block)) { +- BlockPos blockPos = relativePosition ? calculateRelativePosition(settings, structureBlockInfo.pos).offset(pos) : structureBlockInfo.pos; +- if (boundingBox == null || boundingBox.isInside(blockPos)) { +- list.add( +- new StructureTemplate.StructureBlockInfo(blockPos, structureBlockInfo.state.rotate(settings.getRotation()), structureBlockInfo.nbt) +- ); ++ Iterator iterator = settings.getRandomPalette(this.palettes, pos).blocks(block).iterator(); ++ ++ while (iterator.hasNext()) { ++ StructureTemplate.StructureBlockInfo definedstructure_blockinfo = (StructureTemplate.StructureBlockInfo) iterator.next(); ++ BlockPos blockposition1 = relativePosition ? calculateRelativePosition(settings, definedstructure_blockinfo.pos).offset(pos) : definedstructure_blockinfo.pos; ++ ++ if (structureboundingbox == null || structureboundingbox.isInside(blockposition1)) { ++ objectarraylist.add(new StructureTemplate.StructureBlockInfo(blockposition1, definedstructure_blockinfo.state.rotate(settings.getRotation()), definedstructure_blockinfo.nbt)); + } + } + +- return list; ++ return objectarraylist; + } + } + + public BlockPos calculateConnectedPosition(StructurePlaceSettings decorator, BlockPos start, StructurePlaceSettings settings, BlockPos end) { +- BlockPos blockPos = calculateRelativePosition(decorator, start); +- BlockPos blockPos1 = calculateRelativePosition(settings, end); +- return blockPos.subtract(blockPos1); ++ BlockPos blockposition2 = calculateRelativePosition(decorator, start); ++ BlockPos blockposition3 = calculateRelativePosition(settings, end); ++ ++ return blockposition2.subtract(blockposition3); + } + + public static BlockPos calculateRelativePosition(StructurePlaceSettings decorator, BlockPos pos) { +@@ -216,59 +238,91 @@ + if (this.palettes.isEmpty()) { + return false; + } else { ++ // CraftBukkit start ++ // We only want the TransformerGeneratorAccess at certain locations because in here are many "block update" calls that shouldn't be transformed ++ ServerLevelAccessor wrappedAccess = serverLevel; ++ org.bukkit.craftbukkit.util.CraftStructureTransformer structureTransformer = null; ++ if (wrappedAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ serverLevel = transformerAccess.getHandle(); ++ structureTransformer = transformerAccess.getStructureTransformer(); ++ // The structureTransformer is not needed if we can not transform blocks therefore we can save a little bit of performance doing this ++ if (structureTransformer != null && !structureTransformer.canTransformBlocks()) { ++ structureTransformer = null; ++ } ++ } ++ // CraftBukkit end + List list = settings.getRandomPalette(this.palettes, offset).blocks(); +- if ((!list.isEmpty() || !settings.isIgnoreEntities() && !this.entityInfoList.isEmpty()) +- && this.size.getX() >= 1 +- && this.size.getY() >= 1 +- && this.size.getZ() >= 1) { +- BoundingBox boundingBox = settings.getBoundingBox(); ++ ++ if ((!list.isEmpty() || !settings.isIgnoreEntities() && !this.entityInfoList.isEmpty()) && this.size.getX() >= 1 && this.size.getY() >= 1 && this.size.getZ() >= 1) { ++ BoundingBox structureboundingbox = settings.getBoundingBox(); + List list1 = Lists.newArrayListWithCapacity(settings.shouldKeepLiquids() ? list.size() : 0); + List list2 = Lists.newArrayListWithCapacity(settings.shouldKeepLiquids() ? list.size() : 0); + List> list3 = Lists.newArrayListWithCapacity(list.size()); +- int i = Integer.MAX_VALUE; +- int i1 = Integer.MAX_VALUE; +- int i2 = Integer.MAX_VALUE; +- int i3 = Integer.MIN_VALUE; +- int i4 = Integer.MIN_VALUE; +- int i5 = Integer.MIN_VALUE; ++ int j = Integer.MAX_VALUE; ++ int k = Integer.MAX_VALUE; ++ int l = Integer.MAX_VALUE; ++ int i1 = Integer.MIN_VALUE; ++ int j1 = Integer.MIN_VALUE; ++ int k1 = Integer.MIN_VALUE; ++ List list4 = processBlockInfos(serverLevel, offset, pos, settings, list); ++ Iterator iterator = list4.iterator(); + +- for (StructureTemplate.StructureBlockInfo structureBlockInfo : processBlockInfos(serverLevel, offset, pos, settings, list)) { +- BlockPos blockPos = structureBlockInfo.pos; +- if (boundingBox == null || boundingBox.isInside(blockPos)) { +- FluidState fluidState = settings.shouldKeepLiquids() ? serverLevel.getFluidState(blockPos) : null; +- BlockState blockState = structureBlockInfo.state.mirror(settings.getMirror()).rotate(settings.getRotation()); +- if (structureBlockInfo.nbt != null) { +- BlockEntity blockEntity = serverLevel.getBlockEntity(blockPos); +- Clearable.tryClear(blockEntity); +- serverLevel.setBlock(blockPos, Blocks.BARRIER.defaultBlockState(), 20); ++ BlockEntity tileentity; ++ ++ while (iterator.hasNext()) { ++ StructureTemplate.StructureBlockInfo definedstructure_blockinfo = (StructureTemplate.StructureBlockInfo) iterator.next(); ++ BlockPos blockposition2 = definedstructure_blockinfo.pos; ++ ++ if (structureboundingbox == null || structureboundingbox.isInside(blockposition2)) { ++ FluidState fluid = settings.shouldKeepLiquids() ? serverLevel.getFluidState(blockposition2) : null; ++ IBlockData iblockdata = definedstructure_blockinfo.state.mirror(settings.getMirror()).rotate(settings.getRotation()); ++ ++ if (definedstructure_blockinfo.nbt != null) { ++ tileentity = serverLevel.getBlockEntity(blockposition2); ++ Clearable.tryClear(tileentity); ++ serverLevel.setBlock(blockposition2, Blocks.BARRIER.defaultBlockState(), 20); + } ++ // CraftBukkit start ++ if (structureTransformer != null) { ++ org.bukkit.craftbukkit.block.CraftBlockState craftBlockState = (org.bukkit.craftbukkit.block.CraftBlockState) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockposition2, iblockdata, null); ++ if (definedstructure_blockinfo.nbt != null && craftBlockState instanceof org.bukkit.craftbukkit.block.CraftBlockEntityState entityState) { ++ entityState.loadData(definedstructure_blockinfo.nbt); ++ if (craftBlockState instanceof org.bukkit.craftbukkit.block.CraftLootable craftLootable) { ++ craftLootable.setSeed(random.nextLong()); ++ } ++ } ++ craftBlockState = structureTransformer.transformCraftState(craftBlockState); ++ iblockdata = craftBlockState.getHandle(); ++ definedstructure_blockinfo = new StructureTemplate.StructureBlockInfo(blockposition2, iblockdata, (craftBlockState instanceof org.bukkit.craftbukkit.block.CraftBlockEntityState craftBlockEntityState ? craftBlockEntityState.getSnapshotNBT() : null)); ++ } ++ // CraftBukkit end + +- if (serverLevel.setBlock(blockPos, blockState, flags)) { +- i = Math.min(i, blockPos.getX()); +- i1 = Math.min(i1, blockPos.getY()); +- i2 = Math.min(i2, blockPos.getZ()); +- i3 = Math.max(i3, blockPos.getX()); +- i4 = Math.max(i4, blockPos.getY()); +- i5 = Math.max(i5, blockPos.getZ()); +- list3.add(Pair.of(blockPos, structureBlockInfo.nbt)); +- if (structureBlockInfo.nbt != null) { +- BlockEntity blockEntity = serverLevel.getBlockEntity(blockPos); +- if (blockEntity != null) { +- if (blockEntity instanceof RandomizableContainer) { +- structureBlockInfo.nbt.putLong("LootTableSeed", random.nextLong()); ++ if (serverLevel.setBlock(blockposition2, iblockdata, flags)) { ++ j = Math.min(j, blockposition2.getX()); ++ k = Math.min(k, blockposition2.getY()); ++ l = Math.min(l, blockposition2.getZ()); ++ i1 = Math.max(i1, blockposition2.getX()); ++ j1 = Math.max(j1, blockposition2.getY()); ++ k1 = Math.max(k1, blockposition2.getZ()); ++ list3.add(Pair.of(blockposition2, definedstructure_blockinfo.nbt)); ++ if (definedstructure_blockinfo.nbt != null) { ++ tileentity = serverLevel.getBlockEntity(blockposition2); ++ if (tileentity != null) { ++ if (structureTransformer == null && tileentity instanceof RandomizableContainer) { // CraftBukkit - only process if don't have a transformer access (Was already set above) - SPIGOT-7520: Use structureTransformer as check, so that it is the same as above ++ definedstructure_blockinfo.nbt.putLong("LootTableSeed", random.nextLong()); + } + +- blockEntity.load(structureBlockInfo.nbt); ++ tileentity.load(definedstructure_blockinfo.nbt); + } + } + +- if (fluidState != null) { +- if (blockState.getFluidState().isSource()) { +- list2.add(blockPos); +- } else if (blockState.getBlock() instanceof LiquidBlockContainer) { +- ((LiquidBlockContainer)blockState.getBlock()).placeLiquid(serverLevel, blockPos, blockState, fluidState); +- if (!fluidState.isSource()) { +- list1.add(blockPos); ++ if (fluid != null) { ++ if (iblockdata.getFluidState().isSource()) { ++ list2.add(blockposition2); ++ } else if (iblockdata.getBlock() instanceof LiquidBlockContainer) { ++ ((LiquidBlockContainer) iblockdata.getBlock()).placeLiquid(serverLevel, blockposition2, iblockdata, fluid); ++ if (!fluid.isSource()) { ++ list1.add(blockposition2); + } + } + } +@@ -277,82 +331,89 @@ + } + + boolean flag = true; +- Direction[] directions = new Direction[]{Direction.UP, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST}; ++ Direction[] aenumdirection = new Direction[]{Direction.UP, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST}; + ++ Iterator iterator1; ++ int l1; ++ IBlockData iblockdata1; ++ + while (flag && !list1.isEmpty()) { + flag = false; +- Iterator iterator = list1.iterator(); ++ iterator1 = list1.iterator(); + +- while (iterator.hasNext()) { +- BlockPos blockPos1 = iterator.next(); +- FluidState fluidState1 = serverLevel.getFluidState(blockPos1); ++ while (iterator1.hasNext()) { ++ BlockPos blockposition3 = (BlockPos) iterator1.next(); ++ FluidState fluid1 = serverLevel.getFluidState(blockposition3); + +- for (int i6 = 0; i6 < directions.length && !fluidState1.isSource(); i6++) { +- BlockPos blockPos2 = blockPos1.relative(directions[i6]); +- FluidState fluidState2 = serverLevel.getFluidState(blockPos2); +- if (fluidState2.isSource() && !list2.contains(blockPos2)) { +- fluidState1 = fluidState2; ++ for (l1 = 0; l1 < aenumdirection.length && !fluid1.isSource(); ++l1) { ++ BlockPos blockposition4 = blockposition3.relative(aenumdirection[l1]); ++ FluidState fluid2 = serverLevel.getFluidState(blockposition4); ++ ++ if (fluid2.isSource() && !list2.contains(blockposition4)) { ++ fluid1 = fluid2; + } + } + +- if (fluidState1.isSource()) { +- BlockState blockState1 = serverLevel.getBlockState(blockPos1); +- Block block = blockState1.getBlock(); ++ if (fluid1.isSource()) { ++ iblockdata1 = serverLevel.getBlockState(blockposition3); ++ Block block = iblockdata1.getBlock(); ++ + if (block instanceof LiquidBlockContainer) { +- ((LiquidBlockContainer)block).placeLiquid(serverLevel, blockPos1, blockState1, fluidState1); ++ ((LiquidBlockContainer) block).placeLiquid(serverLevel, blockposition3, iblockdata1, fluid1); + flag = true; +- iterator.remove(); ++ iterator1.remove(); + } + } + } + } + +- if (i <= i3) { ++ if (j <= i1) { + if (!settings.getKnownShape()) { +- DiscreteVoxelShape discreteVoxelShape = new BitSetDiscreteVoxelShape(i3 - i + 1, i4 - i1 + 1, i5 - i2 + 1); +- int i7 = i; +- int i8 = i1; +- int i6x = i2; ++ BitSetDiscreteVoxelShape voxelshapebitset = new BitSetDiscreteVoxelShape(i1 - j + 1, j1 - k + 1, k1 - l + 1); ++ int i2 = j; ++ int j2 = k; + +- for (Pair pair : list3) { +- BlockPos blockPos3 = pair.getFirst(); +- discreteVoxelShape.fill(blockPos3.getX() - i7, blockPos3.getY() - i8, blockPos3.getZ() - i6x); ++ l1 = l; ++ Iterator iterator2 = list3.iterator(); ++ ++ while (iterator2.hasNext()) { ++ Pair pair = (Pair) iterator2.next(); ++ BlockPos blockposition5 = (BlockPos) pair.getFirst(); ++ ++ voxelshapebitset.fill(blockposition5.getX() - i2, blockposition5.getY() - j2, blockposition5.getZ() - l1); + } + +- updateShapeAtEdge(serverLevel, flags, discreteVoxelShape, i7, i8, i6x); ++ updateShapeAtEdge(serverLevel, flags, voxelshapebitset, i2, j2, l1); + } + +- for (Pair pair1 : list3) { +- BlockPos blockPos4 = pair1.getFirst(); ++ iterator1 = list3.iterator(); ++ ++ while (iterator1.hasNext()) { ++ Pair pair1 = (Pair) iterator1.next(); ++ BlockPos blockposition6 = (BlockPos) pair1.getFirst(); ++ + if (!settings.getKnownShape()) { +- BlockState blockState1 = serverLevel.getBlockState(blockPos4); +- BlockState blockState2 = Block.updateFromNeighbourShapes(blockState1, serverLevel, blockPos4); +- if (blockState1 != blockState2) { +- serverLevel.setBlock(blockPos4, blockState2, flags & -2 | 16); ++ iblockdata1 = serverLevel.getBlockState(blockposition6); ++ IBlockData iblockdata2 = Block.updateFromNeighbourShapes(iblockdata1, serverLevel, blockposition6); ++ ++ if (iblockdata1 != iblockdata2) { ++ serverLevel.setBlock(blockposition6, iblockdata2, flags & -2 | 16); + } + +- serverLevel.blockUpdated(blockPos4, blockState2.getBlock()); ++ serverLevel.blockUpdated(blockposition6, iblockdata2.getBlock()); + } + + if (pair1.getSecond() != null) { +- BlockEntity blockEntity = serverLevel.getBlockEntity(blockPos4); +- if (blockEntity != null) { +- blockEntity.setChanged(); ++ tileentity = serverLevel.getBlockEntity(blockposition6); ++ if (tileentity != null) { ++ tileentity.setChanged(); + } + } + } + } + + if (!settings.isIgnoreEntities()) { +- this.placeEntities( +- serverLevel, +- offset, +- settings.getMirror(), +- settings.getRotation(), +- settings.getRotationPivot(), +- boundingBox, +- settings.shouldFinalizeEntities() +- ); ++ this.placeEntities(wrappedAccess, offset, settings.getMirror(), settings.getRotation(), settings.getRotationPivot(), structureboundingbox, settings.shouldFinalizeEntities()); // CraftBukkit + } + + return true; +@@ -363,100 +424,97 @@ + } + + public static void updateShapeAtEdge(LevelAccessor level, int flags, DiscreteVoxelShape shape, int x, int y, int z) { +- shape.forAllFaces((direction, x1, y1, z1) -> { +- BlockPos blockPos = new BlockPos(x + x1, y + y1, z + z1); +- BlockPos blockPos1 = blockPos.relative(direction); +- BlockState blockState = level.getBlockState(blockPos); +- BlockState blockState1 = level.getBlockState(blockPos1); +- BlockState blockState2 = blockState.updateShape(direction, blockState1, level, blockPos, blockPos1); +- if (blockState != blockState2) { +- level.setBlock(blockPos, blockState2, flags & -2); ++ shape.forAllFaces((enumdirection, i1, j1, k1) -> { ++ BlockPos blockposition = new BlockPos(x + i1, y + j1, z + k1); ++ BlockPos blockposition1 = blockposition.relative(enumdirection); ++ IBlockData iblockdata = level.getBlockState(blockposition); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ IBlockData iblockdata2 = iblockdata.updateShape(enumdirection, iblockdata1, level, blockposition, blockposition1); ++ ++ if (iblockdata != iblockdata2) { ++ level.setBlock(blockposition, iblockdata2, flags & -2); + } + +- BlockState blockState3 = blockState1.updateShape(direction.getOpposite(), blockState2, level, blockPos1, blockPos); +- if (blockState1 != blockState3) { +- level.setBlock(blockPos1, blockState3, flags & -2); ++ IBlockData iblockdata3 = iblockdata1.updateShape(enumdirection.getOpposite(), iblockdata2, level, blockposition1, blockposition); ++ ++ if (iblockdata1 != iblockdata3) { ++ level.setBlock(blockposition1, iblockdata3, flags & -2); + } ++ + }); + } + +- public static List processBlockInfos( +- ServerLevelAccessor serverLevel, BlockPos offset, BlockPos pos, StructurePlaceSettings settings, List blockInfos +- ) { +- List list = new ArrayList<>(); +- List list1 = new ArrayList<>(); ++ public static List processBlockInfos(ServerLevelAccessor serverLevel, BlockPos offset, BlockPos pos, StructurePlaceSettings settings, List blockInfos) { ++ List list1 = new ArrayList(); ++ List list2 = new ArrayList(); ++ Iterator iterator = blockInfos.iterator(); + +- for (StructureTemplate.StructureBlockInfo structureBlockInfo : blockInfos) { +- BlockPos blockPos = calculateRelativePosition(settings, structureBlockInfo.pos).offset(offset); +- StructureTemplate.StructureBlockInfo structureBlockInfo1 = new StructureTemplate.StructureBlockInfo( +- blockPos, structureBlockInfo.state, structureBlockInfo.nbt != null ? structureBlockInfo.nbt.copy() : null +- ); +- Iterator iterator = settings.getProcessors().iterator(); ++ while (iterator.hasNext()) { ++ StructureTemplate.StructureBlockInfo definedstructure_blockinfo = (StructureTemplate.StructureBlockInfo) iterator.next(); ++ BlockPos blockposition2 = calculateRelativePosition(settings, definedstructure_blockinfo.pos).offset(offset); ++ StructureTemplate.StructureBlockInfo definedstructure_blockinfo1 = new StructureTemplate.StructureBlockInfo(blockposition2, definedstructure_blockinfo.state, definedstructure_blockinfo.nbt != null ? definedstructure_blockinfo.nbt.copy() : null); + +- while (structureBlockInfo1 != null && iterator.hasNext()) { +- structureBlockInfo1 = iterator.next().processBlock(serverLevel, offset, pos, structureBlockInfo, structureBlockInfo1, settings); ++ for (Iterator iterator1 = settings.getProcessors().iterator(); definedstructure_blockinfo1 != null && iterator1.hasNext(); definedstructure_blockinfo1 = ((StructureProcessor) iterator1.next()).processBlock(serverLevel, offset, pos, definedstructure_blockinfo, definedstructure_blockinfo1, settings)) { ++ ; + } + +- if (structureBlockInfo1 != null) { +- list1.add(structureBlockInfo1); +- list.add(structureBlockInfo); ++ if (definedstructure_blockinfo1 != null) { ++ ((List) list2).add(definedstructure_blockinfo1); ++ list1.add(definedstructure_blockinfo); + } + } + +- for (StructureProcessor structureProcessor : settings.getProcessors()) { +- list1 = structureProcessor.finalizeProcessing(serverLevel, offset, pos, list, list1, settings); ++ StructureProcessor definedstructureprocessor; ++ ++ for (iterator = settings.getProcessors().iterator(); iterator.hasNext(); list2 = definedstructureprocessor.finalizeProcessing(serverLevel, offset, pos, list1, (List) list2, settings)) { ++ definedstructureprocessor = (StructureProcessor) iterator.next(); + } + +- return list1; ++ return (List) list2; + } + +- private void placeEntities( +- ServerLevelAccessor serverLevel, +- BlockPos pos, +- Mirror mirror, +- Rotation rotation, +- BlockPos offset, +- @Nullable BoundingBox boundingBox, +- boolean withEntities +- ) { +- for (StructureTemplate.StructureEntityInfo structureEntityInfo : this.entityInfoList) { +- BlockPos blockPos = transform(structureEntityInfo.blockPos, mirror, rotation, offset).offset(pos); +- if (boundingBox == null || boundingBox.isInside(blockPos)) { +- CompoundTag compoundTag = structureEntityInfo.nbt.copy(); +- Vec3 vec3 = transform(structureEntityInfo.pos, mirror, rotation, offset); +- Vec3 vec31 = vec3.add((double)pos.getX(), (double)pos.getY(), (double)pos.getZ()); +- ListTag list = new ListTag(); +- list.add(DoubleTag.valueOf(vec31.x)); +- list.add(DoubleTag.valueOf(vec31.y)); +- list.add(DoubleTag.valueOf(vec31.z)); +- compoundTag.put("Pos", list); +- compoundTag.remove("UUID"); +- createEntityIgnoreException(serverLevel, compoundTag) +- .ifPresent( +- entity -> { +- float f = entity.rotate(rotation); +- f += entity.mirror(mirror) - entity.getYRot(); +- entity.moveTo(vec31.x, vec31.y, vec31.z, f, entity.getXRot()); +- if (withEntities && entity instanceof Mob) { +- ((Mob)entity) +- .finalizeSpawn( +- serverLevel, serverLevel.getCurrentDifficultyAt(BlockPos.containing(vec31)), MobSpawnType.STRUCTURE, null, compoundTag +- ); +- } +- +- serverLevel.addFreshEntityWithPassengers(entity); +- } +- ); ++ private void placeEntities(ServerLevelAccessor serverLevel, BlockPos pos, Mirror mirror, Rotation rotation, BlockPos offset, @Nullable BoundingBox boundingBox, boolean withEntities) { ++ Iterator iterator = this.entityInfoList.iterator(); ++ ++ while (iterator.hasNext()) { ++ StructureTemplate.StructureEntityInfo definedstructure_entityinfo = (StructureTemplate.StructureEntityInfo) iterator.next(); ++ BlockPos blockposition2 = transform(definedstructure_entityinfo.blockPos, mirror, rotation, offset).offset(pos); ++ ++ if (boundingBox == null || boundingBox.isInside(blockposition2)) { ++ CompoundTag nbttagcompound = definedstructure_entityinfo.nbt.copy(); ++ Vec3 vec3d = transform(definedstructure_entityinfo.pos, mirror, rotation, offset); ++ Vec3 vec3d1 = vec3d.add((double) pos.getX(), (double) pos.getY(), (double) pos.getZ()); ++ ListTag nbttaglist = new ListTag(); ++ ++ nbttaglist.add(DoubleTag.valueOf(vec3d1.x)); ++ nbttaglist.add(DoubleTag.valueOf(vec3d1.y)); ++ nbttaglist.add(DoubleTag.valueOf(vec3d1.z)); ++ nbttagcompound.put("Pos", nbttaglist); ++ nbttagcompound.remove("UUID"); ++ createEntityIgnoreException(serverLevel, nbttagcompound).ifPresent((entity) -> { ++ float f = entity.rotate(rotation); ++ ++ f += entity.mirror(mirror) - entity.getYRot(); ++ entity.moveTo(vec3d1.x, vec3d1.y, vec3d1.z, f, entity.getXRot()); ++ if (withEntities && entity instanceof Mob) { ++ ((Mob) entity).finalizeSpawn(serverLevel, serverLevel.getCurrentDifficultyAt(BlockPos.containing(vec3d1)), EnumMobSpawn.STRUCTURE, (GroupDataEntity) null, nbttagcompound); ++ } ++ ++ serverLevel.addFreshEntityWithPassengers(entity); ++ }); + } + } ++ + } + + private static Optional createEntityIgnoreException(ServerLevelAccessor level, CompoundTag tag) { +- try { ++ // CraftBukkit start ++ // try { + return EntityType.create(tag, level.getLevel()); +- } catch (Exception var3) { +- return Optional.empty(); +- } ++ // } catch (Exception exception) { ++ // return Optional.empty(); ++ // } ++ // CraftBukkit end + } + + public Vec3i getSize(Rotation rotation) { +@@ -470,62 +528,66 @@ + } + + public static BlockPos transform(BlockPos targetPos, Mirror mirror, Rotation rotation, BlockPos offset) { +- int x = targetPos.getX(); +- int y = targetPos.getY(); +- int z = targetPos.getZ(); ++ int i = targetPos.getX(); ++ int j = targetPos.getY(); ++ int k = targetPos.getZ(); + boolean flag = true; ++ + switch (mirror) { + case LEFT_RIGHT: +- z = -z; ++ k = -k; + break; + case FRONT_BACK: +- x = -x; ++ i = -i; + break; + default: + flag = false; + } + +- int x1 = offset.getX(); +- int z1 = offset.getZ(); ++ int l = offset.getX(); ++ int i1 = offset.getZ(); ++ + switch (rotation) { + case COUNTERCLOCKWISE_90: +- return new BlockPos(x1 - z1 + z, y, x1 + z1 - x); ++ return new BlockPos(l - i1 + k, j, l + i1 - i); + case CLOCKWISE_90: +- return new BlockPos(x1 + z1 - z, y, z1 - x1 + x); ++ return new BlockPos(l + i1 - k, j, i1 - l + i); + case CLOCKWISE_180: +- return new BlockPos(x1 + x1 - x, y, z1 + z1 - z); ++ return new BlockPos(l + l - i, j, i1 + i1 - k); + default: +- return flag ? new BlockPos(x, y, z) : targetPos; ++ return flag ? new BlockPos(i, j, k) : targetPos; + } + } + + public static Vec3 transform(Vec3 target, Mirror mirror, Rotation rotation, BlockPos centerOffset) { +- double d = target.x; ++ double d0 = target.x; + double d1 = target.y; + double d2 = target.z; + boolean flag = true; ++ + switch (mirror) { + case LEFT_RIGHT: +- d2 = 1.0 - d2; ++ d2 = 1.0D - d2; + break; + case FRONT_BACK: +- d = 1.0 - d; ++ d0 = 1.0D - d0; + break; + default: + flag = false; + } + +- int x = centerOffset.getX(); +- int z = centerOffset.getZ(); ++ int i = centerOffset.getX(); ++ int j = centerOffset.getZ(); ++ + switch (rotation) { + case COUNTERCLOCKWISE_90: +- return new Vec3((double)(x - z) + d2, d1, (double)(x + z + 1) - d); ++ return new Vec3((double) (i - j) + d2, d1, (double) (i + j + 1) - d0); + case CLOCKWISE_90: +- return new Vec3((double)(x + z + 1) - d2, d1, (double)(z - x) + d); ++ return new Vec3((double) (i + j + 1) - d2, d1, (double) (j - i) + d0); + case CLOCKWISE_180: +- return new Vec3((double)(x + x + 1) - d, d1, (double)(z + z + 1) - d2); ++ return new Vec3((double) (i + i + 1) - d0, d1, (double) (j + j + 1) - d2); + default: +- return flag ? new Vec3(d, d1, d2) : target; ++ return flag ? new Vec3(d0, d1, d2) : target; + } + } + +@@ -534,26 +596,27 @@ + } + + public static BlockPos getZeroPositionWithTransform(BlockPos pos, Mirror mirror, Rotation rotation, int sizeX, int sizeZ) { +- sizeX--; +- sizeZ--; +- int i = mirror == Mirror.FRONT_BACK ? sizeX : 0; +- int i1 = mirror == Mirror.LEFT_RIGHT ? sizeZ : 0; +- BlockPos blockPos = pos; ++ --sizeX; ++ --sizeZ; ++ int k = mirror == Mirror.FRONT_BACK ? sizeX : 0; ++ int l = mirror == Mirror.LEFT_RIGHT ? sizeZ : 0; ++ BlockPos blockposition1 = pos; ++ + switch (rotation) { + case COUNTERCLOCKWISE_90: +- blockPos = pos.offset(i1, 0, sizeX - i); ++ blockposition1 = pos.offset(l, 0, sizeX - k); + break; + case CLOCKWISE_90: +- blockPos = pos.offset(sizeZ - i1, 0, i); ++ blockposition1 = pos.offset(sizeZ - l, 0, k); + break; + case CLOCKWISE_180: +- blockPos = pos.offset(sizeX - i, 0, sizeZ - i1); ++ blockposition1 = pos.offset(sizeX - k, 0, sizeZ - l); + break; + case NONE: +- blockPos = pos.offset(i, 0, i1); ++ blockposition1 = pos.offset(k, 0, l); + } + +- return blockPos; ++ return blockposition1; + } + + public BoundingBox getBoundingBox(StructurePlaceSettings settings, BlockPos startPos) { +@@ -566,10 +629,11 @@ + + @VisibleForTesting + protected static BoundingBox getBoundingBox(BlockPos startPos, Rotation rotation, BlockPos pivotPos, Mirror mirror, Vec3i size) { +- Vec3i vec3i = size.offset(-1, -1, -1); +- BlockPos blockPos = transform(BlockPos.ZERO, mirror, rotation, pivotPos); +- BlockPos blockPos1 = transform(BlockPos.ZERO.offset(vec3i), mirror, rotation, pivotPos); +- return BoundingBox.fromCorners(blockPos, blockPos1).move(startPos); ++ Vec3i baseblockposition1 = size.offset(-1, -1, -1); ++ BlockPos blockposition2 = transform(BlockPos.ZERO, mirror, rotation, pivotPos); ++ BlockPos blockposition3 = transform(BlockPos.ZERO.offset(baseblockposition1), mirror, rotation, pivotPos); ++ ++ return BoundingBox.fromCorners(blockposition2, blockposition3).move(startPos); + } + + public CompoundTag save(CompoundTag tag) { +@@ -578,163 +642,215 @@ + tag.put("palette", new ListTag()); + } else { + List list = Lists.newArrayList(); +- StructureTemplate.SimplePalette simplePalette = new StructureTemplate.SimplePalette(); +- list.add(simplePalette); ++ StructureTemplate.SimplePalette definedstructure_b = new StructureTemplate.SimplePalette(); + +- for (int i = 1; i < this.palettes.size(); i++) { ++ list.add(definedstructure_b); ++ ++ for (int i = 1; i < this.palettes.size(); ++i) { + list.add(new StructureTemplate.SimplePalette()); + } + +- ListTag list1 = new ListTag(); +- List list2 = this.palettes.get(0).blocks(); ++ ListTag nbttaglist = new ListTag(); ++ List list1 = ((StructureTemplate.Palette) this.palettes.get(0)).blocks(); + +- for (int i1 = 0; i1 < list2.size(); i1++) { +- StructureTemplate.StructureBlockInfo structureBlockInfo = list2.get(i1); +- CompoundTag compoundTag = new CompoundTag(); +- compoundTag.put("pos", this.newIntegerList(structureBlockInfo.pos.getX(), structureBlockInfo.pos.getY(), structureBlockInfo.pos.getZ())); +- int i2 = simplePalette.idFor(structureBlockInfo.state); +- compoundTag.putInt("state", i2); +- if (structureBlockInfo.nbt != null) { +- compoundTag.put("nbt", structureBlockInfo.nbt); ++ for (int j = 0; j < list1.size(); ++j) { ++ StructureTemplate.StructureBlockInfo definedstructure_blockinfo = (StructureTemplate.StructureBlockInfo) list1.get(j); ++ CompoundTag nbttagcompound1 = new CompoundTag(); ++ ++ nbttagcompound1.put("pos", this.newIntegerList(definedstructure_blockinfo.pos.getX(), definedstructure_blockinfo.pos.getY(), definedstructure_blockinfo.pos.getZ())); ++ int k = definedstructure_b.idFor(definedstructure_blockinfo.state); ++ ++ nbttagcompound1.putInt("state", k); ++ if (definedstructure_blockinfo.nbt != null) { ++ nbttagcompound1.put("nbt", definedstructure_blockinfo.nbt); + } + +- list1.add(compoundTag); ++ nbttaglist.add(nbttagcompound1); + +- for (int i3 = 1; i3 < this.palettes.size(); i3++) { +- StructureTemplate.SimplePalette simplePalette1 = list.get(i3); +- simplePalette1.addMapping(this.palettes.get(i3).blocks().get(i1).state, i2); ++ for (int l = 1; l < this.palettes.size(); ++l) { ++ StructureTemplate.SimplePalette definedstructure_b1 = (StructureTemplate.SimplePalette) list.get(l); ++ ++ definedstructure_b1.addMapping(((StructureTemplate.StructureBlockInfo) ((StructureTemplate.Palette) this.palettes.get(l)).blocks().get(j)).state, k); + } + } + +- tag.put("blocks", list1); ++ tag.put("blocks", nbttaglist); ++ ListTag nbttaglist1; ++ Iterator iterator; ++ + if (list.size() == 1) { +- ListTag list3 = new ListTag(); ++ nbttaglist1 = new ListTag(); ++ iterator = definedstructure_b.iterator(); + +- for (BlockState blockState : simplePalette) { +- list3.add(NbtUtils.writeBlockState(blockState)); ++ while (iterator.hasNext()) { ++ IBlockData iblockdata = (IBlockData) iterator.next(); ++ ++ nbttaglist1.add(NbtUtils.writeBlockState(iblockdata)); + } + +- tag.put("palette", list3); ++ tag.put("palette", nbttaglist1); + } else { +- ListTag list3 = new ListTag(); ++ nbttaglist1 = new ListTag(); ++ iterator = list.iterator(); + +- for (StructureTemplate.SimplePalette simplePalette2 : list) { +- ListTag list4 = new ListTag(); ++ while (iterator.hasNext()) { ++ StructureTemplate.SimplePalette definedstructure_b2 = (StructureTemplate.SimplePalette) iterator.next(); ++ ListTag nbttaglist2 = new ListTag(); ++ Iterator iterator1 = definedstructure_b2.iterator(); + +- for (BlockState blockState1 : simplePalette2) { +- list4.add(NbtUtils.writeBlockState(blockState1)); ++ while (iterator1.hasNext()) { ++ IBlockData iblockdata1 = (IBlockData) iterator1.next(); ++ ++ nbttaglist2.add(NbtUtils.writeBlockState(iblockdata1)); + } + +- list3.add(list4); ++ nbttaglist1.add(nbttaglist2); + } + +- tag.put("palettes", list3); ++ tag.put("palettes", nbttaglist1); + } + } + +- ListTag list5 = new ListTag(); ++ ListTag nbttaglist3 = new ListTag(); + +- for (StructureTemplate.StructureEntityInfo structureEntityInfo : this.entityInfoList) { +- CompoundTag compoundTag1 = new CompoundTag(); +- compoundTag1.put("pos", this.newDoubleList(structureEntityInfo.pos.x, structureEntityInfo.pos.y, structureEntityInfo.pos.z)); +- compoundTag1.put( +- "blockPos", this.newIntegerList(structureEntityInfo.blockPos.getX(), structureEntityInfo.blockPos.getY(), structureEntityInfo.blockPos.getZ()) +- ); +- if (structureEntityInfo.nbt != null) { +- compoundTag1.put("nbt", structureEntityInfo.nbt); +- } ++ CompoundTag nbttagcompound2; + +- list5.add(compoundTag1); ++ for (Iterator iterator2 = this.entityInfoList.iterator(); iterator2.hasNext(); nbttaglist3.add(nbttagcompound2)) { ++ StructureTemplate.StructureEntityInfo definedstructure_entityinfo = (StructureTemplate.StructureEntityInfo) iterator2.next(); ++ ++ nbttagcompound2 = new CompoundTag(); ++ nbttagcompound2.put("pos", this.newDoubleList(definedstructure_entityinfo.pos.x, definedstructure_entityinfo.pos.y, definedstructure_entityinfo.pos.z)); ++ nbttagcompound2.put("blockPos", this.newIntegerList(definedstructure_entityinfo.blockPos.getX(), definedstructure_entityinfo.blockPos.getY(), definedstructure_entityinfo.blockPos.getZ())); ++ if (definedstructure_entityinfo.nbt != null) { ++ nbttagcompound2.put("nbt", definedstructure_entityinfo.nbt); ++ } + } + +- tag.put("entities", list5); ++ tag.put("entities", nbttaglist3); + tag.put("size", this.newIntegerList(this.size.getX(), this.size.getY(), this.size.getZ())); ++ // CraftBukkit start - PDC ++ if (!this.persistentDataContainer.isEmpty()) { ++ tag.put("BukkitValues", this.persistentDataContainer.toTagCompound()); ++ } ++ // CraftBukkit end + return NbtUtils.addCurrentDataVersion(tag); + } + + public void load(HolderGetter blockGetter, CompoundTag tag) { + this.palettes.clear(); + this.entityInfoList.clear(); +- ListTag list = tag.getList("size", 3); +- this.size = new Vec3i(list.getInt(0), list.getInt(1), list.getInt(2)); +- ListTag list1 = tag.getList("blocks", 10); ++ ListTag nbttaglist = tag.getList("size", 3); ++ ++ this.size = new Vec3i(nbttaglist.getInt(0), nbttaglist.getInt(1), nbttaglist.getInt(2)); ++ ListTag nbttaglist1 = tag.getList("blocks", 10); ++ ListTag nbttaglist2; ++ int i; ++ + if (tag.contains("palettes", 9)) { +- ListTag list2 = tag.getList("palettes", 9); ++ nbttaglist2 = tag.getList("palettes", 9); + +- for (int i = 0; i < list2.size(); i++) { +- this.loadPalette(blockGetter, list2.getList(i), list1); ++ for (i = 0; i < nbttaglist2.size(); ++i) { ++ this.loadPalette(blockGetter, nbttaglist2.getList(i), nbttaglist1); + } + } else { +- this.loadPalette(blockGetter, tag.getList("palette", 10), list1); ++ this.loadPalette(blockGetter, tag.getList("palette", 10), nbttaglist1); + } + +- ListTag list2 = tag.getList("entities", 10); ++ nbttaglist2 = tag.getList("entities", 10); + +- for (int i = 0; i < list2.size(); i++) { +- CompoundTag compound = list2.getCompound(i); +- ListTag list3 = compound.getList("pos", 6); +- Vec3 vec3 = new Vec3(list3.getDouble(0), list3.getDouble(1), list3.getDouble(2)); +- ListTag list4 = compound.getList("blockPos", 3); +- BlockPos blockPos = new BlockPos(list4.getInt(0), list4.getInt(1), list4.getInt(2)); +- if (compound.contains("nbt")) { +- CompoundTag compound1 = compound.getCompound("nbt"); +- this.entityInfoList.add(new StructureTemplate.StructureEntityInfo(vec3, blockPos, compound1)); ++ for (i = 0; i < nbttaglist2.size(); ++i) { ++ CompoundTag nbttagcompound1 = nbttaglist2.getCompound(i); ++ ListTag nbttaglist3 = nbttagcompound1.getList("pos", 6); ++ Vec3 vec3d = new Vec3(nbttaglist3.getDouble(0), nbttaglist3.getDouble(1), nbttaglist3.getDouble(2)); ++ ListTag nbttaglist4 = nbttagcompound1.getList("blockPos", 3); ++ BlockPos blockposition = new BlockPos(nbttaglist4.getInt(0), nbttaglist4.getInt(1), nbttaglist4.getInt(2)); ++ ++ if (nbttagcompound1.contains("nbt")) { ++ CompoundTag nbttagcompound2 = nbttagcompound1.getCompound("nbt"); ++ ++ this.entityInfoList.add(new StructureTemplate.StructureEntityInfo(vec3d, blockposition, nbttagcompound2)); + } + } ++ ++ // CraftBukkit start - PDC ++ Tag base = tag.get("BukkitValues"); ++ if (base instanceof CompoundTag) { ++ this.persistentDataContainer.putAll((CompoundTag) base); ++ } ++ // CraftBukkit end + } + + private void loadPalette(HolderGetter blockGetter, ListTag paletteTag, ListTag blocksTag) { +- StructureTemplate.SimplePalette simplePalette = new StructureTemplate.SimplePalette(); ++ StructureTemplate.SimplePalette definedstructure_b = new StructureTemplate.SimplePalette(); + +- for (int i = 0; i < paletteTag.size(); i++) { +- simplePalette.addMapping(NbtUtils.readBlockState(blockGetter, paletteTag.getCompound(i)), i); ++ for (int i = 0; i < paletteTag.size(); ++i) { ++ definedstructure_b.addMapping(NbtUtils.readBlockState(blockGetter, paletteTag.getCompound(i)), i); + } + + List list = Lists.newArrayList(); + List list1 = Lists.newArrayList(); + List list2 = Lists.newArrayList(); + +- for (int i1 = 0; i1 < blocksTag.size(); i1++) { +- CompoundTag compound = blocksTag.getCompound(i1); +- ListTag list3 = compound.getList("pos", 3); +- BlockPos blockPos = new BlockPos(list3.getInt(0), list3.getInt(1), list3.getInt(2)); +- BlockState blockState = simplePalette.stateFor(compound.getInt("state")); +- CompoundTag compound1; +- if (compound.contains("nbt")) { +- compound1 = compound.getCompound("nbt"); ++ for (int j = 0; j < blocksTag.size(); ++j) { ++ CompoundTag nbttagcompound = blocksTag.getCompound(j); ++ ListTag nbttaglist2 = nbttagcompound.getList("pos", 3); ++ BlockPos blockposition = new BlockPos(nbttaglist2.getInt(0), nbttaglist2.getInt(1), nbttaglist2.getInt(2)); ++ IBlockData iblockdata = definedstructure_b.stateFor(nbttagcompound.getInt("state")); ++ CompoundTag nbttagcompound1; ++ ++ if (nbttagcompound.contains("nbt")) { ++ nbttagcompound1 = nbttagcompound.getCompound("nbt"); + } else { +- compound1 = null; ++ nbttagcompound1 = null; + } + +- StructureTemplate.StructureBlockInfo structureBlockInfo = new StructureTemplate.StructureBlockInfo(blockPos, blockState, compound1); +- addToLists(structureBlockInfo, list, list1, list2); ++ StructureTemplate.StructureBlockInfo definedstructure_blockinfo = new StructureTemplate.StructureBlockInfo(blockposition, iblockdata, nbttagcompound1); ++ ++ addToLists(definedstructure_blockinfo, list, list1, list2); + } + +- List list4 = buildInfoList(list, list1, list2); +- this.palettes.add(new StructureTemplate.Palette(list4)); ++ List list3 = buildInfoList(list, list1, list2); ++ ++ this.palettes.add(new StructureTemplate.Palette(list3)); + } + + private ListTag newIntegerList(int... values) { +- ListTag list = new ListTag(); ++ ListTag nbttaglist = new ListTag(); ++ int[] aint1 = values; ++ int i = values.length; + +- for (int i : values) { +- list.add(IntTag.valueOf(i)); ++ for (int j = 0; j < i; ++j) { ++ int k = aint1[j]; ++ ++ nbttaglist.add(IntTag.valueOf(k)); + } + +- return list; ++ return nbttaglist; + } + + private ListTag newDoubleList(double... values) { +- ListTag list = new ListTag(); ++ ListTag nbttaglist = new ListTag(); ++ double[] adouble1 = values; ++ int i = values.length; + +- for (double d : values) { +- list.add(DoubleTag.valueOf(d)); ++ for (int j = 0; j < i; ++j) { ++ double d0 = adouble1[j]; ++ ++ nbttaglist.add(DoubleTag.valueOf(d0)); + } + +- return list; ++ return nbttaglist; + } + ++ public static record StructureBlockInfo(BlockPos pos, IBlockData state, @Nullable CompoundTag nbt) { ++ ++ public String toString() { ++ return String.format(Locale.ROOT, "", this.pos, this.state, this.nbt); ++ } ++ } ++ + public static final class Palette { ++ + private final List blocks; + private final Map> cache = Maps.newHashMap(); + +@@ -747,60 +863,59 @@ + } + + public List blocks(Block block) { +- return this.cache +- .computeIfAbsent( +- block, block1 -> this.blocks.stream().filter(structureBlockInfo -> structureBlockInfo.state.is(block1)).collect(Collectors.toList()) +- ); ++ return (List) this.cache.computeIfAbsent(block, (block1) -> { ++ return (List) this.blocks.stream().filter((definedstructure_blockinfo) -> { ++ return definedstructure_blockinfo.state.is(block1); ++ }).collect(Collectors.toList()); ++ }); + } + } + +- static class SimplePalette implements Iterable { +- public static final BlockState DEFAULT_BLOCK_STATE = Blocks.AIR.defaultBlockState(); +- private final IdMapper ids = new IdMapper<>(16); ++ public static class StructureEntityInfo { ++ ++ public final Vec3 pos; ++ public final BlockPos blockPos; ++ public final CompoundTag nbt; ++ ++ public StructureEntityInfo(Vec3 pos, BlockPos blockPos, CompoundTag nbt) { ++ this.pos = pos; ++ this.blockPos = blockPos; ++ this.nbt = nbt; ++ } ++ } ++ ++ private static class SimplePalette implements Iterable { ++ ++ public static final IBlockData DEFAULT_BLOCK_STATE = Blocks.AIR.defaultBlockState(); ++ private final IdMapper ids = new IdMapper<>(16); + private int lastId; + +- public int idFor(BlockState state) { +- int id = this.ids.getId(state); +- if (id == -1) { +- id = this.lastId++; +- this.ids.addMapping(state, id); ++ SimplePalette() {} ++ ++ public int idFor(IBlockData state) { ++ int i = this.ids.getId(state); ++ ++ if (i == -1) { ++ i = this.lastId++; ++ this.ids.addMapping(state, i); + } + +- return id; ++ return i; + } + + @Nullable +- public BlockState stateFor(int id) { +- BlockState blockState = this.ids.byId(id); +- return blockState == null ? DEFAULT_BLOCK_STATE : blockState; ++ public IBlockData stateFor(int id) { ++ IBlockData iblockdata = (IBlockData) this.ids.byId(id); ++ ++ return iblockdata == null ? DEFAULT_BLOCK_STATE : iblockdata; // CraftBukkit - decompile error + } + +- @Override +- public Iterator iterator() { ++ public Iterator iterator() { + return this.ids.iterator(); + } + +- public void addMapping(BlockState state, int id) { ++ public void addMapping(IBlockData state, int id) { + this.ids.addMapping(state, id); + } + } +- +- public static record StructureBlockInfo(BlockPos pos, BlockState state, @Nullable CompoundTag nbt) { +- @Override +- public String toString() { +- return String.format(Locale.ROOT, "", this.pos, this.state, this.nbt); +- } +- } +- +- public static class StructureEntityInfo { +- public final Vec3 pos; +- public final BlockPos blockPos; +- public final CompoundTag nbt; +- +- public StructureEntityInfo(Vec3 pos, BlockPos blockPos, CompoundTag nbt) { +- this.pos = pos; +- this.blockPos = blockPos; +- this.nbt = nbt; +- } +- } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/material/FlowingFluid.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/material/FlowingFluid.java.patch new file mode 100644 index 0000000000..74b87828a0 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/material/FlowingFluid.java.patch @@ -0,0 +1,718 @@ +--- a/net/minecraft/world/level/material/FlowingFluid.java ++++ b/net/minecraft/world/level/material/FlowingFluid.java +@@ -7,11 +7,13 @@ + import it.unimi.dsi.fastutil.shorts.Short2BooleanOpenHashMap; + import it.unimi.dsi.fastutil.shorts.Short2ObjectMap; + import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap; ++import java.util.Iterator; + import java.util.Map; + import java.util.Map.Entry; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.tags.BlockTags; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; +@@ -21,7 +23,7 @@ + import net.minecraft.world.level.block.DoorBlock; + import net.minecraft.world.level.block.IceBlock; + import net.minecraft.world.level.block.LiquidBlockContainer; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.block.state.properties.BooleanProperty; +@@ -29,73 +31,94 @@ + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.block.BlockFace; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.block.BlockFromToEvent; ++import org.bukkit.event.block.FluidLevelChangeEvent; ++// CraftBukkit end + + public abstract class FlowingFluid extends Fluid { ++ + public static final BooleanProperty FALLING = BlockStateProperties.FALLING; + public static final IntegerProperty LEVEL = BlockStateProperties.LEVEL_FLOWING; + private static final int CACHE_SIZE = 200; + private static final ThreadLocal> OCCLUSION_CACHE = ThreadLocal.withInitial(() -> { +- Object2ByteLinkedOpenHashMap map = new Object2ByteLinkedOpenHashMap(200) { +- @Override +- protected void rehash(int newSize) { +- } ++ Object2ByteLinkedOpenHashMap object2bytelinkedopenhashmap = new Object2ByteLinkedOpenHashMap(200) { ++ protected void rehash(int i) {} + }; +- map.defaultReturnValue((byte)127); +- return map; ++ ++ object2bytelinkedopenhashmap.defaultReturnValue((byte) 127); ++ return object2bytelinkedopenhashmap; + }); + private final Map shapes = Maps.newIdentityHashMap(); + ++ public FlowingFluid() {} ++ + @Override + protected void createFluidStateDefinition(StateDefinition.Builder builder) { +- builder.add(FALLING); ++ builder.add(FlowingFluid.FALLING); + } + + @Override + public Vec3 getFlow(BlockGetter blockReader, BlockPos pos, FluidState fluidState) { +- double d = 0.0; +- double d1 = 0.0; +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ double d0 = 0.0D; ++ double d1 = 0.0D; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- mutableBlockPos.setWithOffset(pos, direction); +- FluidState fluidState1 = blockReader.getFluidState(mutableBlockPos); +- if (this.affectsFlow(fluidState1)) { +- float ownHeight = fluidState1.getOwnHeight(); +- float f = 0.0F; +- if (ownHeight == 0.0F) { +- if (!blockReader.getBlockState(mutableBlockPos).blocksMotion()) { +- BlockPos blockPos = mutableBlockPos.below(); +- FluidState fluidState2 = blockReader.getFluidState(blockPos); +- if (this.affectsFlow(fluidState2)) { +- ownHeight = fluidState2.getOwnHeight(); +- if (ownHeight > 0.0F) { +- f = fluidState.getOwnHeight() - (ownHeight - 0.8888889F); ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ ++ blockposition_mutableblockposition.setWithOffset(pos, enumdirection); ++ FluidState fluid1 = blockReader.getFluidState(blockposition_mutableblockposition); ++ ++ if (this.affectsFlow(fluid1)) { ++ float f = fluid1.getOwnHeight(); ++ float f1 = 0.0F; ++ ++ if (f == 0.0F) { ++ if (!blockReader.getBlockState(blockposition_mutableblockposition).blocksMotion()) { ++ BlockPos blockposition1 = blockposition_mutableblockposition.below(); ++ FluidState fluid2 = blockReader.getFluidState(blockposition1); ++ ++ if (this.affectsFlow(fluid2)) { ++ f = fluid2.getOwnHeight(); ++ if (f > 0.0F) { ++ f1 = fluidState.getOwnHeight() - (f - 0.8888889F); + } + } + } +- } else if (ownHeight > 0.0F) { +- f = fluidState.getOwnHeight() - ownHeight; ++ } else if (f > 0.0F) { ++ f1 = fluidState.getOwnHeight() - f; + } + +- if (f != 0.0F) { +- d += (double)((float)direction.getStepX() * f); +- d1 += (double)((float)direction.getStepZ() * f); ++ if (f1 != 0.0F) { ++ d0 += (double) ((float) enumdirection.getStepX() * f1); ++ d1 += (double) ((float) enumdirection.getStepZ() * f1); + } + } + } + +- Vec3 vec3 = new Vec3(d, 0.0, d1); +- if (fluidState.getValue(FALLING)) { +- for (Direction direction1 : Direction.Plane.HORIZONTAL) { +- mutableBlockPos.setWithOffset(pos, direction1); +- if (this.isSolidFace(blockReader, mutableBlockPos, direction1) || this.isSolidFace(blockReader, mutableBlockPos.above(), direction1)) { +- vec3 = vec3.normalize().add(0.0, -6.0, 0.0); ++ Vec3 vec3d = new Vec3(d0, 0.0D, d1); ++ ++ if ((Boolean) fluidState.getValue(FlowingFluid.FALLING)) { ++ Iterator iterator1 = Direction.Plane.HORIZONTAL.iterator(); ++ ++ while (iterator1.hasNext()) { ++ Direction enumdirection1 = (Direction) iterator1.next(); ++ ++ blockposition_mutableblockposition.setWithOffset(pos, enumdirection1); ++ if (this.isSolidFace(blockReader, blockposition_mutableblockposition, enumdirection1) || this.isSolidFace(blockReader, blockposition_mutableblockposition.above(), enumdirection1)) { ++ vec3d = vec3d.normalize().add(0.0D, -6.0D, 0.0D); + break; + } + } + } + +- return vec3.normalize(); ++ return vec3d.normalize(); + } + + private boolean affectsFlow(FluidState state) { +@@ -103,116 +126,149 @@ + } + + protected boolean isSolidFace(BlockGetter level, BlockPos neighborPos, Direction side) { +- BlockState blockState = level.getBlockState(neighborPos); +- FluidState fluidState = level.getFluidState(neighborPos); +- return !fluidState.getType().isSame(this) +- && (side == Direction.UP || !(blockState.getBlock() instanceof IceBlock) && blockState.isFaceSturdy(level, neighborPos, side)); ++ IBlockData iblockdata = level.getBlockState(neighborPos); ++ FluidState fluid = level.getFluidState(neighborPos); ++ ++ return fluid.getType().isSame(this) ? false : (side == Direction.UP ? true : (iblockdata.getBlock() instanceof IceBlock ? false : iblockdata.isFaceSturdy(level, neighborPos, side))); + } + + protected void spread(Level level, BlockPos pos, FluidState state) { + if (!state.isEmpty()) { +- BlockState blockState = level.getBlockState(pos); +- BlockPos blockPos = pos.below(); +- BlockState blockState1 = level.getBlockState(blockPos); +- FluidState newLiquid = this.getNewLiquid(level, blockPos, blockState1); +- if (this.canSpreadTo(level, pos, blockState, Direction.DOWN, blockPos, blockState1, level.getFluidState(blockPos), newLiquid.getType())) { +- this.spreadTo(level, blockPos, blockState1, Direction.DOWN, newLiquid); ++ IBlockData iblockdata = level.getBlockState(pos); ++ BlockPos blockposition1 = pos.below(); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ FluidState fluid1 = this.getNewLiquid(level, blockposition1, iblockdata1); ++ ++ if (this.canSpreadTo(level, pos, iblockdata, Direction.DOWN, blockposition1, iblockdata1, level.getFluidState(blockposition1), fluid1.getType())) { ++ // CraftBukkit start ++ org.bukkit.block.Block source = CraftBlock.at(level, pos); ++ BlockFromToEvent event = new BlockFromToEvent(source, BlockFace.DOWN); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ this.spreadTo(level, blockposition1, iblockdata1, Direction.DOWN, fluid1); + if (this.sourceNeighborCount(level, pos) >= 3) { +- this.spreadToSides(level, pos, state, blockState); ++ this.spreadToSides(level, pos, state, iblockdata); + } +- } else if (state.isSource() || !this.isWaterHole(level, newLiquid.getType(), pos, blockState, blockPos, blockState1)) { +- this.spreadToSides(level, pos, state, blockState); ++ } else if (state.isSource() || !this.isWaterHole(level, fluid1.getType(), pos, iblockdata, blockposition1, iblockdata1)) { ++ this.spreadToSides(level, pos, state, iblockdata); + } ++ + } + } + +- private void spreadToSides(Level level, BlockPos pos, FluidState fluidState, BlockState blockState) { ++ private void spreadToSides(Level level, BlockPos pos, FluidState fluidState, IBlockData blockState) { + int i = fluidState.getAmount() - this.getDropOff(level); +- if (fluidState.getValue(FALLING)) { ++ ++ if ((Boolean) fluidState.getValue(FlowingFluid.FALLING)) { + i = 7; + } + + if (i > 0) { +- Map spread = this.getSpread(level, pos, blockState); ++ Map map = this.getSpread(level, pos, blockState); ++ Iterator iterator = map.entrySet().iterator(); + +- for (Entry entry : spread.entrySet()) { +- Direction direction = entry.getKey(); +- FluidState fluidState1 = entry.getValue(); +- BlockPos blockPos = pos.relative(direction); +- BlockState blockState1 = level.getBlockState(blockPos); +- if (this.canSpreadTo(level, pos, blockState, direction, blockPos, blockState1, level.getFluidState(blockPos), fluidState1.getType())) { +- this.spreadTo(level, blockPos, blockState1, direction, fluidState1); ++ while (iterator.hasNext()) { ++ Entry entry = (Entry) iterator.next(); ++ Direction enumdirection = (Direction) entry.getKey(); ++ FluidState fluid1 = (FluidState) entry.getValue(); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ if (this.canSpreadTo(level, pos, blockState, enumdirection, blockposition1, iblockdata1, level.getFluidState(blockposition1), fluid1.getType())) { ++ // CraftBukkit start ++ org.bukkit.block.Block source = CraftBlock.at(level, pos); ++ BlockFromToEvent event = new BlockFromToEvent(source, org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(enumdirection)); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end ++ this.spreadTo(level, blockposition1, iblockdata1, enumdirection, fluid1); + } + } ++ + } + } + +- protected FluidState getNewLiquid(Level level, BlockPos pos, BlockState blockState) { ++ protected FluidState getNewLiquid(Level level, BlockPos pos, IBlockData blockState) { + int i = 0; +- int i1 = 0; ++ int j = 0; ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- BlockPos blockPos = pos.relative(direction); +- BlockState blockState1 = level.getBlockState(blockPos); +- FluidState fluidState = blockState1.getFluidState(); +- if (fluidState.getType().isSame(this) && this.canPassThroughWall(direction, level, pos, blockState, blockPos, blockState1)) { +- if (fluidState.isSource()) { +- i1++; ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ FluidState fluid = iblockdata1.getFluidState(); ++ ++ if (fluid.getType().isSame(this) && this.canPassThroughWall(enumdirection, level, pos, blockState, blockposition1, iblockdata1)) { ++ if (fluid.isSource()) { ++ ++j; + } + +- i = Math.max(i, fluidState.getAmount()); ++ i = Math.max(i, fluid.getAmount()); + } + } + +- if (this.canConvertToSource(level) && i1 >= 2) { +- BlockState blockState2 = level.getBlockState(pos.below()); +- FluidState fluidState1 = blockState2.getFluidState(); +- if (blockState2.isSolid() || this.isSourceBlockOfThisType(fluidState1)) { ++ if (this.canConvertToSource(level) && j >= 2) { ++ IBlockData iblockdata2 = level.getBlockState(pos.below()); ++ FluidState fluid1 = iblockdata2.getFluidState(); ++ ++ if (iblockdata2.isSolid() || this.isSourceBlockOfThisType(fluid1)) { + return this.getSource(false); + } + } + +- BlockPos blockPos1 = pos.above(); +- BlockState blockState3 = level.getBlockState(blockPos1); +- FluidState fluidState2 = blockState3.getFluidState(); +- if (!fluidState2.isEmpty() +- && fluidState2.getType().isSame(this) +- && this.canPassThroughWall(Direction.UP, level, pos, blockState, blockPos1, blockState3)) { ++ BlockPos blockposition2 = pos.above(); ++ IBlockData iblockdata3 = level.getBlockState(blockposition2); ++ FluidState fluid2 = iblockdata3.getFluidState(); ++ ++ if (!fluid2.isEmpty() && fluid2.getType().isSame(this) && this.canPassThroughWall(Direction.UP, level, pos, blockState, blockposition2, iblockdata3)) { + return this.getFlowing(8, true); + } else { +- int i2 = i - this.getDropOff(level); +- return i2 <= 0 ? Fluids.EMPTY.defaultFluidState() : this.getFlowing(i2, false); ++ int k = i - this.getDropOff(level); ++ ++ return k <= 0 ? Fluids.EMPTY.defaultFluidState() : this.getFlowing(k, false); + } + } + +- private boolean canPassThroughWall(Direction direction, BlockGetter level, BlockPos pos, BlockState state, BlockPos spreadPos, BlockState spreadState) { +- Object2ByteLinkedOpenHashMap map; ++ private boolean canPassThroughWall(Direction direction, BlockGetter level, BlockPos pos, IBlockData state, BlockPos spreadPos, IBlockData spreadState) { ++ Object2ByteLinkedOpenHashMap object2bytelinkedopenhashmap; ++ + if (!state.getBlock().hasDynamicShape() && !spreadState.getBlock().hasDynamicShape()) { +- map = OCCLUSION_CACHE.get(); ++ object2bytelinkedopenhashmap = (Object2ByteLinkedOpenHashMap) FlowingFluid.OCCLUSION_CACHE.get(); + } else { +- map = null; ++ object2bytelinkedopenhashmap = null; + } + +- Block.BlockStatePairKey blockStatePairKey; +- if (map != null) { +- blockStatePairKey = new Block.BlockStatePairKey(state, spreadState, direction); +- byte andMoveToFirst = map.getAndMoveToFirst(blockStatePairKey); +- if (andMoveToFirst != 127) { +- return andMoveToFirst != 0; ++ Block.BlockStatePairKey block_a; ++ ++ if (object2bytelinkedopenhashmap != null) { ++ block_a = new Block.BlockStatePairKey(state, spreadState, direction); ++ byte b0 = object2bytelinkedopenhashmap.getAndMoveToFirst(block_a); ++ ++ if (b0 != 127) { ++ return b0 != 0; + } + } else { +- blockStatePairKey = null; ++ block_a = null; + } + +- VoxelShape collisionShape = state.getCollisionShape(level, pos); +- VoxelShape collisionShape1 = spreadState.getCollisionShape(level, spreadPos); +- boolean flag = !Shapes.mergedFaceOccludes(collisionShape, collisionShape1, direction); +- if (map != null) { +- if (map.size() == 200) { +- map.removeLastByte(); ++ VoxelShape voxelshape = state.getCollisionShape(level, pos); ++ VoxelShape voxelshape1 = spreadState.getCollisionShape(level, spreadPos); ++ boolean flag = !Shapes.mergedFaceOccludes(voxelshape, voxelshape1, direction); ++ ++ if (object2bytelinkedopenhashmap != null) { ++ if (object2bytelinkedopenhashmap.size() == 200) { ++ object2bytelinkedopenhashmap.removeLastByte(); + } + +- map.putAndMoveToFirst(blockStatePairKey, (byte)(flag ? 1 : 0)); ++ object2bytelinkedopenhashmap.putAndMoveToFirst(block_a, (byte) (flag ? 1 : 0)); + } + + return flag; +@@ -221,20 +277,20 @@ + public abstract Fluid getFlowing(); + + public FluidState getFlowing(int level, boolean falling) { +- return this.getFlowing().defaultFluidState().setValue(LEVEL, Integer.valueOf(level)).setValue(FALLING, Boolean.valueOf(falling)); ++ return (FluidState) ((FluidState) this.getFlowing().defaultFluidState().setValue(FlowingFluid.LEVEL, level)).setValue(FlowingFluid.FALLING, falling); + } + + public abstract Fluid getSource(); + + public FluidState getSource(boolean falling) { +- return this.getSource().defaultFluidState().setValue(FALLING, Boolean.valueOf(falling)); ++ return (FluidState) this.getSource().defaultFluidState().setValue(FlowingFluid.FALLING, falling); + } + + protected abstract boolean canConvertToSource(Level level); + +- protected void spreadTo(LevelAccessor level, BlockPos pos, BlockState blockState, Direction direction, FluidState fluidState) { ++ protected void spreadTo(LevelAccessor level, BlockPos pos, IBlockData blockState, Direction direction, FluidState fluidState) { + if (blockState.getBlock() instanceof LiquidBlockContainer) { +- ((LiquidBlockContainer)blockState.getBlock()).placeLiquid(level, pos, blockState, fluidState); ++ ((LiquidBlockContainer) blockState.getBlock()).placeLiquid(level, pos, blockState, fluidState); + } else { + if (!blockState.isAir()) { + this.beforeDestroyingBlock(level, pos, blockState); +@@ -242,74 +298,68 @@ + + level.setBlock(pos, fluidState.createLegacyBlock(), 3); + } ++ + } + +- protected abstract void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, BlockState state); ++ protected abstract void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, IBlockData state); + + private static short getCacheKey(BlockPos sourcePos, BlockPos spreadPos) { + int i = spreadPos.getX() - sourcePos.getX(); +- int i1 = spreadPos.getZ() - sourcePos.getZ(); +- return (short)((i + 128 & 0xFF) << 8 | i1 + 128 & 0xFF); ++ int j = spreadPos.getZ() - sourcePos.getZ(); ++ ++ return (short) ((i + 128 & 255) << 8 | j + 128 & 255); + } + +- protected int getSlopeDistance( +- LevelReader level, +- BlockPos spreadPos, +- int distance, +- Direction direction, +- BlockState currentSpreadState, +- BlockPos sourcePos, +- Short2ObjectMap> stateCache, +- Short2BooleanMap waterHoleCache +- ) { +- int i = 1000; ++ protected int getSlopeDistance(LevelReader level, BlockPos spreadPos, int distance, Direction direction, IBlockData currentSpreadState, BlockPos sourcePos, Short2ObjectMap> stateCache, Short2BooleanMap waterHoleCache) { ++ int j = 1000; ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction direction1 : Direction.Plane.HORIZONTAL) { +- if (direction1 != direction) { +- BlockPos blockPos = spreadPos.relative(direction1); +- short cacheKey = getCacheKey(sourcePos, blockPos); +- Pair pair = stateCache.computeIfAbsent(cacheKey, key -> { +- BlockState blockState1 = level.getBlockState(blockPos); +- return Pair.of(blockState1, blockState1.getFluidState()); ++ while (iterator.hasNext()) { ++ Direction enumdirection1 = (Direction) iterator.next(); ++ ++ if (enumdirection1 != direction) { ++ BlockPos blockposition2 = spreadPos.relative(enumdirection1); ++ short short0 = getCacheKey(sourcePos, blockposition2); ++ Pair pair = (Pair) stateCache.computeIfAbsent(short0, (short1) -> { ++ IBlockData iblockdata1 = level.getBlockState(blockposition2); ++ ++ return Pair.of(iblockdata1, iblockdata1.getFluidState()); + }); +- BlockState blockState = pair.getFirst(); +- FluidState fluidState = pair.getSecond(); +- if (this.canPassThrough(level, this.getFlowing(), spreadPos, currentSpreadState, direction1, blockPos, blockState, fluidState)) { +- boolean flag = waterHoleCache.computeIfAbsent(cacheKey, key -> { +- BlockPos blockPos1 = blockPos.below(); +- BlockState blockState1 = level.getBlockState(blockPos1); +- return this.isWaterHole(level, this.getFlowing(), blockPos, blockState, blockPos1, blockState1); ++ IBlockData iblockdata1 = (IBlockData) pair.getFirst(); ++ FluidState fluid = (FluidState) pair.getSecond(); ++ ++ if (this.canPassThrough(level, this.getFlowing(), spreadPos, currentSpreadState, enumdirection1, blockposition2, iblockdata1, fluid)) { ++ boolean flag = waterHoleCache.computeIfAbsent(short0, (short1) -> { ++ BlockPos blockposition3 = blockposition2.below(); ++ IBlockData iblockdata2 = level.getBlockState(blockposition3); ++ ++ return this.isWaterHole(level, this.getFlowing(), blockposition2, iblockdata1, blockposition3, iblockdata2); + }); ++ + if (flag) { + return distance; + } + + if (distance < this.getSlopeFindDistance(level)) { +- int slopeDistance = this.getSlopeDistance( +- level, blockPos, distance + 1, direction1.getOpposite(), blockState, sourcePos, stateCache, waterHoleCache +- ); +- if (slopeDistance < i) { +- i = slopeDistance; ++ int k = this.getSlopeDistance(level, blockposition2, distance + 1, enumdirection1.getOpposite(), iblockdata1, sourcePos, stateCache, waterHoleCache); ++ ++ if (k < j) { ++ j = k; + } + } + } + } + } + +- return i; ++ return j; + } + +- private boolean isWaterHole(BlockGetter level, Fluid fluid, BlockPos pos, BlockState state, BlockPos spreadPos, BlockState spreadState) { +- return this.canPassThroughWall(Direction.DOWN, level, pos, state, spreadPos, spreadState) +- && (spreadState.getFluidState().getType().isSame(this) || this.canHoldFluid(level, spreadPos, spreadState, fluid)); ++ private boolean isWaterHole(BlockGetter level, Fluid fluid, BlockPos pos, IBlockData state, BlockPos spreadPos, IBlockData spreadState) { ++ return !this.canPassThroughWall(Direction.DOWN, level, pos, state, spreadPos, spreadState) ? false : (spreadState.getFluidState().getType().isSame(this) ? true : this.canHoldFluid(level, spreadPos, spreadState, fluid)); + } + +- private boolean canPassThrough( +- BlockGetter level, Fluid fluid, BlockPos pos, BlockState state, Direction direction, BlockPos spreadPos, BlockState spreadState, FluidState fluidState +- ) { +- return !this.isSourceBlockOfThisType(fluidState) +- && this.canPassThroughWall(direction, level, pos, state, spreadPos, spreadState) +- && this.canHoldFluid(level, spreadPos, spreadState, fluid); ++ private boolean canPassThrough(BlockGetter level, Fluid fluid, BlockPos pos, IBlockData state, Direction direction, BlockPos spreadPos, IBlockData spreadState, FluidState fluidState) { ++ return !this.isSourceBlockOfThisType(fluidState) && this.canPassThroughWall(direction, level, pos, state, spreadPos, spreadState) && this.canHoldFluid(level, spreadPos, spreadState, fluid); + } + + private boolean isSourceBlockOfThisType(FluidState state) { +@@ -320,54 +370,63 @@ + + private int sourceNeighborCount(LevelReader level, BlockPos pos) { + int i = 0; ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- BlockPos blockPos = pos.relative(direction); +- FluidState fluidState = level.getFluidState(blockPos); +- if (this.isSourceBlockOfThisType(fluidState)) { +- i++; ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ FluidState fluid = level.getFluidState(blockposition1); ++ ++ if (this.isSourceBlockOfThisType(fluid)) { ++ ++i; + } + } + + return i; + } + +- protected Map getSpread(Level level, BlockPos pos, BlockState state) { ++ protected Map getSpread(Level level, BlockPos pos, IBlockData state) { + int i = 1000; + Map map = Maps.newEnumMap(Direction.class); +- Short2ObjectMap> map1 = new Short2ObjectOpenHashMap<>(); +- Short2BooleanMap map2 = new Short2BooleanOpenHashMap(); ++ Short2ObjectMap> short2objectmap = new Short2ObjectOpenHashMap(); ++ Short2BooleanOpenHashMap short2booleanopenhashmap = new Short2BooleanOpenHashMap(); ++ Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); + +- for (Direction direction : Direction.Plane.HORIZONTAL) { +- BlockPos blockPos = pos.relative(direction); +- short cacheKey = getCacheKey(pos, blockPos); +- Pair pair = map1.computeIfAbsent(cacheKey, key -> { +- BlockState blockState1 = level.getBlockState(blockPos); +- return Pair.of(blockState1, blockState1.getFluidState()); ++ while (iterator.hasNext()) { ++ Direction enumdirection = (Direction) iterator.next(); ++ BlockPos blockposition1 = pos.relative(enumdirection); ++ short short0 = getCacheKey(pos, blockposition1); ++ Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (short1) -> { ++ IBlockData iblockdata1 = level.getBlockState(blockposition1); ++ ++ return Pair.of(iblockdata1, iblockdata1.getFluidState()); + }); +- BlockState blockState = pair.getFirst(); +- FluidState fluidState = pair.getSecond(); +- FluidState newLiquid = this.getNewLiquid(level, blockPos, blockState); +- if (this.canPassThrough(level, newLiquid.getType(), pos, state, direction, blockPos, blockState, fluidState)) { +- BlockPos blockPos1 = blockPos.below(); +- boolean flag = map2.computeIfAbsent(cacheKey, key -> { +- BlockState blockState1 = level.getBlockState(blockPos1); +- return this.isWaterHole(level, this.getFlowing(), blockPos, blockState, blockPos1, blockState1); ++ IBlockData iblockdata1 = (IBlockData) pair.getFirst(); ++ FluidState fluid = (FluidState) pair.getSecond(); ++ FluidState fluid1 = this.getNewLiquid(level, blockposition1, iblockdata1); ++ ++ if (this.canPassThrough(level, fluid1.getType(), pos, state, enumdirection, blockposition1, iblockdata1, fluid)) { ++ BlockPos blockposition2 = blockposition1.below(); ++ boolean flag = short2booleanopenhashmap.computeIfAbsent(short0, (short1) -> { ++ IBlockData iblockdata2 = level.getBlockState(blockposition2); ++ ++ return this.isWaterHole(level, this.getFlowing(), blockposition1, iblockdata1, blockposition2, iblockdata2); + }); +- int i1; ++ int j; ++ + if (flag) { +- i1 = 0; ++ j = 0; + } else { +- i1 = this.getSlopeDistance(level, blockPos, 1, direction.getOpposite(), blockState, pos, map1, map2); ++ j = this.getSlopeDistance(level, blockposition1, 1, enumdirection.getOpposite(), iblockdata1, pos, short2objectmap, short2booleanopenhashmap); + } + +- if (i1 < i) { ++ if (j < i) { + map.clear(); + } + +- if (i1 <= i) { +- map.put(direction, newLiquid); +- i = i1; ++ if (j <= i) { ++ map.put(enumdirection, fluid1); ++ i = j; + } + } + } +@@ -375,35 +434,20 @@ + return map; + } + +- private boolean canHoldFluid(BlockGetter level, BlockPos pos, BlockState state, Fluid fluid) { ++ private boolean canHoldFluid(BlockGetter level, BlockPos pos, IBlockData state, Fluid fluid) { + Block block = state.getBlock(); +- return block instanceof LiquidBlockContainer liquidBlockContainer +- ? liquidBlockContainer.canPlaceLiquid(null, level, pos, state, fluid) +- : !(block instanceof DoorBlock) +- && !state.is(BlockTags.SIGNS) +- && !state.is(Blocks.LADDER) +- && !state.is(Blocks.SUGAR_CANE) +- && !state.is(Blocks.BUBBLE_COLUMN) +- && !state.is(Blocks.NETHER_PORTAL) +- && !state.is(Blocks.END_PORTAL) +- && !state.is(Blocks.END_GATEWAY) +- && !state.is(Blocks.STRUCTURE_VOID) +- && !state.blocksMotion(); ++ ++ if (block instanceof LiquidBlockContainer) { ++ LiquidBlockContainer ifluidcontainer = (LiquidBlockContainer) block; ++ ++ return ifluidcontainer.canPlaceLiquid((Player) null, level, pos, state, fluid); ++ } else { ++ return !(block instanceof DoorBlock) && !state.is(BlockTags.SIGNS) && !state.is(Blocks.LADDER) && !state.is(Blocks.SUGAR_CANE) && !state.is(Blocks.BUBBLE_COLUMN) ? (!state.is(Blocks.NETHER_PORTAL) && !state.is(Blocks.END_PORTAL) && !state.is(Blocks.END_GATEWAY) && !state.is(Blocks.STRUCTURE_VOID) ? !state.blocksMotion() : false) : false; ++ } + } + +- protected boolean canSpreadTo( +- BlockGetter level, +- BlockPos fromPos, +- BlockState fromBlockState, +- Direction direction, +- BlockPos toPos, +- BlockState toBlockState, +- FluidState toFluidState, +- Fluid fluid +- ) { +- return toFluidState.canBeReplacedWith(level, toPos, fluid, direction) +- && this.canPassThroughWall(direction, level, fromPos, fromBlockState, toPos, toBlockState) +- && this.canHoldFluid(level, toPos, toBlockState, fluid); ++ protected boolean canSpreadTo(BlockGetter level, BlockPos fromPos, IBlockData fromBlockState, Direction direction, BlockPos toPos, IBlockData toBlockState, FluidState toFluidState, Fluid fluid) { ++ return toFluidState.canBeReplacedWith(level, toPos, fluid, direction) && this.canPassThroughWall(direction, level, fromPos, fromBlockState, toPos, toBlockState) && this.canHoldFluid(level, toPos, toBlockState, fluid); + } + + protected abstract int getDropOff(LevelReader level); +@@ -415,17 +459,30 @@ + @Override + public void tick(Level level, BlockPos pos, FluidState state) { + if (!state.isSource()) { +- FluidState newLiquid = this.getNewLiquid(level, pos, level.getBlockState(pos)); +- int spreadDelay = this.getSpreadDelay(level, pos, state, newLiquid); +- if (newLiquid.isEmpty()) { +- state = newLiquid; +- level.setBlock(pos, Blocks.AIR.defaultBlockState(), 3); +- } else if (!newLiquid.equals(state)) { +- state = newLiquid; +- BlockState blockState = newLiquid.createLegacyBlock(); +- level.setBlock(pos, blockState, 2); +- level.scheduleTick(pos, newLiquid.getType(), spreadDelay); +- level.updateNeighborsAt(pos, blockState.getBlock()); ++ FluidState fluid1 = this.getNewLiquid(level, pos, level.getBlockState(pos)); ++ int i = this.getSpreadDelay(level, pos, state, fluid1); ++ ++ if (fluid1.isEmpty()) { ++ state = fluid1; ++ // CraftBukkit start ++ FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(level, pos, Blocks.AIR.defaultBlockState()); ++ if (event.isCancelled()) { ++ return; ++ } ++ level.setBlock(pos, ((CraftBlockData) event.getNewData()).getState(), 3); ++ // CraftBukkit end ++ } else if (!fluid1.equals(state)) { ++ state = fluid1; ++ IBlockData iblockdata = fluid1.createLegacyBlock(); ++ // CraftBukkit start ++ FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(level, pos, iblockdata); ++ if (event.isCancelled()) { ++ return; ++ } ++ level.setBlock(pos, ((CraftBlockData) event.getNewData()).getState(), 2); ++ // CraftBukkit end ++ level.scheduleTick(pos, fluid1.getType(), i); ++ level.updateNeighborsAt(pos, iblockdata.getBlock()); + } + } + +@@ -433,7 +490,7 @@ + } + + protected static int getLegacyLevel(FluidState state) { +- return state.isSource() ? 0 : 8 - Math.min(state.getAmount(), 8) + (state.getValue(FALLING) ? 8 : 0); ++ return state.isSource() ? 0 : 8 - Math.min(state.getAmount(), 8) + ((Boolean) state.getValue(FlowingFluid.FALLING) ? 8 : 0); + } + + private static boolean hasSameAbove(FluidState fluidState, BlockGetter level, BlockPos pos) { +@@ -447,7 +504,7 @@ + + @Override + public float getOwnHeight(FluidState state) { +- return (float)state.getAmount() / 9.0F; ++ return (float) state.getAmount() / 9.0F; + } + + @Override +@@ -455,8 +512,8 @@ + + @Override + public VoxelShape getShape(FluidState state, BlockGetter level, BlockPos pos) { +- return state.getAmount() == 9 && hasSameAbove(state, level, pos) +- ? Shapes.block() +- : this.shapes.computeIfAbsent(state, stateKey -> Shapes.box(0.0, 0.0, 0.0, 1.0, (double)stateKey.getHeight(level, pos), 1.0)); ++ return state.getAmount() == 9 && hasSameAbove(state, level, pos) ? Shapes.block() : (VoxelShape) this.shapes.computeIfAbsent(state, (fluid1) -> { ++ return Shapes.box(0.0D, 0.0D, 0.0D, 1.0D, (double) fluid1.getHeight(level, pos), 1.0D); ++ }); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/material/LavaFluid.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/material/LavaFluid.java.patch new file mode 100644 index 0000000000..5b1e653794 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/material/LavaFluid.java.patch @@ -0,0 +1,253 @@ +--- a/net/minecraft/world/level/material/LavaFluid.java ++++ b/net/minecraft/world/level/material/LavaFluid.java +@@ -21,12 +21,15 @@ + import net.minecraft.world.level.block.BaseFireBlock; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.LiquidBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.StateDefinition; + + public abstract class LavaFluid extends FlowingFluid { ++ + public static final float MIN_LEVEL_CUTOFF = 0.44444445F; + ++ public LavaFluid() {} ++ + @Override + public Fluid getFlowing() { + return Fluids.FLOWING_LAVA; +@@ -44,74 +47,90 @@ + + @Override + public void animateTick(Level level, BlockPos pos, FluidState state, RandomSource random) { +- BlockPos blockPos = pos.above(); +- if (level.getBlockState(blockPos).isAir() && !level.getBlockState(blockPos).isSolidRender(level, blockPos)) { ++ BlockPos blockposition1 = pos.above(); ++ ++ if (level.getBlockState(blockposition1).isAir() && !level.getBlockState(blockposition1).isSolidRender(level, blockposition1)) { + if (random.nextInt(100) == 0) { +- double d = (double)pos.getX() + random.nextDouble(); +- double d1 = (double)pos.getY() + 1.0; +- double d2 = (double)pos.getZ() + random.nextDouble(); +- level.addParticle(ParticleTypes.LAVA, d, d1, d2, 0.0, 0.0, 0.0); +- level.playLocalSound( +- d, d1, d2, SoundEvents.LAVA_POP, SoundSource.BLOCKS, 0.2F + random.nextFloat() * 0.2F, 0.9F + random.nextFloat() * 0.15F, false +- ); ++ double d0 = (double) pos.getX() + random.nextDouble(); ++ double d1 = (double) pos.getY() + 1.0D; ++ double d2 = (double) pos.getZ() + random.nextDouble(); ++ ++ level.addParticle(ParticleTypes.LAVA, d0, d1, d2, 0.0D, 0.0D, 0.0D); ++ level.playLocalSound(d0, d1, d2, SoundEvents.LAVA_POP, SoundSource.BLOCKS, 0.2F + random.nextFloat() * 0.2F, 0.9F + random.nextFloat() * 0.15F, false); + } + + if (random.nextInt(200) == 0) { +- level.playLocalSound( +- (double)pos.getX(), +- (double)pos.getY(), +- (double)pos.getZ(), +- SoundEvents.LAVA_AMBIENT, +- SoundSource.BLOCKS, +- 0.2F + random.nextFloat() * 0.2F, +- 0.9F + random.nextFloat() * 0.15F, +- false +- ); ++ level.playLocalSound((double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), SoundEvents.LAVA_AMBIENT, SoundSource.BLOCKS, 0.2F + random.nextFloat() * 0.2F, 0.9F + random.nextFloat() * 0.15F, false); + } + } ++ + } + + @Override + public void randomTick(Level level, BlockPos pos, FluidState state, RandomSource random) { + if (level.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) { +- int randomInt = random.nextInt(3); +- if (randomInt > 0) { +- BlockPos blockPos = pos; ++ int i = random.nextInt(3); + +- for (int i = 0; i < randomInt; i++) { +- blockPos = blockPos.offset(random.nextInt(3) - 1, 1, random.nextInt(3) - 1); +- if (!level.isLoaded(blockPos)) { ++ if (i > 0) { ++ BlockPos blockposition1 = pos; ++ ++ for (int j = 0; j < i; ++j) { ++ blockposition1 = blockposition1.offset(random.nextInt(3) - 1, 1, random.nextInt(3) - 1); ++ if (!level.isLoaded(blockposition1)) { + return; + } + +- BlockState blockState = level.getBlockState(blockPos); +- if (blockState.isAir()) { +- if (this.hasFlammableNeighbours(level, blockPos)) { +- level.setBlockAndUpdate(blockPos, BaseFireBlock.getState(level, blockPos)); ++ IBlockData iblockdata = level.getBlockState(blockposition1); ++ ++ if (iblockdata.isAir()) { ++ if (this.hasFlammableNeighbours(level, blockposition1)) { ++ // CraftBukkit start - Prevent lava putting something on fire ++ if (level.getBlockState(blockposition1).getBlock() != Blocks.FIRE) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, blockposition1, pos).isCancelled()) { ++ continue; ++ } ++ } ++ // CraftBukkit end ++ level.setBlockAndUpdate(blockposition1, BaseFireBlock.getState(level, blockposition1)); + return; + } +- } else if (blockState.blocksMotion()) { ++ } else if (iblockdata.blocksMotion()) { + return; + } + } + } else { +- for (int i1 = 0; i1 < 3; i1++) { +- BlockPos blockPos1 = pos.offset(random.nextInt(3) - 1, 0, random.nextInt(3) - 1); +- if (!level.isLoaded(blockPos1)) { ++ for (int k = 0; k < 3; ++k) { ++ BlockPos blockposition2 = pos.offset(random.nextInt(3) - 1, 0, random.nextInt(3) - 1); ++ ++ if (!level.isLoaded(blockposition2)) { + return; + } + +- if (level.isEmptyBlock(blockPos1.above()) && this.isFlammable(level, blockPos1)) { +- level.setBlockAndUpdate(blockPos1.above(), BaseFireBlock.getState(level, blockPos1)); ++ if (level.isEmptyBlock(blockposition2.above()) && this.isFlammable(level, blockposition2)) { ++ // CraftBukkit start - Prevent lava putting something on fire ++ BlockPos up = blockposition2.above(); ++ if (level.getBlockState(up).getBlock() != Blocks.FIRE) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, up, pos).isCancelled()) { ++ continue; ++ } ++ } ++ // CraftBukkit end ++ level.setBlockAndUpdate(blockposition2.above(), BaseFireBlock.getState(level, blockposition2)); + } + } + } ++ + } + } + + private boolean hasFlammableNeighbours(LevelReader level, BlockPos pos) { +- for (Direction direction : Direction.values()) { +- if (this.isFlammable(level, pos.relative(direction))) { ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; ++ ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ ++ if (this.isFlammable(level, pos.relative(enumdirection))) { + return true; + } + } +@@ -120,8 +139,7 @@ + } + + private boolean isFlammable(LevelReader level, BlockPos pos) { +- return (pos.getY() < level.getMinBuildHeight() || pos.getY() >= level.getMaxBuildHeight() || level.hasChunkAt(pos)) +- && level.getBlockState(pos).ignitedByLava(); ++ return pos.getY() >= level.getMinBuildHeight() && pos.getY() < level.getMaxBuildHeight() && !level.hasChunkAt(pos) ? false : level.getBlockState(pos).ignitedByLava(); + } + + @Nullable +@@ -131,7 +149,7 @@ + } + + @Override +- protected void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, BlockState state) { ++ protected void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, IBlockData state) { + this.fizz(level, pos); + } + +@@ -141,8 +159,8 @@ + } + + @Override +- public BlockState createLegacyBlock(FluidState state) { +- return Blocks.LAVA.defaultBlockState().setValue(LiquidBlock.LEVEL, Integer.valueOf(getLegacyLevel(state))); ++ public IBlockData createLegacyBlock(FluidState state) { ++ return (IBlockData) Blocks.LAVA.defaultBlockState().setValue(LiquidBlock.LEVEL, getLegacyLevel(state)); + } + + @Override +@@ -167,17 +185,13 @@ + + @Override + public int getSpreadDelay(Level level, BlockPos pos, FluidState currentState, FluidState newState) { +- int tickDelay = this.getTickDelay(level); +- if (!currentState.isEmpty() +- && !newState.isEmpty() +- && !currentState.getValue(FALLING) +- && !newState.getValue(FALLING) +- && newState.getHeight(level, pos) > currentState.getHeight(level, pos) +- && level.getRandom().nextInt(4) != 0) { +- tickDelay *= 4; ++ int i = this.getTickDelay(level); ++ ++ if (!currentState.isEmpty() && !newState.isEmpty() && !(Boolean) currentState.getValue(LavaFluid.FALLING) && !(Boolean) newState.getValue(LavaFluid.FALLING) && newState.getHeight(level, pos) > currentState.getHeight(level, pos) && level.getRandom().nextInt(4) != 0) { ++ i *= 4; + } + +- return tickDelay; ++ return i; + } + + private void fizz(LevelAccessor level, BlockPos pos) { +@@ -190,12 +204,17 @@ + } + + @Override +- protected void spreadTo(LevelAccessor level, BlockPos pos, BlockState blockState, Direction direction, FluidState fluidState) { ++ protected void spreadTo(LevelAccessor level, BlockPos pos, IBlockData blockState, Direction direction, FluidState fluidState) { + if (direction == Direction.DOWN) { +- FluidState fluidState1 = level.getFluidState(pos); +- if (this.is(FluidTags.LAVA) && fluidState1.is(FluidTags.WATER)) { ++ FluidState fluid1 = level.getFluidState(pos); ++ ++ if (this.is(FluidTags.LAVA) && fluid1.is(FluidTags.WATER)) { + if (blockState.getBlock() instanceof LiquidBlock) { +- level.setBlock(pos, Blocks.STONE.defaultBlockState(), 3); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level.getMinecraftWorld(), pos, Blocks.STONE.defaultBlockState(), 3)) { ++ return; ++ } ++ // CraftBukkit end + } + + this.fizz(level, pos); +@@ -222,15 +241,18 @@ + } + + public static class Flowing extends LavaFluid { ++ ++ public Flowing() {} ++ + @Override + protected void createFluidStateDefinition(StateDefinition.Builder builder) { + super.createFluidStateDefinition(builder); +- builder.add(LEVEL); ++ builder.add(LavaFluid.Flowing.LEVEL); + } + + @Override + public int getAmount(FluidState state) { +- return state.getValue(LEVEL); ++ return (Integer) state.getValue(LavaFluid.Flowing.LEVEL); + } + + @Override +@@ -240,6 +262,9 @@ + } + + public static class Source extends LavaFluid { ++ ++ public Source() {} ++ + @Override + public int getAmount(FluidState state) { + return 8; diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/portal/PortalForcer.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/portal/PortalForcer.java.patch new file mode 100644 index 0000000000..88a665848e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/portal/PortalForcer.java.patch @@ -0,0 +1,312 @@ +--- a/net/minecraft/world/level/portal/PortalForcer.java ++++ b/net/minecraft/world/level/portal/PortalForcer.java +@@ -1,11 +1,11 @@ + package net.minecraft.world.level.portal; + + import java.util.Comparator; ++import java.util.Iterator; + import java.util.Optional; + import net.minecraft.BlockUtil; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; +-import net.minecraft.core.Holder; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.TicketType; + import net.minecraft.util.Mth; +@@ -15,12 +15,13 @@ + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.NetherPortalBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.level.border.WorldBorder; + import net.minecraft.world.level.levelgen.Heightmap; + + public class PortalForcer { ++ + private static final int TICKET_RADIUS = 3; + private static final int SEARCH_RADIUS = 128; + private static final int CREATE_RADIUS = 16; +@@ -41,74 +42,93 @@ + } + + public Optional findPortalAround(BlockPos pos, boolean isNether, WorldBorder worldBorder) { +- PoiManager poiManager = this.level.getPoiManager(); +- int i = isNether ? 16 : 128; +- poiManager.ensureLoadedAndValid(this.level, pos, i); +- Optional optional = poiManager.getInSquare(poiType -> poiType.is(PoiTypes.NETHER_PORTAL), pos, i, PoiManager.Occupancy.ANY) +- .filter(poiRecord -> worldBorder.isWithinBounds(poiRecord.getPos())) +- .sorted( +- Comparator.comparingDouble(poiRecord -> poiRecord.getPos().distSqr(pos)).thenComparingInt(poiRecord -> poiRecord.getPos().getY()) +- ) +- .filter(poiRecord -> this.level.getBlockState(poiRecord.getPos()).hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) +- .findFirst(); +- return optional.map( +- poiRecord -> { +- BlockPos pos1 = poiRecord.getPos(); +- this.level.getChunkSource().addRegionTicket(TicketType.PORTAL, new ChunkPos(pos1), 3, pos1); +- BlockState blockState = this.level.getBlockState(pos1); +- return BlockUtil.getLargestRectangleAround( +- pos1, +- blockState.getValue(BlockStateProperties.HORIZONTAL_AXIS), +- 21, +- Direction.Axis.Y, +- 21, +- possibleBlockPos -> this.level.getBlockState(possibleBlockPos) == blockState +- ); +- } +- ); ++ // CraftBukkit start ++ return findPortalAround(pos, worldBorder, isNether ? 16 : 128); // Search Radius + } + ++ public Optional findPortalAround(BlockPos blockposition, WorldBorder worldborder, int i) { ++ PoiManager villageplace = this.level.getPoiManager(); ++ // int i = flag ? 16 : 128; ++ // CraftBukkit end ++ ++ villageplace.ensureLoadedAndValid(this.level, blockposition, i); ++ Optional optional = villageplace.getInSquare((holder) -> { ++ return holder.is(PoiTypes.NETHER_PORTAL); ++ }, blockposition, i, PoiManager.Occupancy.ANY).filter((villageplacerecord) -> { ++ return worldborder.isWithinBounds(villageplacerecord.getPos()); ++ }).sorted(Comparator.comparingDouble((PoiRecord villageplacerecord) -> { // CraftBukkit - decompile error ++ return villageplacerecord.getPos().distSqr(blockposition); ++ }).thenComparingInt((villageplacerecord) -> { ++ return villageplacerecord.getPos().getY(); ++ })).filter((villageplacerecord) -> { ++ return this.level.getBlockState(villageplacerecord.getPos()).hasProperty(BlockStateProperties.HORIZONTAL_AXIS); ++ }).findFirst(); ++ ++ return optional.map((villageplacerecord) -> { ++ BlockPos blockposition1 = villageplacerecord.getPos(); ++ ++ this.level.getChunkSource().addRegionTicket(TicketType.PORTAL, new ChunkPos(blockposition1), 3, blockposition1); ++ IBlockData iblockdata = this.level.getBlockState(blockposition1); ++ ++ return BlockUtil.getLargestRectangleAround(blockposition1, (Direction.Axis) iblockdata.getValue(BlockStateProperties.HORIZONTAL_AXIS), 21, Direction.Axis.Y, 21, (blockposition2) -> { ++ return this.level.getBlockState(blockposition2) == iblockdata; ++ }); ++ }); ++ } ++ + public Optional createPortal(BlockPos pos, Direction.Axis axis) { +- Direction direction = Direction.get(Direction.AxisDirection.POSITIVE, axis); +- double d = -1.0; +- BlockPos blockPos = null; +- double d1 = -1.0; +- BlockPos blockPos1 = null; +- WorldBorder worldBorder = this.level.getWorldBorder(); ++ // CraftBukkit start ++ return this.createPortal(pos, axis, null, 16); ++ } ++ ++ public Optional createPortal(BlockPos blockposition, Direction.Axis enumdirection_enumaxis, net.minecraft.world.entity.Entity entity, int createRadius) { ++ // CraftBukkit end ++ Direction enumdirection = Direction.get(Direction.AxisDirection.POSITIVE, enumdirection_enumaxis); ++ double d0 = -1.0D; ++ BlockPos blockposition1 = null; ++ double d1 = -1.0D; ++ BlockPos blockposition2 = null; ++ WorldBorder worldborder = this.level.getWorldBorder(); + int i = Math.min(this.level.getMaxBuildHeight(), this.level.getMinBuildHeight() + this.level.getLogicalHeight()) - 1; +- BlockPos.MutableBlockPos mutableBlockPos = pos.mutable(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = blockposition.mutable(); ++ Iterator iterator = BlockPos.spiralAround(blockposition, createRadius, Direction.EAST, Direction.SOUTH).iterator(); // CraftBukkit + +- for (BlockPos.MutableBlockPos mutableBlockPos1 : BlockPos.spiralAround(pos, 16, Direction.EAST, Direction.SOUTH)) { +- int min = Math.min(i, this.level.getHeight(Heightmap.Types.MOTION_BLOCKING, mutableBlockPos1.getX(), mutableBlockPos1.getZ())); +- int i1 = 1; +- if (worldBorder.isWithinBounds(mutableBlockPos1) && worldBorder.isWithinBounds(mutableBlockPos1.move(direction, 1))) { +- mutableBlockPos1.move(direction.getOpposite(), 1); ++ int j; ++ int k; ++ int l; + +- for (int i2 = min; i2 >= this.level.getMinBuildHeight(); i2--) { +- mutableBlockPos1.setY(i2); +- if (this.canPortalReplaceBlock(mutableBlockPos1)) { +- int i3 = i2; ++ while (iterator.hasNext()) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition1 = (BlockPos.MutableBlockPos) iterator.next(); + +- while (i2 > this.level.getMinBuildHeight() && this.canPortalReplaceBlock(mutableBlockPos1.move(Direction.DOWN))) { +- i2--; ++ j = Math.min(i, this.level.getHeight(Heightmap.Types.MOTION_BLOCKING, blockposition_mutableblockposition1.getX(), blockposition_mutableblockposition1.getZ())); ++ boolean flag = true; ++ ++ if (worldborder.isWithinBounds((BlockPos) blockposition_mutableblockposition1) && worldborder.isWithinBounds((BlockPos) blockposition_mutableblockposition1.move(enumdirection, 1))) { ++ blockposition_mutableblockposition1.move(enumdirection.getOpposite(), 1); ++ ++ for (k = j; k >= this.level.getMinBuildHeight(); --k) { ++ blockposition_mutableblockposition1.setY(k); ++ if (this.canPortalReplaceBlock(blockposition_mutableblockposition1)) { ++ for (l = k; k > this.level.getMinBuildHeight() && this.canPortalReplaceBlock(blockposition_mutableblockposition1.move(Direction.DOWN)); --k) { ++ ; + } + +- if (i2 + 4 <= i) { +- int i4 = i3 - i2; +- if (i4 <= 0 || i4 >= 3) { +- mutableBlockPos1.setY(i2); +- if (this.canHostFrame(mutableBlockPos1, mutableBlockPos, direction, 0)) { +- double d2 = pos.distSqr(mutableBlockPos1); +- if (this.canHostFrame(mutableBlockPos1, mutableBlockPos, direction, -1) +- && this.canHostFrame(mutableBlockPos1, mutableBlockPos, direction, 1) +- && (d == -1.0 || d > d2)) { +- d = d2; +- blockPos = mutableBlockPos1.immutable(); ++ if (k + 4 <= i) { ++ int i1 = l - k; ++ ++ if (i1 <= 0 || i1 >= 3) { ++ blockposition_mutableblockposition1.setY(k); ++ if (this.canHostFrame(blockposition_mutableblockposition1, blockposition_mutableblockposition, enumdirection, 0)) { ++ double d2 = blockposition.distSqr(blockposition_mutableblockposition1); ++ ++ if (this.canHostFrame(blockposition_mutableblockposition1, blockposition_mutableblockposition, enumdirection, -1) && this.canHostFrame(blockposition_mutableblockposition1, blockposition_mutableblockposition, enumdirection, 1) && (d0 == -1.0D || d0 > d2)) { ++ d0 = d2; ++ blockposition1 = blockposition_mutableblockposition1.immutable(); + } + +- if (d == -1.0 && (d1 == -1.0 || d1 > d2)) { ++ if (d0 == -1.0D && (d1 == -1.0D || d1 > d2)) { + d1 = d2; +- blockPos1 = mutableBlockPos1.immutable(); ++ blockposition2 = blockposition_mutableblockposition1.immutable(); + } + } + } +@@ -118,79 +138,89 @@ + } + } + +- if (d == -1.0 && d1 != -1.0) { +- blockPos = blockPos1; +- d = d1; ++ if (d0 == -1.0D && d1 != -1.0D) { ++ blockposition1 = blockposition2; ++ d0 = d1; + } + +- if (d == -1.0) { +- int max = Math.max(this.level.getMinBuildHeight() - -1, 70); +- int i5 = i - 9; +- if (i5 < max) { ++ int j1; ++ int k1; ++ ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(this.level); // CraftBukkit - Use BlockStateListPopulator ++ if (d0 == -1.0D) { ++ j1 = Math.max(this.level.getMinBuildHeight() - -1, 70); ++ k1 = i - 9; ++ if (k1 < j1) { + return Optional.empty(); + } + +- blockPos = new BlockPos(pos.getX(), Mth.clamp(pos.getY(), max, i5), pos.getZ()).immutable(); +- Direction clockWise = direction.getClockWise(); +- if (!worldBorder.isWithinBounds(blockPos)) { ++ blockposition1 = (new BlockPos(blockposition.getX(), Mth.clamp(blockposition.getY(), j1, k1), blockposition.getZ())).immutable(); ++ Direction enumdirection1 = enumdirection.getClockWise(); ++ ++ if (!worldborder.isWithinBounds(blockposition1)) { + return Optional.empty(); + } + +- for (int i1 = -1; i1 < 2; i1++) { +- for (int i2x = 0; i2x < 2; i2x++) { +- for (int i3 = -1; i3 < 3; i3++) { +- BlockState blockState = i3 < 0 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); +- mutableBlockPos.setWithOffset( +- blockPos, i2x * direction.getStepX() + i1 * clockWise.getStepX(), i3, i2x * direction.getStepZ() + i1 * clockWise.getStepZ() +- ); +- this.level.setBlockAndUpdate(mutableBlockPos, blockState); ++ for (int l1 = -1; l1 < 2; ++l1) { ++ for (k = 0; k < 2; ++k) { ++ for (l = -1; l < 3; ++l) { ++ IBlockData iblockdata = l < 0 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); ++ ++ blockposition_mutableblockposition.setWithOffset(blockposition1, k * enumdirection.getStepX() + l1 * enumdirection1.getStepX(), l, k * enumdirection.getStepZ() + l1 * enumdirection1.getStepZ()); ++ blockList.setBlock(blockposition_mutableblockposition, iblockdata, 3); // CraftBukkit + } + } + } + } + +- for (int maxx = -1; maxx < 3; maxx++) { +- for (int i5x = -1; i5x < 4; i5x++) { +- if (maxx == -1 || maxx == 2 || i5x == -1 || i5x == 3) { +- mutableBlockPos.setWithOffset(blockPos, maxx * direction.getStepX(), i5x, maxx * direction.getStepZ()); +- this.level.setBlock(mutableBlockPos, Blocks.OBSIDIAN.defaultBlockState(), 3); ++ for (j1 = -1; j1 < 3; ++j1) { ++ for (k1 = -1; k1 < 4; ++k1) { ++ if (j1 == -1 || j1 == 2 || k1 == -1 || k1 == 3) { ++ blockposition_mutableblockposition.setWithOffset(blockposition1, j1 * enumdirection.getStepX(), k1, j1 * enumdirection.getStepZ()); ++ blockList.setBlock(blockposition_mutableblockposition, Blocks.OBSIDIAN.defaultBlockState(), 3); // CraftBukkit + } + } + } + +- BlockState blockState1 = Blocks.NETHER_PORTAL.defaultBlockState().setValue(NetherPortalBlock.AXIS, axis); ++ IBlockData iblockdata1 = (IBlockData) Blocks.NETHER_PORTAL.defaultBlockState().setValue(NetherPortalBlock.AXIS, enumdirection_enumaxis); + +- for (int i5xx = 0; i5xx < 2; i5xx++) { +- for (int min = 0; min < 3; min++) { +- mutableBlockPos.setWithOffset(blockPos, i5xx * direction.getStepX(), min, i5xx * direction.getStepZ()); +- this.level.setBlock(mutableBlockPos, blockState1, 18); ++ for (k1 = 0; k1 < 2; ++k1) { ++ for (j = 0; j < 3; ++j) { ++ blockposition_mutableblockposition.setWithOffset(blockposition1, k1 * enumdirection.getStepX(), j, k1 * enumdirection.getStepZ()); ++ blockList.setBlock(blockposition_mutableblockposition, iblockdata1, 18); // CraftBukkit + } + } + +- return Optional.of(new BlockUtil.FoundRectangle(blockPos.immutable(), 2, 3)); ++ // CraftBukkit start ++ org.bukkit.World bworld = this.level.getWorld(); ++ org.bukkit.event.world.PortalCreateEvent event = new org.bukkit.event.world.PortalCreateEvent((java.util.List) (java.util.List) blockList.getList(), bworld, (entity == null) ? null : entity.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.NETHER_PAIR); ++ ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return Optional.empty(); ++ } ++ blockList.updateList(); ++ // CraftBukkit end ++ return Optional.of(new BlockUtil.FoundRectangle(blockposition1.immutable(), 2, 3)); + } + + private boolean canPortalReplaceBlock(BlockPos.MutableBlockPos pos) { +- BlockState blockState = this.level.getBlockState(pos); +- return blockState.canBeReplaced() && blockState.getFluidState().isEmpty(); ++ IBlockData iblockdata = this.level.getBlockState(pos); ++ ++ return iblockdata.canBeReplaced() && iblockdata.getFluidState().isEmpty(); + } + + private boolean canHostFrame(BlockPos originalPos, BlockPos.MutableBlockPos offsetPos, Direction direction, int offsetScale) { +- Direction clockWise = direction.getClockWise(); ++ Direction enumdirection1 = direction.getClockWise(); + +- for (int i = -1; i < 3; i++) { +- for (int i1 = -1; i1 < 4; i1++) { +- offsetPos.setWithOffset( +- originalPos, +- direction.getStepX() * i + clockWise.getStepX() * offsetScale, +- i1, +- direction.getStepZ() * i + clockWise.getStepZ() * offsetScale +- ); +- if (i1 < 0 && !this.level.getBlockState(offsetPos).isSolid()) { ++ for (int j = -1; j < 3; ++j) { ++ for (int k = -1; k < 4; ++k) { ++ offsetPos.setWithOffset(originalPos, direction.getStepX() * j + enumdirection1.getStepX() * offsetScale, k, direction.getStepZ() * j + enumdirection1.getStepZ() * offsetScale); ++ if (k < 0 && !this.level.getBlockState(offsetPos).isSolid()) { + return false; + } + +- if (i1 >= 0 && !this.canPortalReplaceBlock(offsetPos)) { ++ if (k >= 0 && !this.canPortalReplaceBlock(offsetPos)) { + return false; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/portal/PortalInfo.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/portal/PortalInfo.java.patch new file mode 100644 index 0000000000..7db8384ce5 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/portal/PortalInfo.java.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/level/portal/PortalInfo.java ++++ b/net/minecraft/world/level/portal/PortalInfo.java +@@ -1,17 +1,27 @@ + package net.minecraft.world.level.portal; + ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.phys.Vec3; ++import org.bukkit.craftbukkit.event.CraftPortalEvent; ++// CraftBukkit end + + public class PortalInfo { ++ + public final Vec3 pos; + public final Vec3 speed; + public final float yRot; + public final float xRot; ++ // CraftBukkit start ++ public final ServerLevel world; ++ public final CraftPortalEvent portalEventInfo; + +- public PortalInfo(Vec3 pos, Vec3 speed, float yRot, float xRot) { +- this.pos = pos; +- this.speed = speed; +- this.yRot = yRot; +- this.xRot = xRot; ++ public PortalInfo(Vec3 vec3d, Vec3 vec3d1, float f, float f1, ServerLevel world, CraftPortalEvent portalEventInfo) { ++ this.world = world; ++ this.portalEventInfo = portalEventInfo; ++ // CraftBukkit end ++ this.pos = vec3d; ++ this.speed = vec3d1; ++ this.yRot = f; ++ this.xRot = f1; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/portal/PortalShape.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/portal/PortalShape.java.patch new file mode 100644 index 0000000000..6ce445764f --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/portal/PortalShape.java.patch @@ -0,0 +1,353 @@ +--- a/net/minecraft/world/level/portal/PortalShape.java ++++ b/net/minecraft/world/level/portal/PortalShape.java +@@ -11,26 +11,32 @@ + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; +-import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.NetherPortalBlock; + import net.minecraft.world.level.block.state.BlockBehaviour; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateProperties; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.Shapes; + import net.minecraft.world.phys.shapes.VoxelShape; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftPortalEvent; ++import org.bukkit.event.world.PortalCreateEvent; ++// CraftBukkit end + + public class PortalShape { ++ + private static final int MIN_WIDTH = 2; + public static final int MAX_WIDTH = 21; + private static final int MIN_HEIGHT = 3; + public static final int MAX_HEIGHT = 21; +- private static final BlockBehaviour.StatePredicate FRAME = (state, level, pos) -> state.is(Blocks.OBSIDIAN); ++ private static final BlockBehaviour.StatePredicate FRAME = (iblockdata, iblockaccess, blockposition) -> { ++ return iblockdata.is(Blocks.OBSIDIAN); ++ }; + private static final float SAFE_TRAVEL_MAX_ENTITY_XY = 4.0F; +- private static final double SAFE_TRAVEL_MAX_VERTICAL_DELTA = 1.0; ++ private static final double SAFE_TRAVEL_MAX_VERTICAL_DELTA = 1.0D; + private final LevelAccessor level; + private final Direction.Axis axis; + private final Direction rightDir; +@@ -39,22 +45,28 @@ + private BlockPos bottomLeft; + private int height; + private final int width; ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blocks; // CraftBukkit - add field + + public static Optional findEmptyPortalShape(LevelAccessor level, BlockPos bottomLeft, Direction.Axis axis) { +- return findPortalShape(level, bottomLeft, shape -> shape.isValid() && shape.numPortalBlocks == 0, axis); ++ return findPortalShape(level, bottomLeft, (blockportalshape) -> { ++ return blockportalshape.isValid() && blockportalshape.numPortalBlocks == 0; ++ }, axis); + } + + public static Optional findPortalShape(LevelAccessor level, BlockPos bottomLeft, Predicate predicate, Direction.Axis axis) { + Optional optional = Optional.of(new PortalShape(level, bottomLeft, axis)).filter(predicate); ++ + if (optional.isPresent()) { + return optional; + } else { +- Direction.Axis axis1 = axis == Direction.Axis.X ? Direction.Axis.Z : Direction.Axis.X; +- return Optional.of(new PortalShape(level, bottomLeft, axis1)).filter(predicate); ++ Direction.Axis enumdirection_enumaxis1 = axis == Direction.Axis.X ? Direction.Axis.Z : Direction.Axis.X; ++ ++ return Optional.of(new PortalShape(level, bottomLeft, enumdirection_enumaxis1)).filter(predicate); + } + } + + public PortalShape(LevelAccessor level, BlockPos bottomLeft, Direction.Axis axis) { ++ blocks = new org.bukkit.craftbukkit.util.BlockStateListPopulator(level.getMinecraftWorld()); // CraftBukkit + this.level = level; + this.axis = axis; + this.rightDir = axis == Direction.Axis.X ? Direction.WEST : Direction.SOUTH; +@@ -69,94 +81,107 @@ + this.height = this.calculateHeight(); + } + } ++ + } + + @Nullable + private BlockPos calculateBottomLeft(BlockPos pos) { +- int max = Math.max(this.level.getMinBuildHeight(), pos.getY() - 21); +- +- while (pos.getY() > max && isEmpty(this.level.getBlockState(pos.below()))) { +- pos = pos.below(); ++ for (int i = Math.max(this.level.getMinBuildHeight(), pos.getY() - 21); pos.getY() > i && isEmpty(this.level.getBlockState(pos.below())); pos = pos.below()) { ++ ; + } + +- Direction opposite = this.rightDir.getOpposite(); +- int i = this.getDistanceUntilEdgeAboveFrame(pos, opposite) - 1; +- return i < 0 ? null : pos.relative(opposite, i); ++ Direction enumdirection = this.rightDir.getOpposite(); ++ int j = this.getDistanceUntilEdgeAboveFrame(pos, enumdirection) - 1; ++ ++ return j < 0 ? null : pos.relative(enumdirection, j); + } + + private int calculateWidth() { +- int distanceUntilEdgeAboveFrame = this.getDistanceUntilEdgeAboveFrame(this.bottomLeft, this.rightDir); +- return distanceUntilEdgeAboveFrame >= 2 && distanceUntilEdgeAboveFrame <= 21 ? distanceUntilEdgeAboveFrame : 0; ++ int i = this.getDistanceUntilEdgeAboveFrame(this.bottomLeft, this.rightDir); ++ ++ return i >= 2 && i <= 21 ? i : 0; + } + + private int getDistanceUntilEdgeAboveFrame(BlockPos pos, Direction direction) { +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + +- for (int i = 0; i <= 21; i++) { +- mutableBlockPos.set(pos).move(direction, i); +- BlockState blockState = this.level.getBlockState(mutableBlockPos); +- if (!isEmpty(blockState)) { +- if (FRAME.test(blockState, this.level, mutableBlockPos)) { ++ for (int i = 0; i <= 21; ++i) { ++ blockposition_mutableblockposition.set(pos).move(direction, i); ++ IBlockData iblockdata = this.level.getBlockState(blockposition_mutableblockposition); ++ ++ if (!isEmpty(iblockdata)) { ++ if (PortalShape.FRAME.test(iblockdata, this.level, blockposition_mutableblockposition)) { ++ blocks.setBlock(blockposition_mutableblockposition, iblockdata, 18); // CraftBukkit - lower left / right + return i; + } + break; + } + +- BlockState blockState1 = this.level.getBlockState(mutableBlockPos.move(Direction.DOWN)); +- if (!FRAME.test(blockState1, this.level, mutableBlockPos)) { ++ IBlockData iblockdata1 = this.level.getBlockState(blockposition_mutableblockposition.move(Direction.DOWN)); ++ ++ if (!PortalShape.FRAME.test(iblockdata1, this.level, blockposition_mutableblockposition)) { + break; + } ++ blocks.setBlock(blockposition_mutableblockposition, iblockdata1, 18); // CraftBukkit - bottom row + } + + return 0; + } + + private int calculateHeight() { +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); +- int distanceUntilTop = this.getDistanceUntilTop(mutableBlockPos); +- return distanceUntilTop >= 3 && distanceUntilTop <= 21 && this.hasTopFrame(mutableBlockPos, distanceUntilTop) ? distanceUntilTop : 0; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ int i = this.getDistanceUntilTop(blockposition_mutableblockposition); ++ ++ return i >= 3 && i <= 21 && this.hasTopFrame(blockposition_mutableblockposition, i) ? i : 0; + } + + private boolean hasTopFrame(BlockPos.MutableBlockPos pos, int distanceToTop) { +- for (int i = 0; i < this.width; i++) { +- BlockPos.MutableBlockPos mutableBlockPos = pos.set(this.bottomLeft).move(Direction.UP, distanceToTop).move(this.rightDir, i); +- if (!FRAME.test(this.level.getBlockState(mutableBlockPos), this.level, mutableBlockPos)) { ++ for (int j = 0; j < this.width; ++j) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition1 = pos.set(this.bottomLeft).move(Direction.UP, distanceToTop).move(this.rightDir, j); ++ ++ if (!PortalShape.FRAME.test(this.level.getBlockState(blockposition_mutableblockposition1), this.level, blockposition_mutableblockposition1)) { + return false; + } ++ blocks.setBlock(blockposition_mutableblockposition1, this.level.getBlockState(blockposition_mutableblockposition1), 18); // CraftBukkit - upper row + } + + return true; + } + + private int getDistanceUntilTop(BlockPos.MutableBlockPos pos) { +- for (int i = 0; i < 21; i++) { ++ for (int i = 0; i < 21; ++i) { + pos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, -1); +- if (!FRAME.test(this.level.getBlockState(pos), this.level, pos)) { ++ if (!PortalShape.FRAME.test(this.level.getBlockState(pos), this.level, pos)) { + return i; + } + + pos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, this.width); +- if (!FRAME.test(this.level.getBlockState(pos), this.level, pos)) { ++ if (!PortalShape.FRAME.test(this.level.getBlockState(pos), this.level, pos)) { + return i; + } + +- for (int i1 = 0; i1 < this.width; i1++) { +- pos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, i1); +- BlockState blockState = this.level.getBlockState(pos); +- if (!isEmpty(blockState)) { ++ for (int j = 0; j < this.width; ++j) { ++ pos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, j); ++ IBlockData iblockdata = this.level.getBlockState(pos); ++ ++ if (!isEmpty(iblockdata)) { + return i; + } + +- if (blockState.is(Blocks.NETHER_PORTAL)) { +- this.numPortalBlocks++; ++ if (iblockdata.is(Blocks.NETHER_PORTAL)) { ++ ++this.numPortalBlocks; + } + } ++ // CraftBukkit start - left and right ++ blocks.setBlock(pos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, -1), this.level.getBlockState(pos), 18); ++ blocks.setBlock(pos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, this.width), this.level.getBlockState(pos), 18); ++ // CraftBukkit end + } + + return 21; + } + +- private static boolean isEmpty(BlockState state) { ++ private static boolean isEmpty(IBlockData state) { + return state.isAir() || state.is(BlockTags.FIRE) || state.is(Blocks.NETHER_PORTAL); + } + +@@ -164,10 +189,28 @@ + return this.bottomLeft != null && this.width >= 2 && this.width <= 21 && this.height >= 3 && this.height <= 21; + } + +- public void createPortalBlocks() { +- BlockState blockState = Blocks.NETHER_PORTAL.defaultBlockState().setValue(NetherPortalBlock.AXIS, this.axis); +- BlockPos.betweenClosed(this.bottomLeft, this.bottomLeft.relative(Direction.UP, this.height - 1).relative(this.rightDir, this.width - 1)) +- .forEach(pos -> this.level.setBlock(pos, blockState, 18)); ++ // CraftBukkit start - return boolean ++ public boolean createPortalBlocks() { ++ org.bukkit.World bworld = this.level.getMinecraftWorld().getWorld(); ++ ++ // Copy below for loop ++ IBlockData iblockdata = (IBlockData) Blocks.NETHER_PORTAL.defaultBlockState().setValue(NetherPortalBlock.AXIS, this.axis); ++ ++ BlockPos.betweenClosed(this.bottomLeft, this.bottomLeft.relative(Direction.UP, this.height - 1).relative(this.rightDir, this.width - 1)).forEach((blockposition) -> { ++ blocks.setBlock(blockposition, iblockdata, 18); ++ }); ++ ++ PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) blocks.getList(), bworld, null, PortalCreateEvent.CreateReason.FIRE); ++ this.level.getMinecraftWorld().getServer().server.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ BlockPos.betweenClosed(this.bottomLeft, this.bottomLeft.relative(Direction.UP, this.height - 1).relative(this.rightDir, this.width - 1)).forEach((blockposition) -> { ++ this.level.setBlock(blockposition, iblockdata, 18); ++ }); ++ return true; // CraftBukkit + } + + public boolean isComplete() { +@@ -175,62 +218,64 @@ + } + + public static Vec3 getRelativePosition(BlockUtil.FoundRectangle foundRectangle, Direction.Axis axis, Vec3 pos, EntityDimensions entityDimensions) { +- double d = (double)foundRectangle.axis1Size - (double)entityDimensions.width; +- double d1 = (double)foundRectangle.axis2Size - (double)entityDimensions.height; +- BlockPos blockPos = foundRectangle.minCorner; ++ double d0 = (double) foundRectangle.axis1Size - (double) entityDimensions.width; ++ double d1 = (double) foundRectangle.axis2Size - (double) entityDimensions.height; ++ BlockPos blockposition = foundRectangle.minCorner; ++ double d2; + double d3; +- if (d > 0.0) { +- double d2 = (double)blockPos.get(axis) + (double)entityDimensions.width / 2.0; +- d3 = Mth.clamp(Mth.inverseLerp(pos.get(axis) - d2, 0.0, d), 0.0, 1.0); ++ ++ if (d0 > 0.0D) { ++ d2 = (double) blockposition.get(axis) + (double) entityDimensions.width / 2.0D; ++ d3 = Mth.clamp(Mth.inverseLerp(pos.get(axis) - d2, 0.0D, d0), 0.0D, 1.0D); + } else { +- d3 = 0.5; ++ d3 = 0.5D; + } + +- double d2; +- if (d1 > 0.0) { +- Direction.Axis axis1 = Direction.Axis.Y; +- d2 = Mth.clamp(Mth.inverseLerp(pos.get(axis1) - (double)blockPos.get(axis1), 0.0, d1), 0.0, 1.0); ++ Direction.Axis enumdirection_enumaxis1; ++ ++ if (d1 > 0.0D) { ++ enumdirection_enumaxis1 = Direction.Axis.Y; ++ d2 = Mth.clamp(Mth.inverseLerp(pos.get(enumdirection_enumaxis1) - (double) blockposition.get(enumdirection_enumaxis1), 0.0D, d1), 0.0D, 1.0D); + } else { +- d2 = 0.0; ++ d2 = 0.0D; + } + +- Direction.Axis axis1 = axis == Direction.Axis.X ? Direction.Axis.Z : Direction.Axis.X; +- double d4 = pos.get(axis1) - ((double)blockPos.get(axis1) + 0.5); ++ enumdirection_enumaxis1 = axis == Direction.Axis.X ? Direction.Axis.Z : Direction.Axis.X; ++ double d4 = pos.get(enumdirection_enumaxis1) - ((double) blockposition.get(enumdirection_enumaxis1) + 0.5D); ++ + return new Vec3(d3, d2, d4); + } + +- public static PortalInfo createPortalInfo( +- ServerLevel level, BlockUtil.FoundRectangle portalPos, Direction.Axis axis, Vec3 relativePos, Entity entity, Vec3 velocity, float yRot, float xRot +- ) { +- BlockPos blockPos = portalPos.minCorner; +- BlockState blockState = level.getBlockState(blockPos); +- Direction.Axis axis1 = blockState.getOptionalValue(BlockStateProperties.HORIZONTAL_AXIS).orElse(Direction.Axis.X); +- double d = (double)portalPos.axis1Size; +- double d1 = (double)portalPos.axis2Size; +- EntityDimensions dimensions = entity.getDimensions(entity.getPose()); +- int i = axis == axis1 ? 0 : 90; +- Vec3 vec3 = axis == axis1 ? velocity : new Vec3(velocity.z, velocity.y, -velocity.x); +- double d2 = (double)dimensions.width / 2.0 + (d - (double)dimensions.width) * relativePos.x(); +- double d3 = (d1 - (double)dimensions.height) * relativePos.y(); +- double d4 = 0.5 + relativePos.z(); +- boolean flag = axis1 == Direction.Axis.X; +- Vec3 vec31 = new Vec3((double)blockPos.getX() + (flag ? d2 : d4), (double)blockPos.getY() + d3, (double)blockPos.getZ() + (flag ? d4 : d2)); +- Vec3 vec32 = findCollisionFreePosition(vec31, level, entity, dimensions); +- return new PortalInfo(vec32, vec3, yRot + (float)i, xRot); ++ public static PortalInfo createPortalInfo(ServerLevel worldserver, BlockUtil.FoundRectangle blockutil_rectangle, Direction.Axis enumdirection_enumaxis, Vec3 vec3d, Entity entity, Vec3 vec3d1, float f, float f1, CraftPortalEvent portalEventInfo) { // CraftBukkit ++ BlockPos blockposition = blockutil_rectangle.minCorner; ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ Direction.Axis enumdirection_enumaxis1 = (Direction.Axis) iblockdata.getOptionalValue(BlockStateProperties.HORIZONTAL_AXIS).orElse(Direction.Axis.X); ++ double d0 = (double) blockutil_rectangle.axis1Size; ++ double d1 = (double) blockutil_rectangle.axis2Size; ++ EntityDimensions entitysize = entity.getDimensions(entity.getPose()); ++ int i = enumdirection_enumaxis == enumdirection_enumaxis1 ? 0 : 90; ++ Vec3 vec3d2 = enumdirection_enumaxis == enumdirection_enumaxis1 ? vec3d1 : new Vec3(vec3d1.z, vec3d1.y, -vec3d1.x); ++ double d2 = (double) entitysize.width / 2.0D + (d0 - (double) entitysize.width) * vec3d.x(); ++ double d3 = (d1 - (double) entitysize.height) * vec3d.y(); ++ double d4 = 0.5D + vec3d.z(); ++ boolean flag = enumdirection_enumaxis1 == Direction.Axis.X; ++ Vec3 vec3d3 = new Vec3((double) blockposition.getX() + (flag ? d2 : d4), (double) blockposition.getY() + d3, (double) blockposition.getZ() + (flag ? d4 : d2)); ++ Vec3 vec3d4 = findCollisionFreePosition(vec3d3, worldserver, entity, entitysize); ++ ++ return new PortalInfo(vec3d4, vec3d2, f + (float) i, f1, worldserver, portalEventInfo); // CraftBukkit + } + + private static Vec3 findCollisionFreePosition(Vec3 pos, ServerLevel level, Entity entity, EntityDimensions dimensions) { +- if (!(dimensions.width > 4.0F) && !(dimensions.height > 4.0F)) { +- double d = (double)dimensions.height / 2.0; +- Vec3 vec3 = pos.add(0.0, d, 0.0); +- VoxelShape voxelShape = Shapes.create( +- AABB.ofSize(vec3, (double)dimensions.width, 0.0, (double)dimensions.width).expandTowards(0.0, 1.0, 0.0).inflate(1.0E-6) +- ); +- Optional optional = level.findFreePosition( +- entity, voxelShape, vec3, (double)dimensions.width, (double)dimensions.height, (double)dimensions.width +- ); +- Optional optional1 = optional.map(freePos -> freePos.subtract(0.0, d, 0.0)); +- return optional1.orElse(pos); ++ if (dimensions.width <= 4.0F && dimensions.height <= 4.0F) { ++ double d0 = (double) dimensions.height / 2.0D; ++ Vec3 vec3d1 = pos.add(0.0D, d0, 0.0D); ++ VoxelShape voxelshape = Shapes.create(AABB.ofSize(vec3d1, (double) dimensions.width, 0.0D, (double) dimensions.width).expandTowards(0.0D, 1.0D, 0.0D).inflate(1.0E-6D)); ++ Optional optional = level.findFreePosition(entity, voxelshape, vec3d1, (double) dimensions.width, (double) dimensions.height, (double) dimensions.width); ++ Optional optional1 = optional.map((vec3d2) -> { ++ return vec3d2.subtract(0.0D, d0, 0.0D); ++ }); ++ ++ return (Vec3) optional1.orElse(pos); + } else { + return pos; + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/redstone/NeighborUpdater.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/redstone/NeighborUpdater.java.patch new file mode 100644 index 0000000000..1e953d6e34 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/redstone/NeighborUpdater.java.patch @@ -0,0 +1,111 @@ +--- a/net/minecraft/world/level/redstone/NeighborUpdater.java ++++ b/net/minecraft/world/level/redstone/NeighborUpdater.java +@@ -8,60 +8,75 @@ + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.core.registries.BuiltInRegistries; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.Block; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.event.block.BlockPhysicsEvent; ++// CraftBukkit end + + public interface NeighborUpdater { ++ + Direction[] UPDATE_ORDER = new Direction[]{Direction.WEST, Direction.EAST, Direction.DOWN, Direction.UP, Direction.NORTH, Direction.SOUTH}; + +- void shapeUpdate(Direction direction, BlockState state, BlockPos pos, BlockPos neighborPos, int flags, int recursionLevel); ++ void shapeUpdate(Direction direction, IBlockData state, BlockPos pos, BlockPos neighborPos, int flags, int recursionLevel); + + void neighborChanged(BlockPos pos, Block neighborBlock, BlockPos neighborPos); + +- void neighborChanged(BlockState state, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston); ++ void neighborChanged(IBlockData state, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston); + + default void updateNeighborsAtExceptFromFacing(BlockPos pos, Block block, @Nullable Direction facing) { +- for (Direction direction : UPDATE_ORDER) { +- if (direction != facing) { +- this.neighborChanged(pos.relative(direction), block, pos); ++ Direction[] aenumdirection = NeighborUpdater.UPDATE_ORDER; ++ int i = aenumdirection.length; ++ ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection1 = aenumdirection[j]; ++ ++ if (enumdirection1 != facing) { ++ this.neighborChanged(pos.relative(enumdirection1), block, pos); + } + } ++ + } + +- static void executeShapeUpdate( +- LevelAccessor level, Direction direction, BlockState state, BlockPos pos, BlockPos neighborPos, int flags, int recursionLevel +- ) { +- BlockState blockState = level.getBlockState(pos); +- BlockState blockState1 = blockState.updateShape(direction, state, level, pos, neighborPos); +- Block.updateOrDestroy(blockState, blockState1, level, pos, flags, recursionLevel); ++ static void executeShapeUpdate(LevelAccessor level, Direction direction, IBlockData state, BlockPos pos, BlockPos neighborPos, int flags, int recursionLevel) { ++ IBlockData iblockdata1 = level.getBlockState(pos); ++ IBlockData iblockdata2 = iblockdata1.updateShape(direction, state, level, pos, neighborPos); ++ ++ Block.updateOrDestroy(iblockdata1, iblockdata2, level, pos, flags, recursionLevel); + } + +- static void executeUpdate(Level level, BlockState state, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston) { ++ static void executeUpdate(Level level, IBlockData state, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston) { + try { ++ // CraftBukkit start ++ CraftWorld cworld = ((ServerLevel) level).getWorld(); ++ if (cworld != null) { ++ BlockPhysicsEvent event = new BlockPhysicsEvent(CraftBlock.at(level, pos), CraftBlockData.fromData(state), CraftBlock.at(level, neighborPos)); ++ ((ServerLevel) level).getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + state.neighborChanged(level, pos, neighborBlock, neighborPos, movedByPiston); +- } catch (Throwable var9) { +- CrashReport crashReport = CrashReport.forThrowable(var9, "Exception while updating neighbours"); +- CrashReportCategory crashReportCategory = crashReport.addCategory("Block being updated"); +- crashReportCategory.setDetail( +- "Source block type", +- () -> { +- try { +- return String.format( +- Locale.ROOT, +- "ID #%s (%s // %s)", +- BuiltInRegistries.BLOCK.getKey(neighborBlock), +- neighborBlock.getDescriptionId(), +- neighborBlock.getClass().getCanonicalName() +- ); +- } catch (Throwable var2x) { +- return "ID #" + BuiltInRegistries.BLOCK.getKey(neighborBlock); +- } ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception while updating neighbours"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being updated"); ++ ++ crashreportsystemdetails.setDetail("Source block type", () -> { ++ try { ++ return String.format(Locale.ROOT, "ID #%s (%s // %s)", BuiltInRegistries.BLOCK.getKey(neighborBlock), neighborBlock.getDescriptionId(), neighborBlock.getClass().getCanonicalName()); ++ } catch (Throwable throwable1) { ++ return "ID #" + BuiltInRegistries.BLOCK.getKey(neighborBlock); + } +- ); +- CrashReportCategory.populateBlockDetails(crashReportCategory, level, pos, state); +- throw new ReportedException(crashReport); ++ }); ++ CrashReportCategory.populateBlockDetails(crashreportsystemdetails, level, pos, state); ++ throw new ReportedException(crashreport); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java.patch new file mode 100644 index 0000000000..dacd6102bf --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java.patch @@ -0,0 +1,845 @@ +--- a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java ++++ b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +@@ -3,11 +3,13 @@ + import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import com.mojang.logging.LogUtils; ++import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; + import java.util.Collection; + import java.util.Iterator; + import java.util.List; + import java.util.Map; ++import java.util.Objects; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.nbt.CompoundTag; +@@ -31,29 +33,46 @@ + import net.minecraft.world.level.saveddata.SavedData; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.UUID; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.map.CraftMapView; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++// CraftBukkit end ++ + public class MapItemSavedData extends SavedData { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int MAP_SIZE = 128; + private static final int HALF_MAP_SIZE = 64; + public static final int MAX_SCALE = 4; + public static final int TRACKED_DECORATION_LIMIT = 256; +- public final int centerX; +- public final int centerZ; +- public final ResourceKey dimension; +- private final boolean trackingPosition; +- private final boolean unlimitedTracking; +- public final byte scale; ++ public int centerX; ++ public int centerZ; ++ public ResourceKey dimension; ++ public boolean trackingPosition; ++ public boolean unlimitedTracking; ++ public byte scale; + public byte[] colors = new byte[16384]; +- public final boolean locked; +- private final List carriedBy = Lists.newArrayList(); +- private final Map carriedByPlayers = Maps.newHashMap(); ++ public boolean locked; ++ public final List carriedBy = Lists.newArrayList(); ++ public final Map carriedByPlayers = Maps.newHashMap(); + private final Map bannerMarkers = Maps.newHashMap(); +- final Map decorations = Maps.newLinkedHashMap(); ++ public final Map decorations = Maps.newLinkedHashMap(); + private final Map frameMarkers = Maps.newHashMap(); + private int trackedDecorationCount; + +- public static SavedData.Factory factory() { +- return new SavedData.Factory<>(() -> { ++ // CraftBukkit start ++ public final CraftMapView mapView; ++ private CraftServer server; ++ public UUID uniqueId = null; ++ public String id; ++ // CraftBukkit end ++ ++ public static SavedData.a factory() { ++ return new SavedData.a<>(() -> { + throw new IllegalStateException("Should never create an empty map saved data"); + }, MapItemSavedData::load, DataFixTypes.SAVED_DATA_MAP_DATA); + } +@@ -67,17 +86,20 @@ + this.unlimitedTracking = unlimitedTracking; + this.locked = locked; + this.setDirty(); ++ // CraftBukkit start ++ mapView = new CraftMapView(this); ++ server = (CraftServer) org.bukkit.Bukkit.getServer(); ++ // CraftBukkit end + } + +- public static MapItemSavedData createFresh( +- double x, double z, byte scale, boolean trackingPosition, boolean unlimitedTracking, ResourceKey dimension +- ) { +- int i = 128 * (1 << scale); +- int floor = Mth.floor((x + 64.0) / (double)i); +- int floor1 = Mth.floor((z + 64.0) / (double)i); +- int i1 = floor * i + i / 2 - 64; +- int i2 = floor1 * i + i / 2 - 64; +- return new MapItemSavedData(i1, i2, scale, trackingPosition, unlimitedTracking, false, dimension); ++ public static MapItemSavedData createFresh(double x, double d1, byte z, boolean flag, boolean scale, ResourceKey trackingPosition) { ++ int i = 128 * (1 << z); ++ int j = Mth.floor((x + 64.0D) / (double) i); ++ int k = Mth.floor((d1 + 64.0D) / (double) i); ++ int l = j * i + i / 2 - 64; ++ int i1 = k * i + i / 2 - 64; ++ ++ return new MapItemSavedData(l, i1, z, flag, scale, false, trackingPosition); + } + + public static MapItemSavedData createForClient(byte scale, boolean locked, ResourceKey dimension) { +@@ -85,62 +107,93 @@ + } + + public static MapItemSavedData load(CompoundTag compoundTag) { +- ResourceKey resourceKey = DimensionType.parseLegacy(new Dynamic<>(NbtOps.INSTANCE, compoundTag.get("dimension"))) +- .resultOrPartial(LOGGER::error) +- .orElseThrow(() -> new IllegalArgumentException("Invalid map dimension: " + compoundTag.get("dimension"))); +- int _int = compoundTag.getInt("xCenter"); +- int _int1 = compoundTag.getInt("zCenter"); +- byte b = (byte)Mth.clamp(compoundTag.getByte("scale"), 0, 4); ++ DataResult> dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, compoundTag.get("dimension"))); // CraftBukkit - decompile error ++ Logger logger = MapItemSavedData.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ // CraftBukkit start ++ ResourceKey resourcekey = dataresult.resultOrPartial(logger::error).orElseGet(() -> { ++ long least = compoundTag.getLong("UUIDLeast"); ++ long most = compoundTag.getLong("UUIDMost"); ++ ++ if (least != 0L && most != 0L) { ++ UUID uniqueId = new UUID(most, least); ++ ++ CraftWorld world = (CraftWorld) Bukkit.getWorld(uniqueId); ++ // Check if the stored world details are correct. ++ if (world == null) { ++ /* All Maps which do not have their valid world loaded are set to a dimension which hopefully won't be reached. ++ This is to prevent them being corrupted with the wrong map data. */ ++ // PAIL: Use Vanilla exception handling for now ++ } else { ++ return world.getHandle().dimension(); ++ } ++ } ++ throw new IllegalArgumentException("Invalid map dimension: " + compoundTag.get("dimension")); ++ // CraftBukkit end ++ }); ++ int i = compoundTag.getInt("xCenter"); ++ int j = compoundTag.getInt("zCenter"); ++ byte b0 = (byte) Mth.clamp(compoundTag.getByte("scale"), 0, 4); + boolean flag = !compoundTag.contains("trackingPosition", 1) || compoundTag.getBoolean("trackingPosition"); +- boolean _boolean = compoundTag.getBoolean("unlimitedTracking"); +- boolean _boolean1 = compoundTag.getBoolean("locked"); +- MapItemSavedData mapItemSavedData = new MapItemSavedData(_int, _int1, b, flag, _boolean, _boolean1, resourceKey); +- byte[] byteArray = compoundTag.getByteArray("colors"); +- if (byteArray.length == 16384) { +- mapItemSavedData.colors = byteArray; ++ boolean flag1 = compoundTag.getBoolean("unlimitedTracking"); ++ boolean flag2 = compoundTag.getBoolean("locked"); ++ MapItemSavedData worldmap = new MapItemSavedData(i, j, b0, flag, flag1, flag2, resourcekey); ++ byte[] abyte = compoundTag.getByteArray("colors"); ++ ++ if (abyte.length == 16384) { ++ worldmap.colors = abyte; + } + +- ListTag list = compoundTag.getList("banners", 10); ++ ListTag nbttaglist = compoundTag.getList("banners", 10); + +- for (int i = 0; i < list.size(); i++) { +- MapBanner mapBanner = MapBanner.load(list.getCompound(i)); +- mapItemSavedData.bannerMarkers.put(mapBanner.getId(), mapBanner); +- mapItemSavedData.addDecoration( +- mapBanner.getDecoration(), +- null, +- mapBanner.getId(), +- (double)mapBanner.getPos().getX(), +- (double)mapBanner.getPos().getZ(), +- 180.0, +- mapBanner.getName() +- ); ++ for (int k = 0; k < nbttaglist.size(); ++k) { ++ MapBanner mapiconbanner = MapBanner.load(nbttaglist.getCompound(k)); ++ ++ worldmap.bannerMarkers.put(mapiconbanner.getId(), mapiconbanner); ++ worldmap.addDecoration(mapiconbanner.getDecoration(), (LevelAccessor) null, mapiconbanner.getId(), (double) mapiconbanner.getPos().getX(), (double) mapiconbanner.getPos().getZ(), 180.0D, mapiconbanner.getName()); + } + +- ListTag list1 = compoundTag.getList("frames", 10); ++ ListTag nbttaglist1 = compoundTag.getList("frames", 10); + +- for (int i1 = 0; i1 < list1.size(); i1++) { +- MapFrame mapFrame = MapFrame.load(list1.getCompound(i1)); +- mapItemSavedData.frameMarkers.put(mapFrame.getId(), mapFrame); +- mapItemSavedData.addDecoration( +- MapDecoration.Type.FRAME, +- null, +- "frame-" + mapFrame.getEntityId(), +- (double)mapFrame.getPos().getX(), +- (double)mapFrame.getPos().getZ(), +- (double)mapFrame.getRotation(), +- null +- ); ++ for (int l = 0; l < nbttaglist1.size(); ++l) { ++ MapFrame worldmapframe = MapFrame.load(nbttaglist1.getCompound(l)); ++ ++ worldmap.frameMarkers.put(worldmapframe.getId(), worldmapframe); ++ worldmap.addDecoration(MapDecoration.Type.FRAME, (LevelAccessor) null, "frame-" + worldmapframe.getEntityId(), (double) worldmapframe.getPos().getX(), (double) worldmapframe.getPos().getZ(), (double) worldmapframe.getRotation(), (Component) null); + } + +- return mapItemSavedData; ++ return worldmap; + } + + @Override + public CompoundTag save(CompoundTag compound) { +- ResourceLocation.CODEC +- .encodeStart(NbtOps.INSTANCE, this.dimension.location()) +- .resultOrPartial(LOGGER::error) +- .ifPresent(tag -> compound.put("dimension", tag)); ++ DataResult dataresult = ResourceLocation.CODEC.encodeStart(NbtOps.INSTANCE, this.dimension.location()); // CraftBukkit - decompile error ++ Logger logger = MapItemSavedData.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("dimension", nbtbase); ++ }); ++ // CraftBukkit start ++ if (true) { ++ if (this.uniqueId == null) { ++ for (org.bukkit.World world : server.getWorlds()) { ++ CraftWorld cWorld = (CraftWorld) world; ++ if (cWorld.getHandle().dimension() == this.dimension) { ++ this.uniqueId = cWorld.getUID(); ++ break; ++ } ++ } ++ } ++ /* Perform a second check to see if a matching world was found, this is a necessary ++ change incase Maps are forcefully unlinked from a World and lack a UID.*/ ++ if (this.uniqueId != null) { ++ compound.putLong("UUIDLeast", this.uniqueId.getLeastSignificantBits()); ++ compound.putLong("UUIDMost", this.uniqueId.getMostSignificantBits()); ++ } ++ } ++ // CraftBukkit end + compound.putInt("xCenter", this.centerX); + compound.putInt("zCenter", this.centerZ); + compound.putByte("scale", this.scale); +@@ -148,168 +201,154 @@ + compound.putBoolean("trackingPosition", this.trackingPosition); + compound.putBoolean("unlimitedTracking", this.unlimitedTracking); + compound.putBoolean("locked", this.locked); +- ListTag list = new ListTag(); ++ ListTag nbttaglist = new ListTag(); ++ Iterator iterator = this.bannerMarkers.values().iterator(); + +- for (MapBanner mapBanner : this.bannerMarkers.values()) { +- list.add(mapBanner.save()); ++ while (iterator.hasNext()) { ++ MapBanner mapiconbanner = (MapBanner) iterator.next(); ++ ++ nbttaglist.add(mapiconbanner.save()); + } + +- compound.put("banners", list); +- ListTag list1 = new ListTag(); ++ compound.put("banners", nbttaglist); ++ ListTag nbttaglist1 = new ListTag(); ++ Iterator iterator1 = this.frameMarkers.values().iterator(); + +- for (MapFrame mapFrame : this.frameMarkers.values()) { +- list1.add(mapFrame.save()); ++ while (iterator1.hasNext()) { ++ MapFrame worldmapframe = (MapFrame) iterator1.next(); ++ ++ nbttaglist1.add(worldmapframe.save()); + } + +- compound.put("frames", list1); ++ compound.put("frames", nbttaglist1); + return compound; + } + + public MapItemSavedData locked() { +- MapItemSavedData mapItemSavedData = new MapItemSavedData( +- this.centerX, this.centerZ, this.scale, this.trackingPosition, this.unlimitedTracking, true, this.dimension +- ); +- mapItemSavedData.bannerMarkers.putAll(this.bannerMarkers); +- mapItemSavedData.decorations.putAll(this.decorations); +- mapItemSavedData.trackedDecorationCount = this.trackedDecorationCount; +- System.arraycopy(this.colors, 0, mapItemSavedData.colors, 0, this.colors.length); +- mapItemSavedData.setDirty(); +- return mapItemSavedData; ++ MapItemSavedData worldmap = new MapItemSavedData(this.centerX, this.centerZ, this.scale, this.trackingPosition, this.unlimitedTracking, true, this.dimension); ++ ++ worldmap.bannerMarkers.putAll(this.bannerMarkers); ++ worldmap.decorations.putAll(this.decorations); ++ worldmap.trackedDecorationCount = this.trackedDecorationCount; ++ System.arraycopy(this.colors, 0, worldmap.colors, 0, this.colors.length); ++ worldmap.setDirty(); ++ return worldmap; + } + + public MapItemSavedData scaled(int scalar) { +- return createFresh( +- (double)this.centerX, +- (double)this.centerZ, +- (byte)Mth.clamp(this.scale + scalar, 0, 4), +- this.trackingPosition, +- this.unlimitedTracking, +- this.dimension +- ); ++ return createFresh((double) this.centerX, (double) this.centerZ, (byte) Mth.clamp(this.scale + scalar, 0, 4), this.trackingPosition, this.unlimitedTracking, this.dimension); + } + + public void tickCarriedBy(Player player, ItemStack mapStack) { + if (!this.carriedByPlayers.containsKey(player)) { +- MapItemSavedData.HoldingPlayer holdingPlayer = new MapItemSavedData.HoldingPlayer(player); +- this.carriedByPlayers.put(player, holdingPlayer); +- this.carriedBy.add(holdingPlayer); ++ MapItemSavedData.HoldingPlayer worldmap_worldmaphumantracker = new MapItemSavedData.HoldingPlayer(player); ++ ++ this.carriedByPlayers.put(player, worldmap_worldmaphumantracker); ++ this.carriedBy.add(worldmap_worldmaphumantracker); + } + + if (!player.getInventory().contains(mapStack)) { + this.removeDecoration(player.getName().getString()); + } + +- for (int i = 0; i < this.carriedBy.size(); i++) { +- MapItemSavedData.HoldingPlayer holdingPlayer1 = this.carriedBy.get(i); +- String string = holdingPlayer1.player.getName().getString(); +- if (!holdingPlayer1.player.isRemoved() && (holdingPlayer1.player.getInventory().contains(mapStack) || mapStack.isFramed())) { +- if (!mapStack.isFramed() && holdingPlayer1.player.level().dimension() == this.dimension && this.trackingPosition) { +- this.addDecoration( +- MapDecoration.Type.PLAYER, +- holdingPlayer1.player.level(), +- string, +- holdingPlayer1.player.getX(), +- holdingPlayer1.player.getZ(), +- (double)holdingPlayer1.player.getYRot(), +- null +- ); ++ for (int i = 0; i < this.carriedBy.size(); ++i) { ++ MapItemSavedData.HoldingPlayer worldmap_worldmaphumantracker1 = (MapItemSavedData.HoldingPlayer) this.carriedBy.get(i); ++ String s = worldmap_worldmaphumantracker1.player.getName().getString(); ++ ++ if (!worldmap_worldmaphumantracker1.player.isRemoved() && (worldmap_worldmaphumantracker1.player.getInventory().contains(mapStack) || mapStack.isFramed())) { ++ if (!mapStack.isFramed() && worldmap_worldmaphumantracker1.player.level().dimension() == this.dimension && this.trackingPosition) { ++ this.addDecoration(MapDecoration.Type.PLAYER, worldmap_worldmaphumantracker1.player.level(), s, worldmap_worldmaphumantracker1.player.getX(), worldmap_worldmaphumantracker1.player.getZ(), (double) worldmap_worldmaphumantracker1.player.getYRot(), (Component) null); + } + } else { +- this.carriedByPlayers.remove(holdingPlayer1.player); +- this.carriedBy.remove(holdingPlayer1); +- this.removeDecoration(string); ++ this.carriedByPlayers.remove(worldmap_worldmaphumantracker1.player); ++ this.carriedBy.remove(worldmap_worldmaphumantracker1); ++ this.removeDecoration(s); + } + } + + if (mapStack.isFramed() && this.trackingPosition) { +- ItemFrame frame = mapStack.getFrame(); +- BlockPos pos = frame.getPos(); +- MapFrame mapFrame = this.frameMarkers.get(MapFrame.frameId(pos)); +- if (mapFrame != null && frame.getId() != mapFrame.getEntityId() && this.frameMarkers.containsKey(mapFrame.getId())) { +- this.removeDecoration("frame-" + mapFrame.getEntityId()); ++ ItemFrame entityitemframe = mapStack.getFrame(); ++ BlockPos blockposition = entityitemframe.getPos(); ++ MapFrame worldmapframe = (MapFrame) this.frameMarkers.get(MapFrame.frameId(blockposition)); ++ ++ if (worldmapframe != null && entityitemframe.getId() != worldmapframe.getEntityId() && this.frameMarkers.containsKey(worldmapframe.getId())) { ++ this.removeDecoration("frame-" + worldmapframe.getEntityId()); + } + +- MapFrame mapFrame1 = new MapFrame(pos, frame.getDirection().get2DDataValue() * 90, frame.getId()); +- this.addDecoration( +- MapDecoration.Type.FRAME, +- player.level(), +- "frame-" + frame.getId(), +- (double)pos.getX(), +- (double)pos.getZ(), +- (double)(frame.getDirection().get2DDataValue() * 90), +- null +- ); +- this.frameMarkers.put(mapFrame1.getId(), mapFrame1); ++ MapFrame worldmapframe1 = new MapFrame(blockposition, entityitemframe.getDirection().get2DDataValue() * 90, entityitemframe.getId()); ++ ++ this.addDecoration(MapDecoration.Type.FRAME, player.level(), "frame-" + entityitemframe.getId(), (double) blockposition.getX(), (double) blockposition.getZ(), (double) (entityitemframe.getDirection().get2DDataValue() * 90), (Component) null); ++ this.frameMarkers.put(worldmapframe1.getId(), worldmapframe1); + } + +- CompoundTag tag = mapStack.getTag(); +- if (tag != null && tag.contains("Decorations", 9)) { +- ListTag list = tag.getList("Decorations", 10); ++ CompoundTag nbttagcompound = mapStack.getTag(); + +- for (int i1 = 0; i1 < list.size(); i1++) { +- CompoundTag compound = list.getCompound(i1); +- if (!this.decorations.containsKey(compound.getString("id"))) { +- this.addDecoration( +- MapDecoration.Type.byIcon(compound.getByte("type")), +- player.level(), +- compound.getString("id"), +- compound.getDouble("x"), +- compound.getDouble("z"), +- compound.getDouble("rot"), +- null +- ); ++ if (nbttagcompound != null && nbttagcompound.contains("Decorations", 9)) { ++ ListTag nbttaglist = nbttagcompound.getList("Decorations", 10); ++ ++ for (int j = 0; j < nbttaglist.size(); ++j) { ++ CompoundTag nbttagcompound1 = nbttaglist.getCompound(j); ++ ++ if (!this.decorations.containsKey(nbttagcompound1.getString("id"))) { ++ this.addDecoration(MapDecoration.Type.byIcon(nbttagcompound1.getByte("type")), player.level(), nbttagcompound1.getString("id"), nbttagcompound1.getDouble("x"), nbttagcompound1.getDouble("z"), nbttagcompound1.getDouble("rot"), (Component) null); + } + } + } ++ + } + + private void removeDecoration(String identifier) { +- MapDecoration mapDecoration = this.decorations.remove(identifier); +- if (mapDecoration != null && mapDecoration.type().shouldTrackCount()) { +- this.trackedDecorationCount--; ++ MapDecoration mapicon = (MapDecoration) this.decorations.remove(identifier); ++ ++ if (mapicon != null && mapicon.type().shouldTrackCount()) { ++ --this.trackedDecorationCount; + } + + this.setDecorationsDirty(); + } + + public static void addTargetDecoration(ItemStack map, BlockPos target, String decorationName, MapDecoration.Type type) { +- ListTag list; ++ ListTag nbttaglist; ++ + if (map.hasTag() && map.getTag().contains("Decorations", 9)) { +- list = map.getTag().getList("Decorations", 10); ++ nbttaglist = map.getTag().getList("Decorations", 10); + } else { +- list = new ListTag(); +- map.addTagElement("Decorations", list); ++ nbttaglist = new ListTag(); ++ map.addTagElement("Decorations", nbttaglist); + } + +- CompoundTag compoundTag = new CompoundTag(); +- compoundTag.putByte("type", type.getIcon()); +- compoundTag.putString("id", decorationName); +- compoundTag.putDouble("x", (double)target.getX()); +- compoundTag.putDouble("z", (double)target.getZ()); +- compoundTag.putDouble("rot", 180.0); +- list.add(compoundTag); ++ CompoundTag nbttagcompound = new CompoundTag(); ++ ++ nbttagcompound.putByte("type", type.getIcon()); ++ nbttagcompound.putString("id", decorationName); ++ nbttagcompound.putDouble("x", (double) target.getX()); ++ nbttagcompound.putDouble("z", (double) target.getZ()); ++ nbttagcompound.putDouble("rot", 180.0D); ++ nbttaglist.add(nbttagcompound); + if (type.hasMapColor()) { +- CompoundTag tagElement = map.getOrCreateTagElement("display"); +- tagElement.putInt("MapColor", type.getMapColor()); ++ CompoundTag nbttagcompound1 = map.getOrCreateTagElement("display"); ++ ++ nbttagcompound1.putInt("MapColor", type.getMapColor()); + } ++ + } + +- private void addDecoration( +- MapDecoration.Type type, @Nullable LevelAccessor level, String decorationName, double levelX, double levelZ, double rotation, @Nullable Component name +- ) { ++ private void addDecoration(MapDecoration.Type type, @Nullable LevelAccessor level, String decorationName, double levelX, double d1, double levelZ, @Nullable Component ichatbasecomponent) { + int i = 1 << this.scale; +- float f = (float)(levelX - (double)this.centerX) / (float)i; +- float f1 = (float)(levelZ - (double)this.centerZ) / (float)i; +- byte b = (byte)((int)((double)(f * 2.0F) + 0.5)); +- byte b1 = (byte)((int)((double)(f1 * 2.0F) + 0.5)); +- int i1 = 63; ++ float f = (float) (levelX - (double) this.centerX) / (float) i; ++ float f1 = (float) (d1 - (double) this.centerZ) / (float) i; ++ byte b0 = (byte) ((int) ((double) (f * 2.0F) + 0.5D)); ++ byte b1 = (byte) ((int) ((double) (f1 * 2.0F) + 0.5D)); ++ boolean flag = true; + byte b2; ++ + if (f >= -63.0F && f1 >= -63.0F && f <= 63.0F && f1 <= 63.0F) { +- rotation += rotation < 0.0 ? -8.0 : 8.0; +- b2 = (byte)((int)(rotation * 16.0 / 360.0)); ++ levelZ += levelZ < 0.0D ? -8.0D : 8.0D; ++ b2 = (byte) ((int) (levelZ * 16.0D / 360.0D)); + if (this.dimension == Level.NETHER && level != null) { +- int i2 = (int)(level.getLevelData().getDayTime() / 10L); +- b2 = (byte)(i2 * i2 * 34187121 + i2 * 121 >> 15 & 15); ++ int j = (int) (level.getLevelData().getDayTime() / 10L); ++ ++ b2 = (byte) (j * j * 34187121 + j * 121 >> 15 & 15); + } + } else { + if (type != MapDecoration.Type.PLAYER) { +@@ -317,7 +356,8 @@ + return; + } + +- int i2 = 320; ++ boolean flag1 = true; ++ + if (Math.abs(f) < 320.0F && Math.abs(f1) < 320.0F) { + type = MapDecoration.Type.PLAYER_OFF_MAP; + } else { +@@ -331,7 +371,7 @@ + + b2 = 0; + if (f <= -63.0F) { +- b = -128; ++ b0 = -128; + } + + if (f1 <= -63.0F) { +@@ -339,7 +379,7 @@ + } + + if (f >= 63.0F) { +- b = 127; ++ b0 = 127; + } + + if (f1 >= 63.0F) { +@@ -347,72 +387,82 @@ + } + } + +- MapDecoration mapDecoration = new MapDecoration(type, b, b1, b2, name); +- MapDecoration mapDecoration1 = this.decorations.put(decorationName, mapDecoration); +- if (!mapDecoration.equals(mapDecoration1)) { +- if (mapDecoration1 != null && mapDecoration1.type().shouldTrackCount()) { +- this.trackedDecorationCount--; ++ MapDecoration mapicon = new MapDecoration(type, b0, b1, b2, ichatbasecomponent); ++ MapDecoration mapicon1 = (MapDecoration) this.decorations.put(decorationName, mapicon); ++ ++ if (!mapicon.equals(mapicon1)) { ++ if (mapicon1 != null && mapicon1.type().shouldTrackCount()) { ++ --this.trackedDecorationCount; + } + + if (type.shouldTrackCount()) { +- this.trackedDecorationCount++; ++ ++this.trackedDecorationCount; + } + + this.setDecorationsDirty(); + } ++ + } + + @Nullable + public Packet getUpdatePacket(int mapId, Player player) { +- MapItemSavedData.HoldingPlayer holdingPlayer = this.carriedByPlayers.get(player); +- return holdingPlayer == null ? null : holdingPlayer.nextUpdatePacket(mapId); ++ MapItemSavedData.HoldingPlayer worldmap_worldmaphumantracker = (MapItemSavedData.HoldingPlayer) this.carriedByPlayers.get(player); ++ ++ return worldmap_worldmaphumantracker == null ? null : worldmap_worldmaphumantracker.nextUpdatePacket(mapId); + } + +- private void setColorsDirty(int x, int z) { ++ public void setColorsDirty(int x, int z) { + this.setDirty(); ++ Iterator iterator = this.carriedBy.iterator(); + +- for (MapItemSavedData.HoldingPlayer holdingPlayer : this.carriedBy) { +- holdingPlayer.markColorsDirty(x, z); ++ while (iterator.hasNext()) { ++ MapItemSavedData.HoldingPlayer worldmap_worldmaphumantracker = (MapItemSavedData.HoldingPlayer) iterator.next(); ++ ++ worldmap_worldmaphumantracker.markColorsDirty(x, z); + } ++ + } + +- private void setDecorationsDirty() { ++ public void setDecorationsDirty() { + this.setDirty(); + this.carriedBy.forEach(MapItemSavedData.HoldingPlayer::markDecorationsDirty); + } + + public MapItemSavedData.HoldingPlayer getHoldingPlayer(Player player) { +- MapItemSavedData.HoldingPlayer holdingPlayer = this.carriedByPlayers.get(player); +- if (holdingPlayer == null) { +- holdingPlayer = new MapItemSavedData.HoldingPlayer(player); +- this.carriedByPlayers.put(player, holdingPlayer); +- this.carriedBy.add(holdingPlayer); ++ MapItemSavedData.HoldingPlayer worldmap_worldmaphumantracker = (MapItemSavedData.HoldingPlayer) this.carriedByPlayers.get(player); ++ ++ if (worldmap_worldmaphumantracker == null) { ++ worldmap_worldmaphumantracker = new MapItemSavedData.HoldingPlayer(player); ++ this.carriedByPlayers.put(player, worldmap_worldmaphumantracker); ++ this.carriedBy.add(worldmap_worldmaphumantracker); + } + +- return holdingPlayer; ++ return worldmap_worldmaphumantracker; + } + + public boolean toggleBanner(LevelAccessor accessor, BlockPos pos) { +- double d = (double)pos.getX() + 0.5; +- double d1 = (double)pos.getZ() + 0.5; ++ double d0 = (double) pos.getX() + 0.5D; ++ double d1 = (double) pos.getZ() + 0.5D; + int i = 1 << this.scale; +- double d2 = (d - (double)this.centerX) / (double)i; +- double d3 = (d1 - (double)this.centerZ) / (double)i; +- int i1 = 63; +- if (d2 >= -63.0 && d3 >= -63.0 && d2 <= 63.0 && d3 <= 63.0) { +- MapBanner mapBanner = MapBanner.fromWorld(accessor, pos); +- if (mapBanner == null) { ++ double d2 = (d0 - (double) this.centerX) / (double) i; ++ double d3 = (d1 - (double) this.centerZ) / (double) i; ++ boolean flag = true; ++ ++ if (d2 >= -63.0D && d3 >= -63.0D && d2 <= 63.0D && d3 <= 63.0D) { ++ MapBanner mapiconbanner = MapBanner.fromWorld(accessor, pos); ++ ++ if (mapiconbanner == null) { + return false; + } + +- if (this.bannerMarkers.remove(mapBanner.getId(), mapBanner)) { +- this.removeDecoration(mapBanner.getId()); ++ if (this.bannerMarkers.remove(mapiconbanner.getId(), mapiconbanner)) { ++ this.removeDecoration(mapiconbanner.getId()); + return true; + } + + if (!this.isTrackedCountOverLimit(256)) { +- this.bannerMarkers.put(mapBanner.getId(), mapBanner); +- this.addDecoration(mapBanner.getDecoration(), accessor, mapBanner.getId(), d, d1, 180.0, mapBanner.getName()); ++ this.bannerMarkers.put(mapiconbanner.getId(), mapiconbanner); ++ this.addDecoration(mapiconbanner.getDecoration(), accessor, mapiconbanner.getId(), d0, d1, 180.0D, mapiconbanner.getName()); + return true; + } + } +@@ -421,18 +471,21 @@ + } + + public void checkBanners(BlockGetter reader, int x, int z) { +- Iterator iterator = this.bannerMarkers.values().iterator(); ++ Iterator iterator = this.bannerMarkers.values().iterator(); + + while (iterator.hasNext()) { +- MapBanner mapBanner = iterator.next(); +- if (mapBanner.getPos().getX() == x && mapBanner.getPos().getZ() == z) { +- MapBanner mapBanner1 = MapBanner.fromWorld(reader, mapBanner.getPos()); +- if (!mapBanner.equals(mapBanner1)) { ++ MapBanner mapiconbanner = (MapBanner) iterator.next(); ++ ++ if (mapiconbanner.getPos().getX() == x && mapiconbanner.getPos().getZ() == z) { ++ MapBanner mapiconbanner1 = MapBanner.fromWorld(reader, mapiconbanner.getPos()); ++ ++ if (!mapiconbanner.equals(mapiconbanner1)) { + iterator.remove(); +- this.removeDecoration(mapBanner.getId()); ++ this.removeDecoration(mapiconbanner.getId()); + } + } + } ++ + } + + public Collection getBanners() { +@@ -445,8 +498,9 @@ + } + + public boolean updateColor(int x, int z, byte color) { +- byte b = this.colors[x + z * 128]; +- if (b != color) { ++ byte b1 = this.colors[x + z * 128]; ++ ++ if (b1 != color) { + this.setColor(x, z, color); + return true; + } else { +@@ -460,26 +514,34 @@ + } + + public boolean isExplorationMap() { +- for (MapDecoration mapDecoration : this.decorations.values()) { +- if (mapDecoration.type().isExplorationMapElement()) { +- return true; ++ Iterator iterator = this.decorations.values().iterator(); ++ ++ MapDecoration mapicon; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return false; + } +- } + +- return false; ++ mapicon = (MapDecoration) iterator.next(); ++ } while (!mapicon.type().isExplorationMapElement()); ++ ++ return true; + } + + public void addClientSideDecorations(List decorations) { + this.decorations.clear(); + this.trackedDecorationCount = 0; + +- for (int i = 0; i < decorations.size(); i++) { +- MapDecoration mapDecoration = decorations.get(i); +- this.decorations.put("icon-" + i, mapDecoration); +- if (mapDecoration.type().shouldTrackCount()) { +- this.trackedDecorationCount++; ++ for (int i = 0; i < decorations.size(); ++i) { ++ MapDecoration mapicon = (MapDecoration) decorations.get(i); ++ ++ this.decorations.put("icon-" + i, mapicon); ++ if (mapicon.type().shouldTrackCount()) { ++ ++this.trackedDecorationCount; + } + } ++ + } + + public Iterable getDecorations() { +@@ -491,6 +553,7 @@ + } + + public class HoldingPlayer { ++ + public final Player player; + private boolean dirtyData = true; + private int minDirtyX; +@@ -501,47 +564,57 @@ + private int tick; + public int step; + +- HoldingPlayer(Player player) { +- this.player = player; ++ HoldingPlayer(Player entityhuman) { ++ this.player = entityhuman; + } + +- private MapItemSavedData.MapPatch createPatch() { ++ private MapItemSavedData.MapPatch createPatch(byte[] buffer) { // CraftBukkit + int i = this.minDirtyX; +- int i1 = this.minDirtyY; +- int i2 = this.maxDirtyX + 1 - this.minDirtyX; +- int i3 = this.maxDirtyY + 1 - this.minDirtyY; +- byte[] bytes = new byte[i2 * i3]; ++ int j = this.minDirtyY; ++ int k = this.maxDirtyX + 1 - this.minDirtyX; ++ int l = this.maxDirtyY + 1 - this.minDirtyY; ++ byte[] abyte = new byte[k * l]; + +- for (int i4 = 0; i4 < i2; i4++) { +- for (int i5 = 0; i5 < i3; i5++) { +- bytes[i4 + i5 * i2] = MapItemSavedData.this.colors[i + i4 + (i1 + i5) * 128]; ++ for (int i1 = 0; i1 < k; ++i1) { ++ for (int j1 = 0; j1 < l; ++j1) { ++ abyte[i1 + j1 * k] = buffer[i + i1 + (j + j1) * 128]; // CraftBukkit + } + } + +- return new MapItemSavedData.MapPatch(i, i1, i2, i3, bytes); ++ return new MapItemSavedData.MapPatch(i, j, k, l, abyte); + } + + @Nullable + Packet nextUpdatePacket(int mapId) { +- MapItemSavedData.MapPatch mapPatch; ++ MapItemSavedData.MapPatch worldmap_b; ++ org.bukkit.craftbukkit.map.RenderData render = MapItemSavedData.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()); // CraftBukkit ++ + if (this.dirtyData) { + this.dirtyData = false; +- mapPatch = this.createPatch(); ++ worldmap_b = this.createPatch(render.buffer); // CraftBukkit + } else { +- mapPatch = null; ++ worldmap_b = null; + } + +- Collection collection; +- if (this.dirtyDecorations && this.tick++ % 5 == 0) { ++ Collection collection; ++ ++ if ((true || this.dirtyDecorations) && this.tick++ % 5 == 0) { // CraftBukkit - custom maps don't update this yet + this.dirtyDecorations = false; +- collection = MapItemSavedData.this.decorations.values(); ++ // CraftBukkit start ++ java.util.Collection icons = new java.util.ArrayList(); ++ ++ for (org.bukkit.map.MapCursor cursor : render.cursors) { ++ if (cursor.isVisible()) { ++ icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption()))); ++ } ++ } ++ collection = icons; ++ // CraftBukkit end + } else { + collection = null; + } + +- return collection == null && mapPatch == null +- ? null +- : new ClientboundMapItemDataPacket(mapId, MapItemSavedData.this.scale, MapItemSavedData.this.locked, collection, mapPatch); ++ return collection == null && worldmap_b == null ? null : new ClientboundMapItemDataPacket(mapId, MapItemSavedData.this.scale, MapItemSavedData.this.locked, collection, worldmap_b); + } + + void markColorsDirty(int x, int z) { +@@ -557,6 +630,7 @@ + this.maxDirtyX = x; + this.maxDirtyY = z; + } ++ + } + + private void markDecorationsDirty() { +@@ -565,6 +639,7 @@ + } + + public static class MapPatch { ++ + public final int startX; + public final int startY; + public final int width; +@@ -580,11 +655,12 @@ + } + + public void applyToMap(MapItemSavedData savedData) { +- for (int i = 0; i < this.width; i++) { +- for (int i1 = 0; i1 < this.height; i1++) { +- savedData.setColor(this.startX + i, this.startY + i1, this.mapColors[i + i1 * this.width]); ++ for (int i = 0; i < this.width; ++i) { ++ for (int j = 0; j < this.height; ++j) { ++ savedData.setColor(this.startX + i, this.startY + j, this.mapColors[i + j * this.width]); + } + } ++ + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/storage/LevelStorageSource.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/storage/LevelStorageSource.java.patch new file mode 100644 index 0000000000..9c88e4dd28 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/storage/LevelStorageSource.java.patch @@ -0,0 +1,865 @@ +--- a/net/minecraft/world/level/storage/LevelStorageSource.java ++++ b/net/minecraft/world/level/storage/LevelStorageSource.java +@@ -3,6 +3,7 @@ + import com.google.common.collect.Maps; + import com.mojang.datafixers.DataFixer; + import com.mojang.logging.LogUtils; ++import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; + import com.mojang.serialization.Lifecycle; + import java.io.BufferedOutputStream; +@@ -12,6 +13,7 @@ + import java.nio.file.FileVisitResult; + import java.nio.file.Files; + import java.nio.file.InvalidPathException; ++import java.nio.file.LinkOption; + import java.nio.file.Path; + import java.nio.file.PathMatcher; + import java.nio.file.Paths; +@@ -42,6 +44,7 @@ + import net.minecraft.FileUtil; + import net.minecraft.ReportedException; + import net.minecraft.Util; ++import net.minecraft.core.HolderLookup; + import net.minecraft.core.Registry; + import net.minecraft.core.RegistryAccess; + import net.minecraft.nbt.CompoundTag; +@@ -68,7 +71,6 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelSettings; + import net.minecraft.world.level.WorldDataConfiguration; +-import net.minecraft.world.level.dimension.DimensionType; + import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.levelgen.WorldDimensions; + import net.minecraft.world.level.levelgen.WorldGenSettings; +@@ -79,25 +81,16 @@ + import org.slf4j.Logger; + + public class LevelStorageSource { ++ + static final Logger LOGGER = LogUtils.getLogger(); +- static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder() +- .appendValue(ChronoField.YEAR, 4, 10, SignStyle.EXCEEDS_PAD) +- .appendLiteral('-') +- .appendValue(ChronoField.MONTH_OF_YEAR, 2) +- .appendLiteral('-') +- .appendValue(ChronoField.DAY_OF_MONTH, 2) +- .appendLiteral('_') +- .appendValue(ChronoField.HOUR_OF_DAY, 2) +- .appendLiteral('-') +- .appendValue(ChronoField.MINUTE_OF_HOUR, 2) +- .appendLiteral('-') +- .appendValue(ChronoField.SECOND_OF_MINUTE, 2) +- .toFormatter(); ++ static final DateTimeFormatter FORMATTER = (new DateTimeFormatterBuilder()).appendValue(ChronoField.YEAR, 4, 10, SignStyle.EXCEEDS_PAD).appendLiteral('-').appendValue(ChronoField.MONTH_OF_YEAR, 2).appendLiteral('-').appendValue(ChronoField.DAY_OF_MONTH, 2).appendLiteral('_').appendValue(ChronoField.HOUR_OF_DAY, 2).appendLiteral('-').appendValue(ChronoField.MINUTE_OF_HOUR, 2).appendLiteral('-').appendValue(ChronoField.SECOND_OF_MINUTE, 2).toFormatter(); + private static final String TAG_DATA = "Data"; +- private static final PathMatcher NO_SYMLINKS_ALLOWED = path -> false; ++ private static final PathMatcher NO_SYMLINKS_ALLOWED = (path) -> { ++ return false; ++ }; + public static final String ALLOWED_SYMLINKS_CONFIG_NAME = "allowed_symlinks.txt"; + private static final int UNCOMPRESSED_NBT_QUOTA = 104857600; +- private final Path baseDir; ++ public final Path baseDir; + private final Path backupDir; + final DataFixer fixerUpper; + private final DirectoryValidator worldDirValidator; +@@ -107,8 +100,8 @@ + + try { + FileUtil.createDirectoriesSafe(baseDir); +- } catch (IOException var6) { +- throw new UncheckedIOException(var6); ++ } catch (IOException ioexception) { ++ throw new UncheckedIOException(ioexception); + } + + this.baseDir = baseDir; +@@ -117,119 +110,173 @@ + } + + public static DirectoryValidator parseValidator(Path validator) { +- if (Files.exists(validator)) { ++ if (Files.exists(validator, new LinkOption[0])) { + try { +- DirectoryValidator var2; +- try (BufferedReader bufferedReader = Files.newBufferedReader(validator)) { +- var2 = new DirectoryValidator(PathAllowList.readPlain(bufferedReader)); ++ BufferedReader bufferedreader = Files.newBufferedReader(validator); ++ ++ DirectoryValidator directoryvalidator; ++ ++ try { ++ directoryvalidator = new DirectoryValidator(PathAllowList.readPlain(bufferedreader)); ++ } catch (Throwable throwable) { ++ if (bufferedreader != null) { ++ try { ++ bufferedreader.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } + +- return var2; +- } catch (Exception var6) { +- LOGGER.error("Failed to parse {}, disallowing all symbolic links", "allowed_symlinks.txt", var6); ++ if (bufferedreader != null) { ++ bufferedreader.close(); ++ } ++ ++ return directoryvalidator; ++ } catch (Exception exception) { ++ LevelStorageSource.LOGGER.error("Failed to parse {}, disallowing all symbolic links", "allowed_symlinks.txt", exception); + } + } + +- return new DirectoryValidator(NO_SYMLINKS_ALLOWED); ++ return new DirectoryValidator(LevelStorageSource.NO_SYMLINKS_ALLOWED); + } + + public static LevelStorageSource createDefault(Path savesDir) { +- DirectoryValidator directoryValidator = parseValidator(savesDir.resolve("allowed_symlinks.txt")); +- return new LevelStorageSource(savesDir, savesDir.resolve("../backups"), directoryValidator, DataFixers.getDataFixer()); ++ DirectoryValidator directoryvalidator = parseValidator(savesDir.resolve("allowed_symlinks.txt")); ++ ++ return new LevelStorageSource(savesDir, savesDir.resolve("../backups"), directoryvalidator, DataFixers.getDataFixer()); + } + + public static WorldDataConfiguration readDataConfig(Dynamic dynamic) { +- return WorldDataConfiguration.CODEC.parse(dynamic).resultOrPartial(LOGGER::error).orElse(WorldDataConfiguration.DEFAULT); ++ DataResult dataresult = WorldDataConfiguration.CODEC.parse(dynamic); // CraftBukkit - decompile error ++ Logger logger = LevelStorageSource.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ return (WorldDataConfiguration) dataresult.resultOrPartial(logger::error).orElse(WorldDataConfiguration.DEFAULT); + } + +- public static WorldLoader.PackConfig getPackConfig(Dynamic dynamic, PackRepository packRepository, boolean flag) { +- return new WorldLoader.PackConfig(packRepository, readDataConfig(dynamic), flag, false); ++ public static WorldLoader.d getPackConfig(Dynamic dynamic, PackRepository resourcepackrepository, boolean flag) { ++ return new WorldLoader.d(resourcepackrepository, readDataConfig(dynamic), flag, false); + } + +- public static LevelDataAndDimensions getLevelDataAndDimensions( +- Dynamic dynamic, WorldDataConfiguration worldDataConfiguration, Registry registry, RegistryAccess.Frozen frozen +- ) { +- Dynamic dynamic1 = wrapWithRegistryOps(dynamic, frozen); ++ public static LevelDataAndDimensions getLevelDataAndDimensions(Dynamic dynamic, WorldDataConfiguration worlddataconfiguration, Registry iregistry, RegistryAccess.Dimension iregistrycustom_dimension) { ++ Dynamic dynamic1 = wrapWithRegistryOps(dynamic, iregistrycustom_dimension); + Dynamic dynamic2 = dynamic1.get("WorldGenSettings").orElseEmptyMap(); +- WorldGenSettings worldGenSettings = WorldGenSettings.CODEC.parse(dynamic2).getOrThrow(false, Util.prefix("WorldGenSettings: ", LOGGER::error)); +- LevelSettings levelSettings = LevelSettings.parse(dynamic1, worldDataConfiguration); +- WorldDimensions.Complete complete = worldGenSettings.dimensions().bake(registry); +- Lifecycle lifecycle = complete.lifecycle().add(frozen.allRegistriesLifecycle()); +- PrimaryLevelData primaryLevelData = PrimaryLevelData.parse( +- dynamic1, levelSettings, complete.specialWorldProperty(), worldGenSettings.options(), lifecycle +- ); +- return new LevelDataAndDimensions(primaryLevelData, complete); ++ DataResult dataresult = WorldGenSettings.CODEC.parse(dynamic2); ++ Logger logger = LevelStorageSource.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ WorldGenSettings generatorsettings = (WorldGenSettings) dataresult.getOrThrow(false, Util.prefix("WorldGenSettings: ", logger::error)); ++ LevelSettings worldsettings = LevelSettings.parse(dynamic1, worlddataconfiguration); ++ WorldDimensions.b worlddimensions_b = generatorsettings.dimensions().bake(iregistry); ++ Lifecycle lifecycle = worlddimensions_b.lifecycle().add(iregistrycustom_dimension.allRegistriesLifecycle()); ++ PrimaryLevelData worlddataserver = PrimaryLevelData.parse(dynamic1, worldsettings, worlddimensions_b.specialWorldProperty(), generatorsettings.options(), lifecycle); ++ worlddataserver.pdc = ((Dynamic) dynamic1).getElement("BukkitValues", null); // CraftBukkit - Add PDC to world ++ ++ return new LevelDataAndDimensions(worlddataserver, worlddimensions_b); + } + +- private static Dynamic wrapWithRegistryOps(Dynamic dynamic, RegistryAccess.Frozen frozen) { +- RegistryOps registryOps = RegistryOps.create(dynamic.getOps(), frozen); +- return new Dynamic<>(registryOps, dynamic.getValue()); ++ private static Dynamic wrapWithRegistryOps(Dynamic dynamic, RegistryAccess.Dimension iregistrycustom_dimension) { ++ RegistryOps registryops = RegistryOps.create(dynamic.getOps(), (HolderLookup.Provider) iregistrycustom_dimension); ++ ++ return new Dynamic(registryops, dynamic.getValue()); + } + + public String getName() { + return "Anvil"; + } + +- public LevelStorageSource.LevelCandidates findLevelCandidates() throws LevelStorageException { +- if (!Files.isDirectory(this.baseDir)) { ++ public LevelStorageSource.a findLevelCandidates() throws LevelStorageException { ++ if (!Files.isDirectory(this.baseDir, new LinkOption[0])) { + throw new LevelStorageException(Component.translatable("selectWorld.load_folder_access")); + } else { + try { +- LevelStorageSource.LevelCandidates var3; +- try (Stream stream = Files.list(this.baseDir)) { +- List list = stream.filter(path -> Files.isDirectory(path)) +- .map(LevelStorageSource.LevelDirectory::new) +- .filter(levelDirectory -> Files.isRegularFile(levelDirectory.dataFile()) || Files.isRegularFile(levelDirectory.oldDataFile())) +- .toList(); +- var3 = new LevelStorageSource.LevelCandidates(list); ++ Stream stream = Files.list(this.baseDir); // CraftBukkit - decompile error ++ ++ LevelStorageSource.a convertable_a; ++ ++ try { ++ List list = stream.filter((path) -> { ++ return Files.isDirectory(path, new LinkOption[0]); ++ }).map(LevelStorageSource.LevelDirectory::new).filter((convertable_b) -> { ++ return Files.isRegularFile(convertable_b.dataFile(), new LinkOption[0]) || Files.isRegularFile(convertable_b.oldDataFile(), new LinkOption[0]); ++ }).toList(); ++ ++ convertable_a = new LevelStorageSource.a(list); ++ } catch (Throwable throwable) { ++ if (stream != null) { ++ try { ++ stream.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ } ++ ++ throw throwable; + } + +- return var3; +- } catch (IOException var6) { ++ if (stream != null) { ++ stream.close(); ++ } ++ ++ return convertable_a; ++ } catch (IOException ioexception) { + throw new LevelStorageException(Component.translatable("selectWorld.load_folder_access")); + } + } + } + +- public CompletableFuture> loadLevelSummaries(LevelStorageSource.LevelCandidates candidates) { +- List> list = new ArrayList<>(candidates.levels.size()); ++ public CompletableFuture> loadLevelSummaries(LevelStorageSource.a candidates) { ++ List> list = new ArrayList(candidates.levels.size()); ++ Iterator iterator = candidates.levels.iterator(); + +- for (LevelStorageSource.LevelDirectory levelDirectory : candidates.levels) { ++ while (iterator.hasNext()) { ++ LevelStorageSource.LevelDirectory convertable_b = (LevelStorageSource.LevelDirectory) iterator.next(); ++ + list.add(CompletableFuture.supplyAsync(() -> { +- boolean isLocked; ++ boolean flag; ++ + try { +- isLocked = DirectoryLock.isLocked(levelDirectory.path()); +- } catch (Exception var13) { +- LOGGER.warn("Failed to read {} lock", levelDirectory.path(), var13); ++ flag = DirectoryLock.isLocked(convertable_b.path()); ++ } catch (Exception exception) { ++ LevelStorageSource.LOGGER.warn("Failed to read {} lock", convertable_b.path(), exception); + return null; + } + + try { +- return this.readLevelSummary(levelDirectory, isLocked); +- } catch (OutOfMemoryError var12) { ++ return this.readLevelSummary(convertable_b, flag); ++ } catch (OutOfMemoryError outofmemoryerror) { + MemoryReserve.release(); + System.gc(); +- String string = "Ran out of memory trying to read summary of world folder \"" + levelDirectory.directoryName() + "\""; +- LOGGER.error(LogUtils.FATAL_MARKER, string); +- OutOfMemoryError outOfMemoryError1 = new OutOfMemoryError("Ran out of memory reading level data"); +- outOfMemoryError1.initCause(var12); +- CrashReport crashReport = CrashReport.forThrowable(outOfMemoryError1, string); +- CrashReportCategory crashReportCategory = crashReport.addCategory("World details"); +- crashReportCategory.setDetail("Folder Name", levelDirectory.directoryName()); ++ String s = "Ran out of memory trying to read summary of world folder \"" + convertable_b.directoryName() + "\""; + ++ LevelStorageSource.LOGGER.error(LogUtils.FATAL_MARKER, s); ++ OutOfMemoryError outofmemoryerror1 = new OutOfMemoryError("Ran out of memory reading level data"); ++ ++ outofmemoryerror1.initCause(outofmemoryerror); ++ CrashReport crashreport = CrashReport.forThrowable(outofmemoryerror1, s); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("World details"); ++ ++ crashreportsystemdetails.setDetail("Folder Name", (Object) convertable_b.directoryName()); ++ + try { +- long size = Files.size(levelDirectory.dataFile()); +- crashReportCategory.setDetail("level.dat size", size); +- } catch (IOException var11) { +- crashReportCategory.setDetailError("level.dat size", var11); ++ long i = Files.size(convertable_b.dataFile()); ++ ++ crashreportsystemdetails.setDetail("level.dat size", (Object) i); ++ } catch (IOException ioexception) { ++ crashreportsystemdetails.setDetailError("level.dat size", ioexception); + } + +- throw new ReportedException(crashReport); ++ throw new ReportedException(crashreport); + } + }, Util.backgroundExecutor())); + } + +- return Util.sequenceFailFastAndCancel(list).thenApply(list1 -> list1.stream().filter(Objects::nonNull).sorted().toList()); ++ return Util.sequenceFailFastAndCancel(list).thenApply((list1) -> { ++ return list1.stream().filter(Objects::nonNull).sorted().toList(); ++ }); + } + + private int getStorageVersion() { +@@ -240,114 +287,126 @@ + return NbtIo.readCompressed(path, NbtAccounter.create(104857600L)); + } + +- static Dynamic readLevelDataTagFixed(Path path, DataFixer dataFixer) throws IOException { +- CompoundTag levelDataTagRaw = readLevelDataTagRaw(path); +- CompoundTag compound = levelDataTagRaw.getCompound("Data"); +- int dataVersion = NbtUtils.getDataVersion(compound, -1); +- Dynamic dynamic = DataFixTypes.LEVEL.updateToCurrentVersion(dataFixer, new Dynamic<>(NbtOps.INSTANCE, compound), dataVersion); ++ static Dynamic readLevelDataTagFixed(Path path, DataFixer datafixer) throws IOException { ++ CompoundTag nbttagcompound = readLevelDataTagRaw(path); ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Data"); ++ int i = NbtUtils.getDataVersion(nbttagcompound1, -1); ++ Dynamic dynamic = DataFixTypes.LEVEL.updateToCurrentVersion(datafixer, new Dynamic(NbtOps.INSTANCE, nbttagcompound1), i); + Dynamic dynamic1 = dynamic.get("Player").orElseEmptyMap(); +- Dynamic dynamic2 = DataFixTypes.PLAYER.updateToCurrentVersion(dataFixer, dynamic1, dataVersion); ++ Dynamic dynamic2 = DataFixTypes.PLAYER.updateToCurrentVersion(datafixer, dynamic1, i); ++ + dynamic = dynamic.set("Player", dynamic2); + Dynamic dynamic3 = dynamic.get("WorldGenSettings").orElseEmptyMap(); +- Dynamic dynamic4 = DataFixTypes.WORLD_GEN_SETTINGS.updateToCurrentVersion(dataFixer, dynamic3, dataVersion); +- return dynamic.set("WorldGenSettings", dynamic4); ++ Dynamic dynamic4 = DataFixTypes.WORLD_GEN_SETTINGS.updateToCurrentVersion(datafixer, dynamic3, i); ++ ++ dynamic = dynamic.set("WorldGenSettings", dynamic4); ++ return dynamic; + } + +- private LevelSummary readLevelSummary(LevelStorageSource.LevelDirectory levelDirectory, boolean flag) { +- Path path = levelDirectory.dataFile(); +- if (Files.exists(path)) { ++ private LevelSummary readLevelSummary(LevelStorageSource.LevelDirectory convertable_b, boolean flag) { ++ Path path = convertable_b.dataFile(); ++ ++ if (Files.exists(path, new LinkOption[0])) { + try { + if (Files.isSymbolicLink(path)) { + List list = this.worldDirValidator.validateSymlink(path); ++ + if (!list.isEmpty()) { +- LOGGER.warn("{}", ContentValidationException.getMessage(path, list)); +- return new LevelSummary.SymlinkLevelSummary(levelDirectory.directoryName(), levelDirectory.iconFile()); ++ LevelStorageSource.LOGGER.warn("{}", ContentValidationException.getMessage(path, list)); ++ return new LevelSummary.SymlinkLevelSummary(convertable_b.directoryName(), convertable_b.iconFile()); + } + } + +- if (readLightweightData(path) instanceof CompoundTag compoundTag) { +- CompoundTag compound = compoundTag.getCompound("Data"); +- int dataVersion = NbtUtils.getDataVersion(compound, -1); +- Dynamic dynamic = DataFixTypes.LEVEL.updateToCurrentVersion(this.fixerUpper, new Dynamic<>(NbtOps.INSTANCE, compound), dataVersion); +- return this.makeLevelSummary(dynamic, levelDirectory, flag); ++ Tag nbtbase = readLightweightData(path); ++ ++ if (nbtbase instanceof CompoundTag) { ++ CompoundTag nbttagcompound = (CompoundTag) nbtbase; ++ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Data"); ++ int i = NbtUtils.getDataVersion(nbttagcompound1, -1); ++ Dynamic dynamic = DataFixTypes.LEVEL.updateToCurrentVersion(this.fixerUpper, new Dynamic(NbtOps.INSTANCE, nbttagcompound1), i); ++ ++ return this.makeLevelSummary(dynamic, convertable_b, flag); + } + +- LOGGER.warn("Invalid root tag in {}", path); +- } catch (Exception var9) { +- LOGGER.error("Exception reading {}", path, var9); ++ LevelStorageSource.LOGGER.warn("Invalid root tag in {}", path); ++ } catch (Exception exception) { ++ LevelStorageSource.LOGGER.error("Exception reading {}", path, exception); + } + } + +- return new LevelSummary.CorruptedLevelSummary(levelDirectory.directoryName(), levelDirectory.iconFile(), getFileModificationTime(levelDirectory)); ++ return new LevelSummary.b(convertable_b.directoryName(), convertable_b.iconFile(), getFileModificationTime(convertable_b)); + } + +- private static long getFileModificationTime(LevelStorageSource.LevelDirectory levelDirectory) { +- Instant fileModificationTime = getFileModificationTime(levelDirectory.dataFile()); +- if (fileModificationTime == null) { +- fileModificationTime = getFileModificationTime(levelDirectory.oldDataFile()); ++ private static long getFileModificationTime(LevelStorageSource.LevelDirectory convertable_b) { ++ Instant instant = getFileModificationTime(convertable_b.dataFile()); ++ ++ if (instant == null) { ++ instant = getFileModificationTime(convertable_b.oldDataFile()); + } + +- return fileModificationTime == null ? -1L : fileModificationTime.toEpochMilli(); ++ return instant == null ? -1L : instant.toEpochMilli(); + } + + @Nullable + static Instant getFileModificationTime(Path path) { + try { + return Files.getLastModifiedTime(path).toInstant(); +- } catch (IOException var2) { ++ } catch (IOException ioexception) { + return null; + } + } + +- LevelSummary makeLevelSummary(Dynamic dynamic, LevelStorageSource.LevelDirectory levelDirectory, boolean flag) { +- LevelVersion levelVersion = LevelVersion.parse(dynamic); +- int i = levelVersion.levelDataVersion(); ++ LevelSummary makeLevelSummary(Dynamic dynamic, LevelStorageSource.LevelDirectory convertable_b, boolean flag) { ++ LevelVersion levelversion = LevelVersion.parse(dynamic); ++ int i = levelversion.levelDataVersion(); ++ + if (i != 19132 && i != 19133) { + throw new NbtFormatException("Unknown data version: " + Integer.toHexString(i)); + } else { + boolean flag1 = i != this.getStorageVersion(); +- Path path = levelDirectory.iconFile(); +- WorldDataConfiguration dataConfig = readDataConfig(dynamic); +- LevelSettings levelSettings = LevelSettings.parse(dynamic, dataConfig); +- FeatureFlagSet featureFlagSet = parseFeatureFlagsFromSummary(dynamic); +- boolean isExperimental = FeatureFlags.isExperimental(featureFlagSet); +- return new LevelSummary(levelSettings, levelVersion, levelDirectory.directoryName(), flag1, flag, isExperimental, path); ++ Path path = convertable_b.iconFile(); ++ WorldDataConfiguration worlddataconfiguration = readDataConfig(dynamic); ++ LevelSettings worldsettings = LevelSettings.parse(dynamic, worlddataconfiguration); ++ FeatureFlagSet featureflagset = parseFeatureFlagsFromSummary(dynamic); ++ boolean flag2 = FeatureFlags.isExperimental(featureflagset); ++ ++ return new LevelSummary(worldsettings, levelversion, convertable_b.directoryName(), flag1, flag, flag2, path); + } + } + + private static FeatureFlagSet parseFeatureFlagsFromSummary(Dynamic dataDynamic) { +- Set set = dataDynamic.get("enabled_features") +- .asStream() +- .flatMap(dynamic -> dynamic.asString().result().map(ResourceLocation::tryParse).stream()) +- .collect(Collectors.toSet()); +- return FeatureFlags.REGISTRY.fromNames(set, resourceLocation -> { ++ Set set = (Set) dataDynamic.get("enabled_features").asStream().flatMap((dynamic1) -> { ++ return dynamic1.asString().result().map(ResourceLocation::tryParse).stream(); ++ }).collect(Collectors.toSet()); ++ ++ return FeatureFlags.REGISTRY.fromNames(set, (minecraftkey) -> { + }); + } + + @Nullable + private static Tag readLightweightData(Path file) throws IOException { +- SkipFields skipFields = new SkipFields( +- new FieldSelector("Data", CompoundTag.TYPE, "Player"), new FieldSelector("Data", CompoundTag.TYPE, "WorldGenSettings") +- ); +- NbtIo.parseCompressed(file, skipFields, NbtAccounter.create(104857600L)); +- return skipFields.getResult(); ++ SkipFields skipfields = new SkipFields(new FieldSelector[]{new FieldSelector("Data", CompoundTag.TYPE, "Player"), new FieldSelector("Data", CompoundTag.TYPE, "WorldGenSettings")}); ++ ++ NbtIo.parseCompressed(file, skipfields, NbtAccounter.create(104857600L)); ++ return skipfields.getResult(); + } + + public boolean isNewLevelIdAcceptable(String saveName) { + try { +- Path levelPath = this.getLevelPath(saveName); +- Files.createDirectory(levelPath); +- Files.deleteIfExists(levelPath); ++ Path path = this.getLevelPath(saveName); ++ ++ Files.createDirectory(path); ++ Files.deleteIfExists(path); + return true; +- } catch (IOException var3) { ++ } catch (IOException ioexception) { + return false; + } + } + + public boolean levelExists(String saveName) { + try { +- return Files.isDirectory(this.getLevelPath(saveName)); +- } catch (InvalidPathException var3) { ++ return Files.isDirectory(this.getLevelPath(saveName), new LinkOption[0]); ++ } catch (InvalidPathException invalidpathexception) { + return false; + } + } +@@ -364,37 +423,54 @@ + return this.backupDir; + } + +- public LevelStorageSource.LevelStorageAccess validateAndCreateAccess(String saveName) throws IOException, ContentValidationException { +- Path levelPath = this.getLevelPath(saveName); +- List list = this.worldDirValidator.validateDirectory(levelPath, true); ++ public LevelStorageSource.LevelStorageAccess validateAndCreateAccess(String s, ResourceKey dimensionType) throws IOException, ContentValidationException { // CraftBukkit ++ Path path = this.getLevelPath(s); ++ List list = this.worldDirValidator.validateDirectory(path, true); ++ + if (!list.isEmpty()) { +- throw new ContentValidationException(levelPath, list); ++ throw new ContentValidationException(path, list); + } else { +- return new LevelStorageSource.LevelStorageAccess(saveName, levelPath); ++ return new LevelStorageSource.LevelStorageAccess(s, path, dimensionType); // CraftBukkit + } + } + +- public LevelStorageSource.LevelStorageAccess createAccess(String saveName) throws IOException { +- Path levelPath = this.getLevelPath(saveName); +- return new LevelStorageSource.LevelStorageAccess(saveName, levelPath); ++ public LevelStorageSource.LevelStorageAccess createAccess(String s, ResourceKey dimensionType) throws IOException { // CraftBukkit ++ Path path = this.getLevelPath(s); ++ ++ return new LevelStorageSource.LevelStorageAccess(s, path, dimensionType); // CraftBukkit + } + + public DirectoryValidator getWorldDirValidator() { + return this.worldDirValidator; + } + +- public static record LevelCandidates(List levels) implements Iterable { ++ // CraftBukkit start ++ public static Path getStorageFolder(Path path, ResourceKey dimensionType) { ++ if (dimensionType == LevelStem.OVERWORLD) { ++ return path; ++ } else if (dimensionType == LevelStem.NETHER) { ++ return path.resolve("DIM-1"); ++ } else if (dimensionType == LevelStem.END) { ++ return path.resolve("DIM1"); ++ } else { ++ return path.resolve("dimensions").resolve(dimensionType.location().getNamespace()).resolve(dimensionType.location().getPath()); ++ } ++ } ++ // CraftBukkit end ++ ++ public static record a(List levels) implements Iterable { ++ + public boolean isEmpty() { + return this.levels.isEmpty(); + } + +- @Override + public Iterator iterator() { + return this.levels.iterator(); + } + } + + public static record LevelDirectory(Path path) { ++ + public String directoryName() { + return this.path.getFileName().toString(); + } +@@ -408,11 +484,17 @@ + } + + public Path corruptedDataFile(LocalDateTime dateTime) { +- return this.path.resolve(LevelResource.LEVEL_DATA_FILE.getId() + "_corrupted_" + dateTime.format(LevelStorageSource.FORMATTER)); ++ Path path = this.path; ++ String s = LevelResource.LEVEL_DATA_FILE.getId(); ++ ++ return path.resolve(s + "_corrupted_" + dateTime.format(LevelStorageSource.FORMATTER)); + } + +- public Path rawDataFile(LocalDateTime localDateTime) { +- return this.path.resolve(LevelResource.LEVEL_DATA_FILE.getId() + "_raw_" + localDateTime.format(LevelStorageSource.FORMATTER)); ++ public Path rawDataFile(LocalDateTime localdatetime) { ++ Path path = this.path; ++ String s = LevelResource.LEVEL_DATA_FILE.getId(); ++ ++ return path.resolve(s + "_raw_" + localdatetime.format(LevelStorageSource.FORMATTER)); + } + + public Path iconFile() { +@@ -429,23 +511,29 @@ + } + + public class LevelStorageAccess implements AutoCloseable { ++ + final DirectoryLock lock; +- final LevelStorageSource.LevelDirectory levelDirectory; ++ public final LevelStorageSource.LevelDirectory levelDirectory; + private final String levelId; + private final Map resources = Maps.newHashMap(); ++ // CraftBukkit start ++ public final ResourceKey dimensionType; + +- LevelStorageAccess(String levelId, Path levelDir) throws IOException { +- this.levelId = levelId; +- this.levelDirectory = new LevelStorageSource.LevelDirectory(levelDir); +- this.lock = DirectoryLock.create(levelDir); ++ LevelStorageAccess(String s, Path path, ResourceKey dimensionType) throws IOException { ++ this.dimensionType = dimensionType; ++ // CraftBukkit end ++ this.levelId = s; ++ this.levelDirectory = new LevelStorageSource.LevelDirectory(path); ++ this.lock = DirectoryLock.create(path); + } + + public void safeClose() { + try { + this.close(); +- } catch (IOException var2) { +- LevelStorageSource.LOGGER.warn("Failed to unlock access to level {}", this.getLevelId(), var2); ++ } catch (IOException ioexception) { ++ LevelStorageSource.LOGGER.warn("Failed to unlock access to level {}", this.getLevelId(), ioexception); + } ++ + } + + public LevelStorageSource parent() { +@@ -461,11 +549,15 @@ + } + + public Path getLevelPath(LevelResource folderName) { +- return this.resources.computeIfAbsent(folderName, this.levelDirectory::resourcePath); ++ Map map = this.resources; // CraftBukkit - decompile error ++ LevelStorageSource.LevelDirectory convertable_b = this.levelDirectory; ++ ++ Objects.requireNonNull(this.levelDirectory); ++ return (Path) map.computeIfAbsent(folderName, convertable_b::resourcePath); + } + + public Path getDimensionPath(ResourceKey dimensionPath) { +- return DimensionType.getStorageFolder(dimensionPath, this.levelDirectory.path()); ++ return getStorageFolder(this.levelDirectory.path(), this.dimensionType); // CraftBukkit + } + + private void checkLock() { +@@ -494,34 +586,36 @@ + + private Dynamic getDataTag(boolean flag) throws IOException { + this.checkLock(); +- return LevelStorageSource.readLevelDataTagFixed( +- flag ? this.levelDirectory.oldDataFile() : this.levelDirectory.dataFile(), LevelStorageSource.this.fixerUpper +- ); ++ return LevelStorageSource.readLevelDataTagFixed(flag ? this.levelDirectory.oldDataFile() : this.levelDirectory.dataFile(), LevelStorageSource.this.fixerUpper); + } + + public void saveDataTag(RegistryAccess registries, WorldData serverConfiguration) { +- this.saveDataTag(registries, serverConfiguration, null); ++ this.saveDataTag(registries, serverConfiguration, (CompoundTag) null); + } + + public void saveDataTag(RegistryAccess registries, WorldData serverConfiguration, @Nullable CompoundTag hostPlayerNBT) { +- CompoundTag compoundTag = serverConfiguration.createTag(registries, hostPlayerNBT); +- CompoundTag compoundTag1 = new CompoundTag(); +- compoundTag1.put("Data", compoundTag); +- this.saveLevelData(compoundTag1); ++ CompoundTag nbttagcompound1 = serverConfiguration.createTag(registries, hostPlayerNBT); ++ CompoundTag nbttagcompound2 = new CompoundTag(); ++ ++ nbttagcompound2.put("Data", nbttagcompound1); ++ this.saveLevelData(nbttagcompound2); + } + +- private void saveLevelData(CompoundTag compoundTag) { ++ private void saveLevelData(CompoundTag nbttagcompound) { + Path path = this.levelDirectory.path(); + + try { + Path path1 = Files.createTempFile(path, "level", ".dat"); +- NbtIo.writeCompressed(compoundTag, path1); ++ ++ NbtIo.writeCompressed(nbttagcompound, path1); + Path path2 = this.levelDirectory.oldDataFile(); + Path path3 = this.levelDirectory.dataFile(); ++ + Util.safeReplaceFile(path3, path1, path2); +- } catch (Exception var6) { +- LevelStorageSource.LOGGER.error("Failed to save level {}", path, var6); ++ } catch (Exception exception) { ++ LevelStorageSource.LOGGER.error("Failed to save level {}", path, exception); + } ++ + } + + public Optional getIconFile() { +@@ -531,120 +625,136 @@ + public void deleteLevel() throws IOException { + this.checkLock(); + final Path path = this.levelDirectory.lockFile(); ++ + LevelStorageSource.LOGGER.info("Deleting level {}", this.levelId); ++ int i = 1; + +- for (int i = 1; i <= 5; i++) { ++ while (i <= 5) { + LevelStorageSource.LOGGER.info("Attempt {}...", i); + + try { + Files.walkFileTree(this.levelDirectory.path(), new SimpleFileVisitor() { +- @Override +- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { +- if (!file.equals(path)) { +- LevelStorageSource.LOGGER.debug("Deleting {}", file); +- Files.delete(file); ++ public FileVisitResult visitFile(Path path1, BasicFileAttributes basicfileattributes) throws IOException { ++ if (!path1.equals(path)) { ++ LevelStorageSource.LOGGER.debug("Deleting {}", path1); ++ Files.delete(path1); + } + + return FileVisitResult.CONTINUE; + } + +- @Override +- public FileVisitResult postVisitDirectory(Path dir, @Nullable IOException exception) throws IOException { +- if (exception != null) { +- throw exception; ++ public FileVisitResult postVisitDirectory(Path path1, @Nullable IOException ioexception) throws IOException { ++ if (ioexception != null) { ++ throw ioexception; + } else { +- if (dir.equals(LevelStorageAccess.this.levelDirectory.path())) { ++ if (path1.equals(LevelStorageAccess.this.levelDirectory.path())) { + LevelStorageAccess.this.lock.close(); + Files.deleteIfExists(path); + } + +- Files.delete(dir); ++ Files.delete(path1); + return FileVisitResult.CONTINUE; + } + } + }); + break; +- } catch (IOException var6) { ++ } catch (IOException ioexception) { + if (i >= 5) { +- throw var6; ++ throw ioexception; + } + +- LevelStorageSource.LOGGER.warn("Failed to delete {}", this.levelDirectory.path(), var6); ++ LevelStorageSource.LOGGER.warn("Failed to delete {}", this.levelDirectory.path(), ioexception); + + try { + Thread.sleep(500L); +- } catch (InterruptedException var5) { ++ } catch (InterruptedException interruptedexception) { ++ ; + } ++ ++ ++i; + } + } ++ + } + + public void renameLevel(String saveName) throws IOException { +- this.modifyLevelDataWithoutDatafix(compoundTag -> compoundTag.putString("LevelName", saveName.trim())); ++ this.modifyLevelDataWithoutDatafix((nbttagcompound) -> { ++ nbttagcompound.putString("LevelName", saveName.trim()); ++ }); + } + +- public void renameAndDropPlayer(String string) throws IOException { +- this.modifyLevelDataWithoutDatafix(compoundTag -> { +- compoundTag.putString("LevelName", string.trim()); +- compoundTag.remove("Player"); ++ public void renameAndDropPlayer(String s) throws IOException { ++ this.modifyLevelDataWithoutDatafix((nbttagcompound) -> { ++ nbttagcompound.putString("LevelName", s.trim()); ++ nbttagcompound.remove("Player"); + }); + } + + private void modifyLevelDataWithoutDatafix(Consumer consumer) throws IOException { + this.checkLock(); +- CompoundTag levelDataTagRaw = LevelStorageSource.readLevelDataTagRaw(this.levelDirectory.dataFile()); +- consumer.accept(levelDataTagRaw.getCompound("Data")); +- this.saveLevelData(levelDataTagRaw); ++ CompoundTag nbttagcompound = LevelStorageSource.readLevelDataTagRaw(this.levelDirectory.dataFile()); ++ ++ consumer.accept(nbttagcompound.getCompound("Data")); ++ this.saveLevelData(nbttagcompound); + } + + public long makeWorldBackup() throws IOException { + this.checkLock(); +- String string = LocalDateTime.now().format(LevelStorageSource.FORMATTER) + "_" + this.levelId; +- Path backupPath = LevelStorageSource.this.getBackupPath(); ++ String s = LocalDateTime.now().format(LevelStorageSource.FORMATTER); ++ String s1 = s + "_" + this.levelId; ++ Path path = LevelStorageSource.this.getBackupPath(); + + try { +- FileUtil.createDirectoriesSafe(backupPath); +- } catch (IOException var9) { +- throw new RuntimeException(var9); ++ FileUtil.createDirectoriesSafe(path); ++ } catch (IOException ioexception) { ++ throw new RuntimeException(ioexception); + } + +- Path path = backupPath.resolve(FileUtil.findAvailableName(backupPath, string, ".zip")); ++ Path path1 = path.resolve(FileUtil.findAvailableName(path, s1, ".zip")); ++ final ZipOutputStream zipoutputstream = new ZipOutputStream(new BufferedOutputStream(Files.newOutputStream(path1))); + +- try (final ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(Files.newOutputStream(path)))) { +- final Path path1 = Paths.get(this.levelId); ++ try { ++ final Path path2 = Paths.get(this.levelId); ++ + Files.walkFileTree(this.levelDirectory.path(), new SimpleFileVisitor() { +- @Override +- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { +- if (file.endsWith("session.lock")) { ++ public FileVisitResult visitFile(Path path3, BasicFileAttributes basicfileattributes) throws IOException { ++ if (path3.endsWith("session.lock")) { + return FileVisitResult.CONTINUE; + } else { +- String string1 = path1.resolve(LevelStorageAccess.this.levelDirectory.path().relativize(file)).toString().replace('\\', '/'); +- ZipEntry zipEntry = new ZipEntry(string1); +- zipOutputStream.putNextEntry(zipEntry); +- com.google.common.io.Files.asByteSource(file.toFile()).copyTo(zipOutputStream); +- zipOutputStream.closeEntry(); ++ String s2 = path2.resolve(LevelStorageAccess.this.levelDirectory.path().relativize(path3)).toString().replace('\\', '/'); ++ ZipEntry zipentry = new ZipEntry(s2); ++ ++ zipoutputstream.putNextEntry(zipentry); ++ com.google.common.io.Files.asByteSource(path3.toFile()).copyTo(zipoutputstream); ++ zipoutputstream.closeEntry(); + return FileVisitResult.CONTINUE; + } + } + }); ++ } catch (Throwable throwable) { ++ try { ++ zipoutputstream.close(); ++ } catch (Throwable throwable1) { ++ throwable.addSuppressed(throwable1); ++ } ++ ++ throw throwable; + } + +- return Files.size(path); ++ zipoutputstream.close(); ++ return Files.size(path1); + } + + public boolean hasWorldData() { +- return Files.exists(this.levelDirectory.dataFile()) || Files.exists(this.levelDirectory.oldDataFile()); ++ return Files.exists(this.levelDirectory.dataFile(), new LinkOption[0]) || Files.exists(this.levelDirectory.oldDataFile(), new LinkOption[0]); + } + +- @Override + public void close() throws IOException { + this.lock.close(); + } + + public boolean restoreLevelDataFromOld() { +- return Util.safeReplaceOrMoveFile( +- this.levelDirectory.dataFile(), this.levelDirectory.oldDataFile(), this.levelDirectory.corruptedDataFile(LocalDateTime.now()), true +- ); ++ return Util.safeReplaceOrMoveFile(this.levelDirectory.dataFile(), this.levelDirectory.oldDataFile(), this.levelDirectory.corruptedDataFile(LocalDateTime.now()), true); + } + + @Nullable diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/storage/PlayerDataStorage.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/storage/PlayerDataStorage.java.patch new file mode 100644 index 0000000000..55acdafa7c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/storage/PlayerDataStorage.java.patch @@ -0,0 +1,133 @@ +--- a/net/minecraft/world/level/storage/PlayerDataStorage.java ++++ b/net/minecraft/world/level/storage/PlayerDataStorage.java +@@ -11,11 +11,19 @@ + import net.minecraft.nbt.NbtAccounter; + import net.minecraft.nbt.NbtIo; + import net.minecraft.nbt.NbtUtils; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.datafix.DataFixTypes; + import net.minecraft.world.entity.player.Player; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.io.FileInputStream; ++import java.io.InputStream; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++// CraftBukkit end ++ + public class PlayerDataStorage { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private final File playerDir; + protected final DataFixer fixerUpper; +@@ -28,52 +36,90 @@ + + public void save(Player player) { + try { +- CompoundTag compoundTag = player.saveWithoutId(new CompoundTag()); ++ CompoundTag nbttagcompound = player.saveWithoutId(new CompoundTag()); + Path path = this.playerDir.toPath(); + Path path1 = Files.createTempFile(path, player.getStringUUID() + "-", ".dat"); +- NbtIo.writeCompressed(compoundTag, path1); ++ ++ NbtIo.writeCompressed(nbttagcompound, path1); + Path path2 = path.resolve(player.getStringUUID() + ".dat"); + Path path3 = path.resolve(player.getStringUUID() + ".dat_old"); ++ + Util.safeReplaceFile(path2, path1, path3); +- } catch (Exception var7) { +- LOGGER.warn("Failed to save player data for {}", player.getName().getString()); ++ } catch (Exception exception) { ++ PlayerDataStorage.LOGGER.warn("Failed to save player data for {}", player.getName().getString()); + } ++ + } + + @Nullable + public CompoundTag load(Player player) { +- CompoundTag compoundTag = null; ++ CompoundTag nbttagcompound = null; + + try { + File file = new File(this.playerDir, player.getStringUUID() + ".dat"); ++ + if (file.exists() && file.isFile()) { +- compoundTag = NbtIo.readCompressed(file.toPath(), NbtAccounter.unlimitedHeap()); ++ nbttagcompound = NbtIo.readCompressed(file.toPath(), NbtAccounter.unlimitedHeap()); + } +- } catch (Exception var4) { +- LOGGER.warn("Failed to load player data for {}", player.getName().getString()); ++ } catch (Exception exception) { ++ PlayerDataStorage.LOGGER.warn("Failed to load player data for {}", player.getName().getString()); + } + +- if (compoundTag != null) { +- int dataVersion = NbtUtils.getDataVersion(compoundTag, -1); +- compoundTag = DataFixTypes.PLAYER.updateToCurrentVersion(this.fixerUpper, compoundTag, dataVersion); +- player.load(compoundTag); ++ if (nbttagcompound != null) { ++ // CraftBukkit start ++ if (player instanceof ServerPlayer) { ++ CraftPlayer player = (CraftPlayer) player.getBukkitEntity(); ++ // Only update first played if it is older than the one we have ++ long modified = new File(this.playerDir, player.getUUID().toString() + ".dat").lastModified(); ++ if (modified < player.getFirstPlayed()) { ++ player.setFirstPlayed(modified); ++ } ++ } ++ // CraftBukkit end ++ int i = NbtUtils.getDataVersion(nbttagcompound, -1); ++ ++ nbttagcompound = DataFixTypes.PLAYER.updateToCurrentVersion(this.fixerUpper, nbttagcompound, i); ++ player.load(nbttagcompound); + } + +- return compoundTag; ++ return nbttagcompound; + } + ++ // CraftBukkit start ++ public CompoundTag getPlayerData(String s) { ++ try { ++ File file1 = new File(this.playerDir, s + ".dat"); ++ ++ if (file1.exists()) { ++ return NbtIo.readCompressed(file1.toPath(), NbtAccounter.unlimitedHeap()); ++ } ++ } catch (Exception exception) { ++ LOGGER.warn("Failed to load player data for " + s); ++ } ++ ++ return null; ++ } ++ // CraftBukkit end ++ + public String[] getSeenPlayers() { +- String[] strings = this.playerDir.list(); +- if (strings == null) { +- strings = new String[0]; ++ String[] astring = this.playerDir.list(); ++ ++ if (astring == null) { ++ astring = new String[0]; + } + +- for (int i = 0; i < strings.length; i++) { +- if (strings[i].endsWith(".dat")) { +- strings[i] = strings[i].substring(0, strings[i].length() - 4); ++ for (int i = 0; i < astring.length; ++i) { ++ if (astring[i].endsWith(".dat")) { ++ astring[i] = astring[i].substring(0, astring[i].length() - 4); + } + } + +- return strings; ++ return astring; + } ++ ++ // CraftBukkit start ++ public File getPlayerDir() { ++ return playerDir; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/storage/PrimaryLevelData.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/storage/PrimaryLevelData.java.patch new file mode 100644 index 0000000000..48ded54815 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/storage/PrimaryLevelData.java.patch @@ -0,0 +1,487 @@ +--- a/net/minecraft/world/level/storage/PrimaryLevelData.java ++++ b/net/minecraft/world/level/storage/PrimaryLevelData.java +@@ -7,26 +7,25 @@ + import com.mojang.serialization.Dynamic; + import com.mojang.serialization.DynamicOps; + import com.mojang.serialization.Lifecycle; +-import com.mojang.serialization.DataResult.PartialResult; + import java.util.HashSet; ++import java.util.Objects; + import java.util.Set; + import java.util.UUID; + import java.util.stream.Collectors; ++import java.util.stream.Stream; + import javax.annotation.Nullable; + import net.minecraft.CrashReportCategory; + import net.minecraft.SharedConstants; + import net.minecraft.Util; + import net.minecraft.core.BlockPos; ++import net.minecraft.core.HolderLookup; ++import net.minecraft.core.Registry; + import net.minecraft.core.RegistryAccess; + import net.minecraft.core.UUIDUtil; +-import net.minecraft.nbt.CompoundTag; +-import net.minecraft.nbt.ListTag; +-import net.minecraft.nbt.NbtOps; +-import net.minecraft.nbt.NbtUtils; +-import net.minecraft.nbt.StringTag; +-import net.minecraft.nbt.Tag; + import net.minecraft.resources.RegistryOps; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.Difficulty; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.GameType; +@@ -34,21 +33,36 @@ + import net.minecraft.world.level.LevelSettings; + import net.minecraft.world.level.WorldDataConfiguration; + import net.minecraft.world.level.border.WorldBorder; ++import net.minecraft.world.level.dimension.LevelStem; + import net.minecraft.world.level.dimension.end.EndDragonFight; +-import net.minecraft.world.level.levelgen.WorldGenSettings; + import net.minecraft.world.level.levelgen.WorldOptions; + import net.minecraft.world.level.timers.TimerCallbacks; + import net.minecraft.world.level.timers.TimerQueue; + import org.slf4j.Logger; ++import net.minecraft.core.registries.Registries; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; ++import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.NbtUtils; ++import net.minecraft.nbt.StringTag; ++import net.minecraft.nbt.Tag; ++import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; ++import net.minecraft.world.level.levelgen.WorldDimensions; ++import net.minecraft.world.level.levelgen.WorldGenSettings; ++import org.bukkit.Bukkit; ++import org.bukkit.event.weather.ThunderChangeEvent; ++import org.bukkit.event.weather.WeatherChangeEvent; ++// CraftBukkit end + + public class PrimaryLevelData implements ServerLevelData, WorldData { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + public static final String LEVEL_NAME = "LevelName"; + protected static final String PLAYER = "Player"; + protected static final String WORLD_GEN_SETTINGS = "WorldGenSettings"; +- private LevelSettings settings; ++ public LevelSettings settings; + private final WorldOptions worldOptions; +- private final PrimaryLevelData.SpecialWorldProperty specialWorldProperty; ++ private final PrimaryLevelData.a specialWorldProperty; + private final Lifecycle worldGenSettingsLifecycle; + private int xSpawn; + private int ySpawn; +@@ -78,150 +92,91 @@ + private boolean wasModded; + private final Set removedFeatureFlags; + private final TimerQueue scheduledEvents; ++ // CraftBukkit start - Add world and pdc ++ public Registry customDimensions; ++ private ServerLevel world; ++ protected Tag pdc; + +- private PrimaryLevelData( +- @Nullable CompoundTag compoundTag, +- boolean flag, +- int i, +- int i1, +- int i2, +- float f, +- long l, +- long l1, +- int i3, +- int i4, +- int i5, +- boolean flag1, +- int i6, +- boolean flag2, +- boolean flag3, +- boolean flag4, +- WorldBorder.Settings settings, +- int i7, +- int i8, +- @Nullable UUID uUID, +- Set set, +- Set set1, +- TimerQueue timerQueue, +- @Nullable CompoundTag compoundTag1, +- EndDragonFight.Data data, +- LevelSettings levelSettings, +- WorldOptions worldOptions, +- PrimaryLevelData.SpecialWorldProperty specialWorldProperty, +- Lifecycle lifecycle +- ) { ++ public void setWorld(ServerLevel world) { ++ if (this.world != null) { ++ return; ++ } ++ this.world = world; ++ world.getWorld().readBukkitValues(pdc); ++ pdc = null; ++ } ++ // CraftBukkit end ++ ++ private PrimaryLevelData(@Nullable CompoundTag nbttagcompound, boolean flag, int i, int j, int k, float f, long l, long i1, int j1, int k1, int l1, boolean flag1, int i2, boolean flag2, boolean flag3, boolean flag4, WorldBorder.Settings worldborder_c, int j2, int k2, @Nullable UUID uuid, Set set, Set set1, TimerQueue customfunctioncallbacktimerqueue, @Nullable CompoundTag nbttagcompound1, EndDragonFight.Data enderdragonbattle_a, LevelSettings worldsettings, WorldOptions worldoptions, PrimaryLevelData.a worlddataserver_a, Lifecycle lifecycle) { + this.wasModded = flag; + this.xSpawn = i; +- this.ySpawn = i1; +- this.zSpawn = i2; ++ this.ySpawn = j; ++ this.zSpawn = k; + this.spawnAngle = f; + this.gameTime = l; +- this.dayTime = l1; +- this.version = i3; +- this.clearWeatherTime = i4; +- this.rainTime = i5; ++ this.dayTime = i1; ++ this.version = j1; ++ this.clearWeatherTime = k1; ++ this.rainTime = l1; + this.raining = flag1; +- this.thunderTime = i6; ++ this.thunderTime = i2; + this.thundering = flag2; + this.initialized = flag3; + this.difficultyLocked = flag4; +- this.worldBorder = settings; +- this.wanderingTraderSpawnDelay = i7; +- this.wanderingTraderSpawnChance = i8; +- this.wanderingTraderId = uUID; ++ this.worldBorder = worldborder_c; ++ this.wanderingTraderSpawnDelay = j2; ++ this.wanderingTraderSpawnChance = k2; ++ this.wanderingTraderId = uuid; + this.knownServerBrands = set; + this.removedFeatureFlags = set1; +- this.loadedPlayerTag = compoundTag; +- this.scheduledEvents = timerQueue; +- this.customBossEvents = compoundTag1; +- this.endDragonFightData = data; +- this.settings = levelSettings; +- this.worldOptions = worldOptions; +- this.specialWorldProperty = specialWorldProperty; ++ this.loadedPlayerTag = nbttagcompound; ++ this.scheduledEvents = customfunctioncallbacktimerqueue; ++ this.customBossEvents = nbttagcompound1; ++ this.endDragonFightData = enderdragonbattle_a; ++ this.settings = worldsettings; ++ this.worldOptions = worldoptions; ++ this.specialWorldProperty = worlddataserver_a; + this.worldGenSettingsLifecycle = lifecycle; + } + +- public PrimaryLevelData( +- LevelSettings settings, WorldOptions worldOptions, PrimaryLevelData.SpecialWorldProperty specialWorldProperty, Lifecycle worldGenSettingsLifecycle +- ) { +- this( +- null, +- false, +- 0, +- 0, +- 0, +- 0.0F, +- 0L, +- 0L, +- 19133, +- 0, +- 0, +- false, +- 0, +- false, +- false, +- false, +- WorldBorder.DEFAULT_SETTINGS, +- 0, +- 0, +- null, +- Sets.newLinkedHashSet(), +- new HashSet<>(), +- new TimerQueue<>(TimerCallbacks.SERVER_CALLBACKS), +- null, +- EndDragonFight.Data.DEFAULT, +- settings.copy(), +- worldOptions, +- specialWorldProperty, +- worldGenSettingsLifecycle +- ); ++ public PrimaryLevelData(LevelSettings settings, WorldOptions worldOptions, PrimaryLevelData.a specialWorldProperty, Lifecycle worldGenSettingsLifecycle) { ++ this((CompoundTag) null, false, 0, 0, 0, 0.0F, 0L, 0L, 19133, 0, 0, false, 0, false, false, false, WorldBorder.DEFAULT_SETTINGS, 0, 0, (UUID) null, Sets.newLinkedHashSet(), new HashSet(), new TimerQueue<>(TimerCallbacks.SERVER_CALLBACKS), (CompoundTag) null, EndDragonFight.Data.DEFAULT, settings.copy(), worldOptions, specialWorldProperty, worldGenSettingsLifecycle); + } + +- public static PrimaryLevelData parse( +- Dynamic dynamic, +- LevelSettings levelSettings, +- PrimaryLevelData.SpecialWorldProperty specialWorldProperty, +- WorldOptions worldOptions, +- Lifecycle lifecycle +- ) { +- long _long = dynamic.get("Time").asLong(0L); +- return new PrimaryLevelData( +- CompoundTag.CODEC.parse(dynamic.get("Player").orElseEmptyMap()).result().orElse(null), +- dynamic.get("WasModded").asBoolean(false), +- dynamic.get("SpawnX").asInt(0), +- dynamic.get("SpawnY").asInt(0), +- dynamic.get("SpawnZ").asInt(0), +- dynamic.get("SpawnAngle").asFloat(0.0F), +- _long, +- dynamic.get("DayTime").asLong(_long), +- LevelVersion.parse(dynamic).levelDataVersion(), +- dynamic.get("clearWeatherTime").asInt(0), +- dynamic.get("rainTime").asInt(0), +- dynamic.get("raining").asBoolean(false), +- dynamic.get("thunderTime").asInt(0), +- dynamic.get("thundering").asBoolean(false), +- dynamic.get("initialized").asBoolean(true), +- dynamic.get("DifficultyLocked").asBoolean(false), +- WorldBorder.Settings.read(dynamic, WorldBorder.DEFAULT_SETTINGS), +- dynamic.get("WanderingTraderSpawnDelay").asInt(0), +- dynamic.get("WanderingTraderSpawnChance").asInt(0), +- dynamic.get("WanderingTraderId").read(UUIDUtil.CODEC).result().orElse(null), +- dynamic.get("ServerBrands") +- .asStream() +- .flatMap(brandsDynamic -> brandsDynamic.asString().result().stream()) +- .collect(Collectors.toCollection(Sets::newLinkedHashSet)), +- dynamic.get("removed_features") +- .asStream() +- .flatMap(removedFeaturesDynamic -> removedFeaturesDynamic.asString().result().stream()) +- .collect(Collectors.toSet()), +- new TimerQueue<>(TimerCallbacks.SERVER_CALLBACKS, dynamic.get("ScheduledEvents").asStream()), +- (CompoundTag)dynamic.get("CustomBossEvents").orElseEmptyMap().getValue(), +- dynamic.get("DragonFight").read(EndDragonFight.Data.CODEC).resultOrPartial(LOGGER::error).orElse(EndDragonFight.Data.DEFAULT), +- levelSettings, +- worldOptions, +- specialWorldProperty, +- lifecycle +- ); ++ public static PrimaryLevelData parse(Dynamic dynamic, LevelSettings worldsettings, PrimaryLevelData.a worlddataserver_a, WorldOptions worldoptions, Lifecycle lifecycle) { ++ long i = dynamic.get("Time").asLong(0L); ++ CompoundTag nbttagcompound = (CompoundTag) CompoundTag.CODEC.parse(dynamic.get("Player").orElseEmptyMap()).result().orElse(null); // CraftBukkit - decompile error ++ boolean flag = dynamic.get("WasModded").asBoolean(false); ++ int j = dynamic.get("SpawnX").asInt(0); ++ int k = dynamic.get("SpawnY").asInt(0); ++ int l = dynamic.get("SpawnZ").asInt(0); ++ float f = dynamic.get("SpawnAngle").asFloat(0.0F); ++ long i1 = dynamic.get("DayTime").asLong(i); ++ int j1 = LevelVersion.parse(dynamic).levelDataVersion(); ++ int k1 = dynamic.get("clearWeatherTime").asInt(0); ++ int l1 = dynamic.get("rainTime").asInt(0); ++ boolean flag1 = dynamic.get("raining").asBoolean(false); ++ int i2 = dynamic.get("thunderTime").asInt(0); ++ boolean flag2 = dynamic.get("thundering").asBoolean(false); ++ boolean flag3 = dynamic.get("initialized").asBoolean(true); ++ boolean flag4 = dynamic.get("DifficultyLocked").asBoolean(false); ++ WorldBorder.Settings worldborder_c = WorldBorder.Settings.read(dynamic, WorldBorder.DEFAULT_SETTINGS); ++ int j2 = dynamic.get("WanderingTraderSpawnDelay").asInt(0); ++ int k2 = dynamic.get("WanderingTraderSpawnChance").asInt(0); ++ UUID uuid = (UUID) dynamic.get("WanderingTraderId").read(UUIDUtil.CODEC).result().orElse(null); // CraftBukkit - decompile error ++ Set set = (Set) dynamic.get("ServerBrands").asStream().flatMap((dynamic1) -> { ++ return dynamic1.asString().result().stream(); ++ }).collect(Collectors.toCollection(Sets::newLinkedHashSet)); ++ Set set1 = (Set) dynamic.get("removed_features").asStream().flatMap((dynamic1) -> { ++ return dynamic1.asString().result().stream(); ++ }).collect(Collectors.toSet()); ++ TimerQueue customfunctioncallbacktimerqueue = new TimerQueue<>(TimerCallbacks.SERVER_CALLBACKS, dynamic.get("ScheduledEvents").asStream()); ++ CompoundTag nbttagcompound1 = (CompoundTag) dynamic.get("CustomBossEvents").orElseEmptyMap().getValue(); ++ DataResult dataresult = dynamic.get("DragonFight").read(EndDragonFight.Data.CODEC); // CraftBukkit - decompile error ++ Logger logger = PrimaryLevelData.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ return new PrimaryLevelData(nbttagcompound, flag, j, k, l, f, i, i1, j1, k1, l1, flag1, i2, flag2, flag3, flag4, worldborder_c, j2, k2, uuid, set, set1, customfunctioncallbacktimerqueue, nbttagcompound1, (EndDragonFight.Data) dataresult.resultOrPartial(logger::error).orElse(EndDragonFight.Data.DEFAULT), worldsettings, worldoptions, worlddataserver_a, lifecycle); + } + + @Override +@@ -230,9 +185,10 @@ + hostPlayerNBT = this.loadedPlayerTag; + } + +- CompoundTag compoundTag = new CompoundTag(); +- this.setTagData(registries, compoundTag, hostPlayerNBT); +- return compoundTag; ++ CompoundTag nbttagcompound1 = new CompoundTag(); ++ ++ this.setTagData(registries, nbttagcompound1, hostPlayerNBT); ++ return nbttagcompound1; + } + + private void setTagData(RegistryAccess registry, CompoundTag nbt, @Nullable CompoundTag playerNBT) { +@@ -242,17 +198,22 @@ + nbt.put("removed_features", stringCollectionToTag(this.removedFeatureFlags)); + } + +- CompoundTag compoundTag = new CompoundTag(); +- compoundTag.putString("Name", SharedConstants.getCurrentVersion().getName()); +- compoundTag.putInt("Id", SharedConstants.getCurrentVersion().getDataVersion().getVersion()); +- compoundTag.putBoolean("Snapshot", !SharedConstants.getCurrentVersion().isStable()); +- compoundTag.putString("Series", SharedConstants.getCurrentVersion().getDataVersion().getSeries()); +- nbt.put("Version", compoundTag); ++ CompoundTag nbttagcompound2 = new CompoundTag(); ++ ++ nbttagcompound2.putString("Name", SharedConstants.getCurrentVersion().getName()); ++ nbttagcompound2.putInt("Id", SharedConstants.getCurrentVersion().getDataVersion().getVersion()); ++ nbttagcompound2.putBoolean("Snapshot", !SharedConstants.getCurrentVersion().isStable()); ++ nbttagcompound2.putString("Series", SharedConstants.getCurrentVersion().getDataVersion().getSeries()); ++ nbt.put("Version", nbttagcompound2); + NbtUtils.addCurrentDataVersion(nbt); +- DynamicOps dynamicOps = RegistryOps.create(NbtOps.INSTANCE, registry); +- WorldGenSettings.encode(dynamicOps, this.worldOptions, registry) +- .resultOrPartial(Util.prefix("WorldGenSettings: ", LOGGER::error)) +- .ifPresent(worldOptionsTag -> nbt.put("WorldGenSettings", worldOptionsTag)); ++ DynamicOps dynamicops = RegistryOps.create(NbtOps.INSTANCE, (HolderLookup.Provider) registry); ++ DataResult dataresult = WorldGenSettings.encode(dynamicops, this.worldOptions, new WorldDimensions(this.customDimensions != null ? this.customDimensions : registry.registryOrThrow(Registries.LEVEL_STEM))); // CraftBukkit ++ Logger logger = PrimaryLevelData.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(Util.prefix("WorldGenSettings: ", logger::error)).ifPresent((nbtbase) -> { ++ nbt.put("WorldGenSettings", nbtbase); ++ }); + nbt.putInt("GameType", this.settings.gameType().getId()); + nbt.putInt("SpawnX", this.xSpawn); + nbt.putInt("SpawnY", this.ySpawn); +@@ -272,18 +233,21 @@ + nbt.putBoolean("allowCommands", this.settings.allowCommands()); + nbt.putBoolean("initialized", this.initialized); + this.worldBorder.write(nbt); +- nbt.putByte("Difficulty", (byte)this.settings.difficulty().getId()); ++ nbt.putByte("Difficulty", (byte) this.settings.difficulty().getId()); + nbt.putBoolean("DifficultyLocked", this.difficultyLocked); + nbt.put("GameRules", this.settings.gameRules().createTag()); +- nbt.put("DragonFight", Util.getOrThrow(EndDragonFight.Data.CODEC.encodeStart(NbtOps.INSTANCE, this.endDragonFightData), IllegalStateException::new)); ++ nbt.put("DragonFight", (Tag) Util.getOrThrow(EndDragonFight.Data.CODEC.encodeStart(NbtOps.INSTANCE, this.endDragonFightData), IllegalStateException::new)); + if (playerNBT != null) { + nbt.put("Player", playerNBT); + } + +- DataResult dataResult = WorldDataConfiguration.CODEC.encodeStart(NbtOps.INSTANCE, this.settings.getDataConfiguration()); +- dataResult.get() +- .ifLeft(dataConfigurationTag -> nbt.merge((CompoundTag)dataConfigurationTag)) +- .ifRight(partialResult -> LOGGER.warn("Failed to encode configuration {}", partialResult.message())); ++ DataResult dataresult1 = WorldDataConfiguration.CODEC.encodeStart(NbtOps.INSTANCE, this.settings.getDataConfiguration()); ++ ++ dataresult1.get().ifLeft((nbtbase) -> { ++ nbt.merge((CompoundTag) nbtbase); ++ }).ifRight((partialresult) -> { ++ PrimaryLevelData.LOGGER.warn("Failed to encode configuration {}", partialresult.message()); ++ }); + if (this.customBossEvents != null) { + nbt.put("CustomBossEvents", this.customBossEvents); + } +@@ -294,12 +258,18 @@ + if (this.wanderingTraderId != null) { + nbt.putUUID("WanderingTraderId", this.wanderingTraderId); + } ++ ++ nbt.putString("Bukkit.Version", Bukkit.getName() + "/" + Bukkit.getVersion() + "/" + Bukkit.getBukkitVersion()); // CraftBukkit ++ world.getWorld().storeBukkitValues(nbt); // CraftBukkit - add pdc + } + + private static ListTag stringCollectionToTag(Set stringCollection) { +- ListTag list = new ListTag(); +- stringCollection.stream().map(StringTag::valueOf).forEach(list::add); +- return list; ++ ListTag nbttaglist = new ListTag(); ++ Stream stream = stringCollection.stream().map(StringTag::valueOf); // CraftBukkit - decompile error ++ ++ Objects.requireNonNull(nbttaglist); ++ stream.forEach(nbttaglist::add); ++ return nbttaglist; + } + + @Override +@@ -403,6 +373,20 @@ + + @Override + public void setThundering(boolean thundering) { ++ // CraftBukkit start ++ if (this.thundering == thundering) { ++ return; ++ } ++ ++ org.bukkit.World world = Bukkit.getWorld(getLevelName()); ++ if (world != null) { ++ ThunderChangeEvent thunder = new ThunderChangeEvent(world, thundering); ++ Bukkit.getServer().getPluginManager().callEvent(thunder); ++ if (thunder.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + this.thundering = thundering; + } + +@@ -423,6 +407,20 @@ + + @Override + public void setRaining(boolean isRaining) { ++ // CraftBukkit start ++ if (this.raining == isRaining) { ++ return; ++ } ++ ++ org.bukkit.World world = Bukkit.getWorld(getLevelName()); ++ if (world != null) { ++ WeatherChangeEvent weather = new WeatherChangeEvent(world, isRaining); ++ Bukkit.getServer().getPluginManager().callEvent(weather); ++ if (weather.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + this.raining = isRaining; + } + +@@ -489,6 +487,12 @@ + @Override + public void setDifficulty(Difficulty difficulty) { + this.settings = this.settings.withDifficulty(difficulty); ++ // CraftBukkit start ++ ClientboundChangeDifficultyPacket packet = new ClientboundChangeDifficultyPacket(this.getDifficulty(), this.isDifficultyLocked()); ++ for (ServerPlayer player : (java.util.List) (java.util.List) world.players()) { ++ player.connection.send(packet); ++ } ++ // CraftBukkit end + } + + @Override +@@ -519,12 +523,12 @@ + + @Override + public boolean isFlatWorld() { +- return this.specialWorldProperty == PrimaryLevelData.SpecialWorldProperty.FLAT; ++ return this.specialWorldProperty == PrimaryLevelData.a.FLAT; + } + + @Override + public boolean isDebugWorld() { +- return this.specialWorldProperty == PrimaryLevelData.SpecialWorldProperty.DEBUG; ++ return this.specialWorldProperty == PrimaryLevelData.a.DEBUG; + } + + @Override +@@ -625,10 +629,20 @@ + return this.settings.copy(); + } + ++ // CraftBukkit start - Check if the name stored in NBT is the correct one ++ public void checkName(String name) { ++ if (!this.settings.levelName.equals(name)) { ++ this.settings.levelName = name; ++ } ++ } ++ // CraftBukkit end ++ ++ /** @deprecated */ + @Deprecated +- public static enum SpecialWorldProperty { +- NONE, +- FLAT, +- DEBUG; ++ public static enum a { ++ ++ NONE, FLAT, DEBUG; ++ ++ private a() {} + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/storage/loot/LootDataManager.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/storage/loot/LootDataManager.java.patch new file mode 100644 index 0000000000..c47129877c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/storage/loot/LootDataManager.java.patch @@ -0,0 +1,176 @@ +--- a/net/minecraft/world/level/storage/loot/LootDataManager.java ++++ b/net/minecraft/world/level/storage/loot/LootDataManager.java +@@ -1,9 +1,9 @@ + package net.minecraft.world.level.storage.loot; + + import com.google.common.collect.ImmutableMap; ++import com.google.common.collect.ImmutableMap.Builder; + import com.google.common.collect.ImmutableMultimap; + import com.google.common.collect.Multimap; +-import com.google.common.collect.ImmutableMap.Builder; + import com.google.gson.Gson; + import com.google.gson.GsonBuilder; + import com.google.gson.JsonElement; +@@ -11,6 +11,7 @@ + import java.util.Collection; + import java.util.HashMap; + import java.util.Map; ++import java.util.Objects; + import java.util.concurrent.CompletableFuture; + import java.util.concurrent.Executor; + import javax.annotation.Nullable; +@@ -21,87 +22,104 @@ + import net.minecraft.util.ProblemReporter; + import net.minecraft.util.profiling.ProfilerFiller; + import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; ++import org.bukkit.craftbukkit.CraftLootTable; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; + import org.slf4j.Logger; + + public class LootDataManager implements PreparableReloadListener, LootDataResolver { ++ + private static final Logger LOGGER = LogUtils.getLogger(); +- private static final Gson GSON = new GsonBuilder().create(); ++ private static final Gson GSON = (new GsonBuilder()).create(); + public static final LootDataId EMPTY_LOOT_TABLE_KEY = new LootDataId<>(LootDataType.TABLE, BuiltInLootTables.EMPTY); + private Map, ?> elements = Map.of(); + private Multimap, ResourceLocation> typeKeys = ImmutableMultimap.of(); + ++ public LootDataManager() {} ++ + @Override +- public final CompletableFuture reload( +- PreparableReloadListener.PreparationBarrier preparationBarrier, +- ResourceManager resourceManager, +- ProfilerFiller preparationsProfiler, +- ProfilerFiller reloadProfiler, +- Executor backgroundExecutor, +- Executor gameExecutor +- ) { +- Map, Map> map = new HashMap<>(); +- CompletableFuture[] completableFutures = LootDataType.values() +- .map(lootDataType -> scheduleElementParse((LootDataType)lootDataType, resourceManager, backgroundExecutor, map)) +- .toArray(CompletableFuture[]::new); +- return CompletableFuture.allOf(completableFutures).thenCompose(preparationBarrier::wait).thenAcceptAsync(ignored -> this.apply(map), gameExecutor); ++ public final CompletableFuture reload(PreparableReloadListener.PreparationBarrier preparationBarrier, ResourceManager resourceManager, ProfilerFiller preparationsProfiler, ProfilerFiller reloadProfiler, Executor backgroundExecutor, Executor gameExecutor) { ++ Map, Map> map = new HashMap(); ++ CompletableFuture[] acompletablefuture = (CompletableFuture[]) LootDataType.values().map((lootdatatype) -> { ++ return scheduleElementParse(lootdatatype, resourceManager, backgroundExecutor, map); ++ }).toArray((i) -> { ++ return new CompletableFuture[i]; ++ }); ++ CompletableFuture completablefuture = CompletableFuture.allOf(acompletablefuture); ++ ++ Objects.requireNonNull(preparationBarrier); ++ return completablefuture.thenCompose(preparationBarrier::wait).thenAcceptAsync((ovoid) -> { ++ this.apply(map); ++ }, gameExecutor); + } + +- private static CompletableFuture scheduleElementParse( +- LootDataType lootDataType, +- ResourceManager resourceManager, +- Executor backgroundExecutor, +- Map, Map> elementCollector +- ) { +- Map map = new HashMap<>(); +- elementCollector.put(lootDataType, map); +- return CompletableFuture.runAsync( +- () -> { +- Map map1 = new HashMap<>(); +- SimpleJsonResourceReloadListener.scanDirectory(resourceManager, lootDataType.directory(), GSON, map1); +- map1.forEach( +- (elementName, elementJson) -> lootDataType.deserialize(elementName, elementJson).ifPresent(element -> map.put(elementName, (T)element)) +- ); +- }, +- backgroundExecutor +- ); ++ private static CompletableFuture scheduleElementParse(LootDataType lootDataType, ResourceManager resourceManager, Executor backgroundExecutor, Map, Map> elementCollector) { ++ Map map1 = new HashMap(); ++ ++ elementCollector.put(lootDataType, map1); ++ return CompletableFuture.runAsync(() -> { ++ Map map2 = new HashMap(); ++ ++ SimpleJsonResourceReloadListener.scanDirectory(resourceManager, lootDataType.directory(), LootDataManager.GSON, map2); ++ map2.forEach((minecraftkey, jsonelement) -> { ++ lootDataType.deserialize(minecraftkey, jsonelement).ifPresent((object) -> { ++ map1.put(minecraftkey, object); ++ }); ++ }); ++ }, backgroundExecutor); + } + + private void apply(Map, Map> collectedElements) { +- Object object = collectedElements.get(LootDataType.TABLE).remove(BuiltInLootTables.EMPTY); ++ Object object = ((Map) collectedElements.get(LootDataType.TABLE)).remove(BuiltInLootTables.EMPTY); ++ + if (object != null) { +- LOGGER.warn("Datapack tried to redefine {} loot table, ignoring", BuiltInLootTables.EMPTY); ++ LootDataManager.LOGGER.warn("Datapack tried to redefine {} loot table, ignoring", BuiltInLootTables.EMPTY); + } + + Builder, Object> builder = ImmutableMap.builder(); +- com.google.common.collect.ImmutableMultimap.Builder, ResourceLocation> builder1 = ImmutableMultimap.builder(); +- collectedElements.forEach((lootDataType, elements) -> elements.forEach((elementName, element) -> { +- builder.put(new LootDataId(lootDataType, elementName), element); +- builder1.put(lootDataType, elementName); +- })); +- builder.put(EMPTY_LOOT_TABLE_KEY, LootTable.EMPTY); +- ProblemReporter.Collector collector = new ProblemReporter.Collector(); +- final Map, ?> map = builder.build(); +- ValidationContext validationContext = new ValidationContext(collector, LootContextParamSets.ALL_PARAMS, new LootDataResolver() { ++ com.google.common.collect.ImmutableMultimap.Builder, ResourceLocation> com_google_common_collect_immutablemultimap_builder = ImmutableMultimap.builder(); ++ ++ collectedElements.forEach((lootdatatype, map1) -> { ++ map1.forEach((minecraftkey, object1) -> { ++ builder.put(new LootDataId<>(lootdatatype, minecraftkey), object1); ++ com_google_common_collect_immutablemultimap_builder.put(lootdatatype, minecraftkey); ++ }); ++ }); ++ builder.put(LootDataManager.EMPTY_LOOT_TABLE_KEY, LootTable.EMPTY); ++ ProblemReporter.a problemreporter_a = new ProblemReporter.a(); ++ final Map, ?> map1 = builder.build(); ++ ValidationContext lootcollector = new ValidationContext(problemreporter_a, LootContextParamSets.ALL_PARAMS, new LootDataResolver() { + @Nullable + @Override + public T getElement(LootDataId id) { +- return (T)map.get(id); ++ return (T) map1.get(id); // CraftBukkit - decompile error + } + }); +- map.forEach((id, element) -> castAndValidate(validationContext, id, element)); +- collector.get().forEach((errorOwner, errorMessage) -> LOGGER.warn("Found loot table element validation problem in {}: {}", errorOwner, errorMessage)); +- this.elements = map; +- this.typeKeys = builder1.build(); ++ ++ map1.forEach((lootdataid, object1) -> { ++ castAndValidate(lootcollector, lootdataid, object1); ++ }); ++ problemreporter_a.get().forEach((s, s1) -> { ++ LootDataManager.LOGGER.warn("Found loot table element validation problem in {}: {}", s, s1); ++ }); ++ // CraftBukkit start ++ map1.forEach((key, lootTable) -> { ++ if (object instanceof LootTable table) { ++ table.craftLootTable = new CraftLootTable(CraftNamespacedKey.fromMinecraft(key.location()), table); ++ } ++ }); ++ // CraftBukkit end ++ this.elements = map1; ++ this.typeKeys = com_google_common_collect_immutablemultimap_builder.build(); + } + + private static void castAndValidate(ValidationContext context, LootDataId id, Object element) { +- id.type().runValidation(context, id, (T)element); ++ id.type().runValidation(context, id, (T) element); // CraftBukkit - decompile error + } + + @Nullable + @Override + public T getElement(LootDataId id) { +- return (T)this.elements.get(id); ++ return (T) this.elements.get(id); // CraftBukkit - decompile error + } + + public Collection getKeys(LootDataType type) { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/storage/loot/LootTable.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/storage/loot/LootTable.java.patch new file mode 100644 index 0000000000..e2e20138cc --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/storage/loot/LootTable.java.patch @@ -0,0 +1,341 @@ +--- a/net/minecraft/world/level/storage/loot/LootTable.java ++++ b/net/minecraft/world/level/storage/loot/LootTable.java +@@ -1,14 +1,16 @@ + package net.minecraft.world.level.storage.loot; + + import com.google.common.collect.ImmutableList; ++import com.google.common.collect.ImmutableList.Builder; + import com.google.common.collect.Lists; + import com.mojang.logging.LogUtils; + import com.mojang.serialization.Codec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import it.unimi.dsi.fastutil.objects.ObjectArrayList; ++import it.unimi.dsi.fastutil.objects.ObjectListIterator; + import java.util.Iterator; + import java.util.List; ++import java.util.Objects; + import java.util.Optional; + import java.util.function.BiFunction; + import java.util.function.Consumer; +@@ -27,27 +29,38 @@ + import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.CraftLootTable; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.world.LootGenerateEvent; ++// CraftBukkit end ++ + public class LootTable { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + public static final LootTable EMPTY = new LootTable(LootContextParamSets.EMPTY, Optional.empty(), List.of(), List.of()); + public static final LootContextParamSet DEFAULT_PARAM_SET = LootContextParamSets.ALL_PARAMS; +- public static final Codec CODEC = RecordCodecBuilder.create( +- instance -> instance.group( +- LootContextParamSets.CODEC.optionalFieldOf("type", DEFAULT_PARAM_SET).forGetter(lootTable -> lootTable.paramSet), +- ExtraCodecs.strictOptionalField(ResourceLocation.CODEC, "random_sequence").forGetter(lootTable -> lootTable.randomSequence), +- ExtraCodecs.strictOptionalField(LootPool.CODEC.listOf(), "pools", List.of()).forGetter(lootTable -> lootTable.pools), +- ExtraCodecs.strictOptionalField(LootItemFunctions.CODEC.listOf(), "functions", List.of()).forGetter(lootTable -> lootTable.functions) +- ) +- .apply(instance, LootTable::new) +- ); ++ public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(LootContextParamSets.CODEC.optionalFieldOf("type", LootTable.DEFAULT_PARAM_SET).forGetter((loottable) -> { ++ return loottable.paramSet; ++ }), ExtraCodecs.strictOptionalField(ResourceLocation.CODEC, "random_sequence").forGetter((loottable) -> { ++ return loottable.randomSequence; ++ }), ExtraCodecs.strictOptionalField(LootPool.CODEC.listOf(), "pools", List.of()).forGetter((loottable) -> { ++ return loottable.pools; ++ }), ExtraCodecs.strictOptionalField(LootItemFunctions.CODEC.listOf(), "functions", List.of()).forGetter((loottable) -> { ++ return loottable.functions; ++ })).apply(instance, LootTable::new); ++ }); + private final LootContextParamSet paramSet; + private final Optional randomSequence; + private final List pools; + private final List functions; + private final BiFunction compositeFunction; ++ public CraftLootTable craftLootTable; // CraftBukkit + +- LootTable(LootContextParamSet lootContextParamSet, Optional optional, List list, List list1) { +- this.paramSet = lootContextParamSet; ++ LootTable(LootContextParamSet lootcontextparameterset, Optional optional, List list, List list1) { ++ this.paramSet = lootcontextparameterset; + this.randomSequence = optional; + this.pools = list; + this.functions = list1; +@@ -55,46 +68,51 @@ + } + + public static Consumer createStackSplitter(ServerLevel level, Consumer output) { +- return itemStack -> { +- if (itemStack.isItemEnabled(level.enabledFeatures())) { +- if (itemStack.getCount() < itemStack.getMaxStackSize()) { +- output.accept(itemStack); ++ return (itemstack) -> { ++ if (itemstack.isItemEnabled(level.enabledFeatures())) { ++ if (itemstack.getCount() < itemstack.getMaxStackSize()) { ++ output.accept(itemstack); + } else { +- int count = itemStack.getCount(); ++ int i = itemstack.getCount(); + +- while (count > 0) { +- ItemStack itemStack1 = itemStack.copyWithCount(Math.min(itemStack.getMaxStackSize(), count)); +- count -= itemStack1.getCount(); +- output.accept(itemStack1); ++ while (i > 0) { ++ ItemStack itemstack1 = itemstack.copyWithCount(Math.min(itemstack.getMaxStackSize(), i)); ++ ++ i -= itemstack1.getCount(); ++ output.accept(itemstack1); + } + } ++ + } + }; + } + + public void getRandomItemsRaw(LootParams params, Consumer output) { +- this.getRandomItemsRaw(new LootContext.Builder(params).create(this.randomSequence), output); ++ this.getRandomItemsRaw((new LootContext.Builder(params)).create(this.randomSequence), output); + } + + public void getRandomItemsRaw(LootContext context, Consumer output) { +- LootContext.VisitedEntry visitedEntry = LootContext.createVisitedEntry(this); +- if (context.pushVisitedElement(visitedEntry)) { +- Consumer consumer = LootItemFunction.decorate(this.compositeFunction, output, context); ++ LootContext.c loottableinfo_c = LootContext.createVisitedEntry(this); + +- for (LootPool lootPool : this.pools) { +- lootPool.addRandomItems(consumer, context); ++ if (context.pushVisitedElement(loottableinfo_c)) { ++ Consumer consumer1 = LootItemFunction.decorate(this.compositeFunction, output, context); ++ Iterator iterator = this.pools.iterator(); ++ ++ while (iterator.hasNext()) { ++ LootPool lootselector = (LootPool) iterator.next(); ++ ++ lootselector.addRandomItems(consumer1, context); + } + +- context.popVisitedElement(visitedEntry); ++ context.popVisitedElement(loottableinfo_c); + } else { +- LOGGER.warn("Detected infinite loop in loot tables"); ++ LootTable.LOGGER.warn("Detected infinite loop in loot tables"); + } ++ + } + +- public void getRandomItems(LootParams params, long seed, Consumer output) { +- this.getRandomItemsRaw( +- new LootContext.Builder(params).withOptionalRandomSeed(seed).create(this.randomSequence), createStackSplitter(params.getLevel(), output) +- ); ++ public void getRandomItems(LootParams params, long seed, Consumer consumer) { ++ this.getRandomItemsRaw((new LootContext.Builder(params)).withOptionalRandomSeed(seed).create(this.randomSequence), createStackSplitter(params.getLevel(), consumer)); + } + + public void getRandomItems(LootParams params, Consumer output) { +@@ -106,17 +124,19 @@ + } + + public ObjectArrayList getRandomItems(LootParams params, long seed) { +- return this.getRandomItems(new LootContext.Builder(params).withOptionalRandomSeed(seed).create(this.randomSequence)); ++ return this.getRandomItems((new LootContext.Builder(params)).withOptionalRandomSeed(seed).create(this.randomSequence)); + } + + public ObjectArrayList getRandomItems(LootParams params) { +- return this.getRandomItems(new LootContext.Builder(params).create(this.randomSequence)); ++ return this.getRandomItems((new LootContext.Builder(params)).create(this.randomSequence)); + } + + private ObjectArrayList getRandomItems(LootContext context) { +- ObjectArrayList list = new ObjectArrayList<>(); +- this.getRandomItems(context, list::add); +- return list; ++ ObjectArrayList objectarraylist = new ObjectArrayList(); ++ ++ Objects.requireNonNull(objectarraylist); ++ this.getRandomItems(context, objectarraylist::add); ++ return objectarraylist; + } + + public LootContextParamSet getParamSet() { +@@ -124,64 +144,87 @@ + } + + public void validate(ValidationContext validator) { +- for (int i = 0; i < this.pools.size(); i++) { +- this.pools.get(i).validate(validator.forChild(".pools[" + i + "]")); ++ int i; ++ ++ for (i = 0; i < this.pools.size(); ++i) { ++ ((LootPool) this.pools.get(i)).validate(validator.forChild(".pools[" + i + "]")); + } + +- for (int i = 0; i < this.functions.size(); i++) { +- this.functions.get(i).validate(validator.forChild(".functions[" + i + "]")); ++ for (i = 0; i < this.functions.size(); ++i) { ++ ((LootItemFunction) this.functions.get(i)).validate(validator.forChild(".functions[" + i + "]")); + } ++ + } + + public void fill(Container container, LootParams params, long seed) { +- LootContext lootContext = new LootContext.Builder(params).withOptionalRandomSeed(seed).create(this.randomSequence); +- ObjectArrayList randomItems = this.getRandomItems(lootContext); +- RandomSource random = lootContext.getRandom(); +- List availableSlots = this.getAvailableSlots(container, random); +- this.shuffleAndSplitItems(randomItems, availableSlots.size(), random); ++ // CraftBukkit start ++ this.fillInventory(container, params, seed, false); ++ } + +- for (ItemStack itemStack : randomItems) { +- if (availableSlots.isEmpty()) { +- LOGGER.warn("Tried to over-fill a container"); ++ public void fillInventory(Container iinventory, LootParams lootparams, long i, boolean plugin) { ++ // CraftBukkit end ++ LootContext loottableinfo = (new LootContext.Builder(lootparams)).withOptionalRandomSeed(i).create(this.randomSequence); ++ ObjectArrayList objectarraylist = this.getRandomItems(loottableinfo); ++ RandomSource randomsource = loottableinfo.getRandom(); ++ // CraftBukkit start ++ LootGenerateEvent event = CraftEventFactory.callLootGenerateEvent(iinventory, this, loottableinfo, objectarraylist, plugin); ++ if (event.isCancelled()) { ++ return; ++ } ++ objectarraylist = event.getLoot().stream().map(CraftItemStack::asNMSCopy).collect(ObjectArrayList.toList()); ++ // CraftBukkit end ++ List list = this.getAvailableSlots(iinventory, randomsource); ++ ++ this.shuffleAndSplitItems(objectarraylist, list.size(), randomsource); ++ ObjectListIterator objectlistiterator = objectarraylist.iterator(); ++ ++ while (objectlistiterator.hasNext()) { ++ ItemStack itemstack = (ItemStack) objectlistiterator.next(); ++ ++ if (list.isEmpty()) { ++ LootTable.LOGGER.warn("Tried to over-fill a container"); + return; + } + +- if (itemStack.isEmpty()) { +- container.setItem(availableSlots.remove(availableSlots.size() - 1), ItemStack.EMPTY); ++ if (itemstack.isEmpty()) { ++ iinventory.setItem((Integer) list.remove(list.size() - 1), ItemStack.EMPTY); + } else { +- container.setItem(availableSlots.remove(availableSlots.size() - 1), itemStack); ++ iinventory.setItem((Integer) list.remove(list.size() - 1), itemstack); + } + } ++ + } + + private void shuffleAndSplitItems(ObjectArrayList stacks, int emptySlotsCount, RandomSource random) { + List list = Lists.newArrayList(); +- Iterator iterator = stacks.iterator(); ++ ObjectListIterator objectlistiterator = stacks.iterator(); + +- while (iterator.hasNext()) { +- ItemStack itemStack = iterator.next(); +- if (itemStack.isEmpty()) { +- iterator.remove(); +- } else if (itemStack.getCount() > 1) { +- list.add(itemStack); +- iterator.remove(); ++ while (objectlistiterator.hasNext()) { ++ ItemStack itemstack = (ItemStack) objectlistiterator.next(); ++ ++ if (itemstack.isEmpty()) { ++ objectlistiterator.remove(); ++ } else if (itemstack.getCount() > 1) { ++ list.add(itemstack); ++ objectlistiterator.remove(); + } + } + + while (emptySlotsCount - stacks.size() - list.size() > 0 && !list.isEmpty()) { +- ItemStack itemStack1 = list.remove(Mth.nextInt(random, 0, list.size() - 1)); +- int randomInt = Mth.nextInt(random, 1, itemStack1.getCount() / 2); +- ItemStack itemStack2 = itemStack1.split(randomInt); +- if (itemStack1.getCount() > 1 && random.nextBoolean()) { +- list.add(itemStack1); ++ ItemStack itemstack1 = (ItemStack) list.remove(Mth.nextInt(random, 0, list.size() - 1)); ++ int j = Mth.nextInt(random, 1, itemstack1.getCount() / 2); ++ ItemStack itemstack2 = itemstack1.split(j); ++ ++ if (itemstack1.getCount() > 1 && random.nextBoolean()) { ++ list.add(itemstack1); + } else { +- stacks.add(itemStack1); ++ stacks.add(itemstack1); + } + +- if (itemStack2.getCount() > 1 && random.nextBoolean()) { +- list.add(itemStack2); ++ if (itemstack2.getCount() > 1 && random.nextBoolean()) { ++ list.add(itemstack2); + } else { +- stacks.add(itemStack2); ++ stacks.add(itemstack2); + } + } + +@@ -190,16 +233,16 @@ + } + + private List getAvailableSlots(Container inventory, RandomSource random) { +- ObjectArrayList list = new ObjectArrayList<>(); ++ ObjectArrayList objectarraylist = new ObjectArrayList(); + +- for (int i = 0; i < inventory.getContainerSize(); i++) { ++ for (int i = 0; i < inventory.getContainerSize(); ++i) { + if (inventory.getItem(i).isEmpty()) { +- list.add(i); ++ objectarraylist.add(i); + } + } + +- Util.shuffle(list, random); +- return list; ++ Util.shuffle(objectarraylist, random); ++ return objectarraylist; + } + + public static LootTable.Builder lootTable() { +@@ -207,11 +250,17 @@ + } + + public static class Builder implements FunctionUserBuilder { +- private final ImmutableList.Builder pools = ImmutableList.builder(); +- private final ImmutableList.Builder functions = ImmutableList.builder(); +- private LootContextParamSet paramSet = LootTable.DEFAULT_PARAM_SET; +- private Optional randomSequence = Optional.empty(); + ++ private final Builder pools = ImmutableList.builder(); ++ private final Builder functions = ImmutableList.builder(); ++ private LootContextParamSet paramSet; ++ private Optional randomSequence; ++ ++ public Builder() { ++ this.paramSet = LootTable.DEFAULT_PARAM_SET; ++ this.randomSequence = Optional.empty(); ++ } ++ + public LootTable.Builder withPool(LootPool.Builder lootPool) { + this.pools.add(lootPool.build()); + return this; +@@ -228,7 +277,7 @@ + } + + @Override +- public LootTable.Builder apply(LootItemFunction.Builder functionBuilder) { ++ public LootTable.Builder apply(LootItemFunction.a functionBuilder) { + this.functions.add(functionBuilder.build()); + return this; + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java.patch new file mode 100644 index 0000000000..c9221be8a7 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java.patch @@ -0,0 +1,81 @@ +--- a/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java ++++ b/net/minecraft/world/level/storage/loot/functions/LootingEnchantFunction.java +@@ -4,7 +4,6 @@ + import com.google.common.collect.Sets; + import com.mojang.serialization.Codec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import java.util.List; + import java.util.Set; + import net.minecraft.util.ExtraCodecs; +@@ -20,23 +19,21 @@ + import net.minecraft.world.level.storage.loot.providers.number.NumberProviders; + + public class LootingEnchantFunction extends LootItemConditionalFunction { ++ + public static final int NO_LIMIT = 0; +- public static final Codec CODEC = RecordCodecBuilder.create( +- instance -> commonFields(instance) +- .and( +- instance.group( +- NumberProviders.CODEC.fieldOf("count").forGetter(lootingEnchantFunction -> lootingEnchantFunction.value), +- ExtraCodecs.strictOptionalField(Codec.INT, "limit", 0).forGetter(lootingEnchantFunction -> lootingEnchantFunction.limit) +- ) +- ) +- .apply(instance, LootingEnchantFunction::new) +- ); ++ public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { ++ return commonFields(instance).and(instance.group(NumberProviders.CODEC.fieldOf("count").forGetter((lootenchantfunction) -> { ++ return lootenchantfunction.value; ++ }), ExtraCodecs.strictOptionalField(Codec.INT, "limit", 0).forGetter((lootenchantfunction) -> { ++ return lootenchantfunction.limit; ++ }))).apply(instance, LootingEnchantFunction::new); ++ }); + private final NumberProvider value; + private final int limit; + +- LootingEnchantFunction(List list, NumberProvider numberProvider, int i) { ++ LootingEnchantFunction(List list, NumberProvider numberprovider, int i) { + super(list); +- this.value = numberProvider; ++ this.value = numberprovider; + this.limit = i; + } + +@@ -56,14 +53,22 @@ + + @Override + public ItemStack run(ItemStack stack, LootContext context) { +- Entity entity = context.getParamOrNull(LootContextParams.KILLER_ENTITY); ++ Entity entity = (Entity) context.getParamOrNull(LootContextParams.KILLER_ENTITY); ++ + if (entity instanceof LivingEntity) { +- int mobLooting = EnchantmentHelper.getMobLooting((LivingEntity)entity); +- if (mobLooting == 0) { ++ int i = EnchantmentHelper.getMobLooting((LivingEntity) entity); ++ // CraftBukkit start - use lootingModifier if set by plugin ++ if (context.hasParam(LootContextParams.LOOTING_MOD)) { ++ i = context.getParamOrNull(LootContextParams.LOOTING_MOD); ++ } ++ // CraftBukkit end ++ ++ if (i <= 0) { // CraftBukkit - account for possible negative looting values from Bukkit + return stack; + } + +- float f = (float)mobLooting * this.value.getFloat(context); ++ float f = (float) i * this.value.getFloat(context); ++ + stack.grow(Math.round(f)); + if (this.hasLimit() && stack.getCount() > this.limit) { + stack.setCount(this.limit); +@@ -77,7 +82,8 @@ + return new LootingEnchantFunction.Builder(lootingMultiplier); + } + +- public static class Builder extends LootItemConditionalFunction.Builder { ++ public static class Builder extends LootItemConditionalFunction.a { ++ + private final NumberProvider count; + private int limit = 0; + diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/storage/loot/parameters/LootContextParams.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/storage/loot/parameters/LootContextParams.java.patch new file mode 100644 index 0000000000..63abc11770 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/storage/loot/parameters/LootContextParams.java.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/level/storage/loot/parameters/LootContextParams.java ++++ b/net/minecraft/world/level/storage/loot/parameters/LootContextParams.java +@@ -6,21 +6,25 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; + + public class LootContextParams { ++ + public static final LootContextParam THIS_ENTITY = create("this_entity"); + public static final LootContextParam LAST_DAMAGE_PLAYER = create("last_damage_player"); + public static final LootContextParam DAMAGE_SOURCE = create("damage_source"); + public static final LootContextParam KILLER_ENTITY = create("killer_entity"); + public static final LootContextParam DIRECT_KILLER_ENTITY = create("direct_killer_entity"); + public static final LootContextParam ORIGIN = create("origin"); +- public static final LootContextParam BLOCK_STATE = create("block_state"); ++ public static final LootContextParam BLOCK_STATE = create("block_state"); + public static final LootContextParam BLOCK_ENTITY = create("block_entity"); + public static final LootContextParam TOOL = create("tool"); + public static final LootContextParam EXPLOSION_RADIUS = create("explosion_radius"); ++ public static final LootContextParam LOOTING_MOD = new LootContextParam<>(new ResourceLocation("bukkit:looting_mod")); // CraftBukkit + ++ public LootContextParams() {} ++ + private static LootContextParam create(String id) { + return new LootContextParam<>(new ResourceLocation(id)); + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/storage/loot/predicates/ExplosionCondition.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/storage/loot/predicates/ExplosionCondition.java.patch new file mode 100644 index 0000000000..c9795d4f72 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/storage/loot/predicates/ExplosionCondition.java.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/world/level/storage/loot/predicates/ExplosionCondition.java ++++ b/net/minecraft/world/level/storage/loot/predicates/ExplosionCondition.java +@@ -9,11 +9,11 @@ + import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + + public class ExplosionCondition implements LootItemCondition { ++ + private static final ExplosionCondition INSTANCE = new ExplosionCondition(); +- public static final Codec CODEC = Codec.unit(INSTANCE); ++ public static final Codec CODEC = Codec.unit(ExplosionCondition.INSTANCE); + +- private ExplosionCondition() { +- } ++ private ExplosionCondition() {} + + @Override + public LootItemConditionType getType() { +@@ -25,19 +25,23 @@ + return ImmutableSet.of(LootContextParams.EXPLOSION_RADIUS); + } + +- @Override + public boolean test(LootContext context) { +- Float _float = context.getParamOrNull(LootContextParams.EXPLOSION_RADIUS); +- if (_float != null) { +- RandomSource random = context.getRandom(); +- float f = 1.0F / _float; +- return random.nextFloat() <= f; ++ Float ofloat = (Float) context.getParamOrNull(LootContextParams.EXPLOSION_RADIUS); ++ ++ if (ofloat != null) { ++ RandomSource randomsource = context.getRandom(); ++ float f = 1.0F / ofloat; ++ ++ // CraftBukkit - <= to < to allow for plugins to completely disable block drops from explosions ++ return randomsource.nextFloat() < f; + } else { + return true; + } + } + + public static LootItemCondition.Builder survivesExplosion() { +- return () -> INSTANCE; ++ return () -> { ++ return ExplosionCondition.INSTANCE; ++ }; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/level/storage/loot/predicates/LootItemRandomChanceWithLootingCondition.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/level/storage/loot/predicates/LootItemRandomChanceWithLootingCondition.java.patch new file mode 100644 index 0000000000..ba4742b6d0 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/level/storage/loot/predicates/LootItemRandomChanceWithLootingCondition.java.patch @@ -0,0 +1,60 @@ +--- a/net/minecraft/world/level/storage/loot/predicates/LootItemRandomChanceWithLootingCondition.java ++++ b/net/minecraft/world/level/storage/loot/predicates/LootItemRandomChanceWithLootingCondition.java +@@ -3,7 +3,6 @@ + import com.google.common.collect.ImmutableSet; + import com.mojang.serialization.Codec; + import com.mojang.serialization.codecs.RecordCodecBuilder; +-import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; + import java.util.Set; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.LivingEntity; +@@ -13,14 +12,11 @@ + import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + + public record LootItemRandomChanceWithLootingCondition(float percent, float lootingMultiplier) implements LootItemCondition { +- public static final Codec CODEC = RecordCodecBuilder.create( +- instance -> instance.group( +- Codec.FLOAT.fieldOf("chance").forGetter(LootItemRandomChanceWithLootingCondition::percent), +- Codec.FLOAT.fieldOf("looting_multiplier").forGetter(LootItemRandomChanceWithLootingCondition::lootingMultiplier) +- ) +- .apply(instance, LootItemRandomChanceWithLootingCondition::new) +- ); + ++ public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(Codec.FLOAT.fieldOf("chance").forGetter(LootItemRandomChanceWithLootingCondition::percent), Codec.FLOAT.fieldOf("looting_multiplier").forGetter(LootItemRandomChanceWithLootingCondition::lootingMultiplier)).apply(instance, LootItemRandomChanceWithLootingCondition::new); ++ }); ++ + @Override + public LootItemConditionType getType() { + return LootItemConditions.RANDOM_CHANCE_WITH_LOOTING; +@@ -31,18 +27,25 @@ + return ImmutableSet.of(LootContextParams.KILLER_ENTITY); + } + +- @Override + public boolean test(LootContext context) { +- Entity entity = context.getParamOrNull(LootContextParams.KILLER_ENTITY); ++ Entity entity = (Entity) context.getParamOrNull(LootContextParams.KILLER_ENTITY); + int i = 0; ++ + if (entity instanceof LivingEntity) { +- i = EnchantmentHelper.getMobLooting((LivingEntity)entity); ++ i = EnchantmentHelper.getMobLooting((LivingEntity) entity); + } ++ // CraftBukkit start - only use lootingModifier if set by Bukkit ++ if (context.hasParam(LootContextParams.LOOTING_MOD)) { ++ i = context.getParamOrNull(LootContextParams.LOOTING_MOD); ++ } ++ // CraftBukkit end + +- return context.getRandom().nextFloat() < this.percent + (float)i * this.lootingMultiplier; ++ return context.getRandom().nextFloat() < this.percent + (float) i * this.lootingMultiplier; + } + + public static LootItemCondition.Builder randomChanceAndLootingBoost(float chance, float lootingMultiplier) { +- return () -> new LootItemRandomChanceWithLootingCondition(chance, lootingMultiplier); ++ return () -> { ++ return new LootItemRandomChanceWithLootingCondition(chance, lootingMultiplier); ++ }; + } + } diff --git a/patch-remap/og/net/minecraft/CrashReport.patch b/patch-remap/og/net/minecraft/CrashReport.patch new file mode 100644 index 0000000000..0c5cb0b08e --- /dev/null +++ b/patch-remap/og/net/minecraft/CrashReport.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/CrashReport.java ++++ b/net/minecraft/CrashReport.java +@@ -36,6 +36,7 @@ + public CrashReport(String s, Throwable throwable) { + this.title = s; + this.exception = throwable; ++ this.systemReport.setDetail("CraftBukkit Information", new org.bukkit.craftbukkit.CraftCrashReport()); // CraftBukkit + } + + public String getTitle() { diff --git a/patch-remap/og/net/minecraft/advancements/AdvancementHolder.patch b/patch-remap/og/net/minecraft/advancements/AdvancementHolder.patch new file mode 100644 index 0000000000..211bb9e586 --- /dev/null +++ b/patch-remap/og/net/minecraft/advancements/AdvancementHolder.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/advancements/AdvancementHolder.java ++++ b/net/minecraft/advancements/AdvancementHolder.java +@@ -3,6 +3,11 @@ + import net.minecraft.network.PacketDataSerializer; + import net.minecraft.resources.MinecraftKey; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.advancement.CraftAdvancement; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++// CraftBukkit end ++ + public record AdvancementHolder(MinecraftKey id, Advancement value) { + + public void write(PacketDataSerializer packetdataserializer) { +@@ -41,4 +46,10 @@ + public String toString() { + return this.id.toString(); + } ++ ++ // CraftBukkit start ++ public final org.bukkit.advancement.Advancement toBukkit() { ++ return new CraftAdvancement(this); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/advancements/AdvancementTree.patch b/patch-remap/og/net/minecraft/advancements/AdvancementTree.patch new file mode 100644 index 0000000000..f736fbf6e4 --- /dev/null +++ b/patch-remap/og/net/minecraft/advancements/AdvancementTree.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/advancements/AdvancementTree.java ++++ b/net/minecraft/advancements/AdvancementTree.java +@@ -68,7 +68,7 @@ + } + + public void addAll(Collection collection) { +- ArrayList arraylist = new ArrayList(collection); ++ ArrayList arraylist = new ArrayList(collection); // CraftBukkit - decompile error + + while (!arraylist.isEmpty()) { + if (!arraylist.removeIf(this::tryInsert)) { +@@ -77,7 +77,7 @@ + } + } + +- AdvancementTree.LOGGER.info("Loaded {} advancements", this.nodes.size()); ++ // AdvancementTree.LOGGER.info("Loaded {} advancements", this.nodes.size()); // CraftBukkit - moved to AdvancementDataWorld#reload + } + + private boolean tryInsert(AdvancementHolder advancementholder) { diff --git a/patch-remap/og/net/minecraft/commands/CommandDispatcher.patch b/patch-remap/og/net/minecraft/commands/CommandDispatcher.patch new file mode 100644 index 0000000000..970e29b176 --- /dev/null +++ b/patch-remap/og/net/minecraft/commands/CommandDispatcher.patch @@ -0,0 +1,188 @@ +--- a/net/minecraft/commands/CommandDispatcher.java ++++ b/net/minecraft/commands/CommandDispatcher.java +@@ -134,6 +134,14 @@ + import net.minecraft.world.level.GameRules; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.google.common.base.Joiner; ++import java.util.Collection; ++import java.util.LinkedHashSet; ++import org.bukkit.event.player.PlayerCommandSendEvent; ++import org.bukkit.event.server.ServerCommandEvent; ++// CraftBukkit end ++ + public class CommandDispatcher { + + private static final ThreadLocal> CURRENT_EXECUTION_CONTEXT = new ThreadLocal(); +@@ -146,6 +154,7 @@ + private final com.mojang.brigadier.CommandDispatcher dispatcher = new com.mojang.brigadier.CommandDispatcher(); + + public CommandDispatcher(CommandDispatcher.ServerType commanddispatcher_servertype, CommandBuildContext commandbuildcontext) { ++ this(); // CraftBukkit + CommandAdvancement.register(this.dispatcher); + CommandAttribute.register(this.dispatcher, commandbuildcontext); + CommandExecute.register(this.dispatcher, commandbuildcontext); +@@ -246,6 +255,11 @@ + CommandPublish.register(this.dispatcher); + } + ++ // CraftBukkit start ++ } ++ ++ public CommandDispatcher() { ++ // CraftBukkkit end + this.dispatcher.setConsumer(ExecutionCommandSource.resultConsumer()); + } + +@@ -256,18 +270,65 @@ + return new ParseResults(commandcontextbuilder1, parseresults.getReader(), parseresults.getExceptions()); + } + ++ // CraftBukkit start ++ public void dispatchServerCommand(CommandListenerWrapper sender, String command) { ++ Joiner joiner = Joiner.on(" "); ++ if (command.startsWith("/")) { ++ command = command.substring(1); ++ } ++ ++ ServerCommandEvent event = new ServerCommandEvent(sender.getBukkitSender(), command); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ command = event.getCommand(); ++ ++ String[] args = command.split(" "); ++ ++ String cmd = args[0]; ++ if (cmd.startsWith("minecraft:")) cmd = cmd.substring("minecraft:".length()); ++ if (cmd.startsWith("bukkit:")) cmd = cmd.substring("bukkit:".length()); ++ ++ // Block disallowed commands ++ if (cmd.equalsIgnoreCase("stop") || cmd.equalsIgnoreCase("kick") || cmd.equalsIgnoreCase("op") ++ || cmd.equalsIgnoreCase("deop") || cmd.equalsIgnoreCase("ban") || cmd.equalsIgnoreCase("ban-ip") ++ || cmd.equalsIgnoreCase("pardon") || cmd.equalsIgnoreCase("pardon-ip") || cmd.equalsIgnoreCase("reload")) { ++ return; ++ } ++ ++ // Handle vanilla commands; ++ if (sender.getLevel().getCraftServer().getCommandBlockOverride(args[0])) { ++ args[0] = "minecraft:" + args[0]; ++ } ++ ++ String newCommand = joiner.join(args); ++ this.performPrefixedCommand(sender, newCommand, newCommand); ++ } ++ // CraftBukkit end ++ + public void performPrefixedCommand(CommandListenerWrapper commandlistenerwrapper, String s) { ++ // CraftBukkit start ++ this.performPrefixedCommand(commandlistenerwrapper, s, s); ++ } ++ ++ public void performPrefixedCommand(CommandListenerWrapper commandlistenerwrapper, String s, String label) { + s = s.startsWith("/") ? s.substring(1) : s; +- this.performCommand(this.dispatcher.parse(s, commandlistenerwrapper), s); ++ this.performCommand(this.dispatcher.parse(s, commandlistenerwrapper), s, label); ++ // CraftBukkit end + } + + public void performCommand(ParseResults parseresults, String s) { ++ this.performCommand(parseresults, s, s); ++ } ++ ++ public void performCommand(ParseResults parseresults, String s, String label) { // CraftBukkit + CommandListenerWrapper commandlistenerwrapper = (CommandListenerWrapper) parseresults.getContext().getSource(); + + commandlistenerwrapper.getServer().getProfiler().push(() -> { + return "/" + s; + }); +- ContextChain contextchain = finishParsing(parseresults, s, commandlistenerwrapper); ++ ContextChain contextchain = finishParsing(parseresults, s, commandlistenerwrapper, label); // CraftBukkit + + try { + if (contextchain != null) { +@@ -301,7 +362,7 @@ + } + + @Nullable +- private static ContextChain finishParsing(ParseResults parseresults, String s, CommandListenerWrapper commandlistenerwrapper) { ++ private static ContextChain finishParsing(ParseResults parseresults, String s, CommandListenerWrapper commandlistenerwrapper, String label) { // CraftBukkit + try { + validateParseResults(parseresults); + return (ContextChain) ContextChain.tryFlatten(parseresults.getContext().build(s)).orElseThrow(() -> { +@@ -312,7 +373,7 @@ + if (commandsyntaxexception.getInput() != null && commandsyntaxexception.getCursor() >= 0) { + int i = Math.min(commandsyntaxexception.getInput().length(), commandsyntaxexception.getCursor()); + IChatMutableComponent ichatmutablecomponent = IChatBaseComponent.empty().withStyle(EnumChatFormat.GRAY).withStyle((chatmodifier) -> { +- return chatmodifier.withClickEvent(new ChatClickable(ChatClickable.EnumClickAction.SUGGEST_COMMAND, "/" + s)); ++ return chatmodifier.withClickEvent(new ChatClickable(ChatClickable.EnumClickAction.SUGGEST_COMMAND, label)); // CraftBukkit + }); + + if (i > 10) { +@@ -362,7 +423,7 @@ + + executioncontext1.close(); + } finally { +- CommandDispatcher.CURRENT_EXECUTION_CONTEXT.set((Object) null); ++ CommandDispatcher.CURRENT_EXECUTION_CONTEXT.set(null); // CraftBukkit - decompile error + } + } else { + consumer.accept(executioncontext); +@@ -371,11 +432,36 @@ + } + + public void sendCommands(EntityPlayer entityplayer) { +- Map, CommandNode> map = Maps.newHashMap(); ++ // CraftBukkit start ++ // Register Vanilla commands into builtRoot as before ++ Map, CommandNode> map = Maps.newIdentityHashMap(); // Use identity to prevent aliasing issues ++ RootCommandNode vanillaRoot = new RootCommandNode(); ++ ++ RootCommandNode vanilla = entityplayer.server.vanillaCommandDispatcher.getDispatcher().getRoot(); ++ map.put(vanilla, vanillaRoot); ++ this.fillUsableCommands(vanilla, vanillaRoot, entityplayer.createCommandSourceStack(), (Map) map); ++ ++ // Now build the global commands in a second pass + RootCommandNode rootcommandnode = new RootCommandNode(); + + map.put(this.dispatcher.getRoot(), rootcommandnode); + this.fillUsableCommands(this.dispatcher.getRoot(), rootcommandnode, entityplayer.createCommandSourceStack(), map); ++ ++ Collection bukkit = new LinkedHashSet<>(); ++ for (CommandNode node : rootcommandnode.getChildren()) { ++ bukkit.add(node.getName()); ++ } ++ ++ PlayerCommandSendEvent event = new PlayerCommandSendEvent(entityplayer.getBukkitEntity(), new LinkedHashSet<>(bukkit)); ++ event.getPlayer().getServer().getPluginManager().callEvent(event); ++ ++ // Remove labels that were removed during the event ++ for (String orig : bukkit) { ++ if (!event.getCommands().contains(orig)) { ++ rootcommandnode.removeCommand(orig); ++ } ++ } ++ // CraftBukkit end + entityplayer.connection.send(new PacketPlayOutCommands(rootcommandnode)); + } + +@@ -386,7 +472,7 @@ + CommandNode commandnode2 = (CommandNode) iterator.next(); + + if (commandnode2.canUse(commandlistenerwrapper)) { +- ArgumentBuilder argumentbuilder = commandnode2.createBuilder(); ++ ArgumentBuilder argumentbuilder = commandnode2.createBuilder(); // CraftBukkit - decompile error + + argumentbuilder.requires((icompletionprovider) -> { + return true; +@@ -409,7 +495,7 @@ + argumentbuilder.redirect((CommandNode) map.get(argumentbuilder.getRedirect())); + } + +- CommandNode commandnode3 = argumentbuilder.build(); ++ CommandNode commandnode3 = argumentbuilder.build(); // CraftBukkit - decompile error + + map.put(commandnode2, commandnode3); + commandnode1.addChild(commandnode3); diff --git a/patch-remap/og/net/minecraft/commands/CommandListenerWrapper.patch b/patch-remap/og/net/minecraft/commands/CommandListenerWrapper.patch new file mode 100644 index 0000000000..6b05786842 --- /dev/null +++ b/patch-remap/og/net/minecraft/commands/CommandListenerWrapper.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/commands/CommandListenerWrapper.java ++++ b/net/minecraft/commands/CommandListenerWrapper.java +@@ -44,6 +44,8 @@ + import net.minecraft.world.phys.Vec2F; + import net.minecraft.world.phys.Vec3D; + ++import com.mojang.brigadier.tree.CommandNode; // CraftBukkit ++ + public class CommandListenerWrapper implements ExecutionCommandSource, ICompletionProvider { + + public static final SimpleCommandExceptionType ERROR_NOT_PLAYER = new SimpleCommandExceptionType(IChatBaseComponent.translatable("permissions.requires.player")); +@@ -63,6 +65,7 @@ + private final Vec2F rotation; + private final CommandSigningContext signingContext; + private final TaskChainer chatMessageChainer; ++ public volatile CommandNode currentCommand; // CraftBukkit + + public CommandListenerWrapper(ICommandListener icommandlistener, Vec3D vec3d, Vec2F vec2f, WorldServer worldserver, int i, String s, IChatBaseComponent ichatbasecomponent, MinecraftServer minecraftserver, @Nullable Entity entity) { + this(icommandlistener, vec3d, vec2f, worldserver, i, s, ichatbasecomponent, minecraftserver, entity, false, CommandResultCallback.EMPTY, ArgumentAnchor.Anchor.FEET, CommandSigningContext.ANONYMOUS, TaskChainer.immediate(minecraftserver)); +@@ -169,9 +172,23 @@ + + @Override + public boolean hasPermission(int i) { ++ // CraftBukkit start ++ CommandNode currentCommand = this.currentCommand; ++ if (currentCommand != null) { ++ return hasPermission(i, org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(currentCommand)); ++ } ++ // CraftBukkit end ++ + return this.permissionLevel >= i; + } + ++ // CraftBukkit start ++ public boolean hasPermission(int i, String bukkitPermission) { ++ // World is null when loading functions ++ return ((getLevel() == null || !getLevel().getCraftServer().ignoreVanillaPermissions) && this.permissionLevel >= i) || getBukkitSender().hasPermission(bukkitPermission); ++ } ++ // CraftBukkit end ++ + public Vec3D getPosition() { + return this.worldPosition; + } +@@ -304,7 +321,7 @@ + while (iterator.hasNext()) { + EntityPlayer entityplayer = (EntityPlayer) iterator.next(); + +- if (entityplayer != this.source && this.server.getPlayerList().isOp(entityplayer.getGameProfile())) { ++ if (entityplayer != this.source && entityplayer.getBukkitEntity().hasPermission("minecraft.admin.command_feedback")) { // CraftBukkit + entityplayer.sendSystemMessage(ichatmutablecomponent); + } + } +@@ -397,4 +414,10 @@ + public boolean isSilent() { + return this.silent; + } ++ ++ // CraftBukkit start ++ public org.bukkit.command.CommandSender getBukkitSender() { ++ return source.getBukkitSender(this); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/commands/ICommandListener.patch b/patch-remap/og/net/minecraft/commands/ICommandListener.patch new file mode 100644 index 0000000000..df9bb2402c --- /dev/null +++ b/patch-remap/og/net/minecraft/commands/ICommandListener.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/commands/ICommandListener.java ++++ b/net/minecraft/commands/ICommandListener.java +@@ -22,6 +22,13 @@ + public boolean shouldInformAdmins() { + return false; + } ++ ++ // CraftBukkit start ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandListenerWrapper wrapper) { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ // CraftBukkit end + }; + + void sendSystemMessage(IChatBaseComponent ichatbasecomponent); +@@ -35,4 +42,6 @@ + default boolean alwaysAccepts() { + return false; + } ++ ++ org.bukkit.command.CommandSender getBukkitSender(CommandListenerWrapper wrapper); // CraftBukkit + } diff --git a/patch-remap/og/net/minecraft/commands/arguments/ArgumentEntity.patch b/patch-remap/og/net/minecraft/commands/arguments/ArgumentEntity.patch new file mode 100644 index 0000000000..fe7d5cb425 --- /dev/null +++ b/patch-remap/og/net/minecraft/commands/arguments/ArgumentEntity.patch @@ -0,0 +1,19 @@ +--- a/net/minecraft/commands/arguments/ArgumentEntity.java ++++ b/net/minecraft/commands/arguments/ArgumentEntity.java +@@ -94,9 +94,15 @@ + } + + public EntitySelector parse(StringReader stringreader) throws CommandSyntaxException { ++ // CraftBukkit start ++ return parse(stringreader, false); ++ } ++ ++ public EntitySelector parse(StringReader stringreader, boolean overridePermissions) throws CommandSyntaxException { ++ // CraftBukkit end + boolean flag = false; + ArgumentParserSelector argumentparserselector = new ArgumentParserSelector(stringreader); +- EntitySelector entityselector = argumentparserselector.parse(); ++ EntitySelector entityselector = argumentparserselector.parse(overridePermissions); // CraftBukkit + + if (entityselector.getMaxResults() > 1 && this.single) { + if (this.playersOnly) { diff --git a/patch-remap/og/net/minecraft/commands/arguments/blocks/ArgumentBlock.patch b/patch-remap/og/net/minecraft/commands/arguments/blocks/ArgumentBlock.patch new file mode 100644 index 0000000000..6d86c0ea37 --- /dev/null +++ b/patch-remap/og/net/minecraft/commands/arguments/blocks/ArgumentBlock.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/commands/arguments/blocks/ArgumentBlock.java ++++ b/net/minecraft/commands/arguments/blocks/ArgumentBlock.java +@@ -68,7 +68,7 @@ + private final StringReader reader; + private final boolean forTesting; + private final boolean allowNbt; +- private final Map, Comparable> properties = Maps.newHashMap(); ++ private final Map, Comparable> properties = Maps.newLinkedHashMap(); // CraftBukkit - stable + private final Map vagueProperties = Maps.newHashMap(); + private MinecraftKey id = new MinecraftKey(""); + @Nullable +@@ -276,7 +276,7 @@ + Iterator iterator = iblockstate.getPossibleValues().iterator(); + + while (iterator.hasNext()) { +- T t0 = (Comparable) iterator.next(); ++ T t0 = (T) iterator.next(); // CraftBukkit - decompile error + + if (t0 instanceof Integer) { + Integer integer = (Integer) t0; +@@ -548,7 +548,7 @@ + Optional optional = iblockstate.getValue(s); + + if (optional.isPresent()) { +- this.state = (IBlockData) this.state.setValue(iblockstate, (Comparable) optional.get()); ++ this.state = (IBlockData) this.state.setValue(iblockstate, (T) optional.get()); // CraftBukkit - decompile error + this.properties.put(iblockstate, (Comparable) optional.get()); + } else { + this.reader.setCursor(i); +@@ -584,7 +584,7 @@ + private static > void appendProperty(StringBuilder stringbuilder, IBlockState iblockstate, Comparable comparable) { + stringbuilder.append(iblockstate.getName()); + stringbuilder.append('='); +- stringbuilder.append(iblockstate.getName(comparable)); ++ stringbuilder.append(iblockstate.getName((T) comparable)); // CraftBukkit - decompile error + } + + public static record a(IBlockData blockState, Map, Comparable> properties, @Nullable NBTTagCompound nbt) { diff --git a/patch-remap/og/net/minecraft/commands/arguments/selector/ArgumentParserSelector.patch b/patch-remap/og/net/minecraft/commands/arguments/selector/ArgumentParserSelector.patch new file mode 100644 index 0000000000..73ff62a169 --- /dev/null +++ b/patch-remap/og/net/minecraft/commands/arguments/selector/ArgumentParserSelector.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/commands/arguments/selector/ArgumentParserSelector.java ++++ b/net/minecraft/commands/arguments/selector/ArgumentParserSelector.java +@@ -147,7 +147,7 @@ + axisalignedbb = this.createAabb(this.deltaX == null ? 0.0D : this.deltaX, this.deltaY == null ? 0.0D : this.deltaY, this.deltaZ == null ? 0.0D : this.deltaZ); + } + +- Function function; ++ Function function; // CraftBukkit - decompile error + + if (this.x == null && this.y == null && this.z == null) { + function = (vec3d) -> { +@@ -204,8 +204,10 @@ + }; + } + +- protected void parseSelector() throws CommandSyntaxException { +- this.usesSelectors = true; ++ // CraftBukkit start ++ protected void parseSelector(boolean overridePermissions) throws CommandSyntaxException { ++ this.usesSelectors = !overridePermissions; ++ // CraftBukkit end + this.suggestions = this::suggestSelector; + if (!this.reader.canRead()) { + throw ArgumentParserSelector.ERROR_MISSING_SELECTOR_TYPE.createWithContext(this.reader); +@@ -463,6 +465,12 @@ + } + + public EntitySelector parse() throws CommandSyntaxException { ++ // CraftBukkit start ++ return parse(false); ++ } ++ ++ public EntitySelector parse(boolean overridePermissions) throws CommandSyntaxException { ++ // CraftBukkit end + this.startPosition = this.reader.getCursor(); + this.suggestions = this::suggestNameOrSelector; + if (this.reader.canRead() && this.reader.peek() == '@') { +@@ -471,7 +479,7 @@ + } + + this.reader.skip(); +- this.parseSelector(); ++ this.parseSelector(overridePermissions); // CraftBukkit + } else { + this.parseNameOrUUID(); + } diff --git a/patch-remap/og/net/minecraft/commands/arguments/selector/EntitySelector.patch b/patch-remap/og/net/minecraft/commands/arguments/selector/EntitySelector.patch new file mode 100644 index 0000000000..e4633ef40e --- /dev/null +++ b/patch-remap/og/net/minecraft/commands/arguments/selector/EntitySelector.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/commands/arguments/selector/EntitySelector.java ++++ b/net/minecraft/commands/arguments/selector/EntitySelector.java +@@ -92,7 +92,7 @@ + } + + private void checkPermissions(CommandListenerWrapper commandlistenerwrapper) throws CommandSyntaxException { +- if (this.usesSelector && !commandlistenerwrapper.hasPermission(2)) { ++ if (this.usesSelector && !commandlistenerwrapper.hasPermission(2, "minecraft.command.selector")) { // CraftBukkit + throw ArgumentEntity.ERROR_SELECTORS_NOT_ALLOWED.create(); + } + } diff --git a/patch-remap/og/net/minecraft/core/cauldron/CauldronInteraction.patch b/patch-remap/og/net/minecraft/core/cauldron/CauldronInteraction.patch new file mode 100644 index 0000000000..bf21acdd23 --- /dev/null +++ b/patch-remap/og/net/minecraft/core/cauldron/CauldronInteraction.patch @@ -0,0 +1,235 @@ +--- a/net/minecraft/core/cauldron/CauldronInteraction.java ++++ b/net/minecraft/core/cauldron/CauldronInteraction.java +@@ -33,9 +33,15 @@ + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.event.block.CauldronLevelChangeEvent; ++// CraftBukkit end ++ + public interface CauldronInteraction { + + Map INTERACTIONS = new Object2ObjectArrayMap(); ++ // CraftBukkit start - decompile error ++ /* + Codec CODEC; + CauldronInteraction.a EMPTY; + CauldronInteraction.a WATER; +@@ -47,6 +53,8 @@ + CauldronInteraction SHULKER_BOX; + CauldronInteraction BANNER; + CauldronInteraction DYED_ITEM; ++ */ ++ // CraftBukkit end + + static CauldronInteraction.a newInteractionMap(String s) { + Object2ObjectOpenHashMap object2objectopenhashmap = new Object2ObjectOpenHashMap(); +@@ -71,12 +79,17 @@ + return EnumInteractionResult.PASS; + } else { + if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.changeLevel(iblockdata, world, blockposition, Blocks.WATER_CAULDRON.defaultBlockState(), entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_EMPTY)) { ++ return EnumInteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + Item item = itemstack.getItem(); + + entityhuman.setItemInHand(enumhand, ItemLiquidUtil.createFilledResult(itemstack, entityhuman, new ItemStack(Items.GLASS_BOTTLE))); + entityhuman.awardStat(StatisticList.USE_CAULDRON); + entityhuman.awardStat(StatisticList.ITEM_USED.get(item)); +- world.setBlockAndUpdate(blockposition, Blocks.WATER_CAULDRON.defaultBlockState()); ++ // world.setBlockAndUpdate(blockposition, Blocks.WATER_CAULDRON.defaultBlockState()); // CraftBukkit + world.playSound((EntityHuman) null, blockposition, SoundEffects.BOTTLE_EMPTY, SoundCategory.BLOCKS, 1.0F, 1.0F); + world.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockposition); + } +@@ -94,12 +107,17 @@ + }); + map1.put(Items.GLASS_BOTTLE, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { + if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_FILL)) { ++ return EnumInteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + Item item = itemstack.getItem(); + + entityhuman.setItemInHand(enumhand, ItemLiquidUtil.createFilledResult(itemstack, entityhuman, PotionUtil.setPotion(new ItemStack(Items.POTION), Potions.WATER))); + entityhuman.awardStat(StatisticList.USE_CAULDRON); + entityhuman.awardStat(StatisticList.ITEM_USED.get(item)); +- LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); ++ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit + world.playSound((EntityHuman) null, blockposition, SoundEffects.BOTTLE_FILL, SoundCategory.BLOCKS, 1.0F, 1.0F); + world.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockposition); + } +@@ -109,10 +127,15 @@ + map1.put(Items.POTION, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { + if ((Integer) iblockdata.getValue(LayeredCauldronBlock.LEVEL) != 3 && PotionUtil.getPotion(itemstack) == Potions.WATER) { + if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.changeLevel(iblockdata, world, blockposition, iblockdata.cycle(LayeredCauldronBlock.LEVEL), entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_EMPTY)) { ++ return EnumInteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + entityhuman.setItemInHand(enumhand, ItemLiquidUtil.createFilledResult(itemstack, entityhuman, new ItemStack(Items.GLASS_BOTTLE))); + entityhuman.awardStat(StatisticList.USE_CAULDRON); + entityhuman.awardStat(StatisticList.ITEM_USED.get(itemstack.getItem())); +- world.setBlockAndUpdate(blockposition, (IBlockData) iblockdata.cycle(LayeredCauldronBlock.LEVEL)); ++ // world.setBlockAndUpdate(blockposition, (IBlockData) iblockdata.cycle(LayeredCauldronBlock.LEVEL)); // CraftBukkit + world.playSound((EntityHuman) null, blockposition, SoundEffects.BOTTLE_EMPTY, SoundCategory.BLOCKS, 1.0F, 1.0F); + world.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockposition); + } +@@ -188,12 +211,17 @@ + return EnumInteractionResult.PASS; + } else { + if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.changeLevel(iblockdata, world, blockposition, Blocks.CAULDRON.defaultBlockState(), entityhuman, CauldronLevelChangeEvent.ChangeReason.BUCKET_FILL)) { ++ return EnumInteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + Item item = itemstack.getItem(); + + entityhuman.setItemInHand(enumhand, ItemLiquidUtil.createFilledResult(itemstack, entityhuman, itemstack1)); + entityhuman.awardStat(StatisticList.USE_CAULDRON); + entityhuman.awardStat(StatisticList.ITEM_USED.get(item)); +- world.setBlockAndUpdate(blockposition, Blocks.CAULDRON.defaultBlockState()); ++ // world.setBlockAndUpdate(blockposition, Blocks.CAULDRON.defaultBlockState()); // CraftBukkit + world.playSound((EntityHuman) null, blockposition, soundeffect, SoundCategory.BLOCKS, 1.0F, 1.0F); + world.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockposition); + } +@@ -204,12 +232,17 @@ + + static EnumInteractionResult emptyBucket(World world, BlockPosition blockposition, EntityHuman entityhuman, EnumHand enumhand, ItemStack itemstack, IBlockData iblockdata, SoundEffect soundeffect) { + if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.changeLevel(iblockdata, world, blockposition, iblockdata, entityhuman, CauldronLevelChangeEvent.ChangeReason.BUCKET_EMPTY)) { ++ return EnumInteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + Item item = itemstack.getItem(); + + entityhuman.setItemInHand(enumhand, ItemLiquidUtil.createFilledResult(itemstack, entityhuman, new ItemStack(Items.BUCKET))); + entityhuman.awardStat(StatisticList.FILL_CAULDRON); + entityhuman.awardStat(StatisticList.ITEM_USED.get(item)); +- world.setBlockAndUpdate(blockposition, iblockdata); ++ // world.setBlockAndUpdate(blockposition, iblockdata); // CraftBukkit + world.playSound((EntityHuman) null, blockposition, soundeffect, SoundCategory.BLOCKS, 1.0F, 1.0F); + world.gameEvent((Entity) null, GameEvent.FLUID_PLACE, blockposition); + } +@@ -217,32 +250,35 @@ + return EnumInteractionResult.sidedSuccess(world.isClientSide); + } + +- static { +- Function function = CauldronInteraction.a::name; +- Map map = CauldronInteraction.INTERACTIONS; +- +- Objects.requireNonNull(map); +- CODEC = ExtraCodecs.stringResolverCodec(function, map::get); +- EMPTY = newInteractionMap("empty"); +- WATER = newInteractionMap("water"); +- LAVA = newInteractionMap("lava"); +- POWDER_SNOW = newInteractionMap("powder_snow"); +- FILL_WATER = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ // CraftBukkit start - decompile errors ++ // static { ++ Codec CODEC = ExtraCodecs.stringResolverCodec(CauldronInteraction.a::name, CauldronInteraction.INTERACTIONS::get); ++ CauldronInteraction.a EMPTY = newInteractionMap("empty"); ++ CauldronInteraction.a WATER = newInteractionMap("water"); ++ CauldronInteraction.a LAVA = newInteractionMap("lava"); ++ CauldronInteraction.a POWDER_SNOW = newInteractionMap("powder_snow"); ++ CauldronInteraction FILL_WATER = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { + return emptyBucket(world, blockposition, entityhuman, enumhand, itemstack, (IBlockData) Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEffects.BUCKET_EMPTY); + }; +- FILL_LAVA = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ CauldronInteraction FILL_LAVA = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { + return emptyBucket(world, blockposition, entityhuman, enumhand, itemstack, Blocks.LAVA_CAULDRON.defaultBlockState(), SoundEffects.BUCKET_EMPTY_LAVA); + }; +- FILL_POWDER_SNOW = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ CauldronInteraction FILL_POWDER_SNOW = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { + return emptyBucket(world, blockposition, entityhuman, enumhand, itemstack, (IBlockData) Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEffects.BUCKET_EMPTY_POWDER_SNOW); + }; +- SHULKER_BOX = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ CauldronInteraction SHULKER_BOX = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ // CraftBukkit end + Block block = Block.byItem(itemstack.getItem()); + + if (!(block instanceof BlockShulkerBox)) { + return EnumInteractionResult.PASS; + } else { + if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.SHULKER_WASH)) { ++ return EnumInteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + ItemStack itemstack1 = new ItemStack(Blocks.SHULKER_BOX); + + if (itemstack.hasTag()) { +@@ -251,17 +287,22 @@ + + entityhuman.setItemInHand(enumhand, itemstack1); + entityhuman.awardStat(StatisticList.CLEAN_SHULKER_BOX); +- LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); ++ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit + } + + return EnumInteractionResult.sidedSuccess(world.isClientSide); + } + }; +- BANNER = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ CauldronInteraction BANNER = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { // CraftBukkit - decompile error + if (TileEntityBanner.getPatternCount(itemstack) <= 0) { + return EnumInteractionResult.PASS; + } else { + if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.BANNER_WASH)) { ++ return EnumInteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + ItemStack itemstack1 = itemstack.copyWithCount(1); + + TileEntityBanner.removeLastPattern(itemstack1); +@@ -278,13 +319,13 @@ + } + + entityhuman.awardStat(StatisticList.CLEAN_BANNER); +- LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); ++ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit + } + + return EnumInteractionResult.sidedSuccess(world.isClientSide); + } + }; +- DYED_ITEM = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { ++ CauldronInteraction DYED_ITEM = (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> { // CraftBukkit - decompile error + Item item = itemstack.getItem(); + + if (!(item instanceof IDyeable)) { +@@ -296,16 +337,21 @@ + return EnumInteractionResult.PASS; + } else { + if (!world.isClientSide) { ++ // CraftBukkit start ++ if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.ARMOR_WASH)) { ++ return EnumInteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + idyeable.clearColor(itemstack); + entityhuman.awardStat(StatisticList.CLEAN_ARMOR); +- LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); ++ // LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit + } + + return EnumInteractionResult.sidedSuccess(world.isClientSide); + } + } + }; +- } ++ // } // CraftBukkit - decompile error + + public static record a(String name, Map map) { + diff --git a/patch-remap/og/net/minecraft/core/dispenser/DispenseBehaviorBoat.patch b/patch-remap/og/net/minecraft/core/dispenser/DispenseBehaviorBoat.patch new file mode 100644 index 0000000000..e0360bdb4f --- /dev/null +++ b/patch-remap/og/net/minecraft/core/dispenser/DispenseBehaviorBoat.patch @@ -0,0 +1,60 @@ +--- a/net/minecraft/core/dispenser/DispenseBehaviorBoat.java ++++ b/net/minecraft/core/dispenser/DispenseBehaviorBoat.java +@@ -13,6 +13,12 @@ + import net.minecraft.world.level.block.BlockDispenser; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end ++ + public class DispenseBehaviorBoat extends DispenseBehaviorItem { + + private final DispenseBehaviorItem defaultDispenseItemBehavior; +@@ -51,13 +57,41 @@ + d4 = 0.0D; + } + +- Object object = this.isChestBoat ? new ChestBoat(worldserver, d1, d2 + d4, d3) : new EntityBoat(worldserver, d1, d2 + d4, d3); ++ // Object object = this.isChestBoat ? new ChestBoat(worldserver, d1, d2 + d4, d3) : new EntityBoat(worldserver, d1, d2 + d4, d3); ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d1, d2 + d4, d3)); ++ if (!BlockDispenser.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ EntityBoat object = this.isChestBoat ? new ChestBoat(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ()) : new EntityBoat(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ()); ++ // CraftBukkit end + + EntityTypes.createDefaultStackConfig(worldserver, itemstack, (EntityHuman) null).accept(object); + ((EntityBoat) object).setVariant(this.type); + ((EntityBoat) object).setYRot(enumdirection.toYRot()); +- worldserver.addFreshEntity((Entity) object); +- itemstack.shrink(1); ++ if (!worldserver.addFreshEntity((Entity) object)) itemstack.grow(1); // CraftBukkit ++ // itemstack.shrink(1); // CraftBukkit - handled during event processing + return itemstack; + } + diff --git a/patch-remap/og/net/minecraft/core/dispenser/DispenseBehaviorItem.patch b/patch-remap/og/net/minecraft/core/dispenser/DispenseBehaviorItem.patch new file mode 100644 index 0000000000..35ba36195a --- /dev/null +++ b/patch-remap/og/net/minecraft/core/dispenser/DispenseBehaviorItem.patch @@ -0,0 +1,98 @@ +--- a/net/minecraft/core/dispenser/DispenseBehaviorItem.java ++++ b/net/minecraft/core/dispenser/DispenseBehaviorItem.java +@@ -7,8 +7,23 @@ + import net.minecraft.world.level.World; + import net.minecraft.world.level.block.BlockDispenser; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftVector; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end ++ + public class DispenseBehaviorItem implements IDispenseBehavior { + ++ // CraftBukkit start ++ private boolean dropper; ++ ++ public DispenseBehaviorItem(boolean dropper) { ++ this.dropper = dropper; ++ } ++ // CraftBukkit end ++ + public DispenseBehaviorItem() {} + + @Override +@@ -25,11 +40,22 @@ + IPosition iposition = BlockDispenser.getDispensePosition(sourceblock); + ItemStack itemstack1 = itemstack.split(1); + +- spawnItem(sourceblock.level(), itemstack1, 6, enumdirection, iposition); ++ // CraftBukkit start ++ if (!spawnItem(sourceblock.level(), itemstack1, 6, enumdirection, sourceblock, dropper)) { ++ itemstack.grow(1); ++ } ++ // CraftBukkit end + return itemstack; + } + + public static void spawnItem(World world, ItemStack itemstack, int i, EnumDirection enumdirection, IPosition iposition) { ++ // CraftBukkit start ++ EntityItem entityitem = prepareItem(world, itemstack, i, enumdirection, iposition); ++ world.addFreshEntity(entityitem); ++ } ++ ++ private static EntityItem prepareItem(World world, ItemStack itemstack, int i, EnumDirection enumdirection, IPosition iposition) { ++ // CraftBukkit end + double d0 = iposition.x(); + double d1 = iposition.y(); + double d2 = iposition.z(); +@@ -44,7 +70,47 @@ + double d3 = world.random.nextDouble() * 0.1D + 0.2D; + + entityitem.setDeltaMovement(world.random.triangle((double) enumdirection.getStepX() * d3, 0.0172275D * (double) i), world.random.triangle(0.2D, 0.0172275D * (double) i), world.random.triangle((double) enumdirection.getStepZ() * d3, 0.0172275D * (double) i)); ++ // CraftBukkit start ++ return entityitem; ++ } ++ ++ // CraftBukkit - void -> boolean return, IPosition -> ISourceBlock last argument, dropper ++ public static boolean spawnItem(World world, ItemStack itemstack, int i, EnumDirection enumdirection, SourceBlock sourceblock, boolean dropper) { ++ if (itemstack.isEmpty()) return true; ++ IPosition iposition = BlockDispenser.getDispensePosition(sourceblock); ++ EntityItem entityitem = prepareItem(world, itemstack, i, enumdirection, iposition); ++ ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), CraftVector.toBukkit(entityitem.getDeltaMovement())); ++ if (!BlockDispenser.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ entityitem.setItem(CraftItemStack.asNMSCopy(event.getItem())); ++ entityitem.setDeltaMovement(CraftVector.toNMS(event.getVelocity())); ++ ++ if (!dropper && !event.getItem().getType().equals(craftItem.getType())) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior.getClass() != DispenseBehaviorItem.class) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ } else { ++ world.addFreshEntity(entityitem); ++ } ++ return false; ++ } ++ + world.addFreshEntity(entityitem); ++ ++ return true; ++ // CraftBukkit end + } + + protected void playSound(SourceBlock sourceblock) { diff --git a/patch-remap/og/net/minecraft/core/dispenser/DispenseBehaviorProjectile.patch b/patch-remap/og/net/minecraft/core/dispenser/DispenseBehaviorProjectile.patch new file mode 100644 index 0000000000..df420f085a --- /dev/null +++ b/patch-remap/og/net/minecraft/core/dispenser/DispenseBehaviorProjectile.patch @@ -0,0 +1,57 @@ +--- a/net/minecraft/core/dispenser/DispenseBehaviorProjectile.java ++++ b/net/minecraft/core/dispenser/DispenseBehaviorProjectile.java +@@ -8,6 +8,13 @@ + import net.minecraft.world.level.World; + import net.minecraft.world.level.block.BlockDispenser; + ++// CraftBukkit start ++import net.minecraft.world.entity.Entity; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end ++ + public abstract class DispenseBehaviorProjectile extends DispenseBehaviorItem { + + public DispenseBehaviorProjectile() {} +@@ -19,9 +26,38 @@ + EnumDirection enumdirection = (EnumDirection) sourceblock.state().getValue(BlockDispenser.FACING); + IProjectile iprojectile = this.getProjectile(worldserver, iposition, itemstack); + +- iprojectile.shoot((double) enumdirection.getStepX(), (double) ((float) enumdirection.getStepY() + 0.1F), (double) enumdirection.getStepZ(), this.getPower(), this.getUncertainty()); ++ // CraftBukkit start ++ // iprojectile.shoot((double) enumdirection.getStepX(), (double) ((float) enumdirection.getStepY() + 0.1F), (double) enumdirection.getStepZ(), this.getPower(), this.getUncertainty()); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) enumdirection.getStepX(), (double) ((float) enumdirection.getStepY() + 0.1F), (double) enumdirection.getStepZ())); ++ if (!BlockDispenser.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ iprojectile.shoot(event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), this.getPower(), this.getUncertainty()); ++ ((Entity) iprojectile).projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(sourceblock.blockEntity()); ++ // CraftBukkit end + worldserver.addFreshEntity(iprojectile); +- itemstack.shrink(1); ++ // itemstack.shrink(1); // CraftBukkit - Handled during event processing + return itemstack; + } + diff --git a/patch-remap/og/net/minecraft/core/dispenser/DispenseBehaviorShears.patch b/patch-remap/og/net/minecraft/core/dispenser/DispenseBehaviorShears.patch new file mode 100644 index 0000000000..7db9555285 --- /dev/null +++ b/patch-remap/og/net/minecraft/core/dispenser/DispenseBehaviorShears.patch @@ -0,0 +1,73 @@ +--- a/net/minecraft/core/dispenser/DispenseBehaviorShears.java ++++ b/net/minecraft/core/dispenser/DispenseBehaviorShears.java +@@ -22,6 +22,13 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AxisAlignedBB; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end ++ + public class DispenseBehaviorShears extends DispenseBehaviorMaybe { + + public DispenseBehaviorShears() {} +@@ -29,11 +36,34 @@ + @Override + protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { + WorldServer worldserver = sourceblock.level(); ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!BlockDispenser.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end + + if (!worldserver.isClientSide()) { + BlockPosition blockposition = sourceblock.pos().relative((EnumDirection) sourceblock.state().getValue(BlockDispenser.FACING)); + +- this.setSuccess(tryShearBeehive(worldserver, blockposition) || tryShearLivingEntity(worldserver, blockposition)); ++ this.setSuccess(tryShearBeehive(worldserver, blockposition) || tryShearLivingEntity(worldserver, blockposition, bukkitBlock, craftItem)); // CraftBukkit + if (this.isSuccess() && itemstack.hurt(1, worldserver.getRandom(), (EntityPlayer) null)) { + itemstack.setCount(0); + } +@@ -62,7 +92,7 @@ + return false; + } + +- private static boolean tryShearLivingEntity(WorldServer worldserver, BlockPosition blockposition) { ++ private static boolean tryShearLivingEntity(WorldServer worldserver, BlockPosition blockposition, org.bukkit.block.Block bukkitBlock, CraftItemStack craftItem) { // CraftBukkit - add args + List list = worldserver.getEntitiesOfClass(EntityLiving.class, new AxisAlignedBB(blockposition), IEntitySelector.NO_SPECTATORS); + Iterator iterator = list.iterator(); + +@@ -73,6 +103,11 @@ + IShearable ishearable = (IShearable) entityliving; + + if (ishearable.readyForShearing()) { ++ // CraftBukkit start ++ if (CraftEventFactory.callBlockShearEntityEvent(entityliving, bukkitBlock, craftItem).isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end + ishearable.shear(SoundCategory.BLOCKS); + worldserver.gameEvent((Entity) null, GameEvent.SHEAR, blockposition); + return true; diff --git a/patch-remap/og/net/minecraft/core/dispenser/DispenseBehaviorShulkerBox.patch b/patch-remap/og/net/minecraft/core/dispenser/DispenseBehaviorShulkerBox.patch new file mode 100644 index 0000000000..4c4b20013c --- /dev/null +++ b/patch-remap/og/net/minecraft/core/dispenser/DispenseBehaviorShulkerBox.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/core/dispenser/DispenseBehaviorShulkerBox.java ++++ b/net/minecraft/core/dispenser/DispenseBehaviorShulkerBox.java +@@ -10,6 +10,12 @@ + import net.minecraft.world.level.block.BlockDispenser; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end ++ + public class DispenseBehaviorShulkerBox extends DispenseBehaviorMaybe { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -26,6 +32,30 @@ + BlockPosition blockposition = sourceblock.pos().relative(enumdirection); + EnumDirection enumdirection1 = sourceblock.level().isEmptyBlock(blockposition.below()) ? enumdirection : EnumDirection.UP; + ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(sourceblock.level(), sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!BlockDispenser.eventFired) { ++ sourceblock.level().getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ + try { + this.setSuccess(((ItemBlock) item).place(new BlockActionContextDirectional(sourceblock.level(), blockposition, enumdirection, itemstack, enumdirection1)).consumesAction()); + } catch (Exception exception) { diff --git a/patch-remap/og/net/minecraft/core/dispenser/IDispenseBehavior.patch b/patch-remap/og/net/minecraft/core/dispenser/IDispenseBehavior.patch new file mode 100644 index 0000000000..4a9d4f7e2e --- /dev/null +++ b/patch-remap/og/net/minecraft/core/dispenser/IDispenseBehavior.patch @@ -0,0 +1,657 @@ +--- a/net/minecraft/core/dispenser/IDispenseBehavior.java ++++ b/net/minecraft/core/dispenser/IDispenseBehavior.java +@@ -77,6 +77,22 @@ + import net.minecraft.world.phys.Vec3D; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.world.item.ItemBucket; ++import net.minecraft.world.level.block.BlockSapling; ++import net.minecraft.world.level.block.IFluidContainer; ++import org.bukkit.Location; ++import org.bukkit.TreeType; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.craftbukkit.util.DummyGeneratorAccess; ++import org.bukkit.event.block.BlockDispenseArmorEvent; ++import org.bukkit.event.block.BlockDispenseEvent; ++import org.bukkit.event.block.BlockFertilizeEvent; ++import org.bukkit.event.world.StructureGrowEvent; ++// CraftBukkit end ++ + public interface IDispenseBehavior { + + Logger LOGGER = LogUtils.getLogger(); +@@ -201,14 +217,42 @@ + EnumDirection enumdirection = (EnumDirection) sourceblock.state().getValue(BlockDispenser.FACING); + EntityTypes entitytypes = ((ItemMonsterEgg) itemstack.getItem()).getType(itemstack.getTag()); + ++ // CraftBukkit start ++ WorldServer worldserver = sourceblock.level(); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!BlockDispenser.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ + try { + entitytypes.spawn(sourceblock.level(), itemstack, (EntityHuman) null, sourceblock.pos().relative(enumdirection), EnumMobSpawn.DISPENSER, enumdirection != EnumDirection.UP, false); + } catch (Exception exception) { +- null.LOGGER.error("Error while dispensing spawn egg from dispenser at {}", sourceblock.pos(), exception); ++ LOGGER.error("Error while dispensing spawn egg from dispenser at {}", sourceblock.pos(), exception); // CraftBukkit - decompile error + return ItemStack.EMPTY; + } + +- itemstack.shrink(1); ++ // itemstack.shrink(1); // Handled during event processing ++ // CraftBukkit end + sourceblock.level().gameEvent((Entity) null, GameEvent.ENTITY_PLACE, sourceblock.pos()); + return itemstack; + } +@@ -227,13 +271,41 @@ + EnumDirection enumdirection = (EnumDirection) sourceblock.state().getValue(BlockDispenser.FACING); + BlockPosition blockposition = sourceblock.pos().relative(enumdirection); + WorldServer worldserver = sourceblock.level(); ++ ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!BlockDispenser.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ + Consumer consumer = EntityTypes.appendDefaultStackConfig((entityarmorstand) -> { + entityarmorstand.setYRot(enumdirection.toYRot()); + }, worldserver, itemstack, (EntityHuman) null); + EntityArmorStand entityarmorstand = (EntityArmorStand) EntityTypes.ARMOR_STAND.spawn(worldserver, itemstack.getTag(), consumer, blockposition, EnumMobSpawn.DISPENSER, false, false); + + if (entityarmorstand != null) { +- itemstack.shrink(1); ++ // itemstack.shrink(1); // CraftBukkit - Handled during event processing + } + + return itemstack; +@@ -254,8 +326,35 @@ + }); + + if (!list.isEmpty()) { ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ World world = sourceblock.level(); ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) list.get(0).getBukkitEntity()); ++ if (!BlockDispenser.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != ItemArmor.DISPENSE_ITEM_BEHAVIOR) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end + ((ISaddleable) list.get(0)).equipSaddle(SoundCategory.BLOCKS); +- itemstack.shrink(1); ++ // itemstack.shrink(1); // CraftBukkit - handled above + this.setSuccess(true); + return itemstack; + } else { +@@ -282,7 +381,35 @@ + entityhorseabstract = (EntityHorseAbstract) iterator1.next(); + } while (!entityhorseabstract.isArmor(itemstack) || entityhorseabstract.isWearingArmor() || !entityhorseabstract.isTamed()); + +- entityhorseabstract.getSlot(401).set(itemstack.split(1)); ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ World world = sourceblock.level(); ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityhorseabstract.getBukkitEntity()); ++ if (!BlockDispenser.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != ItemArmor.DISPENSE_ITEM_BEHAVIOR) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ entityhorseabstract.getSlot(401).set(CraftItemStack.asNMSCopy(event.getItem())); ++ // CraftBukkit end + this.setSuccess(true); + return itemstack; + } +@@ -325,9 +452,35 @@ + } + + entityhorsechestedabstract = (EntityHorseChestedAbstract) iterator1.next(); +- } while (!entityhorsechestedabstract.isTamed() || !entityhorsechestedabstract.getSlot(499).set(itemstack)); ++ // CraftBukkit start ++ } while (!entityhorsechestedabstract.isTamed()); ++ ItemStack itemstack1 = itemstack.split(1); ++ World world = sourceblock.level(); ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + +- itemstack.shrink(1); ++ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityhorsechestedabstract.getBukkitEntity()); ++ if (!BlockDispenser.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != ItemArmor.DISPENSE_ITEM_BEHAVIOR) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ entityhorsechestedabstract.getSlot(499).set(CraftItemStack.asNMSCopy(event.getItem())); ++ // CraftBukkit end ++ ++ // itemstack.shrink(1); // CraftBukkit - handled above + this.setSuccess(true); + return itemstack; + } +@@ -336,12 +489,41 @@ + @Override + public ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { + EnumDirection enumdirection = (EnumDirection) sourceblock.state().getValue(BlockDispenser.FACING); ++ // CraftBukkit start ++ WorldServer worldserver = sourceblock.level(); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(enumdirection.getStepX(), enumdirection.getStepY(), enumdirection.getStepZ())); ++ if (!BlockDispenser.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); + Vec3D vec3d = IDispenseBehavior.getEntityPokingOutOfBlockPos(sourceblock, EntityTypes.FIREWORK_ROCKET, enumdirection); + EntityFireworks entityfireworks = new EntityFireworks(sourceblock.level(), itemstack, vec3d.x(), vec3d.y(), vec3d.z(), true); + + entityfireworks.shoot((double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ(), 0.5F, 1.0F); + sourceblock.level().addFreshEntity(entityfireworks); +- itemstack.shrink(1); ++ // itemstack.shrink(1); // Handled during event processing ++ // CraftBukkit end + return itemstack; + } + +@@ -363,12 +545,40 @@ + double d3 = randomsource.triangle((double) enumdirection.getStepX(), 0.11485000000000001D); + double d4 = randomsource.triangle((double) enumdirection.getStepY(), 0.11485000000000001D); + double d5 = randomsource.triangle((double) enumdirection.getStepZ(), 0.11485000000000001D); +- EntitySmallFireball entitysmallfireball = new EntitySmallFireball(worldserver, d0, d1, d2, d3, d4, d5); + +- worldserver.addFreshEntity((Entity) SystemUtils.make(entitysmallfireball, (entitysmallfireball1) -> { +- entitysmallfireball1.setItem(itemstack); +- })); +- itemstack.shrink(1); ++ // CraftBukkit start ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d3, d4, d5)); ++ if (!BlockDispenser.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ EntitySmallFireball entitysmallfireball = new EntitySmallFireball(worldserver, d0, d1, d2, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ()); ++ entitysmallfireball.setItem(itemstack1); ++ entitysmallfireball.projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(sourceblock.blockEntity()); ++ ++ worldserver.addFreshEntity(entitysmallfireball); ++ // itemstack.shrink(1); // Handled during event processing ++ // CraftBukkit end + return itemstack; + } + +@@ -404,9 +614,51 @@ + BlockPosition blockposition = sourceblock.pos().relative((EnumDirection) sourceblock.state().getValue(BlockDispenser.FACING)); + WorldServer worldserver = sourceblock.level(); + ++ // CraftBukkit start ++ int x = blockposition.getX(); ++ int y = blockposition.getY(); ++ int z = blockposition.getZ(); ++ IBlockData iblockdata = worldserver.getBlockState(blockposition); ++ if (iblockdata.isAir() || iblockdata.canBeReplaced() || (dispensiblecontaineritem instanceof ItemBucket && iblockdata.getBlock() instanceof IFluidContainer && ((IFluidContainer) iblockdata.getBlock()).canPlaceLiquid((EntityHuman) null, worldserver, blockposition, iblockdata, ((ItemBucket) dispensiblecontaineritem).content))) { ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(x, y, z)); ++ if (!BlockDispenser.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ dispensiblecontaineritem = (DispensibleContainerItem) CraftItemStack.asNMSCopy(event.getItem()).getItem(); ++ } ++ // CraftBukkit end ++ + if (dispensiblecontaineritem.emptyContents((EntityHuman) null, worldserver, blockposition, (MovingObjectPositionBlock) null)) { + dispensiblecontaineritem.checkExtraContent((EntityHuman) null, worldserver, itemstack, blockposition); +- return new ItemStack(Items.BUCKET); ++ // CraftBukkit start - Handle stacked buckets ++ Item item = Items.BUCKET; ++ itemstack.shrink(1); ++ if (itemstack.isEmpty()) { ++ itemstack.setItem(Items.BUCKET); ++ itemstack.setCount(1); ++ } else if (sourceblock.blockEntity().addItem(new ItemStack(item)) < 0) { ++ this.defaultDispenseItemBehavior.dispense(sourceblock, new ItemStack(item)); ++ } ++ return itemstack; ++ // CraftBukkit end + } else { + return this.defaultDispenseItemBehavior.dispense(sourceblock, itemstack); + } +@@ -434,7 +686,7 @@ + + if (block instanceof IFluidSource) { + IFluidSource ifluidsource = (IFluidSource) block; +- ItemStack itemstack1 = ifluidsource.pickupBlock((EntityHuman) null, worldserver, blockposition, iblockdata); ++ ItemStack itemstack1 = ifluidsource.pickupBlock((EntityHuman) null, DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); // CraftBukkit + + if (itemstack1.isEmpty()) { + return super.execute(sourceblock, itemstack); +@@ -442,6 +694,32 @@ + worldserver.gameEvent((Entity) null, GameEvent.FLUID_PICKUP, blockposition); + Item item = itemstack1.getItem(); + ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!BlockDispenser.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ itemstack1 = ifluidsource.pickupBlock((EntityHuman) null, worldserver, blockposition, iblockdata); // From above ++ // CraftBukkit end ++ + itemstack.shrink(1); + if (itemstack.isEmpty()) { + return new ItemStack(item); +@@ -463,16 +741,44 @@ + protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { + WorldServer worldserver = sourceblock.level(); + ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!BlockDispenser.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ + this.setSuccess(true); + EnumDirection enumdirection = (EnumDirection) sourceblock.state().getValue(BlockDispenser.FACING); + BlockPosition blockposition = sourceblock.pos().relative(enumdirection); + IBlockData iblockdata = worldserver.getBlockState(blockposition); + + if (BlockFireAbstract.canBePlacedAt(worldserver, blockposition, enumdirection)) { +- worldserver.setBlockAndUpdate(blockposition, BlockFireAbstract.getState(worldserver, blockposition)); +- worldserver.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockposition); ++ // CraftBukkit start - Ignition by dispensing flint and steel ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(worldserver, blockposition, sourceblock.pos()).isCancelled()) { ++ worldserver.setBlockAndUpdate(blockposition, BlockFireAbstract.getState(worldserver, blockposition)); ++ worldserver.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockposition); ++ } ++ // CraftBukkit end + } else if (!BlockCampfire.canLight(iblockdata) && !CandleBlock.canLight(iblockdata) && !CandleCakeBlock.canLight(iblockdata)) { +- if (iblockdata.getBlock() instanceof BlockTNT) { ++ if (iblockdata.getBlock() instanceof BlockTNT && org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(worldserver, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.DISPENSER, null, sourceblock.pos())) { // CraftBukkit - TNTPrimeEvent + BlockTNT.explode(worldserver, blockposition); + worldserver.removeBlock(blockposition, false); + } else { +@@ -496,12 +802,62 @@ + this.setSuccess(true); + WorldServer worldserver = sourceblock.level(); + BlockPosition blockposition = sourceblock.pos().relative((EnumDirection) sourceblock.state().getValue(BlockDispenser.FACING)); ++ // CraftBukkit start ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); ++ if (!BlockDispenser.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ worldserver.captureTreeGeneration = true; ++ // CraftBukkit end + + if (!ItemBoneMeal.growCrop(itemstack, worldserver, blockposition) && !ItemBoneMeal.growWaterPlant(itemstack, worldserver, blockposition, (EnumDirection) null)) { + this.setSuccess(false); + } else if (!worldserver.isClientSide) { + worldserver.levelEvent(1505, blockposition, 0); + } ++ // CraftBukkit start ++ worldserver.captureTreeGeneration = false; ++ if (worldserver.capturedBlockStates.size() > 0) { ++ TreeType treeType = BlockSapling.treeType; ++ BlockSapling.treeType = null; ++ Location location = CraftLocation.toBukkit(blockposition, worldserver.getWorld()); ++ List blocks = new java.util.ArrayList<>(worldserver.capturedBlockStates.values()); ++ worldserver.capturedBlockStates.clear(); ++ StructureGrowEvent structureEvent = null; ++ if (treeType != null) { ++ structureEvent = new StructureGrowEvent(location, treeType, false, null, blocks); ++ org.bukkit.Bukkit.getPluginManager().callEvent(structureEvent); ++ } ++ ++ BlockFertilizeEvent fertilizeEvent = new BlockFertilizeEvent(location.getBlock(), null, blocks); ++ fertilizeEvent.setCancelled(structureEvent != null && structureEvent.isCancelled()); ++ org.bukkit.Bukkit.getPluginManager().callEvent(fertilizeEvent); ++ ++ if (!fertilizeEvent.isCancelled()) { ++ for (org.bukkit.block.BlockState blockstate : blocks) { ++ blockstate.update(true); ++ } ++ } ++ } ++ // CraftBukkit end + + return itemstack; + } +@@ -511,12 +867,41 @@ + protected ItemStack execute(SourceBlock sourceblock, ItemStack itemstack) { + WorldServer worldserver = sourceblock.level(); + BlockPosition blockposition = sourceblock.pos().relative((EnumDirection) sourceblock.state().getValue(BlockDispenser.FACING)); +- EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, (EntityLiving) null); ++ // CraftBukkit start ++ // EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, (EntityLiving) null); ++ ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D)); ++ if (!BlockDispenser.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), (EntityLiving) null); ++ // CraftBukkit end + + worldserver.addFreshEntity(entitytntprimed); + worldserver.playSound((EntityHuman) null, entitytntprimed.getX(), entitytntprimed.getY(), entitytntprimed.getZ(), SoundEffects.TNT_PRIMED, SoundCategory.BLOCKS, 1.0F, 1.0F); + worldserver.gameEvent((Entity) null, GameEvent.ENTITY_PLACE, blockposition); +- itemstack.shrink(1); ++ // itemstack.shrink(1); // CraftBukkit - handled above + return itemstack; + } + }); +@@ -541,6 +926,30 @@ + EnumDirection enumdirection = (EnumDirection) sourceblock.state().getValue(BlockDispenser.FACING); + BlockPosition blockposition = sourceblock.pos().relative(enumdirection); + ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!BlockDispenser.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ + if (worldserver.isEmptyBlock(blockposition) && BlockWitherSkull.canSpawnMob(worldserver, blockposition, itemstack)) { + worldserver.setBlock(blockposition, (IBlockData) Blocks.WITHER_SKELETON_SKULL.defaultBlockState().setValue(BlockSkull.ROTATION, RotationSegment.convertToSegment(enumdirection)), 3); + worldserver.gameEvent((Entity) null, GameEvent.BLOCK_PLACE, blockposition); +@@ -566,6 +975,30 @@ + BlockPosition blockposition = sourceblock.pos().relative((EnumDirection) sourceblock.state().getValue(BlockDispenser.FACING)); + BlockPumpkinCarved blockpumpkincarved = (BlockPumpkinCarved) Blocks.CARVED_PUMPKIN; + ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!BlockDispenser.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ + if (worldserver.isEmptyBlock(blockposition) && blockpumpkincarved.canSpawnGolem(worldserver, blockposition)) { + if (!worldserver.isClientSide) { + worldserver.setBlock(blockposition, blockpumpkincarved.defaultBlockState(), 3); +@@ -615,6 +1048,30 @@ + BlockPosition blockposition = sourceblock.pos().relative((EnumDirection) sourceblock.state().getValue(BlockDispenser.FACING)); + IBlockData iblockdata = worldserver.getBlockState(blockposition); + ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ if (!BlockDispenser.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ // CraftBukkit end ++ + if (iblockdata.is(TagsBlock.BEEHIVES, (blockbase_blockdata) -> { + return blockbase_blockdata.hasProperty(BlockBeehive.HONEY_LEVEL) && blockbase_blockdata.getBlock() instanceof BlockBeehive; + }) && (Integer) iblockdata.getValue(BlockBeehive.HONEY_LEVEL) >= 5) { diff --git a/patch-remap/og/net/minecraft/nbt/NBTCompressedStreamTools.patch b/patch-remap/og/net/minecraft/nbt/NBTCompressedStreamTools.patch new file mode 100644 index 0000000000..e7fb3c7967 --- /dev/null +++ b/patch-remap/og/net/minecraft/nbt/NBTCompressedStreamTools.patch @@ -0,0 +1,7 @@ +--- a/net/minecraft/nbt/NBTCompressedStreamTools.java ++++ b/net/minecraft/nbt/NBTCompressedStreamTools.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.nbt; + + import java.io.BufferedOutputStream; diff --git a/patch-remap/og/net/minecraft/nbt/NBTTagByteArray.patch b/patch-remap/og/net/minecraft/nbt/NBTTagByteArray.patch new file mode 100644 index 0000000000..1bd3e4dac0 --- /dev/null +++ b/patch-remap/og/net/minecraft/nbt/NBTTagByteArray.patch @@ -0,0 +1,7 @@ +--- a/net/minecraft/nbt/NBTTagByteArray.java ++++ b/net/minecraft/nbt/NBTTagByteArray.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.nbt; + + import java.io.DataInput; diff --git a/patch-remap/og/net/minecraft/nbt/NBTTagIntArray.patch b/patch-remap/og/net/minecraft/nbt/NBTTagIntArray.patch new file mode 100644 index 0000000000..d62cce3d11 --- /dev/null +++ b/patch-remap/og/net/minecraft/nbt/NBTTagIntArray.patch @@ -0,0 +1,7 @@ +--- a/net/minecraft/nbt/NBTTagIntArray.java ++++ b/net/minecraft/nbt/NBTTagIntArray.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.nbt; + + import java.io.DataInput; diff --git a/patch-remap/og/net/minecraft/network/NetworkManager.patch b/patch-remap/og/net/minecraft/network/NetworkManager.patch new file mode 100644 index 0000000000..fb4e0c61d1 --- /dev/null +++ b/patch-remap/og/net/minecraft/network/NetworkManager.patch @@ -0,0 +1,28 @@ +--- a/net/minecraft/network/NetworkManager.java ++++ b/net/minecraft/network/NetworkManager.java +@@ -105,6 +105,7 @@ + private volatile IChatBaseComponent delayedDisconnect; + @Nullable + BandwidthDebugMonitor bandwidthDebugMonitor; ++ public String hostname = ""; // CraftBukkit - add field + + public NetworkManager(EnumProtocolDirection enumprotocoldirection) { + this.receiving = enumprotocoldirection; +@@ -194,7 +195,7 @@ + } + + private static void genericsFtw(Packet packet, PacketListener packetlistener) { +- packet.handle(packetlistener); ++ packet.handle((T) packetlistener); // CraftBukkit - decompile error + } + + public void suspendInboundAfterProtocolChange() { +@@ -421,7 +422,7 @@ + } + + if (this.isConnected()) { +- this.channel.close().awaitUninterruptibly(); ++ this.channel.close(); // We can't wait as this may be called from an event loop. + this.disconnectedReason = ichatbasecomponent; + } + diff --git a/patch-remap/og/net/minecraft/network/PacketDataSerializer.patch b/patch-remap/og/net/minecraft/network/PacketDataSerializer.patch new file mode 100644 index 0000000000..560385097a --- /dev/null +++ b/patch-remap/og/net/minecraft/network/PacketDataSerializer.patch @@ -0,0 +1,101 @@ +--- a/net/minecraft/network/PacketDataSerializer.java ++++ b/net/minecraft/network/PacketDataSerializer.java +@@ -81,6 +81,8 @@ + import org.joml.Quaternionf; + import org.joml.Vector3f; + ++import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit ++ + public class PacketDataSerializer extends ByteBuf { + + public static final int DEFAULT_NBT_QUOTA = 2097152; +@@ -205,7 +207,7 @@ + + public > C readCollection(IntFunction intfunction, PacketDataSerializer.a packetdataserializer_a) { + int i = this.readVarInt(); +- C c0 = (Collection) intfunction.apply(i); ++ C c0 = intfunction.apply(i); // CraftBukkit - decompile error + + for (int j = 0; j < i; ++j) { + c0.add(packetdataserializer_a.apply(this)); +@@ -216,7 +218,7 @@ + + public void writeCollection(Collection collection, PacketDataSerializer.b packetdataserializer_b) { + this.writeVarInt(collection.size()); +- Iterator iterator = collection.iterator(); ++ Iterator iterator = collection.iterator(); // CraftBukkit - decompile error + + while (iterator.hasNext()) { + T t0 = iterator.next(); +@@ -243,12 +245,12 @@ + + public void writeIntIdList(IntList intlist) { + this.writeVarInt(intlist.size()); +- intlist.forEach(this::writeVarInt); ++ intlist.forEach((java.util.function.IntConsumer) this::writeVarInt); // CraftBukkit - decompile error + } + + public > M readMap(IntFunction intfunction, PacketDataSerializer.a packetdataserializer_a, PacketDataSerializer.a packetdataserializer_a1) { + int i = this.readVarInt(); +- M m0 = (Map) intfunction.apply(i); ++ M m0 = intfunction.apply(i); // CraftBukkit - decompile error + + for (int j = 0; j < i; ++j) { + K k0 = packetdataserializer_a.apply(this); +@@ -282,7 +284,7 @@ + } + + public > void writeEnumSet(EnumSet enumset, Class oclass) { +- E[] ae = (Enum[]) oclass.getEnumConstants(); ++ E[] ae = oclass.getEnumConstants(); // CraftBukkit - decompile error + BitSet bitset = new BitSet(ae.length); + + for (int i = 0; i < ae.length; ++i) { +@@ -293,7 +295,7 @@ + } + + public > EnumSet readEnumSet(Class oclass) { +- E[] ae = (Enum[]) oclass.getEnumConstants(); ++ E[] ae = oclass.getEnumConstants(); // CraftBukkit - decompile error + BitSet bitset = this.readFixedBitSet(ae.length); + EnumSet enumset = EnumSet.noneOf(oclass); + +@@ -529,7 +531,7 @@ + } + + public > T readEnum(Class oclass) { +- return ((Enum[]) oclass.getEnumConstants())[this.readVarInt()]; ++ return ((T[]) oclass.getEnumConstants())[this.readVarInt()]; // CraftBukkit - fix decompile error + } + + public PacketDataSerializer writeEnum(Enum oenum) { +@@ -584,7 +586,7 @@ + try { + NBTCompressedStreamTools.writeAnyTag((NBTBase) nbtbase, new ByteBufOutputStream(this)); + return this; +- } catch (IOException ioexception) { ++ } catch (Exception ioexception) { // CraftBukkit - IOException -> Exception + throw new EncoderException(ioexception); + } + } +@@ -612,7 +614,7 @@ + } + + public PacketDataSerializer writeItem(ItemStack itemstack) { +- if (itemstack.isEmpty()) { ++ if (itemstack.isEmpty() || itemstack.getItem() == null) { // CraftBukkit - NPE fix itemstack.getItem() + this.writeBoolean(false); + } else { + this.writeBoolean(true); +@@ -641,6 +643,11 @@ + ItemStack itemstack = new ItemStack(item, b0); + + itemstack.setTag(this.readNbt()); ++ // CraftBukkit start ++ if (itemstack.getTag() != null) { ++ CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); ++ } ++ // CraftBukkit end + return itemstack; + } + } diff --git a/patch-remap/og/net/minecraft/network/chat/ChatHexColor.patch b/patch-remap/og/net/minecraft/network/chat/ChatHexColor.patch new file mode 100644 index 0000000000..8924ab3f00 --- /dev/null +++ b/patch-remap/og/net/minecraft/network/chat/ChatHexColor.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/network/chat/ChatHexColor.java ++++ b/net/minecraft/network/chat/ChatHexColor.java +@@ -17,7 +17,7 @@ + private static final String CUSTOM_COLOR_PREFIX = "#"; + public static final Codec CODEC = Codec.STRING.comapFlatMap(ChatHexColor::parseColor, ChatHexColor::serialize); + private static final Map LEGACY_FORMAT_TO_COLOR = (Map) Stream.of(EnumChatFormat.values()).filter(EnumChatFormat::isColor).collect(ImmutableMap.toImmutableMap(Function.identity(), (enumchatformat) -> { +- return new ChatHexColor(enumchatformat.getColor(), enumchatformat.getName()); ++ return new ChatHexColor(enumchatformat.getColor(), enumchatformat.getName(), enumchatformat); // CraftBukkit + })); + private static final Map NAMED_COLORS = (Map) ChatHexColor.LEGACY_FORMAT_TO_COLOR.values().stream().collect(ImmutableMap.toImmutableMap((chathexcolor) -> { + return chathexcolor.name; +@@ -25,16 +25,22 @@ + private final int value; + @Nullable + public final String name; ++ // CraftBukkit start ++ @Nullable ++ public final EnumChatFormat format; + +- private ChatHexColor(int i, String s) { ++ private ChatHexColor(int i, String s, EnumChatFormat format) { + this.value = i & 16777215; + this.name = s; ++ this.format = format; + } + + private ChatHexColor(int i) { + this.value = i & 16777215; + this.name = null; ++ this.format = null; + } ++ // CraftBukkit end + + public int getValue() { + return this.value; diff --git a/patch-remap/og/net/minecraft/network/chat/IChatBaseComponent.patch b/patch-remap/og/net/minecraft/network/chat/IChatBaseComponent.patch new file mode 100644 index 0000000000..93751f5b13 --- /dev/null +++ b/patch-remap/og/net/minecraft/network/chat/IChatBaseComponent.patch @@ -0,0 +1,26 @@ +--- a/net/minecraft/network/chat/IChatBaseComponent.java ++++ b/net/minecraft/network/chat/IChatBaseComponent.java +@@ -35,7 +35,22 @@ + import net.minecraft.util.FormattedString; + import net.minecraft.world.level.ChunkCoordIntPair; + +-public interface IChatBaseComponent extends Message, IChatFormatted { ++// CraftBukkit start ++import java.util.stream.Stream; ++// CraftBukkit end ++ ++public interface IChatBaseComponent extends Message, IChatFormatted, Iterable { // CraftBukkit ++ ++ // CraftBukkit start ++ default Stream stream() { ++ return com.google.common.collect.Streams.concat(new Stream[]{Stream.of(this), this.getSiblings().stream().flatMap(IChatBaseComponent::stream)}); ++ } ++ ++ @Override ++ default Iterator iterator() { ++ return this.stream().iterator(); ++ } ++ // CraftBukkit end + + ChatModifier getStyle(); + diff --git a/patch-remap/og/net/minecraft/network/protocol/PlayerConnectionUtils.patch b/patch-remap/og/net/minecraft/network/protocol/PlayerConnectionUtils.patch new file mode 100644 index 0000000000..3f6e230c44 --- /dev/null +++ b/patch-remap/og/net/minecraft/network/protocol/PlayerConnectionUtils.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/network/protocol/PlayerConnectionUtils.java ++++ b/net/minecraft/network/protocol/PlayerConnectionUtils.java +@@ -9,6 +9,11 @@ + import net.minecraft.util.thread.IAsyncTaskHandler; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.network.ServerCommonPacketListenerImpl; ++// CraftBukkit end ++ + public class PlayerConnectionUtils { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -22,6 +27,7 @@ + public static void ensureRunningOnSameThread(Packet packet, T t0, IAsyncTaskHandler iasynctaskhandler) throws CancelledPacketHandleException { + if (!iasynctaskhandler.isSameThread()) { + iasynctaskhandler.executeIfPossible(() -> { ++ if (MinecraftServer.getServer().hasStopped() || (t0 instanceof ServerCommonPacketListenerImpl && ((ServerCommonPacketListenerImpl) t0).processedDisconnect)) return; // CraftBukkit, MC-142590 + if (t0.shouldHandleMessage(packet)) { + try { + packet.handle(t0); +@@ -60,6 +66,10 @@ + + }); + throw CancelledPacketHandleException.RUNNING_ON_DIFFERENT_THREAD; ++ // CraftBukkit start - SPIGOT-5477, MC-142590 ++ } else if (MinecraftServer.getServer().hasStopped() || (t0 instanceof ServerCommonPacketListenerImpl && ((ServerCommonPacketListenerImpl) t0).processedDisconnect)) { ++ throw CancelledPacketHandleException.RUNNING_ON_DIFFERENT_THREAD; ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/og/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.patch b/patch-remap/og/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.patch new file mode 100644 index 0000000000..f4712b4d08 --- /dev/null +++ b/patch-remap/og/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java ++++ b/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java +@@ -12,7 +12,7 @@ + public record ServerboundCustomPayloadPacket(CustomPacketPayload payload) implements Packet { + + private static final int MAX_PAYLOAD_SIZE = 32767; +- private static final Map> KNOWN_TYPES = ImmutableMap.builder().put(BrandPayload.ID, BrandPayload::new).build(); ++ private static final Map> KNOWN_TYPES = ImmutableMap.>builder().build(); // CraftBukkit - no special handling + + public ServerboundCustomPayloadPacket(PacketDataSerializer packetdataserializer) { + this(readPayload(packetdataserializer.readResourceLocation(), packetdataserializer)); +@@ -24,12 +24,13 @@ + return (CustomPacketPayload) (packetdataserializer_a != null ? (CustomPacketPayload) packetdataserializer_a.apply(packetdataserializer) : readUnknownPayload(minecraftkey, packetdataserializer)); + } + +- private static DiscardedPayload readUnknownPayload(MinecraftKey minecraftkey, PacketDataSerializer packetdataserializer) { ++ private static UnknownPayload readUnknownPayload(MinecraftKey minecraftkey, PacketDataSerializer packetdataserializer) { // CraftBukkit + int i = packetdataserializer.readableBytes(); + + if (i >= 0 && i <= 32767) { +- packetdataserializer.skipBytes(i); +- return new DiscardedPayload(minecraftkey); ++ // CraftBukkit start ++ return new UnknownPayload(minecraftkey, packetdataserializer.readBytes(i)); ++ // CraftBukkit end + } else { + throw new IllegalArgumentException("Payload may not be larger than 32767 bytes"); + } +@@ -44,4 +45,14 @@ + public void handle(ServerCommonPacketListener servercommonpacketlistener) { + servercommonpacketlistener.handleCustomPayload(this); + } ++ ++ // CraftBukkit start ++ public record UnknownPayload(MinecraftKey id, io.netty.buffer.ByteBuf data) implements CustomPacketPayload { ++ ++ @Override ++ public void write(PacketDataSerializer packetdataserializer) { ++ packetdataserializer.writeBytes(data); ++ } ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.patch b/patch-remap/og/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.patch new file mode 100644 index 0000000000..fa0dc08cc7 --- /dev/null +++ b/patch-remap/og/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java ++++ b/net/minecraft/network/protocol/game/ClientboundInitializeBorderPacket.java +@@ -27,8 +27,10 @@ + } + + public ClientboundInitializeBorderPacket(WorldBorder worldborder) { +- this.newCenterX = worldborder.getCenterX(); +- this.newCenterZ = worldborder.getCenterZ(); ++ // CraftBukkit start - multiply out nether border ++ this.newCenterX = worldborder.getCenterX() * worldborder.world.dimensionType().coordinateScale(); ++ this.newCenterZ = worldborder.getCenterZ() * worldborder.world.dimensionType().coordinateScale(); ++ // CraftBukkit end + this.oldSize = worldborder.getSize(); + this.newSize = worldborder.getLerpTarget(); + this.lerpTime = worldborder.getLerpRemainingTime(); diff --git a/patch-remap/og/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.patch b/patch-remap/og/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.patch new file mode 100644 index 0000000000..abf12e82da --- /dev/null +++ b/patch-remap/og/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java ++++ b/net/minecraft/network/protocol/game/ClientboundSetBorderCenterPacket.java +@@ -10,8 +10,10 @@ + private final double newCenterZ; + + public ClientboundSetBorderCenterPacket(WorldBorder worldborder) { +- this.newCenterX = worldborder.getCenterX(); +- this.newCenterZ = worldborder.getCenterZ(); ++ // CraftBukkit start - multiply out nether border ++ this.newCenterX = worldborder.getCenterX() * (worldborder.world != null ? worldborder.world.dimensionType().coordinateScale() : 1.0); ++ this.newCenterZ = worldborder.getCenterZ() * (worldborder.world != null ? worldborder.world.dimensionType().coordinateScale() : 1.0); ++ // CraftBukkit end + } + + public ClientboundSetBorderCenterPacket(PacketDataSerializer packetdataserializer) { diff --git a/patch-remap/og/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.patch b/patch-remap/og/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.patch new file mode 100644 index 0000000000..380b8686c6 --- /dev/null +++ b/patch-remap/og/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.patch @@ -0,0 +1,7 @@ +--- a/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.java ++++ b/net/minecraft/network/protocol/game/ClientboundSystemChatPacket.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.network.protocol.game; + + import net.minecraft.network.PacketDataSerializer; diff --git a/patch-remap/og/net/minecraft/network/protocol/game/PacketPlayInBlockPlace.patch b/patch-remap/og/net/minecraft/network/protocol/game/PacketPlayInBlockPlace.patch new file mode 100644 index 0000000000..760a854cd4 --- /dev/null +++ b/patch-remap/og/net/minecraft/network/protocol/game/PacketPlayInBlockPlace.patch @@ -0,0 +1,7 @@ +--- a/net/minecraft/network/protocol/game/PacketPlayInBlockPlace.java ++++ b/net/minecraft/network/protocol/game/PacketPlayInBlockPlace.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.network.protocol.game; + + import net.minecraft.network.PacketDataSerializer; diff --git a/patch-remap/og/net/minecraft/network/protocol/game/PacketPlayInUseItem.patch b/patch-remap/og/net/minecraft/network/protocol/game/PacketPlayInUseItem.patch new file mode 100644 index 0000000000..9475518bd9 --- /dev/null +++ b/patch-remap/og/net/minecraft/network/protocol/game/PacketPlayInUseItem.patch @@ -0,0 +1,7 @@ +--- a/net/minecraft/network/protocol/game/PacketPlayInUseItem.java ++++ b/net/minecraft/network/protocol/game/PacketPlayInUseItem.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.network.protocol.game; + + import net.minecraft.network.PacketDataSerializer; diff --git a/patch-remap/og/net/minecraft/network/protocol/game/PacketPlayOutMultiBlockChange.patch b/patch-remap/og/net/minecraft/network/protocol/game/PacketPlayOutMultiBlockChange.patch new file mode 100644 index 0000000000..06f07964d1 --- /dev/null +++ b/patch-remap/og/net/minecraft/network/protocol/game/PacketPlayOutMultiBlockChange.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/network/protocol/game/PacketPlayOutMultiBlockChange.java ++++ b/net/minecraft/network/protocol/game/PacketPlayOutMultiBlockChange.java +@@ -30,11 +30,19 @@ + short short0 = (Short) shortiterator.next(); + + this.positions[j] = short0; +- this.states[j] = chunksection.getBlockState(SectionPosition.sectionRelativeX(short0), SectionPosition.sectionRelativeY(short0), SectionPosition.sectionRelativeZ(short0)); ++ this.states[j] = (chunksection != null) ? chunksection.getBlockState(SectionPosition.sectionRelativeX(short0), SectionPosition.sectionRelativeY(short0), SectionPosition.sectionRelativeZ(short0)) : net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(); // CraftBukkit - SPIGOT-6076, Mojang bug when empty chunk section notified + } + + } + ++ // CraftBukkit start - Add constructor ++ public PacketPlayOutMultiBlockChange(SectionPosition sectionposition, ShortSet shortset, IBlockData[] states) { ++ this.sectionPos = sectionposition; ++ this.positions = shortset.toShortArray(); ++ this.states = states; ++ } ++ // CraftBukkit end ++ + public PacketPlayOutMultiBlockChange(PacketDataSerializer packetdataserializer) { + this.sectionPos = SectionPosition.of(packetdataserializer.readLong()); + int i = packetdataserializer.readVarInt(); diff --git a/patch-remap/og/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.patch b/patch-remap/og/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.patch new file mode 100644 index 0000000000..3ab554b774 --- /dev/null +++ b/patch-remap/og/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.patch @@ -0,0 +1,7 @@ +--- a/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.java ++++ b/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.network.protocol.handshake; + + import net.minecraft.network.EnumProtocol; diff --git a/patch-remap/og/net/minecraft/network/syncher/DataWatcher.patch b/patch-remap/og/net/minecraft/network/syncher/DataWatcher.patch new file mode 100644 index 0000000000..a818feaeda --- /dev/null +++ b/patch-remap/og/net/minecraft/network/syncher/DataWatcher.patch @@ -0,0 +1,65 @@ +--- a/net/minecraft/network/syncher/DataWatcher.java ++++ b/net/minecraft/network/syncher/DataWatcher.java +@@ -24,6 +24,11 @@ + import org.apache.commons.lang3.ObjectUtils; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata; ++import net.minecraft.server.level.EntityPlayer; ++// CraftBukkit end ++ + public class DataWatcher { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -146,6 +151,13 @@ + + } + ++ // CraftBukkit start - add method from above ++ public void markDirty(DataWatcherObject datawatcherobject) { ++ this.getItem(datawatcherobject).setDirty(true); ++ this.isDirty = true; ++ } ++ // CraftBukkit end ++ + public boolean isDirty() { + return this.isDirty; + } +@@ -227,7 +239,7 @@ + if (!Objects.equals(datawatcher_b.serializer(), datawatcher_item.accessor.getSerializer())) { + throw new IllegalStateException(String.format(Locale.ROOT, "Invalid entity data item type for field %d on entity %s: old=%s(%s), new=%s(%s)", datawatcher_item.accessor.getId(), this.entity, datawatcher_item.value, datawatcher_item.value.getClass(), datawatcher_b.value, datawatcher_b.value.getClass())); + } else { +- datawatcher_item.setValue(datawatcher_b.value); ++ datawatcher_item.setValue((T) datawatcher_b.value); // CraftBukkit - decompile error + } + } + +@@ -235,6 +247,18 @@ + return this.itemsById.isEmpty(); + } + ++ // CraftBukkit start ++ public void refresh(EntityPlayer to) { ++ if (!this.isEmpty()) { ++ List> list = this.getNonDefaultValues(); ++ ++ if (list != null) { ++ to.connection.send(new PacketPlayOutEntityMetadata(this.entity.getId(), list)); ++ } ++ } ++ } ++ // CraftBukkit end ++ + public static class Item { + + final DataWatcherObject accessor; +@@ -277,7 +301,7 @@ + } + } + +- public static record b (int id, DataWatcherSerializer serializer, T value) { ++ public static record b(int id, DataWatcherSerializer serializer, T value) { // CraftBukkit - decompile error + + public static DataWatcher.b create(DataWatcherObject datawatcherobject, T t0) { + DataWatcherSerializer datawatcherserializer = datawatcherobject.getSerializer(); diff --git a/patch-remap/og/net/minecraft/server/AdvancementDataPlayer.patch b/patch-remap/og/net/minecraft/server/AdvancementDataPlayer.patch new file mode 100644 index 0000000000..87812ef579 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/AdvancementDataPlayer.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/server/AdvancementDataPlayer.java ++++ b/net/minecraft/server/AdvancementDataPlayer.java +@@ -196,6 +196,7 @@ + AdvancementHolder advancementholder = advancementdataworld.get(minecraftkey); + + if (advancementholder == null) { ++ if (!minecraftkey.getNamespace().equals("minecraft")) return; // CraftBukkit + AdvancementDataPlayer.LOGGER.warn("Ignored advancement '{}' in progress file {} - it doesn't exist anymore?", minecraftkey, this.playerSavePath); + } else { + this.startProgress(advancementholder, advancementprogress); +@@ -227,6 +228,7 @@ + this.progressChanged.add(advancementholder); + flag = true; + if (!flag1 && advancementprogress.isDone()) { ++ this.player.level().getCraftServer().getPluginManager().callEvent(new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancementholder.toBukkit())); // CraftBukkit + advancementholder.value().rewards().grant(this.player); + advancementholder.value().display().ifPresent((advancementdisplay) -> { + if (advancementdisplay.shouldAnnounceChat() && this.player.level().getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { diff --git a/patch-remap/og/net/minecraft/server/AdvancementDataWorld.patch b/patch-remap/og/net/minecraft/server/AdvancementDataWorld.patch new file mode 100644 index 0000000000..7c005ced93 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/AdvancementDataWorld.patch @@ -0,0 +1,7 @@ +--- a/net/minecraft/server/AdvancementDataWorld.java ++++ b/net/minecraft/server/AdvancementDataWorld.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.server; + + import com.google.common.collect.ImmutableMap; diff --git a/patch-remap/og/net/minecraft/server/CustomFunctionData.patch b/patch-remap/og/net/minecraft/server/CustomFunctionData.patch new file mode 100644 index 0000000000..21f7645c6a --- /dev/null +++ b/patch-remap/og/net/minecraft/server/CustomFunctionData.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/server/CustomFunctionData.java ++++ b/net/minecraft/server/CustomFunctionData.java +@@ -36,7 +36,7 @@ + } + + public CommandDispatcher getDispatcher() { +- return this.server.getCommands().getDispatcher(); ++ return this.server.vanillaCommandDispatcher.getDispatcher(); // CraftBukkit + } + + public void tick() { diff --git a/patch-remap/og/net/minecraft/server/DispenserRegistry.patch b/patch-remap/og/net/minecraft/server/DispenserRegistry.patch new file mode 100644 index 0000000000..e592b70ef9 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/DispenserRegistry.patch @@ -0,0 +1,109 @@ +--- a/net/minecraft/server/DispenserRegistry.java ++++ b/net/minecraft/server/DispenserRegistry.java +@@ -30,6 +30,12 @@ + import net.minecraft.world.level.block.BlockFire; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.util.datafix.fixes.DataConverterFlattenData; ++import net.minecraft.util.datafix.fixes.DataConverterMaterialId; ++import net.minecraft.util.datafix.fixes.DataConverterSpawnEgg; ++// CraftBukkit end ++ + public class DispenserRegistry { + + public static final PrintStream STDOUT = System.out; +@@ -41,6 +47,23 @@ + + public static void bootStrap() { + if (!DispenserRegistry.isBootstrapped) { ++ // CraftBukkit start ++ String name = DispenserRegistry.class.getSimpleName(); ++ switch (name) { ++ case "DispenserRegistry": ++ break; ++ case "Bootstrap": ++ System.err.println("***************************************************************************"); ++ System.err.println("*** WARNING: This server jar may only be used for development purposes. ***"); ++ System.err.println("***************************************************************************"); ++ break; ++ default: ++ System.err.println("**********************************************************************"); ++ System.err.println("*** WARNING: This server jar is unsupported, use at your own risk. ***"); ++ System.err.println("**********************************************************************"); ++ break; ++ } ++ // CraftBukkit end + DispenserRegistry.isBootstrapped = true; + Instant instant = Instant.now(); + +@@ -61,6 +84,69 @@ + wrapStreams(); + DispenserRegistry.bootstrapDuration.set(Duration.between(instant, Instant.now()).toMillis()); + } ++ // CraftBukkit start - easier than fixing the decompile ++ DataConverterFlattenData.register(1008, "{Name:'minecraft:oak_sign',Properties:{rotation:'0'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'0'}}"); ++ DataConverterFlattenData.register(1009, "{Name:'minecraft:oak_sign',Properties:{rotation:'1'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'1'}}"); ++ DataConverterFlattenData.register(1010, "{Name:'minecraft:oak_sign',Properties:{rotation:'2'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'2'}}"); ++ DataConverterFlattenData.register(1011, "{Name:'minecraft:oak_sign',Properties:{rotation:'3'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'3'}}"); ++ DataConverterFlattenData.register(1012, "{Name:'minecraft:oak_sign',Properties:{rotation:'4'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'4'}}"); ++ DataConverterFlattenData.register(1013, "{Name:'minecraft:oak_sign',Properties:{rotation:'5'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'5'}}"); ++ DataConverterFlattenData.register(1014, "{Name:'minecraft:oak_sign',Properties:{rotation:'6'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'6'}}"); ++ DataConverterFlattenData.register(1015, "{Name:'minecraft:oak_sign',Properties:{rotation:'7'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'7'}}"); ++ DataConverterFlattenData.register(1016, "{Name:'minecraft:oak_sign',Properties:{rotation:'8'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'8'}}"); ++ DataConverterFlattenData.register(1017, "{Name:'minecraft:oak_sign',Properties:{rotation:'9'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'9'}}"); ++ DataConverterFlattenData.register(1018, "{Name:'minecraft:oak_sign',Properties:{rotation:'10'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'10'}}"); ++ DataConverterFlattenData.register(1019, "{Name:'minecraft:oak_sign',Properties:{rotation:'11'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'11'}}"); ++ DataConverterFlattenData.register(1020, "{Name:'minecraft:oak_sign',Properties:{rotation:'12'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'12'}}"); ++ DataConverterFlattenData.register(1021, "{Name:'minecraft:oak_sign',Properties:{rotation:'13'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'13'}}"); ++ DataConverterFlattenData.register(1022, "{Name:'minecraft:oak_sign',Properties:{rotation:'14'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'14'}}"); ++ DataConverterFlattenData.register(1023, "{Name:'minecraft:oak_sign',Properties:{rotation:'15'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'15'}}"); ++ DataConverterMaterialId.ITEM_NAMES.put(323, "minecraft:oak_sign"); ++ ++ DataConverterFlattenData.register(1440, "{Name:\'minecraft:portal\',Properties:{axis:\'x\'}}", new String[]{"{Name:\'minecraft:portal\',Properties:{axis:\'x\'}}"}); ++ ++ DataConverterMaterialId.ITEM_NAMES.put(409, "minecraft:prismarine_shard"); ++ DataConverterMaterialId.ITEM_NAMES.put(410, "minecraft:prismarine_crystals"); ++ DataConverterMaterialId.ITEM_NAMES.put(411, "minecraft:rabbit"); ++ DataConverterMaterialId.ITEM_NAMES.put(412, "minecraft:cooked_rabbit"); ++ DataConverterMaterialId.ITEM_NAMES.put(413, "minecraft:rabbit_stew"); ++ DataConverterMaterialId.ITEM_NAMES.put(414, "minecraft:rabbit_foot"); ++ DataConverterMaterialId.ITEM_NAMES.put(415, "minecraft:rabbit_hide"); ++ DataConverterMaterialId.ITEM_NAMES.put(416, "minecraft:armor_stand"); ++ ++ DataConverterMaterialId.ITEM_NAMES.put(423, "minecraft:mutton"); ++ DataConverterMaterialId.ITEM_NAMES.put(424, "minecraft:cooked_mutton"); ++ DataConverterMaterialId.ITEM_NAMES.put(425, "minecraft:banner"); ++ DataConverterMaterialId.ITEM_NAMES.put(426, "minecraft:end_crystal"); ++ DataConverterMaterialId.ITEM_NAMES.put(427, "minecraft:spruce_door"); ++ DataConverterMaterialId.ITEM_NAMES.put(428, "minecraft:birch_door"); ++ DataConverterMaterialId.ITEM_NAMES.put(429, "minecraft:jungle_door"); ++ DataConverterMaterialId.ITEM_NAMES.put(430, "minecraft:acacia_door"); ++ DataConverterMaterialId.ITEM_NAMES.put(431, "minecraft:dark_oak_door"); ++ DataConverterMaterialId.ITEM_NAMES.put(432, "minecraft:chorus_fruit"); ++ DataConverterMaterialId.ITEM_NAMES.put(433, "minecraft:chorus_fruit_popped"); ++ DataConverterMaterialId.ITEM_NAMES.put(434, "minecraft:beetroot"); ++ DataConverterMaterialId.ITEM_NAMES.put(435, "minecraft:beetroot_seeds"); ++ DataConverterMaterialId.ITEM_NAMES.put(436, "minecraft:beetroot_soup"); ++ DataConverterMaterialId.ITEM_NAMES.put(437, "minecraft:dragon_breath"); ++ DataConverterMaterialId.ITEM_NAMES.put(438, "minecraft:splash_potion"); ++ DataConverterMaterialId.ITEM_NAMES.put(439, "minecraft:spectral_arrow"); ++ DataConverterMaterialId.ITEM_NAMES.put(440, "minecraft:tipped_arrow"); ++ DataConverterMaterialId.ITEM_NAMES.put(441, "minecraft:lingering_potion"); ++ DataConverterMaterialId.ITEM_NAMES.put(442, "minecraft:shield"); ++ DataConverterMaterialId.ITEM_NAMES.put(443, "minecraft:elytra"); ++ DataConverterMaterialId.ITEM_NAMES.put(444, "minecraft:spruce_boat"); ++ DataConverterMaterialId.ITEM_NAMES.put(445, "minecraft:birch_boat"); ++ DataConverterMaterialId.ITEM_NAMES.put(446, "minecraft:jungle_boat"); ++ DataConverterMaterialId.ITEM_NAMES.put(447, "minecraft:acacia_boat"); ++ DataConverterMaterialId.ITEM_NAMES.put(448, "minecraft:dark_oak_boat"); ++ DataConverterMaterialId.ITEM_NAMES.put(449, "minecraft:totem_of_undying"); ++ DataConverterMaterialId.ITEM_NAMES.put(450, "minecraft:shulker_shell"); ++ DataConverterMaterialId.ITEM_NAMES.put(452, "minecraft:iron_nugget"); ++ DataConverterMaterialId.ITEM_NAMES.put(453, "minecraft:knowledge_book"); ++ ++ DataConverterSpawnEgg.ID_TO_ENTITY[23] = "Arrow"; ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/og/net/minecraft/server/Main.patch b/patch-remap/og/net/minecraft/server/Main.patch new file mode 100644 index 0000000000..d89f6deee2 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/Main.patch @@ -0,0 +1,216 @@ +--- a/net/minecraft/server/Main.java ++++ b/net/minecraft/server/Main.java +@@ -60,6 +60,17 @@ + import net.minecraft.world.level.storage.WorldInfo; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.google.common.base.Charsets; ++import java.io.InputStreamReader; ++import java.util.concurrent.atomic.AtomicReference; ++import net.minecraft.SharedConstants; ++import net.minecraft.server.packs.EnumResourcePackType; ++import net.minecraft.world.level.dimension.WorldDimension; ++import net.minecraft.world.level.storage.SavedFile; ++import org.bukkit.configuration.file.YamlConfiguration; ++// CraftBukkit end ++ + public class Main { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -67,8 +78,9 @@ + public Main() {} + + @DontObfuscate +- public static void main(String[] astring) { ++ public static void main(final OptionSet optionset) { // CraftBukkit - replaces main(String[] astring) + SharedConstants.tryDetectVersion(); ++ /* CraftBukkit start - Replace everything + OptionParser optionparser = new OptionParser(); + OptionSpec optionspec = optionparser.accepts("nogui"); + OptionSpec optionspec1 = optionparser.accepts("initSettings", "Initializes 'server.properties' and 'eula.txt', then quits"); +@@ -93,15 +105,18 @@ + optionparser.printHelpOn(System.err); + return; + } ++ */ // CraftBukkit end + +- Path path = (Path) optionset.valueOf(optionspec13); ++ try { ++ ++ Path path = (Path) optionset.valueOf("pidFile"); // CraftBukkit + + if (path != null) { + writePidFile(path); + } + + CrashReport.preload(); +- if (optionset.has(optionspec12)) { ++ if (optionset.has("jfrProfile")) { // CraftBukkit + JvmProfiler.INSTANCE.start(Environment.SERVER); + } + +@@ -109,13 +124,26 @@ + DispenserRegistry.validate(); + SystemUtils.startTimerHackThread(); + Path path1 = Paths.get("server.properties"); +- DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(path1); ++ DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(optionset); // CraftBukkit - CLI argument support + + dedicatedserversettings.forceSave(); + Path path2 = Paths.get("eula.txt"); + EULA eula = new EULA(path2); + +- if (optionset.has(optionspec1)) { ++ if (optionset.has("initSettings")) { // CraftBukkit ++ // CraftBukkit start - SPIGOT-5761: Create bukkit.yml and commands.yml if not present ++ File configFile = (File) optionset.valueOf("bukkit-settings"); ++ YamlConfiguration configuration = YamlConfiguration.loadConfiguration(configFile); ++ configuration.options().copyDefaults(true); ++ configuration.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/bukkit.yml"), Charsets.UTF_8))); ++ configuration.save(configFile); ++ ++ File commandFile = (File) optionset.valueOf("commands-settings"); ++ YamlConfiguration commandsConfiguration = YamlConfiguration.loadConfiguration(commandFile); ++ commandsConfiguration.options().copyDefaults(true); ++ commandsConfiguration.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/commands.yml"), Charsets.UTF_8))); ++ commandsConfiguration.save(commandFile); ++ // CraftBukkit end + Main.LOGGER.info("Initialized '{}' and '{}'", path1.toAbsolutePath(), path2.toAbsolutePath()); + return; + } +@@ -125,11 +153,13 @@ + return; + } + +- File file = new File((String) optionset.valueOf(optionspec8)); ++ File file = (File) optionset.valueOf("universe"); // CraftBukkit + Services services = Services.create(new YggdrasilAuthenticationService(Proxy.NO_PROXY), file); +- String s = (String) Optional.ofNullable((String) optionset.valueOf(optionspec9)).orElse(dedicatedserversettings.getProperties().levelName); ++ // CraftBukkit start ++ String s = (String) Optional.ofNullable((String) optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName); + Convertable convertable = Convertable.createDefault(file.toPath()); +- Convertable.ConversionSession convertable_conversionsession = convertable.validateAndCreateAccess(s); ++ Convertable.ConversionSession convertable_conversionsession = convertable.validateAndCreateAccess(s, WorldDimension.OVERWORLD); ++ // CraftBukkit end + Dynamic dynamic; + + if (convertable_conversionsession.hasWorldData()) { +@@ -170,13 +200,31 @@ + } + + Dynamic dynamic1 = dynamic; +- boolean flag = optionset.has(optionspec6); ++ boolean flag = optionset.has("safeMode"); // CraftBukkit + + if (flag) { + Main.LOGGER.warn("Safe mode active, only vanilla datapack will be loaded"); + } + + ResourcePackRepository resourcepackrepository = ResourcePackSourceVanilla.createPackRepository(convertable_conversionsession); ++ // CraftBukkit start ++ File bukkitDataPackFolder = new File(convertable_conversionsession.getLevelPath(SavedFile.DATAPACK_DIR).toFile(), "bukkit"); ++ if (!bukkitDataPackFolder.exists()) { ++ bukkitDataPackFolder.mkdirs(); ++ } ++ File mcMeta = new File(bukkitDataPackFolder, "pack.mcmeta"); ++ try { ++ com.google.common.io.Files.write("{\n" ++ + " \"pack\": {\n" ++ + " \"description\": \"Data pack for resources provided by Bukkit plugins\",\n" ++ + " \"pack_format\": " + SharedConstants.getCurrentVersion().getPackVersion(EnumResourcePackType.SERVER_DATA) + "\n" ++ + " }\n" ++ + "}\n", mcMeta, com.google.common.base.Charsets.UTF_8); ++ } catch (java.io.IOException ex) { ++ throw new RuntimeException("Could not initialize Bukkit datapack", ex); ++ } ++ AtomicReference worldLoader = new AtomicReference<>(); ++ // CraftBukkit end + + WorldStem worldstem; + +@@ -185,6 +233,7 @@ + + worldstem = (WorldStem) SystemUtils.blockUntilDone((executor) -> { + return WorldLoader.load(worldloader_c, (worldloader_a) -> { ++ worldLoader.set(worldloader_a); // CraftBukkit + IRegistry iregistry = worldloader_a.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM); + + if (dynamic1 != null) { +@@ -197,7 +246,7 @@ + WorldOptions worldoptions; + WorldDimensions worlddimensions; + +- if (optionset.has(optionspec2)) { ++ if (optionset.has("demo")) { // CraftBukkit + worldsettings = MinecraftServer.DEMO_SETTINGS; + worldoptions = WorldOptions.DEMO_OPTIONS; + worlddimensions = WorldPresets.createNormalWorldDimensions(worldloader_a.datapackWorldgen()); +@@ -205,7 +254,7 @@ + DedicatedServerProperties dedicatedserverproperties = dedicatedserversettings.getProperties(); + + worldsettings = new WorldSettings(dedicatedserverproperties.levelName, dedicatedserverproperties.gamemode, dedicatedserverproperties.hardcore, dedicatedserverproperties.difficulty, false, new GameRules(), worldloader_a.dataConfiguration()); +- worldoptions = optionset.has(optionspec3) ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions; ++ worldoptions = optionset.has("bonusChest") ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions; // CraftBukkit + worlddimensions = dedicatedserverproperties.createDimensions(worldloader_a.datapackWorldgen()); + } + +@@ -221,6 +270,7 @@ + return; + } + ++ /* + IRegistryCustom.Dimension iregistrycustom_dimension = worldstem.registries().compositeAccess(); + + if (optionset.has(optionspec4)) { +@@ -232,20 +282,31 @@ + SaveData savedata = worldstem.worldData(); + + convertable_conversionsession.saveDataTag(iregistrycustom_dimension, savedata); ++ */ + final DedicatedServer dedicatedserver = (DedicatedServer) MinecraftServer.spin((thread) -> { +- DedicatedServer dedicatedserver1 = new DedicatedServer(thread, convertable_conversionsession, resourcepackrepository, worldstem, dedicatedserversettings, DataConverterRegistry.getDataFixer(), services, WorldLoadListenerLogger::new); ++ DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, worldLoader.get(), thread, convertable_conversionsession, resourcepackrepository, worldstem, dedicatedserversettings, DataConverterRegistry.getDataFixer(), services, WorldLoadListenerLogger::new); + ++ /* + dedicatedserver1.setPort((Integer) optionset.valueOf(optionspec10)); + dedicatedserver1.setDemo(optionset.has(optionspec2)); + dedicatedserver1.setId((String) optionset.valueOf(optionspec11)); +- boolean flag1 = !optionset.has(optionspec) && !optionset.valuesOf(nonoptionargumentspec).contains("nogui"); ++ */ ++ boolean flag1 = !optionset.has("nogui") && !optionset.nonOptionArguments().contains("nogui"); + + if (flag1 && !GraphicsEnvironment.isHeadless()) { + dedicatedserver1.showGui(); + } + ++ if (optionset.has("port")) { ++ int port = (Integer) optionset.valueOf("port"); ++ if (port > 0) { ++ dedicatedserver1.setPort(port); ++ } ++ } ++ + return dedicatedserver1; + }); ++ /* CraftBukkit start + Thread thread = new Thread("Server Shutdown Thread") { + public void run() { + dedicatedserver.halt(true); +@@ -254,6 +315,7 @@ + + thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(Main.LOGGER)); + Runtime.getRuntime().addShutdownHook(thread); ++ */ // CraftBukkit end + } catch (Exception exception1) { + Main.LOGGER.error(LogUtils.FATAL_MARKER, "Failed to start the minecraft server", exception1); + } +@@ -290,7 +352,7 @@ + } + + public static void forceUpgrade(Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, boolean flag, BooleanSupplier booleansupplier, IRegistry iregistry) { +- Main.LOGGER.info("Forcing world upgrade!"); ++ Main.LOGGER.info("Forcing world upgrade! {}", convertable_conversionsession.getLevelId()); // CraftBukkit + WorldUpgrader worldupgrader = new WorldUpgrader(convertable_conversionsession, datafixer, iregistry, flag); + IChatBaseComponent ichatbasecomponent = null; + diff --git a/patch-remap/og/net/minecraft/server/MinecraftServer.patch b/patch-remap/og/net/minecraft/server/MinecraftServer.patch new file mode 100644 index 0000000000..e9eb891bdf --- /dev/null +++ b/patch-remap/og/net/minecraft/server/MinecraftServer.patch @@ -0,0 +1,768 @@ +--- a/net/minecraft/server/MinecraftServer.java ++++ b/net/minecraft/server/MinecraftServer.java +@@ -165,13 +165,36 @@ + import net.minecraft.world.phys.Vec3D; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.mojang.serialization.Dynamic; ++import com.mojang.serialization.Lifecycle; ++import java.util.Random; ++import jline.console.ConsoleReader; ++import joptsimple.OptionSet; ++import net.minecraft.nbt.NbtException; ++import net.minecraft.nbt.ReportedNbtException; ++import net.minecraft.server.dedicated.DedicatedServer; ++import net.minecraft.server.dedicated.DedicatedServerProperties; ++import net.minecraft.util.datafix.DataConverterRegistry; ++import net.minecraft.world.level.levelgen.WorldDimensions; ++import net.minecraft.world.level.levelgen.presets.WorldPresets; ++import net.minecraft.world.level.storage.LevelDataAndDimensions; ++import net.minecraft.world.level.storage.WorldDataServer; ++import net.minecraft.world.level.storage.WorldInfo; ++import net.minecraft.world.level.validation.ContentValidationException; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.Main; ++import org.bukkit.event.server.ServerLoadEvent; ++// CraftBukkit end ++ + public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant implements ServerInfo, ICommandListener, AutoCloseable { + + public static final Logger LOGGER = LogUtils.getLogger(); + public static final String VANILLA_BRAND = "vanilla"; + private static final float AVERAGE_TICK_TIME_SMOOTHING = 0.8F; + private static final int TICK_STATS_SPAN = 100; +- private static final long OVERLOADED_THRESHOLD_NANOS = 20L * TimeRange.NANOSECONDS_PER_SECOND / 20L; ++ private static final long OVERLOADED_THRESHOLD_NANOS = 30L * TimeRange.NANOSECONDS_PER_SECOND / 20L; // CraftBukkit + private static final int OVERLOADED_TICKS_THRESHOLD = 20; + private static final long OVERLOADED_WARNING_INTERVAL_NANOS = 10L * TimeRange.NANOSECONDS_PER_SECOND; + private static final int OVERLOADED_TICKS_WARNING_INTERVAL = 100; +@@ -254,6 +277,19 @@ + protected SaveData worldData; + private volatile boolean isSaving; + ++ // CraftBukkit start ++ public final WorldLoader.a worldLoader; ++ public org.bukkit.craftbukkit.CraftServer server; ++ public OptionSet options; ++ public org.bukkit.command.ConsoleCommandSender console; ++ public ConsoleReader reader; ++ public static int currentTick = (int) (System.currentTimeMillis() / 50); ++ public java.util.Queue processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); ++ public int autosavePeriod; ++ public CommandDispatcher vanillaCommandDispatcher; ++ private boolean forceTicks; ++ // CraftBukkit end ++ + public static S spin(Function function) { + AtomicReference atomicreference = new AtomicReference(); + Thread thread = new Thread(() -> { +@@ -267,14 +303,14 @@ + thread.setPriority(8); + } + +- S s0 = (MinecraftServer) function.apply(thread); ++ S s0 = function.apply(thread); // CraftBukkit - decompile error + + atomicreference.set(s0); + thread.start(); + return s0; + } + +- public MinecraftServer(Thread thread, Convertable.ConversionSession convertable_conversionsession, ResourcePackRepository resourcepackrepository, WorldStem worldstem, Proxy proxy, DataFixer datafixer, Services services, WorldLoadListenerFactory worldloadlistenerfactory) { ++ public MinecraftServer(OptionSet options, WorldLoader.a worldLoader, Thread thread, Convertable.ConversionSession convertable_conversionsession, ResourcePackRepository resourcepackrepository, WorldStem worldstem, Proxy proxy, DataFixer datafixer, Services services, WorldLoadListenerFactory worldloadlistenerfactory) { + super("Server"); + this.metricsRecorder = InactiveMetricsRecorder.INSTANCE; + this.profiler = this.metricsRecorder.getProfiler(); +@@ -295,7 +331,7 @@ + this.customBossEvents = new BossBattleCustomData(); + this.registries = worldstem.registries(); + this.worldData = worldstem.worldData(); +- if (!this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM).containsKey(WorldDimension.OVERWORLD)) { ++ if (false && !this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM).containsKey(WorldDimension.OVERWORLD)) { // CraftBukkit - initialised later + throw new IllegalStateException("Missing Overworld dimension data"); + } else { + this.proxy = proxy; +@@ -319,6 +355,33 @@ + this.serverThread = thread; + this.executor = SystemUtils.backgroundExecutor(); + } ++ // CraftBukkit start ++ this.options = options; ++ this.worldLoader = worldLoader; ++ this.vanillaCommandDispatcher = worldstem.dataPackResources().commands; // CraftBukkit ++ // Try to see if we're actually running in a terminal, disable jline if not ++ if (System.console() == null && System.getProperty("jline.terminal") == null) { ++ System.setProperty("jline.terminal", "jline.UnsupportedTerminal"); ++ Main.useJline = false; ++ } ++ ++ try { ++ reader = new ConsoleReader(System.in, System.out); ++ reader.setExpandEvents(false); // Avoid parsing exceptions for uncommonly used event designators ++ } catch (Throwable e) { ++ try { ++ // Try again with jline disabled for Windows users without C++ 2008 Redistributable ++ System.setProperty("jline.terminal", "jline.UnsupportedTerminal"); ++ System.setProperty("user.language", "en"); ++ Main.useJline = false; ++ reader = new ConsoleReader(System.in, System.out); ++ reader.setExpandEvents(false); ++ } catch (IOException ex) { ++ LOGGER.warn((String) null, ex); ++ } ++ } ++ Runtime.getRuntime().addShutdownHook(new org.bukkit.craftbukkit.util.ServerShutdownThread(this)); ++ // CraftBukkit end + } + + private void readScoreboard(WorldPersistentData worldpersistentdata) { +@@ -327,7 +390,7 @@ + + protected abstract boolean initServer() throws IOException; + +- protected void loadLevel() { ++ protected void loadLevel(String s) { // CraftBukkit + if (!JvmProfiler.INSTANCE.isRunning()) { + ; + } +@@ -335,12 +398,8 @@ + boolean flag = false; + ProfiledDuration profiledduration = JvmProfiler.INSTANCE.onWorldLoadedStarted(); + +- this.worldData.setModdedInfo(this.getServerModName(), this.getModdedStatus().shouldReportAsModified()); +- WorldLoadListener worldloadlistener = this.progressListenerFactory.create(11); ++ loadWorld0(s); // CraftBukkit + +- this.createLevels(worldloadlistener); +- this.forceDifficulty(); +- this.prepareLevels(worldloadlistener); + if (profiledduration != null) { + profiledduration.finish(); + } +@@ -357,23 +416,216 @@ + + protected void forceDifficulty() {} + +- protected void createLevels(WorldLoadListener worldloadlistener) { +- IWorldDataServer iworlddataserver = this.worldData.overworldData(); +- boolean flag = this.worldData.isDebugWorld(); +- IRegistry iregistry = this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM); +- WorldOptions worldoptions = this.worldData.worldGenOptions(); +- long i = worldoptions.seed(); +- long j = BiomeManager.obfuscateSeed(i); +- List list = ImmutableList.of(new MobSpawnerPhantom(), new MobSpawnerPatrol(), new MobSpawnerCat(), new VillageSiege(), new MobSpawnerTrader(iworlddataserver)); +- WorldDimension worlddimension = (WorldDimension) iregistry.get(WorldDimension.OVERWORLD); +- WorldServer worldserver = new WorldServer(this, this.executor, this.storageSource, iworlddataserver, World.OVERWORLD, worlddimension, worldloadlistener, flag, j, list, true, (RandomSequences) null); ++ // CraftBukkit start ++ private void loadWorld0(String s) { ++ Convertable.ConversionSession worldSession = this.storageSource; + +- this.levels.put(World.OVERWORLD, worldserver); +- WorldPersistentData worldpersistentdata = worldserver.getDataStorage(); ++ IRegistry dimensions = this.registries.compositeAccess().registryOrThrow(Registries.LEVEL_STEM); ++ for (WorldDimension worldDimension : dimensions) { ++ ResourceKey dimensionKey = dimensions.getResourceKey(worldDimension).get(); + +- this.readScoreboard(worldpersistentdata); +- this.commandStorage = new PersistentCommandStorage(worldpersistentdata); ++ WorldServer world; ++ int dimension = 0; ++ ++ if (dimensionKey == WorldDimension.NETHER) { ++ if (isNetherEnabled()) { ++ dimension = -1; ++ } else { ++ continue; ++ } ++ } else if (dimensionKey == WorldDimension.END) { ++ if (server.getAllowEnd()) { ++ dimension = 1; ++ } else { ++ continue; ++ } ++ } else if (dimensionKey != WorldDimension.OVERWORLD) { ++ dimension = -999; ++ } ++ ++ String worldType = (dimension == -999) ? dimensionKey.location().getNamespace() + "_" + dimensionKey.location().getPath() : org.bukkit.World.Environment.getEnvironment(dimension).toString().toLowerCase(); ++ String name = (dimensionKey == WorldDimension.OVERWORLD) ? s : s + "_" + worldType; ++ if (dimension != 0) { ++ File newWorld = Convertable.getStorageFolder(new File(name).toPath(), dimensionKey).toFile(); ++ File oldWorld = Convertable.getStorageFolder(new File(s).toPath(), dimensionKey).toFile(); ++ File oldLevelDat = new File(new File(s), "level.dat"); // The data folders exist on first run as they are created in the PersistentCollection constructor above, but the level.dat won't ++ ++ if (!newWorld.isDirectory() && oldWorld.isDirectory() && oldLevelDat.isFile()) { ++ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder required ----"); ++ MinecraftServer.LOGGER.info("Unfortunately due to the way that Minecraft implemented multiworld support in 1.6, Bukkit requires that you move your " + worldType + " folder to a new location in order to operate correctly."); ++ MinecraftServer.LOGGER.info("We will move this folder for you, but it will mean that you need to move it back should you wish to stop using Bukkit in the future."); ++ MinecraftServer.LOGGER.info("Attempting to move " + oldWorld + " to " + newWorld + "..."); ++ ++ if (newWorld.exists()) { ++ MinecraftServer.LOGGER.warn("A file or folder already exists at " + newWorld + "!"); ++ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder failed ----"); ++ } else if (newWorld.getParentFile().mkdirs()) { ++ if (oldWorld.renameTo(newWorld)) { ++ MinecraftServer.LOGGER.info("Success! To restore " + worldType + " in the future, simply move " + newWorld + " to " + oldWorld); ++ // Migrate world data too. ++ try { ++ com.google.common.io.Files.copy(oldLevelDat, new File(new File(name), "level.dat")); ++ org.apache.commons.io.FileUtils.copyDirectory(new File(new File(s), "data"), new File(new File(name), "data")); ++ } catch (IOException exception) { ++ MinecraftServer.LOGGER.warn("Unable to migrate world data."); ++ } ++ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder complete ----"); ++ } else { ++ MinecraftServer.LOGGER.warn("Could not move folder " + oldWorld + " to " + newWorld + "!"); ++ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder failed ----"); ++ } ++ } else { ++ MinecraftServer.LOGGER.warn("Could not create path for " + newWorld + "!"); ++ MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder failed ----"); ++ } ++ } ++ ++ try { ++ worldSession = Convertable.createDefault(server.getWorldContainer().toPath()).validateAndCreateAccess(name, dimensionKey); ++ } catch (IOException | ContentValidationException ex) { ++ throw new RuntimeException(ex); ++ } ++ } ++ ++ Dynamic dynamic; ++ if (worldSession.hasWorldData()) { ++ WorldInfo worldinfo; ++ ++ try { ++ dynamic = worldSession.getDataTag(); ++ worldinfo = worldSession.getSummary(dynamic); ++ } catch (NbtException | ReportedNbtException | IOException ioexception) { ++ Convertable.b convertable_b = worldSession.getLevelDirectory(); ++ ++ MinecraftServer.LOGGER.warn("Failed to load world data from {}", convertable_b.dataFile(), ioexception); ++ MinecraftServer.LOGGER.info("Attempting to use fallback"); ++ ++ try { ++ dynamic = worldSession.getDataTagFallback(); ++ worldinfo = worldSession.getSummary(dynamic); ++ } catch (NbtException | ReportedNbtException | IOException ioexception1) { ++ MinecraftServer.LOGGER.error("Failed to load world data from {}", convertable_b.oldDataFile(), ioexception1); ++ MinecraftServer.LOGGER.error("Failed to load world data from {} and {}. World files may be corrupted. Shutting down.", convertable_b.dataFile(), convertable_b.oldDataFile()); ++ return; ++ } ++ ++ worldSession.restoreLevelDataFromOld(); ++ } ++ ++ if (worldinfo.requiresManualConversion()) { ++ MinecraftServer.LOGGER.info("This world must be opened in an older version (like 1.6.4) to be safely converted"); ++ return; ++ } ++ ++ if (!worldinfo.isCompatible()) { ++ MinecraftServer.LOGGER.info("This world was created by an incompatible version."); ++ return; ++ } ++ } else { ++ dynamic = null; ++ } ++ ++ org.bukkit.generator.ChunkGenerator gen = this.server.getGenerator(name); ++ org.bukkit.generator.BiomeProvider biomeProvider = this.server.getBiomeProvider(name); ++ ++ WorldDataServer worlddata; ++ WorldLoader.a worldloader_a = this.worldLoader; ++ IRegistry iregistry = worldloader_a.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM); ++ if (dynamic != null) { ++ LevelDataAndDimensions leveldataanddimensions = Convertable.getLevelDataAndDimensions(dynamic, worldloader_a.dataConfiguration(), iregistry, worldloader_a.datapackWorldgen()); ++ ++ worlddata = (WorldDataServer) leveldataanddimensions.worldData(); ++ } else { ++ WorldSettings worldsettings; ++ WorldOptions worldoptions; ++ WorldDimensions worlddimensions; ++ ++ if (this.isDemo()) { ++ worldsettings = MinecraftServer.DEMO_SETTINGS; ++ worldoptions = WorldOptions.DEMO_OPTIONS; ++ worlddimensions = WorldPresets.createNormalWorldDimensions(worldloader_a.datapackWorldgen()); ++ } else { ++ DedicatedServerProperties dedicatedserverproperties = ((DedicatedServer) this).getProperties(); ++ ++ worldsettings = new WorldSettings(dedicatedserverproperties.levelName, dedicatedserverproperties.gamemode, dedicatedserverproperties.hardcore, dedicatedserverproperties.difficulty, false, new GameRules(), worldloader_a.dataConfiguration()); ++ worldoptions = options.has("bonusChest") ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions; ++ worlddimensions = dedicatedserverproperties.createDimensions(worldloader_a.datapackWorldgen()); ++ } ++ ++ WorldDimensions.b worlddimensions_b = worlddimensions.bake(iregistry); ++ Lifecycle lifecycle = worlddimensions_b.lifecycle().add(worldloader_a.datapackWorldgen().allRegistriesLifecycle()); ++ ++ worlddata = new WorldDataServer(worldsettings, worldoptions, worlddimensions_b.specialWorldProperty(), lifecycle); ++ } ++ worlddata.checkName(name); // CraftBukkit - Migration did not rewrite the level.dat; This forces 1.8 to take the last loaded world as respawn (in this case the end) ++ if (options.has("forceUpgrade")) { ++ net.minecraft.server.Main.forceUpgrade(worldSession, DataConverterRegistry.getDataFixer(), options.has("eraseCache"), () -> { ++ return true; ++ }, dimensions); ++ } ++ ++ WorldDataServer iworlddataserver = worlddata; ++ boolean flag = worlddata.isDebugWorld(); ++ WorldOptions worldoptions = worlddata.worldGenOptions(); ++ long i = worldoptions.seed(); ++ long j = BiomeManager.obfuscateSeed(i); ++ List list = ImmutableList.of(new MobSpawnerPhantom(), new MobSpawnerPatrol(), new MobSpawnerCat(), new VillageSiege(), new MobSpawnerTrader(iworlddataserver)); ++ WorldDimension worlddimension = (WorldDimension) dimensions.get(dimensionKey); ++ ++ org.bukkit.generator.WorldInfo worldInfo = new org.bukkit.craftbukkit.generator.CraftWorldInfo(iworlddataserver, worldSession, org.bukkit.World.Environment.getEnvironment(dimension), worlddimension.type().value()); ++ if (biomeProvider == null && gen != null) { ++ biomeProvider = gen.getDefaultBiomeProvider(worldInfo); ++ } ++ ++ ResourceKey worldKey = ResourceKey.create(Registries.DIMENSION, dimensionKey.location()); ++ ++ if (dimensionKey == WorldDimension.OVERWORLD) { ++ this.worldData = worlddata; ++ this.worldData.setGameType(((DedicatedServer) this).getProperties().gamemode); // From DedicatedServer.init ++ ++ WorldLoadListener worldloadlistener = this.progressListenerFactory.create(11); ++ ++ world = new WorldServer(this, this.executor, worldSession, iworlddataserver, worldKey, worlddimension, worldloadlistener, flag, j, list, true, (RandomSequences) null, org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider); ++ WorldPersistentData worldpersistentdata = world.getDataStorage(); ++ this.readScoreboard(worldpersistentdata); ++ this.server.scoreboardManager = new org.bukkit.craftbukkit.scoreboard.CraftScoreboardManager(this, world.getScoreboard()); ++ this.commandStorage = new PersistentCommandStorage(worldpersistentdata); ++ } else { ++ WorldLoadListener worldloadlistener = this.progressListenerFactory.create(11); ++ world = new WorldServer(this, this.executor, worldSession, iworlddataserver, worldKey, worlddimension, worldloadlistener, flag, j, ImmutableList.of(), true, this.overworld().getRandomSequences(), org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider); ++ } ++ ++ worlddata.setModdedInfo(this.getServerModName(), this.getModdedStatus().shouldReportAsModified()); ++ this.initWorld(world, worlddata, worldData, worldoptions); ++ ++ this.addLevel(world); ++ this.getPlayerList().addWorldborderListener(world); ++ ++ if (worlddata.getCustomBossEvents() != null) { ++ this.getCustomBossEvents().load(worlddata.getCustomBossEvents()); ++ } ++ } ++ this.forceDifficulty(); ++ for (WorldServer worldserver : this.getAllLevels()) { ++ this.prepareLevels(worldserver.getChunkSource().chunkMap.progressListener, worldserver); ++ worldserver.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API ++ this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldLoadEvent(worldserver.getWorld())); ++ } ++ ++ this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.POSTWORLD); ++ this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP)); ++ this.connection.acceptConnections(); ++ } ++ ++ public void initWorld(WorldServer worldserver, IWorldDataServer iworlddataserver, SaveData saveData, WorldOptions worldoptions) { ++ boolean flag = saveData.isDebugWorld(); ++ // CraftBukkit start ++ if (worldserver.generator != null) { ++ worldserver.getWorld().getPopulators().addAll(worldserver.generator.getDefaultPopulators(worldserver.getWorld())); ++ } + WorldBorder worldborder = worldserver.getWorldBorder(); ++ worldborder.applySettings(iworlddataserver.getWorldBorder()); // CraftBukkit - move up so that WorldBorder is set during WorldInitEvent ++ this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldInitEvent(worldserver.getWorld())); // CraftBukkit - SPIGOT-5569: Call WorldInitEvent before any chunks are generated + + if (!iworlddataserver.isInitialized()) { + try { +@@ -397,30 +649,8 @@ + iworlddataserver.setInitialized(true); + } + +- this.getPlayerList().addWorldborderListener(worldserver); +- if (this.worldData.getCustomBossEvents() != null) { +- this.getCustomBossEvents().load(this.worldData.getCustomBossEvents()); +- } +- +- RandomSequences randomsequences = worldserver.getRandomSequences(); +- Iterator iterator = iregistry.entrySet().iterator(); +- +- while (iterator.hasNext()) { +- Entry, WorldDimension> entry = (Entry) iterator.next(); +- ResourceKey resourcekey = (ResourceKey) entry.getKey(); +- +- if (resourcekey != WorldDimension.OVERWORLD) { +- ResourceKey resourcekey1 = ResourceKey.create(Registries.DIMENSION, resourcekey.location()); +- SecondaryWorldData secondaryworlddata = new SecondaryWorldData(this.worldData, iworlddataserver); +- WorldServer worldserver1 = new WorldServer(this, this.executor, this.storageSource, secondaryworlddata, resourcekey1, (WorldDimension) entry.getValue(), worldloadlistener, flag, j, ImmutableList.of(), false, randomsequences); +- +- worldborder.addListener(new IWorldBorderListener.a(worldserver1.getWorldBorder())); +- this.levels.put(resourcekey1, worldserver1); +- } +- } +- +- worldborder.applySettings(iworlddataserver.getWorldBorder()); + } ++ // CraftBukkit end + + private static void setInitialSpawn(WorldServer worldserver, IWorldDataServer iworlddataserver, boolean flag, boolean flag1) { + if (flag1) { +@@ -428,6 +658,21 @@ + } else { + ChunkProviderServer chunkproviderserver = worldserver.getChunkSource(); + ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(chunkproviderserver.randomState().sampler().findSpawnPosition()); ++ // CraftBukkit start ++ if (worldserver.generator != null) { ++ Random rand = new Random(worldserver.getSeed()); ++ org.bukkit.Location spawn = worldserver.generator.getFixedSpawnLocation(worldserver.getWorld(), rand); ++ ++ if (spawn != null) { ++ if (spawn.getWorld() != worldserver.getWorld()) { ++ throw new IllegalStateException("Cannot set spawn point for " + iworlddataserver.getLevelName() + " to be in another world (" + spawn.getWorld().getName() + ")"); ++ } else { ++ iworlddataserver.setSpawn(new BlockPosition(spawn.getBlockX(), spawn.getBlockY(), spawn.getBlockZ()), spawn.getYaw()); ++ return; ++ } ++ } ++ } ++ // CraftBukkit end + int i = chunkproviderserver.getGenerator().getSpawnHeight(worldserver); + + if (i < worldserver.getMinBuildHeight()) { +@@ -487,8 +732,11 @@ + iworlddataserver.setGameType(EnumGamemode.SPECTATOR); + } + +- public void prepareLevels(WorldLoadListener worldloadlistener) { +- WorldServer worldserver = this.overworld(); ++ // CraftBukkit start ++ public void prepareLevels(WorldLoadListener worldloadlistener, WorldServer worldserver) { ++ // WorldServer worldserver = this.overworld(); ++ this.forceTicks = true; ++ // CraftBukkit end + + MinecraftServer.LOGGER.info("Preparing start region for dimension {}", worldserver.dimension().location()); + BlockPosition blockposition = worldserver.getSharedSpawnPos(); +@@ -497,19 +745,23 @@ + ChunkProviderServer chunkproviderserver = worldserver.getChunkSource(); + + this.nextTickTimeNanos = SystemUtils.getNanos(); +- chunkproviderserver.addRegionTicket(TicketType.START, new ChunkCoordIntPair(blockposition), 11, Unit.INSTANCE); ++ // CraftBukkit start ++ if (worldserver.getWorld().getKeepSpawnInMemory()) { ++ chunkproviderserver.addRegionTicket(TicketType.START, new ChunkCoordIntPair(blockposition), 11, Unit.INSTANCE); + +- while (chunkproviderserver.getTickingGenerated() != 441) { +- this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; +- this.waitUntilNextTick(); ++ while (chunkproviderserver.getTickingGenerated() != 441) { ++ // this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; ++ this.executeModerately(); ++ } + } + +- this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; +- this.waitUntilNextTick(); +- Iterator iterator = this.levels.values().iterator(); ++ // this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; ++ this.executeModerately(); ++ // Iterator iterator = this.levels.values().iterator(); + +- while (iterator.hasNext()) { +- WorldServer worldserver1 = (WorldServer) iterator.next(); ++ if (true) { ++ WorldServer worldserver1 = worldserver; ++ // CraftBukkit end + ForcedChunk forcedchunk = (ForcedChunk) worldserver1.getDataStorage().get(ForcedChunk.factory(), "chunks"); + + if (forcedchunk != null) { +@@ -524,10 +776,17 @@ + } + } + +- this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; +- this.waitUntilNextTick(); ++ // CraftBukkit start ++ // this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; ++ this.executeModerately(); ++ // CraftBukkit end + worldloadlistener.stop(); +- this.updateMobSpawningFlags(); ++ // CraftBukkit start ++ // this.updateMobSpawningFlags(); ++ worldserver.setSpawnSettings(this.isSpawningMonsters(), this.isSpawningAnimals()); ++ ++ this.forceTicks = false; ++ // CraftBukkit end + } + + public EnumGamemode getDefaultGameType() { +@@ -557,12 +816,16 @@ + worldserver.save((IProgressUpdate) null, flag1, worldserver.noSave && !flag2); + } + ++ // CraftBukkit start - moved to WorldServer.save ++ /* + WorldServer worldserver1 = this.overworld(); + IWorldDataServer iworlddataserver = this.worldData.overworldData(); + + iworlddataserver.setWorldBorder(worldserver1.getWorldBorder().createSettings()); + this.worldData.setCustomBossEvents(this.getCustomBossEvents().save()); + this.storageSource.saveDataTag(this.registryAccess(), this.worldData, this.getPlayerList().getSingleplayerData()); ++ */ ++ // CraftBukkit end + if (flag1) { + Iterator iterator1 = this.getAllLevels().iterator(); + +@@ -597,18 +860,40 @@ + this.stopServer(); + } + ++ // CraftBukkit start ++ private boolean hasStopped = false; ++ private final Object stopLock = new Object(); ++ public final boolean hasStopped() { ++ synchronized (stopLock) { ++ return hasStopped; ++ } ++ } ++ // CraftBukkit end ++ + public void stopServer() { ++ // CraftBukkit start - prevent double stopping on multiple threads ++ synchronized(stopLock) { ++ if (hasStopped) return; ++ hasStopped = true; ++ } ++ // CraftBukkit end + if (this.metricsRecorder.isRecording()) { + this.cancelRecordingMetrics(); + } + + MinecraftServer.LOGGER.info("Stopping server"); ++ // CraftBukkit start ++ if (this.server != null) { ++ this.server.disablePlugins(); ++ } ++ // CraftBukkit end + this.getConnection().stop(); + this.isSaving = true; + if (this.playerList != null) { + MinecraftServer.LOGGER.info("Saving players"); + this.playerList.saveAll(); + this.playerList.removeAll(); ++ try { Thread.sleep(100); } catch (InterruptedException ex) {} // CraftBukkit - SPIGOT-625 - give server at least a chance to send packets + } + + MinecraftServer.LOGGER.info("Saving worlds"); +@@ -696,7 +981,7 @@ + } + + this.nextTickTimeNanos = SystemUtils.getNanos(); +- this.statusIcon = (ServerPing.a) this.loadStatusIcon().orElse((Object) null); ++ this.statusIcon = (ServerPing.a) this.loadStatusIcon().orElse(null); // CraftBukkit - decompile error + this.status = this.buildServerStatus(); + + while (this.running) { +@@ -713,6 +998,7 @@ + if (j > MinecraftServer.OVERLOADED_THRESHOLD_NANOS + 20L * i && this.nextTickTimeNanos - this.lastOverloadWarningNanos >= MinecraftServer.OVERLOADED_WARNING_INTERVAL_NANOS + 100L * i) { + long k = j / i; + ++ if (server.getWarnOnOverload()) // CraftBukkit + MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", j / TimeRange.NANOSECONDS_PER_MILLISECOND, k); + this.nextTickTimeNanos += k * i; + this.lastOverloadWarningNanos = this.nextTickTimeNanos; +@@ -726,6 +1012,7 @@ + this.debugCommandProfiler = new MinecraftServer.TimeProfiler(SystemUtils.getNanos(), this.tickCount); + } + ++ MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit + this.nextTickTimeNanos += i; + this.startMetricsRecordingTick(); + this.profiler.push("tick"); +@@ -770,6 +1057,12 @@ + this.services.profileCache().clearExecutor(); + } + ++ // CraftBukkit start - Restore terminal to original settings ++ try { ++ reader.getTerminal().restore(); ++ } catch (Exception ignored) { ++ } ++ // CraftBukkit end + this.onServerExit(); + } + +@@ -803,7 +1096,14 @@ + } + + private boolean haveTime() { +- return this.runningTask() || SystemUtils.getNanos() < (this.mayHaveDelayedTasks ? this.delayedTasksMaxNextTickTimeNanos : this.nextTickTimeNanos); ++ // CraftBukkit start ++ return this.forceTicks || this.runningTask() || SystemUtils.getNanos() < (this.mayHaveDelayedTasks ? this.delayedTasksMaxNextTickTimeNanos : this.nextTickTimeNanos); ++ } ++ ++ private void executeModerately() { ++ this.runAllTasks(); ++ java.util.concurrent.locks.LockSupport.parkNanos("executing tasks", 1000L); ++ // CraftBukkit end + } + + protected void waitUntilNextTick() { +@@ -850,7 +1150,7 @@ + } + } + +- protected void doRunTask(TickTask ticktask) { ++ public void doRunTask(TickTask ticktask) { // CraftBukkit - decompile error + this.getProfiler().incrementCounter("runTask"); + super.doRunTask(ticktask); + } +@@ -909,8 +1209,10 @@ + } + + --this.ticksUntilAutosave; +- if (this.ticksUntilAutosave <= 0) { +- this.ticksUntilAutosave = this.computeNextAutosaveInterval(); ++ // CraftBukkit start ++ if (this.autosavePeriod > 0 && this.ticksUntilAutosave <= 0) { ++ this.ticksUntilAutosave = this.autosavePeriod; ++ // CraftBukkit end + MinecraftServer.LOGGER.debug("Autosave started"); + this.profiler.push("save"); + this.saveEverything(true, false, false); +@@ -991,22 +1293,39 @@ + this.getPlayerList().getPlayers().forEach((entityplayer) -> { + entityplayer.connection.suspendFlushing(); + }); ++ this.server.getScheduler().mainThreadHeartbeat(this.tickCount); // CraftBukkit + this.profiler.push("commandFunctions"); + this.getFunctions().tick(); + this.profiler.popPush("levels"); + Iterator iterator = this.getAllLevels().iterator(); + ++ // CraftBukkit start ++ // Run tasks that are waiting on processing ++ while (!processQueue.isEmpty()) { ++ processQueue.remove().run(); ++ } ++ ++ // Send time updates to everyone, it will get the right time from the world the player is in. ++ if (this.tickCount % 20 == 0) { ++ for (int i = 0; i < this.getPlayerList().players.size(); ++i) { ++ EntityPlayer entityplayer = (EntityPlayer) this.getPlayerList().players.get(i); ++ entityplayer.connection.send(new PacketPlayOutUpdateTime(entityplayer.level().getGameTime(), entityplayer.getPlayerTime(), entityplayer.level().getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); // Add support for per player time ++ } ++ } ++ + while (iterator.hasNext()) { + WorldServer worldserver = (WorldServer) iterator.next(); + + this.profiler.push(() -> { + return worldserver + " " + worldserver.dimension().location(); + }); ++ /* Drop global time updates + if (this.tickCount % 20 == 0) { + this.profiler.push("timeSync"); + this.synchronizeTime(worldserver); + this.profiler.pop(); + } ++ // CraftBukkit end */ + + this.profiler.push("tick"); + +@@ -1096,6 +1415,22 @@ + return (WorldServer) this.levels.get(resourcekey); + } + ++ // CraftBukkit start ++ public void addLevel(WorldServer level) { ++ Map, WorldServer> oldLevels = this.levels; ++ Map, WorldServer> newLevels = Maps.newLinkedHashMap(oldLevels); ++ newLevels.put(level.dimension(), level); ++ this.levels = Collections.unmodifiableMap(newLevels); ++ } ++ ++ public void removeLevel(WorldServer level) { ++ Map, WorldServer> oldLevels = this.levels; ++ Map, WorldServer> newLevels = Maps.newLinkedHashMap(oldLevels); ++ newLevels.remove(level.dimension()); ++ this.levels = Collections.unmodifiableMap(newLevels); ++ } ++ // CraftBukkit end ++ + public Set> levelKeys() { + return this.levels.keySet(); + } +@@ -1125,7 +1460,7 @@ + + @DontObfuscate + public String getServerModName() { +- return "vanilla"; ++ return server.getName(); // CraftBukkit - cb > vanilla! + } + + public SystemReport fillSystemReport(SystemReport systemreport) { +@@ -1466,11 +1801,11 @@ + public CompletableFuture reloadResources(Collection collection) { + IRegistryCustom.Dimension iregistrycustom_dimension = this.registries.getAccessForLoading(RegistryLayer.RELOADABLE); + CompletableFuture completablefuture = CompletableFuture.supplyAsync(() -> { +- Stream stream = collection.stream(); ++ Stream stream = collection.stream(); // CraftBukkit - decompile error + ResourcePackRepository resourcepackrepository = this.packRepository; + + Objects.requireNonNull(this.packRepository); +- return (ImmutableList) stream.map(resourcepackrepository::getPack).filter(Objects::nonNull).map(ResourcePackLoader::open).collect(ImmutableList.toImmutableList()); ++ return stream.map(resourcepackrepository::getPack).filter(Objects::nonNull).map(ResourcePackLoader::open).collect(ImmutableList.toImmutableList()); // CraftBukkit - decompile error + }, this).thenCompose((immutablelist) -> { + ResourceManager resourcemanager = new ResourceManager(EnumResourcePackType.SERVER_DATA, immutablelist); + +@@ -1485,6 +1820,7 @@ + }).thenAcceptAsync((minecraftserver_reloadableresources) -> { + this.resources.close(); + this.resources = minecraftserver_reloadableresources; ++ this.server.syncCommands(); // SPIGOT-5884: Lost on reload + this.packRepository.setSelected(collection); + WorldDataConfiguration worlddataconfiguration = new WorldDataConfiguration(getSelectedPacks(this.packRepository), this.worldData.enabledFeatures()); + +@@ -1853,7 +2189,7 @@ + try { + label51: + { +- ArrayList arraylist; ++ ArrayList arraylist; // CraftBukkit - decompile error + + try { + arraylist = Lists.newArrayList(NativeModuleLister.listModules()); +@@ -1903,6 +2239,22 @@ + + } + ++ // CraftBukkit start ++ @Override ++ public boolean isSameThread() { ++ return super.isSameThread() || this.isStopped(); // CraftBukkit - MC-142590 ++ } ++ ++ public boolean isDebugging() { ++ return false; ++ } ++ ++ @Deprecated ++ public static MinecraftServer getServer() { ++ return (Bukkit.getServer() instanceof CraftServer) ? ((CraftServer) Bukkit.getServer()).getServer() : null; ++ } ++ // CraftBukkit end ++ + private void startMetricsRecordingTick() { + if (this.willStartRecordingMetrics) { + this.metricsRecorder = ActiveMetricsRecorder.createStarted(new ServerMetricsSamplersProvider(SystemUtils.timeSource, this.isDedicatedServer()), SystemUtils.timeSource, SystemUtils.ioPool(), new MetricsPersister("server"), this.onMetricsRecordingStopped, (path) -> { +@@ -2029,6 +2381,11 @@ + + } + ++ // CraftBukkit start ++ public final java.util.concurrent.ExecutorService chatExecutor = java.util.concurrent.Executors.newCachedThreadPool( ++ new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon(true).setNameFormat("Async Chat Thread - #%d").build()); ++ // CraftBukkit end ++ + public ChatDecorator getChatDecorator() { + return ChatDecorator.PLAIN; + } diff --git a/patch-remap/og/net/minecraft/server/ScoreboardServer.patch b/patch-remap/og/net/minecraft/server/ScoreboardServer.patch new file mode 100644 index 0000000000..5522befd5b --- /dev/null +++ b/patch-remap/og/net/minecraft/server/ScoreboardServer.patch @@ -0,0 +1,132 @@ +--- a/net/minecraft/server/ScoreboardServer.java ++++ b/net/minecraft/server/ScoreboardServer.java +@@ -40,7 +40,7 @@ + protected void onScoreChanged(ScoreHolder scoreholder, ScoreboardObjective scoreboardobjective, ScoreboardScore scoreboardscore) { + super.onScoreChanged(scoreholder, scoreboardobjective, scoreboardscore); + if (this.trackedObjectives.contains(scoreboardobjective)) { +- this.server.getPlayerList().broadcastAll(new PacketPlayOutScoreboardScore(scoreholder.getScoreboardName(), scoreboardobjective.getName(), scoreboardscore.value(), scoreboardscore.display(), scoreboardscore.numberFormat())); ++ this.broadcastAll(new PacketPlayOutScoreboardScore(scoreholder.getScoreboardName(), scoreboardobjective.getName(), scoreboardscore.value(), scoreboardscore.display(), scoreboardscore.numberFormat())); // CraftBukkit + } + + this.setDirty(); +@@ -55,7 +55,7 @@ + @Override + public void onPlayerRemoved(ScoreHolder scoreholder) { + super.onPlayerRemoved(scoreholder); +- this.server.getPlayerList().broadcastAll(new ClientboundResetScorePacket(scoreholder.getScoreboardName(), (String) null)); ++ this.broadcastAll(new ClientboundResetScorePacket(scoreholder.getScoreboardName(), (String) null)); // CraftBukkit + this.setDirty(); + } + +@@ -63,7 +63,7 @@ + public void onPlayerScoreRemoved(ScoreHolder scoreholder, ScoreboardObjective scoreboardobjective) { + super.onPlayerScoreRemoved(scoreholder, scoreboardobjective); + if (this.trackedObjectives.contains(scoreboardobjective)) { +- this.server.getPlayerList().broadcastAll(new ClientboundResetScorePacket(scoreholder.getScoreboardName(), scoreboardobjective.getName())); ++ this.broadcastAll(new ClientboundResetScorePacket(scoreholder.getScoreboardName(), scoreboardobjective.getName())); // CraftBukkit + } + + this.setDirty(); +@@ -76,7 +76,7 @@ + super.setDisplayObjective(displayslot, scoreboardobjective); + if (scoreboardobjective1 != scoreboardobjective && scoreboardobjective1 != null) { + if (this.getObjectiveDisplaySlotCount(scoreboardobjective1) > 0) { +- this.server.getPlayerList().broadcastAll(new PacketPlayOutScoreboardDisplayObjective(displayslot, scoreboardobjective)); ++ this.broadcastAll(new PacketPlayOutScoreboardDisplayObjective(displayslot, scoreboardobjective)); // CraftBukkit + } else { + this.stopTrackingObjective(scoreboardobjective1); + } +@@ -84,7 +84,7 @@ + + if (scoreboardobjective != null) { + if (this.trackedObjectives.contains(scoreboardobjective)) { +- this.server.getPlayerList().broadcastAll(new PacketPlayOutScoreboardDisplayObjective(displayslot, scoreboardobjective)); ++ this.broadcastAll(new PacketPlayOutScoreboardDisplayObjective(displayslot, scoreboardobjective)); // CraftBukkit + } else { + this.startTrackingObjective(scoreboardobjective); + } +@@ -96,7 +96,7 @@ + @Override + public boolean addPlayerToTeam(String s, ScoreboardTeam scoreboardteam) { + if (super.addPlayerToTeam(s, scoreboardteam)) { +- this.server.getPlayerList().broadcastAll(PacketPlayOutScoreboardTeam.createPlayerPacket(scoreboardteam, s, PacketPlayOutScoreboardTeam.a.ADD)); ++ this.broadcastAll(PacketPlayOutScoreboardTeam.createPlayerPacket(scoreboardteam, s, PacketPlayOutScoreboardTeam.a.ADD)); // CraftBukkit + this.setDirty(); + return true; + } else { +@@ -107,7 +107,7 @@ + @Override + public void removePlayerFromTeam(String s, ScoreboardTeam scoreboardteam) { + super.removePlayerFromTeam(s, scoreboardteam); +- this.server.getPlayerList().broadcastAll(PacketPlayOutScoreboardTeam.createPlayerPacket(scoreboardteam, s, PacketPlayOutScoreboardTeam.a.REMOVE)); ++ this.broadcastAll(PacketPlayOutScoreboardTeam.createPlayerPacket(scoreboardteam, s, PacketPlayOutScoreboardTeam.a.REMOVE)); // CraftBukkit + this.setDirty(); + } + +@@ -121,7 +121,7 @@ + public void onObjectiveChanged(ScoreboardObjective scoreboardobjective) { + super.onObjectiveChanged(scoreboardobjective); + if (this.trackedObjectives.contains(scoreboardobjective)) { +- this.server.getPlayerList().broadcastAll(new PacketPlayOutScoreboardObjective(scoreboardobjective, 2)); ++ this.broadcastAll(new PacketPlayOutScoreboardObjective(scoreboardobjective, 2)); // CraftBukkit + } + + this.setDirty(); +@@ -140,21 +140,21 @@ + @Override + public void onTeamAdded(ScoreboardTeam scoreboardteam) { + super.onTeamAdded(scoreboardteam); +- this.server.getPlayerList().broadcastAll(PacketPlayOutScoreboardTeam.createAddOrModifyPacket(scoreboardteam, true)); ++ this.broadcastAll(PacketPlayOutScoreboardTeam.createAddOrModifyPacket(scoreboardteam, true)); // CraftBukkit + this.setDirty(); + } + + @Override + public void onTeamChanged(ScoreboardTeam scoreboardteam) { + super.onTeamChanged(scoreboardteam); +- this.server.getPlayerList().broadcastAll(PacketPlayOutScoreboardTeam.createAddOrModifyPacket(scoreboardteam, false)); ++ this.broadcastAll(PacketPlayOutScoreboardTeam.createAddOrModifyPacket(scoreboardteam, false)); // CraftBukkit + this.setDirty(); + } + + @Override + public void onTeamRemoved(ScoreboardTeam scoreboardteam) { + super.onTeamRemoved(scoreboardteam); +- this.server.getPlayerList().broadcastAll(PacketPlayOutScoreboardTeam.createRemovePacket(scoreboardteam)); ++ this.broadcastAll(PacketPlayOutScoreboardTeam.createRemovePacket(scoreboardteam)); // CraftBukkit + this.setDirty(); + } + +@@ -205,6 +205,7 @@ + + while (iterator.hasNext()) { + EntityPlayer entityplayer = (EntityPlayer) iterator.next(); ++ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board + Iterator iterator1 = list.iterator(); + + while (iterator1.hasNext()) { +@@ -241,6 +242,7 @@ + + while (iterator.hasNext()) { + EntityPlayer entityplayer = (EntityPlayer) iterator.next(); ++ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board + Iterator iterator1 = list.iterator(); + + while (iterator1.hasNext()) { +@@ -285,6 +287,16 @@ + return this.createData().load(nbttagcompound); + } + ++ // CraftBukkit start - Send to players ++ private void broadcastAll(Packet packet) { ++ for (EntityPlayer entityplayer : (List) this.server.getPlayerList().players) { ++ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() == this) { ++ entityplayer.connection.send(packet); ++ } ++ } ++ } ++ // CraftBukkit end ++ + public static enum Action { + + CHANGE, REMOVE; diff --git a/patch-remap/og/net/minecraft/server/ServerTickRateManager.patch b/patch-remap/og/net/minecraft/server/ServerTickRateManager.patch new file mode 100644 index 0000000000..ef54ff385b --- /dev/null +++ b/patch-remap/og/net/minecraft/server/ServerTickRateManager.patch @@ -0,0 +1,53 @@ +--- a/net/minecraft/server/ServerTickRateManager.java ++++ b/net/minecraft/server/ServerTickRateManager.java +@@ -59,8 +59,14 @@ + } + + public boolean stopSprinting() { ++ // CraftBukkit start, add sendLog parameter ++ return stopSprinting(true); ++ } ++ ++ public boolean stopSprinting(boolean sendLog) { ++ // CraftBukkit end + if (this.remainingSprintTicks > 0L) { +- this.finishTickSprint(); ++ this.finishTickSprint(sendLog); // CraftBukkit - add sendLog parameter + return true; + } else { + return false; +@@ -78,7 +84,7 @@ + return flag; + } + +- private void finishTickSprint() { ++ private void finishTickSprint(boolean sendLog) { // CraftBukkit - add sendLog parameter + long i = this.scheduledCurrentSprintTicks - this.remainingSprintTicks; + double d0 = Math.max(1.0D, (double) this.sprintTimeSpend) / (double) TimeRange.NANOSECONDS_PER_MILLISECOND; + int j = (int) ((double) (TimeRange.MILLISECONDS_PER_SECOND * i) / d0); +@@ -86,9 +92,13 @@ + + this.scheduledCurrentSprintTicks = 0L; + this.sprintTimeSpend = 0L; +- this.server.createCommandSourceStack().sendSuccess(() -> { +- return IChatBaseComponent.translatable("commands.tick.sprint.report", j, s); +- }, true); ++ // CraftBukkit start - add sendLog parameter ++ if (sendLog) { ++ this.server.createCommandSourceStack().sendSuccess(() -> { ++ return IChatBaseComponent.translatable("commands.tick.sprint.report", j, s); ++ }, true); ++ } ++ // CraftBukkit end + this.remainingSprintTicks = 0L; + this.setFrozen(this.previousIsFrozen); + this.server.onTickRateChanged(); +@@ -102,7 +112,7 @@ + --this.remainingSprintTicks; + return true; + } else { +- this.finishTickSprint(); ++ this.finishTickSprint(true); // CraftBukkit - add sendLog parameter + return false; + } + } diff --git a/patch-remap/og/net/minecraft/server/bossevents/BossBattleCustom.patch b/patch-remap/og/net/minecraft/server/bossevents/BossBattleCustom.patch new file mode 100644 index 0000000000..896ccb39ea --- /dev/null +++ b/patch-remap/og/net/minecraft/server/bossevents/BossBattleCustom.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/server/bossevents/BossBattleCustom.java ++++ b/net/minecraft/server/bossevents/BossBattleCustom.java +@@ -18,12 +18,27 @@ + import net.minecraft.util.MathHelper; + import net.minecraft.world.BossBattle; + ++// CraftBukkit start ++import org.bukkit.boss.KeyedBossBar; ++import org.bukkit.craftbukkit.boss.CraftKeyedBossbar; ++// CraftBukkit end ++ + public class BossBattleCustom extends BossBattleServer { + + private final MinecraftKey id; + private final Set players = Sets.newHashSet(); + private int value; + private int max = 100; ++ // CraftBukkit start ++ private KeyedBossBar bossBar; ++ ++ public KeyedBossBar getBukkitEntity() { ++ if (bossBar == null) { ++ bossBar = new CraftKeyedBossbar(this); ++ } ++ return bossBar; ++ } ++ // CraftBukkit end + + public BossBattleCustom(MinecraftKey minecraftkey, IChatBaseComponent ichatbasecomponent) { + super(ichatbasecomponent, BossBattle.BarColor.WHITE, BossBattle.BarStyle.PROGRESS); diff --git a/patch-remap/og/net/minecraft/server/commands/CommandDifficulty.patch b/patch-remap/og/net/minecraft/server/commands/CommandDifficulty.patch new file mode 100644 index 0000000000..2a303cc1f1 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/commands/CommandDifficulty.patch @@ -0,0 +1,17 @@ +--- a/net/minecraft/server/commands/CommandDifficulty.java ++++ b/net/minecraft/server/commands/CommandDifficulty.java +@@ -44,11 +44,12 @@ + + public static int setDifficulty(CommandListenerWrapper commandlistenerwrapper, EnumDifficulty enumdifficulty) throws CommandSyntaxException { + MinecraftServer minecraftserver = commandlistenerwrapper.getServer(); ++ net.minecraft.server.level.WorldServer worldServer = commandlistenerwrapper.getLevel(); // CraftBukkit + +- if (minecraftserver.getWorldData().getDifficulty() == enumdifficulty) { ++ if (worldServer.getDifficulty() == enumdifficulty) { // CraftBukkit + throw CommandDifficulty.ERROR_ALREADY_DIFFICULT.create(enumdifficulty.getKey()); + } else { +- minecraftserver.setDifficulty(enumdifficulty, true); ++ worldServer.serverLevelData.setDifficulty(enumdifficulty); // CraftBukkit + commandlistenerwrapper.sendSuccess(() -> { + return IChatBaseComponent.translatable("commands.difficulty.success", enumdifficulty.getDisplayName()); + }, true); diff --git a/patch-remap/og/net/minecraft/server/commands/CommandEffect.patch b/patch-remap/og/net/minecraft/server/commands/CommandEffect.patch new file mode 100644 index 0000000000..bc43b68302 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/commands/CommandEffect.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/server/commands/CommandEffect.java ++++ b/net/minecraft/server/commands/CommandEffect.java +@@ -84,7 +84,7 @@ + if (entity instanceof EntityLiving) { + MobEffect mobeffect = new MobEffect(mobeffectlist, k, i, false, flag); + +- if (((EntityLiving) entity).addEffect(mobeffect, commandlistenerwrapper.getEntity())) { ++ if (((EntityLiving) entity).addEffect(mobeffect, commandlistenerwrapper.getEntity(), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.COMMAND)) { // CraftBukkit + ++j; + } + } +@@ -114,7 +114,7 @@ + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); + +- if (entity instanceof EntityLiving && ((EntityLiving) entity).removeAllEffects()) { ++ if (entity instanceof EntityLiving && ((EntityLiving) entity).removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.COMMAND)) { // CraftBukkit + ++i; + } + } +@@ -144,7 +144,7 @@ + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); + +- if (entity instanceof EntityLiving && ((EntityLiving) entity).removeEffect(mobeffectlist)) { ++ if (entity instanceof EntityLiving && ((EntityLiving) entity).removeEffect(mobeffectlist, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.COMMAND)) { // CraftBukkit + ++i; + } + } diff --git a/patch-remap/og/net/minecraft/server/commands/CommandGamerule.patch b/patch-remap/og/net/minecraft/server/commands/CommandGamerule.patch new file mode 100644 index 0000000000..e9c56cdd3c --- /dev/null +++ b/patch-remap/og/net/minecraft/server/commands/CommandGamerule.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/server/commands/CommandGamerule.java ++++ b/net/minecraft/server/commands/CommandGamerule.java +@@ -31,7 +31,7 @@ + + static > int setRule(CommandContext commandcontext, GameRules.GameRuleKey gamerules_gamerulekey) { + CommandListenerWrapper commandlistenerwrapper = (CommandListenerWrapper) commandcontext.getSource(); +- T t0 = commandlistenerwrapper.getServer().getGameRules().getRule(gamerules_gamerulekey); ++ T t0 = commandlistenerwrapper.getLevel().getGameRules().getRule(gamerules_gamerulekey); // CraftBukkit + + t0.setFromArgument(commandcontext, "value"); + commandlistenerwrapper.sendSuccess(() -> { +@@ -41,7 +41,7 @@ + } + + static > int queryRule(CommandListenerWrapper commandlistenerwrapper, GameRules.GameRuleKey gamerules_gamerulekey) { +- T t0 = commandlistenerwrapper.getServer().getGameRules().getRule(gamerules_gamerulekey); ++ T t0 = commandlistenerwrapper.getLevel().getGameRules().getRule(gamerules_gamerulekey); // CraftBukkit + + commandlistenerwrapper.sendSuccess(() -> { + return IChatBaseComponent.translatable("commands.gamerule.query", gamerules_gamerulekey.getId(), t0.toString()); diff --git a/patch-remap/og/net/minecraft/server/commands/CommandGive.patch b/patch-remap/og/net/minecraft/server/commands/CommandGive.patch new file mode 100644 index 0000000000..fb37066202 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/commands/CommandGive.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/server/commands/CommandGive.java ++++ b/net/minecraft/server/commands/CommandGive.java +@@ -61,7 +61,7 @@ + + if (flag && itemstack1.isEmpty()) { + itemstack1.setCount(1); +- entityitem = entityplayer.drop(itemstack1, false); ++ entityitem = entityplayer.drop(itemstack1, false, false, false); // SPIGOT-2942: Add boolean to call event + if (entityitem != null) { + entityitem.makeFakeItem(); + } diff --git a/patch-remap/og/net/minecraft/server/commands/CommandList.patch b/patch-remap/og/net/minecraft/server/commands/CommandList.patch new file mode 100644 index 0000000000..dbd943ac63 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/commands/CommandList.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/server/commands/CommandList.java ++++ b/net/minecraft/server/commands/CommandList.java +@@ -35,7 +35,14 @@ + + private static int format(CommandListenerWrapper commandlistenerwrapper, Function function) { + PlayerList playerlist = commandlistenerwrapper.getServer().getPlayerList(); +- List list = playerlist.getPlayers(); ++ // CraftBukkit start ++ List players = playerlist.getPlayers(); ++ if (commandlistenerwrapper.getBukkitSender() instanceof org.bukkit.entity.Player) { ++ org.bukkit.entity.Player sender = (org.bukkit.entity.Player) commandlistenerwrapper.getBukkitSender(); ++ players = players.stream().filter((ep) -> sender.canSee(ep.getBukkitEntity())).collect(java.util.stream.Collectors.toList()); ++ } ++ List list = players; ++ // CraftBukkit end + IChatBaseComponent ichatbasecomponent = ChatComponentUtils.formatList(list, function); + + commandlistenerwrapper.sendSuccess(() -> { diff --git a/patch-remap/og/net/minecraft/server/commands/CommandLoot.patch b/patch-remap/og/net/minecraft/server/commands/CommandLoot.patch new file mode 100644 index 0000000000..5004695bcc --- /dev/null +++ b/patch-remap/og/net/minecraft/server/commands/CommandLoot.patch @@ -0,0 +1,19 @@ +--- a/net/minecraft/server/commands/CommandLoot.java ++++ b/net/minecraft/server/commands/CommandLoot.java +@@ -90,7 +90,7 @@ + } + + private static > T addTargets(T t0, CommandLoot.c commandloot_c) { +- return t0.then(((LiteralArgumentBuilder) net.minecraft.commands.CommandDispatcher.literal("replace").then(net.minecraft.commands.CommandDispatcher.literal("entity").then(net.minecraft.commands.CommandDispatcher.argument("entities", ArgumentEntity.entities()).then(commandloot_c.construct(net.minecraft.commands.CommandDispatcher.argument("slot", ArgumentInventorySlot.slot()), (commandcontext, list, commandloot_a) -> { ++ return (T) t0.then(((LiteralArgumentBuilder) net.minecraft.commands.CommandDispatcher.literal("replace").then(net.minecraft.commands.CommandDispatcher.literal("entity").then(net.minecraft.commands.CommandDispatcher.argument("entities", ArgumentEntity.entities()).then(commandloot_c.construct(net.minecraft.commands.CommandDispatcher.argument("slot", ArgumentInventorySlot.slot()), (commandcontext, list, commandloot_a) -> { // CraftBukkit - decompile error + return entityReplace(ArgumentEntity.getEntities(commandcontext, "entities"), ArgumentInventorySlot.getSlot(commandcontext, "slot"), list.size(), list, commandloot_a); + }).then(commandloot_c.construct(net.minecraft.commands.CommandDispatcher.argument("count", IntegerArgumentType.integer(0)), (commandcontext, list, commandloot_a) -> { + return entityReplace(ArgumentEntity.getEntities(commandcontext, "entities"), ArgumentInventorySlot.getSlot(commandcontext, "slot"), IntegerArgumentType.getInteger(commandcontext, "count"), list, commandloot_a); +@@ -247,6 +247,7 @@ + private static int dropInWorld(CommandListenerWrapper commandlistenerwrapper, Vec3D vec3d, List list, CommandLoot.a commandloot_a) throws CommandSyntaxException { + WorldServer worldserver = commandlistenerwrapper.getLevel(); + ++ list.removeIf(ItemStack::isEmpty); // CraftBukkit - SPIGOT-6959 Remove empty items for avoid throw an error in new EntityItem + list.forEach((itemstack) -> { + EntityItem entityitem = new EntityItem(worldserver, vec3d.x, vec3d.y, vec3d.z, itemstack.copy()); + diff --git a/patch-remap/og/net/minecraft/server/commands/CommandReload.patch b/patch-remap/og/net/minecraft/server/commands/CommandReload.patch new file mode 100644 index 0000000000..46887c0149 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/commands/CommandReload.patch @@ -0,0 +1,19 @@ +--- a/net/minecraft/server/commands/CommandReload.java ++++ b/net/minecraft/server/commands/CommandReload.java +@@ -44,6 +44,16 @@ + return collection1; + } + ++ // CraftBukkit start ++ public static void reload(MinecraftServer minecraftserver) { ++ ResourcePackRepository resourcepackrepository = minecraftserver.getPackRepository(); ++ SaveData savedata = minecraftserver.getWorldData(); ++ Collection collection = resourcepackrepository.getSelectedIds(); ++ Collection collection1 = discoverNewPacks(resourcepackrepository, savedata, collection); ++ minecraftserver.reloadResources(collection1); ++ } ++ // CraftBukkit end ++ + public static void register(CommandDispatcher commanddispatcher) { + commanddispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.CommandDispatcher.literal("reload").requires((commandlistenerwrapper) -> { + return commandlistenerwrapper.hasPermission(2); diff --git a/patch-remap/og/net/minecraft/server/commands/CommandSchedule.patch b/patch-remap/og/net/minecraft/server/commands/CommandSchedule.patch new file mode 100644 index 0000000000..00b2030779 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/commands/CommandSchedule.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/server/commands/CommandSchedule.java ++++ b/net/minecraft/server/commands/CommandSchedule.java +@@ -55,7 +55,7 @@ + } else { + long j = commandlistenerwrapper.getLevel().getGameTime() + (long) i; + MinecraftKey minecraftkey = (MinecraftKey) pair.getFirst(); +- CustomFunctionCallbackTimerQueue customfunctioncallbacktimerqueue = commandlistenerwrapper.getServer().getWorldData().overworldData().getScheduledEvents(); ++ CustomFunctionCallbackTimerQueue customfunctioncallbacktimerqueue = commandlistenerwrapper.getLevel().serverLevelData.overworldData().getScheduledEvents(); // CraftBukkit - SPIGOT-6667: Use world specific function timer + + ((Either) pair.getSecond()).ifLeft((net_minecraft_commands_functions_commandfunction) -> { + String s = minecraftkey.toString(); diff --git a/patch-remap/og/net/minecraft/server/commands/CommandSpawnpoint.patch b/patch-remap/og/net/minecraft/server/commands/CommandSpawnpoint.patch new file mode 100644 index 0000000000..20b1a585ec --- /dev/null +++ b/patch-remap/og/net/minecraft/server/commands/CommandSpawnpoint.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/server/commands/CommandSpawnpoint.java ++++ b/net/minecraft/server/commands/CommandSpawnpoint.java +@@ -41,7 +41,7 @@ + while (iterator.hasNext()) { + EntityPlayer entityplayer = (EntityPlayer) iterator.next(); + +- entityplayer.setRespawnPosition(resourcekey, blockposition, f, true, false); ++ entityplayer.setRespawnPosition(resourcekey, blockposition, f, true, false, org.bukkit.event.player.PlayerSpawnChangeEvent.Cause.COMMAND); // CraftBukkit + } + + String s = resourcekey.location().toString(); diff --git a/patch-remap/og/net/minecraft/server/commands/CommandSpreadPlayers.patch b/patch-remap/og/net/minecraft/server/commands/CommandSpreadPlayers.patch new file mode 100644 index 0000000000..b637188cd4 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/commands/CommandSpreadPlayers.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/server/commands/CommandSpreadPlayers.java ++++ b/net/minecraft/server/commands/CommandSpreadPlayers.java +@@ -93,7 +93,7 @@ + if (entity instanceof EntityHuman) { + set.add(entity.getTeam()); + } else { +- set.add((Object) null); ++ set.add((ScoreboardTeamBase) null); // CraftBukkit - decompile error + } + } + +@@ -203,7 +203,7 @@ + commandspreadplayers_a = acommandspreadplayers_a[j++]; + } + +- entity.teleportTo(worldserver, (double) MathHelper.floor(commandspreadplayers_a.x) + 0.5D, (double) commandspreadplayers_a.getSpawnY(worldserver, i), (double) MathHelper.floor(commandspreadplayers_a.z) + 0.5D, Set.of(), entity.getYRot(), entity.getXRot()); ++ entity.teleportTo(worldserver, (double) MathHelper.floor(commandspreadplayers_a.x) + 0.5D, (double) commandspreadplayers_a.getSpawnY(worldserver, i), (double) MathHelper.floor(commandspreadplayers_a.z) + 0.5D, Set.of(), entity.getYRot(), entity.getXRot(), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.COMMAND); // CraftBukkit - handle teleport reason + d1 = Double.MAX_VALUE; + CommandSpreadPlayers.a[] acommandspreadplayers_a1 = acommandspreadplayers_a; + int k = acommandspreadplayers_a.length; diff --git a/patch-remap/og/net/minecraft/server/commands/CommandSummon.patch b/patch-remap/og/net/minecraft/server/commands/CommandSummon.patch new file mode 100644 index 0000000000..7ab0f2a793 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/commands/CommandSummon.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/server/commands/CommandSummon.java ++++ b/net/minecraft/server/commands/CommandSummon.java +@@ -67,7 +67,7 @@ + ((EntityInsentient) entity).finalizeSpawn(commandlistenerwrapper.getLevel(), commandlistenerwrapper.getLevel().getCurrentDifficultyAt(entity.blockPosition()), EnumMobSpawn.COMMAND, (GroupDataEntity) null, (NBTTagCompound) null); + } + +- if (!worldserver.tryAddFreshEntityWithPassengers(entity)) { ++ if (!worldserver.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.COMMAND)) { // CraftBukkit - pass a spawn reason of "COMMAND" + throw CommandSummon.ERROR_DUPLICATE_UUID.create(); + } else { + return entity; diff --git a/patch-remap/og/net/minecraft/server/commands/CommandTeleport.patch b/patch-remap/og/net/minecraft/server/commands/CommandTeleport.patch new file mode 100644 index 0000000000..c96cfba8e5 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/commands/CommandTeleport.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/server/commands/CommandTeleport.java ++++ b/net/minecraft/server/commands/CommandTeleport.java +@@ -33,6 +33,13 @@ + import net.minecraft.world.phys.Vec2F; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.event.entity.EntityTeleportEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++// CraftBukkit end ++ + public class CommandTeleport { + + private static final SimpleCommandExceptionType INVALID_POSITION = new SimpleCommandExceptionType(IChatBaseComponent.translatable("commands.teleport.invalidPosition")); +@@ -155,7 +162,30 @@ + float f2 = MathHelper.wrapDegrees(f); + float f3 = MathHelper.wrapDegrees(f1); + +- if (entity.teleportTo(worldserver, d0, d1, d2, set, f2, f3)) { ++ // CraftBukkit start - Teleport event ++ boolean result; ++ if (entity instanceof EntityPlayer player) { ++ result = player.teleportTo(worldserver, d0, d1, d2, set, f2, f3, PlayerTeleportEvent.TeleportCause.COMMAND); ++ } else { ++ Location to = new Location(worldserver.getWorld(), d0, d1, d2, f2, f3); ++ EntityTeleportEvent event = new EntityTeleportEvent(entity.getBukkitEntity(), entity.getBukkitEntity().getLocation(), to); ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ d0 = to.getX(); ++ d1 = to.getY(); ++ d2 = to.getZ(); ++ f2 = to.getYaw(); ++ f3 = to.getPitch(); ++ worldserver = ((CraftWorld) to.getWorld()).getHandle(); ++ ++ result = entity.teleportTo(worldserver, d0, d1, d2, set, f2, f3); ++ } ++ ++ if (result) { ++ // CraftBukkit end + if (commandteleport_a != null) { + commandteleport_a.perform(commandlistenerwrapper, entity); + } diff --git a/patch-remap/og/net/minecraft/server/commands/CommandTime.patch b/patch-remap/og/net/minecraft/server/commands/CommandTime.patch new file mode 100644 index 0000000000..8711223f84 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/commands/CommandTime.patch @@ -0,0 +1,56 @@ +--- a/net/minecraft/server/commands/CommandTime.java ++++ b/net/minecraft/server/commands/CommandTime.java +@@ -9,6 +9,11 @@ + import net.minecraft.network.chat.IChatBaseComponent; + import net.minecraft.server.level.WorldServer; + ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.event.world.TimeSkipEvent; ++// CraftBukkit end ++ + public class CommandTime { + + public CommandTime() {} +@@ -49,12 +54,18 @@ + } + + public static int setTime(CommandListenerWrapper commandlistenerwrapper, int i) { +- Iterator iterator = commandlistenerwrapper.getServer().getAllLevels().iterator(); ++ Iterator iterator = com.google.common.collect.Iterators.singletonIterator(commandlistenerwrapper.getLevel()); // CraftBukkit - SPIGOT-6496: Only set the time for the world the command originates in + + while (iterator.hasNext()) { + WorldServer worldserver = (WorldServer) iterator.next(); + +- worldserver.setDayTime((long) i); ++ // CraftBukkit start ++ TimeSkipEvent event = new TimeSkipEvent(worldserver.getWorld(), TimeSkipEvent.SkipReason.COMMAND, i - worldserver.getDayTime()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ worldserver.setDayTime((long) worldserver.getDayTime() + event.getSkipAmount()); ++ } ++ // CraftBukkit end + } + + commandlistenerwrapper.sendSuccess(() -> { +@@ -64,12 +75,18 @@ + } + + public static int addTime(CommandListenerWrapper commandlistenerwrapper, int i) { +- Iterator iterator = commandlistenerwrapper.getServer().getAllLevels().iterator(); ++ Iterator iterator = com.google.common.collect.Iterators.singletonIterator(commandlistenerwrapper.getLevel()); // CraftBukkit - SPIGOT-6496: Only set the time for the world the command originates in + + while (iterator.hasNext()) { + WorldServer worldserver = (WorldServer) iterator.next(); + +- worldserver.setDayTime(worldserver.getDayTime() + (long) i); ++ // CraftBukkit start ++ TimeSkipEvent event = new TimeSkipEvent(worldserver.getWorld(), TimeSkipEvent.SkipReason.COMMAND, i); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ worldserver.setDayTime(worldserver.getDayTime() + event.getSkipAmount()); ++ } ++ // CraftBukkit end + } + + int j = getDayTime(commandlistenerwrapper.getLevel()); diff --git a/patch-remap/og/net/minecraft/server/commands/CommandWorldBorder.patch b/patch-remap/og/net/minecraft/server/commands/CommandWorldBorder.patch new file mode 100644 index 0000000000..e21e3f8c38 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/commands/CommandWorldBorder.patch @@ -0,0 +1,65 @@ +--- a/net/minecraft/server/commands/CommandWorldBorder.java ++++ b/net/minecraft/server/commands/CommandWorldBorder.java +@@ -57,7 +57,7 @@ + } + + private static int setDamageBuffer(CommandListenerWrapper commandlistenerwrapper, float f) throws CommandSyntaxException { +- WorldBorder worldborder = commandlistenerwrapper.getServer().overworld().getWorldBorder(); ++ WorldBorder worldborder = commandlistenerwrapper.getLevel().getWorldBorder(); // CraftBukkit + + if (worldborder.getDamageSafeZone() == (double) f) { + throw CommandWorldBorder.ERROR_SAME_DAMAGE_BUFFER.create(); +@@ -71,7 +71,7 @@ + } + + private static int setDamageAmount(CommandListenerWrapper commandlistenerwrapper, float f) throws CommandSyntaxException { +- WorldBorder worldborder = commandlistenerwrapper.getServer().overworld().getWorldBorder(); ++ WorldBorder worldborder = commandlistenerwrapper.getLevel().getWorldBorder(); // CraftBukkit + + if (worldborder.getDamagePerBlock() == (double) f) { + throw CommandWorldBorder.ERROR_SAME_DAMAGE_AMOUNT.create(); +@@ -85,7 +85,7 @@ + } + + private static int setWarningTime(CommandListenerWrapper commandlistenerwrapper, int i) throws CommandSyntaxException { +- WorldBorder worldborder = commandlistenerwrapper.getServer().overworld().getWorldBorder(); ++ WorldBorder worldborder = commandlistenerwrapper.getLevel().getWorldBorder(); // CraftBukkit + + if (worldborder.getWarningTime() == i) { + throw CommandWorldBorder.ERROR_SAME_WARNING_TIME.create(); +@@ -99,7 +99,7 @@ + } + + private static int setWarningDistance(CommandListenerWrapper commandlistenerwrapper, int i) throws CommandSyntaxException { +- WorldBorder worldborder = commandlistenerwrapper.getServer().overworld().getWorldBorder(); ++ WorldBorder worldborder = commandlistenerwrapper.getLevel().getWorldBorder(); // CraftBukkit + + if (worldborder.getWarningBlocks() == i) { + throw CommandWorldBorder.ERROR_SAME_WARNING_DISTANCE.create(); +@@ -113,7 +113,7 @@ + } + + private static int getSize(CommandListenerWrapper commandlistenerwrapper) { +- double d0 = commandlistenerwrapper.getServer().overworld().getWorldBorder().getSize(); ++ double d0 = commandlistenerwrapper.getLevel().getWorldBorder().getSize(); // CraftBukkit + + commandlistenerwrapper.sendSuccess(() -> { + return IChatBaseComponent.translatable("commands.worldborder.get", String.format(Locale.ROOT, "%.0f", d0)); +@@ -122,7 +122,7 @@ + } + + private static int setCenter(CommandListenerWrapper commandlistenerwrapper, Vec2F vec2f) throws CommandSyntaxException { +- WorldBorder worldborder = commandlistenerwrapper.getServer().overworld().getWorldBorder(); ++ WorldBorder worldborder = commandlistenerwrapper.getLevel().getWorldBorder(); // CraftBukkit + + if (worldborder.getCenterX() == (double) vec2f.x && worldborder.getCenterZ() == (double) vec2f.y) { + throw CommandWorldBorder.ERROR_SAME_CENTER.create(); +@@ -138,7 +138,7 @@ + } + + private static int setSize(CommandListenerWrapper commandlistenerwrapper, double d0, long i) throws CommandSyntaxException { +- WorldBorder worldborder = commandlistenerwrapper.getServer().overworld().getWorldBorder(); ++ WorldBorder worldborder = commandlistenerwrapper.getLevel().getWorldBorder(); // CraftBukkit + double d1 = worldborder.getSize(); + + if (d1 == d0) { diff --git a/patch-remap/og/net/minecraft/server/commands/PlaceCommand.patch b/patch-remap/og/net/minecraft/server/commands/PlaceCommand.patch new file mode 100644 index 0000000000..2b96dcd0c8 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/commands/PlaceCommand.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/server/commands/PlaceCommand.java ++++ b/net/minecraft/server/commands/PlaceCommand.java +@@ -130,6 +130,7 @@ + if (!structurestart.isValid()) { + throw PlaceCommand.ERROR_STRUCTURE_FAILED.create(); + } else { ++ structurestart.generationEventCause = org.bukkit.event.world.AsyncStructureGenerateEvent.Cause.COMMAND; // CraftBukkit - set AsyncStructureGenerateEvent.Cause.COMMAND as generation cause + StructureBoundingBox structureboundingbox = structurestart.getBoundingBox(); + ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(SectionPosition.blockToSectionCoord(structureboundingbox.minX()), SectionPosition.blockToSectionCoord(structureboundingbox.minZ())); + ChunkCoordIntPair chunkcoordintpair1 = new ChunkCoordIntPair(SectionPosition.blockToSectionCoord(structureboundingbox.maxX()), SectionPosition.blockToSectionCoord(structureboundingbox.maxZ())); diff --git a/patch-remap/og/net/minecraft/server/dedicated/DedicatedServer.patch b/patch-remap/og/net/minecraft/server/dedicated/DedicatedServer.patch new file mode 100644 index 0000000000..cbccc1a814 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/dedicated/DedicatedServer.patch @@ -0,0 +1,256 @@ +--- a/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/net/minecraft/server/dedicated/DedicatedServer.java +@@ -53,6 +53,16 @@ + import net.minecraft.world.level.storage.Convertable; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.server.WorldLoader; ++import org.apache.logging.log4j.Level; ++import org.apache.logging.log4j.LogManager; ++import org.apache.logging.log4j.io.IoBuilder; ++import org.bukkit.command.CommandSender; ++import org.bukkit.event.server.ServerCommandEvent; ++import org.bukkit.event.server.RemoteServerCommandEvent; ++// CraftBukkit end ++ + public class DedicatedServer extends MinecraftServer implements IMinecraftServer { + + static final Logger LOGGER = LogUtils.getLogger(); +@@ -61,7 +71,7 @@ + private final List consoleInput = Collections.synchronizedList(Lists.newArrayList()); + @Nullable + private RemoteStatusListener queryThreadGs4; +- private final RemoteControlCommandListener rconConsoleSource; ++ // private final RemoteControlCommandListener rconConsoleSource; // CraftBukkit - remove field + @Nullable + private RemoteControlListener rconThread; + public DedicatedServerSettings settings; +@@ -70,10 +80,12 @@ + @Nullable + private final TextFilter textFilterClient; + +- public DedicatedServer(Thread thread, Convertable.ConversionSession convertable_conversionsession, ResourcePackRepository resourcepackrepository, WorldStem worldstem, DedicatedServerSettings dedicatedserversettings, DataFixer datafixer, Services services, WorldLoadListenerFactory worldloadlistenerfactory) { +- super(thread, convertable_conversionsession, resourcepackrepository, worldstem, Proxy.NO_PROXY, datafixer, services, worldloadlistenerfactory); ++ // CraftBukkit start - Signature changed ++ public DedicatedServer(joptsimple.OptionSet options, WorldLoader.a worldLoader, Thread thread, Convertable.ConversionSession convertable_conversionsession, ResourcePackRepository resourcepackrepository, WorldStem worldstem, DedicatedServerSettings dedicatedserversettings, DataFixer datafixer, Services services, WorldLoadListenerFactory worldloadlistenerfactory) { ++ super(options, worldLoader, thread, convertable_conversionsession, resourcepackrepository, worldstem, Proxy.NO_PROXY, datafixer, services, worldloadlistenerfactory); ++ // CraftBukkit end + this.settings = dedicatedserversettings; +- this.rconConsoleSource = new RemoteControlCommandListener(this); ++ // this.rconConsoleSource = new RemoteControlCommandListener(this); // CraftBukkit - remove field + this.textFilterClient = TextFilter.createFromConfig(dedicatedserversettings.getProperties().textFilteringConfig); + } + +@@ -81,13 +93,44 @@ + public boolean initServer() throws IOException { + Thread thread = new Thread("Server console handler") { + public void run() { +- BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8)); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.Main.useConsole) { ++ return; ++ } ++ jline.console.ConsoleReader bufferedreader = reader; ++ ++ // MC-33041, SPIGOT-5538: if System.in is not valid due to javaw, then return ++ try { ++ System.in.available(); ++ } catch (IOException ex) { ++ return; ++ } ++ // CraftBukkit end + + String s; + + try { +- while (!DedicatedServer.this.isStopped() && DedicatedServer.this.isRunning() && (s = bufferedreader.readLine()) != null) { +- DedicatedServer.this.handleConsoleInput(s, DedicatedServer.this.createCommandSourceStack()); ++ // CraftBukkit start - JLine disabling compatibility ++ while (!DedicatedServer.this.isStopped() && DedicatedServer.this.isRunning()) { ++ if (org.bukkit.craftbukkit.Main.useJline) { ++ s = bufferedreader.readLine(">", null); ++ } else { ++ s = bufferedreader.readLine(); ++ } ++ ++ // SPIGOT-5220: Throttle if EOF (ctrl^d) or stdin is /dev/null ++ if (s == null) { ++ try { ++ Thread.sleep(50L); ++ } catch (InterruptedException ex) { ++ Thread.currentThread().interrupt(); ++ } ++ continue; ++ } ++ if (s.trim().length() > 0) { // Trim to filter lines which are just spaces ++ DedicatedServer.this.handleConsoleInput(s, DedicatedServer.this.createCommandSourceStack()); ++ } ++ // CraftBukkit end + } + } catch (IOException ioexception) { + DedicatedServer.LOGGER.error("Exception handling console input", ioexception); +@@ -96,6 +139,27 @@ + } + }; + ++ // CraftBukkit start - TODO: handle command-line logging arguments ++ java.util.logging.Logger global = java.util.logging.Logger.getLogger(""); ++ global.setUseParentHandlers(false); ++ for (java.util.logging.Handler handler : global.getHandlers()) { ++ global.removeHandler(handler); ++ } ++ global.addHandler(new org.bukkit.craftbukkit.util.ForwardLogHandler()); ++ ++ final org.apache.logging.log4j.core.Logger logger = ((org.apache.logging.log4j.core.Logger) LogManager.getRootLogger()); ++ for (org.apache.logging.log4j.core.Appender appender : logger.getAppenders().values()) { ++ if (appender instanceof org.apache.logging.log4j.core.appender.ConsoleAppender) { ++ logger.removeAppender(appender); ++ } ++ } ++ ++ new org.bukkit.craftbukkit.util.TerminalConsoleWriterThread(System.out, this.reader).start(); ++ ++ System.setOut(IoBuilder.forLogger(logger).setLevel(Level.INFO).buildPrintStream()); ++ System.setErr(IoBuilder.forLogger(logger).setLevel(Level.WARN).buildPrintStream()); ++ // CraftBukkit end ++ + thread.setDaemon(true); + thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(DedicatedServer.LOGGER)); + thread.start(); +@@ -120,7 +184,7 @@ + this.setMotd(dedicatedserverproperties.motd); + super.setPlayerIdleTimeout((Integer) dedicatedserverproperties.playerIdleTimeout.get()); + this.setEnforceWhitelist(dedicatedserverproperties.enforceWhitelist); +- this.worldData.setGameType(dedicatedserverproperties.gamemode); ++ // this.worldData.setGameType(dedicatedserverproperties.gamemode); // CraftBukkit - moved to world loading + DedicatedServer.LOGGER.info("Default game type: {}", dedicatedserverproperties.gamemode); + InetAddress inetaddress = null; + +@@ -144,6 +208,12 @@ + return false; + } + ++ // CraftBukkit start ++ this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); ++ server.loadPlugins(); ++ server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.STARTUP); ++ // CraftBukkit end ++ + if (!this.usesAuthentication()) { + DedicatedServer.LOGGER.warn("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!"); + DedicatedServer.LOGGER.warn("The server will make no attempt to authenticate usernames. Beware."); +@@ -158,13 +228,13 @@ + if (!NameReferencingFileConverter.serverReadyAfterUserconversion(this)) { + return false; + } else { +- this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); ++ // this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); // CraftBukkit - moved up + long i = SystemUtils.getNanos(); + + TileEntitySkull.setup(this.services, this); + UserCache.setUsesAuthentication(this.usesAuthentication()); + DedicatedServer.LOGGER.info("Preparing level \"{}\"", this.getLevelIdName()); +- this.loadLevel(); ++ this.loadLevel(storageSource.getLevelId()); // CraftBukkit + long j = SystemUtils.getNanos() - i; + String s = String.format(Locale.ROOT, "%.3fs", (double) j / 1.0E9D); + +@@ -296,6 +366,7 @@ + this.queryThreadGs4.stop(); + } + ++ System.exit(0); // CraftBukkit + } + + @Override +@@ -317,7 +388,15 @@ + while (!this.consoleInput.isEmpty()) { + ServerCommand servercommand = (ServerCommand) this.consoleInput.remove(0); + +- this.getCommands().performPrefixedCommand(servercommand.source, servercommand.msg); ++ // CraftBukkit start - ServerCommand for preprocessing ++ ServerCommandEvent event = new ServerCommandEvent(console, servercommand.msg); ++ server.getPluginManager().callEvent(event); ++ if (event.isCancelled()) continue; ++ servercommand = new ServerCommand(event.getCommand(), servercommand.source); ++ ++ // this.getCommands().performPrefixedCommand(servercommand.source, servercommand.msg); // Called in dispatchServerCommand ++ server.dispatchServerCommand(console, servercommand); ++ // CraftBukkit end + } + + } +@@ -544,16 +623,52 @@ + + @Override + public String getPluginNames() { +- return ""; ++ // CraftBukkit start - Whole method ++ StringBuilder result = new StringBuilder(); ++ org.bukkit.plugin.Plugin[] plugins = server.getPluginManager().getPlugins(); ++ ++ result.append(server.getName()); ++ result.append(" on Bukkit "); ++ result.append(server.getBukkitVersion()); ++ ++ if (plugins.length > 0 && server.getQueryPlugins()) { ++ result.append(": "); ++ ++ for (int i = 0; i < plugins.length; i++) { ++ if (i > 0) { ++ result.append("; "); ++ } ++ ++ result.append(plugins[i].getDescription().getName()); ++ result.append(" "); ++ result.append(plugins[i].getDescription().getVersion().replaceAll(";", ",")); ++ } ++ } ++ ++ return result.toString(); ++ // CraftBukkit end + } + + @Override + public String runCommand(String s) { +- this.rconConsoleSource.prepareForCommand(); ++ // CraftBukkit start - fire RemoteServerCommandEvent ++ throw new UnsupportedOperationException("Not supported - remote source required."); ++ } ++ ++ public String runCommand(RemoteControlCommandListener rconConsoleSource, String s) { ++ rconConsoleSource.prepareForCommand(); + this.executeBlocking(() -> { +- this.getCommands().performPrefixedCommand(this.rconConsoleSource.createCommandSourceStack(), s); ++ CommandListenerWrapper wrapper = rconConsoleSource.createCommandSourceStack(); ++ RemoteServerCommandEvent event = new RemoteServerCommandEvent(rconConsoleSource.getBukkitSender(wrapper), s); ++ server.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ ServerCommand serverCommand = new ServerCommand(event.getCommand(), wrapper); ++ server.dispatchServerCommand(event.getSender(), serverCommand); + }); +- return this.rconConsoleSource.getCommandResponse(); ++ return rconConsoleSource.getCommandResponse(); ++ // CraftBukkit end + } + + public void storeUsingWhiteList(boolean flag) { +@@ -604,4 +719,15 @@ + public Optional getServerResourcePack() { + return this.settings.getProperties().serverResourcePackInfo; + } ++ ++ // CraftBukkit start ++ public boolean isDebugging() { ++ return this.getProperties().debug; ++ } ++ ++ @Override ++ public CommandSender getBukkitSender(CommandListenerWrapper wrapper) { ++ return console; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/server/dedicated/DedicatedServerProperties.patch b/patch-remap/og/net/minecraft/server/dedicated/DedicatedServerProperties.patch new file mode 100644 index 0000000000..47870fe56d --- /dev/null +++ b/patch-remap/og/net/minecraft/server/dedicated/DedicatedServerProperties.patch @@ -0,0 +1,74 @@ +--- a/net/minecraft/server/dedicated/DedicatedServerProperties.java ++++ b/net/minecraft/server/dedicated/DedicatedServerProperties.java +@@ -44,11 +44,16 @@ + import net.minecraft.world.level.levelgen.presets.WorldPresets; + import org.slf4j.Logger; + ++// CraftBukkit start ++import joptsimple.OptionSet; ++// CraftBukkit end ++ + public class DedicatedServerProperties extends PropertyManager { + + static final Logger LOGGER = LogUtils.getLogger(); + private static final Pattern SHA1 = Pattern.compile("^[a-fA-F0-9]{40}$"); + private static final Splitter COMMA_SPLITTER = Splitter.on(',').trimResults(); ++ public final boolean debug = this.get("debug", false); // CraftBukkit + public final boolean onlineMode = this.get("online-mode", true); + public final boolean preventProxyConnections = this.get("prevent-proxy-connections", false); + public final String serverIp = this.get("server-ip", ""); +@@ -103,8 +108,10 @@ + private final DedicatedServerProperties.WorldDimensionData worldDimensionData; + public final WorldOptions worldOptions; + +- public DedicatedServerProperties(Properties properties) { +- super(properties); ++ // CraftBukkit start ++ public DedicatedServerProperties(Properties properties, OptionSet optionset) { ++ super(properties, optionset); ++ // CraftBukkit end + this.difficulty = (EnumDifficulty) this.get("difficulty", dispatchNumberOrString(EnumDifficulty::byId, EnumDifficulty::byName), EnumDifficulty::getKey, EnumDifficulty.EASY); + this.gamemode = (EnumGamemode) this.get("gamemode", dispatchNumberOrString(EnumGamemode::byId, EnumGamemode::byName), EnumGamemode::getName, EnumGamemode.SURVIVAL); + this.levelName = this.get("level-name", "world"); +@@ -161,13 +168,15 @@ + this.initialDataPackConfiguration = getDatapackConfig(this.get("initial-enabled-packs", String.join(",", WorldDataConfiguration.DEFAULT.dataPacks().getEnabled())), this.get("initial-disabled-packs", String.join(",", WorldDataConfiguration.DEFAULT.dataPacks().getDisabled()))); + } + +- public static DedicatedServerProperties fromFile(Path path) { +- return new DedicatedServerProperties(loadFromFile(path)); ++ // CraftBukkit start ++ public static DedicatedServerProperties fromFile(Path path, OptionSet optionset) { ++ return new DedicatedServerProperties(loadFromFile(path), optionset); + } + + @Override +- protected DedicatedServerProperties reload(IRegistryCustom iregistrycustom, Properties properties) { +- return new DedicatedServerProperties(properties); ++ protected DedicatedServerProperties reload(IRegistryCustom iregistrycustom, Properties properties, OptionSet optionset) { ++ return new DedicatedServerProperties(properties, optionset); ++ // CraftBukkit end + } + + @Nullable +@@ -248,10 +257,10 @@ + }).orElseThrow(() -> { + return new IllegalStateException("Invalid datapack contents: can't find default preset"); + }); +- Optional optional = Optional.ofNullable(MinecraftKey.tryParse(this.levelType)).map((minecraftkey) -> { ++ Optional> optional = Optional.ofNullable(MinecraftKey.tryParse(this.levelType)).map((minecraftkey) -> { // CraftBukkit - decompile error + return ResourceKey.create(Registries.WORLD_PRESET, minecraftkey); + }).or(() -> { +- return Optional.ofNullable((ResourceKey) DedicatedServerProperties.WorldDimensionData.LEGACY_PRESET_NAMES.get(this.levelType)); ++ return Optional.ofNullable(DedicatedServerProperties.WorldDimensionData.LEGACY_PRESET_NAMES.get(this.levelType)); // CraftBukkit - decompile error + }); + + Objects.requireNonNull(iregistry); +@@ -263,7 +272,7 @@ + + if (holder.is(WorldPresets.FLAT)) { + RegistryOps registryops = RegistryOps.create(JsonOps.INSTANCE, (HolderLookup.b) iregistrycustom); +- DataResult dataresult = GeneratorSettingsFlat.CODEC.parse(new Dynamic(registryops, this.generatorSettings())); ++ DataResult dataresult = GeneratorSettingsFlat.CODEC.parse(new Dynamic(registryops, this.generatorSettings())); // CraftBukkit - decompile error + Logger logger = DedicatedServerProperties.LOGGER; + + Objects.requireNonNull(logger); diff --git a/patch-remap/og/net/minecraft/server/dedicated/DedicatedServerSettings.patch b/patch-remap/og/net/minecraft/server/dedicated/DedicatedServerSettings.patch new file mode 100644 index 0000000000..9a52b5cc81 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/dedicated/DedicatedServerSettings.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/server/dedicated/DedicatedServerSettings.java ++++ b/net/minecraft/server/dedicated/DedicatedServerSettings.java +@@ -3,14 +3,21 @@ + import java.nio.file.Path; + import java.util.function.UnaryOperator; + ++// CraftBukkit start ++import java.io.File; ++import joptsimple.OptionSet; ++// CraftBukkit end ++ + public class DedicatedServerSettings { + + private final Path source; + private DedicatedServerProperties properties; + +- public DedicatedServerSettings(Path path) { +- this.source = path; +- this.properties = DedicatedServerProperties.fromFile(path); ++ // CraftBukkit start ++ public DedicatedServerSettings(OptionSet optionset) { ++ this.source = ((File) optionset.valueOf("config")).toPath(); ++ this.properties = DedicatedServerProperties.fromFile(source, optionset); ++ // CraftBukkit end + } + + public DedicatedServerProperties getProperties() { diff --git a/patch-remap/og/net/minecraft/server/dedicated/PropertyManager.patch b/patch-remap/og/net/minecraft/server/dedicated/PropertyManager.patch new file mode 100644 index 0000000000..3baccfc5e3 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/dedicated/PropertyManager.patch @@ -0,0 +1,124 @@ +--- a/net/minecraft/server/dedicated/PropertyManager.java ++++ b/net/minecraft/server/dedicated/PropertyManager.java +@@ -23,17 +23,37 @@ + import net.minecraft.core.IRegistryCustom; + import org.slf4j.Logger; + ++import joptsimple.OptionSet; // CraftBukkit ++ + public abstract class PropertyManager> { + + private static final Logger LOGGER = LogUtils.getLogger(); + public final Properties properties; ++ // CraftBukkit start ++ private OptionSet options = null; + +- public PropertyManager(Properties properties) { ++ public PropertyManager(Properties properties, final OptionSet options) { + this.properties = properties; ++ ++ this.options = options; ++ } ++ ++ private String getOverride(String name, String value) { ++ if ((this.options != null) && (this.options.has(name))) { ++ return String.valueOf(this.options.valueOf(name)); ++ } ++ ++ return value; ++ // CraftBukkit end + } + + public static Properties loadFromFile(Path path) { + try { ++ // CraftBukkit start - SPIGOT-7465, MC-264979: Don't load if file doesn't exist ++ if (!path.toFile().exists()) { ++ return new Properties(); ++ } ++ // CraftBukkit end + Properties properties; + Properties properties1; + +@@ -97,6 +117,11 @@ + + public void store(Path path) { + try { ++ // CraftBukkit start - Don't attempt writing to file if it's read only ++ if (path.toFile().exists() && !path.toFile().canWrite()) { ++ return; ++ } ++ // CraftBukkit end + BufferedWriter bufferedwriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8); + + try { +@@ -125,7 +150,7 @@ + private static Function wrapNumberDeserializer(Function function) { + return (s) -> { + try { +- return (Number) function.apply(s); ++ return (V) function.apply(s); // CraftBukkit - decompile error + } catch (NumberFormatException numberformatexception) { + return null; + } +@@ -144,7 +169,7 @@ + + @Nullable + private String getStringRaw(String s) { +- return (String) this.properties.get(s); ++ return (String) getOverride(s, this.properties.getProperty(s)); // CraftBukkit + } + + @Nullable +@@ -160,6 +185,16 @@ + } + + protected V get(String s, Function function, Function function1, V v0) { ++ // CraftBukkit start ++ try { ++ return get0(s, function, function1, v0); ++ } catch (Exception ex) { ++ throw new RuntimeException("Could not load invalidly configured property '" + s + "'", ex); ++ } ++ } ++ ++ private V get0(String s, Function function, Function function1, V v0) { ++ // CraftBukkit end + String s1 = this.getStringRaw(s); + V v1 = MoreObjects.firstNonNull(s1 != null ? function.apply(s1) : null, v0); + +@@ -172,7 +207,7 @@ + V v1 = MoreObjects.firstNonNull(s1 != null ? function.apply(s1) : null, v0); + + this.properties.put(s, function1.apply(v1)); +- return new PropertyManager.EditableProperty<>(s, v1, function1); ++ return new PropertyManager.EditableProperty(s, v1, function1); // CraftBukkit - decompile error + } + + protected V get(String s, Function function, UnaryOperator unaryoperator, Function function1, V v0) { +@@ -236,7 +271,7 @@ + return properties; + } + +- protected abstract T reload(IRegistryCustom iregistrycustom, Properties properties); ++ protected abstract T reload(IRegistryCustom iregistrycustom, Properties properties, OptionSet optionset); // CraftBukkit + + public class EditableProperty implements Supplier { + +@@ -244,7 +279,7 @@ + private final V value; + private final Function serializer; + +- EditableProperty(String s, Object object, Function function) { ++ EditableProperty(String s, V object, Function function) { // CraftBukkit - decompile error + this.key = s; + this.value = object; + this.serializer = function; +@@ -258,7 +293,7 @@ + Properties properties = PropertyManager.this.cloneProperties(); + + properties.put(this.key, this.serializer.apply(v0)); +- return PropertyManager.this.reload(iregistrycustom, properties); ++ return PropertyManager.this.reload(iregistrycustom, properties, PropertyManager.this.options); // CraftBukkit + } + } + } diff --git a/patch-remap/og/net/minecraft/server/gui/ServerGUI.patch b/patch-remap/og/net/minecraft/server/gui/ServerGUI.patch new file mode 100644 index 0000000000..5c6b09ab35 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/gui/ServerGUI.patch @@ -0,0 +1,28 @@ +--- a/net/minecraft/server/gui/ServerGUI.java ++++ b/net/minecraft/server/gui/ServerGUI.java +@@ -96,7 +96,7 @@ + private JComponent buildInfoPanel() { + JPanel jpanel = new JPanel(new BorderLayout()); + GuiStatsComponent guistatscomponent = new GuiStatsComponent(this.server); +- Collection collection = this.finalizers; ++ Collection collection = this.finalizers; // CraftBukkit - decompile error + + Objects.requireNonNull(guistatscomponent); + collection.add(guistatscomponent::close); +@@ -166,6 +166,7 @@ + this.finalizers.forEach(Runnable::run); + } + ++ private static final java.util.regex.Pattern ANSI = java.util.regex.Pattern.compile("\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})*)?[m|K]"); // CraftBukkit + public void print(JTextArea jtextarea, JScrollPane jscrollpane, String s) { + if (!SwingUtilities.isEventDispatchThread()) { + SwingUtilities.invokeLater(() -> { +@@ -181,7 +182,7 @@ + } + + try { +- document.insertString(document.getLength(), s, (AttributeSet) null); ++ document.insertString(document.getLength(), ANSI.matcher(s).replaceAll(""), (AttributeSet) null); // CraftBukkit + } catch (BadLocationException badlocationexception) { + ; + } diff --git a/patch-remap/og/net/minecraft/server/level/ChunkMapDistance.patch b/patch-remap/og/net/minecraft/server/level/ChunkMapDistance.patch new file mode 100644 index 0000000000..327db5593a --- /dev/null +++ b/patch-remap/og/net/minecraft/server/level/ChunkMapDistance.patch @@ -0,0 +1,137 @@ +--- a/net/minecraft/server/level/ChunkMapDistance.java ++++ b/net/minecraft/server/level/ChunkMapDistance.java +@@ -122,10 +122,25 @@ + } + + if (!this.chunksToUpdateFutures.isEmpty()) { +- this.chunksToUpdateFutures.forEach((playerchunk) -> { ++ // CraftBukkit start ++ // Iterate pending chunk updates with protection against concurrent modification exceptions ++ java.util.Iterator iter = this.chunksToUpdateFutures.iterator(); ++ int expectedSize = this.chunksToUpdateFutures.size(); ++ do { ++ PlayerChunk playerchunk = iter.next(); ++ iter.remove(); ++ expectedSize--; ++ + playerchunk.updateFutures(playerchunkmap, this.mainThreadExecutor); +- }); +- this.chunksToUpdateFutures.clear(); ++ ++ // Reset iterator if set was modified using add() ++ if (this.chunksToUpdateFutures.size() != expectedSize) { ++ expectedSize = this.chunksToUpdateFutures.size(); ++ iter = this.chunksToUpdateFutures.iterator(); ++ } ++ } while (iter.hasNext()); ++ // CraftBukkit end ++ + return true; + } else { + if (!this.ticketsToRelease.isEmpty()) { +@@ -161,7 +176,7 @@ + } + } + +- void addTicket(long i, Ticket ticket) { ++ boolean addTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean + ArraySetSorted> arraysetsorted = this.getTickets(i); + int j = getTicketLevelAt(arraysetsorted); + Ticket ticket1 = (Ticket) arraysetsorted.addOrGet(ticket); +@@ -171,13 +186,15 @@ + this.ticketTracker.update(i, ticket.getTicketLevel(), true); + } + ++ return ticket == ticket1; // CraftBukkit + } + +- void removeTicket(long i, Ticket ticket) { ++ boolean removeTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean + ArraySetSorted> arraysetsorted = this.getTickets(i); + ++ boolean removed = false; // CraftBukkit + if (arraysetsorted.remove(ticket)) { +- ; ++ removed = true; // CraftBukkit + } + + if (arraysetsorted.isEmpty()) { +@@ -185,6 +202,7 @@ + } + + this.ticketTracker.update(i, getTicketLevelAt(arraysetsorted), false); ++ return removed; // CraftBukkit + } + + public void addTicket(TicketType tickettype, ChunkCoordIntPair chunkcoordintpair, int i, T t0) { +@@ -198,19 +216,33 @@ + } + + public void addRegionTicket(TicketType tickettype, ChunkCoordIntPair chunkcoordintpair, int i, T t0) { ++ // CraftBukkit start ++ addRegionTicketAtDistance(tickettype, chunkcoordintpair, i, t0); ++ } ++ ++ public boolean addRegionTicketAtDistance(TicketType tickettype, ChunkCoordIntPair chunkcoordintpair, int i, T t0) { ++ // CraftBukkit end + Ticket ticket = new Ticket<>(tickettype, ChunkLevel.byStatus(FullChunkStatus.FULL) - i, t0); + long j = chunkcoordintpair.toLong(); + +- this.addTicket(j, ticket); ++ boolean added = this.addTicket(j, ticket); // CraftBukkit + this.tickingTicketsTracker.addTicket(j, ticket); ++ return added; // CraftBukkit + } + + public void removeRegionTicket(TicketType tickettype, ChunkCoordIntPair chunkcoordintpair, int i, T t0) { ++ // CraftBukkit start ++ removeRegionTicketAtDistance(tickettype, chunkcoordintpair, i, t0); ++ } ++ ++ public boolean removeRegionTicketAtDistance(TicketType tickettype, ChunkCoordIntPair chunkcoordintpair, int i, T t0) { ++ // CraftBukkit end + Ticket ticket = new Ticket<>(tickettype, ChunkLevel.byStatus(FullChunkStatus.FULL) - i, t0); + long j = chunkcoordintpair.toLong(); + +- this.removeTicket(j, ticket); ++ boolean removed = this.removeTicket(j, ticket); // CraftBukkit + this.tickingTicketsTracker.removeTicket(j, ticket); ++ return removed; // CraftBukkit + } + + private ArraySetSorted> getTickets(long i) { +@@ -249,6 +281,7 @@ + ChunkCoordIntPair chunkcoordintpair = sectionposition.chunk(); + long i = chunkcoordintpair.toLong(); + ObjectSet objectset = (ObjectSet) this.playersPerChunk.get(i); ++ if (objectset == null) return; // CraftBukkit - SPIGOT-6208 + + objectset.remove(entityplayer); + if (objectset.isEmpty()) { +@@ -378,6 +411,26 @@ + return !this.tickets.isEmpty(); + } + ++ // CraftBukkit start ++ public void removeAllTicketsFor(TicketType ticketType, int ticketLevel, T ticketIdentifier) { ++ Ticket target = new Ticket<>(ticketType, ticketLevel, ticketIdentifier); ++ ++ for (java.util.Iterator>>> iterator = this.tickets.long2ObjectEntrySet().fastIterator(); iterator.hasNext();) { ++ Entry>> entry = iterator.next(); ++ ArraySetSorted> tickets = entry.getValue(); ++ if (tickets.remove(target)) { ++ // copied from removeTicket ++ this.ticketTracker.update(entry.getLongKey(), getTicketLevelAt(tickets), false); ++ ++ // can't use entry after it's removed ++ if (tickets.isEmpty()) { ++ iterator.remove(); ++ } ++ } ++ } ++ } ++ // CraftBukkit end ++ + private class a extends ChunkMap { + + private static final int MAX_LEVEL = ChunkLevel.MAX_LEVEL + 1; diff --git a/patch-remap/og/net/minecraft/server/level/ChunkProviderServer.patch b/patch-remap/og/net/minecraft/server/level/ChunkProviderServer.patch new file mode 100644 index 0000000000..e12e4c657c --- /dev/null +++ b/patch-remap/og/net/minecraft/server/level/ChunkProviderServer.patch @@ -0,0 +1,146 @@ +--- a/net/minecraft/server/level/ChunkProviderServer.java ++++ b/net/minecraft/server/level/ChunkProviderServer.java +@@ -83,6 +83,16 @@ + this.clearCache(); + } + ++ // CraftBukkit start - properly implement isChunkLoaded ++ public boolean isChunkLoaded(int chunkX, int chunkZ) { ++ PlayerChunk chunk = this.chunkMap.getUpdatingChunkIfPresent(ChunkCoordIntPair.asLong(chunkX, chunkZ)); ++ if (chunk == null) { ++ return false; ++ } ++ return chunk.getFullChunkNow() != null; ++ } ++ // CraftBukkit end ++ + @Override + public LightEngineThreaded getLightEngine() { + return this.lightEngine; +@@ -127,7 +137,7 @@ + for (int l = 0; l < 4; ++l) { + if (k == this.lastChunkPos[l] && chunkstatus == this.lastChunkStatus[l]) { + ichunkaccess = this.lastChunk[l]; +- if (ichunkaccess != null || !flag) { ++ if (ichunkaccess != null) { // CraftBukkit - the chunk can become accessible in the meantime TODO for non-null chunks it might also make sense to check that the chunk's state hasn't changed in the meantime + return ichunkaccess; + } + } +@@ -175,12 +185,12 @@ + if (playerchunk == null) { + return null; + } else { +- Either either = (Either) playerchunk.getFutureIfPresent(ChunkStatus.FULL).getNow((Object) null); ++ Either either = (Either) playerchunk.getFutureIfPresent(ChunkStatus.FULL).getNow(null); // CraftBukkit - decompile error + + if (either == null) { + return null; + } else { +- IChunkAccess ichunkaccess1 = (IChunkAccess) either.left().orElse((Object) null); ++ IChunkAccess ichunkaccess1 = (IChunkAccess) either.left().orElse(null); // CraftBukkit - decompile error + + if (ichunkaccess1 != null) { + this.storeInCache(k, ichunkaccess1, ChunkStatus.FULL); +@@ -228,7 +238,15 @@ + int l = ChunkLevel.byStatus(chunkstatus); + PlayerChunk playerchunk = this.getVisibleChunkIfPresent(k); + +- if (flag) { ++ // CraftBukkit start - don't add new ticket for currently unloading chunk ++ boolean currentlyUnloading = false; ++ if (playerchunk != null) { ++ FullChunkStatus oldChunkState = ChunkLevel.fullStatus(playerchunk.oldTicketLevel); ++ FullChunkStatus currentChunkState = ChunkLevel.fullStatus(playerchunk.getTicketLevel()); ++ currentlyUnloading = (oldChunkState.isOrAfter(FullChunkStatus.FULL) && !currentChunkState.isOrAfter(FullChunkStatus.FULL)); ++ } ++ if (flag && !currentlyUnloading) { ++ // CraftBukkit end + this.distanceManager.addTicket(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); + if (this.chunkAbsent(playerchunk, l)) { + GameProfilerFiller gameprofilerfiller = this.level.getProfiler(); +@@ -247,7 +265,7 @@ + } + + private boolean chunkAbsent(@Nullable PlayerChunk playerchunk, int i) { +- return playerchunk == null || playerchunk.getTicketLevel() > i; ++ return playerchunk == null || playerchunk.oldTicketLevel > i; // CraftBukkit using oldTicketLevel for isLoaded checks + } + + @Override +@@ -315,7 +333,7 @@ + } else if (!this.level.shouldTickBlocksAt(i)) { + return false; + } else { +- Either either = (Either) playerchunk.getTickingChunkFuture().getNow((Object) null); ++ Either either = (Either) playerchunk.getTickingChunkFuture().getNow(null); // CraftBukkit - decompile error + + return either != null && either.left().isPresent(); + } +@@ -328,11 +346,31 @@ + + @Override + public void close() throws IOException { +- this.save(true); ++ // CraftBukkit start ++ close(true); ++ } ++ ++ public void close(boolean save) throws IOException { ++ if (save) { ++ this.save(true); ++ } ++ // CraftBukkit end + this.lightEngine.close(); + this.chunkMap.close(); + } + ++ // CraftBukkit start - modelled on below ++ public void purgeUnload() { ++ this.level.getProfiler().push("purge"); ++ this.distanceManager.purgeStaleTickets(); ++ this.runDistanceManagerUpdates(); ++ this.level.getProfiler().popPush("unload"); ++ this.chunkMap.tick(() -> true); ++ this.level.getProfiler().pop(); ++ this.clearCache(); ++ } ++ // CraftBukkit end ++ + @Override + public void tick(BooleanSupplier booleansupplier, boolean flag) { + this.level.getProfiler().push("purge"); +@@ -379,11 +417,11 @@ + + this.lastSpawnState = spawnercreature_d; + gameprofilerfiller.popPush("spawnAndTick"); +- boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING); ++ boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit + + SystemUtils.shuffle(list, this.level.random); + int l = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); +- boolean flag1 = this.level.getLevelData().getGameTime() % 400L == 0L; ++ boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit + Iterator iterator1 = list.iterator(); + + while (iterator1.hasNext()) { +@@ -586,13 +624,19 @@ + } + + @Override +- protected boolean pollTask() { ++ // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task ++ public boolean pollTask() { ++ try { + if (ChunkProviderServer.this.runDistanceManagerUpdates()) { + return true; + } else { + ChunkProviderServer.this.lightEngine.tryScheduleUpdate(); + return super.pollTask(); + } ++ } finally { ++ chunkMap.callbackExecutor.run(); ++ } ++ // CraftBukkit end + } + } + diff --git a/patch-remap/og/net/minecraft/server/level/EntityPlayer.patch b/patch-remap/og/net/minecraft/server/level/EntityPlayer.patch new file mode 100644 index 0000000000..28710b9df4 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/level/EntityPlayer.patch @@ -0,0 +1,1165 @@ +--- a/net/minecraft/server/level/EntityPlayer.java ++++ b/net/minecraft/server/level/EntityPlayer.java +@@ -157,6 +157,38 @@ + import net.minecraft.world.scores.criteria.IScoreboardCriteria; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.nbt.NBTBase; ++import net.minecraft.world.damagesource.CombatTracker; ++import net.minecraft.world.food.FoodMetaData; ++import net.minecraft.world.item.enchantment.EnchantmentManager; ++import net.minecraft.world.level.block.BlockChest; ++import net.minecraft.world.level.dimension.WorldDimension; ++import net.minecraft.world.scores.Scoreboard; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.WeatherType; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.CraftWorldBorder; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.event.CraftPortalEvent; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftDimensionUtil; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.entity.EntityExhaustionEvent; ++import org.bukkit.event.player.PlayerBedLeaveEvent; ++import org.bukkit.event.player.PlayerChangedMainHandEvent; ++import org.bukkit.event.player.PlayerChangedWorldEvent; ++import org.bukkit.event.player.PlayerLocaleChangeEvent; ++import org.bukkit.event.player.PlayerPortalEvent; ++import org.bukkit.event.player.PlayerSpawnChangeEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; ++import org.bukkit.event.player.PlayerToggleSneakEvent; ++import org.bukkit.inventory.MainHand; ++// CraftBukkit end ++ + public class EntityPlayer extends EntityHuman { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -192,7 +224,7 @@ + private int levitationStartTime; + private boolean disconnected; + private int requestedViewDistance; +- public String language; ++ public String language = "en_us"; // CraftBukkit - default + @Nullable + private Vec3D startingToFallPosition; + @Nullable +@@ -217,6 +249,20 @@ + private int containerCounter; + public boolean wonGame; + ++ // CraftBukkit start ++ public String displayName; ++ public IChatBaseComponent listName; ++ public org.bukkit.Location compassTarget; ++ public int newExp = 0; ++ public int newLevel = 0; ++ public int newTotalExp = 0; ++ public boolean keepLevel = false; ++ public double maxHealthCache; ++ public boolean joining = true; ++ public boolean sentListPacket = false; ++ public String kickLeaveMessage = null; // SPIGOT-3034: Forward leave message to PlayerQuitEvent ++ // CraftBukkit end ++ + public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, ClientInformation clientinformation) { + super(worldserver, worldserver.getSharedSpawnPos(), worldserver.getSharedSpawnAngle(), gameprofile); + this.chatVisibility = EnumChatVisibility.FULL; +@@ -283,12 +329,56 @@ + this.setMaxUpStep(1.0F); + this.fudgeSpawnLocation(worldserver); + this.updateOptions(clientinformation); ++ ++ // CraftBukkit start ++ this.displayName = this.getScoreboardName(); ++ this.bukkitPickUpLoot = true; ++ this.maxHealthCache = this.getMaxHealth(); ++ } ++ ++ // Yes, this doesn't match Vanilla, but it's the best we can do for now. ++ // If this is an issue, PRs are welcome ++ public final BlockPosition getSpawnPoint(WorldServer worldserver) { ++ BlockPosition blockposition = worldserver.getSharedSpawnPos(); ++ ++ if (worldserver.dimensionType().hasSkyLight() && worldserver.serverLevelData.getGameType() != EnumGamemode.ADVENTURE) { ++ int i = Math.max(0, this.server.getSpawnRadius(worldserver)); ++ int j = MathHelper.floor(worldserver.getWorldBorder().getDistanceToBorder((double) blockposition.getX(), (double) blockposition.getZ())); ++ ++ if (j < i) { ++ i = j; ++ } ++ ++ if (j <= 1) { ++ i = 1; ++ } ++ ++ long k = (long) (i * 2 + 1); ++ long l = k * k; ++ int i1 = l > 2147483647L ? Integer.MAX_VALUE : (int) l; ++ int j1 = this.getCoprime(i1); ++ int k1 = RandomSource.create().nextInt(i1); ++ ++ for (int l1 = 0; l1 < i1; ++l1) { ++ int i2 = (k1 + j1 * l1) % i1; ++ int j2 = i2 % (i * 2 + 1); ++ int k2 = i2 / (i * 2 + 1); ++ BlockPosition blockposition1 = WorldProviderNormal.getOverworldRespawnPos(worldserver, blockposition.getX() + j2 - i, blockposition.getZ() + k2 - i); ++ ++ if (blockposition1 != null) { ++ return blockposition1; ++ } ++ } ++ } ++ ++ return blockposition; + } ++ // CraftBukkit end + + private void fudgeSpawnLocation(WorldServer worldserver) { + BlockPosition blockposition = worldserver.getSharedSpawnPos(); + +- if (worldserver.dimensionType().hasSkyLight() && worldserver.getServer().getWorldData().getGameType() != EnumGamemode.ADVENTURE) { ++ if (worldserver.dimensionType().hasSkyLight() && worldserver.serverLevelData.getGameType() != EnumGamemode.ADVENTURE) { // CraftBukkit + int i = Math.max(0, this.server.getSpawnRadius(worldserver)); + int j = MathHelper.floor(worldserver.getWorldBorder().getDistanceToBorder((double) blockposition.getX(), (double) blockposition.getZ())); + +@@ -337,7 +427,7 @@ + public void readAdditionalSaveData(NBTTagCompound nbttagcompound) { + super.readAdditionalSaveData(nbttagcompound); + if (nbttagcompound.contains("warden_spawn_tracker", 10)) { +- DataResult dataresult = WardenSpawnTracker.CODEC.parse(new Dynamic(DynamicOpsNBT.INSTANCE, nbttagcompound.get("warden_spawn_tracker"))); ++ DataResult dataresult = WardenSpawnTracker.CODEC.parse(new Dynamic(DynamicOpsNBT.INSTANCE, nbttagcompound.get("warden_spawn_tracker"))); // CraftBukkit - decompile error + Logger logger = EntityPlayer.LOGGER; + + Objects.requireNonNull(logger); +@@ -356,17 +446,26 @@ + if (nbttagcompound.contains("recipeBook", 10)) { + this.recipeBook.fromNbt(nbttagcompound.getCompound("recipeBook"), this.server.getRecipeManager()); + } ++ this.getBukkitEntity().readExtraData(nbttagcompound); // CraftBukkit + + if (this.isSleeping()) { + this.stopSleeping(); + } + ++ // CraftBukkit start ++ String spawnWorld = nbttagcompound.getString("SpawnWorld"); ++ CraftWorld oldWorld = (CraftWorld) Bukkit.getWorld(spawnWorld); ++ if (oldWorld != null) { ++ this.respawnDimension = oldWorld.getHandle().dimension(); ++ } ++ // CraftBukkit end ++ + if (nbttagcompound.contains("SpawnX", 99) && nbttagcompound.contains("SpawnY", 99) && nbttagcompound.contains("SpawnZ", 99)) { + this.respawnPosition = new BlockPosition(nbttagcompound.getInt("SpawnX"), nbttagcompound.getInt("SpawnY"), nbttagcompound.getInt("SpawnZ")); + this.respawnForced = nbttagcompound.getBoolean("SpawnForced"); + this.respawnAngle = nbttagcompound.getFloat("SpawnAngle"); + if (nbttagcompound.contains("SpawnDimension")) { +- DataResult dataresult1 = World.RESOURCE_KEY_CODEC.parse(DynamicOpsNBT.INSTANCE, nbttagcompound.get("SpawnDimension")); ++ DataResult> dataresult1 = World.RESOURCE_KEY_CODEC.parse(DynamicOpsNBT.INSTANCE, nbttagcompound.get("SpawnDimension")); // CraftBukkit - decompile error + Logger logger1 = EntityPlayer.LOGGER; + + Objects.requireNonNull(logger1); +@@ -379,7 +478,7 @@ + @Override + public void addAdditionalSaveData(NBTTagCompound nbttagcompound) { + super.addAdditionalSaveData(nbttagcompound); +- DataResult dataresult = WardenSpawnTracker.CODEC.encodeStart(DynamicOpsNBT.INSTANCE, this.wardenSpawnTracker); ++ DataResult dataresult = WardenSpawnTracker.CODEC.encodeStart(DynamicOpsNBT.INSTANCE, this.wardenSpawnTracker); // CraftBukkit - decompile error + Logger logger = EntityPlayer.LOGGER; + + Objects.requireNonNull(logger); +@@ -400,7 +499,20 @@ + Entity entity = this.getRootVehicle(); + Entity entity1 = this.getVehicle(); + +- if (entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger()) { ++ // CraftBukkit start - handle non-persistent vehicles ++ boolean persistVehicle = true; ++ if (entity1 != null) { ++ Entity vehicle; ++ for (vehicle = entity1; vehicle != null; vehicle = vehicle.getVehicle()) { ++ if (!vehicle.persist) { ++ persistVehicle = false; ++ break; ++ } ++ } ++ } ++ ++ if (persistVehicle && entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger()) { ++ // CraftBukkit end + NBTTagCompound nbttagcompound2 = new NBTTagCompound(); + NBTTagCompound nbttagcompound3 = new NBTTagCompound(); + +@@ -425,8 +537,32 @@ + nbttagcompound.put("SpawnDimension", nbtbase); + }); + } ++ this.getBukkitEntity().setExtraData(nbttagcompound); // CraftBukkit ++ ++ } + ++ // CraftBukkit start - World fallback code, either respawn location or global spawn ++ public void spawnIn(World world) { ++ this.setLevel(world); ++ if (world == null) { ++ this.unsetRemoved(); ++ Vec3D position = null; ++ if (this.respawnDimension != null) { ++ world = this.server.getLevel(this.respawnDimension); ++ if (world != null && this.getRespawnPosition() != null) { ++ position = EntityHuman.findRespawnPositionAndUseSpawnBlock((WorldServer) world, this.getRespawnPosition(), this.getRespawnAngle(), false, false).orElse(null); ++ } ++ } ++ if (world == null || position == null) { ++ world = ((CraftWorld) Bukkit.getServer().getWorlds().get(0)).getHandle(); ++ position = Vec3D.atCenterOf(world.getSharedSpawnPos()); ++ } ++ this.setLevel(world); ++ this.setPos(position); ++ } ++ this.gameMode.setLevel((WorldServer) world); + } ++ // CraftBukkit end + + public void setExperiencePoints(int i) { + float f = (float) this.getXpNeededForNextLevel(); +@@ -486,6 +622,11 @@ + + @Override + public void tick() { ++ // CraftBukkit start ++ if (this.joining) { ++ this.joining = false; ++ } ++ // CraftBukkit end + this.gameMode.tick(); + this.wardenSpawnTracker.tick(); + --this.spawnInvulnerableTime; +@@ -542,7 +683,7 @@ + } + + if (this.getHealth() != this.lastSentHealth || this.lastSentFood != this.foodData.getFoodLevel() || this.foodData.getSaturationLevel() == 0.0F != this.lastFoodSaturationZero) { +- this.connection.send(new PacketPlayOutUpdateHealth(this.getHealth(), this.foodData.getFoodLevel(), this.foodData.getSaturationLevel())); ++ this.connection.send(new PacketPlayOutUpdateHealth(this.getBukkitEntity().getScaledHealth(), this.foodData.getFoodLevel(), this.foodData.getSaturationLevel())); // CraftBukkit + this.lastSentHealth = this.getHealth(); + this.lastSentFood = this.foodData.getFoodLevel(); + this.lastFoodSaturationZero = this.foodData.getSaturationLevel() == 0.0F; +@@ -573,6 +714,12 @@ + this.updateScoreForCriteria(IScoreboardCriteria.EXPERIENCE, MathHelper.ceil((float) this.lastRecordedExperience)); + } + ++ // CraftBukkit start - Force max health updates ++ if (this.maxHealthCache != this.getMaxHealth()) { ++ this.getBukkitEntity().updateScaledHealth(); ++ } ++ // CraftBukkit end ++ + if (this.experienceLevel != this.lastRecordedLevel) { + this.lastRecordedLevel = this.experienceLevel; + this.updateScoreForCriteria(IScoreboardCriteria.LEVEL, MathHelper.ceil((float) this.lastRecordedLevel)); +@@ -587,6 +734,20 @@ + CriterionTriggers.LOCATION.trigger(this); + } + ++ // CraftBukkit start - initialize oldLevel, fire PlayerLevelChangeEvent, and tick client-sided world border ++ if (this.oldLevel == -1) { ++ this.oldLevel = this.experienceLevel; ++ } ++ ++ if (this.oldLevel != this.experienceLevel) { ++ CraftEventFactory.callPlayerLevelChangeEvent(this.getBukkitEntity(), this.oldLevel, this.experienceLevel); ++ this.oldLevel = this.experienceLevel; ++ } ++ ++ if (this.getBukkitEntity().hasClientWorldBorder()) { ++ ((CraftWorldBorder) this.getBukkitEntity().getWorldBorder()).getHandle().tick(); ++ } ++ // CraftBukkit end + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking player"); + CrashReportSystemDetails crashreportsystemdetails = crashreport.addCategory("Player being ticked"); +@@ -629,7 +790,8 @@ + } + + private void updateScoreForCriteria(IScoreboardCriteria iscoreboardcriteria, int i) { +- this.getScoreboard().forAllObjectives(iscoreboardcriteria, this, (scoreaccess) -> { ++ // CraftBukkit - Use our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(iscoreboardcriteria, this, (scoreaccess) -> { + scoreaccess.set(i); + }); + } +@@ -638,9 +800,47 @@ + public void die(DamageSource damagesource) { + this.gameEvent(GameEvent.ENTITY_DIE); + boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); ++ // CraftBukkit start - fire PlayerDeathEvent ++ if (this.isRemoved()) { ++ return; ++ } ++ java.util.List loot = new java.util.ArrayList(this.getInventory().getContainerSize()); ++ boolean keepInventory = this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || this.isSpectator(); + +- if (flag) { +- IChatBaseComponent ichatbasecomponent = this.getCombatTracker().getDeathMessage(); ++ if (!keepInventory) { ++ for (ItemStack item : this.getInventory().getContents()) { ++ if (!item.isEmpty() && !EnchantmentManager.hasVanishingCurse(item)) { ++ loot.add(CraftItemStack.asCraftMirror(item)); ++ } ++ } ++ } ++ // SPIGOT-5071: manually add player loot tables (SPIGOT-5195 - ignores keepInventory rule) ++ this.dropFromLootTable(damagesource, this.lastHurtByPlayerTime > 0); ++ for (org.bukkit.inventory.ItemStack item : this.drops) { ++ loot.add(item); ++ } ++ this.drops.clear(); // SPIGOT-5188: make sure to clear ++ ++ IChatBaseComponent defaultMessage = this.getCombatTracker().getDeathMessage(); ++ ++ String deathmessage = defaultMessage.getString(); ++ keepLevel = keepInventory; // SPIGOT-2222: pre-set keepLevel ++ org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, deathmessage, keepInventory); ++ ++ // SPIGOT-943 - only call if they have an inventory open ++ if (this.containerMenu != this.inventoryMenu) { ++ this.closeContainer(); ++ } ++ ++ String deathMessage = event.getDeathMessage(); ++ ++ if (deathMessage != null && deathMessage.length() > 0 && flag) { // TODO: allow plugins to override? ++ IChatBaseComponent ichatbasecomponent; ++ if (deathMessage.equals(deathmessage)) { ++ ichatbasecomponent = this.getCombatTracker().getDeathMessage(); ++ } else { ++ ichatbasecomponent = org.bukkit.craftbukkit.util.CraftChatMessage.fromStringOrNull(deathMessage); ++ } + + this.connection.send(new ClientboundPlayerCombatKillPacket(this.getId(), ichatbasecomponent), PacketSendListener.exceptionallySend(() -> { + boolean flag1 = true; +@@ -671,12 +871,18 @@ + if (this.level().getGameRules().getBoolean(GameRules.RULE_FORGIVE_DEAD_PLAYERS)) { + this.tellNeutralMobsThatIDied(); + } +- +- if (!this.isSpectator()) { +- this.dropAllDeathLoot(damagesource); ++ // SPIGOT-5478 must be called manually now ++ this.dropExperience(); ++ // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. ++ if (!event.getKeepInventory()) { ++ this.getInventory().clearContent(); + } + +- this.getScoreboard().forAllObjectives(IScoreboardCriteria.DEATH_COUNT, this, ScoreAccess::increment); ++ this.setCamera(this); // Remove spectated target ++ // CraftBukkit end ++ ++ // CraftBukkit - Get our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(IScoreboardCriteria.DEATH_COUNT, this, ScoreAccess::increment); + EntityLiving entityliving = this.getKillCredit(); + + if (entityliving != null) { +@@ -711,10 +917,12 @@ + if (entity != this) { + super.awardKillScore(entity, i, damagesource); + this.increaseScore(i); +- this.getScoreboard().forAllObjectives(IScoreboardCriteria.KILL_COUNT_ALL, this, ScoreAccess::increment); ++ // CraftBukkit - Get our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(IScoreboardCriteria.KILL_COUNT_ALL, this, ScoreAccess::increment); + if (entity instanceof EntityHuman) { + this.awardStat(StatisticList.PLAYER_KILLS); +- this.getScoreboard().forAllObjectives(IScoreboardCriteria.KILL_COUNT_PLAYERS, this, ScoreAccess::increment); ++ // CraftBukkit - Get our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(IScoreboardCriteria.KILL_COUNT_PLAYERS, this, ScoreAccess::increment); + } else { + this.awardStat(StatisticList.MOB_KILLS); + } +@@ -732,7 +940,8 @@ + int i = scoreboardteam.getColor().getId(); + + if (i >= 0 && i < aiscoreboardcriteria.length) { +- this.getScoreboard().forAllObjectives(aiscoreboardcriteria[i], scoreholder, ScoreAccess::increment); ++ // CraftBukkit - Get our scores instead ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(aiscoreboardcriteria[i], scoreholder, ScoreAccess::increment); + } + } + +@@ -782,18 +991,20 @@ + } + + private boolean isPvpAllowed() { +- return this.server.isPvpAllowed(); ++ // CraftBukkit - this.server.isPvpAllowed() -> this.world.pvpMode ++ return this.level().pvpMode; + } + + @Nullable + @Override + protected ShapeDetectorShape findDimensionEntryPoint(WorldServer worldserver) { + ShapeDetectorShape shapedetectorshape = super.findDimensionEntryPoint(worldserver); ++ worldserver = (shapedetectorshape == null) ? worldserver : shapedetectorshape.world; // CraftBukkit + +- if (shapedetectorshape != null && this.level().dimension() == World.OVERWORLD && worldserver.dimension() == World.END) { ++ if (shapedetectorshape != null && this.level().getTypeKey() == WorldDimension.OVERWORLD && worldserver != null && worldserver.getTypeKey() == WorldDimension.END) { // CraftBukkit + Vec3D vec3d = shapedetectorshape.pos.add(0.0D, -1.0D, 0.0D); + +- return new ShapeDetectorShape(vec3d, Vec3D.ZERO, 90.0F, 0.0F); ++ return new ShapeDetectorShape(vec3d, Vec3D.ZERO, 90.0F, 0.0F, worldserver, shapedetectorshape.portalEventInfo); // CraftBukkit + } else { + return shapedetectorshape; + } +@@ -802,11 +1013,20 @@ + @Nullable + @Override + public Entity changeDimension(WorldServer worldserver) { +- this.isChangingDimension = true; ++ // CraftBukkit start ++ return changeDimension(worldserver, TeleportCause.UNKNOWN); ++ } ++ ++ @Nullable ++ public Entity changeDimension(WorldServer worldserver, PlayerTeleportEvent.TeleportCause cause) { ++ // CraftBukkit end ++ if (this.isSleeping()) return this; // CraftBukkit - SPIGOT-3154 ++ // this.isChangingDimension = true; // CraftBukkit - Moved down and into PlayerList#changeDimension + WorldServer worldserver1 = this.serverLevel(); +- ResourceKey resourcekey = worldserver1.dimension(); ++ ResourceKey resourcekey = worldserver1.getTypeKey(); // CraftBukkit + +- if (resourcekey == World.END && worldserver.dimension() == World.OVERWORLD) { ++ if (resourcekey == WorldDimension.END && worldserver != null && worldserver.getTypeKey() == WorldDimension.OVERWORLD) { // CraftBukkit ++ this.isChangingDimension = true; // CraftBukkit - Moved down from above + this.unRide(); + this.serverLevel().removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); + if (!this.wonGame) { +@@ -817,6 +1037,8 @@ + + return this; + } else { ++ // CraftBukkit start ++ /* + WorldData worlddata = worldserver.getLevelData(); + + this.connection.send(new PacketPlayOutRespawn(this.createCommonSpawnInfo(worldserver), (byte) 3)); +@@ -826,20 +1048,50 @@ + playerlist.sendPlayerPermissionLevel(this); + worldserver1.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); + this.unsetRemoved(); ++ */ ++ // CraftBukkit end + ShapeDetectorShape shapedetectorshape = this.findDimensionEntryPoint(worldserver); + + if (shapedetectorshape != null) { + worldserver1.getProfiler().push("moving"); +- if (resourcekey == World.OVERWORLD && worldserver.dimension() == World.NETHER) { ++ worldserver = shapedetectorshape.world; // CraftBukkit ++ if (worldserver == null) { } else // CraftBukkit - empty to fall through to null to event ++ if (resourcekey == WorldDimension.OVERWORLD && worldserver.getTypeKey() == WorldDimension.NETHER) { // CraftBukkit + this.enteredNetherPosition = this.position(); +- } else if (worldserver.dimension() == World.END) { ++ } else if (worldserver.getTypeKey() == WorldDimension.END && shapedetectorshape.portalEventInfo != null && shapedetectorshape.portalEventInfo.getCanCreatePortal()) { // CraftBukkit + this.createEndPlatform(worldserver, BlockPosition.containing(shapedetectorshape.pos)); + } ++ // CraftBukkit start ++ } else { ++ return null; ++ } ++ Location enter = this.getBukkitEntity().getLocation(); ++ Location exit = (worldserver == null) ? null : CraftLocation.toBukkit(shapedetectorshape.pos, worldserver.getWorld(), shapedetectorshape.yRot, shapedetectorshape.xRot); ++ PlayerTeleportEvent tpEvent = new PlayerTeleportEvent(this.getBukkitEntity(), enter, exit, cause); ++ Bukkit.getServer().getPluginManager().callEvent(tpEvent); ++ if (tpEvent.isCancelled() || tpEvent.getTo() == null) { ++ return null; ++ } ++ exit = tpEvent.getTo(); ++ worldserver = ((CraftWorld) exit.getWorld()).getHandle(); ++ // CraftBukkit end + +- worldserver1.getProfiler().pop(); +- worldserver1.getProfiler().push("placing"); ++ worldserver1.getProfiler().pop(); ++ worldserver1.getProfiler().push("placing"); ++ if (true) { // CraftBukkit ++ this.isChangingDimension = true; // CraftBukkit - Set teleport invulnerability only if player changing worlds ++ ++ this.connection.send(new PacketPlayOutRespawn(this.createCommonSpawnInfo(worldserver), (byte) 3)); ++ this.connection.send(new PacketPlayOutServerDifficulty(this.level().getDifficulty(), this.level().getLevelData().isDifficultyLocked())); ++ PlayerList playerlist = this.server.getPlayerList(); ++ ++ playerlist.sendPlayerPermissionLevel(this); ++ worldserver1.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); ++ this.unsetRemoved(); ++ ++ // CraftBukkit end + this.setServerLevel(worldserver); +- this.connection.teleport(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, shapedetectorshape.xRot); ++ this.connection.teleport(exit); // CraftBukkit - use internal teleport without event + this.connection.resetPosition(); + worldserver.addDuringPortalTeleport(this); + worldserver1.getProfiler().pop(); +@@ -859,39 +1111,66 @@ + this.lastSentExp = -1; + this.lastSentHealth = -1.0F; + this.lastSentFood = -1; ++ ++ // CraftBukkit start ++ PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.getBukkitEntity(), worldserver1.getWorld()); ++ this.level().getCraftServer().getPluginManager().callEvent(changeEvent); ++ // CraftBukkit end + } + + return this; + } + } + ++ // CraftBukkit start ++ @Override ++ protected CraftPortalEvent callPortalEvent(Entity entity, WorldServer exitWorldServer, Vec3D exitPosition, TeleportCause cause, int searchRadius, int creationRadius) { ++ Location enter = this.getBukkitEntity().getLocation(); ++ Location exit = CraftLocation.toBukkit(exitPosition, exitWorldServer.getWorld(), getYRot(), getXRot()); ++ PlayerPortalEvent event = new PlayerPortalEvent(this.getBukkitEntity(), enter, exit, cause, searchRadius, true, creationRadius); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null) { ++ return null; ++ } ++ return new CraftPortalEvent(event); ++ } ++ // CraftBukkit end ++ + private void createEndPlatform(WorldServer worldserver, BlockPosition blockposition) { + BlockPosition.MutableBlockPosition blockposition_mutableblockposition = blockposition.mutable(); ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(worldserver); // CraftBukkit + + for (int i = -2; i <= 2; ++i) { + for (int j = -2; j <= 2; ++j) { + for (int k = -1; k < 3; ++k) { + IBlockData iblockdata = k == -1 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); + +- worldserver.setBlockAndUpdate(blockposition_mutableblockposition.set(blockposition).move(j, k, i), iblockdata); ++ blockList.setBlock(blockposition_mutableblockposition.set(blockposition).move(j, k, i), iblockdata, 3); // CraftBukkit + } + } + } ++ // CraftBukkit start - call portal event ++ org.bukkit.event.world.PortalCreateEvent portalEvent = new org.bukkit.event.world.PortalCreateEvent((List) (List) blockList.getList(), worldserver.getWorld(), this.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM); ++ worldserver.getCraftServer().getPluginManager().callEvent(portalEvent); ++ if (!portalEvent.isCancelled()) { ++ blockList.updateList(); ++ } ++ // CraftBukkit end + + } + + @Override +- protected Optional getExitPortal(WorldServer worldserver, BlockPosition blockposition, boolean flag, WorldBorder worldborder) { +- Optional optional = super.getExitPortal(worldserver, blockposition, flag, worldborder); ++ protected Optional getExitPortal(WorldServer worldserver, BlockPosition blockposition, boolean flag, WorldBorder worldborder, int searchRadius, boolean canCreatePortal, int createRadius) { // CraftBukkit ++ Optional optional = super.getExitPortal(worldserver, blockposition, flag, worldborder, searchRadius, canCreatePortal, createRadius); // CraftBukkit + +- if (optional.isPresent()) { ++ if (optional.isPresent() || !canCreatePortal) { // CraftBukkit + return optional; + } else { + EnumDirection.EnumAxis enumdirection_enumaxis = (EnumDirection.EnumAxis) this.level().getBlockState(this.portalEntrancePos).getOptionalValue(BlockPortal.AXIS).orElse(EnumDirection.EnumAxis.X); +- Optional optional1 = worldserver.getPortalForcer().createPortal(blockposition, enumdirection_enumaxis); ++ Optional optional1 = worldserver.getPortalForcer().createPortal(blockposition, enumdirection_enumaxis, this, createRadius); // CraftBukkit + + if (optional1.isEmpty()) { +- EntityPlayer.LOGGER.error("Unable to create a portal, likely target out of worldborder"); ++ // EntityPlayer.LOGGER.error("Unable to create a portal, likely target out of worldborder"); // CraftBukkit + } + + return optional1; +@@ -901,13 +1180,21 @@ + public void triggerDimensionChangeTriggers(WorldServer worldserver) { + ResourceKey resourcekey = worldserver.dimension(); + ResourceKey resourcekey1 = this.level().dimension(); ++ // CraftBukkit start ++ ResourceKey maindimensionkey = CraftDimensionUtil.getMainDimensionKey(worldserver); ++ ResourceKey maindimensionkey1 = CraftDimensionUtil.getMainDimensionKey(this.level()); + +- CriterionTriggers.CHANGED_DIMENSION.trigger(this, resourcekey, resourcekey1); +- if (resourcekey == World.NETHER && resourcekey1 == World.OVERWORLD && this.enteredNetherPosition != null) { ++ CriterionTriggers.CHANGED_DIMENSION.trigger(this, maindimensionkey, maindimensionkey1); ++ if (maindimensionkey != resourcekey || maindimensionkey1 != resourcekey1) { ++ CriterionTriggers.CHANGED_DIMENSION.trigger(this, resourcekey, resourcekey1); ++ } ++ ++ if (maindimensionkey == World.NETHER && maindimensionkey1 == World.OVERWORLD && this.enteredNetherPosition != null) { ++ // CraftBukkit end + CriterionTriggers.NETHER_TRAVEL.trigger(this, this.enteredNetherPosition); + } + +- if (resourcekey1 != World.NETHER) { ++ if (maindimensionkey1 != World.NETHER) { // CraftBukkit + this.enteredNetherPosition = null; + } + +@@ -924,19 +1211,17 @@ + this.containerMenu.broadcastChanges(); + } + +- @Override +- public Either startSleepInBed(BlockPosition blockposition) { +- EnumDirection enumdirection = (EnumDirection) this.level().getBlockState(blockposition).getValue(BlockFacingHorizontal.FACING); +- ++ // CraftBukkit start - moved bed result checks from below into separate method ++ private Either getBedResult(BlockPosition blockposition, EnumDirection enumdirection) { + if (!this.isSleeping() && this.isAlive()) { +- if (!this.level().dimensionType().natural()) { ++ if (!this.level().dimensionType().natural() || !this.level().dimensionType().bedWorks()) { + return Either.left(EntityHuman.EnumBedResult.NOT_POSSIBLE_HERE); + } else if (!this.bedInRange(blockposition, enumdirection)) { + return Either.left(EntityHuman.EnumBedResult.TOO_FAR_AWAY); + } else if (this.bedBlocked(blockposition, enumdirection)) { + return Either.left(EntityHuman.EnumBedResult.OBSTRUCTED); + } else { +- this.setRespawnPosition(this.level().dimension(), blockposition, this.getYRot(), false, true); ++ this.setRespawnPosition(this.level().dimension(), blockposition, this.getYRot(), false, true, PlayerSpawnChangeEvent.Cause.BED); // CraftBukkit + if (this.level().isDay()) { + return Either.left(EntityHuman.EnumBedResult.NOT_POSSIBLE_NOW); + } else { +@@ -953,7 +1238,36 @@ + } + } + +- Either either = super.startSleepInBed(blockposition).ifRight((unit) -> { ++ return Either.right(Unit.INSTANCE); ++ } ++ } ++ } else { ++ return Either.left(EntityHuman.EnumBedResult.OTHER_PROBLEM); ++ } ++ } ++ ++ @Override ++ public Either startSleepInBed(BlockPosition blockposition, boolean force) { ++ EnumDirection enumdirection = (EnumDirection) this.level().getBlockState(blockposition).getValue(BlockFacingHorizontal.FACING); ++ Either bedResult = this.getBedResult(blockposition, enumdirection); ++ ++ if (bedResult.left().orElse(null) == EntityHuman.EnumBedResult.OTHER_PROBLEM) { ++ return bedResult; // return immediately if the result is not bypassable by plugins ++ } ++ ++ if (force) { ++ bedResult = Either.right(Unit.INSTANCE); ++ } ++ ++ bedResult = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBedEnterEvent(this, blockposition, bedResult); ++ if (bedResult.left().isPresent()) { ++ return bedResult; ++ } ++ ++ { ++ { ++ { ++ Either either = super.startSleepInBed(blockposition, force).ifRight((unit) -> { + this.awardStat(StatisticList.SLEEP_IN_BED); + CriterionTriggers.SLEPT_IN_BED.trigger(this); + }); +@@ -966,9 +1280,8 @@ + return either; + } + } +- } else { +- return Either.left(EntityHuman.EnumBedResult.OTHER_PROBLEM); + } ++ // CraftBukkit end + } + + @Override +@@ -995,13 +1308,31 @@ + + @Override + public void stopSleepInBed(boolean flag, boolean flag1) { ++ if (!this.isSleeping()) return; // CraftBukkit - Can't leave bed if not in one! ++ // CraftBukkit start - fire PlayerBedLeaveEvent ++ CraftPlayer player = this.getBukkitEntity(); ++ BlockPosition bedPosition = this.getSleepingPos().orElse(null); ++ ++ org.bukkit.block.Block bed; ++ if (bedPosition != null) { ++ bed = this.level().getWorld().getBlockAt(bedPosition.getX(), bedPosition.getY(), bedPosition.getZ()); ++ } else { ++ bed = this.level().getWorld().getBlockAt(player.getLocation()); ++ } ++ ++ PlayerBedLeaveEvent event = new PlayerBedLeaveEvent(player, bed, true); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + if (this.isSleeping()) { + this.serverLevel().getChunkSource().broadcastAndSend(this, new PacketPlayOutAnimation(this, 2)); + } + + super.stopSleepInBed(flag, flag1); + if (this.connection != null) { +- this.connection.teleport(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); ++ this.connection.teleport(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot(), TeleportCause.EXIT_BED); // CraftBukkit + } + + } +@@ -1051,8 +1382,9 @@ + this.connection.send(new PacketPlayOutOpenSignEditor(tileentitysign.getBlockPos(), flag)); + } + +- public void nextContainerCounter() { ++ public int nextContainerCounter() { // CraftBukkit - void -> int + this.containerCounter = this.containerCounter % 100 + 1; ++ return containerCounter; // CraftBukkit + } + + @Override +@@ -1060,13 +1392,35 @@ + if (itileinventory == null) { + return OptionalInt.empty(); + } else { ++ // CraftBukkit start - SPIGOT-6552: Handle inventory closing in CraftEventFactory#callInventoryOpenEvent(...) ++ /* + if (this.containerMenu != this.inventoryMenu) { + this.closeContainer(); + } ++ */ ++ // CraftBukkit end + + this.nextContainerCounter(); + Container container = itileinventory.createMenu(this.containerCounter, this.getInventory(), this); + ++ // CraftBukkit start - Inventory open hook ++ if (container != null) { ++ container.setTitle(itileinventory.getDisplayName()); ++ ++ boolean cancelled = false; ++ container = CraftEventFactory.callInventoryOpenEvent(this, container, cancelled); ++ if (container == null && !cancelled) { // Let pre-cancelled events fall through ++ // SPIGOT-5263 - close chest if cancelled ++ if (itileinventory instanceof IInventory) { ++ ((IInventory) itileinventory).stopOpen(this); ++ } else if (itileinventory instanceof BlockChest.DoubleInventory) { ++ // SPIGOT-5355 - double chests too :( ++ ((BlockChest.DoubleInventory) itileinventory).inventorylargechest.stopOpen(this); ++ } ++ return OptionalInt.empty(); ++ } ++ } ++ // CraftBukkit end + if (container == null) { + if (this.isSpectator()) { + this.displayClientMessage(IChatBaseComponent.translatable("container.spectatorCantOpen").withStyle(EnumChatFormat.RED), true); +@@ -1074,9 +1428,11 @@ + + return OptionalInt.empty(); + } else { +- this.connection.send(new PacketPlayOutOpenWindow(container.containerId, container.getType(), itileinventory.getDisplayName())); +- this.initMenu(container); ++ // CraftBukkit start + this.containerMenu = container; ++ this.connection.send(new PacketPlayOutOpenWindow(container.containerId, container.getType(), container.getTitle())); ++ // CraftBukkit end ++ this.initMenu(container); + return OptionalInt.of(this.containerCounter); + } + } +@@ -1089,13 +1445,24 @@ + + @Override + public void openHorseInventory(EntityHorseAbstract entityhorseabstract, IInventory iinventory) { ++ // CraftBukkit start - Inventory open hook ++ this.nextContainerCounter(); ++ Container container = new ContainerHorse(this.containerCounter, this.getInventory(), iinventory, entityhorseabstract); ++ container.setTitle(entityhorseabstract.getDisplayName()); ++ container = CraftEventFactory.callInventoryOpenEvent(this, container); ++ ++ if (container == null) { ++ iinventory.stopOpen(this); ++ return; ++ } ++ // CraftBukkit end + if (this.containerMenu != this.inventoryMenu) { + this.closeContainer(); + } + +- this.nextContainerCounter(); ++ // this.nextContainerCounter(); // CraftBukkit - moved up + this.connection.send(new PacketPlayOutOpenWindowHorse(this.containerCounter, iinventory.getContainerSize(), entityhorseabstract.getId())); +- this.containerMenu = new ContainerHorse(this.containerCounter, this.getInventory(), iinventory, entityhorseabstract); ++ this.containerMenu = container; // CraftBukkit + this.initMenu(this.containerMenu); + } + +@@ -1118,6 +1485,7 @@ + + @Override + public void closeContainer() { ++ CraftEventFactory.handleInventoryCloseEvent(this); // CraftBukkit + this.connection.send(new PacketPlayOutCloseWindow(this.containerMenu.containerId)); + this.doCloseContainer(); + } +@@ -1140,6 +1508,16 @@ + } + + this.jumping = flag; ++ // CraftBukkit start ++ if (flag1 != this.isShiftKeyDown()) { ++ PlayerToggleSneakEvent event = new PlayerToggleSneakEvent(this.getBukkitEntity(), flag1); ++ this.server.server.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + this.setShiftKeyDown(flag1); + } + +@@ -1173,19 +1551,19 @@ + i = Math.round((float) Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2) * 100.0F); + if (i > 0) { + this.awardStat(StatisticList.SWIM_ONE_CM, i); +- this.causeFoodExhaustion(0.01F * (float) i * 0.01F); ++ this.causeFoodExhaustion(0.01F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.SWIM); // CraftBukkit - EntityExhaustionEvent + } + } else if (this.isEyeInFluid(TagsFluid.WATER)) { + i = Math.round((float) Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2) * 100.0F); + if (i > 0) { + this.awardStat(StatisticList.WALK_UNDER_WATER_ONE_CM, i); +- this.causeFoodExhaustion(0.01F * (float) i * 0.01F); ++ this.causeFoodExhaustion(0.01F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.WALK_UNDERWATER); // CraftBukkit - EntityExhaustionEvent + } + } else if (this.isInWater()) { + i = Math.round((float) Math.sqrt(d0 * d0 + d2 * d2) * 100.0F); + if (i > 0) { + this.awardStat(StatisticList.WALK_ON_WATER_ONE_CM, i); +- this.causeFoodExhaustion(0.01F * (float) i * 0.01F); ++ this.causeFoodExhaustion(0.01F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.WALK_ON_WATER); // CraftBukkit - EntityExhaustionEvent + } + } else if (this.onClimbable()) { + if (d1 > 0.0D) { +@@ -1196,13 +1574,13 @@ + if (i > 0) { + if (this.isSprinting()) { + this.awardStat(StatisticList.SPRINT_ONE_CM, i); +- this.causeFoodExhaustion(0.1F * (float) i * 0.01F); ++ this.causeFoodExhaustion(0.1F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.SPRINT); // CraftBukkit - EntityExhaustionEvent + } else if (this.isCrouching()) { + this.awardStat(StatisticList.CROUCH_ONE_CM, i); +- this.causeFoodExhaustion(0.0F * (float) i * 0.01F); ++ this.causeFoodExhaustion(0.0F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.CROUCH); // CraftBukkit - EntityExhaustionEvent + } else { + this.awardStat(StatisticList.WALK_ONE_CM, i); +- this.causeFoodExhaustion(0.0F * (float) i * 0.01F); ++ this.causeFoodExhaustion(0.0F * (float) i * 0.01F, EntityExhaustionEvent.ExhaustionReason.WALK); // CraftBukkit - EntityExhaustionEvent + } + } + } else if (this.isFallFlying()) { +@@ -1245,7 +1623,7 @@ + @Override + public void awardStat(Statistic statistic, int i) { + this.stats.increment(this, statistic, i); +- this.getScoreboard().forAllObjectives(statistic, this, (scoreaccess) -> { ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(statistic, this, (scoreaccess) -> { + scoreaccess.add(i); + }); + } +@@ -1253,7 +1631,7 @@ + @Override + public void resetStat(Statistic statistic) { + this.stats.setValue(this, statistic, 0); +- this.getScoreboard().forAllObjectives(statistic, this, ScoreAccess::reset); ++ this.level().getCraftServer().getScoreboardManager().forAllObjectives(statistic, this, ScoreAccess::reset); // CraftBukkit - Get our scores instead + } + + @Override +@@ -1301,6 +1679,7 @@ + + public void resetSentInfo() { + this.lastSentHealth = -1.0E8F; ++ this.lastSentExp = -1; // CraftBukkit - Added to reset + } + + @Override +@@ -1358,7 +1737,7 @@ + this.lastSentExp = -1; + this.lastSentHealth = -1.0F; + this.lastSentFood = -1; +- this.recipeBook.copyOverData(entityplayer.recipeBook); ++ // this.recipeBook.copyOverData(entityplayer.recipeBook); // CraftBukkit + this.seenCredits = entityplayer.seenCredits; + this.enteredNetherPosition = entityplayer.enteredNetherPosition; + this.chunkTrackingView = entityplayer.chunkTrackingView; +@@ -1409,6 +1788,12 @@ + + @Override + public boolean teleportTo(WorldServer worldserver, double d0, double d1, double d2, Set set, float f, float f1) { ++ // CraftBukkit start ++ return teleportTo(worldserver, d0, d1, d2, set, f, f1, TeleportCause.UNKNOWN); ++ } ++ ++ public boolean teleportTo(WorldServer worldserver, double d0, double d1, double d2, Set set, float f, float f1, TeleportCause cause) { ++ // CraftBukkit end + ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(BlockPosition.containing(d0, d1, d2)); + + worldserver.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, chunkcoordintpair, 1, this.getId()); +@@ -1418,9 +1803,9 @@ + } + + if (worldserver == this.level()) { +- this.connection.teleport(d0, d1, d2, f, f1, set); ++ this.connection.teleport(d0, d1, d2, f, f1, set, cause); // CraftBukkit + } else { +- this.teleportTo(worldserver, d0, d1, d2, f, f1); ++ this.teleportTo(worldserver, d0, d1, d2, f, f1, cause); // CraftBukkit + } + + this.setYHeadRot(f); +@@ -1524,6 +1909,16 @@ + } + + public void updateOptions(ClientInformation clientinformation) { ++ // CraftBukkit start ++ if (getMainArm() != clientinformation.mainHand()) { ++ PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(getBukkitEntity(), getMainArm() == EnumMainHand.LEFT ? MainHand.LEFT : MainHand.RIGHT); ++ this.server.server.getPluginManager().callEvent(event); ++ } ++ if (!this.language.equals(clientinformation.language())) { ++ PlayerLocaleChangeEvent event = new PlayerLocaleChangeEvent(getBukkitEntity(), clientinformation.language()); ++ this.server.server.getPluginManager().callEvent(event); ++ } ++ // CraftBukkit end + this.language = clientinformation.language(); + this.requestedViewDistance = clientinformation.viewDistance(); + this.chatVisibility = clientinformation.chatVisibility(); +@@ -1607,7 +2002,7 @@ + if (world instanceof WorldServer) { + WorldServer worldserver = (WorldServer) world; + +- this.teleportTo(worldserver, this.camera.getX(), this.camera.getY(), this.camera.getZ(), Set.of(), this.getYRot(), this.getXRot()); ++ this.teleportTo(worldserver, this.camera.getX(), this.camera.getY(), this.camera.getZ(), Set.of(), this.getYRot(), this.getXRot(), TeleportCause.SPECTATE); // CraftBukkit + } + + if (entity != null) { +@@ -1644,7 +2039,7 @@ + + @Nullable + public IChatBaseComponent getTabListDisplayName() { +- return null; ++ return listName; // CraftBukkit + } + + @Override +@@ -1665,9 +2060,16 @@ + return this.advancements; + } + ++ // CraftBukkit start + public void teleportTo(WorldServer worldserver, double d0, double d1, double d2, float f, float f1) { ++ this.teleportTo(worldserver, d0, d1, d2, f, f1, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.UNKNOWN); ++ } ++ ++ public void teleportTo(WorldServer worldserver, double d0, double d1, double d2, float f, float f1, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { ++ // CraftBukkit end + this.setCamera(this); + this.stopRiding(); ++ /* CraftBukkit start - replace with bukkit handling for multi-world + if (worldserver == this.level()) { + this.connection.teleport(d0, d1, d2, f, f1); + } else { +@@ -1687,6 +2089,9 @@ + this.server.getPlayerList().sendLevelInfo(this, worldserver); + this.server.getPlayerList().sendAllPlayerInfo(this); + } ++ */ ++ this.getBukkitEntity().teleport(new Location(worldserver.getWorld(), d0, d1, d2, f, f1), cause); ++ // CraftBukkit end + + } + +@@ -1708,6 +2113,32 @@ + } + + public void setRespawnPosition(ResourceKey resourcekey, @Nullable BlockPosition blockposition, float f, boolean flag, boolean flag1) { ++ // CraftBukkit start ++ this.setRespawnPosition(resourcekey, blockposition, f, flag, flag1, PlayerSpawnChangeEvent.Cause.UNKNOWN); ++ } ++ ++ public void setRespawnPosition(ResourceKey resourcekey, @Nullable BlockPosition blockposition, float f, boolean flag, boolean flag1, PlayerSpawnChangeEvent.Cause cause) { ++ WorldServer newWorld = this.server.getLevel(resourcekey); ++ Location newSpawn = (blockposition != null) ? CraftLocation.toBukkit(blockposition, newWorld.getWorld(), f, 0) : null; ++ ++ PlayerSpawnChangeEvent event = new PlayerSpawnChangeEvent(this.getBukkitEntity(), newSpawn, flag, cause); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ newSpawn = event.getNewSpawn(); ++ flag = event.isForced(); ++ ++ if (newSpawn != null) { ++ resourcekey = ((CraftWorld) newSpawn.getWorld()).getHandle().dimension(); ++ blockposition = BlockPosition.containing(newSpawn.getX(), newSpawn.getY(), newSpawn.getZ()); ++ f = newSpawn.getYaw(); ++ } else { ++ resourcekey = World.OVERWORLD; ++ blockposition = null; ++ f = 0.0F; ++ } ++ // CraftBukkit end + if (blockposition != null) { + boolean flag2 = blockposition.equals(this.respawnPosition) && resourcekey.equals(this.respawnDimension); + +@@ -1913,4 +2344,146 @@ + public CommonPlayerSpawnInfo createCommonSpawnInfo(WorldServer worldserver) { + return new CommonPlayerSpawnInfo(worldserver.dimensionTypeId(), worldserver.dimension(), BiomeManager.obfuscateSeed(worldserver.getSeed()), this.gameMode.getGameModeForPlayer(), this.gameMode.getPreviousGameModeForPlayer(), worldserver.isDebug(), worldserver.isFlat(), this.getLastDeathLocation(), this.getPortalCooldown()); + } ++ ++ // CraftBukkit start - Add per-player time and weather. ++ public long timeOffset = 0; ++ public boolean relativeTime = true; ++ ++ public long getPlayerTime() { ++ if (this.relativeTime) { ++ // Adds timeOffset to the current server time. ++ return this.level().getDayTime() + this.timeOffset; ++ } else { ++ // Adds timeOffset to the beginning of this day. ++ return this.level().getDayTime() - (this.level().getDayTime() % 24000) + this.timeOffset; ++ } ++ } ++ ++ public WeatherType weather = null; ++ ++ public WeatherType getPlayerWeather() { ++ return this.weather; ++ } ++ ++ public void setPlayerWeather(WeatherType type, boolean plugin) { ++ if (!plugin && this.weather != null) { ++ return; ++ } ++ ++ if (plugin) { ++ this.weather = type; ++ } ++ ++ if (type == WeatherType.DOWNFALL) { ++ this.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.STOP_RAINING, 0)); ++ } else { ++ this.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.START_RAINING, 0)); ++ } ++ } ++ ++ private float pluginRainPosition; ++ private float pluginRainPositionPrevious; ++ ++ public void updateWeather(float oldRain, float newRain, float oldThunder, float newThunder) { ++ if (this.weather == null) { ++ // Vanilla ++ if (oldRain != newRain) { ++ this.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.RAIN_LEVEL_CHANGE, newRain)); ++ } ++ } else { ++ // Plugin ++ if (pluginRainPositionPrevious != pluginRainPosition) { ++ this.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.RAIN_LEVEL_CHANGE, pluginRainPosition)); ++ } ++ } ++ ++ if (oldThunder != newThunder) { ++ if (weather == WeatherType.DOWNFALL || weather == null) { ++ this.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, newThunder)); ++ } else { ++ this.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, 0)); ++ } ++ } ++ } ++ ++ public void tickWeather() { ++ if (this.weather == null) return; ++ ++ pluginRainPositionPrevious = pluginRainPosition; ++ if (weather == WeatherType.DOWNFALL) { ++ pluginRainPosition += 0.01; ++ } else { ++ pluginRainPosition -= 0.01; ++ } ++ ++ pluginRainPosition = MathHelper.clamp(pluginRainPosition, 0.0F, 1.0F); ++ } ++ ++ public void resetPlayerWeather() { ++ this.weather = null; ++ this.setPlayerWeather(this.level().getLevelData().isRaining() ? WeatherType.DOWNFALL : WeatherType.CLEAR, false); ++ } ++ ++ @Override ++ public String toString() { ++ return super.toString() + "(" + this.getScoreboardName() + " at " + this.getX() + "," + this.getY() + "," + this.getZ() + ")"; ++ } ++ ++ // SPIGOT-1903, MC-98153 ++ public void forceSetPositionRotation(double x, double y, double z, float yaw, float pitch) { ++ this.moveTo(x, y, z, yaw, pitch); ++ this.connection.resetPosition(); ++ } ++ ++ @Override ++ public boolean isImmobile() { ++ return super.isImmobile() || !getBukkitEntity().isOnline(); ++ } ++ ++ @Override ++ public Scoreboard getScoreboard() { ++ return getBukkitEntity().getScoreboard().getHandle(); ++ } ++ ++ public void reset() { ++ float exp = 0; ++ boolean keepInventory = this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY); ++ ++ if (this.keepLevel) { // CraftBukkit - SPIGOT-6687: Only use keepLevel (was pre-set with RULE_KEEPINVENTORY value in PlayerDeathEvent) ++ exp = this.experienceProgress; ++ this.newTotalExp = this.totalExperience; ++ this.newLevel = this.experienceLevel; ++ } ++ ++ this.setHealth(this.getMaxHealth()); ++ this.stopUsingItem(); // CraftBukkit - SPIGOT-6682: Clear active item on reset ++ this.setRemainingFireTicks(0); ++ this.fallDistance = 0; ++ this.foodData = new FoodMetaData(this); ++ this.experienceLevel = this.newLevel; ++ this.totalExperience = this.newTotalExp; ++ this.experienceProgress = 0; ++ this.deathTime = 0; ++ this.setArrowCount(0, true); // CraftBukkit - ArrowBodyCountChangeEvent ++ this.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.DEATH); ++ this.effectsDirty = true; ++ this.containerMenu = this.inventoryMenu; ++ this.lastHurtByPlayer = null; ++ this.lastHurtByMob = null; ++ this.combatTracker = new CombatTracker(this); ++ this.lastSentExp = -1; ++ if (this.keepLevel) { // CraftBukkit - SPIGOT-6687: Only use keepLevel (was pre-set with RULE_KEEPINVENTORY value in PlayerDeathEvent) ++ this.experienceProgress = exp; ++ } else { ++ this.giveExperiencePoints(this.newExp); ++ } ++ this.keepLevel = false; ++ this.setDeltaMovement(0, 0, 0); // CraftBukkit - SPIGOT-6948: Reset velocity on death ++ } ++ ++ @Override ++ public CraftPlayer getBukkitEntity() { ++ return (CraftPlayer) super.getBukkitEntity(); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/server/level/EntityTrackerEntry.patch b/patch-remap/og/net/minecraft/server/level/EntityTrackerEntry.patch new file mode 100644 index 0000000000..7f8f46b1df --- /dev/null +++ b/patch-remap/og/net/minecraft/server/level/EntityTrackerEntry.patch @@ -0,0 +1,142 @@ +--- a/net/minecraft/server/level/EntityTrackerEntry.java ++++ b/net/minecraft/server/level/EntityTrackerEntry.java +@@ -42,6 +42,12 @@ + import net.minecraft.world.phys.Vec3D; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.server.network.ServerPlayerConnection; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerVelocityEvent; ++// CraftBukkit end ++ + public class EntityTrackerEntry { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -66,8 +72,12 @@ + private boolean wasOnGround; + @Nullable + private List> trackedDataValues; ++ // CraftBukkit start ++ private final Set trackedPlayers; + +- public EntityTrackerEntry(WorldServer worldserver, Entity entity, int i, boolean flag, Consumer> consumer) { ++ public EntityTrackerEntry(WorldServer worldserver, Entity entity, int i, boolean flag, Consumer> consumer, Set trackedPlayers) { ++ this.trackedPlayers = trackedPlayers; ++ // CraftBukkit end + this.ap = Vec3D.ZERO; + this.lastPassengers = Collections.emptyList(); + this.level = worldserver; +@@ -87,7 +97,7 @@ + List list = this.entity.getPassengers(); + + if (!list.equals(this.lastPassengers)) { +- this.broadcast.accept(new PacketPlayOutMount(this.entity)); ++ this.broadcastAndSend(new PacketPlayOutMount(this.entity)); // CraftBukkit + removedPassengers(list, this.lastPassengers).forEach((entity) -> { + if (entity instanceof EntityPlayer) { + EntityPlayer entityplayer = (EntityPlayer) entity; +@@ -104,18 +114,18 @@ + if (entity instanceof EntityItemFrame) { + EntityItemFrame entityitemframe = (EntityItemFrame) entity; + +- if (this.tickCount % 10 == 0) { ++ if (true || this.tickCount % 10 == 0) { // CraftBukkit - Moved below, should always enter this block + ItemStack itemstack = entityitemframe.getItem(); + +- if (itemstack.getItem() instanceof ItemWorldMap) { ++ if (this.tickCount % 10 == 0 && itemstack.getItem() instanceof ItemWorldMap) { // CraftBukkit - Moved this.tickCounter % 10 logic here so item frames do not enter the other blocks + Integer integer = ItemWorldMap.getMapId(itemstack); + WorldMap worldmap = ItemWorldMap.getSavedData(integer, this.level); + + if (worldmap != null) { +- Iterator iterator = this.level.players().iterator(); ++ Iterator iterator = this.trackedPlayers.iterator(); // CraftBukkit + + while (iterator.hasNext()) { +- EntityPlayer entityplayer = (EntityPlayer) iterator.next(); ++ EntityPlayer entityplayer = iterator.next().getPlayer(); // CraftBukkit + + worldmap.tickCarriedBy(entityplayer, itemstack); + Packet packet = worldmap.getUpdatePacket(integer, entityplayer); +@@ -228,7 +238,27 @@ + + ++this.tickCount; + if (this.entity.hurtMarked) { +- this.broadcastAndSend(new PacketPlayOutEntityVelocity(this.entity)); ++ // CraftBukkit start - Create PlayerVelocity event ++ boolean cancelled = false; ++ ++ if (this.entity instanceof EntityPlayer) { ++ Player player = (Player) this.entity.getBukkitEntity(); ++ org.bukkit.util.Vector velocity = player.getVelocity(); ++ ++ PlayerVelocityEvent event = new PlayerVelocityEvent(player, velocity.clone()); ++ this.entity.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ cancelled = true; ++ } else if (!velocity.equals(event.getVelocity())) { ++ player.setVelocity(event.getVelocity()); ++ } ++ } ++ ++ if (!cancelled) { ++ this.broadcastAndSend(new PacketPlayOutEntityVelocity(this.entity)); ++ } ++ // CraftBukkit end + this.entity.hurtMarked = false; + } + +@@ -256,7 +286,10 @@ + + public void sendPairingData(EntityPlayer entityplayer, Consumer> consumer) { + if (this.entity.isRemoved()) { +- EntityTrackerEntry.LOGGER.warn("Fetching packet for removed entity {}", this.entity); ++ // CraftBukkit start - Remove useless error spam, just return ++ // EntityTrackerEntry.LOGGER.warn("Fetching packet for removed entity {}", this.entity); ++ return; ++ // CraftBukkit end + } + + Packet packet = this.entity.getAddEntityPacket(); +@@ -272,6 +305,12 @@ + if (this.entity instanceof EntityLiving) { + Collection collection = ((EntityLiving) this.entity).getAttributes().getSyncableAttributes(); + ++ // CraftBukkit start - If sending own attributes send scaled health instead of current maximum health ++ if (this.entity.getId() == entityplayer.getId()) { ++ ((EntityPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(collection, false); ++ } ++ // CraftBukkit end ++ + if (!collection.isEmpty()) { + consumer.accept(new PacketPlayOutUpdateAttributes(this.entity.getId(), collection)); + } +@@ -303,7 +342,14 @@ + if (!list.isEmpty()) { + consumer.accept(new PacketPlayOutEntityEquipment(this.entity.getId(), list)); + } ++ ((EntityLiving) this.entity).detectEquipmentUpdatesPublic(); // CraftBukkit - SPIGOT-3789: sync again immediately after sending ++ } ++ ++ // CraftBukkit start - MC-109346: Fix for nonsensical head yaw ++ if (this.entity instanceof EntityPlayer) { ++ consumer.accept(new PacketPlayOutEntityHeadRotation(this.entity, (byte) MathHelper.floor(this.entity.getYHeadRot() * 256.0F / 360.0F))); + } ++ // CraftBukkit end + + if (!this.entity.getPassengers().isEmpty()) { + consumer.accept(new PacketPlayOutMount(this.entity)); +@@ -338,6 +384,11 @@ + Set set = ((EntityLiving) this.entity).getAttributes().getDirtyAttributes(); + + if (!set.isEmpty()) { ++ // CraftBukkit start - Send scaled max health ++ if (this.entity instanceof EntityPlayer) { ++ ((EntityPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(set, false); ++ } ++ // CraftBukkit end + this.broadcastAndSend(new PacketPlayOutUpdateAttributes(this.entity.getId(), set)); + } + diff --git a/patch-remap/og/net/minecraft/server/level/PlayerChunk.patch b/patch-remap/og/net/minecraft/server/level/PlayerChunk.patch new file mode 100644 index 0000000000..67d9bd0f2d --- /dev/null +++ b/patch-remap/og/net/minecraft/server/level/PlayerChunk.patch @@ -0,0 +1,175 @@ +--- a/net/minecraft/server/level/PlayerChunk.java ++++ b/net/minecraft/server/level/PlayerChunk.java +@@ -36,6 +36,10 @@ + import net.minecraft.world.level.chunk.ProtoChunkExtension; + import net.minecraft.world.level.lighting.LevelLightEngine; + ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++// CraftBukkit end ++ + public class PlayerChunk { + + public static final Either UNLOADED_CHUNK = Either.right(PlayerChunk.Failure.UNLOADED); +@@ -72,12 +76,12 @@ + this.fullChunkFuture = PlayerChunk.UNLOADED_LEVEL_CHUNK_FUTURE; + this.tickingChunkFuture = PlayerChunk.UNLOADED_LEVEL_CHUNK_FUTURE; + this.entityTickingChunkFuture = PlayerChunk.UNLOADED_LEVEL_CHUNK_FUTURE; +- this.chunkToSave = CompletableFuture.completedFuture((Object) null); ++ this.chunkToSave = CompletableFuture.completedFuture(null); // CraftBukkit - decompile error + this.chunkToSaveHistory = null; + this.blockChangedLightSectionFilter = new BitSet(); + this.skyChangedLightSectionFilter = new BitSet(); +- this.pendingFullStateConfirmation = CompletableFuture.completedFuture((Object) null); +- this.sendSync = CompletableFuture.completedFuture((Object) null); ++ this.pendingFullStateConfirmation = CompletableFuture.completedFuture(null); // CraftBukkit - decompile error ++ this.sendSync = CompletableFuture.completedFuture(null); // CraftBukkit - decompile error + this.pos = chunkcoordintpair; + this.levelHeightAccessor = levelheightaccessor; + this.lightEngine = levellightengine; +@@ -90,6 +94,20 @@ + this.changedBlocksPerSection = new ShortSet[levelheightaccessor.getSectionsCount()]; + } + ++ // CraftBukkit start ++ public Chunk getFullChunkNow() { ++ // Note: We use the oldTicketLevel for isLoaded checks. ++ if (!ChunkLevel.fullStatus(this.oldTicketLevel).isOrAfter(FullChunkStatus.FULL)) return null; ++ return this.getFullChunkNowUnchecked(); ++ } ++ ++ public Chunk getFullChunkNowUnchecked() { ++ CompletableFuture> statusFuture = this.getFutureIfPresentUnchecked(ChunkStatus.FULL); ++ Either either = (Either) statusFuture.getNow(null); ++ return (either == null) ? null : (Chunk) either.left().orElse(null); ++ } ++ // CraftBukkit end ++ + public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus chunkstatus) { + CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(chunkstatus.getIndex()); + +@@ -115,9 +133,9 @@ + @Nullable + public Chunk getTickingChunk() { + CompletableFuture> completablefuture = this.getTickingChunkFuture(); +- Either either = (Either) completablefuture.getNow((Object) null); ++ Either either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error + +- return either == null ? null : (Chunk) either.left().orElse((Object) null); ++ return either == null ? null : (Chunk) either.left().orElse(null); // CraftBukkit - decompile error + } + + public CompletableFuture getChunkSendSyncFuture() { +@@ -132,9 +150,9 @@ + @Nullable + public Chunk getFullChunk() { + CompletableFuture> completablefuture = this.getFullChunkFuture(); +- Either either = (Either) completablefuture.getNow((Object) null); ++ Either either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error + +- return either == null ? null : (Chunk) either.left().orElse((Object) null); ++ return either == null ? null : (Chunk) either.left().orElse(null); // CraftBukkit - decompile error + } + + @Nullable +@@ -179,6 +197,7 @@ + if (chunk != null) { + int i = this.levelHeightAccessor.getSectionIndex(blockposition.getY()); + ++ if (i < 0 || i >= this.changedBlocksPerSection.length) return; // CraftBukkit - SPIGOT-6086, SPIGOT-6296 + if (this.changedBlocksPerSection[i] == null) { + this.hasChangedSections = true; + this.changedBlocksPerSection[i] = new ShortOpenHashSet(); +@@ -189,10 +208,10 @@ + } + + public void sectionLightChanged(EnumSkyBlock enumskyblock, int i) { +- Either either = (Either) this.getFutureIfPresent(ChunkStatus.INITIALIZE_LIGHT).getNow((Object) null); ++ Either either = (Either) this.getFutureIfPresent(ChunkStatus.INITIALIZE_LIGHT).getNow(null); // CraftBukkit - decompile error + + if (either != null) { +- IChunkAccess ichunkaccess = (IChunkAccess) either.left().orElse((Object) null); ++ IChunkAccess ichunkaccess = (IChunkAccess) either.left().orElse(null); // CraftBukkit - decompile error + + if (ichunkaccess != null) { + ichunkaccess.setUnsaved(true); +@@ -257,8 +276,11 @@ + PacketPlayOutMultiBlockChange packetplayoutmultiblockchange = new PacketPlayOutMultiBlockChange(sectionposition, shortset, chunksection); + + this.broadcast(list, packetplayoutmultiblockchange); ++ // CraftBukkit start ++ List finalList = list; + packetplayoutmultiblockchange.runUpdates((blockposition1, iblockdata1) -> { +- this.broadcastBlockEntityIfNeeded(list, world, blockposition1, iblockdata1); ++ this.broadcastBlockEntityIfNeeded(finalList, world, blockposition1, iblockdata1); ++ // CraftBukkit end + }); + } + } +@@ -394,7 +416,7 @@ + this.pendingFullStateConfirmation = completablefuture1; + completablefuture.thenAccept((either) -> { + either.ifLeft((chunk) -> { +- completablefuture1.complete((Object) null); ++ completablefuture1.complete(null); // CraftBukkit - decompile error + }); + }); + } +@@ -411,6 +433,30 @@ + boolean flag1 = ChunkLevel.isLoaded(this.ticketLevel); + FullChunkStatus fullchunkstatus = ChunkLevel.fullStatus(this.oldTicketLevel); + FullChunkStatus fullchunkstatus1 = ChunkLevel.fullStatus(this.ticketLevel); ++ // CraftBukkit start ++ // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins. ++ if (fullchunkstatus.isOrAfter(FullChunkStatus.FULL) && !fullchunkstatus1.isOrAfter(FullChunkStatus.FULL)) { ++ this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { ++ Chunk chunk = (Chunk)either.left().orElse(null); ++ if (chunk != null) { ++ playerchunkmap.callbackExecutor.execute(() -> { ++ // Minecraft will apply the chunks tick lists to the world once the chunk got loaded, and then store the tick ++ // lists again inside the chunk once the chunk becomes inaccessible and set the chunk's needsSaving flag. ++ // These actions may however happen deferred, so we manually set the needsSaving flag already here. ++ chunk.setUnsaved(true); ++ chunk.unloadCallback(); ++ }); ++ } ++ }).exceptionally((throwable) -> { ++ // ensure exceptions are printed, by default this is not the case ++ MinecraftServer.LOGGER.error("Failed to schedule unload callback for chunk " + PlayerChunk.this.pos, throwable); ++ return null; ++ }); ++ ++ // Run callback right away if the future was already done ++ playerchunkmap.callbackExecutor.run(); ++ } ++ // CraftBukkit end + + if (flag) { + Either either = Either.right(new PlayerChunk.Failure() { +@@ -481,6 +527,26 @@ + + this.onLevelChange.onLevelChange(this.pos, this::getQueueLevel, this.ticketLevel, this::setQueueLevel); + this.oldTicketLevel = this.ticketLevel; ++ // CraftBukkit start ++ // ChunkLoadEvent: Called after the chunk is loaded: isChunkLoaded returns true and chunk is ready to be modified by plugins. ++ if (!fullchunkstatus.isOrAfter(FullChunkStatus.FULL) && fullchunkstatus1.isOrAfter(FullChunkStatus.FULL)) { ++ this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { ++ Chunk chunk = (Chunk)either.left().orElse(null); ++ if (chunk != null) { ++ playerchunkmap.callbackExecutor.execute(() -> { ++ chunk.loadCallback(); ++ }); ++ } ++ }).exceptionally((throwable) -> { ++ // ensure exceptions are printed, by default this is not the case ++ MinecraftServer.LOGGER.error("Failed to schedule load callback for chunk " + PlayerChunk.this.pos, throwable); ++ return null; ++ }); ++ ++ // Run callback right away if the future was already done ++ playerchunkmap.callbackExecutor.run(); ++ } ++ // CraftBukkit end + } + + public boolean wasAccessibleSinceLastSave() { diff --git a/patch-remap/og/net/minecraft/server/level/PlayerChunkMap.patch b/patch-remap/og/net/minecraft/server/level/PlayerChunkMap.patch new file mode 100644 index 0000000000..1115794843 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/level/PlayerChunkMap.patch @@ -0,0 +1,181 @@ +--- a/net/minecraft/server/level/PlayerChunkMap.java ++++ b/net/minecraft/server/level/PlayerChunkMap.java +@@ -101,6 +101,12 @@ + import org.apache.commons.lang3.mutable.MutableBoolean; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.world.level.levelgen.GeneratorSettings; ++import org.bukkit.craftbukkit.generator.CustomChunkGenerator; ++import org.bukkit.entity.Player; ++// CraftBukkit end ++ + public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + + private static final byte CHUNK_TYPE_REPLACEABLE = -1; +@@ -143,6 +149,27 @@ + private final Queue unloadQueue; + private int serverViewDistance; + ++ // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() ++ public final CallbackExecutor callbackExecutor = new CallbackExecutor(); ++ public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable { ++ ++ private final java.util.Queue queue = new java.util.ArrayDeque<>(); ++ ++ @Override ++ public void execute(Runnable runnable) { ++ queue.add(runnable); ++ } ++ ++ @Override ++ public void run() { ++ Runnable task; ++ while ((task = queue.poll()) != null) { ++ task.run(); ++ } ++ } ++ }; ++ // CraftBukkit end ++ + public PlayerChunkMap(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, StructureTemplateManager structuretemplatemanager, Executor executor, IAsyncTaskHandler iasynctaskhandler, ILightAccess ilightaccess, ChunkGenerator chunkgenerator, WorldLoadListener worldloadlistener, ChunkStatusUpdateListener chunkstatusupdatelistener, Supplier supplier, int i, boolean flag) { + super(convertable_conversionsession.getDimensionPath(worldserver.dimension()).resolve("region"), datafixer, flag); + this.visibleChunkMap = this.updatingChunkMap.clone(); +@@ -161,6 +188,11 @@ + this.storageName = path.getFileName().toString(); + this.level = worldserver; + this.generator = chunkgenerator; ++ // CraftBukkit start - SPIGOT-7051: It's a rigged game! Use delegate for random state creation, otherwise it is not so random. ++ if (chunkgenerator instanceof CustomChunkGenerator) { ++ chunkgenerator = ((CustomChunkGenerator) chunkgenerator).getDelegate(); ++ } ++ // CraftBukkit end + IRegistryCustom iregistrycustom = worldserver.registryAccess(); + long j = worldserver.getSeed(); + +@@ -332,9 +364,12 @@ + CompletableFuture>> completablefuture1 = SystemUtils.sequence(list); + CompletableFuture, PlayerChunk.Failure>> completablefuture2 = completablefuture1.thenApply((list2) -> { + List list3 = Lists.newArrayList(); +- final int l1 = 0; ++ // CraftBukkit start - decompile error ++ int cnt = 0; + +- for (Iterator iterator = list2.iterator(); iterator.hasNext(); ++l1) { ++ for (Iterator iterator = list2.iterator(); iterator.hasNext(); ++cnt) { ++ final int l1 = cnt; ++ // CraftBukkit end + final Either either = (Either) iterator.next(); + + if (either == null) { +@@ -540,7 +575,7 @@ + + private void scheduleUnload(long i, PlayerChunk playerchunk) { + CompletableFuture completablefuture = playerchunk.getChunkToSave(); +- Consumer consumer = (ichunkaccess) -> { ++ Consumer consumer = (ichunkaccess) -> { // CraftBukkit - decompile error + CompletableFuture completablefuture1 = playerchunk.getChunkToSave(); + + if (completablefuture1 != completablefuture) { +@@ -631,9 +666,9 @@ + ProtoChunk protochunk = ChunkRegionLoader.read(this.level, this.poiManager, chunkcoordintpair, (NBTTagCompound) optional.get()); + + this.markPosition(chunkcoordintpair, protochunk.getStatus().getChunkType()); +- return Either.left(protochunk); ++ return Either.left(protochunk); // CraftBukkit - decompile error + } else { +- return Either.left(this.createEmptyChunk(chunkcoordintpair)); ++ return Either.left(this.createEmptyChunk(chunkcoordintpair)); // CraftBukkit - decompile error + } + }, this.mainThreadExecutor).exceptionallyAsync((throwable) -> { + return this.handleChunkLoadFailure(throwable, chunkcoordintpair); +@@ -748,7 +783,21 @@ + + private static void postLoadProtoChunk(WorldServer worldserver, List list) { + if (!list.isEmpty()) { +- worldserver.addWorldGenChunkEntities(EntityTypes.loadEntitiesRecursive(list, worldserver)); ++ // CraftBukkit start - these are spawned serialized (DefinedStructure) and we don't call an add event below at the moment due to ordering complexities ++ worldserver.addWorldGenChunkEntities(EntityTypes.loadEntitiesRecursive(list, worldserver).filter((entity) -> { ++ boolean needsRemoval = false; ++ net.minecraft.server.dedicated.DedicatedServer server = worldserver.getCraftServer().getServer(); ++ if (!server.areNpcsEnabled() && entity instanceof net.minecraft.world.entity.npc.NPC) { ++ entity.discard(); ++ needsRemoval = true; ++ } ++ if (!server.isSpawningAnimals() && (entity instanceof net.minecraft.world.entity.animal.EntityAnimal || entity instanceof net.minecraft.world.entity.animal.EntityWaterAnimal)) { ++ entity.discard(); ++ needsRemoval = true; ++ } ++ return !needsRemoval; ++ })); ++ // CraftBukkit end + } + + } +@@ -860,7 +909,7 @@ + if (!playerchunk.wasAccessibleSinceLastSave()) { + return false; + } else { +- IChunkAccess ichunkaccess = (IChunkAccess) playerchunk.getChunkToSave().getNow((Object) null); ++ IChunkAccess ichunkaccess = (IChunkAccess) playerchunk.getChunkToSave().getNow(null); // CraftBukkit - decompile error + + if (!(ichunkaccess instanceof ProtoChunkExtension) && !(ichunkaccess instanceof Chunk)) { + return false; +@@ -1017,7 +1066,8 @@ + return ichunkaccess instanceof Chunk ? Optional.of((Chunk) ichunkaccess) : Optional.empty(); + }); + +- csvwriter.writeRow(chunkcoordintpair.x, chunkcoordintpair.z, playerchunk.getTicketLevel(), optional.isPresent(), optional.map(IChunkAccess::getStatus).orElse((Object) null), optional1.map(Chunk::getFullStatus).orElse((Object) null), printFuture(playerchunk.getFullChunkFuture()), printFuture(playerchunk.getTickingChunkFuture()), printFuture(playerchunk.getEntityTickingChunkFuture()), this.distanceManager.getTicketDebugString(i), this.anyPlayerCloseEnoughForSpawning(chunkcoordintpair), optional1.map((chunk) -> { ++ // CraftBukkit - decompile error ++ csvwriter.writeRow(chunkcoordintpair.x, chunkcoordintpair.z, playerchunk.getTicketLevel(), optional.isPresent(), optional.map(IChunkAccess::getStatus).orElse(null), optional1.map(Chunk::getFullStatus).orElse(null), printFuture(playerchunk.getFullChunkFuture()), printFuture(playerchunk.getTickingChunkFuture()), printFuture(playerchunk.getEntityTickingChunkFuture()), this.distanceManager.getTicketDebugString(i), this.anyPlayerCloseEnoughForSpawning(chunkcoordintpair), optional1.map((chunk) -> { + return chunk.getBlockEntities().size(); + }).orElse(0), tickingtracker.getTicketDebugString(i), tickingtracker.getLevel(i), optional1.map((chunk) -> { + return chunk.getBlockTicks().count(); +@@ -1030,7 +1080,7 @@ + + private static String printFuture(CompletableFuture> completablefuture) { + try { +- Either either = (Either) completablefuture.getNow((Object) null); ++ Either either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error + + return either != null ? (String) either.map((chunk) -> { + return "done"; +@@ -1046,12 +1096,14 @@ + + private CompletableFuture> readChunk(ChunkCoordIntPair chunkcoordintpair) { + return this.read(chunkcoordintpair).thenApplyAsync((optional) -> { +- return optional.map(this::upgradeChunkTag); ++ return optional.map((nbttagcompound) -> upgradeChunkTag(nbttagcompound, chunkcoordintpair)); // CraftBukkit + }, SystemUtils.backgroundExecutor()); + } + +- private NBTTagCompound upgradeChunkTag(NBTTagCompound nbttagcompound) { +- return this.upgradeChunkTag(this.level.dimension(), this.overworldDataStorage, nbttagcompound, this.generator.getTypeNameForDataFixer()); ++ // CraftBukkit start ++ private NBTTagCompound upgradeChunkTag(NBTTagCompound nbttagcompound, ChunkCoordIntPair chunkcoordintpair) { ++ return this.upgradeChunkTag(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, this.generator.getTypeNameForDataFixer(), chunkcoordintpair, level); ++ // CraftBukkit end + } + + boolean anyPlayerCloseEnoughForSpawning(ChunkCoordIntPair chunkcoordintpair) { +@@ -1460,7 +1512,7 @@ + public final Set seenBy = Sets.newIdentityHashSet(); + + public EntityTracker(Entity entity, int i, int j, boolean flag) { +- this.serverEntity = new EntityTrackerEntry(PlayerChunkMap.this.level, entity, j, flag, this::broadcast); ++ this.serverEntity = new EntityTrackerEntry(PlayerChunkMap.this.level, entity, j, flag, this::broadcast, seenBy); // CraftBukkit + this.entity = entity; + this.range = i; + this.lastSectionPos = SectionPosition.of((EntityAccess) entity); +@@ -1520,6 +1572,11 @@ + double d2 = d0 * d0; + boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(entityplayer) && PlayerChunkMap.this.isChunkTracked(entityplayer, this.entity.chunkPosition().x, this.entity.chunkPosition().z); + ++ // CraftBukkit start - respect vanish API ++ if (!entityplayer.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { ++ flag = false; ++ } ++ // CraftBukkit end + if (flag) { + if (this.seenBy.add(entityplayer.connection)) { + this.serverEntity.addPairing(entityplayer); diff --git a/patch-remap/og/net/minecraft/server/level/PlayerInteractManager.patch b/patch-remap/og/net/minecraft/server/level/PlayerInteractManager.patch new file mode 100644 index 0000000000..370a8ae24b --- /dev/null +++ b/patch-remap/og/net/minecraft/server/level/PlayerInteractManager.patch @@ -0,0 +1,353 @@ +--- a/net/minecraft/server/level/PlayerInteractManager.java ++++ b/net/minecraft/server/level/PlayerInteractManager.java +@@ -26,6 +26,27 @@ + import net.minecraft.world.phys.Vec3D; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.ArrayList; ++import net.minecraft.network.protocol.game.PacketPlayOutBlockChange; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.world.entity.EnumItemSlot; ++import net.minecraft.world.item.ItemBisected; ++import net.minecraft.world.level.block.BlockCake; ++import net.minecraft.world.level.block.BlockDoor; ++import net.minecraft.world.level.block.BlockTrapdoor; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.state.properties.BlockPropertyDoubleBlockHalf; ++import org.bukkit.GameMode; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockBreakEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.Event; ++import org.bukkit.event.block.Action; ++import org.bukkit.event.player.PlayerGameModeChangeEvent; ++import org.bukkit.event.player.PlayerInteractEvent; ++// CraftBukkit end ++ + public class PlayerInteractManager { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -56,9 +77,16 @@ + if (enumgamemode == this.gameModeForPlayer) { + return false; + } else { ++ // CraftBukkit start ++ PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(player.getBukkitEntity(), GameMode.getByValue(enumgamemode.getId())); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end + this.setGameModeForPlayer(enumgamemode, this.previousGameModeForPlayer); + this.player.onUpdateAbilities(); +- this.player.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.UPDATE_GAME_MODE, this.player)); ++ this.player.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.UPDATE_GAME_MODE, this.player), this.player); // CraftBukkit + this.level.updateSleepingPlayerList(); + return true; + } +@@ -88,7 +116,7 @@ + } + + public void tick() { +- ++this.gameTicks; ++ this.gameTicks = MinecraftServer.currentTick; // CraftBukkit; + IBlockData iblockdata; + + if (this.hasDelayedDestroy) { +@@ -142,11 +170,33 @@ + + if (packetplayinblockdig_enumplayerdigtype == PacketPlayInBlockDig.EnumPlayerDigType.START_DESTROY_BLOCK) { + if (!this.level.mayInteract(this.player, blockposition)) { ++ // CraftBukkit start - fire PlayerInteractEvent ++ CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, blockposition, enumdirection, this.player.getInventory().getSelected(), EnumHand.MAIN_HAND); + this.player.connection.send(new PacketPlayOutBlockChange(blockposition, this.level.getBlockState(blockposition))); + this.debugLogging(blockposition, false, j, "may not interact"); ++ // Update any tile entity data for this block ++ TileEntity tileentity = level.getBlockEntity(blockposition); ++ if (tileentity != null) { ++ this.player.connection.send(tileentity.getUpdatePacket()); ++ } ++ // CraftBukkit end + return; + } + ++ // CraftBukkit start ++ PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, blockposition, enumdirection, this.player.getInventory().getSelected(), EnumHand.MAIN_HAND); ++ if (event.isCancelled()) { ++ // Let the client know the block still exists ++ this.player.connection.send(new PacketPlayOutBlockChange(this.level, blockposition)); ++ // Update any tile entity data for this block ++ TileEntity tileentity = this.level.getBlockEntity(blockposition); ++ if (tileentity != null) { ++ this.player.connection.send(tileentity.getUpdatePacket()); ++ } ++ return; ++ } ++ // CraftBukkit end ++ + if (this.isCreative()) { + this.destroyAndAck(blockposition, j, "creative destroy"); + return; +@@ -162,11 +212,43 @@ + float f = 1.0F; + + iblockdata = this.level.getBlockState(blockposition); +- if (!iblockdata.isAir()) { ++ // CraftBukkit start - Swings at air do *NOT* exist. ++ if (event.useInteractedBlock() == Event.Result.DENY) { ++ // If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door. ++ IBlockData data = this.level.getBlockState(blockposition); ++ if (data.getBlock() instanceof BlockDoor) { ++ // For some reason *BOTH* the bottom/top part have to be marked updated. ++ boolean bottom = data.getValue(BlockDoor.HALF) == BlockPropertyDoubleBlockHalf.LOWER; ++ this.player.connection.send(new PacketPlayOutBlockChange(this.level, blockposition)); ++ this.player.connection.send(new PacketPlayOutBlockChange(this.level, bottom ? blockposition.above() : blockposition.below())); ++ } else if (data.getBlock() instanceof BlockTrapdoor) { ++ this.player.connection.send(new PacketPlayOutBlockChange(this.level, blockposition)); ++ } ++ } else if (!iblockdata.isAir()) { + iblockdata.attack(this.level, blockposition, this.player); + f = iblockdata.getDestroyProgress(this.player, this.player.level(), blockposition); + } + ++ if (event.useItemInHand() == Event.Result.DENY) { ++ // If we 'insta destroyed' then the client needs to be informed. ++ if (f > 1.0f) { ++ this.player.connection.send(new PacketPlayOutBlockChange(this.level, blockposition)); ++ } ++ return; ++ } ++ org.bukkit.event.block.BlockDamageEvent blockEvent = CraftEventFactory.callBlockDamageEvent(this.player, blockposition, this.player.getInventory().getSelected(), f >= 1.0f); ++ ++ if (blockEvent.isCancelled()) { ++ // Let the client know the block still exists ++ this.player.connection.send(new PacketPlayOutBlockChange(this.level, blockposition)); ++ return; ++ } ++ ++ if (blockEvent.getInstaBreak()) { ++ f = 2.0f; ++ } ++ // CraftBukkit end ++ + if (!iblockdata.isAir() && f >= 1.0F) { + this.destroyAndAck(blockposition, j, "insta mine"); + } else { +@@ -211,13 +293,15 @@ + } else if (packetplayinblockdig_enumplayerdigtype == PacketPlayInBlockDig.EnumPlayerDigType.ABORT_DESTROY_BLOCK) { + this.isDestroyingBlock = false; + if (!Objects.equals(this.destroyPos, blockposition)) { +- PlayerInteractManager.LOGGER.warn("Mismatch in destroy block pos: {} {}", this.destroyPos, blockposition); ++ PlayerInteractManager.LOGGER.debug("Mismatch in destroy block pos: {} {}", this.destroyPos, blockposition); // CraftBukkit - SPIGOT-5457 sent by client when interact event cancelled + this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); + this.debugLogging(blockposition, true, j, "aborted mismatched destroying"); + } + + this.level.destroyBlockProgress(this.player.getId(), blockposition, -1); + this.debugLogging(blockposition, true, j, "aborted destroying"); ++ ++ CraftEventFactory.callBlockDamageAbortEvent(this.player, blockposition, this.player.getInventory().getSelected()); // CraftBukkit + } + + } +@@ -235,10 +319,65 @@ + + public boolean destroyBlock(BlockPosition blockposition) { + IBlockData iblockdata = this.level.getBlockState(blockposition); ++ // CraftBukkit start - fire BlockBreakEvent ++ org.bukkit.block.Block bblock = CraftBlock.at(level, blockposition); ++ BlockBreakEvent event = null; + +- if (!this.player.getMainHandItem().getItem().canAttackBlock(iblockdata, this.level, blockposition, this.player)) { ++ if (this.player instanceof EntityPlayer) { ++ // Sword + Creative mode pre-cancel ++ boolean isSwordNoBreak = !this.player.getMainHandItem().getItem().canAttackBlock(iblockdata, this.level, blockposition, this.player); ++ ++ // Tell client the block is gone immediately then process events ++ // Don't tell the client if its a creative sword break because its not broken! ++ if (level.getBlockEntity(blockposition) == null && !isSwordNoBreak) { ++ PacketPlayOutBlockChange packet = new PacketPlayOutBlockChange(blockposition, Blocks.AIR.defaultBlockState()); ++ this.player.connection.send(packet); ++ } ++ ++ event = new BlockBreakEvent(bblock, this.player.getBukkitEntity()); ++ ++ // Sword + Creative mode pre-cancel ++ event.setCancelled(isSwordNoBreak); ++ ++ // Calculate default block experience ++ IBlockData nmsData = this.level.getBlockState(blockposition); ++ Block nmsBlock = nmsData.getBlock(); ++ ++ ItemStack itemstack = this.player.getItemBySlot(EnumItemSlot.MAINHAND); ++ ++ if (nmsBlock != null && !event.isCancelled() && !this.isCreative() && this.player.hasCorrectToolForDrops(nmsBlock.defaultBlockState())) { ++ event.setExpToDrop(nmsBlock.getExpDrop(nmsData, this.level, blockposition, itemstack, true)); ++ } ++ ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ if (isSwordNoBreak) { ++ return false; ++ } ++ // Let the client know the block still exists ++ this.player.connection.send(new PacketPlayOutBlockChange(this.level, blockposition)); ++ ++ // Brute force all possible updates ++ for (EnumDirection dir : EnumDirection.values()) { ++ this.player.connection.send(new PacketPlayOutBlockChange(level, blockposition.relative(dir))); ++ } ++ ++ // Update any tile entity data for this block ++ TileEntity tileentity = this.level.getBlockEntity(blockposition); ++ if (tileentity != null) { ++ this.player.connection.send(tileentity.getUpdatePacket()); ++ } ++ return false; ++ } ++ } ++ // CraftBukkit end ++ ++ if (false && !this.player.getMainHandItem().getItem().canAttackBlock(iblockdata, this.level, blockposition, this.player)) { // CraftBukkit - false + return false; + } else { ++ iblockdata = this.level.getBlockState(blockposition); // CraftBukkit - update state from plugins ++ if (iblockdata.isAir()) return false; // CraftBukkit - A plugin set block to air without cancelling + TileEntity tileentity = this.level.getBlockEntity(blockposition); + Block block = iblockdata.getBlock(); + +@@ -248,6 +387,10 @@ + } else if (this.player.blockActionRestricted(this.level, blockposition, this.gameModeForPlayer)) { + return false; + } else { ++ // CraftBukkit start ++ org.bukkit.block.BlockState state = bblock.getState(); ++ level.captureDrops = new ArrayList<>(); ++ // CraftBukkit end + IBlockData iblockdata1 = block.playerWillDestroy(this.level, blockposition, iblockdata, this.player); + boolean flag = this.level.removeBlock(blockposition, false); + +@@ -256,19 +399,32 @@ + } + + if (this.isCreative()) { +- return true; ++ // return true; // CraftBukkit + } else { + ItemStack itemstack = this.player.getMainHandItem(); + ItemStack itemstack1 = itemstack.copy(); + boolean flag1 = this.player.hasCorrectToolForDrops(iblockdata1); + + itemstack.mineBlock(this.level, iblockdata1, blockposition, this.player); +- if (flag && flag1) { ++ if (flag && flag1 && event.isDropItems()) { // CraftBukkit - Check if block should drop items + block.playerDestroy(this.level, this.player, blockposition, iblockdata1, tileentity, itemstack1); + } + +- return true; ++ // return true; // CraftBukkit ++ } ++ // CraftBukkit start ++ if (event.isDropItems()) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, level.captureDrops); ++ } ++ level.captureDrops = null; ++ ++ // Drop event experience ++ if (flag && event != null) { ++ iblockdata.getBlock().popExperience(this.level, blockposition, event.getExpToDrop()); + } ++ ++ return true; ++ // CraftBukkit end + } + } + } +@@ -313,14 +469,54 @@ + } + } + ++ // CraftBukkit start - whole method ++ public boolean interactResult = false; ++ public boolean firedInteract = false; ++ public BlockPosition interactPosition; ++ public EnumHand interactHand; ++ public ItemStack interactItemStack; + public EnumInteractionResult useItemOn(EntityPlayer entityplayer, World world, ItemStack itemstack, EnumHand enumhand, MovingObjectPositionBlock movingobjectpositionblock) { + BlockPosition blockposition = movingobjectpositionblock.getBlockPos(); + IBlockData iblockdata = world.getBlockState(blockposition); ++ EnumInteractionResult enuminteractionresult = EnumInteractionResult.PASS; ++ boolean cancelledBlock = false; + + if (!iblockdata.getBlock().isEnabled(world.enabledFeatures())) { + return EnumInteractionResult.FAIL; + } else if (this.gameModeForPlayer == EnumGamemode.SPECTATOR) { + ITileInventory itileinventory = iblockdata.getMenuProvider(world, blockposition); ++ cancelledBlock = !(itileinventory instanceof ITileInventory); ++ } ++ ++ if (entityplayer.getCooldowns().isOnCooldown(itemstack.getItem())) { ++ cancelledBlock = true; ++ } ++ ++ PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(entityplayer, Action.RIGHT_CLICK_BLOCK, blockposition, movingobjectpositionblock.getDirection(), itemstack, cancelledBlock, enumhand, movingobjectpositionblock.getLocation()); ++ firedInteract = true; ++ interactResult = event.useItemInHand() == Event.Result.DENY; ++ interactPosition = blockposition.immutable(); ++ interactHand = enumhand; ++ interactItemStack = itemstack.copy(); ++ ++ if (event.useInteractedBlock() == Event.Result.DENY) { ++ // If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door. ++ if (iblockdata.getBlock() instanceof BlockDoor) { ++ boolean bottom = iblockdata.getValue(BlockDoor.HALF) == BlockPropertyDoubleBlockHalf.LOWER; ++ entityplayer.connection.send(new PacketPlayOutBlockChange(world, bottom ? blockposition.above() : blockposition.below())); ++ } else if (iblockdata.getBlock() instanceof BlockCake) { ++ entityplayer.getBukkitEntity().sendHealthUpdate(); // SPIGOT-1341 - reset health for cake ++ } else if (interactItemStack.getItem() instanceof ItemBisected) { ++ // send a correcting update to the client, as it already placed the upper half of the bisected item ++ entityplayer.connection.send(new PacketPlayOutBlockChange(world, blockposition.relative(movingobjectpositionblock.getDirection()).above())); ++ ++ // send a correcting update to the client for the block above as well, this because of replaceable blocks (such as grass, sea grass etc) ++ entityplayer.connection.send(new PacketPlayOutBlockChange(world, blockposition.above())); ++ } ++ entityplayer.getBukkitEntity().updateInventory(); // SPIGOT-2867 ++ enuminteractionresult = (event.useItemInHand() != Event.Result.ALLOW) ? EnumInteractionResult.SUCCESS : EnumInteractionResult.PASS; ++ } else if (this.gameModeForPlayer == EnumGamemode.SPECTATOR) { ++ ITileInventory itileinventory = iblockdata.getMenuProvider(world, blockposition); + + if (itileinventory != null) { + entityplayer.openMenu(itileinventory); +@@ -334,7 +530,7 @@ + ItemStack itemstack1 = itemstack.copy(); + + if (!flag1) { +- EnumInteractionResult enuminteractionresult = iblockdata.use(world, entityplayer, enumhand, movingobjectpositionblock); ++ enuminteractionresult = iblockdata.use(world, entityplayer, enumhand, movingobjectpositionblock); + + if (enuminteractionresult.consumesAction()) { + CriterionTriggers.ITEM_USED_ON_BLOCK.trigger(entityplayer, blockposition, itemstack1); +@@ -342,7 +538,7 @@ + } + } + +- if (!itemstack.isEmpty() && !entityplayer.getCooldowns().isOnCooldown(itemstack.getItem())) { ++ if (!itemstack.isEmpty() && enuminteractionresult != EnumInteractionResult.SUCCESS && !interactResult) { // add !interactResult SPIGOT-764 + ItemActionContext itemactioncontext = new ItemActionContext(entityplayer, enumhand, movingobjectpositionblock); + EnumInteractionResult enuminteractionresult1; + +@@ -360,10 +556,10 @@ + } + + return enuminteractionresult1; +- } else { +- return EnumInteractionResult.PASS; + } + } ++ return enuminteractionresult; ++ // CraftBukkit end + } + + public void setLevel(WorldServer worldserver) { diff --git a/patch-remap/og/net/minecraft/server/level/RegionLimitedWorldAccess.patch b/patch-remap/og/net/minecraft/server/level/RegionLimitedWorldAccess.patch new file mode 100644 index 0000000000..b638902b8d --- /dev/null +++ b/patch-remap/og/net/minecraft/server/level/RegionLimitedWorldAccess.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/server/level/RegionLimitedWorldAccess.java ++++ b/net/minecraft/server/level/RegionLimitedWorldAccess.java +@@ -208,7 +208,7 @@ + if (iblockdata.isAir()) { + return false; + } else { +- if (flag) { ++ if (false) { // CraftBukkit - SPIGOT-6833: Do not drop during world generation + TileEntity tileentity = iblockdata.hasBlockEntity() ? this.getBlockEntity(blockposition) : null; + + Block.dropResources(iblockdata, this.level, blockposition, tileentity, entity, ItemStack.EMPTY); +@@ -327,6 +327,13 @@ + + @Override + public boolean addFreshEntity(Entity entity) { ++ // CraftBukkit start ++ return addFreshEntity(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ @Override ++ public boolean addFreshEntity(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ // CraftBukkit end + int i = SectionPosition.blockToSectionCoord(entity.getBlockX()); + int j = SectionPosition.blockToSectionCoord(entity.getBlockZ()); + diff --git a/patch-remap/og/net/minecraft/server/level/TicketType.patch b/patch-remap/og/net/minecraft/server/level/TicketType.patch new file mode 100644 index 0000000000..24c2b2c7a5 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/level/TicketType.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/server/level/TicketType.java ++++ b/net/minecraft/server/level/TicketType.java +@@ -23,6 +23,8 @@ + public static final TicketType PORTAL = create("portal", BaseBlockPosition::compareTo, 300); + public static final TicketType POST_TELEPORT = create("post_teleport", Integer::compareTo, 5); + public static final TicketType UNKNOWN = create("unknown", Comparator.comparingLong(ChunkCoordIntPair::toLong), 1); ++ public static final TicketType PLUGIN = create("plugin", (a, b) -> 0); // CraftBukkit ++ public static final TicketType PLUGIN_TICKET = create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit + + public static TicketType create(String s, Comparator comparator) { + return new TicketType<>(s, comparator, 0L); diff --git a/patch-remap/og/net/minecraft/server/level/WorldServer.patch b/patch-remap/og/net/minecraft/server/level/WorldServer.patch new file mode 100644 index 0000000000..2def431f84 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/level/WorldServer.patch @@ -0,0 +1,635 @@ +--- a/net/minecraft/server/level/WorldServer.java ++++ b/net/minecraft/server/level/WorldServer.java +@@ -164,6 +164,26 @@ + import net.minecraft.world.ticks.TickListServer; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.world.level.biome.WorldChunkManager; ++import net.minecraft.world.level.dimension.WorldDimension; ++import net.minecraft.world.level.levelgen.ChunkGeneratorAbstract; ++import net.minecraft.world.level.levelgen.ChunkProviderFlat; ++import net.minecraft.world.level.storage.WorldDataServer; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.WeatherType; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.generator.CustomWorldChunkManager; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.craftbukkit.util.WorldUUID; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.server.MapInitializeEvent; ++import org.bukkit.event.weather.LightningStrikeEvent; ++import org.bukkit.event.world.GenericGameEvent; ++import org.bukkit.event.world.TimeSkipEvent; ++// CraftBukkit end ++ + public class WorldServer extends World implements GeneratorAccessSeed { + + public static final BlockPosition END_SPAWN_POINT = new BlockPosition(100, 50, 0); +@@ -177,7 +197,7 @@ + final List players; + private final ChunkProviderServer chunkSource; + private final MinecraftServer server; +- public final IWorldDataServer serverLevelData; ++ public final WorldDataServer serverLevelData; // CraftBukkit - type + final EntityTickList entityTickList; + public final PersistentEntitySectionManager entityManager; + private final GameEventDispatcher gameEventDispatcher; +@@ -202,12 +222,30 @@ + private final boolean tickTime; + private final RandomSequences randomSequences; + +- public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, WorldDimension worlddimension, WorldLoadListener worldloadlistener, boolean flag, long i, List list, boolean flag1, @Nullable RandomSequences randomsequences) { +- IRegistryCustom.Dimension iregistrycustom_dimension = minecraftserver.registryAccess(); +- Holder holder = worlddimension.type(); ++ // CraftBukkit start ++ public final Convertable.ConversionSession convertable; ++ public final UUID uuid; + +- Objects.requireNonNull(minecraftserver); +- super(iworlddataserver, resourcekey, iregistrycustom_dimension, holder, minecraftserver::getProfiler, false, flag, i, minecraftserver.getMaxChainedNeighborUpdates()); ++ public Chunk getChunkIfLoaded(int x, int z) { ++ return this.chunkSource.getChunk(x, z, false); ++ } ++ ++ @Override ++ public ResourceKey getTypeKey() { ++ return convertable.dimensionType; ++ } ++ ++ // Add env and gen to constructor, IWorldDataServer -> WorldDataServer ++ public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, WorldDataServer iworlddataserver, ResourceKey resourcekey, WorldDimension worlddimension, WorldLoadListener worldloadlistener, boolean flag, long i, List list, boolean flag1, @Nullable RandomSequences randomsequences, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) { ++ // IRegistryCustom.Dimension iregistrycustom_dimension = minecraftserver.registryAccess(); // CraftBukkit - decompile error ++ // Holder holder = worlddimension.type(); // CraftBukkit - decompile error ++ ++ // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error ++ super(iworlddataserver, resourcekey, minecraftserver.registryAccess(), worlddimension.type(), minecraftserver::getProfiler, false, flag, i, minecraftserver.getMaxChainedNeighborUpdates(), gen, biomeProvider, env); ++ this.pvpMode = minecraftserver.isPvpAllowed(); ++ convertable = convertable_conversionsession; ++ uuid = WorldUUID.getUUID(convertable_conversionsession.levelDirectory.path().toFile()); ++ // CraftBukkit end + this.players = Lists.newArrayList(); + this.entityTickList = new EntityTickList(); + this.blockTicks = new TickListServer<>(this::isPositionTickingWithEntitiesLoaded, this.getProfilerSupplier()); +@@ -221,6 +259,22 @@ + this.customSpawners = list; + this.serverLevelData = iworlddataserver; + ChunkGenerator chunkgenerator = worlddimension.generator(); ++ // CraftBukkit start ++ serverLevelData.setWorld(this); ++ ++ if (biomeProvider != null) { ++ WorldChunkManager worldChunkManager = new CustomWorldChunkManager(getWorld(), biomeProvider, server.registryAccess().registryOrThrow(Registries.BIOME)); ++ if (chunkgenerator instanceof ChunkGeneratorAbstract cga) { ++ chunkgenerator = new ChunkGeneratorAbstract(worldChunkManager, cga.settings); ++ } else if (chunkgenerator instanceof ChunkProviderFlat cpf) { ++ chunkgenerator = new ChunkProviderFlat(cpf.settings(), worldChunkManager); ++ } ++ } ++ ++ if (gen != null) { ++ chunkgenerator = new org.bukkit.craftbukkit.generator.CustomChunkGenerator(this, chunkgenerator, gen); ++ } ++ // CraftBukkit end + boolean flag2 = minecraftserver.forceSynchronousWrites(); + DataFixer datafixer = minecraftserver.getFixerUpper(); + EntityPersistentStorage entitypersistentstorage = new EntityStorage(this, convertable_conversionsession.getDimensionPath(resourcekey).resolve("entities"), datafixer, flag2, minecraftserver); +@@ -248,9 +302,9 @@ + long l = minecraftserver.getWorldData().worldGenOptions().seed(); + + this.structureCheck = new StructureCheck(this.chunkSource.chunkScanner(), this.registryAccess(), minecraftserver.getStructureManager(), resourcekey, chunkgenerator, this.chunkSource.randomState(), this, chunkgenerator.getBiomeSource(), l, datafixer); +- this.structureManager = new StructureManager(this, minecraftserver.getWorldData().worldGenOptions(), this.structureCheck); +- if (this.dimension() == World.END && this.dimensionTypeRegistration().is(BuiltinDimensionTypes.END)) { +- this.dragonFight = new EnderDragonBattle(this, l, minecraftserver.getWorldData().endDragonFightData()); ++ this.structureManager = new StructureManager(this, this.serverLevelData.worldGenOptions(), structureCheck); // CraftBukkit ++ if ((this.dimension() == World.END && this.dimensionTypeRegistration().is(BuiltinDimensionTypes.END)) || env == org.bukkit.World.Environment.THE_END) { // CraftBukkit - Allow to create EnderDragonBattle in default and custom END ++ this.dragonFight = new EnderDragonBattle(this, this.serverLevelData.worldGenOptions().seed(), this.serverLevelData.endDragonFightData()); // CraftBukkit + } else { + this.dragonFight = null; + } +@@ -260,6 +314,7 @@ + this.randomSequences = (RandomSequences) Objects.requireNonNullElseGet(randomsequences, () -> { + return (RandomSequences) this.getDataStorage().computeIfAbsent(RandomSequences.factory(l), "random_sequences"); + }); ++ this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit + } + + /** @deprecated */ +@@ -304,12 +359,20 @@ + long j; + + if (this.sleepStatus.areEnoughSleeping(i) && this.sleepStatus.areEnoughDeepSleeping(i, this.players)) { ++ // CraftBukkit start ++ j = this.levelData.getDayTime() + 24000L; ++ TimeSkipEvent event = new TimeSkipEvent(this.getWorld(), TimeSkipEvent.SkipReason.NIGHT_SKIP, (j - j % 24000L) - this.getDayTime()); + if (this.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { +- j = this.levelData.getDayTime() + 24000L; +- this.setDayTime(j - j % 24000L); ++ getCraftServer().getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ this.setDayTime(this.getDayTime() + event.getSkipAmount()); ++ } + } + +- this.wakeUpAllPlayers(); ++ if (!event.isCancelled()) { ++ this.wakeUpAllPlayers(); ++ } ++ // CraftBukkit end + if (this.getGameRules().getBoolean(GameRules.RULE_WEATHER_CYCLE) && this.isRaining()) { + this.resetWeatherCycle(); + } +@@ -344,7 +407,7 @@ + + this.handlingTick = false; + gameprofilerfiller.pop(); +- boolean flag1 = !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); ++ boolean flag1 = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players + + if (flag1) { + this.resetEmptyTime(); +@@ -360,7 +423,7 @@ + + this.entityTickList.forEach((entity) -> { + if (!entity.isRemoved()) { +- if (this.shouldDiscardEntity(entity)) { ++ if (false && this.shouldDiscardEntity(entity)) { // CraftBukkit - We prevent spawning in general, so this butchering is not needed + entity.discard(); + } else if (!tickratemanager.isEntityFrozen(entity)) { + gameprofilerfiller.push("checkDespawn"); +@@ -432,7 +495,7 @@ + + private void wakeUpAllPlayers() { + this.sleepStatus.removeAllSleepers(); +- ((List) this.players.stream().filter(EntityLiving::isSleeping).collect(Collectors.toList())).forEach((entityplayer) -> { ++ (this.players.stream().filter(EntityLiving::isSleeping).collect(Collectors.toList())).forEach((entityplayer) -> { // CraftBukkit - decompile error + entityplayer.stopSleepInBed(false, false); + }); + } +@@ -459,7 +522,7 @@ + entityhorseskeleton.setTrap(true); + entityhorseskeleton.setAge(0); + entityhorseskeleton.setPos((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()); +- this.addFreshEntity(entityhorseskeleton); ++ this.addFreshEntity(entityhorseskeleton, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); // CraftBukkit + } + } + +@@ -468,7 +531,7 @@ + if (entitylightning != null) { + entitylightning.moveTo(Vec3D.atBottomCenterOf(blockposition)); + entitylightning.setVisualOnly(flag1); +- this.addFreshEntity(entitylightning); ++ this.strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.WEATHER); // CraftBukkit + } + } + } +@@ -524,7 +587,7 @@ + BiomeBase biomebase = (BiomeBase) this.getBiome(blockposition1).value(); + + if (biomebase.shouldFreeze(this, blockposition2)) { +- this.setBlockAndUpdate(blockposition2, Blocks.ICE.defaultBlockState()); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition2, Blocks.ICE.defaultBlockState(), null); // CraftBukkit + } + + if (this.isRaining()) { +@@ -540,10 +603,10 @@ + IBlockData iblockdata1 = (IBlockData) iblockdata.setValue(BlockSnow.LAYERS, j + 1); + + Block.pushEntitiesUp(iblockdata, iblockdata1, this, blockposition1); +- this.setBlockAndUpdate(blockposition1, iblockdata1); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, iblockdata1, null); // CraftBukkit + } + } else { +- this.setBlockAndUpdate(blockposition1, Blocks.SNOW.defaultBlockState()); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, Blocks.SNOW.defaultBlockState(), null); // CraftBukkit + } + } + +@@ -704,6 +767,7 @@ + this.rainLevel = MathHelper.clamp(this.rainLevel, 0.0F, 1.0F); + } + ++ /* CraftBukkit start + if (this.oRainLevel != this.rainLevel) { + this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.RAIN_LEVEL_CHANGE, this.rainLevel), this.dimension()); + } +@@ -722,15 +786,48 @@ + this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.RAIN_LEVEL_CHANGE, this.rainLevel)); + this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, this.thunderLevel)); + } ++ // */ ++ for (int idx = 0; idx < this.players.size(); ++idx) { ++ if (((EntityPlayer) this.players.get(idx)).level() == this) { ++ ((EntityPlayer) this.players.get(idx)).tickWeather(); ++ } ++ } ++ ++ if (flag != this.isRaining()) { ++ // Only send weather packets to those affected ++ for (int idx = 0; idx < this.players.size(); ++idx) { ++ if (((EntityPlayer) this.players.get(idx)).level() == this) { ++ ((EntityPlayer) this.players.get(idx)).setPlayerWeather((!flag ? WeatherType.DOWNFALL : WeatherType.CLEAR), false); ++ } ++ } ++ } ++ for (int idx = 0; idx < this.players.size(); ++idx) { ++ if (((EntityPlayer) this.players.get(idx)).level() == this) { ++ ((EntityPlayer) this.players.get(idx)).updateWeather(this.oRainLevel, this.rainLevel, this.oThunderLevel, this.thunderLevel); ++ } ++ } ++ // CraftBukkit end + + } + + @VisibleForTesting + public void resetWeatherCycle() { +- this.serverLevelData.setRainTime(0); ++ // CraftBukkit start + this.serverLevelData.setRaining(false); +- this.serverLevelData.setThunderTime(0); ++ // If we stop due to everyone sleeping we should reset the weather duration to some other random value. ++ // Not that everyone ever manages to get the whole server to sleep at the same time.... ++ if (!this.serverLevelData.isRaining()) { ++ this.serverLevelData.setRainTime(0); ++ } ++ // CraftBukkit end + this.serverLevelData.setThundering(false); ++ // CraftBukkit start ++ // If we stop due to everyone sleeping we should reset the weather duration to some other random value. ++ // Not that everyone ever manages to get the whole server to sleep at the same time.... ++ if (!this.serverLevelData.isThundering()) { ++ this.serverLevelData.setThunderTime(0); ++ } ++ // CraftBukkit end + } + + public void resetEmptyTime() { +@@ -765,6 +862,7 @@ + }); + gameprofilerfiller.incrementCounter("tickNonPassenger"); + entity.tick(); ++ entity.postTick(); // CraftBukkit + this.getProfiler().pop(); + Iterator iterator = entity.getPassengers().iterator(); + +@@ -788,6 +886,7 @@ + }); + gameprofilerfiller.incrementCounter("tickPassenger"); + entity1.rideTick(); ++ entity1.postTick(); // CraftBukkit + gameprofilerfiller.pop(); + Iterator iterator = entity1.getPassengers().iterator(); + +@@ -812,6 +911,7 @@ + ChunkProviderServer chunkproviderserver = this.getChunkSource(); + + if (!flag1) { ++ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit + if (iprogressupdate != null) { + iprogressupdate.progressStartNoAbort(IChatBaseComponent.translatable("menu.savingLevel")); + } +@@ -829,11 +929,19 @@ + } + + } ++ ++ // CraftBukkit start - moved from MinecraftServer.saveChunks ++ WorldServer worldserver1 = this; ++ ++ serverLevelData.setWorldBorder(worldserver1.getWorldBorder().createSettings()); ++ serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save()); ++ convertable.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData()); ++ // CraftBukkit end + } + + private void saveLevelData() { + if (this.dragonFight != null) { +- this.server.getWorldData().setEndDragonFightData(this.dragonFight.saveData()); ++ this.serverLevelData.setEndDragonFightData(this.dragonFight.saveData()); // CraftBukkit + } + + this.getChunkSource().getDataStorage().save(); +@@ -898,15 +1006,37 @@ + + @Override + public boolean addFreshEntity(Entity entity) { +- return this.addEntity(entity); ++ // CraftBukkit start ++ return this.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ @Override ++ public boolean addFreshEntity(Entity entity, CreatureSpawnEvent.SpawnReason reason) { ++ return this.addEntity(entity, reason); ++ // CraftBukkit end + } + + public boolean addWithUUID(Entity entity) { +- return this.addEntity(entity); ++ // CraftBukkit start ++ return this.addWithUUID(entity, CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ public boolean addWithUUID(Entity entity, CreatureSpawnEvent.SpawnReason reason) { ++ return this.addEntity(entity, reason); ++ // CraftBukkit end + } + + public void addDuringTeleport(Entity entity) { +- this.addEntity(entity); ++ // CraftBukkit start ++ // SPIGOT-6415: Don't call spawn event for entities which travel trough worlds, ++ // since it is only an implementation detail, that a new entity is created when ++ // they are traveling between worlds. ++ this.addDuringTeleport(entity, null); ++ } ++ ++ public void addDuringTeleport(Entity entity, CreatureSpawnEvent.SpawnReason reason) { ++ this.addEntity(entity, reason); ++ // CraftBukkit end + } + + public void addDuringCommandTeleport(EntityPlayer entityplayer) { +@@ -937,24 +1067,37 @@ + this.entityManager.addNewEntity(entityplayer); + } + +- private boolean addEntity(Entity entity) { ++ // CraftBukkit start ++ private boolean addEntity(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { + if (entity.isRemoved()) { +- WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getKey(entity.getType())); ++ // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getKey(entity.getType())); // CraftBukkit + return false; + } else { ++ // SPIGOT-6415: Don't call spawn event when reason is null. For example when an entity teleports to a new world. ++ if (spawnReason != null && !CraftEventFactory.doEntityAddEventCalling(this, entity, spawnReason)) { ++ return false; ++ } ++ // CraftBukkit end ++ + return this.entityManager.addNewEntity(entity); + } + } + + public boolean tryAddFreshEntityWithPassengers(Entity entity) { +- Stream stream = entity.getSelfAndPassengers().map(Entity::getUUID); ++ // CraftBukkit start ++ return this.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ public boolean tryAddFreshEntityWithPassengers(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ // CraftBukkit end ++ Stream stream = entity.getSelfAndPassengers().map(Entity::getUUID); // CraftBukkit - decompile error + PersistentEntitySectionManager persistententitysectionmanager = this.entityManager; + + Objects.requireNonNull(this.entityManager); + if (stream.anyMatch(persistententitysectionmanager::isLoaded)) { + return false; + } else { +- this.addFreshEntityWithPassengers(entity); ++ this.addFreshEntityWithPassengers(entity, reason); // CraftBukkit + return true; + } + } +@@ -968,10 +1111,32 @@ + entityplayer.remove(entity_removalreason); + } + ++ // CraftBukkit start ++ public boolean strikeLightning(Entity entitylightning) { ++ return this.strikeLightning(entitylightning, LightningStrikeEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean strikeLightning(Entity entitylightning, LightningStrikeEvent.Cause cause) { ++ LightningStrikeEvent lightning = CraftEventFactory.callLightningStrikeEvent((org.bukkit.entity.LightningStrike) entitylightning.getBukkitEntity(), cause); ++ ++ if (lightning.isCancelled()) { ++ return false; ++ } ++ ++ return this.addFreshEntity(entitylightning); ++ } ++ // CraftBukkit end ++ + @Override + public void destroyBlockProgress(int i, BlockPosition blockposition, int j) { + Iterator iterator = this.server.getPlayerList().getPlayers().iterator(); + ++ // CraftBukkit start ++ EntityHuman entityhuman = null; ++ Entity entity = this.getEntity(i); ++ if (entity instanceof EntityHuman) entityhuman = (EntityHuman) entity; ++ // CraftBukkit end ++ + while (iterator.hasNext()) { + EntityPlayer entityplayer = (EntityPlayer) iterator.next(); + +@@ -980,6 +1145,12 @@ + double d1 = (double) blockposition.getY() - entityplayer.getY(); + double d2 = (double) blockposition.getZ() - entityplayer.getZ(); + ++ // CraftBukkit start ++ if (entityhuman != null && !entityplayer.getBukkitEntity().canSee(entityhuman.getBukkitEntity())) { ++ continue; ++ } ++ // CraftBukkit end ++ + if (d0 * d0 + d1 * d1 + d2 * d2 < 1024.0D) { + entityplayer.connection.send(new PacketPlayOutBlockBreakAnimation(i, blockposition, j)); + } +@@ -1039,7 +1210,18 @@ + Iterator iterator = this.navigatingMobs.iterator(); + + while (iterator.hasNext()) { +- EntityInsentient entityinsentient = (EntityInsentient) iterator.next(); ++ // CraftBukkit start - fix SPIGOT-6362 ++ EntityInsentient entityinsentient; ++ try { ++ entityinsentient = (EntityInsentient) iterator.next(); ++ } catch (java.util.ConcurrentModificationException ex) { ++ // This can happen because the pathfinder update below may trigger a chunk load, which in turn may cause more navigators to register ++ // In this case we just run the update again across all the iterators as the chunk will then be loaded ++ // As this is a relative edge case it is much faster than copying navigators (on either read or write) ++ sendBlockUpdated(blockposition, iblockdata, iblockdata1, i); ++ return; ++ } ++ // CraftBukkit end + NavigationAbstract navigationabstract = entityinsentient.getNavigation(); + + if (navigationabstract.shouldRecomputePath(blockposition)) { +@@ -1101,6 +1283,11 @@ + @Override + public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, World.a world_a, ParticleParam particleparam, ParticleParam particleparam1, SoundEffect soundeffect) { + Explosion explosion = this.explode(entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, world_a, false, particleparam, particleparam1, soundeffect); ++ // CraftBukkit start ++ if (explosion.wasCanceled) { ++ return explosion; ++ } ++ // CraftBukkit end + + if (!explosion.interactsWithBlocks()) { + explosion.clearToBlow(); +@@ -1173,13 +1360,20 @@ + } + + public int sendParticles(T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6) { +- PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(t0, false, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i); ++ // CraftBukkit - visibility api support ++ return sendParticles(null, t0, d0, d1, d2, i, d3, d4, d5, d6, false); ++ } ++ ++ public int sendParticles(EntityPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { ++ PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(t0, force, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i); ++ // CraftBukkit end + int j = 0; + + for (int k = 0; k < this.players.size(); ++k) { + EntityPlayer entityplayer = (EntityPlayer) this.players.get(k); ++ if (sender != null && !entityplayer.getBukkitEntity().canSee(sender.getBukkitEntity())) continue; // CraftBukkit + +- if (this.sendParticles(entityplayer, false, d0, d1, d2, packetplayoutworldparticles)) { ++ if (this.sendParticles(entityplayer, force, d0, d1, d2, packetplayoutworldparticles)) { // CraftBukkit + ++j; + } + } +@@ -1230,7 +1424,7 @@ + + @Nullable + public BlockPosition findNearestMapStructure(TagKey tagkey, BlockPosition blockposition, int i, boolean flag) { +- if (!this.server.getWorldData().worldGenOptions().generateStructures()) { ++ if (!this.serverLevelData.worldGenOptions().generateStructures()) { // CraftBukkit + return null; + } else { + Optional> optional = this.registryAccess().registryOrThrow(Registries.STRUCTURE).getTag(tagkey); +@@ -1272,11 +1466,22 @@ + @Nullable + @Override + public WorldMap getMapData(String s) { +- return (WorldMap) this.getServer().overworld().getDataStorage().get(WorldMap.factory(), s); ++ // CraftBukkit start ++ WorldMap worldmap = (WorldMap) this.getServer().overworld().getDataStorage().get(WorldMap.factory(), s); ++ if (worldmap != null) { ++ worldmap.id = s; ++ } ++ return worldmap; ++ // CraftBukkit end + } + + @Override + public void setMapData(String s, WorldMap worldmap) { ++ // CraftBukkit start ++ worldmap.id = s; ++ MapInitializeEvent event = new MapInitializeEvent(worldmap.mapView); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ // CraftBukkit end + this.getServer().overworld().getDataStorage().set(s, worldmap); + } + +@@ -1574,6 +1779,11 @@ + @Override + public void blockUpdated(BlockPosition blockposition, Block block) { + if (!this.isDebug()) { ++ // CraftBukkit start ++ if (populating) { ++ return; ++ } ++ // CraftBukkit end + this.updateNeighborsAt(blockposition, block); + } + +@@ -1593,12 +1803,12 @@ + } + + public boolean isFlat() { +- return this.server.getWorldData().isFlatWorld(); ++ return this.serverLevelData.isFlatWorld(); // CraftBukkit + } + + @Override + public long getSeed() { +- return this.server.getWorldData().worldGenOptions().seed(); ++ return this.serverLevelData.worldGenOptions().seed(); // CraftBukkit + } + + @Nullable +@@ -1621,7 +1831,7 @@ + private static String getTypeCount(Iterable iterable, Function function) { + try { + Object2IntOpenHashMap object2intopenhashmap = new Object2IntOpenHashMap(); +- Iterator iterator = iterable.iterator(); ++ Iterator iterator = iterable.iterator(); // CraftBukkit - decompile error + + while (iterator.hasNext()) { + T t0 = iterator.next(); +@@ -1630,7 +1840,7 @@ + object2intopenhashmap.addTo(s, 1); + } + +- return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(Entry::getIntValue).reversed()).limit(5L).map((entry) -> { ++ return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(Entry::getIntValue).reversed()).limit(5L).map((entry) -> { // CraftBukkit - decompile error + String s1 = (String) entry.getKey(); + + return s1 + ":" + entry.getIntValue(); +@@ -1641,17 +1851,33 @@ + } + + public static void makeObsidianPlatform(WorldServer worldserver) { ++ // CraftBukkit start ++ WorldServer.makeObsidianPlatform(worldserver, null); ++ } ++ ++ public static void makeObsidianPlatform(WorldServer worldserver, Entity entity) { ++ // CraftBukkit end + BlockPosition blockposition = WorldServer.END_SPAWN_POINT; + int i = blockposition.getX(); + int j = blockposition.getY() - 2; + int k = blockposition.getZ(); + ++ // CraftBukkit start ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(worldserver); + BlockPosition.betweenClosed(i - 2, j + 1, k - 2, i + 2, j + 3, k + 2).forEach((blockposition1) -> { +- worldserver.setBlockAndUpdate(blockposition1, Blocks.AIR.defaultBlockState()); ++ blockList.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3); + }); + BlockPosition.betweenClosed(i - 2, j, k - 2, i + 2, j, k + 2).forEach((blockposition1) -> { +- worldserver.setBlockAndUpdate(blockposition1, Blocks.OBSIDIAN.defaultBlockState()); ++ blockList.setBlock(blockposition1, Blocks.OBSIDIAN.defaultBlockState(), 3); + }); ++ org.bukkit.World bworld = worldserver.getWorld(); ++ org.bukkit.event.world.PortalCreateEvent portalEvent = new org.bukkit.event.world.PortalCreateEvent((List) (List) blockList.getList(), bworld, (entity == null) ? null : entity.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM); ++ ++ worldserver.getCraftServer().getPluginManager().callEvent(portalEvent); ++ if (!portalEvent.isCancelled()) { ++ blockList.updateList(); ++ } ++ // CraftBukkit end + } + + @Override +@@ -1785,6 +2011,8 @@ + } + + entity.updateDynamicGameEventListener(DynamicGameEventListener::add); ++ entity.inWorld = true; // CraftBukkit - Mark entity as in world ++ entity.valid = true; // CraftBukkit + } + + public void onTrackingEnd(Entity entity) { +@@ -1821,6 +2049,14 @@ + } + + entity.updateDynamicGameEventListener(DynamicGameEventListener::remove); ++ // CraftBukkit start ++ entity.valid = false; ++ if (!(entity instanceof EntityPlayer)) { ++ for (EntityPlayer player : players) { ++ player.getBukkitEntity().onEntityRemove(entity); ++ } ++ } ++ // CraftBukkit end + } + + public void onSectionChange(Entity entity) { diff --git a/patch-remap/og/net/minecraft/server/network/HandshakeListener.patch b/patch-remap/og/net/minecraft/server/network/HandshakeListener.patch new file mode 100644 index 0000000000..5abb5c22e7 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/network/HandshakeListener.patch @@ -0,0 +1,65 @@ +--- a/net/minecraft/server/network/HandshakeListener.java ++++ b/net/minecraft/server/network/HandshakeListener.java +@@ -11,8 +11,17 @@ + import net.minecraft.network.protocol.status.ServerPing; + import net.minecraft.server.MinecraftServer; + ++// CraftBukkit start ++import java.net.InetAddress; ++import java.util.HashMap; ++// CraftBukkit end ++ + public class HandshakeListener implements PacketHandshakingInListener { + ++ // CraftBukkit start - add fields ++ private static final HashMap throttleTracker = new HashMap(); ++ private static int throttleCounter = 0; ++ // CraftBukkit end + private static final IChatBaseComponent IGNORE_STATUS_REASON = IChatBaseComponent.translatable("disconnect.ignoring_status_request"); + private final MinecraftServer server; + private final NetworkManager connection; +@@ -24,9 +33,44 @@ + + @Override + public void handleIntention(PacketHandshakingInSetProtocol packethandshakinginsetprotocol) { ++ this.connection.hostname = packethandshakinginsetprotocol.hostName() + ":" + packethandshakinginsetprotocol.port(); // CraftBukkit - set hostname + switch (packethandshakinginsetprotocol.intention()) { + case LOGIN: + this.connection.setClientboundProtocolAfterHandshake(ClientIntent.LOGIN); ++ // CraftBukkit start - Connection throttle ++ try { ++ long currentTime = System.currentTimeMillis(); ++ long connectionThrottle = this.server.server.getConnectionThrottle(); ++ InetAddress address = ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getAddress(); ++ ++ synchronized (throttleTracker) { ++ if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { ++ throttleTracker.put(address, currentTime); ++ IChatMutableComponent chatmessage = IChatBaseComponent.literal("Connection throttled! Please wait before reconnecting."); ++ this.connection.send(new PacketLoginOutDisconnect(chatmessage)); ++ this.connection.disconnect(chatmessage); ++ return; ++ } ++ ++ throttleTracker.put(address, currentTime); ++ throttleCounter++; ++ if (throttleCounter > 200) { ++ throttleCounter = 0; ++ ++ // Cleanup stale entries ++ java.util.Iterator iter = throttleTracker.entrySet().iterator(); ++ while (iter.hasNext()) { ++ java.util.Map.Entry entry = (java.util.Map.Entry) iter.next(); ++ if (entry.getValue() > connectionThrottle) { ++ iter.remove(); ++ } ++ } ++ } ++ } ++ } catch (Throwable t) { ++ org.apache.logging.log4j.LogManager.getLogger().debug("Failed to check connection throttle", t); ++ } ++ // CraftBukkit end + if (packethandshakinginsetprotocol.protocolVersion() != SharedConstants.getCurrentVersion().getProtocolVersion()) { + IChatMutableComponent ichatmutablecomponent; + diff --git a/patch-remap/og/net/minecraft/server/network/LegacyPingHandler.patch b/patch-remap/og/net/minecraft/server/network/LegacyPingHandler.patch new file mode 100644 index 0000000000..bed960eee0 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/network/LegacyPingHandler.patch @@ -0,0 +1,45 @@ +--- a/net/minecraft/server/network/LegacyPingHandler.java ++++ b/net/minecraft/server/network/LegacyPingHandler.java +@@ -35,10 +35,11 @@ + SocketAddress socketaddress = channelhandlercontext.channel().remoteAddress(); + int i = bytebuf.readableBytes(); + String s; ++ org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(socketaddress, server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); // CraftBukkit + + if (i == 0) { + LegacyPingHandler.LOGGER.debug("Ping: (<1.3.x) from {}", socketaddress); +- s = createVersion0Response(this.server); ++ s = createVersion0Response(this.server, event); // CraftBukkit + sendFlushAndClose(channelhandlercontext, createLegacyDisconnectPacket(channelhandlercontext.alloc(), s)); + } else { + if (bytebuf.readUnsignedByte() != 1) { +@@ -55,7 +56,7 @@ + LegacyPingHandler.LOGGER.debug("Ping: (1.4-1.5.x) from {}", socketaddress); + } + +- s = createVersion1Response(this.server); ++ s = createVersion1Response(this.server, event); // CraftBukkit + sendFlushAndClose(channelhandlercontext, createLegacyDisconnectPacket(channelhandlercontext.alloc(), s)); + } + +@@ -106,12 +107,16 @@ + } + } + +- private static String createVersion0Response(ServerInfo serverinfo) { +- return String.format(Locale.ROOT, "%s\u00a7%d\u00a7%d", serverinfo.getMotd(), serverinfo.getPlayerCount(), serverinfo.getMaxPlayers()); ++ // CraftBukkit start ++ private static String createVersion0Response(ServerInfo serverinfo, org.bukkit.event.server.ServerListPingEvent event) { ++ return String.format(Locale.ROOT, "%s\u00a7%d\u00a7%d", event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); ++ // CraftBukkit end + } + +- private static String createVersion1Response(ServerInfo serverinfo) { +- return String.format(Locale.ROOT, "\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, serverinfo.getServerVersion(), serverinfo.getMotd(), serverinfo.getPlayerCount(), serverinfo.getMaxPlayers()); ++ // CraftBukkit start ++ private static String createVersion1Response(ServerInfo serverinfo, org.bukkit.event.server.ServerListPingEvent event) { ++ return String.format(Locale.ROOT, "\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, serverinfo.getServerVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); ++ // CraftBukkit end + } + + private static void sendFlushAndClose(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf) { diff --git a/patch-remap/og/net/minecraft/server/network/LoginListener.patch b/patch-remap/og/net/minecraft/server/network/LoginListener.patch new file mode 100644 index 0000000000..6a6f89996d --- /dev/null +++ b/patch-remap/og/net/minecraft/server/network/LoginListener.patch @@ -0,0 +1,128 @@ +--- a/net/minecraft/server/network/LoginListener.java ++++ b/net/minecraft/server/network/LoginListener.java +@@ -40,6 +40,13 @@ + import org.apache.commons.lang3.Validate; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.server.level.EntityPlayer; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.bukkit.event.player.AsyncPlayerPreLoginEvent; ++import org.bukkit.event.player.PlayerPreLoginEvent; ++// CraftBukkit end ++ + public class LoginListener implements PacketLoginInListener, TickablePacketListener { + + private static final AtomicInteger UNIQUE_THREAD_ID = new AtomicInteger(0); +@@ -56,6 +63,7 @@ + @Nullable + private GameProfile authenticatedProfile; + private final String serverId; ++ private EntityPlayer player; // CraftBukkit + + public LoginListener(MinecraftServer minecraftserver, NetworkManager networkmanager) { + this.state = LoginListener.EnumProtocolState.HELLO; +@@ -81,6 +89,13 @@ + + } + ++ // CraftBukkit start ++ @Deprecated ++ public void disconnect(String s) { ++ disconnect(IChatBaseComponent.literal(s)); ++ } ++ // CraftBukkit end ++ + @Override + public boolean isAcceptingMessages() { + return this.connection.isConnected(); +@@ -139,10 +154,12 @@ + + private void verifyLoginAndFinishConnectionSetup(GameProfile gameprofile) { + PlayerList playerlist = this.server.getPlayerList(); +- IChatBaseComponent ichatbasecomponent = playerlist.canPlayerLogin(this.connection.getRemoteAddress(), gameprofile); ++ // CraftBukkit start - fire PlayerLoginEvent ++ this.player = playerlist.canPlayerLogin(this, gameprofile); // CraftBukkit + +- if (ichatbasecomponent != null) { +- this.disconnect(ichatbasecomponent); ++ if (this.player == null) { ++ // this.disconnect(ichatbasecomponent); ++ // CraftBukkit end + } else { + if (this.server.getCompressionThreshold() >= 0 && !this.connection.isMemoryConnection()) { + this.connection.send(new PacketLoginOutSetCompression(this.server.getCompressionThreshold()), PacketSendListener.thenRun(() -> { +@@ -150,7 +167,7 @@ + })); + } + +- boolean flag = playerlist.disconnectAllPlayersWithProfile(gameprofile); ++ boolean flag = playerlist.disconnectAllPlayersWithProfile(gameprofile, this.player); // CraftBukkit - add player reference + + if (flag) { + this.state = LoginListener.EnumProtocolState.WAITING_FOR_DUPE_DISCONNECT; +@@ -200,6 +217,43 @@ + if (profileresult != null) { + GameProfile gameprofile = profileresult.profile(); + ++ // CraftBukkit start - fire PlayerPreLoginEvent ++ if (!connection.isConnected()) { ++ return; ++ } ++ ++ String playerName = gameprofile.getName(); ++ java.net.InetAddress address = ((java.net.InetSocketAddress) connection.getRemoteAddress()).getAddress(); ++ java.util.UUID uniqueId = gameprofile.getId(); ++ final org.bukkit.craftbukkit.CraftServer server = LoginListener.this.server.server; ++ ++ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId); ++ server.getPluginManager().callEvent(asyncEvent); ++ ++ if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { ++ final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); ++ if (asyncEvent.getResult() != PlayerPreLoginEvent.Result.ALLOWED) { ++ event.disallow(asyncEvent.getResult(), asyncEvent.getKickMessage()); ++ } ++ Waitable waitable = new Waitable() { ++ @Override ++ protected PlayerPreLoginEvent.Result evaluate() { ++ server.getPluginManager().callEvent(event); ++ return event.getResult(); ++ }}; ++ ++ LoginListener.this.server.processQueue.add(waitable); ++ if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) { ++ disconnect(event.getKickMessage()); ++ return; ++ } ++ } else { ++ if (asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { ++ disconnect(asyncEvent.getKickMessage()); ++ return; ++ } ++ } ++ // CraftBukkit end + LoginListener.LOGGER.info("UUID of player {} is {}", gameprofile.getName(), gameprofile.getId()); + LoginListener.this.startClientVerification(gameprofile); + } else if (LoginListener.this.server.isSingleplayer()) { +@@ -217,6 +271,11 @@ + LoginListener.this.disconnect(IChatBaseComponent.translatable("multiplayer.disconnect.authservers_down")); + LoginListener.LOGGER.error("Couldn't verify username because servers are unavailable"); + } ++ // CraftBukkit start - catch all exceptions ++ } catch (Exception exception) { ++ disconnect("Failed to verify username!"); ++ server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + s1, exception); ++ // CraftBukkit end + } + + } +@@ -242,7 +301,7 @@ + public void handleLoginAcknowledgement(ServerboundLoginAcknowledgedPacket serverboundloginacknowledgedpacket) { + Validate.validState(this.state == LoginListener.EnumProtocolState.PROTOCOL_SWITCHING, "Unexpected login acknowledgement packet", new Object[0]); + CommonListenerCookie commonlistenercookie = CommonListenerCookie.createInitial((GameProfile) Objects.requireNonNull(this.authenticatedProfile)); +- ServerConfigurationPacketListenerImpl serverconfigurationpacketlistenerimpl = new ServerConfigurationPacketListenerImpl(this.server, this.connection, commonlistenercookie); ++ ServerConfigurationPacketListenerImpl serverconfigurationpacketlistenerimpl = new ServerConfigurationPacketListenerImpl(this.server, this.connection, commonlistenercookie, this.player); // CraftBukkit + + this.connection.setListener(serverconfigurationpacketlistenerimpl); + serverconfigurationpacketlistenerimpl.startConfiguration(); diff --git a/patch-remap/og/net/minecraft/server/network/PacketStatusListener.patch b/patch-remap/og/net/minecraft/server/network/PacketStatusListener.patch new file mode 100644 index 0000000000..49073b4376 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/network/PacketStatusListener.patch @@ -0,0 +1,127 @@ +--- a/net/minecraft/server/network/PacketStatusListener.java ++++ b/net/minecraft/server/network/PacketStatusListener.java +@@ -9,6 +9,21 @@ + import net.minecraft.network.protocol.status.PacketStatusOutServerInfo; + import net.minecraft.network.protocol.status.ServerPing; + ++// CraftBukkit start ++import com.mojang.authlib.GameProfile; ++import java.net.InetSocketAddress; ++import java.util.Collections; ++import java.util.Iterator; ++import java.util.Optional; ++import net.minecraft.SharedConstants; ++import net.minecraft.network.protocol.status.ServerPing; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.EntityPlayer; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.craftbukkit.util.CraftIconCache; ++import org.bukkit.entity.Player; ++// CraftBukkit end ++ + public class PacketStatusListener implements PacketStatusInListener { + + private static final IChatBaseComponent DISCONNECT_REASON = IChatBaseComponent.translatable("multiplayer.status.request_handled"); +@@ -35,7 +50,101 @@ + this.connection.disconnect(PacketStatusListener.DISCONNECT_REASON); + } else { + this.hasRequestedStatus = true; +- this.connection.send(new PacketStatusOutServerInfo(this.status)); ++ // CraftBukkit start ++ // this.connection.send(new PacketStatusOutServerInfo(this.status)); ++ MinecraftServer server = MinecraftServer.getServer(); ++ final Object[] players = server.getPlayerList().players.toArray(); ++ class ServerListPingEvent extends org.bukkit.event.server.ServerListPingEvent { ++ ++ CraftIconCache icon = server.server.getServerIcon(); ++ ++ ServerListPingEvent() { ++ super(connection.hostname, ((InetSocketAddress) connection.getRemoteAddress()).getAddress(), server.getMotd(), server.getPlayerList().getMaxPlayers()); ++ } ++ ++ @Override ++ public void setServerIcon(org.bukkit.util.CachedServerIcon icon) { ++ if (!(icon instanceof CraftIconCache)) { ++ throw new IllegalArgumentException(icon + " was not created by " + org.bukkit.craftbukkit.CraftServer.class); ++ } ++ this.icon = (CraftIconCache) icon; ++ } ++ ++ @Override ++ public Iterator iterator() throws UnsupportedOperationException { ++ return new Iterator() { ++ int i; ++ int ret = Integer.MIN_VALUE; ++ EntityPlayer player; ++ ++ @Override ++ public boolean hasNext() { ++ if (player != null) { ++ return true; ++ } ++ final Object[] currentPlayers = players; ++ for (int length = currentPlayers.length, i = this.i; i < length; i++) { ++ final EntityPlayer player = (EntityPlayer) currentPlayers[i]; ++ if (player != null) { ++ this.i = i + 1; ++ this.player = player; ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ @Override ++ public Player next() { ++ if (!hasNext()) { ++ throw new java.util.NoSuchElementException(); ++ } ++ final EntityPlayer player = this.player; ++ this.player = null; ++ this.ret = this.i - 1; ++ return player.getBukkitEntity(); ++ } ++ ++ @Override ++ public void remove() { ++ final Object[] currentPlayers = players; ++ final int i = this.ret; ++ if (i < 0 || currentPlayers[i] == null) { ++ throw new IllegalStateException(); ++ } ++ currentPlayers[i] = null; ++ } ++ }; ++ } ++ } ++ ++ ServerListPingEvent event = new ServerListPingEvent(); ++ server.server.getPluginManager().callEvent(event); ++ ++ java.util.List profiles = new java.util.ArrayList(players.length); ++ for (Object player : players) { ++ if (player != null) { ++ EntityPlayer entityPlayer = ((EntityPlayer) player); ++ if (entityPlayer.allowsListing()) { ++ profiles.add(entityPlayer.getGameProfile()); ++ } else { ++ profiles.add(MinecraftServer.ANONYMOUS_PLAYER_PROFILE); ++ } ++ } ++ } ++ ++ ServerPing.ServerPingPlayerSample playerSample = new ServerPing.ServerPingPlayerSample(event.getMaxPlayers(), profiles.size(), (server.hidesOnlinePlayers()) ? Collections.emptyList() : profiles); ++ ++ ServerPing ping = new ServerPing( ++ CraftChatMessage.fromString(event.getMotd(), true)[0], ++ Optional.of(playerSample), ++ Optional.of(new ServerPing.ServerData(server.getServerModName() + " " + server.getServerVersion(), SharedConstants.getCurrentVersion().getProtocolVersion())), ++ (event.icon.value != null) ? Optional.of(new ServerPing.a(event.icon.value)) : Optional.empty(), ++ server.enforceSecureProfile() ++ ); ++ ++ this.connection.send(new PacketStatusOutServerInfo(ping)); ++ // CraftBukkit end + } + } + diff --git a/patch-remap/og/net/minecraft/server/network/PlayerConnection.patch b/patch-remap/og/net/minecraft/server/network/PlayerConnection.patch new file mode 100644 index 0000000000..de9913f60c --- /dev/null +++ b/patch-remap/og/net/minecraft/server/network/PlayerConnection.patch @@ -0,0 +1,1663 @@ +--- a/net/minecraft/server/network/PlayerConnection.java ++++ b/net/minecraft/server/network/PlayerConnection.java +@@ -183,6 +183,67 @@ + import net.minecraft.world.phys.shapes.VoxelShapes; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.mojang.datafixers.util.Pair; ++import java.util.Arrays; ++import java.util.concurrent.ExecutionException; ++import java.util.concurrent.atomic.AtomicInteger; ++import java.util.function.Function; ++import net.minecraft.network.chat.OutgoingChatMessage; ++import net.minecraft.network.protocol.game.PacketPlayOutAttachEntity; ++import net.minecraft.network.protocol.game.PacketPlayOutEntityEquipment; ++import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; ++import net.minecraft.world.entity.EntityInsentient; ++import net.minecraft.world.entity.animal.Bucketable; ++import net.minecraft.world.entity.EntityLiving; ++import net.minecraft.world.entity.EnumItemSlot; ++import net.minecraft.world.entity.animal.allay.Allay; ++import net.minecraft.world.inventory.InventoryClickType; ++import net.minecraft.world.inventory.Slot; ++import net.minecraft.world.item.crafting.RecipeHolder; ++import net.minecraft.world.level.RayTrace; ++import net.minecraft.world.phys.MovingObjectPosition; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftEntity; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.craftbukkit.util.LazyPlayerSet; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Event; ++import org.bukkit.event.block.Action; ++import org.bukkit.event.inventory.ClickType; ++import org.bukkit.event.inventory.CraftItemEvent; ++import org.bukkit.event.inventory.InventoryAction; ++import org.bukkit.event.inventory.InventoryClickEvent; ++import org.bukkit.event.inventory.InventoryCreativeEvent; ++import org.bukkit.event.inventory.InventoryType.SlotType; ++import org.bukkit.event.inventory.SmithItemEvent; ++import org.bukkit.event.player.AsyncPlayerChatEvent; ++import org.bukkit.event.player.PlayerAnimationEvent; ++import org.bukkit.event.player.PlayerAnimationType; ++import org.bukkit.event.player.PlayerChatEvent; ++import org.bukkit.event.player.PlayerCommandPreprocessEvent; ++import org.bukkit.event.player.PlayerInteractAtEntityEvent; ++import org.bukkit.event.player.PlayerInteractEntityEvent; ++import org.bukkit.event.player.PlayerItemHeldEvent; ++import org.bukkit.event.player.PlayerMoveEvent; ++import org.bukkit.event.player.PlayerRespawnEvent.RespawnReason; ++import org.bukkit.event.player.PlayerSwapHandItemsEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++import org.bukkit.event.player.PlayerToggleFlightEvent; ++import org.bukkit.event.player.PlayerToggleSneakEvent; ++import org.bukkit.event.player.PlayerToggleSprintEvent; ++import org.bukkit.inventory.CraftingInventory; ++import org.bukkit.inventory.EquipmentSlot; ++import org.bukkit.inventory.InventoryView; ++import org.bukkit.inventory.SmithingInventory; ++// CraftBukkit end ++ + public class PlayerConnection extends ServerCommonPacketListenerImpl implements PacketListenerPlayIn, ServerPlayerConnection, TickablePacketListener { + + static final Logger LOGGER = LogUtils.getLogger(); +@@ -194,7 +255,9 @@ + public final PlayerChunkSender chunkSender; + private int tickCount; + private int ackBlockChangesUpTo = -1; +- private int chatSpamTickCount; ++ // CraftBukkit start - multithreaded fields ++ private final AtomicInteger chatSpamTickCount = new AtomicInteger(); ++ // CraftBukkit end + private int dropSpamTickCount; + private double firstGoodX; + private double firstGoodY; +@@ -229,7 +292,7 @@ + private boolean waitingForSwitchToConfig; + + public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer, CommonListenerCookie commonlistenercookie) { +- super(minecraftserver, networkmanager, commonlistenercookie); ++ super(minecraftserver, networkmanager, commonlistenercookie, entityplayer); // CraftBukkit + this.chunkSender = new PlayerChunkSender(networkmanager.isMemoryConnection()); + networkmanager.setListener(this); + this.player = entityplayer; +@@ -239,9 +302,25 @@ + + Objects.requireNonNull(minecraftserver); + this.signedMessageDecoder = SignedMessageChain.b.unsigned(uuid, minecraftserver::enforceSecureProfile); +- this.chatMessageChain = new FutureChain(minecraftserver); ++ this.chatMessageChain = new FutureChain(minecraftserver.chatExecutor); // CraftBukkit - async chat + } + ++ // CraftBukkit start - add fields ++ private int lastTick = MinecraftServer.currentTick; ++ private int allowedPlayerTicks = 1; ++ private int lastDropTick = MinecraftServer.currentTick; ++ private int lastBookTick = MinecraftServer.currentTick; ++ private int dropCount = 0; ++ ++ // Get position of last block hit for BlockDamageLevel.STOPPED ++ private double lastPosX = Double.MAX_VALUE; ++ private double lastPosY = Double.MAX_VALUE; ++ private double lastPosZ = Double.MAX_VALUE; ++ private float lastPitch = Float.MAX_VALUE; ++ private float lastYaw = Float.MAX_VALUE; ++ private boolean justTeleported = false; ++ // CraftBukkit end ++ + @Override + public void tick() { + if (this.ackBlockChangesUpTo > -1) { +@@ -293,15 +372,21 @@ + } + + this.keepConnectionAlive(); ++ // CraftBukkit start ++ for (int spam; (spam = this.chatSpamTickCount.get()) > 0 && !chatSpamTickCount.compareAndSet(spam, spam - 1); ) ; ++ /* Use thread-safe field access instead + if (this.chatSpamTickCount > 0) { + --this.chatSpamTickCount; + } ++ */ ++ // CraftBukkit end + + if (this.dropSpamTickCount > 0) { + --this.dropSpamTickCount; + } + + if (this.player.getLastActionTime() > 0L && this.server.getPlayerIdleTimeout() > 0 && SystemUtils.getMillis() - this.player.getLastActionTime() > (long) this.server.getPlayerIdleTimeout() * 1000L * 60L) { ++ this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 + this.disconnect(IChatBaseComponent.translatable("multiplayer.disconnect.idling")); + } + +@@ -392,7 +477,34 @@ + double d9 = entity.getDeltaMovement().lengthSqr(); + double d10 = d6 * d6 + d7 * d7 + d8 * d8; + +- if (d10 - d9 > 100.0D && !this.isSingleplayerOwner()) { ++ ++ // CraftBukkit start - handle custom speeds and skipped ticks ++ this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick; ++ this.allowedPlayerTicks = Math.max(this.allowedPlayerTicks, 1); ++ this.lastTick = (int) (System.currentTimeMillis() / 50); ++ ++ ++this.receivedMovePacketCount; ++ int i = this.receivedMovePacketCount - this.knownMovePacketCount; ++ if (i > Math.max(this.allowedPlayerTicks, 5)) { ++ PlayerConnection.LOGGER.debug(this.player.getScoreboardName() + " is sending move packets too frequently (" + i + " packets since last tick)"); ++ i = 1; ++ } ++ ++ if (d10 > 0) { ++ allowedPlayerTicks -= 1; ++ } else { ++ allowedPlayerTicks = 20; ++ } ++ double speed; ++ if (player.getAbilities().flying) { ++ speed = player.getAbilities().flyingSpeed * 20f; ++ } else { ++ speed = player.getAbilities().walkingSpeed * 10f; ++ } ++ speed *= 2f; // TODO: Get the speed of the vehicle instead of the player ++ ++ if (d10 - d9 > Math.max(100.0D, Math.pow((double) (10.0F * (float) i * speed), 2)) && !this.isSingleplayerOwner()) { ++ // CraftBukkit end + PlayerConnection.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", new Object[]{entity.getName().getString(), this.player.getName().getString(), d6, d7, d8}); + this.send(new PacketPlayOutVehicleMove(entity)); + return; +@@ -432,14 +544,72 @@ + } + + entity.absMoveTo(d3, d4, d5, f, f1); ++ player.absMoveTo(d3, d4, d5, this.player.getYRot(), this.player.getXRot()); // CraftBukkit + boolean flag3 = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D)); + + if (flag && (flag2 || !flag3)) { + entity.absMoveTo(d0, d1, d2, f, f1); ++ player.absMoveTo(d0, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit + this.send(new PacketPlayOutVehicleMove(entity)); + return; + } + ++ // CraftBukkit start - fire PlayerMoveEvent ++ Player player = this.getCraftPlayer(); ++ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. ++ Location to = player.getLocation().clone(); // Start off the To location as the Players current location. ++ ++ // If the packet contains movement information then we update the To location with the correct XYZ. ++ to.setX(packetplayinvehiclemove.getX()); ++ to.setY(packetplayinvehiclemove.getY()); ++ to.setZ(packetplayinvehiclemove.getZ()); ++ ++ ++ // If the packet contains look information then we update the To location with the correct Yaw & Pitch. ++ to.setYaw(packetplayinvehiclemove.getYRot()); ++ to.setPitch(packetplayinvehiclemove.getXRot()); ++ ++ // Prevent 40 event-calls for less than a single pixel of movement >.> ++ double delta = Math.pow(this.lastPosX - to.getX(), 2) + Math.pow(this.lastPosY - to.getY(), 2) + Math.pow(this.lastPosZ - to.getZ(), 2); ++ float deltaAngle = Math.abs(this.lastYaw - to.getYaw()) + Math.abs(this.lastPitch - to.getPitch()); ++ ++ if ((delta > 1f / 256 || deltaAngle > 10f) && !this.player.isImmobile()) { ++ this.lastPosX = to.getX(); ++ this.lastPosY = to.getY(); ++ this.lastPosZ = to.getZ(); ++ this.lastYaw = to.getYaw(); ++ this.lastPitch = to.getPitch(); ++ ++ // Skip the first time we do this ++ if (from.getX() != Double.MAX_VALUE) { ++ Location oldTo = to.clone(); ++ PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ // If the event is cancelled we move the player back to their old location. ++ if (event.isCancelled()) { ++ teleport(from); ++ return; ++ } ++ ++ // If a Plugin has changed the To destination then we teleport the Player ++ // there to avoid any 'Moved wrongly' or 'Moved too quickly' errors. ++ // We only do this if the Event was not cancelled. ++ if (!oldTo.equals(event.getTo()) && !event.isCancelled()) { ++ this.player.getBukkitEntity().teleport(event.getTo(), PlayerTeleportEvent.TeleportCause.PLUGIN); ++ return; ++ } ++ ++ // Check to see if the Players Location has some how changed during the call of the event. ++ // This can happen due to a plugin teleporting the player instead of using .setTo() ++ if (!from.equals(this.getCraftPlayer().getLocation()) && this.justTeleported) { ++ this.justTeleported = false; ++ return; ++ } ++ } ++ } ++ // CraftBukkit end ++ + this.player.serverLevel().getChunkSource().move(this.player); + this.player.checkMovementStatistics(this.player.getX() - d0, this.player.getY() - d1, this.player.getZ() - d2); + this.clientVehicleIsFloating = d11 >= -0.03125D && !flag1 && !this.server.isFlightAllowed() && !entity.isNoGravity() && this.noBlocksAround(entity); +@@ -473,6 +643,7 @@ + } + + this.awaitingPositionFromClient = null; ++ this.player.serverLevel().getChunkSource().move(this.player); // CraftBukkit + } + + } +@@ -480,7 +651,7 @@ + @Override + public void handleRecipeBookSeenRecipePacket(PacketPlayInRecipeDisplayed packetplayinrecipedisplayed) { + PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinrecipedisplayed, this, this.player.serverLevel()); +- Optional optional = this.server.getRecipeManager().byKey(packetplayinrecipedisplayed.getRecipe()); ++ Optional> optional = this.server.getRecipeManager().byKey(packetplayinrecipedisplayed.getRecipe()); // CraftBukkit - decompile error + RecipeBookServer recipebookserver = this.player.getRecipeBook(); + + Objects.requireNonNull(recipebookserver); +@@ -490,6 +661,7 @@ + @Override + public void handleRecipeBookChangeSettingsPacket(PacketPlayInRecipeSettings packetplayinrecipesettings) { + PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinrecipesettings, this, this.player.serverLevel()); ++ CraftEventFactory.callRecipeBookSettingsEvent(this.player, packetplayinrecipesettings.getBookType(), packetplayinrecipesettings.isOpen(), packetplayinrecipesettings.isFiltering()); // CraftBukkit + this.player.getRecipeBook().setBookSetting(packetplayinrecipesettings.getBookType(), packetplayinrecipesettings.isOpen(), packetplayinrecipesettings.isFiltering()); + } + +@@ -510,6 +682,12 @@ + @Override + public void handleCustomCommandSuggestions(PacketPlayInTabComplete packetplayintabcomplete) { + PlayerConnectionUtils.ensureRunningOnSameThread(packetplayintabcomplete, this, this.player.serverLevel()); ++ // CraftBukkit start ++ if (chatSpamTickCount.addAndGet(1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { ++ this.disconnect(IChatBaseComponent.translatable("disconnect.spam")); ++ return; ++ } ++ // CraftBukkit end + StringReader stringreader = new StringReader(packetplayintabcomplete.getCommand()); + + if (stringreader.canRead() && stringreader.peek() == '/') { +@@ -519,6 +697,7 @@ + ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); + + this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { ++ if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer + this.send(new PacketPlayOutTabComplete(packetplayintabcomplete.getId(), suggestions)); + }); + } +@@ -766,6 +945,13 @@ + + if (container instanceof ContainerMerchant) { + ContainerMerchant containermerchant = (ContainerMerchant) container; ++ // CraftBukkit start ++ final org.bukkit.event.inventory.TradeSelectEvent tradeSelectEvent = CraftEventFactory.callTradeSelectEvent(this.player, i, containermerchant); ++ if (tradeSelectEvent.isCancelled()) { ++ this.player.getBukkitEntity().updateInventory(); ++ return; ++ } ++ // CraftBukkit end + + if (!containermerchant.stillValid(this.player)) { + PlayerConnection.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, containermerchant); +@@ -780,6 +966,13 @@ + + @Override + public void handleEditBook(PacketPlayInBEdit packetplayinbedit) { ++ // CraftBukkit start ++ if (this.lastBookTick + 20 > MinecraftServer.currentTick) { ++ this.disconnect("Book edited too quickly!"); ++ return; ++ } ++ this.lastBookTick = MinecraftServer.currentTick; ++ // CraftBukkit end + int i = packetplayinbedit.getSlot(); + + if (PlayerInventory.isHotbarSlot(i) || i == 40) { +@@ -788,7 +981,7 @@ + + Objects.requireNonNull(list); + optional.ifPresent(list::add); +- Stream stream = packetplayinbedit.getPages().stream().limit(100L); ++ Stream stream = packetplayinbedit.getPages().stream().limit(100L); // CraftBukkit - decompile error + + Objects.requireNonNull(list); + stream.forEach(list::add); +@@ -806,7 +999,7 @@ + ItemStack itemstack = this.player.getInventory().getItem(i); + + if (itemstack.is(Items.WRITABLE_BOOK)) { +- this.updateBookPages(list, UnaryOperator.identity(), itemstack); ++ this.updateBookPages(list, UnaryOperator.identity(), itemstack.copy(), i, itemstack); // CraftBukkit + } + } + +@@ -831,16 +1024,16 @@ + + this.updateBookPages(list, (s) -> { + return IChatBaseComponent.ChatSerializer.toJson(IChatBaseComponent.literal(s)); +- }, itemstack1); +- this.player.getInventory().setItem(i, itemstack1); ++ }, itemstack1, i, itemstack); // CraftBukkit ++ this.player.getInventory().setItem(i, itemstack); // CraftBukkit - event factory updates the hand book + } + } + +- private void updateBookPages(List list, UnaryOperator unaryoperator, ItemStack itemstack) { ++ private void updateBookPages(List list, UnaryOperator unaryoperator, ItemStack itemstack, int slot, ItemStack handItem) { // CraftBukkit + NBTTagList nbttaglist = new NBTTagList(); + + if (this.player.isTextFilteringEnabled()) { +- Stream stream = list.stream().map((filteredtext) -> { ++ Stream stream = list.stream().map((filteredtext) -> { // CraftBukkit - decompile error + return NBTTagString.valueOf((String) unaryoperator.apply(filteredtext.filteredOrEmpty())); + }); + +@@ -866,6 +1059,7 @@ + } + + itemstack.addTagElement("pages", nbttaglist); ++ CraftEventFactory.handleEditBookEvent(player, slot, handItem, itemstack); // CraftBukkit + } + + @Override +@@ -922,7 +1116,7 @@ + } else { + WorldServer worldserver = this.player.serverLevel(); + +- if (!this.player.wonGame) { ++ if (!this.player.wonGame && !this.player.isImmobile()) { // CraftBukkit + if (this.tickCount == 0) { + this.resetPosition(); + } +@@ -932,7 +1126,7 @@ + this.awaitingTeleportTime = this.tickCount; + this.teleport(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); + } +- ++ this.allowedPlayerTicks = 20; // CraftBukkit + } else { + this.awaitingTeleportTime = this.tickCount; + double d0 = clampHorizontal(packetplayinflying.getX(this.player.getX())); +@@ -944,7 +1138,15 @@ + if (this.player.isPassenger()) { + this.player.absMoveTo(this.player.getX(), this.player.getY(), this.player.getZ(), f, f1); + this.player.serverLevel().getChunkSource().move(this.player); ++ this.allowedPlayerTicks = 20; // CraftBukkit + } else { ++ // CraftBukkit - Make sure the move is valid but then reset it for plugins to modify ++ double prevX = player.getX(); ++ double prevY = player.getY(); ++ double prevZ = player.getZ(); ++ float prevYaw = player.getYRot(); ++ float prevPitch = player.getXRot(); ++ // CraftBukkit end + double d3 = this.player.getX(); + double d4 = this.player.getY(); + double d5 = this.player.getZ(); +@@ -964,15 +1166,33 @@ + ++this.receivedMovePacketCount; + int i = this.receivedMovePacketCount - this.knownMovePacketCount; + +- if (i > 5) { ++ // CraftBukkit start - handle custom speeds and skipped ticks ++ this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick; ++ this.allowedPlayerTicks = Math.max(this.allowedPlayerTicks, 1); ++ this.lastTick = (int) (System.currentTimeMillis() / 50); ++ ++ if (i > Math.max(this.allowedPlayerTicks, 5)) { + PlayerConnection.LOGGER.debug("{} is sending move packets too frequently ({} packets since last tick)", this.player.getName().getString(), i); + i = 1; + } + ++ if (packetplayinflying.hasRot || d10 > 0) { ++ allowedPlayerTicks -= 1; ++ } else { ++ allowedPlayerTicks = 20; ++ } ++ double speed; ++ if (player.getAbilities().flying) { ++ speed = player.getAbilities().flyingSpeed * 20f; ++ } else { ++ speed = player.getAbilities().walkingSpeed * 10f; ++ } ++ + if (!this.player.isChangingDimension() && (!this.player.level().getGameRules().getBoolean(GameRules.RULE_DISABLE_ELYTRA_MOVEMENT_CHECK) || !this.player.isFallFlying())) { + float f2 = this.player.isFallFlying() ? 300.0F : 100.0F; + +- if (d10 - d9 > (double) (f2 * (float) i) && !this.isSingleplayerOwner()) { ++ if (d10 - d9 > Math.max(f2, Math.pow((double) (10.0F * (float) i * speed), 2)) && !this.isSingleplayerOwner()) { ++ // CraftBukkit end + PlayerConnection.LOGGER.warn("{} moved too quickly! {},{},{}", new Object[]{this.player.getName().getString(), d6, d7, d8}); + this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot()); + return; +@@ -994,6 +1214,7 @@ + boolean flag1 = this.player.verticalCollisionBelow; + + this.player.move(EnumMoveType.PLAYER, new Vec3D(d6, d7, d8)); ++ this.player.onGround = packetplayinflying.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move + double d11 = d7; + + d6 = d0 - this.player.getX(); +@@ -1012,9 +1233,70 @@ + } + + if (!this.player.noPhysics && !this.player.isSleeping() && (flag2 && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb, d0, d1, d2))) { +- this.teleport(d3, d4, d5, f, f1); ++ this.internalTeleport(d3, d4, d5, f, f1, Collections.emptySet()); // CraftBukkit - SPIGOT-1807: Don't call teleport event, when the client thinks the player is falling, because the chunks are not loaded on the client yet. + this.player.doCheckFallDamage(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5, packetplayinflying.isOnGround()); + } else { ++ // CraftBukkit start - fire PlayerMoveEvent ++ // Reset to old location first ++ this.player.absMoveTo(prevX, prevY, prevZ, prevYaw, prevPitch); ++ ++ Player player = this.getCraftPlayer(); ++ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. ++ Location to = player.getLocation().clone(); // Start off the To location as the Players current location. ++ ++ // If the packet contains movement information then we update the To location with the correct XYZ. ++ if (packetplayinflying.hasPos) { ++ to.setX(packetplayinflying.x); ++ to.setY(packetplayinflying.y); ++ to.setZ(packetplayinflying.z); ++ } ++ ++ // If the packet contains look information then we update the To location with the correct Yaw & Pitch. ++ if (packetplayinflying.hasRot) { ++ to.setYaw(packetplayinflying.yRot); ++ to.setPitch(packetplayinflying.xRot); ++ } ++ ++ // Prevent 40 event-calls for less than a single pixel of movement >.> ++ double delta = Math.pow(this.lastPosX - to.getX(), 2) + Math.pow(this.lastPosY - to.getY(), 2) + Math.pow(this.lastPosZ - to.getZ(), 2); ++ float deltaAngle = Math.abs(this.lastYaw - to.getYaw()) + Math.abs(this.lastPitch - to.getPitch()); ++ ++ if ((delta > 1f / 256 || deltaAngle > 10f) && !this.player.isImmobile()) { ++ this.lastPosX = to.getX(); ++ this.lastPosY = to.getY(); ++ this.lastPosZ = to.getZ(); ++ this.lastYaw = to.getYaw(); ++ this.lastPitch = to.getPitch(); ++ ++ // Skip the first time we do this ++ if (from.getX() != Double.MAX_VALUE) { ++ Location oldTo = to.clone(); ++ PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ // If the event is cancelled we move the player back to their old location. ++ if (event.isCancelled()) { ++ teleport(from); ++ return; ++ } ++ ++ // If a Plugin has changed the To destination then we teleport the Player ++ // there to avoid any 'Moved wrongly' or 'Moved too quickly' errors. ++ // We only do this if the Event was not cancelled. ++ if (!oldTo.equals(event.getTo()) && !event.isCancelled()) { ++ this.player.getBukkitEntity().teleport(event.getTo(), PlayerTeleportEvent.TeleportCause.PLUGIN); ++ return; ++ } ++ ++ // Check to see if the Players Location has some how changed during the call of the event. ++ // This can happen due to a plugin teleporting the player instead of using .setTo() ++ if (!from.equals(this.getCraftPlayer().getLocation()) && this.justTeleported) { ++ this.justTeleported = false; ++ return; ++ } ++ } ++ } ++ // CraftBukkit end + this.player.absMoveTo(d0, d1, d2, f, f1); + this.clientIsFloating = d11 >= -0.03125D && !flag1 && this.player.gameMode.getGameModeForPlayer() != EnumGamemode.SPECTATOR && !this.server.isFlightAllowed() && !this.player.getAbilities().mayfly && !this.player.hasEffect(MobEffects.LEVITATION) && !this.player.isFallFlying() && !this.player.isAutoSpinAttack() && this.noBlocksAround(this.player); + this.player.serverLevel().getChunkSource().move(this.player); +@@ -1055,11 +1337,68 @@ + return true; + } + ++ // CraftBukkit start - Delegate to teleport(Location) + public void teleport(double d0, double d1, double d2, float f, float f1) { +- this.teleport(d0, d1, d2, f, f1, Collections.emptySet()); ++ this.teleport(d0, d1, d2, f, f1, PlayerTeleportEvent.TeleportCause.UNKNOWN); ++ } ++ ++ public void teleport(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { ++ this.teleport(d0, d1, d2, f, f1, Collections.emptySet(), cause); + } + + public void teleport(double d0, double d1, double d2, float f, float f1, Set set) { ++ this.teleport(d0, d1, d2, f, f1, set, PlayerTeleportEvent.TeleportCause.UNKNOWN); ++ } ++ ++ public boolean teleport(double d0, double d1, double d2, float f, float f1, Set set, PlayerTeleportEvent.TeleportCause cause) { // CraftBukkit - Return event status ++ Player player = this.getCraftPlayer(); ++ Location from = player.getLocation(); ++ ++ double x = d0; ++ double y = d1; ++ double z = d2; ++ float yaw = f; ++ float pitch = f1; ++ ++ Location to = new Location(this.getCraftPlayer().getWorld(), x, y, z, yaw, pitch); ++ // SPIGOT-5171: Triggered on join ++ if (from.equals(to)) { ++ this.internalTeleport(d0, d1, d2, f, f1, set); ++ return false; // CraftBukkit - Return event status ++ } ++ ++ PlayerTeleportEvent event = new PlayerTeleportEvent(player, from.clone(), to.clone(), cause); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled() || !to.equals(event.getTo())) { ++ set.clear(); // Can't relative teleport ++ to = event.isCancelled() ? event.getFrom() : event.getTo(); ++ d0 = to.getX(); ++ d1 = to.getY(); ++ d2 = to.getZ(); ++ f = to.getYaw(); ++ f1 = to.getPitch(); ++ } ++ ++ this.internalTeleport(d0, d1, d2, f, f1, set); ++ return event.isCancelled(); // CraftBukkit - Return event status ++ } ++ ++ public void teleport(Location dest) { ++ internalTeleport(dest.getX(), dest.getY(), dest.getZ(), dest.getYaw(), dest.getPitch(), Collections.emptySet()); ++ } ++ ++ private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set set) { ++ // CraftBukkit start ++ if (Float.isNaN(f)) { ++ f = 0; ++ } ++ if (Float.isNaN(f1)) { ++ f1 = 0; ++ } ++ ++ this.justTeleported = true; ++ // CraftBukkit end + double d3 = set.contains(RelativeMovement.X) ? this.player.getX() : 0.0D; + double d4 = set.contains(RelativeMovement.Y) ? this.player.getY() : 0.0D; + double d5 = set.contains(RelativeMovement.Z) ? this.player.getZ() : 0.0D; +@@ -1071,6 +1410,14 @@ + this.awaitingTeleport = 0; + } + ++ // CraftBukkit start - update last location ++ this.lastPosX = this.awaitingPositionFromClient.x; ++ this.lastPosY = this.awaitingPositionFromClient.y; ++ this.lastPosZ = this.awaitingPositionFromClient.z; ++ this.lastYaw = f; ++ this.lastPitch = f1; ++ // CraftBukkit end ++ + this.awaitingTeleportTime = this.tickCount; + this.player.absMoveTo(d0, d1, d2, f, f1); + this.player.connection.send(new PacketPlayOutPosition(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport)); +@@ -1079,6 +1426,7 @@ + @Override + public void handlePlayerAction(PacketPlayInBlockDig packetplayinblockdig) { + PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinblockdig, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + BlockPosition blockposition = packetplayinblockdig.getPos(); + + this.player.resetLastActionTime(); +@@ -1089,14 +1437,46 @@ + if (!this.player.isSpectator()) { + ItemStack itemstack = this.player.getItemInHand(EnumHand.OFF_HAND); + +- this.player.setItemInHand(EnumHand.OFF_HAND, this.player.getItemInHand(EnumHand.MAIN_HAND)); +- this.player.setItemInHand(EnumHand.MAIN_HAND, itemstack); ++ // CraftBukkit start - inspiration taken from DispenserRegistry (See SpigotCraft#394) ++ CraftItemStack mainHand = CraftItemStack.asCraftMirror(itemstack); ++ CraftItemStack offHand = CraftItemStack.asCraftMirror(this.player.getItemInHand(EnumHand.MAIN_HAND)); ++ PlayerSwapHandItemsEvent swapItemsEvent = new PlayerSwapHandItemsEvent(getCraftPlayer(), mainHand.clone(), offHand.clone()); ++ this.cserver.getPluginManager().callEvent(swapItemsEvent); ++ if (swapItemsEvent.isCancelled()) { ++ return; ++ } ++ if (swapItemsEvent.getOffHandItem().equals(offHand)) { ++ this.player.setItemInHand(EnumHand.OFF_HAND, this.player.getItemInHand(EnumHand.MAIN_HAND)); ++ } else { ++ this.player.setItemInHand(EnumHand.OFF_HAND, CraftItemStack.asNMSCopy(swapItemsEvent.getOffHandItem())); ++ } ++ if (swapItemsEvent.getMainHandItem().equals(mainHand)) { ++ this.player.setItemInHand(EnumHand.MAIN_HAND, itemstack); ++ } else { ++ this.player.setItemInHand(EnumHand.MAIN_HAND, CraftItemStack.asNMSCopy(swapItemsEvent.getMainHandItem())); ++ } ++ // CraftBukkit end + this.player.stopUsingItem(); + } + + return; + case DROP_ITEM: + if (!this.player.isSpectator()) { ++ // limit how quickly items can be dropped ++ // If the ticks aren't the same then the count starts from 0 and we update the lastDropTick. ++ if (this.lastDropTick != MinecraftServer.currentTick) { ++ this.dropCount = 0; ++ this.lastDropTick = MinecraftServer.currentTick; ++ } else { ++ // Else we increment the drop count and check the amount. ++ this.dropCount++; ++ if (this.dropCount >= 20) { ++ LOGGER.warn(this.player.getScoreboardName() + " dropped their items too quickly!"); ++ this.disconnect("You dropped your items too quickly (Hacking?)"); ++ return; ++ } ++ } ++ // CraftBukkit end + this.player.drop(false); + } + +@@ -1134,6 +1514,7 @@ + @Override + public void handleUseItemOn(PacketPlayInUseItem packetplayinuseitem) { + PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinuseitem, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.connection.ackBlockChangesUpTo(packetplayinuseitem.getSequence()); + WorldServer worldserver = this.player.serverLevel(); + EnumHand enumhand = packetplayinuseitem.getHand(); +@@ -1157,6 +1538,7 @@ + + if (blockposition.getY() < i) { + if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.mayInteract(this.player, blockposition)) { ++ this.player.stopUsingItem(); // CraftBukkit - SPIGOT-4706 + EnumInteractionResult enuminteractionresult = this.player.gameMode.useItemOn(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock); + + if (enumdirection == EnumDirection.UP && !enuminteractionresult.consumesAction() && blockposition.getY() >= i - 1 && wasBlockPlacementAttempt(this.player, itemstack)) { +@@ -1185,6 +1567,7 @@ + @Override + public void handleUseItem(PacketPlayInBlockPlace packetplayinblockplace) { + PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinblockplace, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.ackBlockChangesUpTo(packetplayinblockplace.getSequence()); + WorldServer worldserver = this.player.serverLevel(); + EnumHand enumhand = packetplayinblockplace.getHand(); +@@ -1192,6 +1575,49 @@ + + this.player.resetLastActionTime(); + if (!itemstack.isEmpty() && itemstack.isItemEnabled(worldserver.enabledFeatures())) { ++ // CraftBukkit start ++ // Raytrace to look for 'rogue armswings' ++ float f1 = this.player.getXRot(); ++ float f2 = this.player.getYRot(); ++ double d0 = this.player.getX(); ++ double d1 = this.player.getY() + (double) this.player.getEyeHeight(); ++ double d2 = this.player.getZ(); ++ Vec3D vec3d = new Vec3D(d0, d1, d2); ++ ++ float f3 = MathHelper.cos(-f2 * 0.017453292F - 3.1415927F); ++ float f4 = MathHelper.sin(-f2 * 0.017453292F - 3.1415927F); ++ float f5 = -MathHelper.cos(-f1 * 0.017453292F); ++ float f6 = MathHelper.sin(-f1 * 0.017453292F); ++ float f7 = f4 * f5; ++ float f8 = f3 * f5; ++ double d3 = player.gameMode.getGameModeForPlayer()== EnumGamemode.CREATIVE ? 5.0D : 4.5D; ++ Vec3D vec3d1 = vec3d.add((double) f7 * d3, (double) f6 * d3, (double) f8 * d3); ++ MovingObjectPosition movingobjectposition = this.player.level().clip(new RayTrace(vec3d, vec3d1, RayTrace.BlockCollisionOption.OUTLINE, RayTrace.FluidCollisionOption.NONE, player)); ++ ++ boolean cancelled; ++ if (movingobjectposition == null || movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.BLOCK) { ++ org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.RIGHT_CLICK_AIR, itemstack, enumhand); ++ cancelled = event.useItemInHand() == Event.Result.DENY; ++ } else { ++ MovingObjectPositionBlock movingobjectpositionblock = (MovingObjectPositionBlock) movingobjectposition; ++ if (player.gameMode.firedInteract && player.gameMode.interactPosition.equals(movingobjectpositionblock.getBlockPos()) && player.gameMode.interactHand == enumhand && ItemStack.isSameItemSameTags(player.gameMode.interactItemStack, itemstack)) { ++ cancelled = player.gameMode.interactResult; ++ } else { ++ org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), itemstack, true, enumhand, movingobjectpositionblock.getLocation()); ++ cancelled = event.useItemInHand() == Event.Result.DENY; ++ } ++ player.gameMode.firedInteract = false; ++ } ++ ++ if (cancelled) { ++ this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524 ++ return; ++ } ++ itemstack = this.player.getItemInHand(enumhand); // Update in case it was changed in the event ++ if (itemstack.isEmpty()) { ++ return; ++ } ++ // CraftBukkit end + EnumInteractionResult enuminteractionresult = this.player.gameMode.useItem(this.player, worldserver, itemstack, enumhand); + + if (enuminteractionresult.shouldSwing()) { +@@ -1212,7 +1638,7 @@ + Entity entity = packetplayinspectate.getEntity(worldserver); + + if (entity != null) { +- this.player.teleportTo(worldserver, entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot()); ++ this.player.teleportTo(worldserver, entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot(), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.SPECTATE); // CraftBukkit + return; + } + } +@@ -1235,6 +1661,13 @@ + + @Override + public void onDisconnect(IChatBaseComponent ichatbasecomponent) { ++ // CraftBukkit start - Rarely it would send a disconnect line twice ++ if (this.processedDisconnect) { ++ return; ++ } else { ++ this.processedDisconnect = true; ++ } ++ // CraftBukkit end + PlayerConnection.LOGGER.info("{} lost connection: {}", this.player.getName().getString(), ichatbasecomponent.getString()); + this.removePlayerFromWorld(); + super.onDisconnect(ichatbasecomponent); +@@ -1242,10 +1675,18 @@ + + private void removePlayerFromWorld() { + this.chatMessageChain.close(); ++ // CraftBukkit start - Replace vanilla quit message handling with our own. ++ /* + this.server.invalidateStatus(); + this.server.getPlayerList().broadcastSystemMessage(IChatBaseComponent.translatable("multiplayer.player.left", this.player.getDisplayName()).withStyle(EnumChatFormat.YELLOW), false); ++ */ ++ + this.player.disconnect(); +- this.server.getPlayerList().remove(this.player); ++ String quitMessage = this.server.getPlayerList().remove(this.player); ++ if ((quitMessage != null) && (quitMessage.length() > 0)) { ++ this.server.getPlayerList().broadcastMessage(CraftChatMessage.fromString(quitMessage)); ++ } ++ // CraftBukkit end + this.player.getTextFilter().leave(); + } + +@@ -1260,7 +1701,16 @@ + @Override + public void handleSetCarriedItem(PacketPlayInHeldItemSlot packetplayinhelditemslot) { + PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinhelditemslot, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + if (packetplayinhelditemslot.getSlot() >= 0 && packetplayinhelditemslot.getSlot() < PlayerInventory.getSelectionSize()) { ++ PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getCraftPlayer(), this.player.getInventory().selected, packetplayinhelditemslot.getSlot()); ++ this.cserver.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ this.send(new PacketPlayOutHeldItemSlot(this.player.getInventory().selected)); ++ this.player.resetLastActionTime(); ++ return; ++ } ++ // CraftBukkit end + if (this.player.getInventory().selected != packetplayinhelditemslot.getSlot() && this.player.getUsedItemHand() == EnumHand.MAIN_HAND) { + this.player.stopUsingItem(); + } +@@ -1269,18 +1719,25 @@ + this.player.resetLastActionTime(); + } else { + PlayerConnection.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); ++ this.disconnect("Invalid hotbar selection (Hacking?)"); // CraftBukkit + } + } + + @Override + public void handleChat(PacketPlayInChat packetplayinchat) { ++ // CraftBukkit start - async chat ++ // SPIGOT-3638 ++ if (this.server.isStopped()) { ++ return; ++ } ++ // CraftBukkit end + if (isChatMessageIllegal(packetplayinchat.message())) { + this.disconnect(IChatBaseComponent.translatable("multiplayer.disconnect.illegal_characters")); + } else { + Optional optional = this.tryHandleChat(packetplayinchat.lastSeenMessages()); + + if (optional.isPresent()) { +- this.server.submit(() -> { ++ // this.server.submit(() -> { // CraftBukkit - async chat + PlayerChatMessage playerchatmessage; + + try { +@@ -1290,7 +1747,7 @@ + return; + } + +- CompletableFuture completablefuture = this.filterTextPacket(playerchatmessage.signedContent()); ++ CompletableFuture completablefuture = this.filterTextPacket(playerchatmessage.signedContent()).thenApplyAsync(Function.identity(), this.server.chatExecutor); // CraftBukkit - async chat + IChatBaseComponent ichatbasecomponent = this.server.getChatDecorator().decorate(this.player, playerchatmessage.decoratedContent()); + + this.chatMessageChain.append(completablefuture, (filteredtext) -> { +@@ -1298,7 +1755,7 @@ + + this.broadcastChatMessage(playerchatmessage1); + }); +- }); ++ // }); // CraftBukkit - async chat + } + + } +@@ -1313,6 +1770,12 @@ + + if (optional.isPresent()) { + this.server.submit(() -> { ++ // CraftBukkit start - SPIGOT-7346: Prevent disconnected players from executing commands ++ if (player.hasDisconnected()) { ++ return; ++ } ++ // CraftBukkit end ++ + this.performChatCommand(serverboundchatcommandpacket, (LastSeenMessages) optional.get()); + this.detectRateSpam(); + }); +@@ -1322,12 +1785,25 @@ + } + + private void performChatCommand(ServerboundChatCommandPacket serverboundchatcommandpacket, LastSeenMessages lastseenmessages) { +- ParseResults parseresults = this.parseCommand(serverboundchatcommandpacket.command()); ++ // CraftBukkit start ++ String command = "/" + serverboundchatcommandpacket.command(); ++ PlayerConnection.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + command); ++ ++ PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(getCraftPlayer(), command, new LazyPlayerSet(server)); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ command = event.getMessage().substring(1); ++ ++ ParseResults parseresults = this.parseCommand(command); ++ // CraftBukkit end + + Map map; + + try { +- map = this.collectSignedArguments(serverboundchatcommandpacket, SignableCommand.of(parseresults), lastseenmessages); ++ map = (serverboundchatcommandpacket.command().equals(command)) ? this.collectSignedArguments(serverboundchatcommandpacket, SignableCommand.of(parseresults), lastseenmessages) : Collections.emptyMap(); // CraftBukkit + } catch (SignedMessageChain.a signedmessagechain_a) { + this.handleMessageDecodeFailure(signedmessagechain_a); + return; +@@ -1335,10 +1811,10 @@ + + CommandSigningContext.a commandsigningcontext_a = new CommandSigningContext.a(map); + +- parseresults = CommandDispatcher.mapSource(parseresults, (commandlistenerwrapper) -> { ++ parseresults = CommandDispatcher.mapSource(parseresults, (commandlistenerwrapper) -> { // CraftBukkit - decompile error + return commandlistenerwrapper.withSigningContext(commandsigningcontext_a, this.chatMessageChain); + }); +- this.server.getCommands().performCommand(parseresults, serverboundchatcommandpacket.command()); ++ this.server.getCommands().performCommand(parseresults, command); // CraftBukkit + } + + private void handleMessageDecodeFailure(SignedMessageChain.a signedmessagechain_a) { +@@ -1375,7 +1851,7 @@ + private Optional tryHandleChat(LastSeenMessages.b lastseenmessages_b) { + Optional optional = this.unpackAndApplyLastSeen(lastseenmessages_b); + +- if (this.player.getChatVisibility() == EnumChatVisibility.HIDDEN) { ++ if (this.player.isRemoved() || this.player.getChatVisibility() == EnumChatVisibility.HIDDEN) { // CraftBukkit - dead men tell no tales + this.send(new ClientboundSystemChatPacket(IChatBaseComponent.translatable("chat.disabled.options").withStyle(EnumChatFormat.RED), false)); + return Optional.empty(); + } else { +@@ -1409,6 +1885,116 @@ + return false; + } + ++ // CraftBukkit start - add method ++ public void chat(String s, PlayerChatMessage original, boolean async) { ++ if (s.isEmpty() || this.player.getChatVisibility() == EnumChatVisibility.HIDDEN) { ++ return; ++ } ++ OutgoingChatMessage outgoing = OutgoingChatMessage.create(original); ++ ++ if (!async && s.startsWith("/")) { ++ this.handleCommand(s); ++ } else if (this.player.getChatVisibility() == EnumChatVisibility.SYSTEM) { ++ // Do nothing, this is coming from a plugin ++ } else { ++ Player player = this.getCraftPlayer(); ++ AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(server)); ++ String originalFormat = event.getFormat(), originalMessage = event.getMessage(); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (PlayerChatEvent.getHandlerList().getRegisteredListeners().length != 0) { ++ // Evil plugins still listening to deprecated event ++ final PlayerChatEvent queueEvent = new PlayerChatEvent(player, event.getMessage(), event.getFormat(), event.getRecipients()); ++ queueEvent.setCancelled(event.isCancelled()); ++ Waitable waitable = new Waitable() { ++ @Override ++ protected Object evaluate() { ++ org.bukkit.Bukkit.getPluginManager().callEvent(queueEvent); ++ ++ if (queueEvent.isCancelled()) { ++ return null; ++ } ++ ++ String message = String.format(queueEvent.getFormat(), queueEvent.getPlayer().getDisplayName(), queueEvent.getMessage()); ++ if (((LazyPlayerSet) queueEvent.getRecipients()).isLazy()) { ++ if (originalFormat.equals(queueEvent.getFormat()) && originalMessage.equals(queueEvent.getMessage()) && queueEvent.getPlayer().getName().equalsIgnoreCase(queueEvent.getPlayer().getDisplayName())) { ++ PlayerConnection.this.server.getPlayerList().broadcastChatMessage(original, PlayerConnection.this.player, ChatMessageType.bind(ChatMessageType.CHAT, (Entity) PlayerConnection.this.player)); ++ return null; ++ } ++ ++ for (EntityPlayer recipient : server.getPlayerList().players) { ++ recipient.getBukkitEntity().sendMessage(PlayerConnection.this.player.getUUID(), message); ++ } ++ } else { ++ for (Player player : queueEvent.getRecipients()) { ++ player.sendMessage(PlayerConnection.this.player.getUUID(), message); ++ } ++ } ++ PlayerConnection.this.server.console.sendMessage(message); ++ ++ return null; ++ }}; ++ if (async) { ++ server.processQueue.add(waitable); ++ } else { ++ waitable.run(); ++ } ++ try { ++ waitable.get(); ++ } catch (InterruptedException e) { ++ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on! ++ } catch (ExecutionException e) { ++ throw new RuntimeException("Exception processing chat event", e.getCause()); ++ } ++ } else { ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ s = String.format(event.getFormat(), event.getPlayer().getDisplayName(), event.getMessage()); ++ if (((LazyPlayerSet) event.getRecipients()).isLazy()) { ++ if (originalFormat.equals(event.getFormat()) && originalMessage.equals(event.getMessage()) && event.getPlayer().getName().equalsIgnoreCase(event.getPlayer().getDisplayName())) { ++ PlayerConnection.this.server.getPlayerList().broadcastChatMessage(original, PlayerConnection.this.player, ChatMessageType.bind(ChatMessageType.CHAT, (Entity) PlayerConnection.this.player)); ++ return; ++ } ++ ++ for (EntityPlayer recipient : server.getPlayerList().players) { ++ recipient.getBukkitEntity().sendMessage(PlayerConnection.this.player.getUUID(), s); ++ } ++ } else { ++ for (Player recipient : event.getRecipients()) { ++ recipient.sendMessage(PlayerConnection.this.player.getUUID(), s); ++ } ++ } ++ server.console.sendMessage(s); ++ } ++ } ++ } ++ ++ private void handleCommand(String s) { ++ this.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + s); ++ ++ CraftPlayer player = this.getCraftPlayer(); ++ ++ PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(player, s, new LazyPlayerSet(server)); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ try { ++ if (this.cserver.dispatchCommand(event.getPlayer(), event.getMessage().substring(1))) { ++ return; ++ } ++ } catch (org.bukkit.command.CommandException ex) { ++ player.sendMessage(org.bukkit.ChatColor.RED + "An internal error occurred while attempting to perform this command"); ++ java.util.logging.Logger.getLogger(PlayerConnection.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); ++ return; ++ } ++ } ++ // CraftBukkit end ++ + private PlayerChatMessage getSignedMessage(PacketPlayInChat packetplayinchat, LastSeenMessages lastseenmessages) throws SignedMessageChain.a { + SignedMessageBody signedmessagebody = new SignedMessageBody(packetplayinchat.message(), packetplayinchat.timeStamp(), packetplayinchat.salt(), lastseenmessages); + +@@ -1416,13 +2002,33 @@ + } + + private void broadcastChatMessage(PlayerChatMessage playerchatmessage) { +- this.server.getPlayerList().broadcastChatMessage(playerchatmessage, this.player, ChatMessageType.bind(ChatMessageType.CHAT, (Entity) this.player)); ++ // CraftBukkit start ++ String s = playerchatmessage.signedContent(); ++ if (s.isEmpty()) { ++ LOGGER.warn(this.player.getScoreboardName() + " tried to send an empty message"); ++ } else if (getCraftPlayer().isConversing()) { ++ final String conversationInput = s; ++ this.server.processQueue.add(new Runnable() { ++ @Override ++ public void run() { ++ getCraftPlayer().acceptConversationInput(conversationInput); ++ } ++ }); ++ } else if (this.player.getChatVisibility() == EnumChatVisibility.SYSTEM) { // Re-add "Command Only" flag check ++ this.send(new ClientboundSystemChatPacket(IChatBaseComponent.translatable("chat.cannotSend").withStyle(EnumChatFormat.RED), false)); ++ } else { ++ this.chat(s, playerchatmessage, true); ++ } ++ // this.server.getPlayerList().broadcastChatMessage(playerchatmessage, this.player, ChatMessageType.bind(ChatMessageType.CHAT, (Entity) this.player)); ++ // CraftBukkit end + this.detectRateSpam(); + } + + private void detectRateSpam() { +- this.chatSpamTickCount += 20; +- if (this.chatSpamTickCount > 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { ++ // CraftBukkit start - replaced with thread safe throttle ++ // this.chatSpamTickCount += 20; ++ if (this.chatSpamTickCount.addAndGet(20) > 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { ++ // CraftBukkit end + this.disconnect(IChatBaseComponent.translatable("disconnect.spam")); + } + +@@ -1444,13 +2050,62 @@ + @Override + public void handleAnimate(PacketPlayInArmAnimation packetplayinarmanimation) { + PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinarmanimation, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.resetLastActionTime(); ++ // CraftBukkit start - Raytrace to look for 'rogue armswings' ++ float f1 = this.player.getXRot(); ++ float f2 = this.player.getYRot(); ++ double d0 = this.player.getX(); ++ double d1 = this.player.getY() + (double) this.player.getEyeHeight(); ++ double d2 = this.player.getZ(); ++ Location origin = new Location(this.player.level().getWorld(), d0, d1, d2, f2, f1); ++ ++ double d3 = player.gameMode.getGameModeForPlayer() == EnumGamemode.CREATIVE ? 5.0D : 4.5D; ++ // SPIGOT-5607: Only call interact event if no block or entity is being clicked. Use bukkit ray trace method, because it handles blocks and entities at the same time ++ // SPIGOT-7429: Make sure to call PlayerInteractEvent for spectators and non-pickable entities ++ org.bukkit.util.RayTraceResult result = this.player.level().getWorld().rayTrace(origin, origin.getDirection(), d3, org.bukkit.FluidCollisionMode.NEVER, false, 0.1, entity -> { ++ Entity handle = ((CraftEntity) entity).getHandle(); ++ return entity != this.player.getBukkitEntity() && this.player.getBukkitEntity().canSee(entity) && !handle.isSpectator() && handle.isPickable() && !handle.isPassengerOfSameVehicle(player); ++ }); ++ if (result == null) { ++ CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_AIR, this.player.getInventory().getSelected(), EnumHand.MAIN_HAND); ++ } ++ ++ // Arm swing animation ++ PlayerAnimationEvent event = new PlayerAnimationEvent(this.getCraftPlayer(), (packetplayinarmanimation.getHand() == EnumHand.MAIN_HAND) ? PlayerAnimationType.ARM_SWING : PlayerAnimationType.OFF_ARM_SWING); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) return; ++ // CraftBukkit end + this.player.swing(packetplayinarmanimation.getHand()); + } + + @Override + public void handlePlayerCommand(PacketPlayInEntityAction packetplayinentityaction) { + PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinentityaction, this, this.player.serverLevel()); ++ // CraftBukkit start ++ if (this.player.isRemoved()) return; ++ switch (packetplayinentityaction.getAction()) { ++ case PRESS_SHIFT_KEY: ++ case RELEASE_SHIFT_KEY: ++ PlayerToggleSneakEvent event = new PlayerToggleSneakEvent(this.getCraftPlayer(), packetplayinentityaction.getAction() == PacketPlayInEntityAction.EnumPlayerAction.PRESS_SHIFT_KEY); ++ this.cserver.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ break; ++ case START_SPRINTING: ++ case STOP_SPRINTING: ++ PlayerToggleSprintEvent e2 = new PlayerToggleSprintEvent(this.getCraftPlayer(), packetplayinentityaction.getAction() == PacketPlayInEntityAction.EnumPlayerAction.START_SPRINTING); ++ this.cserver.getPluginManager().callEvent(e2); ++ ++ if (e2.isCancelled()) { ++ return; ++ } ++ break; ++ } ++ // CraftBukkit end + this.player.resetLastActionTime(); + Entity entity; + IJumpable ijumpable; +@@ -1532,6 +2187,12 @@ + } + + public void sendPlayerChatMessage(PlayerChatMessage playerchatmessage, ChatMessageType.a chatmessagetype_a) { ++ // CraftBukkit start - SPIGOT-7262: if hidden we have to send as disguised message. Query whether we should send at all (but changing this may not be expected). ++ if (!getCraftPlayer().canSee(playerchatmessage.link().sender())) { ++ sendDisguisedChatMessage(playerchatmessage.decoratedContent(), chatmessagetype_a); ++ return; ++ } ++ // CraftBukkit end + this.send(new ClientboundPlayerChatPacket(playerchatmessage.link().sender(), playerchatmessage.link().index(), playerchatmessage.signature(), playerchatmessage.signedBody().pack(this.messageSignatureCache), playerchatmessage.unsignedContent(), playerchatmessage.filterMask(), chatmessagetype_a.toNetwork(this.player.level().registryAccess()))); + this.addPendingMessage(playerchatmessage); + } +@@ -1558,6 +2219,7 @@ + @Override + public void handleInteract(PacketPlayInUseEntity packetplayinuseentity) { + PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinuseentity, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + final WorldServer worldserver = this.player.serverLevel(); + final Entity entity = packetplayinuseentity.getTarget(worldserver); + +@@ -1572,13 +2234,51 @@ + + if (axisalignedbb.distanceToSqr(this.player.getEyePosition()) < PlayerConnection.MAX_INTERACTION_DISTANCE) { + packetplayinuseentity.dispatch(new PacketPlayInUseEntity.c() { +- private void performInteraction(EnumHand enumhand, PlayerConnection.a playerconnection_a) { ++ private void performInteraction(EnumHand enumhand, PlayerConnection.a playerconnection_a, PlayerInteractEntityEvent event) { // CraftBukkit + ItemStack itemstack = PlayerConnection.this.player.getItemInHand(enumhand); + + if (itemstack.isItemEnabled(worldserver.enabledFeatures())) { + ItemStack itemstack1 = itemstack.copy(); ++ // CraftBukkit start ++ ItemStack itemInHand = PlayerConnection.this.player.getItemInHand(enumhand); ++ boolean triggerLeashUpdate = itemInHand != null && itemInHand.getItem() == Items.LEAD && entity instanceof EntityInsentient; ++ Item origItem = player.getInventory().getSelected() == null ? null : player.getInventory().getSelected().getItem(); ++ ++ cserver.getPluginManager().callEvent(event); ++ ++ // Entity in bucket - SPIGOT-4048 and SPIGOT-6859a ++ if ((entity instanceof Bucketable && entity instanceof EntityLiving && origItem != null && origItem.asItem() == Items.WATER_BUCKET) && (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem)) { ++ send(new PacketPlayOutSpawnEntity(entity)); ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ ++ if (triggerLeashUpdate && (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem)) { ++ // Refresh the current leash state ++ send(new PacketPlayOutAttachEntity(entity, ((EntityInsentient) entity).getLeashHolder())); ++ } ++ ++ if (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem) { ++ // Refresh the current entity metadata ++ entity.getEntityData().refresh(player); ++ // SPIGOT-7136 - Allays ++ if (entity instanceof Allay) { ++ send(new PacketPlayOutEntityEquipment(entity.getId(), Arrays.stream(EnumItemSlot.values()).map((slot) -> Pair.of(slot, ((EntityLiving) entity).getItemBySlot(slot).copy())).collect(Collectors.toList()))); ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ } ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + EnumInteractionResult enuminteractionresult = playerconnection_a.run(PlayerConnection.this.player, entity, enumhand); + ++ // CraftBukkit start ++ if (!itemInHand.isEmpty() && itemInHand.getCount() <= -1) { ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ // CraftBukkit end ++ + if (enuminteractionresult.consumesAction()) { + CriterionTriggers.PLAYER_INTERACTED_WITH_ENTITY.trigger(PlayerConnection.this.player, itemstack1, entity); + if (enuminteractionresult.shouldSwing()) { +@@ -1591,23 +2291,29 @@ + + @Override + public void onInteraction(EnumHand enumhand) { +- this.performInteraction(enumhand, EntityHuman::interactOn); ++ this.performInteraction(enumhand, EntityHuman::interactOn, new PlayerInteractEntityEvent(getCraftPlayer(), entity.getBukkitEntity(), (enumhand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); // CraftBukkit + } + + @Override + public void onInteraction(EnumHand enumhand, Vec3D vec3d) { + this.performInteraction(enumhand, (entityplayer, entity1, enumhand1) -> { + return entity1.interactAt(entityplayer, vec3d, enumhand1); +- }); ++ }, new PlayerInteractAtEntityEvent(getCraftPlayer(), entity.getBukkitEntity(), new org.bukkit.util.Vector(vec3d.x, vec3d.y, vec3d.z), (enumhand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); // CraftBukkit + } + + @Override + public void onAttack() { +- if (!(entity instanceof EntityItem) && !(entity instanceof EntityExperienceOrb) && !(entity instanceof EntityArrow) && entity != PlayerConnection.this.player) { ++ // CraftBukkit ++ if (!(entity instanceof EntityItem) && !(entity instanceof EntityExperienceOrb) && !(entity instanceof EntityArrow) && (entity != PlayerConnection.this.player || player.isSpectator())) { + ItemStack itemstack = PlayerConnection.this.player.getItemInHand(EnumHand.MAIN_HAND); + + if (itemstack.isItemEnabled(worldserver.enabledFeatures())) { + PlayerConnection.this.player.attack(entity); ++ // CraftBukkit start ++ if (!itemstack.isEmpty() && itemstack.getCount() <= -1) { ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ // CraftBukkit end + } + } else { + PlayerConnection.this.disconnect(IChatBaseComponent.translatable("multiplayer.disconnect.invalid_entity_attacked")); +@@ -1630,14 +2336,14 @@ + case PERFORM_RESPAWN: + if (this.player.wonGame) { + this.player.wonGame = false; +- this.player = this.server.getPlayerList().respawn(this.player, true); ++ this.player = this.server.getPlayerList().respawn(this.player, true, RespawnReason.END_PORTAL); + CriterionTriggers.CHANGED_DIMENSION.trigger(this.player, World.END, World.OVERWORLD); + } else { + if (this.player.getHealth() > 0.0F) { + return; + } + +- this.player = this.server.getPlayerList().respawn(this.player, false); ++ this.player = this.server.getPlayerList().respawn(this.player, false, RespawnReason.DEATH); + if (this.server.isHardcore()) { + this.player.setGameMode(EnumGamemode.SPECTATOR); + ((GameRules.GameRuleBoolean) this.player.level().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS)).set(false, this.server); +@@ -1653,15 +2359,21 @@ + @Override + public void handleContainerClose(PacketPlayInCloseWindow packetplayinclosewindow) { + PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinclosewindow, this, this.player.serverLevel()); ++ ++ if (this.player.isImmobile()) return; // CraftBukkit ++ CraftEventFactory.handleInventoryCloseEvent(this.player); // CraftBukkit ++ + this.player.doCloseContainer(); + } + + @Override + public void handleContainerClick(PacketPlayInWindowClick packetplayinwindowclick) { + PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinwindowclick, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.resetLastActionTime(); +- if (this.player.containerMenu.containerId == packetplayinwindowclick.getContainerId()) { +- if (this.player.isSpectator()) { ++ if (this.player.containerMenu.containerId == packetplayinwindowclick.getContainerId() && this.player.containerMenu.stillValid(this.player)) { // CraftBukkit ++ boolean cancelled = this.player.isSpectator(); // CraftBukkit - see below if ++ if (false/*this.player.isSpectator()*/) { // CraftBukkit + this.player.containerMenu.sendAllDataToRemote(); + } else if (!this.player.containerMenu.stillValid(this.player)) { + PlayerConnection.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu); +@@ -1674,7 +2386,284 @@ + boolean flag = packetplayinwindowclick.getStateId() != this.player.containerMenu.getStateId(); + + this.player.containerMenu.suppressRemoteUpdates(); +- this.player.containerMenu.clicked(i, packetplayinwindowclick.getButtonNum(), packetplayinwindowclick.getClickType(), this.player); ++ // CraftBukkit start - Call InventoryClickEvent ++ if (packetplayinwindowclick.getSlotNum() < -1 && packetplayinwindowclick.getSlotNum() != -999) { ++ return; ++ } ++ ++ InventoryView inventory = this.player.containerMenu.getBukkitView(); ++ SlotType type = inventory.getSlotType(packetplayinwindowclick.getSlotNum()); ++ ++ InventoryClickEvent event; ++ ClickType click = ClickType.UNKNOWN; ++ InventoryAction action = InventoryAction.UNKNOWN; ++ ++ ItemStack itemstack = ItemStack.EMPTY; ++ ++ switch (packetplayinwindowclick.getClickType()) { ++ case PICKUP: ++ if (packetplayinwindowclick.getButtonNum() == 0) { ++ click = ClickType.LEFT; ++ } else if (packetplayinwindowclick.getButtonNum() == 1) { ++ click = ClickType.RIGHT; ++ } ++ if (packetplayinwindowclick.getButtonNum() == 0 || packetplayinwindowclick.getButtonNum() == 1) { ++ action = InventoryAction.NOTHING; // Don't want to repeat ourselves ++ if (packetplayinwindowclick.getSlotNum() == -999) { ++ if (!player.containerMenu.getCarried().isEmpty()) { ++ action = packetplayinwindowclick.getButtonNum() == 0 ? InventoryAction.DROP_ALL_CURSOR : InventoryAction.DROP_ONE_CURSOR; ++ } ++ } else if (packetplayinwindowclick.getSlotNum() < 0) { ++ action = InventoryAction.NOTHING; ++ } else { ++ Slot slot = this.player.containerMenu.getSlot(packetplayinwindowclick.getSlotNum()); ++ if (slot != null) { ++ ItemStack clickedItem = slot.getItem(); ++ ItemStack cursor = player.containerMenu.getCarried(); ++ if (clickedItem.isEmpty()) { ++ if (!cursor.isEmpty()) { ++ action = packetplayinwindowclick.getButtonNum() == 0 ? InventoryAction.PLACE_ALL : InventoryAction.PLACE_ONE; ++ } ++ } else if (slot.mayPickup(player)) { ++ if (cursor.isEmpty()) { ++ action = packetplayinwindowclick.getButtonNum() == 0 ? InventoryAction.PICKUP_ALL : InventoryAction.PICKUP_HALF; ++ } else if (slot.mayPlace(cursor)) { ++ if (ItemStack.isSameItemSameTags(clickedItem, cursor)) { ++ int toPlace = packetplayinwindowclick.getButtonNum() == 0 ? cursor.getCount() : 1; ++ toPlace = Math.min(toPlace, clickedItem.getMaxStackSize() - clickedItem.getCount()); ++ toPlace = Math.min(toPlace, slot.container.getMaxStackSize() - clickedItem.getCount()); ++ if (toPlace == 1) { ++ action = InventoryAction.PLACE_ONE; ++ } else if (toPlace == cursor.getCount()) { ++ action = InventoryAction.PLACE_ALL; ++ } else if (toPlace < 0) { ++ action = toPlace != -1 ? InventoryAction.PICKUP_SOME : InventoryAction.PICKUP_ONE; // this happens with oversized stacks ++ } else if (toPlace != 0) { ++ action = InventoryAction.PLACE_SOME; ++ } ++ } else if (cursor.getCount() <= slot.getMaxStackSize()) { ++ action = InventoryAction.SWAP_WITH_CURSOR; ++ } ++ } else if (ItemStack.isSameItemSameTags(cursor, clickedItem)) { ++ if (clickedItem.getCount() >= 0) { ++ if (clickedItem.getCount() + cursor.getCount() <= cursor.getMaxStackSize()) { ++ // As of 1.5, this is result slots only ++ action = InventoryAction.PICKUP_ALL; ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ break; ++ // TODO check on updates ++ case QUICK_MOVE: ++ if (packetplayinwindowclick.getButtonNum() == 0) { ++ click = ClickType.SHIFT_LEFT; ++ } else if (packetplayinwindowclick.getButtonNum() == 1) { ++ click = ClickType.SHIFT_RIGHT; ++ } ++ if (packetplayinwindowclick.getButtonNum() == 0 || packetplayinwindowclick.getButtonNum() == 1) { ++ if (packetplayinwindowclick.getSlotNum() < 0) { ++ action = InventoryAction.NOTHING; ++ } else { ++ Slot slot = this.player.containerMenu.getSlot(packetplayinwindowclick.getSlotNum()); ++ if (slot != null && slot.mayPickup(this.player) && slot.hasItem()) { ++ action = InventoryAction.MOVE_TO_OTHER_INVENTORY; ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } ++ } ++ break; ++ case SWAP: ++ if ((packetplayinwindowclick.getButtonNum() >= 0 && packetplayinwindowclick.getButtonNum() < 9) || packetplayinwindowclick.getButtonNum() == 40) { ++ click = (packetplayinwindowclick.getButtonNum() == 40) ? ClickType.SWAP_OFFHAND : ClickType.NUMBER_KEY; ++ Slot clickedSlot = this.player.containerMenu.getSlot(packetplayinwindowclick.getSlotNum()); ++ if (clickedSlot.mayPickup(player)) { ++ ItemStack hotbar = this.player.getInventory().getItem(packetplayinwindowclick.getButtonNum()); ++ boolean canCleanSwap = hotbar.isEmpty() || (clickedSlot.container == player.getInventory() && clickedSlot.mayPlace(hotbar)); // the slot will accept the hotbar item ++ if (clickedSlot.hasItem()) { ++ if (canCleanSwap) { ++ action = InventoryAction.HOTBAR_SWAP; ++ } else { ++ action = InventoryAction.HOTBAR_MOVE_AND_READD; ++ } ++ } else if (!clickedSlot.hasItem() && !hotbar.isEmpty() && clickedSlot.mayPlace(hotbar)) { ++ action = InventoryAction.HOTBAR_SWAP; ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } ++ break; ++ case CLONE: ++ if (packetplayinwindowclick.getButtonNum() == 2) { ++ click = ClickType.MIDDLE; ++ if (packetplayinwindowclick.getSlotNum() < 0) { ++ action = InventoryAction.NOTHING; ++ } else { ++ Slot slot = this.player.containerMenu.getSlot(packetplayinwindowclick.getSlotNum()); ++ if (slot != null && slot.hasItem() && player.getAbilities().instabuild && player.containerMenu.getCarried().isEmpty()) { ++ action = InventoryAction.CLONE_STACK; ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } ++ } else { ++ click = ClickType.UNKNOWN; ++ action = InventoryAction.UNKNOWN; ++ } ++ break; ++ case THROW: ++ if (packetplayinwindowclick.getSlotNum() >= 0) { ++ if (packetplayinwindowclick.getButtonNum() == 0) { ++ click = ClickType.DROP; ++ Slot slot = this.player.containerMenu.getSlot(packetplayinwindowclick.getSlotNum()); ++ if (slot != null && slot.hasItem() && slot.mayPickup(player) && !slot.getItem().isEmpty() && slot.getItem().getItem() != Item.byBlock(Blocks.AIR)) { ++ action = InventoryAction.DROP_ONE_SLOT; ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } else if (packetplayinwindowclick.getButtonNum() == 1) { ++ click = ClickType.CONTROL_DROP; ++ Slot slot = this.player.containerMenu.getSlot(packetplayinwindowclick.getSlotNum()); ++ if (slot != null && slot.hasItem() && slot.mayPickup(player) && !slot.getItem().isEmpty() && slot.getItem().getItem() != Item.byBlock(Blocks.AIR)) { ++ action = InventoryAction.DROP_ALL_SLOT; ++ } else { ++ action = InventoryAction.NOTHING; ++ } ++ } ++ } else { ++ // Sane default (because this happens when they are holding nothing. Don't ask why.) ++ click = ClickType.LEFT; ++ if (packetplayinwindowclick.getButtonNum() == 1) { ++ click = ClickType.RIGHT; ++ } ++ action = InventoryAction.NOTHING; ++ } ++ break; ++ case QUICK_CRAFT: ++ this.player.containerMenu.clicked(packetplayinwindowclick.getSlotNum(), packetplayinwindowclick.getButtonNum(), packetplayinwindowclick.getClickType(), this.player); ++ break; ++ case PICKUP_ALL: ++ click = ClickType.DOUBLE_CLICK; ++ action = InventoryAction.NOTHING; ++ if (packetplayinwindowclick.getSlotNum() >= 0 && !this.player.containerMenu.getCarried().isEmpty()) { ++ ItemStack cursor = this.player.containerMenu.getCarried(); ++ action = InventoryAction.NOTHING; ++ // Quick check for if we have any of the item ++ if (inventory.getTopInventory().contains(CraftMagicNumbers.getMaterial(cursor.getItem())) || inventory.getBottomInventory().contains(CraftMagicNumbers.getMaterial(cursor.getItem()))) { ++ action = InventoryAction.COLLECT_TO_CURSOR; ++ } ++ } ++ break; ++ default: ++ break; ++ } ++ ++ if (packetplayinwindowclick.getClickType() != InventoryClickType.QUICK_CRAFT) { ++ if (click == ClickType.NUMBER_KEY) { ++ event = new InventoryClickEvent(inventory, type, packetplayinwindowclick.getSlotNum(), click, action, packetplayinwindowclick.getButtonNum()); ++ } else { ++ event = new InventoryClickEvent(inventory, type, packetplayinwindowclick.getSlotNum(), click, action); ++ } ++ ++ org.bukkit.inventory.Inventory top = inventory.getTopInventory(); ++ if (packetplayinwindowclick.getSlotNum() == 0 && top instanceof CraftingInventory) { ++ org.bukkit.inventory.Recipe recipe = ((CraftingInventory) top).getRecipe(); ++ if (recipe != null) { ++ if (click == ClickType.NUMBER_KEY) { ++ event = new CraftItemEvent(recipe, inventory, type, packetplayinwindowclick.getSlotNum(), click, action, packetplayinwindowclick.getButtonNum()); ++ } else { ++ event = new CraftItemEvent(recipe, inventory, type, packetplayinwindowclick.getSlotNum(), click, action); ++ } ++ } ++ } ++ ++ if (packetplayinwindowclick.getSlotNum() == 3 && top instanceof SmithingInventory) { ++ org.bukkit.inventory.ItemStack result = ((SmithingInventory) top).getResult(); ++ if (result != null) { ++ if (click == ClickType.NUMBER_KEY) { ++ event = new SmithItemEvent(inventory, type, packetplayinwindowclick.getSlotNum(), click, action, packetplayinwindowclick.getButtonNum()); ++ } else { ++ event = new SmithItemEvent(inventory, type, packetplayinwindowclick.getSlotNum(), click, action); ++ } ++ } ++ } ++ ++ event.setCancelled(cancelled); ++ Container oldContainer = this.player.containerMenu; // SPIGOT-1224 ++ cserver.getPluginManager().callEvent(event); ++ if (this.player.containerMenu != oldContainer) { ++ return; ++ } ++ ++ switch (event.getResult()) { ++ case ALLOW: ++ case DEFAULT: ++ this.player.containerMenu.clicked(i, packetplayinwindowclick.getButtonNum(), packetplayinwindowclick.getClickType(), this.player); ++ break; ++ case DENY: ++ /* Needs enum constructor in InventoryAction ++ if (action.modifiesOtherSlots()) { ++ ++ } else { ++ if (action.modifiesCursor()) { ++ this.player.playerConnection.sendPacket(new Packet103SetSlot(-1, -1, this.player.inventory.getCarried())); ++ } ++ if (action.modifiesClicked()) { ++ this.player.playerConnection.sendPacket(new Packet103SetSlot(this.player.activeContainer.windowId, packet102windowclick.slot, this.player.activeContainer.getSlot(packet102windowclick.slot).getItem())); ++ } ++ }*/ ++ switch (action) { ++ // Modified other slots ++ case PICKUP_ALL: ++ case MOVE_TO_OTHER_INVENTORY: ++ case HOTBAR_MOVE_AND_READD: ++ case HOTBAR_SWAP: ++ case COLLECT_TO_CURSOR: ++ case UNKNOWN: ++ this.player.containerMenu.sendAllDataToRemote(); ++ break; ++ // Modified cursor and clicked ++ case PICKUP_SOME: ++ case PICKUP_HALF: ++ case PICKUP_ONE: ++ case PLACE_ALL: ++ case PLACE_SOME: ++ case PLACE_ONE: ++ case SWAP_WITH_CURSOR: ++ this.player.connection.send(new PacketPlayOutSetSlot(-1, -1, this.player.inventoryMenu.incrementStateId(), this.player.containerMenu.getCarried())); ++ this.player.connection.send(new PacketPlayOutSetSlot(this.player.containerMenu.containerId, this.player.inventoryMenu.incrementStateId(), packetplayinwindowclick.getSlotNum(), this.player.containerMenu.getSlot(packetplayinwindowclick.getSlotNum()).getItem())); ++ break; ++ // Modified clicked only ++ case DROP_ALL_SLOT: ++ case DROP_ONE_SLOT: ++ this.player.connection.send(new PacketPlayOutSetSlot(this.player.containerMenu.containerId, this.player.inventoryMenu.incrementStateId(), packetplayinwindowclick.getSlotNum(), this.player.containerMenu.getSlot(packetplayinwindowclick.getSlotNum()).getItem())); ++ break; ++ // Modified cursor only ++ case DROP_ALL_CURSOR: ++ case DROP_ONE_CURSOR: ++ case CLONE_STACK: ++ this.player.connection.send(new PacketPlayOutSetSlot(-1, -1, this.player.inventoryMenu.incrementStateId(), this.player.containerMenu.getCarried())); ++ break; ++ // Nothing ++ case NOTHING: ++ break; ++ } ++ } ++ ++ if (event instanceof CraftItemEvent || event instanceof SmithItemEvent) { ++ // Need to update the inventory on crafting to ++ // correctly support custom recipes ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ } ++ // CraftBukkit end + ObjectIterator objectiterator = Int2ObjectMaps.fastIterable(packetplayinwindowclick.getChangedSlots()).iterator(); + + while (objectiterator.hasNext()) { +@@ -1704,9 +2693,18 @@ + if (!this.player.containerMenu.stillValid(this.player)) { + PlayerConnection.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu); + } else { +- this.server.getRecipeManager().byKey(packetplayinautorecipe.getRecipe()).ifPresent((recipeholder) -> { +- ((ContainerRecipeBook) this.player.containerMenu).handlePlacement(packetplayinautorecipe.isShiftDown(), recipeholder, this.player); ++ // CraftBukkit start - implement PlayerRecipeBookClickEvent ++ org.bukkit.inventory.Recipe recipe = this.cserver.getRecipe(CraftNamespacedKey.fromMinecraft(packetplayinautorecipe.getRecipe())); ++ if (recipe == null) { ++ return; ++ } ++ org.bukkit.event.player.PlayerRecipeBookClickEvent event = CraftEventFactory.callRecipeBookClickEvent(this.player, recipe, packetplayinautorecipe.isShiftDown()); ++ ++ // Cast to keyed should be safe as the recipe will never be a MerchantRecipe. ++ this.server.getRecipeManager().byKey(CraftNamespacedKey.toMinecraft(((org.bukkit.Keyed) event.getRecipe()).getKey())).ifPresent((recipeholder) -> { ++ ((ContainerRecipeBook) this.player.containerMenu).handlePlacement(event.isShiftClick(), recipeholder, this.player); + }); ++ // CraftBukkit end + } + } + } +@@ -1714,6 +2712,7 @@ + @Override + public void handleContainerButtonClick(PacketPlayInEnchantItem packetplayinenchantitem) { + PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinenchantitem, this, this.player.serverLevel()); ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.resetLastActionTime(); + if (this.player.containerMenu.containerId == packetplayinenchantitem.getContainerId() && !this.player.isSpectator()) { + if (!this.player.containerMenu.stillValid(this.player)) { +@@ -1756,6 +2755,43 @@ + + boolean flag1 = packetplayinsetcreativeslot.getSlotNum() >= 1 && packetplayinsetcreativeslot.getSlotNum() <= 45; + boolean flag2 = itemstack.isEmpty() || itemstack.getDamageValue() >= 0 && itemstack.getCount() <= 64 && !itemstack.isEmpty(); ++ if (flag || (flag1 && !ItemStack.matches(this.player.inventoryMenu.getSlot(packetplayinsetcreativeslot.getSlotNum()).getItem(), packetplayinsetcreativeslot.getItem()))) { // Insist on valid slot ++ // CraftBukkit start - Call click event ++ InventoryView inventory = this.player.inventoryMenu.getBukkitView(); ++ org.bukkit.inventory.ItemStack item = CraftItemStack.asBukkitCopy(packetplayinsetcreativeslot.getItem()); ++ ++ SlotType type = SlotType.QUICKBAR; ++ if (flag) { ++ type = SlotType.OUTSIDE; ++ } else if (packetplayinsetcreativeslot.getSlotNum() < 36) { ++ if (packetplayinsetcreativeslot.getSlotNum() >= 5 && packetplayinsetcreativeslot.getSlotNum() < 9) { ++ type = SlotType.ARMOR; ++ } else { ++ type = SlotType.CONTAINER; ++ } ++ } ++ InventoryCreativeEvent event = new InventoryCreativeEvent(inventory, type, flag ? -999 : packetplayinsetcreativeslot.getSlotNum(), item); ++ cserver.getPluginManager().callEvent(event); ++ ++ itemstack = CraftItemStack.asNMSCopy(event.getCursor()); ++ ++ switch (event.getResult()) { ++ case ALLOW: ++ // Plugin cleared the id / stacksize checks ++ flag2 = true; ++ break; ++ case DEFAULT: ++ break; ++ case DENY: ++ // Reset the slot ++ if (packetplayinsetcreativeslot.getSlotNum() >= 0) { ++ this.player.connection.send(new PacketPlayOutSetSlot(this.player.inventoryMenu.containerId, this.player.inventoryMenu.incrementStateId(), packetplayinsetcreativeslot.getSlotNum(), this.player.inventoryMenu.getSlot(packetplayinsetcreativeslot.getSlotNum()).getItem())); ++ this.player.connection.send(new PacketPlayOutSetSlot(-1, this.player.inventoryMenu.incrementStateId(), -1, ItemStack.EMPTY)); ++ } ++ return; ++ } ++ } ++ // CraftBukkit end + + if (flag1 && flag2) { + this.player.inventoryMenu.getSlot(packetplayinsetcreativeslot.getSlotNum()).setByPlayer(itemstack); +@@ -1778,6 +2814,7 @@ + } + + private void updateSignText(PacketPlayInUpdateSign packetplayinupdatesign, List list) { ++ if (this.player.isImmobile()) return; // CraftBukkit + this.player.resetLastActionTime(); + WorldServer worldserver = this.player.serverLevel(); + BlockPosition blockposition = packetplayinupdatesign.getPos(); +@@ -1799,7 +2836,17 @@ + @Override + public void handlePlayerAbilities(PacketPlayInAbilities packetplayinabilities) { + PlayerConnectionUtils.ensureRunningOnSameThread(packetplayinabilities, this, this.player.serverLevel()); +- this.player.getAbilities().flying = packetplayinabilities.isFlying() && this.player.getAbilities().mayfly; ++ // CraftBukkit start ++ if (this.player.getAbilities().mayfly && this.player.getAbilities().flying != packetplayinabilities.isFlying()) { ++ PlayerToggleFlightEvent event = new PlayerToggleFlightEvent(this.player.getBukkitEntity(), packetplayinabilities.isFlying()); ++ this.cserver.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ this.player.getAbilities().flying = packetplayinabilities.isFlying(); // Actually set the player's flying status ++ } else { ++ this.player.onUpdateAbilities(); // Tell the player their ability was reverted ++ } ++ } ++ // CraftBukkit end + } + + @Override +@@ -1858,7 +2905,7 @@ + if (!this.waitingForSwitchToConfig) { + throw new IllegalStateException("Client acknowledged config, but none was requested"); + } else { +- this.connection.setListener(new ServerConfigurationPacketListenerImpl(this.server, this.connection, this.createCookie(this.player.clientInformation()))); ++ this.connection.setListener(new ServerConfigurationPacketListenerImpl(this.server, this.connection, this.createCookie(this.player.clientInformation()), this.player)); // CraftBukkit + } + } + diff --git a/patch-remap/og/net/minecraft/server/network/ServerCommonPacketListenerImpl.patch b/patch-remap/og/net/minecraft/server/network/ServerCommonPacketListenerImpl.patch new file mode 100644 index 0000000000..bf4ec91fe2 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/network/ServerCommonPacketListenerImpl.patch @@ -0,0 +1,215 @@ +--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java +@@ -26,6 +26,21 @@ + import net.minecraft.util.thread.IAsyncTaskHandler; + import org.slf4j.Logger; + ++// CraftBukkit start ++import io.netty.buffer.ByteBuf; ++import java.util.concurrent.ExecutionException; ++import net.minecraft.EnumChatFormat; ++import net.minecraft.network.protocol.game.PacketPlayOutSpawnPosition; ++import net.minecraft.resources.MinecraftKey; ++import net.minecraft.server.level.EntityPlayer; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.craftbukkit.util.Waitable; ++import org.bukkit.event.player.PlayerKickEvent; ++import org.bukkit.event.player.PlayerResourcePackStatusEvent; ++// CraftBukkit end ++ + public abstract class ServerCommonPacketListenerImpl implements ServerCommonPacketListener { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -39,11 +54,22 @@ + private int latency; + private volatile boolean suspendFlushingOnServerThread = false; + +- public ServerCommonPacketListenerImpl(MinecraftServer minecraftserver, NetworkManager networkmanager, CommonListenerCookie commonlistenercookie) { ++ public ServerCommonPacketListenerImpl(MinecraftServer minecraftserver, NetworkManager networkmanager, CommonListenerCookie commonlistenercookie, EntityPlayer player) { // CraftBukkit + this.server = minecraftserver; + this.connection = networkmanager; + this.keepAliveTime = SystemUtils.getMillis(); + this.latency = commonlistenercookie.latency(); ++ // CraftBukkit start - add fields and methods ++ this.player = player; ++ this.cserver = minecraftserver.server; ++ } ++ protected final EntityPlayer player; ++ protected final org.bukkit.craftbukkit.CraftServer cserver; ++ public boolean processedDisconnect; ++ ++ public CraftPlayer getCraftPlayer() { ++ return (this.player == null) ? null : (CraftPlayer) this.player.getBukkitEntity(); ++ // CraftBukkit end + } + + @Override +@@ -57,6 +83,7 @@ + + @Override + public void handleKeepAlive(ServerboundKeepAlivePacket serverboundkeepalivepacket) { ++ PlayerConnectionUtils.ensureRunningOnSameThread(serverboundkeepalivepacket, this, this.player.serverLevel()); // CraftBukkit + if (this.keepAlivePending && serverboundkeepalivepacket.getId() == this.keepAliveChallenge) { + int i = (int) (SystemUtils.getMillis() - this.keepAliveTime); + +@@ -71,8 +98,56 @@ + @Override + public void handlePong(ServerboundPongPacket serverboundpongpacket) {} + ++ // CraftBukkit start ++ private static final MinecraftKey CUSTOM_REGISTER = new MinecraftKey("register"); ++ private static final MinecraftKey CUSTOM_UNREGISTER = new MinecraftKey("unregister"); ++ + @Override +- public void handleCustomPayload(ServerboundCustomPayloadPacket serverboundcustompayloadpacket) {} ++ public void handleCustomPayload(ServerboundCustomPayloadPacket serverboundcustompayloadpacket) { ++ if (!(serverboundcustompayloadpacket.payload() instanceof ServerboundCustomPayloadPacket.UnknownPayload)) { ++ return; ++ } ++ PlayerConnectionUtils.ensureRunningOnSameThread(serverboundcustompayloadpacket, this, this.player.serverLevel()); ++ MinecraftKey identifier = serverboundcustompayloadpacket.payload().id(); ++ ByteBuf payload = ((ServerboundCustomPayloadPacket.UnknownPayload)serverboundcustompayloadpacket.payload()).data(); ++ ++ if (identifier.equals(CUSTOM_REGISTER)) { ++ try { ++ String channels = payload.toString(com.google.common.base.Charsets.UTF_8); ++ for (String channel : channels.split("\0")) { ++ getCraftPlayer().addChannel(channel); ++ } ++ } catch (Exception ex) { ++ PlayerConnection.LOGGER.error("Couldn\'t register custom payload", ex); ++ this.disconnect("Invalid payload REGISTER!"); ++ } ++ } else if (identifier.equals(CUSTOM_UNREGISTER)) { ++ try { ++ String channels = payload.toString(com.google.common.base.Charsets.UTF_8); ++ for (String channel : channels.split("\0")) { ++ getCraftPlayer().removeChannel(channel); ++ } ++ } catch (Exception ex) { ++ PlayerConnection.LOGGER.error("Couldn\'t unregister custom payload", ex); ++ this.disconnect("Invalid payload UNREGISTER!"); ++ } ++ } else { ++ try { ++ byte[] data = new byte[payload.readableBytes()]; ++ payload.readBytes(data); ++ cserver.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), identifier.toString(), data); ++ } catch (Exception ex) { ++ PlayerConnection.LOGGER.error("Couldn\'t dispatch custom payload", ex); ++ this.disconnect("Invalid custom payload!"); ++ } ++ } ++ ++ } ++ ++ public final boolean isDisconnected() { ++ return !this.player.joining && !this.connection.isConnected(); ++ } ++ // CraftBukkit end + + @Override + public void handleResourcePackResponse(ServerboundResourcePackPacket serverboundresourcepackpacket) { +@@ -81,6 +156,7 @@ + ServerCommonPacketListenerImpl.LOGGER.info("Disconnecting {} due to resource pack {} rejection", this.playerProfile().getName(), serverboundresourcepackpacket.id()); + this.disconnect(IChatBaseComponent.translatable("multiplayer.requiredTexturePrompt.disconnect")); + } ++ this.cserver.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getCraftPlayer(), serverboundresourcepackpacket.id(), PlayerResourcePackStatusEvent.Status.values()[serverboundresourcepackpacket.action().ordinal()])); // CraftBukkit + + } + +@@ -88,7 +164,7 @@ + this.server.getProfiler().push("keepAlive"); + long i = SystemUtils.getMillis(); + +- if (i - this.keepAliveTime >= 15000L) { ++ if (i - this.keepAliveTime >= 25000L) { // CraftBukkit + if (this.keepAlivePending) { + this.disconnect(ServerCommonPacketListenerImpl.TIMEOUT_DISCONNECTION_MESSAGE); + } else { +@@ -116,6 +192,14 @@ + } + + public void send(Packet packet, @Nullable PacketSendListener packetsendlistener) { ++ // CraftBukkit start ++ if (packet == null) { ++ return; ++ } else if (packet instanceof PacketPlayOutSpawnPosition) { ++ PacketPlayOutSpawnPosition packet6 = (PacketPlayOutSpawnPosition) packet; ++ this.player.compassTarget = CraftLocation.toBukkit(packet6.pos, this.getCraftPlayer().getWorld()); ++ } ++ // CraftBukkit end + boolean flag = !this.suspendFlushingOnServerThread || !this.server.isSameThread(); + + try { +@@ -131,16 +215,67 @@ + } + } + ++ // CraftBukkit start ++ @Deprecated + public void disconnect(IChatBaseComponent ichatbasecomponent) { ++ disconnect(CraftChatMessage.fromComponent(ichatbasecomponent)); ++ } ++ // CraftBukkit end ++ ++ public void disconnect(String s) { ++ // CraftBukkit start - fire PlayerKickEvent ++ if (this.processedDisconnect) { ++ return; ++ } ++ if (!this.cserver.isPrimaryThread()) { ++ Waitable waitable = new Waitable() { ++ @Override ++ protected Object evaluate() { ++ ServerCommonPacketListenerImpl.this.disconnect(s); ++ return null; ++ } ++ }; ++ ++ this.server.processQueue.add(waitable); ++ ++ try { ++ waitable.get(); ++ } catch (InterruptedException e) { ++ Thread.currentThread().interrupt(); ++ } catch (ExecutionException e) { ++ throw new RuntimeException(e); ++ } ++ return; ++ } ++ ++ String leaveMessage = EnumChatFormat.YELLOW + this.player.getScoreboardName() + " left the game."; ++ ++ PlayerKickEvent event = new PlayerKickEvent(this.player.getBukkitEntity(), s, leaveMessage); ++ ++ if (this.cserver.getServer().isRunning()) { ++ this.cserver.getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ // Do not kick the player ++ return; ++ } ++ this.player.kickLeaveMessage = event.getLeaveMessage(); // CraftBukkit - SPIGOT-3034: Forward leave message to PlayerQuitEvent ++ // Send the possibly modified leave message ++ final IChatBaseComponent ichatbasecomponent = CraftChatMessage.fromString(event.getReason(), true)[0]; ++ // CraftBukkit end ++ + this.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), PacketSendListener.thenRun(() -> { + this.connection.disconnect(ichatbasecomponent); + })); ++ this.onDisconnect(ichatbasecomponent); // CraftBukkit - fire quit instantly + this.connection.setReadOnly(); + MinecraftServer minecraftserver = this.server; + NetworkManager networkmanager = this.connection; + + Objects.requireNonNull(this.connection); +- minecraftserver.executeBlocking(networkmanager::handleDisconnection); ++ // CraftBukkit - Don't wait ++ minecraftserver.wrapRunnable(networkmanager::handleDisconnection); + } + + protected boolean isSingleplayerOwner() { diff --git a/patch-remap/og/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.patch b/patch-remap/og/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.patch new file mode 100644 index 0000000000..f35ab94328 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java +@@ -44,8 +44,8 @@ + private ConfigurationTask currentTask; + private ClientInformation clientInformation; + +- public ServerConfigurationPacketListenerImpl(MinecraftServer minecraftserver, NetworkManager networkmanager, CommonListenerCookie commonlistenercookie) { +- super(minecraftserver, networkmanager, commonlistenercookie); ++ public ServerConfigurationPacketListenerImpl(MinecraftServer minecraftserver, NetworkManager networkmanager, CommonListenerCookie commonlistenercookie, EntityPlayer player) { // CraftBukkit ++ super(minecraftserver, networkmanager, commonlistenercookie, player); // CraftBukkit + this.gameProfile = commonlistenercookie.gameProfile(); + this.clientInformation = commonlistenercookie.clientInformation(); + } +@@ -117,14 +117,14 @@ + return; + } + +- IChatBaseComponent ichatbasecomponent = playerlist.canPlayerLogin(this.connection.getRemoteAddress(), this.gameProfile); ++ IChatBaseComponent ichatbasecomponent = null; // CraftBukkit - login checks already completed + + if (ichatbasecomponent != null) { + this.disconnect(ichatbasecomponent); + return; + } + +- EntityPlayer entityplayer = playerlist.getPlayerForLogin(this.gameProfile, this.clientInformation); ++ EntityPlayer entityplayer = playerlist.getPlayerForLogin(this.gameProfile, this.clientInformation, this.player); // CraftBukkit + + playerlist.placeNewPlayer(this.connection, entityplayer, this.createCookie(this.clientInformation)); + this.connection.resumeInboundAfterProtocolChange(); diff --git a/patch-remap/og/net/minecraft/server/network/ServerConnection.patch b/patch-remap/og/net/minecraft/server/network/ServerConnection.patch new file mode 100644 index 0000000000..1108bf2026 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/network/ServerConnection.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/server/network/ServerConnection.java ++++ b/net/minecraft/server/network/ServerConnection.java +@@ -98,15 +98,25 @@ + + NetworkManager.configureSerialization(channelpipeline, EnumProtocolDirection.SERVERBOUND, (BandwidthDebugMonitor) null); + int j = ServerConnection.this.server.getRateLimitPacketsPerSecond(); +- Object object = j > 0 ? new NetworkManagerServer(j) : new NetworkManager(EnumProtocolDirection.SERVERBOUND); ++ NetworkManager object = j > 0 ? new NetworkManagerServer(j) : new NetworkManager(EnumProtocolDirection.SERVERBOUND); // CraftBukkit - decompile error + + ServerConnection.this.connections.add(object); + ((NetworkManager) object).configurePacketHandler(channelpipeline); + ((NetworkManager) object).setListenerForServerboundHandshake(new HandshakeListener(ServerConnection.this.server, (NetworkManager) object)); + } +- }).group(eventloopgroup).localAddress(inetaddress, i)).bind().syncUninterruptibly()); ++ }).group(eventloopgroup).localAddress(inetaddress, i)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit ++ } ++ } ++ ++ // CraftBukkit start ++ public void acceptConnections() { ++ synchronized (this.channels) { ++ for (ChannelFuture future : this.channels) { ++ future.channel().config().setAutoRead(true); ++ } + } + } ++ // CraftBukkit end + + public SocketAddress startMemoryChannel() { + List list = this.channels; diff --git a/patch-remap/og/net/minecraft/server/players/ExpirableListEntry.patch b/patch-remap/og/net/minecraft/server/players/ExpirableListEntry.patch new file mode 100644 index 0000000000..4291c54428 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/players/ExpirableListEntry.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/server/players/ExpirableListEntry.java ++++ b/net/minecraft/server/players/ExpirableListEntry.java +@@ -27,7 +27,7 @@ + } + + protected ExpirableListEntry(@Nullable T t0, JsonObject jsonobject) { +- super(t0); ++ super(checkExpiry(t0, jsonobject)); // CraftBukkit + + Date date; + +@@ -83,4 +83,22 @@ + jsonobject.addProperty("expires", this.expires == null ? "forever" : ExpirableListEntry.DATE_FORMAT.format(this.expires)); + jsonobject.addProperty("reason", this.reason); + } ++ ++ // CraftBukkit start ++ private static T checkExpiry(T object, JsonObject jsonobject) { ++ Date expires = null; ++ ++ try { ++ expires = jsonobject.has("expires") ? DATE_FORMAT.parse(jsonobject.get("expires").getAsString()) : null; ++ } catch (ParseException ex) { ++ // Guess we don't have a date ++ } ++ ++ if (expires == null || expires.after(new Date())) { ++ return object; ++ } else { ++ return null; ++ } ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/server/players/GameProfileBanEntry.patch b/patch-remap/og/net/minecraft/server/players/GameProfileBanEntry.patch new file mode 100644 index 0000000000..ccd98b70e1 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/players/GameProfileBanEntry.patch @@ -0,0 +1,7 @@ +--- a/net/minecraft/server/players/GameProfileBanEntry.java ++++ b/net/minecraft/server/players/GameProfileBanEntry.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.server.players; + + import com.google.gson.JsonObject; diff --git a/patch-remap/og/net/minecraft/server/players/JsonList.patch b/patch-remap/og/net/minecraft/server/players/JsonList.patch new file mode 100644 index 0000000000..5b359f8e02 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/players/JsonList.patch @@ -0,0 +1,52 @@ +--- a/net/minecraft/server/players/JsonList.java ++++ b/net/minecraft/server/players/JsonList.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.server.players; + + import com.google.common.collect.Lists; +@@ -54,7 +55,7 @@ + @Nullable + public V get(K k0) { + this.removeExpired(); +- return (JsonListEntry) this.map.get(this.getKeyForUser(k0)); ++ return (V) this.map.get(this.getKeyForUser(k0)); // CraftBukkit - fix decompile error + } + + public void remove(K k0) { +@@ -93,7 +94,7 @@ + Iterator iterator = this.map.values().iterator(); + + while (iterator.hasNext()) { +- V v0 = (JsonListEntry) iterator.next(); ++ V v0 = (V) iterator.next(); // CraftBukkit - decompile error + + if (v0.hasExpired()) { + list.add(v0.getUser()); +@@ -103,7 +104,7 @@ + iterator = list.iterator(); + + while (iterator.hasNext()) { +- K k0 = iterator.next(); ++ K k0 = (K) iterator.next(); // CraftBukkit - decompile error + + this.map.remove(this.getKeyForUser(k0)); + } +@@ -118,7 +119,7 @@ + + public void save() throws IOException { + JsonArray jsonarray = new JsonArray(); +- Stream stream = this.map.values().stream().map((jsonlistentry) -> { ++ Stream stream = this.map.values().stream().map((jsonlistentry) -> { // CraftBukkit - decompile error + JsonObject jsonobject = new JsonObject(); + + Objects.requireNonNull(jsonlistentry); +@@ -171,7 +172,7 @@ + JsonListEntry jsonlistentry = this.createEntry(jsonobject); + + if (jsonlistentry.getUser() != null) { +- this.map.put(this.getKeyForUser(jsonlistentry.getUser()), jsonlistentry); ++ this.map.put(this.getKeyForUser(jsonlistentry.getUser()), (V) jsonlistentry); // CraftBukkit - decompile error + } + } + } catch (Throwable throwable) { diff --git a/patch-remap/og/net/minecraft/server/players/NameReferencingFileConverter.patch b/patch-remap/og/net/minecraft/server/players/NameReferencingFileConverter.patch new file mode 100644 index 0000000000..57e1d5a7c4 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/players/NameReferencingFileConverter.patch @@ -0,0 +1,82 @@ +--- a/net/minecraft/server/players/NameReferencingFileConverter.java ++++ b/net/minecraft/server/players/NameReferencingFileConverter.java +@@ -27,6 +27,12 @@ + import net.minecraft.world.level.storage.SavedFile; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.nbt.NBTCompressedStreamTools; ++import net.minecraft.nbt.NBTReadLimiter; ++import net.minecraft.nbt.NBTTagCompound; ++// CraftBukkit end ++ + public class NameReferencingFileConverter { + + static final Logger LOGGER = LogUtils.getLogger(); +@@ -85,7 +91,7 @@ + try { + gameprofilebanlist.load(); + } catch (IOException ioexception) { +- NameReferencingFileConverter.LOGGER.warn("Could not load existing file {}", gameprofilebanlist.getFile().getName(), ioexception); ++ NameReferencingFileConverter.LOGGER.warn("Could not load existing file {}", gameprofilebanlist.getFile().getName()); // CraftBukkit - don't print stacktrace + } + } + +@@ -143,7 +149,7 @@ + try { + ipbanlist.load(); + } catch (IOException ioexception) { +- NameReferencingFileConverter.LOGGER.warn("Could not load existing file {}", ipbanlist.getFile().getName(), ioexception); ++ NameReferencingFileConverter.LOGGER.warn("Could not load existing file {}", ipbanlist.getFile().getName()); // CraftBukkit - don't print stacktrace + } + } + +@@ -184,7 +190,7 @@ + try { + oplist.load(); + } catch (IOException ioexception) { +- NameReferencingFileConverter.LOGGER.warn("Could not load existing file {}", oplist.getFile().getName(), ioexception); ++ NameReferencingFileConverter.LOGGER.warn("Could not load existing file {}", oplist.getFile().getName()); // CraftBukkit - don't print stacktrace + } + } + +@@ -228,7 +234,7 @@ + try { + whitelist.load(); + } catch (IOException ioexception) { +- NameReferencingFileConverter.LOGGER.warn("Could not load existing file {}", whitelist.getFile().getName(), ioexception); ++ NameReferencingFileConverter.LOGGER.warn("Could not load existing file {}", whitelist.getFile().getName()); // CraftBukkit - don't print stacktrace + } + } + +@@ -347,6 +353,30 @@ + File file5 = new File(file, s2 + ".dat"); + File file6 = new File(file4, s3 + ".dat"); + ++ // CraftBukkit start - Use old file name to seed lastKnownName ++ NBTTagCompound root = null; ++ ++ try { ++ root = NBTCompressedStreamTools.readCompressed(new java.io.FileInputStream(file5), NBTReadLimiter.unlimitedHeap()); ++ } catch (Exception exception) { ++ exception.printStackTrace(); ++ } ++ ++ if (root != null) { ++ if (!root.contains("bukkit")) { ++ root.put("bukkit", new NBTTagCompound()); ++ } ++ NBTTagCompound data = root.getCompound("bukkit"); ++ data.putString("lastKnownName", s2); ++ ++ try { ++ NBTCompressedStreamTools.writeCompressed(root, new java.io.FileOutputStream(file2)); ++ } catch (Exception exception) { ++ exception.printStackTrace(); ++ } ++ } ++ // CraftBukkit end ++ + NameReferencingFileConverter.ensureDirectoryExists(file4); + if (!file5.renameTo(file6)) { + throw new NameReferencingFileConverter.FileConversionException("Could not convert file for " + s2); diff --git a/patch-remap/og/net/minecraft/server/players/PlayerList.patch b/patch-remap/og/net/minecraft/server/players/PlayerList.patch new file mode 100644 index 0000000000..2dafb72373 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/players/PlayerList.patch @@ -0,0 +1,818 @@ +--- a/net/minecraft/server/players/PlayerList.java ++++ b/net/minecraft/server/players/PlayerList.java +@@ -101,6 +101,26 @@ + import net.minecraft.world.scores.ScoreboardTeam; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.stream.Collectors; ++import net.minecraft.server.dedicated.DedicatedServer; ++import net.minecraft.server.network.LoginListener; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerChangedWorldEvent; ++import org.bukkit.event.player.PlayerJoinEvent; ++import org.bukkit.event.player.PlayerLoginEvent; ++import org.bukkit.event.player.PlayerQuitEvent; ++import org.bukkit.event.player.PlayerRespawnEvent; ++import org.bukkit.event.player.PlayerRespawnEvent.RespawnReason; ++import org.bukkit.event.player.PlayerSpawnChangeEvent; ++// CraftBukkit end ++ + public abstract class PlayerList { + + public static final File USERBANLIST_FILE = new File("banned-players.json"); +@@ -113,14 +133,16 @@ + private static final int SEND_PLAYER_INFO_INTERVAL = 600; + private static final SimpleDateFormat BAN_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z"); + private final MinecraftServer server; +- public final List players = Lists.newArrayList(); ++ public final List players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety + private final Map playersByUUID = Maps.newHashMap(); + private final GameProfileBanList bans; + private final IpBanList ipBans; + private final OpList ops; + private final WhiteList whitelist; +- private final Map stats; +- private final Map advancements; ++ // CraftBukkit start ++ // private final Map stats; ++ // private final Map advancements; ++ // CraftBukkit end + public final WorldNBTStorage playerIo; + private boolean doWhiteList; + private final LayeredRegistryAccess registries; +@@ -131,13 +153,23 @@ + private static final boolean ALLOW_LOGOUTIVATOR = false; + private int sendAllPlayerInfoIn; + ++ // CraftBukkit start ++ private CraftServer cserver; ++ + public PlayerList(MinecraftServer minecraftserver, LayeredRegistryAccess layeredregistryaccess, WorldNBTStorage worldnbtstorage, int i) { ++ this.cserver = minecraftserver.server = new CraftServer((DedicatedServer) minecraftserver, this); ++ minecraftserver.console = org.bukkit.craftbukkit.command.ColouredConsoleSender.getInstance(); ++ minecraftserver.reader.addCompleter(new org.bukkit.craftbukkit.command.ConsoleCommandCompleter(minecraftserver.server)); ++ // CraftBukkit end ++ + this.bans = new GameProfileBanList(PlayerList.USERBANLIST_FILE); + this.ipBans = new IpBanList(PlayerList.IPBANLIST_FILE); + this.ops = new OpList(PlayerList.OPLIST_FILE); + this.whitelist = new WhiteList(PlayerList.WHITELIST_FILE); +- this.stats = Maps.newHashMap(); +- this.advancements = Maps.newHashMap(); ++ // CraftBukkit start ++ // this.stats = Maps.newHashMap(); ++ // this.advancements = Maps.newHashMap(); ++ // CraftBukkit end + this.server = minecraftserver; + this.registries = layeredregistryaccess; + this.maxPlayers = i; +@@ -160,15 +192,21 @@ + + NBTTagCompound nbttagcompound = this.load(entityplayer); + ResourceKey resourcekey; ++ // CraftBukkit start - Better rename detection ++ if (nbttagcompound != null && nbttagcompound.contains("bukkit")) { ++ NBTTagCompound bukkit = nbttagcompound.getCompound("bukkit"); ++ s = bukkit.contains("lastKnownName", 8) ? bukkit.getString("lastKnownName") : s; ++ } ++ // CraftBukkit end + + if (nbttagcompound != null) { +- DataResult dataresult = DimensionManager.parseLegacy(new Dynamic(DynamicOpsNBT.INSTANCE, nbttagcompound.get("Dimension"))); ++ DataResult> dataresult = DimensionManager.parseLegacy(new Dynamic(DynamicOpsNBT.INSTANCE, nbttagcompound.get("Dimension"))); // CraftBukkit - decompile error + Logger logger = PlayerList.LOGGER; + + Objects.requireNonNull(logger); +- resourcekey = (ResourceKey) dataresult.resultOrPartial(logger::error).orElse(World.OVERWORLD); ++ resourcekey = (ResourceKey) dataresult.resultOrPartial(logger::error).orElse(entityplayer.serverLevel().dimension()); // CraftBukkit - SPIGOT-7507: If no dimension, fall back to existing dimension loaded from "WorldUUID", which in turn defaults to World.OVERWORLD + } else { +- resourcekey = World.OVERWORLD; ++ resourcekey = entityplayer.serverLevel().dimension(); // CraftBukkit - SPIGOT-7507: If no dimension, fall back to existing dimension loaded from "WorldUUID", which in turn defaults to World.OVERWORLD + } + + ResourceKey resourcekey1 = resourcekey; +@@ -185,7 +223,8 @@ + entityplayer.setServerLevel(worldserver1); + String s1 = networkmanager.getLoggableAddress(this.server.logIPs()); + +- PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ({}, {}, {})", new Object[]{entityplayer.getName().getString(), s1, entityplayer.getId(), entityplayer.getX(), entityplayer.getY(), entityplayer.getZ()}); ++ // CraftBukkit - Moved message to after join ++ // PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ({}, {}, {})", new Object[]{entityplayer.getName().getString(), s1, entityplayer.getId(), entityplayer.getX(), entityplayer.getY(), entityplayer.getZ()}); + WorldData worlddata = worldserver1.getLevelData(); + + entityplayer.loadGameTypes(nbttagcompound); +@@ -196,6 +235,7 @@ + boolean flag2 = gamerules.getBoolean(GameRules.RULE_LIMITED_CRAFTING); + + playerconnection.send(new PacketPlayOutLogin(entityplayer.getId(), worlddata.isHardcore(), this.server.levelKeys(), this.getMaxPlayers(), this.viewDistance, this.simulationDistance, flag1, !flag, flag2, entityplayer.createCommonSpawnInfo(worldserver1))); ++ entityplayer.getBukkitEntity().sendSupportedChannels(); // CraftBukkit + playerconnection.send(new PacketPlayOutServerDifficulty(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); + playerconnection.send(new PacketPlayOutAbilities(entityplayer.getAbilities())); + playerconnection.send(new PacketPlayOutHeldItemSlot(entityplayer.getInventory().selected)); +@@ -212,8 +252,10 @@ + } else { + ichatmutablecomponent = IChatBaseComponent.translatable("multiplayer.player.joined.renamed", entityplayer.getDisplayName(), s); + } ++ // CraftBukkit start ++ ichatmutablecomponent.withStyle(EnumChatFormat.YELLOW); ++ String joinMessage = CraftChatMessage.fromComponent(ichatmutablecomponent); + +- this.broadcastSystemMessage(ichatmutablecomponent.withStyle(EnumChatFormat.YELLOW), false); + playerconnection.teleport(entityplayer.getX(), entityplayer.getY(), entityplayer.getZ(), entityplayer.getYRot(), entityplayer.getXRot()); + ServerPing serverping = this.server.getStatus(); + +@@ -221,13 +263,64 @@ + entityplayer.sendServerStatus(serverping); + } + +- entityplayer.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); ++ // entityplayer.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below + this.players.add(entityplayer); + this.playersByUUID.put(entityplayer.getUUID(), entityplayer); +- this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer))); ++ // this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer))); // CraftBukkit - replaced with loop below ++ ++ // CraftBukkit start ++ CraftPlayer bukkitPlayer = entityplayer.getBukkitEntity(); ++ ++ // Ensure that player inventory is populated with its viewer ++ entityplayer.containerMenu.transferTo(entityplayer.containerMenu, bukkitPlayer); ++ ++ PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(bukkitPlayer, joinMessage); ++ cserver.getPluginManager().callEvent(playerJoinEvent); ++ ++ if (!entityplayer.connection.isAcceptingMessages()) { ++ return; ++ } ++ ++ joinMessage = playerJoinEvent.getJoinMessage(); ++ ++ if (joinMessage != null && joinMessage.length() > 0) { ++ for (IChatBaseComponent line : org.bukkit.craftbukkit.util.CraftChatMessage.fromString(joinMessage)) { ++ server.getPlayerList().broadcastSystemMessage(line, false); ++ } ++ } ++ // CraftBukkit end ++ ++ // CraftBukkit start - sendAll above replaced with this loop ++ ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer)); ++ ++ for (int i = 0; i < this.players.size(); ++i) { ++ EntityPlayer entityplayer1 = (EntityPlayer) this.players.get(i); ++ ++ if (entityplayer1.getBukkitEntity().canSee(bukkitPlayer)) { ++ entityplayer1.connection.send(packet); ++ } ++ ++ if (!bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { ++ continue; ++ } ++ ++ entityplayer.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer1))); ++ } ++ entityplayer.sentListPacket = true; ++ // CraftBukkit end ++ ++ entityplayer.getEntityData().refresh(entityplayer); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn ++ + this.sendLevelInfo(entityplayer, worldserver1); +- worldserver1.addNewPlayer(entityplayer); +- this.server.getCustomBossEvents().onPlayerConnect(entityplayer); ++ ++ // CraftBukkit start - Only add if the player wasn't moved in the event ++ if (entityplayer.level() == worldserver1 && !worldserver1.players().contains(entityplayer)) { ++ worldserver1.addNewPlayer(entityplayer); ++ this.server.getCustomBossEvents().onPlayerConnect(entityplayer); ++ } ++ ++ worldserver1 = entityplayer.serverLevel(); // CraftBukkit - Update in case join event changed it ++ // CraftBukkit end + Iterator iterator = entityplayer.getActiveEffects().iterator(); + + while (iterator.hasNext()) { +@@ -238,8 +331,11 @@ + + if (nbttagcompound != null && nbttagcompound.contains("RootVehicle", 10)) { + NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("RootVehicle"); +- Entity entity = EntityTypes.loadEntityRecursive(nbttagcompound1.getCompound("Entity"), worldserver1, (entity1) -> { +- return !worldserver1.addWithUUID(entity1) ? null : entity1; ++ // CraftBukkit start ++ WorldServer finalWorldServer = worldserver1; ++ Entity entity = EntityTypes.loadEntityRecursive(nbttagcompound1.getCompound("Entity"), finalWorldServer, (entity1) -> { ++ return !finalWorldServer.addWithUUID(entity1) ? null : entity1; ++ // CraftBukkit end + }); + + if (entity != null) { +@@ -282,6 +378,8 @@ + } + + entityplayer.initInventoryMenu(); ++ // CraftBukkit - Moved from above, added world ++ PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", entityplayer.getName().getString(), s1, entityplayer.getId(), worldserver1.serverLevelData.getLevelName(), entityplayer.getX(), entityplayer.getY(), entityplayer.getZ()); + } + + public void updateEntireScoreboard(ScoreboardServer scoreboardserver, EntityPlayer entityplayer) { +@@ -318,30 +416,31 @@ + } + + public void addWorldborderListener(WorldServer worldserver) { ++ if (playerIo != null) return; // CraftBukkit + worldserver.getWorldBorder().addListener(new IWorldBorderListener() { + @Override + public void onBorderSizeSet(WorldBorder worldborder, double d0) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderSizePacket(worldborder)); ++ PlayerList.this.broadcastAll(new ClientboundSetBorderSizePacket(worldborder), worldborder.world); // CraftBukkit + } + + @Override + public void onBorderSizeLerping(WorldBorder worldborder, double d0, double d1, long i) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderLerpSizePacket(worldborder)); ++ PlayerList.this.broadcastAll(new ClientboundSetBorderLerpSizePacket(worldborder), worldborder.world); // CraftBukkit + } + + @Override + public void onBorderCenterSet(WorldBorder worldborder, double d0, double d1) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderCenterPacket(worldborder)); ++ PlayerList.this.broadcastAll(new ClientboundSetBorderCenterPacket(worldborder), worldborder.world); // CraftBukkit + } + + @Override + public void onBorderSetWarningTime(WorldBorder worldborder, int i) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDelayPacket(worldborder)); ++ PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDelayPacket(worldborder), worldborder.world); // CraftBukkit + } + + @Override + public void onBorderSetWarningBlocks(WorldBorder worldborder, int i) { +- PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDistancePacket(worldborder)); ++ PlayerList.this.broadcastAll(new ClientboundSetBorderWarningDistancePacket(worldborder), worldborder.world); // CraftBukkit + } + + @Override +@@ -369,14 +468,15 @@ + } + + protected void save(EntityPlayer entityplayer) { ++ if (!entityplayer.getBukkitEntity().isPersistent()) return; // CraftBukkit + this.playerIo.save(entityplayer); +- ServerStatisticManager serverstatisticmanager = (ServerStatisticManager) this.stats.get(entityplayer.getUUID()); ++ ServerStatisticManager serverstatisticmanager = (ServerStatisticManager) entityplayer.getStats(); // CraftBukkit + + if (serverstatisticmanager != null) { + serverstatisticmanager.save(); + } + +- AdvancementDataPlayer advancementdataplayer = (AdvancementDataPlayer) this.advancements.get(entityplayer.getUUID()); ++ AdvancementDataPlayer advancementdataplayer = (AdvancementDataPlayer) entityplayer.getAdvancements(); // CraftBukkit + + if (advancementdataplayer != null) { + advancementdataplayer.save(); +@@ -384,10 +484,24 @@ + + } + +- public void remove(EntityPlayer entityplayer) { ++ public String remove(EntityPlayer entityplayer) { // CraftBukkit - return string + WorldServer worldserver = entityplayer.serverLevel(); + + entityplayer.awardStat(StatisticList.LEAVE_GAME); ++ ++ // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it ++ // See SPIGOT-5799, SPIGOT-6145 ++ if (entityplayer.containerMenu != entityplayer.inventoryMenu) { ++ entityplayer.closeContainer(); ++ } ++ ++ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(entityplayer.getBukkitEntity(), entityplayer.kickLeaveMessage != null ? entityplayer.kickLeaveMessage : "\u00A7e" + entityplayer.getScoreboardName() + " left the game"); ++ cserver.getPluginManager().callEvent(playerQuitEvent); ++ entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); ++ ++ entityplayer.doTick(); // SPIGOT-924 ++ // CraftBukkit end ++ + this.save(entityplayer); + if (entityplayer.isPassenger()) { + Entity entity = entityplayer.getRootVehicle(); +@@ -411,18 +525,66 @@ + + if (entityplayer1 == entityplayer) { + this.playersByUUID.remove(uuid); +- this.stats.remove(uuid); +- this.advancements.remove(uuid); ++ // CraftBukkit start ++ // this.stats.remove(uuid); ++ // this.advancements.remove(uuid); ++ // CraftBukkit end + } + +- this.broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID()))); ++ // CraftBukkit start ++ // this.broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID()))); ++ ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID())); ++ for (int i = 0; i < players.size(); i++) { ++ EntityPlayer entityplayer2 = (EntityPlayer) this.players.get(i); ++ ++ if (entityplayer2.getBukkitEntity().canSee(entityplayer.getBukkitEntity())) { ++ entityplayer2.connection.send(packet); ++ } else { ++ entityplayer2.getBukkitEntity().onEntityRemove(entityplayer); ++ } ++ } ++ // This removes the scoreboard (and player reference) for the specific player in the manager ++ cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); ++ // CraftBukkit end ++ ++ return playerQuitEvent.getQuitMessage(); // CraftBukkit + } + +- @Nullable +- public IChatBaseComponent canPlayerLogin(SocketAddress socketaddress, GameProfile gameprofile) { ++ // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer ++ public EntityPlayer canPlayerLogin(LoginListener loginlistener, GameProfile gameprofile) { + IChatMutableComponent ichatmutablecomponent; + +- if (this.bans.isBanned(gameprofile)) { ++ // Moved from processLogin ++ UUID uuid = gameprofile.getId(); ++ List list = Lists.newArrayList(); ++ ++ EntityPlayer entityplayer; ++ ++ for (int i = 0; i < this.players.size(); ++i) { ++ entityplayer = (EntityPlayer) this.players.get(i); ++ if (entityplayer.getUUID().equals(uuid)) { ++ list.add(entityplayer); ++ } ++ } ++ ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ entityplayer = (EntityPlayer) iterator.next(); ++ save(entityplayer); // CraftBukkit - Force the player's inventory to be saved ++ entityplayer.connection.disconnect(IChatBaseComponent.translatable("multiplayer.disconnect.duplicate_login")); ++ } ++ ++ // Instead of kicking then returning, we need to store the kick reason ++ // in the event, check with plugins to see if it's ok, and THEN kick ++ // depending on the outcome. ++ SocketAddress socketaddress = loginlistener.connection.getRemoteAddress(); ++ ++ EntityPlayer entity = new EntityPlayer(this.server, this.server.getLevel(World.OVERWORLD), gameprofile, ClientInformation.createDefault()); ++ Player player = entity.getBukkitEntity(); ++ PlayerLoginEvent event = new PlayerLoginEvent(player, loginlistener.connection.hostname, ((java.net.InetSocketAddress) socketaddress).getAddress()); ++ ++ if (getBans().isBanned(gameprofile) && !getBans().get(gameprofile).hasExpired()) { + GameProfileBanEntry gameprofilebanentry = (GameProfileBanEntry) this.bans.get(gameprofile); + + ichatmutablecomponent = IChatBaseComponent.translatable("multiplayer.disconnect.banned.reason", gameprofilebanentry.getReason()); +@@ -430,10 +592,12 @@ + ichatmutablecomponent.append((IChatBaseComponent) IChatBaseComponent.translatable("multiplayer.disconnect.banned.expiration", PlayerList.BAN_DATE_FORMAT.format(gameprofilebanentry.getExpires()))); + } + +- return ichatmutablecomponent; ++ // return chatmessage; ++ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(ichatmutablecomponent)); + } else if (!this.isWhiteListed(gameprofile)) { +- return IChatBaseComponent.translatable("multiplayer.disconnect.not_whitelisted"); +- } else if (this.ipBans.isBanned(socketaddress)) { ++ ichatmutablecomponent = IChatBaseComponent.translatable("multiplayer.disconnect.not_whitelisted"); ++ event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, CraftChatMessage.fromComponent(ichatmutablecomponent)); ++ } else if (getIpBans().isBanned(socketaddress) && !getIpBans().get(socketaddress).hasExpired()) { + IpBanEntry ipbanentry = this.ipBans.get(socketaddress); + + ichatmutablecomponent = IChatBaseComponent.translatable("multiplayer.disconnect.banned_ip.reason", ipbanentry.getReason()); +@@ -441,17 +605,32 @@ + ichatmutablecomponent.append((IChatBaseComponent) IChatBaseComponent.translatable("multiplayer.disconnect.banned_ip.expiration", PlayerList.BAN_DATE_FORMAT.format(ipbanentry.getExpires()))); + } + +- return ichatmutablecomponent; ++ // return chatmessage; ++ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(ichatmutablecomponent)); + } else { +- return this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile) ? IChatBaseComponent.translatable("multiplayer.disconnect.server_full") : null; ++ // return this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile) ? IChatBaseComponent.translatable("multiplayer.disconnect.server_full") : null; ++ if (this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile)) { ++ event.disallow(PlayerLoginEvent.Result.KICK_FULL, "The server is full"); ++ } + } ++ ++ cserver.getPluginManager().callEvent(event); ++ if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) { ++ loginlistener.disconnect(event.getKickMessage()); ++ return null; ++ } ++ return entity; + } + +- public EntityPlayer getPlayerForLogin(GameProfile gameprofile, ClientInformation clientinformation) { +- return new EntityPlayer(this.server, this.server.overworld(), gameprofile, clientinformation); ++ // CraftBukkit start - added EntityPlayer ++ public EntityPlayer getPlayerForLogin(GameProfile gameprofile, ClientInformation clientinformation, EntityPlayer player) { ++ player.updateOptions(clientinformation); ++ return player; ++ // CraftBukkit end + } + +- public boolean disconnectAllPlayersWithProfile(GameProfile gameprofile) { ++ public boolean disconnectAllPlayersWithProfile(GameProfile gameprofile, EntityPlayer player) { // CraftBukkit - added EntityPlayer ++ /* CraftBukkit startMoved up + UUID uuid = gameprofile.getId(); + Set set = Sets.newIdentityHashSet(); + Iterator iterator = this.players.iterator(); +@@ -479,14 +658,24 @@ + } + + return !set.isEmpty(); ++ */ ++ return player == null; ++ // CraftBukkit end + } + +- public EntityPlayer respawn(EntityPlayer entityplayer, boolean flag) { ++ // CraftBukkit start ++ public EntityPlayer respawn(EntityPlayer entityplayer, boolean flag, RespawnReason reason) { ++ return this.respawn(entityplayer, this.server.getLevel(entityplayer.getRespawnDimension()), flag, null, true, reason); ++ } ++ ++ public EntityPlayer respawn(EntityPlayer entityplayer, WorldServer worldserver, boolean flag, Location location, boolean avoidSuffocation, RespawnReason reason) { ++ entityplayer.stopRiding(); // CraftBukkit + this.players.remove(entityplayer); + entityplayer.serverLevel().removePlayerImmediately(entityplayer, Entity.RemovalReason.DISCARDED); + BlockPosition blockposition = entityplayer.getRespawnPosition(); + float f = entityplayer.getRespawnAngle(); + boolean flag1 = entityplayer.isRespawnForced(); ++ /* CraftBukkit start + WorldServer worldserver = this.server.getLevel(entityplayer.getRespawnDimension()); + Optional optional; + +@@ -498,6 +687,11 @@ + + WorldServer worldserver1 = worldserver != null && optional.isPresent() ? worldserver : this.server.overworld(); + EntityPlayer entityplayer1 = new EntityPlayer(this.server, worldserver1, entityplayer.getGameProfile(), entityplayer.clientInformation()); ++ // */ ++ EntityPlayer entityplayer1 = entityplayer; ++ org.bukkit.World fromWorld = entityplayer.getBukkitEntity().getWorld(); ++ entityplayer.wonGame = false; ++ // CraftBukkit end + + entityplayer1.connection = entityplayer.connection; + entityplayer1.restoreFrom(entityplayer, flag); +@@ -513,28 +707,66 @@ + + boolean flag2 = false; + +- if (optional.isPresent()) { +- IBlockData iblockdata = worldserver1.getBlockState(blockposition); +- boolean flag3 = iblockdata.is(Blocks.RESPAWN_ANCHOR); +- Vec3D vec3d = (Vec3D) optional.get(); +- float f1; ++ // CraftBukkit start - fire PlayerRespawnEvent ++ if (location == null) { ++ boolean isBedSpawn = false; ++ WorldServer worldserver1 = this.server.getLevel(entityplayer.getRespawnDimension()); ++ if (worldserver1 != null) { ++ Optional optional; + +- if (!iblockdata.is(TagsBlock.BEDS) && !flag3) { +- f1 = f; +- } else { +- Vec3D vec3d1 = Vec3D.atBottomCenterOf(blockposition).subtract(vec3d).normalize(); ++ if (blockposition != null) { ++ optional = EntityHuman.findRespawnPositionAndUseSpawnBlock(worldserver1, blockposition, f, flag1, flag); ++ } else { ++ optional = Optional.empty(); ++ } + +- f1 = (float) MathHelper.wrapDegrees(MathHelper.atan2(vec3d1.z, vec3d1.x) * 57.2957763671875D - 90.0D); ++ if (optional.isPresent()) { ++ IBlockData iblockdata = worldserver1.getBlockState(blockposition); ++ boolean flag3 = iblockdata.is(Blocks.RESPAWN_ANCHOR); ++ Vec3D vec3d = (Vec3D) optional.get(); ++ float f1; ++ ++ if (!iblockdata.is(TagsBlock.BEDS) && !flag3) { ++ f1 = f; ++ } else { ++ Vec3D vec3d1 = Vec3D.atBottomCenterOf(blockposition).subtract(vec3d).normalize(); ++ ++ f1 = (float) MathHelper.wrapDegrees(MathHelper.atan2(vec3d1.z, vec3d1.x) * 57.2957763671875D - 90.0D); ++ } ++ ++ // entityplayer1.setRespawnPosition(worldserver1.dimension(), blockposition, f, flag1, false); // CraftBukkit - not required, just copies old location into reused entity ++ flag2 = !flag && flag3; ++ isBedSpawn = true; ++ location = CraftLocation.toBukkit(vec3d, worldserver1.getWorld(), f1, 0.0F); ++ } else if (blockposition != null) { ++ entityplayer1.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F)); ++ entityplayer1.setRespawnPosition(null, null, 0f, false, false, PlayerSpawnChangeEvent.Cause.RESET); // CraftBukkit - SPIGOT-5988: Clear respawn location when obstructed ++ } + } + +- entityplayer1.moveTo(vec3d.x, vec3d.y, vec3d.z, f1, 0.0F); +- entityplayer1.setRespawnPosition(worldserver1.dimension(), blockposition, f, flag1, false); +- flag2 = !flag && flag3; +- } else if (blockposition != null) { +- entityplayer1.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F)); ++ if (location == null) { ++ worldserver1 = this.server.getLevel(World.OVERWORLD); ++ blockposition = entityplayer1.getSpawnPoint(worldserver1); ++ location = CraftLocation.toBukkit(blockposition, worldserver1.getWorld()).add(0.5F, 0.1F, 0.5F); ++ } ++ ++ Player respawnPlayer = entityplayer1.getBukkitEntity(); ++ PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !flag2, flag2, reason); ++ cserver.getPluginManager().callEvent(respawnEvent); ++ ++ location = respawnEvent.getRespawnLocation(); ++ if (!flag) entityplayer.reset(); // SPIGOT-4785 ++ } else { ++ location.setWorld(worldserver.getWorld()); + } ++ WorldServer worldserver1 = ((CraftWorld) location.getWorld()).getHandle(); ++ entityplayer1.spawnIn(worldserver1); ++ entityplayer1.unsetRemoved(); ++ entityplayer1.setShiftKeyDown(false); ++ entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + +- while (!worldserver1.noCollision((Entity) entityplayer1) && entityplayer1.getY() < (double) worldserver1.getMaxBuildHeight()) { ++ while (avoidSuffocation && !worldserver1.noCollision((Entity) entityplayer1) && entityplayer1.getY() < (double) worldserver1.getMaxBuildHeight()) { ++ // CraftBukkit end + entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); + } + +@@ -543,21 +775,43 @@ + WorldData worlddata = worldserver2.getLevelData(); + + entityplayer1.connection.send(new PacketPlayOutRespawn(entityplayer1.createCommonSpawnInfo(worldserver2), (byte) i)); +- entityplayer1.connection.teleport(entityplayer1.getX(), entityplayer1.getY(), entityplayer1.getZ(), entityplayer1.getYRot(), entityplayer1.getXRot()); ++ entityplayer1.connection.teleport(CraftLocation.toBukkit(entityplayer1.position(), worldserver2.getWorld(), entityplayer1.getYRot(), entityplayer1.getXRot())); // CraftBukkit + entityplayer1.connection.send(new PacketPlayOutSpawnPosition(worldserver1.getSharedSpawnPos(), worldserver1.getSharedSpawnAngle())); + entityplayer1.connection.send(new PacketPlayOutServerDifficulty(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); + entityplayer1.connection.send(new PacketPlayOutExperience(entityplayer1.experienceProgress, entityplayer1.totalExperience, entityplayer1.experienceLevel)); + this.sendLevelInfo(entityplayer1, worldserver1); + this.sendPlayerPermissionLevel(entityplayer1); +- worldserver1.addRespawnedPlayer(entityplayer1); +- this.players.add(entityplayer1); +- this.playersByUUID.put(entityplayer1.getUUID(), entityplayer1); +- entityplayer1.initInventoryMenu(); ++ if (!entityplayer.connection.isDisconnected()) { ++ worldserver1.addRespawnedPlayer(entityplayer1); ++ this.players.add(entityplayer1); ++ this.playersByUUID.put(entityplayer1.getUUID(), entityplayer1); ++ } ++ // entityplayer1.initInventoryMenu(); + entityplayer1.setHealth(entityplayer1.getHealth()); + if (flag2) { + entityplayer1.connection.send(new PacketPlayOutNamedSoundEffect(SoundEffects.RESPAWN_ANCHOR_DEPLETE, SoundCategory.BLOCKS, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), 1.0F, 1.0F, worldserver1.getRandom().nextLong())); + } ++ // Added from changeDimension ++ sendAllPlayerInfo(entityplayer); // Update health, etc... ++ entityplayer.onUpdateAbilities(); ++ for (MobEffect mobEffect : entityplayer.getActiveEffects()) { ++ entityplayer.connection.send(new PacketPlayOutEntityEffect(entityplayer.getId(), mobEffect)); ++ } ++ ++ // Fire advancement trigger ++ entityplayer.triggerDimensionChangeTriggers(((CraftWorld) fromWorld).getHandle()); ++ ++ // Don't fire on respawn ++ if (fromWorld != location.getWorld()) { ++ PlayerChangedWorldEvent event = new PlayerChangedWorldEvent(entityplayer.getBukkitEntity(), fromWorld); ++ server.server.getPluginManager().callEvent(event); ++ } + ++ // Save player file again if they were disconnected ++ if (entityplayer.connection.isDisconnected()) { ++ this.save(entityplayer); ++ } ++ // CraftBukkit end + return entityplayer1; + } + +@@ -570,7 +824,18 @@ + + public void tick() { + if (++this.sendAllPlayerInfoIn > 600) { +- this.broadcastAll(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.a.UPDATE_LATENCY), this.players)); ++ // CraftBukkit start ++ for (int i = 0; i < this.players.size(); ++i) { ++ final EntityPlayer target = (EntityPlayer) this.players.get(i); ++ ++ target.connection.send(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.a.UPDATE_LATENCY), this.players.stream().filter(new Predicate() { ++ @Override ++ public boolean test(EntityPlayer input) { ++ return target.getBukkitEntity().canSee(input.getBukkitEntity()); ++ } ++ }).collect(Collectors.toList()))); ++ } ++ // CraftBukkit end + this.sendAllPlayerInfoIn = 0; + } + +@@ -587,6 +852,25 @@ + + } + ++ // CraftBukkit start - add a world/entity limited version ++ public void broadcastAll(Packet packet, EntityHuman entityhuman) { ++ for (int i = 0; i < this.players.size(); ++i) { ++ EntityPlayer entityplayer = this.players.get(i); ++ if (entityhuman != null && !entityplayer.getBukkitEntity().canSee(entityhuman.getBukkitEntity())) { ++ continue; ++ } ++ ((EntityPlayer) this.players.get(i)).connection.send(packet); ++ } ++ } ++ ++ public void broadcastAll(Packet packet, World world) { ++ for (int i = 0; i < world.players().size(); ++i) { ++ ((EntityPlayer) world.players().get(i)).connection.send(packet); ++ } ++ ++ } ++ // CraftBukkit end ++ + public void broadcastAll(Packet packet, ResourceKey resourcekey) { + Iterator iterator = this.players.iterator(); + +@@ -665,7 +949,7 @@ + } + + public void deop(GameProfile gameprofile) { +- this.ops.remove((Object) gameprofile); ++ this.ops.remove(gameprofile); // CraftBukkit - decompile error + EntityPlayer entityplayer = this.getPlayer(gameprofile.getId()); + + if (entityplayer != null) { +@@ -689,6 +973,7 @@ + entityplayer.connection.send(new PacketPlayOutEntityStatus(entityplayer, b0)); + } + ++ entityplayer.getBukkitEntity().recalculatePermissions(); // CraftBukkit + this.server.getCommands().sendCommands(entityplayer); + } + +@@ -719,6 +1004,12 @@ + for (int i = 0; i < this.players.size(); ++i) { + EntityPlayer entityplayer = (EntityPlayer) this.players.get(i); + ++ // CraftBukkit start - Test if player receiving packet can see the source of the packet ++ if (entityhuman != null && !entityplayer.getBukkitEntity().canSee(entityhuman.getBukkitEntity())) { ++ continue; ++ } ++ // CraftBukkit end ++ + if (entityplayer != entityhuman && entityplayer.level().dimension() == resourcekey) { + double d4 = d0 - entityplayer.getX(); + double d5 = d1 - entityplayer.getY(); +@@ -758,15 +1049,19 @@ + public void reloadWhiteList() {} + + public void sendLevelInfo(EntityPlayer entityplayer, WorldServer worldserver) { +- WorldBorder worldborder = this.server.overworld().getWorldBorder(); ++ WorldBorder worldborder = entityplayer.level().getWorldBorder(); // CraftBukkit + + entityplayer.connection.send(new ClientboundInitializeBorderPacket(worldborder)); + entityplayer.connection.send(new PacketPlayOutUpdateTime(worldserver.getGameTime(), worldserver.getDayTime(), worldserver.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); + entityplayer.connection.send(new PacketPlayOutSpawnPosition(worldserver.getSharedSpawnPos(), worldserver.getSharedSpawnAngle())); + if (worldserver.isRaining()) { +- entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.START_RAINING, 0.0F)); +- entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.RAIN_LEVEL_CHANGE, worldserver.getRainLevel(1.0F))); +- entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, worldserver.getThunderLevel(1.0F))); ++ // CraftBukkit start - handle player weather ++ // entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.START_RAINING, 0.0F)); ++ // entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.RAIN_LEVEL_CHANGE, worldserver.getRainLevel(1.0F))); ++ // entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, worldserver.getThunderLevel(1.0F))); ++ entityplayer.setPlayerWeather(org.bukkit.WeatherType.DOWNFALL, false); ++ entityplayer.updateWeather(-worldserver.rainLevel, worldserver.rainLevel, -worldserver.thunderLevel, worldserver.thunderLevel); ++ // CraftBukkit end + } + + entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.LEVEL_CHUNKS_LOAD_START, 0.0F)); +@@ -775,8 +1070,16 @@ + + public void sendAllPlayerInfo(EntityPlayer entityplayer) { + entityplayer.inventoryMenu.sendAllDataToRemote(); +- entityplayer.resetSentInfo(); ++ // entityplayer.resetSentInfo(); ++ entityplayer.getBukkitEntity().updateScaledHealth(); // CraftBukkit - Update scaled health on respawn and worldchange ++ entityplayer.getEntityData().refresh(entityplayer); // CraftBukkkit - SPIGOT-7218: sync metadata + entityplayer.connection.send(new PacketPlayOutHeldItemSlot(entityplayer.getInventory().selected)); ++ // CraftBukkit start - from GameRules ++ int i = entityplayer.level().getGameRules().getBoolean(GameRules.RULE_REDUCEDDEBUGINFO) ? 22 : 23; ++ entityplayer.connection.send(new PacketPlayOutEntityStatus(entityplayer, (byte) i)); ++ float immediateRespawn = entityplayer.level().getGameRules().getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN) ? 1.0F: 0.0F; ++ entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.IMMEDIATE_RESPAWN, immediateRespawn)); ++ // CraftBukkit end + } + + public int getPlayerCount() { +@@ -832,12 +1135,22 @@ + } + + public void removeAll() { +- for (int i = 0; i < this.players.size(); ++i) { +- ((EntityPlayer) this.players.get(i)).connection.disconnect(IChatBaseComponent.translatable("multiplayer.disconnect.server_shutdown")); ++ // CraftBukkit start - disconnect safely ++ for (EntityPlayer player : this.players) { ++ player.connection.disconnect(this.server.server.getShutdownMessage()); // CraftBukkit - add custom shutdown message + } ++ // CraftBukkit end + + } + ++ // CraftBukkit start ++ public void broadcastMessage(IChatBaseComponent[] iChatBaseComponents) { ++ for (IChatBaseComponent component : iChatBaseComponents) { ++ broadcastSystemMessage(component, false); ++ } ++ } ++ // CraftBukkit end ++ + public void broadcastSystemMessage(IChatBaseComponent ichatbasecomponent, boolean flag) { + this.broadcastSystemMessage(ichatbasecomponent, (entityplayer) -> { + return ichatbasecomponent; +@@ -895,16 +1208,23 @@ + return playerchatmessage.hasSignature() && !playerchatmessage.hasExpiredServer(Instant.now()); + } + +- public ServerStatisticManager getPlayerStats(EntityHuman entityhuman) { +- UUID uuid = entityhuman.getUUID(); +- ServerStatisticManager serverstatisticmanager = (ServerStatisticManager) this.stats.get(uuid); ++ // CraftBukkit start ++ public ServerStatisticManager getPlayerStats(EntityPlayer entityhuman) { ++ ServerStatisticManager serverstatisticmanager = entityhuman.getStats(); ++ return serverstatisticmanager == null ? getPlayerStats(entityhuman.getUUID(), entityhuman.getDisplayName().getString()) : serverstatisticmanager; ++ } ++ ++ public ServerStatisticManager getPlayerStats(UUID uuid, String displayName) { ++ EntityPlayer entityhuman = this.getPlayer(uuid); ++ ServerStatisticManager serverstatisticmanager = entityhuman == null ? null : (ServerStatisticManager) entityhuman.getStats(); ++ // CraftBukkit end + + if (serverstatisticmanager == null) { + File file = this.server.getWorldPath(SavedFile.PLAYER_STATS_DIR).toFile(); + File file1 = new File(file, uuid + ".json"); + + if (!file1.exists()) { +- File file2 = new File(file, entityhuman.getName().getString() + ".json"); ++ File file2 = new File(file, displayName + ".json"); // CraftBukkit + Path path = file2.toPath(); + + if (FileUtils.isPathNormalized(path) && FileUtils.isPathPortable(path) && path.startsWith(file.getPath()) && file2.isFile()) { +@@ -913,7 +1233,7 @@ + } + + serverstatisticmanager = new ServerStatisticManager(this.server, file1); +- this.stats.put(uuid, serverstatisticmanager); ++ // this.stats.put(uuid, serverstatisticmanager); // CraftBukkit + } + + return serverstatisticmanager; +@@ -921,13 +1241,13 @@ + + public AdvancementDataPlayer getPlayerAdvancements(EntityPlayer entityplayer) { + UUID uuid = entityplayer.getUUID(); +- AdvancementDataPlayer advancementdataplayer = (AdvancementDataPlayer) this.advancements.get(uuid); ++ AdvancementDataPlayer advancementdataplayer = (AdvancementDataPlayer) entityplayer.getAdvancements(); // CraftBukkit + + if (advancementdataplayer == null) { + Path path = this.server.getWorldPath(SavedFile.PLAYER_ADVANCEMENTS_DIR).resolve(uuid + ".json"); + + advancementdataplayer = new AdvancementDataPlayer(this.server.getFixerUpper(), this, this.server.getAdvancements(), path, entityplayer); +- this.advancements.put(uuid, advancementdataplayer); ++ // this.advancements.put(uuid, advancementdataplayer); // CraftBukkit + } + + advancementdataplayer.setPlayer(entityplayer); +@@ -978,13 +1298,20 @@ + } + + public void reloadResources() { +- Iterator iterator = this.advancements.values().iterator(); ++ // CraftBukkit start ++ /*Iterator iterator = this.advancements.values().iterator(); + + while (iterator.hasNext()) { + AdvancementDataPlayer advancementdataplayer = (AdvancementDataPlayer) iterator.next(); + + advancementdataplayer.reload(this.server.getAdvancements()); ++ }*/ ++ ++ for (EntityPlayer player : players) { ++ player.getAdvancements().reload(this.server.getAdvancements()); ++ player.getAdvancements().flushDirty(player); // CraftBukkit - trigger immediate flush of advancements + } ++ // CraftBukkit end + + this.broadcastAll(new ClientboundUpdateTagsPacket(TagNetworkSerialization.serializeTagsToNetwork(this.registries))); + PacketPlayOutRecipeUpdate packetplayoutrecipeupdate = new PacketPlayOutRecipeUpdate(this.server.getRecipeManager().getRecipes()); diff --git a/patch-remap/og/net/minecraft/server/players/SleepStatus.patch b/patch-remap/og/net/minecraft/server/players/SleepStatus.patch new file mode 100644 index 0000000000..3af51ebff8 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/players/SleepStatus.patch @@ -0,0 +1,44 @@ +--- a/net/minecraft/server/players/SleepStatus.java ++++ b/net/minecraft/server/players/SleepStatus.java +@@ -18,9 +18,12 @@ + } + + public boolean areEnoughDeepSleeping(int i, List list) { +- int j = (int) list.stream().filter(EntityHuman::isSleepingLongEnough).count(); ++ // CraftBukkit start ++ int j = (int) list.stream().filter((eh) -> { return eh.isSleepingLongEnough() || eh.fauxSleeping; }).count(); ++ boolean anyDeepSleep = list.stream().anyMatch(EntityHuman::isSleepingLongEnough); + +- return j >= this.sleepersNeeded(i); ++ return anyDeepSleep && j >= this.sleepersNeeded(i); ++ // CraftBukkit end + } + + public int sleepersNeeded(int i) { +@@ -42,18 +45,24 @@ + this.activePlayers = 0; + this.sleepingPlayers = 0; + Iterator iterator = list.iterator(); ++ boolean anySleep = false; // CraftBukkit + + while (iterator.hasNext()) { + EntityPlayer entityplayer = (EntityPlayer) iterator.next(); + + if (!entityplayer.isSpectator()) { + ++this.activePlayers; +- if (entityplayer.isSleeping()) { ++ if (entityplayer.isSleeping() || entityplayer.fauxSleeping) { // CraftBukkit + ++this.sleepingPlayers; + } ++ // CraftBukkit start ++ if (entityplayer.isSleeping()) { ++ anySleep = true; ++ } ++ // CraftBukkit end + } + } + +- return (j > 0 || this.sleepingPlayers > 0) && (i != this.activePlayers || j != this.sleepingPlayers); ++ return anySleep && (j > 0 || this.sleepingPlayers > 0) && (i != this.activePlayers || j != this.sleepingPlayers); // CraftBukkit + } + } diff --git a/patch-remap/og/net/minecraft/server/players/UserCache.patch b/patch-remap/og/net/minecraft/server/players/UserCache.patch new file mode 100644 index 0000000000..78c40358b9 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/players/UserCache.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/server/players/UserCache.java ++++ b/net/minecraft/server/players/UserCache.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.server.players; + + import com.google.common.collect.ImmutableList; +@@ -85,7 +86,7 @@ + } + + public void onProfileLookupFailed(String s1, Exception exception) { +- atomicreference.set((Object) null); ++ atomicreference.set(null); // CraftBukkit - decompile error + } + }; + diff --git a/patch-remap/og/net/minecraft/server/rcon/RemoteControlCommandListener.patch b/patch-remap/og/net/minecraft/server/rcon/RemoteControlCommandListener.patch new file mode 100644 index 0000000000..df736515af --- /dev/null +++ b/patch-remap/og/net/minecraft/server/rcon/RemoteControlCommandListener.patch @@ -0,0 +1,45 @@ +--- a/net/minecraft/server/rcon/RemoteControlCommandListener.java ++++ b/net/minecraft/server/rcon/RemoteControlCommandListener.java +@@ -9,14 +9,23 @@ + import net.minecraft.world.phys.Vec2F; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import java.net.SocketAddress; ++import org.bukkit.craftbukkit.command.CraftRemoteConsoleCommandSender; ++// CraftBukkit end + public class RemoteControlCommandListener implements ICommandListener { + + private static final String RCON = "Rcon"; + private static final IChatBaseComponent RCON_COMPONENT = IChatBaseComponent.literal("Rcon"); + private final StringBuffer buffer = new StringBuffer(); + private final MinecraftServer server; ++ // CraftBukkit start ++ public final SocketAddress socketAddress; ++ private final CraftRemoteConsoleCommandSender remoteConsole = new CraftRemoteConsoleCommandSender(this); + +- public RemoteControlCommandListener(MinecraftServer minecraftserver) { ++ public RemoteControlCommandListener(MinecraftServer minecraftserver, SocketAddress socketAddress) { ++ this.socketAddress = socketAddress; ++ // CraftBukkit end + this.server = minecraftserver; + } + +@@ -34,6 +43,17 @@ + return new CommandListenerWrapper(this, Vec3D.atLowerCornerOf(worldserver.getSharedSpawnPos()), Vec2F.ZERO, worldserver, 4, "Rcon", RemoteControlCommandListener.RCON_COMPONENT, this.server, (Entity) null); + } + ++ // CraftBukkit start - Send a String ++ public void sendMessage(String message) { ++ this.buffer.append(message); ++ } ++ ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandListenerWrapper wrapper) { ++ return this.remoteConsole; ++ } ++ // CraftBukkit end ++ + @Override + public void sendSystemMessage(IChatBaseComponent ichatbasecomponent) { + this.buffer.append(ichatbasecomponent.getString()); diff --git a/patch-remap/og/net/minecraft/server/rcon/thread/RemoteControlSession.patch b/patch-remap/og/net/minecraft/server/rcon/thread/RemoteControlSession.patch new file mode 100644 index 0000000000..f3e0a80992 --- /dev/null +++ b/patch-remap/og/net/minecraft/server/rcon/thread/RemoteControlSession.patch @@ -0,0 +1,77 @@ +--- a/net/minecraft/server/rcon/thread/RemoteControlSession.java ++++ b/net/minecraft/server/rcon/thread/RemoteControlSession.java +@@ -11,6 +11,10 @@ + import net.minecraft.server.IMinecraftServer; + import net.minecraft.server.rcon.StatusChallengeUtils; + import org.slf4j.Logger; ++// CraftBukkit start ++import net.minecraft.server.dedicated.DedicatedServer; ++import net.minecraft.server.rcon.RemoteControlCommandListener; ++// CraftBukkit end + + public class RemoteControlSession extends RemoteConnectionThread { + +@@ -24,11 +28,14 @@ + private final Socket client; + private final byte[] buf = new byte[1460]; + private final String rconPassword; +- private final IMinecraftServer serverInterface; ++ // CraftBukkit start ++ private final DedicatedServer serverInterface; ++ private final RemoteControlCommandListener rconConsoleSource; ++ // CraftBukkit end + + RemoteControlSession(IMinecraftServer iminecraftserver, String s, Socket socket) { + super("RCON Client " + socket.getInetAddress()); +- this.serverInterface = iminecraftserver; ++ this.serverInterface = (DedicatedServer) iminecraftserver; // CraftBukkit + this.client = socket; + + try { +@@ -38,11 +45,14 @@ + } + + this.rconPassword = s; ++ this.rconConsoleSource = new net.minecraft.server.rcon.RemoteControlCommandListener(this.serverInterface, socket.getRemoteSocketAddress()); // CraftBukkit + } + + public void run() { +- while (true) { +- try { ++ // CraftBukkit start - decompile error: switch try / while statement ++ try { ++ while (true) { ++ // CraftBukkit end + if (!this.running) { + return; + } +@@ -71,7 +81,7 @@ + String s = StatusChallengeUtils.stringFromByteArray(this.buf, k, i); + + try { +- this.sendCmdResponse(l, this.serverInterface.runCommand(s)); ++ this.sendCmdResponse(l, this.serverInterface.runCommand(this.rconConsoleSource, s)); // CraftBukkit + } catch (Exception exception) { + this.sendCmdResponse(l, "Error executing: " + s + " (" + exception.getMessage() + ")"); + } +@@ -98,6 +108,7 @@ + continue; + } + } ++ } // CraftBukkit - decompile error: switch try / while statement + } catch (IOException ioexception) { + return; + } catch (Exception exception1) { +@@ -109,8 +120,10 @@ + this.running = false; + } + +- return; +- } ++ // CraftBukkit start - decompile error: switch try / while statement ++ // return; ++ // } ++ // CraftBukkit end + } + + private void send(int i, int j, String s) throws IOException { diff --git a/patch-remap/og/net/minecraft/stats/RecipeBookServer.patch b/patch-remap/og/net/minecraft/stats/RecipeBookServer.patch new file mode 100644 index 0000000000..82d48407a1 --- /dev/null +++ b/patch-remap/og/net/minecraft/stats/RecipeBookServer.patch @@ -0,0 +1,28 @@ +--- a/net/minecraft/stats/RecipeBookServer.java ++++ b/net/minecraft/stats/RecipeBookServer.java +@@ -20,6 +20,8 @@ + import net.minecraft.world.item.crafting.RecipeHolder; + import org.slf4j.Logger; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public class RecipeBookServer extends RecipeBook { + + public static final String RECIPE_BOOK_TAG = "recipeBook"; +@@ -36,7 +38,7 @@ + RecipeHolder recipeholder = (RecipeHolder) iterator.next(); + MinecraftKey minecraftkey = recipeholder.id(); + +- if (!this.known.contains(minecraftkey) && !recipeholder.value().isSpecial()) { ++ if (!this.known.contains(minecraftkey) && !recipeholder.value().isSpecial() && CraftEventFactory.handlePlayerRecipeListUpdateEvent(entityplayer, minecraftkey)) { // CraftBukkit + this.add(minecraftkey); + this.addHighlight(minecraftkey); + list.add(minecraftkey); +@@ -73,6 +75,7 @@ + } + + private void sendRecipes(PacketPlayOutRecipes.Action packetplayoutrecipes_action, EntityPlayer entityplayer, List list) { ++ if (entityplayer.connection == null) return; // SPIGOT-4478 during PlayerLoginEvent + entityplayer.connection.send(new PacketPlayOutRecipes(packetplayoutrecipes_action, list, Collections.emptyList(), this.getBookSettings())); + } + diff --git a/patch-remap/og/net/minecraft/stats/ServerStatisticManager.patch b/patch-remap/og/net/minecraft/stats/ServerStatisticManager.patch new file mode 100644 index 0000000000..ac3c4fffdf --- /dev/null +++ b/patch-remap/og/net/minecraft/stats/ServerStatisticManager.patch @@ -0,0 +1,26 @@ +--- a/net/minecraft/stats/ServerStatisticManager.java ++++ b/net/minecraft/stats/ServerStatisticManager.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.stats; + + import com.google.common.collect.Maps; +@@ -158,13 +159,12 @@ + } + + private Optional> getStat(StatisticWrapper statisticwrapper, String s) { +- Optional optional = Optional.ofNullable(MinecraftKey.tryParse(s)); +- IRegistry iregistry = statisticwrapper.getRegistry(); ++ // CraftBukkit - decompile error start ++ Optional optional = Optional.ofNullable(MinecraftKey.tryParse(s)); ++ IRegistry iregistry = statisticwrapper.getRegistry(); + +- Objects.requireNonNull(iregistry); +- optional = optional.flatMap(iregistry::getOptional); +- Objects.requireNonNull(statisticwrapper); +- return optional.map(statisticwrapper::get); ++ return optional.flatMap(iregistry::getOptional).map(statisticwrapper::get); ++ // CraftBukkit - decompile error end + } + + private static NBTTagCompound fromJson(JsonObject jsonobject) { diff --git a/patch-remap/og/net/minecraft/stats/StatisticManager.patch b/patch-remap/og/net/minecraft/stats/StatisticManager.patch new file mode 100644 index 0000000000..118075d566 --- /dev/null +++ b/patch-remap/og/net/minecraft/stats/StatisticManager.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/stats/StatisticManager.java ++++ b/net/minecraft/stats/StatisticManager.java +@@ -16,6 +16,12 @@ + public void increment(EntityHuman entityhuman, Statistic statistic, int i) { + int j = (int) Math.min((long) this.getValue(statistic) + (long) i, 2147483647L); + ++ // CraftBukkit start - fire Statistic events ++ org.bukkit.event.Cancellable cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.handleStatisticsIncrease(entityhuman, statistic, this.getValue(statistic), j); ++ if (cancellable != null && cancellable.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.setValue(entityhuman, statistic, j); + } + diff --git a/patch-remap/og/net/minecraft/util/SpawnUtil.patch b/patch-remap/og/net/minecraft/util/SpawnUtil.patch new file mode 100644 index 0000000000..150612747c --- /dev/null +++ b/patch-remap/og/net/minecraft/util/SpawnUtil.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/util/SpawnUtil.java ++++ b/net/minecraft/util/SpawnUtil.java +@@ -21,6 +21,12 @@ + public SpawnUtil() {} + + public static Optional trySpawnMob(EntityTypes entitytypes, EnumMobSpawn enummobspawn, WorldServer worldserver, BlockPosition blockposition, int i, int j, int k, SpawnUtil.a spawnutil_a) { ++ // CraftBukkit start ++ return trySpawnMob(entitytypes, enummobspawn, worldserver, blockposition, i, j, k, spawnutil_a, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ public static Optional trySpawnMob(EntityTypes entitytypes, EnumMobSpawn enummobspawn, WorldServer worldserver, BlockPosition blockposition, int i, int j, int k, SpawnUtil.a spawnutil_a, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ // CraftBukkit end + BlockPosition.MutableBlockPosition blockposition_mutableblockposition = blockposition.mutable(); + + for (int l = 0; l < i; ++l) { +@@ -29,11 +35,11 @@ + + blockposition_mutableblockposition.setWithOffset(blockposition, i1, k, j1); + if (worldserver.getWorldBorder().isWithinBounds((BlockPosition) blockposition_mutableblockposition) && moveToPossibleSpawnPosition(worldserver, k, blockposition_mutableblockposition, spawnutil_a)) { +- T t0 = (EntityInsentient) entitytypes.create(worldserver, (NBTTagCompound) null, (Consumer) null, blockposition_mutableblockposition, enummobspawn, false, false); ++ T t0 = entitytypes.create(worldserver, (NBTTagCompound) null, null, blockposition_mutableblockposition, enummobspawn, false, false); // CraftBukkit - decompile error + + if (t0 != null) { + if (t0.checkSpawnRules(worldserver, enummobspawn) && t0.checkSpawnObstruction(worldserver)) { +- worldserver.addFreshEntityWithPassengers(t0); ++ worldserver.addFreshEntityWithPassengers(t0, reason); // CraftBukkit + return Optional.of(t0); + } + diff --git a/patch-remap/og/net/minecraft/util/datafix/DataConverterRegistry.patch b/patch-remap/og/net/minecraft/util/datafix/DataConverterRegistry.patch new file mode 100644 index 0000000000..3990ce056e --- /dev/null +++ b/patch-remap/og/net/minecraft/util/datafix/DataConverterRegistry.patch @@ -0,0 +1,72 @@ +--- a/net/minecraft/util/datafix/DataConverterRegistry.java ++++ b/net/minecraft/util/datafix/DataConverterRegistry.java +@@ -455,6 +455,18 @@ + datafixerbuilder.addFixer(new DataConverterItemFrame(schema44, false)); + Schema schema45 = datafixerbuilder.addSchema(1458, DataConverterRegistry.SAME_NAMESPACED); + ++ // CraftBukkit start ++ datafixerbuilder.addFixer(new com.mojang.datafixers.DataFix(schema45, false) { ++ @Override ++ protected com.mojang.datafixers.TypeRewriteRule makeRule() { ++ return this.fixTypeEverywhereTyped("Player CustomName", this.getInputSchema().getType(DataConverterTypes.PLAYER), (typed) -> { ++ return typed.update(DSL.remainderFinder(), (dynamic) -> { ++ return DataConverterCustomNameEntity.fixTagCustomName(dynamic); ++ }); ++ }); ++ } ++ }); ++ // CraftBukkit end + datafixerbuilder.addFixer(new DataConverterCustomNameEntity(schema45, false)); + datafixerbuilder.addFixer(new DataConverterCustomNameItem(schema45, false)); + datafixerbuilder.addFixer(new DataConverterCustomNameTile(schema45, false)); +@@ -776,12 +788,14 @@ + datafixerbuilder.addFixer(new DataConverterAddChoices(schema130, "Added Glow Squid", DataConverterTypes.ENTITY)); + datafixerbuilder.addFixer(new DataConverterAddChoices(schema130, "Added Glow Item Frame", DataConverterTypes.ENTITY)); + Schema schema131 = datafixerbuilder.addSchema(2690, DataConverterRegistry.SAME_NAMESPACED); +- ImmutableMap immutablemap = ImmutableMap.builder().put("minecraft:weathered_copper_block", "minecraft:oxidized_copper_block").put("minecraft:semi_weathered_copper_block", "minecraft:weathered_copper_block").put("minecraft:lightly_weathered_copper_block", "minecraft:exposed_copper_block").put("minecraft:weathered_cut_copper", "minecraft:oxidized_cut_copper").put("minecraft:semi_weathered_cut_copper", "minecraft:weathered_cut_copper").put("minecraft:lightly_weathered_cut_copper", "minecraft:exposed_cut_copper").put("minecraft:weathered_cut_copper_stairs", "minecraft:oxidized_cut_copper_stairs").put("minecraft:semi_weathered_cut_copper_stairs", "minecraft:weathered_cut_copper_stairs").put("minecraft:lightly_weathered_cut_copper_stairs", "minecraft:exposed_cut_copper_stairs").put("minecraft:weathered_cut_copper_slab", "minecraft:oxidized_cut_copper_slab").put("minecraft:semi_weathered_cut_copper_slab", "minecraft:weathered_cut_copper_slab").put("minecraft:lightly_weathered_cut_copper_slab", "minecraft:exposed_cut_copper_slab").put("minecraft:waxed_semi_weathered_copper", "minecraft:waxed_weathered_copper").put("minecraft:waxed_lightly_weathered_copper", "minecraft:waxed_exposed_copper").put("minecraft:waxed_semi_weathered_cut_copper", "minecraft:waxed_weathered_cut_copper").put("minecraft:waxed_lightly_weathered_cut_copper", "minecraft:waxed_exposed_cut_copper").put("minecraft:waxed_semi_weathered_cut_copper_stairs", "minecraft:waxed_weathered_cut_copper_stairs").put("minecraft:waxed_lightly_weathered_cut_copper_stairs", "minecraft:waxed_exposed_cut_copper_stairs").put("minecraft:waxed_semi_weathered_cut_copper_slab", "minecraft:waxed_weathered_cut_copper_slab").put("minecraft:waxed_lightly_weathered_cut_copper_slab", "minecraft:waxed_exposed_cut_copper_slab").build(); ++ // CraftBukkit - decompile error ++ ImmutableMap immutablemap = ImmutableMap.builder().put("minecraft:weathered_copper_block", "minecraft:oxidized_copper_block").put("minecraft:semi_weathered_copper_block", "minecraft:weathered_copper_block").put("minecraft:lightly_weathered_copper_block", "minecraft:exposed_copper_block").put("minecraft:weathered_cut_copper", "minecraft:oxidized_cut_copper").put("minecraft:semi_weathered_cut_copper", "minecraft:weathered_cut_copper").put("minecraft:lightly_weathered_cut_copper", "minecraft:exposed_cut_copper").put("minecraft:weathered_cut_copper_stairs", "minecraft:oxidized_cut_copper_stairs").put("minecraft:semi_weathered_cut_copper_stairs", "minecraft:weathered_cut_copper_stairs").put("minecraft:lightly_weathered_cut_copper_stairs", "minecraft:exposed_cut_copper_stairs").put("minecraft:weathered_cut_copper_slab", "minecraft:oxidized_cut_copper_slab").put("minecraft:semi_weathered_cut_copper_slab", "minecraft:weathered_cut_copper_slab").put("minecraft:lightly_weathered_cut_copper_slab", "minecraft:exposed_cut_copper_slab").put("minecraft:waxed_semi_weathered_copper", "minecraft:waxed_weathered_copper").put("minecraft:waxed_lightly_weathered_copper", "minecraft:waxed_exposed_copper").put("minecraft:waxed_semi_weathered_cut_copper", "minecraft:waxed_weathered_cut_copper").put("minecraft:waxed_lightly_weathered_cut_copper", "minecraft:waxed_exposed_cut_copper").put("minecraft:waxed_semi_weathered_cut_copper_stairs", "minecraft:waxed_weathered_cut_copper_stairs").put("minecraft:waxed_lightly_weathered_cut_copper_stairs", "minecraft:waxed_exposed_cut_copper_stairs").put("minecraft:waxed_semi_weathered_cut_copper_slab", "minecraft:waxed_weathered_cut_copper_slab").put("minecraft:waxed_lightly_weathered_cut_copper_slab", "minecraft:waxed_exposed_cut_copper_slab").build(); + + datafixerbuilder.addFixer(DataConverterItemName.create(schema131, "Renamed copper block items to new oxidized terms", createRenamer(immutablemap))); + datafixerbuilder.addFixer(BlockRenameFixWithJigsaw.create(schema131, "Renamed copper blocks to new oxidized terms", createRenamer(immutablemap))); + Schema schema132 = datafixerbuilder.addSchema(2691, DataConverterRegistry.SAME_NAMESPACED); +- ImmutableMap immutablemap1 = ImmutableMap.builder().put("minecraft:waxed_copper", "minecraft:waxed_copper_block").put("minecraft:oxidized_copper_block", "minecraft:oxidized_copper").put("minecraft:weathered_copper_block", "minecraft:weathered_copper").put("minecraft:exposed_copper_block", "minecraft:exposed_copper").build(); ++ // CraftBukkit - decompile error ++ ImmutableMap immutablemap1 = ImmutableMap.builder().put("minecraft:waxed_copper", "minecraft:waxed_copper_block").put("minecraft:oxidized_copper_block", "minecraft:oxidized_copper").put("minecraft:weathered_copper_block", "minecraft:weathered_copper").put("minecraft:exposed_copper_block", "minecraft:exposed_copper").build(); + + datafixerbuilder.addFixer(DataConverterItemName.create(schema132, "Rename copper item suffixes", createRenamer(immutablemap1))); + datafixerbuilder.addFixer(BlockRenameFixWithJigsaw.create(schema132, "Rename copper blocks suffixes", createRenamer(immutablemap1))); +@@ -789,7 +803,8 @@ + + datafixerbuilder.addFixer(new AddFlagIfNotPresentFix(schema133, DataConverterTypes.WORLD_GEN_SETTINGS, "has_increased_height_already", false)); + Schema schema134 = datafixerbuilder.addSchema(2696, DataConverterRegistry.SAME_NAMESPACED); +- ImmutableMap immutablemap2 = ImmutableMap.builder().put("minecraft:grimstone", "minecraft:deepslate").put("minecraft:grimstone_slab", "minecraft:cobbled_deepslate_slab").put("minecraft:grimstone_stairs", "minecraft:cobbled_deepslate_stairs").put("minecraft:grimstone_wall", "minecraft:cobbled_deepslate_wall").put("minecraft:polished_grimstone", "minecraft:polished_deepslate").put("minecraft:polished_grimstone_slab", "minecraft:polished_deepslate_slab").put("minecraft:polished_grimstone_stairs", "minecraft:polished_deepslate_stairs").put("minecraft:polished_grimstone_wall", "minecraft:polished_deepslate_wall").put("minecraft:grimstone_tiles", "minecraft:deepslate_tiles").put("minecraft:grimstone_tile_slab", "minecraft:deepslate_tile_slab").put("minecraft:grimstone_tile_stairs", "minecraft:deepslate_tile_stairs").put("minecraft:grimstone_tile_wall", "minecraft:deepslate_tile_wall").put("minecraft:grimstone_bricks", "minecraft:deepslate_bricks").put("minecraft:grimstone_brick_slab", "minecraft:deepslate_brick_slab").put("minecraft:grimstone_brick_stairs", "minecraft:deepslate_brick_stairs").put("minecraft:grimstone_brick_wall", "minecraft:deepslate_brick_wall").put("minecraft:chiseled_grimstone", "minecraft:chiseled_deepslate").build(); ++ // CraftBukkit - decompile error ++ ImmutableMap immutablemap2 = ImmutableMap.builder().put("minecraft:grimstone", "minecraft:deepslate").put("minecraft:grimstone_slab", "minecraft:cobbled_deepslate_slab").put("minecraft:grimstone_stairs", "minecraft:cobbled_deepslate_stairs").put("minecraft:grimstone_wall", "minecraft:cobbled_deepslate_wall").put("minecraft:polished_grimstone", "minecraft:polished_deepslate").put("minecraft:polished_grimstone_slab", "minecraft:polished_deepslate_slab").put("minecraft:polished_grimstone_stairs", "minecraft:polished_deepslate_stairs").put("minecraft:polished_grimstone_wall", "minecraft:polished_deepslate_wall").put("minecraft:grimstone_tiles", "minecraft:deepslate_tiles").put("minecraft:grimstone_tile_slab", "minecraft:deepslate_tile_slab").put("minecraft:grimstone_tile_stairs", "minecraft:deepslate_tile_stairs").put("minecraft:grimstone_tile_wall", "minecraft:deepslate_tile_wall").put("minecraft:grimstone_bricks", "minecraft:deepslate_bricks").put("minecraft:grimstone_brick_slab", "minecraft:deepslate_brick_slab").put("minecraft:grimstone_brick_stairs", "minecraft:deepslate_brick_stairs").put("minecraft:grimstone_brick_wall", "minecraft:deepslate_brick_wall").put("minecraft:chiseled_grimstone", "minecraft:chiseled_deepslate").build(); + + datafixerbuilder.addFixer(DataConverterItemName.create(schema134, "Renamed grimstone block items to deepslate", createRenamer(immutablemap2))); + datafixerbuilder.addFixer(BlockRenameFixWithJigsaw.create(schema134, "Renamed grimstone blocks to deepslate", createRenamer(immutablemap2))); +@@ -876,10 +891,11 @@ + datafixerbuilder.addFixer(new DataConverterAddChoices(schema159, "Added Allay", DataConverterTypes.ENTITY)); + Schema schema160 = datafixerbuilder.addSchema(3084, DataConverterRegistry.SAME_NAMESPACED); + +- datafixerbuilder.addFixer(new NamespacedTypeRenameFix(schema160, "game_event_renames_3084", DataConverterTypes.GAME_EVENT_NAME, createRenamer(ImmutableMap.builder().put("minecraft:block_press", "minecraft:block_activate").put("minecraft:block_switch", "minecraft:block_activate").put("minecraft:block_unpress", "minecraft:block_deactivate").put("minecraft:block_unswitch", "minecraft:block_deactivate").put("minecraft:drinking_finish", "minecraft:drink").put("minecraft:elytra_free_fall", "minecraft:elytra_glide").put("minecraft:entity_damaged", "minecraft:entity_damage").put("minecraft:entity_dying", "minecraft:entity_die").put("minecraft:entity_killed", "minecraft:entity_die").put("minecraft:mob_interact", "minecraft:entity_interact").put("minecraft:ravager_roar", "minecraft:entity_roar").put("minecraft:ring_bell", "minecraft:block_change").put("minecraft:shulker_close", "minecraft:container_close").put("minecraft:shulker_open", "minecraft:container_open").put("minecraft:wolf_shaking", "minecraft:entity_shake").build()))); ++ // CraftBukkit - decompile error ++ datafixerbuilder.addFixer(new NamespacedTypeRenameFix(schema160, "game_event_renames_3084", DataConverterTypes.GAME_EVENT_NAME, createRenamer(ImmutableMap.builder().put("minecraft:block_press", "minecraft:block_activate").put("minecraft:block_switch", "minecraft:block_activate").put("minecraft:block_unpress", "minecraft:block_deactivate").put("minecraft:block_unswitch", "minecraft:block_deactivate").put("minecraft:drinking_finish", "minecraft:drink").put("minecraft:elytra_free_fall", "minecraft:elytra_glide").put("minecraft:entity_damaged", "minecraft:entity_damage").put("minecraft:entity_dying", "minecraft:entity_die").put("minecraft:entity_killed", "minecraft:entity_die").put("minecraft:mob_interact", "minecraft:entity_interact").put("minecraft:ravager_roar", "minecraft:entity_roar").put("minecraft:ring_bell", "minecraft:block_change").put("minecraft:shulker_close", "minecraft:container_close").put("minecraft:shulker_open", "minecraft:container_open").put("minecraft:wolf_shaking", "minecraft:entity_shake").build()))); + Schema schema161 = datafixerbuilder.addSchema(3086, DataConverterRegistry.SAME_NAMESPACED); + TypeReference typereference = DataConverterTypes.ENTITY; +- Int2ObjectOpenHashMap int2objectopenhashmap = (Int2ObjectOpenHashMap) SystemUtils.make(new Int2ObjectOpenHashMap(), (int2objectopenhashmap1) -> { ++ Int2ObjectOpenHashMap int2objectopenhashmap = (Int2ObjectOpenHashMap) SystemUtils.make(new Int2ObjectOpenHashMap(), (int2objectopenhashmap1) -> { // CraftBukkit - decompile error + int2objectopenhashmap1.defaultReturnValue("minecraft:tabby"); + int2objectopenhashmap1.put(0, "minecraft:tabby"); + int2objectopenhashmap1.put(1, "minecraft:black"); +@@ -896,7 +912,8 @@ + + Objects.requireNonNull(int2objectopenhashmap); + datafixerbuilder.addFixer(new EntityVariantFix(schema161, "Change cat variant type", typereference, "minecraft:cat", "CatType", int2objectopenhashmap::get)); +- ImmutableMap immutablemap3 = ImmutableMap.builder().put("textures/entity/cat/tabby.png", "minecraft:tabby").put("textures/entity/cat/black.png", "minecraft:black").put("textures/entity/cat/red.png", "minecraft:red").put("textures/entity/cat/siamese.png", "minecraft:siamese").put("textures/entity/cat/british_shorthair.png", "minecraft:british").put("textures/entity/cat/calico.png", "minecraft:calico").put("textures/entity/cat/persian.png", "minecraft:persian").put("textures/entity/cat/ragdoll.png", "minecraft:ragdoll").put("textures/entity/cat/white.png", "minecraft:white").put("textures/entity/cat/jellie.png", "minecraft:jellie").put("textures/entity/cat/all_black.png", "minecraft:all_black").build(); ++ // CraftBukkit - decompile error ++ ImmutableMap immutablemap3 = ImmutableMap.builder().put("textures/entity/cat/tabby.png", "minecraft:tabby").put("textures/entity/cat/black.png", "minecraft:black").put("textures/entity/cat/red.png", "minecraft:red").put("textures/entity/cat/siamese.png", "minecraft:siamese").put("textures/entity/cat/british_shorthair.png", "minecraft:british").put("textures/entity/cat/calico.png", "minecraft:calico").put("textures/entity/cat/persian.png", "minecraft:persian").put("textures/entity/cat/ragdoll.png", "minecraft:ragdoll").put("textures/entity/cat/white.png", "minecraft:white").put("textures/entity/cat/jellie.png", "minecraft:jellie").put("textures/entity/cat/all_black.png", "minecraft:all_black").build(); + + datafixerbuilder.addFixer(new CriteriaRenameFix(schema161, "Migrate cat variant advancement", "minecraft:husbandry/complete_catalogue", (s) -> { + return (String) immutablemap3.getOrDefault(s, s); diff --git a/patch-remap/og/net/minecraft/util/datafix/fixes/DataConverterFlatten.patch b/patch-remap/og/net/minecraft/util/datafix/fixes/DataConverterFlatten.patch new file mode 100644 index 0000000000..6916dff542 --- /dev/null +++ b/patch-remap/og/net/minecraft/util/datafix/fixes/DataConverterFlatten.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/util/datafix/fixes/DataConverterFlatten.java ++++ b/net/minecraft/util/datafix/fixes/DataConverterFlatten.java +@@ -376,7 +376,7 @@ + Typed typed2 = typed.getOrCreateTyped(opticfinder1); + Dynamic dynamic1 = (Dynamic) typed2.get(DSL.remainderFinder()); + +- dynamic1 = dynamic1.set("Damage", dynamic1.createInt(i)); ++ if (i != 0) dynamic1 = dynamic1.set("Damage", dynamic1.createInt(i)); // CraftBukkit + typed1 = typed1.set(opticfinder1, typed2.set(DSL.remainderFinder(), dynamic1)); + } + diff --git a/patch-remap/og/net/minecraft/util/datafix/fixes/DataConverterMap.patch b/patch-remap/og/net/minecraft/util/datafix/fixes/DataConverterMap.patch new file mode 100644 index 0000000000..41b8ab111a --- /dev/null +++ b/patch-remap/og/net/minecraft/util/datafix/fixes/DataConverterMap.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/util/datafix/fixes/DataConverterMap.java ++++ b/net/minecraft/util/datafix/fixes/DataConverterMap.java +@@ -32,7 +32,7 @@ + Typed typed1 = typed.getOrCreateTyped(opticfinder1); + Dynamic dynamic1 = (Dynamic) typed1.get(DSL.remainderFinder()); + +- dynamic1 = dynamic1.set("map", dynamic1.createInt(dynamic.get("Damage").asInt(0))); ++ if (!dynamic1.getElement("map").result().isPresent()) dynamic1 = dynamic1.set("map", dynamic1.createInt(dynamic.get("Damage").asInt(0))); // CraftBukkit + return typed.set(opticfinder1, typed1.set(DSL.remainderFinder(), dynamic1)); + } else { + return typed; diff --git a/patch-remap/og/net/minecraft/util/worldupdate/WorldUpgrader.patch b/patch-remap/og/net/minecraft/util/worldupdate/WorldUpgrader.patch new file mode 100644 index 0000000000..3a08d57bb0 --- /dev/null +++ b/patch-remap/og/net/minecraft/util/worldupdate/WorldUpgrader.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/util/worldupdate/WorldUpgrader.java ++++ b/net/minecraft/util/worldupdate/WorldUpgrader.java +@@ -66,7 +66,7 @@ + + public WorldUpgrader(Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, IRegistry iregistry, boolean flag) { + this.dimensions = iregistry; +- this.levels = (Set) iregistry.registryKeySet().stream().map(Registries::levelStemToLevel).collect(Collectors.toUnmodifiableSet()); ++ this.levels = (Set) java.util.stream.Stream.of(convertable_conversionsession.dimensionType).map(Registries::levelStemToLevel).collect(Collectors.toUnmodifiableSet()); // CraftBukkit + this.eraseCache = flag; + this.dataFixer = datafixer; + this.levelStorage = convertable_conversionsession; +@@ -145,9 +145,9 @@ + if (nbttagcompound != null) { + int j = IChunkLoader.getVersion(nbttagcompound); + ChunkGenerator chunkgenerator = ((WorldDimension) this.dimensions.getOrThrow(Registries.levelToLevelStem(resourcekey2))).generator(); +- NBTTagCompound nbttagcompound1 = ichunkloader.upgradeChunkTag(resourcekey2, () -> { ++ NBTTagCompound nbttagcompound1 = ichunkloader.upgradeChunkTag(Registries.levelToLevelStem(resourcekey2), () -> { // CraftBukkit + return this.overworldDataStorage; +- }, nbttagcompound, chunkgenerator.getTypeNameForDataFixer()); ++ }, nbttagcompound, chunkgenerator.getTypeNameForDataFixer(), chunkcoordintpair, null); // CraftBukkit + ChunkCoordIntPair chunkcoordintpair1 = new ChunkCoordIntPair(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); + + if (!chunkcoordintpair1.equals(chunkcoordintpair)) { diff --git a/patch-remap/og/net/minecraft/world/ChestLock.patch b/patch-remap/og/net/minecraft/world/ChestLock.patch new file mode 100644 index 0000000000..424ef2ca00 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/ChestLock.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/ChestLock.java ++++ b/net/minecraft/world/ChestLock.java +@@ -4,6 +4,11 @@ + import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.ChatColor; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++// CraftBukkit end ++ + @Immutable + public class ChestLock { + +@@ -16,7 +21,19 @@ + } + + public boolean unlocksWith(ItemStack itemstack) { +- return this.key.isEmpty() || !itemstack.isEmpty() && itemstack.hasCustomHoverName() && this.key.equals(itemstack.getHoverName().getString()); ++ // CraftBukkit start - SPIGOT-6307: Check for color codes if the lock contains color codes ++ if (this.key.isEmpty()) return true; ++ if (!itemstack.isEmpty() && itemstack.hasCustomHoverName()) { ++ if (this.key.indexOf(ChatColor.COLOR_CHAR) == -1) { ++ // The lock key contains no color codes, so let's ignore colors in the item display name (vanilla Minecraft behavior): ++ return this.key.equals(itemstack.getHoverName().getString()); ++ } else { ++ // The lock key contains color codes, so let's take them into account: ++ return this.key.equals(CraftChatMessage.fromComponent(itemstack.getHoverName())); ++ } ++ } ++ return false; ++ // CraftBukkit end + } + + public void addToTag(NBTTagCompound nbttagcompound) { diff --git a/patch-remap/og/net/minecraft/world/IInventory.patch b/patch-remap/og/net/minecraft/world/IInventory.patch new file mode 100644 index 0000000000..8fecf72098 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/IInventory.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/IInventory.java ++++ b/net/minecraft/world/IInventory.java +@@ -9,6 +9,11 @@ + import net.minecraft.world.level.World; + import net.minecraft.world.level.block.entity.TileEntity; + ++// CraftBukkit start ++import net.minecraft.world.item.crafting.RecipeHolder; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++// CraftBukkit end ++ + public interface IInventory extends Clearable { + + int LARGE_MAX_STACK_SIZE = 64; +@@ -26,9 +31,7 @@ + + void setItem(int i, ItemStack itemstack); + +- default int getMaxStackSize() { +- return 64; +- } ++ int getMaxStackSize(); // CraftBukkit + + void setChanged(); + +@@ -88,4 +91,29 @@ + + return world == null ? false : (world.getBlockEntity(blockposition) != tileentity ? false : entityhuman.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) <= (double) (i * i)); + } ++ ++ // CraftBukkit start ++ java.util.List getContents(); ++ ++ void onOpen(CraftHumanEntity who); ++ ++ void onClose(CraftHumanEntity who); ++ ++ java.util.List getViewers(); ++ ++ org.bukkit.inventory.InventoryHolder getOwner(); ++ ++ void setMaxStackSize(int size); ++ ++ org.bukkit.Location getLocation(); ++ ++ default RecipeHolder getCurrentRecipe() { ++ return null; ++ } ++ ++ default void setCurrentRecipe(RecipeHolder recipe) { ++ } ++ ++ int MAX_STACK = 64; ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/InventoryLargeChest.patch b/patch-remap/og/net/minecraft/world/InventoryLargeChest.patch new file mode 100644 index 0000000000..871fff1b74 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/InventoryLargeChest.patch @@ -0,0 +1,74 @@ +--- a/net/minecraft/world/InventoryLargeChest.java ++++ b/net/minecraft/world/InventoryLargeChest.java +@@ -3,11 +3,62 @@ + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import org.bukkit.Location; ++ ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class InventoryLargeChest implements IInventory { + + public final IInventory container1; + public final IInventory container2; + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ ++ public List getContents() { ++ List result = new ArrayList(this.getContainerSize()); ++ for (int i = 0; i < this.getContainerSize(); i++) { ++ result.add(this.getItem(i)); ++ } ++ return result; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ this.container1.onOpen(who); ++ this.container2.onOpen(who); ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ this.container1.onClose(who); ++ this.container2.onClose(who); ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return null; // This method won't be called since CraftInventoryDoubleChest doesn't defer to here ++ } ++ ++ public void setMaxStackSize(int size) { ++ this.container1.setMaxStackSize(size); ++ this.container2.setMaxStackSize(size); ++ } ++ ++ @Override ++ public Location getLocation() { ++ return container1.getLocation(); // TODO: right? ++ } ++ // CraftBukkit end ++ + public InventoryLargeChest(IInventory iinventory, IInventory iinventory1) { + this.container1 = iinventory; + this.container2 = iinventory1; +@@ -54,7 +105,7 @@ + + @Override + public int getMaxStackSize() { +- return this.container1.getMaxStackSize(); ++ return Math.min(this.container1.getMaxStackSize(), this.container2.getMaxStackSize()); // CraftBukkit - check both sides + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/InventorySubcontainer.patch b/patch-remap/og/net/minecraft/world/InventorySubcontainer.patch new file mode 100644 index 0000000000..c77b2aa78e --- /dev/null +++ b/patch-remap/og/net/minecraft/world/InventorySubcontainer.patch @@ -0,0 +1,75 @@ +--- a/net/minecraft/world/InventorySubcontainer.java ++++ b/net/minecraft/world/InventorySubcontainer.java +@@ -14,6 +14,12 @@ + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class InventorySubcontainer implements IInventory, AutoRecipeOutput { + + private final int size; +@@ -21,7 +27,59 @@ + @Nullable + private List listeners; + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ protected org.bukkit.inventory.InventoryHolder bukkitOwner; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return bukkitOwner; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return null; ++ } ++ ++ public InventorySubcontainer(InventorySubcontainer original) { ++ this(original.size); ++ for (int slot = 0; slot < original.size; slot++) { ++ this.items.set(slot, original.items.get(slot).copy()); ++ } ++ } ++ + public InventorySubcontainer(int i) { ++ this(i, null); ++ } ++ ++ public InventorySubcontainer(int i, org.bukkit.inventory.InventoryHolder owner) { ++ this.bukkitOwner = owner; ++ // CraftBukkit end + this.size = i; + this.items = NonNullList.withSize(i, ItemStack.EMPTY); + } diff --git a/patch-remap/og/net/minecraft/world/damagesource/DamageSource.patch b/patch-remap/og/net/minecraft/world/damagesource/DamageSource.patch new file mode 100644 index 0000000000..d05a3b1119 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/damagesource/DamageSource.patch @@ -0,0 +1,41 @@ +--- a/net/minecraft/world/damagesource/DamageSource.java ++++ b/net/minecraft/world/damagesource/DamageSource.java +@@ -20,6 +20,38 @@ + private final Entity directEntity; + @Nullable + private final Vec3D damageSourcePosition; ++ // CraftBukkit start ++ private boolean sweep; ++ private boolean melting; ++ private boolean poison; ++ ++ public boolean isSweep() { ++ return sweep; ++ } ++ ++ public DamageSource sweep() { ++ this.sweep = true; ++ return this; ++ } ++ ++ public boolean isMelting() { ++ return melting; ++ } ++ ++ public DamageSource melting() { ++ this.melting = true; ++ return this; ++ } ++ ++ public boolean isPoison() { ++ return poison; ++ } ++ ++ public DamageSource poison() { ++ this.poison = true; ++ return this; ++ } ++ // CraftBukkit end + + public String toString() { + return "DamageSource (" + this.type().msgId() + ")"; diff --git a/patch-remap/og/net/minecraft/world/damagesource/DamageSources.patch b/patch-remap/og/net/minecraft/world/damagesource/DamageSources.patch new file mode 100644 index 0000000000..55ecabb4d9 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/damagesource/DamageSources.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/damagesource/DamageSources.java ++++ b/net/minecraft/world/damagesource/DamageSources.java +@@ -41,9 +41,15 @@ + private final DamageSource stalagmite; + private final DamageSource outsideBorder; + private final DamageSource genericKill; ++ // CraftBukkit start ++ public final DamageSource melting; ++ public final DamageSource poison; + + public DamageSources(IRegistryCustom iregistrycustom) { + this.damageTypes = iregistrycustom.registryOrThrow(Registries.DAMAGE_TYPE); ++ this.melting = this.source(DamageTypes.ON_FIRE).melting(); ++ this.poison = this.source(DamageTypes.MAGIC).poison(); ++ // CraftBukkit end + this.inFire = this.source(DamageTypes.IN_FIRE); + this.lightningBolt = this.source(DamageTypes.LIGHTNING_BOLT); + this.onFire = this.source(DamageTypes.ON_FIRE); diff --git a/patch-remap/og/net/minecraft/world/effect/HealOrHarmMobEffect.patch b/patch-remap/og/net/minecraft/world/effect/HealOrHarmMobEffect.patch new file mode 100644 index 0000000000..f4b437045a --- /dev/null +++ b/patch-remap/og/net/minecraft/world/effect/HealOrHarmMobEffect.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/effect/HealOrHarmMobEffect.java ++++ b/net/minecraft/world/effect/HealOrHarmMobEffect.java +@@ -17,7 +17,7 @@ + public void applyEffectTick(EntityLiving entityliving, int i) { + super.applyEffectTick(entityliving, i); + if (this.isHarm == entityliving.isInvertedHealAndHarm()) { +- entityliving.heal((float) Math.max(4 << i, 0)); ++ entityliving.heal((float) Math.max(4 << i, 0), org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.MAGIC); // CraftBukkit + } else { + entityliving.hurt(entityliving.damageSources().magic(), (float) (6 << i)); + } +@@ -30,7 +30,7 @@ + + if (this.isHarm == entityliving.isInvertedHealAndHarm()) { + j = (int) (d0 * (double) (4 << i) + 0.5D); +- entityliving.heal((float) j); ++ entityliving.heal((float) j, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.MAGIC); // CraftBukkit + } else { + j = (int) (d0 * (double) (6 << i) + 0.5D); + if (entity == null) { diff --git a/patch-remap/og/net/minecraft/world/effect/HungerMobEffect.patch b/patch-remap/og/net/minecraft/world/effect/HungerMobEffect.patch new file mode 100644 index 0000000000..65962d9d09 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/effect/HungerMobEffect.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/effect/HungerMobEffect.java ++++ b/net/minecraft/world/effect/HungerMobEffect.java +@@ -15,7 +15,7 @@ + if (entityliving instanceof EntityHuman) { + EntityHuman entityhuman = (EntityHuman) entityliving; + +- entityhuman.causeFoodExhaustion(0.005F * (float) (i + 1)); ++ entityhuman.causeFoodExhaustion(0.005F * (float) (i + 1), org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.HUNGER_EFFECT); // CraftBukkit - EntityExhaustionEvent + } + + } diff --git a/patch-remap/og/net/minecraft/world/effect/MobEffectUtil.patch b/patch-remap/og/net/minecraft/world/effect/MobEffectUtil.patch new file mode 100644 index 0000000000..f243643eea --- /dev/null +++ b/patch-remap/og/net/minecraft/world/effect/MobEffectUtil.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/world/effect/MobEffectUtil.java ++++ b/net/minecraft/world/effect/MobEffectUtil.java +@@ -49,13 +49,19 @@ + } + + public static List addEffectToPlayersAround(WorldServer worldserver, @Nullable Entity entity, Vec3D vec3d, double d0, MobEffect mobeffect, int i) { ++ // CraftBukkit start ++ return addEffectToPlayersAround(worldserver, entity, vec3d, d0, mobeffect, i, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public static List addEffectToPlayersAround(WorldServer worldserver, @Nullable Entity entity, Vec3D vec3d, double d0, MobEffect mobeffect, int i, org.bukkit.event.entity.EntityPotionEffectEvent.Cause cause) { ++ // CraftBukkit end + MobEffectList mobeffectlist = mobeffect.getEffect(); + List list = worldserver.getPlayers((entityplayer) -> { + return entityplayer.gameMode.isSurvival() && (entity == null || !entity.isAlliedTo((Entity) entityplayer)) && vec3d.closerThan(entityplayer.position(), d0) && (!entityplayer.hasEffect(mobeffectlist) || entityplayer.getEffect(mobeffectlist).getAmplifier() < mobeffect.getAmplifier() || entityplayer.getEffect(mobeffectlist).endsWithin(i - 1)); + }); + + list.forEach((entityplayer) -> { +- entityplayer.addEffect(new MobEffect(mobeffect), entity); ++ entityplayer.addEffect(new MobEffect(mobeffect), entity, cause); // CraftBukkit + }); + return list; + } diff --git a/patch-remap/og/net/minecraft/world/effect/PoisonMobEffect.patch b/patch-remap/og/net/minecraft/world/effect/PoisonMobEffect.patch new file mode 100644 index 0000000000..8ad1602201 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/effect/PoisonMobEffect.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/effect/PoisonMobEffect.java ++++ b/net/minecraft/world/effect/PoisonMobEffect.java +@@ -12,7 +12,7 @@ + public void applyEffectTick(EntityLiving entityliving, int i) { + super.applyEffectTick(entityliving, i); + if (entityliving.getHealth() > 1.0F) { +- entityliving.hurt(entityliving.damageSources().magic(), 1.0F); ++ entityliving.hurt(entityliving.damageSources().poison, 1.0F); // CraftBukkit - DamageSource.MAGIC -> CraftEventFactory.POISON + } + + } diff --git a/patch-remap/og/net/minecraft/world/effect/RegenerationMobEffect.patch b/patch-remap/og/net/minecraft/world/effect/RegenerationMobEffect.patch new file mode 100644 index 0000000000..3c8b576194 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/effect/RegenerationMobEffect.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/effect/RegenerationMobEffect.java ++++ b/net/minecraft/world/effect/RegenerationMobEffect.java +@@ -12,7 +12,7 @@ + public void applyEffectTick(EntityLiving entityliving, int i) { + super.applyEffectTick(entityliving, i); + if (entityliving.getHealth() < entityliving.getMaxHealth()) { +- entityliving.heal(1.0F); ++ entityliving.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.MAGIC_REGEN); // CraftBukkit + } + + } diff --git a/patch-remap/og/net/minecraft/world/effect/SaturationMobEffect.patch b/patch-remap/og/net/minecraft/world/effect/SaturationMobEffect.patch new file mode 100644 index 0000000000..cd7fcfc9ce --- /dev/null +++ b/patch-remap/og/net/minecraft/world/effect/SaturationMobEffect.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/effect/SaturationMobEffect.java ++++ b/net/minecraft/world/effect/SaturationMobEffect.java +@@ -3,6 +3,11 @@ + import net.minecraft.world.entity.EntityLiving; + import net.minecraft.world.entity.player.EntityHuman; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + class SaturationMobEffect extends InstantMobEffect { + + protected SaturationMobEffect(MobEffectInfo mobeffectinfo, int i) { +@@ -15,7 +20,15 @@ + if (!entityliving.level().isClientSide && entityliving instanceof EntityHuman) { + EntityHuman entityhuman = (EntityHuman) entityliving; + +- entityhuman.getFoodData().eat(i + 1, 1.0F); ++ // CraftBukkit start ++ int oldFoodLevel = entityhuman.getFoodData().foodLevel; ++ org.bukkit.event.entity.FoodLevelChangeEvent event = CraftEventFactory.callFoodLevelChangeEvent(entityhuman, i + 1 + oldFoodLevel); ++ if (!event.isCancelled()) { ++ entityhuman.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, 1.0F); ++ } ++ ++ ((CraftPlayer) entityhuman.getBukkitEntity()).sendHealthUpdate(); ++ // CraftBukkit end + } + + } diff --git a/patch-remap/og/net/minecraft/world/entity/Entity.patch b/patch-remap/og/net/minecraft/world/entity/Entity.patch new file mode 100644 index 0000000000..ce4f7224e8 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/Entity.patch @@ -0,0 +1,930 @@ +--- a/net/minecraft/world/entity/Entity.java ++++ b/net/minecraft/world/entity/Entity.java +@@ -126,8 +126,65 @@ + import org.joml.Vector3f; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.world.level.dimension.WorldDimension; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.Server; ++import org.bukkit.block.BlockFace; ++import org.bukkit.command.CommandSender; ++import org.bukkit.craftbukkit.event.CraftPortalEvent; ++import org.bukkit.entity.Hanging; ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.entity.Vehicle; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.hanging.HangingBreakByEntityEvent; ++import org.bukkit.event.vehicle.VehicleBlockCollisionEvent; ++import org.bukkit.event.vehicle.VehicleEnterEvent; ++import org.bukkit.event.vehicle.VehicleExitEvent; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.entity.CraftEntity; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.Pose; ++import org.bukkit.event.entity.EntityAirChangeEvent; ++import org.bukkit.event.entity.EntityCombustEvent; ++import org.bukkit.event.entity.EntityDropItemEvent; ++import org.bukkit.event.entity.EntityPortalEvent; ++import org.bukkit.event.entity.EntityPoseChangeEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++import org.bukkit.plugin.PluginManager; ++// CraftBukkit end ++ + public abstract class Entity implements INamableTileEntity, EntityAccess, ICommandListener, ScoreHolder { + ++ // CraftBukkit start ++ private static final int CURRENT_LEVEL = 2; ++ static boolean isLevelAtLeast(NBTTagCompound tag, int level) { ++ return tag.contains("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; ++ } ++ ++ private CraftEntity bukkitEntity; ++ ++ public CraftEntity getBukkitEntity() { ++ if (bukkitEntity == null) { ++ bukkitEntity = CraftEntity.getEntity(level.getCraftServer(), this); ++ } ++ return bukkitEntity; ++ } ++ ++ @Override ++ public CommandSender getBukkitSender(CommandListenerWrapper wrapper) { ++ return getBukkitEntity(); ++ } ++ ++ // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ public int getDefaultMaxAirSupply() { ++ return TOTAL_AIR_SUPPLY; ++ } ++ // CraftBukkit end ++ + private static final Logger LOGGER = LogUtils.getLogger(); + public static final String ID_TAG = "id"; + public static final String PASSENGERS_TAG = "Passengers"; +@@ -242,6 +299,29 @@ + public boolean hasVisualFire; + @Nullable + private IBlockData feetBlockState; ++ // CraftBukkit start ++ public boolean persist = true; ++ public boolean visibleByDefault = true; ++ public boolean valid; ++ public boolean inWorld = false; ++ public boolean generation; ++ public int maxAirTicks = getDefaultMaxAirSupply(); // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only ++ public boolean lastDamageCancelled; // SPIGOT-5339, SPIGOT-6252, SPIGOT-6777: Keep track if the event was canceled ++ public boolean persistentInvisibility = false; ++ public BlockPosition lastLavaContact; ++ // Marks an entity, that it was removed by a plugin via Entity#remove ++ // Main use case currently is for SPIGOT-7487, preventing dropping of leash when leash is removed ++ public boolean pluginRemoved = false; ++ ++ public float getBukkitYaw() { ++ return this.yRot; ++ } ++ ++ public boolean isChunkLoaded() { ++ return level.hasChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); ++ } ++ // CraftBukkit end + + public Entity(EntityTypes entitytypes, World world) { + this.id = Entity.ENTITY_COUNTER.incrementAndGet(); +@@ -375,6 +455,12 @@ + public void onClientRemoval() {} + + public void setPose(EntityPose entitypose) { ++ // CraftBukkit start ++ if (entitypose == this.getPose()) { ++ return; ++ } ++ this.level.getCraftServer().getPluginManager().callEvent(new EntityPoseChangeEvent(this.getBukkitEntity(), Pose.values()[entitypose.ordinal()])); ++ // CraftBukkit end + this.entityData.set(Entity.DATA_POSE, entitypose); + } + +@@ -399,6 +485,33 @@ + } + + protected void setRot(float f, float f1) { ++ // CraftBukkit start - yaw was sometimes set to NaN, so we need to set it back to 0 ++ if (Float.isNaN(f)) { ++ f = 0; ++ } ++ ++ if (f == Float.POSITIVE_INFINITY || f == Float.NEGATIVE_INFINITY) { ++ if (this instanceof EntityPlayer) { ++ this.level.getCraftServer().getLogger().warning(this.getScoreboardName() + " was caught trying to crash the server with an invalid yaw"); ++ ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Infinite yaw (Hacking?)"); ++ } ++ f = 0; ++ } ++ ++ // pitch was sometimes set to NaN, so we need to set it back to 0 ++ if (Float.isNaN(f1)) { ++ f1 = 0; ++ } ++ ++ if (f1 == Float.POSITIVE_INFINITY || f1 == Float.NEGATIVE_INFINITY) { ++ if (this instanceof EntityPlayer) { ++ this.level.getCraftServer().getLogger().warning(this.getScoreboardName() + " was caught trying to crash the server with an invalid pitch"); ++ ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Infinite pitch (Hacking?)"); ++ } ++ f1 = 0; ++ } ++ // CraftBukkit end ++ + this.setYRot(f % 360.0F); + this.setXRot(f1 % 360.0F); + } +@@ -440,6 +553,15 @@ + this.baseTick(); + } + ++ // CraftBukkit start ++ public void postTick() { ++ // No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle ++ if (!(this instanceof EntityPlayer)) { ++ this.handleNetherPortal(); ++ } ++ } ++ // CraftBukkit end ++ + public void baseTick() { + this.level().getProfiler().push("entityBaseTick"); + this.feetBlockState = null; +@@ -454,7 +576,7 @@ + this.walkDistO = this.walkDist; + this.xRotO = this.getXRot(); + this.yRotO = this.getYRot(); +- this.handleNetherPortal(); ++ if (this instanceof EntityPlayer) this.handleNetherPortal(); // CraftBukkit - // Moved up to postTick + if (this.canSpawnSprintParticle()) { + this.spawnSprintParticle(); + } +@@ -489,6 +611,10 @@ + if (this.isInLava()) { + this.lavaHurt(); + this.fallDistance *= 0.5F; ++ // CraftBukkit start ++ } else { ++ this.lastLavaContact = null; ++ // CraftBukkit end + } + + this.checkBelowWorld(); +@@ -540,15 +666,48 @@ + + public void lavaHurt() { + if (!this.fireImmune()) { +- this.setSecondsOnFire(15); ++ // CraftBukkit start - Fallen in lava TODO: this event spams! ++ if (this instanceof EntityLiving && remainingFireTicks <= 0) { ++ // not on fire yet ++ org.bukkit.block.Block damager = (lastLavaContact == null) ? null : org.bukkit.craftbukkit.block.CraftBlock.at(level, lastLavaContact); ++ org.bukkit.entity.Entity damagee = this.getBukkitEntity(); ++ EntityCombustEvent combustEvent = new org.bukkit.event.entity.EntityCombustByBlockEvent(damager, damagee, 15); ++ this.level.getCraftServer().getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ this.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ } else { ++ // This will be called every single tick the entity is in lava, so don't throw an event ++ this.setSecondsOnFire(15, false); ++ } ++ CraftEventFactory.blockDamage = (lastLavaContact) == null ? null : org.bukkit.craftbukkit.block.CraftBlock.at(level, lastLavaContact); + if (this.hurt(this.damageSources().lava(), 4.0F)) { + this.playSound(SoundEffects.GENERIC_BURN, 0.4F, 2.0F + this.random.nextFloat() * 0.4F); + } ++ CraftEventFactory.blockDamage = null; ++ // CraftBukkit end - we also don't throw an event unless the object in lava is living, to save on some event calls + + } + } + + public void setSecondsOnFire(int i) { ++ // CraftBukkit start ++ this.setSecondsOnFire(i, true); ++ } ++ ++ public void setSecondsOnFire(int i, boolean callEvent) { ++ if (callEvent) { ++ EntityCombustEvent event = new EntityCombustEvent(this.getBukkitEntity(), i); ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ i = event.getDuration(); ++ } ++ // CraftBukkit end + int j = i * 20; + + if (this instanceof EntityLiving) { +@@ -699,6 +858,28 @@ + block.updateEntityAfterFallOn(this.level(), this); + } + ++ // CraftBukkit start ++ if (horizontalCollision && getBukkitEntity() instanceof Vehicle) { ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ org.bukkit.block.Block bl = this.level.getWorld().getBlockAt(MathHelper.floor(this.getX()), MathHelper.floor(this.getY()), MathHelper.floor(this.getZ())); ++ ++ if (vec3d.x > vec3d1.x) { ++ bl = bl.getRelative(BlockFace.EAST); ++ } else if (vec3d.x < vec3d1.x) { ++ bl = bl.getRelative(BlockFace.WEST); ++ } else if (vec3d.z > vec3d1.z) { ++ bl = bl.getRelative(BlockFace.SOUTH); ++ } else if (vec3d.z < vec3d1.z) { ++ bl = bl.getRelative(BlockFace.NORTH); ++ } ++ ++ if (!bl.getType().isAir()) { ++ VehicleBlockCollisionEvent event = new VehicleBlockCollisionEvent(vehicle, bl); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ } ++ } ++ // CraftBukkit end ++ + if (this.onGround()) { + block.stepOn(this.level(), blockposition, iblockdata, this); + } +@@ -1026,6 +1207,20 @@ + return SoundEffects.GENERIC_SPLASH; + } + ++ // CraftBukkit start - Add delegate methods ++ public SoundEffect getSwimSound0() { ++ return getSwimSound(); ++ } ++ ++ public SoundEffect getSwimSplashSound0() { ++ return getSwimSplashSound(); ++ } ++ ++ public SoundEffect getSwimHighSpeedSplashSound0() { ++ return getSwimHighSpeedSplashSound(); ++ } ++ // CraftBukkit end ++ + protected void checkInsideBlocks() { + AxisAlignedBB axisalignedbb = this.getBoundingBox(); + BlockPosition blockposition = BlockPosition.containing(axisalignedbb.minX + 1.0E-7D, axisalignedbb.minY + 1.0E-7D, axisalignedbb.minZ + 1.0E-7D); +@@ -1440,6 +1635,7 @@ + this.yo = d1; + this.zo = d4; + this.setPos(d3, d1, d4); ++ if (valid) level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit + } + + public void moveTo(Vec3D vec3d) { +@@ -1634,6 +1830,12 @@ + return false; + } + ++ // CraftBukkit start - collidable API ++ public boolean canCollideWithBukkit(Entity entity) { ++ return isPushable(); ++ } ++ // CraftBukkit end ++ + public void awardKillScore(Entity entity, int i, DamageSource damagesource) { + if (entity instanceof EntityPlayer) { + CriterionTriggers.ENTITY_KILLED_PLAYER.trigger((EntityPlayer) entity, this, damagesource); +@@ -1662,16 +1864,22 @@ + } + + public boolean saveAsPassenger(NBTTagCompound nbttagcompound) { ++ // CraftBukkit start - allow excluding certain data when saving ++ return saveAsPassenger(nbttagcompound, true); ++ } ++ ++ public boolean saveAsPassenger(NBTTagCompound nbttagcompound, boolean includeAll) { ++ // CraftBukkit end + if (this.removalReason != null && !this.removalReason.shouldSave()) { + return false; + } else { + String s = this.getEncodeId(); + +- if (s == null) { ++ if (!this.persist || s == null) { // CraftBukkit - persist flag + return false; + } else { + nbttagcompound.putString("id", s); +- this.saveWithoutId(nbttagcompound); ++ this.saveWithoutId(nbttagcompound, includeAll); // CraftBukkit - pass on includeAll + return true; + } + } +@@ -1682,16 +1890,38 @@ + } + + public NBTTagCompound saveWithoutId(NBTTagCompound nbttagcompound) { ++ // CraftBukkit start - allow excluding certain data when saving ++ return saveWithoutId(nbttagcompound, true); ++ } ++ ++ public NBTTagCompound saveWithoutId(NBTTagCompound nbttagcompound, boolean includeAll) { ++ // CraftBukkit end + try { +- if (this.vehicle != null) { +- nbttagcompound.put("Pos", this.newDoubleList(this.vehicle.getX(), this.getY(), this.vehicle.getZ())); +- } else { +- nbttagcompound.put("Pos", this.newDoubleList(this.getX(), this.getY(), this.getZ())); ++ // CraftBukkit start - selectively save position ++ if (includeAll) { ++ if (this.vehicle != null) { ++ nbttagcompound.put("Pos", this.newDoubleList(this.vehicle.getX(), this.getY(), this.vehicle.getZ())); ++ } else { ++ nbttagcompound.put("Pos", this.newDoubleList(this.getX(), this.getY(), this.getZ())); ++ } + } ++ // CraftBukkit end + + Vec3D vec3d = this.getDeltaMovement(); + + nbttagcompound.put("Motion", this.newDoubleList(vec3d.x, vec3d.y, vec3d.z)); ++ ++ // CraftBukkit start - Checking for NaN pitch/yaw and resetting to zero ++ // TODO: make sure this is the best way to address this. ++ if (Float.isNaN(this.yRot)) { ++ this.yRot = 0; ++ } ++ ++ if (Float.isNaN(this.xRot)) { ++ this.xRot = 0; ++ } ++ // CraftBukkit end ++ + nbttagcompound.put("Rotation", this.newFloatList(this.getYRot(), this.getXRot())); + nbttagcompound.putFloat("FallDistance", this.fallDistance); + nbttagcompound.putShort("Fire", (short) this.remainingFireTicks); +@@ -1699,7 +1929,28 @@ + nbttagcompound.putBoolean("OnGround", this.onGround()); + nbttagcompound.putBoolean("Invulnerable", this.invulnerable); + nbttagcompound.putInt("PortalCooldown", this.portalCooldown); +- nbttagcompound.putUUID("UUID", this.getUUID()); ++ // CraftBukkit start - selectively save uuid and world ++ if (includeAll) { ++ nbttagcompound.putUUID("UUID", this.getUUID()); ++ // PAIL: Check above UUID reads 1.8 properly, ie: UUIDMost / UUIDLeast ++ nbttagcompound.putLong("WorldUUIDLeast", ((WorldServer) this.level).getWorld().getUID().getLeastSignificantBits()); ++ nbttagcompound.putLong("WorldUUIDMost", ((WorldServer) this.level).getWorld().getUID().getMostSignificantBits()); ++ } ++ nbttagcompound.putInt("Bukkit.updateLevel", CURRENT_LEVEL); ++ if (!this.persist) { ++ nbttagcompound.putBoolean("Bukkit.persist", this.persist); ++ } ++ if (!this.visibleByDefault) { ++ nbttagcompound.putBoolean("Bukkit.visibleByDefault", this.visibleByDefault); ++ } ++ if (this.persistentInvisibility) { ++ nbttagcompound.putBoolean("Bukkit.invisible", this.persistentInvisibility); ++ } ++ // SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ if (maxAirTicks != getDefaultMaxAirSupply()) { ++ nbttagcompound.putInt("Bukkit.MaxAirSupply", getMaxAirSupply()); ++ } ++ // CraftBukkit end + IChatBaseComponent ichatbasecomponent = this.getCustomName(); + + if (ichatbasecomponent != null) { +@@ -1748,7 +1999,7 @@ + nbttagcompound.put("Tags", nbttaglist); + } + +- this.addAdditionalSaveData(nbttagcompound); ++ this.addAdditionalSaveData(nbttagcompound, includeAll); // CraftBukkit - pass on includeAll + if (this.isVehicle()) { + nbttaglist = new NBTTagList(); + iterator = this.getPassengers().iterator(); +@@ -1757,7 +2008,7 @@ + Entity entity = (Entity) iterator.next(); + NBTTagCompound nbttagcompound1 = new NBTTagCompound(); + +- if (entity.saveAsPassenger(nbttagcompound1)) { ++ if (entity.saveAsPassenger(nbttagcompound1, includeAll)) { // CraftBukkit - pass on includeAll + nbttaglist.add(nbttagcompound1); + } + } +@@ -1767,6 +2018,11 @@ + } + } + ++ // CraftBukkit start - stores eventually existing bukkit values ++ if (this.bukkitEntity != null) { ++ this.bukkitEntity.storeBukkitValues(nbttagcompound); ++ } ++ // CraftBukkit end + return nbttagcompound; + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT"); +@@ -1850,6 +2106,45 @@ + } else { + throw new IllegalStateException("Entity has invalid position"); + } ++ ++ // CraftBukkit start ++ this.persist = !nbttagcompound.contains("Bukkit.persist") || nbttagcompound.getBoolean("Bukkit.persist"); ++ this.visibleByDefault = !nbttagcompound.contains("Bukkit.visibleByDefault") || nbttagcompound.getBoolean("Bukkit.visibleByDefault"); ++ // SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ if (nbttagcompound.contains("Bukkit.MaxAirSupply")) { ++ maxAirTicks = nbttagcompound.getInt("Bukkit.MaxAirSupply"); ++ } ++ // CraftBukkit end ++ ++ // CraftBukkit start - Reset world ++ if (this instanceof EntityPlayer) { ++ Server server = Bukkit.getServer(); ++ org.bukkit.World bworld = null; ++ ++ // TODO: Remove World related checks, replaced with WorldUID ++ String worldName = nbttagcompound.getString("world"); ++ ++ if (nbttagcompound.contains("WorldUUIDMost") && nbttagcompound.contains("WorldUUIDLeast")) { ++ UUID uid = new UUID(nbttagcompound.getLong("WorldUUIDMost"), nbttagcompound.getLong("WorldUUIDLeast")); ++ bworld = server.getWorld(uid); ++ } else { ++ bworld = server.getWorld(worldName); ++ } ++ ++ if (bworld == null) { ++ bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getLevel(World.OVERWORLD).getWorld(); ++ } ++ ++ ((EntityPlayer) this).setLevel(bworld == null ? null : ((CraftWorld) bworld).getHandle()); ++ } ++ this.getBukkitEntity().readBukkitValues(nbttagcompound); ++ if (nbttagcompound.contains("Bukkit.invisible")) { ++ boolean bukkitInvisible = nbttagcompound.getBoolean("Bukkit.invisible"); ++ this.setInvisible(bukkitInvisible); ++ this.persistentInvisibility = bukkitInvisible; ++ } ++ // CraftBukkit end ++ + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT"); + CrashReportSystemDetails crashreportsystemdetails = crashreport.addCategory("Entity being loaded"); +@@ -1871,6 +2166,12 @@ + return entitytypes.canSerialize() && minecraftkey != null ? minecraftkey.toString() : null; + } + ++ // CraftBukkit start - allow excluding certain data when saving ++ protected void addAdditionalSaveData(NBTTagCompound nbttagcompound, boolean includeAll) { ++ addAdditionalSaveData(nbttagcompound); ++ } ++ // CraftBukkit end ++ + protected abstract void readAdditionalSaveData(NBTTagCompound nbttagcompound); + + protected abstract void addAdditionalSaveData(NBTTagCompound nbttagcompound); +@@ -1925,9 +2226,22 @@ + } else if (this.level().isClientSide) { + return null; + } else { ++ // CraftBukkit start - Capture drops for death event ++ if (this instanceof EntityLiving && !((EntityLiving) this).forceDrops) { ++ ((EntityLiving) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); ++ return null; ++ } ++ // CraftBukkit end + EntityItem entityitem = new EntityItem(this.level(), this.getX(), this.getY() + (double) f, this.getZ(), itemstack); + + entityitem.setDefaultPickUpDelay(); ++ // CraftBukkit start ++ EntityDropItemEvent event = new EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return null; ++ } ++ // CraftBukkit end + this.level().addFreshEntity(entityitem); + return entityitem; + } +@@ -2025,6 +2339,18 @@ + if (!flag && (!this.canRide(entity) || !entity.canAddPassenger(this))) { + return false; + } else { ++ // CraftBukkit start ++ if (entity.getBukkitEntity() instanceof Vehicle && this.getBukkitEntity() instanceof LivingEntity) { ++ VehicleEnterEvent event = new VehicleEnterEvent((Vehicle) entity.getBukkitEntity(), this.getBukkitEntity()); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ if (event.isCancelled()) { ++ return false; ++ } ++ } ++ // CraftBukkit end + if (this.isPassenger()) { + this.stopRiding(); + } +@@ -2058,7 +2384,7 @@ + Entity entity = this.vehicle; + + this.vehicle = null; +- entity.removePassenger(this); ++ if (!entity.removePassenger(this)) this.vehicle = entity; // CraftBukkit + } + + } +@@ -2089,10 +2415,29 @@ + } + } + +- protected void removePassenger(Entity entity) { ++ protected boolean removePassenger(Entity entity) { // CraftBukkit + if (entity.getVehicle() == this) { + throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); + } else { ++ // CraftBukkit start ++ CraftEntity craft = (CraftEntity) entity.getBukkitEntity().getVehicle(); ++ Entity orig = craft == null ? null : craft.getHandle(); ++ if (getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { ++ VehicleExitEvent event = new VehicleExitEvent( ++ (Vehicle) getBukkitEntity(), ++ (LivingEntity) entity.getBukkitEntity() ++ ); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ CraftEntity craftn = (CraftEntity) entity.getBukkitEntity().getVehicle(); ++ Entity n = craftn == null ? null : craftn.getHandle(); ++ if (event.isCancelled() || n != orig) { ++ return false; ++ } ++ } ++ // CraftBukkit end + if (this.passengers.size() == 1 && this.passengers.get(0) == entity) { + this.passengers = ImmutableList.of(); + } else { +@@ -2104,6 +2449,7 @@ + entity.boardingCooldown = 60; + this.gameEvent(GameEvent.ENTITY_DISMOUNT, entity); + } ++ return true; // CraftBukkit + } + + protected boolean canAddPassenger(Entity entity) { +@@ -2190,14 +2536,20 @@ + + if (this.isInsidePortal) { + MinecraftServer minecraftserver = worldserver.getServer(); +- ResourceKey resourcekey = this.level().dimension() == World.NETHER ? World.OVERWORLD : World.NETHER; ++ ResourceKey resourcekey = this.level().getTypeKey() == WorldDimension.NETHER ? World.OVERWORLD : World.NETHER; // CraftBukkit + WorldServer worldserver1 = minecraftserver.getLevel(resourcekey); + +- if (worldserver1 != null && minecraftserver.isNetherEnabled() && !this.isPassenger() && this.portalTime++ >= i) { ++ if (true && !this.isPassenger() && this.portalTime++ >= i) { // CraftBukkit + this.level().getProfiler().push("portal"); + this.portalTime = i; + this.setPortalCooldown(); +- this.changeDimension(worldserver1); ++ // CraftBukkit start ++ if (this instanceof EntityPlayer) { ++ ((EntityPlayer) this).changeDimension(worldserver1, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL); ++ } else { ++ this.changeDimension(worldserver1); ++ } ++ // CraftBukkit end + this.level().getProfiler().pop(); + } + +@@ -2321,6 +2673,13 @@ + } + + public void setSwimming(boolean flag) { ++ // CraftBukkit start ++ if (valid && this.isSwimming() != flag && this instanceof EntityLiving) { ++ if (CraftEventFactory.callToggleSwimEvent((EntityLiving) this, flag).isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + this.setSharedFlag(4, flag); + } + +@@ -2370,8 +2729,12 @@ + return this.getTeam() != null ? this.getTeam().isAlliedTo(scoreboardteambase) : false; + } + ++ // CraftBukkit - start + public void setInvisible(boolean flag) { +- this.setSharedFlag(5, flag); ++ if (!this.persistentInvisibility) { // Prevent Minecraft from removing our invisibility flag ++ this.setSharedFlag(5, flag); ++ } ++ // CraftBukkit - end + } + + public boolean getSharedFlag(int i) { +@@ -2390,7 +2753,7 @@ + } + + public int getMaxAirSupply() { +- return 300; ++ return maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() + } + + public int getAirSupply() { +@@ -2398,7 +2761,18 @@ + } + + public void setAirSupply(int i) { +- this.entityData.set(Entity.DATA_AIR_SUPPLY_ID, i); ++ // CraftBukkit start ++ EntityAirChangeEvent event = new EntityAirChangeEvent(this.getBukkitEntity(), i); ++ // Suppress during worldgen ++ if (this.valid) { ++ event.getEntity().getServer().getPluginManager().callEvent(event); ++ } ++ if (event.isCancelled() && this.getAirSupply() != i) { ++ this.entityData.markDirty(Entity.DATA_AIR_SUPPLY_ID); ++ return; ++ } ++ this.entityData.set(Entity.DATA_AIR_SUPPLY_ID, event.getAmount()); ++ // CraftBukkit end + } + + public int getTicksFrozen() { +@@ -2425,11 +2799,41 @@ + + public void thunderHit(WorldServer worldserver, EntityLightning entitylightning) { + this.setRemainingFireTicks(this.remainingFireTicks + 1); ++ // CraftBukkit start ++ final org.bukkit.entity.Entity thisBukkitEntity = this.getBukkitEntity(); ++ final org.bukkit.entity.Entity stormBukkitEntity = entitylightning.getBukkitEntity(); ++ final PluginManager pluginManager = Bukkit.getPluginManager(); ++ // CraftBukkit end ++ + if (this.remainingFireTicks == 0) { +- this.setSecondsOnFire(8); ++ // CraftBukkit start - Call a combust event when lightning strikes ++ EntityCombustByEntityEvent entityCombustEvent = new EntityCombustByEntityEvent(stormBukkitEntity, thisBukkitEntity, 8); ++ pluginManager.callEvent(entityCombustEvent); ++ if (!entityCombustEvent.isCancelled()) { ++ this.setSecondsOnFire(entityCombustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + +- this.hurt(this.damageSources().lightningBolt(), 5.0F); ++ // CraftBukkit start ++ if (thisBukkitEntity instanceof Hanging) { ++ HangingBreakByEntityEvent hangingEvent = new HangingBreakByEntityEvent((Hanging) thisBukkitEntity, stormBukkitEntity); ++ pluginManager.callEvent(hangingEvent); ++ ++ if (hangingEvent.isCancelled()) { ++ return; ++ } ++ } ++ ++ if (this.fireImmune()) { ++ return; ++ } ++ CraftEventFactory.entityDamage = entitylightning; ++ if (!this.hurt(this.damageSources().lightningBolt(), 5.0F)) { ++ CraftEventFactory.entityDamage = null; ++ return; ++ } ++ // CraftBukkit end + } + + public void onAboveBubbleCol(boolean flag) { +@@ -2594,15 +2998,38 @@ + + @Nullable + public Entity changeDimension(WorldServer worldserver) { ++ // CraftBukkit start ++ return teleportTo(worldserver, null); ++ } ++ ++ @Nullable ++ public Entity teleportTo(WorldServer worldserver, Vec3D location) { ++ // CraftBukkit end + if (this.level() instanceof WorldServer && !this.isRemoved()) { + this.level().getProfiler().push("changeDimension"); +- this.unRide(); ++ // CraftBukkit start ++ // this.unRide(); ++ if (worldserver == null) { ++ return null; ++ } ++ // CraftBukkit end + this.level().getProfiler().push("reposition"); +- ShapeDetectorShape shapedetectorshape = this.findDimensionEntryPoint(worldserver); ++ ShapeDetectorShape shapedetectorshape = (location == null) ? this.findDimensionEntryPoint(worldserver) : new ShapeDetectorShape(new Vec3D(location.x(), location.y(), location.z()), Vec3D.ZERO, this.yRot, this.xRot, worldserver, null); // CraftBukkit + + if (shapedetectorshape == null) { + return null; + } else { ++ // CraftBukkit start ++ worldserver = shapedetectorshape.world; ++ if (worldserver == level) { ++ // SPIGOT-6782: Just move the entity if a plugin changed the world to the one the entity is already in ++ moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, shapedetectorshape.xRot); ++ setDeltaMovement(shapedetectorshape.speed); ++ return this; ++ } ++ this.unRide(); ++ // CraftBukkit end ++ + this.level().getProfiler().popPush("reloading"); + Entity entity = this.getType().create(worldserver); + +@@ -2610,10 +3037,22 @@ + entity.restoreFrom(this); + entity.moveTo(shapedetectorshape.pos.x, shapedetectorshape.pos.y, shapedetectorshape.pos.z, shapedetectorshape.yRot, entity.getXRot()); + entity.setDeltaMovement(shapedetectorshape.speed); +- worldserver.addDuringTeleport(entity); +- if (worldserver.dimension() == World.END) { +- WorldServer.makeObsidianPlatform(worldserver); ++ // CraftBukkit start - Don't spawn the new entity if the current entity isn't spawned ++ if (this.inWorld) { ++ worldserver.addDuringTeleport(entity); ++ if (worldserver.getTypeKey() == WorldDimension.END) { // CraftBukkit ++ WorldServer.makeObsidianPlatform(worldserver, this); // CraftBukkit ++ } ++ } ++ // CraftBukkit end ++ // CraftBukkit start - Forward the CraftEntity to the new entity ++ this.getBukkitEntity().setHandle(entity); ++ entity.bukkitEntity = this.getBukkitEntity(); ++ ++ if (this instanceof EntityInsentient) { ++ ((EntityInsentient) this).dropLeash(true, false); // Unleash to prevent duping of leads. + } ++ // CraftBukkit end + } + + this.removeAfterChangingDimensions(); +@@ -2634,20 +3073,34 @@ + + @Nullable + protected ShapeDetectorShape findDimensionEntryPoint(WorldServer worldserver) { +- boolean flag = this.level().dimension() == World.END && worldserver.dimension() == World.OVERWORLD; +- boolean flag1 = worldserver.dimension() == World.END; ++ // CraftBukkit start ++ if (worldserver == null) { ++ return null; ++ } ++ boolean flag = this.level().getTypeKey() == WorldDimension.END && worldserver.getTypeKey() == WorldDimension.OVERWORLD; // fromEndToOverworld ++ boolean flag1 = worldserver.getTypeKey() == WorldDimension.END; // targetIsEnd ++ // CraftBukkit end + + if (!flag && !flag1) { +- boolean flag2 = worldserver.dimension() == World.NETHER; ++ boolean flag2 = worldserver.getTypeKey() == WorldDimension.NETHER; // CraftBukkit + +- if (this.level().dimension() != World.NETHER && !flag2) { ++ if (this.level().getTypeKey() != WorldDimension.NETHER && !flag2) { // CraftBukkit + return null; + } else { + WorldBorder worldborder = worldserver.getWorldBorder(); + double d0 = DimensionManager.getTeleportationScale(this.level().dimensionType(), worldserver.dimensionType()); + BlockPosition blockposition = worldborder.clampToBounds(this.getX() * d0, this.getY(), this.getZ() * d0); ++ // CraftBukkit start ++ CraftPortalEvent event = callPortalEvent(this, worldserver, new Vec3D(blockposition.getX(), blockposition.getY(), blockposition.getZ()), PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, flag2 ? 16 : 128, 16); ++ if (event == null) { ++ return null; ++ } ++ final WorldServer worldserverFinal = worldserver = ((CraftWorld) event.getTo().getWorld()).getHandle(); ++ worldborder = worldserverFinal.getWorldBorder(); ++ blockposition = worldborder.clampToBounds(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); + +- return (ShapeDetectorShape) this.getExitPortal(worldserver, blockposition, flag2, worldborder).map((blockutil_rectangle) -> { ++ return (ShapeDetectorShape) this.getExitPortal(worldserver, blockposition, flag2, worldborder, event.getSearchRadius(), event.getCanCreatePortal(), event.getCreationRadius()).map((blockutil_rectangle) -> { ++ // CraftBukkit end + IBlockData iblockdata = this.level().getBlockState(this.portalEntrancePos); + EnumDirection.EnumAxis enumdirection_enumaxis; + Vec3D vec3d; +@@ -2664,8 +3117,8 @@ + vec3d = new Vec3D(0.5D, 0.0D, 0.0D); + } + +- return BlockPortalShape.createPortalInfo(worldserver, blockutil_rectangle, enumdirection_enumaxis, vec3d, this, this.getDeltaMovement(), this.getYRot(), this.getXRot()); +- }).orElse((Object) null); ++ return BlockPortalShape.createPortalInfo(worldserverFinal, blockutil_rectangle, enumdirection_enumaxis, vec3d, this, this.getDeltaMovement(), this.getYRot(), this.getXRot(), event); // CraftBukkit ++ }).orElse(null); // CraftBukkit - decompile error + } + } else { + BlockPosition blockposition1; +@@ -2675,8 +3128,14 @@ + } else { + blockposition1 = worldserver.getHeightmapPos(HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, worldserver.getSharedSpawnPos()); + } ++ // CraftBukkit start ++ CraftPortalEvent event = callPortalEvent(this, worldserver, new Vec3D(blockposition1.getX() + 0.5D, blockposition1.getY(), blockposition1.getZ() + 0.5D), PlayerTeleportEvent.TeleportCause.END_PORTAL, 0, 0); ++ if (event == null) { ++ return null; ++ } + +- return new ShapeDetectorShape(new Vec3D((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY(), (double) blockposition1.getZ() + 0.5D), this.getDeltaMovement(), this.getYRot(), this.getXRot()); ++ return new ShapeDetectorShape(new Vec3D(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()), this.getDeltaMovement(), this.getYRot(), this.getXRot(), ((CraftWorld) event.getTo().getWorld()).getHandle(), event); ++ // CraftBukkit end + } + } + +@@ -2684,8 +3143,23 @@ + return BlockPortalShape.getRelativePosition(blockutil_rectangle, enumdirection_enumaxis, this.position(), this.getDimensions(this.getPose())); + } + +- protected Optional getExitPortal(WorldServer worldserver, BlockPosition blockposition, boolean flag, WorldBorder worldborder) { +- return worldserver.getPortalForcer().findPortalAround(blockposition, flag, worldborder); ++ // CraftBukkit start ++ protected CraftPortalEvent callPortalEvent(Entity entity, WorldServer exitWorldServer, Vec3D exitPosition, PlayerTeleportEvent.TeleportCause cause, int searchRadius, int creationRadius) { ++ org.bukkit.entity.Entity bukkitEntity = entity.getBukkitEntity(); ++ Location enter = bukkitEntity.getLocation(); ++ Location exit = CraftLocation.toBukkit(exitPosition, exitWorldServer.getWorld()); ++ ++ EntityPortalEvent event = new EntityPortalEvent(bukkitEntity, enter, exit, searchRadius); ++ event.getEntity().getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null || !entity.isAlive()) { ++ return null; ++ } ++ return new CraftPortalEvent(event); ++ } ++ ++ protected Optional getExitPortal(WorldServer worldserver, BlockPosition blockposition, boolean flag, WorldBorder worldborder, int searchRadius, boolean canCreatePortal, int createRadius) { ++ return worldserver.getPortalForcer().findPortalAround(blockposition, worldborder, searchRadius); ++ // CraftBukkit end + } + + public boolean canChangeDimensions() { +@@ -2806,6 +3280,12 @@ + } + } + ++ // CraftBukkit start ++ public boolean teleportTo(WorldServer worldserver, double d0, double d1, double d2, Set set, float f, float f1, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { ++ return this.teleportTo(worldserver, d0, d1, d2, set, f, f1); ++ } ++ // CraftBukkit end ++ + public boolean teleportTo(WorldServer worldserver, double d0, double d1, double d2, Set set, float f, float f1) { + float f2 = MathHelper.clamp(f1, -90.0F, 90.0F); + +@@ -2825,7 +3305,11 @@ + entity.moveTo(d0, d1, d2, f, f2); + entity.setYHeadRot(f); + this.setRemoved(Entity.RemovalReason.CHANGED_DIMENSION); +- worldserver.addDuringTeleport(entity); ++ // CraftBukkit start - Don't spawn the new entity if the current entity isn't spawned ++ if (inWorld) { ++ worldserver.addDuringTeleport(entity); ++ } ++ // CraftBukkit end + } + + return true; +@@ -2931,7 +3415,26 @@ + } + + public final void setBoundingBox(AxisAlignedBB axisalignedbb) { +- this.bb = axisalignedbb; ++ // CraftBukkit start - block invalid bounding boxes ++ double minX = axisalignedbb.minX, ++ minY = axisalignedbb.minY, ++ minZ = axisalignedbb.minZ, ++ maxX = axisalignedbb.maxX, ++ maxY = axisalignedbb.maxY, ++ maxZ = axisalignedbb.maxZ; ++ double len = axisalignedbb.maxX - axisalignedbb.minX; ++ if (len < 0) maxX = minX; ++ if (len > 64) maxX = minX + 64.0; ++ ++ len = axisalignedbb.maxY - axisalignedbb.minY; ++ if (len < 0) maxY = minY; ++ if (len > 64) maxY = minY + 64.0; ++ ++ len = axisalignedbb.maxZ - axisalignedbb.minZ; ++ if (len < 0) maxZ = minZ; ++ if (len > 64) maxZ = minZ + 64.0; ++ this.bb = new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); ++ // CraftBukkit end + } + + protected float getEyeHeight(EntityPose entitypose, EntitySize entitysize) { +@@ -3246,6 +3749,11 @@ + vec3d = vec3d.add(vec3d1); + ++k1; + } ++ // CraftBukkit start - store last lava contact location ++ if (tagkey == TagsFluid.LAVA) { ++ this.lastLavaContact = blockposition_mutableblockposition.immutable(); ++ } ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/EntityAgeable.patch b/patch-remap/og/net/minecraft/world/entity/EntityAgeable.patch new file mode 100644 index 0000000000..b5e1154ce9 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/EntityAgeable.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/entity/EntityAgeable.java ++++ b/net/minecraft/world/entity/EntityAgeable.java +@@ -20,6 +20,7 @@ + protected int age; + protected int forcedAge; + protected int forcedAgeTimer; ++ public boolean ageLocked; // CraftBukkit + + protected EntityAgeable(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -103,6 +104,7 @@ + super.addAdditionalSaveData(nbttagcompound); + nbttagcompound.putInt("Age", this.getAge()); + nbttagcompound.putInt("ForcedAge", this.forcedAge); ++ nbttagcompound.putBoolean("AgeLocked", this.ageLocked); // CraftBukkit + } + + @Override +@@ -110,6 +112,7 @@ + super.readAdditionalSaveData(nbttagcompound); + this.setAge(nbttagcompound.getInt("Age")); + this.forcedAge = nbttagcompound.getInt("ForcedAge"); ++ this.ageLocked = nbttagcompound.getBoolean("AgeLocked"); // CraftBukkit + } + + @Override +@@ -124,7 +127,7 @@ + @Override + public void aiStep() { + super.aiStep(); +- if (this.level().isClientSide) { ++ if (this.level().isClientSide || ageLocked) { // CraftBukkit + if (this.forcedAgeTimer > 0) { + if (this.forcedAgeTimer % 4 == 0) { + this.level().addParticle(Particles.HAPPY_VILLAGER, this.getRandomX(1.0D), this.getRandomY() + 0.5D, this.getRandomZ(1.0D), 0.0D, 0.0D, 0.0D); diff --git a/patch-remap/og/net/minecraft/world/entity/EntityAreaEffectCloud.patch b/patch-remap/og/net/minecraft/world/entity/EntityAreaEffectCloud.patch new file mode 100644 index 0000000000..90305ddb11 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/EntityAreaEffectCloud.patch @@ -0,0 +1,50 @@ +--- a/net/minecraft/world/entity/EntityAreaEffectCloud.java ++++ b/net/minecraft/world/entity/EntityAreaEffectCloud.java +@@ -31,6 +31,12 @@ + import net.minecraft.world.level.material.EnumPistonReaction; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.resources.MinecraftKey; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.entity.LivingEntity; ++// CraftBukkit end ++ + public class EntityAreaEffectCloud extends Entity implements TraceableEntity { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -264,6 +270,7 @@ + if (!list1.isEmpty()) { + Iterator iterator1 = list1.iterator(); + ++ List entities = new java.util.ArrayList(); // CraftBukkit + while (iterator1.hasNext()) { + EntityLiving entityliving = (EntityLiving) iterator1.next(); + +@@ -273,6 +280,17 @@ + double d8 = d6 * d6 + d7 * d7; + + if (d8 <= (double) (f * f)) { ++ // CraftBukkit start ++ entities.add((LivingEntity) entityliving.getBukkitEntity()); ++ } ++ } ++ } ++ org.bukkit.event.entity.AreaEffectCloudApplyEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callAreaEffectCloudApplyEvent(this, entities); ++ if (!event.isCancelled()) { ++ for (LivingEntity entity : event.getAffectedEntities()) { ++ if (entity instanceof CraftLivingEntity) { ++ EntityLiving entityliving = ((CraftLivingEntity) entity).getHandle(); ++ // CraftBukkit end + this.victims.put(entityliving, this.tickCount + this.reapplicationDelay); + Iterator iterator2 = list.iterator(); + +@@ -282,7 +300,7 @@ + if (mobeffect1.getEffect().isInstantenous()) { + mobeffect1.getEffect().applyInstantenousEffect(this, this.getOwner(), entityliving, mobeffect1.getAmplifier(), 0.5D); + } else { +- entityliving.addEffect(new MobEffect(mobeffect1), this); ++ entityliving.addEffect(new MobEffect(mobeffect1), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AREA_EFFECT_CLOUD); // CraftBukkit + } + } + diff --git a/patch-remap/og/net/minecraft/world/entity/EntityCreature.patch b/patch-remap/og/net/minecraft/world/entity/EntityCreature.patch new file mode 100644 index 0000000000..0af2eb0e05 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/EntityCreature.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/world/entity/EntityCreature.java ++++ b/net/minecraft/world/entity/EntityCreature.java +@@ -9,6 +9,10 @@ + import net.minecraft.world.level.World; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.event.entity.EntityUnleashEvent; ++// CraftBukkit end ++ + public abstract class EntityCreature extends EntityInsentient { + + protected static final float DEFAULT_WALK_TARGET_VALUE = 0.0F; +@@ -51,6 +55,7 @@ + + if (this instanceof EntityTameableAnimal && ((EntityTameableAnimal) this).isInSittingPose()) { + if (f > 10.0F) { ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit + this.dropLeash(true, true); + } + +@@ -59,6 +64,7 @@ + + this.onLeashDistance(f); + if (f > 10.0F) { ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit + this.dropLeash(true, true); + this.goalSelector.disableControlFlag(PathfinderGoal.Type.MOVE); + } else if (f > 6.0F) { diff --git a/patch-remap/og/net/minecraft/world/entity/EntityExperienceOrb.patch b/patch-remap/og/net/minecraft/world/entity/EntityExperienceOrb.patch new file mode 100644 index 0000000000..54d5acc771 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/EntityExperienceOrb.patch @@ -0,0 +1,106 @@ +--- a/net/minecraft/world/entity/EntityExperienceOrb.java ++++ b/net/minecraft/world/entity/EntityExperienceOrb.java +@@ -21,6 +21,13 @@ + import net.minecraft.world.phys.AxisAlignedBB; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.player.PlayerExpCooldownChangeEvent; ++// CraftBukkit end ++ + public class EntityExperienceOrb extends Entity { + + private static final int LIFETIME = 6000; +@@ -59,6 +66,7 @@ + @Override + public void tick() { + super.tick(); ++ EntityHuman prevTarget = this.followingPlayer;// CraftBukkit - store old target + this.xo = this.getX(); + this.yo = this.getY(); + this.zo = this.getZ(); +@@ -84,7 +92,22 @@ + this.followingPlayer = null; + } + +- if (this.followingPlayer != null) { ++ // CraftBukkit start ++ boolean cancelled = false; ++ if (this.followingPlayer != prevTarget) { ++ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(this, followingPlayer, (followingPlayer != null) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.FORGOT_TARGET); ++ EntityLiving target = (event.getTarget() == null) ? null : ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getTarget()).getHandle(); ++ cancelled = event.isCancelled(); ++ ++ if (cancelled) { ++ followingPlayer = prevTarget; ++ } else { ++ followingPlayer = (target instanceof EntityHuman) ? (EntityHuman) target : null; ++ } ++ } ++ ++ if (this.followingPlayer != null && !cancelled) { ++ // CraftBukkit end + Vec3D vec3d = new Vec3D(this.followingPlayer.getX() - this.getX(), this.followingPlayer.getY() + (double) this.followingPlayer.getEyeHeight() / 2.0D - this.getY(), this.followingPlayer.getZ() - this.getZ()); + double d0 = vec3d.lengthSqr(); + +@@ -227,12 +250,12 @@ + public void playerTouch(EntityHuman entityhuman) { + if (!this.level().isClientSide) { + if (entityhuman.takeXpDelay == 0) { +- entityhuman.takeXpDelay = 2; ++ entityhuman.takeXpDelay = CraftEventFactory.callPlayerXpCooldownEvent(entityhuman, 2, PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2; + entityhuman.take(this, 1); + int i = this.repairPlayerItems(entityhuman, this.value); + + if (i > 0) { +- entityhuman.giveExperiencePoints(i); ++ entityhuman.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(entityhuman, i).getAmount()); // CraftBukkit - this.value -> event.getAmount() + } + + --this.count; +@@ -250,9 +273,17 @@ + if (entry != null) { + ItemStack itemstack = (ItemStack) entry.getValue(); + int j = Math.min(this.xpToDurability(i), itemstack.getDamageValue()); ++ // CraftBukkit start ++ org.bukkit.event.player.PlayerItemMendEvent event = CraftEventFactory.callPlayerItemMendEvent(entityhuman, this, itemstack, entry.getKey(), j); ++ j = event.getRepairAmount(); ++ if (event.isCancelled()) { ++ return i; ++ } ++ // CraftBukkit end + + itemstack.setDamageValue(itemstack.getDamageValue() - j); + int k = i - this.durabilityToXp(j); ++ this.value = k; // CraftBukkit - update exp value of orb for PlayerItemMendEvent calls + + return k > 0 ? this.repairPlayerItems(entityhuman, k) : 0; + } else { +@@ -277,6 +308,24 @@ + } + + public static int getExperienceValue(int i) { ++ // CraftBukkit start ++ if (i > 162670129) return i - 100000; ++ if (i > 81335063) return 81335063; ++ if (i > 40667527) return 40667527; ++ if (i > 20333759) return 20333759; ++ if (i > 10166857) return 10166857; ++ if (i > 5083423) return 5083423; ++ if (i > 2541701) return 2541701; ++ if (i > 1270849) return 1270849; ++ if (i > 635413) return 635413; ++ if (i > 317701) return 317701; ++ if (i > 158849) return 158849; ++ if (i > 79423) return 79423; ++ if (i > 39709) return 39709; ++ if (i > 19853) return 19853; ++ if (i > 9923) return 9923; ++ if (i > 4957) return 4957; ++ // CraftBukkit end + return i >= 2477 ? 2477 : (i >= 1237 ? 1237 : (i >= 617 ? 617 : (i >= 307 ? 307 : (i >= 149 ? 149 : (i >= 73 ? 73 : (i >= 37 ? 37 : (i >= 17 ? 17 : (i >= 7 ? 7 : (i >= 3 ? 3 : 1))))))))); + } + diff --git a/patch-remap/og/net/minecraft/world/entity/EntityInsentient.patch b/patch-remap/og/net/minecraft/world/entity/EntityInsentient.patch new file mode 100644 index 0000000000..0287040351 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/EntityInsentient.patch @@ -0,0 +1,329 @@ +--- a/net/minecraft/world/entity/EntityInsentient.java ++++ b/net/minecraft/world/entity/EntityInsentient.java +@@ -76,6 +76,19 @@ + import net.minecraft.world.level.pathfinder.PathType; + import net.minecraft.world.phys.AxisAlignedBB; + ++// CraftBukkit start ++import net.minecraft.server.level.EntityPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++import org.bukkit.event.entity.EntityUnleashEvent; ++import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; ++// CraftBukkit end ++ + public abstract class EntityInsentient extends EntityLiving implements Targeting { + + private static final DataWatcherObject DATA_MOB_FLAGS_ID = DataWatcher.defineId(EntityInsentient.class, DataWatcherRegistry.BYTE); +@@ -123,6 +136,8 @@ + private BlockPosition restrictCenter; + private float restrictRadius; + ++ public boolean aware = true; // CraftBukkit ++ + protected EntityInsentient(EntityTypes entitytypes, World world) { + super(entitytypes, world); + this.handItems = NonNullList.withSize(2, ItemStack.EMPTY); +@@ -148,6 +163,12 @@ + + } + ++ // CraftBukkit start ++ public void setPersistenceRequired(boolean persistenceRequired) { ++ this.persistenceRequired = persistenceRequired; ++ } ++ // CraftBukkit end ++ + protected void registerGoals() {} + + public static AttributeProvider.Builder createMobAttributes() { +@@ -259,7 +280,38 @@ + } + + public void setTarget(@Nullable EntityLiving entityliving) { ++ // CraftBukkit start - fire event ++ setTarget(entityliving, EntityTargetEvent.TargetReason.UNKNOWN, true); ++ } ++ ++ public boolean setTarget(EntityLiving entityliving, EntityTargetEvent.TargetReason reason, boolean fireEvent) { ++ if (getTarget() == entityliving) return false; ++ if (fireEvent) { ++ if (reason == EntityTargetEvent.TargetReason.UNKNOWN && getTarget() != null && entityliving == null) { ++ reason = getTarget().isAlive() ? EntityTargetEvent.TargetReason.FORGOT_TARGET : EntityTargetEvent.TargetReason.TARGET_DIED; ++ } ++ if (reason == EntityTargetEvent.TargetReason.UNKNOWN) { ++ this.level().getCraftServer().getLogger().log(java.util.logging.Level.WARNING, "Unknown target reason, please report on the issue tracker", new Exception()); ++ } ++ CraftLivingEntity ctarget = null; ++ if (entityliving != null) { ++ ctarget = (CraftLivingEntity) entityliving.getBukkitEntity(); ++ } ++ EntityTargetLivingEntityEvent event = new EntityTargetLivingEntityEvent(this.getBukkitEntity(), ctarget, reason); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ if (event.getTarget() != null) { ++ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ } else { ++ entityliving = null; ++ } ++ } + this.target = entityliving; ++ return true; ++ // CraftBukkit end + } + + @Override +@@ -399,6 +451,12 @@ + return null; + } + ++ // CraftBukkit start - Add delegate method ++ public SoundEffect getAmbientSound0() { ++ return getAmbientSound(); ++ } ++ // CraftBukkit end ++ + @Override + public void addAdditionalSaveData(NBTTagCompound nbttagcompound) { + super.addAdditionalSaveData(nbttagcompound); +@@ -457,7 +515,7 @@ + } + + nbttagcompound.put("HandDropChances", nbttaglist3); +- if (this.leashHolder != null) { ++ if (this.leashHolder != null && !this.leashHolder.pluginRemoved) { // CraftBukkit - SPIGOT-7487: Don't save (and possible drop) leash, when the holder was removed by a plugin + nbttagcompound2 = new NBTTagCompound(); + if (this.leashHolder instanceof EntityLiving) { + UUID uuid = this.leashHolder.getUUID(); +@@ -488,16 +546,26 @@ + nbttagcompound.putBoolean("NoAI", this.isNoAi()); + } + ++ nbttagcompound.putBoolean("Bukkit.Aware", this.aware); // CraftBukkit + } + + @Override + public void readAdditionalSaveData(NBTTagCompound nbttagcompound) { + super.readAdditionalSaveData(nbttagcompound); ++ ++ // CraftBukkit start - If looting or persistence is false only use it if it was set after we started using it + if (nbttagcompound.contains("CanPickUpLoot", 1)) { +- this.setCanPickUpLoot(nbttagcompound.getBoolean("CanPickUpLoot")); ++ boolean data = nbttagcompound.getBoolean("CanPickUpLoot"); ++ if (isLevelAtLeast(nbttagcompound, 1) || data) { ++ this.setCanPickUpLoot(data); ++ } + } + +- this.persistenceRequired = nbttagcompound.getBoolean("PersistenceRequired"); ++ boolean data = nbttagcompound.getBoolean("PersistenceRequired"); ++ if (isLevelAtLeast(nbttagcompound, 1) || data) { ++ this.persistenceRequired = data; ++ } ++ // CraftBukkit end + NBTTagList nbttaglist; + int i; + +@@ -544,6 +612,11 @@ + } + + this.setNoAi(nbttagcompound.getBoolean("NoAI")); ++ // CraftBukkit start ++ if (nbttagcompound.contains("Bukkit.Aware")) { ++ this.aware = nbttagcompound.getBoolean("Bukkit.Aware"); ++ } ++ // CraftBukkit end + } + + @Override +@@ -611,7 +684,7 @@ + + protected void pickUpItem(EntityItem entityitem) { + ItemStack itemstack = entityitem.getItem(); +- ItemStack itemstack1 = this.equipItemIfPossible(itemstack.copy()); ++ ItemStack itemstack1 = this.equipItemIfPossible(itemstack.copy(), entityitem); // CraftBukkit - add item + + if (!itemstack1.isEmpty()) { + this.onItemPickup(entityitem); +@@ -625,6 +698,12 @@ + } + + public ItemStack equipItemIfPossible(ItemStack itemstack) { ++ // CraftBukkit start - add item ++ return this.equipItemIfPossible(itemstack, null); ++ } ++ ++ public ItemStack equipItemIfPossible(ItemStack itemstack, EntityItem entityitem) { ++ // CraftBukkit end + EnumItemSlot enumitemslot = getEquipmentSlotForItem(itemstack); + ItemStack itemstack1 = this.getItemBySlot(enumitemslot); + boolean flag = this.canReplaceCurrentItem(itemstack, itemstack1); +@@ -635,11 +714,19 @@ + flag = itemstack1.isEmpty(); + } + +- if (flag && this.canHoldItem(itemstack)) { ++ // CraftBukkit start ++ boolean canPickup = flag && this.canHoldItem(itemstack); ++ if (entityitem != null) { ++ canPickup = !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, entityitem, 0, !canPickup).isCancelled(); ++ } ++ if (canPickup) { ++ // CraftBukkit end + double d0 = (double) this.getEquipmentDropChance(enumitemslot); + + if (!itemstack1.isEmpty() && (double) Math.max(this.random.nextFloat() - 0.1F, 0.0F) < d0) { ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation(itemstack1); ++ this.forceDrops = false; // CraftBukkit + } + + if (enumitemslot.isArmor() && itemstack.getCount() > 1) { +@@ -791,6 +878,7 @@ + @Override + protected final void serverAiStep() { + ++this.noActionTime; ++ if (!this.aware) return; // CraftBukkit + this.level().getProfiler().push("sensing"); + this.sensing.tick(); + this.level().getProfiler().pop(); +@@ -1184,6 +1272,12 @@ + if (!this.isAlive()) { + return EnumInteractionResult.PASS; + } else if (this.getLeashHolder() == entityhuman) { ++ // CraftBukkit start - fire PlayerUnleashEntityEvent ++ if (CraftEventFactory.callPlayerUnleashEntityEvent(this, entityhuman, enumhand).isCancelled()) { ++ ((EntityPlayer) entityhuman).connection.send(new PacketPlayOutAttachEntity(this, this.getLeashHolder())); ++ return EnumInteractionResult.PASS; ++ } ++ // CraftBukkit end + this.dropLeash(true, !entityhuman.getAbilities().instabuild); + this.gameEvent(GameEvent.ENTITY_INTERACT, entityhuman); + return EnumInteractionResult.sidedSuccess(this.level().isClientSide); +@@ -1209,6 +1303,12 @@ + ItemStack itemstack = entityhuman.getItemInHand(enumhand); + + if (itemstack.is(Items.LEAD) && this.canBeLeashed(entityhuman)) { ++ // CraftBukkit start - fire PlayerLeashEntityEvent ++ if (CraftEventFactory.callPlayerLeashEntityEvent(this, entityhuman, entityhuman, enumhand).isCancelled()) { ++ ((EntityPlayer) entityhuman).connection.send(new PacketPlayOutAttachEntity(this, this.getLeashHolder())); ++ return EnumInteractionResult.PASS; ++ } ++ // CraftBukkit end + this.setLeashedTo(entityhuman, true); + itemstack.shrink(1); + return EnumInteractionResult.sidedSuccess(this.level().isClientSide); +@@ -1224,7 +1324,7 @@ + if (itemstack.getItem() instanceof ItemMonsterEgg) { + if (this.level() instanceof WorldServer) { + ItemMonsterEgg itemmonsteregg = (ItemMonsterEgg) itemstack.getItem(); +- Optional optional = itemmonsteregg.spawnOffspringFromSpawnEgg(entityhuman, this, this.getType(), (WorldServer) this.level(), this.position(), itemstack); ++ Optional optional = itemmonsteregg.spawnOffspringFromSpawnEgg(entityhuman, this, (EntityTypes) this.getType(), (WorldServer) this.level(), this.position(), itemstack); // CraftBukkit - decompile error + + optional.ifPresent((entityinsentient) -> { + this.onOffspringSpawnedFromEgg(entityhuman, entityinsentient); +@@ -1274,12 +1374,19 @@ + return this.restrictRadius != -1.0F; + } + ++ // CraftBukkit start + @Nullable + public T convertTo(EntityTypes entitytypes, boolean flag) { ++ return this.convertTo(entitytypes, flag, EntityTransformEvent.TransformReason.UNKNOWN, CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ @Nullable ++ public T convertTo(EntityTypes entitytypes, boolean flag, EntityTransformEvent.TransformReason transformReason, CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end + if (this.isRemoved()) { + return null; + } else { +- T t0 = (EntityInsentient) entitytypes.create(this.level()); ++ T t0 = entitytypes.create(this.level()); // CraftBukkit - decompile error + + if (t0 == null) { + return null; +@@ -1313,7 +1420,12 @@ + } + } + +- this.level().addFreshEntity(t0); ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, t0, transformReason).isCancelled()) { ++ return null; ++ } ++ this.level().addFreshEntity(t0, spawnReason); ++ // CraftBukkit end + if (this.isPassenger()) { + Entity entity = this.getVehicle(); + +@@ -1334,7 +1446,8 @@ + + if (this.leashHolder != null) { + if (!this.isAlive() || !this.leashHolder.isAlive()) { +- this.dropLeash(true, true); ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE)); // CraftBukkit ++ this.dropLeash(true, !this.leashHolder.pluginRemoved);// CraftBukkit - SPIGOT-7487: Don't drop leash, when the holder was removed by a plugin + } + + } +@@ -1345,7 +1458,9 @@ + this.leashHolder = null; + this.leashInfoTag = null; + if (!this.level().isClientSide && flag1) { ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation((IMaterial) Items.LEAD); ++ this.forceDrops = false; // CraftBukkit + } + + if (!this.level().isClientSide && flag && this.level() instanceof WorldServer) { +@@ -1395,6 +1510,7 @@ + boolean flag1 = super.startRiding(entity, flag); + + if (flag1 && this.isLeashed()) { ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit + this.dropLeash(true, true); + } + +@@ -1419,7 +1535,9 @@ + } + + if (this.tickCount > 100) { ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation((IMaterial) Items.LEAD); ++ this.forceDrops = false; // CraftBukkit + this.leashInfoTag = null; + } + } +@@ -1501,7 +1619,14 @@ + int i = EnchantmentManager.getFireAspect(this); + + if (i > 0) { +- entity.setSecondsOnFire(i * 4); ++ // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), i * 4); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ entity.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + + boolean flag = entity.hurt(this.damageSources().mobAttack(this), f); +@@ -1576,6 +1701,7 @@ + @Override + protected void removeAfterChangingDimensions() { + super.removeAfterChangingDimensions(); ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit + this.dropLeash(true, false); + this.getAllSlots().forEach((itemstack) -> { + if (!itemstack.isEmpty()) { diff --git a/patch-remap/og/net/minecraft/world/entity/EntityLightning.patch b/patch-remap/og/net/minecraft/world/entity/EntityLightning.patch new file mode 100644 index 0000000000..a6705430a4 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/EntityLightning.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/world/entity/EntityLightning.java ++++ b/net/minecraft/world/entity/EntityLightning.java +@@ -29,6 +29,10 @@ + import net.minecraft.world.phys.AxisAlignedBB; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class EntityLightning extends Entity { + + private static final int START_LIFE = 2; +@@ -129,7 +133,7 @@ + } + } + +- if (this.life >= 0) { ++ if (this.life >= 0 && !this.visualOnly) { // CraftBukkit - add !this.visualOnly + if (!(this.level() instanceof WorldServer)) { + this.level().setSkyFlashTime(2); + } else if (!this.visualOnly) { +@@ -163,8 +167,12 @@ + IBlockData iblockdata = BlockFireAbstract.getState(this.level(), blockposition); + + if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) { +- this.level().setBlockAndUpdate(blockposition, iblockdata); +- ++this.blocksSetOnFire; ++ // CraftBukkit start - add "!visualOnly" ++ if (!visualOnly && !CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition, this).isCancelled()) { ++ this.level().setBlockAndUpdate(blockposition, iblockdata); ++ ++this.blocksSetOnFire; ++ } ++ // CraftBukkit end + } + + for (int j = 0; j < i; ++j) { +@@ -172,8 +180,12 @@ + + iblockdata = BlockFireAbstract.getState(this.level(), blockposition1); + if (this.level().getBlockState(blockposition1).isAir() && iblockdata.canSurvive(this.level(), blockposition1)) { +- this.level().setBlockAndUpdate(blockposition1, iblockdata); +- ++this.blocksSetOnFire; ++ // CraftBukkit start - add "!visualOnly" ++ if (!visualOnly && !CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition1, this).isCancelled()) { ++ this.level().setBlockAndUpdate(blockposition1, iblockdata); ++ ++this.blocksSetOnFire; ++ } ++ // CraftBukkit end + } + } + +@@ -237,8 +249,9 @@ + iblockdata = world.getBlockState(blockposition1); + } while (!(iblockdata.getBlock() instanceof WeatheringCopper)); + ++ BlockPosition blockposition1Final = blockposition1; // CraftBukkit - decompile error + WeatheringCopper.getPrevious(iblockdata).ifPresent((iblockdata1) -> { +- world.setBlockAndUpdate(blockposition1, iblockdata1); ++ world.setBlockAndUpdate(blockposition1Final, iblockdata1); // CraftBukkit - decompile error + }); + world.levelEvent(3002, blockposition1, -1); + return Optional.of(blockposition1); diff --git a/patch-remap/og/net/minecraft/world/entity/EntityLiving.patch b/patch-remap/og/net/minecraft/world/entity/EntityLiving.patch new file mode 100644 index 0000000000..703992a8fe --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/EntityLiving.patch @@ -0,0 +1,1012 @@ +--- a/net/minecraft/world/entity/EntityLiving.java ++++ b/net/minecraft/world/entity/EntityLiving.java +@@ -119,6 +119,30 @@ + import net.minecraft.world.scores.ScoreboardTeam; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.HashSet; ++import java.util.Set; ++import com.google.common.base.Function; ++import net.minecraft.nbt.NBTTagFloat; ++import net.minecraft.nbt.NBTTagInt; ++import net.minecraft.world.entity.animal.EntityAnimal; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.attribute.CraftAttributeMap; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.entity.ArrowBodyCountChangeEvent; ++import org.bukkit.event.entity.EntityDamageEvent; ++import org.bukkit.event.entity.EntityDamageEvent.DamageModifier; ++import org.bukkit.event.entity.EntityPotionEffectEvent; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++import org.bukkit.event.entity.EntityResurrectEvent; ++import org.bukkit.event.entity.EntityTeleportEvent; ++import org.bukkit.event.player.PlayerItemConsumeEvent; ++// CraftBukkit end ++ + public abstract class EntityLiving extends Entity implements Attackable { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -226,6 +250,20 @@ + private float swimAmountO; + protected BehaviorController brain; + private boolean skipDropExperience; ++ // CraftBukkit start ++ public int expToDrop; ++ public boolean forceDrops; ++ public ArrayList drops = new ArrayList(); ++ public final org.bukkit.craftbukkit.attribute.CraftAttributeMap craftAttributes; ++ public boolean collides = true; ++ public Set collidableExemptions = new HashSet<>(); ++ public boolean bukkitPickUpLoot; ++ ++ @Override ++ public float getBukkitYaw() { ++ return getYHeadRot(); ++ } ++ // CraftBukkit end + + protected EntityLiving(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -238,7 +276,9 @@ + this.useItem = ItemStack.EMPTY; + this.lastClimbablePos = Optional.empty(); + this.attributes = new AttributeMapBase(AttributeDefaults.getSupplier(entitytypes)); +- this.setHealth(this.getMaxHealth()); ++ this.craftAttributes = new CraftAttributeMap(attributes); // CraftBukkit ++ // CraftBukkit - setHealth(getMaxHealth()) inlined and simplified to skip the instanceof check for EntityPlayer, as getBukkitEntity() is not initialized in constructor ++ this.entityData.set(EntityLiving.DATA_HEALTH_ID, (float) this.getAttribute(GenericAttributes.MAX_HEALTH).getValue()); + this.blocksBuilding = true; + this.rotA = (float) ((Math.random() + 1.0D) * 0.009999999776482582D); + this.reapplyPosition(); +@@ -317,7 +357,13 @@ + double d7 = Math.min((double) (0.2F + f / 15.0F), 2.5D); + int i = (int) (150.0D * d7); + +- ((WorldServer) this.level()).sendParticles(new ParticleParamBlock(Particles.BLOCK, iblockdata), d1, d2, d3, i, 0.0D, 0.0D, 0.0D, 0.15000000596046448D); ++ // CraftBukkit start - visiblity api ++ if (this instanceof EntityPlayer) { ++ ((WorldServer) this.level()).sendParticles((EntityPlayer) this, new ParticleParamBlock(Particles.BLOCK, iblockdata), this.getX(), this.getY(), this.getZ(), i, 0.0D, 0.0D, 0.0D, 0.15000000596046448D, false); ++ } else { ++ ((WorldServer) this.level()).sendParticles(new ParticleParamBlock(Particles.BLOCK, iblockdata), d1, d2, d3, i, 0.0D, 0.0D, 0.0D, 0.15000000596046448D); ++ } ++ // CraftBukkit end + } + + super.checkFallDamage(d0, flag, iblockdata, blockposition); +@@ -672,13 +718,19 @@ + } + + public void onEquipItem(EnumItemSlot enumitemslot, ItemStack itemstack, ItemStack itemstack1) { ++ // CraftBukkit start ++ onEquipItem(enumitemslot, itemstack, itemstack1, false); ++ } ++ ++ public void onEquipItem(EnumItemSlot enumitemslot, ItemStack itemstack, ItemStack itemstack1, boolean silent) { ++ // CraftBukkit end + boolean flag = itemstack1.isEmpty() && itemstack.isEmpty(); + + if (!flag && !ItemStack.isSameItemSameTags(itemstack, itemstack1) && !this.firstTick) { + Equipable equipable = Equipable.get(itemstack1); + + if (!this.level().isClientSide() && !this.isSpectator()) { +- if (!this.isSilent() && equipable != null && equipable.getEquipmentSlot() == enumitemslot) { ++ if (!this.isSilent() && equipable != null && equipable.getEquipmentSlot() == enumitemslot && !silent) { // CraftBukkit + this.level().playSound((EntityHuman) null, this.getX(), this.getY(), this.getZ(), equipable.getEquipSound(), this.getSoundSource(), 1.0F, 1.0F); + } + +@@ -752,6 +804,17 @@ + } + } + ++ // CraftBukkit start ++ if (nbttagcompound.contains("Bukkit.MaxHealth")) { ++ NBTBase nbtbase = nbttagcompound.get("Bukkit.MaxHealth"); ++ if (nbtbase.getId() == 5) { ++ this.getAttribute(GenericAttributes.MAX_HEALTH).setBaseValue(((NBTTagFloat) nbtbase).getAsDouble()); ++ } else if (nbtbase.getId() == 3) { ++ this.getAttribute(GenericAttributes.MAX_HEALTH).setBaseValue(((NBTTagInt) nbtbase).getAsDouble()); ++ } ++ } ++ // CraftBukkit end ++ + if (nbttagcompound.contains("Health", 99)) { + this.setHealth(nbttagcompound.getFloat("Health")); + } +@@ -789,9 +852,32 @@ + + } + ++ // CraftBukkit start ++ private boolean isTickingEffects = false; ++ private List effectsToProcess = Lists.newArrayList(); ++ ++ private static class ProcessableEffect { ++ ++ private MobEffectList type; ++ private MobEffect effect; ++ private final EntityPotionEffectEvent.Cause cause; ++ ++ private ProcessableEffect(MobEffect effect, EntityPotionEffectEvent.Cause cause) { ++ this.effect = effect; ++ this.cause = cause; ++ } ++ ++ private ProcessableEffect(MobEffectList type, EntityPotionEffectEvent.Cause cause) { ++ this.type = type; ++ this.cause = cause; ++ } ++ } ++ // CraftBukkit end ++ + protected void tickEffects() { + Iterator iterator = this.activeEffects.keySet().iterator(); + ++ isTickingEffects = true; // CraftBukkit + try { + while (iterator.hasNext()) { + MobEffectList mobeffectlist = (MobEffectList) iterator.next(); +@@ -801,6 +887,12 @@ + this.onEffectUpdated(mobeffect, true, (Entity) null); + })) { + if (!this.level().isClientSide) { ++ // CraftBukkit start ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, mobeffect, null, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.EXPIRATION); ++ if (event.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end + iterator.remove(); + this.onEffectRemoved(mobeffect); + } +@@ -811,6 +903,17 @@ + } catch (ConcurrentModificationException concurrentmodificationexception) { + ; + } ++ // CraftBukkit start ++ isTickingEffects = false; ++ for (ProcessableEffect e : effectsToProcess) { ++ if (e.effect != null) { ++ addEffect(e.effect, e.cause); ++ } else { ++ removeEffect(e.type, e.cause); ++ } ++ } ++ effectsToProcess.clear(); ++ // CraftBukkit end + + if (this.effectsDirty) { + if (!this.level().isClientSide) { +@@ -937,7 +1040,13 @@ + this.entityData.set(EntityLiving.DATA_EFFECT_COLOR_ID, 0); + } + ++ // CraftBukkit start + public boolean removeAllEffects() { ++ return removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean removeAllEffects(EntityPotionEffectEvent.Cause cause) { ++ // CraftBukkit end + if (this.level().isClientSide) { + return false; + } else { +@@ -946,7 +1055,14 @@ + boolean flag; + + for (flag = false; iterator.hasNext(); flag = true) { +- this.onEffectRemoved((MobEffect) iterator.next()); ++ // CraftBukkit start ++ MobEffect effect = (MobEffect) iterator.next(); ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, effect, null, cause, EntityPotionEffectEvent.Action.CLEARED); ++ if (event.isCancelled()) { ++ continue; ++ } ++ this.onEffectRemoved(effect); ++ // CraftBukkit end + iterator.remove(); + } + +@@ -975,19 +1091,49 @@ + return this.addEffect(mobeffect, (Entity) null); + } + ++ // CraftBukkit start ++ public boolean addEffect(MobEffect mobeffect, EntityPotionEffectEvent.Cause cause) { ++ return this.addEffect(mobeffect, (Entity) null, cause); ++ } ++ + public boolean addEffect(MobEffect mobeffect, @Nullable Entity entity) { ++ return this.addEffect(mobeffect, entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean addEffect(MobEffect mobeffect, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause) { ++ if (isTickingEffects) { ++ effectsToProcess.add(new ProcessableEffect(mobeffect, cause)); ++ return true; ++ } ++ // CraftBukkit end ++ + if (!this.canBeAffected(mobeffect)) { + return false; + } else { + MobEffect mobeffect1 = (MobEffect) this.activeEffects.get(mobeffect.getEffect()); + boolean flag = false; + ++ // CraftBukkit start ++ boolean override = false; ++ if (mobeffect1 != null) { ++ override = new MobEffect(mobeffect1).update(mobeffect); ++ } ++ ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, mobeffect1, mobeffect, cause, override); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ + if (mobeffect1 == null) { + this.activeEffects.put(mobeffect.getEffect(), mobeffect); + this.onEffectAdded(mobeffect, entity); + flag = true; +- } else if (mobeffect1.update(mobeffect)) { ++ // CraftBukkit start ++ } else if (event.isOverride()) { ++ mobeffect1.update(mobeffect); + this.onEffectUpdated(mobeffect1, true, entity); ++ // CraftBukkit end + flag = true; + } + +@@ -1025,13 +1171,39 @@ + return this.getMobType() == EnumMonsterType.UNDEAD; + } + ++ // CraftBukkit start + @Nullable + public MobEffect removeEffectNoUpdate(@Nullable MobEffectList mobeffectlist) { ++ return c(mobeffectlist, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ @Nullable ++ public MobEffect c(@Nullable MobEffectList mobeffectlist, EntityPotionEffectEvent.Cause cause) { ++ if (isTickingEffects) { ++ effectsToProcess.add(new ProcessableEffect(mobeffectlist, cause)); ++ return null; ++ } ++ ++ MobEffect effect = this.activeEffects.get(mobeffectlist); ++ if (effect == null) { ++ return null; ++ } ++ ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, effect, null, cause); ++ if (event.isCancelled()) { ++ return null; ++ } ++ + return (MobEffect) this.activeEffects.remove(mobeffectlist); + } + + public boolean removeEffect(MobEffectList mobeffectlist) { +- MobEffect mobeffect = this.removeEffectNoUpdate(mobeffectlist); ++ return removeEffect(mobeffectlist, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean removeEffect(MobEffectList mobeffectlist, EntityPotionEffectEvent.Cause cause) { ++ MobEffect mobeffect = this.c(mobeffectlist, cause); ++ // CraftBukkit end + + if (mobeffect != null) { + this.onEffectRemoved(mobeffect); +@@ -1129,20 +1301,55 @@ + + } + ++ // CraftBukkit start - Delegate so we can handle providing a reason for health being regained + public void heal(float f) { ++ heal(f, EntityRegainHealthEvent.RegainReason.CUSTOM); ++ } ++ ++ public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason) { + float f1 = this.getHealth(); + + if (f1 > 0.0F) { +- this.setHealth(f1 + f); ++ EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason); ++ // Suppress during worldgen ++ if (this.valid) { ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (!event.isCancelled()) { ++ this.setHealth((float) (this.getHealth() + event.getAmount())); ++ } ++ // CraftBukkit end + } + + } + + public float getHealth() { ++ // CraftBukkit start - Use unscaled health ++ if (this instanceof EntityPlayer) { ++ return (float) ((EntityPlayer) this).getBukkitEntity().getHealth(); ++ } ++ // CraftBukkit end + return (Float) this.entityData.get(EntityLiving.DATA_HEALTH_ID); + } + + public void setHealth(float f) { ++ // CraftBukkit start - Handle scaled health ++ if (this instanceof EntityPlayer) { ++ org.bukkit.craftbukkit.entity.CraftPlayer player = ((EntityPlayer) this).getBukkitEntity(); ++ // Squeeze ++ if (f < 0.0F) { ++ player.setRealHealth(0.0D); ++ } else if (f > player.getMaxHealth()) { ++ player.setRealHealth(player.getMaxHealth()); ++ } else { ++ player.setRealHealth(f); ++ } ++ ++ player.updateScaledHealth(false); ++ return; ++ } ++ // CraftBukkit end + this.entityData.set(EntityLiving.DATA_HEALTH_ID, MathHelper.clamp(f, 0.0F, this.getMaxHealth())); + } + +@@ -1156,7 +1363,7 @@ + return false; + } else if (this.level().isClientSide) { + return false; +- } else if (this.isDeadOrDying()) { ++ } else if (this.isRemoved() || this.dead || this.getHealth() <= 0.0F) { // CraftBukkit - Don't allow entities that got set to dead/killed elsewhere to get damaged and die + return false; + } else if (damagesource.is(DamageTypeTags.IS_FIRE) && this.hasEffect(MobEffects.FIRE_RESISTANCE)) { + return false; +@@ -1167,10 +1374,11 @@ + + this.noActionTime = 0; + float f1 = f; +- boolean flag = false; ++ boolean flag = f > 0.0F && this.isDamageSourceBlocked(damagesource); // Copied from below + float f2 = 0.0F; + +- if (f > 0.0F && this.isDamageSourceBlocked(damagesource)) { ++ // CraftBukkit - Moved into damageEntity0(DamageSource, float) ++ if (false && f > 0.0F && this.isDamageSourceBlocked(damagesource)) { + this.hurtCurrentlyUsedShield(f); + f2 = f; + f = 0.0F; +@@ -1194,23 +1402,33 @@ + this.walkAnimation.setSpeed(1.5F); + boolean flag1 = true; + +- if ((float) this.invulnerableTime > 10.0F && !damagesource.is(DamageTypeTags.BYPASSES_COOLDOWN)) { ++ if ((float) this.invulnerableTime > (float) this.invulnerableDuration / 2.0F && !damagesource.is(DamageTypeTags.BYPASSES_COOLDOWN)) { // CraftBukkit - restore use of maxNoDamageTicks + if (f <= this.lastHurt) { + return false; + } + +- this.actuallyHurt(damagesource, f - this.lastHurt); ++ // CraftBukkit start ++ if (!this.damageEntity0(damagesource, f - this.lastHurt)) { ++ return false; ++ } ++ // CraftBukkit end + this.lastHurt = f; + flag1 = false; + } else { ++ // CraftBukkit start ++ if (!this.damageEntity0(damagesource, f)) { ++ return false; ++ } + this.lastHurt = f; +- this.invulnerableTime = 20; +- this.actuallyHurt(damagesource, f); ++ this.invulnerableTime = this.invulnerableDuration; // CraftBukkit - restore use of maxNoDamageTicks ++ // this.damageEntity0(damagesource, f); ++ // CraftBukkit end + this.hurtDuration = 10; + this.hurtTime = this.hurtDuration; + } + +- if (damagesource.is(DamageTypeTags.DAMAGES_HELMET) && !this.getItemBySlot(EnumItemSlot.HEAD).isEmpty()) { ++ // CraftBukkit - Moved into damageEntity0(DamageSource, float) ++ if (false && damagesource.is(DamageTypeTags.DAMAGES_HELMET) && !this.getItemBySlot(EnumItemSlot.HEAD).isEmpty()) { + this.hurtHelmet(damagesource, f); + f *= 0.75F; + } +@@ -1328,19 +1546,32 @@ + EnumHand[] aenumhand = EnumHand.values(); + int i = aenumhand.length; + ++ // CraftBukkit start ++ EnumHand hand = null; ++ ItemStack itemstack1 = ItemStack.EMPTY; + for (int j = 0; j < i; ++j) { + EnumHand enumhand = aenumhand[j]; +- ItemStack itemstack1 = this.getItemInHand(enumhand); ++ itemstack1 = this.getItemInHand(enumhand); + + if (itemstack1.is(Items.TOTEM_OF_UNDYING)) { ++ hand = enumhand; // CraftBukkit + itemstack = itemstack1.copy(); +- itemstack1.shrink(1); ++ // itemstack1.subtract(1); // CraftBukkit + break; + } + } + +- if (itemstack != null) { +- if (this instanceof EntityPlayer) { ++ org.bukkit.inventory.EquipmentSlot handSlot = (hand != null) ? org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand) : null; ++ EntityResurrectEvent event = new EntityResurrectEvent((LivingEntity) this.getBukkitEntity(), handSlot); ++ event.setCancelled(itemstack == null); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ if (!itemstack1.isEmpty()) { ++ itemstack1.shrink(1); ++ } ++ if (itemstack != null && this instanceof EntityPlayer) { ++ // CraftBukkit end + EntityPlayer entityplayer = (EntityPlayer) this; + + entityplayer.awardStat(StatisticList.ITEM_USED.get(Items.TOTEM_OF_UNDYING)); +@@ -1349,14 +1580,16 @@ + } + + this.setHealth(1.0F); +- this.removeAllEffects(); +- this.addEffect(new MobEffect(MobEffects.REGENERATION, 900, 1)); +- this.addEffect(new MobEffect(MobEffects.ABSORPTION, 100, 1)); +- this.addEffect(new MobEffect(MobEffects.FIRE_RESISTANCE, 800, 0)); ++ // CraftBukkit start ++ this.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ this.addEffect(new MobEffect(MobEffects.REGENERATION, 900, 1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ this.addEffect(new MobEffect(MobEffects.ABSORPTION, 100, 1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ this.addEffect(new MobEffect(MobEffects.FIRE_RESISTANCE, 800, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ // CraftBukkit end + this.level().broadcastEntityEvent(this, (byte) 35); + } + +- return itemstack != null; ++ return !event.isCancelled(); + } + } + +@@ -1463,14 +1696,22 @@ + IBlockData iblockdata = Blocks.WITHER_ROSE.defaultBlockState(); + + if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) { +- this.level().setBlock(blockposition, iblockdata, 3); +- flag = true; ++ // CraftBukkit start - call EntityBlockFormEvent for Wither Rose ++ flag = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this.level(), blockposition, iblockdata, 3, this); ++ // CraftBukkit end + } + } + + if (!flag) { + EntityItem entityitem = new EntityItem(this.level(), this.getX(), this.getY(), this.getZ(), new ItemStack(Items.WITHER_ROSE)); + ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ CraftEventFactory.callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.level().addFreshEntity(entityitem); + } + } +@@ -1490,21 +1731,40 @@ + + boolean flag = this.lastHurtByPlayerTime > 0; + ++ this.dropEquipment(); // CraftBukkit - from below + if (this.shouldDropLoot() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { + this.dropFromLootTable(damagesource, flag); + this.dropCustomDeathLoot(damagesource, i, flag); + } ++ // CraftBukkit start - Call death event ++ CraftEventFactory.callEntityDeathEvent(this, this.drops); ++ this.drops = new ArrayList<>(); ++ // CraftBukkit end + +- this.dropEquipment(); ++ // this.dropInventory();// CraftBukkit - moved up + this.dropExperience(); + } + + protected void dropEquipment() {} + +- protected void dropExperience() { ++ // CraftBukkit start ++ public int getExpReward() { + if (this.level() instanceof WorldServer && !this.wasExperienceConsumed() && (this.isAlwaysExperienceDropper() || this.lastHurtByPlayerTime > 0 && this.shouldDropExperience() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT))) { +- EntityExperienceOrb.award((WorldServer) this.level(), this.position(), this.getExperienceReward()); ++ int i = this.getExperienceReward(); ++ return i; ++ } else { ++ return 0; + } ++ } ++ // CraftBukkit end ++ ++ protected void dropExperience() { ++ // CraftBukkit start - Update getExpReward() above if the removed if() changes! ++ if (true && !(this instanceof net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon)) { // CraftBukkit - SPIGOT-2420: Special case ender dragon will drop the xp over time ++ EntityExperienceOrb.award((WorldServer) this.level(), this.position(), this.expToDrop); ++ this.expToDrop = 0; ++ } ++ // CraftBukkit end + + } + +@@ -1596,6 +1856,28 @@ + return itemstack.getEatingSound(); + } + ++ // CraftBukkit start - Add delegate methods ++ public SoundEffect getHurtSound0(DamageSource damagesource) { ++ return getHurtSound(damagesource); ++ } ++ ++ public SoundEffect getDeathSound0() { ++ return getDeathSound(); ++ } ++ ++ public SoundEffect getFallDamageSound0(int fallHeight) { ++ return getFallDamageSound(fallHeight); ++ } ++ ++ public SoundEffect getDrinkingSound0(ItemStack itemstack) { ++ return getDrinkingSound(itemstack); ++ } ++ ++ public SoundEffect getEatingSound0(ItemStack itemstack) { ++ return getEatingSound(itemstack); ++ } ++ // CraftBukkit end ++ + public Optional getLastClimbablePos() { + return this.lastClimbablePos; + } +@@ -1642,9 +1924,14 @@ + int i = this.calculateFallDamage(f, f1); + + if (i > 0) { ++ // CraftBukkit start ++ if (!this.hurt(damagesource, (float) i)) { ++ return true; ++ } ++ // CraftBukkit end + this.playSound(this.getFallDamageSound(i), 1.0F, 1.0F); + this.playBlockFallSound(); +- this.hurt(damagesource, (float) i); ++ // this.damageEntity(damagesource, (float) i); // CraftBukkit - moved up + return true; + } else { + return flag; +@@ -1696,7 +1983,7 @@ + + protected float getDamageAfterArmorAbsorb(DamageSource damagesource, float f) { + if (!damagesource.is(DamageTypeTags.BYPASSES_ARMOR)) { +- this.hurtArmor(damagesource, f); ++ // this.hurtArmor(damagesource, f); // CraftBukkit - Moved into damageEntity0(DamageSource, float) + f = CombatMath.getDamageAfterAbsorb(f, (float) this.getArmorValue(), (float) this.getAttributeValue(GenericAttributes.ARMOR_TOUGHNESS)); + } + +@@ -1709,7 +1996,8 @@ + } else { + int i; + +- if (this.hasEffect(MobEffects.DAMAGE_RESISTANCE) && !damagesource.is(DamageTypeTags.BYPASSES_RESISTANCE)) { ++ // CraftBukkit - Moved to damageEntity0(DamageSource, float) ++ if (false && this.hasEffect(MobEffects.DAMAGE_RESISTANCE) && !damagesource.is(DamageTypeTags.BYPASSES_RESISTANCE)) { + i = (this.getEffect(MobEffects.DAMAGE_RESISTANCE).getAmplifier() + 1) * 5; + int j = 25 - i; + float f1 = f * (float) j; +@@ -1742,16 +2030,125 @@ + } + } + +- protected void actuallyHurt(DamageSource damagesource, float f) { +- if (!this.isInvulnerableTo(damagesource)) { +- f = this.getDamageAfterArmorAbsorb(damagesource, f); +- f = this.getDamageAfterMagicAbsorb(damagesource, f); +- float f1 = f; ++ // CraftBukkit start ++ protected boolean damageEntity0(final DamageSource damagesource, float f) { // void -> boolean, add final ++ if (!this.isInvulnerableTo(damagesource)) { ++ final boolean human = this instanceof EntityHuman; ++ float originalDamage = f; ++ Function hardHat = new Function() { ++ @Override ++ public Double apply(Double f) { ++ if (damagesource.is(DamageTypeTags.DAMAGES_HELMET) && !EntityLiving.this.getItemBySlot(EnumItemSlot.HEAD).isEmpty()) { ++ return -(f - (f * 0.75F)); + +- f = Math.max(f - this.getAbsorptionAmount(), 0.0F); +- this.setAbsorptionAmount(this.getAbsorptionAmount() - (f1 - f)); +- float f2 = f1 - f; ++ } ++ return -0.0; ++ } ++ }; ++ float hardHatModifier = hardHat.apply((double) f).floatValue(); ++ f += hardHatModifier; ++ ++ Function blocking = new Function() { ++ @Override ++ public Double apply(Double f) { ++ return -((EntityLiving.this.isDamageSourceBlocked(damagesource)) ? f : 0.0); ++ } ++ }; ++ float blockingModifier = blocking.apply((double) f).floatValue(); ++ f += blockingModifier; ++ ++ Function armor = new Function() { ++ @Override ++ public Double apply(Double f) { ++ return -(f - EntityLiving.this.getDamageAfterArmorAbsorb(damagesource, f.floatValue())); ++ } ++ }; ++ float armorModifier = armor.apply((double) f).floatValue(); ++ f += armorModifier; ++ ++ Function resistance = new Function() { ++ @Override ++ public Double apply(Double f) { ++ if (!damagesource.is(DamageTypeTags.BYPASSES_EFFECTS) && EntityLiving.this.hasEffect(MobEffects.DAMAGE_RESISTANCE) && !damagesource.is(DamageTypeTags.BYPASSES_RESISTANCE)) { ++ int i = (EntityLiving.this.getEffect(MobEffects.DAMAGE_RESISTANCE).getAmplifier() + 1) * 5; ++ int j = 25 - i; ++ float f1 = f.floatValue() * (float) j; ++ return -(f - (f1 / 25.0F)); ++ } ++ return -0.0; ++ } ++ }; ++ float resistanceModifier = resistance.apply((double) f).floatValue(); ++ f += resistanceModifier; ++ ++ Function magic = new Function() { ++ @Override ++ public Double apply(Double f) { ++ return -(f - EntityLiving.this.getDamageAfterMagicAbsorb(damagesource, f.floatValue())); ++ } ++ }; ++ float magicModifier = magic.apply((double) f).floatValue(); ++ f += magicModifier; ++ ++ Function absorption = new Function() { ++ @Override ++ public Double apply(Double f) { ++ return -(Math.max(f - Math.max(f - EntityLiving.this.getAbsorptionAmount(), 0.0F), 0.0F)); ++ } ++ }; ++ float absorptionModifier = absorption.apply((double) f).floatValue(); ++ ++ EntityDamageEvent event = CraftEventFactory.handleLivingEntityDamageEvent(this, damagesource, originalDamage, hardHatModifier, blockingModifier, armorModifier, resistanceModifier, magicModifier, absorptionModifier, hardHat, blocking, armor, resistance, magic, absorption); ++ if (damagesource.getEntity() instanceof EntityHuman) { ++ ((EntityHuman) damagesource.getEntity()).resetAttackStrengthTicker(); // Moved from EntityHuman in order to make the cooldown reset get called after the damage event is fired ++ } ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ f = (float) event.getFinalDamage(); ++ ++ // Resistance ++ if (event.getDamage(DamageModifier.RESISTANCE) < 0) { ++ float f3 = (float) -event.getDamage(DamageModifier.RESISTANCE); ++ if (f3 > 0.0F && f3 < 3.4028235E37F) { ++ if (this instanceof EntityPlayer) { ++ ((EntityPlayer) this).awardStat(StatisticList.DAMAGE_RESISTED, Math.round(f3 * 10.0F)); ++ } else if (damagesource.getEntity() instanceof EntityPlayer) { ++ ((EntityPlayer) damagesource.getEntity()).awardStat(StatisticList.DAMAGE_DEALT_RESISTED, Math.round(f3 * 10.0F)); ++ } ++ } ++ } ++ ++ // Apply damage to helmet ++ if (damagesource.is(DamageTypeTags.DAMAGES_HELMET) && !this.getItemBySlot(EnumItemSlot.HEAD).isEmpty()) { ++ this.hurtHelmet(damagesource, f); ++ } ++ ++ // Apply damage to armor ++ if (!damagesource.is(DamageTypeTags.BYPASSES_ARMOR)) { ++ float armorDamage = (float) (event.getDamage() + event.getDamage(DamageModifier.BLOCKING) + event.getDamage(DamageModifier.HARD_HAT)); ++ this.hurtArmor(damagesource, armorDamage); ++ } ++ ++ // Apply blocking code // PAIL: steal from above ++ if (event.getDamage(DamageModifier.BLOCKING) < 0) { ++ this.level().broadcastEntityEvent(this, (byte) 29); // SPIGOT-4635 - shield damage sound ++ this.hurtCurrentlyUsedShield((float) -event.getDamage(DamageModifier.BLOCKING)); ++ Entity entity = damagesource.getDirectEntity(); ++ ++ if (entity instanceof EntityLiving) { ++ this.blockUsingShield((EntityLiving) entity); ++ } ++ } ++ ++ absorptionModifier = (float) -event.getDamage(DamageModifier.ABSORPTION); ++ this.setAbsorptionAmount(Math.max(this.getAbsorptionAmount() - absorptionModifier, 0.0F)); ++ float f2 = absorptionModifier; + ++ if (f2 > 0.0F && f2 < 3.4028235E37F && this instanceof EntityHuman) { ++ ((EntityHuman) this).awardStat(StatisticList.DAMAGE_ABSORBED, Math.round(f2 * 10.0F)); ++ } + if (f2 > 0.0F && f2 < 3.4028235E37F) { + Entity entity = damagesource.getEntity(); + +@@ -1762,13 +2159,47 @@ + } + } + +- if (f != 0.0F) { ++ if (f > 0 || !human) { ++ if (human) { ++ // PAIL: Be sure to drag all this code from the EntityHuman subclass each update. ++ ((EntityHuman) this).causeFoodExhaustion(damagesource.getFoodExhaustion(), org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.DAMAGED); // CraftBukkit - EntityExhaustionEvent ++ if (f < 3.4028235E37F) { ++ ((EntityHuman) this).awardStat(StatisticList.DAMAGE_TAKEN, Math.round(f * 10.0F)); ++ } ++ } ++ // CraftBukkit end + this.getCombatTracker().recordDamage(damagesource, f); + this.setHealth(this.getHealth() - f); +- this.setAbsorptionAmount(this.getAbsorptionAmount() - f); ++ // CraftBukkit start ++ if (!human) { ++ this.setAbsorptionAmount(this.getAbsorptionAmount() - f); ++ } + this.gameEvent(GameEvent.ENTITY_DAMAGE); ++ ++ return true; ++ } else { ++ // Duplicate triggers if blocking ++ if (event.getDamage(DamageModifier.BLOCKING) < 0) { ++ if (this instanceof EntityPlayer) { ++ CriterionTriggers.ENTITY_HURT_PLAYER.trigger((EntityPlayer) this, damagesource, f, originalDamage, true); ++ f2 = (float) -event.getDamage(DamageModifier.BLOCKING); ++ if (f2 > 0.0F && f2 < 3.4028235E37F) { ++ ((EntityPlayer) this).awardStat(StatisticList.DAMAGE_BLOCKED_BY_SHIELD, Math.round(originalDamage * 10.0F)); ++ } ++ } ++ ++ if (damagesource.getEntity() instanceof EntityPlayer) { ++ CriterionTriggers.PLAYER_HURT_ENTITY.trigger((EntityPlayer) damagesource.getEntity(), this, damagesource, f, originalDamage, true); ++ } ++ ++ return false; ++ } else { ++ return originalDamage > 0; ++ } ++ // CraftBukkit end + } + } ++ return false; // CraftBukkit + } + + public CombatTracker getCombatTracker() { +@@ -1793,8 +2224,18 @@ + } + + public final void setArrowCount(int i) { +- this.entityData.set(EntityLiving.DATA_ARROW_COUNT_ID, i); ++ // CraftBukkit start ++ setArrowCount(i, false); ++ } ++ ++ public final void setArrowCount(int i, boolean flag) { ++ ArrowBodyCountChangeEvent event = CraftEventFactory.callArrowBodyCountChangeEvent(this, getArrowCount(), i, flag); ++ if (event.isCancelled()) { ++ return; ++ } ++ this.entityData.set(EntityLiving.DATA_ARROW_COUNT_ID, event.getNewAmount()); + } ++ // CraftBukkit end + + public final int getStingerCount() { + return (Integer) this.entityData.get(EntityLiving.DATA_STINGER_COUNT_ID); +@@ -2036,6 +2477,12 @@ + + public abstract ItemStack getItemBySlot(EnumItemSlot enumitemslot); + ++ // CraftBukkit start ++ public void setItemSlot(EnumItemSlot enumitemslot, ItemStack itemstack, boolean silent) { ++ this.setItemSlot(enumitemslot, itemstack); ++ } ++ // CraftBukkit end ++ + @Override + public abstract void setItemSlot(EnumItemSlot enumitemslot, ItemStack itemstack); + +@@ -2270,6 +2717,7 @@ + } + + if (this.onGround() && !this.level().isClientSide) { ++ if (getSharedFlag(7) && !CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) // CraftBukkit + this.setSharedFlag(7, false); + } + } else { +@@ -2440,7 +2888,7 @@ + } + } + +- this.detectEquipmentUpdates(); ++ this.detectEquipmentUpdatesPublic(); // CraftBukkit + if (this.tickCount % 20 == 0) { + this.getCombatTracker().recheckStatus(); + } +@@ -2537,7 +2985,7 @@ + this.refreshDirtyAttributes(); + } + +- public void detectEquipmentUpdates() { ++ public void detectEquipmentUpdatesPublic() { // CraftBukkit + Map map = this.collectEquipmentChanges(); + + if (map != null) { +@@ -2839,6 +3287,7 @@ + } + + if (!this.level().isClientSide) { ++ if (flag != this.getSharedFlag(7) && !CraftEventFactory.callToggleGlideEvent(this, flag).isCancelled()) // CraftBukkit + this.setSharedFlag(7, flag); + } + +@@ -3029,13 +3478,20 @@ + + @Override + public boolean isPickable() { +- return !this.isRemoved(); ++ return !this.isRemoved() && this.collides; // CraftBukkit + } + + @Override + public boolean isPushable() { +- return this.isAlive() && !this.isSpectator() && !this.onClimbable(); ++ return this.isAlive() && !this.isSpectator() && !this.onClimbable() && this.collides; // CraftBukkit ++ } ++ ++ // CraftBukkit start - collidable API ++ @Override ++ public boolean canCollideWithBukkit(Entity entity) { ++ return isPushable() && this.collides != this.collidableExemptions.contains(entity.getUUID()); + } ++ // CraftBukkit end + + @Override + public float getYHeadRot() { +@@ -3231,7 +3687,26 @@ + } else { + if (!this.useItem.isEmpty() && this.isUsingItem()) { + this.triggerItemUseEffects(this.useItem, 16); +- ItemStack itemstack = this.useItem.finishUsingItem(this.level(), this); ++ // CraftBukkit start - fire PlayerItemConsumeEvent ++ ItemStack itemstack; ++ if (this instanceof EntityPlayer) { ++ org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(this.useItem); ++ org.bukkit.inventory.EquipmentSlot hand = org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(enumhand); ++ PlayerItemConsumeEvent event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem, hand); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ // Update client ++ ((EntityPlayer) this).getBukkitEntity().updateInventory(); ++ ((EntityPlayer) this).getBukkitEntity().updateScaledHealth(); ++ return; ++ } ++ ++ itemstack = (craftItem.equals(event.getItem())) ? this.useItem.finishUsingItem(this.level(), this) : CraftItemStack.asNMSCopy(event.getItem()).finishUsingItem(this.level(), this); ++ } else { ++ itemstack = this.useItem.finishUsingItem(this.level(), this); ++ } ++ // CraftBukkit end + + if (itemstack != this.useItem) { + this.setItemInHand(enumhand, itemstack); +@@ -3309,6 +3784,12 @@ + } + + public boolean randomTeleport(double d0, double d1, double d2, boolean flag) { ++ // CraftBukkit start ++ return randomTeleport(d0, d1, d2, flag, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.UNKNOWN).orElse(false); ++ } ++ ++ public Optional randomTeleport(double d0, double d1, double d2, boolean flag, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { ++ // CraftBukkit end + double d3 = this.getX(); + double d4 = this.getY(); + double d5 = this.getZ(); +@@ -3333,16 +3814,41 @@ + } + + if (flag2) { +- this.teleportTo(d0, d6, d2); ++ // CraftBukkit start - Teleport event ++ // this.teleportTo(d0, d6, d2); ++ ++ // first set position, to check if the place to teleport is valid ++ this.setPos(d0, d6, d2); + if (world.noCollision((Entity) this) && !world.containsAnyLiquid(this.getBoundingBox())) { + flag1 = true; + } ++ // now revert and call event if the teleport place is valid ++ this.setPos(d3, d4, d5); ++ ++ if (flag1) { ++ if (!(this instanceof EntityPlayer)) { ++ EntityTeleportEvent teleport = new EntityTeleportEvent(this.getBukkitEntity(), new Location(this.level().getWorld(), d3, d4, d5), new Location(this.level().getWorld(), d0, d6, d2)); ++ this.level().getCraftServer().getPluginManager().callEvent(teleport); ++ if (!teleport.isCancelled()) { ++ Location to = teleport.getTo(); ++ this.teleportTo(to.getX(), to.getY(), to.getZ()); ++ } else { ++ return Optional.empty(); ++ } ++ } else { ++ // player teleport event is called in the underlining code ++ if (((EntityPlayer) this).connection.teleport(d0, d6, d2, this.getYRot(), this.getXRot(), java.util.Collections.emptySet(), cause)) { ++ return Optional.empty(); ++ } ++ } ++ } ++ // CraftBukkit end + } + } + + if (!flag1) { +- this.teleportTo(d3, d4, d5); +- return false; ++ // this.enderTeleportTo(d3, d4, d5); // CraftBukkit - already set the location back ++ return Optional.of(false); // CraftBukkit + } else { + if (flag) { + world.broadcastEntityEvent(this, (byte) 46); +@@ -3354,7 +3860,7 @@ + entitycreature.getNavigation().stop(); + } + +- return true; ++ return Optional.of(true); // CraftBukkit + } + } + +@@ -3443,7 +3949,7 @@ + } + + public void stopSleeping() { +- Optional optional = this.getSleepingPos(); ++ Optional optional = this.getSleepingPos(); // CraftBukkit - decompile error + World world = this.level(); + + java.util.Objects.requireNonNull(world); +@@ -3477,7 +3983,7 @@ + + @Nullable + public EnumDirection getBedOrientation() { +- BlockPosition blockposition = (BlockPosition) this.getSleepingPos().orElse((Object) null); ++ BlockPosition blockposition = (BlockPosition) this.getSleepingPos().orElse(null); // CraftBukkit - decompile error + + return blockposition != null ? BlockBed.getBedOrientation(this.level(), blockposition) : null; + } +@@ -3525,7 +4031,7 @@ + Pair pair = (Pair) iterator.next(); + + if (!world.isClientSide && pair.getFirst() != null && world.random.nextFloat() < (Float) pair.getSecond()) { +- entityliving.addEffect(new MobEffect((MobEffect) pair.getFirst())); ++ entityliving.addEffect(new MobEffect((MobEffect) pair.getFirst()), EntityPotionEffectEvent.Cause.FOOD); // CraftBukkit + } + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/EntityTypes.patch b/patch-remap/og/net/minecraft/world/entity/EntityTypes.patch new file mode 100644 index 0000000000..7ec6526629 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/EntityTypes.patch @@ -0,0 +1,124 @@ +--- a/net/minecraft/world/entity/EntityTypes.java ++++ b/net/minecraft/world/entity/EntityTypes.java +@@ -160,6 +160,7 @@ + import net.minecraft.world.phys.AxisAlignedBB; + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapes; ++import org.bukkit.event.entity.CreatureSpawnEvent; + import org.slf4j.Logger; + + public class EntityTypes implements FeatureElement, EntityTypeTest { +@@ -170,7 +171,7 @@ + private static final float MAGIC_HORSE_WIDTH = 1.3964844F; + private static final int DISPLAY_TRACKING_RANGE = 10; + public static final EntityTypes ALLAY = register("allay", EntityTypes.Builder.of(Allay::new, EnumCreatureType.CREATURE).sized(0.35F, 0.6F).clientTrackingRange(8).updateInterval(2)); +- public static final EntityTypes AREA_EFFECT_CLOUD = register("area_effect_cloud", EntityTypes.Builder.of(EntityAreaEffectCloud::new, EnumCreatureType.MISC).fireImmune().sized(6.0F, 0.5F).clientTrackingRange(10).updateInterval(Integer.MAX_VALUE)); ++ public static final EntityTypes AREA_EFFECT_CLOUD = register("area_effect_cloud", EntityTypes.Builder.of(EntityAreaEffectCloud::new, EnumCreatureType.MISC).fireImmune().sized(6.0F, 0.5F).clientTrackingRange(10).updateInterval(10)); // CraftBukkit - SPIGOT-3729: track area effect clouds + public static final EntityTypes ARMOR_STAND = register("armor_stand", EntityTypes.Builder.of(EntityArmorStand::new, EnumCreatureType.MISC).sized(0.5F, 1.975F).clientTrackingRange(10)); + public static final EntityTypes ARROW = register("arrow", EntityTypes.Builder.of(EntityTippedArrow::new, EnumCreatureType.MISC).sized(0.5F, 0.5F).clientTrackingRange(4).updateInterval(20)); + public static final EntityTypes AXOLOTL = register("axolotl", EntityTypes.Builder.of(Axolotl::new, EnumCreatureType.AXOLOTLS).sized(0.75F, 0.42F).clientTrackingRange(10)); +@@ -313,8 +314,8 @@ + private final EntitySize dimensions; + private final FeatureFlagSet requiredFeatures; + +- private static EntityTypes register(String s, EntityTypes.Builder entitytypes_builder) { +- return (EntityTypes) IRegistry.register(BuiltInRegistries.ENTITY_TYPE, s, entitytypes_builder.build(s)); ++ private static EntityTypes register(String s, EntityTypes.Builder entitytypes_builder) { // CraftBukkit - decompile error ++ return (EntityTypes) IRegistry.register(BuiltInRegistries.ENTITY_TYPE, s, (EntityTypes) entitytypes_builder.build(s)); // CraftBukkit - decompile error + } + + public static MinecraftKey getKey(EntityTypes entitytypes) { +@@ -342,8 +343,15 @@ + + @Nullable + public T spawn(WorldServer worldserver, @Nullable ItemStack itemstack, @Nullable EntityHuman entityhuman, BlockPosition blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1) { ++ // CraftBukkit start ++ return this.spawn(worldserver, itemstack, entityhuman, blockposition, enummobspawn, flag, flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG); ++ } ++ ++ @Nullable ++ public T spawn(WorldServer worldserver, @Nullable ItemStack itemstack, @Nullable EntityHuman entityhuman, BlockPosition blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end + NBTTagCompound nbttagcompound; +- Consumer consumer; ++ Consumer consumer; // CraftBukkit - decompile error + + if (itemstack != null) { + nbttagcompound = itemstack.getTag(); +@@ -354,7 +362,7 @@ + nbttagcompound = null; + } + +- return this.spawn(worldserver, nbttagcompound, consumer, blockposition, enummobspawn, flag, flag1); ++ return this.spawn(worldserver, nbttagcompound, consumer, blockposition, enummobspawn, flag, flag1, spawnReason); // CraftBukkit + } + + public static Consumer createDefaultStackConfig(WorldServer worldserver, ItemStack itemstack, @Nullable EntityHuman entityhuman) { +@@ -376,21 +384,37 @@ + NBTTagCompound nbttagcompound = itemstack.getTag(); + + return nbttagcompound != null ? consumer.andThen((entity) -> { +- updateCustomEntityTag(worldserver, entityhuman, entity, nbttagcompound); ++ try { updateCustomEntityTag(worldserver, entityhuman, entity, nbttagcompound); } catch (Throwable t) { LOGGER.warn("Error loading spawn egg NBT", t); } // CraftBukkit - SPIGOT-5665 + }) : consumer; + } + + @Nullable + public T spawn(WorldServer worldserver, BlockPosition blockposition, EnumMobSpawn enummobspawn) { +- return this.spawn(worldserver, (NBTTagCompound) null, (Consumer) null, blockposition, enummobspawn, false, false); ++ // CraftBukkit start ++ return this.spawn(worldserver, blockposition, enummobspawn, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ @Nullable ++ public T spawn(WorldServer worldserver, BlockPosition blockposition, EnumMobSpawn enummobspawn, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ return this.spawn(worldserver, (NBTTagCompound) null, null, blockposition, enummobspawn, false, false, spawnReason); // CraftBukkit - decompile error ++ // CraftBukkit end + } + + @Nullable + public T spawn(WorldServer worldserver, @Nullable NBTTagCompound nbttagcompound, @Nullable Consumer consumer, BlockPosition blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1) { ++ // CraftBukkit start ++ return this.spawn(worldserver, nbttagcompound, consumer, blockposition, enummobspawn, flag, flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ @Nullable ++ public T spawn(WorldServer worldserver, @Nullable NBTTagCompound nbttagcompound, @Nullable Consumer consumer, BlockPosition blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end + T t0 = this.create(worldserver, nbttagcompound, consumer, blockposition, enummobspawn, flag, flag1); + + if (t0 != null) { +- worldserver.addFreshEntityWithPassengers(t0); ++ worldserver.addFreshEntityWithPassengers(t0, spawnReason); ++ return !t0.isRemoved() ? t0 : null; // Don't return an entity when CreatureSpawnEvent is canceled ++ // CraftBukkit end + } + + return t0; +@@ -577,7 +601,7 @@ + } + + return entity; +- }).orElse((Object) null); ++ }).orElse(null); // CraftBukkit - decompile error + } + + public static Stream loadEntitiesRecursive(final List list, final World world) { +@@ -638,7 +662,7 @@ + + @Nullable + public T tryCast(Entity entity) { +- return entity.getType() == this ? entity : null; ++ return entity.getType() == this ? (T) entity : null; // CraftBukkit - decompile error + } + + @Override +@@ -673,7 +697,7 @@ + this.canSpawnFarFromPlayer = enumcreaturetype == EnumCreatureType.CREATURE || enumcreaturetype == EnumCreatureType.MISC; + } + +- public static EntityTypes.Builder of(EntityTypes.b entitytypes_b, EnumCreatureType enumcreaturetype) { ++ public static EntityTypes.Builder of(EntityTypes.b entitytypes_b, EnumCreatureType enumcreaturetype) { // CraftBukkit - decompile error + return new EntityTypes.Builder<>(entitytypes_b, enumcreaturetype); + } + diff --git a/patch-remap/og/net/minecraft/world/entity/IEntityAngerable.patch b/patch-remap/og/net/minecraft/world/entity/IEntityAngerable.patch new file mode 100644 index 0000000000..902b88e16e --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/IEntityAngerable.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/entity/IEntityAngerable.java ++++ b/net/minecraft/world/entity/IEntityAngerable.java +@@ -108,7 +108,7 @@ + default void stopBeingAngry() { + this.setLastHurtByMob((EntityLiving) null); + this.setPersistentAngerTarget((UUID) null); +- this.setTarget((EntityLiving) null); ++ this.setTarget((EntityLiving) null, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET, true); // CraftBukkit + this.setRemainingPersistentAngerTime(0); + } + +@@ -121,6 +121,8 @@ + + void setTarget(@Nullable EntityLiving entityliving); + ++ boolean setTarget(@Nullable EntityLiving entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent); // CraftBukkit ++ + boolean canAttack(EntityLiving entityliving); + + @Nullable diff --git a/patch-remap/og/net/minecraft/world/entity/IEntitySelector.patch b/patch-remap/og/net/minecraft/world/entity/IEntitySelector.patch new file mode 100644 index 0000000000..625f1d6c14 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/IEntitySelector.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/IEntitySelector.java ++++ b/net/minecraft/world/entity/IEntitySelector.java +@@ -44,7 +44,7 @@ + ScoreboardTeamBase.EnumTeamPush scoreboardteambase_enumteampush = scoreboardteam == null ? ScoreboardTeamBase.EnumTeamPush.ALWAYS : scoreboardteam.getCollisionRule(); + + return (Predicate) (scoreboardteambase_enumteampush == ScoreboardTeamBase.EnumTeamPush.NEVER ? Predicates.alwaysFalse() : IEntitySelector.NO_SPECTATORS.and((entity1) -> { +- if (!entity1.isPushable()) { ++ if (!entity1.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(entity1)) { // CraftBukkit - collidable API + return false; + } else if (entity.level().isClientSide && (!(entity1 instanceof EntityHuman) || !((EntityHuman) entity1).isLocalPlayer())) { + return false; diff --git a/patch-remap/og/net/minecraft/world/entity/Interaction.patch b/patch-remap/og/net/minecraft/world/entity/Interaction.patch new file mode 100644 index 0000000000..717ba74985 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/Interaction.patch @@ -0,0 +1,45 @@ +--- a/net/minecraft/world/entity/Interaction.java ++++ b/net/minecraft/world/entity/Interaction.java +@@ -24,6 +24,12 @@ + import net.minecraft.world.phys.AxisAlignedBB; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.world.damagesource.DamageSource; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityDamageEvent; ++// CraftBukkit end ++ + public class Interaction extends Entity implements Attackable, Targeting { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -62,7 +68,7 @@ + this.setHeight(nbttagcompound.getFloat("height")); + } + +- DataResult dataresult; ++ DataResult> dataresult; // CraftBukkit - decompile error + Logger logger; + + if (nbttagcompound.contains("attack")) { +@@ -143,12 +149,19 @@ + public boolean skipAttackInteraction(Entity entity) { + if (entity instanceof EntityHuman) { + EntityHuman entityhuman = (EntityHuman) entity; ++ // CraftBukkit start ++ DamageSource source = entityhuman.damageSources().playerAttack(entityhuman); ++ EntityDamageEvent event = CraftEventFactory.callNonLivingEntityDamageEvent(this, source, 1.0F, false); ++ if (event.isCancelled()) { ++ return true; ++ } ++ // CraftBukkit end + + this.attack = new Interaction.PlayerAction(entityhuman.getUUID(), this.level().getGameTime()); + if (entityhuman instanceof EntityPlayer) { + EntityPlayer entityplayer = (EntityPlayer) entityhuman; + +- CriterionTriggers.PLAYER_HURT_ENTITY.trigger(entityplayer, this, entityhuman.damageSources().generic(), 1.0F, 1.0F, false); ++ CriterionTriggers.PLAYER_HURT_ENTITY.trigger(entityplayer, this, source, (float) event.getFinalDamage(), 1.0F, false); // CraftBukkit + } + + return !this.getResponse(); diff --git a/patch-remap/og/net/minecraft/world/entity/SaddleStorage.patch b/patch-remap/og/net/minecraft/world/entity/SaddleStorage.patch new file mode 100644 index 0000000000..087cd81c37 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/SaddleStorage.patch @@ -0,0 +1,17 @@ +--- a/net/minecraft/world/entity/SaddleStorage.java ++++ b/net/minecraft/world/entity/SaddleStorage.java +@@ -53,6 +53,14 @@ + return (Integer) this.entityData.get(this.boostTimeAccessor); + } + ++ // CraftBukkit add setBoostTicks(int) ++ public void setBoostTicks(int ticks) { ++ this.boosting = true; ++ this.boostTime = 0; ++ this.entityData.set(this.boostTimeAccessor, ticks); ++ } ++ // CraftBukkit end ++ + public void addAdditionalSaveData(NBTTagCompound nbttagcompound) { + nbttagcompound.putBoolean("Saddle", this.hasSaddle()); + } diff --git a/patch-remap/og/net/minecraft/world/entity/ai/attributes/GenericAttributes.patch b/patch-remap/og/net/minecraft/world/entity/ai/attributes/GenericAttributes.patch new file mode 100644 index 0000000000..c44303ee46 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/attributes/GenericAttributes.patch @@ -0,0 +1,7 @@ +--- a/net/minecraft/world/entity/ai/attributes/GenericAttributes.java ++++ b/net/minecraft/world/entity/ai/attributes/GenericAttributes.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.world.entity.ai.attributes; + + import net.minecraft.core.IRegistry; diff --git a/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.patch b/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.patch new file mode 100644 index 0000000000..24aed4d7eb --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.java ++++ b/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.java +@@ -8,6 +8,12 @@ + import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end ++ + public class BehaviorAttackTargetForget { + + private static final int TIMEOUT_TO_GET_WITHIN_ATTACK_RANGE = 200; +@@ -41,6 +47,18 @@ + if (entityinsentient.canAttack(entityliving) && (!flag || !isTiredOfTryingToReachTarget(entityinsentient, behaviorbuilder_b.tryGet(memoryaccessor1))) && entityliving.isAlive() && entityliving.level() == entityinsentient.level() && !predicate.test(entityliving)) { + return true; + } else { ++ // CraftBukkit start ++ EntityLiving old = entityinsentient.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); ++ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entityinsentient, null, (old != null && !old.isAlive()) ? EntityTargetEvent.TargetReason.TARGET_DIED : EntityTargetEvent.TargetReason.FORGOT_TARGET); ++ if (event.isCancelled()) { ++ return false; ++ } ++ if (event.getTarget() == null) { ++ memoryaccessor.erase(); ++ return true; ++ } ++ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ // CraftBukkit end + biconsumer.accept(entityinsentient, entityliving); + memoryaccessor.erase(); + return true; diff --git a/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetSet.patch b/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetSet.patch new file mode 100644 index 0000000000..774133bc5c --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetSet.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetSet.java ++++ b/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetSet.java +@@ -8,6 +8,13 @@ + import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + ++// CraftBukkit start ++import net.minecraft.server.level.EntityPlayer; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end ++ + public class BehaviorAttackTargetSet { + + public BehaviorAttackTargetSet() {} +@@ -35,6 +42,17 @@ + if (!entityinsentient.canAttack(entityliving)) { + return false; + } else { ++ // CraftBukkit start ++ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entityinsentient, entityliving, (entityliving instanceof EntityPlayer) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.CLOSEST_ENTITY); ++ if (event.isCancelled()) { ++ return false; ++ } ++ if (event.getTarget() == null) { ++ memoryaccessor.erase(); ++ return true; ++ } ++ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ // CraftBukkit end + memoryaccessor.set(entityliving); + memoryaccessor1.erase(); + return true; diff --git a/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorCareer.patch b/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorCareer.patch new file mode 100644 index 0000000000..ec8f9aad80 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorCareer.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/entity/ai/behavior/BehaviorCareer.java ++++ b/net/minecraft/world/entity/ai/behavior/BehaviorCareer.java +@@ -9,6 +9,12 @@ + import net.minecraft.world.entity.npc.EntityVillager; + import net.minecraft.world.entity.npc.VillagerProfession; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftVillager; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.VillagerCareerChangeEvent; ++// CraftBukkit end ++ + public class BehaviorCareer { + + public BehaviorCareer() {} +@@ -37,7 +43,14 @@ + return villagerprofession.heldJobSite().test(holder); + }).findFirst(); + }).ifPresent((villagerprofession) -> { +- entityvillager.setVillagerData(entityvillager.getVillagerData().setProfession(villagerprofession)); ++ // CraftBukkit start - Fire VillagerCareerChangeEvent where Villager gets employed ++ VillagerCareerChangeEvent event = CraftEventFactory.callVillagerCareerChangeEvent(entityvillager, CraftVillager.CraftProfession.minecraftToBukkit(villagerprofession), VillagerCareerChangeEvent.ChangeReason.EMPLOYED); ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ entityvillager.setVillagerData(entityvillager.getVillagerData().setProfession(CraftVillager.CraftProfession.bukkitToMinecraft(event.getProfession()))); ++ // CraftBukkit end + entityvillager.refreshBrain(worldserver); + }); + return true; diff --git a/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorFarm.patch b/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorFarm.patch new file mode 100644 index 0000000000..98ac31afba --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorFarm.patch @@ -0,0 +1,58 @@ +--- a/net/minecraft/world/entity/ai/behavior/BehaviorFarm.java ++++ b/net/minecraft/world/entity/ai/behavior/BehaviorFarm.java +@@ -26,6 +26,11 @@ + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import net.minecraft.world.level.block.Blocks; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class BehaviorFarm extends Behavior { + + private static final int HARVEST_DURATION = 200; +@@ -81,8 +86,8 @@ + + protected void start(WorldServer worldserver, EntityVillager entityvillager, long i) { + if (i > this.nextOkStartTime && this.aboveFarmlandPos != null) { +- entityvillager.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (Object) (new BehaviorTarget(this.aboveFarmlandPos))); +- entityvillager.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (Object) (new MemoryTarget(new BehaviorTarget(this.aboveFarmlandPos), 0.5F, 1))); ++ entityvillager.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (new BehaviorTarget(this.aboveFarmlandPos))); // CraftBukkit - decompile error ++ entityvillager.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (new MemoryTarget(new BehaviorTarget(this.aboveFarmlandPos), 0.5F, 1))); // CraftBukkit - decompile error + } + + } +@@ -102,7 +107,9 @@ + Block block1 = worldserver.getBlockState(this.aboveFarmlandPos.below()).getBlock(); + + if (block instanceof BlockCrops && ((BlockCrops) block).isMaxAge(iblockdata)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(entityvillager, this.aboveFarmlandPos, Blocks.AIR.defaultBlockState())) { // CraftBukkit + worldserver.destroyBlock(this.aboveFarmlandPos, true, entityvillager); ++ } // CraftBukkit + } + + if (iblockdata.isAir() && block1 instanceof BlockSoil && entityvillager.hasFarmSeeds()) { +@@ -119,9 +126,11 @@ + ItemBlock itemblock = (ItemBlock) item; + IBlockData iblockdata1 = itemblock.getBlock().defaultBlockState(); + ++ if (CraftEventFactory.callEntityChangeBlockEvent(entityvillager, this.aboveFarmlandPos, iblockdata1)) { // CraftBukkit + worldserver.setBlockAndUpdate(this.aboveFarmlandPos, iblockdata1); + worldserver.gameEvent(GameEvent.BLOCK_PLACE, this.aboveFarmlandPos, GameEvent.a.of(entityvillager, iblockdata1)); + flag = true; ++ } // CraftBukkit + } + } + +@@ -141,8 +150,8 @@ + this.aboveFarmlandPos = this.getValidFarmland(worldserver); + if (this.aboveFarmlandPos != null) { + this.nextOkStartTime = i + 20L; +- entityvillager.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (Object) (new MemoryTarget(new BehaviorTarget(this.aboveFarmlandPos), 0.5F, 1))); +- entityvillager.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (Object) (new BehaviorTarget(this.aboveFarmlandPos))); ++ entityvillager.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (new MemoryTarget(new BehaviorTarget(this.aboveFarmlandPos), 0.5F, 1))); // CraftBukkit - decompile error ++ entityvillager.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (new BehaviorTarget(this.aboveFarmlandPos))); // CraftBukkit - decompile error + } + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorFindAdmirableItem.patch b/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorFindAdmirableItem.patch new file mode 100644 index 0000000000..de85cbfef8 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorFindAdmirableItem.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/world/entity/ai/behavior/BehaviorFindAdmirableItem.java ++++ b/net/minecraft/world/entity/ai/behavior/BehaviorFindAdmirableItem.java +@@ -28,6 +28,20 @@ + EntityItem entityitem = (EntityItem) behaviorbuilder_b.get(memoryaccessor2); + + if (behaviorbuilder_b.tryGet(memoryaccessor3).isEmpty() && predicate.test(entityliving) && entityitem.closerThan(entityliving, (double) i) && entityliving.level().getWorldBorder().isWithinBounds(entityitem.blockPosition())) { ++ // CraftBukkit start ++ if (entityliving instanceof net.minecraft.world.entity.animal.allay.Allay) { ++ org.bukkit.event.entity.EntityTargetEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTargetEvent(entityliving, entityitem, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_ENTITY); ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ if (!(event.getTarget() instanceof EntityItem)) { ++ memoryaccessor2.erase(); ++ } ++ ++ entityitem = (EntityItem) ((org.bukkit.craftbukkit.entity.CraftEntity) event.getTarget()).getHandle(); ++ } ++ // CraftBukkit end + MemoryTarget memorytarget = new MemoryTarget(new BehaviorPositionEntity(entityitem, false), f, 0); + + memoryaccessor.set(new BehaviorPositionEntity(entityitem, true)); diff --git a/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorFollowAdult.patch b/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorFollowAdult.patch new file mode 100644 index 0000000000..fd374d3742 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorFollowAdult.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/world/entity/ai/behavior/BehaviorFollowAdult.java ++++ b/net/minecraft/world/entity/ai/behavior/BehaviorFollowAdult.java +@@ -8,6 +8,13 @@ + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + import net.minecraft.world.entity.ai.memory.MemoryTarget; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++// CraftBukkit end ++ + public class BehaviorFollowAdult { + + public BehaviorFollowAdult() {} +@@ -25,9 +32,20 @@ + if (!entityageable.isBaby()) { + return false; + } else { +- EntityAgeable entityageable1 = (EntityAgeable) behaviorbuilder_b.get(memoryaccessor); ++ EntityLiving entityageable1 = (EntityAgeable) behaviorbuilder_b.get(memoryaccessor); // CraftBukkit - type + + if (entityageable.closerThan(entityageable1, (double) (uniformint.getMaxValue() + 1)) && !entityageable.closerThan(entityageable1, (double) uniformint.getMinValue())) { ++ // CraftBukkit start ++ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(entityageable, entityageable1, EntityTargetEvent.TargetReason.FOLLOW_LEADER); ++ if (event.isCancelled()) { ++ return false; ++ } ++ if (event.getTarget() == null) { ++ memoryaccessor.erase(); ++ return true; ++ } ++ entityageable1 = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ // CraftBukkit end + MemoryTarget memorytarget = new MemoryTarget(new BehaviorPositionEntity(entityageable1, false), (Float) function.apply(entityageable), uniformint.getMinValue() - 1); + + memoryaccessor1.set(new BehaviorPositionEntity(entityageable1, true)); diff --git a/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorInteractDoor.patch b/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorInteractDoor.patch new file mode 100644 index 0000000000..28e608f44b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorInteractDoor.patch @@ -0,0 +1,39 @@ +--- a/net/minecraft/world/entity/ai/behavior/BehaviorInteractDoor.java ++++ b/net/minecraft/world/entity/ai/behavior/BehaviorInteractDoor.java +@@ -61,6 +61,13 @@ + BlockDoor blockdoor = (BlockDoor) iblockdata.getBlock(); + + if (!blockdoor.isOpen(iblockdata)) { ++ // CraftBukkit start - entities opening doors ++ org.bukkit.event.entity.EntityInteractEvent event = new org.bukkit.event.entity.EntityInteractEvent(entityliving.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(entityliving.level(), blockposition)); ++ entityliving.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end + blockdoor.setOpen(entityliving, worldserver, iblockdata, blockposition, true); + } + +@@ -76,6 +83,13 @@ + BlockDoor blockdoor1 = (BlockDoor) iblockdata1.getBlock(); + + if (!blockdoor1.isOpen(iblockdata1)) { ++ // CraftBukkit start - entities opening doors ++ org.bukkit.event.entity.EntityInteractEvent event = new org.bukkit.event.entity.EntityInteractEvent(entityliving.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(entityliving.level(), blockposition1)); ++ entityliving.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end + blockdoor1.setOpen(entityliving, worldserver, iblockdata1, blockposition1, true); + optional = rememberDoorToClose(memoryaccessor1, optional, worldserver, blockposition1); + } +@@ -129,7 +143,7 @@ + } + + private static boolean areOtherMobsComingThroughDoor(EntityLiving entityliving, BlockPosition blockposition, Optional> optional) { +- return optional.isEmpty() ? false : ((List) optional.get()).stream().filter((entityliving1) -> { ++ return optional.isEmpty() ? false : (optional.get()).stream().filter((entityliving1) -> { // CraftBukkit - decompile error + return entityliving1.getType() == entityliving.getType(); + }).filter((entityliving1) -> { + return blockposition.closerToCenterThan(entityliving1.position(), 2.0D); diff --git a/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorMakeLove.patch b/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorMakeLove.patch new file mode 100644 index 0000000000..7599010630 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorMakeLove.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/world/entity/ai/behavior/BehaviorMakeLove.java ++++ b/net/minecraft/world/entity/ai/behavior/BehaviorMakeLove.java +@@ -18,6 +18,11 @@ + import net.minecraft.world.entity.npc.EntityVillager; + import net.minecraft.world.level.pathfinder.PathEntity; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++// CraftBukkit end ++ + public class BehaviorMakeLove extends Behavior { + + private static final int INTERACT_DIST_SQR = 5; +@@ -116,11 +121,17 @@ + if (entityvillager2 == null) { + return Optional.empty(); + } else { +- entityvillager.setAge(6000); +- entityvillager1.setAge(6000); + entityvillager2.setAge(-24000); + entityvillager2.moveTo(entityvillager.getX(), entityvillager.getY(), entityvillager.getZ(), 0.0F, 0.0F); +- worldserver.addFreshEntityWithPassengers(entityvillager2); ++ // CraftBukkit start - call EntityBreedEvent ++ if (CraftEventFactory.callEntityBreedEvent(entityvillager2, entityvillager, entityvillager1, null, null, 0).isCancelled()) { ++ return Optional.empty(); ++ } ++ // Move age setting down ++ entityvillager.setAge(6000); ++ entityvillager1.setAge(6000); ++ worldserver.addFreshEntityWithPassengers(entityvillager2, CreatureSpawnEvent.SpawnReason.BREEDING); ++ // CraftBukkit end + worldserver.broadcastEntityEvent(entityvillager2, (byte) 12); + return Optional.of(entityvillager2); + } +@@ -129,6 +140,6 @@ + private void giveBedToChild(WorldServer worldserver, EntityVillager entityvillager, BlockPosition blockposition) { + GlobalPos globalpos = GlobalPos.of(worldserver.dimension(), blockposition); + +- entityvillager.getBrain().setMemory(MemoryModuleType.HOME, (Object) globalpos); ++ entityvillager.getBrain().setMemory(MemoryModuleType.HOME, globalpos); // CraftBukkit - decompile error + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorProfession.patch b/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorProfession.patch new file mode 100644 index 0000000000..71a1571ee4 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorProfession.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/entity/ai/behavior/BehaviorProfession.java ++++ b/net/minecraft/world/entity/ai/behavior/BehaviorProfession.java +@@ -6,6 +6,12 @@ + import net.minecraft.world.entity.npc.VillagerData; + import net.minecraft.world.entity.npc.VillagerProfession; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftVillager; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.VillagerCareerChangeEvent; ++// CraftBukkit end ++ + public class BehaviorProfession { + + public BehaviorProfession() {} +@@ -17,7 +23,14 @@ + VillagerData villagerdata = entityvillager.getVillagerData(); + + if (villagerdata.getProfession() != VillagerProfession.NONE && villagerdata.getProfession() != VillagerProfession.NITWIT && entityvillager.getVillagerXp() == 0 && villagerdata.getLevel() <= 1) { +- entityvillager.setVillagerData(entityvillager.getVillagerData().setProfession(VillagerProfession.NONE)); ++ // CraftBukkit start ++ VillagerCareerChangeEvent event = CraftEventFactory.callVillagerCareerChangeEvent(entityvillager, CraftVillager.CraftProfession.minecraftToBukkit(VillagerProfession.NONE), VillagerCareerChangeEvent.ChangeReason.LOSING_JOB); ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ entityvillager.setVillagerData(entityvillager.getVillagerData().setProfession(CraftVillager.CraftProfession.bukkitToMinecraft(event.getProfession()))); ++ // CraftBukkit end + entityvillager.refreshBrain(worldserver); + return true; + } else { diff --git a/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorUtil.patch b/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorUtil.patch new file mode 100644 index 0000000000..246146ed44 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/behavior/BehaviorUtil.patch @@ -0,0 +1,51 @@ +--- a/net/minecraft/world/entity/ai/behavior/BehaviorUtil.java ++++ b/net/minecraft/world/entity/ai/behavior/BehaviorUtil.java +@@ -60,7 +60,7 @@ + } + + public static void lookAtEntity(EntityLiving entityliving, EntityLiving entityliving1) { +- entityliving.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (Object) (new BehaviorPositionEntity(entityliving1, true))); ++ entityliving.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (new BehaviorPositionEntity(entityliving1, true))); // CraftBukkit - decompile error + } + + private static void setWalkAndLookTargetMemoriesToEachOther(EntityLiving entityliving, EntityLiving entityliving1, float f) { +@@ -81,8 +81,8 @@ + public static void setWalkAndLookTargetMemories(EntityLiving entityliving, BehaviorPosition behaviorposition, float f, int i) { + MemoryTarget memorytarget = new MemoryTarget(behaviorposition, f, i); + +- entityliving.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (Object) behaviorposition); +- entityliving.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (Object) memorytarget); ++ entityliving.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, behaviorposition); // CraftBukkit - decompile error ++ entityliving.getBrain().setMemory(MemoryModuleType.WALK_TARGET, memorytarget); // CraftBukkit - decompile error + } + + public static void throwItem(EntityLiving entityliving, ItemStack itemstack, Vec3D vec3d) { +@@ -92,6 +92,7 @@ + } + + public static void throwItem(EntityLiving entityliving, ItemStack itemstack, Vec3D vec3d, Vec3D vec3d1, float f) { ++ if (itemstack.isEmpty()) return; // CraftBukkit - SPIGOT-4940: no empty loot + double d0 = entityliving.getEyeY() - (double) f; + EntityItem entityitem = new EntityItem(entityliving.level(), entityliving.getX(), d0, entityliving.getZ(), itemstack); + +@@ -101,12 +102,19 @@ + vec3d2 = vec3d2.normalize().multiply(vec3d1.x, vec3d1.y, vec3d1.z); + entityitem.setDeltaMovement(vec3d2); + entityitem.setDefaultPickUpDelay(); ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(entityliving.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ entityitem.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + entityliving.level().addFreshEntity(entityitem); + } + + public static SectionPosition findSectionClosestToVillage(WorldServer worldserver, SectionPosition sectionposition, int i) { + int j = worldserver.sectionsToVillage(sectionposition); +- Stream stream = SectionPosition.cube(sectionposition, i).filter((sectionposition1) -> { ++ Stream stream = SectionPosition.cube(sectionposition, i).filter((sectionposition1) -> { // CraftBukkit - decompile error + return worldserver.sectionsToVillage(sectionposition1) < j; + }); + diff --git a/patch-remap/og/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.patch b/patch-remap/og/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.patch new file mode 100644 index 0000000000..904dd8f58a --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.patch @@ -0,0 +1,68 @@ +--- a/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java ++++ b/net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.java +@@ -30,6 +30,13 @@ + import net.minecraft.world.level.pathfinder.PathfinderNormal; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import net.minecraft.server.level.EntityPlayer; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end ++ + public class PrepareRamNearestTarget extends Behavior { + + public static final int TIME_OUT_DURATION = 160; +@@ -62,6 +69,13 @@ + return this.ramTargeting.test(entitycreature, entityliving); + }); + }).ifPresent((entityliving) -> { ++ // CraftBukkit start ++ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entitycreature, entityliving, (entityliving instanceof EntityPlayer) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.CLOSEST_ENTITY); ++ if (event.isCancelled() || event.getTarget() == null) { ++ return; ++ } ++ entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ // CraftBukkit end + this.chooseRamPosition(entitycreature, entityliving); + }); + } +@@ -71,7 +85,7 @@ + + if (!behaviorcontroller.hasMemoryValue(MemoryModuleType.RAM_TARGET)) { + worldserver.broadcastEntityEvent(e0, (byte) 59); +- behaviorcontroller.setMemory(MemoryModuleType.RAM_COOLDOWN_TICKS, (Object) this.getCooldownOnFail.applyAsInt(e0)); ++ behaviorcontroller.setMemory(MemoryModuleType.RAM_COOLDOWN_TICKS, this.getCooldownOnFail.applyAsInt(e0)); // CraftBukkit - decompile error + } + + } +@@ -82,8 +96,8 @@ + + protected void tick(WorldServer worldserver, E e0, long i) { + if (!this.ramCandidate.isEmpty()) { +- e0.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (Object) (new MemoryTarget(((PrepareRamNearestTarget.a) this.ramCandidate.get()).getStartPosition(), this.walkSpeed, 0))); +- e0.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (Object) (new BehaviorPositionEntity(((PrepareRamNearestTarget.a) this.ramCandidate.get()).getTarget(), true))); ++ e0.getBrain().setMemory(MemoryModuleType.WALK_TARGET, (new MemoryTarget(((PrepareRamNearestTarget.a) this.ramCandidate.get()).getStartPosition(), this.walkSpeed, 0))); // CraftBukkit - decompile error ++ e0.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, (new BehaviorPositionEntity(((PrepareRamNearestTarget.a) this.ramCandidate.get()).getTarget(), true))); // CraftBukkit - decompile error + boolean flag = !((PrepareRamNearestTarget.a) this.ramCandidate.get()).getTarget().blockPosition().equals(((PrepareRamNearestTarget.a) this.ramCandidate.get()).getTargetPosition()); + + if (flag) { +@@ -100,7 +114,7 @@ + } + + if (i - (Long) this.reachedRamPositionTimestamp.get() >= (long) this.ramPrepareTime) { +- e0.getBrain().setMemory(MemoryModuleType.RAM_TARGET, (Object) this.getEdgeOfBlock(blockposition, ((PrepareRamNearestTarget.a) this.ramCandidate.get()).getTargetPosition())); ++ e0.getBrain().setMemory(MemoryModuleType.RAM_TARGET, this.getEdgeOfBlock(blockposition, ((PrepareRamNearestTarget.a) this.ramCandidate.get()).getTargetPosition())); // CraftBukkit - decompile error + worldserver.playSound((EntityHuman) null, (Entity) e0, (SoundEffect) this.getPrepareRamSound.apply(e0), SoundCategory.NEUTRAL, 1.0F, e0.getVoicePitch()); + this.ramCandidate = Optional.empty(); + } +@@ -152,7 +166,7 @@ + } + + NavigationAbstract navigationabstract = entitycreature.getNavigation(); +- Stream stream = list.stream(); ++ Stream stream = list.stream(); // CraftBukkit - decompile error + BlockPosition blockposition1 = entitycreature.blockPosition(); + + Objects.requireNonNull(blockposition1); diff --git a/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalBreakDoor.patch b/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalBreakDoor.patch new file mode 100644 index 0000000000..2a6ba8eb11 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalBreakDoor.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/entity/ai/goal/PathfinderGoalBreakDoor.java ++++ b/net/minecraft/world/entity/ai/goal/PathfinderGoalBreakDoor.java +@@ -71,6 +71,12 @@ + } + + if (this.breakTime == this.getDoorBreakTime() && this.isValidDifficulty(this.mob.level().getDifficulty())) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreakDoorEvent(this.mob, this.doorPos).isCancelled()) { ++ this.start(); ++ return; ++ } ++ // CraftBukkit end + this.mob.level().removeBlock(this.doorPos, false); + this.mob.level().levelEvent(1021, this.doorPos, 0); + this.mob.level().levelEvent(2001, this.doorPos, Block.getId(this.mob.level().getBlockState(this.doorPos))); diff --git a/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalEatTile.patch b/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalEatTile.patch new file mode 100644 index 0000000000..169dd13029 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalEatTile.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/entity/ai/goal/PathfinderGoalEatTile.java ++++ b/net/minecraft/world/entity/ai/goal/PathfinderGoalEatTile.java +@@ -11,6 +11,10 @@ + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.predicate.BlockStatePredicate; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class PathfinderGoalEatTile extends PathfinderGoal { + + private static final int EAT_ANIMATION_TICKS = 40; +@@ -64,7 +68,7 @@ + BlockPosition blockposition = this.mob.blockPosition(); + + if (PathfinderGoalEatTile.IS_TALL_GRASS.test(this.level.getBlockState(blockposition))) { +- if (this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition, Blocks.AIR.defaultBlockState(), !this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit + this.level.destroyBlock(blockposition, false); + } + +@@ -73,7 +77,7 @@ + BlockPosition blockposition1 = blockposition.below(); + + if (this.level.getBlockState(blockposition1).is(Blocks.GRASS_BLOCK)) { +- if (this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition1, Blocks.AIR.defaultBlockState(), !this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit + this.level.levelEvent(2001, blockposition1, Block.getId(Blocks.GRASS_BLOCK.defaultBlockState())); + this.level.setBlock(blockposition1, Blocks.DIRT.defaultBlockState(), 2); + } diff --git a/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalFollowOwner.patch b/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalFollowOwner.patch new file mode 100644 index 0000000000..096124f0b9 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalFollowOwner.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/entity/ai/goal/PathfinderGoalFollowOwner.java ++++ b/net/minecraft/world/entity/ai/goal/PathfinderGoalFollowOwner.java +@@ -14,6 +14,12 @@ + import net.minecraft.world.level.pathfinder.PathType; + import net.minecraft.world.level.pathfinder.PathfinderNormal; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTeleportEvent; ++// CraftBukkit end ++ + public class PathfinderGoalFollowOwner extends PathfinderGoal { + + public static final int TELEPORT_WHEN_DISTANCE_IS = 12; +@@ -122,7 +128,14 @@ + } else if (!this.canTeleportTo(new BlockPosition(i, j, k))) { + return false; + } else { +- this.tamable.moveTo((double) i + 0.5D, (double) j, (double) k + 0.5D, this.tamable.getYRot(), this.tamable.getXRot()); ++ // CraftBukkit start ++ EntityTeleportEvent event = CraftEventFactory.callEntityTeleportEvent(this.tamable, (double) i + 0.5D, (double) j, (double) k + 0.5D); ++ if (event.isCancelled()) { ++ return false; ++ } ++ Location to = event.getTo(); ++ this.tamable.moveTo(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch()); ++ // CraftBukkit end + this.navigation.stop(); + return true; + } diff --git a/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.patch b/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.patch new file mode 100644 index 0000000000..c8ddbaec1c --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.patch @@ -0,0 +1,26 @@ +--- a/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java ++++ b/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java +@@ -21,6 +21,11 @@ + import net.minecraft.world.level.chunk.IChunkAccess; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class PathfinderGoalRemoveBlock extends PathfinderGoalGotoTarget { + + private final Block blockToRemove; +@@ -96,6 +101,11 @@ + } + + if (this.ticksSinceReachedGoal > 60) { ++ // CraftBukkit start - Step on eggs ++ if (!CraftEventFactory.callEntityInteractEvent(this.removerMob, CraftBlock.at(world, blockposition1))) { ++ return; ++ } ++ // CraftBukkit end + world.removeBlock(blockposition1, false); + if (!world.isClientSide) { + for (int i = 0; i < 20; ++i) { diff --git a/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalSit.patch b/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalSit.patch new file mode 100644 index 0000000000..10fef72e32 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalSit.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/ai/goal/PathfinderGoalSit.java ++++ b/net/minecraft/world/entity/ai/goal/PathfinderGoalSit.java +@@ -22,7 +22,7 @@ + @Override + public boolean canUse() { + if (!this.mob.isTame()) { +- return false; ++ return this.mob.isOrderedToSit() && this.mob.getTarget() == null; // CraftBukkit - Allow sitting for wild animals + } else if (this.mob.isInWaterOrBubble()) { + return false; + } else if (!this.mob.onGround()) { diff --git a/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.patch b/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.patch new file mode 100644 index 0000000000..a7469ed6d1 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java ++++ b/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java +@@ -7,6 +7,11 @@ + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class PathfinderGoalTame extends PathfinderGoal { + + private final EntityHorseAbstract horse; +@@ -63,7 +68,7 @@ + int i = this.horse.getTemper(); + int j = this.horse.getMaxTemper(); + +- if (j > 0 && this.horse.getRandom().nextInt(j) < i) { ++ if (j > 0 && this.horse.getRandom().nextInt(j) < i && !CraftEventFactory.callEntityTameEvent(this.horse, ((CraftHumanEntity) this.horse.getBukkitEntity().getPassenger()).getHandle()).isCancelled()) { // CraftBukkit - fire EntityTameEvent + this.horse.tameWithName(entityhuman); + return; + } diff --git a/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.patch b/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.patch new file mode 100644 index 0000000000..2d265cb8c5 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.patch @@ -0,0 +1,41 @@ +--- a/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.java ++++ b/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.java +@@ -9,6 +9,13 @@ + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.crafting.RecipeItemStack; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++// CraftBukkit end ++ + public class PathfinderGoalTempt extends PathfinderGoal { + + private static final PathfinderTargetCondition TEMP_TARGETING = PathfinderTargetCondition.forNonCombat().range(10.0D).ignoreLineOfSight(); +@@ -21,7 +28,7 @@ + private double pRotX; + private double pRotY; + @Nullable +- protected EntityHuman player; ++ protected EntityLiving player; // CraftBukkit + private int calmDown; + private boolean isRunning; + private final RecipeItemStack items; +@@ -43,6 +50,15 @@ + return false; + } else { + this.player = this.mob.level().getNearestPlayer(this.targetingConditions, this.mob); ++ // CraftBukkit start ++ if (this.player != null) { ++ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(this.mob, this.player, EntityTargetEvent.TargetReason.TEMPT); ++ if (event.isCancelled()) { ++ return false; ++ } ++ this.player = (event.getTarget() == null) ? null : ((CraftLivingEntity) event.getTarget()).getHandle(); ++ } ++ // CraftBukkit end + return this.player != null; + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/ai/sensing/TemptingSensor.patch b/patch-remap/og/net/minecraft/world/entity/ai/sensing/TemptingSensor.patch new file mode 100644 index 0000000000..414d830b7c --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/sensing/TemptingSensor.patch @@ -0,0 +1,45 @@ +--- a/net/minecraft/world/entity/ai/sensing/TemptingSensor.java ++++ b/net/minecraft/world/entity/ai/sensing/TemptingSensor.java +@@ -18,6 +18,14 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.crafting.RecipeItemStack; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTargetLivingEntityEvent; ++// CraftBukkit end ++ + public class TemptingSensor extends Sensor { + + public static final int TEMPTATION_RANGE = 10; +@@ -30,7 +38,7 @@ + + protected void doTick(WorldServer worldserver, EntityCreature entitycreature) { + BehaviorController behaviorcontroller = entitycreature.getBrain(); +- Stream stream = worldserver.players().stream().filter(IEntitySelector.NO_SPECTATORS).filter((entityplayer) -> { ++ Stream stream = worldserver.players().stream().filter(IEntitySelector.NO_SPECTATORS).filter((entityplayer) -> { // CraftBukkit - decompile error + return TemptingSensor.TEMPT_TARGETING.test(entitycreature, entityplayer); + }).filter((entityplayer) -> { + return entitycreature.closerThan(entityplayer, 10.0D); +@@ -44,7 +52,17 @@ + if (!list.isEmpty()) { + EntityHuman entityhuman = (EntityHuman) list.get(0); + +- behaviorcontroller.setMemory(MemoryModuleType.TEMPTING_PLAYER, (Object) entityhuman); ++ // CraftBukkit start ++ EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(entitycreature, entityhuman, EntityTargetEvent.TargetReason.TEMPT); ++ if (event.isCancelled()) { ++ return; ++ } ++ if (event.getTarget() instanceof HumanEntity) { ++ behaviorcontroller.setMemory(MemoryModuleType.TEMPTING_PLAYER, ((CraftHumanEntity) event.getTarget()).getHandle()); ++ } else { ++ behaviorcontroller.eraseMemory(MemoryModuleType.TEMPTING_PLAYER); ++ } ++ // CraftBukkit end + } else { + behaviorcontroller.eraseMemory(MemoryModuleType.TEMPTING_PLAYER); + } diff --git a/patch-remap/og/net/minecraft/world/entity/ai/village/VillageSiege.patch b/patch-remap/og/net/minecraft/world/entity/ai/village/VillageSiege.patch new file mode 100644 index 0000000000..59d73fb17b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ai/village/VillageSiege.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/ai/village/VillageSiege.java ++++ b/net/minecraft/world/entity/ai/village/VillageSiege.java +@@ -122,7 +122,7 @@ + } + + entityzombie.moveTo(vec3d.x, vec3d.y, vec3d.z, worldserver.random.nextFloat() * 360.0F, 0.0F); +- worldserver.addFreshEntityWithPassengers(entityzombie); ++ worldserver.addFreshEntityWithPassengers(entityzombie, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_INVASION); // CraftBukkit + } + } + diff --git a/patch-remap/og/net/minecraft/world/entity/ambient/EntityBat.patch b/patch-remap/og/net/minecraft/world/entity/ambient/EntityBat.patch new file mode 100644 index 0000000000..dfb7ac2bcc --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/ambient/EntityBat.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/world/entity/ambient/EntityBat.java ++++ b/net/minecraft/world/entity/ambient/EntityBat.java +@@ -29,6 +29,10 @@ + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class EntityBat extends EntityAmbient { + + public static final float FLAP_LENGTH_SECONDS = 0.5F; +@@ -143,13 +147,13 @@ + this.yHeadRot = (float) this.random.nextInt(360); + } + +- if (this.level().getNearestPlayer(EntityBat.BAT_RESTING_TARGETING, this) != null) { ++ if (this.level().getNearestPlayer(EntityBat.BAT_RESTING_TARGETING, this) != null && CraftEventFactory.handleBatToggleSleepEvent(this, true)) { // CraftBukkit - Call BatToggleSleepEvent + this.setResting(false); + if (!flag) { + this.level().levelEvent((EntityHuman) null, 1025, blockposition, 0); + } + } +- } else { ++ } else if (CraftEventFactory.handleBatToggleSleepEvent(this, true)) { // CraftBukkit - Call BatToggleSleepEvent + this.setResting(false); + if (!flag) { + this.level().levelEvent((EntityHuman) null, 1025, blockposition, 0); +@@ -176,7 +180,7 @@ + + this.zza = 0.5F; + this.setYRot(this.getYRot() + f1); +- if (this.random.nextInt(100) == 0 && this.level().getBlockState(blockposition1).isRedstoneConductor(this.level(), blockposition1)) { ++ if (this.random.nextInt(100) == 0 && this.level().getBlockState(blockposition1).isRedstoneConductor(this.level(), blockposition1) && CraftEventFactory.handleBatToggleSleepEvent(this, false)) { // CraftBukkit - Call BatToggleSleepEvent + this.setResting(true); + } + } +@@ -201,7 +205,7 @@ + if (this.isInvulnerableTo(damagesource)) { + return false; + } else { +- if (!this.level().isClientSide && this.isResting()) { ++ if (!this.level().isClientSide && this.isResting() && CraftEventFactory.handleBatToggleSleepEvent(this, true)) { // CraftBukkit - Call BatToggleSleepEvent + this.setResting(false); + } + diff --git a/patch-remap/og/net/minecraft/world/entity/animal/Bucketable.patch b/patch-remap/og/net/minecraft/world/entity/animal/Bucketable.patch new file mode 100644 index 0000000000..9fd8543e5a --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/Bucketable.patch @@ -0,0 +1,41 @@ +--- a/net/minecraft/world/entity/animal/Bucketable.java ++++ b/net/minecraft/world/entity/animal/Bucketable.java +@@ -15,6 +15,14 @@ + import net.minecraft.world.item.Items; + import net.minecraft.world.level.World; + ++// CraftBukkit start ++import net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata; ++import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerBucketEntityEvent; ++// CraftBukkit end ++ + public interface Bucketable { + + boolean fromBucket(); +@@ -94,10 +102,22 @@ + ItemStack itemstack = entityhuman.getItemInHand(enumhand); + + if (itemstack.getItem() == Items.WATER_BUCKET && t0.isAlive()) { +- t0.playSound(((Bucketable) t0).getPickupSound(), 1.0F, 1.0F); ++ // CraftBukkit start ++ // t0.playSound(((Bucketable) t0).getPickupSound(), 1.0F, 1.0F); // CraftBukkit - moved down + ItemStack itemstack1 = ((Bucketable) t0).getBucketItemStack(); + + ((Bucketable) t0).saveToBucketTag(itemstack1); ++ ++ PlayerBucketEntityEvent playerBucketFishEvent = CraftEventFactory.callPlayerFishBucketEvent(t0, entityhuman, itemstack, itemstack1, enumhand); ++ itemstack1 = CraftItemStack.asNMSCopy(playerBucketFishEvent.getEntityBucket()); ++ if (playerBucketFishEvent.isCancelled()) { ++ ((EntityPlayer) entityhuman).containerMenu.sendAllDataToRemote(); // We need to update inventory to resync client's bucket ++ ((EntityPlayer) entityhuman).connection.send(new PacketPlayOutSpawnEntity(t0)); // We need to play out these packets as the client assumes the fish is gone ++ t0.getEntityData().refresh((EntityPlayer) entityhuman); // Need to send data such as the display name to client ++ return Optional.of(EnumInteractionResult.FAIL); ++ } ++ t0.playSound(((Bucketable) t0).getPickupSound(), 1.0F, 1.0F); ++ // CraftBukkit end + ItemStack itemstack2 = ItemLiquidUtil.createFilledResult(itemstack, entityhuman, itemstack1, false); + + entityhuman.setItemInHand(enumhand, itemstack2); diff --git a/patch-remap/og/net/minecraft/world/entity/animal/EntityAnimal.patch b/patch-remap/og/net/minecraft/world/entity/animal/EntityAnimal.patch new file mode 100644 index 0000000000..f9b7960cb5 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/EntityAnimal.patch @@ -0,0 +1,101 @@ +--- a/net/minecraft/world/entity/animal/EntityAnimal.java ++++ b/net/minecraft/world/entity/animal/EntityAnimal.java +@@ -30,12 +30,19 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.pathfinder.PathType; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityBreedEvent; ++import org.bukkit.event.entity.EntityEnterLoveModeEvent; ++// CraftBukkit end ++ + public abstract class EntityAnimal extends EntityAgeable { + + protected static final int PARENT_AGE_AFTER_BREEDING = 6000; + public int inLove; + @Nullable + public UUID loveCause; ++ public ItemStack breedItem; // CraftBukkit - Add breedItem variable + + protected EntityAnimal(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -77,8 +84,13 @@ + if (this.isInvulnerableTo(damagesource)) { + return false; + } else { ++ // CraftBukkit start ++ boolean result = super.hurt(damagesource, f); ++ if (result) { + this.inLove = 0; +- return super.hurt(damagesource, f); ++ } ++ return result; ++ // CraftBukkit end + } + } + +@@ -172,10 +184,17 @@ + } + + public void setInLove(@Nullable EntityHuman entityhuman) { +- this.inLove = 600; ++ // CraftBukkit start ++ EntityEnterLoveModeEvent entityEnterLoveModeEvent = CraftEventFactory.callEntityEnterLoveModeEvent(entityhuman, this, 600); ++ if (entityEnterLoveModeEvent.isCancelled()) { ++ return; ++ } ++ this.inLove = entityEnterLoveModeEvent.getTicksInLove(); ++ // CraftBukkit end + if (entityhuman != null) { + this.loveCause = entityhuman.getUUID(); + } ++ this.breedItem = entityhuman.getInventory().getSelected(); // CraftBukkit + + this.level().broadcastEntityEvent(this, (byte) 18); + } +@@ -217,12 +236,29 @@ + if (entityageable != null) { + entityageable.setBaby(true); + entityageable.moveTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F); +- this.finalizeSpawnChildFromBreeding(worldserver, entityanimal, entityageable); +- worldserver.addFreshEntityWithPassengers(entityageable); ++ // CraftBukkit start - call EntityBreedEvent ++ EntityPlayer breeder = Optional.ofNullable(this.getLoveCause()).or(() -> { ++ return Optional.ofNullable(entityanimal.getLoveCause()); ++ }).orElse(null); ++ int experience = this.getRandom().nextInt(7) + 1; ++ EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(entityageable, this, entityanimal, breeder, this.breedItem, experience); ++ if (entityBreedEvent.isCancelled()) { ++ return; ++ } ++ experience = entityBreedEvent.getExperience(); ++ this.finalizeSpawnChildFromBreeding(worldserver, entityanimal, entityageable, experience); ++ worldserver.addFreshEntityWithPassengers(entityageable, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); ++ // CraftBukkit end + } + } + + public void finalizeSpawnChildFromBreeding(WorldServer worldserver, EntityAnimal entityanimal, @Nullable EntityAgeable entityageable) { ++ // CraftBukkit start ++ this.finalizeSpawnChildFromBreeding(worldserver, entityanimal, entityageable, this.getRandom().nextInt(7) + 1); ++ } ++ ++ public void finalizeSpawnChildFromBreeding(WorldServer worldserver, EntityAnimal entityanimal, @Nullable EntityAgeable entityageable, int experience) { ++ // CraftBukkit end + Optional.ofNullable(this.getLoveCause()).or(() -> { + return Optional.ofNullable(entityanimal.getLoveCause()); + }).ifPresent((entityplayer) -> { +@@ -235,7 +271,11 @@ + entityanimal.resetLove(); + worldserver.broadcastEntityEvent(this, (byte) 18); + if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +- worldserver.addFreshEntity(new EntityExperienceOrb(worldserver, this.getX(), this.getY(), this.getZ(), this.getRandom().nextInt(7) + 1)); ++ // CraftBukkit start - use event experience ++ if (experience > 0) { ++ worldserver.addFreshEntity(new EntityExperienceOrb(worldserver, this.getX(), this.getY(), this.getZ(), experience)); ++ } ++ // CraftBukkit end + } + + } diff --git a/patch-remap/og/net/minecraft/world/entity/animal/EntityBee.patch b/patch-remap/og/net/minecraft/world/entity/animal/EntityBee.patch new file mode 100644 index 0000000000..88399604e3 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/EntityBee.patch @@ -0,0 +1,108 @@ +--- a/net/minecraft/world/entity/animal/EntityBee.java ++++ b/net/minecraft/world/entity/animal/EntityBee.java +@@ -90,6 +90,12 @@ + import net.minecraft.world.level.pathfinder.PathType; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityPotionEffectEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end ++ + public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityBird { + + public static final float FLAP_DEGREES_PER_TICK = 120.32113F; +@@ -187,12 +193,19 @@ + + @Override + public void addAdditionalSaveData(NBTTagCompound nbttagcompound) { ++ // CraftBukkit start - selectively save data ++ addAdditionalSaveData(nbttagcompound, true); ++ } ++ ++ @Override ++ public void addAdditionalSaveData(NBTTagCompound nbttagcompound, boolean includeAll) { ++ // CraftBukkit end + super.addAdditionalSaveData(nbttagcompound); +- if (this.hasHive()) { ++ if (includeAll && this.hasHive()) { // CraftBukkit - selectively save hive + nbttagcompound.put("HivePos", GameProfileSerializer.writeBlockPos(this.getHivePos())); + } + +- if (this.hasSavedFlowerPos()) { ++ if (includeAll && this.hasSavedFlowerPos()) { // CraftBukkit - selectively save flower + nbttagcompound.put("FlowerPos", GameProfileSerializer.writeBlockPos(this.getSavedFlowerPos())); + } + +@@ -242,7 +255,7 @@ + } + + if (b0 > 0) { +- ((EntityLiving) entity).addEffect(new MobEffect(MobEffects.POISON, b0 * 20, 0), this); ++ ((EntityLiving) entity).addEffect(new MobEffect(MobEffects.POISON, b0 * 20, 0), this, EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + +@@ -640,11 +653,14 @@ + if (this.isInvulnerableTo(damagesource)) { + return false; + } else { +- if (!this.level().isClientSide) { ++ // CraftBukkit start - Only stop pollinating if entity was damaged ++ boolean result = super.hurt(damagesource, f); ++ if (result && !this.level().isClientSide) { ++ // CraftBukkit end + this.beePollinateGoal.stopPollinating(); + } + +- return super.hurt(damagesource, f); ++ return result; // CraftBukkit + } + } + +@@ -999,7 +1015,7 @@ + + e() { + super(); +- this.travellingTicks = EntityBee.this.level().random.nextInt(10); ++ this.travellingTicks = EntityBee.this.random.nextInt(10); // CraftBukkit - SPIGOT-7495: Give Bees another chance and let them use their own random, avoid concurrency issues + this.blacklistedTargets = Lists.newArrayList(); + this.setFlags(EnumSet.of(PathfinderGoal.Type.MOVE)); + } +@@ -1116,7 +1132,7 @@ + + f() { + super(); +- this.travellingTicks = EntityBee.this.level().random.nextInt(10); ++ this.travellingTicks = EntityBee.this.random.nextInt(10); // CraftBukkit - SPIGOT-7495: Give Bees another chance and let them use their own random, avoid concurrency issues + this.setFlags(EnumSet.of(PathfinderGoal.Type.MOVE)); + } + +@@ -1216,7 +1232,7 @@ + } + } + +- if (iblockdata1 != null) { ++ if (iblockdata1 != null && CraftEventFactory.callEntityChangeBlockEvent(EntityBee.this, blockposition, iblockdata1)) { // CraftBukkit + EntityBee.this.level().levelEvent(2005, blockposition, 0); + EntityBee.this.level().setBlockAndUpdate(blockposition, iblockdata1); + EntityBee.this.incrementNumCropsGrownSincePollination(); +@@ -1289,7 +1305,7 @@ + @Override + protected void alertOther(EntityInsentient entityinsentient, EntityLiving entityliving) { + if (entityinsentient instanceof EntityBee && this.mob.hasLineOfSight(entityliving)) { +- entityinsentient.setTarget(entityliving); ++ entityinsentient.setTarget(entityliving, EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY, true); // CraftBukkit - reason + } + + } +@@ -1298,7 +1314,7 @@ + private static class c extends PathfinderGoalNearestAttackableTarget { + + c(EntityBee entitybee) { +- Objects.requireNonNull(entitybee); ++ // Objects.requireNonNull(entitybee); // CraftBukkit - decompile error + super(entitybee, EntityHuman.class, 10, true, false, entitybee::isAngryAt); + } + diff --git a/patch-remap/og/net/minecraft/world/entity/animal/EntityCat.patch b/patch-remap/og/net/minecraft/world/entity/animal/EntityCat.patch new file mode 100644 index 0000000000..5f15487654 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/EntityCat.patch @@ -0,0 +1,51 @@ +--- a/net/minecraft/world/entity/animal/EntityCat.java ++++ b/net/minecraft/world/entity/animal/EntityCat.java +@@ -413,7 +413,7 @@ + } + } else if (this.isFood(itemstack)) { + this.usePlayerItem(entityhuman, enumhand, itemstack); +- if (this.random.nextInt(3) == 0) { ++ if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled()) { // CraftBukkit + this.tame(entityhuman); + this.setOrderedToSit(true); + this.level().broadcastEntityEvent(this, (byte) 7); +@@ -475,7 +475,7 @@ + private static class PathfinderGoalTemptChance extends PathfinderGoalTempt { + + @Nullable +- private EntityHuman selectedPlayer; ++ private EntityLiving selectedPlayer; // CraftBukkit + private final EntityCat cat; + + public PathfinderGoalTemptChance(EntityCat entitycat, double d0, RecipeItemStack recipeitemstack, boolean flag) { +@@ -616,7 +616,15 @@ + while (iterator.hasNext()) { + ItemStack itemstack = (ItemStack) iterator.next(); + +- this.cat.level().addFreshEntity(new EntityItem(this.cat.level(), (double) blockposition_mutableblockposition.getX() - (double) MathHelper.sin(this.cat.yBodyRot * 0.017453292F), (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + (double) MathHelper.cos(this.cat.yBodyRot * 0.017453292F), itemstack)); ++ // CraftBukkit start ++ EntityItem entityitem = new EntityItem(this.cat.level(), (double) blockposition_mutableblockposition.getX() - (double) MathHelper.sin(this.cat.yBodyRot * 0.017453292F), (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + (double) MathHelper.cos(this.cat.yBodyRot * 0.017453292F), itemstack); ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.cat.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ entityitem.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ continue; ++ } ++ this.cat.level().addFreshEntity(entityitem); ++ // CraftBukkit end + } + + } +@@ -648,10 +656,10 @@ + private final EntityCat cat; + + public a(EntityCat entitycat, Class oclass, float f, double d0, double d1) { +- Predicate predicate = IEntitySelector.NO_CREATIVE_OR_SPECTATOR; ++ // Predicate predicate = IEntitySelector.NO_CREATIVE_OR_SPECTATOR; // CraftBukkit - decompile error + +- Objects.requireNonNull(predicate); +- super(entitycat, oclass, f, d0, d1, predicate::test); ++ // Objects.requireNonNull(predicate); // CraftBukkit - decompile error ++ super(entitycat, oclass, f, d0, d1, IEntitySelector.NO_CREATIVE_OR_SPECTATOR::test); // CraftBukkit - decompile error + this.cat = entitycat; + } + diff --git a/patch-remap/og/net/minecraft/world/entity/animal/EntityChicken.patch b/patch-remap/og/net/minecraft/world/entity/animal/EntityChicken.patch new file mode 100644 index 0000000000..30e374f7f8 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/EntityChicken.patch @@ -0,0 +1,12 @@ +--- a/net/minecraft/world/entity/animal/EntityChicken.java ++++ b/net/minecraft/world/entity/animal/EntityChicken.java +@@ -97,7 +97,9 @@ + this.flap += this.flapping * 2.0F; + if (!this.level().isClientSide && this.isAlive() && !this.isBaby() && !this.isChickenJockey() && --this.eggTime <= 0) { + this.playSound(SoundEffects.CHICKEN_EGG, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation((IMaterial) Items.EGG); ++ this.forceDrops = false; // CraftBukkit + this.gameEvent(GameEvent.ENTITY_PLACE); + this.eggTime = this.random.nextInt(6000) + 6000; + } diff --git a/patch-remap/og/net/minecraft/world/entity/animal/EntityCow.patch b/patch-remap/og/net/minecraft/world/entity/animal/EntityCow.patch new file mode 100644 index 0000000000..c09b33ea87 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/EntityCow.patch @@ -0,0 +1,33 @@ +--- a/net/minecraft/world/entity/animal/EntityCow.java ++++ b/net/minecraft/world/entity/animal/EntityCow.java +@@ -33,6 +33,12 @@ + import net.minecraft.world.level.block.state.IBlockData; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerBucketFillEvent; ++// CraftBukkit end ++ + public class EntityCow extends EntityAnimal { + + public EntityCow(EntityTypes entitytypes, World world) { +@@ -85,8 +91,16 @@ + ItemStack itemstack = entityhuman.getItemInHand(enumhand); + + if (itemstack.is(Items.BUCKET) && !this.isBaby()) { ++ // CraftBukkit start - Got milk? ++ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) entityhuman.level(), entityhuman, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, enumhand); ++ ++ if (event.isCancelled()) { ++ return EnumInteractionResult.PASS; ++ } ++ // CraftBukkit end ++ + entityhuman.playSound(SoundEffects.COW_MILK, 1.0F, 1.0F); +- ItemStack itemstack1 = ItemLiquidUtil.createFilledResult(itemstack, entityhuman, Items.MILK_BUCKET.getDefaultInstance()); ++ ItemStack itemstack1 = ItemLiquidUtil.createFilledResult(itemstack, entityhuman, CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit + + entityhuman.setItemInHand(enumhand, itemstack1); + return EnumInteractionResult.sidedSuccess(this.level().isClientSide); diff --git a/patch-remap/og/net/minecraft/world/entity/animal/EntityDolphin.patch b/patch-remap/og/net/minecraft/world/entity/animal/EntityDolphin.patch new file mode 100644 index 0000000000..c5e7b5f4cd --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/EntityDolphin.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/entity/animal/EntityDolphin.java ++++ b/net/minecraft/world/entity/animal/EntityDolphin.java +@@ -61,8 +61,19 @@ + import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityPotionEffectEvent; ++// CraftBukkit end ++ + public class EntityDolphin extends EntityWaterAnimal { + ++ // CraftBukkit start - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ @Override ++ public int getDefaultMaxAirSupply() { ++ return TOTAL_AIR_SUPPLY; ++ } ++ // CraftBukkit end + private static final DataWatcherObject TREASURE_POS = DataWatcher.defineId(EntityDolphin.class, DataWatcherRegistry.BLOCK_POS); + private static final DataWatcherObject GOT_FISH = DataWatcher.defineId(EntityDolphin.class, DataWatcherRegistry.BOOLEAN); + private static final DataWatcherObject MOISTNESS_LEVEL = DataWatcher.defineId(EntityDolphin.class, DataWatcherRegistry.INT); +@@ -185,7 +196,7 @@ + + @Override + public int getMaxAirSupply() { +- return 4800; ++ return maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() + } + + @Override +@@ -226,6 +237,12 @@ + ItemStack itemstack = entityitem.getItem(); + + if (this.canHoldItem(itemstack)) { ++ // CraftBukkit start - call EntityPickupItemEvent ++ if (CraftEventFactory.callEntityPickupItemEvent(this, entityitem, 0, false).isCancelled()) { ++ return; ++ } ++ itemstack = entityitem.getItem(); // CraftBukkit- update ItemStack from event ++ // CraftBukkit start + this.onItemPickup(entityitem); + this.setItemSlot(EnumItemSlot.MAINHAND, itemstack); + this.setGuaranteedDrop(EnumItemSlot.MAINHAND); +@@ -484,7 +501,7 @@ + + @Override + public void start() { +- this.player.addEffect(new MobEffect(MobEffects.DOLPHINS_GRACE, 100), this.dolphin); ++ this.player.addEffect(new MobEffect(MobEffects.DOLPHINS_GRACE, 100), this.dolphin, EntityPotionEffectEvent.Cause.DOLPHIN); // CraftBukkit + } + + @Override +@@ -503,7 +520,7 @@ + } + + if (this.player.isSwimming() && this.player.level().random.nextInt(6) == 0) { +- this.player.addEffect(new MobEffect(MobEffects.DOLPHINS_GRACE, 100), this.dolphin); ++ this.player.addEffect(new MobEffect(MobEffects.DOLPHINS_GRACE, 100), this.dolphin, EntityPotionEffectEvent.Cause.DOLPHIN); // CraftBukkit + } + + } diff --git a/patch-remap/og/net/minecraft/world/entity/animal/EntityFox.patch b/patch-remap/og/net/minecraft/world/entity/animal/EntityFox.patch new file mode 100644 index 0000000000..ec69250917 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/EntityFox.patch @@ -0,0 +1,69 @@ +--- a/net/minecraft/world/entity/animal/EntityFox.java ++++ b/net/minecraft/world/entity/animal/EntityFox.java +@@ -523,7 +523,8 @@ + protected void pickUpItem(EntityItem entityitem) { + ItemStack itemstack = entityitem.getItem(); + +- if (this.canHoldItem(itemstack)) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, entityitem, itemstack.getCount() - 1, !this.canHoldItem(itemstack)).isCancelled()) { // CraftBukkit - call EntityPickupItemEvent ++ itemstack = entityitem.getItem(); // CraftBukkit - update ItemStack from event + int i = itemstack.getCount(); + + if (i > 1) { +@@ -883,6 +884,16 @@ + if (entityplayer1 != null && entityplayer != entityplayer1) { + entityfox.addTrustedUUID(entityplayer1.getUUID()); + } ++ // CraftBukkit start - call EntityBreedEvent ++ entityfox.setAge(-24000); ++ entityfox.moveTo(this.animal.getX(), this.animal.getY(), this.animal.getZ(), 0.0F, 0.0F); ++ int experience = this.animal.getRandom().nextInt(7) + 1; ++ org.bukkit.event.entity.EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(entityfox, animal, partner, entityplayer, this.animal.breedItem, experience); ++ if (entityBreedEvent.isCancelled()) { ++ return; ++ } ++ experience = entityBreedEvent.getExperience(); ++ // CraftBukkit end + + if (entityplayer2 != null) { + entityplayer2.awardStat(StatisticList.ANIMALS_BRED); +@@ -893,12 +904,14 @@ + this.partner.setAge(6000); + this.animal.resetLove(); + this.partner.resetLove(); +- entityfox.setAge(-24000); +- entityfox.moveTo(this.animal.getX(), this.animal.getY(), this.animal.getZ(), 0.0F, 0.0F); +- worldserver.addFreshEntityWithPassengers(entityfox); ++ worldserver.addFreshEntityWithPassengers(entityfox, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - added SpawnReason + this.level.broadcastEntityEvent(this.animal, (byte) 18); + if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +- this.level.addFreshEntity(new EntityExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), this.animal.getRandom().nextInt(7) + 1)); ++ // CraftBukkit start - use event experience ++ if (experience > 0) { ++ this.level.addFreshEntity(new EntityExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience)); ++ } ++ // CraftBukkit end + } + + } +@@ -1294,6 +1307,11 @@ + int i = (Integer) iblockdata.getValue(BlockSweetBerryBush.AGE); + + iblockdata.setValue(BlockSweetBerryBush.AGE, 1); ++ // CraftBukkit start - call EntityChangeBlockEvent ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(EntityFox.this, this.blockPos, iblockdata.setValue(BlockSweetBerryBush.AGE, 1))) { ++ return; ++ } ++ // CraftBukkit end + int j = 1 + EntityFox.this.level().random.nextInt(2) + (i == 3 ? 1 : 0); + ItemStack itemstack = EntityFox.this.getItemBySlot(EnumItemSlot.MAINHAND); + +@@ -1451,7 +1469,7 @@ + private EntityLiving trustedLastHurt; + private int timestamp; + +- public a(Class oclass, boolean flag, boolean flag1, @Nullable Predicate predicate) { ++ public a(Class oclass, boolean flag, boolean flag1, @Nullable Predicate predicate) { // CraftBukkit - decompile error + super(EntityFox.this, oclass, 10, flag, flag1, predicate); + } + diff --git a/patch-remap/og/net/minecraft/world/entity/animal/EntityIronGolem.patch b/patch-remap/og/net/minecraft/world/entity/animal/EntityIronGolem.patch new file mode 100644 index 0000000000..9142266872 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/EntityIronGolem.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/animal/EntityIronGolem.java ++++ b/net/minecraft/world/entity/animal/EntityIronGolem.java +@@ -102,7 +102,7 @@ + @Override + protected void doPush(Entity entity) { + if (entity instanceof IMonster && !(entity instanceof EntityCreeper) && this.getRandom().nextInt(20) == 0) { +- this.setTarget((EntityLiving) entity); ++ this.setTarget((EntityLiving) entity, org.bukkit.event.entity.EntityTargetLivingEntityEvent.TargetReason.COLLISION, true); // CraftBukkit - set reason + } + + super.doPush(entity); diff --git a/patch-remap/og/net/minecraft/world/entity/animal/EntityMushroomCow.patch b/patch-remap/og/net/minecraft/world/entity/animal/EntityMushroomCow.patch new file mode 100644 index 0000000000..9e8f913847 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/EntityMushroomCow.patch @@ -0,0 +1,65 @@ +--- a/net/minecraft/world/entity/animal/EntityMushroomCow.java ++++ b/net/minecraft/world/entity/animal/EntityMushroomCow.java +@@ -42,6 +42,13 @@ + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityDropItemEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++// CraftBukkit end ++ + public class EntityMushroomCow extends EntityCow implements IShearable, VariantHolder { + + private static final DataWatcherObject DATA_TYPE = DataWatcher.defineId(EntityMushroomCow.class, DataWatcherRegistry.STRING); +@@ -114,6 +121,11 @@ + this.playSound(soundeffect, 1.0F, 1.0F); + return EnumInteractionResult.sidedSuccess(this.level().isClientSide); + } else if (itemstack.is(Items.SHEARS) && this.readyForShearing()) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handlePlayerShearEntityEvent(entityhuman, this, itemstack, enumhand)) { ++ return EnumInteractionResult.PASS; ++ } ++ // CraftBukkit end + this.shear(SoundCategory.PLAYERS); + this.gameEvent(GameEvent.SHEAR, entityhuman); + if (!this.level().isClientSide) { +@@ -161,7 +173,7 @@ + + if (entitycow != null) { + ((WorldServer) this.level()).sendParticles(Particles.EXPLOSION, this.getX(), this.getY(0.5D), this.getZ(), 1, 0.0D, 0.0D, 0.0D, 0.0D); +- this.discard(); ++ // this.discard(); // CraftBukkit - moved down + entitycow.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); + entitycow.setHealth(this.getHealth()); + entitycow.yBodyRot = this.yBodyRot; +@@ -175,10 +187,25 @@ + } + + entitycow.setInvulnerable(this.isInvulnerable()); +- this.level().addFreshEntity(entitycow); ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, entitycow, EntityTransformEvent.TransformReason.SHEARED).isCancelled()) { ++ return; ++ } ++ this.level().addFreshEntity(entitycow, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SHEARED); ++ ++ this.discard(); // CraftBukkit - from above ++ // CraftBukkit end + + for (int i = 0; i < 5; ++i) { +- this.level().addFreshEntity(new EntityItem(this.level(), this.getX(), this.getY(1.0D), this.getZ(), new ItemStack(this.getVariant().blockState.getBlock()))); ++ // CraftBukkit start ++ EntityItem entityitem = new EntityItem(this.level(), this.getX(), this.getY(1.0D), this.getZ(), new ItemStack(this.getVariant().blockState.getBlock())); ++ EntityDropItemEvent event = new EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ continue; ++ } ++ this.level().addFreshEntity(entityitem); ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/animal/EntityOcelot.patch b/patch-remap/og/net/minecraft/world/entity/animal/EntityOcelot.patch new file mode 100644 index 0000000000..e57d802e95 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/EntityOcelot.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/world/entity/animal/EntityOcelot.java ++++ b/net/minecraft/world/entity/animal/EntityOcelot.java +@@ -179,7 +179,7 @@ + if ((this.temptGoal == null || this.temptGoal.isRunning()) && !this.isTrusting() && this.isFood(itemstack) && entityhuman.distanceToSqr((Entity) this) < 9.0D) { + this.usePlayerItem(entityhuman, enumhand, itemstack); + if (!this.level().isClientSide) { +- if (this.random.nextInt(3) == 0) { ++ if (this.random.nextInt(3) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled()) { // CraftBukkit - added event call and isCancelled check + this.setTrusting(true); + this.spawnTrustingParticles(true); + this.level().broadcastEntityEvent(this, (byte) 41); +@@ -315,10 +315,10 @@ + private final EntityOcelot ocelot; + + public a(EntityOcelot entityocelot, Class oclass, float f, double d0, double d1) { +- Predicate predicate = IEntitySelector.NO_CREATIVE_OR_SPECTATOR; ++ // Predicate predicate = IEntitySelector.NO_CREATIVE_OR_SPECTATOR; // CraftBukkit - decompile error + +- Objects.requireNonNull(predicate); +- super(entityocelot, oclass, f, d0, d1, predicate::test); ++ // Objects.requireNonNull(predicate); // CraftBukkit - decompile error ++ super(entityocelot, oclass, f, d0, d1, IEntitySelector.NO_CREATIVE_OR_SPECTATOR::test); // CraftBukkit - decompile error + this.ocelot = entityocelot; + } + diff --git a/patch-remap/og/net/minecraft/world/entity/animal/EntityPanda.patch b/patch-remap/og/net/minecraft/world/entity/animal/EntityPanda.patch new file mode 100644 index 0000000000..7d72eaafc1 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/EntityPanda.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/world/entity/animal/EntityPanda.java ++++ b/net/minecraft/world/entity/animal/EntityPanda.java +@@ -67,6 +67,11 @@ + import net.minecraft.world.phys.Vec3D; + import org.joml.Vector3f; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end ++ + public class EntityPanda extends EntityAnimal { + + private static final DataWatcherObject UNHAPPY_COUNTER = DataWatcher.defineId(EntityPanda.class, DataWatcherRegistry.INT); +@@ -534,7 +539,7 @@ + + @Override + protected void pickUpItem(EntityItem entityitem) { +- if (this.getItemBySlot(EnumItemSlot.MAINHAND).isEmpty() && EntityPanda.PANDA_ITEMS.test(entityitem)) { ++ if (!CraftEventFactory.callEntityPickupItemEvent(this, entityitem, 0, !(this.getItemBySlot(EnumItemSlot.MAINHAND).isEmpty() && EntityPanda.PANDA_ITEMS.test(entityitem))).isCancelled()) { // CraftBukkit + this.onItemPickup(entityitem); + ItemStack itemstack = entityitem.getItem(); + +@@ -870,10 +875,10 @@ + private final EntityPanda panda; + + public c(EntityPanda entitypanda, Class oclass, float f, double d0, double d1) { +- Predicate predicate = IEntitySelector.NO_SPECTATORS; ++ // Predicate predicate = IEntitySelector.NO_SPECTATORS; + +- Objects.requireNonNull(predicate); +- super(entitypanda, oclass, f, d0, d1, predicate::test); ++ // Objects.requireNonNull(predicate); ++ super(entitypanda, oclass, f, d0, d1, IEntitySelector.NO_SPECTATORS::test); + this.panda = entitypanda; + } + +@@ -1112,7 +1117,7 @@ + @Override + protected void alertOther(EntityInsentient entityinsentient, EntityLiving entityliving) { + if (entityinsentient instanceof EntityPanda && entityinsentient.isAggressive()) { +- entityinsentient.setTarget(entityliving); ++ entityinsentient.setTarget(entityliving, EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY, true); // CraftBukkit + } + + } diff --git a/patch-remap/og/net/minecraft/world/entity/animal/EntityParrot.patch b/patch-remap/og/net/minecraft/world/entity/animal/EntityParrot.patch new file mode 100644 index 0000000000..3aa036a9b0 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/EntityParrot.patch @@ -0,0 +1,46 @@ +--- a/net/minecraft/world/entity/animal/EntityParrot.java ++++ b/net/minecraft/world/entity/animal/EntityParrot.java +@@ -263,7 +263,7 @@ + } + + if (!this.level().isClientSide) { +- if (this.random.nextInt(10) == 0) { ++ if (this.random.nextInt(10) == 0 && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled()) { // CraftBukkit + this.tame(entityhuman); + this.level().broadcastEntityEvent(this, (byte) 7); + } else { +@@ -277,7 +277,7 @@ + itemstack.shrink(1); + } + +- this.addEffect(new MobEffect(MobEffects.POISON, 900)); ++ this.addEffect(new MobEffect(MobEffects.POISON, 900), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.FOOD); // CraftBukkit + if (entityhuman.isCreative() || !this.isInvulnerable()) { + this.hurt(this.damageSources().playerAttack(entityhuman), Float.MAX_VALUE); + } +@@ -384,7 +384,7 @@ + + @Override + public boolean isPushable() { +- return true; ++ return super.isPushable(); // CraftBukkit - collidable API + } + + @Override +@@ -399,11 +399,14 @@ + if (this.isInvulnerableTo(damagesource)) { + return false; + } else { +- if (!this.level().isClientSide) { ++ // CraftBukkit start ++ boolean result = super.hurt(damagesource, f); ++ if (!this.level().isClientSide && result) { ++ // CraftBukkit end + this.setOrderedToSit(false); + } + +- return super.hurt(damagesource, f); ++ return result; // CraftBukkit + } + } + diff --git a/patch-remap/og/net/minecraft/world/entity/animal/EntityPig.patch b/patch-remap/og/net/minecraft/world/entity/animal/EntityPig.patch new file mode 100644 index 0000000000..9066083a4d --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/EntityPig.patch @@ -0,0 +1,28 @@ +--- a/net/minecraft/world/entity/animal/EntityPig.java ++++ b/net/minecraft/world/entity/animal/EntityPig.java +@@ -51,6 +51,10 @@ + import net.minecraft.world.phys.Vec3D; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable { + + private static final DataWatcherObject DATA_SADDLE_ID = DataWatcher.defineId(EntityPig.class, DataWatcherRegistry.BOOLEAN); +@@ -252,7 +256,13 @@ + } + + entitypigzombie.setPersistenceRequired(); +- worldserver.addFreshEntity(entitypigzombie); ++ // CraftBukkit start ++ if (CraftEventFactory.callPigZapEvent(this, entitylightning, entitypigzombie).isCancelled()) { ++ return; ++ } ++ // CraftBukkit - added a reason for spawning this creature ++ worldserver.addFreshEntity(entitypigzombie, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); ++ // CraftBukkit end + this.discard(); + } else { + super.thunderHit(worldserver, entitylightning); diff --git a/patch-remap/og/net/minecraft/world/entity/animal/EntityPufferFish.patch b/patch-remap/og/net/minecraft/world/entity/animal/EntityPufferFish.patch new file mode 100644 index 0000000000..e01702784b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/EntityPufferFish.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/entity/animal/EntityPufferFish.java ++++ b/net/minecraft/world/entity/animal/EntityPufferFish.java +@@ -144,7 +144,7 @@ + int i = this.getPuffState(); + + if (entityinsentient.hurt(this.damageSources().mobAttack(this), (float) (1 + i))) { +- entityinsentient.addEffect(new MobEffect(MobEffects.POISON, 60 * i, 0), this); ++ entityinsentient.addEffect(new MobEffect(MobEffects.POISON, 60 * i, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + this.playSound(SoundEffects.PUFFER_FISH_STING, 1.0F, 1.0F); + } + +@@ -159,7 +159,7 @@ + ((EntityPlayer) entityhuman).connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.PUFFER_FISH_STING, 0.0F)); + } + +- entityhuman.addEffect(new MobEffect(MobEffects.POISON, 60 * i, 0), this); ++ entityhuman.addEffect(new MobEffect(MobEffects.POISON, 60 * i, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + + } diff --git a/patch-remap/og/net/minecraft/world/entity/animal/EntityRabbit.patch b/patch-remap/og/net/minecraft/world/entity/animal/EntityRabbit.patch new file mode 100644 index 0000000000..faa5bddea2 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/EntityRabbit.patch @@ -0,0 +1,41 @@ +--- a/net/minecraft/world/entity/animal/EntityRabbit.java ++++ b/net/minecraft/world/entity/animal/EntityRabbit.java +@@ -67,6 +67,10 @@ + import net.minecraft.world.level.pathfinder.PathEntity; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class EntityRabbit extends EntityAnimal implements VariantHolder { + + public static final double STROLL_SPEED_MOD = 0.6D; +@@ -89,7 +93,6 @@ + super(entitytypes, world); + this.jumpControl = new EntityRabbit.ControllerJumpRabbit(this); + this.moveControl = new EntityRabbit.ControllerMoveRabbit(this); +- this.setSpeedModifier(0.0D); + } + + @Override +@@ -577,9 +580,19 @@ + int i = (Integer) iblockdata.getValue(BlockCarrots.AGE); + + if (i == 0) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.rabbit, blockposition, Blocks.AIR.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end + world.setBlock(blockposition, Blocks.AIR.defaultBlockState(), 2); + world.destroyBlock(blockposition, true, this.rabbit); + } else { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.rabbit, blockposition, iblockdata.setValue(BlockCarrots.AGE, i - 1))) { ++ return; ++ } ++ // CraftBukkit end + world.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockCarrots.AGE, i - 1), 2); + world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.a.of((Entity) this.rabbit)); + world.levelEvent(2001, blockposition, Block.getId(iblockdata)); diff --git a/patch-remap/og/net/minecraft/world/entity/animal/EntitySheep.patch b/patch-remap/og/net/minecraft/world/entity/animal/EntitySheep.patch new file mode 100644 index 0000000000..efda17bf77 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/EntitySheep.patch @@ -0,0 +1,80 @@ +--- a/net/minecraft/world/entity/animal/EntitySheep.java ++++ b/net/minecraft/world/entity/animal/EntitySheep.java +@@ -66,6 +66,14 @@ + import net.minecraft.world.level.storage.loot.LootTables; + import org.joml.Vector3f; + ++// CraftBukkit start ++import net.minecraft.world.inventory.InventoryCraftResult; ++import net.minecraft.world.item.Item; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.SheepRegrowWoolEvent; ++import org.bukkit.inventory.InventoryView; ++// CraftBukkit end ++ + public class EntitySheep extends EntityAnimal implements IShearable { + + private static final int EAT_ANIMATION_TICKS = 40; +@@ -246,6 +254,11 @@ + + if (itemstack.is(Items.SHEARS)) { + if (!this.level().isClientSide && this.readyForShearing()) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handlePlayerShearEntityEvent(entityhuman, this, itemstack, enumhand)) { ++ return EnumInteractionResult.PASS; ++ } ++ // CraftBukkit end + this.shear(SoundCategory.PLAYERS); + this.gameEvent(GameEvent.SHEAR, entityhuman); + itemstack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { +@@ -267,7 +280,9 @@ + int i = 1 + this.random.nextInt(3); + + for (int j = 0; j < i; ++j) { ++ this.forceDrops = true; // CraftBukkit + EntityItem entityitem = this.spawnAtLocation((IMaterial) EntitySheep.ITEM_BY_DYE.get(this.getColor()), 1); ++ this.forceDrops = false; // CraftBukkit + + if (entityitem != null) { + entityitem.setDeltaMovement(entityitem.getDeltaMovement().add((double) ((this.random.nextFloat() - this.random.nextFloat()) * 0.1F), (double) (this.random.nextFloat() * 0.05F), (double) ((this.random.nextFloat() - this.random.nextFloat()) * 0.1F))); +@@ -360,6 +375,12 @@ + + @Override + public void ate() { ++ // CraftBukkit start ++ SheepRegrowWoolEvent event = new SheepRegrowWoolEvent((org.bukkit.entity.Sheep) this.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) return; ++ // CraftBukkit end + super.ate(); + this.setSheared(false); + if (this.isBaby()) { +@@ -379,7 +400,7 @@ + EnumColor enumcolor = ((EntitySheep) entityanimal).getColor(); + EnumColor enumcolor1 = ((EntitySheep) entityanimal1).getColor(); + InventoryCrafting inventorycrafting = makeContainer(enumcolor, enumcolor1); +- Optional optional = this.level().getRecipeManager().getRecipeFor(Recipes.CRAFTING, inventorycrafting, this.level()).map((recipeholder) -> { ++ Optional optional = this.level().getRecipeManager().getRecipeFor(Recipes.CRAFTING, inventorycrafting, this.level()).map((recipeholder) -> { // CraftBukkit - decompile error + return ((RecipeCrafting) recipeholder.value()).assemble(inventorycrafting, this.level().registryAccess()); + }).map(ItemStack::getItem); + +@@ -402,10 +423,18 @@ + public boolean stillValid(EntityHuman entityhuman) { + return false; + } ++ ++ // CraftBukkit start ++ @Override ++ public InventoryView getBukkitView() { ++ return null; // TODO: O.O ++ } ++ // CraftBukkit end + }, 2, 1); + + transientcraftingcontainer.setItem(0, new ItemStack(ItemDye.byColor(enumcolor))); + transientcraftingcontainer.setItem(1, new ItemStack(ItemDye.byColor(enumcolor1))); ++ transientcraftingcontainer.resultInventory = new InventoryCraftResult(); // CraftBukkit - add result slot for event + return transientcraftingcontainer; + } + diff --git a/patch-remap/og/net/minecraft/world/entity/animal/EntitySnowman.patch b/patch-remap/og/net/minecraft/world/entity/animal/EntitySnowman.patch new file mode 100644 index 0000000000..6f2789438a --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/EntitySnowman.patch @@ -0,0 +1,57 @@ +--- a/net/minecraft/world/entity/animal/EntitySnowman.java ++++ b/net/minecraft/world/entity/animal/EntitySnowman.java +@@ -41,6 +41,10 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class EntitySnowman extends EntityGolem implements IShearable, IRangedEntity { + + private static final DataWatcherObject DATA_PUMPKIN_ID = DataWatcher.defineId(EntitySnowman.class, DataWatcherRegistry.BYTE); +@@ -97,7 +101,7 @@ + super.aiStep(); + if (!this.level().isClientSide) { + if (this.level().getBiome(this.blockPosition()).is(BiomeTags.SNOW_GOLEM_MELTS)) { +- this.hurt(this.damageSources().onFire(), 1.0F); ++ this.hurt(this.damageSources().melting, 1.0F); // CraftBukkit - DamageSource.BURN -> CraftEventFactory.MELTING + } + + if (!this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +@@ -113,7 +117,11 @@ + BlockPosition blockposition = new BlockPosition(j, k, l); + + if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) { +- this.level().setBlockAndUpdate(blockposition, iblockdata); ++ // CraftBukkit start ++ if (!CraftEventFactory.handleBlockFormEvent(this.level(), blockposition, iblockdata, this)) { ++ continue; ++ } ++ // CraftBukkit end + this.level().gameEvent(GameEvent.BLOCK_PLACE, blockposition, GameEvent.a.of(this, iblockdata)); + } + } +@@ -145,6 +153,11 @@ + ItemStack itemstack = entityhuman.getItemInHand(enumhand); + + if (itemstack.is(Items.SHEARS) && this.readyForShearing()) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handlePlayerShearEntityEvent(entityhuman, this, itemstack, enumhand)) { ++ return EnumInteractionResult.PASS; ++ } ++ // CraftBukkit end + this.shear(SoundCategory.PLAYERS); + this.gameEvent(GameEvent.SHEAR, entityhuman); + if (!this.level().isClientSide) { +@@ -164,7 +177,9 @@ + this.level().playSound((EntityHuman) null, (Entity) this, SoundEffects.SNOW_GOLEM_SHEAR, soundcategory, 1.0F, 1.0F); + if (!this.level().isClientSide()) { + this.setPumpkin(false); ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation(new ItemStack(Items.CARVED_PUMPKIN), 1.7F); ++ this.forceDrops = false; // CraftBukkit + } + + } diff --git a/patch-remap/og/net/minecraft/world/entity/animal/EntityTurtle.patch b/patch-remap/og/net/minecraft/world/entity/animal/EntityTurtle.patch new file mode 100644 index 0000000000..9125bf6969 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/EntityTurtle.patch @@ -0,0 +1,37 @@ +--- a/net/minecraft/world/entity/animal/EntityTurtle.java ++++ b/net/minecraft/world/entity/animal/EntityTurtle.java +@@ -307,7 +307,9 @@ + protected void ageBoundaryReached() { + super.ageBoundaryReached(); + if (!this.isBaby() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation(Items.SCUTE, 1); ++ this.forceDrops = false; // CraftBukkit + } + + } +@@ -334,7 +336,9 @@ + + @Override + public void thunderHit(WorldServer worldserver, EntityLightning entitylightning) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = entitylightning; // CraftBukkit + this.hurt(this.damageSources().lightningBolt(), Float.MAX_VALUE); ++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = null; // CraftBukkit + } + + @Override +@@ -491,12 +495,14 @@ + } else if (this.turtle.layEggCounter > this.adjustedTickDelay(200)) { + World world = this.turtle.level(); + ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.turtle, this.blockPos.above(), (IBlockData) Blocks.TURTLE_EGG.defaultBlockState().setValue(BlockTurtleEgg.EGGS, this.turtle.random.nextInt(4) + 1))) { // CraftBukkit + world.playSound((EntityHuman) null, blockposition, SoundEffects.TURTLE_LAY_EGG, SoundCategory.BLOCKS, 0.3F, 0.9F + world.random.nextFloat() * 0.2F); + BlockPosition blockposition1 = this.blockPos.above(); + IBlockData iblockdata = (IBlockData) Blocks.TURTLE_EGG.defaultBlockState().setValue(BlockTurtleEgg.EGGS, this.turtle.random.nextInt(4) + 1); + + world.setBlock(blockposition1, iblockdata, 3); + world.gameEvent(GameEvent.BLOCK_PLACE, blockposition1, GameEvent.a.of(this.turtle, iblockdata)); ++ } // CraftBukkit + this.turtle.setHasEgg(false); + this.turtle.setLayingEgg(false); + this.turtle.setInLoveTime(600); diff --git a/patch-remap/og/net/minecraft/world/entity/animal/EntityWolf.patch b/patch-remap/og/net/minecraft/world/entity/animal/EntityWolf.patch new file mode 100644 index 0000000000..8114754db0 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/EntityWolf.patch @@ -0,0 +1,76 @@ +--- a/net/minecraft/world/entity/animal/EntityWolf.java ++++ b/net/minecraft/world/entity/animal/EntityWolf.java +@@ -70,6 +70,12 @@ + import net.minecraft.world.phys.Vec3D; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class EntityWolf extends EntityTameableAnimal implements IEntityAngerable { + + private static final DataWatcherObject DATA_INTERESTED_ID = DataWatcher.defineId(EntityWolf.class, DataWatcherRegistry.BOOLEAN); +@@ -298,15 +304,19 @@ + } else { + Entity entity = damagesource.getEntity(); + +- if (!this.level().isClientSide) { +- this.setOrderedToSit(false); +- } ++ // CraftBukkit - move diff down + + if (entity != null && !(entity instanceof EntityHuman) && !(entity instanceof EntityArrow)) { + f = (f + 1.0F) / 2.0F; + } + +- return super.hurt(damagesource, f); ++ // CraftBukkit start ++ boolean result = super.hurt(damagesource, f); ++ if (!this.level().isClientSide && result) { ++ this.setOrderedToSit(false); ++ } ++ return result; ++ // CraftBukkit end + } + } + +@@ -326,7 +336,7 @@ + super.setTame(flag); + if (flag) { + this.getAttribute(GenericAttributes.MAX_HEALTH).setBaseValue(20.0D); +- this.setHealth(20.0F); ++ this.setHealth(this.getMaxHealth()); // CraftBukkit - 20.0 -> getMaxHealth() + } else { + this.getAttribute(GenericAttributes.MAX_HEALTH).setBaseValue(8.0D); + } +@@ -349,7 +359,7 @@ + itemstack.shrink(1); + } + +- this.heal((float) item.getFoodProperties().getNutrition()); ++ this.heal((float) item.getFoodProperties().getNutrition(), EntityRegainHealthEvent.RegainReason.EATING); // CraftBukkit + return EnumInteractionResult.SUCCESS; + } else { + if (item instanceof ItemDye) { +@@ -377,7 +387,7 @@ + this.setOrderedToSit(!this.isOrderedToSit()); + this.jumping = false; + this.navigation.stop(); +- this.setTarget((EntityLiving) null); ++ this.setTarget((EntityLiving) null, EntityTargetEvent.TargetReason.FORGOT_TARGET, true); // CraftBukkit - reason + return EnumInteractionResult.SUCCESS; + } else { + return enuminteractionresult; +@@ -388,7 +398,8 @@ + itemstack.shrink(1); + } + +- if (this.random.nextInt(3) == 0) { ++ // CraftBukkit - added event call and isCancelled check. ++ if (this.random.nextInt(3) == 0 && !CraftEventFactory.callEntityTameEvent(this, entityhuman).isCancelled()) { + this.tame(entityhuman); + this.navigation.stop(); + this.setTarget((EntityLiving) null); diff --git a/patch-remap/og/net/minecraft/world/entity/animal/allay/Allay.patch b/patch-remap/og/net/minecraft/world/entity/animal/allay/Allay.patch new file mode 100644 index 0000000000..40b4cd0b15 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/allay/Allay.patch @@ -0,0 +1,111 @@ +--- a/net/minecraft/world/entity/animal/allay/Allay.java ++++ b/net/minecraft/world/entity/animal/allay/Allay.java +@@ -99,6 +99,7 @@ + private float dancingAnimationTicks; + private float spinningAnimationTicks; + private float spinningAnimationTicks0; ++ public boolean forceDancing = false; // CraftBukkit + + public Allay(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -110,6 +111,12 @@ + this.dynamicJukeboxListener = new DynamicGameEventListener<>(new Allay.a(this.vibrationUser.getPositionSource(), GameEvent.JUKEBOX_PLAY.getNotificationRadius())); + } + ++ // CraftBukkit start ++ public void setCanDuplicate(boolean canDuplicate) { ++ this.entityData.set(Allay.DATA_CAN_DUPLICATE, canDuplicate); ++ } ++ // CraftBukkit end ++ + @Override + protected BehaviorController.b brainProvider() { + return BehaviorController.provider(Allay.MEMORY_TYPES, Allay.SENSOR_TYPES); +@@ -122,7 +129,7 @@ + + @Override + public BehaviorController getBrain() { +- return super.getBrain(); ++ return (BehaviorController) super.getBrain(); // CraftBukkit - decompile error + } + + public static AttributeProvider.Builder createAttributes() { +@@ -229,7 +236,7 @@ + public void aiStep() { + super.aiStep(); + if (!this.level().isClientSide && this.isAlive() && this.tickCount % 10 == 0) { +- this.heal(1.0F); ++ this.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit + } + + if (this.isDancing() && this.shouldStopDancing() && this.tickCount % 20 == 0) { +@@ -299,7 +306,12 @@ + ItemStack itemstack1 = this.getItemInHand(EnumHand.MAIN_HAND); + + if (this.isDancing() && this.isDuplicationItem(itemstack) && this.canDuplicate()) { +- this.duplicateAllay(); ++ // CraftBukkit start - handle cancel duplication ++ Allay allay = this.duplicateAllay(); ++ if (allay == null) { ++ return EnumInteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + this.level().broadcastEntityEvent(this, (byte) 18); + this.level().playSound(entityhuman, (Entity) this, SoundEffects.AMETHYST_BLOCK_CHIME, SoundCategory.NEUTRAL, 2.0F, 1.0F); + this.removeInteractionItem(entityhuman, itemstack); +@@ -310,7 +322,7 @@ + this.setItemInHand(EnumHand.MAIN_HAND, itemstack2); + this.removeInteractionItem(entityhuman, itemstack); + this.level().playSound(entityhuman, (Entity) this, SoundEffects.ALLAY_ITEM_GIVEN, SoundCategory.NEUTRAL, 2.0F, 1.0F); +- this.getBrain().setMemory(MemoryModuleType.LIKED_PLAYER, (Object) entityhuman.getUUID()); ++ this.getBrain().setMemory(MemoryModuleType.LIKED_PLAYER, entityhuman.getUUID()); // CraftBukkit - decompile error + return EnumInteractionResult.SUCCESS; + } else if (!itemstack1.isEmpty() && enumhand == EnumHand.MAIN_HAND && itemstack.isEmpty()) { + this.setItemSlot(EnumItemSlot.MAINHAND, ItemStack.EMPTY); +@@ -427,6 +439,7 @@ + } + + private boolean shouldStopDancing() { ++ if (this.forceDancing) {return false;} // CraftBukkit + return this.jukeboxPos == null || !this.jukeboxPos.closerToCenterThan(this.position(), (double) GameEvent.JUKEBOX_PLAY.getNotificationRadius()) || !this.level().getBlockState(this.jukeboxPos).is(Blocks.JUKEBOX); + } + +@@ -471,7 +484,7 @@ + public void addAdditionalSaveData(NBTTagCompound nbttagcompound) { + super.addAdditionalSaveData(nbttagcompound); + this.writeInventoryToTag(nbttagcompound); +- DataResult dataresult = VibrationSystem.a.CODEC.encodeStart(DynamicOpsNBT.INSTANCE, this.vibrationData); ++ DataResult dataresult = VibrationSystem.a.CODEC.encodeStart(DynamicOpsNBT.INSTANCE, this.vibrationData); // CraftBukkit - decompile error + Logger logger = Allay.LOGGER; + + Objects.requireNonNull(logger); +@@ -487,7 +500,7 @@ + super.readAdditionalSaveData(nbttagcompound); + this.readInventoryFromTag(nbttagcompound); + if (nbttagcompound.contains("listener", 10)) { +- DataResult dataresult = VibrationSystem.a.CODEC.parse(new Dynamic(DynamicOpsNBT.INSTANCE, nbttagcompound.getCompound("listener"))); ++ DataResult dataresult = VibrationSystem.a.CODEC.parse(new Dynamic(DynamicOpsNBT.INSTANCE, nbttagcompound.getCompound("listener"))); // CraftBukkit - decompile error + Logger logger = Allay.LOGGER; + + Objects.requireNonNull(logger); +@@ -520,7 +533,7 @@ + return Allay.DUPLICATION_ITEM.test(itemstack); + } + +- public void duplicateAllay() { ++ public Allay duplicateAllay() { // CraftBukkit - return allay + Allay allay = (Allay) EntityTypes.ALLAY.create(this.level()); + + if (allay != null) { +@@ -528,9 +541,9 @@ + allay.setPersistenceRequired(); + allay.resetDuplicationCooldown(); + this.resetDuplicationCooldown(); +- this.level().addFreshEntity(allay); ++ this.level().addFreshEntity(allay, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DUPLICATION); // CraftBukkit - reason for duplicated allay + } +- ++ return allay; // CraftBukkit + } + + public void resetDuplicationCooldown() { diff --git a/patch-remap/og/net/minecraft/world/entity/animal/axolotl/Axolotl.patch b/patch-remap/og/net/minecraft/world/entity/animal/axolotl/Axolotl.patch new file mode 100644 index 0000000000..afe800ab58 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/axolotl/Axolotl.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/world/entity/animal/axolotl/Axolotl.java ++++ b/net/minecraft/world/entity/animal/axolotl/Axolotl.java +@@ -68,9 +68,16 @@ + + public class Axolotl extends EntityAnimal implements LerpingModel, VariantHolder, Bucketable { + ++ // CraftBukkit start - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() ++ @Override ++ public int getDefaultMaxAirSupply() { ++ return AXOLOTL_TOTAL_AIR_SUPPLY; ++ } ++ // CraftBukkit end + public static final int TOTAL_PLAYDEAD_TIME = 200; + protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_ADULT, SensorType.HURT_BY, SensorType.AXOLOTL_ATTACKABLES, SensorType.AXOLOTL_TEMPTATIONS); +- protected static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.BREED_TARGET, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.LOOK_TARGET, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.PATH, MemoryModuleType.ATTACK_TARGET, MemoryModuleType.ATTACK_COOLING_DOWN, MemoryModuleType.NEAREST_VISIBLE_ADULT, new MemoryModuleType[]{MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.PLAY_DEAD_TICKS, MemoryModuleType.NEAREST_ATTACKABLE, MemoryModuleType.TEMPTING_PLAYER, MemoryModuleType.TEMPTATION_COOLDOWN_TICKS, MemoryModuleType.IS_TEMPTED, MemoryModuleType.HAS_HUNTING_COOLDOWN, MemoryModuleType.IS_PANICKING}); ++ // CraftBukkit - decompile error ++ protected static final ImmutableList> MEMORY_TYPES = ImmutableList.>of(MemoryModuleType.BREED_TARGET, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.LOOK_TARGET, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.PATH, MemoryModuleType.ATTACK_TARGET, MemoryModuleType.ATTACK_COOLING_DOWN, MemoryModuleType.NEAREST_VISIBLE_ADULT, new MemoryModuleType[]{MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.PLAY_DEAD_TICKS, MemoryModuleType.NEAREST_ATTACKABLE, MemoryModuleType.TEMPTING_PLAYER, MemoryModuleType.TEMPTATION_COOLDOWN_TICKS, MemoryModuleType.IS_TEMPTED, MemoryModuleType.HAS_HUNTING_COOLDOWN, MemoryModuleType.IS_PANICKING}); + private static final DataWatcherObject DATA_VARIANT = DataWatcher.defineId(Axolotl.class, DataWatcherRegistry.INT); + private static final DataWatcherObject DATA_PLAYING_DEAD = DataWatcher.defineId(Axolotl.class, DataWatcherRegistry.BOOLEAN); + private static final DataWatcherObject FROM_BUCKET = DataWatcher.defineId(Axolotl.class, DataWatcherRegistry.BOOLEAN); +@@ -188,7 +195,7 @@ + + @Override + public int getMaxAirSupply() { +- return 6000; ++ return maxAirTicks; // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() + } + + @Override +@@ -409,7 +416,7 @@ + int i = mobeffect != null ? mobeffect.getDuration() : 0; + int j = Math.min(2400, 100 + i); + +- entityhuman.addEffect(new MobEffect(MobEffects.REGENERATION, j, 0), this); ++ entityhuman.addEffect(new MobEffect(MobEffects.REGENERATION, j, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.AXOLOTL); // CraftBukkit + } + + entityhuman.removeEffect(MobEffects.DIG_SLOWDOWN); +@@ -459,7 +466,7 @@ + + @Override + public BehaviorController getBrain() { +- return super.getBrain(); ++ return (BehaviorController) super.getBrain(); // CraftBukkit - decompile error + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/entity/animal/frog/Tadpole.patch b/patch-remap/og/net/minecraft/world/entity/animal/frog/Tadpole.patch new file mode 100644 index 0000000000..f8e7f4762b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/frog/Tadpole.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/world/entity/animal/frog/Tadpole.java ++++ b/net/minecraft/world/entity/animal/frog/Tadpole.java +@@ -68,7 +68,7 @@ + + @Override + public BehaviorController getBrain() { +- return super.getBrain(); ++ return (BehaviorController) super.getBrain(); // CraftBukkit - decompile error + } + + @Override +@@ -233,8 +233,14 @@ + } + + frog.setPersistenceRequired(); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTransformEvent(this, frog, org.bukkit.event.entity.EntityTransformEvent.TransformReason.METAMORPHOSIS).isCancelled()) { ++ this.setAge(0); // Sets the age to 0 for avoid a loop if the event is canceled ++ return; ++ } ++ // CraftBukkit end + this.playSound(SoundEffects.TADPOLE_GROW_UP, 0.15F, 1.0F); +- worldserver.addFreshEntityWithPassengers(frog); ++ worldserver.addFreshEntityWithPassengers(frog, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.METAMORPHOSIS); // CraftBukkit - add SpawnReason + this.discard(); + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/animal/goat/Goat.patch b/patch-remap/og/net/minecraft/world/entity/animal/goat/Goat.patch new file mode 100644 index 0000000000..ca94087b21 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/goat/Goat.patch @@ -0,0 +1,41 @@ +--- a/net/minecraft/world/entity/animal/goat/Goat.java ++++ b/net/minecraft/world/entity/animal/goat/Goat.java +@@ -55,6 +55,12 @@ + import net.minecraft.world.phys.Vec3D; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerBucketFillEvent; ++// CraftBukkit end ++ + public class Goat extends EntityAnimal { + + public static final EntitySize LONG_JUMPING_DIMENSIONS = EntitySize.scalable(0.9F, 1.3F).scale(0.7F); +@@ -182,7 +188,7 @@ + + @Override + public BehaviorController getBrain() { +- return super.getBrain(); ++ return (BehaviorController) super.getBrain(); // CraftBukkit - decompile error + } + + @Override +@@ -220,8 +226,15 @@ + ItemStack itemstack = entityhuman.getItemInHand(enumhand); + + if (itemstack.is(Items.BUCKET) && !this.isBaby()) { ++ // CraftBukkit start - Got milk? ++ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) entityhuman.level(), entityhuman, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, enumhand); ++ ++ if (event.isCancelled()) { ++ return EnumInteractionResult.PASS; ++ } ++ // CraftBukkit end + entityhuman.playSound(this.getMilkingSound(), 1.0F, 1.0F); +- ItemStack itemstack1 = ItemLiquidUtil.createFilledResult(itemstack, entityhuman, Items.MILK_BUCKET.getDefaultInstance()); ++ ItemStack itemstack1 = ItemLiquidUtil.createFilledResult(itemstack, entityhuman, CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit + + entityhuman.setItemInHand(enumhand, itemstack1); + return EnumInteractionResult.sidedSuccess(this.level().isClientSide); diff --git a/patch-remap/og/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.patch b/patch-remap/og/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.patch new file mode 100644 index 0000000000..5fa071ec87 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.patch @@ -0,0 +1,97 @@ +--- a/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java ++++ b/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java +@@ -79,6 +79,12 @@ + import net.minecraft.world.phys.Vec3D; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.entity.AbstractHorse; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++// CraftBukkit end ++ + public abstract class EntityHorseAbstract extends EntityAnimal implements IInventoryListener, HasCustomInventoryScreen, OwnableEntity, IJumpable, ISaddleable { + + public static final int EQUIPMENT_SLOT_OFFSET = 400; +@@ -140,6 +146,7 @@ + protected int gallopSoundCounter; + @Nullable + private UUID owner; ++ public int maxDomestication = 100; // CraftBukkit - store max domestication value + + protected EntityHorseAbstract(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -335,7 +342,7 @@ + public void createInventory() { + InventorySubcontainer inventorysubcontainer = this.inventory; + +- this.inventory = new InventorySubcontainer(this.getInventorySize()); ++ this.inventory = new InventorySubcontainer(this.getInventorySize(), (AbstractHorse) this.getBukkitEntity()); // CraftBukkit + if (inventorysubcontainer != null) { + inventorysubcontainer.removeListener(this); + int i = Math.min(inventorysubcontainer.getContainerSize(), this.inventory.getContainerSize()); +@@ -443,7 +450,7 @@ + } + + public int getMaxTemper() { +- return 100; ++ return this.maxDomestication; // CraftBukkit - return stored max domestication instead of 100 + } + + @Override +@@ -514,7 +521,7 @@ + } + + if (this.getHealth() < this.getMaxHealth() && f > 0.0F) { +- this.heal(f); ++ this.heal(f, EntityRegainHealthEvent.RegainReason.EATING); // CraftBukkit + flag = true; + } + +@@ -588,7 +595,7 @@ + super.aiStep(); + if (!this.level().isClientSide && this.isAlive()) { + if (this.random.nextInt(900) == 0 && this.deathTime == 0) { +- this.heal(1.0F); ++ this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit + } + + if (this.canEatGrass()) { +@@ -855,6 +862,7 @@ + if (this.getOwnerUUID() != null) { + nbttagcompound.putUUID("Owner", this.getOwnerUUID()); + } ++ nbttagcompound.putInt("Bukkit.MaxDomestication", this.maxDomestication); // CraftBukkit + + if (!this.inventory.getItem(0).isEmpty()) { + nbttagcompound.put("SaddleItem", this.inventory.getItem(0).save(new NBTTagCompound())); +@@ -882,6 +890,11 @@ + if (uuid != null) { + this.setOwnerUUID(uuid); + } ++ // CraftBukkit start ++ if (nbttagcompound.contains("Bukkit.MaxDomestication")) { ++ this.maxDomestication = nbttagcompound.getInt("Bukkit.MaxDomestication"); ++ } ++ // CraftBukkit end + + if (nbttagcompound.contains("SaddleItem", 10)) { + ItemStack itemstack = ItemStack.of(nbttagcompound.getCompound("SaddleItem")); +@@ -984,6 +997,17 @@ + + @Override + public void handleStartJump(int i) { ++ // CraftBukkit start ++ float power; ++ if (i >= 90) { ++ power = 1.0F; ++ } else { ++ power = 0.4F + 0.4F * (float) i / 90.0F; ++ } ++ if (!CraftEventFactory.callHorseJumpEvent(this, power)) { ++ return; ++ } ++ // CraftBukkit end + this.allowStandSliding = true; + this.standIfPossible(); + this.playJumpSound(); diff --git a/patch-remap/og/net/minecraft/world/entity/animal/horse/EntityLlama.patch b/patch-remap/og/net/minecraft/world/entity/animal/horse/EntityLlama.patch new file mode 100644 index 0000000000..865898eebf --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/horse/EntityLlama.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/entity/animal/horse/EntityLlama.java ++++ b/net/minecraft/world/entity/animal/horse/EntityLlama.java +@@ -84,6 +84,11 @@ + return false; + } + ++ // CraftBukkit start ++ public void setStrengthPublic(int i) { ++ this.setStrength(i); ++ } ++ // CraftBukkit end + private void setStrength(int i) { + this.entityData.set(EntityLlama.DATA_STRENGTH_ID, Math.max(1, Math.min(5, i))); + } diff --git a/patch-remap/og/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.patch b/patch-remap/og/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.patch new file mode 100644 index 0000000000..25306fc4b9 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java ++++ b/net/minecraft/world/entity/animal/horse/EntityLlamaTrader.java +@@ -153,7 +153,7 @@ + + @Override + public void start() { +- this.mob.setTarget(this.ownerLastHurtBy); ++ this.mob.setTarget(this.ownerLastHurtBy, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_OWNER, true); // CraftBukkit + Entity entity = this.llama.getLeashHolder(); + + if (entity instanceof EntityVillagerTrader) { diff --git a/patch-remap/og/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.patch b/patch-remap/og/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.patch new file mode 100644 index 0000000000..6e536d03d6 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.patch @@ -0,0 +1,26 @@ +--- a/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.java ++++ b/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.java +@@ -41,12 +41,12 @@ + if (entitylightning != null) { + entitylightning.moveTo(this.horse.getX(), this.horse.getY(), this.horse.getZ()); + entitylightning.setVisualOnly(true); +- worldserver.addFreshEntity(entitylightning); ++ worldserver.strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.TRAP); // CraftBukkit + EntitySkeleton entityskeleton = this.createSkeleton(difficultydamagescaler, this.horse); + + if (entityskeleton != null) { + entityskeleton.startRiding(this.horse); +- worldserver.addFreshEntityWithPassengers(entityskeleton); ++ worldserver.addFreshEntityWithPassengers(entityskeleton, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.TRAP); // CraftBukkit + + for (int i = 0; i < 3; ++i) { + EntityHorseAbstract entityhorseabstract = this.createHorse(difficultydamagescaler); +@@ -57,7 +57,7 @@ + if (entityskeleton1 != null) { + entityskeleton1.startRiding(entityhorseabstract); + entityhorseabstract.push(this.horse.getRandom().triangle(0.0D, 1.1485D), 0.0D, this.horse.getRandom().triangle(0.0D, 1.1485D)); +- worldserver.addFreshEntityWithPassengers(entityhorseabstract); ++ worldserver.addFreshEntityWithPassengers(entityhorseabstract, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.JOCKEY); // CraftBukkit + } + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/animal/sniffer/Sniffer.patch b/patch-remap/og/net/minecraft/world/entity/animal/sniffer/Sniffer.patch new file mode 100644 index 0000000000..94108b6b12 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/animal/sniffer/Sniffer.patch @@ -0,0 +1,60 @@ +--- a/net/minecraft/world/entity/animal/sniffer/Sniffer.java ++++ b/net/minecraft/world/entity/animal/sniffer/Sniffer.java +@@ -83,14 +83,23 @@ + + public Sniffer(EntityTypes entitytypes, World world) { + super(entitytypes, world); +- this.entityData.define(Sniffer.DATA_STATE, Sniffer.State.IDLING); +- this.entityData.define(Sniffer.DATA_DROP_SEED_AT_TICK, 0); ++ // this.entityData.define(Sniffer.DATA_STATE, Sniffer.State.IDLING); // CraftBukkit - moved down to appropriate location ++ // this.entityData.define(Sniffer.DATA_DROP_SEED_AT_TICK, 0); // CraftBukkit - moved down to appropriate location + this.getNavigation().setCanFloat(true); + this.setPathfindingMalus(PathType.WATER, -1.0F); + this.setPathfindingMalus(PathType.DANGER_POWDER_SNOW, -1.0F); + this.setPathfindingMalus(PathType.DAMAGE_CAUTIOUS, -1.0F); + } + ++ // CraftBukkit start - SPIGOT-7295: moved from constructor to appropriate location ++ @Override ++ protected void defineSynchedData() { ++ super.defineSynchedData(); ++ this.entityData.define(Sniffer.DATA_STATE, Sniffer.State.IDLING); ++ this.entityData.define(Sniffer.DATA_DROP_SEED_AT_TICK, 0); ++ } ++ // CraftBukkit end ++ + @Override + protected float getStandingEyeHeight(EntityPose entitypose, EntitySize entitysize) { + return this.getDimensions(entitypose).height * 0.6F; +@@ -267,6 +276,13 @@ + ItemStack itemstack = (ItemStack) iterator.next(); + EntityItem entityitem = new EntityItem(worldserver, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), itemstack); + ++ // CraftBukkit start - handle EntityDropItemEvent ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end + entityitem.setDefaultPickUpDelay(); + worldserver.addFreshEntity(entityitem); + } +@@ -306,7 +322,7 @@ + List list = (List) this.getExploredPositions().limit(20L).collect(Collectors.toList()); + + list.add(0, GlobalPos.of(this.level().dimension(), blockposition)); +- this.getBrain().setMemory(MemoryModuleType.SNIFFER_EXPLORED_POSITIONS, (Object) list); ++ this.getBrain().setMemory(MemoryModuleType.SNIFFER_EXPLORED_POSITIONS, list); // CraftBukkit - decompile error + return this; + } + +@@ -458,7 +474,7 @@ + + @Override + public BehaviorController getBrain() { +- return super.getBrain(); ++ return (BehaviorController) super.getBrain(); // CraftBukkit - decompile error + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.patch b/patch-remap/og/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.patch new file mode 100644 index 0000000000..cf987efb76 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.patch @@ -0,0 +1,52 @@ +--- a/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java ++++ b/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java +@@ -20,6 +20,11 @@ + import net.minecraft.world.level.block.BlockFireAbstract; + import net.minecraft.world.level.dimension.end.EnderDragonBattle; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end ++ + public class EntityEnderCrystal extends Entity { + + private static final DataWatcherObject> DATA_BEAM_TARGET = DataWatcher.defineId(EntityEnderCrystal.class, DataWatcherRegistry.OPTIONAL_BLOCK_POS); +@@ -55,7 +60,11 @@ + BlockPosition blockposition = this.blockPosition(); + + if (((WorldServer) this.level()).getDragonFight() != null && this.level().getBlockState(blockposition).isAir()) { +- this.level().setBlockAndUpdate(blockposition, BlockFireAbstract.getState(this.level(), blockposition)); ++ // CraftBukkit start ++ if (!CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition, this).isCancelled()) { ++ this.level().setBlockAndUpdate(blockposition, BlockFireAbstract.getState(this.level(), blockposition)); ++ } ++ // CraftBukkit end + } + } + +@@ -95,11 +104,23 @@ + return false; + } else { + if (!this.isRemoved() && !this.level().isClientSide) { ++ // CraftBukkit start - All non-living entities need this ++ if (CraftEventFactory.handleNonLivingEntityDamageEvent(this, damagesource, f, false)) { ++ return false; ++ } ++ // CraftBukkit end + this.remove(Entity.RemovalReason.KILLED); + if (!damagesource.is(DamageTypeTags.IS_EXPLOSION)) { + DamageSource damagesource1 = damagesource.getEntity() != null ? this.damageSources().explosion(this, damagesource.getEntity()) : null; + +- this.level().explode(this, damagesource1, (ExplosionDamageCalculator) null, this.getX(), this.getY(), this.getZ(), 6.0F, false, World.a.BLOCK); ++ // CraftBukkit start ++ ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent(this, 6.0F, false); ++ if (event.isCancelled()) { ++ this.unsetRemoved(); ++ return false; ++ } ++ this.level().explode(this, damagesource1, (ExplosionDamageCalculator) null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), World.a.BLOCK); ++ // CraftBukkit end + } + + this.onDestroyedBy(damagesource); diff --git a/patch-remap/og/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.patch b/patch-remap/og/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.patch new file mode 100644 index 0000000000..745512736f --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.patch @@ -0,0 +1,211 @@ +--- a/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java ++++ b/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java +@@ -53,6 +53,19 @@ + import org.joml.Vector3f; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.world.item.ItemStack; ++import net.minecraft.world.level.Explosion; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.entity.TileEntity; ++import net.minecraft.world.level.storage.loot.LootParams; ++import net.minecraft.world.level.storage.loot.LootTableInfo; ++import net.minecraft.world.level.storage.loot.parameters.LootContextParameters; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.entity.EntityExplodeEvent; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++// CraftBukkit end ++ + public class EntityEnderDragon extends EntityInsentient implements IMonster { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -90,6 +103,7 @@ + private final PathPoint[] nodes; + private final int[] nodeAdjacency; + private final Path openSet; ++ private final Explosion explosionSource; // CraftBukkit - reusable source for CraftTNTPrimed.getSource() + + public EntityEnderDragon(EntityTypes entitytypes, World world) { + super(EntityTypes.ENDER_DRAGON, world); +@@ -111,6 +125,7 @@ + this.noPhysics = true; + this.noCulling = true; + this.phaseManager = new DragonControllerManager(this); ++ this.explosionSource = new Explosion(world, this, null, null, Double.NaN, Double.NaN, Double.NaN, Float.NaN, true, Explosion.Effect.DESTROY, Particles.EXPLOSION, Particles.EXPLOSION_EMITTER, SoundEffects.GENERIC_EXPLODE); // CraftBukkit + } + + public void setDragonFight(EnderDragonBattle enderdragonbattle) { +@@ -258,7 +273,7 @@ + + Vec3D vec3d1 = idragoncontroller.getFlyTargetLocation(); + +- if (vec3d1 != null) { ++ if (vec3d1 != null && idragoncontroller.getPhase() != DragonControllerPhase.HOVERING) { // CraftBukkit - Don't move when hovering + double d0 = vec3d1.x - this.getX(); + double d1 = vec3d1.y - this.getY(); + double d2 = vec3d1.z - this.getZ(); +@@ -399,7 +414,14 @@ + if (this.nearestCrystal.isRemoved()) { + this.nearestCrystal = null; + } else if (this.tickCount % 10 == 0 && this.getHealth() < this.getMaxHealth()) { +- this.setHealth(this.getHealth() + 1.0F); ++ // CraftBukkit start ++ EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), 1.0F, EntityRegainHealthEvent.RegainReason.ENDER_CRYSTAL); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ this.setHealth((float) (this.getHealth() + event.getAmount())); ++ } ++ // CraftBukkit end + } + } + +@@ -474,6 +496,9 @@ + int j1 = MathHelper.floor(axisalignedbb.maxZ); + boolean flag = false; + boolean flag1 = false; ++ // CraftBukkit start - Create a list to hold all the destroyed blocks ++ List destroyedBlocks = new java.util.ArrayList(); ++ // CraftBukkit end + + for (int k1 = i; k1 <= l; ++k1) { + for (int l1 = j; l1 <= i1; ++l1) { +@@ -483,7 +508,11 @@ + + if (!iblockdata.isAir() && !iblockdata.is(TagsBlock.DRAGON_TRANSPARENT)) { + if (this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && !iblockdata.is(TagsBlock.DRAGON_IMMUNE)) { +- flag1 = this.level().removeBlock(blockposition, false) || flag1; ++ // CraftBukkit start - Add blocks to list rather than destroying them ++ // flag1 = this.level().removeBlock(blockposition, false) || flag1; ++ flag1 = true; ++ destroyedBlocks.add(CraftBlock.at(this.level(), blockposition)); ++ // CraftBukkit end + } else { + flag = true; + } +@@ -492,6 +521,51 @@ + } + } + ++ // CraftBukkit start - Set off an EntityExplodeEvent for the dragon exploding all these blocks ++ // SPIGOT-4882: don't fire event if nothing hit ++ if (!flag1) { ++ return flag; ++ } ++ ++ org.bukkit.entity.Entity bukkitEntity = this.getBukkitEntity(); ++ EntityExplodeEvent event = new EntityExplodeEvent(bukkitEntity, bukkitEntity.getLocation(), destroyedBlocks, 0F); ++ bukkitEntity.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ // This flag literally means 'Dragon hit something hard' (Obsidian, White Stone or Bedrock) and will cause the dragon to slow down. ++ // We should consider adding an event extension for it, or perhaps returning true if the event is cancelled. ++ return flag; ++ } else if (event.getYield() == 0F) { ++ // Yield zero ==> no drops ++ for (org.bukkit.block.Block block : event.blockList()) { ++ this.level().removeBlock(new BlockPosition(block.getX(), block.getY(), block.getZ()), false); ++ } ++ } else { ++ for (org.bukkit.block.Block block : event.blockList()) { ++ org.bukkit.Material blockId = block.getType(); ++ if (blockId.isAir()) { ++ continue; ++ } ++ ++ CraftBlock craftBlock = ((CraftBlock) block); ++ BlockPosition blockposition = craftBlock.getPosition(); ++ ++ Block nmsBlock = craftBlock.getNMS().getBlock(); ++ if (nmsBlock.dropFromExplosion(explosionSource)) { ++ TileEntity tileentity = craftBlock.getNMS().hasBlockEntity() ? this.level().getBlockEntity(blockposition) : null; ++ LootParams.a loottableinfo_builder = (new LootParams.a((WorldServer) this.level())).withParameter(LootContextParameters.ORIGIN, Vec3D.atCenterOf(blockposition)).withParameter(LootContextParameters.TOOL, ItemStack.EMPTY).withParameter(LootContextParameters.EXPLOSION_RADIUS, 1.0F / event.getYield()).withOptionalParameter(LootContextParameters.BLOCK_ENTITY, tileentity); ++ ++ craftBlock.getNMS().getDrops(loottableinfo_builder).forEach((itemstack) -> { ++ Block.popResource(this.level(), blockposition, itemstack); ++ }); ++ craftBlock.getNMS().spawnAfterBreak((WorldServer) this.level(), blockposition, ItemStack.EMPTY, false); ++ } ++ nmsBlock.wasExploded(this.level(), blockposition, explosionSource); ++ ++ this.level().removeBlock(blockposition, false); ++ } ++ } ++ // CraftBukkit end ++ + if (flag1) { + BlockPosition blockposition1 = new BlockPosition(i + this.random.nextInt(l - i + 1), j + this.random.nextInt(i1 - j + 1), k + this.random.nextInt(j1 - k + 1)); + +@@ -556,6 +630,21 @@ + + } + ++ // CraftBukkit start - SPIGOT-2420: Special case, the ender dragon drops 12000 xp for the first kill and 500 xp for every other kill and this over time. ++ @Override ++ public int getExpReward() { ++ // CraftBukkit - Moved from #tickDeath method ++ boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT); ++ short short0 = 500; ++ ++ if (this.dragonFight != null && !this.dragonFight.hasPreviouslyKilledDragon()) { ++ short0 = 12000; ++ } ++ ++ return flag ? short0 : 0; ++ } ++ // CraftBukkit end ++ + @Override + protected void tickDeath() { + if (this.dragonFight != null) { +@@ -571,15 +660,20 @@ + this.level().addParticle(Particles.EXPLOSION_EMITTER, this.getX() + (double) f, this.getY() + 2.0D + (double) f1, this.getZ() + (double) f2, 0.0D, 0.0D, 0.0D); + } + ++ // CraftBukkit start - SPIGOT-2420: Moved up to #getExpReward method ++ /* + boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT); + short short0 = 500; + + if (this.dragonFight != null && !this.dragonFight.hasPreviouslyKilledDragon()) { + short0 = 12000; + } ++ */ ++ int short0 = expToDrop; ++ // CraftBukkit end + + if (this.level() instanceof WorldServer) { +- if (this.dragonDeathTime > 150 && this.dragonDeathTime % 5 == 0 && flag) { ++ if (this.dragonDeathTime > 150 && this.dragonDeathTime % 5 == 0 && true) { // CraftBukkit - SPIGOT-2420: Already checked for the game rule when calculating the xp + EntityExperienceOrb.award((WorldServer) this.level(), this.position(), MathHelper.floor((float) short0 * 0.08F)); + } + +@@ -590,7 +684,7 @@ + + this.move(EnumMoveType.SELF, new Vec3D(0.0D, 0.10000000149011612D, 0.0D)); + if (this.dragonDeathTime == 200 && this.level() instanceof WorldServer) { +- if (flag) { ++ if (true) { // CraftBukkit - SPIGOT-2420: Already checked for the game rule when calculating the xp + EntityExperienceOrb.award((WorldServer) this.level(), this.position(), MathHelper.floor((float) short0 * 0.2F)); + } + +@@ -811,6 +905,7 @@ + super.addAdditionalSaveData(nbttagcompound); + nbttagcompound.putInt("DragonPhase", this.phaseManager.getCurrentPhase().getPhase().getId()); + nbttagcompound.putInt("DragonDeathTime", this.dragonDeathTime); ++ nbttagcompound.putInt("Bukkit.expToDrop", expToDrop); // CraftBukkit - SPIGOT-2420: The ender dragon drops xp over time which can also happen between server starts + } + + @Override +@@ -824,6 +919,11 @@ + this.dragonDeathTime = nbttagcompound.getInt("DragonDeathTime"); + } + ++ // CraftBukkit start - SPIGOT-2420: The ender dragon drops xp over time which can also happen between server starts ++ if (nbttagcompound.contains("Bukkit.expToDrop")) { ++ this.expToDrop = nbttagcompound.getInt("Bukkit.expToDrop"); ++ } ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerManager.patch b/patch-remap/og/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerManager.patch new file mode 100644 index 0000000000..21603a23d6 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerManager.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerManager.java ++++ b/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerManager.java +@@ -5,6 +5,11 @@ + import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftEnderDragon; ++import org.bukkit.event.entity.EnderDragonChangePhaseEvent; ++// CraftBukkit end ++ + public class DragonControllerManager { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -24,6 +29,19 @@ + this.currentPhase.end(); + } + ++ // CraftBukkit start - Call EnderDragonChangePhaseEvent ++ EnderDragonChangePhaseEvent event = new EnderDragonChangePhaseEvent( ++ (CraftEnderDragon) this.dragon.getBukkitEntity(), ++ (this.currentPhase == null) ? null : CraftEnderDragon.getBukkitPhase(this.currentPhase.getPhase()), ++ CraftEnderDragon.getBukkitPhase(dragoncontrollerphase) ++ ); ++ this.dragon.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ dragoncontrollerphase = CraftEnderDragon.getMinecraftPhase(event.getNewPhase()); ++ // CraftBukkit end ++ + this.currentPhase = this.getPhase(dragoncontrollerphase); + if (!this.dragon.level().isClientSide) { + this.dragon.getEntityData().set(EntityEnderDragon.DATA_PHASE, dragoncontrollerphase.getId()); +@@ -45,6 +63,6 @@ + this.phases[i] = dragoncontrollerphase.createInstance(this.dragon); + } + +- return this.phases[i]; ++ return (T) this.phases[i]; // CraftBukkit - decompile error + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/boss/wither/EntityWither.patch b/patch-remap/og/net/minecraft/world/entity/boss/wither/EntityWither.patch new file mode 100644 index 0000000000..8c4356d20e --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/boss/wither/EntityWither.patch @@ -0,0 +1,93 @@ +--- a/net/minecraft/world/entity/boss/wither/EntityWither.java ++++ b/net/minecraft/world/entity/boss/wither/EntityWither.java +@@ -55,6 +55,17 @@ + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.WorldServer; ++import net.minecraft.world.level.block.Blocks; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end ++ + public class EntityWither extends EntityMonster implements PowerableMob, IRangedEntity { + + private static final DataWatcherObject DATA_TARGET_A = DataWatcher.defineId(EntityWither.class, DataWatcherRegistry.INT); +@@ -248,15 +259,40 @@ + i = this.getInvulnerableTicks() - 1; + this.bossEvent.setProgress(1.0F - (float) i / 220.0F); + if (i <= 0) { +- this.level().explode(this, this.getX(), this.getEyeY(), this.getZ(), 7.0F, false, World.a.MOB); ++ // CraftBukkit start ++ // this.level().explode(this, this.getX(), this.getEyeY(), this.getZ(), 7.0F, false, World.a.MOB); ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), 7.0F, false); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ this.level().explode(this, this.getX(), this.getEyeY(), this.getZ(), event.getRadius(), event.getFire(), World.a.MOB); ++ } ++ // CraftBukkit end ++ + if (!this.isSilent()) { +- this.level().globalLevelEvent(1023, this.blockPosition(), 0); ++ // CraftBukkit start - Use relative location for far away sounds ++ // this.level().globalLevelEvent(1023, new BlockPosition(this), 0); ++ int viewDistance = ((WorldServer) this.level()).getCraftServer().getViewDistance() * 16; ++ for (EntityPlayer player : (List) MinecraftServer.getServer().getPlayerList().players) { ++ double deltaX = this.getX() - player.getX(); ++ double deltaZ = this.getZ() - player.getZ(); ++ double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; ++ if (distanceSquared > viewDistance * viewDistance) { ++ double deltaLength = Math.sqrt(distanceSquared); ++ double relativeX = player.getX() + (deltaX / deltaLength) * viewDistance; ++ double relativeZ = player.getZ() + (deltaZ / deltaLength) * viewDistance; ++ player.connection.send(new PacketPlayOutWorldEvent(1023, new BlockPosition((int) relativeX, (int) this.getY(), (int) relativeZ), 0, true)); ++ } else { ++ player.connection.send(new PacketPlayOutWorldEvent(1023, this.blockPosition(), 0, true)); ++ } ++ } ++ // CraftBukkit end + } + } + + this.setInvulnerableTicks(i); + if (this.tickCount % 10 == 0) { +- this.heal(10.0F); ++ this.heal(10.0F, EntityRegainHealthEvent.RegainReason.WITHER_SPAWN); // CraftBukkit + } + + } else { +@@ -301,6 +337,7 @@ + if (!list.isEmpty()) { + EntityLiving entityliving1 = (EntityLiving) list.get(this.random.nextInt(list.size())); + ++ if (CraftEventFactory.callEntityTargetLivingEvent(this, entityliving1, EntityTargetEvent.TargetReason.CLOSEST_ENTITY).isCancelled()) continue; // CraftBukkit + this.setAlternativeTarget(i, entityliving1.getId()); + } + } +@@ -331,6 +368,11 @@ + IBlockData iblockdata = this.level().getBlockState(blockposition); + + if (canDestroy(iblockdata)) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState())) { ++ continue; ++ } ++ // CraftBukkit end + flag = this.level().destroyBlock(blockposition, true, this) || flag; + } + } +@@ -344,7 +386,7 @@ + } + + if (this.tickCount % 20 == 0) { +- this.heal(1.0F); ++ this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit + } + + this.bossEvent.setProgress(this.getHealth() / this.getMaxHealth()); diff --git a/patch-remap/og/net/minecraft/world/entity/decoration/EntityArmorStand.patch b/patch-remap/og/net/minecraft/world/entity/decoration/EntityArmorStand.patch new file mode 100644 index 0000000000..a379f5ffa3 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/decoration/EntityArmorStand.patch @@ -0,0 +1,174 @@ +--- a/net/minecraft/world/entity/decoration/EntityArmorStand.java ++++ b/net/minecraft/world/entity/decoration/EntityArmorStand.java +@@ -44,6 +44,15 @@ + import net.minecraft.world.phys.AxisAlignedBB; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.inventory.EquipmentSlot; ++import org.bukkit.craftbukkit.CraftEquipmentSlot; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.ArmorStand; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerArmorStandManipulateEvent; ++// CraftBukkit end ++ + public class EntityArmorStand extends EntityLiving { + + public static final int WOBBLE_TIME = 5; +@@ -106,6 +115,13 @@ + this.setPos(d0, d1, d2); + } + ++ // CraftBukkit start - SPIGOT-3607, SPIGOT-3637 ++ @Override ++ public float getBukkitYaw() { ++ return this.getYRot(); ++ } ++ // CraftBukkit end ++ + @Override + public void refreshDimensions() { + double d0 = this.getX(); +@@ -161,13 +177,20 @@ + + @Override + public void setItemSlot(EnumItemSlot enumitemslot, ItemStack itemstack) { ++ // CraftBukkit start ++ this.setItemSlot(enumitemslot, itemstack, false); ++ } ++ ++ @Override ++ public void setItemSlot(EnumItemSlot enumitemslot, ItemStack itemstack, boolean silent) { ++ // CraftBukkit end + this.verifyEquippedItem(itemstack); + switch (enumitemslot.getType()) { + case HAND: +- this.onEquipItem(enumitemslot, (ItemStack) this.handItems.set(enumitemslot.getIndex(), itemstack), itemstack); ++ this.onEquipItem(enumitemslot, (ItemStack) this.handItems.set(enumitemslot.getIndex(), itemstack), itemstack, silent); // CraftBukkit + break; + case ARMOR: +- this.onEquipItem(enumitemslot, (ItemStack) this.armorItems.set(enumitemslot.getIndex(), itemstack), itemstack); ++ this.onEquipItem(enumitemslot, (ItemStack) this.armorItems.set(enumitemslot.getIndex(), itemstack), itemstack, silent); // CraftBukkit + } + + } +@@ -402,7 +425,25 @@ + return false; + } else if (itemstack1.isEmpty() && (this.disabledSlots & 1 << enumitemslot.getFilterFlag() + 16) != 0) { + return false; +- } else if (entityhuman.getAbilities().instabuild && itemstack1.isEmpty() && !itemstack.isEmpty()) { ++ // CraftBukkit start ++ } else { ++ org.bukkit.inventory.ItemStack armorStandItem = CraftItemStack.asCraftMirror(itemstack1); ++ org.bukkit.inventory.ItemStack playerHeldItem = CraftItemStack.asCraftMirror(itemstack); ++ ++ Player player = (Player) entityhuman.getBukkitEntity(); ++ ArmorStand self = (ArmorStand) this.getBukkitEntity(); ++ ++ EquipmentSlot slot = CraftEquipmentSlot.getSlot(enumitemslot); ++ EquipmentSlot hand = CraftEquipmentSlot.getHand(enumhand); ++ PlayerArmorStandManipulateEvent armorStandManipulateEvent = new PlayerArmorStandManipulateEvent(player, self, playerHeldItem, armorStandItem, slot, hand); ++ this.level().getCraftServer().getPluginManager().callEvent(armorStandManipulateEvent); ++ ++ if (armorStandManipulateEvent.isCancelled()) { ++ return true; ++ } ++ ++ if (entityhuman.getAbilities().instabuild && itemstack1.isEmpty() && !itemstack.isEmpty()) { ++ // CraftBukkit end + this.setItemSlot(enumitemslot, itemstack.copyWithCount(1)); + return true; + } else if (!itemstack.isEmpty() && itemstack.getCount() > 1) { +@@ -417,15 +458,26 @@ + entityhuman.setItemInHand(enumhand, itemstack1); + return true; + } ++ } // CraftBukkit + } + + @Override + public boolean hurt(DamageSource damagesource, float f) { + if (!this.level().isClientSide && !this.isRemoved()) { + if (damagesource.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, damagesource, f)) { ++ return false; ++ } ++ // CraftBukkit end + this.kill(); + return false; +- } else if (!this.isInvulnerableTo(damagesource) && !this.invisible && !this.isMarker()) { ++ } else if (!this.isInvulnerableTo(damagesource) && (true || !this.invisible) && !this.isMarker()) { // CraftBukkit ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, damagesource, f, true, this.invisible)) { ++ return false; ++ } ++ // CraftBukkit end + if (damagesource.is(DamageTypeTags.IS_EXPLOSION)) { + this.brokenByAnything(damagesource); + this.kill(); +@@ -473,7 +525,7 @@ + } else { + this.brokenByPlayer(damagesource); + this.showBreakingParticles(); +- this.kill(); ++ this.discard(); // CraftBukkit - SPIGOT-4890: remain as this.discard() since above damagesource method will call death event + } + + return true; +@@ -541,13 +593,13 @@ + itemstack.setHoverName(this.getCustomName()); + } + +- Block.popResource(this.level(), this.blockPosition(), itemstack); ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops + this.brokenByAnything(damagesource); + } + + private void brokenByAnything(DamageSource damagesource) { + this.playBrokenSound(); +- this.dropAllDeathLoot(damagesource); ++ // this.dropAllDeathLoot(damagesource); // CraftBukkit - moved down + + ItemStack itemstack; + int i; +@@ -555,7 +607,7 @@ + for (i = 0; i < this.handItems.size(); ++i) { + itemstack = (ItemStack) this.handItems.get(i); + if (!itemstack.isEmpty()) { +- Block.popResource(this.level(), this.blockPosition().above(), itemstack); ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops + this.handItems.set(i, ItemStack.EMPTY); + } + } +@@ -563,10 +615,11 @@ + for (i = 0; i < this.armorItems.size(); ++i) { + itemstack = (ItemStack) this.armorItems.get(i); + if (!itemstack.isEmpty()) { +- Block.popResource(this.level(), this.blockPosition().above(), itemstack); ++ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops + this.armorItems.set(i, ItemStack.EMPTY); + } + } ++ this.dropAllDeathLoot(damagesource); // CraftBukkit - moved from above + + } + +@@ -662,8 +715,16 @@ + return this.isSmall(); + } + ++ // CraftBukkit start ++ @Override ++ public boolean shouldDropExperience() { ++ return true; // MC-157395, SPIGOT-5193 even baby (small) armor stands should drop ++ } ++ // CraftBukkit end ++ + @Override + public void kill() { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event + this.remove(Entity.RemovalReason.KILLED); + this.gameEvent(GameEvent.ENTITY_DIE); + } diff --git a/patch-remap/og/net/minecraft/world/entity/decoration/EntityHanging.patch b/patch-remap/og/net/minecraft/world/entity/decoration/EntityHanging.patch new file mode 100644 index 0000000000..82589f5909 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/decoration/EntityHanging.patch @@ -0,0 +1,173 @@ +--- a/net/minecraft/world/entity/decoration/EntityHanging.java ++++ b/net/minecraft/world/entity/decoration/EntityHanging.java +@@ -26,6 +26,13 @@ + import org.apache.commons.lang3.Validate; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.tags.DamageTypeTags; ++import org.bukkit.entity.Hanging; ++import org.bukkit.event.hanging.HangingBreakByEntityEvent; ++import org.bukkit.event.hanging.HangingBreakEvent; ++// CraftBukkit end ++ + public abstract class EntityHanging extends Entity { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -60,26 +67,37 @@ + + protected void recalculateBoundingBox() { + if (this.direction != null) { +- double d0 = (double) this.pos.getX() + 0.5D; +- double d1 = (double) this.pos.getY() + 0.5D; +- double d2 = (double) this.pos.getZ() + 0.5D; ++ // CraftBukkit start code moved in to calculateBoundingBox ++ this.setBoundingBox(calculateBoundingBox(this, this.pos, this.direction, this.getWidth(), this.getHeight())); ++ // CraftBukkit end ++ } ++ } ++ ++ // CraftBukkit start - break out BB calc into own method ++ public static AxisAlignedBB calculateBoundingBox(@Nullable Entity entity, BlockPosition blockPosition, EnumDirection direction, int width, int height) { ++ { ++ double d0 = (double) blockPosition.getX() + 0.5D; ++ double d1 = (double) blockPosition.getY() + 0.5D; ++ double d2 = (double) blockPosition.getZ() + 0.5D; + double d3 = 0.46875D; +- double d4 = this.offs(this.getWidth()); +- double d5 = this.offs(this.getHeight()); ++ double d4 = offs(width); ++ double d5 = offs(height); + +- d0 -= (double) this.direction.getStepX() * 0.46875D; +- d2 -= (double) this.direction.getStepZ() * 0.46875D; ++ d0 -= (double) direction.getStepX() * 0.46875D; ++ d2 -= (double) direction.getStepZ() * 0.46875D; + d1 += d5; +- EnumDirection enumdirection = this.direction.getCounterClockWise(); ++ EnumDirection enumdirection = direction.getCounterClockWise(); + + d0 += d4 * (double) enumdirection.getStepX(); + d2 += d4 * (double) enumdirection.getStepZ(); +- this.setPosRaw(d0, d1, d2); +- double d6 = (double) this.getWidth(); +- double d7 = (double) this.getHeight(); +- double d8 = (double) this.getWidth(); ++ if (entity != null) { ++ entity.setPosRaw(d0, d1, d2); ++ } ++ double d6 = (double) width; ++ double d7 = (double) height; ++ double d8 = (double) width; + +- if (this.direction.getAxis() == EnumDirection.EnumAxis.Z) { ++ if (direction.getAxis() == EnumDirection.EnumAxis.Z) { + d8 = 1.0D; + } else { + d6 = 1.0D; +@@ -88,11 +106,12 @@ + d6 /= 32.0D; + d7 /= 32.0D; + d8 /= 32.0D; +- this.setBoundingBox(new AxisAlignedBB(d0 - d6, d1 - d7, d2 - d8, d0 + d6, d1 + d7, d2 + d8)); ++ return new AxisAlignedBB(d0 - d6, d1 - d7, d2 - d8, d0 + d6, d1 + d7, d2 + d8); + } + } ++ // CraftBukkit end + +- private double offs(int i) { ++ private static double offs(int i) { // CraftBukkit - static + return i % 32 == 0 ? 0.5D : 0.0D; + } + +@@ -103,6 +122,24 @@ + if (this.checkInterval++ == 100) { + this.checkInterval = 0; + if (!this.isRemoved() && !this.survives()) { ++ // CraftBukkit start - fire break events ++ IBlockData material = this.level().getBlockState(this.blockPosition()); ++ HangingBreakEvent.RemoveCause cause; ++ ++ if (!material.isAir()) { ++ // TODO: This feels insufficient to catch 100% of suffocation cases ++ cause = HangingBreakEvent.RemoveCause.OBSTRUCTION; ++ } else { ++ cause = HangingBreakEvent.RemoveCause.PHYSICS; ++ } ++ ++ HangingBreakEvent event = new HangingBreakEvent((Hanging) this.getBukkitEntity(), cause); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (this.isRemoved() || event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.discard(); + this.dropItem((Entity) null); + } +@@ -166,6 +203,22 @@ + return false; + } else { + if (!this.isRemoved() && !this.level().isClientSide) { ++ // CraftBukkit start - fire break events ++ Entity damager = (damagesource.isIndirect()) ? damagesource.getEntity() : damagesource.getDirectEntity(); ++ HangingBreakEvent event; ++ if (damager != null) { ++ event = new HangingBreakByEntityEvent((Hanging) this.getBukkitEntity(), damager.getBukkitEntity(), damagesource.is(DamageTypeTags.IS_EXPLOSION) ? HangingBreakEvent.RemoveCause.EXPLOSION : HangingBreakEvent.RemoveCause.ENTITY); ++ } else { ++ event = new HangingBreakEvent((Hanging) this.getBukkitEntity(), damagesource.is(DamageTypeTags.IS_EXPLOSION) ? HangingBreakEvent.RemoveCause.EXPLOSION : HangingBreakEvent.RemoveCause.DEFAULT); ++ } ++ ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (this.isRemoved() || event.isCancelled()) { ++ return true; ++ } ++ // CraftBukkit end ++ + this.kill(); + this.markHurt(); + this.dropItem(damagesource.getEntity()); +@@ -178,6 +231,18 @@ + @Override + public void move(EnumMoveType enummovetype, Vec3D vec3d) { + if (!this.level().isClientSide && !this.isRemoved() && vec3d.lengthSqr() > 0.0D) { ++ if (this.isRemoved()) return; // CraftBukkit ++ ++ // CraftBukkit start - fire break events ++ // TODO - Does this need its own cause? Seems to only be triggered by pistons ++ HangingBreakEvent event = new HangingBreakEvent((Hanging) this.getBukkitEntity(), HangingBreakEvent.RemoveCause.PHYSICS); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (this.isRemoved() || event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ + this.kill(); + this.dropItem((Entity) null); + } +@@ -186,13 +251,22 @@ + + @Override + public void push(double d0, double d1, double d2) { +- if (!this.level().isClientSide && !this.isRemoved() && d0 * d0 + d1 * d1 + d2 * d2 > 0.0D) { ++ if (false && !this.level().isClientSide && !this.isRemoved() && d0 * d0 + d1 * d1 + d2 * d2 > 0.0D) { // CraftBukkit - not needed + this.kill(); + this.dropItem((Entity) null); + } + + } + ++ // CraftBukkit start - selectively save tile position ++ @Override ++ public void addAdditionalSaveData(NBTTagCompound nbttagcompound, boolean includeAll) { ++ if (includeAll) { ++ addAdditionalSaveData(nbttagcompound); ++ } ++ } ++ // CraftBukkit end ++ + @Override + public void addAdditionalSaveData(NBTTagCompound nbttagcompound) { + BlockPosition blockposition = this.getPos(); diff --git a/patch-remap/og/net/minecraft/world/entity/decoration/EntityItemFrame.patch b/patch-remap/og/net/minecraft/world/entity/decoration/EntityItemFrame.patch new file mode 100644 index 0000000000..68b8ccd011 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/decoration/EntityItemFrame.patch @@ -0,0 +1,83 @@ +--- a/net/minecraft/world/entity/decoration/EntityItemFrame.java ++++ b/net/minecraft/world/entity/decoration/EntityItemFrame.java +@@ -96,16 +96,27 @@ + @Override + protected void recalculateBoundingBox() { + if (this.direction != null) { ++ // CraftBukkit start code moved in to calculateBoundingBox ++ this.setBoundingBox(calculateBoundingBox(this, this.pos, this.direction, this.getWidth(), this.getHeight())); ++ // CraftBukkit end ++ } ++ } ++ ++ // CraftBukkit start - break out BB calc into own method ++ public static AxisAlignedBB calculateBoundingBox(@Nullable Entity entity, BlockPosition blockPosition, EnumDirection direction, int width, int height) { ++ { + double d0 = 0.46875D; +- double d1 = (double) this.pos.getX() + 0.5D - (double) this.direction.getStepX() * 0.46875D; +- double d2 = (double) this.pos.getY() + 0.5D - (double) this.direction.getStepY() * 0.46875D; +- double d3 = (double) this.pos.getZ() + 0.5D - (double) this.direction.getStepZ() * 0.46875D; ++ double d1 = (double) blockPosition.getX() + 0.5D - (double) direction.getStepX() * 0.46875D; ++ double d2 = (double) blockPosition.getY() + 0.5D - (double) direction.getStepY() * 0.46875D; ++ double d3 = (double) blockPosition.getZ() + 0.5D - (double) direction.getStepZ() * 0.46875D; + +- this.setPosRaw(d1, d2, d3); +- double d4 = (double) this.getWidth(); +- double d5 = (double) this.getHeight(); +- double d6 = (double) this.getWidth(); +- EnumDirection.EnumAxis enumdirection_enumaxis = this.direction.getAxis(); ++ if (entity != null) { ++ entity.setPosRaw(d1, d2, d3); ++ } ++ double d4 = (double) width; ++ double d5 = (double) height; ++ double d6 = (double) width; ++ EnumDirection.EnumAxis enumdirection_enumaxis = direction.getAxis(); + + switch (enumdirection_enumaxis) { + case X: +@@ -121,9 +132,10 @@ + d4 /= 32.0D; + d5 /= 32.0D; + d6 /= 32.0D; +- this.setBoundingBox(new AxisAlignedBB(d1 - d4, d2 - d5, d3 - d6, d1 + d4, d2 + d5, d3 + d6)); ++ return new AxisAlignedBB(d1 - d4, d2 - d5, d3 - d6, d1 + d4, d2 + d5, d3 + d6); + } + } ++ // CraftBukkit end + + @Override + public boolean survives() { +@@ -168,6 +180,11 @@ + return false; + } else if (!damagesource.is(DamageTypeTags.IS_EXPLOSION) && !this.getItem().isEmpty()) { + if (!this.level().isClientSide) { ++ // CraftBukkit start - fire EntityDamageEvent ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, damagesource, f, false) || this.isRemoved()) { ++ return true; ++ } ++ // CraftBukkit end + this.dropItem(damagesource.getEntity(), false); + this.gameEvent(GameEvent.BLOCK_CHANGE, damagesource.getEntity()); + this.playSound(this.getRemoveItemSound(), 1.0F, 1.0F); +@@ -297,13 +314,19 @@ + } + + public void setItem(ItemStack itemstack, boolean flag) { ++ // CraftBukkit start ++ this.setItem(itemstack, flag, true); ++ } ++ ++ public void setItem(ItemStack itemstack, boolean flag, boolean playSound) { ++ // CraftBukkit end + if (!itemstack.isEmpty()) { + itemstack = itemstack.copyWithCount(1); + } + + this.onItemChanged(itemstack); + this.getEntityData().set(EntityItemFrame.DATA_ITEM, itemstack); +- if (!itemstack.isEmpty()) { ++ if (!itemstack.isEmpty() && playSound) { // CraftBukkit + this.playSound(this.getAddItemSound(), 1.0F, 1.0F); + } + diff --git a/patch-remap/og/net/minecraft/world/entity/decoration/EntityLeash.patch b/patch-remap/og/net/minecraft/world/entity/decoration/EntityLeash.patch new file mode 100644 index 0000000000..e07f3e2b8b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/decoration/EntityLeash.patch @@ -0,0 +1,64 @@ +--- a/net/minecraft/world/entity/decoration/EntityLeash.java ++++ b/net/minecraft/world/entity/decoration/EntityLeash.java +@@ -26,6 +26,12 @@ + import net.minecraft.world.phys.AxisAlignedBB; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import net.minecraft.network.protocol.game.PacketPlayOutAttachEntity; ++import net.minecraft.server.level.EntityPlayer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class EntityLeash extends EntityHanging { + + public static final double OFFSET_Y = 0.375D; +@@ -96,6 +102,12 @@ + EntityInsentient entityinsentient = (EntityInsentient) iterator.next(); + + if (entityinsentient.getLeashHolder() == entityhuman) { ++ // CraftBukkit start ++ if (CraftEventFactory.callPlayerLeashEntityEvent(entityinsentient, this, entityhuman, enumhand).isCancelled()) { ++ ((EntityPlayer) entityhuman).connection.send(new PacketPlayOutAttachEntity(entityinsentient, entityinsentient.getLeashHolder())); ++ continue; ++ } ++ // CraftBukkit end + entityinsentient.setLeashedTo(this, true); + flag = true; + } +@@ -104,18 +116,32 @@ + boolean flag1 = false; + + if (!flag) { +- this.discard(); +- if (entityhuman.getAbilities().instabuild) { ++ // CraftBukkit start - Move below ++ // this.discard(); ++ boolean die = true; ++ // CraftBukkit end ++ if (true || entityhuman.getAbilities().instabuild) { // CraftBukkit - Process for non-creative as well + Iterator iterator1 = list.iterator(); + + while (iterator1.hasNext()) { + EntityInsentient entityinsentient1 = (EntityInsentient) iterator1.next(); + + if (entityinsentient1.isLeashed() && entityinsentient1.getLeashHolder() == this) { +- entityinsentient1.dropLeash(true, false); ++ // CraftBukkit start ++ if (CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient1, entityhuman, enumhand).isCancelled()) { ++ die = false; ++ continue; ++ } ++ entityinsentient1.dropLeash(true, !entityhuman.getAbilities().instabuild); // false -> survival mode boolean ++ // CraftBukkit end + flag1 = true; + } + } ++ // CraftBukkit start ++ if (die) { ++ this.discard(); ++ } ++ // CraftBukkit end + } + } + diff --git a/patch-remap/og/net/minecraft/world/entity/item/EntityFallingBlock.patch b/patch-remap/og/net/minecraft/world/entity/item/EntityFallingBlock.patch new file mode 100644 index 0000000000..db4e674df7 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/item/EntityFallingBlock.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/entity/item/EntityFallingBlock.java ++++ b/net/minecraft/world/entity/item/EntityFallingBlock.java +@@ -49,6 +49,10 @@ + import net.minecraft.world.phys.Vec3D; + import org.slf4j.Logger; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class EntityFallingBlock extends Entity { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -83,10 +87,17 @@ + } + + public static EntityFallingBlock fall(World world, BlockPosition blockposition, IBlockData iblockdata) { ++ // CraftBukkit start ++ return fall(world, blockposition, iblockdata, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ public static EntityFallingBlock fall(World world, BlockPosition blockposition, IBlockData iblockdata, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end + EntityFallingBlock entityfallingblock = new EntityFallingBlock(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, iblockdata.hasProperty(BlockProperties.WATERLOGGED) ? (IBlockData) iblockdata.setValue(BlockProperties.WATERLOGGED, false) : iblockdata); ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entityfallingblock, blockposition, iblockdata.getFluidState().createLegacyBlock())) return entityfallingblock; // CraftBukkit + + world.setBlock(blockposition, iblockdata.getFluidState().createLegacyBlock(), 3); +- world.addFreshEntity(entityfallingblock); ++ world.addFreshEntity(entityfallingblock, spawnReason); // CraftBukkit + return entityfallingblock; + } + +@@ -169,6 +180,12 @@ + this.blockState = (IBlockData) this.blockState.setValue(BlockProperties.WATERLOGGED, true); + } + ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, this.blockState)) { ++ this.discard(); // SPIGOT-6586 called before the event in previous versions ++ return; ++ } ++ // CraftBukkit end + if (this.level().setBlock(blockposition, this.blockState, 3)) { + ((WorldServer) this.level()).getChunkSource().chunkMap.broadcast(this, new PacketPlayOutBlockChange(blockposition, this.level().getBlockState(blockposition))); + this.discard(); +@@ -255,7 +272,9 @@ + float f2 = (float) Math.min(MathHelper.floor((float) i * this.fallDamagePerDistance), this.fallDamageMax); + + this.level().getEntities((Entity) this, this.getBoundingBox(), predicate).forEach((entity) -> { ++ CraftEventFactory.entityDamage = this; // CraftBukkit + entity.hurt(damagesource2, f2); ++ CraftEventFactory.entityDamage = null; // CraftBukkit + }); + boolean flag = this.blockState.is(TagsBlock.ANVIL); + diff --git a/patch-remap/og/net/minecraft/world/entity/item/EntityItem.patch b/patch-remap/og/net/minecraft/world/entity/item/EntityItem.patch new file mode 100644 index 0000000000..2960be8781 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/item/EntityItem.patch @@ -0,0 +1,137 @@ +--- a/net/minecraft/world/entity/item/EntityItem.java ++++ b/net/minecraft/world/entity/item/EntityItem.java +@@ -31,6 +31,14 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.entity.Player; ++import org.bukkit.event.entity.EntityPickupItemEvent; ++import org.bukkit.event.player.PlayerPickupItemEvent; ++// CraftBukkit end ++ + public class EntityItem extends Entity implements TraceableEntity { + + private static final DataWatcherObject DATA_ITEM = DataWatcher.defineId(EntityItem.class, DataWatcherRegistry.ITEM_STACK); +@@ -47,6 +55,7 @@ + @Nullable + public UUID target; + public final float bobOffs; ++ private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit + + public EntityItem(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -128,9 +137,12 @@ + this.discard(); + } else { + super.tick(); +- if (this.pickupDelay > 0 && this.pickupDelay != 32767) { +- --this.pickupDelay; +- } ++ // CraftBukkit start - Use wall time for pickup and despawn timers ++ int elapsedTicks = MinecraftServer.currentTick - this.lastTick; ++ if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; ++ if (this.age != -32768) this.age += elapsedTicks; ++ this.lastTick = MinecraftServer.currentTick; ++ // CraftBukkit end + + this.xo = this.getX(); + this.yo = this.getY(); +@@ -180,9 +192,11 @@ + this.mergeWithNeighbours(); + } + ++ /* CraftBukkit start - moved up + if (this.age != -32768) { + ++this.age; + } ++ // CraftBukkit end */ + + this.hasImpulse |= this.updateInWaterStateAndDoFluidPushing(); + if (!this.level().isClientSide) { +@@ -194,6 +208,12 @@ + } + + if (!this.level().isClientSide && this.age >= 6000) { ++ // CraftBukkit start - fire ItemDespawnEvent ++ if (CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { ++ this.age = 0; ++ return; ++ } ++ // CraftBukkit end + this.discard(); + } + +@@ -277,6 +297,11 @@ + } + + private static void merge(EntityItem entityitem, ItemStack itemstack, EntityItem entityitem1, ItemStack itemstack1) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callItemMergeEvent(entityitem1, entityitem)) { ++ return; ++ } ++ // CraftBukkit end + merge(entityitem, itemstack, itemstack1); + entityitem.pickupDelay = Math.max(entityitem.pickupDelay, entityitem1.pickupDelay); + entityitem.age = Math.min(entityitem.age, entityitem1.age); +@@ -302,6 +327,11 @@ + } else if (this.level().isClientSide) { + return true; + } else { ++ // CraftBukkit start ++ if (CraftEventFactory.handleNonLivingEntityDamageEvent(this, damagesource, f)) { ++ return false; ++ } ++ // CraftBukkit end + this.markHurt(); + this.health = (int) ((float) this.health - f); + this.gameEvent(GameEvent.ENTITY_DAMAGE, damagesource.getEntity()); +@@ -366,6 +396,46 @@ + Item item = itemstack.getItem(); + int i = itemstack.getCount(); + ++ // CraftBukkit start - fire PlayerPickupItemEvent ++ int canHold = entityhuman.getInventory().canHold(itemstack); ++ int remaining = i - canHold; ++ ++ if (this.pickupDelay <= 0 && canHold > 0) { ++ itemstack.setCount(canHold); ++ // Call legacy event ++ PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent((Player) entityhuman.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); ++ playerEvent.setCancelled(!playerEvent.getPlayer().getCanPickupItems()); ++ this.level().getCraftServer().getPluginManager().callEvent(playerEvent); ++ if (playerEvent.isCancelled()) { ++ itemstack.setCount(i); // SPIGOT-5294 - restore count ++ return; ++ } ++ ++ // Call newer event afterwards ++ EntityPickupItemEvent entityEvent = new EntityPickupItemEvent((Player) entityhuman.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); ++ entityEvent.setCancelled(!entityEvent.getEntity().getCanPickupItems()); ++ this.level().getCraftServer().getPluginManager().callEvent(entityEvent); ++ if (entityEvent.isCancelled()) { ++ itemstack.setCount(i); // SPIGOT-5294 - restore count ++ return; ++ } ++ ++ // Update the ItemStack if it was changed in the event ++ ItemStack current = this.getItem(); ++ if (!itemstack.equals(current)) { ++ itemstack = current; ++ } else { ++ itemstack.setCount(canHold + remaining); // = i ++ } ++ ++ // Possibly < 0; fix here so we do not have to modify code below ++ this.pickupDelay = 0; ++ } else if (this.pickupDelay == 0) { ++ // ensure that the code below isn't triggered if canHold says we can't pick the items up ++ this.pickupDelay = -1; ++ } ++ // CraftBukkit end ++ + if (this.pickupDelay == 0 && (this.target == null || this.target.equals(entityhuman.getUUID())) && entityhuman.getInventory().add(itemstack)) { + entityhuman.take(this, i); + if (itemstack.isEmpty()) { diff --git a/patch-remap/og/net/minecraft/world/entity/item/EntityTNTPrimed.patch b/patch-remap/og/net/minecraft/world/entity/item/EntityTNTPrimed.patch new file mode 100644 index 0000000000..073f462bcf --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/item/EntityTNTPrimed.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/entity/item/EntityTNTPrimed.java ++++ b/net/minecraft/world/entity/item/EntityTNTPrimed.java +@@ -19,6 +19,11 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end ++ + public class EntityTNTPrimed extends Entity implements TraceableEntity { + + private static final DataWatcherObject DATA_FUSE_ID = DataWatcher.defineId(EntityTNTPrimed.class, DataWatcherRegistry.INT); +@@ -28,6 +33,8 @@ + public static final String TAG_FUSE = "fuse"; + @Nullable + public EntityLiving owner; ++ public float yield = 4; // CraftBukkit - add field ++ public boolean isIncendiary = false; // CraftBukkit - add field + + public EntityTNTPrimed(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -79,10 +86,13 @@ + + this.setFuse(i); + if (i <= 0) { +- this.discard(); ++ // CraftBukkit start - Need to reverse the order of the explosion and the entity death so we have a location for the event ++ // this.discard(); + if (!this.level().isClientSide) { + this.explode(); + } ++ this.discard(); ++ // CraftBukkit end + } else { + this.updateInWaterStateAndDoFluidPushing(); + if (this.level().isClientSide) { +@@ -93,9 +103,14 @@ + } + + private void explode() { +- float f = 4.0F; ++ // CraftBukkit start ++ // float f = 4.0F; ++ ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent((org.bukkit.entity.Explosive)this.getBukkitEntity()); + +- this.level().explode(this, this.getX(), this.getY(0.0625D), this.getZ(), 4.0F, World.a.TNT); ++ if (!event.isCancelled()) { ++ this.level().explode(this, this.getX(), this.getY(0.0625D), this.getZ(), event.getRadius(), event.getFire(), World.a.TNT); ++ } ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntityCaveSpider.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntityCaveSpider.patch new file mode 100644 index 0000000000..b73945ea16 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntityCaveSpider.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/monster/EntityCaveSpider.java ++++ b/net/minecraft/world/entity/monster/EntityCaveSpider.java +@@ -42,7 +42,7 @@ + } + + if (b0 > 0) { +- ((EntityLiving) entity).addEffect(new MobEffect(MobEffects.POISON, b0 * 20, 0), this); ++ ((EntityLiving) entity).addEffect(new MobEffect(MobEffects.POISON, b0 * 20, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntityCreeper.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntityCreeper.patch new file mode 100644 index 0000000000..4a1e9252c6 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntityCreeper.patch @@ -0,0 +1,83 @@ +--- a/net/minecraft/world/entity/monster/EntityCreeper.java ++++ b/net/minecraft/world/entity/monster/EntityCreeper.java +@@ -43,6 +43,12 @@ + import net.minecraft.world.level.World; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end ++ + public class EntityCreeper extends EntityMonster implements PowerableMob { + + private static final DataWatcherObject DATA_SWELL_DIR = DataWatcher.defineId(EntityCreeper.class, DataWatcherRegistry.INT); +@@ -218,9 +224,20 @@ + @Override + public void thunderHit(WorldServer worldserver, EntityLightning entitylightning) { + super.thunderHit(worldserver, entitylightning); ++ // CraftBukkit start ++ if (CraftEventFactory.callCreeperPowerEvent(this, entitylightning, org.bukkit.event.entity.CreeperPowerEvent.PowerCause.LIGHTNING).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.entityData.set(EntityCreeper.DATA_IS_POWERED, true); + } + ++ // CraftBukkit start ++ public void setPowered(boolean powered) { ++ this.entityData.set(EntityCreeper.DATA_IS_POWERED, powered); ++ } ++ // CraftBukkit end ++ + @Override + protected EnumInteractionResult mobInteract(EntityHuman entityhuman, EnumHand enumhand) { + ItemStack itemstack = entityhuman.getItemInHand(enumhand); +@@ -231,7 +248,7 @@ + this.level().playSound(entityhuman, this.getX(), this.getY(), this.getZ(), soundeffect, this.getSoundSource(), 1.0F, this.random.nextFloat() * 0.4F + 0.8F); + if (!this.level().isClientSide) { + this.ignite(); +- if (!itemstack.isDamageableItem()) { ++ if (itemstack.getItem().getMaxDamage() == 0) { // CraftBukkit - fix MC-264285: unbreakable flint and steels are completely consumed when igniting a creeper + itemstack.shrink(1); + } else { + itemstack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { +@@ -250,10 +267,19 @@ + if (!this.level().isClientSide) { + float f = this.isPowered() ? 2.0F : 1.0F; + ++ // CraftBukkit start ++ ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent(this, this.explosionRadius * f, false); ++ if (!event.isCancelled()) { ++ // CraftBukkit end + this.dead = true; +- this.level().explode(this, this.getX(), this.getY(), this.getZ(), (float) this.explosionRadius * f, World.a.MOB); ++ this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), World.a.MOB); // CraftBukkit + this.discard(); + this.spawnLingeringCloud(); ++ // CraftBukkit start ++ } else { ++ swell = 0; ++ } ++ // CraftBukkit end + } + + } +@@ -264,6 +290,7 @@ + if (!collection.isEmpty()) { + EntityAreaEffectCloud entityareaeffectcloud = new EntityAreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); + ++ entityareaeffectcloud.setOwner(this); // CraftBukkit + entityareaeffectcloud.setRadius(2.5F); + entityareaeffectcloud.setRadiusOnUse(-0.5F); + entityareaeffectcloud.setWaitTime(10); +@@ -277,7 +304,7 @@ + entityareaeffectcloud.addEffect(new MobEffect(mobeffect)); + } + +- this.level().addFreshEntity(entityareaeffectcloud); ++ this.level().addFreshEntity(entityareaeffectcloud, CreatureSpawnEvent.SpawnReason.EXPLOSION); // CraftBukkit + } + + } diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntityDrowned.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntityDrowned.patch new file mode 100644 index 0000000000..b405773eca --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntityDrowned.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/monster/EntityDrowned.java ++++ b/net/minecraft/world/entity/monster/EntityDrowned.java +@@ -244,7 +244,7 @@ + + @Override + public void performRangedAttack(EntityLiving entityliving, float f) { +- EntityThrownTrident entitythrowntrident = new EntityThrownTrident(this.level(), this, new ItemStack(Items.TRIDENT)); ++ EntityThrownTrident entitythrowntrident = new EntityThrownTrident(this.level(), this, this.getItemInHand(net.minecraft.world.entity.projectile.ProjectileHelper.getWeaponHoldingHand(this, Items.TRIDENT))); // CraftBukkit - Use Trident in hand like skeletons (SPIGOT-7025) + double d0 = entityliving.getX() - this.getX(); + double d1 = entityliving.getY(0.3333333333333333D) - entitythrowntrident.getY(); + double d2 = entityliving.getZ() - this.getZ(); diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntityEnderman.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntityEnderman.patch new file mode 100644 index 0000000000..0470b2434f --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntityEnderman.patch @@ -0,0 +1,65 @@ +--- a/net/minecraft/world/entity/monster/EntityEnderman.java ++++ b/net/minecraft/world/entity/monster/EntityEnderman.java +@@ -71,6 +71,11 @@ + import net.minecraft.world.phys.Vec3D; + import org.joml.Vector3f; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end ++ + public class EntityEnderman extends EntityMonster implements IEntityAngerable { + + private static final UUID SPEED_MODIFIER_ATTACKING_UUID = UUID.fromString("020E0DFB-87AE-4653-9556-831010E291A0"); +@@ -115,7 +120,17 @@ + + @Override + public void setTarget(@Nullable EntityLiving entityliving) { +- super.setTarget(entityliving); ++ // CraftBukkit start - fire event ++ setTarget(entityliving, EntityTargetEvent.TargetReason.UNKNOWN, true); ++ } ++ ++ @Override ++ public boolean setTarget(EntityLiving entityliving, EntityTargetEvent.TargetReason reason, boolean fireEvent) { ++ if (!super.setTarget(entityliving, reason, fireEvent)) { ++ return false; ++ } ++ entityliving = getTarget(); ++ // CraftBukkit end + AttributeModifiable attributemodifiable = this.getAttribute(GenericAttributes.MOVEMENT_SPEED); + + if (entityliving == null) { +@@ -130,6 +145,7 @@ + attributemodifiable.addTransientModifier(EntityEnderman.SPEED_MODIFIER_ATTACKING); + } + } ++ return true; + + } + +@@ -493,9 +509,11 @@ + if (iblockdata2 != null) { + iblockdata2 = Block.updateFromNeighbourShapes(iblockdata2, this.enderman.level(), blockposition); + if (this.canPlaceBlock(world, blockposition, iblockdata2, iblockdata, iblockdata1, blockposition1)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockposition, iblockdata2)) { // CraftBukkit - Place event + world.setBlock(blockposition, iblockdata2, 3); + world.gameEvent(GameEvent.BLOCK_PLACE, blockposition, GameEvent.a.of(this.enderman, iblockdata2)); + this.enderman.setCarriedBlock((IBlockData) null); ++ } // CraftBukkit + } + + } +@@ -534,9 +552,11 @@ + boolean flag = movingobjectpositionblock.getBlockPos().equals(blockposition); + + if (iblockdata.is(TagsBlock.ENDERMAN_HOLDABLE) && flag) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockposition, Blocks.AIR.defaultBlockState())) { // CraftBukkit - Place event + world.removeBlock(blockposition, false); + world.gameEvent(GameEvent.BLOCK_DESTROY, blockposition, GameEvent.a.of(this.enderman, iblockdata)); + this.enderman.setCarriedBlock(iblockdata.getBlock().defaultBlockState()); ++ } // CraftBukkit + } + + } diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntityEvoker.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntityEvoker.patch new file mode 100644 index 0000000000..c3fa3d030d --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntityEvoker.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/monster/EntityEvoker.java ++++ b/net/minecraft/world/entity/monster/EntityEvoker.java +@@ -200,7 +200,7 @@ + worldserver.getScoreboard().addPlayerToTeam(entityvex.getScoreboardName(), scoreboardteam); + } + +- worldserver.addFreshEntityWithPassengers(entityvex); ++ worldserver.addFreshEntityWithPassengers(entityvex, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPELL); // CraftBukkit - Add SpawnReason + worldserver.gameEvent(GameEvent.ENTITY_PLACE, blockposition, GameEvent.a.of((Entity) EntityEvoker.this)); + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntityGhast.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntityGhast.patch new file mode 100644 index 0000000000..b13f60c7ee --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntityGhast.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/monster/EntityGhast.java ++++ b/net/minecraft/world/entity/monster/EntityGhast.java +@@ -348,6 +348,8 @@ + + EntityLargeFireball entitylargefireball = new EntityLargeFireball(world, this.ghast, d2, d3, d4, this.ghast.getExplosionPower()); + ++ // CraftBukkit - set bukkitYield when setting explosionpower ++ entitylargefireball.bukkitYield = entitylargefireball.explosionPower = this.ghast.getExplosionPower(); + entitylargefireball.setPos(this.ghast.getX() + vec3d.x * 4.0D, this.ghast.getY(0.5D) + 0.5D, entitylargefireball.getZ() + vec3d.z * 4.0D); + world.addFreshEntity(entitylargefireball); + this.chargeTime = -40; diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntityGuardian.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntityGuardian.patch new file mode 100644 index 0000000000..ca9e89b61e --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntityGuardian.patch @@ -0,0 +1,19 @@ +--- a/net/minecraft/world/entity/monster/EntityGuardian.java ++++ b/net/minecraft/world/entity/monster/EntityGuardian.java +@@ -63,6 +63,7 @@ + private boolean clientSideTouchedGround; + @Nullable + public PathfinderGoalRandomStroll randomStrollGoal; ++ public EntityGuardian.PathfinderGoalGuardianAttack guardianAttackGoal; // CraftBukkit - add field + + public EntityGuardian(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -78,7 +79,7 @@ + PathfinderGoalMoveTowardsRestriction pathfindergoalmovetowardsrestriction = new PathfinderGoalMoveTowardsRestriction(this, 1.0D); + + this.randomStrollGoal = new PathfinderGoalRandomStroll(this, 1.0D, 80); +- this.goalSelector.addGoal(4, new EntityGuardian.PathfinderGoalGuardianAttack(this)); ++ this.goalSelector.addGoal(4, guardianAttackGoal = new EntityGuardian.PathfinderGoalGuardianAttack(this)); // CraftBukkit - assign field + this.goalSelector.addGoal(5, pathfindergoalmovetowardsrestriction); + this.goalSelector.addGoal(7, this.randomStrollGoal); + this.goalSelector.addGoal(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntityGuardianElder.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntityGuardianElder.patch new file mode 100644 index 0000000000..d1e4065c39 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntityGuardianElder.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/monster/EntityGuardianElder.java ++++ b/net/minecraft/world/entity/monster/EntityGuardianElder.java +@@ -70,7 +70,7 @@ + super.customServerAiStep(); + if ((this.tickCount + this.getId()) % 1200 == 0) { + MobEffect mobeffect = new MobEffect(MobEffects.DIG_SLOWDOWN, 6000, 2); +- List list = MobEffectUtil.addEffectToPlayersAround((WorldServer) this.level(), this, this.position(), 50.0D, mobeffect, 1200); ++ List list = MobEffectUtil.addEffectToPlayersAround((WorldServer) this.level(), this, this.position(), 50.0D, mobeffect, 1200, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + + list.forEach((entityplayer) -> { + entityplayer.connection.send(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.GUARDIAN_ELDER_EFFECT, this.isSilent() ? 0.0F : 1.0F)); diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntityIllagerIllusioner.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntityIllagerIllusioner.patch new file mode 100644 index 0000000000..a749b7a0e5 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntityIllagerIllusioner.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java ++++ b/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java +@@ -228,7 +228,7 @@ + + @Override + protected void performSpellCasting() { +- EntityIllagerIllusioner.this.addEffect(new MobEffect(MobEffects.INVISIBILITY, 1200)); ++ EntityIllagerIllusioner.this.addEffect(new MobEffect(MobEffects.INVISIBILITY, 1200), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ILLUSION); // CraftBukkit + } + + @Nullable +@@ -279,7 +279,7 @@ + + @Override + protected void performSpellCasting() { +- EntityIllagerIllusioner.this.getTarget().addEffect(new MobEffect(MobEffects.BLINDNESS, 400), EntityIllagerIllusioner.this); ++ EntityIllagerIllusioner.this.getTarget().addEffect(new MobEffect(MobEffects.BLINDNESS, 400), EntityIllagerIllusioner.this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntityIllagerWizard.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntityIllagerWizard.patch new file mode 100644 index 0000000000..a25bbe31a5 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntityIllagerWizard.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/world/entity/monster/EntityIllagerWizard.java ++++ b/net/minecraft/world/entity/monster/EntityIllagerWizard.java +@@ -16,6 +16,10 @@ + import net.minecraft.world.entity.ai.goal.PathfinderGoal; + import net.minecraft.world.level.World; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public abstract class EntityIllagerWizard extends EntityIllagerAbstract { + + private static final DataWatcherObject DATA_SPELL_CASTING_ID = DataWatcher.defineId(EntityIllagerWizard.class, DataWatcherRegistry.BYTE); +@@ -155,6 +159,11 @@ + public void tick() { + --this.attackWarmupDelay; + if (this.attackWarmupDelay == 0) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handleEntitySpellCastEvent(EntityIllagerWizard.this, this.getSpell())) { ++ return; ++ } ++ // CraftBukkit end + this.performSpellCasting(); + EntityIllagerWizard.this.playSound(EntityIllagerWizard.this.getCastingSoundEvent(), 1.0F, 1.0F); + } diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntityPhantom.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntityPhantom.patch new file mode 100644 index 0000000000..d1fe7ee4b9 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntityPhantom.patch @@ -0,0 +1,19 @@ +--- a/net/minecraft/world/entity/monster/EntityPhantom.java ++++ b/net/minecraft/world/entity/monster/EntityPhantom.java +@@ -543,14 +543,14 @@ + List list = EntityPhantom.this.level().getNearbyPlayers(this.attackTargeting, EntityPhantom.this, EntityPhantom.this.getBoundingBox().inflate(16.0D, 64.0D, 16.0D)); + + if (!list.isEmpty()) { +- list.sort(Comparator.comparing(Entity::getY).reversed()); ++ list.sort(Comparator.comparing((Entity e) -> { return e.getY(); }).reversed()); // CraftBukkit - decompile error + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { + EntityHuman entityhuman = (EntityHuman) iterator.next(); + + if (EntityPhantom.this.canAttack(entityhuman, PathfinderTargetCondition.DEFAULT)) { +- EntityPhantom.this.setTarget(entityhuman); ++ EntityPhantom.this.setTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit - reason + return true; + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntityPigZombie.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntityPigZombie.patch new file mode 100644 index 0000000000..0c71b9df7e --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntityPigZombie.patch @@ -0,0 +1,44 @@ +--- a/net/minecraft/world/entity/monster/EntityPigZombie.java ++++ b/net/minecraft/world/entity/monster/EntityPigZombie.java +@@ -150,7 +150,7 @@ + }).filter((entitypigzombie) -> { + return !entitypigzombie.isAlliedTo((Entity) this.getTarget()); + }).forEach((entitypigzombie) -> { +- entitypigzombie.setTarget(this.getTarget()); ++ entitypigzombie.setTarget(this.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_NEARBY_ENTITY, true); // CraftBukkit + }); + } + +@@ -159,7 +159,7 @@ + } + + @Override +- public void setTarget(@Nullable EntityLiving entityliving) { ++ public boolean setTarget(@Nullable EntityLiving entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) { // CraftBukkit - signature + if (this.getTarget() == null && entityliving != null) { + this.playFirstAngerSoundIn = EntityPigZombie.FIRST_ANGER_SOUND_DELAY.sample(this.random); + this.ticksUntilNextAlert = EntityPigZombie.ALERT_INTERVAL.sample(this.random); +@@ -169,12 +169,21 @@ + this.setLastHurtByPlayer((EntityHuman) entityliving); + } + +- super.setTarget(entityliving); ++ return super.setTarget(entityliving, reason, fireEvent); // CraftBukkit + } + + @Override + public void startPersistentAngerTimer() { +- this.setRemainingPersistentAngerTime(EntityPigZombie.PERSISTENT_ANGER_TIME.sample(this.random)); ++ // CraftBukkit start ++ Entity entity = ((WorldServer) this.level()).getEntity(getPersistentAngerTarget()); ++ org.bukkit.event.entity.PigZombieAngerEvent event = new org.bukkit.event.entity.PigZombieAngerEvent((org.bukkit.entity.PigZombie) this.getBukkitEntity(), (entity == null) ? null : entity.getBukkitEntity(), EntityPigZombie.PERSISTENT_ANGER_TIME.sample(this.random)); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ this.setPersistentAngerTarget(null); ++ return; ++ } ++ this.setRemainingPersistentAngerTime(event.getNewAnger()); ++ // CraftBukkit end + } + + public static boolean checkZombifiedPiglinSpawnRules(EntityTypes entitytypes, GeneratorAccess generatoraccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, RandomSource randomsource) { diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntityRavager.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntityRavager.patch new file mode 100644 index 0000000000..feae2dad01 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntityRavager.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/world/entity/monster/EntityRavager.java ++++ b/net/minecraft/world/entity/monster/EntityRavager.java +@@ -43,6 +43,10 @@ + import net.minecraft.world.phys.Vec3D; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class EntityRavager extends EntityRaider { + + private static final Predicate NO_RAVAGER_AND_ALIVE = (entity) -> { +@@ -153,6 +157,11 @@ + Block block = iblockdata.getBlock(); + + if (block instanceof BlockLeaves) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState())) { ++ continue; ++ } ++ // CraftBukkit end + flag = this.level().destroyBlock(blockposition, true, this) || flag; + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntityShulker.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntityShulker.patch new file mode 100644 index 0000000000..1a9d64e269 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntityShulker.patch @@ -0,0 +1,39 @@ +--- a/net/minecraft/world/entity/monster/EntityShulker.java ++++ b/net/minecraft/world/entity/monster/EntityShulker.java +@@ -59,6 +59,12 @@ + import net.minecraft.world.phys.Vec3D; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.entity.EntityTeleportEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class EntityShulker extends EntityGolem implements VariantHolder>, IMonster { + + private static final UUID COVERED_ARMOR_MODIFIER_UUID = UUID.fromString("7E0292F2-9434-48D5-A29F-9583AF7DF27F"); +@@ -400,6 +406,14 @@ + EnumDirection enumdirection = this.findAttachableSurface(blockposition1); + + if (enumdirection != null) { ++ // CraftBukkit start ++ EntityTeleportEvent teleportEvent = CraftEventFactory.callEntityTeleportEvent(this, blockposition1.getX(), blockposition1.getY(), blockposition1.getZ()); ++ if (teleportEvent.isCancelled()) { ++ return false; ++ } else { ++ blockposition1 = CraftLocation.toBlockPosition(teleportEvent.getTo()); ++ } ++ // CraftBukkit end + this.unRide(); + this.setAttachFace(enumdirection); + this.playSound(SoundEffects.SHULKER_TELEPORT, 1.0F, 1.0F); +@@ -470,7 +484,7 @@ + if (entityshulker != null) { + entityshulker.setVariant(this.getVariant()); + entityshulker.moveTo(vec3d); +- this.level().addFreshEntity(entityshulker); ++ this.level().addFreshEntity(entityshulker, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - the mysteries of life + } + + } diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntitySilverfish.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntitySilverfish.patch new file mode 100644 index 0000000000..d7e3c5aabf --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntitySilverfish.patch @@ -0,0 +1,37 @@ +--- a/net/minecraft/world/entity/monster/EntitySilverfish.java ++++ b/net/minecraft/world/entity/monster/EntitySilverfish.java +@@ -34,6 +34,10 @@ + import net.minecraft.world.level.block.state.IBlockData; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class EntitySilverfish extends EntityMonster { + + @Nullable +@@ -176,6 +180,11 @@ + Block block = iblockdata.getBlock(); + + if (block instanceof BlockMonsterEggs) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.silverfish, blockposition1, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState())) { ++ continue; ++ } ++ // CraftBukkit end + if (world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { + world.destroyBlock(blockposition1, true, this.silverfish); + } else { +@@ -245,6 +254,11 @@ + IBlockData iblockdata = world.getBlockState(blockposition); + + if (BlockMonsterEggs.isCompatibleHostBlock(iblockdata)) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition, BlockMonsterEggs.infestedStateByHost(iblockdata))) { ++ return; ++ } ++ // CraftBukkit end + world.setBlock(blockposition, BlockMonsterEggs.infestedStateByHost(iblockdata), 3); + this.mob.spawnAnim(); + this.mob.discard(); diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntitySkeleton.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntitySkeleton.patch new file mode 100644 index 0000000000..0d58e34745 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntitySkeleton.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/monster/EntitySkeleton.java ++++ b/net/minecraft/world/entity/monster/EntitySkeleton.java +@@ -90,7 +90,7 @@ + } + + protected void doFreezeConversion() { +- this.convertTo(EntityTypes.STRAY, true); ++ this.convertTo(EntityTypes.STRAY, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.FROZEN, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.FROZEN); // CraftBukkit - add spawn and transform reasons + if (!this.isSilent()) { + this.level().levelEvent((EntityHuman) null, 1048, this.blockPosition(), 0); + } diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntitySkeletonAbstract.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntitySkeletonAbstract.patch new file mode 100644 index 0000000000..bab47f75c2 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntitySkeletonAbstract.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java ++++ b/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java +@@ -200,8 +200,19 @@ + double d3 = Math.sqrt(d0 * d0 + d2 * d2); + + entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level().getDifficulty().getId() * 4)); ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), null, entityarrow, net.minecraft.world.EnumHand.MAIN_HAND, 0.8F, true); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ ++ if (event.getProjectile() == entityarrow.getBukkitEntity()) { ++ this.level().addFreshEntity(entityarrow); ++ } ++ // CraftBukkit end + this.playSound(SoundEffects.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); +- this.level().addFreshEntity(entityarrow); ++ // this.level().addFreshEntity(entityarrow); // CraftBukkit - moved up + } + + protected EntityArrow getArrow(ItemStack itemstack, float f) { diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntitySkeletonWither.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntitySkeletonWither.patch new file mode 100644 index 0000000000..b5f342f3e1 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntitySkeletonWither.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/monster/EntitySkeletonWither.java ++++ b/net/minecraft/world/entity/monster/EntitySkeletonWither.java +@@ -111,7 +111,7 @@ + return false; + } else { + if (entity instanceof EntityLiving) { +- ((EntityLiving) entity).addEffect(new MobEffect(MobEffects.WITHER, 200), this); ++ ((EntityLiving) entity).addEffect(new MobEffect(MobEffects.WITHER, 200), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + + return true; diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntitySlime.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntitySlime.patch new file mode 100644 index 0000000000..1c26a1f3a3 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntitySlime.patch @@ -0,0 +1,66 @@ +--- a/net/minecraft/world/entity/monster/EntitySlime.java ++++ b/net/minecraft/world/entity/monster/EntitySlime.java +@@ -44,6 +44,14 @@ + import net.minecraft.world.phys.Vec3D; + import org.joml.Vector3f; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTransformEvent; ++import org.bukkit.event.entity.SlimeSplitEvent; ++// CraftBukkit end ++ + public class EntitySlime extends EntityInsentient implements IMonster { + + private static final DataWatcherObject ID_SIZE = DataWatcher.defineId(EntitySlime.class, DataWatcherRegistry.INT); +@@ -192,7 +200,7 @@ + + @Override + public EntityTypes getType() { +- return super.getType(); ++ return (EntityTypes) super.getType(); // CraftBukkit - decompile error + } + + @Override +@@ -206,6 +214,19 @@ + int j = i / 2; + int k = 2 + this.random.nextInt(3); + ++ // CraftBukkit start ++ SlimeSplitEvent event = new SlimeSplitEvent((org.bukkit.entity.Slime) this.getBukkitEntity(), k); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled() && event.getCount() > 0) { ++ k = event.getCount(); ++ } else { ++ super.remove(entity_removalreason); ++ return; ++ } ++ List slimes = new ArrayList<>(j); ++ // CraftBukkit end ++ + for (int l = 0; l < k; ++l) { + float f1 = ((float) (l % 2) - 0.5F) * f; + float f2 = ((float) (l / 2) - 0.5F) * f; +@@ -221,9 +242,18 @@ + entityslime.setInvulnerable(this.isInvulnerable()); + entityslime.setSize(j, true); + entityslime.moveTo(this.getX() + (double) f1, this.getY() + 0.5D, this.getZ() + (double) f2, this.random.nextFloat() * 360.0F, 0.0F); +- this.level().addFreshEntity(entityslime); ++ slimes.add(entityslime); // CraftBukkit + } + } ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, slimes, EntityTransformEvent.TransformReason.SPLIT).isCancelled()) { ++ super.remove(entity_removalreason); ++ return; ++ } ++ for (EntityLiving living : slimes) { ++ this.level().addFreshEntity(living, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SLIME_SPLIT); // CraftBukkit - SpawnReason ++ } ++ // CraftBukkit end + } + + super.remove(entity_removalreason); diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntitySpider.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntitySpider.patch new file mode 100644 index 0000000000..530bbaf31d --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntitySpider.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/monster/EntitySpider.java ++++ b/net/minecraft/world/entity/monster/EntitySpider.java +@@ -182,7 +182,7 @@ + MobEffectList mobeffectlist = entityspider_groupdataspider.effect; + + if (mobeffectlist != null) { +- this.addEffect(new MobEffect(mobeffectlist, -1)); ++ this.addEffect(new MobEffect(mobeffectlist, -1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.SPIDER_SPAWN); // CraftBukkit + } + } + diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntityStrider.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntityStrider.patch new file mode 100644 index 0000000000..53c7c3088b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntityStrider.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/entity/monster/EntityStrider.java ++++ b/net/minecraft/world/entity/monster/EntityStrider.java +@@ -351,7 +351,14 @@ + + boolean flag2 = flag1; + +- this.setSuffocating(!flag || flag2); ++ // CraftBukkit start ++ boolean suffocating = !flag || flag2; ++ if (suffocating ^ this.isSuffocating()) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callStriderTemperatureChangeEvent(this, suffocating)) { ++ this.setSuffocating(suffocating); ++ } ++ } ++ // CraftBukkit end + } + + super.tick(); diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntityVex.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntityVex.patch new file mode 100644 index 0000000000..d88bba7677 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntityVex.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/monster/EntityVex.java ++++ b/net/minecraft/world/entity/monster/EntityVex.java +@@ -404,7 +404,7 @@ + + @Override + public void start() { +- EntityVex.this.setTarget(EntityVex.this.owner.getTarget()); ++ EntityVex.this.setTarget(EntityVex.this.owner.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.OWNER_ATTACKED_TARGET, true); // CraftBukkit + super.start(); + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntityWitch.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntityWitch.patch new file mode 100644 index 0000000000..27eff7ad40 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntityWitch.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/monster/EntityWitch.java ++++ b/net/minecraft/world/entity/monster/EntityWitch.java +@@ -134,7 +134,7 @@ + while (iterator.hasNext()) { + MobEffect mobeffect = (MobEffect) iterator.next(); + +- this.addEffect(new MobEffect(mobeffect)); ++ this.addEffect(new MobEffect(mobeffect), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntityZombie.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntityZombie.patch new file mode 100644 index 0000000000..1c62de83fa --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntityZombie.patch @@ -0,0 +1,150 @@ +--- a/net/minecraft/world/entity/monster/EntityZombie.java ++++ b/net/minecraft/world/entity/monster/EntityZombie.java +@@ -67,6 +67,15 @@ + import net.minecraft.world.level.block.state.IBlockData; + import org.joml.Vector3f; + ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.entity.Zombie; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++// CraftBukkit end ++ + public class EntityZombie extends EntityMonster { + + private static final UUID SPEED_MODIFIER_BABY_UUID = UUID.fromString("B9766B59-9566-4402-BC1F-2EE2A276D836"); +@@ -87,6 +96,7 @@ + private boolean canBreakDoors; + private int inWaterTime; + public int conversionTime; ++ private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field + + public EntityZombie(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -203,7 +213,10 @@ + public void tick() { + if (!this.level().isClientSide && this.isAlive() && !this.isNoAi()) { + if (this.isUnderWaterConverting()) { +- --this.conversionTime; ++ // CraftBukkit start - Use wall time instead of ticks for conversion ++ int elapsedTicks = MinecraftServer.currentTick - this.lastTick; ++ this.conversionTime -= elapsedTicks; ++ // CraftBukkit end + if (this.conversionTime < 0) { + this.doUnderWaterConversion(); + } +@@ -220,6 +233,7 @@ + } + + super.tick(); ++ this.lastTick = MinecraftServer.currentTick; // CraftBukkit + } + + @Override +@@ -252,6 +266,7 @@ + } + + public void startUnderWaterConversion(int i) { ++ this.lastTick = MinecraftServer.currentTick; // CraftBukkit + this.conversionTime = i; + this.getEntityData().set(EntityZombie.DATA_DROWNED_CONVERSION_ID, true); + } +@@ -265,11 +280,15 @@ + } + + protected void convertToZombieType(EntityTypes entitytypes) { +- EntityZombie entityzombie = (EntityZombie) this.convertTo(entitytypes, true); ++ EntityZombie entityzombie = (EntityZombie) this.convertTo(entitytypes, true, EntityTransformEvent.TransformReason.DROWNED, CreatureSpawnEvent.SpawnReason.DROWNED); + + if (entityzombie != null) { + entityzombie.handleAttributes(entityzombie.level().getCurrentDifficultyAt(entityzombie.blockPosition()).getSpecialMultiplier()); + entityzombie.setCanBreakDoors(entityzombie.supportsBreakDoorGoal() && this.canBreakDoors()); ++ // CraftBukkit start - SPIGOT-5208: End conversion to stop event spam ++ } else { ++ ((Zombie) getBukkitEntity()).setConversionTime(-1); ++ // CraftBukkit end + } + + } +@@ -309,9 +328,9 @@ + if (SpawnerCreature.isSpawnPositionOk(entitypositiontypes_surface, this.level(), blockposition, entitytypes) && EntityPositionTypes.checkSpawnRules(entitytypes, worldserver, EnumMobSpawn.REINFORCEMENT, blockposition, this.level().random)) { + entityzombie.setPos((double) i1, (double) j1, (double) k1); + if (!this.level().hasNearbyAlivePlayer((double) i1, (double) j1, (double) k1, 7.0D) && this.level().isUnobstructed(entityzombie) && this.level().noCollision((Entity) entityzombie) && !this.level().containsAnyLiquid(entityzombie.getBoundingBox())) { +- entityzombie.setTarget(entityliving); ++ entityzombie.setTarget(entityliving, EntityTargetEvent.TargetReason.REINFORCEMENT_TARGET, true); // CraftBukkit + entityzombie.finalizeSpawn(worldserver, this.level().getCurrentDifficultyAt(entityzombie.blockPosition()), EnumMobSpawn.REINFORCEMENT, (GroupDataEntity) null, (NBTTagCompound) null); +- worldserver.addFreshEntityWithPassengers(entityzombie); ++ worldserver.addFreshEntityWithPassengers(entityzombie, CreatureSpawnEvent.SpawnReason.REINFORCEMENTS); // CraftBukkit + this.getAttribute(GenericAttributes.SPAWN_REINFORCEMENTS_CHANCE).addPermanentModifier(new AttributeModifier("Zombie reinforcement caller charge", -0.05000000074505806D, AttributeModifier.Operation.ADDITION)); + entityzombie.getAttribute(GenericAttributes.SPAWN_REINFORCEMENTS_CHANCE).addPermanentModifier(new AttributeModifier("Zombie reinforcement callee charge", -0.05000000074505806D, AttributeModifier.Operation.ADDITION)); + break; +@@ -332,7 +351,14 @@ + float f = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty(); + + if (this.getMainHandItem().isEmpty() && this.isOnFire() && this.random.nextFloat() < f * 0.3F) { +- entity.setSecondsOnFire(2 * (int) f); ++ // CraftBukkit start ++ EntityCombustByEntityEvent event = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), 2 * (int) f); // PAIL: fixme ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ entity.setSecondsOnFire(event.getDuration(), false); ++ } ++ // CraftBukkit end + } + } + +@@ -414,8 +440,17 @@ + if (worldserver.getDifficulty() != EnumDifficulty.HARD && this.random.nextBoolean()) { + return flag; + } ++ // CraftBukkit start ++ flag = zombifyVillager(worldserver, entityvillager, this.blockPosition(), this.isSilent(), CreatureSpawnEvent.SpawnReason.INFECTION) == null; ++ } + +- EntityZombieVillager entityzombievillager = (EntityZombieVillager) entityvillager.convertTo(EntityTypes.ZOMBIE_VILLAGER, false); ++ return flag; ++ } ++ ++ public static EntityZombieVillager zombifyVillager(WorldServer worldserver, EntityVillager entityvillager, net.minecraft.core.BlockPosition blockPosition, boolean silent, CreatureSpawnEvent.SpawnReason spawnReason) { ++ { ++ EntityZombieVillager entityzombievillager = (EntityZombieVillager) entityvillager.convertTo(EntityTypes.ZOMBIE_VILLAGER, false, EntityTransformEvent.TransformReason.INFECTION, spawnReason); ++ // CraftBukkit end + + if (entityzombievillager != null) { + entityzombievillager.finalizeSpawn(worldserver, worldserver.getCurrentDifficultyAt(entityzombievillager.blockPosition()), EnumMobSpawn.CONVERSION, new EntityZombie.GroupDataZombie(false, true), (NBTTagCompound) null); +@@ -423,15 +458,17 @@ + entityzombievillager.setGossips((NBTBase) entityvillager.getGossips().store(DynamicOpsNBT.INSTANCE)); + entityzombievillager.setTradeOffers(entityvillager.getOffers().createTag()); + entityzombievillager.setVillagerXp(entityvillager.getVillagerXp()); +- if (!this.isSilent()) { +- worldserver.levelEvent((EntityHuman) null, 1026, this.blockPosition(), 0); ++ // CraftBukkit start ++ if (!silent) { ++ worldserver.levelEvent((EntityHuman) null, 1026, blockPosition, 0); + } + +- flag = false; ++ // flag = false; + } +- } + +- return flag; ++ return entityzombievillager; ++ } ++ // CraftBukkit end + } + + @Override +@@ -484,7 +521,7 @@ + entitychicken1.finalizeSpawn(worldaccess, difficultydamagescaler, EnumMobSpawn.JOCKEY, (GroupDataEntity) null, (NBTTagCompound) null); + entitychicken1.setChickenJockey(true); + this.startRiding(entitychicken1); +- worldaccess.addFreshEntity(entitychicken1); ++ worldaccess.addFreshEntity(entitychicken1, CreatureSpawnEvent.SpawnReason.MOUNT); // CraftBukkit + } + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntityZombieHusk.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntityZombieHusk.patch new file mode 100644 index 0000000000..f02083ca8a --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntityZombieHusk.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/monster/EntityZombieHusk.java ++++ b/net/minecraft/world/entity/monster/EntityZombieHusk.java +@@ -60,7 +60,7 @@ + if (flag && this.getMainHandItem().isEmpty() && entity instanceof EntityLiving) { + float f = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty(); + +- ((EntityLiving) entity).addEffect(new MobEffect(MobEffects.HUNGER, 140 * (int) f), this); ++ ((EntityLiving) entity).addEffect(new MobEffect(MobEffects.HUNGER, 140 * (int) f), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + + return flag; diff --git a/patch-remap/og/net/minecraft/world/entity/monster/EntityZombieVillager.patch b/patch-remap/og/net/minecraft/world/entity/monster/EntityZombieVillager.patch new file mode 100644 index 0000000000..bfa1832ada --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/EntityZombieVillager.patch @@ -0,0 +1,99 @@ +--- a/net/minecraft/world/entity/monster/EntityZombieVillager.java ++++ b/net/minecraft/world/entity/monster/EntityZombieVillager.java +@@ -50,6 +50,13 @@ + import org.joml.Vector3f; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.entity.ZombieVillager; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++// CraftBukkit end ++ + public class EntityZombieVillager extends EntityZombie implements VillagerDataHolder { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -67,6 +74,7 @@ + @Nullable + private NBTTagCompound tradeOffers; + private int villagerXp; ++ private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field + + public EntityZombieVillager(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -85,7 +93,7 @@ + @Override + public void addAdditionalSaveData(NBTTagCompound nbttagcompound) { + super.addAdditionalSaveData(nbttagcompound); +- DataResult dataresult = VillagerData.CODEC.encodeStart(DynamicOpsNBT.INSTANCE, this.getVillagerData()); ++ DataResult dataresult = VillagerData.CODEC.encodeStart(DynamicOpsNBT.INSTANCE, this.getVillagerData()); // CraftBukkit - decompile error + Logger logger = EntityZombieVillager.LOGGER; + + Objects.requireNonNull(logger); +@@ -141,6 +149,10 @@ + public void tick() { + if (!this.level().isClientSide && this.isAlive() && this.isConverting()) { + int i = this.getConversionProgress(); ++ // CraftBukkit start - Use wall time instead of ticks for villager conversion ++ int elapsedTicks = MinecraftServer.currentTick - this.lastTick; ++ i *= elapsedTicks; ++ // CraftBukkit end + + this.villagerConversionTime -= i; + if (this.villagerConversionTime <= 0) { +@@ -149,6 +161,7 @@ + } + + super.tick(); ++ this.lastTick = MinecraftServer.currentTick; // CraftBukkit + } + + @Override +@@ -192,8 +205,10 @@ + this.conversionStarter = uuid; + this.villagerConversionTime = i; + this.getEntityData().set(EntityZombieVillager.DATA_CONVERTING_ID, true); +- this.removeEffect(MobEffects.WEAKNESS); +- this.addEffect(new MobEffect(MobEffects.DAMAGE_BOOST, i, Math.min(this.level().getDifficulty().getId() - 1, 0))); ++ // CraftBukkit start ++ this.removeEffect(MobEffects.WEAKNESS, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); ++ this.addEffect(new MobEffect(MobEffects.DAMAGE_BOOST, i, Math.min(this.level().getDifficulty().getId() - 1, 0)), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); ++ // CraftBukkit end + this.level().broadcastEntityEvent(this, (byte) 16); + } + +@@ -210,7 +225,13 @@ + } + + private void finishConversion(WorldServer worldserver) { +- EntityVillager entityvillager = (EntityVillager) this.convertTo(EntityTypes.VILLAGER, false); ++ // CraftBukkit start ++ EntityVillager entityvillager = (EntityVillager) this.convertTo(EntityTypes.VILLAGER, false, EntityTransformEvent.TransformReason.CURED, CreatureSpawnEvent.SpawnReason.CURED); ++ if (entityvillager == null) { ++ ((ZombieVillager) getBukkitEntity()).setConversionTime(-1); // SPIGOT-5208: End conversion to stop event spam ++ return; ++ } ++ // CraftBukkit end + EnumItemSlot[] aenumitemslot = EnumItemSlot.values(); + int i = aenumitemslot.length; + +@@ -225,7 +246,9 @@ + double d0 = (double) this.getEquipmentDropChance(enumitemslot); + + if (d0 > 1.0D) { ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation(itemstack); ++ this.forceDrops = false; // CraftBukkit + } + } + } +@@ -252,7 +275,7 @@ + } + } + +- entityvillager.addEffect(new MobEffect(MobEffects.CONFUSION, 200, 0)); ++ entityvillager.addEffect(new MobEffect(MobEffects.CONFUSION, 200, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); // CraftBukkit + if (!this.isSilent()) { + worldserver.levelEvent((EntityHuman) null, 1027, this.blockPosition(), 0); + } diff --git a/patch-remap/og/net/minecraft/world/entity/monster/piglin/EntityPiglin.patch b/patch-remap/og/net/minecraft/world/entity/monster/piglin/EntityPiglin.patch new file mode 100644 index 0000000000..e52f9a28e5 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/piglin/EntityPiglin.patch @@ -0,0 +1,96 @@ +--- a/net/minecraft/world/entity/monster/piglin/EntityPiglin.java ++++ b/net/minecraft/world/entity/monster/piglin/EntityPiglin.java +@@ -55,6 +55,18 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start ++import java.util.stream.Collectors; ++import java.util.HashSet; ++import java.util.Set; ++import net.minecraft.core.registries.BuiltInRegistries; ++import net.minecraft.nbt.NBTTagList; ++import net.minecraft.nbt.NBTTagString; ++import net.minecraft.nbt.NBTBase; ++import net.minecraft.resources.MinecraftKey; ++import net.minecraft.world.item.Item; ++// CraftBukkit end ++ + public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow, InventoryCarrier { + + private static final DataWatcherObject DATA_BABY_ID = DataWatcher.defineId(EntityPiglin.class, DataWatcherRegistry.BOOLEAN); +@@ -75,6 +87,10 @@ + public boolean cannotHunt; + protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.NEAREST_ITEMS, SensorType.HURT_BY, SensorType.PIGLIN_SPECIFIC_SENSOR); + protected static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.LOOK_TARGET, MemoryModuleType.DOORS_TO_CLOSE, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ADULT_PIGLINS, MemoryModuleType.NEARBY_ADULT_PIGLINS, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, new MemoryModuleType[]{MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.ATTACK_TARGET, MemoryModuleType.ATTACK_COOLING_DOWN, MemoryModuleType.INTERACTION_TARGET, MemoryModuleType.PATH, MemoryModuleType.ANGRY_AT, MemoryModuleType.UNIVERSAL_ANGER, MemoryModuleType.AVOID_TARGET, MemoryModuleType.ADMIRING_ITEM, MemoryModuleType.TIME_TRYING_TO_REACH_ADMIRE_ITEM, MemoryModuleType.ADMIRING_DISABLED, MemoryModuleType.DISABLE_WALK_TO_ADMIRE_ITEM, MemoryModuleType.CELEBRATE_LOCATION, MemoryModuleType.DANCING, MemoryModuleType.HUNTED_RECENTLY, MemoryModuleType.NEAREST_VISIBLE_BABY_HOGLIN, MemoryModuleType.NEAREST_VISIBLE_NEMESIS, MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED, MemoryModuleType.RIDE_TARGET, MemoryModuleType.VISIBLE_ADULT_PIGLIN_COUNT, MemoryModuleType.VISIBLE_ADULT_HOGLIN_COUNT, MemoryModuleType.NEAREST_VISIBLE_HUNTABLE_HOGLIN, MemoryModuleType.NEAREST_TARGETABLE_PLAYER_NOT_WEARING_GOLD, MemoryModuleType.NEAREST_PLAYER_HOLDING_WANTED_ITEM, MemoryModuleType.ATE_RECENTLY, MemoryModuleType.NEAREST_REPELLENT}); ++ // CraftBukkit start - Custom bartering and interest list ++ public Set allowedBarterItems = new HashSet<>(); ++ public Set interestItems = new HashSet<>(); ++ // CraftBukkit end + + public EntityPiglin(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -93,6 +109,14 @@ + } + + this.writeInventoryToTag(nbttagcompound); ++ // CraftBukkit start ++ NBTTagList barterList = new NBTTagList(); ++ allowedBarterItems.stream().map(BuiltInRegistries.ITEM::getKey).map(MinecraftKey::toString).map(NBTTagString::valueOf).forEach(barterList::add); ++ nbttagcompound.put("Bukkit.BarterList", barterList); ++ NBTTagList interestList = new NBTTagList(); ++ interestItems.stream().map(BuiltInRegistries.ITEM::getKey).map(MinecraftKey::toString).map(NBTTagString::valueOf).forEach(interestList::add); ++ nbttagcompound.put("Bukkit.InterestList", interestList); ++ // CraftBukkit end + } + + @Override +@@ -101,6 +125,10 @@ + this.setBaby(nbttagcompound.getBoolean("IsBaby")); + this.setCannotHunt(nbttagcompound.getBoolean("CannotHunt")); + this.readInventoryFromTag(nbttagcompound); ++ // CraftBukkit start ++ this.allowedBarterItems = nbttagcompound.getList("Bukkit.BarterList", 8).stream().map(NBTBase::getAsString).map(MinecraftKey::tryParse).map(BuiltInRegistries.ITEM::get).collect(Collectors.toCollection(HashSet::new)); ++ this.interestItems = nbttagcompound.getList("Bukkit.InterestList", 8).stream().map(NBTBase::getAsString).map(MinecraftKey::tryParse).map(BuiltInRegistries.ITEM::get).collect(Collectors.toCollection(HashSet::new)); ++ // CraftBukkit end + } + + @VisibleForDebug +@@ -220,7 +248,7 @@ + + @Override + public BehaviorController getBrain() { +- return super.getBrain(); ++ return (BehaviorController) super.getBrain(); // CraftBukkit - Decompile error + } + + @Override +@@ -360,7 +388,7 @@ + } + + protected void holdInOffHand(ItemStack itemstack) { +- if (itemstack.is(PiglinAI.BARTERING_ITEM)) { ++ if (itemstack.is(PiglinAI.BARTERING_ITEM) || allowedBarterItems.contains(itemstack.getItem())) { // CraftBukkit - Changes to accept custom payment items + this.setItemSlot(EnumItemSlot.OFFHAND, itemstack); + this.setGuaranteedDrop(EnumItemSlot.OFFHAND); + } else { +@@ -386,8 +414,8 @@ + if (EnchantmentManager.hasBindingCurse(itemstack1)) { + return false; + } else { +- boolean flag = PiglinAI.isLovedItem(itemstack) || itemstack.is(Items.CROSSBOW); +- boolean flag1 = PiglinAI.isLovedItem(itemstack1) || itemstack1.is(Items.CROSSBOW); ++ boolean flag = PiglinAI.isLovedItem(itemstack, this) || itemstack.is(Items.CROSSBOW); // CraftBukkit ++ boolean flag1 = PiglinAI.isLovedItem(itemstack1, this) || itemstack1.is(Items.CROSSBOW); // CraftBukkit + + return flag && !flag1 ? true : (!flag && flag1 ? false : (this.isAdult() && !itemstack.is(Items.CROSSBOW) && itemstack1.is(Items.CROSSBOW) ? false : super.canReplaceCurrentItem(itemstack, itemstack1))); + } +@@ -416,7 +444,7 @@ + + @Override + protected SoundEffect getAmbientSound() { +- return this.level().isClientSide ? null : (SoundEffect) PiglinAI.getSoundForCurrentActivity(this).orElse((Object) null); ++ return this.level().isClientSide ? null : (SoundEffect) PiglinAI.getSoundForCurrentActivity(this).orElse(null); // CraftBukkit - Decompile error + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/entity/monster/piglin/EntityPiglinAbstract.patch b/patch-remap/og/net/minecraft/world/entity/monster/piglin/EntityPiglinAbstract.patch new file mode 100644 index 0000000000..6c912b25f0 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/piglin/EntityPiglinAbstract.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/entity/monster/piglin/EntityPiglinAbstract.java ++++ b/net/minecraft/world/entity/monster/piglin/EntityPiglinAbstract.java +@@ -115,7 +115,7 @@ + } + + protected void finishConversion(WorldServer worldserver) { +- EntityPigZombie entitypigzombie = (EntityPigZombie) this.convertTo(EntityTypes.ZOMBIFIED_PIGLIN, true); ++ EntityPigZombie entitypigzombie = (EntityPigZombie) this.convertTo(EntityTypes.ZOMBIFIED_PIGLIN, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.PIGLIN_ZOMBIFIED, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.PIGLIN_ZOMBIFIED); // CraftBukkit - add spawn and transform reasons + + if (entitypigzombie != null) { + entitypigzombie.addEffect(new MobEffect(MobEffects.CONFUSION, 200, 0)); +@@ -132,7 +132,7 @@ + @Nullable + @Override + public EntityLiving getTarget() { +- return (EntityLiving) this.brain.getMemory(MemoryModuleType.ATTACK_TARGET).orElse((Object) null); ++ return (EntityLiving) this.brain.getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); // CraftBukkit - decompile error + } + + protected boolean isHoldingMeleeWeapon() { diff --git a/patch-remap/og/net/minecraft/world/entity/monster/piglin/PiglinAI.patch b/patch-remap/og/net/minecraft/world/entity/monster/piglin/PiglinAI.patch new file mode 100644 index 0000000000..78bc59e864 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/piglin/PiglinAI.patch @@ -0,0 +1,163 @@ +--- a/net/minecraft/world/entity/monster/piglin/PiglinAI.java ++++ b/net/minecraft/world/entity/monster/piglin/PiglinAI.java +@@ -74,6 +74,13 @@ + import net.minecraft.world.level.storage.loot.parameters.LootContextParameters; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import java.util.stream.Collectors; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.entity.PiglinBarterEvent; ++// CraftBukkit end ++ + public class PiglinAI { + + public static final int REPELLENT_DETECTION_RANGE_HORIZONTAL = 8; +@@ -164,7 +171,8 @@ + } + + private static void initRideHoglinActivity(BehaviorController behaviorcontroller) { +- behaviorcontroller.addActivityAndRemoveMemoryWhenStopped(Activity.RIDE, 10, ImmutableList.of(BehaviorStartRiding.create(0.8F), BehaviorLookTarget.create(PiglinAI::isPlayerHoldingLovedItem, 8.0F), BehaviorBuilder.sequence(BehaviorBuilder.triggerIf(Entity::isPassenger), TriggerGate.triggerOneShuffled(ImmutableList.builder().addAll(createLookBehaviors()).add(Pair.of(BehaviorBuilder.triggerIf((entitypiglin) -> { ++ // CraftBukkit - decompile error ++ behaviorcontroller.addActivityAndRemoveMemoryWhenStopped(Activity.RIDE, 10, ImmutableList.of(BehaviorStartRiding.create(0.8F), BehaviorLookTarget.create(PiglinAI::isPlayerHoldingLovedItem, 8.0F), BehaviorBuilder.sequence(BehaviorBuilder.triggerIf(Entity::isPassenger), TriggerGate.triggerOneShuffled(ImmutableList., Integer>>builder().addAll(createLookBehaviors()).add(Pair.of(BehaviorBuilder.triggerIf((entitypiglin) -> { + return true; + }), 1)).build())), BehaviorStopRiding.create(8, PiglinAI::wantsToStopRiding)), MemoryModuleType.RIDE_TARGET); + } +@@ -174,7 +182,7 @@ + } + + private static BehaviorGateSingle createIdleLookBehaviors() { +- return new BehaviorGateSingle<>(ImmutableList.builder().addAll(createLookBehaviors()).add(Pair.of(new BehaviorNop(30, 60), 1)).build()); ++ return new BehaviorGateSingle<>(ImmutableList., Integer>>builder().addAll(createLookBehaviors()).add(Pair.of(new BehaviorNop(30, 60), 1)).build()); // CraftBukkit - decompile error + } + + private static BehaviorGateSingle createIdleMovementBehaviors() { +@@ -195,13 +203,13 @@ + + protected static void updateActivity(EntityPiglin entitypiglin) { + BehaviorController behaviorcontroller = entitypiglin.getBrain(); +- Activity activity = (Activity) behaviorcontroller.getActiveNonCoreActivity().orElse((Object) null); ++ Activity activity = (Activity) behaviorcontroller.getActiveNonCoreActivity().orElse(null); // CraftBukkit - decompile error + + behaviorcontroller.setActiveActivityToFirstValid(ImmutableList.of(Activity.ADMIRE_ITEM, Activity.FIGHT, Activity.AVOID, Activity.CELEBRATE, Activity.RIDE, Activity.IDLE)); +- Activity activity1 = (Activity) behaviorcontroller.getActiveNonCoreActivity().orElse((Object) null); ++ Activity activity1 = (Activity) behaviorcontroller.getActiveNonCoreActivity().orElse(null); // CraftBukkit - decompile error + + if (activity != activity1) { +- Optional optional = getSoundForCurrentActivity(entitypiglin); ++ Optional optional = getSoundForCurrentActivity(entitypiglin); // CraftBukkit - decompile error + + Objects.requireNonNull(entitypiglin); + optional.ifPresent(entitypiglin::playSoundEvent); +@@ -233,23 +241,27 @@ + stopWalking(entitypiglin); + ItemStack itemstack; + +- if (entityitem.getItem().is(Items.GOLD_NUGGET)) { ++ // CraftBukkit start ++ if (entityitem.getItem().is(Items.GOLD_NUGGET) && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(entitypiglin, entityitem, 0, false).isCancelled()) { + entitypiglin.take(entityitem, entityitem.getItem().getCount()); + itemstack = entityitem.getItem(); + entityitem.discard(); +- } else { ++ } else if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(entitypiglin, entityitem, entityitem.getItem().getCount() - 1, false).isCancelled()) { + entitypiglin.take(entityitem, 1); + itemstack = removeOneItemFromItemEntity(entityitem); ++ } else { ++ return; + } ++ // CraftBukkit end + +- if (isLovedItem(itemstack)) { ++ if (isLovedItem(itemstack, entitypiglin)) { // CraftBukkit - Changes to allow for custom payment in bartering + entitypiglin.getBrain().eraseMemory(MemoryModuleType.TIME_TRYING_TO_REACH_ADMIRE_ITEM); + holdInOffhand(entitypiglin, itemstack); + admireGoldItem(entitypiglin); + } else if (isFood(itemstack) && !hasEatenRecently(entitypiglin)) { + eat(entitypiglin); + } else { +- boolean flag = !entitypiglin.equipItemIfPossible(itemstack).equals(ItemStack.EMPTY); ++ boolean flag = !entitypiglin.equipItemIfPossible(itemstack, entityitem).equals(ItemStack.EMPTY); // CraftBukkit + + if (!flag) { + putInInventory(entitypiglin, itemstack); +@@ -285,9 +297,14 @@ + boolean flag1; + + if (entitypiglin.isAdult()) { +- flag1 = isBarterCurrency(itemstack); ++ flag1 = isBarterCurrency(itemstack, entitypiglin); // CraftBukkit - Changes to allow custom payment for bartering + if (flag && flag1) { +- throwItems(entitypiglin, getBarterResponseItems(entitypiglin)); ++ // CraftBukkit start ++ PiglinBarterEvent event = CraftEventFactory.callPiglinBarterEvent(entitypiglin, getBarterResponseItems(entitypiglin), itemstack); ++ if (!event.isCancelled()) { ++ throwItems(entitypiglin, event.getOutcome().stream().map(CraftItemStack::asNMSCopy).collect(Collectors.toList())); ++ } ++ // CraftBukkit end + } else if (!flag1) { + boolean flag2 = !entitypiglin.equipItemIfPossible(itemstack).isEmpty(); + +@@ -300,7 +317,7 @@ + if (!flag1) { + ItemStack itemstack1 = entitypiglin.getMainHandItem(); + +- if (isLovedItem(itemstack1)) { ++ if (isLovedItem(itemstack1, entitypiglin)) { // CraftBukkit - Changes to allow for custom payment in bartering + putInInventory(entitypiglin, itemstack1); + } else { + throwItems(entitypiglin, Collections.singletonList(itemstack1)); +@@ -377,7 +394,7 @@ + return false; + } else if (isAdmiringDisabled(entitypiglin) && entitypiglin.getBrain().hasMemoryValue(MemoryModuleType.ATTACK_TARGET)) { + return false; +- } else if (isBarterCurrency(itemstack)) { ++ } else if (isBarterCurrency(itemstack, entitypiglin)) { // CraftBukkit + return isNotHoldingLovedItemInOffHand(entitypiglin); + } else { + boolean flag = entitypiglin.canAddToInventory(itemstack); +@@ -386,6 +403,12 @@ + } + } + ++ // CraftBukkit start - Added method to allow checking for custom payment items ++ protected static boolean isLovedItem(ItemStack itemstack, EntityPiglin piglin) { ++ return isLovedItem(itemstack) || (piglin.interestItems.contains(itemstack.getItem()) || piglin.allowedBarterItems.contains(itemstack.getItem())); ++ } ++ // CraftBukkit end ++ + protected static boolean isLovedItem(ItemStack itemstack) { + return itemstack.is(TagsItem.PIGLIN_LOVED); + } +@@ -481,7 +504,7 @@ + } + + protected static boolean canAdmire(EntityPiglin entitypiglin, ItemStack itemstack) { +- return !isAdmiringDisabled(entitypiglin) && !isAdmiringItem(entitypiglin) && entitypiglin.isAdult() && isBarterCurrency(itemstack); ++ return !isAdmiringDisabled(entitypiglin) && !isAdmiringItem(entitypiglin) && entitypiglin.isAdult() && isBarterCurrency(itemstack, entitypiglin); // CraftBukkit + } + + protected static void wasHurtBy(EntityPiglin entitypiglin, EntityLiving entityliving) { +@@ -738,6 +761,12 @@ + return entitypiglin.getBrain().hasMemoryValue(MemoryModuleType.ADMIRING_ITEM); + } + ++ // CraftBukkit start - Changes to allow custom payment for bartering ++ private static boolean isBarterCurrency(ItemStack itemstack, EntityPiglin piglin) { ++ return isBarterCurrency(itemstack) || piglin.allowedBarterItems.contains(itemstack.getItem()); ++ } ++ // CraftBukkit end ++ + private static boolean isBarterCurrency(ItemStack itemstack) { + return itemstack.is(PiglinAI.BARTERING_ITEM); + } +@@ -775,7 +804,7 @@ + } + + private static boolean isNotHoldingLovedItemInOffHand(EntityPiglin entitypiglin) { +- return entitypiglin.getOffhandItem().isEmpty() || !isLovedItem(entitypiglin.getOffhandItem()); ++ return entitypiglin.getOffhandItem().isEmpty() || !isLovedItem(entitypiglin.getOffhandItem(), entitypiglin); // CraftBukkit - Changes to allow custom payment for bartering + } + + public static boolean isZombified(EntityTypes entitytypes) { diff --git a/patch-remap/og/net/minecraft/world/entity/monster/warden/Warden.patch b/patch-remap/og/net/minecraft/world/entity/monster/warden/Warden.patch new file mode 100644 index 0000000000..ae64567f37 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/monster/warden/Warden.patch @@ -0,0 +1,72 @@ +--- a/net/minecraft/world/entity/monster/warden/Warden.java ++++ b/net/minecraft/world/entity/monster/warden/Warden.java +@@ -373,7 +373,7 @@ + + @Override + public BehaviorController getBrain() { +- return super.getBrain(); ++ return (BehaviorController) super.getBrain(); // CraftBukkit - decompile error + } + + @Override +@@ -414,13 +414,13 @@ + public static void applyDarknessAround(WorldServer worldserver, Vec3D vec3d, @Nullable Entity entity, int i) { + MobEffect mobeffect = new MobEffect(MobEffects.DARKNESS, 260, 0, false, false); + +- MobEffectUtil.addEffectToPlayersAround(worldserver, entity, vec3d, (double) i, mobeffect, 200); ++ MobEffectUtil.addEffectToPlayersAround(worldserver, entity, vec3d, i, mobeffect, 200, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.WARDEN); // CraftBukkit - Add EntityPotionEffectEvent.Cause + } + + @Override + public void addAdditionalSaveData(NBTTagCompound nbttagcompound) { + super.addAdditionalSaveData(nbttagcompound); +- DataResult dataresult = AngerManagement.codec(this::canTargetEntity).encodeStart(DynamicOpsNBT.INSTANCE, this.angerManagement); ++ DataResult dataresult = AngerManagement.codec(this::canTargetEntity).encodeStart(DynamicOpsNBT.INSTANCE, this.angerManagement); // CraftBukkit - decompile error + Logger logger = Warden.LOGGER; + + Objects.requireNonNull(logger); +@@ -445,7 +445,7 @@ + dataresult = AngerManagement.codec(this::canTargetEntity).parse(new Dynamic(DynamicOpsNBT.INSTANCE, nbttagcompound.get("anger"))); + logger = Warden.LOGGER; + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((angermanagement) -> { ++ ((DataResult) dataresult).resultOrPartial(logger::error).ifPresent((angermanagement) -> { // CraftBukkit - decompile error + this.angerManagement = angermanagement; + }); + this.syncClientAngerLevel(); +@@ -455,7 +455,7 @@ + dataresult = VibrationSystem.a.CODEC.parse(new Dynamic(DynamicOpsNBT.INSTANCE, nbttagcompound.getCompound("listener"))); + logger = Warden.LOGGER; + Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((vibrationsystem_a) -> { ++ ((DataResult) dataresult).resultOrPartial(logger::error).ifPresent((vibrationsystem_a) -> { // CraftBukkit - decompile error + this.vibrationData = vibrationsystem_a; + }); + } +@@ -489,7 +489,7 @@ + public void increaseAngerAt(@Nullable Entity entity, int i, boolean flag) { + if (!this.isNoAi() && this.canTargetEntity(entity)) { + WardenAi.setDigCooldown(this); +- boolean flag1 = !(this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse((Object) null) instanceof EntityHuman); ++ boolean flag1 = !(this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null) instanceof EntityHuman); // CraftBukkit - decompile error + int j = this.angerManagement.increaseAnger(entity, i); + + if (entity instanceof EntityHuman && flag1 && AngerLevel.byAnger(j).isAngry()) { +@@ -510,7 +510,7 @@ + @Nullable + @Override + public EntityLiving getTarget() { +- return (EntityLiving) this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse((Object) null); ++ return (EntityLiving) this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); // CraftBukkit - decompile error + } + + @Override +@@ -553,7 +553,7 @@ + + public void setAttackTarget(EntityLiving entityliving) { + this.getBrain().eraseMemory(MemoryModuleType.ROAR_TARGET); +- this.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, (Object) entityliving); ++ this.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, entityliving); // CraftBukkit - decompile error + this.getBrain().eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE); + SonicBoom.setCooldown(this, 200); + } diff --git a/patch-remap/og/net/minecraft/world/entity/npc/EntityVillager.patch b/patch-remap/og/net/minecraft/world/entity/npc/EntityVillager.patch new file mode 100644 index 0000000000..9e8c71fa85 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/npc/EntityVillager.patch @@ -0,0 +1,115 @@ +--- a/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/net/minecraft/world/entity/npc/EntityVillager.java +@@ -92,6 +92,14 @@ + import net.minecraft.world.phys.AxisAlignedBB; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.entity.Villager; ++import org.bukkit.event.entity.EntityTransformEvent; ++import org.bukkit.event.entity.VillagerReplenishTradeEvent; ++// CraftBukkit end ++ + public class EntityVillager extends EntityVillagerAbstract implements ReputationHandler, VillagerDataHolder { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -150,7 +158,7 @@ + + @Override + public BehaviorController getBrain() { +- return super.getBrain(); ++ return (BehaviorController) super.getBrain(); // CraftBukkit - decompile error + } + + @Override +@@ -233,7 +241,7 @@ + this.increaseProfessionLevelOnUpdate = false; + } + +- this.addEffect(new MobEffect(MobEffects.REGENERATION, 200, 0)); ++ this.addEffect(new MobEffect(MobEffects.REGENERATION, 200, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.VILLAGER_TRADE); // CraftBukkit + } + } + +@@ -361,7 +369,13 @@ + while (iterator.hasNext()) { + MerchantRecipe merchantrecipe = (MerchantRecipe) iterator.next(); + +- merchantrecipe.resetUses(); ++ // CraftBukkit start ++ VillagerReplenishTradeEvent event = new VillagerReplenishTradeEvent((Villager) this.getBukkitEntity(), merchantrecipe.asBukkit()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ merchantrecipe.resetUses(); ++ } ++ // CraftBukkit end + } + + this.resendOffersToTradingPlayer(); +@@ -430,7 +444,13 @@ + while (iterator.hasNext()) { + MerchantRecipe merchantrecipe = (MerchantRecipe) iterator.next(); + +- merchantrecipe.resetUses(); ++ // CraftBukkit start ++ VillagerReplenishTradeEvent event = new VillagerReplenishTradeEvent((Villager) this.getBukkitEntity(), merchantrecipe.asBukkit()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ merchantrecipe.resetUses(); ++ } ++ // CraftBukkit end + } + } + +@@ -490,7 +510,7 @@ + @Override + public void addAdditionalSaveData(NBTTagCompound nbttagcompound) { + super.addAdditionalSaveData(nbttagcompound); +- DataResult dataresult = VillagerData.CODEC.encodeStart(DynamicOpsNBT.INSTANCE, this.getVillagerData()); ++ DataResult dataresult = VillagerData.CODEC.encodeStart(DynamicOpsNBT.INSTANCE, this.getVillagerData()); // CraftBukkit - decompile error + Logger logger = EntityVillager.LOGGER; + + Objects.requireNonNull(logger); +@@ -834,7 +854,12 @@ + } + + entitywitch.setPersistenceRequired(); +- worldserver.addFreshEntityWithPassengers(entitywitch); ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, entitywitch, EntityTransformEvent.TransformReason.LIGHTNING).isCancelled()) { ++ return; ++ } ++ worldserver.addFreshEntityWithPassengers(entitywitch, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); ++ // CraftBukkit end + this.releaseAllPois(); + this.discard(); + } else { +@@ -933,7 +958,7 @@ + }).limit(5L).collect(Collectors.toList()); + + if (list1.size() >= j) { +- if (!SpawnUtil.trySpawnMob(EntityTypes.IRON_GOLEM, EnumMobSpawn.MOB_SUMMONED, worldserver, this.blockPosition(), 10, 8, 6, SpawnUtil.a.LEGACY_IRON_GOLEM).isEmpty()) { ++ if (!SpawnUtil.trySpawnMob(EntityTypes.IRON_GOLEM, EnumMobSpawn.MOB_SUMMONED, worldserver, this.blockPosition(), 10, 8, 6, SpawnUtil.a.LEGACY_IRON_GOLEM, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE).isEmpty()) { // CraftBukkit + list.forEach(SensorGolemLastSeen::golemDetected); + } + } +@@ -990,7 +1015,7 @@ + @Override + public void startSleeping(BlockPosition blockposition) { + super.startSleeping(blockposition); +- this.brain.setMemory(MemoryModuleType.LAST_SLEPT, (Object) this.level().getGameTime()); ++ this.brain.setMemory(MemoryModuleType.LAST_SLEPT, this.level().getGameTime()); // CraftBukkit - decompile error + this.brain.eraseMemory(MemoryModuleType.WALK_TARGET); + this.brain.eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE); + } +@@ -998,7 +1023,7 @@ + @Override + public void stopSleeping() { + super.stopSleeping(); +- this.brain.setMemory(MemoryModuleType.LAST_WOKEN, (Object) this.level().getGameTime()); ++ this.brain.setMemory(MemoryModuleType.LAST_WOKEN, this.level().getGameTime()); // CraftBukkit - decompile error + } + + private boolean golemSpawnConditionsMet(long i) { diff --git a/patch-remap/og/net/minecraft/world/entity/npc/EntityVillagerAbstract.patch b/patch-remap/og/net/minecraft/world/entity/npc/EntityVillagerAbstract.patch new file mode 100644 index 0000000000..d6c61da367 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/npc/EntityVillagerAbstract.patch @@ -0,0 +1,54 @@ +--- a/net/minecraft/world/entity/npc/EntityVillagerAbstract.java ++++ b/net/minecraft/world/entity/npc/EntityVillagerAbstract.java +@@ -35,8 +35,24 @@ + import net.minecraft.world.level.pathfinder.PathType; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.inventory.CraftMerchant; ++import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; ++import org.bukkit.entity.AbstractVillager; ++import org.bukkit.event.entity.VillagerAcquireTradeEvent; ++// CraftBukkit end ++ + public abstract class EntityVillagerAbstract extends EntityAgeable implements InventoryCarrier, NPC, IMerchant { + ++ // CraftBukkit start ++ private CraftMerchant craftMerchant; ++ ++ @Override ++ public CraftMerchant getCraftMerchant() { ++ return (craftMerchant == null) ? craftMerchant = new CraftMerchant(this) : craftMerchant; ++ } ++ // CraftBukkit end + private static final DataWatcherObject DATA_UNHAPPY_COUNTER = DataWatcher.defineId(EntityVillagerAbstract.class, DataWatcherRegistry.INT); + public static final int VILLAGER_SLOT_OFFSET = 300; + private static final int VILLAGER_INVENTORY_SIZE = 8; +@@ -44,7 +60,7 @@ + private EntityHuman tradingPlayer; + @Nullable + protected MerchantRecipeList offers; +- private final InventorySubcontainer inventory = new InventorySubcontainer(8); ++ private final InventorySubcontainer inventory = new InventorySubcontainer(8, (org.bukkit.craftbukkit.entity.CraftAbstractVillager) this.getBukkitEntity()); // CraftBukkit add argument + + public EntityVillagerAbstract(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -233,7 +249,16 @@ + MerchantRecipe merchantrecipe = ((VillagerTrades.IMerchantRecipeOption) arraylist.remove(this.random.nextInt(arraylist.size()))).getOffer(this, this.random); + + if (merchantrecipe != null) { +- merchantrecipelist.add(merchantrecipe); ++ // CraftBukkit start ++ VillagerAcquireTradeEvent event = new VillagerAcquireTradeEvent((AbstractVillager) getBukkitEntity(), merchantrecipe.asBukkit()); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ if (!event.isCancelled()) { ++ merchantrecipelist.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); ++ } ++ // CraftBukkit end + ++j; + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/npc/EntityVillagerTrader.patch b/patch-remap/og/net/minecraft/world/entity/npc/EntityVillagerTrader.patch new file mode 100644 index 0000000000..13fa1f829d --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/npc/EntityVillagerTrader.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/world/entity/npc/EntityVillagerTrader.java ++++ b/net/minecraft/world/entity/npc/EntityVillagerTrader.java +@@ -47,6 +47,13 @@ + import net.minecraft.world.phys.Vec3D; + import org.apache.commons.lang3.tuple.Pair; + ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; ++import org.bukkit.entity.AbstractVillager; ++import org.bukkit.event.entity.VillagerAcquireTradeEvent; ++// CraftBukkit end ++ + public class EntityVillagerTrader extends EntityVillagerAbstract { + + private static final int NUMBER_OF_TRADE_OFFERS = 5; +@@ -56,6 +63,7 @@ + + public EntityVillagerTrader(EntityTypes entitytypes, World world) { + super(entitytypes, world); ++ this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader + } + + @Override +@@ -136,7 +144,16 @@ + MerchantRecipe merchantrecipe = villagertrades_imerchantrecipeoption.getOffer(this, this.random); + + if (merchantrecipe != null) { +- merchantrecipelist.add(merchantrecipe); ++ // CraftBukkit start ++ VillagerAcquireTradeEvent event = new VillagerAcquireTradeEvent((AbstractVillager) getBukkitEntity(), merchantrecipe.asBukkit()); ++ // Suppress during worldgen ++ if (this.valid) { ++ Bukkit.getPluginManager().callEvent(event); ++ } ++ if (!event.isCancelled()) { ++ merchantrecipelist.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); ++ } ++ // CraftBukkit end + } + + } diff --git a/patch-remap/og/net/minecraft/world/entity/npc/InventoryCarrier.patch b/patch-remap/og/net/minecraft/world/entity/npc/InventoryCarrier.patch new file mode 100644 index 0000000000..977c925820 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/npc/InventoryCarrier.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/entity/npc/InventoryCarrier.java ++++ b/net/minecraft/world/entity/npc/InventoryCarrier.java +@@ -23,6 +23,13 @@ + return; + } + ++ // CraftBukkit start ++ ItemStack remaining = new InventorySubcontainer(inventorysubcontainer).addItem(itemstack); ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(entityinsentient, entityitem, remaining.getCount(), false).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ + entityinsentient.onItemPickup(entityitem); + int i = itemstack.getCount(); + ItemStack itemstack1 = inventorysubcontainer.addItem(itemstack); diff --git a/patch-remap/og/net/minecraft/world/entity/npc/MobSpawnerTrader.patch b/patch-remap/og/net/minecraft/world/entity/npc/MobSpawnerTrader.patch new file mode 100644 index 0000000000..c19f83c2c8 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/npc/MobSpawnerTrader.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/world/entity/npc/MobSpawnerTrader.java ++++ b/net/minecraft/world/entity/npc/MobSpawnerTrader.java +@@ -110,7 +110,7 @@ + return false; + } + +- EntityVillagerTrader entityvillagertrader = (EntityVillagerTrader) EntityTypes.WANDERING_TRADER.spawn(worldserver, blockposition2, EnumMobSpawn.EVENT); ++ EntityVillagerTrader entityvillagertrader = (EntityVillagerTrader) EntityTypes.WANDERING_TRADER.spawn(worldserver, blockposition2, EnumMobSpawn.EVENT, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit + + if (entityvillagertrader != null) { + for (int i = 0; i < 2; ++i) { +@@ -118,7 +118,7 @@ + } + + this.serverLevelData.setWanderingTraderId(entityvillagertrader.getUUID()); +- entityvillagertrader.setDespawnDelay(48000); ++ // entityvillagertrader.setDespawnDelay(48000); // CraftBukkit - moved to EntityVillagerTrader constructor. This lets the value be modified by plugins on CreatureSpawnEvent + entityvillagertrader.setWanderTarget(blockposition1); + entityvillagertrader.restrictTo(blockposition1, 16); + return true; +@@ -133,7 +133,7 @@ + BlockPosition blockposition = this.findSpawnPositionNear(worldserver, entityvillagertrader.blockPosition(), i); + + if (blockposition != null) { +- EntityLlamaTrader entityllamatrader = (EntityLlamaTrader) EntityTypes.TRADER_LLAMA.spawn(worldserver, blockposition, EnumMobSpawn.EVENT); ++ EntityLlamaTrader entityllamatrader = (EntityLlamaTrader) EntityTypes.TRADER_LLAMA.spawn(worldserver, blockposition, EnumMobSpawn.EVENT, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit + + if (entityllamatrader != null) { + entityllamatrader.setLeashedTo(entityvillagertrader, true); diff --git a/patch-remap/og/net/minecraft/world/entity/player/EntityHuman.patch b/patch-remap/og/net/minecraft/world/entity/player/EntityHuman.patch new file mode 100644 index 0000000000..2371941fe2 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/player/EntityHuman.patch @@ -0,0 +1,513 @@ +--- a/net/minecraft/world/entity/player/EntityHuman.java ++++ b/net/minecraft/world/entity/player/EntityHuman.java +@@ -112,6 +112,20 @@ + import net.minecraft.world.scores.ScoreboardTeam; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.nbt.NBTBase; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.util.CraftVector; ++import org.bukkit.entity.Item; ++import org.bukkit.entity.Player; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.entity.EntityExhaustionEvent; ++import org.bukkit.event.player.PlayerDropItemEvent; ++import org.bukkit.event.player.PlayerVelocityEvent; ++// CraftBukkit end ++ + public abstract class EntityHuman extends EntityLiving { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -127,7 +141,8 @@ + public static final float SWIMMING_BB_HEIGHT = 0.6F; + public static final float DEFAULT_EYE_HEIGHT = 1.62F; + public static final EntitySize STANDING_DIMENSIONS = EntitySize.scalable(0.6F, 1.8F); +- private static final Map POSES = ImmutableMap.builder().put(EntityPose.STANDING, EntityHuman.STANDING_DIMENSIONS).put(EntityPose.SLEEPING, EntityHuman.SLEEPING_DIMENSIONS).put(EntityPose.FALL_FLYING, EntitySize.scalable(0.6F, 0.6F)).put(EntityPose.SWIMMING, EntitySize.scalable(0.6F, 0.6F)).put(EntityPose.SPIN_ATTACK, EntitySize.scalable(0.6F, 0.6F)).put(EntityPose.CROUCHING, EntitySize.scalable(0.6F, 1.5F)).put(EntityPose.DYING, EntitySize.fixed(0.2F, 0.2F)).build(); ++ // CraftBukkit - decompile error ++ private static final Map POSES = ImmutableMap.builder().put(EntityPose.STANDING, EntityHuman.STANDING_DIMENSIONS).put(EntityPose.SLEEPING, EntityHuman.SLEEPING_DIMENSIONS).put(EntityPose.FALL_FLYING, EntitySize.scalable(0.6F, 0.6F)).put(EntityPose.SWIMMING, EntitySize.scalable(0.6F, 0.6F)).put(EntityPose.SPIN_ATTACK, EntitySize.scalable(0.6F, 0.6F)).put(EntityPose.CROUCHING, EntitySize.scalable(0.6F, 1.5F)).put(EntityPose.DYING, EntitySize.fixed(0.2F, 0.2F)).build(); + private static final DataWatcherObject DATA_PLAYER_ABSORPTION_ID = DataWatcher.defineId(EntityHuman.class, DataWatcherRegistry.FLOAT); + private static final DataWatcherObject DATA_SCORE_ID = DataWatcher.defineId(EntityHuman.class, DataWatcherRegistry.INT); + protected static final DataWatcherObject DATA_PLAYER_MODE_CUSTOMISATION = DataWatcher.defineId(EntityHuman.class, DataWatcherRegistry.BYTE); +@@ -136,10 +151,10 @@ + protected static final DataWatcherObject DATA_SHOULDER_RIGHT = DataWatcher.defineId(EntityHuman.class, DataWatcherRegistry.COMPOUND_TAG); + private long timeEntitySatOnShoulder; + private final PlayerInventory inventory = new PlayerInventory(this); +- protected InventoryEnderChest enderChestInventory = new InventoryEnderChest(); ++ protected InventoryEnderChest enderChestInventory = new InventoryEnderChest(this); // CraftBukkit - add "this" to constructor + public final ContainerPlayer inventoryMenu; + public Container containerMenu; +- protected FoodMetaData foodData = new FoodMetaData(); ++ protected FoodMetaData foodData = new FoodMetaData(this); // CraftBukkit - add "this" to constructor + protected int jumpTriggerTime; + public float oBob; + public float bob; +@@ -168,6 +183,16 @@ + public EntityFishingHook fishing; + protected float hurtDir; + ++ // CraftBukkit start ++ public boolean fauxSleeping; ++ public int oldLevel = -1; ++ ++ @Override ++ public CraftHumanEntity getBukkitEntity() { ++ return (CraftHumanEntity) super.getBukkitEntity(); ++ } ++ // CraftBukkit end ++ + public EntityHuman(World world, BlockPosition blockposition, float f, GameProfile gameprofile) { + super(EntityTypes.PLAYER, world); + this.lastItemInMainHand = ItemStack.EMPTY; +@@ -312,7 +337,7 @@ + ItemStack itemstack = this.getItemBySlot(EnumItemSlot.HEAD); + + if (itemstack.is(Items.TURTLE_HELMET) && !this.isEyeInFluid(TagsFluid.WATER)) { +- this.addEffect(new MobEffect(MobEffects.WATER_BREATHING, 200, 0, false, false, true)); ++ this.addEffect(new MobEffect(MobEffects.WATER_BREATHING, 200, 0, false, false, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TURTLE_HELMET); // CraftBukkit + } + + } +@@ -482,8 +507,14 @@ + public void rideTick() { + if (!this.level().isClientSide && this.wantsToStopRiding() && this.isPassenger()) { + this.stopRiding(); +- this.setShiftKeyDown(false); +- } else { ++ // CraftBukkit start - SPIGOT-7316: no longer passenger, dismount and return ++ if (!this.isPassenger()) { ++ this.setShiftKeyDown(false); ++ return; ++ } ++ } ++ { ++ // CraftBukkit end + super.rideTick(); + this.oBob = this.bob; + this.bob = 0.0F; +@@ -505,7 +536,8 @@ + + if (this.level().getDifficulty() == EnumDifficulty.PEACEFUL && this.level().getGameRules().getBoolean(GameRules.RULE_NATURAL_REGENERATION)) { + if (this.getHealth() < this.getMaxHealth() && this.tickCount % 20 == 0) { +- this.heal(1.0F); ++ // CraftBukkit - added regain reason of "REGEN" for filtering purposes. ++ this.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.REGEN); + } + + if (this.foodData.needsFood() && this.tickCount % 10 == 0) { +@@ -665,6 +697,13 @@ + + @Nullable + public EntityItem drop(ItemStack itemstack, boolean flag, boolean flag1) { ++ // CraftBukkit start - SPIGOT-2942: Add boolean to call event ++ return drop(itemstack, flag, flag1, true); ++ } ++ ++ @Nullable ++ public EntityItem drop(ItemStack itemstack, boolean flag, boolean flag1, boolean callEvent) { ++ // CraftBukkit end + if (itemstack.isEmpty()) { + return null; + } else { +@@ -699,6 +738,33 @@ + entityitem.setDeltaMovement((double) (-f3 * f2 * 0.3F) + Math.cos((double) f5) * (double) f6, (double) (-f1 * 0.3F + 0.1F + (this.random.nextFloat() - this.random.nextFloat()) * 0.1F), (double) (f4 * f2 * 0.3F) + Math.sin((double) f5) * (double) f6); + } + ++ // CraftBukkit start - fire PlayerDropItemEvent ++ if (!callEvent) { // SPIGOT-2942: Add boolean to call event ++ return entityitem; ++ } ++ Player player = (Player) this.getBukkitEntity(); ++ Item drop = (Item) entityitem.getBukkitEntity(); ++ ++ PlayerDropItemEvent event = new PlayerDropItemEvent(player, drop); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ org.bukkit.inventory.ItemStack cur = player.getInventory().getItemInHand(); ++ if (flag1 && (cur == null || cur.getAmount() == 0)) { ++ // The complete stack was dropped ++ player.getInventory().setItemInHand(drop.getItemStack()); ++ } else if (flag1 && cur.isSimilar(drop.getItemStack()) && cur.getAmount() < cur.getMaxStackSize() && drop.getItemStack().getAmount() == 1) { ++ // Only one item is dropped ++ cur.setAmount(cur.getAmount() + 1); ++ player.getInventory().setItemInHand(cur); ++ } else { ++ // Fallback ++ player.getInventory().addItem(drop.getItemStack()); ++ } ++ return null; ++ } ++ // CraftBukkit end ++ + return entityitem; + } + } +@@ -789,7 +855,7 @@ + } + + if (nbttagcompound.contains("LastDeathLocation", 10)) { +- DataResult dataresult = GlobalPos.CODEC.parse(DynamicOpsNBT.INSTANCE, nbttagcompound.get("LastDeathLocation")); ++ DataResult dataresult = GlobalPos.CODEC.parse(DynamicOpsNBT.INSTANCE, nbttagcompound.get("LastDeathLocation")); // CraftBukkit - decompile error + Logger logger = EntityHuman.LOGGER; + + Objects.requireNonNull(logger); +@@ -822,7 +888,7 @@ + } + + this.getLastDeathLocation().flatMap((globalpos) -> { +- DataResult dataresult = GlobalPos.CODEC.encodeStart(DynamicOpsNBT.INSTANCE, globalpos); ++ DataResult dataresult = GlobalPos.CODEC.encodeStart(DynamicOpsNBT.INSTANCE, globalpos); // CraftBukkit - decompile error + Logger logger = EntityHuman.LOGGER; + + Objects.requireNonNull(logger); +@@ -849,12 +915,12 @@ + return false; + } else { + if (!this.level().isClientSide) { +- this.removeEntitiesOnShoulder(); ++ // this.removeEntitiesOnShoulder(); // CraftBukkit - moved down + } + + if (damagesource.scalesWithDifficulty()) { + if (this.level().getDifficulty() == EnumDifficulty.PEACEFUL) { +- f = 0.0F; ++ return false; // CraftBukkit - f = 0.0f -> return false + } + + if (this.level().getDifficulty() == EnumDifficulty.EASY) { +@@ -866,7 +932,13 @@ + } + } + +- return f == 0.0F ? false : super.hurt(damagesource, f); ++ // CraftBukkit start - Don't filter out 0 damage ++ boolean damaged = super.hurt(damagesource, f); ++ if (damaged) { ++ this.removeEntitiesOnShoulder(); ++ } ++ return damaged; ++ // CraftBukkit end + } + } + } +@@ -886,10 +958,29 @@ + } + + public boolean canHarmPlayer(EntityHuman entityhuman) { +- ScoreboardTeam scoreboardteam = this.getTeam(); +- ScoreboardTeam scoreboardteam1 = entityhuman.getTeam(); ++ // CraftBukkit start - Change to check OTHER player's scoreboard team according to API ++ // To summarize this method's logic, it's "Can parameter hurt this" ++ org.bukkit.scoreboard.Team team; ++ if (entityhuman instanceof EntityPlayer) { ++ EntityPlayer thatPlayer = (EntityPlayer) entityhuman; ++ team = thatPlayer.getBukkitEntity().getScoreboard().getPlayerTeam(thatPlayer.getBukkitEntity()); ++ if (team == null || team.allowFriendlyFire()) { ++ return true; ++ } ++ } else { ++ // This should never be called, but is implemented anyway ++ org.bukkit.OfflinePlayer thisPlayer = entityhuman.level().getCraftServer().getOfflinePlayer(entityhuman.getScoreboardName()); ++ team = entityhuman.level().getCraftServer().getScoreboardManager().getMainScoreboard().getPlayerTeam(thisPlayer); ++ if (team == null || team.allowFriendlyFire()) { ++ return true; ++ } ++ } + +- return scoreboardteam == null ? true : (!scoreboardteam.isAlliedTo(scoreboardteam1) ? true : scoreboardteam.isAllowFriendlyFire()); ++ if (this instanceof EntityPlayer) { ++ return !team.hasPlayer(((EntityPlayer) this).getBukkitEntity()); ++ } ++ return !team.hasPlayer(this.level().getCraftServer().getOfflinePlayer(this.getScoreboardName())); ++ // CraftBukkit end + } + + @Override +@@ -931,8 +1022,13 @@ + } + } + ++ // CraftBukkit start + @Override +- protected void actuallyHurt(DamageSource damagesource, float f) { ++ protected boolean damageEntity0(DamageSource damagesource, float f) { // void -> boolean ++ if (true) { ++ return super.damageEntity0(damagesource, f); ++ } ++ // CraftBukkit end + if (!this.isInvulnerableTo(damagesource)) { + f = this.getDamageAfterArmorAbsorb(damagesource, f); + f = this.getDamageAfterMagicAbsorb(damagesource, f); +@@ -947,7 +1043,7 @@ + } + + if (f != 0.0F) { +- this.causeFoodExhaustion(damagesource.getFoodExhaustion()); ++ this.causeFoodExhaustion(damagesource.getFoodExhaustion(), EntityExhaustionEvent.ExhaustionReason.DAMAGED); // CraftBukkit - EntityExhaustionEvent + this.getCombatTracker().recordDamage(damagesource, f); + this.setHealth(this.getHealth() - f); + if (f < 3.4028235E37F) { +@@ -957,6 +1053,7 @@ + this.gameEvent(GameEvent.ENTITY_DAMAGE); + } + } ++ return false; // CraftBukkit + } + + @Override +@@ -1121,7 +1218,7 @@ + + f *= 0.2F + f2 * f2 * 0.8F; + f1 *= f2; +- this.resetAttackStrengthTicker(); ++ // this.resetAttackCooldown(); // CraftBukkit - Moved to EntityLiving to reset the cooldown after the damage is dealt + if (f > 0.0F || f1 > 0.0F) { + boolean flag = f2 > 0.9F; + boolean flag1 = false; +@@ -1160,8 +1257,15 @@ + if (entity instanceof EntityLiving) { + f3 = ((EntityLiving) entity).getHealth(); + if (j > 0 && !entity.isOnFire()) { +- flag4 = true; +- entity.setSecondsOnFire(1); ++ // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), 1); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ flag4 = true; ++ entity.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + } + +@@ -1189,8 +1293,11 @@ + EntityLiving entityliving = (EntityLiving) iterator.next(); + + if (entityliving != this && entityliving != entity && !this.isAlliedTo((Entity) entityliving) && (!(entityliving instanceof EntityArmorStand) || !((EntityArmorStand) entityliving).isMarker()) && this.distanceToSqr((Entity) entityliving) < 9.0D) { ++ // CraftBukkit start - Only apply knockback if the damage hits ++ if (entityliving.hurt(this.damageSources().playerAttack(this).sweep(), f4)) { + entityliving.knockback(0.4000000059604645D, (double) MathHelper.sin(this.getYRot() * 0.017453292F), (double) (-MathHelper.cos(this.getYRot() * 0.017453292F))); +- entityliving.hurt(this.damageSources().playerAttack(this), f4); ++ } ++ // CraftBukkit end + } + } + +@@ -1199,9 +1306,26 @@ + } + + if (entity instanceof EntityPlayer && entity.hurtMarked) { ++ // CraftBukkit start - Add Velocity Event ++ boolean cancelled = false; ++ Player player = (Player) entity.getBukkitEntity(); ++ org.bukkit.util.Vector velocity = CraftVector.toBukkit(vec3d); ++ ++ PlayerVelocityEvent event = new PlayerVelocityEvent(player, velocity.clone()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ cancelled = true; ++ } else if (!velocity.equals(event.getVelocity())) { ++ player.setVelocity(event.getVelocity()); ++ } ++ ++ if (!cancelled) { + ((EntityPlayer) entity).connection.send(new PacketPlayOutEntityVelocity(entity)); + entity.hurtMarked = false; + entity.setDeltaMovement(vec3d); ++ } ++ // CraftBukkit end + } + + if (flag2) { +@@ -1246,7 +1370,14 @@ + + this.awardStat(StatisticList.DAMAGE_DEALT, Math.round(f5 * 10.0F)); + if (j > 0) { +- entity.setSecondsOnFire(j * 4); ++ // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), j * 4); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ entity.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + + if (this.level() instanceof WorldServer && f5 > 2.0F) { +@@ -1256,12 +1387,17 @@ + } + } + +- this.causeFoodExhaustion(0.1F); ++ this.causeFoodExhaustion(0.1F, EntityExhaustionEvent.ExhaustionReason.ATTACK); // CraftBukkit - EntityExhaustionEvent + } else { + this.level().playSound((EntityHuman) null, this.getX(), this.getY(), this.getZ(), SoundEffects.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F); + if (flag4) { + entity.clearFire(); + } ++ // CraftBukkit start - resync on cancelled event ++ if (this instanceof EntityPlayer) { ++ ((EntityPlayer) this).getBukkitEntity().updateInventory(); ++ } ++ // CraftBukkit end + } + } + +@@ -1338,6 +1474,12 @@ + } + + public Either startSleepInBed(BlockPosition blockposition) { ++ // CraftBukkit start ++ return this.startSleepInBed(blockposition, false); ++ } ++ ++ public Either startSleepInBed(BlockPosition blockposition, boolean force) { ++ // CraftBukkit end + this.startSleeping(blockposition); + this.sleepCounter = 0; + return Either.right(Unit.INSTANCE); +@@ -1425,9 +1567,9 @@ + super.jumpFromGround(); + this.awardStat(StatisticList.JUMP); + if (this.isSprinting()) { +- this.causeFoodExhaustion(0.2F); ++ this.causeFoodExhaustion(0.2F, EntityExhaustionEvent.ExhaustionReason.JUMP_SPRINT); // CraftBukkit - EntityExhaustionEvent + } else { +- this.causeFoodExhaustion(0.05F); ++ this.causeFoodExhaustion(0.05F, EntityExhaustionEvent.ExhaustionReason.JUMP); // CraftBukkit - EntityExhaustionEvent + } + + } +@@ -1454,7 +1596,11 @@ + + this.setDeltaMovement(vec3d2.x, d0 * 0.6D, vec3d2.z); + this.resetFallDistance(); +- this.setSharedFlag(7, false); ++ // CraftBukkit start ++ if (getSharedFlag(7) && !org.bukkit.craftbukkit.event.CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) { ++ this.setSharedFlag(7, false); ++ } ++ // CraftBukkit end + } else { + super.travel(vec3d); + } +@@ -1507,12 +1653,24 @@ + } + + public void startFallFlying() { +- this.setSharedFlag(7, true); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callToggleGlideEvent(this, true).isCancelled()) { ++ this.setSharedFlag(7, true); ++ } else { ++ // SPIGOT-5542: must toggle like below ++ this.setSharedFlag(7, true); ++ this.setSharedFlag(7, false); ++ } ++ // CraftBukkit end + } + + public void stopFallFlying() { ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) { + this.setSharedFlag(7, true); + this.setSharedFlag(7, false); ++ } ++ // CraftBukkit end + } + + @Override +@@ -1626,10 +1784,21 @@ + return this.experienceLevel >= 30 ? 112 + (this.experienceLevel - 30) * 9 : (this.experienceLevel >= 15 ? 37 + (this.experienceLevel - 15) * 5 : 7 + this.experienceLevel * 2); + } + ++ // CraftBukkit start + public void causeFoodExhaustion(float f) { ++ this.causeFoodExhaustion(f, EntityExhaustionEvent.ExhaustionReason.UNKNOWN); ++ } ++ ++ public void causeFoodExhaustion(float f, EntityExhaustionEvent.ExhaustionReason reason) { ++ // CraftBukkit end + if (!this.abilities.invulnerable) { + if (!this.level().isClientSide) { +- this.foodData.addExhaustion(f); ++ // CraftBukkit start ++ EntityExhaustionEvent event = CraftEventFactory.callPlayerExhaustionEvent(this, reason, f); ++ if (!event.isCancelled()) { ++ this.foodData.addExhaustion(event.getExhaustion()); ++ } ++ // CraftBukkit end + } + + } +@@ -1715,13 +1884,20 @@ + + @Override + public void setItemSlot(EnumItemSlot enumitemslot, ItemStack itemstack) { ++ // CraftBukkit start ++ setItemSlot(enumitemslot, itemstack, false); ++ } ++ ++ @Override ++ public void setItemSlot(EnumItemSlot enumitemslot, ItemStack itemstack, boolean silent) { ++ // CraftBukkit end + this.verifyEquippedItem(itemstack); + if (enumitemslot == EnumItemSlot.MAINHAND) { +- this.onEquipItem(enumitemslot, (ItemStack) this.inventory.items.set(this.inventory.selected, itemstack), itemstack); ++ this.onEquipItem(enumitemslot, (ItemStack) this.inventory.items.set(this.inventory.selected, itemstack), itemstack, silent); // CraftBukkit + } else if (enumitemslot == EnumItemSlot.OFFHAND) { +- this.onEquipItem(enumitemslot, (ItemStack) this.inventory.offhand.set(0, itemstack), itemstack); ++ this.onEquipItem(enumitemslot, (ItemStack) this.inventory.offhand.set(0, itemstack), itemstack, silent); // CraftBukkit + } else if (enumitemslot.getType() == EnumItemSlot.Function.ARMOR) { +- this.onEquipItem(enumitemslot, (ItemStack) this.inventory.armor.set(enumitemslot.getIndex(), itemstack), itemstack); ++ this.onEquipItem(enumitemslot, (ItemStack) this.inventory.armor.set(enumitemslot.getIndex(), itemstack), itemstack, silent); // CraftBukkit + } + + } +@@ -1760,26 +1936,31 @@ + + protected void removeEntitiesOnShoulder() { + if (this.timeEntitySatOnShoulder + 20L < this.level().getGameTime()) { +- this.respawnEntityOnShoulder(this.getShoulderEntityLeft()); +- this.setShoulderEntityLeft(new NBTTagCompound()); +- this.respawnEntityOnShoulder(this.getShoulderEntityRight()); +- this.setShoulderEntityRight(new NBTTagCompound()); ++ // CraftBukkit start ++ if (this.respawnEntityOnShoulder(this.getShoulderEntityLeft())) { ++ this.setShoulderEntityLeft(new NBTTagCompound()); ++ } ++ if (this.respawnEntityOnShoulder(this.getShoulderEntityRight())) { ++ this.setShoulderEntityRight(new NBTTagCompound()); ++ } ++ // CraftBukkit end + } + + } + +- private void respawnEntityOnShoulder(NBTTagCompound nbttagcompound) { ++ private boolean respawnEntityOnShoulder(NBTTagCompound nbttagcompound) { // CraftBukkit void->boolean + if (!this.level().isClientSide && !nbttagcompound.isEmpty()) { +- EntityTypes.create(nbttagcompound, this.level()).ifPresent((entity) -> { ++ return EntityTypes.create(nbttagcompound, this.level()).map((entity) -> { // CraftBukkit + if (entity instanceof EntityTameableAnimal) { + ((EntityTameableAnimal) entity).setOwnerUUID(this.uuid); + } + + entity.setPos(this.getX(), this.getY() + 0.699999988079071D, this.getZ()); +- ((WorldServer) this.level()).addWithUUID(entity); +- }); ++ return ((WorldServer) this.level()).addWithUUID(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit ++ }).orElse(true); // CraftBukkit + } + ++ return true; // CraftBukkit + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/entity/player/PlayerInventory.patch b/patch-remap/og/net/minecraft/world/entity/player/PlayerInventory.patch new file mode 100644 index 0000000000..b579293e22 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/player/PlayerInventory.patch @@ -0,0 +1,100 @@ +--- a/net/minecraft/world/entity/player/PlayerInventory.java ++++ b/net/minecraft/world/entity/player/PlayerInventory.java +@@ -26,6 +26,13 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start ++import java.util.ArrayList; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class PlayerInventory implements IInventory, INamableTileEntity { + + public static final int POP_TIME_DURATION = 5; +@@ -43,6 +50,54 @@ + public final EntityHuman player; + private int timesChanged; + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ List combined = new ArrayList(items.size() + armor.size() + offhand.size()); ++ for (List sub : this.compartments) { ++ combined.addAll(sub); ++ } ++ ++ return combined; ++ } ++ ++ public List getArmorContents() { ++ return this.armor; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return this.player.getBukkitEntity(); ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return player.getBukkitEntity().getLocation(); ++ } ++ // CraftBukkit end ++ + public PlayerInventory(EntityHuman entityhuman) { + this.items = NonNullList.withSize(36, ItemStack.EMPTY); + this.armor = NonNullList.withSize(4, ItemStack.EMPTY); +@@ -63,6 +118,28 @@ + return !itemstack.isEmpty() && ItemStack.isSameItemSameTags(itemstack, itemstack1) && itemstack.isStackable() && itemstack.getCount() < itemstack.getMaxStackSize() && itemstack.getCount() < this.getMaxStackSize(); + } + ++ // CraftBukkit start - Watch method above! :D ++ public int canHold(ItemStack itemstack) { ++ int remains = itemstack.getCount(); ++ for (int i = 0; i < this.items.size(); ++i) { ++ ItemStack itemstack1 = this.getItem(i); ++ if (itemstack1.isEmpty()) return itemstack.getCount(); ++ ++ if (this.hasRemainingSpaceForItem(itemstack1, itemstack)) { ++ remains -= (itemstack1.getMaxStackSize() < this.getMaxStackSize() ? itemstack1.getMaxStackSize() : this.getMaxStackSize()) - itemstack1.getCount(); ++ } ++ if (remains <= 0) return itemstack.getCount(); ++ } ++ ItemStack offhandItemStack = this.getItem(this.items.size() + this.armor.size()); ++ if (this.hasRemainingSpaceForItem(offhandItemStack, itemstack)) { ++ remains -= (offhandItemStack.getMaxStackSize() < this.getMaxStackSize() ? offhandItemStack.getMaxStackSize() : this.getMaxStackSize()) - offhandItemStack.getCount(); ++ } ++ if (remains <= 0) return itemstack.getCount(); ++ ++ return itemstack.getCount() - remains; ++ } ++ // CraftBukkit end ++ + public int getFreeSlot() { + for (int i = 0; i < this.items.size(); ++i) { + if (((ItemStack) this.items.get(i)).isEmpty()) { diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntityArrow.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntityArrow.patch new file mode 100644 index 0000000000..eef2007b80 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntityArrow.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/world/entity/projectile/EntityArrow.java ++++ b/net/minecraft/world/entity/projectile/EntityArrow.java +@@ -47,6 +47,12 @@ + import net.minecraft.world.phys.Vec3D; + import net.minecraft.world.phys.shapes.VoxelShape; + ++// CraftBukkit start ++import net.minecraft.world.entity.item.EntityItem; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.player.PlayerPickupArrowEvent; ++// CraftBukkit end ++ + public abstract class EntityArrow extends IProjectile { + + private static final double ARROW_BASE_DAMAGE = 2.0D; +@@ -219,7 +225,7 @@ + } + + if (object != null && !flag) { +- this.onHit((MovingObjectPosition) object); ++ this.preOnHit((MovingObjectPosition) object); // CraftBukkit - projectile hit event + this.hasImpulse = true; + } + +@@ -367,7 +373,13 @@ + boolean flag1 = entity.getType().is(TagsEntity.DEFLECTS_ARROWS); + + if (this.isOnFire() && !flag && !flag1) { +- entity.setSecondsOnFire(5); ++ // CraftBukkit start ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), 5); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ if (!combustEvent.isCancelled()) { ++ entity.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + } + + if (entity.hurt(damagesource, (float) i)) { +@@ -545,7 +557,22 @@ + @Override + public void playerTouch(EntityHuman entityhuman) { + if (!this.level().isClientSide && (this.inGround || this.isNoPhysics()) && this.shakeTime <= 0) { +- if (this.tryPickup(entityhuman)) { ++ // CraftBukkit start ++ ItemStack itemstack = this.getPickupItem(); ++ if (this.pickup == PickupStatus.ALLOWED && !itemstack.isEmpty() && entityhuman.getInventory().canHold(itemstack) > 0) { ++ EntityItem item = new EntityItem(this.level(), this.getX(), this.getY(), this.getZ(), itemstack); ++ PlayerPickupArrowEvent event = new PlayerPickupArrowEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), new org.bukkit.craftbukkit.entity.CraftItem(this.level().getCraftServer(), item), (org.bukkit.entity.AbstractArrow) this.getBukkitEntity()); ++ // event.setCancelled(!entityhuman.canPickUpLoot); TODO ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ itemstack = item.getItem(); ++ } ++ ++ if ((this.pickup == EntityArrow.PickupStatus.ALLOWED && entityhuman.getInventory().add(itemstack)) || (this.pickup == EntityArrow.PickupStatus.CREATIVE_ONLY && entityhuman.getAbilities().instabuild)) { ++ // CraftBukkit end + entityhuman.take(this, 1); + this.discard(); + } diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntityEgg.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntityEgg.patch new file mode 100644 index 0000000000..ba9188ddf6 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntityEgg.patch @@ -0,0 +1,71 @@ +--- a/net/minecraft/world/entity/projectile/EntityEgg.java ++++ b/net/minecraft/world/entity/projectile/EntityEgg.java +@@ -11,6 +11,15 @@ + import net.minecraft.world.phys.MovingObjectPosition; + import net.minecraft.world.phys.MovingObjectPositionEntity; + ++// CraftBukkit start ++import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.world.entity.Entity; ++import org.bukkit.entity.Ageable; ++import org.bukkit.entity.EntityType; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerEggThrowEvent; ++// CraftBukkit end ++ + public class EntityEgg extends EntityProjectileThrowable { + + public EntityEgg(EntityTypes entitytypes, World world) { +@@ -47,20 +56,47 @@ + protected void onHit(MovingObjectPosition movingobjectposition) { + super.onHit(movingobjectposition); + if (!this.level().isClientSide) { +- if (this.random.nextInt(8) == 0) { ++ // CraftBukkit start ++ boolean hatching = this.random.nextInt(8) == 0; ++ if (true) { ++ // CraftBukkit end + byte b0 = 1; + + if (this.random.nextInt(32) == 0) { + b0 = 4; + } + ++ // CraftBukkit start ++ EntityType hatchingType = EntityType.CHICKEN; ++ ++ Entity shooter = this.getOwner(); ++ if (!hatching) { ++ b0 = 0; ++ } ++ if (shooter instanceof EntityPlayer) { ++ PlayerEggThrowEvent event = new PlayerEggThrowEvent((Player) shooter.getBukkitEntity(), (org.bukkit.entity.Egg) this.getBukkitEntity(), hatching, b0, hatchingType); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ b0 = event.getNumHatches(); ++ hatching = event.isHatching(); ++ hatchingType = event.getHatchingType(); ++ // If hatching is set to false, ensure child count is 0 ++ if (!hatching) { ++ b0 = 0; ++ } ++ } ++ // CraftBukkit end ++ + for (int i = 0; i < b0; ++i) { +- EntityChicken entitychicken = (EntityChicken) EntityTypes.CHICKEN.create(this.level()); ++ Entity entitychicken = this.level().getWorld().makeEntity(new org.bukkit.Location(this.level().getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F), hatchingType.getEntityClass()); // CraftBukkit + + if (entitychicken != null) { +- entitychicken.setAge(-24000); +- entitychicken.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); +- this.level().addFreshEntity(entitychicken); ++ // CraftBukkit start ++ if (entitychicken.getBukkitEntity() instanceof Ageable) { ++ ((Ageable) entitychicken.getBukkitEntity()).setBaby(); ++ } ++ this.level().addFreshEntity(entitychicken, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntityEnderPearl.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntityEnderPearl.patch new file mode 100644 index 0000000000..cd97343db7 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntityEnderPearl.patch @@ -0,0 +1,75 @@ +--- a/net/minecraft/world/entity/projectile/EntityEnderPearl.java ++++ b/net/minecraft/world/entity/projectile/EntityEnderPearl.java +@@ -18,6 +18,13 @@ + import net.minecraft.world.phys.MovingObjectPosition; + import net.minecraft.world.phys.MovingObjectPositionEntity; + ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++// CraftBukkit end ++ + public class EntityEnderPearl extends EntityProjectileThrowable { + + public EntityEnderPearl(EntityTypes entitytypes, World world) { +@@ -54,23 +61,36 @@ + EntityPlayer entityplayer = (EntityPlayer) entity; + + if (entityplayer.connection.isAcceptingMessages() && entityplayer.level() == this.level() && !entityplayer.isSleeping()) { +- if (this.random.nextFloat() < 0.05F && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { +- EntityEndermite entityendermite = (EntityEndermite) EntityTypes.ENDERMITE.create(this.level()); ++ // CraftBukkit start - Fire PlayerTeleportEvent ++ org.bukkit.craftbukkit.entity.CraftPlayer player = entityplayer.getBukkitEntity(); ++ org.bukkit.Location location = getBukkitEntity().getLocation(); ++ location.setPitch(player.getLocation().getPitch()); ++ location.setYaw(player.getLocation().getYaw()); + +- if (entityendermite != null) { +- entityendermite.moveTo(entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot()); +- this.level().addFreshEntity(entityendermite); ++ PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.ENDER_PEARL); ++ Bukkit.getPluginManager().callEvent(teleEvent); ++ ++ if (!teleEvent.isCancelled() && entityplayer.connection.isAcceptingMessages()) { ++ if (this.random.nextFloat() < 0.05F && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { ++ EntityEndermite entityendermite = (EntityEndermite) EntityTypes.ENDERMITE.create(this.level()); ++ ++ if (entityendermite != null) { ++ entityendermite.moveTo(entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot()); ++ this.level().addFreshEntity(entityendermite, CreatureSpawnEvent.SpawnReason.ENDER_PEARL); ++ } + } +- } + +- if (entity.isPassenger()) { +- entityplayer.dismountTo(this.getX(), this.getY(), this.getZ()); +- } else { +- entity.teleportTo(this.getX(), this.getY(), this.getZ()); +- } ++ if (entity.isPassenger()) { ++ entity.stopRiding(); ++ } + +- entity.resetFallDistance(); +- entity.hurt(this.damageSources().fall(), 5.0F); ++ entityplayer.connection.teleport(teleEvent.getTo()); ++ entity.resetFallDistance(); ++ CraftEventFactory.entityDamage = this; ++ entity.hurt(this.damageSources().fall(), 5.0F); ++ CraftEventFactory.entityDamage = null; ++ } ++ // CraftBukkit end + this.level().playSound((EntityHuman) null, this.getX(), this.getY(), this.getZ(), SoundEffects.PLAYER_TELEPORT, SoundCategory.PLAYERS); + } + } else if (entity != null) { +@@ -100,7 +120,7 @@ + public Entity changeDimension(WorldServer worldserver) { + Entity entity = this.getOwner(); + +- if (entity != null && entity.level().dimension() != worldserver.dimension()) { ++ if (entity != null && worldserver != null && entity.level().dimension() != worldserver.dimension()) { // CraftBukkit - SPIGOT-6113 + this.setOwner((Entity) null); + } + diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntityEnderSignal.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntityEnderSignal.patch new file mode 100644 index 0000000000..63b12f9cc6 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntityEnderSignal.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/entity/projectile/EntityEnderSignal.java ++++ b/net/minecraft/world/entity/projectile/EntityEnderSignal.java +@@ -35,7 +35,7 @@ + } + + public void setItem(ItemStack itemstack) { +- if (!itemstack.is(Items.ENDER_EYE) || itemstack.hasTag()) { ++ if (true || !itemstack.is(Items.ENDER_EYE) || itemstack.hasTag()) { // CraftBukkit - always allow item changing + this.getEntityData().set(EntityEnderSignal.DATA_ITEM_STACK, itemstack.copyWithCount(1)); + } + +@@ -177,7 +177,7 @@ + public void readAdditionalSaveData(NBTTagCompound nbttagcompound) { + ItemStack itemstack = ItemStack.of(nbttagcompound.getCompound("Item")); + +- this.setItem(itemstack); ++ if (!itemstack.isEmpty()) this.setItem(itemstack); // CraftBukkit - SPIGOT-6103 summon, see also SPIGOT-5474 + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntityEvokerFangs.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntityEvokerFangs.patch new file mode 100644 index 0000000000..89000e6e43 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntityEvokerFangs.patch @@ -0,0 +1,12 @@ +--- a/net/minecraft/world/entity/projectile/EntityEvokerFangs.java ++++ b/net/minecraft/world/entity/projectile/EntityEvokerFangs.java +@@ -129,7 +129,9 @@ + + if (entityliving.isAlive() && !entityliving.isInvulnerable() && entityliving != entityliving1) { + if (entityliving1 == null) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = this; // CraftBukkit + entityliving.hurt(this.damageSources().magic(), 6.0F); ++ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = null; // CraftBukkit + } else { + if (entityliving1.isAlliedTo((Entity) entityliving)) { + return; diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntityFireball.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntityFireball.patch new file mode 100644 index 0000000000..7642d2b0c7 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntityFireball.patch @@ -0,0 +1,58 @@ +--- a/net/minecraft/world/entity/projectile/EntityFireball.java ++++ b/net/minecraft/world/entity/projectile/EntityFireball.java +@@ -17,11 +17,15 @@ + import net.minecraft.world.phys.MovingObjectPosition; + import net.minecraft.world.phys.Vec3D; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public abstract class EntityFireball extends IProjectile { + + public double xPower; + public double yPower; + public double zPower; ++ public float bukkitYield = 1; // CraftBukkit ++ public boolean isIncendiary = true; // CraftBukkit + + protected EntityFireball(EntityTypes entitytypes, World world) { + super(entitytypes, world); +@@ -36,6 +40,12 @@ + this(entitytypes, world); + this.moveTo(d0, d1, d2, this.getYRot(), this.getXRot()); + this.reapplyPosition(); ++ // CraftBukkit start - Added setDirection method ++ this.setDirection(d3, d4, d5); ++ } ++ ++ public void setDirection(double d3, double d4, double d5) { ++ // CraftBukkit end + double d6 = Math.sqrt(d3 * d3 + d4 * d4 + d5 * d5); + + if (d6 != 0.0D) { +@@ -86,7 +96,13 @@ + MovingObjectPosition movingobjectposition = ProjectileHelper.getHitResultOnMoveVector(this, this::canHitEntity, this.getClipType()); + + if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) { +- this.onHit(movingobjectposition); ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event ++ ++ // CraftBukkit start - Fire ProjectileHitEvent ++ if (this.isRemoved()) { ++ CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); ++ } ++ // CraftBukkit end + } + + this.checkInsideBlocks(); +@@ -184,6 +200,11 @@ + + if (entity != null) { + if (!this.level().isClientSide) { ++ // CraftBukkit start ++ if (CraftEventFactory.handleNonLivingEntityDamageEvent(this, damagesource, f, false)) { ++ return false; ++ } ++ // CraftBukkit end + Vec3D vec3d = entity.getLookAngle(); + + this.setDeltaMovement(vec3d); diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntityFireballFireball.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntityFireballFireball.patch new file mode 100644 index 0000000000..4c175de142 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntityFireballFireball.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/world/entity/projectile/EntityFireballFireball.java ++++ b/net/minecraft/world/entity/projectile/EntityFireballFireball.java +@@ -65,6 +65,6 @@ + super.readAdditionalSaveData(nbttagcompound); + ItemStack itemstack = ItemStack.of(nbttagcompound.getCompound("Item")); + +- this.setItem(itemstack); ++ if (!itemstack.isEmpty()) this.setItem(itemstack); // CraftBukkit - SPIGOT-5474 probably came from bugged earlier versions + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntityFireworks.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntityFireworks.patch new file mode 100644 index 0000000000..1fd74e3369 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntityFireworks.patch @@ -0,0 +1,79 @@ +--- a/net/minecraft/world/entity/projectile/EntityFireworks.java ++++ b/net/minecraft/world/entity/projectile/EntityFireworks.java +@@ -28,6 +28,8 @@ + import net.minecraft.world.phys.MovingObjectPositionEntity; + import net.minecraft.world.phys.Vec3D; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public class EntityFireworks extends IProjectile implements ItemSupplier { + + public static final DataWatcherObject DATA_ID_FIREWORKS_ITEM = DataWatcher.defineId(EntityFireworks.class, DataWatcherRegistry.ITEM_STACK); +@@ -143,7 +145,7 @@ + MovingObjectPosition movingobjectposition = ProjectileHelper.getHitResultOnMoveVector(this, this::canHitEntity); + + if (!this.noPhysics) { +- this.onHit(movingobjectposition); ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + this.hasImpulse = true; + } + +@@ -158,7 +160,11 @@ + } + + if (!this.level().isClientSide && this.life > this.lifetime) { +- this.explode(); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) { ++ this.explode(); ++ } ++ // CraftBukkit end + } + + } +@@ -174,7 +180,11 @@ + protected void onHitEntity(MovingObjectPositionEntity movingobjectpositionentity) { + super.onHitEntity(movingobjectpositionentity); + if (!this.level().isClientSide) { +- this.explode(); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) { ++ this.explode(); ++ } ++ // CraftBukkit end + } + } + +@@ -184,7 +194,11 @@ + + this.level().getBlockState(blockposition).entityInside(this.level(), blockposition, this); + if (!this.level().isClientSide() && this.hasExplosion()) { +- this.explode(); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) { ++ this.explode(); ++ } ++ // CraftBukkit end + } + + super.onHitBlock(movingobjectpositionblock); +@@ -210,7 +224,9 @@ + + if (f > 0.0F) { + if (this.attachedToEntity != null) { ++ CraftEventFactory.entityDamage = this; // CraftBukkit + this.attachedToEntity.hurt(this.damageSources().fireworks(this, this.getOwner()), 5.0F + (float) (nbttaglist.size() * 2)); ++ CraftEventFactory.entityDamage = null; // CraftBukkit + } + + double d0 = 5.0D; +@@ -237,7 +253,9 @@ + if (flag) { + float f1 = f * (float) Math.sqrt((5.0D - (double) this.distanceTo(entityliving)) / 5.0D); + ++ CraftEventFactory.entityDamage = this; // CraftBukkit + entityliving.hurt(this.damageSources().fireworks(this, this.getOwner()), f1); ++ CraftEventFactory.entityDamage = null; // CraftBukkit + } + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntityFishingHook.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntityFishingHook.patch new file mode 100644 index 0000000000..93a0601030 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntityFishingHook.patch @@ -0,0 +1,173 @@ +--- a/net/minecraft/world/entity/projectile/EntityFishingHook.java ++++ b/net/minecraft/world/entity/projectile/EntityFishingHook.java +@@ -46,6 +46,12 @@ + import net.minecraft.world.phys.Vec3D; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.entity.Player; ++import org.bukkit.entity.FishHook; ++import org.bukkit.event.player.PlayerFishEvent; ++// CraftBukkit end ++ + public class EntityFishingHook extends IProjectile { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -67,6 +73,18 @@ + private final int luck; + private final int lureSpeed; + ++ // CraftBukkit start - Extra variables to enable modification of fishing wait time, values are minecraft defaults ++ public int minWaitTime = 100; ++ public int maxWaitTime = 600; ++ public int minLureTime = 20; ++ public int maxLureTime = 80; ++ public float minLureAngle = 0.0F; ++ public float maxLureAngle = 360.0F; ++ public boolean applyLure = true; ++ public boolean rainInfluenced = true; ++ public boolean skyInfluenced = true; ++ // CraftBukkit end ++ + private EntityFishingHook(EntityTypes entitytypes, World world, int i, int j) { + super(entitytypes, world); + this.syncronizedRandom = RandomSource.create(); +@@ -261,7 +279,7 @@ + private void checkCollision() { + MovingObjectPosition movingobjectposition = ProjectileHelper.getHitResultOnMoveVector(this, this::canHitEntity); + +- this.onHit(movingobjectposition); ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + } + + @Override +@@ -294,11 +312,11 @@ + int i = 1; + BlockPosition blockposition1 = blockposition.above(); + +- if (this.random.nextFloat() < 0.25F && this.level().isRainingAt(blockposition1)) { ++ if (this.rainInfluenced && this.random.nextFloat() < 0.25F && this.level().isRainingAt(blockposition1)) { // CraftBukkit + ++i; + } + +- if (this.random.nextFloat() < 0.5F && !this.level().canSeeSky(blockposition1)) { ++ if (this.skyInfluenced && this.random.nextFloat() < 0.5F && !this.level().canSeeSky(blockposition1)) { // CraftBukkit + --i; + } + +@@ -308,6 +326,10 @@ + this.timeUntilLured = 0; + this.timeUntilHooked = 0; + this.getEntityData().set(EntityFishingHook.DATA_BITING, false); ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) this.getPlayerOwner().getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.FAILED_ATTEMPT); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ // CraftBukkit end + } + } else { + float f; +@@ -341,6 +363,13 @@ + worldserver.sendParticles(Particles.FISHING, d0, d1, d2, 0, (double) (-f4), 0.01D, (double) f3, 1.0D); + } + } else { ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) this.getPlayerOwner().getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.BITE); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ if (playerFishEvent.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.playSound(SoundEffects.FISHING_BOBBER_SPLASH, 0.25F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F); + double d3 = this.getY() + 0.5D; + +@@ -373,12 +402,16 @@ + } + + if (this.timeUntilLured <= 0) { +- this.fishAngle = MathHelper.nextFloat(this.random, 0.0F, 360.0F); +- this.timeUntilHooked = MathHelper.nextInt(this.random, 20, 80); ++ // CraftBukkit start - logic to modify fishing wait time, lure time, and lure angle ++ this.fishAngle = MathHelper.nextFloat(this.random, this.minLureAngle, this.maxLureAngle); ++ this.timeUntilHooked = MathHelper.nextInt(this.random, this.minLureTime, this.maxLureTime); ++ // CraftBukkit end + } + } else { +- this.timeUntilLured = MathHelper.nextInt(this.random, 100, 600); +- this.timeUntilLured -= this.lureSpeed * 20 * 5; ++ // CraftBukkit start - logic to modify fishing wait time ++ this.timeUntilLured = MathHelper.nextInt(this.random, this.minWaitTime, this.maxWaitTime); ++ this.timeUntilLured -= (this.applyLure) ? this.lureSpeed * 20 * 5 : 0; ++ // CraftBukkit end + } + } + +@@ -445,6 +478,14 @@ + int i = 0; + + if (this.hookedIn != null) { ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), this.hookedIn.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_ENTITY); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ return 0; ++ } ++ // CraftBukkit end + this.pullEntity(this.hookedIn); + CriterionTriggers.FISHING_ROD_HOOKED.trigger((EntityPlayer) entityhuman, itemstack, this, Collections.emptyList()); + this.level().broadcastEntityEvent(this, (byte) 31); +@@ -460,6 +501,15 @@ + while (iterator.hasNext()) { + ItemStack itemstack1 = (ItemStack) iterator.next(); + EntityItem entityitem = new EntityItem(this.level(), this.getX(), this.getY(), this.getZ(), itemstack1); ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); ++ playerFishEvent.setExpToDrop(this.random.nextInt(6) + 1); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ return 0; ++ } ++ // CraftBukkit end + double d0 = entityhuman.getX() - this.getX(); + double d1 = entityhuman.getY() - this.getY(); + double d2 = entityhuman.getZ() - this.getZ(); +@@ -467,7 +517,11 @@ + + entityitem.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); + this.level().addFreshEntity(entityitem); +- entityhuman.level().addFreshEntity(new EntityExperienceOrb(entityhuman.level(), entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, this.random.nextInt(6) + 1)); ++ // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() ++ if (playerFishEvent.getExpToDrop() > 0) { ++ entityhuman.level().addFreshEntity(new EntityExperienceOrb(entityhuman.level(), entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop())); ++ } ++ // CraftBukkit end + if (itemstack1.is(TagsItem.FISHES)) { + entityhuman.awardStat(StatisticList.FISH_CAUGHT, 1); + } +@@ -477,8 +531,25 @@ + } + + if (this.onGround()) { ++ // CraftBukkit start ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.IN_GROUND); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ return 0; ++ } ++ // CraftBukkit end + i = 2; + } ++ // CraftBukkit start ++ if (i == 0) { ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.REEL_IN); ++ this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ if (playerFishEvent.isCancelled()) { ++ return 0; ++ } ++ } ++ // CraftBukkit end + + this.discard(); + return i; diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntityLargeFireball.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntityLargeFireball.patch new file mode 100644 index 0000000000..3a8815f46c --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntityLargeFireball.patch @@ -0,0 +1,51 @@ +--- a/net/minecraft/world/entity/projectile/EntityLargeFireball.java ++++ b/net/minecraft/world/entity/projectile/EntityLargeFireball.java +@@ -9,17 +9,21 @@ + import net.minecraft.world.phys.MovingObjectPosition; + import net.minecraft.world.phys.MovingObjectPositionEntity; + ++import org.bukkit.event.entity.ExplosionPrimeEvent; // CraftBukkit ++ + public class EntityLargeFireball extends EntityFireballFireball { + + public int explosionPower = 1; + + public EntityLargeFireball(EntityTypes entitytypes, World world) { + super(entitytypes, world); ++ isIncendiary = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // CraftBukkit + } + + public EntityLargeFireball(World world, EntityLiving entityliving, double d0, double d1, double d2, int i) { + super(EntityTypes.FIREBALL, entityliving, d0, d1, d2, world); + this.explosionPower = i; ++ isIncendiary = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // CraftBukkit + } + + @Override +@@ -28,7 +32,15 @@ + if (!this.level().isClientSide) { + boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); + +- this.level().explode(this, this.getX(), this.getY(), this.getZ(), (float) this.explosionPower, flag, World.a.MOB); ++ // CraftBukkit start - fire ExplosionPrimeEvent ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent((org.bukkit.entity.Explosive) this.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ // give 'this' instead of (Entity) null so we know what causes the damage ++ this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), World.a.MOB); ++ } ++ // CraftBukkit end + this.discard(); + } + +@@ -59,7 +71,8 @@ + public void readAdditionalSaveData(NBTTagCompound nbttagcompound) { + super.readAdditionalSaveData(nbttagcompound); + if (nbttagcompound.contains("ExplosionPower", 99)) { +- this.explosionPower = nbttagcompound.getByte("ExplosionPower"); ++ // CraftBukkit - set bukkitYield when setting explosionpower ++ bukkitYield = this.explosionPower = nbttagcompound.getByte("ExplosionPower"); + } + + } diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntityLlamaSpit.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntityLlamaSpit.patch new file mode 100644 index 0000000000..408aa43d97 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntityLlamaSpit.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/projectile/EntityLlamaSpit.java ++++ b/net/minecraft/world/entity/projectile/EntityLlamaSpit.java +@@ -32,7 +32,7 @@ + Vec3D vec3d = this.getDeltaMovement(); + MovingObjectPosition movingobjectposition = ProjectileHelper.getHitResultOnMoveVector(this, this::canHitEntity); + +- this.onHit(movingobjectposition); ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + double d0 = this.getX() + vec3d.x; + double d1 = this.getY() + vec3d.y; + double d2 = this.getZ() + vec3d.z; diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntityPotion.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntityPotion.patch new file mode 100644 index 0000000000..a6087a3bc0 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntityPotion.patch @@ -0,0 +1,168 @@ +--- a/net/minecraft/world/entity/projectile/EntityPotion.java ++++ b/net/minecraft/world/entity/projectile/EntityPotion.java +@@ -31,6 +31,17 @@ + import net.minecraft.world.phys.MovingObjectPositionBlock; + import net.minecraft.world.phys.MovingObjectPositionEntity; + ++// CraftBukkit start ++import java.util.HashMap; ++import java.util.Map; ++import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.world.effect.MobEffects; ++import net.minecraft.world.level.block.Blocks; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.entity.LivingEntity; ++// CraftBukkit end ++ + public class EntityPotion extends EntityProjectileThrowable implements ItemSupplier { + + public static final double SPLASH_RANGE = 4.0D; +@@ -99,11 +110,11 @@ + + if (flag) { + this.applyWater(); +- } else if (!list.isEmpty()) { ++ } else if (true || !list.isEmpty()) { // CraftBukkit - Call event even if no effects to apply + if (this.isLingering()) { +- this.makeAreaOfEffectCloud(itemstack, potionregistry); ++ this.makeAreaOfEffectCloud(itemstack, potionregistry, movingobjectposition); // CraftBukkit - Pass MovingObjectPosition + } else { +- this.applySplash(list, movingobjectposition.getType() == MovingObjectPosition.EnumMovingObjectType.ENTITY ? ((MovingObjectPositionEntity) movingobjectposition).getEntity() : null); ++ this.applySplash(list, movingobjectposition.getType() == MovingObjectPosition.EnumMovingObjectType.ENTITY ? ((MovingObjectPositionEntity) movingobjectposition).getEntity() : null, movingobjectposition); // CraftBukkit - Pass MovingObjectPosition + } + } + +@@ -145,9 +156,10 @@ + + } + +- private void applySplash(List list, @Nullable Entity entity) { ++ private void applySplash(List list, @Nullable Entity entity, MovingObjectPosition position) { // CraftBukkit - Pass MovingObjectPosition + AxisAlignedBB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D); + List list1 = this.level().getEntitiesOfClass(EntityLiving.class, axisalignedbb); ++ Map affected = new HashMap(); // CraftBukkit + + if (!list1.isEmpty()) { + Entity entity1 = this.getEffectSource(); +@@ -168,24 +180,49 @@ + d1 = 1.0D - Math.sqrt(d0) / 4.0D; + } + +- Iterator iterator1 = list.iterator(); ++ // CraftBukkit start ++ affected.put((LivingEntity) entityliving.getBukkitEntity(), d1); ++ } ++ } ++ } ++ } + +- while (iterator1.hasNext()) { +- MobEffect mobeffect = (MobEffect) iterator1.next(); +- MobEffectList mobeffectlist = mobeffect.getEffect(); ++ org.bukkit.event.entity.PotionSplashEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPotionSplashEvent(this, position, affected); ++ if (!event.isCancelled() && list != null && !list.isEmpty()) { // do not process effects if there are no effects to process ++ Entity entity1 = this.getEffectSource(); ++ for (LivingEntity victim : event.getAffectedEntities()) { ++ if (!(victim instanceof CraftLivingEntity)) { ++ continue; ++ } + +- if (mobeffectlist.isInstantenous()) { +- mobeffectlist.applyInstantenousEffect(this, this.getOwner(), entityliving, mobeffect.getAmplifier(), d1); +- } else { +- int i = mobeffect.mapDuration((j) -> { +- return (int) (d1 * (double) j + 0.5D); +- }); +- MobEffect mobeffect1 = new MobEffect(mobeffectlist, i, mobeffect.getAmplifier(), mobeffect.isAmbient(), mobeffect.isVisible()); ++ EntityLiving entityliving = ((CraftLivingEntity) victim).getHandle(); ++ double d1 = event.getIntensity(victim); ++ // CraftBukkit end + +- if (!mobeffect1.endsWithin(20)) { +- entityliving.addEffect(mobeffect1, entity1); +- } +- } ++ Iterator iterator1 = list.iterator(); ++ ++ while (iterator1.hasNext()) { ++ MobEffect mobeffect = (MobEffect) iterator1.next(); ++ MobEffectList mobeffectlist = mobeffect.getEffect(); ++ // CraftBukkit start - Abide by PVP settings - for players only! ++ if (!this.level().pvpMode && this.getOwner() instanceof EntityPlayer && entityliving instanceof EntityPlayer && entityliving != this.getOwner()) { ++ if (mobeffectlist == MobEffects.MOVEMENT_SLOWDOWN || mobeffectlist == MobEffects.DIG_SLOWDOWN || mobeffectlist == MobEffects.HARM || mobeffectlist == MobEffects.BLINDNESS ++ || mobeffectlist == MobEffects.HUNGER || mobeffectlist == MobEffects.WEAKNESS || mobeffectlist == MobEffects.POISON) { ++ continue; ++ } ++ } ++ // CraftBukkit end ++ ++ if (mobeffectlist.isInstantenous()) { ++ mobeffectlist.applyInstantenousEffect(this, this.getOwner(), entityliving, mobeffect.getAmplifier(), d1); ++ } else { ++ int i = mobeffect.mapDuration((j) -> { ++ return (int) (d1 * (double) j + 0.5D); ++ }); ++ MobEffect mobeffect1 = new MobEffect(mobeffectlist, i, mobeffect.getAmplifier(), mobeffect.isAmbient(), mobeffect.isVisible()); ++ ++ if (!mobeffect1.endsWithin(20)) { ++ entityliving.addEffect(mobeffect1, entity1, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_SPLASH); // CraftBukkit + } + } + } +@@ -194,7 +231,7 @@ + + } + +- private void makeAreaOfEffectCloud(ItemStack itemstack, PotionRegistry potionregistry) { ++ private void makeAreaOfEffectCloud(ItemStack itemstack, PotionRegistry potionregistry, MovingObjectPosition position) { // CraftBukkit - Pass MovingObjectPosition + EntityAreaEffectCloud entityareaeffectcloud = new EntityAreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); + Entity entity = this.getOwner(); + +@@ -221,7 +258,14 @@ + entityareaeffectcloud.setFixedColor(nbttagcompound.getInt("CustomPotionColor")); + } + +- this.level().addFreshEntity(entityareaeffectcloud); ++ // CraftBukkit start ++ org.bukkit.event.entity.LingeringPotionSplashEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callLingeringPotionSplashEvent(this, position, entityareaeffectcloud); ++ if (!(event.isCancelled() || entityareaeffectcloud.isRemoved())) { ++ this.level().addFreshEntity(entityareaeffectcloud); ++ } else { ++ entityareaeffectcloud.discard(); ++ } ++ // CraftBukkit end + } + + public boolean isLingering() { +@@ -232,13 +276,25 @@ + IBlockData iblockdata = this.level().getBlockState(blockposition); + + if (iblockdata.is(TagsBlock.FIRE)) { +- this.level().destroyBlock(blockposition, false, this); ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState())) { ++ this.level().destroyBlock(blockposition, false, this); ++ } ++ // CraftBukkit end + } else if (AbstractCandleBlock.isLit(iblockdata)) { +- AbstractCandleBlock.extinguish((EntityHuman) null, iblockdata, this.level(), blockposition); ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, iblockdata.setValue(AbstractCandleBlock.LIT, false))) { ++ AbstractCandleBlock.extinguish((EntityHuman) null, iblockdata, this.level(), blockposition); ++ } ++ // CraftBukkit end + } else if (BlockCampfire.isLitCampfire(iblockdata)) { +- this.level().levelEvent((EntityHuman) null, 1009, blockposition, 0); +- BlockCampfire.dowse(this.getOwner(), this.level(), blockposition, iblockdata); +- this.level().setBlockAndUpdate(blockposition, (IBlockData) iblockdata.setValue(BlockCampfire.LIT, false)); ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, iblockdata.setValue(BlockCampfire.LIT, false))) { ++ this.level().levelEvent((EntityHuman) null, 1009, blockposition, 0); ++ BlockCampfire.dowse(this.getOwner(), this.level(), blockposition, iblockdata); ++ this.level().setBlockAndUpdate(blockposition, (IBlockData) iblockdata.setValue(BlockCampfire.LIT, false)); ++ } ++ // CraftBukkit end + } + + } diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntityProjectile.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntityProjectile.patch new file mode 100644 index 0000000000..eacc230d95 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntityProjectile.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/projectile/EntityProjectile.java ++++ b/net/minecraft/world/entity/projectile/EntityProjectile.java +@@ -66,7 +66,7 @@ + } + + if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS && !flag) { +- this.onHit(movingobjectposition); ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + } + + this.checkInsideBlocks(); diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntityProjectileThrowable.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntityProjectileThrowable.patch new file mode 100644 index 0000000000..969c95218b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntityProjectileThrowable.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/entity/projectile/EntityProjectileThrowable.java ++++ b/net/minecraft/world/entity/projectile/EntityProjectileThrowable.java +@@ -35,6 +35,12 @@ + + protected abstract Item getDefaultItem(); + ++ // CraftBukkit start ++ public Item getDefaultItemPublic() { ++ return getDefaultItem(); ++ } ++ // CraftBukkit end ++ + public ItemStack getItemRaw() { + return (ItemStack) this.getEntityData().get(EntityProjectileThrowable.DATA_ITEM_STACK); + } diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntityShulkerBullet.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntityShulkerBullet.patch new file mode 100644 index 0000000000..cdcf10b224 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntityShulkerBullet.patch @@ -0,0 +1,53 @@ +--- a/net/minecraft/world/entity/projectile/EntityShulkerBullet.java ++++ b/net/minecraft/world/entity/projectile/EntityShulkerBullet.java +@@ -60,7 +60,20 @@ + this.finalTarget = entity; + this.currentMoveDirection = EnumDirection.UP; + this.selectNextMoveDirection(enumdirection_enumaxis); ++ projectileSource = (org.bukkit.entity.LivingEntity) entityliving.getBukkitEntity(); // CraftBukkit ++ } ++ ++ // CraftBukkit start ++ public Entity getTarget() { ++ return this.finalTarget; ++ } ++ ++ public void setTarget(Entity e) { ++ this.finalTarget = e; ++ this.currentMoveDirection = EnumDirection.UP; ++ this.selectNextMoveDirection(EnumDirection.EnumAxis.X); + } ++ // CraftBukkit end + + @Override + public SoundCategory getSoundSource() { +@@ -225,7 +238,7 @@ + MovingObjectPosition movingobjectposition = ProjectileHelper.getHitResultOnMoveVector(this, this::canHitEntity); + + if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) { +- this.onHit(movingobjectposition); ++ this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event + } + } + +@@ -294,7 +307,7 @@ + if (entity instanceof EntityLiving) { + EntityLiving entityliving1 = (EntityLiving) entity; + +- entityliving1.addEffect(new MobEffect(MobEffects.LEVITATION, 200), (Entity) MoreObjects.firstNonNull(entity1, this)); ++ entityliving1.addEffect(new MobEffect(MobEffects.LEVITATION, 200), (Entity) MoreObjects.firstNonNull(entity1, this), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + +@@ -325,6 +338,11 @@ + + @Override + public boolean hurt(DamageSource damagesource, float f) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, damagesource, f, false)) { ++ return false; ++ } ++ // CraftBukkit end + if (!this.level().isClientSide) { + this.playSound(SoundEffects.SHULKER_BULLET_HURT, 1.0F, 1.0F); + ((WorldServer) this.level()).sendParticles(Particles.CRIT, this.getX(), this.getY(), this.getZ(), 15, 0.2D, 0.2D, 0.2D, 0.0D); diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntitySmallFireball.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntitySmallFireball.patch new file mode 100644 index 0000000000..d193a82795 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntitySmallFireball.patch @@ -0,0 +1,52 @@ +--- a/net/minecraft/world/entity/projectile/EntitySmallFireball.java ++++ b/net/minecraft/world/entity/projectile/EntitySmallFireball.java +@@ -13,6 +13,8 @@ + import net.minecraft.world.phys.MovingObjectPositionBlock; + import net.minecraft.world.phys.MovingObjectPositionEntity; + ++import org.bukkit.event.entity.EntityCombustByEntityEvent; // CraftBukkit ++ + public class EntitySmallFireball extends EntityFireballFireball { + + public EntitySmallFireball(EntityTypes entitytypes, World world) { +@@ -21,6 +23,11 @@ + + public EntitySmallFireball(World world, EntityLiving entityliving, double d0, double d1, double d2) { + super(EntityTypes.SMALL_FIREBALL, entityliving, d0, d1, d2, world); ++ // CraftBukkit start ++ if (this.getOwner() != null && this.getOwner() instanceof EntityInsentient) { ++ isIncendiary = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); ++ } ++ // CraftBukkit end + } + + public EntitySmallFireball(World world, double d0, double d1, double d2, double d3, double d4, double d5) { +@@ -35,7 +42,14 @@ + Entity entity1 = this.getOwner(); + int i = entity.getRemainingFireTicks(); + +- entity.setSecondsOnFire(5); ++ // CraftBukkit start - Entity damage by entity event + combust event ++ EntityCombustByEntityEvent event = new EntityCombustByEntityEvent((org.bukkit.entity.Projectile) this.getBukkitEntity(), entity.getBukkitEntity(), 5); ++ entity.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ entity.setSecondsOnFire(event.getDuration(), false); ++ } ++ // CraftBukkit end + if (!entity.hurt(this.damageSources().fireball(this, entity1), 5.0F)) { + entity.setRemainingFireTicks(i); + } else if (entity1 instanceof EntityLiving) { +@@ -51,10 +65,10 @@ + if (!this.level().isClientSide) { + Entity entity = this.getOwner(); + +- if (!(entity instanceof EntityInsentient) || this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ if (isIncendiary) { // CraftBukkit + BlockPosition blockposition = movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()); + +- if (this.level().isEmptyBlock(blockposition)) { ++ if (this.level().isEmptyBlock(blockposition) && !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(this.level(), blockposition, this).isCancelled()) { // CraftBukkit + this.level().setBlockAndUpdate(blockposition, BlockFireAbstract.getState(this.level(), blockposition)); + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntitySpectralArrow.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntitySpectralArrow.patch new file mode 100644 index 0000000000..292ce8948a --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntitySpectralArrow.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/projectile/EntitySpectralArrow.java ++++ b/net/minecraft/world/entity/projectile/EntitySpectralArrow.java +@@ -41,7 +41,7 @@ + super.doPostHurtEffects(entityliving); + MobEffect mobeffect = new MobEffect(MobEffects.GLOWING, this.duration, 0); + +- entityliving.addEffect(mobeffect, this.getEffectSource()); ++ entityliving.addEffect(mobeffect, this.getEffectSource(), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ARROW); // CraftBukkit + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntityThrownExpBottle.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntityThrownExpBottle.patch new file mode 100644 index 0000000000..4d2228fa51 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntityThrownExpBottle.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java ++++ b/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java +@@ -39,9 +39,18 @@ + protected void onHit(MovingObjectPosition movingobjectposition) { + super.onHit(movingobjectposition); + if (this.level() instanceof WorldServer) { +- this.level().levelEvent(2002, this.blockPosition(), PotionUtil.getColor(Potions.WATER)); ++ // CraftBukkit - moved to after event ++ // this.level().levelEvent(2002, this.blockPosition(), PotionUtil.getColor(Potions.WATER)); + int i = 3 + this.level().random.nextInt(5) + this.level().random.nextInt(5); + ++ // CraftBukkit start ++ org.bukkit.event.entity.ExpBottleEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExpBottleEvent(this, movingobjectposition, i); ++ i = event.getExperience(); ++ if (event.getShowEffect()) { ++ this.level().levelEvent(2002, this.blockPosition(), PotionUtil.getColor(Potions.WATER)); ++ } ++ // CraftBukkit end ++ + EntityExperienceOrb.award((WorldServer) this.level(), this.position(), i); + this.discard(); + } diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntityThrownTrident.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntityThrownTrident.patch new file mode 100644 index 0000000000..fac6f2e3ab --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntityThrownTrident.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/projectile/EntityThrownTrident.java ++++ b/net/minecraft/world/entity/projectile/EntityThrownTrident.java +@@ -153,7 +153,7 @@ + if (entitylightning != null) { + entitylightning.moveTo(Vec3D.atBottomCenterOf(blockposition)); + entitylightning.setCause(entity1 instanceof EntityPlayer ? (EntityPlayer) entity1 : null); +- this.level().addFreshEntity(entitylightning); ++ ((WorldServer) this.level()).strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.TRIDENT); // CraftBukkit + soundeffect = SoundEffects.TRIDENT_THUNDER; + f1 = 5.0F; + } diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntityTippedArrow.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntityTippedArrow.patch new file mode 100644 index 0000000000..c33358120b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntityTippedArrow.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/entity/projectile/EntityTippedArrow.java ++++ b/net/minecraft/world/entity/projectile/EntityTippedArrow.java +@@ -213,7 +213,7 @@ + mobeffect = (MobEffect) iterator.next(); + entityliving.addEffect(new MobEffect(mobeffect.getEffect(), Math.max(mobeffect.mapDuration((i) -> { + return i / 8; +- }), 1), mobeffect.getAmplifier(), mobeffect.isAmbient(), mobeffect.isVisible()), entity); ++ }), 1), mobeffect.getAmplifier(), mobeffect.isAmbient(), mobeffect.isVisible()), entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ARROW); // CraftBukkit + } + + if (!this.effects.isEmpty()) { +@@ -221,7 +221,7 @@ + + while (iterator.hasNext()) { + mobeffect = (MobEffect) iterator.next(); +- entityliving.addEffect(mobeffect, entity); ++ entityliving.addEffect(mobeffect, entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ARROW); // CraftBukkit + } + } + diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/EntityWitherSkull.patch b/patch-remap/og/net/minecraft/world/entity/projectile/EntityWitherSkull.patch new file mode 100644 index 0000000000..0554cccc02 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/EntityWitherSkull.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/world/entity/projectile/EntityWitherSkull.java ++++ b/net/minecraft/world/entity/projectile/EntityWitherSkull.java +@@ -21,6 +21,10 @@ + import net.minecraft.world.phys.MovingObjectPosition; + import net.minecraft.world.phys.MovingObjectPositionEntity; + ++// CraftBukkit start ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end ++ + public class EntityWitherSkull extends EntityFireball { + + private static final DataWatcherObject DATA_DANGEROUS = DataWatcher.defineId(EntityWitherSkull.class, DataWatcherRegistry.BOOLEAN); +@@ -64,7 +68,7 @@ + if (entity.isAlive()) { + this.doEnchantDamageEffects(entityliving, entity); + } else { +- entityliving.heal(5.0F); ++ entityliving.heal(5.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.WITHER); // CraftBukkit + } + } + } else { +@@ -82,7 +86,7 @@ + } + + if (b0 > 0) { +- entityliving.addEffect(new MobEffect(MobEffects.WITHER, 20 * b0, 1), this.getEffectSource()); ++ entityliving.addEffect(new MobEffect(MobEffects.WITHER, 20 * b0, 1), this.getEffectSource(), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + +@@ -93,7 +97,15 @@ + protected void onHit(MovingObjectPosition movingobjectposition) { + super.onHit(movingobjectposition); + if (!this.level().isClientSide) { +- this.level().explode(this, this.getX(), this.getY(), this.getZ(), 1.0F, false, World.a.MOB); ++ // CraftBukkit start ++ // this.level().explode(this, this.getX(), this.getY(), this.getZ(), 1.0F, false, World.a.MOB); ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), 1.0F, false); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), World.a.MOB); ++ } ++ // CraftBukkit end + this.discard(); + } + diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/IProjectile.patch b/patch-remap/og/net/minecraft/world/entity/projectile/IProjectile.patch new file mode 100644 index 0000000000..3f2ade60da --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/IProjectile.patch @@ -0,0 +1,61 @@ +--- a/net/minecraft/world/entity/projectile/IProjectile.java ++++ b/net/minecraft/world/entity/projectile/IProjectile.java +@@ -25,6 +25,10 @@ + import net.minecraft.world.phys.MovingObjectPositionEntity; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.projectiles.ProjectileSource; ++// CraftBukkit end ++ + public abstract class IProjectile extends Entity implements TraceableEntity { + + @Nullable +@@ -34,6 +38,10 @@ + private boolean leftOwner; + private boolean hasBeenShot; + ++ // CraftBukkit start ++ private boolean hitCancelled = false; ++ // CraftBukkit end ++ + IProjectile(EntityTypes entitytypes, World world) { + super(entitytypes, world); + } +@@ -43,6 +51,7 @@ + this.ownerUUID = entity.getUUID(); + this.cachedOwner = entity; + } ++ this.projectileSource = (entity != null && entity.getBukkitEntity() instanceof ProjectileSource) ? (ProjectileSource) entity.getBukkitEntity() : null; // CraftBukkit + + } + +@@ -167,6 +176,16 @@ + this.setDeltaMovement(this.getDeltaMovement().add(vec3d.x, entity.onGround() ? 0.0D : vec3d.y, vec3d.z)); + } + ++ // CraftBukkit start - call projectile hit event ++ protected void preOnHit(MovingObjectPosition movingobjectposition) { ++ org.bukkit.event.entity.ProjectileHitEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); ++ this.hitCancelled = event != null && event.isCancelled(); ++ if (movingobjectposition.getType() == MovingObjectPosition.EnumMovingObjectType.BLOCK || !this.hitCancelled) { ++ this.onHit(movingobjectposition); ++ } ++ } ++ // CraftBukkit end ++ + protected void onHit(MovingObjectPosition movingobjectposition) { + MovingObjectPosition.EnumMovingObjectType movingobjectposition_enummovingobjecttype = movingobjectposition.getType(); + +@@ -187,6 +206,11 @@ + protected void onHitEntity(MovingObjectPositionEntity movingobjectpositionentity) {} + + protected void onHitBlock(MovingObjectPositionBlock movingobjectpositionblock) { ++ // CraftBukkit start - cancellable hit event ++ if (hitCancelled) { ++ return; ++ } ++ // CraftBukkit end + IBlockData iblockdata = this.level().getBlockState(movingobjectpositionblock.getBlockPos()); + + iblockdata.onProjectileHit(this.level(), iblockdata, movingobjectpositionblock, this); diff --git a/patch-remap/og/net/minecraft/world/entity/projectile/WindCharge.patch b/patch-remap/og/net/minecraft/world/entity/projectile/WindCharge.patch new file mode 100644 index 0000000000..036fa3fec3 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/projectile/WindCharge.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/entity/projectile/WindCharge.java ++++ b/net/minecraft/world/entity/projectile/WindCharge.java +@@ -81,7 +81,7 @@ + } + } + +- private void explode() { ++ public void explode() { // PAIL private -> public + this.level().explode(this, (DamageSource) null, WindCharge.EXPLOSION_DAMAGE_CALCULATOR, this.getX(), this.getY(), this.getZ(), (float) (3.0D + this.random.nextDouble()), false, World.a.BLOW, Particles.GUST, Particles.GUST_EMITTER, SoundEffects.WIND_BURST); + } + diff --git a/patch-remap/og/net/minecraft/world/entity/raid/EntityRaider.patch b/patch-remap/og/net/minecraft/world/entity/raid/EntityRaider.patch new file mode 100644 index 0000000000..a54568be33 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/raid/EntityRaider.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/world/entity/raid/EntityRaider.java ++++ b/net/minecraft/world/entity/raid/EntityRaider.java +@@ -165,7 +165,7 @@ + MobEffect mobeffect1 = new MobEffect(MobEffects.BAD_OMEN, 120000, i, false, false, true); + + if (!this.level().getGameRules().getBoolean(GameRules.RULE_DISABLE_RAIDS)) { +- entityhuman.addEffect(mobeffect1); ++ entityhuman.addEffect(mobeffect1, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.PATROL_CAPTAIN); // CraftBukkit + } + } + } +@@ -305,7 +305,7 @@ + + private final T mob; + +- public b(EntityRaider entityraider) { ++ public b(T entityraider) { // CraftBukkit - decompile error + this.mob = entityraider; + this.setFlags(EnumSet.of(PathfinderGoal.Type.MOVE)); + } +@@ -521,7 +521,7 @@ + while (iterator.hasNext()) { + EntityRaider entityraider = (EntityRaider) iterator.next(); + +- entityraider.setTarget(this.mob.getTarget()); ++ entityraider.setTarget(this.mob.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.FOLLOW_LEADER, true); // CraftBukkit + } + + } +@@ -538,7 +538,7 @@ + while (iterator.hasNext()) { + EntityRaider entityraider = (EntityRaider) iterator.next(); + +- entityraider.setTarget(entityliving); ++ entityraider.setTarget(this.mob.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.FOLLOW_LEADER, true); // CraftBukkit + entityraider.setAggressive(true); + } + diff --git a/patch-remap/og/net/minecraft/world/entity/raid/PersistentRaid.patch b/patch-remap/og/net/minecraft/world/entity/raid/PersistentRaid.patch new file mode 100644 index 0000000000..72213d9b13 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/raid/PersistentRaid.patch @@ -0,0 +1,37 @@ +--- a/net/minecraft/world/entity/raid/PersistentRaid.java ++++ b/net/minecraft/world/entity/raid/PersistentRaid.java +@@ -121,19 +121,33 @@ + boolean flag = false; + + if (!raid.isStarted()) { ++ /* CraftBukkit - moved down + if (!this.raidMap.containsKey(raid.getId())) { + this.raidMap.put(raid.getId(), raid); + } ++ */ + + flag = true; +- } else if (raid.getBadOmenLevel() < raid.getMaxBadOmenLevel()) { ++ // CraftBukkit start - fixed a bug with raid: players could add up Bad Omen level even when the raid had finished ++ } else if (raid.isInProgress() && raid.getBadOmenLevel() < raid.getMaxBadOmenLevel()) { + flag = true; ++ // CraftBukkit end + } else { + entityplayer.removeEffect(MobEffects.BAD_OMEN); + entityplayer.connection.send(new PacketPlayOutEntityStatus(entityplayer, (byte) 43)); + } + + if (flag) { ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callRaidTriggerEvent(raid, entityplayer)) { ++ entityplayer.removeEffect(MobEffects.BAD_OMEN); ++ return null; ++ } ++ ++ if (!this.raidMap.containsKey(raid.getId())) { ++ this.raidMap.put(raid.getId(), raid); ++ } ++ // CraftBukkit end + raid.absorbBadOmen(entityplayer); + entityplayer.connection.send(new PacketPlayOutEntityStatus(entityplayer, (byte) 43)); + if (!raid.hasFirstWaveSpawned()) { diff --git a/patch-remap/og/net/minecraft/world/entity/raid/Raid.patch b/patch-remap/og/net/minecraft/world/entity/raid/Raid.patch new file mode 100644 index 0000000000..c44497a2f3 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/raid/Raid.patch @@ -0,0 +1,138 @@ +--- a/net/minecraft/world/entity/raid/Raid.java ++++ b/net/minecraft/world/entity/raid/Raid.java +@@ -176,6 +176,12 @@ + return this.status == Raid.Status.LOSS; + } + ++ // CraftBukkit start ++ public boolean isInProgress() { ++ return this.status == Status.ONGOING; ++ } ++ // CraftBukkit end ++ + public float getTotalHealth() { + return this.totalHealth; + } +@@ -272,6 +278,7 @@ + + this.active = this.level.hasChunkAt(this.center); + if (this.level.getDifficulty() == EnumDifficulty.PEACEFUL) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.PEACE); // CraftBukkit + this.stop(); + return; + } +@@ -291,13 +298,16 @@ + if (!this.level.isVillage(this.center)) { + if (this.groupsSpawned > 0) { + this.status = Raid.Status.LOSS; ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidFinishEvent(this, new java.util.ArrayList<>()); // CraftBukkit + } else { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.NOT_IN_VILLAGE); // CraftBukkit + this.stop(); + } + } + + ++this.ticksActive; + if (this.ticksActive >= 48000L) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.TIMEOUT); // CraftBukkit + this.stop(); + return; + } +@@ -371,6 +381,7 @@ + } + + if (j > 3) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.UNSPAWNABLE); // CraftBukkit + this.stop(); + break; + } +@@ -383,6 +394,7 @@ + this.status = Raid.Status.VICTORY; + Iterator iterator = this.heroesOfTheVillage.iterator(); + ++ List winners = new java.util.ArrayList<>(); // CraftBukkit + while (iterator.hasNext()) { + UUID uuid = (UUID) iterator.next(); + Entity entity = this.level.getEntity(uuid); +@@ -397,10 +409,12 @@ + + entityplayer.awardStat(StatisticList.RAID_WIN); + CriterionTriggers.RAID_WIN.trigger(entityplayer); ++ winners.add(entityplayer.getBukkitEntity()); // CraftBukkit + } + } + } + } ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidFinishEvent(this, winners); // CraftBukkit + } + } + +@@ -408,6 +422,7 @@ + } else if (this.isOver()) { + ++this.celebrationTicks; + if (this.celebrationTicks >= 600) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.FINISHED); // CraftBukkit + this.stop(); + return; + } +@@ -544,6 +559,10 @@ + int j = araid_wave.length; + int k = 0; + ++ // CraftBukkit start ++ EntityRaider leader = null; ++ List raiders = new java.util.ArrayList<>(); ++ // CraftBukkit end + while (k < j) { + Raid.Wave raid_wave = araid_wave[k]; + int l = this.getDefaultNumSpawns(raid_wave, i, flag1) + this.getPotentialBonusSpawns(raid_wave, this.random, i, difficultydamagescaler, flag1); +@@ -559,9 +578,11 @@ + entityraider.setPatrolLeader(true); + this.setLeader(i, entityraider); + flag = true; ++ leader = entityraider; // CraftBukkit + } + + this.joinRaid(i, entityraider, blockposition, false); ++ raiders.add(entityraider); // CraftBukkit + if (raid_wave.entityType == EntityTypes.RAVAGER) { + EntityRaider entityraider1 = null; + +@@ -580,6 +601,7 @@ + this.joinRaid(i, entityraider1, blockposition, false); + entityraider1.moveTo(blockposition, 0.0F, 0.0F); + entityraider1.startRiding(entityraider); ++ raiders.add(entityraider); // CraftBukkit + } + } + +@@ -597,6 +619,7 @@ + ++this.groupsSpawned; + this.updateBossbar(); + this.setDirty(); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRaidSpawnWaveEvent(this, leader, raiders); // CraftBukkit + } + + public void joinRaid(int i, EntityRaider entityraider, @Nullable BlockPosition blockposition, boolean flag) { +@@ -612,7 +635,7 @@ + entityraider.finalizeSpawn(this.level, this.level.getCurrentDifficultyAt(blockposition), EnumMobSpawn.EVENT, (GroupDataEntity) null, (NBTTagCompound) null); + entityraider.applyRaidBuffs(i, false); + entityraider.setOnGround(true); +- this.level.addFreshEntityWithPassengers(entityraider); ++ this.level.addFreshEntityWithPassengers(entityraider, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.RAID); // CraftBukkit + } + } + +@@ -862,6 +885,12 @@ + this.heroesOfTheVillage.add(entity.getUUID()); + } + ++ // CraftBukkit start - a method to get all raiders ++ public java.util.Collection getRaiders() { ++ return this.groupRaiderMap.values().stream().flatMap(Set::stream).collect(java.util.stream.Collectors.toSet()); ++ } ++ // CraftBukkit end ++ + private static enum Status { + + ONGOING, VICTORY, LOSS, STOPPED; diff --git a/patch-remap/og/net/minecraft/world/entity/vehicle/ChestBoat.patch b/patch-remap/og/net/minecraft/world/entity/vehicle/ChestBoat.patch new file mode 100644 index 0000000000..fa8f1a63b7 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/vehicle/ChestBoat.patch @@ -0,0 +1,68 @@ +--- a/net/minecraft/world/entity/vehicle/ChestBoat.java ++++ b/net/minecraft/world/entity/vehicle/ChestBoat.java +@@ -23,6 +23,13 @@ + import net.minecraft.world.item.Items; + import net.minecraft.world.level.World; + import net.minecraft.world.level.gameevent.GameEvent; ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end + + public class ChestBoat extends EntityBoat implements HasCustomInventoryScreen, ContainerEntity { + +@@ -238,4 +245,51 @@ + public void stopOpen(EntityHuman entityhuman) { + this.level().gameEvent(GameEvent.CONTAINER_CLOSE, this.position(), GameEvent.a.of((Entity) entityhuman)); + } ++ ++ // CraftBukkit start ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ @Override ++ public List getContents() { ++ return this.itemStacks; ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public InventoryHolder getOwner() { ++ org.bukkit.entity.Entity entity = getBukkitEntity(); ++ if (entity instanceof InventoryHolder) return (InventoryHolder) entity; ++ return null; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ @Override ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return getBukkitEntity().getLocation(); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/entity/vehicle/EntityBoat.patch b/patch-remap/og/net/minecraft/world/entity/vehicle/EntityBoat.patch new file mode 100644 index 0000000000..3541afdcf1 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/vehicle/EntityBoat.patch @@ -0,0 +1,114 @@ +--- a/net/minecraft/world/entity/vehicle/EntityBoat.java ++++ b/net/minecraft/world/entity/vehicle/EntityBoat.java +@@ -55,6 +55,15 @@ + import net.minecraft.world.phys.shapes.VoxelShapes; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.Vehicle; ++import org.bukkit.event.vehicle.VehicleDestroyEvent; ++import org.bukkit.event.vehicle.VehicleEntityCollisionEvent; ++import org.bukkit.event.vehicle.VehicleMoveEvent; ++// CraftBukkit end ++ + public class EntityBoat extends VehicleEntity implements VariantHolder { + + private static final DataWatcherObject DATA_ID_TYPE = DataWatcher.defineId(EntityBoat.class, DataWatcherRegistry.INT); +@@ -92,6 +101,14 @@ + private float bubbleAngle; + private float bubbleAngleO; + ++ // CraftBukkit start ++ // PAIL: Some of these haven't worked since a few updates, and since 1.9 they are less and less applicable. ++ public double maxSpeed = 0.4D; ++ public double occupiedDeceleration = 0.2D; ++ public double unoccupiedDeceleration = -1; ++ public boolean landBoats = false; ++ // CraftBukkit end ++ + public EntityBoat(EntityTypes entitytypes, World world) { + super(entitytypes, world); + this.paddlePositions = new float[2]; +@@ -192,9 +209,29 @@ + public void push(Entity entity) { + if (entity instanceof EntityBoat) { + if (entity.getBoundingBox().minY < this.getBoundingBox().maxY) { ++ // CraftBukkit start ++ if (!this.isPassengerOfSameVehicle(entity)) { ++ VehicleEntityCollisionEvent event = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + super.push(entity); + } + } else if (entity.getBoundingBox().minY <= this.getBoundingBox().minY) { ++ // CraftBukkit start ++ if (!this.isPassengerOfSameVehicle(entity)) { ++ VehicleEntityCollisionEvent event = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + super.push(entity); + } + +@@ -288,6 +325,7 @@ + return this.getDirection().getClockWise(); + } + ++ private Location lastLocation; // CraftBukkit + @Override + public void tick() { + this.oldStatus = this.status; +@@ -328,6 +366,22 @@ + this.setDeltaMovement(Vec3D.ZERO); + } + ++ // CraftBukkit start ++ org.bukkit.Server server = this.level().getCraftServer(); ++ org.bukkit.World bworld = this.level().getWorld(); ++ ++ Location to = CraftLocation.toBukkit(this.position(), bworld, this.getYRot(), this.getXRot()); ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ ++ server.getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleUpdateEvent(vehicle)); ++ ++ if (lastLocation != null && !lastLocation.equals(to)) { ++ VehicleMoveEvent event = new VehicleMoveEvent(vehicle, lastLocation, to); ++ server.getPluginManager().callEvent(event); ++ } ++ lastLocation = vehicle.getLocation(); ++ // CraftBukkit end ++ + this.tickBubbleColumn(); + + for (int i = 0; i <= 1; ++i) { +@@ -813,6 +867,11 @@ + + this.causeFallDamage(this.fallDistance, 1.0F, this.damageSources().fall()); + if (!this.level().isClientSide && !this.isRemoved()) { ++ // CraftBukkit start ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, null); ++ this.level().getCraftServer().getPluginManager().callEvent(destroyEvent); ++ if (!destroyEvent.isCancelled()) { + this.kill(); + if (this.level().getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { + int i; +@@ -826,6 +885,7 @@ + } + } + } ++ } // CraftBukkit end + } + + this.resetFallDistance(); diff --git a/patch-remap/og/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.patch b/patch-remap/og/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.patch new file mode 100644 index 0000000000..fa2f12d6d9 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.patch @@ -0,0 +1,208 @@ +--- a/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java ++++ b/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java +@@ -48,6 +48,14 @@ + import net.minecraft.world.phys.Vec3D; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.Vehicle; ++import org.bukkit.event.vehicle.VehicleEntityCollisionEvent; ++import org.bukkit.util.Vector; ++// CraftBukkit end ++ + public abstract class EntityMinecartAbstract extends VehicleEntity { + + private static final float LOWERED_PASSENGER_ATTACHMENT_Y = 0.0F; +@@ -88,6 +96,17 @@ + enummap.put(BlockPropertyTrackPosition.NORTH_EAST, Pair.of(baseblockposition2, baseblockposition1)); + }); + ++ // CraftBukkit start ++ public boolean slowWhenEmpty = true; ++ private double derailedX = 0.5; ++ private double derailedY = 0.5; ++ private double derailedZ = 0.5; ++ private double flyingX = 0.95; ++ private double flyingY = 0.95; ++ private double flyingZ = 0.95; ++ public double maxSpeed = 0.4D; ++ // CraftBukkit end ++ + protected EntityMinecartAbstract(EntityTypes entitytypes, World world) { + super(entitytypes, world); + this.targetDeltaMovement = Vec3D.ZERO; +@@ -128,7 +147,7 @@ + object = new EntityMinecartRideable(worldserver, d0, d1, d2); + } + +- Object object1 = object; ++ EntityMinecartAbstract object1 = (EntityMinecartAbstract) object; // CraftBukkit- decompile error + + EntityTypes.createDefaultStackConfig(worldserver, itemstack, entityhuman).accept(object1); + return (EntityMinecartAbstract) object1; +@@ -267,6 +286,14 @@ + + @Override + public void tick() { ++ // CraftBukkit start ++ double prevX = this.getX(); ++ double prevY = this.getY(); ++ double prevZ = this.getZ(); ++ float prevYaw = this.getYRot(); ++ float prevPitch = this.getXRot(); ++ // CraftBukkit end ++ + if (this.getHurtTime() > 0) { + this.setHurtTime(this.getHurtTime() - 1); + } +@@ -276,7 +303,7 @@ + } + + this.checkBelowWorld(); +- this.handleNetherPortal(); ++ // this.handleNetherPortal(); // CraftBukkit - handled in postTick + if (this.level().isClientSide) { + if (this.lerpSteps > 0) { + this.lerpPositionAndRotationStep(this.lerpSteps, this.lerpX, this.lerpY, this.lerpZ, this.lerpYRot, this.lerpXRot); +@@ -334,6 +361,18 @@ + } + + this.setRot(this.getYRot(), this.getXRot()); ++ // CraftBukkit start ++ org.bukkit.World bworld = this.level().getWorld(); ++ Location from = new Location(bworld, prevX, prevY, prevZ, prevYaw, prevPitch); ++ Location to = CraftLocation.toBukkit(this.position(), bworld, this.getYRot(), this.getXRot()); ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ ++ this.level().getCraftServer().getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleUpdateEvent(vehicle)); ++ ++ if (!from.equals(to)) { ++ this.level().getCraftServer().getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleMoveEvent(vehicle, from, to)); ++ } ++ // CraftBukkit end + if (this.getMinecartType() == EntityMinecartAbstract.EnumMinecartType.RIDEABLE && this.getDeltaMovement().horizontalDistanceSqr() > 0.01D) { + List list = this.level().getEntities((Entity) this, this.getBoundingBox().inflate(0.20000000298023224D, 0.0D, 0.20000000298023224D), IEntitySelector.pushableBy(this)); + +@@ -344,8 +383,26 @@ + Entity entity = (Entity) iterator.next(); + + if (!(entity instanceof EntityHuman) && !(entity instanceof EntityIronGolem) && !(entity instanceof EntityMinecartAbstract) && !this.isVehicle() && !entity.isPassenger()) { ++ // CraftBukkit start ++ VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(collisionEvent); ++ ++ if (collisionEvent.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end + entity.startRiding(this); + } else { ++ // CraftBukkit start ++ if (!this.isPassengerOfSameVehicle(entity)) { ++ VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(collisionEvent); ++ ++ if (collisionEvent.isCancelled()) { ++ continue; ++ } ++ } ++ // CraftBukkit end + entity.push(this); + } + } +@@ -357,6 +414,14 @@ + Entity entity1 = (Entity) iterator1.next(); + + if (!this.hasPassenger(entity1) && entity1.isPushable() && entity1 instanceof EntityMinecartAbstract) { ++ // CraftBukkit start ++ VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, entity1.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(collisionEvent); ++ ++ if (collisionEvent.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end + entity1.push(this); + } + } +@@ -373,7 +438,7 @@ + } + + protected double getMaxSpeed() { +- return (this.isInWater() ? 4.0D : 8.0D) / 20.0D; ++ return (this.isInWater() ? this.maxSpeed / 2.0D: this.maxSpeed); // CraftBukkit + } + + public void activateMinecart(int i, int j, int k, boolean flag) {} +@@ -384,12 +449,16 @@ + + this.setDeltaMovement(MathHelper.clamp(vec3d.x, -d0, d0), vec3d.y, MathHelper.clamp(vec3d.z, -d0, d0)); + if (this.onGround()) { +- this.setDeltaMovement(this.getDeltaMovement().scale(0.5D)); ++ // CraftBukkit start - replace magic numbers with our variables ++ this.setDeltaMovement(new Vec3D(this.getDeltaMovement().x * this.derailedX, this.getDeltaMovement().y * this.derailedY, this.getDeltaMovement().z * this.derailedZ)); ++ // CraftBukkit end + } + + this.move(EnumMoveType.SELF, this.getDeltaMovement()); + if (!this.onGround()) { +- this.setDeltaMovement(this.getDeltaMovement().scale(0.95D)); ++ // CraftBukkit start - replace magic numbers with our variables ++ this.setDeltaMovement(new Vec3D(this.getDeltaMovement().x * this.flyingX, this.getDeltaMovement().y * this.flyingY, this.getDeltaMovement().z * this.flyingZ)); ++ // CraftBukkit end + } + + } +@@ -585,7 +654,7 @@ + } + + protected void applyNaturalSlowdown() { +- double d0 = this.isVehicle() ? 0.997D : 0.96D; ++ double d0 = this.isVehicle() || !this.slowWhenEmpty ? 0.997D : 0.96D; // CraftBukkit - add !this.slowWhenEmpty + Vec3D vec3d = this.getDeltaMovement(); + + vec3d = vec3d.multiply(d0, 0.0D, d0); +@@ -724,6 +793,14 @@ + if (!this.level().isClientSide) { + if (!entity.noPhysics && !this.noPhysics) { + if (!this.hasPassenger(entity)) { ++ // CraftBukkit start ++ VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); ++ this.level().getCraftServer().getPluginManager().callEvent(collisionEvent); ++ ++ if (collisionEvent.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + double d0 = entity.getX() - this.getX(); + double d1 = entity.getZ() - this.getZ(); + double d2 = d0 * d0 + d1 * d1; +@@ -898,4 +975,26 @@ + + private EnumMinecartType() {} + } ++ ++ // CraftBukkit start - Methods for getting and setting flying and derailed velocity modifiers ++ public Vector getFlyingVelocityMod() { ++ return new Vector(flyingX, flyingY, flyingZ); ++ } ++ ++ public void setFlyingVelocityMod(Vector flying) { ++ flyingX = flying.getX(); ++ flyingY = flying.getY(); ++ flyingZ = flying.getZ(); ++ } ++ ++ public Vector getDerailedVelocityMod() { ++ return new Vector(derailedX, derailedY, derailedZ); ++ } ++ ++ public void setDerailedVelocityMod(Vector derailed) { ++ derailedX = derailed.getX(); ++ derailedY = derailed.getY(); ++ derailedZ = derailed.getZ(); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/entity/vehicle/EntityMinecartCommandBlock.patch b/patch-remap/og/net/minecraft/world/entity/vehicle/EntityMinecartCommandBlock.patch new file mode 100644 index 0000000000..fc124c7edf --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/vehicle/EntityMinecartCommandBlock.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/entity/vehicle/EntityMinecartCommandBlock.java ++++ b/net/minecraft/world/entity/vehicle/EntityMinecartCommandBlock.java +@@ -143,5 +143,12 @@ + public boolean isValid() { + return !EntityMinecartCommandBlock.this.isRemoved(); + } ++ ++ // CraftBukkit start ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandListenerWrapper wrapper) { ++ return (org.bukkit.craftbukkit.entity.CraftMinecartCommand) EntityMinecartCommandBlock.this.getBukkitEntity(); ++ } ++ // CraftBukkit end + } + } diff --git a/patch-remap/og/net/minecraft/world/entity/vehicle/EntityMinecartContainer.patch b/patch-remap/og/net/minecraft/world/entity/vehicle/EntityMinecartContainer.patch new file mode 100644 index 0000000000..b5693bdfa2 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/vehicle/EntityMinecartContainer.patch @@ -0,0 +1,75 @@ +--- a/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java ++++ b/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java +@@ -18,6 +18,14 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.World; + ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end ++ + public abstract class EntityMinecartContainer extends EntityMinecartAbstract implements ContainerEntity { + + private NonNullList itemStacks; +@@ -25,14 +33,55 @@ + public MinecraftKey lootTable; + public long lootTableSeed; + ++ // CraftBukkit start ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.itemStacks; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public InventoryHolder getOwner() { ++ org.bukkit.entity.Entity cart = getBukkitEntity(); ++ if(cart instanceof InventoryHolder) return (InventoryHolder) cart; ++ return null; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return getBukkitEntity().getLocation(); ++ } ++ // CraftBukkit end ++ + protected EntityMinecartContainer(EntityTypes entitytypes, World world) { + super(entitytypes, world); +- this.itemStacks = NonNullList.withSize(36, ItemStack.EMPTY); ++ this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); // CraftBukkit - SPIGOT-3513 + } + + protected EntityMinecartContainer(EntityTypes entitytypes, double d0, double d1, double d2, World world) { + super(entitytypes, world, d0, d1, d2); +- this.itemStacks = NonNullList.withSize(36, ItemStack.EMPTY); ++ this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); // CraftBukkit - SPIGOT-3513 + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/entity/vehicle/EntityMinecartTNT.patch b/patch-remap/og/net/minecraft/world/entity/vehicle/EntityMinecartTNT.patch new file mode 100644 index 0000000000..9e12da637f --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/vehicle/EntityMinecartTNT.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/entity/vehicle/EntityMinecartTNT.java ++++ b/net/minecraft/world/entity/vehicle/EntityMinecartTNT.java +@@ -23,6 +23,10 @@ + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.Fluid; + ++// CraftBukkit start ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end ++ + public class EntityMinecartTNT extends EntityMinecartAbstract { + + private static final byte EVENT_PRIME = 10; +@@ -115,7 +119,15 @@ + d1 = 5.0D; + } + +- this.level().explode(this, damagesource, (ExplosionDamageCalculator) null, this.getX(), this.getY(), this.getZ(), (float) (4.0D + this.random.nextDouble() * 1.5D * d1), false, World.a.TNT); ++ // CraftBukkit start ++ ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), (float) (4.0D + this.random.nextDouble() * 1.5D * d1), false); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ fuse = -1; ++ return; ++ } ++ this.level().explode(this, damagesource, (ExplosionDamageCalculator) null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), World.a.TNT); ++ // CraftBukkit end + this.discard(); + } + diff --git a/patch-remap/og/net/minecraft/world/entity/vehicle/VehicleEntity.patch b/patch-remap/og/net/minecraft/world/entity/vehicle/VehicleEntity.patch new file mode 100644 index 0000000000..ea7db6b296 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/entity/vehicle/VehicleEntity.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/entity/vehicle/VehicleEntity.java ++++ b/net/minecraft/world/entity/vehicle/VehicleEntity.java +@@ -13,6 +13,12 @@ + import net.minecraft.world.level.World; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.entity.Vehicle; ++import org.bukkit.event.vehicle.VehicleDamageEvent; ++import org.bukkit.event.vehicle.VehicleDestroyEvent; ++// CraftBukkit end ++ + public abstract class VehicleEntity extends Entity { + + protected static final DataWatcherObject DATA_ID_HURT = DataWatcher.defineId(VehicleEntity.class, DataWatcherRegistry.INT); +@@ -29,6 +35,18 @@ + if (this.isInvulnerableTo(damagesource)) { + return false; + } else { ++ // CraftBukkit start ++ Vehicle vehicle = (Vehicle) this.getBukkitEntity(); ++ org.bukkit.entity.Entity attacker = (damagesource.getEntity() == null) ? null : damagesource.getEntity().getBukkitEntity(); ++ ++ VehicleDamageEvent event = new VehicleDamageEvent(vehicle, attacker, (double) f); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ f = (float) event.getDamage(); ++ // CraftBukkit end + this.setHurtDir(-this.getHurtDir()); + this.setHurtTime(10); + this.markHurt(); +@@ -38,9 +56,27 @@ + + if ((flag || this.getDamage() <= 40.0F) && !this.shouldSourceDestroy(damagesource)) { + if (flag) { ++ // CraftBukkit start ++ VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, attacker); ++ this.level().getCraftServer().getPluginManager().callEvent(destroyEvent); ++ ++ if (destroyEvent.isCancelled()) { ++ this.setDamage(40.0F); // Maximize damage so this doesn't get triggered again right away ++ return true; ++ } ++ // CraftBukkit end + this.discard(); + } + } else { ++ // CraftBukkit start ++ VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, attacker); ++ this.level().getCraftServer().getPluginManager().callEvent(destroyEvent); ++ ++ if (destroyEvent.isCancelled()) { ++ this.setDamage(40.0F); // Maximize damage so this doesn't get triggered again right away ++ return true; ++ } ++ // CraftBukkit end + this.destroy(damagesource); + } + diff --git a/patch-remap/og/net/minecraft/world/food/FoodMetaData.patch b/patch-remap/og/net/minecraft/world/food/FoodMetaData.patch new file mode 100644 index 0000000000..ea2002c264 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/food/FoodMetaData.patch @@ -0,0 +1,106 @@ +--- a/net/minecraft/world/food/FoodMetaData.java ++++ b/net/minecraft/world/food/FoodMetaData.java +@@ -7,15 +7,33 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.GameRules; + ++// CraftBukkit start ++import net.minecraft.network.protocol.game.PacketPlayOutUpdateHealth; ++import net.minecraft.server.level.EntityPlayer; ++// CraftBukkit end ++ + public class FoodMetaData { + + public int foodLevel = 20; + public float saturationLevel = 5.0F; + public float exhaustionLevel; + private int tickTimer; ++ // CraftBukkit start ++ private EntityHuman entityhuman; ++ public int saturatedRegenRate = 10; ++ public int unsaturatedRegenRate = 80; ++ public int starvationRate = 80; ++ // CraftBukkit end + private int lastFoodLevel = 20; + +- public FoodMetaData() {} ++ public FoodMetaData() { throw new AssertionError("Whoopsie, we missed the bukkit."); } // CraftBukkit start - throw an error ++ ++ // CraftBukkit start - added EntityHuman constructor ++ public FoodMetaData(EntityHuman entityhuman) { ++ org.apache.commons.lang.Validate.notNull(entityhuman); ++ this.entityhuman = entityhuman; ++ } ++ // CraftBukkit end + + public void eat(int i, float f) { + this.foodLevel = Math.min(i + this.foodLevel, 20); +@@ -25,8 +43,17 @@ + public void eat(Item item, ItemStack itemstack) { + if (item.isEdible()) { + FoodInfo foodinfo = item.getFoodProperties(); ++ // CraftBukkit start ++ int oldFoodLevel = foodLevel; + +- this.eat(foodinfo.getNutrition(), foodinfo.getSaturationModifier()); ++ org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(entityhuman, foodinfo.getNutrition() + oldFoodLevel, itemstack); ++ ++ if (!event.isCancelled()) { ++ this.eat(event.getFoodLevel() - oldFoodLevel, foodinfo.getSaturationModifier()); ++ } ++ ++ ((EntityPlayer) entityhuman).getBukkitEntity().sendHealthUpdate(); ++ // CraftBukkit end + } + + } +@@ -40,7 +67,15 @@ + if (this.saturationLevel > 0.0F) { + this.saturationLevel = Math.max(this.saturationLevel - 1.0F, 0.0F); + } else if (enumdifficulty != EnumDifficulty.PEACEFUL) { +- this.foodLevel = Math.max(this.foodLevel - 1, 0); ++ // CraftBukkit start ++ org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(entityhuman, Math.max(this.foodLevel - 1, 0)); ++ ++ if (!event.isCancelled()) { ++ this.foodLevel = event.getFoodLevel(); ++ } ++ ++ ((EntityPlayer) entityhuman).connection.send(new PacketPlayOutUpdateHealth(((EntityPlayer) entityhuman).getBukkitEntity().getScaledHealth(), this.foodLevel, this.saturationLevel)); ++ // CraftBukkit end + } + } + +@@ -48,23 +83,25 @@ + + if (flag && this.saturationLevel > 0.0F && entityhuman.isHurt() && this.foodLevel >= 20) { + ++this.tickTimer; +- if (this.tickTimer >= 10) { ++ if (this.tickTimer >= this.saturatedRegenRate) { // CraftBukkit + float f = Math.min(this.saturationLevel, 6.0F); + +- entityhuman.heal(f / 6.0F); +- this.addExhaustion(f); ++ entityhuman.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED); // CraftBukkit - added RegainReason ++ // this.addExhaustion(f); CraftBukkit - EntityExhaustionEvent ++ entityhuman.causeFoodExhaustion(f, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.REGEN); // CraftBukkit - EntityExhaustionEvent + this.tickTimer = 0; + } + } else if (flag && this.foodLevel >= 18 && entityhuman.isHurt()) { + ++this.tickTimer; +- if (this.tickTimer >= 80) { +- entityhuman.heal(1.0F); +- this.addExhaustion(6.0F); ++ if (this.tickTimer >= this.unsaturatedRegenRate) { // CraftBukkit - add regen rate manipulation ++ entityhuman.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED); // CraftBukkit - added RegainReason ++ // this.a(6.0F); CraftBukkit - EntityExhaustionEvent ++ entityhuman.causeFoodExhaustion(6.0f, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.REGEN); // CraftBukkit - EntityExhaustionEvent + this.tickTimer = 0; + } + } else if (this.foodLevel <= 0) { + ++this.tickTimer; +- if (this.tickTimer >= 80) { ++ if (this.tickTimer >= this.starvationRate) { // CraftBukkit - add regen rate manipulation + if (entityhuman.getHealth() > 10.0F || enumdifficulty == EnumDifficulty.HARD || entityhuman.getHealth() > 1.0F && enumdifficulty == EnumDifficulty.NORMAL) { + entityhuman.hurt(entityhuman.damageSources().starve(), 1.0F); + } diff --git a/patch-remap/og/net/minecraft/world/inventory/Container.patch b/patch-remap/og/net/minecraft/world/inventory/Container.patch new file mode 100644 index 0000000000..483c8191b4 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/Container.patch @@ -0,0 +1,193 @@ +--- a/net/minecraft/world/inventory/Container.java ++++ b/net/minecraft/world/inventory/Container.java +@@ -33,6 +33,20 @@ + import net.minecraft.world.level.block.entity.TileEntity; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.google.common.base.Preconditions; ++import java.util.HashMap; ++import java.util.Map; ++import net.minecraft.network.chat.IChatBaseComponent; ++import net.minecraft.network.protocol.game.PacketPlayOutSetSlot; ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.Event.Result; ++import org.bukkit.event.inventory.InventoryDragEvent; ++import org.bukkit.event.inventory.InventoryType; ++import org.bukkit.inventory.InventoryView; ++// CraftBukkit end ++ + public abstract class Container { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -63,6 +77,27 @@ + private ContainerSynchronizer synchronizer; + private boolean suppressRemoteUpdates; + ++ // CraftBukkit start ++ public boolean checkReachable = true; ++ public abstract InventoryView getBukkitView(); ++ public void transferTo(Container other, org.bukkit.craftbukkit.entity.CraftHumanEntity player) { ++ InventoryView source = this.getBukkitView(), destination = other.getBukkitView(); ++ ((CraftInventory) source.getTopInventory()).getInventory().onClose(player); ++ ((CraftInventory) source.getBottomInventory()).getInventory().onClose(player); ++ ((CraftInventory) destination.getTopInventory()).getInventory().onOpen(player); ++ ((CraftInventory) destination.getBottomInventory()).getInventory().onOpen(player); ++ } ++ private IChatBaseComponent title; ++ public final IChatBaseComponent getTitle() { ++ Preconditions.checkState(this.title != null, "Title not set"); ++ return this.title; ++ } ++ public final void setTitle(IChatBaseComponent title) { ++ Preconditions.checkState(this.title == null, "Title already set"); ++ this.title = title; ++ } ++ // CraftBukkit end ++ + protected Container(@Nullable Containers containers, int i) { + this.carried = ItemStack.EMPTY; + this.remoteSlots = NonNullList.create(); +@@ -164,6 +199,15 @@ + + } + ++ // CraftBukkit start ++ public void broadcastCarriedItem() { ++ this.remoteCarried = this.getCarried().copy(); ++ if (this.synchronizer != null) { ++ this.synchronizer.sendCarriedChange(this, this.remoteCarried); ++ } ++ } ++ // CraftBukkit end ++ + public void removeSlotListener(ICrafting icrafting) { + this.containerListeners.remove(icrafting); + } +@@ -380,7 +424,7 @@ + } + } else if (this.quickcraftStatus == 2) { + if (!this.quickcraftSlots.isEmpty()) { +- if (this.quickcraftSlots.size() == 1) { ++ if (false && this.quickcraftSlots.size() == 1) { // CraftBukkit - treat everything as a drag since we are unable to easily call InventoryClickEvent instead + k = ((Slot) this.quickcraftSlots.iterator().next()).index; + this.resetQuickCraft(); + this.doClick(k, this.quickcraftType, InventoryClickType.PICKUP, entityhuman); +@@ -396,6 +440,7 @@ + l = this.getCarried().getCount(); + Iterator iterator = this.quickcraftSlots.iterator(); + ++ Map draggedSlots = new HashMap(); // CraftBukkit - Store slots from drag in map (raw slot id -> new stack) + while (iterator.hasNext()) { + Slot slot1 = (Slot) iterator.next(); + ItemStack itemstack2 = this.getCarried(); +@@ -406,12 +451,48 @@ + int l1 = Math.min(getQuickCraftPlaceCount(this.quickcraftSlots, this.quickcraftType, itemstack1) + j1, k1); + + l -= l1 - j1; +- slot1.setByPlayer(itemstack1.copyWithCount(l1)); ++ // slot1.setByPlayer(itemstack1.copyWithCount(l1)); ++ draggedSlots.put(slot1.index, itemstack1.copyWithCount(l1)); // CraftBukkit - Put in map instead of setting + } + } + +- itemstack1.setCount(l); +- this.setCarried(itemstack1); ++ // CraftBukkit start - InventoryDragEvent ++ InventoryView view = getBukkitView(); ++ org.bukkit.inventory.ItemStack newcursor = CraftItemStack.asCraftMirror(itemstack1); ++ newcursor.setAmount(l); ++ Map eventmap = new HashMap(); ++ for (Map.Entry ditem : draggedSlots.entrySet()) { ++ eventmap.put(ditem.getKey(), CraftItemStack.asBukkitCopy(ditem.getValue())); ++ } ++ ++ // It's essential that we set the cursor to the new value here to prevent item duplication if a plugin closes the inventory. ++ ItemStack oldCursor = this.getCarried(); ++ this.setCarried(CraftItemStack.asNMSCopy(newcursor)); ++ ++ InventoryDragEvent event = new InventoryDragEvent(view, (newcursor.getType() != org.bukkit.Material.AIR ? newcursor : null), CraftItemStack.asBukkitCopy(oldCursor), this.quickcraftType == 1, eventmap); ++ entityhuman.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ // Whether or not a change was made to the inventory that requires an update. ++ boolean needsUpdate = event.getResult() != Result.DEFAULT; ++ ++ if (event.getResult() != Result.DENY) { ++ for (Map.Entry dslot : draggedSlots.entrySet()) { ++ view.setItem(dslot.getKey(), CraftItemStack.asBukkitCopy(dslot.getValue())); ++ } ++ // The only time the carried item will be set to null is if the inventory is closed by the server. ++ // If the inventory is closed by the server, then the cursor items are dropped. This is why we change the cursor early. ++ if (this.getCarried() != null) { ++ this.setCarried(CraftItemStack.asNMSCopy(event.getCursor())); ++ needsUpdate = true; ++ } ++ } else { ++ this.setCarried(oldCursor); ++ } ++ ++ if (needsUpdate && entityhuman instanceof EntityPlayer) { ++ this.sendAllDataToRemote(); ++ } ++ // CraftBukkit end + } + + this.resetQuickCraft(); +@@ -429,8 +510,11 @@ + if (i == -999) { + if (!this.getCarried().isEmpty()) { + if (clickaction == ClickAction.PRIMARY) { +- entityhuman.drop(this.getCarried(), true); ++ // CraftBukkit start ++ ItemStack carried = this.getCarried(); + this.setCarried(ItemStack.EMPTY); ++ entityhuman.drop(carried, true); ++ // CraftBukkit start + } else { + entityhuman.drop(this.getCarried().split(1), true); + } +@@ -493,6 +577,15 @@ + } + + slot.setChanged(); ++ // CraftBukkit start - Make sure the client has the right slot contents ++ if (entityhuman instanceof EntityPlayer && slot.getMaxStackSize() != 64) { ++ ((EntityPlayer) entityhuman).connection.send(new PacketPlayOutSetSlot(this.containerId, this.incrementStateId(), slot.index, slot.getItem())); ++ // Updating a crafting inventory makes the client reset the result slot, have to send it again ++ if (this.getBukkitView().getType() == InventoryType.WORKBENCH || this.getBukkitView().getType() == InventoryType.CRAFTING) { ++ ((EntityPlayer) entityhuman).connection.send(new PacketPlayOutSetSlot(this.containerId, this.incrementStateId(), 0, this.getSlot(0).getItem())); ++ } ++ } ++ // CraftBukkit end + } + } else { + int j2; +@@ -609,13 +702,14 @@ + ItemStack itemstack = this.getCarried(); + + if (!itemstack.isEmpty()) { ++ this.setCarried(ItemStack.EMPTY); // CraftBukkit - SPIGOT-4556 - from below + if (entityhuman.isAlive() && !((EntityPlayer) entityhuman).hasDisconnected()) { + entityhuman.getInventory().placeItemBackInInventory(itemstack); + } else { + entityhuman.drop(itemstack, false); + } + +- this.setCarried(ItemStack.EMPTY); ++ // this.setCarried(ItemStack.EMPTY); // CraftBukkit - moved up + } + } + +@@ -832,6 +926,11 @@ + } + + public ItemStack getCarried() { ++ // CraftBukkit start ++ if (this.carried.isEmpty()) { ++ this.setCarried(ItemStack.EMPTY); ++ } ++ // CraftBukkit end + return this.carried; + } + diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerAccess.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerAccess.patch new file mode 100644 index 0000000000..72e419a336 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerAccess.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/world/inventory/ContainerAccess.java ++++ b/net/minecraft/world/inventory/ContainerAccess.java +@@ -8,6 +8,20 @@ + + public interface ContainerAccess { + ++ // CraftBukkit start ++ default World getWorld() { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ ++ default BlockPosition getPosition() { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ ++ default org.bukkit.Location getLocation() { ++ return new org.bukkit.Location(getWorld().getWorld(), getPosition().getX(), getPosition().getY(), getPosition().getZ()); ++ } ++ // CraftBukkit end ++ + ContainerAccess NULL = new ContainerAccess() { + @Override + public Optional evaluate(BiFunction bifunction) { +@@ -17,6 +31,18 @@ + + static ContainerAccess create(final World world, final BlockPosition blockposition) { + return new ContainerAccess() { ++ // CraftBukkit start ++ @Override ++ public World getWorld() { ++ return world; ++ } ++ ++ @Override ++ public BlockPosition getPosition() { ++ return blockposition; ++ } ++ // CraftBukkit end ++ + @Override + public Optional evaluate(BiFunction bifunction) { + return Optional.of(bifunction.apply(world, blockposition)); diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerAnvil.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerAnvil.patch new file mode 100644 index 0000000000..6565787448 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerAnvil.patch @@ -0,0 +1,131 @@ +--- a/net/minecraft/world/inventory/ContainerAnvil.java ++++ b/net/minecraft/world/inventory/ContainerAnvil.java +@@ -19,6 +19,10 @@ + import net.minecraft.world.level.block.state.IBlockData; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class ContainerAnvil extends ContainerAnvilAbstract { + + public static final int INPUT_SLOT = 0; +@@ -42,6 +46,11 @@ + private static final int ADDITIONAL_SLOT_X_PLACEMENT = 76; + private static final int RESULT_SLOT_X_PLACEMENT = 134; + private static final int SLOT_Y_PLACEMENT = 47; ++ // CraftBukkit start ++ public static final int DEFAULT_DENIED_COST = -1; ++ public int maximumRepairCost = 40; ++ private CraftInventoryView bukkitEntity; ++ // CraftBukkit end + + public ContainerAnvil(int i, PlayerInventory playerinventory) { + this(i, playerinventory, ContainerAccess.NULL); +@@ -69,7 +78,7 @@ + + @Override + protected boolean mayPickup(EntityHuman entityhuman, boolean flag) { +- return (entityhuman.getAbilities().instabuild || entityhuman.experienceLevel >= this.cost.get()) && this.cost.get() > 0; ++ return (entityhuman.getAbilities().instabuild || entityhuman.experienceLevel >= this.cost.get()) && this.cost.get() > ContainerAnvil.DEFAULT_DENIED_COST && flag; // CraftBukkit - allow cost 0 like a free item + } + + @Override +@@ -92,7 +101,7 @@ + this.inputSlots.setItem(1, ItemStack.EMPTY); + } + +- this.cost.set(0); ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + this.access.execute((world, blockposition) -> { + IBlockData iblockdata = world.getBlockState(blockposition); + +@@ -123,8 +132,8 @@ + byte b1 = 0; + + if (itemstack.isEmpty()) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- this.cost.set(0); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + } else { + ItemStack itemstack1 = itemstack.copy(); + ItemStack itemstack2 = this.inputSlots.getItem(1); +@@ -141,8 +150,8 @@ + if (itemstack1.isDamageableItem() && itemstack1.getItem().isValidRepairItem(itemstack, itemstack2)) { + k = Math.min(itemstack1.getDamageValue(), itemstack1.getMaxDamage() / 4); + if (k <= 0) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- this.cost.set(0); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + return; + } + +@@ -156,8 +165,8 @@ + this.repairItemCountCost = i1; + } else { + if (!flag && (!itemstack1.is(itemstack2.getItem()) || !itemstack1.isDamageableItem())) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- this.cost.set(0); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + return; + } + +@@ -246,8 +255,8 @@ + } + + if (flag2 && !flag1) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); +- this.cost.set(0); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit ++ this.cost.set(DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item + return; + } + } +@@ -270,11 +279,11 @@ + itemstack1 = ItemStack.EMPTY; + } + +- if (b1 == i && b1 > 0 && this.cost.get() >= 40) { +- this.cost.set(39); ++ if (b1 == i && b1 > 0 && this.cost.get() >= maximumRepairCost) { // CraftBukkit ++ this.cost.set(maximumRepairCost - 1); // CraftBukkit + } + +- if (this.cost.get() >= 40 && !this.player.getAbilities().instabuild) { ++ if (this.cost.get() >= maximumRepairCost && !this.player.getAbilities().instabuild) { // CraftBukkit + itemstack1 = ItemStack.EMPTY; + } + +@@ -293,7 +302,8 @@ + EnchantmentManager.setEnchantments(map, itemstack1); + } + +- this.resultSlots.setItem(0, itemstack1); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), itemstack1); // CraftBukkit ++ sendAllDataToRemote(); // CraftBukkit - SPIGOT-6686: Always send completed inventory to stay in sync with client + this.broadcastChanges(); + } + } +@@ -334,4 +344,18 @@ + public int getCost() { + return this.cost.get(); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventory inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryAnvil( ++ access.getLocation(), this.inputSlots, this.resultSlots, this); ++ bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerAnvilAbstract.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerAnvilAbstract.patch new file mode 100644 index 0000000000..e90413e53d --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerAnvilAbstract.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/world/inventory/ContainerAnvilAbstract.java ++++ b/net/minecraft/world/inventory/ContainerAnvilAbstract.java +@@ -124,6 +124,7 @@ + + @Override + public boolean stillValid(EntityHuman entityhuman) { ++ if (!this.checkReachable) return true; // CraftBukkit + return (Boolean) this.access.evaluate((world, blockposition) -> { + return !this.isValidBlock(world.getBlockState(blockposition)) ? false : entityhuman.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) <= 64.0D; + }, true); diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerBeacon.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerBeacon.patch new file mode 100644 index 0000000000..c416f96192 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerBeacon.patch @@ -0,0 +1,70 @@ +--- a/net/minecraft/world/inventory/ContainerBeacon.java ++++ b/net/minecraft/world/inventory/ContainerBeacon.java +@@ -12,6 +12,11 @@ + import net.minecraft.world.level.World; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import net.minecraft.world.entity.player.PlayerInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class ContainerBeacon extends Container { + + private static final int PAYMENT_SLOT = 0; +@@ -26,6 +31,10 @@ + private final ContainerBeacon.SlotBeacon paymentSlot; + private final ContainerAccess access; + private final IContainerProperties beaconData; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private PlayerInventory player; ++ // CraftBukkit end + + public ContainerBeacon(int i, IInventory iinventory) { + this(i, iinventory, new ContainerProperties(3), ContainerAccess.NULL); +@@ -33,6 +42,7 @@ + + public ContainerBeacon(int i, IInventory iinventory, IContainerProperties icontainerproperties, ContainerAccess containeraccess) { + super(Containers.BEACON, i); ++ player = (PlayerInventory) iinventory; // CraftBukkit - TODO: check this + this.beacon = new InventorySubcontainer(1) { + @Override + public boolean canPlaceItem(int j, ItemStack itemstack) { +@@ -82,6 +92,7 @@ + + @Override + public boolean stillValid(EntityHuman entityhuman) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, entityhuman, Blocks.BEACON); + } + +@@ -163,8 +174,8 @@ + + public void updateEffects(Optional optional, Optional optional1) { + if (this.paymentSlot.hasItem()) { +- this.beaconData.set(1, encodeEffect((MobEffectList) optional.orElse((Object) null))); +- this.beaconData.set(2, encodeEffect((MobEffectList) optional1.orElse((Object) null))); ++ this.beaconData.set(1, encodeEffect((MobEffectList) optional.orElse(null))); // CraftBukkit - decompile error ++ this.beaconData.set(2, encodeEffect((MobEffectList) optional1.orElse(null))); // CraftBukkit - decompile error + this.paymentSlot.remove(1); + this.access.execute(World::blockEntityChanged); + } +@@ -191,4 +202,17 @@ + return 1; + } + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventory inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryBeacon(this.beacon); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerBrewingStand.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerBrewingStand.patch new file mode 100644 index 0000000000..9fa2aa3fdd --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerBrewingStand.patch @@ -0,0 +1,59 @@ +--- a/net/minecraft/world/inventory/ContainerBrewingStand.java ++++ b/net/minecraft/world/inventory/ContainerBrewingStand.java +@@ -13,6 +13,11 @@ + import net.minecraft.world.item.alchemy.PotionRegistry; + import net.minecraft.world.item.alchemy.PotionUtil; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryBrewer; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class ContainerBrewingStand extends Container { + + private static final int BOTTLE_SLOT_START = 0; +@@ -29,12 +34,18 @@ + private final IContainerProperties brewingStandData; + private final Slot ingredientSlot; + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private PlayerInventory player; ++ // CraftBukkit end ++ + public ContainerBrewingStand(int i, PlayerInventory playerinventory) { + this(i, playerinventory, new InventorySubcontainer(5), new ContainerProperties(2)); + } + + public ContainerBrewingStand(int i, PlayerInventory playerinventory, IInventory iinventory, IContainerProperties icontainerproperties) { + super(Containers.BREWING_STAND, i); ++ player = playerinventory; // CraftBukkit + checkContainerSize(iinventory, 5); + checkContainerDataCount(icontainerproperties, 2); + this.brewingStand = iinventory; +@@ -62,6 +73,7 @@ + + @Override + public boolean stillValid(EntityHuman entityhuman) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.brewingStand.stillValid(entityhuman); + } + +@@ -199,4 +211,17 @@ + return 64; + } + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryBrewer inventory = new CraftInventoryBrewer(this.brewingStand); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerCartography.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerCartography.patch new file mode 100644 index 0000000000..0a48c9eda0 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerCartography.patch @@ -0,0 +1,74 @@ +--- a/net/minecraft/world/inventory/ContainerCartography.java ++++ b/net/minecraft/world/inventory/ContainerCartography.java +@@ -12,8 +12,30 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.saveddata.maps.WorldMap; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.inventory.CraftInventoryCartography; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++// CraftBukkit end ++ + public class ContainerCartography extends Container { + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryCartography inventory = new CraftInventoryCartography(this.container, this.resultContainer); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + public static final int MAP_SLOT = 0; + public static final int ADDITIONAL_SLOT = 1; + public static final int RESULT_SLOT = 2; +@@ -38,6 +60,13 @@ + ContainerCartography.this.slotsChanged(this); + super.setChanged(); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return containeraccess.getLocation(); ++ } ++ // CraftBukkit end + }; + this.resultContainer = new InventoryCraftResult() { + @Override +@@ -45,6 +74,13 @@ + ContainerCartography.this.slotsChanged(this); + super.setChanged(); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return containeraccess.getLocation(); ++ } ++ // CraftBukkit end + }; + this.access = containeraccess; + this.addSlot(new Slot(this.container, 0, 15, 15) { +@@ -95,10 +131,12 @@ + this.addSlot(new Slot(playerinventory, j, 8 + j * 18, 142)); + } + ++ player = (Player) playerinventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override + public boolean stillValid(EntityHuman entityhuman) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, entityhuman, Blocks.CARTOGRAPHY_TABLE); + } + diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerChest.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerChest.patch new file mode 100644 index 0000000000..e955215fd1 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerChest.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/inventory/ContainerChest.java ++++ b/net/minecraft/world/inventory/ContainerChest.java +@@ -6,11 +6,40 @@ + import net.minecraft.world.entity.player.PlayerInventory; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import net.minecraft.world.InventoryLargeChest; ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class ContainerChest extends Container { + + private static final int SLOTS_PER_ROW = 9; + private final IInventory container; + private final int containerRows; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private PlayerInventory player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventory inventory; ++ if (this.container instanceof PlayerInventory) { ++ inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryPlayer((PlayerInventory) this.container); ++ } else if (this.container instanceof InventoryLargeChest) { ++ inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) this.container); ++ } else { ++ inventory = new CraftInventory(this.container); ++ } ++ ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + + private ContainerChest(Containers containers, int i, PlayerInventory playerinventory, int j) { + this(containers, i, playerinventory, new InventorySubcontainer(9 * j), j); +@@ -56,6 +85,10 @@ + iinventory.startOpen(playerinventory.player); + int k = (this.containerRows - 4) * 18; + ++ // CraftBukkit start - Save player ++ this.player = playerinventory; ++ // CraftBukkit end ++ + int l; + int i1; + +@@ -79,6 +112,7 @@ + + @Override + public boolean stillValid(EntityHuman entityhuman) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(entityhuman); + } + diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerDispenser.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerDispenser.patch new file mode 100644 index 0000000000..a678f092ce --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerDispenser.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/inventory/ContainerDispenser.java ++++ b/net/minecraft/world/inventory/ContainerDispenser.java +@@ -6,6 +6,11 @@ + import net.minecraft.world.entity.player.PlayerInventory; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class ContainerDispenser extends Container { + + private static final int SLOT_COUNT = 9; +@@ -14,6 +19,10 @@ + private static final int USE_ROW_SLOT_START = 36; + private static final int USE_ROW_SLOT_END = 45; + public final IInventory dispenser; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private PlayerInventory player; ++ // CraftBukkit end + + public ContainerDispenser(int i, PlayerInventory playerinventory) { + this(i, playerinventory, new InventorySubcontainer(9)); +@@ -21,6 +30,10 @@ + + public ContainerDispenser(int i, PlayerInventory playerinventory, IInventory iinventory) { + super(Containers.GENERIC_3x3, i); ++ // CraftBukkit start - Save player ++ this.player = playerinventory; ++ // CraftBukkit end ++ + checkContainerSize(iinventory, 9); + this.dispenser = iinventory; + iinventory.startOpen(playerinventory.player); +@@ -48,6 +61,7 @@ + + @Override + public boolean stillValid(EntityHuman entityhuman) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.dispenser.stillValid(entityhuman); + } + +@@ -89,4 +103,17 @@ + super.removed(entityhuman); + this.dispenser.stopOpen(entityhuman); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventory inventory = new CraftInventory(this.dispenser); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerEnchantTable.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerEnchantTable.patch new file mode 100644 index 0000000000..4775eabe34 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerEnchantTable.patch @@ -0,0 +1,203 @@ +--- a/net/minecraft/world/inventory/ContainerEnchantTable.java ++++ b/net/minecraft/world/inventory/ContainerEnchantTable.java +@@ -27,6 +27,21 @@ + import net.minecraft.world.level.block.BlockEnchantmentTable; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import java.util.Map; ++import net.minecraft.world.item.enchantment.Enchantment; ++import org.bukkit.Location; ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftInventoryEnchanting; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.enchantments.EnchantmentOffer; ++import org.bukkit.event.enchantment.EnchantItemEvent; ++import org.bukkit.event.enchantment.PrepareItemEnchantEvent; ++import org.bukkit.entity.Player; ++// CraftBukkit end ++ + public class ContainerEnchantTable extends Container { + + static final MinecraftKey EMPTY_SLOT_LAPIS_LAZULI = new MinecraftKey("item/empty_slot_lapis_lazuli"); +@@ -37,6 +52,10 @@ + public final int[] costs; + public final int[] enchantClue; + public final int[] levelClue; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ // CraftBukkit end + + public ContainerEnchantTable(int i, PlayerInventory playerinventory) { + this(i, playerinventory, ContainerAccess.NULL); +@@ -50,6 +69,13 @@ + super.setChanged(); + ContainerEnchantTable.this.slotsChanged(this); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return containeraccess.getLocation(); ++ } ++ // CraftBukkit end + }; + this.random = RandomSource.create(); + this.enchantmentSeed = ContainerProperty.standalone(); +@@ -97,6 +123,9 @@ + this.addDataSlot(ContainerProperty.shared(this.levelClue, 0)); + this.addDataSlot(ContainerProperty.shared(this.levelClue, 1)); + this.addDataSlot(ContainerProperty.shared(this.levelClue, 2)); ++ // CraftBukkit start ++ player = (Player) playerinventory.player.getBukkitEntity(); ++ // CraftBukkit end + } + + @Override +@@ -104,7 +133,7 @@ + if (iinventory == this.enchantSlots) { + ItemStack itemstack = iinventory.getItem(0); + +- if (!itemstack.isEmpty() && itemstack.isEnchantable()) { ++ if (!itemstack.isEmpty()) { // CraftBukkit - relax condition + this.access.execute((world, blockposition) -> { + int i = 0; + Iterator iterator = BlockEnchantmentTable.BOOKSHELF_OFFSETS.iterator(); +@@ -143,6 +172,41 @@ + } + } + ++ // CraftBukkit start ++ CraftItemStack item = CraftItemStack.asCraftMirror(itemstack); ++ org.bukkit.enchantments.EnchantmentOffer[] offers = new EnchantmentOffer[3]; ++ for (j = 0; j < 3; ++j) { ++ org.bukkit.enchantments.Enchantment enchantment = (this.enchantClue[j] >= 0) ? org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(BuiltInRegistries.ENCHANTMENT.byId(this.enchantClue[j])))) : null; ++ offers[j] = (enchantment != null) ? new EnchantmentOffer(enchantment, this.levelClue[j], this.costs[j]) : null; ++ } ++ ++ PrepareItemEnchantEvent event = new PrepareItemEnchantEvent(player, this.getBukkitView(), access.getLocation().getBlock(), item, offers, i); ++ event.setCancelled(!itemstack.isEnchantable()); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ for (j = 0; j < 3; ++j) { ++ this.costs[j] = 0; ++ this.enchantClue[j] = -1; ++ this.levelClue[j] = -1; ++ } ++ return; ++ } ++ ++ for (j = 0; j < 3; j++) { ++ EnchantmentOffer offer = event.getOffers()[j]; ++ if (offer != null) { ++ this.costs[j] = offer.getCost(); ++ this.enchantClue[j] = BuiltInRegistries.ENCHANTMENT.getId(BuiltInRegistries.ENCHANTMENT.get(CraftNamespacedKey.toMinecraft(offer.getEnchantment().getKey()))); ++ this.levelClue[j] = offer.getEnchantmentLevel(); ++ } else { ++ this.costs[j] = 0; ++ this.enchantClue[j] = -1; ++ this.levelClue[j] = -1; ++ } ++ } ++ // CraftBukkit end ++ + this.broadcastChanges(); + }); + } else { +@@ -170,8 +234,25 @@ + ItemStack itemstack2 = itemstack; + List list = this.getEnchantmentList(itemstack, i, this.costs[i]); + +- if (!list.isEmpty()) { +- entityhuman.onEnchantmentPerformed(itemstack, j); ++ // CraftBukkit start ++ if (true || !list.isEmpty()) { ++ // entityhuman.onEnchantmentPerformed(itemstack, j); // Moved down ++ Map enchants = new java.util.HashMap(); ++ for (WeightedRandomEnchant instance : list) { ++ enchants.put(org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(instance.enchantment))), instance.level); ++ } ++ CraftItemStack item = CraftItemStack.asCraftMirror(itemstack2); ++ ++ org.bukkit.enchantments.Enchantment hintedEnchantment = org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(Enchantment.byId(enchantClue[i])))); ++ int hintedEnchantmentLevel = levelClue[i]; ++ EnchantItemEvent event = new EnchantItemEvent((Player) entityhuman.getBukkitEntity(), this.getBukkitView(), access.getLocation().getBlock(), item, this.costs[i], enchants, hintedEnchantment, hintedEnchantmentLevel, i); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ int level = event.getExpLevelCost(); ++ if (event.isCancelled() || (level > entityhuman.experienceLevel && !entityhuman.getAbilities().instabuild) || event.getEnchantsToAdd().isEmpty()) { ++ return; ++ } ++ // CraftBukkit end + boolean flag = itemstack.is(Items.BOOK); + + if (flag) { +@@ -185,18 +266,30 @@ + this.enchantSlots.setItem(0, itemstack2); + } + +- Iterator iterator = list.iterator(); +- +- while (iterator.hasNext()) { +- WeightedRandomEnchant weightedrandomenchant = (WeightedRandomEnchant) iterator.next(); ++ // CraftBukkit start ++ for (Map.Entry entry : event.getEnchantsToAdd().entrySet()) { ++ try { ++ if (flag) { ++ NamespacedKey enchantId = entry.getKey().getKey(); ++ Enchantment nms = BuiltInRegistries.ENCHANTMENT.get(CraftNamespacedKey.toMinecraft(enchantId)); ++ if (nms == null) { ++ continue; ++ } + +- if (flag) { +- ItemEnchantedBook.addEnchantment(itemstack2, weightedrandomenchant); +- } else { +- itemstack2.enchant(weightedrandomenchant.enchantment, weightedrandomenchant.level); ++ WeightedRandomEnchant weightedrandomenchant = new WeightedRandomEnchant(nms, entry.getValue()); ++ ItemEnchantedBook.addEnchantment(itemstack2, weightedrandomenchant); ++ } else { ++ item.addUnsafeEnchantment(entry.getKey(), entry.getValue()); ++ } ++ } catch (IllegalArgumentException e) { ++ /* Just swallow invalid enchantments */ + } + } + ++ entityhuman.onEnchantmentPerformed(itemstack, j); ++ // CraftBukkit end ++ ++ // CraftBukkit - TODO: let plugins change this + if (!entityhuman.getAbilities().instabuild) { + itemstack1.shrink(j); + if (itemstack1.isEmpty()) { +@@ -259,6 +352,7 @@ + + @Override + public boolean stillValid(EntityHuman entityhuman) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, entityhuman, Blocks.ENCHANTING_TABLE); + } + +@@ -309,4 +403,17 @@ + + return itemstack; + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryEnchanting inventory = new CraftInventoryEnchanting(this.enchantSlots); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerFurnace.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerFurnace.patch new file mode 100644 index 0000000000..12f662acb0 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerFurnace.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/inventory/ContainerFurnace.java ++++ b/net/minecraft/world/inventory/ContainerFurnace.java +@@ -14,6 +14,11 @@ + import net.minecraft.world.level.World; + import net.minecraft.world.level.block.entity.TileEntityFurnace; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryFurnace; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public abstract class ContainerFurnace extends ContainerRecipeBook { + + public static final int INGREDIENT_SLOT = 0; +@@ -31,6 +36,22 @@ + private final Recipes recipeType; + private final RecipeBookType recipeBookType; + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private PlayerInventory player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryFurnace inventory = new CraftInventoryFurnace((TileEntityFurnace) this.container); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end ++ + protected ContainerFurnace(Containers containers, Recipes recipes, RecipeBookType recipebooktype, int i, PlayerInventory playerinventory) { + this(containers, recipes, recipebooktype, i, playerinventory, new InventorySubcontainer(3), new ContainerProperties(4)); + } +@@ -47,6 +68,7 @@ + this.addSlot(new Slot(iinventory, 0, 56, 17)); + this.addSlot(new SlotFurnaceFuel(this, iinventory, 1, 56, 53)); + this.addSlot(new SlotFurnaceResult(playerinventory.player, iinventory, 2, 116, 35)); ++ this.player = playerinventory; // CraftBukkit - save player + + int j; + +@@ -104,6 +126,7 @@ + + @Override + public boolean stillValid(EntityHuman entityhuman) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(entityhuman); + } + +@@ -159,7 +182,7 @@ + } + + protected boolean canSmelt(ItemStack itemstack) { +- return this.level.getRecipeManager().getRecipeFor(this.recipeType, new InventorySubcontainer(new ItemStack[]{itemstack}), this.level).isPresent(); ++ return this.level.getRecipeManager().getRecipeFor((Recipes) this.recipeType, new InventorySubcontainer(new ItemStack[]{itemstack}), this.level).isPresent(); // Eclipse fail + } + + protected boolean isFuel(ItemStack itemstack) { diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerGrindstone.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerGrindstone.patch new file mode 100644 index 0000000000..7569ed90a7 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerGrindstone.patch @@ -0,0 +1,106 @@ +--- a/net/minecraft/world/inventory/ContainerGrindstone.java ++++ b/net/minecraft/world/inventory/ContainerGrindstone.java +@@ -19,8 +19,30 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.inventory.CraftInventoryGrindstone; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++// CraftBukkit end ++ + public class ContainerGrindstone extends Container { + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryGrindstone inventory = new CraftInventoryGrindstone(this.repairSlots, this.resultSlots); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + public static final int MAX_NAME_LENGTH = 35; + public static final int INPUT_SLOT = 0; + public static final int ADDITIONAL_SLOT = 1; +@@ -46,6 +68,13 @@ + super.setChanged(); + ContainerGrindstone.this.slotsChanged(this); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return containeraccess.getLocation(); ++ } ++ // CraftBukkit end + }; + this.access = containeraccess; + this.addSlot(new Slot(this.repairSlots, 0, 49, 19) { +@@ -124,6 +153,7 @@ + this.addSlot(new Slot(playerinventory, j, 8 + j * 18, 142)); + } + ++ player = (Player) playerinventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override +@@ -145,7 +175,7 @@ + boolean flag2 = !itemstack.isEmpty() && !itemstack.is(Items.ENCHANTED_BOOK) && !itemstack.isEnchanted() || !itemstack1.isEmpty() && !itemstack1.is(Items.ENCHANTED_BOOK) && !itemstack1.isEnchanted(); + + if (itemstack.getCount() > 1 || itemstack1.getCount() > 1 || !flag1 && flag2) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + this.broadcastChanges(); + return; + } +@@ -156,7 +186,7 @@ + + if (flag1) { + if (!itemstack.is(itemstack1.getItem())) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + this.broadcastChanges(); + return; + } +@@ -170,7 +200,7 @@ + itemstack2 = this.mergeEnchants(itemstack, itemstack1); + if (!itemstack2.isDamageableItem()) { + if (!ItemStack.matches(itemstack, itemstack1)) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + this.broadcastChanges(); + return; + } +@@ -183,12 +213,12 @@ + i = flag3 ? itemstack.getDamageValue() : itemstack1.getDamageValue(); + itemstack2 = flag3 ? itemstack : itemstack1; + } +- +- this.resultSlots.setItem(0, this.removeNonCurses(itemstack2, i, b0)); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), this.removeNonCurses(itemstack2, i, b0)); // CraftBukkit + } else { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + } + ++ sendAllDataToRemote(); // CraftBukkit - SPIGOT-6686: Always send completed inventory to stay in sync with client + this.broadcastChanges(); + } + +@@ -250,6 +280,7 @@ + + @Override + public boolean stillValid(EntityHuman entityhuman) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, entityhuman, Blocks.GRINDSTONE); + } + diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerHopper.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerHopper.patch new file mode 100644 index 0000000000..1a6a55058d --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerHopper.patch @@ -0,0 +1,51 @@ +--- a/net/minecraft/world/inventory/ContainerHopper.java ++++ b/net/minecraft/world/inventory/ContainerHopper.java +@@ -6,11 +6,32 @@ + import net.minecraft.world.entity.player.PlayerInventory; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class ContainerHopper extends Container { + + public static final int CONTAINER_SIZE = 5; + private final IInventory hopper; + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private PlayerInventory player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventory inventory = new CraftInventory(this.hopper); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end ++ + public ContainerHopper(int i, PlayerInventory playerinventory) { + this(i, playerinventory, new InventorySubcontainer(5)); + } +@@ -18,6 +39,7 @@ + public ContainerHopper(int i, PlayerInventory playerinventory, IInventory iinventory) { + super(Containers.HOPPER, i); + this.hopper = iinventory; ++ this.player = playerinventory; // CraftBukkit - save player + checkContainerSize(iinventory, 5); + iinventory.startOpen(playerinventory.player); + boolean flag = true; +@@ -42,6 +64,7 @@ + + @Override + public boolean stillValid(EntityHuman entityhuman) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.hopper.stillValid(entityhuman); + } + diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerHorse.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerHorse.patch new file mode 100644 index 0000000000..062a5c8d6d --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerHorse.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/world/inventory/ContainerHorse.java ++++ b/net/minecraft/world/inventory/ContainerHorse.java +@@ -8,13 +8,33 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.inventory.InventoryView; ++// CraftBukkit end ++ + public class ContainerHorse extends Container { + + private final IInventory horseContainer; + private final EntityHorseAbstract horse; + ++ // CraftBukkit start ++ org.bukkit.craftbukkit.inventory.CraftInventoryView bukkitEntity; ++ PlayerInventory player; ++ ++ @Override ++ public InventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ return bukkitEntity = new CraftInventoryView(player.player.getBukkitEntity(), horseContainer.getOwner().getInventory(), this); ++ } ++ + public ContainerHorse(int i, PlayerInventory playerinventory, IInventory iinventory, final EntityHorseAbstract entityhorseabstract) { + super((Containers) null, i); ++ player = playerinventory; ++ // CraftBukkit end + this.horseContainer = iinventory; + this.horse = entityhorseabstract; + boolean flag = true; diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerLectern.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerLectern.patch new file mode 100644 index 0000000000..795ee21d6d --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerLectern.patch @@ -0,0 +1,84 @@ +--- a/net/minecraft/world/inventory/ContainerLectern.java ++++ b/net/minecraft/world/inventory/ContainerLectern.java +@@ -5,8 +5,33 @@ + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import net.minecraft.world.level.block.entity.TileEntityLectern.LecternInventory; ++import net.minecraft.world.entity.player.PlayerInventory; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.inventory.CraftInventoryLectern; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++import org.bukkit.event.player.PlayerTakeLecternBookEvent; ++// CraftBukkit end ++ + public class ContainerLectern extends Container { + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryLectern inventory = new CraftInventoryLectern(this.lectern); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + private static final int DATA_COUNT = 1; + private static final int SLOT_COUNT = 1; + public static final int BUTTON_PREV_PAGE = 1; +@@ -16,11 +41,13 @@ + private final IInventory lectern; + private final IContainerProperties lecternData; + +- public ContainerLectern(int i) { +- this(i, new InventorySubcontainer(1), new ContainerProperties(1)); ++ // CraftBukkit start - add player ++ public ContainerLectern(int i, PlayerInventory playerinventory) { ++ this(i, new InventorySubcontainer(1), new ContainerProperties(1), playerinventory); + } + +- public ContainerLectern(int i, IInventory iinventory, IContainerProperties icontainerproperties) { ++ public ContainerLectern(int i, IInventory iinventory, IContainerProperties icontainerproperties, PlayerInventory playerinventory) { ++ // CraftBukkit end + super(Containers.LECTERN, i); + checkContainerSize(iinventory, 1); + checkContainerDataCount(icontainerproperties, 1); +@@ -34,6 +61,7 @@ + } + }); + this.addDataSlots(icontainerproperties); ++ player = (Player) playerinventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override +@@ -59,6 +87,13 @@ + return false; + } + ++ // CraftBukkit start - Event for taking the book ++ PlayerTakeLecternBookEvent event = new PlayerTakeLecternBookEvent(player, ((CraftInventoryLectern) getBukkitView().getTopInventory()).getHolder()); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end + ItemStack itemstack = this.lectern.removeItemNoUpdate(0); + + this.lectern.setChanged(); +@@ -86,6 +121,8 @@ + + @Override + public boolean stillValid(EntityHuman entityhuman) { ++ if (lectern instanceof LecternInventory && !((LecternInventory) lectern).getLectern().hasBook()) return false; // CraftBukkit ++ if (!this.checkReachable) return true; // CraftBukkit + return this.lectern.stillValid(entityhuman); + } + diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerLoom.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerLoom.patch new file mode 100644 index 0000000000..858325140c --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerLoom.patch @@ -0,0 +1,86 @@ +--- a/net/minecraft/world/inventory/ContainerLoom.java ++++ b/net/minecraft/world/inventory/ContainerLoom.java +@@ -24,8 +24,30 @@ + import net.minecraft.world.level.block.entity.EnumBannerPatternType; + import net.minecraft.world.level.block.entity.TileEntityTypes; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.inventory.CraftInventoryLoom; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++// CraftBukkit end ++ + public class ContainerLoom extends Container { + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryLoom inventory = new CraftInventoryLoom(this.inputContainer, this.outputContainer); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + private static final int PATTERN_NOT_SET = -1; + private static final int INV_SLOT_START = 4; + private static final int INV_SLOT_END = 31; +@@ -60,6 +82,13 @@ + ContainerLoom.this.slotsChanged(this); + ContainerLoom.this.slotUpdateListener.run(); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return containeraccess.getLocation(); ++ } ++ // CraftBukkit end + }; + this.outputContainer = new InventorySubcontainer(1) { + @Override +@@ -67,6 +96,13 @@ + super.setChanged(); + ContainerLoom.this.slotUpdateListener.run(); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return containeraccess.getLocation(); ++ } ++ // CraftBukkit end + }; + this.access = containeraccess; + this.bannerSlot = this.addSlot(new Slot(this.inputContainer, 0, 13, 26) { +@@ -127,10 +163,12 @@ + } + + this.addDataSlot(this.selectedBannerPatternIndex); ++ player = (Player) playerinventory.player.getBukkitEntity(); // CraftBukkit + } + + @Override + public boolean stillValid(EntityHuman entityhuman) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, entityhuman, Blocks.LOOM); + } + +@@ -308,6 +346,11 @@ + + if (nbttagcompound != null && nbttagcompound.contains("Patterns", 9)) { + nbttaglist = nbttagcompound.getList("Patterns", 10); ++ // CraftBukkit start ++ while (nbttaglist.size() > 20) { ++ nbttaglist.remove(20); ++ } ++ // CraftBukkit end + } else { + nbttaglist = new NBTTagList(); + if (nbttagcompound == null) { diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerMerchant.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerMerchant.patch new file mode 100644 index 0000000000..0d7382d66f --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerMerchant.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/world/inventory/ContainerMerchant.java ++++ b/net/minecraft/world/inventory/ContainerMerchant.java +@@ -12,6 +12,8 @@ + import net.minecraft.world.item.trading.MerchantRecipe; + import net.minecraft.world.item.trading.MerchantRecipeList; + ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; // CraftBukkit ++ + public class ContainerMerchant extends Container { + + protected static final int PAYMENT1_SLOT = 0; +@@ -31,6 +33,19 @@ + private boolean showProgressBar; + private boolean canRestock; + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private PlayerInventory player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity == null) { ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), new org.bukkit.craftbukkit.inventory.CraftInventoryMerchant(trader, tradeContainer), this); ++ } ++ return bukkitEntity; ++ } ++ // CraftBukkit end ++ + public ContainerMerchant(int i, PlayerInventory playerinventory) { + this(i, playerinventory, new MerchantWrapper(playerinventory.player)); + } +@@ -42,6 +57,7 @@ + this.addSlot(new Slot(this.tradeContainer, 0, 136, 37)); + this.addSlot(new Slot(this.tradeContainer, 1, 162, 37)); + this.addSlot(new SlotMerchantResult(playerinventory.player, imerchant, this.tradeContainer, 2, 220, 37)); ++ this.player = playerinventory; // CraftBukkit - save player + + int j; + +@@ -154,7 +170,7 @@ + } + + private void playTradeSound() { +- if (!this.trader.isClientSide()) { ++ if (!this.trader.isClientSide() && this.trader instanceof Entity) { // CraftBukkit - SPIGOT-5035 + Entity entity = (Entity) this.trader; + + entity.level().playLocalSound(entity.getX(), entity.getY(), entity.getZ(), this.trader.getNotifyTradeSound(), SoundCategory.NEUTRAL, 1.0F, 1.0F, false); diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerPlayer.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerPlayer.patch new file mode 100644 index 0000000000..527e1dcde0 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerPlayer.patch @@ -0,0 +1,64 @@ +--- a/net/minecraft/world/inventory/ContainerPlayer.java ++++ b/net/minecraft/world/inventory/ContainerPlayer.java +@@ -13,6 +13,12 @@ + import net.minecraft.world.item.crafting.RecipeHolder; + import net.minecraft.world.item.enchantment.EnchantmentManager; + ++// CraftBukkit start ++import net.minecraft.network.chat.IChatBaseComponent; ++import org.bukkit.craftbukkit.inventory.CraftInventoryCrafting; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class ContainerPlayer extends ContainerRecipeBook { + + public static final int CONTAINER_ID = 0; +@@ -34,15 +40,28 @@ + public static final MinecraftKey EMPTY_ARMOR_SLOT_SHIELD = new MinecraftKey("item/empty_armor_slot_shield"); + static final MinecraftKey[] TEXTURE_EMPTY_SLOTS = new MinecraftKey[]{ContainerPlayer.EMPTY_ARMOR_SLOT_BOOTS, ContainerPlayer.EMPTY_ARMOR_SLOT_LEGGINGS, ContainerPlayer.EMPTY_ARMOR_SLOT_CHESTPLATE, ContainerPlayer.EMPTY_ARMOR_SLOT_HELMET}; + private static final EnumItemSlot[] SLOT_IDS = new EnumItemSlot[]{EnumItemSlot.HEAD, EnumItemSlot.CHEST, EnumItemSlot.LEGS, EnumItemSlot.FEET}; +- private final InventoryCrafting craftSlots = new TransientCraftingContainer(this, 2, 2); +- private final InventoryCraftResult resultSlots = new InventoryCraftResult(); ++ // CraftBukkit start ++ private final TransientCraftingContainer craftSlots; ++ private final InventoryCraftResult resultSlots; ++ // CraftBukkit end + public final boolean active; + private final EntityHuman owner; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private PlayerInventory player; ++ // CraftBukkit end + + public ContainerPlayer(PlayerInventory playerinventory, boolean flag, final EntityHuman entityhuman) { + super((Containers) null, 0); + this.active = flag; + this.owner = entityhuman; ++ // CraftBukkit start ++ this.resultSlots = new InventoryCraftResult(); // CraftBukkit - moved to before InventoryCrafting construction ++ this.craftSlots = new TransientCraftingContainer(this, 2, 2, playerinventory.player); // CraftBukkit - pass player ++ this.craftSlots.resultInventory = this.resultSlots; // CraftBukkit - let InventoryCrafting know about its result slot ++ this.player = playerinventory; // CraftBukkit - save player ++ setTitle(IChatBaseComponent.translatable("container.crafting")); // SPIGOT-4722: Allocate title for player inventory ++ // CraftBukkit end + this.addSlot(new SlotResult(playerinventory.player, this.craftSlots, this.resultSlots, 0, 154, 28)); + + int i; +@@ -259,4 +278,17 @@ + public boolean shouldMoveToInventory(int i) { + return i != this.getResultSlotIndex(); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryCrafting inventory = new CraftInventoryCrafting(this.craftSlots, this.resultSlots); ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerShulkerBox.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerShulkerBox.patch new file mode 100644 index 0000000000..19429ef381 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerShulkerBox.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/world/inventory/ContainerShulkerBox.java ++++ b/net/minecraft/world/inventory/ContainerShulkerBox.java +@@ -6,10 +6,29 @@ + import net.minecraft.world.entity.player.PlayerInventory; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class ContainerShulkerBox extends Container { + + private static final int CONTAINER_SIZE = 27; + private final IInventory container; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity; ++ private PlayerInventory player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), new CraftInventory(this.container), this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + + public ContainerShulkerBox(int i, PlayerInventory playerinventory) { + this(i, playerinventory, new InventorySubcontainer(27)); +@@ -19,6 +38,7 @@ + super(Containers.SHULKER_BOX, i); + checkContainerSize(iinventory, 27); + this.container = iinventory; ++ this.player = playerinventory; // CraftBukkit - save player + iinventory.startOpen(playerinventory.player); + boolean flag = true; + boolean flag1 = true; +@@ -46,6 +66,7 @@ + + @Override + public boolean stillValid(EntityHuman entityhuman) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(entityhuman); + } + diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerSmithing.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerSmithing.patch new file mode 100644 index 0000000000..3484de6c67 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerSmithing.patch @@ -0,0 +1,60 @@ +--- a/net/minecraft/world/inventory/ContainerSmithing.java ++++ b/net/minecraft/world/inventory/ContainerSmithing.java +@@ -13,6 +13,8 @@ + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.state.IBlockData; + ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; // CraftBukkit ++ + public class ContainerSmithing extends ContainerAnvilAbstract { + + public static final int TEMPLATE_SLOT = 0; +@@ -28,6 +30,9 @@ + @Nullable + private RecipeHolder selectedRecipe; + private final List> recipes; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity; ++ // CraftBukkit end + + public ContainerSmithing(int i, PlayerInventory playerinventory) { + this(i, playerinventory, ContainerAccess.NULL); +@@ -97,7 +102,7 @@ + List> list = this.level.getRecipeManager().getRecipesFor(Recipes.SMITHING, this.inputSlots, this.level); + + if (list.isEmpty()) { +- this.resultSlots.setItem(0, ItemStack.EMPTY); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareSmithingEvent(getBukkitView(), ItemStack.EMPTY); // CraftBukkit + } else { + RecipeHolder recipeholder = (RecipeHolder) list.get(0); + ItemStack itemstack = ((SmithingRecipe) recipeholder.value()).assemble(this.inputSlots, this.level.registryAccess()); +@@ -105,7 +110,9 @@ + if (itemstack.isItemEnabled(this.level.enabledFeatures())) { + this.selectedRecipe = recipeholder; + this.resultSlots.setRecipeUsed(recipeholder); +- this.resultSlots.setItem(0, itemstack); ++ // CraftBukkit start ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareSmithingEvent(getBukkitView(), itemstack); ++ // CraftBukkit end + } + } + +@@ -137,4 +144,18 @@ + return !this.getSlot(i).hasItem(); + }).findFirst(); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ org.bukkit.craftbukkit.inventory.CraftInventory inventory = new org.bukkit.craftbukkit.inventory.CraftInventorySmithing( ++ access.getLocation(), this.inputSlots, this.resultSlots); ++ bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerStonecutter.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerStonecutter.patch new file mode 100644 index 0000000000..2ea9c6719b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerStonecutter.patch @@ -0,0 +1,68 @@ +--- a/net/minecraft/world/inventory/ContainerStonecutter.java ++++ b/net/minecraft/world/inventory/ContainerStonecutter.java +@@ -16,6 +16,13 @@ + import net.minecraft.world.level.World; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.inventory.CraftInventoryStonecutter; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++import org.bukkit.entity.Player; ++// CraftBukkit end ++ + public class ContainerStonecutter extends Container { + + public static final int INPUT_SLOT = 0; +@@ -35,6 +42,21 @@ + Runnable slotUpdateListener; + public final IInventory container; + final InventoryCraftResult resultContainer; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ private Player player; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryStonecutter inventory = new CraftInventoryStonecutter(this.container, this.resultContainer); ++ bukkitEntity = new CraftInventoryView(this.player, inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + + public ContainerStonecutter(int i, PlayerInventory playerinventory) { + this(i, playerinventory, ContainerAccess.NULL); +@@ -54,6 +76,13 @@ + ContainerStonecutter.this.slotsChanged(this); + ContainerStonecutter.this.slotUpdateListener.run(); + } ++ ++ // CraftBukkit start ++ @Override ++ public Location getLocation() { ++ return containeraccess.getLocation(); ++ } ++ // CraftBukkit end + }; + this.resultContainer = new InventoryCraftResult(); + this.access = containeraccess; +@@ -105,6 +134,7 @@ + } + + this.addDataSlot(this.selectedRecipeIndex); ++ player = (Player) playerinventory.player.getBukkitEntity(); // CraftBukkit + } + + public int getSelectedRecipeIndex() { +@@ -125,6 +155,7 @@ + + @Override + public boolean stillValid(EntityHuman entityhuman) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, entityhuman, Blocks.STONECUTTER); + } + diff --git a/patch-remap/og/net/minecraft/world/inventory/ContainerWorkbench.patch b/patch-remap/og/net/minecraft/world/inventory/ContainerWorkbench.patch new file mode 100644 index 0000000000..8ed346b3b1 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/ContainerWorkbench.patch @@ -0,0 +1,77 @@ +--- a/net/minecraft/world/inventory/ContainerWorkbench.java ++++ b/net/minecraft/world/inventory/ContainerWorkbench.java +@@ -15,6 +15,12 @@ + import net.minecraft.world.level.World; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import net.minecraft.world.item.crafting.RecipeRepair; ++import org.bukkit.craftbukkit.inventory.CraftInventoryCrafting; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class ContainerWorkbench extends ContainerRecipeBook { + + public static final int RESULT_SLOT = 0; +@@ -24,10 +30,13 @@ + private static final int INV_SLOT_END = 37; + private static final int USE_ROW_SLOT_START = 37; + private static final int USE_ROW_SLOT_END = 46; +- public final InventoryCrafting craftSlots; ++ public final TransientCraftingContainer craftSlots; // CraftBukkit + public final InventoryCraftResult resultSlots; + public final ContainerAccess access; + private final EntityHuman player; ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ // CraftBukkit end + + public ContainerWorkbench(int i, PlayerInventory playerinventory) { + this(i, playerinventory, ContainerAccess.NULL); +@@ -35,8 +44,11 @@ + + public ContainerWorkbench(int i, PlayerInventory playerinventory, ContainerAccess containeraccess) { + super(Containers.CRAFTING, i); +- this.craftSlots = new TransientCraftingContainer(this, 3, 3); ++ // CraftBukkit start - Switched order of IInventory construction and stored player + this.resultSlots = new InventoryCraftResult(); ++ this.craftSlots = new TransientCraftingContainer(this, 3, 3, playerinventory.player); // CraftBukkit - pass player ++ this.craftSlots.resultInventory = this.resultSlots; ++ // CraftBukkit end + this.access = containeraccess; + this.player = playerinventory.player; + this.addSlot(new SlotResult(playerinventory.player, this.craftSlots, this.resultSlots, 0, 124, 35)); +@@ -80,6 +92,7 @@ + } + } + } ++ itemstack = org.bukkit.craftbukkit.event.CraftEventFactory.callPreCraftEvent(inventorycrafting, inventorycraftresult, itemstack, container.getBukkitView(), optional.map(RecipeHolder::toBukkitRecipe).orElse(null) instanceof RecipeRepair); // CraftBukkit + + inventorycraftresult.setItem(0, itemstack); + container.setRemoteSlot(0, itemstack); +@@ -120,6 +133,7 @@ + + @Override + public boolean stillValid(EntityHuman entityhuman) { ++ if (!this.checkReachable) return true; // CraftBukkit + return stillValid(this.access, entityhuman, Blocks.CRAFTING_TABLE); + } + +@@ -208,4 +222,17 @@ + public boolean shouldMoveToInventory(int i) { + return i != this.getResultSlotIndex(); + } ++ ++ // CraftBukkit start ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryCrafting inventory = new CraftInventoryCrafting(this.craftSlots, this.resultSlots); ++ bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/inventory/Containers.patch b/patch-remap/og/net/minecraft/world/inventory/Containers.patch new file mode 100644 index 0000000000..0febcbd231 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/Containers.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/inventory/Containers.java ++++ b/net/minecraft/world/inventory/Containers.java +@@ -8,6 +8,10 @@ + import net.minecraft.world.flag.FeatureFlagSet; + import net.minecraft.world.flag.FeatureFlags; + ++// CraftBukkit start ++import net.minecraft.world.entity.player.PlayerInventory; ++// CraftBukkit end ++ + public class Containers implements FeatureElement { + + public static final Containers GENERIC_9x1 = register("generic_9x1", ContainerChest::oneRow); +@@ -28,7 +32,7 @@ + public static final Containers GRINDSTONE = register("grindstone", ContainerGrindstone::new); + public static final Containers HOPPER = register("hopper", ContainerHopper::new); + public static final Containers LECTERN = register("lectern", (i, playerinventory) -> { +- return new ContainerLectern(i); ++ return new ContainerLectern(i, playerinventory); // CraftBukkit + }); + public static final Containers LOOM = register("loom", ContainerLoom::new); + public static final Containers MERCHANT = register("merchant", ContainerMerchant::new); diff --git a/patch-remap/og/net/minecraft/world/inventory/CrafterMenu.patch b/patch-remap/og/net/minecraft/world/inventory/CrafterMenu.patch new file mode 100644 index 0000000000..586aff71de --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/CrafterMenu.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/world/inventory/CrafterMenu.java ++++ b/net/minecraft/world/inventory/CrafterMenu.java +@@ -8,8 +8,27 @@ + import net.minecraft.world.level.World; + import net.minecraft.world.level.block.CrafterBlock; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftInventoryCrafter; ++import org.bukkit.craftbukkit.inventory.CraftInventoryView; ++// CraftBukkit end ++ + public class CrafterMenu extends Container implements ICrafting { + ++ // CraftBukkit start ++ private CraftInventoryView bukkitEntity = null; ++ ++ @Override ++ public CraftInventoryView getBukkitView() { ++ if (bukkitEntity != null) { ++ return bukkitEntity; ++ } ++ ++ CraftInventoryCrafter inventory = new CraftInventoryCrafter(this.container, this.resultContainer); ++ bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), inventory, this); ++ return bukkitEntity; ++ } ++ // CraftBukkit end + protected static final int SLOT_COUNT = 9; + private static final int INV_SLOT_START = 9; + private static final int INV_SLOT_END = 36; +@@ -116,6 +135,7 @@ + + @Override + public boolean stillValid(EntityHuman entityhuman) { ++ if (!this.checkReachable) return true; // CraftBukkit + return this.container.stillValid(entityhuman); + } + diff --git a/patch-remap/og/net/minecraft/world/inventory/InventoryCraftResult.patch b/patch-remap/og/net/minecraft/world/inventory/InventoryCraftResult.patch new file mode 100644 index 0000000000..8b0b0e9540 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/InventoryCraftResult.patch @@ -0,0 +1,54 @@ +--- a/net/minecraft/world/inventory/InventoryCraftResult.java ++++ b/net/minecraft/world/inventory/InventoryCraftResult.java +@@ -9,12 +9,51 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.crafting.RecipeHolder; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class InventoryCraftResult implements IInventory, RecipeCraftingHolder { + + private final NonNullList itemStacks; + @Nullable + private RecipeHolder recipeUsed; + ++ // CraftBukkit start ++ private int maxStack = MAX_STACK; ++ ++ public java.util.List getContents() { ++ return this.itemStacks; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return null; // Result slots don't get an owner ++ } ++ ++ // Don't need a transaction; the InventoryCrafting keeps track of it for us ++ public void onOpen(CraftHumanEntity who) {} ++ public void onClose(CraftHumanEntity who) {} ++ public java.util.List getViewers() { ++ return new java.util.ArrayList(); ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return null; ++ } ++ // CraftBukkit end ++ + public InventoryCraftResult() { + this.itemStacks = NonNullList.withSize(1, ItemStack.EMPTY); + } diff --git a/patch-remap/og/net/minecraft/world/inventory/InventoryEnderChest.patch b/patch-remap/og/net/minecraft/world/inventory/InventoryEnderChest.patch new file mode 100644 index 0000000000..38e077798e --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/InventoryEnderChest.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/world/inventory/InventoryEnderChest.java ++++ b/net/minecraft/world/inventory/InventoryEnderChest.java +@@ -8,13 +8,32 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.entity.TileEntityEnderChest; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end ++ + public class InventoryEnderChest extends InventorySubcontainer { + + @Nullable + private TileEntityEnderChest activeChest; ++ // CraftBukkit start ++ private final EntityHuman owner; + +- public InventoryEnderChest() { ++ public InventoryHolder getBukkitOwner() { ++ return owner.getBukkitEntity(); ++ } ++ ++ @Override ++ public Location getLocation() { ++ return this.activeChest != null ? CraftLocation.toBukkit(this.activeChest.getBlockPos(), this.activeChest.getLevel().getWorld()) : null; ++ } ++ ++ public InventoryEnderChest(EntityHuman owner) { + super(27); ++ this.owner = owner; ++ // CraftBukkit end + } + + public void setActiveChest(TileEntityEnderChest tileentityenderchest) { diff --git a/patch-remap/og/net/minecraft/world/inventory/InventoryMerchant.patch b/patch-remap/og/net/minecraft/world/inventory/InventoryMerchant.patch new file mode 100644 index 0000000000..a2dec8965d --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/InventoryMerchant.patch @@ -0,0 +1,66 @@ +--- a/net/minecraft/world/inventory/InventoryMerchant.java ++++ b/net/minecraft/world/inventory/InventoryMerchant.java +@@ -11,6 +11,16 @@ + import net.minecraft.world.item.trading.MerchantRecipe; + import net.minecraft.world.item.trading.MerchantRecipeList; + ++// CraftBukkit start ++import java.util.List; ++import net.minecraft.world.entity.npc.EntityVillager; ++import net.minecraft.world.entity.npc.EntityVillagerAbstract; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.entity.CraftAbstractVillager; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class InventoryMerchant implements IInventory { + + private final IMerchant merchant; +@@ -20,6 +30,46 @@ + public int selectionHint; + private int futureXp; + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.itemStacks; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ merchant.setTradingPlayer((EntityHuman) null); // SPIGOT-4860 ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return (merchant instanceof EntityVillagerAbstract) ? (CraftAbstractVillager) ((EntityVillagerAbstract) this.merchant).getBukkitEntity() : null; ++ } ++ ++ @Override ++ public Location getLocation() { ++ return (merchant instanceof EntityVillager) ? ((EntityVillager) this.merchant).getBukkitEntity().getLocation() : null; ++ } ++ // CraftBukkit end ++ + public InventoryMerchant(IMerchant imerchant) { + this.itemStacks = NonNullList.withSize(3, ItemStack.EMPTY); + this.merchant = imerchant; diff --git a/patch-remap/og/net/minecraft/world/inventory/SlotFurnaceResult.patch b/patch-remap/og/net/minecraft/world/inventory/SlotFurnaceResult.patch new file mode 100644 index 0000000000..6f6494dba3 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/SlotFurnaceResult.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/inventory/SlotFurnaceResult.java ++++ b/net/minecraft/world/inventory/SlotFurnaceResult.java +@@ -54,7 +54,7 @@ + if (iinventory instanceof TileEntityFurnace) { + TileEntityFurnace tileentityfurnace = (TileEntityFurnace) iinventory; + +- tileentityfurnace.awardUsedRecipesAndPopExperience(entityplayer); ++ tileentityfurnace.awardUsedRecipesAndPopExperience(entityplayer, itemstack, this.removeCount); // CraftBukkit + } + } + diff --git a/patch-remap/og/net/minecraft/world/inventory/TransientCraftingContainer.patch b/patch-remap/og/net/minecraft/world/inventory/TransientCraftingContainer.patch new file mode 100644 index 0000000000..87f4eec5f1 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/inventory/TransientCraftingContainer.patch @@ -0,0 +1,88 @@ +--- a/net/minecraft/world/inventory/TransientCraftingContainer.java ++++ b/net/minecraft/world/inventory/TransientCraftingContainer.java +@@ -8,6 +8,16 @@ + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import java.util.List; ++import net.minecraft.world.IInventory; ++import net.minecraft.world.item.crafting.RecipeHolder; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.event.inventory.InventoryType; ++// CraftBukkit end ++ + public class TransientCraftingContainer implements InventoryCrafting { + + private final NonNullList items; +@@ -15,6 +25,68 @@ + private final int height; + private final Container menu; + ++ // CraftBukkit start - add fields ++ public List transaction = new java.util.ArrayList(); ++ private RecipeHolder currentRecipe; ++ public IInventory resultInventory; ++ private EntityHuman owner; ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public InventoryType getInvType() { ++ return items.size() == 4 ? InventoryType.CRAFTING : InventoryType.WORKBENCH; ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public org.bukkit.inventory.InventoryHolder getOwner() { ++ return (owner == null) ? null : owner.getBukkitEntity(); ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ resultInventory.setMaxStackSize(size); ++ } ++ ++ @Override ++ public Location getLocation() { ++ return menu instanceof ContainerWorkbench ? ((ContainerWorkbench) menu).access.getLocation() : owner.getBukkitEntity().getLocation(); ++ } ++ ++ @Override ++ public RecipeHolder getCurrentRecipe() { ++ return currentRecipe; ++ } ++ ++ @Override ++ public void setCurrentRecipe(RecipeHolder currentRecipe) { ++ this.currentRecipe = currentRecipe; ++ } ++ ++ public TransientCraftingContainer(Container container, int i, int j, EntityHuman player) { ++ this(container, i, j); ++ this.owner = player; ++ } ++ // CraftBukkit end ++ + public TransientCraftingContainer(Container container, int i, int j) { + this(container, i, j, NonNullList.withSize(i * j, ItemStack.EMPTY)); + } diff --git a/patch-remap/og/net/minecraft/world/item/ItemArmor.patch b/patch-remap/og/net/minecraft/world/item/ItemArmor.patch new file mode 100644 index 0000000000..4b18f9463e --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemArmor.patch @@ -0,0 +1,51 @@ +--- a/net/minecraft/world/item/ItemArmor.java ++++ b/net/minecraft/world/item/ItemArmor.java +@@ -27,6 +27,12 @@ + import net.minecraft.world.level.block.BlockDispenser; + import net.minecraft.world.phys.AxisAlignedBB; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseArmorEvent; ++// CraftBukkit end ++ + public class ItemArmor extends Item implements Equipable { + + private static final EnumMap ARMOR_MODIFIER_UUID_PER_TYPE = (EnumMap) SystemUtils.make(new EnumMap(ItemArmor.a.class), (enummap) -> { +@@ -58,8 +64,34 @@ + EntityLiving entityliving = (EntityLiving) list.get(0); + EnumItemSlot enumitemslot = EntityInsentient.getEquipmentSlotForItem(itemstack); + ItemStack itemstack1 = itemstack.split(1); ++ // CraftBukkit start ++ World world = sourceblock.level(); ++ org.bukkit.block.Block block = CraftBlock.at(world, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + +- entityliving.setItemSlot(enumitemslot, itemstack1); ++ BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityliving.getBukkitEntity()); ++ if (!BlockDispenser.eventFired) { ++ world.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return false; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != ItemArmor.DISPENSE_ITEM_BEHAVIOR) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return true; ++ } ++ } ++ ++ entityliving.setItemSlot(enumitemslot, CraftItemStack.asNMSCopy(event.getItem())); ++ // CraftBukkit end + if (entityliving instanceof EntityInsentient) { + ((EntityInsentient) entityliving).setDropChance(enumitemslot, 2.0F); + ((EntityInsentient) entityliving).setPersistenceRequired(); diff --git a/patch-remap/og/net/minecraft/world/item/ItemArmorStand.patch b/patch-remap/og/net/minecraft/world/item/ItemArmorStand.patch new file mode 100644 index 0000000000..6069029c14 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemArmorStand.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/item/ItemArmorStand.java ++++ b/net/minecraft/world/item/ItemArmorStand.java +@@ -53,6 +53,11 @@ + float f = (float) MathHelper.floor((MathHelper.wrapDegrees(itemactioncontext.getRotation() - 180.0F) + 22.5F) / 45.0F) * 45.0F; + + entityarmorstand.moveTo(entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), f, 0.0F); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(itemactioncontext, entityarmorstand).isCancelled()) { ++ return EnumInteractionResult.FAIL; ++ } ++ // CraftBukkit end + worldserver.addFreshEntityWithPassengers(entityarmorstand); + world.playSound((EntityHuman) null, entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), SoundEffects.ARMOR_STAND_PLACE, SoundCategory.BLOCKS, 0.75F, 0.8F); + entityarmorstand.gameEvent(GameEvent.ENTITY_PLACE, itemactioncontext.getPlayer()); diff --git a/patch-remap/og/net/minecraft/world/item/ItemBlock.patch b/patch-remap/og/net/minecraft/world/item/ItemBlock.patch new file mode 100644 index 0000000000..0f096b5bd2 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemBlock.patch @@ -0,0 +1,121 @@ +--- a/net/minecraft/world/item/ItemBlock.java ++++ b/net/minecraft/world/item/ItemBlock.java +@@ -33,6 +33,13 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++// CraftBukkit start ++import net.minecraft.server.level.WorldServer; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.event.block.BlockCanBuildEvent; ++// CraftBukkit end ++ + public class ItemBlock extends Item { + + public static final String BLOCK_ENTITY_TAG = "BlockEntityTag"; +@@ -71,6 +78,12 @@ + return EnumInteractionResult.FAIL; + } else { + IBlockData iblockdata = this.getPlacementState(blockactioncontext1); ++ // CraftBukkit start - special case for handling block placement with water lilies and snow buckets ++ org.bukkit.block.BlockState blockstate = null; ++ if (this instanceof PlaceOnWaterBlockItem || this instanceof SolidBucketItem) { ++ blockstate = org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockactioncontext1.getLevel(), blockactioncontext1.getClickedPos()); ++ } ++ // CraftBukkit end + + if (iblockdata == null) { + return EnumInteractionResult.FAIL; +@@ -87,6 +100,19 @@ + iblockdata1 = this.updateBlockStateFromTag(blockposition, world, itemstack, iblockdata1); + this.updateCustomBlockEntityTag(blockposition, world, entityhuman, itemstack, iblockdata1); + iblockdata1.getBlock().setPlacedBy(world, blockposition, iblockdata1, entityhuman, itemstack); ++ // CraftBukkit start ++ if (blockstate != null) { ++ org.bukkit.event.block.BlockPlaceEvent placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEvent((WorldServer) world, entityhuman, blockactioncontext1.getHand(), blockstate, blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild())) { ++ blockstate.update(true, false); ++ ++ if (this instanceof SolidBucketItem) { ++ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 ++ } ++ return EnumInteractionResult.FAIL; ++ } ++ } ++ // CraftBukkit end + if (entityhuman instanceof EntityPlayer) { + CriterionTriggers.PLACED_BLOCK.trigger((EntityPlayer) entityhuman, blockposition, itemstack); + } +@@ -94,9 +120,9 @@ + + SoundEffectType soundeffecttype = iblockdata1.getSoundType(); + +- world.playSound(entityhuman, blockposition, this.getPlaceSound(iblockdata1), SoundCategory.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F); ++ // world.playSound(entityhuman, blockposition, this.getPlaceSound(iblockdata1), SoundCategory.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F); + world.gameEvent(GameEvent.BLOCK_PLACE, blockposition, GameEvent.a.of(entityhuman, iblockdata1)); +- if (entityhuman == null || !entityhuman.getAbilities().instabuild) { ++ if ((entityhuman == null || !entityhuman.getAbilities().instabuild) && itemstack != ItemStack.EMPTY) { // CraftBukkit + itemstack.shrink(1); + } + +@@ -132,6 +158,21 @@ + + if (nbttagcompound != null) { + NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("BlockStateTag"); ++ // CraftBukkit start ++ iblockdata1 = getBlockState(iblockdata1, nbttagcompound1); ++ } ++ ++ if (iblockdata1 != iblockdata) { ++ world.setBlock(blockposition, iblockdata1, 2); ++ } ++ ++ return iblockdata1; ++ } ++ ++ public static IBlockData getBlockState(IBlockData iblockdata, NBTTagCompound nbttagcompound1) { ++ IBlockData iblockdata1 = iblockdata; ++ { ++ // CraftBukkit end + BlockStateList blockstatelist = iblockdata.getBlock().getStateDefinition(); + Iterator iterator = nbttagcompound1.getAllKeys().iterator(); + +@@ -146,11 +187,6 @@ + } + } + } +- +- if (iblockdata1 != iblockdata) { +- world.setBlock(blockposition, iblockdata1, 2); +- } +- + return iblockdata1; + } + +@@ -163,8 +199,15 @@ + protected boolean canPlace(BlockActionContext blockactioncontext, IBlockData iblockdata) { + EntityHuman entityhuman = blockactioncontext.getPlayer(); + VoxelShapeCollision voxelshapecollision = entityhuman == null ? VoxelShapeCollision.empty() : VoxelShapeCollision.of(entityhuman); ++ // CraftBukkit start - store default return ++ boolean defaultReturn = (!this.mustSurvive() || iblockdata.canSurvive(blockactioncontext.getLevel(), blockactioncontext.getClickedPos())) && blockactioncontext.getLevel().isUnobstructed(iblockdata, blockactioncontext.getClickedPos(), voxelshapecollision); ++ org.bukkit.entity.Player player = (blockactioncontext.getPlayer() instanceof EntityPlayer) ? (org.bukkit.entity.Player) blockactioncontext.getPlayer().getBukkitEntity() : null; + +- return (!this.mustSurvive() || iblockdata.canSurvive(blockactioncontext.getLevel(), blockactioncontext.getClickedPos())) && blockactioncontext.getLevel().isUnobstructed(iblockdata, blockactioncontext.getClickedPos(), voxelshapecollision); ++ BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(blockactioncontext.getLevel(), blockactioncontext.getClickedPos()), player, CraftBlockData.fromData(iblockdata), defaultReturn); ++ blockactioncontext.getLevel().getCraftServer().getPluginManager().callEvent(event); ++ ++ return event.isBuildable(); ++ // CraftBukkit end + } + + protected boolean mustSurvive() { +@@ -239,7 +282,7 @@ + + if (nbttagcompound != null && nbttagcompound.contains("Items", 9)) { + NBTTagList nbttaglist = nbttagcompound.getList("Items", 10); +- Stream stream = nbttaglist.stream(); ++ Stream stream = nbttaglist.stream(); // CraftBukkit - decompile error + + Objects.requireNonNull(NBTTagCompound.class); + ItemLiquidUtil.onContainerDestroyed(entityitem, stream.map(NBTTagCompound.class::cast).map(ItemStack::of)); diff --git a/patch-remap/og/net/minecraft/world/item/ItemBlockWallable.patch b/patch-remap/og/net/minecraft/world/item/ItemBlockWallable.patch new file mode 100644 index 0000000000..f1eec80670 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemBlockWallable.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/world/item/ItemBlockWallable.java ++++ b/net/minecraft/world/item/ItemBlockWallable.java +@@ -10,6 +10,12 @@ + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; ++// CraftBukkit start ++import net.minecraft.server.level.EntityPlayer; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.event.block.BlockCanBuildEvent; ++// CraftBukkit end + + public class ItemBlockWallable extends ItemBlock { + +@@ -49,7 +55,19 @@ + } + } + +- return iblockdata1 != null && world.isUnobstructed(iblockdata1, blockposition, VoxelShapeCollision.empty()) ? iblockdata1 : null; ++ // CraftBukkit start ++ if (iblockdata1 != null) { ++ boolean defaultReturn = world.isUnobstructed(iblockdata1, blockposition, VoxelShapeCollision.empty()); ++ org.bukkit.entity.Player player = (blockactioncontext.getPlayer() instanceof EntityPlayer) ? (org.bukkit.entity.Player) blockactioncontext.getPlayer().getBukkitEntity() : null; ++ ++ BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(world, blockposition), player, CraftBlockData.fromData(iblockdata1), defaultReturn); ++ blockactioncontext.getLevel().getCraftServer().getPluginManager().callEvent(event); ++ ++ return (event.isBuildable()) ? iblockdata1 : null; ++ } else { ++ return null; ++ } ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/item/ItemBoat.patch b/patch-remap/og/net/minecraft/world/item/ItemBoat.patch new file mode 100644 index 0000000000..93150dedb2 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemBoat.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/world/item/ItemBoat.java ++++ b/net/minecraft/world/item/ItemBoat.java +@@ -60,6 +60,13 @@ + } + + if (movingobjectpositionblock.getType() == MovingObjectPosition.EnumMovingObjectType.BLOCK) { ++ // CraftBukkit start - Boat placement ++ org.bukkit.event.player.PlayerInteractEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(entityhuman, org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), itemstack, false, enumhand, movingobjectpositionblock.getLocation()); ++ ++ if (event.isCancelled()) { ++ return InteractionResultWrapper.pass(itemstack); ++ } ++ // CraftBukkit end + EntityBoat entityboat = this.getBoat(world, movingobjectpositionblock, itemstack, entityhuman); + + entityboat.setVariant(this.type); +@@ -68,7 +75,15 @@ + return InteractionResultWrapper.fail(itemstack); + } else { + if (!world.isClientSide) { +- world.addFreshEntity(entityboat); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(world, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), entityhuman, entityboat, enumhand).isCancelled()) { ++ return InteractionResultWrapper.fail(itemstack); ++ } ++ ++ if (!world.addFreshEntity(entityboat)) { ++ return InteractionResultWrapper.pass(itemstack); ++ } ++ // CraftBukkit end + world.gameEvent((Entity) entityhuman, GameEvent.ENTITY_PLACE, movingobjectpositionblock.getLocation()); + if (!entityhuman.getAbilities().instabuild) { + itemstack.shrink(1); +@@ -86,7 +101,7 @@ + + private EntityBoat getBoat(World world, MovingObjectPosition movingobjectposition, ItemStack itemstack, EntityHuman entityhuman) { + Vec3D vec3d = movingobjectposition.getLocation(); +- Object object = this.hasChest ? new ChestBoat(world, vec3d.x, vec3d.y, vec3d.z) : new EntityBoat(world, vec3d.x, vec3d.y, vec3d.z); ++ EntityBoat object = this.hasChest ? new ChestBoat(world, vec3d.x, vec3d.y, vec3d.z) : new EntityBoat(world, vec3d.x, vec3d.y, vec3d.z); // CraftBukkit - decompile error + + if (world instanceof WorldServer) { + WorldServer worldserver = (WorldServer) world; diff --git a/patch-remap/og/net/minecraft/world/item/ItemBoneMeal.patch b/patch-remap/og/net/minecraft/world/item/ItemBoneMeal.patch new file mode 100644 index 0000000000..0e32a858eb --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemBoneMeal.patch @@ -0,0 +1,32 @@ +--- a/net/minecraft/world/item/ItemBoneMeal.java ++++ b/net/minecraft/world/item/ItemBoneMeal.java +@@ -34,13 +34,19 @@ + + @Override + public EnumInteractionResult useOn(ItemActionContext itemactioncontext) { ++ // CraftBukkit start - extract bonemeal application logic to separate, static method ++ return applyBonemeal(itemactioncontext); ++ } ++ ++ public static EnumInteractionResult applyBonemeal(ItemActionContext itemactioncontext) { ++ // CraftBukkit end + World world = itemactioncontext.getLevel(); + BlockPosition blockposition = itemactioncontext.getClickedPos(); + BlockPosition blockposition1 = blockposition.relative(itemactioncontext.getClickedFace()); + + if (growCrop(itemactioncontext.getItemInHand(), world, blockposition)) { + if (!world.isClientSide) { +- itemactioncontext.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); ++ if (itemactioncontext.getPlayer() != null) itemactioncontext.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); // CraftBukkit - SPIGOT-7518 + world.levelEvent(1505, blockposition, 0); + } + +@@ -51,7 +57,7 @@ + + if (flag && growWaterPlant(itemactioncontext.getItemInHand(), world, blockposition1, itemactioncontext.getClickedFace())) { + if (!world.isClientSide) { +- itemactioncontext.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); ++ if (itemactioncontext.getPlayer() != null) itemactioncontext.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); // CraftBukkit - SPIGOT-7518 + world.levelEvent(1505, blockposition1, 0); + } + diff --git a/patch-remap/og/net/minecraft/world/item/ItemBow.patch b/patch-remap/og/net/minecraft/world/item/ItemBow.patch new file mode 100644 index 0000000000..44da9e2cbf --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemBow.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/item/ItemBow.java ++++ b/net/minecraft/world/item/ItemBow.java +@@ -64,6 +64,14 @@ + if (EnchantmentManager.getItemEnchantmentLevel(Enchantments.FLAMING_ARROWS, itemstack) > 0) { + entityarrow.setSecondsOnFire(100); + } ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(entityhuman, itemstack, itemstack1, entityarrow, entityhuman.getUsedItemHand(), f, !flag1); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ flag1 = !event.shouldConsumeItem(); ++ // CraftBukkit end + + itemstack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { + entityhuman1.broadcastBreakEvent(entityhuman.getUsedItemHand()); +@@ -72,7 +80,16 @@ + entityarrow.pickup = EntityArrow.PickupStatus.CREATIVE_ONLY; + } + +- world.addFreshEntity(entityarrow); ++ // CraftBukkit start ++ if (event.getProjectile() == entityarrow.getBukkitEntity()) { ++ if (!world.addFreshEntity(entityarrow)) { ++ if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { ++ ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } ++ return; ++ } ++ } ++ // CraftBukkit end + } + + world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.ARROW_SHOOT, SoundCategory.PLAYERS, 1.0F, 1.0F / (world.getRandom().nextFloat() * 0.4F + 1.2F) + f * 0.5F); diff --git a/patch-remap/og/net/minecraft/world/item/ItemBucket.patch b/patch-remap/og/net/minecraft/world/item/ItemBucket.patch new file mode 100644 index 0000000000..6f02b19e96 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemBucket.patch @@ -0,0 +1,88 @@ +--- a/net/minecraft/world/item/ItemBucket.java ++++ b/net/minecraft/world/item/ItemBucket.java +@@ -29,6 +29,16 @@ + import net.minecraft.world.phys.MovingObjectPosition; + import net.minecraft.world.phys.MovingObjectPositionBlock; + ++// CraftBukkit start ++import net.minecraft.network.protocol.game.PacketPlayOutBlockChange; ++import net.minecraft.server.level.WorldServer; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.DummyGeneratorAccess; ++import org.bukkit.event.player.PlayerBucketEmptyEvent; ++import org.bukkit.event.player.PlayerBucketFillEvent; ++// CraftBukkit end ++ + public class ItemBucket extends Item implements DispensibleContainerItem { + + public final FluidType content; +@@ -61,6 +71,17 @@ + + if (block instanceof IFluidSource) { + IFluidSource ifluidsource = (IFluidSource) block; ++ // CraftBukkit start ++ ItemStack dummyFluid = ifluidsource.pickupBlock(entityhuman, DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); ++ if (dummyFluid.isEmpty()) return InteractionResultWrapper.fail(itemstack); // Don't fire event if the bucket won't be filled. ++ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) world, entityhuman, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.getItem(), enumhand); ++ ++ if (event.isCancelled()) { ++ ((EntityPlayer) entityhuman).connection.send(new PacketPlayOutBlockChange(world, blockposition)); // SPIGOT-5163 (see PlayerInteractManager) ++ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 ++ return InteractionResultWrapper.fail(itemstack); ++ } ++ // CraftBukkit end + ItemStack itemstack1 = ifluidsource.pickupBlock(entityhuman, world, blockposition, iblockdata); + + if (!itemstack1.isEmpty()) { +@@ -69,7 +90,7 @@ + entityhuman.playSound(soundeffect, 1.0F, 1.0F); + }); + world.gameEvent((Entity) entityhuman, GameEvent.FLUID_PICKUP, blockposition); +- ItemStack itemstack2 = ItemLiquidUtil.createFilledResult(itemstack, entityhuman, itemstack1); ++ ItemStack itemstack2 = ItemLiquidUtil.createFilledResult(itemstack, entityhuman, CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit + + if (!world.isClientSide) { + CriterionTriggers.FILLED_BUCKET.trigger((EntityPlayer) entityhuman, itemstack1); +@@ -84,7 +105,7 @@ + iblockdata = world.getBlockState(blockposition); + BlockPosition blockposition2 = iblockdata.getBlock() instanceof IFluidContainer && this.content == FluidTypes.WATER ? blockposition : blockposition1; + +- if (this.emptyContents(entityhuman, world, blockposition2, movingobjectpositionblock)) { ++ if (this.emptyContents(entityhuman, world, blockposition2, movingobjectpositionblock, movingobjectpositionblock.getDirection(), blockposition, itemstack, enumhand)) { // CraftBukkit + this.checkExtraContent(entityhuman, world, itemstack, blockposition2); + if (entityhuman instanceof EntityPlayer) { + CriterionTriggers.PLACED_BLOCK.trigger((EntityPlayer) entityhuman, blockposition2, itemstack); +@@ -111,6 +132,12 @@ + + @Override + public boolean emptyContents(@Nullable EntityHuman entityhuman, World world, BlockPosition blockposition, @Nullable MovingObjectPositionBlock movingobjectpositionblock) { ++ // CraftBukkit start ++ return emptyContents(entityhuman, world, blockposition, movingobjectpositionblock, null, null, null, EnumHand.MAIN_HAND); ++ } ++ ++ public boolean emptyContents(EntityHuman entityhuman, World world, BlockPosition blockposition, @Nullable MovingObjectPositionBlock movingobjectpositionblock, EnumDirection enumdirection, BlockPosition clicked, ItemStack itemstack, EnumHand enumhand) { ++ // CraftBukkit end + FluidType fluidtype = this.content; + + if (!(fluidtype instanceof FluidTypeFlowing)) { +@@ -148,8 +175,18 @@ + + boolean flag2 = flag1; + ++ // CraftBukkit start ++ if (flag2 && entityhuman != null) { ++ PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((WorldServer) world, entityhuman, blockposition, clicked, enumdirection, itemstack, enumhand); ++ if (event.isCancelled()) { ++ ((EntityPlayer) entityhuman).connection.send(new PacketPlayOutBlockChange(world, blockposition)); // SPIGOT-4238: needed when looking through entity ++ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 ++ return false; ++ } ++ } ++ // CraftBukkit end + if (!flag2) { +- return movingobjectpositionblock != null && this.emptyContents(entityhuman, world, movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()), (MovingObjectPositionBlock) null); ++ return movingobjectpositionblock != null && this.emptyContents(entityhuman, world, movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()), (MovingObjectPositionBlock) null, enumdirection, clicked, itemstack, enumhand); // CraftBukkit + } else if (world.dimensionType().ultraWarm() && this.content.is(TagsFluid.WATER)) { + int i = blockposition.getX(); + int j = blockposition.getY(); diff --git a/patch-remap/og/net/minecraft/world/item/ItemChorusFruit.patch b/patch-remap/og/net/minecraft/world/item/ItemChorusFruit.patch new file mode 100644 index 0000000000..8915087352 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemChorusFruit.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/item/ItemChorusFruit.java ++++ b/net/minecraft/world/item/ItemChorusFruit.java +@@ -35,7 +35,16 @@ + + Vec3D vec3d = entityliving.position(); + +- if (entityliving.randomTeleport(d0, d1, d2, true)) { ++ // CraftBukkit start - handle canceled status of teleport event ++ java.util.Optional status = entityliving.randomTeleport(d0, d1, d2, true, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.CHORUS_FRUIT); ++ ++ if (!status.isPresent()) { ++ // teleport event was canceled, no more tries ++ break; ++ } ++ ++ if (status.get()) { ++ // CraftBukkit end + world.gameEvent(GameEvent.TELEPORT, vec3d, GameEvent.a.of((Entity) entityliving)); + SoundEffect soundeffect; + SoundCategory soundcategory; diff --git a/patch-remap/og/net/minecraft/world/item/ItemCrossbow.patch b/patch-remap/og/net/minecraft/world/item/ItemCrossbow.patch new file mode 100644 index 0000000000..d1b86c9d2e --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemCrossbow.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/item/ItemCrossbow.java ++++ b/net/minecraft/world/item/ItemCrossbow.java +@@ -236,11 +236,27 @@ + + ((IProjectile) object).shoot((double) vector3f.x(), (double) vector3f.y(), (double) vector3f.z(), f1, f2); + } ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(entityliving, itemstack, itemstack1, (Entity) object, entityliving.getUsedItemHand(), f, true); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ // CraftBukkit end + + itemstack.hurtAndBreak(flag1 ? 3 : 1, entityliving, (entityliving1) -> { + entityliving1.broadcastBreakEvent(enumhand); + }); +- world.addFreshEntity((Entity) object); ++ // CraftBukkit start ++ if (event.getProjectile() == ((Entity) object).getBukkitEntity()) { ++ if (!world.addFreshEntity((Entity) object)) { ++ if (entityliving instanceof EntityPlayer) { ++ ((EntityPlayer) entityliving).getBukkitEntity().updateInventory(); ++ } ++ return; ++ } ++ } ++ // CraftBukkit end + world.playSound((EntityHuman) null, entityliving.getX(), entityliving.getY(), entityliving.getZ(), SoundEffects.CROSSBOW_SHOOT, SoundCategory.PLAYERS, 1.0F, f); + } + } diff --git a/patch-remap/og/net/minecraft/world/item/ItemDebugStick.patch b/patch-remap/og/net/minecraft/world/item/ItemDebugStick.patch new file mode 100644 index 0000000000..f1eea636d5 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemDebugStick.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/item/ItemDebugStick.java ++++ b/net/minecraft/world/item/ItemDebugStick.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.world.item; + + import java.util.Collection; +@@ -95,7 +96,7 @@ + } + + private static > IBlockData cycleState(IBlockData iblockdata, IBlockState iblockstate, boolean flag) { +- return (IBlockData) iblockdata.setValue(iblockstate, (Comparable) getRelative(iblockstate.getPossibleValues(), iblockdata.getValue(iblockstate), flag)); ++ return (IBlockData) iblockdata.setValue(iblockstate, getRelative(iblockstate.getPossibleValues(), iblockdata.getValue(iblockstate), flag)); // CraftBukkit - decompile error + } + + private static T getRelative(Iterable iterable, @Nullable T t0, boolean flag) { diff --git a/patch-remap/og/net/minecraft/world/item/ItemDye.patch b/patch-remap/og/net/minecraft/world/item/ItemDye.patch new file mode 100644 index 0000000000..67a3f2eab9 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemDye.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/item/ItemDye.java ++++ b/net/minecraft/world/item/ItemDye.java +@@ -13,6 +13,8 @@ + import net.minecraft.world.level.World; + import net.minecraft.world.level.block.entity.TileEntitySign; + ++import org.bukkit.event.entity.SheepDyeWoolEvent; // CraftBukkit ++ + public class ItemDye extends Item implements SignApplicator { + + private static final Map ITEM_BY_COLOR = Maps.newEnumMap(EnumColor.class); +@@ -32,7 +34,17 @@ + if (entitysheep.isAlive() && !entitysheep.isSheared() && entitysheep.getColor() != this.dyeColor) { + entitysheep.level().playSound(entityhuman, (Entity) entitysheep, SoundEffects.DYE_USE, SoundCategory.PLAYERS, 1.0F, 1.0F); + if (!entityhuman.level().isClientSide) { +- entitysheep.setColor(this.dyeColor); ++ // CraftBukkit start ++ byte bColor = (byte) this.dyeColor.getId(); ++ SheepDyeWoolEvent event = new SheepDyeWoolEvent((org.bukkit.entity.Sheep) entitysheep.getBukkitEntity(), org.bukkit.DyeColor.getByWoolData(bColor), (org.bukkit.entity.Player) entityhuman.getBukkitEntity()); ++ entitysheep.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return EnumInteractionResult.PASS; ++ } ++ ++ entitysheep.setColor(EnumColor.byId((byte) event.getColor().getWoolData())); ++ // CraftBukkit end + itemstack.shrink(1); + } + diff --git a/patch-remap/og/net/minecraft/world/item/ItemEgg.patch b/patch-remap/og/net/minecraft/world/item/ItemEgg.patch new file mode 100644 index 0000000000..40f4faa8e8 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemEgg.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/world/item/ItemEgg.java ++++ b/net/minecraft/world/item/ItemEgg.java +@@ -19,14 +19,22 @@ + public InteractionResultWrapper use(World world, EntityHuman entityhuman, EnumHand enumhand) { + ItemStack itemstack = entityhuman.getItemInHand(enumhand); + +- world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); ++ // world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); // CraftBukkit - moved down + if (!world.isClientSide) { + EntityEgg entityegg = new EntityEgg(world, entityhuman); + + entityegg.setItem(itemstack); + entityegg.shootFromRotation(entityhuman, entityhuman.getXRot(), entityhuman.getYRot(), 0.0F, 1.5F, 1.0F); +- world.addFreshEntity(entityegg); ++ // CraftBukkit start ++ if (!world.addFreshEntity(entityegg)) { ++ if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { ++ ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } ++ return InteractionResultWrapper.fail(itemstack); ++ } ++ // CraftBukkit end + } ++ world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); + + entityhuman.awardStat(StatisticList.ITEM_USED.get(this)); + if (!entityhuman.getAbilities().instabuild) { diff --git a/patch-remap/og/net/minecraft/world/item/ItemEndCrystal.patch b/patch-remap/og/net/minecraft/world/item/ItemEndCrystal.patch new file mode 100644 index 0000000000..9ca1d4f105 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemEndCrystal.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/item/ItemEndCrystal.java ++++ b/net/minecraft/world/item/ItemEndCrystal.java +@@ -46,6 +46,11 @@ + EntityEnderCrystal entityendercrystal = new EntityEnderCrystal(world, d0 + 0.5D, d1, d2 + 0.5D); + + entityendercrystal.setShowBottom(false); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(itemactioncontext, entityendercrystal).isCancelled()) { ++ return EnumInteractionResult.FAIL; ++ } ++ // CraftBukkit end + world.addFreshEntity(entityendercrystal); + world.gameEvent((Entity) itemactioncontext.getPlayer(), GameEvent.ENTITY_PLACE, blockposition1); + EnderDragonBattle enderdragonbattle = ((WorldServer) world).getDragonFight(); diff --git a/patch-remap/og/net/minecraft/world/item/ItemEnderEye.patch b/patch-remap/og/net/minecraft/world/item/ItemEnderEye.patch new file mode 100644 index 0000000000..e573b447a5 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemEnderEye.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/item/ItemEnderEye.java ++++ b/net/minecraft/world/item/ItemEnderEye.java +@@ -89,7 +89,11 @@ + entityendersignal.setItem(itemstack); + entityendersignal.signalTo(blockposition); + world.gameEvent(GameEvent.PROJECTILE_SHOOT, entityendersignal.position(), GameEvent.a.of((Entity) entityhuman)); +- world.addFreshEntity(entityendersignal); ++ // CraftBukkit start ++ if (!world.addFreshEntity(entityendersignal)) { ++ return new InteractionResultWrapper(EnumInteractionResult.FAIL, itemstack); ++ } ++ // CraftBukkit end + if (entityhuman instanceof EntityPlayer) { + CriterionTriggers.USED_ENDER_EYE.trigger((EntityPlayer) entityhuman, blockposition); + } diff --git a/patch-remap/og/net/minecraft/world/item/ItemEnderPearl.patch b/patch-remap/og/net/minecraft/world/item/ItemEnderPearl.patch new file mode 100644 index 0000000000..8ec7abc437 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemEnderPearl.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/item/ItemEnderPearl.java ++++ b/net/minecraft/world/item/ItemEnderPearl.java +@@ -19,16 +19,24 @@ + public InteractionResultWrapper use(World world, EntityHuman entityhuman, EnumHand enumhand) { + ItemStack itemstack = entityhuman.getItemInHand(enumhand); + +- world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); +- entityhuman.getCooldowns().addCooldown(this, 20); ++ // CraftBukkit start - change order + if (!world.isClientSide) { + EntityEnderPearl entityenderpearl = new EntityEnderPearl(world, entityhuman); + + entityenderpearl.setItem(itemstack); + entityenderpearl.shootFromRotation(entityhuman, entityhuman.getXRot(), entityhuman.getYRot(), 0.0F, 1.5F, 1.0F); +- world.addFreshEntity(entityenderpearl); ++ if (!world.addFreshEntity(entityenderpearl)) { ++ if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { ++ ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } ++ return InteractionResultWrapper.fail(itemstack); ++ } + } + ++ world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); ++ entityhuman.getCooldowns().addCooldown(this, 20); ++ // CraftBukkit end ++ + entityhuman.awardStat(StatisticList.ITEM_USED.get(this)); + if (!entityhuman.getAbilities().instabuild) { + itemstack.shrink(1); diff --git a/patch-remap/og/net/minecraft/world/item/ItemFireball.patch b/patch-remap/og/net/minecraft/world/item/ItemFireball.patch new file mode 100644 index 0000000000..7d05028ae8 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemFireball.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/item/ItemFireball.java ++++ b/net/minecraft/world/item/ItemFireball.java +@@ -33,12 +33,28 @@ + if (!BlockCampfire.canLight(iblockdata) && !CandleBlock.canLight(iblockdata) && !CandleCakeBlock.canLight(iblockdata)) { + blockposition = blockposition.relative(itemactioncontext.getClickedFace()); + if (BlockFireAbstract.canBePlacedAt(world, blockposition, itemactioncontext.getHorizontalDirection())) { ++ // CraftBukkit start - fire BlockIgniteEvent ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FIREBALL, itemactioncontext.getPlayer()).isCancelled()) { ++ if (!itemactioncontext.getPlayer().getAbilities().instabuild) { ++ itemactioncontext.getItemInHand().shrink(1); ++ } ++ return EnumInteractionResult.PASS; ++ } ++ // CraftBukkit end + this.playSound(world, blockposition); + world.setBlockAndUpdate(blockposition, BlockFireAbstract.getState(world, blockposition)); + world.gameEvent((Entity) itemactioncontext.getPlayer(), GameEvent.BLOCK_PLACE, blockposition); + flag = true; + } + } else { ++ // CraftBukkit start - fire BlockIgniteEvent ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FIREBALL, itemactioncontext.getPlayer()).isCancelled()) { ++ if (!itemactioncontext.getPlayer().getAbilities().instabuild) { ++ itemactioncontext.getItemInHand().shrink(1); ++ } ++ return EnumInteractionResult.PASS; ++ } ++ // CraftBukkit end + this.playSound(world, blockposition); + world.setBlockAndUpdate(blockposition, (IBlockData) iblockdata.setValue(BlockProperties.LIT, true)); + world.gameEvent((Entity) itemactioncontext.getPlayer(), GameEvent.BLOCK_CHANGE, blockposition); diff --git a/patch-remap/og/net/minecraft/world/item/ItemFishingRod.patch b/patch-remap/og/net/minecraft/world/item/ItemFishingRod.patch new file mode 100644 index 0000000000..e35b245432 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemFishingRod.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/item/ItemFishingRod.java ++++ b/net/minecraft/world/item/ItemFishingRod.java +@@ -11,6 +11,11 @@ + import net.minecraft.world.level.World; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.event.player.PlayerFishEvent; ++import org.bukkit.craftbukkit.CraftEquipmentSlot; ++// CraftBukkit end ++ + public class ItemFishingRod extends Item implements ItemVanishable { + + public ItemFishingRod(Item.Info item_info) { +@@ -33,12 +38,23 @@ + world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.FISHING_BOBBER_RETRIEVE, SoundCategory.NEUTRAL, 1.0F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); + entityhuman.gameEvent(GameEvent.ITEM_INTERACT_FINISH); + } else { +- world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.FISHING_BOBBER_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); ++ // world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.FISHING_BOBBER_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); + if (!world.isClientSide) { + i = EnchantmentManager.getFishingSpeedBonus(itemstack); + int j = EnchantmentManager.getFishingLuckBonus(itemstack); + +- world.addFreshEntity(new EntityFishingHook(entityhuman, world, j, i)); ++ // CraftBukkit start ++ EntityFishingHook entityfishinghook = new EntityFishingHook(entityhuman, world, j, i); ++ PlayerFishEvent playerFishEvent = new PlayerFishEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), null, (org.bukkit.entity.FishHook) entityfishinghook.getBukkitEntity(), CraftEquipmentSlot.getHand(enumhand), PlayerFishEvent.State.FISHING); ++ world.getCraftServer().getPluginManager().callEvent(playerFishEvent); ++ ++ if (playerFishEvent.isCancelled()) { ++ entityhuman.fishing = null; ++ return InteractionResultWrapper.pass(itemstack); ++ } ++ world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.FISHING_BOBBER_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); ++ world.addFreshEntity(entityfishinghook); ++ // CraftBukkit end + } + + entityhuman.awardStat(StatisticList.ITEM_USED.get(this)); diff --git a/patch-remap/og/net/minecraft/world/item/ItemFlintAndSteel.patch b/patch-remap/og/net/minecraft/world/item/ItemFlintAndSteel.patch new file mode 100644 index 0000000000..4ecadc4d1e --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemFlintAndSteel.patch @@ -0,0 +1,32 @@ +--- a/net/minecraft/world/item/ItemFlintAndSteel.java ++++ b/net/minecraft/world/item/ItemFlintAndSteel.java +@@ -35,6 +35,14 @@ + BlockPosition blockposition1 = blockposition.relative(itemactioncontext.getClickedFace()); + + if (BlockFireAbstract.canBePlacedAt(world, blockposition1, itemactioncontext.getHorizontalDirection())) { ++ // CraftBukkit start - Store the clicked block ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition1, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL, entityhuman).isCancelled()) { ++ itemactioncontext.getItemInHand().hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(itemactioncontext.getHand()); ++ }); ++ return EnumInteractionResult.PASS; ++ } ++ // CraftBukkit end + world.playSound(entityhuman, blockposition1, SoundEffects.FLINTANDSTEEL_USE, SoundCategory.BLOCKS, 1.0F, world.getRandom().nextFloat() * 0.4F + 0.8F); + IBlockData iblockdata1 = BlockFireAbstract.getState(world, blockposition1); + +@@ -54,6 +62,14 @@ + return EnumInteractionResult.FAIL; + } + } else { ++ // CraftBukkit start - Store the clicked block ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL, entityhuman).isCancelled()) { ++ itemactioncontext.getItemInHand().hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(itemactioncontext.getHand()); ++ }); ++ return EnumInteractionResult.PASS; ++ } ++ // CraftBukkit end + world.playSound(entityhuman, blockposition, SoundEffects.FLINTANDSTEEL_USE, SoundCategory.BLOCKS, 1.0F, world.getRandom().nextFloat() * 0.4F + 0.8F); + world.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockProperties.LIT, true), 11); + world.gameEvent((Entity) entityhuman, GameEvent.BLOCK_CHANGE, blockposition); diff --git a/patch-remap/og/net/minecraft/world/item/ItemHanging.patch b/patch-remap/og/net/minecraft/world/item/ItemHanging.patch new file mode 100644 index 0000000000..e259a2f2fb --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemHanging.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/item/ItemHanging.java ++++ b/net/minecraft/world/item/ItemHanging.java +@@ -22,6 +22,11 @@ + import net.minecraft.world.level.World; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.entity.Player; ++import org.bukkit.event.hanging.HangingPlaceEvent; ++// CraftBukkit end ++ + public class ItemHanging extends Item { + + private static final IChatBaseComponent TOOLTIP_RANDOM_VARIANT = IChatBaseComponent.translatable("painting.random").withStyle(EnumChatFormat.GRAY); +@@ -72,6 +77,19 @@ + + if (((EntityHanging) object).survives()) { + if (!world.isClientSide) { ++ // CraftBukkit start - fire HangingPlaceEvent ++ Player who = (itemactioncontext.getPlayer() == null) ? null : (Player) itemactioncontext.getPlayer().getBukkitEntity(); ++ org.bukkit.block.Block blockClicked = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(enumdirection); ++ org.bukkit.inventory.EquipmentSlot hand = org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(itemactioncontext.getHand()); ++ ++ HangingPlaceEvent event = new HangingPlaceEvent((org.bukkit.entity.Hanging) ((EntityHanging) object).getBukkitEntity(), who, blockClicked, blockFace, hand, org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return EnumInteractionResult.FAIL; ++ } ++ // CraftBukkit end + ((EntityHanging) object).playPlacementSound(); + world.gameEvent((Entity) entityhuman, GameEvent.ENTITY_PLACE, ((EntityHanging) object).position()); + world.addFreshEntity((Entity) object); diff --git a/patch-remap/og/net/minecraft/world/item/ItemLeash.patch b/patch-remap/og/net/minecraft/world/item/ItemLeash.patch new file mode 100644 index 0000000000..53a585f225 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemLeash.patch @@ -0,0 +1,70 @@ +--- a/net/minecraft/world/item/ItemLeash.java ++++ b/net/minecraft/world/item/ItemLeash.java +@@ -15,6 +15,11 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AxisAlignedBB; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.CraftEquipmentSlot; ++import org.bukkit.event.hanging.HangingPlaceEvent; ++// CraftBukkit end ++ + public class ItemLeash extends Item { + + public ItemLeash(Item.Info item_info) { +@@ -31,7 +36,7 @@ + EntityHuman entityhuman = itemactioncontext.getPlayer(); + + if (!world.isClientSide && entityhuman != null) { +- bindPlayerMobs(entityhuman, world, blockposition); ++ bindPlayerMobs(entityhuman, world, blockposition, itemactioncontext.getHand()); // CraftBukkit - Pass hand + } + + return EnumInteractionResult.sidedSuccess(world.isClientSide); +@@ -40,7 +45,7 @@ + } + } + +- public static EnumInteractionResult bindPlayerMobs(EntityHuman entityhuman, World world, BlockPosition blockposition) { ++ public static EnumInteractionResult bindPlayerMobs(EntityHuman entityhuman, World world, BlockPosition blockposition, net.minecraft.world.EnumHand enumhand) { // CraftBukkit - Add EnumHand + EntityLeash entityleash = null; + boolean flag = false; + double d0 = 7.0D; +@@ -56,9 +61,26 @@ + if (entityinsentient.getLeashHolder() == entityhuman) { + if (entityleash == null) { + entityleash = EntityLeash.getOrCreateKnot(world, blockposition); ++ ++ // CraftBukkit start - fire HangingPlaceEvent ++ org.bukkit.inventory.EquipmentSlot hand = CraftEquipmentSlot.getHand(enumhand); ++ HangingPlaceEvent event = new HangingPlaceEvent((org.bukkit.entity.Hanging) entityleash.getBukkitEntity(), entityhuman != null ? (org.bukkit.entity.Player) entityhuman.getBukkitEntity() : null, world.getWorld().getBlockAt(i, j, k), org.bukkit.block.BlockFace.SELF, hand); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ entityleash.discard(); ++ return EnumInteractionResult.PASS; ++ } ++ // CraftBukkit end + entityleash.playPlacementSound(); + } + ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerLeashEntityEvent(entityinsentient, entityleash, entityhuman, enumhand).isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end ++ + entityinsentient.setLeashedTo(entityleash, true); + flag = true; + } +@@ -70,4 +92,10 @@ + + return flag ? EnumInteractionResult.SUCCESS : EnumInteractionResult.PASS; + } ++ ++ // CraftBukkit start ++ public static EnumInteractionResult bindPlayerMobs(EntityHuman entityhuman, World world, BlockPosition blockposition) { ++ return bindPlayerMobs(entityhuman, world, blockposition, net.minecraft.world.EnumHand.MAIN_HAND); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/item/ItemMilkBucket.patch b/patch-remap/og/net/minecraft/world/item/ItemMilkBucket.patch new file mode 100644 index 0000000000..43f0adc5b7 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemMilkBucket.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/item/ItemMilkBucket.java ++++ b/net/minecraft/world/item/ItemMilkBucket.java +@@ -31,7 +31,7 @@ + } + + if (!world.isClientSide) { +- entityliving.removeAllEffects(); ++ entityliving.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.MILK); // CraftBukkit + } + + return itemstack.isEmpty() ? new ItemStack(Items.BUCKET) : itemstack; diff --git a/patch-remap/og/net/minecraft/world/item/ItemMinecart.patch b/patch-remap/og/net/minecraft/world/item/ItemMinecart.patch new file mode 100644 index 0000000000..33589d482b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemMinecart.patch @@ -0,0 +1,72 @@ +--- a/net/minecraft/world/item/ItemMinecart.java ++++ b/net/minecraft/world/item/ItemMinecart.java +@@ -19,6 +19,12 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockDispenseEvent; ++// CraftBukkit end ++ + public class ItemMinecart extends Item { + + private static final IDispenseBehavior DISPENSE_ITEM_BEHAVIOR = new DispenseBehaviorItem() { +@@ -58,10 +64,39 @@ + } + } + +- EntityMinecartAbstract entityminecartabstract = EntityMinecartAbstract.createMinecart(worldserver, d0, d1 + d3, d2, ((ItemMinecart) itemstack.getItem()).type, itemstack, (EntityHuman) null); ++ // CraftBukkit start ++ // EntityMinecartAbstract entityminecartabstract = EntityMinecartAbstract.createMinecart(worldserver, d0, d1 + d3, d2, ((ItemMinecart) itemstack.getItem()).type); ++ ItemStack itemstack1 = itemstack.split(1); ++ org.bukkit.block.Block block2 = CraftBlock.at(worldserver, sourceblock.pos()); ++ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + +- worldserver.addFreshEntity(entityminecartabstract); +- itemstack.shrink(1); ++ BlockDispenseEvent event = new BlockDispenseEvent(block2, craftItem.clone(), new org.bukkit.util.Vector(d0, d1 + d3, d2)); ++ if (!BlockDispenser.eventFired) { ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (event.isCancelled()) { ++ itemstack.grow(1); ++ return itemstack; ++ } ++ ++ if (!event.getItem().equals(craftItem)) { ++ itemstack.grow(1); ++ // Chain to handler for new item ++ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); ++ IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.DISPENSER_REGISTRY.get(eventStack.getItem()); ++ if (idispensebehavior != IDispenseBehavior.NOOP && idispensebehavior != this) { ++ idispensebehavior.dispense(sourceblock, eventStack); ++ return itemstack; ++ } ++ } ++ ++ itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); ++ EntityMinecartAbstract entityminecartabstract = EntityMinecartAbstract.createMinecart(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), ((ItemMinecart) itemstack1.getItem()).type, itemstack1, (EntityHuman) null); ++ ++ if (!worldserver.addFreshEntity(entityminecartabstract)) itemstack.grow(1); ++ // itemstack.shrink(1); // CraftBukkit - handled during event processing ++ // CraftBukkit end + return itemstack; + } + +@@ -100,7 +135,12 @@ + + EntityMinecartAbstract entityminecartabstract = EntityMinecartAbstract.createMinecart(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.0625D + d0, (double) blockposition.getZ() + 0.5D, this.type, itemstack, itemactioncontext.getPlayer()); + +- worldserver.addFreshEntity(entityminecartabstract); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(itemactioncontext, entityminecartabstract).isCancelled()) { ++ return EnumInteractionResult.FAIL; ++ } ++ // CraftBukkit end ++ if (!worldserver.addFreshEntity(entityminecartabstract)) return EnumInteractionResult.PASS; // CraftBukkit + worldserver.gameEvent(GameEvent.ENTITY_PLACE, blockposition, GameEvent.a.of(itemactioncontext.getPlayer(), worldserver.getBlockState(blockposition.below()))); + } + diff --git a/patch-remap/og/net/minecraft/world/item/ItemMonsterEgg.patch b/patch-remap/og/net/minecraft/world/item/ItemMonsterEgg.patch new file mode 100644 index 0000000000..72316a341e --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemMonsterEgg.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/item/ItemMonsterEgg.java ++++ b/net/minecraft/world/item/ItemMonsterEgg.java +@@ -180,7 +180,7 @@ + return Optional.empty(); + } else { + ((EntityInsentient) object).moveTo(vec3d.x(), vec3d.y(), vec3d.z(), 0.0F, 0.0F); +- worldserver.addFreshEntityWithPassengers((Entity) object); ++ worldserver.addFreshEntityWithPassengers((Entity) object, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG); // CraftBukkit + if (itemstack.hasCustomHoverName()) { + ((EntityInsentient) object).setCustomName(itemstack.getHoverName()); + } +@@ -189,7 +189,7 @@ + itemstack.shrink(1); + } + +- return Optional.of(object); ++ return Optional.of((EntityInsentient) object); // CraftBukkit - decompile error + } + } + } diff --git a/patch-remap/og/net/minecraft/world/item/ItemPotion.patch b/patch-remap/og/net/minecraft/world/item/ItemPotion.patch new file mode 100644 index 0000000000..70bceabbb2 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemPotion.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/item/ItemPotion.java ++++ b/net/minecraft/world/item/ItemPotion.java +@@ -60,7 +60,7 @@ + if (mobeffect.getEffect().isInstantenous()) { + mobeffect.getEffect().applyInstantenousEffect(entityhuman, entityhuman, entityliving, mobeffect.getAmplifier(), 1.0D); + } else { +- entityliving.addEffect(new MobEffect(mobeffect)); ++ entityliving.addEffect(new MobEffect(mobeffect), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_DRINK); // CraftBukkit + } + } + } diff --git a/patch-remap/og/net/minecraft/world/item/ItemRecord.patch b/patch-remap/og/net/minecraft/world/item/ItemRecord.patch new file mode 100644 index 0000000000..74b4bd490d --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemRecord.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/world/item/ItemRecord.java ++++ b/net/minecraft/world/item/ItemRecord.java +@@ -46,6 +46,7 @@ + ItemStack itemstack = itemactioncontext.getItemInHand(); + + if (!world.isClientSide) { ++ if (true) return EnumInteractionResult.SUCCESS; // CraftBukkit - handled in ItemStack + EntityHuman entityhuman = itemactioncontext.getPlayer(); + TileEntity tileentity = world.getBlockEntity(blockposition); + diff --git a/patch-remap/og/net/minecraft/world/item/ItemSign.patch b/patch-remap/og/net/minecraft/world/item/ItemSign.patch new file mode 100644 index 0000000000..2b304e15d8 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemSign.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/world/item/ItemSign.java ++++ b/net/minecraft/world/item/ItemSign.java +@@ -13,6 +13,8 @@ + + public class ItemSign extends ItemBlockWallable { + ++ public static BlockPosition openSign; // CraftBukkit ++ + public ItemSign(Item.Info item_info, Block block, Block block1) { + super(block, block1, item_info, EnumDirection.DOWN); + } +@@ -35,7 +37,10 @@ + if (block instanceof BlockSign) { + BlockSign blocksign = (BlockSign) block; + +- blocksign.openTextEdit(entityhuman, tileentitysign, true); ++ // CraftBukkit start - SPIGOT-4678 ++ // blocksign.openTextEdit(entityhuman, tileentitysign, true); ++ ItemSign.openSign = blockposition; ++ // CraftBukkit end + } + } + } diff --git a/patch-remap/og/net/minecraft/world/item/ItemSnowball.patch b/patch-remap/og/net/minecraft/world/item/ItemSnowball.patch new file mode 100644 index 0000000000..84f81c9d47 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemSnowball.patch @@ -0,0 +1,37 @@ +--- a/net/minecraft/world/item/ItemSnowball.java ++++ b/net/minecraft/world/item/ItemSnowball.java +@@ -19,19 +19,32 @@ + public InteractionResultWrapper use(World world, EntityHuman entityhuman, EnumHand enumhand) { + ItemStack itemstack = entityhuman.getItemInHand(enumhand); + +- world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.SNOWBALL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); ++ // CraftBukkit - moved down ++ // world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.SNOWBALL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); + if (!world.isClientSide) { + EntitySnowball entitysnowball = new EntitySnowball(world, entityhuman); + + entitysnowball.setItem(itemstack); + entitysnowball.shootFromRotation(entityhuman, entityhuman.getXRot(), entityhuman.getYRot(), 0.0F, 1.5F, 1.0F); +- world.addFreshEntity(entitysnowball); ++ if (world.addFreshEntity(entitysnowball)) { ++ if (!entityhuman.getAbilities().instabuild) { ++ itemstack.shrink(1); ++ } ++ ++ world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.SNOWBALL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); ++ } else if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { ++ ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } + } ++ // CraftBukkit end + + entityhuman.awardStat(StatisticList.ITEM_USED.get(this)); ++ // CraftBukkit start - moved up ++ /* + if (!entityhuman.getAbilities().instabuild) { + itemstack.shrink(1); + } ++ */ + + return InteractionResultWrapper.sidedSuccess(itemstack, world.isClientSide()); + } diff --git a/patch-remap/og/net/minecraft/world/item/ItemStack.patch b/patch-remap/og/net/minecraft/world/item/ItemStack.patch new file mode 100644 index 0000000000..0b0e59dac4 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemStack.patch @@ -0,0 +1,337 @@ +--- a/net/minecraft/world/item/ItemStack.java ++++ b/net/minecraft/world/item/ItemStack.java +@@ -81,6 +81,43 @@ + import net.minecraft.world.level.block.state.pattern.ShapeDetectorBlock; + import org.slf4j.Logger; + ++// CraftBukkit start ++import com.mojang.serialization.Dynamic; ++import java.util.Map; ++import java.util.Objects; ++import net.minecraft.core.EnumDirection; ++import net.minecraft.nbt.DynamicOpsNBT; ++import net.minecraft.network.protocol.game.PacketPlayOutBlockChange; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.WorldServer; ++import net.minecraft.sounds.SoundCategory; ++import net.minecraft.util.datafix.fixes.DataConverterTypes; ++import net.minecraft.world.level.block.BlockBed; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.BlockSapling; ++import net.minecraft.world.level.block.BlockSign; ++import net.minecraft.world.level.block.BlockTileEntity; ++import net.minecraft.world.level.block.BlockWitherSkull; ++import net.minecraft.world.level.block.SoundEffectType; ++import net.minecraft.world.level.block.entity.TileEntity; ++import net.minecraft.world.level.block.entity.TileEntityJukeBox; ++import net.minecraft.world.level.block.entity.TileEntitySign; ++import net.minecraft.world.level.block.entity.TileEntitySkull; ++import net.minecraft.world.level.gameevent.GameEvent; ++import org.bukkit.Location; ++import org.bukkit.TreeType; ++import org.bukkit.block.BlockState; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.entity.Player; ++import org.bukkit.event.block.BlockFertilizeEvent; ++import org.bukkit.event.player.PlayerItemDamageEvent; ++import org.bukkit.event.world.StructureGrowEvent; ++// CraftBukkit end ++ + public final class ItemStack { + + public static final Codec CODEC = RecordCodecBuilder.create((instance) -> { +@@ -175,7 +212,18 @@ + this.item = null; + } + +- private ItemStack(NBTTagCompound nbttagcompound) { ++ // Called to run this stack through the data converter to handle older storage methods and serialized items ++ public void convertStack(int version) { ++ if (0 < version && version < CraftMagicNumbers.INSTANCE.getDataVersion()) { ++ NBTTagCompound savedStack = new NBTTagCompound(); ++ this.save(savedStack); ++ savedStack = (NBTTagCompound) MinecraftServer.getServer().fixerUpper.update(DataConverterTypes.ITEM_STACK, new Dynamic(DynamicOpsNBT.INSTANCE, savedStack), version, CraftMagicNumbers.INSTANCE.getDataVersion()).getValue(); ++ this.load(savedStack); ++ } ++ } ++ ++ // CraftBukkit - break into own method ++ private void load(NBTTagCompound nbttagcompound) { + this.item = (Item) BuiltInRegistries.ITEM.get(new MinecraftKey(nbttagcompound.getString("id"))); + this.count = nbttagcompound.getByte("Count"); + if (nbttagcompound.contains("tag", 10)) { +@@ -189,6 +237,11 @@ + + } + ++ private ItemStack(NBTTagCompound nbttagcompound) { ++ this.load(nbttagcompound); ++ // CraftBukkit end ++ } ++ + public static ItemStack of(NBTTagCompound nbttagcompound) { + try { + return new ItemStack(nbttagcompound); +@@ -266,11 +319,190 @@ + return EnumInteractionResult.PASS; + } else { + Item item = this.getItem(); +- EnumInteractionResult enuminteractionresult = item.useOn(itemactioncontext); ++ // CraftBukkit start - handle all block place event logic here ++ NBTTagCompound oldData = this.getTagClone(); ++ int oldCount = this.getCount(); ++ WorldServer world = (WorldServer) itemactioncontext.getLevel(); ++ ++ if (!(item instanceof ItemBucket || item instanceof SolidBucketItem)) { // if not bucket ++ world.captureBlockStates = true; ++ // special case bonemeal ++ if (item == Items.BONE_MEAL) { ++ world.captureTreeGeneration = true; ++ } ++ } ++ EnumInteractionResult enuminteractionresult; ++ try { ++ enuminteractionresult = item.useOn(itemactioncontext); ++ } finally { ++ world.captureBlockStates = false; ++ } ++ NBTTagCompound newData = this.getTagClone(); ++ int newCount = this.getCount(); ++ this.setCount(oldCount); ++ this.setTagClone(oldData); ++ if (enuminteractionresult.consumesAction() && world.captureTreeGeneration && world.capturedBlockStates.size() > 0) { ++ world.captureTreeGeneration = false; ++ Location location = CraftLocation.toBukkit(blockposition, world.getWorld()); ++ TreeType treeType = BlockSapling.treeType; ++ BlockSapling.treeType = null; ++ List blocks = new java.util.ArrayList<>(world.capturedBlockStates.values()); ++ world.capturedBlockStates.clear(); ++ StructureGrowEvent structureEvent = null; ++ if (treeType != null) { ++ boolean isBonemeal = getItem() == Items.BONE_MEAL; ++ structureEvent = new StructureGrowEvent(location, treeType, isBonemeal, (Player) entityhuman.getBukkitEntity(), (List< BlockState>) (List) blocks); ++ org.bukkit.Bukkit.getPluginManager().callEvent(structureEvent); ++ } ++ ++ BlockFertilizeEvent fertilizeEvent = new BlockFertilizeEvent(CraftBlock.at(world, blockposition), (Player) entityhuman.getBukkitEntity(), (List< BlockState>) (List) blocks); ++ fertilizeEvent.setCancelled(structureEvent != null && structureEvent.isCancelled()); ++ org.bukkit.Bukkit.getPluginManager().callEvent(fertilizeEvent); ++ ++ if (!fertilizeEvent.isCancelled()) { ++ // Change the stack to its new contents if it hasn't been tampered with. ++ if (this.getCount() == oldCount && Objects.equals(this.tag, oldData)) { ++ this.setTag(newData); ++ this.setCount(newCount); ++ } ++ for (CraftBlockState blockstate : blocks) { ++ world.setBlock(blockstate.getPosition(),blockstate.getHandle(), blockstate.getFlag()); // SPIGOT-7248 - manual update to avoid physics where appropriate ++ } ++ entityhuman.awardStat(StatisticList.ITEM_USED.get(item)); // SPIGOT-7236 - award stat ++ } ++ ++ ItemSign.openSign = null; // SPIGOT-6758 - Reset on early return ++ return enuminteractionresult; ++ } ++ world.captureTreeGeneration = false; + + if (entityhuman != null && enuminteractionresult.shouldAwardStats()) { +- entityhuman.awardStat(StatisticList.ITEM_USED.get(item)); ++ EnumHand enumhand = itemactioncontext.getHand(); ++ org.bukkit.event.block.BlockPlaceEvent placeEvent = null; ++ List blocks = new java.util.ArrayList<>(world.capturedBlockStates.values()); ++ world.capturedBlockStates.clear(); ++ if (blocks.size() > 1) { ++ placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockMultiPlaceEvent(world, entityhuman, enumhand, blocks, blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ } else if (blocks.size() == 1) { ++ placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEvent(world, entityhuman, enumhand, blocks.get(0), blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ } ++ ++ if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild())) { ++ enuminteractionresult = EnumInteractionResult.FAIL; // cancel placement ++ // PAIL: Remove this when MC-99075 fixed ++ placeEvent.getPlayer().updateInventory(); ++ // revert back all captured blocks ++ world.preventPoiUpdated = true; // CraftBukkit - SPIGOT-5710 ++ for (BlockState blockstate : blocks) { ++ blockstate.update(true, false); ++ } ++ world.preventPoiUpdated = false; ++ ++ // Brute force all possible updates ++ BlockPosition placedPos = ((CraftBlock) placeEvent.getBlock()).getPosition(); ++ for (EnumDirection dir : EnumDirection.values()) { ++ ((EntityPlayer) entityhuman).connection.send(new PacketPlayOutBlockChange(world, placedPos.relative(dir))); ++ } ++ ItemSign.openSign = null; // SPIGOT-6758 - Reset on early return ++ } else { ++ // Change the stack to its new contents if it hasn't been tampered with. ++ if (this.getCount() == oldCount && Objects.equals(this.tag, oldData)) { ++ this.setTag(newData); ++ this.setCount(newCount); ++ } ++ ++ for (Map.Entry e : world.capturedTileEntities.entrySet()) { ++ world.setBlockEntity(e.getValue()); ++ } ++ ++ for (BlockState blockstate : blocks) { ++ int updateFlag = ((CraftBlockState) blockstate).getFlag(); ++ IBlockData oldBlock = ((CraftBlockState) blockstate).getHandle(); ++ BlockPosition newblockposition = ((CraftBlockState) blockstate).getPosition(); ++ IBlockData block = world.getBlockState(newblockposition); ++ ++ if (!(block.getBlock() instanceof BlockTileEntity)) { // Containers get placed automatically ++ block.getBlock().onPlace(block, world, newblockposition, oldBlock, true); ++ } ++ ++ world.notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, world.getBlockState(newblockposition), updateFlag, 512); // send null chunk as chunk.k() returns false by this point ++ } ++ ++ // Special case juke boxes as they update their tile entity. Copied from ItemRecord. ++ // PAIL: checkme on updates. ++ if (this.item instanceof ItemRecord) { ++ TileEntity tileentity = world.getBlockEntity(blockposition); ++ ++ if (tileentity instanceof TileEntityJukeBox) { ++ TileEntityJukeBox tileentityjukebox = (TileEntityJukeBox) tileentity; ++ ++ // There can only be one ++ ItemStack record = this.copy(); ++ if (!record.isEmpty()) { ++ record.setCount(1); ++ } ++ ++ tileentityjukebox.setTheItem(record); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.a.of(entityhuman, world.getBlockState(blockposition))); ++ } ++ ++ this.shrink(1); ++ entityhuman.awardStat(StatisticList.PLAY_RECORD); ++ } ++ ++ if (this.item == Items.WITHER_SKELETON_SKULL) { // Special case skulls to allow wither spawns to be cancelled ++ BlockPosition bp = blockposition; ++ if (!world.getBlockState(blockposition).canBeReplaced()) { ++ if (!world.getBlockState(blockposition).isSolid()) { ++ bp = null; ++ } else { ++ bp = bp.relative(itemactioncontext.getClickedFace()); ++ } ++ } ++ if (bp != null) { ++ TileEntity te = world.getBlockEntity(bp); ++ if (te instanceof TileEntitySkull) { ++ BlockWitherSkull.checkSpawn(world, bp, (TileEntitySkull) te); ++ } ++ } ++ } ++ ++ // SPIGOT-4678 ++ if (this.item instanceof ItemSign && ItemSign.openSign != null) { ++ try { ++ if (world.getBlockEntity(ItemSign.openSign) instanceof TileEntitySign tileentitysign) { ++ if (world.getBlockState(ItemSign.openSign).getBlock() instanceof BlockSign blocksign) { ++ blocksign.openTextEdit(entityhuman, tileentitysign, true, org.bukkit.event.player.PlayerSignOpenEvent.Cause.PLACE); // Craftbukkit ++ } ++ } ++ } finally { ++ ItemSign.openSign = null; ++ } ++ } ++ ++ // SPIGOT-7315: Moved from BlockBed#setPlacedBy ++ if (placeEvent != null && this.item instanceof ItemBed) { ++ BlockPosition position = ((CraftBlock) placeEvent.getBlock()).getPosition(); ++ IBlockData blockData = world.getBlockState(position); ++ ++ if (blockData.getBlock() instanceof BlockBed) { ++ world.blockUpdated(position, Blocks.AIR); ++ blockData.updateNeighbourShapes(world, position, 3); ++ } ++ } ++ ++ // SPIGOT-1288 - play sound stripped from ItemBlock ++ if (this.item instanceof ItemBlock) { ++ SoundEffectType soundeffecttype = ((ItemBlock) this.item).getBlock().defaultBlockState().getSoundType(); // TODO: not strictly correct, however currently only affects decorated pots ++ world.playSound(entityhuman, blockposition, soundeffecttype.getPlaceSound(), SoundCategory.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F); ++ } ++ ++ entityhuman.awardStat(StatisticList.ITEM_USED.get(item)); ++ } + } ++ world.capturedTileEntities.clear(); ++ world.capturedBlockStates.clear(); ++ // CraftBukkit end + + return enuminteractionresult; + } +@@ -351,6 +583,21 @@ + } + + i -= k; ++ // CraftBukkit start ++ if (entityplayer != null) { ++ PlayerItemDamageEvent event = new PlayerItemDamageEvent(entityplayer.getBukkitEntity(), CraftItemStack.asCraftMirror(this), i); ++ event.getPlayer().getServer().getPluginManager().callEvent(event); ++ ++ if (i != event.getDamage() || event.isCancelled()) { ++ event.getPlayer().updateInventory(); ++ } ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ i = event.getDamage(); ++ } ++ // CraftBukkit end + if (i <= 0) { + return false; + } +@@ -372,6 +619,11 @@ + if (this.hurt(i, t0.getRandom(), t0 instanceof EntityPlayer ? (EntityPlayer) t0 : null)) { + consumer.accept(t0); + Item item = this.getItem(); ++ // CraftBukkit start - Check for item breaking ++ if (this.count == 1 && t0 instanceof EntityHuman) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemBreakEvent((EntityHuman) t0, this); ++ } ++ // CraftBukkit end + + this.shrink(1); + if (t0 instanceof EntityHuman) { +@@ -524,6 +776,17 @@ + return this.tag; + } + ++ // CraftBukkit start ++ @Nullable ++ private NBTTagCompound getTagClone() { ++ return this.tag == null ? null : this.tag.copy(); ++ } ++ ++ private void setTagClone(@Nullable NBTTagCompound nbtttagcompound) { ++ this.setTag(nbtttagcompound == null ? null : nbtttagcompound.copy()); ++ } ++ // CraftBukkit end ++ + public NBTTagCompound getOrCreateTag() { + if (this.tag == null) { + this.setTag(new NBTTagCompound()); +@@ -948,6 +1211,13 @@ + nbttaglist.add(nbttagcompound); + } + ++ // CraftBukkit start ++ @Deprecated ++ public void setItem(Item item) { ++ this.item = item; ++ } ++ // CraftBukkit end ++ + public IChatBaseComponent getDisplayName() { + IChatMutableComponent ichatmutablecomponent = IChatBaseComponent.empty().append(this.getHoverName()); + diff --git a/patch-remap/og/net/minecraft/world/item/ItemTrident.patch b/patch-remap/og/net/minecraft/world/item/ItemTrident.patch new file mode 100644 index 0000000000..9fbf8a3290 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemTrident.patch @@ -0,0 +1,56 @@ +--- a/net/minecraft/world/item/ItemTrident.java ++++ b/net/minecraft/world/item/ItemTrident.java +@@ -68,9 +68,12 @@ + + if (k <= 0 || entityhuman.isInWaterOrRain()) { + if (!world.isClientSide) { ++ // CraftBukkit - moved down ++ /* + itemstack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { + entityhuman1.broadcastBreakEvent(entityliving.getUsedItemHand()); + }); ++ */ + if (k == 0) { + EntityThrownTrident entitythrowntrident = new EntityThrownTrident(world, entityhuman, itemstack); + +@@ -79,16 +82,39 @@ + entitythrowntrident.pickup = EntityArrow.PickupStatus.CREATIVE_ONLY; + } + +- world.addFreshEntity(entitythrowntrident); ++ // CraftBukkit start ++ if (!world.addFreshEntity(entitythrowntrident)) { ++ if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { ++ ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); ++ } ++ return; ++ } ++ ++ itemstack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(entityliving.getUsedItemHand()); ++ }); ++ entitythrowntrident.pickupItemStack = itemstack.copy(); // SPIGOT-4511 update since damage call moved ++ // CraftBukkit end ++ + world.playSound((EntityHuman) null, (Entity) entitythrowntrident, SoundEffects.TRIDENT_THROW, SoundCategory.PLAYERS, 1.0F, 1.0F); + if (!entityhuman.getAbilities().instabuild) { + entityhuman.getInventory().removeItem(itemstack); + } ++ // CraftBukkit start - SPIGOT-5458 also need in this branch :( ++ } else { ++ itemstack.hurtAndBreak(1, entityhuman, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(entityliving.getUsedItemHand()); ++ }); ++ // CraftBukkkit end + } + } + + entityhuman.awardStat(StatisticList.ITEM_USED.get(this)); + if (k > 0) { ++ // CraftBukkit start ++ org.bukkit.event.player.PlayerRiptideEvent event = new org.bukkit.event.player.PlayerRiptideEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); ++ event.getPlayer().getServer().getPluginManager().callEvent(event); ++ // CraftBukkit end + float f = entityhuman.getYRot(); + float f1 = entityhuman.getXRot(); + float f2 = -MathHelper.sin(f * 0.017453292F) * MathHelper.cos(f1 * 0.017453292F); diff --git a/patch-remap/og/net/minecraft/world/item/ItemWorldMap.patch b/patch-remap/og/net/minecraft/world/item/ItemWorldMap.patch new file mode 100644 index 0000000000..a3353d72e8 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/ItemWorldMap.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/item/ItemWorldMap.java ++++ b/net/minecraft/world/item/ItemWorldMap.java +@@ -69,7 +69,7 @@ + public static Integer getMapId(ItemStack itemstack) { + NBTTagCompound nbttagcompound = itemstack.getTag(); + +- return nbttagcompound != null && nbttagcompound.contains("map", 99) ? nbttagcompound.getInt("map") : null; ++ return nbttagcompound != null && nbttagcompound.contains("map", 99) ? nbttagcompound.getInt("map") : -1; // CraftBukkit - make new maps for no tag + } + + public static int createNewSavedData(World world, int i, int j, int k, boolean flag, boolean flag1, ResourceKey resourcekey) { diff --git a/patch-remap/og/net/minecraft/world/item/crafting/CraftingManager.patch b/patch-remap/og/net/minecraft/world/item/crafting/CraftingManager.patch new file mode 100644 index 0000000000..ee7d2c7245 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/crafting/CraftingManager.patch @@ -0,0 +1,143 @@ +--- a/net/minecraft/world/item/crafting/CraftingManager.java ++++ b/net/minecraft/world/item/crafting/CraftingManager.java +@@ -34,11 +34,16 @@ + import net.minecraft.world.level.World; + import org.slf4j.Logger; + ++// CraftBukkit start ++import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; ++import net.minecraft.core.registries.BuiltInRegistries; ++// CraftBukkit end ++ + public class CraftingManager extends ResourceDataJson { + + private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().disableHtmlEscaping().create(); + private static final Logger LOGGER = LogUtils.getLogger(); +- public Map, Map>> recipes = ImmutableMap.of(); ++ public Map, Object2ObjectLinkedOpenHashMap>> recipes = ImmutableMap.of(); // CraftBukkit + private Map> byName = ImmutableMap.of(); + private boolean hasErrors; + +@@ -48,7 +53,12 @@ + + protected void apply(Map map, IResourceManager iresourcemanager, GameProfilerFiller gameprofilerfiller) { + this.hasErrors = false; +- Map, Builder>> map1 = Maps.newHashMap(); ++ // CraftBukkit start - SPIGOT-5667 make sure all types are populated and mutable ++ Map, Object2ObjectLinkedOpenHashMap>> map1 = Maps.newHashMap(); ++ for (Recipes recipeType : BuiltInRegistries.RECIPE_TYPE) { ++ map1.put(recipeType, new Object2ObjectLinkedOpenHashMap<>()); ++ } ++ // CraftBukkit end + Builder> builder = ImmutableMap.builder(); + Iterator iterator = map.entrySet().iterator(); + +@@ -59,8 +69,10 @@ + try { + RecipeHolder recipeholder = fromJson(minecraftkey, ChatDeserializer.convertToJsonObject((JsonElement) entry.getValue(), "top element")); + +- ((Builder) map1.computeIfAbsent(recipeholder.value().getType(), (recipes) -> { +- return ImmutableMap.builder(); ++ // CraftBukkit start ++ (map1.computeIfAbsent(recipeholder.value().getType(), (recipes) -> { ++ return new Object2ObjectLinkedOpenHashMap<>(); ++ // CraftBukkit end + })).put(minecraftkey, recipeholder); + builder.put(minecraftkey, recipeholder); + } catch (IllegalArgumentException | JsonParseException jsonparseexception) { +@@ -69,20 +81,37 @@ + } + + this.recipes = (Map) map1.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry1) -> { +- return ((Builder) entry1.getValue()).build(); ++ return (entry1.getValue()); // CraftBukkit + })); +- this.byName = builder.build(); ++ this.byName = Maps.newHashMap(builder.build()); // CraftBukkit + CraftingManager.LOGGER.info("Loaded {} recipes", map1.size()); + } + ++ // CraftBukkit start ++ public void addRecipe(RecipeHolder irecipe) { ++ Object2ObjectLinkedOpenHashMap> map = this.recipes.get(irecipe.value().getType()); // CraftBukkit ++ ++ if (byName.containsKey(irecipe.id()) || map.containsKey(irecipe.id())) { ++ throw new IllegalStateException("Duplicate recipe ignored with ID " + irecipe.id()); ++ } else { ++ map.putAndMoveToFirst(irecipe.id(), irecipe); // CraftBukkit - SPIGOT-4638: last recipe gets priority ++ byName.put(irecipe.id(), irecipe); ++ } ++ } ++ // CraftBukkit end ++ + public boolean hadErrorsLoading() { + return this.hasErrors; + } + + public > Optional> getRecipeFor(Recipes recipes, C c0, World world) { +- return this.byType(recipes).values().stream().filter((recipeholder) -> { ++ // CraftBukkit start ++ Optional> recipe = this.byType(recipes).values().stream().filter((recipeholder) -> { + return recipeholder.value().matches(c0, world); + }).findFirst(); ++ c0.setCurrentRecipe(recipe.orElse(null)); // CraftBukkit - Clear recipe when no recipe is found ++ return recipe; ++ // CraftBukkit end + } + + public > Optional>> getRecipeFor(Recipes recipes, C c0, World world, @Nullable MinecraftKey minecraftkey) { +@@ -116,7 +145,7 @@ + } + + private > Map> byType(Recipes recipes) { +- return (Map) this.recipes.getOrDefault(recipes, Collections.emptyMap()); ++ return (Map) this.recipes.getOrDefault(recipes, new Object2ObjectLinkedOpenHashMap<>()); // CraftBukkit + } + + public > NonNullList getRemainingItemsFor(Recipes recipes, C c0, World world) { +@@ -159,12 +188,12 @@ + + public void replaceRecipes(Iterable> iterable) { + this.hasErrors = false; +- Map, Map>> map = Maps.newHashMap(); ++ Map, Object2ObjectLinkedOpenHashMap>> map = Maps.newHashMap(); // CraftBukkit + Builder> builder = ImmutableMap.builder(); + + iterable.forEach((recipeholder) -> { + Map> map1 = (Map) map.computeIfAbsent(recipeholder.value().getType(), (recipes) -> { +- return Maps.newHashMap(); ++ return new Object2ObjectLinkedOpenHashMap<>(); // CraftBukkit + }); + MinecraftKey minecraftkey = recipeholder.id(); + RecipeHolder recipeholder1 = (RecipeHolder) map1.put(minecraftkey, recipeholder); +@@ -175,9 +204,29 @@ + } + }); + this.recipes = ImmutableMap.copyOf(map); +- this.byName = builder.build(); ++ this.byName = Maps.newHashMap(builder.build()); // CraftBukkit + } + ++ // CraftBukkit start ++ public boolean removeRecipe(MinecraftKey mcKey) { ++ for (Object2ObjectLinkedOpenHashMap> recipes : recipes.values()) { ++ recipes.remove(mcKey); ++ } ++ ++ return byName.remove(mcKey) != null; ++ } ++ ++ public void clearRecipes() { ++ this.recipes = Maps.newHashMap(); ++ ++ for (Recipes recipeType : BuiltInRegistries.RECIPE_TYPE) { ++ this.recipes.put(recipeType, new Object2ObjectLinkedOpenHashMap<>()); ++ } ++ ++ this.byName = Maps.newHashMap(); ++ } ++ // CraftBukkit end ++ + public static > CraftingManager.a createCheck(final Recipes recipes) { + return new CraftingManager.a() { + @Nullable diff --git a/patch-remap/og/net/minecraft/world/item/crafting/FurnaceRecipe.patch b/patch-remap/og/net/minecraft/world/item/crafting/FurnaceRecipe.patch new file mode 100644 index 0000000000..30ac7e9127 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/crafting/FurnaceRecipe.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/item/crafting/FurnaceRecipe.java ++++ b/net/minecraft/world/item/crafting/FurnaceRecipe.java +@@ -3,6 +3,14 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftFurnaceRecipe; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class FurnaceRecipe extends RecipeCooking { + + public FurnaceRecipe(String s, CookingBookCategory cookingbookcategory, RecipeItemStack recipeitemstack, ItemStack itemstack, float f, int i) { +@@ -18,4 +26,17 @@ + public RecipeSerializer getSerializer() { + return RecipeSerializer.SMELTING_RECIPE; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftFurnaceRecipe recipe = new CraftFurnaceRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/item/crafting/IRecipe.patch b/patch-remap/og/net/minecraft/world/item/crafting/IRecipe.patch new file mode 100644 index 0000000000..ef02d2d023 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/crafting/IRecipe.patch @@ -0,0 +1,9 @@ +--- a/net/minecraft/world/item/crafting/IRecipe.java ++++ b/net/minecraft/world/item/crafting/IRecipe.java +@@ -67,4 +67,6 @@ + return recipeitemstack.getItems().length == 0; + }); + } ++ ++ org.bukkit.inventory.Recipe toBukkitRecipe(org.bukkit.NamespacedKey id); // CraftBukkit + } diff --git a/patch-remap/og/net/minecraft/world/item/crafting/IRecipeComplex.patch b/patch-remap/og/net/minecraft/world/item/crafting/IRecipeComplex.patch new file mode 100644 index 0000000000..80ea716a5d --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/crafting/IRecipeComplex.patch @@ -0,0 +1,26 @@ +--- a/net/minecraft/world/item/crafting/IRecipeComplex.java ++++ b/net/minecraft/world/item/crafting/IRecipeComplex.java +@@ -3,6 +3,11 @@ + import net.minecraft.core.IRegistryCustom; + import net.minecraft.world.item.ItemStack; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public abstract class IRecipeComplex implements RecipeCrafting { + + private final CraftingBookCategory category; +@@ -25,4 +30,11 @@ + public CraftingBookCategory category() { + return this.category; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ return new org.bukkit.craftbukkit.inventory.CraftComplexRecipe(id, this); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/item/crafting/RecipeBlasting.patch b/patch-remap/og/net/minecraft/world/item/crafting/RecipeBlasting.patch new file mode 100644 index 0000000000..daa0c936b0 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/crafting/RecipeBlasting.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/item/crafting/RecipeBlasting.java ++++ b/net/minecraft/world/item/crafting/RecipeBlasting.java +@@ -3,6 +3,14 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftBlastingRecipe; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class RecipeBlasting extends RecipeCooking { + + public RecipeBlasting(String s, CookingBookCategory cookingbookcategory, RecipeItemStack recipeitemstack, ItemStack itemstack, float f, int i) { +@@ -18,4 +26,17 @@ + public RecipeSerializer getSerializer() { + return RecipeSerializer.BLASTING_RECIPE; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftBlastingRecipe recipe = new CraftBlastingRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/item/crafting/RecipeCampfire.patch b/patch-remap/og/net/minecraft/world/item/crafting/RecipeCampfire.patch new file mode 100644 index 0000000000..fa7909db0b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/crafting/RecipeCampfire.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/item/crafting/RecipeCampfire.java ++++ b/net/minecraft/world/item/crafting/RecipeCampfire.java +@@ -3,6 +3,14 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftCampfireRecipe; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class RecipeCampfire extends RecipeCooking { + + public RecipeCampfire(String s, CookingBookCategory cookingbookcategory, RecipeItemStack recipeitemstack, ItemStack itemstack, float f, int i) { +@@ -18,4 +26,17 @@ + public RecipeSerializer getSerializer() { + return RecipeSerializer.CAMPFIRE_COOKING_RECIPE; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftCampfireRecipe recipe = new CraftCampfireRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/item/crafting/RecipeHolder.patch b/patch-remap/og/net/minecraft/world/item/crafting/RecipeHolder.patch new file mode 100644 index 0000000000..980b0b897b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/crafting/RecipeHolder.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/item/crafting/RecipeHolder.java ++++ b/net/minecraft/world/item/crafting/RecipeHolder.java +@@ -2,7 +2,16 @@ + + import net.minecraft.resources.MinecraftKey; + +-public record RecipeHolder> (MinecraftKey id, T value) { ++// CraftBukkit start ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.inventory.Recipe; ++ ++public record RecipeHolder>(MinecraftKey id, T value) { ++ ++ public final Recipe toBukkitRecipe() { ++ return this.value.toBukkitRecipe(CraftNamespacedKey.fromMinecraft(this.id)); ++ } ++ // CraftBukkit end + + public boolean equals(Object object) { + if (this == object) { diff --git a/patch-remap/og/net/minecraft/world/item/crafting/RecipeItemStack.patch b/patch-remap/og/net/minecraft/world/item/crafting/RecipeItemStack.patch new file mode 100644 index 0000000000..45fa2e7694 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/crafting/RecipeItemStack.patch @@ -0,0 +1,26 @@ +--- a/net/minecraft/world/item/crafting/RecipeItemStack.java ++++ b/net/minecraft/world/item/crafting/RecipeItemStack.java +@@ -35,6 +35,7 @@ + public ItemStack[] itemStacks; + @Nullable + private IntList stackingIds; ++ public boolean exact; // CraftBukkit + public static final Codec CODEC = codec(true); + public static final Codec CODEC_NONEMPTY = codec(false); + +@@ -72,6 +73,15 @@ + for (int j = 0; j < i; ++j) { + ItemStack itemstack1 = aitemstack[j]; + ++ // CraftBukkit start ++ if (exact) { ++ if (itemstack1.getItem() == itemstack.getItem() && ItemStack.isSameItemSameTags(itemstack, itemstack1)) { ++ return true; ++ } ++ ++ continue; ++ } ++ // CraftBukkit end + if (itemstack1.is(itemstack.getItem())) { + return true; + } diff --git a/patch-remap/og/net/minecraft/world/item/crafting/RecipeSmoking.patch b/patch-remap/og/net/minecraft/world/item/crafting/RecipeSmoking.patch new file mode 100644 index 0000000000..2fe0991274 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/crafting/RecipeSmoking.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/item/crafting/RecipeSmoking.java ++++ b/net/minecraft/world/item/crafting/RecipeSmoking.java +@@ -3,6 +3,14 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftSmokingRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class RecipeSmoking extends RecipeCooking { + + public RecipeSmoking(String s, CookingBookCategory cookingbookcategory, RecipeItemStack recipeitemstack, ItemStack itemstack, float f, int i) { +@@ -18,4 +26,17 @@ + public RecipeSerializer getSerializer() { + return RecipeSerializer.SMOKING_RECIPE; + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftSmokingRecipe recipe = new CraftSmokingRecipe(id, result, CraftRecipe.toBukkit(this.ingredient), this.experience, this.cookingTime); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/item/crafting/RecipeStonecutting.patch b/patch-remap/og/net/minecraft/world/item/crafting/RecipeStonecutting.patch new file mode 100644 index 0000000000..8f96573bb3 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/crafting/RecipeStonecutting.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/item/crafting/RecipeStonecutting.java ++++ b/net/minecraft/world/item/crafting/RecipeStonecutting.java +@@ -5,6 +5,14 @@ + import net.minecraft.world.level.World; + import net.minecraft.world.level.block.Blocks; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftStonecuttingRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class RecipeStonecutting extends RecipeSingleItem { + + public RecipeStonecutting(String s, RecipeItemStack recipeitemstack, ItemStack itemstack) { +@@ -20,4 +28,16 @@ + public ItemStack getToastSymbol() { + return new ItemStack(Blocks.STONECUTTER); + } ++ ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftStonecuttingRecipe recipe = new CraftStonecuttingRecipe(id, result, CraftRecipe.toBukkit(this.ingredient)); ++ recipe.setGroup(this.group); ++ ++ return recipe; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/item/crafting/ShapedRecipes.patch b/patch-remap/og/net/minecraft/world/item/crafting/ShapedRecipes.patch new file mode 100644 index 0000000000..a9a8c24aa0 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/crafting/ShapedRecipes.patch @@ -0,0 +1,86 @@ +--- a/net/minecraft/world/item/crafting/ShapedRecipes.java ++++ b/net/minecraft/world/item/crafting/ShapedRecipes.java +@@ -10,6 +10,14 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.World; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftShapedRecipe; ++import org.bukkit.inventory.RecipeChoice; ++// CraftBukkit end ++ + public class ShapedRecipes implements RecipeCrafting { + + final ShapedRecipePattern pattern; +@@ -30,6 +38,68 @@ + this(s, craftingbookcategory, shapedrecipepattern, itemstack, true); + } + ++ // CraftBukkit start ++ @Override ++ public org.bukkit.inventory.ShapedRecipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ CraftShapedRecipe recipe = new CraftShapedRecipe(id, result, this); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ switch (this.pattern.height()) { ++ case 1: ++ switch (this.pattern.width()) { ++ case 1: ++ recipe.shape("a"); ++ break; ++ case 2: ++ recipe.shape("ab"); ++ break; ++ case 3: ++ recipe.shape("abc"); ++ break; ++ } ++ break; ++ case 2: ++ switch (this.pattern.width()) { ++ case 1: ++ recipe.shape("a","b"); ++ break; ++ case 2: ++ recipe.shape("ab","cd"); ++ break; ++ case 3: ++ recipe.shape("abc","def"); ++ break; ++ } ++ break; ++ case 3: ++ switch (this.pattern.width()) { ++ case 1: ++ recipe.shape("a","b","c"); ++ break; ++ case 2: ++ recipe.shape("ab","cd","ef"); ++ break; ++ case 3: ++ recipe.shape("abc","def","ghi"); ++ break; ++ } ++ break; ++ } ++ char c = 'a'; ++ for (RecipeItemStack list : this.pattern.ingredients()) { ++ RecipeChoice choice = CraftRecipe.toBukkit(list); ++ if (choice != null) { ++ recipe.setIngredient(c, choice); ++ } ++ ++ c++; ++ } ++ return recipe; ++ } ++ // CraftBukkit end ++ + @Override + public RecipeSerializer getSerializer() { + return RecipeSerializer.SHAPED_RECIPE; diff --git a/patch-remap/og/net/minecraft/world/item/crafting/ShapelessRecipes.patch b/patch-remap/og/net/minecraft/world/item/crafting/ShapelessRecipes.patch new file mode 100644 index 0000000000..d9fc255ffe --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/crafting/ShapelessRecipes.patch @@ -0,0 +1,39 @@ +--- a/net/minecraft/world/item/crafting/ShapelessRecipes.java ++++ b/net/minecraft/world/item/crafting/ShapelessRecipes.java +@@ -14,6 +14,13 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.World; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftShapelessRecipe; ++// CraftBukkit end ++ + public class ShapelessRecipes implements RecipeCrafting { + + final String group; +@@ -28,6 +35,22 @@ + this.ingredients = nonnulllist; + } + ++ // CraftBukkit start ++ @SuppressWarnings("unchecked") ++ @Override ++ public org.bukkit.inventory.ShapelessRecipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ CraftShapelessRecipe recipe = new CraftShapelessRecipe(id, result, this); ++ recipe.setGroup(this.group); ++ recipe.setCategory(CraftRecipe.getCategory(this.category())); ++ ++ for (RecipeItemStack list : this.ingredients) { ++ recipe.addIngredient(CraftRecipe.toBukkit(list)); ++ } ++ return recipe; ++ } ++ // CraftBukkit end ++ + @Override + public RecipeSerializer getSerializer() { + return RecipeSerializer.SHAPELESS_RECIPE; diff --git a/patch-remap/og/net/minecraft/world/item/crafting/SmithingTransformRecipe.patch b/patch-remap/og/net/minecraft/world/item/crafting/SmithingTransformRecipe.patch new file mode 100644 index 0000000000..6fa252918d --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/crafting/SmithingTransformRecipe.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/item/crafting/SmithingTransformRecipe.java ++++ b/net/minecraft/world/item/crafting/SmithingTransformRecipe.java +@@ -10,6 +10,14 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.World; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftSmithingTransformRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class SmithingTransformRecipe implements SmithingRecipe { + + final RecipeItemStack template; +@@ -71,6 +79,17 @@ + return Stream.of(this.template, this.base, this.addition).anyMatch(RecipeItemStack::isEmpty); + } + ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ CraftItemStack result = CraftItemStack.asCraftMirror(this.result); ++ ++ CraftSmithingTransformRecipe recipe = new CraftSmithingTransformRecipe(id, result, CraftRecipe.toBukkit(this.template), CraftRecipe.toBukkit(this.base), CraftRecipe.toBukkit(this.addition)); ++ ++ return recipe; ++ } ++ // CraftBukkit end ++ + public static class a implements RecipeSerializer { + + private static final Codec CODEC = RecordCodecBuilder.create((instance) -> { diff --git a/patch-remap/og/net/minecraft/world/item/crafting/SmithingTrimRecipe.patch b/patch-remap/og/net/minecraft/world/item/crafting/SmithingTrimRecipe.patch new file mode 100644 index 0000000000..f598fae7a9 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/crafting/SmithingTrimRecipe.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/item/crafting/SmithingTrimRecipe.java ++++ b/net/minecraft/world/item/crafting/SmithingTrimRecipe.java +@@ -18,6 +18,13 @@ + import net.minecraft.world.item.armortrim.TrimPatterns; + import net.minecraft.world.level.World; + ++// CraftBukkit start ++import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.inventory.CraftRecipe; ++import org.bukkit.craftbukkit.inventory.CraftSmithingTrimRecipe; ++import org.bukkit.inventory.Recipe; ++// CraftBukkit end ++ + public class SmithingTrimRecipe implements SmithingRecipe { + + final RecipeItemStack template; +@@ -107,6 +114,13 @@ + return Stream.of(this.template, this.base, this.addition).anyMatch(RecipeItemStack::isEmpty); + } + ++ // CraftBukkit start ++ @Override ++ public Recipe toBukkitRecipe(NamespacedKey id) { ++ return new CraftSmithingTrimRecipe(id, CraftRecipe.toBukkit(this.template), CraftRecipe.toBukkit(this.base), CraftRecipe.toBukkit(this.addition)); ++ } ++ // CraftBukkit end ++ + public static class a implements RecipeSerializer { + + private static final Codec CODEC = RecordCodecBuilder.create((instance) -> { diff --git a/patch-remap/og/net/minecraft/world/item/enchantment/EnchantmentFrostWalker.patch b/patch-remap/og/net/minecraft/world/item/enchantment/EnchantmentFrostWalker.patch new file mode 100644 index 0000000000..7e3647bd33 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/enchantment/EnchantmentFrostWalker.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/item/enchantment/EnchantmentFrostWalker.java ++++ b/net/minecraft/world/item/enchantment/EnchantmentFrostWalker.java +@@ -55,8 +55,11 @@ + IBlockData iblockdata2 = world.getBlockState(blockposition1); + + if (iblockdata2 == BlockIceFrost.meltsInto() && iblockdata.canSurvive(world, blockposition1) && world.isUnobstructed(iblockdata, blockposition1, VoxelShapeCollision.empty())) { +- world.setBlockAndUpdate(blockposition1, iblockdata); +- world.scheduleTick(blockposition1, Blocks.FROSTED_ICE, MathHelper.nextInt(entityliving.getRandom(), 60, 120)); ++ // CraftBukkit Start - Call EntityBlockFormEvent for Frost Walker ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(world, blockposition1, iblockdata, entityliving)) { ++ world.scheduleTick(blockposition1, Blocks.FROSTED_ICE, MathHelper.nextInt(entityliving.getRandom(), 60, 120)); ++ } ++ // CraftBukkit End + } + } + } diff --git a/patch-remap/og/net/minecraft/world/item/enchantment/EnchantmentWeaponDamage.patch b/patch-remap/og/net/minecraft/world/item/enchantment/EnchantmentWeaponDamage.patch new file mode 100644 index 0000000000..d637e8fc60 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/enchantment/EnchantmentWeaponDamage.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/item/enchantment/EnchantmentWeaponDamage.java ++++ b/net/minecraft/world/item/enchantment/EnchantmentWeaponDamage.java +@@ -63,7 +63,7 @@ + if (this.type == 2 && i > 0 && entityliving1.getMobType() == EnumMonsterType.ARTHROPOD) { + int j = 20 + entityliving.getRandom().nextInt(10 * i); + +- entityliving1.addEffect(new MobEffect(MobEffects.MOVEMENT_SLOWDOWN, j, 3)); ++ entityliving1.addEffect(new MobEffect(MobEffects.MOVEMENT_SLOWDOWN, j, 3), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + diff --git a/patch-remap/og/net/minecraft/world/item/trading/IMerchant.patch b/patch-remap/og/net/minecraft/world/item/trading/IMerchant.patch new file mode 100644 index 0000000000..0ea0e940d0 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/trading/IMerchant.patch @@ -0,0 +1,9 @@ +--- a/net/minecraft/world/item/trading/IMerchant.java ++++ b/net/minecraft/world/item/trading/IMerchant.java +@@ -52,4 +52,6 @@ + } + + boolean isClientSide(); ++ ++ org.bukkit.craftbukkit.inventory.CraftMerchant getCraftMerchant(); // CraftBukkit + } diff --git a/patch-remap/og/net/minecraft/world/item/trading/MerchantRecipe.patch b/patch-remap/og/net/minecraft/world/item/trading/MerchantRecipe.patch new file mode 100644 index 0000000000..b5c7195163 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/item/trading/MerchantRecipe.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/item/trading/MerchantRecipe.java ++++ b/net/minecraft/world/item/trading/MerchantRecipe.java +@@ -5,6 +5,8 @@ + import net.minecraft.util.MathHelper; + import net.minecraft.world.item.ItemStack; + ++import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; // CraftBukkit ++ + public class MerchantRecipe { + + public ItemStack baseCostA; +@@ -17,6 +19,22 @@ + public int demand; + public float priceMultiplier; + public int xp; ++ // CraftBukkit start ++ private CraftMerchantRecipe bukkitHandle; ++ ++ public CraftMerchantRecipe asBukkit() { ++ return (bukkitHandle == null) ? bukkitHandle = new CraftMerchantRecipe(this) : bukkitHandle; ++ } ++ ++ public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, CraftMerchantRecipe bukkit) { ++ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, 0, bukkit); ++ } ++ ++ public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, int demand, CraftMerchantRecipe bukkit) { ++ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, demand); ++ this.bukkitHandle = bukkit; ++ } ++ // CraftBukkit end + + public MerchantRecipe(NBTTagCompound nbttagcompound) { + this.rewardExp = true; +@@ -96,6 +114,7 @@ + return ItemStack.EMPTY; + } else { + int i = this.baseCostA.getCount(); ++ if (i <= 0) return ItemStack.EMPTY; // CraftBukkit - SPIGOT-5476 + int j = Math.max(0, MathHelper.floor((float) (i * this.demand) * this.priceMultiplier)); + + return this.baseCostA.copyWithCount(MathHelper.clamp(i + j + this.specialPriceDiff, 1, this.baseCostA.getItem().getMaxStackSize())); +@@ -216,7 +235,11 @@ + if (!this.satisfiedBy(itemstack, itemstack1)) { + return false; + } else { +- itemstack.shrink(this.getCostA().getCount()); ++ // CraftBukkit start ++ if (!this.getCostA().isEmpty()) { ++ itemstack.shrink(this.getCostA().getCount()); ++ } ++ // CraftBukkit end + if (!this.getCostB().isEmpty()) { + itemstack1.shrink(this.getCostB().getCount()); + } diff --git a/patch-remap/og/net/minecraft/world/level/CommandBlockListenerAbstract.patch b/patch-remap/og/net/minecraft/world/level/CommandBlockListenerAbstract.patch new file mode 100644 index 0000000000..3a6e452457 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/CommandBlockListenerAbstract.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/level/CommandBlockListenerAbstract.java ++++ b/net/minecraft/world/level/CommandBlockListenerAbstract.java +@@ -30,6 +30,10 @@ + private IChatBaseComponent lastOutput; + private String command = ""; + private IChatBaseComponent name; ++ // CraftBukkit start ++ @Override ++ public abstract org.bukkit.command.CommandSender getBukkitSender(CommandListenerWrapper wrapper); ++ // CraftBukkit end + + public CommandBlockListenerAbstract() { + this.name = CommandBlockListenerAbstract.DEFAULT_NAME; +@@ -126,7 +130,7 @@ + + }); + +- minecraftserver.getCommands().performPrefixedCommand(commandlistenerwrapper, this.command); ++ minecraftserver.getCommands().dispatchServerCommand(commandlistenerwrapper, this.command); // CraftBukkit + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Executing command block"); + CrashReportSystemDetails crashreportsystemdetails = crashreport.addCategory("Command to be executed"); diff --git a/patch-remap/og/net/minecraft/world/level/Explosion.patch b/patch-remap/og/net/minecraft/world/level/Explosion.patch new file mode 100644 index 0000000000..68abd58e3d --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/Explosion.patch @@ -0,0 +1,183 @@ +--- a/net/minecraft/world/level/Explosion.java ++++ b/net/minecraft/world/level/Explosion.java +@@ -39,6 +39,16 @@ + import net.minecraft.world.phys.MovingObjectPosition; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import net.minecraft.world.entity.boss.EntityComplexPart; ++import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon; ++import net.minecraft.world.level.block.Blocks; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityExplodeEvent; ++import org.bukkit.Location; ++import org.bukkit.event.block.BlockExplodeEvent; ++// CraftBukkit end ++ + public class Explosion { + + private static final ExplosionDamageCalculator EXPLOSION_DAMAGE_CALCULATOR = new ExplosionDamageCalculator(); +@@ -60,6 +70,10 @@ + private final SoundEffect explosionSound; + private final ObjectArrayList toBlow; + private final Map hitPlayers; ++ // CraftBukkit - add field ++ public boolean wasCanceled = false; ++ public float yield; ++ // CraftBukkit end + + public static DamageSource getDefaultDamageSource(World world, @Nullable Entity entity) { + return world.damageSources().explosion(entity, getIndirectSourceEntityInternal(entity)); +@@ -85,7 +99,7 @@ + this.hitPlayers = Maps.newHashMap(); + this.level = world; + this.source = entity; +- this.radius = f; ++ this.radius = (float) Math.max(f, 0.0); // CraftBukkit - clamp bad values + this.x = d0; + this.y = d1; + this.z = d2; +@@ -96,6 +110,7 @@ + this.smallExplosionParticles = particleparam; + this.largeExplosionParticles = particleparam1; + this.explosionSound = soundeffect; ++ this.yield = this.blockInteraction == Explosion.Effect.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F; // CraftBukkit + } + + private ExplosionDamageCalculator makeDamageCalculator(@Nullable Entity entity) { +@@ -146,6 +161,11 @@ + } + + public void explode() { ++ // CraftBukkit start ++ if (this.radius < 0.1F) { ++ return; ++ } ++ // CraftBukkit end + this.level.gameEvent(this.source, GameEvent.EXPLODE, new Vec3D(this.x, this.y, this.z)); + Set set = Sets.newHashSet(); + boolean flag = true; +@@ -228,7 +248,37 @@ + d9 /= d11; + d10 /= d11; + if (this.damageCalculator.shouldDamageEntity(this, entity)) { +- entity.hurt(this.damageSource, this.damageCalculator.getEntityDamageAmount(this, entity)); ++ // CraftBukkit start ++ ++ // Special case ender dragon only give knockback if no damage is cancelled ++ // Thinks to note: ++ // - Setting a velocity to a ComplexEntityPart is ignored (and therefore not needed) ++ // - Damaging ComplexEntityPart while forward the damage to EntityEnderDragon ++ // - Damaging EntityEnderDragon does nothing ++ // - EntityEnderDragon hitbock always covers the other parts and is therefore always present ++ if (entity instanceof EntityComplexPart) { ++ continue; ++ } ++ ++ CraftEventFactory.entityDamage = source; ++ entity.lastDamageCancelled = false; ++ ++ if (entity instanceof EntityEnderDragon) { ++ for (EntityComplexPart entityComplexPart : ((EntityEnderDragon) entity).subEntities) { ++ // Calculate damage separately for each EntityComplexPart ++ if (list.contains(entityComplexPart)) { ++ entityComplexPart.hurt(this.damageSource, this.damageCalculator.getEntityDamageAmount(this, entity)); ++ } ++ } ++ } else { ++ entity.hurt(this.damageSource, this.damageCalculator.getEntityDamageAmount(this, entity)); ++ } ++ ++ CraftEventFactory.entityDamage = null; ++ if (entity.lastDamageCancelled) { // SPIGOT-5339, SPIGOT-6252, SPIGOT-6777: Skip entity if damage event was cancelled ++ continue; ++ } ++ // CraftBukkit end + } + + double d12 = (1.0D - d7) * (double) getSeenPercent(vec3d, entity); +@@ -287,9 +337,63 @@ + + SystemUtils.shuffle(this.toBlow, this.level.random); + ObjectListIterator objectlistiterator = this.toBlow.iterator(); ++ // CraftBukkit start ++ org.bukkit.World bworld = this.level.getWorld(); ++ org.bukkit.entity.Entity explode = this.source == null ? null : this.source.getBukkitEntity(); ++ Location location = new Location(bworld, this.x, this.y, this.z); ++ ++ List blockList = new ObjectArrayList<>(); ++ for (int i1 = this.toBlow.size() - 1; i1 >= 0; i1--) { ++ BlockPosition cpos = this.toBlow.get(i1); ++ org.bukkit.block.Block bblock = bworld.getBlockAt(cpos.getX(), cpos.getY(), cpos.getZ()); ++ if (!bblock.getType().isAir()) { ++ blockList.add(bblock); ++ } ++ } ++ ++ List bukkitBlocks; ++ ++ if (explode != null) { ++ EntityExplodeEvent event = new EntityExplodeEvent(explode, location, blockList, this.yield); ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ this.wasCanceled = event.isCancelled(); ++ bukkitBlocks = event.blockList(); ++ this.yield = event.getYield(); ++ } else { ++ BlockExplodeEvent event = new BlockExplodeEvent(location.getBlock(), blockList, this.yield); ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ this.wasCanceled = event.isCancelled(); ++ bukkitBlocks = event.blockList(); ++ this.yield = event.getYield(); ++ } ++ ++ this.toBlow.clear(); ++ ++ for (org.bukkit.block.Block bblock : bukkitBlocks) { ++ BlockPosition coords = new BlockPosition(bblock.getX(), bblock.getY(), bblock.getZ()); ++ toBlow.add(coords); ++ } ++ ++ if (this.wasCanceled) { ++ return; ++ } ++ // CraftBukkit end ++ objectlistiterator = this.toBlow.iterator(); + + while (objectlistiterator.hasNext()) { + BlockPosition blockposition = (BlockPosition) objectlistiterator.next(); ++ // CraftBukkit start - TNTPrimeEvent ++ IBlockData iblockdata = this.level.getBlockState(blockposition); ++ Block block = iblockdata.getBlock(); ++ if (block instanceof net.minecraft.world.level.block.BlockTNT) { ++ Entity sourceEntity = source == null ? null : source; ++ BlockPosition sourceBlock = sourceEntity == null ? BlockPosition.containing(this.x, this.y, this.z) : null; ++ if (!CraftEventFactory.callTNTPrimeEvent(this.level, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.EXPLOSION, sourceEntity, sourceBlock)) { ++ this.level.sendBlockUpdated(blockposition, Blocks.AIR.defaultBlockState(), iblockdata, 3); // Update the block on the client ++ continue; ++ } ++ } ++ // CraftBukkit end + + this.level.getBlockState(blockposition).onExplosionHit(this.level, blockposition, this, (itemstack, blockposition1) -> { + addOrAppendStack(list, itemstack, blockposition1); +@@ -314,7 +418,11 @@ + BlockPosition blockposition1 = (BlockPosition) objectlistiterator1.next(); + + if (this.random.nextInt(3) == 0 && this.level.getBlockState(blockposition1).isAir() && this.level.getBlockState(blockposition1.below()).isSolidRender(this.level, blockposition1.below())) { +- this.level.setBlockAndUpdate(blockposition1, BlockFireAbstract.getState(this.level, blockposition1)); ++ // CraftBukkit start - Ignition by explosion ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(this.level, blockposition1, this).isCancelled()) { ++ this.level.setBlockAndUpdate(blockposition1, BlockFireAbstract.getState(this.level, blockposition1)); ++ } ++ // CraftBukkit end + } + } + } +@@ -322,6 +430,7 @@ + } + + private static void addOrAppendStack(List> list, ItemStack itemstack, BlockPosition blockposition) { ++ if (itemstack.isEmpty()) return; // CraftBukkit - SPIGOT-5425 + for (int i = 0; i < list.size(); ++i) { + Pair pair = (Pair) list.get(i); + ItemStack itemstack1 = (ItemStack) pair.getFirst(); diff --git a/patch-remap/og/net/minecraft/world/level/GameRules.patch b/patch-remap/og/net/minecraft/world/level/GameRules.patch new file mode 100644 index 0000000000..a124b75912 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/GameRules.patch @@ -0,0 +1,67 @@ +--- a/net/minecraft/world/level/GameRules.java ++++ b/net/minecraft/world/level/GameRules.java +@@ -142,7 +142,7 @@ + } + + public > T getRule(GameRules.GameRuleKey gamerules_gamerulekey) { +- return (GameRules.GameRuleValue) this.rules.get(gamerules_gamerulekey); ++ return (T) this.rules.get(gamerules_gamerulekey); // CraftBukkit - decompile error + } + + public NBTTagCompound createTag() { +@@ -156,7 +156,7 @@ + + private void loadFromTag(DynamicLike dynamiclike) { + this.rules.forEach((gamerules_gamerulekey, gamerules_gamerulevalue) -> { +- Optional optional = dynamiclike.get(gamerules_gamerulekey.id).asString().result(); ++ Optional optional = dynamiclike.get(gamerules_gamerulekey.id).asString().result(); // CraftBukkit - decompile error + + Objects.requireNonNull(gamerules_gamerulevalue); + optional.ifPresent(gamerules_gamerulevalue::deserialize); +@@ -176,8 +176,8 @@ + } + + private static > void callVisitorCap(GameRules.GameRuleVisitor gamerules_gamerulevisitor, GameRules.GameRuleKey gamerules_gamerulekey, GameRules.GameRuleDefinition gamerules_gameruledefinition) { +- gamerules_gamerulevisitor.visit(gamerules_gamerulekey, gamerules_gameruledefinition); +- gamerules_gameruledefinition.callVisitor(gamerules_gamerulevisitor, gamerules_gamerulekey); ++ gamerules_gamerulevisitor.visit((GameRules.GameRuleKey) gamerules_gamerulekey, (GameRules.GameRuleDefinition) gamerules_gameruledefinition); // CraftBukkit - decompile error ++ ((GameRules.GameRuleDefinition) gamerules_gameruledefinition).callVisitor(gamerules_gamerulevisitor, (GameRules.GameRuleKey) gamerules_gamerulekey); // CraftBukkit - decompile error + } + + public void assignFrom(GameRules gamerules, @Nullable MinecraftServer minecraftserver) { +@@ -269,7 +269,7 @@ + } + + public T createRule() { +- return (GameRules.GameRuleValue) this.constructor.apply(this); ++ return this.constructor.apply(this); // CraftBukkit - decompile error + } + + public void callVisitor(GameRules.GameRuleVisitor gamerules_gamerulevisitor, GameRules.GameRuleKey gamerules_gamerulekey) { +@@ -299,7 +299,7 @@ + + } + +- protected abstract void deserialize(String s); ++ public abstract void deserialize(String s); // PAIL - private->public + + public abstract String serialize(); + +@@ -365,7 +365,7 @@ + } + + @Override +- protected void deserialize(String s) { ++ public void deserialize(String s) { // PAIL - protected->public + this.value = Boolean.parseBoolean(s); + } + +@@ -430,7 +430,7 @@ + } + + @Override +- protected void deserialize(String s) { ++ public void deserialize(String s) { // PAIL - protected->public + this.value = safeParse(s); + } + diff --git a/patch-remap/og/net/minecraft/world/level/GeneratorAccess.patch b/patch-remap/og/net/minecraft/world/level/GeneratorAccess.patch new file mode 100644 index 0000000000..70019a1569 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/GeneratorAccess.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/world/level/GeneratorAccess.java ++++ b/net/minecraft/world/level/GeneratorAccess.java +@@ -35,11 +35,11 @@ + + LevelTickAccess getBlockTicks(); + +- private default NextTickListEntry createTick(BlockPosition blockposition, T t0, int i, TickListPriority ticklistpriority) { ++ default NextTickListEntry createTick(BlockPosition blockposition, T t0, int i, TickListPriority ticklistpriority) { // CraftBukkit - decompile error + return new NextTickListEntry<>(t0, blockposition, this.getLevelData().getGameTime() + (long) i, ticklistpriority, this.nextSubTickCount()); + } + +- private default NextTickListEntry createTick(BlockPosition blockposition, T t0, int i) { ++ default NextTickListEntry createTick(BlockPosition blockposition, T t0, int i) { // CraftBukkit - decompile error + return new NextTickListEntry<>(t0, blockposition, this.getLevelData().getGameTime() + (long) i, this.nextSubTickCount()); + } + +@@ -114,4 +114,6 @@ + default void gameEvent(GameEvent gameevent, BlockPosition blockposition, GameEvent.a gameevent_a) { + this.gameEvent(gameevent, Vec3D.atCenterOf(blockposition), gameevent_a); + } ++ ++ net.minecraft.server.level.WorldServer getMinecraftWorld(); // CraftBukkit + } diff --git a/patch-remap/og/net/minecraft/world/level/IBlockAccess.patch b/patch-remap/og/net/minecraft/world/level/IBlockAccess.patch new file mode 100644 index 0000000000..15e1b1d7c4 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/IBlockAccess.patch @@ -0,0 +1,44 @@ +--- a/net/minecraft/world/level/IBlockAccess.java ++++ b/net/minecraft/world/level/IBlockAccess.java +@@ -26,7 +26,7 @@ + default Optional getBlockEntity(BlockPosition blockposition, TileEntityTypes tileentitytypes) { + TileEntity tileentity = this.getBlockEntity(blockposition); + +- return tileentity != null && tileentity.getType() == tileentitytypes ? Optional.of(tileentity) : Optional.empty(); ++ return tileentity != null && tileentity.getType() == tileentitytypes ? (Optional) Optional.of(tileentity) : Optional.empty(); // CraftBukkit - decompile error + } + + IBlockData getBlockState(BlockPosition blockposition); +@@ -58,8 +58,8 @@ + }); + } + +- default MovingObjectPositionBlock clip(RayTrace raytrace) { +- return (MovingObjectPositionBlock) traverseBlocks(raytrace.getFrom(), raytrace.getTo(), raytrace, (raytrace1, blockposition) -> { ++ // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace ++ default MovingObjectPositionBlock clip(RayTrace raytrace1, BlockPosition blockposition) { + IBlockData iblockdata = this.getBlockState(blockposition); + Fluid fluid = this.getFluidState(blockposition); + Vec3D vec3d = raytrace1.getFrom(); +@@ -72,6 +72,12 @@ + double d1 = movingobjectpositionblock1 == null ? Double.MAX_VALUE : raytrace1.getFrom().distanceToSqr(movingobjectpositionblock1.getLocation()); + + return d0 <= d1 ? movingobjectpositionblock : movingobjectpositionblock1; ++ } ++ // CraftBukkit end ++ ++ default MovingObjectPositionBlock clip(RayTrace raytrace) { ++ return (MovingObjectPositionBlock) traverseBlocks(raytrace.getFrom(), raytrace.getTo(), raytrace, (raytrace1, blockposition) -> { ++ return this.clip(raytrace1, blockposition); // CraftBukkit - moved into separate method + }, (raytrace1) -> { + Vec3D vec3d = raytrace1.getFrom().subtract(raytrace1.getTo()); + +@@ -144,7 +150,7 @@ + double d13 = d10 * (i1 > 0 ? 1.0D - MathHelper.frac(d4) : MathHelper.frac(d4)); + double d14 = d11 * (j1 > 0 ? 1.0D - MathHelper.frac(d5) : MathHelper.frac(d5)); + +- Object object; ++ T object; // CraftBukkit - decompile error + + do { + if (d12 > 1.0D && d13 > 1.0D && d14 > 1.0D) { diff --git a/patch-remap/og/net/minecraft/world/level/IWorldWriter.patch b/patch-remap/og/net/minecraft/world/level/IWorldWriter.patch new file mode 100644 index 0000000000..29fe1cde21 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/IWorldWriter.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/world/level/IWorldWriter.java ++++ b/net/minecraft/world/level/IWorldWriter.java +@@ -28,4 +28,10 @@ + default boolean addFreshEntity(Entity entity) { + return false; + } ++ ++ // CraftBukkit start ++ default boolean addFreshEntity(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ return false; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/level/MobSpawnerAbstract.patch b/patch-remap/og/net/minecraft/world/level/MobSpawnerAbstract.patch new file mode 100644 index 0000000000..fb7462dcad --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/MobSpawnerAbstract.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/world/level/MobSpawnerAbstract.java ++++ b/net/minecraft/world/level/MobSpawnerAbstract.java +@@ -52,6 +52,7 @@ + + public void setEntityId(EntityTypes entitytypes, @Nullable World world, RandomSource randomsource, BlockPosition blockposition) { + this.getOrCreateNextSpawnData(world, randomsource, blockposition).getEntityToSpawn().putString("id", BuiltInRegistries.ENTITY_TYPE.getKey(entitytypes).toString()); ++ this.spawnPotentials = SimpleWeightedRandomList.empty(); // CraftBukkit - SPIGOT-3496, MC-92282 + } + + private boolean isNearPlayer(World world, BlockPosition blockposition) { +@@ -154,7 +155,12 @@ + } + } + +- if (!worldserver.tryAddFreshEntityWithPassengers(entity)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { ++ continue; ++ } ++ if (!worldserver.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER)) { ++ // CraftBukkit end + this.delay(worldserver, blockposition); + return; + } diff --git a/patch-remap/og/net/minecraft/world/level/RayTrace.patch b/patch-remap/og/net/minecraft/world/level/RayTrace.patch new file mode 100644 index 0000000000..c6598f3aa2 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/RayTrace.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/level/RayTrace.java ++++ b/net/minecraft/world/level/RayTrace.java +@@ -22,7 +22,7 @@ + private final VoxelShapeCollision collisionContext; + + public RayTrace(Vec3D vec3d, Vec3D vec3d1, RayTrace.BlockCollisionOption raytrace_blockcollisionoption, RayTrace.FluidCollisionOption raytrace_fluidcollisionoption, Entity entity) { +- this(vec3d, vec3d1, raytrace_blockcollisionoption, raytrace_fluidcollisionoption, VoxelShapeCollision.of(entity)); ++ this(vec3d, vec3d1, raytrace_blockcollisionoption, raytrace_fluidcollisionoption, (entity == null) ? VoxelShapeCollision.empty() : VoxelShapeCollision.of(entity)); // CraftBukkit + } + + public RayTrace(Vec3D vec3d, Vec3D vec3d1, RayTrace.BlockCollisionOption raytrace_blockcollisionoption, RayTrace.FluidCollisionOption raytrace_fluidcollisionoption, VoxelShapeCollision voxelshapecollision) { +@@ -79,7 +79,7 @@ + + private final Predicate canPick; + +- private FluidCollisionOption(Predicate predicate) { ++ private FluidCollisionOption(Predicate predicate) { // CraftBukkit - decompile error + this.canPick = predicate; + } + diff --git a/patch-remap/og/net/minecraft/world/level/SpawnerCreature.patch b/patch-remap/og/net/minecraft/world/level/SpawnerCreature.patch new file mode 100644 index 0000000000..24b8cc9dac --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/SpawnerCreature.patch @@ -0,0 +1,85 @@ +--- a/net/minecraft/world/level/SpawnerCreature.java ++++ b/net/minecraft/world/level/SpawnerCreature.java +@@ -49,6 +49,13 @@ + import net.minecraft.world.phys.Vec3D; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.world.level.storage.WorldData; ++import org.bukkit.craftbukkit.util.CraftSpawnCategory; ++import org.bukkit.entity.SpawnCategory; ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; ++// CraftBukkit end ++ + public final class SpawnerCreature { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -113,10 +120,25 @@ + EnumCreatureType[] aenumcreaturetype = SpawnerCreature.SPAWNING_CATEGORIES; + int i = aenumcreaturetype.length; + ++ WorldData worlddata = worldserver.getLevelData(); // CraftBukkit - Other mob type spawn tick rate ++ + for (int j = 0; j < i; ++j) { + EnumCreatureType enumcreaturetype = aenumcreaturetype[j]; ++ // CraftBukkit start - Use per-world spawn limits ++ boolean spawnThisTick = true; ++ int limit = enumcreaturetype.getMaxInstancesPerChunk(); ++ SpawnCategory spawnCategory = CraftSpawnCategory.toBukkit(enumcreaturetype); ++ if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { ++ spawnThisTick = worldserver.ticksPerSpawnCategory.getLong(spawnCategory) != 0 && worlddata.getGameTime() % worldserver.ticksPerSpawnCategory.getLong(spawnCategory) == 0; ++ limit = worldserver.getWorld().getSpawnLimit(spawnCategory); ++ } + +- if ((flag || !enumcreaturetype.isFriendly()) && (flag1 || enumcreaturetype.isFriendly()) && (flag2 || !enumcreaturetype.isPersistent()) && spawnercreature_d.canSpawnForCategory(enumcreaturetype, chunk.getPos())) { ++ if (!spawnThisTick || limit == 0) { ++ continue; ++ } ++ ++ if ((flag || !enumcreaturetype.isFriendly()) && (flag1 || enumcreaturetype.isFriendly()) && (flag2 || !enumcreaturetype.isPersistent()) && spawnercreature_d.canSpawnForCategory(enumcreaturetype, chunk.getPos(), limit)) { ++ // CraftBukkit end + Objects.requireNonNull(spawnercreature_d); + SpawnerCreature.c spawnercreature_c = spawnercreature_d::canSpawn; + +@@ -201,10 +223,15 @@ + entityinsentient.moveTo(d0, (double) i, d1, worldserver.random.nextFloat() * 360.0F, 0.0F); + if (isValidPositionForMob(worldserver, entityinsentient, d2)) { + groupdataentity = entityinsentient.finalizeSpawn(worldserver, worldserver.getCurrentDifficultyAt(entityinsentient.blockPosition()), EnumMobSpawn.NATURAL, groupdataentity, (NBTTagCompound) null); +- ++j; +- ++k1; +- worldserver.addFreshEntityWithPassengers(entityinsentient); +- spawnercreature_a.run(entityinsentient, ichunkaccess); ++ // CraftBukkit start ++ // SPIGOT-7045: Give ocelot babies back their special spawn reason. Note: This is the only modification required as ocelots count as monsters which means they only spawn during normal chunk ticking and do not spawn during chunk generation as starter mobs. ++ worldserver.addFreshEntityWithPassengers(entityinsentient, (entityinsentient instanceof net.minecraft.world.entity.animal.EntityOcelot && !((org.bukkit.entity.Ageable) entityinsentient.getBukkitEntity()).isAdult()) ? SpawnReason.OCELOT_BABY : SpawnReason.NATURAL); ++ if (!entityinsentient.isRemoved()) { ++ ++j; ++ ++k1; ++ spawnercreature_a.run(entityinsentient, ichunkaccess); ++ } ++ // CraftBukkit end + if (j >= entityinsentient.getMaxSpawnClusterSize()) { + return; + } +@@ -390,7 +417,7 @@ + + if (entityinsentient.checkSpawnRules(worldaccess, EnumMobSpawn.CHUNK_GENERATION) && entityinsentient.checkSpawnObstruction(worldaccess)) { + groupdataentity = entityinsentient.finalizeSpawn(worldaccess, worldaccess.getCurrentDifficultyAt(entityinsentient.blockPosition()), EnumMobSpawn.CHUNK_GENERATION, groupdataentity, (NBTTagCompound) null); +- worldaccess.addFreshEntityWithPassengers(entityinsentient); ++ worldaccess.addFreshEntityWithPassengers(entityinsentient, SpawnReason.CHUNK_GEN); // CraftBukkit + flag = true; + } + } +@@ -511,8 +538,10 @@ + return this.unmodifiableMobCategoryCounts; + } + +- boolean canSpawnForCategory(EnumCreatureType enumcreaturetype, ChunkCoordIntPair chunkcoordintpair) { +- int i = enumcreaturetype.getMaxInstancesPerChunk() * this.spawnableChunkCount / SpawnerCreature.MAGIC_NUMBER; ++ // CraftBukkit start ++ boolean canSpawnForCategory(EnumCreatureType enumcreaturetype, ChunkCoordIntPair chunkcoordintpair, int limit) { ++ int i = limit * this.spawnableChunkCount / SpawnerCreature.MAGIC_NUMBER; ++ // CraftBukkit end + + return this.mobCategoryCounts.getInt(enumcreaturetype) >= i ? false : this.localMobCapCalculator.canSpawn(enumcreaturetype, chunkcoordintpair); + } diff --git a/patch-remap/og/net/minecraft/world/level/World.patch b/patch-remap/og/net/minecraft/world/level/World.patch new file mode 100644 index 0000000000..4fb42ae72c --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/World.patch @@ -0,0 +1,310 @@ +--- a/net/minecraft/world/level/World.java ++++ b/net/minecraft/world/level/World.java +@@ -75,6 +75,31 @@ + import net.minecraft.world.phys.Vec3D; + import net.minecraft.world.scores.Scoreboard; + ++// CraftBukkit start ++import java.util.HashMap; ++import java.util.Map; ++import net.minecraft.network.protocol.game.ClientboundSetBorderCenterPacket; ++import net.minecraft.network.protocol.game.ClientboundSetBorderLerpSizePacket; ++import net.minecraft.network.protocol.game.ClientboundSetBorderSizePacket; ++import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDelayPacket; ++import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDistancePacket; ++import net.minecraft.server.level.WorldServer; ++import net.minecraft.world.entity.item.EntityItem; ++import net.minecraft.world.level.border.IWorldBorderListener; ++import net.minecraft.world.level.dimension.WorldDimension; ++import org.bukkit.Bukkit; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.block.CapturedBlockState; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.craftbukkit.util.CraftSpawnCategory; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; ++import org.bukkit.entity.SpawnCategory; ++import org.bukkit.event.block.BlockPhysicsEvent; ++import org.bukkit.event.world.GenericGameEvent; ++// CraftBukkit end ++ + public abstract class World implements GeneratorAccess, AutoCloseable { + + public static final Codec> RESOURCE_KEY_CODEC = ResourceKey.codec(Registries.DIMENSION); +@@ -117,7 +142,43 @@ + private final DamageSources damageSources; + private long subTickCount; + +- protected World(WorldDataMutable worlddatamutable, ResourceKey resourcekey, IRegistryCustom iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j) { ++ // CraftBukkit start Added the following ++ private final CraftWorld world; ++ public boolean pvpMode; ++ public boolean keepSpawnInMemory = true; ++ public org.bukkit.generator.ChunkGenerator generator; ++ ++ public boolean preventPoiUpdated = false; // CraftBukkit - SPIGOT-5710 ++ public boolean captureBlockStates = false; ++ public boolean captureTreeGeneration = false; ++ public Map capturedBlockStates = new java.util.LinkedHashMap<>(); ++ public Map capturedTileEntities = new HashMap<>(); ++ public List captureDrops; ++ public final it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap ticksPerSpawnCategory = new it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<>(); ++ public boolean populating; ++ ++ public CraftWorld getWorld() { ++ return this.world; ++ } ++ ++ public CraftServer getCraftServer() { ++ return (CraftServer) Bukkit.getServer(); ++ } ++ ++ public abstract ResourceKey getTypeKey(); ++ ++ protected World(WorldDataMutable worlddatamutable, ResourceKey resourcekey, IRegistryCustom iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env) { ++ this.generator = gen; ++ this.world = new CraftWorld((WorldServer) this, gen, biomeProvider, env); ++ ++ // CraftBukkit Ticks things ++ for (SpawnCategory spawnCategory : SpawnCategory.values()) { ++ if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { ++ this.ticksPerSpawnCategory.put(spawnCategory, (long) this.getCraftServer().getTicksPerSpawns(spawnCategory)); ++ } ++ } ++ ++ // CraftBukkit end + this.profiler = supplier; + this.levelData = worlddatamutable; + this.dimensionTypeRegistration = holder; +@@ -132,12 +193,12 @@ + this.worldBorder = new WorldBorder() { + @Override + public double getCenterX() { +- return super.getCenterX() / dimensionmanager.coordinateScale(); ++ return super.getCenterX(); // CraftBukkit + } + + @Override + public double getCenterZ() { +- return super.getCenterZ() / dimensionmanager.coordinateScale(); ++ return super.getCenterZ(); // CraftBukkit + } + }; + } else { +@@ -150,6 +211,42 @@ + this.neighborUpdater = new CollectingNeighborUpdater(this, j); + this.registryAccess = iregistrycustom; + this.damageSources = new DamageSources(iregistrycustom); ++ // CraftBukkit start ++ getWorldBorder().world = (WorldServer) this; ++ // From PlayerList.setPlayerFileData ++ getWorldBorder().addListener(new IWorldBorderListener() { ++ @Override ++ public void onBorderSizeSet(WorldBorder worldborder, double d0) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderSizePacket(worldborder), worldborder.world); ++ } ++ ++ @Override ++ public void onBorderSizeLerping(WorldBorder worldborder, double d0, double d1, long i) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderLerpSizePacket(worldborder), worldborder.world); ++ } ++ ++ @Override ++ public void onBorderCenterSet(WorldBorder worldborder, double d0, double d1) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderCenterPacket(worldborder), worldborder.world); ++ } ++ ++ @Override ++ public void onBorderSetWarningTime(WorldBorder worldborder, int i) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderWarningDelayPacket(worldborder), worldborder.world); ++ } ++ ++ @Override ++ public void onBorderSetWarningBlocks(WorldBorder worldborder, int i) { ++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderWarningDistancePacket(worldborder), worldborder.world); ++ } ++ ++ @Override ++ public void onBorderSetDamagePerBlock(WorldBorder worldborder, double d0) {} ++ ++ @Override ++ public void onBorderSetDamageSafeZOne(WorldBorder worldborder, double d0) {} ++ }); ++ // CraftBukkit end + } + + @Override +@@ -207,6 +304,17 @@ + + @Override + public boolean setBlock(BlockPosition blockposition, IBlockData iblockdata, int i, int j) { ++ // CraftBukkit start - tree generation ++ if (this.captureTreeGeneration) { ++ CapturedBlockState blockstate = capturedBlockStates.get(blockposition); ++ if (blockstate == null) { ++ blockstate = CapturedBlockState.getTreeBlockState(this, blockposition, i); ++ this.capturedBlockStates.put(blockposition.immutable(), blockstate); ++ } ++ blockstate.setData(iblockdata); ++ return true; ++ } ++ // CraftBukkit end + if (this.isOutsideBuildHeight(blockposition)) { + return false; + } else if (!this.isClientSide && this.isDebug()) { +@@ -214,13 +322,29 @@ + } else { + Chunk chunk = this.getChunkAt(blockposition); + Block block = iblockdata.getBlock(); +- IBlockData iblockdata1 = chunk.setBlockState(blockposition, iblockdata, (i & 64) != 0); ++ ++ // CraftBukkit start - capture blockstates ++ boolean captured = false; ++ if (this.captureBlockStates && !this.capturedBlockStates.containsKey(blockposition)) { ++ CapturedBlockState blockstate = CapturedBlockState.getBlockState(this, blockposition, i); ++ this.capturedBlockStates.put(blockposition.immutable(), blockstate); ++ captured = true; ++ } ++ // CraftBukkit end ++ ++ IBlockData iblockdata1 = chunk.setBlockState(blockposition, iblockdata, (i & 64) != 0, (i & 1024) == 0); // CraftBukkit custom NO_PLACE flag + + if (iblockdata1 == null) { ++ // CraftBukkit start - remove blockstate if failed (or the same) ++ if (this.captureBlockStates && captured) { ++ this.capturedBlockStates.remove(blockposition); ++ } ++ // CraftBukkit end + return false; + } else { + IBlockData iblockdata2 = this.getBlockState(blockposition); + ++ /* + if (iblockdata2 == iblockdata) { + if (iblockdata1 != iblockdata2) { + this.setBlocksDirty(blockposition, iblockdata1, iblockdata2); +@@ -247,12 +371,69 @@ + + this.onBlockStateChange(blockposition, iblockdata1, iblockdata2); + } ++ */ ++ ++ // CraftBukkit start ++ if (!this.captureBlockStates) { // Don't notify clients or update physics while capturing blockstates ++ // Modularize client and physic updates ++ notifyAndUpdatePhysics(blockposition, chunk, iblockdata1, iblockdata, iblockdata2, i, j); ++ } ++ // CraftBukkit end + + return true; + } + } + } + ++ // CraftBukkit start - Split off from above in order to directly send client and physic updates ++ public void notifyAndUpdatePhysics(BlockPosition blockposition, Chunk chunk, IBlockData oldBlock, IBlockData newBlock, IBlockData actualBlock, int i, int j) { ++ IBlockData iblockdata = newBlock; ++ IBlockData iblockdata1 = oldBlock; ++ IBlockData iblockdata2 = actualBlock; ++ if (iblockdata2 == iblockdata) { ++ if (iblockdata1 != iblockdata2) { ++ this.setBlocksDirty(blockposition, iblockdata1, iblockdata2); ++ } ++ ++ if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getFullStatus() != null && chunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement ++ this.sendBlockUpdated(blockposition, iblockdata1, iblockdata, i); ++ } ++ ++ if ((i & 1) != 0) { ++ this.blockUpdated(blockposition, iblockdata1.getBlock()); ++ if (!this.isClientSide && iblockdata.hasAnalogOutputSignal()) { ++ this.updateNeighbourForOutputSignal(blockposition, newBlock.getBlock()); ++ } ++ } ++ ++ if ((i & 16) == 0 && j > 0) { ++ int k = i & -34; ++ ++ // CraftBukkit start ++ iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam ++ CraftWorld world = ((WorldServer) this).getWorld(); ++ if (world != null) { ++ BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata)); ++ this.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ iblockdata.updateNeighbourShapes(this, blockposition, k, j - 1); ++ iblockdata.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); ++ } ++ ++ // CraftBukkit start - SPIGOT-5710 ++ if (!preventPoiUpdated) { ++ this.onBlockStateChange(blockposition, iblockdata1, iblockdata2); ++ } ++ // CraftBukkit end ++ } ++ } ++ // CraftBukkit end ++ + public void onBlockStateChange(BlockPosition blockposition, IBlockData iblockdata, IBlockData iblockdata1) {} + + @Override +@@ -338,6 +519,14 @@ + + @Override + public IBlockData getBlockState(BlockPosition blockposition) { ++ // CraftBukkit start - tree generation ++ if (captureTreeGeneration) { ++ CapturedBlockState previous = capturedBlockStates.get(blockposition); ++ if (previous != null) { ++ return previous.getHandle(); ++ } ++ } ++ // CraftBukkit end + if (this.isOutsideBuildHeight(blockposition)) { + return Blocks.VOID_AIR.defaultBlockState(); + } else { +@@ -543,6 +732,16 @@ + @Nullable + @Override + public TileEntity getBlockEntity(BlockPosition blockposition) { ++ // CraftBukkit start ++ return getBlockEntity(blockposition, true); ++ } ++ ++ @Nullable ++ public TileEntity getBlockEntity(BlockPosition blockposition, boolean validate) { ++ if (capturedTileEntities.containsKey(blockposition)) { ++ return capturedTileEntities.get(blockposition); ++ } ++ // CraftBukkit end + return this.isOutsideBuildHeight(blockposition) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(blockposition).getBlockEntity(blockposition, Chunk.EnumTileEntityState.IMMEDIATE)); + } + +@@ -550,6 +749,12 @@ + BlockPosition blockposition = tileentity.getBlockPos(); + + if (!this.isOutsideBuildHeight(blockposition)) { ++ // CraftBukkit start ++ if (captureBlockStates) { ++ capturedTileEntities.put(blockposition.immutable(), tileentity); ++ return; ++ } ++ // CraftBukkit end + this.getChunkAt(blockposition).addAndRegisterBlockEntity(tileentity); + } + } +@@ -680,7 +885,7 @@ + + for (int k = 0; k < j; ++k) { + EntityComplexPart entitycomplexpart = aentitycomplexpart[k]; +- T t0 = (Entity) entitytypetest.tryCast(entitycomplexpart); ++ T t0 = entitytypetest.tryCast(entitycomplexpart); // CraftBukkit - decompile error + + if (t0 != null && predicate.test(t0)) { + list.add(t0); diff --git a/patch-remap/og/net/minecraft/world/level/WorldAccess.patch b/patch-remap/og/net/minecraft/world/level/WorldAccess.patch new file mode 100644 index 0000000000..46d84cb1c3 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/WorldAccess.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/level/WorldAccess.java ++++ b/net/minecraft/world/level/WorldAccess.java +@@ -8,6 +8,17 @@ + WorldServer getLevel(); + + default void addFreshEntityWithPassengers(Entity entity) { +- entity.getSelfAndPassengers().forEach(this::addFreshEntity); ++ // CraftBukkit start ++ this.addFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ default void addFreshEntityWithPassengers(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) { ++ entity.getSelfAndPassengers().forEach((e) -> this.addFreshEntity(e, reason)); + } ++ ++ @Override ++ default WorldServer getMinecraftWorld() { ++ return getLevel(); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/level/block/AbstractCandleBlock.patch b/patch-remap/og/net/minecraft/world/level/block/AbstractCandleBlock.patch new file mode 100644 index 0000000000..5ce2f55f0d --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/AbstractCandleBlock.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/block/AbstractCandleBlock.java ++++ b/net/minecraft/world/level/block/AbstractCandleBlock.java +@@ -45,6 +45,11 @@ + @Override + public void onProjectileHit(World world, IBlockData iblockdata, MovingObjectPositionBlock movingobjectpositionblock, IProjectile iprojectile) { + if (!world.isClientSide && iprojectile.isOnFire() && this.canBeLit(iblockdata)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, movingobjectpositionblock.getBlockPos(), iprojectile).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + setLit(world, iblockdata, movingobjectpositionblock.getBlockPos(), true); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BigDripleafBlock.patch b/patch-remap/og/net/minecraft/world/level/block/BigDripleafBlock.patch new file mode 100644 index 0000000000..17afb0f509 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BigDripleafBlock.patch @@ -0,0 +1,102 @@ +--- a/net/minecraft/world/level/block/BigDripleafBlock.java ++++ b/net/minecraft/world/level/block/BigDripleafBlock.java +@@ -42,6 +42,11 @@ + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + import net.minecraft.world.phys.shapes.VoxelShapes; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end ++ + public class BigDripleafBlock extends BlockFacingHorizontal implements IBlockFragilePlantElement, IBlockWaterlogged { + + public static final MapCodec CODEC = simpleCodec(BigDripleafBlock::new); +@@ -116,7 +121,7 @@ + + @Override + public void onProjectileHit(World world, IBlockData iblockdata, MovingObjectPositionBlock movingobjectpositionblock, IProjectile iprojectile) { +- this.setTiltAndScheduleTick(iblockdata, world, movingobjectpositionblock.getBlockPos(), Tilt.FULL, SoundEffects.BIG_DRIPLEAF_TILT_DOWN); ++ this.setTiltAndScheduleTick(iblockdata, world, movingobjectpositionblock.getBlockPos(), Tilt.FULL, SoundEffects.BIG_DRIPLEAF_TILT_DOWN, iprojectile); // CraftBukkit + } + + @Override +@@ -175,7 +180,20 @@ + public void entityInside(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { + if (!world.isClientSide) { + if (iblockdata.getValue(BigDripleafBlock.TILT) == Tilt.NONE && canEntityTilt(blockposition, entity) && !world.hasNeighborSignal(blockposition)) { +- this.setTiltAndScheduleTick(iblockdata, world, blockposition, Tilt.UNSTABLE, (SoundEffect) null); ++ // CraftBukkit start - tilt dripleaf ++ org.bukkit.event.Cancellable cancellable; ++ if (entity instanceof EntityHuman) { ++ cancellable = CraftEventFactory.callPlayerInteractEvent((EntityHuman) entity, org.bukkit.event.block.Action.PHYSICAL, blockposition, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ world.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ if (cancellable.isCancelled()) { ++ return; ++ } ++ this.setTiltAndScheduleTick(iblockdata, world, blockposition, Tilt.UNSTABLE, (SoundEffect) null, entity); ++ // CraftBukkit end + } + + } +@@ -189,9 +207,9 @@ + Tilt tilt = (Tilt) iblockdata.getValue(BigDripleafBlock.TILT); + + if (tilt == Tilt.UNSTABLE) { +- this.setTiltAndScheduleTick(iblockdata, worldserver, blockposition, Tilt.PARTIAL, SoundEffects.BIG_DRIPLEAF_TILT_DOWN); ++ this.setTiltAndScheduleTick(iblockdata, worldserver, blockposition, Tilt.PARTIAL, SoundEffects.BIG_DRIPLEAF_TILT_DOWN, null); // CraftBukkit + } else if (tilt == Tilt.PARTIAL) { +- this.setTiltAndScheduleTick(iblockdata, worldserver, blockposition, Tilt.FULL, SoundEffects.BIG_DRIPLEAF_TILT_DOWN); ++ this.setTiltAndScheduleTick(iblockdata, worldserver, blockposition, Tilt.FULL, SoundEffects.BIG_DRIPLEAF_TILT_DOWN, null); // CraftBukkit + } else if (tilt == Tilt.FULL) { + resetTilt(iblockdata, worldserver, blockposition); + } +@@ -217,8 +235,10 @@ + return entity.onGround() && entity.position().y > (double) ((float) blockposition.getY() + 0.6875F); + } + +- private void setTiltAndScheduleTick(IBlockData iblockdata, World world, BlockPosition blockposition, Tilt tilt, @Nullable SoundEffect soundeffect) { +- setTilt(iblockdata, world, blockposition, tilt); ++ // CraftBukkit start ++ private void setTiltAndScheduleTick(IBlockData iblockdata, World world, BlockPosition blockposition, Tilt tilt, @Nullable SoundEffect soundeffect, @Nullable Entity entity) { ++ if (!setTilt(iblockdata, world, blockposition, tilt, entity)) return; ++ // CraftBukkit end + if (soundeffect != null) { + playTiltSound(world, blockposition, soundeffect); + } +@@ -232,14 +252,21 @@ + } + + private static void resetTilt(IBlockData iblockdata, World world, BlockPosition blockposition) { +- setTilt(iblockdata, world, blockposition, Tilt.NONE); ++ setTilt(iblockdata, world, blockposition, Tilt.NONE, null); // CraftBukkit + if (iblockdata.getValue(BigDripleafBlock.TILT) != Tilt.NONE) { + playTiltSound(world, blockposition, SoundEffects.BIG_DRIPLEAF_TILT_UP); + } + + } + +- private static void setTilt(IBlockData iblockdata, World world, BlockPosition blockposition, Tilt tilt) { ++ // CraftBukkit start ++ private static boolean setTilt(IBlockData iblockdata, World world, BlockPosition blockposition, Tilt tilt, @Nullable Entity entity) { ++ if (entity != null) { ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, iblockdata.setValue(BigDripleafBlock.TILT, tilt))) { ++ return false; ++ } ++ } ++ // CraftBukkit end + Tilt tilt1 = (Tilt) iblockdata.getValue(BigDripleafBlock.TILT); + + world.setBlock(blockposition, (IBlockData) iblockdata.setValue(BigDripleafBlock.TILT, tilt), 2); +@@ -247,6 +274,7 @@ + world.gameEvent((Entity) null, GameEvent.BLOCK_CHANGE, blockposition); + } + ++ return true; // CraftBukkit + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/level/block/Block.patch b/patch-remap/og/net/minecraft/world/level/block/Block.patch new file mode 100644 index 0000000000..f388912c32 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/Block.patch @@ -0,0 +1,54 @@ +--- a/net/minecraft/world/level/block/Block.java ++++ b/net/minecraft/world/level/block/Block.java +@@ -349,7 +349,13 @@ + EntityItem entityitem = (EntityItem) supplier.get(); + + entityitem.setDefaultPickUpDelay(); +- world.addFreshEntity(entityitem); ++ // CraftBukkit start ++ if (world.captureDrops != null) { ++ world.captureDrops.add(entityitem); ++ } else { ++ world.addFreshEntity(entityitem); ++ } ++ // CraftBukkit end + } + } + +@@ -375,7 +381,7 @@ + + public void playerDestroy(World world, EntityHuman entityhuman, BlockPosition blockposition, IBlockData iblockdata, @Nullable TileEntity tileentity, ItemStack itemstack) { + entityhuman.awardStat(StatisticList.BLOCK_MINED.get(this)); +- entityhuman.causeFoodExhaustion(0.005F); ++ entityhuman.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED); // CraftBukkit - EntityExhaustionEvent + dropResources(iblockdata, world, blockposition, tileentity, entityhuman, itemstack); + } + +@@ -512,17 +518,25 @@ + return this.builtInRegistryHolder; + } + +- protected void tryDropExperience(WorldServer worldserver, BlockPosition blockposition, ItemStack itemstack, IntProvider intprovider) { ++ // CraftBukkit start ++ protected int tryDropExperience(WorldServer worldserver, BlockPosition blockposition, ItemStack itemstack, IntProvider intprovider) { + if (EnchantmentManager.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, itemstack) == 0) { + int i = intprovider.sample(worldserver.random); + + if (i > 0) { +- this.popExperience(worldserver, blockposition, i); ++ // this.popExperience(worldserver, blockposition, i); ++ return i; + } + } + ++ return 0; + } + ++ public int getExpDrop(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, ItemStack itemstack, boolean flag) { ++ return 0; ++ } ++ // CraftBukkit end ++ + public static final class a { + + private final IBlockData first; diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockBamboo.patch b/patch-remap/og/net/minecraft/world/level/block/BlockBamboo.patch new file mode 100644 index 0000000000..4d6cca39ca --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockBamboo.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/world/level/block/BlockBamboo.java ++++ b/net/minecraft/world/level/block/BlockBamboo.java +@@ -187,7 +187,7 @@ + BlockPosition blockposition1 = blockposition.above(i); + IBlockData iblockdata1 = worldserver.getBlockState(blockposition1); + +- if (k >= 16 || (Integer) iblockdata1.getValue(BlockBamboo.STAGE) == 1 || !worldserver.isEmptyBlock(blockposition1.above())) { ++ if (k >= 16 || !iblockdata1.is(Blocks.BAMBOO) || (Integer) iblockdata1.getValue(BlockBamboo.STAGE) == 1 || !worldserver.isEmptyBlock(blockposition1.above())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here + return; + } + +@@ -208,14 +208,18 @@ + BlockPosition blockposition1 = blockposition.below(2); + IBlockData iblockdata2 = world.getBlockState(blockposition1); + BlockPropertyBambooSize blockpropertybamboosize = BlockPropertyBambooSize.NONE; ++ boolean shouldUpdateOthers = false; // CraftBukkit + + if (i >= 1) { + if (iblockdata1.is(Blocks.BAMBOO) && iblockdata1.getValue(BlockBamboo.LEAVES) != BlockPropertyBambooSize.NONE) { + if (iblockdata1.is(Blocks.BAMBOO) && iblockdata1.getValue(BlockBamboo.LEAVES) != BlockPropertyBambooSize.NONE) { + blockpropertybamboosize = BlockPropertyBambooSize.LARGE; + if (iblockdata2.is(Blocks.BAMBOO)) { +- world.setBlock(blockposition.below(), (IBlockData) iblockdata1.setValue(BlockBamboo.LEAVES, BlockPropertyBambooSize.SMALL), 3); +- world.setBlock(blockposition1, (IBlockData) iblockdata2.setValue(BlockBamboo.LEAVES, BlockPropertyBambooSize.NONE), 3); ++ // CraftBukkit start - moved down ++ // world.setBlock(blockposition.below(), (IBlockData) iblockdata1.setValue(BlockBamboo.LEAVES, BlockPropertyBambooSize.SMALL), 3); ++ // world.setBlock(blockposition1, (IBlockData) iblockdata2.setValue(BlockBamboo.LEAVES, BlockPropertyBambooSize.NONE), 3); ++ shouldUpdateOthers = true; ++ // CraftBukkit end + } + } + } else { +@@ -226,7 +230,14 @@ + int j = (Integer) iblockdata.getValue(BlockBamboo.AGE) != 1 && !iblockdata2.is(Blocks.BAMBOO) ? 0 : 1; + int k = (i < 11 || randomsource.nextFloat() >= 0.25F) && i != 15 ? 0 : 1; + +- world.setBlock(blockposition.above(), (IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(BlockBamboo.AGE, j)).setValue(BlockBamboo.LEAVES, blockpropertybamboosize)).setValue(BlockBamboo.STAGE, k), 3); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, blockposition, blockposition.above(), (IBlockData) ((IBlockData) ((IBlockData) this.defaultBlockState().setValue(BlockBamboo.AGE, j)).setValue(BlockBamboo.LEAVES, blockpropertybamboosize)).setValue(BlockBamboo.STAGE, k), 3)) { ++ if (shouldUpdateOthers) { ++ world.setBlock(blockposition.below(), (IBlockData) iblockdata1.setValue(BlockBamboo.LEAVES, BlockPropertyBambooSize.SMALL), 3); ++ world.setBlock(blockposition1, (IBlockData) iblockdata2.setValue(BlockBamboo.LEAVES, BlockPropertyBambooSize.NONE), 3); ++ } ++ } ++ // CraftBukkit end + } + + protected int getHeightAboveUpToMax(IBlockAccess iblockaccess, BlockPosition blockposition) { diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockBambooSapling.patch b/patch-remap/og/net/minecraft/world/level/block/BlockBambooSapling.patch new file mode 100644 index 0000000000..e734aac68c --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockBambooSapling.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/world/level/block/BlockBambooSapling.java ++++ b/net/minecraft/world/level/block/BlockBambooSapling.java +@@ -95,6 +95,6 @@ + } + + protected void growBamboo(World world, BlockPosition blockposition) { +- world.setBlock(blockposition.above(), (IBlockData) Blocks.BAMBOO.defaultBlockState().setValue(BlockBamboo.LEAVES, BlockPropertyBambooSize.SMALL), 3); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, blockposition, blockposition.above(), (IBlockData) Blocks.BAMBOO.defaultBlockState().setValue(BlockBamboo.LEAVES, BlockPropertyBambooSize.SMALL), 3); // CraftBukkit - BlockSpreadEvent + } + } diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockBed.patch b/patch-remap/og/net/minecraft/world/level/block/BlockBed.patch new file mode 100644 index 0000000000..a5a97d00dd --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockBed.patch @@ -0,0 +1,72 @@ +--- a/net/minecraft/world/level/block/BlockBed.java ++++ b/net/minecraft/world/level/block/BlockBed.java +@@ -94,7 +94,8 @@ + } + } + +- if (!canSetSpawn(world)) { ++ // CraftBukkit - moved world and biome check into EntityHuman ++ if (false && !canSetSpawn(world)) { + world.removeBlock(blockposition, false); + BlockPosition blockposition1 = blockposition.relative(((EnumDirection) iblockdata.getValue(BlockBed.FACING)).getOpposite()); + +@@ -113,7 +114,16 @@ + + return EnumInteractionResult.SUCCESS; + } else { ++ // CraftBukkit start ++ IBlockData finaliblockdata = iblockdata; ++ BlockPosition finalblockposition = blockposition; ++ // CraftBukkit end + entityhuman.startSleepInBed(blockposition).ifLeft((entityhuman_enumbedresult) -> { ++ // CraftBukkit start - handling bed explosion from below here ++ if (!world.dimensionType().bedWorks()) { ++ this.explodeBed(finaliblockdata, world, finalblockposition); ++ } else ++ // CraftBukkit end + if (entityhuman_enumbedresult.getMessage() != null) { + entityhuman.displayClientMessage(entityhuman_enumbedresult.getMessage(), true); + } +@@ -124,8 +134,29 @@ + } + } + ++ // CraftBukkit start ++ private EnumInteractionResult explodeBed(IBlockData iblockdata, World world, BlockPosition blockposition) { ++ { ++ { ++ world.removeBlock(blockposition, false); ++ BlockPosition blockposition1 = blockposition.relative(((EnumDirection) iblockdata.getValue(BlockBed.FACING)).getOpposite()); ++ ++ if (world.getBlockState(blockposition1).getBlock() == this) { ++ world.removeBlock(blockposition1, false); ++ } ++ ++ Vec3D vec3d = blockposition.getCenter(); ++ ++ world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, World.a.BLOCK); ++ return EnumInteractionResult.SUCCESS; ++ } ++ } ++ } ++ // CraftBukkit end ++ + public static boolean canSetSpawn(World world) { +- return world.dimensionType().bedWorks(); ++ // CraftBukkit - moved world and biome check into EntityHuman ++ return true || world.dimensionType().bedWorks(); + } + + private boolean kickVillagerOutOfBed(World world, BlockPosition blockposition) { +@@ -324,6 +355,11 @@ + BlockPosition blockposition1 = blockposition.relative((EnumDirection) iblockdata.getValue(BlockBed.FACING)); + + world.setBlock(blockposition1, (IBlockData) iblockdata.setValue(BlockBed.PART, BlockPropertyBedPart.HEAD), 3); ++ // CraftBukkit start - SPIGOT-7315: Don't updated if we capture block states ++ if (world.captureBlockStates) { ++ return; ++ } ++ // CraftBukkit end + world.blockUpdated(blockposition, Blocks.AIR); + iblockdata.updateNeighbourShapes(world, blockposition, 3); + } diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockBeehive.patch b/patch-remap/og/net/minecraft/world/level/block/BlockBeehive.patch new file mode 100644 index 0000000000..7b6ec34eb1 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockBeehive.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/level/block/BlockBeehive.java ++++ b/net/minecraft/world/level/block/BlockBeehive.java +@@ -119,7 +119,7 @@ + if (entitybee.getTarget() == null) { + EntityHuman entityhuman = (EntityHuman) SystemUtils.getRandom(list1, world.random); + +- entitybee.setTarget(entityhuman); ++ entitybee.setTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit + } + } + } diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockBell.patch b/patch-remap/og/net/minecraft/world/level/block/BlockBell.patch new file mode 100644 index 0000000000..76a048508f --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockBell.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/block/BlockBell.java ++++ b/net/minecraft/world/level/block/BlockBell.java +@@ -146,6 +146,11 @@ + if (enumdirection == null) { + enumdirection = (EnumDirection) world.getBlockState(blockposition).getValue(BlockBell.FACING); + } ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBellRingEvent(world, blockposition, enumdirection, entity)) { ++ return false; ++ } ++ // CraftBukkit end + + ((TileEntityBell) tileentity).onHit(enumdirection); + world.playSound((EntityHuman) null, blockposition, SoundEffects.BELL_BLOCK, SoundCategory.BLOCKS, 2.0F, 1.0F); diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockButtonAbstract.patch b/patch-remap/og/net/minecraft/world/level/block/BlockButtonAbstract.patch new file mode 100644 index 0000000000..c06c5eb264 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockButtonAbstract.patch @@ -0,0 +1,72 @@ +--- a/net/minecraft/world/level/block/BlockButtonAbstract.java ++++ b/net/minecraft/world/level/block/BlockButtonAbstract.java +@@ -33,6 +33,11 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++// CraftBukkit start ++import org.bukkit.event.block.BlockRedstoneEvent; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end ++ + public class BlockButtonAbstract extends BlockAttachable { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +@@ -124,6 +129,19 @@ + if ((Boolean) iblockdata.getValue(BlockButtonAbstract.POWERED)) { + return EnumInteractionResult.CONSUME; + } else { ++ // CraftBukkit start ++ boolean powered = ((Boolean) iblockdata.getValue(POWERED)); ++ org.bukkit.block.Block block = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ int old = (powered) ? 15 : 0; ++ int current = (!powered) ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current); ++ world.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if ((eventRedstone.getNewCurrent() > 0) != (!powered)) { ++ return EnumInteractionResult.SUCCESS; ++ } ++ // CraftBukkit end + this.press(iblockdata, world, blockposition); + this.playSound(entityhuman, world, blockposition, true); + world.gameEvent((Entity) entityhuman, GameEvent.BLOCK_ACTIVATE, blockposition); +@@ -195,11 +213,36 @@ + } + + protected void checkPressed(IBlockData iblockdata, World world, BlockPosition blockposition) { +- EntityArrow entityarrow = this.type.canButtonBeActivatedByArrows() ? (EntityArrow) world.getEntitiesOfClass(EntityArrow.class, iblockdata.getShape(world, blockposition).bounds().move(blockposition)).stream().findFirst().orElse((Object) null) : null; ++ EntityArrow entityarrow = this.type.canButtonBeActivatedByArrows() ? (EntityArrow) world.getEntitiesOfClass(EntityArrow.class, iblockdata.getShape(world, blockposition).bounds().move(blockposition)).stream().findFirst().orElse(null) : null; // CraftBukkit - decompile error + boolean flag = entityarrow != null; + boolean flag1 = (Boolean) iblockdata.getValue(BlockButtonAbstract.POWERED); + ++ // CraftBukkit start - Call interact event when arrows turn on wooden buttons ++ if (flag1 != flag && flag) { ++ org.bukkit.block.Block block = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ EntityInteractEvent event = new EntityInteractEvent(entityarrow.getBukkitEntity(), block); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ + if (flag != flag1) { ++ // CraftBukkit start ++ boolean powered = flag1; ++ org.bukkit.block.Block block = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ int old = (powered) ? 15 : 0; ++ int current = (!powered) ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current); ++ world.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if ((flag && eventRedstone.getNewCurrent() <= 0) || (!flag && eventRedstone.getNewCurrent() > 0)) { ++ return; ++ } ++ // CraftBukkit end + world.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockButtonAbstract.POWERED, flag), 3); + this.updateNeighbours(iblockdata, world, blockposition); + this.playSound((EntityHuman) null, world, blockposition, flag); diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockCactus.patch b/patch-remap/og/net/minecraft/world/level/block/BlockCactus.patch new file mode 100644 index 0000000000..83fdc4bebd --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockCactus.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/level/block/BlockCactus.java ++++ b/net/minecraft/world/level/block/BlockCactus.java +@@ -22,6 +22,8 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public class BlockCactus extends Block { + + public static final MapCodec CODEC = simpleCodec(BlockCactus::new); +@@ -64,7 +66,7 @@ + int j = (Integer) iblockdata.getValue(BlockCactus.AGE); + + if (j == 15) { +- worldserver.setBlockAndUpdate(blockposition1, this.defaultBlockState()); ++ CraftEventFactory.handleBlockGrowEvent(worldserver, blockposition1, this.defaultBlockState()); // CraftBukkit + IBlockData iblockdata1 = (IBlockData) iblockdata.setValue(BlockCactus.AGE, 0); + + worldserver.setBlock(blockposition, iblockdata1, 4); +@@ -119,7 +121,9 @@ + + @Override + public void entityInside(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { ++ CraftEventFactory.blockDamage = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); // CraftBukkit + entity.hurt(world.damageSources().cactus(), 1.0F); ++ CraftEventFactory.blockDamage = null; // CraftBukkit + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockCake.patch b/patch-remap/og/net/minecraft/world/level/block/BlockCake.patch new file mode 100644 index 0000000000..f35b847b9c --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockCake.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/level/block/BlockCake.java ++++ b/net/minecraft/world/level/block/BlockCake.java +@@ -92,7 +92,18 @@ + return EnumInteractionResult.PASS; + } else { + entityhuman.awardStat(StatisticList.EAT_CAKE_SLICE); +- entityhuman.getFoodData().eat(2, 0.1F); ++ // CraftBukkit start ++ // entityhuman.getFoodData().eat(2, 0.1F); ++ int oldFoodLevel = entityhuman.getFoodData().foodLevel; ++ ++ org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(entityhuman, 2 + oldFoodLevel); ++ ++ if (!event.isCancelled()) { ++ entityhuman.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, 0.1F); ++ } ++ ++ ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().sendHealthUpdate(); ++ // CraftBukkit end + int i = (Integer) iblockdata.getValue(BlockCake.BITES); + + generatoraccess.gameEvent((Entity) entityhuman, GameEvent.EAT, blockposition); diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockCampfire.patch b/patch-remap/og/net/minecraft/world/level/block/BlockCampfire.patch new file mode 100644 index 0000000000..71f21908c3 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockCampfire.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/level/block/BlockCampfire.java ++++ b/net/minecraft/world/level/block/BlockCampfire.java +@@ -50,6 +50,10 @@ + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + import net.minecraft.world.phys.shapes.VoxelShapes; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++// CraftBukkit end ++ + public class BlockCampfire extends BlockTileEntity implements IBlockWaterlogged { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +@@ -106,7 +110,9 @@ + @Override + public void entityInside(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { + if ((Boolean) iblockdata.getValue(BlockCampfire.LIT) && entity instanceof EntityLiving && !EnchantmentManager.hasFrostWalker((EntityLiving) entity)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = CraftBlock.at(world, blockposition); // CraftBukkit + entity.hurt(world.damageSources().inFire(), (float) this.fireDamage); ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = null; // CraftBukkit + } + + super.entityInside(iblockdata, world, blockposition, entity); +@@ -216,6 +222,11 @@ + BlockPosition blockposition = movingobjectpositionblock.getBlockPos(); + + if (!world.isClientSide && iprojectile.isOnFire() && iprojectile.mayInteract(world, blockposition) && !(Boolean) iblockdata.getValue(BlockCampfire.LIT) && !(Boolean) iblockdata.getValue(BlockCampfire.WATERLOGGED)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition, iprojectile).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + world.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockProperties.LIT, true), 11); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockCauldron.patch b/patch-remap/og/net/minecraft/world/level/block/BlockCauldron.patch new file mode 100644 index 0000000000..e699d35015 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockCauldron.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/world/level/block/BlockCauldron.java ++++ b/net/minecraft/world/level/block/BlockCauldron.java +@@ -12,6 +12,10 @@ + import net.minecraft.world.level.material.FluidType; + import net.minecraft.world.level.material.FluidTypes; + ++// CraftBukkit start ++import org.bukkit.event.block.CauldronLevelChangeEvent; ++// CraftBukkit end ++ + public class BlockCauldron extends AbstractCauldronBlock { + + public static final MapCodec CODEC = simpleCodec(BlockCauldron::new); +@@ -61,13 +65,11 @@ + + if (fluidtype == FluidTypes.WATER) { + iblockdata1 = Blocks.WATER_CAULDRON.defaultBlockState(); +- world.setBlockAndUpdate(blockposition, iblockdata1); +- world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.a.of(iblockdata1)); ++ LayeredCauldronBlock.changeLevel(iblockdata, world, blockposition, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL); // CraftBukkit + world.levelEvent(1047, blockposition, 0); + } else if (fluidtype == FluidTypes.LAVA) { + iblockdata1 = Blocks.LAVA_CAULDRON.defaultBlockState(); +- world.setBlockAndUpdate(blockposition, iblockdata1); +- world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.a.of(iblockdata1)); ++ LayeredCauldronBlock.changeLevel(iblockdata, world, blockposition, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL); // CraftBukkit + world.levelEvent(1046, blockposition, 0); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockChest.patch b/patch-remap/og/net/minecraft/world/level/block/BlockChest.patch new file mode 100644 index 0000000000..3f9027edce --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockChest.patch @@ -0,0 +1,92 @@ +--- a/net/minecraft/world/level/block/BlockChest.java ++++ b/net/minecraft/world/level/block/BlockChest.java +@@ -93,24 +93,7 @@ + public Optional acceptDouble(final TileEntityChest tileentitychest, final TileEntityChest tileentitychest1) { + final InventoryLargeChest inventorylargechest = new InventoryLargeChest(tileentitychest, tileentitychest1); + +- return Optional.of(new ITileInventory() { +- @Nullable +- @Override +- public Container createMenu(int i, PlayerInventory playerinventory, EntityHuman entityhuman) { +- if (tileentitychest.canOpen(entityhuman) && tileentitychest1.canOpen(entityhuman)) { +- tileentitychest.unpackLootTable(playerinventory.player); +- tileentitychest1.unpackLootTable(playerinventory.player); +- return ContainerChest.sixRows(i, playerinventory, inventorylargechest); +- } else { +- return null; +- } +- } +- +- @Override +- public IChatBaseComponent getDisplayName() { +- return (IChatBaseComponent) (tileentitychest.hasCustomName() ? tileentitychest.getDisplayName() : (tileentitychest1.hasCustomName() ? tileentitychest1.getDisplayName() : IChatBaseComponent.translatable("container.chestDouble"))); +- } +- }); ++ return Optional.of(new DoubleInventory(tileentitychest, tileentitychest1, inventorylargechest)); // CraftBukkit + } + + public Optional acceptSingle(TileEntityChest tileentitychest) { +@@ -123,6 +106,38 @@ + } + }; + ++ // CraftBukkit start ++ public static class DoubleInventory implements ITileInventory { ++ ++ private final TileEntityChest tileentitychest; ++ private final TileEntityChest tileentitychest1; ++ public final InventoryLargeChest inventorylargechest; ++ ++ public DoubleInventory(TileEntityChest tileentitychest, TileEntityChest tileentitychest1, InventoryLargeChest inventorylargechest) { ++ this.tileentitychest = tileentitychest; ++ this.tileentitychest1 = tileentitychest1; ++ this.inventorylargechest = inventorylargechest; ++ } ++ ++ @Nullable ++ @Override ++ public Container createMenu(int i, PlayerInventory playerinventory, EntityHuman entityhuman) { ++ if (tileentitychest.canOpen(entityhuman) && tileentitychest1.canOpen(entityhuman)) { ++ tileentitychest.unpackLootTable(playerinventory.player); ++ tileentitychest1.unpackLootTable(playerinventory.player); ++ return ContainerChest.sixRows(i, playerinventory, inventorylargechest); ++ } else { ++ return null; ++ } ++ } ++ ++ @Override ++ public IChatBaseComponent getDisplayName() { ++ return (IChatBaseComponent) (tileentitychest.hasCustomName() ? tileentitychest.getDisplayName() : (tileentitychest1.hasCustomName() ? tileentitychest1.getDisplayName() : IChatBaseComponent.translatable("container.chestDouble"))); ++ } ++ }; ++ // CraftBukkit end ++ + @Override + public MapCodec codec() { + return BlockChest.CODEC; +@@ -278,7 +293,7 @@ + + @Override + public DoubleBlockFinder.Result combine(IBlockData iblockdata, World world, BlockPosition blockposition, boolean flag) { +- BiPredicate bipredicate; ++ BiPredicate bipredicate; // CraftBukkit - decompile error + + if (flag) { + bipredicate = (generatoraccess, blockposition1) -> { +@@ -294,7 +309,14 @@ + @Nullable + @Override + public ITileInventory getMenuProvider(IBlockData iblockdata, World world, BlockPosition blockposition) { +- return (ITileInventory) ((Optional) this.combine(iblockdata, world, blockposition, false).apply(BlockChest.MENU_PROVIDER_COMBINER)).orElse((Object) null); ++ // CraftBukkit start ++ return getMenuProvider(iblockdata, world, blockposition, false); ++ } ++ ++ @Nullable ++ public ITileInventory getMenuProvider(IBlockData iblockdata, World world, BlockPosition blockposition, boolean ignoreObstructions) { ++ return (ITileInventory) ((Optional) this.combine(iblockdata, world, blockposition, ignoreObstructions).apply(BlockChest.MENU_PROVIDER_COMBINER)).orElse((Object) null); ++ // CraftBukkit end + } + + public static DoubleBlockFinder.Combiner opennessCombiner(final LidBlockEntity lidblockentity) { diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockChorusFlower.patch b/patch-remap/og/net/minecraft/world/level/block/BlockChorusFlower.patch new file mode 100644 index 0000000000..69451ae16f --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockChorusFlower.patch @@ -0,0 +1,73 @@ +--- a/net/minecraft/world/level/block/BlockChorusFlower.java ++++ b/net/minecraft/world/level/block/BlockChorusFlower.java +@@ -22,6 +22,8 @@ + import net.minecraft.world.phys.MovingObjectPositionBlock; + import net.minecraft.world.phys.shapes.VoxelShape; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public class BlockChorusFlower extends Block { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +@@ -102,8 +104,12 @@ + } + + if (flag && allNeighborsEmpty(worldserver, blockposition1, (EnumDirection) null) && worldserver.isEmptyBlock(blockposition.above(2))) { +- worldserver.setBlock(blockposition, BlockChorusFruit.getStateWithConnections(worldserver, blockposition, this.plant.defaultBlockState()), 2); +- this.placeGrownFlower(worldserver, blockposition1, i); ++ // CraftBukkit start - add event ++ if (CraftEventFactory.handleBlockSpreadEvent(worldserver, blockposition, blockposition1, this.defaultBlockState().setValue(BlockChorusFlower.AGE, Integer.valueOf(i)), 2)) { ++ worldserver.setBlock(blockposition, BlockChorusFruit.getStateWithConnections(worldserver, blockposition, this.plant.defaultBlockState()), 2); ++ this.placeGrownFlower(worldserver, blockposition1, i); ++ } ++ // CraftBukkit end + } else if (i < 4) { + j = randomsource.nextInt(4); + if (flag1) { +@@ -117,18 +123,30 @@ + BlockPosition blockposition2 = blockposition.relative(enumdirection); + + if (worldserver.isEmptyBlock(blockposition2) && worldserver.isEmptyBlock(blockposition2.below()) && allNeighborsEmpty(worldserver, blockposition2, enumdirection.getOpposite())) { +- this.placeGrownFlower(worldserver, blockposition2, i + 1); +- flag2 = true; ++ // CraftBukkit start - add event ++ if (CraftEventFactory.handleBlockSpreadEvent(worldserver, blockposition, blockposition2, this.defaultBlockState().setValue(BlockChorusFlower.AGE, Integer.valueOf(i + 1)), 2)) { ++ this.placeGrownFlower(worldserver, blockposition2, i + 1); ++ flag2 = true; ++ } ++ // CraftBukkit end + } + } + + if (flag2) { + worldserver.setBlock(blockposition, BlockChorusFruit.getStateWithConnections(worldserver, blockposition, this.plant.defaultBlockState()), 2); + } else { +- this.placeDeadFlower(worldserver, blockposition); ++ // CraftBukkit start - add event ++ if (CraftEventFactory.handleBlockGrowEvent(worldserver, blockposition, this.defaultBlockState().setValue(BlockChorusFlower.AGE, Integer.valueOf(5)), 2)) { ++ this.placeDeadFlower(worldserver, blockposition); ++ } ++ // CraftBukkit end + } + } else { +- this.placeDeadFlower(worldserver, blockposition); ++ // CraftBukkit start - add event ++ if (CraftEventFactory.handleBlockGrowEvent(worldserver, blockposition, this.defaultBlockState().setValue(BlockChorusFlower.AGE, Integer.valueOf(5)), 2)) { ++ this.placeDeadFlower(worldserver, blockposition); ++ } ++ // CraftBukkit end + } + + } +@@ -265,6 +283,11 @@ + BlockPosition blockposition = movingobjectpositionblock.getBlockPos(); + + if (!world.isClientSide && iprojectile.mayInteract(world, blockposition) && iprojectile.mayBreak(world)) { ++ // CraftBukkit ++ if (!CraftEventFactory.callEntityChangeBlockEvent(iprojectile, blockposition, Blocks.AIR.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end + world.destroyBlock(blockposition, true, iprojectile); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockCocoa.patch b/patch-remap/og/net/minecraft/world/level/block/BlockCocoa.patch new file mode 100644 index 0000000000..3e8d91fa13 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockCocoa.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/world/level/block/BlockCocoa.java ++++ b/net/minecraft/world/level/block/BlockCocoa.java +@@ -21,6 +21,8 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public class BlockCocoa extends BlockFacingHorizontal implements IBlockFragilePlantElement { + + public static final MapCodec CODEC = simpleCodec(BlockCocoa::new); +@@ -61,7 +63,7 @@ + int i = (Integer) iblockdata.getValue(BlockCocoa.AGE); + + if (i < 2) { +- worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockCocoa.AGE, i + 1), 2); ++ CraftEventFactory.handleBlockGrowEvent(worldserver, blockposition, (IBlockData) iblockdata.setValue(BlockCocoa.AGE, i + 1), 2); // CraftBukkkit + } + } + +@@ -131,7 +133,7 @@ + + @Override + public void performBonemeal(WorldServer worldserver, RandomSource randomsource, BlockPosition blockposition, IBlockData iblockdata) { +- worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockCocoa.AGE, (Integer) iblockdata.getValue(BlockCocoa.AGE) + 1), 2); ++ CraftEventFactory.handleBlockGrowEvent(worldserver, blockposition, (IBlockData) iblockdata.setValue(BlockCocoa.AGE, (Integer) iblockdata.getValue(BlockCocoa.AGE) + 1), 2); // CraftBukkit + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockCommand.patch b/patch-remap/og/net/minecraft/world/level/block/BlockCommand.patch new file mode 100644 index 0000000000..49d5b66ba7 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockCommand.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/world/level/block/BlockCommand.java ++++ b/net/minecraft/world/level/block/BlockCommand.java +@@ -30,6 +30,8 @@ + import net.minecraft.world.phys.MovingObjectPositionBlock; + import org.slf4j.Logger; + ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit ++ + public class BlockCommand extends BlockTileEntity implements GameMasterBlock { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +@@ -70,6 +72,15 @@ + TileEntityCommand tileentitycommand = (TileEntityCommand) tileentity; + boolean flag1 = world.hasNeighborSignal(blockposition); + boolean flag2 = tileentitycommand.isPowered(); ++ // CraftBukkit start ++ org.bukkit.block.Block bukkitBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ int old = flag2 ? 15 : 0; ++ int current = flag1 ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bukkitBlock, old, current); ++ world.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ flag1 = eventRedstone.getNewCurrent() > 0; ++ // CraftBukkit end + + tileentitycommand.setPowered(flag1); + if (!flag2 && !tileentitycommand.isAutomatic() && tileentitycommand.getMode() != TileEntityCommand.Type.SEQUENCE) { diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockComposter.patch b/patch-remap/og/net/minecraft/world/level/block/BlockComposter.patch new file mode 100644 index 0000000000..3fd61efded --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockComposter.patch @@ -0,0 +1,116 @@ +--- a/net/minecraft/world/level/block/BlockComposter.java ++++ b/net/minecraft/world/level/block/BlockComposter.java +@@ -41,6 +41,11 @@ + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + import net.minecraft.world.phys.shapes.VoxelShapes; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.inventory.CraftBlockInventoryHolder; ++import org.bukkit.craftbukkit.util.DummyGeneratorAccess; ++// CraftBukkit end ++ + public class BlockComposter extends Block implements IInventoryHolder { + + public static final MapCodec CODEC = simpleCodec(BlockComposter::new); +@@ -255,7 +260,14 @@ + int i = (Integer) iblockdata.getValue(BlockComposter.LEVEL); + + if (i < 7 && BlockComposter.COMPOSTABLES.containsKey(itemstack.getItem())) { +- IBlockData iblockdata1 = addItem(entity, iblockdata, worldserver, blockposition, itemstack); ++ // CraftBukkit start ++ double rand = worldserver.getRandom().nextDouble(); ++ IBlockData iblockdata1 = addItem(entity, iblockdata, DummyGeneratorAccess.INSTANCE, blockposition, itemstack, rand); ++ if (iblockdata == iblockdata1 || !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, iblockdata1)) { ++ return iblockdata; ++ } ++ iblockdata1 = addItem(entity, iblockdata, worldserver, blockposition, itemstack, rand); ++ // CraftBukkit end + + itemstack.shrink(1); + return iblockdata1; +@@ -265,6 +277,14 @@ + } + + public static IBlockData extractProduce(Entity entity, IBlockData iblockdata, World world, BlockPosition blockposition) { ++ // CraftBukkit start ++ if (entity != null && !(entity instanceof EntityHuman)) { ++ IBlockData iblockdata1 = empty(entity, iblockdata, DummyGeneratorAccess.INSTANCE, blockposition); ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, iblockdata1)) { ++ return iblockdata; ++ } ++ } ++ // CraftBukkit end + if (!world.isClientSide) { + Vec3D vec3d = Vec3D.atLowerCornerWithOffset(blockposition, 0.5D, 1.01D, 0.5D).offsetRandom(world.random, 0.7F); + EntityItem entityitem = new EntityItem(world, vec3d.x(), vec3d.y(), vec3d.z(), new ItemStack(Items.BONE_MEAL)); +@@ -288,10 +308,16 @@ + } + + static IBlockData addItem(@Nullable Entity entity, IBlockData iblockdata, GeneratorAccess generatoraccess, BlockPosition blockposition, ItemStack itemstack) { ++ // CraftBukkit start ++ return addItem(entity, iblockdata, generatoraccess, blockposition, itemstack, generatoraccess.getRandom().nextDouble()); ++ } ++ ++ static IBlockData addItem(@Nullable Entity entity, IBlockData iblockdata, GeneratorAccess generatoraccess, BlockPosition blockposition, ItemStack itemstack, double rand) { ++ // CraftBukkit end + int i = (Integer) iblockdata.getValue(BlockComposter.LEVEL); + float f = BlockComposter.COMPOSTABLES.getFloat(itemstack.getItem()); + +- if ((i != 0 || f <= 0.0F) && generatoraccess.getRandom().nextDouble() >= (double) f) { ++ if ((i != 0 || f <= 0.0F) && rand >= (double) f) { + return iblockdata; + } else { + int j = i + 1; +@@ -340,7 +366,8 @@ + public IWorldInventory getContainer(IBlockData iblockdata, GeneratorAccess generatoraccess, BlockPosition blockposition) { + int i = (Integer) iblockdata.getValue(BlockComposter.LEVEL); + +- return (IWorldInventory) (i == 8 ? new BlockComposter.ContainerOutput(iblockdata, generatoraccess, blockposition, new ItemStack(Items.BONE_MEAL)) : (i < 7 ? new BlockComposter.ContainerInput(iblockdata, generatoraccess, blockposition) : new BlockComposter.ContainerEmpty())); ++ // CraftBukkit - empty generatoraccess, blockposition ++ return (IWorldInventory) (i == 8 ? new BlockComposter.ContainerOutput(iblockdata, generatoraccess, blockposition, new ItemStack(Items.BONE_MEAL)) : (i < 7 ? new BlockComposter.ContainerInput(iblockdata, generatoraccess, blockposition) : new BlockComposter.ContainerEmpty(generatoraccess, blockposition))); + } + + public static class ContainerOutput extends InventorySubcontainer implements IWorldInventory { +@@ -355,6 +382,7 @@ + this.state = iblockdata; + this.level = generatoraccess; + this.pos = blockposition; ++ this.bukkitOwner = new CraftBlockInventoryHolder(generatoraccess, blockposition, this); // CraftBukkit + } + + @Override +@@ -379,8 +407,15 @@ + + @Override + public void setChanged() { ++ // CraftBukkit start - allow putting items back (eg cancelled InventoryMoveItemEvent) ++ if (this.isEmpty()) { + BlockComposter.empty((Entity) null, this.state, this.level, this.pos); + this.changed = true; ++ } else { ++ this.level.setBlock(this.pos, this.state, 3); ++ this.changed = false; ++ } ++ // CraftBukkit end + } + } + +@@ -393,6 +428,7 @@ + + public ContainerInput(IBlockData iblockdata, GeneratorAccess generatoraccess, BlockPosition blockposition) { + super(1); ++ this.bukkitOwner = new CraftBlockInventoryHolder(generatoraccess, blockposition, this); // CraftBukkit + this.state = iblockdata; + this.level = generatoraccess; + this.pos = blockposition; +@@ -435,8 +471,9 @@ + + public static class ContainerEmpty extends InventorySubcontainer implements IWorldInventory { + +- public ContainerEmpty() { ++ public ContainerEmpty(GeneratorAccess generatoraccess, BlockPosition blockposition) { // CraftBukkit + super(0); ++ this.bukkitOwner = new CraftBlockInventoryHolder(generatoraccess, blockposition, this); // CraftBukkit + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockConcretePowder.patch b/patch-remap/og/net/minecraft/world/level/block/BlockConcretePowder.patch new file mode 100644 index 0000000000..8eb772daf5 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockConcretePowder.patch @@ -0,0 +1,77 @@ +--- a/net/minecraft/world/level/block/BlockConcretePowder.java ++++ b/net/minecraft/world/level/block/BlockConcretePowder.java +@@ -14,6 +14,12 @@ + import net.minecraft.world.level.block.state.BlockBase; + import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.block.CraftBlockStates; ++import org.bukkit.event.block.BlockFormEvent; ++// CraftBukkit end ++ + public class BlockConcretePowder extends BlockFalling { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +@@ -36,7 +42,7 @@ + @Override + public void onLand(World world, BlockPosition blockposition, IBlockData iblockdata, IBlockData iblockdata1, EntityFallingBlock entityfallingblock) { + if (shouldSolidify(world, blockposition, iblockdata1)) { +- world.setBlock(blockposition, this.concrete.defaultBlockState(), 3); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(world, blockposition, this.concrete.defaultBlockState(), 3); // CraftBukkit + } + + } +@@ -47,7 +53,24 @@ + BlockPosition blockposition = blockactioncontext.getClickedPos(); + IBlockData iblockdata = world.getBlockState(blockposition); + +- return shouldSolidify(world, blockposition, iblockdata) ? this.concrete.defaultBlockState() : super.getStateForPlacement(blockactioncontext); ++ // CraftBukkit start ++ if (!shouldSolidify(world, blockposition, iblockdata)) { ++ return super.getStateForPlacement(blockactioncontext); ++ } ++ ++ // TODO: An event factory call for methods like this ++ CraftBlockState blockState = CraftBlockStates.getBlockState(world, blockposition); ++ blockState.setData(this.concrete.defaultBlockState()); ++ ++ BlockFormEvent event = new BlockFormEvent(blockState.getBlock(), blockState); ++ world.getServer().server.getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ return blockState.getHandle(); ++ } ++ ++ return super.getStateForPlacement(blockactioncontext); ++ // CraftBukkit end + } + + private static boolean shouldSolidify(IBlockAccess iblockaccess, BlockPosition blockposition, IBlockData iblockdata) { +@@ -83,7 +106,25 @@ + + @Override + public IBlockData updateShape(IBlockData iblockdata, EnumDirection enumdirection, IBlockData iblockdata1, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) { +- return touchesLiquid(generatoraccess, blockposition) ? this.concrete.defaultBlockState() : super.updateShape(iblockdata, enumdirection, iblockdata1, generatoraccess, blockposition, blockposition1); ++ // CraftBukkit start ++ if (touchesLiquid(generatoraccess, blockposition)) { ++ // Suppress during worldgen ++ if (!(generatoraccess instanceof World)) { ++ return this.concrete.defaultBlockState(); ++ } ++ CraftBlockState blockState = CraftBlockStates.getBlockState(generatoraccess, blockposition); ++ blockState.setData(this.concrete.defaultBlockState()); ++ ++ BlockFormEvent event = new BlockFormEvent(blockState.getBlock(), blockState); ++ ((World) generatoraccess).getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ return blockState.getHandle(); ++ } ++ } ++ ++ return super.updateShape(iblockdata, enumdirection, iblockdata1, generatoraccess, blockposition, blockposition1); ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockCoral.patch b/patch-remap/og/net/minecraft/world/level/block/BlockCoral.patch new file mode 100644 index 0000000000..f8f8b0374a --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockCoral.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/block/BlockCoral.java ++++ b/net/minecraft/world/level/block/BlockCoral.java +@@ -39,6 +39,11 @@ + @Override + public void tick(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, RandomSource randomsource) { + if (!this.scanForWater(worldserver, blockposition)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(worldserver, blockposition, this.deadBlock.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + worldserver.setBlock(blockposition, this.deadBlock.defaultBlockState(), 2); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockCoralFan.patch b/patch-remap/og/net/minecraft/world/level/block/BlockCoralFan.patch new file mode 100644 index 0000000000..0ed25f6eea --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockCoralFan.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/block/BlockCoralFan.java ++++ b/net/minecraft/world/level/block/BlockCoralFan.java +@@ -40,6 +40,11 @@ + @Override + public void tick(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, RandomSource randomsource) { + if (!scanForWater(iblockdata, worldserver, blockposition)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(worldserver, blockposition, this.deadBlock.defaultBlockState().setValue(BlockCoralFan.WATERLOGGED, false)).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + worldserver.setBlock(blockposition, (IBlockData) this.deadBlock.defaultBlockState().setValue(BlockCoralFan.WATERLOGGED, false), 2); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockCoralFanWall.patch b/patch-remap/og/net/minecraft/world/level/block/BlockCoralFanWall.patch new file mode 100644 index 0000000000..225691788b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockCoralFanWall.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/block/BlockCoralFanWall.java ++++ b/net/minecraft/world/level/block/BlockCoralFanWall.java +@@ -40,6 +40,11 @@ + @Override + public void tick(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, RandomSource randomsource) { + if (!scanForWater(iblockdata, worldserver, blockposition)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(worldserver, blockposition, this.deadBlock.defaultBlockState().setValue(BlockCoralFanWall.WATERLOGGED, false).setValue(BlockCoralFanWall.FACING, iblockdata.getValue(BlockCoralFanWall.FACING))).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + worldserver.setBlock(blockposition, (IBlockData) ((IBlockData) this.deadBlock.defaultBlockState().setValue(BlockCoralFanWall.WATERLOGGED, false)).setValue(BlockCoralFanWall.FACING, (EnumDirection) iblockdata.getValue(BlockCoralFanWall.FACING)), 2); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockCoralPlant.patch b/patch-remap/og/net/minecraft/world/level/block/BlockCoralPlant.patch new file mode 100644 index 0000000000..e716d85de0 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockCoralPlant.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/block/BlockCoralPlant.java ++++ b/net/minecraft/world/level/block/BlockCoralPlant.java +@@ -45,6 +45,11 @@ + @Override + public void tick(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, RandomSource randomsource) { + if (!scanForWater(iblockdata, worldserver, blockposition)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(worldserver, blockposition, this.deadBlock.defaultBlockState().setValue(BlockCoralPlant.WATERLOGGED, false)).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + worldserver.setBlock(blockposition, (IBlockData) this.deadBlock.defaultBlockState().setValue(BlockCoralPlant.WATERLOGGED, false), 2); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockCrops.patch b/patch-remap/og/net/minecraft/world/level/block/BlockCrops.patch new file mode 100644 index 0000000000..1d40ca9bfd --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockCrops.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/world/level/block/BlockCrops.java ++++ b/net/minecraft/world/level/block/BlockCrops.java +@@ -22,6 +22,8 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public class BlockCrops extends BlockPlant implements IBlockFragilePlantElement { + + public static final MapCodec CODEC = simpleCodec(BlockCrops::new); +@@ -83,7 +85,7 @@ + float f = getGrowthSpeed(this, worldserver, blockposition); + + if (randomsource.nextInt((int) (25.0F / f) + 1) == 0) { +- worldserver.setBlock(blockposition, this.getStateForAge(i + 1), 2); ++ CraftEventFactory.handleBlockGrowEvent(worldserver, blockposition, this.getStateForAge(i + 1), 2); // CraftBukkit + } + } + } +@@ -98,7 +100,7 @@ + i = j; + } + +- world.setBlock(blockposition, this.getStateForAge(i), 2); ++ CraftEventFactory.handleBlockGrowEvent(world, blockposition, this.getStateForAge(i), 2); // CraftBukkit + } + + protected int getBonemealAgeIncrease(World world) { +@@ -160,7 +162,7 @@ + + @Override + public void entityInside(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { +- if (entity instanceof EntityRavager && world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ if (entity instanceof EntityRavager && CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, Blocks.AIR.defaultBlockState(), !world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit + world.destroyBlock(blockposition, true, entity); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockDaylightDetector.patch b/patch-remap/og/net/minecraft/world/level/block/BlockDaylightDetector.patch new file mode 100644 index 0000000000..f15f2f15ff --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockDaylightDetector.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/world/level/block/BlockDaylightDetector.java ++++ b/net/minecraft/world/level/block/BlockDaylightDetector.java +@@ -74,6 +74,7 @@ + + i = MathHelper.clamp(i, 0, 15); + if ((Integer) iblockdata.getValue(BlockDaylightDetector.POWER) != i) { ++ i = org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(world, blockposition, ((Integer) iblockdata.getValue(POWER)), i).getNewCurrent(); // CraftBukkit - Call BlockRedstoneEvent + world.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockDaylightDetector.POWER, i), 3); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockDiodeAbstract.patch b/patch-remap/og/net/minecraft/world/level/block/BlockDiodeAbstract.patch new file mode 100644 index 0000000000..6f3a7b9965 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockDiodeAbstract.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/level/block/BlockDiodeAbstract.java ++++ b/net/minecraft/world/level/block/BlockDiodeAbstract.java +@@ -21,6 +21,8 @@ + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + import net.minecraft.world.ticks.TickListPriority; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public abstract class BlockDiodeAbstract extends BlockFacingHorizontal { + + protected static final VoxelShape SHAPE = Block.box(0.0D, 0.0D, 0.0D, 16.0D, 2.0D, 16.0D); +@@ -56,8 +58,18 @@ + boolean flag1 = this.shouldTurnOn(worldserver, blockposition, iblockdata); + + if (flag && !flag1) { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(worldserver, blockposition, 15, 0).getNewCurrent() != 0) { ++ return; ++ } ++ // CraftBukkit end + worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockDiodeAbstract.POWERED, false), 2); + } else if (!flag) { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(worldserver, blockposition, 0, 15).getNewCurrent() != 15) { ++ return; ++ } ++ // CraftBukkit end + worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockDiodeAbstract.POWERED, true), 2); + if (!flag1) { + worldserver.scheduleTick(blockposition, (Block) this, this.getDelay(iblockdata), TickListPriority.VERY_HIGH); diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockDirtSnowSpreadable.patch b/patch-remap/og/net/minecraft/world/level/block/BlockDirtSnowSpreadable.patch new file mode 100644 index 0000000000..8bee36a94b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockDirtSnowSpreadable.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java ++++ b/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java +@@ -44,6 +44,11 @@ + @Override + public void randomTick(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, RandomSource randomsource) { + if (!canBeGrass(iblockdata, worldserver, blockposition)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(worldserver, blockposition, Blocks.DIRT.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + worldserver.setBlockAndUpdate(blockposition, Blocks.DIRT.defaultBlockState()); + } else { + if (worldserver.getMaxLocalRawBrightness(blockposition.above()) >= 9) { +@@ -53,7 +58,7 @@ + BlockPosition blockposition1 = blockposition.offset(randomsource.nextInt(3) - 1, randomsource.nextInt(5) - 3, randomsource.nextInt(3) - 1); + + if (worldserver.getBlockState(blockposition1).is(Blocks.DIRT) && canPropagate(iblockdata1, worldserver, blockposition1)) { +- worldserver.setBlockAndUpdate(blockposition1, (IBlockData) iblockdata1.setValue(BlockDirtSnowSpreadable.SNOWY, worldserver.getBlockState(blockposition1.above()).is(Blocks.SNOW))); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(worldserver, blockposition, blockposition1, (IBlockData) iblockdata1.setValue(BlockDirtSnowSpreadable.SNOWY, worldserver.getBlockState(blockposition1.above()).is(Blocks.SNOW))); // CraftBukkit + } + } + } diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockDispenser.patch b/patch-remap/og/net/minecraft/world/level/block/BlockDispenser.patch new file mode 100644 index 0000000000..36f91ac5b5 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockDispenser.patch @@ -0,0 +1,27 @@ +--- a/net/minecraft/world/level/block/BlockDispenser.java ++++ b/net/minecraft/world/level/block/BlockDispenser.java +@@ -49,6 +49,7 @@ + object2objectopenhashmap.defaultReturnValue(new DispenseBehaviorItem()); + }); + private static final int TRIGGER_DURATION = 4; ++ public static boolean eventFired = false; // CraftBukkit + + @Override + public MapCodec codec() { +@@ -85,7 +86,7 @@ + } + + public void dispenseFrom(WorldServer worldserver, IBlockData iblockdata, BlockPosition blockposition) { +- TileEntityDispenser tileentitydispenser = (TileEntityDispenser) worldserver.getBlockEntity(blockposition, TileEntityTypes.DISPENSER).orElse((Object) null); ++ TileEntityDispenser tileentitydispenser = (TileEntityDispenser) worldserver.getBlockEntity(blockposition, TileEntityTypes.DISPENSER).orElse(null); // CraftBukkit - decompile error + + if (tileentitydispenser == null) { + BlockDispenser.LOGGER.warn("Ignoring dispensing attempt for Dispenser without matching block entity at {}", blockposition); +@@ -101,6 +102,7 @@ + IDispenseBehavior idispensebehavior = this.getDispenseMethod(itemstack); + + if (idispensebehavior != IDispenseBehavior.NOOP) { ++ eventFired = false; // CraftBukkit - reset event status + tileentitydispenser.setItem(i, idispensebehavior.dispense(sourceblock, itemstack)); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockDoor.patch b/patch-remap/og/net/minecraft/world/level/block/BlockDoor.patch new file mode 100644 index 0000000000..284fd9f532 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockDoor.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/world/level/block/BlockDoor.java ++++ b/net/minecraft/world/level/block/BlockDoor.java +@@ -37,6 +37,8 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit ++ + public class BlockDoor extends Block { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +@@ -220,9 +222,24 @@ + + @Override + public void neighborChanged(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1, boolean flag) { +- boolean flag1 = world.hasNeighborSignal(blockposition) || world.hasNeighborSignal(blockposition.relative(iblockdata.getValue(BlockDoor.HALF) == BlockPropertyDoubleBlockHalf.LOWER ? EnumDirection.UP : EnumDirection.DOWN)); ++ // CraftBukkit start ++ BlockPosition otherHalf = blockposition.relative(iblockdata.getValue(BlockDoor.HALF) == BlockPropertyDoubleBlockHalf.LOWER ? EnumDirection.UP : EnumDirection.DOWN); + +- if (!this.defaultBlockState().is(block) && flag1 != (Boolean) iblockdata.getValue(BlockDoor.POWERED)) { ++ org.bukkit.World bworld = world.getWorld(); ++ org.bukkit.block.Block bukkitBlock = bworld.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ org.bukkit.block.Block blockTop = bworld.getBlockAt(otherHalf.getX(), otherHalf.getY(), otherHalf.getZ()); ++ ++ int power = bukkitBlock.getBlockPower(); ++ int powerTop = blockTop.getBlockPower(); ++ if (powerTop > power) power = powerTop; ++ int oldPower = (Boolean) iblockdata.getValue(BlockDoor.POWERED) ? 15 : 0; ++ ++ if (oldPower == 0 ^ power == 0) { ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bukkitBlock, oldPower, power); ++ world.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ boolean flag1 = eventRedstone.getNewCurrent() > 0; ++ // CraftBukkit end + if (flag1 != (Boolean) iblockdata.getValue(BlockDoor.OPEN)) { + this.playSound((Entity) null, world, blockposition, flag1); + world.gameEvent((Entity) null, flag1 ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, blockposition); diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockDragonEgg.patch b/patch-remap/og/net/minecraft/world/level/block/BlockDragonEgg.patch new file mode 100644 index 0000000000..ab3c8078a6 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockDragonEgg.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/level/block/BlockDragonEgg.java ++++ b/net/minecraft/world/level/block/BlockDragonEgg.java +@@ -17,6 +17,8 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++import org.bukkit.event.block.BlockFromToEvent; // CraftBukkit ++ + public class BlockDragonEgg extends BlockFalling { + + public static final MapCodec CODEC = simpleCodec(BlockDragonEgg::new); +@@ -54,6 +56,18 @@ + BlockPosition blockposition1 = blockposition.offset(world.random.nextInt(16) - world.random.nextInt(16), world.random.nextInt(8) - world.random.nextInt(8), world.random.nextInt(16) - world.random.nextInt(16)); + + if (world.getBlockState(blockposition1).isAir() && worldborder.isWithinBounds(blockposition1)) { ++ // CraftBukkit start ++ org.bukkit.block.Block from = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ org.bukkit.block.Block to = world.getWorld().getBlockAt(blockposition1.getX(), blockposition1.getY(), blockposition1.getZ()); ++ BlockFromToEvent event = new BlockFromToEvent(from, to); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ blockposition1 = new BlockPosition(event.getToBlock().getX(), event.getToBlock().getY(), event.getToBlock().getZ()); ++ // CraftBukkit end + if (world.isClientSide) { + for (int j = 0; j < 128; ++j) { + double d0 = world.random.nextDouble(); diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockDropper.patch b/patch-remap/og/net/minecraft/world/level/block/BlockDropper.patch new file mode 100644 index 0000000000..1a97f33a5c --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockDropper.patch @@ -0,0 +1,58 @@ +--- a/net/minecraft/world/level/block/BlockDropper.java ++++ b/net/minecraft/world/level/block/BlockDropper.java +@@ -19,11 +19,17 @@ + import net.minecraft.world.level.block.state.IBlockData; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.world.InventoryLargeChest; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.inventory.InventoryMoveItemEvent; ++// CraftBukkit end ++ + public class BlockDropper extends BlockDispenser { + + private static final Logger LOGGER = LogUtils.getLogger(); + public static final MapCodec CODEC = simpleCodec(BlockDropper::new); +- private static final IDispenseBehavior DISPENSE_BEHAVIOUR = new DispenseBehaviorItem(); ++ private static final IDispenseBehavior DISPENSE_BEHAVIOUR = new DispenseBehaviorItem(true); // CraftBukkit + + @Override + public MapCodec codec() { +@@ -46,7 +52,7 @@ + + @Override + public void dispenseFrom(WorldServer worldserver, IBlockData iblockdata, BlockPosition blockposition) { +- TileEntityDispenser tileentitydispenser = (TileEntityDispenser) worldserver.getBlockEntity(blockposition, TileEntityTypes.DROPPER).orElse((Object) null); ++ TileEntityDispenser tileentitydispenser = (TileEntityDispenser) worldserver.getBlockEntity(blockposition, TileEntityTypes.DROPPER).orElse(null); // CraftBukkit - decompile error + + if (tileentitydispenser == null) { + BlockDropper.LOGGER.warn("Ignoring dispensing attempt for Dropper without matching block entity at {}", blockposition); +@@ -67,8 +73,25 @@ + if (iinventory == null) { + itemstack1 = BlockDropper.DISPENSE_BEHAVIOUR.dispense(sourceblock, itemstack); + } else { +- itemstack1 = TileEntityHopper.addItem(tileentitydispenser, iinventory, itemstack.copy().split(1), enumdirection.getOpposite()); +- if (itemstack1.isEmpty()) { ++ // CraftBukkit start - Fire event when pushing items into other inventories ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(itemstack.copy().split(1)); ++ ++ org.bukkit.inventory.Inventory destinationInventory; ++ // Have to special case large chests as they work oddly ++ if (iinventory instanceof InventoryLargeChest) { ++ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory); ++ } else { ++ destinationInventory = iinventory.getOwner().getInventory(); ++ } ++ ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(tileentitydispenser.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true); ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ itemstack1 = TileEntityHopper.addItem(tileentitydispenser, iinventory, CraftItemStack.asNMSCopy(event.getItem()), enumdirection.getOpposite()); ++ if (event.getItem().equals(oitemstack) && itemstack1.isEmpty()) { ++ // CraftBukkit end + itemstack1 = itemstack.copy(); + itemstack1.shrink(1); + } else { diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockEnderPortal.patch b/patch-remap/og/net/minecraft/world/level/block/BlockEnderPortal.patch new file mode 100644 index 0000000000..2bbe455a3a --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockEnderPortal.patch @@ -0,0 +1,41 @@ +--- a/net/minecraft/world/level/block/BlockEnderPortal.java ++++ b/net/minecraft/world/level/block/BlockEnderPortal.java +@@ -21,6 +21,13 @@ + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + import net.minecraft.world.phys.shapes.VoxelShapes; + ++// CraftBukkit start ++import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.world.level.dimension.WorldDimension; ++import org.bukkit.event.entity.EntityPortalEnterEvent; ++import org.bukkit.event.player.PlayerTeleportEvent; ++// CraftBukkit end ++ + public class BlockEnderPortal extends BlockTileEntity { + + public static final MapCodec CODEC = simpleCodec(BlockEnderPortal::new); +@@ -48,13 +55,22 @@ + @Override + public void entityInside(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { + if (world instanceof WorldServer && entity.canChangeDimensions() && VoxelShapes.joinIsNotEmpty(VoxelShapes.create(entity.getBoundingBox().move((double) (-blockposition.getX()), (double) (-blockposition.getY()), (double) (-blockposition.getZ()))), iblockdata.getShape(world, blockposition), OperatorBoolean.AND)) { +- ResourceKey resourcekey = world.dimension() == World.END ? World.OVERWORLD : World.END; ++ ResourceKey resourcekey = world.getTypeKey() == WorldDimension.END ? World.OVERWORLD : World.END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends + WorldServer worldserver = ((WorldServer) world).getServer().getLevel(resourcekey); + + if (worldserver == null) { +- return; ++ // return; // CraftBukkit - always fire event in case plugins wish to change it + } + ++ // CraftBukkit start - Entity in portal ++ EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (entity instanceof EntityPlayer) { ++ ((EntityPlayer) entity).changeDimension(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); ++ return; ++ } ++ // CraftBukkit end + entity.changeDimension(worldserver); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockFenceGate.patch b/patch-remap/og/net/minecraft/world/level/block/BlockFenceGate.patch new file mode 100644 index 0000000000..ab12c8c076 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockFenceGate.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/level/block/BlockFenceGate.java ++++ b/net/minecraft/world/level/block/BlockFenceGate.java +@@ -168,6 +168,17 @@ + public void neighborChanged(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1, boolean flag) { + if (!world.isClientSide) { + boolean flag1 = world.hasNeighborSignal(blockposition); ++ // CraftBukkit start ++ boolean oldPowered = iblockdata.getValue(BlockFenceGate.POWERED); ++ if (oldPowered != flag1) { ++ int newPower = flag1 ? 15 : 0; ++ int oldPower = oldPowered ? 15 : 0; ++ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition); ++ org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(bukkitBlock, oldPower, newPower); ++ world.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ flag1 = eventRedstone.getNewCurrent() > 0; ++ } ++ // CraftBukkit end + + if ((Boolean) iblockdata.getValue(BlockFenceGate.POWERED) != flag1) { + world.setBlock(blockposition, (IBlockData) ((IBlockData) iblockdata.setValue(BlockFenceGate.POWERED, flag1)).setValue(BlockFenceGate.OPEN, flag1), 2); diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockFire.patch b/patch-remap/og/net/minecraft/world/level/block/BlockFire.patch new file mode 100644 index 0000000000..7a4a7bd484 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockFire.patch @@ -0,0 +1,146 @@ +--- a/net/minecraft/world/level/block/BlockFire.java ++++ b/net/minecraft/world/level/block/BlockFire.java +@@ -29,6 +29,14 @@ + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + import net.minecraft.world.phys.shapes.VoxelShapes; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.block.CraftBlockStates; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.block.BlockBurnEvent; ++import org.bukkit.event.block.BlockFadeEvent; ++// CraftBukkit end ++ + public class BlockFire extends BlockFireAbstract { + + public static final MapCodec CODEC = simpleCodec(BlockFire::new); +@@ -100,7 +108,24 @@ + + @Override + public IBlockData updateShape(IBlockData iblockdata, EnumDirection enumdirection, IBlockData iblockdata1, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) { +- return this.canSurvive(iblockdata, generatoraccess, blockposition) ? this.getStateWithAge(generatoraccess, blockposition, (Integer) iblockdata.getValue(BlockFire.AGE)) : Blocks.AIR.defaultBlockState(); ++ // CraftBukkit start ++ if (!this.canSurvive(iblockdata, generatoraccess, blockposition)) { ++ // Suppress during worldgen ++ if (!(generatoraccess instanceof World)) { ++ return Blocks.AIR.defaultBlockState(); ++ } ++ CraftBlockState blockState = CraftBlockStates.getBlockState(generatoraccess, blockposition); ++ blockState.setData(Blocks.AIR.defaultBlockState()); ++ ++ BlockFadeEvent event = new BlockFadeEvent(blockState.getBlock(), blockState); ++ ((World) generatoraccess).getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ return blockState.getHandle(); ++ } ++ } ++ return this.getStateWithAge(generatoraccess, blockposition, (Integer) iblockdata.getValue(BlockFire.AGE)); ++ // CraftBukkit end + } + + @Override +@@ -149,7 +174,7 @@ + worldserver.scheduleTick(blockposition, (Block) this, getFireTickDelay(worldserver.random)); + if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) { + if (!iblockdata.canSurvive(worldserver, blockposition)) { +- worldserver.removeBlock(blockposition, false); ++ fireExtinguished(worldserver, blockposition); // CraftBukkit - invalid place location + } + + IBlockData iblockdata1 = worldserver.getBlockState(blockposition.below()); +@@ -157,7 +182,7 @@ + int i = (Integer) iblockdata.getValue(BlockFire.AGE); + + if (!flag && worldserver.isRaining() && this.isNearRain(worldserver, blockposition) && randomsource.nextFloat() < 0.2F + (float) i * 0.03F) { +- worldserver.removeBlock(blockposition, false); ++ fireExtinguished(worldserver, blockposition); // CraftBukkit - extinguished by rain + } else { + int j = Math.min(15, i + randomsource.nextInt(3) / 2); + +@@ -171,14 +196,14 @@ + BlockPosition blockposition1 = blockposition.below(); + + if (!worldserver.getBlockState(blockposition1).isFaceSturdy(worldserver, blockposition1, EnumDirection.UP) || i > 3) { +- worldserver.removeBlock(blockposition, false); ++ fireExtinguished(worldserver, blockposition); // CraftBukkit + } + + return; + } + + if (i == 15 && randomsource.nextInt(4) == 0 && !this.canBurn(worldserver.getBlockState(blockposition.below()))) { +- worldserver.removeBlock(blockposition, false); ++ fireExtinguished(worldserver, blockposition); // CraftBukkit + return; + } + } +@@ -186,12 +211,14 @@ + boolean flag1 = worldserver.getBiome(blockposition).is(BiomeTags.INCREASED_FIRE_BURNOUT); + int k = flag1 ? -50 : 0; + +- this.checkBurnOut(worldserver, blockposition.east(), 300 + k, randomsource, i); +- this.checkBurnOut(worldserver, blockposition.west(), 300 + k, randomsource, i); +- this.checkBurnOut(worldserver, blockposition.below(), 250 + k, randomsource, i); +- this.checkBurnOut(worldserver, blockposition.above(), 250 + k, randomsource, i); +- this.checkBurnOut(worldserver, blockposition.north(), 300 + k, randomsource, i); +- this.checkBurnOut(worldserver, blockposition.south(), 300 + k, randomsource, i); ++ // CraftBukkit start - add source blockposition to burn calls ++ this.trySpread(worldserver, blockposition.east(), 300 + k, randomsource, i, blockposition); ++ this.trySpread(worldserver, blockposition.west(), 300 + k, randomsource, i, blockposition); ++ this.trySpread(worldserver, blockposition.below(), 250 + k, randomsource, i, blockposition); ++ this.trySpread(worldserver, blockposition.above(), 250 + k, randomsource, i, blockposition); ++ this.trySpread(worldserver, blockposition.north(), 300 + k, randomsource, i, blockposition); ++ this.trySpread(worldserver, blockposition.south(), 300 + k, randomsource, i, blockposition); ++ // CraftBukkit end + BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); + + for (int l = -1; l <= 1; ++l) { +@@ -217,7 +244,15 @@ + if (i2 > 0 && randomsource.nextInt(k1) <= i2 && (!worldserver.isRaining() || !this.isNearRain(worldserver, blockposition_mutableblockposition))) { + int j2 = Math.min(15, i + randomsource.nextInt(5) / 4); + +- worldserver.setBlock(blockposition_mutableblockposition, this.getStateWithAge(worldserver, blockposition_mutableblockposition, j2), 3); ++ // CraftBukkit start - Call to stop spread of fire ++ if (worldserver.getBlockState(blockposition_mutableblockposition).getBlock() != Blocks.FIRE) { ++ if (CraftEventFactory.callBlockIgniteEvent(worldserver, blockposition_mutableblockposition, blockposition).isCancelled()) { ++ continue; ++ } ++ ++ CraftEventFactory.handleBlockSpreadEvent(worldserver, blockposition, blockposition_mutableblockposition, this.getStateWithAge(worldserver, blockposition_mutableblockposition, j2), 3); // CraftBukkit ++ } ++ // CraftBukkit end + } + } + } +@@ -241,12 +276,28 @@ + return iblockdata.hasProperty(BlockProperties.WATERLOGGED) && (Boolean) iblockdata.getValue(BlockProperties.WATERLOGGED) ? 0 : this.igniteOdds.getInt(iblockdata.getBlock()); + } + +- private void checkBurnOut(World world, BlockPosition blockposition, int i, RandomSource randomsource, int j) { ++ private void trySpread(World world, BlockPosition blockposition, int i, RandomSource randomsource, int j, BlockPosition sourceposition) { // CraftBukkit add sourceposition + int k = this.getBurnOdds(world.getBlockState(blockposition)); + + if (randomsource.nextInt(i) < k) { + IBlockData iblockdata = world.getBlockState(blockposition); + ++ // CraftBukkit start ++ org.bukkit.block.Block theBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ org.bukkit.block.Block sourceBlock = world.getWorld().getBlockAt(sourceposition.getX(), sourceposition.getY(), sourceposition.getZ()); ++ ++ BlockBurnEvent event = new BlockBurnEvent(theBlock, sourceBlock); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ if (iblockdata.getBlock() instanceof BlockTNT && !CraftEventFactory.callTNTPrimeEvent(world, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.FIRE, null, sourceposition)) { ++ return; ++ } ++ // CraftBukkit end ++ + if (randomsource.nextInt(j + 10) < 5 && !world.isRainingAt(blockposition)) { + int l = Math.min(j + randomsource.nextInt(5) / 4, 15); + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockFireAbstract.patch b/patch-remap/og/net/minecraft/world/level/block/BlockFireAbstract.patch new file mode 100644 index 0000000000..6712a45f71 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockFireAbstract.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/world/level/block/BlockFireAbstract.java ++++ b/net/minecraft/world/level/block/BlockFireAbstract.java +@@ -127,7 +127,14 @@ + if (!entity.fireImmune()) { + entity.setRemainingFireTicks(entity.getRemainingFireTicks() + 1); + if (entity.getRemainingFireTicks() == 0) { +- entity.setSecondsOnFire(8); ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityCombustEvent event = new org.bukkit.event.entity.EntityCombustByBlockEvent(org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition), entity.getBukkitEntity(), 8); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ entity.setSecondsOnFire(event.getDuration(), false); ++ } ++ // CraftBukkit end + } + } + +@@ -148,14 +155,14 @@ + } + + if (!iblockdata.canSurvive(world, blockposition)) { +- world.removeBlock(blockposition, false); ++ fireExtinguished(world, blockposition); // CraftBukkit - fuel block broke + } + + } + } + + private static boolean inPortalDimension(World world) { +- return world.dimension() == World.OVERWORLD || world.dimension() == World.NETHER; ++ return world.getTypeKey() == net.minecraft.world.level.dimension.WorldDimension.OVERWORLD || world.getTypeKey() == net.minecraft.world.level.dimension.WorldDimension.NETHER; // CraftBukkit - getTypeKey() + } + + @Override +@@ -203,4 +210,12 @@ + } + } + } ++ ++ // CraftBukkit start ++ protected void fireExtinguished(net.minecraft.world.level.GeneratorAccess world, BlockPosition position) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, position, Blocks.AIR.defaultBlockState()).isCancelled()) { ++ world.removeBlock(position, false); ++ } ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockFluids.patch b/patch-remap/og/net/minecraft/world/level/block/BlockFluids.patch new file mode 100644 index 0000000000..33ae74b51b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockFluids.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/world/level/block/BlockFluids.java ++++ b/net/minecraft/world/level/block/BlockFluids.java +@@ -39,7 +39,7 @@ + public class BlockFluids extends Block implements IFluidSource { + + private static final Codec FLOWING_FLUID = BuiltInRegistries.FLUID.byNameCodec().comapFlatMap((fluidtype) -> { +- DataResult dataresult; ++ DataResult dataresult; // CraftBukkit - decompile error + + if (fluidtype instanceof FluidTypeFlowing) { + FluidTypeFlowing fluidtypeflowing = (FluidTypeFlowing) fluidtype; +@@ -174,14 +174,20 @@ + if (world.getFluidState(blockposition1).is(TagsFluid.WATER)) { + Block block = world.getFluidState(blockposition).isSource() ? Blocks.OBSIDIAN : Blocks.COBBLESTONE; + +- world.setBlockAndUpdate(blockposition, block.defaultBlockState()); +- this.fizz(world, blockposition); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(world, blockposition, block.defaultBlockState())) { ++ this.fizz(world, blockposition); ++ } ++ // CraftBukkit end + return false; + } + + if (flag && world.getBlockState(blockposition1).is(Blocks.BLUE_ICE)) { +- world.setBlockAndUpdate(blockposition, Blocks.BASALT.defaultBlockState()); +- this.fizz(world, blockposition); ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(world, blockposition, Blocks.BASALT.defaultBlockState())) { ++ this.fizz(world, blockposition); ++ } ++ // CraftBukkit end + return false; + } + } diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockFungi.patch b/patch-remap/og/net/minecraft/world/level/block/BlockFungi.patch new file mode 100644 index 0000000000..3f128a977a --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockFungi.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/level/block/BlockFungi.java ++++ b/net/minecraft/world/level/block/BlockFungi.java +@@ -74,6 +74,13 @@ + @Override + public void performBonemeal(WorldServer worldserver, RandomSource randomsource, BlockPosition blockposition, IBlockData iblockdata) { + this.getFeature(worldserver).ifPresent((holder) -> { ++ // CraftBukkit start ++ if (this == Blocks.WARPED_FUNGUS) { ++ BlockSapling.treeType = org.bukkit.TreeType.WARPED_FUNGUS; ++ } else if (this == Blocks.CRIMSON_FUNGUS) { ++ BlockSapling.treeType = org.bukkit.TreeType.CRIMSON_FUNGUS; ++ } ++ // CraftBukkit end + ((WorldGenFeatureConfigured) holder.value()).place(worldserver, worldserver.getChunkSource().getGenerator(), randomsource, blockposition); + }); + } diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockGrassPath.patch b/patch-remap/og/net/minecraft/world/level/block/BlockGrassPath.patch new file mode 100644 index 0000000000..b98e33d889 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockGrassPath.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/block/BlockGrassPath.java ++++ b/net/minecraft/world/level/block/BlockGrassPath.java +@@ -51,6 +51,11 @@ + + @Override + public void tick(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, RandomSource randomsource) { ++ // CraftBukkit start - do not fade if the block is valid here ++ if (iblockdata.canSurvive(worldserver, blockposition)) { ++ return; ++ } ++ // CraftBukkit end + BlockSoil.turnToDirt((Entity) null, iblockdata, worldserver, blockposition); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockGrowingTop.patch b/patch-remap/og/net/minecraft/world/level/block/BlockGrowingTop.patch new file mode 100644 index 0000000000..6421b07264 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockGrowingTop.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/level/block/BlockGrowingTop.java ++++ b/net/minecraft/world/level/block/BlockGrowingTop.java +@@ -48,7 +48,7 @@ + BlockPosition blockposition1 = blockposition.relative(this.growthDirection); + + if (this.canGrowInto(worldserver.getBlockState(blockposition1))) { +- worldserver.setBlockAndUpdate(blockposition1, this.getGrowIntoState(iblockdata, worldserver.random)); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(worldserver, blockposition, blockposition1, this.getGrowIntoState(iblockdata, worldserver.random)); // CraftBukkit + } + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockIce.patch b/patch-remap/og/net/minecraft/world/level/block/BlockIce.patch new file mode 100644 index 0000000000..7164cce2f7 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockIce.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/block/BlockIce.java ++++ b/net/minecraft/world/level/block/BlockIce.java +@@ -59,6 +59,11 @@ + } + + protected void melt(IBlockData iblockdata, World world, BlockPosition blockposition) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, blockposition, world.dimensionType().ultraWarm() ? Blocks.AIR.defaultBlockState() : Blocks.WATER.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + if (world.dimensionType().ultraWarm()) { + world.removeBlock(blockposition, false); + } else { diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockLeaves.patch b/patch-remap/og/net/minecraft/world/level/block/BlockLeaves.patch new file mode 100644 index 0000000000..55eeb6d259 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockLeaves.patch @@ -0,0 +1,26 @@ +--- a/net/minecraft/world/level/block/BlockLeaves.java ++++ b/net/minecraft/world/level/block/BlockLeaves.java +@@ -25,6 +25,8 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapes; + ++import org.bukkit.event.block.LeavesDecayEvent; // CraftBukkit ++ + public class BlockLeaves extends Block implements IBlockWaterlogged { + + public static final MapCodec CODEC = simpleCodec(BlockLeaves::new); +@@ -57,6 +59,14 @@ + @Override + public void randomTick(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, RandomSource randomsource) { + if (this.decaying(iblockdata)) { ++ // CraftBukkit start ++ LeavesDecayEvent event = new LeavesDecayEvent(worldserver.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled() || worldserver.getBlockState(blockposition).getBlock() != this) { ++ return; ++ } ++ // CraftBukkit end + dropResources(iblockdata, worldserver, blockposition); + worldserver.removeBlock(blockposition, false); + } diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockLectern.patch b/patch-remap/og/net/minecraft/world/level/block/BlockLectern.patch new file mode 100644 index 0000000000..d8d6c1e3a0 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockLectern.patch @@ -0,0 +1,17 @@ +--- a/net/minecraft/world/level/block/BlockLectern.java ++++ b/net/minecraft/world/level/block/BlockLectern.java +@@ -207,12 +207,13 @@ + } + + private void popBook(IBlockData iblockdata, World world, BlockPosition blockposition) { +- TileEntity tileentity = world.getBlockEntity(blockposition); ++ TileEntity tileentity = world.getBlockEntity(blockposition, false); // CraftBukkit - don't validate, type may be changed already + + if (tileentity instanceof TileEntityLectern) { + TileEntityLectern tileentitylectern = (TileEntityLectern) tileentity; + EnumDirection enumdirection = (EnumDirection) iblockdata.getValue(BlockLectern.FACING); + ItemStack itemstack = tileentitylectern.getBook().copy(); ++ if (itemstack.isEmpty()) return; // CraftBukkit - SPIGOT-5500 + float f = 0.25F * (float) enumdirection.getStepX(); + float f1 = 0.25F * (float) enumdirection.getStepZ(); + EntityItem entityitem = new EntityItem(world, (double) blockposition.getX() + 0.5D + (double) f, (double) (blockposition.getY() + 1), (double) blockposition.getZ() + 0.5D + (double) f1, itemstack); diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockLever.patch b/patch-remap/og/net/minecraft/world/level/block/BlockLever.patch new file mode 100644 index 0000000000..35959fa06a --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockLever.patch @@ -0,0 +1,32 @@ +--- a/net/minecraft/world/level/block/BlockLever.java ++++ b/net/minecraft/world/level/block/BlockLever.java +@@ -28,6 +28,8 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit ++ + public class BlockLever extends BlockAttachable { + + public static final MapCodec CODEC = simpleCodec(BlockLever::new); +@@ -101,6 +103,20 @@ + + return EnumInteractionResult.SUCCESS; + } else { ++ // CraftBukkit start - Interact Lever ++ boolean powered = iblockdata.getValue(BlockLever.POWERED); // Old powered state ++ org.bukkit.block.Block block = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ int old = (powered) ? 15 : 0; ++ int current = (!powered) ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current); ++ world.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if ((eventRedstone.getNewCurrent() > 0) != (!powered)) { ++ return EnumInteractionResult.SUCCESS; ++ } ++ // CraftBukkit end ++ + iblockdata1 = this.pull(iblockdata, world, blockposition); + float f = (Boolean) iblockdata1.getValue(BlockLever.POWERED) ? 0.6F : 0.5F; + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockMagma.patch b/patch-remap/og/net/minecraft/world/level/block/BlockMagma.patch new file mode 100644 index 0000000000..49050cce28 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockMagma.patch @@ -0,0 +1,12 @@ +--- a/net/minecraft/world/level/block/BlockMagma.java ++++ b/net/minecraft/world/level/block/BlockMagma.java +@@ -30,7 +30,9 @@ + @Override + public void stepOn(World world, BlockPosition blockposition, IBlockData iblockdata, Entity entity) { + if (!entity.isSteppingCarefully() && entity instanceof EntityLiving && !EnchantmentManager.hasFrostWalker((EntityLiving) entity)) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); // CraftBukkit + entity.hurt(world.damageSources().hotFloor(), 1.0F); ++ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = null; // CraftBukkit + } + + super.stepOn(world, blockposition, iblockdata, entity); diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockMinecartDetector.patch b/patch-remap/og/net/minecraft/world/level/block/BlockMinecartDetector.patch new file mode 100644 index 0000000000..0abacadda9 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockMinecartDetector.patch @@ -0,0 +1,28 @@ +--- a/net/minecraft/world/level/block/BlockMinecartDetector.java ++++ b/net/minecraft/world/level/block/BlockMinecartDetector.java +@@ -26,6 +26,8 @@ + import net.minecraft.world.level.block.state.properties.IBlockState; + import net.minecraft.world.phys.AxisAlignedBB; + ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit ++ + public class BlockMinecartDetector extends BlockMinecartTrackAbstract { + + public static final MapCodec CODEC = simpleCodec(BlockMinecartDetector::new); +@@ -87,6 +89,16 @@ + } + + IBlockData iblockdata1; ++ // CraftBukkit start ++ if (flag != flag1) { ++ org.bukkit.block.Block block = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, flag ? 15 : 0, flag1 ? 15 : 0); ++ world.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ flag1 = eventRedstone.getNewCurrent() > 0; ++ } ++ // CraftBukkit end + + if (flag1 && !flag) { + iblockdata1 = (IBlockData) iblockdata.setValue(BlockMinecartDetector.POWERED, true); diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockMobSpawner.patch b/patch-remap/og/net/minecraft/world/level/block/BlockMobSpawner.patch new file mode 100644 index 0000000000..3a7c1b280b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockMobSpawner.patch @@ -0,0 +1,24 @@ +--- a/net/minecraft/world/level/block/BlockMobSpawner.java ++++ b/net/minecraft/world/level/block/BlockMobSpawner.java +@@ -45,12 +45,20 @@ + @Override + public void spawnAfterBreak(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, ItemStack itemstack, boolean flag) { + super.spawnAfterBreak(iblockdata, worldserver, blockposition, itemstack, flag); ++ // CraftBukkit start - Delegate to getExpDrop ++ } ++ ++ @Override ++ public int getExpDrop(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, ItemStack itemstack, boolean flag) { + if (flag) { + int i = 15 + worldserver.random.nextInt(15) + worldserver.random.nextInt(15); + +- this.popExperience(worldserver, blockposition, i); ++ // this.popExperience(worldserver, blockposition, i); ++ return i; + } + ++ return 0; ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockMonsterEggs.patch b/patch-remap/og/net/minecraft/world/level/block/BlockMonsterEggs.patch new file mode 100644 index 0000000000..d77107faf6 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockMonsterEggs.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/level/block/BlockMonsterEggs.java ++++ b/net/minecraft/world/level/block/BlockMonsterEggs.java +@@ -19,6 +19,8 @@ + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.IBlockState; + ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; // CraftBukkit ++ + public class BlockMonsterEggs extends Block { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +@@ -53,7 +55,7 @@ + + if (entitysilverfish != null) { + entitysilverfish.moveTo((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, 0.0F, 0.0F); +- worldserver.addFreshEntity(entitysilverfish); ++ worldserver.addFreshEntity(entitysilverfish, SpawnReason.SILVERFISH_BLOCK); // CraftBukkit - add SpawnReason + entitysilverfish.spawnAnim(); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockMushroom.patch b/patch-remap/og/net/minecraft/world/level/block/BlockMushroom.patch new file mode 100644 index 0000000000..bad8fd7e4b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockMushroom.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/level/block/BlockMushroom.java ++++ b/net/minecraft/world/level/block/BlockMushroom.java +@@ -20,6 +20,10 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++// CraftBukkit start ++import org.bukkit.TreeType; ++// CraftBukkit end ++ + public class BlockMushroom extends BlockPlant implements IBlockFragilePlantElement { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +@@ -75,7 +79,7 @@ + } + + if (worldserver.isEmptyBlock(blockposition2) && iblockdata.canSurvive(worldserver, blockposition2)) { +- worldserver.setBlock(blockposition2, iblockdata, 2); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(worldserver, blockposition, blockposition2, iblockdata, 2); // CraftBukkit + } + } + +@@ -101,6 +105,7 @@ + return false; + } else { + worldserver.removeBlock(blockposition, false); ++ BlockSapling.treeType = (this == Blocks.BROWN_MUSHROOM) ? TreeType.BROWN_MUSHROOM : TreeType.BROWN_MUSHROOM; // CraftBukkit + if (((WorldGenFeatureConfigured) ((Holder) optional.get()).value()).place(worldserver, worldserver.getChunkSource().getGenerator(), randomsource, blockposition)) { + return true; + } else { diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockNetherWart.patch b/patch-remap/og/net/minecraft/world/level/block/BlockNetherWart.patch new file mode 100644 index 0000000000..3e9f116ef7 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockNetherWart.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/level/block/BlockNetherWart.java ++++ b/net/minecraft/world/level/block/BlockNetherWart.java +@@ -54,7 +54,7 @@ + + if (i < 3 && randomsource.nextInt(10) == 0) { + iblockdata = (IBlockData) iblockdata.setValue(BlockNetherWart.AGE, i + 1); +- worldserver.setBlock(blockposition, iblockdata, 2); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(worldserver, blockposition, iblockdata, 2); // CraftBukkit + } + + } diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockNote.patch b/patch-remap/og/net/minecraft/world/level/block/BlockNote.patch new file mode 100644 index 0000000000..0d436f9471 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockNote.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/world/level/block/BlockNote.java ++++ b/net/minecraft/world/level/block/BlockNote.java +@@ -82,6 +82,7 @@ + if (flag1 != (Boolean) iblockdata.getValue(BlockNote.POWERED)) { + if (flag1) { + this.playNote((Entity) null, iblockdata, world, blockposition); ++ iblockdata = world.getBlockState(blockposition); // CraftBukkit - SPIGOT-5617: update in case changed in event + } + + world.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockNote.POWERED, flag1), 3); +@@ -91,6 +92,12 @@ + + private void playNote(@Nullable Entity entity, IBlockData iblockdata, World world, BlockPosition blockposition) { + if (((BlockPropertyInstrument) iblockdata.getValue(BlockNote.INSTRUMENT)).worksAboveNoteBlock() || world.getBlockState(blockposition.above()).isAir()) { ++ // CraftBukkit start ++ org.bukkit.event.block.NotePlayEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callNotePlayEvent(world, blockposition, iblockdata.getValue(BlockNote.INSTRUMENT), iblockdata.getValue(BlockNote.NOTE)); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + world.blockEvent(blockposition, this, 0, 0); + world.gameEvent(entity, GameEvent.NOTE_BLOCK_PLAY, blockposition); + } diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockNylium.patch b/patch-remap/og/net/minecraft/world/level/block/BlockNylium.patch new file mode 100644 index 0000000000..3e7fcfebe7 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockNylium.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/block/BlockNylium.java ++++ b/net/minecraft/world/level/block/BlockNylium.java +@@ -41,6 +41,11 @@ + @Override + public void randomTick(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, RandomSource randomsource) { + if (!canBeNylium(iblockdata, worldserver, blockposition)) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(worldserver, blockposition, Blocks.NETHERRACK.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + worldserver.setBlockAndUpdate(blockposition, Blocks.NETHERRACK.defaultBlockState()); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockObserver.patch b/patch-remap/og/net/minecraft/world/level/block/BlockObserver.patch new file mode 100644 index 0000000000..dae36bc563 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockObserver.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/level/block/BlockObserver.java ++++ b/net/minecraft/world/level/block/BlockObserver.java +@@ -15,6 +15,8 @@ + import net.minecraft.world.level.block.state.properties.BlockProperties; + import net.minecraft.world.level.block.state.properties.BlockStateBoolean; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public class BlockObserver extends BlockDirectional { + + public static final MapCodec CODEC = simpleCodec(BlockObserver::new); +@@ -48,8 +50,18 @@ + @Override + public void tick(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, RandomSource randomsource) { + if ((Boolean) iblockdata.getValue(BlockObserver.POWERED)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(worldserver, blockposition, 15, 0).getNewCurrent() != 0) { ++ return; ++ } ++ // CraftBukkit end + worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockObserver.POWERED, false), 2); + } else { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(worldserver, blockposition, 0, 15).getNewCurrent() != 15) { ++ return; ++ } ++ // CraftBukkit end + worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockObserver.POWERED, true), 2); + worldserver.scheduleTick(blockposition, (Block) this, 2); + } diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockPlant.patch b/patch-remap/og/net/minecraft/world/level/block/BlockPlant.patch new file mode 100644 index 0000000000..689f95275a --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockPlant.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/level/block/BlockPlant.java ++++ b/net/minecraft/world/level/block/BlockPlant.java +@@ -26,7 +26,14 @@ + + @Override + public IBlockData updateShape(IBlockData iblockdata, EnumDirection enumdirection, IBlockData iblockdata1, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) { +- return !iblockdata.canSurvive(generatoraccess, blockposition) ? Blocks.AIR.defaultBlockState() : super.updateShape(iblockdata, enumdirection, iblockdata1, generatoraccess, blockposition, blockposition1); ++ // CraftBukkit start ++ if (!iblockdata.canSurvive(generatoraccess, blockposition)) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(generatoraccess, blockposition).isCancelled()) { ++ return Blocks.AIR.defaultBlockState(); ++ } ++ } ++ return super.updateShape(iblockdata, enumdirection, iblockdata1, generatoraccess, blockposition, blockposition1); ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockPortal.patch b/patch-remap/og/net/minecraft/world/level/block/BlockPortal.patch new file mode 100644 index 0000000000..eaa6a9758f --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockPortal.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/level/block/BlockPortal.java ++++ b/net/minecraft/world/level/block/BlockPortal.java +@@ -26,6 +26,10 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++// CraftBukkit start ++import org.bukkit.event.entity.EntityPortalEnterEvent; ++// CraftBukkit end ++ + public class BlockPortal extends Block { + + public static final MapCodec CODEC = simpleCodec(BlockPortal::new); +@@ -63,7 +67,8 @@ + } + + if (worldserver.getBlockState(blockposition).isValidSpawn(worldserver, blockposition, EntityTypes.ZOMBIFIED_PIGLIN)) { +- Entity entity = EntityTypes.ZOMBIFIED_PIGLIN.spawn(worldserver, blockposition.above(), EnumMobSpawn.STRUCTURE); ++ // CraftBukkit - set spawn reason to NETHER_PORTAL ++ Entity entity = EntityTypes.ZOMBIFIED_PIGLIN.spawn(worldserver, blockposition.above(), EnumMobSpawn.STRUCTURE, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NETHER_PORTAL); + + if (entity != null) { + entity.setPortalCooldown(); +@@ -85,6 +90,10 @@ + @Override + public void entityInside(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { + if (entity.canChangeDimensions()) { ++ // CraftBukkit start - Entity in portal ++ EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ // CraftBukkit end + entity.handleInsidePortal(blockposition); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockPoweredRail.patch b/patch-remap/og/net/minecraft/world/level/block/BlockPoweredRail.patch new file mode 100644 index 0000000000..96b338866d --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockPoweredRail.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/world/level/block/BlockPoweredRail.java ++++ b/net/minecraft/world/level/block/BlockPoweredRail.java +@@ -12,6 +12,8 @@ + import net.minecraft.world.level.block.state.properties.BlockStateEnum; + import net.minecraft.world.level.block.state.properties.IBlockState; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public class BlockPoweredRail extends BlockMinecartTrackAbstract { + + public static final MapCodec CODEC = simpleCodec(BlockPoweredRail::new); +@@ -120,6 +122,13 @@ + boolean flag1 = world.hasNeighborSignal(blockposition) || this.findPoweredRailSignal(world, blockposition, iblockdata, true, 0) || this.findPoweredRailSignal(world, blockposition, iblockdata, false, 0); + + if (flag1 != flag) { ++ // CraftBukkit start ++ int power = flag ? 15 : 0; ++ int newPower = CraftEventFactory.callRedstoneChange(world, blockposition, power, 15 - power).getNewCurrent(); ++ if (newPower == power) { ++ return; ++ } ++ // CraftBukkit end + world.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockPoweredRail.POWERED, flag1), 3); + world.updateNeighborsAt(blockposition.below(), this); + if (((BlockPropertyTrackPosition) iblockdata.getValue(BlockPoweredRail.SHAPE)).isAscending()) { diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockPressurePlateAbstract.patch b/patch-remap/og/net/minecraft/world/level/block/BlockPressurePlateAbstract.patch new file mode 100644 index 0000000000..d985b2e505 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockPressurePlateAbstract.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/world/level/block/BlockPressurePlateAbstract.java ++++ b/net/minecraft/world/level/block/BlockPressurePlateAbstract.java +@@ -22,6 +22,8 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit ++ + public abstract class BlockPressurePlateAbstract extends Block { + + protected static final VoxelShape PRESSED_AABB = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 0.5D, 15.0D); +@@ -90,6 +92,19 @@ + boolean flag = i > 0; + boolean flag1 = j > 0; + ++ // CraftBukkit start - Interact Pressure Plate ++ org.bukkit.World bworld = world.getWorld(); ++ org.bukkit.plugin.PluginManager manager = world.getCraftServer().getPluginManager(); ++ ++ if (flag != flag1) { ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bworld.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), i, j); ++ manager.callEvent(eventRedstone); ++ ++ flag1 = eventRedstone.getNewCurrent() > 0; ++ j = eventRedstone.getNewCurrent(); ++ } ++ // CraftBukkit end ++ + if (i != j) { + IBlockData iblockdata1 = this.setSignalForState(iblockdata, j); + +@@ -144,9 +159,15 @@ + } + + protected static int getEntityCount(World world, AxisAlignedBB axisalignedbb, Class oclass) { ++ // CraftBukkit start ++ return getEntities(world, axisalignedbb, oclass).size(); ++ } ++ ++ protected static java.util.List getEntities(World world, AxisAlignedBB axisalignedbb, Class oclass) { ++ // CraftBukkit end + return world.getEntitiesOfClass(oclass, axisalignedbb, IEntitySelector.NO_SPECTATORS.and((entity) -> { + return !entity.isIgnoringBlockTriggers(); +- })).size(); ++ })); // CraftBukkit + } + + protected abstract int getSignalStrength(World world, BlockPosition blockposition); diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockPressurePlateBinary.patch b/patch-remap/og/net/minecraft/world/level/block/BlockPressurePlateBinary.patch new file mode 100644 index 0000000000..43f9df9d0c --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockPressurePlateBinary.patch @@ -0,0 +1,56 @@ +--- a/net/minecraft/world/level/block/BlockPressurePlateBinary.java ++++ b/net/minecraft/world/level/block/BlockPressurePlateBinary.java +@@ -13,6 +13,11 @@ + import net.minecraft.world.level.block.state.properties.BlockSetType; + import net.minecraft.world.level.block.state.properties.BlockStateBoolean; + ++// CraftBukkit start ++import net.minecraft.world.entity.player.EntityHuman; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end ++ + public class BlockPressurePlateBinary extends BlockPressurePlateAbstract { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +@@ -44,7 +49,7 @@ + + @Override + protected int getSignalStrength(World world, BlockPosition blockposition) { +- Class oclass; ++ Class oclass; // CraftBukkit + + switch (this.type.pressurePlateSensitivity()) { + case EVERYTHING: +@@ -59,7 +64,31 @@ + + Class oclass1 = oclass; + +- return getEntityCount(world, BlockPressurePlateBinary.TOUCH_AABB.move(blockposition), oclass1) > 0 ? 15 : 0; ++ // CraftBukkit start - Call interact event when turning on a pressure plate ++ for (Entity entity : getEntities(world, BlockPressurePlateBinary.TOUCH_AABB.move(blockposition), oclass)) { ++ if (this.getSignalForState(world.getBlockState(blockposition)) == 0) { ++ org.bukkit.World bworld = world.getWorld(); ++ org.bukkit.plugin.PluginManager manager = world.getCraftServer().getPluginManager(); ++ org.bukkit.event.Cancellable cancellable; ++ ++ if (entity instanceof EntityHuman) { ++ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((EntityHuman) entity, org.bukkit.event.block.Action.PHYSICAL, blockposition, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), bworld.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ manager.callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ // We only want to block turning the plate on if all events are cancelled ++ if (cancellable.isCancelled()) { ++ continue; ++ } ++ } ++ ++ return 15; ++ } ++ ++ return 0; ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockPressurePlateWeighted.patch b/patch-remap/og/net/minecraft/world/level/block/BlockPressurePlateWeighted.patch new file mode 100644 index 0000000000..39a40e09dd --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockPressurePlateWeighted.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/world/level/block/BlockPressurePlateWeighted.java ++++ b/net/minecraft/world/level/block/BlockPressurePlateWeighted.java +@@ -14,6 +14,11 @@ + import net.minecraft.world.level.block.state.properties.BlockSetType; + import net.minecraft.world.level.block.state.properties.BlockStateInteger; + ++// CraftBukkit start ++import net.minecraft.world.entity.player.EntityHuman; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end ++ + public class BlockPressurePlateWeighted extends BlockPressurePlateAbstract { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +@@ -39,7 +44,27 @@ + + @Override + protected int getSignalStrength(World world, BlockPosition blockposition) { +- int i = Math.min(getEntityCount(world, BlockPressurePlateWeighted.TOUCH_AABB.move(blockposition), Entity.class), this.maxWeight); ++ // CraftBukkit start ++ // int i = Math.min(getEntityCount(world, BlockPressurePlateWeighted.TOUCH_AABB.move(blockposition), Entity.class), this.maxWeight); ++ int i = 0; ++ for (Entity entity : getEntities(world, BlockPressurePlateWeighted.TOUCH_AABB.move(blockposition), Entity.class)) { ++ org.bukkit.event.Cancellable cancellable; ++ ++ if (entity instanceof EntityHuman) { ++ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((EntityHuman) entity, org.bukkit.event.block.Action.PHYSICAL, blockposition, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ world.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ // We only want to block turning the plate on if all events are cancelled ++ if (!cancellable.isCancelled()) { ++ i++; ++ } ++ } ++ ++ i = Math.min(i, this.maxWeight); ++ // CraftBukkit end + + if (i > 0) { + float f = (float) Math.min(this.maxWeight, i) / (float) this.maxWeight; diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockPumpkinCarved.patch b/patch-remap/og/net/minecraft/world/level/block/BlockPumpkinCarved.patch new file mode 100644 index 0000000000..00de2418d7 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockPumpkinCarved.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/level/block/BlockPumpkinCarved.java ++++ b/net/minecraft/world/level/block/BlockPumpkinCarved.java +@@ -24,6 +24,10 @@ + import net.minecraft.world.level.block.state.predicate.BlockStatePredicate; + import net.minecraft.world.level.block.state.properties.BlockStateDirection; + ++// CraftBukkit start ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; ++// CraftBukkit end ++ + public class BlockPumpkinCarved extends BlockFacingHorizontal { + + public static final MapCodec CODEC = simpleCodec(BlockPumpkinCarved::new); +@@ -86,9 +90,14 @@ + } + + private static void spawnGolemInWorld(World world, ShapeDetector.ShapeDetectorCollection shapedetector_shapedetectorcollection, Entity entity, BlockPosition blockposition) { +- clearPatternBlocks(world, shapedetector_shapedetectorcollection); ++ // clearPatternBlocks(world, shapedetector_shapedetectorcollection); // CraftBukkit - moved down + entity.moveTo((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.05D, (double) blockposition.getZ() + 0.5D, 0.0F, 0.0F); +- world.addFreshEntity(entity); ++ // CraftBukkit start ++ if (!world.addFreshEntity(entity, SpawnReason.BUILD_IRONGOLEM)) { ++ return; ++ } ++ clearPatternBlocks(world, shapedetector_shapedetectorcollection); // CraftBukkit - from above ++ // CraftBukkit end + Iterator iterator = world.getEntitiesOfClass(EntityPlayer.class, entity.getBoundingBox().inflate(5.0D)).iterator(); + + while (iterator.hasNext()) { diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockRedstoneComparator.patch b/patch-remap/og/net/minecraft/world/level/block/BlockRedstoneComparator.patch new file mode 100644 index 0000000000..76133c1a1a --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockRedstoneComparator.patch @@ -0,0 +1,40 @@ +--- a/net/minecraft/world/level/block/BlockRedstoneComparator.java ++++ b/net/minecraft/world/level/block/BlockRedstoneComparator.java +@@ -28,6 +28,8 @@ + import net.minecraft.world.phys.MovingObjectPositionBlock; + import net.minecraft.world.ticks.TickListPriority; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public class BlockRedstoneComparator extends BlockDiodeAbstract implements ITileEntity { + + public static final MapCodec CODEC = simpleCodec(BlockRedstoneComparator::new); +@@ -110,7 +112,8 @@ + + @Nullable + private EntityItemFrame getItemFrame(World world, EnumDirection enumdirection, BlockPosition blockposition) { +- List list = world.getEntitiesOfClass(EntityItemFrame.class, new AxisAlignedBB((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), (double) (blockposition.getX() + 1), (double) (blockposition.getY() + 1), (double) (blockposition.getZ() + 1)), (entityitemframe) -> { ++ // CraftBukkit - decompile error ++ List list = world.getEntitiesOfClass(EntityItemFrame.class, new AxisAlignedBB((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), (double) (blockposition.getX() + 1), (double) (blockposition.getY() + 1), (double) (blockposition.getZ() + 1)), (java.util.function.Predicate) (entityitemframe) -> { + return entityitemframe != null && entityitemframe.getDirection() == enumdirection; + }); + +@@ -165,8 +168,18 @@ + boolean flag1 = (Boolean) iblockdata.getValue(BlockRedstoneComparator.POWERED); + + if (flag1 && !flag) { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(world, blockposition, 15, 0).getNewCurrent() != 0) { ++ return; ++ } ++ // CraftBukkit end + world.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockRedstoneComparator.POWERED, false), 2); + } else if (!flag1 && flag) { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(world, blockposition, 0, 15).getNewCurrent() != 15) { ++ return; ++ } ++ // CraftBukkit end + world.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockRedstoneComparator.POWERED, true), 2); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockRedstoneLamp.patch b/patch-remap/og/net/minecraft/world/level/block/BlockRedstoneLamp.patch new file mode 100644 index 0000000000..57cd0c7351 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockRedstoneLamp.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/level/block/BlockRedstoneLamp.java ++++ b/net/minecraft/world/level/block/BlockRedstoneLamp.java +@@ -12,6 +12,8 @@ + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockStateBoolean; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public class BlockRedstoneLamp extends Block { + + public static final MapCodec CODEC = simpleCodec(BlockRedstoneLamp::new); +@@ -42,6 +44,11 @@ + if (flag1) { + world.scheduleTick(blockposition, (Block) this, 4); + } else { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(world, blockposition, 0, 15).getNewCurrent() != 15) { ++ return; ++ } ++ // CraftBukkit end + world.setBlock(blockposition, (IBlockData) iblockdata.cycle(BlockRedstoneLamp.LIT), 2); + } + } +@@ -52,6 +59,11 @@ + @Override + public void tick(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, RandomSource randomsource) { + if ((Boolean) iblockdata.getValue(BlockRedstoneLamp.LIT) && !worldserver.hasNeighborSignal(blockposition)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callRedstoneChange(worldserver, blockposition, 15, 0).getNewCurrent() != 0) { ++ return; ++ } ++ // CraftBukkit end + worldserver.setBlock(blockposition, (IBlockData) iblockdata.cycle(BlockRedstoneLamp.LIT), 2); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockRedstoneOre.patch b/patch-remap/og/net/minecraft/world/level/block/BlockRedstoneOre.patch new file mode 100644 index 0000000000..2667a38da8 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockRedstoneOre.patch @@ -0,0 +1,103 @@ +--- a/net/minecraft/world/level/block/BlockRedstoneOre.java ++++ b/net/minecraft/world/level/block/BlockRedstoneOre.java +@@ -22,6 +22,11 @@ + import net.minecraft.world.level.block.state.properties.BlockStateBoolean; + import net.minecraft.world.phys.MovingObjectPositionBlock; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityInteractEvent; ++// CraftBukkit end ++ + public class BlockRedstoneOre extends Block { + + public static final MapCodec CODEC = simpleCodec(BlockRedstoneOre::new); +@@ -39,14 +44,27 @@ + + @Override + public void attack(IBlockData iblockdata, World world, BlockPosition blockposition, EntityHuman entityhuman) { +- interact(iblockdata, world, blockposition); ++ interact(iblockdata, world, blockposition, entityhuman); // CraftBukkit - add entityhuman + super.attack(iblockdata, world, blockposition, entityhuman); + } + + @Override + public void stepOn(World world, BlockPosition blockposition, IBlockData iblockdata, Entity entity) { + if (!entity.isSteppingCarefully()) { +- interact(iblockdata, world, blockposition); ++ // CraftBukkit start ++ if (entity instanceof EntityHuman) { ++ org.bukkit.event.player.PlayerInteractEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((EntityHuman) entity, org.bukkit.event.block.Action.PHYSICAL, blockposition, null, null, null); ++ if (!event.isCancelled()) { ++ interact(world.getBlockState(blockposition), world, blockposition, entity); // add entity ++ } ++ } else { ++ EntityInteractEvent event = new EntityInteractEvent(entity.getBukkitEntity(), world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ if (!event.isCancelled()) { ++ interact(world.getBlockState(blockposition), world, blockposition, entity); // add entity ++ } ++ } ++ // CraftBukkit end + } + + super.stepOn(world, blockposition, iblockdata, entity); +@@ -57,7 +75,7 @@ + if (world.isClientSide) { + spawnParticles(world, blockposition); + } else { +- interact(iblockdata, world, blockposition); ++ interact(iblockdata, world, blockposition, entityhuman); // CraftBukkit - add entityhuman + } + + ItemStack itemstack = entityhuman.getItemInHand(enumhand); +@@ -65,9 +83,14 @@ + return itemstack.getItem() instanceof ItemBlock && (new BlockActionContext(entityhuman, enumhand, itemstack, movingobjectpositionblock)).canPlace() ? EnumInteractionResult.PASS : EnumInteractionResult.SUCCESS; + } + +- private static void interact(IBlockData iblockdata, World world, BlockPosition blockposition) { ++ private static void interact(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { // CraftBukkit - add Entity + spawnParticles(world, blockposition); + if (!(Boolean) iblockdata.getValue(BlockRedstoneOre.LIT)) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, iblockdata.setValue(BlockRedstoneOre.LIT, true))) { ++ return; ++ } ++ // CraftBukkit end + world.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockRedstoneOre.LIT, true), 3); + } + +@@ -81,6 +104,11 @@ + @Override + public void randomTick(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, RandomSource randomsource) { + if ((Boolean) iblockdata.getValue(BlockRedstoneOre.LIT)) { ++ // CraftBukkit start ++ if (CraftEventFactory.callBlockFadeEvent(worldserver, blockposition, iblockdata.setValue(BlockRedstoneOre.LIT, false)).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockRedstoneOre.LIT, false), 3); + } + +@@ -89,12 +117,20 @@ + @Override + public void spawnAfterBreak(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, ItemStack itemstack, boolean flag) { + super.spawnAfterBreak(iblockdata, worldserver, blockposition, itemstack, flag); ++ // CraftBukkit start - Delegated to getExpDrop ++ } ++ ++ @Override ++ public int getExpDrop(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, ItemStack itemstack, boolean flag) { + if (flag && EnchantmentManager.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, itemstack) == 0) { + int i = 1 + worldserver.random.nextInt(5); + +- this.popExperience(worldserver, blockposition, i); ++ // this.popExperience(worldserver, blockposition, i); ++ return i; + } + ++ return 0; ++ // CraftBukkit end + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockRedstoneTorch.patch b/patch-remap/og/net/minecraft/world/level/block/BlockRedstoneTorch.patch new file mode 100644 index 0000000000..e6c3fb386a --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockRedstoneTorch.patch @@ -0,0 +1,52 @@ +--- a/net/minecraft/world/level/block/BlockRedstoneTorch.java ++++ b/net/minecraft/world/level/block/BlockRedstoneTorch.java +@@ -19,6 +19,8 @@ + import net.minecraft.world.level.block.state.properties.BlockProperties; + import net.minecraft.world.level.block.state.properties.BlockStateBoolean; + ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit ++ + public class BlockRedstoneTorch extends BaseTorchBlock { + + public static final MapCodec CODEC = simpleCodec(BlockRedstoneTorch::new); +@@ -85,8 +87,24 @@ + list.remove(0); + } + ++ // CraftBukkit start ++ org.bukkit.plugin.PluginManager manager = worldserver.getCraftServer().getPluginManager(); ++ org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ int oldCurrent = ((Boolean) iblockdata.getValue(BlockRedstoneTorch.LIT)).booleanValue() ? 15 : 0; ++ ++ BlockRedstoneEvent event = new BlockRedstoneEvent(block, oldCurrent, oldCurrent); ++ // CraftBukkit end + if ((Boolean) iblockdata.getValue(BlockRedstoneTorch.LIT)) { + if (flag) { ++ // CraftBukkit start ++ if (oldCurrent != 0) { ++ event.setNewCurrent(0); ++ manager.callEvent(event); ++ if (event.getNewCurrent() != 0) { ++ return; ++ } ++ } ++ // CraftBukkit end + worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockRedstoneTorch.LIT, false), 3); + if (isToggledTooFrequently(worldserver, blockposition, true)) { + worldserver.levelEvent(1502, blockposition, 0); +@@ -94,6 +112,15 @@ + } + } + } else if (!flag && !isToggledTooFrequently(worldserver, blockposition, false)) { ++ // CraftBukkit start ++ if (oldCurrent != 15) { ++ event.setNewCurrent(15); ++ manager.callEvent(event); ++ if (event.getNewCurrent() != 15) { ++ return; ++ } ++ } ++ // CraftBukkit end + worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockRedstoneTorch.LIT, true), 3); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockRedstoneWire.patch b/patch-remap/og/net/minecraft/world/level/block/BlockRedstoneWire.patch new file mode 100644 index 0000000000..99beb3beb8 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockRedstoneWire.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/world/level/block/BlockRedstoneWire.java ++++ b/net/minecraft/world/level/block/BlockRedstoneWire.java +@@ -37,6 +37,8 @@ + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + import net.minecraft.world.phys.shapes.VoxelShapes; + ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit ++ + public class BlockRedstoneWire extends Block { + + public static final MapCodec CODEC = simpleCodec(BlockRedstoneWire::new); +@@ -261,7 +263,16 @@ + private void updatePowerStrength(World world, BlockPosition blockposition, IBlockData iblockdata) { + int i = this.calculateTargetStrength(world, blockposition); + +- if ((Integer) iblockdata.getValue(BlockRedstoneWire.POWER) != i) { ++ // CraftBukkit start ++ int oldPower = (Integer) iblockdata.getValue(BlockRedstoneWire.POWER); ++ if (oldPower != i) { ++ BlockRedstoneEvent event = new BlockRedstoneEvent(world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), oldPower, i); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ i = event.getNewCurrent(); ++ } ++ if (oldPower != i) { ++ // CraftBukkit end + if (world.getBlockState(blockposition) == iblockdata) { + world.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockRedstoneWire.POWER, i), 2); + } diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockReed.patch b/patch-remap/og/net/minecraft/world/level/block/BlockReed.patch new file mode 100644 index 0000000000..332579a6d1 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockReed.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/level/block/BlockReed.java ++++ b/net/minecraft/world/level/block/BlockReed.java +@@ -63,7 +63,7 @@ + int j = (Integer) iblockdata.getValue(BlockReed.AGE); + + if (j == 15) { +- worldserver.setBlockAndUpdate(blockposition.above(), this.defaultBlockState()); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(worldserver, blockposition.above(), this.defaultBlockState()); // CraftBukkit + worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockReed.AGE, 0), 4); + } else { + worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockReed.AGE, j + 1), 4); diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockRespawnAnchor.patch b/patch-remap/og/net/minecraft/world/level/block/BlockRespawnAnchor.patch new file mode 100644 index 0000000000..90d1e0c3fa --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockRespawnAnchor.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/level/block/BlockRespawnAnchor.java ++++ b/net/minecraft/world/level/block/BlockRespawnAnchor.java +@@ -87,7 +87,7 @@ + EntityPlayer entityplayer = (EntityPlayer) entityhuman; + + if (entityplayer.getRespawnDimension() != world.dimension() || !blockposition.equals(entityplayer.getRespawnPosition())) { +- entityplayer.setRespawnPosition(world.dimension(), blockposition, 0.0F, false, true); ++ entityplayer.setRespawnPosition(world.dimension(), blockposition, 0.0F, false, true, org.bukkit.event.player.PlayerSpawnChangeEvent.Cause.RESPAWN_ANCHOR); // CraftBukkit + world.playSound((EntityHuman) null, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, SoundEffects.RESPAWN_ANCHOR_SET_SPAWN, SoundCategory.BLOCKS, 1.0F, 1.0F); + return EnumInteractionResult.SUCCESS; + } +@@ -127,7 +127,7 @@ + + private void explode(IBlockData iblockdata, World world, final BlockPosition blockposition) { + world.removeBlock(blockposition, false); +- Stream stream = EnumDirection.EnumDirectionLimit.HORIZONTAL.stream(); ++ Stream stream = EnumDirection.EnumDirectionLimit.HORIZONTAL.stream(); // CraftBukkit - decompile error + + Objects.requireNonNull(blockposition); + boolean flag = stream.map(blockposition::relative).anyMatch((blockposition1) -> { diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockSapling.patch b/patch-remap/og/net/minecraft/world/level/block/BlockSapling.patch new file mode 100644 index 0000000000..1814898e5b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockSapling.patch @@ -0,0 +1,59 @@ +--- a/net/minecraft/world/level/block/BlockSapling.java ++++ b/net/minecraft/world/level/block/BlockSapling.java +@@ -17,6 +17,14 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.TreeType; ++import org.bukkit.block.BlockState; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.world.StructureGrowEvent; ++// CraftBukkit end ++ + public class BlockSapling extends BlockPlant implements IBlockFragilePlantElement { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +@@ -28,6 +36,7 @@ + protected static final float AABB_OFFSET = 6.0F; + protected static final VoxelShape SHAPE = Block.box(2.0D, 0.0D, 2.0D, 14.0D, 12.0D, 14.0D); + protected final WorldGenTreeProvider treeGrower; ++ public static TreeType treeType; // CraftBukkit + + @Override + public MapCodec codec() { +@@ -57,7 +66,32 @@ + if ((Integer) iblockdata.getValue(BlockSapling.STAGE) == 0) { + worldserver.setBlock(blockposition, (IBlockData) iblockdata.cycle(BlockSapling.STAGE), 4); + } else { +- this.treeGrower.growTree(worldserver, worldserver.getChunkSource().getGenerator(), blockposition, iblockdata, randomsource); ++ // CraftBukkit start ++ if (worldserver.captureTreeGeneration) { ++ this.treeGrower.growTree(worldserver, worldserver.getChunkSource().getGenerator(), blockposition, iblockdata, randomsource); ++ } else { ++ worldserver.captureTreeGeneration = true; ++ this.treeGrower.growTree(worldserver, worldserver.getChunkSource().getGenerator(), blockposition, iblockdata, randomsource); ++ worldserver.captureTreeGeneration = false; ++ if (worldserver.capturedBlockStates.size() > 0) { ++ TreeType treeType = BlockSapling.treeType; ++ BlockSapling.treeType = null; ++ Location location = CraftLocation.toBukkit(blockposition, worldserver.getWorld()); ++ java.util.List blocks = new java.util.ArrayList<>(worldserver.capturedBlockStates.values()); ++ worldserver.capturedBlockStates.clear(); ++ StructureGrowEvent event = null; ++ if (treeType != null) { ++ event = new StructureGrowEvent(location, treeType, false, null, blocks); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ } ++ if (event == null || !event.isCancelled()) { ++ for (BlockState blockstate : blocks) { ++ blockstate.update(true); ++ } ++ } ++ } ++ } ++ // CraftBukkit end + } + + } diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockScaffolding.patch b/patch-remap/og/net/minecraft/world/level/block/BlockScaffolding.patch new file mode 100644 index 0000000000..d151507de8 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockScaffolding.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/level/block/BlockScaffolding.java ++++ b/net/minecraft/world/level/block/BlockScaffolding.java +@@ -103,7 +103,7 @@ + int i = getDistance(worldserver, blockposition); + IBlockData iblockdata1 = (IBlockData) ((IBlockData) iblockdata.setValue(BlockScaffolding.DISTANCE, i)).setValue(BlockScaffolding.BOTTOM, this.isBottom(worldserver, blockposition, i)); + +- if ((Integer) iblockdata1.getValue(BlockScaffolding.DISTANCE) == 7) { ++ if ((Integer) iblockdata1.getValue(BlockScaffolding.DISTANCE) == 7 && !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(worldserver, blockposition, Blocks.AIR.defaultBlockState()).isCancelled()) { // CraftBukkit - BlockFadeEvent + if ((Integer) iblockdata.getValue(BlockScaffolding.DISTANCE) == 7) { + EntityFallingBlock.fall(worldserver, blockposition, iblockdata1); + } else { diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockSign.patch b/patch-remap/og/net/minecraft/world/level/block/BlockSign.patch new file mode 100644 index 0000000000..3affa3a945 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockSign.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/level/block/BlockSign.java ++++ b/net/minecraft/world/level/block/BlockSign.java +@@ -118,7 +118,7 @@ + } else if (flag2) { + return EnumInteractionResult.SUCCESS; + } else if (!this.otherPlayerIsEditingSign(entityhuman, tileentitysign) && entityhuman.mayBuild() && this.hasEditableText(entityhuman, tileentitysign, flag1)) { +- this.openTextEdit(entityhuman, tileentitysign, flag1); ++ this.openTextEdit(entityhuman, tileentitysign, flag1, org.bukkit.event.player.PlayerSignOpenEvent.Cause.INTERACT); // CraftBukkit + return this.getInteractionResult(flag); + } else { + return EnumInteractionResult.PASS; +@@ -171,6 +171,15 @@ + } + + public void openTextEdit(EntityHuman entityhuman, TileEntitySign tileentitysign, boolean flag) { ++ // Craftbukkit start ++ openTextEdit(entityhuman, tileentitysign, flag, org.bukkit.event.player.PlayerSignOpenEvent.Cause.UNKNOWN); ++ } ++ ++ public void openTextEdit(EntityHuman entityhuman, TileEntitySign tileentitysign, boolean flag, org.bukkit.event.player.PlayerSignOpenEvent.Cause cause) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerSignOpenEvent(entityhuman, tileentitysign, flag, cause)) { ++ return; ++ } ++ // Craftbukkit end + tileentitysign.setAllowedPlayerEditor(entityhuman.getUUID()); + entityhuman.openTextEdit(tileentitysign, flag); + } +@@ -184,6 +193,6 @@ + @Nullable + @Override + public BlockEntityTicker getTicker(World world, IBlockData iblockdata, TileEntityTypes tileentitytypes) { +- return createTickerHelper(tileentitytypes, TileEntityTypes.SIGN, TileEntitySign::tick); ++ return null; // Craftbukkit - remove unnecessary sign ticking + } + } diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockSnow.patch b/patch-remap/og/net/minecraft/world/level/block/BlockSnow.patch new file mode 100644 index 0000000000..923cc20747 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockSnow.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/block/BlockSnow.java ++++ b/net/minecraft/world/level/block/BlockSnow.java +@@ -99,6 +99,11 @@ + @Override + public void randomTick(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, RandomSource randomsource) { + if (worldserver.getBrightness(EnumSkyBlock.BLOCK, blockposition) > 11) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(worldserver, blockposition, Blocks.AIR.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + dropResources(iblockdata, worldserver, blockposition); + worldserver.removeBlock(blockposition, false); + } diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockSoil.patch b/patch-remap/og/net/minecraft/world/level/block/BlockSoil.patch new file mode 100644 index 0000000000..e370f14b57 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockSoil.patch @@ -0,0 +1,67 @@ +--- a/net/minecraft/world/level/block/BlockSoil.java ++++ b/net/minecraft/world/level/block/BlockSoil.java +@@ -29,6 +29,11 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++// CraftBukkit start ++import org.bukkit.event.entity.EntityInteractEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class BlockSoil extends Block { + + public static final MapCodec CODEC = simpleCodec(BlockSoil::new); +@@ -91,26 +96,49 @@ + + if (!isNearWater(worldserver, blockposition) && !worldserver.isRainingAt(blockposition.above())) { + if (i > 0) { +- worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockSoil.MOISTURE, i - 1), 2); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleMoistureChangeEvent(worldserver, blockposition, (IBlockData) iblockdata.setValue(BlockSoil.MOISTURE, i - 1), 2); // CraftBukkit + } else if (!shouldMaintainFarmland(worldserver, blockposition)) { + turnToDirt((Entity) null, iblockdata, worldserver, blockposition); + } + } else if (i < 7) { +- worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockSoil.MOISTURE, 7), 2); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleMoistureChangeEvent(worldserver, blockposition, (IBlockData) iblockdata.setValue(BlockSoil.MOISTURE, 7), 2); // CraftBukkit + } + + } + + @Override + public void fallOn(World world, IBlockData iblockdata, BlockPosition blockposition, Entity entity, float f) { ++ super.fallOn(world, iblockdata, blockposition, entity, f); // CraftBukkit - moved here as game rules / events shouldn't affect fall damage. + if (!world.isClientSide && world.random.nextFloat() < f - 0.5F && entity instanceof EntityLiving && (entity instanceof EntityHuman || world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && entity.getBbWidth() * entity.getBbWidth() * entity.getBbHeight() > 0.512F) { ++ // CraftBukkit start - Interact soil ++ org.bukkit.event.Cancellable cancellable; ++ if (entity instanceof EntityHuman) { ++ cancellable = CraftEventFactory.callPlayerInteractEvent((EntityHuman) entity, org.bukkit.event.block.Action.PHYSICAL, blockposition, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ world.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ if (cancellable.isCancelled()) { ++ return; ++ } ++ ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, Blocks.DIRT.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end + turnToDirt(entity, iblockdata, world, blockposition); + } + +- super.fallOn(world, iblockdata, blockposition, entity, f); ++ // super.fallOn(world, iblockdata, blockposition, entity, f); // CraftBukkit - moved up + } + + public static void turnToDirt(@Nullable Entity entity, IBlockData iblockdata, World world, BlockPosition blockposition) { ++ // CraftBukkit start ++ if (CraftEventFactory.callBlockFadeEvent(world, blockposition, Blocks.DIRT.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + IBlockData iblockdata1 = pushEntitiesUp(iblockdata, Blocks.DIRT.defaultBlockState(), world, blockposition); + + world.setBlockAndUpdate(blockposition, iblockdata1); diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockSponge.patch b/patch-remap/og/net/minecraft/world/level/block/BlockSponge.patch new file mode 100644 index 0000000000..ae282d2920 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockSponge.patch @@ -0,0 +1,110 @@ +--- a/net/minecraft/world/level/block/BlockSponge.java ++++ b/net/minecraft/world/level/block/BlockSponge.java +@@ -13,6 +13,13 @@ + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.Fluid; + ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.util.BlockStateListPopulator; ++import org.bukkit.event.block.SpongeAbsorbEvent; ++// CraftBukkit end ++ + public class BlockSponge extends Block { + + public static final MapCodec CODEC = simpleCodec(BlockSponge::new); +@@ -51,7 +58,8 @@ + } + + private boolean removeWaterBreadthFirstSearch(World world, BlockPosition blockposition) { +- return BlockPosition.breadthFirstTraversal(blockposition, 6, 65, (blockposition1, consumer) -> { ++ BlockStateListPopulator blockList = new BlockStateListPopulator(world); // CraftBukkit - Use BlockStateListPopulator ++ BlockPosition.breadthFirstTraversal(blockposition, 6, 65, (blockposition1, consumer) -> { + EnumDirection[] aenumdirection = BlockSponge.ALL_DIRECTIONS; + int i = aenumdirection.length; + +@@ -65,8 +73,10 @@ + if (blockposition1.equals(blockposition)) { + return true; + } else { +- IBlockData iblockdata = world.getBlockState(blockposition1); +- Fluid fluid = world.getFluidState(blockposition1); ++ // CraftBukkit start ++ IBlockData iblockdata = blockList.getBlockState(blockposition1); ++ Fluid fluid = blockList.getFluidState(blockposition1); ++ // CraftBukkit end + + if (!fluid.is(TagsFluid.WATER)) { + return false; +@@ -76,27 +86,64 @@ + if (block instanceof IFluidSource) { + IFluidSource ifluidsource = (IFluidSource) block; + +- if (!ifluidsource.pickupBlock((EntityHuman) null, world, blockposition1, iblockdata).isEmpty()) { ++ if (!ifluidsource.pickupBlock((EntityHuman) null, blockList, blockposition1, iblockdata).isEmpty()) { // CraftBukkit + return true; + } + } + + if (iblockdata.getBlock() instanceof BlockFluids) { +- world.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3); ++ blockList.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3); // CraftBukkit + } else { + if (!iblockdata.is(Blocks.KELP) && !iblockdata.is(Blocks.KELP_PLANT) && !iblockdata.is(Blocks.SEAGRASS) && !iblockdata.is(Blocks.TALL_SEAGRASS)) { + return false; + } + +- TileEntity tileentity = iblockdata.hasBlockEntity() ? world.getBlockEntity(blockposition1) : null; ++ // CraftBukkit start ++ // TileEntity tileentity = iblockdata.hasBlockEntity() ? world.getBlockEntity(blockposition1) : null; + +- dropResources(iblockdata, world, blockposition1, tileentity); +- world.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3); ++ // dropResources(iblockdata, world, blockposition1, tileentity); ++ blockList.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3); ++ // CraftBukkit end + } + + return true; + } + } +- }) > 1; ++ }); ++ // CraftBukkit start ++ List blocks = blockList.getList(); // Is a clone ++ if (!blocks.isEmpty()) { ++ final org.bukkit.block.Block bblock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ ++ SpongeAbsorbEvent event = new SpongeAbsorbEvent(bblock, (List) (List) blocks); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ for (CraftBlockState block : blocks) { ++ BlockPosition blockposition1 = block.getPosition(); ++ IBlockData iblockdata = world.getBlockState(blockposition1); ++ Fluid fluid = world.getFluidState(blockposition1); ++ ++ if (fluid.is(TagsFluid.WATER)) { ++ if (iblockdata.getBlock() instanceof IFluidSource && !((IFluidSource) iblockdata.getBlock()).pickupBlock((EntityHuman) null, blockList, blockposition1, iblockdata).isEmpty()) { ++ // NOP ++ } else if (iblockdata.getBlock() instanceof BlockFluids) { ++ // NOP ++ } else if (iblockdata.is(Blocks.KELP) || iblockdata.is(Blocks.KELP_PLANT) || iblockdata.is(Blocks.SEAGRASS) || iblockdata.is(Blocks.TALL_SEAGRASS)) { ++ TileEntity tileentity = iblockdata.hasBlockEntity() ? world.getBlockEntity(blockposition1) : null; ++ ++ dropResources(iblockdata, world, blockposition1, tileentity); ++ } ++ } ++ world.setBlock(blockposition1, block.getHandle(), block.getFlag()); ++ } ++ ++ return true; ++ } ++ return false; ++ // CraftBukkit end + } + } diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockStem.patch b/patch-remap/og/net/minecraft/world/level/block/BlockStem.patch new file mode 100644 index 0000000000..d1f2af0417 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockStem.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/world/level/block/BlockStem.java ++++ b/net/minecraft/world/level/block/BlockStem.java +@@ -27,6 +27,8 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public class BlockStem extends BlockPlant implements IBlockFragilePlantElement { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +@@ -79,7 +81,7 @@ + + if (i < 7) { + iblockdata = (IBlockData) iblockdata.setValue(BlockStem.AGE, i + 1); +- worldserver.setBlock(blockposition, iblockdata, 2); ++ CraftEventFactory.handleBlockGrowEvent(worldserver, blockposition, iblockdata, 2); // CraftBukkit + } else { + EnumDirection enumdirection = EnumDirection.EnumDirectionLimit.HORIZONTAL.getRandomDirection(randomsource); + BlockPosition blockposition1 = blockposition.relative(enumdirection); +@@ -91,7 +93,11 @@ + Optional optional1 = iregistry.getOptional(this.attachedStem); + + if (optional.isPresent() && optional1.isPresent()) { +- worldserver.setBlockAndUpdate(blockposition1, ((Block) optional.get()).defaultBlockState()); ++ // CraftBukkit start ++ if (!CraftEventFactory.handleBlockGrowEvent(worldserver, blockposition1, ((Block) optional.get()).defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end + worldserver.setBlockAndUpdate(blockposition, (IBlockData) ((Block) optional1.get()).defaultBlockState().setValue(BlockFacingHorizontal.FACING, enumdirection)); + } + } +@@ -121,7 +127,7 @@ + int i = Math.min(7, (Integer) iblockdata.getValue(BlockStem.AGE) + MathHelper.nextInt(worldserver.random, 2, 5)); + IBlockData iblockdata1 = (IBlockData) iblockdata.setValue(BlockStem.AGE, i); + +- worldserver.setBlock(blockposition, iblockdata1, 2); ++ CraftEventFactory.handleBlockGrowEvent(worldserver, blockposition, iblockdata1, 2); // CraftBukkit + if (i == 7) { + iblockdata1.randomTick(worldserver, blockposition, worldserver.random); + } diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockSweetBerryBush.patch b/patch-remap/og/net/minecraft/world/level/block/BlockSweetBerryBush.patch new file mode 100644 index 0000000000..803ce226a9 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockSweetBerryBush.patch @@ -0,0 +1,53 @@ +--- a/net/minecraft/world/level/block/BlockSweetBerryBush.java ++++ b/net/minecraft/world/level/block/BlockSweetBerryBush.java +@@ -28,6 +28,14 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++// CraftBukkit start ++import java.util.Collections; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerHarvestBlockEvent; ++// CraftBukkit end ++ + public class BlockSweetBerryBush extends BlockPlant implements IBlockFragilePlantElement { + + public static final MapCodec CODEC = simpleCodec(BlockSweetBerryBush::new); +@@ -69,7 +77,7 @@ + if (i < 3 && randomsource.nextInt(5) == 0 && worldserver.getRawBrightness(blockposition.above(), 0) >= 9) { + IBlockData iblockdata1 = (IBlockData) iblockdata.setValue(BlockSweetBerryBush.AGE, i + 1); + +- worldserver.setBlock(blockposition, iblockdata1, 2); ++ if (!CraftEventFactory.handleBlockGrowEvent(worldserver, blockposition, iblockdata1, 2)) return; // CraftBukkit + worldserver.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.a.of(iblockdata1)); + } + +@@ -84,7 +92,9 @@ + double d1 = Math.abs(entity.getZ() - entity.zOld); + + if (d0 >= 0.003000000026077032D || d1 >= 0.003000000026077032D) { ++ CraftEventFactory.blockDamage = CraftBlock.at(world, blockposition); // CraftBukkit + entity.hurt(world.damageSources().sweetBerryBush(), 1.0F); ++ CraftEventFactory.blockDamage = null; // CraftBukkit + } + } + +@@ -101,7 +111,15 @@ + } else if (i > 1) { + int j = 1 + world.random.nextInt(2); + +- popResource(world, blockposition, new ItemStack(Items.SWEET_BERRIES, j + (flag ? 1 : 0))); ++ // CraftBukkit start ++ PlayerHarvestBlockEvent event = CraftEventFactory.callPlayerHarvestBlockEvent(world, blockposition, entityhuman, enumhand, Collections.singletonList(new ItemStack(Items.SWEET_BERRIES, j + (flag ? 1 : 0)))); ++ if (event.isCancelled()) { ++ return EnumInteractionResult.SUCCESS; // We need to return a success either way, because making it PASS or FAIL will result in a bug where cancelling while harvesting w/ block in hand places block ++ } ++ for (org.bukkit.inventory.ItemStack itemStack : event.getItemsHarvested()) { ++ popResource(world, blockposition, CraftItemStack.asNMSCopy(itemStack)); ++ } ++ // CraftBukkit end + world.playSound((EntityHuman) null, blockposition, SoundEffects.SWEET_BERRY_BUSH_PICK_BERRIES, SoundCategory.BLOCKS, 1.0F, 0.8F + world.random.nextFloat() * 0.4F); + IBlockData iblockdata1 = (IBlockData) iblockdata.setValue(BlockSweetBerryBush.AGE, 1); + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockTNT.patch b/patch-remap/og/net/minecraft/world/level/block/BlockTNT.patch new file mode 100644 index 0000000000..9d73f902c8 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockTNT.patch @@ -0,0 +1,65 @@ +--- a/net/minecraft/world/level/block/BlockTNT.java ++++ b/net/minecraft/world/level/block/BlockTNT.java +@@ -26,6 +26,11 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.MovingObjectPositionBlock; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.block.TNTPrimeEvent.PrimeCause; ++// CraftBukkit end ++ + public class BlockTNT extends Block { + + public static final MapCodec CODEC = simpleCodec(BlockTNT::new); +@@ -44,7 +49,7 @@ + @Override + public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { + if (!iblockdata1.is(iblockdata.getBlock())) { +- if (world.hasNeighborSignal(blockposition)) { ++ if (world.hasNeighborSignal(blockposition) && CraftEventFactory.callTNTPrimeEvent(world, blockposition, PrimeCause.REDSTONE, null, null)) { // CraftBukkit - TNTPrimeEvent + explode(world, blockposition); + world.removeBlock(blockposition, false); + } +@@ -54,7 +59,7 @@ + + @Override + public void neighborChanged(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1, boolean flag) { +- if (world.hasNeighborSignal(blockposition)) { ++ if (world.hasNeighborSignal(blockposition) && CraftEventFactory.callTNTPrimeEvent(world, blockposition, PrimeCause.REDSTONE, null, blockposition1)) { // CraftBukkit - TNTPrimeEvent + explode(world, blockposition); + world.removeBlock(blockposition, false); + } +@@ -63,7 +68,7 @@ + + @Override + public IBlockData playerWillDestroy(World world, BlockPosition blockposition, IBlockData iblockdata, EntityHuman entityhuman) { +- if (!world.isClientSide() && !entityhuman.isCreative() && (Boolean) iblockdata.getValue(BlockTNT.UNSTABLE)) { ++ if (!world.isClientSide() && !entityhuman.isCreative() && (Boolean) iblockdata.getValue(BlockTNT.UNSTABLE) && CraftEventFactory.callTNTPrimeEvent(world, blockposition, PrimeCause.BLOCK_BREAK, entityhuman, null)) { // CraftBukkit - TNTPrimeEvent + explode(world, blockposition); + } + +@@ -102,6 +107,11 @@ + if (!itemstack.is(Items.FLINT_AND_STEEL) && !itemstack.is(Items.FIRE_CHARGE)) { + return super.use(iblockdata, world, blockposition, entityhuman, enumhand, movingobjectpositionblock); + } else { ++ // CraftBukkit start - TNTPrimeEvent ++ if (!CraftEventFactory.callTNTPrimeEvent(world, blockposition, PrimeCause.PLAYER, entityhuman, null)) { ++ return EnumInteractionResult.CONSUME; ++ } ++ // CraftBukkit end + explode(world, blockposition, entityhuman); + world.setBlock(blockposition, Blocks.AIR.defaultBlockState(), 11); + Item item = itemstack.getItem(); +@@ -128,6 +138,11 @@ + Entity entity = iprojectile.getOwner(); + + if (iprojectile.isOnFire() && iprojectile.mayInteract(world, blockposition)) { ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(iprojectile, blockposition, Blocks.AIR.defaultBlockState()) || !CraftEventFactory.callTNTPrimeEvent(world, blockposition, PrimeCause.PROJECTILE, iprojectile, null)) { ++ return; ++ } ++ // CraftBukkit end + explode(world, blockposition, entity instanceof EntityLiving ? (EntityLiving) entity : null); + world.removeBlock(blockposition, false); + } diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockTallPlant.patch b/patch-remap/og/net/minecraft/world/level/block/BlockTallPlant.patch new file mode 100644 index 0000000000..975c30491b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockTallPlant.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/block/BlockTallPlant.java ++++ b/net/minecraft/world/level/block/BlockTallPlant.java +@@ -101,6 +101,11 @@ + } + + protected static void preventDropFromBottomPart(World world, BlockPosition blockposition, IBlockData iblockdata, EntityHuman entityhuman) { ++ // CraftBukkit start ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, blockposition).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + BlockPropertyDoubleBlockHalf blockpropertydoubleblockhalf = (BlockPropertyDoubleBlockHalf) iblockdata.getValue(BlockTallPlant.HALF); + + if (blockpropertydoubleblockhalf == BlockPropertyDoubleBlockHalf.UPPER) { diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockTrapdoor.patch b/patch-remap/og/net/minecraft/world/level/block/BlockTrapdoor.patch new file mode 100644 index 0000000000..fb5c64d9e6 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockTrapdoor.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/level/block/BlockTrapdoor.java ++++ b/net/minecraft/world/level/block/BlockTrapdoor.java +@@ -34,6 +34,8 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit ++ + public class BlockTrapdoor extends BlockFacingHorizontal implements IBlockWaterlogged { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +@@ -139,6 +141,19 @@ + boolean flag1 = world.hasNeighborSignal(blockposition); + + if (flag1 != (Boolean) iblockdata.getValue(BlockTrapdoor.POWERED)) { ++ // CraftBukkit start ++ org.bukkit.World bworld = world.getWorld(); ++ org.bukkit.block.Block bblock = bworld.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ ++ int power = bblock.getBlockPower(); ++ int oldPower = (Boolean) iblockdata.getValue(OPEN) ? 15 : 0; ++ ++ if (oldPower == 0 ^ power == 0 || block.defaultBlockState().isSignalSource()) { ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bblock, oldPower, power); ++ world.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ flag1 = eventRedstone.getNewCurrent() > 0; ++ } ++ // CraftBukkit end + if ((Boolean) iblockdata.getValue(BlockTrapdoor.OPEN) != flag1) { + iblockdata = (IBlockData) iblockdata.setValue(BlockTrapdoor.OPEN, flag1); + this.playSound((EntityHuman) null, world, blockposition, flag1); diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockTripwire.patch b/patch-remap/og/net/minecraft/world/level/block/BlockTripwire.patch new file mode 100644 index 0000000000..168a220143 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockTripwire.patch @@ -0,0 +1,52 @@ +--- a/net/minecraft/world/level/block/BlockTripwire.java ++++ b/net/minecraft/world/level/block/BlockTripwire.java +@@ -27,6 +27,8 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++import org.bukkit.event.entity.EntityInteractEvent; // CraftBukkit ++ + public class BlockTripwire extends Block { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +@@ -166,6 +168,40 @@ + } + } + ++ // CraftBukkit start - Call interact even when triggering connected tripwire ++ if (flag != flag1 && flag1 && (Boolean)iblockdata.getValue(ATTACHED)) { ++ org.bukkit.World bworld = world.getWorld(); ++ org.bukkit.plugin.PluginManager manager = world.getCraftServer().getPluginManager(); ++ org.bukkit.block.Block block = bworld.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ boolean allowed = false; ++ ++ // If all of the events are cancelled block the tripwire trigger, else allow ++ for (Object object : list) { ++ if (object != null) { ++ org.bukkit.event.Cancellable cancellable; ++ ++ if (object instanceof EntityHuman) { ++ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((EntityHuman) object, org.bukkit.event.block.Action.PHYSICAL, blockposition, null, null, null); ++ } else if (object instanceof Entity) { ++ cancellable = new EntityInteractEvent(((Entity) object).getBukkitEntity(), block); ++ manager.callEvent((EntityInteractEvent) cancellable); ++ } else { ++ continue; ++ } ++ ++ if (!cancellable.isCancelled()) { ++ allowed = true; ++ break; ++ } ++ } ++ } ++ ++ if (!allowed) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ + if (flag1 != flag) { + iblockdata = (IBlockData) iblockdata.setValue(BlockTripwire.POWERED, flag1); + world.setBlock(blockposition, iblockdata, 3); diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockTripwireHook.patch b/patch-remap/og/net/minecraft/world/level/block/BlockTripwireHook.patch new file mode 100644 index 0000000000..b1ffb21273 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockTripwireHook.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/level/block/BlockTripwireHook.java ++++ b/net/minecraft/world/level/block/BlockTripwireHook.java +@@ -29,6 +29,11 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockRedstoneEvent; ++// CraftBukkit end ++ + public class BlockTripwireHook extends Block { + + public static final MapCodec CODEC = simpleCodec(BlockTripwireHook::new); +@@ -173,6 +178,15 @@ + emitState(world, blockposition1, flag4, flag5, flag2, flag3); + } + ++ // CraftBukkit start ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(world, blockposition), 15, 0); ++ world.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if (eventRedstone.getNewCurrent() > 0) { ++ return; ++ } ++ // CraftBukkit end ++ + emitState(world, blockposition, flag4, flag5, flag2, flag3); + if (!flag) { + world.setBlock(blockposition, (IBlockData) iblockdata3.setValue(BlockTripwireHook.FACING, enumdirection), 3); diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockTurtleEgg.patch b/patch-remap/og/net/minecraft/world/level/block/BlockTurtleEgg.patch new file mode 100644 index 0000000000..04cbc51718 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockTurtleEgg.patch @@ -0,0 +1,66 @@ +--- a/net/minecraft/world/level/block/BlockTurtleEgg.java ++++ b/net/minecraft/world/level/block/BlockTurtleEgg.java +@@ -30,6 +30,12 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++// CraftBukkit start ++import org.bukkit.event.entity.EntityInteractEvent; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class BlockTurtleEgg extends Block { + + public static final MapCodec CODEC = simpleCodec(BlockTurtleEgg::new); +@@ -72,6 +78,19 @@ + private void destroyEgg(World world, IBlockData iblockdata, BlockPosition blockposition, Entity entity, int i) { + if (this.canDestroyEgg(world, entity)) { + if (!world.isClientSide && world.random.nextInt(i) == 0 && iblockdata.is(Blocks.TURTLE_EGG)) { ++ // CraftBukkit start - Step on eggs ++ org.bukkit.event.Cancellable cancellable; ++ if (entity instanceof EntityHuman) { ++ cancellable = CraftEventFactory.callPlayerInteractEvent((EntityHuman) entity, org.bukkit.event.block.Action.PHYSICAL, blockposition, null, null, null); ++ } else { ++ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), CraftBlock.at(world, blockposition)); ++ world.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable); ++ } ++ ++ if (cancellable.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.decreaseEggs(world, blockposition, iblockdata); + } + +@@ -98,10 +117,20 @@ + int i = (Integer) iblockdata.getValue(BlockTurtleEgg.HATCH); + + if (i < 2) { ++ // CraftBukkit start - Call BlockGrowEvent ++ if (!CraftEventFactory.handleBlockGrowEvent(worldserver, blockposition, iblockdata.setValue(BlockTurtleEgg.HATCH, i + 1), 2)) { ++ return; ++ } ++ // CraftBukkit end + worldserver.playSound((EntityHuman) null, blockposition, SoundEffects.TURTLE_EGG_CRACK, SoundCategory.BLOCKS, 0.7F, 0.9F + randomsource.nextFloat() * 0.2F); +- worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockTurtleEgg.HATCH, i + 1), 2); ++ // worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockTurtleEgg.HATCH, i + 1), 2); // CraftBukkit - handled above + worldserver.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.a.of(iblockdata)); + } else { ++ // CraftBukkit start - Call BlockFadeEvent ++ if (CraftEventFactory.callBlockFadeEvent(worldserver, blockposition, Blocks.AIR.defaultBlockState()).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + worldserver.playSound((EntityHuman) null, blockposition, SoundEffects.TURTLE_EGG_HATCH, SoundCategory.BLOCKS, 0.7F, 0.9F + randomsource.nextFloat() * 0.2F); + worldserver.removeBlock(blockposition, false); + worldserver.gameEvent(GameEvent.BLOCK_DESTROY, blockposition, GameEvent.a.of(iblockdata)); +@@ -114,7 +143,7 @@ + entityturtle.setAge(-24000); + entityturtle.setHomePos(blockposition); + entityturtle.moveTo((double) blockposition.getX() + 0.3D + (double) j * 0.2D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.3D, 0.0F, 0.0F); +- worldserver.addFreshEntity(entityturtle); ++ worldserver.addFreshEntity(entityturtle, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); // CraftBukkit + } + } + } diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockVine.patch b/patch-remap/og/net/minecraft/world/level/block/BlockVine.patch new file mode 100644 index 0000000000..907a641fa3 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockVine.patch @@ -0,0 +1,71 @@ +--- a/net/minecraft/world/level/block/BlockVine.java ++++ b/net/minecraft/world/level/block/BlockVine.java +@@ -25,6 +25,8 @@ + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + import net.minecraft.world.phys.shapes.VoxelShapes; + ++import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit ++ + public class BlockVine extends Block { + + public static final MapCodec CODEC = simpleCodec(BlockVine::new); +@@ -203,30 +205,34 @@ + BlockPosition blockposition3 = blockposition2.relative(enumdirection1); + BlockPosition blockposition4 = blockposition2.relative(enumdirection2); + ++ // CraftBukkit start - Call BlockSpreadEvent ++ BlockPosition source = blockposition; ++ + if (flag && isAcceptableNeighbour(worldserver, blockposition3, enumdirection1)) { +- worldserver.setBlock(blockposition2, (IBlockData) this.defaultBlockState().setValue(getPropertyForFace(enumdirection1), true), 2); ++ CraftEventFactory.handleBlockSpreadEvent(worldserver, source, blockposition2, (IBlockData) this.defaultBlockState().setValue(getPropertyForFace(enumdirection1), true), 2); + } else if (flag1 && isAcceptableNeighbour(worldserver, blockposition4, enumdirection2)) { +- worldserver.setBlock(blockposition2, (IBlockData) this.defaultBlockState().setValue(getPropertyForFace(enumdirection2), true), 2); ++ CraftEventFactory.handleBlockSpreadEvent(worldserver, source, blockposition2, (IBlockData) this.defaultBlockState().setValue(getPropertyForFace(enumdirection2), true), 2); + } else { + EnumDirection enumdirection3 = enumdirection.getOpposite(); + + if (flag && worldserver.isEmptyBlock(blockposition3) && isAcceptableNeighbour(worldserver, blockposition.relative(enumdirection1), enumdirection3)) { +- worldserver.setBlock(blockposition3, (IBlockData) this.defaultBlockState().setValue(getPropertyForFace(enumdirection3), true), 2); ++ CraftEventFactory.handleBlockSpreadEvent(worldserver, source, blockposition3, (IBlockData) this.defaultBlockState().setValue(getPropertyForFace(enumdirection3), true), 2); + } else if (flag1 && worldserver.isEmptyBlock(blockposition4) && isAcceptableNeighbour(worldserver, blockposition.relative(enumdirection2), enumdirection3)) { +- worldserver.setBlock(blockposition4, (IBlockData) this.defaultBlockState().setValue(getPropertyForFace(enumdirection3), true), 2); ++ CraftEventFactory.handleBlockSpreadEvent(worldserver, source, blockposition4, (IBlockData) this.defaultBlockState().setValue(getPropertyForFace(enumdirection3), true), 2); + } else if ((double) randomsource.nextFloat() < 0.05D && isAcceptableNeighbour(worldserver, blockposition2.above(), EnumDirection.UP)) { +- worldserver.setBlock(blockposition2, (IBlockData) this.defaultBlockState().setValue(BlockVine.UP, true), 2); ++ CraftEventFactory.handleBlockSpreadEvent(worldserver, source, blockposition2, (IBlockData) this.defaultBlockState().setValue(BlockVine.UP, true), 2); + } ++ // CraftBukkit end + } + } else if (isAcceptableNeighbour(worldserver, blockposition2, enumdirection)) { +- worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(getPropertyForFace(enumdirection), true), 2); ++ CraftEventFactory.handleBlockGrowEvent(worldserver, blockposition, (IBlockData) iblockdata.setValue(getPropertyForFace(enumdirection), true), 2); // CraftBukkit + } + + } + } else { + if (enumdirection == EnumDirection.UP && blockposition.getY() < worldserver.getMaxBuildHeight() - 1) { + if (this.canSupportAtFace(worldserver, blockposition, enumdirection)) { +- worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockVine.UP, true), 2); ++ CraftEventFactory.handleBlockGrowEvent(worldserver, blockposition, (IBlockData) iblockdata.setValue(BlockVine.UP, true), 2); // CraftBukkit + return; + } + +@@ -246,7 +252,7 @@ + } + + if (this.hasHorizontalConnection(iblockdata2)) { +- worldserver.setBlock(blockposition1, iblockdata2, 2); ++ CraftEventFactory.handleBlockSpreadEvent(worldserver, blockposition, blockposition1, iblockdata2, 2); // CraftBukkit + } + + return; +@@ -261,7 +267,7 @@ + IBlockData iblockdata4 = this.copyRandomFaces(iblockdata, iblockdata3, randomsource); + + if (iblockdata3 != iblockdata4 && this.hasHorizontalConnection(iblockdata4)) { +- worldserver.setBlock(blockposition2, iblockdata4, 2); ++ CraftEventFactory.handleBlockSpreadEvent(worldserver, blockposition, blockposition2, iblockdata4, 2); // CraftBukkit + } + } + } diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockWaterLily.patch b/patch-remap/og/net/minecraft/world/level/block/BlockWaterLily.patch new file mode 100644 index 0000000000..d453a0b8d6 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockWaterLily.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/world/level/block/BlockWaterLily.java ++++ b/net/minecraft/world/level/block/BlockWaterLily.java +@@ -14,6 +14,10 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class BlockWaterLily extends BlockPlant { + + public static final MapCodec CODEC = simpleCodec(BlockWaterLily::new); +@@ -32,6 +36,11 @@ + public void entityInside(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { + super.entityInside(iblockdata, world, blockposition, entity); + if (world instanceof WorldServer && entity instanceof EntityBoat) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, Blocks.AIR.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end + world.destroyBlock(new BlockPosition(blockposition), true, entity); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockWitherRose.patch b/patch-remap/og/net/minecraft/world/level/block/BlockWitherRose.patch new file mode 100644 index 0000000000..ac6dbdd5b3 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockWitherRose.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/level/block/BlockWitherRose.java ++++ b/net/minecraft/world/level/block/BlockWitherRose.java +@@ -66,7 +66,7 @@ + EntityLiving entityliving = (EntityLiving) entity; + + if (!entityliving.isInvulnerableTo(world.damageSources().wither())) { +- entityliving.addEffect(new MobEffect(MobEffects.WITHER, 40)); ++ entityliving.addEffect(new MobEffect(MobEffects.WITHER, 40), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.WITHER_ROSE); // CraftBukkit + } + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BlockWitherSkull.patch b/patch-remap/og/net/minecraft/world/level/block/BlockWitherSkull.patch new file mode 100644 index 0000000000..40c507d61c --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BlockWitherSkull.patch @@ -0,0 +1,50 @@ +--- a/net/minecraft/world/level/block/BlockWitherSkull.java ++++ b/net/minecraft/world/level/block/BlockWitherSkull.java +@@ -25,6 +25,10 @@ + import net.minecraft.world.level.block.state.pattern.ShapeDetectorBuilder; + import net.minecraft.world.level.block.state.predicate.BlockStatePredicate; + ++// CraftBukkit start ++import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; ++// CraftBukkit end ++ + public class BlockWitherSkull extends BlockSkull { + + public static final MapCodec CODEC = simpleCodec(BlockWitherSkull::new); +@@ -54,6 +58,7 @@ + } + + public static void checkSpawn(World world, BlockPosition blockposition, TileEntitySkull tileentityskull) { ++ if (world.captureBlockStates) return; // CraftBukkit + if (!world.isClientSide) { + IBlockData iblockdata = tileentityskull.getBlockState(); + boolean flag = iblockdata.is(Blocks.WITHER_SKELETON_SKULL) || iblockdata.is(Blocks.WITHER_SKELETON_WALL_SKULL); +@@ -65,12 +70,18 @@ + EntityWither entitywither = (EntityWither) EntityTypes.WITHER.create(world); + + if (entitywither != null) { +- BlockPumpkinCarved.clearPatternBlocks(world, shapedetector_shapedetectorcollection); ++ // BlockPumpkinCarved.clearPatternBlocks(world, shapedetector_shapedetectorcollection); // CraftBukkit - move down + BlockPosition blockposition1 = shapedetector_shapedetectorcollection.getBlock(1, 2, 0).getPos(); + + entitywither.moveTo((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.55D, (double) blockposition1.getZ() + 0.5D, shapedetector_shapedetectorcollection.getForwards().getAxis() == EnumDirection.EnumAxis.X ? 0.0F : 90.0F, 0.0F); + entitywither.yBodyRot = shapedetector_shapedetectorcollection.getForwards().getAxis() == EnumDirection.EnumAxis.X ? 0.0F : 90.0F; + entitywither.makeInvulnerable(); ++ // CraftBukkit start ++ if (!world.addFreshEntity(entitywither, SpawnReason.BUILD_WITHER)) { ++ return; ++ } ++ BlockPumpkinCarved.clearPatternBlocks(world, shapedetector_shapedetectorcollection); // CraftBukkit - from above ++ // CraftBukkit end + Iterator iterator = world.getEntitiesOfClass(EntityPlayer.class, entitywither.getBoundingBox().inflate(50.0D)).iterator(); + + while (iterator.hasNext()) { +@@ -79,7 +90,7 @@ + CriterionTriggers.SUMMONED_ENTITY.trigger(entityplayer, (Entity) entitywither); + } + +- world.addFreshEntity(entitywither); ++ // world.addFreshEntity(entitywither); // CraftBukkit - moved up + BlockPumpkinCarved.updatePatternBlocks(world, shapedetector_shapedetectorcollection); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/BuddingAmethystBlock.patch b/patch-remap/og/net/minecraft/world/level/block/BuddingAmethystBlock.patch new file mode 100644 index 0000000000..9188275263 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/BuddingAmethystBlock.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/level/block/BuddingAmethystBlock.java ++++ b/net/minecraft/world/level/block/BuddingAmethystBlock.java +@@ -45,7 +45,7 @@ + if (block != null) { + IBlockData iblockdata2 = (IBlockData) ((IBlockData) block.defaultBlockState().setValue(AmethystClusterBlock.FACING, enumdirection)).setValue(AmethystClusterBlock.WATERLOGGED, iblockdata1.getFluidState().getType() == FluidTypes.WATER); + +- worldserver.setBlockAndUpdate(blockposition1, iblockdata2); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(worldserver, blockposition, blockposition1, iblockdata2); // CraftBukkit + } + + } diff --git a/patch-remap/og/net/minecraft/world/level/block/CaveVines.patch b/patch-remap/og/net/minecraft/world/level/block/CaveVines.patch new file mode 100644 index 0000000000..aab8189b74 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/CaveVines.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/world/level/block/CaveVines.java ++++ b/net/minecraft/world/level/block/CaveVines.java +@@ -18,6 +18,13 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.shapes.VoxelShape; + ++// CraftBukkit start ++import java.util.Collections; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.player.PlayerHarvestBlockEvent; ++// CraftBukkit end ++ + public interface CaveVines { + + VoxelShape SHAPE = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 16.0D, 15.0D); +@@ -25,7 +32,24 @@ + + static EnumInteractionResult use(@Nullable Entity entity, IBlockData iblockdata, World world, BlockPosition blockposition) { + if ((Boolean) iblockdata.getValue(CaveVines.BERRIES)) { +- Block.popResource(world, blockposition, new ItemStack(Items.GLOW_BERRIES, 1)); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, (IBlockData) iblockdata.setValue(CaveVines.BERRIES, false))) { ++ return EnumInteractionResult.SUCCESS; ++ } ++ ++ if (entity instanceof EntityHuman) { ++ PlayerHarvestBlockEvent event = CraftEventFactory.callPlayerHarvestBlockEvent(world, blockposition, (EntityHuman) entity, net.minecraft.world.EnumHand.MAIN_HAND, Collections.singletonList(new ItemStack(Items.GLOW_BERRIES, 1))); ++ if (event.isCancelled()) { ++ return EnumInteractionResult.SUCCESS; // We need to return a success either way, because making it PASS or FAIL will result in a bug where cancelling while harvesting w/ block in hand places block ++ } ++ for (org.bukkit.inventory.ItemStack itemStack : event.getItemsHarvested()) { ++ Block.popResource(world, blockposition, CraftItemStack.asNMSCopy(itemStack)); ++ } ++ } else { ++ Block.popResource(world, blockposition, new ItemStack(Items.GLOW_BERRIES, 1)); ++ } ++ // CraftBukkit end ++ + float f = MathHelper.randomBetween(world.random, 0.8F, 1.2F); + + world.playSound((EntityHuman) null, blockposition, SoundEffects.CAVE_VINES_PICK_BERRIES, SoundCategory.BLOCKS, 1.0F, f); diff --git a/patch-remap/og/net/minecraft/world/level/block/CeilingHangingSignBlock.patch b/patch-remap/og/net/minecraft/world/level/block/CeilingHangingSignBlock.patch new file mode 100644 index 0000000000..2cffc8787e --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/CeilingHangingSignBlock.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/world/level/block/CeilingHangingSignBlock.java ++++ b/net/minecraft/world/level/block/CeilingHangingSignBlock.java +@@ -161,6 +161,6 @@ + @Nullable + @Override + public BlockEntityTicker getTicker(World world, IBlockData iblockdata, TileEntityTypes tileentitytypes) { +- return createTickerHelper(tileentitytypes, TileEntityTypes.HANGING_SIGN, TileEntitySign::tick); ++ return null; // Craftbukkit - remove unnecessary sign ticking + } + } diff --git a/patch-remap/og/net/minecraft/world/level/block/ChangeOverTimeBlock.patch b/patch-remap/og/net/minecraft/world/level/block/ChangeOverTimeBlock.patch new file mode 100644 index 0000000000..cb2cffd6c0 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/ChangeOverTimeBlock.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/level/block/ChangeOverTimeBlock.java ++++ b/net/minecraft/world/level/block/ChangeOverTimeBlock.java +@@ -20,7 +20,7 @@ + + if (randomsource.nextFloat() < 0.05688889F) { + this.getNextState(iblockdata, worldserver, blockposition, randomsource).ifPresent((iblockdata1) -> { +- worldserver.setBlockAndUpdate(blockposition, iblockdata1); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(worldserver, blockposition, iblockdata1); // CraftBukkit + }); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/DropExperienceBlock.patch b/patch-remap/og/net/minecraft/world/level/block/DropExperienceBlock.patch new file mode 100644 index 0000000000..cf005a11d4 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/DropExperienceBlock.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/level/block/DropExperienceBlock.java ++++ b/net/minecraft/world/level/block/DropExperienceBlock.java +@@ -31,9 +31,16 @@ + @Override + public void spawnAfterBreak(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, ItemStack itemstack, boolean flag) { + super.spawnAfterBreak(iblockdata, worldserver, blockposition, itemstack, flag); ++ // CraftBukkit start - Delegate to getExpDrop ++ } ++ ++ @Override ++ public int getExpDrop(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, ItemStack itemstack, boolean flag) { + if (flag) { +- this.tryDropExperience(worldserver, blockposition, itemstack, this.xpRange); ++ return this.tryDropExperience(worldserver, blockposition, itemstack, this.xpRange); + } + ++ return 0; ++ // CraftBukkit end + } + } diff --git a/patch-remap/og/net/minecraft/world/level/block/LayeredCauldronBlock.patch b/patch-remap/og/net/minecraft/world/level/block/LayeredCauldronBlock.patch new file mode 100644 index 0000000000..d9702e0b22 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/LayeredCauldronBlock.patch @@ -0,0 +1,93 @@ +--- a/net/minecraft/world/level/block/LayeredCauldronBlock.java ++++ b/net/minecraft/world/level/block/LayeredCauldronBlock.java +@@ -16,6 +16,12 @@ + import net.minecraft.world.level.material.FluidType; + import net.minecraft.world.level.material.FluidTypes; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlockState; ++import org.bukkit.craftbukkit.block.CraftBlockStates; ++import org.bukkit.event.block.CauldronLevelChangeEvent; ++// CraftBukkit end ++ + public class LayeredCauldronBlock extends AbstractCauldronBlock { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +@@ -61,10 +67,14 @@ + @Override + public void entityInside(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { + if (!world.isClientSide && entity.isOnFire() && this.isEntityInsideContent(iblockdata, blockposition, entity)) { +- entity.clearFire(); ++ // CraftBukkit start + if (entity.mayInteract(world, blockposition)) { +- this.handleEntityOnFireInside(iblockdata, world, blockposition); ++ if (!lowerFillLevel(iblockdata, world, blockposition, entity, CauldronLevelChangeEvent.ChangeReason.EXTINGUISH)) { ++ return; ++ } + } ++ entity.clearFire(); ++ // CraftBukkit end + } + + } +@@ -79,20 +89,42 @@ + } + + public static void lowerFillLevel(IBlockData iblockdata, World world, BlockPosition blockposition) { ++ // CraftBukkit start ++ lowerFillLevel(iblockdata, world, blockposition, null, CauldronLevelChangeEvent.ChangeReason.UNKNOWN); ++ } ++ ++ public static boolean lowerFillLevel(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity, CauldronLevelChangeEvent.ChangeReason reason) { + int i = (Integer) iblockdata.getValue(LayeredCauldronBlock.LEVEL) - 1; + IBlockData iblockdata1 = i == 0 ? Blocks.CAULDRON.defaultBlockState() : (IBlockData) iblockdata.setValue(LayeredCauldronBlock.LEVEL, i); + +- world.setBlockAndUpdate(blockposition, iblockdata1); +- world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.a.of(iblockdata1)); ++ return changeLevel(iblockdata, world, blockposition, iblockdata1, entity, reason); + } + ++ // CraftBukkit start ++ public static boolean changeLevel(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData newBlock, Entity entity, CauldronLevelChangeEvent.ChangeReason reason) { ++ CraftBlockState newState = CraftBlockStates.getBlockState(world, blockposition); ++ newState.setData(newBlock); ++ ++ CauldronLevelChangeEvent event = new CauldronLevelChangeEvent( ++ world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), ++ (entity == null) ? null : entity.getBukkitEntity(), reason, newState ++ ); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ newState.update(true); ++ world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.a.of(newBlock)); ++ return true; ++ } ++ // CraftBukkit end ++ + @Override + public void handlePrecipitation(IBlockData iblockdata, World world, BlockPosition blockposition, BiomeBase.Precipitation biomebase_precipitation) { + if (BlockCauldron.shouldHandlePrecipitation(world, biomebase_precipitation) && (Integer) iblockdata.getValue(LayeredCauldronBlock.LEVEL) != 3 && biomebase_precipitation == this.precipitationType) { + IBlockData iblockdata1 = (IBlockData) iblockdata.cycle(LayeredCauldronBlock.LEVEL); + +- world.setBlockAndUpdate(blockposition, iblockdata1); +- world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.a.of(iblockdata1)); ++ changeLevel(iblockdata, world, blockposition, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL); // CraftBukkit + } + } + +@@ -111,8 +143,11 @@ + if (!this.isFull(iblockdata)) { + IBlockData iblockdata1 = (IBlockData) iblockdata.setValue(LayeredCauldronBlock.LEVEL, (Integer) iblockdata.getValue(LayeredCauldronBlock.LEVEL) + 1); + +- world.setBlockAndUpdate(blockposition, iblockdata1); +- world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.a.of(iblockdata1)); ++ // CraftBukkit start ++ if (!changeLevel(iblockdata, world, blockposition, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL)) { ++ return; ++ } ++ // CraftBukkit end + world.levelEvent(1047, blockposition, 0); + } + } diff --git a/patch-remap/og/net/minecraft/world/level/block/LightningRodBlock.patch b/patch-remap/og/net/minecraft/world/level/block/LightningRodBlock.patch new file mode 100644 index 0000000000..c67e7fcb32 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/LightningRodBlock.patch @@ -0,0 +1,42 @@ +--- a/net/minecraft/world/level/block/LightningRodBlock.java ++++ b/net/minecraft/world/level/block/LightningRodBlock.java +@@ -33,6 +33,11 @@ + import net.minecraft.world.phys.MovingObjectPositionBlock; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockRedstoneEvent; ++// CraftBukkit end ++ + public class LightningRodBlock extends RodBlock implements IBlockWaterlogged { + + public static final MapCodec CODEC = simpleCodec(LightningRodBlock::new); +@@ -85,6 +90,18 @@ + } + + public void onLightningStrike(IBlockData iblockdata, World world, BlockPosition blockposition) { ++ // CraftBukkit start ++ boolean powered = iblockdata.getValue(LightningRodBlock.POWERED); ++ int old = (powered) ? 15 : 0; ++ int current = (!powered) ? 15 : 0; ++ ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(world, blockposition), old, current); ++ world.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if (eventRedstone.getNewCurrent() <= 0) { ++ return; ++ } ++ // CraftBukkit end + world.setBlock(blockposition, (IBlockData) iblockdata.setValue(LightningRodBlock.POWERED, true), 3); + this.updateNeighbours(iblockdata, world, blockposition); + world.scheduleTick(blockposition, (Block) this, 8); +@@ -142,7 +159,7 @@ + Entity entity = iprojectile.getOwner(); + + entitylightning.setCause(entity instanceof EntityPlayer ? (EntityPlayer) entity : null); +- world.addFreshEntity(entitylightning); ++ ((WorldServer) world).strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.TRIDENT); // CraftBukkit + } + + world.playSound((EntityHuman) null, blockposition, SoundEffects.TRIDENT_THUNDER, SoundCategory.WEATHER, 5.0F, 1.0F); diff --git a/patch-remap/og/net/minecraft/world/level/block/MultifaceSpreader.patch b/patch-remap/og/net/minecraft/world/level/block/MultifaceSpreader.patch new file mode 100644 index 0000000000..216e14a222 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/MultifaceSpreader.patch @@ -0,0 +1,43 @@ +--- a/net/minecraft/world/level/block/MultifaceSpreader.java ++++ b/net/minecraft/world/level/block/MultifaceSpreader.java +@@ -156,7 +156,7 @@ + generatoraccess.getChunk(multifacespreader_c.pos()).markPosForPostprocessing(multifacespreader_c.pos()); + } + +- return generatoraccess.setBlock(multifacespreader_c.pos(), iblockdata1, 2); ++ return org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(generatoraccess, multifacespreader_c.source(), multifacespreader_c.pos(), iblockdata1, 2); // CraftBukkit + } else { + return false; + } +@@ -174,19 +174,19 @@ + SAME_POSITION { + @Override + public MultifaceSpreader.c getSpreadPos(BlockPosition blockposition, EnumDirection enumdirection, EnumDirection enumdirection1) { +- return new MultifaceSpreader.c(blockposition, enumdirection); ++ return new MultifaceSpreader.c(blockposition, enumdirection, blockposition); // CraftBukkit + } + }, + SAME_PLANE { + @Override + public MultifaceSpreader.c getSpreadPos(BlockPosition blockposition, EnumDirection enumdirection, EnumDirection enumdirection1) { +- return new MultifaceSpreader.c(blockposition.relative(enumdirection), enumdirection1); ++ return new MultifaceSpreader.c(blockposition.relative(enumdirection), enumdirection1, blockposition); // CraftBukkit + } + }, + WRAP_AROUND { + @Override + public MultifaceSpreader.c getSpreadPos(BlockPosition blockposition, EnumDirection enumdirection, EnumDirection enumdirection1) { +- return new MultifaceSpreader.c(blockposition.relative(enumdirection).relative(enumdirection1), enumdirection.getOpposite()); ++ return new MultifaceSpreader.c(blockposition.relative(enumdirection).relative(enumdirection1), enumdirection.getOpposite(), blockposition); // CraftBukkit + } + }; + +@@ -195,7 +195,7 @@ + public abstract MultifaceSpreader.c getSpreadPos(BlockPosition blockposition, EnumDirection enumdirection, EnumDirection enumdirection1); + } + +- public static record c(BlockPosition pos, EnumDirection face) { ++ public static record c(BlockPosition pos, EnumDirection face, BlockPosition source) { // CraftBukkit + + } + } diff --git a/patch-remap/og/net/minecraft/world/level/block/PointedDripstoneBlock.patch b/patch-remap/og/net/minecraft/world/level/block/PointedDripstoneBlock.patch new file mode 100644 index 0000000000..9e2b95127e --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/PointedDripstoneBlock.patch @@ -0,0 +1,93 @@ +--- a/net/minecraft/world/level/block/PointedDripstoneBlock.java ++++ b/net/minecraft/world/level/block/PointedDripstoneBlock.java +@@ -43,6 +43,11 @@ + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + import net.minecraft.world.phys.shapes.VoxelShapes; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class PointedDripstoneBlock extends Block implements Fallable, IBlockWaterlogged { + + public static final MapCodec CODEC = simpleCodec(PointedDripstoneBlock::new); +@@ -132,6 +137,11 @@ + BlockPosition blockposition = movingobjectpositionblock.getBlockPos(); + + if (iprojectile.mayInteract(world, blockposition) && iprojectile.mayBreak(world) && iprojectile instanceof EntityThrownTrident && iprojectile.getDeltaMovement().length() > 0.6D) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(iprojectile, blockposition, Blocks.AIR.defaultBlockState())) { ++ return; ++ } ++ // CraftBukkit end + world.destroyBlock(blockposition, true); + } + +@@ -141,7 +151,9 @@ + @Override + public void fallOn(World world, IBlockData iblockdata, BlockPosition blockposition, Entity entity, float f) { + if (iblockdata.getValue(PointedDripstoneBlock.TIP_DIRECTION) == EnumDirection.UP && iblockdata.getValue(PointedDripstoneBlock.THICKNESS) == DripstoneThickness.TIP) { ++ CraftEventFactory.blockDamage = CraftBlock.at(world, blockposition); // CraftBukkit + entity.causeFallDamage(f + 2.0F, 2.0F, world.damageSources().stalagmite()); ++ CraftEventFactory.blockDamage = null; // CraftBukkit + } else { + super.fallOn(world, iblockdata, blockposition, entity, f); + } +@@ -386,15 +398,15 @@ + if (isUnmergedTipWithDirection(iblockdata, enumdirection.getOpposite())) { + createMergedTips(iblockdata, worldserver, blockposition1); + } else if (iblockdata.isAir() || iblockdata.is(Blocks.WATER)) { +- createDripstone(worldserver, blockposition1, enumdirection, DripstoneThickness.TIP); ++ createDripstone(worldserver, blockposition1, enumdirection, DripstoneThickness.TIP, blockposition); // CraftBukkit + } + + } + +- private static void createDripstone(GeneratorAccess generatoraccess, BlockPosition blockposition, EnumDirection enumdirection, DripstoneThickness dripstonethickness) { ++ private static void createDripstone(GeneratorAccess generatoraccess, BlockPosition blockposition, EnumDirection enumdirection, DripstoneThickness dripstonethickness, BlockPosition source) { // CraftBukkit + IBlockData iblockdata = (IBlockData) ((IBlockData) ((IBlockData) Blocks.POINTED_DRIPSTONE.defaultBlockState().setValue(PointedDripstoneBlock.TIP_DIRECTION, enumdirection)).setValue(PointedDripstoneBlock.THICKNESS, dripstonethickness)).setValue(PointedDripstoneBlock.WATERLOGGED, generatoraccess.getFluidState(blockposition).getType() == FluidTypes.WATER); + +- generatoraccess.setBlock(blockposition, iblockdata, 3); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(generatoraccess, source, blockposition, iblockdata, 3); // CraftBukkit + } + + private static void createMergedTips(IBlockData iblockdata, GeneratorAccess generatoraccess, BlockPosition blockposition) { +@@ -409,8 +421,8 @@ + blockposition1 = blockposition.below(); + } + +- createDripstone(generatoraccess, blockposition2, EnumDirection.DOWN, DripstoneThickness.TIP_MERGE); +- createDripstone(generatoraccess, blockposition1, EnumDirection.UP, DripstoneThickness.TIP_MERGE); ++ createDripstone(generatoraccess, blockposition2, EnumDirection.DOWN, DripstoneThickness.TIP_MERGE, blockposition); // CraftBukkit ++ createDripstone(generatoraccess, blockposition1, EnumDirection.UP, DripstoneThickness.TIP_MERGE, blockposition); // CraftBukkit + } + + public static void spawnDripParticle(World world, BlockPosition blockposition, IBlockData iblockdata) { +@@ -443,7 +455,7 @@ + + return (BlockPosition) findBlockVertical(generatoraccess, blockposition, enumdirection.getAxisDirection(), bipredicate, (iblockdata1) -> { + return isTip(iblockdata1, flag); +- }, i).orElse((Object) null); ++ }, i).orElse(null); // CraftBukkit - decompile error + } + } + +@@ -559,7 +571,7 @@ + return canDripThrough(world, blockposition1, iblockdata); + }; + +- return (BlockPosition) findBlockVertical(world, blockposition, EnumDirection.DOWN.getAxisDirection(), bipredicate, predicate, 11).orElse((Object) null); ++ return (BlockPosition) findBlockVertical(world, blockposition, EnumDirection.DOWN.getAxisDirection(), bipredicate, predicate, 11).orElse(null); // CraftBukkit - decompile error + } + + @Nullable +@@ -568,7 +580,7 @@ + return canDripThrough(world, blockposition1, iblockdata); + }; + +- return (BlockPosition) findBlockVertical(world, blockposition, EnumDirection.UP.getAxisDirection(), bipredicate, PointedDripstoneBlock::canDrip, 11).orElse((Object) null); ++ return (BlockPosition) findBlockVertical(world, blockposition, EnumDirection.UP.getAxisDirection(), bipredicate, PointedDripstoneBlock::canDrip, 11).orElse(null); // CraftBukkit - decompile error + } + + public static FluidType getCauldronFillFluidType(WorldServer worldserver, BlockPosition blockposition) { diff --git a/patch-remap/og/net/minecraft/world/level/block/PowderSnowBlock.patch b/patch-remap/og/net/minecraft/world/level/block/PowderSnowBlock.patch new file mode 100644 index 0000000000..3897c7400e --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/PowderSnowBlock.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/level/block/PowderSnowBlock.java ++++ b/net/minecraft/world/level/block/PowderSnowBlock.java +@@ -77,7 +77,12 @@ + + entity.setIsInPowderSnow(true); + if (!world.isClientSide) { +- if (entity.isOnFire() && (world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity instanceof EntityHuman) && entity.mayInteract(world, blockposition)) { ++ // CraftBukkit start ++ if (entity.isOnFire() && entity.mayInteract(world, blockposition)) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, Blocks.AIR.defaultBlockState(), !(world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity instanceof EntityHuman))) { ++ return; ++ } ++ // CraftBukkit end + world.destroyBlock(blockposition, false); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/RootedDirtBlock.patch b/patch-remap/og/net/minecraft/world/level/block/RootedDirtBlock.patch new file mode 100644 index 0000000000..fe3878c9a7 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/RootedDirtBlock.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/world/level/block/RootedDirtBlock.java ++++ b/net/minecraft/world/level/block/RootedDirtBlock.java +@@ -34,6 +34,6 @@ + + @Override + public void performBonemeal(WorldServer worldserver, RandomSource randomsource, BlockPosition blockposition, IBlockData iblockdata) { +- worldserver.setBlockAndUpdate(blockposition.below(), Blocks.HANGING_ROOTS.defaultBlockState()); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(worldserver, blockposition, blockposition.below(), Blocks.HANGING_ROOTS.defaultBlockState()); // CraftBukkit + } + } diff --git a/patch-remap/og/net/minecraft/world/level/block/SculkBlock.patch b/patch-remap/og/net/minecraft/world/level/block/SculkBlock.patch new file mode 100644 index 0000000000..e6fd17eed5 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/SculkBlock.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/level/block/SculkBlock.java ++++ b/net/minecraft/world/level/block/SculkBlock.java +@@ -43,8 +43,11 @@ + BlockPosition blockposition2 = blockposition1.above(); + IBlockData iblockdata = this.getRandomGrowthState(generatoraccess, blockposition2, randomsource, sculkspreader.isWorldGeneration()); + +- generatoraccess.setBlock(blockposition2, iblockdata, 3); +- generatoraccess.playSound((EntityHuman) null, blockposition1, iblockdata.getSoundType().getPlaceSound(), SoundCategory.BLOCKS, 1.0F, 1.0F); ++ // CraftBukkit start - Call BlockSpreadEvent ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(generatoraccess, blockposition, blockposition2, iblockdata, 3)) { ++ generatoraccess.playSound((EntityHuman) null, blockposition1, iblockdata.getSoundType().getPlaceSound(), SoundCategory.BLOCKS, 1.0F, 1.0F); ++ } ++ // CraftBukkit end + } + + return Math.max(0, i - j); diff --git a/patch-remap/og/net/minecraft/world/level/block/SculkCatalystBlock.patch b/patch-remap/og/net/minecraft/world/level/block/SculkCatalystBlock.patch new file mode 100644 index 0000000000..3373f9def5 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/SculkCatalystBlock.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/level/block/SculkCatalystBlock.java ++++ b/net/minecraft/world/level/block/SculkCatalystBlock.java +@@ -68,9 +68,16 @@ + @Override + public void spawnAfterBreak(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, ItemStack itemstack, boolean flag) { + super.spawnAfterBreak(iblockdata, worldserver, blockposition, itemstack, flag); ++ // CraftBukkit start - Delegate to getExpDrop ++ } ++ ++ @Override ++ public int getExpDrop(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, ItemStack itemstack, boolean flag) { + if (flag) { +- this.tryDropExperience(worldserver, blockposition, itemstack, this.xpRange); ++ return this.tryDropExperience(worldserver, blockposition, itemstack, this.xpRange); + } + ++ return 0; ++ // CraftBukkit end + } + } diff --git a/patch-remap/og/net/minecraft/world/level/block/SculkSensorBlock.patch b/patch-remap/og/net/minecraft/world/level/block/SculkSensorBlock.patch new file mode 100644 index 0000000000..3598fb5a29 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/SculkSensorBlock.patch @@ -0,0 +1,83 @@ +--- a/net/minecraft/world/level/block/SculkSensorBlock.java ++++ b/net/minecraft/world/level/block/SculkSensorBlock.java +@@ -42,6 +42,11 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockRedstoneEvent; ++// CraftBukkit end ++ + public class SculkSensorBlock extends BlockTileEntity implements IBlockWaterlogged { + + public static final MapCodec CODEC = simpleCodec(SculkSensorBlock::new); +@@ -102,6 +107,18 @@ + @Override + public void stepOn(World world, BlockPosition blockposition, IBlockData iblockdata, Entity entity) { + if (!world.isClientSide() && canActivate(iblockdata) && entity.getType() != EntityTypes.WARDEN) { ++ // CraftBukkit start ++ org.bukkit.event.Cancellable cancellable; ++ if (entity instanceof EntityHuman) { ++ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((EntityHuman) entity, org.bukkit.event.block.Action.PHYSICAL, blockposition, null, null, null); ++ } else { ++ cancellable = new org.bukkit.event.entity.EntityInteractEvent(entity.getBukkitEntity(), world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ())); ++ world.getCraftServer().getPluginManager().callEvent((org.bukkit.event.entity.EntityInteractEvent) cancellable); ++ } ++ if (cancellable.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + TileEntity tileentity = world.getBlockEntity(blockposition); + + if (tileentity instanceof SculkSensorBlockEntity) { +@@ -205,6 +222,15 @@ + } + + public static void deactivate(World world, BlockPosition blockposition, IBlockData iblockdata) { ++ // CraftBukkit start ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(world, blockposition), iblockdata.getValue(SculkSensorBlock.POWER), 0); ++ world.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if (eventRedstone.getNewCurrent() > 0) { ++ world.setBlock(blockposition, iblockdata.setValue(SculkSensorBlock.POWER, eventRedstone.getNewCurrent()), 3); ++ return; ++ } ++ // CraftBukkit end + world.setBlock(blockposition, (IBlockData) ((IBlockData) iblockdata.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.COOLDOWN)).setValue(SculkSensorBlock.POWER, 0), 3); + world.scheduleTick(blockposition, iblockdata.getBlock(), 10); + updateNeighbours(world, blockposition, iblockdata); +@@ -216,6 +242,15 @@ + } + + public void activate(@Nullable Entity entity, World world, BlockPosition blockposition, IBlockData iblockdata, int i, int j) { ++ // CraftBukkit start ++ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(world, blockposition), iblockdata.getValue(SculkSensorBlock.POWER), i); ++ world.getCraftServer().getPluginManager().callEvent(eventRedstone); ++ ++ if (eventRedstone.getNewCurrent() <= 0) { ++ return; ++ } ++ i = eventRedstone.getNewCurrent(); ++ // CraftBukkit end + world.setBlock(blockposition, (IBlockData) ((IBlockData) iblockdata.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.ACTIVE)).setValue(SculkSensorBlock.POWER, i), 3); + world.scheduleTick(blockposition, iblockdata.getBlock(), this.getActiveTicks()); + updateNeighbours(world, blockposition, iblockdata); +@@ -298,9 +333,16 @@ + @Override + public void spawnAfterBreak(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, ItemStack itemstack, boolean flag) { + super.spawnAfterBreak(iblockdata, worldserver, blockposition, itemstack, flag); ++ // CraftBukkit start - Delegate to getExpDrop ++ } ++ ++ @Override ++ public int getExpDrop(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, ItemStack itemstack, boolean flag) { + if (flag) { +- this.tryDropExperience(worldserver, blockposition, itemstack, ConstantInt.of(5)); ++ return this.tryDropExperience(worldserver, blockposition, itemstack, ConstantInt.of(5)); + } + ++ return 0; ++ // CraftBukkit end + } + } diff --git a/patch-remap/og/net/minecraft/world/level/block/SculkShriekerBlock.patch b/patch-remap/og/net/minecraft/world/level/block/SculkShriekerBlock.patch new file mode 100644 index 0000000000..59cb55a612 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/SculkShriekerBlock.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/world/level/block/SculkShriekerBlock.java ++++ b/net/minecraft/world/level/block/SculkShriekerBlock.java +@@ -63,6 +63,7 @@ + EntityPlayer entityplayer = SculkShriekerBlockEntity.tryGetPlayer(entity); + + if (entityplayer != null) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(entityplayer, org.bukkit.event.block.Action.PHYSICAL, blockposition, null, null, null).isCancelled()) return; // CraftBukkit + worldserver.getBlockEntity(blockposition, TileEntityTypes.SCULK_SHRIEKER).ifPresent((sculkshriekerblockentity) -> { + sculkshriekerblockentity.tryShriek(worldserver, entityplayer); + }); +@@ -147,10 +148,17 @@ + @Override + public void spawnAfterBreak(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, ItemStack itemstack, boolean flag) { + super.spawnAfterBreak(iblockdata, worldserver, blockposition, itemstack, flag); ++ // CraftBukkit start - Delegate to getExpDrop ++ } ++ ++ @Override ++ public int getExpDrop(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, ItemStack itemstack, boolean flag) { + if (flag) { +- this.tryDropExperience(worldserver, blockposition, itemstack, ConstantInt.of(5)); ++ return this.tryDropExperience(worldserver, blockposition, itemstack, ConstantInt.of(5)); + } + ++ return 0; ++ // CraftBukkit end + } + + @Nullable diff --git a/patch-remap/og/net/minecraft/world/level/block/SculkSpreader.patch b/patch-remap/og/net/minecraft/world/level/block/SculkSpreader.patch new file mode 100644 index 0000000000..f7fdd0b5b4 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/SculkSpreader.patch @@ -0,0 +1,72 @@ +--- a/net/minecraft/world/level/block/SculkSpreader.java ++++ b/net/minecraft/world/level/block/SculkSpreader.java +@@ -41,6 +41,14 @@ + import net.minecraft.world.level.block.state.IBlockData; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.nbt.NBTBase; ++import net.minecraft.world.level.World; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.SculkBloomEvent; ++// CraftBukkit end ++ + public class SculkSpreader { + + public static final int MAX_GROWTH_RATE_RADIUS = 24; +@@ -56,6 +64,7 @@ + private final int additionalDecayRate; + private List cursors = new ArrayList(); + private static final Logger LOGGER = LogUtils.getLogger(); ++ public World level; // CraftBukkit + + public SculkSpreader(boolean flag, TagKey tagkey, int i, int j, int k, int l) { + this.isWorldGeneration = flag; +@@ -110,7 +119,7 @@ + public void load(NBTTagCompound nbttagcompound) { + if (nbttagcompound.contains("cursors", 9)) { + this.cursors.clear(); +- DataResult dataresult = SculkSpreader.a.CODEC.listOf().parse(new Dynamic(DynamicOpsNBT.INSTANCE, nbttagcompound.getList("cursors", 10))); ++ DataResult> dataresult = SculkSpreader.a.CODEC.listOf().parse(new Dynamic<>(DynamicOpsNBT.INSTANCE, nbttagcompound.getList("cursors", 10))); // CraftBukkit - decompile error + Logger logger = SculkSpreader.LOGGER; + + Objects.requireNonNull(logger); +@@ -125,7 +134,7 @@ + } + + public void save(NBTTagCompound nbttagcompound) { +- DataResult dataresult = SculkSpreader.a.CODEC.listOf().encodeStart(DynamicOpsNBT.INSTANCE, this.cursors); ++ DataResult dataresult = SculkSpreader.a.CODEC.listOf().encodeStart(DynamicOpsNBT.INSTANCE, this.cursors); // CraftBukkit - decompile error + Logger logger = SculkSpreader.LOGGER; + + Objects.requireNonNull(logger); +@@ -146,6 +155,19 @@ + + private void addCursor(SculkSpreader.a sculkspreader_a) { + if (this.cursors.size() < 32) { ++ // CraftBukkit start ++ if (!isWorldGeneration()) { // CraftBukkit - SPIGOT-7475: Don't call event during world generation ++ CraftBlock bukkitBlock = CraftBlock.at(level, sculkspreader_a.pos); ++ SculkBloomEvent event = new SculkBloomEvent(bukkitBlock, sculkspreader_a.getCharge()); ++ Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ sculkspreader_a.charge = event.getCharge(); ++ } ++ // CraftBukkit end ++ + this.cursors.add(sculkspreader_a); + } + } +@@ -241,7 +263,7 @@ + this.charge = i; + this.decayDelay = j; + this.updateDelay = k; +- this.facings = (Set) optional.orElse((Object) null); ++ this.facings = (Set) optional.orElse(null); // CraftBukkit - decompile error + } + + public a(BlockPosition blockposition, int i) { diff --git a/patch-remap/og/net/minecraft/world/level/block/SculkVeinBlock.patch b/patch-remap/og/net/minecraft/world/level/block/SculkVeinBlock.patch new file mode 100644 index 0000000000..73b7016900 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/SculkVeinBlock.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/world/level/block/SculkVeinBlock.java ++++ b/net/minecraft/world/level/block/SculkVeinBlock.java +@@ -108,10 +108,11 @@ + + @Override + public int attemptUseCharge(SculkSpreader.a sculkspreader_a, GeneratorAccess generatoraccess, BlockPosition blockposition, RandomSource randomsource, SculkSpreader sculkspreader, boolean flag) { +- return flag && this.attemptPlaceSculk(sculkspreader, generatoraccess, sculkspreader_a.getPos(), randomsource) ? sculkspreader_a.getCharge() - 1 : (randomsource.nextInt(sculkspreader.chargeDecayRate()) == 0 ? MathHelper.floor((float) sculkspreader_a.getCharge() * 0.5F) : sculkspreader_a.getCharge()); ++ // CraftBukkit - add source block ++ return flag && this.attemptPlaceSculk(sculkspreader, generatoraccess, sculkspreader_a.getPos(), randomsource, blockposition) ? sculkspreader_a.getCharge() - 1 : (randomsource.nextInt(sculkspreader.chargeDecayRate()) == 0 ? MathHelper.floor((float) sculkspreader_a.getCharge() * 0.5F) : sculkspreader_a.getCharge()); + } + +- private boolean attemptPlaceSculk(SculkSpreader sculkspreader, GeneratorAccess generatoraccess, BlockPosition blockposition, RandomSource randomsource) { ++ private boolean attemptPlaceSculk(SculkSpreader sculkspreader, GeneratorAccess generatoraccess, BlockPosition blockposition, RandomSource randomsource, BlockPosition sourceBlock) { // CraftBukkit + IBlockData iblockdata = generatoraccess.getBlockState(blockposition); + TagKey tagkey = sculkspreader.replaceableBlocks(); + Iterator iterator = EnumDirection.allShuffled(randomsource).iterator(); +@@ -126,7 +127,11 @@ + if (iblockdata1.is(tagkey)) { + IBlockData iblockdata2 = Blocks.SCULK.defaultBlockState(); + +- generatoraccess.setBlock(blockposition1, iblockdata2, 3); ++ // CraftBukkit start - Call BlockSpreadEvent ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(generatoraccess, sourceBlock, blockposition1, iblockdata2, 3)) { ++ return false; ++ } ++ // CraftBukkit end + Block.pushEntitiesUp(iblockdata1, iblockdata2, generatoraccess, blockposition1); + generatoraccess.playSound((EntityHuman) null, blockposition1, SoundEffects.SCULK_BLOCK_SPREAD, SoundCategory.BLOCKS, 1.0F, 1.0F); + this.veinSpreader.spreadAll(iblockdata2, generatoraccess, blockposition1, sculkspreader.isWorldGeneration()); diff --git a/patch-remap/og/net/minecraft/world/level/block/WallHangingSignBlock.patch b/patch-remap/og/net/minecraft/world/level/block/WallHangingSignBlock.patch new file mode 100644 index 0000000000..8195d10645 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/WallHangingSignBlock.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/world/level/block/WallHangingSignBlock.java ++++ b/net/minecraft/world/level/block/WallHangingSignBlock.java +@@ -186,6 +186,6 @@ + @Nullable + @Override + public BlockEntityTicker getTicker(World world, IBlockData iblockdata, TileEntityTypes tileentitytypes) { +- return createTickerHelper(tileentitytypes, TileEntityTypes.HANGING_SIGN, TileEntitySign::tick); ++ return null; // Craftbukkit - remove unnecessary sign ticking + } + } diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/BrushableBlockEntity.patch b/patch-remap/og/net/minecraft/world/level/block/entity/BrushableBlockEntity.patch new file mode 100644 index 0000000000..b49f707120 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/BrushableBlockEntity.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/level/block/entity/BrushableBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BrushableBlockEntity.java +@@ -28,6 +28,12 @@ + import net.minecraft.world.phys.Vec3D; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.Arrays; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class BrushableBlockEntity extends TileEntity { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -153,7 +159,10 @@ + EntityItem entityitem = new EntityItem(this.level, d3, d4, d5, this.item.split(this.level.random.nextInt(21) + 10)); + + entityitem.setDeltaMovement(Vec3D.ZERO); +- this.level.addFreshEntity(entityitem); ++ // CraftBukkit start ++ org.bukkit.block.Block bblock = CraftBlock.at(this.level, this.worldPosition); ++ CraftEventFactory.handleBlockDropItemEvent(bblock, bblock.getState(), (EntityPlayer) entityhuman, Arrays.asList(entityitem)); ++ // CraftBukkit end + this.item = ItemStack.EMPTY; + } + +@@ -230,6 +239,7 @@ + + @Override + public void load(NBTTagCompound nbttagcompound) { ++ super.load(nbttagcompound); // CraftBukkit - SPIGOT-7393: Load super Bukkit data + if (!this.tryLoadLootTable(nbttagcompound) && nbttagcompound.contains("item")) { + this.item = ItemStack.of(nbttagcompound.getCompound("item")); + } diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.patch b/patch-remap/og/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.patch new file mode 100644 index 0000000000..85e86180b1 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.patch @@ -0,0 +1,92 @@ +--- a/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java +@@ -18,12 +18,54 @@ + import net.minecraft.world.level.gameevent.GameEvent; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class ChiseledBookShelfBlockEntity extends TileEntity implements IInventory { + + public static final int MAX_BOOKS_IN_STORAGE = 6; + private static final Logger LOGGER = LogUtils.getLogger(); + private final NonNullList items; + public int lastInteractedSlot; ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList<>(); ++ private int maxStack = 1; ++ ++ @Override ++ public List getContents() { ++ return this.items; ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ } ++ // CraftBukkit end + + public ChiseledBookShelfBlockEntity(BlockPosition blockposition, IBlockData iblockdata) { + super(TileEntityTypes.CHISELED_BOOKSHELF, blockposition, iblockdata); +@@ -52,6 +94,7 @@ + + @Override + public void load(NBTTagCompound nbttagcompound) { ++ super.load(nbttagcompound); // CraftBukkit - SPIGOT-7393: Load super Bukkit data + this.items.clear(); + ContainerUtil.loadAllItems(nbttagcompound, this.items); + this.lastInteractedSlot = nbttagcompound.getInt("last_interacted_slot"); +@@ -93,7 +136,7 @@ + + this.items.set(i, ItemStack.EMPTY); + if (!itemstack.isEmpty()) { +- this.updateState(i); ++ if (level != null) this.updateState(i); // CraftBukkit - SPIGOT-7381: check for null world + } + + return itemstack; +@@ -108,7 +151,7 @@ + public void setItem(int i, ItemStack itemstack) { + if (itemstack.is(TagsItem.BOOKSHELF_BOOKS)) { + this.items.set(i, itemstack); +- this.updateState(i); ++ if (level != null) this.updateState(i); // CraftBukkit - SPIGOT-7381: check for null world + } else if (itemstack.isEmpty()) { + this.removeItem(i, 1); + } +@@ -124,7 +167,7 @@ + + @Override + public int getMaxStackSize() { +- return 1; ++ return maxStack; // CraftBukkit + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/ContainerOpenersCounter.patch b/patch-remap/og/net/minecraft/world/level/block/entity/ContainerOpenersCounter.patch new file mode 100644 index 0000000000..dfb1293593 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/ContainerOpenersCounter.patch @@ -0,0 +1,75 @@ +--- a/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java ++++ b/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java +@@ -13,6 +13,7 @@ + + private static final int CHECK_TICK_DELAY = 5; + private int openCount; ++ public boolean opened; // CraftBukkit + + public ContainerOpenersCounter() {} + +@@ -22,11 +23,36 @@ + + protected abstract void openerCountChanged(World world, BlockPosition blockposition, IBlockData iblockdata, int i, int j); + ++ // CraftBukkit start ++ public void onAPIOpen(World world, BlockPosition blockposition, IBlockData iblockdata) { ++ onOpen(world, blockposition, iblockdata); ++ } ++ ++ public void onAPIClose(World world, BlockPosition blockposition, IBlockData iblockdata) { ++ onClose(world, blockposition, iblockdata); ++ } ++ ++ public void openerAPICountChanged(World world, BlockPosition blockposition, IBlockData iblockdata, int i, int j) { ++ openerCountChanged(world, blockposition, iblockdata, i, j); ++ } ++ // CraftBukkit end ++ + protected abstract boolean isOwnContainer(EntityHuman entityhuman); + + public void incrementOpeners(EntityHuman entityhuman, World world, BlockPosition blockposition, IBlockData iblockdata) { ++ int oldPower = Math.max(0, Math.min(15, this.openCount)); // CraftBukkit - Get power before new viewer is added + int i = this.openCount++; + ++ // CraftBukkit start - Call redstone event ++ if (world.getBlockState(blockposition).is(net.minecraft.world.level.block.Blocks.TRAPPED_CHEST)) { ++ int newPower = Math.max(0, Math.min(15, this.openCount)); ++ ++ if (oldPower != newPower) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(world, blockposition, oldPower, newPower); ++ } ++ } ++ // CraftBukkit end ++ + if (i == 0) { + this.onOpen(world, blockposition, iblockdata); + world.gameEvent((Entity) entityhuman, GameEvent.CONTAINER_OPEN, blockposition); +@@ -37,8 +63,19 @@ + } + + public void decrementOpeners(EntityHuman entityhuman, World world, BlockPosition blockposition, IBlockData iblockdata) { ++ int oldPower = Math.max(0, Math.min(15, this.openCount)); // CraftBukkit - Get power before new viewer is added + int i = this.openCount--; + ++ // CraftBukkit start - Call redstone event ++ if (world.getBlockState(blockposition).is(net.minecraft.world.level.block.Blocks.TRAPPED_CHEST)) { ++ int newPower = Math.max(0, Math.min(15, this.openCount)); ++ ++ if (oldPower != newPower) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(world, blockposition, oldPower, newPower); ++ } ++ } ++ // CraftBukkit end ++ + if (this.openCount == 0) { + this.onClose(world, blockposition, iblockdata); + world.gameEvent((Entity) entityhuman, GameEvent.CONTAINER_CLOSE, blockposition); +@@ -59,6 +96,7 @@ + + public void recheckOpeners(World world, BlockPosition blockposition, IBlockData iblockdata) { + int i = this.getOpenCount(world, blockposition); ++ if (opened) i++; // CraftBukkit - add dummy count from API + int j = this.openCount; + + if (j != i) { diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/CrafterBlockEntity.patch b/patch-remap/og/net/minecraft/world/level/block/entity/CrafterBlockEntity.patch new file mode 100644 index 0000000000..884f519a3e --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/CrafterBlockEntity.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/level/block/entity/CrafterBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/CrafterBlockEntity.java +@@ -21,6 +21,12 @@ + import net.minecraft.world.level.block.CrafterBlock; + import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class CrafterBlockEntity extends TileEntityLootable implements InventoryCrafting { + + public static final int CONTAINER_WIDTH = 3; +@@ -33,6 +39,46 @@ + private NonNullList items; + public int craftingTicksRemaining; + protected final IContainerProperties containerData; ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList<>(); ++ private int maxStack = 1; ++ ++ @Override ++ public List getContents() { ++ return this.items; ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ @Override ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ } ++ // CraftBukkit end + + public CrafterBlockEntity(BlockPosition blockposition, IBlockData iblockdata) { + super(TileEntityTypes.CRAFTER, blockposition, iblockdata); diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.patch b/patch-remap/og/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.patch new file mode 100644 index 0000000000..8602300644 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java +@@ -21,8 +21,59 @@ + import net.minecraft.world.level.block.state.properties.BlockProperties; + import net.minecraft.world.ticks.ContainerSingleItem; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class DecoratedPotBlockEntity extends TileEntity implements RandomizableContainer, ContainerSingleItem { + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new ArrayList<>(); ++ private int maxStack = MAX_STACK; ++ ++ @Override ++ public List getContents() { ++ return Arrays.asList(this.item); ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ @Override ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return CraftLocation.toBukkit(worldPosition, level.getWorld()); ++ } ++ // CraftBukkit end ++ + public static final String TAG_SHERDS = "sherds"; + public static final String TAG_ITEM = "item"; + public static final int EVENT_POT_WOBBLES = 1; diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.patch b/patch-remap/og/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.patch new file mode 100644 index 0000000000..4044ba6f05 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.patch @@ -0,0 +1,35 @@ +--- a/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java +@@ -32,14 +32,18 @@ + public SculkCatalystBlockEntity(BlockPosition blockposition, IBlockData iblockdata) { + super(TileEntityTypes.SCULK_CATALYST, blockposition, iblockdata); + this.catalystListener = new SculkCatalystBlockEntity.CatalystListener(iblockdata, new BlockPositionSource(blockposition)); ++ catalystListener.level = level; // CraftBukkit + } + + public static void serverTick(World world, BlockPosition blockposition, IBlockData iblockdata, SculkCatalystBlockEntity sculkcatalystblockentity) { ++ org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = sculkcatalystblockentity.getBlockPos(); // CraftBukkit - SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep. + sculkcatalystblockentity.catalystListener.getSculkSpreader().updateCursors(world, blockposition, world.getRandom(), true); ++ org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = null; // CraftBukkit + } + + @Override + public void load(NBTTagCompound nbttagcompound) { ++ super.load(nbttagcompound); // CraftBukkit - SPIGOT-7393: Load super Bukkit data + this.catalystListener.sculkSpreader.load(nbttagcompound); + } + +@@ -60,11 +64,13 @@ + final SculkSpreader sculkSpreader; + private final IBlockData blockState; + private final PositionSource positionSource; ++ private World level; // CraftBukkit + + public CatalystListener(IBlockData iblockdata, PositionSource positionsource) { + this.blockState = iblockdata; + this.positionSource = positionsource; + this.sculkSpreader = SculkSpreader.createLevelSpreader(); ++ this.sculkSpreader.level = level; // CraftBukkit + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntity.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntity.patch new file mode 100644 index 0000000000..1627b9e82c --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntity.patch @@ -0,0 +1,65 @@ +--- a/net/minecraft/world/level/block/entity/TileEntity.java ++++ b/net/minecraft/world/level/block/entity/TileEntity.java +@@ -15,8 +15,18 @@ + import net.minecraft.world.level.block.state.IBlockData; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer; ++import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end ++ + public abstract class TileEntity { + ++ // CraftBukkit start - data containers ++ private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); ++ public CraftPersistentDataContainer persistentDataContainer; ++ // CraftBukkit end + private static final Logger LOGGER = LogUtils.getLogger(); + private final TileEntityTypes type; + @Nullable +@@ -48,7 +58,16 @@ + return this.level != null; + } + +- public void load(NBTTagCompound nbttagcompound) {} ++ // CraftBukkit start - read container ++ public void load(NBTTagCompound nbttagcompound) { ++ this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); ++ ++ net.minecraft.nbt.NBTBase persistentDataTag = nbttagcompound.get("PublicBukkitValues"); ++ if (persistentDataTag instanceof NBTTagCompound) { ++ this.persistentDataContainer.putAll((NBTTagCompound) persistentDataTag); ++ } ++ } ++ // CraftBukkit end + + protected void saveAdditional(NBTTagCompound nbttagcompound) {} + +@@ -70,6 +89,11 @@ + NBTTagCompound nbttagcompound = new NBTTagCompound(); + + this.saveAdditional(nbttagcompound); ++ // CraftBukkit start - store container ++ if (this.persistentDataContainer != null && !this.persistentDataContainer.isEmpty()) { ++ nbttagcompound.put("PublicBukkitValues", this.persistentDataContainer.toTagCompound()); ++ } ++ // CraftBukkit end + return nbttagcompound; + } + +@@ -202,4 +226,13 @@ + public void setBlockState(IBlockData iblockdata) { + this.blockState = iblockdata; + } ++ ++ // CraftBukkit start - add method ++ public InventoryHolder getOwner() { ++ if (level == null) return null; ++ org.bukkit.block.BlockState state = level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()).getState(); ++ if (state instanceof InventoryHolder) return (InventoryHolder) state; ++ return null; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityBanner.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityBanner.patch new file mode 100644 index 0000000000..af3a633df7 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityBanner.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/block/entity/TileEntityBanner.java ++++ b/net/minecraft/world/level/block/entity/TileEntityBanner.java +@@ -102,6 +102,11 @@ + } + + this.itemPatterns = nbttagcompound.getList("Patterns", 10); ++ // CraftBukkit start ++ while (this.itemPatterns.size() > 20) { ++ this.itemPatterns.remove(20); ++ } ++ // CraftBukkit end + this.patterns = null; + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityBarrel.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityBarrel.patch new file mode 100644 index 0000000000..f7705b809a --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityBarrel.patch @@ -0,0 +1,52 @@ +--- a/net/minecraft/world/level/block/entity/TileEntityBarrel.java ++++ b/net/minecraft/world/level/block/entity/TileEntityBarrel.java +@@ -20,8 +20,49 @@ + import net.minecraft.world.level.block.BlockBarrel; + import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class TileEntityBarrel extends TileEntityLootable { + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new ArrayList<>(); ++ private int maxStack = MAX_STACK; ++ ++ @Override ++ public List getContents() { ++ return this.items; ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ @Override ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ // CraftBukkit end + private NonNullList items; + public final ContainerOpenersCounter openersCounter; + diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityBeacon.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityBeacon.patch new file mode 100644 index 0000000000..a6a2223b39 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityBeacon.patch @@ -0,0 +1,135 @@ +--- a/net/minecraft/world/level/block/entity/TileEntityBeacon.java ++++ b/net/minecraft/world/level/block/entity/TileEntityBeacon.java +@@ -40,6 +40,11 @@ + import net.minecraft.world.level.levelgen.HeightMap; + import net.minecraft.world.phys.AxisAlignedBB; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.potion.CraftPotionUtil; ++import org.bukkit.potion.PotionEffect; ++// CraftBukkit end ++ + public class TileEntityBeacon extends TileEntity implements ITileInventory, INamableTileEntity { + + private static final int MAX_LEVELS = 4; +@@ -65,6 +70,15 @@ + public IChatBaseComponent name; + public ChestLock lockKey; + private final IContainerProperties dataAccess; ++ // CraftBukkit start - add fields and methods ++ public PotionEffect getPrimaryEffect() { ++ return (this.primaryPower != null) ? CraftPotionUtil.toBukkit(new MobEffect(this.primaryPower, getLevel(this.levels), getAmplification(levels, primaryPower, secondaryPower), true, true)) : null; ++ } ++ ++ public PotionEffect getSecondaryEffect() { ++ return (hasSecondaryEffect(levels, primaryPower, secondaryPower)) ? CraftPotionUtil.toBukkit(new MobEffect(this.secondaryPower, getLevel(this.levels), getAmplification(levels, primaryPower, secondaryPower), true, true)) : null; ++ } ++ // CraftBukkit end + + @Nullable + static MobEffectList filterEffect(@Nullable MobEffectList mobeffectlist) { +@@ -245,38 +259,77 @@ + super.setRemoved(); + } + +- private static void applyEffects(World world, BlockPosition blockposition, int i, @Nullable MobEffectList mobeffectlist, @Nullable MobEffectList mobeffectlist1) { +- if (!world.isClientSide && mobeffectlist != null) { +- double d0 = (double) (i * 10 + 10); ++ // CraftBukkit start - split into components ++ private static byte getAmplification(int i, @Nullable MobEffectList mobeffectlist, @Nullable MobEffectList mobeffectlist1) { ++ { + byte b0 = 0; + + if (i >= 4 && mobeffectlist == mobeffectlist1) { + b0 = 1; + } + ++ return b0; ++ } ++ } ++ ++ private static int getLevel(int i) { ++ { + int j = (9 + i * 2) * 20; ++ return j; ++ } ++ } ++ ++ public static List getHumansInRange(World world, BlockPosition blockposition, int i) { ++ { ++ double d0 = (double) (i * 10 + 10); ++ + AxisAlignedBB axisalignedbb = (new AxisAlignedBB(blockposition)).inflate(d0).expandTowards(0.0D, (double) world.getHeight(), 0.0D); + List list = world.getEntitiesOfClass(EntityHuman.class, axisalignedbb); ++ ++ return list; ++ } ++ } ++ ++ private static void applyEffect(List list, MobEffectList mobeffectlist, int j, int b0) { ++ { + Iterator iterator = list.iterator(); + + EntityHuman entityhuman; + + while (iterator.hasNext()) { + entityhuman = (EntityHuman) iterator.next(); +- entityhuman.addEffect(new MobEffect(mobeffectlist, j, b0, true, true)); ++ entityhuman.addEffect(new MobEffect(mobeffectlist, j, b0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); + } ++ } ++ } + ++ private static boolean hasSecondaryEffect(int i, @Nullable MobEffectList mobeffectlist, @Nullable MobEffectList mobeffectlist1) { ++ { + if (i >= 4 && mobeffectlist != mobeffectlist1 && mobeffectlist1 != null) { +- iterator = list.iterator(); +- +- while (iterator.hasNext()) { +- entityhuman = (EntityHuman) iterator.next(); +- entityhuman.addEffect(new MobEffect(mobeffectlist1, j, 0, true, true)); +- } ++ return true; + } + ++ return false; ++ } ++ } ++ ++ private static void applyEffects(World world, BlockPosition blockposition, int i, @Nullable MobEffectList mobeffectlist, @Nullable MobEffectList mobeffectlist1) { ++ if (!world.isClientSide && mobeffectlist != null) { ++ double d0 = (double) (i * 10 + 10); ++ byte b0 = getAmplification(i, mobeffectlist, mobeffectlist1); ++ ++ int j = getLevel(i); ++ List list = getHumansInRange(world, blockposition, i); ++ ++ applyEffect(list, mobeffectlist, j, b0); ++ ++ if (hasSecondaryEffect(i, mobeffectlist, mobeffectlist1)) { ++ applyEffect(list, mobeffectlist1, j, 0); ++ } + } ++ + } ++ // CraftBukkit end + + public static void playSound(World world, BlockPosition blockposition, SoundEffect soundeffect) { + world.playSound((EntityHuman) null, blockposition, soundeffect, SoundCategory.BLOCKS, 1.0F, 1.0F); +@@ -312,7 +365,7 @@ + if (nbttagcompound.contains(s, 8)) { + MinecraftKey minecraftkey = MinecraftKey.tryParse(nbttagcompound.getString(s)); + +- return filterEffect((MobEffectList) BuiltInRegistries.MOB_EFFECT.get(minecraftkey)); ++ return (MobEffectList) BuiltInRegistries.MOB_EFFECT.get(minecraftkey); // CraftBukkit - persist manually set non-default beacon effects (SPIGOT-3598) + } else { + return null; + } +@@ -323,6 +376,7 @@ + super.load(nbttagcompound); + this.primaryPower = loadEffect(nbttagcompound, "primary_effect"); + this.secondaryPower = loadEffect(nbttagcompound, "secondary_effect"); ++ this.levels = nbttagcompound.getInt("Levels"); // CraftBukkit - SPIGOT-5053, use where available + if (nbttagcompound.contains("CustomName", 8)) { + this.name = IChatBaseComponent.ChatSerializer.fromJson(nbttagcompound.getString("CustomName")); + } diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityBeehive.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityBeehive.patch new file mode 100644 index 0000000000..706e9a6773 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityBeehive.patch @@ -0,0 +1,154 @@ +--- a/net/minecraft/world/level/block/entity/TileEntityBeehive.java ++++ b/net/minecraft/world/level/block/entity/TileEntityBeehive.java +@@ -43,6 +43,7 @@ + private final List stored = Lists.newArrayList(); + @Nullable + public BlockPosition savedFlowerPos; ++ public int maxBees = 3; // CraftBukkit - allow setting max amount of bees a hive can hold + + public TileEntityBeehive(BlockPosition blockposition, IBlockData iblockdata) { + super(TileEntityTypes.BEEHIVE, blockposition, iblockdata); +@@ -82,7 +83,7 @@ + } + + public boolean isFull() { +- return this.stored.size() == 3; ++ return this.stored.size() == this.maxBees; // CraftBukkit + } + + public void emptyAllLivingFromHive(@Nullable EntityHuman entityhuman, IBlockData iblockdata, TileEntityBeehive.ReleaseStatus tileentitybeehive_releasestatus) { +@@ -99,7 +100,7 @@ + + if (entityhuman.position().distanceToSqr(entity.position()) <= 16.0D) { + if (!this.isSedated()) { +- entitybee.setTarget(entityhuman); ++ entitybee.setTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit + } else { + entitybee.setStayOutOfHiveCountdown(400); + } +@@ -111,10 +112,16 @@ + } + + private List releaseAllOccupants(IBlockData iblockdata, TileEntityBeehive.ReleaseStatus tileentitybeehive_releasestatus) { ++ // CraftBukkit start - This allows us to bypass the night/rain/emergency check ++ return releaseBees(iblockdata, tileentitybeehive_releasestatus, false); ++ } ++ ++ public List releaseBees(IBlockData iblockdata, TileEntityBeehive.ReleaseStatus tileentitybeehive_releasestatus, boolean force) { + List list = Lists.newArrayList(); + + this.stored.removeIf((tileentitybeehive_hivebee) -> { +- return releaseOccupant(this.level, this.worldPosition, iblockdata, tileentitybeehive_hivebee, list, tileentitybeehive_releasestatus, this.savedFlowerPos); ++ return releaseBee(this.level, this.worldPosition, iblockdata, tileentitybeehive_hivebee, list, tileentitybeehive_releasestatus, this.savedFlowerPos, force); ++ // CraftBukkit end + }); + if (!list.isEmpty()) { + super.setChanged(); +@@ -142,7 +149,19 @@ + } + + public void addOccupantWithPresetTicks(Entity entity, boolean flag, int i) { +- if (this.stored.size() < 3) { ++ if (this.stored.size() < this.maxBees) { // CraftBukkit ++ // CraftBukkit start ++ if (this.level != null) { ++ org.bukkit.event.entity.EntityEnterBlockEvent event = new org.bukkit.event.entity.EntityEnterBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, getBlockPos())); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ if (entity instanceof EntityBee) { ++ ((EntityBee) entity).setStayOutOfHiveCountdown(400); ++ } ++ return; ++ } ++ } ++ // CraftBukkit end + entity.stopRiding(); + entity.ejectPassengers(); + NBTTagCompound nbttagcompound = new NBTTagCompound(); +@@ -174,7 +193,13 @@ + } + + private static boolean releaseOccupant(World world, BlockPosition blockposition, IBlockData iblockdata, TileEntityBeehive.HiveBee tileentitybeehive_hivebee, @Nullable List list, TileEntityBeehive.ReleaseStatus tileentitybeehive_releasestatus, @Nullable BlockPosition blockposition1) { +- if ((world.isNight() || world.isRaining()) && tileentitybeehive_releasestatus != TileEntityBeehive.ReleaseStatus.EMERGENCY) { ++ // CraftBukkit start - This allows us to bypass the night/rain/emergency check ++ return releaseBee(world, blockposition, iblockdata, tileentitybeehive_hivebee, list, tileentitybeehive_releasestatus, blockposition1, false); ++ } ++ ++ private static boolean releaseBee(World world, BlockPosition blockposition, IBlockData iblockdata, TileEntityBeehive.HiveBee tileentitybeehive_hivebee, @Nullable List list, TileEntityBeehive.ReleaseStatus tileentitybeehive_releasestatus, @Nullable BlockPosition blockposition1, boolean force) { ++ if (!force && (world.isNight() || world.isRaining()) && tileentitybeehive_releasestatus != TileEntityBeehive.ReleaseStatus.EMERGENCY) { ++ // CraftBukkit end + return false; + } else { + NBTTagCompound nbttagcompound = tileentitybeehive_hivebee.entityData.copy(); +@@ -197,6 +222,18 @@ + if (!entity.getType().is(TagsEntity.BEEHIVE_INHABITORS)) { + return false; + } else { ++ // CraftBukkit start ++ if (entity instanceof EntityBee) { ++ float f = entity.getBbWidth(); ++ double d0 = flag ? 0.0D : 0.55D + (double) (f / 2.0F); ++ double d1 = (double) blockposition.getX() + 0.5D + d0 * (double) enumdirection.getStepX(); ++ double d2 = (double) blockposition.getY() + 0.5D - (double) (entity.getBbHeight() / 2.0F); ++ double d3 = (double) blockposition.getZ() + 0.5D + d0 * (double) enumdirection.getStepZ(); ++ ++ entity.moveTo(d1, d2, d3, entity.getYRot(), entity.getXRot()); ++ } ++ if (!world.addFreshEntity(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BEEHIVE)) return false; // CraftBukkit - SpawnReason, moved from below ++ // CraftBukkit end + if (entity instanceof EntityBee) { + EntityBee entitybee = (EntityBee) entity; + +@@ -228,6 +265,7 @@ + list.add(entitybee); + } + ++ /* // CraftBukkit start + float f = entity.getBbWidth(); + double d0 = flag ? 0.0D : 0.55D + (double) (f / 2.0F); + double d1 = (double) blockposition.getX() + 0.5D + d0 * (double) enumdirection.getStepX(); +@@ -235,11 +273,12 @@ + double d3 = (double) blockposition.getZ() + 0.5D + d0 * (double) enumdirection.getStepZ(); + + entity.moveTo(d1, d2, d3, entity.getYRot(), entity.getXRot()); ++ */ // CraftBukkit end + } + + world.playSound((EntityHuman) null, blockposition, SoundEffects.BEEHIVE_EXIT, SoundCategory.BLOCKS, 1.0F, 1.0F); + world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.a.of(entity, world.getBlockState(blockposition))); +- return world.addFreshEntity(entity); ++ return true; // return this.world.addFreshEntity(entity); // CraftBukkit - moved up + } + } else { + return false; +@@ -288,6 +327,10 @@ + if (releaseOccupant(world, blockposition, iblockdata, tileentitybeehive_hivebee, (List) null, tileentitybeehive_releasestatus, blockposition1)) { + flag = true; + iterator.remove(); ++ // CraftBukkit start ++ } else { ++ tileentitybeehive_hivebee.ticksInHive = tileentitybeehive_hivebee.minOccupationTicks / 2; // Not strictly Vanilla behaviour in cases where bees cannot spawn but still reasonable ++ // CraftBukkit end + } + } + } +@@ -329,6 +372,11 @@ + this.savedFlowerPos = GameProfileSerializer.readBlockPos(nbttagcompound.getCompound("FlowerPos")); + } + ++ // CraftBukkit start ++ if (nbttagcompound.contains("Bukkit.MaxEntities")) { ++ this.maxBees = nbttagcompound.getInt("Bukkit.MaxEntities"); ++ } ++ // CraftBukkit end + } + + @Override +@@ -338,6 +386,7 @@ + if (this.hasSavedFlowerPos()) { + nbttagcompound.put("FlowerPos", GameProfileSerializer.writeBlockPos(this.savedFlowerPos)); + } ++ nbttagcompound.putInt("Bukkit.MaxEntities", this.maxBees); // CraftBukkit + + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityBell.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityBell.patch new file mode 100644 index 0000000000..c54d843b60 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityBell.patch @@ -0,0 +1,26 @@ +--- a/net/minecraft/world/level/block/entity/TileEntityBell.java ++++ b/net/minecraft/world/level/block/entity/TileEntityBell.java +@@ -120,7 +120,7 @@ + EntityLiving entityliving = (EntityLiving) iterator.next(); + + if (entityliving.isAlive() && !entityliving.isRemoved() && blockposition.closerToCenterThan(entityliving.position(), 32.0D)) { +- entityliving.getBrain().setMemory(MemoryModuleType.HEARD_BELL_TIME, (Object) this.level.getGameTime()); ++ entityliving.getBrain().setMemory(MemoryModuleType.HEARD_BELL_TIME, this.level.getGameTime()); // CraftBukkit - decompile error + } + } + } +@@ -144,9 +144,13 @@ + } + + private static void makeRaidersGlow(World world, BlockPosition blockposition, List list) { ++ List entities = // CraftBukkit + list.stream().filter((entityliving) -> { + return isRaiderWithinRange(blockposition, entityliving); +- }).forEach(TileEntityBell::glow); ++ }).map((entity) -> (org.bukkit.entity.LivingEntity) entity.getBukkitEntity()).collect(java.util.stream.Collectors.toCollection(java.util.ArrayList::new)); // CraftBukkit ++ ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBellResonateEvent(world, blockposition, entities).forEach(TileEntityBell::glow); ++ // CraftBukkit end + } + + private static void showBellParticles(World world, BlockPosition blockposition, List list) { diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityBrewingStand.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityBrewingStand.patch new file mode 100644 index 0000000000..ebdc6f2bab --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityBrewingStand.patch @@ -0,0 +1,152 @@ +--- a/net/minecraft/world/level/block/entity/TileEntityBrewingStand.java ++++ b/net/minecraft/world/level/block/entity/TileEntityBrewingStand.java +@@ -25,6 +25,20 @@ + import net.minecraft.world.level.block.BlockBrewingStand; + import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.event.block.BrewingStartEvent; ++import org.bukkit.event.inventory.BrewEvent; ++import org.bukkit.event.inventory.BrewingStandFuelEvent; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end ++ + public class TileEntityBrewingStand extends TileEntityContainer implements IWorldInventory { + + private static final int INGREDIENT_SLOT = 3; +@@ -42,6 +56,36 @@ + private Item ingredient; + public int fuel; + protected final IContainerProperties dataAccess; ++ // CraftBukkit start - add fields and methods ++ private int lastTick = MinecraftServer.currentTick; ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = 64; ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end + + public TileEntityBrewingStand(BlockPosition blockposition, IBlockData iblockdata) { + super(TileEntityTypes.BREWING_STAND, blockposition, iblockdata); +@@ -109,8 +153,19 @@ + ItemStack itemstack = (ItemStack) tileentitybrewingstand.items.get(4); + + if (tileentitybrewingstand.fuel <= 0 && itemstack.is(Items.BLAZE_POWDER)) { +- tileentitybrewingstand.fuel = 20; +- itemstack.shrink(1); ++ // CraftBukkit start ++ BrewingStandFuelEvent event = new BrewingStandFuelEvent(CraftBlock.at(world, blockposition), CraftItemStack.asCraftMirror(itemstack), 20); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ ++ tileentitybrewingstand.fuel = event.getFuelPower(); ++ if (tileentitybrewingstand.fuel > 0 && event.isConsuming()) { ++ itemstack.shrink(1); ++ } ++ // CraftBukkit end + setChanged(world, blockposition, iblockdata); + } + +@@ -118,12 +173,17 @@ + boolean flag1 = tileentitybrewingstand.brewTime > 0; + ItemStack itemstack1 = (ItemStack) tileentitybrewingstand.items.get(3); + ++ // CraftBukkit start - Use wall time instead of ticks for brewing ++ int elapsedTicks = MinecraftServer.currentTick - tileentitybrewingstand.lastTick; ++ tileentitybrewingstand.lastTick = MinecraftServer.currentTick; ++ + if (flag1) { +- --tileentitybrewingstand.brewTime; +- boolean flag2 = tileentitybrewingstand.brewTime == 0; ++ tileentitybrewingstand.brewTime -= elapsedTicks; ++ boolean flag2 = tileentitybrewingstand.brewTime <= 0; // == -> <= ++ // CraftBukkit end + + if (flag2 && flag) { +- doBrew(world, blockposition, tileentitybrewingstand.items); ++ doBrew(world, blockposition, tileentitybrewingstand.items, tileentitybrewingstand); // CraftBukkit + setChanged(world, blockposition, iblockdata); + } else if (!flag || !itemstack1.is(tileentitybrewingstand.ingredient)) { + tileentitybrewingstand.brewTime = 0; +@@ -131,7 +191,11 @@ + } + } else if (flag && tileentitybrewingstand.fuel > 0) { + --tileentitybrewingstand.fuel; +- tileentitybrewingstand.brewTime = 400; ++ // CraftBukkit start ++ BrewingStartEvent event = new BrewingStartEvent(CraftBlock.at(world, blockposition), CraftItemStack.asCraftMirror(itemstack1), 400); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ tileentitybrewingstand.brewTime = event.getTotalBrewTime(); // 400 -> event.getTotalBrewTime() ++ // CraftBukkit end + tileentitybrewingstand.ingredient = itemstack1.getItem(); + setChanged(world, blockposition, iblockdata); + } +@@ -187,11 +251,33 @@ + } + } + +- private static void doBrew(World world, BlockPosition blockposition, NonNullList nonnulllist) { ++ // CraftBukkit start ++ private static void doBrew(World world, BlockPosition blockposition, NonNullList nonnulllist, TileEntityBrewingStand tileentitybrewingstand) { + ItemStack itemstack = (ItemStack) nonnulllist.get(3); ++ InventoryHolder owner = tileentitybrewingstand.getOwner(); ++ List brewResults = new ArrayList<>(3); + + for (int i = 0; i < 3; ++i) { +- nonnulllist.set(i, PotionBrewer.mix(itemstack, (ItemStack) nonnulllist.get(i))); ++ brewResults.add(i, CraftItemStack.asCraftMirror(PotionBrewer.mix(itemstack, (ItemStack) nonnulllist.get(i)))); ++ } ++ ++ if (owner != null) { ++ BrewEvent event = new BrewEvent(CraftBlock.at(world, blockposition), (org.bukkit.inventory.BrewerInventory) owner.getInventory(), brewResults, tileentitybrewingstand.fuel); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end ++ ++ for (int i = 0; i < 3; ++i) { ++ // CraftBukkit start - validate index in case it is cleared by plugins ++ if (i < brewResults.size()) { ++ nonnulllist.set(i, CraftItemStack.asNMSCopy(brewResults.get(i))); ++ } else { ++ nonnulllist.set(i, ItemStack.EMPTY); ++ } ++ // CraftBukkit end + } + + itemstack.shrink(1); diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityCampfire.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityCampfire.patch new file mode 100644 index 0000000000..21a94892ef --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityCampfire.patch @@ -0,0 +1,51 @@ +--- a/net/minecraft/world/level/block/entity/TileEntityCampfire.java ++++ b/net/minecraft/world/level/block/entity/TileEntityCampfire.java +@@ -26,6 +26,14 @@ + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.block.BlockCookEvent; ++import org.bukkit.event.block.CampfireStartEvent; ++import org.bukkit.inventory.CampfireRecipe; ++// CraftBukkit end ++ + public class TileEntityCampfire extends TileEntity implements Clearable { + + private static final int BURN_COOL_SPEED = 2; +@@ -60,6 +68,20 @@ + }).orElse(itemstack); + + if (itemstack1.isItemEnabled(world.enabledFeatures())) { ++ // CraftBukkit start - fire BlockCookEvent ++ CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); ++ org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); ++ ++ BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(world, blockposition), source, result); ++ world.getCraftServer().getPluginManager().callEvent(blockCookEvent); ++ ++ if (blockCookEvent.isCancelled()) { ++ return; ++ } ++ ++ result = blockCookEvent.getResult(); ++ itemstack1 = CraftItemStack.asNMSCopy(result); ++ // CraftBukkit end + InventoryUtils.dropItemStack(world, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), itemstack1); + tileentitycampfire.items.set(i, ItemStack.EMPTY); + world.sendBlockUpdated(blockposition, iblockdata, iblockdata, 3); +@@ -172,7 +194,11 @@ + ItemStack itemstack1 = (ItemStack) this.items.get(j); + + if (itemstack1.isEmpty()) { +- this.cookingTime[j] = i; ++ // CraftBukkit start ++ CampfireStartEvent event = new CampfireStartEvent(CraftBlock.at(this.level,this.worldPosition), CraftItemStack.asCraftMirror(itemstack), (CampfireRecipe) getCookableRecipe(itemstack).get().toBukkitRecipe()); ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ this.cookingTime[j] = event.getTotalCookTime(); // i -> event.getTotalCookTime() ++ // CraftBukkit end + this.cookingProgress[j] = 0; + this.items.set(j, itemstack.split(1)); + this.level.gameEvent(GameEvent.BLOCK_CHANGE, this.getBlockPos(), GameEvent.a.of(entity, this.getBlockState())); diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityChest.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityChest.patch new file mode 100644 index 0000000000..1e541199dd --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityChest.patch @@ -0,0 +1,64 @@ +--- a/net/minecraft/world/level/block/entity/TileEntityChest.java ++++ b/net/minecraft/world/level/block/entity/TileEntityChest.java +@@ -23,6 +23,12 @@ + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.properties.BlockPropertyChestType; + ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class TileEntityChest extends TileEntityLootable implements LidBlockEntity { + + private static final int EVENT_SET_OPEN_COUNT = 1; +@@ -30,6 +36,36 @@ + public final ContainerOpenersCounter openersCounter; + private final ChestLidController chestLidController; + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ + protected TileEntityChest(TileEntityTypes tileentitytypes, BlockPosition blockposition, IBlockData iblockdata) { + super(tileentitytypes, blockposition, iblockdata); + this.items = NonNullList.withSize(27, ItemStack.EMPTY); +@@ -198,4 +234,11 @@ + + world.blockEvent(blockposition, block, 1, j); + } ++ ++ // CraftBukkit start ++ @Override ++ public boolean onlyOpCanSetNbt() { ++ return true; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityCommand.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityCommand.patch new file mode 100644 index 0000000000..76aef62fa6 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityCommand.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/level/block/entity/TileEntityCommand.java ++++ b/net/minecraft/world/level/block/entity/TileEntityCommand.java +@@ -20,6 +20,13 @@ + private boolean auto; + private boolean conditionMet; + private final CommandBlockListenerAbstract commandBlock = new CommandBlockListenerAbstract() { ++ // CraftBukkit start ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandListenerWrapper wrapper) { ++ return new org.bukkit.craftbukkit.command.CraftBlockCommandSender(wrapper, TileEntityCommand.this); ++ } ++ // CraftBukkit end ++ + @Override + public void setCommand(String s) { + super.setCommand(s); diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityConduit.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityConduit.patch new file mode 100644 index 0000000000..ed07d7116d --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityConduit.patch @@ -0,0 +1,39 @@ +--- a/net/minecraft/world/level/block/entity/TileEntityConduit.java ++++ b/net/minecraft/world/level/block/entity/TileEntityConduit.java +@@ -27,6 +27,11 @@ + import net.minecraft.world.phys.AxisAlignedBB; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class TileEntityConduit extends TileEntity { + + private static final int BLOCK_REFRESH_RATE = 2; +@@ -201,7 +206,7 @@ + EntityHuman entityhuman = (EntityHuman) iterator.next(); + + if (blockposition.closerThan(entityhuman.blockPosition(), (double) j) && entityhuman.isInWaterOrRain()) { +- entityhuman.addEffect(new MobEffect(MobEffects.CONDUIT_POWER, 260, 0, true, true)); ++ entityhuman.addEffect(new MobEffect(MobEffects.CONDUIT_POWER, 260, 0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONDUIT); // CraftBukkit + } + } + +@@ -230,8 +235,13 @@ + } + + if (tileentityconduit.destroyTarget != null) { +- world.playSound((EntityHuman) null, tileentityconduit.destroyTarget.getX(), tileentityconduit.destroyTarget.getY(), tileentityconduit.destroyTarget.getZ(), SoundEffects.CONDUIT_ATTACK_TARGET, SoundCategory.BLOCKS, 1.0F, 1.0F); +- tileentityconduit.destroyTarget.hurt(world.damageSources().magic(), 4.0F); ++ // CraftBukkit start ++ CraftEventFactory.blockDamage = CraftBlock.at(world, blockposition); ++ if (tileentityconduit.destroyTarget.hurt(world.damageSources().magic(), 4.0F)) { ++ world.playSound((EntityHuman) null, tileentityconduit.destroyTarget.getX(), tileentityconduit.destroyTarget.getY(), tileentityconduit.destroyTarget.getZ(), SoundEffects.CONDUIT_ATTACK_TARGET, SoundCategory.BLOCKS, 1.0F, 1.0F); ++ } ++ CraftEventFactory.blockDamage = null; ++ // CraftBukkit end + } + + if (entityliving != tileentityconduit.destroyTarget) { diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityContainer.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityContainer.patch new file mode 100644 index 0000000000..bb36a0fa74 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityContainer.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/level/block/entity/TileEntityContainer.java ++++ b/net/minecraft/world/level/block/entity/TileEntityContainer.java +@@ -89,4 +89,12 @@ + } + + protected abstract Container createMenu(int i, PlayerInventory playerinventory); ++ ++ // CraftBukkit start ++ @Override ++ public org.bukkit.Location getLocation() { ++ if (level == null) return null; ++ return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityDispenser.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityDispenser.patch new file mode 100644 index 0000000000..462f32c847 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityDispenser.patch @@ -0,0 +1,50 @@ +--- a/net/minecraft/world/level/block/entity/TileEntityDispenser.java ++++ b/net/minecraft/world/level/block/entity/TileEntityDispenser.java +@@ -13,11 +13,47 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start ++import java.util.List; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class TileEntityDispenser extends TileEntityLootable { + + public static final int CONTAINER_SIZE = 9; + private NonNullList items; + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ + protected TileEntityDispenser(TileEntityTypes tileentitytypes, BlockPosition blockposition, IBlockData iblockdata) { + super(tileentitytypes, blockposition, iblockdata); + this.items = NonNullList.withSize(9, ItemStack.EMPTY); diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityEndGateway.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityEndGateway.patch new file mode 100644 index 0000000000..6020597ac4 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityEndGateway.patch @@ -0,0 +1,62 @@ +--- a/net/minecraft/world/level/block/entity/TileEntityEndGateway.java ++++ b/net/minecraft/world/level/block/entity/TileEntityEndGateway.java +@@ -33,6 +33,14 @@ + import net.minecraft.world.phys.Vec3D; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.world.level.dimension.WorldDimension; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.player.PlayerTeleportEvent; ++// CraftBukkit end ++ + public class TileEntityEndGateway extends TileEntityEnderPortal { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -169,7 +177,7 @@ + tileentityendgateway.teleportCooldown = 100; + BlockPosition blockposition1; + +- if (tileentityendgateway.exitPortal == null && world.dimension() == World.END) { ++ if (tileentityendgateway.exitPortal == null && world.getTypeKey() == WorldDimension.END) { // CraftBukkit - work in alternate worlds + blockposition1 = findOrCreateValidTeleportPos(worldserver, blockposition); + blockposition1 = blockposition1.above(10); + TileEntityEndGateway.LOGGER.debug("Creating portal at {}", blockposition1); +@@ -198,8 +206,34 @@ + entity1 = entity.getRootVehicle(); + } + ++ // CraftBukkit start - Fire PlayerTeleportEvent/EntityTeleportEvent ++ if (entity1 instanceof EntityPlayer) { ++ org.bukkit.craftbukkit.entity.CraftPlayer player = (CraftPlayer) entity1.getBukkitEntity(); ++ org.bukkit.Location location = CraftLocation.toBukkit(blockposition1, world.getWorld()).add(0.5D, 0.5D, 0.5D); ++ location.setPitch(player.getLocation().getPitch()); ++ location.setYaw(player.getLocation().getYaw()); ++ ++ PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.END_GATEWAY); ++ Bukkit.getPluginManager().callEvent(teleEvent); ++ if (teleEvent.isCancelled()) { ++ return; ++ } ++ ++ entity1.setPortalCooldown(); ++ ((EntityPlayer) entity1).connection.teleport(teleEvent.getTo()); ++ triggerCooldown(world, blockposition, iblockdata, tileentityendgateway); // CraftBukkit - call at end of method ++ return; ++ ++ } ++ ++ org.bukkit.event.entity.EntityTeleportEvent teleEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTeleportEvent(entity1, blockposition1.getX() + 0.5, blockposition1.getY() + 0.5, blockposition1.getZ() + 0.5); ++ if (teleEvent.isCancelled()) { ++ return; ++ } ++ + entity1.setPortalCooldown(); +- entity1.teleportToWithTicket((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY(), (double) blockposition1.getZ() + 0.5D); ++ entity1.teleportToWithTicket(teleEvent.getTo().getX(), teleEvent.getTo().getY(), teleEvent.getTo().getZ()); ++ // CraftBukkit end + } + + triggerCooldown(world, blockposition, iblockdata, tileentityendgateway); diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityFurnace.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityFurnace.patch new file mode 100644 index 0000000000..a23e69cbf8 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityFurnace.patch @@ -0,0 +1,243 @@ +--- a/net/minecraft/world/level/block/entity/TileEntityFurnace.java ++++ b/net/minecraft/world/level/block/entity/TileEntityFurnace.java +@@ -47,6 +47,20 @@ + import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.block.BlockExpEvent; ++import org.bukkit.event.inventory.FurnaceBurnEvent; ++import org.bukkit.event.inventory.FurnaceExtractEvent; ++import org.bukkit.event.inventory.FurnaceSmeltEvent; ++import org.bukkit.event.inventory.FurnaceStartSmeltEvent; ++import org.bukkit.inventory.CookingRecipe; ++// CraftBukkit end ++ + public abstract class TileEntityFurnace extends TileEntityContainer implements IWorldInventory, RecipeCraftingHolder, AutoRecipeOutput { + + protected static final int SLOT_INPUT = 0; +@@ -115,7 +129,7 @@ + } + }; + this.recipesUsed = new Object2IntOpenHashMap(); +- this.quickCheck = CraftingManager.createCheck(recipes); ++ this.quickCheck = CraftingManager.createCheck((Recipes) recipes); // CraftBukkit - decompile error // Eclipse fail + } + + public static Map getFuel() { +@@ -183,6 +197,40 @@ + return map; + } + ++ // CraftBukkit start - add fields and methods ++ private int maxStack = MAX_STACK; ++ public List transaction = new java.util.ArrayList(); ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ public Object2IntOpenHashMap getRecipesUsed() { ++ return this.recipesUsed; // PAIL private -> public ++ } ++ // CraftBukkit end ++ + private static boolean isNeverAFurnaceFuel(Item item) { + return item.builtInRegistryHolder().is(TagsItem.NON_FLAMMABLE_WOOD); + } +@@ -271,7 +319,7 @@ + RecipeHolder recipeholder; + + if (flag2) { +- recipeholder = (RecipeHolder) tileentityfurnace.quickCheck.getRecipeFor(tileentityfurnace, world).orElse((Object) null); ++ recipeholder = (RecipeHolder) tileentityfurnace.quickCheck.getRecipeFor(tileentityfurnace, world).orElse(null); // CraftBukkit - decompile error + } else { + recipeholder = null; + } +@@ -279,9 +327,20 @@ + int i = tileentityfurnace.getMaxStackSize(); + + if (!tileentityfurnace.isLit() && canBurn(world.registryAccess(), recipeholder, tileentityfurnace.items, i)) { +- tileentityfurnace.litTime = tileentityfurnace.getBurnDuration(itemstack); ++ // CraftBukkit start ++ CraftItemStack fuel = CraftItemStack.asCraftMirror(itemstack); ++ ++ FurnaceBurnEvent furnaceBurnEvent = new FurnaceBurnEvent(CraftBlock.at(world, blockposition), fuel, tileentityfurnace.getBurnDuration(itemstack)); ++ world.getCraftServer().getPluginManager().callEvent(furnaceBurnEvent); ++ ++ if (furnaceBurnEvent.isCancelled()) { ++ return; ++ } ++ ++ tileentityfurnace.litTime = furnaceBurnEvent.getBurnTime(); + tileentityfurnace.litDuration = tileentityfurnace.litTime; +- if (tileentityfurnace.isLit()) { ++ if (tileentityfurnace.isLit() && furnaceBurnEvent.isBurning()) { ++ // CraftBukkit end + flag1 = true; + if (flag3) { + Item item = itemstack.getItem(); +@@ -297,11 +356,23 @@ + } + + if (tileentityfurnace.isLit() && canBurn(world.registryAccess(), recipeholder, tileentityfurnace.items, i)) { ++ // CraftBukkit start ++ if (recipeholder != null && tileentityfurnace.cookingProgress == 0) { ++ CraftItemStack source = CraftItemStack.asCraftMirror(tileentityfurnace.items.get(0)); ++ CookingRecipe recipe = (CookingRecipe) recipeholder.toBukkitRecipe(); ++ ++ FurnaceStartSmeltEvent event = new FurnaceStartSmeltEvent(CraftBlock.at(world, blockposition), source, recipe); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ tileentityfurnace.cookingTotalTime = event.getTotalCookTime(); ++ } ++ // CraftBukkit end ++ + ++tileentityfurnace.cookingProgress; + if (tileentityfurnace.cookingProgress == tileentityfurnace.cookingTotalTime) { + tileentityfurnace.cookingProgress = 0; + tileentityfurnace.cookingTotalTime = getTotalCookTime(world, tileentityfurnace); +- if (burn(world.registryAccess(), recipeholder, tileentityfurnace.items, i)) { ++ if (burn(tileentityfurnace.level, tileentityfurnace.worldPosition, world.registryAccess(), recipeholder, tileentityfurnace.items, i)) { // CraftBukkit + tileentityfurnace.setRecipeUsed(recipeholder); + } + +@@ -340,17 +411,44 @@ + } + } + +- private static boolean burn(IRegistryCustom iregistrycustom, @Nullable RecipeHolder recipeholder, NonNullList nonnulllist, int i) { ++ private static boolean burn(World world, BlockPosition blockposition, IRegistryCustom iregistrycustom, @Nullable RecipeHolder recipeholder, NonNullList nonnulllist, int i) { // CraftBukkit + if (recipeholder != null && canBurn(iregistrycustom, recipeholder, nonnulllist, i)) { + ItemStack itemstack = (ItemStack) nonnulllist.get(0); + ItemStack itemstack1 = recipeholder.value().getResultItem(iregistrycustom); + ItemStack itemstack2 = (ItemStack) nonnulllist.get(2); + ++ // CraftBukkit start - fire FurnaceSmeltEvent ++ CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); ++ org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); ++ ++ FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(CraftBlock.at(world, blockposition), source, result); ++ world.getCraftServer().getPluginManager().callEvent(furnaceSmeltEvent); ++ ++ if (furnaceSmeltEvent.isCancelled()) { ++ return false; ++ } ++ ++ result = furnaceSmeltEvent.getResult(); ++ itemstack1 = CraftItemStack.asNMSCopy(result); ++ ++ if (!itemstack1.isEmpty()) { ++ if (itemstack2.isEmpty()) { ++ nonnulllist.set(2, itemstack1.copy()); ++ } else if (CraftItemStack.asCraftMirror(itemstack2).isSimilar(result)) { ++ itemstack2.grow(itemstack1.getCount()); ++ } else { ++ return false; ++ } ++ } ++ ++ /* + if (itemstack2.isEmpty()) { + nonnulllist.set(2, itemstack1.copy()); + } else if (itemstack2.is(itemstack1.getItem())) { + itemstack2.grow(1); + } ++ */ ++ // CraftBukkit end + + if (itemstack.is(Blocks.WET_SPONGE.asItem()) && !((ItemStack) nonnulllist.get(1)).isEmpty() && ((ItemStack) nonnulllist.get(1)).is(Items.BUCKET)) { + nonnulllist.set(1, new ItemStack(Items.WATER_BUCKET)); +@@ -374,6 +472,7 @@ + } + + private static int getTotalCookTime(World world, TileEntityFurnace tileentityfurnace) { ++ if (world == null) return 200; // CraftBukkit - SPIGOT-4302 + return (Integer) tileentityfurnace.quickCheck.getRecipeFor(tileentityfurnace, world).map((recipeholder) -> { + return ((RecipeCooking) recipeholder.value()).getCookingTime(); + }).orElse(200); +@@ -495,8 +594,8 @@ + @Override + public void awardUsedRecipes(EntityHuman entityhuman, List list) {} + +- public void awardUsedRecipesAndPopExperience(EntityPlayer entityplayer) { +- List> list = this.getRecipesToAwardAndPopExperience(entityplayer.serverLevel(), entityplayer.position()); ++ public void awardUsedRecipesAndPopExperience(EntityPlayer entityplayer, ItemStack itemstack, int amount) { // CraftBukkit ++ List> list = this.getRecipesToAwardAndPopExperience(entityplayer.serverLevel(), entityplayer.position(), this.worldPosition, entityplayer, itemstack, amount); // CraftBukkit + + entityplayer.awardRecipes(list); + Iterator iterator = list.iterator(); +@@ -513,6 +612,12 @@ + } + + public List> getRecipesToAwardAndPopExperience(WorldServer worldserver, Vec3D vec3d) { ++ // CraftBukkit start ++ return this.getRecipesToAwardAndPopExperience(worldserver, vec3d, this.worldPosition, null, null, 0); ++ } ++ ++ public List> getRecipesToAwardAndPopExperience(WorldServer worldserver, Vec3D vec3d, BlockPosition blockposition, EntityPlayer entityplayer, ItemStack itemstack, int amount) { ++ // CraftBukkit end + List> list = Lists.newArrayList(); + ObjectIterator objectiterator = this.recipesUsed.object2IntEntrySet().iterator(); + +@@ -521,14 +626,14 @@ + + worldserver.getRecipeManager().byKey((MinecraftKey) entry.getKey()).ifPresent((recipeholder) -> { + list.add(recipeholder); +- createExperience(worldserver, vec3d, entry.getIntValue(), ((RecipeCooking) recipeholder.value()).getExperience()); ++ createExperience(worldserver, vec3d, entry.getIntValue(), ((RecipeCooking) recipeholder.value()).getExperience(), blockposition, entityplayer, itemstack, amount); // CraftBukkit + }); + } + + return list; + } + +- private static void createExperience(WorldServer worldserver, Vec3D vec3d, int i, float f) { ++ private static void createExperience(WorldServer worldserver, Vec3D vec3d, int i, float f, BlockPosition blockposition, EntityHuman entityhuman, ItemStack itemstack, int amount) { // CraftBukkit + int j = MathHelper.floor((float) i * f); + float f1 = MathHelper.frac((float) i * f); + +@@ -536,6 +641,17 @@ + ++j; + } + ++ // CraftBukkit start - fire FurnaceExtractEvent / BlockExpEvent ++ BlockExpEvent event; ++ if (amount != 0) { ++ event = new FurnaceExtractEvent((Player) entityhuman.getBukkitEntity(), CraftBlock.at(worldserver, blockposition), org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(itemstack.getItem()), amount, j); ++ } else { ++ event = new BlockExpEvent(CraftBlock.at(worldserver, blockposition), j); ++ } ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ j = event.getExpToDrop(); ++ // CraftBukkit end ++ + EntityExperienceOrb.award(worldserver, vec3d, j); + } + diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityHopper.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityHopper.patch new file mode 100644 index 0000000000..31cee6b138 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityHopper.patch @@ -0,0 +1,204 @@ +--- a/net/minecraft/world/level/block/entity/TileEntityHopper.java ++++ b/net/minecraft/world/level/block/entity/TileEntityHopper.java +@@ -32,6 +32,21 @@ + import net.minecraft.world.phys.shapes.OperatorBoolean; + import net.minecraft.world.phys.shapes.VoxelShapes; + ++// CraftBukkit start ++import net.minecraft.world.InventoryLargeChest; ++import net.minecraft.world.entity.vehicle.EntityMinecartHopper; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.inventory.CraftInventory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.event.inventory.HopperInventorySearchEvent; ++import org.bukkit.event.inventory.InventoryMoveItemEvent; ++import org.bukkit.event.inventory.InventoryPickupItemEvent; ++import org.bukkit.inventory.Inventory; ++// CraftBukkit end ++ + public class TileEntityHopper extends TileEntityLootable implements IHopper { + + public static final int MOVE_ITEM_SPEED = 8; +@@ -40,6 +55,36 @@ + private int cooldownTime; + private long tickedGameTime; + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ ++ public List getContents() { ++ return this.items; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ + public TileEntityHopper(BlockPosition blockposition, IBlockData iblockdata) { + super(TileEntityTypes.HOPPER, blockposition, iblockdata); + this.items = NonNullList.withSize(5, ItemStack.EMPTY); +@@ -113,7 +158,7 @@ + boolean flag = false; + + if (!tileentityhopper.isEmpty()) { +- flag = ejectItems(world, blockposition, iblockdata, tileentityhopper); ++ flag = ejectItems(world, blockposition, iblockdata, (IInventory) tileentityhopper, tileentityhopper); // CraftBukkit + } + + if (!tileentityhopper.inventoryFull()) { +@@ -147,7 +192,7 @@ + return false; + } + +- private static boolean ejectItems(World world, BlockPosition blockposition, IBlockData iblockdata, IInventory iinventory) { ++ private static boolean ejectItems(World world, BlockPosition blockposition, IBlockData iblockdata, IInventory iinventory, TileEntityHopper hopper) { // CraftBukkit + IInventory iinventory1 = getAttachedContainer(world, blockposition, iblockdata); + + if (iinventory1 == null) { +@@ -161,7 +206,30 @@ + for (int i = 0; i < iinventory.getContainerSize(); ++i) { + if (!iinventory.getItem(i).isEmpty()) { + ItemStack itemstack = iinventory.getItem(i).copy(); +- ItemStack itemstack1 = addItem(iinventory, iinventory1, iinventory.removeItem(i, 1), enumdirection); ++ // ItemStack itemstack1 = addItem(iinventory, iinventory1, iinventory.removeItem(i, 1), enumdirection); ++ ++ // CraftBukkit start - Call event when pushing items into other inventories ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.removeItem(i, 1)); ++ ++ Inventory destinationInventory; ++ // Have to special case large chests as they work oddly ++ if (iinventory1 instanceof InventoryLargeChest) { ++ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory1); ++ } else if (iinventory1.getOwner() != null) { ++ destinationInventory = iinventory1.getOwner().getInventory(); ++ } else { ++ destinationInventory = new CraftInventory(iinventory); ++ } ++ ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(iinventory.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ hopper.setItem(i, itemstack); ++ hopper.setCooldown(8); // Delay hopper checks ++ return false; ++ } ++ ItemStack itemstack1 = addItem(iinventory, iinventory1, CraftItemStack.asNMSCopy(event.getItem()), enumdirection); ++ // CraftBukkit end + + if (itemstack1.isEmpty()) { + iinventory1.setChanged(); +@@ -226,7 +294,34 @@ + + if (!itemstack.isEmpty() && canTakeItemFromContainer(ihopper, iinventory, itemstack, i, enumdirection)) { + ItemStack itemstack1 = itemstack.copy(); +- ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.removeItem(i, 1), (EnumDirection) null); ++ // ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.removeItem(i, 1), (EnumDirection) null); ++ // CraftBukkit start - Call event on collection of items from inventories into the hopper ++ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.removeItem(i, 1)); ++ ++ Inventory sourceInventory; ++ // Have to special case large chests as they work oddly ++ if (iinventory instanceof InventoryLargeChest) { ++ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory); ++ } else if (iinventory.getOwner() != null) { ++ sourceInventory = iinventory.getOwner().getInventory(); ++ } else { ++ sourceInventory = new CraftInventory(iinventory); ++ } ++ ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack.clone(), ihopper.getOwner().getInventory(), false); ++ ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ iinventory.setItem(i, itemstack1); ++ ++ if (ihopper instanceof TileEntityHopper) { ++ ((TileEntityHopper) ihopper).setCooldown(8); // Delay hopper checks ++ } ++ ++ return false; ++ } ++ ItemStack itemstack2 = addItem(iinventory, ihopper, CraftItemStack.asNMSCopy(event.getItem()), null); ++ // CraftBukkit end + + if (itemstack2.isEmpty()) { + iinventory.setChanged(); +@@ -241,6 +336,13 @@ + + public static boolean addItem(IInventory iinventory, EntityItem entityitem) { + boolean flag = false; ++ // CraftBukkit start ++ InventoryPickupItemEvent event = new InventoryPickupItemEvent(iinventory.getOwner().getInventory(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ entityitem.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end + ItemStack itemstack = entityitem.getItem().copy(); + ItemStack itemstack1 = addItem((IInventory) null, iinventory, itemstack, (EnumDirection) null); + +@@ -367,16 +469,40 @@ + return itemstack; + } + ++ // CraftBukkit start ++ @Nullable ++ private static IInventory runHopperInventorySearchEvent(IInventory inventory, CraftBlock hopper, CraftBlock searchLocation, HopperInventorySearchEvent.ContainerType containerType) { ++ HopperInventorySearchEvent event = new HopperInventorySearchEvent((inventory != null) ? new CraftInventory(inventory) : null, containerType, hopper, searchLocation); ++ Bukkit.getServer().getPluginManager().callEvent(event); ++ CraftInventory craftInventory = (CraftInventory) event.getInventory(); ++ return (craftInventory != null) ? craftInventory.getInventory() : null; ++ } ++ // CraftBukkit end ++ + @Nullable + private static IInventory getAttachedContainer(World world, BlockPosition blockposition, IBlockData iblockdata) { + EnumDirection enumdirection = (EnumDirection) iblockdata.getValue(BlockHopper.FACING); + +- return getContainerAt(world, blockposition.relative(enumdirection)); ++ // CraftBukkit start ++ BlockPosition searchPosition = blockposition.relative(enumdirection); ++ IInventory inventory = getContainerAt(world, blockposition.relative(enumdirection)); ++ ++ CraftBlock hopper = CraftBlock.at(world, blockposition); ++ CraftBlock searchBlock = CraftBlock.at(world, searchPosition); ++ return runHopperInventorySearchEvent(inventory, hopper, searchBlock, HopperInventorySearchEvent.ContainerType.DESTINATION); ++ // CraftBukkit end + } + + @Nullable + private static IInventory getSourceContainer(World world, IHopper ihopper) { +- return getContainerAt(world, ihopper.getLevelX(), ihopper.getLevelY() + 1.0D, ihopper.getLevelZ()); ++ // CraftBukkit start ++ IInventory inventory = getContainerAt(world, ihopper.getLevelX(), ihopper.getLevelY() + 1.0D, ihopper.getLevelZ()); ++ ++ BlockPosition blockPosition = BlockPosition.containing(ihopper.getLevelX(), ihopper.getLevelY(), ihopper.getLevelZ()); ++ CraftBlock hopper = CraftBlock.at(world, blockPosition); ++ CraftBlock container = CraftBlock.at(world, blockPosition.above()); ++ return runHopperInventorySearchEvent(inventory, hopper, container, HopperInventorySearchEvent.ContainerType.SOURCE); ++ // CraftBukkit end + } + + public static List getItemsAtAndAbove(World world, IHopper ihopper) { diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityJukeBox.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityJukeBox.patch new file mode 100644 index 0000000000..9276a5ca06 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityJukeBox.patch @@ -0,0 +1,82 @@ +--- a/net/minecraft/world/level/block/entity/TileEntityJukeBox.java ++++ b/net/minecraft/world/level/block/entity/TileEntityJukeBox.java +@@ -22,6 +22,14 @@ + import net.minecraft.world.phys.Vec3D; + import net.minecraft.world.ticks.ContainerSingleItem; + ++// CraftBukkit start ++import java.util.Collections; ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class TileEntityJukeBox extends TileEntity implements Clearable, ContainerSingleItem { + + private static final int SONG_END_PADDING = 20; +@@ -30,6 +38,42 @@ + public long tickCount; + public long recordStartedTick; + public boolean isPlaying; ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ public boolean opened; ++ ++ @Override ++ public List getContents() { ++ return Collections.singletonList(item); ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return new org.bukkit.Location(level.getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ } ++ // CraftBukkit end + + public TileEntityJukeBox(BlockPosition blockposition, IBlockData iblockdata) { + super(TileEntityTypes.JUKEBOX, blockposition, iblockdata); +@@ -150,7 +194,7 @@ + + @Override + public int getMaxStackSize() { +- return 1; ++ return maxStack; // CraftBukkit + } + + @Override +@@ -203,7 +247,11 @@ + @VisibleForTesting + public void setRecordWithoutPlaying(ItemStack itemstack) { + this.item = itemstack; +- this.level.updateNeighborsAt(this.getBlockPos(), this.getBlockState().getBlock()); ++ // CraftBukkit start - add null check for level ++ if (level != null) { ++ this.level.updateNeighborsAt(this.getBlockPos(), this.getBlockState().getBlock()); ++ } ++ // CraftBukkit end + this.setChanged(); + } + } diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityLectern.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityLectern.patch new file mode 100644 index 0000000000..f74e6f4cca --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityLectern.patch @@ -0,0 +1,161 @@ +--- a/net/minecraft/world/level/block/entity/TileEntityLectern.java ++++ b/net/minecraft/world/level/block/entity/TileEntityLectern.java +@@ -25,13 +25,72 @@ + import net.minecraft.world.phys.Vec2F; + import net.minecraft.world.phys.Vec3D; + +-public class TileEntityLectern extends TileEntity implements Clearable, ITileInventory { ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.List; ++import org.bukkit.Location; ++import org.bukkit.block.Lectern; ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.inventory.InventoryHolder; ++// CraftBukkit end ++ ++public class TileEntityLectern extends TileEntity implements Clearable, ITileInventory, ICommandListener { // CraftBukkit - ICommandListener + + public static final int DATA_PAGE = 0; + public static final int NUM_DATA = 1; + public static final int SLOT_BOOK = 0; + public static final int NUM_SLOTS = 1; +- public final IInventory bookAccess = new IInventory() { ++ // CraftBukkit start - add fields and methods ++ public final IInventory bookAccess = new LecternInventory(); ++ public class LecternInventory implements IInventory { ++ ++ public List transaction = new ArrayList<>(); ++ private int maxStack = 1; ++ ++ @Override ++ public List getContents() { ++ return Arrays.asList(book); ++ } ++ ++ @Override ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ @Override ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ @Override ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public void setMaxStackSize(int i) { ++ maxStack = i; ++ } ++ ++ @Override ++ public Location getLocation() { ++ if (level == null) return null; ++ return CraftLocation.toBukkit(worldPosition, level.getWorld()); ++ } ++ ++ @Override ++ public InventoryHolder getOwner() { ++ return (Lectern) TileEntityLectern.this.getOwner(); ++ } ++ ++ public TileEntityLectern getLectern() { ++ return TileEntityLectern.this; ++ } ++ // CraftBukkit end ++ + @Override + public int getContainerSize() { + return 1; +@@ -76,11 +135,20 @@ + } + + @Override +- public void setItem(int i, ItemStack itemstack) {} ++ // CraftBukkit start ++ public void setItem(int i, ItemStack itemstack) { ++ if (i == 0) { ++ TileEntityLectern.this.setBook(itemstack); ++ if (TileEntityLectern.this.getLevel() != null) { ++ BlockLectern.resetBookState(null, TileEntityLectern.this.getLevel(), TileEntityLectern.this.getBlockPos(), TileEntityLectern.this.getBlockState(), TileEntityLectern.this.hasBook()); ++ } ++ } ++ } ++ // CraftBukkit end + + @Override + public int getMaxStackSize() { +- return 1; ++ return maxStack; // CraftBukkit + } + + @Override +@@ -160,7 +228,7 @@ + if (j != this.page) { + this.page = j; + this.setChanged(); +- BlockLectern.signalPageChange(this.getLevel(), this.getBlockPos(), this.getBlockState()); ++ if (this.level != null) BlockLectern.signalPageChange(this.getLevel(), this.getBlockPos(), this.getBlockState()); // CraftBukkit + } + + } +@@ -183,6 +251,32 @@ + return itemstack; + } + ++ // CraftBukkit start ++ @Override ++ public void sendSystemMessage(IChatBaseComponent ichatbasecomponent) { ++ } ++ ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandListenerWrapper wrapper) { ++ return wrapper.getEntity() != null ? wrapper.getEntity().getBukkitSender(wrapper) : new org.bukkit.craftbukkit.command.CraftBlockCommandSender(wrapper, this); ++ } ++ ++ @Override ++ public boolean acceptsSuccess() { ++ return false; ++ } ++ ++ @Override ++ public boolean acceptsFailure() { ++ return false; ++ } ++ ++ @Override ++ public boolean shouldInformAdmins() { ++ return false; ++ } ++ ++ // CraftBukkit end + private CommandListenerWrapper createCommandSourceStack(@Nullable EntityHuman entityhuman) { + String s; + Object object; +@@ -197,7 +291,8 @@ + + Vec3D vec3d = Vec3D.atCenterOf(this.worldPosition); + +- return new CommandListenerWrapper(ICommandListener.NULL, vec3d, Vec2F.ZERO, (WorldServer) this.level, 2, s, (IChatBaseComponent) object, this.level.getServer(), entityhuman); ++ // CraftBukkit - this ++ return new CommandListenerWrapper(this, vec3d, Vec2F.ZERO, (WorldServer) this.level, 2, s, (IChatBaseComponent) object, this.level.getServer(), entityhuman); + } + + @Override +@@ -235,7 +330,7 @@ + + @Override + public Container createMenu(int i, PlayerInventory playerinventory, EntityHuman entityhuman) { +- return new ContainerLectern(i, this.bookAccess, this.dataAccess); ++ return new ContainerLectern(i, this.bookAccess, this.dataAccess, playerinventory); // CraftBukkit + } + + @Override diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityShulkerBox.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityShulkerBox.patch new file mode 100644 index 0000000000..56eb39fb56 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntityShulkerBox.patch @@ -0,0 +1,68 @@ +--- a/net/minecraft/world/level/block/entity/TileEntityShulkerBox.java ++++ b/net/minecraft/world/level/block/entity/TileEntityShulkerBox.java +@@ -32,6 +32,11 @@ + import net.minecraft.world.phys.AxisAlignedBB; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.entity.CraftHumanEntity; ++import org.bukkit.entity.HumanEntity; ++// CraftBukkit end ++ + public class TileEntityShulkerBox extends TileEntityLootable implements IWorldInventory { + + public static final int COLUMNS = 9; +@@ -51,6 +56,37 @@ + @Nullable + private final EnumColor color; + ++ // CraftBukkit start - add fields and methods ++ public List transaction = new java.util.ArrayList(); ++ private int maxStack = MAX_STACK; ++ public boolean opened; ++ ++ public List getContents() { ++ return this.itemStacks; ++ } ++ ++ public void onOpen(CraftHumanEntity who) { ++ transaction.add(who); ++ } ++ ++ public void onClose(CraftHumanEntity who) { ++ transaction.remove(who); ++ } ++ ++ public List getViewers() { ++ return transaction; ++ } ++ ++ @Override ++ public int getMaxStackSize() { ++ return maxStack; ++ } ++ ++ public void setMaxStackSize(int size) { ++ maxStack = size; ++ } ++ // CraftBukkit end ++ + public TileEntityShulkerBox(@Nullable EnumColor enumcolor, BlockPosition blockposition, IBlockData iblockdata) { + super(TileEntityTypes.SHULKER_BOX, blockposition, iblockdata); + this.itemStacks = NonNullList.withSize(27, ItemStack.EMPTY); +@@ -172,6 +208,7 @@ + } + + ++this.openCount; ++ if (opened) return; // CraftBukkit - only animate if the ShulkerBox hasn't been forced open already by an API call. + this.level.blockEvent(this.worldPosition, this.getBlockState().getBlock(), 1, this.openCount); + if (this.openCount == 1) { + this.level.gameEvent((Entity) entityhuman, GameEvent.CONTAINER_OPEN, this.worldPosition); +@@ -185,6 +222,7 @@ + public void stopOpen(EntityHuman entityhuman) { + if (!this.remove && !entityhuman.isSpectator()) { + --this.openCount; ++ if (opened) return; // CraftBukkit - only animate if the ShulkerBox hasn't been forced open already by an API call. + this.level.blockEvent(this.worldPosition, this.getBlockState().getBlock(), 1, this.openCount); + if (this.openCount <= 0) { + this.level.gameEvent((Entity) entityhuman, GameEvent.CONTAINER_CLOSE, this.worldPosition); diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntitySign.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntitySign.patch new file mode 100644 index 0000000000..84e9fa6536 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntitySign.patch @@ -0,0 +1,153 @@ +--- a/net/minecraft/world/level/block/entity/TileEntitySign.java ++++ b/net/minecraft/world/level/block/entity/TileEntitySign.java +@@ -33,7 +33,17 @@ + import net.minecraft.world.phys.Vec3D; + import org.slf4j.Logger; + +-public class TileEntitySign extends TileEntity { ++// CraftBukkit start ++import net.minecraft.nbt.NBTBase; ++import net.minecraft.server.level.EntityPlayer; ++import org.bukkit.block.sign.Side; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++import org.bukkit.entity.Player; ++import org.bukkit.event.block.SignChangeEvent; ++// CraftBukkit end ++ ++public class TileEntitySign extends TileEntity implements ICommandListener { // CraftBukkit - implements + + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int MAX_TEXT_LINE_WIDTH = 90; +@@ -98,7 +108,7 @@ + @Override + protected void saveAdditional(NBTTagCompound nbttagcompound) { + super.saveAdditional(nbttagcompound); +- DataResult dataresult = SignText.DIRECT_CODEC.encodeStart(DynamicOpsNBT.INSTANCE, this.frontText); ++ DataResult dataresult = SignText.DIRECT_CODEC.encodeStart(DynamicOpsNBT.INSTANCE, this.frontText); // CraftBukkit - decompile error + Logger logger = TileEntitySign.LOGGER; + + Objects.requireNonNull(logger); +@@ -117,7 +127,7 @@ + @Override + public void load(NBTTagCompound nbttagcompound) { + super.load(nbttagcompound); +- DataResult dataresult; ++ DataResult dataresult; // CraftBukkit - decompile error + Logger logger; + + if (nbttagcompound.contains("front_text")) { +@@ -171,12 +181,13 @@ + public void updateSignText(EntityHuman entityhuman, boolean flag, List list) { + if (!this.isWaxed() && entityhuman.getUUID().equals(this.getPlayerWhoMayEdit()) && this.level != null) { + this.updateText((signtext) -> { +- return this.setMessages(entityhuman, list, signtext); ++ return this.setMessages(entityhuman, list, signtext, flag); // CraftBukkit + }, flag); + this.setAllowedPlayerEditor((UUID) null); + this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3); + } else { + TileEntitySign.LOGGER.warn("Player {} just tried to change non-editable sign", entityhuman.getName().getString()); ++ ((EntityPlayer) entityhuman).connection.send(this.getUpdatePacket()); // CraftBukkit + } + } + +@@ -186,7 +197,8 @@ + return this.setText((SignText) unaryoperator.apply(signtext), flag); + } + +- private SignText setMessages(EntityHuman entityhuman, List list, SignText signtext) { ++ private SignText setMessages(EntityHuman entityhuman, List list, SignText signtext, boolean front) { // CraftBukkit ++ SignText originalText = signtext; // CraftBukkit + for (int i = 0; i < list.size(); ++i) { + FilteredText filteredtext = (FilteredText) list.get(i); + ChatModifier chatmodifier = signtext.getMessage(i, entityhuman.isTextFilteringEnabled()).getStyle(); +@@ -198,6 +210,29 @@ + } + } + ++ // CraftBukkit start ++ Player player = ((EntityPlayer) entityhuman).getBukkitEntity(); ++ String[] lines = new String[4]; ++ ++ for (int i = 0; i < list.size(); ++i) { ++ lines[i] = CraftChatMessage.fromComponent(signtext.getMessage(i, entityhuman.isTextFilteringEnabled())); ++ } ++ ++ SignChangeEvent event = new SignChangeEvent(CraftBlock.at(this.level, this.worldPosition), player, lines.clone(), (front) ? Side.FRONT : Side.BACK); ++ entityhuman.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return originalText; ++ } ++ ++ IChatBaseComponent[] components = org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()); ++ for (int i = 0; i < components.length; i++) { ++ if (!Objects.equals(lines[i], event.getLine(i))) { ++ signtext = signtext.setMessage(i, components[i]); ++ } ++ } ++ // CraftBukkit end ++ + return signtext; + } + +@@ -248,11 +283,37 @@ + return flag1; + } + +- private static CommandListenerWrapper createCommandSourceStack(@Nullable EntityHuman entityhuman, World world, BlockPosition blockposition) { ++ // CraftBukkit start ++ @Override ++ public void sendSystemMessage(IChatBaseComponent ichatbasecomponent) {} ++ ++ @Override ++ public org.bukkit.command.CommandSender getBukkitSender(CommandListenerWrapper wrapper) { ++ return wrapper.getEntity() != null ? wrapper.getEntity().getBukkitSender(wrapper) : new org.bukkit.craftbukkit.command.CraftBlockCommandSender(wrapper, this); ++ } ++ ++ @Override ++ public boolean acceptsSuccess() { ++ return false; ++ } ++ ++ @Override ++ public boolean acceptsFailure() { ++ return false; ++ } ++ ++ @Override ++ public boolean shouldInformAdmins() { ++ return false; ++ } ++ ++ private CommandListenerWrapper createCommandSourceStack(@Nullable EntityHuman entityhuman, World world, BlockPosition blockposition) { ++ // CraftBukkit end + String s = entityhuman == null ? "Sign" : entityhuman.getName().getString(); + Object object = entityhuman == null ? IChatBaseComponent.literal("Sign") : entityhuman.getDisplayName(); + +- return new CommandListenerWrapper(ICommandListener.NULL, Vec3D.atCenterOf(blockposition), Vec2F.ZERO, (WorldServer) world, 2, s, (IChatBaseComponent) object, world.getServer(), entityhuman); ++ // CraftBukkit - this ++ return new CommandListenerWrapper(this, Vec3D.atCenterOf(blockposition), Vec2F.ZERO, (WorldServer) world, 2, s, (IChatBaseComponent) object, world.getServer(), entityhuman); + } + + @Override +@@ -276,12 +337,17 @@ + + @Nullable + public UUID getPlayerWhoMayEdit() { ++ // CraftBukkit start - unnecessary sign ticking removed, so do this lazily ++ if (this.level != null && this.playerWhoMayEdit != null) { ++ clearInvalidPlayerWhoMayEdit(this, this.level, this.playerWhoMayEdit); ++ } ++ // CraftBukkit end + return this.playerWhoMayEdit; + } + + private void markUpdated() { + this.setChanged(); +- this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3); ++ if (this.level != null) this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3); // CraftBukkit - skip notify if world is null (SPIGOT-5122) + } + + public boolean isWaxed() { diff --git a/patch-remap/og/net/minecraft/world/level/block/entity/TileEntitySkull.patch b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntitySkull.patch new file mode 100644 index 0000000000..7da68fc7be --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/entity/TileEntitySkull.patch @@ -0,0 +1,19 @@ +--- a/net/minecraft/world/level/block/entity/TileEntitySkull.java ++++ b/net/minecraft/world/level/block/entity/TileEntitySkull.java +@@ -194,6 +194,16 @@ + + if (!SystemUtils.isBlank(s)) { + resolveGameProfile(nbttagcompound, s); ++ // CraftBukkit start ++ } else { ++ net.minecraft.nbt.NBTTagList textures = nbttagcompound.getCompound("SkullOwner").getCompound("Properties").getList("textures", 10); // Safe due to method contracts ++ for (int i = 0; i < textures.size(); i++) { ++ if (textures.get(i) instanceof NBTTagCompound && !((NBTTagCompound) textures.get(i)).contains("Signature", 8) && ((NBTTagCompound) textures.get(i)).getString("Value").trim().isEmpty()) { ++ nbttagcompound.remove("SkullOwner"); ++ break; ++ } ++ } ++ // CraftBukkit end + } + + } diff --git a/patch-remap/og/net/minecraft/world/level/block/grower/WorldGenTreeProvider.patch b/patch-remap/og/net/minecraft/world/level/block/grower/WorldGenTreeProvider.patch new file mode 100644 index 0000000000..ee456896d2 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/grower/WorldGenTreeProvider.patch @@ -0,0 +1,120 @@ +--- a/net/minecraft/world/level/block/grower/WorldGenTreeProvider.java ++++ b/net/minecraft/world/level/block/grower/WorldGenTreeProvider.java +@@ -25,6 +25,12 @@ + import net.minecraft.world.level.chunk.ChunkGenerator; + import net.minecraft.world.level.levelgen.feature.WorldGenFeatureConfigured; + ++// CraftBukkit start ++import net.minecraft.data.worldgen.features.TreeFeatures; ++import net.minecraft.world.level.block.BlockSapling; ++import org.bukkit.TreeType; ++// CraftBukkit end ++ + public final class WorldGenTreeProvider { + + private static final Map GROWERS = new Object2ObjectArrayMap(); +@@ -75,21 +81,22 @@ + } + } + +- return flag && this.flowers.isPresent() ? (ResourceKey) this.flowers.get() : (ResourceKey) this.tree.orElse((Object) null); ++ return flag && this.flowers.isPresent() ? (ResourceKey) this.flowers.get() : (ResourceKey) this.tree.orElse(null); // CraftBukkit - decompile error + } + + @Nullable + private ResourceKey> getConfiguredMegaFeature(RandomSource randomsource) { +- return this.secondaryMegaTree.isPresent() && randomsource.nextFloat() < this.secondaryChance ? (ResourceKey) this.secondaryMegaTree.get() : (ResourceKey) this.megaTree.orElse((Object) null); ++ return this.secondaryMegaTree.isPresent() && randomsource.nextFloat() < this.secondaryChance ? (ResourceKey) this.secondaryMegaTree.get() : (ResourceKey) this.megaTree.orElse(null); // CraftBukkit - decompile error + } + + public boolean growTree(WorldServer worldserver, ChunkGenerator chunkgenerator, BlockPosition blockposition, IBlockData iblockdata, RandomSource randomsource) { + ResourceKey> resourcekey = this.getConfiguredMegaFeature(randomsource); + + if (resourcekey != null) { +- Holder> holder = (Holder) worldserver.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE).getHolder(resourcekey).orElse((Object) null); ++ Holder> holder = (Holder) worldserver.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE).getHolder(resourcekey).orElse(null); // CraftBukkit - decompile error + + if (holder != null) { ++ setTreeType(holder); // CraftBukkit + for (int i = 0; i >= -1; --i) { + for (int j = 0; j >= -1; --j) { + if (isTwoByTwoSapling(iblockdata, worldserver, blockposition, i, j)) { +@@ -120,11 +127,12 @@ + if (resourcekey1 == null) { + return false; + } else { +- Holder> holder1 = (Holder) worldserver.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE).getHolder(resourcekey1).orElse((Object) null); ++ Holder> holder1 = (Holder) worldserver.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE).getHolder(resourcekey1).orElse(null); // CraftBukkit - decompile error + + if (holder1 == null) { + return false; + } else { ++ setTreeType(holder1); // CraftBukkit + WorldGenFeatureConfigured worldgenfeatureconfigured1 = (WorldGenFeatureConfigured) holder1.value(); + IBlockData iblockdata2 = worldserver.getFluidState(blockposition).createLegacyBlock(); + +@@ -165,11 +173,62 @@ + return true; + } + ++ // CraftBukkit start ++ private void setTreeType(Holder> holder) { ++ ResourceKey> worldgentreeabstract = holder.unwrapKey().get(); ++ if (worldgentreeabstract == TreeFeatures.OAK || worldgentreeabstract == TreeFeatures.OAK_BEES_005) { ++ BlockSapling.treeType = TreeType.TREE; ++ } else if (worldgentreeabstract == TreeFeatures.HUGE_RED_MUSHROOM) { ++ BlockSapling.treeType = TreeType.RED_MUSHROOM; ++ } else if (worldgentreeabstract == TreeFeatures.HUGE_BROWN_MUSHROOM) { ++ BlockSapling.treeType = TreeType.BROWN_MUSHROOM; ++ } else if (worldgentreeabstract == TreeFeatures.JUNGLE_TREE) { ++ BlockSapling.treeType = TreeType.COCOA_TREE; ++ } else if (worldgentreeabstract == TreeFeatures.JUNGLE_TREE_NO_VINE) { ++ BlockSapling.treeType = TreeType.SMALL_JUNGLE; ++ } else if (worldgentreeabstract == TreeFeatures.PINE) { ++ BlockSapling.treeType = TreeType.TALL_REDWOOD; ++ } else if (worldgentreeabstract == TreeFeatures.SPRUCE) { ++ BlockSapling.treeType = TreeType.REDWOOD; ++ } else if (worldgentreeabstract == TreeFeatures.ACACIA) { ++ BlockSapling.treeType = TreeType.ACACIA; ++ } else if (worldgentreeabstract == TreeFeatures.BIRCH || worldgentreeabstract == TreeFeatures.BIRCH_BEES_005) { ++ BlockSapling.treeType = TreeType.BIRCH; ++ } else if (worldgentreeabstract == TreeFeatures.SUPER_BIRCH_BEES_0002) { ++ BlockSapling.treeType = TreeType.TALL_BIRCH; ++ } else if (worldgentreeabstract == TreeFeatures.SWAMP_OAK) { ++ BlockSapling.treeType = TreeType.SWAMP; ++ } else if (worldgentreeabstract == TreeFeatures.FANCY_OAK || worldgentreeabstract == TreeFeatures.FANCY_OAK_BEES_005) { ++ BlockSapling.treeType = TreeType.BIG_TREE; ++ } else if (worldgentreeabstract == TreeFeatures.JUNGLE_BUSH) { ++ BlockSapling.treeType = TreeType.JUNGLE_BUSH; ++ } else if (worldgentreeabstract == TreeFeatures.DARK_OAK) { ++ BlockSapling.treeType = TreeType.DARK_OAK; ++ } else if (worldgentreeabstract == TreeFeatures.MEGA_SPRUCE) { ++ BlockSapling.treeType = TreeType.MEGA_REDWOOD; ++ } else if (worldgentreeabstract == TreeFeatures.MEGA_PINE) { ++ BlockSapling.treeType = TreeType.MEGA_REDWOOD; ++ } else if (worldgentreeabstract == TreeFeatures.MEGA_JUNGLE_TREE) { ++ BlockSapling.treeType = TreeType.JUNGLE; ++ } else if (worldgentreeabstract == TreeFeatures.AZALEA_TREE) { ++ BlockSapling.treeType = TreeType.AZALEA; ++ } else if (worldgentreeabstract == TreeFeatures.MANGROVE) { ++ BlockSapling.treeType = TreeType.MANGROVE; ++ } else if (worldgentreeabstract == TreeFeatures.TALL_MANGROVE) { ++ BlockSapling.treeType = TreeType.TALL_MANGROVE; ++ } else if (worldgentreeabstract == TreeFeatures.CHERRY || worldgentreeabstract == TreeFeatures.CHERRY_BEES_005) { ++ BlockSapling.treeType = TreeType.CHERRY; ++ } else { ++ throw new IllegalArgumentException("Unknown tree generator " + worldgentreeabstract); ++ } ++ } ++ // CraftBukkit end ++ + static { +- Function function = (worldgentreeprovider) -> { ++ Function function = (worldgentreeprovider) -> { // CraftBukkit - decompile error + return worldgentreeprovider.name; + }; +- Map map = WorldGenTreeProvider.GROWERS; ++ Map map = WorldGenTreeProvider.GROWERS; // CraftBukkit - decompile error + + Objects.requireNonNull(map); + CODEC = ExtraCodecs.stringResolverCodec(function, map::get); diff --git a/patch-remap/og/net/minecraft/world/level/block/piston/BlockPiston.patch b/patch-remap/og/net/minecraft/world/level/block/piston/BlockPiston.patch new file mode 100644 index 0000000000..779c46db5c --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/piston/BlockPiston.patch @@ -0,0 +1,85 @@ +--- a/net/minecraft/world/level/block/piston/BlockPiston.java ++++ b/net/minecraft/world/level/block/piston/BlockPiston.java +@@ -41,6 +41,14 @@ + import net.minecraft.world.phys.shapes.VoxelShapeCollision; + import net.minecraft.world.phys.shapes.VoxelShapes; + ++// CraftBukkit start ++import com.google.common.collect.ImmutableList; ++import java.util.AbstractList; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockPistonRetractEvent; ++import org.bukkit.event.block.BlockPistonExtendEvent; ++// CraftBukkit end ++ + public class BlockPiston extends BlockDirectional { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> { +@@ -151,6 +159,18 @@ + } + } + ++ // CraftBukkit start ++ if (!this.isSticky) { ++ org.bukkit.block.Block block = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ BlockPistonRetractEvent event = new BlockPistonRetractEvent(block, ImmutableList.of(), CraftBlock.notchToBlockFace(enumdirection)); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // PAIL: checkME - what happened to setTypeAndData? ++ // CraftBukkit end + world.blockEvent(blockposition, this, b0, enumdirection.get3DDataValue()); + } + +@@ -331,6 +351,48 @@ + IBlockData[] aiblockdata = new IBlockData[list.size() + list2.size()]; + EnumDirection enumdirection1 = flag ? enumdirection : enumdirection.getOpposite(); + int i = 0; ++ // CraftBukkit start ++ final org.bukkit.block.Block bblock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ ++ final List moved = pistonextendschecker.getToPush(); ++ final List broken = pistonextendschecker.getToDestroy(); ++ ++ List blocks = new AbstractList() { ++ ++ @Override ++ public int size() { ++ return moved.size() + broken.size(); ++ } ++ ++ @Override ++ public org.bukkit.block.Block get(int index) { ++ if (index >= size() || index < 0) { ++ throw new ArrayIndexOutOfBoundsException(index); ++ } ++ BlockPosition pos = (BlockPosition) (index < moved.size() ? moved.get(index) : broken.get(index - moved.size())); ++ return bblock.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ } ++ }; ++ org.bukkit.event.block.BlockPistonEvent event; ++ if (flag) { ++ event = new BlockPistonExtendEvent(bblock, blocks, CraftBlock.notchToBlockFace(enumdirection1)); ++ } else { ++ event = new BlockPistonRetractEvent(bblock, blocks, CraftBlock.notchToBlockFace(enumdirection1)); ++ } ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ for (BlockPosition b : broken) { ++ world.sendBlockUpdated(b, Blocks.AIR.defaultBlockState(), world.getBlockState(b), 3); ++ } ++ for (BlockPosition b : moved) { ++ world.sendBlockUpdated(b, Blocks.AIR.defaultBlockState(), world.getBlockState(b), 3); ++ b = b.relative(enumdirection1); ++ world.sendBlockUpdated(b, Blocks.AIR.defaultBlockState(), world.getBlockState(b), 3); ++ } ++ return false; ++ } ++ // CraftBukkit end + + BlockPosition blockposition3; + int j; diff --git a/patch-remap/og/net/minecraft/world/level/block/state/BlockBase.patch b/patch-remap/og/net/minecraft/world/level/block/state/BlockBase.patch new file mode 100644 index 0000000000..9bc9a05b7f --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/block/state/BlockBase.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/level/block/state/BlockBase.java ++++ b/net/minecraft/world/level/block/state/BlockBase.java +@@ -188,8 +188,10 @@ + TileEntity tileentity = iblockdata.hasBlockEntity() ? world.getBlockEntity(blockposition) : null; + LootParams.a lootparams_a = (new LootParams.a(worldserver)).withParameter(LootContextParameters.ORIGIN, Vec3D.atCenterOf(blockposition)).withParameter(LootContextParameters.TOOL, ItemStack.EMPTY).withOptionalParameter(LootContextParameters.BLOCK_ENTITY, tileentity).withOptionalParameter(LootContextParameters.THIS_ENTITY, explosion.getDirectSourceEntity()); + +- if (explosion.getBlockInteraction() == Explosion.Effect.DESTROY_WITH_DECAY) { +- lootparams_a.withParameter(LootContextParameters.EXPLOSION_RADIUS, explosion.radius()); ++ // CraftBukkit start - add yield ++ if (explosion.yield < 1.0F) { ++ lootparams_a.withParameter(LootContextParameters.EXPLOSION_RADIUS, 1.0F / explosion.yield); ++ // CraftBukkit end + } + + iblockdata.spawnAfterBreak(worldserver, blockposition, ItemStack.EMPTY, flag); diff --git a/patch-remap/og/net/minecraft/world/level/border/WorldBorder.patch b/patch-remap/og/net/minecraft/world/level/border/WorldBorder.patch new file mode 100644 index 0000000000..30e7fd67a6 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/border/WorldBorder.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/level/border/WorldBorder.java ++++ b/net/minecraft/world/level/border/WorldBorder.java +@@ -29,6 +29,7 @@ + int absoluteMaxSize = 29999984; + private WorldBorder.a extent = new WorldBorder.d(5.9999968E7D); + public static final WorldBorder.c DEFAULT_SETTINGS = new WorldBorder.c(0.0D, 0.0D, 0.2D, 5.0D, 5, 15, 5.9999968E7D, 0L, 0.0D); ++ public net.minecraft.server.level.WorldServer world; // CraftBukkit + + public WorldBorder() {} + +@@ -164,6 +165,7 @@ + } + + public void addListener(IWorldBorderListener iworldborderlistener) { ++ if (listeners.contains(iworldborderlistener)) return; // CraftBukkit + this.listeners.add(iworldborderlistener); + } + diff --git a/patch-remap/og/net/minecraft/world/level/chunk/Chunk.patch b/patch-remap/og/net/minecraft/world/level/chunk/Chunk.patch new file mode 100644 index 0000000000..a09e16522b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/chunk/Chunk.patch @@ -0,0 +1,187 @@ +--- a/net/minecraft/world/level/chunk/Chunk.java ++++ b/net/minecraft/world/level/chunk/Chunk.java +@@ -75,7 +75,7 @@ + }; + private final Map tickersInLevel; + public boolean loaded; +- public final World level; ++ public final WorldServer level; // CraftBukkit - type + @Nullable + private Supplier fullStatus; + @Nullable +@@ -91,7 +91,7 @@ + public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, LevelChunkTicks levelchunkticks, LevelChunkTicks levelchunkticks1, long i, @Nullable ChunkSection[] achunksection, @Nullable Chunk.c chunk_c, @Nullable BlendingData blendingdata) { + super(chunkcoordintpair, chunkconverter, world, world.registryAccess().registryOrThrow(Registries.BIOME), i, achunksection, blendingdata); + this.tickersInLevel = Maps.newHashMap(); +- this.level = world; ++ this.level = (WorldServer) world; // CraftBukkit - type + this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap(); + HeightMap.Type[] aheightmap_type = HeightMap.Type.values(); + int j = aheightmap_type.length; +@@ -109,6 +109,11 @@ + this.fluidTicks = levelchunkticks1; + } + ++ // CraftBukkit start ++ public boolean mustNotSave; ++ public boolean needsDecoration; ++ // CraftBukkit end ++ + public Chunk(WorldServer worldserver, ProtoChunk protochunk, @Nullable Chunk.c chunk_c) { + this(worldserver, protochunk.getPos(), protochunk.getUpgradeData(), protochunk.unpackBlockTicks(), protochunk.unpackFluidTicks(), protochunk.getInhabitedTime(), protochunk.getSections(), chunk_c, protochunk.getBlendingData()); + Iterator iterator = protochunk.getBlockEntities().values().iterator(); +@@ -140,6 +145,10 @@ + this.skyLightSources = protochunk.skyLightSources; + this.setLightCorrect(protochunk.isLightCorrect()); + this.unsaved = true; ++ this.needsDecoration = true; // CraftBukkit ++ // CraftBukkit start ++ this.persistentDataContainer = protochunk.persistentDataContainer; // SPIGOT-6814: copy PDC to account for 1.17 to 1.18 chunk upgrading. ++ // CraftBukkit end + } + + @Override +@@ -244,9 +253,16 @@ + } + } + ++ // CraftBukkit start + @Nullable + @Override + public IBlockData setBlockState(BlockPosition blockposition, IBlockData iblockdata, boolean flag) { ++ return this.setBlockState(blockposition, iblockdata, flag, true); ++ } ++ ++ @Nullable ++ public IBlockData setBlockState(BlockPosition blockposition, IBlockData iblockdata, boolean flag, boolean doPlace) { ++ // CraftBukkit end + int i = blockposition.getY(); + ChunkSection chunksection = this.getSection(this.getSectionIndex(i)); + boolean flag1 = chunksection.hasOnlyAir(); +@@ -295,7 +311,8 @@ + if (!chunksection.getBlockState(j, k, l).is(block)) { + return null; + } else { +- if (!this.level.isClientSide) { ++ // CraftBukkit - Don't place while processing the BlockPlaceEvent, unless it's a BlockContainer. Prevents blocks such as TNT from activating when cancelled. ++ if (!this.level.isClientSide && doPlace && (!this.level.captureBlockStates || block instanceof net.minecraft.world.level.block.BlockTileEntity)) { + iblockdata.onPlace(this.level, blockposition, iblockdata1, flag); + } + +@@ -340,7 +357,12 @@ + + @Nullable + public TileEntity getBlockEntity(BlockPosition blockposition, Chunk.EnumTileEntityState chunk_enumtileentitystate) { +- TileEntity tileentity = (TileEntity) this.blockEntities.get(blockposition); ++ // CraftBukkit start ++ TileEntity tileentity = level.capturedTileEntities.get(blockposition); ++ if (tileentity == null) { ++ tileentity = (TileEntity) this.blockEntities.get(blockposition); ++ } ++ // CraftBukkit end + + if (tileentity == null) { + NBTTagCompound nbttagcompound = (NBTTagCompound) this.pendingBlockEntities.remove(blockposition); +@@ -418,6 +440,13 @@ + tileentity1.setRemoved(); + } + ++ // CraftBukkit start ++ } else { ++ System.out.println("Attempted to place a tile entity (" + tileentity + ") at " + tileentity.getBlockPos().getX() + "," + tileentity.getBlockPos().getY() + "," + tileentity.getBlockPos().getZ() ++ + " (" + getBlockState(blockposition) + ") where there was no entity tile!"); ++ System.out.println("Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); ++ new Exception().printStackTrace(); ++ // CraftBukkit end + } + } + +@@ -447,6 +476,12 @@ + if (this.isInLevel()) { + TileEntity tileentity = (TileEntity) this.blockEntities.remove(blockposition); + ++ // CraftBukkit start - SPIGOT-5561: Also remove from pending map ++ if (!pendingBlockEntities.isEmpty()) { ++ pendingBlockEntities.remove(blockposition); ++ } ++ // CraftBukkit end ++ + if (tileentity != null) { + World world = this.level; + +@@ -500,6 +535,57 @@ + + } + ++ // CraftBukkit start ++ public void loadCallback() { ++ org.bukkit.Server server = this.level.getCraftServer(); ++ if (server != null) { ++ /* ++ * If it's a new world, the first few chunks are generated inside ++ * the World constructor. We can't reliably alter that, so we have ++ * no way of creating a CraftWorld/CraftServer at that point. ++ */ ++ org.bukkit.Chunk bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this); ++ server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(bukkitChunk, this.needsDecoration)); ++ ++ if (this.needsDecoration) { ++ this.needsDecoration = false; ++ java.util.Random random = new java.util.Random(); ++ random.setSeed(level.getSeed()); ++ long xRand = random.nextLong() / 2L * 2L + 1L; ++ long zRand = random.nextLong() / 2L * 2L + 1L; ++ random.setSeed((long) this.chunkPos.x * xRand + (long) this.chunkPos.z * zRand ^ level.getSeed()); ++ ++ org.bukkit.World world = this.level.getWorld(); ++ if (world != null) { ++ this.level.populating = true; ++ try { ++ for (org.bukkit.generator.BlockPopulator populator : world.getPopulators()) { ++ populator.populate(world, random, bukkitChunk); ++ } ++ } finally { ++ this.level.populating = false; ++ } ++ } ++ server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk)); ++ } ++ } ++ } ++ ++ public void unloadCallback() { ++ org.bukkit.Server server = this.level.getCraftServer(); ++ org.bukkit.Chunk bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this); ++ org.bukkit.event.world.ChunkUnloadEvent unloadEvent = new org.bukkit.event.world.ChunkUnloadEvent(bukkitChunk, this.isUnsaved()); ++ server.getPluginManager().callEvent(unloadEvent); ++ // note: saving can be prevented, but not forced if no saving is actually required ++ this.mustNotSave = !unloadEvent.isSaveChunk(); ++ } ++ ++ @Override ++ public boolean isUnsaved() { ++ return super.isUnsaved() && !this.mustNotSave; ++ } ++ // CraftBukkit end ++ + public boolean isEmpty() { + return false; + } +@@ -697,7 +783,7 @@ + + private void updateBlockEntityTicker(T t0) { + IBlockData iblockdata = t0.getBlockState(); +- BlockEntityTicker blockentityticker = iblockdata.getTicker(this.level, t0.getType()); ++ BlockEntityTicker blockentityticker = iblockdata.getTicker(this.level, (TileEntityTypes) t0.getType()); // CraftBukkit - decompile error + + if (blockentityticker == null) { + this.removeBlockEntityTicker(t0.getBlockPos()); +@@ -782,7 +868,7 @@ + private boolean loggedInvalidBlockState; + + a(TileEntity tileentity, BlockEntityTicker blockentityticker) { +- this.blockEntity = tileentity; ++ this.blockEntity = (T) tileentity; // CraftBukkit - decompile error + this.ticker = blockentityticker; + } + diff --git a/patch-remap/og/net/minecraft/world/level/chunk/ChunkGenerator.patch b/patch-remap/og/net/minecraft/world/level/chunk/ChunkGenerator.patch new file mode 100644 index 0000000000..33a33996ac --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/chunk/ChunkGenerator.patch @@ -0,0 +1,78 @@ +--- a/net/minecraft/world/level/chunk/ChunkGenerator.java ++++ b/net/minecraft/world/level/chunk/ChunkGenerator.java +@@ -306,7 +306,7 @@ + } + } + +- public void applyBiomeDecoration(GeneratorAccessSeed generatoraccessseed, IChunkAccess ichunkaccess, StructureManager structuremanager) { ++ public void addVanillaDecorations(GeneratorAccessSeed generatoraccessseed, IChunkAccess ichunkaccess, StructureManager structuremanager) { // CraftBukkit + ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos(); + + if (!SharedConstants.debugVoidTerrain(chunkcoordintpair)) { +@@ -328,7 +328,7 @@ + + for (int k = 0; k < j; ++k) { + ChunkSection chunksection = achunksection[k]; +- PalettedContainerRO palettedcontainerro = chunksection.getBiomes(); ++ PalettedContainerRO> palettedcontainerro = chunksection.getBiomes(); // CraftBukkit - decompile error + + Objects.requireNonNull(set); + palettedcontainerro.getAll(set::add); +@@ -354,7 +354,7 @@ + Structure structure = (Structure) iterator.next(); + + seededrandom.setFeatureSeed(i, i1, l); +- Supplier supplier = () -> { ++ Supplier supplier = () -> { // CraftBukkit - decompile error + Optional optional = iregistry.getResourceKey(structure).map(Object::toString); + + Objects.requireNonNull(structure); +@@ -439,6 +439,33 @@ + } + } + ++ // CraftBukkit start ++ public void applyBiomeDecoration(GeneratorAccessSeed generatoraccessseed, IChunkAccess ichunkaccess, StructureManager structuremanager) { ++ applyBiomeDecoration(generatoraccessseed, ichunkaccess, structuremanager, true); ++ } ++ ++ public void applyBiomeDecoration(GeneratorAccessSeed generatoraccessseed, IChunkAccess ichunkaccess, StructureManager structuremanager, boolean vanilla) { ++ if (vanilla) { ++ addVanillaDecorations(generatoraccessseed, ichunkaccess, structuremanager); ++ } ++ ++ org.bukkit.World world = generatoraccessseed.getMinecraftWorld().getWorld(); ++ // only call when a populator is present (prevents unnecessary entity conversion) ++ if (!world.getPopulators().isEmpty()) { ++ org.bukkit.craftbukkit.generator.CraftLimitedRegion limitedRegion = new org.bukkit.craftbukkit.generator.CraftLimitedRegion(generatoraccessseed, ichunkaccess.getPos()); ++ int x = ichunkaccess.getPos().x; ++ int z = ichunkaccess.getPos().z; ++ for (org.bukkit.generator.BlockPopulator populator : world.getPopulators()) { ++ SeededRandom seededrandom = new SeededRandom(new net.minecraft.world.level.levelgen.LegacyRandomSource(generatoraccessseed.getSeed())); ++ seededrandom.setDecorationSeed(generatoraccessseed.getSeed(), x, z); ++ populator.populate(world, new org.bukkit.craftbukkit.util.RandomSourceWrapper.RandomWrapper(seededrandom), x, z, limitedRegion); ++ } ++ limitedRegion.saveEntities(); ++ limitedRegion.breakLink(); ++ } ++ } ++ // CraftBukkit end ++ + private static StructureBoundingBox getWritableArea(IChunkAccess ichunkaccess) { + ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos(); + int i = chunkcoordintpair.getMinBlockX(); +@@ -576,6 +603,14 @@ + StructureStart structurestart = structure.generate(iregistrycustom, this, this.biomeSource, randomstate, structuretemplatemanager, i, chunkcoordintpair, j, ichunkaccess, predicate); + + if (structurestart.isValid()) { ++ // CraftBukkit start ++ StructureBoundingBox box = structurestart.getBoundingBox(); ++ org.bukkit.event.world.AsyncStructureSpawnEvent event = new org.bukkit.event.world.AsyncStructureSpawnEvent(structuremanager.level.getMinecraftWorld().getWorld(), org.bukkit.craftbukkit.generator.structure.CraftStructure.minecraftToBukkit(structure, iregistrycustom), new org.bukkit.util.BoundingBox(box.minX(), box.minY(), box.minZ(), box.maxX(), box.maxY(), box.maxZ()), chunkcoordintpair.x, chunkcoordintpair.z); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return true; ++ } ++ // CraftBukkit end + structuremanager.setStartForStructure(sectionposition, structure, structurestart, ichunkaccess); + return true; + } else { diff --git a/patch-remap/og/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.patch b/patch-remap/og/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.patch new file mode 100644 index 0000000000..ac75ddd5c3 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.patch @@ -0,0 +1,7 @@ +--- a/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java ++++ b/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.world.level.chunk; + + import com.google.common.base.Stopwatch; diff --git a/patch-remap/og/net/minecraft/world/level/chunk/ChunkSection.patch b/patch-remap/og/net/minecraft/world/level/chunk/ChunkSection.patch new file mode 100644 index 0000000000..2978daa498 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/chunk/ChunkSection.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/world/level/chunk/ChunkSection.java ++++ b/net/minecraft/world/level/chunk/ChunkSection.java +@@ -23,9 +23,11 @@ + private short tickingBlockCount; + private short tickingFluidCount; + private final DataPaletteBlock states; +- private PalettedContainerRO> biomes; ++ // CraftBukkit start - read/write ++ private DataPaletteBlock> biomes; + +- public ChunkSection(DataPaletteBlock datapaletteblock, PalettedContainerRO> palettedcontainerro) { ++ public ChunkSection(DataPaletteBlock datapaletteblock, DataPaletteBlock> palettedcontainerro) { ++ // CraftBukkit end + this.states = datapaletteblock; + this.biomes = palettedcontainerro; + this.recalcBlockCounts(); +@@ -188,6 +190,12 @@ + return (Holder) this.biomes.get(i, j, k); + } + ++ // CraftBukkit start ++ public void setBiome(int i, int j, int k, Holder biome) { ++ this.biomes.set(i, j, k, biome); ++ } ++ // CraftBukkit end ++ + public void fillBiomesFromNoise(BiomeResolver biomeresolver, Climate.Sampler climate_sampler, int i, int j, int k) { + DataPaletteBlock> datapaletteblock = this.biomes.recreate(); + boolean flag = true; diff --git a/patch-remap/og/net/minecraft/world/level/chunk/ChunkStatus.patch b/patch-remap/og/net/minecraft/world/level/chunk/ChunkStatus.patch new file mode 100644 index 0000000000..b06192ac5d --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/chunk/ChunkStatus.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/level/chunk/ChunkStatus.java ++++ b/net/minecraft/world/level/chunk/ChunkStatus.java +@@ -39,7 +39,7 @@ + public static final ChunkStatus EMPTY = registerSimple("empty", (ChunkStatus) null, -1, ChunkStatus.PRE_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, worldserver, chunkgenerator, list, ichunkaccess) -> { + }); + public static final ChunkStatus STRUCTURE_STARTS = register("structure_starts", ChunkStatus.EMPTY, 0, false, ChunkStatus.PRE_FEATURES, ChunkStatus.Type.PROTOCHUNK, (chunkstatus, executor, worldserver, chunkgenerator, structuretemplatemanager, lightenginethreaded, function, list, ichunkaccess) -> { +- if (worldserver.getServer().getWorldData().worldGenOptions().generateStructures()) { ++ if (worldserver.serverLevelData.worldGenOptions().generateStructures()) { // CraftBukkit + chunkgenerator.createStructures(worldserver.registryAccess(), worldserver.getChunkSource().getGeneratorState(), worldserver.structureManager(), ichunkaccess, structuretemplatemanager); + } + diff --git a/patch-remap/og/net/minecraft/world/level/chunk/IChunkAccess.patch b/patch-remap/og/net/minecraft/world/level/chunk/IChunkAccess.patch new file mode 100644 index 0000000000..ef98585d46 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/chunk/IChunkAccess.patch @@ -0,0 +1,67 @@ +--- a/net/minecraft/world/level/chunk/IChunkAccess.java ++++ b/net/minecraft/world/level/chunk/IChunkAccess.java +@@ -82,6 +82,11 @@ + protected final LevelHeightAccessor levelHeightAccessor; + protected final ChunkSection[] sections; + ++ // CraftBukkit start - SPIGOT-6814: move to IChunkAccess to account for 1.17 to 1.18 chunk upgrading. ++ private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry(); ++ public org.bukkit.craftbukkit.persistence.DirtyCraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.DirtyCraftPersistentDataContainer(DATA_TYPE_REGISTRY); ++ // CraftBukkit end ++ + public IChunkAccess(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, LevelHeightAccessor levelheightaccessor, IRegistry iregistry, long i, @Nullable ChunkSection[] achunksection, @Nullable BlendingData blendingdata) { + this.chunkPos = chunkcoordintpair; + this.upgradeData = chunkconverter; +@@ -100,7 +105,11 @@ + } + + replaceMissingSections(iregistry, this.sections); ++ // CraftBukkit start ++ this.biomeRegistry = iregistry; + } ++ public final IRegistry biomeRegistry; ++ // CraftBukkit end + + private static void replaceMissingSections(IRegistry iregistry, ChunkSection[] achunksection) { + for (int i = 0; i < achunksection.length; ++i) { +@@ -263,10 +272,11 @@ + + public void setUnsaved(boolean flag) { + this.unsaved = flag; ++ if (!flag) this.persistentDataContainer.dirty(false); // CraftBukkit - SPIGOT-6814: chunk was saved, pdc is no longer dirty + } + + public boolean isUnsaved() { +- return this.unsaved; ++ return this.unsaved || this.persistentDataContainer.dirty(); // CraftBukkit - SPIGOT-6814: chunk is unsaved if pdc was mutated + } + + public abstract ChunkStatus getStatus(); +@@ -442,6 +452,27 @@ + } + } + ++ // CraftBukkit start ++ public void setBiome(int i, int j, int k, Holder biome) { ++ try { ++ int l = QuartPos.fromBlock(this.getMinBuildHeight()); ++ int i1 = l + QuartPos.fromBlock(this.getHeight()) - 1; ++ int j1 = MathHelper.clamp(j, l, i1); ++ int k1 = this.getSectionIndex(QuartPos.toBlock(j1)); ++ ++ this.sections[k1].setBiome(i & 3, j1 & 3, k & 3, biome); ++ } catch (Throwable throwable) { ++ CrashReport crashreport = CrashReport.forThrowable(throwable, "Setting biome"); ++ CrashReportSystemDetails crashreportsystemdetails = crashreport.addCategory("Biome being set"); ++ ++ crashreportsystemdetails.setDetail("Location", () -> { ++ return CrashReportSystemDetails.formatLocation(this, i, j, k); ++ }); ++ throw new ReportedException(crashreport); ++ } ++ } ++ // CraftBukkit end ++ + public void fillBiomesFromNoise(BiomeResolver biomeresolver, Climate.Sampler climate_sampler) { + ChunkCoordIntPair chunkcoordintpair = this.getPos(); + int i = QuartPos.fromBlock(chunkcoordintpair.getMinBlockX()); diff --git a/patch-remap/og/net/minecraft/world/level/chunk/NibbleArray.patch b/patch-remap/og/net/minecraft/world/level/chunk/NibbleArray.patch new file mode 100644 index 0000000000..48ffdb3140 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/chunk/NibbleArray.patch @@ -0,0 +1,7 @@ +--- a/net/minecraft/world/level/chunk/NibbleArray.java ++++ b/net/minecraft/world/level/chunk/NibbleArray.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.world.level.chunk; + + import java.util.Arrays; diff --git a/patch-remap/og/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.patch b/patch-remap/og/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.patch new file mode 100644 index 0000000000..4f2cd8bb05 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.patch @@ -0,0 +1,116 @@ +--- a/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java ++++ b/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java +@@ -102,7 +102,7 @@ + ChunkProviderServer chunkproviderserver = worldserver.getChunkSource(); + LevelLightEngine levellightengine = chunkproviderserver.getLightEngine(); + IRegistry iregistry = worldserver.registryAccess().registryOrThrow(Registries.BIOME); +- Codec>> codec = makeBiomeCodec(iregistry); ++ Codec>> codec = makeBiomeCodecRW(iregistry); // CraftBukkit - read/write + boolean flag2 = false; + + DataResult dataresult; +@@ -122,12 +122,12 @@ + }); + logger = ChunkRegionLoader.LOGGER; + Objects.requireNonNull(logger); +- datapaletteblock = (DataPaletteBlock) dataresult.getOrThrow(false, logger::error); ++ datapaletteblock = (DataPaletteBlock) ((DataResult>) dataresult).getOrThrow(false, logger::error); // CraftBukkit - decompile error + } else { + datapaletteblock = new DataPaletteBlock<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), DataPaletteBlock.d.SECTION_STATES); + } + +- Object object; ++ DataPaletteBlock object; // CraftBukkit - read/write + + if (nbttagcompound1.contains("biomes", 10)) { + dataresult = codec.parse(DynamicOpsNBT.INSTANCE, nbttagcompound1.getCompound("biomes")).promotePartial((s) -> { +@@ -135,12 +135,12 @@ + }); + logger = ChunkRegionLoader.LOGGER; + Objects.requireNonNull(logger); +- object = (PalettedContainerRO) dataresult.getOrThrow(false, logger::error); ++ object = ((DataResult>>) dataresult).getOrThrow(false, logger::error); // CraftBukkit - decompile error + } else { + object = new DataPaletteBlock<>(iregistry.asHolderIdMap(), iregistry.getHolderOrThrow(Biomes.PLAINS), DataPaletteBlock.d.SECTION_BIOMES); + } + +- ChunkSection chunksection = new ChunkSection(datapaletteblock, (PalettedContainerRO) object); ++ ChunkSection chunksection = new ChunkSection(datapaletteblock, (DataPaletteBlock) object); // CraftBukkit - read/write + + achunksection[k] = chunksection; + SectionPosition sectionposition = SectionPosition.of(chunkcoordintpair, b0); +@@ -176,7 +176,7 @@ + dataresult = BlendingData.CODEC.parse(new Dynamic(DynamicOpsNBT.INSTANCE, nbttagcompound.getCompound("blending_data"))); + logger1 = ChunkRegionLoader.LOGGER; + Objects.requireNonNull(logger1); +- blendingdata = (BlendingData) dataresult.resultOrPartial(logger1::error).orElse((Object) null); ++ blendingdata = (BlendingData) ((DataResult) dataresult).resultOrPartial(logger1::error).orElse(null); // CraftBukkit - decompile error + } else { + blendingdata = null; + } +@@ -207,7 +207,7 @@ + dataresult = BelowZeroRetrogen.CODEC.parse(new Dynamic(DynamicOpsNBT.INSTANCE, nbttagcompound.getCompound("below_zero_retrogen"))); + logger1 = ChunkRegionLoader.LOGGER; + Objects.requireNonNull(logger1); +- Optional optional = dataresult.resultOrPartial(logger1::error); ++ Optional optional = ((DataResult) dataresult).resultOrPartial(logger1::error); // CraftBukkit - decompile error + + Objects.requireNonNull(protochunk); + optional.ifPresent(protochunk::setBelowZeroRetrogen); +@@ -221,6 +221,13 @@ + } + } + ++ // CraftBukkit start - load chunk persistent data from nbt - SPIGOT-6814: Already load PDC here to account for 1.17 to 1.18 chunk upgrading. ++ net.minecraft.nbt.NBTBase persistentBase = nbttagcompound.get("ChunkBukkitValues"); ++ if (persistentBase instanceof NBTTagCompound) { ++ ((IChunkAccess) object1).persistentDataContainer.putAll((NBTTagCompound) persistentBase); ++ } ++ // CraftBukkit end ++ + ((IChunkAccess) object1).setLightCorrect(flag); + NBTTagCompound nbttagcompound2 = nbttagcompound.getCompound("Heightmaps"); + EnumSet enumset = EnumSet.noneOf(HeightMap.Type.class); +@@ -300,6 +307,12 @@ + return DataPaletteBlock.codecRO(iregistry.asHolderIdMap(), iregistry.holderByNameCodec(), DataPaletteBlock.d.SECTION_BIOMES, iregistry.getHolderOrThrow(Biomes.PLAINS)); + } + ++ // CraftBukkit start - read/write ++ private static Codec>> makeBiomeCodecRW(IRegistry iregistry) { ++ return DataPaletteBlock.codecRW(iregistry.asHolderIdMap(), iregistry.holderByNameCodec(), DataPaletteBlock.d.SECTION_BIOMES, iregistry.getHolderOrThrow(Biomes.PLAINS)); ++ } ++ // CraftBukkit end ++ + public static NBTTagCompound write(WorldServer worldserver, IChunkAccess ichunkaccess) { + ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos(); + NBTTagCompound nbttagcompound = GameProfileSerializer.addCurrentDataVersion(new NBTTagCompound()); +@@ -311,7 +324,7 @@ + nbttagcompound.putLong("InhabitedTime", ichunkaccess.getInhabitedTime()); + nbttagcompound.putString("Status", BuiltInRegistries.CHUNK_STATUS.getKey(ichunkaccess.getStatus()).toString()); + BlendingData blendingdata = ichunkaccess.getBlendingData(); +- DataResult dataresult; ++ DataResult dataresult; // CraftBukkit - decompile error + Logger logger; + + if (blendingdata != null) { +@@ -358,7 +371,7 @@ + + if (flag1) { + ChunkSection chunksection = achunksection[j]; +- DataResult dataresult1 = ChunkRegionLoader.BLOCK_STATE_CODEC.encodeStart(DynamicOpsNBT.INSTANCE, chunksection.getStates()); ++ DataResult dataresult1 = ChunkRegionLoader.BLOCK_STATE_CODEC.encodeStart(DynamicOpsNBT.INSTANCE, chunksection.getStates()); // CraftBukkit - decompile error + Logger logger1 = ChunkRegionLoader.LOGGER; + + Objects.requireNonNull(logger1); +@@ -441,6 +454,11 @@ + + nbttagcompound.put("Heightmaps", nbttagcompound3); + nbttagcompound.put("structures", packStructureData(StructurePieceSerializationContext.fromLevel(worldserver), chunkcoordintpair, ichunkaccess.getAllStarts(), ichunkaccess.getAllReferences())); ++ // CraftBukkit start - store chunk persistent data in nbt ++ if (!ichunkaccess.persistentDataContainer.isEmpty()) { // SPIGOT-6814: Always save PDC to account for 1.17 to 1.18 chunk upgrading. ++ nbttagcompound.put("ChunkBukkitValues", ichunkaccess.persistentDataContainer.toTagCompound()); ++ } ++ // CraftBukkit end + return nbttagcompound; + } + diff --git a/patch-remap/og/net/minecraft/world/level/chunk/storage/IChunkLoader.patch b/patch-remap/og/net/minecraft/world/level/chunk/storage/IChunkLoader.patch new file mode 100644 index 0000000000..3b86f06e19 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/chunk/storage/IChunkLoader.patch @@ -0,0 +1,91 @@ +--- a/net/minecraft/world/level/chunk/storage/IChunkLoader.java ++++ b/net/minecraft/world/level/chunk/storage/IChunkLoader.java +@@ -19,6 +19,15 @@ + import net.minecraft.world.level.levelgen.structure.PersistentStructureLegacy; + import net.minecraft.world.level.storage.WorldPersistentData; + ++// CraftBukkit start ++import java.util.concurrent.ExecutionException; ++import net.minecraft.server.level.ChunkProviderServer; ++import net.minecraft.server.level.WorldServer; ++import net.minecraft.world.level.GeneratorAccess; ++import net.minecraft.world.level.chunk.ChunkStatus; ++import net.minecraft.world.level.dimension.WorldDimension; ++// CraftBukkit end ++ + public class IChunkLoader implements AutoCloseable { + + public static final int LAST_MONOLYTH_STRUCTURE_DATA_VERSION = 1493; +@@ -36,9 +45,53 @@ + return this.worker.isOldChunkAround(chunkcoordintpair, i); + } + +- public NBTTagCompound upgradeChunkTag(ResourceKey resourcekey, Supplier supplier, NBTTagCompound nbttagcompound, Optional>> optional) { ++ // CraftBukkit start ++ private boolean check(ChunkProviderServer cps, int x, int z) { ++ ChunkCoordIntPair pos = new ChunkCoordIntPair(x, z); ++ if (cps != null) { ++ com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); ++ if (cps.hasChunk(x, z)) { ++ return true; ++ } ++ } ++ ++ NBTTagCompound nbt; ++ try { ++ nbt = read(pos).get().orElse(null); ++ } catch (InterruptedException | ExecutionException ex) { ++ throw new RuntimeException(ex); ++ } ++ if (nbt != null) { ++ NBTTagCompound level = nbt.getCompound("Level"); ++ if (level.getBoolean("TerrainPopulated")) { ++ return true; ++ } ++ ++ ChunkStatus status = ChunkStatus.byName(level.getString("Status")); ++ if (status != null && status.isOrAfter(ChunkStatus.FEATURES)) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ public NBTTagCompound upgradeChunkTag(ResourceKey resourcekey, Supplier supplier, NBTTagCompound nbttagcompound, Optional>> optional, ChunkCoordIntPair pos, @Nullable GeneratorAccess generatoraccess) { ++ // CraftBukkit end + int i = getVersion(nbttagcompound); + ++ // CraftBukkit start ++ if (i < 1466) { ++ NBTTagCompound level = nbttagcompound.getCompound("Level"); ++ if (level.getBoolean("TerrainPopulated") && !level.getBoolean("LightPopulated")) { ++ ChunkProviderServer cps = (generatoraccess == null) ? null : ((WorldServer) generatoraccess).getChunkSource(); ++ if (check(cps, pos.x - 1, pos.z) && check(cps, pos.x - 1, pos.z - 1) && check(cps, pos.x, pos.z - 1)) { ++ level.putBoolean("LightPopulated", true); ++ } ++ } ++ } ++ // CraftBukkit end ++ + if (i < 1493) { + nbttagcompound = DataFixTypes.CHUNK.update(this.fixerUpper, nbttagcompound, i, 1493); + if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) { +@@ -58,7 +111,7 @@ + return nbttagcompound; + } + +- private PersistentStructureLegacy getLegacyStructureHandler(ResourceKey resourcekey, Supplier supplier) { ++ private PersistentStructureLegacy getLegacyStructureHandler(ResourceKey resourcekey, Supplier supplier) { // CraftBukkit + PersistentStructureLegacy persistentstructurelegacy = this.legacyStructureHandler; + + if (persistentstructurelegacy == null) { +@@ -73,7 +126,7 @@ + return persistentstructurelegacy; + } + +- public static void injectDatafixingContext(NBTTagCompound nbttagcompound, ResourceKey resourcekey, Optional>> optional) { ++ public static void injectDatafixingContext(NBTTagCompound nbttagcompound, ResourceKey resourcekey, Optional>> optional) { // CraftBukkit + NBTTagCompound nbttagcompound1 = new NBTTagCompound(); + + nbttagcompound1.putString("dimension", resourcekey.location().toString()); diff --git a/patch-remap/og/net/minecraft/world/level/chunk/storage/RegionFile.patch b/patch-remap/og/net/minecraft/world/level/chunk/storage/RegionFile.patch new file mode 100644 index 0000000000..f9394a9a46 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/chunk/storage/RegionFile.patch @@ -0,0 +1,81 @@ +--- a/net/minecraft/world/level/chunk/storage/RegionFile.java ++++ b/net/minecraft/world/level/chunk/storage/RegionFile.java +@@ -1,3 +1,4 @@ ++// mc-dev import + package net.minecraft.world.level.chunk.storage; + + import com.google.common.annotations.VisibleForTesting; +@@ -57,8 +58,8 @@ + } else { + this.externalFileDir = path1; + this.offsets = this.header.asIntBuffer(); +- this.offsets.limit(1024); +- this.header.position(4096); ++ ((java.nio.Buffer) this.offsets).limit(1024); // CraftBukkit - decompile error ++ ((java.nio.Buffer) this.header).position(4096); // CraftBukkit - decompile error + this.timestamps = this.header.asIntBuffer(); + if (flag) { + this.file = FileChannel.open(path, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.DSYNC); +@@ -67,7 +68,7 @@ + } + + this.usedSectors.force(0, 2); +- this.header.position(0); ++ ((java.nio.Buffer) this.header).position(0); // CraftBukkit - decompile error + int i = this.file.read(this.header, 0L); + + if (i != -1) { +@@ -122,7 +123,7 @@ + ByteBuffer bytebuffer = ByteBuffer.allocate(l); + + this.file.read(bytebuffer, (long) (j * 4096)); +- bytebuffer.flip(); ++ ((java.nio.Buffer) bytebuffer).flip(); // CraftBukkit - decompile error + if (bytebuffer.remaining() < 5) { + RegionFile.LOGGER.error("Chunk {} header is truncated: expected {} but read {}", new Object[]{chunkcoordintpair, l, bytebuffer.remaining()}); + return null; +@@ -224,7 +225,7 @@ + + try { + this.file.read(bytebuffer, (long) (j * 4096)); +- bytebuffer.flip(); ++ ((java.nio.Buffer) bytebuffer).flip(); // CraftBukkit - decompile error + if (bytebuffer.remaining() != 5) { + return false; + } else { +@@ -327,7 +328,7 @@ + + bytebuffer.putInt(1); + bytebuffer.put((byte) (this.version.getId() | 128)); +- bytebuffer.flip(); ++ ((java.nio.Buffer) bytebuffer).flip(); // CraftBukkit - decompile error + return bytebuffer; + } + +@@ -336,7 +337,7 @@ + FileChannel filechannel = FileChannel.open(path1, StandardOpenOption.CREATE, StandardOpenOption.WRITE); + + try { +- bytebuffer.position(5); ++ ((java.nio.Buffer) bytebuffer).position(5); // CraftBukkit - decompile error + filechannel.write(bytebuffer); + } catch (Throwable throwable) { + if (filechannel != null) { +@@ -360,7 +361,7 @@ + } + + private void writeHeader() throws IOException { +- this.header.position(0); ++ ((java.nio.Buffer) this.header).position(0); // CraftBukkit - decompile error + this.file.write(this.header, 0L); + } + +@@ -396,7 +397,7 @@ + if (i != j) { + ByteBuffer bytebuffer = RegionFile.PADDING_BUFFER.duplicate(); + +- bytebuffer.position(0); ++ ((java.nio.Buffer) bytebuffer).position(0); // CraftBukkit - decompile error + this.file.write(bytebuffer, (long) (j - 1)); + } + diff --git a/patch-remap/og/net/minecraft/world/level/chunk/storage/RegionFileCache.patch b/patch-remap/og/net/minecraft/world/level/chunk/storage/RegionFileCache.patch new file mode 100644 index 0000000000..d4050c6461 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/chunk/storage/RegionFileCache.patch @@ -0,0 +1,56 @@ +--- a/net/minecraft/world/level/chunk/storage/RegionFileCache.java ++++ b/net/minecraft/world/level/chunk/storage/RegionFileCache.java +@@ -30,7 +30,7 @@ + this.sync = flag; + } + +- private RegionFile getRegionFile(ChunkCoordIntPair chunkcoordintpair) throws IOException { ++ private RegionFile getRegionFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit + long i = ChunkCoordIntPair.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); + RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i); + +@@ -45,6 +45,7 @@ + Path path = this.folder; + int j = chunkcoordintpair.getRegionX(); + Path path1 = path.resolve("r." + j + "." + chunkcoordintpair.getRegionZ() + ".mca"); ++ if (existingOnly && !java.nio.file.Files.exists(path1)) return null; // CraftBukkit + RegionFile regionfile1 = new RegionFile(path1, this.folder, this.sync); + + this.regionCache.putAndMoveToFirst(i, regionfile1); +@@ -54,7 +55,12 @@ + + @Nullable + public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { +- RegionFile regionfile = this.getRegionFile(chunkcoordintpair); ++ // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing ++ RegionFile regionfile = this.getRegionFile(chunkcoordintpair, true); ++ if (regionfile == null) { ++ return null; ++ } ++ // CraftBukkit end + DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkcoordintpair); + + NBTTagCompound nbttagcompound; +@@ -94,7 +100,12 @@ + } + + public void scanChunk(ChunkCoordIntPair chunkcoordintpair, StreamTagVisitor streamtagvisitor) throws IOException { +- RegionFile regionfile = this.getRegionFile(chunkcoordintpair); ++ // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing ++ RegionFile regionfile = this.getRegionFile(chunkcoordintpair, true); ++ if (regionfile == null) { ++ return; ++ } ++ // CraftBukkit end + DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkcoordintpair); + + try { +@@ -120,7 +131,7 @@ + } + + protected void write(ChunkCoordIntPair chunkcoordintpair, @Nullable NBTTagCompound nbttagcompound) throws IOException { +- RegionFile regionfile = this.getRegionFile(chunkcoordintpair); ++ RegionFile regionfile = this.getRegionFile(chunkcoordintpair, false); // CraftBukkit + + if (nbttagcompound == null) { + regionfile.clear(chunkcoordintpair); diff --git a/patch-remap/og/net/minecraft/world/level/dimension/end/EnderDragonBattle.patch b/patch-remap/og/net/minecraft/world/level/dimension/end/EnderDragonBattle.patch new file mode 100644 index 0000000000..66b3002c09 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/dimension/end/EnderDragonBattle.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/world/level/dimension/end/EnderDragonBattle.java ++++ b/net/minecraft/world/level/dimension/end/EnderDragonBattle.java +@@ -110,14 +110,14 @@ + this.origin = blockposition; + this.validPlayer = IEntitySelector.ENTITY_STILL_ALIVE.and(IEntitySelector.withinDistance((double) blockposition.getX(), (double) (128 + blockposition.getY()), (double) blockposition.getZ(), 192.0D)); + this.needsStateScanning = enderdragonbattle_a.needsStateScanning; +- this.dragonUUID = (UUID) enderdragonbattle_a.dragonUUID.orElse((Object) null); ++ this.dragonUUID = (UUID) enderdragonbattle_a.dragonUUID.orElse(null); // CraftBukkit - decompile error + this.dragonKilled = enderdragonbattle_a.dragonKilled; + this.previouslyKilled = enderdragonbattle_a.previouslyKilled; + if (enderdragonbattle_a.isRespawning) { + this.respawnStage = EnumDragonRespawn.START; + } + +- this.portalLocation = (BlockPosition) enderdragonbattle_a.exitPortalLocation.orElse((Object) null); ++ this.portalLocation = (BlockPosition) enderdragonbattle_a.exitPortalLocation.orElse(null); // CraftBukkit - decompile error + this.gateways.addAll((Collection) enderdragonbattle_a.gateways.orElseGet(() -> { + ObjectArrayList objectarraylist = new ObjectArrayList(ContiguousSet.create(Range.closedOpen(0, 20), DiscreteDomain.integers())); + +@@ -510,7 +510,7 @@ + return this.previouslyKilled; + } + +- public void tryRespawn() { ++ public boolean tryRespawn() { // CraftBukkit - return boolean + if (this.dragonKilled && this.respawnStage == null) { + BlockPosition blockposition = this.portalLocation; + +@@ -537,19 +537,19 @@ + List list1 = this.level.getEntitiesOfClass(EntityEnderCrystal.class, new AxisAlignedBB(blockposition1.relative(enumdirection, 2))); + + if (list1.isEmpty()) { +- return; ++ return false; // CraftBukkit - return value + } + + list.addAll(list1); + } + + EnderDragonBattle.LOGGER.debug("Found all crystals, respawning dragon."); +- this.respawnDragon(list); ++ return this.respawnDragon(list); // CraftBukkit - return value + } +- ++ return false; // CraftBukkit - return value + } + +- public void respawnDragon(List list) { ++ public boolean respawnDragon(List list) { // CraftBukkit - return boolean + if (this.dragonKilled && this.respawnStage == null) { + for (ShapeDetector.ShapeDetectorCollection shapedetector_shapedetectorcollection = this.findExitPortal(); shapedetector_shapedetectorcollection != null; shapedetector_shapedetectorcollection = this.findExitPortal()) { + for (int i = 0; i < this.exitPortalPattern.getWidth(); ++i) { +@@ -569,8 +569,9 @@ + this.respawnTime = 0; + this.spawnExitPortal(false); + this.respawnCrystals = list; ++ return true; // CraftBukkit - return value + } +- ++ return false; // CraftBukkit - return value + } + + public void resetSpikeCrystals() { diff --git a/patch-remap/og/net/minecraft/world/level/entity/PersistentEntitySectionManager.patch b/patch-remap/og/net/minecraft/world/level/entity/PersistentEntitySectionManager.patch new file mode 100644 index 0000000000..2fb5483db0 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/entity/PersistentEntitySectionManager.patch @@ -0,0 +1,148 @@ +--- a/net/minecraft/world/level/entity/PersistentEntitySectionManager.java ++++ b/net/minecraft/world/level/entity/PersistentEntitySectionManager.java +@@ -32,6 +32,11 @@ + import net.minecraft.world.level.ChunkCoordIntPair; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.world.level.chunk.storage.EntityStorage; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class PersistentEntitySectionManager implements AutoCloseable { + + static final Logger LOGGER = LogUtils.getLogger(); +@@ -55,6 +60,16 @@ + this.entityGetter = new LevelEntityGetterAdapter<>(this.visibleEntityStorage, this.sectionStorage); + } + ++ // CraftBukkit start - add method to get all entities in chunk ++ public List getEntities(ChunkCoordIntPair chunkCoordIntPair) { ++ return sectionStorage.getExistingSectionsInChunk(chunkCoordIntPair.toLong()).flatMap(EntitySection::getEntities).map(entity -> (Entity) entity).collect(Collectors.toList()); ++ } ++ ++ public boolean isPending(long pair) { ++ return chunkLoadStatuses.get(pair) == b.PENDING; ++ } ++ // CraftBukkit end ++ + void removeSectionIfEmpty(long i, EntitySection entitysection) { + if (entitysection.isEmpty()) { + this.sectionStorage.remove(i); +@@ -196,6 +211,12 @@ + } + + private boolean storeChunkSections(long i, Consumer consumer) { ++ // CraftBukkit start - add boolean for event call ++ return storeChunkSections(i, consumer, false); ++ } ++ ++ private boolean storeChunkSections(long i, Consumer consumer, boolean callEvent) { ++ // CraftBukkit end + PersistentEntitySectionManager.b persistententitysectionmanager_b = (PersistentEntitySectionManager.b) this.chunkLoadStatuses.get(i); + + if (persistententitysectionmanager_b == PersistentEntitySectionManager.b.PENDING) { +@@ -207,6 +228,7 @@ + + if (list.isEmpty()) { + if (persistententitysectionmanager_b == PersistentEntitySectionManager.b.LOADED) { ++ if (callEvent) CraftEventFactory.callEntitiesUnloadEvent(((EntityStorage) permanentStorage).level, new ChunkCoordIntPair(i), ImmutableList.of()); // CraftBukkit + this.permanentStorage.storeEntities(new ChunkEntities<>(new ChunkCoordIntPair(i), ImmutableList.of())); + } + +@@ -215,6 +237,7 @@ + this.requestChunkLoad(i); + return false; + } else { ++ if (callEvent) CraftEventFactory.callEntitiesUnloadEvent(((EntityStorage) permanentStorage).level, new ChunkCoordIntPair(i), list.stream().map(entity -> (Entity) entity).collect(Collectors.toList())); // CraftBukkit + this.permanentStorage.storeEntities(new ChunkEntities<>(new ChunkCoordIntPair(i), list)); + list.forEach(consumer); + return true; +@@ -238,7 +261,7 @@ + private boolean processChunkUnload(long i) { + boolean flag = this.storeChunkSections(i, (entityaccess) -> { + entityaccess.getPassengersAndSelf().forEach(this::unloadEntity); +- }); ++ }, true); // CraftBukkit - add boolean for event call + + if (!flag) { + return false; +@@ -254,19 +277,23 @@ + } + + private void processUnloads() { +- this.chunksToUnload.removeIf((i) -> { ++ this.chunksToUnload.removeIf((java.util.function.LongPredicate) (i) -> { // CraftBukkit - decompile error + return this.chunkVisibility.get(i) != Visibility.HIDDEN ? true : this.processChunkUnload(i); + }); + } + + private void processPendingLoads() { +- ChunkEntities chunkentities; ++ ChunkEntities chunkentities; // CraftBukkit - decompile error + + while ((chunkentities = (ChunkEntities) this.loadingInbox.poll()) != null) { + chunkentities.getEntities().forEach((entityaccess) -> { + this.addEntity(entityaccess, true); + }); + this.chunkLoadStatuses.put(chunkentities.getPos().toLong(), PersistentEntitySectionManager.b.LOADED); ++ // CraftBukkit start - call entity load event ++ List entities = getEntities(chunkentities.getPos()); ++ CraftEventFactory.callEntitiesLoadEvent(((EntityStorage) permanentStorage).level, chunkentities.getPos(), entities); ++ // CraftBukkit end + } + + } +@@ -292,7 +319,7 @@ + } + + public void autoSave() { +- this.getAllChunksToSave().forEach((i) -> { ++ this.getAllChunksToSave().forEach((java.util.function.LongConsumer) (i) -> { // CraftBukkit - decompile error + boolean flag = this.chunkVisibility.get(i) == Visibility.HIDDEN; + + if (flag) { +@@ -311,7 +338,7 @@ + while (!longset.isEmpty()) { + this.permanentStorage.flush(false); + this.processPendingLoads(); +- longset.removeIf((i) -> { ++ longset.removeIf((java.util.function.LongPredicate) (i) -> { // CraftBukkit - decompile error + boolean flag = this.chunkVisibility.get(i) == Visibility.HIDDEN; + + return flag ? this.processChunkUnload(i) : this.storeChunkSections(i, (entityaccess) -> { +@@ -323,7 +350,15 @@ + } + + public void close() throws IOException { +- this.saveAll(); ++ // CraftBukkit start - add save boolean ++ close(true); ++ } ++ ++ public void close(boolean save) throws IOException { ++ if (save) { ++ this.saveAll(); ++ } ++ // CraftBukkit end + this.permanentStorage.close(); + } + +@@ -350,7 +385,7 @@ + public void dumpSections(Writer writer) throws IOException { + CSVWriter csvwriter = CSVWriter.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("visibility").addColumn("load_status").addColumn("entity_count").build(writer); + +- this.sectionStorage.getAllChunksWithExistingSections().forEach((i) -> { ++ this.sectionStorage.getAllChunksWithExistingSections().forEach((java.util.function.LongConsumer) (i) -> { // CraftBukkit - decompile error + PersistentEntitySectionManager.b persistententitysectionmanager_b = (PersistentEntitySectionManager.b) this.chunkLoadStatuses.get(i); + + this.sectionStorage.getExistingSectionPositionsInChunk(i).forEach((j) -> { +@@ -394,7 +429,7 @@ + private EntitySection currentSection; + + a(EntityAccess entityaccess, long i, EntitySection entitysection) { +- this.entity = entityaccess; ++ this.entity = (T) entityaccess; // CraftBukkit - decompile error + this.currentSectionKey = i; + this.currentSection = entitysection; + } diff --git a/patch-remap/og/net/minecraft/world/level/gameevent/GameEventDispatcher.patch b/patch-remap/og/net/minecraft/world/level/gameevent/GameEventDispatcher.patch new file mode 100644 index 0000000000..079afdc38c --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/gameevent/GameEventDispatcher.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/world/level/gameevent/GameEventDispatcher.java ++++ b/net/minecraft/world/level/gameevent/GameEventDispatcher.java +@@ -11,6 +11,13 @@ + import net.minecraft.world.level.chunk.Chunk; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.CraftGameEvent; ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.world.GenericGameEvent; ++// CraftBukkit end ++ + public class GameEventDispatcher { + + private final WorldServer level; +@@ -22,6 +29,14 @@ + public void post(GameEvent gameevent, Vec3D vec3d, GameEvent.a gameevent_a) { + int i = gameevent.getNotificationRadius(); + BlockPosition blockposition = BlockPosition.containing(vec3d); ++ // CraftBukkit start ++ GenericGameEvent event = new GenericGameEvent(CraftGameEvent.minecraftToBukkit(gameevent), CraftLocation.toBukkit(blockposition, level.getWorld()), (gameevent_a.sourceEntity() == null) ? null : gameevent_a.sourceEntity().getBukkitEntity(), i, !Bukkit.isPrimaryThread()); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ i = event.getRadius(); ++ // CraftBukkit end + int j = SectionPosition.blockToSectionCoord(blockposition.getX() - i); + int k = SectionPosition.blockToSectionCoord(blockposition.getY() - i); + int l = SectionPosition.blockToSectionCoord(blockposition.getZ() - i); diff --git a/patch-remap/og/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.patch b/patch-remap/og/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.patch new file mode 100644 index 0000000000..e36dd6a4bb --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.patch @@ -0,0 +1,51 @@ +--- a/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java ++++ b/net/minecraft/world/level/gameevent/vibrations/VibrationSystem.java +@@ -28,6 +28,12 @@ + import net.minecraft.world.phys.MovingObjectPosition; + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.CraftGameEvent; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.event.block.BlockReceiveGameEvent; ++// CraftBukkit end ++ + public interface VibrationSystem { + + GameEvent[] RESONANCE_EVENTS = new GameEvent[]{GameEvent.RESONATE_1, GameEvent.RESONATE_2, GameEvent.RESONATE_3, GameEvent.RESONATE_4, GameEvent.RESONATE_5, GameEvent.RESONATE_6, GameEvent.RESONATE_7, GameEvent.RESONATE_8, GameEvent.RESONATE_9, GameEvent.RESONATE_10, GameEvent.RESONATE_11, GameEvent.RESONATE_12, GameEvent.RESONATE_13, GameEvent.RESONATE_14, GameEvent.RESONATE_15}; +@@ -227,7 +233,8 @@ + if (vibrationsystem_d.requiresAdjacentChunksToBeTicking() && !areAdjacentChunksTicking(worldserver, blockposition1)) { + return false; + } else { +- vibrationsystem_d.onReceiveVibration(worldserver, blockposition, vibrationinfo.gameEvent(), (Entity) vibrationinfo.getEntity(worldserver).orElse((Object) null), (Entity) vibrationinfo.getProjectileOwner(worldserver).orElse((Object) null), VibrationSystem.b.distanceBetweenInBlocks(blockposition, blockposition1)); ++ // CraftBukkit - decompile error ++ vibrationsystem_d.onReceiveVibration(worldserver, blockposition, vibrationinfo.gameEvent(), (Entity) vibrationinfo.getEntity(worldserver).orElse(null), (Entity) vibrationinfo.getProjectileOwner(worldserver).orElse(null), VibrationSystem.b.distanceBetweenInBlocks(blockposition, blockposition1)); + vibrationsystem_a.setCurrentVibration((VibrationInfo) null); + return true; + } +@@ -282,8 +289,14 @@ + return false; + } else { + Vec3D vec3d1 = (Vec3D) optional.get(); +- +- if (!vibrationsystem_d.canReceiveVibration(worldserver, BlockPosition.containing(vec3d), gameevent, gameevent_a)) { ++ // CraftBukkit start ++ boolean defaultCancel = !vibrationsystem_d.canReceiveVibration(worldserver, BlockPosition.containing(vec3d), gameevent, gameevent_a); ++ Entity entity = gameevent_a.sourceEntity(); ++ BlockReceiveGameEvent event = new BlockReceiveGameEvent(CraftGameEvent.minecraftToBukkit(gameevent), CraftBlock.at(worldserver, BlockPosition.containing(vec3d1)), (entity == null) ? null : entity.getBukkitEntity()); ++ event.setCancelled(defaultCancel); ++ worldserver.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ // CraftBukkit end + return false; + } else if (isOccluded(worldserver, vec3d, vec3d1)) { + return false; +@@ -336,7 +349,7 @@ + return instance.group(VibrationInfo.CODEC.optionalFieldOf("event").forGetter((vibrationsystem_a) -> { + return Optional.ofNullable(vibrationsystem_a.currentVibration); + }), VibrationSelector.CODEC.fieldOf("selector").forGetter(VibrationSystem.a::getSelectionStrategy), ExtraCodecs.NON_NEGATIVE_INT.fieldOf("event_delay").orElse(0).forGetter(VibrationSystem.a::getTravelTimeInTicks)).apply(instance, (optional, vibrationselector, integer) -> { +- return new VibrationSystem.a((VibrationInfo) optional.orElse((Object) null), vibrationselector, integer, true); ++ return new VibrationSystem.a((VibrationInfo) optional.orElse(null), vibrationselector, integer, true); // CraftBukkit - decompile error + }); + }); + public static final String NBT_TAG_KEY = "listener"; diff --git a/patch-remap/og/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.patch b/patch-remap/og/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.patch new file mode 100644 index 0000000000..9e7f2e0416 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.patch @@ -0,0 +1,7 @@ +--- a/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java ++++ b/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java +@@ -1,3 +1,4 @@ ++// keep + package net.minecraft.world.level.levelgen; + + import com.google.common.annotations.VisibleForTesting; diff --git a/patch-remap/og/net/minecraft/world/level/levelgen/ChunkProviderFlat.patch b/patch-remap/og/net/minecraft/world/level/levelgen/ChunkProviderFlat.patch new file mode 100644 index 0000000000..6434e53e09 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/levelgen/ChunkProviderFlat.patch @@ -0,0 +1,22 @@ +--- a/net/minecraft/world/level/levelgen/ChunkProviderFlat.java ++++ b/net/minecraft/world/level/levelgen/ChunkProviderFlat.java +@@ -35,10 +35,16 @@ + private final GeneratorSettingsFlat settings; + + public ChunkProviderFlat(GeneratorSettingsFlat generatorsettingsflat) { +- WorldChunkManagerHell worldchunkmanagerhell = new WorldChunkManagerHell(generatorsettingsflat.getBiome()); ++ // CraftBukkit start ++ // WorldChunkManagerHell worldchunkmanagerhell = new WorldChunkManagerHell(generatorsettingsflat.getBiome()); + +- Objects.requireNonNull(generatorsettingsflat); +- super(worldchunkmanagerhell, SystemUtils.memoize(generatorsettingsflat::adjustGenerationSettings)); ++ // Objects.requireNonNull(generatorsettingsflat); ++ this(generatorsettingsflat, new WorldChunkManagerHell(generatorsettingsflat.getBiome())); ++ } ++ ++ public ChunkProviderFlat(GeneratorSettingsFlat generatorsettingsflat, net.minecraft.world.level.biome.WorldChunkManager worldchunkmanager) { ++ super(worldchunkmanager, SystemUtils.memoize(generatorsettingsflat::adjustGenerationSettings)); ++ // CraftBukkit end + this.settings = generatorsettingsflat; + } + diff --git a/patch-remap/og/net/minecraft/world/level/levelgen/MobSpawnerPatrol.patch b/patch-remap/og/net/minecraft/world/level/levelgen/MobSpawnerPatrol.patch new file mode 100644 index 0000000000..4320791a07 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/levelgen/MobSpawnerPatrol.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java ++++ b/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java +@@ -117,7 +117,7 @@ + + entitymonsterpatrolling.setPos((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()); + entitymonsterpatrolling.finalizeSpawn(worldserver, worldserver.getCurrentDifficultyAt(blockposition), EnumMobSpawn.PATROL, (GroupDataEntity) null, (NBTTagCompound) null); +- worldserver.addFreshEntityWithPassengers(entitymonsterpatrolling); ++ worldserver.addFreshEntityWithPassengers(entitymonsterpatrolling, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.PATROL); // CraftBukkit + return true; + } else { + return false; diff --git a/patch-remap/og/net/minecraft/world/level/levelgen/MobSpawnerPhantom.patch b/patch-remap/og/net/minecraft/world/level/levelgen/MobSpawnerPhantom.patch new file mode 100644 index 0000000000..dd29749c1a --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/levelgen/MobSpawnerPhantom.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java ++++ b/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java +@@ -75,7 +75,7 @@ + if (entityphantom != null) { + entityphantom.moveTo(blockposition1, 0.0F, 0.0F); + groupdataentity = entityphantom.finalizeSpawn(worldserver, difficultydamagescaler, EnumMobSpawn.NATURAL, groupdataentity, (NBTTagCompound) null); +- worldserver.addFreshEntityWithPassengers(entityphantom); ++ worldserver.addFreshEntityWithPassengers(entityphantom, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit + ++i; + } + } diff --git a/patch-remap/og/net/minecraft/world/level/levelgen/structure/PersistentStructureLegacy.patch b/patch-remap/og/net/minecraft/world/level/levelgen/structure/PersistentStructureLegacy.patch new file mode 100644 index 0000000000..1c6fcf5985 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/levelgen/structure/PersistentStructureLegacy.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/level/levelgen/structure/PersistentStructureLegacy.java ++++ b/net/minecraft/world/level/levelgen/structure/PersistentStructureLegacy.java +@@ -21,6 +21,10 @@ + import net.minecraft.world.level.World; + import net.minecraft.world.level.storage.WorldPersistentData; + ++// CraftBukkit start ++import net.minecraft.world.level.dimension.WorldDimension; ++// CraftBukkit end ++ + public class PersistentStructureLegacy { + + private static final Map CURRENT_TO_LEGACY_MAP = (Map) SystemUtils.make(Maps.newHashMap(), (hashmap) -> { +@@ -236,16 +240,16 @@ + } + } + +- public static PersistentStructureLegacy getLegacyStructureHandler(ResourceKey resourcekey, @Nullable WorldPersistentData worldpersistentdata) { +- if (resourcekey == World.OVERWORLD) { ++ public static PersistentStructureLegacy getLegacyStructureHandler(ResourceKey resourcekey, @Nullable WorldPersistentData worldpersistentdata) { // CraftBukkit ++ if (resourcekey == WorldDimension.OVERWORLD) { // CraftBukkit + return new PersistentStructureLegacy(worldpersistentdata, ImmutableList.of("Monument", "Stronghold", "Village", "Mineshaft", "Temple", "Mansion"), ImmutableList.of("Village", "Mineshaft", "Mansion", "Igloo", "Desert_Pyramid", "Jungle_Pyramid", "Swamp_Hut", "Stronghold", "Monument")); + } else { + ImmutableList immutablelist; + +- if (resourcekey == World.NETHER) { ++ if (resourcekey == WorldDimension.NETHER) { // CraftBukkit + immutablelist = ImmutableList.of("Fortress"); + return new PersistentStructureLegacy(worldpersistentdata, immutablelist, immutablelist); +- } else if (resourcekey == World.END) { ++ } else if (resourcekey == WorldDimension.END) { // CraftBukkit + immutablelist = ImmutableList.of("EndCity"); + return new PersistentStructureLegacy(worldpersistentdata, immutablelist, immutablelist); + } else { diff --git a/patch-remap/og/net/minecraft/world/level/levelgen/structure/StructurePiece.patch b/patch-remap/og/net/minecraft/world/level/levelgen/structure/StructurePiece.patch new file mode 100644 index 0000000000..290d5b21c9 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/levelgen/structure/StructurePiece.patch @@ -0,0 +1,160 @@ +--- a/net/minecraft/world/level/levelgen/structure/StructurePiece.java ++++ b/net/minecraft/world/level/levelgen/structure/StructurePiece.java +@@ -50,7 +50,7 @@ + private EnumBlockRotation rotation; + protected int genDepth; + private final WorldGenFeatureStructurePieceType type; +- private static final Set SHAPE_CHECK_BLOCKS = ImmutableSet.builder().add(Blocks.NETHER_BRICK_FENCE).add(Blocks.TORCH).add(Blocks.WALL_TORCH).add(Blocks.OAK_FENCE).add(Blocks.SPRUCE_FENCE).add(Blocks.DARK_OAK_FENCE).add(Blocks.ACACIA_FENCE).add(Blocks.BIRCH_FENCE).add(Blocks.JUNGLE_FENCE).add(Blocks.LADDER).add(Blocks.IRON_BARS).build(); ++ public static final Set SHAPE_CHECK_BLOCKS = ImmutableSet.builder().add(Blocks.NETHER_BRICK_FENCE).add(Blocks.TORCH).add(Blocks.WALL_TORCH).add(Blocks.OAK_FENCE).add(Blocks.SPRUCE_FENCE).add(Blocks.DARK_OAK_FENCE).add(Blocks.ACACIA_FENCE).add(Blocks.BIRCH_FENCE).add(Blocks.JUNGLE_FENCE).add(Blocks.LADDER).add(Blocks.IRON_BARS).build(); // CraftBukkit - decompile error / PAIL private -> public + + protected StructurePiece(WorldGenFeatureStructurePieceType worldgenfeaturestructurepiecetype, int i, StructureBoundingBox structureboundingbox) { + this.type = worldgenfeaturestructurepiecetype; +@@ -59,14 +59,11 @@ + } + + public StructurePiece(WorldGenFeatureStructurePieceType worldgenfeaturestructurepiecetype, NBTTagCompound nbttagcompound) { +- int i = nbttagcompound.getInt("GD"); +- DataResult dataresult = StructureBoundingBox.CODEC.parse(DynamicOpsNBT.INSTANCE, nbttagcompound.get("BB")); +- Logger logger = StructurePiece.LOGGER; +- +- Objects.requireNonNull(logger); +- this(worldgenfeaturestructurepiecetype, i, (StructureBoundingBox) dataresult.resultOrPartial(logger::error).orElseThrow(() -> { ++ // CraftBukkit start - decompile error ++ this(worldgenfeaturestructurepiecetype, nbttagcompound.getInt("GD"), (StructureBoundingBox) StructureBoundingBox.CODEC.parse(DynamicOpsNBT.INSTANCE, nbttagcompound.get("BB")).resultOrPartial(Objects.requireNonNull(StructurePiece.LOGGER)::error).orElseThrow(() -> { + return new IllegalArgumentException("Invalid boundingbox"); + })); ++ // CraftBukkit end + int j = nbttagcompound.getInt("O"); + + this.setOrientation(j == -1 ? null : EnumDirection.from2DDataValue(j)); +@@ -84,13 +81,11 @@ + NBTTagCompound nbttagcompound = new NBTTagCompound(); + + nbttagcompound.putString("id", BuiltInRegistries.STRUCTURE_PIECE.getKey(this.getType()).toString()); +- DataResult dataresult = StructureBoundingBox.CODEC.encodeStart(DynamicOpsNBT.INSTANCE, this.boundingBox); +- Logger logger = StructurePiece.LOGGER; +- +- Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { +- nbttagcompound.put("BB", nbtbase); ++ // CraftBukkit start - decompile error ++ StructureBoundingBox.CODEC.encodeStart(DynamicOpsNBT.INSTANCE, this.boundingBox).resultOrPartial(Objects.requireNonNull(StructurePiece.LOGGER)::error).ifPresent((nbtbase) -> { ++ nbttagcompound.put("BB", nbtbase); + }); ++ // CraftBukkit end + EnumDirection enumdirection = this.getOrientation(); + + nbttagcompound.putInt("O", enumdirection == null ? -1 : enumdirection.get2DDataValue()); +@@ -190,6 +185,11 @@ + } + + generatoraccessseed.setBlock(blockposition_mutableblockposition, iblockdata, 2); ++ // CraftBukkit start - fluid handling is already done if we have a transformer generator access ++ if (generatoraccessseed instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess) { ++ return; ++ } ++ // CraftBukkit end + Fluid fluid = generatoraccessseed.getFluidState(blockposition_mutableblockposition); + + if (!fluid.isEmpty()) { +@@ -204,6 +204,38 @@ + } + } + ++ // CraftBukkit start ++ protected boolean placeCraftBlockEntity(WorldAccess worldAccess, BlockPosition position, org.bukkit.craftbukkit.block.CraftBlockEntityState craftBlockEntityState, int i) { ++ if (worldAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ return transformerAccess.setCraftBlock(position, craftBlockEntityState, i); ++ } ++ boolean result = worldAccess.setBlock(position, craftBlockEntityState.getHandle(), i); ++ TileEntity tileEntity = worldAccess.getBlockEntity(position); ++ if (tileEntity != null) { ++ tileEntity.load(craftBlockEntityState.getSnapshotNBT()); ++ } ++ return result; ++ } ++ ++ protected void placeCraftSpawner(WorldAccess worldAccess, BlockPosition position, org.bukkit.entity.EntityType entityType, int i) { ++ // This method is used in structures that are generated by code and place spawners as they set the entity after the block was placed making it impossible for plugins to access that information ++ org.bukkit.craftbukkit.block.CraftCreatureSpawner spawner = (org.bukkit.craftbukkit.block.CraftCreatureSpawner) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(position, Blocks.SPAWNER.defaultBlockState(), null); ++ spawner.setSpawnedType(entityType); ++ placeCraftBlockEntity(worldAccess, position, spawner, i); ++ } ++ ++ protected void setCraftLootTable(WorldAccess worldAccess, BlockPosition position, RandomSource randomSource, net.minecraft.resources.MinecraftKey loottableKey) { ++ // This method is used in structures that use data markers to a loot table to loot containers as otherwise plugins won't have access to that information. ++ net.minecraft.world.level.block.entity.TileEntity tileEntity = worldAccess.getBlockEntity(position); ++ if (tileEntity instanceof net.minecraft.world.level.block.entity.TileEntityLootable tileEntityLootable) { ++ tileEntityLootable.setLootTable(loottableKey, randomSource.nextLong()); ++ if (worldAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ transformerAccess.setCraftBlock(position, (org.bukkit.craftbukkit.block.CraftBlockState) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(position, tileEntity.getBlockState(), tileEntityLootable.saveWithFullMetadata()), 3); ++ } ++ } ++ } ++ // CraftBukkit end ++ + protected boolean canBeReplaced(IWorldReader iworldreader, int i, int j, int k, StructureBoundingBox structureboundingbox) { + return true; + } +@@ -397,12 +429,20 @@ + iblockdata = reorient(worldaccess, blockposition, Blocks.CHEST.defaultBlockState()); + } + ++ // CraftBukkit start ++ /* + worldaccess.setBlock(blockposition, iblockdata, 2); + TileEntity tileentity = worldaccess.getBlockEntity(blockposition); + + if (tileentity instanceof TileEntityChest) { + ((TileEntityChest) tileentity).setLootTable(minecraftkey, randomsource.nextLong()); + } ++ */ ++ org.bukkit.craftbukkit.block.CraftChest chestState = (org.bukkit.craftbukkit.block.CraftChest) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockposition, iblockdata, null); ++ chestState.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(minecraftkey))); ++ chestState.setSeed(randomsource.nextLong()); ++ placeCraftBlockEntity(worldaccess, blockposition, chestState, 2); ++ // CraftBukkit end + + return true; + } else { +@@ -414,12 +454,31 @@ + BlockPosition.MutableBlockPosition blockposition_mutableblockposition = this.getWorldPos(i, j, k); + + if (structureboundingbox.isInside(blockposition_mutableblockposition) && !generatoraccessseed.getBlockState(blockposition_mutableblockposition).is(Blocks.DISPENSER)) { ++ // CraftBukkit start ++ /* + this.placeBlock(generatoraccessseed, (IBlockData) Blocks.DISPENSER.defaultBlockState().setValue(BlockDispenser.FACING, enumdirection), i, j, k, structureboundingbox); + TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); + + if (tileentity instanceof TileEntityDispenser) { + ((TileEntityDispenser) tileentity).setLootTable(minecraftkey, randomsource.nextLong()); + } ++ */ ++ if (!this.canBeReplaced(generatoraccessseed, i, j, k, structureboundingbox)) { ++ return true; ++ } ++ IBlockData iblockdata = Blocks.DISPENSER.defaultBlockState().setValue(BlockDispenser.FACING, enumdirection); ++ if (this.mirror != EnumBlockMirror.NONE) { ++ iblockdata = iblockdata.mirror(this.mirror); ++ } ++ if (this.rotation != EnumBlockRotation.NONE) { ++ iblockdata = iblockdata.rotate(this.rotation); ++ } ++ ++ org.bukkit.craftbukkit.block.CraftDispenser dispenserState = (org.bukkit.craftbukkit.block.CraftDispenser) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockposition_mutableblockposition, iblockdata, null); ++ dispenserState.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(minecraftkey))); ++ dispenserState.setSeed(randomsource.nextLong()); ++ placeCraftBlockEntity(generatoraccessseed, blockposition_mutableblockposition, dispenserState, 2); ++ // CraftBukkit end + + return true; + } else { +@@ -432,7 +491,7 @@ + } + + public static StructureBoundingBox createBoundingBox(Stream stream) { +- Stream stream1 = stream.map(StructurePiece::getBoundingBox); ++ Stream stream1 = stream.map(StructurePiece::getBoundingBox); // CraftBukkit - decompile error + + Objects.requireNonNull(stream1); + return (StructureBoundingBox) StructureBoundingBox.encapsulatingBoxes(stream1::iterator).orElseThrow(() -> { diff --git a/patch-remap/og/net/minecraft/world/level/levelgen/structure/StructureStart.patch b/patch-remap/og/net/minecraft/world/level/levelgen/structure/StructureStart.patch new file mode 100644 index 0000000000..f94fcf5193 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/levelgen/structure/StructureStart.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/world/level/levelgen/structure/StructureStart.java ++++ b/net/minecraft/world/level/levelgen/structure/StructureStart.java +@@ -31,6 +31,7 @@ + private int references; + @Nullable + private volatile StructureBoundingBox cachedBoundingBox; ++ public org.bukkit.event.world.AsyncStructureGenerateEvent.Cause generationEventCause = org.bukkit.event.world.AsyncStructureGenerateEvent.Cause.WORLD_GENERATION; // CraftBukkit + + public StructureStart(Structure structure, ChunkCoordIntPair chunkcoordintpair, int i, PiecesContainer piecescontainer) { + this.structure = structure; +@@ -91,6 +92,8 @@ + StructureBoundingBox structureboundingbox1 = ((StructurePiece) list.get(0)).boundingBox; + BlockPosition blockposition = structureboundingbox1.getCenter(); + BlockPosition blockposition1 = new BlockPosition(blockposition.getX(), structureboundingbox1.minY(), blockposition.getZ()); ++ // CraftBukkit start ++ /* + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +@@ -100,6 +103,18 @@ + structurepiece.postProcess(generatoraccessseed, structuremanager, chunkgenerator, randomsource, structureboundingbox, chunkcoordintpair, blockposition1); + } + } ++ */ ++ List pieces = list.stream().filter(piece -> piece.getBoundingBox().intersects(structureboundingbox)).toList(); ++ if (!pieces.isEmpty()) { ++ org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess = new org.bukkit.craftbukkit.util.TransformerGeneratorAccess(); ++ transformerAccess.setHandle(generatoraccessseed); ++ transformerAccess.setStructureTransformer(new org.bukkit.craftbukkit.util.CraftStructureTransformer(generationEventCause, generatoraccessseed, structuremanager, structure, structureboundingbox, chunkcoordintpair)); ++ for (StructurePiece piece : pieces) { ++ piece.postProcess(transformerAccess, structuremanager, chunkgenerator, randomsource, structureboundingbox, chunkcoordintpair, blockposition1); ++ } ++ transformerAccess.getStructureTransformer().discard(); ++ } ++ // CraftBukkit end + + this.structure.afterPlace(generatoraccessseed, structuremanager, chunkgenerator, randomsource, structureboundingbox, chunkcoordintpair, this.pieceContainer); + } diff --git a/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.patch b/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.patch new file mode 100644 index 0000000000..a015136b4f --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java +@@ -70,6 +70,15 @@ + + private static void placeSuspiciousSand(StructureBoundingBox structureboundingbox, GeneratorAccessSeed generatoraccessseed, BlockPosition blockposition) { + if (structureboundingbox.isInside(blockposition)) { ++ // CraftBukkit start ++ if (generatoraccessseed instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ org.bukkit.craftbukkit.block.CraftBrushableBlock brushableState = (org.bukkit.craftbukkit.block.CraftBrushableBlock) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockposition, Blocks.SUSPICIOUS_SAND.defaultBlockState(), null); ++ brushableState.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(LootTables.DESERT_PYRAMID_ARCHAEOLOGY))); ++ brushableState.setSeed(blockposition.asLong()); ++ transformerAccess.setCraftBlock(blockposition, brushableState, 2); ++ return; ++ } ++ // CraftBukkit end + generatoraccessseed.setBlock(blockposition, Blocks.SUSPICIOUS_SAND.defaultBlockState(), 2); + generatoraccessseed.getBlockEntity(blockposition, TileEntityTypes.BRUSHABLE_BLOCK).ifPresent((brushableblockentity) -> { + brushableblockentity.setLootTable(LootTables.DESERT_PYRAMID_ARCHAEOLOGY, blockposition.asLong()); diff --git a/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.patch b/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.patch new file mode 100644 index 0000000000..de8fd65afb --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java +@@ -284,7 +284,12 @@ + BlockPosition blockposition1 = blockposition.below(); + + if (structureboundingbox.isInside(blockposition1)) { ++ // CraftBukkit start - ensure block transformation ++ /* + RandomizableContainer.setBlockEntityLootTable(worldaccess, randomsource, blockposition1, LootTables.END_CITY_TREASURE); ++ */ ++ setCraftLootTable(worldaccess, blockposition1, randomsource, LootTables.END_CITY_TREASURE); ++ // CraftBukkit end + } + } else if (structureboundingbox.isInside(blockposition) && World.isInSpawnableBounds(blockposition)) { + if (s.startsWith("Sentry")) { diff --git a/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.patch b/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.patch new file mode 100644 index 0000000000..5d607215b4 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.patch @@ -0,0 +1,19 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java +@@ -85,11 +85,16 @@ + protected void handleDataMarker(String s, BlockPosition blockposition, WorldAccess worldaccess, RandomSource randomsource, StructureBoundingBox structureboundingbox) { + if ("chest".equals(s)) { + worldaccess.setBlock(blockposition, Blocks.AIR.defaultBlockState(), 3); ++ // CraftBukkit start - ensure block transformation ++ /* + TileEntity tileentity = worldaccess.getBlockEntity(blockposition.below()); + + if (tileentity instanceof TileEntityChest) { + ((TileEntityChest) tileentity).setLootTable(LootTables.IGLOO_CHEST, randomsource.nextLong()); + } ++ */ ++ setCraftLootTable(worldaccess, blockposition.below(), randomsource, LootTables.IGLOO_CHEST); ++ // CraftBukkit end + + } + } diff --git a/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.patch b/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.patch new file mode 100644 index 0000000000..2cedb04da6 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java +@@ -42,6 +42,10 @@ + import net.minecraft.world.level.storage.loot.LootTables; + import org.slf4j.Logger; + ++// CraftBukkit start - imports ++import net.minecraft.nbt.NBTBase; ++// CraftBukkit end ++ + public class MineshaftPieces { + + static final Logger LOGGER = LogUtils.getLogger(); +@@ -514,6 +518,8 @@ + + if (structureboundingbox.isInside(blockposition_mutableblockposition) && this.isInterior(generatoraccessseed, 1, 0, l, structureboundingbox)) { + this.hasPlacedSpider = true; ++ // CraftBukkit start ++ /* + generatoraccessseed.setBlock(blockposition_mutableblockposition, Blocks.SPAWNER.defaultBlockState(), 2); + TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); + +@@ -522,6 +528,9 @@ + + tileentitymobspawner.setEntityId(EntityTypes.CAVE_SPIDER, randomsource); + } ++ */ ++ placeCraftSpawner(generatoraccessseed, blockposition_mutableblockposition, org.bukkit.entity.EntityType.CAVE_SPIDER, 2); ++ // CraftBukkit end + } + } + } +@@ -813,11 +822,11 @@ + + public d(NBTTagCompound nbttagcompound) { + super(WorldGenFeatureStructurePieceType.MINE_SHAFT_ROOM, nbttagcompound); +- DataResult dataresult = StructureBoundingBox.CODEC.listOf().parse(DynamicOpsNBT.INSTANCE, nbttagcompound.getList("Entrances", 11)); ++ DataResult> dataresult = StructureBoundingBox.CODEC.listOf().parse(DynamicOpsNBT.INSTANCE, nbttagcompound.getList("Entrances", 11)); // CraftBukkit - decompile error + Logger logger = MineshaftPieces.LOGGER; + + Objects.requireNonNull(logger); +- Optional optional = dataresult.resultOrPartial(logger::error); ++ Optional> optional = dataresult.resultOrPartial(logger::error); // CraftBukkit - decompile error + List list = this.childEntranceBoxes; + + Objects.requireNonNull(this.childEntranceBoxes); +@@ -923,7 +932,7 @@ + @Override + protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, NBTTagCompound nbttagcompound) { + super.addAdditionalSaveData(structurepieceserializationcontext, nbttagcompound); +- DataResult dataresult = StructureBoundingBox.CODEC.listOf().encodeStart(DynamicOpsNBT.INSTANCE, this.childEntranceBoxes); ++ DataResult dataresult = StructureBoundingBox.CODEC.listOf().encodeStart(DynamicOpsNBT.INSTANCE, this.childEntranceBoxes); // CraftBukkit - decompile error + Logger logger = MineshaftPieces.LOGGER; + + Objects.requireNonNull(logger); diff --git a/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.patch b/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.patch new file mode 100644 index 0000000000..ab12d63ae0 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java +@@ -428,6 +428,8 @@ + + if (structureboundingbox.isInside(blockposition_mutableblockposition)) { + this.hasPlacedSpawner = true; ++ // CraftBukkit start ++ /* + generatoraccessseed.setBlock(blockposition_mutableblockposition, Blocks.SPAWNER.defaultBlockState(), 2); + TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); + +@@ -436,6 +438,9 @@ + + tileentitymobspawner.setEntityId(EntityTypes.BLAZE, randomsource); + } ++ */ ++ placeCraftSpawner(generatoraccessseed, blockposition_mutableblockposition, org.bukkit.entity.EntityType.BLAZE, 2); ++ // CraftBukkit end + } + } + diff --git a/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.patch b/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.patch new file mode 100644 index 0000000000..f73431b188 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java +@@ -198,12 +198,20 @@ + @Override + protected void handleDataMarker(String s, BlockPosition blockposition, WorldAccess worldaccess, RandomSource randomsource, StructureBoundingBox structureboundingbox) { + if ("chest".equals(s)) { ++ // CraftBukkit start - transform block to ensure loot table is accessible ++ /* + worldaccess.setBlock(blockposition, (IBlockData) Blocks.CHEST.defaultBlockState().setValue(BlockChest.WATERLOGGED, worldaccess.getFluidState(blockposition).is(TagsFluid.WATER)), 2); + TileEntity tileentity = worldaccess.getBlockEntity(blockposition); + + if (tileentity instanceof TileEntityChest) { + ((TileEntityChest) tileentity).setLootTable(this.isLarge ? LootTables.UNDERWATER_RUIN_BIG : LootTables.UNDERWATER_RUIN_SMALL, randomsource.nextLong()); + } ++ */ ++ org.bukkit.craftbukkit.block.CraftChest craftChest = (org.bukkit.craftbukkit.block.CraftChest) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockposition, Blocks.CHEST.defaultBlockState().setValue(BlockChest.WATERLOGGED, worldaccess.getFluidState(blockposition).is(TagsFluid.WATER)), null); ++ craftChest.setSeed(randomsource.nextLong()); ++ craftChest.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.isLarge ? LootTables.UNDERWATER_RUIN_BIG : LootTables.UNDERWATER_RUIN_SMALL))); ++ placeCraftBlockEntity(worldaccess, blockposition, craftChest, 2); ++ // CraftBukkit end + } else if ("drowned".equals(s)) { + EntityDrowned entitydrowned = (EntityDrowned) EntityTypes.DROWNED.create(worldaccess.getLevel()); + diff --git a/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.patch b/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.patch new file mode 100644 index 0000000000..b1409167ea --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java +@@ -53,7 +53,7 @@ + public boolean doPlace(int i) { + return super.doPlace(i) && i > 5; + } +- }}; ++ } }; // CraftBukkit - fix decompile styling + private static List currentPieces; + static Class imposedPiece; + private static int totalWeight; +@@ -1136,6 +1136,8 @@ + + if (structureboundingbox.isInside(blockposition_mutableblockposition)) { + this.hasPlacedSpawner = true; ++ // CraftBukkit start ++ /* + generatoraccessseed.setBlock(blockposition_mutableblockposition, Blocks.SPAWNER.defaultBlockState(), 2); + TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); + +@@ -1144,6 +1146,9 @@ + + tileentitymobspawner.setEntityId(EntityTypes.SILVERFISH, randomsource); + } ++ */ ++ placeCraftSpawner(generatoraccessseed, blockposition_mutableblockposition, org.bukkit.entity.EntityType.SILVERFISH, 2); ++ // CraftBukkit end + } + } + diff --git a/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.patch b/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.patch new file mode 100644 index 0000000000..0dc4ec2371 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.patch @@ -0,0 +1,20 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/SwampHutPiece.java +@@ -100,7 +100,7 @@ + entitywitch.setPersistenceRequired(); + entitywitch.moveTo((double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + 0.5D, 0.0F, 0.0F); + entitywitch.finalizeSpawn(generatoraccessseed, generatoraccessseed.getCurrentDifficultyAt(blockposition_mutableblockposition), EnumMobSpawn.STRUCTURE, (GroupDataEntity) null, (NBTTagCompound) null); +- generatoraccessseed.addFreshEntityWithPassengers(entitywitch); ++ generatoraccessseed.addFreshEntityWithPassengers(entitywitch, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN); // CraftBukkit - add SpawnReason + } + } + } +@@ -121,7 +121,7 @@ + entitycat.setPersistenceRequired(); + entitycat.moveTo((double) blockposition_mutableblockposition.getX() + 0.5D, (double) blockposition_mutableblockposition.getY(), (double) blockposition_mutableblockposition.getZ() + 0.5D, 0.0F, 0.0F); + entitycat.finalizeSpawn(worldaccess, worldaccess.getCurrentDifficultyAt(blockposition_mutableblockposition), EnumMobSpawn.STRUCTURE, (GroupDataEntity) null, (NBTTagCompound) null); +- worldaccess.addFreshEntityWithPassengers(entitycat); ++ worldaccess.addFreshEntityWithPassengers(entitycat, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN); // CraftBukkit - add SpawnReason + } + } + } diff --git a/patch-remap/og/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.patch b/patch-remap/og/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.patch new file mode 100644 index 0000000000..fc7d71b539 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.patch @@ -0,0 +1,147 @@ +--- a/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java ++++ b/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java +@@ -52,6 +52,12 @@ + import net.minecraft.world.phys.shapes.VoxelShapeBitSet; + import net.minecraft.world.phys.shapes.VoxelShapeDiscrete; + ++// CraftBukkit start ++import net.minecraft.nbt.NBTBase; ++import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer; ++import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry; ++// CraftBukkit end ++ + public class DefinedStructure { + + public static final String PALETTE_TAG = "palette"; +@@ -70,6 +76,11 @@ + private BaseBlockPosition size; + private String author; + ++ // CraftBukkit start - data containers ++ private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); ++ public CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); ++ // CraftBukkit end ++ + public DefinedStructure() { + this.size = BaseBlockPosition.ZERO; + this.author = "?"; +@@ -143,7 +154,7 @@ + } + + private static List buildInfoList(List list, List list1, List list2) { +- Comparator comparator = Comparator.comparingInt((definedstructure_blockinfo) -> { ++ Comparator comparator = Comparator.comparingInt((definedstructure_blockinfo) -> { // CraftBukkit - decompile error + return definedstructure_blockinfo.pos.getY(); + }).thenComparingInt((definedstructure_blockinfo) -> { + return definedstructure_blockinfo.pos.getX(); +@@ -229,6 +240,19 @@ + if (this.palettes.isEmpty()) { + return false; + } else { ++ // CraftBukkit start ++ // We only want the TransformerGeneratorAccess at certain locations because in here are many "block update" calls that shouldn't be transformed ++ WorldAccess wrappedAccess = worldaccess; ++ org.bukkit.craftbukkit.util.CraftStructureTransformer structureTransformer = null; ++ if (wrappedAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ worldaccess = transformerAccess.getHandle(); ++ structureTransformer = transformerAccess.getStructureTransformer(); ++ // The structureTransformer is not needed if we can not transform blocks therefore we can save a little bit of performance doing this ++ if (structureTransformer != null && !structureTransformer.canTransformBlocks()) { ++ structureTransformer = null; ++ } ++ } ++ // CraftBukkit end + List list = definedstructureinfo.getRandomPalette(this.palettes, blockposition).blocks(); + + if ((!list.isEmpty() || !definedstructureinfo.isIgnoreEntities() && !this.entityInfoList.isEmpty()) && this.size.getX() >= 1 && this.size.getY() >= 1 && this.size.getZ() >= 1) { +@@ -260,6 +284,20 @@ + Clearable.tryClear(tileentity); + worldaccess.setBlock(blockposition2, Blocks.BARRIER.defaultBlockState(), 20); + } ++ // CraftBukkit start ++ if (structureTransformer != null) { ++ org.bukkit.craftbukkit.block.CraftBlockState craftBlockState = (org.bukkit.craftbukkit.block.CraftBlockState) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockposition2, iblockdata, null); ++ if (definedstructure_blockinfo.nbt != null && craftBlockState instanceof org.bukkit.craftbukkit.block.CraftBlockEntityState entityState) { ++ entityState.loadData(definedstructure_blockinfo.nbt); ++ if (craftBlockState instanceof org.bukkit.craftbukkit.block.CraftLootable craftLootable) { ++ craftLootable.setSeed(randomsource.nextLong()); ++ } ++ } ++ craftBlockState = structureTransformer.transformCraftState(craftBlockState); ++ iblockdata = craftBlockState.getHandle(); ++ definedstructure_blockinfo = new DefinedStructure.BlockInfo(blockposition2, iblockdata, (craftBlockState instanceof org.bukkit.craftbukkit.block.CraftBlockEntityState craftBlockEntityState ? craftBlockEntityState.getSnapshotNBT() : null)); ++ } ++ // CraftBukkit end + + if (worldaccess.setBlock(blockposition2, iblockdata, i)) { + j = Math.min(j, blockposition2.getX()); +@@ -272,7 +310,7 @@ + if (definedstructure_blockinfo.nbt != null) { + tileentity = worldaccess.getBlockEntity(blockposition2); + if (tileentity != null) { +- if (tileentity instanceof RandomizableContainer) { ++ if (structureTransformer == null && tileentity instanceof RandomizableContainer) { // CraftBukkit - only process if don't have a transformer access (Was already set above) - SPIGOT-7520: Use structureTransformer as check, so that it is the same as above + definedstructure_blockinfo.nbt.putLong("LootTableSeed", randomsource.nextLong()); + } + +@@ -377,7 +415,7 @@ + } + + if (!definedstructureinfo.isIgnoreEntities()) { +- this.placeEntities(worldaccess, blockposition, definedstructureinfo.getMirror(), definedstructureinfo.getRotation(), definedstructureinfo.getRotationPivot(), structureboundingbox, definedstructureinfo.shouldFinalizeEntities()); ++ this.placeEntities(wrappedAccess, blockposition, definedstructureinfo.getMirror(), definedstructureinfo.getRotation(), definedstructureinfo.getRotationPivot(), structureboundingbox, definedstructureinfo.shouldFinalizeEntities()); // CraftBukkit + } + + return true; +@@ -472,11 +510,13 @@ + } + + private static Optional createEntityIgnoreException(WorldAccess worldaccess, NBTTagCompound nbttagcompound) { +- try { ++ // CraftBukkit start ++ // try { + return EntityTypes.create(nbttagcompound, worldaccess.getLevel()); +- } catch (Exception exception) { +- return Optional.empty(); +- } ++ // } catch (Exception exception) { ++ // return Optional.empty(); ++ // } ++ // CraftBukkit end + } + + public BaseBlockPosition getSize(EnumBlockRotation enumblockrotation) { +@@ -690,6 +730,11 @@ + + nbttagcompound.put("entities", nbttaglist3); + nbttagcompound.put("size", this.newIntegerList(this.size.getX(), this.size.getY(), this.size.getZ())); ++ // CraftBukkit start - PDC ++ if (!this.persistentDataContainer.isEmpty()) { ++ nbttagcompound.put("BukkitValues", this.persistentDataContainer.toTagCompound()); ++ } ++ // CraftBukkit end + return GameProfileSerializer.addCurrentDataVersion(nbttagcompound); + } + +@@ -729,6 +774,12 @@ + } + } + ++ // CraftBukkit start - PDC ++ NBTBase base = nbttagcompound.get("BukkitValues"); ++ if (base instanceof NBTTagCompound) { ++ this.persistentDataContainer.putAll((NBTTagCompound) base); ++ } ++ // CraftBukkit end + } + + private void loadPalette(HolderGetter holdergetter, NBTTagList nbttaglist, NBTTagList nbttaglist1) { +@@ -858,7 +909,7 @@ + public IBlockData stateFor(int i) { + IBlockData iblockdata = (IBlockData) this.ids.byId(i); + +- return iblockdata == null ? DefinedStructure.b.DEFAULT_BLOCK_STATE : iblockdata; ++ return iblockdata == null ? DEFAULT_BLOCK_STATE : iblockdata; // CraftBukkit - decompile error + } + + public Iterator iterator() { diff --git a/patch-remap/og/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureInfo.patch b/patch-remap/og/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureInfo.patch new file mode 100644 index 0000000000..24c76defd1 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureInfo.patch @@ -0,0 +1,25 @@ +--- a/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureInfo.java ++++ b/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructureInfo.java +@@ -22,7 +22,7 @@ + private boolean keepLiquids; + @Nullable + private RandomSource random; +- private int palette; ++ public int palette = -1; // CraftBukkit - Set initial value so we know if the palette has been set forcefully + private final List processors; + private boolean knownShape; + private boolean finalizeEntities; +@@ -149,6 +149,13 @@ + + if (i == 0) { + throw new IllegalStateException("No palettes"); ++ // CraftBukkit start ++ } else if (this.palette > 0) { ++ if (this.palette >= i) { ++ throw new IllegalArgumentException("Palette index out of bounds. Got " + this.palette + " where there are only " + i + " palettes available."); ++ } ++ return list.get(this.palette); ++ // CraftBukkit end + } else { + return (DefinedStructure.a) list.get(this.getRandom(blockposition).nextInt(i)); + } diff --git a/patch-remap/og/net/minecraft/world/level/material/FluidTypeFlowing.patch b/patch-remap/og/net/minecraft/world/level/material/FluidTypeFlowing.patch new file mode 100644 index 0000000000..8b3d30a04b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/material/FluidTypeFlowing.patch @@ -0,0 +1,77 @@ +--- a/net/minecraft/world/level/material/FluidTypeFlowing.java ++++ b/net/minecraft/world/level/material/FluidTypeFlowing.java +@@ -32,6 +32,15 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapes; + ++// CraftBukkit start ++import org.bukkit.block.BlockFace; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.block.BlockFromToEvent; ++import org.bukkit.event.block.FluidLevelChangeEvent; ++// CraftBukkit end ++ + public abstract class FluidTypeFlowing extends FluidType { + + public static final BlockStateBoolean FALLING = BlockProperties.FALLING; +@@ -132,6 +141,15 @@ + Fluid fluid1 = this.getNewLiquid(world, blockposition1, iblockdata1); + + if (this.canSpreadTo(world, blockposition, iblockdata, EnumDirection.DOWN, blockposition1, iblockdata1, world.getFluidState(blockposition1), fluid1.getType())) { ++ // CraftBukkit start ++ org.bukkit.block.Block source = CraftBlock.at(world, blockposition); ++ BlockFromToEvent event = new BlockFromToEvent(source, BlockFace.DOWN); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.spreadTo(world, blockposition1, iblockdata1, EnumDirection.DOWN, fluid1); + if (this.sourceNeighborCount(world, blockposition) >= 3) { + this.spreadToSides(world, blockposition, fluid, iblockdata); +@@ -162,6 +180,15 @@ + IBlockData iblockdata1 = world.getBlockState(blockposition1); + + if (this.canSpreadTo(world, blockposition, iblockdata, enumdirection, blockposition1, iblockdata1, world.getFluidState(blockposition1), fluid1.getType())) { ++ // CraftBukkit start ++ org.bukkit.block.Block source = CraftBlock.at(world, blockposition); ++ BlockFromToEvent event = new BlockFromToEvent(source, org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(enumdirection)); ++ world.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end + this.spreadTo(world, blockposition1, iblockdata1, enumdirection, fluid1); + } + } +@@ -438,12 +465,23 @@ + + if (fluid1.isEmpty()) { + fluid = fluid1; +- world.setBlock(blockposition, Blocks.AIR.defaultBlockState(), 3); ++ // CraftBukkit start ++ FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(world, blockposition, Blocks.AIR.defaultBlockState()); ++ if (event.isCancelled()) { ++ return; ++ } ++ world.setBlock(blockposition, ((CraftBlockData) event.getNewData()).getState(), 3); ++ // CraftBukkit end + } else if (!fluid1.equals(fluid)) { + fluid = fluid1; + IBlockData iblockdata = fluid1.createLegacyBlock(); +- +- world.setBlock(blockposition, iblockdata, 2); ++ // CraftBukkit start ++ FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(world, blockposition, iblockdata); ++ if (event.isCancelled()) { ++ return; ++ } ++ world.setBlock(blockposition, ((CraftBlockData) event.getNewData()).getState(), 2); ++ // CraftBukkit end + world.scheduleTick(blockposition, fluid1.getType(), i); + world.updateNeighborsAt(blockposition, iblockdata.getBlock()); + } diff --git a/patch-remap/og/net/minecraft/world/level/material/FluidTypeLava.patch b/patch-remap/og/net/minecraft/world/level/material/FluidTypeLava.patch new file mode 100644 index 0000000000..d696818519 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/material/FluidTypeLava.patch @@ -0,0 +1,44 @@ +--- a/net/minecraft/world/level/material/FluidTypeLava.java ++++ b/net/minecraft/world/level/material/FluidTypeLava.java +@@ -84,6 +84,13 @@ + + if (iblockdata.isAir()) { + if (this.hasFlammableNeighbours(world, blockposition1)) { ++ // CraftBukkit start - Prevent lava putting something on fire ++ if (world.getBlockState(blockposition1).getBlock() != Blocks.FIRE) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition1, blockposition).isCancelled()) { ++ continue; ++ } ++ } ++ // CraftBukkit end + world.setBlockAndUpdate(blockposition1, BlockFireAbstract.getState(world, blockposition1)); + return; + } +@@ -100,6 +107,14 @@ + } + + if (world.isEmptyBlock(blockposition2.above()) && this.isFlammable(world, blockposition2)) { ++ // CraftBukkit start - Prevent lava putting something on fire ++ BlockPosition up = blockposition2.above(); ++ if (world.getBlockState(up).getBlock() != Blocks.FIRE) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, up, blockposition).isCancelled()) { ++ continue; ++ } ++ } ++ // CraftBukkit end + world.setBlockAndUpdate(blockposition2.above(), BlockFireAbstract.getState(world, blockposition2)); + } + } +@@ -195,7 +210,11 @@ + + if (this.is(TagsFluid.LAVA) && fluid1.is(TagsFluid.WATER)) { + if (iblockdata.getBlock() instanceof BlockFluids) { +- generatoraccess.setBlock(blockposition, Blocks.STONE.defaultBlockState(), 3); ++ // CraftBukkit start ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(generatoraccess.getMinecraftWorld(), blockposition, Blocks.STONE.defaultBlockState(), 3)) { ++ return; ++ } ++ // CraftBukkit end + } + + this.fizz(generatoraccess, blockposition); diff --git a/patch-remap/og/net/minecraft/world/level/portal/BlockPortalShape.patch b/patch-remap/og/net/minecraft/world/level/portal/BlockPortalShape.patch new file mode 100644 index 0000000000..a45205cfec --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/portal/BlockPortalShape.patch @@ -0,0 +1,113 @@ +--- a/net/minecraft/world/level/portal/BlockPortalShape.java ++++ b/net/minecraft/world/level/portal/BlockPortalShape.java +@@ -22,6 +22,11 @@ + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapes; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftPortalEvent; ++import org.bukkit.event.world.PortalCreateEvent; ++// CraftBukkit end ++ + public class BlockPortalShape { + + private static final int MIN_WIDTH = 2; +@@ -41,6 +46,7 @@ + private BlockPosition bottomLeft; + private int height; + private final int width; ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blocks; // CraftBukkit - add field + + public static Optional findEmptyPortalShape(GeneratorAccess generatoraccess, BlockPosition blockposition, EnumDirection.EnumAxis enumdirection_enumaxis) { + return findPortalShape(generatoraccess, blockposition, (blockportalshape) -> { +@@ -61,6 +67,7 @@ + } + + public BlockPortalShape(GeneratorAccess generatoraccess, BlockPosition blockposition, EnumDirection.EnumAxis enumdirection_enumaxis) { ++ blocks = new org.bukkit.craftbukkit.util.BlockStateListPopulator(generatoraccess.getMinecraftWorld()); // CraftBukkit + this.level = generatoraccess; + this.axis = enumdirection_enumaxis; + this.rightDir = enumdirection_enumaxis == EnumDirection.EnumAxis.X ? EnumDirection.WEST : EnumDirection.SOUTH; +@@ -105,6 +112,7 @@ + + if (!isEmpty(iblockdata)) { + if (BlockPortalShape.FRAME.test(iblockdata, this.level, blockposition_mutableblockposition)) { ++ blocks.setBlock(blockposition_mutableblockposition, iblockdata, 18); // CraftBukkit - lower left / right + return i; + } + break; +@@ -115,6 +123,7 @@ + if (!BlockPortalShape.FRAME.test(iblockdata1, this.level, blockposition_mutableblockposition)) { + break; + } ++ blocks.setBlock(blockposition_mutableblockposition, iblockdata1, 18); // CraftBukkit - bottom row + } + + return 0; +@@ -134,6 +143,7 @@ + if (!BlockPortalShape.FRAME.test(this.level.getBlockState(blockposition_mutableblockposition1), this.level, blockposition_mutableblockposition1)) { + return false; + } ++ blocks.setBlock(blockposition_mutableblockposition1, this.level.getBlockState(blockposition_mutableblockposition1), 18); // CraftBukkit - upper row + } + + return true; +@@ -163,6 +173,10 @@ + ++this.numPortalBlocks; + } + } ++ // CraftBukkit start - left and right ++ blocks.setBlock(blockposition_mutableblockposition.set(this.bottomLeft).move(EnumDirection.UP, i).move(this.rightDir, -1), this.level.getBlockState(blockposition_mutableblockposition), 18); ++ blocks.setBlock(blockposition_mutableblockposition.set(this.bottomLeft).move(EnumDirection.UP, i).move(this.rightDir, this.width), this.level.getBlockState(blockposition_mutableblockposition), 18); ++ // CraftBukkit end + } + + return 21; +@@ -176,12 +190,28 @@ + return this.bottomLeft != null && this.width >= 2 && this.width <= 21 && this.height >= 3 && this.height <= 21; + } + +- public void createPortalBlocks() { ++ // CraftBukkit start - return boolean ++ public boolean createPortalBlocks() { ++ org.bukkit.World bworld = this.level.getMinecraftWorld().getWorld(); ++ ++ // Copy below for loop + IBlockData iblockdata = (IBlockData) Blocks.NETHER_PORTAL.defaultBlockState().setValue(BlockPortal.AXIS, this.axis); + + BlockPosition.betweenClosed(this.bottomLeft, this.bottomLeft.relative(EnumDirection.UP, this.height - 1).relative(this.rightDir, this.width - 1)).forEach((blockposition) -> { ++ blocks.setBlock(blockposition, iblockdata, 18); ++ }); ++ ++ PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) blocks.getList(), bworld, null, PortalCreateEvent.CreateReason.FIRE); ++ this.level.getMinecraftWorld().getServer().server.getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ BlockPosition.betweenClosed(this.bottomLeft, this.bottomLeft.relative(EnumDirection.UP, this.height - 1).relative(this.rightDir, this.width - 1)).forEach((blockposition) -> { + this.level.setBlock(blockposition, iblockdata, 18); + }); ++ return true; // CraftBukkit + } + + public boolean isComplete() { +@@ -217,7 +247,7 @@ + return new Vec3D(d3, d2, d4); + } + +- public static ShapeDetectorShape createPortalInfo(WorldServer worldserver, BlockUtil.Rectangle blockutil_rectangle, EnumDirection.EnumAxis enumdirection_enumaxis, Vec3D vec3d, Entity entity, Vec3D vec3d1, float f, float f1) { ++ public static ShapeDetectorShape createPortalInfo(WorldServer worldserver, BlockUtil.Rectangle blockutil_rectangle, EnumDirection.EnumAxis enumdirection_enumaxis, Vec3D vec3d, Entity entity, Vec3D vec3d1, float f, float f1, CraftPortalEvent portalEventInfo) { // CraftBukkit + BlockPosition blockposition = blockutil_rectangle.minCorner; + IBlockData iblockdata = worldserver.getBlockState(blockposition); + EnumDirection.EnumAxis enumdirection_enumaxis1 = (EnumDirection.EnumAxis) iblockdata.getOptionalValue(BlockProperties.HORIZONTAL_AXIS).orElse(EnumDirection.EnumAxis.X); +@@ -233,7 +263,7 @@ + Vec3D vec3d3 = new Vec3D((double) blockposition.getX() + (flag ? d2 : d4), (double) blockposition.getY() + d3, (double) blockposition.getZ() + (flag ? d4 : d2)); + Vec3D vec3d4 = findCollisionFreePosition(vec3d3, worldserver, entity, entitysize); + +- return new ShapeDetectorShape(vec3d4, vec3d2, f + (float) i, f1); ++ return new ShapeDetectorShape(vec3d4, vec3d2, f + (float) i, f1, worldserver, portalEventInfo); // CraftBukkit + } + + private static Vec3D findCollisionFreePosition(Vec3D vec3d, WorldServer worldserver, Entity entity, EntitySize entitysize) { diff --git a/patch-remap/og/net/minecraft/world/level/portal/PortalTravelAgent.patch b/patch-remap/og/net/minecraft/world/level/portal/PortalTravelAgent.patch new file mode 100644 index 0000000000..aad3697fda --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/portal/PortalTravelAgent.patch @@ -0,0 +1,96 @@ +--- a/net/minecraft/world/level/portal/PortalTravelAgent.java ++++ b/net/minecraft/world/level/portal/PortalTravelAgent.java +@@ -42,15 +42,21 @@ + } + + public Optional findPortalAround(BlockPosition blockposition, boolean flag, WorldBorder worldborder) { ++ // CraftBukkit start ++ return findPortalAround(blockposition, worldborder, flag ? 16 : 128); // Search Radius ++ } ++ ++ public Optional findPortalAround(BlockPosition blockposition, WorldBorder worldborder, int i) { + VillagePlace villageplace = this.level.getPoiManager(); +- int i = flag ? 16 : 128; ++ // int i = flag ? 16 : 128; ++ // CraftBukkit end + + villageplace.ensureLoadedAndValid(this.level, blockposition, i); + Optional optional = villageplace.getInSquare((holder) -> { + return holder.is(PoiTypes.NETHER_PORTAL); + }, blockposition, i, VillagePlace.Occupancy.ANY).filter((villageplacerecord) -> { + return worldborder.isWithinBounds(villageplacerecord.getPos()); +- }).sorted(Comparator.comparingDouble((villageplacerecord) -> { ++ }).sorted(Comparator.comparingDouble((VillagePlaceRecord villageplacerecord) -> { // CraftBukkit - decompile error + return villageplacerecord.getPos().distSqr(blockposition); + }).thenComparingInt((villageplacerecord) -> { + return villageplacerecord.getPos().getY(); +@@ -71,6 +77,12 @@ + } + + public Optional createPortal(BlockPosition blockposition, EnumDirection.EnumAxis enumdirection_enumaxis) { ++ // CraftBukkit start ++ return this.createPortal(blockposition, enumdirection_enumaxis, null, 16); ++ } ++ ++ public Optional createPortal(BlockPosition blockposition, EnumDirection.EnumAxis enumdirection_enumaxis, net.minecraft.world.entity.Entity entity, int createRadius) { ++ // CraftBukkit end + EnumDirection enumdirection = EnumDirection.get(EnumDirection.EnumAxisDirection.POSITIVE, enumdirection_enumaxis); + double d0 = -1.0D; + BlockPosition blockposition1 = null; +@@ -79,7 +91,7 @@ + WorldBorder worldborder = this.level.getWorldBorder(); + int i = Math.min(this.level.getMaxBuildHeight(), this.level.getMinBuildHeight() + this.level.getLogicalHeight()) - 1; + BlockPosition.MutableBlockPosition blockposition_mutableblockposition = blockposition.mutable(); +- Iterator iterator = BlockPosition.spiralAround(blockposition, 16, EnumDirection.EAST, EnumDirection.SOUTH).iterator(); ++ Iterator iterator = BlockPosition.spiralAround(blockposition, createRadius, EnumDirection.EAST, EnumDirection.SOUTH).iterator(); // CraftBukkit + + int j; + int k; +@@ -134,6 +146,7 @@ + int j1; + int k1; + ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(this.level); // CraftBukkit - Use BlockStateListPopulator + if (d0 == -1.0D) { + j1 = Math.max(this.level.getMinBuildHeight() - -1, 70); + k1 = i - 9; +@@ -154,7 +167,7 @@ + IBlockData iblockdata = l < 0 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); + + blockposition_mutableblockposition.setWithOffset(blockposition1, k * enumdirection.getStepX() + l1 * enumdirection1.getStepX(), l, k * enumdirection.getStepZ() + l1 * enumdirection1.getStepZ()); +- this.level.setBlockAndUpdate(blockposition_mutableblockposition, iblockdata); ++ blockList.setBlock(blockposition_mutableblockposition, iblockdata, 3); // CraftBukkit + } + } + } +@@ -164,7 +177,7 @@ + for (k1 = -1; k1 < 4; ++k1) { + if (j1 == -1 || j1 == 2 || k1 == -1 || k1 == 3) { + blockposition_mutableblockposition.setWithOffset(blockposition1, j1 * enumdirection.getStepX(), k1, j1 * enumdirection.getStepZ()); +- this.level.setBlock(blockposition_mutableblockposition, Blocks.OBSIDIAN.defaultBlockState(), 3); ++ blockList.setBlock(blockposition_mutableblockposition, Blocks.OBSIDIAN.defaultBlockState(), 3); // CraftBukkit + } + } + } +@@ -174,10 +187,20 @@ + for (k1 = 0; k1 < 2; ++k1) { + for (j = 0; j < 3; ++j) { + blockposition_mutableblockposition.setWithOffset(blockposition1, k1 * enumdirection.getStepX(), j, k1 * enumdirection.getStepZ()); +- this.level.setBlock(blockposition_mutableblockposition, iblockdata1, 18); ++ blockList.setBlock(blockposition_mutableblockposition, iblockdata1, 18); // CraftBukkit + } + } + ++ // CraftBukkit start ++ org.bukkit.World bworld = this.level.getWorld(); ++ org.bukkit.event.world.PortalCreateEvent event = new org.bukkit.event.world.PortalCreateEvent((java.util.List) (java.util.List) blockList.getList(), bworld, (entity == null) ? null : entity.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.NETHER_PAIR); ++ ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return Optional.empty(); ++ } ++ blockList.updateList(); ++ // CraftBukkit end + return Optional.of(new BlockUtil.Rectangle(blockposition1.immutable(), 2, 3)); + } + diff --git a/patch-remap/og/net/minecraft/world/level/portal/ShapeDetectorShape.patch b/patch-remap/og/net/minecraft/world/level/portal/ShapeDetectorShape.patch new file mode 100644 index 0000000000..55ca342786 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/portal/ShapeDetectorShape.patch @@ -0,0 +1,29 @@ +--- a/net/minecraft/world/level/portal/ShapeDetectorShape.java ++++ b/net/minecraft/world/level/portal/ShapeDetectorShape.java +@@ -2,14 +2,25 @@ + + import net.minecraft.world.phys.Vec3D; + ++// CraftBukkit start ++import net.minecraft.server.level.WorldServer; ++import org.bukkit.craftbukkit.event.CraftPortalEvent; ++// CraftBukkit end ++ + public class ShapeDetectorShape { + + public final Vec3D pos; + public final Vec3D speed; + public final float yRot; + public final float xRot; ++ // CraftBukkit start ++ public final WorldServer world; ++ public final CraftPortalEvent portalEventInfo; + +- public ShapeDetectorShape(Vec3D vec3d, Vec3D vec3d1, float f, float f1) { ++ public ShapeDetectorShape(Vec3D vec3d, Vec3D vec3d1, float f, float f1, WorldServer world, CraftPortalEvent portalEventInfo) { ++ this.world = world; ++ this.portalEventInfo = portalEventInfo; ++ // CraftBukkit end + this.pos = vec3d; + this.speed = vec3d1; + this.yRot = f; diff --git a/patch-remap/og/net/minecraft/world/level/redstone/NeighborUpdater.patch b/patch-remap/og/net/minecraft/world/level/redstone/NeighborUpdater.patch new file mode 100644 index 0000000000..54951e9f75 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/redstone/NeighborUpdater.patch @@ -0,0 +1,34 @@ +--- a/net/minecraft/world/level/redstone/NeighborUpdater.java ++++ b/net/minecraft/world/level/redstone/NeighborUpdater.java +@@ -12,6 +12,13 @@ + import net.minecraft.world.level.World; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.state.IBlockData; ++// CraftBukkit start ++import net.minecraft.server.level.WorldServer; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.block.CraftBlock; ++import org.bukkit.craftbukkit.block.data.CraftBlockData; ++import org.bukkit.event.block.BlockPhysicsEvent; ++// CraftBukkit end + + public interface NeighborUpdater { + +@@ -46,6 +53,17 @@ + + static void executeUpdate(World world, IBlockData iblockdata, BlockPosition blockposition, Block block, BlockPosition blockposition1, boolean flag) { + try { ++ // CraftBukkit start ++ CraftWorld cworld = ((WorldServer) world).getWorld(); ++ if (cworld != null) { ++ BlockPhysicsEvent event = new BlockPhysicsEvent(CraftBlock.at(world, blockposition), CraftBlockData.fromData(iblockdata), CraftBlock.at(world, blockposition1)); ++ ((WorldServer) world).getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + iblockdata.neighborChanged(world, blockposition, block, blockposition1, flag); + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception while updating neighbours"); diff --git a/patch-remap/og/net/minecraft/world/level/saveddata/maps/WorldMap.patch b/patch-remap/og/net/minecraft/world/level/saveddata/maps/WorldMap.patch new file mode 100644 index 0000000000..92a6fd4445 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/saveddata/maps/WorldMap.patch @@ -0,0 +1,163 @@ +--- a/net/minecraft/world/level/saveddata/maps/WorldMap.java ++++ b/net/minecraft/world/level/saveddata/maps/WorldMap.java +@@ -32,6 +32,16 @@ + import net.minecraft.world.level.saveddata.PersistentBase; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.UUID; ++import net.minecraft.nbt.NBTBase; ++import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.craftbukkit.CraftWorld; ++import org.bukkit.craftbukkit.map.CraftMapView; ++import org.bukkit.craftbukkit.util.CraftChatMessage; ++// CraftBukkit end ++ + public class WorldMap extends PersistentBase { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -54,6 +64,13 @@ + private final Map frameMarkers = Maps.newHashMap(); + private int trackedDecorationCount; + ++ // CraftBukkit start ++ public final CraftMapView mapView; ++ private CraftServer server; ++ public UUID uniqueId = null; ++ public String id; ++ // CraftBukkit end ++ + public static PersistentBase.a factory() { + return new PersistentBase.a<>(() -> { + throw new IllegalStateException("Should never create an empty map saved data"); +@@ -69,6 +86,10 @@ + this.unlimitedTracking = flag1; + this.locked = flag2; + this.setDirty(); ++ // CraftBukkit start ++ mapView = new CraftMapView(this); ++ server = (CraftServer) org.bukkit.Bukkit.getServer(); ++ // CraftBukkit end + } + + public static WorldMap createFresh(double d0, double d1, byte b0, boolean flag, boolean flag1, ResourceKey resourcekey) { +@@ -86,12 +107,30 @@ + } + + public static WorldMap load(NBTTagCompound nbttagcompound) { +- DataResult dataresult = DimensionManager.parseLegacy(new Dynamic(DynamicOpsNBT.INSTANCE, nbttagcompound.get("dimension"))); ++ DataResult> dataresult = DimensionManager.parseLegacy(new Dynamic(DynamicOpsNBT.INSTANCE, nbttagcompound.get("dimension"))); // CraftBukkit - decompile error + Logger logger = WorldMap.LOGGER; + + Objects.requireNonNull(logger); +- ResourceKey resourcekey = (ResourceKey) dataresult.resultOrPartial(logger::error).orElseThrow(() -> { +- return new IllegalArgumentException("Invalid map dimension: " + nbttagcompound.get("dimension")); ++ // CraftBukkit start ++ ResourceKey resourcekey = dataresult.resultOrPartial(logger::error).orElseGet(() -> { ++ long least = nbttagcompound.getLong("UUIDLeast"); ++ long most = nbttagcompound.getLong("UUIDMost"); ++ ++ if (least != 0L && most != 0L) { ++ UUID uniqueId = new UUID(most, least); ++ ++ CraftWorld world = (CraftWorld) Bukkit.getWorld(uniqueId); ++ // Check if the stored world details are correct. ++ if (world == null) { ++ /* All Maps which do not have their valid world loaded are set to a dimension which hopefully won't be reached. ++ This is to prevent them being corrupted with the wrong map data. */ ++ // PAIL: Use Vanilla exception handling for now ++ } else { ++ return world.getHandle().dimension(); ++ } ++ } ++ throw new IllegalArgumentException("Invalid map dimension: " + nbttagcompound.get("dimension")); ++ // CraftBukkit end + }); + int i = nbttagcompound.getInt("xCenter"); + int j = nbttagcompound.getInt("zCenter"); +@@ -129,13 +168,32 @@ + + @Override + public NBTTagCompound save(NBTTagCompound nbttagcompound) { +- DataResult dataresult = MinecraftKey.CODEC.encodeStart(DynamicOpsNBT.INSTANCE, this.dimension.location()); ++ DataResult dataresult = MinecraftKey.CODEC.encodeStart(DynamicOpsNBT.INSTANCE, this.dimension.location()); // CraftBukkit - decompile error + Logger logger = WorldMap.LOGGER; + + Objects.requireNonNull(logger); + dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { + nbttagcompound.put("dimension", nbtbase); + }); ++ // CraftBukkit start ++ if (true) { ++ if (this.uniqueId == null) { ++ for (org.bukkit.World world : server.getWorlds()) { ++ CraftWorld cWorld = (CraftWorld) world; ++ if (cWorld.getHandle().dimension() == this.dimension) { ++ this.uniqueId = cWorld.getUID(); ++ break; ++ } ++ } ++ } ++ /* Perform a second check to see if a matching world was found, this is a necessary ++ change incase Maps are forcefully unlinked from a World and lack a UID.*/ ++ if (this.uniqueId != null) { ++ nbttagcompound.putLong("UUIDLeast", this.uniqueId.getLeastSignificantBits()); ++ nbttagcompound.putLong("UUIDMost", this.uniqueId.getMostSignificantBits()); ++ } ++ } ++ // CraftBukkit end + nbttagcompound.putInt("xCenter", this.centerX); + nbttagcompound.putInt("zCenter", this.centerZ); + nbttagcompound.putByte("scale", this.scale); +@@ -510,7 +568,7 @@ + this.player = entityhuman; + } + +- private WorldMap.b createPatch() { ++ private WorldMap.b createPatch(byte[] buffer) { // CraftBukkit + int i = this.minDirtyX; + int j = this.minDirtyY; + int k = this.maxDirtyX + 1 - this.minDirtyX; +@@ -519,7 +577,7 @@ + + for (int i1 = 0; i1 < k; ++i1) { + for (int j1 = 0; j1 < l; ++j1) { +- abyte[i1 + j1 * k] = WorldMap.this.colors[i + i1 + (j + j1) * 128]; ++ abyte[i1 + j1 * k] = buffer[i + i1 + (j + j1) * 128]; // CraftBukkit + } + } + +@@ -529,19 +587,29 @@ + @Nullable + Packet nextUpdatePacket(int i) { + WorldMap.b worldmap_b; ++ org.bukkit.craftbukkit.map.RenderData render = WorldMap.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()); // CraftBukkit + + if (this.dirtyData) { + this.dirtyData = false; +- worldmap_b = this.createPatch(); ++ worldmap_b = this.createPatch(render.buffer); // CraftBukkit + } else { + worldmap_b = null; + } + + Collection collection; + +- if (this.dirtyDecorations && this.tick++ % 5 == 0) { ++ if ((true || this.dirtyDecorations) && this.tick++ % 5 == 0) { // CraftBukkit - custom maps don't update this yet + this.dirtyDecorations = false; +- collection = WorldMap.this.decorations.values(); ++ // CraftBukkit start ++ java.util.Collection icons = new java.util.ArrayList(); ++ ++ for (org.bukkit.map.MapCursor cursor : render.cursors) { ++ if (cursor.isVisible()) { ++ icons.add(new MapIcon(MapIcon.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption()))); ++ } ++ } ++ collection = icons; ++ // CraftBukkit end + } else { + collection = null; + } diff --git a/patch-remap/og/net/minecraft/world/level/storage/Convertable.patch b/patch-remap/og/net/minecraft/world/level/storage/Convertable.patch new file mode 100644 index 0000000000..db73231168 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/storage/Convertable.patch @@ -0,0 +1,117 @@ +--- a/net/minecraft/world/level/storage/Convertable.java ++++ b/net/minecraft/world/level/storage/Convertable.java +@@ -81,6 +81,10 @@ + import net.minecraft.world.level.validation.PathAllowList; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.world.level.dimension.WorldDimension; ++// CraftBukkit end ++ + public class Convertable { + + static final Logger LOGGER = LogUtils.getLogger(); +@@ -151,7 +155,7 @@ + } + + public static WorldDataConfiguration readDataConfig(Dynamic dynamic) { +- DataResult dataresult = WorldDataConfiguration.CODEC.parse(dynamic); ++ DataResult dataresult = WorldDataConfiguration.CODEC.parse(dynamic); // CraftBukkit - decompile error + Logger logger = Convertable.LOGGER; + + Objects.requireNonNull(logger); +@@ -174,6 +178,7 @@ + WorldDimensions.b worlddimensions_b = generatorsettings.dimensions().bake(iregistry); + Lifecycle lifecycle = worlddimensions_b.lifecycle().add(iregistrycustom_dimension.allRegistriesLifecycle()); + WorldDataServer worlddataserver = WorldDataServer.parse(dynamic1, worldsettings, worlddimensions_b.specialWorldProperty(), generatorsettings.options(), lifecycle); ++ worlddataserver.pdc = ((Dynamic) dynamic1).getElement("BukkitValues", null); // CraftBukkit - Add PDC to world + + return new LevelDataAndDimensions(worlddataserver, worlddimensions_b); + } +@@ -193,7 +198,7 @@ + throw new LevelStorageException(IChatBaseComponent.translatable("selectWorld.load_folder_access")); + } else { + try { +- Stream stream = Files.list(this.baseDir); ++ Stream stream = Files.list(this.baseDir); // CraftBukkit - decompile error + + Convertable.a convertable_a; + +@@ -423,27 +428,41 @@ + return this.backupDir; + } + +- public Convertable.ConversionSession validateAndCreateAccess(String s) throws IOException, ContentValidationException { ++ public Convertable.ConversionSession validateAndCreateAccess(String s, ResourceKey dimensionType) throws IOException, ContentValidationException { // CraftBukkit + Path path = this.getLevelPath(s); + List list = this.worldDirValidator.validateDirectory(path, true); + + if (!list.isEmpty()) { + throw new ContentValidationException(path, list); + } else { +- return new Convertable.ConversionSession(s, path); ++ return new Convertable.ConversionSession(s, path, dimensionType); // CraftBukkit + } + } + +- public Convertable.ConversionSession createAccess(String s) throws IOException { ++ public Convertable.ConversionSession createAccess(String s, ResourceKey dimensionType) throws IOException { // CraftBukkit + Path path = this.getLevelPath(s); + +- return new Convertable.ConversionSession(s, path); ++ return new Convertable.ConversionSession(s, path, dimensionType); // CraftBukkit + } + + public DirectoryValidator getWorldDirValidator() { + return this.worldDirValidator; + } + ++ // CraftBukkit start ++ public static Path getStorageFolder(Path path, ResourceKey dimensionType) { ++ if (dimensionType == WorldDimension.OVERWORLD) { ++ return path; ++ } else if (dimensionType == WorldDimension.NETHER) { ++ return path.resolve("DIM-1"); ++ } else if (dimensionType == WorldDimension.END) { ++ return path.resolve("DIM1"); ++ } else { ++ return path.resolve("dimensions").resolve(dimensionType.location().getNamespace()).resolve(dimensionType.location().getPath()); ++ } ++ } ++ // CraftBukkit end ++ + public static record a(List levels) implements Iterable { + + public boolean isEmpty() { +@@ -502,8 +521,12 @@ + public final Convertable.b levelDirectory; + private final String levelId; + private final Map resources = Maps.newHashMap(); ++ // CraftBukkit start ++ public final ResourceKey dimensionType; + +- ConversionSession(String s, Path path) throws IOException { ++ ConversionSession(String s, Path path, ResourceKey dimensionType) throws IOException { ++ this.dimensionType = dimensionType; ++ // CraftBukkit end + this.levelId = s; + this.levelDirectory = new Convertable.b(path); + this.lock = SessionLock.create(path); +@@ -531,7 +554,7 @@ + } + + public Path getLevelPath(SavedFile savedfile) { +- Map map = this.resources; ++ Map map = this.resources; // CraftBukkit - decompile error + Convertable.b convertable_b = this.levelDirectory; + + Objects.requireNonNull(this.levelDirectory); +@@ -539,7 +562,7 @@ + } + + public Path getDimensionPath(ResourceKey resourcekey) { +- return DimensionManager.getStorageFolder(resourcekey, this.levelDirectory.path()); ++ return getStorageFolder(this.levelDirectory.path(), this.dimensionType); // CraftBukkit + } + + private void checkLock() { diff --git a/patch-remap/og/net/minecraft/world/level/storage/WorldDataServer.patch b/patch-remap/og/net/minecraft/world/level/storage/WorldDataServer.patch new file mode 100644 index 0000000000..b5a259c25e --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/storage/WorldDataServer.patch @@ -0,0 +1,164 @@ +--- a/net/minecraft/world/level/storage/WorldDataServer.java ++++ b/net/minecraft/world/level/storage/WorldDataServer.java +@@ -43,6 +43,19 @@ + import net.minecraft.world.level.timers.CustomFunctionCallbackTimers; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.core.IRegistry; ++import net.minecraft.core.registries.Registries; ++import net.minecraft.network.protocol.game.PacketPlayOutServerDifficulty; ++import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.server.level.WorldServer; ++import net.minecraft.world.level.dimension.WorldDimension; ++import net.minecraft.world.level.levelgen.WorldDimensions; ++import org.bukkit.Bukkit; ++import org.bukkit.event.weather.ThunderChangeEvent; ++import org.bukkit.event.weather.WeatherChangeEvent; ++// CraftBukkit end ++ + public class WorldDataServer implements IWorldDataServer, SaveData { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -81,6 +94,20 @@ + private boolean wasModded; + private final Set removedFeatureFlags; + private final CustomFunctionCallbackTimerQueue scheduledEvents; ++ // CraftBukkit start - Add world and pdc ++ public IRegistry customDimensions; ++ private WorldServer world; ++ protected NBTBase pdc; ++ ++ public void setWorld(WorldServer world) { ++ if (this.world != null) { ++ return; ++ } ++ this.world = world; ++ world.getWorld().readBukkitValues(pdc); ++ pdc = null; ++ } ++ // CraftBukkit end + + private WorldDataServer(@Nullable NBTTagCompound nbttagcompound, boolean flag, int i, int j, int k, float f, long l, long i1, int j1, int k1, int l1, boolean flag1, int i2, boolean flag2, boolean flag3, boolean flag4, WorldBorder.c worldborder_c, int j2, int k2, @Nullable UUID uuid, Set set, Set set1, CustomFunctionCallbackTimerQueue customfunctioncallbacktimerqueue, @Nullable NBTTagCompound nbttagcompound1, EnderDragonBattle.a enderdragonbattle_a, WorldSettings worldsettings, WorldOptions worldoptions, WorldDataServer.a worlddataserver_a, Lifecycle lifecycle) { + this.wasModded = flag; +@@ -120,7 +147,7 @@ + + public static WorldDataServer parse(Dynamic dynamic, WorldSettings worldsettings, WorldDataServer.a worlddataserver_a, WorldOptions worldoptions, Lifecycle lifecycle) { + long i = dynamic.get("Time").asLong(0L); +- NBTTagCompound nbttagcompound = (NBTTagCompound) NBTTagCompound.CODEC.parse(dynamic.get("Player").orElseEmptyMap()).result().orElse((Object) null); ++ NBTTagCompound nbttagcompound = (NBTTagCompound) NBTTagCompound.CODEC.parse(dynamic.get("Player").orElseEmptyMap()).result().orElse(null); // CraftBukkit - decompile error + boolean flag = dynamic.get("WasModded").asBoolean(false); + int j = dynamic.get("SpawnX").asInt(0); + int k = dynamic.get("SpawnY").asInt(0); +@@ -138,7 +165,7 @@ + WorldBorder.c worldborder_c = WorldBorder.c.read(dynamic, WorldBorder.DEFAULT_SETTINGS); + int j2 = dynamic.get("WanderingTraderSpawnDelay").asInt(0); + int k2 = dynamic.get("WanderingTraderSpawnChance").asInt(0); +- UUID uuid = (UUID) dynamic.get("WanderingTraderId").read(UUIDUtil.CODEC).result().orElse((Object) null); ++ UUID uuid = (UUID) dynamic.get("WanderingTraderId").read(UUIDUtil.CODEC).result().orElse(null); // CraftBukkit - decompile error + Set set = (Set) dynamic.get("ServerBrands").asStream().flatMap((dynamic1) -> { + return dynamic1.asString().result().stream(); + }).collect(Collectors.toCollection(Sets::newLinkedHashSet)); +@@ -147,7 +174,7 @@ + }).collect(Collectors.toSet()); + CustomFunctionCallbackTimerQueue customfunctioncallbacktimerqueue = new CustomFunctionCallbackTimerQueue<>(CustomFunctionCallbackTimers.SERVER_CALLBACKS, dynamic.get("ScheduledEvents").asStream()); + NBTTagCompound nbttagcompound1 = (NBTTagCompound) dynamic.get("CustomBossEvents").orElseEmptyMap().getValue(); +- DataResult dataresult = dynamic.get("DragonFight").read(EnderDragonBattle.a.CODEC); ++ DataResult dataresult = dynamic.get("DragonFight").read(EnderDragonBattle.a.CODEC); // CraftBukkit - decompile error + Logger logger = WorldDataServer.LOGGER; + + Objects.requireNonNull(logger); +@@ -182,7 +209,7 @@ + nbttagcompound.put("Version", nbttagcompound2); + GameProfileSerializer.addCurrentDataVersion(nbttagcompound); + DynamicOps dynamicops = RegistryOps.create(DynamicOpsNBT.INSTANCE, (HolderLookup.b) iregistrycustom); +- DataResult dataresult = GeneratorSettings.encode(dynamicops, this.worldOptions, iregistrycustom); ++ DataResult dataresult = GeneratorSettings.encode(dynamicops, this.worldOptions, new WorldDimensions(this.customDimensions != null ? this.customDimensions : iregistrycustom.registryOrThrow(Registries.LEVEL_STEM))); // CraftBukkit + Logger logger = WorldDataServer.LOGGER; + + Objects.requireNonNull(logger); +@@ -234,11 +261,13 @@ + nbttagcompound.putUUID("WanderingTraderId", this.wanderingTraderId); + } + ++ nbttagcompound.putString("Bukkit.Version", Bukkit.getName() + "/" + Bukkit.getVersion() + "/" + Bukkit.getBukkitVersion()); // CraftBukkit ++ world.getWorld().storeBukkitValues(nbttagcompound); // CraftBukkit - add pdc + } + + private static NBTTagList stringCollectionToTag(Set set) { + NBTTagList nbttaglist = new NBTTagList(); +- Stream stream = set.stream().map(NBTTagString::valueOf); ++ Stream stream = set.stream().map(NBTTagString::valueOf); // CraftBukkit - decompile error + + Objects.requireNonNull(nbttaglist); + stream.forEach(nbttaglist::add); +@@ -346,6 +375,20 @@ + + @Override + public void setThundering(boolean flag) { ++ // CraftBukkit start ++ if (this.thundering == flag) { ++ return; ++ } ++ ++ org.bukkit.World world = Bukkit.getWorld(getLevelName()); ++ if (world != null) { ++ ThunderChangeEvent thunder = new ThunderChangeEvent(world, flag); ++ Bukkit.getServer().getPluginManager().callEvent(thunder); ++ if (thunder.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + this.thundering = flag; + } + +@@ -366,6 +409,20 @@ + + @Override + public void setRaining(boolean flag) { ++ // CraftBukkit start ++ if (this.raining == flag) { ++ return; ++ } ++ ++ org.bukkit.World world = Bukkit.getWorld(getLevelName()); ++ if (world != null) { ++ WeatherChangeEvent weather = new WeatherChangeEvent(world, flag); ++ Bukkit.getServer().getPluginManager().callEvent(weather); ++ if (weather.isCancelled()) { ++ return; ++ } ++ } ++ // CraftBukkit end + this.raining = flag; + } + +@@ -432,6 +489,12 @@ + @Override + public void setDifficulty(EnumDifficulty enumdifficulty) { + this.settings = this.settings.withDifficulty(enumdifficulty); ++ // CraftBukkit start ++ PacketPlayOutServerDifficulty packet = new PacketPlayOutServerDifficulty(this.getDifficulty(), this.isDifficultyLocked()); ++ for (EntityPlayer player : (java.util.List) (java.util.List) world.players()) { ++ player.connection.send(packet); ++ } ++ // CraftBukkit end + } + + @Override +@@ -568,6 +631,14 @@ + return this.settings.copy(); + } + ++ // CraftBukkit start - Check if the name stored in NBT is the correct one ++ public void checkName(String name) { ++ if (!this.settings.levelName.equals(name)) { ++ this.settings.levelName = name; ++ } ++ } ++ // CraftBukkit end ++ + /** @deprecated */ + @Deprecated + public static enum a { diff --git a/patch-remap/og/net/minecraft/world/level/storage/WorldNBTStorage.patch b/patch-remap/og/net/minecraft/world/level/storage/WorldNBTStorage.patch new file mode 100644 index 0000000000..246fcf9fad --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/storage/WorldNBTStorage.patch @@ -0,0 +1,67 @@ +--- a/net/minecraft/world/level/storage/WorldNBTStorage.java ++++ b/net/minecraft/world/level/storage/WorldNBTStorage.java +@@ -15,6 +15,13 @@ + import net.minecraft.world.entity.player.EntityHuman; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.io.FileInputStream; ++import java.io.InputStream; ++import net.minecraft.server.level.EntityPlayer; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++// CraftBukkit end ++ + public class WorldNBTStorage { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -59,6 +66,16 @@ + } + + if (nbttagcompound != null) { ++ // CraftBukkit start ++ if (entityhuman instanceof EntityPlayer) { ++ CraftPlayer player = (CraftPlayer) entityhuman.getBukkitEntity(); ++ // Only update first played if it is older than the one we have ++ long modified = new File(this.playerDir, entityhuman.getUUID().toString() + ".dat").lastModified(); ++ if (modified < player.getFirstPlayed()) { ++ player.setFirstPlayed(modified); ++ } ++ } ++ // CraftBukkit end + int i = GameProfileSerializer.getDataVersion(nbttagcompound, -1); + + nbttagcompound = DataFixTypes.PLAYER.updateToCurrentVersion(this.fixerUpper, nbttagcompound, i); +@@ -68,6 +85,22 @@ + return nbttagcompound; + } + ++ // CraftBukkit start ++ public NBTTagCompound getPlayerData(String s) { ++ try { ++ File file1 = new File(this.playerDir, s + ".dat"); ++ ++ if (file1.exists()) { ++ return NBTCompressedStreamTools.readCompressed(file1.toPath(), NBTReadLimiter.unlimitedHeap()); ++ } ++ } catch (Exception exception) { ++ LOGGER.warn("Failed to load player data for " + s); ++ } ++ ++ return null; ++ } ++ // CraftBukkit end ++ + public String[] getSeenPlayers() { + String[] astring = this.playerDir.list(); + +@@ -83,4 +116,10 @@ + + return astring; + } ++ ++ // CraftBukkit start ++ public File getPlayerDir() { ++ return playerDir; ++ } ++ // CraftBukkit end + } diff --git a/patch-remap/og/net/minecraft/world/level/storage/loot/LootDataManager.patch b/patch-remap/og/net/minecraft/world/level/storage/loot/LootDataManager.patch new file mode 100644 index 0000000000..24e8aded70 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/storage/loot/LootDataManager.patch @@ -0,0 +1,48 @@ +--- a/net/minecraft/world/level/storage/loot/LootDataManager.java ++++ b/net/minecraft/world/level/storage/loot/LootDataManager.java +@@ -22,6 +22,8 @@ + import net.minecraft.util.ProblemReporter; + import net.minecraft.util.profiling.GameProfilerFiller; + import net.minecraft.world.level.storage.loot.parameters.LootContextParameterSets; ++import org.bukkit.craftbukkit.CraftLootTable; ++import org.bukkit.craftbukkit.util.CraftNamespacedKey; + import org.slf4j.Logger; + + public class LootDataManager implements IReloadListener, LootDataResolver { +@@ -89,7 +91,7 @@ + @Nullable + @Override + public T getElement(LootDataId lootdataid) { +- return map1.get(lootdataid); ++ return (T) map1.get(lootdataid); // CraftBukkit - decompile error + } + }); + +@@ -99,18 +101,25 @@ + problemreporter_a.get().forEach((s, s1) -> { + LootDataManager.LOGGER.warn("Found loot table element validation problem in {}: {}", s, s1); + }); ++ // CraftBukkit start ++ map1.forEach((key, lootTable) -> { ++ if (object instanceof LootTable table) { ++ table.craftLootTable = new CraftLootTable(CraftNamespacedKey.fromMinecraft(key.location()), table); ++ } ++ }); ++ // CraftBukkit end + this.elements = map1; + this.typeKeys = com_google_common_collect_immutablemultimap_builder.build(); + } + + private static void castAndValidate(LootCollector lootcollector, LootDataId lootdataid, Object object) { +- lootdataid.type().runValidation(lootcollector, lootdataid, object); ++ lootdataid.type().runValidation(lootcollector, lootdataid, (T) object); // CraftBukkit - decompile error + } + + @Nullable + @Override + public T getElement(LootDataId lootdataid) { +- return this.elements.get(lootdataid); ++ return (T) this.elements.get(lootdataid); // CraftBukkit - decompile error + } + + public Collection getKeys(LootDataType lootdatatype) { diff --git a/patch-remap/og/net/minecraft/world/level/storage/loot/LootTable.patch b/patch-remap/og/net/minecraft/world/level/storage/loot/LootTable.patch new file mode 100644 index 0000000000..57ca9b550b --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/storage/loot/LootTable.patch @@ -0,0 +1,47 @@ +--- a/net/minecraft/world/level/storage/loot/LootTable.java ++++ b/net/minecraft/world/level/storage/loot/LootTable.java +@@ -29,6 +29,13 @@ + import net.minecraft.world.level.storage.loot.parameters.LootContextParameterSets; + import org.slf4j.Logger; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.CraftLootTable; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.world.LootGenerateEvent; ++// CraftBukkit end ++ + public class LootTable { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -50,6 +57,7 @@ + private final List pools; + private final List functions; + private final BiFunction compositeFunction; ++ public CraftLootTable craftLootTable; // CraftBukkit + + LootTable(LootContextParameterSet lootcontextparameterset, Optional optional, List list, List list1) { + this.paramSet = lootcontextparameterset; +@@ -149,9 +157,22 @@ + } + + public void fill(IInventory iinventory, LootParams lootparams, long i) { ++ // CraftBukkit start ++ this.fillInventory(iinventory, lootparams, i, false); ++ } ++ ++ public void fillInventory(IInventory iinventory, LootParams lootparams, long i, boolean plugin) { ++ // CraftBukkit end + LootTableInfo loottableinfo = (new LootTableInfo.Builder(lootparams)).withOptionalRandomSeed(i).create(this.randomSequence); + ObjectArrayList objectarraylist = this.getRandomItems(loottableinfo); + RandomSource randomsource = loottableinfo.getRandom(); ++ // CraftBukkit start ++ LootGenerateEvent event = CraftEventFactory.callLootGenerateEvent(iinventory, this, loottableinfo, objectarraylist, plugin); ++ if (event.isCancelled()) { ++ return; ++ } ++ objectarraylist = event.getLoot().stream().map(CraftItemStack::asNMSCopy).collect(ObjectArrayList.toList()); ++ // CraftBukkit end + List list = this.getAvailableSlots(iinventory, randomsource); + + this.shuffleAndSplitItems(objectarraylist, list.size(), randomsource); diff --git a/patch-remap/og/net/minecraft/world/level/storage/loot/functions/LootEnchantFunction.patch b/patch-remap/og/net/minecraft/world/level/storage/loot/functions/LootEnchantFunction.patch new file mode 100644 index 0000000000..29bd58bedf --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/storage/loot/functions/LootEnchantFunction.patch @@ -0,0 +1,17 @@ +--- a/net/minecraft/world/level/storage/loot/functions/LootEnchantFunction.java ++++ b/net/minecraft/world/level/storage/loot/functions/LootEnchantFunction.java +@@ -57,8 +57,13 @@ + + if (entity instanceof EntityLiving) { + int i = EnchantmentManager.getMobLooting((EntityLiving) entity); ++ // CraftBukkit start - use lootingModifier if set by plugin ++ if (loottableinfo.hasParam(LootContextParameters.LOOTING_MOD)) { ++ i = loottableinfo.getParamOrNull(LootContextParameters.LOOTING_MOD); ++ } ++ // CraftBukkit end + +- if (i == 0) { ++ if (i <= 0) { // CraftBukkit - account for possible negative looting values from Bukkit + return itemstack; + } + diff --git a/patch-remap/og/net/minecraft/world/level/storage/loot/parameters/LootContextParameters.patch b/patch-remap/og/net/minecraft/world/level/storage/loot/parameters/LootContextParameters.patch new file mode 100644 index 0000000000..c0e4302af4 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/storage/loot/parameters/LootContextParameters.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/world/level/storage/loot/parameters/LootContextParameters.java ++++ b/net/minecraft/world/level/storage/loot/parameters/LootContextParameters.java +@@ -21,6 +21,7 @@ + public static final LootContextParameter BLOCK_ENTITY = create("block_entity"); + public static final LootContextParameter TOOL = create("tool"); + public static final LootContextParameter EXPLOSION_RADIUS = create("explosion_radius"); ++ public static final LootContextParameter LOOTING_MOD = new LootContextParameter<>(new MinecraftKey("bukkit:looting_mod")); // CraftBukkit + + public LootContextParameters() {} + diff --git a/patch-remap/og/net/minecraft/world/level/storage/loot/predicates/LootItemConditionRandomChanceWithLooting.patch b/patch-remap/og/net/minecraft/world/level/storage/loot/predicates/LootItemConditionRandomChanceWithLooting.patch new file mode 100644 index 0000000000..c14edd2391 --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/storage/loot/predicates/LootItemConditionRandomChanceWithLooting.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/storage/loot/predicates/LootItemConditionRandomChanceWithLooting.java ++++ b/net/minecraft/world/level/storage/loot/predicates/LootItemConditionRandomChanceWithLooting.java +@@ -34,6 +34,11 @@ + if (entity instanceof EntityLiving) { + i = EnchantmentManager.getMobLooting((EntityLiving) entity); + } ++ // CraftBukkit start - only use lootingModifier if set by Bukkit ++ if (loottableinfo.hasParam(LootContextParameters.LOOTING_MOD)) { ++ i = loottableinfo.getParamOrNull(LootContextParameters.LOOTING_MOD); ++ } ++ // CraftBukkit end + + return loottableinfo.getRandom().nextFloat() < this.percent + (float) i * this.lootingMultiplier; + } diff --git a/patch-remap/og/net/minecraft/world/level/storage/loot/predicates/LootItemConditionSurvivesExplosion.patch b/patch-remap/og/net/minecraft/world/level/storage/loot/predicates/LootItemConditionSurvivesExplosion.patch new file mode 100644 index 0000000000..d0a4a03dbb --- /dev/null +++ b/patch-remap/og/net/minecraft/world/level/storage/loot/predicates/LootItemConditionSurvivesExplosion.patch @@ -0,0 +1,12 @@ +--- a/net/minecraft/world/level/storage/loot/predicates/LootItemConditionSurvivesExplosion.java ++++ b/net/minecraft/world/level/storage/loot/predicates/LootItemConditionSurvivesExplosion.java +@@ -32,7 +32,8 @@ + RandomSource randomsource = loottableinfo.getRandom(); + float f = 1.0F / ofloat; + +- return randomsource.nextFloat() <= f; ++ // CraftBukkit - <= to < to allow for plugins to completely disable block drops from explosions ++ return randomsource.nextFloat() < f; + } else { + return true; + }